From 85705939c65dcf47a48d79dfc3f3ecf537a93baf Mon Sep 17 00:00:00 2001 From: Packit Date: Sep 10 2020 11:21:08 +0000 Subject: opa-ff-10.10.1.0.35 base --- diff --git a/CommonInstall/DESIGN b/CommonInstall/DESIGN new file mode 100644 index 0000000..4641059 --- /dev/null +++ b/CommonInstall/DESIGN @@ -0,0 +1,48 @@ +All the util_*pl files are provide utility functions for use. + +The comp*pl files are various examples of comp.pl files for assorted products. + +the main*pl files are the main installer algorithm for assorted packagings, +the one of interest for IntelOPA-IFS is main_omnipathwrap_delta.pl + +The comp_qlgc_fm.pl is a good example. It implements a component consisting of +two user space rpms with init.d scripts. + +The main*pl defines which components are part of the packaging and what their +capabilities are. main_omnipathwrap_delta.pl is a packaging for IntelOPA-IFS +and IntelOPA-Basic. This main is also used for individual component INSTALLs +along with the corresponding override*pl file. + +routines in a comp.pl file: +config_autostart_X - called to configure autostart of component. Only called if HasStart set in main. + +get_rpms_dir_X - returns the directory on the media which contains the given + package within the component + +available_X - is component X available on the install media (use of this allows for optional components in packaging or limited availability if a component isn't available on some OS/CPU combos) + +installed_X - is component X presently installed on the system. This is a quick check, not a "verify". + +installed_version_X - what is the version installed on system. Only called if installed_X is true. versions are short strings displayed and logged, no operations are done (eg. only compare for equality) + +media_version_X - only called if available_X. Indicates version on media. Will be compared with installed_version_X to determine if present installation is up to date. Should return exact same format for version string so comparison of equality is possible. + +build_X - used to build/rebuild component on local system (if supported). We support this for many items in comp_ofed.pl. Other components (like SM) are not available in source and hence do not support this and simply implement a noop. + +need_reinstall_X - does this need to be reinstalled. Mainly used for ofed due to subtle changes such as install prefix or kernel options which may force a reinstall. You'll find this is a noop in most others. + +check_os_prereqs_X - optional function to verify OS prereqs (such as required rpms) are installed already. Typically calls rpm_check_os_prereqs() to do the checks. see comp_fastfabric or comp_ofed for examples. + +preinstall_X - called for all components before they are installed. Use to build things if needed, etc. + +install_X - installs component. also handles reinstall on top of existing installation and upgrade. + +postinstall_X - called after all components are installed. + +uninstall_X - uninstalls component. May be called even if component is partially or not installed at all in which case should do its best to get rid or what might remain of component from a previously aborted uninstall or failed install + +The above routines are called from util_component.pl which has functions to drive +the main menus and call these per component functions. main sets up lists of +what components will be in the menus and calls functions in util_component.pl +to perform the actions selected by the user in the main menu. + diff --git a/CommonInstall/Makefile b/CommonInstall/Makefile new file mode 100644 index 0000000..31fb1a3 --- /dev/null +++ b/CommonInstall/Makefile @@ -0,0 +1,183 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2018, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** +# Makefile for OPENIB_HOST Project + +# Include Make Control Settings +include $(TL_DIR)/$(PROJ_FILE_DIR)/Makesettings.project + +# default target for project level makefile is stage +stage:: +#prepfiles:: prepfiles_global +clobber:: +ALL:: ff_files fm_files + +BSP_SPECIFIC_DIRS= + +#=============================================================================# +# Definitions: +#-----------------------------------------------------------------------------# + +# Name of SubProjects +DS_SUBPROJECTS = +# name of executable or downloadable image +EXECUTABLE = # +# list of sub directories to build + + +DIRS = \ + +# C files (.c) +CFILES = \ + # Add more c files here +# C++ files (.cpp) +CCFILES = \ + # Add more cpp files here +# lex files (.lex) +LFILES = \ + # Add more lex files here +# archive library files (basename, $ARFILES will add MOD_LIB_DIR/prefix and suffix) +LIBFILES = +# Windows Resource Files (.rc) +RSCFILES = +# Windows IDL File (.idl) +IDLFILE = +# Windows Linker Module Definitions (.def) file for dll's +DEFFILE = +# targets to build during INCLUDES phase (add public includes here) +INCLUDE_TARGETS = \ + # Add more h hpp files here +# Non-compiled files +MISC_FILES = +# all source files +SOURCES = $(CFILES) $(CCFILES) $(LFILES) $(RSCFILES) $(IDLFILE) +# Source files to include in DSP File +DSP_SOURCES = $(INCLUDE_TARGETS) $(SOURCES) $(MISC_FILES) \ + $(RSCFILES) $(DEFFILE) $(MAKEFILE) Makerules.project +# all object files +OBJECTS = $(CFILES:.c=$(OBJ_SUFFIX)) $(CCFILES:.cpp=$(OBJ_SUFFIX)) \ + $(LFILES:.lex=$(OBJ_SUFFIX)) +RSCOBJECTS = $(RSCFILES:.rc=$(RES_SUFFIX)) +# targets to build during LIBS phase +LIB_TARGETS_IMPLIB = +LIB_TARGETS_ARLIB = +LIB_TARGETS_EXP = $(LIB_TARGETS_IMPLIB:$(ARLIB_SUFFIX)=$(EXP_SUFFIX)) +LIB_TARGETS_MISC = +# targets to build during CMDS phase +CMD_TARGETS_SHLIB = +CMD_TARGETS_EXE = $(EXECUTABLE) +CMD_TARGETS_MISC = +# files to remove during clean phase +CLEAN_TARGETS_MISC = +CLEAN_TARGETS = $(OBJECTS) $(RSCOBJECTS) $(IDL_TARGETS) $(CLEAN_TARGETS_MISC) +# other files to remove during clobber phase +CLOBBER_TARGETS_MISC= comp_ff_of_prereq_RHEL72.pl comp_ff_of_prereq_RHEL73.pl comp_ff_of_prereq_RHEL74.pl comp_ff_of_prereq_RHEL75.pl comp_ff_of_prereq_RHEL76.pl \ + comp_ff_of_prereq_RHEL77.pl comp_ff_of_prereq_RHEL8.pl comp_ff_of_prereq_RHEL81.pl \ + comp_ff_of_prereq_SLES122.pl comp_ff_of_prereq_SLES123.pl comp_ff_of_prereq_SLES124.pl comp_ff_of_prereq_SLES15.pl comp_ff_of_prereq_SLES151.pl \ + comp_fm_prereq_RHEL72.pl comp_fm_prereq_RHEL73.pl comp_fm_prereq_RHEL74.pl comp_fm_prereq_RHEL75.pl comp_fm_prereq_RHEL76.pl comp_fm_prereq_RHEL77.pl \ + comp_fm_prereq_RHEL8.pl comp_fm_prereq_RHEL81.pl comp_fm_prereq_SLES122.pl comp_fm_prereq_SLES123.pl comp_fm_prereq_SLES124.pl comp_fm_prereq_SLES15.pl \ + comp_fm_prereq_SLES151.pl +# sub-directory to install to within bin +BIN_SUBDIR = +# sub-directory to install to within include +INCLUDE_SUBDIR = + +# Additional Settings +#CLOCALDEBUG = User defined C debugging compilation flags [Empty] +#CCLOCALDEBUG = User defined C++ debugging compilation flags [Empty] +#CLOCAL = User defined C flags for compiling [Empty] +#CCLOCAL = User defined C++ flags for compiling [Empty] +#BSCLOCAL = User flags for Browse File Builder [Empty] +#DEPENDLOCAL = user defined makedepend flags [Empty] +#LINTLOCAL = User defined lint flags [Empty] +#LOCAL_INCLUDE_DIRS = User include directories to search for C/C++ headers [Empty] +#LDLOCAL = User defined C flags for linking [Empty] +#IMPLIBLOCAL = User flags for Object Lirary Manager [Empty] +#MIDLLOCAL = User flags for IDL compiler [Empty] +#RSCLOCAL = User flags for resource compiler [Empty] +#LOCALDEPLIBS = User libraries to include in dependencies [Empty] +#LOCALLIBS = User libraries to use when linking [Empty] +# (in addition to LOCALDEPLIBS) +#LOCAL_LIB_DIRS = User library directories for libpaths [Empty] + +LOCALDEPLIBS = + +FF_FILES = comp_ff_of_prereq_RHEL72.pl comp_ff_of_prereq_RHEL73.pl comp_ff_of_prereq_RHEL74.pl \ + comp_ff_of_prereq_RHEL75.pl comp_ff_of_prereq_RHEL76.pl comp_ff_of_prereq_RHEL77.pl comp_ff_of_prereq_RHEL8.pl comp_ff_of_prereq_RHEL81.pl \ + comp_ff_of_prereq_SLES122.pl comp_ff_of_prereq_SLES123.pl comp_ff_of_prereq_SLES124.pl \ + comp_ff_of_prereq_SLES15.pl comp_ff_of_prereq_SLES151.pl +FM_FILES = comp_fm_prereq_RHEL72.pl comp_fm_prereq_RHEL73.pl comp_fm_prereq_RHEL74.pl \ + comp_fm_prereq_RHEL75.pl comp_fm_prereq_RHEL76.pl comp_fm_prereq_RHEL77.pl comp_fm_prereq_RHEL8.pl comp_fm_prereq_RHEL81.pl \ + comp_fm_prereq_SLES122.pl comp_fm_prereq_SLES123.pl comp_fm_prereq_SLES124.pl \ + comp_fm_prereq_SLES15.pl comp_fm_prereq_SLES151.pl + +# Include Make Rules definitions and rules +include $(TL_DIR)/$(PROJ_FILE_DIR)/Makerules.project + +#=============================================================================# +# Overrides: +#-----------------------------------------------------------------------------# +#CCOPT = # C++ optimization flags, default lets build config decide +#COPT = # C optimization flags, default lets build config decide +#SUBSYSTEM = Subsystem to build for (none, console or windows) [none] +# (Windows Only) +#USEMFC = How Windows MFC should be used (none, static, shared, no_mfc) [none] +# (Windows Only) +#=============================================================================# + +#=============================================================================# +# Rules: +#-----------------------------------------------------------------------------# +# process Sub-directories +include $(TL_DIR)/Makerules/Maketargets.toplevel + +# build cmds and libs +include $(TL_DIR)/Makerules/Maketargets.build + +# install for includes, libs and cmds phases +include $(TL_DIR)/Makerules/Maketargets.install + +# install for stage phase +include $(TL_DIR)/Makerules/Maketargets.stage + +ff_files: $(FF_FILES) + +fm_files: $(FM_FILES) + +clobber_pl_files: + rm -f $(FF_FILES) $(FM_FILES) + +STAGE:: + +CLOBBER:: + +#=============================================================================# + +#=============================================================================# +# DO NOT DELETE THIS LINE -- make depend depends on it. +#=============================================================================# diff --git a/CommonInstall/README b/CommonInstall/README new file mode 100644 index 0000000..2badf04 --- /dev/null +++ b/CommonInstall/README @@ -0,0 +1,3 @@ +Portable Installation and opa_config code +these files are designed to permit cat at build time to join them into one +INSTALL script diff --git a/CommonInstall/comp_delta.pl b/CommonInstall/comp_delta.pl new file mode 100755 index 0000000..5e280e8 --- /dev/null +++ b/CommonInstall/comp_delta.pl @@ -0,0 +1,1886 @@ +#!/usr/bin/perl +# BEGIN_ICS_COPYRIGHT8 +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 + +# This file incorporates work covered by the following copyright and permission notice + +# +# Copyright (c) 2006 Mellanox Technologies. All rights reserved. +# +# This Software is licensed under one of the following licenses: +# +# 1) under the terms of the "Common Public License 1.0" a copy of which is +# available from the Open Source Initiative, see +# http://www.opensource.org/licenses/cpl.php. +# +# 2) under the terms of the "The BSD License" a copy of which is +# available from the Open Source Initiative, see +# http://www.opensource.org/licenses/bsd-license.php. +# +# 3) under the terms of the "GNU General Public License (GPL) Version 2" a +# copy of which is available from the Open Source Initiative, see +# http://www.opensource.org/licenses/gpl-license.php. +# +# Licensee has the right to choose one of the above licenses. +# +# Redistributions of source code must retain the above copyright +# notice and one of the license notices. +# +# Redistributions in binary form must reproduce both the above copyright +# notice, one of the license notices in the documentation +# and/or other materials provided with the distribution. + +use strict; +#use Term::ANSIColor; +#use Term::ANSIColor qw(:constants); +#use File::Basename; +#use Math::BigInt; + +# ========================================================================== +# OFA_Delta installation, includes Intel value-adding packages only + +# all kernel srpms +# these are in the order we must build/process them to meet basic dependencies +my @delta_kernel_srpms_rhel72 = ( 'kmod-ifs-kernel-updates' ); +# the kernel srpm for HFI2 +my @delta_kernel_srpms_rhel74_hfi2 = ( 'hfi2' ); +my @delta_kernel_srpms_sles12_sp2 = ( 'ifs-kernel-updates-kmp-default' ); +my @delta_kernel_srpms_sles12_sp3 = ( 'ifs-kernel-updates-kmp-default' ); +my @delta_kernel_srpms_sles12_sp4 = ( 'ifs-kernel-updates-kmp-default' ); +my @delta_kernel_srpms_sles12_sp5 = ( 'ifs-kernel-updates-kmp-default' ); +my @delta_kernel_srpms_sles15 = ( 'ifs-kernel-updates-kmp-default' ); +my @delta_kernel_srpms_sles15_sp1 = ( 'ifs-kernel-updates-kmp-default' ); +my @delta_kernel_srpms_rhel73 = ( 'kmod-ifs-kernel-updates' ); +my @delta_kernel_srpms_rhel74 = ( 'kmod-ifs-kernel-updates' ); +my @delta_kernel_srpms_rhel75 = ( 'kmod-ifs-kernel-updates' ); +my @delta_kernel_srpms_rhel76 = ( 'kmod-ifs-kernel-updates' ); +my @delta_kernel_srpms_rhel77 = ( 'kmod-ifs-kernel-updates' ); +my @delta_kernel_srpms_rhel8 = ( 'kmod-ifs-kernel-updates' ); +my @delta_kernel_srpms_rhel81 = ( 'kmod-ifs-kernel-updates' ); +my @delta_kernel_srpms = ( ); + +# This provides information for all kernel srpms +# Only srpms listed in @delta_kernel_srpms are considered for install +# As such, this may list some srpms which are N/A to the selected distro +# +# Fields: +# Available => indicate which platforms each srpm can be built for +# Builds => list of kernel and user rpms built from each srpm +# caller must know if user/kernel rpm is expected +# PartOf => Components which the rpms built from this srpm are part of +my %delta_srpm_info = ( + # only used in sles12sp2 + "ifs-kernel-updates-kmp-default" => { Available => "", + Builds => "ifs-kernel-updates-kmp-default ifs-kernel-updates-devel", + PartOf => " opa_stack opa_stack_dev", + }, + # only used in rhel72 and rhel73 + "kmod-ifs-kernel-updates" => { Available => "", + Builds => "kmod-ifs-kernel-updates ifs-kernel-updates-devel", + PartOf => " opa_stack opa_stack_dev", + }, + # only use for HFI2. right now only in rhel74 + "hfi2" => { Available => "", + Builds => "hfi2", + PartOf => " opa_stack", + }, +); + +my %delta_autostart_save = (); +# ========================================================================== +# Delta opa_stack build in prep for installation + +# based on %delta_srpm_info{}{'Available'} determine if the given SRPM is +# buildable and hence available on this CPU for $osver combination +# "user" and kernel rev values for mode are treated same +sub available_srpm($$$) +{ + my $srpm = shift(); + # $mode can be any other value, + # only used to select Available + my $mode = shift(); # "user" or kernel rev + my $osver = shift(); + my $avail ="Available"; + + DebugPrint("checking $srpm $mode $osver against '$delta_srpm_info{$srpm}{$avail}'\n"); + return arch_kernel_is_allowed($osver, $delta_srpm_info{$srpm}{$avail}); +} + +# initialize delta srpm list based on specified osver +# for present system +sub init_delta_info($) +{ + my $osver = shift(); + + # filter components by distro + if ("$CUR_DISTRO_VENDOR" eq 'SuSE' + && "$CUR_VENDOR_VER" eq 'ES122') { + @delta_kernel_srpms = ( @delta_kernel_srpms_sles12_sp2 ); + } elsif ("$CUR_DISTRO_VENDOR" eq 'SuSE' + && "$CUR_VENDOR_VER" eq 'ES123') { + @delta_kernel_srpms = ( @delta_kernel_srpms_sles12_sp3 ); + } elsif ("$CUR_DISTRO_VENDOR" eq 'SuSE' + && "$CUR_VENDOR_VER" eq 'ES124') { + @delta_kernel_srpms = ( @delta_kernel_srpms_sles12_sp4 ); + } elsif ("$CUR_DISTRO_VENDOR" eq 'SuSE' + && "$CUR_VENDOR_VER" eq 'ES125') { + @delta_kernel_srpms = ( @delta_kernel_srpms_sles12_sp5 ); + } elsif ("$CUR_DISTRO_VENDOR" eq 'SuSE' + && "$CUR_VENDOR_VER" eq 'ES15') { + @delta_kernel_srpms = ( @delta_kernel_srpms_sles15 ); + } elsif ("$CUR_DISTRO_VENDOR" eq 'SuSE' + && "$CUR_VENDOR_VER" eq 'ES151') { + @delta_kernel_srpms = ( @delta_kernel_srpms_sles15_sp1 ); + } elsif ( "$CUR_VENDOR_VER" eq "ES74" ) { + if ($HFI2_INSTALL) { + @delta_kernel_srpms = (@delta_kernel_srpms_rhel74_hfi2); + } else { + @delta_kernel_srpms = (@delta_kernel_srpms_rhel74); + } + } elsif ( "$CUR_VENDOR_VER" eq "ES81" ) { + @delta_kernel_srpms = ( @delta_kernel_srpms_rhel81 ); + } elsif ( "$CUR_VENDOR_VER" eq "ES8" ) { + @delta_kernel_srpms = ( @delta_kernel_srpms_rhel8 ); + } elsif ( "$CUR_VENDOR_VER" eq "ES77" ) { + @delta_kernel_srpms = ( @delta_kernel_srpms_rhel77 ); + } elsif ( "$CUR_VENDOR_VER" eq "ES76" ) { + @delta_kernel_srpms = ( @delta_kernel_srpms_rhel76 ); + } elsif ( "$CUR_VENDOR_VER" eq "ES75" ) { + @delta_kernel_srpms = ( @delta_kernel_srpms_rhel75 ); + } elsif ( "$CUR_VENDOR_VER" eq "ES73" ) { + @delta_kernel_srpms = ( @delta_kernel_srpms_rhel73 ); + } elsif ( "$CUR_VENDOR_VER" eq "ES72" ) { + @delta_kernel_srpms = ( @delta_kernel_srpms_rhel72 ); + } else { + # unknown distro, leave empty + @delta_kernel_srpms = ( ); + } + + if (DebugPrintEnabled() ) { + # dump all SRPM info + DebugPrint "\nSRPMs:\n"; + foreach my $srpm ( @delta_kernel_srpms ) { + DebugPrint("$srpm => Builds: '$delta_srpm_info{$srpm}{'Builds'}'\n"); + DebugPrint(" Available: '$delta_srpm_info{$srpm}{'Available'}'\n"); + DebugPrint(" Available: ".available_srpm($srpm, "user", $osver)." PartOf: '$delta_srpm_info{$srpm}{'PartOf'}'\n"); + } + DebugPrint "\n"; + } +} + +sub get_rpms_dir_delta($); + +# verify the rpmfiles exist for all the RPMs listed +sub delta_rpm_exists_list($@) +{ + my $mode = shift(); # "user" or kernel rev or "firmware" + my(@package_list) = @_; # package names + + foreach my $package ( @package_list ) + { + next if ( "$package" eq '' ); + my $rpmdir = get_rpms_dir_delta("$package"); + if (! rpm_exists("$rpmdir/$package", $mode) ) { + return 0; + } + } + return 1; +} + +# resolve filename within $srcdir/$SRPMS_SUBDIR +# and return filename relative to $srcdir +sub delta_srpm_file($$) +{ + my $srcdir = shift(); + my $globname = shift(); # in $srcdir + my $result; + + if ( $GPU_Install == 1 ) { + if ( -d $srcdir."/SRPMS/CUDA" ) { + $result = file_glob("$srcdir/$SRPMS_SUBDIR/CUDA/$globname"); + } else { + NormalPrint("CUDA specific SRPMs do not exist\n"); + exit 0; + } + } else { + $result = file_glob("$srcdir/$SRPMS_SUBDIR/$globname"); + } + + $result =~ s|^$srcdir/||; + return $result; +} + +# indicate where DELTA built RPMs can be found +sub delta_rpms_dir() +{ + my $srcdir=$ComponentInfo{'opa_stack'}{'SrcDir'}; + + if (-d "$srcdir/$RPMS_SUBDIR/$CUR_DISTRO_VENDOR-$CUR_VENDOR_VER" ) { + return "$srcdir/$RPMS_SUBDIR/$CUR_DISTRO_VENDOR-$CUR_VENDOR_VER"; + } else { + return "$srcdir/$RPMS_SUBDIR/$CUR_DISTRO_VENDOR-$CUR_VENDOR_MAJOR_VER"; + } +} + +# package is supplied since for a few packages (such as GPU Direct specific +# packages) we may pick a different directory based on package name +sub get_rpms_dir_delta($) +{ + my $package = shift(); + + my $rpmsdir = delta_rpms_dir(); + + # Note no need to check kernel levels since GPU Direct now supported + # for all distros. If we add a distro without this, such as Ubuntu, + # perhaps argument parser should turn off GPU_Install on that distro. + if ( $GPU_Install == 1 + && ( $package =~ /ifs-kernel-updates/ || $package =~ /libpsm/) ) { + if ( -d $rpmsdir."/CUDA" ) { + $rpmsdir=$rpmsdir."/CUDA"; + } else { + NormalPrint("CUDA specific packages do not exist\n"); + exit 0; + } + } + return $rpmsdir; +} + +# verify if all rpms have been built from the given srpm +sub is_built_srpm($$) +{ + my $srpm = shift(); # srpm name prefix + my $mode = shift(); # "user" or kernel rev + + my @package_list = split /[[:space:]]+/, $delta_srpm_info{$srpm}{'Builds'}; + return ( delta_rpm_exists_list($mode, @package_list) ); +} + +# see if srpm is part of any of the components being installed/reinstalled +sub need_srpm_for_install($$$$) +{ + my $srpm = shift(); # srpm name prefix + my $mode = shift(); # "user" or kernel rev + my $osver = shift(); + # add space at start and end so can search + # list with spaces around searched comp + my $installing_list = " ".shift()." "; # items being installed/reinstalled + + if (! available_srpm($srpm, $mode, $osver)) { + DebugPrint("$srpm $mode $osver not available\n"); + return 0; + } + + my @complist = split /[[:space:]]+/, $delta_srpm_info{$srpm}{'PartOf'}; + foreach my $comp (@complist) { + next if ("$comp" eq ''); + DebugPrint("Check for $comp in ( $installing_list )\n"); + if ($installing_list =~ / $comp /) { + return 1; + } + } + return 0; +} + +sub need_build_srpm($$$$$$) +{ + my $srpm = shift(); # srpm name prefix + my $mode = shift(); # "user" or kernel rev + my $osver = shift(); # kernel rev + my $installing_list = shift(); # what items are being installed/reinstalled + my $force = shift(); # force a rebuild + my $prompt = shift(); # prompt (only used if ! $force) + + return ( need_srpm_for_install($srpm, $mode, $osver, $installing_list) + && ($force + || ! is_built_srpm($srpm, $mode) + || ($prompt && GetYesNo("Rebuild $srpm src RPM for $mode?", "n")))); +} + +# move rpms from build tree (srcdir) to install tree (destdir) +sub delta_move_rpms($$) +{ + my $srcdir = shift(); + my $destdir = shift(); + + system("mkdir -p $destdir"); + if (file_glob("$srcdir/$RPM_ARCH/*") ne "" ) { + system("mv $srcdir/$RPM_ARCH/* $destdir"); + } + if (file_glob("$srcdir/$RPM_KERNEL_ARCH/*") ne "" ) { + system("mv $srcdir/$RPM_KERNEL_ARCH/* $destdir"); + } + if (file_glob("$srcdir/noarch/*") ne "" ) { + system("mv $srcdir/noarch/* $destdir"); + } +} + +# build all OFA components specified in installing_list +# if already built, prompt user for option to build +sub build_delta($$$$$$) +{ + my $install_list = shift(); # total that will be installed when done + my $installing_list = shift(); # what items are being installed/reinstalled + my $K_VER = shift(); # osver + my $debug = shift(); # enable extra debug of build itself + my $build_temp = shift(); # temp area for use by build + my $force = shift(); # force a rebuild + + my $prompt_srpm = 0; # prompt per SRPM + my $force_srpm = $force; # force SRPM rebuild + my $force_kernel_srpm = 0; + my $rpmsdir = delta_rpms_dir(); + + # we only support building kernel code, so if user wants to skip install + # of kernel, we have nothing to do here + # TBD, if its selected to install opa_stack_dev and user_space_only we still + # don't rebuild the kernel srpm, even though it creates the -devel package + # However, that package is not kernel specific, so we should be ok + if($user_space_only) { + return 0; # success + } + + if (! $force && ! $Default_Prompt && ! $force_kernel_srpm) { + my $choice = GetChoice("Rebuild OFA kernel SRPM (a=all, p=prompt per SRPM, n=only as needed?)", "n", ("a", "p", "n")); + if ("$choice" eq "a") { + $force_srpm=1; + } elsif ("$choice" eq "p") { + $prompt_srpm=1; + } elsif ("$choice" eq "n") { + $prompt_srpm=0; + } + } + + # ------------------------------------------------------------------------- + # do all rebuild prompting first so user doesn't have to wait 5 minutes + # between prompts + my %build_kernel_srpms = (); + my $need_build = 0; + my $build_compat_rdma = 0; + + # there will be exactly 1 srpm in delta_kernel_srpms + foreach my $kernel_srpm ( @delta_kernel_srpms ) { + $build_kernel_srpms{"${kernel_srpm}_build_kernel"} = need_build_srpm($kernel_srpm, "$K_VER", "$K_VER", + $installing_list, + $force_srpm || $force_kernel_srpm, + $prompt_srpm); + $need_build |= $build_kernel_srpms{"${kernel_srpm}_build_kernel"}; + } + + if (! $need_build) { + return 0; # success + } + + # ------------------------------------------------------------------------- + # check OS dependencies for all srpms which we will build + my $dep_error = 0; + + NormalPrint "Checking OS Dependencies needed for builds...\n"; + + foreach my $srpm ( @delta_kernel_srpms ) { + next if ( ! $build_kernel_srpms{"${srpm}_build_kernel"} ); + + VerbosePrint("check dependencies for $srpm\n"); + if (check_kbuild_dependencies($K_VER, $srpm )) { + DebugPrint "$srpm kbuild dependency failure\n"; + $dep_error = 1; + } + if (check_rpmbuild_dependencies($srpm)) { + DebugPrint "$srpm rpmbuild dependency failure\n"; + $dep_error = 1; + } + } + + if ($dep_error) { + NormalPrint "ERROR - unable to perform builds due to need for additional OS rpms\n"; + return 1; # failure + } + + # ------------------------------------------------------------------------- + # perform the builds + my $srcdir=$ComponentInfo{'opa_stack'}{'SrcDir'}; + + # use a different directory for BUILD_ROOT to limit conflict with OFED + if ("$build_temp" eq "" ) { + $build_temp = "/var/tmp/IntelOPA-DELTA"; + } + my $BUILD_ROOT="$build_temp/build"; + my $RPM_DIR="$build_temp/DELTARPMS"; + my $resfileop = "replace"; # replace for 1st build, append for rest + + system("rm -rf ${build_temp}"); + + # use a different directory for BUILD_ROOT to limit conflict with OFED + if (0 != system("mkdir -p $BUILD_ROOT $RPM_DIR/BUILD $RPM_DIR/RPMS $RPM_DIR/SOURCES $RPM_DIR/SPECS $RPM_DIR/SRPMS")) { + NormalPrint "ERROR - mkdir -p $BUILD_ROOT $RPM_DIR/BUILD $RPM_DIR/RPMS $RPM_DIR/SOURCES $RPM_DIR/SPECS $RPM_DIR/SRPMS FAILED\n"; + return 1; # failure + } + + foreach my $srpm ( @delta_kernel_srpms ) { + VerbosePrint("process $srpm\n"); + + next if (! $build_kernel_srpms{"${srpm}_build_kernel"}); + + my $SRC_RPM = delta_srpm_file($srcdir, "$srpm*.src.rpm"); + + # Deal with SLES renaming + if ("$srpm" eq "kmod-ifs-kernel-updates" + || "$srpm" eq "ifs-kernel-updates-kmp-default") { + $SRC_RPM = delta_srpm_file($srcdir, "ifs-kernel-updates*.src.rpm"); + } + + my $cmd = "rpmbuild --rebuild --define '_topdir $RPM_DIR'"; + $cmd .= " --define 'dist %{nil}'"; + $cmd .= " --target $RPM_KERNEL_ARCH"; + # IFS - also set build_root so we can cleanup and avoid conflicts + $cmd .= " --buildroot '${BUILD_ROOT}'"; + $cmd .= " --define 'build_root ${BUILD_ROOT}'"; + + $cmd .= " --define 'kver $K_VER'"; + + $cmd .= " $SRC_RPM"; + + if (0 != run_build("$srcdir $SRC_RPM $RPM_KERNEL_ARCH $K_VER", "$srcdir", $cmd, "$resfileop")) { + return 1; # failure + } + $resfileop = "append"; + if ( $GPU_Install == 1 ) { + delta_move_rpms("$RPM_DIR/$RPMS_SUBDIR", "$rpmsdir/CUDA"); + } else { + delta_move_rpms("$RPM_DIR/$RPMS_SUBDIR", "$rpmsdir"); + } + } + + if (! $debug) { + system("rm -rf ${build_temp}"); + } else { + LogPrint "Build remnants left in $BUILD_ROOT and $RPM_DIR\n"; + } + + return 0; # success +} + +# forward declarations +sub installed_delta_opa_stack(); + +# TBD - might not need any more +# return 0 on success, != 0 otherwise +sub uninstall_old_delta_rpms($$$) +{ + my $mode = shift(); # "user" or kernel rev or "firmware" + # "any"- checks if any variation of package is installed + my $verbosity = shift(); + my $message = shift(); + + my $ret = 0; # assume success + my @packages = (); + my @prev_release_rpms = ( "hfi1-psm-compat-devel","hfi1-psm","hfi1-psm-devel","hfi1-psm-debuginfo","libhfi1verbs","libhfi1verbs-devel", "ifs-kernel-updates" ); + + if ("$message" eq "" ) { + $message = "previous OFA Delta"; + } + NormalPrint "\nUninstalling $message RPMs\n"; + + # uninstall all present version OFA rpms, just to be safe + foreach my $i ( "mpiRest", reverse(@Components) ) { + next if (! $ComponentInfo{$i}{'IsOFA'}); + @packages = (@packages, @{ $ComponentInfo{$i}{'DebugRpms'}}); + @packages = (@packages, @{ $ComponentInfo{$i}{'UserRpms'}}); + @packages = (@packages, @{ $ComponentInfo{$i}{'FirmwareRpms'}}); + @packages = (@packages, @{ $ComponentInfo{$i}{'KernelRpms'}}); + } + + # workaround LAM and other MPIs usng mpi-selector + # we uninstall mpi-selector separately and ignore failures for its uninstall + my @filtered_packages = (); + my @rest_packages = (); + foreach my $i ( @packages ) { + if (scalar(grep /^$i$/, (@filtered_packages, @rest_packages)) > 0) { + # skip, already in list + } elsif ( "$i" eq "mpi-selector" ) { + @rest_packages = (@rest_packages, "$i"); + } else { + @filtered_packages = (@filtered_packages, "$i"); + } + } + + # get rpms we are going to remove + my $installed_mpi_rpms = ""; + foreach my $rpm (@{ $ComponentInfo{'mpiRest'}{'UserRpms'}}) { + if (rpm_is_installed($rpm, "user")) { + $installed_mpi_rpms .= " $rpm"; + } + } + + $ret ||= rpm_uninstall_all_list_with_options($mode, " --nodeps ", $verbosity, @filtered_packages); + + if ($ret == 0 && $installed_mpi_rpms ne "") { + NormalPrint "The following MPIs were removed because they are built from a different version of OPA.\n"; + NormalPrint "Please rebuild these MPIs if you still need them.\n $installed_mpi_rpms\n"; + } + +# TBD can simply handle mpi_selector component specially at end as a component + # ignore errors uninstalling mpi-selector + if (scalar(@rest_packages) != 0) { + if (rpm_uninstall_all_list_with_options($mode, " --nodeps ", $verbosity, @rest_packages) && ! $ret) { + NormalPrint "The previous errors can be ignored\n"; + } + } + + if (rpm_uninstall_all_list_with_options($mode, " --nodeps ", $verbosity, @prev_release_rpms) && ! $ret) { + NormalPrint "The previous errors can be ignored\n"; + } + + if ( $ret ) { + NormalPrint "Unable to uninstall $message RPMs\n"; + } + return $ret; +} + + +# TBD - might not need anymore +# remove any old stacks or old versions of the stack +# this is necessary before doing builds to ensure we don't use old dependent +# rpms +sub uninstall_prev_versions() +{ + if (! installed_delta_opa_stack) { + return 0; + } elsif (! comp_is_uptodate('opa_stack')) { # all delta_comp same version + if (0 != uninstall_old_delta_rpms("any", "silent", "previous OFA DELTA")) { + return 1; + } + } + return 0; +} + +sub has_version_delta() +{ + # check both current and old location + # NOTE: When we upgrade/downgrade, the previous installation may have + # different BASE_DIR. Ideally we shall figure out previous installation + # location and then check version_delta there. For now, we are doing it + # in static way by checking all possible locations. + return -e "$BASE_DIR/version_delta" + || -e "$OLD_BASE_DIR/version_delta"; +} + +sub media_version_delta() +{ + # all OFA components at same version as opa_stack + my $srcdir=$ComponentInfo{'opa_stack'}{'SrcDir'}; + return `cat "$srcdir/Version"`; +} + +sub delta_save_autostart() +{ + foreach my $comp ( @Components ) { + next if (! $ComponentInfo{$comp}{'IsOFA'}); + if ($ComponentInfo{$comp}{'HasStart'} + && $ComponentInfo{$comp}{'StartupScript'} ne "") { + $delta_autostart_save{$comp} = comp_IsAutostart2($comp); + } else { + $delta_autostart_save{$comp} = 0; + } + } +} + +sub delta_restore_autostart($) +{ + my $comp = shift(); + + if ( $delta_autostart_save{$comp} ) { + comp_enable_autostart2($comp, 1); + } else { + if ($ComponentInfo{$comp}{'HasStart'} + && $ComponentInfo{$comp}{'StartupScript'} ne "") { + comp_disable_autostart2($comp, 1); + } + } +} + +# makes sure needed OFA components are already built, builts/rebuilds as needed +# called for every delta component's preinstall, noop for all but +# first OFA component in installing_list +sub preinstall_delta($$$) +{ + my $comp = shift(); # calling component + my $install_list = shift(); # total that will be installed when done + my $installing_list = shift(); # what items are being installed/reinstalled + + # ignore non-delta components at start of installing_list + my @installing = split /[[:space:]]+/, $installing_list; + while (scalar(@installing) != 0 + && ("$installing[0]" eq "" + || ! $ComponentInfo{$installing[0]}{'IsOFA'} )) { + shift @installing; + } + # now, only do work if $comp is the 1st delta component in installing_list + if ("$comp" eq "$installing[0]") { + delta_save_autostart(); + init_delta_info($CUR_OS_VER); + +# TBD - do we really need this any more? + # Before we do any builds make sure old stacks removed so we don't + # build against the wrong version of dependent rpms + if (0 != uninstall_prev_versions()) { + return 1; + } + print_separator; + my $version=media_version_delta(); + chomp $version; + printf("Preparing OFA $version $DBG_FREE for Install...\n"); + LogPrint "Preparing OFA $version $DBG_FREE for Install for $CUR_OS_VER\n"; + return build_delta("$install_list", "$installing_list", "$CUR_OS_VER",0,"",$OFED_force_rebuild); + } else { + return 0; + } +} + +# ========================================================================== +# OFA DELTA generic routines + +# OFA has a single start script but controls which ULPs are loaded via +# entries in $OPA_CONFIG (rdma.conf) +# change all StartupParams for given delta component to $newvalue +sub delta_comp_change_opa_conf_param($$) +{ + my $comp=shift(); + my $newvalue=shift(); + + VerbosePrint("edit /$OPA_CONFIG $comp StartUp set to '$newvalue'\n"); + foreach my $p ( @{ $ComponentInfo{$comp}{'StartupParams'} } ) { + change_opa_conf_param($p, $newvalue); + } +} + +# generic functions to handle autostart needs for delta components with +# more complex rdma.conf based startup needs. These assume opa_stack handles +# the actual startup script. Hence these focus on the rdma.conf parameters +# determine if the given capability is configured for Autostart at boot +sub IsAutostart_delta_comp2($) +{ + my $comp = shift(); # component to check + my $WhichStartup = $ComponentInfo{$comp}{'StartupScript'}; + my $ret = $WhichStartup eq "" ? 1 : IsAutostart($WhichStartup); # just to be safe, test this too + + # to be true, all parameters must be yes + foreach my $p ( @{ $ComponentInfo{$comp}{'StartupParams'} } ) { + $ret &= ( read_opa_conf_param($p, "") eq "yes"); + } + return $ret; +} +sub autostart_desc_delta_comp($) +{ + my $comp = shift(); # component to describe + my $WhichStartup = $ComponentInfo{$comp}{'StartupScript'}; + if ( "$WhichStartup" eq "" ) { + return "$ComponentInfo{$comp}{'Name'}" + } else { + return "$ComponentInfo{$comp}{'Name'} ($WhichStartup)"; + } +} +# enable autostart for the given capability +sub enable_autostart_delta_comp2($) +{ + my $comp = shift(); # component to enable + #my $WhichStartup = $ComponentInfo{$comp}{'StartupScript'}; + + #opa_stack handles this: enable_autostart($WhichStartup); + delta_comp_change_opa_conf_param($comp, "yes"); +} +# disable autostart for the given capability +sub disable_autostart_delta_comp2($) +{ + my $comp = shift(); # component to disable + #my $WhichStartup = $ComponentInfo{$comp}{'StartupScript'}; + + delta_comp_change_opa_conf_param($comp, "no"); +} + +# helper to determine if we need to reinstall due to parameter change +sub need_reinstall_delta_comp($$$) +{ + my $comp = shift(); + my $install_list = shift(); # total that will be installed when done + my $installing_list = shift(); # what items are being installed/reinstalled + + if (! comp_is_uptodate('opa_stack')) { # all delta_comp same version + # on upgrade force reinstall to recover from uninstall of old rpms + return "all"; + } else { + return "no"; + } +} + +# OFA has all the drivers in a single RPM. This function installs that RPM +# ========================================================================== +# OFA Delta opa_stack installation + +# determine if the given capability is configured for Autostart at boot +sub IsAutostart2_opa_stack() +{ + # opa_stack is tricky, there are multiple parameters. We just test + # the things we control here, if user has edited rdma.conf they + # could end up with startup still disabled by having disabled all + # the individual HCA drivers + return IsAutostart_delta_comp2("opa_stack"); +} +sub autostart_desc_opa_stack() +{ + return autostart_desc_delta_comp('opa_stack'); +} +# enable autostart for the given capability +sub enable_autostart2_opa_stack() +{ + enable_autostart("opa"); +} +# disable autostart for the given capability +sub disable_autostart2_opa_stack() +{ + disable_autostart("opa"); +} + +sub get_rpms_dir_opa_stack($) +{ + my $package = shift(); + return get_rpms_dir_delta($package) +} + +sub available_opa_stack() +{ + my $srcdir=$ComponentInfo{'opa_stack'}{'SrcDir'}; +# TBD better checks for available? + return ( -d "$srcdir/SRPMS" || -d "$srcdir/RPMS" ); +} + +sub installed_delta_opa_stack() +{ + if ( "$CUR_VENDOR_VER" eq "ES72" ) { + return ( has_version_delta() + && (rpm_is_installed("kmod-ifs-kernel-updates", $CUR_OS_VER) + || rpm_is_installed("ifs-kernel-updates", $CUR_OS_VER))); + } elsif ( "$CUR_VENDOR_VER" eq "ES73" ) { + return ( has_version_delta() + && rpm_is_installed("kmod-ifs-kernel-updates", $CUR_OS_VER)); + } elsif ( "$CUR_VENDOR_VER" eq "ES74" ) { + if ($HFI2_INSTALL) { + return ( has_version_delta() + && rpm_is_installed("hfi2", $CUR_OS_VER)); + } else { + return ( has_version_delta() + && rpm_is_installed("kmod-ifs-kernel-updates", $CUR_OS_VER)); + } + } elsif ( "$CUR_VENDOR_VER" eq "ES81" ) { + return ( has_version_delta() + && rpm_is_installed("kmod-ifs-kernel-updates", $CUR_OS_VER)); + } elsif ( "$CUR_VENDOR_VER" eq "ES8" ) { + return ( has_version_delta() + && rpm_is_installed("kmod-ifs-kernel-updates", $CUR_OS_VER)); + } elsif ( "$CUR_VENDOR_VER" eq "ES77" ) { + return ( has_version_delta() + && rpm_is_installed("kmod-ifs-kernel-updates", $CUR_OS_VER)); + } elsif ( "$CUR_VENDOR_VER" eq "ES76" ) { + return ( has_version_delta() + && rpm_is_installed("kmod-ifs-kernel-updates", $CUR_OS_VER)); + } elsif ( "$CUR_VENDOR_VER" eq "ES75" ) { + return ( has_version_delta() + && rpm_is_installed("kmod-ifs-kernel-updates", $CUR_OS_VER)); + } elsif ( "$CUR_VENDOR_VER" eq 'ES122' ) { + return ( has_version_delta() + && rpm_is_installed("ifs-kernel-updates-kmp-default", $CUR_OS_VER)); + } elsif ( "$CUR_VENDOR_VER" eq 'ES123' ) { + return ( has_version_delta() + && rpm_is_installed("ifs-kernel-updates-kmp-default", $CUR_OS_VER)); + } elsif ( "$CUR_VENDOR_VER" eq 'ES124' ) { + return ( has_version_delta() + && rpm_is_installed("ifs-kernel-updates-kmp-default", $CUR_OS_VER)); + } elsif ( "$CUR_VENDOR_VER" eq 'ES125' ) { + return ( has_version_delta() + && rpm_is_installed("ifs-kernel-updates-kmp-default", $CUR_OS_VER)); + } elsif ( "$CUR_VENDOR_VER" eq 'ES15' ) { + return ( has_version_delta() + && rpm_is_installed("ifs-kernel-updates-kmp-default", $CUR_OS_VER)); + } elsif ( "$CUR_VENDOR_VER" eq 'ES151' ) { + return ( has_version_delta() + && rpm_is_installed("ifs-kernel-updates-kmp-default", $CUR_OS_VER)); + } else { + return 0; + } +} + +sub installed_opa_stack() +{ + return (installed_delta_opa_stack); +} + +# only called if installed_opa_stack is true +sub installed_version_opa_stack() +{ + if ( -e "$BASE_DIR/version_delta" ) { + return `cat $BASE_DIR/version_delta`; + } else { + return 'NONE'; + } +} + +# only called if available_opa_stack is true +sub media_version_opa_stack() +{ + return media_version_delta(); +} + +# return 0 on success, 1 on failure +sub run_uninstall($$$) +{ + my $stack = shift(); + my $cmd = shift(); + my $cmdargs = shift(); + + if ( "$cmd" ne "" && -e "$cmd" ) { + NormalPrint "\nUninstalling $stack: $cmd $cmdargs\n"; + if (0 != system("yes | $cmd $cmdargs")) { + NormalPrint "Unable to uninstall $stack\n"; + return 1; + } + } + return 0; +} + +# return 0 on success, !=0 on failure +sub build_opa_stack($$$$) +{ + my $osver = shift(); + my $debug = shift(); # enable extra debug of build itself + my $build_temp = shift(); # temp area for use by build + my $force = shift(); # force a rebuild + + init_delta_info($osver); + + # We can't remove old ib stack because we need them for build + # OFA_DELTA. More importantly, we don't know where are the rpms. + + # Before we do any builds make sure old stacks removed so we don't + # build against the wrong version of dependent rpms + #if (0 != uninstall_prev_versions()) { + # return 1; + #} + + return build_delta("@Components", "@Components", $osver, $debug,$build_temp,$force); +} + +sub need_reinstall_opa_stack($$) +{ + my $install_list = shift(); # total that will be installed when done + my $installing_list = shift(); # what items are being installed/reinstalled + + return (need_reinstall_delta_comp('opa_stack', $install_list, $installing_list)); +} + +sub check_os_prereqs_opa_stack +{ + return rpm_check_os_prereqs("opa_stack", "any"); +} + +sub preinstall_opa_stack($$) +{ + my $install_list = shift(); # total that will be installed when done + my $installing_list = shift(); # what items are being installed/reinstalled + + return preinstall_delta("opa_stack", $install_list, $installing_list); +} + +my $arptbl_tunning = "ARPTABLE_TUNING"; +my $arptbl_tunning_desc = 'Adjust kernel ARP table size for large fabrics'; +AddAnswerHelp("$arptbl_tunning", "$arptbl_tunning_desc"); + +sub install_opa_stack($$) +{ + my $install_list = shift(); # total that will be installed when done + my $installing_list = shift(); # what items are being installed/reinstalled + + my $srcdir=$ComponentInfo{'opa_stack'}{'SrcDir'}; + + print_comp_install_banner('opa_stack'); + + # do the following before we set any system env vars + if ( $Default_SameAutostart ) { + # set env vars to -1 for SRP and SRPT, so we keep the autostart option + setup_env("OPA_SRP_LOAD", -1); + setup_env("OPA_SRPT_LOAD", -1); + } + + #override the udev permissions. + install_udev_permissions("$srcdir/config"); + + # setup environment variable so that RPM can configure limits conf + setup_env("OPA_LIMITS_CONF", 1); + # so setting up envirnment to install driver for this component. actual install is done by rpm + setup_env("OPA_INSTALL_CALLER", 1); + + # Check $BASE_DIR directory ...exist + check_config_dirs(); + check_dir("/usr/lib/opa"); + + prompt_opa_conf_param("$arptbl_tunning", "$arptbl_tunning_desc", "y", 'OPA_ARPTABLE_TUNING'); + + install_comp_rpms('opa_stack', " -U --nodeps ", $install_list); + # rdma.conf values not directly associated with driver startup are left + # untouched delta rpm install will keep existing value + + # prevent distro's open IB from loading + #add_blacklist("ib_mthca"); + #add_blacklist("ib_ipath"); + disable_distro_ofed(); + + # Take care of the configuration files for srptools + check_rpm_config_file("/etc/srp_daemon.conf"); + check_rpm_config_file("/etc/logrotate.d/srp_daemon"); + check_rpm_config_file("/etc/rsyslog.d/srp_daemon.conf"); + + need_reboot(); + $ComponentWasInstalled{'opa_stack'}=1; +} + +sub postinstall_opa_stack($$) +{ + my $old_conf = 0; # do we have an existing conf file + my $install_list = shift(); # total that will be installed when done + my $installing_list = shift(); # what items are being installed/reinstalled + + if ( -e "/$OPA_CONFIG" ) { + if (0 == system("cp /$OPA_CONFIG /$OPA_CONFIG-save")) { + $old_conf=1; + } + } + + # adjust rdma.conf autostart settings + foreach my $c ( @Components ) + { + next if (! $ComponentInfo{$c}{'IsOFA'}); + if ($install_list !~ / $c /) { + # disable autostart of uninstalled components + # opa_stack is at least installed + delta_comp_change_opa_conf_param($c, "no"); + } else { + # retain previous setting for components being installed + # set to no if initial install + # TBD - should move this to rpm .spec file + # the rpm might do this for us, repeat just to be safe + foreach my $p ( @{ $ComponentInfo{$c}{'StartupParams'} } ) { + my $old_value = ""; + if ( $old_conf ) { + $old_value = read_opa_conf_param($p, "/$OPA_CONFIG-save"); + } + if ( "$old_value" eq "" ) { + $old_value = "no"; + } + change_opa_conf_param($p, $old_value); + } + } + } + + delta_restore_autostart('opa_stack'); +} + +# Do we need to do any of the stuff??? +sub uninstall_opa_stack($$) +{ + my $install_list = shift(); # total that will be left installed when done + my $uninstalling_list = shift(); # what items are being uninstalled + + print_comp_uninstall_banner('opa_stack'); + remove_blacklist("ib_qib"); + + # allow open IB to load + #remove_blacklist("ib_mthca"); + #remove_blacklist("ib_ipath"); + + # the following is the work around for STL-14186. hfi2 rpm doesn't call depmod on uninstall, so we need to do it + # here. After we resolve the issue, we shall remove the following 3 lines + if ($HFI2_INSTALL) { + set_run_depmod(); + } + + # uninstall mpiRest + uninstall_comp_rpms('mpiRest', ' --nodeps ', $install_list, $uninstalling_list, 'verbose'); + + # If we call uninstall intel_hfi before this function, OPA_INSTALL_CALLER will be 1. + # So we reset it back to zero here to ensure we will skip check in opa-scripts + setup_env("OPA_INSTALL_CALLER", 0); + uninstall_comp_rpms('opa_stack', ' --nodeps ', $install_list, $uninstalling_list, 'verbose'); + remove_limits_conf; + + remove_udev_permissions; + + system("rm -rf $BASE_DIR/version_delta"); + system("rm -rf $OLD_BASE_DIR/version_delta"); + system("rm -rf /usr/lib/opa/.comp_delta.pl"); + system "rmdir /usr/lib/opa 2>/dev/null"; # remove only if empty + system "rmdir $BASE_DIR 2>/dev/null"; # remove only if empty + system "rmdir $OPA_CONFIG_DIR 2>/dev/null"; # remove only if empty + + need_reboot(); + $ComponentWasInstalled{'opa_stack'}=0; +} +# ========================================================================== +# intel_hfi installation + +# determine if the given capability is configured for Autostart at boot +sub IsAutostart2_intel_hfi() +{ + return (! is_blacklisted('hfi1')); +} +sub autostart_desc_intel_hfi() +{ + return autostart_desc_delta_comp('intel_hfi'); +} +# enable autostart for the given capability +sub enable_autostart2_intel_hfi() +{ + if (! IsAutostart2_intel_hfi()) { + remove_blacklist('hfi1'); + rebuild_ramdisk(); + } +} +# disable autostart for the given capability +sub disable_autostart2_intel_hfi() +{ + if (IsAutostart2_intel_hfi()) { + add_blacklist('hfi1'); + rebuild_ramdisk(); + } +} + +sub get_rpms_dir_intel_hfi($) +{ + my $package = shift(); + return get_rpms_dir_delta($package) +} + +sub available_intel_hfi() +{ + my $srcdir=$ComponentInfo{'intel_hfi'}{'SrcDir'}; + return (-d "$srcdir/SRPMS" || -d "$srcdir/RPMS" ); +} + +sub installed_intel_hfi() +{ + if (!rpm_is_installed("hfi1-firmware", "firmware")) { + return 0; + } + + if ( "$CUR_VENDOR_VER" eq "ES72" || "$CUR_VENDOR_VER" eq "ES73" ) { + return (rpm_is_installed("libhfi1", "user") + && has_version_delta() + && rpm_is_installed("kmod-ifs-kernel-updates", $CUR_OS_VER)); + } elsif ( "$CUR_VENDOR_VER" eq "ES122" ) { + return (rpm_is_installed("libhfi1verbs-rdmav2", "user") + && has_version_delta() + && rpm_is_installed("ifs-kernel-updates-kmp-default", $CUR_OS_VER)); + } elsif ( "$CUR_VENDOR_VER" eq "ES74" ) { + if ($HFI2_INSTALL) { + return (has_version_delta() + && rpm_is_installed("hfi2", $CUR_OS_VER)); + } else { + return (has_version_delta() + && rpm_is_installed("kmod-ifs-kernel-updates", $CUR_OS_VER)); + } + } elsif ( "$CUR_VENDOR_VER" eq "ES75" ) { + return (has_version_delta() + && rpm_is_installed("kmod-ifs-kernel-updates", $CUR_OS_VER)); + } elsif ( "$CUR_VENDOR_VER" eq "ES76" ) { + return (has_version_delta() + && rpm_is_installed("kmod-ifs-kernel-updates", $CUR_OS_VER)); + } elsif ( "$CUR_VENDOR_VER" eq "ES77" ) { + return (has_version_delta() + && rpm_is_installed("kmod-ifs-kernel-updates", $CUR_OS_VER)); + } elsif ( "$CUR_VENDOR_VER" eq "ES8" ) { + return (has_version_delta() + && rpm_is_installed("kmod-ifs-kernel-updates", $CUR_OS_VER)); + } elsif ( "$CUR_VENDOR_VER" eq "ES81" ) { + return (has_version_delta() + && rpm_is_installed("kmod-ifs-kernel-updates", $CUR_OS_VER)); + } elsif ( "$CUR_VENDOR_VER" eq "ES123" ) { + return (has_version_delta() + && rpm_is_installed("ifs-kernel-updates-kmp-default", $CUR_OS_VER)); + } elsif ( "$CUR_VENDOR_VER" eq "ES124" ) { + return (has_version_delta() + && rpm_is_installed("ifs-kernel-updates-kmp-default", $CUR_OS_VER)); + } elsif ( "$CUR_VENDOR_VER" eq "ES125" ) { + return (has_version_delta() + && rpm_is_installed("ifs-kernel-updates-kmp-default", $CUR_OS_VER)); + } elsif ( "$CUR_VENDOR_VER" eq "ES15" ) { + return (has_version_delta() + && rpm_is_installed("ifs-kernel-updates-kmp-default", $CUR_OS_VER)); + } elsif ( "$CUR_VENDOR_VER" eq "ES151" ) { + return (has_version_delta() + && rpm_is_installed("ifs-kernel-updates-kmp-default", $CUR_OS_VER)); + } else { + return 0; + } +} + +# only called if installed_intel_hfi is true +sub installed_version_intel_hfi() +{ + if ( -e "$BASE_DIR/version_delta" ) { + return `cat $BASE_DIR/version_delta`; + } else { + return ""; + } +} + +# only called if available_intel_hfi is true +sub media_version_intel_hfi() +{ + return media_version_delta(); +} + +sub build_intel_hfi($$$$) +{ + my $osver = shift(); + my $debug = shift(); # enable extra debug of build itself + my $build_temp = shift(); # temp area for use by build + my $force = shift(); # force a rebuild + return 0; # success +} + +sub need_reinstall_intel_hfi($$) +{ + my $install_list = shift(); # total that will be installed when done + my $installing_list = shift(); # what items are being installed/reinstalled + + return (need_reinstall_delta_comp('intel_hfi', $install_list, $installing_list)); +} + +sub preinstall_intel_hfi($$) +{ + my $install_list = shift(); # total that will be installed when done + my $installing_list = shift(); # what items are being installed/reinstalled + + return preinstall_delta("intel_hfi", $install_list, $installing_list); +} + +sub install_intel_hfi($$) +{ + my $install_list = shift(); # total that will be installed when done + my $installing_list = shift(); # what items are being installed/reinstalled + + print_comp_install_banner('intel_hfi'); + setup_env("OPA_INSTALL_CALLER", 1); + + install_comp_rpms('intel_hfi', " -U --nodeps ", $install_list); + + need_reboot(); + $ComponentWasInstalled{'intel_hfi'}=1; +} + +sub postinstall_intel_hfi($$) +{ + my $install_list = shift(); # total that will be installed when done + my $installing_list = shift(); # what items are being installed/reinstalled + delta_restore_autostart('intel_hfi'); + + rebuild_ramdisk(); +} + +sub uninstall_intel_hfi($$) +{ + my $install_list = shift(); # total that will be left installed when done + my $uninstalling_list = shift(); # what items are being uninstalled + + print_comp_uninstall_banner('intel_hfi'); + setup_env("OPA_INSTALL_CALLER", 1); + uninstall_comp_rpms('intel_hfi', ' --nodeps ', $install_list, $uninstalling_list, 'verbose'); + need_reboot(); + $ComponentWasInstalled{'intel_hfi'}=0; + remove_blacklist('hfi1'); + rebuild_ramdisk(); +} + +sub check_os_prereqs_intel_hfi +{ + return rpm_check_os_prereqs("intel_hfi", "any"); +} + +# ========================================================================== +# OFA opa_stack development installation + +sub get_rpms_dir_opa_stack_dev($) +{ + my $package = shift(); + return get_rpms_dir_delta($package) +} + +sub available_opa_stack_dev() +{ + my $srcdir=$ComponentInfo{'opa_stack_dev'}{'SrcDir'}; + return ( -d "$srcdir/SRPMS" || -d "$srcdir/RPMS" ); +} + +sub installed_opa_stack_dev() +{ + return (rpm_is_installed("ifs-kernel-updates-devel", $CUR_OS_VER) && + has_version_delta()); +} + +# only called if installed_opa_stack_dev is true +sub installed_version_opa_stack_dev() +{ + if ( -e "$BASE_DIR/version_delta" ) { + return `cat $BASE_DIR/version_delta`; + } else { + return ""; + } +} + +# only called if available_opa_stack_dev is true +sub media_version_opa_stack_dev() +{ + return media_version_delta(); +} + +sub build_opa_stack_dev($$$$) +{ + my $osver = shift(); + my $debug = shift(); # enable extra debug of build itself + my $build_temp = shift(); # temp area for use by build + my $force = shift(); # force a rebuild + return 0; # success +} + +sub need_reinstall_opa_stack_dev($$) +{ + my $install_list = shift(); # total that will be installed when done + my $installing_list = shift(); # what items are being installed/reinstalled + + return (need_reinstall_delta_comp('opa_stack_dev', $install_list, $installing_list)); +} + +sub preinstall_opa_stack_dev($$) +{ + my $install_list = shift(); # total that will be installed when done + my $installing_list = shift(); # what items are being installed/reinstalled + + return preinstall_delta("opa_stack_dev", $install_list, $installing_list); +} + +sub install_opa_stack_dev($$) +{ + my $install_list = shift(); # total that will be installed when done + my $installing_list = shift(); # what items are being installed/reinstalled + + print_comp_install_banner('opa_stack_dev'); + install_comp_rpms('opa_stack_dev', " -U --nodeps ", $install_list); + + $ComponentWasInstalled{'opa_stack_dev'}=1; +} + +sub postinstall_opa_stack_dev($$) +{ + my $install_list = shift(); # total that will be installed when done + my $installing_list = shift(); # what items are being installed/reinstalled + #delta_restore_autostart('opa_stack_dev'); +} + +sub uninstall_opa_stack_dev($$) +{ + my $install_list = shift(); # total that will be left installed when done + my $uninstalling_list = shift(); # what items are being uninstalled + + print_comp_uninstall_banner('opa_stack_dev'); + uninstall_comp_rpms('opa_stack_dev', ' --nodeps ', $install_list, $uninstalling_list, 'verbose'); + $ComponentWasInstalled{'opa_stack_dev'}=0; +} + +# ========================================================================== +# OFA delta_ipoib installation + +# determine if the given capability is configured for Autostart at boot +sub IsAutostart2_delta_ipoib() +{ + return IsAutostart_delta_comp2('delta_ipoib') || IsAutostart("ipoib"); +} +sub autostart_desc_delta_ipoib() +{ + return autostart_desc_delta_comp('delta_ipoib'); +} +# enable autostart for the given capability +sub enable_autostart2_delta_ipoib() +{ + enable_autostart_delta_comp2('delta_ipoib'); +} +# disable autostart for the given capability +sub disable_autostart2_delta_ipoib() +{ + disable_autostart_delta_comp2('delta_ipoib'); + if (Exist_ifcfg("ib")) { + print "$ComponentInfo{'delta_ipoib'}{'Name'} will autostart if ifcfg files exists\n"; + print "To fully disable autostart, it's recommended to also remove related ifcfg files\n"; + Remove_ifcfg("ib_ipoib","$ComponentInfo{'delta_ipoib'}{'Name'}","ib"); + } +} + +sub get_rpms_dir_delta_ipoib($) +{ + my $package = shift(); + return get_rpms_dir_delta($package) +} + +sub available_delta_ipoib() +{ + my $srcdir=$ComponentInfo{'delta_ipoib'}{'SrcDir'}; + return ( -d "$srcdir/SRPMS" || -d "$srcdir/RPMS" ); +} + +sub installed_delta_ipoib() +{ + return 1; +} + +# only called if installed_delta_ipoib is true +sub installed_version_delta_ipoib() +{ + if ( -e "$BASE_DIR/version_delta" ) { + return `cat $BASE_DIR/version_delta`; + } else { + return 'Unknown'; + } +} + +# only called if available_delta_ipoib is true +sub media_version_delta_ipoib() +{ + return media_version_delta(); +} + +sub build_delta_ipoib($$$$) +{ + my $osver = shift(); + my $debug = shift(); # enable extra debug of build itself + my $build_temp = shift(); # temp area for use by build + my $force = shift(); # force a rebuild + return 0; # success +} + +sub need_reinstall_delta_ipoib($$) +{ + my $install_list = shift(); # total that will be installed when done + my $installing_list = shift(); # what items are being installed/reinstalled + + return (need_reinstall_delta_comp('delta_ipoib', $install_list, $installing_list)); +} + +sub preinstall_delta_ipoib($$) +{ + my $install_list = shift(); # total that will be installed when done + my $installing_list = shift(); # what items are being installed/reinstalled + + return preinstall_delta("delta_ipoib", $install_list, $installing_list); +} + +sub install_delta_ipoib($$) +{ + my $install_list = shift(); # total that will be installed when done + my $installing_list = shift(); # what items are being installed/reinstalled + + print_comp_install_banner('delta_ipoib'); + install_comp_rpms('delta_ipoib', " -U --nodeps ", $install_list); + + # bonding is more involved, require user to edit to enable that + Config_ifcfg(1,"$ComponentInfo{'delta_ipoib'}{'Name'}","ib", "$FirstIPoIBInterface",1); + check_network_config; + #Config_IPoIB_cfg; + need_reboot(); + $ComponentWasInstalled{'delta_ipoib'}=1; +} + +sub postinstall_delta_ipoib($$) +{ + my $install_list = shift(); # total that will be installed when done + my $installing_list = shift(); # what items are being installed/reinstalled + delta_restore_autostart('delta_ipoib'); +} + +sub uninstall_delta_ipoib($$) +{ + my $install_list = shift(); # total that will be left installed when done + my $uninstalling_list = shift(); # what items are being uninstalled + + print_comp_uninstall_banner('delta_ipoib'); + uninstall_comp_rpms('delta_ipoib', ' --nodeps ', $install_list, $uninstalling_list, 'verbose'); + Remove_ifcfg("ib_ipoib","$ComponentInfo{'delta_ipoib'}{'Name'}","ib"); + need_reboot(); + $ComponentWasInstalled{'delta_ipoib'}=0; +} + +# ========================================================================== +# OFA DELTA mpi-selector installation + +sub get_rpms_dir_mpi_selector($) +{ + my $package = shift(); + return get_rpms_dir_delta($package) +} + +sub available_mpi_selector() +{ + my $srcdir=$ComponentInfo{'mpi_selector'}{'SrcDir'}; + return ( -d "$srcdir/SRPMS" || -d "$srcdir/RPMS" ); +} + +sub installed_mpi_selector() +{ + return (rpm_is_installed("mpi-selector", "user") + && has_version_delta()); +} + +# only called if installed_mpi_selector is true +sub installed_version_mpi_selector() +{ + if ( -e "$BASE_DIR/version_delta" ) { + return `cat $BASE_DIR/version_delta`; + } else { + return ""; + } +} + +# only called if available_mpi_selector is true +sub media_version_mpi_selector() +{ + return media_version_delta(); +} + +sub build_mpi_selector($$$$) +{ + my $osver = shift(); + my $debug = shift(); # enable extra debug of build itself + my $build_temp = shift(); # temp area for use by build + my $force = shift(); # force a rebuild + return 0; # success +} + +sub need_reinstall_mpi_selector($$) +{ + my $install_list = shift(); # total that will be installed when done + my $installing_list = shift(); # what items are being installed/reinstalled + + return (need_reinstall_delta_comp('mpi_selector', $install_list, $installing_list)); +} + +sub check_os_prereqs_mpi_selector +{ + return rpm_check_os_prereqs("mpi_selector", "any"); +} + +sub preinstall_mpi_selector($$) +{ + my $install_list = shift(); # total that will be installed when done + my $installing_list = shift(); # what items are being installed/reinstalled + + return preinstall_delta("mpi_selector", $install_list, $installing_list); +} + +sub install_mpi_selector($$) +{ + my $install_list = shift(); # total that will be installed when done + my $installing_list = shift(); # what items are being installed/reinstalled + + print_comp_install_banner('mpi_selector'); + install_comp_rpms('mpi_selector', " -U --nodeps ", $install_list); + + $ComponentWasInstalled{'mpi_selector'}=1; +} + +sub postinstall_mpi_selector($$) +{ + my $install_list = shift(); # total that will be installed when done + my $installing_list = shift(); # what items are being installed/reinstalled + #delta_restore_autostart('mpi_selector'); +} + +sub uninstall_mpi_selector($$) +{ + my $install_list = shift(); # total that will be left installed when done + my $uninstalling_list = shift(); # what items are being uninstalled + + print_comp_uninstall_banner('mpi_selector'); + uninstall_comp_rpms('mpi_selector', '', $install_list, $uninstalling_list, 'verbose'); + $ComponentWasInstalled{'mpi_selector'}=0; +} + +# ========================================================================== +# OFA delta_debug installation + +# this is an odd component. It consists of the debuginfo files which +# are built and identified in DebugRpms in other components. Installing this +# component installs the debuginfo files for the installed components. +# uninstalling this component gets rid of all debuginfo files. +# uninstalling other components will get rid of individual debuginfo files +# for those components + +sub get_rpms_dir_delta_debug($) +{ + my $package = shift(); + return get_rpms_dir_delta($package) +} + +sub available_delta_debug() +{ + my $srcdir=$ComponentInfo{'delta_debug'}{'SrcDir'}; + return (( -d "$srcdir/SRPMS" || -d "$srcdir/RPMS") + && ( "$CUR_DISTRO_VENDOR" ne "SuSE" && rpm_will_build_debuginfo())); +} + +sub installed_delta_debug() +{ + return (rpm_is_installed("libibumad-debuginfo", "user") || rpm_is_installed("libpsm2-debuginfo", "user") + && has_version_delta()); +} + +# only called if installed_delta_debug is true +sub installed_version_delta_debug() +{ + if ( -e "$BASE_DIR/version_delta" ) { + return `cat $BASE_DIR/version_delta`; + } else { + return ""; + } +} + +# only called if available_delta_debug is true +sub media_version_delta_debug() +{ + return media_version_delta(); +} + +sub build_delta_debug($$$$) +{ + my $osver = shift(); + my $debug = shift(); # enable extra debug of build itself + my $build_temp = shift(); # temp area for use by build + my $force = shift(); # force a rebuild + return 0; # success +} + +sub need_reinstall_delta_debug($$) +{ + my $install_list = shift(); # total that will be installed when done + my $installing_list = shift(); # what items are being installed/reinstalled + + my $reins = need_reinstall_delta_comp('delta_debug', $install_list, $installing_list); + if ("$reins" eq "no" ) { + # if delta components with DebugRpms have been added we need to reinstall + # this component. Note uninstall for individual components will + # get rid of associated debuginfo files + foreach my $comp ( @Components ) { + # TBD can remove IsOFA test, the only + # components with DebugRpms are for OFA delta debug + next if (! $ComponentInfo{$comp}{'IsOFA'}); + if ( " $installing_list " =~ / $comp / + && 0 != scalar(@{ $ComponentInfo{$comp}{'DebugRpms'}})) { + return "this"; + } + } + + } + return $reins; +} + +sub preinstall_delta_debug($$) +{ + my $install_list = shift(); # total that will be installed when done + my $installing_list = shift(); # what items are being installed/reinstalled + + return preinstall_delta("delta_debug", $install_list, $installing_list); +} + +sub install_delta_debug($$) +{ + my $install_list = shift(); # total that will be installed when done + my $installing_list = shift(); # what items are being installed/reinstalled + + my @list; + + print_comp_install_banner('delta_debug'); + install_comp_rpms('delta_debug', " -U --nodeps ", $install_list); + + # install DebugRpms for each installed component + foreach my $comp ( @Components ) { + # TBD can remove IsOFA test, the only + # components with DebugRpms are for OFA delta debug + next if (! $ComponentInfo{$comp}{'IsOFA'}); + if ( " $install_list " =~ / $comp / ) { + install_comp_rpm_list("$comp", "user", " -U --nodeps ", + @{ $ComponentInfo{$comp}{'DebugRpms'}}); + } + } + + $ComponentWasInstalled{'delta_debug'}=1; +} + +sub postinstall_delta_debug($$) +{ + my $install_list = shift(); # total that will be installed when done + my $installing_list = shift(); # what items are being installed/reinstalled + #delta_restore_autostart('delta_debug'); +} + +sub uninstall_delta_debug($$) +{ + my $install_list = shift(); # total that will be left installed when done + my $uninstalling_list = shift(); # what items are being uninstalled + + print_comp_uninstall_banner('delta_debug'); + + uninstall_comp_rpms('delta_debug', ' --nodeps ', $install_list, $uninstalling_list, 'verbose'); + # uninstall debug rpms for all components + foreach my $comp ( reverse(@Components) ) { + next if (! $ComponentInfo{$comp}{'IsOFA'}); + rpm_uninstall_list2("any", " --nodeps ", 'verbose', + @{ $ComponentInfo{$comp}{'DebugRpms'}}); + } + $ComponentWasInstalled{'delta_debug'}=0; +} + +# ========================================================================== +# OFA DELTA ibacm installation + +# determine if the given capability is configured for Autostart at boot +sub IsAutostart2_ibacm() +{ + return IsAutostart_delta_comp2('ibacm'); +} +sub autostart_desc_ibacm() +{ + return autostart_desc_delta_comp('ibacm'); +} +# enable autostart for the given capability +sub enable_autostart2_ibacm() +{ + enable_autostart($ComponentInfo{'ibacm'}{'StartupScript'}); +} +# disable autostart for the given capability +sub disable_autostart2_ibacm() +{ + disable_autostart($ComponentInfo{'ibacm'}{'StartupScript'}); +} + +sub get_rpms_dir_ibacm($) +{ + my $package = shift(); + return get_rpms_dir_delta($package) +} + +sub available_ibacm() +{ + my $srcdir=$ComponentInfo{'ibacm'}{'SrcDir'}; + return ( -d "$srcdir/SRPMS" || -d "$srcdir/RPMS" ); +} + +sub installed_ibacm() +{ + return (rpm_is_installed("ibacm", "user") + && has_version_delta()); +} + +# only used on RHEL72, for other distros ibacm is only a SubComponent +# only called if installed_ibacm is true +sub installed_version_ibacm() +{ + if ( -e "$BASE_DIR/version_delta" ) { + return `cat $BASE_DIR/version_delta`; + } else { + return ""; + } +} + +# only called if available_ibacm is true +sub media_version_ibacm() +{ + return media_version_delta(); +} + +sub build_ibacm($$$$) +{ + my $osver = shift(); + my $debug = shift(); # enable extra debug of build itself + my $build_temp = shift(); # temp area for use by build + my $force = shift(); # force a rebuild + return 0; # success +} + +sub need_reinstall_ibacm($$) +{ + my $install_list = shift(); # total that will be installed when done + my $installing_list = shift(); # what items are being installed/reinstalled + + return (need_reinstall_delta_comp('ibacm', $install_list, $installing_list)); +} + +sub preinstall_ibacm($$) +{ + my $install_list = shift(); # total that will be installed when done + my $installing_list = shift(); # what items are being installed/reinstalled + + return preinstall_delta("ibacm", $install_list, $installing_list); +} + +sub install_ibacm($$) +{ + my $install_list = shift(); # total that will be installed when done + my $installing_list = shift(); # what items are being installed/reinstalled + + print_comp_install_banner('ibacm'); + install_comp_rpms('ibacm', " -U --nodeps ", $install_list); + + $ComponentWasInstalled{'ibacm'}=1; +} + +sub postinstall_ibacm($$) +{ + my $install_list = shift(); # total that will be installed when done + my $installing_list = shift(); # what items are being installed/reinstalled + delta_restore_autostart('ibacm'); +} + +sub uninstall_ibacm($$) +{ + my $install_list = shift(); # total that will be left installed when done + my $uninstalling_list = shift(); # what items are being uninstalled + + print_comp_uninstall_banner('ibacm'); + + uninstall_comp_rpms('ibacm', ' --nodeps ', $install_list, $uninstalling_list, 'verbose'); + $ComponentWasInstalled{'ibacm'}=0; +} + +sub check_os_prereqs_ibacm +{ + return rpm_check_os_prereqs("ibacm", "user"); +} + +# ------------------------------------------------------------------ +# # subroutines for rdma-ndd component +# # ----------------------------------------------------------------- +sub installed_rdma_ndd() +{ + return (rpm_is_installed("infiniband-diags", "user")); +} + +sub enable_autostart2_rdma_ndd() +{ + system "systemctl enable rdma-ndd >/dev/null 2>&1"; +} + +sub disable_autostart2_rdma_ndd() +{ + system "systemctl disable rdma-ndd >/dev/null 2>&1"; +} + +sub IsAutostart2_rdma_ndd() +{ + my $status = `systemctl is-enabled rdma-ndd`; + if ( $status eq "disabled\n" || $status eq "" ){ + return 0; + } + else{ + return 1; + } +} + +# ------------------------------------------------------------------ +# # subroutines for delta_srp component +# # ----------------------------------------------------------------- +sub installed_delta_srp() +{ + if ( -f "/etc/rdma/rdma.conf" ) { + return 1; + } + else { + return 0; + } + +} + +sub enable_autostart2_delta_srp() +{ + change_opa_conf_param("SRP_LOAD", "yes"); +} + +sub disable_autostart2_delta_srp() +{ + change_opa_conf_param("SRP_LOAD", "no"); +} + +sub IsAutostart2_delta_srp() +{ + my $status = read_opa_conf_param("SRP_LOAD", ""); + if ( $status eq "yes" ){ + return 1; + } + else{ + return 0; + } +} + +# ------------------------------------------------------------------ +# # subroutines for delta_srpt component +# # ----------------------------------------------------------------- +sub installed_delta_srpt() +{ + if ( -f "/etc/rdma/rdma.conf" ) { + return 1; + } + else { + return 0; + } +} + +sub enable_autostart2_delta_srpt() +{ + change_opa_conf_param("SRPT_LOAD", "yes"); +} + +sub disable_autostart2_delta_srpt() +{ + change_opa_conf_param("SRPT_LOAD", "no"); +} + +sub IsAutostart2_delta_srpt() +{ + my $status = read_opa_conf_param("SRPT_LOAD", ""); + if ( $status eq "yes" ){ + return 1; + } + else{ + return 0; + } +} + diff --git a/CommonInstall/comp_delta_prereq_RHEL72.pl b/CommonInstall/comp_delta_prereq_RHEL72.pl new file mode 100644 index 0000000..5a9012f --- /dev/null +++ b/CommonInstall/comp_delta_prereq_RHEL72.pl @@ -0,0 +1,150 @@ +#!/usr/bin/perl +## BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +## END_ICS_COPYRIGHT8 **************************************** +# +## [ICS VERSION STRING: unknown] +#use strict; +##use Term::ANSIColor; +##use Term::ANSIColor qw(:constants); +##use File::Basename; +##use Math::BigInt; +# +## ========================================================================== +# +#Installation Prequisites array for delta components +my @opa_stack_prereq = ( + "bash", + "kernel", + "kmod", + "rdma", + "systemd", + "glibc", + "libibumad", + "libibumad-devel", + "libibverbs", + "pciutils", + "opensm-libs", + "libibcm", +); +$comp_prereq_hash{'opa_stack_prereq'} = \@opa_stack_prereq; + +my @ibacm_prereq = ( + "bash", + "chkconfig", + "glibc", + "libibumad", + "libibverbs", +); +$comp_prereq_hash{'ibacm_prereq'} = \@ibacm_prereq; + +my @mpi_selector_prereq = ( + "bash", + "coreutils", + "perl", + "perl-Getopt-Long", + "tcsh", +); +$comp_prereq_hash{'mpi_selector_prereq'} = \@mpi_selector_prereq; + +my @intel_hfi_prereq = ( + "bash", + "glibc", + "libgcc", + "libibverbs", + "python", + "systemd", + "numactl-libs", + "irqbalance", +); +$comp_prereq_hash{'intel_hfi_prereq'} = \@intel_hfi_prereq; + +my @mvapich2_prereq = ( + "bash", + "libibverbs", + "librdmacm", + "glibc", + "zlib", + "sysfsutils", +); +$comp_prereq_hash{'mvapich2_prereq'} = \@mvapich2_prereq; + +my @openmpi_prereq = ( + "bash", + "glibc", + "libgcc", + "libgfortran", + "gcc-gfortran", + "libgomp", + "libibverbs", + "libquadmath", + "librdmacm", + "libstdc++", + "libstdc++-devel", + "opensm-libs", + "pkgconfig", + "zlib", +); +$comp_prereq_hash{'openmpi_prereq'} = \@openmpi_prereq; + +my @mvapich2_gcc_hfi_prereq = ( + "bash", + "zlib", + +); +$comp_prereq_hash{'mvapich2_gcc_hfi_prereq'} = \@mvapich2_gcc_hfi_prereq; + +my @mvapich2_intel_hfi_prereq = ( + "bash", +); +$comp_prereq_hash{'mvapich2_intel_hfi_prereq'} = \@mvapich2_intel_hfi_prereq; + +my @openmpi_gcc_hfi_prereq = ( + "bash", + "glibc", + "infinipath-psm", + "libgcc", + "libgfortran", + "gcc-gfortran", + "libgomp", + "libibverbs", + "libquadmath", + "librdmacm", + "libstdc++", + "libstdc++-devel", + "opensm-libs", + "pkgconfig", + "zlib", +); +$comp_prereq_hash{'openmpi_gcc_hfi_prereq'} = \@openmpi_gcc_hfi_prereq; + +my @openmpi_intel_hfi_prereq = ( + "bash", +); +$comp_prereq_hash{'openmpi_intel_hfi_prereq'} = \@openmpi_intel_hfi_prereq; + diff --git a/CommonInstall/comp_delta_prereq_RHEL73.pl b/CommonInstall/comp_delta_prereq_RHEL73.pl new file mode 100644 index 0000000..a2b29cf --- /dev/null +++ b/CommonInstall/comp_delta_prereq_RHEL73.pl @@ -0,0 +1,140 @@ +#!/usr/bin/perl +## BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +## END_ICS_COPYRIGHT8 **************************************** +# +## [ICS VERSION STRING: unknown] +#use strict; +##use Term::ANSIColor; +##use Term::ANSIColor qw(:constants); +##use File::Basename; +##use Math::BigInt; +# +## ========================================================================== +# +#Installation Prequisites array for delta components +my @opa_stack_prereq = ( + "bash", + "kernel", + "kmod", + "rdma", + "systemd", + "glibc", + "pciutils", + "opensm-libs", + "libibmad", + "libibcm", + "libibumad", + "libibumad-devel", +); +$comp_prereq_hash{'opa_stack_prereq'} = \@opa_stack_prereq; + +my @mpi_selector_prereq = ( + "bash", + "coreutils", + "perl", + "perl-Getopt-Long", + "tcsh", +); +$comp_prereq_hash{'mpi_selector_prereq'} = \@mpi_selector_prereq; + +my @intel_hfi_prereq = ( + "bash", + "libhfi1", + "glibc", + "libgcc", + "python", + "systemd", + "numactl-libs", + "irqbalance", +); +$comp_prereq_hash{'intel_hfi_prereq'} = \@intel_hfi_prereq; + +my @mvapich2_prereq = ( + "bash", + "libibverbs", + "librdmacm", + "glibc", + "zlib", + "sysfsutils", +); +$comp_prereq_hash{'mvapich2_prereq'} = \@mvapich2_prereq; + +my @openmpi_prereq = ( + "bash", + "glibc", + "libgcc", + "libgfortran", + "gcc-gfortran", + "libgomp", + "libibverbs", + "libquadmath", + "librdmacm", + "libstdc++", + "libstdc++-devel", + "opensm-libs", + "pkgconfig", + "zlib", +); +$comp_prereq_hash{'openmpi_prereq'} = \@openmpi_prereq; + +my @mvapich2_gcc_hfi_prereq = ( + "bash", + "zlib", + "glibc", +); +$comp_prereq_hash{'mvapich2_gcc_hfi_prereq'} = \@mvapich2_gcc_hfi_prereq; + +my @mvapich2_intel_hfi_prereq = ( + "bash", +); +$comp_prereq_hash{'mvapich2_intel_hfi_prereq'} = \@mvapich2_intel_hfi_prereq; + +my @openmpi_gcc_hfi_prereq = ( + "bash", + "glibc", + "infinipath-psm", + "libgcc", + "libgfortran", + "gcc-gfortran", + "libgomp", + "libibverbs", + "libquadmath", + "librdmacm", + "libstdc++", + "libstdc++-devel", + "opensm-libs", + "pkgconfig", + "zlib", +); +$comp_prereq_hash{'openmpi_gcc_hfi_prereq'} = \@openmpi_gcc_hfi_prereq; + +my @openmpi_intel_hfi_prereq = ( + "bash", +); +$comp_prereq_hash{'openmpi_intel_hfi_prereq'} = \@openmpi_intel_hfi_prereq; diff --git a/CommonInstall/comp_delta_prereq_RHEL74.pl b/CommonInstall/comp_delta_prereq_RHEL74.pl new file mode 100644 index 0000000..a7a3a2a --- /dev/null +++ b/CommonInstall/comp_delta_prereq_RHEL74.pl @@ -0,0 +1,138 @@ +#!/usr/bin/perl +## BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +## END_ICS_COPYRIGHT8 **************************************** +# +## [ICS VERSION STRING: unknown] +#use strict; +##use Term::ANSIColor; +##use Term::ANSIColor qw(:constants); +##use File::Basename; +##use Math::BigInt; +# +## ========================================================================== +# +#Installation Prequisites array for delta components +my @opa_stack_prereq = ( + "bash", + "kernel", + "kmod", + "rdma-core", + "systemd", + "glibc", + "pciutils", + "opensm-libs", + "libibcm", + "libibumad", + "rdma-core-devel", +); +$comp_prereq_hash{'opa_stack_prereq'} = \@opa_stack_prereq; + +my @mpi_selector_prereq = ( + "bash", + "coreutils", + "perl", + "perl-Getopt-Long", + "tcsh", +); +$comp_prereq_hash{'mpi_selector_prereq'} = \@mpi_selector_prereq; + +my @intel_hfi_prereq = ( + "bash", + "glibc", + "libgcc", + "python", + "systemd", + "numactl-libs", + "irqbalance", +); +$comp_prereq_hash{'intel_hfi_prereq'} = \@intel_hfi_prereq; + +my @mvapich2_prereq = ( + "bash", + "libibverbs", + "librdmacm", + "glibc", + "zlib", + "sysfsutils", +); +$comp_prereq_hash{'mvapich2_prereq'} = \@mvapich2_prereq; + +my @openmpi_prereq = ( + "bash", + "glibc", + "libgcc", + "libgfortran", + "gcc-gfortran", + "libgomp", + "libibverbs", + "libquadmath", + "librdmacm", + "libstdc++", + "libstdc++-devel", + "opensm-libs", + "pkgconfig", + "zlib", +); +$comp_prereq_hash{'openmpi_prereq'} = \@openmpi_prereq; + +my @mvapich2_gcc_hfi_prereq = ( + "bash", + "zlib", + "glibc", +); +$comp_prereq_hash{'mvapich2_gcc_hfi_prereq'} = \@mvapich2_gcc_hfi_prereq; + +my @mvapich2_intel_hfi_prereq = ( + "bash", +); +$comp_prereq_hash{'mvapich2_intel_hfi_prereq'} = \@mvapich2_intel_hfi_prereq; + +my @openmpi_gcc_hfi_prereq = ( + "bash", + "glibc", + "infinipath-psm", + "libgcc", + "libgfortran", + "gcc-gfortran", + "libgomp", + "libibverbs", + "libquadmath", + "librdmacm", + "libstdc++", + "libstdc++-devel", + "opensm-libs", + "pkgconfig", + "zlib", +); +$comp_prereq_hash{'openmpi_gcc_hfi_prereq'} = \@openmpi_gcc_hfi_prereq; + +my @openmpi_intel_hfi_prereq = ( + "bash", +); +$comp_prereq_hash{'openmpi_intel_hfi_prereq'} = \@openmpi_intel_hfi_prereq; diff --git a/CommonInstall/comp_delta_prereq_RHEL75.pl b/CommonInstall/comp_delta_prereq_RHEL75.pl new file mode 100644 index 0000000..9bc57e0 --- /dev/null +++ b/CommonInstall/comp_delta_prereq_RHEL75.pl @@ -0,0 +1,139 @@ +#!/usr/bin/perl +## BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +## END_ICS_COPYRIGHT8 **************************************** +# +## [ICS VERSION STRING: unknown] +#use strict; +##use Term::ANSIColor; +##use Term::ANSIColor qw(:constants); +##use File::Basename; +##use Math::BigInt; +# +## ========================================================================== +# +#Installation Prequisites array for delta components +my @opa_stack_prereq = ( + "bash", + "kernel", + "kmod", + "rdma-core", + "systemd", + "glibc", + "pciutils", + "opensm-libs", + "libibcm", + "libibumad", + "rdma-core-devel", +); +$comp_prereq_hash{'opa_stack_prereq'} = \@opa_stack_prereq; + +my @mpi_selector_prereq = ( + "bash", + "coreutils", + "perl", + "perl-Getopt-Long", + "tcsh", +); +$comp_prereq_hash{'mpi_selector_prereq'} = \@mpi_selector_prereq; + +my @intel_hfi_prereq = ( + "bash", + "glibc", + "libgcc", + "python", + "systemd", + "numactl-libs", + "irqbalance", + "libatomic", +); +$comp_prereq_hash{'intel_hfi_prereq'} = \@intel_hfi_prereq; + +my @mvapich2_prereq = ( + "bash", + "libibverbs", + "librdmacm", + "glibc", + "zlib", + "sysfsutils", +); +$comp_prereq_hash{'mvapich2_prereq'} = \@mvapich2_prereq; + +my @openmpi_prereq = ( + "bash", + "glibc", + "libgcc", + "libgfortran", + "gcc-gfortran", + "libgomp", + "libibverbs", + "libquadmath", + "librdmacm", + "libstdc++", + "libstdc++-devel", + "opensm-libs", + "pkgconfig", + "zlib", +); +$comp_prereq_hash{'openmpi_prereq'} = \@openmpi_prereq; + +my @mvapich2_gcc_hfi_prereq = ( + "bash", + "zlib", + "glibc", +); +$comp_prereq_hash{'mvapich2_gcc_hfi_prereq'} = \@mvapich2_gcc_hfi_prereq; + +my @mvapich2_intel_hfi_prereq = ( + "bash", +); +$comp_prereq_hash{'mvapich2_intel_hfi_prereq'} = \@mvapich2_intel_hfi_prereq; + +my @openmpi_gcc_hfi_prereq = ( + "bash", + "glibc", + "infinipath-psm", + "libgcc", + "libgfortran", + "gcc-gfortran", + "libgomp", + "libibverbs", + "libquadmath", + "librdmacm", + "libstdc++", + "libstdc++-devel", + "opensm-libs", + "pkgconfig", + "zlib", +); +$comp_prereq_hash{'openmpi_gcc_hfi_prereq'} = \@openmpi_gcc_hfi_prereq; + +my @openmpi_intel_hfi_prereq = ( + "bash", +); +$comp_prereq_hash{'openmpi_intel_hfi_prereq'} = \@openmpi_intel_hfi_prereq; diff --git a/CommonInstall/comp_delta_prereq_RHEL76.pl b/CommonInstall/comp_delta_prereq_RHEL76.pl new file mode 100644 index 0000000..8125735 --- /dev/null +++ b/CommonInstall/comp_delta_prereq_RHEL76.pl @@ -0,0 +1,138 @@ +#!/usr/bin/perl +## BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2018, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +## END_ICS_COPYRIGHT8 **************************************** +# +## [ICS VERSION STRING: unknown] +#use strict; +##use Term::ANSIColor; +##use Term::ANSIColor qw(:constants); +##use File::Basename; +##use Math::BigInt; +# +## ========================================================================== +# +#Installation Prequisites array for delta components +my @opa_stack_prereq = ( + "bash", + "kernel", + "kmod", + "rdma-core", + "systemd", + "glibc", + "pciutils", + "opensm-libs", + "libibumad", + "rdma-core-devel", +); +$comp_prereq_hash{'opa_stack_prereq'} = \@opa_stack_prereq; + +my @mpi_selector_prereq = ( + "bash", + "coreutils", + "perl", + "perl-Getopt-Long", + "tcsh", +); +$comp_prereq_hash{'mpi_selector_prereq'} = \@mpi_selector_prereq; + +my @intel_hfi_prereq = ( + "bash", + "glibc", + "libgcc", + "python", + "systemd", + "numactl-libs", + "irqbalance", + "libatomic", +); +$comp_prereq_hash{'intel_hfi_prereq'} = \@intel_hfi_prereq; + +my @mvapich2_prereq = ( + "bash", + "libibverbs", + "librdmacm", + "glibc", + "zlib", + "sysfsutils", +); +$comp_prereq_hash{'mvapich2_prereq'} = \@mvapich2_prereq; + +my @openmpi_prereq = ( + "bash", + "glibc", + "libgcc", + "libgfortran", + "gcc-gfortran", + "libgomp", + "libibverbs", + "libquadmath", + "librdmacm", + "libstdc++", + "libstdc++-devel", + "opensm-libs", + "pkgconfig", + "zlib", +); +$comp_prereq_hash{'openmpi_prereq'} = \@openmpi_prereq; + +my @mvapich2_gcc_hfi_prereq = ( + "bash", + "zlib", + "glibc", +); +$comp_prereq_hash{'mvapich2_gcc_hfi_prereq'} = \@mvapich2_gcc_hfi_prereq; + +my @mvapich2_intel_hfi_prereq = ( + "bash", +); +$comp_prereq_hash{'mvapich2_intel_hfi_prereq'} = \@mvapich2_intel_hfi_prereq; + +my @openmpi_gcc_hfi_prereq = ( + "bash", + "glibc", + "infinipath-psm", + "libgcc", + "libgfortran", + "gcc-gfortran", + "libgomp", + "libibverbs", + "libquadmath", + "librdmacm", + "libstdc++", + "libstdc++-devel", + "opensm-libs", + "pkgconfig", + "zlib", +); +$comp_prereq_hash{'openmpi_gcc_hfi_prereq'} = \@openmpi_gcc_hfi_prereq; + +my @openmpi_intel_hfi_prereq = ( + "bash", +); +$comp_prereq_hash{'openmpi_intel_hfi_prereq'} = \@openmpi_intel_hfi_prereq; diff --git a/CommonInstall/comp_delta_prereq_RHEL77.pl b/CommonInstall/comp_delta_prereq_RHEL77.pl new file mode 100644 index 0000000..8125735 --- /dev/null +++ b/CommonInstall/comp_delta_prereq_RHEL77.pl @@ -0,0 +1,138 @@ +#!/usr/bin/perl +## BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2018, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +## END_ICS_COPYRIGHT8 **************************************** +# +## [ICS VERSION STRING: unknown] +#use strict; +##use Term::ANSIColor; +##use Term::ANSIColor qw(:constants); +##use File::Basename; +##use Math::BigInt; +# +## ========================================================================== +# +#Installation Prequisites array for delta components +my @opa_stack_prereq = ( + "bash", + "kernel", + "kmod", + "rdma-core", + "systemd", + "glibc", + "pciutils", + "opensm-libs", + "libibumad", + "rdma-core-devel", +); +$comp_prereq_hash{'opa_stack_prereq'} = \@opa_stack_prereq; + +my @mpi_selector_prereq = ( + "bash", + "coreutils", + "perl", + "perl-Getopt-Long", + "tcsh", +); +$comp_prereq_hash{'mpi_selector_prereq'} = \@mpi_selector_prereq; + +my @intel_hfi_prereq = ( + "bash", + "glibc", + "libgcc", + "python", + "systemd", + "numactl-libs", + "irqbalance", + "libatomic", +); +$comp_prereq_hash{'intel_hfi_prereq'} = \@intel_hfi_prereq; + +my @mvapich2_prereq = ( + "bash", + "libibverbs", + "librdmacm", + "glibc", + "zlib", + "sysfsutils", +); +$comp_prereq_hash{'mvapich2_prereq'} = \@mvapich2_prereq; + +my @openmpi_prereq = ( + "bash", + "glibc", + "libgcc", + "libgfortran", + "gcc-gfortran", + "libgomp", + "libibverbs", + "libquadmath", + "librdmacm", + "libstdc++", + "libstdc++-devel", + "opensm-libs", + "pkgconfig", + "zlib", +); +$comp_prereq_hash{'openmpi_prereq'} = \@openmpi_prereq; + +my @mvapich2_gcc_hfi_prereq = ( + "bash", + "zlib", + "glibc", +); +$comp_prereq_hash{'mvapich2_gcc_hfi_prereq'} = \@mvapich2_gcc_hfi_prereq; + +my @mvapich2_intel_hfi_prereq = ( + "bash", +); +$comp_prereq_hash{'mvapich2_intel_hfi_prereq'} = \@mvapich2_intel_hfi_prereq; + +my @openmpi_gcc_hfi_prereq = ( + "bash", + "glibc", + "infinipath-psm", + "libgcc", + "libgfortran", + "gcc-gfortran", + "libgomp", + "libibverbs", + "libquadmath", + "librdmacm", + "libstdc++", + "libstdc++-devel", + "opensm-libs", + "pkgconfig", + "zlib", +); +$comp_prereq_hash{'openmpi_gcc_hfi_prereq'} = \@openmpi_gcc_hfi_prereq; + +my @openmpi_intel_hfi_prereq = ( + "bash", +); +$comp_prereq_hash{'openmpi_intel_hfi_prereq'} = \@openmpi_intel_hfi_prereq; diff --git a/CommonInstall/comp_delta_prereq_RHEL8.pl b/CommonInstall/comp_delta_prereq_RHEL8.pl new file mode 100644 index 0000000..804443d --- /dev/null +++ b/CommonInstall/comp_delta_prereq_RHEL8.pl @@ -0,0 +1,137 @@ +#!/usr/bin/perl +## BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2019, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +## END_ICS_COPYRIGHT8 **************************************** +# +## [ICS VERSION STRING: unknown] +#use strict; +##use Term::ANSIColor; +##use Term::ANSIColor qw(:constants); +##use File::Basename; +##use Math::BigInt; +# +## ========================================================================== +# +#Installation Prequisites array for delta components +my @opa_stack_prereq = ( + "bash", + "kernel", + "kmod", + "rdma-core", + "systemd", + "glibc", + "pciutils", + "opensm-libs", + "libibumad", + "rdma-core-devel", +); +$comp_prereq_hash{'opa_stack_prereq'} = \@opa_stack_prereq; + +my @mpi_selector_prereq = ( + "bash", + "coreutils", + "perl", + "perl-Getopt-Long", + "tcsh", +); +$comp_prereq_hash{'mpi_selector_prereq'} = \@mpi_selector_prereq; + +my @intel_hfi_prereq = ( + "bash", + "glibc", + "libgcc", + "python2", + "systemd", + "numactl-libs", + "irqbalance", + "libatomic", +); +$comp_prereq_hash{'intel_hfi_prereq'} = \@intel_hfi_prereq; + +my @mvapich2_prereq = ( + "bash", + "libibverbs", + "librdmacm", + "glibc", + "zlib", + "sysfsutils", +); +$comp_prereq_hash{'mvapich2_prereq'} = \@mvapich2_prereq; + +my @openmpi_prereq = ( + "bash", + "glibc", + "libgcc", + "libgfortran", + "gcc-gfortran", + "libgomp", + "libibverbs", + "libquadmath", + "librdmacm", + "libstdc++", + "libstdc++-devel", + "opensm-libs", + "pkgconf", + "zlib", +); +$comp_prereq_hash{'openmpi_prereq'} = \@openmpi_prereq; + +my @mvapich2_gcc_hfi_prereq = ( + "bash", + "zlib", + "glibc", +); +$comp_prereq_hash{'mvapich2_gcc_hfi_prereq'} = \@mvapich2_gcc_hfi_prereq; + +my @mvapich2_intel_hfi_prereq = ( + "bash", +); +$comp_prereq_hash{'mvapich2_intel_hfi_prereq'} = \@mvapich2_intel_hfi_prereq; + +my @openmpi_gcc_hfi_prereq = ( + "bash", + "glibc", + "libgcc", + "libgfortran", + "gcc-gfortran", + "libgomp", + "libibverbs", + "libquadmath", + "librdmacm", + "libstdc++", + "libstdc++-devel", + "opensm-libs", + "pkgconf", + "zlib", +); +$comp_prereq_hash{'openmpi_gcc_hfi_prereq'} = \@openmpi_gcc_hfi_prereq; + +my @openmpi_intel_hfi_prereq = ( + "bash", +); +$comp_prereq_hash{'openmpi_intel_hfi_prereq'} = \@openmpi_intel_hfi_prereq; diff --git a/CommonInstall/comp_delta_prereq_RHEL81.pl b/CommonInstall/comp_delta_prereq_RHEL81.pl new file mode 100644 index 0000000..804443d --- /dev/null +++ b/CommonInstall/comp_delta_prereq_RHEL81.pl @@ -0,0 +1,137 @@ +#!/usr/bin/perl +## BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2019, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +## END_ICS_COPYRIGHT8 **************************************** +# +## [ICS VERSION STRING: unknown] +#use strict; +##use Term::ANSIColor; +##use Term::ANSIColor qw(:constants); +##use File::Basename; +##use Math::BigInt; +# +## ========================================================================== +# +#Installation Prequisites array for delta components +my @opa_stack_prereq = ( + "bash", + "kernel", + "kmod", + "rdma-core", + "systemd", + "glibc", + "pciutils", + "opensm-libs", + "libibumad", + "rdma-core-devel", +); +$comp_prereq_hash{'opa_stack_prereq'} = \@opa_stack_prereq; + +my @mpi_selector_prereq = ( + "bash", + "coreutils", + "perl", + "perl-Getopt-Long", + "tcsh", +); +$comp_prereq_hash{'mpi_selector_prereq'} = \@mpi_selector_prereq; + +my @intel_hfi_prereq = ( + "bash", + "glibc", + "libgcc", + "python2", + "systemd", + "numactl-libs", + "irqbalance", + "libatomic", +); +$comp_prereq_hash{'intel_hfi_prereq'} = \@intel_hfi_prereq; + +my @mvapich2_prereq = ( + "bash", + "libibverbs", + "librdmacm", + "glibc", + "zlib", + "sysfsutils", +); +$comp_prereq_hash{'mvapich2_prereq'} = \@mvapich2_prereq; + +my @openmpi_prereq = ( + "bash", + "glibc", + "libgcc", + "libgfortran", + "gcc-gfortran", + "libgomp", + "libibverbs", + "libquadmath", + "librdmacm", + "libstdc++", + "libstdc++-devel", + "opensm-libs", + "pkgconf", + "zlib", +); +$comp_prereq_hash{'openmpi_prereq'} = \@openmpi_prereq; + +my @mvapich2_gcc_hfi_prereq = ( + "bash", + "zlib", + "glibc", +); +$comp_prereq_hash{'mvapich2_gcc_hfi_prereq'} = \@mvapich2_gcc_hfi_prereq; + +my @mvapich2_intel_hfi_prereq = ( + "bash", +); +$comp_prereq_hash{'mvapich2_intel_hfi_prereq'} = \@mvapich2_intel_hfi_prereq; + +my @openmpi_gcc_hfi_prereq = ( + "bash", + "glibc", + "libgcc", + "libgfortran", + "gcc-gfortran", + "libgomp", + "libibverbs", + "libquadmath", + "librdmacm", + "libstdc++", + "libstdc++-devel", + "opensm-libs", + "pkgconf", + "zlib", +); +$comp_prereq_hash{'openmpi_gcc_hfi_prereq'} = \@openmpi_gcc_hfi_prereq; + +my @openmpi_intel_hfi_prereq = ( + "bash", +); +$comp_prereq_hash{'openmpi_intel_hfi_prereq'} = \@openmpi_intel_hfi_prereq; diff --git a/CommonInstall/comp_delta_prereq_SLES122.pl b/CommonInstall/comp_delta_prereq_SLES122.pl new file mode 100644 index 0000000..7b44ffd --- /dev/null +++ b/CommonInstall/comp_delta_prereq_SLES122.pl @@ -0,0 +1,140 @@ +#!/usr/bin/perl +## BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +## END_ICS_COPYRIGHT8 **************************************** +# +## [ICS VERSION STRING: unknown] +#use strict; +##use Term::ANSIColor; +##use Term::ANSIColor qw(:constants); +##use File::Basename; +##use Math::BigInt; +# +## ========================================================================== +# +#Installation Prequisites array for delta components +my @opa_stack_prereq = ( + "bash", + "kmod", + "rdma", + "systemd", + "coreutils", + "grep", + "opensm-libs3", + "libibmad5", + "libibcm1", + "libibumad3", + "libibumad-devel", +); +$comp_prereq_hash{'opa_stack_prereq'} = \@opa_stack_prereq; + +my @intel_hfi_prereq = ( + "glibc", + "libhfi1verbs-rdmav2", + "libgcc_s1", + "bash", + "udev", + "libudev-devel", + "python-base", + "libedit0", + "libncurses5", + "libnuma1", + "irqbalance", + "libatomic1", +); +$comp_prereq_hash{'intel_hfi_prereq'} = \@intel_hfi_prereq; + +my @mvapich2_gcc_hfi_prereq = ( + "bash", + "glibc", + "libz1", + "mpi-selector", +); +$comp_prereq_hash{'mvapich2_gcc_hfi_prereq'} = \@mvapich2_gcc_hfi_prereq; + +my @mvapich2_intel_hfi_prereq = ( + "bash", + "mpi-selector", +); +$comp_prereq_hash{'mvapich2_intel_hfi_prereq'} = \@mvapich2_intel_hfi_prereq; + +my @openmpi_gcc_hfi_prereq = ( + "glibc", + "bash", + "libpsm_infinipath1", + "pkg-config", + "libgcc_s1", + "libgfortran3", + "gcc-fortran", + "libgomp1", + "libibverbs1", + "libquadmath0", + "librdmacm1", + "libstdc++6", + "libz1", + "opensm-libs3", + "opensm-devel", + "mpi-selector", +); +$comp_prereq_hash{'openmpi_gcc_hfi_prereq'} = \@openmpi_gcc_hfi_prereq; + +my @openmpi_intel_hfi_prereq = ( + "bash", + "mpi-selector", +); +$comp_prereq_hash{'openmpi_intel_hfi_prereq'} = \@openmpi_intel_hfi_prereq; + +my @mvapich2_prereq = ( + "bash", + "libibverbs1", + "librdmacm1", + "glibc", + "libz1", + "mpi-selector", +); +$comp_prereq_hash{'mvapich2_prereq'} = \@mvapich2_prereq; + +my @openmpi_prereq = ( + "glibc", + "bash", + "libz1", + "pkg-config", + "libgcc_s1", + "libgfortran3", + "gcc-fortran", + "libgomp1", + "libibverbs1", + "libquadmath0", + "librdmacm1", + "libstdc++6", + "libz1", + "opensm-libs3", + "opensm-devel", + "mpi-selector", +); +$comp_prereq_hash{'openmpi_prereq'} = \@openmpi_prereq; diff --git a/CommonInstall/comp_delta_prereq_SLES123.pl b/CommonInstall/comp_delta_prereq_SLES123.pl new file mode 100644 index 0000000..29b1c1f --- /dev/null +++ b/CommonInstall/comp_delta_prereq_SLES123.pl @@ -0,0 +1,140 @@ +#!/usr/bin/perl +## BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +## END_ICS_COPYRIGHT8 **************************************** +# +## [ICS VERSION STRING: unknown] +#use strict; +##use Term::ANSIColor; +##use Term::ANSIColor qw(:constants); +##use File::Basename; +##use Math::BigInt; +# +## ========================================================================== +# +#Installation Prequisites array for delta components +my @opa_stack_prereq = ( + "bash", + "kmod", + "rdma-core", + "systemd", + "coreutils", + "grep", + "opensm-libs3", + "libibmad5", + "libibcm1", + "libibumad3", + "rdma-core-devel", + "rdma-ndd", +); +$comp_prereq_hash{'opa_stack_prereq'} = \@opa_stack_prereq; + +my @intel_hfi_prereq = ( + "glibc", + "libgcc_s1", + "bash", + "udev", + "libudev-devel", + "python-base", + "libedit0", + "libncurses5", + "libnuma1", + "irqbalance", + "libatomic1", +); +$comp_prereq_hash{'intel_hfi_prereq'} = \@intel_hfi_prereq; + +my @mvapich2_gcc_hfi_prereq = ( + "bash", + "glibc", + "libz1", + "mpi-selector", +); +$comp_prereq_hash{'mvapich2_gcc_hfi_prereq'} = \@mvapich2_gcc_hfi_prereq; + +my @mvapich2_intel_hfi_prereq = ( + "bash", + "mpi-selector", +); +$comp_prereq_hash{'mvapich2_intel_hfi_prereq'} = \@mvapich2_intel_hfi_prereq; + +my @openmpi_gcc_hfi_prereq = ( + "glibc", + "bash", + "libpsm_infinipath1", + "pkg-config", + "libgcc_s1", + "libgfortran3", + "gcc-fortran", + "libgomp1", + "libibverbs1", + "libquadmath0", + "librdmacm1", + "libstdc++6", + "libz1", + "opensm-libs3", + "opensm-devel", + "mpi-selector", +); +$comp_prereq_hash{'openmpi_gcc_hfi_prereq'} = \@openmpi_gcc_hfi_prereq; + +my @openmpi_intel_hfi_prereq = ( + "bash", + "mpi-selector", +); +$comp_prereq_hash{'openmpi_intel_hfi_prereq'} = \@openmpi_intel_hfi_prereq; + +my @mvapich2_prereq = ( + "bash", + "libibverbs1", + "librdmacm1", + "glibc", + "libz1", + "mpi-selector", +); +$comp_prereq_hash{'mvapich2_prereq'} = \@mvapich2_prereq; + +my @openmpi_prereq = ( + "glibc", + "bash", + "libz1", + "pkg-config", + "libgcc_s1", + "libgfortran3", + "gcc-fortran", + "libgomp1", + "libibverbs1", + "libquadmath0", + "librdmacm1", + "libstdc++6", + "libz1", + "opensm-libs3", + "opensm-devel", + "mpi-selector", +); +$comp_prereq_hash{'openmpi_prereq'} = \@openmpi_prereq; diff --git a/CommonInstall/comp_delta_prereq_SLES124.pl b/CommonInstall/comp_delta_prereq_SLES124.pl new file mode 100644 index 0000000..9fe4f42 --- /dev/null +++ b/CommonInstall/comp_delta_prereq_SLES124.pl @@ -0,0 +1,140 @@ +#!/usr/bin/perl +## BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2018, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +## END_ICS_COPYRIGHT8 **************************************** +# +## [ICS VERSION STRING: unknown] +#use strict; +##use Term::ANSIColor; +##use Term::ANSIColor qw(:constants); +##use File::Basename; +##use Math::BigInt; +# +## ========================================================================== +# +#Installation Prequisites array for delta components +my @opa_stack_prereq = ( + "bash", + "kmod", + "rdma-core", + "rdma-ndd", + "systemd", + "coreutils", + "grep", + "opensm-libs3", + "libibmad5", + "libibcm1", + "libibumad3", + "rdma-core-devel", +); +$comp_prereq_hash{'opa_stack_prereq'} = \@opa_stack_prereq; + +my @intel_hfi_prereq = ( + "glibc", + "libgcc_s1", + "bash", + "udev", + "libudev-devel", + "python-base", + "libedit0", + "libncurses5", + "libnuma1", + "irqbalance", + "libatomic1", +); +$comp_prereq_hash{'intel_hfi_prereq'} = \@intel_hfi_prereq; + +my @mvapich2_gcc_hfi_prereq = ( + "bash", + "glibc", + "libz1", + "mpi-selector", +); +$comp_prereq_hash{'mvapich2_gcc_hfi_prereq'} = \@mvapich2_gcc_hfi_prereq; + +my @mvapich2_intel_hfi_prereq = ( + "bash", + "mpi-selector", +); +$comp_prereq_hash{'mvapich2_intel_hfi_prereq'} = \@mvapich2_intel_hfi_prereq; + +my @openmpi_gcc_hfi_prereq = ( + "glibc", + "bash", + "libpsm_infinipath1", + "pkg-config", + "libgcc_s1", + "libgfortran3", + "gcc-fortran", + "libgomp1", + "libibverbs1", + "libquadmath0", + "librdmacm1", + "libstdc++6", + "libz1", + "opensm-libs3", + "opensm-devel", + "mpi-selector", +); +$comp_prereq_hash{'openmpi_gcc_hfi_prereq'} = \@openmpi_gcc_hfi_prereq; + +my @openmpi_intel_hfi_prereq = ( + "bash", + "mpi-selector", +); +$comp_prereq_hash{'openmpi_intel_hfi_prereq'} = \@openmpi_intel_hfi_prereq; + +my @mvapich2_prereq = ( + "bash", + "libibverbs1", + "librdmacm1", + "glibc", + "libz1", + "mpi-selector", +); +$comp_prereq_hash{'mvapich2_prereq'} = \@mvapich2_prereq; + +my @openmpi_prereq = ( + "glibc", + "bash", + "libz1", + "pkg-config", + "libgcc_s1", + "libgfortran3", + "gcc-fortran", + "libgomp1", + "libibverbs1", + "libquadmath0", + "librdmacm1", + "libstdc++6", + "libz1", + "opensm-libs3", + "opensm-devel", + "mpi-selector", +); +$comp_prereq_hash{'openmpi_prereq'} = \@openmpi_prereq; diff --git a/CommonInstall/comp_delta_prereq_SLES125.pl b/CommonInstall/comp_delta_prereq_SLES125.pl new file mode 100644 index 0000000..2577582 --- /dev/null +++ b/CommonInstall/comp_delta_prereq_SLES125.pl @@ -0,0 +1,139 @@ +#!/usr/bin/perl +## BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2018, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +## END_ICS_COPYRIGHT8 **************************************** +# +## [ICS VERSION STRING: unknown] +#use strict; +##use Term::ANSIColor; +##use Term::ANSIColor qw(:constants); +##use File::Basename; +##use Math::BigInt; +# +## ========================================================================== +# +#Installation Prequisites array for delta components +my @opa_stack_prereq = ( + "bash", + "kmod", + "rdma-core", + "rdma-ndd", + "systemd", + "coreutils", + "grep", + "libopensm8", + "libibmad5", + "libibumad3", + "rdma-core-devel", +); +$comp_prereq_hash{'opa_stack_prereq'} = \@opa_stack_prereq; + +my @intel_hfi_prereq = ( + "glibc", + "libgcc_s1", + "bash", + "udev", + "libudev-devel", + "python-base", + "libedit0", + "libncurses5", + "libnuma1", + "irqbalance", + "libatomic1", +); +$comp_prereq_hash{'intel_hfi_prereq'} = \@intel_hfi_prereq; + +my @mvapich2_gcc_hfi_prereq = ( + "bash", + "glibc", + "libz1", + "mpi-selector", +); +$comp_prereq_hash{'mvapich2_gcc_hfi_prereq'} = \@mvapich2_gcc_hfi_prereq; + +my @mvapich2_intel_hfi_prereq = ( + "bash", + "mpi-selector", +); +$comp_prereq_hash{'mvapich2_intel_hfi_prereq'} = \@mvapich2_intel_hfi_prereq; + +my @openmpi_gcc_hfi_prereq = ( + "glibc", + "bash", + "libpsm_infinipath1", + "pkg-config", + "libgcc_s1", + "libgfortran3", + "gcc-fortran", + "libgomp1", + "libibverbs1", + "libquadmath0", + "librdmacm1", + "libstdc++6", + "libz1", + "libopensm8", + "opensm-devel", + "mpi-selector", +); +$comp_prereq_hash{'openmpi_gcc_hfi_prereq'} = \@openmpi_gcc_hfi_prereq; + +my @openmpi_intel_hfi_prereq = ( + "bash", + "mpi-selector", +); +$comp_prereq_hash{'openmpi_intel_hfi_prereq'} = \@openmpi_intel_hfi_prereq; + +my @mvapich2_prereq = ( + "bash", + "libibverbs1", + "librdmacm1", + "glibc", + "libz1", + "mpi-selector", +); +$comp_prereq_hash{'mvapich2_prereq'} = \@mvapich2_prereq; + +my @openmpi_prereq = ( + "glibc", + "bash", + "libz1", + "pkg-config", + "libgcc_s1", + "libgfortran3", + "gcc-fortran", + "libgomp1", + "libibverbs1", + "libquadmath0", + "librdmacm1", + "libstdc++6", + "libz1", + "libopensm8", + "opensm-devel", + "mpi-selector", +); +$comp_prereq_hash{'openmpi_prereq'} = \@openmpi_prereq; diff --git a/CommonInstall/comp_delta_prereq_SLES15.pl b/CommonInstall/comp_delta_prereq_SLES15.pl new file mode 100644 index 0000000..305f034 --- /dev/null +++ b/CommonInstall/comp_delta_prereq_SLES15.pl @@ -0,0 +1,138 @@ +#!/usr/bin/perl +## BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +## END_ICS_COPYRIGHT8 **************************************** +# +## [ICS VERSION STRING: unknown] +#use strict; +##use Term::ANSIColor; +##use Term::ANSIColor qw(:constants); +##use File::Basename; +##use Math::BigInt; +# +## ========================================================================== +# +#Installation Prequisites array for delta components +my @opa_stack_prereq = ( + "bash", + "kmod", + "rdma-core", + "rdma-ndd", + "systemd", + "coreutils", + "grep", + "libosmcomp3", + "libibmad5", + "libibumad3", + "rdma-core-devel", +); +$comp_prereq_hash{'opa_stack_prereq'} = \@opa_stack_prereq; + +my @intel_hfi_prereq = ( + "glibc", + "libgcc_s1", + "bash", + "udev", + "libudev-devel", + "python-base", + "libedit0", + "libncurses6", + "libnuma1", + "irqbalance", + "libatomic1", +); +$comp_prereq_hash{'intel_hfi_prereq'} = \@intel_hfi_prereq; + +my @mvapich2_gcc_hfi_prereq = ( + "bash", + "glibc", + "libz1", + "mpi-selector", +); +$comp_prereq_hash{'mvapich2_gcc_hfi_prereq'} = \@mvapich2_gcc_hfi_prereq; + +my @mvapich2_intel_hfi_prereq = ( + "bash", + "mpi-selector", +); +$comp_prereq_hash{'mvapich2_intel_hfi_prereq'} = \@mvapich2_intel_hfi_prereq; + +my @openmpi_gcc_hfi_prereq = ( + "glibc", + "bash", + "libpsm_infinipath1", + "pkg-config", + "libgcc_s1", + "libgfortran4", + "gcc-fortran", + "libgomp1", + "libibverbs1", + "libquadmath0", + "librdmacm1", + "libstdc++6", + "libz1", + "opensm-devel", + "mpi-selector", +); +$comp_prereq_hash{'openmpi_gcc_hfi_prereq'} = \@openmpi_gcc_hfi_prereq; + +my @openmpi_intel_hfi_prereq = ( + "bash", + "mpi-selector", +); +$comp_prereq_hash{'openmpi_intel_hfi_prereq'} = \@openmpi_intel_hfi_prereq; + +my @mvapich2_prereq = ( + "bash", + "libibverbs1", + "librdmacm1", + "glibc", + "libz1", + "mpi-selector", +); +$comp_prereq_hash{'mvapich2_prereq'} = \@mvapich2_prereq; + +my @openmpi_prereq = ( + "glibc", + "bash", + "libz1", + "pkg-config", + "libgcc_s1", + "libgfortran3", + "gcc-fortran", + "libgomp1", + "libibverbs1", + "libquadmath0", + "librdmacm1", + "libstdc++6", + "libz1", + "opensm-libs3", + "opensm-devel", + "mpi-selector", +); +$comp_prereq_hash{'openmpi_prereq'} = \@openmpi_prereq; diff --git a/CommonInstall/comp_delta_prereq_SLES151.pl b/CommonInstall/comp_delta_prereq_SLES151.pl new file mode 100644 index 0000000..172a3ca --- /dev/null +++ b/CommonInstall/comp_delta_prereq_SLES151.pl @@ -0,0 +1,138 @@ +#!/usr/bin/perl +## BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2019, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +## END_ICS_COPYRIGHT8 **************************************** +# +## [ICS VERSION STRING: unknown] +#use strict; +##use Term::ANSIColor; +##use Term::ANSIColor qw(:constants); +##use File::Basename; +##use Math::BigInt; +# +## ========================================================================== +# +#Installation Prequisites array for delta components +my @opa_stack_prereq = ( + "bash", + "kmod", + "rdma-core", + "rdma-ndd", + "systemd", + "coreutils", + "grep", + "libosmcomp4", + "libibmad5", + "libibumad3", + "rdma-core-devel", +); +$comp_prereq_hash{'opa_stack_prereq'} = \@opa_stack_prereq; + +my @intel_hfi_prereq = ( + "glibc", + "libgcc_s1", + "bash", + "udev", + "libudev-devel", + "python-base", + "libedit0", + "libncurses6", + "libnuma1", + "irqbalance", + "libatomic1", +); +$comp_prereq_hash{'intel_hfi_prereq'} = \@intel_hfi_prereq; + +my @mvapich2_gcc_hfi_prereq = ( + "bash", + "glibc", + "libz1", + "mpi-selector", +); +$comp_prereq_hash{'mvapich2_gcc_hfi_prereq'} = \@mvapich2_gcc_hfi_prereq; + +my @mvapich2_intel_hfi_prereq = ( + "bash", + "mpi-selector", +); +$comp_prereq_hash{'mvapich2_intel_hfi_prereq'} = \@mvapich2_intel_hfi_prereq; + +my @openmpi_gcc_hfi_prereq = ( + "glibc", + "bash", + "libpsm_infinipath1", + "pkg-config", + "libgcc_s1", + "libgfortran4", + "gcc-fortran", + "libgomp1", + "libibverbs1", + "libquadmath0", + "librdmacm1", + "libstdc++6", + "libz1", + "opensm-devel", + "mpi-selector", +); +$comp_prereq_hash{'openmpi_gcc_hfi_prereq'} = \@openmpi_gcc_hfi_prereq; + +my @openmpi_intel_hfi_prereq = ( + "bash", + "mpi-selector", +); +$comp_prereq_hash{'openmpi_intel_hfi_prereq'} = \@openmpi_intel_hfi_prereq; + +my @mvapich2_prereq = ( + "bash", + "libibverbs1", + "librdmacm1", + "glibc", + "libz1", + "mpi-selector", +); +$comp_prereq_hash{'mvapich2_prereq'} = \@mvapich2_prereq; + +my @openmpi_prereq = ( + "glibc", + "bash", + "libz1", + "pkg-config", + "libgcc_s1", + "libgfortran3", + "gcc-fortran", + "libgomp1", + "libibverbs1", + "libquadmath0", + "librdmacm1", + "libstdc++6", + "libz1", + "opensm-libs3", + "opensm-devel", + "mpi-selector", +); +$comp_prereq_hash{'openmpi_prereq'} = \@openmpi_prereq; diff --git a/CommonInstall/comp_fastfabric.pl b/CommonInstall/comp_fastfabric.pl new file mode 100755 index 0000000..1838e53 --- /dev/null +++ b/CommonInstall/comp_fastfabric.pl @@ -0,0 +1,261 @@ +#!/usr/bin/perl +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] +use strict; +#use Term::ANSIColor; +#use Term::ANSIColor qw(:constants); +#use File::Basename; +#use Math::BigInt; + +# ========================================================================== +# Fast Fabric installation + +my $FF_CONF_FILE = "/usr/lib/opa/tools/opafastfabric.conf"; +my $FF_TLS_CONF_FILE = "/etc/opa/opaff.xml"; + +sub get_rpms_dir_fastfabric +{ + my $srcdir=$ComponentInfo{'fastfabric'}{'SrcDir'}; + return "$srcdir/RPMS/*"; +} + +sub available_fastfabric +{ + my $srcdir=$ComponentInfo{'fastfabric'}{'SrcDir'}; + return ((rpm_resolve("$srcdir/RPMS/*/opa-mpi-apps", "any") ne "") && + (rpm_resolve("$srcdir/RPMS/*/opa-fastfabric", "any") ne "")); +} + +sub installed_fastfabric +{ + return rpm_is_installed("opa-fastfabric", "any"); +} + +# only called if installed_fastfabric is true +sub installed_version_fastfabric +{ + my $version = rpm_query_version_release_pkg("opa-fastfabric"); + return dot_version("$version"); +} + +# only called if available_fastfabric is true +sub media_version_fastfabric +{ + my $srcdir=$ComponentInfo{'fastfabric'}{'SrcDir'}; + my $rpmfile = rpm_resolve("$srcdir/RPMS/*/opa-fastfabric", "any"); + my $version= rpm_query_version_release("$rpmfile"); + # assume media properly built with matching versions for all rpms + return dot_version("$version"); +} + +sub build_fastfabric +{ + my $osver = $_[0]; + my $debug = $_[1]; # enable extra debug of build itself + my $build_temp = $_[2]; # temp area for use by build + my $force = $_[3]; # force a rebuild + return 0; # success +} + +sub need_reinstall_fastfabric($$) +{ + my $install_list = shift(); # total that will be installed when done + my $installing_list = shift(); # what items are being installed/reinstalled + + return "no"; +} + +sub check_os_prereqs_fastfabric +{ + return rpm_check_os_prereqs("fastfabric", "user"); +} + +sub preinstall_fastfabric +{ + my $install_list = $_[0]; # total that will be installed when done + my $installing_list = $_[1]; # what items are being installed/reinstalled + + return 0; # success +} + +sub install_fastfabric +{ + my $install_list = $_[0]; # total that will be installed when done + my $installing_list = $_[1]; # what items are being installed/reinstalled + + my $depricated_dir = "/etc/sysconfig/opa"; + + my $version=media_version_fastfabric(); + chomp $version; + printf("Installing $ComponentInfo{'fastfabric'}{'Name'} $version $DBG_FREE...\n"); + LogPrint "Installing $ComponentInfo{'fastfabric'}{'Name'} $version $DBG_FREE for $CUR_DISTRO_VENDOR $CUR_VENDOR_VER\n"; + + install_comp_rpms('fastfabric', " -U ", $install_list); + + # TBD - spec file should do this + check_dir("/usr/share/opa/samples"); + system "chmod ug+x /usr/share/opa/samples/hostverify.sh"; + system "rm -f /usr/share/opa/samples/nodeverify.sh"; + + check_rpm_config_file("$FF_TLS_CONF_FILE"); + printf("Default opaff.xml can be found in '/usr/share/opa/samples/opaff.xml-sample'\n"); + check_rpm_config_file("$CONFIG_DIR/opa/opamon.conf", $depricated_dir); + check_rpm_config_file("$CONFIG_DIR/opa/opafastfabric.conf", $depricated_dir); + check_rpm_config_file("$CONFIG_DIR/opa/allhosts", $depricated_dir); + check_rpm_config_file("$CONFIG_DIR/opa/chassis", $depricated_dir); + check_rpm_config_file("$CONFIG_DIR/opa/hosts", $depricated_dir); + check_rpm_config_file("$CONFIG_DIR/opa/ports", $depricated_dir); + check_rpm_config_file("$CONFIG_DIR/opa/switches", $depricated_dir); +# TBD - this should not be a config file + check_rpm_config_file("/usr/lib/opa/tools/osid_wrapper"); + + # TBD - spec file should remove this + system("rm -rf $OPA_CONFIG_DIR/iba_stat.conf"); # old config + + $ComponentWasInstalled{'fastfabric'}=1; +} + +sub postinstall_fastfabric +{ + my $install_list = $_[0]; # total that will be installed when done + my $installing_list = $_[1]; # what items are being installed/reinstalled +} + +sub uninstall_fastfabric +{ + my $install_list = $_[0]; # total that will be left installed when done + my $uninstalling_list = $_[1]; # what items are being uninstalled + + uninstall_comp_rpms('fastfabric', '', $install_list, $uninstalling_list, 'verbose'); + + NormalPrint("Uninstalling $ComponentInfo{'fastfabric'}{'Name'}...\n"); + remove_conf_file("$ComponentInfo{'fastfabric'}{'Name'}", "$FF_CONF_FILE"); + remove_conf_file("$ComponentInfo{'fastfabric'}{'Name'}", "$OPA_CONFIG_DIR/iba_stat.conf"); + remove_conf_file("$ComponentInfo{'fastfabric'}{'Name'}", "$FF_TLS_CONF_FILE"); + + # remove samples we installed (or user compiled), however do not remove + # any logs or other files the user may have created + remove_installed_files "/usr/share/opa/samples"; + system "rmdir /usr/share/opa/samples 2>/dev/null"; # remove only if empty + # just in case, newer rpms should clean these up + + system("rm -rf /usr/lib/opa/.comp_fastfabric.pl"); + system "rmdir /usr/lib/opa 2>/dev/null"; # remove only if empty + system "rmdir $BASE_DIR 2>/dev/null"; # remove only if empty + system "rmdir $OPA_CONFIG_DIR 2>/dev/null"; # remove only if empty + $ComponentWasInstalled{'fastfabric'}=0; +} + +############################################################################# +## +## OPAMGT SDK + +sub get_rpms_dir_opamgt_sdk +{ + my $srcdir=$ComponentInfo{'opamgt_sdk'}{'SrcDir'}; + return "$srcdir/RPMS/*"; +} + +sub available_opamgt_sdk +{ + my $srcdir = $ComponentInfo{'opamgt_sdk'}{'SrcDir'}; + return ( rpm_exists("$srcdir/RPMS/*/opa-libopamgt-devel", "any") && + rpm_exists("$srcdir/RPMS/*/opa-libopamgt", "any")); +} + +sub installed_opamgt_sdk +{ + return ( rpm_is_installed("opa-libopamgt-devel", "any") && + rpm_is_installed("opa-libopamgt", "any")); +} + +sub installed_version_opamgt_sdk +{ + my $version = rpm_query_version_release_pkg("opa-libopamgt-devel"); + return dot_version("$version"); +} + +sub media_version_opamgt_sdk +{ + my $srcdir = $ComponentInfo{'opamgt_sdk'}{'SrcDir'}; + my $rpm = rpm_resolve("$srcdir/RPMS/*/opa-libopamgt-devel", "any"); + my $version = rpm_query_version_release($rpm); + return dot_version("$version"); +} + +sub build_opamgt_sdk +{ + return 0; +} + +sub need_reinstall_opamgt_sdk +{ + return "no"; +} + +sub check_os_prereqs_opamgt_sdk +{ + return rpm_check_os_prereqs("opamgt_sdk", "user"); +} + +sub preinstall_opamgt_sdk +{ + return 0; +} + +sub install_opamgt_sdk +{ + my $install_list = $_[0]; # total that will be installed when done + my $installing_list = $_[1]; # what items are being installed/reinstalled + + my $version=media_version_opamgt_sdk(); + chomp $version; + printf("Installing $ComponentInfo{'opamgt_sdk'}{'Name'} $version $DBG_FREE...\n"); + LogPrint "Installing $ComponentInfo{'opamgt_sdk'}{'Name'} $version $DBG_FREE for $CUR_DISTRO_VENDOR $CUR_VENDOR_VER\n"; + + install_comp_rpms('opamgt_sdk', "", $install_list); + + $ComponentWasInstalled{'opamgt_sdk'}=1; +} + +sub postinstall_opamgt_sdk +{ + +} + +sub uninstall_opamgt_sdk +{ + my $install_list = $_[0]; # total that will be left installed when done + my $uninstalling_list = $_[1]; # what items are being uninstalled + + uninstall_comp_rpms('opamgt_sdk', '', $install_list, $uninstalling_list, 'verbose'); + $ComponentWasInstalled{'opamgt_sdk'}=0; +} diff --git a/CommonInstall/comp_ff_of_prereq_RHEL72.pl b/CommonInstall/comp_ff_of_prereq_RHEL72.pl new file mode 100644 index 0000000..7107407 --- /dev/null +++ b/CommonInstall/comp_ff_of_prereq_RHEL72.pl @@ -0,0 +1,86 @@ +#!/usr/bin/perl +## BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +## END_ICS_COPYRIGHT8 **************************************** +# +## [ICS VERSION STRING: unknown] +#use strict; +##use Term::ANSIColor; +##use Term::ANSIColor qw(:constants); +##use File::Basename; +##use Math::BigInt; +# +## ========================================================================== +# +#Installation Prequisites array for fast fabric +#and of tools component +my @oftools_prereq = ( + "glibc", + "libgcc", + "libibumad", + "libibverbs", + "libstdc++", +); +$comp_prereq_hash{'oftools_prereq'} = \@oftools_prereq; + +my @fastfabric_prereq = ( + "atlas", + "bash", + "bc", + "expat", + "expect", + "glibc", + "libgcc", + "libibumad", + "libibverbs", + "libstdc++", + "ncurses-libs", + "openssl-libs", + "perl", + "perl-Getopt-Long", + "perl-Socket", + "rdma", + "tcl", + "zlib", +); +$comp_prereq_hash{'fastfabric_prereq'} = \@fastfabric_prereq; + +my @opamgt_sdk_prereq = ( + "bash", + "glibc", + "libgcc", + "libibumad", + "libibumad-devel", + "libibverbs", + "libibverbs-devel", + "libstdc++", + "openssl", + "openssl-devel", + "openssl-libs", +); +$comp_prereq_hash{'opamgt_sdk_prereq'} = \@opamgt_sdk_prereq; diff --git a/CommonInstall/comp_ff_of_prereq_RHEL72.pl.base b/CommonInstall/comp_ff_of_prereq_RHEL72.pl.base new file mode 100644 index 0000000..7107407 --- /dev/null +++ b/CommonInstall/comp_ff_of_prereq_RHEL72.pl.base @@ -0,0 +1,86 @@ +#!/usr/bin/perl +## BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +## END_ICS_COPYRIGHT8 **************************************** +# +## [ICS VERSION STRING: unknown] +#use strict; +##use Term::ANSIColor; +##use Term::ANSIColor qw(:constants); +##use File::Basename; +##use Math::BigInt; +# +## ========================================================================== +# +#Installation Prequisites array for fast fabric +#and of tools component +my @oftools_prereq = ( + "glibc", + "libgcc", + "libibumad", + "libibverbs", + "libstdc++", +); +$comp_prereq_hash{'oftools_prereq'} = \@oftools_prereq; + +my @fastfabric_prereq = ( + "atlas", + "bash", + "bc", + "expat", + "expect", + "glibc", + "libgcc", + "libibumad", + "libibverbs", + "libstdc++", + "ncurses-libs", + "openssl-libs", + "perl", + "perl-Getopt-Long", + "perl-Socket", + "rdma", + "tcl", + "zlib", +); +$comp_prereq_hash{'fastfabric_prereq'} = \@fastfabric_prereq; + +my @opamgt_sdk_prereq = ( + "bash", + "glibc", + "libgcc", + "libibumad", + "libibumad-devel", + "libibverbs", + "libibverbs-devel", + "libstdc++", + "openssl", + "openssl-devel", + "openssl-libs", +); +$comp_prereq_hash{'opamgt_sdk_prereq'} = \@opamgt_sdk_prereq; diff --git a/CommonInstall/comp_ff_of_prereq_RHEL73.pl b/CommonInstall/comp_ff_of_prereq_RHEL73.pl new file mode 100644 index 0000000..407d31a --- /dev/null +++ b/CommonInstall/comp_ff_of_prereq_RHEL73.pl @@ -0,0 +1,91 @@ +#!/usr/bin/perl +## BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +## END_ICS_COPYRIGHT8 **************************************** +# +## [ICS VERSION STRING: unknown] +#use strict; +##use Term::ANSIColor; +##use Term::ANSIColor qw(:constants); +##use File::Basename; +##use Math::BigInt; +# +## ========================================================================== +# +#Installation Prequisites array for fast fabric +#and of tools component +my @oftools_prereq = ( + "glibc", + "libgcc", + "libibmad", + "libibumad", + "libibverbs", + "libhfi1", + "libstdc++", + "ibacm", +); +$comp_prereq_hash{'oftools_prereq'} = \@oftools_prereq; + +my @fastfabric_prereq = ( + "atlas", + "bash", + "bc", + "expat", + "expect", + "glibc", + "libgcc", + "libibmad", + "libibumad", + "libibverbs", + "libhfi1", + "libstdc++", + "ncurses-libs", + "openssl-libs", + "perl", + "perl-Getopt-Long", + "perl-Socket", + "rdma", + "tcl", + "zlib", +); +$comp_prereq_hash{'fastfabric_prereq'} = \@fastfabric_prereq; + +my @opamgt_sdk_prereq = ( + "bash", + "glibc", + "libgcc", + "libibumad", + "libibumad-devel", + "libibverbs", + "libibverbs-devel", + "libstdc++", + "openssl", + "openssl-devel", + "openssl-libs", +); +$comp_prereq_hash{'opamgt_sdk_prereq'} = \@opamgt_sdk_prereq; diff --git a/CommonInstall/comp_ff_of_prereq_RHEL73.pl.base b/CommonInstall/comp_ff_of_prereq_RHEL73.pl.base new file mode 100644 index 0000000..407d31a --- /dev/null +++ b/CommonInstall/comp_ff_of_prereq_RHEL73.pl.base @@ -0,0 +1,91 @@ +#!/usr/bin/perl +## BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +## END_ICS_COPYRIGHT8 **************************************** +# +## [ICS VERSION STRING: unknown] +#use strict; +##use Term::ANSIColor; +##use Term::ANSIColor qw(:constants); +##use File::Basename; +##use Math::BigInt; +# +## ========================================================================== +# +#Installation Prequisites array for fast fabric +#and of tools component +my @oftools_prereq = ( + "glibc", + "libgcc", + "libibmad", + "libibumad", + "libibverbs", + "libhfi1", + "libstdc++", + "ibacm", +); +$comp_prereq_hash{'oftools_prereq'} = \@oftools_prereq; + +my @fastfabric_prereq = ( + "atlas", + "bash", + "bc", + "expat", + "expect", + "glibc", + "libgcc", + "libibmad", + "libibumad", + "libibverbs", + "libhfi1", + "libstdc++", + "ncurses-libs", + "openssl-libs", + "perl", + "perl-Getopt-Long", + "perl-Socket", + "rdma", + "tcl", + "zlib", +); +$comp_prereq_hash{'fastfabric_prereq'} = \@fastfabric_prereq; + +my @opamgt_sdk_prereq = ( + "bash", + "glibc", + "libgcc", + "libibumad", + "libibumad-devel", + "libibverbs", + "libibverbs-devel", + "libstdc++", + "openssl", + "openssl-devel", + "openssl-libs", +); +$comp_prereq_hash{'opamgt_sdk_prereq'} = \@opamgt_sdk_prereq; diff --git a/CommonInstall/comp_ff_of_prereq_RHEL74.pl b/CommonInstall/comp_ff_of_prereq_RHEL74.pl new file mode 100644 index 0000000..c45e66c --- /dev/null +++ b/CommonInstall/comp_ff_of_prereq_RHEL74.pl @@ -0,0 +1,87 @@ +#!/usr/bin/perl +## BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +## END_ICS_COPYRIGHT8 **************************************** +# +## [ICS VERSION STRING: unknown] +#use strict; +##use Term::ANSIColor; +##use Term::ANSIColor qw(:constants); +##use File::Basename; +##use Math::BigInt; +# +## ========================================================================== +# +#Installation Prequisites array for fast fabric +#and of tools component +my @oftools_prereq = ( + "glibc", + "libgcc", + "libibumad", + "libibverbs", + "libstdc++", + "ibacm", + "rdma-core", +); +$comp_prereq_hash{'oftools_prereq'} = \@oftools_prereq; + +my @fastfabric_prereq = ( + "atlas", + "bash", + "bc", + "expat", + "expect", + "glibc", + "libgcc", + "libibumad", + "libibverbs", + "libstdc++", + "ncurses-libs", + "openssl-libs", + "perl", + "perl-Getopt-Long", + "perl-Socket", + "rdma-core", + "tcl", + "zlib", +); +$comp_prereq_hash{'fastfabric_prereq'} = \@fastfabric_prereq; + +my @opamgt_sdk_prereq = ( + "bash", + "glibc", + "libgcc", + "libibumad", + "libibverbs", + "libstdc++", + "openssl", + "openssl-devel", + "openssl-libs", + "rdma-core-devel", +); +$comp_prereq_hash{'opamgt_sdk_prereq'} = \@opamgt_sdk_prereq; diff --git a/CommonInstall/comp_ff_of_prereq_RHEL74.pl.base b/CommonInstall/comp_ff_of_prereq_RHEL74.pl.base new file mode 100644 index 0000000..c45e66c --- /dev/null +++ b/CommonInstall/comp_ff_of_prereq_RHEL74.pl.base @@ -0,0 +1,87 @@ +#!/usr/bin/perl +## BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +## END_ICS_COPYRIGHT8 **************************************** +# +## [ICS VERSION STRING: unknown] +#use strict; +##use Term::ANSIColor; +##use Term::ANSIColor qw(:constants); +##use File::Basename; +##use Math::BigInt; +# +## ========================================================================== +# +#Installation Prequisites array for fast fabric +#and of tools component +my @oftools_prereq = ( + "glibc", + "libgcc", + "libibumad", + "libibverbs", + "libstdc++", + "ibacm", + "rdma-core", +); +$comp_prereq_hash{'oftools_prereq'} = \@oftools_prereq; + +my @fastfabric_prereq = ( + "atlas", + "bash", + "bc", + "expat", + "expect", + "glibc", + "libgcc", + "libibumad", + "libibverbs", + "libstdc++", + "ncurses-libs", + "openssl-libs", + "perl", + "perl-Getopt-Long", + "perl-Socket", + "rdma-core", + "tcl", + "zlib", +); +$comp_prereq_hash{'fastfabric_prereq'} = \@fastfabric_prereq; + +my @opamgt_sdk_prereq = ( + "bash", + "glibc", + "libgcc", + "libibumad", + "libibverbs", + "libstdc++", + "openssl", + "openssl-devel", + "openssl-libs", + "rdma-core-devel", +); +$comp_prereq_hash{'opamgt_sdk_prereq'} = \@opamgt_sdk_prereq; diff --git a/CommonInstall/comp_ff_of_prereq_RHEL75.pl b/CommonInstall/comp_ff_of_prereq_RHEL75.pl new file mode 100644 index 0000000..591bbff --- /dev/null +++ b/CommonInstall/comp_ff_of_prereq_RHEL75.pl @@ -0,0 +1,87 @@ +#!/usr/bin/perl +## BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +## END_ICS_COPYRIGHT8 **************************************** +# +## [ICS VERSION STRING: unknown] +#use strict; +##use Term::ANSIColor; +##use Term::ANSIColor qw(:constants); +##use File::Basename; +##use Math::BigInt; +# +## ========================================================================== +# +#Installation Prequisites array for fast fabric +#and of tools component +my @oftools_prereq = ( + "glibc", + "libgcc", + "libibumad", + "libibverbs", + "libstdc++", + "ibacm", + "rdma-core", +); +$comp_prereq_hash{'oftools_prereq'} = \@oftools_prereq; + +my @fastfabric_prereq = ( + "atlas", + "bash", + "bc", + "expat", + "expect", + "glibc", + "libgcc", + "libibumad", + "libibverbs", + "libstdc++", + "ncurses-libs", + "openssl-libs", + "perl", + "perl-Getopt-Long", + "perl-Socket", + "rdma-core", + "tcl", + "zlib", +); +$comp_prereq_hash{'fastfabric_prereq'} = \@fastfabric_prereq; + +my @opamgt_sdk_prereq = ( + "bash", + "glibc", + "libgcc", + "libibumad", + "libibverbs", + "libstdc++", + "openssl", + "openssl-devel", + "openssl-libs", + "rdma-core-devel", +); +$comp_prereq_hash{'opamgt_sdk_prereq'} = \@opamgt_sdk_prereq; diff --git a/CommonInstall/comp_ff_of_prereq_RHEL75.pl.base b/CommonInstall/comp_ff_of_prereq_RHEL75.pl.base new file mode 100644 index 0000000..591bbff --- /dev/null +++ b/CommonInstall/comp_ff_of_prereq_RHEL75.pl.base @@ -0,0 +1,87 @@ +#!/usr/bin/perl +## BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +## END_ICS_COPYRIGHT8 **************************************** +# +## [ICS VERSION STRING: unknown] +#use strict; +##use Term::ANSIColor; +##use Term::ANSIColor qw(:constants); +##use File::Basename; +##use Math::BigInt; +# +## ========================================================================== +# +#Installation Prequisites array for fast fabric +#and of tools component +my @oftools_prereq = ( + "glibc", + "libgcc", + "libibumad", + "libibverbs", + "libstdc++", + "ibacm", + "rdma-core", +); +$comp_prereq_hash{'oftools_prereq'} = \@oftools_prereq; + +my @fastfabric_prereq = ( + "atlas", + "bash", + "bc", + "expat", + "expect", + "glibc", + "libgcc", + "libibumad", + "libibverbs", + "libstdc++", + "ncurses-libs", + "openssl-libs", + "perl", + "perl-Getopt-Long", + "perl-Socket", + "rdma-core", + "tcl", + "zlib", +); +$comp_prereq_hash{'fastfabric_prereq'} = \@fastfabric_prereq; + +my @opamgt_sdk_prereq = ( + "bash", + "glibc", + "libgcc", + "libibumad", + "libibverbs", + "libstdc++", + "openssl", + "openssl-devel", + "openssl-libs", + "rdma-core-devel", +); +$comp_prereq_hash{'opamgt_sdk_prereq'} = \@opamgt_sdk_prereq; diff --git a/CommonInstall/comp_ff_of_prereq_RHEL76.pl b/CommonInstall/comp_ff_of_prereq_RHEL76.pl new file mode 100644 index 0000000..af44df6 --- /dev/null +++ b/CommonInstall/comp_ff_of_prereq_RHEL76.pl @@ -0,0 +1,87 @@ +#!/usr/bin/perl +## BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2018, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +## END_ICS_COPYRIGHT8 **************************************** +# +## [ICS VERSION STRING: unknown] +#use strict; +##use Term::ANSIColor; +##use Term::ANSIColor qw(:constants); +##use File::Basename; +##use Math::BigInt; +# +## ========================================================================== +# +#Installation Prequisites array for fast fabric +#and of tools component +my @oftools_prereq = ( + "glibc", + "libgcc", + "libibumad", + "libibverbs", + "libstdc++", + "ibacm", + "rdma-core", +); +$comp_prereq_hash{'oftools_prereq'} = \@oftools_prereq; + +my @fastfabric_prereq = ( + "atlas", + "bash", + "bc", + "expat", + "expect", + "glibc", + "libgcc", + "libibumad", + "libibverbs", + "libstdc++", + "ncurses-libs", + "openssl-libs", + "perl", + "perl-Getopt-Long", + "perl-Socket", + "rdma-core", + "tcl", + "zlib", +); +$comp_prereq_hash{'fastfabric_prereq'} = \@fastfabric_prereq; + +my @opamgt_sdk_prereq = ( + "bash", + "glibc", + "libgcc", + "libibumad", + "libibverbs", + "libstdc++", + "openssl", + "openssl-devel", + "openssl-libs", + "rdma-core-devel", +); +$comp_prereq_hash{'opamgt_sdk_prereq'} = \@opamgt_sdk_prereq; diff --git a/CommonInstall/comp_ff_of_prereq_RHEL76.pl.base b/CommonInstall/comp_ff_of_prereq_RHEL76.pl.base new file mode 100644 index 0000000..af44df6 --- /dev/null +++ b/CommonInstall/comp_ff_of_prereq_RHEL76.pl.base @@ -0,0 +1,87 @@ +#!/usr/bin/perl +## BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2018, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +## END_ICS_COPYRIGHT8 **************************************** +# +## [ICS VERSION STRING: unknown] +#use strict; +##use Term::ANSIColor; +##use Term::ANSIColor qw(:constants); +##use File::Basename; +##use Math::BigInt; +# +## ========================================================================== +# +#Installation Prequisites array for fast fabric +#and of tools component +my @oftools_prereq = ( + "glibc", + "libgcc", + "libibumad", + "libibverbs", + "libstdc++", + "ibacm", + "rdma-core", +); +$comp_prereq_hash{'oftools_prereq'} = \@oftools_prereq; + +my @fastfabric_prereq = ( + "atlas", + "bash", + "bc", + "expat", + "expect", + "glibc", + "libgcc", + "libibumad", + "libibverbs", + "libstdc++", + "ncurses-libs", + "openssl-libs", + "perl", + "perl-Getopt-Long", + "perl-Socket", + "rdma-core", + "tcl", + "zlib", +); +$comp_prereq_hash{'fastfabric_prereq'} = \@fastfabric_prereq; + +my @opamgt_sdk_prereq = ( + "bash", + "glibc", + "libgcc", + "libibumad", + "libibverbs", + "libstdc++", + "openssl", + "openssl-devel", + "openssl-libs", + "rdma-core-devel", +); +$comp_prereq_hash{'opamgt_sdk_prereq'} = \@opamgt_sdk_prereq; diff --git a/CommonInstall/comp_ff_of_prereq_RHEL77.pl b/CommonInstall/comp_ff_of_prereq_RHEL77.pl new file mode 100644 index 0000000..af44df6 --- /dev/null +++ b/CommonInstall/comp_ff_of_prereq_RHEL77.pl @@ -0,0 +1,87 @@ +#!/usr/bin/perl +## BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2018, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +## END_ICS_COPYRIGHT8 **************************************** +# +## [ICS VERSION STRING: unknown] +#use strict; +##use Term::ANSIColor; +##use Term::ANSIColor qw(:constants); +##use File::Basename; +##use Math::BigInt; +# +## ========================================================================== +# +#Installation Prequisites array for fast fabric +#and of tools component +my @oftools_prereq = ( + "glibc", + "libgcc", + "libibumad", + "libibverbs", + "libstdc++", + "ibacm", + "rdma-core", +); +$comp_prereq_hash{'oftools_prereq'} = \@oftools_prereq; + +my @fastfabric_prereq = ( + "atlas", + "bash", + "bc", + "expat", + "expect", + "glibc", + "libgcc", + "libibumad", + "libibverbs", + "libstdc++", + "ncurses-libs", + "openssl-libs", + "perl", + "perl-Getopt-Long", + "perl-Socket", + "rdma-core", + "tcl", + "zlib", +); +$comp_prereq_hash{'fastfabric_prereq'} = \@fastfabric_prereq; + +my @opamgt_sdk_prereq = ( + "bash", + "glibc", + "libgcc", + "libibumad", + "libibverbs", + "libstdc++", + "openssl", + "openssl-devel", + "openssl-libs", + "rdma-core-devel", +); +$comp_prereq_hash{'opamgt_sdk_prereq'} = \@opamgt_sdk_prereq; diff --git a/CommonInstall/comp_ff_of_prereq_RHEL77.pl.base b/CommonInstall/comp_ff_of_prereq_RHEL77.pl.base new file mode 100644 index 0000000..af44df6 --- /dev/null +++ b/CommonInstall/comp_ff_of_prereq_RHEL77.pl.base @@ -0,0 +1,87 @@ +#!/usr/bin/perl +## BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2018, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +## END_ICS_COPYRIGHT8 **************************************** +# +## [ICS VERSION STRING: unknown] +#use strict; +##use Term::ANSIColor; +##use Term::ANSIColor qw(:constants); +##use File::Basename; +##use Math::BigInt; +# +## ========================================================================== +# +#Installation Prequisites array for fast fabric +#and of tools component +my @oftools_prereq = ( + "glibc", + "libgcc", + "libibumad", + "libibverbs", + "libstdc++", + "ibacm", + "rdma-core", +); +$comp_prereq_hash{'oftools_prereq'} = \@oftools_prereq; + +my @fastfabric_prereq = ( + "atlas", + "bash", + "bc", + "expat", + "expect", + "glibc", + "libgcc", + "libibumad", + "libibverbs", + "libstdc++", + "ncurses-libs", + "openssl-libs", + "perl", + "perl-Getopt-Long", + "perl-Socket", + "rdma-core", + "tcl", + "zlib", +); +$comp_prereq_hash{'fastfabric_prereq'} = \@fastfabric_prereq; + +my @opamgt_sdk_prereq = ( + "bash", + "glibc", + "libgcc", + "libibumad", + "libibverbs", + "libstdc++", + "openssl", + "openssl-devel", + "openssl-libs", + "rdma-core-devel", +); +$comp_prereq_hash{'opamgt_sdk_prereq'} = \@opamgt_sdk_prereq; diff --git a/CommonInstall/comp_ff_of_prereq_RHEL8.pl b/CommonInstall/comp_ff_of_prereq_RHEL8.pl new file mode 100644 index 0000000..ee2fa78 --- /dev/null +++ b/CommonInstall/comp_ff_of_prereq_RHEL8.pl @@ -0,0 +1,87 @@ +#!/usr/bin/perl +## BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2019, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +## END_ICS_COPYRIGHT8 **************************************** +# +## [ICS VERSION STRING: unknown] +#use strict; +##use Term::ANSIColor; +##use Term::ANSIColor qw(:constants); +##use File::Basename; +##use Math::BigInt; +# +## ========================================================================== +# +#Installation Prequisites array for fast fabric +#and of tools component +my @oftools_prereq = ( + "glibc", + "libgcc", + "libibumad", + "libibverbs", + "libstdc++", + "ibacm", + "rdma-core", +); +$comp_prereq_hash{'oftools_prereq'} = \@oftools_prereq; + +my @fastfabric_prereq = ( + "atlas", + "bash", + "bc", + "expat", + "expect", + "glibc", + "libgcc", + "libibumad", + "libibverbs", + "libstdc++", + "ncurses-libs", + "openssl-libs", + "perl", + "perl-Getopt-Long", + "perl-Socket", + "rdma-core", + "tcl", + "zlib", +); +$comp_prereq_hash{'fastfabric_prereq'} = \@fastfabric_prereq; + +my @opamgt_sdk_prereq = ( + "bash", + "glibc", + "libgcc", + "libibumad", + "libibverbs", + "libstdc++", + "openssl", + "openssl-devel", + "openssl-libs", + "rdma-core-devel", +); +$comp_prereq_hash{'opamgt_sdk_prereq'} = \@opamgt_sdk_prereq; diff --git a/CommonInstall/comp_ff_of_prereq_RHEL8.pl.base b/CommonInstall/comp_ff_of_prereq_RHEL8.pl.base new file mode 100644 index 0000000..ee2fa78 --- /dev/null +++ b/CommonInstall/comp_ff_of_prereq_RHEL8.pl.base @@ -0,0 +1,87 @@ +#!/usr/bin/perl +## BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2019, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +## END_ICS_COPYRIGHT8 **************************************** +# +## [ICS VERSION STRING: unknown] +#use strict; +##use Term::ANSIColor; +##use Term::ANSIColor qw(:constants); +##use File::Basename; +##use Math::BigInt; +# +## ========================================================================== +# +#Installation Prequisites array for fast fabric +#and of tools component +my @oftools_prereq = ( + "glibc", + "libgcc", + "libibumad", + "libibverbs", + "libstdc++", + "ibacm", + "rdma-core", +); +$comp_prereq_hash{'oftools_prereq'} = \@oftools_prereq; + +my @fastfabric_prereq = ( + "atlas", + "bash", + "bc", + "expat", + "expect", + "glibc", + "libgcc", + "libibumad", + "libibverbs", + "libstdc++", + "ncurses-libs", + "openssl-libs", + "perl", + "perl-Getopt-Long", + "perl-Socket", + "rdma-core", + "tcl", + "zlib", +); +$comp_prereq_hash{'fastfabric_prereq'} = \@fastfabric_prereq; + +my @opamgt_sdk_prereq = ( + "bash", + "glibc", + "libgcc", + "libibumad", + "libibverbs", + "libstdc++", + "openssl", + "openssl-devel", + "openssl-libs", + "rdma-core-devel", +); +$comp_prereq_hash{'opamgt_sdk_prereq'} = \@opamgt_sdk_prereq; diff --git a/CommonInstall/comp_ff_of_prereq_RHEL81.pl b/CommonInstall/comp_ff_of_prereq_RHEL81.pl new file mode 100644 index 0000000..ee2fa78 --- /dev/null +++ b/CommonInstall/comp_ff_of_prereq_RHEL81.pl @@ -0,0 +1,87 @@ +#!/usr/bin/perl +## BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2019, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +## END_ICS_COPYRIGHT8 **************************************** +# +## [ICS VERSION STRING: unknown] +#use strict; +##use Term::ANSIColor; +##use Term::ANSIColor qw(:constants); +##use File::Basename; +##use Math::BigInt; +# +## ========================================================================== +# +#Installation Prequisites array for fast fabric +#and of tools component +my @oftools_prereq = ( + "glibc", + "libgcc", + "libibumad", + "libibverbs", + "libstdc++", + "ibacm", + "rdma-core", +); +$comp_prereq_hash{'oftools_prereq'} = \@oftools_prereq; + +my @fastfabric_prereq = ( + "atlas", + "bash", + "bc", + "expat", + "expect", + "glibc", + "libgcc", + "libibumad", + "libibverbs", + "libstdc++", + "ncurses-libs", + "openssl-libs", + "perl", + "perl-Getopt-Long", + "perl-Socket", + "rdma-core", + "tcl", + "zlib", +); +$comp_prereq_hash{'fastfabric_prereq'} = \@fastfabric_prereq; + +my @opamgt_sdk_prereq = ( + "bash", + "glibc", + "libgcc", + "libibumad", + "libibverbs", + "libstdc++", + "openssl", + "openssl-devel", + "openssl-libs", + "rdma-core-devel", +); +$comp_prereq_hash{'opamgt_sdk_prereq'} = \@opamgt_sdk_prereq; diff --git a/CommonInstall/comp_ff_of_prereq_RHEL81.pl.base b/CommonInstall/comp_ff_of_prereq_RHEL81.pl.base new file mode 100644 index 0000000..ee2fa78 --- /dev/null +++ b/CommonInstall/comp_ff_of_prereq_RHEL81.pl.base @@ -0,0 +1,87 @@ +#!/usr/bin/perl +## BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2019, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +## END_ICS_COPYRIGHT8 **************************************** +# +## [ICS VERSION STRING: unknown] +#use strict; +##use Term::ANSIColor; +##use Term::ANSIColor qw(:constants); +##use File::Basename; +##use Math::BigInt; +# +## ========================================================================== +# +#Installation Prequisites array for fast fabric +#and of tools component +my @oftools_prereq = ( + "glibc", + "libgcc", + "libibumad", + "libibverbs", + "libstdc++", + "ibacm", + "rdma-core", +); +$comp_prereq_hash{'oftools_prereq'} = \@oftools_prereq; + +my @fastfabric_prereq = ( + "atlas", + "bash", + "bc", + "expat", + "expect", + "glibc", + "libgcc", + "libibumad", + "libibverbs", + "libstdc++", + "ncurses-libs", + "openssl-libs", + "perl", + "perl-Getopt-Long", + "perl-Socket", + "rdma-core", + "tcl", + "zlib", +); +$comp_prereq_hash{'fastfabric_prereq'} = \@fastfabric_prereq; + +my @opamgt_sdk_prereq = ( + "bash", + "glibc", + "libgcc", + "libibumad", + "libibverbs", + "libstdc++", + "openssl", + "openssl-devel", + "openssl-libs", + "rdma-core-devel", +); +$comp_prereq_hash{'opamgt_sdk_prereq'} = \@opamgt_sdk_prereq; diff --git a/CommonInstall/comp_ff_of_prereq_SLES122.pl b/CommonInstall/comp_ff_of_prereq_SLES122.pl new file mode 100644 index 0000000..630b16c --- /dev/null +++ b/CommonInstall/comp_ff_of_prereq_SLES122.pl @@ -0,0 +1,89 @@ +#!/usr/bin/perl +## BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +## END_ICS_COPYRIGHT8 **************************************** +# +## [ICS VERSION STRING: unknown] +#use strict; +##use Term::ANSIColor; +##use Term::ANSIColor qw(:constants); +##use File::Basename; +##use Math::BigInt; +# +## ========================================================================== +# +#Installation Prequisites array for fast fabric +#and of tools component + +my @oftools_prereq = ( + "glibc", + "libgcc_s1", + "libibmad5", + "libibumad3", + "libibverbs1", + "libhfi1verbs-rdmav2 ", + "libstdc++6", + "ibacm", +); +$comp_prereq_hash{'oftools_prereq'} = \@oftools_prereq; + +my @fastfabric_prereq = ( + "glibc", + "bash", + "expect", + "perl-base", + "tcl", + "libexpat1", + "libgcc_s1", + "libibmad5", + "libibumad3", + "libibverbs1", + "libhfi1verbs-rdmav2", + "libncurses5", + "libopenssl1_0_0", + "libstdc++6", + "libz1", + "bc", + "rdma", +); +$comp_prereq_hash{'fastfabric_prereq'} = \@fastfabric_prereq; + +my @opamgt_sdk_prereq = ( + "bash", + "glibc", + "libgcc_s1", + "libibumad-devel", + "libibumad3", + "libibverbs-devel", + "libibverbs1", + "libopenssl-devel", + "libopenssl1_0_0", + "libstdc++6", + "openssl", +); +$comp_prereq_hash{'opamgt_sdk_prereq'} = \@opamgt_sdk_prereq; diff --git a/CommonInstall/comp_ff_of_prereq_SLES122.pl.base b/CommonInstall/comp_ff_of_prereq_SLES122.pl.base new file mode 100644 index 0000000..630b16c --- /dev/null +++ b/CommonInstall/comp_ff_of_prereq_SLES122.pl.base @@ -0,0 +1,89 @@ +#!/usr/bin/perl +## BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +## END_ICS_COPYRIGHT8 **************************************** +# +## [ICS VERSION STRING: unknown] +#use strict; +##use Term::ANSIColor; +##use Term::ANSIColor qw(:constants); +##use File::Basename; +##use Math::BigInt; +# +## ========================================================================== +# +#Installation Prequisites array for fast fabric +#and of tools component + +my @oftools_prereq = ( + "glibc", + "libgcc_s1", + "libibmad5", + "libibumad3", + "libibverbs1", + "libhfi1verbs-rdmav2 ", + "libstdc++6", + "ibacm", +); +$comp_prereq_hash{'oftools_prereq'} = \@oftools_prereq; + +my @fastfabric_prereq = ( + "glibc", + "bash", + "expect", + "perl-base", + "tcl", + "libexpat1", + "libgcc_s1", + "libibmad5", + "libibumad3", + "libibverbs1", + "libhfi1verbs-rdmav2", + "libncurses5", + "libopenssl1_0_0", + "libstdc++6", + "libz1", + "bc", + "rdma", +); +$comp_prereq_hash{'fastfabric_prereq'} = \@fastfabric_prereq; + +my @opamgt_sdk_prereq = ( + "bash", + "glibc", + "libgcc_s1", + "libibumad-devel", + "libibumad3", + "libibverbs-devel", + "libibverbs1", + "libopenssl-devel", + "libopenssl1_0_0", + "libstdc++6", + "openssl", +); +$comp_prereq_hash{'opamgt_sdk_prereq'} = \@opamgt_sdk_prereq; diff --git a/CommonInstall/comp_ff_of_prereq_SLES123.pl b/CommonInstall/comp_ff_of_prereq_SLES123.pl new file mode 100644 index 0000000..0fc926d --- /dev/null +++ b/CommonInstall/comp_ff_of_prereq_SLES123.pl @@ -0,0 +1,88 @@ +#!/usr/bin/perl +## BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +## END_ICS_COPYRIGHT8 **************************************** +# +## [ICS VERSION STRING: unknown] +#use strict; +##use Term::ANSIColor; +##use Term::ANSIColor qw(:constants); +##use File::Basename; +##use Math::BigInt; +# +## ========================================================================== +# +#Installation Prequisites array for fast fabric +#and of tools component + +my @oftools_prereq = ( + "glibc", + "libgcc_s1", + "libibmad5", + "libibumad3", + "libibverbs1", + "libstdc++6", + "ibacm", +); +$comp_prereq_hash{'oftools_prereq'} = \@oftools_prereq; + +my @fastfabric_prereq = ( + "glibc", + "bash", + "expect", + "perl-base", + "tcl", + "libexpat1", + "libgcc_s1", + "libibmad5", + "libibumad3", + "libibverbs1", + "libncurses5", + "libopenssl1_0_0", + "libstdc++6", + "libz1", + "bc", + "rdma-core", + "rdma-ndd", +); +$comp_prereq_hash{'fastfabric_prereq'} = \@fastfabric_prereq; + +my @opamgt_sdk_prereq = ( + "bash", + "glibc", + "libgcc_s1", + "libibumad3", + "libibverbs1", + "libopenssl-devel", + "libopenssl1_0_0", + "libstdc++6", + "openssl", + "rdma-core-devel", + "rdma-ndd", +); +$comp_prereq_hash{'opamgt_sdk_prereq'} = \@opamgt_sdk_prereq; diff --git a/CommonInstall/comp_ff_of_prereq_SLES123.pl.base b/CommonInstall/comp_ff_of_prereq_SLES123.pl.base new file mode 100644 index 0000000..0fc926d --- /dev/null +++ b/CommonInstall/comp_ff_of_prereq_SLES123.pl.base @@ -0,0 +1,88 @@ +#!/usr/bin/perl +## BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +## END_ICS_COPYRIGHT8 **************************************** +# +## [ICS VERSION STRING: unknown] +#use strict; +##use Term::ANSIColor; +##use Term::ANSIColor qw(:constants); +##use File::Basename; +##use Math::BigInt; +# +## ========================================================================== +# +#Installation Prequisites array for fast fabric +#and of tools component + +my @oftools_prereq = ( + "glibc", + "libgcc_s1", + "libibmad5", + "libibumad3", + "libibverbs1", + "libstdc++6", + "ibacm", +); +$comp_prereq_hash{'oftools_prereq'} = \@oftools_prereq; + +my @fastfabric_prereq = ( + "glibc", + "bash", + "expect", + "perl-base", + "tcl", + "libexpat1", + "libgcc_s1", + "libibmad5", + "libibumad3", + "libibverbs1", + "libncurses5", + "libopenssl1_0_0", + "libstdc++6", + "libz1", + "bc", + "rdma-core", + "rdma-ndd", +); +$comp_prereq_hash{'fastfabric_prereq'} = \@fastfabric_prereq; + +my @opamgt_sdk_prereq = ( + "bash", + "glibc", + "libgcc_s1", + "libibumad3", + "libibverbs1", + "libopenssl-devel", + "libopenssl1_0_0", + "libstdc++6", + "openssl", + "rdma-core-devel", + "rdma-ndd", +); +$comp_prereq_hash{'opamgt_sdk_prereq'} = \@opamgt_sdk_prereq; diff --git a/CommonInstall/comp_ff_of_prereq_SLES124.pl b/CommonInstall/comp_ff_of_prereq_SLES124.pl new file mode 100644 index 0000000..0291334 --- /dev/null +++ b/CommonInstall/comp_ff_of_prereq_SLES124.pl @@ -0,0 +1,88 @@ +#!/usr/bin/perl +## BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2018, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +## END_ICS_COPYRIGHT8 **************************************** +# +## [ICS VERSION STRING: unknown] +#use strict; +##use Term::ANSIColor; +##use Term::ANSIColor qw(:constants); +##use File::Basename; +##use Math::BigInt; +# +## ========================================================================== +# +#Installation Prequisites array for fast fabric +#and of tools component + +my @oftools_prereq = ( + "glibc", + "libgcc_s1", + "libibmad5", + "libibumad3", + "libibverbs1", + "libstdc++6", + "ibacm", +); +$comp_prereq_hash{'oftools_prereq'} = \@oftools_prereq; + +my @fastfabric_prereq = ( + "glibc", + "bash", + "expect", + "perl-base", + "tcl", + "libexpat1", + "libgcc_s1", + "libibmad5", + "libibumad3", + "libibverbs1", + "libncurses5", + "libopenssl1_0_0", + "libstdc++6", + "libz1", + "bc", + "rdma-core", + "rdma-ndd", +); +$comp_prereq_hash{'fastfabric_prereq'} = \@fastfabric_prereq; + +my @opamgt_sdk_prereq = ( + "bash", + "glibc", + "libgcc_s1", + "libibumad3", + "libibverbs1", + "libopenssl-devel", + "libopenssl1_0_0", + "libstdc++6", + "openssl", + "rdma-core-devel", + "rdma-ndd", +); +$comp_prereq_hash{'opamgt_sdk_prereq'} = \@opamgt_sdk_prereq; diff --git a/CommonInstall/comp_ff_of_prereq_SLES124.pl.base b/CommonInstall/comp_ff_of_prereq_SLES124.pl.base new file mode 100644 index 0000000..0291334 --- /dev/null +++ b/CommonInstall/comp_ff_of_prereq_SLES124.pl.base @@ -0,0 +1,88 @@ +#!/usr/bin/perl +## BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2018, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +## END_ICS_COPYRIGHT8 **************************************** +# +## [ICS VERSION STRING: unknown] +#use strict; +##use Term::ANSIColor; +##use Term::ANSIColor qw(:constants); +##use File::Basename; +##use Math::BigInt; +# +## ========================================================================== +# +#Installation Prequisites array for fast fabric +#and of tools component + +my @oftools_prereq = ( + "glibc", + "libgcc_s1", + "libibmad5", + "libibumad3", + "libibverbs1", + "libstdc++6", + "ibacm", +); +$comp_prereq_hash{'oftools_prereq'} = \@oftools_prereq; + +my @fastfabric_prereq = ( + "glibc", + "bash", + "expect", + "perl-base", + "tcl", + "libexpat1", + "libgcc_s1", + "libibmad5", + "libibumad3", + "libibverbs1", + "libncurses5", + "libopenssl1_0_0", + "libstdc++6", + "libz1", + "bc", + "rdma-core", + "rdma-ndd", +); +$comp_prereq_hash{'fastfabric_prereq'} = \@fastfabric_prereq; + +my @opamgt_sdk_prereq = ( + "bash", + "glibc", + "libgcc_s1", + "libibumad3", + "libibverbs1", + "libopenssl-devel", + "libopenssl1_0_0", + "libstdc++6", + "openssl", + "rdma-core-devel", + "rdma-ndd", +); +$comp_prereq_hash{'opamgt_sdk_prereq'} = \@opamgt_sdk_prereq; diff --git a/CommonInstall/comp_ff_of_prereq_SLES125.pl b/CommonInstall/comp_ff_of_prereq_SLES125.pl new file mode 100644 index 0000000..0291334 --- /dev/null +++ b/CommonInstall/comp_ff_of_prereq_SLES125.pl @@ -0,0 +1,88 @@ +#!/usr/bin/perl +## BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2018, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +## END_ICS_COPYRIGHT8 **************************************** +# +## [ICS VERSION STRING: unknown] +#use strict; +##use Term::ANSIColor; +##use Term::ANSIColor qw(:constants); +##use File::Basename; +##use Math::BigInt; +# +## ========================================================================== +# +#Installation Prequisites array for fast fabric +#and of tools component + +my @oftools_prereq = ( + "glibc", + "libgcc_s1", + "libibmad5", + "libibumad3", + "libibverbs1", + "libstdc++6", + "ibacm", +); +$comp_prereq_hash{'oftools_prereq'} = \@oftools_prereq; + +my @fastfabric_prereq = ( + "glibc", + "bash", + "expect", + "perl-base", + "tcl", + "libexpat1", + "libgcc_s1", + "libibmad5", + "libibumad3", + "libibverbs1", + "libncurses5", + "libopenssl1_0_0", + "libstdc++6", + "libz1", + "bc", + "rdma-core", + "rdma-ndd", +); +$comp_prereq_hash{'fastfabric_prereq'} = \@fastfabric_prereq; + +my @opamgt_sdk_prereq = ( + "bash", + "glibc", + "libgcc_s1", + "libibumad3", + "libibverbs1", + "libopenssl-devel", + "libopenssl1_0_0", + "libstdc++6", + "openssl", + "rdma-core-devel", + "rdma-ndd", +); +$comp_prereq_hash{'opamgt_sdk_prereq'} = \@opamgt_sdk_prereq; diff --git a/CommonInstall/comp_ff_of_prereq_SLES125.pl.base b/CommonInstall/comp_ff_of_prereq_SLES125.pl.base new file mode 100644 index 0000000..0291334 --- /dev/null +++ b/CommonInstall/comp_ff_of_prereq_SLES125.pl.base @@ -0,0 +1,88 @@ +#!/usr/bin/perl +## BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2018, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +## END_ICS_COPYRIGHT8 **************************************** +# +## [ICS VERSION STRING: unknown] +#use strict; +##use Term::ANSIColor; +##use Term::ANSIColor qw(:constants); +##use File::Basename; +##use Math::BigInt; +# +## ========================================================================== +# +#Installation Prequisites array for fast fabric +#and of tools component + +my @oftools_prereq = ( + "glibc", + "libgcc_s1", + "libibmad5", + "libibumad3", + "libibverbs1", + "libstdc++6", + "ibacm", +); +$comp_prereq_hash{'oftools_prereq'} = \@oftools_prereq; + +my @fastfabric_prereq = ( + "glibc", + "bash", + "expect", + "perl-base", + "tcl", + "libexpat1", + "libgcc_s1", + "libibmad5", + "libibumad3", + "libibverbs1", + "libncurses5", + "libopenssl1_0_0", + "libstdc++6", + "libz1", + "bc", + "rdma-core", + "rdma-ndd", +); +$comp_prereq_hash{'fastfabric_prereq'} = \@fastfabric_prereq; + +my @opamgt_sdk_prereq = ( + "bash", + "glibc", + "libgcc_s1", + "libibumad3", + "libibverbs1", + "libopenssl-devel", + "libopenssl1_0_0", + "libstdc++6", + "openssl", + "rdma-core-devel", + "rdma-ndd", +); +$comp_prereq_hash{'opamgt_sdk_prereq'} = \@opamgt_sdk_prereq; diff --git a/CommonInstall/comp_ff_of_prereq_SLES15.pl b/CommonInstall/comp_ff_of_prereq_SLES15.pl new file mode 100644 index 0000000..743ac94 --- /dev/null +++ b/CommonInstall/comp_ff_of_prereq_SLES15.pl @@ -0,0 +1,90 @@ +#!/usr/bin/perl +## BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +## END_ICS_COPYRIGHT8 **************************************** +# +## [ICS VERSION STRING: unknown] +#use strict; +##use Term::ANSIColor; +##use Term::ANSIColor qw(:constants); +##use File::Basename; +##use Math::BigInt; +# +## ========================================================================== +# +#Installation Prequisites array for fast fabric +#and of tools component + +my @oftools_prereq = ( + "glibc", + "libgcc_s1", + "libibmad5", + "libibumad3", + "libibverbs1", + "libstdc++6", + "ibacm", +); +$comp_prereq_hash{'oftools_prereq'} = \@oftools_prereq; + +my @fastfabric_prereq = ( + "glibc", + "bash", + "expect", + "perl-base", + "tcl", + "libexpat1", + "libgcc_s1", + "libibmad5", + "libibumad3", + "libibverbs1", + "libncurses6", + "libopenssl1_1", + "libstdc++6", + "libz1", + "bc", + "rdma-core", + "rdma-ndd", + "qperf", + "perftest", +); +$comp_prereq_hash{'fastfabric_prereq'} = \@fastfabric_prereq; + +my @opamgt_sdk_prereq = ( + "bash", + "glibc", + "libgcc_s1", + "libibumad3", + "libibverbs1", + "libopenssl-devel", + "libopenssl1_1", + "libstdc++6", + "openssl", + "rdma-core-devel", + "rdma-ndd", +); +$comp_prereq_hash{'opamgt_sdk_prereq'} = \@opamgt_sdk_prereq; diff --git a/CommonInstall/comp_ff_of_prereq_SLES15.pl.base b/CommonInstall/comp_ff_of_prereq_SLES15.pl.base new file mode 100644 index 0000000..743ac94 --- /dev/null +++ b/CommonInstall/comp_ff_of_prereq_SLES15.pl.base @@ -0,0 +1,90 @@ +#!/usr/bin/perl +## BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +## END_ICS_COPYRIGHT8 **************************************** +# +## [ICS VERSION STRING: unknown] +#use strict; +##use Term::ANSIColor; +##use Term::ANSIColor qw(:constants); +##use File::Basename; +##use Math::BigInt; +# +## ========================================================================== +# +#Installation Prequisites array for fast fabric +#and of tools component + +my @oftools_prereq = ( + "glibc", + "libgcc_s1", + "libibmad5", + "libibumad3", + "libibverbs1", + "libstdc++6", + "ibacm", +); +$comp_prereq_hash{'oftools_prereq'} = \@oftools_prereq; + +my @fastfabric_prereq = ( + "glibc", + "bash", + "expect", + "perl-base", + "tcl", + "libexpat1", + "libgcc_s1", + "libibmad5", + "libibumad3", + "libibverbs1", + "libncurses6", + "libopenssl1_1", + "libstdc++6", + "libz1", + "bc", + "rdma-core", + "rdma-ndd", + "qperf", + "perftest", +); +$comp_prereq_hash{'fastfabric_prereq'} = \@fastfabric_prereq; + +my @opamgt_sdk_prereq = ( + "bash", + "glibc", + "libgcc_s1", + "libibumad3", + "libibverbs1", + "libopenssl-devel", + "libopenssl1_1", + "libstdc++6", + "openssl", + "rdma-core-devel", + "rdma-ndd", +); +$comp_prereq_hash{'opamgt_sdk_prereq'} = \@opamgt_sdk_prereq; diff --git a/CommonInstall/comp_ff_of_prereq_SLES151.pl b/CommonInstall/comp_ff_of_prereq_SLES151.pl new file mode 100644 index 0000000..d51d011 --- /dev/null +++ b/CommonInstall/comp_ff_of_prereq_SLES151.pl @@ -0,0 +1,90 @@ +#!/usr/bin/perl +## BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2019, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +## END_ICS_COPYRIGHT8 **************************************** +# +## [ICS VERSION STRING: unknown] +#use strict; +##use Term::ANSIColor; +##use Term::ANSIColor qw(:constants); +##use File::Basename; +##use Math::BigInt; +# +## ========================================================================== +# +#Installation Prequisites array for fast fabric +#and of tools component + +my @oftools_prereq = ( + "glibc", + "libgcc_s1", + "libibmad5", + "libibumad3", + "libibverbs1", + "libstdc++6", + "ibacm", +); +$comp_prereq_hash{'oftools_prereq'} = \@oftools_prereq; + +my @fastfabric_prereq = ( + "glibc", + "bash", + "expect", + "perl-base", + "tcl", + "libexpat1", + "libgcc_s1", + "libibmad5", + "libibumad3", + "libibverbs1", + "libncurses6", + "libopenssl1_1", + "libstdc++6", + "libz1", + "bc", + "rdma-core", + "rdma-ndd", + "qperf", + "perftest", +); +$comp_prereq_hash{'fastfabric_prereq'} = \@fastfabric_prereq; + +my @opamgt_sdk_prereq = ( + "bash", + "glibc", + "libgcc_s1", + "libibumad3", + "libibverbs1", + "libopenssl-devel", + "libopenssl1_1", + "libstdc++6", + "openssl", + "rdma-core-devel", + "rdma-ndd", +); +$comp_prereq_hash{'opamgt_sdk_prereq'} = \@opamgt_sdk_prereq; diff --git a/CommonInstall/comp_ff_of_prereq_SLES151.pl.base b/CommonInstall/comp_ff_of_prereq_SLES151.pl.base new file mode 100644 index 0000000..d51d011 --- /dev/null +++ b/CommonInstall/comp_ff_of_prereq_SLES151.pl.base @@ -0,0 +1,90 @@ +#!/usr/bin/perl +## BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2019, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +## END_ICS_COPYRIGHT8 **************************************** +# +## [ICS VERSION STRING: unknown] +#use strict; +##use Term::ANSIColor; +##use Term::ANSIColor qw(:constants); +##use File::Basename; +##use Math::BigInt; +# +## ========================================================================== +# +#Installation Prequisites array for fast fabric +#and of tools component + +my @oftools_prereq = ( + "glibc", + "libgcc_s1", + "libibmad5", + "libibumad3", + "libibverbs1", + "libstdc++6", + "ibacm", +); +$comp_prereq_hash{'oftools_prereq'} = \@oftools_prereq; + +my @fastfabric_prereq = ( + "glibc", + "bash", + "expect", + "perl-base", + "tcl", + "libexpat1", + "libgcc_s1", + "libibmad5", + "libibumad3", + "libibverbs1", + "libncurses6", + "libopenssl1_1", + "libstdc++6", + "libz1", + "bc", + "rdma-core", + "rdma-ndd", + "qperf", + "perftest", +); +$comp_prereq_hash{'fastfabric_prereq'} = \@fastfabric_prereq; + +my @opamgt_sdk_prereq = ( + "bash", + "glibc", + "libgcc_s1", + "libibumad3", + "libibverbs1", + "libopenssl-devel", + "libopenssl1_1", + "libstdc++6", + "openssl", + "rdma-core-devel", + "rdma-ndd", +); +$comp_prereq_hash{'opamgt_sdk_prereq'} = \@opamgt_sdk_prereq; diff --git a/CommonInstall/comp_fm_prereq_RHEL72.pl b/CommonInstall/comp_fm_prereq_RHEL72.pl new file mode 100644 index 0000000..4a10b94 --- /dev/null +++ b/CommonInstall/comp_fm_prereq_RHEL72.pl @@ -0,0 +1,52 @@ +#!/usr/bin/perl +## BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +## END_ICS_COPYRIGHT8 **************************************** +# +## [ICS VERSION STRING: unknown] +#use strict; +##use Term::ANSIColor; +##use Term::ANSIColor qw(:constants); +##use File::Basename; +##use Math::BigInt; +# +## ========================================================================== +# +#Installation Prequisites array for opafm +my @opafm_prereq = ( + "bash", + "expat", + "glibc", + "libibumad", + "libibverbs", + "openssl-libs", + "rdma", + "systemd", + "zlib", +); +$comp_prereq_hash{'opafm_prereq'} = \@opafm_prereq; diff --git a/CommonInstall/comp_fm_prereq_RHEL72.pl.base b/CommonInstall/comp_fm_prereq_RHEL72.pl.base new file mode 100644 index 0000000..4a10b94 --- /dev/null +++ b/CommonInstall/comp_fm_prereq_RHEL72.pl.base @@ -0,0 +1,52 @@ +#!/usr/bin/perl +## BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +## END_ICS_COPYRIGHT8 **************************************** +# +## [ICS VERSION STRING: unknown] +#use strict; +##use Term::ANSIColor; +##use Term::ANSIColor qw(:constants); +##use File::Basename; +##use Math::BigInt; +# +## ========================================================================== +# +#Installation Prequisites array for opafm +my @opafm_prereq = ( + "bash", + "expat", + "glibc", + "libibumad", + "libibverbs", + "openssl-libs", + "rdma", + "systemd", + "zlib", +); +$comp_prereq_hash{'opafm_prereq'} = \@opafm_prereq; diff --git a/CommonInstall/comp_fm_prereq_RHEL73.pl b/CommonInstall/comp_fm_prereq_RHEL73.pl new file mode 100644 index 0000000..7566eaa --- /dev/null +++ b/CommonInstall/comp_fm_prereq_RHEL73.pl @@ -0,0 +1,55 @@ +#!/usr/bin/perl +## BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +## END_ICS_COPYRIGHT8 **************************************** +# +## [ICS VERSION STRING: unknown] +#use strict; +##use Term::ANSIColor; +##use Term::ANSIColor qw(:constants); +##use File::Basename; +##use Math::BigInt; +# +## ========================================================================== +# +#Installation Prequisites array for opafm +my @opafm_prereq = ( + "bash", + "expat", + "glibc", + "libibmad", + "libibumad", + "libibverbs", + "libhfi1", + "openssl-libs", + "rdma", + "systemd", + "zlib", +); +$comp_prereq_hash{'opafm_prereq'} = \@opafm_prereq; + diff --git a/CommonInstall/comp_fm_prereq_RHEL73.pl.base b/CommonInstall/comp_fm_prereq_RHEL73.pl.base new file mode 100644 index 0000000..7566eaa --- /dev/null +++ b/CommonInstall/comp_fm_prereq_RHEL73.pl.base @@ -0,0 +1,55 @@ +#!/usr/bin/perl +## BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +## END_ICS_COPYRIGHT8 **************************************** +# +## [ICS VERSION STRING: unknown] +#use strict; +##use Term::ANSIColor; +##use Term::ANSIColor qw(:constants); +##use File::Basename; +##use Math::BigInt; +# +## ========================================================================== +# +#Installation Prequisites array for opafm +my @opafm_prereq = ( + "bash", + "expat", + "glibc", + "libibmad", + "libibumad", + "libibverbs", + "libhfi1", + "openssl-libs", + "rdma", + "systemd", + "zlib", +); +$comp_prereq_hash{'opafm_prereq'} = \@opafm_prereq; + diff --git a/CommonInstall/comp_fm_prereq_RHEL74.pl b/CommonInstall/comp_fm_prereq_RHEL74.pl new file mode 100644 index 0000000..3c9d252 --- /dev/null +++ b/CommonInstall/comp_fm_prereq_RHEL74.pl @@ -0,0 +1,53 @@ +#!/usr/bin/perl +## BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +## END_ICS_COPYRIGHT8 **************************************** +# +## [ICS VERSION STRING: unknown] +#use strict; +##use Term::ANSIColor; +##use Term::ANSIColor qw(:constants); +##use File::Basename; +##use Math::BigInt; +# +## ========================================================================== +# +#Installation Prequisites array for opafm +my @opafm_prereq = ( + "bash", + "expat", + "glibc", + "libibumad", + "libibverbs", + "openssl-libs", + "rdma-core", + "systemd", + "zlib", +); +$comp_prereq_hash{'opafm_prereq'} = \@opafm_prereq; + diff --git a/CommonInstall/comp_fm_prereq_RHEL74.pl.base b/CommonInstall/comp_fm_prereq_RHEL74.pl.base new file mode 100644 index 0000000..3c9d252 --- /dev/null +++ b/CommonInstall/comp_fm_prereq_RHEL74.pl.base @@ -0,0 +1,53 @@ +#!/usr/bin/perl +## BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +## END_ICS_COPYRIGHT8 **************************************** +# +## [ICS VERSION STRING: unknown] +#use strict; +##use Term::ANSIColor; +##use Term::ANSIColor qw(:constants); +##use File::Basename; +##use Math::BigInt; +# +## ========================================================================== +# +#Installation Prequisites array for opafm +my @opafm_prereq = ( + "bash", + "expat", + "glibc", + "libibumad", + "libibverbs", + "openssl-libs", + "rdma-core", + "systemd", + "zlib", +); +$comp_prereq_hash{'opafm_prereq'} = \@opafm_prereq; + diff --git a/CommonInstall/comp_fm_prereq_RHEL75.pl b/CommonInstall/comp_fm_prereq_RHEL75.pl new file mode 100644 index 0000000..28a9377 --- /dev/null +++ b/CommonInstall/comp_fm_prereq_RHEL75.pl @@ -0,0 +1,53 @@ +#!/usr/bin/perl +## BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +## END_ICS_COPYRIGHT8 **************************************** +# +## [ICS VERSION STRING: unknown] +#use strict; +##use Term::ANSIColor; +##use Term::ANSIColor qw(:constants); +##use File::Basename; +##use Math::BigInt; +# +## ========================================================================== +# +#Installation Prequisites array for opafm +my @opafm_prereq = ( + "bash", + "expat", + "glibc", + "libibumad", + "libibverbs", + "openssl-libs", + "rdma-core", + "systemd", + "zlib", +); +$comp_prereq_hash{'opafm_prereq'} = \@opafm_prereq; + diff --git a/CommonInstall/comp_fm_prereq_RHEL75.pl.base b/CommonInstall/comp_fm_prereq_RHEL75.pl.base new file mode 100644 index 0000000..28a9377 --- /dev/null +++ b/CommonInstall/comp_fm_prereq_RHEL75.pl.base @@ -0,0 +1,53 @@ +#!/usr/bin/perl +## BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +## END_ICS_COPYRIGHT8 **************************************** +# +## [ICS VERSION STRING: unknown] +#use strict; +##use Term::ANSIColor; +##use Term::ANSIColor qw(:constants); +##use File::Basename; +##use Math::BigInt; +# +## ========================================================================== +# +#Installation Prequisites array for opafm +my @opafm_prereq = ( + "bash", + "expat", + "glibc", + "libibumad", + "libibverbs", + "openssl-libs", + "rdma-core", + "systemd", + "zlib", +); +$comp_prereq_hash{'opafm_prereq'} = \@opafm_prereq; + diff --git a/CommonInstall/comp_fm_prereq_RHEL76.pl b/CommonInstall/comp_fm_prereq_RHEL76.pl new file mode 100644 index 0000000..a166489 --- /dev/null +++ b/CommonInstall/comp_fm_prereq_RHEL76.pl @@ -0,0 +1,53 @@ +#!/usr/bin/perl +## BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2018, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +## END_ICS_COPYRIGHT8 **************************************** +# +## [ICS VERSION STRING: unknown] +#use strict; +##use Term::ANSIColor; +##use Term::ANSIColor qw(:constants); +##use File::Basename; +##use Math::BigInt; +# +## ========================================================================== +# +#Installation Prequisites array for opafm +my @opafm_prereq = ( + "bash", + "expat", + "glibc", + "libibumad", + "libibverbs", + "openssl-libs", + "rdma-core", + "systemd", + "zlib", +); +$comp_prereq_hash{'opafm_prereq'} = \@opafm_prereq; + diff --git a/CommonInstall/comp_fm_prereq_RHEL76.pl.base b/CommonInstall/comp_fm_prereq_RHEL76.pl.base new file mode 100644 index 0000000..a166489 --- /dev/null +++ b/CommonInstall/comp_fm_prereq_RHEL76.pl.base @@ -0,0 +1,53 @@ +#!/usr/bin/perl +## BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2018, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +## END_ICS_COPYRIGHT8 **************************************** +# +## [ICS VERSION STRING: unknown] +#use strict; +##use Term::ANSIColor; +##use Term::ANSIColor qw(:constants); +##use File::Basename; +##use Math::BigInt; +# +## ========================================================================== +# +#Installation Prequisites array for opafm +my @opafm_prereq = ( + "bash", + "expat", + "glibc", + "libibumad", + "libibverbs", + "openssl-libs", + "rdma-core", + "systemd", + "zlib", +); +$comp_prereq_hash{'opafm_prereq'} = \@opafm_prereq; + diff --git a/CommonInstall/comp_fm_prereq_RHEL77.pl b/CommonInstall/comp_fm_prereq_RHEL77.pl new file mode 100644 index 0000000..a166489 --- /dev/null +++ b/CommonInstall/comp_fm_prereq_RHEL77.pl @@ -0,0 +1,53 @@ +#!/usr/bin/perl +## BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2018, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +## END_ICS_COPYRIGHT8 **************************************** +# +## [ICS VERSION STRING: unknown] +#use strict; +##use Term::ANSIColor; +##use Term::ANSIColor qw(:constants); +##use File::Basename; +##use Math::BigInt; +# +## ========================================================================== +# +#Installation Prequisites array for opafm +my @opafm_prereq = ( + "bash", + "expat", + "glibc", + "libibumad", + "libibverbs", + "openssl-libs", + "rdma-core", + "systemd", + "zlib", +); +$comp_prereq_hash{'opafm_prereq'} = \@opafm_prereq; + diff --git a/CommonInstall/comp_fm_prereq_RHEL77.pl.base b/CommonInstall/comp_fm_prereq_RHEL77.pl.base new file mode 100644 index 0000000..a166489 --- /dev/null +++ b/CommonInstall/comp_fm_prereq_RHEL77.pl.base @@ -0,0 +1,53 @@ +#!/usr/bin/perl +## BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2018, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +## END_ICS_COPYRIGHT8 **************************************** +# +## [ICS VERSION STRING: unknown] +#use strict; +##use Term::ANSIColor; +##use Term::ANSIColor qw(:constants); +##use File::Basename; +##use Math::BigInt; +# +## ========================================================================== +# +#Installation Prequisites array for opafm +my @opafm_prereq = ( + "bash", + "expat", + "glibc", + "libibumad", + "libibverbs", + "openssl-libs", + "rdma-core", + "systemd", + "zlib", +); +$comp_prereq_hash{'opafm_prereq'} = \@opafm_prereq; + diff --git a/CommonInstall/comp_fm_prereq_RHEL8.pl b/CommonInstall/comp_fm_prereq_RHEL8.pl new file mode 100644 index 0000000..c16ef21 --- /dev/null +++ b/CommonInstall/comp_fm_prereq_RHEL8.pl @@ -0,0 +1,52 @@ +#!/usr/bin/perl +## BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2019, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +## END_ICS_COPYRIGHT8 **************************************** +# +## [ICS VERSION STRING: unknown] +#use strict; +##use Term::ANSIColor; +##use Term::ANSIColor qw(:constants); +##use File::Basename; +##use Math::BigInt; +# +## ========================================================================== +# +#Installation Prequisites array for opafm +my @opafm_prereq = ( + "bash", + "expat", + "glibc", + "libibumad", + "libibverbs", + "openssl-libs", + "rdma-core", + "systemd", + "zlib", +); +$comp_prereq_hash{'opafm_prereq'} = \@opafm_prereq; diff --git a/CommonInstall/comp_fm_prereq_RHEL8.pl.base b/CommonInstall/comp_fm_prereq_RHEL8.pl.base new file mode 100644 index 0000000..c16ef21 --- /dev/null +++ b/CommonInstall/comp_fm_prereq_RHEL8.pl.base @@ -0,0 +1,52 @@ +#!/usr/bin/perl +## BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2019, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +## END_ICS_COPYRIGHT8 **************************************** +# +## [ICS VERSION STRING: unknown] +#use strict; +##use Term::ANSIColor; +##use Term::ANSIColor qw(:constants); +##use File::Basename; +##use Math::BigInt; +# +## ========================================================================== +# +#Installation Prequisites array for opafm +my @opafm_prereq = ( + "bash", + "expat", + "glibc", + "libibumad", + "libibverbs", + "openssl-libs", + "rdma-core", + "systemd", + "zlib", +); +$comp_prereq_hash{'opafm_prereq'} = \@opafm_prereq; diff --git a/CommonInstall/comp_fm_prereq_RHEL81.pl b/CommonInstall/comp_fm_prereq_RHEL81.pl new file mode 100644 index 0000000..c16ef21 --- /dev/null +++ b/CommonInstall/comp_fm_prereq_RHEL81.pl @@ -0,0 +1,52 @@ +#!/usr/bin/perl +## BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2019, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +## END_ICS_COPYRIGHT8 **************************************** +# +## [ICS VERSION STRING: unknown] +#use strict; +##use Term::ANSIColor; +##use Term::ANSIColor qw(:constants); +##use File::Basename; +##use Math::BigInt; +# +## ========================================================================== +# +#Installation Prequisites array for opafm +my @opafm_prereq = ( + "bash", + "expat", + "glibc", + "libibumad", + "libibverbs", + "openssl-libs", + "rdma-core", + "systemd", + "zlib", +); +$comp_prereq_hash{'opafm_prereq'} = \@opafm_prereq; diff --git a/CommonInstall/comp_fm_prereq_RHEL81.pl.base b/CommonInstall/comp_fm_prereq_RHEL81.pl.base new file mode 100644 index 0000000..c16ef21 --- /dev/null +++ b/CommonInstall/comp_fm_prereq_RHEL81.pl.base @@ -0,0 +1,52 @@ +#!/usr/bin/perl +## BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2019, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +## END_ICS_COPYRIGHT8 **************************************** +# +## [ICS VERSION STRING: unknown] +#use strict; +##use Term::ANSIColor; +##use Term::ANSIColor qw(:constants); +##use File::Basename; +##use Math::BigInt; +# +## ========================================================================== +# +#Installation Prequisites array for opafm +my @opafm_prereq = ( + "bash", + "expat", + "glibc", + "libibumad", + "libibverbs", + "openssl-libs", + "rdma-core", + "systemd", + "zlib", +); +$comp_prereq_hash{'opafm_prereq'} = \@opafm_prereq; diff --git a/CommonInstall/comp_fm_prereq_SLES122.pl b/CommonInstall/comp_fm_prereq_SLES122.pl new file mode 100644 index 0000000..819b374 --- /dev/null +++ b/CommonInstall/comp_fm_prereq_SLES122.pl @@ -0,0 +1,54 @@ +#!/usr/bin/perl +## BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +## END_ICS_COPYRIGHT8 **************************************** +# +## [ICS VERSION STRING: unknown] +#use strict; +##use Term::ANSIColor; +##use Term::ANSIColor qw(:constants); +##use File::Basename; +##use Math::BigInt; +# +## ========================================================================== +# +##Installation Prequisites array for opafm +my @opafm_prereq = ( + "glibc", + "bash", + "rdma", + "systemd", + "libexpat1", + "libibmad5", + "libibumad3", + "libibverbs1", + "libhfi1verbs-rdmav2", + "libopenssl1_0_0", + "libz1", +); +$comp_prereq_hash{'opafm_prereq'} = \@opafm_prereq; diff --git a/CommonInstall/comp_fm_prereq_SLES122.pl.base b/CommonInstall/comp_fm_prereq_SLES122.pl.base new file mode 100644 index 0000000..819b374 --- /dev/null +++ b/CommonInstall/comp_fm_prereq_SLES122.pl.base @@ -0,0 +1,54 @@ +#!/usr/bin/perl +## BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +## END_ICS_COPYRIGHT8 **************************************** +# +## [ICS VERSION STRING: unknown] +#use strict; +##use Term::ANSIColor; +##use Term::ANSIColor qw(:constants); +##use File::Basename; +##use Math::BigInt; +# +## ========================================================================== +# +##Installation Prequisites array for opafm +my @opafm_prereq = ( + "glibc", + "bash", + "rdma", + "systemd", + "libexpat1", + "libibmad5", + "libibumad3", + "libibverbs1", + "libhfi1verbs-rdmav2", + "libopenssl1_0_0", + "libz1", +); +$comp_prereq_hash{'opafm_prereq'} = \@opafm_prereq; diff --git a/CommonInstall/comp_fm_prereq_SLES123.pl b/CommonInstall/comp_fm_prereq_SLES123.pl new file mode 100644 index 0000000..06aa0d4 --- /dev/null +++ b/CommonInstall/comp_fm_prereq_SLES123.pl @@ -0,0 +1,54 @@ +#!/usr/bin/perl +## BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +## END_ICS_COPYRIGHT8 **************************************** +# +## [ICS VERSION STRING: unknown] +#use strict; +##use Term::ANSIColor; +##use Term::ANSIColor qw(:constants); +##use File::Basename; +##use Math::BigInt; +# +## ========================================================================== +# +##Installation Prequisites array for opafm +my @opafm_prereq = ( + "glibc", + "bash", + "rdma-core", + "rdma-ndd", + "systemd", + "libexpat1", + "libibmad5", + "libibumad3", + "libibverbs1", + "libopenssl1_0_0", + "libz1", +); +$comp_prereq_hash{'opafm_prereq'} = \@opafm_prereq; diff --git a/CommonInstall/comp_fm_prereq_SLES123.pl.base b/CommonInstall/comp_fm_prereq_SLES123.pl.base new file mode 100644 index 0000000..06aa0d4 --- /dev/null +++ b/CommonInstall/comp_fm_prereq_SLES123.pl.base @@ -0,0 +1,54 @@ +#!/usr/bin/perl +## BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +## END_ICS_COPYRIGHT8 **************************************** +# +## [ICS VERSION STRING: unknown] +#use strict; +##use Term::ANSIColor; +##use Term::ANSIColor qw(:constants); +##use File::Basename; +##use Math::BigInt; +# +## ========================================================================== +# +##Installation Prequisites array for opafm +my @opafm_prereq = ( + "glibc", + "bash", + "rdma-core", + "rdma-ndd", + "systemd", + "libexpat1", + "libibmad5", + "libibumad3", + "libibverbs1", + "libopenssl1_0_0", + "libz1", +); +$comp_prereq_hash{'opafm_prereq'} = \@opafm_prereq; diff --git a/CommonInstall/comp_fm_prereq_SLES124.pl b/CommonInstall/comp_fm_prereq_SLES124.pl new file mode 100644 index 0000000..aa0845d --- /dev/null +++ b/CommonInstall/comp_fm_prereq_SLES124.pl @@ -0,0 +1,54 @@ +#!/usr/bin/perl +## BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2018, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +## END_ICS_COPYRIGHT8 **************************************** +# +## [ICS VERSION STRING: unknown] +#use strict; +##use Term::ANSIColor; +##use Term::ANSIColor qw(:constants); +##use File::Basename; +##use Math::BigInt; +# +## ========================================================================== +# +##Installation Prequisites array for opafm +my @opafm_prereq = ( + "glibc", + "bash", + "rdma-core", + "rdma-ndd", + "systemd", + "libexpat1", + "libibmad5", + "libibumad3", + "libibverbs1", + "libopenssl1_0_0", + "libz1", +); +$comp_prereq_hash{'opafm_prereq'} = \@opafm_prereq; diff --git a/CommonInstall/comp_fm_prereq_SLES124.pl.base b/CommonInstall/comp_fm_prereq_SLES124.pl.base new file mode 100644 index 0000000..aa0845d --- /dev/null +++ b/CommonInstall/comp_fm_prereq_SLES124.pl.base @@ -0,0 +1,54 @@ +#!/usr/bin/perl +## BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2018, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +## END_ICS_COPYRIGHT8 **************************************** +# +## [ICS VERSION STRING: unknown] +#use strict; +##use Term::ANSIColor; +##use Term::ANSIColor qw(:constants); +##use File::Basename; +##use Math::BigInt; +# +## ========================================================================== +# +##Installation Prequisites array for opafm +my @opafm_prereq = ( + "glibc", + "bash", + "rdma-core", + "rdma-ndd", + "systemd", + "libexpat1", + "libibmad5", + "libibumad3", + "libibverbs1", + "libopenssl1_0_0", + "libz1", +); +$comp_prereq_hash{'opafm_prereq'} = \@opafm_prereq; diff --git a/CommonInstall/comp_fm_prereq_SLES125.pl b/CommonInstall/comp_fm_prereq_SLES125.pl new file mode 100644 index 0000000..aa0845d --- /dev/null +++ b/CommonInstall/comp_fm_prereq_SLES125.pl @@ -0,0 +1,54 @@ +#!/usr/bin/perl +## BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2018, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +## END_ICS_COPYRIGHT8 **************************************** +# +## [ICS VERSION STRING: unknown] +#use strict; +##use Term::ANSIColor; +##use Term::ANSIColor qw(:constants); +##use File::Basename; +##use Math::BigInt; +# +## ========================================================================== +# +##Installation Prequisites array for opafm +my @opafm_prereq = ( + "glibc", + "bash", + "rdma-core", + "rdma-ndd", + "systemd", + "libexpat1", + "libibmad5", + "libibumad3", + "libibverbs1", + "libopenssl1_0_0", + "libz1", +); +$comp_prereq_hash{'opafm_prereq'} = \@opafm_prereq; diff --git a/CommonInstall/comp_fm_prereq_SLES125.pl.base b/CommonInstall/comp_fm_prereq_SLES125.pl.base new file mode 100644 index 0000000..aa0845d --- /dev/null +++ b/CommonInstall/comp_fm_prereq_SLES125.pl.base @@ -0,0 +1,54 @@ +#!/usr/bin/perl +## BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2018, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +## END_ICS_COPYRIGHT8 **************************************** +# +## [ICS VERSION STRING: unknown] +#use strict; +##use Term::ANSIColor; +##use Term::ANSIColor qw(:constants); +##use File::Basename; +##use Math::BigInt; +# +## ========================================================================== +# +##Installation Prequisites array for opafm +my @opafm_prereq = ( + "glibc", + "bash", + "rdma-core", + "rdma-ndd", + "systemd", + "libexpat1", + "libibmad5", + "libibumad3", + "libibverbs1", + "libopenssl1_0_0", + "libz1", +); +$comp_prereq_hash{'opafm_prereq'} = \@opafm_prereq; diff --git a/CommonInstall/comp_fm_prereq_SLES15.pl b/CommonInstall/comp_fm_prereq_SLES15.pl new file mode 100644 index 0000000..f4dac89 --- /dev/null +++ b/CommonInstall/comp_fm_prereq_SLES15.pl @@ -0,0 +1,54 @@ +#!/usr/bin/perl +## BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +## END_ICS_COPYRIGHT8 **************************************** +# +## [ICS VERSION STRING: unknown] +#use strict; +##use Term::ANSIColor; +##use Term::ANSIColor qw(:constants); +##use File::Basename; +##use Math::BigInt; +# +## ========================================================================== +# +##Installation Prequisites array for opafm +my @opafm_prereq = ( + "glibc", + "bash", + "rdma-core", + "rdma-ndd", + "systemd", + "libexpat1", + "libibmad5", + "libibumad3", + "libibverbs1", + "libopenssl1_1", + "libz1", +); +$comp_prereq_hash{'opafm_prereq'} = \@opafm_prereq; diff --git a/CommonInstall/comp_fm_prereq_SLES15.pl.base b/CommonInstall/comp_fm_prereq_SLES15.pl.base new file mode 100644 index 0000000..f4dac89 --- /dev/null +++ b/CommonInstall/comp_fm_prereq_SLES15.pl.base @@ -0,0 +1,54 @@ +#!/usr/bin/perl +## BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +## END_ICS_COPYRIGHT8 **************************************** +# +## [ICS VERSION STRING: unknown] +#use strict; +##use Term::ANSIColor; +##use Term::ANSIColor qw(:constants); +##use File::Basename; +##use Math::BigInt; +# +## ========================================================================== +# +##Installation Prequisites array for opafm +my @opafm_prereq = ( + "glibc", + "bash", + "rdma-core", + "rdma-ndd", + "systemd", + "libexpat1", + "libibmad5", + "libibumad3", + "libibverbs1", + "libopenssl1_1", + "libz1", +); +$comp_prereq_hash{'opafm_prereq'} = \@opafm_prereq; diff --git a/CommonInstall/comp_fm_prereq_SLES151.pl b/CommonInstall/comp_fm_prereq_SLES151.pl new file mode 100644 index 0000000..289eddb --- /dev/null +++ b/CommonInstall/comp_fm_prereq_SLES151.pl @@ -0,0 +1,54 @@ +#!/usr/bin/perl +## BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2019, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +## END_ICS_COPYRIGHT8 **************************************** +# +## [ICS VERSION STRING: unknown] +#use strict; +##use Term::ANSIColor; +##use Term::ANSIColor qw(:constants); +##use File::Basename; +##use Math::BigInt; +# +## ========================================================================== +# +##Installation Prequisites array for opafm +my @opafm_prereq = ( + "glibc", + "bash", + "rdma-core", + "rdma-ndd", + "systemd", + "libexpat1", + "libibmad5", + "libibumad3", + "libibverbs1", + "libopenssl1_1", + "libz1", +); +$comp_prereq_hash{'opafm_prereq'} = \@opafm_prereq; diff --git a/CommonInstall/comp_fm_prereq_SLES151.pl.base b/CommonInstall/comp_fm_prereq_SLES151.pl.base new file mode 100644 index 0000000..289eddb --- /dev/null +++ b/CommonInstall/comp_fm_prereq_SLES151.pl.base @@ -0,0 +1,54 @@ +#!/usr/bin/perl +## BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2019, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +## END_ICS_COPYRIGHT8 **************************************** +# +## [ICS VERSION STRING: unknown] +#use strict; +##use Term::ANSIColor; +##use Term::ANSIColor qw(:constants); +##use File::Basename; +##use Math::BigInt; +# +## ========================================================================== +# +##Installation Prequisites array for opafm +my @opafm_prereq = ( + "glibc", + "bash", + "rdma-core", + "rdma-ndd", + "systemd", + "libexpat1", + "libibmad5", + "libibumad3", + "libibverbs1", + "libopenssl1_1", + "libz1", +); +$comp_prereq_hash{'opafm_prereq'} = \@opafm_prereq; diff --git a/CommonInstall/comp_oftools.pl b/CommonInstall/comp_oftools.pl new file mode 100755 index 0000000..5cb5f59 --- /dev/null +++ b/CommonInstall/comp_oftools.pl @@ -0,0 +1,164 @@ +#!/usr/bin/perl +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] +use strict; +#use Term::ANSIColor; +#use Term::ANSIColor qw(:constants); +#use File::Basename; +#use Math::BigInt; + +# ========================================================================== +# Fast Fabric Support tools for OFA (oftools) installation + +sub get_rpms_dir_oftools +{ + my $srcdir=$ComponentInfo{'oftools'}{'SrcDir'}; + return "$srcdir/RPMS/*"; +} + +sub available_oftools +{ +# TBD - could we move the algorithms for many of these functions into +# util_component.pl and simply put a list of rpms in the ComponentInfo +# as well as perhaps config files + my $srcdir=$ComponentInfo{'oftools'}{'SrcDir'}; + return ((rpm_resolve("$srcdir/RPMS/*/opa-basic-tools", "any") ne "") + && (rpm_resolve("$srcdir/RPMS/*/opa-address-resolution", "any") ne "" )); +} + +sub installed_oftools +{ + return rpm_is_installed("opa-basic-tools", "any"); +} + +# only called if installed_oftools is true +sub installed_version_oftools +{ + my $version = rpm_query_version_release_pkg("opa-basic-tools"); + return dot_version("$version"); +} + +# only called if available_oftools is true +sub media_version_oftools +{ + my $srcdir=$ComponentInfo{'oftools'}{'SrcDir'}; + my $rpmfile = rpm_resolve("$srcdir/RPMS/*/opa-basic-tools", "any"); + my $version= rpm_query_version_release("$rpmfile"); + # assume media properly built with matching versions for all rpms + return dot_version("$version"); +} + +sub build_oftools +{ + my $osver = $_[0]; + my $debug = $_[1]; # enable extra debug of build itself + my $build_temp = $_[2]; # temp area for use by build + my $force = $_[3]; # force a rebuild + return 0; # success +} + +sub need_reinstall_oftools($$) +{ + my $install_list = shift(); # total that will be installed when done + my $installing_list = shift(); # what items are being installed/reinstalled + + return "no"; +} + +sub preinstall_oftools +{ + my $install_list = $_[0]; # total that will be installed when done + my $installing_list = $_[1]; # what items are being installed/reinstalled + + return 0; # success +} + +sub install_oftools +{ + my $install_list = $_[0]; # total that will be installed when done + my $installing_list = $_[1]; # what items are being installed/reinstalled + + my $version=media_version_oftools(); + chomp $version; + printf("Installing $ComponentInfo{'oftools'}{'Name'} $version $DBG_FREE...\n"); + # TBD - review all components and make installing messages the same + #LogPrint "Installing $ComponentInfo{'oftools'}{'Name'} $version $DBG_FREE for $CUR_OS_VER\n"; + LogPrint "Installing $ComponentInfo{'oftools'}{'Name'} $version $DBG_FREE for $CUR_DISTRO_VENDOR $CUR_VENDOR_VER\n"; + + # RHEL7.4 and older in-distro IFS defines opa-address-resolution depends on opa-basic-tools with exact version match + # that will fail our installation because of dependency check. We need to use '-nodeps' to force the installation + install_comp_rpms('oftools', " -U --nodeps ", $install_list); + +# TBD - could we figure out the list of config files from a query of rpm +# and then simply iterate on each config file? + check_rpm_config_file("/etc/rdma/dsap.conf"); + + $ComponentWasInstalled{'oftools'}=1; +} + +sub postinstall_oftools +{ + my $install_list = $_[0]; # total that will be installed when done + my $installing_list = $_[1]; # what items are being installed/reinstalled +} + +sub uninstall_oftools +{ + my $install_list = $_[0]; # total that will be left installed when done + my $uninstalling_list = $_[1]; # what items are being uninstalled + + NormalPrint("Uninstalling $ComponentInfo{'oftools'}{'Name'}...\n"); + + uninstall_comp_rpms('oftools', '', $install_list, $uninstalling_list, 'verbose'); + + # remove LSF and Moab related files + system("rm -rf /usr/lib/opa/LSF_scripts"); + system("rm -rf /usr/lib/opa/Moab_scripts"); + + # may be created by opaverifyhosts + system("rm -rf /usr/lib/opa/tools/nodescript.sh"); + system("rm -rf /usr/lib/opa/tools/nodeverify.sh"); + + system "rmdir /usr/lib/opa/tools 2>/dev/null"; # remove only if empty + + # oftools is a prereq of fastfabric can cleanup shared files here + system("rm -rf $BASE_DIR/version_ff"); + system "rmdir $BASE_DIR 2>/dev/null"; # remove only if empty + system "rmdir $OPA_CONFIG_DIR 2>/dev/null"; # remove only if empty + system("rm -rf /usr/lib/opa/.comp_oftools.pl"); + system "rmdir /usr/lib/opa 2>/dev/null"; # remove only if empty + $ComponentWasInstalled{'oftools'}=0; +} + +sub check_os_prereqs_oftools +{ + return rpm_check_os_prereqs("oftools", "user"); +} diff --git a/CommonInstall/comp_omnipath.pl b/CommonInstall/comp_omnipath.pl new file mode 100644 index 0000000..3f137c3 --- /dev/null +++ b/CommonInstall/comp_omnipath.pl @@ -0,0 +1,1329 @@ +#!/usr/bin/perl +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +#[ICS VERSION STRING: unknown] +use strict; +use File::Basename; + +############################################################################# +## +## MPI installation generic functions + +# these functions can be used by the MPI specific install functions + +# installs PSM based MPI component. also handles reinstall on top of +# existing installation and upgrade. +sub install_generic_mpi +{ + my $install_list = $_[0]; + my $installing_list = $_[1]; + my $mpiname = $_[2]; + my $compiler = $_[3]; + my $suffix = $_[4]; + my $mpifullname = "$mpiname"."_$compiler"; + if ( "$suffix" ne "") { + $mpifullname = "$mpifullname" . "_" . "$suffix"; + } + my $srcdir = $ComponentInfo{$mpifullname}{'SrcDir'}; + my $version = eval "media_version_$mpifullname()"; + + printf ("Installing $ComponentInfo{$mpifullname}{'Name'} $version...\n"); + LogPrint ("Installing $ComponentInfo{$mpifullname}{'Name'} $version for $CUR_OS_VER\n"); + # make sure any old potentially custom built versions of mpi are uninstalled + uninstall_comp_rpms($mpifullname, ' --nodeps ', $install_list, $installing_list, 'silent'); + # cleanup from older installs just in case + system ("rm -rf /usr/lib/opa/.comp_$mpifullname.pl"); + + my $rpmfile = rpm_resolve("$srcdir/$mpifullname", "any"); + if ( "$rpmfile" ne "" && -e "$rpmfile" ) { + my $mpich_prefix= "/usr/mpi/$compiler/$mpiname-" + . rpm_query_attr($rpmfile, "VERSION"); + if ( "$suffix" ne "") { + $mpich_prefix= "$mpich_prefix" . "-" . "$suffix"; + } + if ( -d "$mpich_prefix" ) { + if (GetYesNo ("Remove $mpich_prefix directory?", "y")) { + LogPrint "rm -rf $mpich_prefix\n"; + system("rm -rf $mpich_prefix"); + } + } + } + # enable this code if mpitests is missing for some compilers or MPIs + #my $mpitests_rpmfile = rpm_resolve("$srcdir/OtherMPIs/mpitests_$mpifullname", "any"); + #if ( "$mpitests_rpmfile" ne "" && -e "$mpitests_rpmfile" ) { + install_comp_rpms($mpifullname, " -U --nodeps ", $install_list); + #} else { + # rpm_install("$srcdir/OtherMPIs/$mpifullname", "user"); + #} + + $ComponentWasInstalled{$mpifullname} = 1; +} + +sub installed_generic_mpi +{ + my $mpiname = $_[0]; + my $compiler = $_[1]; + my $suffix = $_[2]; + my $mpifullname = "$mpiname"."_$compiler"; + if ( "$suffix" ne "") { + $mpifullname = "$mpifullname" . "_" . "$suffix"; + } + + return (rpm_is_installed ($mpifullname, "user") ); +} + +sub uninstall_generic_mpi +{ + my $install_list = $_[0]; + my $installing_list = $_[1]; + my $mpiname = $_[2]; + my $compiler = $_[3]; + my $suffix = $_[4]; + my $mpifullname = "$mpiname"."_$compiler"; + if ( "$suffix" ne "") { + $mpifullname = "$mpifullname" . "_" . "$suffix"; + } + my $mpich_prefix= "/usr/mpi/$compiler/$mpiname-" + . rpm_query_attr_pkg("$mpifullname", "VERSION"); + if ( "$suffix" ne "") { + $mpich_prefix= "$mpich_prefix" . "-" . "$suffix"; + } + my $rc; + my $top; + + NormalPrint ("Uninstalling $ComponentInfo{$mpifullname}{'Name'}...\n"); + $top = rpm_query_attr_pkg("$mpifullname", "INSTALLPREFIX"); + if ($top eq "" || $top =~ /is not installed/) { + $top = undef; + } else { + $top = `dirname $top`; + chomp $top; + } + + # uninstall tests in case built by do_build + uninstall_comp_rpms($mpifullname, '', $install_list, $installing_list, 'verbose'); + + # unfortunately mpi and mpitests can leave empty directories on uninstall + # this can confuse IFS MPI tools because correct MPI to use + # cannot be identified. This remove such empty directories + if ( -d "/$mpich_prefix" ) { + system("cd '/$mpich_prefix'; rmdir -p tests/* >/dev/null 2>&1"); + } + if ( -d $top ) { + my @files = glob("$top/*"); + my $num = scalar (@files); + if ( $num == 0 ) { + system ("rm -rf $top"); + } + } + + # cleanup from older installs just in case + system ("rm -rf /usr/lib/opa/.comp_$mpifullname.pl"); + system ("rmdir /usr/lib/opa 2>/dev/null"); # remove only if empty + $ComponentWasInstalled{$mpifullname} = 0; +} + +############################################################################# +## +## OpenMPI GCC Verbs + +# is component X available on the install media (use of this +# allows for optional components in packaging or limited availability if a +# component isn't available on some OS/CPU combos) +sub get_rpms_dir_openmpi_gcc +{ + return $ComponentInfo{'openmpi_gcc'}{'SrcDir'}; +} + +sub available_openmpi_gcc +{ + my $srcdir = $ComponentInfo{'openmpi_gcc'}{'SrcDir'}; + return rpm_exists ("$srcdir/openmpi_gcc", "user"); +} + +# is component X presently installed on the system. This is +# a quick check, not a "verify" +sub installed_openmpi_gcc +{ + return installed_generic_mpi("openmpi", "gcc", ""); +} + +# what is the version installed on system. Only +# called if installed_X is true. versions are short strings displayed and +# logged, no operations are done (eg. only compare for equality) +sub installed_version_openmpi_gcc +{ + return rpm_query_version_release_pkg ("openmpi_gcc"); +} + +# only called if available_X. Indicates version on +# media. Will be compared with installed_version_X to determine if +# present installation is up to date. Should return exact same format for +# version string so comparison of equality is possible. +sub media_version_openmpi_gcc +{ + my $srcdir = $ComponentInfo{'openmpi_gcc'}{'SrcDir'}; + my $rpm = rpm_resolve ("$srcdir/openmpi_gcc", "user"); + return rpm_query_version_release ($rpm); +} + +# used to build/rebuild component on local system (if +# supported). We support this for many items in comp_ofed.pl +# Other components (like SM) are +# not available in source and hence do not support this and simply +# implement a noop. +sub build_openmpi_gcc +{ + my $osver = $_[0]; + my $debug = $_[1]; + my $build_temp = $_[2]; + my $force = $_[3]; + + return 0; +} + +# does this need to be reinstalled. Mainly used for +# ofed due to subtle changes such as install prefix or kernel options +# which may force a reinstall. You'll find this is a noop in most others. +sub need_reinstall_openmpi_gcc +{ + my $install_list = shift (); + my $installing_list = shift (); + + return "no"; +} + +# called for all components before they are installed. Use to verify OS +# has proper dependent rpms installed. +sub check_os_prereqs_openmpi_gcc +{ + return rpm_check_os_prereqs("openmpi_gcc", "user"); +} + +# called for all components before they are installed. Use +# to build things if needed, etc. +sub preinstall_openmpi_gcc +{ + my $install_list = $_[0]; + my $installing_list = $_[1]; + + my $full = ""; + my $rc; + + return 0; +} + +# installs component. also handles reinstall on top of +# existing installation and upgrade. +sub install_openmpi_gcc +{ + install_generic_mpi("$_[0]", "$_[1]", "openmpi", "gcc", ""); +} + +# called after all components are installed. +sub postinstall_openmpi_gcc +{ + my $install_list = $_[0]; # total that will be installed when done + my $installing_list = $_[1]; # what items are being installed/reinstalled +} + +# uninstalls component. May be called even if component is +# partially or not installed at all in which case should do its best to +# get rid or what might remain of component from a previously aborted +# uninstall or failed install +sub uninstall_openmpi_gcc +{ + uninstall_generic_mpi("$_[0]", "$_[1]", "openmpi", "gcc", ""); +} + +############################################################################# +## +## MVAPICH2 GCC Verbs + +# is component X available on the install media (use of this +# allows for optional components in packaging or limited availability if a +# component isn't available on some OS/CPU combos) + +sub get_rpms_dir_mvapich2_gcc +{ + return $ComponentInfo{'mvapich2_gcc'}{'SrcDir'}; +} + +sub available_mvapich2_gcc +{ + my $srcdir = $ComponentInfo{'mvapich2_gcc'}{'SrcDir'}; + return rpm_exists ("$srcdir/mvapich2_gcc", "user"); +} + +# is component X presently installed on the system. This is +# a quick check, not a "verify" +sub installed_mvapich2_gcc +{ + return installed_generic_mpi("mvapich2", "gcc", ""); +} + +# what is the version installed on system. Only +# called if installed_X is true. versions are short strings displayed and +# logged, no operations are done (eg. only compare for equality) +sub installed_version_mvapich2_gcc +{ + return rpm_query_version_release_pkg ("mvapich2_gcc"); +} + +# only called if available_X. Indicates version on +# media. Will be compared with installed_version_X to determine if +# present installation is up to date. Should return exact same format for +# version string so comparison of equality is possible. +sub media_version_mvapich2_gcc +{ + my $srcdir = $ComponentInfo{'mvapich2_gcc'}{'SrcDir'}; + my $rpm = rpm_resolve ("$srcdir/mvapich2_gcc", "user"); + return rpm_query_version_release ($rpm); +} + +# used to build/rebuild component on local system (if +# supported). We support this for many items in comp_ofed.pl +# Other components (like SM) are +# not available in source and hence do not support this and simply +# implement a noop. +sub build_mvapich2_gcc +{ + my $osver = $_[0]; + my $debug = $_[1]; + my $build_temp = $_[2]; + my $force = $_[3]; + + return 0; +} + +# does this need to be reinstalled. Mainly used for +# ofed due to subtle changes such as install prefix or kernel options +# which may force a reinstall. You'll find this is a noop in most others. +sub need_reinstall_mvapich2_gcc +{ + my $install_list = shift (); + my $installing_list = shift (); + + return "no"; +} + +# called for all components before they are installed. Use to verify OS +# has proper dependent rpms installed. +sub check_os_prereqs_mvapich2_gcc +{ + return rpm_check_os_prereqs("mvapich2_gcc", "user"); +} + +# called for all components before they are installed. Use +# to build things if needed, etc. +sub preinstall_mvapich2_gcc +{ + my $install_list = $_[0]; + my $installing_list = $_[1]; + + my $full = ""; + my $rc; + + return 0; +} + +# installs component. also handles reinstall on top of +# existing installation and upgrade. +sub install_mvapich2_gcc +{ + install_generic_mpi("$_[0]", "$_[1]", "mvapich2", "gcc", ""); +} + +# called after all components are installed. +sub postinstall_mvapich2_gcc +{ + my $install_list = $_[0]; # total that will be installed when done + my $installing_list = $_[1]; # what items are being installed/reinstalled +} + +# uninstalls component. May be called even if component is +# partially or not installed at all in which case should do its best to +# get rid or what might remain of component from a previously aborted +# uninstall or failed install +sub uninstall_mvapich2_gcc +{ + uninstall_generic_mpi("$_[0]", "$_[1]", "mvapich2", "gcc", ""); +} + +############################################################################# +## +## OpenMPI GCC PSM + +# is component X available on the install media (use of this +# allows for optional components in packaging or limited availability if a +# component isn't available on some OS/CPU combos) + +sub get_rpms_dir_openmpi_gcc_hfi +{ + return $ComponentInfo{'openmpi_gcc_hfi'}{'SrcDir'}; +} + +sub available_openmpi_gcc_hfi +{ + my $srcdir = $ComponentInfo{'openmpi_gcc_hfi'}{'SrcDir'}; + return rpm_exists ("$srcdir/openmpi_gcc_hfi", "user"); +} + +# is component X presently installed on the system. This is +# a quick check, not a "verify" +sub installed_openmpi_gcc_hfi +{ + return installed_generic_mpi("openmpi", "gcc", "hfi"); +} + +# what is the version installed on system. Only +# called if installed_X is true. versions are short strings displayed and +# logged, no operations are done (eg. only compare for equality) +sub installed_version_openmpi_gcc_hfi +{ + return rpm_query_version_release_pkg ("openmpi_gcc_hfi"); +} + +# only called if available_X. Indicates version on +# media. Will be compared with installed_version_X to determine if +# present installation is up to date. Should return exact same format for +# version string so comparison of equality is possible. +sub media_version_openmpi_gcc_hfi +{ + my $srcdir = $ComponentInfo{'openmpi_gcc_hfi'}{'SrcDir'}; + my $rpm = rpm_resolve ("$srcdir/openmpi_gcc_hfi", "user"); + return rpm_query_version_release ($rpm); +} + +# used to build/rebuild component on local system (if +# supported). We support this for many items in comp_ofed.pl +# Other components (like SM) are +# not available in source and hence do not support this and simply +# implement a noop. +sub build_openmpi_gcc_hfi +{ + my $osver = $_[0]; + my $debug = $_[1]; + my $build_temp = $_[2]; + my $force = $_[3]; + + return 0; +} + +# does this need to be reinstalled. Mainly used for +# ofed due to subtle changes such as install prefix or kernel options +# which may force a reinstall. You'll find this is a noop in most others. +sub need_reinstall_openmpi_gcc_hfi +{ + my $install_list = shift (); + my $installing_list = shift (); + + return "no"; +} + +# called for all components before they are installed. Use to verify OS +# has proper dependent rpms installed. +sub check_os_prereqs_openmpi_gcc_hfi +{ + return rpm_check_os_prereqs("openmpi_gcc_hfi", "user"); +} + +# called for all components before they are installed. Use +# to build things if needed, etc. +sub preinstall_openmpi_gcc_hfi +{ + my $install_list = $_[0]; + my $installing_list = $_[1]; + + my $full = ""; + my $rc; + + return 0; +} + +# installs component. also handles reinstall on top of +# existing installation and upgrade. +sub install_openmpi_gcc_hfi +{ + install_generic_mpi("$_[0]", "$_[1]", "openmpi", "gcc", "hfi"); +} + +# called after all components are installed. +sub postinstall_openmpi_gcc_hfi +{ + my $install_list = $_[0]; # total that will be installed when done + my $installing_list = $_[1]; # what items are being installed/reinstalled +} + +# uninstalls component. May be called even if component is +# partially or not installed at all in which case should do its best to +# get rid or what might remain of component from a previously aborted +# uninstall or failed install +sub uninstall_openmpi_gcc_hfi +{ + uninstall_generic_mpi("$_[0]", "$_[1]", "openmpi", "gcc", "hfi"); +} + +############################################################################# +## +## OpenMPI Intel PSM + +# is component X available on the install media (use of this +# allows for optional components in packaging or limited availability if a +# component isn't available on some OS/CPU combos) + +sub get_rpms_dir_openmpi_intel_hfi +{ + return $ComponentInfo{'openmpi_intel_hfi'}{'SrcDir'}; +} + +sub available_openmpi_intel_hfi +{ + my $srcdir = $ComponentInfo{'openmpi_intel_hfi'}{'SrcDir'}; + return rpm_exists ("$srcdir/openmpi_intel_hfi", "user"); +} + +# is component X presently installed on the system. This is +# a quick check, not a "verify" +sub installed_openmpi_intel_hfi +{ + return installed_generic_mpi("openmpi", "intel", "hfi"); +} + +# what is the version installed on system. Only +# called if installed_X is true. versions are short strings displayed and +# logged, no operations are done (eg. only compare for equality) +sub installed_version_openmpi_intel_hfi +{ + return rpm_query_version_release_pkg ("openmpi_intel_hfi"); +} + +# only called if available_X. Indicates version on +# media. Will be compared with installed_version_X to determine if +# present installation is up to date. Should return exact same format for +# version string so comparison of equality is possible. +sub media_version_openmpi_intel_hfi +{ + my $srcdir = $ComponentInfo{'openmpi_intel_hfi'}{'SrcDir'}; + my $rpm = rpm_resolve ("$srcdir/openmpi_intel_hfi", "user"); + return rpm_query_version_release ($rpm); +} + +# used to build/rebuild component on local system (if +# supported). We support this for many items in comp_ofed.pl +# Other components (like SM) are +# not available in source and hence do not support this and simply +# implement a noop. +sub build_openmpi_intel_hfi +{ + my $osver = $_[0]; + my $debug = $_[1]; + my $build_temp = $_[2]; + my $force = $_[3]; + + return 0; +} + +# does this need to be reinstalled. Mainly used for +# ofed due to subtle changes such as install prefix or kernel options +# which may force a reinstall. You'll find this is a noop in most others. +sub need_reinstall_openmpi_intel_hfi +{ + my $install_list = shift (); + my $installing_list = shift (); + + return "no"; +} + +# called for all components before they are installed. Use to verify OS +# has proper dependent rpms installed. +sub check_os_prereqs_openmpi_intel_hfi +{ + return rpm_check_os_prereqs("openmpi_intel_hfi", "user"); +} + +# called for all components before they are installed. Use +# to build things if needed, etc. +sub preinstall_openmpi_intel_hfi +{ + my $install_list = $_[0]; + my $installing_list = $_[1]; + + my $full = ""; + my $rc; + + return 0; +} + +# installs component. also handles reinstall on top of +# existing installation and upgrade. +sub install_openmpi_intel_hfi +{ + install_generic_mpi("$_[0]", "$_[1]", "openmpi", "intel", "hfi"); +} + +# called after all components are installed. +sub postinstall_openmpi_intel_hfi +{ + my $install_list = $_[0]; # total that will be installed when done + my $installing_list = $_[1]; # what items are being installed/reinstalled +} + +# uninstalls component. May be called even if component is +# partially or not installed at all in which case should do its best to +# get rid or what might remain of component from a previously aborted +# uninstall or failed install +sub uninstall_openmpi_intel_hfi +{ + uninstall_generic_mpi("$_[0]", "$_[1]", "openmpi", "intel", "hfi"); +} + +############################################################################# +## +## OpenMPI PGI PSM + +# is component X available on the install media (use of this +# allows for optional components in packaging or limited availability if a +# component isn't available on some OS/CPU combos) + +sub get_rpms_dir_openmpi_pgi_hfi +{ + return $ComponentInfo{'openmpi_pgi_hfi'}{'SrcDir'}; +} + +sub available_openmpi_pgi_hfi +{ + my $srcdir = $ComponentInfo{'openmpi_pgi_hfi'}{'SrcDir'}; + return rpm_exists ("$srcdir/openmpi_pgi_hfi", "user"); +} + +# is component X presently installed on the system. This is +# a quick check, not a "verify" +sub installed_openmpi_pgi_hfi +{ + return installed_generic_mpi("openmpi", "pgi", "hfi"); +} + +# what is the version installed on system. Only +# called if installed_X is true. versions are short strings displayed and +# logged, no operations are done (eg. only compare for equality) +sub installed_version_openmpi_pgi_hfi +{ + return rpm_query_version_release_pkg ("openmpi_pgi_hfi"); +} + +# only called if available_X. Indicates version on +# media. Will be compared with installed_version_X to determine if +# present installation is up to date. Should return exact same format for +# version string so comparison of equality is possible. +sub media_version_openmpi_pgi_hfi +{ + my $srcdir = $ComponentInfo{'openmpi_pgi_hfi'}{'SrcDir'}; + my $rpm = rpm_resolve ("$srcdir/openmpi_pgi_hfi", "user"); + return rpm_query_version_release ($rpm); +} + +# used to build/rebuild component on local system (if +# supported). We support this for many items in comp_ofed.pl +# Other components (like SM) are +# not available in source and hence do not support this and simply +# implement a noop. +sub build_openmpi_pgi_hfi +{ + my $osver = $_[0]; + my $debug = $_[1]; + my $build_temp = $_[2]; + my $force = $_[3]; + + return 0; +} + +# does this need to be reinstalled. Mainly used for +# ofed due to subtle changes such as install prefix or kernel options +# which may force a reinstall. You'll find this is a noop in most others. +sub need_reinstall_openmpi_pgi_hfi +{ + my $install_list = shift (); + my $installing_list = shift (); + + return "no"; +} + +# called for all components before they are installed. Use to verify OS +# has proper dependent rpms installed. +sub check_os_prereqs_openmpi_pgi_hfi +{ + return rpm_check_os_prereqs("openmpi_pgi_hfi", "user"); +} + +# called for all components before they are installed. Use +# to build things if needed, etc. +sub preinstall_openmpi_pgi_hfi +{ + my $install_list = $_[0]; + my $installing_list = $_[1]; + + my $full = ""; + my $rc; + + return 0; +} + +# installs component. also handles reinstall on top of +# existing installation and upgrade. +sub install_openmpi_pgi_hfi +{ + install_generic_mpi("$_[0]", "$_[1]", "openmpi", "pgi", "hfi"); +} + +# called after all components are installed. +sub postinstall_openmpi_pgi_hfi +{ + my $install_list = $_[0]; # total that will be installed when done + my $installing_list = $_[1]; # what items are being installed/reinstalled +} + +# uninstalls component. May be called even if component is +# partially or not installed at all in which case should do its best to +# get rid or what might remain of component from a previously aborted +# uninstall or failed install +sub uninstall_openmpi_pgi_hfi +{ + uninstall_generic_mpi("$_[0]", "$_[1]", "openmpi", "pgi", "hfi"); +} + +############################################################################# +## +## MVAPICH2 GCC PSM + +# is component X available on the install media (use of this +# allows for optional components in packaging or limited availability if a +# component isn't available on some OS/CPU combos) + +sub get_rpms_dir_mvapich2_gcc_hfi +{ + return $ComponentInfo{'mvapich2_gcc_hfi'}{'SrcDir'}; +} + +sub available_mvapich2_gcc_hfi +{ + my $srcdir = $ComponentInfo{'mvapich2_gcc_hfi'}{'SrcDir'}; + return rpm_exists ("$srcdir/mvapich2_gcc_hfi", "user"); +} + +# is component X presently installed on the system. This is +# a quick check, not a "verify" +sub installed_mvapich2_gcc_hfi +{ + return installed_generic_mpi("mvapich2", "gcc", "hfi"); +} + +# what is the version installed on system. Only +# called if installed_X is true. versions are short strings displayed and +# logged, no operations are done (eg. only compare for equality) +sub installed_version_mvapich2_gcc_hfi +{ + return rpm_query_version_release_pkg ("mvapich2_gcc_hfi"); +} + +# only called if available_X. Indicates version on +# media. Will be compared with installed_version_X to determine if +# present installation is up to date. Should return exact same format for +# version string so comparison of equality is possible. +sub media_version_mvapich2_gcc_hfi +{ + my $srcdir = $ComponentInfo{'mvapich2_gcc_hfi'}{'SrcDir'}; + my $rpm = rpm_resolve ("$srcdir/mvapich2_gcc_hfi", "user"); + return rpm_query_version_release ($rpm); +} + +# used to build/rebuild component on local system (if +# supported). We support this for many items in comp_ofed.pl +# Other components (like SM) are +# not available in source and hence do not support this and simply +# implement a noop. +sub build_mvapich2_gcc_hfi +{ + my $osver = $_[0]; + my $debug = $_[1]; + my $build_temp = $_[2]; + my $force = $_[3]; + + return 0; +} + +# does this need to be reinstalled. Mainly used for +# ofed due to subtle changes such as install prefix or kernel options +# which may force a reinstall. You'll find this is a noop in most others. +sub need_reinstall_mvapich2_gcc_hfi +{ + my $install_list = shift (); + my $installing_list = shift (); + + return "no"; +} + +# called for all components before they are installed. Use to verify OS +# has proper dependent rpms installed. +sub check_os_prereqs_mvapich2_gcc_hfi +{ + return rpm_check_os_prereqs("mvapich2_gcc_hfi", "user"); +} + +# called for all components before they are installed. Use +# to build things if needed, etc. +sub preinstall_mvapich2_gcc_hfi +{ + my $install_list = $_[0]; + my $installing_list = $_[1]; + + my $full = ""; + my $rc; + + return 0; +} + +# installs component. also handles reinstall on top of +# existing installation and upgrade. +sub install_mvapich2_gcc_hfi +{ + install_generic_mpi("$_[0]", "$_[1]", "mvapich2", "gcc", "hfi"); +} + +# called after all components are installed. +sub postinstall_mvapich2_gcc_hfi +{ + my $install_list = $_[0]; # total that will be installed when done + my $installing_list = $_[1]; # what items are being installed/reinstalled +} + +# uninstalls component. May be called even if component is +# partially or not installed at all in which case should do its best to +# get rid or what might remain of component from a previously aborted +# uninstall or failed install +sub uninstall_mvapich2_gcc_hfi +{ + uninstall_generic_mpi("$_[0]", "$_[1]", "mvapich2", "gcc", "hfi"); +} + +############################################################################# +## +## MVAPICH2 Intel PSM + +# is component X available on the install media (use of this +# allows for optional components in packaging or limited availability if a +# component isn't available on some OS/CPU combos) + +sub get_rpms_dir_mvapich2_intel_hfi +{ + return $ComponentInfo{'mvapich2_intel_hfi'}{'SrcDir'}; +} + +sub available_mvapich2_intel_hfi +{ + my $srcdir = $ComponentInfo{'mvapich2_intel_hfi'}{'SrcDir'}; + return rpm_exists ("$srcdir/mvapich2_intel_hfi", "user"); +} + +# is component X presently installed on the system. This is +# a quick check, not a "verify" +sub installed_mvapich2_intel_hfi +{ + return installed_generic_mpi("mvapich2", "intel", "hfi"); +} + +# what is the version installed on system. Only +# called if installed_X is true. versions are short strings displayed and +# logged, no operations are done (eg. only compare for equality) +sub installed_version_mvapich2_intel_hfi +{ + return rpm_query_version_release_pkg ("mvapich2_intel_hfi"); +} + +# only called if available_X. Indicates version on +# media. Will be compared with installed_version_X to determine if +# present installation is up to date. Should return exact same format for +# version string so comparison of equality is possible. +sub media_version_mvapich2_intel_hfi +{ + my $srcdir = $ComponentInfo{'mvapich2_intel_hfi'}{'SrcDir'}; + my $rpm = rpm_resolve ("$srcdir/mvapich2_intel_hfi", "user"); + return rpm_query_version_release ($rpm); +} + +# used to build/rebuild component on local system (if +# supported). We support this for many items in comp_ofed.pl +# Other components (like SM) are +# not available in source and hence do not support this and simply +# implement a noop. +sub build_mvapich2_intel_hfi +{ + my $osver = $_[0]; + my $debug = $_[1]; + my $build_temp = $_[2]; + my $force = $_[3]; + + return 0; +} + +# does this need to be reinstalled. Mainly used for +# ofed due to subtle changes such as install prefix or kernel options +# which may force a reinstall. You'll find this is a noop in most others. +sub need_reinstall_mvapich2_intel_hfi +{ + my $install_list = shift (); + my $installing_list = shift (); + + return "no"; +} + +# called for all components before they are installed. Use to verify OS +# has proper dependent rpms installed. +sub check_os_prereqs_mvapich2_intel_hfi +{ + # we allow this to install even if intel compiler runtime not available + return rpm_check_os_prereqs("mvapich2_intel_hfi", "user"); +} + +# called for all components before they are installed. Use +# to build things if needed, etc. +sub preinstall_mvapich2_intel_hfi +{ + my $install_list = $_[0]; + my $installing_list = $_[1]; + + my $full = ""; + my $rc; + + return 0; +} + +# installs component. also handles reinstall on top of +# existing installation and upgrade. +sub install_mvapich2_intel_hfi +{ + install_generic_mpi("$_[0]", "$_[1]", "mvapich2", "intel", "hfi"); +} + +# called after all components are installed. +sub postinstall_mvapich2_intel_hfi +{ + my $install_list = $_[0]; # total that will be installed when done + my $installing_list = $_[1]; # what items are being installed/reinstalled +} + +# uninstalls component. May be called even if component is +# partially or not installed at all in which case should do its best to +# get rid or what might remain of component from a previously aborted +# uninstall or failed install +sub uninstall_mvapich2_intel_hfi +{ + uninstall_generic_mpi("$_[0]", "$_[1]", "mvapich2", "intel", "hfi"); +} + +############################################################################# +## +## MVAPICH2 PGI PSM + +# is component X available on the install media (use of this +# allows for optional components in packaging or limited availability if a +# component isn't available on some OS/CPU combos) + +sub get_rpms_dir_mvapich2_pgi_hfi +{ + return $ComponentInfo{'mvapich2_pgi_hfi'}{'SrcDir'}; +} + +sub available_mvapich2_pgi_hfi +{ + my $srcdir = $ComponentInfo{'mvapich2_pgi_hfi'}{'SrcDir'}; + return rpm_exists ("$srcdir/mvapich2_pgi_hfi", "user"); +} + +# is component X presently installed on the system. This is +# a quick check, not a "verify" +sub installed_mvapich2_pgi_hfi +{ + return installed_generic_mpi("mvapich2", "pgi", "hfi"); +} + +# what is the version installed on system. Only +# called if installed_X is true. versions are short strings displayed and +# logged, no operations are done (eg. only compare for equality) +sub installed_version_mvapich2_pgi_hfi +{ + return rpm_query_version_release_pkg ("mvapich2_pgi_hfi"); +} + +# only called if available_X. Indicates version on +# media. Will be compared with installed_version_X to determine if +# present installation is up to date. Should return exact same format for +# version string so comparison of equality is possible. +sub media_version_mvapich2_pgi_hfi +{ + my $srcdir = $ComponentInfo{'mvapich2_pgi_hfi'}{'SrcDir'}; + my $rpm = rpm_resolve ("$srcdir/mvapich2_pgi_hfi", "user"); + return rpm_query_version_release ($rpm); +} + +# used to build/rebuild component on local system (if +# supported). We support this for many items in comp_ofed.pl +# Other components (like SM) are +# not available in source and hence do not support this and simply +# implement a noop. +sub build_mvapich2_pgi_hfi +{ + my $osver = $_[0]; + my $debug = $_[1]; + my $build_temp = $_[2]; + my $force = $_[3]; + + return 0; +} + +# does this need to be reinstalled. Mainly used for +# ofed due to subtle changes such as install prefix or kernel options +# which may force a reinstall. You'll find this is a noop in most others. +sub need_reinstall_mvapich2_pgi_hfi +{ + my $install_list = shift (); + my $installing_list = shift (); + + return "no"; +} + +# called for all components before they are installed. Use to verify OS +# has proper dependent rpms installed. +sub check_os_prereqs_mvapich2_pgi_hfi +{ + # we allow this to install even if pgi compiler runtime not available + return rpm_check_os_prereqs("mvapich2_pgi_hfi", "user"); +} + +# called for all components before they are installed. Use +# to build things if needed, etc. +sub preinstall_mvapich2_pgi_hfi +{ + my $install_list = $_[0]; + my $installing_list = $_[1]; + + my $full = ""; + my $rc; + + return 0; +} + +# installs component. also handles reinstall on top of +# existing installation and upgrade. +sub install_mvapich2_pgi_hfi +{ + install_generic_mpi("$_[0]", "$_[1]", "mvapich2", "pgi", "hfi"); +} + +# called after all components are installed. +sub postinstall_mvapich2_pgi_hfi +{ + my $install_list = $_[0]; # total that will be installed when done + my $installing_list = $_[1]; # what items are being installed/reinstalled +} + +# uninstalls component. May be called even if component is +# partially or not installed at all in which case should do its best to +# get rid or what might remain of component from a previously aborted +# uninstall or failed install +sub uninstall_mvapich2_pgi_hfi +{ + uninstall_generic_mpi("$_[0]", "$_[1]", "mvapich2", "pgi", "hfi"); +} + + + +############################################################################# +### +### OpenMPI GCC CUDA +# + +# is component X available on the install media (use of this +# allows for optional components in packaging or limited availability if a +# component isn't available on some OS/CPU combos) + +sub get_rpms_dir_openmpi_gcc_cuda_hfi +{ + return $ComponentInfo{'openmpi_gcc_cuda_hfi'}{'SrcDir'}; +} + +sub available_openmpi_gcc_cuda_hfi +{ + my $srcdir = $ComponentInfo{'openmpi_gcc_cuda_hfi'}{'SrcDir'}; + return rpm_exists ("$srcdir/openmpi_gcc_cuda_hfi", "user"); +} + +# is component X presently installed on the system. This is +# a quick check, not a "verify" +sub installed_openmpi_gcc_cuda_hfi +{ + return installed_generic_mpi("openmpi", "gcc_cuda", "hfi"); +} + +# what is the version installed on system. Only +# called if installed_X is true. versions are short strings displayed and +# logged, no operations are done (eg. only compare for equality) +sub installed_version_openmpi_gcc_cuda_hfi +{ + return rpm_query_version_release_pkg ("openmpi_gcc_cuda_hfi"); +} + +# only called if available_X. Indicates version on +# media. Will be compared with installed_version_X to determine if +# present installation is up to date. Should return exact same format for +# version string so comparison of equality is possible. +sub media_version_openmpi_gcc_cuda_hfi +{ + my $srcdir = $ComponentInfo{'openmpi_gcc_cuda_hfi'}{'SrcDir'}; + my $rpm = rpm_resolve ("$srcdir/openmpi_gcc_cuda_hfi", "user"); + return rpm_query_version_release ($rpm); +} + +# used to build/rebuild component on local system (if +# supported). We support this for many items in comp_ofed.pl +# Other components (like SM) are +# not available in source and hence do not support this and simply +# implement a noop. +sub build_openmpi_gcc_cuda_hfi +{ + my $osver = $_[0]; + my $debug = $_[1]; + my $build_temp = $_[2]; + my $force = $_[3]; + + return 0; +} + +# does this need to be reinstalled. Mainly used for +# ofed due to subtle changes such as install prefix or kernel options +# which may force a reinstall. You'll find this is a noop in most others. +sub need_reinstall_openmpi_gcc_cuda_hfi +{ + my $install_list = shift (); + my $installing_list = shift (); + + return "no"; +} + +# called for all components before they are installed. Use to verify OS +# has proper dependent rpms installed. +sub check_os_prereqs_openmpi_gcc_cuda_hfi +{ + return rpm_check_os_prereqs("openmpi_gcc_cuda_hfi", "user"); +} + +# called for all components before they are installed. Use +# to build things if needed, etc. +sub preinstall_openmpi_gcc_cuda_hfi +{ + my $install_list = $_[0]; + my $installing_list = $_[1]; + + my $full = ""; + my $rc; + + return 0; +} + +# installs component. also handles reinstall on top of +# existing installation and upgrade. +sub install_openmpi_gcc_cuda_hfi +{ + install_generic_mpi("$_[0]", "$_[1]", "openmpi", "gcc_cuda", "hfi"); +} + +# called after all components are installed. +sub postinstall_openmpi_gcc_cuda_hfi +{ + my $install_list = $_[0]; # total that will be installed when done + my $installing_list = $_[1]; # what items are being installed/reinstalled +} + +# uninstalls component. May be called even if component is +# partially or not installed at all in which case should do its best to +# get rid or what might remain of component from a previously aborted +# uninstall or failed install +sub uninstall_openmpi_gcc_cuda_hfi +{ + uninstall_generic_mpi("$_[0]", "$_[1]", "openmpi", "gcc_cuda", "hfi"); +} + +############################################################################# +### +### MPI Source + +sub available_mpisrc() +{ + my $srcdir=$ComponentInfo{'mpisrc'}{'SrcDir'}; + return has_mpisrc($srcdir); + #return ( (-d "$srcdir/SRPMS" || -d "$srcdir/RPMS" ) ); +} + +sub installed_mpisrc() +{ + my $srcdir = "/usr/src/opa/MPI"; + my $old_srcdir = "/usr/lib/opa/src/MPI"; + return (has_mpisrc($srcdir) || has_mpisrc($old_srcdir)); +} + +sub has_mpisrc($) +{ + my $srcdir = shift(); + return (file_glob("$srcdir/mvapich*.src.rpm") ne "" + && file_glob("$srcdir/openmpi*.src.rpm") ne "" + && file_glob("$srcdir/mpitests*.src.rpm") ne ""); +} + +# only called if installed_mpisrc is true +sub installed_version_mpisrc() +{ + return `cat /usr/src/opa/MPI/.version`; +} + +# only called if available_mpisrc is true +sub media_version_mpisrc() +{ + my $srcdir=$ComponentInfo{'mpisrc'}{'SrcDir'}; + return `cat "$srcdir/version"`; +} + +sub build_mpisrc($$$$) +{ + my $osver = shift(); + my $debug = shift(); # enable extra debug of build itself + my $build_temp = shift(); # temp area for use by build + my $force = shift(); # force a rebuild + return 0; # success +} + +sub need_reinstall_mpisrc($$) +{ + my $install_list = shift(); # total that will be installed when done + my $installing_list = shift(); # what items are being installed/reinstalled + + return "no"; +} + +sub check_os_prereqs_mpisrc +{ + return rpm_check_os_prereqs("mpisrc", "any"); +} + +sub preinstall_mpisrc($$) +{ + my $install_list = shift(); # total that will be installed when done + my $installing_list = shift(); # what items are being installed/reinstalled + + return 0; +} + +sub install_mpisrc($$) +{ + my $install_list = shift(); # total that will be installed when done + my $installing_list = shift(); # what items are being installed/reinstalled + + my $srcdir=$ComponentInfo{'mpisrc'}{'SrcDir'}; + my $version = media_version_mpisrc(); + chomp $version; + + printf ("Installing $ComponentInfo{'mpisrc'}{'Name'} $version...\n"); + LogPrint ("Installing $ComponentInfo{'mpisrc'}{'Name'} $version for $CUR_OS_VER\n"); + + check_dir("/usr/src/opa"); + check_dir("/usr/src/opa/MPI"); + # remove old versions (.src.rpm and built .rpm files too) + system "rm -rf /usr/src/opa/MPI/mvapich[-_]*.rpm 2>/dev/null"; + system "rm -rf /usr/src/opa/MPI/mvapich2[-_]*.rpm 2>/dev/null"; + system "rm -rf /usr/src/opa/MPI/openmpi[-_]*.rpm 2>/dev/null"; + system "rm -rf /usr/src/opa/MPI/mpitests[-_]*.rpm 2>/dev/null"; + system "rm -rf /usr/src/opa/MPI/make.*.res 2>/dev/null"; + system "rm -rf /usr/src/opa/MPI/make.*.err 2>/dev/null"; + system "rm -rf /usr/src/opa/MPI/make.*.warn 2>/dev/null"; + system "rm -rf /usr/src/opa/MPI/.mpiinfo 2>/dev/null"; + + # install new versions + foreach my $srpm ( "mvapich2", "openmpi", "mpitests" ) { + my $srpmfile = file_glob("$srcdir/${srpm}-*.src.rpm"); + if ( "$srpmfile" ne "" ) { + my $file = my_basename($srpmfile); + copy_data_file($srpmfile, "/usr/src/opa/MPI/$file"); + } + } + copy_systool_file("$srcdir/do_build", "/usr/src/opa/MPI/do_build"); + copy_systool_file("$srcdir/do_mvapich2_build", "/usr/src/opa/MPI/do_mvapich2_build"); + copy_systool_file("$srcdir/do_openmpi_build", "/usr/src/opa/MPI/do_openmpi_build"); + copy_data_file("$srcdir/version", "/usr/src/opa/MPI/.version"); + + $ComponentWasInstalled{'mpisrc'}=1; +} + +sub postinstall_mpisrc($$) +{ + my $install_list = shift(); # total that will be installed when done + my $installing_list = shift(); # what items are being installed/reinstalled +} + +sub uninstall_mpisrc($$) +{ + my $install_list = shift(); # total that will be left installed when done + my $uninstalling_list = shift(); # what items are being uninstalled + + NormalPrint ("Uninstalling $ComponentInfo{'mpisrc'}{'Name'}...\n"); + + # try to uninstall meta pkg if it exists + if (rpm_is_installed("opameta_mpisrc", "any") || + rpm_is_installed("opameta_mpisrc_userspace", "any")) { + rpm_uninstall_matches("opameta_mpisrc", "opameta_mpisrc", "", ""); + } else { + # remove old versions (.src.rpm and built .rpm files too) + system "rm -rf /usr/src/opa/MPI/.version 2>/dev/null"; + system "rm -rf /usr/src/opa/MPI/mvapich2[-_]*.rpm 2>/dev/null"; + system "rm -rf /usr/src/opa/MPI/openmpi[-_]*.rpm 2>/dev/null"; + system "rm -rf /usr/src/opa/MPI/mpitests[-_]*.rpm 2>/dev/null"; + system "rm -rf /usr/src/opa/MPI/make.*.res 2>/dev/null"; + system "rm -rf /usr/src/opa/MPI/make.*.err 2>/dev/null"; + system "rm -rf /usr/src/opa/MPI/make.*.warn 2>/dev/null"; + system "rm -rf /usr/src/opa/MPI/.mpiinfo 2>/dev/null"; + system "rm -rf /usr/src/opa/MPI/do_build 2>/dev/null"; + system "rm -rf /usr/src/opa/MPI/do_mvapich2_build 2>/dev/null"; + system "rm -rf /usr/src/opa/MPI/do_openmpi_build 2>/dev/null"; + system "rm -rf /usr/src/opa/MPI/.mpiinfo 2>/dev/null"; + + system "rmdir /usr/src/opa/MPI 2>/dev/null"; # remove only if empty + system "rmdir /usr/src/opa 2>/dev/null"; # remove only if empty + } + + $ComponentWasInstalled{'mpisrc'}=0; +} diff --git a/CommonInstall/comp_qlgc_fm.pl b/CommonInstall/comp_qlgc_fm.pl new file mode 100755 index 0000000..c7473ab --- /dev/null +++ b/CommonInstall/comp_qlgc_fm.pl @@ -0,0 +1,180 @@ +#!/usr/bin/perl +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] +use strict; +#use Term::ANSIColor; +#use Term::ANSIColor qw(:constants); +#use File::Basename; +#use Math::BigInt; + +# ========================================================================== +# OPA FM for OFA installation + +# autostart functions are per subcomponent +# determine if the given capability is configured for Autostart at boot +sub IsAutostart2_opafm() +{ + return IsAutostart("opafm"); +} +sub autostart_desc_opafm() +{ + return "$ComponentInfo{'opafm'}{'Name'} (opafm)"; +} +# enable autostart for the given capability +sub enable_autostart2_opafm() +{ + enable_autostart("opafm"); +} +# disable autostart for the given capability +sub disable_autostart2_opafm() +{ + disable_autostart("opafm"); +} + +sub get_rpms_dir_opafm +{ + my $srcdir=$ComponentInfo{'opafm'}{'SrcDir'}; + return "$srcdir/RPMS/*"; +} + +sub available_opafm +{ + my $srcdir=$ComponentInfo{'opafm'}{'SrcDir'}; + return (rpm_resolve("$srcdir/RPMS/*/opa-fm", "any") ne ""); +} + +sub installed_opafm +{ + return rpm_is_installed("opa-fm", "any"); +} + +# only called if installed_opafm is true +sub installed_version_opafm +{ + my $version = rpm_query_version_release_pkg("opa-fm"); + return dot_version("$version"); +} + +# only called if available_opafm is true +sub media_version_opafm +{ + my $srcdir=$ComponentInfo{'opafm'}{'SrcDir'}; + my $rpmfile = rpm_resolve("$srcdir/RPMS/*/opa-fm", "any"); + my $version= rpm_query_version_release("$rpmfile"); + # assume media properly built with matching versions + return dot_version("$version"); +} + +sub build_opafm +{ + my $osver = $_[0]; + my $debug = $_[1]; # enable extra debug of build itself + my $build_temp = $_[2]; # temp area for use by build + my $force = $_[3]; # force a rebuild + my $srcdir=$ComponentInfo{'opafm'}{'SrcDir'}; + + return 0; # success +} + +sub need_reinstall_opafm($$) +{ + my $install_list = shift(); # total that will be installed when done + my $installing_list = shift(); # what items are being installed/reinstalled + + return "no"; +} + +sub preinstall_opafm +{ + my $install_list = $_[0]; # total that will be installed when done + my $installing_list = $_[1]; # what items are being installed/reinstalled + my $srcdir=$ComponentInfo{'opafm'}{'SrcDir'}; + + return 0; # success +} + +sub install_opafm +{ + my $install_list = $_[0]; # total that will be installed when done + my $installing_list = $_[1]; # what items are being installed/reinstalled + + my $version=media_version_opafm(); + chomp $version; + + printf("Installing $ComponentInfo{'opafm'}{'Name'} $version $DBG_FREE...\n"); + LogPrint "Installing $ComponentInfo{'opafm'}{'Name'} $version $DBG_FREE for $CUR_OS_VER\n"; + + # because RPM will change autostart settings of opafm we need to save + # and restore the settings + my $fm_start = IsAutostart2_opafm(); + + # Install the rpm + install_comp_rpms('opafm', " -U ", $install_list); + + check_rpm_config_file("$CONFIG_DIR/opa-fm/opafm.xml", "/etc/sysconfig"); + check_rpm_config_file("$CONFIG_DIR/opa-fm/opafm_pp.xml"); + check_dir("/usr/lib/opa"); + + if ($fm_start) { + enable_autostart("opafm"); + } else { + disable_autostart("opafm"); + } + + $ComponentWasInstalled{'opafm'}=1; +} + +sub postinstall_opafm +{ + my $install_list = $_[0]; # total that will be installed when done + my $installing_list = $_[1]; # what items are being installed/reinstalled +} + +sub uninstall_opafm +{ + my $install_list = $_[0]; # total that will be left installed when done + my $uninstalling_list = $_[1]; # what items are being uninstalled + + NormalPrint("Uninstalling $ComponentInfo{'opafm'}{'Name'}...\n"); + + uninstall_comp_rpms('opafm', '', $install_list, $uninstalling_list, 'verbose'); + # just in case, newer rpms should clean these up + system("rm -rf /usr/lib/opa/.comp_opafm.pl"); + system("rmdir -p /opt/iba/fm_tools 2>/dev/null"); # remove only if empty + system("rm -rf /usr/lib/opa-fm"); + $ComponentWasInstalled{'opafm'}=0; +} + +sub check_os_prereqs_opafm +{ + return rpm_check_os_prereqs("opafm", "user"); +} + diff --git a/CommonInstall/do_build.sh b/CommonInstall/do_build.sh new file mode 100755 index 0000000..548c2a2 --- /dev/null +++ b/CommonInstall/do_build.sh @@ -0,0 +1,135 @@ +#!/bin/bash +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2018, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] + +# rebuild selected MPI to target a specific compiler + +Usage() +{ + echo "Usage: do_build [-d] [-Q] [mpi [config_opt [install_dir]]]" >&2 + echo " -d - use default settings for selected MPI's options" >&2 + echo " if omitted, will be prompted for each option" >&2 + echo " -Q - build the MPI targeted for the PSM API." >&2 + echo " mpi - MPI to build (mvapich, mvapich2 or openmpi)" >&2 + echo " config_opt - a compiler selection option (gcc, pathscale, pgi or intel)" >&2 + echo " if config_opt is not specified, the user will be prompted" >&2 + echo " based on compilers found on this system" >&2 + echo " install_dir - where to install MPI, see MPICH_PREFIX below" >&2 + echo "" >&2 + echo "Environment:" >&2 + echo " STACK_PREFIX - where to find IB stack." >&2 + echo " BUILD_DIR - temporary directory to use during build of MPI" >&2 + echo " Default is /var/tmp/Intel-mvapich or /var/tmp/Intel-mvapich2" >&2 + echo " or /var/tmp/Intel-openmpi" >&2 + echo " MPICH_PREFIX - selects location for installed MPI" >&2 + echo " default is /usr/mpi//-" >&2 + echo " where COMPILER is selected compiler (gcc, pathscale, etc above)" >&2 + echo " MPI is mvapich, mvapich2 or openmpi" >&2 + echo " and VERSION is MPI version (eg. 1.0.0)" >&2 + echo " CONFIG_OPTIONS - additional configuration options to be" >&2 + echo " specified to srpm (not applicable to mvapich)" >&2 + echo " Default is ''" >&2 + echo " INSTALL_ROOT - location of system image in which to install." >&2 + echo " Default is '/'" >&2 + echo "" >&2 + echo "The RPMs built during this process will be installed on this system" >&2 + echo "they can also be found in /usr/src/opa/MPI" >&2 + exit 2 +} + +build_opts= +while getopts "Qd" o +do + case "$o" in + d) build_opts="$build_opts -d";; + Q) build_opts="$build_opts -Q";; + *) Usage;; + esac +done +shift $((OPTIND -1)) +if [ $# -gt 3 ] +then + Usage +fi + +if [ "$(/usr/bin/id -u)" != 0 ] +then + echo "You must be 'root' to run this program" >&2 + exit 1 +fi +cd /usr/src/opa/MPI +if [ $? != 0 ] +then + echo "Unable to cd to /usr/src/opa/MPI" >&2 + exit 1 +fi + +echo +echo "IFS MPI Library/Tools rebuild" +mpi="$1" +compiler="$2" +if [ ! -z "$3" ] +then + export MPICH_PREFIX="$3" +fi + +nompi() +{ + echo "No MPI Build scripts Found, unable to Rebuild MPI" >&2 + exit 1 +} + +if [ -z "$mpi" ] +then + choices="" + for i in openmpi mvapich2 + do + if [ -e do_${i}_build ] + then + choices="$choices $i" + fi + done + if [ x"$choices" = x ] + then + nompi + else + PS3="Select MPI to Build: " + select mpi in $choices + do + case "$mpi" in + mvapich2|openmpi) break;; + esac + done + fi +fi + +./do_${mpi}_build $build_opts "$compiler" +exit $? diff --git a/CommonInstall/do_mvapich2_build.sh b/CommonInstall/do_mvapich2_build.sh new file mode 100755 index 0000000..4cc34b1 --- /dev/null +++ b/CommonInstall/do_mvapich2_build.sh @@ -0,0 +1,721 @@ +#!/bin/bash +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2018, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# This file incorporates work covered by the following copyright and permission notice + +#[ICS VERSION STRING: unknown] + +# Copyright (c) 2006 Mellanox Technologies. All rights reserved. +# +# This Software is licensed under one of the following licenses: +# +# 1) under the terms of the "Common Public License 1.0" a copy of which is +# available from the Open Source Initiative, see +# http://www.opensource.org/licenses/cpl.php. +# +# 2) under the terms of the "The BSD License" a copy of which is +# available from the Open Source Initiative, see +# http://www.opensource.org/licenses/bsd-license.php. +# +# 3) under the terms of the "GNU General Public License (GPL) Version 2" a +# copy of which is available from the Open Source Initiative, see +# http://www.opensource.org/licenses/gpl-license.php. +# +# Licensee has the right to choose one of the above licenses. +# +# Redistributions of source code must retain the above copyright +# notice and one of the license notices. +# +# Redistributions in binary form must reproduce both the above copyright +# notice, one of the license notices in the documentation +# and/or other materials provided with the distribution. + + +# rebuild MVAPICH2 to target a specific compiler + +ID="" +VERSION_ID="" + +if [ -e /etc/os-release ]; then + . /etc/os-release +else + echo /etc/os-release is not available !!! +fi + +if [[ ( "$ID" == "rhel" && $(echo "$VERSION_ID > 7.3" | bc -l) == 1 ) || \ + ( "$ID" == "sles" && $(echo "$VERSION_ID > 12.2" | bc -l) == 1 ) ]]; then + PREREQ=("rdma-core-devel" "mpi-selector") +else + PREREQ=("libibverbs-devel" "librdmacm-devel" "mpi-selector") +fi + +CheckPreReqs() +{ + e=0; + i=0; + while [ $i -lt ${#PREREQ[@]} ]; do + rpm -q ${PREREQ[$i]} >/dev/null + if [ $? -ne 0 ]; then + if [ $e -eq 0 ]; then + echo + fi + echo "ERROR: Before re-compiling mvapich2 you must first install the ${PREREQ[$i]} package." >&2 + e+=1; + fi + i=$((i+1)) + done + + if [ $e -ne 0 ]; then + if [ $e -eq 1 ]; then + echo "ERROR: Cannot build. Please install the missing package before re-trying." >&2 + else + echo "ERROR: Cannot build. Please install the listed packages before re-trying." >&2 + fi + echo + exit 2 + fi +} + +Usage() +{ + echo "Usage: do_mvapich2_build [-d] [-Q|-O] [config_opt [install_dir]]" >&2 + echo " -d - use default settings for various MVAPICH2 capabilities" >&2 + echo " if omitted, will be prompted for each capability" >&2 + echo " -Q - build the MPI targeted for the PSM API." >&2 + echo " -O - build the MPI targeted for the PSM2 API." >&2 + echo " config_opt - a compiler selection option (gcc, pathscale, pgi or intel)" >&2 + echo " if config_opt is not specified, the user will be prompted" >&2 + echo " based on compilers found on this system" >&2 + echo " install_dir - where to install MPI, see MPICH_PREFIX below" >&2 + echo "" >&2 + echo "Environment:" >&2 + echo " STACK_PREFIX - where to find IB stack." >&2 + echo " BUILD_DIR - temporary directory to use during build of MPI" >&2 + echo " Default is /var/tmp/Intel-mvapich2" >&2 + echo " MPICH_PREFIX - selects location for installed MPI" >&2 + echo " default is /usr/mpi//mvapich2-" >&2 + echo " where COMPILER is selected compiler (gcc, pathscale, etc above)" >&2 + echo " VERSION is mvapich2 version (eg. 1.0.0)" >&2 + echo " CONFIG_OPTIONS - additional MVAPICH2 configuration options to be" >&2 + echo " specified to srpm" >&2 + echo " Default is ''" >&2 + echo " INSTALL_ROOT - location of system image in which to install." >&2 + echo " Default is '/'" >&2 + echo "" >&2 + echo "The RPMs built during this process will be installed on this system" >&2 + echo "they can also be found in /usr/src/opa/MPI" >&2 + exit 2 +} + +unset MAKEFLAGS + +# fixup possible missing path to X11 +export PATH=$PATH:/usr/X11R6/bin + +ARCH=$(uname -m | sed -e s/ppc/PPC/ -e s/powerpc/PPC/ -e s/i.86/IA32/ -e s/ia64/IA64/ -e s/x86_64/X86_64/) + +target_cpu=$(rpm --eval '%{_target_cpu}') +dist_rpm_rel_int=0 +if [ "$ARCH" = "PPC64" -a -f /etc/issue ] +then + # needed to test for SLES 10 SP1 on PPC64 below + dist_rpm_rel=$(rpm --queryformat "[%{RELEASE}]\n" -q $(rpm -qf /etc/issue)|uniq) + dist_rpm_rel_major="$(echo $dist_rpm_rel|cut -f1 -d.)" + dist_rpm_rel_minor="$(echo $dist_rpm_rel|cut -f2 -d.)" + # convert version to a 4 digit integer + if [ $dist_rpm_rel_major -lt 10 ] + then + dist_rpm_rel_major="0$dist_rpm_rel_major"; + fi + if [ $dist_rpm_rel_minor -lt 10 ] + then + dist_rpm_rel_minor="0$dist_rpm_rel_minor"; + fi + dist_rpm_rel_int="$dist_rpm_rel_major$dist_rpm_rel_minor" +fi + +nofort() +{ + echo "ERROR: No Fortran Compiler Found, unable to Rebuild MVAPICH2 MPI" >&2 + exit 1 +} + +# determine if the given tool/compiler exists in the PATH +have_comp() +{ + type $1 > /dev/null 2>&1 + return $? +} + +# global $ans set to 1 for yes or 0 for no +get_yes_no() +{ + local prompt default input + prompt="$1" + default="$2" + while true + do + echo -n "$prompt [$default]:" + read input + if [ "x$input" = x ] + then + input="$default" + fi + case "$input" in + [Yy]*) ans=1; break;; + [Nn]*) ans=0; break;; + esac + done +} + +skip_prompt=n +iflag=n # undocumented option, build in context of install +Qflag=n +Oflag=n +xflag=n # undocumented option, source intel compiler environment +Vflag=n # undocumented option, build verbs only transport +while getopts "idQOV" o +do + case "$o" in + i) iflag=y;; + Q) Qflag=y;; + O) Oflag=y;; + V) Vflag=y;; + d) skip_prompt=y;; + x) xflag=y;; + *) Usage;; + esac +done +shift $((OPTIND -1)) +if [ $# -gt 2 ] +then + Usage +fi + +if [[ "$Vflag" == "y" && \ + ( "$Qflag" == "y" || "$Oflag" == "y" ) ]]; then + echo "ERROR: Option -V cannot be used with any other" >&2 + exit 1 +fi + +if [ "$(/usr/bin/id -u)" != 0 ] +then + echo "ERROR: You must be 'root' to run this program" >&2 + exit 1 +fi +if [ "$iflag" = n ] +then + cd /usr/src/opa/MPI + if [ $? != 0 ] + then + echo "ERROR: Unable to cd to /usr/src/opa/MPI" >&2 + exit 1 + fi +fi + +echo +echo "IFS MVAPICH2 MPI Library/Tools rebuild" + +if [ x"$1" != x"" ] +then + compiler="$1" +else + compiler=none + choices="" + if have_comp gcc && { have_comp g77 || have_comp gfortran; } + then + choices="$choices gcc" + fi + if have_comp pathcc && have_comp pathcCC && have_comp pathf90 + then + choices="$choices pathscale" + fi + if have_comp pgcc && have_comp pgf77 && have_comp pgf90 + then + choices="$choices pgi" + fi + if have_comp icc && have_comp icpc && have_comp ifort + then + choices="$choices intel" + fi + if [ x"$choices" = x ] + then + nofort + else + PS3="Select Compiler: " + select compiler in $choices + do + case "$compiler" in + gcc|pathscale|pgi|intel) break;; + esac + done + fi +fi + +case "$compiler" in +gcc|pathscale|pgi|intel) >/dev/null;; +*) + echo "ERROR: Invalid Compiler selection: $compiler" >&2 + exit 1;; +esac +shift +if [ ! -z "$1" ] +then + export MPICH_PREFIX="$1" +fi + +# set up intel compiler environment +if [ "$compiler" == "intel" -a "$xflag" == "y" ]; then + source /opt/intel/bin/compilervars.sh intel64 +fi + +PS3="Select MVAPICH2 Transport : " +choices='' +mvapich2_conf_impl='' +mvapich2_conf_impl_define='' +# Now get MVAPICH2 capability options. Note that you can't build for +# TrueScale and Omnipath at the same time. +if [ "$Vflag" == y ] +then + interface=verbs + mvapich2_conf_impl='ofa' + +elif [ "$skip_prompt" == "n" -a "$Qflag" == "n" -a "$Oflag" == "n" ] +then + echo + # only have a choice if psm is installed + if rpm -qa|grep infinipath-psm-devel >/dev/null 2>&1 + then + choices+=("ts-psm") + PS3="Select MVAPICH2 Transport: " + fi + if rpm -qa|grep libpsm2-devel >/dev/null 2>&1 + then + choices+=("opa-psm2") + PS3="Select MVAPICH2 Transport: " + fi + if [ ${#choices[@]} -gt 0 ] + then + select mvapich2_conf_impl in ${choices[*]} + do + case "$mvapich2_conf_impl" in + ts-psm) + interface=psm + Qflag=y + Oflag=n + break;; + opa-psm2) + interface=psm + Oflag=y + Qflag=n + break;; + esac + done + else + echo "ERROR: No RDMA stack available." + exit 1 + fi +else # Default to PSM2 + interface=psm + Oflag=y +fi + +case $interface in + verbs) + mvapich2_conf_impl_define="impl ofa" + mvapich2_path_suffix= + mvapich2_rpm_suffix= + ;; + psm) + mvapich2_conf_impl=psm +# mvapich2_conf_impl_define="channel ch3:psm" + mvapich2_conf_psm= + if [ "$Oflag" == "y" ] + then + # PSM2 indicated by hfi suffix so user can ID from PSM and verbs MPIs + mvapich2_conf_impl_define="impl psm2" + mvapich2_path_suffix="-hfi" + mvapich2_rpm_suffix="_hfi" + PREREQ+=('libpsm2-devel') + else + # PSM indicated by qlc suffix so user can ID from PSM2 and verbs MPIs + mvapich2_conf_impl_define="impl psm" + mvapich2_path_suffix="-qlc" + mvapich2_rpm_suffix="_qlc" + PREREQ+=('infinipath-psm-devel') + fi + ;; +esac + +CheckPreReqs + +if [ "$skip_prompt" = y ] +then + mvapich2_conf_romio=1 + mvapich2_conf_shared_libs=1 + mvapich2_conf_ckpt=0 + mvapich2_conf_blcr_home="" +else + get_yes_no "Enable ROMIO support" "y" + mvapich2_conf_romio=$ans + + get_yes_no "Enable shared library support" "y" + mvapich2_conf_shared_libs=$ans + + if [ "$mvapich2_conf_impl" = "ofa" ] + then + while true + do + get_yes_no "Enable Checkpoint-Restart support" "n" + mvapich2_conf_ckpt=$ans + if [ $ans = 1 ] + then + echo -n "BLCR installation directory [or NONE if not installed]:" + read mvapich2_conf_blcr_home + if [ "$mvapich2_conf_blcr_home" = NONE -o x"$mvapich2_conf_blcr_home" = x ] + then + mvapich2_conf_blcr_home="" + elif [ ! -d "$mvapich2_conf_blcr_home" ] + then + echo "$mvapich2_conf_blcr_home: Not Found" + else + break + fi + else + mvapich2_conf_ckpt=0 + break + fi + done + fi +fi + +if [ "$ARCH" = "PPC64" -a \ + \( ! -f /etc/SuSE-release -o "$dist_rpm_rel_int" -le "1502" \) ] # eg. 15.2 +then + export LDFLAGS="-m64 -g -O2 -L/usr/lib64 -L/usr/X11R6/lib64" + export CFLAGS="-m64 -g -O2" + export CPPFLAGS="-m64 -g -O2" + export CXXFLAGS="-m64 -g -O2" + export FFLAGS="-m64 -g -O2" + export FCFLAGS="-m64 -g -O2" + export LDLIBS="-m64 -g -O2 -L/usr/lib64 -L/usr/X11R6/lib64" +else + # just to be safe + unset LDFLAGS + unset CFLAGS + unset CPPFLAGS + unset CXXFLAGS + unset FFLAGS + unset FCFLAGS + unset LDLIBS +fi + +logfile=make.mvapich2.$interface.$compiler +( + STACK_PREFIX=${STACK_PREFIX:-/usr} + BUILD_DIR=${BUILD_DIR:-/var/tmp/Intel-mvapich2} + BUILD_ROOT="$BUILD_DIR/build"; + RPM_DIR="$BUILD_DIR/OFEDRPMS"; + DESTDIR=/usr/src/opa/MPI + if [ "$iflag" = n ] + then + mvapich2_srpm=/usr/src/opa/MPI/mvapich2-*.src.rpm + mpitests_srpm=/usr/src/opa/MPI/mpitests-*.src.rpm + else + mvapich2_srpm=./SRPMS/mvapich2-*.src.rpm + mpitests_srpm=./SRPMS/mpitests-*.src.rpm + fi + mvapich2_version=$(ls $mvapich2_srpm 2>/dev/null|head -1|cut -f2 -d-) + mvapich2_fullversion=$(ls $mvapich2_srpm 2>/dev/null|head -1|cut -f2- -d-|sed -e 's/.src.rpm//') + mpitests_version=$(ls $mpitests_srpm 2>/dev/null|head -1|cut -f2 -d-) + mpitests_fullversion=$(ls $mpitests_srpm 2>/dev/null|head -1|cut -f2- -d-|sed -e 's/.src.rpm//') + MPICH_PREFIX=${MPICH_PREFIX:-$STACK_PREFIX/mpi/$compiler/mvapich2-$mvapich2_version$mvapich2_path_suffix} + CONFIG_OPTIONS=${CONFIG_OPTIONS:-""} + + if [ x"$mvapich2_version" = x"" ] + then + echo "Error $mvapich2_srpm: Not Found" + exit 1 + fi + if [ x"$mpitests_version" = x"" ] + then + echo "Error $mpitests_srpm: Not Found" + exit 1 + fi + + echo "Environment:" + env + echo "==========================================================" + echo + echo "Build Settings:" + echo "STACK_PREFIX='$STACK_PREFIX'" + echo "BUILD_DIR='$BUILD_DIR'" + echo "MPICH_PREFIX='$MPICH_PREFIX'" + echo "CONFIG_OPTIONS='$CONFIG_OPTIONS'" + echo "MVAPICH2 Version: $mvapich2_version" + echo "MVAPICH2 Full Version: $mvapich2_fullversion" + echo "mpitests Version: $mpitests_version" + echo "mpitests Full Version: $mpitests_fullversion" + echo "==========================================================" + if [ "$iflag" = n ] + then + echo "MPICH_PREFIX='$MPICH_PREFIX'"> /usr/src/opa/MPI/.mpiinfo + #echo "MPI_RUNTIME='$MPICH_PREFIX/bin $MPICH_PREFIX/lib $MPICH_PREFIX/tests'">> /usr/src/opa/MPI/.mpiinfo + echo "MPI_RPMS='mvapich2_$compiler$mvapich2_rpm_suffix-$mvapich2_fullversion.$target_cpu.rpm mpitests_mvapich2_$compiler$mvapich2_rpm_suffix-$mpitests_fullversion.$target_cpu.rpm'">> /usr/src/opa/MPI/.mpiinfo + chmod +x /usr/src/opa/MPI/.mpiinfo + fi + + echo + echo "Cleaning build tree..." + rm -rf $BUILD_DIR > /dev/null 2>&1 + + echo "==========================================================" + echo "Building MVAPICH2 MPI $mvapich2_version Library/Tools..." + mkdir -p $BUILD_ROOT $RPM_DIR/BUILD $RPM_DIR/RPMS $RPM_DIR/SOURCES $RPM_DIR/SPECS $RPM_DIR/SRPMS + + disable_auto_requires="" + # need to create proper mvapich2_comp_env value for MVAPICH2 builds + case "$compiler" in + gcc) + if have_comp gfortran + then + if [ "$ARCH" = "PPC64" ] + then + mvapich2_comp_env='CC="gcc -m64" CXX="g++ -m64" F77="gfortran -m64" FC="gfortran -m64"' + else + mvapich2_comp_env='CC=gcc CXX=g++ F77=gfortran FC=gfortran' + if [[ ( "$ID" == "rhel" && $(echo "$VERSION_ID >= 8.0" | bc -l) == 1 ) ]]; then + mvapich2_comp_env="$mvapich2_comp_env CFLAGS='-fPIC'" + fi + fi + else + if [ "$ARCH" = "PPC64" ] + then + mvapich2_comp_env='CC="gcc -m64" CXX="g++ -m64" F77="g77 -m64" FC="/bin/false"' + else + mvapich2_comp_env='CC=gcc CXX=g++ F77=g77 FC=/bin/false' + if [[ ( "$ID" == "rhel" && $(echo "$VERSION_ID >= 8.0" | bc -l) == 1 ) ]]; then + mvapich2_comp_env="$mvapich2_comp_env CFLAGS='-fPIC'" + fi + fi + fi;; + + pathscale) + disable_auto_requires="--define 'disable_auto_requires 1'" + mvapich2_comp_env='CC=pathcc CXX=pathCC F77=pathf90 FC=pathf90' + if [ "$target_cpu" = "i686" && $mvapich2_conf_shared_libs = 1 ] + then + # on i686 with shared libs need -g for MVAPICH2 + mvapich2_comp_env="$mvapich2_comp_env OPT_FLAG='-g'" + fi;; + + pgi) + disable_auto_requires="--define 'disable_auto_requires 1'" + mvapich2_comp_env='CC=pgcc CXX=pgCC F77=pgf77 FC=pgf90';; + + intel) + disable_auto_requires="--define 'disable_auto_requires 1'" + if [ "$mvapich2_conf_shared_libs" = 1 ] + then + mvapich2_comp_env='CC=icc CXX=icpc F77=ifort FC=ifort' + else + mvapich2_comp_env='CC=icc CXX=icpc F77=ifort FC=ifort' + fi;; + + *) + echo "ERROR: Invalid compiler" + exit 1;; + esac + + # HWLOC component auto detects CUDA and will use it if found on the system + # So, tell HWLOC to ignore CUDA: enable_gl=no + pref_env="enable_gl=no" + if [ "$STACK_PREFIX" != "/usr" ] + then + pref_env="$pref_env LD_LIBRARY_PATH=$STACK_PREFIX/lib64:$STACK_PREFIX/lib:\$LD_LIBRARY_PATH" + fi + + cmd="$pref_env rpmbuild --rebuild \ + --define '_topdir $RPM_DIR' \ + --buildroot '$BUILD_ROOT' \ + --define 'build_root $BUILD_ROOT' \ + --target $target_cpu \ + --define '_name mvapich2_$compiler$mvapich2_rpm_suffix' \ + --define 'compiler $compiler' \ + --define '$mvapich2_conf_impl_define' \ + --define 'open_ib_home $STACK_PREFIX' \ + --define '_usr $STACK_PREFIX' \ + --define 'comp_env $mvapich2_comp_env $CONFIG_OPTIONS $mvapich2_conf_psm' \ + --define 'auto_req 0' \ + --define 'mpi_selector $STACK_PREFIX/bin/mpi-selector' \ + --define '_prefix $MPICH_PREFIX'" + #cmd="$cmd --define 'shared_libs $mvapich2_conf_shared_libs'" + if [ "$mvapich2_conf_shared_libs" = 1 ] + then + cmd="$cmd --define 'shared_libs $mvapich2_conf_shared_libs'" + fi + #cmd="$cmd --define 'romio $mvapich2_conf_romio'" + if [ "$mvapich2_conf_romio" = 1 ] + then + cmd="$cmd --define 'romio $mvapich2_conf_romio'" + fi + if [ "$mvapich2_conf_impl" = "ofa" ] + then + cmd="$cmd --define 'rdma --with-rdma=gen2' \ + --define 'ib_include --with-ib-include=$STACK_PREFIX/include'" + if [ "$ARCH" = "PPC64" -o "$ARCH" = "X86_64" ] + then + cmd="$cmd --define 'ib_libpath --with-ib-libpath=$STACK_PREFIX/lib64'" + else + cmd="$cmd --define 'ib_libpath --with-ib-libpath=$STACK_PREFIX/lib'" + fi + if [ "$mvapich2_conf_ckpt" = 1 ] + then + cmd="$cmd --define 'blcr 1'" + cmd="$cmd --define 'blcr_include --with-blcr-include=$mvapich2_conf_blcr_home/include' \ + --define 'blcr_libpath --with-blcr-libpath=$mvapich2_conf_blcr_home/lib'" + fi + elif [ "$mvapich2_conf_impl" = "psm" ] + then + # no special args needed + > /dev/null + else + echo "ERROR: Invalid mvapich2_conf_impl: $mvapich2_conf_impl" >&2 + exit 1 + fi + + cmd="$cmd \ + $mvapich2_srpm" + echo "Executing: $cmd" + eval $cmd + if [ $? != 0 ] + then + echo "error: mvapich2_$compiler$mvapich2_rpm_suffix Build ERROR: bad exit code" + exit 1 + fi + if [ "$iflag" = n ] + then + cp $RPM_DIR/RPMS/$target_cpu/mvapich2_$compiler$mvapich2_rpm_suffix-$mvapich2_fullversion.$target_cpu.rpm $DESTDIR + fi + + echo "==========================================================" + echo "Installing MVAPICH2 MPI $mvapich2_version Library/Tools..." + rpmfile=$RPM_DIR/RPMS/$target_cpu/mvapich2_$compiler$mvapich2_rpm_suffix-$mvapich2_fullversion.$target_cpu.rpm + + # need force for reinstall case + if [ x"$INSTALL_ROOT" != x"" -a x"$INSTALL_ROOT" != x"/" ] + then + tempfile=/var/tmp/rpminstall.tmp.rpm + mkdir -p $INSTALL_ROOT/var/tmp + cp $rpmfile $INSTALL_ROOT$tempfile + chroot /$INSTALL_ROOT rpm -Uv --force $tempfile + rm -f $tempfile + else + rpm -Uv --force $rpmfile + fi + + echo "==========================================================" + echo "Building test programs $mpitests_version for MVAPICH2 MPI $mvapich2_version..." + # mpitests uses buildroot instead of build_root, play it safe for future + # and define both + cmd="$pref_env rpmbuild --rebuild \ + --define '_topdir $RPM_DIR' \ + --buildroot '$BUILD_ROOT' \ + --define 'buildroot $BUILD_ROOT' \ + --define 'build_root $BUILD_ROOT' \ + --target $target_cpu \ + --define '_name mpitests_mvapich2_$compiler$mvapich2_rpm_suffix' \ + --define 'root_path /' \ + --define '_usr $STACK_PREFIX' \ + --define 'path_to_mpihome $MPICH_PREFIX' \ + $disable_auto_requires \ + $mpitests_srpm" + echo "Executing: $cmd" + eval $cmd + if [ $? != 0 ] + then + echo "error: mpitests_mvapich2_$compiler$mvapich2_rpm_suffix Build ERROR: bad exit code" + exit 1 + fi + + if [ "$iflag" = n ] + then + mv $RPM_DIR/RPMS/$target_cpu/mpitests_mvapich2_$compiler$mvapich2_rpm_suffix-$mpitests_fullversion.$target_cpu.rpm $DESTDIR + + echo "==========================================================" + echo "Installing test programs $mpitests_version for MVAPICH2 MPI $mvapich2_version..." + rpmfile=$DESTDIR/mpitests_mvapich2_$compiler$mvapich2_rpm_suffix-$mpitests_fullversion.$target_cpu.rpm + # need force for reinstall case + if [ x"$INSTALL_ROOT" != x"" -a x"$INSTALL_ROOT" != x"/" ] + then + tempfile=/var/tmp/rpminstall.tmp.rpm + mkdir -p $INSTALL_ROOT/var/tmp + cp $rpmfile $INSTALL_ROOT$tempfile + chroot /$INSTALL_ROOT rpm -Uv --force $tempfile + rm -f $tempfile + else + rpm -Uv --force $rpmfile + fi + + rm -rf $BUILD_DIR + fi +) 2>&1|tee $logfile.res +set +x + +# review log for errors and warnings +# disable output of build warnings, way too many +#echo +#echo "Build Warnings:" +# ignore the warning for old C++ header usage in sample programs +egrep 'warning:' $logfile.res |sort -u | + egrep -v 'at least one deprecated or antiquated header.*C\+\+ includes' > $logfile.warn +#cat $logfile.warn +#echo + +if egrep 'error:|Error | Stop' $logfile.res > $logfile.err +then + echo "Build Errors:" + sort -u $logfile.err + echo + echo "FAILED Build, errors detected" + exit 1 +elif [ -s $logfile.warn ] +then + # at present lots of warnings are expected + echo "SUCCESSFUL Build, no errors detected" + exit 0 + + # No warnings are expected + echo "QUESTIONABLE Build, warnings detected" + exit 1 +else + echo "SUCCESSFUL Build, no errors detected" + exit 0 +fi diff --git a/CommonInstall/do_openmpi_build.sh b/CommonInstall/do_openmpi_build.sh new file mode 100755 index 0000000..fad9e14 --- /dev/null +++ b/CommonInstall/do_openmpi_build.sh @@ -0,0 +1,756 @@ +#!/bin/bash +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2018, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# This file incorporates work covered by the following copyright and permission notice + +# [ICS VERSION STRING: unknown] + +# Copyright (c) 2006 Mellanox Technologies. All rights reserved. +# +# This Software is licensed under one of the following licenses: +# +# 1) under the terms of the "Common Public License 1.0" a copy of which is +# available from the Open Source Initiative, see +# http://www.opensource.org/licenses/cpl.php. +# +# 2) under the terms of the "The BSD License" a copy of which is +# available from the Open Source Initiative, see +# http://www.opensource.org/licenses/bsd-license.php. +# +# 3) under the terms of the "GNU General Public License (GPL) Version 2" a +# copy of which is available from the Open Source Initiative, see +# http://www.opensource.org/licenses/gpl-license.php. +# +# Licensee has the right to choose one of the above licenses. +# +# Redistributions of source code must retain the above copyright +# notice and one of the license notices. +# +# Redistributions in binary form must reproduce both the above copyright +# notice, one of the license notices in the documentation +# and/or other materials provided with the distribution. + + +# rebuild OpenMPI to target a specific compiler + +ID="" +VERSION_ID="" + +if [ -e /etc/os-release ]; then + . /etc/os-release +else + echo /etc/os-release is not available !!! +fi + +if [[ ( "$ID" == "rhel" && $(echo "$VERSION_ID > 7.3" | bc -l) == 1 ) || \ + ( "$ID" == "sles" && $(echo "$VERSION_ID > 12.2" | bc -l) == 1 ) ]]; then + PREREQ=("rdma-core-devel" "mpi-selector") +else + PREREQ=("libibverbs-devel" "librdmacm-devel" "mpi-selector") +fi + +CheckPreReqs() +{ + e=0; + i=0; + while [ $i -lt ${#PREREQ[@]} ]; do + rpm -qa | grep ${PREREQ[$i]} >/dev/null + if [ $? -ne 0 ]; then + if [ $e -eq 0 ]; then + echo + fi + echo "ERROR: Before re-compiling OpenMPI you must first install the ${PREREQ[$i]} package." >&2 + e+=1; + fi + i=$((i+1)) + done + + if [ $e -ne 0 ]; then + if [ $e -eq 1 ]; then + echo "ERROR: Cannot build. Please install the missing package before re-trying." >&2 + else + echo "ERROR: Cannot build. Please install the listed packages before re-trying." >&2 + fi + echo + exit 2 + fi +} + +Usage() +{ + echo "Usage: do_openmpi_build [-d] [-Q|-O] [config_opt [install_dir]]" >&2 + echo " -d - use default settings for openmpi options" >&2 + echo " if omitted, will be prompted for each option" >&2 + echo " -Q - build the MPI targeted for the PSM API." >&2 + echo " -O - build the MPI targeted for the Omni-path HFI PSM2 and OFI API." >&2 + echo " -C - build the MPI targeted for the Omnipath HFI PSM with CUDA." >&2 + echo " config_opt - a compiler selection option (gcc, pathscale, pgi or intel)" >&2 + echo " if config_opt is not specified, the user will be prompted" >&2 + echo " based on compilers found on this system" >&2 + echo " install_dir - where to install MPI, see MPICH_PREFIX below" >&2 + echo "" >&2 + echo "Environment:" >&2 + echo " STACK_PREFIX - where to find IB stack." >&2 + echo " BUILD_DIR - temporary directory to use during build of MPI" >&2 + echo " Default is /var/tmp/Intel-openmpi" >&2 + echo " MPICH_PREFIX - selects location for installed MPI" >&2 + echo " default is /usr/mpi//openmpi-" >&2 + echo " where COMPILER is selected compiler (gcc, pathscale, etc above)" >&2 + echo " VERSION is openmpi version (eg. 1.0.0)" >&2 + echo " CONFIG_OPTIONS - additional OpenMPI configuration options to be" >&2 + echo " specified via configure_options parameter to srpm" >&2 + echo " Default is ''" >&2 + echo " INSTALL_ROOT - location of system image in which to install." >&2 + echo " Default is '/'" >&2 + echo "" >&2 + echo "The RPMs built during this process will be installed on this system" >&2 + echo "they can also be found in /usr/src/opa/MPI" >&2 + exit 2 +} + +unset MAKEFLAGS + +ARCH=$(uname -m | sed -e s/ppc/PPC/ -e s/powerpc/PPC/ -e s/i.86/IA32/ -e s/ia64/IA64/ -e s/x86_64/X86_64/) + +target_cpu=$(rpm --eval '%{_target_cpu}') +dist_rpm_rel_int=0 +if [ "$ARCH" = "PPC64" -a -f /etc/issue -a -f /etc/SuSE-release ] +then + # needed to test for SLES 10 SP1 on PPC64 below + dist_rpm_rel=$(rpm --queryformat "[%{RELEASE}]\n" -q $(rpm -qf /etc/issue)|uniq) + dist_rpm_rel_major="$(echo $dist_rpm_rel|cut -f1 -d.)" + dist_rpm_rel_minor="$(echo $dist_rpm_rel|cut -f2 -d.)" + # convert version to a 4 digit integer + if [ $dist_rpm_rel_major -lt 10 ] + then + dist_rpm_rel_major="0$dist_rpm_rel_major"; + fi + if [ $dist_rpm_rel_minor -lt 10 ] + then + dist_rpm_rel_minor="0$dist_rpm_rel_minor"; + fi + dist_rpm_rel_int="$dist_rpm_rel_major$dist_rpm_rel_minor" +fi + +nocomp() +{ + echo "ERROR: No Compiler Found, unable to Rebuild OpenMPI MPI" >&2 + exit 1 +} + +# determine if the given tool/compiler exists in the PATH +have_comp() +{ + type $1 > /dev/null 2>&1 + return $? +} + +# global $ans set to 1 for yes or 0 for no +get_yes_no() +{ + local prompt default input + prompt="$1" + default="$2" + while true + do + echo -n "$prompt [$default]:" + read input + if [ "x$input" = x ] + then + input="$default" + fi + case "$input" in + [Yy]*) ans=1; break;; + [Nn]*) ans=0; break;; + esac + done +} + +skip_prompt=n +iflag=n # undocumented option, build in context of install +Qflag=n +Oflag=n +Cflag=n +Vflag=n # undocumented option, build verbs only transport +while getopts "idQOCV" o +do + case "$o" in + i) iflag=y;; + Q) Qflag=y;; + O) Oflag=y;; + C) Cflag=y;; + V) Vflag=y;; + d) skip_prompt=y;; + *) Usage;; + esac +done +shift $((OPTIND -1)) +if [ $# -gt 2 ] +then + Usage +fi + +if [[ "$Vflag" == "y" && \ + ( "$Qflag" == "y" || "$Oflag" == "y" || "$Cflag" == "y" ) ]]; then + echo "ERROR: Option -V cannot be used with any other" >&2 + exit 1 +fi + +if [ "$(/usr/bin/id -u)" != 0 ] +then + echo "ERROR: You must be 'root' to run this program" >&2 + exit 1 +fi +if [ "$iflag" = n ] +then + cd /usr/src/opa/MPI + if [ $? != 0 ] + then + echo "ERROR: Unable to cd to /usr/src/opa/MPI" >&2 + exit 1 + fi +fi + +echo +echo "IFS OpenMPI MPI Library/Tools rebuild" + +if [ x"$1" != x"" ] +then + compiler="$1" +else + compiler=none + choices="" + # open MPI does not require fortran compiler, so just check for C + if have_comp gcc + then + choices="$choices gcc" + fi + if have_comp pathcc + then + choices="$choices pathscale" + fi + if have_comp pgcc + then + choices="$choices pgi" + fi + if have_comp icc + then + choices="$choices intel" + fi + if [ x"$choices" = x ] + then + nocomp + else + PS3="Select Compiler: " + select compiler in $choices + do + case "$compiler" in + gcc|pathscale|pgi|intel) break;; + esac + done + fi +fi + +case "$compiler" in +gcc|pathscale|pgi|intel) >/dev/null;; +*) + echo "ERROR: Invalid Compiler selection: $compiler" >&2 + exit 1;; +esac +shift +if [ ! -z "$1" ] +then + export MPICH_PREFIX="$1" +fi + +# now get openmpi options. +if [ "$Vflag" != y ] +then + if [ "$skip_prompt" != y -a "$Qflag" != y ] + then + if rpm -qa|grep infinipath-psm-devel >/dev/null 2>&1 + then + echo + get_yes_no "Build for True Scale HCA PSM" "y" + if [ "$ans" = 1 ] + then + Qflag=y + fi + fi + fi + + if [ "$skip_prompt" != y -a "$Oflag" != y ] + then + if rpm -qa|grep libpsm2-devel >/dev/null 2>&1 && + rpm -qa|grep libfabric-devel >/dev/null 2>&1 + then + echo + get_yes_no "Build for Omnipath HFI PSM2 and OFI" "y" + if [ "$ans" = 1 ] + then + Oflag=y + fi + fi + fi + + if [ "$skip_prompt" != y -a "$Cflag" != y ] + then + if rpm -qa|grep libpsm2-devel >/dev/null 2>&1 && + rpm -qa|grep cuda-cudart-dev >/dev/null 2>&1 + then + echo + get_yes_no "Build for Omnipath HFI PSM2 with Cuda" "y" + if [ "$ans" = 1 ] + then + Cflag=y + fi + fi + fi +fi +# if -d (skip_prompt) the only option provided, ./configure will run with +# no paramters and build what is auto-detected + +openmpi_conf_psm='' + +if [ "$Vflag" = y ] +then + # The openmpi configure script complains about enable-mca-no-build + # not being a supported option, but then actually executes it correctly. + #openmpi_conf_psm='--enable-mca-no-build=mtl-psm' + openmpi_conf_psm='--with-psm=no --with-psm2=no --with-libfabric=no --enable-mca-no-build=mtl-psm ' + openmpi_path_suffix= + openmpi_rpm_suffix= + interface=verbs +else + if [ "$Qflag" = y ] + then + PREREQ+=('infinipath-psm-devel') + openmpi_conf_psm='--with-psm=/usr ' + # PSM indicated by qlc suffix so user can ID PSM vs verbs or PSM2 MPIs + openmpi_path_suffix="-qlc" + openmpi_rpm_suffix="_qlc" + interface=psm + fi + + if [ "$Oflag" = y ] + then + PREREQ+=('libpsm2-devel' 'libfabric-devel') + openmpi_conf_psm=" $openmpi_conf_psm --with-psm2=/usr --with-libfabric=/usr " + # PSM2 indicated by hfi suffix so user can ID from PSM or verbs MPIs + openmpi_path_suffix="-hfi" + openmpi_rpm_suffix="_hfi" + interface=psm + fi + + if [ "$Cflag" = y ] + then + PREREQ+=('libpsm2-devel' 'cuda-cudart-dev') + openmpi_conf_psm=" $openmpi_conf_psm --with-psm2=/usr --with-cuda=/usr/local/cuda " + # CUDA indicated by -cuda suffix so user can ID from PSM2 without cuda, PSM or verbs MPIs + openmpi_path_suffix="-cuda-hfi" + openmpi_rpm_suffix="_cuda_hfi" + interface=psm + fi +fi + +CheckPreReqs + +if [ "$ARCH" = "PPC64" -a \ + \( ! -f /etc/SuSE-release -o "$dist_rpm_rel_int" -le "1502" \) ] # eg. 15.2 +then + export LDFLAGS="-m64 -g -O2 -L/usr/lib64 -L/usr/X11R6/lib64" + export CFLAGS="-m64 -g -O2" + export CPPFLAGS="-m64 -g -O2" + export CXXFLAGS="-m64 -g -O2" + export FFLAGS="-m64 -g -O2" + export F90FLAGS="-m64 -g -O2" + export LDLIBS="-m64 -g -O2 -L/usr/lib64 -L/usr/X11R6/lib64" +else + # just to be safe + unset LDFLAGS + unset CFLAGS + unset CPPFLAGS + unset CXXFLAGS + unset FFLAGS + unset F90FLAGS + unset LDLIBS +fi + +logfile=make.openmpi.$interface.$compiler +( + STACK_PREFIX=${STACK_PREFIX:-/usr} + BUILD_DIR=${BUILD_DIR:-/var/tmp/Intel-openmpi} + BUILD_ROOT="$BUILD_DIR/build"; + RPM_DIR="$BUILD_DIR/OFEDRPMS"; + DESTDIR=/usr/src/opa/MPI + if [ "$iflag" = n ] + then + openmpi_srpm=/usr/src/opa/MPI/openmpi-*.src.rpm + mpitests_srpm=/usr/src/opa/MPI/mpitests-*.src.rpm + else + openmpi_srpm=./SRPMS/openmpi-*.src.rpm + mpitests_srpm=./SRPMS/mpitests-*.src.rpm + fi + openmpi_version=$(ls $openmpi_srpm 2>/dev/null|head -1|cut -f2 -d-) + + # For RHEL7x: %{?dist} resolves to '.el7'. For SLES, an empty string + # E.g. on rhel7.x: openmpi_gcc_hfi-2.1.2-11.el7.x86_64.rpm; on SLES openmpi_gcc_hfi-2.1.2-11.x86_64.rpm + openmpi_fullversion=$(ls $openmpi_srpm 2>/dev/null|head -1|cut -f2- -d-|sed -e 's/.src.rpm//')$(rpm --eval %{?dist}) + mpitests_version=$(ls $mpitests_srpm 2>/dev/null|head -1|cut -f2 -d-) + mpitests_fullversion=$(ls $mpitests_srpm 2>/dev/null|head -1|cut -f2- -d-|sed -e 's/.src.rpm//') + MPICH_PREFIX=${MPICH_PREFIX:-$STACK_PREFIX/mpi/$compiler/openmpi-$openmpi_version$openmpi_path_suffix} + CONFIG_OPTIONS=${CONFIG_OPTIONS:-""} + + if [ x"$openmpi_version" = x"" ] + then + echo "Error $openmpi_srpm: Not Found" + exit 1 + fi + if [ x"$mpitests_version" = x"" ] + then + echo "Error $mpitests_srpm: Not Found" + exit 1 + fi + + echo "Environment:" + env + echo "==========================================================" + echo + echo "Build Settings:" + echo "STACK_PREFIX='$STACK_PREFIX'" + echo "BUILD_DIR='$BUILD_DIR'" + echo "MPICH_PREFIX='$MPICH_PREFIX'" + echo "CONFIG_OPTIONS='$CONFIG_OPTIONS'" + echo "OpenMPI Version: $openmpi_version" + echo "OpenMPI Full Version: $openmpi_fullversion" + echo "mpitests Version: $mpitests_version" + echo "mpitests Full Version: $mpitests_fullversion" + echo "==========================================================" + if [ "$iflag" = n ] + then + echo "MPICH_PREFIX='$MPICH_PREFIX'"> /usr/src/opa/MPI/.mpiinfo + #echo "MPI_RUNTIME='$MPICH_PREFIX/bin $MPICH_PREFIX/lib* $MPICH_PREFIX/etc $MPICH_PREFIX/share $MPICH_PREFIX/tests'">> /usr/src/opa/MPI/.mpiinfo + echo "MPI_RPMS='openmpi_$compiler$openmpi_rpm_suffix-$openmpi_fullversion.$target_cpu.rpm mpitests_openmpi_$compiler$openmpi_rpm_suffix-$mpitests_fullversion.$target_cpu.rpm'">> /usr/src/opa/MPI/.mpiinfo + chmod +x /usr/src/opa/MPI/.mpiinfo + fi + + echo + echo "Cleaning build tree..." + rm -rf $BUILD_DIR > /dev/null 2>&1 + + echo "==========================================================" + echo "Building OpenMPI MPI $openmpi_version Library/Tools..." + mkdir -p $BUILD_ROOT $RPM_DIR/BUILD $RPM_DIR/RPMS $RPM_DIR/SOURCES $RPM_DIR/SPECS $RPM_DIR/SRPMS + + if [ "$ARCH" = "PPC64" -o "$ARCH" = "X86_64" ] + then + openmpi_lib="lib64" + else + openmpi_lib="lib" + fi + + use_default_rpm_opt_flags=1 + disable_auto_requires="" + openmpi_ldflags="" + openmpi_wrapper_cxx_flags="" + + # need to create proper openmpi_comp_env value for OpenMPI builds + if [ "$ARCH" = "PPC64" -a \ + \( -f /etc/SuSE-release -a "$dist_rpm_rel_int" -gt "1502" \) ] # eg. 15.2 + then + openmpi_comp_env='LDFLAGS="-m64 -O2 -L/usr/lib/gcc/powerpc64-suse-linux/4.1.2/64"' + else + openmpi_comp_env="" + fi + + case "$compiler" in + gcc) + if [[ ( "$ID" == "rhel" && $(echo "$VERSION_ID >= 8.0" | bc -l) == 1 ) ]]; then + openmpi_comp_env="$openmpi_comp_env CC=gcc CFLAGS="-O3 -fPIC"" + else + openmpi_comp_env="$openmpi_comp_env CC=gcc CFLAGS=-O3" + fi + if have_comp g++ + then + openmpi_comp_env="$openmpi_comp_env CXX=g++" + else + openmpi_comp_env="$openmpi_comp_env --disable-mpi-cxx" + fi + if have_comp gfortran + then + openmpi_comp_env="$openmpi_comp_env F77=gfortran FC=gfortran" + elif have_comp g77 + then + openmpi_comp_env="$openmpi_comp_env F77=g77 --disable-mpi-f90" + else + openmpi_comp_env="$openmpi_comp_env --disable-mpi-f77 --disable-mpi-f90" + fi;; + + pathscale) + openmpi_comp_env="$openmpi_comp_env CC=pathcc" + disable_auto_requires="--define 'disable_auto_requires 1'" + if have_comp pathCC + then + openmpi_comp_env="$openmpi_comp_env CXX=pathCC" + else + openmpi_comp_env="$openmpi_comp_env --disable-mpi-cxx" + fi + if have_comp pathf90 + then + openmpi_comp_env="$openmpi_comp_env F77=pathf90 FC=pathf90" + else + openmpi_comp_env="$openmpi_comp_env --disable-mpi-f77 --disable-mpi-f90" + fi + # test for fedora core 6 or redhat EL5 + if { [ -f /etc/fedora-release ] && { uname -r|grep fc6; }; } \ + || { [ -f /etc/redhat-release ] && { uname -r|grep el5; }; } + then + use_default_rpm_opt_flags=0 + fi;; + + pgi) + disable_auto_requires="--define 'disable_auto_requires 1'" + openmpi_comp_env="$openmpi_comp_env CC=pgcc" + use_default_rpm_opt_flags=0 + if have_comp pgCC + then + openmpi_comp_env="$openmpi_comp_env CXX=pgCC" + # See http://www.pgroup.com/userforum/viewtopic.php?p=2371 + openmpi_wrapper_cxx_flags="-fpic" + else + openmpi_comp_env="$openmpi_comp_env --disable-mpi-cxx" + fi + if have_comp pgf77 + then + openmpi_comp_env="$openmpi_comp_env F77=pgf77" + else + openmpi_comp_env="$openmpi_comp_env --disable-mpi-f77" + fi + if have_comp pgf90 + then + openmpi_comp_env="$openmpi_comp_env FC=pgf90 FCFLAGS=-O2" + else + openmpi_comp_env="$openmpi_comp_env --disable-mpi-f90" + fi;; + + intel) + disable_auto_requires="--define 'disable_auto_requires 1'" + openmpi_comp_env="$openmpi_comp_env CC=icc" + if have_comp icpc + then + openmpi_comp_env="$openmpi_comp_env CXX=icpc" + else + openmpi_comp_env="$openmpi_comp_env --disable-mpi-cxx" + fi + if have_comp ifort + then + openmpi_comp_env="$openmpi_comp_env F77=ifort FC=ifort" + else + openmpi_comp_env="$openmpi_comp_env --disable-mpi-f77 --disable-mpi-f90" + fi;; + + *) + echo "ERROR: Invalid compiler" + exit 1;; + esac + + if [ "$ARCH" = "PPC64" ] + then + openmpi_comp_env="$openmpi_comp_env --disable-mpi-f77 --disable-mpi-f90" + # In the ppc64 case, add -m64 to all the relevant + # flags because it's not the default. Also + # unconditionally add $OMPI_RPATH because even if + # it's blank, it's ok because there are other + # options added into the ldflags so the overall + # string won't be blank. + openmpi_comp_env="$openmpi_comp_env CFLAGS=\"-m64 -O2\" CXXFLAGS=\"-m64 -O2\" FCFLAGS=\"-m64 -O2\" FFLAGS=\"-m64 -O2\"" + openmpi_comp_env="$openmpi_comp_env --with-wrapper-ldflags=\"-g -O2 -m64 -L/usr/lib64\" --with-wrapper-cflags=-m64" + openmpi_comp_env="$openmpi_comp_env --with-wrapper-cxxflags=-m64 --with-wrapper-fflags=-m64 --with-wrapper-fcflags=-m64" + openmpi_wrapper_cxx_flags="$openmpi_wrapper_cxx_flags -m64"; + fi + + openmpi_comp_env="$openmpi_comp_env --enable-mpirun-prefix-by-default" + if [ x"$openmpi_wrapper_cxx_flags" != x ] + then + openmpi_comp_env="$openmpi_comp_env --with-wrapper-cxxflags=\"$openmpi_wrapper_cxx_flags\"" + fi + + pref_env= + if [ "$STACK_PREFIX" != "/usr" ] + then + pref_env="$pref_env LD_LIBRARY_PATH=$STACK_PREFIX/lib64:$STACK_PREFIX/lib:\$LD_LIBRARY_PATH" + fi + + if [ "$Cflag" = y ] + then + pref_env="$pref_env MPI_STRESS_CUDA=1" + else + # HWLOC component auto detects CUDA and will use it even if it is NOT + # a CUDA OMPI build. So, tell HWLOC to ignore CUDA (if found on the system) + # when not creating a CUDA build. + pref_env="$pref_env enable_gl=no" + fi + + cmd="$pref_env rpmbuild --rebuild \ + --define '_topdir $RPM_DIR' \ + --buildroot '$BUILD_ROOT' \ + --define 'build_root $BUILD_ROOT' \ + --target $target_cpu \ + --define '_name openmpi_$compiler$openmpi_rpm_suffix' \ + --define 'compiler $compiler' \ + --define 'mpi_selector $STACK_PREFIX/bin/mpi-selector' \ + --define 'use_mpi_selector 1' \ + --define 'install_shell_scripts 1' \ + --define 'shell_scripts_basename mpivars' \ + --define '_usr $STACK_PREFIX' \ + --define 'ofed 0' \ + --define '_prefix $MPICH_PREFIX' \ + --define '_defaultdocdir $MPICH_PREFIX/doc/..' \ + --define '_mandir %{_prefix}/share/man' \ + --define 'mflags -j 4' \ + --define 'configure_options $CONFIG_OPTIONS $openmpi_ldflags --with-verbs=$STACK_PREFIX --with-verbs-libdir=$STACK_PREFIX/$openmpi_lib $openmpi_comp_env $openmpi_conf_psm --with-devel-headers --disable-oshmem' \ + --define 'use_default_rpm_opt_flags $use_default_rpm_opt_flags' \ + $disable_auto_requires" + cmd="$cmd \ + $openmpi_srpm" + echo "Executing: $cmd" + eval $cmd + if [ $? != 0 ] + then + echo "error: openmpi_$compiler$openmpi_rpm_suffix Build ERROR: bad exit code" + exit 1 + fi + if [ "$iflag" = n ] + then + cp $RPM_DIR/RPMS/$target_cpu/openmpi_$compiler$openmpi_rpm_suffix-$openmpi_fullversion.$target_cpu.rpm $DESTDIR + fi + + echo "==========================================================" + echo "Installing OpenMPI MPI $openmpi_version Library/Tools..." + rpmfile=$RPM_DIR/RPMS/$target_cpu/openmpi_$compiler$openmpi_rpm_suffix-$openmpi_fullversion.$target_cpu.rpm + + # need force for reinstall case + if [ x"$INSTALL_ROOT" != x"" -a x"$INSTALL_ROOT" != x"/" ] + then + tempfile=/var/tmp/rpminstall.tmp.rpm + mkdir -p $INSTALL_ROOT/var/tmp + cp $rpmfile $INSTALL_ROOT$tempfile + #chroot /$INSTALL_ROOT rpm -ev --nodeps openmpi_$compiler$openmpi_rpm_suffix-$openmpi_version + chroot /$INSTALL_ROOT rpm -Uv --force $tempfile + rm -f $tempfile + else + #rpm -ev --nodeps openmpi_$compiler$openmpi_rpm_suffix-$openmpi_version + rpm -Uv --force $rpmfile + fi + + echo "==========================================================" + echo "Building test programs $mpitests_version for OpenMPI MPI $openmpi_version..." + # mpitests uses buildroot instead of build_root, play it safe for future + # and define both + cmd="$pref_env rpmbuild --rebuild \ + --define '_topdir $RPM_DIR' \ + --buildroot '$BUILD_ROOT' \ + --define 'buildroot $BUILD_ROOT' \ + --define 'build_root $BUILD_ROOT' \ + --target $target_cpu \ + --define '_name mpitests_openmpi_$compiler$openmpi_rpm_suffix' \ + --define 'root_path /' \ + --define '_usr $STACK_PREFIX' \ + --define 'path_to_mpihome $MPICH_PREFIX' \ + --define 'enable_cuda $Cflag' \ + $disable_auto_requires \ + $mpitests_srpm" + echo "Executing: $cmd" + eval $cmd + if [ $? != 0 ] + then + echo "error: mpitests_openmpi_$compiler$openmpi_rpm_suffix Build ERROR: bad exit code" + exit 1 + fi + + if [ "$iflag" = n ] + then + mv $RPM_DIR/RPMS/$target_cpu/mpitests_openmpi_$compiler$openmpi_rpm_suffix-$mpitests_fullversion.$target_cpu.rpm $DESTDIR + + echo "==========================================================" + echo "Installing test programs $mpitests_version for OpenMPI MPI $openmpi_version..." + rpmfile=$DESTDIR/mpitests_openmpi_$compiler$openmpi_rpm_suffix-$mpitests_fullversion.$target_cpu.rpm + # need force for reinstall case + if [ x"$INSTALL_ROOT" != x"" -a x"$INSTALL_ROOT" != x"/" ] + then + tempfile=/var/tmp/rpminstall.tmp.rpm + mkdir -p $INSTALL_ROOT/var/tmp + cp $rpmfile $INSTALL_ROOT$tempfile + chroot /$INSTALL_ROOT rpm -Uv --force $tempfile + rm -f $tempfile + else + rpm -Uv --force $rpmfile + fi + + rm -rf $BUILD_DIR + fi +) 2>&1|tee $logfile.res +set +x + +# review log for errors and warnings +# disable output of build warnings, way too many +#echo +#echo "Build Warnings:" +# ignore the warning for old C++ header usage in sample programs +egrep 'warning:' $logfile.res |sort -u | + egrep -v 'at least one deprecated or antiquated header.*C\+\+ includes' > $logfile.warn +#cat $logfile.warn +#echo + +#egrep 'error:|Error | Stop' $logfile.res| sort -u | +# egrep -v 'error: this file was generated for autoconf 2.61.' > $logfile.err +egrep 'error:|Error | Stop' $logfile.res| sort -u | + egrep -v 'configure: error: no BPatch.h found; check path for Dyninst package|configure: error: no vtf3.h found; check path for VTF3 package|configure: error: MPI Correctness Checking support cannot be built inside Open MPI|configure: error: no bmi.h found; check path for BMI package first...|configure: error: no ctool/ctool.h found; check path for CTool package first...|configure: error: no cuda.h found; check path for CUDA Toolkit first...|configure: error: no cuda_runtime_api.h found; check path for CUDA Toolkit first...|configure: error: no cupti.h found; check path for CUPTI package first...|configure: error: no f2c.h found; check path for CLAPACK package first...|configure: error: no jvmti.h found; check path for JVMTI package first...|configure: error: no libcpc.h found; check path for CPC package first...|configure: error: no tau_instrumentor found; check path for PDToolkit first...|configure: error: no unimci-config found; check path for UniMCI package first...|"Error code:|"Unknown error:|strerror_r|configure: error: CUPTI API version could not be determined...|asprintf(&msg, "Unexpected sendto() error: errno=%d (%s)",' > $logfile.err + +if [ -s $logfile.err ] +then + echo "Build Errors:" + sort -u $logfile.err + echo + echo "FAILED Build, errors detected" + exit 1 +elif [ -s $logfile.warn ] +then + # at present lots of warnings are expected + echo "SUCCESSFUL Build, no errors detected" + exit 0 + + # No warnings are expected + echo "QUESTIONABLE Build, warnings detected" + exit 1 +else + echo "SUCCESSFUL Build, no errors detected" + exit 0 +fi diff --git a/CommonInstall/main_omnipathwrap_delta.pl b/CommonInstall/main_omnipathwrap_delta.pl new file mode 100644 index 0000000..90f93a0 --- /dev/null +++ b/CommonInstall/main_omnipathwrap_delta.pl @@ -0,0 +1,1980 @@ +#!/usr/bin/perl +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] +use strict; +#use Term::ANSIColor; +#use Term::ANSIColor qw(:constants); +#use File::Basename; +#use Math::BigInt; + +# =========================================================================== +# Main menus, option handling and version handling for FF for OFA install +# + +my $Build_OsVer=$CUR_OS_VER; +my $Build_Debug=0; # should we provide more info for debug +my $Build_Temp=""; # temp area to use for build +my $Default_Build = 0; # -B option used to select build +my $Build_Force = 0;# rebuild option used to force full rebuild + +$FirstIPoIBInterface=0; # first device is ib0 + + # Names of supported install components + # must be listed in dependency order such that prereqs appear 1st + # delta_debug must be last + +my @OmniPathAllComponents = ( + "oftools", "intel_hfi", "opa_stack_dev", "fastfabric", + "delta_ipoib", "opafm", "opamgt_sdk", + "mvapich2_gcc_hfi", "mvapich2_intel_hfi", + "openmpi_gcc_hfi", "openmpi_intel_hfi", + "openmpi_gcc_cuda_hfi", + "mvapich2_gcc", "openmpi_gcc", #"mpiRest", + "mpisrc", "delta_debug" ); + +my @Components_rhel72 = ( "opa_stack", "ibacm", "mpi_selector", + @OmniPathAllComponents); +my @Components_sles12_sp2 = ( "opa_stack", + @OmniPathAllComponents ); +my @Components_rhel73 = ( "opa_stack", "mpi_selector", + @OmniPathAllComponents ); +my @Components_sles12_sp3 = ( "opa_stack", + @OmniPathAllComponents ); +my @Components_sles12_sp4 = ( "opa_stack", + @OmniPathAllComponents ); +my @Components_sles12_sp5 = ( "opa_stack", + @OmniPathAllComponents ); +my @Components_sles15 = ( "opa_stack", + @OmniPathAllComponents ); +my @Components_sles15_sp1 = ( "opa_stack", + @OmniPathAllComponents ); +my @Components_rhel74 = ( "opa_stack", "mpi_selector", + @OmniPathAllComponents ); +my @Components_rhel75 = ( "opa_stack", "mpi_selector", + @OmniPathAllComponents ); +my @Components_rhel76 = ( "opa_stack", "mpi_selector", + @OmniPathAllComponents ); +my @Components_rhel77 = ( "opa_stack", "mpi_selector", + @OmniPathAllComponents ); +my @Components_rhel8 = ( "opa_stack", "mpi_selector", + @OmniPathAllComponents ); +my @Components_rhel81 = ( "opa_stack", "mpi_selector", + @OmniPathAllComponents ); + +@Components = ( ); + +# RHEL7.2, ibacm is a full component with rpms to install +my @SubComponents_older = ( "rdma_ndd", "delta_srp", "delta_srpt" ); +# RHEL7.3 and newer AND SLES12.2 and newer +my @SubComponents_newer = ( "ibacm", "rdma_ndd", "delta_srp", "delta_srpt" ); +@SubComponents = ( ); + + # an additional "special" component which is always installed when + # we install/upgrade anything and which is only uninstalled when everything + # else has been uninstalled. Typically this will be the opaconfig + # file and related files absolutely required by it (such as wrapper_version) +$WrapperComponent = "opaconfig"; + +# This provides more detailed information about each Component in @Components +# since hashes are not retained in the order specified, we still need +# @Components and @SubComponents to control install and menu order +# Only items listed in @Components and @SubComponents are considered for install +# As such, this may list some components which are N/A to the selected distro +# Fields are as follows: +# Name => full name of component/subcomponent for prompts +# DefaultInstall => default installation (State_DoNotInstall or State_Install) +# used only when available and ! installed +# SrcDir => directory name within install media for component +# PreReq => other components which are prereqs of a given +# component/subcomponent +# Need space before and after each component name to +# facilitate compares so that compares do not mistake names +# such as mpidev for mpi +# CoReq => other components which are coreqs of a given component +# Note that CoReqs can also be listed as prereqs to provide +# install verification as each component is installed, +# however prereqs should only refer to items earlier in the list +# Need space before and after each component name to +# facilitate compares so that compares do not mistake names +# such as mpidev for mpi +# Hidden => component should not be shown in menus/prompts +# used for hidden PreReq. Hidden components can't HasStart +# nor HasFirmware +# Disabled => components/subcomponents which are disabled from installation +# IsOFA => is an in-distro OFA component we upgrade (excludes MPI) +# KernelRpms => kernel rpms for given component, in dependency order +# These are rpms which are kernel version specific and +# will have kernel uname -r in rpm package name. +# For a given distro a separate version of each of these rpms +# may exist per kernel. These are always architecture dependent +# Note KernelRpms are always installed before FirmwareRpms and +# UserRpms +# FirmwareRpms => firmware rpms for given component, in dependency order +# These are rpms which are not kernel specific. For a given +# distro a single version of each of these rpms will +# exist per distro/arch combination. In most cases they will +# be architecture independent (noarch). +# These are rpms which are installed in user space but +# ultimately end up in hardware such as HFI firmware, TMM firmware +# BIOS firmware, etc. +# UserRpms => user rpms for given component, in dependency order +# These are rpms which are not kernel specific. For a given +# distro a single version of each of these rpms will +# exist per distro/arch combination. Some of these may +# be architecture independent (noarch). +# DebugRpms => user rpms for component which should be installed as part +# of delta_debug component. +# HasStart => components/subcomponents which have autostart capability +# DefaultStart => should autostart default to Enable (1) or Disable (0) +# Not needed/ignored unless HasStart=1 +# StartPreReq => other components/subcomponents which must be autostarted +# before autostarting this component/subcomponent +# Not needed/ignored unless HasStart=1 +# Need space before and after each component name to +# facilitate compares so that compares do not mistake names +# such as mpidev for mpi +# StartComponents => components/subcomponents with start for this component +# if a component has a start script +# list the component as a subcomponent of itself +# StartupScript => name of startup script which controls startup of this +# component +# StartupParams => list of parameter names in $OPA_CONFIG which control +# startup of this component (set to yes/no values) +# HasFirmware => components which need HCA firmware update after installed +# +# Note both Components and SubComponents are included in the list below. +# Components require all fields be supplied +# SubComponents only require the following fields: +# Name, PreReq (should reference only components), HasStart, StartPreReq, +# DefaultStart, and optionally StartupScript, StartupParams +# Also SubComponents only require the IsAutostart2_X, autostart_desc_X, +# enable_autostart2_X, disable_autostart2_X and installed_X functions. +# Typically installed_X for a SubComponent will simply call installed_X for +# the component which contains it. +%ComponentInfo = ( + # our special WrapperComponent, limited use + "opaconfig" => { Name => "opaconfig", + DefaultInstall => $State_Install, + SrcDir => ".", + PreReq => "", CoReq => "", + Hidden => 0, Disabled => 0, IsOFA => 0, + KernelRpms => [ ], + FirmwareRpms => [ ], + UserRpms => [ ], + DebugRpms => [ ], + HasStart => 0, HasFirmware => 0, + StartPreReq => "", + StartComponents => [ ], + StartupScript => "", + StartupParams => [ ] + + }, + "oftools" => { Name => "OPA Tools", + DefaultInstall => $State_Install, + SrcDir => file_glob("./IntelOPA-Tools*.*"), + PreReq => " opa_stack ", CoReq => " opa_stack ", + Hidden => 0, Disabled => 0, IsOFA => 0, + KernelRpms => [ ], + FirmwareRpms => [ ], + UserRpms => [ "opa-basic-tools", "opa-address-resolution" ], + DebugRpms => [ ], + HasStart => 1, HasFirmware => 0, DefaultStart => 0, + StartPreReq => " opa_stack ", # TBD + StartComponents => [ ], + StartupScript => "", + StartupParams => [ ] + }, + "mpi_selector" => { Name => "MPI selector", + DefaultInstall => $State_Install, + SrcDir => file_glob("./IntelOPA-OFA_DELTA.*"), + PreReq => " opa_stack ", CoReq => "", + Hidden => 1, Disabled => 0, IsOFA => 1, + KernelRpms => [ ], + FirmwareRpms => [ ], + UserRpms => [ "mpi-selector" ], + DebugRpms => [ ], + HasStart => 0, HasFirmware => 0, DefaultStart => 0, + StartPreReq => "", + StartComponents => [ ], + StartupScript => "", + StartupParams => [ ] + }, + "fastfabric" => { Name => "FastFabric", + DefaultInstall => $State_Install, + SrcDir => file_glob("./IntelOPA-Tools*.*"), + PreReq => " opa_stack oftools ", CoReq => "", + Hidden => 0, Disabled => 0, IsOFA => 0, + KernelRpms => [ ], + FirmwareRpms => [ ], + UserRpms => [ "opa-fastfabric", "opa-mpi-apps" ], + DebugRpms => [ ], + HasStart => 0, HasFirmware => 0, DefaultStart => 0, + StartPreReq => " opa_stack ", + StartComponents => [ ], + StartupScript => "", + StartupParams => [ ] + }, +# TBD - only a startup script, should act like a subcomponent only + "delta_ipoib" => { Name => "OFA IP over IB", + DefaultInstall => $State_Install, + SrcDir => file_glob("./IntelOPA-OFA_DELTA.*"), + PreReq => " opa_stack ", CoReq => "", + Hidden => 0, Disabled => 0, IsOFA => 1, + KernelRpms => [ ], + FirmwareRpms => [ ], + UserRpms => [ ], + DebugRpms => [ ], + HasStart => 1, HasFirmware => 0, DefaultStart => 1, + StartPreReq => " opa_stack ", + StartComponents => [ "delta_ipoib" ], + StartupScript => "", + StartupParams => [ "IPOIB_LOAD" ] + }, + "mvapich2_gcc" => { Name => "MVAPICH2 (verbs,gcc)", + DefaultInstall => $State_DoNotInstall, + SrcDir => file_glob ("./OFA_MPIS.*"), + PreReq => " opa_stack mpi_selector intel_hfi ", CoReq => "", + Hidden => 1, Disabled => 0, IsOFA => 0, + KernelRpms => [ ], + FirmwareRpms => [ ], + UserRpms => [ "mvapich2_gcc", "mpitests_mvapich2_gcc" ], + DebugRpms => [ ], + HasStart => 0, HasFirmware => 0, DefaultStart => 0, + StartPreReq => "", + StartComponents => [ ], + StartupScript => "", + StartupParams => [ ] + }, + "openmpi_gcc" => { Name => "OpenMPI (verbs,gcc)", + DefaultInstall => $State_DoNotInstall, + SrcDir => file_glob ("./OFA_MPIS.*"), + PreReq => " opa_stack mpi_selector intel_hfi ", CoReq => "", + Hidden => 1, Disabled => 0, IsOFA => 0, + KernelRpms => [ ], + FirmwareRpms => [ ], + UserRpms => [ "openmpi_gcc", "mpitests_openmpi_gcc" ], + DebugRpms => [ ], + HasStart => 0, HasFirmware => 0, DefaultStart => 0, + StartPreReq => "", + StartComponents => [ ], + StartupScript => "", + StartupParams => [ ] + }, + "openmpi_gcc_cuda_hfi" =>{ Name => "OpenMPI (cuda,gcc)", + DefaultInstall => $State_Install, + SrcDir => file_glob ("./OFA_MPIS.*"), + PreReq => " opa_stack intel_hfi mpi_selector ", CoReq => "", + Hidden => 0, Disabled => 0, IsOFA => 0, + KernelRpms => [ ], + FirmwareRpms => [ ], + UserRpms => [ "openmpi_gcc_cuda_hfi", "mpitests_openmpi_gcc_cuda_hfi" ], + DebugRpms => [ ], + HasStart => 0, HasFirmware => 0, DefaultStart => 0, + StartPreReq => "", + StartComponents => [ ], + StartupScript => "", + StartupParams => [ ] + }, + "mvapich2_gcc_hfi" => { Name => "MVAPICH2 (hfi,gcc)", + DefaultInstall => $State_Install, + SrcDir => file_glob ("./OFA_MPIS.*"), + PreReq => " opa_stack intel_hfi mpi_selector ", CoReq => "", + Hidden => 0, Disabled => 0, IsOFA => 0, + KernelRpms => [ ], + FirmwareRpms => [ ], + UserRpms => [ "mvapich2_gcc_hfi", "mpitests_mvapich2_gcc_hfi" ], + DebugRpms => [ ], + HasStart => 0, HasFirmware => 0, DefaultStart => 0, + StartPreReq => "", + StartComponents => [ ], + StartupScript => "", + StartupParams => [ ] + }, + "mvapich2_intel_hfi" => { Name => "MVAPICH2 (hfi,Intel)", + DefaultInstall => $State_Install, + SrcDir => file_glob ("./OFA_MPIS.*"), + PreReq => " opa_stack intel_hfi mpi_selector ", CoReq => "", + Hidden => 1, Disabled => 0, IsOFA => 0, + KernelRpms => [ ], + FirmwareRpms => [ ], + UserRpms => [ "mvapich2_intel_hfi", "mpitests_mvapich2_intel_hfi" ], + DebugRpms => [ ], + HasStart => 0, HasFirmware => 0, DefaultStart => 0, + StartPreReq => "", + StartComponents => [ ], + StartupScript => "", + StartupParams => [ ] + }, + "openmpi_gcc_hfi" => { Name => "OpenMPI (hfi,gcc)", + DefaultInstall => $State_Install, + SrcDir => file_glob ("./OFA_MPIS.*"), + PreReq => " opa_stack intel_hfi mpi_selector ", CoReq => "", + Hidden => 0, Disabled => 0, IsOFA => 0, + KernelRpms => [ ], + FirmwareRpms => [ ], + UserRpms => [ "openmpi_gcc_hfi", "mpitests_openmpi_gcc_hfi" ], + DebugRpms => [ ], + HasStart => 0, HasFirmware => 0, DefaultStart => 0, + StartPreReq => "", + StartComponents => [ ], + StartupScript => "", + StartupParams => [ ] + }, + "openmpi_intel_hfi" => { Name => "OpenMPI (hfi,Intel)", + DefaultInstall => $State_Install, + SrcDir => file_glob ("./OFA_MPIS.*"), + PreReq => " opa_stack intel_hfi mpi_selector ", CoReq => "", + Hidden => 1, Disabled => 0, IsOFA => 0, + KernelRpms => [ ], + FirmwareRpms => [ ], + UserRpms => [ "openmpi_intel_hfi", "mpitests_openmpi_intel_hfi" ], + DebugRpms => [ ], + HasStart => 0, HasFirmware => 0, DefaultStart => 0, + StartPreReq => "", + StartComponents => [ ], + StartupScript => "", + StartupParams => [ ] + }, +# rest of MPI stuff which customer can build via do_build +# this is included here so we can uninstall +# special case use in comp_delta.pl, omitted from Components list +# TBD - how to best refactor this so we remove these (do we still need to remove them?) + "mpiRest" => { Name => "MpiRest (pgi,Intel)", + DefaultInstall => $State_DoNotInstall, + SrcDir => file_glob ("./OFA_MPIS.*"), + PreReq => "", CoReq => "", + Hidden => 1, Disabled => 1, IsOFA => 1, + KernelRpms => [ ], + FirmwareRpms => [ ], + UserRpms => [ "mvapich2_pgi", + "mvapich2_intel", "mvapich2_pathscale", + "mvapich2_pgi_qlc", "mvapich2_gcc_qlc", + "mvapich2_intel_qlc", "mvapich2_pathscale_qlc", + "mvapich2_pgi_hfi", "mvapich2_pathscale_hfi", + "mvapich2_pgi_cuda_hfi", "mvapich2_pathscale_cuda_hfi", + "openmpi_pgi", + "openmpi_intel", "openmpi_pathscale", + "openmpi_pgi_qlc", "openmpi_gcc_qlc", + "openmpi_intel_qlc", "openmpi_pathscale_qlc", + "openmpi_pgi_hfi", "openmpi_pathscale_hfi", + "openmpi_pgi_cuda_hfi", "openmpi_pathscale_cuda_hfi", + "mpitests_mvapich2_pgi", + "mpitests_mvapich2_intel", + "mpitests_mvapich2_pathscale", + "mpitests_mvapich2_pgi_qlc", "mpitests_mvapich2_gcc_qlc", + "mpitests_mvapich2_intel_qlc", "mpitests_mvapich2_pathscale_qlc", + "mpitests_mvapich2_pgi_hfi", "mpitests_mvapich2_pathscale_hfi", + "mpitests_mvapich2_pgi_cuda_hfi", "mpitests_mvapich2_pathscale_cuda_hfi", + "mpitests_openmpi_pgi", + "mpitests_openmpi_intel", + "mpitests_openmpi_pathscale", + "mpitests_openmpi_pgi_qlc", "mpitests_openmpi_gcc_qlc", + "mpitests_openmpi_intel_qlc", "mpitests_openmpi_pathscale_qlc", + "mpitests_openmpi_pgi_hfi", "mpitests_openmpi_pathscale_hfi", + "mpitests_openmpi_pgi_cuda_hfi", "mpitests_openmpi_pathscale_cuda_hfi", + ], + DebugRpms => [ ], + HasStart => 0, HasFirmware => 0, DefaultStart => 0, + StartPreReq => "", + StartComponents => [ ], + StartupScript => "", + StartupParams => [ ] + }, + "mpisrc" =>{ Name => "MPI Source", + DefaultInstall => $State_Install, + SrcDir => file_glob ("./OFA_MPIS.*"), + PreReq => " opa_stack opa_stack_dev mpi_selector ", CoReq => "", + Hidden => 0, Disabled => 0, IsOFA => 0, + KernelRpms => [ ], + FirmwareRpms => [ ], + UserRpms => [ ], + DebugRpms => [ ], + HasStart => 0, HasFirmware => 0, DefaultStart => 0, + StartPreReq => "", + StartComponents => [ ], + StartupScript => "", + StartupParams => [ ] + }, + "opafm" => { Name => "OPA FM", + DefaultInstall => $State_Install, + SrcDir => file_glob("./IntelOPA-FM.*"), + PreReq => " opa_stack ", CoReq => "", + Hidden => 0, Disabled => 0, IsOFA => 0, + KernelRpms => [ ], + FirmwareRpms => [ ], + UserRpms => [ "opa-fm", "opa-fm-debuginfo" ], + DebugRpms => [ ], + HasStart => 1, HasFirmware => 0, DefaultStart => 0, + StartPreReq => " opa_stack ", + #StartComponents => [ "qlgc_fm", "qlgc_fm_snmp"], + StartComponents => [ "opafm" ], + StartupScript => "", + StartupParams => [ ] + }, + "opamgt_sdk" => { Name => "OPA Management SDK", + DefaultInstall => $State_Install, + SrcDir => file_glob("./IntelOPA-Tools*.*"), + PreReq => " opa_stack ", CoReq => "", + Hidden => 0, Disabled => 0, IsOFA => 0, + KernelRpms => [ ], + FirmwareRpms => [ ], + UserRpms => [ "opa-libopamgt", "opa-libopamgt-devel" ], + DebugRpms => [ ], + HasStart => 0, HasFirmware => 0, DefaultStart => 0, + StartPreReq => " opa_stack ", + StartComponents => [ ], + StartupScript => "", + StartupParams => [ ] + }, + "delta_debug" => { Name => "OFA Debug Info", + DefaultInstall => $State_DoNotInstall, + SrcDir => file_glob("./IntelOPA-OFA_DELTA.*"), + PreReq => " opa_stack ", CoReq => "", + Hidden => 0, Disabled => 0, IsOFA => 1, + KernelRpms => [ ], + FirmwareRpms => [ ], + UserRpms => [ ], + DebugRpms => [ ], # listed per comp + HasStart => 0, HasFirmware => 0, DefaultStart => 0, + StartPreReq => "", + StartComponents => [ ], + StartupScript => "", + StartupParams => [ ] + }, + # rdma_ndd is a subcomponent + # it has a startup, but is considered part of opa_stack + "rdma_ndd" => { Name => "RDMA NDD", + PreReq => " opa_stack ", + HasStart => 1, DefaultStart => 1, + StartPreReq => " opa_stack ", + StartComponents => [ "rdma_ndd" ], + StartupScript => "", + StartupParams => [ ] + }, + # delta_srp is a subcomponent + # it has a startup, but is considered part of opa_stack + "delta_srp" => { Name => "OFA SRP", + PreReq => " opa_stack ", + HasStart => 1, DefaultStart => 0, + StartPreReq => " opa_stack ", + StartComponents => [ "delta_srp" ], + StartupScript => "", + StartupParams => [ ] + }, + # delta_srpt is a subcomponent + # it has a startup, but is considered part of opa_stack + "delta_srpt" => { Name => "OFA SRPT", + PreReq => " opa_stack ", + HasStart => 1, DefaultStart => 0, + StartPreReq => " opa_stack ", + StartComponents => [ "delta_srpt" ], + StartupScript => "", + StartupParams => [ ] + }, + ); + +# one of these opa_stack comp_info gets appended to ComponentInfo +# for RHEL72 +my %opa_stack_rhel72_comp_info = ( + "opa_stack" => { Name => "OFA OPA Stack", + DefaultInstall => $State_Install, + SrcDir => file_glob("./IntelOPA-OFA_DELTA.*"), + PreReq => "", CoReq => " oftools ", + # TBD - HasFirmware - FW update + Hidden => 0, Disabled => 0, IsOFA => 1, + KernelRpms => [ "kmod-ifs-kernel-updates" ], + FirmwareRpms => [ ], + UserRpms => [ "opa-scripts", + #"libibumad", + "srptools", + "libibmad", + "infiniband-diags", + ], + DebugRpms => [ #"libibumad-debuginfo", + "srptools-debuginfo", + ], + HasStart => 1, HasFirmware => 0, DefaultStart => 1, + StartPreReq => "", + StartComponents => [ "opa_stack", "rdma_ndd", "delta_srp", "delta_srpt" ], + StartupScript => "opa", + StartupParams => [ "ARPTABLE_TUNING" ] + }, +); +# for RHEL73 +my %opa_stack_rhel73_comp_info = ( + "opa_stack" => { Name => "OFA OPA Stack", + DefaultInstall => $State_Install, + SrcDir => file_glob("./IntelOPA-OFA_DELTA.*"), + PreReq => "", CoReq => " oftools ", + # TBD - HasFirmware - FW update + Hidden => 0, Disabled => 0, IsOFA => 1, + KernelRpms => [ "kmod-ifs-kernel-updates" ], + FirmwareRpms => [ ], + UserRpms => [ "opa-scripts", + #"libibumad", + #"srptools", + #"libibmad", + "infiniband-diags", + ], + DebugRpms => [ #"libibumad-debuginfo", + #"srptools-debuginfo", + ], + HasStart => 1, HasFirmware => 0, DefaultStart => 1, + StartPreReq => "", + StartComponents => [ "opa_stack", "ibacm", "rdma_ndd", "delta_srp", "delta_srpt" ], + StartupScript => "opa", + StartupParams => [ "ARPTABLE_TUNING" ] + }, +); +# for RHEL74 and above +my %opa_stack_rhel_comp_info = ( + "opa_stack" => { Name => "OFA OPA Stack", + DefaultInstall => $State_Install, + SrcDir => file_glob("./IntelOPA-OFA_DELTA.*"), + PreReq => "", CoReq => " oftools ", + # TBD - HasFirmware - FW update + Hidden => 0, Disabled => 0, IsOFA => 1, + KernelRpms => [ "kmod-ifs-kernel-updates" ], + FirmwareRpms => [ ], + UserRpms => [ "opa-scripts", + #"libibumad", + #"srptools", + #"libibmad", + #"infiniband-diags", + ], + DebugRpms => [ #"libibumad-debuginfo", + #"srptools-debuginfo", + ], + HasStart => 1, HasFirmware => 0, DefaultStart => 1, + StartPreReq => "", + StartComponents => [ "opa_stack", "ibacm", "rdma_ndd", "delta_srp", "delta_srpt" ], + StartupScript => "opa", + StartupParams => [ "ARPTABLE_TUNING" ] + }, +); +# for RHEL74 HFI2 +my %opa_stack_rhel74_hfi2_comp_info = ( + "opa_stack" => { Name => "OFA OPA Stack", + DefaultInstall => $State_Install, + SrcDir => file_glob("./IntelOPA-OFA_DELTA.*"), + PreReq => "", CoReq => " oftools ", + # TBD - HasFirmware - FW update + Hidden => 0, Disabled => 0, IsOFA => 1, + KernelRpms => [ "hfi2" ], + FirmwareRpms => [ ], + UserRpms => [ "opa-scripts", + #"libibumad", + #"srptools", + #"libibmad", + #"infiniband-diags", + ], + DebugRpms => [ #"libibumad-debuginfo", + #"srptools-debuginfo", + ], + HasStart => 1, HasFirmware => 0, DefaultStart => 1, + StartPreReq => "", + StartComponents => [ "opa_stack", "ibacm", "rdma_ndd", "delta_srp", "delta_srpt" ], + StartupScript => "opa", + StartupParams => [ "ARPTABLE_TUNING" ] + }, +); +# for SLES12sp2 +my %opa_stack_sles12_sp2_comp_info = ( + "opa_stack" => { Name => "OFA OPA Stack", + DefaultInstall => $State_Install, + SrcDir => file_glob("./IntelOPA-OFA_DELTA.*"), + PreReq => "", CoReq => " oftools ", + # TBD - HasFirmware - FW update + Hidden => 0, Disabled => 0, IsOFA => 1, + KernelRpms => [ "ifs-kernel-updates-kmp-default" ], + FirmwareRpms => [ ], + UserRpms => [ "opa-scripts", + #"libibumad3", + #"srptools", + #"libibmad5", + "infiniband-diags", + ], + DebugRpms => [ ], + HasStart => 1, HasFirmware => 0, DefaultStart => 1, + StartPreReq => "", + StartComponents => [ "opa_stack", "ibacm", "rdma_ndd", "delta_srp", "delta_srpt" ], + StartupScript => "opa", + StartupParams => [ "ARPTABLE_TUNING" ] + }, +); +# for SLES12sp3 +my %opa_stack_sles12_sp3_comp_info = ( + "opa_stack" => { Name => "OFA OPA Stack", + DefaultInstall => $State_Install, + SrcDir => file_glob("./IntelOPA-OFA_DELTA.*"), + PreReq => "", CoReq => " oftools ", + # TBD - HasFirmware - FW update + Hidden => 0, Disabled => 0, IsOFA => 1, + KernelRpms => [ "ifs-kernel-updates-kmp-default" ], + FirmwareRpms => [ ], + UserRpms => [ "opa-scripts", + #"libibumad3", + #"srptools", + #"libibmad5", + #"infiniband-diags", + ], + DebugRpms => [ ], + HasStart => 1, HasFirmware => 0, DefaultStart => 1, + StartPreReq => "", + StartComponents => [ "opa_stack", "ibacm", "rdma_ndd", "delta_srp", "delta_srpt" ], + StartupScript => "opa", + StartupParams => [ "ARPTABLE_TUNING" ] + }, +); + +# for SLES12sp4 +my %opa_stack_sles12_sp4_comp_info = ( + "opa_stack" => { Name => "OFA OPA Stack", + DefaultInstall => $State_Install, + SrcDir => file_glob("./IntelOPA-OFA_DELTA.*"), + PreReq => "", CoReq => " oftools ", + Hidden => 0, Disabled => 0, IsOFA => 1, + KernelRpms => [ "ifs-kernel-updates-kmp-default" ], + FirmwareRpms => [ ], + UserRpms => [ "opa-scripts", + ], + DebugRpms => [ ], + HasStart => 1, HasFirmware => 0, DefaultStart => 1, + StartPreReq => "", + StartComponents => [ "opa_stack", "ibacm", "rdma_ndd", "delta_srp", "delta_srpt" ], + StartupScript => "opa", + StartupParams => [ "ARPTABLE_TUNING" ] + }, +); + +# for SLES12sp5 +my %opa_stack_sles12_sp5_comp_info = ( + "opa_stack" => { Name => "OFA OPA Stack", + DefaultInstall => $State_Install, + SrcDir => file_glob("./IntelOPA-OFA_DELTA.*"), + PreReq => "", CoReq => " oftools ", + Hidden => 0, Disabled => 0, IsOFA => 1, + KernelRpms => [ "ifs-kernel-updates-kmp-default" ], + FirmwareRpms => [ ], + UserRpms => [ "opa-scripts", + ], + DebugRpms => [ ], + HasStart => 1, HasFirmware => 0, DefaultStart => 1, + StartPreReq => "", + StartComponents => [ "opa_stack", "ibacm", "rdma_ndd", "delta_srp", "delta_srpt" ], + StartupScript => "opa", + StartupParams => [ "ARPTABLE_TUNING" ] + }, +); + +# for SLES15.x +my %opa_stack_sles15_comp_info = ( + "opa_stack" => { Name => "OFA OPA Stack", + DefaultInstall => $State_Install, + SrcDir => file_glob("./IntelOPA-OFA_DELTA.*"), + PreReq => "", CoReq => " oftools ", + # TBD - HasFirmware - FW update + Hidden => 0, Disabled => 0, IsOFA => 1, + KernelRpms => [ "ifs-kernel-updates-kmp-default" ], + FirmwareRpms => [ ], + UserRpms => [ "opa-scripts", + #"libibumad3", + #"srptools", + #"libibmad5", + #"infiniband-diags", + ], + DebugRpms => [ ], + HasStart => 1, HasFirmware => 0, DefaultStart => 1, + StartPreReq => "", + StartComponents => [ "opa_stack", "ibacm", "rdma_ndd", "delta_srp", "delta_srpt" ], + StartupScript => "opa", + StartupParams => [ "ARPTABLE_TUNING" ] + }, +); + + +# one of these ibacm comp_info gets appended to ComponentInfo +# for RHEL72 +my %ibacm_older_comp_info = ( + "ibacm" => { Name => "OFA IBACM", + DefaultInstall => $State_Install, + SrcDir => file_glob("./IntelOPA-OFA_DELTA.*"), + PreReq => " opa_stack ", CoReq => "", + Hidden => 0, Disabled => 0, IsOFA => 1, + KernelRpms => [ ], + FirmwareRpms => [ ], + UserRpms => [ "ibacm",], + DebugRpms => [ "ibacm-debuginfo" ], + HasStart => 1, HasFirmware => 0, DefaultStart => 0, + StartPreReq => " opa_stack ", + StartComponents => [ "ibacm" ], + StartupScript => "ibacm", + StartupParams => [ ] + }, +); + +# For RHEL73, SLES12sp2 and other newer distros + # ibacm is a subcomponent + # it has a startup, but is considered part of opa_stack +my %ibacm_comp_info = ( + # TBD - should be a StartComponent only for these distros + "ibacm" => { Name => "OFA IBACM", + PreReq => " opa_stack ", + HasStart => 1, DefaultStart => 0, + StartPreReq => " opa_stack ", + StartComponents => [ "ibacm" ], + StartupScript => "ibacm", + StartupParams => [ ] + }, +); + + +# one of these intel_hfi comp_info gets appended to ComponentInfo +# for RHEL72 which lacks libhfi1 +my %intel_hfi_older_comp_info = ( + "intel_hfi" => { Name => "Intel HFI Components", + DefaultInstall => $State_Install, + SrcDir => file_glob("./IntelOPA-OFA_DELTA.*"), + PreReq => " opa_stack ", CoReq => " oftools ", + # TBD - HasFirmware - FW update + Hidden => 0, Disabled => 0, IsOFA => 1, + KernelRpms => [ ], + FirmwareRpms => [ + "hfi1-firmware", "hfi1-firmware_debug" + ], + UserRpms => [ "libhfi1", "libhfi1-static", + "libpsm2", + "libpsm2-devel", "libpsm2-compat", + "libfabric", "libfabric-devel", + "libfabric-psm", + "libfabric-psm2", "libfabric-verbs", + "hfi1-diagtools-sw", "hfidiags", + ], + DebugRpms => [ "hfi1_debuginfo", + "hfi1-diagtools-sw-debuginfo", + "libpsm2-debuginfo", "libhfi1-debuginfo" + ], + HasStart => 1, HasFirmware => 0, DefaultStart => 1, + StartPreReq => " opa_stack ", + StartComponents => [ "intel_hfi" ], + StartupScript => "", + StartupParams => [ ] + }, +); +# for RHEL73, SLES12.2 and other newer distros which include libhfi1 +my %intel_hfi_comp_info = ( + "intel_hfi" => { Name => "Intel HFI Components", + DefaultInstall => $State_Install, + SrcDir => file_glob("./IntelOPA-OFA_DELTA.*"), + PreReq => " opa_stack ", CoReq => " oftools ", + # TBD - HasFirmware - FW update + Hidden => 0, Disabled => 0, IsOFA => 1, + KernelRpms => [ ], + FirmwareRpms => [ + "hfi1-firmware", "hfi1-firmware_debug" + ], + UserRpms => [ #"libhfi1", "libhfi1-static", + "libpsm2", + "libpsm2-devel", "libpsm2-compat", + "libfabric", "libfabric-devel", + "libfabric-psm", + "libfabric-psm2", "libfabric-verbs", + "hfi1-diagtools-sw", "hfidiags", + ], + DebugRpms => [ #"hfi1_debuginfo", + "hfi1-diagtools-sw-debuginfo", + "libpsm2-debuginfo", #"libhfi1-debuginfo" + ], + HasStart => 1, HasFirmware => 0, DefaultStart => 1, + StartPreReq => " opa_stack ", + StartComponents => [ "intel_hfi" ], + StartupScript => "", + StartupParams => [ ] + }, +); +# +# for RHEL8, which does not currently support opa_stack and does not require libfabric-psm +my %intel_hfi_rhel8_comp_info = ( + "intel_hfi" => { Name => "Intel HFI Components", + DefaultInstall => $State_Install, + SrcDir => file_glob("./IntelOPA-OFA_DELTA.*"), + PreReq => " opa_stack ", CoReq => " oftools ", + # TBD - HasFirmware - FW update + Hidden => 0, Disabled => 0, IsOFA => 1, + KernelRpms => [ ], + FirmwareRpms => [ + "hfi1-firmware", "hfi1-firmware_debug" + ], + UserRpms => [ #"libhfi1", "libhfi1-static", + "libpsm2", + "libpsm2-devel", "libpsm2-compat", + "libfabric", "libfabric-devel", + "libfabric-psm2", "libfabric-verbs", + "hfi1-diagtools-sw", "hfidiags", + ], + DebugRpms => [ #"hfi1_debuginfo", + "hfi1-diagtools-sw-debuginfo", + "libpsm2-debuginfo", #"libhfi1-debuginfo" + ], + HasStart => 1, HasFirmware => 0, DefaultStart => 1, + StartPreReq => " opa_stack ", + StartComponents => [ "intel_hfi" ], + StartupScript => "", + StartupParams => [ ] + }, +); + +my %intel_hfi_rhel81_comp_info = ( + "intel_hfi" => { Name => "Intel HFI Components", + DefaultInstall => $State_Install, + SrcDir => file_glob("./IntelOPA-OFA_DELTA.*"), + PreReq => " opa_stack ", CoReq => " oftools ", + # TBD - HasFirmware - FW update + Hidden => 0, Disabled => 0, IsOFA => 1, + KernelRpms => [ ], + FirmwareRpms => [ + "hfi1-firmware", "hfi1-firmware_debug" + ], + UserRpms => [ #"libhfi1", "libhfi1-static", + "libpsm2", + "libpsm2-devel", "libpsm2-compat", + "libfabric", "libfabric-devel", + "libfabric-psm2", "libfabric-verbs", + "hfi1-diagtools-sw", "hfidiags", + ], + DebugRpms => [ #"hfi1_debuginfo", + "hfi1-diagtools-sw-debuginfo", + "libpsm2-debuginfo", #"libhfi1-debuginfo" + ], + HasStart => 1, HasFirmware => 0, DefaultStart => 1, + StartPreReq => " opa_stack ", + StartComponents => [ "intel_hfi" ], + StartupScript => "", + StartupParams => [ ] + }, +); + +# For SLES12sp3 that has different name for libpsm2 +my %intel_hfi_sles123_comp_info = ( + "intel_hfi" => { Name => "Intel HFI Components", + DefaultInstall => $State_Install, + SrcDir => file_glob("./IntelOPA-OFA_DELTA.*"), + PreReq => " opa_stack ", CoReq => " oftools ", + # TBD - HasFirmware - FW update + Hidden => 0, Disabled => 0, IsOFA => 1, + KernelRpms => [ ], + FirmwareRpms => [ + "hfi1-firmware", "hfi1-firmware_debug" + ], + UserRpms => [ #"libhfi1", "libhfi1-static", + "libpsm2-2", + "libpsm2-devel", "libpsm2-compat", + "libfabric", "libfabric-devel", + "libfabric-psm", + "libfabric-psm2", "libfabric-verbs", + "hfi1-diagtools-sw", "hfidiags", + ], + DebugRpms => [ #"hfi1_debuginfo", + "hfi1-diagtools-sw-debuginfo", + "libpsm2-debuginfo", #"libhfi1-debuginfo" + ], + HasStart => 1, HasFirmware => 0, DefaultStart => 1, + StartPreReq => " opa_stack ", + StartComponents => [ "intel_hfi" ], + StartupScript => "", + StartupParams => [ ] + }, +); + +my %intel_hfi_sles124_comp_info = ( + "intel_hfi" => { Name => "Intel HFI Components", + DefaultInstall => $State_Install, + SrcDir => file_glob("./IntelOPA-OFA_DELTA.*"), + PreReq => " opa_stack ", CoReq => " oftools ", + Hidden => 0, Disabled => 0, IsOFA => 1, + KernelRpms => [ ], + FirmwareRpms => [ + "hfi1-firmware", "hfi1-firmware_debug" + ], + UserRpms => [ "libpsm2-2", + "libpsm2-devel", "libpsm2-compat", + "libfabric", "libfabric-devel", + "libfabric-psm", + "libfabric-psm2", "libfabric-verbs", + "hfi1-diagtools-sw", "hfidiags", + ], + DebugRpms => [ "hfi1-diagtools-sw-debuginfo", + "libpsm2-debuginfo", + ], + HasStart => 1, HasFirmware => 0, DefaultStart => 1, + StartPreReq => " opa_stack ", + StartComponents => [ "intel_hfi" ], + StartupScript => "", + StartupParams => [ ] + }, +); + +my %intel_hfi_sles125_comp_info = ( + "intel_hfi" => { Name => "Intel HFI Components", + DefaultInstall => $State_Install, + SrcDir => file_glob("./IntelOPA-OFA_DELTA.*"), + PreReq => " opa_stack ", CoReq => " oftools ", + Hidden => 0, Disabled => 0, IsOFA => 1, + KernelRpms => [ ], + FirmwareRpms => [ + "hfi1-firmware", "hfi1-firmware_debug" + ], + UserRpms => [ "libpsm2-2", + "libpsm2-devel", "libpsm2-compat", + "libfabric", "libfabric-devel", + "libfabric-psm", + "libfabric-psm2", "libfabric-verbs", + "hfi1-diagtools-sw", "hfidiags", + ], + DebugRpms => [ "hfi1-diagtools-sw-debuginfo", + "libpsm2-debuginfo", + ], + HasStart => 1, HasFirmware => 0, DefaultStart => 1, + StartPreReq => " opa_stack ", + StartComponents => [ "intel_hfi" ], + StartupScript => "", + StartupParams => [ ] + }, +); + +# For SLES15.x that has different name for libpsm2 +my %intel_hfi_sles15_comp_info = ( + "intel_hfi" => { Name => "Intel HFI Components", + DefaultInstall => $State_Install, + SrcDir => file_glob("./IntelOPA-OFA_DELTA.*"), + PreReq => " opa_stack ", CoReq => " oftools ", + # TBD - HasFirmware - FW update + Hidden => 0, Disabled => 0, IsOFA => 1, + KernelRpms => [ ], + FirmwareRpms => [ + "hfi1-firmware", "hfi1-firmware_debug" + ], + UserRpms => [ #"libhfi1", "libhfi1-static", + "libpsm2-2", + "libpsm2-devel", "libpsm2-compat", + "libfabric", "libfabric-devel", + "libfabric-psm", + "libfabric-psm2", "libfabric-verbs", + "hfi1-diagtools-sw", "hfidiags", + ], + DebugRpms => [ #"hfi1_debuginfo", + "hfi1-diagtools-sw-debuginfo", + "libpsm2-debuginfo", #"libhfi1-debuginfo" + ], + HasStart => 1, HasFirmware => 0, DefaultStart => 1, + StartPreReq => " opa_stack ", + StartComponents => [ "intel_hfi" ], + StartupScript => "", + StartupParams => [ ] + }, +); + +# for RHEL74 HFI2 +my %intel_hfi__rhel74_hfi2_comp_info = ( + "intel_hfi" => { Name => "Intel HFI Components", + DefaultInstall => $State_Install, + SrcDir => file_glob("./IntelOPA-OFA_DELTA.*"), + PreReq => " opa_stack ", CoReq => " oftools ", + # TBD - HasFirmware - FW update + Hidden => 0, Disabled => 0, IsOFA => 1, + KernelRpms => [ ], + FirmwareRpms => [ + "hfi1-firmware", "hfi1-firmware_debug" + ], + UserRpms => [ #"libhfi1", "libhfi1-static", + "libpsm2", + "libpsm2-devel", "libpsm2-compat", + "libfabric", "libfabric-devel", + "libfabric-fxr", + "libfabric-psm", + "libfabric-psm2", "libfabric-verbs", + "hfi1-diagtools-sw", "hfidiags", + ], + DebugRpms => [ #"hfi1_debuginfo", + "hfi1-diagtools-sw-debuginfo", + "libpsm2-debuginfo", #"libhfi1-debuginfo" + ], + HasStart => 1, HasFirmware => 0, DefaultStart => 1, + StartPreReq => " opa_stack ", + StartComponents => [ "intel_hfi" ], + StartupScript => "", + StartupParams => [ ] + }, +); +# one of these opa_stack_dev comp_info gets appended to ComponentInfo +# for RHEL72 +my %opa_stack_dev_rhel72_comp_info = ( + "opa_stack_dev" => { Name => "OFA OPA Development", + DefaultInstall => $State_Install, + SrcDir => file_glob("./IntelOPA-OFA_DELTA.*"), + PreReq => " opa_stack ", CoReq => "", + Hidden => 0, Disabled => 0, IsOFA => 1, + KernelRpms => [ "ifs-kernel-updates-devel" ], + FirmwareRpms => [ ], + UserRpms => [ "ibacm-devel", + #"libibumad-devel", "libibumad-static", + #"libibmad-devel", "libibmad-static" + ], + DebugRpms => [ ], + HasStart => 0, HasFirmware => 0, DefaultStart => 0, + StartPreReq => "", + StartComponents => [ ], + StartupScript => "", + StartupParams => [ ] + }, +); +# for RHEL73 and SLES12sp2 and newer distros +my %opa_stack_dev_comp_info = ( + "opa_stack_dev" => { Name => "OFA OPA Development", + DefaultInstall => $State_Install, + SrcDir => file_glob("./IntelOPA-OFA_DELTA.*"), + PreReq => " opa_stack ", CoReq => "", + Hidden => 0, Disabled => 0, IsOFA => 1, + KernelRpms => [ "ifs-kernel-updates-devel" ], + FirmwareRpms => [ ], + UserRpms => [ #"ibacm-devel", + #"libibumad-devel", "libibumad-static", + #"libibmad-devel", "libibmad-static" + ], + DebugRpms => [ ], + HasStart => 0, HasFirmware => 0, DefaultStart => 0, + StartPreReq => "", + StartComponents => [ ], + StartupScript => "", + StartupParams => [ ] + }, +); + + # translate from startup script name to component/subcomponent name +%StartupComponent = ( + "opa_stack" => "opa_stack", + "opafm" => "opafm", + ); + # has component been loaded since last configured autostart +%ComponentWasInstalled = ( + "opa_stack" => 0, + "ibacm" => 0, + "oftools" => 0, + "mpi_selector" => 0, + "opa_stack_dev" => 0, + "fastfabric" => 0, + "delta_ipoib" => 0, + "mvapich2_gcc" => 0, + "openmpi_gcc" => 0, + "mvapich2_gcc_hfi" => 0, + "mvapich2_intel_hfi" => 0, + "openmpi_gcc_hfi" => 0, + "openmpi_gcc_cuda_hfi" => 0, + "openmpi_intel_hfi" => 0, + "mpiRest" => 0, + "mpisrc" => 0, + "opafm" => 0, + "opamgt_sdk" => 0, + "delta_debug" => 0, + "rdma_ndd" => 0, + "delta_srp" => 0, + "delta_srpt" => 0, + ); + +# check whether we support HFI2 +sub support_HFI2() +{ + # right now we support HFI2 only in RHEL7.4 with kVer >= 4.6 + if ("$CUR_VENDOR_VER" eq "ES74" && $CUR_OS_VER_SHORT >= 4.6) { + # We prefer to check it based on feature (i.e. hfi2 pkg) rather than version (i.e. content in version file) + my $rpmdir = "$RPMS_SUBDIR/$CUR_DISTRO_VENDOR-$CUR_VENDOR_VER"; + my $srcdir = $opa_stack_rhel74_hfi2_comp_info{'opa_stack'}{'SrcDir'}; + my @rpmlist = @{$opa_stack_rhel74_hfi2_comp_info{'opa_stack'}{'KernelRpms'}}; + # this function get called before overrides, so we need to consider the case we run it from DELTA pkg that + # srcdir is current location, i.e. "." + return rpm_exists_list("$srcdir/$rpmdir", $CUR_OS_VER, @rpmlist) || + rpm_exists_list("./$rpmdir", $CUR_OS_VER, @rpmlist); + } + return 0; +} + +sub init_components +{ + $HFI2_INSTALL = support_HFI2(); + + # The component list has slight variations per distro + if ( "$CUR_VENDOR_VER" eq "ES72" ) { + @Components = ( @Components_rhel72 ); + @SubComponents = ( @SubComponents_older ); + %ComponentInfo = ( %ComponentInfo, %ibacm_older_comp_info, + %intel_hfi_older_comp_info, + %opa_stack_dev_rhel72_comp_info, + %opa_stack_rhel72_comp_info, + ); + $ComponentInfo{'oftools'}{'PreReq'} = " opastack ibacm "; + } elsif ( "$CUR_VENDOR_VER" eq "ES122" ) { + @Components = ( @Components_sles12_sp2 ); + @SubComponents = ( @SubComponents_newer ); + %ComponentInfo = ( %ComponentInfo, %ibacm_comp_info, + %intel_hfi_comp_info, + %opa_stack_dev_comp_info, + %opa_stack_sles12_sp2_comp_info, + ); + } elsif ( "$CUR_VENDOR_VER" eq "ES73" ) { + @Components = ( @Components_rhel73 ); + @SubComponents = ( @SubComponents_newer ); + %ComponentInfo = ( %ComponentInfo, %ibacm_comp_info, + %intel_hfi_comp_info, + %opa_stack_dev_comp_info, + %opa_stack_rhel73_comp_info, + ); + } elsif ( "$CUR_VENDOR_VER" eq "ES123" ) { + @Components = ( @Components_sles12_sp3 ); + @SubComponents = ( @SubComponents_newer ); + %ComponentInfo = ( %ComponentInfo, %ibacm_comp_info, + %intel_hfi_sles123_comp_info, + %opa_stack_dev_comp_info, + %opa_stack_sles12_sp3_comp_info, + ); + } elsif ( "$CUR_VENDOR_VER" eq "ES124" ) { + @Components = ( @Components_sles12_sp4 ); + @SubComponents = ( @SubComponents_newer ); + %ComponentInfo = ( %ComponentInfo, %ibacm_comp_info, + %intel_hfi_sles124_comp_info, + %opa_stack_dev_comp_info, + %opa_stack_sles12_sp4_comp_info, + ); + } elsif ( "$CUR_VENDOR_VER" eq "ES125" ) { + @Components = ( @Components_sles12_sp5 ); + @SubComponents = ( @SubComponents_newer ); + %ComponentInfo = ( %ComponentInfo, %ibacm_comp_info, + %intel_hfi_sles125_comp_info, + %opa_stack_dev_comp_info, + %opa_stack_sles12_sp5_comp_info, + ); + } elsif ( "$CUR_VENDOR_VER" eq "ES74" ) { + @SubComponents = ( @SubComponents_newer ); + @Components = ( @Components_rhel74 ); + if ($HFI2_INSTALL) { + %ComponentInfo = ( %ComponentInfo, %ibacm_comp_info, + %intel_hfi__rhel74_hfi2_comp_info, + %opa_stack_dev_comp_info, + %opa_stack_rhel74_hfi2_comp_info, + ); + } else { + %ComponentInfo = ( %ComponentInfo, %ibacm_comp_info, + %intel_hfi_comp_info, + %opa_stack_dev_comp_info, + %opa_stack_rhel_comp_info, + ); + } + } elsif ( "$CUR_VENDOR_VER" eq "ES75" ) { + @Components = ( @Components_rhel75 ); + @SubComponents = ( @SubComponents_newer ); + %ComponentInfo = ( %ComponentInfo, %ibacm_comp_info, + %intel_hfi_comp_info, + %opa_stack_dev_comp_info, + %opa_stack_rhel_comp_info, + ); + } elsif ( "$CUR_VENDOR_VER" eq "ES76" ) { + @Components = ( @Components_rhel76 ); + @SubComponents = ( @SubComponents_newer ); + %ComponentInfo = ( %ComponentInfo, %ibacm_comp_info, + %intel_hfi_comp_info, + %opa_stack_dev_comp_info, + %opa_stack_rhel_comp_info, + ); + } elsif ( "$CUR_VENDOR_VER" eq "ES77" ) { + @Components = ( @Components_rhel77 ); + @SubComponents = ( @SubComponents_newer ); + %ComponentInfo = ( %ComponentInfo, %ibacm_comp_info, + %intel_hfi_comp_info, + %opa_stack_dev_comp_info, + %opa_stack_rhel_comp_info, + ); + } elsif ( "$CUR_VENDOR_VER" eq "ES8" ) { + @Components = ( @Components_rhel8 ); + @SubComponents = ( @SubComponents_newer ); + %ComponentInfo = ( %ComponentInfo, %ibacm_comp_info, + %intel_hfi_rhel8_comp_info, + %opa_stack_dev_comp_info, + %opa_stack_rhel_comp_info, + ); + } elsif ( "$CUR_VENDOR_VER" eq "ES81" ) { + @Components = ( @Components_rhel81 ); + @SubComponents = ( @SubComponents_newer ); + %ComponentInfo = ( %ComponentInfo, %ibacm_comp_info, + %intel_hfi_rhel81_comp_info, + %opa_stack_dev_comp_info, + %opa_stack_rhel_comp_info, + ); + } elsif ( "$CUR_VENDOR_VER" eq "ES15" ) { + @Components = ( @Components_sles15 ); + @SubComponents = ( @SubComponents_newer ); + %ComponentInfo = ( %ComponentInfo, %ibacm_comp_info, + %intel_hfi_sles15_comp_info, + %opa_stack_dev_comp_info, + %opa_stack_sles15_comp_info, + ); + } elsif ( "$CUR_VENDOR_VER" eq "ES151" ) { + @Components = ( @Components_sles15_sp1 ); + @SubComponents = ( @SubComponents_newer ); + %ComponentInfo = ( %ComponentInfo, %ibacm_comp_info, + %intel_hfi_sles15_comp_info, + %opa_stack_dev_comp_info, + %opa_stack_sles15_comp_info, + ); + } else { + # unknown or unsupported distro, leave lists empty + # verify_distrib_files will catch unsupported distro + @Components = ( ); + @SubComponents = ( ); + } +} + +# ========================================================================== +# opaconfig installation +# This is a special WrapperComponent which only needs: +# available, install and uninstall +# it cannot have startup scripts, dependencies, prereqs, etc + +sub available_opaconfig +{ + my $srcdir=$ComponentInfo{'opaconfig'}{'SrcDir'}; + return (rpm_resolve("$srcdir/*/opaconfig", "any")); +} + +sub installed_opaconfig +{ + return rpm_is_installed("opaconfig", "any"); +} + +sub installed_version_opaconfig +{ + my $version = rpm_query_version_release_pkg("opaconfig"); + return dot_version("$version"); +} + +sub media_version_opaconfig +{ + my $srcdir = $ComponentInfo{'opaconfig'}{'SrcDir'}; + my $rpm = rpm_resolve("$srcdir/RPMS/*/opaconfig", "any"); + my $version = rpm_query_version_release($rpm); + return dot_version("$version"); +} + +sub build_opaconfig +{ + my $osver = $_[0]; + my $debug = $_[1]; # enable extra debug of build itself + my $build_temp = $_[2]; # temp area for use by build + my $force = $_[3]; # force a rebuild + return 0; # success +} + +sub need_reinstall_opaconfig($$) +{ + my $install_list = shift(); # total that will be installed when done + my $installing_list = shift(); # what items are being installed/reinstalled + + return "no"; +} + +sub check_os_prereqs_opaconfig +{ + return rpm_check_os_prereqs("opaconfig", "user"); +} + +sub preinstall_opaconfig +{ + my $install_list = $_[0]; # total that will be installed when done + my $installing_list = $_[1]; # what items are being installed/reinstalled + + return 0; # success +} + +sub install_opaconfig +{ + my $install_list = $_[0]; # total that will be installed when done + my $installing_list = $_[1]; # what items are being installed/reinstalled + + my $srcdir=$ComponentInfo{'opaconfig'}{'SrcDir'}; + NormalPrint("Installing $ComponentInfo{'opaconfig'}{'Name'}...\n"); + + # all meta pkgs depend on opaconfig. We may directly upgrade opaconfig, so we remove them first. + rpm_uninstall_matches("opameta_", "opameta_", "", ""); + + # New Install Code + my $rpmfile = rpm_resolve("$srcdir/RPMS/*/opaconfig", "any"); + rpm_run_install($rpmfile, "any", " -U "); + # New Install Code + + # remove the old style version file + system("rm -rf /$BASE_DIR/version"); + # version_wrapper is only for support (fetched in opacapture) + system("echo '$VERSION' > $BASE_DIR/version_wrapper 2>/dev/null"); + # make sure we cleanup possibly old opaconfig_* files + system("rm -rf /sbin/opa_config_ff"); + system("rm -rf /sbin/opa_config_fm"); + system("rm -rf /sbin/opa_config_srp"); + system("rm -rf /sbin/opa_config_vnic"); + system("rm -rf /sbin/opa_config_delta"); + + $ComponentWasInstalled{'opaconfig'}=1; +} + +sub postinstall_opaconfig +{ + my $install_list = $_[0]; # total that will be installed when done + my $installing_list = $_[1]; # what items are being installed/reinstalled +} + +sub uninstall_opaconfig +{ + my $install_list = $_[0]; # total that will be left installed when done + my $uninstalling_list = $_[1]; # what items are being uninstalled + + NormalPrint("Uninstalling $ComponentInfo{'opaconfig'}{'Name'}...\n"); + + # all meta pkgs depend on opaconfig. Remove them first. + rpm_uninstall_matches("opameta_", "opameta_", "", ""); + + # New Uninstall Code + rpm_uninstall_list("any", "verbose", ("opaconfig") ); + # New Uninstall Code + + system("rm -rf $BASE_DIR/version_wrapper"); + system("rm -rf $BASE_DIR/osid_wrapper"); + # remove the old style version file + system("rm -rf /$BASE_DIR/version"); + system("rm -rf /sbin/opaconfig"); + # there is no ideal answer here, if we install updates separately + # then uninstall all with wrapper, make sure we cleanup + system("rm -rf /sbin/opa_config_ff"); + system("rm -rf /sbin/opa_config_fm"); + system("rm -rf /sbin/opa_config_srp"); + system("rm -rf /sbin/opa_config_vnic"); + system("rm -rf /sbin/opa_config_delta"); + system "rmdir $BASE_DIR 2>/dev/null"; # remove only if empty + system "rmdir $OPA_CONFIG_DIR 2>/dev/null"; # remove only if empty + $ComponentWasInstalled{'opaconfig'}=0; +} + +my $allow_install; +if ( my_basename($0) ne "INSTALL" ) +{ + $allow_install=0; +} else { + $allow_install=1; + $FabricSetupScpFromDir=".."; +} + +sub Usage +{ + if ( $allow_install ) { + #printf STDERR "Usage: $0 [-r root] [-v|-vv] -R osver -B osver [-d][-t tempdir] [--prefix dir] [--without-depcheck] [--rebuild] [--force] [--answer keyword=value]\n"; + #printf STDERR " or\n"; + #printf STDERR "Usage: $0 [-r root] [-v|-vv] [-a|-n|-U|-F|-u|-s|-i comp|-e comp] [-E comp] [-D comp] [-f] [--fwupdate asneeded|always] [-l] [--prefix dir] [--without-depcheck] [--rebuild] [--force] [--answer keyword=value]\n"; + #printf STDERR "Usage: $0 [-r root] [-v|-vv] [-a|-n|-U|-F|-u|-s|-i comp|-e comp] [-E comp] [-D comp] [-f] [--fwupdate asneeded|always] [--prefix dir] [--without-depcheck] [--rebuild] [--force] [--answer keyword=value]\n"; + printf STDERR "Usage: $0 [-v|-vv] -R osver [-a|-n|-U|-u|-s|-O|-N|-i comp|-e comp] [-G] [-E comp] [-D comp] [--user-space] [--without-depcheck] [--rebuild] [--force] [--answer keyword=value]\n"; + } else { +# printf STDERR "Usage: $0 [-r root] [-v|-vv] [-F|-u|-s|-e comp] [-E comp] [-D comp]\n"; +# printf STDERR " [--fwupdate asneeded|always] [--user_queries|--no_user_queries] [--answer keyword=value]\n"; + printf STDERR "Usage: $0 [-v|-vv] [-u|-s|-e comp] [-E comp] [-D comp]\n"; + printf STDERR " [--user_queries|--no_user_queries] [--answer keyword=value]\n"; + } + printf STDERR " or\n"; + printf STDERR "Usage: $0 -C\n"; + printf STDERR " or\n"; + printf STDERR "Usage: $0 -V\n"; + if ( $allow_install ) { + printf STDERR " -a - install all ULPs and drivers with default options\n"; + printf STDERR " -n - install all ULPs and drivers with default options\n"; + printf STDERR " but with no change to autostart options\n"; + printf STDERR " -U - upgrade/re-install all presently installed ULPs and drivers with\n"; + printf STDERR " default options and no change to autostart options\n"; + printf STDERR " -i comp - install the given component with default options\n"; + printf STDERR " can appear more than once on command line\n"; +# printf STDERR " -f - skip HCA firmware upgrade during install\n"; + printf STDERR " --user-space - Skip kernel space and firmware packages during installation\n"; + printf STDERR " can be useful when installing into a container\n"; + #printf STDERR " -l - skip creating/removing symlinks to /usr/local from /usr/lib/opa\n"; + printf STDERR " --without-depcheck - disable check of OS dependencies\n"; + printf STDERR " --rebuild - force OFA Delta rebuild\n"; + printf STDERR " --force - force install even if distro don't match\n"; + printf STDERR " Use of this option can result in undefined behaviors\n"; + printf STDERR " -O - Keep current modified rpm config file\n"; + printf STDERR " -N - Use new default rpm config file\n"; + + # -B, -t and -d options are purposely not documented + #printf STDERR " -B osver - run build for all components targetting kernel osver\n"; + #printf STDERR " -t - temp area for use by builds, only valid with -B\n"; + #printf STDERR " -d - enable build debugging assists, only valid with -B\n"; + printf STDERR " -R osver - force install for kernel osver rather than running kernel.\n"; + } +# printf STDERR " -F - upgrade HCA Firmware with default options\n"; +# printf STDERR " --fwupdate asneeded|always - select fw update auto update mode\n"; +# printf STDERR " asneeded - update or downgrade to match version in this release\n"; +# printf STDERR " always - rewrite with this releases version even if matches\n"; +# printf STDERR " default is to upgrade as needed but not downgrade\n"; +# printf STDERR " this option is ignored for interactive install\n"; + printf STDERR " -u - uninstall all ULPs and drivers with default options\n"; + printf STDERR " -s - enable autostart for all installed drivers\n"; + printf STDERR " -e comp - uninstall the given component with default options\n"; + printf STDERR " can appear more than once on command line\n"; + printf STDERR " -E comp - enable autostart of given component\n"; + printf STDERR " can appear with -D or more than once on command line\n"; + printf STDERR " -D comp - disable autostart of given component\n"; + printf STDERR " can appear with -E or more than once on command line\n"; + printf STDERR " -G - install GPU Direct components(must have NVidia drivers installed)\n"; + printf STDERR " -v - verbose logging\n"; + printf STDERR " -vv - very verbose debug logging\n"; + printf STDERR " -C - output list of supported components\n"; +# Hidden feature for internal use +# printf STDERR " -c comp - output component information in JSON format\n"; + printf STDERR " -V - output Version\n"; + + printf STDERR " --user_queries - permit non-root users to query the fabric. (default)\n"; + printf STDERR " --no_user_queries - non root users cannot query the fabric.\n"; + showAnswerHelp(); + + printf STDERR " default options retain existing configuration files\n"; + printf STDERR " supported component names:\n"; + printf STDERR " "; + ShowComponents(\*STDERR); + printf STDERR " supported component name aliases:\n"; + printf STDERR " opa ipoib mpi psm_mpi verbs_mpi pgas opadev\n"; + if (scalar(@SubComponents) > 0) { + printf STDERR " additional component names allowed for -E and -D options:\n"; + printf STDERR " "; + foreach my $comp ( @SubComponents ) + { + printf STDERR " $comp"; + } + printf STDERR "\n"; + } + exit (2); +} + +my $Default_FirmwareUpgrade=0; # -F option used to select default firmware upgrade + +# translate an ibaccess component name into the corresponding list of OFA comps +# if the given name is invalid or has no corresponding OFA component +# returns an empty list +sub translate_comp +{ + my($arg)=$_[0]; + if ("$arg" eq "opadev") { + return ( "opa_stack_dev" ); + } elsif ("$arg" eq "opa"){ + return ("oftools","mvapich2_gcc_hfi", "openmpi_gcc_hfi"); + } elsif ("$arg" eq "ipoib"){ + return ( "delta_ipoib" ); + } elsif ("$arg" eq "mpi"){ + return ( "mvapich2_gcc_hfi","openmpi_gcc_hfi"); + } elsif ("$arg" eq "psm_mpi"){ + return ( "mvapich2_gcc_hfi","openmpi_gcc_hfi"); + } elsif ("$arg" eq "delta_mpisrc"){ + return ( "mpisrc" ); # legacy + # no ibaccess argument equivalent for: + # delta_debug + # + } else { + return (); # invalid name + } +} + +sub process_args +{ + my $arg; + my $last_arg; + my $install_opt = 0; + my $setcomp = 0; + my $setanswer = 0; + my $setenabled = 0; + my $setdisabled = 0; + my $setosver = 0; + my $setbuildtemp = 0; + my $comp = 0; + my $osver = 0; + my $setcurosver = 0; + my $setfwmode = 0; + my $patch_ofed=0; + + if (scalar @ARGV >= 1) { + foreach $arg (@ARGV) { + if ( $setanswer ) { + my @pair = split /=/,$arg; + if ( scalar(@pair) != 2 ) { + printf STDERR "Invalid --answer keyword=value: '$arg'\n"; + Usage; + } + set_answer($pair[0], $pair[1]); + $setanswer=0; + } elsif ( $setcomp ) { + foreach $comp ( @Components ) + { + if ( "$arg" eq "$comp" ) + { + $Default_Components{$arg} = 1; + $setcomp=0; + } + } + if ( $setcomp ) + { + my @comps = translate_comp($arg); + # if empty list returned, we will not clear setcomp and + # will get error below + foreach $comp ( @comps ) + { + $Default_Components{$comp} = 1; + $setcomp=0; + } + } + if ( $setcomp ) + { + printf STDERR "Invalid component: $arg\n"; + Usage; + } + } elsif ( $setenabled ) { + foreach $comp ( @Components, @SubComponents ) + { + if ( "$arg" eq "$comp" ) + { + $Default_EnabledComponents{$arg} = 1; + $setenabled=0; + } + } + if ( $setenabled ) + { + my @comps = translate_comp($arg); + # if empty list returned, we will not clear setcomp and + # will get error below + foreach $comp ( @comps ) + { + $Default_EnabledComponents{$comp} = 1; + $setenabled=0; + } + } + if ( $setenabled ) + { + printf STDERR "Invalid component: $arg\n"; + Usage; + } + } elsif ( $setdisabled ) { + foreach $comp ( @Components, @SubComponents ) + { + if ( "$arg" eq "$comp" ) + { + $Default_DisabledComponents{$arg} = 1; + $setdisabled=0; + } + } + if ( $setdisabled ) + { + my @comps = translate_comp($arg); + # if empty list returned, we will not clear setcomp and + # will get error below + foreach $comp ( @comps ) + { + $Default_DisabledComponents{$comp} = 1; + $setdisabled=0; + } + } + if ( $setdisabled ) + { + printf STDERR "Invalid component: $arg\n"; + Usage; + } + } elsif ( $setosver ) { + $Build_OsVer="$arg"; + $setosver=0; + } elsif ( $setbuildtemp ) { + $Build_Temp="$arg"; + $setbuildtemp=0; +# } elsif ( $setfwmode ) { +# if ( "$arg" eq "always" || "$arg" eq "asneeded") { +# $Default_FirmwareUpgradeMode="$arg"; +# } else { +# printf STDERR "Invalid --fwupdate mode: $arg\n"; +# Usage; +# } +# $setfwmode = 0; + } elsif ( $setcurosver ) { + $CUR_OS_VER="$arg"; + $setcurosver=0; + } elsif ( "$arg" eq "-v" ) { + $LogLevel=1; + } elsif ( "$arg" eq "-vv" ) { + $LogLevel=2; +# } elsif ( "$arg" eq "-f" ) { +# $Skip_FirmwareUpgrade=1; + } elsif ( "$arg" eq "-i" ) { + $Default_CompInstall=1; + $Default_Prompt=1; + $setcomp=1; + if ($install_opt || $Default_CompUninstall || $Default_Build) { + # can't mix -i with other install controls + printf STDERR "Invalid combination of options: $arg not permitted with previous options\n"; + Usage; + } + } elsif ( "$arg" eq "-e" ) { + $Default_CompUninstall=1; + $Default_Prompt=1; + $setcomp=1; + if ($install_opt || $Default_CompInstall || $Default_Build) { + # can't mix -e with other install controls + printf STDERR "Invalid combination of options: $arg not permitted with previous options\n"; + Usage; + } + } elsif ( "$arg" eq "-E" ) { + $Default_Autostart=1; + $Default_EnableAutostart=1; + $Default_Prompt=1; + $setenabled=1; + if ($Default_Build) { + # can't mix -E with other install controls + printf STDERR "Invalid combination of options: $arg not permitted with previous options\n"; + Usage; + } + } elsif ( "$arg" eq "-D" ) { + $Default_Autostart=1; + $Default_DisableAutostart=1; + $Default_Prompt=1; + $setdisabled=1; + if ($Default_Build) { + # can't mix -D with other install controls + printf STDERR "Invalid combination of options: $arg not permitted with previous options\n"; + Usage; + } + } elsif ( "$arg" eq "--fwupdate" ) { + $setfwmode=1; + } elsif ( "$arg" eq "--answer" ) { + $setanswer=1; + } elsif ( "$arg" eq "--without-depcheck" ) { + $rpm_check_dependencies=0; + } elsif ( "$arg" eq "--user-space" ) { + $user_space_only = 1; + } elsif ( "$arg" eq "--force" ) { + $Force_Install=1; + } elsif ( "$arg" eq "-G") { + if ($HFI2_INSTALL) { + printf STDERR "Invalid option: $arg not supported in 11.x OPA for HFI2.\n"; + Usage; + } else { + $GPU_Install=1; + } + } elsif ( "$arg" eq "-C" ) { + ShowComponents; + exit(0); + } elsif ( "$arg" eq "-c" ) { + # undocumented option to output detailed information on a component + $Default_ShowCompInfo=1; + $setcomp=1; + } elsif ( "$arg" eq "-V" ) { + printf "$VERSION\n"; + exit(0); + } elsif ( "$arg" eq "-R" ) { + $setcurosver=1; + } elsif ( "$arg" eq "-B" ) { + # undocumented option to do a build for specific OS + $Default_Build=1; + $Default_Prompt=1; + $setosver=1; + if ($install_opt || $Default_CompInstall || $Default_CompUninstall || $Default_Autostart) { + # can't mix -B with install + printf STDERR "Invalid combination of options: $arg not permitted with previous options\n"; + Usage; + } + } elsif ( "$arg" eq "-d" ) { + # undocumented option to aid debug of build + $Build_Debug=1; + if ($install_opt || $Default_CompInstall || $Default_CompUninstall || $Default_Autostart) { + # can't mix -d with install + printf STDERR "Invalid combination of options: $arg not permitted with previous options\n"; + Usage; + } + } elsif ( "$arg" eq "-t" ) { + # undocumented option to aid debug of build + $setbuildtemp=1; + if ($install_opt || $Default_CompInstall || $Default_CompUninstall || $Default_Autostart) { + # can't mix -t with install + printf STDERR "Invalid combination of options: $arg not permitted with previous options\n"; + Usage; + } + } elsif ( "$arg" eq "--rebuild" ) { + # force rebuild + $Build_Force=1; + $OFED_force_rebuild=1; + } elsif ( "$arg" eq "--user_queries" ) { + $Default_UserQueries=1; + } elsif ( "$arg" eq "--no_user_queries" ) { + $Default_UserQueries=-1; + } elsif ( "$arg" eq "--patch_ofed" ) { + $patch_ofed=1; + } else { + # Install options + if ( "$arg" eq "-a" ) { + $Default_Install=1; + } elsif ( "$arg" eq "-u" ) { + $Default_Uninstall=1; + } elsif ( "$arg" eq "-s" ) { + $Default_Autostart=1; + } elsif ( "$arg" eq "-n" ) { + $Default_Install=1; + $Default_SameAutostart=1; + } elsif ( "$arg" eq "-U" ) { + $Default_Upgrade=1; + $Default_SameAutostart=1; +# } elsif ( "$arg" eq "-F" ) { +# $Default_FirmwareUpgrade=1; + } elsif ("$arg" eq "-O") { + $Default_RpmConfigKeepOld=1; + $Default_RpmConfigUseNew=0; + } elsif ("$arg" eq "-N") { + $Default_RpmConfigKeepOld=0; + $Default_RpmConfigUseNew=1; + } else { + printf STDERR "Invalid option: $arg\n"; + Usage; + } + if ($install_opt || $Default_CompInstall + || $Default_CompUninstall) { + # only one of the above install selections + printf STDERR "Invalid combination of options: $arg not permitted with previous options\n"; + Usage; + } + $install_opt=1; + if ( $Default_RpmConfigKeepOld || $Default_RpmConfigUseNew) { + $Default_Prompt=0; + } else { + $Default_Prompt=1; + } + } + $last_arg=$arg; + } + } + if ( $setcomp || $setenabled || $setdisabled || $setosver || $setbuildtemp || $setfwmode || $setanswer) { + printf STDERR "Missing argument for option: $last_arg\n"; + Usage; + } + if ( ($Default_Install || $Default_CompInstall || $Default_Upgrade + || $Force_Install) + && ! $allow_install) { + printf STDERR "Installation options not permitted in this mode\n"; + Usage; + } + if ( ($Default_Build || $OFED_force_rebuild ) && ! $allow_install) { + printf STDERR "Build options not permitted in this mode\n"; + Usage; + } + if ( $patch_ofed) { + NormalPrint("Patching OFA...\n"); + LogPrint("Executing: cd $ComponentInfo{'opa_stack'}{'SrcDir'}; ./patch_ofed3\n"); + system("cd $ComponentInfo{'opa_stack'}{'SrcDir'}; ./patch_ofed3"); + HitKeyCont; + } +} + +my @INSTALL_CHOICES= (); +sub show_menu +{ + my $inp; + my $max_inp; + + @INSTALL_CHOICES= (); + if ( $Default_Install ) { + NormalPrint ("Installing All OPA Software\n"); + @INSTALL_CHOICES = ( @INSTALL_CHOICES, 1); + } + if ( $Default_CompInstall ) { + NormalPrint ("Installing Selected OPA Software\n"); + @INSTALL_CHOICES = ( @INSTALL_CHOICES, 1); + } + if ( $Default_Upgrade ) { + NormalPrint ("Upgrading/Re-Installing OPA Software\n"); + @INSTALL_CHOICES = ( @INSTALL_CHOICES, 1); + } +# if ( $Default_FirmwareUpgrade ) { +# NormalPrint ("Upgrading HCA Firmware\n"); +# @INSTALL_CHOICES = ( @INSTALL_CHOICES, 4); +# } + if ($Default_Uninstall ) { + NormalPrint ("Uninstalling All OPA Software\n"); + @INSTALL_CHOICES = ( @INSTALL_CHOICES, 6); + } + if ($Default_CompUninstall ) { + NormalPrint ("Uninstalling Selected OPA Software\n"); + @INSTALL_CHOICES = ( @INSTALL_CHOICES, 6); + } + if ($Default_Autostart) { + NormalPrint ("Configuring autostart for Selected installed OPA Drivers\n"); + @INSTALL_CHOICES = ( @INSTALL_CHOICES, 3); + } + if (scalar(@INSTALL_CHOICES) > 0) { + return; + } + system "clear"; + printf ("$BRAND OPA $VERSION Software\n\n"); + if ($allow_install) { + printf (" 1) Install/Uninstall Software\n"); + } else { + printf (" 1) Show Installed Software\n"); + } + printf (" 2) Reconfigure $ComponentInfo{'delta_ipoib'}{'Name'}\n"); + printf (" 3) Reconfigure Driver Autostart \n"); + printf (" 4) Generate Supporting Information for Problem Report\n"); + printf (" 5) FastFabric (Host/Chassis/Switch Setup/Admin)\n"); +# printf (" 6) Update HCA Firmware\n"); + $max_inp=5; + if (!$allow_install) + { +# printf (" 7) Uninstall Software\n"); + printf (" 6) Uninstall Software\n"); + $max_inp=6; + } + printf ("\n X) Exit\n"); + + while( $inp < 1 || $inp > $max_inp) { + $inp = getch(); + + if ($inp =~ /[qQ]/ || $inp =~ /[Xx]/ ) { + return 1; + } + if ($inp =~ /[0123456789abcdefABCDEF]/) + { + $inp = hex($inp); + } + } + @INSTALL_CHOICES = ( $inp ); + return 0; +} + +determine_os_version; +init_components; + +# when this is used as main for a component specific INSTALL +# the component can provide some overrides of global settings such as Components +overrides; + +process_args; +check_root_user; +if ( $Default_ShowCompInfo ) +{ + ShowCompInfo(); + exit(0); +} +if ( ! $Default_Build ) { + open_log(""); +} else { + open_log("./build.log"); +} + +if ( ! $Default_Build ) { + verify_modtools; + if ($allow_install) { + verify_distrib_files; + } +} + +set_libdir; +init_delta_info($CUR_OS_VER); + +do{ + if ($Default_Build) { + $exit_code = build_all_components($Build_OsVer, $Build_Debug, $Build_Temp, $Build_Force); + done(); + } else { + if ( show_menu != 0) { + done(); + } + } + + foreach my $INSTALL_CHOICE ( @INSTALL_CHOICES ) + { + if ($allow_install && $INSTALL_CHOICE == 1) + { + select_debug_release("."); + show_install_menu(1); + if ($Default_Prompt) { + if ($exit_code == 0) { + print "Done Installing OPA Software.\n" + } else { + print "Failed to install all OPA software.\n" + } + } + } + elsif ($INSTALL_CHOICE == 1) { + show_installed(1); + } + elsif ($INSTALL_CHOICE == 6) + { + show_uninstall_menu(1); + if ( $Default_Prompt ) { + if ($exit_code == 0) { + print "Done Uninstalling OPA Software.\n" + } else { + print "Failed to uninstall all OPA Software.\n" + } + } + } + elsif ($INSTALL_CHOICE == 2) + { + Config_ifcfg(1,"$ComponentInfo{'delta_ipoib'}{'Name'}","ib", "$FirstIPoIBInterface",1); + check_network_config; + } + elsif ($INSTALL_CHOICE == 3) + { + reconfig_autostart; + if ( $Default_Prompt ) { + print "Done OPA Driver Autostart Configuration.\n" + } + } + elsif ($INSTALL_CHOICE == 4) + { + # Generate Supporting Information for Problem Report + capture_report($ComponentInfo{'oftools'}{'Name'}); + } + elsif ($INSTALL_CHOICE == 5) + { + # FastFabric (Host/Chassis/Switch Setup/Admin) + run_fastfabric($ComponentInfo{'fastfabric'}{'Name'}); + } + } +}while( !$Default_Prompt ); +done(); +sub done() { + if ( not $user_space_only ) { + do_rebuild_ramdisk; + } + close_log; + exit $exit_code; +} diff --git a/CommonInstall/ofed_firmware.pl b/CommonInstall/ofed_firmware.pl new file mode 100755 index 0000000..221d30d --- /dev/null +++ b/CommonInstall/ofed_firmware.pl @@ -0,0 +1,37 @@ +#!/usr/bin/perl +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] +use strict; + +my $Default_FirmwareUpgradeMode=""; # --fwupdate option +# "" - normal operation for upgrade +# "asneeded" - force update to this rev unless already on HCA +# "always" - force update to this rev diff --git a/CommonInstall/overrides_delta.pl b/CommonInstall/overrides_delta.pl new file mode 100644 index 0000000..4426c0f --- /dev/null +++ b/CommonInstall/overrides_delta.pl @@ -0,0 +1,158 @@ +#!/usr/bin/perl +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] +use strict; +#use Term::ANSIColor; +#use Term::ANSIColor qw(:constants); +#use File::Basename; +#use Math::BigInt; + + # Names of supported install components + # must be listed in dependency order such that prereqs appear 1st + # delta_debug must be last +my @delta_Components_rhel72 = ( "opa_stack", "ibacm", "mpi_selector", "intel_hfi", + "opa_stack_dev", + "delta_ipoib", + "delta_debug", ); +my @delta_Components_sles12_sp2 = ( "opa_stack", "intel_hfi", + "opa_stack_dev", + "delta_ipoib", + "delta_debug", ); +my @delta_Components_rhel73 = ( "opa_stack", "mpi_selector", "intel_hfi", + "opa_stack_dev", + "delta_ipoib", + "delta_debug", ); +my @delta_Components_sles12_sp3 = ( "opa_stack", "intel_hfi", + "opa_stack_dev", + "delta_ipoib", + "delta_debug", ); +my @delta_Components_sles12_sp4 = ( "opa_stack", "intel_hfi", + "opa_stack_dev", + "delta_ipoib", + "delta_debug", ); +my @delta_Components_sles12_sp5 = ( "opa_stack", "intel_hfi", + "opa_stack_dev", + "delta_ipoib", + "delta_debug", ); +my @delta_Components_rhel74 = ( "opa_stack", "mpi_selector", "intel_hfi", + "opa_stack_dev", + "delta_ipoib", + "delta_debug", ); +my @delta_Components_rhel75 = ( "opa_stack", "mpi_selector", "intel_hfi", + "opa_stack_dev", + "delta_ipoib", + "delta_debug", ); +my @delta_Components_rhel76 = ( "opa_stack", "mpi_selector", "intel_hfi", + "opa_stack_dev", + "delta_ipoib", + "delta_debug", ); +my @delta_Components_rhel77 = ( "opa_stack", "mpi_selector", "intel_hfi", + "opa_stack_dev", + "delta_ipoib", + "delta_debug", ); +my @delta_Components_rhel8 = ( "opa_stack", "mpi_selector", "intel_hfi", + "opa_stack_dev", + "delta_ipoib", + "delta_debug", ); +my @delta_Components_rhel81 = ( "opa_stack", "mpi_selector", "intel_hfi", + "opa_stack_dev", + "delta_ipoib", + "delta_debug", ); +my @delta_Components_sles15 = ( "opa_stack", "intel_hfi", + "opa_stack_dev", + "delta_ipoib", + "delta_debug", ); +my @delta_Components_sles15_sp1 = ( "opa_stack", "intel_hfi", + "opa_stack_dev", + "delta_ipoib", + "delta_debug", ); + +@Components = ( ); +# RHEL7.2, ibacm is a full component with rpms to install +my @delta_SubComponents_older = ( "rdma_ndd", "delta_srp", "delta_srpt" ); +# RHEL7.3 and newer AND SLES12.2 and newer +my @delta_SubComponents_newer = ( "ibacm", "rdma_ndd", "delta_srp", "delta_srpt" ); +@SubComponents = ( ); + +# override some of settings in main_omnipathwrap_delta.pl +sub overrides() +{ + # The component list has slight variations per distro + if ( "$CUR_VENDOR_VER" eq "ES72" ) { + @Components = ( @delta_Components_rhel72 ); + } elsif ( "$CUR_VENDOR_VER" eq "ES122" ) { + @Components = ( @delta_Components_sles12_sp2 ); + } elsif ( "$CUR_VENDOR_VER" eq "ES73" ) { + @Components = ( @delta_Components_rhel73 ); + } elsif ( "$CUR_VENDOR_VER" eq "ES123" ) { + @Components = ( @delta_Components_sles12_sp3 ); + } elsif ( "$CUR_VENDOR_VER" eq "ES124" ) { + @Components = ( @delta_Components_sles12_sp4 ); + } elsif ( "$CUR_VENDOR_VER" eq "ES125" ) { + @Components = ( @delta_Components_sles12_sp5 ); + } elsif ( "$CUR_VENDOR_VER" eq "ES74" ) { + @Components = ( @delta_Components_rhel74 ); + } elsif ( "$CUR_VENDOR_VER" eq "ES75" ) { + @Components = ( @delta_Components_rhel75 ); + } elsif ( "$CUR_VENDOR_VER" eq "ES76" ) { + @Components = ( @delta_Components_rhel76 ); + } elsif ( "$CUR_VENDOR_VER" eq "ES77" ) { + @Components = ( @delta_Components_rhel77 ); + } elsif ( "$CUR_VENDOR_VER" eq "ES8" ) { + @Components = ( @delta_Components_rhel8 ); + } elsif ( "$CUR_VENDOR_VER" eq "ES81" ) { + @Components = ( @delta_Components_rhel81 ); + } elsif ( "$CUR_VENDOR_VER" eq "ES15" ) { + @Components = ( @delta_Components_sles15 ); + } elsif ( "$CUR_VENDOR_VER" eq "ES151" ) { + @Components = ( @delta_Components_sles15_sp1 ); + } else { + # unsupported OS + @Components = ( ); + } + + # Sub components for autostart processing + if ( "$CUR_VENDOR_VER" eq "ES72" ) { + @SubComponents = ( @delta_SubComponents_older ); + } else { + @SubComponents = ( @delta_SubComponents_newer ); + } + + # TBD remove this concept + # no WrapperComponent (eg. opaconfig) + $WrapperComponent = ""; + + # set SrcDir for all components to . + foreach my $comp ( @Components ) + { + $ComponentInfo{$comp}{'SrcDir'} = "."; + } +} diff --git a/CommonInstall/overrides_ff.pl b/CommonInstall/overrides_ff.pl new file mode 100644 index 0000000..69069ae --- /dev/null +++ b/CommonInstall/overrides_ff.pl @@ -0,0 +1,64 @@ +#!/usr/bin/perl +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] +use strict; +#use Term::ANSIColor; +#use Term::ANSIColor qw(:constants); +#use File::Basename; +#use Math::BigInt; + +# override some of settings in main_omnipathwrap_delta.pl +sub overrides() +{ + # Names of supported install components + # must be listed in depdency order such that prereqs appear 1st + @Components = ( "oftools", "fastfabric", "opamgt_sdk" ); + + # Sub components for autostart processing + @SubComponents = ( ); + + # TBD remove this concept + # no WrapperComponent (eg. opaconfig) + $WrapperComponent = ""; + + # set SrcDir for all components to . + foreach my $comp ( @Components ) + { + $ComponentInfo{$comp}{'SrcDir'} = "."; + } +} + +# main_omnipathwrap_delta.pl calls this, but since we don't have comp_delta.pl +# we just provide a dummy function to keep PERL happy +# TBD - move this to util_init.pl? +sub init_delta_info($) +{ +} diff --git a/CommonInstall/overrides_fm.pl b/CommonInstall/overrides_fm.pl new file mode 100644 index 0000000..d8c0777 --- /dev/null +++ b/CommonInstall/overrides_fm.pl @@ -0,0 +1,64 @@ +#!/usr/bin/perl +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] +use strict; +#use Term::ANSIColor; +#use Term::ANSIColor qw(:constants); +#use File::Basename; +#use Math::BigInt; + +# override some of settings in main_omnipathwrap_delta.pl +sub overrides() +{ + # Names of supported install components + # must be listed in depdency order such that prereqs appear 1st + @Components = ( "opafm" ); + + # Sub components for autostart processing + @SubComponents = ( ); + + # TBD remove this concept + # no WrapperComponent (eg. opaconfig) + $WrapperComponent = ""; + + # set SrcDir for all components to . + foreach my $comp ( @Components ) + { + $ComponentInfo{$comp}{'SrcDir'} = "."; + } +} + +# main_omnipathwrap_delta.pl calls this, but since we don't have comp_delta.pl +# we just provide a dummy function to keep PERL happy +# TBD - move this to util_init.pl? +sub init_delta_info($) +{ +} diff --git a/CommonInstall/query_files.sh b/CommonInstall/query_files.sh new file mode 100755 index 0000000..1cfb569 --- /dev/null +++ b/CommonInstall/query_files.sh @@ -0,0 +1,57 @@ +#!/bin/bash +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# helpful tool to help identify what files are in each of a set of rpms +# Usage: query_files.sh [dir [rpmfiles]] +dir=. +if [ "$1" != "" ] +then + dir="$1" +fi +shift +cd $dir +query_rpm() +{ + echo "$1:" + rpm -q --filesbypkg -p $1 + echo "-------------------------------------------------------------------------------" +} +if [ "$1" != "" ] +then + for file in "$@" + do + query_rpm $file + done +else + for file in *.rpm + do + query_rpm $file + done +fi diff --git a/CommonInstall/rpm_query b/CommonInstall/rpm_query new file mode 100755 index 0000000..644ab1d --- /dev/null +++ b/CommonInstall/rpm_query @@ -0,0 +1,33 @@ +#!/bin/bash +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +#[ICS VERSION STRING: unknown] + +rpm --queryformat '[%{NAME}-%{VERSION}-%{RELEASE}.%{ARCH}\n]' -q $1 diff --git a/CommonInstall/util_basicfile.pl b/CommonInstall/util_basicfile.pl new file mode 100755 index 0000000..53cbbcb --- /dev/null +++ b/CommonInstall/util_basicfile.pl @@ -0,0 +1,235 @@ +#!/usr/bin/perl +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] +use strict; +#use Term::ANSIColor; +#use Term::ANSIColor qw(:constants); +#use File::Basename; +#use Math::BigInt; + +# =========================================================================== +# Basic file/directory install/remove + +my $OWNER = "root"; +my $GROUP = "root"; + +# remove any directory prefixes from path +sub my_basename($) +{ + my($path) = shift(); + + $path =~ s/.*\/(.*)$/$1/; + return $path; +} + +# check for a file using a glob pattern +# return 1st filename to match pattern +# return "" if no match +sub file_glob($) +{ + my $globpat = shift(); # glob pattern to expand + + my $file; + # there is a little perl trick here, glob returns a list of matching + # files. If we simply assigned glob to a scalar it would retain + # the rest of the list and return subsequent entries on future glob calls + # then it would return "" after the last matched name. + # Hence even if glob matched only 1 name, it would return a 2nd "" + # value to a future caller. real subtle problem to figure out. + + # the list assignment below allows glob to return a list + # and all extra list entries are discarded. Hence this returns the + # first filename which matches or "" if none are matched + ( $file) = glob("$globpat"); + + return "$file"; +} + +sub make_dir($$$$) +{ + my($dir) = shift(); + my($owner) = shift(); + my($group) = shift(); + my($mode) = shift(); + + system "mkdir -p -m $mode $dir"; + system "chown $owner $dir"; + system "chgrp $group $dir"; +} + +sub check_dir($) +{ + my($dir) = shift(); + if (! -d "$dir" ) + { + #Creating directory + + make_dir("$dir", "$OWNER", "$GROUP", "ugo=rx,u=rwx"); + } +} + +sub copy_file($$$$$) +{ + my($src) = shift(); + my($dest) = shift(); + my($owner) = shift(); + my($group) = shift(); + my($mode) = shift(); + # only copy file if source exists, this keep all those cp errors for litering + # install for development. + + if ( -e $src) + { + system "cp -rf $src $dest"; + system "chown $owner $dest"; + system "chgrp $group $dest"; + system "chmod $mode $dest"; + } +} + +sub symlink_usrlocal($$) +{ + my($src) = shift(); + my($dest) = shift(); +} + +sub copy_all_files($$$$$;$) +{ + my($src_dir)=shift(); + my($dest_dir)=shift(); + my($owner) = shift(); + my($group) = shift(); + my($mode) = shift(); + my($symlink_dir) = shift(); # optional argument + my(@files); + my $f; + my $d; + + if (!-d "$src_dir" ) + { + return; + } + if (!-d "$dest_dir") + { + return; + } + @files = glob("$src_dir/*"); + foreach $f (@files) + { + $d= my_basename($f); + if (!-d $f) + { + copy_file($f, "$dest_dir/$d", $owner, $group, $mode); + if ( "$symlink_dir" ne "") { + symlink_usrlocal("$dest_dir/$d", "$symlink_dir/$d"); + } + } else { + check_dir("$dest_dir/$d"); + copy_all_files($f, "$dest_dir/$d", $owner, $group, $mode,""); + } + } + } + +sub remove_file($) +{ + my($file) = shift(); + system "rm -f $file"; +} + +sub copy_data_file($$) +{ + copy_file("$_[0]", "$_[1]", "$OWNER", "$GROUP", "ugo=r,u=rw"); +} + +sub copy_systool_file($$) +{ + # Administrator execution only + copy_file("$_[0]", "$_[1]", "$OWNER", "$GROUP", "ug=rx,u=rwx"); +} + +# (as listed in .files and .dirs) +# $0 = dirname relative to +sub remove_installed_files($) +{ + my $dirname = shift(); + + # remove files we installed or user compiled, however do not remove + # any logs or other files the user may have created + if ( -d "/$dirname" ) { + system "cd /$dirname; for dir in `cat .dirs 2>/dev/null`; do ( cd \$dir; make clobber ) >/dev/null 2>&1; done"; + system "cd /$dirname; cat .files 2>/dev/null|xargs rm -f 2>/dev/null"; + system "cd /$dirname; cat .files 2>/dev/null|sort -r|xargs rmdir 2>/dev/null"; + system "rm -f /$dirname/.files 2>/dev/null"; + system "rm -f /$dirname/.dirs 2>/dev/null"; + system "rmdir /$dirname/ 2>/dev/null"; + } +} + +# =========================================================================== +# Shared Libaries +my $RunLdconfig=0; + +sub check_ldconfig() +{ + if ($RunLdconfig == 1 ) + { + print_separator; + print "Updating dynamic linker cache...\n"; + # this is how /etc/rc.sysinit runs ldconfig + #LogPrint "Updating dynamic linker cache: /sbin/ldconfig -n /lib\n"; + #system "/sbin/ldconfig -n /lib > /dev/null 2>&1"; + LogPrint "Updating dynamic linker cache: /sbin/ldconfig\n"; + system "/sbin/ldconfig > /dev/null 2>&1"; + $RunLdconfig=0; + return 1; + } + return 0; +} + +# =========================================================================== +# Will Reboot be required +my $NeedReboot=0; +sub need_reboot() +{ + $NeedReboot=1; +} + +sub check_need_reboot() +{ + if ($NeedReboot == 1 ) + { + print_separator; + print BOLD, RED, "A System Reboot is recommended to activate the software changes\n", RESET; + LogPrint "A System Reboot is recommended to activate the software changes\n"; + return 1; + } + return 0; +} diff --git a/CommonInstall/util_basicio.pl b/CommonInstall/util_basicio.pl new file mode 100755 index 0000000..7bcd513 --- /dev/null +++ b/CommonInstall/util_basicio.pl @@ -0,0 +1,423 @@ +#!/usr/bin/perl +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] +use strict; +#use Term::ANSIColor; +#use Term::ANSIColor qw(:constants); +#use File::Basename; +#use Math::BigInt; + +# ========================================================================== +# Installation logging + +my $LogLevel = 0; # 0 = normal/quiet, 1=verbose, 2=very verbose +my $LogFile = "/dev/null"; # set when open_log + +sub open_log(;$) +{ + my($logfile) = shift(); + if ( "$logfile" eq "" ) { + $logfile="/var/log/opa.log"; + } + $LogFile = $logfile; + open(LOG_FD, ">>$logfile"); + print LOG_FD "-------------------------------------------------------------------------------\n"; + print LOG_FD my_basename($0) . " $INT_VERSION Run " . `/bin/date`; + print LOG_FD "$0 @ARGV\n"; + print LOG_FD "Current Dir: " . getcwd() . "\n"; +} + +sub close_log() +{ + close LOG_FD; +} + +# output to log and screen and die +sub Abort(@) +{ + print(LOG_FD @_); + die(@_); +} + +# output to log and screen +sub NormalPrint(@) +{ + print(@_); + print(LOG_FD @_); +} + +# output to log only +sub LogPrint(@) +{ + print(LOG_FD @_); +} + +sub VerbosePrintEnabled() +{ + return ($LogLevel >= 1); +} + +sub VerbosePrint(@) +{ + if (VerbosePrintEnabled() ) { + print(LOG_FD @_); + } +} +sub DebugPrintEnabled() +{ + return ($LogLevel >= 2); +} + +sub DebugPrint(@) +{ + if (DebugPrintEnabled() ) { + print(LOG_FD @_); + } +} + +# ============================================================================ +# Basic input and prompting routines +my $KEY_ESC=27; +my $KEY_CNTL_C=3; +my $KEY_ENTER=13; + +my $Default_Prompt=0; # use default values at prompts, non-interactive + +sub getch() +{ + my $c; + system("stty -echo raw"); + $c=getc(STDIN); + system("stty echo -raw"); + return $c; +} + +sub HitKeyCont() +{ + if ( $Default_Prompt ) + { + return; + } + + print "Hit any key to continue..."; + getch(); + return; +} + +sub remove_whitespace($) +{ + my $string=shift(); + chomp($string); + $string =~ s/^[[:space:]]*//; # remove leading + $string =~ s/[[:space:]]*$//; # remove trailing + return $string; +} + +# return numeric value: minimum <= value <= maximum +sub GetNumericValue($$$$) +{ + my($retval) = 0; + + my($Question) = $_[0]; + my($default) = $_[1]; + my($minvalue) = $_[2]; + my($maxvalue) = $_[3]; + + if ( $Default_Prompt ) { + NormalPrint "$Question -> $default\n"; + if (($default ge $minvalue) && ($default le $maxvalue)) { + return $default; + } + # for invalid default, fall through and prompt + } + + while (1) + { + NormalPrint "$Question [$default]: "; + chomp($retval = ); + $retval=remove_whitespace($retval); + + if (length($retval) == 0) { + $retval=$default; + } + if (($retval >= $minvalue) && ($retval <= $maxvalue)) { + LogPrint "$Question -> $retval\n"; + return $retval; + } + else { + NormalPrint "Value Out-of-Range\n"; + } + } +} + +#return 0 for no, 1 for yes +sub GetYesNo($$) +{ + my($Question) = shift(); + my($default) = shift(); + + my($retval) = 1; + my($answer) = 0; + + if ( $Default_Prompt ) { + NormalPrint "$Question ->$default\n"; + if ( "$default" eq "y") { + return 1; + } elsif ("$default" eq "n") { + return 0; + } + # for invalid default, fall through and prompt + } + + while ($answer == 0) + { + print "$Question [$default]: "; + chomp($_ = ); + $_=remove_whitespace($_); + if ("$_" eq "") { + $_=$default; + } + if (/^[Nn]/) + { + LogPrint "$Question -> n\n"; + $retval = 0; + $answer = 1; + } elsif (/^[Yy]/ ) { + LogPrint "$Question -> y\n"; + $retval = 1; + $answer = 1; + } + } + return $retval; +} + +# we keep answers in text format. This way we can later enhance the command +# line argument list to allow answers to more complex questions +my %AnswerMemory = (); # keep track of past answers to yes/no questions + +my @AnswerHelp = (); # help test for each keyword + +sub AddAnswerHelp($$) +{ + my($Keyword) = shift(); + my($help) = shift(); + + # check for duplicates, skip if already in list + foreach my $ans (@AnswerHelp) + { + if ($ans =~ m/^$Keyword -/) + { + return; + } + } + @AnswerHelp = (@AnswerHelp, "$Keyword - $help"); +} + +sub showAnswerHelp() +{ + if (scalar(@AnswerHelp) != 0) { + printf STDERR " --answer keyword=value - provide an answer to a question which might\n"; + printf STDERR " occur during the operation. answers to questions which are not\n"; + printf STDERR " asked are ignored. Invalid answers will result in prompting\n"; + printf STDERR " for interactive installs or use of the default for non-interactive.\n"; + printf STDERR " Possible Questions:\n"; + foreach my $help (@AnswerHelp) { + printf STDERR " $help\n"; + } + } else { + printf STDERR " --answer keyword=value - presently ignored\n"; + } +} + +# similar to GetYesNo, except if the question has already been answered +# (or defaulted on the command line), the question is not asked, instead the +# previous answer is provided +sub GetYesNoWithMemory($$$$) +{ + my($Keyword) = shift(); # unique keyword to identify question + my($remember) = shift(); # remember answer for use next time + my($Question) = shift(); # the question shown to user + my($default) = shift(); # the default to use if not already remembered + my($retval); + + if ( exists $AnswerMemory{"$Keyword"}) + { + $_ = $AnswerMemory{"$Keyword"}; + if (/^[Nn]/) + { + NormalPrint "$Keyword: $Question -> n\n"; + $retval = 0; + } elsif (/^[Yy]/ ) { + NormalPrint "$Keyword: $Question -> y\n"; + $retval = 1; + } else { + # invalid answer, now what? prompt? + NormalPrint "$Keyword: $Question -> Invalid answer: $_\n"; + delete $AnswerMemory{"$Keyword"}; + } + } + if ( ! exists $AnswerMemory{"$Keyword"}) + { + $retval = GetYesNo($Question, $default); + if ($remember) { + my($ans); + if ( $retval ) { + $ans = "y"; + } else { + $ans = "n"; + } + $AnswerMemory{"$Keyword"} = $ans; + } + } + return $retval; +} + +sub set_answer($$) +{ + my($Keyword) = shift(); # unique keyword to identify question + my($answer) = shift(); # answer to question + + $AnswerMemory{"$Keyword"} = $answer; +} + +sub clear_answer($) +{ + my($Keyword) = shift(); + + delete $AnswerMemory{"$Keyword"}; +} + +sub clear_all_answers($) +{ + my $Keyword; + + foreach $Keyword (keys(%AnswerMemory)) + { + delete $AnswerMemory{"$Keyword"}; + } +} + + +#return choice +sub GetChoice($$@) +{ + my($Question) = shift(); + my($default) = shift(); + my(@choices) = @_; # single character choices + + my $c; + + if ( $Default_Prompt ) { + NormalPrint "$Question -> $default\n"; + foreach $c ( @choices ) + { + if (my_tolower("$default") eq my_tolower("$c")) { + return $c; + } + } + # for invalid default, fall through and prompt + } + + while (1) + { + print "$Question [$default]: "; + chomp($_ = ); + $_=remove_whitespace($_); + if ("$_" eq "") { + $_=$default; + } + $_ = my_tolower($_); + foreach $c ( @choices ) + { + if ("$_" eq my_tolower("$c")) { + LogPrint "$Question -> $c\n"; + return $c; + } + } + } + # NOTREACHED +} + +sub print_separator() +{ + print "-------------------------------------------------------------------------------\n"; +} + +# based on files on install media update DBG_FREE +# if both release and debug are available on media, prompt user +# This routine checks both the location for IbAccess and Open IB FF installs +sub select_debug_release($) +{ + my($srcdir) = shift(); + my $inp; + + # check current directory to determine if Debug available + if ( (! -d "$srcdir/bin/$ARCH/$CUR_OS_VER/debug") + and (! -d "$srcdir/bin/$ARCH/$CUR_DISTRO_VENDOR.$CUR_VENDOR_VER/lib/debug") + and (! -d "$srcdir/bin/$ARCH/$CUR_DISTRO_VENDOR.$CUR_VENDOR_MAJOR_VER/lib/debug") ) + { + # no choice, only release available + $DBG_FREE="release"; + } + elsif ( (! -d "$srcdir/bin/$ARCH/$CUR_OS_VER/release") + and (! -d "$srcdir/bin/$ARCH/$CUR_DISTRO_VENDOR.$CUR_VENDOR_VER/lib/release") + and (! -d "$srcdir/bin/$ARCH/$CUR_DISTRO_VENDOR.$CUR_VENDOR_MAJOR_VER/lib/release") ) + { + # no choice, only debug available + $DBG_FREE="debug"; + } elsif ( $Default_Prompt ) { + $DBG_FREE="release"; + printf ("Installing $DBG_FREE Software\n"); + } else { + printf ("Both Release and Debug versions are available\n\n"); + printf ("Please select which version should be used for install or upgrade operations:\n\n"); + printf ("1) Release Software\n"); + printf ("2) Debug Software\n"); + + $inp = getch(); + + if ($inp == 1) + { + $DBG_FREE="release"; + } + elsif ($inp == 2) + { + $DBG_FREE="debug"; + } + else + { + printf ("Invalid Choice...\n"); + HitKeyCont; + return; + } + } +} + diff --git a/CommonInstall/util_blacklist.pl b/CommonInstall/util_blacklist.pl new file mode 100755 index 0000000..8d819fc --- /dev/null +++ b/CommonInstall/util_blacklist.pl @@ -0,0 +1,146 @@ +#!/usr/bin/perl +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] +use strict; +#use Term::ANSIColor; +#use Term::ANSIColor qw(:constants); +#use File::Basename; +#use Math::BigInt; + +# ============================================================================= +# The functions and constants below assist in editing hotplug and blacklists +# to prevent autoloading of drivers prior to startup scripts + +my $HOTPLUG_HARDWARE_DIR = "/etc/sysconfig/hardware"; + +# if not existing file on OS, use this location and create empty file +# code in add_blacklist depends on pre-existance of file +my $HOTPLUG_BLACKLIST_FILE = "/etc/modprobe.d/opa-blacklist.conf"; +my $HOTPLUG_BLACKLIST_PREFIX = "blacklist"; +my $HOTPLUG_BLACKLIST_SPACE = " "; +my $HOTPLUG_BLACKLIST_SPACE_WILDCARD = "[ ]*"; + +# check if the module is blacklisted +sub is_blacklisted($) +{ + my $module = shift(); + + my $file = "${HOTPLUG_BLACKLIST_FILE}"; + my $found; + + if (! -f "$file") + { + return 0; + } + + return ! system("grep -q $module $file"); +} + +# add to list to prevent automatic hotplug of driver +sub add_blacklist($) +{ + my $module = shift(); + + my $file = "${HOTPLUG_BLACKLIST_FILE}"; + my $found; + + if (! -e "$file") + { + system("touch $file"); # Blacklist file missing, let's create it. + } elsif (! -f "$file") { + return; # Blacklist file exists but is not regular file, abort. + } + open (INPUT, "$file"); + open (OUTPUT, ">>$TMP_CONF"); + + select (OUTPUT); + while (($_=)) + { + if (/^${HOTPLUG_BLACKLIST_PREFIX}${HOTPLUG_BLACKLIST_SPACE_WILDCARD}$module[ ]*$/) + { + $found++; + } + print $_; + } + if (!defined($found)) + { + print "${HOTPLUG_BLACKLIST_PREFIX}${HOTPLUG_BLACKLIST_SPACE}$module\n"; + } + select(STDOUT); + + close (INPUT); + close (OUTPUT); + system "mv $TMP_CONF $file"; + + # also remove any hotplug config files which load the driver + open hwconfig, "ls /$HOTPLUG_HARDWARE_DIR/hwcfg* 2>/dev/null |" + || Abort "Unable to open pipe\n"; + while () { + chop; + if ( ! system("grep -q \"MODULE.*'$module'\" $_ 2>/dev/null") ) { + system "rm -f $_" + } + } + close hwconfig; +} + +sub remove_blacklist($) +{ + my($module) = shift(); + + my($file) = "${HOTPLUG_BLACKLIST_FILE}"; + if (! -f "$file") + { + return; + } + open (INPUT, "$file"); + open (OUTPUT, ">>$TMP_CONF"); + + select (OUTPUT); + while (($_=)) + { + if (/^${HOTPLUG_BLACKLIST_PREFIX}${HOTPLUG_BLACKLIST_SPACE_WILDCARD}$module[ ]*$/) + { + next; + } else { + print $_; + } + } + select(STDOUT); + + close (INPUT); + close (OUTPUT); + system "mv $TMP_CONF $file"; + if ( -z "$file" ) { + system("rm -f $file"); # blacklist file is empty, remove it. + } +} + diff --git a/CommonInstall/util_build.pl b/CommonInstall/util_build.pl new file mode 100755 index 0000000..2169db7 --- /dev/null +++ b/CommonInstall/util_build.pl @@ -0,0 +1,204 @@ +#!/usr/bin/perl +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] +use strict; +#use Term::ANSIColor; +#use Term::ANSIColor qw(:constants); +#use File::Basename; +#use Math::BigInt; + +# ============================================================================= +# The functions and constants below assist in doing builds such as via rpmbuild + +# The functions below assume a hash of build options. A sample is shown below +#my %ofed_kernel_ib_options = ( +# # build option # arch & kernels supported on +# "--with-core-mod" => "", # supported on all +# "--with-ehca-mod" => "PPC 2\.6\.1[6-9].* 2\.6\.20.* 2\.6\.9-55\. +# PPC64 2\.6\.1[6-9].* 2\.6\.20.* 2\.6\.9-55\.", +# "--with-iser-mod" => "ALL 2\.6\.16\..*-.*-.* 2\.6\..*\.el5 2\.6\.9-[3-5].*\.EL.*", +# # all kernels except 2.6.5* note .* wildcard need as 2nd kernelpat +# "--with-rds-mod" => "ALL !2\.6\.5.* .*", +# "--without-ipoibconf" => "NONE", # essentially a comment +# # DAPL not supported for PPC64 +# "--with-dapl" => "!PPC64", # any kernel for !PPC64 +#); + +# The arch & kernels specification is quite flexible. +# +# special formats: +# "" -> always use option (any arch, any kernels) +# "NONE" -> never use option, no remaining lines are processed +# +# typical format is one line per arch, separated by newline (inside string): +# "arch1 kernelpat1 kernelpat2 +# arch2 kernelpat3" +# leading spaces and tabs ignored before arch +# +# arch format: +# exact ARCH value (IA32, PPC, X86_64, etc) +# ALL - remainder of line applies to all architectures +# if no matches for kernel are found on this line, continues to later +# lines +# !arch - remainder of line applies to all architectures except arch +# if no matches for kernel are found on this line, continues to later +# lines. If no kernels listed, applies to any kernel. +# if for a given arch line, no kernels are specified, it matches any kernels +# +# kernelpat format: +# "" -> (eg. no kernelpat specified for arch), option applies to any kernel +# for given arch +# - all patterns are regex style +# beware: . is a wildcard unless \. used +# - !kernelpat means not on kernel, unlike !arch this indicates option is +# not appliable to this specific kernel, but does not affect other kernels + +# process osver and $ARCH against the list of allowed kernel/arch for +# a given build option to decide if option allowed for given kernel/arch +sub arch_kernel_is_allowed($$) +{ + my $osver = shift(); + my $archs = shift(); + + if ( "$archs" eq "" ) { + # option applicable to all archs all kernels + DebugPrint "yes\n"; + return 1; + } else { + # newlines separate details of each arch + my @arch_list = split /\n/, $archs; + foreach my $archdetails ( @arch_list ) { + # spaces separate arch and each kernelpattern + # ignore leading and trailing tabs/spaces + $archdetails =~ s/^[ ]*//; # remove leading + $archdetails =~ s/[ ]*$//; # remove trailing + # all other whitespace is just separators + my @archkernels = split /[[:space:]]+/,$archdetails; + # arch is 1st, rest are kernelpatterns + my $arch = $archkernels[0]; + shift @archkernels; + if ( "$arch" eq "NONE" ) { + DebugPrint "no\n"; + return 0; + } elsif ( "$ARCH" eq "$arch" || "ALL" eq "$arch" + || (substr($arch,0,1) eq "!" && "$ARCH" ne substr($arch,1)) ) { + if (scalar(@archkernels) == 0) { + # option applicable to all kernels for arch + DebugPrint "yes\n";; + return 1; + } else { + # list of kernel patterns specified + foreach my $kernelpattern ( @archkernels ) { +#print "check $kernelpattern\n"; + if (substr($kernelpattern,0,1) eq "!") { + $kernelpattern = substr($kernelpattern, 1); + if ( $osver =~ /^$kernelpattern$/ ) { + # option not available on this kernel + DebugPrint "no\n"; + return 0; + } + } elsif ( $osver =~ /^$kernelpattern$/ ) { + # option applicable to this kernel for arch + DebugPrint "yes\n"; + return 1; + } + } + } + } + } + } + DebugPrint "no\n"; + return 0; # not specified +} + +# given a build option and a kernel, decide if applicable to ARCH and kernel +# based on lookup in build_options hash +sub build_option_is_allowed($$@) +{ + my $osver = shift(); + my $build_option = shift(); + my(%build_options) = @_; # list of options and when valid + + return arch_kernel_is_allowed($osver, $build_options{$build_option}); +} + +# based on $osver and $ARCH decide what build options to use +sub get_build_options($@) +{ + my $osver = shift(); + my(@build_options) = @_; # list of options and when valid + + my $ret = ""; + my $i; + for($i=0; $i < scalar(@build_options); $i += 2) { + my $option = $build_options[$i]; + my $archs = $build_options[$i+1]; + if (arch_kernel_is_allowed($osver, $archs)) { + DebugPrint "Check $option - yes\n"; + $ret="$ret $option"; + } else { + DebugPrint "Check $option - no\n"; + } + } + return "$ret"; +} + +# execute build_cmd within srcdir +# return 0 on success, != 0 on failure +sub run_build($$$$) +{ + my $message= shift(); # message for building output + my $srcdir= shift(); + my $build_cmd= shift(); + my $resfileop= shift(); # "append" or "replace" + + my $rc; + my $shfileop; + + if ( "$resfileop" eq "append" ) { + $shfileop = ">>"; + } else { + $shfileop = ">"; + } + + NormalPrint "Building $message..."; + + LogPrint "\n cd $srcdir; $build_cmd $shfileop build.res 2>&1\n"; + $rc=system "cd $srcdir; $build_cmd $shfileop build.res 2>&1"; + if ( $rc != 0 ) { + NormalPrint "\nERROR - FAILED to build $message, see $srcdir/build.res\n"; + # TBD system("cat $srcdir/build.res >> $LogFile"); + } else { + NormalPrint " done\n"; + } + return $rc; +} + diff --git a/CommonInstall/util_components.pl b/CommonInstall/util_components.pl new file mode 100755 index 0000000..d0da409 --- /dev/null +++ b/CommonInstall/util_components.pl @@ -0,0 +1,2323 @@ +#!/usr/bin/perl +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] +use strict; +#use Term::ANSIColor; +#use Term::ANSIColor qw(:constants); +#use File::Basename; +#use Math::BigInt; + +# ========================================================================= +# Component installation state + +# constants for component state/action tracking during menus +my $State_Uninstall = 0; +my $State_Install = 1; +my $State_UpToDate = 2; +my $State_DoNotInstall = 3; +my $State_DoNotAutoInstall = 4; # valid only in DefaultInstall, must explicitly select + +sub disable_components(@); +my %comp_prereq_hash; +# indicate if given state reflects a component which will be on the system +# after processing the present menu selections +# states: +# $State_Uninstall - make sure not on system (Uninstall) +# $State_Install - install on system (Install/Upgrade/Re-Install) +# $State_UpToDate - leave as is on system (Installed/Up To Date) +# $State_DoNotInstall - leave as is not on system (Do Not Install) +sub will_be_on_system($) +{ + my $state = shift(); + + return ($state == $State_Install || $state == $State_UpToDate); +} + +# state returned: +# $State_Uninstall - make sure not on system (Uninstall) +# $State_Install - install on system (Install/Upgrade/Re-Install) +# $State_UpToDate - leave as is on system (Installed/Up To Date) +# $State_DoNotInstall - leave as is not on system (Do Not Install) +sub setstate($$$$) +{ + my $isinstalled = shift(); + my $available = shift(); + my $isupgrade = shift(); + my $defaultstate= shift(); # default if available and ! installed + + if (! $available && $isinstalled && !$isupgrade){ return $State_UpToDate; } + if (! $available && ! $isinstalled ) { return $State_DoNotInstall; } + if (! $available ) { return $State_Uninstall; } + if ($isinstalled && !$isupgrade) { return $State_UpToDate; } + if ($isinstalled) { return $State_Install; } + # available and not installed + if ($defaultstate == $State_DoNotAutoInstall) { return $State_DoNotInstall; } + return $defaultstate; # typcally State_Install +} + +# state returned: +# $State_Uninstall - make sure not on system (Uninstall) +# $State_Install - install on system (Install/Upgrade/Re-Install) +# $State_UpToDate - leave as is on system (Installed/Up To Date) +# $State_DoNotInstall - leave as is not on system (Do Not Install) +sub shiftstate($$$$) +{ + my $state = shift(); + my $isinstalled = shift(); + my $available = shift(); + my $isupgrade = shift(); + + if (! $available && $isinstalled && ! $isupgrade) { + return ($state==$State_UpToDate)?$State_Uninstall:$State_UpToDate; + } + if (! $available && ! $isinstalled ) { + return ($state==$State_DoNotInstall)?$State_Uninstall:$State_DoNotInstall; + } + if (! $available ) { + return $State_Uninstall; + } + if ($isinstalled && !$isupgrade) { + return ($state==$State_UpToDate)?$State_Install + :($state==$State_Install)?$State_Uninstall + :$State_UpToDate; + } + if ($isinstalled ) { + return ($state==$State_Install)?$State_Uninstall:$State_Install; + } + # available and not installed + return ($state==$State_Uninstall)?$State_Install + :($state==$State_Install)?$State_DoNotInstall:$State_Uninstall; +} + +sub InstallStateToStr($) +{ + my $state = shift(); + + if ($state == $State_Uninstall) { + return "Uninstall"; + } elsif ($state == $State_Install) { + return "Install"; + } elsif ($state == $State_UpToDate) { + return "UpToDate"; + } elsif ($state == $State_DoNotInstall) { + return "DoNotInstall"; + } elsif ($state == $State_DoNotAutoInstall) { + return "DoNotAutoInstall"; + } else { + return "INVALID"; + } +} + +# caller has output 24 characters, we have 55 left to play with +# (avoid using last column so don't autowrap terminal) +sub printInstallState($$$$) +{ + my $installed = shift(); + my $uninstall = shift(); + my $boldmessage = shift(); + my $message = shift(); + + if ($uninstall ) + { + print RED, "[ Uninstall ] ", RESET; + } elsif ($installed ) { + print GREEN, "[ Installed ] ", RESET; + } else { + print "[Not Installed] "; + } + if ("$message" ne "" && $boldmessage) { + print BOLD, RED "$message", RESET, "\n"; + } else { + print "$message\n"; + } + return; +} + +# states: +# $State_Uninstall - make sure not on system (Uninstall) +# $State_Install - install on system (Install/Upgrade/Re-Install) +# $State_UpToDate - leave as is on system (Installed/Up To Date) +# $State_DoNotInstall - leave as is not on system (Do Not Install) +sub printInstallAvailableState($$$$$$) +{ + my $installed = shift(); + my $available = shift(); + my $isupgrade = shift(); + my $state = shift(); + my $boldmessage = shift(); + my $message = shift(); + + if ( $state == $State_Uninstall ) + { + print RED, "[ Uninstall ]", RESET; + } elsif ( $state == $State_Install) { + if ($installed) + { + if ( $isupgrade ) + { + print GREEN, "[ Upgrade ]", RESET; + } else { + print "[ Re-Install ]"; + } + } else { + print "[ Install ]"; + } + } elsif ($state == $State_UpToDate) { + print "[ Up To Date ]"; + } elsif ($state == $State_DoNotInstall) { + print "[Don't Install]"; + } + + if ( $available ) + { + print "[Available] "; + } else { + print BOLD, RED "[Not Avail] ", RESET; + } + if ("$message" ne "" && $boldmessage) { + print BOLD, RED "$message", RESET, "\n"; + } else { + print "$message\n"; + } + + return; +} + +# ======================================================================= +# Component processing + +# function must be supplied if any components set ComponentInfo{}{HasFirmware} + +# these variables must be initialized by main program to control the +# data driven component menus and functions in this section +my $Default_Install=0; # -a option used to select default install of All +my $Default_Upgrade=0; # -U option used to select default upgrade of installed +my $Default_Uninstall=0; # -u option used to select default uninstall of All +my $Default_SameAutostart=0; # -n option used to default install, preserving autostart values +my $Default_CompInstall=0; # -i option used to select default install of Default_Components +my $Default_CompUninstall=0; # -e option used to select default uninstall of Default_Components +my %Default_Components = (); # components selected by -i or -e +my $Skip_FirmwareUpgrade=1; # -f option used to select skipping firmware upgrade +my $Default_Autostart=0; # -s option used to select default autostart of All +my $Default_DisableAutostart=0; # -D option used to select default disabling of autostart for Default_DisabledComponents +my %Default_DisabledComponents = (); # components selected by -D +my $Default_EnableAutostart=0; # -E option used to select default enabling of autostart for Default_EnabledComponents +my %Default_EnabledComponents = (); # components selected by -E +my $Default_ShowCompInfo=0; # -c option used to select default component information display of Default_Components + + # Names of supported install components + # must be listed in depdency order such that prereqs appear 1st +my @Components = (); + +# Sub components for autostart processing +my @SubComponents = (); + +# components/subcomponents for autostart processing +my @AutostartComponents = (); + + # an additional "special" component which is always installed when + # we install/upgrade anything and which is only uninstalled when everything + # else has been uninstalled. Typically this will be the opaconfig + # file and related files absolutely required by it (such as wrapper_version) +my $WrapperComponent = ""; + +# This provides more detailed information about each Component in @Components +# since hashes are not retained in the order specified, we still need +# @Components and @SubComponents to control install and menu order +# Only items listed in @Components and @SubComponents are considered for install +# As such, this may list some components which are N/A to the selected distro +# Fields are as follows: +# Name => full name of component/subcomponent for prompts +# DefaultInstall => default installation (State_DoNotInstall, +# State_DoNotAutoInstall or State_Install) +# used only when available and ! installed +# SrcDir => directory name within install media for component +# PreReq => other components which are prereqs of a given +# component/subcomponent +# Need space before and after each component name to +# facilitate compares so that compares do not mistake names +# such as mpidev for mpi +# CoReq => other components which are coreqs of a given component +# Note that CoReqs can also be listed as prereqs to provide +# install verification as each component is installed, +# however prereqs should only refer to items earlier in the list +# Need space before and after each component name to +# facilitate compares so that compares do not mistake names +# such as mpidev for mpi +# Hidden => component should not be shown in menus/prompts +# used for hidden PreReq. Hidden components can't HasStart +# nor HasFirmware +# Disabled => components/subcomponents which are disabled from installation +# IsOFA => is an in-distro OFA component we upgrade (excludes MPI) +# KernelRpms => kernel rpms for given component, in dependency order +# These are rpms which are kernel version specific and +# will have kernel uname -r in rpm package name. +# For a given distro a separate version of each of these rpms +# may exist per kernel. These are always architecture dependent +# Note KernelRpms are always installed before FirmwareRpms and +# UserRpms +# FirmwareRpms => firmware rpms for given component, in dependency order +# These are rpms which are not kernel specific. For a given +# distro a single version of each of these rpms will +# exist per distro/arch combination. In most cases they will +# be architecture independent (noarch). +# These are rpms which are installed in user space but +# ultimately end up in hardware such as HFI firmware, TMM firmware +# BIOS firmware, etc. +# UserRpms => user rpms for given component, in dependency order +# These are rpms which are not kernel specific. For a given +# distro a single version of each of these rpms will +# exist per distro/arch combination. Some of these may +# be architecture independent (noarch). +# DebugRpms => user rpms for component which should be installed as part +# of delta_debug component. +# HasStart => components/subcomponents which have autostart capability +# DefaultStart => should autostart default to Enable (1) or Disable (0) +# Not needed/ignored unless HasStart=1 +# StartPreReq => other components/subcomponents which must be autostarted +# before autostarting this component/subcomponent +# Not needed/ignored unless HasStart=1 +# Need space before and after each component name to +# facilitate compares so that compares do not mistake names +# such as mpidev for mpi +# StartComponents => components/subcomponents with start for this component +# if a component has a start script +# list the component as a subcomponent of itself +# StartupScript => name of startup script which controls startup of this +# component +# StartupParams => list of parameter names in $OPA_CONFIG which control +# startup of this component (set to yes/no values) +# HasFirmware => components which need HCA firmware update after installed +# +# Note both Components and SubComponents are included in the list below. +# Components require all fields be supplied +# SubComponents only require the following fields: +# Name, PreReq (should reference only components), HasStart, StartPreReq, +# DefaultStart, and optionally StartupScript, StartupParams +# Also SubComponents only require the IsAutostart2_X, autostart_desc_X, +# enable_autostart2_X, disable_autostart2_X and installed_X functions. +# Typically installed_X for a SubComponent will simply call installed_X for +# the component which contains it. +my %ComponentInfo = (); + # translate from startup script name to component/subcomponent name +my %StartupComponent = (); + # has component been installed since last configured autostart +my %ComponentWasInstalled = (); + +# constants for autostart functions $configure argument +my $Start_Unspecified=0; +my $Start_NoStart=1; +my $Start_Start=2; + +sub ShowComponents(;$) +{ + my $print_param = shift || \*STDOUT; #STDOUT as default parameter + foreach my $comp ( @Components ) + { + if (! $ComponentInfo{$comp}{'Hidden'}) { + print $print_param " $comp"; + } + } + print $print_param "\n"; +} + +sub ShowCompInfo(;$) +{ + my $print_param = shift || \*STDOUT; #STDOUT as default parameter + print $print_param "[\n"; + my $first_comp = 1; + my $first_item = 1; + foreach my $comp ( @Components ) + { + if ( $Default_Components{$comp} ) { + if ($first_comp == 1) { + $first_comp = 0; + print $print_param " {\n"; + } else { + print $print_param ",\n {\n"; + } + print $print_param " \"id\": \"$comp\",\n"; + my $description = $ComponentInfo{$comp}{'Name'}; + print $print_param " \"description\": \"$description\",\n"; + if ( $comp eq "delta_debug" ) { + print $print_param " \"error\": \"Not apply. We ship debug rpms in meta pkg _debuginfo.\"\n"; + print $print_param " },\n"; + next; + } + if (comp_is_available($comp)) { + print $print_param " \"available\": \"yes\",\n"; + } else { + print $print_param " \"available\": \"no\",\n"; + } + my $full_ver = comp_media_version($comp); + my ($version, $release) = GetVerRel($full_ver); + print $print_param " \"version\": \"$version\",\n"; + print $print_param " \"release\": \"$release\",\n"; + print $print_param " \"prereqs\": [\n"; + $first_item = 1; + my @reqs = split(/ /, $ComponentInfo{$comp}{'PreReq'}); + foreach my $req (@reqs) { + # ignore req that is not a component. This is for the case we do not + # have mpi_selector for SLES + if ( $req ne '' && grep( /^$req$/, @Components) ) { + my $reqver = comp_media_version($req); + my ($version, $release) = GetVerRel($reqver); + $reqver = "$version-$release"; + if ($first_item == 1) { + $first_item = 0; + print $print_param " {\"id\": \"$req\", \"version\": \"$reqver\"}"; + } else { + print $print_param ",\n {\"id\": \"$req\", \"version\": \"$reqver\"}"; + } + } + } + print $print_param "\n ],\n"; + @reqs = split(/ /, $ComponentInfo{$comp}{'CoReq'}); + print $print_param " \"coreqs\": [\n"; + $first_item = 1; + foreach my $req (@reqs) { + # ignore req that is not a component. This is for the case we do not + # have mpi_selector for SLES + if ( $req ne '' && grep( /^$req$/, @Components) ) { + my $reqver = comp_media_version($req); + my ($version, $release) = GetVerRel($reqver); + $reqver = "$version-$release"; + if ($first_item == 1) { + $first_item = 0; + print $print_param " {\"id\": \"$req\", \"version\": \"$reqver\"}"; + } else { + print $print_param ",\n {\"id\": \"$req\", \"version\": \"$reqver\"}"; + } + } + } + print $print_param "\n ],\n"; + if ( $comp eq "mpisrc" ) { + print $print_param " \"srcrpms\": {\n"; + print $print_param " \"dest\": \"/usr/src/opa/MPI/\",\n"; + my $srcdir=$ComponentInfo{'mpisrc'}{'SrcDir'}; + print $print_param " \"source\": \"$srcdir\",\n"; + print $print_param " \"resources\": [\n"; + $first_item = 1; + foreach my $srpm ( "mvapich2", "openmpi", "mpitests" ) { + my $srpmfile = file_glob("$srcdir/${srpm}-*.src.rpm"); + if ( "$srpmfile" ne "" ) { + my $file = my_basename($srpmfile); + if ($first_item == 1) { + $first_item = 0; + print $print_param " \"$file\""; + } else { + print $print_param ",\n \"$file\""; + } + } + } + print $print_param "\n ]\n"; + print $print_param " },\n"; + print $print_param " \"tools\": {\n"; + print $print_param " \"dest\": \"/usr/src/opa/MPI/\",\n"; + print $print_param " \"source\": \"$srcdir\",\n"; + print $print_param " \"resources\": [\n"; + print $print_param " \"do_build\",\n"; + print $print_param " \"do_mvapich2_build\",\n"; + print $print_param " \"do_openmpi_build\"\n"; + print $print_param " ]\n"; + print $print_param " },\n"; + print $print_param " \"misc\": [\n"; + print $print_param " {\"dest\": \"/usr/src/opa/MPI/.version\", \"source\": \"$srcdir\", \"resource\": \"version\"}\n"; + print $print_param " ]\n"; + } else { + print $print_param " \"userrpms\": [\n"; + ShowRpmList($print_param, " ", "user", @{$ComponentInfo{$comp}{'UserRpms'}}); + print $print_param "\n ],\n"; + print $print_param " \"kernelrpms\": [\n"; + ShowRpmList($print_param, " ", $CUR_OS_VER, @{$ComponentInfo{$comp}{'KernelRpms'}}); + print $print_param "\n ],\n"; + print $print_param " \"firmwarerpms\": [\n"; + ShowRpmList($print_param, " ", "firmware", @{$ComponentInfo{$comp}{'FirmwareRpms'}}); + print $print_param "\n ],\n"; + print $print_param " \"debugrpms\": [\n"; + ShowRpmList($print_param, " ", "any", @{$ComponentInfo{$comp}{'DebugRpms'}}); + print $print_param "\n ]\n"; + } + + print $print_param " }"; + } + } + print $print_param "\n]\n"; +} + +sub GetVerRel($) +{ + my $full_ver = shift(); + my ($version, $release) = split('-', $full_ver, 2); + if ("$release" eq "") { + # assume the version is in expected format, and it shall be. + my @segs = split('\.', $version); + my $last = scalar(@segs)-1; + $version = join('.', @segs[0..3]); + $release = join('.', @segs[4..$last]); + } + return ($version, $release); +} + +sub ShowRpmList($$$$@) +{ + my $print_param = shift(); + my $prefix = shift(); + my $mode = shift(); + my @rpms = @_; + my $rpmsdir = ""; + my $first_item = 1; + foreach my $rpm (@rpms) { + if ( $GPU_Install && -d file_glob("./repos/OPA_PKGS_CUDA") ) { + $rpmsdir=file_glob("./repos/OPA_PKGS_CUDA/RPMS"); + } else { + $rpmsdir=file_glob("./repos/OPA_PKGS/RPMS"); + } + my $rpm_file = rpm_resolve("$rpmsdir/$rpm", $mode); + if ( $rpm_file ne '' ) { + my $version = rpm_query_version_release($rpm_file); + my $epoch = rpm_query_attr($rpm_file, "EPOCH"); + if ("$epoch" ne "") { + $version = "$epoch:$version"; + } + if ($first_item == 1) { + $first_item = 0; + print $print_param "$prefix\{\"id\": \"$rpm\", \"version\": \"$version\"}"; + } else { + print $print_param ",\n$prefix\{\"id\": \"$rpm\", \"version\": \"$version\"}"; + } + } else { + DebugPrint "Not found $rpm"; + } + } +} + +# return 1 if $comp has a prereq of $prereq, 0 otherwise +sub comp_has_prereq_of($$) +{ + my($comp) = shift(); + my($prereq) = shift(); + + if ($ComponentInfo{$comp}{'PreReq'} =~ / $prereq /) { + return 1; + } else { + return 0; + } +} + +# return 1 if $comp has a coreq of $coreq, 0 otherwise +sub comp_has_coreq_of($$) +{ + my($comp) = shift(); + my($coreq) = shift(); + + if ($ComponentInfo{$comp}{'CoReq'} =~ / $coreq /) { + return 1; + } else { + return 0; + } +} + +# return 1 if $comp has a prereq or coreq of $req, 0 otherwise +sub comp_has_req_of($$) +{ + my($comp) = shift(); + my($req) = shift(); + + return (comp_has_prereq_of($comp, $req) || comp_has_coreq_of($comp, $req)); +} +# return 1 if $comp has a prereq of $prereq, 0 otherwise +sub comp_has_startprereq_of($$) +{ + my($comp) = shift(); + my($prereq) = shift(); + + if ($ComponentInfo{$comp}{'StartPreReq'} =~ / $prereq /) { + return 1; + } else { + return 0; + } +} + +# package is supplied since for a few packages (such as GPU Direct specific +# packages) we may pick a different directory based on package name +sub comp_get_rpms_dir($$) +{ + my $comp = shift(); + my $package = shift(); + return eval "get_rpms_dir_$comp('$package')"; +} + +# for comp_is_available we specially handle the case of function not found +# in which case eval returns "" +# all other component functions against install media will have called +# comp_is_available first, so they need not be protected by this test +sub comp_is_available($) +{ + my $comp = shift(); + my $rc; + + if ($ComponentInfo{$comp}{'Disabled'}) { + return 0; + } + $rc = eval "available_$comp()"; + if ( "$rc" eq "" ) { + return 0; # $comp not loaded + } else { + return $rc; + } +} + +# return version string for component on install media +# only valid if comp_is_available is TRUE +sub comp_media_version($) +{ + my $comp = shift(); + + my $result = eval "media_version_$comp()"; + chomp $result; + return $result; +} + +# for comp_is_installed we specially handle the case of function not found +# in which case eval returns "" +# all other component functions against system itself will have called +# comp_is_installed first, so they need not be protected by this test +sub comp_is_installed($) +{ + my $comp = shift(); + my $rc; + + $rc = eval "installed_$comp()"; + if ( "$rc" eq "" ) { + return 0; # $comp not loaded + } else { + return $rc; + } +} + +# return version string for component on system +# only valid if comp_is_installed is TRUE +sub comp_installed_version($) +{ + my $comp = shift(); + + my $result = eval "installed_version_$comp()"; + chomp $result; + return $result; +} + +# return TRUE if component is installed and up to date +# return FALSE if not installed, or not same version as media +# typically only called when component is available, returns +# FALSE if component not available +sub comp_is_uptodate($) +{ + my $comp = shift(); + + # safety check + if (! comp_is_available("$comp") ) { + return 0; + } + if (! comp_is_installed("$comp")) { + return 0; + } + # available and installed, compare versions + return (comp_installed_version($comp) eq comp_media_version($comp)); +} + +# check if all prereqs of $comp have been installed +# returns: 1 - all ok, 0 - some prereqs missing +sub check_prereqs($) +{ + my($comp) = shift(); + + foreach my $c ( @Components ) + { + if (comp_has_prereq_of($comp, $c) && ! comp_is_installed("$c") ) + { + NormalPrint "Unable to Install $ComponentInfo{$comp}{'Name'}, prereq $ComponentInfo{$c}{'Name'} not installed\n"; + HitKeyCont; + return 0; + } + } + return 1; +} + +# build processing for the given component +# returns 0 on success, 1 on failure +# only valid if comp_is_available is TRUE +sub comp_build($$$$$) +{ + my $comp = shift(); + my $osver = shift(); + my $debug = shift(); # enable extra debug of build itself + my $build_temp = shift(); # temp area for use by build + my $force = shift(); # force a rebuild + + LogPrint "Building $ComponentInfo{$comp}{'Name'} for $osver using '$build_temp'\n"; + return eval "build_$comp('$osver',$debug,'$build_temp',$force)"; +} + +# special hook for build processing for the given component within OFED build +# returns 1 if build should be done, 0 if not +# only valid for subset of components and if comp_is_available is TRUE +sub comp_ofed_need_build($$$$) +{ + my $comp = shift(); + my $osver = shift(); + my $force = shift(); # should we force build + my $prompt = shift(); # should we prompt user about build + + return eval "ofed_need_build_$comp('$osver',$force,$prompt)"; +} + +# special hook for build processing for the given component within OFED build +# returns 0 on success, >0 on failure +# only valid for subset of components and if comp_is_available is TRUE +sub comp_ofed_check_build_dependencies($$) +{ + my $comp = shift(); + my $osver = shift(); + + return eval "ofed_check_build_dependencies_$comp('$osver')"; +} + +# special hook for build processing for the given component within OFED build +# returns 0 on success, 1 on failure +# only valid for subset of components and if comp_is_available is TRUE +sub comp_ofed_build($$$$) +{ + my $comp = shift(); + my $osver = shift(); + my $debug = shift(); # enable extra debug of build itself + my $build_temp = shift(); # temp area for use by build + + LogPrint "Building $ComponentInfo{$comp}{'Name'} for $osver using '$build_temp'\n"; + return eval "ofed_build_$comp('$osver',$debug,'$build_temp')"; +} + +# before preinstall determine if present settings will require all +# installed components to be reinstalled +# returns "all" if need to reinstall all UpToDate components +# returns "this" if need to reinstall this component even if up to date +# returns "no" if no need to reinstall this component even if up to date +# only valid if comp_is_available is TRUE +sub comp_need_reinstall($$$) +{ + my $comp = shift(); + my $install_list = shift(); # total that will be installed when done + my $installing_list = shift(); # what items are being installed/reinstalled + + return eval "need_reinstall_$comp('$install_list', '$installing_list')"; +} + +# check presence of OS prereqs for the given component +# returns 0 on success, 1 on failure +# only valid if comp_is_available is TRUE +# for backward compatibility with old comp.pl files +# we specially handle the case of function not found +# in which case eval returns "" +sub comp_check_os_prereqs($) +{ + my $comp = shift(); + my $rc; + + DebugPrint "Checking OS Prereqs for $ComponentInfo{$comp}{'Name'}\n"; + $rc = eval "check_os_prereqs_$comp()"; + DebugPrint "Done: rc='$rc'\n"; + if ( "$rc" eq "" ) { + return 0; # $comp not loaded + } else { + return $rc; + } +} + +# preinstall processing for the given component +# returns 0 on success, 1 on failure +# only valid if comp_is_available is TRUE +sub comp_preinstall($$$) +{ + my $comp = shift(); + my $install_list = shift(); # total that will be installed when done + my $installing_list = shift(); # what items are being installed/reinstalled + + return eval "preinstall_$comp('$install_list', '$installing_list')"; +} + +# install the given component +# only valid if comp_is_available is TRUE +sub comp_install($$$) +{ + my $comp = shift(); + my $install_list = shift(); # total that will be installed when done + my $installing_list = shift(); # what items are being installed/reinstalled + + # sanity check, should not get here if false + if (! comp_is_available($comp) ) { + $exit_code = 1; + return; + } + print_separator; + # this will catch failures in install of prereqs + if (! check_prereqs($comp)) { + $exit_code = 1; + return; + } + + eval "install_$comp('$install_list', '$installing_list')"; +} + +# postinstall processing for the given component +# only valid if comp_is_available is TRUE +sub comp_postinstall($$$) +{ + my $comp = shift(); + my $install_list = shift(); # total that will be installed when done + my $installing_list = shift(); # what items are being installed/reinstalled + + eval "postinstall_$comp('$install_list', '$installing_list')"; +} + +# uninstall the given component +# typically only called if comp_is_available is TRUE +# or comp_is_installed is TRUE +# however could be called when not available and not installed in which +# case could be an empty function, in which case we can simply ignore +# eval's "" return +sub comp_uninstall($$$) +{ + my $comp = shift(); + my $install_list = shift(); # total that will be left installed when done + my $uninstalling_list = shift(); # what items are being uninstalled + + print_separator; + if ($ComponentInfo{$comp}{'HasStart'}) { + disable_components(@{ $ComponentInfo{$comp}{'StartComponents'} }); + } + eval "uninstall_$comp('$install_list', '$uninstalling_list')"; +} + +# determine if the given component is configured for Autostart at boot +sub comp_IsAutostart2($) +{ + my $comp = shift(); + + return eval "IsAutostart2_$comp()"; +} +# get autostart desc for the given component +sub comp_autostart_desc($) +{ + my $comp = shift(); + + my $desc = eval "autostart_desc_$comp()"; + if ( "$desc" eq "" ) { + $desc = $ComponentInfo{$comp}{'Name'}; + } + return $desc; +} +# enable autostart for the given component +sub comp_enable_autostart2($$) +{ + my $comp = shift(); + my $quiet = shift(); + + if ( ! comp_IsAutostart2($comp) == 1 ) + { + if (! $quiet) { + my $desc = comp_autostart_desc($comp); + NormalPrint "Enabling autostart for $desc\n"; + } + } + eval "enable_autostart2_$comp()"; +} +# disable autostart for the given component +sub comp_disable_autostart2($$) +{ + my $comp = shift(); + my $quiet = shift(); + + if ( comp_IsAutostart2($comp) == 1 ) + { + if (! $quiet) { + my $desc = comp_autostart_desc($comp); + NormalPrint "Disabling autostart for $desc\n"; + } + } + + eval "disable_autostart2_$comp()"; +} + +sub DumpComponents($) +{ + my $allow_install = shift(); + + if (! DebugPrintEnabled() ) { + return; + } + DebugPrint("\nComponents:\n"); + foreach my $comp ( @Components, "mpiRest" ) { + DebugPrint(" $comp: '$ComponentInfo{$comp}{'Name'}' SrcDir: $ComponentInfo{$comp}{'SrcDir'}\n"); + DebugPrint(" DefaultInstall: ".InstallStateToStr($ComponentInfo{$comp}{'DefaultInstall'})."\n"); + DebugPrint(" PreReq: $ComponentInfo{$comp}{'PreReq'} CoReq: $ComponentInfo{$comp}{'CoReq'}\n"); + DebugPrint(" Hidden: $ComponentInfo{$comp}{'Hidden'} Disabled: $ComponentInfo{$comp}{'Disabled'} HasFirmware: $ComponentInfo{$comp}{'HasFirmware'} IsOFA: $ComponentInfo{$comp}{'IsOFA'}\n"); + DebugPrint(" KernelRpms: @{ $ComponentInfo{$comp}{'KernelRpms'}}\n"); + DebugPrint(" FirmwareRpms @{ $ComponentInfo{$comp}{'FirmwareRpms'}}\n"); + DebugPrint(" UserRpms: @{ $ComponentInfo{$comp}{'UserRpms'}}\n"); + DebugPrint(" DebugRpms: @{ $ComponentInfo{$comp}{'DebugRpms'}}\n"); + DebugPrint(" HasStart: $ComponentInfo{$comp}{'HasStart'} DefaultStart: $ComponentInfo{$comp}{'DefaultStart'}\n"); + DebugPrint(" StartPreReq: $ComponentInfo{$comp}{'StartPreReq'} StartComponents: @{ $ComponentInfo{$comp}{'StartComponents'}}\n"); + DebugPrint(" StartupScript: $ComponentInfo{$comp}{'StartupScript'} StartupParams: @{ $ComponentInfo{$comp}{'StartupParams'}}\n"); + if ($allow_install) { + my $avail = comp_is_available($comp); + DebugPrint(" IsAvailable: $avail"); + if ($avail) { + DebugPrint(" MediaVersion: ".comp_media_version($comp)); + } + DebugPrint("\n"); + } + my $installed = comp_is_installed($comp); + DebugPrint(" IsInstalled: $installed"); + if ($installed) { + DebugPrint(" InstalledVersion: ".comp_installed_version($comp)); + } + DebugPrint("\n"); + } + + DebugPrint("\nSubComponents:\n"); + foreach my $comp ( @SubComponents ) { + DebugPrint(" $comp: '$ComponentInfo{$comp}{'Name'}'\n"); + DebugPrint(" PreReq: $ComponentInfo{$comp}{'PreReq'} CoReq: $ComponentInfo{$comp}{'CoReq'}\n"); + DebugPrint(" HasStart: $ComponentInfo{$comp}{'HasStart'}\n"); + DebugPrint(" StartPreReq: $ComponentInfo{$comp}{'StartPreReq'}\n"); + DebugPrint(" StartupScript: $ComponentInfo{$comp}{'StartupScript'} StartupParams: @{ $ComponentInfo{$comp}{'StartupParams'}}\n"); + } +} + +# output standard banner for component install +# This function can be called within a components install_X function +sub print_comp_install_banner($) +{ + my $comp = shift(); + + my $version=comp_media_version($comp); + chomp $version; + printf("Installing $ComponentInfo{$comp}{'Name'} $version $DBG_FREE...\n"); + LogPrint "Installing $ComponentInfo{$comp}{'Name'} $version $DBG_FREE for $CUR_DISTRO_VENDOR $CUR_VENDOR_VER $CUR_OS_VER\n"; +} + +# install the given list of rpms for a component +sub install_comp_rpm_list($$$@) +{ + my $comp = shift(); + my $mode = shift(); # "user" or kernel rev or "firmware" + my $options = shift(); # additional rpm command options + my @package_list = @_; # package names + + my @rpmpath_list = (); + + foreach my $package ( @package_list ) + { + my $rpmsdir=comp_get_rpms_dir($comp, $package); + @rpmpath_list = ( @rpmpath_list, "$rpmsdir/$package" ); + } + rpm_install_path_list_with_options($mode, "$options", @rpmpath_list); +} + +# helper which does most of the work for installing rpms for a component +# This function can be called within a components install_X function +# installs KernelRpms, FirmwareRpms and UserRpms +# caller must handle any non-RPM files +sub install_comp_rpms($$$) +{ + my $comp = shift(); + my $options = shift(); # additional rpm command options + my $install_list = shift(); # total that will be installed when done + + if (! $user_space_only ) { + install_comp_rpm_list($comp, $CUR_OS_VER, "$options", + @{ $ComponentInfo{$comp}{'KernelRpms'}} ); + install_comp_rpm_list($comp, "firmware", "$options", + @{ $ComponentInfo{$comp}{'FirmwareRpms'}} ); + } + install_comp_rpm_list($comp, "user", "$options", + @{ $ComponentInfo{$comp}{'UserRpms'}} ); + # DebugRpms are installed as part of 'delta_debug' component +} + +# output standard banner for component uninstall +# This function can be called within a components install_X function +sub print_comp_uninstall_banner($) +{ + my $comp = shift(); + + NormalPrint("Uninstalling $ComponentInfo{$comp}{'Name'}...\n"); +} + +# helper which does most of the work for uinstalling rpms for a component +# This function can be called within a components uninstall_X function +# uninstalls KernelRpms, FirmwareRpms, UserRpms and DebugRpms +# caller must handle any non-RPM files +sub uninstall_comp_rpms($$$$$) +{ + my $comp = shift(); + # the rpm command options + my $option = shift(); + my $install_list = shift(); + my $uninstalling_list = shift(); + my $verbosity = shift(); + + # try to uninstall meta pkg if it exists + my $metapkg = "opameta_$comp"; + rpm_uninstall_matches($metapkg, $metapkg, '', ""); + + rpm_uninstall_list2("any", "$option", $verbosity, + @{ $ComponentInfo{$comp}{'DebugRpms'}}); + rpm_uninstall_list2("any", "$option", $verbosity, + @{ $ComponentInfo{$comp}{'UserRpms'}}); + if (! $user_space_only ) { + rpm_uninstall_list2("any", "$option", $verbosity, + @{ $ComponentInfo{$comp}{'FirmwareRpms'}}); + rpm_uninstall_list2("any", "$option", $verbosity, + @{ $ComponentInfo{$comp}{'KernelRpms'}}); + } +} + +# build @AutostartComponents listing all components and subcomponents which +# have autostart capability. They are listed in prefered startup order +sub build_autostart_components_list() +{ + my $comp; + # only need to do once + if (scalar(@AutostartComponents) != 0 ) { + return; + } + foreach $comp ( @Components ) + { + if ( $ComponentInfo{$comp}{'HasStart'} ) + { + # StartComponents will list Components and SubComponents which + # have start capability + @AutostartComponents = ( @AutostartComponents, @{ $ComponentInfo{$comp}{'StartComponents'} }) + } + } +} + +# disable autostart for a list of components and +# all components dependent on given component +sub disable_components(@) +{ + my @disabled = ( @_ ); + my %need_disable = (); + my %dont_need_disable = (); + my $comp; + + build_autostart_components_list; + foreach $comp ( @disabled ) { + $need_disable{$comp} = 1; + DebugPrint("disable $comp explicitly\n"); + } + my $done = 0; + while ( ! $done) { + $done=1; + foreach $comp ( @disabled ) { + # comp will be disabled, any which depend on it as a + # startprereqs will also be disabled + foreach my $c ( @AutostartComponents ) { + if (comp_has_startprereq_of($c, $comp) + && ! $need_disable{$c} && ! $dont_need_disable{$c} ) { + if (comp_is_installed("$c") ) { + @disabled = ( @disabled, $c ); + $need_disable{$c}=1; + DebugPrint("also disable $c\n"); + $done=0; + } else { + $dont_need_disable{$c}=1; + DebugPrint("no need to disable $c\n"); + } + } + } + } + } + foreach $comp ( reverse(@AutostartComponents) ) { + foreach my $c ( @disabled ) { + if ( "$comp" eq "$c" ) { + DebugPrint("invoke disable $c\n"); + comp_disable_autostart2($c,0); + } + } + } +} + +# enable autostart for a list of components and +# all components they depend on +sub enable_components(@) +{ + my @enabled = ( @_ ); + my %need_enable = (); + my $comp; + + build_autostart_components_list; + foreach $comp ( @enabled ) { + $need_enable{$comp} = 1; + DebugPrint("enable $comp explicitly\n"); + } + my $done = 0; + while ( ! $done) { + $done=1; + foreach $comp ( @enabled ) { + # comp will be enabled, make sure all its + # startprereqs will also be enabled + foreach my $c ( @AutostartComponents ) { + if (comp_has_startprereq_of($comp, $c) && ! $need_enable{$c} ) { + DebugPrint("also enable $c\n"); + @enabled = ( $c, @enabled ); + $need_enable{$c}=1; + $done=0; + } + } + } + } + foreach $comp ( @AutostartComponents ) { + foreach my $c ( @enabled ) { + if ( "$comp" eq "$c" ) { + DebugPrint("invoke enable $c\n"); + comp_enable_autostart2($c,0); + } + } + } +} + +# run build for all components +sub build_all_components($$$$) +{ + my $osver = shift(); # Kernel OS Version to build for + my $debug = shift(); # enable extra debug of build itself + my $build_temp = shift(); # temp area for use by build + my $force = shift(); # force a full rebuild + + my $comp; + my $ret = 0; + + foreach $comp ( @Components ) + { + my $rc = comp_build($comp,$osver,$debug,$build_temp,$force); + if (0 != $rc) { + NormalPrint "Unable to Build $ComponentInfo{$comp}{'Name'}\n"; + } + $ret |= $rc; + } + return $ret; +} + +sub count_hidden_comps() +{ + my $i; + my $ret=0; + + for($i=0; $i < scalar(@Components); $i++) + { + my $comp = $Components[$i]; + if ($ComponentInfo{$comp}{'Hidden'}) { + $ret++; + } + } + return $ret; +} + +# convert a screen selection into a Components subscript, accounting for Hidden +sub get_comp_subscript($$$) +{ + my $firstline=shift(); + my $maxlines=shift(); + my $selection=shift(); + my $index=0; + my $i; + + for ($i=0; $i < scalar(@Components); $i++) + { + my $comp = $Components[$i]; + if ($index >= $firstline && $index < $firstline+$maxlines) { + if (! $ComponentInfo{$comp}{'Hidden'}) { + if ($index - $firstline == $selection) { + return $i; + } + $index++; + } + } else { + if (! $ComponentInfo{$comp}{'Hidden'}) { + $index++; + } + } + } + return $i # invalid entry return 1 past number of Components +} + +sub show_install_menu($) +{ + my $showversion = shift(); # should per comp versions be shown + + my $inp; + my %available = (); + my %installed = (); + my %installed_version = (); + my %media_version = (); + my %isupgrade = (); + my %installState = (); + my %statusMessage = (); + my %boldMessage = (); + my $comp; + my $i; + my $newstate = $State_Uninstall; # most recent state change for a comp + my $firstline = 0; + my $maxlines=14; + my $num_hidden_comps = count_hidden_comps(); + + print "Determining what is installed on system...\n"; + DumpComponents(1); + foreach $comp ( @Components ) + { + $available{$comp} = comp_is_available("$comp"); + $installed{$comp} = comp_is_installed("$comp"); + if ( $available{$comp} ) { + $media_version{$comp} = comp_media_version($comp); + } else { + $media_version{$comp} = ""; + } + if ( $installed{$comp} ) { + $installed_version{$comp} = comp_installed_version($comp); + $isupgrade{$comp}= ($installed_version{$comp} ne $media_version{$comp}); + } else { + $installed_version{$comp} = ""; + $isupgrade{$comp}=1; + } + $installState{$comp}= setstate($installed{$comp}, $available{$comp}, + $isupgrade{$comp}, $ComponentInfo{$comp}{'DefaultInstall'}); + } + # to avoid a subtle effect, mark as not available any items whose + # coreqs are not available. Such packagings should not + # occur, but better to be safe + foreach $comp ( @Components ) + { + if (! $available{$comp}) { + foreach my $c ( @Components ) + { + if (comp_has_coreq_of($c, $comp) && $available{$c}) { + $available{$c}=0; + } + } + } + } + + do {{ + if ( $Default_Install) { + # setstate set UnInstall or DoNotInstall for those not available + # force install for all available even if UpToDate + # or ComponentInfo{comp}{'DefaultInstall'} is DoNotInstall + foreach $comp ( @Components ) + { + if ( $available{$comp} + && ($installState{$comp} != $State_DoNotInstall + || $ComponentInfo{$comp}{'DefaultInstall'} != $State_DoNotAutoInstall)) { + $installState{$comp} = $State_Install; + } + } + $newstate = $State_Install; + $inp='P'; + } elsif ( $Default_Upgrade) { + foreach $comp ( @Components ) + { + if ( $installed{$comp} ) + { + if ( $available{$comp} ) + { + $installState{$comp} = $State_Install; + } elsif ( ! $isupgrade{$comp} ) { + $installState{$comp} = $State_UpToDate; + } else { + $installState{$comp} = $State_Uninstall; # we must uninstall + } + } else { + $installState{$comp} = $State_DoNotInstall; + } + } + $newstate = $State_Install; + $inp='P'; + } elsif ( $Default_CompInstall) { + foreach $comp ( @Components ) + { + if ( $Default_Components{$comp} ) + { + if ( $available{$comp} ) + { + $installState{$comp} = $State_Install; + } else { + NormalPrint "Unable to install $ComponentInfo{$comp}{'Name'}, Not Available\n"; + # setstate provided a reasonable default action + } + } else { + # setstate defaulted to install all available and not installed + # for version updates re-install to be safe + if ( $installState{$comp} == $State_Install + && ( ! $installed{$comp} || ! $isupgrade{$comp} ) ) + { + # Do Not Install + $installState{$comp} = $State_DoNotInstall; + } + } + } + $newstate = $State_Install; + $inp='P'; + } else { + system "clear"; + printf ("$BRAND OPA Install ($VERSION $DBG_FREE) Menu\n\n"); + my $screens = int((scalar(@Components) - $num_hidden_comps + $maxlines-1)/$maxlines); + + if($GPU_Install == 1) { + printf ("Install GPU Direct components, ensure nvidia drivers + SDK are present \n\n"); + } + if ($screens > 1 ) { + printf ("Please Select Install Action (screen %d of $screens):\n", + $firstline/$maxlines+1); + } else { + printf ("Please Select Install Action:\n"); + } + my $index=0; + for ($i=0; $i < scalar(@Components); $i++) + { + $comp = $Components[$i]; + if ($index >= $firstline && $index < $firstline+$maxlines) { + if ($showversion && "$statusMessage{$comp}" eq "") { + if ($available{$comp}) { + $statusMessage{$comp} = $media_version{$comp}; + $boldMessage{$comp} = 0; + } elsif($installed{$comp}) { + $statusMessage{$comp} = $installed_version{$comp}; + $boldMessage{$comp} = 0; + } + } + if (! $ComponentInfo{$comp}{'Hidden'}) { + printf ("%x) %-20s", $index-$firstline, $ComponentInfo{$comp}{'Name'}); + printInstallAvailableState($installed{$comp}, + $available{$comp}, + $isupgrade{$comp}, + $installState{$comp}, + $boldMessage{$comp}, $statusMessage{$comp}); + $index++; + } + } elsif (! $ComponentInfo{$comp}{'Hidden'}) { + $index++; + } + } + + printf ("\n"); + if ($screens > 1 ) { + printf ("N) Next Screen\n"); + } + printf ( "P) Perform the selected actions I) Install All\n"); + printf ( "R) Re-Install All U) Uninstall All\n"); + printf ( "X) Return to Previous Menu (or ESC)\n"); + + $inp = getch(); + + if ($inp =~ /[qQ]/ || $inp =~ /[xX]/ || ord($inp) == $KEY_ESC ) + { + return; + } + + # do not clear status messages when jump between screens + if ($inp !~ /[nN]/ ) { + %statusMessage = (); + %boldMessage = (); + } + } + + if ($inp =~ /[nN]/ ) + { + if (scalar(@Components) > $maxlines) { + $firstline += $maxlines; + if ($firstline >= scalar(@Components)) { + $firstline=0; + } + } + } elsif ($inp =~ /[rR]/ ) + { + foreach $comp ( @Components ) + { + if ( $installed{$comp} && $available{$comp}) { + $installState{$comp} = $State_Install; + } + } + } elsif ($inp =~ /[iI]/ ) + { + foreach $comp ( @Components ) + { + if ( $available{$comp} ) { + $installState{$comp} = $State_Install; + } + } + $newstate = $State_Install; + } elsif ($inp =~ /[uU]/ ) + { + foreach $comp ( @Components ) + { + $installState{$comp} = $State_Uninstall; + } + $newstate = $State_Uninstall; + } elsif ($inp =~ /[0123456789abcdefABCDEF]/) { + my $value = hex($inp); + my $index = get_comp_subscript($firstline, $maxlines, $value); + if ( $value < $maxlines && $index < scalar(@Components)) { + my $selected = $Components[$index]; + $installState{$selected} = shiftstate($installState{$selected},$installed{$selected},$available{$selected},$isupgrade{$selected}); + $newstate = $installState{$selected}; + } + } + + if (! will_be_on_system($newstate)) { + # something is being uninstalled or not installed + # loop through a few times to catch all coreqs, prereqs + # and coreqs of prereqs + my $done = 0; # we are done if we loop through with no changes + while (! $done) { + $done=1; + foreach $comp ( @Components ) + { + if (! will_be_on_system($installState{$comp})) { + # comp will not be on system, make sure all its + # pre/coreqs will also not be on system + foreach my $c ( @Components ) + { + if (comp_has_req_of($c, $comp) + && will_be_on_system($installState{$c})) { + $statusMessage{$c}="requires $ComponentInfo{$comp}{'Name'}"; + $boldMessage{$c}=1; + $installState{$c}=$installed{$c}?$State_Uninstall:$State_DoNotInstall; + $done=0; + } + } + } + if ($ComponentInfo{$comp}{'Hidden'}) { + # if no longer needed, also remove it + my $needed = 0; # is $comp needed + foreach my $c ( @Components ) + { + if (comp_has_req_of($c, $comp) + && will_be_on_system($installState{$c})) { + $needed=1; + } + } + if (! $needed && will_be_on_system($installState{$comp})) { + $installState{$comp}=$installed{$comp}?$State_Uninstall:$State_DoNotInstall; + $done=0; + } + } + } + } + } elsif (will_be_on_system($newstate)) { + # something is being installed or left on system + # loop through a few times to catch all coreqs, prereqs + # and coreqs of prereqs + my $done = 0; # we are done if we loop through with no changes + my $forcedone = 0; # used to break infinite loop in subtle issue below + while (! $forcedone && ! $done) { + $done=1; + foreach $comp ( @Components ) + { + if (will_be_on_system($installState{$comp})) { + # comp will be on system, make sure all its + # pre/coreqs will also be on system + foreach my $c ( @Components ) + { + if (comp_has_req_of($comp, $c) + && ! will_be_on_system($installState{$c})) { + if (! $available{$c} ) { + # pre/coreq $c not available, can't install comp + $statusMessage{$comp}="requires $ComponentInfo{$c}{'Name'}"; + $boldMessage{$comp}=1; + $installState{$comp}=$installed{$comp}?$State_Uninstall:$State_DoNotInstall; + # this should not occur for coreqs + # however there are subtle effects here. + # If we install an item which has a prereq + # whose prereq is not available we could get + # stuck with an invalid combination since we + # will have marked the 1st prereq installed, + # found the 2nd prereq problem + # unmarked the 1st prereq but still have + # left the original item to be installed + # bail to avoid infinite loop + $forcedone=1; + last; + } else { + # also install $c + $statusMessage{$c}="needed by $ComponentInfo{$comp}{'Name'}"; + $boldMessage{$c}=1; + $installState{$c}=$State_Install; + } + $done=0; + } + } + } + if ($ComponentInfo{$comp}{'Hidden'} && $available{$comp} + && will_be_on_system($installState{$comp})) { + # if all prereqs being reinstalled also reinstall it + my $reinstall = 1; # no already installed dependents + foreach my $c ( @Components ) + { + if (comp_has_req_of($c, $comp) + && will_be_on_system($installState{$c}) + && $installState{$c} != $State_Install) { + $reinstall=0; + } + } + if ($reinstall) { + $installState{$comp}=$State_Install; + # no need to force another loop, didn't change + # will_be_on_system($comp) + } + } + } + } + } + + if ($inp =~ /[pP]/) { + # perform the install + my $updateFirmware=0; + + # build a list of what will be installed after installation completes + # use a space separate string so easier to pass and can be "grep'ed" + my $install_list = ""; + my $installing_list = ""; + my $uninstalling_list = ""; + my $have_some_uptodate = 0; + foreach $comp ( @Components ) + { + if ($installState{$comp} == $State_UpToDate) { + $have_some_uptodate = 1; + } + if ($installState{$comp} == $State_Install + || $installState{$comp} == $State_UpToDate) { + $install_list .= " $comp "; + } + if ($installState{$comp} == $State_Install) { + $installing_list .= " $comp "; + } + if ($installState{$comp} == $State_Uninstall) { + $uninstalling_list .= " $comp "; + } + } + + # remove any alias pkgs if it exists. Meta pkgs will be handled in comp uninstall. + rpm_uninstall_matches("opanode_", "opanode_", "", ""); + + # first uninstall what will be removed, do this in reverse order + # so dependency issues are avoided + foreach $comp ( reverse(@Components) ) { + if ($installState{$comp} == $State_Uninstall) { + comp_uninstall($comp, $install_list, $uninstalling_list); + $installed{$comp} = 0; + } + } + if ( "$WrapperComponent" ne "" && "$installing_list" eq "" && "$install_list" eq "" ) { + comp_uninstall($WrapperComponent, $install_list, $uninstalling_list); + } + + if ($have_some_uptodate ) { + # determine if some up to date components need to be reinstalled + # for example due to a change in install prefix, install options ... + # to determine this run need_reinstall for all components which + # will be installed or are up to date. Net result is we may change + # some or all components in State_UpToDate to State_Install + + my $need_reinstall_all = 0; + my $need_reinstall_some = 0; + foreach $comp ( @Components ) + { + if (($installState{$comp} == $State_Install + || $installState{$comp} == $State_UpToDate) + && $available{$comp} ) { + my $reins = comp_need_reinstall($comp,$install_list,$installing_list); + if ("$reins" eq "all") { + VerbosePrint("$comp needs reinstall all\n"); + $need_reinstall_all = 1; + last; + } elsif ("$reins" eq "this") { + if ($installState{$comp} == $State_UpToDate + && $available{$comp} ) { + VerbosePrint("$comp needs reinstall\n"); + $installState{$comp} = $State_Install; + $need_reinstall_some = 1; + } + } + } + } + if ($need_reinstall_all || $need_reinstall_some) { + if ($need_reinstall_all) { + NormalPrint "INSTALL options require Reinstall of all UpToDate Components\n"; + } else { + NormalPrint "Reinstall of some UpToDate Components is Required\n"; + } + $installing_list = ""; # recompute + foreach $comp ( @Components ) + { + if ($need_reinstall_all + && $installState{$comp} == $State_UpToDate + && $available{$comp} ) { + $installState{$comp} = $State_Install; + } + if ($installState{$comp} == $State_Install) { + $installing_list .= " $comp "; + } + } + } + } + # check OS pre-reqs for all components which will be installed + my $have_all_os_prereqs=1; + foreach $comp ( @Components ) + { + if ($installState{$comp} == $State_Install) { + if (0 != comp_check_os_prereqs($comp)) { + $have_all_os_prereqs=0; + NormalPrint "Lacking OS Prereqs for $ComponentInfo{$comp}{'Name'}\n"; + } + } + } + if (! $have_all_os_prereqs) { + HitKeyCont; + last; + } + + # run pre-install for all components which will be installed + # Reverse the order to avoid dependency issues + foreach $comp ( reverse(@Components) ) + { + if ($installState{$comp} == $State_Install) { + if (0 != comp_preinstall($comp,$install_list,$installing_list)) { + NormalPrint "Unable to Prepare $ComponentInfo{$comp}{'Name'} for Install\n"; + HitKeyCont; + last; + } + } + } + + # Now install components + if ( "$WrapperComponent" ne "" && "$installing_list" ne "" ) { + comp_install($WrapperComponent, $install_list, $installing_list); + } + foreach $comp ( @Components ) + { + if ($installState{$comp} == $State_Install) { + comp_install($comp, $install_list, $installing_list); + if ( $ComponentInfo{$comp}{'HasFirmware'} ) { + $updateFirmware=1; + } + } + } + + # run post-install for all components which were installed + foreach $comp ( @Components ) + { + if ($installState{$comp} == $State_Install) { + comp_postinstall($comp, $install_list, $installing_list); + } + } + + %installed = (); + if ( $Default_Prompt ) { + foreach $comp ( @Components ) + { + $installed{$comp} = 0; + } + # limit autostart to newly installed components with a + # default start. Also include their start prereqs. + # Note start prereqs are all inclusive, so we don't need to + # find prereqs of prereqs + foreach $comp ( @Components ) + { + if ($installState{$comp} == $State_Install + && $ComponentInfo{$comp}{'HasStart'} + && ($Default_SameAutostart + || $ComponentInfo{$comp}{'DefaultStart'}) ) { + $installed{$comp} = 1; + foreach my $c ( @Components ) { + if (comp_has_startprereq_of($comp, $c)) { + $installed{$c} = 1; + } + } + } + } + } else { + foreach $comp ( @Components ) + { + if ($installState{$comp} == $State_Install + || $installState{$comp} == $State_UpToDate) { + $installed{$comp} = 1; + } else { + $installed{$comp} = 0; + } + } + } + show_autostart_menu(0); + + # show_autostart_menu unconditionally requested user hit return, + # update_hca_firmware will also as needed, so only request return below + # if one of these functions does something. + my $need_ret = 0; + $need_ret |= check_depmod; + $need_ret |= check_ldconfig; + $need_ret |= check_need_reboot; + if ($need_ret) { + HitKeyCont; + } + return; + } + }} until ($Default_Prompt); + # we had an error above + $exit_code = 1; +} + +sub show_installed($) +{ + my $showversion = shift(); # should per comp versions be shown + + my %installed = (); + my %statusMessage = (); + my $comp; + my $i; + + system "clear"; + printf ("$BRAND OPA Installed Software ($VERSION)\n\n"); + my $index=0; + for ($i=0; $i < scalar(@Components); $i++) + { + if ($index > 0 && ($index % 20 == 0) ) { + HitKeyCont; + } + $comp = $Components[$i]; + $installed{$comp} = comp_is_installed("$comp"); + if ( $showversion && $installed{$comp} ) { + $statusMessage{$comp} = comp_installed_version($comp); + } + if (! $ComponentInfo{$comp}{'Hidden'}) { + printf (" %-20s ", $ComponentInfo{$comp}{'Name'}); + printInstallState($installed{$comp}, 0, 0, "$statusMessage{$comp}"); + $index++; + } + } + HitKeyCont; +} + +sub show_uninstall_menu($) +{ + my $showversion = shift(); # should per comp versions be shown + + my %installed = (); + my %installed_version = (); + my %installState = (); + my %statusMessage = (); + my %boldMessage = (); + my $inp; + my $comp; + my $i; + my $newstate; # most recent state change for a comp + my $firstline = 0; + my $maxlines=14; + my $num_hidden_comps = count_hidden_comps(); + + print "Determining what is installed on system...\n"; + DumpComponents(0); + foreach $comp ( @Components ) + { + $installed{$comp} = comp_is_installed("$comp"); + if ($installed{$comp}) { + $installed_version{$comp} = comp_installed_version("$comp"); + } + $installState{$comp}= setstate($installed{$comp},0,0,$State_DoNotInstall); + } + do { + if ( $Default_Uninstall) { + foreach $comp ( @Components ) + { + $installState{$comp} = $State_Uninstall; + } + $newstate = $State_Uninstall; + $inp="P"; + } elsif ( $Default_CompUninstall) { + foreach $comp ( @Components ) + { + if ( $Default_Components{$comp} ) + { + $installState{$comp} = $State_Uninstall; + } + } + $newstate = $State_Uninstall; + $inp="P"; + } else { + system "clear"; + printf ("$BRAND OPA Uninstall Menu ($VERSION)\n\n"); + my $screens = int((scalar(@Components)-$num_hidden_comps + $maxlines-1)/$maxlines); + if ($screens > 1 ) { + printf ("Please Select Uninstall Action (screen %d of $screens):\n", + $firstline/$maxlines+1); + } else { + printf ("Please Select Uninstall Action:\n"); + } + my $index=0; + for($i=0; $i < scalar(@Components); $i++) + { + $comp = $Components[$i]; + if ($index >= $firstline && $index < $firstline+$maxlines) { + if ($showversion && "$statusMessage{$comp}" eq "" + && $installed{$comp}) { + $statusMessage{$comp} = $installed_version{$comp}; + $boldMessage{$comp} = 0; + } + if (! $ComponentInfo{$comp}{'Hidden'}) { + printf ("%x) %-20s ", $index-$firstline, $ComponentInfo{$comp}{'Name'}); + printInstallState($installed{$comp}, ($installState{$comp} == $State_Uninstall), + $boldMessage{$comp}, $statusMessage{$comp}); + $index++; + } + } elsif (! $ComponentInfo{$comp}{'Hidden'}) { + $index++; + } + } + + printf ("\n"); + if ($screens > 1 ) { + printf ("N) Next Screen\n"); + } + printf ( "P) Perform the selected actions\n"); + printf ( "U) Uninstall All\n"); + printf ( "X) Return to Previous Menu (or ESC)\n"); + + + $inp = getch(); + + if ($inp =~ /[qQ]/ || $inp =~ /[xX]/ || ord($inp) == $KEY_ESC) + { + return; + } + + # do not clear status messages when jump between screens + if ($inp !~ /[nN]/ ) + { + %statusMessage = (); + %boldMessage = (); + } + } + + if ($inp =~ /[nN]/ ) + { + if (scalar(@Components) > $maxlines) { + $firstline += $maxlines; + if ($firstline >= scalar(@Components)) { + $firstline=0; + } + } + } elsif ($inp =~ /[uU]/ ) + { + foreach $comp ( @Components ) + { + $installState{$comp} = $State_Uninstall; + } + $newstate = $State_Uninstall; + } + elsif ($inp =~ /[0123456789abcdefABCDEF]/) + { + my $value = hex($inp); + my $index = get_comp_subscript($firstline, $maxlines, $value); + if ( $value < $maxlines && $index < scalar(@Components)) { + my $selected = $Components[$index]; + $installState{$selected} = shiftstate($installState{$selected},$installed{$selected},0,0); + $newstate = $installState{$selected}; + } + } + + if (! will_be_on_system($newstate)) { + my $done = 0; # we are done if we loop through with no changes + # something is being uninstalled or not installed + # loop through a few times to catch all coreqs, prereqs + # and coreqs of prereqs + while (! $done) { + $done=1; + foreach $comp ( @Components ) + { + if (! will_be_on_system($installState{$comp})) { + # comp will not be on system, make sure all its + # pre/coreqs will also not be on system + foreach my $c ( @Components ) + { + if (comp_has_req_of($c, $comp) + && will_be_on_system($installState{$c})) { + $statusMessage{$c}="requires $ComponentInfo{$comp}{'Name'}"; + $boldMessage{$c}=1; + $installState{$c}=$installed{$c}?$State_Uninstall:$State_DoNotInstall; + $done=0; + } + } + } + if ($ComponentInfo{$comp}{'Hidden'}) { + # if no longer needed, also remove it + my $needed = 0; # is $comp needed + foreach my $c ( @Components ) + { + if (comp_has_req_of($c, $comp) + && will_be_on_system($installState{$c})) { + $needed=1; + } + } + if (! $needed && will_be_on_system($installState{$comp})) { + $installState{$comp}=$installed{$comp}?$State_Uninstall:$State_DoNotInstall; + $done=0; + } + } + } + } + } elsif (will_be_on_system($newstate)) { + # something is being left on system + # loop through a few times to catch all coreqs, prereqs + # and coreqs of prereqs + my $done = 0; # we are done if we loop through with no changes + my $forcedone = 0; # used to force infinite loop in subtle issue below + while (! $forcedone && ! $done) { + $done=1; + foreach $comp ( @Components ) + { + if (will_be_on_system($installState{$comp})) { + # comp will be on system, make sure all its + # pre/coreqs will also be on system + foreach my $c ( @Components ) + { + if (comp_has_req_of($comp, $c) + && ! will_be_on_system($installState{$c})) { + if (! $installed{$c} ) { + # pre/coreq $c not installed, can't keep comp + # this is not expected to occur, but is + # a safety net for corrupted systems + $statusMessage{$comp}="requires $ComponentInfo{$c}{'Name'}"; + $boldMessage{$comp}=1; + $installState{$comp}=$installed{$comp}?$State_Uninstall:$State_DoNotInstall; + # bail to avoid infinite loop, especially + # for prereq chains and missing coreqs + # see install_menu discussion for a similar + # related issue + $forcedone=1; + last; + } else { + # also install $c + $statusMessage{$c}="needed by $ComponentInfo{$comp}{'Name'}"; + $boldMessage{$c}=1; + $installState{$c}=$State_Install; + } + $done=0; + } + } + } + } + } + } + + if ($inp =~ /[pP]/) + { + # build a list of what will be installed after installation completes + # use a space separate string so easier to pass and can be "grep'ed" + my $install_list = ""; + my $uninstalling_list = ""; + foreach $comp ( @Components ) + { + if ($installState{$comp} == $State_Install + || $installState{$comp} == $State_UpToDate) { + $install_list .= " $comp "; + } + if ($installState{$comp} == $State_Uninstall) { + $uninstalling_list .= " $comp "; + } + } + + # remove any alias pkgs if it exists. Meta pkgs will be handled in comp uninstall. + rpm_uninstall_matches("opanode_", "opanode_", "", ""); + + # perform the uninstall, work backwards through list + foreach $comp ( reverse(@Components) ) + { + if ($installState{$comp} == $State_Uninstall) + { + comp_uninstall($comp, $install_list, $uninstalling_list); + $installed{$comp} = 0; + } + } + if ( "$WrapperComponent" ne "" && "$install_list" eq "" ) { + comp_uninstall($WrapperComponent, $install_list, $uninstalling_list); + } + # since we did an uninstall should request a return + my $need_ret = 1; + $need_ret |= check_depmod; + $need_ret |= check_ldconfig; + $need_ret |= check_need_reboot; + if ($need_ret) { + HitKeyCont; + } + return; + } + }while( !$Default_Prompt ) +} + +sub reconfig_autostart() +{ + my %installed = (); + my $comp; + + build_autostart_components_list; + foreach $comp ( @Components ) { + $installed{$comp} = comp_is_installed("$comp"); + DebugPrint("installed($comp)=$installed{$comp}\n"); + # fill in subcomponents to simplify tests for Default_*Components below + # if show_autostart_menu is called, it will ignore these extra entries + foreach my $c ( @{ $ComponentInfo{$comp}{'StartComponents'} }) { + $installed{$c} = $installed{$comp}; + } + } + if (! $Default_Autostart) { + # interactive menu, use previous value as default + show_autostart_menu(1); + } else { + if ( $Default_DisableAutostart) { + # build list of components/subcomponents to disable + my @disabled = (); + foreach $comp ( @AutostartComponents ) { + if ( $installed{$comp} ) { + if ($Default_DisabledComponents{$comp}) { + @disabled = ( @disabled, $comp ); + } + } + } + disable_components(@disabled); + } + if ( $Default_EnableAutostart) { + # build list of components/subcomponents to enable + my @enabled = (); + foreach $comp ( @AutostartComponents ) { + if ( $installed{$comp} ) { + if ($Default_EnabledComponents{$comp}) { + @enabled = ( @enabled, $comp ); + } + } else { + } + } + enable_components(@enabled); + } + if (! $Default_DisableAutostart && ! $Default_EnableAutostart) { + # use component specific default as value + show_autostart_menu(2); + } + } +} + +# states: +# $Start_Start - Enable Autostart +# $Start_NoStart - Disable Autostart +sub printStartState($$$$) +{ + my $enabled = shift(); + my $boldmessage = shift(); + my $message = shift(); + my $state_change = shift(); + + if ( $enabled ) + { + print GREEN, "[Enable ]", RESET; + } else { + print RED, "[Disable]", RESET; + } + if ( $state_change ) + { + print " *"; + } else { + print " "; + } + if ("$message" ne "" && $boldmessage) { + print BOLD, RED "$message", RESET, "\n"; + } else { + print "$message\n"; + } + + return; +} + +# convert a screen selection into a Autostart subscript +sub get_subscript($$$@) +{ + my $firstline=shift(); + my $maxlines=shift(); + my $selection=shift(); + my @list = ( @_ ); + my $index=0; + my $i; + + for ($i=0; $i < scalar(@list); $i++) + { + my $comp = $list[$i]; + if ($index >= $firstline && $index < $firstline+$maxlines) { + if ($index - $firstline == $selection) { + return $i; + } + $index++; + } else { + $index++; + } + } + return $i # invalid entry return 1 past number of Components +} +sub show_autostart_menu($) +{ + my $sel_mode = shift(); # possible values are: 1: keep previous, 0: use default, 2: enable + + my $inp; + my @PromptAutostart = (); + my %enabled = (); + my %statusMessage = (); + my %boldMessage = (); + my $comp; + my $i; + my $newenabled = 0; # most recent state change for a comp + my $firstline = 0; + my $maxlines=13; + + # figure out which to prompt for + # while selections may include SubComponents, we only look + # at components and include all their subcomponents in the prompts + foreach $comp ( @Components ) + { + if ( comp_is_installed("$comp") && $ComponentInfo{$comp}{'HasStart'} ) + { + # StartComponents will list Components and SubComponents which + # have start capability + @PromptAutostart = ( @PromptAutostart, @{ $ComponentInfo{$comp}{'StartComponents'} }) + } + } + if ( $Default_SameAutostart ) { + foreach $comp ( @PromptAutostart ) + { + my $state; + # we recreate startup files to ensure they are in the + # startup order of the new release + if ( comp_IsAutostart2($comp) == 1 ) + { + comp_enable_autostart2($comp,1); + $state = "enabled"; + } else { + comp_disable_autostart2($comp,1); + $state = "disabled"; + } + my $desc = comp_autostart_desc($comp); + NormalPrint "Leaving autostart for $desc at its previous value: $state\n"; + } + return; + } + + foreach $comp ( @PromptAutostart ) + { + DebugPrint("prompt for $comp\n"); + if ($sel_mode == 1) { + # keep previous + $enabled{$comp} = comp_IsAutostart2($comp); + } elsif ($sel_mode == 2) { + # enable + $enabled{$comp} = 1; + } else { + # use default + $enabled{$comp} = $ComponentInfo{$comp}{'DefaultStart'}; + } + } + while() { + if ( $Default_Prompt) { + $inp='P'; + } else { + system "clear"; + printf ("$BRAND OPA Autostart ($VERSION $DBG_FREE) Menu\n\n"); + my $screens = int((scalar(@PromptAutostart) + $maxlines-1)/$maxlines); + if ($screens > 1 ) { + printf ("Please Select Autostart Option (screen %d of $screens):\n", + $firstline/$maxlines+1); + } else { + printf ("Please Select Autostart Option:\n"); + } + my $index=0; + for ($i=0; $i < scalar(@PromptAutostart); $i++) + { + $comp = $PromptAutostart[$i]; + my $state_change = 0; + if( comp_IsAutostart2($comp) != $enabled{$comp} ) + { + $state_change = 1; + } + if ($index >= $firstline && $index < $firstline+$maxlines) { + printf ("%x) %-32s", $index-$firstline, comp_autostart_desc($comp)); + printStartState($enabled{$comp}, + $boldMessage{$comp}, $statusMessage{$comp}, $state_change); + $index++; + } else { + $index++; + } + } + printf("\n*: new desired state\n"); + printf ("\n"); + if ($screens > 1 ) { + printf ("N) Next Screen\n"); + } + printf ( "P) Perform the autostart changes\n"); + printf ( "S) Autostart All R) Autostart None\n"); + printf ( "X) Return to Previous Menu (or ESC)\n"); + + $inp = getch(); + + if ($inp =~ /[qQ]/ || $inp =~ /[xX]/ || ord($inp) == $KEY_ESC ) + { + return; + } + + # do not clear status messages when jump between screens + if ($inp !~ /[nN]/ ) { + %statusMessage = (); + %boldMessage = (); + } + + } + + if ($inp =~ /[nN]/ ) + { + if (scalar(@PromptAutostart) > $maxlines) { + $firstline += $maxlines; + if ($firstline >= scalar(@PromptAutostart)) { + $firstline=0; + } + } + } elsif ($inp =~ /[sS]/ ) + { + foreach $comp ( @PromptAutostart ) + { + $enabled{$comp} = 1; + } + $newenabled = 1; + } elsif ($inp =~ /[rR]/ ) + { + foreach $comp ( @PromptAutostart ) + { + $enabled{$comp} = 0; + } + $newenabled = 0; + } elsif ($inp =~ /[0123456789abcdefABCDEF]/) { + my $value = hex($inp); + my $index = get_subscript($firstline, $maxlines, $value, @PromptAutostart); + if ( $value < $maxlines && $index < scalar(@PromptAutostart)) { + my $selected = $PromptAutostart[$index]; + $enabled{$selected} = ! $enabled{$selected}; + $newenabled = $enabled{$selected}; + } + } + + if (! $newenabled) { + # something is being disabled + # loop through a few times to catch all prereqs + # and prereqs of prereqs + my $done = 0; # we are done if we loop through with no changes + while (! $done) { + $done=1; + foreach $comp ( @PromptAutostart ) + { + if (! $enabled{$comp}) { + # comp will be disabled, make sure all its + # startprereqs will also be disabled + foreach my $c ( @PromptAutostart ) + { + if (comp_has_startprereq_of($c, $comp) && $enabled{$c}) { + $statusMessage{$c}="requires $ComponentInfo{$comp}{'Name'}"; + $boldMessage{$c}=1; + $enabled{$c}=0; + $done=0; + } + } + } + } + } + } else { + # something is being disabled + # loop through a few times to catch all prereqs + my $done = 0; # we are done if we loop through with no changes + while (! $done) { + $done=1; + foreach $comp ( @PromptAutostart ) + { + if ($enabled{$comp}) { + # comp will be enabled, make sure all its + # startprereqs will also be enabled + foreach my $c ( @PromptAutostart ) + { + if (comp_has_startprereq_of($comp, $c) && ! $enabled{$c}) { + # also enable $c + $statusMessage{$c}="needed by $ComponentInfo{$comp}{'Name'}"; + $boldMessage{$c}=1; + $enabled{$c}=1; + $done=0; + } + } + } + } + } + } + + if ($inp =~ /[pP]/) { + # perform the changes + + # first disable, do this in reverse order + # so dependency issues are avoided + foreach $comp ( reverse(@PromptAutostart) ) { + if (! $enabled{$comp}) { + comp_disable_autostart2($comp,0); + } + } + # now enable + foreach $comp ( @PromptAutostart ) { + if ($enabled{$comp}) { + comp_enable_autostart2($comp,0); + } + } + HitKeyCont; + return; + } + if ( $Default_Prompt ) { + return; + } + } + $exit_code = 1; # unexpected +} + diff --git a/CommonInstall/util_configfile.pl b/CommonInstall/util_configfile.pl new file mode 100755 index 0000000..8ed527a --- /dev/null +++ b/CommonInstall/util_configfile.pl @@ -0,0 +1,580 @@ +#!/usr/bin/perl +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# + +use strict; +#use Term::ANSIColor; +#use Term::ANSIColor qw(:constants); +#use File::Basename; +#use Math::BigInt; + +# ======================================================================== +# Basic configuration files + +my $CONFIG_DIR = "/etc"; # general driver config +my $OFED_CONFIG_DIR = "/etc/infiniband"; # general driver config +my $OFED_CONFIG = "$OFED_CONFIG_DIR/openib.conf"; +my $OPA_CONFIG_DIR = "/etc/rdma"; +my $OPA_CONFIG = "$OPA_CONFIG_DIR/rdma.conf"; +my %KeepConfig = (); # keep track of past questions to config questions +my $Default_RpmConfigKeepOld=0; # -O option used to select current rpm config file +my $Default_RpmConfigUseNew=0; # -N option used to select new rpm config file + +my $TMP_CONF="/tmp/conf.$$"; # scratch file + +sub check_config_dirs() +{ + check_dir("$BASE_DIR"); + check_dir("$OPA_CONFIG_DIR"); +} + +sub check_keep_config($$$) +{ + my($configFile) = shift(); + my($configDesc) = shift(); + my($default) = shift(); + + my($prompt) = ""; + my $keep; + + if ("$configDesc" eq "") + { + $prompt="$configFile"; + } else { + $prompt="$configDesc ($configFile)"; + } + + if (! exists $KeepConfig{"$configFile"}) + { + $keep=system "diff $configFile $configFile-sample > /dev/null 2>&1"; + if ($keep != 0) + { + NormalPrint "You have a modified $configFile configuration file\n"; + $KeepConfig{"$configFile"} = GetYesNo("Do you want to keep $prompt?", "$default"); + } else { + $KeepConfig{"$configFile"} = $keep; + } + } + return $KeepConfig{"$configFile"}; +} + +# This is to update the old path when upgrading from 10.3 to newer version +sub replace_old_path_in($) +{ + my $filename = shift(); + open(FILE, "<$filename") || die "\nUnable to locate $filename\n"; + my @lines = ; + close(FILE); + + # Replace /etc/sysconfig/opa/ with /etc/opa/ + my @newlines; + foreach(@lines) { + $_ =~ s/\/etc\/sysconfig\/opa\//\/etc\/opa\//g; + push(@newlines,$_); + } + + open(FILE, ">$filename") || die "\nUnable to locate $filename\n"; + print FILE @newlines; + close(FILE); +} + +# This subroutine is used to check if we should keep a modified rpm config file +# Optional second parameter used to check if a file exist in a previous (now deprecated) +# file location. +sub check_rpm_config_file($;$) +{ + my($config) = shift(); + my($old_config_dir) = shift(); + my($file_name) = basename($config); + + if ( $old_config_dir ne "" && !$Default_RpmConfigUseNew) { + if ( -e "$old_config_dir/$file_name") { + if ($Default_RpmConfigKeepOld || GetYesNo ("$file_name found in old file path $old_config_dir, move to new location?", "y")) { + # This is to update the old path when upgrading from 10.3 to newer version + replace_old_path_in ("$old_config_dir/$file_name"); + system "mv -f $old_config_dir/$file_name $config"; + return; + } + } elsif ( -e "$old_config_dir/$file_name.rpmsave") { + if ($Default_RpmConfigKeepOld || GetYesNo ("$file_name.rpmsave found in old file path $old_config_dir, move to new location?", "y")) { + # This is to update the old path when upgrading from 10.3 to newer version + replace_old_path_in ("$old_config_dir/$file_name.rpmsave"); + system "mv -f $old_config_dir/$file_name.rpmsave $config"; + return; + } + } + } + + if ( -e "$config.rpmsave") { + if ($Default_RpmConfigKeepOld) { + system "mv -f $config.rpmsave $config"; + } elsif ($Default_RpmConfigUseNew){ + system "rm -f $config.rpmsave"; + } elsif (GetYesNo ("Do you want to keep $config?", "y")) { + system "mv -f $config.rpmsave $config"; + } else { + system "rm -f $config.rpmsave"; + } + } elsif ( -e "$config.rpmnew") { + if ($Default_RpmConfigKeepOld) { + system "rm -f $config.rpmnew"; + } elsif ($Default_RpmConfigUseNew){ + system "mv -f $config.rpmnew $config"; + } elsif (GetYesNo ("Do you want to keep $config?", "y")) { + system "rm -f $config.rpmnew"; + } else { + system "mv -f $config.rpmnew $config"; + } + } +} + +sub clear_keep_config($) +{ + my($configFile) = shift(); + + delete $KeepConfig{"$configFile"}; +} + +sub remove_conf_file($$) +{ + my($WhichDriver) = shift(); + my($ConfFile) = shift(); + + if (-e "$ConfFile") + { + if (check_keep_config("$ConfFile", "$WhichDriver configuration file", "y")) + { + NormalPrint "Keeping $WhichDriver configuration file ($ConfFile) ...\n"; + } else { + system "rm -rf $ConfFile"; + } + } + system "rm -rf ${ConfFile}-sample"; +} + +# remove a config file where a previous release used a different name for +# the file +sub remove_renamed_conf_file($$;@) +{ + my($WhichDriver) = shift(); + my($ConfFile) = shift(); + my(@OldConfFile_list) = @_; # old config file names + + foreach my $OldConfFile ( @OldConfFile_list) { + remove_conf_file("$WhichDriver", "$OldConfFile"); + } + remove_conf_file("$WhichDriver", "$ConfFile"); +} + +sub install_conf_file($$$;@) +{ + my($WhichDriver) = shift(); + my($ConfFileDest) = shift(); + my($ConfFileSrc) = shift(); + my(@OldConfFileDest_list) = @_; # optional + my $diff_src_dest; + my $diff_src_sample; + my $diff_dest_sample; + my $keep; + my $need_copy = 1; + + # install an appropriate file into $ConfFileDest + foreach my $OldConfFileDest ( @OldConfFileDest_list, $ConfFileDest ) { + DebugPrint("Checking $OldConfFileDest\n"); + next if ( ! -e "$OldConfFileDest" ); + + $diff_src_dest = system "diff $ConfFileSrc $OldConfFileDest > /dev/null 2>&1"; + + if ( ! -e "${OldConfFileDest}-sample" ) + { + DebugPrint("No ${OldConfFileDest}-sample\n"); + $diff_src_sample=1; + $diff_dest_sample=1; + } else { + $diff_src_sample = system "diff $ConfFileSrc ${OldConfFileDest}-sample > /dev/null 2>&1"; + $diff_dest_sample = system "diff $OldConfFileDest ${OldConfFileDest}-sample > /dev/null 2>&1"; + } + DebugPrint("Comparisons: src vs old=$diff_src_dest, src vs oldsample=$diff_src_sample, old vs oldsample=$diff_dest_sample\n"); + + if ($diff_src_dest != 0) + { + if ($diff_dest_sample == 0) + { + NormalPrint "You have an unmodified $WhichDriver configuration file from an earlier install\n"; + $keep =check_keep_config("$OldConfFileDest", "", "n"); + } elsif ($diff_src_sample != 0) + { + NormalPrint "You have a $WhichDriver configuration file from an earlier install\n"; + $keep=check_keep_config("$OldConfFileDest", "", "y"); + } else { + NormalPrint "You have a modified $WhichDriver configuration file\n"; + $keep=check_keep_config("$OldConfFileDest", "", "y"); + } + if ( $keep ) { + if ("$OldConfFileDest" ne "$ConfFileDest") { + # we are working on an old config file + copy_data_file("$OldConfFileDest", "$ConfFileDest"); + NormalPrint "Using $OldConfFileDest as $ConfFileDest...\n"; + } else { + # we are working against the new supplied config file + NormalPrint "Leaving $OldConfFileDest unchanged...\n"; + } + $need_copy=0; + last; + } # otherwise onto next file, if needed will copy new file below + } + } + if ( $need_copy) { + # no old files kept (or not found), use new release version + NormalPrint "Updating $ConfFileDest ...\n"; + copy_data_file("$ConfFileSrc", "$ConfFileDest"); + } + foreach my $OldConfFileDest ( @OldConfFileDest_list ) { + system "rm -rf ${OldConfFileDest}-sample"; + } + copy_file("$ConfFileSrc", "${ConfFileDest}-sample", "$OWNER", "$GROUP", "ugo=r,u=r"); +} + +# after doing an rpm install, config files will be either installed (if new) +# or retained with the new version in .rpmnew +# this allows user to select which to keep as their present config file +sub copy_rpm_conf_file($$;@) +{ + my($WhichDriver) = shift(); + my($ConfFileDest) = shift(); + my(@OldConfFileDest_list) = @_; # optional + my($ConfFileSrc) = "$ConfFileDest.rpmnew"; + + if ( ! -e "$ConfFileDest.rpmnew" ) + { + # must be first install, Dest is the newest file + # save a copy in case we overwrite it with an OldConfFileDest below + system("cp $ConfFileDest $TMP_CONF"); + $ConfFileSrc="$TMP_CONF" + } + install_conf_file($WhichDriver, $ConfFileDest, $ConfFileSrc, @OldConfFileDest_list); + system("rm -f $ConfFileSrc"); +} + +# After an RPM install, config files from previous install (denoted via .rpmsave) +# may need to be preserved. Ask the user if they want to keep. +sub preserve_prev_rpm_conf($) +{ + my($ConfFileDest) = shift(); + my($ConfFileSave) = "$ConfFileDest.rpmsave"; + + if ( -e "$ConfFileSave" ) + { + #install_conf_file($WhichDriver, $ConfFileDest, $ConfFileSave); + #system("rm -f $ConfFileSave"); + my $diff_src_dest = system "diff $ConfFileDest $ConfFileSave > /dev/null 2>&1"; + if ($diff_src_dest != 0) { + printf("You have a modified $ConfFileDest configuration file \n"); + my $keep = GetYesNo("Do you want to keep $ConfFileDest?", "y"); + if ($keep) { + printf("Using the modified $ConfFileDest file \n"); + copy_data_file("$ConfFileSave", "$ConfFileDest"); + } + else { + printf("Using the new $ConfFileDest file \n"); + } + } + + system "rm -f $ConfFileSave" + } +} + +# install a config file where a previous release used a different name for +# the file +sub install_renamed_conf_file($$$;@) +{ + my($WhichDriver) = shift(); + my($ConfFileDest) = shift(); + my($ConfFileSrc) = shift(); + my(@OldConfFileDest_list) = @_; # in order that we consider them + + my $diff_src_dest; + my $diff_src_sample; + my $diff_dest_sample; + + if (! -e "$ConfFileDest") { + # first upgrade install, we consider old files as relevant + # we want to do the install_conf_file algorithm + # but use OldConfFileDest for all but file destination of copy + install_conf_file("$WhichDriver","$ConfFileDest","$ConfFileSrc",@OldConfFileDest_list); + } else { + # don't touch old (if any), just perform normal upgrade/install + foreach my $OldConfFileDest ( @OldConfFileDest_list ) { + system "rm -rf ${OldConfFileDest}-sample"; + } + install_conf_file("$WhichDriver","$ConfFileDest","$ConfFileSrc"); + } +} + +# =========================================================================== +# functions to insert/remove config file additions bounded by markers + +# +# Deletes contents from start marker to end marker +# arg0 : Start marker +# arg1 : End Marker +# arg2 : Leave Marks in file after removing contents +# arg3 : Filename to operate on +# + +sub del_marks($$$$) +{ + my($StartMark) = shift(); + my($EndMark) = shift(); + my($LeaveMarks) = shift(); + my($FileName) = shift(); + + my($found_mark)=0; + + open (INPUT, "$FileName"); + open (OUTPUT, ">>$TMP_CONF"); + + select (OUTPUT); + while (($found_mark == 0) && ($_=)) { + if (/$StartMark/) { + $found_mark=1; + if ($LeaveMarks) { + print $_; + } + } else { + print $_; + } + } + + while (($found_mark == 1) && ($_=)) { + if (/$EndMark/) { + $found_mark = 0; + if ($LeaveMarks) { + print $_; + } + } + } + + while ($_=) { + print $_; + } + + select(STDOUT); + + close (INPUT); + close (OUTPUT); + + system "mv $TMP_CONF $FileName"; +} + +# gets contents including marks and compares to specified file +# returns 0 on match, 1 if different +sub compare_marks($$$$) +{ + my($StartMark) = shift(); + my($EndMark) = shift(); + my($FileName) = shift(); + my($CompareTo) = shift(); + + my $is_different; + my $found_inf; + + system "awk '/$StartMark/, /$EndMark/ {print}' $FileName > /tmp/tmp.conf"; + $found_inf = `diff /tmp/tmp.conf $CompareTo`; + system "rm -f /tmp/tmp.conf"; + + if ($found_inf eq "") + { + $is_different = 0; + } else + { + $is_different = 1; + } + return $is_different +} + +# =========================================================================== +# functions to edit simple config files + +# This function supports reading parameters from config file which are +# actually shell scripts. openib.conf, opafastfabric.conf and the Linux network +# config files are examples of such. +# If the file or parameter does not exist, returns "" +sub read_simple_config_param($$) +{ + my $config_file=shift(); + my $parameter=shift(); + + if ( ! -e "$config_file" ) { + return ""; + } + my $value=`. $config_file >/dev/null 2>/dev/null; echo \$$parameter`; + chomp($value); + return "$value"; +} + +sub edit_simple_config_file($$) +{ + my($FileName) = shift(); + my($changes) = shift(); # set of sed commands + + my $rc; + + $rc = system("sed $changes < $FileName > $TMP_CONF"); + if ($rc != 0) { + system ("rm -rf $TMP_CONF >/dev/null 2>&1"); + return $rc; + } + + $rc = system "mv $TMP_CONF $FileName"; + return $rc; +} + +# ========================================================================== +# configuration file + +# OFED & OPA configuration files are structured as a list of lines of the form: +# parameter=value +# There may be additional comment and whitespace lines +sub change_conf_param($$$) +{ + my $parameter=shift(); + my $newvalue=shift(); + my $conf=shift(); + + VerbosePrint("edit $conf: '$parameter=$newvalue'\n"); + if (0 != system("grep '^$parameter=' $conf >/dev/null 2>/dev/null")) { + # add parameter to file + system ("echo '$parameter=$newvalue' >> $conf 2>/dev/null");; + } else { + return edit_simple_config_file("$conf", + "-e 's/^$parameter=.*/$parameter=$newvalue/g'"); + } +} + +sub change_openib_conf_param($$) +{ + my $p1=shift(); + my $p2=shift(); + change_conf_param($p1,$p2,"/$OFED_CONFIG"); +} + +sub change_opa_conf_param($$) +{ + my $p1=shift(); + my $p2=shift(); + change_conf_param($p1,$p2,"/$OPA_CONFIG"); +} + +sub read_openib_conf_param($$) +{ + my $parameter=shift(); + my $config_file=shift(); # if "", defaults to standard file + + if ( "$config_file" eq "" ) { + $config_file="/$OFED_CONFIG"; + } + return read_simple_config_param($config_file, $parameter); +} + +sub read_opa_conf_param($$) +{ + my $parameter=shift(); + my $config_file=shift(); # if "", defaults to standard file + + if ( "$config_file" eq "" ) { + $config_file="/$OPA_CONFIG"; + } + return read_simple_config_param($config_file, $parameter); +} +# Function to setup environment variable. used to setup environment variables for RPM post install +# configuration +sub setup_env($$) +{ + my ($env_type) = shift(); # environment variable + my ($env_value) = shift(); # value to be set + $ENV{$env_type}="$env_value"; +} + +sub prompt_conf_param($$$$;$) +{ + my $parameter=shift(); + my $parameterDesc=shift(); + my $default=shift(); + my $conf=shift(); + my $OPA_INSTALL_ENV=shift(); + + my $prompt; + my $value; + my $env_value; + + if ("$parameterDesc" eq "") { + $prompt="$parameter"; + } else { + $prompt="$parameterDesc ($parameter)"; + } + if (GetYesNoWithMemory($parameter, 0, "Enable $prompt?", $default) == 1) { + $value="yes"; + $env_value=1; + } else { + $value="no"; + $env_value=0; + } + # some configuation parameter are configured directly, some are by RPM. for RPM we will setup env variable. + if ( $OPA_INSTALL_ENV eq "OPA_SRPHA_ENABLE" || $OPA_INSTALL_ENV eq "OPA_RENICE_IB_MAD" || $OPA_INSTALL_ENV eq "OPA_SET_IPOIB_CM" ) { + change_conf_param($parameter, $value, $conf); + } else { + # setup env variable, RPM installation will configure these + setup_env("$OPA_INSTALL_ENV", $env_value); + } +} + +sub prompt_openib_conf_param($$$;$) +{ + my $parameter=shift(); + my $parameterDesc=shift(); + my $default=shift(); + my $OPA_INSTALL_ENV=shift(); + + prompt_conf_param($parameter, $parameterDesc, $default, + "/$OFED_CONFIG", $OPA_INSTALL_ENV); +} + +sub prompt_opa_conf_param($$$;$) +{ + my $parameter=shift(); + my $parameterDesc=shift(); + my $default=shift(); + my $OPA_INSTALL_ENV=shift(); + + prompt_conf_param($parameter, $parameterDesc, $default, + "/$OPA_CONFIG", $OPA_INSTALL_ENV); +} diff --git a/CommonInstall/util_deb.pl b/CommonInstall/util_deb.pl new file mode 100755 index 0000000..9c8d2ba --- /dev/null +++ b/CommonInstall/util_deb.pl @@ -0,0 +1,781 @@ +#!/usr/bin/perl +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] +use strict; +#use Term::ANSIColor; +#use Term::ANSIColor qw(:constants); +#use File::Basename; +#use Math::BigInt; + +# ============================================================================= +# The functions and constants below assist in using DEB files +my $rpm_check_dependencies = 1; # can be set to 0 to disable rpm_check_os_prereqs + +my $RPM_ARCH=my_tolower("$ARCH"); +my $RPM_KERNEL_ARCH = `uname -m`; # typically matches $RPM_ARCH +chomp $RPM_KERNEL_ARCH; + +# return array of cmds for verification during init +sub rpm_get_cmds_for_verification() +{ + return ("dpkg", "dpkg-deb", "dpkg-query"); +} + +sub rpm_to_deb_option_trans($) +{ + my ($options) = shift(); + + #Update option is not required for deb, remove it + $options =~ s/-U//g; + #Installation despite lacking dependencies should not be necessary on Ubuntu + $options =~ s/--nodeps/--force-depends/g; + + return $options; +} + +# version string for kernel used in RPM filenames uses _ instead of - +sub rpm_tr_os_version($) +{ + my $osver = shift(); # uname -r style output + $osver =~ s/-/_/g; + return "$osver"; +} + +# translation from rpm package format to deb one +sub rpm_to_deb_pkg_trans($) +{ + my ($pkg) = shift(); # package name + $pkg =~ s/-devel/-dev/g; + return $pkg; +} + +# Attribute translation +sub rpm_to_deb_attr_trans($) +{ + my $attr = shift(); # attribute name: such as NAME or VERSION + if($attr eq 'RELEASE'){ + $attr = 'Version'; + } + + if($attr eq 'NAME'){ + $attr = 'Package'; + } + + if($attr eq 'VERSION'){ + $attr = 'Version'; + } + + if($attr eq 'INSTALLPREFIX'){ + # TODO: no equivalent in dpkg + $attr = '/usr/mpi'; + } + + return $attr; +} + +# query a parameter of RPM tools themselves +sub rpm_query_param($) +{ + my $param = shift(); # parameter name: such as _mandir, _sysconfdir, _target_cpu + my $ret = ''; + + if($param eq 'arch'){ + $ret = `dpkg --print-architecture`; + } elsif ($param eq '_mandir'){ + $ret = '/usr/share/man'; + } elsif ($param eq '_sysconfdir'){ + $ret = '/etc'; + } elsif ($param eq 'optflags'){ + return ""; + } else { + return ""; + } + + chomp $ret; + return $ret; +} + +# query an attribute of the RPM file +sub rpm_query_attr($$) +{ + my $debfile = shift(); # .deb file + my $attr = shift(); # attribute name: such as NAME or VERSION + + $attr = rpm_to_deb_attr_trans($attr); + + if ( ! -f "$debfile" ) { + return ""; + } + + my $query = 'dpkg-deb --showformat=\'${'.$attr.'}\n\' --show '.$debfile.' 2>/dev/null'; + my $val = `$query`; + + return $val; +} + +# query an attribute of the installed RPM package +sub rpm_query_attr_pkg($$) +{ + my $package = shift(); # installed package + my $attr = shift(); # attribute name: such as NAME or VERSION + + $attr = rpm_to_deb_attr_trans($attr); + $package = rpm_to_deb_pkg_trans($package); + + my $val = `dpkg-query --showformat='\${$attr}\n' --show $package 2>/dev/null`; + + return $val; +} + +# get name of deb package +sub rpm_query_name($) +{ + my $debfile = shift(); # .deb file + return rpm_query_attr($debfile, "Package"); +} + +# return NAME-VERSION-RELEASE.ARCH +sub rpm_query_full_name($) +{ + my $debfile = shift(); # .deb file + + if ( ! -f "$debfile" ) { + return ""; + } + my $var = `dpkg-deb --showformat='[\${Package}-\${Version}.\${Architecture}]' --show $debfile 2>/dev/null`; + return $var; +} + +# get list of package debs installed +# the list could include multiple versions and/or multiple architectures +# and/or multiple kernel releases +# all entries in returned list are complete package names in the form: +# NAME-VERSION-RELEASE.ARCH +sub rpms_installed_pkg($$) +{ + my $package=shift(); + my $mode = shift(); # "user" or kernel rev or "firmware" + # "any"- checks if any variation of package is installed + my @lines=(); + my $cpu; + + $package = rpm_to_deb_pkg_trans($package); + + $cpu = rpm_get_cpu_arch($mode); + my $cmd = 'dpkg-query --showformat=\'${Package}:${Architecture}\' --show '.$package.' 2>/dev/null\n'; + if ( "$mode" eq "any" ) { + DebugPrint($cmd."|"); + open(debs, $cmd."|"); + } elsif ("$mode" eq "user" || "$mode" eq "firmware") { + DebugPrint($cmd."|egrep '\.$cpu\$' 2>/dev/null\n"); + open(debs, $cmd."|egrep '\.$cpu\$' 2>/dev/null|"); + } else { + # $mode is kernel rev, verify proper kernel version is installed + # for kernel packages, RELEASE is kernel rev + my $release = rpm_tr_os_version($mode); + DebugPrint($cmd."|egrep '-$release\.$cpu\$' 2>/dev/null\n"); + open(debs, $cmd."|egrep '-$release\.$cpu\$' 2>/dev/null|"); + } + @lines=; + close(debs); + if ( $? != 0) { + # query command failed, package must not be installed + @lines=(); + } + chomp(@lines); + DebugPrint("package $package $mode: installed: @lines\n"); + return @lines; +} + +# get list of package debs installed +# the list could include multiple versions and/or multiple architectures +# and/or multiple kernel releases +# all entries in returned list are complete package names in the form: +# NAME:ARCH +sub rpms_variations_installed_pkg($$) +{ + my $package=shift(); + my $mode = shift(); + + my @result=(); + + @result = ( @result, rpms_installed_pkg($package, $mode) ); + return @result; +} + +sub rpm_query_all($$) +{ + my $package = shift(); + my $filter = shift(); + + $package = rpm_to_deb_pkg_trans($package); + + my $res=`dpkg --get-selections 2>/dev/null |grep -v '\sdeinstall\s'|grep -i '$package'|grep '$filter'`; + $res=~s/\n/ /g; + return $res; +} + +# determine if rpm parameters will allow srpms to build debuginfo rpms +sub rpm_will_build_debuginfo() +{ + +} + +sub rpm_query_version_release($) +{ + my $debfile = shift(); # .deb file + return rpm_query_attr($debfile, "VERSION"); +} + +# get VERSION-RELEASE of installed RPM package +sub rpm_query_version_release_pkg($) +{ + my $package = shift(); # installed package + return rpm_query_attr_pkg($package, "VERSION"); +} + +sub rpm_get_cpu_arch($) +{ + my $mode = shift(); # "user" or kernel rev or "firmware" + # "any"- checks if any variation of package is installed + return rpm_query_param("arch"); +} + +my $last_checked; # last checked for in rpm_is_installed +sub rpm_is_installed($$) +{ + my $package = shift(); # package name + my $mode = shift(); # "user" or kernel rev or "firmware" + # "any"- checks if any variation of package is installed + my $rc; + my $cpu; + + $package = rpm_to_deb_pkg_trans($package); + + if ($user_space_only && "$mode" ne "user" && "$mode" ne "any") { + return 1; + } + + $cpu = rpm_get_cpu_arch($mode); + if ("$mode" eq "any" ) { + # any variation is ok + my $cmd = "dpkg -l '$package' | egrep '^ii' > /dev/null 2>&1"; + DebugPrint $cmd."\n"; + $rc = system($cmd); + $last_checked = "any variation"; + } elsif ("$mode" eq "user" || "$mode" eq "firmware") { + # verify $cpu version or any is installed + my $cmd = "dpkg -l '$package' | egrep '^ii' 2>/dev/null|egrep '^$cpu\$|' >/dev/null 2>&1"; + DebugPrint $cmd."\n"; + $rc = system $cmd; + $last_checked = "for $mode $cpu or noarch"; + } else { + # $mode is kernel rev, verify proper kernel version is installed + # for kernel packages, RELEASE is kernel rev + my $release = rpm_tr_os_version($mode); + my $cmd = "dpkg --get-selections | grep $package.*'[%{VERSION}\\n]' | grep -v 'deinstall' 2>/dev/null|egrep '$release' >/dev/null 2>&1"; + DebugPrint $cmd."\n"; + $rc = system $cmd; + $last_checked = "for kernel $release"; + } + DebugPrint("Checked if $package $mode is installed: ".(($rc==0)?"yes":"no")."\n"); + return 0 == $rc; +} + +sub rpm_is_installed_list($@) +{ + my $mode = shift(); # "user" or kernel rev or "firmware" + # "any"- verifies any variation of package is installed + my @package_list = @_; # package names + + foreach my $package ( @package_list ) + { + if ( ! rpm_is_installed($package, $mode) ) { + return 0; + } + } + return 1 +} + +# return 0 on success, number of errors otherwise +sub rpm_check_os_prereqs_internal($$@) +{ + my $mode = shift(); # default mode + my $message = shift(); + my @package_list = @_; # package names + my $err=0; + + if ( ! $rpm_check_dependencies ) { + return 0; + } + # Check installation requirements + DebugPrint "Checking prereqs $message: @package_list\n"; + for my $package_info ( @package_list ) + { + # expand any alias in package_info + my $full_package_info=""; + my @alternatives = (split ('\|',$package_info)); + for my $altpackage_info ( @alternatives ) + { + my ($package, $details) = (split (' ',$altpackage_info,2)); + if ($details ne "") { + $details=" $details"; + } + if ( "$full_package_info" ne "" ) { + $full_package_info = "$full_package_info|"; + } + + # expand "g77" alias for various fortran compilers + # and "libgfortran" alias for various fortran library + if ("$package" eq "g77" ) { + # on Ubuntu 17.04: gfortran + $full_package_info = "${full_package_info}gfortran$details"; + } elsif ("$package" eq "libgfortran") { + # on Ubuntu 17.04: libgfortran + $full_package_info = "${full_package_info}libgfortran$details"; + } else { + $full_package_info = "${full_package_info}$altpackage_info"; + } + } + + # now process the expanded list of alternatives + DebugPrint "Checking prereq: $full_package_info\n"; + my $errmessage=""; + @alternatives = (split ('\|',$full_package_info)); + for my $altpackage_info ( @alternatives ) + { + DebugPrint "Checking prereq: $altpackage_info\n"; + my ($package, $version, $pkgmode) = (split (' ',$altpackage_info)); + if ("$pkgmode" eq "") { + $pkgmode = $mode; + } + + $package = rpm_to_deb_pkg_trans($package); + if (! rpm_is_installed($package, $pkgmode)) { + if ( $errmessage ne "") { + $errmessage="$errmessage\n OR "; + } + $errmessage = "$errmessage$package ($last_checked)"; + } else { + $errmessage=""; + last; + } + } + if ( $errmessage ne "" ) { + if (scalar(@alternatives) > 1) { + $errmessage="$errmessage\n"; + } + NormalPrint("$errmessage is required$message\n"); + $err++; + } + } + return $err; +} + +sub rpm_check_os_prereqs($$) +{ + no strict 'refs'; + my $comp = shift(); + my $mode = shift(); + my $list_name; + my $array_ref; + my @rpm_list = {}; + my $prereq_check = 0; + + if ( ! $rpm_check_dependencies ) { + return 0; + } + + $list_name=$comp."_prereq"; + $array_ref = $comp_prereq_hash{$list_name}; + #checking if prereq array exists + #it assumed that it has no prereqs it array does not exist + if ( $array_ref ) { + @rpm_list = @{ $array_ref }; + } + else{ + return 0; + } + + #checking whether each entry in rpm_list is installed + DebugPrint "Checking prereqs for $comp\n"; + foreach (@rpm_list){ + DebugPrint "Checking installation of $_\n"; + #Don't check dependencies for kernel RPMS if their installation is skipped + if($user_space_only == 1){ + if( "$_" =~ /kernel/ || "$_" =~ /kmod/ || "$_" eq "pciutils" ) { + DebugPrint("Skipping check for $_ \n"); + next; + } + } + if(!rpm_is_installed($_, $mode)){ + NormalPrint("--> $comp requires $_ \n"); + $prereq_check = 1; + } + } + + return $prereq_check; +} + +sub rpm_check_build_os_prereqs($$@) +{ + my $mode = shift(); + my $build_info = shift(); + my @package_list = @_; # package names + return rpm_check_os_prereqs_internal($mode, " to build $build_info", @package_list); +} + +# uninstall all packages which match package partial name and filter +# returns 0 on sucess (or package not installed), != 0 on failure +sub rpm_uninstall_matches($$$;$) +{ + my $name = shift(); # for use only in log messages + my $package = shift(); # part of package name + my $filter = shift(); # any additional grep filter + my $options = shift(); # additional rpm command options + + $options = rpm_to_deb_option_trans($options); + my $rpms = rpm_query_all("$package", "$filter"); + + if ( "$rpms" ne "" ) { + LogPrint "uninstalling $name: dpkg -r $options $rpms\n"; + my $out =`dpkg -r $options $rpms 2>&1`; + my $rc=$?; + NormalPrint("$out"); + if ($rc != 0) { + $exit_code = 1; + } + return $rc; + } else { + return 0; + } +} + +sub rpm_run_install($$$) +{ + my $debfile = shift(); # .rpm file + my $mode = shift(); # "user" or kernel rev or "firmware" + # "any"- will install any variation found + my $options = shift(); # additional rpm command options + + $options = rpm_to_deb_option_trans($options); + + + if ($user_space_only && "$mode" ne "user" && "$mode" ne "any") { + return; + } + + if ( ! -e $debfile ) { + NormalPrint "Not Found: $debfile $mode\n"; + return; + } + + my $package = rpm_query_name($debfile); + my $fullname = rpm_query_full_name($debfile); + my $out; + + NormalPrint "installing ${fullname}...\n"; + + my $cmd = "dpkg -i $options $debfile"; + LogPrint $cmd."\n"; + $out=`$cmd 2>&1`; + if ( $? == 0 ) { + NormalPrint("$out"); + } else { + NormalPrint("ERROR - Failed to install $debfile\n"); + NormalPrint("$out"); + $exit_code = 1; + HitKeyCont; + } +} + +# returns 0 on sucess (or package not installed), != 0 on failure +# uninstalls all variations of given package +sub rpm_uninstall($$$$) +{ + my $package = shift(); # package name + my $mode = shift(); # "user" or kernel rev or "firmware" + # "any"- checks if any variation of package is installed + my $options = shift(); # additional rpm command options + my $verbosity = shift(); # verbose or silent + my @fullnames = rpms_variations_installed_pkg($package, $mode); # already adjusts mode + $options = rpm_to_deb_option_trans($options); + my $rc = 0; + + foreach my $fullname (@fullnames) { + if ( "$verbosity" ne "silent" ) { + print "Uninstalling ${fullname}...\n"; + } + my $cmd = "dpkg -r $options $fullname"; + LogPrint $cmd."\n"; + my $out=`$cmd 2>&1`; + $rc |= $?; + NormalPrint("$out"); + if ($rc != 0) { + $exit_code = 1; + } + } + return $rc; +} + +# resolve rpm package filename for $mode +# package_path is a glob style absolute or relative path to the package +# including the package name, but excluding package version, architecture and +# .rpm suffix +sub rpm_resolve($$) +{ + my $debpath = shift(); + my $mode = shift(); + my $debfile; + my $cpu; + + $package = rpm_to_deb_pkg_trans($package); + + $cpu = rpm_get_cpu_arch($mode); + # we expect 0-1 match, ignore all other filenames returned + DebugPrint("Checking for User Deb: ${debpath}_*-*_${cpu}.deb\n"); + $debfile = file_glob("${debpath}_*-*_${cpu}.deb"); + if ( "$debfile" eq "" || ! -e "$debfile" ) { + # we expect 0-1 match, ignore all other filenames returned + DebugPrint("Checking for User Deb: ${debpath}_*-*.any.deb\n"); + $debfile = file_glob("${debpath}_*-*.any.deb"); + } + if ( "$debfile" eq "" || ! -e "$debfile" ) { + # we expect 0-1 match, ignore all other filenames returned + DebugPrint("Checking for User Deb: ${debpath}_*-*_all.deb\n"); + $debfile = file_glob("${debpath}_*-*_all.deb"); + } + VerbosePrint("Resolved $debpath $mode: $debfile\n"); + return $debfile; +} + +sub rpm_exists($$) +{ + my $debpath = shift(); + my $mode = shift(); # "user" or kernel rev or "firmware" + # "any"- any variation found + my $debfile; + + $debfile = rpm_resolve("$debpath", $mode); + return ("$debfile" ne "" && -e "$debfile") +} + +sub rpm_install_with_options($$$) +{ + my $debpath = shift(); + my $mode = shift(); # "user" or kernel rev or "firmware" + # "any"- will install any variation found + my $options = shift(); # additional deb command options + my $debfile; + + if ($user_space_only && "$mode" ne "user" && "$mode" ne "any") { + return; + } + + $debfile = rpm_resolve("$debpath", $mode); + if ( "$debfile" eq "" || ! -e "$debfile" ) { + NormalPrint "Not Found: $debpath $mode\n"; + } else { + rpm_run_install($debfile, $mode, $options); + } +} + +# TBD - phase out this function (or get all callers to use same options) +sub rpm_install($$) +{ + my $debpath = shift(); + my $mode = shift(); # "user" or kernel rev or "firmware" + # "any"- will install any variation found + rpm_install_with_options($debpath, $mode, ""); +} + + +# verify the rpmfiles exist for all the RPMs listed +sub rpm_exists_list($$@) +{ + my $debdir = shift(); + my $mode = shift(); # "user" or kernel rev or "firmware" + # "any"- any variation found + my @package_list = @_; # package names + + foreach my $package ( @package_list ) + { + if (! rpm_exists("$debdir/$package", $mode) ) { + return 0; + } + } + return 1; +} + +sub rpm_install_list_with_options($$$@) +{ + my $debdir = shift(); + my $mode = shift(); # "user" or kernel rev or "firmware" + # "any"- will install any variation found + my $options = shift(); # additional rpm command options + my @package_list = @_; # package names + + foreach my $package ( @package_list ) + { + rpm_install_with_options("$debdir/$package", $mode, $options); + } +} + +# TBD - phase out this function (or get all callers to use same options) +sub rpm_install_list($$@) +{ + my $debdir = shift(); + my $mode = shift(); # "user" or kernel rev or "firmware" + # "any"- will install any variation found + my @package_list = @_; # package names + + rpm_install_list_with_options($debdir, $mode, "", @package_list); +} + +# debpath_list is a list of glob style absolute or relative path to the packages +# including the package name, but excluding package version, architecture and +# .deb suffix +sub rpm_install_path_list_with_options($@) +{ + my $mode = shift(); # "user" or kernel rev or "firmware" + # "any"- will install any variation found + my $options = shift(); # additional rpm command options + my @debpath_list = @_; # deb pathnames + + foreach my $debpath ( @debpath_list ) + { + rpm_install_with_options("$debpath", $mode, $options); + } +} + +# debpath_list is a list of glob style absolute or relative path to the packages +# including the package name, but excluding package version, architecture and +# .deb suffix +# TBD - phase out this function (or get all callers to use same options) +sub rpm_install_path_list($@) +{ + my $mode = shift(); # "user" or kernel rev or "firmware" + # "any"- will install any variation found + my @debpath_list = @_; # deb pathnames + + rpm_install_path_list_with_options($mode, "", @debpath_list); +} + +# returns 0 on success (or rpms not installed), != 0 on failure +sub rpm_uninstall_list2($$$@) +{ + my $mode = shift(); # "user" or kernel rev or "firmware" + # "any"- checks if any variation of package is installed + my $options = shift(); # additional rpm command options + my $verbosity = shift(); # verbose or silent + my @package_list = @_; # package names + my $package; + my $ret = 0; # assume success + + foreach $package ( reverse(@package_list) ) + { + $ret |= rpm_uninstall($package, $mode, $options, $verbosity); + } + return $ret; +} + +# returns 0 on success (or rpms not installed), != 0 on failure +sub rpm_uninstall_list($$@) +{ + my $mode = shift(); # "user" or kernel rev or "firmware" + # "any"- checks if any variation of package is installed + my $verbosity = shift(); # verbose or silent + my @package_list = @_; # package names + my $options = ""; + return rpm_uninstall_list2($mode, $options, $verbosity, @package_list); +} + + +# uninstall all rpms which match any of the supplied package names +# and based on mode and distro/cpu, +# uninstall is done in a single command +# returns 0 on success (or rpms not installed), != 0 on failure +# Force to uninstall without any concern for dependency. +sub rpm_uninstall_all_list_with_options($$$@) +{ + my $mode = shift(); # "user" or kernel rev or "firmware" + # "any"- checks if any variation of package is installed + my $options = shift(); # additional rpm command options + my $verbosity = shift(); # verbose or silent + my @package_list = @_; # package names + return rpm_uninstall_list2($mode, $options, $verbosity, @package_list); +} + +# uninstall all rpms which match any of the supplied package names +# and based on mode and distro/cpu. +# uninstall is done in a single command so dependency issues handled +# returns 0 on success (or rpms not installed), != 0 on failure +# # TBD - phase out this function (or get all callers to use same options) +sub rpm_uninstall_all_list($$@) +{ + my $mode = shift(); # "user" or kernel rev or "firmware" + # "any"- checks if any variation of package is installed + my $verbosity = shift(); # verbose or silent + my @package_list = @_; # package names + return rpm_uninstall_all_list_with_options($mode, "", $verbosity, (@package_list)); +} + +# see if prereqs for building kernel modules are installed +# return 0 on success, 1 if missing dependencies +sub check_kbuild_dependencies($$) +{ + my $osver = shift(); # kernel rev + my $srpm = shift(); # what trying to build + my $dir = "/lib/modules/$osver/build"; + + if ( ! $rpm_check_dependencies ) { + return 0; + } + if ( ! -d "$dir/scripts" ) { + NormalPrint "Unable to build $srpm: $dir/scripts: not found\n"; + NormalPrint "linux-source or linux-headers-generic is required to build $srpm\n"; + return 1; # failure + } + return 0; +} + +# see if basic prereqs for building RPMs are installed +# return 0 on success, or number of missing dependencies +sub check_rpmbuild_dependencies($) +{ + my $srpm = shift(); # what trying to build + my $err = 0; + if (! rpm_is_installed("devscripts", "any")) { + NormalPrint("devscripts is required to build $srpm\n"); + $err++; + } +} + diff --git a/CommonInstall/util_driver.pl b/CommonInstall/util_driver.pl new file mode 100755 index 0000000..80ac93d --- /dev/null +++ b/CommonInstall/util_driver.pl @@ -0,0 +1,88 @@ +#!/usr/bin/perl +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] +use strict; +#use Term::ANSIColor; +#use Term::ANSIColor qw(:constants); +#use File::Basename; +#use Math::BigInt; + +# ============================================================================ +# Driver file management + +my $RunDepmod=0; # do we need to run depmod +sub verify_modtools() +{ + my $look_str; + my $look_len; + my $ver; + my $mod_ver; + + $look_str = "insmod version "; + $look_len = length ($look_str); + $ver = `/sbin/insmod -V 2>&1 | grep \"$look_str\"`; + chomp $ver; + $mod_ver = substr ($ver, $look_len - 1, length($ver)-$look_len+1); + $_ = $mod_ver; + /2\.[34]\.[0-9]+/; + #$MOD_UTILS_REV; + if ($& eq "") + { + NormalPrint "Unable to proceed, modutils tool old: $mod_ver\n"; + Abort "Install newer version of modutils 2.3.15 or greater" ; + } +} + +# the following two routines are used for STL-14186. hfi2 rpm doesn't call depmod on uninstall, so we need to explicitly +# call it when we uninstall opa_stack. After we resolve the issue, we shall remove the following 2 routines +sub clear_run_depmod() +{ + $RunDepmod=0; +} + +sub set_run_depmod() +{ + $RunDepmod=1; +} + +sub check_depmod() +{ + if ($RunDepmod == 1 ) + { + print_separator; + print "Generating module dependencies...\n"; + LogPrint "Generating module dependencies: /sbin/depmod -aev\n"; + system "/sbin/depmod -aev > /dev/null 2>&1"; + $RunDepmod=0; + return 1; + } + return 0; +} diff --git a/CommonInstall/util_hosttools.pl b/CommonInstall/util_hosttools.pl new file mode 100755 index 0000000..7274801 --- /dev/null +++ b/CommonInstall/util_hosttools.pl @@ -0,0 +1,99 @@ +#!/usr/bin/perl +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] +use strict; +#use Term::ANSIColor; +#use Term::ANSIColor qw(:constants); +#use File::Basename; +#use Math::BigInt; + +# =========================================================================== +# Host Tools + +# capture host information for problem report +sub capture_report($) +{ + my($req_compname) = shift(); + + my $result; + my $inp; + my $detail; + + if ( ! -e "$BIN_DIR/opacapture" ) { + printf("$req_compname not installed on this system\n"); + printf("Unable to Generate Supporting Information\n"); + HitKeyCont; + return; + } + do { + printf ("\n\nEnter Filename to Generate [q to quit] : "); + $inp = ; + $inp=remove_whitespace($inp); + chomp $inp; + $_ = $inp; + + if (/^[Qq]$/) { + return; + } + + if ( length($inp) == 0 ) { + next; + } + + LogPrint "Capturing $INT_VERSION Report to $inp\n"; + $detail=GetNumericValue("Capture detail level (1-Normal 2-Fabric 3-Fabric+FDB 4-Analysis):", 1, 1, 4); + close_log; + $result = system "$BIN_DIR/opacapture -d $detail $inp"; + if ( $result != 0 ) { + printf("\nError generating $inp\n"); + } + } while ($result != 0); + open_log; + HitKeyCont; +} + +# invoke FastFabric TUI +my $FabricSetupScpFromDir="."; + +sub run_fastfabric($) +{ + my($req_compname) = shift(); + + if ( ! -e "$BIN_DIR/opafastfabric" ) { + printf("$req_compname not installed on this system\n"); + printf("Unable to perform FastFabric (Host/Chassis/Switch Setup/Admin)\n"); + HitKeyCont; + return; + } + system("$BIN_DIR/opafastfabric --fromdir $FabricSetupScpFromDir"); + return; +} + diff --git a/CommonInstall/util_ifcfg.pl b/CommonInstall/util_ifcfg.pl new file mode 100755 index 0000000..d847b5e --- /dev/null +++ b/CommonInstall/util_ifcfg.pl @@ -0,0 +1,634 @@ +#!/usr/bin/perl +## BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] + +# + +use strict; +#use Term::ANSIColor; +#use Term::ANSIColor qw(:constants); +#use File::Basename; +#use Math::BigInt; + +# ========================================================================== +# IP address configuration +# used for IPoIB at present but generalized so could support VNIC or +# iPathEther also + +my $FirstIPoIBInterface=0; # first device is ib0 +my $MAX_HFI_PORTS=20; # maximum valid ports + +# Validate the passed in IP address (or netmask). +# Verify there are enough dots '.' and same number of +# decimal numbers. This is not comprehensive. +# +# inputs: +# IP address in dot notation. eg: +# 'a.b.c.d' or 'a.b.c' or 'a.b' +# +# outputs: +# 0 == failure(not a valid IP address) +# 1 == Success. + +sub Validate_IP_Addr($) +{ + $_ = shift(); # setup for translate & other cmds + + my($count)= 0; + + # verify there are 3 and only 3 dots, 'a.b.c.d'. + # translate '.' to self, side-effect is the count. + + $count=(tr/\.//); + if ( $count < 1 || $count > 3 ) + { + return 0; + } + + # accept only decimal digits separated by dots. + if ( /[0-9\.]/ ) + { + # because we checked dots above, any of the three below is ok + if ( /([0-9]+)\.([0-9]+)\.([0-9]+)\.([0-9]+)/ ) + { + return 1; # Success + } + if ( /([0-9]+)\.([0-9]+)\.([0-9]+)/ ) + { + return 1; # Success + } + if ( /([0-9]+)\.([0-9]+)/ ) + { + return 1; # Success + } + } + return 0; # failure. +} + + +# Retrieve an IPV4 address in standard 'dot' notation from stdin. +# Perform simple IP address format validation. +# +# returns: +# IP address string. +# + +sub Get_IP_Addr($$) +{ + my($interface) = shift(); + my($default_ip) = shift(); + + my($ip,$idx); + + # acquire a valid IP address. + # sadly last & redo caused runtime errors? + + do + { + if ("$default_ip" ne "") + { + print "Enter IPV4 address in dot notation (or dhcp) for $interface [$default_ip]: "; + } else { + print "Enter IPV4 address in dot notation (or dhcp) for $interface: "; + } + chomp($ip = ); + $ip=remove_whitespace($ip); + + if ( length($ip) == 0 && "$default_ip" ne "" ) + { + $ip = $default_ip; + $_ = "y"; + } + else + { + # verify there are enough chars for a valid IP address + if ( "$ip" ne "dhcp" && Validate_IP_Addr($ip) == 0 ) + { + print("Bad IPV4 address '$ip'\n"); + $_ = "n"; + } + else + { + do + { + # require a response + print("Is IPV4 address '$ip' correct? (y/n): "); + chomp($_ = ); + $_=remove_whitespace($_); + } until (/[YyNn]/); + } + } + } until (/[Yy]/); + LogPrint "Enter IPV4 address in dot notation for $interface: -> $ip\n"; + + return $ip; +} + +# Retrieve an IPV4 netmask in standard 'dot' notation from stdin. +# Perform simple IP address format validation. +# +# returns: +# IP address string. +# + +sub Get_IP_Addr_Netmask($$) +{ + my($interface) = shift(); + my($ipaddr) = shift(); + + my($idx,$default_netmask,$dot_count); + my $netmask; + + if ( "$ipaddr" eq "dhcp" ) { + return ""; + } + $default_netmask = `/usr/lib/opa/tools/opaipcalc --netmask $ipaddr`; + $default_netmask =~ s/NETMASK=//; + $default_netmask =~ s/\n//; + $_ = $ipaddr; # setup for translate & other cmds + $dot_count=(tr/\.//); + do + { + print "Enter IPV4 netmask in dot notation for $interface $ipaddr [$default_netmask]: "; + chomp($netmask = ); + $netmask=remove_whitespace($netmask); + $_=$netmask; + + if ( length($netmask) == 0 ) + { + $netmask = $default_netmask; + print("Is IPV4 netmask '$netmask' correct? (y/n): "); + chomp($_ = ); + $_=remove_whitespace($_); + } + else + { + # verify there are enough chars for a valid IP address + if ( Validate_IP_Addr($netmask) == 0 ) + { + print("Bad IPV4 netmask: '$netmask'\n"); + $_ = "n"; + } + elsif ($dot_count != (tr/\.//)) + { + print("Inappropriate IPV4 netmask for $ipaddr: '$netmask'\n"); + $_ = "n"; + } + else + { + print("Is IPV4 netmask '$netmask' correct? (y/n): "); + chomp($_ = ); + $_=remove_whitespace($_); + } + } + } until (/[Yy]/); + LogPrint "Enter IPV4 netmask in dot notation for $interface $ipaddr [$default_netmask]: -> $netmask\n"; + return $netmask; +} + +# return the next sequential IPV4 address. Last numeric field is incremented. +# +# Assumes a valid dot notation IP address (e.g., 7.7.7.240) +# Increment the 'host' number ('240' in the example) by 1. +# 7.7.7.240 --> 7.7.7.241 +# +# input: +# base IP address in 'dot' notation. +# output: +# next IP address + +sub NextIPaddr($) +{ + my($base) = shift(); + + my($next,$hostnum,$idx,$len); + + if ( "$base" eq "dhcp" ) { + return "$base"; + } + # locate right-most '.' + $idx = rindex($base, "."); + Abort "NextIPaddr: Bad IPV4 address ".$base + if ($idx == -1); + + $idx += 1; # move past the dot to the last numeric field portion of + # the IP address. + + # extract the host number + $len = length($base); + $hostnum = substr($base, ($idx), ($len - $idx)); + + $hostnum += 1; # next host number + + # replace the last numeric field with the incremented host number + $next = $base; + substr($next,$idx,length($hostnum)) = $hostnum; + + DebugPrint("Next IP '$next'\n"); + + return $next +} + +# return the next sequential interface name. Last numeric field is incremented. +# if the final field is not numeric, returns "" +sub NextInterface($) +{ + my($base) = shift(); + + my($next,$hostnum,$idx,$len); + my $number; + my $prefix; + + $_ = $base; + if ( ! /.*([0-9]+)$/ ) + { + # non numeric name, can't auto-increment + return ""; + } + $prefix = $base; + $prefix =~ s/(.*)([0-9]+)$/$1/; + $number = $base; + $number =~ s/(.*)([0-9]+)$/$2/; + + $number += 1; # next intf number + + return "$prefix$number"; +} + +# build the ifcfg file for a network device +sub Build_ifcfg($$$) +{ + my($device) = shift(); # device name + my($ipaddr) = shift(); # ip address for device or "dhcp" + my($netmask) = shift(); # ip address netmask for device + + my($target, $SysCmd); + my ($temp); + + $target = "$NETWORK_CONF_DIR/ifcfg-$device"; + print("Creating ifcfg-$device for $ipaddr mask $netmask\n\n"); + + if ( "$CUR_DISTRO_VENDOR" eq "UnitedLinux" || "$CUR_DISTRO_VENDOR" eq "SuSE") { + if ( "$ipaddr" eq "dhcp" ) { + # append boot protocol type + $SysCmd = "echo \"BOOTPROTO=\'dhcp\'\" >> $target"; + DebugPrint("cmd '$SysCmd'\n"); + system $SysCmd; + } else { + # append boot protocol type + $SysCmd = "echo \"BOOTPROTO=\'static\'\" >> $target"; + DebugPrint("cmd '$SysCmd'\n"); + system $SysCmd; + + # append the device instance internet protocol address + $SysCmd = "echo \"IPADDR=\'$ipaddr\'\" >> $target"; + DebugPrint("cmd '$SysCmd'\n"); + system $SysCmd; + + # append the netmask + $SysCmd = "echo \"NETMASK=\'$netmask\'\" >> $target"; + DebugPrint("cmd '$SysCmd'\n"); + system $SysCmd; + + # append the network + $temp = `/usr/lib/opa/tools/opaipcalc --network $ipaddr $netmask`; + chomp($temp); + $temp =~ s/NETWORK=//; + $SysCmd = "echo \"NETWORK=\'$temp\'\" >> $target"; + DebugPrint("cmd '$SysCmd'\n"); + system $SysCmd; + + # append the broadcast + $temp = `/usr/lib/opa/tools/opaipcalc --broadcast $ipaddr $netmask`; + chomp($temp); + $temp =~ s/BROADCAST=//; + $SysCmd = "echo \"BROADCAST=\'$temp\'\" >> $target"; + DebugPrint("cmd '$SysCmd'\n"); + system $SysCmd; + + $SysCmd = "echo \"REMOTE_IPADDR=\'\'\" >> $target"; + DebugPrint("cmd '$SysCmd'\n"); + system $SysCmd; + } + + $SysCmd = "echo \"STARTMODE=\'hotplug\'\" >> $target"; + DebugPrint("cmd '$SysCmd'\n"); + system $SysCmd; + + $SysCmd = "echo \"WIRELESS='no'\" >> $target"; + DebugPrint("cmd '$SysCmd'\n"); + system $SysCmd; + + # SLES11 and newer have IPOIB_MODE option in ifcfg + if ( "$CUR_VENDOR_VER" eq "ES123" ) { + $SysCmd = "echo \"IPOIB_MODE='connected'\" >> $target"; + DebugPrint("cmd '$SysCmd'\n"); + system $SysCmd; + $SysCmd = "echo \"MTU=65520\" >> $target"; + DebugPrint("cmd '$SysCmd'\n"); + system $SysCmd; + } else { + $SysCmd = "echo \"IPOIB_MODE='datagram'\" >> $target"; + DebugPrint("cmd '$SysCmd'\n"); + system $SysCmd; + NormalPrint "Note: IPoIB Mode is Datagram\n"; + } + } else { + # Append the device instance name + $SysCmd = "echo DEVICE=$device > $target"; + DebugPrint("cmd '$SysCmd'\n"); + system $SysCmd; + + $SysCmd = "echo \"TYPE=\'InfiniBand\'\" >> $target"; + DebugPrint("cmd '$SysCmd'\n"); + system $SysCmd; + + if ( "$ipaddr" eq "dhcp" ) { + $SysCmd = "echo BOOTPROTO=dhcp >> $target"; + DebugPrint("cmd '$SysCmd'\n"); + system $SysCmd; + + $SysCmd = "echo DHCPCLASS= >> $target"; + DebugPrint("cmd '$SysCmd'\n"); + system $SysCmd; + } else { + + $SysCmd = "echo BOOTPROTO=static >> $target"; + DebugPrint("cmd '$SysCmd'\n"); + system $SysCmd; + + # Append the device instance Internet Protocol address + $SysCmd = "echo IPADDR=$ipaddr >> $target"; + DebugPrint("cmd '$SysCmd'\n"); + system $SysCmd; + + # append the network,broadcast + $SysCmd = "/usr/lib/opa/tools/opaipcalc --network --broadcast $ipaddr $netmask >> $target"; + DebugPrint("cmd '$SysCmd'\n"); + system $SysCmd; + + # append the netmask + $SysCmd = "echo NETMASK=$netmask >> $target"; + DebugPrint("cmd '$SysCmd'\n"); + system $SysCmd; + } + + $SysCmd = "echo ONBOOT=yes >> $target"; + DebugPrint("cmd '$SysCmd'\n"); + system $SysCmd; + + $SysCmd = "echo CONNECTED_MODE=no >> $target"; + DebugPrint("cmd '$SysCmd'\n"); + system $SysCmd; +# $SysCmd = "echo MTU=65520 >> $target"; +# DebugPrint("cmd '$SysCmd'\n"); +# system $SysCmd; + NormalPrint "Note: IPoIB Mode is Datagram\n"; + } + + system "chown $OWNER $target"; + system "chgrp $GROUP $target"; + system "chmod ugo=r,u=rw $target"; +} + +sub Config_IP_Manually($$) +{ + my($compname) = shift(); + my($sampledev) = shift(); + + print "\n$compname requires an ifcfg file for each $compname device instance.\n"; + print ("Manually create files such as '$NETWORK_CONF_DIR/ifcfg-$sampledev'\n"); +} + + +sub Exist_ifcfg($) +{ + my($prefix) = shift(); + + my $ifcfg_wildcard="$NETWORK_CONF_DIR/ifcfg-$prefix"."[0-9]*"; + return ( `ls $ifcfg_wildcard 2>/dev/null` ne "" ); +} + +# +# Generate the network interface config files for IP over IB +# /etc/sysconfig/network-scripts/ifcfg-ibl1 +# +# Assign IP (Internet Protocol) addresses in standard 'dot' notation to +# IP over IB device instances. Create IP over IB 'ifup ibX' configuration files +# located in '/etc/sysconfig/network-scripts' for each IP over IB port. +# +# **** Currently - ONLY static IP address assignment is supported. +# +# inputs: +# [0] == are we reconfiguring, if 1, allows editing of existing ifcfg files +# +# outputs: +# none. +# +sub Config_ifcfg($$$$$) +{ + my($reconfig) = shift(); + my($compname) = shift(); + my($prefix) = shift(); + my($firstdev) = shift(); + my($showoptions) = shift(); + + my($max_ports,$port,$a,$inp,$seq,$intf_seq,$default_intf); + my($netmask); + my($ipaddr) = ""; + my($interface) = ""; + my(%interfaces) = (); + my $config_dir; + + $max_ports = 0; + + # Check if ifcfg files are present + my $ifcfg_wildcard="$NETWORK_CONF_DIR/ifcfg-$prefix"."[0-9]*"; + if ( `ls $ifcfg_wildcard 2>/dev/null` ne "" ) + { + if ($reconfig) + { + # always prompt regardless of previous check_keep_config answer + clear_keep_config("$ifcfg_wildcard"); + } + if (! $reconfig + || check_keep_config("$ifcfg_wildcard", "$compname ifcfg files", "y")) + { + print "Leaving $ifcfg_wildcard unchanged...\n"; + return; + } + print "removing $ifcfg_wildcard\n"; + system "rm -f $ifcfg_wildcard"; + } + if (GetYesNo("Configure $compname IPV4 addresses now?", "n") == 0) + { + # If user answered 'no', then reluctantly bail. + Config_IP_Manually("$compname","$prefix$firstdev"); + return; + } + + if ( $showoptions != 0 ) + { + printf ("\nYou may configure an $compname interface for each HFI port\n"); + printf ("Or you may select to have $compname only run on some HFI ports\n"); + printf ("Or you may select to configure redundant HFI ports with a\n"); + printf ("pair of HFI ports running a single $compname interface\n"); + } + do + { + printf ("How many $compname interfaces would you like to configure? [1]: "); + + $inp = ; + $inp=remove_whitespace($inp); + + if ( length($inp) == 0 ) + { + $max_ports=1; + } elsif ($inp < 0 || $inp > $MAX_HFI_PORTS) + { + printf ("You must specify a number between 0 and $MAX_HFI_PORTS\n"); + } elsif ($inp == 0) { + LogPrint "How many $compname interfaces would you like to configure? -> $inp\n"; + if (GetYesNo("You specified 0, would you like to skip IP address configuration?", "n") == 1) + { + # If user answered to skip, then reluctantly bail. + Config_IP_Manually("$compname","$prefix$firstdev"); + return; + } + } else { + $max_ports=$inp; + LogPrint "How many $compname interfaces would you like to configure? -> $inp\n"; + } + } while ($max_ports == 0); + + print "\nAbout to create $compname ifcfg files in $NETWORK_CONF_DIR\n"; + + # Does the user want sequential IP address assignment starting at a base + # IP address or specify an IP address for each HFI port (a.k.a. IPoIB device + # instance). + + if ( $max_ports > 1 ) { + $intf_seq = GetYesNo("Configure interface names sequentially starting with $prefix$firstdev?", "y"); + $seq = GetYesNo("Assign Internet Addresses sequentially from a base IP address?", "y"); + } else { + $intf_seq = GetYesNo("Use interface name $prefix$firstdev?", "y"); + $seq = 1; # doesn't matter + } + + # Allocate IP addresses and create the network config files '$prefix[firstdev...n]'. + + for($a=$firstdev; $a < $max_ports+$firstdev; $a++) + { + if ($intf_seq) + { + $interface="$prefix$a"; + } else { + $default_intf = $interface; + $interface = ""; + do { + if ($default_intf eq "" ) + { + print "Enter $compname interface name: "; + } else { + print "Enter $compname interface name [$default_intf]: "; + } + + chomp($inp = ); + $inp=remove_whitespace($inp); + if ( length($inp) == 0 ) + { + $inp=$default_intf; + } + if ("$inp" eq "" ) + { + printf "You must enter an interface name, such as $prefix$firstdev\n"; + } else { + if (exists $interfaces{$inp}) + { + print "You have already used $interface, specify a different name\n"; + } else { + $interface=$inp; + $interfaces{$interface} = 1; + } + } + } while ("$interface" eq ""); + } + LogPrint "Enter $compname interface name [$default_intf]: -> $interface\n"; + if ( $seq == 0 || $a == $firstdev) + { + # not sequential assignment, get each IP addr. + $ipaddr = Get_IP_Addr($interface, $ipaddr); + $netmask = Get_IP_Addr_Netmask($interface, $ipaddr); + } + + Build_ifcfg($interface, $ipaddr, $netmask); + # make sure future prompts start fresh and don't auto remove + clear_keep_config("$ifcfg_wildcard"); + + # generate the next sequential IP address + $ipaddr = NextIPaddr($ipaddr); + $interface = NextInterface($interface); + } +} + +# Remove ifcfg files. +# driver should have already been unloaded. +# +sub Remove_ifcfg($$$) +{ + my($WhichDriver) = shift(); # driver name + my($compname) = shift(); + my($prefix) = shift(); + + # This could be an 'update' where we might not want to clobber the + # IPoIB config files. + + my $ifcfg_wildcard="$NETWORK_CONF_DIR/ifcfg-$prefix"."[0-9]*"; + if ( `ls $ifcfg_wildcard 2>/dev/null` ne "" ) + { + if (check_keep_config("$ifcfg_wildcard", "$compname ifcfg files", "y")) + { + print "Keeping $compname ifcfg files ...\n"; + } else { + print "removing $ifcfg_wildcard\n"; + system "rm -f $ifcfg_wildcard"; + } + } +} + +sub check_network_config() +{ + my $nm=read_simple_config_param("/etc/sysconfig/network/config", "NETWORKMANAGER"); + if ( "$nm" eq "yes" ) { + print RED "Please set NETWORKMANAGER=no in /etc/sysconfig/network/config", RESET "\n"; + HitKeyCont; + } +} diff --git a/CommonInstall/util_init.pl b/CommonInstall/util_init.pl new file mode 100755 index 0000000..7768ac4 --- /dev/null +++ b/CommonInstall/util_init.pl @@ -0,0 +1,451 @@ +#!/usr/bin/perl +## BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] + +# + +#============================================================================ +# initialization +use strict; +use Term::ANSIColor; +use Term::ANSIColor qw(:constants); +use File::Basename; +use Math::BigInt; +use Cwd; + +#Setup some defaults +my $exit_code=0; + +my $Force_Install = 0;# force option used to force install on unsupported distro +my $GPU_Install = 0; +my $HFI2_INSTALL = 0; # indicate whether we shall install HFI2 +# When --user-space is selected we are targeting a user space container for +# installation and will skip kernel modules and firmware +my $user_space_only = 0; # can be set to 1 by --user-space argument + +# some options specific to OFA builds +my $OFED_force_rebuild=0; + +my $CUR_OS_VER = `uname -r`; +chomp $CUR_OS_VER; + +# related to HFI2_INSTALL. The following code is introduced to help us check b-s-m kernel for HFI2. +# After we merge HFI2 into ifs-kernel-updates, we shall remove the following. +my $CUR_OS_VER_SHORT = ''; +if ($CUR_OS_VER =~ /([0-9]+\.[0-9]+)/ ) { + $CUR_OS_VER_SHORT=$1; +} else { + die "\n\nKernel version \"${CUR_OS_VER}\" doesn't have an extractable major/minor version!\n\n"; +} + +my $RPMS_SUBDIR = "RPMS"; +my $SRPMS_SUBDIR = "SRPMS"; + +# firmware and data files +my $OLD_BASE_DIR = "/etc/sysconfig/opa"; +my $BASE_DIR = "/etc/opa"; +# iba editable config scripts +my $OPA_CONFIG_DIR = "/etc/opa"; + +my $UVP_CONF_FILE = "$BASE_DIR/uvp.conf"; +my $UVP_CONF_FILE_SOURCE = "uvp.conf"; +my $DAT_CONF_FILE_SOURCE = "dat.conf"; +my $NETWORK_CONF_DIR = "/etc/sysconfig/network-scripts"; +my $BIN_DIR = "/usr/sbin"; + +#This string is compared in verify_os_rev for correct revision of +#kernel release. +my $CUR_DISTRO_VENDOR = ""; +my $CUR_VENDOR_VER = ""; # full version (such as ES5.1) +my $CUR_VENDOR_MAJOR_VER = ""; # just major number part (such as ES5) +my $ARCH = `uname -m | sed -e s/ppc/PPC/ -e s/powerpc/PPC/ -e s/i.86/IA32/ -e s/ia64/IA64/ -e s/x86_64/X86_64/`; +chomp $ARCH; +my $DRIVER_SUFFIX=".o"; +if (substr($CUR_OS_VER,0,3) eq "2.6" || substr($CUR_OS_VER,0,2) eq "3.") +{ + $DRIVER_SUFFIX=".ko"; +} +my $DBG_FREE="release"; + + +# Command paths +my $RPM = "/bin/rpm"; + +# a few key commands to verify exist +my @verify_cmds = ( "uname", "mv", "cp", "rm", "ln", "cmp", "yes", "echo", "sed", "chmod", "chown", "chgrp", "mkdir", "rmdir", "grep", "diff", "awk", "find", "xargs", "sort"); + +# opa-scripts expects the following env vars to be 0 or 1. We set them to the default value here +setup_env("OPA_INSTALL_CALLER", 0); +default_opascripts_env_vars(); + +sub Abort(@); +sub NormalPrint(@); +sub LogPrint(@); +sub HitKeyCont(); +# ============================================================================ +# General utility functions + +# verify the given command can be found in the PATH +sub check_cmd_exists($) +{ + my $cmd=shift(); + return (0 == system("which $cmd >/dev/null 2>/dev/null")); +} + +sub check_root_user() +{ + my $user; + $user=`/usr/bin/id -u`; + if ($user != 0) + { + die "\n\nYou must be \"root\" to run this install program\n\n"; + } + + @verify_cmds = (@verify_cmds, rpm_get_cmds_for_verification()); + # verify basic commands are in path + foreach my $cmd ( @verify_cmds ) { + if (! check_cmd_exists($cmd)) { + die "\n\n$cmd not found in PATH.\nIt is required to login as root or su - root.\nMake sure the path includes /sbin and /usr/sbin\n\n"; + } + } +} + +sub my_tolower($) +{ + my($str) = shift(); + + $str =~ tr/[A-Z]/[a-z]/; + return "$str"; +} + +# ============================================================================ +# Version and branding + +# version string is filled in by prep, special marker format for it to use +my $VERSION = "THIS_IS_THE_ICS_VERSION_NUMBER:@(#)000.000.000.000B000"; +$VERSION =~ s/THIS_IS_THE_ICS_VERSION_NUMBER:@\(#\)//; +$VERSION =~ s/%.*//; +my $INT_VERSION = "THIS_IS_THE_ICS_INTERNAL_VERSION_NUMBER:@(#)000.000.000.000B000"; +$INT_VERSION =~ s/THIS_IS_THE_ICS_INTERNAL_VERSION_NUMBER:@\(#\)//; +$INT_VERSION =~ s/%.*//; +my $BRAND = "THIS_IS_THE_ICS_BRAND:Intel% "; +# backslash before : is so patch_brand doesn't replace string +$BRAND =~ s/THIS_IS_THE_ICS_BRAND\://; +$BRAND =~ s/%.*//; + +# convert _ and - in version to dots +sub dot_version($) +{ + my $version = shift(); + + $version =~ tr/_-/./; + return $version; +} + +# ============================================================================ +# installation paths + +# where to install libraries +my $LIB_DIR = "/lib"; +my $UVP_LIB_DIR = "/lib"; +my $USRLOCALLIB_DIR = "/usr/local/lib"; +my $OPTIBALIB_DIR = "/usr/lib/opa/lib"; +my $USRLIB_DIR = "/usr/lib"; +# if different from $LIB_DIR, where to remove libraries from past release +my $OLD_LIB_DIR = "/lib"; +my $OLD_USRLOCALLIB_DIR = "/usr/local/lib"; +my $OLD_UVP_LIB_DIR = "/lib"; + +sub set_libdir() +{ + if ( -d "/lib64" ) + { + $LIB_DIR = "/lib64"; + $UVP_LIB_DIR = "/lib64"; + $UVP_CONF_FILE_SOURCE = "uvp.conf.64"; + $DAT_CONF_FILE_SOURCE = "dat.conf.64"; + $USRLOCALLIB_DIR = "/usr/local/lib64"; + $OPTIBALIB_DIR = "/usr/lib/opa/lib64"; + $USRLIB_DIR = "/usr/lib64"; + } +} + +# determine the os vendor release level based on build system +# this script is stolen from funcs-ext.sh and should +# be maintained in parallel +sub os_vendor_version($) +{ + my $vendor = shift(); + + my $rval = ""; + my $mn = ""; + if ( -e "/etc/os-release" ) { + if ($vendor eq "ubuntu") { + $rval=`cat /etc/os-release | grep VERSION_ID | cut -d'=' -f2 | tr -d [\\"\\.]`; + } else { + $rval=`cat /etc/os-release | grep VERSION_ID | cut -d'=' -f2 | tr -d [\\"\\.0]`; + } + chop($rval); + $rval="ES".$rval; + if ( -e "/etc/redhat-release" ) { + if (!system("grep -qi centos /etc/redhat-release")) { + $rval = `cat /etc/redhat-release | cut -d' ' -f4`; + $rval =~ m/(\d+).(\d+)/; + if ($2 eq "0") { + $rval="ES".$1; + } else { + $rval="ES".$1.$2; + } + } + } + } elsif ($vendor eq "apple") { + $rval=`sw_vers -productVersion|cut -f1-2 -d.`; + chop($rval); + } elsif ($vendor eq "rocks") { + $rval=`cat /etc/rocks-release | cut -d' ' -f3`; + chop($rval); + } elsif ($vendor eq "scyld") { + $rval=`cat /etc/scyld-release | cut -d' ' -f4`; + chop($rval); + } elsif ($vendor eq "mandrake") { + $rval=`cat /etc/mandrake-release | cut -d' ' -f4`; + chop($rval); + } elsif ($vendor eq "fedora") { + $rval=`cat /etc/fedora-release | cut -d' ' -f4`; + chop($rval); + } elsif ($vendor eq "redhat") { + if (!system("grep -qi advanced /etc/redhat-release")) { + $rval=`cat /etc/redhat-release | cut -d' ' -f7`; + chop($rval); + } elsif (!system("grep -qi centos /etc/redhat-release")) { + # Find a number of the form "#.#" and output the portion + # to the left of the decimal point. + $rval = `cat /etc/redhat-release`; + $rval =~ m/(\d+).(\d+)/; + $rval="ES".$1.$2; + } elsif (!system("grep -qi Scientific /etc/redhat-release")) { + # Find a number of the form "#.#" and output the portion + # to the left of the decimal point. + $rval = `cat /etc/redhat-release`; + $rval =~ m/(\d+).(\d+)/; + $rval="ES".$1; + } elsif (!system("grep -qi enterprise /etc/redhat-release")) { + # Red Hat Enterprise Linux Server release $a.$b (name) + #PR 110926 + $rval=`cat /etc/redhat-release | cut -d' ' -f7 | cut -d'.' -f1`; + $mn=`cat /etc/redhat-release | cut -d' ' -f7 | cut -d'.' -f2`; + chop($rval); + if ( (($rval >= 7) && ($mn > 0)) || + (($rval == 6) && ($mn >= 7)) ) { + chomp($mn); + $rval=join "","ES","$rval","$mn"; + } else { + $rval="ES".$rval; + } + } else { + $rval=`cat /etc/redhat-release | cut -d' ' -f5`; + chop($rval); + } + } elsif ($vendor eq "UnitedLinux") { + $rval=`grep United /etc/UnitedLinux-release | cut -d' ' -f2`; + chop($rval); + } elsif ($vendor eq "SuSE") { + if (!system("grep -qi enterprise /etc/SuSE-release")) { + $rval=`grep -i enterprise /etc/SuSE-release | cut -d' ' -f5`; + chop($rval); + $rval="ES".$rval; + } else { + $rval=`grep SuSE /etc/SuSE-release | cut -d' ' -f3`; + chop($rval); + } + } elsif ($vendor eq "turbolinux") { + $rval=`cat /etc/turbolinux-release | cut -d' ' -f3`; + chop($rval); + } + return $rval; +} + +# Get OS distribution, vendor and vendor version +# set CUR_DISTRO_VENDOR, CUR_VENDOR_VER, CUR_VENDOR_MAJOR_VER +sub determine_os_version() +{ + # we use the current system to select the distribution + # TBD we expect client image for diskless client install to have these files + my $os_release_file = "/etc/os-release"; + if ( -e "/etc/redhat-release" && !(-l "/etc/redhat-release") ) { + $CUR_DISTRO_VENDOR = "redhat"; + } elsif ( -s "/etc/centos-release" ) { + $CUR_DISTRO_VENDOR = "redhat"; + } elsif ( -s "/etc/UnitedLinux-release" ) { + $CUR_DISTRO_VENDOR = "UnitedLinux"; + $NETWORK_CONF_DIR = "/etc/sysconfig/network"; + } elsif ( -s "/etc/SuSE-release" ) { + $CUR_DISTRO_VENDOR = "SuSE"; + $NETWORK_CONF_DIR = "/etc/sysconfig/network"; + } elsif ( -e "/usr/bin/lsb_release" ) { + $CUR_DISTRO_VENDOR = `/usr/bin/lsb_release -is`; + chop($CUR_DISTRO_VENDOR); + $CUR_DISTRO_VENDOR = lc($CUR_DISTRO_VENDOR); + if ($CUR_DISTRO_VENDOR eq "suse") { + $CUR_DISTRO_VENDOR = "SuSE"; + } + } elsif ( -e $os_release_file) { + my %distroVendor = ( + "rhel" => "redhat", + "centos" => "redhat", + "sles" => "SuSE" + ); + my %network_conf_dir = ( + "rhel" => $NETWORK_CONF_DIR, + "centos" => $NETWORK_CONF_DIR, + "sles" => "/etc/sysconfig/network" + ); + my $os_id = `cat $os_release_file | grep '^ID=' | cut -d'=' -f2 | tr -d [\\"\\.0] | tr -d ["\n"]`; + $CUR_DISTRO_VENDOR = $distroVendor{$os_id}; + $NETWORK_CONF_DIR = $network_conf_dir{$os_id}; + } else { + # autodetermine the distribution + open DISTRO_VENDOR, "ls /etc/*-release|grep -v lsb\|^os 2>/dev/null |" + || die "Unable to open pipe\n"; + $CUR_DISTRO_VENDOR=""; + while () { + chop; + if (!(-l $_)) { + my $CDV = fileparse($_, '-release'); + if ( "$CDV" ne "rocks" ) { + $CUR_DISTRO_VENDOR = $CDV; + } + } + } + close DISTRO_VENDOR; + if ( $CUR_DISTRO_VENDOR eq "" ) + { + NormalPrint "Unable to determine current Linux distribution.\n"; + Abort "Please contact your support representative...\n"; + } elsif ($CUR_DISTRO_VENDOR eq "SuSE") { + $NETWORK_CONF_DIR = "/etc/sysconfig/network"; + } elsif ($CUR_DISTRO_VENDOR eq "centos") { + $CUR_DISTRO_VENDOR = "redhat"; + } + } + $CUR_VENDOR_VER = os_vendor_version($CUR_DISTRO_VENDOR); + $CUR_VENDOR_MAJOR_VER = $CUR_VENDOR_VER; + $CUR_VENDOR_MAJOR_VER =~ s/\..*//; # remove any . version suffix +} + +# verify distrib of this system matches files indicating supported +# arch, distro, distro_version +sub verify_distrib_files +{ + my $supported_arch=`cat ./arch 2>/dev/null`; + chomp($supported_arch); + my $supported_distro_vendor=`cat ./distro 2>/dev/null`; + chomp($supported_distro_vendor); + my $supported_distro_vendor_ver=`cat ./distro_version 2>/dev/null`; + chomp($supported_distro_vendor_ver); + + if ( "$supported_arch" eq "" || $supported_distro_vendor eq "" + || $supported_distro_vendor_ver eq "") { + NormalPrint "Unable to proceed: installation image corrupted or install not run as ./INSTALL\n"; + NormalPrint "INSTALL must be run from within untar'ed install image directory\n"; + Abort "Please contact your support representative...\n"; + } + + my $archname; + my $supported_archname; + if ( "$supported_arch" ne "$ARCH" + || "$supported_distro_vendor" ne "$CUR_DISTRO_VENDOR" + || ("$supported_distro_vendor_ver" ne "$CUR_VENDOR_VER" + && "$supported_distro_vendor_ver" ne "$CUR_VENDOR_MAJOR_VER")) + { + #LogPrint "Unable to proceed, $CUR_DISTRO_VENDOR $CUR_VENDOR_VER not supported by $INT_VERSION media\n"; + + $archname=$ARCH; + if ( $ARCH eq "IA32") { + $archname="the Pentium Family"; + } + if ( $ARCH eq "IA64" ) { + $archname="the Itanium family"; + } + if ( $ARCH eq "X86_64" ) { + $archname="the EM64T or Opteron"; + } + if ( $ARCH eq "PPC64" ) { + $archname="the PowerPC 64 bit"; + } + if ( $ARCH eq "PPC" ) { + $archname="the PowerPC"; + } + + NormalPrint "$CUR_DISTRO_VENDOR $CUR_VENDOR_VER for $archname is not supported by this installation\n"; + NormalPrint "This installation supports the following Linux Distributions:\n"; + $supported_archname=$ARCH; + if ( $supported_arch eq "IA32") { + $supported_archname="the Pentium Family"; + } + if ( $supported_arch eq "IA64" ) { + $supported_archname="the Itanium family"; + } + if ( $supported_arch eq "X86_64" ) { + $supported_archname="the EM64T or Opteron"; + } + if ( $supported_arch eq "PPC64" ) { + $supported_archname="the PowerPC 64 bit"; + } + if ( $supported_arch eq "PPC" ) { + $supported_archname="the PowerPC"; + } + NormalPrint "For $supported_archname: $supported_distro_vendor.$supported_distro_vendor_ver\n"; + if ( $Force_Install ) { + NormalPrint "Installation Forced, will proceed with risk of undefined results\n"; + HitKeyCont; + } else { + Abort "Please contact your support representative...\n"; + } + } +} + +# set the env vars to their default value, when the first we install opa-scripts, we will have proper configs +sub default_opascripts_env_vars() +{ + setup_env("OPA_UDEV_RULES", 1); + setup_env("OPA_LIMITS_CONF", 1); + setup_env("OPA_ARPTABLE_TUNING", 1); + setup_env("OPA_SRP_LOAD", 0); + setup_env("OPA_SRPT_LOAD", 0); + setup_env("OPA_IRQBALANCE", 1); +} + +# this will be replaced in component specific INSTALL with any special +# overrides of things in main*pl +sub overrides() +{ +} diff --git a/CommonInstall/util_linuxconfig.pl b/CommonInstall/util_linuxconfig.pl new file mode 100755 index 0000000..e80ff0f --- /dev/null +++ b/CommonInstall/util_linuxconfig.pl @@ -0,0 +1,222 @@ +#!/usr/bin/perl +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] +use strict; +#use Term::ANSIColor; +#use Term::ANSIColor qw(:constants); +#use File::Basename; +#use Math::BigInt; + +# ============================================================================= +# The functions and constants below assist in editing modules.conf or +# modprobe.conf to add IB specific entries + +my $MODULE_CONF_FILE = "/etc/modules.conf"; +my $MODULE_CONF_DIST_FILE; +my $DRACUT_EXE_FILE = "/usr/bin/dracut"; +if (substr($CUR_OS_VER,0,3) eq "2.6") +{ + $MODULE_CONF_FILE = "/etc/modprobe.conf"; + $MODULE_CONF_DIST_FILE = "/etc/modprobe.conf.dist"; + $DRACUT_EXE_FILE = "/sbin/dracut"; +} +if (-f "$(MODULE_CONF_FILE).local") +{ + $MODULE_CONF_FILE = "$(MODULE_CONF_FILE).local"; +} +my $OPA_CONF="modules.conf"; ## additions to modules.conf + +# marker strings used in MODULES_CONF_FILE +# for entries added by installation +my $START_DRIVER_MARKER="OPA Drivers Start here"; +my $END_DRIVER_MARKER="OPA Drivers End here"; + +# Keep track of whether we already did edits to avoid repeated edits +my $DidConfig=0; + +# This code is from OFED, it removes lines related to IB from +# modprobe.conf. Used to prevent distro specific effects on OFED. +sub disable_distro_ofed() +{ + if ( "$MODULE_CONF_DIST_FILE" ne "" && -f "$MODULE_CONF_DIST_FILE" ) { + my $res; + + $res = open(MDIST, "$MODULE_CONF_DIST_FILE"); + if ( ! $res ) { + NormalPrint("Can't open $MODULE_CONF_DIST_FILE for input: $!"); + return; + } + my @mdist_lines; + while () { + push @mdist_lines, $_; + } + close(MDIST); + + $res = open(MDIST, ">$MODULE_CONF_DIST_FILE"); + if ( ! $res ) { + NormalPrint("Can't open $MODULE_CONF_DIST_FILE for output: $!"); + return; + } + foreach my $line (@mdist_lines) { + chomp $line; + if ($line =~ /^\s*install ib_core|^\s*alias ib|^\s*alias net-pf-26 ib_sdp/) { + print MDIST "# $line\n"; + } else { + print MDIST "$line\n"; + } + } + close(MDIST); + } +} + +# ============================================================================= +# The functions and constants below assist in editing limits.conf +# to add IB specific entries related to memory locking + +my $LIMITS_CONF_FILE = "/etc/security/limits.conf"; +my $LIMITS_CONF="limits.conf"; ## additions to limits.conf + +# marker strings used in LIMITS_CONF_FILE +# for entries added by installation +my $START_LIMITS_MARKER="OPA Settings Start here"; +my $END_LIMITS_MARKER="OPA Settings End here"; + +# Keep track of whether we already did edits to avoid repeated edits +my $DidLimits=0; + +# Path to opasystemconfig +my $OPA_SYSTEMCFG_FILE = "/sbin/opasystemconfig"; + +# remove iba entries from modules.conf +sub remove_limits_conf() +{ + $DidLimits = 0; + if ( -e "$LIMITS_CONF_FILE") { + if (check_keep_config($LIMITS_CONF_FILE, "", "y")) + { + print "Keeping /$LIMITS_CONF_FILE changes ...\n"; + } else { + print "Modifying $LIMITS_CONF_FILE ...\n"; + if ( -e "$OPA_SYSTEMCFG_FILE" ) { + system("$OPA_SYSTEMCFG_FILE --disable Memory_Limit"); + } + } + } +} + +# +# Override the system's standard udev configuration to allow +# different access rights to some of the infiniband device files. +# +my $UDEV_RULES_DIR ="/etc/udev/rules.d"; +my $UDEV_RULES_FILE = "05-opa.rules"; +my $Default_UserQueries = 0; + +my $udev_perm_string = "Allow non-root users to access the UMAD interface?"; + +AddAnswerHelp("UserQueries", "$udev_perm_string"); + +sub install_udev_permissions($) +{ + my ($srcdir) = shift(); # source directory. + my $SourceFile; + my $Context; + my $Cnt; + + if ($Default_UserQueries == 0) { + $Default_UserQueries = GetYesNoWithMemory("UserQueries",0,"$udev_perm_string", "y"); + } + + if ($Default_UserQueries > 0) { + # Installation of udev will be taken care during RPM installation, we just have to set + setup_env("OPA_UDEV_RULES", 1); + } elsif ( -e "$UDEV_RULES_DIR/$UDEV_RULES_FILE" ) { + #update environment variable accordingly + setup_env("OPA_UDEV_RULES", 0); + } else { + # do nothing + setup_env("OPA_UDEV_RULES", -1); + } +} + +sub remove_udev_permissions() +{ + remove_file("$UDEV_RULES_DIR/$UDEV_RULES_FILE"); +} + +# +# Ensures OPA drivers are incorporated in the initial ram disk. +# +my $CallDracut = 0; + +sub rebuild_ramdisk() +{ + # Just increase the count. We will do the rebuild at the end of the script. + $CallDracut++; +} + +sub do_rebuild_ramdisk() +{ + if ($CallDracut && -d '/boot') { + my $cmd = $DRACUT_EXE_FILE . ' --stdlog 0'; + if ( -d '/dev') { + $cmd = $DRACUT_EXE_FILE; + } + #name of initramfs may vary between distros, so need to get it from lsinitrd + my $current_initrd = `lsinitrd 2>&1 | head -n 1`; + my ($initrd_prefix) = $current_initrd =~ m/\/boot\/(\w+)-[\w\-\.]+.*/; + my $initrd_suffix = ""; + if ($current_initrd =~ m/\.img[':]/) { + $initrd_suffix = ".img"; + } + my $tmpfile = "/tmp/$initrd_prefix-$CUR_OS_VER$initrd_suffix"; + + if ( -e $cmd ) { + do { + NormalPrint("Rebuilding boot image with \"$cmd -f $tmpfile $CUR_OS_VER\"...\n"); + # Try to build a temporary image first as a dry-run to make sure + # a failed run will not destroy an existing image. + if (system("$cmd -f $tmpfile $CUR_OS_VER") == 0 && system("mv -f $tmpfile /boot/") == 0) { + NormalPrint("New initramfs installed in /boot.\n"); + NormalPrint("done.\n"); + return; + } else { + NormalPrint("failed.\n"); + } + } while(GetYesNo("Do you want to retry?", "n")); + $exit_code = 1; + } else { + NormalPrint("$cmd not found, cannot update initial ram disk."); + $exit_code = 1; + } + } +} + diff --git a/CommonInstall/util_rpm.pl b/CommonInstall/util_rpm.pl new file mode 100755 index 0000000..9851bd4 --- /dev/null +++ b/CommonInstall/util_rpm.pl @@ -0,0 +1,1023 @@ +#!/usr/bin/perl +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] +use strict; +#use Term::ANSIColor; +#use Term::ANSIColor qw(:constants); +#use File::Basename; +#use Math::BigInt; + +# ============================================================================= +# The functions and constants below assist in using RPM files + +# on platforms without 32 bit app on 64 bit OS support, these are '' +# _glob is a glob pattern version which can be used to match rpm names +# when building rpms the simple _cpu32 values should be used +my $suffix_64bit = ""; # suffix for rpm name for 64 bit rpms + +my $rpm_check_dependencies = 1; # can be set to 0 to disable rpm_check_os_prereqs + +sub rpm_query_param($); +# TBD or +# my $RPM_ARCH = rpm_query_param('_target_cpu'); +# chomp $RPM_ARCH; +my $RPM_ARCH=my_tolower("$ARCH"); +if ( "$RPM_ARCH" eq "ia32" ) { + $RPM_ARCH = rpm_query_param('_target_cpu'); + #$RPM_ARCH=`uname -m`; # or i386 + chomp $RPM_ARCH; +} +my $RPM_KERNEL_ARCH = `uname -m`; # typically matches $RPM_ARCH +chomp $RPM_KERNEL_ARCH; + +# return array of cmds for verification during init +sub rpm_get_cmds_for_verification() +{ + return ("/bin/rpm"); # Command paths +} + +# version string for kernel used in RPM filenames uses _ instead of - +sub rpm_tr_os_version($) +{ + my $osver = shift(); # uname -r style output + $osver =~ s/-/_/g; + return "$osver"; +} + +# query a parameter of RPM tools themselves +sub rpm_query_param($) +{ + my $param = shift(); # parameter name: such as _mandir, _sysconfdir, _target_cpu + my $ret = `$RPM --eval "%{$param}"`; + chomp $ret; + return $ret; +} + +# query an attribute of the RPM file +sub rpm_query_attr($$) +{ + my $rpmfile = shift(); # .rpm file + my $attr = shift(); # attribute name: such as NAME or VERSION + + if ( ! -f "$rpmfile" ) { + return ""; + } + return `$RPM --queryformat "[%{$attr}]" -qp $rpmfile 2>/dev/null`; +} + +# query an attribute of the installed RPM package +sub rpm_query_attr_pkg($$) +{ + my $package = shift(); # installed package + my $attr = shift(); # attribute name: such as NAME or VERSION + + return `$RPM --queryformat "[%{$attr}]" -q $package 2>/dev/null`; +} + +# determine if rpm parameters will allow srpms to build debuginfo rpms +sub rpm_will_build_debuginfo() +{ + # If debug_package is set to nil in .rpmmacros, srpms will not generate + # -debuginfo rpms, so they will not be available to install + return (rpm_query_param('debug_package') ne ""); +} + +# get NAME of RPM file +sub rpm_query_name($) +{ + my $rpmfile = shift(); # .rpm file + + return rpm_query_attr($rpmfile, "NAME"); +} + +sub rpm_query_version_release($) +{ + my $rpmfile = shift(); # .rpm file + + my $ver = rpm_query_attr($rpmfile, "VERSION"); + my $rel = rpm_query_attr($rpmfile, "RELEASE"); + return "${ver}-${rel}"; +} + +# get VERSION-RELEASE of installed RPM package +sub rpm_query_version_release_pkg($) +{ + my $package = shift(); # installed package + + my $ver = rpm_query_attr_pkg($package, "VERSION"); + my $rel = rpm_query_attr_pkg($package, "RELEASE"); + return "${ver}-${rel}"; +} + +# return NAME-VERSION-RELEASE.ARCH +sub rpm_query_full_name($) +{ + my $rpmfile = shift(); # .rpm file + + if ( ! -f "$rpmfile" ) { + return ""; + } + return `$RPM --queryformat '[%{NAME}-%{VERSION}-%{RELEASE}.%{ARCH}]' -qp $rpmfile 2>/dev/null`; +} + +# beware, this could return more than 1 name +#sub rpm_query_full_name_pkg($) +#{ +# my $package = shift(); # installed package +# return `$RPM --queryformat '[%{NAME}-%{VERSION}-%{RELEASE}.%{ARCH}]' -q $package 2>/dev/null`; +#} + +sub rpm_get_cpu_arch($) +{ + my $mode = shift(); # "user" or kernel rev or "firmware" + # "any"- checks if any variation of package is installed + + if ("$mode" eq "user" || "$mode" eq "any" || "$mode" eq "firmware") { + return $RPM_ARCH; + } else { + return $RPM_KERNEL_ARCH; + } +} + +my $last_checked; # last checked for in rpm_is_installed +sub rpm_is_installed($$) +{ + my $package = shift(); # package name + my $mode = shift(); # "user" or kernel rev or "firmware" + # "any"- checks if any variation of package is installed + my $rc; + my $cpu; + + if ($user_space_only && "$mode" ne "user" && "$mode" ne "any") { + return 1; + } + + $cpu = rpm_get_cpu_arch($mode); + if ("$mode" eq "any" ) { + # any variation is ok + DebugPrint("$RPM -q $package > /dev/null 2>&1\n"); + $rc = system("$RPM -q $package > /dev/null 2>&1"); + $last_checked = "any variation"; + } elsif ("$mode" eq "user" || "$mode" eq "firmware" || $package eq "hfi2") { + # the above check on hfi2 is a temporary work around because the current hfi2 kernel rpm has no kernel version + # number in file name (see STL-14187). After we resolve the issue, we shall remove the above check on hfi2 + # verify $cpu version or noarch is installed + DebugPrint "$RPM --queryformat '[%{ARCH}\\n]' -q $package 2>/dev/null|egrep '^$cpu\$|^noarch\$' >/dev/null 2>&1\n"; + $rc = system "$RPM --queryformat '[%{ARCH}\\n]' -q $package 2>/dev/null|egrep '^$cpu\$|^noarch\$' >/dev/null 2>&1"; + $last_checked = "for $mode $cpu or noarch"; + } else { + # $mode is kernel rev, verify proper kernel version is installed + # for kernel packages, RELEASE is kernel rev + my $release = rpm_tr_os_version($mode); + DebugPrint "$RPM --queryformat '[%{VERSION}\\n]' -q $package 2>/dev/null|egrep '$release' >/dev/null 2>&1\n"; + $rc = system " $RPM --queryformat '[%{VERSION}\\n]' -q $package 2>/dev/null|egrep '$release' >/dev/null 2>&1"; + $last_checked = "for kernel $release"; + } + DebugPrint("Checked if $package $mode is installed: ".(($rc==0)?"yes":"no")."\n"); + return 0 == $rc; +} + +sub rpm_is_installed_list($@) +{ + my $mode = shift(); # "user" or kernel rev or "firmware" + # "any"- verifies any variation of package is installed + my @package_list = @_; # package names + + foreach my $package ( @package_list ) + { + if ( ! rpm_is_installed($package, $mode) ) { + return 0; + } + } + return 1; +} + +# return 0 on success, number of errors otherwise +sub rpm_check_os_prereqs_internal($$@) +{ + my $mode = shift(); # default mode + my $message = shift(); + my @package_list = @_; # package names + my $err=0; + + if ( ! $rpm_check_dependencies ) { + return 0; + } + # Check installation requirements + DebugPrint "Checking prereqs $message: @package_list\n"; + for my $package_info ( @package_list ) + { + # expand any alias in package_info + my $full_package_info=""; + my @alternatives = (split ('\|',$package_info)); + for my $altpackage_info ( @alternatives ) + { + my ($package, $details) = (split (' ',$altpackage_info,2)); + if ($details ne "") { + $details=" $details"; + } + if ( "$full_package_info" ne "" ) { + $full_package_info = "$full_package_info|"; + } + + # expand "g77" alias for various fortran compilers + # and "libgfortran" alias for various fortran library + if ("$package" eq "g77" ) { + # on RHEL4u5-6: gcc4-gfortran, gcc-g77 + # on RHEL5.1: gcc-gfortran, compat-gcc-34-g77 + # on RHEL5.2: gcc-gfortran + # on RHEL5.3: gcc43-gfortran + # on sles10sp1-2: gcc-fortran + # on sles11: gcc-fortran + $full_package_info = "${full_package_info}gcc4-gfortran$details|gcc-g77$details|gcc-gfortran$details|compat-gcc-34-g77$details|gcc43-gfortran$details|gcc42-gfortran$details|gcc-fortran$details|gcc42-fortran$details|gcc43-fortran$details" + + } elsif ("$package" eq "libgfortran") { + # on RHEL4u5-6: libgfortran + # on RHEL5.1: libgfortran + # on RHEL5.2: libgfortran + # on RHEL5.3: libgfortran43 + # on sles10sp1-2: libgfortran + # on sles11sp0-1: libgfortran43 + # on sles11sp2: libgfortran46 + # TBD - openSUSE11.2 has libgfortran44 + # sles12sp0: libgfortran3-4 + $full_package_info = "${full_package_info}libgfortran$details|libgfortran42$details|libgfortran43$details|libgfortran46$details|compat-gcc-34-g77$details|libgfortran3$details"; + } else { + $full_package_info = "${full_package_info}$altpackage_info"; + } + } + + # now process the expanded list of alternatives + DebugPrint "Checking prereq: $full_package_info\n"; + my $errmessage=""; + @alternatives = (split ('\|',$full_package_info)); + for my $altpackage_info ( @alternatives ) + { + DebugPrint "Checking prereq: $altpackage_info\n"; + my ($package, $version, $pkgmode) = (split (' ',$altpackage_info)); + if ("$pkgmode" eq "") { + $pkgmode = $mode; + } + + # keep things simple for callers, handle distro specific namings + + # distro specific naming of libstdc++ + if ("$package" eq "libstdc++" && "$CUR_DISTRO_VENDOR" eq 'SuSE' + && "$CUR_VENDOR_VER" eq 'ES11') { + # hack because CUR_VENDOR_VER doesn't actually contain the minor + # version any more... + my $CUR_VENDOR_MINOR_VER = `grep PATCHLEVEL /etc/SuSE-release | cut -d' ' -f 3`; + chop($CUR_VENDOR_MINOR_VER); + if ($CUR_VENDOR_MINOR_VER eq '0' || $CUR_VENDOR_MINOR_VER eq '1') { $package="libstdc++43"; } + if ($CUR_VENDOR_MINOR_VER eq '2' ) { $package="libstdc++46"; } + if ($CUR_VENDOR_MINOR_VER eq '3' ) { $package="libstdc++6"; } + # SLES11 SP3 has renamed libstdc++47 as libstdc++6 + # TBD - openSUSE has libstdc++42 + # TBD - openSUSE11.2 has libstdc++44 + } elsif ("$package" eq "libstdc++" && "$CUR_DISTRO_VENDOR" eq 'SuSE' + && ("$CUR_VENDOR_VER" eq 'ES12' || "$CUR_VENDOR_VER" eq 'ES121' || "$CUR_VENDOR_VER" eq 'ES122')) { + $package="libstdc++6"; + } elsif ("$package" eq "libstdc++-devel" && "$CUR_DISTRO_VENDOR" eq 'SuSE' + && "$CUR_VENDOR_VER" eq 'ES11') { + # hack because CUR_VENDOR_VER doesn't actually contain the minor + # version any more... + my $CUR_VENDOR_MINOR_VER = `grep PATCHLEVEL /etc/SuSE-release | cut -d' ' -f 3`; + chop($CUR_VENDOR_MINOR_VER); + if ($CUR_VENDOR_MINOR_VER eq '0' || $CUR_VENDOR_MINOR_VER eq '1') { $package="libstdc++43-devel"; } + if ($CUR_VENDOR_MINOR_VER eq '2' ) { $package="libstdc++46-devel"; } + if ($CUR_VENDOR_MINOR_VER eq '3') { $package="libstdc++47-devel"; } + # TBD - openSUSE has libstdc++42-devel + # TBD - openSUSE11.2 has libstdc++44-devel + } + + # distro specific naming of sysfsutils + if ("$package" eq "sysfsutils" ) { + if ("$CUR_DISTRO_VENDOR" ne 'SuSE' && "$CUR_DISTRO_VENDOR" ne 'redhat' + && "$CUR_DISTRO_VENDOR" ne 'fedora' && "$CUR_DISTRO_VENDOR" ne 'rocks') { + $package="libsysfs"; + } + } + + # distro specific naming of sysfsutils-devel + # RHEL4 used sysfsutils-devel + # SuSE uses sysfsutils + # others use libsysfs-devel + if ("$package" eq "sysfsutils-devel" ) { + if (($CUR_DISTRO_VENDOR eq "SuSE") + or ($CUR_DISTRO_VENDOR eq "redhat" and $CUR_VENDOR_VER eq "ES5") + ) { + $package = "sysfsutils"; + } elsif (($CUR_DISTRO_VENDOR eq "rocks") or + ($CUR_DISTRO_VENDOR eq "fedora") or + ($CUR_DISTRO_VENDOR eq "redhat")) { + $package = "sysfsutils-devel"; + } else { + $package = "libsysfs-devel"; + } + + } + + if ("$pkgmode" eq "user") { + # SLES10 and 11 -64bit rpms report ppc as ARCH + $package="$package$suffix_64bit"; + if ( "$suffix_64bit" ne "" ) { + $pkgmode="any"; + } + } + if (! rpm_is_installed($package, $pkgmode)) { + if ( $errmessage ne "") { + $errmessage="$errmessage\n OR "; + } + $errmessage = "$errmessage$package ($last_checked)"; + #} elsif ("$version" ne "" && "$version" ne "any") { + # # TBD - could be multiple versions of package installed + # # in which case this returns merged strings, not good + # my $ver = rpm_query_attr_pkg($package, "VERSION"); + # TBD - string compare not the same as proper numeric compare + # if ($ver lt $version) { + # if ( $errmessage ne "") { + # $errmessage="$errmessage\n OR "; + # } + # $errmessage = "$errmessage$package version $version ($last_checked)"; + # } + } else { + $errmessage=""; + last; + } + } + if ( $errmessage ne "" ) { + if (scalar(@alternatives) > 1) { + $errmessage="$errmessage\n"; + } + NormalPrint("$errmessage is required$message\n"); + $err++; + } + } + return $err; +} + +sub rpm_check_os_prereqs($$) +{ + no strict 'refs'; + my $comp = shift(); + my $mode = shift(); + my $list_name; + my $array_ref; + my @rpm_list = {}; + my $prereq_check = 0; + + if ( ! $rpm_check_dependencies ) { + return 0; + } + + $list_name=$comp."_prereq"; + $array_ref = $comp_prereq_hash{$list_name}; + #checking if prereq array exists + #it assumed that it has no prereqs it array does not exist + if ( $array_ref ) { + @rpm_list = @{ $array_ref }; + } + else{ + return 0; + } + + #checking whether each entry in rpm_list is installed + DebugPrint "Checking prereqs for $comp\n"; + foreach (@rpm_list){ + DebugPrint "Checking installation of $_\n"; + #Don't check dependencies for kernel RPMS if their installation is skipped + if($user_space_only == 1){ + if( "$_" =~ /kernel/ || "$_" =~ /kmod/ || "$_" eq "pciutils" ) { + DebugPrint("Skipping check for $_ \n"); + next; + } + } + if(!rpm_is_installed($_, $mode)){ + NormalPrint("--> $comp requires $_ \n"); + $prereq_check = 1; + } + } + + return $prereq_check; +} + + +sub rpm_check_build_os_prereqs($$@) +{ + my $mode = shift(); + my $build_info = shift(); + my @package_list = @_; # package names + return rpm_check_os_prereqs_internal($mode, " to build $build_info", @package_list); +} + +# get list of package rpms installed +# the list could include multiple versions and/or multiple architectures +# and/or multiple kernel releases +# all entries in returned list are complete package names in the form: +# NAME-VERSION-RELEASE.ARCH +sub rpms_installed_pkg($$) +{ + my $package=shift(); + my $mode = shift(); # "user" or kernel rev or "firmware" + # "any"- checks if any variation of package is installed + + my @lines=(); + my $cpu; + + $cpu = rpm_get_cpu_arch($mode); + if ( "$mode" eq "any" ) { + DebugPrint("$RPM --queryformat '[%{NAME}-%{VERSION}-%{RELEASE}.%{ARCH}\n]' -q $package 2>/dev/null\n"); + open(rpms, "$RPM --queryformat '[%{NAME}-%{VERSION}-%{RELEASE}.%{ARCH}\n]' -q $package 2>/dev/null|"); + } elsif ("$mode" eq "user" || "$mode" eq "firmware") { + DebugPrint("$RPM --queryformat '[%{NAME}-%{VERSION}-%{RELEASE}.%{ARCH}\n]' -q $package 2>/dev/null|egrep '\.$cpu\$|\.noarch\$' 2>/dev/null\n"); + open(rpms, "$RPM --queryformat '[%{NAME}-%{VERSION}-%{RELEASE}.%{ARCH}\n]' -q $package 2>/dev/null|egrep '\.$cpu\$|\.noarch\$' 2>/dev/null|"); + } else { + # $mode is kernel rev, verify proper kernel version is installed + # for kernel packages, RELEASE is kernel rev + my $release = rpm_tr_os_version($mode); + DebugPrint("$RPM --queryformat '[%{NAME}-%{VERSION}-%{RELEASE}.%{ARCH}\n]' -q $package 2>/dev/null|egrep '-$release\.$cpu\$' 2>/dev/null\n"); + open(rpms, "$RPM --queryformat '[%{NAME}-%{VERSION}-%{RELEASE}.%{ARCH}\n]' -q $package 2>/dev/null|egrep '-$release\.$cpu\$' 2>/dev/null|"); + } + @lines=; + close(rpms); + if ( $? != 0) { + # query command failed, package must not be installed + @lines=(); + } + chomp(@lines); + DebugPrint("package $package $mode: installed: @lines\n"); + return @lines; +} + +# identify all possible variations of the package +sub rpm_variations($$) +{ + my $package=shift(); + my $mode = shift(); # "user", kernel rev, "firmware" or "any" + # "any" checks if any variation of package is installed + my @variations = ( $package ); + + if ( ("$mode" eq "any" || "$mode" eq "user") && $suffix_64bit ne "") { + @variations = (@variations, "$package$suffix_64bit"); + } + return @variations; +} + +# get list of package rpms installed +# the list could include multiple versions and/or multiple architectures +# and/or multiple kernel releases +# all entries in returned list are complete package names in the form: +# NAME-VERSION-RELEASE.ARCH +sub rpms_variations_installed_pkg($$) +{ + my $package=shift(); + my $mode = shift(); + + my @result=(); + + foreach my $p ( rpm_variations($package, $mode) ) { + @result = ( @result, rpms_installed_pkg($p, $mode) ); + } + return @result; +} + +# determine if given rpm contains the given file +sub rpm_has_file($$) +{ + my $rpmfile = shift(); # .rpm file + my $file = shift(); # file to look for in rpm + + if ( ! -f "$rpmfile" ) { + return 0; + } + return (! system("$RPM -qlp $rpmfile 2>/dev/null | grep '/${file}\$' > /dev/null 2>&1")); +} + +# return names of all installed RPMs matching the given partial name and filter +sub rpm_query_all($$) +{ + my $package = shift(); + my $filter = shift(); + + my $res=` $RPM -qa 2>/dev/null|grep -i '$package'|grep '$filter'`; + $res=~s/\n/ /g; + return $res; +} + +# uninstall all packages which match package partial name and filter +# returns 0 on sucess (or package not installed), != 0 on failure +sub rpm_uninstall_matches($$$;$) +{ + my $name = shift(); # for use only in log messages + my $package = shift(); # part of package name + my $filter = shift(); # any additional grep filter + my $options = shift(); # additional rpm command options + my $rpms = rpm_query_all("$package", "$filter"); + + if ( "$rpms" ne "" ) { + LogPrint "uninstalling $name: $RPM -e $rpms\n"; + my $out =`$RPM -e $options $rpms 2>&1`; + my $rc=$?; + NormalPrint("$out"); + if ($rc != 0) { + $exit_code = 1; + } + return $rc; + } else { + return 0; + } +} + +sub rpm_run_install($$$) +{ + my $rpmfile = shift(); # .rpm file + my $mode = shift(); # "user" or kernel rev or "firmware" + # "any"- will install any variation found + my $options = shift(); # additional rpm command options + # if " -U " is part of these options, -U will be + # unconditionally used, even if the rpm is not + # already installed. Otherwise -U will only be + # used if the rpm is installed. Note that some OFED + # rpms do not properly handle -U for actual upgrades. + # Hence for OFED we tend to uninstall the old rpms first + # and the rpm -i is used to install here. + + my $Uoption= 0; + + if ($user_space_only && "$mode" ne "user" && "$mode" ne "any") { + return; + } + + # We require whitespace around -U so its not mistaken for filenames or other + # multi-letter options + if ($options =~ / -U /) { + $Uoption=1; + $options =~ s/ -U //; + } + + if ( ! -e $rpmfile ) { + NormalPrint "Not Found: $rpmfile $mode\n"; + return; + } + + my $package = rpm_query_name($rpmfile); + my $fullname = rpm_query_full_name($rpmfile); + my $out; + + NormalPrint "installing ${fullname}...\n"; + + my $upgrade=rpm_is_installed($package, $mode); + if ( ! $upgrade ) { + my @obsoletes = split /[[:space:]]+/, `$RPM --queryformat '[%{OBSOLETES}\\n]' -qp $rpmfile 2>/dev/null`; + for my $p ( @obsoletes ) { + next if ( "$p" eq "(none)" ); + $upgrade |= rpm_is_installed($p, $mode); + if ($upgrade) { + last; + } + } + } + + if( $Uoption || $upgrade ) { + # -U option will only update this exact package and architecture + # when multiple architectures are installed, other architecture rpms + # are not affected by -U, however --force is needed in that case + # also need --force for reinstall case + LogPrint " $RPM -U --force $options $rpmfile\n"; + $out=`$RPM -U --force $options $rpmfile 2>&1`; + if ( $? == 0 ) { + NormalPrint("$out"); + } else { + NormalPrint("ERROR - Failed to install $rpmfile\n"); + NormalPrint("$out"); + $exit_code = 1; + HitKeyCont; + } + + } else { + # initial install of rpm + # force not required, even if other architectures already installed + if ("$ARCH" eq 'PPC64') { + # PPC64 SLES10 needs --force + $options='--force '."$options"; + } + LogPrint " $RPM -i $options $rpmfile\n"; + $out=`$RPM -i $options $rpmfile 2>&1`; + if ( $? == 0 ) { + NormalPrint("$out"); + } else { + NormalPrint("ERROR - Failed to install $rpmfile\n"); + NormalPrint("$out"); + $exit_code = 1; + HitKeyCont; + } + } +} + +# returns 0 on sucess (or package not installed), != 0 on failure +# uninstalls all variations of given package +sub rpm_uninstall($$$$) +{ + my $package = shift(); # package name + my $mode = shift(); # "user" or kernel rev or "firmware" + # "any"- checks if any variation of package is installed + my $options = shift(); # additional rpm command options + my $verbosity = shift(); # verbose or silent + my @fullnames = rpms_variations_installed_pkg($package, $mode); # already adjusts mode + my $rc = 0; + foreach my $fullname (@fullnames) { + if ( "$verbosity" ne "silent" ) { + print "uninstalling ${fullname}...\n"; + } + LogPrint "$RPM -e $options $fullname\n"; + my $out=`$RPM -e $options $fullname 2>&1`; + $rc |= $?; + NormalPrint("$out"); + if ($rc != 0) { + $exit_code = 1; + } + } + return $rc; +} + +# resolve rpm package filename for $mode +# rpmpath is a glob style absolute or relative path to the package +# including the package name, but excluding package version, architecture and +# .rpm suffix +# TBD - can restructure this as a loop for a list of paths to check +# for each in @( "-[0-9]*.${cpu}.rpm "-r[0-9]*.${cpu}.rpm" ... ) +# Print +# file_glob("${rpmpath}${suffix}" +# if match +# exit loop +sub rpm_resolve($$) +{ + my $rpmpath = shift(); + my $mode = shift(); # "user" or kernel rev or "firmware" + # "any"- any variation found + my $rpmfile; + my $cpu; + + $cpu = rpm_get_cpu_arch($mode); + if ("$mode" eq "user" || "$mode" eq "firmware") { + # we expect 0-1 match, ignore all other filenames returned + DebugPrint("Checking for $mode Rpm: ${rpmpath}-[0-9]*.${cpu}.rpm\n"); + $rpmfile = file_glob("${rpmpath}-[0-9]*.${cpu}.rpm"); + if ( "$rpmfile" eq "" || ! -e "$rpmfile" ) { + DebugPrint("Checking for $mode Rpm: ${rpmpath}-r[0-9]*.${cpu}.rpm\n"); + $rpmfile = file_glob("${rpmpath}-r[0-9]*.${cpu}.rpm"); + } + if ( "$rpmfile" eq "" || ! -e "$rpmfile" ) { + DebugPrint("Checking for $mode Rpm: ${rpmpath}-trunk-[0-9]*.${cpu}.rpm\n"); + $rpmfile = file_glob("${rpmpath}-trunk-[0-9]*.${cpu}.rpm"); + } + if ( "$rpmfile" eq "" || ! -e "$rpmfile" ) { + # we expect 0-1 match, ignore all other filenames returned + DebugPrint("Checking for $mode Rpm: ${rpmpath}-[0-9]*.noarch.rpm\n"); + $rpmfile = file_glob("${rpmpath}-[0-9]*.noarch.rpm"); + if ( "$rpmfile" eq "" || ! -e "$rpmfile" ) { + DebugPrint("Checking for $mode Rpm: ${rpmpath}-r[0-9]*.noarch.rpm\n"); + $rpmfile = file_glob("${rpmpath}-r[0-9]*.noarch.rpm"); + } + if ( "$rpmfile" eq "" || ! -e "$rpmfile" ) { + DebugPrint("Checking for $mode Rpm: ${rpmpath}-trunk-[0-9]*.noarch.rpm\n"); + $rpmfile = file_glob("${rpmpath}-trunk-[0-9]*.noarch.rpm"); + } + } + } elsif ("$mode" eq "any" ) { + # we expect 0-1 match, ignore all other filenames returned + DebugPrint("Checking for User Rpm: ${rpmpath}-[0-9]*.*.rpm\n"); + $rpmfile = file_glob("${rpmpath}-[0-9]*.*.rpm"); + if ( "$rpmfile" eq "" || ! -e "$rpmfile" ) { + DebugPrint("Checking for User Rpm: ${rpmpath}-r[0-9]*.*.rpm\n"); + $rpmfile = file_glob("${rpmpath}-r[0-9]*.*.rpm"); + } + if ( "$rpmfile" eq "" || ! -e "$rpmfile" ) { + DebugPrint("Checking for User Rpm: ${rpmpath}-trunk-[0-9]*.*.rpm\n"); + $rpmfile = file_glob("${rpmpath}-trunk-[0-9]*.*.rpm"); + } + } else { + my $osver = rpm_tr_os_version("$mode"); # OS version + # we expect 1 match, ignore all other filenames returned + if ( "$CUR_VENDOR_VER" eq 'ES122' || "$CUR_VENDOR_VER" eq 'ES123' || "$CUR_VENDOR_VER" eq 'ES124' || "$CUR_VENDOR_VER" eq 'ES125' ||"$CUR_VENDOR_VER" eq 'ES15' || "$CUR_VENDOR_VER" eq 'ES151') { + DebugPrint("Checking for Kernel Rpm: ${rpmpath}-${osver}_k*.${cpu}.rpm\n"); + $rpmfile = file_glob("${rpmpath}-${osver}_k*.${cpu}.rpm"); + } else { + DebugPrint("Checking for Kernel Rpm: ${rpmpath}-[0-9]*.[0-9][0-9].${osver}-[0-9]*.${cpu}.rpm\n"); + $rpmfile = file_glob("${rpmpath}-[0-9]*.[0-9][0-9].${osver}-[0-9]*.${cpu}.rpm"); + } + if ( "$rpmfile" eq "" || ! -e "$rpmfile" ) { + DebugPrint("Checking for Kernel Rpm: ${rpmpath}-${osver}-[0-9]*.${cpu}.rpm\n"); + $rpmfile = file_glob("${rpmpath}-${osver}-[0-9]*.${cpu}.rpm"); + } + if ( "$rpmfile" eq "" || ! -e "$rpmfile" ) { + DebugPrint("Checking for Kernel Rpm: ${rpmpath}-trunk-[0-9]*-${osver}.${cpu}.rpm\n"); + $rpmfile = file_glob("${rpmpath}-trunk-[0-9]*-${osver}.${cpu}.rpm"); + } + # the following is a temporary work around because the current hfi2 kernel rpm has no kernel version + # number in file name (see STL-14187). After we resolve the issue, we shall remove the following 4 lines + if ( $HFI2_INSTALL && ("$rpmfile" eq "" || ! -e "$rpmfile") ) { + DebugPrint("Checking for Kernel Rpm: ${rpmpath}-[0-9]*.${cpu}.rpm\n"); + $rpmfile = file_glob("${rpmpath}-[0-9]*.${cpu}.rpm"); + } + } + VerbosePrint("Resolved $rpmpath $mode: $rpmfile\n"); + return $rpmfile; +} + +sub rpm_exists($$) +{ + my $rpmpath = shift(); + my $mode = shift(); # "user" or kernel rev or "firmware" + # "any"- any variation found + my $rpmfile; + + $rpmfile = rpm_resolve("$rpmpath", $mode); + return ("$rpmfile" ne "" && -e "$rpmfile"); +} + +sub rpm_install_with_options($$$) +{ + my $rpmpath = shift(); + my $mode = shift(); # "user" or kernel rev or "firmware" + # "any"- will install any variation found + my $options = shift(); # additional rpm command options + my $rpmfile; + + if ($user_space_only && "$mode" ne "user" && "$mode" ne "any") { + return; + } + + $rpmfile = rpm_resolve("$rpmpath", $mode); + if ( "$rpmfile" eq "" || ! -e "$rpmfile" ) { + NormalPrint "Not Found: $rpmpath $mode\n"; + } else { + if ("$mode" eq "user" || "$mode" eq "any" || "$mode" eq "firmware" ) { + rpm_run_install($rpmfile, $mode, $options); + } else { + # kernel install + if ("$CUR_DISTRO_VENDOR" eq 'SuSE' && + $options !~ / --nodeps /) { + # ofed1.3 only uses --nodeps on SuSE to workaround ksym + # dependencies. + # TBD - is this still needed? + rpm_run_install($rpmfile, $mode, "--nodeps $options"); + } else { + rpm_run_install($rpmfile, $mode, $options); + } + } + } +} + +# TBD - phase out this function (or get all callers to use same options) +sub rpm_install($$) +{ + my $rpmpath = shift(); + my $mode = shift(); # "user" or kernel rev or "firmware" + # "any"- will install any variation found + + rpm_install_with_options($rpmpath, $mode, ""); +} + +# verify the rpmfiles exist for all the RPMs listed +sub rpm_exists_list($$@) +{ + my $rpmdir = shift(); + my $mode = shift(); # "user" or kernel rev or "firmware" + # "any"- any variation found + my @package_list = @_; # package names + + foreach my $package ( @package_list ) + { + if (! rpm_exists("$rpmdir/$package", $mode) ) { + return 0; + } + } + return 1; +} + +sub rpm_install_list_with_options($$$@) +{ + my $rpmdir = shift(); + my $mode = shift(); # "user" or kernel rev or "firmware" + # "any"- will install any variation found + my $options = shift(); # additional rpm command options + my @package_list = @_; # package names + + foreach my $package ( @package_list ) + { + rpm_install_with_options("$rpmdir/$package", $mode, $options); + } +} + +# TBD - phase out this function (or get all callers to use same options) +sub rpm_install_list($$@) +{ + my $rpmdir = shift(); + my $mode = shift(); # "user" or kernel rev or "firmware" + # "any"- will install any variation found + my @package_list = @_; # package names + + rpm_install_list_with_options($rpmdir, $mode, "", @package_list); +} + +# rpmpath_list is a list of glob style absolute or relative path to the packages +# including the package name, but excluding package version, architecture and +# .rpm suffix +sub rpm_install_path_list_with_options($$@) +{ + my $mode = shift(); # "user" or kernel rev or "firmware" + # "any"- will install any variation found + my $options = shift(); # additional rpm command options + my @rpmpath_list = @_; # rpm pathnames + + foreach my $rpmpath ( @rpmpath_list ) + { + rpm_install_with_options("$rpmpath", $mode, $options); + } +} + +# rpmpath_list is a list of glob style absolute or relative path to the packages +# including the package name, but excluding package version, architecture and +# .rpm suffix +# TBD - phase out this function (or get all callers to use same options) +sub rpm_install_path_list($@) +{ + my $mode = shift(); # "user" or kernel rev or "firmware" + # "any"- will install any variation found + my @rpmpath_list = @_; # rpm pathnames + + rpm_install_path_list_with_options($mode, "", @rpmpath_list); +} + + +# returns 0 on success (or rpms not installed), != 0 on failure +sub rpm_uninstall_list2($$$@) +{ + my $mode = shift(); # "user" or kernel rev or "firmware" + # "any"- checks if any variation of package is installed + my $options = shift(); # additional rpm command options + my $verbosity = shift(); # verbose or silent + my @package_list = @_; # package names + my $package; + my $ret = 0; # assume success + + foreach $package ( reverse(@package_list) ) + { + $ret |= rpm_uninstall($package, $mode, $options, $verbosity); + } + return $ret; +} + +# returns 0 on success (or rpms not installed), != 0 on failure +sub rpm_uninstall_list($$@) +{ + my $mode = shift(); # "user" or kernel rev or "firmware" + # "any"- checks if any variation of package is installed + my $verbosity = shift(); # verbose or silent + my @package_list = @_; # package names + + return rpm_uninstall_list2($mode, "", $verbosity, (@package_list)); +} + +# uninstall all rpms which match any of the supplied package names +# and based on mode and distro/cpu, +# uninstall is done in a single command +# returns 0 on success (or rpms not installed), != 0 on failure +# Force to uninstall without any concern for dependency. +sub rpm_uninstall_all_list_with_options($$$@) +{ + my $mode = shift(); # "user" or kernel rev or "firmware" + # "any"- checks if any variation of package is installed + my $options = shift(); # additional rpm command options + my $verbosity = shift(); # verbose or silent + my @package_list = @_; # package names + my @uninstall = (); + + if ("$mode" eq "any") { + $options .= "--allmatches"; + } + foreach my $package ( @package_list ) + { + foreach my $p ( rpm_variations($package, $mode) ) + { + if (rpm_is_installed($p, $mode)) { + if ("$mode" eq "any") { + @uninstall = (@uninstall, $p); + } else { + @uninstall = (@uninstall, rpms_installed_pkg($p, $mode)); + } + } + } + } + + if (scalar(@uninstall) != 0) { + LogPrint "$RPM -e $options @uninstall\n"; + my $out=`$RPM -e $options @uninstall 2>&1`; + my $rc=$?; + NormalPrint("$out"); + if ($rc != 0) { + $exit_code = 1; + } + return $rc; + } else { + LogPrint "None Found\n"; + return 0; # nothing to do + } +} + +# uninstall all rpms which match any of the supplied package names +# and based on mode and distro/cpu. +# uninstall is done in a single command so dependency issues handled +# returns 0 on success (or rpms not installed), != 0 on failure +# TBD - phase out this function (or get all callers to use same options) +sub rpm_uninstall_all_list($$@) +{ + my $mode = shift(); # "user" or kernel rev or "firmware" + # "any"- checks if any variation of package is installed + my $verbosity = shift(); # verbose or silent + my @package_list = @_; # package names + + rpm_uninstall_all_list_with_options($mode, "", $verbosity, @package_list); +} + +# see if prereqs for building kernel modules are installed +# return 0 on success, 1 if missing dependencies +sub check_kbuild_dependencies($$) +{ + my $osver = shift(); # kernel rev + my $srpm = shift(); # what trying to build + my $dir = "/lib/modules/$osver/build"; + + if ( ! $rpm_check_dependencies ) { + return 0; + } + if ( ! -d "$dir/scripts" ) { + NormalPrint "Unable to build $srpm: $dir/scripts: not found\n"; + NormalPrint "kernel-source or kernel-devel is required to build $srpm\n"; + return 1; # failure + } + return 0; +} + +# see if basic prereqs for building RPMs are installed +# return 0 on success, or number of missing dependencies +sub check_rpmbuild_dependencies($) +{ + my $srpm = shift(); # what trying to build + my $err = 0; + + if ("$CUR_DISTRO_VENDOR" eq 'redhat') { + if (! rpm_is_installed("rpm-build", "any") ) { + NormalPrint("rpm-build ($last_checked) is required to build $srpm\n"); + $err++; + } + # RHEL 8 and later + if (substr("$CUR_VENDOR_VER", 0, 3) eq "ES8") { + if (! rpm_is_installed("kernel-rpm-macros", "any") ) { + NormalPrint("kernel-rpm-macros ($last_checked) is required to build $srpm\n"); + $err++; + } + if (! rpm_is_installed("kernel-abi-whitelists", "any") ) { + NormalPrint("kernel-abi-whitelist ($last_checked) is required to build $srpm\n"); + $err++; + } + } + } + if ( "$CUR_DISTRO_VENDOR" ne "SuSE" && rpm_will_build_debuginfo()) { + if (! rpm_is_installed("redhat-rpm-config", "any")) { + NormalPrint("redhat-rpm-config ($last_checked) is required to build $srpm\n"); + $err++; + } + } + return $err; +} + diff --git a/CommonInstall/util_startup.pl b/CommonInstall/util_startup.pl new file mode 100755 index 0000000..b8a3f06 --- /dev/null +++ b/CommonInstall/util_startup.pl @@ -0,0 +1,115 @@ +#!/usr/bin/perl +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] +use strict; +#use Term::ANSIColor; +#use Term::ANSIColor qw(:constants); +#use File::Basename; +#use Math::BigInt; + +# =========================================================================== +# startup scripts + +# on Some Os's this configures startup file dependencies, especially for +# parallel startup optimizations +my $INSSERV_CONF="/etc/insserv.conf"; +# where master copy of init scripts are installed +my $INIT_DIR = "/etc/init.d"; +my $SYSTEMCTL_EXEC = system("command -v systemctl > /dev/null 2>&1"); + +sub disable_autostart($) +{ + my($WhichStartup) = shift(); + + # disable autostart but leave any kill scripts so stopped on shutdown + # Note on SLES off removes kill scripts too, on redhat they remain + if($SYSTEMCTL_EXEC eq 0 && + ($WhichStartup eq "opafm" || $WhichStartup eq "opa" || $WhichStartup eq "ibacm")) + { + system "systemctl disable $WhichStartup >/dev/null 2>&1"; + } else { + system "/sbin/chkconfig $WhichStartup off > /dev/null 2>&1"; + } +} + +sub enable_autostart($) +{ + my($WhichStartup) = shift(); + + # cleanup to be safe + if($SYSTEMCTL_EXEC eq 0 && + ($WhichStartup eq "opafm" || $WhichStartup eq "opa" || $WhichStartup eq "ibacm")) + { + system "systemctl enable $WhichStartup >/dev/null 2>&1"; + } else { + system "/sbin/chkconfig --del $WhichStartup > /dev/null 2>&1"; + system "/sbin/chkconfig --add $WhichStartup > /dev/null 2>&1"; + # make sure its enabled now + system "/sbin/chkconfig $WhichStartup on > /dev/null 2>&1"; + } +} + +# Is given startup script currently configured to autostart +sub IsAutostart($) +{ + my($WhichStartup) = shift(); + + if($SYSTEMCTL_EXEC eq 0 && + ($WhichStartup eq "opafm" || $WhichStartup eq "opa" || $WhichStartup eq "ibacm")) + { + my($isEnabled) = `systemctl is-enabled $WhichStartup 2>/dev/null`; + chomp($isEnabled); + if($isEnabled eq "disabled" || $isEnabled eq "") + { + return 0; + } else { + return 1; + } + } else { + my $logoutput; + open(CHKCONFIG,"/sbin/chkconfig --list $WhichStartup 2> /dev/null |") || Abort "Couldn't open a pipe for chkconfig\n"; + $logoutput = ; + close(CHKCONFIG); + # remove startup name from output, this way opamon is not mistaken for "on" + $logoutput=~s/^$WhichStartup//; + if (grep /:on/, $logoutput) + { + return 1; + } elsif ( `ls /etc/rc.d/rc3.d/S*$WhichStartup 2>/dev/null` ne "" || + `ls /etc/init.d/rc3.d/S*$WhichStartup 2>/dev/null` ne "") { + # this case is an old install being updated. + # A SLES OS may have no link from init.d to rc.d. So we check init.d folder as well. + return 1; + } else { + return 0; + } + } +} diff --git a/Dsap/Makefile b/Dsap/Makefile new file mode 100644 index 0000000..64aeb2d --- /dev/null +++ b/Dsap/Makefile @@ -0,0 +1,165 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** +# Makefile for Dsap + +# Include Make Control Settings +include $(TL_DIR)/$(PROJ_FILE_DIR)/Makesettings.project + +#=============================================================================# +# Definitions: +#-----------------------------------------------------------------------------# + +# Name of SubProjects +DS_SUBPROJECTS = +# name of executable or downloadable image +EXECUTABLE = +# list of sub directories to build +DIRS = +# C files (.c) +CFILES = \ + src/dsap_prov.c \ + src/dsap.c \ + src/dsap_scan_fabric.c \ + src/dsap_query.c \ + src/dsap_notifications.c \ + src/dsap_topology.c \ + # Add more c files here +# C++ files (.cpp) +CCFILES = \ + # Add more cpp files here +# lex files (.lex) +LFILES = \ + # Add more lex files here +# archive library files (basename, $ARFILES will add MOD_LIB_DIR/prefix and suffix) +LIBFILES = +# Windows Resource Files (.rc) +RSCFILES = +# Windows IDL File (.idl) +IDLFILE = +# Windows Linker Module Definitions (.def) file for dll's +DEFFILE = +# targets to build during INCLUDES phase (add public includes here) +INCLUDE_TARGETS = +# Non-compiled files +MISC_FILES = +MISC_CONFIG_FILES = dsap.conf +# all source files +SOURCES = $(CFILES) $(CCFILES) $(LFILES) $(RSCFILES) $(IDLFILE) +# Source files to include in DSP File +DSP_SOURCES = $(INCLUDE_TARGETS) $(SOURCES) $(MISC_FILES) \ + $(RSCFILES) $(DEFFILE) $(MAKEFILE) +# all object files +OBJECTS = $(CFILES:.c=$(OBJ_SUFFIX)) $(CCFILES:.cpp=$(OBJ_SUFFIX)) \ + $(LFILES:.lex=$(OBJ_SUFFIX)) +RSCOBJECTS = $(RSCFILES:.rc=$(RES_SUFFIX)) +# targets to build during LIBS phase +LIB_TARGETS_IMPLIB = +LIB_TARGETS_ARLIB = +LIB_TARGETS_EXP = $(LIB_TARGETS_IMPLIB:$(ARLIB_SUFFIX)=$(EXP_SUFFIX)) +LIB_TARGETS_MISC = +# targets to build during CMDS phase +SHLIB_VERSION = 1.0.0 +CMD_TARGETS_SHLIB = $(LIB_PREFIX)dsap$(SHLIB_VERSION_SUFFIX) +CMD_TARGETS_EXE = $(EXECUTABLE) +CMD_TARGETS_MISC = +CMD_TARGETS_DRIVER = +# files to remove during clean phase +CLEAN_TARGETS_MISC = +CLEAN_TARGETS = $(OBJECTS) $(RSCOBJECTS) $(IDL_TARGETS) $(CLEAN_TARGETS_MISC) +# other files to remove during clobber phase +CLOBBER_TARGETS_MISC= dsap.conf +# sub-directory to install to within bin +BIN_SUBDIR = +# sub-directory to install to within include +INCLUDE_SUBDIR = + +# Additional Settings +#CLOCALDEBUG = User defined C debugging compilation flags [Empty] +#CCLOCALDEBUG = User defined C++ debugging compilation flags [Empty] +#CCLOCAL = User defined C++ flags for compiling [Empty] +#BSCLOCAL = User flags for Browse File Builder [Empty] +#DEPENDLOCAL = user defined makedepend flags [Empty] +#LINTLOCAL = User defined lint flags [Empty] +LDLOCAL = -Wl,--export-dynamic -Wl,--version-script=libdsap.map +#IMPLIBLOCAL = User flags for Object Lirary Manager [Empty] +#MIDLLOCAL = User flags for IDL compiler [Empty] +#RSCLOCAL = User flags for resource compiler [Empty] +#LOCALDEPLIBS = User libraries to include in dependencies [Empty] +#LOCALLIBS = User libraries to use when linking [Empty] +# (in addition to LOCALDEPLIBS) +#LOCAL_LIB_DIRS = User library directories for libpaths [Empty] + +COMMON_SRCDIR=. +CLOCAL=$(CIBACCESS) $(CPIC) +LOCALDEPLIBS=$(IBACCESS_USER_LIBS) opamgt-priv +LOCAL_INCLUDE_DIRS= $(COMMON_SRCDIR) +# opasadb is a shared library, don't need in LOCALDEPLIBS +LOCALLIBS=$(OPENIB_USER_LIBS) opasadb rt +LOCAL_LIB_DIRS=$(OPENIB_USER_LIB_DIRS) $(IBACCESS_USER_LIB_DIRS) + +include $(TL_DIR)/$(PROJ_FILE_DIR)/Makerules.project +#=============================================================================# +# Overrides: +#-----------------------------------------------------------------------------# +#CCOPT = # C++ optimization flags, default lets build config decide +#COPT = # C optimization flags, default lets build config decide +#SUBSYSTEM = Subsystem to build for (none, console or windows) [none] +# (Windows Only) +#USEMFC = How Windows MFC should be used (none, static, shared, no_mfc) [none] +# (Windows Only) +COPT = # set by CKERNEL for drivers +CCOPT = # set by CKERNEL for drivers +#=============================================================================# + +#=============================================================================# +# Rules: +#-----------------------------------------------------------------------------# +# process Sub-directories + +include $(TL_DIR)/Makerules/Maketargets.toplevel + +# build cmds and libs +include $(TL_DIR)/Makerules/Maketargets.build + +# install for includes, libs and cmds phases +include $(TL_DIR)/Makerules/Maketargets.install + +# install for stage phase +include $(TL_DIR)/Makerules/Maketargets.stage +STAGE:: + $(VS)$(STAGE_INSTALL) $(STAGE_INSTALL_DIR_OPT) $(PROJ_STAGE_DIR)/config $(MISC_CONFIG_FILES) $(MISC_FILES) + +# Unit test execution +#include $(TL_DIR)/Makerules/Maketargets.runtest + +#=============================================================================# + +#=============================================================================# +# DO NOT DELETE THIS LINE -- make depend depends on it. +#=============================================================================# diff --git a/Dsap/README b/Dsap/README new file mode 100644 index 0000000..61024a8 --- /dev/null +++ b/Dsap/README @@ -0,0 +1,2 @@ +Distributed SA provider for ibacm, which provides name resolution through data +file and path record resolution by caching SA data. diff --git a/Dsap/dsap.conf b/Dsap/dsap.conf new file mode 100644 index 0000000..81c2b6e --- /dev/null +++ b/Dsap/dsap.conf @@ -0,0 +1,95 @@ +# [ICS VERSION STRING: unknown] + +# Usage: +# +# NoSubscribe (Boolean): +# Do not subscribe to SM for notifications. +# Valid: true or false (default). +# ScanFrequency (Unsigned): +# Number of seconds between unconditional sweeps. +# Range: 1 - 0xFFFFFFFF; Default: 600. +# UnsubscribedScanFrequency (Unsigned): +# Number of seconds between sweeps when not receiving notifications. +# Range: 1 - 0xFFFFFFFF; Default: 10. +# Dbg (Hex): +# Debug logging controls. Uses syslog log levels, ranging from 1 (system panic) +# to 7 (trace level). Generally, only levels 4-6 are useful to normal users. +# See the man page for vsyslog for more information. Default: 5. +# Publish (Boolean): +# Publish paths to shared memory. Valid: true (default) or false. +# SID (Special): +# Service ID that identifies a virtual fabric to include in the cache. +# Can be specified multiple times. +# Range: 1 - 0xFFFFFFFFFFFFFFFF +# LogFile (String): +# Write log messages to a file instead of the system log +# or stderr. +# This value can be up to 256 characters long. +# +# Settings can be provided in a config file. +# The syntax takes the form "p=v", +# where "p" is the parameter and "v" is the value. + +# The SID arguments have a very particular logic that must be +# understood for correct operation. A SID= argument defines one +# Service ID that is associated with a SINGLE virtual fabric. +# In addition, multiple SID= arguments can point to a single +# virtual fabric. +# +# For example, say a virtual fabric has three sets of SIDS associated +# with it: 0x0a1-0x0a3, 0x1a1-0x1a3 and 0x2a1-0x2a3. You would define this as +# +# SID=0x0a1 +# SID=0x0a2 +# SID=0x0a3 +# SID=0x1a1 +# SID=0x1a2 +# SID=0x1a3 +# SID=0x2a1 +# SID=0x2a2 +# SID=0x2a3 +# +# Note that a SID of zero is not supported at this time. Instead, +# the OPP libraries treat zero values as "unspecified". +# + +Dbg=5 + +#PSM MPI SID range. +# PSM_Control +SID=0x1000117500000000 +SID=0x1000117500000001 +SID=0x1000117500000002 +SID=0x1000117500000003 +SID=0x1000117500000004 +SID=0x1000117500000005 +SID=0x1000117500000006 +SID=0x1000117500000007 +# PSM_Data +SID=0x1000117500000008 +SID=0x1000117500000009 +SID=0x100011750000000a +SID=0x100011750000000b +SID=0x100011750000000c +SID=0x100011750000000d +SID=0x100011750000000e +SID=0x100011750000000f + +#PSM MPI SID range #2 +# PSM_Control +SID=0x1 +SID=0x2 +SID=0x3 +SID=0x4 +SID=0x5 +SID=0x6 +SID=0x7 +# PSM_Data +SID=0x9 +SID=0xa +SID=0xb +SID=0xc +SID=0xd +SID=0xe +SID=0xf + diff --git a/Dsap/dsap.conf.base b/Dsap/dsap.conf.base new file mode 100644 index 0000000..81c2b6e --- /dev/null +++ b/Dsap/dsap.conf.base @@ -0,0 +1,95 @@ +# [ICS VERSION STRING: unknown] + +# Usage: +# +# NoSubscribe (Boolean): +# Do not subscribe to SM for notifications. +# Valid: true or false (default). +# ScanFrequency (Unsigned): +# Number of seconds between unconditional sweeps. +# Range: 1 - 0xFFFFFFFF; Default: 600. +# UnsubscribedScanFrequency (Unsigned): +# Number of seconds between sweeps when not receiving notifications. +# Range: 1 - 0xFFFFFFFF; Default: 10. +# Dbg (Hex): +# Debug logging controls. Uses syslog log levels, ranging from 1 (system panic) +# to 7 (trace level). Generally, only levels 4-6 are useful to normal users. +# See the man page for vsyslog for more information. Default: 5. +# Publish (Boolean): +# Publish paths to shared memory. Valid: true (default) or false. +# SID (Special): +# Service ID that identifies a virtual fabric to include in the cache. +# Can be specified multiple times. +# Range: 1 - 0xFFFFFFFFFFFFFFFF +# LogFile (String): +# Write log messages to a file instead of the system log +# or stderr. +# This value can be up to 256 characters long. +# +# Settings can be provided in a config file. +# The syntax takes the form "p=v", +# where "p" is the parameter and "v" is the value. + +# The SID arguments have a very particular logic that must be +# understood for correct operation. A SID= argument defines one +# Service ID that is associated with a SINGLE virtual fabric. +# In addition, multiple SID= arguments can point to a single +# virtual fabric. +# +# For example, say a virtual fabric has three sets of SIDS associated +# with it: 0x0a1-0x0a3, 0x1a1-0x1a3 and 0x2a1-0x2a3. You would define this as +# +# SID=0x0a1 +# SID=0x0a2 +# SID=0x0a3 +# SID=0x1a1 +# SID=0x1a2 +# SID=0x1a3 +# SID=0x2a1 +# SID=0x2a2 +# SID=0x2a3 +# +# Note that a SID of zero is not supported at this time. Instead, +# the OPP libraries treat zero values as "unspecified". +# + +Dbg=5 + +#PSM MPI SID range. +# PSM_Control +SID=0x1000117500000000 +SID=0x1000117500000001 +SID=0x1000117500000002 +SID=0x1000117500000003 +SID=0x1000117500000004 +SID=0x1000117500000005 +SID=0x1000117500000006 +SID=0x1000117500000007 +# PSM_Data +SID=0x1000117500000008 +SID=0x1000117500000009 +SID=0x100011750000000a +SID=0x100011750000000b +SID=0x100011750000000c +SID=0x100011750000000d +SID=0x100011750000000e +SID=0x100011750000000f + +#PSM MPI SID range #2 +# PSM_Control +SID=0x1 +SID=0x2 +SID=0x3 +SID=0x4 +SID=0x5 +SID=0x6 +SID=0x7 +# PSM_Data +SID=0x9 +SID=0xa +SID=0xb +SID=0xc +SID=0xd +SID=0xe +SID=0xf + diff --git a/Dsap/dsap.spec b/Dsap/dsap.spec new file mode 100644 index 0000000..37fe8e4 --- /dev/null +++ b/Dsap/dsap.spec @@ -0,0 +1,71 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +#[ICS VERSION STRING: unknown] +Name: dsap +Version: 1.0.0 +Release: 1%{?dist} +Summary: Intel Distributed SA Provider for Ibacm + +Group: Applications/System +License: Copyright (c) 2014 Intel Corporation All Rights Reserved +Source0: %{name}-%{version}.tar.gz +BuildRoot: %{_builddir} +Vendor: Intel Corporation +AutoReqProv: no +Requires: ibacm + +%description +The %{name} is an ibacm provider that provides name and path record +resolution by reading host data file and caching SA data. + +%prep +%setup -q -n %{name}-%{version} + +%build +#nothing to do because we copy pre-built files into SOURCES + +%install +# simply copy the files +mkdir -p ${RPM_BUILD_ROOT}%{_sysconfdir}/rdma/ +cp -pr dsap.conf ${RPM_BUILD_ROOT}%{_sysconfdir}/rdma/ +mkdir -p ${RPM_BUILD_ROOT}%{_libdir}/ibacm/ +cp -pr lib%{name}.so.%{version} ${RPM_BUILD_ROOT}%{_libdir}/ibacm/ + +%clean +rm -rf $RPM_BUILD_ROOT + +%files +%defattr(-,root,root,-) +%doc README +%{_libdir}/ibacm/lib*.* +%{_sysconfdir}/rdma/dsap.conf + + + diff --git a/Dsap/libdsap.map b/Dsap/libdsap.map new file mode 100644 index 0000000..e5d4664 --- /dev/null +++ b/Dsap/libdsap.map @@ -0,0 +1,5 @@ +LIBDSAP_1.0.0 { + global: + provider_query; + local: *; +}; diff --git a/Dsap/src/dsap.c b/Dsap/src/dsap.c new file mode 100644 index 0000000..1c85b78 --- /dev/null +++ b/Dsap/src/dsap.c @@ -0,0 +1,362 @@ + /* BEGIN_ICS_COPYRIGHT4 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT4 ****************************************/ +/*! + + \file dsap_module.c + + $Revision: 1.5 $ + $Date: 2015/01/27 23:00:24 $ + + \brief Provider initialization and cleanup functions. +*/ + +#include + + +/* + ICS IBT stuff +*/ +#include "iba/ibt.h" +#include "iba/public/isemaphore.h" +#include "opasadb_debug.h" + +/* + Module stuff +*/ +#include "dsap.h" + +// Module parameters + + +uint32 dsap_dbg_level = _DBG_LVL_NOTICE; + +#define LOG_FILE_LENGTH 256 +static char dsap_log_file[LOG_FILE_LENGTH] = {0}; +static FILE *omgt_log_file = NULL; + +/* + * Parameter handling - replaces module parameters. + * + * name - variable name of the parameter. + * desc - human readable description + * type - enumerated type of the parameter (integer, unsigned, boolean, etc.) + * length - for string parameters, the max length of the string. + * ptr - pointer to the variable. + * parser - points to a function to handle special parameters. + * printer - points to a function that can print special parameters. + */ +typedef struct parameter { + char name[32]; + char desc[256]; + char type; + int length; + void *ptr; + int (*parser)(char *str, void *ptr); + char *(*printer)(void *ptr); +} parameter_t; + +static parameter_t parameters[] = { + { .name="NoSubscribe", + .type='b', + .desc="Do not subscribe to SM for notifications.", + .length = 0, + .ptr=(void*)&dsap_no_subscribe}, + { .name="ScanFrequency", + .type='u', + .desc="Number of seconds between unconditional sweeps.", + .length = 0, + .ptr=(void*)&dsap_scan_frequency}, + { .name="UnsubscribedScanFrequency", + .type='u', + .desc="Number of seconds between sweeps when not receiving " + "notifications.", + .length = 0, + .ptr=(void*)&dsap_unsub_scan_frequency}, + { .name="Dbg", + .type='x', + .desc="Debug logging controls. Uses syslog log levels, ranging" + " from 1 (least)\n\tto 7 (trace level).", + .length = 0, + .ptr=(void*)&dsap_dbg_level}, + { .name="Publish", + .type='b', + .desc="Publish paths to shared memory. Defaults to true.", + .length = 0, + .ptr=(void*)&dsap_publish}, + { .name="SID", + .type='S', + .desc="Service ID that identifies a virtual fabric to include " + "in the cache.\n\tCan be specified multiple times.", + .parser=dsap_service_id_range_parser, + .printer=dsap_service_id_range_printer, + .ptr=(void*)&sid_range_args}, + { .name="LogFile", + .type='s', + .desc="Write log messages to a file instead of the system log" + "\n\tor stderr.", + .length = LOG_FILE_LENGTH, + .ptr=(void*)&dsap_log_file}, + { .name="dsap_default_fabric", + .type='S', + .desc="normal = do not match SIDs to the default fabric unless" + " they don't\n\t match any other fabric.\n\tnone = never" + " match SIDs to the default fabric.\n\t Defaults to " + "normal.", + .parser=dsap_default_fabric_parser, + .printer=dsap_default_fabric_printer, + .ptr=(void*)&dsap_default_fabric }, + {"", "", 0, 0, NULL} +}; + +static void dsap_dump_params(parameter_t *params) +{ + int i=0; + + while (params[i].ptr != NULL) { + switch (params[i].type) { + case 'S': + acm_log(0, "%s = %s\n", params[i].name, + params[i].printer(params[i].ptr)); + break; + case 'X': + acm_log(0, "%s = 0x%016"PRIx64"\n", params[i].name, + (*(uint64 *) params[i].ptr)); + break; + case 'x': + acm_log(0, "%s = 0x%x\n", params[i].name, + (*(uint32 *) params[i].ptr)); + break; + case 'u': + acm_log(0, "%s = %u\n", params[i].name, + (*(uint32 *) params[i].ptr)); + break; + case 'i': + acm_log(0, "%s = %i\n", params[i].name, + (*(int32 *) params[i].ptr)); + break; + case 'b': + acm_log(0, "%s = %s\n", params[i].name, + (*(uint32 *) params[i].ptr) ? "yes" : "no"); + break; + case 's': + acm_log(0, "%s = %s\n", params[i].name, + (char *)params[i].ptr); + break; + default: + acm_log(0, "%s = Unhandled parameter type.\n", + params[i].name); + break; + } + i++; + } +} + +static char *dsap_trim(char *buffer) +{ + char *p; + int j = strlen(buffer) - 1; + + /* Trim trailing whitespace. */ + while (j>0 && isspace(buffer[j])) { + buffer[j] = 0; + j--; + } + + p=buffer; + /* Trim leading whitespce.*/ + j=0; + while (buffer[j]!=0 && isspace(buffer[j])) j++; + + p=&buffer[j]; + if (*p == '#' || *p == '\n' || *p == 0) + return NULL; + + return p; +} + +static int dsap_parse_record(parameter_t *params, char *buffer) +{ + char *k, *v, *l; + int i=0; + + k=strtok_r(buffer, "=", &l); + v=strtok_r(NULL, "=", &l); + + if (!k || !v) { + acm_log(0, "Config syntax error: %s\n", buffer); + return -1; + } + + /* strip white space */ + k=dsap_trim(k); + v=dsap_trim(v); + if (!k || !v) { + acm_log(0, "Config syntax error: %s\n", buffer); + return -1; + } + + while (params[i].ptr != NULL && (k != NULL && v != NULL)) { + if (strncasecmp(k, params[i].name, strlen(k)) == 0) { + switch (params[i].type) { + case 'S': + return params[i].parser(v, params[i].ptr); + case 'X': + (*(uint64 *) params[i].ptr) = + strtoull(v, NULL, 0); + return 0; + case 'x': + case 'u': + (*(uint32 *) params[i].ptr) = + strtoul(v, NULL, 0); + return 0; + case 'i': + (*(int32 *) params[i].ptr) = + strtol(v, NULL, 0); + return 0; + case 's': + strncpy((char *) params[i].ptr, v, + params[i].length); + ((char *) params[i].ptr)[params[i].length - 1] = 0; + return 0; + case 'b': + if (strcmp(v,"yes")==0 || + strcmp(v,"y") == 0 || + strcmp(v,"true") == 0 || + strcmp(v,"t") == 0) + (*(uint32 *) params[i].ptr) = 1; + else + (*(uint32 *) params[i].ptr) = + strtol(v, NULL, 0); + return 0; + default: + acm_log(0, "Unrecognized token in config.\n"); + } + } + i++; + } + + return -1; +} + +static int dsap_parse_settings(char *filename, parameter_t *params) +{ + int err = 0; + char *ptr; + char record[1024]; + FILE *f; + + acm_log(2, "\n"); + f = fopen(filename,"r"); + if (!f) { + acm_log(0, "Unable to open config file %s.\n", filename); + err=-1; + } + + while(!err && fgets(record, 1024, f)) { + ptr = dsap_trim(record); + if (ptr) { + if ((err = dsap_parse_record(params, record))) + acm_log(0, "Invalid Config Option: %s\n", ptr); + } + } + + if (f) fclose(f); + return err; +} + +/* Get dsap's own configuration parameters */ +void dsap_get_config(char *filename) +{ + if (dsap_parse_settings(filename, parameters)) + return; + + if (dsap_dbg_level > 7) dsap_dbg_level = 7; + + if (strlen(dsap_log_file) > 0) { + op_log_set_file(dsap_log_file); + op_log_set_level(dsap_dbg_level); + } + + dsap_dump_params(parameters); +} + + +/*! + \brief Cleanup function called when the provider is unloaded. +*/ + +void dsap_cleanup(void) +{ + acm_log(2, "\n"); + + dsap_scanner_cleanup(); + dsap_topology_cleanup(); + + if (omgt_log_file) + fclose(omgt_log_file); +} + +/*! + \brief Init function called when the provider is loaded. +*/ + +FSTATUS +dsap_init(void) +{ + FSTATUS fstatus = FERROR; + + acm_log(2, "\n"); + + + fstatus = dsap_topology_init(); + if (fstatus != FSUCCESS) + goto exit; + + fstatus = dsap_scanner_init(); + if (FSUCCESS != fstatus) + goto exit; + + /* Guard against scans without timeout */ + if (dsap_unsub_scan_frequency == 0) + dsap_unsub_scan_frequency = 10; + + fstatus = dsap_scanner_start(); + +exit: + return fstatus; +} +void dsap_omgt_log_init(struct omgt_port *omgt_port) +{ + if (strlen(dsap_log_file) > 0) { + omgt_log_file = op_log_get_file(); + omgt_set_err(omgt_port, omgt_log_file); + if (dsap_dbg_level >= 7) + omgt_set_dbg(omgt_port, omgt_log_file); + } +} diff --git a/Dsap/src/dsap.h b/Dsap/src/dsap.h new file mode 100644 index 0000000..053800d --- /dev/null +++ b/Dsap/src/dsap.h @@ -0,0 +1,161 @@ +/* BEGIN_ICS_COPYRIGHT4 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT4 ****************************************/ +/*! + + \file dsap_module.h + + $Revision: 1.3 $ + $Date: 2015/01/22 18:07:38 $ + + Defines the prototypes and constants used by the ibacm provider dsap. +*/ +#ifndef _DSAP_H_ +#define _DSAP_H_ + +#include +#include +#include +#include +#include + +#include +#include +#include "ispinlock_osd.h" +#include "opamgt_sa_priv.h" + +#include "dsap_topology.h" + +#define MAX_EP_ADDR 4 + +#define for_each(list, item) \ + for (item = QListHead(list); item != NULL; item = QListNext(list, item)) + +typedef enum port_event_type { + DSAP_PT_EVT_SRC_PORT_UP, + DSAP_PT_EVT_SRC_PORT_DOWN, + DSAP_PT_EVT_DST_PORT_UP, + DSAP_PT_EVT_DST_PORT_DOWN, + DSAP_PT_EVT_PORT_RESCAN, + DSAP_PT_EVT_FULL_RESCAN +} port_event_type_t; + +typedef enum default_fabric_action { + DSAP_DEF_FAB_ACT_NORMAL, + DSAP_DEF_FAB_ACT_NONE, + DSAP_DEF_FAB_ACT_ALL +} default_fabric_action_t; + + +/* Device/port/endpoint/adddress structures for local provider ports */ +struct dsap_device; + +struct dsap_port { + struct dsap_device *dev; + const struct acm_port *port; + QUICK_LIST ep_list; + SPIN_LOCK lock; + enum ibv_port_state state; + uint16_t default_pkey_ix; + uint16_t lid; + uint16_t lid_mask; + uint16_t lmc; + uint16_t sm_lid; + pthread_t notice_thread; + int notice_started; + int terminating; + struct omgt_port *omgt_handle; + void *lib_handle; +}; + + +struct dsap_device { + const struct acm_device *device; + LIST_ITEM item; + int port_cnt; + struct dsap_port port[0]; +}; + +struct dsap_ep; + +struct dsap_addr { + uint16_t type; + union acm_ep_info info; + struct acm_address *addr; + struct dsap_ep *ep; +}; + +struct dsap_ep { + struct dsap_port *port; + LIST_ITEM item; + char id_string[ACM_MAX_ADDRESS]; + const struct acm_endpoint *endpoint; + SPIN_LOCK lock; + struct dsap_addr addr_info[MAX_EP_ADDR]; + uint64_t counters[ACM_MAX_COUNTER]; +}; + +/* Configuration parameters */ +extern uint32 dsap_no_subscribe; +extern uint32 dsap_unsub_scan_frequency; +extern uint32 dsap_scan_frequency; +extern boolean dsap_publish; +extern uint32 dsap_default_fabric; + +/* Function prototypes */ +void dsap_get_config(char *filename); +void dsap_cleanup(void); +FSTATUS dsap_init(void); +void dsap_omgt_log_init(struct omgt_port *omgt_port); + +int dsap_default_fabric_parser(char *str, void *ptr); +char *dsap_default_fabric_printer(void *ptr); + +FSTATUS dsap_scanner_init(void); +FSTATUS dsap_scanner_start(void); +void dsap_scanner_cleanup(void); + +FSTATUS dsap_query_path_records(dsap_src_port_t *src_port, + dsap_dst_port_t *dst_port, uint64_t sid, + uint16_t pkey); + +FSTATUS dsap_query_dst_ports(dsap_subnet_t *subnet); +FSTATUS dsap_query_default_vfinfo_record(dsap_subnet_t *subnet); +FSTATUS dsap_query_vfinfo_records(dsap_subnet_t *subnet, + dsap_service_id_range_t *service_id_range); +FSTATUS dsap_query_dst_port(union ibv_gid *dst_gid, NODE_TYPE *node_type, + char * node_desc); + +void dsap_port_event(uint64 src_guid, uint64 src_subnet, uint64 dest_guid, + port_event_type_t port_event_type); + +struct dsap_port * dsap_lock_prov_port(dsap_src_port_t *src_port); +void dsap_release_prov_port(struct dsap_port *port); +FSTATUS dsap_add_src_ports(void); + +#endif diff --git a/Dsap/src/dsap_notifications.c b/Dsap/src/dsap_notifications.c new file mode 100644 index 0000000..d631f2f --- /dev/null +++ b/Dsap/src/dsap_notifications.c @@ -0,0 +1,357 @@ +/* BEGIN_ICS_COPYRIGHT5 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + * ** END_ICS_COPYRIGHT5 ****************************************/ +/* [ICS VERSION STRING: unknown] */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "ib_notice_net.h" +#include "opamgt_sa_notice.h" +#include "dsap.h" +#include "dsap_notifications.h" + +typedef enum { + DSAP_NOTIFY_NO_ACTION, + DSAP_NOTIFY_REREGISTER, + DSAP_NOTIFY_REINITIALIZE +} notify_t; + +uint32 dsap_no_subscribe = 0; + +static pthread_mutex_t m_context = PTHREAD_MUTEX_INITIALIZER; +static pthread_mutex_t m_reinitialize = PTHREAD_MUTEX_INITIALIZER; +static pthread_cond_t c_reinitialize; + +static int report_notice_callback(uint16_t trap_num, IB_GID *gid, struct dsap_port *port); + +static int dsap_handle_event(struct dsap_port *port, STL_NOTICE *notice, size_t len, + void *context, OMGT_STATUS_T status) +{ + struct dsap_port *evt_port = context; + int action = DSAP_NOTIFY_NO_ACTION; + STL_TRAP_GID *data_details; + IB_GID gid; + + if (status == OMGT_STATUS_SUCCESS) { + if (port != evt_port) { + /* Verify context matches */ + acm_log(1, "Received an invalid context pointer from ib_usa: 0x%p\n", + context); + if (notice) free(notice); + return action; + } + /* NOTICE */ + data_details = (STL_TRAP_GID *)notice->Data; + + acm_log(2, "NOTICE: source lid = %d, status = %d, attr_size = %lu, context = %p\n", + notice->IssuerLID, status, len, evt_port); + memcpy(gid.Raw, data_details->Gid.Raw, sizeof(gid.Raw)); + action = report_notice_callback(notice->Attributes.Generic.TrapNumber, + &gid, evt_port); + free(notice); + } else if (status == OMGT_STATUS_DISCONNECT) { + /* INFORM INFO */ + acm_log(2, "INFORM_INFO: Timeout\n\n"); + acm_log(0, "Port %u has timed out trying to contact with the SM.\n", + port->port->port_num); + + action = DSAP_NOTIFY_REINITIALIZE; + } else { + acm_log(2, "Unhandled notification: status = %u\n", status); + } + return action; +} + +static void dsap_take_action(int action) +{ + struct timeval now; + struct timespec delay; + + switch (action) { + case DSAP_NOTIFY_NO_ACTION: + break; + case DSAP_NOTIFY_REREGISTER: + break; + case DSAP_NOTIFY_REINITIALIZE: + if (pthread_mutex_trylock(&m_reinitialize)) { + /* This should be impossible. */ + acm_log(1, "Discarding nested re-initialize event.\n"); + break; + } + + gettimeofday(&now,NULL); + delay.tv_sec = now.tv_sec + dsap_unsub_scan_frequency; + delay.tv_nsec = 0; + + acm_log(1, "Re-initializing in %u seconds.\n", + (unsigned int)(delay.tv_sec - now.tv_sec)); + + pthread_cond_timedwait(&c_reinitialize, &m_reinitialize, + &delay); + + dsap_reinitialize_notifications(); + pthread_mutex_unlock(&m_reinitialize); + break; + } +} + +static void * dsap_notification_event_thread(void *arg) +{ + struct dsap_port *port; + int action; + STL_NOTICE *notice = NULL; + size_t notice_len = 0; + OMGT_STATUS_T status; + void *context = NULL; + + acm_log(2, "\n"); + + if (arg == NULL) { + acm_log(0, "Port context empty.\n"); + pthread_exit (arg); + return arg; + } + port = arg; + + if (pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL)) { + acm_log(0, "Failed to set cancel type \n"); + pthread_exit(NULL); + return NULL; + } + if (pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL)) { + acm_log(0, "Failed to set cancel state\n"); + pthread_exit(NULL); + return NULL; + } + + while (!port->terminating) { + pthread_testcancel(); + action = DSAP_NOTIFY_NO_ACTION; + status = omgt_sa_get_notice_report(port->omgt_handle, ¬ice, ¬ice_len, + &context, -1); + + action = dsap_handle_event(port, notice, notice_len, context, status); + + dsap_take_action(action); + } + + pthread_exit (arg); + return arg; +} + +void dsap_terminate_notification(struct dsap_port *port) +{ + acm_log(2, "\n"); + + if (port->notice_started) { + port->terminating = 1; + pthread_cancel(port->notice_thread); + pthread_join(port->notice_thread, NULL); + port->notice_started = 0; + } + + + if (port->omgt_handle != NULL) { + omgt_close_port(port->omgt_handle); + port->omgt_handle = NULL; + } +} + +static int +report_notice_callback(uint16_t trap_num, IB_GID *gid, struct dsap_port *port) +{ + char gid_str[INET6_ADDRSTRLEN]; + union ibv_gid src_gid; + + acm_log(2, "\n"); + if (acm_get_gid((struct acm_port *) port->port, 0, &src_gid)) { + acm_log(0, "Failed to get src gid\n"); + goto cb_exit; + } + + switch (trap_num) + { + case IBV_SA_SM_TRAP_GID_IN_SERVICE: + acm_log(1, "Received GID Now In Service = 0x%016"PRIx64"/%s\n", + ntoh64(src_gid.global.interface_id), + inet_ntop(AF_INET6, gid->Raw, gid_str, sizeof gid_str)); + dsap_port_event(src_gid.global.interface_id, + src_gid.global.subnet_prefix, + gid->Type.Global.InterfaceID, + DSAP_PT_EVT_DST_PORT_UP); + break; + case IBV_SA_SM_TRAP_GID_OUT_OF_SERVICE: + acm_log(1, "Received GID Out Of Service = 0x%016"PRIx64"/%s\n", + ntoh64(src_gid.global.interface_id), + inet_ntop(AF_INET6, gid->Raw, gid_str, sizeof gid_str)); + dsap_port_event(src_gid.global.interface_id, + src_gid.global.subnet_prefix, + gid->Type.Global.InterfaceID, + DSAP_PT_EVT_DST_PORT_DOWN); + break; + default: + acm_log(0, "Received Unknown Notice = %u. Gid = 0x%016"PRIx64"/%s\n", + trap_num, ntoh64(src_gid.global.interface_id), + inet_ntop(AF_INET6, gid->Raw, gid_str, sizeof gid_str)); + break; + } + +cb_exit: + return DSAP_NOTIFY_NO_ACTION; +} + +FSTATUS dsap_notification_register_port(struct dsap_port *port) +{ + int rval; + union ibv_gid gid; + + acm_log(2, "port %s/%d\n", port->dev->device->verbs->device->name, + port->port->port_num); + + /* open the opamgt port object */ + if (acm_get_gid((struct acm_port *) port->port, 0, &gid)) { + acm_log(0, "Failed to get gid\n"); + goto error; + } + if ((rval = omgt_open_port_by_guid(&port->omgt_handle, + ntoh64(gid.global.interface_id), NULL))) { + acm_log(0, "Cannot open opamgt port object. (%d)\n", rval); + goto error; + } + + //set logging + dsap_omgt_log_init(port->omgt_handle); + + + if (dsap_no_subscribe) + return FSUCCESS; + + /* spawn the notification thread before registering for the traps */ + port->terminating = 0; + if (pthread_create(&port->notice_thread, NULL, + dsap_notification_event_thread, port)) { + acm_log(0, "Failed to create the notification thread\n"); + goto error; + } + + rval = omgt_sa_register_trap(port->omgt_handle, + ntoh16(IBV_SA_SM_TRAP_GID_IN_SERVICE), + port); + if (rval) { + acm_log(0, "Cannot subscribe for Trap GID_IN_SERVICE. (%d)\n", + rval); + goto error1; + } + + rval = omgt_sa_register_trap(port->omgt_handle, + ntoh16(IBV_SA_SM_TRAP_GID_OUT_OF_SERVICE), + port); + if (rval) { + acm_log(0, "Cannot subscrb for Trap GID_OUT_OF_SERVICE.(%d)\n", + rval); + goto error1; + } + port->notice_started = 1; + + return FSUCCESS; + +error1: + port->terminating = 1; + pthread_cancel(port->notice_thread); + pthread_join(port->notice_thread, NULL); +error: + port->notice_started = 0; + + return FERROR; +} + +FSTATUS dsap_notification_reregister_port(struct dsap_port *port) +{ + FSTATUS fstatus = FSUCCESS; + int rval; + + acm_log(2, "\n"); + + if (dsap_no_subscribe) + return FSUCCESS; + + pthread_mutex_lock(&m_context); + if (!port || !port->omgt_handle) { + fstatus = FERROR; + acm_log(0, "Invalid parameters.\n"); + goto error; + } + + rval = omgt_sa_register_trap(port->omgt_handle, + ntoh16(IBV_SA_SM_TRAP_GID_IN_SERVICE), + port); + if (rval) { + acm_log(0, "Cannot subscribe for Trap GID_IN_SERVICE. (%d)\n", + rval); + fstatus = FERROR; + goto error; + } + + rval = omgt_sa_register_trap(port->omgt_handle, + ntoh16(IBV_SA_SM_TRAP_GID_OUT_OF_SERVICE), + port); + if (rval) { + acm_log(0, "Cannot subscrb for Trap GID_OUT_OF_SERVICE.(%d)\n", + rval); + fstatus = FERROR; + } + +error: + pthread_mutex_unlock(&m_context); + + return fstatus; +} + +/* + * There seems to be a bug in ib_usa that causes it to crash if you + * just try to re-subscribe after a time out error. So, we trash + * the whole channel and reconnect. + */ +FSTATUS dsap_reinitialize_notifications(void) +{ + acm_log(2, "Initiating re-scan.\n"); + + dsap_port_event(0, 0, 0, DSAP_PT_EVT_FULL_RESCAN); + + return FSUCCESS; +} diff --git a/Dsap/src/dsap_notifications.h b/Dsap/src/dsap_notifications.h new file mode 100644 index 0000000..c1de2f6 --- /dev/null +++ b/Dsap/src/dsap_notifications.h @@ -0,0 +1,55 @@ +/* BEGIN_ICS_COPYRIGHT4 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT4 ****************************************/ +/*! + + \file dsap_hca.h + + $Revision: 1.2 $ + $Date: 2015/01/22 18:07:38 $ + + \brief Routines for registering for notifications from the SM. +*/ +#if !defined(_DSAP_NOTIFICATIONS_H_) +#define _DSAP_NOTIFICATIONS_H_ + +#include + +#include "iba/ibt.h" + + +FSTATUS dsap_reinitialize_notifications(void); + +void dsap_terminate_notification(struct dsap_port *port); + +FSTATUS dsap_notification_register_port(struct dsap_port *port); + +FSTATUS dsap_notification_reregister_port(struct dsap_port *port); + + +#endif /* !defined(_DSAP_NOTIFICATIONS_H_) */ diff --git a/Dsap/src/dsap_prov.c b/Dsap/src/dsap_prov.c new file mode 100644 index 0000000..df50c6f --- /dev/null +++ b/Dsap/src/dsap_prov.c @@ -0,0 +1,990 @@ + /* BEGIN_ICS_COPYRIGHT4 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT4 ****************************************/ + +/* This file incorporates work covered by the following copyright and permission notice */ + +/* Part of the code is copied and modified from ibacm/prov/acmp/src/acmp.c. */ +/* + * Copyright (c) 2009-2014 Intel Corporation. All rights reserved. + * Copyright (c) 2013 Mellanox Technologies LTD. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AWV + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +/*! + + \file dsap_main.c + + \brief Ibacm provider dsap +*/ + +#include +#include +#include + +#include +#include +#include +#include + +#define __USE_GNU +#include + +#include +#include "iba/ibt.h" +#include "opasadb_debug.h" +#include "dsap.h" +#include "dsap_topology.h" +#include "opasadb_path.h" +#include "dsap_notifications.h" + +#define src_out data[0] +#define src_index data[1] +#define dst_index data[2] + +/* Copied from ibacm/include/acm_mad.h */ +#define ACM_ADDRESS_INVALID 0x00 +#define ACM_ADDRESS_NAME 0x01 +#define ACM_ADDRESS_IP 0x02 +#define ACM_ADDRESS_IP6 0x03 +#define ACM_ADDRESS_GID 0x04 +#define ACM_ADDRESS_LID 0x05 +#define ACM_ADDRESS_RESERVED 0x06 + +struct dsap_dest { + uint8_t address[ACM_MAX_ADDRESS]; + char name[ACM_MAX_ADDRESS]; + union ibv_gid gid; + uint8_t addr_type; +}; + +static void * dest_map[ACM_ADDRESS_RESERVED - 1]; + +QUICK_LIST dsap_dev_list; +SPIN_LOCK dsap_dev_lock; + +static char log_data[ACM_MAX_ADDRESS]; + +static char config_file[128] = "/etc/rdma/dsap.conf"; +static char addr_data_file[128] = "/etc/rdma/ibacm_hosts.data"; +static int dsap_initialized; + +static int dsap_open_dev(const struct acm_device *device, void **dev_context); +static void dsap_close_dev(void *dev_context); +static int dsap_open_port(const struct acm_port *port, void *dev_context, + void **port_context); +static void dsap_close_port(void *port_context); +static int dsap_open_endpoint(const struct acm_endpoint *endpoint, + void *port_context, void **ep_context); +static void dsap_close_endpoint(void *ep_context); +static int dsap_add_addr(const struct acm_address *addr, void *ep_context, + void **addr_context); +static void dsap_remove_addr(void *addr_context); +static int dsap_resolve(void *addr_context, struct acm_msg *msg, uint64_t id); +static int dsap_query(void *addr_context, struct acm_msg *msg, uint64_t id); +static int dsap_handle_event(void *port_context, enum ibv_event_type type); +static void dsap_query_perf(void *ep_context, uint64_t *values, uint8_t *cnt); + +static struct acm_provider def_prov = { + .size = sizeof(struct acm_provider), + .version = 1, + .name = "dsap", + .open_device = dsap_open_dev, + .close_device = dsap_close_dev, + .open_port = dsap_open_port, + .close_port = dsap_close_port, + .open_endpoint = dsap_open_endpoint, + .close_endpoint = dsap_close_endpoint, + .add_address = dsap_add_addr, + .remove_address = dsap_remove_addr, + .resolve = dsap_resolve, + .query = dsap_query, + .handle_event = dsap_handle_event, + .query_perf = dsap_query_perf, +}; + +static int dsap_compare_dest(const void *dest1, const void *dest2) +{ + return memcmp(dest1, dest2, ACM_MAX_ADDRESS); +} + +static void +dsap_set_dest_addr(struct dsap_dest *dest, uint8_t addr_type, + const uint8_t *addr, size_t size) +{ + memcpy(dest->address, addr, size); + dest->addr_type = addr_type; + acm_format_name(0, dest->name, sizeof dest->name, addr_type, addr, + size); +} + +static void +dsap_init_dest(struct dsap_dest *dest, uint8_t addr_type, + const uint8_t *addr, size_t size) +{ + if (size) + dsap_set_dest_addr(dest, addr_type, addr, size); +} + +static struct dsap_dest * +dsap_alloc_dest(uint8_t addr_type, const uint8_t *addr) +{ + struct dsap_dest *dest; + + dest = calloc(1, sizeof *dest); + if (!dest) { + acm_log(0, "ERROR - unable to allocate dest\n"); + return NULL; + } + + dsap_init_dest(dest, addr_type, addr, ACM_MAX_ADDRESS); + acm_log(1, "%s\n", dest->name); + return dest; +} + +static struct dsap_dest * +dsap_get_dest(uint8_t addr_type, const uint8_t *addr) +{ + struct dsap_dest *dest, **tdest; + + tdest = tfind(addr, &dest_map[addr_type - 1], dsap_compare_dest); + if (tdest) { + dest = *tdest; + acm_log(2, "%s\n", dest->name); + } else { + dest = NULL; + acm_format_name(2, log_data, sizeof log_data, + addr_type, addr, ACM_MAX_ADDRESS); + acm_log(2, "%s not found\n", log_data); + } + return dest; +} + +static struct dsap_dest * +dsap_acquire_dest(uint8_t addr_type, const uint8_t *addr) +{ + struct dsap_dest *dest; + + acm_format_name(2, log_data, sizeof log_data, + addr_type, addr, ACM_MAX_ADDRESS); + acm_log(2, "%s\n", log_data); + dest = dsap_get_dest(addr_type, addr); + if (!dest) { + dest = dsap_alloc_dest(addr_type, addr); + if (dest) + tsearch(dest, &dest_map[addr_type - 1], + dsap_compare_dest); + } + return dest; +} + +static void dsap_init_port(struct dsap_port *port, + struct dsap_device *dev, uint8_t port_num) +{ + acm_log(1, "%s %d\n", dev->device->verbs->device->name, port_num); + port->dev = dev; + SpinLockInitState(&port->lock); + SpinLockInit(&port->lock); + QListInitState(&port->ep_list); + QListInit(&port->ep_list); + port->state = IBV_PORT_DOWN; +} + +static int dsap_open_dev(const struct acm_device *device, void **dev_context) +{ + struct dsap_device *dev; + size_t size; + struct ibv_device_attr attr; + int i, ret; + + acm_log(1, "dev_guid 0x%"PRIx64" %s\n", ntoh64(device->dev_guid), + device->verbs->device->name); + + ret = ibv_query_device(device->verbs, &attr); + if (ret) { + acm_log(0, "ERROR - ibv_query_device (%s) %d\n", + device->verbs->device->name, ret); + goto err; + } + + size = sizeof(*dev) + sizeof(struct dsap_port) * attr.phys_port_cnt; + dev = (struct dsap_device *) calloc(1, size); + if (!dev) + goto err; + + dev->device = device; + dev->port_cnt = attr.phys_port_cnt; + + for (i = 0; i < dev->port_cnt; i++) { + dsap_init_port(&dev->port[i], dev, i + 1); + } + + ListItemInitState(&dev->item); + QListSetObj(&dev->item, dev); + SpinLockAcquire(&dsap_dev_lock); + QListInsertTail(&dsap_dev_list, &dev->item); + SpinLockRelease(&dsap_dev_lock); + *dev_context = dev; + + acm_log(1, "%s opened\n", device->verbs->device->name); + return 0; +err: + return -1; +} + +static void dsap_close_dev(void *dev_context) +{ + struct dsap_device *dev = dev_context; + + acm_log(1, "dev_guid 0x%"PRIx64"\n", ntoh64(dev->device->dev_guid)); + SpinLockAcquire(&dsap_dev_lock); + QListRemoveItem(&dsap_dev_list, &dev->item); + SpinLockRelease(&dsap_dev_lock); + free(dev); +} + + +static void dsap_port_up(struct dsap_port *port) +{ + struct ibv_port_attr attr; + uint16_t pkey; + int i, ret; + + acm_log(1, "%s %d\n", port->dev->device->verbs->device->name, + port->port->port_num); + ret = ibv_query_port(port->dev->device->verbs, port->port->port_num, + &attr); + if (ret) { + acm_log(0, "ERROR - unable to get port attribute\n"); + return; + } + + port->lid = attr.lid; + port->lmc = attr.lmc; + port->lid_mask = 0xffff - ((1 << attr.lmc) - 1); + port->sm_lid = attr.sm_lid; + + for (i = 0; i < attr.pkey_tbl_len; i++) { + ret = ibv_query_pkey(port->dev->device->verbs, + port->port->port_num, i, &pkey); + if (ret) + continue; + pkey = ntohs(pkey); + if (!(pkey & 0x7fff)) + continue; + + /* Determine pkey index for default partition with preference + * for full membership + */ + if ((pkey & 0x7fff) == 0x7fff) { + port->default_pkey_ix = i; + break; + } + } + + /* Start the notification thread */ + if (dsap_notification_register_port(port) != FSUCCESS) { + dsap_terminate_notification(port); + acm_log(0, "Failed to register port for notification\n"); + return; + } + + /* + * open the Libopasadb library for this port. If it is not + * available yet, we will try to open it at the first access + * to the database. + * Note: by this time, the first scan may have not been + * started yet and any attempt to open the libopasadb + * will fail. Hold on until the first request comes in. + */ + /*port->lib_handle = op_path_open(port->dev->device->verbs->device, + port->port->port_num); + if (!port->lib_handle) + acm_log(1, "Failed to open libopasadb\n"); */ + + SpinLockAcquire(&port->lock); + port->state = IBV_PORT_ACTIVE; + SpinLockRelease(&port->lock); + acm_log(1, "%s %d is up\n", port->dev->device->verbs->device->name, + port->port->port_num); +} + +static int dsap_open_port(const struct acm_port *port, void *dev_context, + void **port_context) +{ + struct dsap_device *dev = dev_context; + struct dsap_port *dport; + + if (port->port_num < 1 || port->port_num > dev->port_cnt) { + acm_log(0, "Error: port_num %d is out of range (max %d)\n", + port->port_num, dev->port_cnt); + return -1; + } + + dport = &dev->port[port->port_num - 1]; + SpinLockAcquire(&dport->lock); + dport->port = port; + dport->state = IBV_PORT_DOWN; + SpinLockRelease(&dport->lock); + dsap_port_up(dport); + *port_context = dport; + /* Theoretically we should send an event to the scanner thread to + * announce our presence. However, since the scanner needs the + * pkeys, we will delay the announcement until the first + * endpoint is opened. */ + + return 0; +} + +static void dsap_close_port(void *port_context) +{ + struct dsap_port *port = port_context; + union ibv_gid gid; + + acm_log(1, "%s %d\n", port->dev->device->verbs->device->name, + port->port->port_num); + /* Send an event to the scanner */ + if (!acm_get_gid((struct acm_port *) port->port, 0, &gid)) { + dsap_port_event(gid.global.interface_id, + gid.global.subnet_prefix, + gid.global.interface_id, + DSAP_PT_EVT_SRC_PORT_DOWN); + } + + if (port->lib_handle) { + op_path_close(port->lib_handle); + port->lib_handle = NULL; + } + SpinLockAcquire(&port->lock); + /* Terminate the notification thread */ + dsap_terminate_notification(port); + port->state = IBV_PORT_DOWN; + port->port = NULL; + SpinLockRelease(&port->lock); +} + +static struct dsap_ep * +dsap_alloc_ep(struct dsap_port *port, struct acm_endpoint *endpoint) +{ + struct dsap_ep *ep; + + acm_log(1, "\n"); + ep = calloc(1, sizeof *ep); + if (!ep) + return NULL; + + ep->port = port; + ep->endpoint = endpoint; + snprintf(ep->id_string, ACM_MAX_ADDRESS, "%s-%d-0x%x", + port->dev->device->verbs->device->name, + port->port->port_num, endpoint->pkey); + + return ep; +} + +static int dsap_open_endpoint(const struct acm_endpoint *endpoint, + void *port_context, void **ep_context) +{ + struct dsap_port *port = port_context; + struct dsap_ep *ep; + union ibv_gid gid; + + acm_log(2, "creating endpoint for pkey 0x%x\n", endpoint->pkey); + ep = dsap_alloc_ep(port, (struct acm_endpoint *) endpoint); + if (!ep) + return -1; + + snprintf(ep->id_string, ACM_MAX_ADDRESS, "%s-%d-0x%x", + port->dev->device->verbs->device->name, + port->port->port_num, endpoint->pkey); + + ListItemInitState(&ep->item); + QListSetObj(&ep->item, ep); + SpinLockAcquire(&port->lock); + QListInsertTail(&port->ep_list, &ep->item); + SpinLockRelease(&port->lock); + *ep_context = (void *) ep; + + /* Now send an event to the scanner: only once per port */ + if (!acm_get_gid((struct acm_port *) port->port, 0, &gid)) + dsap_port_event(gid.global.interface_id, + gid.global.subnet_prefix, + gid.global.interface_id, + DSAP_PT_EVT_SRC_PORT_UP); + + return 0; +} + +static void dsap_close_endpoint(void *ep_context) +{ + struct dsap_ep *ep = ep_context; + + acm_log(1, "%s %d pkey 0x%04x\n", + ep->port->dev->device->verbs->device->name, + ep->port->port->port_num, ep->endpoint->pkey); + SpinLockAcquire(&ep->port->lock); + QListRemoveItem(&ep->port->ep_list, &ep->item); + SpinLockRelease(&ep->port->lock); + + free(ep); +} + +static int dsap_add_addr(const struct acm_address *addr, void *ep_context, + void **addr_context) +{ + struct dsap_ep *ep = ep_context; + int i; + + acm_log(2, "\n"); + + for (i = 0; (i < MAX_EP_ADDR) && + (ep->addr_info[i].type != ACM_ADDRESS_INVALID); i++) + ; + + if (i == MAX_EP_ADDR) { + acm_log(0, "ERROR - no more space for local address\n"); + return -1; + } + ep->addr_info[i].type = addr->type; + memcpy(&ep->addr_info[i].info, &addr->info, sizeof(addr->info)); + ep->addr_info[i].addr = (struct acm_address *) addr; + ep->addr_info[i].ep = ep; + *addr_context = &ep->addr_info[i]; + + return 0; +} + +static void dsap_remove_addr(void *addr_context) +{ + struct dsap_addr *address = addr_context; + + acm_log(2, "\n"); + memset(address, 0, sizeof(*address)); +} + +static int +dsap_resolve_response(uint64_t id, struct acm_msg *req_msg, + struct dsap_ep *ep, uint8_t status) +{ + struct acm_msg msg; + + acm_log(2, "client %"PRId64", status 0x%x\n", id, status); + memset(&msg, 0, sizeof msg); + + if (ep) { + if (status == ACM_STATUS_ENODATA) + ep->counters[ACM_CNTR_NODATA]++; + else if (status) + ep->counters[ACM_CNTR_ERROR]++; + } + msg.hdr = req_msg->hdr; + msg.hdr.status = status; + msg.hdr.length = ACM_MSG_HDR_LENGTH; + memset(msg.hdr.data, 0, sizeof(msg.hdr.data)); + + if (status == ACM_STATUS_SUCCESS) { + msg.hdr.length += ACM_MSG_EP_LENGTH; + msg.resolve_data[0].flags = IBV_PATH_FLAG_GMP | + IBV_PATH_FLAG_PRIMARY | IBV_PATH_FLAG_BIDIRECTIONAL; + msg.resolve_data[0].type = ACM_EP_INFO_PATH; + msg.resolve_data[0].info.path = + req_msg->resolve_data[0].info.path; + + if (req_msg->hdr.src_out) { + msg.hdr.length += ACM_MSG_EP_LENGTH; + memcpy(&msg.resolve_data[1], + &req_msg->resolve_data[req_msg->hdr.src_index], + ACM_MSG_EP_LENGTH); + } + } + + return acm_resolve_response(id, &msg); +} + +static int +dsap_resolve_dest(struct dsap_ep *ep, struct acm_msg *msg, uint64_t id) +{ + struct dsap_dest *dest; + struct acm_ep_addr_data *daddr; + uint8_t status = ACM_STATUS_SUCCESS; + struct ibv_path_record *path; + struct ibv_path_record query; + + daddr = &msg->resolve_data[msg->hdr.dst_index]; + acm_format_name(2, log_data, sizeof log_data, + daddr->type, daddr->info.addr, + sizeof daddr->info.addr); + acm_log(2, "dest %s\n", log_data); + + dest = dsap_get_dest(daddr->type, daddr->info.addr); + if (!dest) { + acm_log(0, "ERROR - unable to get destination in request\n"); + status = ACM_STATUS_ENODATA; + goto resp; + } + + path = &msg->resolve_data[0].info.path; + memset(&query, 0, sizeof(query)); + query.slid = htons(ep->port->lid); + query.pkey = htons(ep->endpoint->pkey); + acm_get_gid((struct acm_port *) ep->port->port, 0, &query.sgid); + memcpy(&query.dgid, &dest->gid, sizeof(query.dgid)); + acm_log(2, "slid %04x pkey %04x sgid %"PRIx64":%"PRIx64" dgid %"PRIx64":%"PRIx64"\n", + ntohs(query.slid), ntohs(query.pkey), + ntoh64(query.sgid.global.subnet_prefix), + ntoh64(query.sgid.global.interface_id), + ntoh64(query.dgid.global.subnet_prefix), + ntoh64(query.dgid.global.interface_id)); + + /* If we have not opened libopasadb previously, do it now */ + if (!ep->port->lib_handle) { + ep->port->lib_handle = + op_path_open(ep->port->dev->device->verbs->device, + ep->port->port->port_num); + if (!ep->port->lib_handle) { + acm_log(0, "Error -- Failed to open libopasadb\n"); + status = ACM_STATUS_ENODATA; + goto resp; + } + } + + if (op_path_get_path_by_rec(ep->port->lib_handle, + (op_path_rec_t *) &query, + (op_path_rec_t *) path)) { + acm_log(0, "Error -- Failed to get path record\n"); + status = ACM_STATUS_ENODATA; + } + +resp: + return dsap_resolve_response(id, msg, ep, status); +} + +static int +dsap_resolve_path(struct dsap_ep *ep, struct acm_msg *msg, uint64_t id) +{ + struct ibv_path_record *path; + uint8_t status = ACM_STATUS_SUCCESS; + struct ibv_path_record query; + + path = &msg->resolve_data[0].info.path; + if (!path->slid && ib_any_gid(&path->sgid)) { + path->slid = htons(ep->port->lid); + acm_get_gid((struct acm_port *) ep->port->port, 0, + &path->sgid); + } + + /* If we have not opened libopasadb previously, do it now */ + if (!ep->port->lib_handle) { + ep->port->lib_handle = + op_path_open(ep->port->dev->device->verbs->device, + ep->port->port->port_num); + if (!ep->port->lib_handle) { + acm_log(0, "Error -- Failed to open libopasadb\n"); + status = ACM_STATUS_ENODATA; + goto resp; + } + } + + memcpy(&query, path, sizeof(query)); + /* The query requires at least one of them be present */ + if (!query.pkey && !query.service_id) + query.pkey = htons(ep->endpoint->pkey); + if (op_path_get_path_by_rec(ep->port->lib_handle, + (op_path_rec_t *) &query, + (op_path_rec_t *) path)) { + acm_log(0, "Error -- Failed to get path record\n"); + status = ACM_STATUS_ENODATA; + } + +resp: + return dsap_resolve_response(id, msg, ep, status); +} + +static int dsap_resolve(void *addr_context, struct acm_msg *msg, uint64_t id) +{ + struct dsap_addr *address = addr_context; + struct dsap_ep *ep = address->ep; + + ep->counters[ACM_CNTR_RESOLVE]++; + if (msg->resolve_data[0].type == ACM_EP_INFO_PATH) + return dsap_resolve_path(ep, msg, id); + else + return dsap_resolve_dest(ep, msg, id); +} + +static int dsap_query(void *addr_context, struct acm_msg *msg, uint64_t id) +{ + struct dsap_addr *address = addr_context; + struct dsap_ep *ep = address->ep; + uint8_t status = ACM_STATUS_SUCCESS; + struct ibv_path_record *path; + struct ibv_path_record query; + + acm_log(2, "\n"); + + acm_increment_counter(ACM_CNTR_ROUTE_QUERY); + ep->counters[ACM_CNTR_ROUTE_QUERY]++; + /* If we have not opened libopasadb previously, do it now */ + if (!ep->port->lib_handle) { + ep->port->lib_handle = + op_path_open(ep->port->dev->device->verbs->device, + ep->port->port->port_num); + if (!ep->port->lib_handle) { + acm_log(0, "Error -- Failed to open libopasadb\n"); + status = ACM_STATUS_ENODATA; + goto resp; + } + } + + path = &msg->resolve_data[0].info.path; + memcpy(&query, path, sizeof(query)); + if (op_path_get_path_by_rec(ep->port->lib_handle, + (op_path_rec_t *) &query, + (op_path_rec_t *) path)) { + acm_log(0, "Error -- Failed to get path record\n"); + status = ACM_STATUS_ENODATA; + } + +resp: + msg->hdr.opcode |= ACM_OP_ACK; + msg->hdr.status = status; + if (status == ACM_STATUS_ENODATA) + ep->counters[ACM_CNTR_NODATA]++; + else if (status) + ep->counters[ACM_CNTR_ERROR]++; + return acm_query_response(id, msg); +} + +static int dsap_handle_event(void *port_context, enum ibv_event_type type) +{ + struct dsap_port *port = port_context; + union ibv_gid gid; + + acm_log(2, "Event %d\n", type); + + /* Only some events are passed to us */ + switch (type) + { + case IBV_EVENT_CLIENT_REREGISTER: + if (dsap_notification_reregister_port(port) != FSUCCESS) { + acm_log(0, "Failed to re-register port %s/%d for " + "notification\n", + port->dev->device->verbs->device->name, + port->port->port_num); + return -1; + } + acm_get_gid((struct acm_port *) port->port, 0, &gid); + dsap_port_event(gid.global.interface_id, + gid.global.subnet_prefix, + gid.global.interface_id, + DSAP_PT_EVT_FULL_RESCAN); + break; + case IBV_EVENT_SM_CHANGE: + acm_get_gid((struct acm_port *) port->port, 0, &gid); + dsap_port_event(gid.global.interface_id, + gid.global.subnet_prefix, + gid.global.interface_id, + DSAP_PT_EVT_FULL_RESCAN); + break; + default: + /* Ignore */ + break; + } + return 0; +} + +static void dsap_query_perf(void *ep_context, uint64_t *values, uint8_t *cnt) +{ + struct dsap_ep *ep = ep_context; + int i; + + for (i = 0; i < ACM_MAX_COUNTER; i++) + values[i] = hton64(ep->counters[i]); + *cnt = ACM_MAX_COUNTER; +} + +static void dsap_parse_hosts_file(void) +{ + FILE *f; + char s[120]; + char addr[INET6_ADDRSTRLEN], gid[INET6_ADDRSTRLEN]; + uint8_t name[ACM_MAX_ADDRESS]; + struct in6_addr ip_addr, ib_addr; + struct dsap_dest *dest; + uint8_t addr_type; + + if (!(f = fopen(addr_data_file, "r"))) { + acm_log(0, "ERROR - couldn't open %s\n", addr_data_file); + return; + } + + while (fgets(s, sizeof s, f)) { + if (s[0] == '#') + continue; + + if (sscanf(s, "%46s%46s", addr, gid) != 2) + continue; + + acm_log(2, "%s", s); + if (inet_pton(AF_INET6, gid, &ib_addr) <= 0) { + acm_log(0, "ERROR - %s is not IB GID\n", gid); + continue; + } + memset(name, 0, ACM_MAX_ADDRESS); + if (inet_pton(AF_INET, addr, &ip_addr) > 0) { + addr_type = ACM_ADDRESS_IP; + memcpy(name, &ip_addr, 4); + } else if (inet_pton(AF_INET6, addr, &ip_addr) > 0) { + addr_type = ACM_ADDRESS_IP6; + memcpy(name, &ip_addr, sizeof(ip_addr)); + } else { + addr_type = ACM_ADDRESS_NAME; + strncpy((char *)name, addr, ACM_MAX_ADDRESS); + } + + dest = dsap_acquire_dest(addr_type, name); + if (!dest) { + acm_log(0, "ERROR - unable to create dest %s\n", addr); + continue; + } + memcpy(&dest->gid, &ib_addr, sizeof(ib_addr)); + + acm_log(1, "added host %s address type %d IB GID %s\n", + addr, addr_type, gid); + } + + fclose(f); +} + +void dsap_free_map_node(void *nodep) +{ + struct dsap_dest *dest = nodep; + + free(dest); +} + +static void dsap_remove_mapping(void) +{ + int i; + + for (i = 0; i < (ACM_ADDRESS_RESERVED - 1); i++) { + if (dest_map[i]) + tdestroy(dest_map[i], dsap_free_map_node); + } +} + +/* Get ibacm configuration options related to dist_sap */ +static void dsap_set_options(void) +{ + FILE *f; + char s[120]; + char opt[32], value[256]; + const char *opts_file = acm_get_opts_file(); + + if (!(f = fopen(opts_file, "r"))) + return; + + while (fgets(s, sizeof s, f)) { + if (s[0] == '#') + continue; + + memset(opt, 0, 32); + memset(value, 0, 256); + if (sscanf(s, "%32s%256s", opt, value) != 2) + continue; + + if (!strcasecmp("dsap_conf_file", opt)) { + strncpy(config_file, value, 127); + config_file[127] = '\0'; + } + else if (!strcasecmp("addr_data_file", opt)) { + strncpy(addr_data_file, value, 127); + addr_data_file[127] = '\0'; + } + } + + fclose(f); +} + +static void dsap_log_options(void) +{ + acm_log(0, "dsap config file %s\n", config_file); + acm_log(0, "address data file %s\n", addr_data_file); +} + +static void __attribute__((constructor)) dsap_prov_init(void) +{ + int i; + + dsap_set_options(); + dsap_log_options(); + dsap_get_config(config_file); + + QListInitState(&dsap_dev_list); + QListInit(&dsap_dev_list); + SpinLockInitState(&dsap_dev_lock); + SpinLockInit(&dsap_dev_lock); + for (i = 0; i < (ACM_ADDRESS_RESERVED - 1); i++) + dest_map[i] = NULL; + + if (dsap_init()) + return; + dsap_parse_hosts_file(); + dsap_initialized = 1; +} + +static void __attribute__((destructor)) dsap_prov_exit(void) +{ + acm_log(1, "Unloading...\n"); + + dsap_remove_mapping(); + dsap_cleanup(); + + dsap_initialized = 0; +} + +int provider_query(struct acm_provider **provider, uint32_t *version) +{ + acm_log(1, "\n"); + + if (!dsap_initialized) + return -1; + + if (provider) + *provider = &def_prov; + if (version) + *version = 1; + + return 0; +} + +/* Get the provider port and hold the port lock. The caller + must call dsap_release_prov_port() to release the port + lock if this call succeeds */ +struct dsap_port * dsap_lock_prov_port(dsap_src_port_t *src_port) +{ + LIST_ITEM * dev_item; + struct dsap_device *dev; + struct dsap_port *port = NULL; + int i; + union ibv_gid gid; + + acm_log(2, "port %s/%d\n", src_port->hfi_name, src_port->port_num); + + /* Protect against device close */ + SpinLockAcquire(&dsap_dev_lock); + for_each(&dsap_dev_list, dev_item) { + dev = QListObj(dev_item); + + for (i = 0; i < dev->port_cnt; i++) { + port = &dev->port[i]; + SpinLockAcquire(&port->lock); + if (port->state != IBV_PORT_ACTIVE) + goto next_port; + if (acm_get_gid((struct acm_port *) port->port, 0, + &gid)) + goto next_port; + if (!memcmp(&gid, &src_port->gid, sizeof(gid))) + goto get_exit; + next_port: + SpinLockRelease(&port->lock); + port = NULL; + } + } +get_exit: + SpinLockRelease(&dsap_dev_lock); + + return port; +} + +void dsap_release_prov_port(struct dsap_port *port) +{ + acm_log(2, "port %s/%d\n", port->dev->device->verbs->device->name, + port->port->port_num); + + SpinLockRelease(&port->lock); +} + +FSTATUS dsap_add_src_ports(void) +{ + FSTATUS rval = FSUCCESS; + LIST_ITEM * dev_item; + struct dsap_device *dev; + struct dsap_port *port; + int i; + + acm_log(2, "\n"); + + /* Protect against device close */ + SpinLockAcquire(&dsap_dev_lock); + for_each(&dsap_dev_list, dev_item) { + dev = QListObj(dev_item); + + for (i = 0; i < dev->port_cnt; i++) { + port = &dev->port[i]; + SpinLockAcquire(&port->lock); + if (dev->port[i].state != IBV_PORT_ACTIVE) + goto next_port; + + rval = dsap_add_src_port(port); + if (rval != FSUCCESS) { + SpinLockRelease(&port->lock); + goto src_exit; + } + next_port: + SpinLockRelease(&port->lock); + } + } +src_exit: + SpinLockRelease(&dsap_dev_lock); + + return rval; +} diff --git a/Dsap/src/dsap_query.c b/Dsap/src/dsap_query.c new file mode 100644 index 0000000..ba2c128 --- /dev/null +++ b/Dsap/src/dsap_query.c @@ -0,0 +1,689 @@ +/* BEGIN_ICS_COPYRIGHT4 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT4 ****************************************/ +/*! + + \file dsap_query.c + + \brief Various functions for querying SA. +*/ + +/* work around conflicting names */ +#include +#include + +#include "iba/ibt.h" +#include "iba/stl_sd.h" +#include "iba/public/ievent.h" +#include "iba/public/ilist.h" +#include "opasadb_debug.h" +#include "dsap.h" +#include "opamgt_sa_priv.h" + +#include + +#define PATHRECORD_NUMBPATH 127 /* max to request */ + +static FSTATUS dsap_check_query_results(PQUERY_RESULT_VALUES res) +{ + acm_log(2, "\n"); + + if (res == NULL) { + acm_log(1, "NULL query results returned!\n"); + return FERROR; + } + + if (res->Status != FSUCCESS) { + acm_log(1, "SA Query Returned Failed status = %s(%d)\n", + FSTATUS_MSG(res->Status), + res->Status); + return res->Status; + } + + if (res->ResultDataSize == 0) { + acm_log(1, "SA Query Returned no data!\n"); + return FNOT_FOUND; + } + + if (res->QueryResult == NULL) { + acm_log(1, "SA Query Returned no result data!\n"); + return FNOT_FOUND; + } + + return FSUCCESS; +} + +static inline void dump_path_record(IB_PATH_RECORD_NO *path, int byte_order) +{ +#if defined(ICSDEBUG) + char gid_str[INET6_ADDRSTRLEN]; + char gid_str2[INET6_ADDRSTRLEN]; + + if (byte_order) { + acm_log(2, "Path SGID(%s) SLID(0x%x) to \n\t\tDGID(%s) " + "DLID(0x%x) SID(0x%016" PRIx64 ") PKEY(0x%x)\n", + inet_ntop(AF_INET6, path->SGID.Raw, gid_str2, + sizeof gid_str2), + ntohs(path->SLID), + inet_ntop(AF_INET6, path->DGID.Raw, gid_str, + sizeof gid_str), + ntohs(path->DLID), + ntoh64(path->ServiceID), + ntohs(path->P_Key)); + } else { + acm_log(2, "Query SGID(%"PRIx64":%"PRIx64") SLID(0x%x) to \n\t\tDGID" + "(%"PRIx64":%"PRIx64") DLID(0x%x) SID(0x%016" PRIx64 ") " + "PKEY(0x%x)\n", + path->SGID.Type.Global.InterfaceID, + path->SGID.Type.Global.SubnetPrefix, + path->SLID, + path->DGID.Type.Global.InterfaceID, + path->DGID.Type.Global.SubnetPrefix, + path->DLID, + path->ServiceID, + path->P_Key); + } +#endif +} + + +static FSTATUS dsap_process_path_records_query_results( + dsap_src_port_t *src_port, PPATH_RESULTS res) +{ + FSTATUS rval = FSUCCESS; + unsigned i; + IB_PATH_RECORD_NO *path_record; + + acm_log(2, "\n"); + + if (res->NumPathRecords == 0) { + rval = FNOT_FOUND; + goto exit; + } + + for (i = 0, path_record = (IB_PATH_RECORD_NO*) res->PathRecords; + i < res->NumPathRecords; i++, path_record++) { + dump_path_record(path_record, 1); + rval = dsap_add_path_record(src_port, path_record); + if (rval != FSUCCESS) + break; + } + +exit: + return rval; +} + + +FSTATUS dsap_query_path_records(dsap_src_port_t *src_port, + dsap_dst_port_t *dst_port, + uint64_t sid, uint16_t pkey) +{ + FSTATUS rval = FNOT_FOUND; + OMGT_QUERY query; + PQUERY_RESULT_VALUES res = NULL; + struct dsap_port *port; + + acm_log(2, "\n"); + + /* While the mask prevents unused fields from being used in the query, + this will still help when trying to dump or debug paths. */ + memset(&query,0,sizeof(OMGT_QUERY)); + + /* Get ALL Paths between ports using Local and Remote Port GIDs */ + query.InputType = InputTypePathRecord; + query.OutputType = OutputTypePathRecordNetworkOrder; + query.InputValue.IbPathRecord.PathRecord.ComponentMask = + IB_PATH_RECORD_COMP_SERVICEID | + IB_PATH_RECORD_COMP_DGID | + IB_PATH_RECORD_COMP_SGID | + IB_PATH_RECORD_COMP_PKEY | + IB_PATH_RECORD_COMP_REVERSIBLE | + IB_PATH_RECORD_COMP_NUMBPATH; + query.InputValue.IbPathRecord.PathRecord.PathRecord.DGID.Type.Global.SubnetPrefix = + ntoh64(dst_port->gid.global.subnet_prefix); + query.InputValue.IbPathRecord.PathRecord.PathRecord.DGID.Type.Global.InterfaceID = + ntoh64(dst_port->gid.global.interface_id); + query.InputValue.IbPathRecord.PathRecord.PathRecord.SGID.Type.Global.SubnetPrefix = + ntoh64(src_port->gid.global.subnet_prefix); + query.InputValue.IbPathRecord.PathRecord.PathRecord.SGID.Type.Global.InterfaceID = + ntoh64(src_port->gid.global.interface_id); + query.InputValue.IbPathRecord.PathRecord.PathRecord.ServiceID = ntoh64(sid); + query.InputValue.IbPathRecord.PathRecord.PathRecord.P_Key = ntohs(pkey ) & 0x7fff; + query.InputValue.IbPathRecord.PathRecord.PathRecord.Reversible = 1; + query.InputValue.IbPathRecord.PathRecord.PathRecord.NumbPath = PATHRECORD_NUMBPATH; + + dump_path_record( + (IB_PATH_RECORD_NO *) &query.InputValue.IbPathRecord.PathRecord.PathRecord, + 0); + + port = dsap_lock_prov_port(src_port); + if (!port) + return rval; + if (!port->omgt_handle) { + goto query_exit; + } + + rval = omgt_query_sa(port->omgt_handle, &query, &res); + if (rval == FSUCCESS) { + rval = dsap_check_query_results(res); + if (rval == FSUCCESS) { + if (res->MadStatus == MAD_STATUS_BUSY) { + rval = FBUSY; + } else { + rval = dsap_process_path_records_query_results( + src_port, + (PPATH_RESULTS)res->QueryResult); + } + } + } + + if (rval == FNOT_FOUND) { + /* Not found is acceptable here, because we may be querying + for a vfab the destination isn't a member of. */ + rval = FSUCCESS; + } else if (rval != FSUCCESS) { + acm_log(0, "Path query failed! Error code = %d (%d)\n", + rval, (res) ? res->MadStatus : 0); + } + + if ((res != NULL) && (res->QueryResult != NULL)) + omgt_free_query_result_buffer(res); + +query_exit: + dsap_release_prov_port(port); + + return rval; +} + +static FSTATUS +dsap_process_dst_ports_query_results(dsap_subnet_t *subnet, + PNODE_RECORD_RESULTS res) +{ + FSTATUS rval = FSUCCESS; + unsigned i; + union ibv_gid dst_port_gid; + + acm_log(2, "\n"); + + if (res->NumNodeRecords == 0) { + rval = FNOT_FOUND; + goto exit; + } + + for (i = 0; i < res->NumNodeRecords; i++) { + dst_port_gid.global.subnet_prefix = subnet->subnet_prefix; + dst_port_gid.global.interface_id = + hton64(res->NodeRecords[i].NodeInfoData.PortGUID); + + rval = dsap_add_dst_port( + &dst_port_gid, res->NodeRecords[i].NodeInfoData.NodeType, + (char *)res->NodeRecords[i].NodeDescData.NodeString); + if (rval != FSUCCESS) { + acm_log(0, "Failed to add destination port 0x%"PRIx64"\n", + res->NodeRecords[i].NodeInfoData.PortGUID); + break; + } + } + +exit: + return rval; +} + + +FSTATUS dsap_query_dst_ports(dsap_subnet_t *subnet) +{ + FSTATUS rval = FNOT_FOUND; + LIST_ITEM *item; + OMGT_QUERY query; + PQUERY_RESULT_VALUES res = NULL; + dsap_src_port_t *src_port; + struct dsap_port *port; + + acm_log(2, "\n"); + + query.InputType = InputTypeNoInput; + query.OutputType = OutputTypeNodeRecord; + + for_each (&subnet->src_port_list, item) { + src_port = QListObj(item); + + port = dsap_lock_prov_port(src_port); + if (!port) { + acm_log(1, "src_port %s/%d not available\n", + src_port->hfi_name, src_port->port_num); + continue; + } + if (!port->omgt_handle) { + acm_log(1, "no opamgt port handle for port %s/%d\n", + port->dev->device->verbs->device->name, + port->port->port_num); + goto next_src_port; + } + + if ((rval = omgt_query_sa(port->omgt_handle, &query, &res)) == + FSUCCESS) { + dsap_release_prov_port(port); + break; + } + + if ((res != NULL) && (res->QueryResult != NULL)) { + omgt_free_query_result_buffer(res); + res = NULL; + } + + next_src_port: + dsap_release_prov_port(port); + } + + if (rval != FSUCCESS || res == NULL) { + acm_log(1, "dst_port query failed\n"); + return rval; + } + + rval = dsap_check_query_results(res); + if (rval == FSUCCESS) { + if (res->MadStatus == MAD_STATUS_BUSY) { + rval = FBUSY; + } else { + rval = dsap_process_dst_ports_query_results( + subnet, + (PNODE_RECORD_RESULTS)res->QueryResult); + } + } + + if ((res != NULL) && (res->QueryResult != NULL)) + omgt_free_query_result_buffer(res); + + return rval; +} + +static FSTATUS +dsap_add_service_id_range_to_virtual_fabric( + dsap_subnet_t *subnet, + dsap_service_id_range_t *sid_range, + uint8_t *vf_name) +{ + FSTATUS rval; + dsap_virtual_fabric_t *vfab = + dsap_find_virtual_fabric(vf_name, subnet); + + acm_log(2, "\n"); + + if (vfab) { + rval = dsap_add_service_id_record(vfab, sid_range); + if (rval == FSUCCESS) { + if (sid_range->upper_service_id == 0) { + acm_log(1, "Added sid 0x%"PRIx64" to vfab " + "%s\n", + ntoh64(sid_range->lower_service_id), + vf_name); + } else { + acm_log(1, "Added sid range 0x%"PRIx64"..0x%" + PRIx64" to vfab %s.\n", + ntoh64(sid_range->lower_service_id), + ntoh64(sid_range->upper_service_id), + vf_name); + } + } else if (rval == FDUPLICATE) { + rval = FSUCCESS; + } else { + acm_log(0, "Unable to add sid record to vfab %s.\n", + vf_name); + } + + return rval; + } + + return FNOT_FOUND; +} + +static FSTATUS +dsap_process_service_id_range_and_virtual_fabric( + dsap_subnet_t *subnet, + dsap_service_id_range_t *sid_range, + STL_VFINFO_RECORD *rec) +{ + LIST_ITEM *src_port_item; + FSTATUS rval; + LIST_ITEM *pkey_item; + dsap_src_port_t *src_port; + dsap_pkey_t *pkey; + + acm_log(2, "\n"); + + /* Does it already exist? Just add the service id record */ + if (dsap_add_service_id_range_to_virtual_fabric( + subnet, sid_range, rec->vfName) == FSUCCESS) + return FSUCCESS; + + /* Find matching PKEY */ + for_each (&subnet->src_port_list, src_port_item) { + src_port = QListObj(src_port_item); + + for_each (&src_port->pkey_list, pkey_item) { + pkey = QListObj(pkey_item); + /* Mask off the high bit (fields are in network byte + order....) */ + if ((pkey->pkey & 0xff7f) != (rec->pKey & 0xff7f)) + continue; + + rval = dsap_add_virtual_fabric(subnet, rec); + if (rval != FSUCCESS) + return rval; + + return dsap_add_service_id_range_to_virtual_fabric( + subnet, sid_range, rec->vfName); + } + } + + if (!sid_range->warned) { + sid_range->warned=1; + if (sid_range->upper_service_id == 0) { + acm_log(1, "Sid 0x%"PRIx64" does not match any vfab " + "that this node is a member of.\n", + hton64(sid_range->lower_service_id)); + } else { + acm_log(1, "Sid range 0x%"PRIx64"-0x%"PRIx64" does " + "not match any vfab that this node is a " + "member of.\n", + hton64(sid_range->lower_service_id), + hton64(sid_range->upper_service_id)); + } + } + + return FNOT_FOUND; +} + +static FSTATUS dsap_process_vfinfo_record_query_results( + dsap_subnet_t *subnet, dsap_service_id_range_t *sid_range, + PSTL_VFINFO_RECORD_RESULTS res) +{ + FSTATUS rval = FNOT_FOUND; + unsigned i; + unsigned result_index; + uint16_t vf_index; + + acm_log(2, "\n"); + + if (res->NumVfInfoRecords == 0) + return rval; + + if (res->NumVfInfoRecords == 1) { + /* Swap the vfinfo record back to network order */ + BSWAP_STL_VFINFO_RECORD(&res->VfInfoRecords[0]); + if (dsap_default_fabric != DSAP_DEF_FAB_ACT_NONE) + goto process_res; + + /* Mask off the high bit (fields in network byte + order...) */ + if ((res->VfInfoRecords[0].pKey & 0xff7f) == 0xff7f && + !sid_range->warned) { + sid_range->warned = 1; + if (sid_range->upper_service_id == 0) { + acm_log(1, "Found sid of 0x%016"PRIx64" in " + "default/admin vfab only. However, " + "it is not configured for use. " + "Check your configuration.\n", + ntoh64(sid_range->lower_service_id)); + } else { + acm_log(1, "Found sid range of 0x%016"PRIx64 + "..0x%016"PRIx64" in default/admin" + " virtual fabric only. However, it " + "is not configured for use. Check " + "your configuration.\n", + ntoh64(sid_range->lower_service_id), + ntoh64(sid_range->upper_service_id)); + } + } + return rval; + + process_res: + return dsap_process_service_id_range_and_virtual_fabric( + subnet, sid_range, &res->VfInfoRecords[0]); + } + + if (sid_range->upper_service_id == 0 && !sid_range->warned) { + sid_range->warned=1; + acm_log(1, "Found %d vfab with a sid of 0x%016"PRIx64". " + "Check your configuration. Only using first " + "non-default vfab found.\n", + res->NumVfInfoRecords, + ntoh64(sid_range->lower_service_id)); + } else if (!sid_range->warned) { + sid_range->warned=1; + acm_log(1, "Found %d vfab with a sid range of 0x%016"PRIx64".." + "0x%016"PRIx64". Check your configuration. Only " + "using first non-default vfab found.\n", + res->NumVfInfoRecords, + ntoh64(sid_range->lower_service_id), + ntoh64(sid_range->upper_service_id)); + } + + for (i = 0, result_index = res->NumVfInfoRecords, vf_index = 0xffff; + i < res->NumVfInfoRecords; i++) { + /* Swap the vfinfo record back to network order */ + BSWAP_STL_VFINFO_RECORD(&res->VfInfoRecords[i]); + /* + * Mask off the high bit (fields are in network byte order...) + */ + if ((res->VfInfoRecords[i].pKey & 0xff7f) == 0xff7f) { + if (sid_range->upper_service_id == 0) { + acm_log(1, "Ignoring sid 0x%016"PRIx64" on " + "default vfab %s.\n", + ntoh64(sid_range->lower_service_id), + res->VfInfoRecords[i].vfName); + } else { + acm_log(1, "Ignoring sid range 0x%016"PRIx64 + "..0x%016"PRIx64" on default vfab " + "%s.\n", + ntoh64(sid_range->lower_service_id), + ntoh64(sid_range->upper_service_id), + res->VfInfoRecords[i].vfName); + } + continue; + } + + if (vf_index > res->VfInfoRecords[i].vfIndex) { + vf_index = res->VfInfoRecords[i].vfIndex; + result_index = i; + } + } + + if (result_index < res->NumVfInfoRecords) { + rval = dsap_process_service_id_range_and_virtual_fabric( + subnet, sid_range, &res->VfInfoRecords[result_index]); + + return rval; + } + + if (sid_range->upper_service_id == 0) { + acm_log(0, "Internal error for sid 0x%016"PRIx64".\n", + ntoh64(sid_range->lower_service_id)); + } else { + acm_log(0, "Internal error for sid range 0x%016"PRIx64 + "..0x%016"PRIx64".\n", + ntoh64(sid_range->lower_service_id), + ntoh64(sid_range->upper_service_id)); + } + + return FNOT_FOUND; +} + +FSTATUS dsap_query_vfinfo_records(dsap_subnet_t *subnet, + dsap_service_id_range_t *sid_range) +{ + FSTATUS rval = FNOT_FOUND; + FSTATUS status = FNOT_FOUND; + LIST_ITEM *item; + OMGT_QUERY query; + PQUERY_RESULT_VALUES res = NULL; + dsap_src_port_t *src_port; + struct dsap_port *port; + + acm_log(2, "\n"); + + query.InputType = InputTypeServiceId; + query.InputValue.VfInfoRecord.ServiceId = ntoh64(sid_range->lower_service_id); + query.OutputType = OutputTypeStlVfInfoRecord; + + for_each (&subnet->src_port_list, item) { + src_port = QListObj(item); + port = dsap_lock_prov_port(src_port); + if (!port) + continue; + if (!port->omgt_handle) + goto next_src_port; + + rval = omgt_query_sa(port->omgt_handle, &query, &res); + if (rval != FSUCCESS) + goto next_src_port; + + rval = dsap_check_query_results(res); + if (rval != FSUCCESS) + goto free_result; + + if (res->MadStatus == MAD_STATUS_BUSY) { + rval = FBUSY; + } else { + rval = dsap_process_vfinfo_record_query_results( + subnet, sid_range, + (PSTL_VFINFO_RECORD_RESULTS)res->QueryResult); + sid_range->warned = 0; + } + + if (rval == FSUCCESS) + status = FSUCCESS; + + free_result: + if ((res != NULL) && (res->QueryResult != NULL)) { + omgt_free_query_result_buffer(res); + res = NULL; + } + next_src_port: + dsap_release_prov_port(port); + } + + if (status == FNOT_FOUND && !sid_range->warned) { + sid_range->warned=1; + if (sid_range->upper_service_id == 0) { + acm_log(1, "Could not match SID 0x%016"PRIx64" to any " + "vfab visible on subnet 0x%016"PRIx64".\n", + ntoh64(sid_range->lower_service_id), + ntoh64(subnet->subnet_prefix)); + } else { + acm_log(1, "Could not match SID range 0x%016"PRIx64" - 0x%016"PRIx64 + " to any vfab visible on subnet 0x%016" + PRIx64".\n", + ntoh64(sid_range->lower_service_id), + ntoh64(sid_range->upper_service_id), + ntoh64(subnet->subnet_prefix)); + } + } + + return rval; +} + +FSTATUS dsap_query_dst_port(union ibv_gid *dst_gid, NODE_TYPE *node_type, + char *node_desc) +{ + FSTATUS rval = FNOT_FOUND; + LIST_ITEM *item; + OMGT_QUERY query; + PQUERY_RESULT_VALUES res = NULL; + dsap_subnet_t *subnet; + PNODE_RECORD_RESULTS rec; + dsap_src_port_t *src_port; + struct dsap_port *port; + + acm_log(2, "\n"); + + query.InputType = InputTypePortGuid; + query.InputValue.IbNodeRecord.PortGUID = ntoh64(dst_gid->global.interface_id); + query.OutputType = OutputTypeNodeRecord; + subnet = dsap_find_subnet((uint64_t *)&dst_gid->global.subnet_prefix); + + if (subnet == NULL) + return rval; + + for_each (&subnet->src_port_list, item) { + src_port = QListObj(item); + + port = dsap_lock_prov_port(src_port); + if (!port) + continue; + if (!port->omgt_handle) + goto next_src_port; + + if ((rval = omgt_query_sa(port->omgt_handle, &query, + &res)) == FSUCCESS) { + dsap_release_prov_port(port); + break; + } + if ((res != NULL) && (res->QueryResult != NULL)) { + omgt_free_query_result_buffer(res); + res = NULL; + } + next_src_port: + dsap_release_prov_port(port); + } + + if (rval != FSUCCESS || res == NULL) + return rval; + + rval = dsap_check_query_results(res); + if (rval != FSUCCESS) + goto exit; + + if (res->MadStatus == MAD_STATUS_BUSY) { + rval = FBUSY; + goto exit; + } + + rec = (PNODE_RECORD_RESULTS)res->QueryResult; + + if (rec->NumNodeRecords == 0) { + rval = FNOT_FOUND; + goto exit; + } + + if (rec->NumNodeRecords != 1) { + rval = FERROR; + goto exit; + } + *node_type = rec->NodeRecords[0].NodeInfoData.NodeType; + memcpy(node_desc, + rec->NodeRecords[0].NodeDescData.NodeString, + NODE_DESCRIPTION_ARRAY_SIZE); + +exit: + if ((res != NULL) && (res->QueryResult != NULL)) + omgt_free_query_result_buffer(res); + + return rval; +} + diff --git a/Dsap/src/dsap_scan_fabric.c b/Dsap/src/dsap_scan_fabric.c new file mode 100644 index 0000000..0931c5a --- /dev/null +++ b/Dsap/src/dsap_scan_fabric.c @@ -0,0 +1,1107 @@ +/* BEGIN_ICS_COPYRIGHT4 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT4 ****************************************/ + +#include +#include +#include + +/* work around conflicting names */ +#include +#include + +#include "iba/public/ilist.h" +#include "iba/public/ievent.h" +#include "iba/public/ispinlock.h" +#include "iba/public/itimer.h" +#include "opasadb_path_private.h" +#include "opasadb_debug.h" +#include "dsap_topology.h" +#include "dsap_notifications.h" +#include "dsap.h" + +static int dsap_scanner_end = 0; + +uint32 dsap_scan_frequency = 600; /* in secconds */ +uint32 dsap_unsub_scan_frequency = 10; /* in secconds */ +boolean dsap_publish = 1; +uint32 dsap_default_fabric = DSAP_DEF_FAB_ACT_NORMAL; + +static pthread_t dsap_scanner_thread; +static int dsap_scanner_rescan = 0; +static SPIN_LOCK dsap_scanner_lock; +static EVENT dsap_scanner_event; /* wakes up scanner thread to do + another scan */ + +#define SCAN_RING_SIZE 512 /* Must be power of 2 */ +static struct dsap_scan_port { + uint64 src_guid; + uint64 src_subnet; + uint64 dest_guid; + port_event_type_t event_type; +} dsap_scan_port_ring[SCAN_RING_SIZE]; +static int scan_ring_put = 0; +static int scan_ring_take = 0; + +static op_ppath_writer_t shared_memory_writer; + +struct sigaction new_action, old_action; + +static char *port_event[] = { + "Source Port Up", + "Source Port Down", + "Destination Port Up", + "Destination Port Down", + "Port Scan Request", + "Complete Fabric Scan Request" +}; + +int dsap_default_fabric_parser(char *str, void *ptr) +{ + int err = 0; + + if (!str || !ptr) { + acm_log(0, "Bad arguments to default fabric parser.\n"); + err = EINVAL; + goto exit; + } + + if (strcmp(str, "none") == 0) { + dsap_default_fabric = DSAP_DEF_FAB_ACT_NONE; + goto exit; + } + + if (strcmp(str, "normal") == 0) { + dsap_default_fabric = DSAP_DEF_FAB_ACT_NORMAL; + goto exit; + } + + if (strcmp(str, "all") == 0) { + dsap_default_fabric = DSAP_DEF_FAB_ACT_ALL; + goto exit; + } + + acm_log(0, "Invalid value (%s) specified for dsap_default_fabric.\n", + str); + err = EINVAL; + +exit: + return err; +} + +char * dsap_default_fabric_printer(void *ptr) +{ + switch (dsap_default_fabric) { + case DSAP_DEF_FAB_ACT_NONE: + return "none"; + + case DSAP_DEF_FAB_ACT_NORMAL: + return "normal"; + + case DSAP_DEF_FAB_ACT_ALL: + return "all"; + + default: + return "UNKNOWN"; + } +} + +/*----------------------------------------------------------- + * Wait for an event - this event is NOT interruptible + *----------------------------------------------------------- +*/ +static FSTATUS +EventWaitOnSeconds( EVENT *pEvent, int32 wait_seconds) +{ + FSTATUS status = FERROR; + int retval; + + /* Make sure that the event was started */ + ASSERT (pEvent->ev_state == Started); + + /* + Don't wait if the it has been signaled already! + */ + pthread_mutex_lock( &pEvent->ev_mutex ); + if (pEvent->ev_signaled == TRUE) { + /* autoclear */ + pEvent->ev_signaled = FALSE; + + pthread_mutex_unlock(&pEvent->ev_mutex); + return FSUCCESS; + } + + if (wait_seconds == EVENT_NO_TIMEOUT) { + wait_seconds = 0; + /* Wait for condition variable ev_condvar to be signaled or + broadcast. */ + pthread_cond_wait(&pEvent->ev_condvar,&pEvent->ev_mutex); + + pEvent->ev_signaled = FALSE; + pthread_mutex_unlock(&pEvent->ev_mutex); + return FSUCCESS; + } else { + /* Get the current time */ + if (gettimeofday(&pEvent->ev_curtime, NULL) == 0) { + pEvent->ev_timeout.tv_sec = pEvent->ev_curtime.tv_sec + + wait_seconds; + pEvent->ev_timeout.tv_nsec = pEvent->ev_curtime.tv_usec; + + retval = pthread_cond_timedwait(&pEvent->ev_condvar, + &pEvent->ev_mutex, + &pEvent->ev_timeout); + if (retval == ETIMEDOUT) { + status = FTIMEOUT; + } else { + /* We got signalled */ + status = FSUCCESS; + } + } + pEvent->ev_signaled = FALSE; + pthread_mutex_unlock(&pEvent->ev_mutex); + return status; + } +} + +/* + * Returns the number of published paths. + */ +uintn dsap_publish_paths(void) +{ + int err; + uintn i; + uintn count=0; + uintn subnet_count=0; + uint32 port_count; + dsap_subnet_t *subnet; + LIST_ITEM *vf_item; + dsap_virtual_fabric_t *vfab; + LIST_ITEM *sid_item; + dsap_service_id_record_t *record; + LIST_ITEM *sport_item; + int j; + dsap_src_port_t *sport; + LIST_ITEM *path_item; + LIST_ITEM *pkey_item; + op_ppath_port_record_t op_port; + dsap_pkey_t *pkey; + dsap_path_record_t *path; + + acm_log(2, "\n"); + + subnet_count = dsap_subnet_count(); + if (subnet_count == 0) { + acm_log(0, "No subnets to publish.\n"); + goto exit; + } + + /* + * We reserve one extra slot for SID 0 (i.e., no SID) + */ + err = op_ppath_initialize_subnets(&shared_memory_writer, subnet_count, + dsap_tot_sid_rec_count() + 1); + if (err) { + acm_log(0, "Failed to create the subnet table: %s.\n", + strerror(err)); + goto exit; + } + + port_count = dsap_tot_src_port_count(); + err = op_ppath_initialize_ports(&shared_memory_writer, port_count); + if (err) { + acm_log(0, "Failed to create the port table: %s.\n", + strerror(err)); + goto exit; + } + + err = op_ppath_initialize_vfabrics(&shared_memory_writer, + dsap_tot_vfab_count() + 1); + if (err) { + acm_log(0, "Failed to create the virtual fabric table: %s.\n", + strerror(err)); + goto exit; + } + + err = op_ppath_initialize_paths(&shared_memory_writer, + dsap_tot_path_rec_count()); + if (err) { + acm_log(0, "Failed to create the path table: %s.\n", + strerror(err)); + goto exit; + } + + for (i=0; i< subnet_count; i++) { + subnet = dsap_get_subnet_at(i); + if (!subnet) + continue; + vf_item = QListHead(&subnet->virtual_fabric_list); + + err = op_ppath_add_subnet(&shared_memory_writer, + subnet->subnet_prefix); + if (err) { + acm_log(0, "Failed to add subnet: %s\n", + strerror(err)); + goto exit; + } + + while (vf_item) { + vfab = QListObj(vf_item); + sid_item = QListHead(&vfab->service_id_record_list); + + err = op_ppath_add_vfab( + &shared_memory_writer, + (char *) vfab->vfinfo_record.vfName, + subnet->subnet_prefix, + vfab->vfinfo_record.pKey, + vfab->vfinfo_record.s1.slBase); + if (err) { + acm_log(0, "Failed to add vfab: %s\n", + strerror(err)); + goto exit; + } + + while (sid_item) { + record = QListObj(sid_item); + + err = op_ppath_add_sid( + &shared_memory_writer, + subnet->subnet_prefix, + record->service_id_range.lower_service_id, + record->service_id_range.upper_service_id, + (char *) vfab->vfinfo_record.vfName); + if (err) { + acm_log(0, "Failed to add SID range: " + "%s\n", + strerror(err)); + goto exit; + } + sid_item = QListNext( + &vfab->service_id_record_list, sid_item); + } + + vf_item = QListNext(&subnet->virtual_fabric_list, + vf_item); + } + + sport_item = QListHead(&subnet->src_port_list); + while (sport_item) { + sport = QListObj(sport_item); + path_item = QListHead(&sport->path_record_list); + pkey_item = QListHead(&sport->pkey_list); + + if (sport->state != IBV_PORT_ACTIVE) { + acm_log(2, "Skip inact port (0x%016"PRIx64")\n", + ntoh64(sport->gid.global.interface_id)); + sport_item = QListNext(&subnet->src_port_list, + sport_item); + continue; + } + + memset(&op_port, 0, sizeof(op_port)); + + op_port.source_prefix = + sport->gid.global.subnet_prefix; + op_port.source_guid = sport->gid.global.interface_id; + op_port.base_lid = sport->base_lid; + op_port.lmc = sport->lmc; + op_port.port = sport->port_num; + strcpy(op_port.hfi_name, sport->hfi_name); + + j=0; + while (pkey_item && j < PKEY_TABLE_LENGTH) { + pkey = QListObj(pkey_item); + op_port.pkey[j] = pkey->pkey; + j++; + + pkey_item = QListNext(&sport->pkey_list, + pkey_item); + } + + err = op_ppath_add_port(&shared_memory_writer, + op_port); + if (err) { + acm_log(0, "Failed to add port: %s\n", + strerror(err)); + goto exit; + } + + while (path_item) { + path = QListObj(path_item); + + err = op_ppath_add_path(&shared_memory_writer, + &path->path); + if (err) { + acm_log(0, "Failed to add path: %s\n", + strerror(err)); + break; + } + path_item = QListNext(&sport->path_record_list, + path_item); + count++; + } + sport_item = QListNext(&subnet->src_port_list, + sport_item); + } + } + +exit: + op_ppath_publish(&shared_memory_writer); + + _DBG_FUNC_EXIT; + return count; +} + +static void dsap_full_rescan(void) +{ + acm_log(2, "\n"); + dsap_scanner_rescan = 1; + EventTrigger(&dsap_scanner_event); +} + + +static void dsap_rescan(union ibv_gid *src_gid) +{ + acm_log(2, "\n"); + dsap_port_event(src_gid->global.interface_id, + src_gid->global.subnet_prefix, + src_gid->global.interface_id, DSAP_PT_EVT_PORT_RESCAN); +} + +static FSTATUS dsap_add_vfinfo_records(dsap_subnet_t *subnet) +{ + FSTATUS rval = FSUCCESS; + LIST_ITEM *sid_range_item; + dsap_service_id_record_t *record; + + acm_log(2, "\n"); + + for_each(&sid_range_args, sid_range_item) { + record = QListObj(sid_range_item); + + rval = dsap_query_vfinfo_records(subnet, + &record->service_id_range); + if (rval == FBUSY) + break; + if (rval == FDUPLICATE) + rval = FSUCCESS; + if (rval != FSUCCESS) { + acm_log(0, "Vfinfo query failed with status %d\n", + rval); + rval = FSUCCESS; + } + } + + return rval; +} + +static boolean dsap_pkey_match_found(dsap_src_port_t *src_port, + uint16_t vfab_pKey) +{ + LIST_ITEM *pkey_item; + dsap_pkey_t *pkey; + + acm_log(2, "\n"); + + for_each (&src_port->pkey_list, pkey_item) { + pkey = QListObj(pkey_item); + /* Mask off the high bit (fields are in network byte order) */ + if ((pkey->pkey & 0xff7f) == (vfab_pKey & 0xff7f)) + return TRUE; + } + + return FALSE; +} + +static FSTATUS dsap_for_each_service_id_record(dsap_src_port_t *src_port, + dsap_dst_port_t *dst_port, + dsap_virtual_fabric_t *vfab) +{ + FSTATUS rval = FSUCCESS; + LIST_ITEM *sid_rec_item; + dsap_service_id_record_t *sid_rec; + + acm_log(2, "\n"); + + for_each (&vfab->service_id_record_list, sid_rec_item) { + sid_rec = QListObj(sid_rec_item); + + if (dsap_scanner_end) + break; + rval = dsap_query_path_records( + src_port, dst_port, + sid_rec->service_id_range.lower_service_id, + vfab->vfinfo_record.pKey); + /* We only need to find one set of path records */ + /* So only scan until a successful set is returned */ + /* or we have exhausted all possible avenues */ + if (rval == FSUCCESS) + break; + + /* If the SM is busy retry the scan at a later time */ + /* in order to alleviate congestion.*/ + if (rval == FBUSY) + break; + } + + return rval; +} + +static FSTATUS dsap_for_each_virtual_fabric(dsap_subnet_t *subnet, + dsap_src_port_t *src_port, + dsap_dst_port_t *dst_port) +{ + FSTATUS rval = FSUCCESS; + LIST_ITEM *vfab_item; + dsap_virtual_fabric_t *vfab; + + acm_log(2, "\n"); + + for_each (&subnet->virtual_fabric_list, vfab_item) { + vfab = QListObj(vfab_item); + + if (dsap_scanner_end) + break; + + if (dsap_pkey_match_found(src_port, + vfab->vfinfo_record.pKey)) { + rval = dsap_for_each_service_id_record( + src_port, dst_port, vfab); + if (rval != FSUCCESS) + break; + } + } + + return rval; +} + +static FSTATUS dsap_for_each_dst_port(dsap_subnet_t *subnet, + dsap_src_port_t *src_port) +{ + FSTATUS rval = FSUCCESS; + LIST_ITEM *dst_port_item; + dsap_dst_port_t *dst_port; + + acm_log(2, "\n"); + + for_each (&subnet->dst_port_list, dst_port_item) { + dst_port = QListObj(dst_port_item); + + if (dsap_scanner_end) { + break; + } + + if (dst_port->node_type != STL_NODE_FI) { +#ifdef PRINT_PORTS_FOUND + acm_log(2, "Found Switch Port 0x%016"PRIx64":0x%016" + PRIx64".\n", + ntoh64(dst_port->gid.global.subnet_prefix), + ntoh64(dst_port->gid.global.interface_id)); +#endif + continue; + } + +#ifdef PRINT_PORTS_FOUND + acm_log(2, "Found HFI Port 0x%016"PRIx64":0x%016"PRIx64".\n", + ntoh64(dst_port->gid.global.subnet_prefix), + ntoh64(dst_port->gid.global.interface_id)); +#endif + rval = dsap_for_each_virtual_fabric(subnet, src_port, + dst_port); + if (rval != FSUCCESS) + break; + } + + return rval; +} + +static FSTATUS dsap_add_path_records(dsap_subnet_t *subnet) +{ + FSTATUS rval = FSUCCESS; + LIST_ITEM *src_port_item; + dsap_src_port_t *src_port; + + acm_log(2, "\n"); + + for_each (&subnet->src_port_list, src_port_item) { + src_port = QListObj(src_port_item); + + if (dsap_scanner_end) { + break; + } + + rval = dsap_for_each_dst_port(subnet, src_port); + if (rval != FSUCCESS) + break; + + acm_log(2, "Found %u path records on port 0x%016"PRIx64".\n", + (unsigned int)dsap_path_record_count(src_port), + ntoh64(src_port->gid.global.interface_id)); + } + + return rval; +} + +FSTATUS dsap_scan_subnets(void) +{ + FSTATUS rval = FERROR; + uint32_t subnet_index; + int retry_needed = 0; + int error_occurred = 0; + uint64_t prefix; + + acm_log(2, "\n"); + for (subnet_index = 0; subnet_index < dsap_subnet_count(); + subnet_index++) { + dsap_subnet_t *subnet = dsap_get_subnet_at(subnet_index); + if (!subnet) + continue; + + if (dsap_scanner_end) + break; + + if (!subnet->current) { + if (FBUSY == (rval = dsap_query_dst_ports(subnet))) { + retry_needed = 1; + continue; + } else if (rval != FSUCCESS) { + error_occurred = 1; + continue; + } else { + prefix = subnet->subnet_prefix; + acm_log(0, "Found %u dest ports for subnet " + "0x%016"PRIx64"\n", + (unsigned int)dsap_dst_port_count(subnet), + ntoh64(prefix)); + } + + rval = dsap_add_vfinfo_records(subnet); + if (rval == FBUSY) { + retry_needed = 1; + continue; + } else if (rval != FSUCCESS) { + error_occurred = 1; + continue; + } else { + prefix = subnet->subnet_prefix; + acm_log(0, "Found %u vfabs for subnet 0x%016" + PRIx64"\n", + (unsigned int)dsap_virtual_fabric_count(subnet), + ntoh64(prefix)); + } + + rval = dsap_add_path_records(subnet); + if (rval == FBUSY) { + retry_needed = 1; + continue; + } else if (rval != FSUCCESS) { + error_occurred = 1; + continue; + } else { + prefix = subnet->subnet_prefix; + acm_log(0, "Found %u paths for subnet 0x%016" + PRIx64"\n", + (unsigned int)dsap_subnet_path_record_count(subnet), + ntoh64(prefix)); + } + subnet->current = 1; + } + } + + if (error_occurred) + rval = FERROR; + else if (retry_needed) + rval = FBUSY; + else + rval = FSUCCESS; + + return rval; +} + +static boolean dsap_dst_port_up(union ibv_gid *dst_gid, union ibv_gid *src_gid) +{ + FSTATUS rval; + NODE_TYPE node_type; + char node_desc[NODE_DESCRIPTION_ARRAY_SIZE]; + dsap_subnet_t *subnet; + dsap_src_port_t *src_port; + dsap_dst_port_t *dst_port; + + acm_log(2, "\n"); + + rval = dsap_query_dst_port(dst_gid, &node_type, node_desc); + if ((rval != FSUCCESS) || (node_type != STL_NODE_FI)) { + dsap_full_rescan(); + return FALSE; + } + + rval = dsap_add_dst_port(dst_gid, node_type, node_desc); + if ((rval == FSUCCESS) || (rval == FDUPLICATE)) { + subnet = dsap_find_subnet((uint64_t *)&dst_gid->global.subnet_prefix); + src_port = dsap_find_src_port(src_gid); + dst_port = dsap_find_dst_port(dst_gid); + + dsap_remove_path_records(src_port, dst_gid); + + rval = dsap_for_each_virtual_fabric(subnet, src_port, + dst_port); + if (rval != FSUCCESS) { + dsap_rescan(src_gid); + return FALSE; + } + + return TRUE; + } + + acm_log(0, "Failure Adding Dest Port 0x%016"PRIx64":0x%016"PRIx64"\n", + ntoh64(dst_gid->global.subnet_prefix), + ntoh64(dst_gid->global.interface_id)); + + return FALSE; +} + +static boolean dsap_dst_port_down(union ibv_gid *dst_gid) +{ + dsap_dst_port_t *dst_port = dsap_find_dst_port(dst_gid); + + acm_log(2, "\n"); + + if (dst_port != NULL) { + if (dst_port->node_type != STL_NODE_FI) { + dsap_full_rescan(); + return TRUE; + } + + if (dsap_remove_dst_port(dst_gid) == FSUCCESS) + return TRUE; + } + + acm_log(1, "Unable To Remove Dst Port 0x%016"PRIx64":0x%016"PRIx64"\n", + ntoh64(dst_gid->global.subnet_prefix), + ntoh64(dst_gid->global.interface_id)); + + return FALSE; +} + +static boolean dsap_src_port_down(union ibv_gid *src_gid) +{ + acm_log(2, "\n"); + + if (dsap_remove_src_port(src_gid) == FSUCCESS) + return TRUE; + + acm_log(0, "Unable To Find Src Port 0x%016"PRIx64":0x%016"PRIx64"\n", + ntoh64(src_gid->global.subnet_prefix), + ntoh64(src_gid->global.interface_id)); + + return FALSE; +} + +static boolean dsap_src_port_up(union ibv_gid *src_gid, char *src_desc) +{ + FSTATUS rval; + dsap_src_port_t *src_port = dsap_find_src_port(src_gid); + struct dsap_port *port; + + acm_log(2, "\n"); + + if (!src_port) + return FALSE; + rval = dsap_add_dst_port(src_gid, STL_NODE_FI, + src_desc); + if ((rval == FSUCCESS) || (rval == FDUPLICATE)) { + port = dsap_lock_prov_port(src_port); + if (port != NULL) { + rval = dsap_update_src_port(src_port, port); + dsap_release_prov_port(port); + if (rval == FSUCCESS) + return TRUE; + } + } + + acm_log(0, "Unable To Locate Src Port 0x%016"PRIx64":0x%016"PRIx64"\n", + ntoh64(src_gid->global.subnet_prefix), + ntoh64(src_gid->global.interface_id)); + + dsap_full_rescan(); + + return FALSE; +} + +static boolean dsap_src_port_rescan(union ibv_gid *src_gid) +{ + dsap_subnet_t *subnet = dsap_find_subnet( + (uint64_t *)&src_gid->global.subnet_prefix); + dsap_src_port_t *src_port = dsap_find_src_port(src_gid); + FSTATUS rval; + + acm_log(2, "\n"); + + if (!subnet || !src_port) + return FALSE; + + if (dsap_src_port_up(src_gid, src_port->hfi_name) == FALSE) + return FALSE; + + rval = dsap_for_each_dst_port(subnet, src_port); + if (rval != FSUCCESS) { + dsap_rescan(src_gid); + return FALSE; + } + + return TRUE; +} + +static boolean dsap_process_port_events(void) +{ + boolean publish = FALSE; + uint64 src_guid, src_subnet, dest_guid; + port_event_type_t event_type; + union ibv_gid src_gid; + union ibv_gid dst_gid; + dsap_src_port_t *src_port; + + acm_log(2, "\n"); + + SpinLockAcquire(&dsap_scanner_lock); + + while(scan_ring_put != scan_ring_take) { + scan_ring_take++; + scan_ring_take &= (SCAN_RING_SIZE - 1); + src_guid = dsap_scan_port_ring[scan_ring_take].src_guid; + src_subnet = dsap_scan_port_ring[scan_ring_take].src_subnet; + dest_guid = dsap_scan_port_ring[scan_ring_take].dest_guid; + event_type = dsap_scan_port_ring[scan_ring_take].event_type; + SpinLockRelease(&dsap_scanner_lock); + + src_gid.global.subnet_prefix = src_subnet; + src_gid.global.interface_id = src_guid; + + dst_gid.global.subnet_prefix = src_subnet; + dst_gid.global.interface_id = dest_guid; + + switch (event_type) { + case DSAP_PT_EVT_DST_PORT_UP: + acm_log(1, "PROCESSING GID(0x%016"PRIx64") IN SERVICE" + "ON PORT 0x%016"PRIx64".\n", + ntoh64(dest_guid), ntoh64(src_guid)); + + src_port = dsap_find_src_port(&src_gid); + if (src_port == NULL) { + acm_log(0, "Unable to find src port.\n"); + dsap_full_rescan(); + break; + } + + if (dsap_dst_port_up(&dst_gid, &src_gid) == TRUE) + publish = TRUE; + break; + + case DSAP_PT_EVT_DST_PORT_DOWN: + acm_log(1, "PROCESSING GID(0x%016"PRIx64") OUT OF" + "SERVICE ON PORT 0x%016"PRIx64".\n", + ntoh64(dest_guid), + ntoh64(src_guid)); + if (dsap_dst_port_down(&dst_gid) == TRUE) + publish = TRUE; + break; + + case DSAP_PT_EVT_SRC_PORT_UP: + acm_log(1, "PROCESSING LOCAL PORT(0x%016"PRIx64") " + "ACTIVE.\n", ntoh64(src_guid)); + publish = TRUE; + dsap_scanner_rescan = 1; + break; + + case DSAP_PT_EVT_SRC_PORT_DOWN: + acm_log(1, "PROCESSING LOCAL PORT(0x%016"PRIx64") " + "DOWN.\n", ntoh64(src_guid)); + if (dsap_src_port_down(&src_gid) == TRUE) + publish = TRUE; + break; + + case DSAP_PT_EVT_PORT_RESCAN: + acm_log(1, "PROCESSING RESCAN REQUEST FOR PORT(0x%016" + PRIx64").\n", ntoh64(src_guid)); + + if (dsap_src_port_rescan(&src_gid) == TRUE) + publish = TRUE; + break; + + case DSAP_PT_EVT_FULL_RESCAN: + acm_log(1, "PROCESSING FULL FABRIC RESCAN REQUESTED BY" + " PORT(0x%016"PRIx64").\n", + ntoh64(src_guid)); + dsap_full_rescan(); + goto exit; + } + SpinLockAcquire(&dsap_scanner_lock); + } + SpinLockRelease(&dsap_scanner_lock); + +exit: + return publish; +} + +void dsap_port_event(uint64 src_guid, uint64 src_subnet, uint64 dest_guid, + port_event_type_t event_type) +{ + acm_log(2, "Port Event Src %"PRIx64":%"PRIx64", Dst %"PRIx64", %s.\n", + ntoh64(src_subnet), ntoh64(src_guid), ntoh64(dest_guid), + port_event[event_type]); + SpinLockAcquire(&dsap_scanner_lock); + scan_ring_put++; + scan_ring_put &= (SCAN_RING_SIZE - 1); + if(scan_ring_put == scan_ring_take) { + /* full ring, just do a full scan, leave ring empty as side + effect */ + dsap_scanner_rescan = 1; + } else { + dsap_scan_port_ring[scan_ring_put].src_guid = src_guid; + dsap_scan_port_ring[scan_ring_put].src_subnet = src_subnet; + dsap_scan_port_ring[scan_ring_put].dest_guid = dest_guid; + dsap_scan_port_ring[scan_ring_put].event_type = event_type; + } + SpinLockRelease(&dsap_scanner_lock); + EventTrigger(&dsap_scanner_event); +} + +static void kill_proc_handler(int signo){ + if (signo == SIGTERM) { + dsap_scanner_cleanup(); + if(sigaction(SIGTERM, &old_action, NULL) < 0) + acm_log(2, "Signal handler Restore failed \n"); + raise(SIGTERM); + } +} + +#define SCAN_DELAY 5 + +static void * dsap_scanner(void* dummy) +{ + int32 timeout_sec; + uint64 last_scan = 0; + int32 scan_delay = SCAN_DELAY; + uintn pub_count = 0; + uintn publish = 0; + FSTATUS rval; + int err; + uint64 time_stamp; + uint64 since_scan; + + acm_log(2, "\n"); + + /* Setting up signal handler to cleanup database*/ + new_action.sa_handler = kill_proc_handler; + sigemptyset (&new_action.sa_mask); + new_action.sa_flags = 0; + if(sigaction(SIGTERM, &new_action, &old_action) < 0) + acm_log(2, "Signal handler Init failed \n"); + + timeout_sec = 0; + + if (dsap_publish) { + if (op_ppath_version() != 3) { + acm_log(0, "opasadb mis-match %u. Cannot Publish.\n", + OPA_SA_DB_PATH_TABLE_VERSION); + return NULL; + } + err = op_ppath_create_writer(&shared_memory_writer); + if (err != 0) { + acm_log(0, "Failed to create shared memory tables.\n"); + return NULL; + } + } + + while (!dsap_scanner_end) { + if (dsap_process_port_events()) + publish = 1; + + if (dsap_scanner_rescan) { + acm_log(2, "Attempting Fabric Rescan.\n"); + SpinLockAcquire(&dsap_scanner_lock); + scan_ring_take = scan_ring_put; + SpinLockRelease(&dsap_scanner_lock); + + /* Don't do fabric scans more than once every + * scan_delay second(s). + */ + if ((GetTimeStamp() / 1000000) < + (last_scan + scan_delay)) { + timeout_sec = scan_delay; + acm_log(2, "Delaying Fabric Sweep By %u Sec\n", + scan_delay); + goto delay_scan; + } + + /* Set the last scan time to the last time a full scan + was started, not when it was finished. */ + last_scan = GetTimeStamp() / 1000000; + + acm_log(2, "Performing Full Fabric Sweep.\n"); + dsap_empty_subnet_list(); + + rval = dsap_add_src_ports(); + if (rval != FSUCCESS) { + /* Wait a bit before trying to add the ports + again.*/ + timeout_sec = dsap_unsub_scan_frequency; + scan_delay = dsap_unsub_scan_frequency; + goto delay_scan; + } + + acm_log(2, "After adding src ports there are %lu " + "subnets %lu total src ports\n\t\t%lu " + "total dst ports %lu total virtual " + "fabrics %lu pkeys %lu path_records.\n", + dsap_subnet_count(), + dsap_tot_src_port_count(), + dsap_tot_dst_port_count(), + dsap_tot_vfab_count(), + dsap_tot_pkey_count(), + dsap_tot_path_rec_count()); + + while (((rval = dsap_scan_subnets()) == FBUSY) && + !dsap_scanner_end) { + scan_delay = lrand48() % + dsap_unsub_scan_frequency; + timeout_sec = scan_delay; + acm_log(2, "An SM Reported Busy. Delaying " + "Fabric Scan %u Seconds.\n", + (unsigned)(scan_delay)); + EventWaitOnSeconds(&dsap_scanner_event, + timeout_sec); + } + + dsap_scanner_rescan = 0; + publish = 1; + + if (dsap_no_subscribe) + timeout_sec = dsap_unsub_scan_frequency; + else + timeout_sec = dsap_scan_frequency; + + acm_log(2, "After fabric scan there are %lu local ports" + " on %lu subnets,\n\t\t%lu destination ports," + " %lu total virtual fabrics, %lu pkeys and %lu" + " path_records.\n", + dsap_tot_src_port_count(), + dsap_subnet_count(), + dsap_tot_dst_port_count(), + dsap_tot_vfab_count(), + dsap_tot_pkey_count(), + dsap_tot_path_rec_count()); + } + + if (publish && dsap_publish) { + pub_count = dsap_publish_paths(); + acm_log(2, "Published %lu paths.\n", pub_count); + publish=0; + } + +delay_scan: + if (timeout_sec != 0) { + time_stamp = GetTimeStamp() / 1000000; + + if (time_stamp >= last_scan) { + since_scan = (time_stamp - last_scan); + } else { + /* Something or someone set the system clock + back in time */ + acm_log(2, "current time_stamp < last_scan." + "Forcing full fabric sweep\n"); + since_scan = timeout_sec; + last_scan = time_stamp; + } + + if (since_scan >= timeout_sec) { + acm_log(2, "since_scan >= timeout_sec. " + "Performing full fabric sweep.\n"); + dsap_scanner_rescan = 1; + } else { + acm_log(2, "Waiting on scanner event for %d " + "sec.\n", + (int32)(timeout_sec - since_scan)); + if (EventWaitOnSeconds( + &dsap_scanner_event, + timeout_sec - since_scan) != FSUCCESS) + dsap_scanner_rescan = 1; + } + } else { + EventWaitOnSeconds(&dsap_scanner_event, + EVENT_NO_TIMEOUT); + } + } + + return NULL; +} + +FSTATUS dsap_scanner_init(void) +{ + srand48(GetTimeStamp()); + + SpinLockInitState(&dsap_scanner_lock); + if (! SpinLockInit(&dsap_scanner_lock)) + goto faillock; + + EventInitState(&dsap_scanner_event); + if (! EventInit(&dsap_scanner_event)) + goto failsevent; + + return FSUCCESS; + +failsevent: + SpinLockDestroy(&dsap_scanner_lock); +faillock: + return FINSUFFICIENT_RESOURCES; +} + +FSTATUS dsap_scanner_start(void) +{ + int rval; + + rval = pthread_create(&dsap_scanner_thread, NULL, dsap_scanner, NULL); + + return rval ? FINSUFFICIENT_RESOURCES: FSUCCESS; +} + +void dsap_scanner_cleanup(void) +{ + acm_log(2, "\n"); + + dsap_scanner_end = 1; + EventTrigger(&dsap_scanner_event); + pthread_join(dsap_scanner_thread, NULL); + EventDestroy(&dsap_scanner_event); + SpinLockDestroy(&dsap_scanner_lock); + + acm_log(1, "Closing shared memory.\n"); + op_ppath_close_writer(&shared_memory_writer); + + + return; +} diff --git a/Dsap/src/dsap_topology.c b/Dsap/src/dsap_topology.c new file mode 100644 index 0000000..24e30f9 --- /dev/null +++ b/Dsap/src/dsap_topology.c @@ -0,0 +1,987 @@ +/* BEGIN_ICS_COPYRIGHT4 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT4 ****************************************/ + +#include +#include + +/* work around conflicting names */ +#include +#include + +#include +#include "opasadb_debug.h" +#include "dsap.h" +#include "dsap_topology.h" + +static QUICK_LIST subnet_list; + +/* Command line parsing */ +QUICK_LIST sid_range_args; +static int sid_range_args_init = 0; + +/* + * Valid formats are "SID" and "SID-SID" where "SID" + * is a 64-bit hexadecimal string. + */ +int dsap_service_id_range_parser(char *str, void *ptr) +{ + uint64 lower, upper; + dsap_service_id_record_t *record; + int err = 0; + char *k=0; + + if (!str || !ptr) { + acm_log(0, "Bad arguments to sid parser.\n"); + err = EINVAL; + goto exit; + } + + if (sid_range_args_init == 0) { + sid_range_args_init = QListInit(&sid_range_args); + if (!sid_range_args_init) { + acm_log(0, "Failed to initialize quick list.\n"); + err = ENOMEM; + goto exit; + } + } + + record = malloc(sizeof(dsap_service_id_record_t)); + if (!record) { + acm_log(0, "Failed to allocate memory.\n"); + err = ENOMEM; + goto exit; + } + memset(record, 0, sizeof(dsap_service_id_record_t)); + + /* Disabling ranged parameters for now. + k = strchr(str,'-'); + if (k) *k=0; */ + + lower = strtoull(str, NULL, 0); + upper = (k)? strtoull(k+1, NULL, 0) : 0; + + record->service_id_range.warned = 0; + record->service_id_range.lower_service_id = hton64(lower); + record->service_id_range.upper_service_id = hton64(upper); + + QListSetObj(&record->item, record); + QListInsertTail(&sid_range_args, &record->item); + +exit: + return err; +} + +/* + * Note that this function isn't re-entrant. + */ +char *dsap_service_id_range_printer(void *ptr) +{ + static char buffer[1024]; + int p = 0; + LIST_ITEM *item; + dsap_service_id_record_t *record; + uint64_t lo, hi; + int count = 0; + + if (!sid_range_args_init) + return ""; + else + p += sprintf(&buffer[p], "\n\t\t"); + for (item = QListHead(&sid_range_args); + item != NULL && p<960; + item = QListNext(&sid_range_args, item)) { + record = QListObj(item); + if (record->service_id_range.upper_service_id) { + lo = record->service_id_range.lower_service_id; + hi = record->service_id_range.upper_service_id; + p += sprintf(&buffer[p], + "[0x%016"PRIx64"-0x%016"PRIx64"] ", + ntoh64(lo), ntoh64(hi)); + count += 2; + } else { + lo = record->service_id_range.lower_service_id; + p += sprintf(&buffer[p],"0x%016"PRIx64" ", + ntoh64(lo)); + count++; + } + if (!(count % 4)) + p += sprintf(&buffer[p], "\n\t\t"); + } + + return buffer; +} + +/* Comparison Callback Functions */ + +static boolean dsap_compare_pkey(LIST_ITEM *item, void *context) +{ + dsap_pkey_t *pkey_item = QListObj(item); + uint16_t *pkey = context; + + return (pkey_item->pkey == *pkey); +} + +static boolean dsap_compare_src_port(LIST_ITEM *item, void *context) +{ + dsap_src_port_t *src_port = QListObj(item); + union ibv_gid *gid = context; + + return (src_port->gid.global.interface_id == gid->global.interface_id); +} + +static boolean dsap_compare_src_port_by_lid(LIST_ITEM *item, void *context) +{ + dsap_src_port_t *src_port = QListObj(item); + unsigned *lid = context; + unsigned mask = 0xffff - ((1 << src_port->lmc) - 1); + + return ((src_port->base_lid & mask )== (*lid & mask)); +} + +static boolean dsap_compare_path(LIST_ITEM *item, void *context) +{ + dsap_path_record_t *dsap_path = QListObj(item); + IB_PATH_RECORD_NO *path = context; + uint16_t key_mask = htons(0x7fff); + + /* Compare Incoming parameters */ + if (path->ServiceID && (path->ServiceID != dsap_path->path.ServiceID)) + return 0; + + if (path->DGID.Type.Global.InterfaceID && + (path->DGID.Type.Global.InterfaceID != + dsap_path->path.DGID.Type.Global.InterfaceID)) + return 0; + + if (path->DGID.Type.Global.SubnetPrefix && + (path->DGID.Type.Global.SubnetPrefix != + dsap_path->path.DGID.Type.Global.SubnetPrefix)) + return 0; + + if (path->DLID && (path->DLID != dsap_path->path.DLID)) + return 0; + + if ((path->P_Key & key_mask) && + (path->P_Key & key_mask) != (dsap_path->path.P_Key & key_mask)) + return 0; + + /* Found */ + return 1; +} + + +static boolean dsap_compare_dst_port(LIST_ITEM *item, void *context) +{ + dsap_dst_port_t *dst_port = QListObj(item); + union ibv_gid *gid = context; + + return (dst_port->gid.global.interface_id == gid->global.interface_id); +} + +static boolean dsap_compare_dst_port_by_name(LIST_ITEM *item, void *context) +{ + dsap_dst_port_t *dst_port = QListObj(item); + char *desc = (char *)context; + + /* We are not doing the exact match here. As long as the user provided + destination is part of the node description, it will be fine for us. + */ + return (0 == strncasecmp(dst_port->node_desc, desc, strlen(desc))); +} + +static boolean dsap_compare_service_id_record(LIST_ITEM *item, void *context) +{ + dsap_service_id_record_t *rec = QListObj(item); + dsap_service_id_range_t *range = context; + + return ((rec->service_id_range.lower_service_id == + range->lower_service_id) && + (rec->service_id_range.upper_service_id == + range->upper_service_id)); +} + +static boolean dsap_compare_virtual_fabric(LIST_ITEM *item, void *context) +{ + dsap_virtual_fabric_t *virtual_fabric = QListObj(item); + uint8_t *vfName = context; + + return (strncmp((const char*)virtual_fabric->vfinfo_record.vfName, + (const char*)vfName, + sizeof(virtual_fabric->vfinfo_record.vfName)) == 0); +} + +static boolean dsap_compare_subnet(LIST_ITEM *item, void *context) +{ + dsap_subnet_t *subnet = QListObj(item); + uint64_t * subnet_prefix = context; + + return (subnet->subnet_prefix == *subnet_prefix); +} + +/* Search Utility Routines */ + +dsap_subnet_t* dsap_find_subnet(uint64_t *subnet_prefix) +{ + LIST_ITEM *item = QListFindItem(&subnet_list, dsap_compare_subnet, + subnet_prefix); + + return item ? QListObj(item) : NULL; +} + +dsap_src_port_t* dsap_find_src_port(union ibv_gid *gid) +{ + LIST_ITEM *subnet_item; + dsap_subnet_t *subnet; + LIST_ITEM *src_port_item; + + for_each (&subnet_list, subnet_item) { + subnet = QListObj(subnet_item); + src_port_item = QListFindItem(&subnet->src_port_list, + dsap_compare_src_port, gid); + if (src_port_item) + return QListObj(src_port_item); + } + + return NULL; +} + +dsap_src_port_t* dsap_find_src_port_by_lid(unsigned *lid) +{ + LIST_ITEM *subnet_item; + dsap_subnet_t *subnet; + LIST_ITEM *src_port_item; + + for_each (&subnet_list, subnet_item) { + subnet = QListObj(subnet_item); + src_port_item = QListFindItem(&subnet->src_port_list, + dsap_compare_src_port_by_lid, + lid); + if (src_port_item) + return QListObj(src_port_item); + } + + return NULL; +} + +dsap_path_record_t * dsap_find_path_record(dsap_src_port_t *src_port, + IB_PATH_RECORD_NO *path) +{ + LIST_ITEM *path_item = QListFindFromHead(&src_port->path_record_list, + dsap_compare_path, path); + if (path_item) + return QListObj(path_item); + return NULL; +} + + +dsap_dst_port_t* dsap_find_dst_port(union ibv_gid *gid) +{ + LIST_ITEM *subnet_item; + LIST_ITEM *dst_port_item; + + for_each (&subnet_list, subnet_item) { + dsap_subnet_t *subnet = QListObj(subnet_item); + dst_port_item = QListFindItem(&subnet->dst_port_list, + dsap_compare_dst_port, gid); + if (dst_port_item) + return QListObj(dst_port_item); + } + + return NULL; +} + +dsap_dst_port_t* dsap_find_dst_port_by_name(char *node_desc) +{ + LIST_ITEM *subnet_item; + LIST_ITEM *dst_port_item; + + for_each (&subnet_list, subnet_item) { + dsap_subnet_t *subnet = QListObj(subnet_item); + dst_port_item = QListFindItem(&subnet->dst_port_list, + dsap_compare_dst_port_by_name, + node_desc); + if (dst_port_item) { + return QListObj(dst_port_item); + } + } + + return NULL; +} + +dsap_virtual_fabric_t* dsap_find_virtual_fabric(uint8_t *vfName, + dsap_subnet_t *subnet) +{ + LIST_ITEM *vf_item; + LIST_ITEM *subnet_item; + + if (subnet) { + vf_item = QListFindItem(&subnet->virtual_fabric_list, + dsap_compare_virtual_fabric, vfName); + return vf_item ? QListObj(vf_item) : NULL; + } + + for_each (&subnet_list, subnet_item) { + subnet = (dsap_subnet_t *)ListObj(subnet_item); + vf_item = QListFindItem(&subnet->virtual_fabric_list, + dsap_compare_virtual_fabric, vfName); + if (vf_item) + return QListObj(vf_item); + } + + return NULL; +} + +size_t dsap_tot_src_port_count(void) +{ + size_t total_count = 0; + LIST_ITEM *item; + + for_each (&subnet_list, item) { + total_count += dsap_src_port_count( + (dsap_subnet_t*)QListObj(item)); + } + + return total_count; +} + +size_t dsap_tot_dst_port_count(void) +{ + size_t total_count = 0; + LIST_ITEM *item; + + for_each (&subnet_list, item) { + total_count += dsap_dst_port_count( + (dsap_subnet_t*)QListObj(item)); + } + + return total_count; +} + +size_t dsap_tot_vfab_count(void) +{ + size_t total_count = 0; + LIST_ITEM *item; + + for_each (&subnet_list, item) { + total_count += dsap_virtual_fabric_count( + (dsap_subnet_t*)QListObj(item)); + } + + return total_count; +} + +size_t dsap_tot_sid_rec_count(void) +{ + size_t total_count = 0; + LIST_ITEM *item1, *item2; + dsap_subnet_t *subnet; + + for_each (&subnet_list, item1) { + subnet = QListObj(item1); + + for_each (&subnet->virtual_fabric_list, item2) { + total_count += dsap_service_id_record_count( + (dsap_virtual_fabric_t*)QListObj(item2)); + } + } + + return total_count; +} + +size_t dsap_subnet_path_record_count(dsap_subnet_t *subnet) +{ + size_t total_count = 0; + LIST_ITEM *item; + for_each (&subnet->src_port_list, item) { + total_count += dsap_path_record_count( + (dsap_src_port_t*)QListObj(item)); + } + + return total_count; +} + +size_t dsap_tot_path_rec_count(void) +{ + size_t total_count = 0; + LIST_ITEM *item1; + dsap_subnet_t *subnet; + + for_each (&subnet_list, item1) { + subnet = QListObj(item1); + total_count += dsap_subnet_path_record_count(subnet); + } + + return total_count; +} + +size_t dsap_tot_pkey_count(void) +{ + size_t total_count = 0; + LIST_ITEM *item1, *item2; + + for_each (&subnet_list, item1) { + dsap_subnet_t *subnet = QListObj(item1); + + for_each (&subnet->src_port_list, item2) { + total_count += dsap_pkey_count( + (dsap_src_port_t*)QListObj(item2)); + } + } + + return total_count; +} + +/* PKEY Handling functions */ + +size_t dsap_pkey_count(dsap_src_port_t *src_port) +{ + return QListCount(&src_port->pkey_list); +} + +/* pkey is in network byte order */ +FSTATUS dsap_add_pkey(dsap_src_port_t *src_port, uint16_t pkey) +{ + dsap_pkey_t *new_pkey = malloc(sizeof(*new_pkey)); + + if (new_pkey == NULL) + return FINSUFFICIENT_MEMORY; + + ListItemInitState(&new_pkey->item); + QListSetObj(&new_pkey->item, new_pkey); + new_pkey->pkey = pkey; + QListInsertTail(&src_port->pkey_list, &new_pkey->item); + + return FSUCCESS; +} + +FSTATUS dsap_empty_pkey_list(dsap_src_port_t *src_port) +{ + LIST_ITEM *item; + + while ((item = QListRemoveHead(&src_port->pkey_list)) != NULL) { + free(QListObj(item)); + } + + return FSUCCESS; +} + +FSTATUS dsap_remove_pkey(dsap_src_port_t *src_port, uint16_t pkey) +{ + LIST_ITEM *item = + QListFindItem(&src_port->pkey_list, dsap_compare_pkey, &pkey); + + if (!item) + return FNOT_FOUND; + + QListRemoveItem(&src_port->pkey_list, item); + free(QListObj(item)); + + return FSUCCESS; +} + +/* Path Record Handling functions */ + +size_t dsap_path_record_count(dsap_src_port_t *src_port) +{ + return QListCount(&src_port->path_record_list); +} + +FSTATUS dsap_add_path_record(dsap_src_port_t *src_port, + IB_PATH_RECORD_NO *path_record) +{ + dsap_path_record_t *new_path_record = malloc(sizeof(*new_path_record)); + + if (new_path_record == NULL) + return FINSUFFICIENT_MEMORY; + + ListItemInitState(&new_path_record->item); + QListSetObj(&new_path_record->item, new_path_record); + new_path_record->path = *path_record; + QListInsertTail(&src_port->path_record_list, &new_path_record->item); + + return FSUCCESS; +} + + +FSTATUS dsap_empty_path_record_list(dsap_src_port_t *src_port) +{ + LIST_ITEM *item; + + while ((item = QListRemoveHead(&src_port->path_record_list)) != NULL) { + free(QListObj(item)); + } + + return FSUCCESS; +} + +FSTATUS dsap_remove_path_records(dsap_src_port_t *src_port, + union ibv_gid *dst_port_gid) +{ + LIST_ITEM *item, *next_item; + dsap_path_record_t *path_record; + + for (item = QListHead(&src_port->path_record_list); item != NULL; + item = next_item) { + next_item = QListNext(&src_port->path_record_list, item); + path_record = QListObj(item); + if (dst_port_gid->global.interface_id == + path_record->path.DGID.Type.Global.InterfaceID) { + QListRemoveItem(&src_port->path_record_list, + &path_record->item); + free(path_record); + } + } + + return FSUCCESS; +} + +/* Src Port Handling functions */ + +size_t dsap_src_port_count(dsap_subnet_t *subnet) +{ + return QListCount(&subnet->src_port_list); +} + +/* The port lock is held */ +FSTATUS dsap_update_src_port(dsap_src_port_t *src_port, struct dsap_port *port) +{ + LIST_ITEM * ep_item; + struct dsap_ep *ep; + + strncpy(src_port->hfi_name, port->dev->device->verbs->device->name, + sizeof(src_port->hfi_name)-1); + src_port->hfi_name[sizeof(src_port->hfi_name)-1]=0; + src_port->port_num = port->port->port_num; + src_port->base_lid = port->lid; + src_port->lmc = port->lmc; + src_port->state = port->state; + dsap_empty_pkey_list(src_port); + dsap_empty_path_record_list(src_port); + + /* Get the pkey from the ep list */ + for_each(&port->ep_list, ep_item) { + ep = QListObj(ep_item); + if (dsap_add_pkey(src_port, htons(ep->endpoint->pkey)) + != FSUCCESS) { + dsap_empty_pkey_list(src_port); + return FINSUFFICIENT_MEMORY; + } + } + + acm_log(2, "Updated port %d on HFI %s: base_lid 0x%x, lmc 0x%x\n", + src_port->port_num, src_port->hfi_name, + src_port->base_lid, src_port->lmc); + + return FSUCCESS; +} + +FSTATUS dsap_remove_src_port(union ibv_gid *src_gid) +{ + dsap_src_port_t *src_port; + dsap_subnet_t *subnet; + + acm_log(2, "\n"); + + src_port = dsap_find_src_port(src_gid); + if (!src_port) + return FNOT_FOUND; + + /* It should be in the dst port list */ + if (dsap_remove_dst_port(src_gid)) { + acm_log(0, "Failure Removing Dst Port 0x%016"PRIx64":0x%016" + PRIx64"\n", + ntoh64(src_gid->global.subnet_prefix), + ntoh64(src_gid->global.interface_id)); + } + + dsap_empty_pkey_list(src_port); + dsap_empty_path_record_list(src_port); + + subnet = dsap_find_subnet((uint64_t *)&src_port->gid.global.subnet_prefix); + if (subnet) + QListRemoveItem(&subnet->src_port_list, &src_port->item); + + free(src_port); + + return FSUCCESS; +} + +/* The port lock is held */ +FSTATUS dsap_add_src_port(struct dsap_port *port) +{ + FSTATUS rval; + dsap_subnet_t *subnet; + union ibv_gid src_port_gid; + dsap_src_port_t *src_port; + + if (acm_get_gid((struct acm_port *) port->port, 0, &src_port_gid)) + return FNOT_FOUND; + + + subnet = dsap_find_subnet((uint64_t *)&src_port_gid.global.subnet_prefix); + if (!subnet) { + if (dsap_add_subnet(src_port_gid.global.subnet_prefix) != + FSUCCESS) + return FINSUFFICIENT_MEMORY; + + subnet = dsap_find_subnet((uint64_t *)&src_port_gid.global.subnet_prefix); + if (!subnet) + return FNOT_FOUND; /* This better not happen */ + } + + src_port = dsap_find_src_port(&src_port_gid); + if (src_port) + return FDUPLICATE; + + src_port = malloc(sizeof(*src_port)); + if (src_port == NULL) { + return FINSUFFICIENT_MEMORY; + } + + ListItemInitState(&src_port->item); + QListSetObj(&src_port->item, src_port); + src_port->gid = src_port_gid; + QListInitState(&src_port->pkey_list); + QListInit(&src_port->pkey_list); + QListInitState(&src_port->path_record_list); + QListInit(&src_port->path_record_list); + QListInsertTail(&subnet->src_port_list, &src_port->item); + + rval = dsap_update_src_port(src_port, port); + if (rval != FSUCCESS) { + free(src_port); + return rval; + } + + acm_log(2, "Added port %d on HFI %s\n", src_port->port_num, + src_port->hfi_name); + + return FSUCCESS; +} + +FSTATUS dsap_empty_src_port_list(dsap_subnet_t *subnet) +{ + LIST_ITEM *item; + + while ((item = QListRemoveHead(&subnet->src_port_list)) != NULL) { + dsap_src_port_t *src_port = QListObj(item); + dsap_empty_path_record_list(src_port); + dsap_empty_pkey_list(src_port); + QListDestroy(&src_port->path_record_list); + free(src_port); + } + + return FSUCCESS; +} + +/* Dst Port Handling functions */ + +size_t dsap_dst_port_count(dsap_subnet_t *subnet) +{ + return QListCount(&subnet->dst_port_list); +} + +FSTATUS dsap_add_dst_port(union ibv_gid *dst_port_gid, NODE_TYPE node_type, + char * node_desc) +{ + dsap_subnet_t *subnet = dsap_find_subnet( + (uint64_t *)&dst_port_gid->global.subnet_prefix); + dsap_dst_port_t *dst_port; + + if (!subnet) + return FNOT_DONE; + + dst_port = dsap_find_dst_port(dst_port_gid); + if (dst_port) + return FDUPLICATE; + + dst_port = malloc(sizeof(*dst_port)); + if (dst_port == NULL) + return FINSUFFICIENT_MEMORY; + + ListItemInitState(&dst_port->item); + QListSetObj(&dst_port->item, dst_port); + dst_port->gid = *dst_port_gid; + dst_port->node_type = node_type; + memcpy(dst_port->node_desc, node_desc, NODE_DESCRIPTION_ARRAY_SIZE); + QListInsertTail(&subnet->dst_port_list, &dst_port->item); + +#ifdef PRINT_PORTS_FOUND + if (dst_port->node_type == STL_NODE_FI) { + acm_log(2, "Added HFI Port 0x%016"PRIx64":0x%016"PRIx64"\n", + ntoh64(dst_port->gid.global.subnet_prefix), + ntoh64(dst_port->gid.global.interface_id)); + } else { + acm_log(2, "Added Switch Port 0x%016"PRIx64":0x%016"PRIx64"\n", + ntoh64(dst_port->gid.global.subnet_prefix), + ntoh64(dst_port->gid.global.interface_id)); + } +#endif + + return FSUCCESS; +} + +FSTATUS dsap_empty_dst_port_list(dsap_subnet_t *subnet) +{ + LIST_ITEM *item; + + while ((item = QListRemoveHead(&subnet->dst_port_list)) != NULL) { + free(QListObj(item)); + } + + return FSUCCESS; +} + +FSTATUS dsap_remove_dst_port(union ibv_gid *dst_port_gid) +{ + dsap_subnet_t *subnet; + dsap_dst_port_t *dst_port; + LIST_ITEM *item; + + dst_port = dsap_find_dst_port(dst_port_gid); + if (!dst_port) { + return FNOT_FOUND; + } + + subnet = dsap_find_subnet((uint64_t *)&dst_port_gid->global.subnet_prefix); + if (!subnet) { + free(dst_port); + return FNOT_FOUND; + } + + if (dst_port->node_type == STL_NODE_FI) { + for_each (&subnet->src_port_list, item) { + dsap_remove_path_records( + (dsap_src_port_t *)ListObj(item), &dst_port->gid); + } + } + + QListRemoveItem(&subnet->dst_port_list, &dst_port->item); + free(dst_port); + + return FSUCCESS; +} + +/* Service ID Record Handling functions */ + +size_t dsap_service_id_record_count(dsap_virtual_fabric_t *virtual_fabric) +{ + return QListCount(&virtual_fabric->service_id_record_list); +} + +FSTATUS dsap_add_service_id_record(dsap_virtual_fabric_t *virtual_fabric, + dsap_service_id_range_t *service_id_range) +{ + LIST_ITEM *item = QListFindItem(&virtual_fabric->service_id_record_list, + dsap_compare_service_id_record, + service_id_range); + dsap_service_id_record_t *new_service_id_record; + + if (item) + return FDUPLICATE; + + new_service_id_record = malloc(sizeof(*new_service_id_record)); + if (new_service_id_record == NULL) { + return FINSUFFICIENT_MEMORY; + } + + ListItemInitState(&new_service_id_record->item); + QListSetObj(&new_service_id_record->item, new_service_id_record); + new_service_id_record->service_id_range = *service_id_range; + QListInsertTail(&virtual_fabric->service_id_record_list, + &new_service_id_record->item); + + return FSUCCESS; +} + +FSTATUS dsap_empty_service_id_record_list(dsap_virtual_fabric_t *vfab) +{ + LIST_ITEM *item; + + while ((item = QListRemoveHead(&vfab->service_id_record_list)) + != NULL) { + free(QListObj(item)); + } + + return FSUCCESS; +} + +FSTATUS dsap_remove_service_id_record(dsap_virtual_fabric_t *vfab, + dsap_service_id_range_t *sid_range) +{ + LIST_ITEM *item = QListFindItem(&vfab->service_id_record_list, + dsap_compare_service_id_record, + sid_range); + + if (!item) + return FNOT_FOUND; + + QListRemoveItem(&vfab->service_id_record_list, item); + free(QListObj(item)); + + return FSUCCESS; +} + +/* Virtual Fabric Record Handling functions */ + +size_t dsap_virtual_fabric_count(dsap_subnet_t *subnet) +{ + return QListCount(&subnet->virtual_fabric_list); +} + +FSTATUS dsap_add_virtual_fabric(dsap_subnet_t *subnet, + STL_VFINFO_RECORD *vfinfo_record) +{ + dsap_virtual_fabric_t *vfab = + dsap_find_virtual_fabric(vfinfo_record->vfName, subnet); + + if (vfab) + return FDUPLICATE; + + vfab = malloc(sizeof(*vfab)); + if (vfab == NULL) + return FINSUFFICIENT_MEMORY; + + ListItemInitState(&vfab->item); + QListSetObj(&vfab->item, vfab); + vfab->vfinfo_record = *vfinfo_record; + QListInitState(&vfab->service_id_record_list); + QListInit(&vfab->service_id_record_list); + QListInsertTail(&subnet->virtual_fabric_list, &vfab->item); + + return FSUCCESS; +} + +FSTATUS dsap_empty_virtual_fabric_list(dsap_subnet_t *subnet) +{ + LIST_ITEM *item; + dsap_virtual_fabric_t *vfab; + + while ((item = QListRemoveHead(&subnet->virtual_fabric_list)) + != NULL) { + vfab = QListObj(item); + dsap_empty_service_id_record_list(vfab); + QListDestroy(&vfab->service_id_record_list); + free(vfab); + } + + return FSUCCESS; +} + +FSTATUS dsap_remove_virtual_fabric(dsap_subnet_t *subnet, uint8_t *vfName) +{ + dsap_virtual_fabric_t *vfab = dsap_find_virtual_fabric(vfName, subnet); + + if (!vfab) + return FNOT_FOUND; + + QListRemoveItem(&subnet->virtual_fabric_list, &vfab->item); + dsap_empty_service_id_record_list(vfab); + QListDestroy(&vfab->service_id_record_list); + free(vfab); + + return FSUCCESS; +} + +/* Subnet Handling functions */ + +size_t dsap_subnet_count(void) +{ + return QListCount(&subnet_list); +} + +dsap_subnet_t* dsap_get_subnet_at(uint32_t index) +{ + LIST_ITEM *item = QListGetItemAt(&subnet_list, index); + + if (item) + return (dsap_subnet_t*)QListObj(item); + + return NULL; +} + +FSTATUS dsap_add_subnet(uint64_t subnet_prefix) +{ + dsap_subnet_t *subnet = dsap_find_subnet(&subnet_prefix); + + if (subnet) + return FDUPLICATE; + + subnet = malloc(sizeof(*subnet)); + if (subnet == NULL) + return FINSUFFICIENT_MEMORY; + memset((void*)subnet,0,sizeof(*subnet)); + + ListItemInitState(&subnet->item); + QListSetObj(&subnet->item, subnet); + subnet->subnet_prefix = subnet_prefix; + QListInitState(&subnet->src_port_list); + QListInit(&subnet->src_port_list); + QListInitState(&subnet->dst_port_list); + QListInit(&subnet->dst_port_list); + QListInitState(&subnet->virtual_fabric_list); + QListInit(&subnet->virtual_fabric_list); + QListInsertTail(&subnet_list, &subnet->item); + + return FSUCCESS; +} + +FSTATUS dsap_empty_subnet_list(void) +{ + LIST_ITEM *item; + dsap_subnet_t *subnet; + + acm_log(2, "Emptying subnet list.\n"); + + while ((item = QListRemoveHead(&subnet_list)) != NULL) { + subnet = QListObj(item); + dsap_empty_src_port_list(subnet); + dsap_empty_dst_port_list(subnet); + dsap_empty_virtual_fabric_list(subnet); + QListDestroy(&subnet->src_port_list); + QListDestroy(&subnet->dst_port_list); + QListDestroy(&subnet->virtual_fabric_list); + free(subnet); + } + + return FSUCCESS; +} + +void dsap_topology_cleanup(void) +{ + dsap_empty_subnet_list(); +} + +FSTATUS dsap_topology_init(void) +{ + QListInitState(&subnet_list); + QListInit(&subnet_list); + + return FSUCCESS; +} diff --git a/Dsap/src/dsap_topology.h b/Dsap/src/dsap_topology.h new file mode 100644 index 0000000..a448d0b --- /dev/null +++ b/Dsap/src/dsap_topology.h @@ -0,0 +1,191 @@ +/* BEGIN_ICS_COPYRIGHT4 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT4 ****************************************/ +/*! + + \file dsap_topology.h + + $Revision: 1.4 $ + $Date: 2015/01/27 23:00:24 $ + + \brief Routines for populating tables to define fabric topology from the SM. +*/ + +#if !defined(_DSC_TOPOLOGY_H_) +#define _DSC_TOPOLOGY_H_ + +#include +#include + +#include "iba/ibt.h" +#include + +#include "ilist.h" +#include "iba/stl_sd.h" + +typedef struct dsap_pkey { + LIST_ITEM item; + uint16_t pkey; /* Stored in network order */ +} dsap_pkey_t; + +typedef struct dsap_path_record { + LIST_ITEM item; + IB_PATH_RECORD_NO path; /* Stored in network order */ +} dsap_path_record_t; + + +typedef struct dsap_src_port { + LIST_ITEM item; + union ibv_gid gid; /* Stored in network order */ + char hfi_name[IBV_SYSFS_NAME_MAX]; + uint8_t port_num; + unsigned base_lid; + unsigned lmc; + unsigned state; + QUICK_LIST pkey_list; + QUICK_LIST path_record_list; +} dsap_src_port_t; + +typedef struct dsap_dst_port { + LIST_ITEM item; + union ibv_gid gid; /* Stored in network order */ + NODE_TYPE node_type; + char node_desc[NODE_DESCRIPTION_ARRAY_SIZE]; +} dsap_dst_port_t; + +typedef struct dsap_service_id_range { + int warned; /* set if an error has been emitted for this SID range. */ + uint64_t lower_service_id; /* Stored in network order */ + uint64_t upper_service_id; /* Stored in network order */ +} dsap_service_id_range_t; + +typedef struct dsap_service_id_record { + LIST_ITEM item; + dsap_service_id_range_t service_id_range; +} dsap_service_id_record_t; + +typedef struct dsap_virtual_fabric { + LIST_ITEM item; + STL_VFINFO_RECORD vfinfo_record; /* Stored in network order */ + QUICK_LIST service_id_record_list; +} dsap_virtual_fabric_t; + +typedef struct dsap_subnet { + LIST_ITEM item; + uint64_t subnet_prefix; /* Stored in network order */ + QUICK_LIST src_port_list; + QUICK_LIST dst_port_list; + QUICK_LIST virtual_fabric_list; + int current; /* 0 = needs to be updated. */ +} dsap_subnet_t; + +struct dsap_port; + +/* PKEY Handling functions */ +size_t dsap_pkey_count(dsap_src_port_t *src_port); +FSTATUS dsap_add_pkey(dsap_src_port_t *src_port, uint16_t pkey); +FSTATUS dsap_empty_pkey_list(dsap_src_port_t *src_port); +FSTATUS dsap_remove_pkey(dsap_src_port_t *src_port, uint16_t pkey); + +/* Path Record Handling functions */ +size_t dsap_path_record_count(dsap_src_port_t *src_port); +size_t dsap_subnet_path_record_count(dsap_subnet_t *subnet); +FSTATUS dsap_add_path_record(dsap_src_port_t *src_port, + IB_PATH_RECORD_NO *path_record); +FSTATUS dsap_empty_path_record_list(dsap_src_port_t *src_port); +FSTATUS dsap_remove_path_records(dsap_src_port_t *src_port, + union ibv_gid *dst_port_gid); + +/* Src Port Handling functions */ +size_t dsap_src_port_count(dsap_subnet_t *subnet); +FSTATUS dsap_update_src_port(dsap_src_port_t *src_port, + struct dsap_port *port); +FSTATUS dsap_add_src_port(struct dsap_port *port); +FSTATUS dsap_empty_src_port_list(dsap_subnet_t *subnet); +FSTATUS dsap_remove_src_port(union ibv_gid *src_gid); + +/* Dst Port Handling functions */ +size_t dsap_dst_port_count(dsap_subnet_t *subnet); +FSTATUS dsap_add_dst_port(union ibv_gid *dst_port_gid, NODE_TYPE node_type, + char *node_desc); +FSTATUS dsap_empty_dst_port_list(dsap_subnet_t *subnet); +FSTATUS dsap_remove_dst_port(union ibv_gid *dst_port_gid); + +/* ServiceID Record Handling functions */ +size_t dsap_service_id_record_count(dsap_virtual_fabric_t *virtual_fabric); +FSTATUS dsap_add_service_id_record(dsap_virtual_fabric_t *virtual_fabric, + dsap_service_id_range_t *service_id_range); +FSTATUS dsap_empty_service_id_record_list( + dsap_virtual_fabric_t *virtual_fabric); +FSTATUS dsap_remove_service_id_record( + dsap_virtual_fabric_t *virtual_fabric, + dsap_service_id_range_t *service_id_range); + +/* Virtual Fabric Record Handling functions */ +size_t dsap_virtual_fabric_count(dsap_subnet_t *subnet); +FSTATUS dsap_add_virtual_fabric(dsap_subnet_t *subnet, + STL_VFINFO_RECORD *vfinfo_record); +FSTATUS dsap_empty_virtual_fabric_list(dsap_subnet_t *subnet); +FSTATUS dsap_remove_virtual_fabric(dsap_subnet_t *subnet, uint8_t *vfName); + +/* Subnet Handling functions */ +size_t dsap_subnet_count(void); +dsap_subnet_t* dsap_get_subnet_at(uint32_t index); +FSTATUS dsap_add_subnet(uint64_t subnet_prefix); +FSTATUS dsap_empty_subnet_list(void); + +/* Search Utility Routines */ +dsap_subnet_t* dsap_find_subnet(uint64_t *subnet_prefix); +dsap_src_port_t* dsap_find_src_port(union ibv_gid *gid); +dsap_src_port_t* dsap_find_src_port_by_lid(unsigned *lid); +dsap_path_record_t * dsap_find_path_record(dsap_src_port_t *src_port, + IB_PATH_RECORD_NO *path); +dsap_dst_port_t* dsap_find_dst_port(union ibv_gid *gid); +dsap_dst_port_t* dsap_find_dst_port_by_name(char *node_desc); +dsap_virtual_fabric_t* dsap_find_virtual_fabric(uint8_t *vfName, + dsap_subnet_t *subnet); + +size_t dsap_tot_src_port_count(void); +size_t dsap_tot_dst_port_count(void); +size_t dsap_tot_vfab_count(void); +size_t dsap_tot_sid_rec_count(void); +size_t dsap_tot_path_rec_count(void); +size_t dsap_tot_pkey_count(void); + +void dsap_topology_cleanup(void); +FSTATUS dsap_topology_init(void); + +/* + * Used for parsing & printing command line arguments. + */ +int dsap_service_id_range_parser(char *str, void *ptr); +char *dsap_service_id_range_printer(void *ptr); +extern QUICK_LIST sid_range_args; + + +#endif diff --git a/Esm/ib/Makerules.module b/Esm/ib/Makerules.module new file mode 100644 index 0000000..d370bca --- /dev/null +++ b/Esm/ib/Makerules.module @@ -0,0 +1,149 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** +## Rules for SM module +#=============================================================================# +## Module Make Rules File +## ----------------------- +## +#=============================================================================# +## +#=============================================================================# +# The following list is the standard list of definitions which will be defined +# for all platforms. It consists of general and machine specific sections that +# contain many system parameters which may be used in a makefile. Please keep +# the list(s) in strictly aphabetical order to facilitate simple searches. +# +# See Makerules.global for the meaning of these flags +#-----------------------------------------------------------------------------# +# Common platform definitions: +#-----------------------------------------------------------------------------# +MOD_DIR=$(PROJ_SM_DIR) +MOD_INCLUDE_DIR=$(PROJ_INCLUDE_DIR) +MOD_LIB_DIR=$(MOD_DIR)/builtlibs$(BUILT_SUFFIX) +MOD_BIN_DIR=$(PROJ_BIN_DIR) +MOD_SHLIB_DIR=$(PROJ_SHLIB_DIR) +MOD_SBR_DIR=$(PROJ_SBR_DIR) + +MOD_STAGE_DIR=$(PROJ_STAGE_DIR) +MOD_STAGE_INCLUDE_DIR=$(PROJ_STAGE_INCLUDE_DIR) +MOD_STAGE_LIB_DIR=$(MOD_DIR)/builtlibs$(BUILT_SUFFIX) +MOD_STAGE_BIN_DIR=$(PROJ_STAGE_BIN_DIR) +MOD_STAGE_SHLIB_DIR=$(PROJ_STAGE_SHLIB_DIR) +MOD_STAGE_SBR_DIR=$(PROJ_STAGE_SBR_DIR) +MOD_STAGE_DRIVER_BIN_DIR=$(PROJ_STAGE_DRIVER_BIN_DIR) + +MOD_BIN_SUBDIR = +MOD_DRIVER_BIN_SUBDIR = + +MOD_INCLUDE_SUBDIR = +#MOD_INCLUDE_DIRS = . $(GLOBAL_INCLUDE_DIR)/$(MOD_INCLUDE_SUBDIR) +MOD_INCLUDE_DIRS = . $(MOD_DIR)/include $(IBACCESS_USER_INCLUDE_DIRS) $(TL_DIR)/BSP/bspcommon/wrs/h +MOD_LIB_DIRS = $(MOD_LIB_DIR) $(OPENIB_USER_LIB_DIRS) +MODDEPLIBS = +MODLIBS = + +BSCMOD = + +CMOD = -D_THREAD_SAFE -D_REENTRANT +ifeq "$(BUILD_CONFIG)" "debug" +CMOD += -DDEBUG -DVIEO_DEBUG -O0 +endif +CCMOD = $(CMOD) +DEPENDMOD = +LDMOD = +LINTMOD = +MIDLMOD = +RSCMOD = + +#-----------------------------------------------------------------------------# +# Platform specific definitions: +#-----------------------------------------------------------------------------# +ifeq "$(BUILD_TARGET_OS)" "VXWORKS" +MOD_INCLUDE_DIRS += \ + $(TL_DIR)/BSP/bspcommon/wrs/config \ + $(TGT_DIR)/components/ip_net2-6.9/ipcrypto/include \ + $(TGT_DIR)/components/ip_net2-6.9/ipcrypto/$(OPENSSL_VER)/include +# FIXME, change uses of __VXWORKS__ to VXWORKS +CMOD += -DCAL_IBACCESS -D__VXWORKS__ +ifeq "$(BUILD_TARGET)" "ATOM" +# FIXME: seems like -DINET6 should be set in Makerules.project +CMOD += -DINET6 +else +CMOD += -I$(TL_DIR)/tmsTarget/src/ssecure/sshield/include +endif +ifneq "$(BUILD_CONFIG)" "debug" +CMOD += -DVIEO_TRACE_DISABLED +endif +endif +ifeq "$(BUILD_TARGET_OS)" "LINUX" +# only for linux, unfortunately vxWorks headers have too many violations of this +CMOD += -Wstrict-prototypes +endif # LINUX +ifeq "$(BUILD_TARGET_OS)" "WIN32" +endif # WIN32 +#=============================================================================# +# Include Global makerules definitions and rules +include $(TL_DIR)/$(PROJ_FILE_DIR)/Makerules.project +#=============================================================================# + +#=============================================================================# +## The project makerules file also contains the following basic make target +## rules for simplifying application build processes: +## +#=============================================================================# +# The following section contains a list of standard targets which will be used +# by all of the makefiles. The targets are listed in alphabetical order and +# depend on the above definitions section as well as externally defined items +# from the user specific makefile. +#=============================================================================# +# General Rules: +#-----------------------------------------------------------------------------# +#=============================================================================# +ifeq "$(BUILD_TARGET_OS)" "VXWORKS" +endif +#=============================================================================# +# This section contains a set of targets which override the standard ones +# provided for by GNU make. +#=============================================================================# +# Standard Makefile Rules Overrides: +#-----------------------------------------------------------------------------# +#=============================================================================# + +#=============================================================================# +# Targets to make sure the initial environment is properly configured +#=============================================================================# +#ifndef ENVIRONMENT +#check_env: +# @echo "The ENVIRONMENT environment variable must be set to be valid" +# @exit 1 +#else #ENVIRONMENT +#check_env: +#endif #ENVIRONMENT +#.PHONY: check_env +#=============================================================================# diff --git a/Esm/ib/include/Makefile b/Esm/ib/include/Makefile new file mode 100755 index 0000000..0ddd07d --- /dev/null +++ b/Esm/ib/include/Makefile @@ -0,0 +1,52 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +include $(shell GetBuildRoot)/ib/rules/toplevel.cf + +INSTALL: + +INSTALL_OLD: + @(DEST=include; FILES="\ + cs_endian.h \ + cs_g.h \ + cs_log.h \ + ib_const.h \ + ib_mad.h \ + ib_sa.h \ + ib_status.h \ + ib_macros.h \ + ib_sm.h \ + ib_types.h \ + if3.h \ + mai_g.h \ + os_g.h \ + vfi_g.h \ + vs_g.h \ + fm_xml.h \ + "; $(INSTALL_TARG)) diff --git a/Esm/ib/include/README b/Esm/ib/include/README new file mode 100644 index 0000000..a22314f --- /dev/null +++ b/Esm/ib/include/README @@ -0,0 +1,42 @@ +/* BEGIN_ICS_COPYRIGHT10 **************************************** + +Copyright (c) 2015, Intel Corporation +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: +- Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. +- Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. +- Neither the name of Intel Corporation nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL INTEL, THE COPYRIGHT OWNER OR CONTRIBUTORS +BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. + +EXPORT LAWS: THIS LICENSE ADDS NO RESTRICTIONS TO THE EXPORT LAWS OF YOUR +JURISDICTION. It is licensee's responsibility to comply with any export +regulations applicable in licensee's jurisdiction. Under CURRENT (May 2000) +U.S. export regulations this software is eligible for export from the U.S. +and can be downloaded by or otherwise exported or reexported worldwide EXCEPT +to U.S. embargoed destinations which include Cuba, Iraq, Libya, North Korea, +Iran, Syria, Sudan, Afghanistan and any other country to which the U.S. has +embargoed goods and services. + +** END_ICS_COPYRIGHT10 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ +include files for use within host and embedded fabric manager only +these represent global includes for APIs between modules in the FM diff --git a/Esm/ib/include/cal_ibaccess_g.h b/Esm/ib/include/cal_ibaccess_g.h new file mode 100644 index 0000000..56b9836 --- /dev/null +++ b/Esm/ib/include/cal_ibaccess_g.h @@ -0,0 +1,51 @@ +/* BEGIN_ICS_COPYRIGHT2 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + * ** END_ICS_COPYRIGHT2 ****************************************/ + +/* + * CAL_IBACCESS layer global header + */ + +#ifndef __CAL_IBACCESS_G_H__ +#define __CAL_IBACCESS_G_H__ + +/****************************************************************************** +* Includes +******************************************************************************/ + +#include "ib_status.h" +#include "ib_types.h" +#include "iba/ib_types.h" + +/****************************************************************************** +* Functions +******************************************************************************/ + +extern void cal_ibaccess_global_shutdown(void); + +#endif // __CAL_IBACCESS_G_H__ diff --git a/Esm/ib/include/cs_bitset.h b/Esm/ib/include/cs_bitset.h new file mode 100644 index 0000000..6a245f1 --- /dev/null +++ b/Esm/ib/include/cs_bitset.h @@ -0,0 +1,139 @@ +/* BEGIN_ICS_COPYRIGHT2 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + * ** END_ICS_COPYRIGHT2 ****************************************/ + +//===========================================================================// +// +// FILE NAME +// cs_bitset.h +// +// DESCRIPTION +// Implement a generic bitset structure. +// +// DATA STRUCTURES +// None +// +// FUNCTIONS +// None +// +// DEPENDENCIES +// None +// +// +//===========================================================================// + +#ifndef _CS_BITSET_H_ +#define _CS_BITSET_H_ + +#include +#include +#include "vs_g.h" +#include "ib_const.h" +#include "ib_types.h" + +typedef struct { + size_t nwords_m; + size_t nbits_m; + uint32_t *bits_m; + size_t nset_m; + Pool_t* pool_m; +} bitset_t; + +/* Initialize a bitset struct large enough to hold nbits. */ +int bitset_init(Pool_t *, bitset_t *, size_t nbits); + +/* Like bitset_init() only the bitset_t is assumed to be valid when + called, so the existing memory used by the bitset if freed after + the bitset is resized */ +int bitset_resize(bitset_t *, size_t nbits); + +/* Destroy a bitset. */ +void bitset_free(bitset_t *); + +/* Clear all bits (default) */ +void bitset_clear_all(bitset_t *); + +/* Set all bits */ +void bitset_set_all(bitset_t *); + +/* Copy one bitset to the other */ +void bitset_copy(bitset_t *, bitset_t *); + +/* Clear a specific bit (0..nbits-1). Returns -1 on error */ +int bitset_clear(bitset_t *, unsigned bit); + +/* Set a specific bit, Returns -1 on error */ +int bitset_set(bitset_t *, unsigned bit); + +/* Test a specific bit. Result is undefined if bit >= nbits() */ +int bitset_equal(bitset_t*, bitset_t*); + +/* Test a specific bit. Result is undefined if bit >= nbits() */ +int bitset_test(bitset_t *, unsigned bit); + +/* Find the first one bit. Returns -1 if not found */ +int bitset_find_first_one(bitset_t *); + +/* Find the next one bit. */ +int bitset_find_next_one(bitset_t *, unsigned bit); + +/* Find the last one bit. */ +int bitset_find_last_one(bitset_t *); + +/* Find the first zero bit. Returns -1 if not found */ +int bitset_find_first_zero(bitset_t *); + +/* Find the next zero bit past the given bit */ +int bitset_find_next_zero(bitset_t *, unsigned bit); + +/* Returns -1 if not found */ +int bitset_find_last_zero(bitset_t *); + +/* Return the number of bits in the bitset */ +size_t bitset_nbits(bitset_t *); + +/* Return the number of one bits in the bitset. */ +size_t bitset_nset(bitset_t *); + +/* Returns 1 if logical and of the bitsets has at least one bit set, + * returns 0 if bitsets are different sizes or logical and is 0 */ +int bitset_test_intersection(bitset_t * a, bitset_t * b); + +/* Sets result to the bitwise and of bitsets a and b + * Returns the number of bits set in the result + * or -1 if the bitsets aren't allocated or differ in size */ +int bitset_set_intersection(bitset_t * a, bitset_t * b, bitset_t * result); + +/* Display a human readable representation of the bitset. + This uses log level INFINI_INFO and should probably only + be called under debug mode. */ +void bitset_info_log(bitset_t*, char* prelude); + +#endif // _CS_BITSET_H_ + + diff --git a/Esm/ib/include/cs_context.h b/Esm/ib/include/cs_context.h new file mode 100644 index 0000000..523b900 --- /dev/null +++ b/Esm/ib/include/cs_context.h @@ -0,0 +1,212 @@ +/* BEGIN_ICS_COPYRIGHT2 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + * ** END_ICS_COPYRIGHT2 ****************************************/ + +//===========================================================================// +// +// FILE NAME +// cs_context.h +// +// DESCRIPTION +// Definitions for a generic context pool for reliable single packet +// comunications +// +// There are three models for using this: +// 1. Simple state based operation with multiple concurrent requests and +// a sequence initiated via callbacks. This model is used by the PM. +// A set of operations are started by a main thread. +// Then callbacks process the responses and issue the next packet(s). +// When all packets are done, the callback wakes up the main thread. +// 2. A "polling based" operation with multiple concurrent requests and +// a sequence initiated by polling a resp_queue. This model is used by +// the SM for GuidInfo queries (sm_send_request_async_and_queue_rsp). +// In this model a callback is not allowed. The main thread issues one +// or more packets. As the responses complete (or timeout) the cntxt_entry +// is put on the resp_queue. The main thread polls or waits on the +// resp_queue and processes the responses and decides when ti issue the +// next packet. +// 3. A dispatcher operation with a work queue and a sequence initiated by +// callbacks. This is very similar to mode #1. This model is used by the +// SM for LFT and MFT sets. The main thread puts outbound packets on a +// dispatcher queue (sm_send_request_async_dispatch*). Then callbacks +// process the responses. A dispatcher is also called periodically to +// take items off the queue and issue new packets. When the dispatcher +// queue is empty an event is signalled which wakes the main thread. +// +// In all the above models the cs_context can handle retries and timeouts. +// As part of this design, care is taken to ensure that callers can depend +// on eventually getting a callback. As such there are no allocations +// needed within the callback. Even in model #1, care is taken by the +// callbacks to ensure there is never an attempt to have more than +// poolSize requests outstanding, hence the context can always provide an +// entry to use for issuing the packet. +// +// DATA STRUCTURES +// None +// +// FUNCTIONS +// None +// +// DEPENDENCIES +// ib_types.h +// ib_mad.h +// ib_status.h +// +// +//===========================================================================// + +#ifndef _CS_CONTEXT_H_ +#define _CS_CONTEXT_H_ + +#include "vs_g.h" +#include "mai_g.h" +#include "cs_queue.h" + +// +// SM Notice context definitions +// + +#define CNTXT_HASH_TABLE_DEPTH 79 + +struct _cntxt_entry; + +// response mad is supplied to callback only if Status is VSTATUS_OK +typedef void (*cntxt_callback_t)(struct _cntxt_entry *, Status_t, void *, Mai_t *mad); + +typedef struct _cntxt_entry { + uint64_t tstamp; + uint64_t tid; // Tid for hash table search + STL_LID lid; // Lid for hash table search + uint16_t index; // entry index into list + uint8_t hashed; + uint8_t alloced; + uint16_t retries; // retry count + uint64_t RespTimeout; // current response timeout value (13.6.3.1) + uint64_t cumulative_timeout; //sum of timeouts across retries + uint64_t totalTimeout; // total initial timeout value + uint8_t senderWantsResponse; // 1 = sender wants the response on the resp_queue + uint8_t sendFailed; // most recent attempt to send failed + uint16_t releasing; // have begun to release + Mai_t mad; // mad to send + // also for entries on resp_queue it holds + // the received mad (or original sent mad if + // MAI_TYPE_ERROR) + cntxt_callback_t callback; // caller callback called when context is freed + void * callback_data; // caller-specific data passed to callback + struct _cntxt_entry *next; // Link List next pointer + struct _cntxt_entry *prev; // Link List prev pointer +} cntxt_entry_t; + +typedef struct _generic_cntxt_ { + int hashTableDepth; // can set to 0 if non-lid routed packets + // otherwise set to CNTXT_HASH_TABLE_DEPTH + int poolSize; + int maxRetries; // max number of times to time to try sending mad + IBhandle_t ibHandle; // IBHandle file descriptor used for sending mads + uint64_t defaultTimeout; + uint64_t totalTimeout; //if using stepped retries, this is the total Max timeout (in microseconds) across all retries + uint64_t MinRespTimeout; //if using stepped retries, smallest response timeout (in microseconds) with which to start + int errorOnSendFail; // 0 = if fail to send a retry, leave + // on hash for attempt at next retry + // interval + // 1 = if fail to send a retry, fail + // the entry without doing more retries + uint64_t timeoutAdder; // amount to add to timeouts in + // cs_cntxt_age. If OFED style timeout + // handling is being done in the kernel + // this will cause non-send failure + // entries to be checked with a higher + // just in case OFED losed the packet + // otherwise OFED is expected to provide + // response or MAI_TYPE_ERROR packet + // much sooner + int numAlloc; + int numFree; + Lock_t lock; + cs_Queue_ptr resp_queue; // queue to post responses + // cntxt_entry* will be posted + // to this queue. when removed + // from queue they should be + // cs_cntxt_retire or cs_cntxt_reuse + int numWaiters; // num waiters for a free context + Sema_t freeContextWaitSema; + cntxt_entry_t *free_list; + cntxt_entry_t *hash[CNTXT_HASH_TABLE_DEPTH]; + cntxt_entry_t *pool; // array of context entries 'poolSize' deep + Pool_t *globalPool; // pool to allocate data from if needed for queued messages +} generic_cntxt_t; + +// external function definitions +Pool_t *cs_cntxt_get_global_pool (generic_cntxt_t *cntx); +Status_t cs_cntxt_instance_init (Pool_t *pool, generic_cntxt_t *cntx, uint64_t timeout); +Status_t cs_cntxt_instance_free (Pool_t *pool, generic_cntxt_t *cntx); + +void cs_cntxt_lock( generic_cntxt_t *cntx); +void cs_cntxt_unlock( generic_cntxt_t *cntx); + +uint64_t cs_cntxt_age (generic_cntxt_t *cntx); + +// Get routines will allocate a context entry, initialize its mad +// and place it on the hash list. +// To avoid copying a mad, can specify mad=NULL then +// build mad directly in entry->mad +// Wait should be FALSE on all calls, wait=TRUE is only for internal use +cntxt_entry_t *cs_cntxt_get_nolock ( Mai_t* mad, generic_cntxt_t *cntx, boolean wait ); +cntxt_entry_t *cs_cntxt_get ( Mai_t* mad, generic_cntxt_t *cntx, boolean wait ); +cntxt_entry_t *cs_cntxt_get_wait ( Mai_t* mad, generic_cntxt_t *cntx ); + +// find context entry matching received mad, invoke the callback and +// release the entry +void cs_cntxt_find_release (Mai_t *mad, generic_cntxt_t *cntx); + +// find context entry matching failed mad, initiate retries or invoke the +// callback and release the entry as appropriate +void cs_cntxt_find_release_error (Mai_t *mad, generic_cntxt_t *cntx); + +// This is only valid for use within a cntxt callback, it will reuse the +// entry and prevent the cntxt_release function (which invoked the callback) +// from freeing entry. mad can be NULL just like in cs_cntxt_get* in which +// case caller must build output mad directly in entry->mad +void cs_cntxt_reuse_nolock( cntxt_entry_t *entry, generic_cntxt_t *cntx, Mai_t *mad ); + +// This will free the entry. +// If used within a callback, after the retire, caller can use +// cs_cntxt_get_nolock with wait=0 to allocate another entry. +void cs_cntxt_retire_nolock( cntxt_entry_t *entry, generic_cntxt_t *cntx ); +void cs_cntxt_retire( cntxt_entry_t *entry, generic_cntxt_t *cntx ); + +void cs_cntxt_set_callback(cntxt_entry_t *cntxt, cntxt_callback_t cb, void *data); + +// within a callback, it is valid to call cs_cntxt_send_mad_nolock to +// resend the same mad without change. This can be useful when dealing +// with temporary errors (BUSY). Note that when invoked from a callback, the +// entry will be re-hashed so its ok to change some aspects of the mad. +Status_t cs_cntxt_send_mad_nolock (cntxt_entry_t *entry, generic_cntxt_t *cntx); +Status_t cs_cntxt_send_mad (cntxt_entry_t *entry, generic_cntxt_t *cntx); + +#endif // _CS_CONTEXT_H diff --git a/Esm/ib/include/cs_csm_log.h b/Esm/ib/include/cs_csm_log.h new file mode 100644 index 0000000..8fcb05f --- /dev/null +++ b/Esm/ib/include/cs_csm_log.h @@ -0,0 +1,83 @@ +/* BEGIN_ICS_COPYRIGHT2 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + * ** END_ICS_COPYRIGHT2 ****************************************/ + +#ifndef CS_CSM_LOG_L_H +#define CS_CSM_LOG_L_H + +/* enumerations */ +typedef enum { + CSM_SEV_INFO = 1, + CSM_SEV_NOTICE = 2, + CSM_SEV_WARNING = 3, + CSM_SEV_ERROR = 4, + CSM_SEV_MAX +} SmCsmMsgType_t; + +typedef enum { + CSM_COND_REDUNDANCY_LOST = 1, + CSM_COND_REDUNDANCY_RESTORED = 2, + CSM_COND_APPEARANCE = 3, + CSM_COND_DISAPPEARANCE = 4, + CSM_COND_SM_STATE_TO_MASTER = 5, + CSM_COND_SM_STATE_TO_STANDBY = 6, + CSM_COND_SM_SHUTDOWN = 7, + CSM_COND_FABRIC_INIT_ERROR = 8, + CSM_COND_LINK_ERROR = 9, + CSM_COND_SECURITY_ERROR = 10, + CSM_COND_OTHER_ERROR = 11, + CSM_COND_FABRIC_SUMMARY = 12, + CSM_COND_SM_STATE_TO_NOTACTIVE = 13, + CSM_COND_STANDBY_SM_DEACTIVATION = 14, + CSM_COND_STANDBY_SM_VF_DEACTIVATION = 15, + CSM_COND_SECONDARY_BM_DEACTIVATION = 16, + CSM_COND_SECONDARY_PM_DEACTIVATION = 17, + CSM_COND_DEACTIVATION_OF_STANDBY = 18, + CSM_COND_SECONDARY_EM_DEACTIVATION = 19, + CSM_COND_MAX +} SmCsmMsgCondition_t; + +/* structure definitions */ +typedef struct { + char description[64]; /* 64 == Maximum length of node description in IBTA v1.2 */ + uint8_t port; + uint64_t guid; +} SmCsmNodeId_t; + +void smCsmFormatNodeId(SmCsmNodeId_t * id, uint8_t * desc, int port, uint64_t guid); + +/* prototypes */ +int smCsmSetLogSmDesc(const char * nodeDesc, int port, uint64_t guid); +SmCsmNodeId_t * getMyCsmNodeId(void); + +int smCsmLogMessage( SmCsmMsgType_t msgType, SmCsmMsgCondition_t cond, + SmCsmNodeId_t * node, SmCsmNodeId_t * linkedTo, + char * detailFmt, ... ); + + +#endif diff --git a/Esm/ib/include/cs_g.h b/Esm/ib/include/cs_g.h new file mode 100644 index 0000000..359be6c --- /dev/null +++ b/Esm/ib/include/cs_g.h @@ -0,0 +1,61 @@ +/* BEGIN_ICS_COPYRIGHT2 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + * ** END_ICS_COPYRIGHT2 ****************************************/ + +//==============================================================================/ +// / +// FILE NAME / +// cs_g.h / +// / +// DESCRIPTION / +// This file contains global function prototypes and structure / +// definitions for common services. / +//==============================================================================/ + +#ifndef _CS_G_H_ +#define _CS_G_H_ + +#include "ib_types.h" +#include + +#ifndef bool_t +typedef uint32_t bool_t; +#endif + +#include + +//==============================================================================/ +// OS +//==============================================================================/ +#include + +/* Include the logging header file to get the logging support macros */ +#include + +#endif /* _CS_G_H_ */ + diff --git a/Esm/ib/include/cs_hashtable.h b/Esm/ib/include/cs_hashtable.h new file mode 100644 index 0000000..610ae90 --- /dev/null +++ b/Esm/ib/include/cs_hashtable.h @@ -0,0 +1,344 @@ +/* + * Copyright (c) 2002, Christopher Clark + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name of the original author; nor the names of any contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef __CS_HASHTABLE_H__ +#define __CS_HASHTABLE_H__ + +#include "vs_g.h" + +/* Example of use: + * + * struct cs_hashtable *h; + * struct a_key *k; + * struct a_value *v; + * + * static unsigned int hash_from_key_fn( void *k ); + * static int keys_equal_fn ( void *key1, void *key2 ); + * + * h = cs_create_hashtable(16, hash_from_key_fn, keys_equal_fn); + * k = (struct a_key *) malloc(sizeof(struct some_key)); + * v = (struct a_value *) malloc(sizeof(struct some_value)); + * + * (initialise k and v to suitable values) + * + * if (! cs_hashtable_insert(h,k,v) ) + * { exit(-1); } + * + * if (NULL == (found = cs_hashtable_search(h,k) )) + * { printf("not found!"); } + * + * if (NULL == (found = cs_hashtable_remove(h,k) )) + * { printf("Not found\n"); } + * + */ + +/* Macros may be used to define type-safe(r) hashtable access functions, with + * methods specialized to take known key and value types as parameters. + * + * Example: + * + * Insert this at the start of your file: + * + * DEFINE_HASHTABLE_INSERT(hashInsert, struct a_key, struct a_value); + * DEFINE_HASHTABLE_SEARCH(hashSearch, struct a_key, struct a_value); + * DEFINE_HASHTABLE_REMOVE(hashRemove, struct a_key, struct a_value); + * + * This defines the functions 'hashInsert', 'hashSearch' and 'hashRemove'. + * These operate just like cs_hashtable_insert etc., with the same parameters, + * but their function signatures have 'struct a_key *' rather than + * 'void *', and hence can generate compile time errors if your program is + * supplying incorrect data as a key (and similarly for value). + * + * Note that the hash and key equality functions passed to cs_create_hashtable + * still take 'void *' parameters instead of 'a_key *'. This shouldn't be + * a difficult issue as they're only defined and passed once, and the other + * functions will ensure that only valid keys are supplied to them. + * + * The cost for this checking is increased code size and runtime overhead + * - if performance is important, it may be worth switching back to the + * unsafe methods once your program has been debugged with the safe methods. + * This just requires switching to some simple alternative defines - eg: + * #define hashInsert cs_hashtable_insert + * + */ + +typedef enum { + CS_HASH_KEY_NOT_ALLOCATED, + CS_HASH_KEY_ALLOCATED +} CS_Hash_KeyType_t; + +/* + * hash_entry + */ +struct hash_entry +{ + void *k, *v; + uint64_t h; + struct hash_entry *hashNext; + struct hash_entry *listNext; + struct hash_entry *listPrev; +}; +typedef struct hash_entry CS_HashEntry_t; +typedef struct hash_entry * CS_HashEntryp; + +struct cs_hashtable { + const char *name; + CS_HashEntry_t *listHead; + CS_HashEntry_t *listTail; + CS_HashEntry_t *freeHead; + uint32_t tablelength; + CS_HashEntryp *table; + uint32_t entrycount; + uint32_t loadlimit; + uint32_t primeindex; + CS_Hash_KeyType_t keyType; + uint64_t (*hashfn) (void *k); + int32_t (*eqfn) (void *k1, void *k2); +}; +typedef struct cs_hashtable CS_HashTable_t; +typedef struct cs_hashtable * CS_HashTablep; + +/* + * This struct is only concrete here to allow the inlining of two of the + * accessor functions. + */ +struct cs_hashtable_itr +{ + CS_HashTablep h; + CS_HashEntryp e; +}; +typedef struct cs_hashtable_itr CS_HashTableItr_t; +typedef struct cs_hashtable_itr * CS_HashTableItrp; + + +/* + * indexFor + * */ +static inline uint32_t +indexFor(uint32_t tablelength, uint32_t hashvalue) { + return (hashvalue % tablelength); +}; + + +/* + * Free the key + */ +#define freekey(X) free(X) + +/***************************************************************************** + * cs_create_hashtable + + * @name cs_create_hashtable + * @param name hash name string + * @param minsize minimum initial size of hashtable + * @param hashfunction function for hashing keys + * @param key_eq_fn function for determining key equality + * @param keytype set to true if key is an allocated structure, false otherwise + * @return newly created hashtable or NULL on failure + */ + +CS_HashTablep +cs_create_hashtable(const char *name, uint32_t minsize, + uint64_t (*hashfunction) (void*), + int32_t (*key_eq_fn) (void*,void*), + CS_Hash_KeyType_t keytype); + +/***************************************************************************** + * cs_hashtable_insert + + * @name cs_hashtable_insert + * @param h the hashtable to insert into + * @param k the key - hashtable claims ownership and will free on removal + * @param v the value - does not claim ownership + * @return non-zero for successful insertion + * + * This function will cause the table to expand if the insertion would take + * the ratio of entries to table size over the maximum load factor. + * + * This function does not check for repeated insertions with a duplicate key. + * The value returned when using a duplicate key is undefined -- when + * the hashtable changes size, the order of retrieval of duplicate key + * entries is reversed. + * If in doubt, remove before insert. + */ + +int32_t cs_hashtable_insert(CS_HashTablep h, void *k, void *v); + +#define DEFINE_HASHTABLE_INSERT(fncname, keytype, valuetype) \ +int32_t fncname (CS_HashTablep h, keytype *k, valuetype *v) \ +{ \ + return cs_hashtable_insert(h,k,v); \ +} + +/***************************************************************************** + * cs_hashtable_search + + * @name cs_hashtable_search + * @param h the hashtable to search + * @param k the key to search for - does not claim ownership + * @return the value associated with the key, or NULL if none found + */ + +void *cs_hashtable_search(CS_HashTablep h, void *k); + +#define DEFINE_HASHTABLE_SEARCH(fncname, keytype, valuetype) \ +valuetype * fncname (CS_HashTablep h, keytype *k) \ +{ \ + return (valuetype *) (cs_hashtable_search(h,k)); \ +} + +/***************************************************************************** + * cs_hashtable_remove + + * @name cs_hashtable_remove + * @param h the hashtable to remove the item from + * @param k the key to search for - does not claim ownership + * @return the value associated with the key, or NULL if none found + */ + +void *cs_hashtable_remove(CS_HashTablep h, void *k); + +#define DEFINE_HASHTABLE_REMOVE(fncname, keytype, valuetype) \ +valuetype * fncname (CS_HashTablep h, keytype *k) \ +{ \ + return (valuetype *) (cs_hashtable_remove(h,k)); \ +} + + +/***************************************************************************** + * cs_hashtable_count + + * @name cs_hashtable_count + * @param h the hashtable + * @return the number of items stored in the hashtable + */ +static __inline uint32_t +cs_hashtable_count(CS_HashTablep h) +{ + return h->entrycount; +} + + +/***************************************************************************** + * cs_hashtable_destroy + + * @name cs_hashtable_destroy + * @param h the hashtable + * @param free_values whether to call 'free' on the remaining values + */ + +void cs_hashtable_destroy(CS_HashTablep h, int32_t free_values); + +/***************************************************************************** + * cs_hashtable_change + * + * function to change the value associated with a key, where there already + * exists a value bound to the key in the hashtable. + * Source due to Holger Schemel. + * + * @name cs_hashtable_change + * @param h the hashtable + * @param key + * @param value + * + */ +int32_t cs_hashtable_change(CS_HashTablep h, void *k, void *v); + +/* + * cs_hashtable_iterator + */ + +static __inline void +cs_hashtable_iterator(CS_HashTablep h, CS_HashTableItr_t *itr) { + itr->h = h; + itr->e = h->listHead; +} + +/* + * cs_hashtable_iterator_key + * - return the value of the (key,value) pair at the current position + */ + +static __inline void * +cs_hashtable_iterator_key(CS_HashTableItrp i) +{ + return i->e->k; +} + +/* + * value - return the value of the (key,value) pair at the current position + */ + +static __inline void * +cs_hashtable_iterator_value(CS_HashTableItrp i) +{ + return i->e->v; +} + +/* + * advance - advance the iterator to the next element + * returns zero if advanced to end of table + */ + +static __inline int32_t +cs_hashtable_iterator_advance(CS_HashTableItrp itr) { + if (itr->e != NULL) + return (itr->e = itr->e->listNext) == NULL ? 0 : -1; + return 0; +} + +/* + * remove - remove current element and advance the iterator to the next element + * NB: if you need the value to free it, read it before + * removing. ie: beware memory leaks! + * returns zero if advanced to end of table + */ + +int32_t cs_hashtable_iterator_remove(CS_HashTableItrp itr); + +/* + * search - overwrite the supplied iterator, to point to the entry + * matching the supplied key. + * h points to the hashtable to be searched. + * returns zero if not found. + */ +int32_t cs_hashtable_iterator_search(CS_HashTableItrp itr, + CS_HashTablep h, void *k); + +#define DEFINE_HASHTABLE_ITERATOR_SEARCH(fncname, keytype) \ +int32_t fncname (CS_HashTableItrp i, CS_HashTablep h, keytype *k) \ +{ \ + return (cs_hashtable_iterator_search(i,h,k)); \ +} + +#endif /* __CS_HASHTABLE_H__ */ + diff --git a/Esm/ib/include/cs_log.h b/Esm/ib/include/cs_log.h new file mode 100644 index 0000000..b0795e5 --- /dev/null +++ b/Esm/ib/include/cs_log.h @@ -0,0 +1,1212 @@ +/* BEGIN_ICS_COPYRIGHT2 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + * ** END_ICS_COPYRIGHT2 ****************************************/ + +/************************************************************************ + * + * FILE NAME + * cs_log.h + * + * DESCRIPTION + * Logging and Tracing subsystem definition + * + * DATA STRUCTURES + * + * FUNCTIONS + * vs_log_control + * + * DEPENDENCIES + * ib_types.h + * + * + * HISTORY + * + * NAME DATE REMARKS + * paw 10/18/01 Initial creation of file. + * joc 10/26/01 Updates based on discussions and internal review + * golio 3/20/01 Added VIEO_VSNET_MOD_ID. + * + * + ************************************************************************/ + +#ifndef __VIEO_VS_LOG__ +#define __VIEO_VS_LOG__ +#include +#include +#include +#include +#include + +#ifndef stringize +#define stringize(x) #x +#endif +#ifndef add_quotes +#define add_quotes(x) stringize(x) +#endif + +#ifdef __VXWORKS__ + +#include +#include +#include "bspcommon/h/sysPrintf.h" + +#define CS64 "ll" +#define LogVal_t uint32_t +#define LogVal64_t uint64_t + +#else + +#define Log_StrDup(x) (x) + +#define sysPrintf printf + +#include + +#if __WORDSIZE == 64 +#define CS64 "l" +#define LogVal_t uint64_t +#define LogVal64_t uint64_t +#define LOG_PTR(x) ((uint64_t)(x)) +#elif __WORDSIZE == 32 +#define CS64 "L" +#define LogVal_t uint32_t +#define LogVal64_t uint64_t +#define LOG_PTR(x) ((uint32_t)(x)) +#else +#error "__WORDSIZE not 64 nor 32" +#endif + +#endif + +#define CS64x CS64"x" +#define CS64X CS64"X" +#define CS64d CS64"d" +#define CS64o CS64"o" +#define CS64u CS64"u" + +/* + * Convienience formatting macros for standardizing log messages + */ +#define FMT_U64 "0x%.16" CS64x + +#define FMT_GID "0x%.16" CS64x ":%.16" CS64x + +#define GIDPRINTARGS(GID) ntoh64(alignArray64(&GID[0])), ntoh64(alignArray64(&GID[8])) + +static __inline__ uint64_t +alignArray64(uint8_t * array) { + uint64_t rv; + memcpy(&rv, array, sizeof(rv)); + return rv; +} + +/************************************************************************ + Severity mask usage. + + Severity mask values are used to allow selection of logging information + to be output to the error/trace log. + It is possible to add new log severity values as + requirements are discovered in the future without impacting existing + code. + + ************************************************************************/ + +/************************************************************************/ +/** Define Severity values **********************************************/ +/************************************************************************/ +/** The VS_LOG_CSM_* constants below are only for internal use in **/ +/** smCsm functions. DO NOT USE THEM DIRECTLY IN ANY OTHER MACROS/FUNCS*/ +/************************************************************************/ + +#define VS_LOG_NONE (0) /* special for vs_syslog_output_message */ +#define VS_LOG_FATAL (0x00001) /* Fatal error */ +#define VS_LOG_CSM_ERROR (0x00002) /* Actionable error */ +#define VS_LOG_CSM_WARN (0x00004) /* Actionable warning */ +#define VS_LOG_CSM_NOTICE (0x00008) /* Actionable notice */ +#define VS_LOG_CSM_INFO (0x00010) /* Actionable info */ +#define VS_LOG_ERROR (0x00020) /* Recoverable error */ +#define VS_LOG_WARN (0x00040) /* Log warn information */ +#define VS_LOG_NOTICE (0x00080) /* Notice level */ +#define VS_LOG_INFINI_INFO (0x00100) /* Infini Info Debug information msgs */ +#define VS_LOG_INFO (0x00200) /* Debug information Messages */ +#define VS_LOG_VERBOSE (0x00400) /* Verbose information */ +#define VS_LOG_DATA (0x00800) /* Binary data */ +#define VS_LOG_DEBUG1 (0x01000) /* debug1 information */ +#define VS_LOG_DEBUG2 (0x02000) /* debug2 information */ +#define VS_LOG_DEBUG3 (0x04000) /* debug3 information */ +#define VS_LOG_DEBUG4 (0x08000) /* debug4 information */ +#define VS_LOG_ENTER (0x10000) /* Function entry */ +#define VS_LOG_ARGS (0x20000) /* function entry with more args */ +#define VS_LOG_EXIT (0x40000) /* Function exit */ + +/* combination flags which can be used when initialize mask */ +#define VS_LOG_OFF (0x00000000) /* Disable all logging */ +#define VS_LOG_TRACE (VS_LOG_ARGS|VS_LOG_ENTER|VS_LOG_EXIT) /* Tracing ON .. enter/exit/args */ +#define VS_LOG_ALL (0xFFFFFFFF) /* Enable all debugging info */ + +#define NONDEBUG_LOG_MASK (VS_LOG_FATAL|VS_LOG_CSM_ERROR|VS_LOG_CSM_WARN \ + |VS_LOG_CSM_NOTICE|VS_LOG_CSM_INFO|VS_LOG_ERROR|VS_LOG_WARN \ + |VS_LOG_NOTICE|VS_LOG_INFINI_INFO) +#define DEFAULT_LOG_MASK NONDEBUG_LOG_MASK + +/************************************************************************/ +/** Define Module IDs ***************************************************/ +/* Module IDs are used to identify the module that generated the error.*/ +/* These values may be used in the output facility for filtering. */ +/************************************************************************/ + +#define VIEO_NONE_MOD_ID 0 // special for vs_syslog_output_message + // LogMask for this module is not used + // this must be modid 0 +#define VIEO_CS_MOD_ID 1 /* Library Modules */ +#define VIEO_MAI_MOD_ID 2 +#define VIEO_CAL_MOD_ID 3 +#define VIEO_DRIVER_MOD_ID 4 + +#define VIEO_IF3_MOD_ID 5 + +#define VIEO_SM_MOD_ID 6 /* Subnet Mgr */ +#define VIEO_SA_MOD_ID 7 /* Subnet Administrator */ + +#define VIEO_PM_MOD_ID 8 /* Performance Mgr */ +#define VIEO_PA_MOD_ID 9 /* Performance Administrator */ +#define VIEO_BM_MOD_ID 10 /* Baseboard Mgr */ + +#define VIEO_FE_MOD_ID 11 /* Fabric Executive */ + +#define VIEO_APP_MOD_ID 12 /* Generic VIEO mod id */ + /* also used for all CSM messages */ +#define VIEO_LAST_MOD_ID 13 /* last in list, used to size array */ +// the present implementation is limited to 32 module ids (0-31) +// However that limitation only occurs in cs_log_set_mods_mask API +// and the internals of cs_log_translate_level + +#define VS_MOD_ALL (0xffffffff) /* all modules */ + +#define DEFAULT_LOG_MODS (VS_MOD_ALL & ~(1< +#define IB_FATAL_ERROR_NODUMP(p1) do {\ + smCsmLogMessage(CSM_SEV_NOTICE, CSM_COND_SM_SHUTDOWN, NULL, NULL, p1); \ + ESM_LOG_FINAL_ESMFATAL(p1); \ +} while (0) +#define IB_FATAL_ERROR(p1) do {\ + IB_FATAL_ERROR_NODUMP(p1); \ + abort(); \ +} while (0) +#else +#define IB_FATAL_ERROR_NODUMP(p1) do { \ + smCsmLogMessage(CSM_SEV_NOTICE, CSM_COND_SM_SHUTDOWN, NULL, NULL, p1); \ + vs_log_output(VS_LOG_FATAL, LOCAL_MOD_ID, __func__, NULL, "%s", p1); \ + exit(2); \ +} while (0) +#define IB_FATAL_ERROR(p1) do { \ + smCsmLogMessage(CSM_SEV_NOTICE, CSM_COND_SM_SHUTDOWN, NULL, NULL, p1); \ + vs_log_output(VS_LOG_FATAL, LOCAL_MOD_ID, __func__, NULL, "%s", p1); \ + vs_fatal_error((uint8_t *)(p1)); \ +} while (0) +#endif /* __VXWORKS__ */ + +/******************************* + * RECOVERABLE ERROR + ******************************/ + +#ifdef __VXWORKS__ +// TBD - test LOG_IS_INTERESTED to pick up Mask & Filter +// TBD output module name in VxWorks messages +#define IB_LOG_ERROR0(p1) ESM_LOG_FINAL_ESMERROR0(p1) +#define IB_LOG_MOD_ERROR0(modid, p1) ESM_LOG_FINAL_ESMERROR0(p1) +#define IB_LOG_ERROR(p1,p2) ESM_LOG_FINAL_ESMERROR(p1, p2) +#define IB_LOG_MOD_ERROR(modid, p1,p2) ESM_LOG_FINAL_ESMERROR(p1, p2) +#define IB_LOG_ERRORX(p1,p2) ESM_LOG_FINAL_ESMERRORX(p1, p2) +#define IB_LOG_MOD_ERRORX(modid, p1,p2) ESM_LOG_FINAL_ESMERRORX(p1, p2) +#define IB_LOG_ERRORLX(p1,p2) ESM_LOG_FINAL_ESMERRORLX(p1, p2) +#define IB_LOG_MOD_ERRORLX(modid, p1,p2) ESM_LOG_FINAL_ESMERRORLX(p1, p2) +#define IB_LOG_ERROR64(p1,p2) ESM_LOG_FINAL_ESMERROR64(p1, p2) +#define IB_LOG_MOD_ERROR64(modid, p1,p2) ESM_LOG_FINAL_ESMERROR64(p1, p2) +#define IB_LOG_ERRORSTR(p1,p2) ESM_LOG_FINAL_ESMERRORSTR(p1, p2) +#define IB_LOG_MOD_ERRORSTR(modid, p1,p2) ESM_LOG_FINAL_ESMERRORSTR(p1, p2) +#define IB_LOG_ERRORRC(p1,p2) ESM_LOG_FINAL_ESMERRORSTR(p1, cs_convert_status(p2)) +#define IB_LOG_MOD_ERRORRC(modid, p1,p2) ESM_LOG_FINAL_ESMERRORSTR(p1, cs_convert_status(p2)) +#else +#define IB_LOG_ERROR0(p1) IB_LOG_FMT0(VS_LOG_ERROR, p1) +#define IB_LOG_MOD_ERROR0(modid, p1) IB_LOG_MOD_FMT0(VS_LOG_ERROR, modid, p1) +#define IB_LOG_ERROR(p1, p2) IB_LOG_FMTU(VS_LOG_ERROR, p1, p2) +#define IB_LOG_MOD_ERROR(modid, p1, p2) IB_LOG_MOD_FMTU(VS_LOG_ERROR, modid, p1, p2) +#define IB_LOG_ERRORX(p1, p2) IB_LOG_FMTX(VS_LOG_ERROR, p1, p2) +#define IB_LOG_MOD_ERRORX(modid, p1, p2) IB_LOG_MOD_FMTX(VS_LOG_ERROR, modid, p1, p2) +#define IB_LOG_ERRORLX(p1, p2) IB_LOG_FMTLX(VS_LOG_ERROR, p1, p2) +#define IB_LOG_MOD_ERRORLX(modid, p1, p2) IB_LOG_MOD_FMTLX(VS_LOG_ERROR, modid, p1, p2) +#define IB_LOG_ERROR64(p1, p2) IB_LOG_FMT64(VS_LOG_ERROR, p1, p2) +#define IB_LOG_MOD_ERROR64(modid, p1, p2) IB_LOG_MOD_FMT64(VS_LOG_ERROR, modid, p1, p2) +#define IB_LOG_ERRORSTR(p1, p2) IB_LOG_FMTSTR(VS_LOG_ERROR, p1, p2) +#define IB_LOG_MOD_ERRORSTR(modid, p1, p2) IB_LOG_MOD_FMTSTR(VS_LOG_ERROR, modid, p1, p2) +#define IB_LOG_ERRORRC(p1, p2) IB_LOG_FMTRC(VS_LOG_ERROR, p1, p2) +#define IB_LOG_MOD_ERRORRC(modid, p1, p2) IB_LOG_MOD_FMTRC(VS_LOG_ERROR, modid, p1, p2) +#endif /* __VXWORKS__ */ +// for cs_log* and hence these macros +// Log_StrDup will be performed internally as part of formatting the message +#define IB_LOG_ERROR_FMT(func, fmt...) \ + cs_log(VS_LOG_ERROR, func, ## fmt) +#define IB_LOG_MOD_ERROR_FMT(modid, func, fmt...) \ + cs_log_mod(VS_LOG_ERROR, modid, func, ## fmt) +#define IB_LOG_ERROR_FMT_VF(vf, func, fmt...) \ + cs_log_vf(VS_LOG_ERROR, vf, func, ## fmt) +#define IB_LOG_MOD_ERROR_FMT_VF(modid, vf, func, fmt...) \ + cs_log_mod_vf(VS_LOG_ERROR, modid, vf, func, ## fmt) + +/******************************* + * WARNING + ******************************/ + +#ifdef __VXWORKS__ +// TBD - test LOG_IS_INTERESTED to pick up Mask & Filter +// TBD output module name in VxWorks messages +#define IB_LOG_WARN0(p1) ESM_LOG_FINAL_ESMWARNING0(p1) +#define IB_LOG_MOD_WARN0(modid, p1) ESM_LOG_FINAL_ESMWARNING0(p1) +#define IB_LOG_WARN(p1, p2) ESM_LOG_FINAL_ESMWARNING(p1, p2) +#define IB_LOG_MOD_WARN(modid, p1, p2) ESM_LOG_FINAL_ESMWARNING(p1, p2) +#define IB_LOG_WARNX(p1, p2) ESM_LOG_FINAL_ESMWARNINGX(p1, p2) +#define IB_LOG_MOD_WARNX(modid, p1, p2) ESM_LOG_FINAL_ESMWARNINGX(p1, p2) +#define IB_LOG_WARNLX(p1, p2) ESM_LOG_FINAL_ESMWARNINGLX(p1, p2) +#define IB_LOG_MOD_WARNLX(modid, p1, p2) ESM_LOG_FINAL_ESMWARNINGLX(p1, p2) +#define IB_LOG_WARN64(p1, p2) ESM_LOG_FINAL_ESMWARNING64(p1, p2) +#define IB_LOG_MOD_WARN64(modid, p1, p2) ESM_LOG_FINAL_ESMWARNING64(p1, p2) +#define IB_LOG_WARNSTR(p1, p2) ESM_LOG_FINAL_ESMWARNINGSTR(p1, p2) +#define IB_LOG_MOD_WARNSTR(modid, p1, p2) ESM_LOG_FINAL_ESMWARNINGSTR(p1, p2) +#define IB_LOG_WARNRC(p1, p2) ESM_LOG_FINAL_ESMWARNINGSTR(p1, cs_convert_status(p2)) +#define IB_LOG_MOD_WARNRC(p1, p2) ESM_LOG_FINAL_ESMWARNINGSTR(p1, cs_convert_status(p2)) +#else +#define IB_LOG_WARN0(p1) IB_LOG_FMT0(VS_LOG_WARN, p1) +#define IB_LOG_MOD_WARN0(modid, p1) IB_LOG_MOD_FMT0(VS_LOG_WARN, modid, p1) +#define IB_LOG_WARN(p1, p2) IB_LOG_FMTU(VS_LOG_WARN, p1, p2) +#define IB_LOG_MOD_WARN(modid, p1, p2) IB_LOG_MOD_FMTU(VS_LOG_WARN, modid, p1, p2) +#define IB_LOG_WARNX(p1, p2) IB_LOG_FMTX(VS_LOG_WARN, p1, p2) +#define IB_LOG_MOD_WARNX(modid, p1, p2) IB_LOG_MOD_FMTX(VS_LOG_WARN, modid, p1, p2) +#define IB_LOG_WARNLX(p1, p2) IB_LOG_FMTLX(VS_LOG_WARN, p1, p2) +#define IB_LOG_MOD_WARNLX(modid, p1, p2) IB_LOG_MOD_FMTLX(VS_LOG_WARN, modid, p1, p2) +#define IB_LOG_WARN64(p1, p2) IB_LOG_FMT64(VS_LOG_WARN, p1, p2) +#define IB_LOG_MOD_WARN64(modid, p1, p2) IB_LOG_MOD_FMT64(VS_LOG_WARN, modid, p1, p2) +#define IB_LOG_WARNSTR(p1, p2) IB_LOG_FMTSTR(VS_LOG_WARN, p1, p2) +#define IB_LOG_MOD_WARNSTR(modid, p1, p2) IB_LOG_MOD_FMTSTR(VS_LOG_WARN, modid, p1, p2) +#define IB_LOG_WARNRC(p1, p2) IB_LOG_FMTRC(VS_LOG_WARN, p1, p2) +#define IB_LOG_MOD_WARNRC(modid, p1, p2) IB_LOG_MOD_FMTRC(VS_LOG_WARN, modid, p1, p2) +#endif /* __VXWORKS__ */ +// for cs_log* and hence these macros +// Log_StrDup will be performed internally as part of formatting the message +#define IB_LOG_WARN_FMT(func, fmt...) \ + cs_log(VS_LOG_WARN, func, ## fmt) +#define IB_LOG_MOD_WARN_FMT(modid, func, fmt...) \ + cs_log_mod(VS_LOG_WARN, modid, func, ## fmt) +#define IB_LOG_WARN_FMT_VF(vf, func, fmt...) \ + cs_log_vf(VS_LOG_WARN, vf, func, ## fmt) +#define IB_LOG_MOD_WARN_FMT_VF(modid, vf, func, fmt...) \ + cs_log_mod_vf(VS_LOG_WARN, modid, vf, func, ## fmt) + +/******************************* + * NOTICE + ******************************/ + +#ifdef __VXWORKS__ +// TBD - test LOG_IS_INTERESTED to pick up Mask & Filter +// TBD output module name in VxWorks messages +#define IB_LOG_NOTICE0(p1) ESM_LOG_FINAL_ESMNOTICE0(p1) +#define IB_LOG_MOD_NOTICE0(modid, p1) ESM_LOG_FINAL_ESMNOTICE0(p1) +#define IB_LOG_NOTICE(p1, p2) ESM_LOG_FINAL_ESMNOTICE(p1, p2) +#define IB_LOG_MOD_NOTICE(modid, p1, p2) ESM_LOG_FINAL_ESMNOTICE(p1, p2) +#define IB_LOG_NOTICEX(p1, p2) ESM_LOG_FINAL_ESMNOTICEX(p1, p2) +#define IB_LOG_MOD_NOTICEX(modid, p1, p2) ESM_LOG_FINAL_ESMNOTICEX(p1, p2) +#define IB_LOG_NOTICELX(p1, p2) ESM_LOG_FINAL_ESMNOTICELX(p1, p2) +#define IB_LOG_MOD_NOTICELX(modid, p1, p2) ESM_LOG_FINAL_ESMNOTICELX(p1, p2) +#define IB_LOG_NOTICE64(p1, p2) ESM_LOG_FINAL_ESMNOTICE64(p1, p2) +#define IB_LOG_MOD_NOTICE64(modid, p1, p2) ESM_LOG_FINAL_ESMNOTICE64(p1, p2) +#define IB_LOG_NOTICESTR(p1, p2) ESM_LOG_FINAL_ESMNOTICESTR(p1, p2) +#define IB_LOG_MOD_NOTICESTR(modid, p1, p2) ESM_LOG_FINAL_ESMNOTICESTR(p1, p2) +#define IB_LOG_NOTICERC(p1, p2) ESM_LOG_FINAL_ESMNOTICESTR(p1, cs_convert_status(p2)) +#define IB_LOG_MOD_NOTICERC(modid, p1, p2) ESM_LOG_FINAL_ESMNOTICESTR(p1, cs_convert_status(p2)) +#else +#define IB_LOG_NOTICE0(p1) IB_LOG_FMT0(VS_LOG_NOTICE, p1) +#define IB_LOG_MOD_NOTICE0(modid, p1) IB_LOG_MOD_FMT0(VS_LOG_NOTICE, modid, p1) +#define IB_LOG_NOTICE(p1, p2) IB_LOG_FMTU(VS_LOG_NOTICE, p1, p2) +#define IB_LOG_MOD_NOTICE(modid, p1, p2) IB_LOG_MOD_FMTU(VS_LOG_NOTICE, modid, p1, p2) +#define IB_LOG_NOTICEX(p1, p2) IB_LOG_FMTX(VS_LOG_NOTICE, p1, p2) +#define IB_LOG_MOD_NOTICEX(modid, p1, p2) IB_LOG_MOD_FMTX(VS_LOG_NOTICE, modid, p1, p2) +#define IB_LOG_NOTICELX(p1, p2) IB_LOG_FMTLX(VS_LOG_NOTICE, p1, p2) +#define IB_LOG_MOD_NOTICELX(modid, p1, p2) IB_LOG_MOD_FMTLX(VS_LOG_NOTICE, modid, p1, p2) +#define IB_LOG_NOTICE64(p1, p2) IB_LOG_FMT64(VS_LOG_NOTICE, p1, p2) +#define IB_LOG_MOD_NOTICE64(modid, p1, p2) IB_LOG_MOD_FMT64(VS_LOG_NOTICE, modid, p1, p2) +#define IB_LOG_NOTICESTR(p1, p2) IB_LOG_FMTSTR(VS_LOG_NOTICE, p1, p2) +#define IB_LOG_MOD_NOTICESTR(modid, p1, p2) IB_LOG_MOD_FMTSTR(VS_LOG_NOTICE, modid, p1, p2) +#define IB_LOG_NOTICERC(p1, p2) IB_LOG_FMTRC(VS_LOG_NOTICE, p1, p2) +#define IB_LOG_MOD_NOTICERC(modid, p1, p2) IB_LOG_MOD_FMTRC(VS_LOG_NOTICE, modid, p1, p2) +#endif /* __VXWORKS__ */ +// for cs_log* and hence these macros +// Log_StrDup will be performed internally as part of formatting the message +#define IB_LOG_NOTICE_FMT(func, fmt...) \ + cs_log(VS_LOG_NOTICE, func, ## fmt) +#define IB_LOG_MOD_NOTICE_FMT(modid, func, fmt...) \ + cs_log_mod(VS_LOG_NOTICE, modid, func, ## fmt) +#define IB_LOG_NOTICE_FMT_VF(vf, func, fmt...) \ + cs_log_vf(VS_LOG_NOTICE, vf, func, ## fmt) +#define IB_LOG_MOD_NOTICE_FMT_VF(modid, vf, func, fmt...) \ + cs_log_mod_vf(VS_LOG_NOTICE, modid, vf, func, ## fmt) + +/******************************* + * INFO INFINI_INFO + ******************************/ + +#ifdef __VXWORKS__ +// TBD - test LOG_IS_INTERESTED to pick up Mask & Filter +// TBD output module name in VxWorks messages + +// we put it in our logging system's Program_Info +#define IB_LOG_INFINI_INFO0(p1) ESM_LOG_ESMINFO0(p1) +#define IB_LOG_MOD_INFINI_INFO0(modid, p1) ESM_LOG_ESMINFO0(p1) +#define IB_LOG_INFINI_INFO(p1, p2) ESM_LOG_ESMINFO(p1, p2) +#define IB_LOG_MOD_INFINI_INFO(modid, p1, p2) ESM_LOG_ESMINFO(p1, p2) +#define IB_LOG_INFINI_INFOX(p1, p2) ESM_LOG_ESMINFOX(p1, p2) +#define IB_LOG_MOD_INFINI_INFOX(modid, p1, p2) ESM_LOG_ESMINFOX(p1, p2) +#define IB_LOG_INFINI_INFOLX(p1, p2) ESM_LOG_ESMINFOLX(p1, p2) +#define IB_LOG_MOD_INFINI_INFOLX(modid, p1, p2) ESM_LOG_ESMINFOLX(p1, p2) +#define IB_LOG_INFINI_INFO64(p1, p2) ESM_LOG_ESMINFO64(p1, p2) +#define IB_LOG_MOD_INFINI_INFO64(modid, p1, p2) ESM_LOG_ESMINFO64(p1, p2) +#define IB_LOG_INFINI_INFOSTR(p1, p2) ESM_LOG_ESMINFOSTR(p1, p2) +#define IB_LOG_MOD_INFINI_INFOSTR(modid, p1, p2) ESM_LOG_ESMINFOSTR(p1, p2) +#define IB_LOG_INFINI_INFORC(p1, p2) ESM_LOG_ESMINFOSTR(p1, cs_convert_status(p2)) +#define IB_LOG_MOD_INFINI_INFORC(modid, p1, p2) ESM_LOG_ESMINFOSTR(p1, cs_convert_status(p2)) +#else +#define IB_LOG_INFINI_INFO0(p1) IB_LOG_FMT0(VS_LOG_INFINI_INFO, p1) +#define IB_LOG_MOD_INFINI_INFO0(modid, p1) IB_LOG_MOD_FMT0(VS_LOG_INFINI_INFO, modid, p1) +#define IB_LOG_INFINI_INFO(p1, p2) IB_LOG_FMTU(VS_LOG_INFINI_INFO, p1, p2) +#define IB_LOG_MOD_INFINI_INFO(modid, p1, p2) IB_LOG_MOD_FMTU(VS_LOG_INFINI_INFO, modid, p1, p2) +#define IB_LOG_INFINI_INFOX(p1, p2) IB_LOG_FMTX(VS_LOG_INFINI_INFO, p1, p2) +#define IB_LOG_MOD_INFINI_INFOX(modid, p1, p2) IB_LOG_MOD_FMTX(VS_LOG_INFINI_INFO, modid, p1, p2) +#define IB_LOG_INFINI_INFOLX(p1, p2) IB_LOG_FMTLX(VS_LOG_INFINI_INFO, p1, p2) +#define IB_LOG_MOD_INFINI_INFOLX(modid, p1, p2) IB_LOG_MOD_FMTLX(VS_LOG_INFINI_INFO, modid, p1, p2) +#define IB_LOG_INFINI_INFO64(p1, p2) IB_LOG_FMT64(VS_LOG_INFINI_INFO, p1, p2) +#define IB_LOG_MOD_INFINI_INFO64(modid, p1, p2) IB_LOG_MOD_FMT64(VS_LOG_INFINI_INFO, modid, p1, p2) +#define IB_LOG_INFINI_INFOSTR(p1, p2) IB_LOG_FMTSTR(VS_LOG_INFINI_INFO, p1, p2) +#define IB_LOG_MOD_INFINI_INFOSTR(modid, p1, p2) IB_LOG_MOD_FMTSTR(VS_LOG_INFINI_INFO, modid, p1, p2) +#define IB_LOG_INFINI_INFORC(p1, p2) IB_LOG_FMTRC(VS_LOG_INFINI_INFO, p1, p2) +#define IB_LOG_MOD_INFINI_INFORC(modid, p1, p2) IB_LOG_MOD_FMTRC(VS_LOG_INFINI_INFO, modid, p1, p2) +#endif /* __VXWORKS__ */ +// for cs_log* and hence these macros +// Log_StrDup will be performed internally as part of formatting the message +#define IB_LOG_INFINI_INFO_FMT(func, fmt...) \ + cs_log(VS_LOG_INFINI_INFO, func, ## fmt) +#define IB_LOG_MOD_INFINI_INFO_FMT(modid, func, fmt...) \ + cs_log_mod(VS_LOG_INFINI_INFO, modid, func, ## fmt) +#define IB_LOG_INFINI_INFO_FMT_VF(vf, func, fmt...) \ + cs_log_vf(VS_LOG_INFINI_INFO, vf, func, ## fmt) +#define IB_LOG_MOD_INFINI_INFO_FMT_VF(modid, vf, func, fmt...) \ + cs_log_mod_vf(VS_LOG_INFINI_INFO, modid, vf, func, ## fmt) + +#ifdef VIEO_TRACE_DISABLED +#define IB_LOG_INFO0(p1) do { } while(0) +#define IB_LOG_MOD_INFO0(modid, p1) do { } while(0) +#define IB_LOG_INFO(p1, p2) do { } while(0) +#define IB_LOG_MOD_INFO(modid, p1, p2) do { } while(0) +#define IB_LOG_INFOX(p1, p2) do { } while(0) +#define IB_LOG_MOD_INFOX(modid, p1, p2) do { } while(0) +#define IB_LOG_INFOLX(p1, p2) do { } while(0) +#define IB_LOG_MOD_INFOLX(modid, p1, p2) do { } while(0) +#define IB_LOG_INFO64(p1, p2) do { } while(0) +#define IB_LOG_MOD_INFO64(modid, p1, p2) do { } while(0) +#define IB_LOG_INFOSTR(p1, p2) do { } while(0) +#define IB_LOG_MOD_INFOSTR(modid, p1, p2) do { } while(0) +#define IB_LOG_INFORC(p1, p2) do { } while(0) +#define IB_LOG_MOD_INFORC(modid, p1, p2) do { } while(0) +#define IB_LOG_INFO_FMT(func, fmt...) do { } while(0) +#define IB_LOG_MOD_INFO_FMT(modid, func, fmt...) do { } while(0) +#define IB_LOG_INFO_FMT_VF(vf, func, fmt...) do { } while(0) +#define IB_LOG_MOD_INFO_FMT_VF(modid, vf, func, fmt...) do { } while(0) +#else +#define IB_LOG_INFO0(p1) IB_LOG_FMT0(VS_LOG_INFO, p1) +#define IB_LOG_MOD_INFO0(modid, p1) IB_LOG_MOD_FMT0(VS_LOG_INFO, modid, p1) +#define IB_LOG_INFO(p1, p2) IB_LOG_FMTU(VS_LOG_INFO, p1, p2) +#define IB_LOG_MOD_INFO(modid, p1, p2) IB_LOG_MOD_FMTU(VS_LOG_INFO, modid, p1, p2) +#define IB_LOG_INFOX(p1, p2) IB_LOG_FMTX(VS_LOG_INFO, p1, p2) +#define IB_LOG_MOD_INFOX(modid, p1, p2) IB_LOG_MOD_FMTX(VS_LOG_INFO, modid, p1, p2) +#define IB_LOG_INFOLX(p1, p2) IB_LOG_FMTLX(VS_LOG_INFO, p1, p2) +#define IB_LOG_MOD_INFOLX(modid, p1, p2) IB_LOG_MOD_FMTLX(VS_LOG_INFO, modid, p1, p2) +#define IB_LOG_INFO64(p1, p2) IB_LOG_FMT64(VS_LOG_INFO, p1, p2) +#define IB_LOG_MOD_INFO64(modid, p1, p2) IB_LOG_MOD_FMT64(VS_LOG_INFO, modid, p1, p2) +#define IB_LOG_INFOSTR(p1, p2) IB_LOG_FMTSTR(VS_LOG_INFO, p1, p2) +#define IB_LOG_MOD_INFOSTR(modid, p1, p2) IB_LOG_MOD_FMTSTR(VS_LOG_INFO, modid, p1, p2) +#define IB_LOG_INFORC(p1, p2) IB_LOG_FMTRC(VS_LOG_INFO, p1, p2) +#define IB_LOG_MOD_INFORC(modid, p1, p2) IB_LOG_MOD_FMTRC(VS_LOG_INFO, modid, p1, p2) +// for cs_log* and hence these macros +// Log_StrDup will be performed internally as part of formatting the message +#define IB_LOG_INFO_FMT(func, fmt...) \ + cs_log(VS_LOG_INFO, func, ## fmt) +#define IB_LOG_MOD_INFO_FMT(modid, func, fmt...) \ + cs_log_mod(VS_LOG_INFO, modid, func, ## fmt) +#define IB_LOG_INFO_FMT_VF(vf, func, fmt...) \ + cs_log_vf(VS_LOG_INFO, vf, func, ## fmt) +#define IB_LOG_MOD_INFO_FMT_VF(modid, vf, func, fmt...) \ + cs_log_mod_vf(VS_LOG_INFO, modid, vf, func, ## fmt) +#endif + +/******************************* + * DATA + ******************************/ + +#ifdef VIEO_TRACE_DISABLED +#define IB_LOG_DATA(p1, addr, len) do {} while(0) +#define IB_LOG_MOD_DATA(modid, p1, addr, len) do {} while(0) +#else +#ifdef __VXWORKS__ +// TBD output module name in VxWorks messages +#define IB_LOG_DATA(p1, addr, len) \ + do { if (IB_LOG_IS_INTERESTED(VS_LOG_DATA) && ! vs_log_filter() ) \ + LOG_DEBUG2(MOD_ESM, "%s: %F", LOG_PTR(p1), Log_MemoryDump(addr, len),0,0,0,0); \ + } while (0) +#define IB_LOG_MOD_DATA(modid, p1, addr, len) \ + do { if (IB_LOG_IS_INTERESTED_MOD(VS_LOG_DATA, modid) && ! vs_log_filter() ) \ + LOG_DEBUG2(MOD_ESM, "%s: %F", LOG_PTR(p1), Log_MemoryDump(addr, len),0,0,0,0); \ + } while (0) +#else +#define IB_LOG_DATA(p1, addr, len) \ + do { if (IB_LOG_IS_INTERESTED(VS_LOG_DATA) ) \ + vs_log_output_memory(VS_LOG_DATA, LOCAL_MOD_ID, __func__, NULL, p1, addr, len); \ + } while (0) +#define IB_LOG_MOD_DATA(modid, p1, addr, len) \ + do { if (IB_LOG_IS_INTERESTED_MOD(VS_LOG_DATA, modid) ) \ + vs_log_output_memory(VS_LOG_DATA, modid, __func__, NULL, p1, addr, len); \ + } while (0) +#endif +#endif + +/******************************* + * VERBOSE + ******************************/ + +#ifdef VIEO_TRACE_DISABLED +#define IB_LOG_VERBOSE0(p1) do { } while(0) +#define IB_LOG_MOD_VERBOSE0(modid, p1) do { } while(0) +#define IB_LOG_VERBOSE(p1, p2) do { } while(0) +#define IB_LOG_MOD_VERBOSE(modid, p1, p2) do { } while(0) +#define IB_LOG_VERBOSEX(p1, p2) do { } while(0) +#define IB_LOG_MOD_VERBOSEX(modid, p1, p2) do { } while(0) +#define IB_LOG_VERBOSELX(p1, p2) do { } while(0) +#define IB_LOG_MOD_VERBOSELX(modid, p1, p2) do { } while(0) +#define IB_LOG_VERBOSE64(p1, p2) do { } while(0) +#define IB_LOG_MOD_VERBOSE64(modid, p1, p2) do { } while(0) +#define IB_LOG_VERBOSESTR(p1, p2) do { } while(0) +#define IB_LOG_MOD_VERBOSESTR(modid, p1, p2) do { } while(0) +#define IB_LOG_VERBOSERC(p1, p2) do { } while(0) +#define IB_LOG_MOD_VERBOSERC(modid, p1, p2) do { } while(0) +#define IB_LOG_VERBOSE_FMT(func, fmt...) do { } while(0) +#define IB_LOG_MOD_VERBOSE_FMT(modid, func, fmt...) do { } while(0) +#define IB_LOG_VERBOSE_FMT_VF(vf, func, fmt...) do { } while(0) +#define IB_LOG_MOD_VERBOSE_FMT_VF(modid, vf, func, fmt...) do { } while(0) +#else +#define IB_LOG_VERBOSE0(p1) IB_LOG_FMT0(VS_LOG_VERBOSE, p1) +#define IB_LOG_MOD_VERBOSE0(modid, p1) IB_LOG_MOD_FMT0(VS_LOG_VERBOSE, modid, p1) +#define IB_LOG_VERBOSE(p1, p2) IB_LOG_FMTU(VS_LOG_VERBOSE, p1, p2) +#define IB_LOG_MOD_VERBOSE(modid, p1, p2) IB_LOG_MOD_FMTU(VS_LOG_VERBOSE, modid, p1, p2) +#define IB_LOG_VERBOSEX(p1, p2) IB_LOG_FMTX(VS_LOG_VERBOSE, p1, p2) +#define IB_LOG_MOD_VERBOSEX(modid, p1, p2) IB_LOG_MOD_FMTX(VS_LOG_VERBOSE, modid, p1, p2) +#define IB_LOG_VERBOSELX(p1, p2) IB_LOG_FMTLX(VS_LOG_VERBOSE, p1, p2) +#define IB_LOG_MOD_VERBOSELX(modid, p1, p2) IB_LOG_MOD_FMTLX(VS_LOG_VERBOSE, modid, p1, p2) +#define IB_LOG_VERBOSE64(p1, p2) IB_LOG_FMT64(VS_LOG_VERBOSE, p1, p2) +#define IB_LOG_MOD_VERBOSE64(modid, p1, p2) IB_LOG_MOD_FMT64(VS_LOG_VERBOSE, modid, p1, p2) +#define IB_LOG_VERBOSESTR(p1, p2) IB_LOG_FMTSTR(VS_LOG_VERBOSE, p1, p2) +#define IB_LOG_MOD_VERBOSESTR(modid, p1, p2) IB_LOG_MOD_FMTSTR(VS_LOG_VERBOSE, modid, p1, p2) +#define IB_LOG_VERBOSERC(p1, p2) IB_LOG_FMTRC(VS_LOG_VERBOSE, p1, p2) +#define IB_LOG_MOD_VERBOSERC(modid, p1, p2) IB_LOG_MOD_FMTRC(VS_LOG_VERBOSE, modid, p1, p2) +// for cs_log* and hence these macros +// Log_StrDup will be performed internally as part of formatting the message +#define IB_LOG_VERBOSE_FMT(func, fmt...) \ + cs_log(VS_LOG_VERBOSE, func, ## fmt) +#define IB_LOG_MOD_VERBOSE_FMT(modid, func, fmt...) \ + cs_log_mod(VS_LOG_VERBOSE, modid, func, ## fmt) +#define IB_LOG_VERBOSE_FMT_VF(vf, func, fmt...) \ + cs_log_vf(VS_LOG_VERBOSE, vf, func, ## fmt) +#define IB_LOG_MOD_VERBOSE_FMT_VF(modid, vf, func, fmt...) \ + cs_log_mod_vf(VS_LOG_VERBOSE, modid, vf, func, ## fmt) +#endif + +/******************************* + * DEBUG1 + ******************************/ + +#ifdef VIEO_TRACE_DISABLED +#define IB_LOG_DEBUG1_0(p1) do { } while(0) +#define IB_LOG_MOD_DEBUG1_0(modid, p1) do { } while(0) +#define IB_LOG_DEBUG1(p1, p2) do { } while(0) +#define IB_LOG_MOD_DEBUG1(modid, p1, p2) do { } while(0) +#define IB_LOG_DEBUG1X(p1, p2) do { } while(0) +#define IB_LOG_MOD_DEBUG1X(modid, p1, p2) do { } while(0) +#define IB_LOG_DEBUG1LX(p1, p2) do { } while(0) +#define IB_LOG_MOD_DEBUG1LX(modid, p1, p2) do { } while(0) +#define IB_LOG_DEBUG1_64(p1, p2) do { } while(0) +#define IB_LOG_MOD_DEBUG1_64(modid, p1, p2) do { } while(0) +#define IB_LOG_DEBUG1STR(p1, p2) do { } while(0) +#define IB_LOG_MOD_DEBUG1STR(modid, p1, p2) do { } while(0) +#define IB_LOG_DEBUG1RC(p1, p2) do { } while(0) +#define IB_LOG_MOD_DEBUG1RC(modid, p1, p2) do { } while(0) +#define IB_LOG_DEBUG1_FMT(func, fmt...) do { } while(0) +#define IB_LOG_MOD_DEBUG1_FMT(modid, func, fmt...) do { } while(0) +#define IB_LOG_DEBUG1_FMT_VF(vf, func, fmt...) do { } while(0) +#define IB_LOG_MOD_DEBUG1_FMT_VF(modid, vf, func, fmt...) do { } while(0) +#else +#define IB_LOG_DEBUG1_0(p1) IB_LOG_FMT0(VS_LOG_DEBUG1, p1) +#define IB_LOG_MOD_DEBUG1_0(modid, p1) IB_LOG_MOD_FMT0(VS_LOG_DEBUG1, modid, p1) +#define IB_LOG_DEBUG1(p1, p2) IB_LOG_FMTU(VS_LOG_DEBUG1, p1, p2) +#define IB_LOG_MOD_DEBUG1(modid, p1, p2) IB_LOG_MOD_FMTU(VS_LOG_DEBUG1, modid, p1, p2) +#define IB_LOG_DEBUG1X(p1, p2) IB_LOG_FMTX(VS_LOG_DEBUG1, p1, p2) +#define IB_LOG_MOD_DEBUG1X(modid, p1, p2) IB_LOG_MOD_FMTX(VS_LOG_DEBUG1, modid, p1, p2) +#define IB_LOG_DEBUG1LX(p1, p2) IB_LOG_FMTLX(VS_LOG_DEBUG1, p1, p2) +#define IB_LOG_MOD_DEBUG1LX(modid, p1, p2) IB_LOG_MOD_FMTLX(VS_LOG_DEBUG1, modid, p1, p2) +#define IB_LOG_DEBUG1_64(p1, p2) IB_LOG_FMT64(VS_LOG_DEBUG1, p1, p2) +#define IB_LOG_MOD_DEBUG1_64(modid, p1, p2) IB_LOG_MOD_FMT64(VS_LOG_DEBUG1, modid, p1, p2) +#define IB_LOG_DEBUG1STR(p1, p2) IB_LOG_FMTSTR(VS_LOG_DEBUG1, p1, p2) +#define IB_LOG_MOD_DEBUG1STR(modid, p1, p2) IB_LOG_MOD_FMTSTR(VS_LOG_DEBUG1, modid, p1, p2) +#define IB_LOG_DEBUG1RC(p1, p2) IB_LOG_FMTRC(VS_LOG_DEBUG1, p1, p2) +#define IB_LOG_MOD_DEBUG1RC(modid, p1, p2) IB_LOG_MOD_FMTRC(VS_LOG_DEBUG1, modid, p1, p2) +// for cs_log* and hence these macros +// Log_StrDup will be performed internally as part of formatting the message +#define IB_LOG_DEBUG1_FMT(func, fmt...) \ + cs_log(VS_LOG_DEBUG1, func, ## fmt) +#define IB_LOG_MOD_DEBUG1_FMT(modid,func, fmt...) \ + cs_log_mod(VS_LOG_DEBUG1, modid, func, ## fmt) +#define IB_LOG_DEBUG1_FMT_VF(vf, func, fmt...) \ + cs_log_vf(VS_LOG_DEBUG1, vf, func, ## fmt) +#define IB_LOG_MOD_DEBUG1_FMT_VF(modid,vf, func, fmt...) \ + cs_log_mod_vf(VS_LOG_DEBUG1, modid, vf, func, ## fmt) +#endif + +/******************************* + * DEBUG2 + ******************************/ + +#ifdef VIEO_TRACE_DISABLED +#define IB_LOG_DEBUG2_0(p1) do { } while(0) +#define IB_LOG_MOD_DEBUG2_0(modid, p1) do { } while(0) +#define IB_LOG_DEBUG2(p1, p2) do { } while(0) +#define IB_LOG_MOD_DEBUG2(modid, p1, p2) do { } while(0) +#define IB_LOG_DEBUG2X(p1, p2) do { } while(0) +#define IB_LOG_MOD_DEBUG2X(modid, p1, p2) do { } while(0) +#define IB_LOG_DEBUG2LX(p1, p2) do { } while(0) +#define IB_LOG_MOD_DEBUG2LX(modid, p1, p2) do { } while(0) +#define IB_LOG_DEBUG2_64(p1, p2) do { } while(0) +#define IB_LOG_MOD_DEBUG2_64(modid, p1, p2) do { } while(0) +#define IB_LOG_DEBUG2STR(p1, p2) do { } while(0) +#define IB_LOG_MOD_DEBUG2STR(modid, p1, p2) do { } while(0) +#define IB_LOG_DEBUG2RC(p1, p2) do { } while(0) +#define IB_LOG_MOD_DEBUG2RC(modid, p1, p2) do { } while(0) +#define IB_LOG_DEBUG2_FMT(func, fmt...) do { } while(0) +#define IB_LOG_MOD_DEBUG2_FMT(modid, func, fmt...) do { } while(0) +#define IB_LOG_DEBUG2_FMT_VF(vf, func, fmt...) do { } while(0) +#define IB_LOG_MOD_DEBUG2_FMT_VF(modid, vf, func, fmt...) do { } while(0) +#else +#define IB_LOG_DEBUG2_0(p1) IB_LOG_FMT0(VS_LOG_DEBUG2, p1) +#define IB_LOG_MOD_DEBUG2_0(modid, p1) IB_LOG_MOD_FMT0(VS_LOG_DEBUG2, modid, p1) +#define IB_LOG_DEBUG2(p1, p2) IB_LOG_FMTU(VS_LOG_DEBUG2, p1, p2) +#define IB_LOG_MOD_DEBUG2(modid, p1, p2) IB_LOG_MOD_FMTU(VS_LOG_DEBUG2, modid, p1, p2) +#define IB_LOG_DEBUG2X(p1, p2) IB_LOG_FMTX(VS_LOG_DEBUG2, p1, p2) +#define IB_LOG_MOD_DEBUG2X(modid, p1, p2) IB_LOG_MOD_FMTX(VS_LOG_DEBUG2, modid, p1, p2) +#define IB_LOG_DEBUG2LX(p1, p2) IB_LOG_FMTLX(VS_LOG_DEBUG2, p1, p2) +#define IB_LOG_MOD_DEBUG2LX(modid, p1, p2) IB_LOG_MOD_FMTLX(VS_LOG_DEBUG2, modid, p1, p2) +#define IB_LOG_DEBUG2_64(p1, p2) IB_LOG_FMT64(VS_LOG_DEBUG2, p1, p2) +#define IB_LOG_MOD_DEBUG2_64(modid, p1, p2) IB_LOG_MOD_FMT64(VS_LOG_DEBUG2, modid, p1, p2) +#define IB_LOG_DEBUG2STR(p1, p2) IB_LOG_FMTSTR(VS_LOG_DEBUG2, p1, p2) +#define IB_LOG_MOD_DEBUG2STR(modid, p1, p2) IB_LOG_MOD_FMTSTR(VS_LOG_DEBUG2, modid, p1, p2) +#define IB_LOG_DEBUG2RC(p1, p2) IB_LOG_FMTRC(VS_LOG_DEBUG2, p1, p2) +#define IB_LOG_MOD_DEBUG2RC(modid, p1, p2) IB_LOG_MOD_FMTRC(VS_LOG_DEBUG2, modid, p1, p2) +// for cs_log* and hence these macros +// Log_StrDup will be performed internally as part of formatting the message +#define IB_LOG_DEBUG2_FMT(func, fmt...) \ + cs_log(VS_LOG_DEBUG2, func, ## fmt) +#define IB_LOG_MOD_DEBUG2_FMT(modid,func, fmt...) \ + cs_log_mod(VS_LOG_DEBUG2, modid, func, ## fmt) +#define IB_LOG_DEBUG2_FMT_VF(vf, func, fmt...) \ + cs_log_vf(VS_LOG_DEBUG2, vf, func, ## fmt) +#define IB_LOG_MOD_DEBUG2_FMT_VF(modid,vf, func, fmt...) \ + cs_log_mod_vf(VS_LOG_DEBUG2, modid, vf, func, ## fmt) +#endif + +/******************************* + * DEBUG3 + ******************************/ + +#ifdef VIEO_TRACE_DISABLED +#define IB_LOG_DEBUG3_0(p1) do { } while(0) +#define IB_LOG_MOD_DEBUG3_0(modid, p1) do { } while(0) +#define IB_LOG_DEBUG3(p1, p2) do { } while(0) +#define IB_LOG_MOD_DEBUG3(modid, p1, p2) do { } while(0) +#define IB_LOG_DEBUG3X(p1, p2) do { } while(0) +#define IB_LOG_MOD_DEBUG3X(modid, p1, p2) do { } while(0) +#define IB_LOG_DEBUG3LX(p1, p2) do { } while(0) +#define IB_LOG_MOD_DEBUG3LX(modid, p1, p2) do { } while(0) +#define IB_LOG_DEBUG3_64(p1, p2) do { } while(0) +#define IB_LOG_MOD_DEBUG3_64(modid, p1, p2) do { } while(0) +#define IB_LOG_DEBUG3STR(p1, p2) do { } while(0) +#define IB_LOG_MOD_DEBUG3STR(modid, p1, p2) do { } while(0) +#define IB_LOG_DEBUG3RC(p1, p2) do { } while(0) +#define IB_LOG_MOD_DEBUG3RC(modid, p1, p2) do { } while(0) +#define IB_LOG_DEBUG3_FMT(func, fmt...) do { } while(0) +#define IB_LOG_MOD_DEBUG3_FMT(modid, func, fmt...) do { } while(0) +#define IB_LOG_DEBUG3_FMT_VF(vf, func, fmt...) do { } while(0) +#define IB_LOG_MOD_DEBUG3_FMT_VF(modid, vf, func, fmt...) do { } while(0) +#else +#define IB_LOG_DEBUG3_0(p1) IB_LOG_FMT0(VS_LOG_DEBUG3, p1) +#define IB_LOG_MOD_DEBUG3_0(modid, p1) IB_LOG_MOD_FMT0(VS_LOG_DEBUG3, modid, p1) +#define IB_LOG_DEBUG3(p1, p2) IB_LOG_FMTU(VS_LOG_DEBUG3, p1, p2) +#define IB_LOG_MOD_DEBUG3(modid, p1, p2) IB_LOG_MOD_FMTU(VS_LOG_DEBUG3, modid, p1, p2) +#define IB_LOG_DEBUG3X(p1, p2) IB_LOG_FMTX(VS_LOG_DEBUG3, p1, p2) +#define IB_LOG_MOD_DEBUG3X(modid, p1, p2) IB_LOG_MOD_FMTX(VS_LOG_DEBUG3, modid, p1, p2) +#define IB_LOG_DEBUG3LX(p1, p2) IB_LOG_FMTLX(VS_LOG_DEBUG3, p1, p2) +#define IB_LOG_MOD_DEBUG3LX(modid, p1, p2) IB_LOG_MOD_FMTLX(VS_LOG_DEBUG3, modid, p1, p2) +#define IB_LOG_DEBUG3_64(p1, p2) IB_LOG_FMT64(VS_LOG_DEBUG3, p1, p2) +#define IB_LOG_MOD_DEBUG3_64(modid, p1, p2) IB_LOG_MOD_FMT64(VS_LOG_DEBUG3, modid, p1, p2) +#define IB_LOG_DEBUG3STR(p1, p2) IB_LOG_FMTSTR(VS_LOG_DEBUG3, p1, p2) +#define IB_LOG_MOD_DEBUG3STR(modid, p1, p2) IB_LOG_MOD_FMTSTR(VS_LOG_DEBUG3, modid, p1, p2) +#define IB_LOG_DEBUG3RC(p1, p2) IB_LOG_FMTRC(VS_LOG_DEBUG3, p1, p2) +#define IB_LOG_MOD_DEBUG3RC(modid, p1, p2) IB_LOG_MOD_FMTRC(VS_LOG_DEBUG3, modid, p1, p2) +// for cs_log* and hence these macros +// Log_StrDup will be performed internally as part of formatting the message +#define IB_LOG_DEBUG3_FMT(func, fmt...) \ + cs_log(VS_LOG_DEBUG3, func, ## fmt) +#define IB_LOG_MOD_DEBUG3_FMT(modid,func, fmt...) \ + cs_log_mod(VS_LOG_DEBUG3, modid, func, ## fmt) +#define IB_LOG_DEBUG3_FMT_VF(vf, func, fmt...) \ + cs_log_vf(VS_LOG_DEBUG3, vf, func, ## fmt) +#define IB_LOG_MOD_DEBUG3_FMT_VF(modid,vf, func, fmt...) \ + cs_log_mod_vf(VS_LOG_DEBUG3, modid, vf, func, ## fmt) +#endif + +/******************************* + * DEBUG4 + ******************************/ + +#ifdef VIEO_TRACE_DISABLED +#define IB_LOG_DEBUG4_0(p1) do { } while(0) +#define IB_LOG_MOD_DEBUG4_0(modid, p1) do { } while(0) +#define IB_LOG_DEBUG4(p1, p2) do { } while(0) +#define IB_LOG_MOD_DEBUG4(modid, p1, p2) do { } while(0) +#define IB_LOG_DEBUG4X(p1, p2) do { } while(0) +#define IB_LOG_MOD_DEBUG4X(modid, p1, p2) do { } while(0) +#define IB_LOG_DEBUG4LX(p1, p2) do { } while(0) +#define IB_LOG_MOD_DEBUG4LX(modid, p1, p2) do { } while(0) +#define IB_LOG_DEBUG4_64(p1, p2) do { } while(0) +#define IB_LOG_MOD_DEBUG4_64(modid, p1, p2) do { } while(0) +#define IB_LOG_DEBUG4STR(p1, p2) do { } while(0) +#define IB_LOG_MOD_DEBUG4STR(modid, p1, p2) do { } while(0) +#define IB_LOG_DEBUG4RC(p1, p2) do { } while(0) +#define IB_LOG_MOD_DEBUG4RC(modid, p1, p2) do { } while(0) +#define IB_LOG_DEBUG4_FMT(func, fmt...) do { } while(0) +#define IB_LOG_MOD_DEBUG4_FMT(modid, func, fmt...) do { } while(0) +#define IB_LOG_DEBUG4_FMT_VF(vf, func, fmt...) do { } while(0) +#define IB_LOG_MOD_DEBUG4_FMT_VF(modid, vf, func, fmt...) do { } while(0) +#else +#define IB_LOG_DEBUG4_0(p1) IB_LOG_FMT0(VS_LOG_DEBUG4, p1) +#define IB_LOG_MOD_DEBUG4_0(modid, p1) IB_LOG_MOD_FMT0(VS_LOG_DEBUG4, modid, p1) +#define IB_LOG_DEBUG4(p1, p2) IB_LOG_FMTU(VS_LOG_DEBUG4, p1, p2) +#define IB_LOG_MOD_DEBUG4(modid, p1, p2) IB_LOG_MOD_FMTU(VS_LOG_DEBUG4, modid, p1, p2) +#define IB_LOG_DEBUG4X(p1, p2) IB_LOG_FMTX(VS_LOG_DEBUG4, p1, p2) +#define IB_LOG_MOD_DEBUG4X(modid, p1, p2) IB_LOG_MOD_FMTX(VS_LOG_DEBUG4, modid, p1, p2) +#define IB_LOG_DEBUG4LX(p1, p2) IB_LOG_FMTLX(VS_LOG_DEBUG4, p1, p2) +#define IB_LOG_MOD_DEBUG4LX(modid, p1, p2) IB_LOG_MOD_FMTLX(VS_LOG_DEBUG4, modid, p1, p2) +#define IB_LOG_DEBUG4_64(p1, p2) IB_LOG_FMT64(VS_LOG_DEBUG4, p1, p2) +#define IB_LOG_MOD_DEBUG4_64(modid, p1, p2) IB_LOG_MOD_FMT64(VS_LOG_DEBUG4, modid, p1, p2) +#define IB_LOG_DEBUG4STR(p1, p2) IB_LOG_FMTSTR(VS_LOG_DEBUG4, p1, p2) +#define IB_LOG_MOD_DEBUG4STR(modid, p1, p2) IB_LOG_MOD_FMTSTR(VS_LOG_DEBUG4, modid, p1, p2) +#define IB_LOG_DEBUG4RC(p1, p2) IB_LOG_FMTRC(VS_LOG_DEBUG4, p1, p2) +#define IB_LOG_MOD_DEBUG4RC(modid, p1, p2) IB_LOG_MOD_FMTRC(VS_LOG_DEBUG4, modid, p1, p2) +// for cs_log* and hence these macros +// Log_StrDup will be performed internally as part of formatting the message +#define IB_LOG_DEBUG4_FMT(func, fmt...) \ + cs_log(VS_LOG_DEBUG4, func, ## fmt) +#define IB_LOG_MOD_DEBUG4_FMT(modid,func, fmt...) \ + cs_log_mod(VS_LOG_DEBUG4, modid, func, ## fmt) +#define IB_LOG_DEBUG4_FMT_VF(vf, func, fmt...) \ + cs_log_vf(VS_LOG_DEBUG4, vf, func, ## fmt) +#define IB_LOG_MOD_DEBUG4_FMT_VF(modid,vf, func, fmt...) \ + cs_log_mod_vf(VS_LOG_DEBUG4, modid, vf, func, ## fmt) +#endif + +/******************************* + * ENTER + ******************************/ + +// TBD - rename this as IB_LOG_ENTER +#if (! defined(VIEO_DEBUG) && ! defined(DEBUG) ) || defined(VIEO_TRACE_DISABLED) +#define IB_MOD_ENTER(modid, p1,p2,p3,p4,p5) ((void)(p1)) +// additional arguments on function entry +#define IB_LOG_MOD_ARGS1(modid,p1) do { } while (0) +#define IB_LOG_MOD_ARGS2(modid,p1,p2) do { } while (0) +#define IB_LOG_MOD_ARGS3(modid,p1,p2,p3) do { } while (0) +#define IB_LOG_MOD_ARGS4(modid,p1,p2,p3,p4) do { } while (0) +#define IB_LOG_MOD_ARGS5(modid,p1,p2,p3,p4,p5) do { } while (0) +#else +#ifdef __VXWORKS__ +// TBD - remove LogVal_t (32 bit) so can show 64 bit args too +// but will require callers to use LOG_PTR macro +#define IB_MOD_ENTER(modid, p1,p2,p3,p4,p5) \ + do { if (IB_LOG_IS_INTERESTED_MOD(VS_LOG_ENTER, modid) && ! vs_log_filter() ) \ + LOG_DEBUG5(MOD_ESM, "SM Enter: %s%s %llu %llu %llu %llu", \ + LOG_PTR(cs_log_get_module_prefix(modid)),LOG_PTR(p1), \ + LOG_ARG((LogVal64_t)(LogVal_t)p2), LOG_ARG((LogVal64_t)(LogVal_t)p3), \ + LOG_ARG((LogVal64_t)(LogVal_t)p4), LOG_ARG((LogVal64_t)(LogVal_t)p5)); \ + } while (0) +#define IB_LOG_MOD_ARGS1(modid, p1) \ + do { if (IB_LOG_IS_INTERESTED_MOD(VS_LOG_ENTER, modid) && ! vs_log_filter() ) \ + LOG_DEBUG5(MOD_ESM, "SM Args: %s %llu", \ + LOG_PTR(cs_log_get_module_prefix(modid)), \ + LOG_ARG((LogVal64_t)p1), 0, 0, 0, 0); \ + } while (0) +#define IB_LOG_MOD_ARGS2(modid, p1,p2) \ + do { if (IB_LOG_IS_INTERESTED_MOD(VS_LOG_ENTER, modid) && ! vs_log_filter() ) \ + LOG_DEBUG5(MOD_ESM, "SM Args: %s %llu %llu", \ + LOG_PTR(cs_log_get_module_prefix(modid)), \ + LOG_ARG((LogVal64_t)p1), LOG_ARG((LogVal64_t)p2), 0, 0, 0); \ + } while (0) +#define IB_LOG_MOD_ARGS3(modid, p1,p2,p3) \ + do { if (IB_LOG_IS_INTERESTED_MOD(VS_LOG_ENTER, modid) && ! vs_log_filter() ) \ + LOG_DEBUG5(MOD_ESM, "SM Args: %s %llu %llu %llu", \ + LOG_PTR(cs_log_get_module_prefix(modid)), \ + LOG_ARG((LogVal64_t)p1), LOG_ARG((LogVal64_t)p2), \ + LOG_ARG((LogVal64_t)p3), 0, 0); \ + } while (0) +#define IB_LOG_MOD_ARGS4(modid, p1,p2,p3,p4) \ + do { if (IB_LOG_IS_INTERESTED_MOD(VS_LOG_ENTER, modid) && ! vs_log_filter() ) \ + LOG_DEBUG5(MOD_ESM, "SM Args: %s %llu %llu %llu %llu", \ + LOG_PTR(cs_log_get_module_prefix(modid)), \ + LOG_ARG((LogVal64_t)p1), LOG_ARG((LogVal64_t)p2), \ + LOG_ARG((LogVal64_t)p3), LOG_ARG((LogVal64_t)p4), 0); \ + } while (0) +#define IB_LOG_MOD_ARGS5(modid, p1,p2,p3,p4,p5) \ + do { if (IB_LOG_IS_INTERESTED_MOD(VS_LOG_ENTER, modid) && ! vs_log_filter() ) \ + LOG_DEBUG5(MOD_ESM, "SM Args: %s %llu %llu %llu %llu %llu", \ + LOG_PTR(cs_log_get_module_prefix(modid)), \ + LOG_ARG((LogVal64_t)p1), LOG_ARG((LogVal64_t)p2), \ + LOG_ARG((LogVal64_t)p3), LOG_ARG((LogVal64_t)p4), \ + LOG_ARG((LogVal64_t)p5)); \ + } while (0) +#else +#define IB_MOD_ENTER(modid,p1,p2,p3,p4,p5) \ + do { if (IB_LOG_IS_INTERESTED_MOD(VS_LOG_ENTER, modid) ) \ + vs_log_output(VS_LOG_ENTER, modid, __func__, NULL, \ + "%s %"CS64u" %"CS64u" %"CS64u" %"CS64u, \ + p1, (LogVal64_t)p2, (LogVal64_t)p3, (LogVal64_t)p4, \ + (LogVal64_t)p5); \ + } while (0) +#define IB_LOG_MOD_ARGS1(modid, p1) \ + do { if (IB_LOG_IS_INTERESTED_MOD(VS_LOG_ENTER, modid) ) \ + vs_log_output(VS_LOG_ARGS, modid, __func__, NULL, \ + "%"CS64u, (LogVal64_t)p1); \ + } while (0) +#define IB_LOG_MOD_ARGS2(modid, p1,p2) \ + do { if (IB_LOG_IS_INTERESTED_MOD(VS_LOG_ENTER, modid) ) \ + vs_log_output(VS_LOG_ARGS, modid, __func__, NULL, \ + "%"CS64u" %"CS64u, (LogVal64_t)p1, (LogVal64_t)p2); \ + } while (0) +#define IB_LOG_MOD_ARGS3(modid, p1,p2,p3) \ + do { if (IB_LOG_IS_INTERESTED_MOD(VS_LOG_ENTER, modid) ) \ + vs_log_output(VS_LOG_ARGS, modid, __func__, NULL, \ + "%"CS64u" %"CS64u" %"CS64u, \ + (LogVal64_t)p1, (LogVal64_t)p2, (LogVal64_t)p3); \ + } while (0) +#define IB_LOG_MOD_ARGS4(modid, p1,p2,p3,p4) \ + do { if (IB_LOG_IS_INTERESTED_MOD(VS_LOG_ENTER, modid) ) \ + vs_log_output(VS_LOG_ARGS, modid, __func__, NULL, \ + "%"CS64u" %"CS64u" %"CS64u" %"CS64u, \ + (LogVal64_t)p1, (LogVal64_t)p2, (LogVal64_t)p3, \ + (LogVal64_t)p4); \ + } while (0) +#define IB_LOG_MOD_ARGS5(modid, p1,p2,p3,p4,p5) \ + do { if (IB_LOG_IS_INTERESTED_MOD(VS_LOG_ENTER, modid) ) \ + vs_log_output(VS_LOG_ARGS, modid, __func__, NULL, \ + "%"CS64u" %"CS64u" %"CS64u" %"CS64u" %"CS64u, \ + (LogVal64_t)p1, (LogVal64_t)p2, (LogVal64_t)p3, \ + (LogVal64_t)p4, (LogVal64_t)p5); \ + } while (0) +#endif +#endif + +#define IB_ENTER(p1,p2,p3,p4,p5) IB_MOD_ENTER(LOCAL_MOD_ID,p1,p2,p3,p4,p5) +#define IB_LOG_ARGS1(p1) IB_LOG_MOD_ARGS1(LOCAL_MOD_ID,p1) +#define IB_LOG_ARGS2(p1,p2) IB_LOG_MOD_ARGS2(LOCAL_MOD_ID,p1,p2) +#define IB_LOG_ARGS3(p1,p2,p3) IB_LOG_MOD_ARGS3(LOCAL_MOD_ID,p1,p2,p3) +#define IB_LOG_ARGS4(p1,p2,p3,p4) IB_LOG_MOD_ARGS4(LOCAL_MOD_ID,p1,p2,p3,p4) +#define IB_LOG_ARGS5(p1,p2,p3,p4,p5) \ + IB_LOG_MOD_ARGS5(LOCAL_MOD_ID,p1,p2,p3,p4,p5) + + +/******************************* + * EXIT + ******************************/ + +// TBD - rename this as IB_LOG_EXIT +#if (! defined(VIEO_DEBUG) && ! defined(DEBUG) ) || defined(VIEO_TRACE_DISABLED) +#define IB_MOD_EXIT0(modid, p1) ((void)(p1)) +#define IB_MOD_EXIT(modid, p1,p2) ((void)(p1)) +#define IB_MOD_EXITRC(modid, p1,p2) ((void)(p1)) +#else +#define IB_MOD_EXIT0(modid, p1) IB_LOG_MOD_FMT0(VS_LOG_EXIT,modid,p1) +#define IB_MOD_EXIT(modid, p1, p2) IB_LOG_MOD_FMTU(VS_LOG_EXIT,modid,p1,p2) +#define IB_MOD_EXITRC(modid, p1, p2) IB_LOG_MOD_FMTRC(VS_LOG_EXIT,modid,p1,p2) +#endif + +#define IB_EXIT0(p1) IB_MOD_EXIT0(LOCAL_MOD_ID,p1) +#define IB_EXIT(p1,p2) IB_MOD_EXIT(LOCAL_MOD_ID,p1,p2) +#define IB_EXITRC(p1,p2) IB_MOD_EXITRC(LOCAL_MOD_ID,p1,p2) + +/**************************************************************************/ +/******************************** API *************************************/ +/**************************************************************************/ + +/** Define Commands accepted by vs_log_control call. **********************/ + +#define VS_LOG_SETMASK (1) +#define VS_LOG_SETOUTPUTFILE (6) /* Causes log messages to go to the file. Passing in an empty string sets log back to syslog */ +#define VS_LOG_SETSYSLOGNAME (7) /* Sets the name that will appear in syslog messages. */ +#define VS_LOG_SETFACILITY (8) /* Sets the syslog facility. */ +#define VS_LOG_STARTSYSLOG (9) /* Starts Syslog. */ + +/* + * vs_log_control + * Function used to pass commands to the logging subsystem. + * + * INPUTS + * cmd Defines the action to carried out in the subsystem + * arg1 First arg type + * arg2 Second arg + * arg3 Second arg + * + * cmd == VS_LOG_STARTSYSLOG + * + * arg1, arg2 and arg3 is NULL. + * + * cmd == VS_LOG_SETFACILITY + * + * arg1 Contains facility + * arg2 and arg3 is NULL. + * + * cmd == VS_LOG_SETMASK + * + * arg1 Contains a new debug mask + * arg2 NULL + * arg3 NULL + * + * RETURNS + * VSTATUS_OK + * VSTATUS_BAD + */ + +Status_t vs_log_control(int cmd, void *arg1, void *arg2, + void *arg3); + +// module name in form of "name: ", useful for messages where name is optional +// for VIEO_NONE_MOD_ID, returns "" +const char * +cs_log_get_module_prefix(uint32_t modid); + +// module name in simple form, useful to put in middle of other messages +// names provided also match prefixes used in LogMask config file names +// for VIEO_NONE_MOD_ID, returns "NONE" +const char * +cs_log_get_module_name(uint32_t modid); + +const char* +cs_log_get_sev_name(uint32_t sev); + +// fill log_masks based on mod_mask and sev_mask +// not recommended for general use, use cs_log_set_log_masks +void +cs_log_set_mods_mask(uint32_t mod_mask, uint32_t sev_mask, uint32_t log_masks[VIEO_LAST_MOD_ID+1]); + +// build log_masks based on level and mode +void +cs_log_set_log_masks(uint32_t level, int mode, uint32_t log_masks[VIEO_LAST_MOD_ID+1]); + +// convert module name to modid +// names provided also match prefixes used in LogMask config file names +// returns 0 if invalid name given +uint32_t +cs_log_get_module_id(const char * mod); + +// set mask for a given module specified by name +void +cs_log_set_log_mask(const char* mod, uint32_t mask, uint32_t log_masks[VIEO_LAST_MOD_ID+1]); + +// get mask for a given module specified by name +uint32_t +cs_log_get_log_mask(const char* mod, uint32_t log_masks[VIEO_LAST_MOD_ID+1]); + +char * +cs_convert_status (Status_t status); + +// always does Log_StrDup of msg for VxWorks +void +vs_log_output_message(char *msg, int show_masks); + +void +vs_log_set_log_mode(int mode); + +void +vs_log_output(uint32_t sev, /* severity */ + uint32_t modid, /* optional Module id */ + const char *function, /* optional function name */ + const char *vf, /* optional vFabric name */ + const char *format, ... + ) __attribute__((format(printf,5,6))); + +FILE* vs_log_get_logfile_fd(void); + +#ifdef __VXWORKS__ +// used for single argument data output so we can avoid Log_StrDup for +// IB_LOG_FMT* macros +void +vs_log_output_data(uint32_t sev, /* severity */ + uint32_t modid, /* optional Module id */ + const char *format, // "%s%s%s%s%s 0x%x", + // have some #defines for format + const char *function, /* optional function name */ // TBD if can use + const char *vf, /* optional vFabric name */ // TBD if can use + Log_Arg_t message, Log_Arg_t arg + ); + +// check for single thread filtering +int vs_log_filter(void); + +#else +// hex dump of a memory buffer at addr[0] - addr[len-1] +void +vs_log_output_memory(uint32_t sev, /* severity */ + uint32_t modid, /* optional Module id */ + const char *function, /* optional function name */ + const char *vf, /* optional vFabric name */ + const char *prefix, + const void* addr, + uint32_t len + ); + +// fatal abort with core dump +void vs_fatal_error(uint8_t *string); +#endif + +// +// IB_*_NOREPEAT(lastMst, msgNum, [argument list]) +// +// Prevent the same error from coming out over and over by tracking the +// previous error that was logged. Functions using these macros should locally +// declare an (optionally static) unsigned variable to track the last message +// sent and clear that variable before returning successfully. In addition, +// each invocation of IB_WARN_NOREPEAT and IB_ERROR_NOREPEAT in that function should +// be assigned a unique msgNum. +#define IB_WARN_NOREPEAT(lastMsg, msgNum, fmt...) \ + if (lastMsg != msgNum) { \ + cs_log(VS_LOG_WARN,__func__, ## fmt); \ + lastMsg = msgNum; \ + } + +#define IB_ERROR_NOREPEAT(lastMsg, msgNum, fmt...) \ + if (lastMsg != msgNum) { \ + cs_log(VS_LOG_ERROR,__func__, ## fmt); \ + lastMsg = msgNum; \ + } + +#endif /*__VIEO_VS_LOG__*/ diff --git a/Esm/ib/include/cs_queue.h b/Esm/ib/include/cs_queue.h new file mode 100644 index 0000000..9810be6 --- /dev/null +++ b/Esm/ib/include/cs_queue.h @@ -0,0 +1,85 @@ +/* BEGIN_ICS_COPYRIGHT2 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + * ** END_ICS_COPYRIGHT2 ****************************************/ + +//===========================================================================// +// +// FILE NAME +// cs_queue.h +// +// DESCRIPTION +// Definitions for a generic queue +// +// DATA STRUCTURES +// None +// +// FUNCTIONS +// None +// +// DEPENDENCIES +// None +// +// +//===========================================================================// + +#ifndef _CS_QUEUE_H_ +#define _CS_QUEUE_H_ + +#include "ib_types.h" +#include "vs_g.h" + + // pointer to a queue element + typedef void *cs_QueueElement_ptr; + + // queue record structure definition + typedef struct _cs_QueueRecord_ + { + int Capacity; + int Size; + int Front; + int Rear; + Lock_t lock; + void *qData; + } cs_QueueRecord_t; + + // pointer to a queue record + typedef cs_QueueRecord_t *cs_Queue_ptr; + + // function definitions + static __inline int cs_queue_Capacity( cs_Queue_ptr Q ) { return Q->Capacity; }; + int cs_queue_IsEmpty( cs_Queue_ptr Q ); + int cs_queue_IsFull( cs_Queue_ptr Q ); + cs_Queue_ptr cs_queue_CreateQueue( Pool_t *pool, uint32_t MaxElements ); + void cs_queue_DisposeQueue( Pool_t *pool, cs_Queue_ptr Q ); + void cs_queue_MakeEmpty( cs_Queue_ptr Q ); + Status_t cs_queue_Enqueue( cs_QueueElement_ptr X, cs_Queue_ptr Q ); + cs_QueueElement_ptr cs_queue_Front( cs_Queue_ptr Q ); + void cs_queue_Dequeue( cs_Queue_ptr Q ); + cs_QueueElement_ptr cs_queue_FrontAndDequeue( cs_Queue_ptr Q ); + +#endif /* _CS_QUEUE_H_ */ diff --git a/Esm/ib/include/cs_sockwrap.h b/Esm/ib/include/cs_sockwrap.h new file mode 100644 index 0000000..f84a87d --- /dev/null +++ b/Esm/ib/include/cs_sockwrap.h @@ -0,0 +1,60 @@ +/* BEGIN_ICS_COPYRIGHT2 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + * ** END_ICS_COPYRIGHT2 ****************************************/ + +/******************************************************************************* + * @file cs_sockwrap.h + * + * @brief + * Header file contains declarations of socket creation routines for server + * and client AF_UNIX type sockets. + * The routines are supposed to be used on both Unix and Vxworks but the + * structure of the socket addresss strings passed to the routines differs + * between the operating systems. + * In UNIX the structure of the strings is supposed to be generally of the + * form "/var/tmp/" and in VXWORKS the string should + * take the form "/comp/socket/0xNumber" where 0xNumber is a string + * representation of a 16 bit number is hexadecimal form. + ******************************************************************************* + */ +#ifndef __CS_SOCKWRAP_H__ + +#define __CS_SOCKWRAP_H__ + +#include + +extern int cs_local_comm_init(const char *name); +extern int cs_local_comm_connect(const char *srvaddr, const char *claddr); +extern int cs_local_comm_accept(int listenfd); +extern int cs_udp_comm_connect(const struct sockaddr *srv_addr, + socklen_t srv_len); +extern int cs_tcp_comm_connect(const struct sockaddr *srv_addr, + socklen_t srv_len); +extern int cs_set_fd_non_block(int fd); + +#endif /*__CS_SOCKWRAP_H__ */ diff --git a/Esm/ib/include/cs_vesw.h b/Esm/ib/include/cs_vesw.h new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/Esm/ib/include/cs_vesw.h diff --git a/Esm/ib/include/eeph_eostl.h b/Esm/ib/include/eeph_eostl.h new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/Esm/ib/include/eeph_eostl.h diff --git a/Esm/ib/include/eepha_msg.h b/Esm/ib/include/eepha_msg.h new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/Esm/ib/include/eepha_msg.h diff --git a/Esm/ib/include/fm_xml.h b/Esm/ib/include/fm_xml.h new file mode 100644 index 0000000..641d3a3 --- /dev/null +++ b/Esm/ib/include/fm_xml.h @@ -0,0 +1,1442 @@ +/* BEGIN_ICS_COPYRIGHT2 **************************************** + +Copyright (c) 2015-2018, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + * ** END_ICS_COPYRIGHT2 ****************************************/ + +//===========================================================================// +// +// FILE NAME +// fm_xml.h +// +// DESCRIPTION +// This file contains structures used for parsing the fm_config.xml +// file for configuring SM +// +//===========================================================================// + +#ifndef _FM_XML_H_ +#define _FM_XML_H_ + +#include +#include +#include +#include "cs_log.h" + + +#ifdef __VXWORKS__ +#include "regexp.h" +#else +#include "regex.h" +#endif + +#ifndef __VXWORKS__ +#define MAX_SUBNET_SIZE 64000 // HSM has no realistic max +#define DEFAULT_SUBNET_SIZE 2560 // XML default subnet size +#else // __VXWORKS__ +#define MAX_SUBNET_SIZE 288 // ESM has a max subnet size of 288 +#define DEFAULT_SUBNET_SIZE 100 // XML default subnet size +#endif // __VXWORKS__ + +// Key PM config parameter defaults and ranges +#define PM_DEFAULT_TOTAL_IMAGES 10 // for Image[] and history[] +#define PM_MIN_TOTAL_IMAGES 3 // for Image[] and history[] +#ifdef __VXWORKS__ +// keep vxWorks limited to save memory and also because pm_compute_pool_size +// is called before reading config file +#define PM_MAX_TOTAL_IMAGES 10 // for Image[] and history[] +#else +#define PM_MAX_TOTAL_IMAGES 100000 // for Image[] and history[] +#endif + +#define PM_DEFAULT_FF_IMAGES 5 // for freezeFrame[] +#define PM_MIN_FF_IMAGES 2 // for freezeFrame[] +#ifdef __VXWORKS__ +#define PM_MAX_FF_IMAGES (PM_MAX_TOTAL_IMAGES-2) // for freezeFrame[] +#else +// due to some linear searches, we limit number of FF. 2-3 per client is enough +// and only a handful of clients are expected, 100 should be plenty +#define PM_MAX_FF_IMAGES 100 // for freezeFrame[] +#endif + +#define PM_DEFAULT_PA_MAX_CLIENTS 3 +#define PM_MIN_MAX_CLIENTS 3 +#ifdef __VXWORKS__ +// keep vxWorks limited to save memory and also because pm_compute_pool_size +// is called before reading config file +#define PM_MAX_MAX_CLIENTS 4 +#else +#define PM_MAX_MAX_CLIENTS 20 +#endif + +#define PM_DEFAULT_FF_LEASE 60 // in seconds + +#define PM_DEFAULT_MAX_ATTEMPTS 3 +#define PM_DEFAULT_RESP_TIMEOUT 250 +#define PM_DEFAULT_MIN_RESP_TIMEOUT 35 +#define PM_DEFAULT_SWEEP_ERRORS_LOG_THRESHOLD 10 +#define PM_DEFAULT_MAX_PARALLEL_NODES 10 +#define PM_DEFAULT_PMA_BATCH_SIZE 2 + +#define STL_PM_MAX_DG_PER_PMPG 5 //Maximum number of Monitors allowed in a PmPortGroup +#define STL_PM_GROUPNAMELEN 64 +#define STL_PM_MAX_CUSTOM_PORT_GROUPS 8 // HFIs and SWs take the first 2 slots. + +#define FE_LISTEN_PORT 3245 // FAB_EXEC listen port +#define FE_WIN_SIZE 1 // Default Window Size for Reliable +#define FE_MAX_WIN_SIZE 16 // Maximum window size +#define FE_MIN_WIN_SIZE 1 // Minimum window size + +#define FE_MAX_TRAP_SUBS 20 // Maximum number of TrapSubs + +// max number of times to fail to check on master +#define SM_CHECK_MASTER_INTERVAL 5 +#define SM_CHECK_MASTER_MAX_COUNT 3 + +#define SM_TRAP_THRESHOLD_MIN 10 +#define SM_TRAP_THRESHOLD_MAX 100 +#define SM_TRAP_THRESHOLD_DEFAULT 0 // off + +#define SM_TRAP_THRESHOLD_COUNT_DEFAULT 10 +#define SM_TRAP_THRESHOLD_COUNT_MIN 2 +#define SM_TRAP_THRESHOLD_COUNT_MAX 100 + +#define STL_CONFIGURABLE_SLS 16 + + +#define NONRESP_TIMEOUT 600ull +#define NONRESP_MAXRETRY 3 + + +// Cable Info Policy +#define CIP_NONE 0 +#define CIP_LINK 1 +#define CIP_PORT 2 + +// SwitchCascadeActivateEnable setting +#define SCAE_DISABLED 0 +#define SCAE_SW_ONLY 1 +#define SCAE_ALL 2 + +// PortBounceLogLimit no limit setting +#define PORT_BOUNCE_LOG_NO_LIMIT 0 + +// While logging of traps from a port is suppressed, summary trap information +// will be logged for that port after accumulating a certain number of traps. +// This number starts with SM_TRAP_LOG_SUMMARY_THRESHOLD_START. +// Once that number is reached and sa_TrapNeedsLogging() is called, the count +// of traps is reset to zero and the threshold is increased by +// SM_TRAP_LOG_SUMMARY_THRESHOLD_INCREMENT, with the maximum value of the +// threshold being capped off by SM_TRAP_LOG_SUMMARY_THRESHOLD_MAX + +#define SM_TRAP_LOG_SUMMARY_THRESHOLD_START 5 +#define SM_TRAP_LOG_SUMMARY_THRESHOLD_INCREMENT 5 +/* Should not be greater than 250 - logSuppressTrapCount is an 8 bit field*/ +#define SM_TRAP_LOG_SUMMARY_THRESHOLD_MAX 250 + +// Below constants are for suppressing trap logging information to reduce +// too much noise in the log + +// If two traps are received from the same port with in +// SM_TRAP_LOG_SUPPRESS_TRIGGER_INTERVAL, logging of trap information from +// that port will be suppressed + +#define SM_TRAP_LOG_SUPPRESS_TRIGGER_INTERVAL 30 /*in seconds*/ + +// Preemption Default Values +#define SM_PREEMPT_SMALL_PACKET_MIN 32 +#define SM_PREEMPT_SMALL_PACKET_MAX 8192 +#define SM_PREEMPT_SMALL_PACKET_DEF 256 +#define SM_PREEMPT_SMALL_PACKET_INC 32 + +#define SM_PREEMPT_LARGE_PACKET_MIN 512 +#define SM_PREEMPT_LARGE_PACKET_MAX 8192 +#define SM_PREEMPT_LARGE_PACKET_DEF 4096 +#define SM_PREEMPT_LARGE_PACKET_INC 512 + +#define SM_PREEMPT_LIMIT_MIN 256 // Note 0 is a valid value, but effectively turns off preemption +#define SM_PREEMPT_LIMIT_MAX 65024 // This is the max without being infinite +#define SM_PREEMPT_LIMIT_INF 65280 // This is the magical infinite value. SM_PREEMPT_LIMIT_INF / SM_PREEMPT_LIMIT_INC = 0xff. +#define SM_PREEMPT_LIMIT_DEF 4096 +#define SM_PREEMPT_LIMIT_INC 256 + +#define SM_PREEMPT_TAIL_MIN 80 +#define SM_PREEMPT_TAIL_DEF 80 +#define SM_PREEMPT_TAIL_INC 8 + +#define SM_PREEMPT_HEAD_MIN 80 +#define SM_PREEMPT_HEAD_DEF 80 +#define SM_PREEMPT_HEAD_INC 8 +#define SM_DEFAULT_MAX_LID 0xBFFF +#define SM_MAX_LID_LIMIT 0xBFFF +#define SM_MAX_9B_LID 0xBFFF + +// Note: Multicast and Collective masks are currently +// not configurable. +#define SM_DEFAULT_MULTICAST_MASK 4 +#define SM_DEFAULT_COLLECTIVE_MASK 1 + +// Constants related to our multicast lid collescing scheme +#define MAX_SUPPORTED_MCAST_GRP_CLASSES 32 +#define DEFAULT_SW_MLID_TABLE_CAP 1024 + +#define XML_PARSE_MEMORY_LIMIT 10000000 // limit to 10M per instance of FM + +// this define will turn on a series of debug statements for XML parsing +//#define XML_DEBUG + +// this define will turn on memory debugging for XML and VF parsing +//#define XML_MEMORY + +// Max number on FM instances - ESM only requires one instance and will be +// adjusted for in the parser +#define MAX_INSTANCES 8 + +// VF definitions - note that the number of devices is unlimited and has been +// tested to 20,000 +#ifdef __VXWORKS__ +#define MAX_CONFIGURED_VFABRICS 64 +#define MAX_ENABLED_VFABRICS 32 +#else /* __VXWORKS__ */ +#define MAX_CONFIGURED_VFABRICS 1000 +#define MAX_ENABLED_VFABRICS 1000 +#endif /* __VXWORKS__ */ + +#define MAX_VFABRIC_APPS 64 +#define MAX_VFABRIC_GROUPS 1024 +#define MAX_VFABRIC_MEMBERS_PER_VF 1024 +#define MAX_VFABRIC_APPS_PER_VF 64 +#define MAX_VFABRIC_APP_SIDS 64 +#define MAX_VFABRIC_APP_MGIDS 64 +#define MAX_QOS_GROUPS 32 +#define MAX_INCLUDED_GROUPS 32 +#define MAX_INCLUDED_APPS 32 +#define MAX_DEFAULT_GROUPS 64 +#define MAX_VFABRIC_DG_MGIDS 32 + +// Length of VirtualFabric, Group, Application, Fm instance Names +#define MAX_VFABRIC_NAME 64 + +// Length of longest compound string in App - typically MGID +#define MAX_VFABRIC_APP_ELEMENT 96 + +// same quantity as MAX_SUPPORTED_MCAST_GRP_CLASSES in sm_l.h +#define MAX_SUPPORTED_MCAST_GRP_CLASSES_XML 32 + +// priority range +#define MAX_PRIORITY 15 + +// VL15CreditRate range +#define MAX_VL15_CREDIT_RATE 21 + +// Max ports per switch, used in config definitions +#define MAX_SWITCH_PORTS 255 + +// out of memory error +#define OUT_OF_MEMORY "Memory limit has been exceeded parsing the XML configuration" +#define OUT_OF_MEMORY_RETURN "Memory limit has been exceeded parsing the XML configuration\n" +#define PRINT_MEMORY_ERROR IXmlParserPrintError(state, OUT_OF_MEMORY); + +// undefined XML values - used to see if XML config provided value after parsing +#define UNDEFINED_XML8 0xff +#define UNDEFINED_XML16 0xffff +#define UNDEFINED_XML32 0xffffffff +#define UNDEFINED_XML64 0xffffffffffffffffull + +// array sizes +#define FILENAME_SIZE 256 +#define LOGFILE_SIZE 100 +#define STRING_SIZE 32 + +// config consistency check levels +#define NO_CHECK_CCC_LEVEL 0 +#define CHECK_NO_ACTION_CCC_LEVEL 1 +#define CHECK_ACTION_CCC_LEVEL 2 +#define DEFAULT_CCC_LEVEL CHECK_ACTION_CCC_LEVEL +#define DEFAULT_CCC_METHOD MD5_CHECKSUM_METHOD + +// values for Sm.PathSelection parameter +#define PATH_MODE_MINIMAL 0 // no more than 1 path per lid +#define PATH_MODE_PAIRWISE 1 // cover every lid on "bigger side" exactly once +#define PATH_MODE_ORDERALL 2 // PAIRWISE, then all src, all dst (skip dups) +#define PATH_MODE_SRCDSTALL 3 // all src, all dst + +// Bitmask definitions for [Debug] SM Skip Write +#define SM_SKIP_WRITE_PORTINFO 0x00000001 // Includes Port Info +#define SM_SKIP_WRITE_SMINFO 0x00000002 // Includes Sm Info +#define SM_SKIP_WRITE_GUID 0x00000004 // Includes GUID Info +#define SM_SKIP_WRITE_SWITCHINFO 0x00000008 // Includes Switch Info +#define SM_SKIP_WRITE_VLARB 0x00000020 // Includes VLArb Tables (High / Low / Preempt Matrix) +#define SM_SKIP_WRITE_MAPS 0x00000040 // Includes SL::SC, SC::SL, SC::VL + +#define SM_SKIP_WRITE_LFT 0x00000080 // Includes LFT and MFT + +#define SM_SKIP_WRITE_AR 0x00000100 // Includes port group table, portgroup FDB +#define SM_SKIP_WRITE_PKEY 0x00000200 +#define SM_SKIP_WRITE_CONG 0x00000400 // Includes HFI congestion / Switch congestion +#define SM_SKIP_WRITE_BFRCTRL 0x00000800 +#define SM_SKIP_WRITE_NOTICE 0x00001000 +#define SM_SKIP_WRITE_PORTSTATEINFO 0x00002000 // Includes PortStateInfo sets for cascade activation + + +// This can be used for values such as LogMask's where it is necessary +// to know if a value was supplied. +typedef struct _FmParamU32 { + uint32_t value; + uint8_t valid; // is value valid +} FmParamU32_t; + +// Structures for parsing of Virtual Fabric XML tags + +typedef struct _XmlGuid { + uint64_t guid; + struct _XmlGuid *next; +} XmlGuid_t; + +typedef struct _XmlNode { + char node[MAX_VFABRIC_NAME]; + struct _XmlNode *next; +} XmlNode_t; + +typedef struct _XmlIncGroup { + char group[MAX_VFABRIC_NAME]; + int dg_index; // Index into dg_config + struct _XmlIncGroup *next; +} XmlIncGroup_t; + + +#define MAX_BRACKETS_SUPPORTED 10 +#define MAX_DIGITS_TO_PROCESS 5 +#define MAX_NODE_DESC_REG_EXPR 1500 +typedef struct _RegexBracketParseInfo{ + int totalGroups; + boolean portRangeDefined; + int portNum1; + int portNum2; + int lead0sPort1; + int lead0sPort2; + + int numBracketRangesDefined; + int number1[MAX_BRACKETS_SUPPORTED]; + int numDigitsNum1[MAX_BRACKETS_SUPPORTED]; + int number2[MAX_BRACKETS_SUPPORTED]; + int numDigitsNum2[MAX_BRACKETS_SUPPORTED]; + int leading0sNum1[MAX_BRACKETS_SUPPORTED]; + int leading0sNum2[MAX_BRACKETS_SUPPORTED]; + int bracketGroupNum[MAX_BRACKETS_SUPPORTED]; +} RegexBracketParseInfo_t; + +typedef struct _RegExp { + char regexString[MAX_NODE_DESC_REG_EXPR]; + boolean isSyntaxValid; + RegexBracketParseInfo_t regexInfo; + +#ifdef __VXWORKS__ + regexp *regexpCompiled; +#else + regmatch_t groupArray[MAX_BRACKETS_SUPPORTED]; + regex_t regexCompiled; +#endif + + struct _RegExp *next; +} RegExp_t; + + +// Virtual Fabric Group configuration +typedef struct _DGConfig { + char name[MAX_VFABRIC_NAME]; + int dg_index; // index into dg_config + uint32_t number_of_system_image_guids; + cl_qmap_t system_image_guid; + uint32_t number_of_node_guids; + cl_qmap_t node_guid; + uint32_t number_of_port_guids; + cl_qmap_t port_guid; + uint32_t number_of_node_descriptions; + XmlNode_t *node_description; + RegExp_t *reg_expr; // setup by SM + uint32_t number_of_included_groups; + XmlIncGroup_t *included_group; + + // Select + uint8_t select_all; + uint8_t select_self; + uint8_t select_swe0; + uint8_t select_all_mgmt_allowed; + uint8_t select_hfi_direct_connect; + uint8_t select_all_tfis; + + + // NodeType + uint8_t node_type_fi; + uint8_t node_type_sw; +} DGConfig_t; + +typedef struct _XmlAppMgid { + char mgid[MAX_VFABRIC_NAME]; +} XmlAppMgid_t; + +typedef struct _XmlAppMgidRng { + char range[MAX_VFABRIC_APP_ELEMENT]; +} XmlAppMgidRng_t; + +typedef struct _XmlAppMgidMsk { + char masked[MAX_VFABRIC_APP_ELEMENT]; +} XmlAppMgidMsk_t; + +// Virtual Fabric Application configuration +typedef struct _AppConfig { + char name[MAX_VFABRIC_NAME]; /* MUST BE FIRST FIELD FOR MAP */ + uint32_t serviceIdMapSize; + cl_qmap_t serviceIdMap; + uint32_t serviceIdRangeMapSize; + cl_qmap_t serviceIdRangeMap; + uint32_t serviceIdMaskedMapSize; + cl_qmap_t serviceIdMaskedMap; + uint32_t number_of_mgids; + XmlAppMgid_t mgid[MAX_VFABRIC_APP_MGIDS]; + uint32_t number_of_mgid_ranges; + XmlAppMgidRng_t mgid_range[MAX_VFABRIC_APP_MGIDS]; + uint32_t number_of_mgid_maskeds; + XmlAppMgidMsk_t mgid_masked[MAX_VFABRIC_APP_MGIDS]; + uint32_t number_of_included_apps; + XmlNode_t included_app[MAX_INCLUDED_APPS]; + uint8_t select_sa; + uint8_t select_unmatched_sid; + uint8_t select_unmatched_mgid; + uint8_t select_pm; +} AppConfig_t; + +// Virtual Fabric QOS Group configuration +typedef struct _QosConfig { + char name[MAX_VFABRIC_NAME]; + uint8_t enable; + uint8_t qos_enable; /* For legacy support of VFs with QOS=0 */ + uint8_t private_group; /* For legacy support of VFs with QOS=0 */ + uint8_t base_sl; + uint8_t base_sl_specified; + uint8_t resp_sl; + uint8_t resp_sl_specified; + uint8_t requires_resp_sl; + uint8_t mcast_sl; + uint8_t mcast_sl_specified; + uint8_t contains_mcast; + uint8_t flowControlDisable; + uint8_t percent_bandwidth; + uint8_t priority; + uint8_t pkt_lifetime_mult; /* Converted to power of 2 */ + uint32_t hoqlife_qos; + uint8_t preempt_rank; + uint32_t num_implicit_vfs; + uint32_t num_vfs; + uint8_t pkt_lifetime_specified; + uint8_t hoqlife_specified; +} QosConfig_t; + +// Application configuration +typedef struct _XMLApp { + char application[MAX_VFABRIC_NAME]; +} XMLApp_t; + +typedef struct _XMLMember { + char member[MAX_VFABRIC_NAME]; + int dg_index; // Index into dg_config; +} XMLMember_t; + +// Virtual Fabric configuration +typedef struct _VFConfig { + char name[MAX_VFABRIC_NAME]; /* MUST BE FIRST FIELD FOR MAP */ + uint32_t enable; + uint32_t standby; + uint32_t pkey; + uint32_t security; + uint32_t qos_index; + char qos_group[MAX_VFABRIC_NAME]; + uint32_t number_of_full_members; + XMLMember_t full_member[MAX_VFABRIC_MEMBERS_PER_VF]; + uint32_t number_of_limited_members; + XMLMember_t limited_member[MAX_VFABRIC_MEMBERS_PER_VF]; + uint32_t number_of_applications; + XMLApp_t application[MAX_VFABRIC_APPS_PER_VF]; + uint8_t max_mtu_int; + uint8_t max_rate_int; + uint8_t qos_implicit; + // Deprecated configuration items (see QOSConfig_t for new fields) + uint8_t qos_enable; + uint8_t base_sl; + uint8_t resp_sl; + uint8_t mcast_sl; + uint8_t flowControlDisable; + uint8_t percent_bandwidth; + uint8_t priority; + uint8_t pkt_lifetime_mult; + uint8_t preempt_rank; + uint32_t hoqlife_vf; +} VFConfig_t; + +// Application Database Composite per FM +typedef struct _AppXmlConfig { + uint32_t appMapSize; + cl_qmap_t appMap; // binary tree of apps by name +} AppXmlConfig_t; + +// DeviceGroup Database Composite per FM +typedef struct _DGXmlConfig { + uint32_t number_of_dgs; + DGConfig_t *dg[MAX_VFABRIC_GROUPS]; +} DGXmlConfig_t; + +// QOSGroup Database Composite per FM +typedef struct _QosXmlConfig { + uint32_t number_of_qosgroups; + QosConfig_t *qosgroups[MAX_QOS_GROUPS]; +} QosXmlConfig_t; + +// VirtualFabrics Database Composite per FM +typedef struct _VFXmlConfig { + uint32_t number_of_vfs; + VFConfig_t *vf[MAX_CONFIGURED_VFABRICS]; + uint8_t securityEnabled; // Composite of all vf's + uint8_t qosEnabled; // Composite of all vf's +} VFXmlConfig_t; + +// Internal structures for internal application use for Virtual Fabric Configuration + +// Internal Service ID's +typedef struct VFAppSid_t { + uint64_t service_id; // service_id or first service_id in range + // if 0xfffffffffffffff then all apps + uint64_t service_id_last; // if 0 then then no range + uint64_t service_id_mask; // if 0xfffffffffffffff then no mask +} VFAppSid_t; + +// Internal Multicast Group ID's +typedef struct _VFAppMgid { + uint64_t mgid[2]; // 128 bit MGID - upper word at index 0 + uint64_t mgid_last[2]; // 128 bit MGID upper range - if 0 then + // no range + uint64_t mgid_mask[2]; // 128 bit MGID mask + // if 0xffffffffffffffffffffffffffffff + // then no mask +} VFAppMgid_t; + +// Internal Virtual Fabric Applications +typedef struct _VFApp { + // Service ID list + uint32_t sidMapSize; + cl_qmap_t sidMap; // Map of VFAppSid_t + // Multicast Group list + uint32_t mgidMapSize; + cl_qmap_t mgidMap; // Map of VFAppMgid_t + + // aggregate settings from application and included applications + uint8_t select_sa; // boolean select SA - defaults to 0 + uint8_t select_unmatched_sid; // boolean select unmatched service id + // defaults to 0 + uint8_t select_unmatched_mgid; // boolean select unmatched MGID + uint8_t select_pm; // boolean select PM - defaults to 0 + + +} VFApp_t; + +// Internal rendering of Virtual Fabric Members +typedef struct _VFMem { + // System Image GUID's + uint32_t sysGuidMapSize; // number of System Image GUID entries + cl_qmap_t sysGuidMap; // binary tree of System Image GUID's + + // Node GUID entries + uint32_t nodeGuidMapSize; // number of Node GUID entries + cl_qmap_t nodeGuidMap; // binary tree of Node GUID's + + // Port GUID entries + uint32_t portGuidMapSize; // number of Port GUID entries + cl_qmap_t portGuidMap; // binary tree of Port GUID's + + // Node Description entries + uint32_t nodeDescMapSize; // number of Node descriptions + cl_qmap_t nodeDescMap; // binary tree of Node Description pointers + + // aggregate settings from group and included groups + uint8_t select_all; // boolean select all - defaults to 0 + uint8_t select_self; // boolean select self - defaults to 0 + uint8_t select_hfi_direct_connect; // boolean select all nodes in b2b (hfi direct connect) + uint8_t select_swe0; // boolean select SWE0 - defaults to 0 + uint8_t select_all_mgmt_allowed; // boolean select all mgmt allowed - defaults to 0 + uint8_t select_all_tfis; // boolean select all TFIs - defaults to 0 + + // aggregate settings from group and included groups + uint8_t node_type_fi; // boolean FI type - defaults to 0 + uint8_t node_type_sw; // boolean SW type - defaults to 0 +} VFMem_t; + +// Internal rendering of Default Groups +typedef struct _VFDg { + uint8_t def_mc_create; // if undefined will default to 1 + uint32_t def_mc_mlid; // if undefined will default to 0x0 + uint32_t def_mc_pkey; // if undefined will default to + // STL_DEFAULT_APP_PKEY + uint8_t def_mc_mtu_int; // if undefined will default to 0xff + uint8_t def_mc_rate_int; // if undefined will default to 0xff + uint8_t def_mc_sl; // if undefined will default to 0xff + uint32_t def_mc_qkey; // if undefined will default to 0x0 + uint32_t def_mc_fl; // if undefined will default to 0x0 + uint32_t def_mc_tc; // if undefined will default to 0x0 + + uint32_t mgidMapSize; + cl_qmap_t mgidMap; // Map of VFAppMgid_t + struct _VFDg *next_default_group; // pointer to next group +} VFDg_t; + +// Internal rendering of Virtual Fabric configuration - if no Vitual Fabrics +// are configured or all Virtual Fabrics are Disabled, a default single +// Virtual Fabric will be created. Disabled Virtual Fabrics will not show +// up as a defined VirtualFabric within this structure. +typedef struct _VFabric { + char name[MAX_VFABRIC_NAME]; // defaults to "Default" + uint32_t index; // one will be uniquely assigned + uint32_t pkey; // if 0xffffffff use default pkey + uint32_t qos_index; + uint8_t qos_implicit; + union { // Index in old/new vf array + uint32_t old_index; // if 0xFFFFFFFF (-1) then it is a new VF (added) + uint32_t new_index; // if 0xFFFFFFFF (-1) then it is a deleted VF (removed) + } reconf_idx; + uint8_t standby; + uint8_t security; // defaults to 0 or false + uint8_t max_mtu_int; // if 0xff then unlimited + uint8_t max_mtu_specified; + uint8_t max_rate_int; // if 0xff then unlimited + uint8_t max_rate_specified; // set by SM for use in queries + VFApp_t apps; // application SID's and MGID's etc... + uint32_t number_of_full_members; + XMLMember_t full_member[MAX_VFABRIC_MEMBERS_PER_VF]; + uint32_t number_of_limited_members; + XMLMember_t limited_member[MAX_VFABRIC_MEMBERS_PER_VF]; + uint32_t number_of_default_groups; // number of default multicast groups + VFDg_t *default_group; // default group configuration linked list + uint32_t consistency_checksum; + uint32_t disruptive_checksum; + uint32_t overall_checksum; +} VF_t; + +// Internal rendering of Composite Virtual Fabric configuration +typedef struct _SMVirtualFabricsInternal { + uint32_t number_of_vfs_all; + uint32_t number_of_qos_all; + uint8_t securityEnabled; // setup by SM + uint8_t qosEnabled; // setup by SM + VF_t v_fabric_all[MAX_ENABLED_VFABRICS]; + QosConfig_t qos_all[MAX_QOS_GROUPS]; + DGXmlConfig_t dg_config; + uint32_t consistency_checksum; + uint32_t disruptive_checksum; + uint32_t overall_checksum; +} VirtualFabrics_t; + +// SM Dynamic Packet Lifetime configuration +typedef struct _SMDPLXmlConfig { + uint32_t dp_lifetime[10]; +} SMDPLXmlConfig_t; + +// SM Multicast DefaultGroup configuration +typedef struct _SMMcastDefGrp { + uint32_t def_mc_create; + uint32_t def_mc_mlid; + char virtual_fabric[MAX_VFABRIC_NAME]; + uint32_t def_mc_pkey; + uint8_t def_mc_mtu_int; + uint8_t def_mc_rate_int; + uint8_t def_mc_sl; + uint32_t def_mc_qkey; + uint32_t def_mc_fl; + uint32_t def_mc_tc; + uint32_t number_of_mgids; + XmlAppMgid_t mgid[MAX_VFABRIC_DG_MGIDS]; + uint32_t number_of_mgid_ranges; + XmlAppMgidRng_t mgid_range[MAX_VFABRIC_DG_MGIDS]; // May implement in future + uint32_t number_of_mgid_maskeds; + XmlAppMgidMsk_t mgid_masked[MAX_VFABRIC_DG_MGIDS]; // May implement in future +} SMMcastDefGrp_t; + +// SM Multicast DefaultGroups +typedef struct _SMMcastDefGrpCfg { + uint32_t number_of_groups; + SMMcastDefGrp_t group[MAX_DEFAULT_GROUPS]; // list of default groups +} SMMcastDefGrpCfg_t; + +// SM configuration for McastGrpMGidLimitMask +typedef struct _mcastGrpMGidLimitMask { + char value[40]; +} mcastGrpMGidLimitMask_t; + +// SM configuration for McastGrpMGidLimitValue +typedef struct _mcastGrpMGidLimitValue { + char value[40]; +} mcastGrpMGidLimitValue_t; + +// SM configuration of MLIDShared +typedef struct _SmMcastMlidShared { + uint32_t enable; + mcastGrpMGidLimitMask_t mcastGrpMGidLimitMaskConvert; + mcastGrpMGidLimitValue_t mcastGrpMGidLimitValueConvert; + uint32_t mcastGrpMGidLimitMax; + uint32_t mcastGrpMGidperPkeyMax; +} SmMcastMlidShared_t; + +// SM MLIDShared Instances +typedef struct _SmMcastMlidShare { + uint32_t number_of_shared; + SmMcastMlidShared_t mcastMlid[MAX_SUPPORTED_MCAST_GRP_CLASSES_XML]; +} SmMcastMlidShare_t; + +// SM configuration for Multicast configuration +typedef struct _SMMcastConfig { + uint32_t disable_mcast_check; + uint32_t enable_pruning; + uint32_t mcast_mlid_table_cap; + char mcroot_select_algorithm[STRING_SIZE]; + char mcroot_min_cost_improvement[STRING_SIZE]; +} SMMcastConfig_t; + +// SM configuration for Link Policy +typedef struct _SMPolicyConfig { + uint8_t enabled; + uint16_t policy; +} SMPolicyConfig_t; + +typedef struct _SMLinkPolicyXmlConfig { + uint16_t link_max_downgrade; + SMPolicyConfig_t width_policy; + SMPolicyConfig_t speed_policy; +} SMLinkPolicyXmlConfig_t; + +typedef struct _SMFlappingXmlConfig{ + uint32_t window_size; //Size in minutes of sliding window over which bounce events are counted + uint32_t high_thresh; // Threshold of bounce events used to trigger quarantine state for port + uint32_t low_thresh; // threshold of bounce events to trigger unquarantine or unmonitor of port +} SMFlappingXmlConfig_t; + +typedef struct _SMPortQuarantineXmlConfig { + uint8_t enabled; + SMFlappingXmlConfig_t flapping; +} SMPortQuarantineXmlConfig_t; + +// SM configuration for Preemption +typedef struct _SMPreemptionXmlConfig { + uint32_t small_packet; + uint32_t large_packet; + uint32_t preempt_limit; +} SMPreemptionXmlConfig_t; + + +// uniform switch congestion control settings +typedef struct _SmSwCongestionXmlConfig { + uint8_t victim_marking_enable; + uint8_t threshold; + uint8_t packet_size; + uint8_t cs_threshold; + uint16_t cs_return_delay; + uint32_t marking_rate; +} SmSwCongestionXmlConfig_t; + +// uniform congestion control settings +typedef struct _SmCaCongestionXmlConfig { + uint8_t sl_based; + uint8_t increase; + uint16_t timer; + uint8_t threshold; + uint8_t min; + uint16_t limit; + uint32_t desired_max_delay; +} SmCaCongestionXmlConfig_t; + +// uniform congestion control settings +typedef struct _SmCongestionXmlConfig { + uint8_t enable; + uint8_t debug; + SmSwCongestionXmlConfig_t sw; + SmCaCongestionXmlConfig_t ca; +} SmCongestionXmlConfig_t; + + +// Adaptive Routing control settings +typedef struct _SmAdaptiveRoutingXmlConfig { + uint8_t enable; + uint8_t debug; + uint8_t lostRouteOnly; + uint8_t algorithm; + uint8_t arFrequency; + uint8_t threshold; +} SmAdaptiveRoutingXmlConfig_t; + +#define MAX_TIER 10 +typedef struct _SmFtreeRouting_t { + uint8_t debug; + uint8_t passthru; + uint8_t converge; + uint8_t tierCount; // height of the fat tree. edges are rank 0. + uint8_t fis_on_same_tier; // indicates that all end nodes are at the bottom of the tree. + XMLMember_t coreSwitches; // device group indicating core switches + XMLMember_t routeLast; // device group indicating HFIs that should be routed last. +} SmFtreeRouting_t; + + + +/* + * Structure for Device Group Min Hop routing. + * + * MAX_DGROUTING_ORDER is arbitrarily capped at 8. This could be higher, + * but raising it might cause a performance hit. + */ +#define MAX_DGROUTING_ORDER 8 +typedef struct _SmDGRouting_t { + uint8_t dgCount; + XMLMember_t dg[MAX_DGROUTING_ORDER]; +} SmDGRouting_t; + +/* + * Structures for Enhanced Routing Control for Hypercube Routing, per switch. + */ +typedef uint32_t portMap_t; + +static __inline__ void portMapSet(portMap_t *portMap, int port) +{ + portMap[port/(sizeof(portMap_t)*8)] |= (1u << port%(sizeof(portMap_t)*8)); +} + +static __inline__ portMap_t portMapTest(portMap_t *portMap, int port) +{ + return portMap[port/(sizeof(portMap_t)*8)] & (1u << port%(sizeof(portMap_t)*8)); +} + +typedef struct _SmSPRoutingPort { + uint8_t pport; + uint8_t vport; + uint16_t cost; +} SmSPRoutingPort_t; + +typedef struct _SmSPRoutingCtrl { + struct _SmSPRoutingCtrl *next; + XMLMember_t switches; // one or more switches + portMap_t pportMap[MAX_SWITCH_PORTS/(sizeof(portMap_t)*8) + 1]; + portMap_t vportMap[MAX_SWITCH_PORTS/(sizeof(portMap_t)*8) + 1]; + SmSPRoutingPort_t *ports; + uint16_t portCount; +} SmSPRoutingCtrl_t; + +typedef struct _SmHypercubeRouting_t { + uint8_t debug; + XMLMember_t routeLast; // device group indicating HFIs that should be routed last. + SmSPRoutingCtrl_t *enhancedRoutingCtrl; +} SmHypercubeRouting_t; + +#define MAX_TOROIDAL_DIMENSIONS 6 +#define MAX_DOR_DIMENSIONS 20 +#define DEFAULT_DOR_PORT_PAIR_WARN_THRESHOLD 5 +#define DEFAULT_UPDN_MC_SAME_SPANNING_TREE 1 +#define DEFAULT_ESCAPE_VLS_IN_USE 1 +#define DEFAULT_FAULT_REGIONS_IN_USE 1 + +typedef enum { + DOR_MESH, + DOR_TORUS, + DOR_PARTIAL_TORUS, +} DorTop_t; + +typedef struct _SmPortPair { + uint8_t port1; + uint8_t port2; +} SmPortPair_t; + +typedef struct _SmDimension { + uint8_t toroidal; + uint8_t length; + uint8_t portCount; + uint8_t created; + SmPortPair_t portPair[MAX_SWITCH_PORTS]; +} SmDimension_t; + +typedef struct _SmDorRouting { + uint8_t debug; + uint8_t overlayMCast; + uint8_t dimensionCount; + uint8_t numToroidal; + uint8_t routingSCs; + uint32_t warn_threshold; + SmDimension_t dimension[MAX_DOR_DIMENSIONS]; + DorTop_t topology; + uint8_t escapeVLs; + uint8_t faultRegions; + XMLMember_t routeLast; // device group indicating HFIs that should be routed last. +} SmDorRouting_t; + +#define MAX_SM_APPLIANCES 5 +typedef struct _SmAppliancesXmlConfig { + uint8_t enable; + uint64_t guids[MAX_SM_APPLIANCES]; +} SmAppliancesXmlConfig_t; + +typedef enum { + FIELD_ENF_LEVEL_DISABLED = 0, + FIELD_ENF_LEVEL_WARN = 1, + FIELD_ENF_LEVEL_ENABLED = 2, +} FieldEnforcementLevel_t; + +typedef struct _SmPreDefTopoFieldEnfXmlConfig{ + FieldEnforcementLevel_t nodeGuid; + FieldEnforcementLevel_t nodeDesc; + FieldEnforcementLevel_t portGuid; + FieldEnforcementLevel_t undefinedLink; +} SmPreDefTopoFieldEnfXmlConfig_t; + +typedef struct _SmPreDefTopoXmlConfig { + uint8_t enabled; + char topologyFilename[FILENAME_SIZE]; + uint32_t logMessageThreshold; + SmPreDefTopoFieldEnfXmlConfig_t fieldEnforcement; +} SmPreDefTopoXmlConfig_t; + +extern const char* SmPreDefFieldEnfToText(FieldEnforcementLevel_t fieldEnfLevel); + +typedef enum { + LID_STRATEGY_SERIAL, + LID_STRATEGY_TOPOLOGY +} LidStrategy_t; + + + +// SM configuration +typedef struct _SMXmlConfig { + uint64_t subnet_prefix; + uint32_t subnet_size; + uint32_t config_consistency_check_level; + + uint32_t startup_retries; + uint32_t startup_stable_wait; + uint64_t sm_key; + uint64_t mkey; + uint64_t timer; + uint32_t IgnoreTraps; + uint32_t trap_hold_down; + uint32_t max_retries; + uint32_t rcv_wait_msec; + uint32_t min_rcv_wait_msec; + uint32_t master_ping_interval; + uint32_t master_ping_max_fail; + uint32_t topo_errors_threshold; + uint32_t topo_abandon_threshold; + uint32_t switch_lifetime_n2; + uint32_t hoqlife_n2; + uint32_t vl15FlowControlDisable; + uint32_t vl15_credit_rate; + uint32_t sa_resp_time_n2; + uint32_t sa_packet_lifetime_n2; + uint32_t vlstall; + uint32_t db_sync_interval; + uint32_t mc_dos_threshold; + uint32_t mc_dos_action; + uint32_t mc_dos_interval; + uint32_t trap_threshold; + uint32_t trap_threshold_min_count; + uint32_t node_appearance_msg_thresh; + uint32_t spine_first_routing; + uint32_t shortestPathBalanced; + uint32_t lmc; + uint32_t lmc_e0; + char routing_algorithm[STRING_SIZE]; + uint32_t path_selection; + uint32_t queryValidation; + uint32_t enforceVFPathRecs; // Default to Enable to limit pathrecord scope to VFs + // otherwise, use PKEY as scope limit. + uint32_t sma_batch_size; + uint32_t max_parallel_reqs; + uint32_t check_mft_responses; + uint32_t min_supported_vls; + uint64_t cumulative_timeout_limit; + uint32_t max_fixed_vls; + uint32_t allow_mixed_vls; // Don't quarantine nodes that can't support all VLs. + uint64_t non_resp_tsec; + uint32_t non_resp_max_count; + + uint32_t monitor_standby_enable; + uint32_t loopback_mode; // disable duplicate portguid checking, allowing loopback fabrics + uint32_t max_supported_lid; + uint32_t force_rebalance; + uint32_t use_cached_node_data; + uint32_t use_cached_hfi_node_data; + + SMLinkPolicyXmlConfig_t hfi_link_policy; + SMLinkPolicyXmlConfig_t isl_link_policy; + SMPortQuarantineXmlConfig_t port_quarantine; + SMPreemptionXmlConfig_t preemption; + + SmCongestionXmlConfig_t congestion; + + + SmDorRouting_t smDorRouting; + + SmAdaptiveRoutingXmlConfig_t adaptiveRouting; + + uint32_t sma_spoofing_check; // used to enable/disable usage of SMA security checking + uint32_t NoReplyIfBusy; // Normally when an SA query cannot be processed because + // a context is temporarily not available or an error is + // detected which may be resolved when an im progress sweep + // finishes, a busy status will be returned to the requester. + // + // If the new configuration option NoReplyIfBusy is set to 1, + // rather than returning the busy status, no status will + // be returned. The behaviour will be as if the MAD request + // were lost. + // + // If NoReplyIfBusy is set to 0 or is not in the configuration + // file, the behavior of SM will be the same as if this change + // had not been made. + + /* STL EXTENSIONS */ + uint32_t lft_multi_block; // # of LFT blocks per MAD. Valid range is 1-31. + uint32_t use_aggregates; // 0/1 - if true, combine MADs where possible. + uint32_t optimized_buffer_control; // 0/1 - if true, use multi-port and uniform buffer ctrl + // MADs to program switch ports. + SmAppliancesXmlConfig_t appliances; // List of node GUIDs associated with appliance nodes + SmPreDefTopoXmlConfig_t preDefTopo; // Pre-defined topology verification options and field enforcement + + uint32_t minSharedVLMem; // A specification (percentage) for minimum VL shared memory. + uint32_t dedicatedVLMemMulti; // A multiplier increasing the dedicated memory per VL + int32_t wireDepthOverride; // Value (bytes) to override the wire depth, + // -1 means use from Portinfo, 0 means no wire depth + int32_t replayDepthOverride; // Value (bytes) to override the replay buffer depth, -1 means use from Portinfo + // -1 means use from Portinfo, 0 means no replay depth + + uint8_t cableInfoPolicy; // 0 means no CI cache, 1 means assume CI is identical for both ends of a cable, + // 2 means do not assume CI is identical for both ends. + uint32_t forceAttributeRewrite; // Used to force the SM to rewrite all attributes upon resweep + // 0 is disabled (default), 1 is enabled + uint32_t timerScalingEnable; // 0 is disabled (default), when enabled - HOQ and SLL are potentially modified. + uint32_t defaultPortErrorAction; // Bitfield representing default PortInfo PortErrorAction(s) to set for each port + uint32_t skipAttributeWrite; // Bitfield indicating attributes to be skipped for updating (debug) + uint32_t switchCascadeActivateEnable;// 0 - Disabled, 1 - Enable cascade activation using IsActiveOptimizeEnable + uint32_t neighborNormalRetries; // Number of retries when a port fails to go ACTIVE based on neighbor state (NeighborNormal flag) + uint8_t terminateAfter; // Undocumented setting. 0 - Disabled, #>0 - Terminate after # sweeps. + uint8_t psThreads; // Undocumented setting. The # of threads to use for parallel SM programming. + uint32_t portBounceLogLimit; // Number of port bounce log messages to show before suppressing the rest. + uint32_t neighborFWAuthenEnable; // used to enable/disable usage of NeighborFWAuthenBypass checking + uint32_t SslSecurityEnabled; + char SslSecurityDir[FILENAME_SIZE]; + char SslSecurityFmCertificate[FILENAME_SIZE]; + char SslSecurityFmPrivateKey[FILENAME_SIZE]; + char SslSecurityFmCaCertificate[FILENAME_SIZE]; + uint32_t SslSecurityFmCertChainDepth; + char SslSecurityFmDHParameters[FILENAME_SIZE]; + uint32_t SslSecurityFmCaCRLEnabled; + char SslSecurityFmCaCRL[FILENAME_SIZE]; + + uint32_t consistency_checksum; // used for checking SM consistency in fabric + uint32_t overall_checksum; // used to determine if SM config needs to be re-read + uint32_t disruptive_checksum; // checksum of parameters that are disruptive to change + + SmFtreeRouting_t ftreeRouting; + SmDGRouting_t dgRouting; + SmHypercubeRouting_t hypercubeRouting; + + char name[MAX_VFABRIC_NAME]; + uint32_t start; + uint32_t hca; + uint32_t port; + uint64_t port_guid; + + uint32_t lid; + uint32_t sa_rmpp_checksum; + uint32_t dynamic_port_alloc; + + uint32_t sm_debug_perf; + uint32_t sa_debug_perf; + uint32_t sm_debug_vf; + uint32_t sm_debug_routing; + uint32_t sm_debug_lid_assign; + uint32_t trap_log_suppress_trigger_interval; + uint32_t debug_jm; + + uint32_t priority; + uint32_t elevated_priority; + char CoreDumpLimit[STRING_SIZE]; // inherited from Common FM setting + char CoreDumpDir[FILENAME_SIZE]; // inherited from Common FM setting + uint32_t debug; + uint32_t debug_rmpp; + uint32_t log_level; + char log_file[LOGFILE_SIZE]; + uint32_t syslog_mode; + char syslog_facility[STRING_SIZE]; + FmParamU32_t log_masks[VIEO_LAST_MOD_ID+1]; + + uint32_t loop_test_on; + uint32_t loop_test_fast_mode; + uint32_t loop_test_packets; + + char dumpCounters[LOGFILE_SIZE]; // Undocumented setting. Null - Disabled. Not Null - dump performance counters after each sweep. + + uint32_t multicast_mask; + uint32_t lid_strategy; + uint32_t sm_dsap_enabled; + uint32_t P_Key_8B; + uint32_t P_Key_10B; +} SMXmlConfig_t; + +typedef struct _XMLMonitor { + char monitor[MAX_VFABRIC_NAME]; + uint16_t dg_Index; +} XMLMonitor_t; +//Pm PortGroups +typedef struct PmPortGroupXmlConfig { + uint8_t Enabled; + char Name[STL_PM_GROUPNAMELEN+1]; + XMLMonitor_t Monitors[STL_PM_MAX_DG_PER_PMPG]; +} PmPortGroupXmlConfig_t; + +// Pm Thresholds +typedef struct _PmThresholdsXmlConfig { + uint32_t Integrity; + uint32_t Congestion; + uint32_t SmaCongestion; + uint32_t Bubble; + uint32_t Security; + uint32_t Routing; +} PmThresholdsXmlConfig_t; + +// Pm ThresholdsExceededMsgLimit +typedef struct _PmThresholdsExceededMsgLimitXmlConfig { + uint32_t Integrity; + uint32_t Congestion; + uint32_t SmaCongestion; + uint32_t Bubble; + uint32_t Security; + uint32_t Routing; +} PmThresholdsExceededMsgLimitXmlConfig_t; + +typedef struct _PmSweepErrorInfoThresholds { + uint32_t Integrity; + uint32_t Security; + uint32_t Routing; +} PmSweepErrorInfoThresholds_t; + +// Pm IntegrityWeights +typedef struct _PmIntegrityWeightsXmlConfig { + uint8_t LocalLinkIntegrityErrors; + uint8_t PortRcvErrors; + uint8_t ExcessiveBufferOverruns; + uint8_t LinkErrorRecovery; + uint8_t LinkDowned; + uint8_t UncorrectableErrors; + uint8_t FMConfigErrors; + uint8_t LinkQualityIndicator; + uint8_t LinkWidthDowngrade; +} PmIntegrityWeightsXmlConfig_t; + +// Pm CongestionWeights +typedef struct _PmCongestionWeightsConfig { + uint8_t PortXmitWait; + uint8_t SwPortCongestion; + uint8_t PortRcvFECN; + uint8_t PortRcvBECN; + uint8_t PortXmitTimeCong; + uint8_t PortMarkFECN; +} PmCongestionWeightsXmlConfig_t; + +typedef struct _PmResolutionXmlConfig { + uint64_t LocalLinkIntegrity; + uint32_t LinkErrorRecovery; +} PmResolutionXmlConfig_t; + +typedef struct _PmShortTermHistoryXmlConfig { + uint8_t enable; + char StorageLocation[FILENAME_SIZE]; + uint32_t totalHistory; + uint32_t imagesPerComposite; + uint64_t maxDiskSpace; + uint8_t compressionDivisions; +} PmShortTermHistoryXmlConfig_t; + +// PM configuration +typedef struct _PMXmlConfig { + uint32_t subnet_size; + uint32_t config_consistency_check_level; + + uint16_t sweep_interval; + uint32_t timer; + uint8_t ErrorClear; + uint8_t ClearDataXfer; + uint8_t Clear64bit; + uint8_t Clear32bit; + uint8_t Clear8bit; + uint8_t process_hfi_counters; + uint8_t process_vl_counters; + uint8_t process_errorinfo; + uint32_t MaxRetries; + uint32_t RcvWaitInterval; + uint32_t MinRcvWaitInterval; + uint32_t SweepErrorsLogThreshold; + uint32_t MaxParallelNodes; + uint32_t PmaBatchSize; + uint32_t freeze_frame_lease; + uint32_t total_images; + uint32_t freeze_frame_images; + uint32_t max_clients; + uint32_t history_file_update_rate; + uint16_t image_update_interval; + PmThresholdsXmlConfig_t thresholds; + PmIntegrityWeightsXmlConfig_t integrityWeights; + PmCongestionWeightsXmlConfig_t congestionWeights; + PmResolutionXmlConfig_t resolution; + uint8_t number_of_pm_groups; + PmPortGroupXmlConfig_t pm_portgroups[STL_PM_MAX_CUSTOM_PORT_GROUPS]; + PmShortTermHistoryXmlConfig_t shortTermHistory; + uint32_t SslSecurityEnabled; + char SslSecurityDir[FILENAME_SIZE]; + char SslSecurityFmCertificate[FILENAME_SIZE]; + char SslSecurityFmPrivateKey[FILENAME_SIZE]; + char SslSecurityFmCaCertificate[FILENAME_SIZE]; + uint32_t SslSecurityFmCertChainDepth; + char SslSecurityFmDHParameters[FILENAME_SIZE]; + uint32_t SslSecurityFmCaCRLEnabled; + char SslSecurityFmCaCRL[FILENAME_SIZE]; + + uint32_t consistency_checksum; + uint32_t overall_checksum; + uint32_t disruptive_checksum; // checksum of parameters that are disruptive to change + + char name[MAX_VFABRIC_NAME]; + uint32_t start; + uint32_t hca; + uint32_t port; + uint64_t port_guid; + + uint32_t priority; + uint32_t elevated_priority; + uint32_t debug; + uint32_t debug_rmpp; + uint32_t pm_debug_perf; + uint32_t log_level; + char log_file[LOGFILE_SIZE]; + uint32_t syslog_mode; + char syslog_facility[STRING_SIZE]; + FmParamU32_t log_masks[VIEO_LAST_MOD_ID+1]; + + PmThresholdsExceededMsgLimitXmlConfig_t thresholdsExceededMsgLimit; + + PmSweepErrorInfoThresholds_t errorinfo_thresholds; + +} PMXmlConfig_t; + +// FE configuration +typedef struct _FEXmlConfig { + uint32_t subnet_size; + uint32_t startup_retries; + uint32_t startup_stable_wait; + + uint32_t manager_check_rate; + uint32_t login; + uint32_t window; + uint32_t SslSecurityEnabled; + char SslSecurityDir[FILENAME_SIZE]; + char SslSecurityFmCertificate[FILENAME_SIZE]; + char SslSecurityFmPrivateKey[FILENAME_SIZE]; + char SslSecurityFmCaCertificate[FILENAME_SIZE]; + uint32_t SslSecurityFmCertChainDepth; + char SslSecurityFmDHParameters[FILENAME_SIZE]; + uint32_t SslSecurityFmCaCRLEnabled; + char SslSecurityFmCaCRL[FILENAME_SIZE]; + + char name[MAX_VFABRIC_NAME + 4]; // Padded for the "_fe" suffix. + uint32_t start; + uint32_t hca; + uint32_t port; + uint64_t port_guid; + + uint32_t listen; + + char CoreDumpLimit[STRING_SIZE]; + char CoreDumpDir[FILENAME_SIZE]; + uint32_t debug; + uint32_t debug_rmpp; + uint32_t log_level; + char log_file[LOGFILE_SIZE]; + uint32_t syslog_mode; + char syslog_facility[STRING_SIZE]; + FmParamU32_t log_masks[VIEO_LAST_MOD_ID+1]; + + uint32_t trap_count; + uint16_t trap_nums[FE_MAX_TRAP_SUBS]; +} FEXmlConfig_t; + +// FM configuration (Shared) +typedef struct _FMXmlConfig { + uint64_t subnet_prefix; + uint32_t subnet_size; + uint32_t startup_retries; + uint32_t startup_stable_wait; + uint32_t config_consistency_check_level; + uint32_t SslSecurityEnabled; + char SslSecurityDir[FILENAME_SIZE]; + char SslSecurityFmCertificate[FILENAME_SIZE]; + char SslSecurityFmPrivateKey[FILENAME_SIZE]; + char SslSecurityFmCaCertificate[FILENAME_SIZE]; + uint32_t SslSecurityFmCertChainDepth; + char SslSecurityFmDHParameters[FILENAME_SIZE]; + uint32_t SslSecurityFmCaCRLEnabled; + char SslSecurityFmCaCRL[FILENAME_SIZE]; + + char fm_name[MAX_VFABRIC_NAME]; + uint32_t start; + uint32_t hca; + uint32_t port; + uint64_t port_guid; + + uint32_t priority; + uint32_t elevated_priority; + char CoreDumpLimit[STRING_SIZE]; + char CoreDumpDir[FILENAME_SIZE]; + uint32_t debug; + uint32_t debug_rmpp; + uint32_t log_level; + char log_file[LOGFILE_SIZE]; + uint32_t syslog_mode; + char syslog_facility[STRING_SIZE]; + FmParamU32_t log_masks[VIEO_LAST_MOD_ID+1]; + // FM config doesn't have checksums because all the data is contained in SM, PM, or FE configs +} FMXmlConfig_t; + + + + +// FM instance +typedef struct _FMXmlInstance { + FMXmlConfig_t fm_config; + SMXmlConfig_t sm_config; + SMDPLXmlConfig_t sm_dpl_config; + SMMcastConfig_t sm_mc_config; + SmMcastMlidShare_t sm_mls_config; + SMMcastDefGrpCfg_t sm_mdg_config; + VFXmlConfig_t vf_config; + QosXmlConfig_t qos_config; + DGXmlConfig_t dg_config; + AppXmlConfig_t app_config; + PMXmlConfig_t pm_config; + FEXmlConfig_t fe_config; + + +} FMXmlInstance_t; + +// XML debug +typedef struct _XmlDebug { + uint32_t xml_all_debug; + uint32_t xml_vf_debug; + uint32_t xml_sm_debug; + uint32_t xml_fe_debug; + uint32_t xml_pm_debug; + uint32_t xml_parse_debug; +} XmlDebug_t; + +// Composite FM configuration +typedef struct _FMXmlCompositeConfig { + FMXmlInstance_t *fm_instance_common; + FMXmlInstance_t *fm_instance[MAX_INSTANCES]; + int num_instances; + XmlDebug_t xmlDebug; +} FMXmlCompositeConfig_t; + +// parseFmConfig: +// fm - instance to parse +// full - Parse all the instances in the config file (ignore the fm parameter) +// preverify - run renderVirtualFabics on config to verify VFs +// (not necessary if renderVirtualFabrics will be called) +extern FMXmlCompositeConfig_t* parseFmConfig(char *filename, uint32_t flags, uint32_t fm, uint32_t full, uint32_t preverify, uint32_t embedded); +extern void releaseXmlConfig(FMXmlCompositeConfig_t *config, uint32_t full); +extern VirtualFabrics_t* renderVirtualFabricsConfig(uint32_t fm, FMXmlCompositeConfig_t *config, + IXmlParserPrintMessage printError, IXmlParserPrintMessage printWarning); +extern VirtualFabrics_t* reRenderVirtualFabricsConfig(uint32_t fm, VirtualFabrics_t *oldVfsip, FMXmlCompositeConfig_t *config, + IXmlParserPrintMessage printError, IXmlParserPrintMessage printWarning); + + +extern void releaseVirtualFabricsConfig(VirtualFabrics_t *vfsip); +extern void initXmlPoolGetCallback(void *function); +extern void initXmlPoolFreeCallback(void *function); +extern uint32_t xml_compute_pool_size(uint8_t full); +extern uint8_t verifyFmConfig(char* filename, uint32_t flags); +int generateDefaultXmlConfig(uint8_t cli); +extern VF_t* findVfPointer(VirtualFabrics_t*, char*); +extern void fmClearConfig(FMXmlConfig_t *fmp); +extern void pmClearConfig(PMXmlConfig_t *pmp); +extern void feClearConfig(FEXmlConfig_t *fep); +extern void smScrubConfig(SMXmlConfig_t *smp); +extern boolean smCopyConfig(SMXmlConfig_t *dst,SMXmlConfig_t *src); +extern void smClearConfig(SMXmlConfig_t *smp); +#ifndef __VXWORKS__ +extern int getFacility(char* name, uint8_t test); +#endif +extern void smShowConfig(SMXmlConfig_t *smp, SMDPLXmlConfig_t *dplp, SMMcastConfig_t *mcp, SmMcastMlidShare_t *mlsp); +extern void pmShowConfig(PMXmlConfig_t *pmp); +extern void feShowConfig(FEXmlConfig_t *fep); +extern int getXMLConfigData(uint8_t *buffer, uint32_t bufflen, uint32_t *filelen); +extern int putXMLConfigData(uint8_t *buffer, uint32_t filelen); +extern int copyCompressXMLConfigFile(char *src, char *dst); +extern void freeDgInfo(DGXmlConfig_t *dg); +extern FSTATUS MatchImplicitMGIDtoVF(SMMcastDefGrp_t *mdgp, VirtualFabrics_t *vf_config); +extern FSTATUS MatchExplicitMGIDtoVF(SMMcastDefGrp_t *mdgp, VirtualFabrics_t *vf_config, boolean update_active_vfabrics, int enforceVFPathRecs); +int verifyAndConvertMGidString(char *mgidString, VFAppMgid_t *mgidMapping); +// Export XML Memory mapping functions for the SM to use with the Topology lib on ESM +#ifdef __VXWORKS__ +extern void* getParserMemory(size_t size); +extern void* reallocParserMemory(void* ptr, size_t size); +extern void freeParserMemory(void* ptr); +#endif + +// Macro for proper typecasting of pointers into the cl_map_item key +#ifdef __VXWORKS__ +#define XML_QMAP_CHAR_CAST (char*)(uint32) +#define XML_QMAP_U64_CAST (uint64)(uint32) +#define XML_QMAP_VOID_CAST (void*)(uint32) +#define XML_QMAP_U8_CAST (uint8_t*)(uint32) +#else +#define XML_QMAP_CHAR_CAST (char*) +#define XML_QMAP_U64_CAST (uint64) +#define XML_QMAP_VOID_CAST (void*) +#define XML_QMAP_U8_CAST (uint8_t*) +#endif + +#define for_all_qmap_item(map, item) \ + for(item = cl_qmap_head(map); \ + item != cl_qmap_end(map); \ + item = cl_qmap_next(item)) + +#define for_all_qmap_type(map, item, obj, type) \ + for(item = cl_qmap_head(map), obj = type cl_qmap_key(item); \ + item != cl_qmap_end(map); \ + item = cl_qmap_next(item), obj = type cl_qmap_key(item)) + +#define for_all_qmap_u64(map, item, obj) for_all_qmap_type(map, item, obj, XML_QMAP_U64_CAST) +#define for_all_qmap_ptr(map, item, obj) for_all_qmap_type(map, item, obj, XML_QMAP_VOID_CAST) + +#endif // _FM_XML_H_ diff --git a/Esm/ib/include/hsm_com_srvr_api.h b/Esm/ib/include/hsm_com_srvr_api.h new file mode 100644 index 0000000..d241bb2 --- /dev/null +++ b/Esm/ib/include/hsm_com_srvr_api.h @@ -0,0 +1,151 @@ +/* BEGIN_ICS_COPYRIGHT2 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + * ** END_ICS_COPYRIGHT2 ****************************************/ + +#ifndef HSM_COM_SRVR_API +#define HSM_COM_SRVR_API + +/* TODO: + Define message structure? + Define callback - provide to server_init or server_start + Define error callback - ditto + Define error structure + +*/ + + + +#ifndef IN +#define IN +#endif /* #ifndef IN */ + +#ifndef OUT +#define OUT +#endif /* #ifndef OUT */ + +#ifndef OPTIONAL +#define OPTIONAL +#endif /* #ifndef OPTIONAL */ + +#define HSM_COM_API_MAX_DATA 1024 + + +// C++ wrapper +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +// Error codes +typedef enum{ + HSM_COM_ERR_LEN, + HSM_COM_ERR_VERSION, + HSM_COM_ERR_DISC, + HSM_COM_TEST = -1, + HSM_COM_OK = 0, + HSM_COM_ERROR = 1, + HSM_COM_NO_RESOURCES = 2, + HSM_COM_NO_MEM, + HSM_COM_PATH_ERR, + HSM_COM_BAD, + HSM_COM_BIND_ERR, + HSM_COM_SOCK_ERR, + HSM_COM_CHMOD_ERR, + HSM_COM_CONX_ERR, + HSM_COM_SEND_ERR, + HSM_COM_NOT_CONNECTED, + HSM_COM_LISTEN_ERR, + HSM_COM_MAX_ERROR_NUM +}hsm_com_errno_t; + + +typedef enum{ + HSM_METH_GET = 1, + HSM_METH_SET, + HSM_METH_RSP, +}hsm_com_method_t; + +// Session structures (opaque) +typedef struct _hsm_com_server_hdl *p_hsm_com_server_hdl_t; +typedef struct _hsm_com_client_hdl *p_hsm_com_client_hdl_t; +typedef struct _hsm_com_stream_hdl *p_hsm_com_stream_hdl_t; + +typedef struct hsm_com_datagram_s{ + int data_len; + int buf_size; + char *buf; +}hsm_com_datagram_t; + +// Server Data callback function +// Note: data is IN/OUT. +typedef hsm_com_errno_t (*hsm_com_callback_func)(hsm_com_datagram_t *data); + +// Server Error callback function +typedef void (*hsm_com_err_callback_func)(hsm_com_errno_t err); + + +hsm_com_errno_t +hcom_server_init +( + OUT p_hsm_com_server_hdl_t *p_hdl, + IN char *socket_path, + IN int max_conx, + IN int max_data_len, + IN hsm_com_callback_func callback +); + + +hsm_com_errno_t +hcom_server_terminate +( + IN p_hsm_com_server_hdl_t p_hdl +); + + + +hsm_com_errno_t +hcom_server_start +( + IN p_hsm_com_server_hdl_t p_hdl +); + + +hsm_com_errno_t +hcom_server_stop +( + IN p_hsm_com_server_hdl_t p_hdl +); + + + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /*HSM_COM_SRVR_API*/ + diff --git a/Esm/ib/include/hsm_config_srvr_api.h b/Esm/ib/include/hsm_config_srvr_api.h new file mode 100644 index 0000000..1368061 --- /dev/null +++ b/Esm/ib/include/hsm_config_srvr_api.h @@ -0,0 +1,712 @@ +/* BEGIN_ICS_COPYRIGHT2 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + * ** END_ICS_COPYRIGHT2 ****************************************/ + +#ifndef HSM_CONFIG_SRVR_API +#define HSM_CONFIG_SRVR_API + +#include "hsm_com_srvr_api.h" +#ifdef __LINUX__ +#include +#include +#else +#ifndef uint64_t +#define uint64_t unsigned long long +#endif +#endif + +#ifndef IN +#define IN +#endif /* #ifndef IN */ + +#ifndef OUT +#define OUT +#endif /* #ifndef OUT */ + +#ifndef OPTIONAL +#define OPTIONAL +#endif /* #ifndef OPTIONAL */ + + + +typedef struct _fm_config_conx_hdl *p_fm_config_conx_hdlt; + + +typedef enum fm_mgr_type_s{ + FM_MGR_NONE = 0, + FM_MGR_SM = 0x0001, + FM_MGR_PM = 0x0002, + FM_MGR_FE = 0x0004, +}fm_mgr_type_t; + +typedef enum{ + FM_CONF_ERR_LEN = -4, + FM_CONF_ERR_VERSION = -3, + FM_CONF_ERR_DISC = -2, + FM_CONF_TEST = -1, + FM_CONF_OK = 0, + FM_CONF_ERROR = 1, + FM_CONF_NO_RESOURCES = 2, + FM_CONF_NO_MEM, + FM_CONF_PATH_ERR, + FM_CONF_BAD, + FM_CONF_BIND_ERR, + FM_CONF_SOCK_ERR, + FM_CONF_CHMOD_ERR, + FM_CONF_CONX_ERR, + FM_CONF_SEND_ERR, + FM_CONF_INIT_ERR, + FM_CONF_NO_RESP, + FM_CONF_ALLOC_ERR, + FM_CONF_MAX_ERROR_NUM +}fm_mgr_config_errno_t; + +typedef enum{ + FM_ACT_NONE = 0, + FM_ACT_GET, // Get selected attributes + FM_ACT_SET, // Set appropriate attributes + FM_ACT_RSP, // Response + FM_ACT_SUP_GET, // Query which attributes are supported + FM_ACT_SUP_SET, // Query which attributes are supported + FM_ACT_GET_NEXT // Get next logical row in table +}fm_mgr_action_t; + + +typedef enum{ + FM_RET_BAD_RET_LEN = -1, + FM_RET_OK = 0, + FM_RET_DT_NOT_SUPPORTED, // Datatype is not supported + FM_RET_ACT_NOT_SUPPORTED, // Action is not supported for this datatype + FM_RET_INVALID, // Data is invalid. + FM_RET_BAD_LEN, // Data is an invalid length + FM_RET_BUSY, // Server busy, try again later. + FM_RET_UNKNOWN_DT, // Data type is not recognized. + FM_RET_NOT_FOUND, // Object not found + FM_RET_NO_NEXT, // No next entry in table + FM_RET_NOT_MASTER, // SM is not master and cannot perform requested operation + FM_RET_NOSUCHOBJECT, + FM_RET_NOSUCHINSTANCE, + FM_RET_ENDOFMIBVIEW, + FM_RET_ERR_NOERROR, + FM_RET_ERR_TOOBIG, + FM_RET_ERR_NOSUCHNAME, + FM_RET_ERR_BADVALUE, + FM_RET_ERR_READONLY, + FM_RET_ERR_GENERR, + FM_RET_ERR_NOACCESS, + FM_RET_ERR_WRONGTYPE, + FM_RET_ERR_WRONGLENGTH, + FM_RET_ERR_WRONGENCODING, + FM_RET_ERR_WRONGVALUE, + FM_RET_ERR_NOCREATION, + FM_RET_ERR_INCONSISTENTVALUE, + FM_RET_ERR_RESOURCEUNAVAILABLE, + FM_RET_ERR_COMMITFAILED, + FM_RET_ERR_UNDOFAILED, + FM_RET_ERR_AUTHORIZATIONERROR, + FM_RET_ERR_NOTWRITABLE, + FM_RET_END_OF_TABLE, + FM_RET_INTERNAL_ERR, + FM_RET_CONX_CLOSED, + FM_RET_TIMEOUT +}fm_msg_ret_code_t; + + +typedef enum{ + FM_DT_NONE = 0, + FM_DT_COMMON, + FM_DT_BM_CFG, + FM_DT_PM_CFG, + FM_DT_FE_CFG, + FM_DT_SM_CFG, + FM_DT_SM_PKEY, + FM_DT_SM_MC, + FM_DT_SM_STATUS, + FM_DT_PM_STATUS, + FM_DT_BM_STATUS, + FM_DT_FE_STATUS, + FM_DT_SM_NODE_INFO, + FM_DT_SM_PORT_INFO, + FM_DT_SM_SWITCH_INFO, + FM_DT_SM_MCAST_GRP_INFO, + FM_DT_SM_MCAST_REC_INFO, + FM_DT_SM_SM_INFO, + FM_DT_SM_LINK_INFO, + FM_DT_SM_SERV_INFO, + FM_DT_SM_GUID_INFO, + FM_DT_LOG_LEVEL, + FM_DT_DEBUG_TOGGLE, + FM_DT_RMPP_DEBUG_TOGGLE, + FM_DT_FORCE_SWEEP, + FM_DT_SM_PERF_DEBUG_TOGGLE, + FM_DT_SA_PERF_DEBUG_TOGGLE, + FM_DT_SM_LOOP_TEST_FAST_MODE_START, + FM_DT_SM_LOOP_TEST_START, + FM_DT_SM_LOOP_TEST_STOP, + FM_DT_SM_LOOP_TEST_FAST, + FM_DT_SM_LOOP_TEST_INJECT_PACKETS, + FM_DT_SM_LOOP_TEST_INJECT_ATNODE, + FM_DT_SM_LOOP_TEST_INJECT_EACH_SWEEP, + FM_DT_SM_LOOP_TEST_PATH_LEN, + FM_DT_SM_LOOP_TEST_MIN_ISL_REDUNDANCY, + FM_DT_SM_LOOP_TEST_SHOW_PATHS, + FM_DT_SM_LOOP_TEST_SHOW_LFTS, + FM_DT_SM_LOOP_TEST_SHOW_TOPO, + FM_DT_SM_LOOP_TEST_SHOW_CONFIG, + FM_DT_SM_RESTORE_PRIORITY, + FM_DT_SM_GET_COUNTERS, + FM_DT_SM_RESET_COUNTERS, + FM_DT_SM_DUMP_STATE, + FM_DT_BM_RESTORE_PRIORITY, + FM_DT_PM_RESTORE_PRIORITY, + FM_DT_SM_FORCE_REBALANCE_TOGGLE, + FM_DT_PM_GET_COUNTERS, + FM_DT_PM_RESET_COUNTERS, + FM_DT_LOG_MODE, + FM_DT_LOG_MASK, + FM_DT_SM_BROADCAST_XML_CONFIG, + FM_DT_SM_GET_ADAPTIVE_ROUTING, + FM_DT_SM_SET_ADAPTIVE_ROUTING, + FM_DT_SM_FORCE_ATTRIBUTE_REWRITE, + FM_DT_SM_SKIP_ATTRIBUTE_WRITE, + FM_DT_PAUSE_SWEEPS, + FM_DT_RESUME_SWEEPS, +}fm_datatype_t; + +typedef struct fm_error_map_s{ + int err_set; + fm_msg_ret_code_t map[64]; +}fm_error_map_t; + + +/* The current error map is copied to the pointer provided */ +fm_mgr_config_errno_t +fm_mgr_config_get_error_map +( + IN p_fm_config_conx_hdlt hdl, + OUT fm_error_map_t *error_map +); + +fm_mgr_config_errno_t +fm_mgr_config_clear_error_map +( + IN p_fm_config_conx_hdlt hdl +); + + +fm_mgr_config_errno_t +fm_mgr_config_get_error_map_entry +( + IN p_fm_config_conx_hdlt hdl, + IN uint64_t mask, + OUT fm_mgr_config_errno_t *error_code +); + +fm_mgr_config_errno_t +fm_mgr_config_set_error_map_entry +( + IN p_fm_config_conx_hdlt hdl, + IN uint64_t mask, + IN fm_mgr_config_errno_t error_code +); + + + + + + +#define CFG_COM_SEL_DEVICE 0x0001 +#define CFG_COM_SEL_PORT 0x0002 +#define CFG_COM_SEL_DEBUG 0x0004 +#define CFG_COM_SEL_POOL_SIZE 0x0008 +#define CFG_COM_SEL_NODAEMON 0x0010 +#define CFG_COM_SEL_LOG_LEVEL 0x0020 +#define CFG_COM_SEL_DBG_RMPP 0x0040 +#define CFG_COM_SEL_LOG_FILTER 0x0080 +#define CFG_COM_SEL_LOG_MASK 0x0100 +#define CFG_COM_SEL_LOG_FILE 0x0200 + +#define CFG_COM_SEL_ALL 0xFFFF + +// Common query routines. +typedef struct fm_config_common_s{ + uint64_t select_mask; + int32_t device; + int32_t port; + int debug; + unsigned long pool_size; + int nodaemon; // NOTE: READ-ONLY + int log_level; + int debug_rmpp; + int log_filter; + int log_mask; + char log_file[256]; +}fm_config_common_t; + +#define CFG_BM_SEL_BKEY 0x0001 +#define CFG_BM_SEL_BKEY_LEASE 0x0002 +#define CFG_BM_SEL_PRIORITY 0x0004 +#define CFG_BM_SEL_TIMER 0x0008 + +#define CFG_BM_SEL_ALL 0xFFFF + +typedef struct bm_config_s{ + uint64_t select_mask; + unsigned char bkey[8]; + int32_t bkey_lease; + unsigned priority; + unsigned timer; +}bm_config_t; + + +#define CFG_FE_SEL_LISTEN 0x0001 +#define CFG_FE_SEL_LOGIN 0x0002 +#define CFG_FE_SEL_PRIORITY 0x0004 + +#define CFG_FE_SEL_ALL 0xFFFF + +typedef struct fe_config_s{ + uint64_t select_mask; + unsigned listen; + unsigned login; + unsigned priority; +}fe_config_t; + + +#define CFG_PM_SEL_PRIORITY 0x0001 +#define CFG_PM_SEL_TIMER 0x0002 + +#define CFG_PM_SEL_ALL 0xFFFF + + +typedef struct pm_config_s{ + uint64_t select_mask; + int32_t priority; + unsigned timer; +}pm_config_t; + +#define CFG_SM_SEL_KEY 0x0001 +#define CFG_SM_SEL_PRIORITY 0x0002 +#define CFG_SM_SEL_TIMER 0x0004 +#define CFG_SM_SEL_MAX_RETRY 0x0008 +#define CFG_SM_SEL_RCV_WAIT_MSEC 0x0010 +#define CFG_SM_SEL_SW_LFTIME 0x0020 +#define CFG_SM_SEL_HOQ_LIFE 0x0040 +#define CFG_SM_SEL_VL_STALL 0x0080 +#define CFG_SM_SEL_SA_RESP_TIME 0x0100 +#define CFG_SM_SEL_SA_PKT_LIFETIME 0x0200 +#define CFG_SM_SEL_LID 0x0400 +#define CFG_SM_SEL_LMC 0x0800 +#define CFG_SM_SEL_PKEY_SUPPORT 0x1000 +#define CFG_SM_SEL_MKEY 0x2000 + +#define CFG_SM_SEL_ALL 0xFFFF + + +typedef struct sm_config_s{ + uint64_t select_mask; + unsigned char key[8]; + int32_t priority; + unsigned timer; + unsigned max_retries; + unsigned rcv_wait_msec; + unsigned switch_lifetime; + unsigned hoq_life; + unsigned vl_stall; + unsigned sa_resp_time; + unsigned sa_packet_lifetime; + unsigned lid; + unsigned lmc; + unsigned pkey_support; + unsigned char mkey[8]; +}sm_config_t; + +// Note: Select mask here indicates the pkey index. +typedef struct sm_pkey_s{ + uint64_t select_mask; + unsigned long pkey[32]; +}sm_pkey_t; + +#define CFG_SM_MC_SEL_CREATE 0x0001 +#define CFG_SM_MC_SEL_PKEY 0x0002 +#define CFG_SM_MC_SEL_MTU 0x0004 +#define CFG_SM_MC_SEL_RATE 0x0008 +#define CFG_SM_MC_SEL_SL 0x0010 + +#define CFG_SM_MC_SEL_ALL 0xFFFF + +typedef struct sm_mc_group_s{ + uint64_t select_mask; + unsigned create; + unsigned pkey; + unsigned mtu; + unsigned rate; + unsigned sl; +}sm_mc_group_t; + + +#define CFG_SM_STATUS_STATE 0x0001 +#define CFG_SM_STATUS_UPTIME 0x0002 +#define CFG_SM_STATUS_MASTER 0x0004 + +#define CFG_SM_STATUS_SEL_ALL 0xFFFF + +typedef struct fm_sm_status_s{ + uint64_t select_mask; + unsigned status; + int32_t uptime; + unsigned master; +}fm_sm_status_t; + +#define CFG_PM_STATUS_STATE 0x0001 +#define CFG_PM_STATUS_UPTIME 0x0002 +#define CFG_PM_STATUS_MASTER 0x0004 + +#define CFG_PM_STATUS_SEL_ALL 0xFFFF + +typedef struct fm_pm_status_s{ + uint64_t select_mask; + unsigned status; + unsigned long uptime; + unsigned master; +}fm_pm_status_t; + +#define CFG_FE_STATUS_STATE 0x0001 +#define CFG_FE_STATUS_UPTIME 0x0002 +#define CFG_FE_STATUS_MASTER 0x0004 + +#define CFG_FE_STATUS_SEL_ALL 0xFFFF + +typedef struct fm_fe_status_s{ + uint64_t select_mask; + unsigned status; + unsigned long uptime; + unsigned master; +}fm_fe_status_t; + +#define CFG_BM_STATUS_STATE 0x0001 +#define CFG_BM_STATUS_UPTIME 0x0002 +#define CFG_BM_STATUS_MASTER 0x0004 + +#define CFG_BM_STATUS_SEL_ALL 0xFFFF + +typedef struct fm_bm_status_s{ + uint64_t select_mask; + unsigned status; + unsigned long uptime; + unsigned master; +}fm_bm_status_t; + +typedef struct fm_sm_node_info_s{ + uint64_t select_mask; + unsigned char ibSmNodeInfoSubnetPrefix[8]; + unsigned char ibSmNodeInfoNodeGUID[8]; + unsigned long ibSmNodeInfoBaseVersion; + unsigned long ibSmNodeInfoClassVersion; + long ibSmNodeInfoType; + unsigned long ibSmNodeInfoNumPorts; + unsigned char ibSmNodeInfoSystemImageGUID[8]; + unsigned long ibSmNodeInfoPartitionCap; + unsigned char ibSmNodeInfoDeviceID[2]; + unsigned char ibSmNodeInfoRevision[4]; + unsigned char ibSmNodeInfoVendorID[3]; + char ibSmNodeInfoDescription[256]; +}fm_sm_node_info_t; + + +typedef struct fm_sm_port_info_s{ + uint64_t select_mask; + char ibSmPortInfoSubnetPrefix[8]; + char ibSmPortInfoNodeGUID[8]; + unsigned long ibSmPortInfoLocalPortNum; + char ibSmPortInfoMKey[8]; + char ibSmPortInfoGIDPrefix[8]; + unsigned long ibSmPortInfoLID; + unsigned long ibSmPortInfoMasterSmLID; + char ibSmPortInfoCapMask[4]; + char ibSmPortInfoDiagCode[2]; + unsigned long ibSmPortInfoMKeyLeasePeriod; + unsigned long ibSmPortInfoLinkWidthEnabled; + unsigned long ibSmPortInfoLinkWidthSupported; + unsigned long ibSmPortInfoLinkWidthActive; + unsigned long ibSmPortInfoLinkSpeedSupported; + unsigned long ibSmPortInfoState; + unsigned long ibSmPortInfoPhyState; + unsigned long ibSmPortInfoLinkDownDefState; + unsigned long ibSmPortInfoMKeyProtBits; + unsigned long ibSmPortInfoLMC; + unsigned long ibSmPortInfoLinkSpeedActive; + unsigned long ibSmPortInfoLinkSpeedEnabled; + long ibSmPortInfoNeighborMTU; + unsigned long ibSmPortInfoMasterSmSL; + unsigned long ibSmPortInfoVLCap; + unsigned long ibSmPortInfoVLHighLimit; + unsigned long ibSmPortInfoVLArbHighCap; + unsigned long ibSmPortInfoVLArbLowCap; + long ibSmPortInfoMTUCap; + unsigned long ibSmPortInfoVLStallCount; + unsigned long ibSmPortInfoHOQLife; + unsigned long ibSmPortInfoOperVL; + long ibSmPortInfoInPartEnforce; + long ibSmPortInfoOutPartEnforce; + long ibSmPortInfoInFilterRawPktEnf; + long ibSmPortInfoOutFilterRawPktEnf; + unsigned long ibSmPortInfoMKeyViolation; + unsigned long ibSmPortInfoPKeyViolation; + unsigned long ibSmPortInfoQKeyViolation; + unsigned long ibSmPortInfoGUIDCap; + unsigned long ibSmPortInfoSubnetTimeout; + unsigned long ibSmPortInfoRespTime; + unsigned long ibSmPortInfoLocalPhyError; + unsigned long ibSmPortInfoOverrunError; + char ibSmPortInfoInitType; + char ibSmPortInfoInitTypeReply; +}fm_sm_port_info_t; + +typedef struct fm_sm_switch_info_s{ + uint64_t select_mask; + char ibSmSwitchInfoSubnetPrefix[8]; + char ibSmSwitchInfoNodeGUID[8]; + unsigned long ibSmSwitchInfoLinearFdbCap; + unsigned long ibSmSwitchInfoRandomFdbCap; + unsigned long ibSmSwitchInfoMcastFdbCap; + unsigned long ibSmSwitchInfoLinearFdbTop; + unsigned long ibSmSwitchInfoDefaultPort; + unsigned long ibSmSwitchInfoDefPriMcastPort; + unsigned long ibSmSwitchInfoDefNonPriMcastPort; + unsigned long ibSmSwitchInfoLifeTimeValue; + unsigned long ibSmSwitchInfoPortStateChange; + unsigned long ibSmSwitchInfoLIDsPerPort; + unsigned long ibSmSwitchInfoPartitionEnfCap; + long ibSmSwitchInfoInEnfCap; + long ibSmSwitchInfoOutEnfCap; + long ibSmSwitchInfoInFilterRawPktCap; + long ibSmSwitchInfoOutFilterRawPktCap; + long ibSmSwitchInfoEnhanced0; +}fm_sm_switch_info_t; + +typedef struct fm_sm_guid_info_s{ + uint64_t select_mask; + char ibSmGUIDInfoSubnetPrefix[8]; + char ibSmGUIDInfoNodeGUID[8]; + unsigned long ibSmGUIDInfoPortNum; + unsigned long ibSmGUIDInfoBlockNum; + char ibSmGUIDInfoBlock[255]; + +}fm_sm_guid_info_t; + +typedef struct fm_sm_link_info_s{ + uint64_t select_mask; + char ibSmLinkSubnetPrefix[8]; + char ibSmLinkFromNodeGUID[8]; + unsigned long ibSmLinkFromPortNum; + char ibSmLinkToNodeGUID[8]; + unsigned long ibSmLinkToPortNum; +}fm_sm_link_info_t; + +typedef struct fm_sm_mcast_group_info_s{ + uint64_t select_mask; + unsigned char ibSmMcastGroupSubnetPrefix[8]; + unsigned char ibSmMcastGroupMGID[16]; + unsigned char ibSmMcastGroupQKey[2]; + unsigned long ibSmMcastGroupMLID; + long ibSmMcastGroupMTU; + unsigned long ibSmMcastGroupTClass; + unsigned long ibSmMcastGroupPKey; + unsigned long ibSmMcastGroupRate; + unsigned long ibSmMcastGroupPacketLifeTime; + unsigned long ibSmMcastGroupSL; + unsigned char ibSmMcastGroupFlowLabel[3]; + unsigned long ibSmMcastGroupHopLimit; + unsigned long ibSmMcastGroupScope; +}fm_sm_mcast_group_info_t; + +typedef struct fm_sm_mcast_member_info_s{ + uint64_t select_mask; + char ibSmMcastMemberSubnetPrefix[8]; + char ibSmMcastMemberMGID[16]; + long ibSmMcastMemberVectorIndex; + char ibSmMcastMemberVector[255]; + long ibSmMcastMemberVectorSize; + long ibSmMcastMemberVectorElementSize; + unsigned long ibSmMcastMemberLastChange; + +}fm_sm_mcast_member_info_t; + +typedef struct fm_sm_service_info_s{ + uint64_t select_mask; + unsigned char ibSmServiceSubnetPrefix[8]; + unsigned char ibSmServiceID[8]; + unsigned char ibSmServiceGID[16]; + unsigned long ibSmServicePKey; + unsigned long ibSmServiceLease; + unsigned char ibSmServiceKey[16]; + char ibSmServiceName[256]; + unsigned char ibSmServiceData[128]; +}fm_sm_service_info_t; + + +fm_mgr_config_errno_t +fm_mgr_simple_query +( + IN p_fm_config_conx_hdlt hdl, + IN fm_mgr_action_t action, + IN fm_datatype_t data_type_id, + IN fm_mgr_type_t mgr, + IN int data_len, + OUT void *data, + OUT fm_msg_ret_code_t *ret_code +); + +// init +fm_mgr_config_errno_t +fm_mgr_config_init +( + OUT p_fm_config_conx_hdlt *p_hdl, + IN int instance, + OPTIONAL IN char *rem_address, + OPTIONAL IN char *community +); + + +// connect +fm_mgr_config_errno_t +fm_mgr_config_connect +( + IN p_fm_config_conx_hdlt p_hdl +); + + +fm_mgr_config_errno_t +fm_mgr_commong_cfg_query +( + IN p_fm_config_conx_hdlt hdl, + IN fm_mgr_type_t mgr, + IN fm_mgr_action_t action, + OUT fm_config_common_t *info, + OUT fm_msg_ret_code_t *ret_code +); + + +fm_mgr_config_errno_t +fm_mgr_bm_cfg_query +( + IN p_fm_config_conx_hdlt hdl, + IN fm_mgr_action_t action, + OUT bm_config_t *info, + OUT fm_msg_ret_code_t *ret_code +); + + +fm_mgr_config_errno_t +fm_mgr_fe_cfg_query +( + IN p_fm_config_conx_hdlt hdl, + IN fm_mgr_action_t action, + OUT fe_config_t *info, + OUT fm_msg_ret_code_t *ret_code +); + +fm_mgr_config_errno_t +fm_mgr_pm_cfg_query +( + IN p_fm_config_conx_hdlt hdl, + IN fm_mgr_action_t action, + OUT pm_config_t *info, + OUT fm_msg_ret_code_t *ret_code +); + + + +fm_mgr_config_errno_t +fm_mgr_sm_cfg_query +( + IN p_fm_config_conx_hdlt hdl, + IN fm_mgr_action_t action, + OUT sm_config_t *info, + OUT fm_msg_ret_code_t *ret_code +); + +fm_mgr_config_errno_t +fm_sm_status_query +( + IN p_fm_config_conx_hdlt hdl, + IN fm_mgr_action_t action, + OUT fm_sm_status_t *info, + OUT fm_msg_ret_code_t *ret_code +); + +fm_mgr_config_errno_t +fm_pm_status_query +( + IN p_fm_config_conx_hdlt hdl, + IN fm_mgr_action_t action, + OUT fm_pm_status_t *info, + OUT fm_msg_ret_code_t *ret_code +); + +fm_mgr_config_errno_t +fm_bm_status_query +( + IN p_fm_config_conx_hdlt hdl, + IN fm_mgr_action_t action, + OUT fm_bm_status_t *info, + OUT fm_msg_ret_code_t *ret_code +); + +fm_mgr_config_errno_t +fm_fe_status_query +( + IN p_fm_config_conx_hdlt hdl, + IN fm_mgr_action_t action, + OUT fm_fe_status_t *info, + OUT fm_msg_ret_code_t *ret_code +); + +const char* +fm_mgr_get_error_str +( + IN fm_mgr_config_errno_t err +); + +const char* +fm_mgr_get_resp_error_str +( + IN fm_msg_ret_code_t err +); + + + + + + + + + + +#endif diff --git a/Esm/ib/include/hsm_config_srvr_data.h b/Esm/ib/include/hsm_config_srvr_data.h new file mode 100644 index 0000000..6d6c581 --- /dev/null +++ b/Esm/ib/include/hsm_config_srvr_data.h @@ -0,0 +1,87 @@ +/* BEGIN_ICS_COPYRIGHT2 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + * ** END_ICS_COPYRIGHT2 ****************************************/ + +#ifndef HSM_CONFIG_SRVR_DATA +#define HSM_CONFIG_SRVR_DATA + +#include "hsm_config_srvr_api.h" + +#define HSM_FM_SCK_PREFIX "/var/lib/opa-fm/" +#define HSM_FM_SCK_SM "sm_" +#define HSM_FM_SCK_PM "pm_" +#define HSM_FM_SCK_FE "fe_" + +typedef struct _fm_config_conx_hdl{ + unsigned instance; + unsigned conx_mask; // Mask to store which services are currently connected. + p_hsm_com_client_hdl_t sm_hdl; + p_hsm_com_client_hdl_t pm_hdl; + p_hsm_com_client_hdl_t bm_hdl; + p_hsm_com_client_hdl_t fe_hdl; + uint32_t index_len; + fm_error_map_t error_map; +}fm_config_conx_hdl; + +typedef struct fm_config_datagram_header_s{ + fm_msg_ret_code_t ret_code; + unsigned long action; + unsigned long data_id; + unsigned long data_len; +}fm_config_datagram_header_t; + +typedef struct fm_config_status_header_s{ + fm_msg_ret_code_t ret_code; + uint32_t run_status; + uint32_t uptime; + uint32_t master; +}fm_config_status_header_t; + +typedef struct fm_config_datagram_s{ + fm_config_datagram_header_t header; + char data[1]; // Storage for the first data byte. +}fm_config_datagram_t; + +#define FM_CONFIG_INTERMEDIATE_SIZE 10000 +#define FM_CONFIG_INTERMEDIATE_BUFF 10032 + +typedef struct fm_config_interation_data_s { + int index; + int offset; + int more; + int start; + int done; + int largeLength; + char *largeBuffer; + int intermediateLength; + char intermediateBuffer[FM_CONFIG_INTERMEDIATE_BUFF]; +}fm_config_interation_data_t; + + + +#endif /* HSM_CONFIG_SRVR_DATA */ diff --git a/Esm/ib/include/ib_const.h b/Esm/ib/include/ib_const.h new file mode 100644 index 0000000..cf72393 --- /dev/null +++ b/Esm/ib/include/ib_const.h @@ -0,0 +1,156 @@ +/* BEGIN_ICS_COPYRIGHT2 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + * ** END_ICS_COPYRIGHT2 ****************************************/ + +#ifndef _IB_CONST_H_ +#define _IB_CONST_H_ + +// ******************************************************************** // +// // +// FILE NAME // +// ib_const.h // +// // +// DESCRIPTION // +// Constant values for iba // +// // +// // +// FUNCTIONS // +// None // +// // +// DEPENDENCIES // +// // +// // +// // +// HISTORY // +// // +// NAME DATE REMARKS // +// pwalker 12/21/00 Initial creation of file. // +// jsy 02/09/01 Added default GID prefix. // +// // +// ******************************************************************** // + +#define OUI_TRUESCALE_0 (0x00) /* 3-byte InfiniCon (now Intel) OUI */ +#define OUI_TRUESCALE_1 (0x06) +#define OUI_TRUESCALE_2 (0x6a) + +#define GSI_WELLKNOWN_QKEY (0x80010000) /* QKEY for GSI */ +#define UNICAST_LID_MIN (0x0001) /* Lowest valid Unicast Lid*/ +#define UNICAST_LID_MAX (0xBFFF) /* max valid Unicast Lid*/ +#define MULTICAST_LID_MAX (0xFFFE) /* MAX MC lid value */ +#define MULTICAST_LID_MIN (0xC000) /* Min MC lid value */ +#define PERMISSIVE_LID (0xFFFF) /* permissive lid for SMP */ +#define RESERVED_LID (0) /* Reserved lid in IB space*/ + +#define MAX_LMC_BITS (8) /* Max number of LMC bits */ +#define DEFAULT_GID_PREFIX 0xFE80000000000000ull /* Default GID */ + +#define LINK_LOCAL_ADDR_MASK (0xFE80) /* mask for link local addr */ +#define SITE_LOCAL_ADDR_MASK (0xFEC0) /* mask for site local */ +#define MUTLICAST_ADDR_MASK (0xFF00) /* multicast address */ +#define MULTICAST_GID_FLAGSCOPE_MASK (0x00FF) /* mask for scope bits */ + +#define IBA_MAX_HDR (128) /* Maximum pkt hdr size */ +#define IBA_MAX_PATHSIZE (63) /* mximum DR hops */ + +#define IBA_VENDOR_RANGE1_START (0x09) /* range for standard vendor classes */ +#define IBA_VENDOR_RANGE1_END (0x0f) +#define IBA_VENDOR_RANGE2_START (0x30) /* range for RMPP/OUI vendor classes */ +#define IBA_VENDOR_RANGE2_END (0x4f) + +#define EUI64_COMPANYID_LEN (3) /* length in bytes */ +#define EUI64_EXTENSION_LEN (5) /* length in bytes */ +#define EUI64_LEN (8) /* length in bytes */ + +#define SMP_VIRTUAL_LANE (0xf) /* use by SMP MADs only */ +#define MAX_VIRTUAL_LANES (16) /* Max number of VLs 0 .. 15 */ +#define MAX_SLS (16) /* Max number of SLs 0 .. 15 */ + + +#define MAX_LFT_SIZE (48*1024) /* for all UNICAST LIDs */ +#define MAX_RFT_SIZE (48*1024) /* worst case for RFT */ +#define MAX_MCFT_SIZE (16*1024) /* for all Multicast LIDS */ + +// +// SM Mad retries and default Receive wait interval +// +#define LOG_LEVEL_MIN 0 +#define LOG_LEVEL_MAX 5 +#define MAD_RETRIES 3 +#define MAD_RCV_WAIT_MSEC 250 +#define MAD_MIN_RCV_WAIT_MSEC 35 /* PR 110945 - when using stepped retries, default minimum timeout + * with which retries are started. Subsequent retries will be + * multiples of this timeout value. + */ + +#define DYNAMIC_PACKET_LIFETIME_ARRAY_SIZE 10 + +#define DYNAMIC_PLT_MIN 0 +#define DYNAMIC_PLT_MAX 0x3F + +#define SM_MAX_PRIORITY 15 /* 4-bit field in SMInfo - table 45 vol 1.1 */ + +#define SM_NO_SWEEP 0 /* do not allow a sweep */ +#define SM_MIN_SWEEPRATE 3 /* 3 Seconds */ +#define SM_MAX_SWEEPRATE 86400 /* 24 Hours */ + +#define BM_NO_SWEEP 0 /* do not allow a sweep */ +#define BM_MIN_SWEEPRATE 30 /* 30 Seconds */ +#define BM_MAX_SWEEPRATE 86400 /* 24 Hours */ + +#define PM_MIN_SWEEPRATE 1 /* 1 Second */ +#define PM_MAX_SWEEPRATE 43200 /* 12 Hours */ + +/* the multi path defs are from sm_l.h */ +// FIXME +#define SM_NO_MULTI_PATH 0 +#define SM_SOURCE_ROUTE_MULTIPATH 1 + +#define SM_MIN_SWITCH_LIFETIME 0 +#define SM_MAX_SWITCH_LIFETIME 31 + +#define SM_MIN_HOQ_LIFE 0 +#define SM_MAX_HOQ_LIFE 31 + +#define SM_MIN_VL_STALL 1 +#define SM_MAX_VL_STALL 7 + +#define MAX_PKEYS 32 + +#define PKEY_TABLE_LIST_COUNT 32 + +/* number of endports suppported by fabric related defines */ +#ifdef __VXWORKS__ +#define MIN_SUPPORTED_ENDPORTS 40 /* max for 9020 VIO card */ +#define MAX_SUPPORTED_ENDPORTS 512 +#define MAX_SUPPORTED_ENDPORTS_9020 MIN_SUPPORTED_ENDPORTS +#else +#define MIN_SUPPORTED_ENDPORTS 40 +#endif + +#endif // _IB_CONST_H_ + diff --git a/Esm/ib/include/ib_macros.h b/Esm/ib/include/ib_macros.h new file mode 100644 index 0000000..76b9996 --- /dev/null +++ b/Esm/ib/include/ib_macros.h @@ -0,0 +1,139 @@ +/* BEGIN_ICS_COPYRIGHT2 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + * ** END_ICS_COPYRIGHT2 ****************************************/ + +//======================================================================= +// / +// FILE NAME / +// ib_macros.h / +// / +// DESCRIPTION / +// Definition of some convenience macros for MAD processing. / +// / +// DATA STRUCTURES / +// None / +// / +// FUNCTIONS / +// None / +// / +// DEPENDENCIES / +// ib_mad.h / +// / +// / +//======================================================================= + +#ifndef _IB_MACROS_H_ +#define _IB_MACROS_H_ + +#include "ib_mad.h" + +// -------------------------------------------------------------------- // +// // +// These macros are for the use of Infiniband managers. They are // +// convenience macros only. // +// // +// -------------------------------------------------------------------- // + +// +// Setup the MAI. +// +#define Mai_Init(MAIP) { \ + (void)memset((void *)MAIP, 0, sizeof(*MAIP)); \ + \ + (MAIP)->type = MAI_TYPE_EXTERNAL; \ + (MAIP)->active = MAI_ACT_TYPE; \ +} + +// +// Setup the addrInfo. +// +#define AddrInfo_Init(MAIP,SLID,DLID,SL,PKEY,SRCQP,DSTQP,QKEY) { \ + (MAIP)->active |= MAI_ACT_ADDRINFO; \ + (MAIP)->addrInfo.slid = SLID; \ + (MAIP)->addrInfo.dlid = DLID; \ + (MAIP)->addrInfo.sl = SL; \ + (MAIP)->addrInfo.pkey = PKEY; \ + (MAIP)->addrInfo.srcqp = SRCQP; \ + (MAIP)->addrInfo.destqp = DSTQP; \ + (MAIP)->addrInfo.qkey = QKEY; \ +} + +// +// Setup the LR_Mad +// +#define LRMad_Init(MAIP,MCLASS,METHOD,TID,AID,AMOD,MKEY) { \ + LRSmp_t *lrp; \ + \ + (void)memset((void *)&(MAIP)->base, 0, sizeof((MAIP)->base)); \ + \ + (MAIP)->active |= (MAI_ACT_BASE | MAI_ACT_DATA); \ + (MAIP)->base.bversion = MAD_BVERSION; \ + (MAIP)->base.mclass = MCLASS; \ + (MAIP)->base.cversion = MCLASS == MAD_CV_SUBN_ADM ? SA_MAD_CVERSION : MAD_CVERSION; \ + (MAIP)->base.method = METHOD; \ + (MAIP)->base.status = 0; \ + (MAIP)->base.hopPointer = 0; \ + (MAIP)->base.hopCount = 0; \ + (MAIP)->base.tid = TID; \ + (MAIP)->base.aid = AID; \ + (MAIP)->base.rsvd3 = 0; \ + (MAIP)->base.amod = AMOD; \ + \ + lrp = (LRSmp_t *)(MAIP)->data; \ + (void)memset((void *)lrp, 0, sizeof(*lrp)); \ + \ + lrp->mkey = MKEY; \ +} + +// +// Setup the LR_Mad data. +// +#define LRData_Init(MAIP,DATA,BYTES) { \ + LRSmp_t *lrp; \ + \ + (MAIP)->active |= MAI_ACT_DATA; \ + \ + lrp = (LRSmp_t *)(MAIP)->data; \ + (void)memcpy((void *)lrp->smpdata, (void *)(DATA), BYTES); \ +} + +// +// Setup the Filter. +// +#define Filter_Init(FILTERP,ACTIVE,TYPE) { \ + (void)memset((void *)FILTERP, 0, sizeof(*FILTERP)); \ + \ + (FILTERP)->active = ACTIVE; \ + (FILTERP)->type = TYPE; \ + (FILTERP)->dev = MAI_FILTER_ANY; \ + (FILTERP)->port = MAI_FILTER_ANY; \ + (FILTERP)->qp = MAI_FILTER_ANY; \ +} + +#endif // _IB_MACROS_H_ + diff --git a/Esm/ib/include/ib_mad.h b/Esm/ib/include/ib_mad.h new file mode 100644 index 0000000..e7fdc21 --- /dev/null +++ b/Esm/ib/include/ib_mad.h @@ -0,0 +1,226 @@ +/* BEGIN_ICS_COPYRIGHT2 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + * ** END_ICS_COPYRIGHT2 ****************************************/ + +// -------------------------------------------------------------------- // +// // +// FILE NAME // +// ib_mad.h // +// // +// DESCRIPTION // +// General transport definitions // +// // +// DATA STRUCTURES // +// Mad_t Common MAD header // +// DRSmp_t Directed Route MAD data // +// LRSmp_t LID Route MAD data // +// // +// FUNCTIONS // +// None // +// // +// DEPENDENCIES // +// ib_types.h // +// // +// // +// -------------------------------------------------------------------- // + +// -------------------------------------------------------------------- // +// // +// WARNING: These structures do NOT represent the IBTA defined // +// structures as they appear in the Volume1 spec. // +// // +// -------------------------------------------------------------------- // + +#ifndef _IB_MAD_H_ +#define _IB_MAD_H_ + +#include "ib_types.h" +#include "ib_const.h" + +// IBTA: Volume 1, Section 13.4.2 + +// +// Base MAD format +// +// NOTE: +// 1. Changes here require changes to mai/maic.c +// +typedef struct { + uint8_t bversion; // base version - 1 + uint8_t mclass; // management class + uint8_t cversion; // class version - 1 + uint8_t method; // method and/or response + uint16_t status; // status - upper bit is 'D' for DR + uint8_t hopPointer; // DR only + uint8_t hopCount; // DR only + uint64_t tid; // transaction ID + uint16_t aid; // attribute ID + uint16_t rsvd3; // reserved - 0 + uint32_t amod; // attribute modifier +} Mad_t; + +// IBTA: Volume 1, Section 13.4.3 + +#define MAD_BVERSION 1 +#define MAD_CVERSION 1 +#define SA_MAD_CVERSION 2 /* IB 1.1 compliance */ +#define CC_MAD_CVERSION 2 +#define PA_MAD_CVERSION 1 +#define RMPP_MAD_CVERSION 2 +#define RMPP_MAD_BVERSION 1 +#define MAD_STATUS_MASK 0x7fff + +// IBTA: Volume 1, Section 13.4.4 + +// +// Mad Class Values (MAD_CV) +// +#define MAD_CV_SUBN_LR 0x01 +#define MAD_CV_SUBN_DR 0x81 +#define MAD_CV_SUBN_ADM 0x03 +#define MAD_CV_PERF 0x04 +#define MAD_CV_BM 0x05 +#define MAD_CV_DEV_MGT 0x06 +#define MAD_CV_COMM_MGT 0x07 +#define MAD_CV_SNMP 0x08 +#define MAD_CV_VENDOR_0 0x09 +#define MAD_CV_VENDOR_CM 0x09 // reserved by CM +//#define MAD_CV_VENDOR_FE 0x0a // reserved by FabricExec(tm) +//#define MAD_CV_INTEL_NS 0x0b // JSY - temp for Intel testing +//#define MAD_CV_VENDOR_DBSYNC 0x0b // SM db sync +#define MAD_CV_VENDOR_LOG 0x0c // reserved by CS for Logging +//#define MAD_CV_VFI_PM 0x0d // PM VFI mclass value +//#define MAD_CV_VFI_BM 0x0e // BM VFI mclass value +#define MAD_CV_VENDOR_1 0x0f // use by PMA to get 64bit ctrs +#define MAD_CV_APP_0 0x10 +#define MAD_CV_APP_1 0x1f +#define MAD_CV_CC 0x21 // CCA +#define MAD_CV_VENDOR_FE 0x30 // reserved by FabricExec(tm) +#define MAD_CV_VENDOR_DBSYNC 0x31 // SM db sync +#define MAD_CV_VFI_PM 0x32 // PM VFI mclass value +#define MAD_CV_VFI_BM 0x33 // BM VFI mclass value + + +// VENDOR MAD RANGE +#define MAD_VENDOR_CLASS_MIN 0x30 +#define MAD_VENDOR_CLASS_MAX 0x4f + +// IBTA: Volume 1, Section 13.4.5 + +// +// Mad Class Methods (MAD_CM) +// +#define MAD_CM_GET 0x01 +#define MAD_CM_SET 0x02 +#define MAD_CM_GET_RESP 0x81 +#define MAD_CM_SEND 0x03 +#define MAD_CM_TRAP 0x05 +#define MAD_CM_REPORT 0x06 +#define MAD_CM_REPORT_RESP 0x86 +#define MAD_CM_TRAP_REPRESS 0x07 +#define MAD_CM_VIEO_REQ 0x98 // VIEO specific +#define MAD_CM_VIEO_REP 0x99 // VIEO specific + +#define MAD_CM_REPLY 0x80 // Reply bit for methods + +// IBTA: Volume 1, Section 13.4.7 + +// +// Common MAD status bits +// + +#define MAD_STATUS_OK 0x0000 +#define MAD_STATUS_BUSY 0x0001 +#define MAD_STATUS_REDIRECT 0x0002 +#define MAD_STATUS_BAD_CLASS 0x0004 +#define MAD_STATUS_BAD_METHOD 0x0008 +#define MAD_STATUS_BAD_ATTR 0x000c +#define MAD_STATUS_RSVD1 0x0010 +#define MAD_STATUS_RSVD2 0x0014 +#define MAD_STATUS_RSVD3 0x0018 +#define MAD_STATUS_BAD_FIELD 0x001c +#define MAD_STATUS_D_BIT 0x8000 // set by SM if response to directed route SMInfo + +// IBTA: Volume 1, Section 13.4.8.3 + +#define TRAP_ALL 0xffff +#define NODE_TYPE_ALL 0xffffff + +// +// InformInfo Producer Type +// +#define INFORMINFO_PRODUCERTYPE_CA 1 +#define INFORMINFO_PRODUCERTYPE_SWITCH 2 +#define INFORMINFO_PRODUCERTYPE_ROUTER 3 +#define INFORMINFO_PRODUCERTYPE_SM 4 + +// IBTA: Volume 1, Section 14.2.1.1 + +#define LRSMP_RSVD3_COUNT 32 +#define LRSMP_SMPDATA_COUNT 64 +#define LRSMP_RSVD4_COUNT 128 + +typedef struct { + uint64_t mkey; // management key + uint8_t rsvd3[LRSMP_RSVD3_COUNT]; // reserved - 0 + uint8_t smpdata[LRSMP_SMPDATA_COUNT]; // SMP data + uint8_t rsvd4[LRSMP_RSVD4_COUNT]; // reserved - 0 +} LRSmp_t; + +// IBTA: Volume 1, Section 14.2.1.2 + +#define DRSMP_RSVD2_COUNT 28 +#define DRSMP_SMPDATA_COUNT 64 +#define DRSMP_IPATH_COUNT 64 +#define DRSMP_RPATH_COUNT 64 + +#define MAD_DR_INITIAL 0x0000 +#define MAD_DR_RETURN 0x8000 + +// IBTA: Volume 1, Section 13.4.8.2 + +// +// Generic Notice structure. +// + +#define NOTICE_TYPE_FATAL 0 +#define NOTICE_TYPE_URGENT 1 +#define NOTICE_TYPE_SECURITY 2 +#define NOTICE_TYPE_SM 3 +#define NOTICE_TYPE_INFO 4 +#define NOTICE_TYPE_EMPTY 0x7f + +#define NOTICE_PRODUCERTYPE_CA 1 +#define NOTICE_PRODUCERTYPE_SWITCH 2 +#define NOTICE_PRODUCERTYPE_ROUTER 3 +#define NOTICE_PRODUCERTYPE_CLASSMANAGER 4 + +#include "ib_sm.h" + +#endif // _IB_MAD_H_ + diff --git a/Esm/ib/include/ib_sa.h b/Esm/ib/include/ib_sa.h new file mode 100644 index 0000000..e79f925 --- /dev/null +++ b/Esm/ib/include/ib_sa.h @@ -0,0 +1,247 @@ +/* BEGIN_ICS_COPYRIGHT2 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + * ** END_ICS_COPYRIGHT2 ****************************************/ + +// -------------------------------------------------------------------- // +// // +// WARNING: These structures do NOT represent the IBTA defined // +// structures as they appear in the Volume1 spec. // +// // +// -------------------------------------------------------------------- // + +#ifndef _IB_SA_H_ +#define _IB_SA_H_ + +#include "ib_types.h" +#include "ib_mad.h" +#include "cs_hashtable.h" +#include "iba/stl_sm_types.h" +#include "iba/stl_sa_priv.h" + +#if defined(__KERNEL__) && ! defined(__VXWORKS__) +#include "linux/iba/public/ipackon.h" +#else +#include "iba/public/ipackon.h" +#endif + +// IBTA: Volume 1, Section 15.2.1 + +// +// Subnet Administration(SA) Mad format +// + +#define IB_SAMAD_DATA_COUNT 200 +#define IB_SA_HEADER_SIZE 20 // SA header fields after RMPP header and before data +#define IB_SA_FULL_HEADER_SIZE 32 // SA header including RMPP header + +#define STL_SAMAD_BLOCK_SIZE 2048 +#define STL_SAMAD_DATA_COUNT (STL_SAMAD_BLOCK_SIZE - (IB_SA_FULL_HEADER_SIZE + 8)) // Original SA header is one byte short + +#define SAMAD_DATA_COUNT IB_SAMAD_DATA_COUNT +#define SA_HEADER_SIZE IB_SA_HEADER_SIZE // SA header fields after RMPP header and before data +#define SA_FULL_HEADER_SIZE IB_SA_FULL_HEADER_SIZE // SA header including RMPP header + +// SA MAD header only +typedef struct { + uint8_t rmppVersion; + uint8_t rmppType; + union { + struct { + #if CPU_BE + uint8_t rmppRespTime : 5; // 5 bit field + uint8_t rmppFlags : 3; // 3 bit field + #else + uint8_t rmppFlags : 3; // 3 bit field + uint8_t rmppRespTime : 5; // 5 bit field + #endif + } tf; + uint8_t timeFlag; // entire 8 bits + } u; + uint8_t rmppStatus; + uint32_t segNum; + uint32_t length; + uint64_t smKey; // SM key + uint16_t offset; // num 8-byte words from begin of attrib to begin of next attrib + uint16_t rservd; // reserved + uint64_t mask; // attribute components for queries +} PACK_SUFFIX SAMadh_t; + +// (old = 192) Maximum data in a single SA Mad +#define IB_SA_DATA_LEN 200 + +#define SA_AMOD_TEMPLATE 0xffffffff + +#define SA_EM_ADD 0x0 // add record modifier +#define SA_EM_DELETE 0x1 // delete record modifier +#define SA_EM_EDIT 0x2 // edit record modifier + +// IBTA: Volume 1, Section 15.2.3 + +#define MAD_STATUS_SA_NO_ERROR 0x0000 // no error +#define MAD_STATUS_SA_NO_RESOURCES 0x0100 // No resources +#define MAD_STATUS_SA_REQ_INVALID 0x0200 // Request invalid +#define MAD_STATUS_SA_NO_RECORDS 0x0300 // No records found +#define MAD_STATUS_SA_TOO_MANY_RECS 0x0400 // Too many records +#define MAD_STATUS_SA_REQ_INVALID_GID 0x0500 // invalid GID +#define MAD_STATUS_SA_REQ_INSUFFICIENT_COMPONENTS 0x0600 // Insufficient Components +#define MAD_STATUS_SA_REQ_DENIED 0x0700 // request is denied - new in IBTA 1.2.1 +#define MAD_STATUS_SA_REQ_PRIORITY 0x0800 // suggested QoS is unobtainable - IBTA 1.2.1 Annex A13 + +// IBTA: Volume 1, Section 13.6.2.1 - RMPP +#define RMPP_VERSION 1 + +#define RMPP_TYPE_NOT 0 +#define RMPP_TYPE_DATA 1 +#define RMPP_TYPE_ACK 2 +#define RMPP_TYPE_STOP 3 +#define RMPP_TYPE_ABORT 4 + +#define RMPP_RESPTIME_NONE 0x1F + +#define RMPP_FLAGS_ACTIVE 0x01 +#define RMPP_FLAGS_FIRST 0x02 +#define RMPP_FLAGS_LAST 0x04 + +// IBTA: Volume 1, Section 13.6.2.1 - RMPP Status +#define RMPP_STATUS_NO_ERROR 0 +#define RMPP_STATUS_STOP_NORESOURCES 1 +#define RMPP_STATUS_ABORT_TIMETOOLONG 118 +#define RMPP_STATUS_ABORT_INCONSISTENT_LAST_PAYLOADLENGTH 119 +#define RMPP_STATUS_ABORT_INCONSISTENT_FIRST_SEGNUM 120 +#define RMPP_STATUS_ABORT_BADTYPE 121 +#define RMPP_STATUS_ABORT_NEWWINDOWLAST_TOOSMALL 122 +#define RMPP_STATUS_ABORT_SEGNUM_TOOBIG 123 +#define RMPP_STATUS_ABORT_ILLEGAL_STATUS 124 +#define RMPP_STATUS_ABORT_UNSUPPORTED_VERSION 125 +#define RMPP_STATUS_ABORT_TOO_MANY_RETRIES 126 +#define RMPP_STATUS_ABORT_UNSPECIFIED 127 + +// IBTA: Volume 1, Section 15.2.2 + +// +// SA class methods +// +#define SA_CM_GET 0x01 // Get an attribute from a node +#define SA_CM_GET_RESP 0x81 // Get/Set response +#define SA_CM_SET 0x02 // Set an attribute from a node +#define SA_CM_REPORT 0x06 // Forward a subscribed event +#define SA_CM_REPORT_RESP 0x86 // Report response +#define SA_CM_GETTABLE 0x12 // SM table request +#define SA_CM_GETTABLE_RESP 0x92 // Gettable response +#define SA_CM_GETTRACETABLE 0x13 // Request path trace table - returns GETTABLE_RESP +#define SA_CM_GETMULTI 0x14 // Multi-packet request +#define SA_CM_GETMULTI_RESP 0x94 // Multi-packet response +#define SA_CM_DELETE 0x15 // Request to delete an attribute +#define SA_CM_DELETE_RESP 0x95 // Response to delete an attribute + +// IBTA: Volume 1, Section 15.2.5.1 + +// +// SA Attributes +// +#define SA_CLASSPORTINFO 0x0001 // Class information +#define SA_NOTICE 0x0002 // Notice information +#define SA_INFORMINFO 0x0003 // Subscription information +#define SA_NODE_RECORD 0x0011 // NodeInfo record +#define SA_PORTINFO_RECORD 0x0012 // PortInfo record +#define SA_SWITCH_RECORD 0x0014 // SwitchInfo record +#define SA_LFT_RECORD 0x0015 // LFT record +#define SA_RFT_RECORD 0x0016 // RFT record +#define SA_MFT_RECORD 0x0017 // MFT record +#define SA_SMINFO_RECORD 0x0018 // SmInfo record +#define SA_INFORM_RECORD 0x00f3 // InforInfo record +//was SA_NOTICE_RECORD 0x00f4 // Notice record +#define SA_LINK_RECORD 0x0020 // Link record +//was SA_GUIDINFO_RECORD 0x0030 // GUIDs assigned to a port +#define SA_SERVICE_RECORD 0x0031 // Service Ad record +#define SA_PARTITION_RECORD 0x0033 // Partition record +//was SA_RANGE_RECORD 0x0034 // Range record +#define SA_PATH_RECORD 0x0035 // Subnet path information +#define SA_VLARBITRATION_RECORD 0x0036 // VL arbitration record +//was SA_MCGROUP_RECORD 0x0037 // MC Group record +#define SA_MCMEMBER_RECORD 0x0038 // MC Member record +#define SA_TRACE_RECORD 0x0039 // Trace Record +#define SA_MULTIPATH_RECORD 0x003A // Request for multi paths +#define SA_SARESPONSE 0x8001 // Container for query responses +#define SA_VFABRIC_RECORD 0xFF02 // "Vendor unique" vfabric record + +#define IB_LINK_LOCAL_SCOPE 0x2 +#define IB_SITE_LOCAL_SCOPE 0x5 +#define IB_ORG_LOCAL_SCOPE 0x8 +#define IB_GLOBAL_SCOPE 0xE + +/* + * subscriber table (informInfo) + */ +typedef struct { + CS_HashTablep subsMap; /* pointer to hashmap of subscriptions */ + Lock_t subsLock; +} SubscriberTable_t; + +/* + * event subscription entry key structure + */ +typedef struct { + Gid_t subscriberGid; + STL_LID lid; // destination lid + uint16_t trapnum; // trap number + uint32_t qpn; // queue pair number - 24 bits + uint8_t producer; // producer of traps/notices - using 3 bits + uint8_t rtv; // time to respond to requests - 5 bits + uint16_t pkey; // original PKey + uint32_t qkey; // queue pair key (32) + STL_LID startLid; // calculated start Lid + STL_LID endLid; // calculated end Lid + uint8_t ibMode; // true if subscriber needs IB notices. +} SubscriberKey_t; +typedef SubscriberKey_t * SubscriberKeyp; + +/* + * service record table (ServiceRecord) + */ +typedef struct { + CS_HashTablep serviceRecMap; /* pointer to hashmap of service records */ + Lock_t serviceRecLock; +} ServiceRecTable_t; + +/* + * event subscription entry key structure + */ +typedef struct { + uint64_t serviceId; // Id of service on port specified by serviceGid + IB_GID serviceGid; + uint16_t servicep_key; // p_key used in contacting service +} ServiceRecKey_t; +typedef ServiceRecKey_t * ServiceRecKeyp; + +// +// Calculate 8-byte multiple padding for multi record SA responses +// +#define Calculate_Padding(RECSIZE) ( (((RECSIZE)%8) == 0 ) ? 0 : (8 - ((RECSIZE)%8)) ) + +#endif // _IB_SA_H_ diff --git a/Esm/ib/include/ib_sm.h b/Esm/ib/include/ib_sm.h new file mode 100644 index 0000000..f86491c --- /dev/null +++ b/Esm/ib/include/ib_sm.h @@ -0,0 +1,339 @@ +/* BEGIN_ICS_COPYRIGHT2 **************************************** + +Copyright (c) 2015-2018, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + * ** END_ICS_COPYRIGHT2 ****************************************/ + +//----------------------------------------------------------------------/ +// / +// FILE NAME / +// ib_mad.h / +// / +// DESCRIPTION / +// general transport definitions / +// / +// DATA STRUCTURES / +// Trap64_t Trap information (port up) / +// Trap65_t Trap information (link down) / +// Trap66_t Trap information (multicast group created) / +// Trap67_t Trap information (multicast group deleted) / +// Trap128_t Trap information (link state change) / +// Trap129_t Trap information (link integrity threshold) / +// Trap130_t Trap information (buffer overrun threshold) / +// Trap131_t Trap information (flow control update timer) / +// Trap144_t Trap information (change to cap mask/other) / +// Trap256_t Trap information (bad M_Key) / +// Trap257_t Trap information (bad P_Key) / +// Trap258_t Trap information (bad Q_Key) / +// SMTrap259_t Trap information (bad P_Key) / +// NodeDesc_t Node description / +// GuidInfo_t IEEE address information / +// PKeyBlock_t Partition Key / +// / +// FUNCTIONS / +// None / +// / +// DEPENDENCIES / +// ib_types.h / +// / +// / +// HISTORY / +// / +// NAME DATE REMARKS / +// / +//----------------------------------------------------------------------/ + +//----------------------------------------------------------------------// +// // +// WARNING: These structures do NOT represent the IBTA defined // +// structures as they appear in the Volume1 spec. // +// // +//----------------------------------------------------------------------// + +#ifndef _IB_SM_H_ +#define _IB_SM_H_ + +#include "ib_types.h" + +// IBTA: Volume 1, Section 14.2.5 + +// +// Subnet Management Attributes (MAD_SMA) +// +#define MAD_SMA_NOTICE 0x0002 +#define MAD_SMA_NODEDESC 0x0010 +#define MAD_SMA_NODEINFO 0x0011 +#define MAD_SMA_SWITCHINFO 0x0012 +#define MAD_SMA_GUIDINFO 0x0014 +#define MAD_SMA_PORTINFO 0x0015 +#define MAD_SMA_PART_TABLE 0x0016 +#define MAD_SMA_VL_ARBITRATION 0x0018 +#define MAD_SMA_LFT 0x0019 +#define MAD_SMA_RFT 0x001a +#define MAD_SMA_MFT 0x001b +#define MAD_SMA_SMINFO 0x0020 +#define MAD_SMA_VENDOR_DIAG 0x0030 +#define MAD_SMA_LEDINFO 0x0031 + +// IBTA: Volume 1, Section 14.2.5.1 + +// +// Subnet Management Traps (MAD_SMT) +// +#define MAD_SMT_PORT_UP 64 +#define MAD_SMT_PORT_DOWN 65 +#define MAD_SMT_MCAST_GRP_CREATED 66 +#define MAD_SMT_MCAST_GRP_DELETED 67 +#define MAD_SMT_UNPATH 68 +#define MAD_SMT_REPATH 69 +#define MAD_SMT_PORT_CHANGE 128 +#define MAD_SMT_LINK_INTEGRITY 129 +#define MAD_SMT_BUF_OVERRUN 130 +#define MAD_SMT_FLOW_CONTROL 131 +#define MAD_SMT_CAPABILITYMASK_CHANGE 144 +#define MAD_SMT_SYSTEMIMAGEGUID_CHANGE 145 +#define MAD_SMT_BAD_MKEY 256 +#define MAD_SMT_BAD_PKEY 257 +#define MAD_SMT_BAD_QKEY 258 +/* optional bad pkey on switch external port */ +#define MAD_SMT_BAD_PKEY_ONPORT 259 + +// IBTA: Volume 1, Section 14.2.5.2 + +#define ND_LEN 64 + +// IBTA: Volume 1, Section 14.2.5.3 + +#define NI_LPN_MASK 0xff000000 +#define NI_VID_MASK 0x00ffffff + +#define NI_TYPE_CA 0x01 +#define NI_TYPE_SWITCH 0x02 +#define NI_TYPE_ROUTER 0x03 + +#define NI_TYPE_MASK 0x03 + + +// IBTA: Volume 1, Section 14.2.5.5 + +#define GUID_INFO_GUID_COUNT 8 + +typedef struct { + uint64_t guid[GUID_INFO_GUID_COUNT]; // list of GUID block elements +} GuidInfo_t; + + +// IBTA: Table 126 Page 665 Vol1 1.0.a (June 19 2001) + +// +// CapabilityMask. +// +// Note for STL capability mask: +// STL provides a bitfield definition for its capability mask. (see stl_sm_types.h) +// Many capability bits that were optional in IB are now mandatory in STL. +// However, as per STL1G1 spec, STL returns these "mandatory" capability +// bits as 0. Be careful when checking STL capabilities and using +// bitmask manipulations below instead of the new STL bitfields. +// STL responses for the IB capability bits are annotated below. + +#define PI_CM_RESERVED 0xff00e011 // These are all reserved bits. +#define PI_CM_IS_SM 0x00000002 /* STL: 0/1 */ +//#define PI_CM_IS_NOTICE_SUPPORTED 0x00000004 /* STL: 0 */ +//#define PI_CM_IS_TRAP_SUPPORTED 0x00000008 /* STL: 0 */ +//#define PI_CM_IS_OPTIONAL_IPD_SUPPORTED 0x00000010 /* STL: 0 */ +#define PI_CM_IS_AUTOMATIC_MIGRATION_SUPPORTED 0x00000020 /* STL: 0/1 */ +//#define PI_CM_IS_SL_MAPPING_SUPPORTED 0x00000040 /* STL: 0 */ +//#define PI_CM_IS_MKEY_NVRAM 0x00000080 /* STL: 0 */ +//#define PI_CM_IS_PKEY_NVRAM 0x00000100 /* STL: 0 */ +//#define PI_CM_IS_LEDINFO_SUPPORTED 0x00000200 /* STL: 0 */ +//#define PI_CM_IS_SM_DISABLED 0x00000400 /* STL: 0 */ +//#define PI_CM_IS_SYS_IMAGE_SUPPORTED 0x00000800 /* STL: 0 */ +//#define PI_CM_IS_PKEY_SWITCH_EXTERNAL_TRAP_SUPPORTED 0x00001000 /* STL: 0 */ +//#define PI_CM_IS_EXT_LINK_SPEED_SUPPORTED 0x00004000 /* STL: 0 */ +#define PI_CM_IS_COM_MGT_SUPPORTED 0x00010000 /* STL: 0/1 */ +//#define PI_CM_IS_SNMP_SUPPORTED 0x00020000 /* STL: 0 */ +//#define PI_CM_IS_REINIT_SUPPORTED 0x00040000 /* STL: 0 */ +#define PI_CM_IS_DEVICE_MGT_SUPPORTED 0x00080000 /* STL: 0/1 */ +#define PI_CM_IS_VENDOR_CLASS_SUPPORTED 0x00100000 /* STL: 0/1 */ +//#define PI_CM_IS_DRNOTICE_SUPPORTED 0x00200000 /* STL: 0 */ +#define PI_CM_IS_CAPMASKNOTICE_SUPPORTED 0x00400000 /* STL: 0/1 */ +//#define PI_CM_IS_BOOT_MGT_SUPPORTED 0x00800000 /* STL: 0 */ +//#define PI_CM_IS_LINK_ROUNDTRIP_LATENCY_SUPPORTED 0x01000000 /* STL: 0 */ +//#define PI_CM_IS_CLIENT_REREGISTER_SUPPORTED 0x02000000 /* STL: 0 */ +//#define PI_CM_IS_OTHER_LOCAL_NOTICE_SUPPORTED 0x04000000 /* STL: 0 */ +//#define PI_CM_IS_MULTICAST_FDB_TOP_SUPPORTED 0x40000000 /* STL: 0 */ + +// IBTA: Volume 1, Section 14.2.5.7 + +/* Macros for extracting the two pieces of a PKey */ +#define PKEY_TYPE(key) ( ((uint16_t) (key)) >> 15 ) +#define PKEY_VALUE(key) ( ((uint16_t) (key)) & 0x7FFF ) +#define MAKE_PKEY(type, key) \ + ((uint16_t) ((((uint16_t)(type)) & 0x01) << 15) | ((key) & 0x7FFF)) + +typedef PKey_t PKeyBlock_t; + +// IBTA: Volume 1, Section 14.2.5.10 + +#define LFTABLE_LIST_COUNT 64 + +#define MFTABLE_LIST_COUNT 32 // entries per MFT Table block +#define MFTABLE_POSITION_COUNT 16 // Positions per portMask + +#define MFT_MAX_INDEX 511 // maximum Block Number value for Get or Set +#define MFT_MAX_POSITION 15 // Maximum PortMask Position value for Get or Set + +// IBTA: Volume 1, Section 14.2.5.13 + +#define SM_STATE_NOTACTIVE 0 +#define SM_STATE_DISCOVERING 1 +#define SM_STATE_STANDBY 2 +#define SM_STATE_MASTER 3 + +#define SM_AMOD_HANDOVER 1 // SM state transitions +#define SM_AMOD_ACKNOWLEDGE 2 +#define SM_AMOD_DISABLE 3 +#define SM_AMOD_STANDBY 4 +#define SM_AMOD_DISCOVER 5 + +#define SM_VERSION 0x01 + +// +// SM Service Record Capability bits +// +#define SM_CAPABILITY_NONE 0x00000000 +#define SM_CAPABILITY_VSWINFO 0x00000001 + +/* + * Per SM data + */ +typedef struct { + uint32_t version; /* version = 1 */ + + uint32_t fullSyncStatus; /* 0=un-initialized, 1=in progress, 2=synchronized, 3=failure */ + uint32_t fullSyncFailCount; /* count of consecutive full sync attempt failures */ + uint32_t fullTimeSyncFail; /* time of last full sync attempt failure */ + uint32_t fullTimeLastSync; /* time of last scheduled full sync - 0 if never sync'd */ + + uint32_t informSyncStatus; /* 0=un-initialized, 1=in progress, 2=synchronized, 3=failure */ + uint32_t informSyncFailCount; /* count of consecutive sync attempt failures for INFORM records */ + uint32_t informTimeSyncFail; /* time of last INFORM sync attempt failure */ + uint32_t informTimeLastSync; /* time of last sync of INFORM records; 0=un-initialized */ + + uint32_t groupSyncStatus; /* 0=un-initialized, 1=in progress, 2=synchronized, 3=failure */ + uint32_t groupSyncFailCount; /* count of consecutive sync attempt failures for MCAST group records */ + uint32_t groupTimeSyncFail; /* time of last MCAST group sync attempt failure */ + uint32_t groupTimeLastSync; /* time of last sync of mcast groups; 0=un-initialized */ + + uint32_t serviceSyncStatus; /* 0=un-initialized, 1=in progress, 2=synchronized, 3=failure */ + uint32_t serviceSyncFailCount; /* count of consecutive sync attempt failures for SERVICE records */ + uint32_t serviceTimeSyncFail; /* time of last SERVICE sync attempt failure */ + uint32_t serviceTimeLastSync; /* time of last sync of services; 0=un-initialized */ + + uint32_t mcrootSyncStatus; /* 0=un-initialized, 1=in progress, 2=synchronized, 3=failure */ + uint32_t mcrootSyncFailCount; /* count of consecutive sync attempt failures for MC Root records */ + uint32_t mcrootTimeSyncFail; /* time of last MC Root sync attempt failure */ + uint32_t mcrootTimeLastSync; /* time of last sync of services; 0=un-initialized */ + + uint32_t datelineGuidSyncStatus; /*0=un-initialized, 1=in progress, 2=synchronized, 3=failure */ + uint32_t datelineGuidSyncFailCount;/* count of consecutive sync attempt failures for Dateline Switch GUID records */ + uint32_t datelineGuidTimeSyncFail; /* time of last Dateline Switch GUID sync attempt failure */ + uint32_t datelineGuidTimeLastSync; /* time of last sync of services; 0=un-initialized */ +} SMDBSync_t; +typedef SMDBSync_t *SMDBSyncp; /* SM DBSYNC pointer type */ + +// FM Protocol Version + + +// version 1 - initial creation of FM protocol version feature +// version 2 - 10.0.1 releases and before +// version 3 - 10.1 release +// version 4 - 10.2 release +// version 5 - 10.3 release +// version 6 - 10.4 release +// version 7 - 10.5 release +// version 8 - 10.6 release +// version 9 - 10.7 release +// version 10 - 10.8 release +// version 11 - 10.9 release +// version 12 - 10.9.3 release +// version 13 - 10.10.1 release +#define FM_PROTOCOL_VERSION 13 + + +typedef struct { + uint32_t protocolVersion; + + // SM checksums + uint32_t smVfChecksum; /* Virtual Fabric database checksum */ + uint32_t smConfigChecksum; /* SM configuration checksum */ + + // PM checksums + uint32_t pmConfigChecksum; + + // EM checksums + uint32_t emConfigChecksum; /* Ethernet over STL */ + + // spare values for future expansion so packet framing does not need to change + uint32_t spare1; + uint32_t spare2; + uint32_t spare3; + uint32_t spare4; + uint32_t spare5; + uint32_t spare6; + uint32_t spare7; + uint32_t spare8; + +} SMDBCCCSync_t; +typedef SMDBCCCSync_t *SMDBCCCSyncp; /* SM DBSYNC CCC pointer type */ + +// File transport structure + +#define DBSYNC_FILE_TRANSPORT_VERSION 1 + +typedef enum { + DBSYNC_FILE_XML_CONFIG = 1, + DBSYNC_PM_SWEEP_IMAGE, + DBSYNC_PM_HIST_IMAGE +} DBSyncFileType_t; + +#define SMDBSYNCFILE_NAME_LEN 64 +typedef struct { + uint32_t version; /* structure version */ + uint32_t length; /* structure length */ + uint32_t activate; /* should file be activated */ + uint32_t type; /* type of file */ + uint32_t size; /* size of file */ + uint32_t spare1; + uint32_t spare2; + uint32_t spare3; + uint32_t spare4; + char name[SMDBSYNCFILE_NAME_LEN]; /* filename */ +} SMDBSyncFile_t; +typedef SMDBSyncFile_t *SMDBSyncFilep; /* pointer to sync file transport structure */ + +#endif // _IB_SM_H_ + diff --git a/Esm/ib/include/ib_status.h b/Esm/ib/include/ib_status.h new file mode 100644 index 0000000..deb6ffa --- /dev/null +++ b/Esm/ib/include/ib_status.h @@ -0,0 +1,217 @@ +/* BEGIN_ICS_COPYRIGHT2 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + * ** END_ICS_COPYRIGHT2 ****************************************/ + +// ******************************************************************** // +// // +// FILE NAME // +// ib_status.h // +// // +// DESCRIPTION // +// lists all of the possible status codes which are returned by // +// routines of type Status_t // +// // +// DATA STRUCTURES // +// Status_t VIEO specifiec status // +// // +// FUNCTIONS // +// None // +// // +// DEPENDENCIES // +// ib_types.h // +// // +// // +// HISTORY // +// // +// NAME DATE REMARKS // +// jsy 01/15/01 Initial creation of file // +// jsy 01/15/01 Fix typo // +// jmm 01/21/01 Added some new mai required status codes // +// jsy 01/29/01 Added conditional status // +// trp 02/05/01 Added common transport services error codes // +// jsy 02/05/01 Added VSTATUS_EIO // +// jsy 02/08/01 Added VSTATUS_KNOWN // +// jsy 02/08/01 Added VSTATUS_NOT_MASTER // +// jsy 02/09/01 Added VSTATUS_BAD in second place // +// jsy 02/12/01 Added VSTATUS_QFULL and EMPTY // +// sfw 02/13/01 Added VSTATUS_AGAIN // +// trp 02/14/01 Added VSTATUS_UNINIT // +// jmm 02/18/01 Added more descriptive mai_* error codes // +// dkj 03/08/01 Added VSTATUS_NOSUPPORT // +// jak 03/21/01 Added VSTATUS_IGNORE // +// dkj 03/29/01 Added VSTATUS_INUSE // +// pjg 04/02/01 Added VSTATUS_INVALID_PORT through / +// VSTATUS_INVALID_NODE // +// trp 04/05/01 Added INTERNAL and MAD_FULL for MAI // +// jak 04/20/01 Added VSTATUS_SIGNAL // +// trp 06/10/01 Cleaned up comments // +// trp 07/31/01 Added MAI FILTER and RAW // +// sfw 08/14/01 Added VSTATUS_EVENT_CONSUMED // +// ram 11/13/01 Fix type (VSTATUS_MAD_OERFLOW) // +// dkj 01/09/02 Added VSTATUS_INVALID_GID_INDEX // +// dkj 03/21/02 Added VSTATUS_BADPAGESIZE // +// dkj 04/16/02 Added VSTATUS_INVALID_CQ_HANDLE // +// ram 04/22/02 Added VSTATUS_INVALID_FORMAT // +// ******************************************************************** // + +#ifndef _IB_STATUS_H_ +#define _IB_STATUS_H_ + +#include "ib_types.h" + +typedef uint32_t Status_t; + +#define VSTATUS_OK (0) // Good status +#define VSTATUS_BAD (1) // Bad status +#define VSTATUS_MISMATCH (2) // Key mismatch +#define VSTATUS_DROP (3) // Drop this packet +#define VSTATUS_FORWARD (4) // Forward this packet +#define VSTATUS_ILLPARM (5) // Invalid parameter +#define VSTATUS_NOMEM (6) // Out of memory +#define VSTATUS_TIMEOUT (7) // Request timed out +#define VSTATUS_NOPRIV (8) // Not enough privs +#define VSTATUS_BUSY (9) // Can't do it - busy +#define VSTATUS_NODEV (10) // No object available +#define VSTATUS_NXIO (11) // Invalid object +#define VSTATUS_PARTIAL_PRIVS (12) // Some privs are avail +#define VSTATUS_CONDITIONAL (13) // Conditionally good +#define VSTATUS_NOPORT (14) // Port does not exist + +#define VSTATUS_INVALID_HANDL (15) // invalid handle +#define VSTATUS_INVALID_TYPE (16) // invalid type (ib_attr) +#define VSTATUS_INVALID_ATTR (17) // invalid attribute (ib_attr) +#define VSTATUS_INVALID_PROTO (18) // invalid protocol (RC,RD,UC,UD,RAW) +#define VSTATUS_INVALID_STATE (19) // invalid CEP or QP state +#define VSTATUS_NOT_FOUND (20) // item not found +#define VSTATUS_TOO_LARGE (21) // value too large +#define VSTATUS_CONNECT_FAILED (22) // attempt to connect failed +#define VSTATUS_CONNECT_GONE (23) // connection torn down +#define VSTATUS_NOHANDLE (24) // no more handles available +#define VSTATUS_NOCONNECT (25) // no more connections available + +#define VSTATUS_EIO (26) // generic IO error +#define VSTATUS_KNOWN (27) // info already known +#define VSTATUS_NOT_MASTER (28) // not the Master SM + +#define VSTATUS_INVALID_MAD (29) // invalid MAD +#define VSTATUS_QFULL (30) // Queue is full +#define VSTATUS_QEMPTY (31) // Queue is full + +#define VSTATUS_AGAIN (32) // Data not available + +#define VSTATUS_BAD_VERSION (33) // Version mismatch + +#define VSTATUS_UNINIT (34) // Library not initialized + +#define VSTATUS_NOT_OWNER (35) // Not resource owner +#define VSTATUS_INVALID_MADT (36) // Malformed Mai_t +#define VSTATUS_INVALID_METHOD (37) // MAD method invalid +#define VSTATUS_INVALID_HOPCNT (38) // HopCount not in [0..63] +#define VSTATUS_MISSING_ADDRINFO (39) // Mai_t has no addrInfo +#define VSTATUS_INVALID_LID (40) // LID=RESERVED_LID +#define VSTATUS_INVALID_ADDRINFO (41) // invalid addrInfo in Mai_t +#define VSTATUS_MISSING_QP (42) // QP not in Mai_t +#define VSTATUS_INVALID_QP (43) // MAI QP not SMI(0) or GSI(1) +#define VSTATUS_INVALID_MCLASS (48) // Reserved mclass used +#define VSTATUS_INVALID_QKEY (51) // BTH qkey field for GSI invalid +#define VSTATUS_INVALID_MADLEN (53) // MAD datasize invalid/not determinable +#define VSTATUS_NOSUPPORT (55) // Function not supported +#define VSTATUS_IGNORE (56) // Ignorable condition +#define VSTATUS_INUSE (57) // Resource already in use + +#define VSTATUS_INVALID_PORT (58) // Port invalid +#define VSTATUS_ATOMICS_NOTSUP (59) // Atomic operations not + // supported by hardware +#define VSTATUS_INVALID_ACCESSCTL (60) // Access definition invalid +#define VSTATUS_INVALID_ADDR_HANDLE (61) // Address handle invalid +#define VSTATUS_INVALID_ADDR (62) // Address invalid +#define VSTATUS_INVALID_ARG (63) // Arguments invalid +#define VSTATUS_INVALID_HCA_HANDLE (64) // Channel adapter handle invalid +#define VSTATUS_INVALID_KEY_VALUE (65) // Partition key invalid +#define VSTATUS_INVALID_MEMADDR (66) // Memory not accessible +#define VSTATUS_INVALID_MEMSIZE (67) // Memory region size not + // supported by hardware +#define VSTATUS_INVALID_MIGSTATE (68) // Migration state requested invalid +#define VSTATUS_INVALID_NOTICE (69) // Completion notice requested invalid +#define VSTATUS_INVALID_OFFSET (70) // Offset specified invalid +#define VSTATUS_INVALID_PD (71) // Protection domain invalid +#define VSTATUS_INVALID_PKEY_IDX (72) // Partition key index invalid +#define VSTATUS_INVALID_RC_TIMER (73) // Reliable connection timeout invalid +#define VSTATUS_INVALID_RDD (74) // Reliable datagram domain invalid +#define VSTATUS_INVALID_REQUEST (75) // Request is invalid for this type of hardware +#define VSTATUS_INVALID_RNR_CNT (76) // Receiver not ready count invalid. +#define VSTATUS_INVALID_RNR_TIMER (77) // Receiver not ready timer invalid. +#define VSTATUS_INVALID_TRANSPORT (78) // Transport type invalid or not supported +#define VSTATUS_INVALID_WORKREQ (79) // Work request invalid for transport service +#define VSTATUS_MCAST_NOTSUP (80) // Multicast not supported +#define VSTATUS_MCGRP_QPEXCEEDED (81) // Number of Queue Pairs in the + // multicast group exceeded + // the number supported +#define VSTATUS_MEMRGN_NOTSUP (82) // Memory regions not supported +#define VSTATUS_MEMWIN_NOTSUP (83) // Memory windows not supported +#define VSTATUS_NORESOURCE (84) // Out of hardware resources +#define VSTATUS_OPERATION_DENIED (85) // Operation cannot be performed +#define VSTATUS_QP_BUSY (86) // Queue Pair is already opened +#define VSTATUS_RDMA_NOTSUP (87) // Remote DMA operations not supported +#define VSTATUS_RD_NOTSUP (88) // Reliable Datagram transport not supported +#define VSTATUS_SG_TOOMANY (89) // Number of scatter/gather entries + // exceeds supported capability. +#define VSTATUS_WQ_RESIZE_NOTSUP (90) // Work queue resizing not supported +#define VSTATUS_WR_TOOMANY (91) // Work queue size not supported +#define VSTATUS_INVALID_NODE (92) // Node index invalid +#define VSTATUS_MAI_INTERNAL (93) // MAI internal loopback message +#define VSTATUS_MAD_OVERFLOW (94) // MAD buffer overflow +#define VSTATUS_SIGNAL (95) // Signal received +#define VSTATUS_FILTER (96) // Filter take over notification received +#define VSTATUS_EXPIRED (98) // time period has expired +#define VSTATUS_EVENT_CONSUMED (99) // handler consumed event +#define VSTATUS_INVALID_PATH (100) // path handle invalid +#define VSTATUS_INVALID_GID_INDEX (101) // GID index invalid +#define VSTATUS_INVALID_DEVICE (102) // Device ordinal out of range +#define VSTATUS_INVALID_RESOP (103) // resolver operation invalid +#define VSTATUS_INVALID_RESCMD (104) // resolver command invalid +#define VSTATUS_INVALID_ITERATOR (105) // resolver iterator invalid +#define VSTATUS_INVALID_MAGIC (106) // magic number not correct for structure +#define VSTATUS_BADPAGESIZE (107) // invalid memory page size specified +#define VSTATUS_UNRECOVERABLE (108) // a variant of BAD that indicates to the + // caller that recovery (within a context) + // should not be attempted +#define VSTATUS_TIMEOUT_LIMIT (109) // the maximum cumulative timeout limit + // was reached +#define VSTATUS_ITERATOR_OUT_OF_DATE (119) // data referred by + // iterator updated or deleted. +#define VSTATUS_INSUFFICIENT_PERMISSION (120) // client has insufficient + // privillages for action +#define VSTATUS_INVALID_CQ_HANDLE (126) // CQ handle is invalid +#define VSTATUS_INVALID_FORMAT (127) // Data format is invalid +#define VSTATUS_REJECT (128) // Request rejected +#define VSTATUS_DONE (129) // Request done + +// WHEN ADDING STATUS CODES, ALSO UPDATE cs_convert_status() in cs_utility.c + +#endif // _IB_STATUS_H_ diff --git a/Esm/ib/include/ib_types.h b/Esm/ib/include/ib_types.h new file mode 100644 index 0000000..cc0961e --- /dev/null +++ b/Esm/ib/include/ib_types.h @@ -0,0 +1,164 @@ +/* BEGIN_ICS_COPYRIGHT2 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + * ** END_ICS_COPYRIGHT2 ****************************************/ + +//----------------------------------------------------------------------------// +// // +// FILE NAME // +// ib_types.h // +// // +// DESCRIPTION // +// Basic VIEO and IB type definitions // +// // +// DATA STRUCTURES // +// None // +// // +// FUNCTIONS // +// None // +// // +// DEPENDENCIES // +// None // +// // +// // +// PJG 05/29/02 PR2176: Include keyword 'signed' in int8_t typedefs. // +//----------------------------------------------------------------------------// + +#ifndef _IB_TYPES_H_ +#define _IB_TYPES_H_ + +//----------------------------------------------------------------------------// +// // +// Fundamental data types. There should be a set for each type // +// of compiler/architecture that we need to use. // +// // +//----------------------------------------------------------------------------// +typedef unsigned long unint; /* define native unsigned integer (32 or 64 bit) */ +typedef long nint; /* define native integer (32 or 64 bit) */ + + +//----------------------------------------------------------------------------// +// // +// Linux defines. // +// // +//----------------------------------------------------------------------------// + +#if defined(__LINUX__) + +#include // int*_t defined here +#include // uint*_t defined here + +//----------------------------------------------------------------------------// +// // +// FreeBSD defines. // +// // +//----------------------------------------------------------------------------// + +#elif defined(__FreeBSD__) + +#include + +//----------------------------------------------------------------------------// +// // +// Windows 32 defines. // +// // +//----------------------------------------------------------------------------// + +#elif defined(WIN32) + +typedef unsigned char uint8_t; +typedef unsigned short uint16_t; +typedef unsigned int uint32_t; +typedef unsigned __int64 uint64_t; + +typedef signed char int8_t; +typedef short int16_t; +typedef int int32_t; +typedef __int64 int64_t; + + +//----------------------------------------------------------------------------// +// // +// vxWorks defines. // +// // +//----------------------------------------------------------------------------// + +#elif defined(__VXWORKS__) + +#include +// VxWorks for ATOM defines uint64_t and int64_t + + + +//----------------------------------------------------------------------------// +// // +// Unknown OS defines. // +// // +//----------------------------------------------------------------------------// + +#else + +typedef unsigned char uint8_t; +typedef unsigned short uint16_t; +typedef unsigned int uint32_t; +typedef unsigned long long int uint64_t; + +typedef signed char int8_t; +typedef short int16_t; +typedef int int32_t; +typedef long long int int64_t; + +#endif + +//----------------------------------------------------------------------------// +// // +// Fundamental IBA types. These are defined only in terms of the // +// types above. // +// // +//----------------------------------------------------------------------------// + +typedef uint64_t Guid_t; +typedef uint16_t PKey_t; +typedef uint16_t QKey_t; +typedef uint64_t BKey_t; +typedef uint64_t MKey_t; +typedef uint64_t SAKey_t; +typedef uint64_t CCKey_t; +typedef uint8_t Gid_t[16]; + +//----------------------------------------------------------------------------// +// // +// Other fundamental types for the implementation. // +// // +//----------------------------------------------------------------------------// + +typedef nint IBhandle_t; // -1 => no handle (NULL) + +#define IB_NULLH (-1) + +#endif /* _IB_TYPES_H_ */ + diff --git a/Esm/ib/include/if3.h b/Esm/ib/include/if3.h new file mode 100644 index 0000000..128e02b --- /dev/null +++ b/Esm/ib/include/if3.h @@ -0,0 +1,213 @@ +/* BEGIN_ICS_COPYRIGHT2 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + * ** END_ICS_COPYRIGHT2 ****************************************/ + +/************************************************************************/ +/* */ +/* FILE NAME */ +/* if3.h */ +/* */ +/* DESCRIPTION */ +/* Library calls for interface 3 */ +/* */ +/* */ +/* DEPENDENCIES */ +/* ib_types.h */ +/* */ +/* */ +/************************************************************************/ + + +#ifndef __IF3___ +#define __IF3___ + +#include +#include +#include + +/* + * Defines for service ID, service name and classes used by IF3 + * and managers that it speaks to. + */ + + +#define FE_SERVICE_ID (0x1100d03c34834444ull) +#define FE_SERVICE_NAME "Intel OmniPath Fabric Executive" + +#define SM_SERVICE_ID (0x1100d03c34822222ull) +#define SM_SERVICE_ID_SEC (0x1100d03c34822222ull) +#define SM_SERVICE_NAME "Primary Intel OmniPath Subnet Manager" +#define SM_SERVICE_NAME_SEC "Secondary Intel OmniPath Subnet Manager" + + +#define IF3_REGFORCE_PORT (1) /* force the registration */ +#define IF3_REGFORCE_FABRIC (2) /* force the registration */ +#define IF3_REGTRY_PORT (3) /* only try to register */ +#define IF3_REGTRY_FABRIC (4) /* only try to register */ +#define IF3_CONTROL_CMD (0x0000) /* by IF3 transport */ + +// Intra manager reliable communication commands set in method field +#define FE_MNGR_PROBE_CMD (0x21) +#define FE_MNGR_CLOSE_CMD (0x22) +#define FE_CMD_RESP (0x25 | MAD_CM_REPLY) +#define FM_CMD_SHUTDOWN (0x40) + + +#define SM_KEY 0 + +#define SA_MAD_SET_HEADER(mad, smKey, mask) {\ + (mad)->SaHdr.SmKey = smKey; \ + (mad)->SaHdr.ComponentMask = mask; \ +} + + +#define SA_SRP_NAME_LEN 124 + +/* + * Function used to do call backs while manager is communicating over IF3. + */ +typedef void (*AsyncCallBack_t)(IBhandle_t fd , Mai_t *mad, void *context); + +typedef struct { + uint8_t flag; /* flag indicating whether the entry is in use */ + + STL_LID slid; /* this port lid */ + STL_LID dlid; /* the managers port lid */ + STL_LID saLid; /* where the sa lives */ + uint8_t lmc; /* lmc of port */ + uint64_t SubnetTO; /* Subnet Timeout */ + + uint16_t mclass; /* manager's class */ + + uint16_t dev; /* our device */ + uint16_t port; /* our port */ + + uint8_t sl; /* Service Level */ + + uint16_t pkey; /* the pkey to use */ + uint32_t qkey; /* the qkey; */ + uint8_t qp; /* destination qp */ + + IBhandle_t fdr; /* handle used for recv */ + IBhandle_t fds; /* handle used for command sends. */ + + uint8_t cb_flag; /* If call back set this is true. */ + AsyncCallBack_t cb_func; /* callback function for high priority data + * received while speaking to FE + */ + IBhandle_t cb_fd; /* callback handle to listen on currently while + * doing recieve from FE + */ + void *cb_ctx; /* context to pass to call back function */ + + uint8_t guidIsValid; /* true if the guid is valid */ + int8_t vfi_guid; /* Guid being used by vfi - set to -1 when not initialized */ + GuidInfo_t guid; /* Guid for port */ + uint64_t gidPrefix; /* GID prefix */ + STL_CLASS_PORT_INFO cpi; + int cpi_valid; /* true if classPortInfo is valid */ + uint8_t isRegistered; /* true if Manager service is + * registered */ + uint8_t servName[SA_SRP_NAME_LEN]; /* name of service */ + uint64_t servID; /* service ID regiseter */ + uint32_t retries; + uint64_t timeout; + uint8_t rmppCreateFilters; + Pool_t *rmppPool; + uint32_t rmppDataLength; + uint32_t rmppMaxCntxt; + IBhandle_t *rmppMngrfd; + IBhandle_t rmppGetfd; + IBhandle_t rmppGetTablefd; +} ManagerInfo_t; + +Status_t if3_timeout_retry(IBhandle_t fd, uint64_t timeout, uint32_t retry); +/**/ +/* Data structure to pass back information to call back function*/ +/**/ + +typedef struct +{ + uint32_t msize; /*the total message size being sent/expected*/ + uint32_t offset; /*the byte offset of this payload relative to message*/ + uint8_t *data; /*pointer to the data being passed */ + uint32_t dlen; /*amount of data being passed in callback*/ + uint8_t dir; /*direction: CB_TX_DIR,CB_RX_DIR*/ +}CBTxRxData_t; + +/**/ +/* Return values from CBTxRxFunc_t supported */ +/* VSTATUS_OK - continue to get data from SA*/ +/* VSTATUS_DROP - terminate data reception from SA*/ +/**/ +typedef uint32_t (*CBTxRxFunc_t)(CBTxRxData_t *arg, void* context); + + +Status_t if3_register_fe(uint32_t dev, uint32_t port, uint8_t *servName, uint64_t servID, uint32_t option, IBhandle_t *pfd); +Status_t if3_deregister_fe(IBhandle_t fd); +Status_t if3_lid_mngr_cnx(uint32_t dev,uint32_t port, uint8_t mclass, STL_LID lid, IBhandle_t *mhdl); +Status_t if3_sid_mngr_cnx(uint32_t dev,uint32_t port, uint8_t *servName, uint64_t servID, uint8_t mclass, IBhandle_t *mhdl); + +Status_t if3_local_mngr_cnx (uint32_t dev, uint32_t port, uint8_t mclass, IBhandle_t * mhdl); +Status_t if3_close_mngr_cnx(IBhandle_t mhdl); +Status_t if3_close_mngr_rmpp_cnx (IBhandle_t mhdl); +void STL_BasicMadInit (Mai_t * madp, uint8_t mclass, uint8_t method, uint16_t aid, uint32_t amod, STL_LID slid, STL_LID dlid, uint8_t sl); +Status_t if3_mad_init(IBhandle_t fd, Mai_t *madp, uint8_t mclass, uint8_t method, uint16_t aid, uint32_t amod, STL_LID dlid); +Status_t if3_cntrl_cmd_send(IBhandle_t fd, uint8_t cmd); +Status_t if3_open(uint32_t dev, uint32_t port, uint8_t mclass, IBhandle_t * pfd); +Status_t if3_close(IBhandle_t mhdl); +Status_t if3_check_sa(IBhandle_t fd, int refresh, uint16_t *hasMoved); +Status_t if3_set_dlid(IBhandle_t fd, STL_LID dlid); + +Status_t if3_mngr_locate_minfo(IBhandle_t rcv, ManagerInfo_t ** pt); + +Status_t if3_mngr_open_cnx_fe(uint32_t dev, uint32_t port, uint16_t mclass, IBhandle_t *fhdl); +Status_t if3_mngr_close_cnx_fe(IBhandle_t fhdl, uint8_t complete); +Status_t if3_mngr_rcv_fe_data(IBhandle_t fhdl, Mai_t *fimad, uint8_t *inbuff, uint32_t *inlen); +Status_t if3_mngr_get_fe_cmd(Mai_t *mad, uint16_t *cmd); +Status_t if3_mngr_send_mad(IBhandle_t fd, SA_MAD *psa, uint32_t dataLength, uint8_t *buffer, uint32_t *bufferLength, uint32_t *madRc, CBTxRxFunc_t cb, void *context); +Status_t if3_mngr_send_passthru_mad (IBhandle_t fd, SA_MAD *psa, uint32_t dataLength, Mai_t *maip, uint8_t *buffer, uint32_t *bufferLength, uint32_t *madRc, CBTxRxFunc_t cb, void *context); +Status_t if3_dbsync_cmd_from_mngr(IBhandle_t fd, Mai_t *maip, uint8_t *buffer, uint32_t *bufferLength, uint32_t *madRc, CBTxRxFunc_t cb, void *context); +Status_t if3_dbsync_reply_to_mngr(IBhandle_t fhdl, Mai_t *fmad, uint8_t *outbuff, uint32_t outlen, uint32_t resp_status); +Status_t if3_dbsync_cmd_to_mngr(IBhandle_t mhdl, uint16_t cmd, uint32_t mod, uint8_t *outbuff, uint32_t outlen, uint8_t *inbuff, uint32_t *inlen, uint32_t *resp_status); +Status_t if3_dbsync_close(IBhandle_t mhdl); + +Status_t MngrWaitHandle(IBhandle_t *ha, uint32_t count, uint64_t timeout, uint32_t *pfirst, Mai_t *maip); + +Status_t if3_ssl_init(Pool_t *pool); +void * if3_ssl_srvr_open(const char *dir, const char *fmCertificate, const char *fmPrivateKey, const char *fmCaCertificate, uint32_t fmCertChainDepth, const char *fmDHParameters, uint32_t fmCaCrlEnabled, const char *fmCaCrl); +void * if3_ssl_accept(void *context, int clientfd); +int if3_ssl_read(void *session, uint8_t *buffer, int bufferLength); +int if3_ssl_write(void *session, uint8_t *buffer, int bufferLength); +void if3_ssl_conn_close(void *context); +void if3_ssl_sess_close(void *session); + +Status_t vfi_GetPortGuid(ManagerInfo_t *fp, uint32_t gididx); + + +#endif diff --git a/Esm/ib/include/ifs_g.h b/Esm/ib/include/ifs_g.h new file mode 100644 index 0000000..2c90c38 --- /dev/null +++ b/Esm/ib/include/ifs_g.h @@ -0,0 +1,57 @@ +/* BEGIN_ICS_COPYRIGHT2 **************************************** + +Copyright (c) 2018, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + * ** END_ICS_COPYRIGHT2 ****************************************/ + +//==============================================================================/ +// / +// FILE NAME / +// ifs_g.h / +// / +// DESCRIPTION / +// This file contains global structure and definitions used in the HSM and / +// the ESM and other tools. / +//==============================================================================/ + +#ifndef _IFS_G_H_ +#define _IFS_G_H_ + +// For dynamic Adaptive Routing configuration for the HSM and ESM +#define AR_FREQUENCY_LOWER 0 +#define AR_FREQUENCY_UPPER 7 + +#define AR_THRESHOLD_LOWER 0 +#define AR_THRESHOLD_UPPER 7 + +typedef struct fm_ar_config { + uint32_t enable; + uint32_t frequency; + uint32_t threshold; +}fm_ar_config_t; + +#endif /* _IFS_G_H_ */ + diff --git a/Esm/ib/include/mai_g.h b/Esm/ib/include/mai_g.h new file mode 100644 index 0000000..4287fc2 --- /dev/null +++ b/Esm/ib/include/mai_g.h @@ -0,0 +1,872 @@ +/* BEGIN_ICS_COPYRIGHT2 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + * ** END_ICS_COPYRIGHT2 ****************************************/ + +/****************************************************************************/ +/* */ +/* FILE NAME VERSION */ +/* mai_g.h MAPI 0.05 */ +/* */ +/* DESCRIPTION */ +/* This file contains global function prototypes and structure */ +/* definitions for the Management API. */ +/* */ +/* */ +/* DATA STRUCTURES */ +/* Filter_t Holds filter description */ +/* Mai_t Used to exchange MADs with API */ +/* */ +/* FUNCTIONS */ +/* max_get_max_filters return MAI_MAX_FILTERS for unit test use */ +/* mai_open Create a channel to send/recv MADs */ +/* mai_close Tear down an unneeded channel */ +/* mai_filter_create Add a filter to an open channel */ +/* mai_filter_delete Remove a channel */ +/* mai_recv Receive one MAD from a channel */ +/* mai_send Send a MAD to an open channel */ +/* mai_init Initialize MAD API layer */ +/* mai_filter_mclass Create filter that accepts only MADs */ +/* of a specified mclass */ +/* mai_filter_method Create a filter that accepts only MADs */ +/* of a specified mclass and method */ +/* mai_filter_aid Create a filter that accepts only MADs */ +/* of a specified mclass, method, and aid */ +/* mai_filter_amod Create a filter that accepts only MADs of */ +/* a specified mclass, method, aid, and amod */ +/* mai_filter_once Create a one-shot� filter with a unique */ +/* TID and associate it with the filter */ +/* mai_filter_tid Create a filter that accepts only MADs of */ +/* a specified mclass and tid */ +/* mai_alloc_tid Allocate a unique TID for this class */ +/* mai_filter_handle Returns the handle associated with a */ +/* previously created filter */ +/* mai_filter_hcreate Create a filter */ +/* mai_filter_hdelete Delete the specified filter */ +/* mai_get_stl_portinfo Receive port information for the local port */ +/* mai_shutdown Mark the MAI library as uninitialized */ +/* */ +/* DEPENDENCIES */ +/* VIEO_THREADED Global definition */ +/* */ +/* */ +/* HISTORY */ +/* NAME DATE REMARKS */ +/* Jim Mott 01-15-2001 Entry from prototype code */ +/* Jeff Young 02-08-2001 Fixed Filter_t def */ +/* Todd Pisek 02-12-2001 Moved grh b4 lrh in mai_mad*/ +/* Jim Mott 02-18-2001 Added base+extra lengths */ +/* to Mai_t. */ +/* Peter Walker 03-26-2001 remove extra in Mai_t */ +/* */ +/* OUTSTANDING ISSUES */ +/* */ +/****************************************************************************/ + + +#ifndef _IB_MAI_G_H_ +#define _IB_MAI_G_H_ + +#include +#include +#include +#include "iba/stl_sm_priv.h" + + +#define MAD_BASEHDR_SIZE (24) + +#define IB_MAX_MAD_DATA (256) +#define IB_MAD_PAYLOAD_SIZE (IB_MAX_MAD_DATA - MAD_BASEHDR_SIZE) + +#define STL_MAX_MAD_DATA (2048) +#define STL_MAD_PAYLOAD_SIZE (STL_MAX_MAD_DATA - MAD_BASEHDR_SIZE) + +#define MAI_FNAME_LEN (16) +/* + * Structure definitions + */ + +/* MaiAddrInfo_t + * This striucture is used within Mai_t to describe the source and + * destination addressing for a MAD packet. + */ +typedef struct _MaiAddrInfo_t { + STL_LID slid; // source LID (32) + STL_LID dlid; // destination LID (32) + uint8_t sl; // service level (4) + uint16_t pkey; // partition key (16) + uint32_t srcqp; // WQP number at the source (24) + uint32_t destqp; // destination QP (24) + uint32_t qkey; // queue pair key (32) +} MaiAddrInfo_t; + +#define SMI_MAD_SL 0 // C7-25 + +/* + * Mai_t + * This structure is the primary interchange for the + * Management API and all the glue layers. It is created by managers + * and agents on one side of the pipe and IB hardware on the other. + * + * active + * This bit field describes which parts of Mai_t contain + * real information. Manager and agents use it to communicate with + * hardware on wire level protocol. The receive side + * code+hardware use it to communicate with agents and managers how + * much of the data is valid. + * + * type + * There are 3 types of mai_mad data objects: + * EXTERNAL send + receive Contains a MAD for the wire + * INTERNAL send + receive Used for inter-agent communication + * When an agent/manager sends a MAD of type INTERNAL, that data chunk + * is transported to the very bottom of the stream and queued to + * the incoming MAD chain. As it passes back up the stack, the + * various fields are matched against every channels filters and + * the MAD is duplicated on the input queue of each of them. + * + * dev + * When there are multiple FIs in a system, the dev parameter is + * used to select them. FIs are numbered consecutively from 0 to + * n-1 where there are n adapters. The dev fields must be >0 except + * when constructing filters. dev==-1 --> MAI_FILTER_ANY. + * + * port + * Switches use the port parameter to select the correct output + * port for PERMISSIVE MADs. Multi-port channel adapters use the + * port to indicate which port in the FI should be used. The port + * fields must be >0 except when constructing filters. + * ports==-1 --> MAI_FILTER_ANY + * + * addrInfo + * addressing information for the MAD packet + * + * base + * Contains the standard MAD header + * + * datasize + * Contains the number of active bytes in data. + * + * data + * Optional fields at the end of the standard MAD header. + * + * + * + * + * NOTES: + * 1. You must always preserve the order of the following fields + * - base + * - data + * 2. Changes to the active masks (MAI_ACT_*) require updates to the + * filter-checking logic in maif.c + */ + +typedef struct _Mai_t + { + uint32_t active; /* Active field bit array */ + int16_t datasize; /* Amount of valid data in 'data'; Default all. */ + int16_t type; /* Type of mad: EXTERNAL, INTERNAL */ + int16_t dev; /* Device that received the MAD */ + int16_t port; /* Port that the MAD is sent or received on */ + int32_t qp; /* QP for data */ + MaiAddrInfo_t addrInfo; /* address information */ + Mad_t base; /* Base MAD */ + uint64_t intime; /* Time data arrived at the bottom of the stack */ + uint8_t data[STL_MAX_MAD_DATA]; /* The rest of basic MAD */ + /* DO NOT PLACE ANY FIELDS BELOW data */ + } Mai_t; + + +static __inline uint8_t* stl_mai_get_smp_data(Mai_t *maip) +{ + if (maip->base.mclass == MCLASS_SM_DIRECTED_ROUTE) { + return ((DRStlSmp_t *)maip->data)->SMPData; + } + return ((LRStlSmp_t *)maip->data)->SMPData; +} +static __inline size_t stl_mai_get_smp_data_offset(Mai_t *maip) +{ + if (maip->base.mclass == MCLASS_SM_DIRECTED_ROUTE) { + return offsetof(DRStlSmp_t, SMPData); + } + return offsetof(LRStlSmp_t, SMPData); +} +static __inline uint64_t* stl_mai_get_mkey(Mai_t *maip) +{ + if (maip->base.mclass == MCLASS_SM_DIRECTED_ROUTE) { + return &(((DRStlSmp_t *)maip->data)->M_Key); + } + return &(((LRStlSmp_t *)maip->data)->M_Key); +} + +/* Function for filter callback */ +typedef int (mai_filter_check_packet_t)(Mai_t * data); + +/* + * Filter_t + * This structure is used to pass filter requests around. + * + * NOTES: + * 1. If MAI_FILTER_ANY is set for any value, a match is + * is considered to have occured only if: + * A. active has MAI_ACT_FMASK set and there is a corresponding + * match on the MAD data as set by the tuple (mask,value) + * B. active does not have MAI_ACT_FMASK set. + */ +typedef struct _Filter_t + { + uint32_t active; /* Active field mask: MAI_ACT_* */ + int16_t type; /* Type of MAD: EXTERNAL, INTERNAL */ + int16_t dev; /* Device that received the MAD */ + int16_t port; /* Port the MAD sent or received on */ + int32_t qp; /* Zero or one */ + uint8_t unused; /* Alignment */ + Mad_t value; /* Value to match */ + Mad_t mask; /* Mask to match */ + char fname[MAI_FNAME_LEN+1]; /* To identify the filter */ + uint32_t refcnt; /* Instances of references to this filter */ + + uint8_t flags; /* State flags: Opaque to user */ + void *handle; /* lower-level handle for this filter */ + mai_filter_check_packet_t * mai_filter_check_packet; +} Filter_t; +#define MAI_FILTER_ANY (-1) /* Match any type,dev,port,qp */ + + + + +#define MAI_TYPE_ANY (-1) /* MAI_FILTER_ANY place holder */ +#define MAI_TYPE_EXTERNAL (1) /* Normal MAD packet */ +#define MAI_TYPE_INTERNAL (3) /* Mai_t payload is an internal message */ + /* sent between handles in the MAI stack */ +#define MAI_TYPE_ERROR (8) /* Indicates error, mad was never sent, returning original mad */ + +#define MAI_TYPE_DROP (9) /* Indicates security violation error, mad was never processed, dropping the mad */ + +#define MAI_ACT_TYPE (0x00000001) /* Type field is valid */ +#define MAI_ACT_ADDRINFO (0x00000004) /* addrInfo contains valid data */ +#define MAI_ACT_BASE (0x00000040) /* base contains valid data */ +#define MAI_ACT_DATA (0x00000080) /* data contains valid data */ +#define MAI_ACT_DEV (0x00000100) /* Device field is active */ +#define MAI_ACT_PORT (0x00000200) /* Port field is active */ +#define MAI_ACT_QP (0x00000400) /* qp field is active */ +#define MAI_ACT_FMASK (0x00000800) /* Filter mask is active */ +#define MAI_ACT_FNAME (0x00001000) /* Filter name is active */ +#define MAI_ACT_TSTAMP (0x00002000) /* The Time stamp is active */ +#define MAI_ACT_DATASIZE (0x00004000) /* datasize field valid data */ + + + +#define MAI_MAX_PORT (255) +#define MAI_MAX_DEV (255) + +/* Used to set the mask on filters. */ +#define MAI_FMASK_ALL (~0) + +/* Declaration on constants */ + +#define MAI_SMI_QP (0) /* Subnet Management QP */ +#define MAI_GSI_QP (1) /* General Service QP */ + + +/* + * MAI_MAX_QUEUED_DEFAULT + * To prevent one consumer from shutting down all the others by not + * servicing his queue, we will limit the maximum number of outstanding + * MADs allowed on a single channel. + * + * Note that this default may be overriden prior to initializing MAI. + */ +#ifndef MAI_MAX_QUEUED_DEFAULT +#ifdef __VXWORKS__ +#define MAI_MAX_QUEUED_DEFAULT 256 +#else +#define MAI_MAX_QUEUED_DEFAULT 512 +#endif +#endif /* MAI_MAX_QUEUED_DEFAULT */ + + +/* + * MAI_MAX_DATA_DEFAULT + * The size of the buffer pool that stores MADs flowing up from the + * bottom. In cases where we are single threaded, there are not many + * of these. + * It is possible for 2 SA threads to consume 2 X MAI_MAX_QUEUED by + * themselves so alloc 3X buffers to support SM/PM/BM/FE + * + * Note that this default may be overriden prior to initializing MAI. + */ +#ifndef MAI_MAX_DATA_DEFAULT +#define MAI_MAX_DATA_DEFAULT (5 * MAI_MAX_QUEUED_DEFAULT) +#endif /* MAI_MAX_DATA_DEFAULT */ + + +/* Macro to set the name of a filter. Particularly useful during debug */ + +#define MAI_SET_FILTER_NAME(ft, szname) do{ \ + int _i=0; char *_p = (char *)(szname); \ + int _l=(sizeof(szname)<(MAI_FNAME_LEN-1)?sizeof(szname):(MAI_FNAME_LEN-1)); \ + for(_i=0;_i<_l;_i++) \ + { (ft)->fname[_i]=_p[_i]; if (_p[_i]==0)break;} \ + (ft)->fname[_i]=0; (ft)->active |= MAI_ACT_FNAME; \ +}while(0) + +/* + * Masks the bits of the TID that are reserved for the IB stacks use. In + * particular, OFED places no guarantee on preserving the integrity of the + * upper 32 bits. + * + * To be used when comparing TID coming up from the stack against expected + * values. + */ +#ifdef IB_STACK_OPENIB +#define MAI_MASK_TID(tid) (tid & 0xffffffffull) +#else +#define MAI_MASK_TID(tid) (tid) +#endif + +/* + * mai_set_num_endports + * This function can be called prior to calling mai_init. It will adjust + * the MAD buffer size and queue depths accordingly. If not called, they will + * be given reasonable defaults. + * + * INPUTS + * num_end_ports The required number of fabric end ports to scale to. + * + * RETURNS + * Nothing. + */ +void mai_set_num_end_ports(uint32_t num_end_ports); + + +/* + * mai_init + * This function must be called prior to calling any of the other management + * API function. It can only be called once. + * + * INPUTS + * None + * + * RETURNS + * Nothing. Errors are fatal. + */ +void mai_init(void); + +/* + * mai_get_max_filters + * return maximum filters available in MAI + * provided for use by MAI unit tests since MAI_MAX_FILTERS is + * a local constant + * + * INPUTS + * None + * + * RETURNS + * unsigned + */ +unsigned mai_get_max_filters(void); + +/* + * mai_open + * This function will create a new channel to the SMI or GSI. + * Initially there are no filters active on the channel so you will receive nothing + * from it. You can always send MADs to a channel. The qp, dev, port parameters are + * the default values associated with filters that are created on the handle. + * This function also calls through the hardware to validate the values passed in. + * If the values in the message have not been set by the caller, they will be the + * default values assigned to Mai_t messages on mai_send. + * + * INPUTS + * qp The QP to open. SMI=QP0, GSI=QP1. Nothing else is valid + * dev Device number [0..n-1] when n FIs in a system + * port FI port for multi-ported FIs + * fd Pointer to a place to store the channel number + * + * RETURNS + * Status_t See ib_status.h + */ +Status_t mai_open(uint32_t qp, uint32_t dev, uint32_t port, IBhandle_t *fd); + + + + +/* + * mai_close + * Close a previously opened channel. Release all resources (filters, + * queued read data) to the handle. + * + * INPUTS + * fd An open channel (mai_open) to close + * + * RETURNS + * Status_t See ib_status.h + */ +Status_t mai_close(IBhandle_t fd); + + +#define VFILTER_SHARE (0x000) /* Filter will share MADs */ +#define VFILTER_PURGE (0x002) /* Purge filter MADs on delete */ +#define VFILTER_ONCE (0x008) /* Filter deleted after first match */ + + +/* + * mai_filter_create + * Add a filter to an open channel. This function will add both + * absorbing filters and copy filters. In the case where a new filter + * has been added to absorb Subnet Manager Datatgrams (SMDs), this + * function will notify all other channels that would have received + * that SMD. If the dev, port, qp are not marked active in the filter, + * the default values associated with the handle are assigned to filter. + * + * INPUTS + * fd An open channel (mai_open) to close + * filter The filter to add to the open channel + * flags Flags that modify the filter + * + * RETURNS + * Status_t See ib_status.h + */ +Status_t mai_filter_create(IBhandle_t fd, Filter_t *filter, uint32_t flags); + +/* + * mai_filter_delete + * This functions removes an active filter from an open channel. If + * there are multiple instances of the filter, it removes only the + * first one. + * + * INPUTS + * fd An open channel (mai_open) to use + * filter The filter to remove from the open channel + * flags Flags that modify the filter + * + * RETURNS + * Status_t See ib_status.h + */ +Status_t mai_filter_delete(IBhandle_t fd, Filter_t *filter, uint32_t flags); + + +/* + * mai_send_timeout + * Send an SMD to the hardware channel (QP0/QP1) interface associated with + * the fd (mai_open). This is a synchronous call. The dev, port, qp that the message gets + * sent on is determined by the values in the Mai_t argument. If the these + * are not marked as active the values associated with the handle are assigned to it. + * + * Note that on OFED, the timeout will be passed down to the kernel. This + * does not make the call block, but instead just lets the kernel know how + * long to keep the MAD around on the send list while waiting for an ACK. + * On OFED, when the MAD expires from the kernel send list, incoming responses + * with the same TID will be dropped. + * + * INPUTS + * fd An open channel (mai_open) to send on + * buffer Pointer to MAD to send down + * timeout Send timeout to pass down to the kernel (OFED only) + * + * RETURNS + * Status_t See ib_status.h + */ +Status_t mai_send_timeout(IBhandle_t fd, Mai_t *buffer, uint64_t timeout); +Status_t mai_send_stl_timeout(IBhandle_t fd, Mai_t *buffer, uint32_t *datalen, uint64_t timeout); + +#define MAI_DEFAULT_SEND_TIMEOUT (1ull * VTIMER_1S) +#define mai_send(fd, buffer) mai_send_timeout(fd, buffer, MAI_DEFAULT_SEND_TIMEOUT) +#define mai_stl_send(fd, buffer, datalen) mai_send_stl_timeout(fd, buffer, datalen, MAI_DEFAULT_SEND_TIMEOUT) + +/* + * mai_recv + * Receive the next SMD on the channel opened (mai_open) earlier. The + * MAD must pass the filters (mai_filter_create) added to the open channel. + * A single MAD will be returned no matter how many filters on this channel + * happen to describe that MAD. The return status indicates the normal MAD was + * received or otherwise. MADs coming from the wire have status VSTATUS_OK. + * Otherwise the following values are possible + * VSTATUS_MAI_INTERNAL - an internal message was received + * VSTATUS_FILTER - a filter take-over notice was received. + * + * INPUTS + * fd An open channel (mai_open) to receive on + * buffer Pointer to space to store the received MAD + * timeout The number of microseconds to wait for a MAD; + * a timeout value of 0 means to wait forever + * + * RETURNS + * Status_t See ib_status.h + */ +Status_t mai_recv(IBhandle_t fd, Mai_t *buffer, uint64_t timeout); + + +/* + * FUNCTION + * mai_recv_handles + * + * DESCRIPTION + * This function will wait for a message to be posted to any of the handles + * specified in argument. It returns the index of the lowest handle + * that has a message on it, if a message is received before timeout. + * This index is posted to the location the user passed in, pointed + * by the location pfirst. + * + * INPUTS + * ha Array of handles returned from mai_open + * count Number of handles in array. + * timout How long to wait. 0 means return immediately + * pfirst Where to post the index handle with message on in + * maip Where to post the MAD received on the handle + * + * OUTPUTS + * VSTATUS_OK + * VSTATUS_ILLPARM + * VSTATUS_TIMEOUT + * + * HISTORY + * NAME DATE REMARKS + * JMS 02/16/07 Initial entry + */ +Status_t mai_recv_handles(IBhandle_t *ha, uint32_t count, + uint64_t timeout, uint32_t *pfirst, Mai_t *maip); + +#define MAI_RECV_NOWAIT (0ull) /* Implies mai_recv should not block*/ + +/* + * mai_alloc_tid + * Allocates a unique TID to be set in filters and MADs. + * + * INPUTS + * fd An open channel (mai_open) to use + * mclass The class associated with the TID. + * buf Pointer to place the TID. + * + * RETURNS + * Status_t See ib_status.h + */ +Status_t mai_alloc_tid(IBhandle_t fd, uint8_t mclass, uint64_t *buf); + +/* + * mai_increment_tid + * Given a tid allocated by mai_alloc_tid, computes a new unique TID + * + * INPUTS + * the previous tid + * + * RETURNS + * new tid + */ +uint64_t mai_increment_tid(uint64_t tid); + +/* + * mai_filter_hcreate + * + * DESCRIPTION + * Add a filter to an open channel. This function will add both + * absorbing filters and copy filters. In the case where a new filter + * has been added to absorb SMDs, this function will notify all + * other channels that would have received that SMD. It returns a handle + * to the created filter. + * + * + * INPUTS + * fd Channel number to add the filter to + * filter Pointer to the filter to add to the channel + * flags Flags to modify filter (absorb or copy) + * fh Pointer to the filter handle location + * + * OUTPUTS + * Status_t See ib_status.h + */ +Status_t mai_filter_hcreate(IBhandle_t fd, Filter_t *filter, + uint32_t flags, IBhandle_t *fh); + + +/* + *mai_filter_mclass + * + * DESCRIPTION + * Create a filter that accepts only MADs of a specified mclass. + * + * INPUTS + * devh Device handle returned by mai_open + * flags A set of characteristics to determine behavior. + * - VFILTER_SHARE: Filter shared MAD with other filters + * ftype Filter type + * filterh Filter handle returned by call. + * mclass The class to filter (see ib_mad.h for a list of classes). + * + * OUTPUTS + * Status_t See ib_status.h + */ +Status_t mai_filter_mclass(IBhandle_t devh, uint32_t flags, int ftype, + IBhandle_t *filterh, uint8_t mclass); + +/* + * mai_filter_method + * + * DESCRIPTION + * Create a filter that accepts only MADs of a specified mclass, + * method. + * + * + * INPUTS + * devh Device handle returned by mai_open + * flags A set of characteristics to determine behavior. + * - VFILTER_SHARE: Filter shared MAD with other filters + * ftype Filter type + * filterh Filter handle returned by call. + * mclass The class to filter (see ib_mad.h for a list of classes). + * method The method within the class. + * + * OUTPUTS + * Status_t See ib_status.h + * + */ + +Status_t mai_filter_method(IBhandle_t devh, uint32_t flags, int ftype, + IBhandle_t *filterh, uint8_t mclass, uint8_t method); + + +/* + * mai_filter_aid + * + * DESCRIPTION + * Create a filter that accepts only MADs of a specified mclass, + * method, aid. + * + * INPUTS + * devh Device handle returned by mai_open + * flags A set of characteristics to determine behavior. + * - VFILTER_SHARE: Filter shared MAD with other filters + * ftype Filter type + * filterh Filter handle returned by call. + * mclass The class to filter (see ib_mad.h for a list of classes). + * method The method within the class. + * aid The attribute ID within the method. + * + * OUTPUTS + * Status_t See ib_status.h + * + */ +Status_t mai_filter_aid(IBhandle_t devh, uint32_t flags, int ftype, + IBhandle_t *filterh, + uint8_t mclass, + uint8_t method, + uint16_t aid); + + + +/* + * mai_filter_amod + * + * DESCRIPTION + * Create a filter that accepts only MADs of a specified mclass, + * method, aid, and amod. + * + * INPUTS + * devh Device handle returned by mai_open + * flags A set of characteristics to determine behavior. + * - VFILTER_SHARE - Filter shared MAD with other filters + * ftype Filter type + * filterh Filter handle returned by call. + * mclass The class to filter (see ib_mad.h for a list of classes). + * method The method within the class. + * aid The attribute ID within the method. + * amod The attribute modifier within the aid + * + * OUTPUTS + * Status_t See ib_status.h + */ +Status_t mai_filter_amod(IBhandle_t devh, uint32_t flags, int ftype, + IBhandle_t *filterh, + uint8_t mclass, + uint8_t method, + uint16_t aid, + uint32_t amod); + + + +/* + * mai_filter_handle + * + * DESCRIPTION + * Returns the handle to previously created filter. + * + * INPUTS + * devh Device handle returned by mai_open and used in filter create. + * filter The filter's definition. + * flags A set of characteristics to determine behavior. + * - VFILTER_SHARE - Filter shared MAD with other filters + * fh Pointer to filter handle returned by call. + * + * OUTPUTS + * Status_t See ib_status.h + * + */ + +Status_t mai_filter_handle(IBhandle_t devh, + Filter_t *filter, + uint32_t flags, + IBhandle_t *fh); + +/* + * mai_filter_hdelete + * + * DESCRIPTION + * Removes a filter from a channel. + * + * INPUTS + * devh Device handle returned by mai_open and used in filter create. + * fh Filter handle + * + * OUTPUTS + * Status_t See ib_status.h + * + */ +Status_t mai_filter_hdelete(IBhandle_t devh, IBhandle_t fh); + + +/* + * mai_filter_once + * + * DESCRIPTION + * This routine will create a filter which will accept messages + * for a specified mclass and TID. This routine allows an application + * to issue a request and wait for the reply by filtering on just + * the TID and mclass. After a messAge is received which passes the filter, + * the filter is automatically deleted. + * + * + * INPUTS + * devh Device handle returned by mai_open + * flags A set of characteristics to determine behavior. + * - VFILTER_SHARE: Filter shared MAD with other filters + * ftype Filter type + * filterh Filter handle returned by call. + * mclass The class to filter (see ib_mad.h for a list of classes). + * tid The transaction ID to use. + * + * OUTPUTS + * Status_t See ib_status.h + * + */ +Status_t mai_filter_once(IBhandle_t devh, uint32_t flags, int ftype, + IBhandle_t *filterh, + uint8_t mclass, + uint64_t tid); + + + +/* + * mai_filter_tid + * + * DESCRIPTION + * This routine will create a filter which will accept messages + * for a specified mclass and tid. + * + * + * INPUTS + * devh Device handle returned by mai_open + * flags A set of characteristics to determine behavior. + * - VFILTER_SHARE: Filter shared MAD with other filters + * ftype Filter type + * filterh Filter handle returned by call. + * mclass The class to filter (see ib_mad.h for a list of classes). + * tid The transaction ID to use. + * + * OUTPUTS + * Status_t See ib_status.h + * + */ +Status_t mai_filter_tid(IBhandle_t devh, uint32_t flags, int ftype, + IBhandle_t *filterh, + uint8_t mclass, + uint64_t tid); + + + +/* + * mai_get_stl_portinfo + * + * DESCRIPTION + * This function allows the local user to retrieve the portinfo + * of the local port. + * + * + * INPUTS + * fd MAI handle + * pinfop Pointer to STL_PORT_INFO + * port The port to get + * + * OUTPUTS + * Status_t See ib_status.h + * + */ +Status_t mai_get_stl_portinfo(IBhandle_t fd, STL_PORT_INFO *pinfop, uint8_t port); + + +/* + * FUNCTION + * mai_shutdown + * + * DESCRIPTION + * This function marks the MAI library (at the calling layer) as uninitialized. + * This forces all users of the interface to fail and return. + * + * INPUTS + * None + * + * OUTPUTS + * None + */ + +void mai_shut_down(void); + +/* + * FUNCTION + * mai_get_default_pkey + * + * DESCRIPTION + * This function retrieves the default PKey (index 0) for the adapter. + * + * + * INPUTS + * None + * + * OUTPUTS + */ + +uint16_t mai_get_default_pkey(void); + +#endif /* IB_MAI_G_H */ + + + + + + + + + diff --git a/Esm/ib/include/mal_g.h b/Esm/ib/include/mal_g.h new file mode 100644 index 0000000..c42f994 --- /dev/null +++ b/Esm/ib/include/mal_g.h @@ -0,0 +1,139 @@ +/* BEGIN_ICS_COPYRIGHT2 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + * ** END_ICS_COPYRIGHT2 ****************************************/ + +/* + * MAL - MAI Abstraction Layer + * + * These are the public interfaces to the MAL layer. Historically, this + * layer represented the interface between MAI and the next layer down (CAL). + * + * As of the port to OFED, CAL has been eliminated, and the MAL layer now + * interfaces with the IB stack directly. + */ + +#ifndef _IB_MAL_G_H_ +#define _IB_MAL_G_H_ + +#include + +#ifndef __VXWORKS__ +#include "opamgt_priv.h" +#endif + +extern int ib_instrumentJmMads; + + +#ifndef __VXWORKS__ +/* + * ib_init_devport + * + * Initializes stack interface and binds to the specified + * device and port. + * If *Guidp is 0, *devp and *portp are used to select the device and port + * and *Guidp is returned. + * If *Guidp is not 0, *Guid is used to select the device and port + * and *devp and *portp are returned. + * Guidp may be NULL and/or devp and portp may be NULL + */ +Status_t ib_init_devport(uint32_t *dev, uint32_t *port, uint64_t *Guid, struct omgt_params *session_params); + +/* + * ib_get_devport + * + * Returns current porthandle + */ +struct omgt_port * ib_get_devport(void); +#else +/* + * ib_init_devport + * + * Initializes stack interface and binds to the specified + * device and port. + * If *Guidp is 0, *devp and *portp are used to select the device and port + * and *Guidp is returned. + * If *Guidp is not 0, *Guid is used to select the device and port + * and *devp and *portp are returned. + * Guidp may be NULL and/or devp and portp may be NULL + */ +Status_t ib_init_devport(uint32_t *dev, uint32_t *port, uint64_t *Guid); + +#endif + +/* + * ib_refresh_devport + * + * refreshes pkeys for stack interface + */ +Status_t ib_refresh_devport(void); + +/* + * ib_shutdown + * + * De-initializes stack interface (closes OFED port and releases 'issm' device) + */ +Status_t ib_shutdown(void); + +/* + * ib_register_sm + * + * Registers the SM with the MAL layer. + */ +Status_t ib_register_sm(int queue_size); + +/* + * ib_register_fe + * + * Registers the FE with the MAL layer. + */ +Status_t ib_register_fe(int queue_size, uint8_t thread); + +/* + * ib_register_pm + * + * Registers the PM with the MAL layer. + */ +Status_t ib_register_pm(int queue_size); + + + +/* + * ib_disable_is_sm + * + * Enables the IS_SM capability flag for the currently bound port. + */ +Status_t ib_enable_is_sm(void); + +/* + * ib_disable_is_sm + * + * Disables the IS_SM capability flag on the currently active port. + */ +Status_t ib_disable_is_sm(void); + +#endif // _IB_MAL_G_H_ diff --git a/Esm/ib/include/os_g.h b/Esm/ib/include/os_g.h new file mode 100644 index 0000000..2743c69 --- /dev/null +++ b/Esm/ib/include/os_g.h @@ -0,0 +1,147 @@ +/* BEGIN_ICS_COPYRIGHT2 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + * ** END_ICS_COPYRIGHT2 ****************************************/ + +//---------------------------------------------------------------------// +// // +// FILE NAME // +// os_g.h // +// // +// DESCRIPTION // +// general global include file for OS specific files // +// // +// DATA STRUCTURES // +// None // +// // +// FUNCTIONS // +// None // +// // +// DEPENDENCIES // +// None // +// // +// // +//---------------------------------------------------------------------// + +#ifndef _OS_G_H_ +#define _OS_G_H_ + +//---------------------------------------------------------------------// +// // +// Linux defines. // +// // +//---------------------------------------------------------------------// + +#if defined(__LINUX__) + +//#ifdef CAL_IBACCESS +#include +//#endif + +#include +#include +#include +#include +#include + +/* Get a random number between two numbers. + * a%b will return a value between 0 and b-1 (inclusive). + * By doing rand()%(HIGH-LOW) we get a random index between HIGH and LOW + * Add that value to LOW to get a random number between HIGH and LOW. + */ +#define GET_RANDOM(HIGH, LOW) ((rand() % (HIGH-LOW))+LOW) + +/* Macros for min/max. */ +#ifndef MIN +#define MIN(a,b) (((a)<(b))?(a):(b)) +#endif +#ifndef MAX +#define MAX(a,b) (((a)>(b))?(a):(b)) +#endif + +// ASSERTs which are only tested in DEBUG builds +// x can be a function call or expensive expression, do not evaluate +// it in debug builds +#ifndef DEBUG_ASSERT +#if DEBUG +#define DEBUG_ASSERT(x) ASSERT(x) +#else +#define DEBUG_ASSERT(x) do {} while(0) +#endif +#endif + +//---------------------------------------------------------------------// +// // +// FreeBSD defines. // +// // +//---------------------------------------------------------------------// + +#elif defined(__FreeBSD__) + +//---------------------------------------------------------------------// +// // +// Windows 32 defines. // +// // +//---------------------------------------------------------------------// + +#elif defined(WIN32) + +//---------------------------------------------------------------------// +// // +// __VXWORKS__ defines. // +// // +//---------------------------------------------------------------------// + +#elif defined(__VXWORKS__) +extern unsigned long SystemGetRandom(void); +/* Get a random number between two numbers. + * a%b will return a value between 0 and b-1 (inclusive). + * By doing rand()%(HIGH-LOW) we get a random index between HIGH and LOW + * Add that value to LOW to get a random number between HIGH and LOW. + */ +#define GET_RANDOM(HIGH, LOW) ((SystemGetRandom() % (HIGH-LOW))+LOW) + +/* Macros for min/max. */ +#ifndef MIN +#define MIN(a,b) (((a)<(b))?(a):(b)) +#endif +#ifndef MAX +#define MAX(a,b) (((a)>(b))?(a):(b)) +#endif + +//---------------------------------------------------------------------// +// // +// Unknown OS defines. // +// // +//---------------------------------------------------------------------// + +#else + +#endif + +#endif // _OS_G_H_ + diff --git a/Esm/ib/include/stleep_msg.h b/Esm/ib/include/stleep_msg.h new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/Esm/ib/include/stleep_msg.h diff --git a/Esm/ib/include/vfi_g.h b/Esm/ib/include/vfi_g.h new file mode 100644 index 0000000..8b68c80 --- /dev/null +++ b/Esm/ib/include/vfi_g.h @@ -0,0 +1,88 @@ +/* BEGIN_ICS_COPYRIGHT2 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + * ** END_ICS_COPYRIGHT2 ****************************************/ + +/************************************************************************ +* * +* FILE NAME * +* if3.h * +* * +* DESCRIPTION * +* Library calls for interface 3 * +* * +* * +* DEPENDENCIES * +* ib_types.h * +* * +* * +************************************************************************/ + +#ifndef ___VFI_G_H___ +#define ___VFI_G_H___ + +#include "ib_types.h" +#include "mai_g.h" +#include "ib_sa.h" +#include "stl_sa_priv.h" + +#define VFI_DEFAULT_GUID (0) + +#define VFI_SERVICE_RECORD IB_SERVICE_RECORD +#define VFI_SVRREC_ID IB_SERVICE_RECORD_COMP_SERVICEID +#define VFI_SVRREC_GID IB_SERVICE_RECORD_COMP_SERVICEGID +#define VFI_SVREC_NAME IB_SERVICE_RECORD_COMP_SERVICENAME +#define VFI_SVREC_PARTITION IB_SERVICE_RECORD_COMP_SERVICEPKEY +#define VFI_SVREC_LEASE IB_SERVICE_RECORD_COMP_SERVICELEASE +#define VFI_SVREC_KEY IB_SERVICE_RECORD_COMP_SERVICEKEY + +#define VFI_REGFORCE_FABRIC (0x01) +#define VFI_REGTRY_FABRIC (0x00) + +#define VFI_LMC_BASELID (0x00) +#define VFI_MAX_LMC (7) /* Maximum value the lmc 3 bits allow */ + +#define VFI_MAX_SERVICE_PATH (128) +#define VFI_MAX_PORT_GUID (7) /* The maximum guid index */ + +typedef int (*VfiSvcRecCmp_t)(VFI_SERVICE_RECORD *, VFI_SERVICE_RECORD *); + +Status_t vfi_mngr_register(IBhandle_t fd, uint8_t mclass, + int gididx, VFI_SERVICE_RECORD * service, + uint64_t mask, int option); +Status_t vfi_mngr_unregister(IBhandle_t fd, uint8_t mclass, + int gididx, VFI_SERVICE_RECORD * service, + uint64_t mask); +Status_t vfi_mngr_find(IBhandle_t fd, uint8_t mclass, + int slmc, VFI_SERVICE_RECORD * service, uint64_t mask, + int *count, IB_PATH_RECORD * pbuff); + +Status_t vfi_mngr_find_cmp(IBhandle_t fd, uint8_t mclass, + int slmc, VFI_SERVICE_RECORD * service, uint64_t mask, + int *count, IB_PATH_RECORD * pbuff, VfiSvcRecCmp_t cmp); + +#endif diff --git a/Esm/ib/include/vs_g.h b/Esm/ib/include/vs_g.h new file mode 100644 index 0000000..48173a1 --- /dev/null +++ b/Esm/ib/include/vs_g.h @@ -0,0 +1,506 @@ +/* BEGIN_ICS_COPYRIGHT2 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + * ** END_ICS_COPYRIGHT2 ****************************************/ + +/************************************************************************ + * + * FILE NAME + * vs_g.h + * + * DESCRIPTION + * OS Abstraction Layer Header + * + * DATA STRUCTURES + * + * FUNCTIONS + * vs_time_get Get OS independent uS since epoch + * + * + * DEPENDENCIES + * ib_types.h + * ib_status.h + * + * + * HISTORY + * + * NAME DATE REMARKS + * dkj 02/27/02 Initial creation of file. + * pjg 02/27/02 Moved vs_time_get to here. + * pjg 02/28/02 Move VEVENT_WAKE_* from cs_g.h + * sfw 03/05/02 Added initial Thread support + * dkj 03/05/02 Added vs_pool services + * dkj 03/06/02 Added additional vs_pool services + * sfw 03/07/02 Added comments for new functions implemented + * pjg 03/11/02 Increase OPAQUE_THREAD_ELEMENTS. + * dkj 03/12/02 Increase OPAQUE_POOL_ELEMENTS. + * dkj 03/14/02 Updated passing functions list + * dkj 03/18/02 Added vs_pool_page_size + * mgr 03/18/02 Added counting semaphore support. + * dkj 03/19/02 Updated events to use New locks + * sfw 03/20/02 Added flag to indicate is prefixed to prototypes + * dkj 03/21/02 Updated vs_pool_create prototype + * dkj 03/22/02 More Pool prototype cleanup + * dkj 04/01/02 PR 1676. vs_pool* prototype per OS API 2.0g + * pjg 04/02/02 PR 1676. vs_thread_sleep prototype per OS API 2.0g + * dkj 04/02/02 PR 1676. vs_event* prototype per OS API 2.0g + * mgr 04/02/02 PR 1651. Added user_flag to Thread_t structure. + * dkj 04/04/02 PR 1676. vs_thread_create prototype per OS API 2.0g + * mgr 04/04/02 PR 1676. vs_lock_init prototype per OS API 2.0g + ************************************************************************/ + +/************************************************************************ + * The following is a list of functions that successfully pass testing + * and in which environments. + * + * vs_event_*() - Linux Kernel, Linux User + * vs_time_get() - Linux Kernel, Linux User + * vs_thread_*() - Linux Kernel, Linux User + * vs_pool_create() - Linux Kernel, Linux User + * vs_pool_delete() - Linux Kernel, Linux User + * vs_pool_alloc() - Linux Kernel, Linux User + * vs_pool_free() - Linux Kernel, Linux User + * vs_pool_page_size() - Linux Kernel, Linux User, ATI + ************************************************************************/ + + +#ifndef __VS_G_ +#define __VS_G_ + +#include +#include +#include +#include + +#ifndef MIN +#define MIN(a,b) ((a)<(b)?(a):(b)) +#endif + +#define VS_NAME_MAX (16U) + +/*=== Locks ===*/ +#define VLOCK_LOCKED (0) /* Initialize to locked */ +#define VLOCK_FREE (1) /* Initialze lock to free */ +#define VLOCK_SPIN (3) /* Initialize spin lock */ +#define VLOCK_THREAD (4) /* Initialize thread lock */ +#define VLOCK_RWTHREAD (5) /* Initialize rw thread lock */ + +#define OPAQUE_LOCK_ELEMENTS (18U) +#define VLOCK_THREADLOCK_MAGIC (0x283CB160UL) +#define VLOCK_RWTHREADLOCK_MAGIC (0x283CB185UL) +#define VLOCK_SPINLOCK_MAGIC (0xAF22AE30UL) +typedef volatile struct +{ + uint32_t type; /* type of lock (VLOCK_SPIN, VLOCK_RWTHREAD or VLOCK_THREAD) */ + uint32_t status; /* status of lock (VLOCK_LOCKED or VLOCK_FREE) */ + uint32_t magic; /* magic of lock (VLOCK_THREAD/SPINLOCK_MAGIC) */ + + /* implementation private data */ + uint64_t opaque[OPAQUE_LOCK_ELEMENTS]; +} +Lock_t; + +extern Status_t vs_lock_init (Lock_t * handle, + unsigned int state, + unsigned int type); +extern Status_t vs_lock_delete (Lock_t * handle); +extern Status_t vs_lock (Lock_t * handle); // for THREAD +extern Status_t vs_unlock (Lock_t * handle); // for THREAD +extern Status_t vs_wrlock (Lock_t * handle); // for RWTHREAD +extern Status_t vs_rdlock (Lock_t * handle); // for RWTHREAD +extern Status_t vs_rwunlock (Lock_t * handle); // for RWTHREAD +extern Status_t vs_spinlock (Lock_t * handle); // for SPIN +extern Status_t vs_spinunlock (Lock_t * handle); // for SPIN + +/*=== Locks ===*/ + +/*=== Events ===*/ + +typedef void *Evt_handle_t; +typedef uint32_t Eventset_t; +#define VEVENT_NUM_EVENTS (sizeof(Eventset_t) << 3) +#define OPAQUE_EVENT_ELEMENTS (25U) +typedef struct +{ + unsigned char name[VS_NAME_MAX]; + Evt_handle_t event_handle; + uint64_t opaque[OPAQUE_EVENT_ELEMENTS]; +} +Event_t; +/* +** Creates a set of global events and associates a name with the +** event set. +*/ +extern Status_t vs_event_create (Event_t * ec, unsigned char name[], + Eventset_t state); +/* +** Deletes the specified event set. +*/ +extern Status_t vs_event_delete (Event_t * ec); +/* +** Wait for any of specified events. +*/ +extern Status_t vs_event_wait (Evt_handle_t handle, uint64_t timeout, + Eventset_t mask, Eventset_t * events); +/* +** Post a set of events. +*/ +extern Status_t vs_event_post (Evt_handle_t handle, uint32_t option, + Eventset_t mask); +#define VEVENT_WAKE_ONE (1) /* Wake one thread waiting */ +#define VEVENT_WAKE_ALL (2) /* Wake all threads in vs_event_wait() */ + // BEWARE, a WAKE_ALL before there are waiters will cause + // the waiters to still wait for the next WAKE_ALL or WAKE_ONE + +/*=== Events ===*/ + +/*=== Time ===*/ + +/* + * vs_time_get + * Return a 64 bit number of uSecs since some epoch. This function must + * return a monotonically increasing sequence. The actual granularity of + * time is dependent on the OS/HW you are running on. + * + * INPUTS + * loc Where to put the time value + * + * RETURNS + * VSTATUS_OK + * VSTATUS_ILLPARM + */ +Status_t vs_time_get (uint64_t * loc); + +#define VTIMER_1S 1000000ull +#define VTIMER_1_MILLISEC 1000ull +#define VTIMER_10_MILLISEC 10000ull +#define VTIMER_100_MILLISEC 100000ull +#define VTIMER_200_MILLISEC 200000ull +#define VTIMER_500_MILLISEC 500000ull +#define VTIMER_ETERNITY 0x0100000000000000ull +#define TIMER_1S (1000000ull) +#define TIMER_ETERNITY (0x0100000000000000ull) + +/* + * vs_stdtime_get - get current time as a time_t, seconds since 1970 + */ +Status_t vs_stdtime_get(time_t *address); +/*=== Time ===*/ + +/*=== Core Dumps ===*/ +// Translate CoreDumpLimit string to a rlimit value +// returns 0 on success, -1 on error +// value argument is optional, if NULL just checks str is valid CoreDumpLimit +// str can be a byte count or "unlimited" +int vs_getCoreDumpLimit(const char* str, uint64_t* value); + +#ifndef __VXWORKS__ +/* + * vs_init_coredump_settings - setup coredump config for this process + * note this changes the current directory + */ +void vs_init_coredump_settings(const char* mgr, const char* limit, const char *dir); +#endif +/*=== Core Dumps ===*/ + +/*=== Threads ===*/ + +#define OPAQUE_THREAD_ELEMENTS (96U) /* XXXXX for now */ + +typedef uint64_t Threadname_t; + +typedef struct New_Thread +{ + unsigned char name[VS_NAME_MAX]; + uint32_t magic; + unsigned int user_flag; + int priority; + + struct Thread *next; /* XXXXXX maybe will use these */ + struct Thread *prev; + + uint64_t opaque[OPAQUE_THREAD_ELEMENTS]; +} +Thread_t; + +/* +** Create a thread. +*/ +extern Status_t +vs_thread_create (Thread_t * thr, + unsigned char * name, + void (*function) (uint32_t, uint8_t **), + uint32_t argc, + uint8_t * argv[], + size_t stack_size); + +/* +** Create a thread and copy its argv vector. +*/ +extern Status_t +vs_thread_create2(Thread_t * thr, + unsigned char * name, + void (*function) (uint32_t, uint8_t **), + uint32_t argc, + uint8_t * argv[], + size_t stack_size); + +/* +** Query the threadname associated with the current thread +*/ +extern Status_t vs_thread_name (Threadname_t * threadname); + +/* +** Query the thread name string associated with the current thread +*/ +extern const char *vs_thread_name_str (void); + +/* +** Query the threadname group associated with the current +** thread +*/ +extern Status_t +vs_thread_groupname (Threadname_t threadname, + Threadname_t * groupname); + +/* +** Kill the specified thread +*/ +extern Status_t vs_thread_kill (Thread_t * handle); + +/* +** Exit the current thread, does not return on success. +*/ +extern Status_t vs_thread_exit (Thread_t * handle); + +/* +** Sleep for sleeptime microseconds. +*/ +extern void vs_thread_sleep (uint64_t sleep_time); + +/* +** Wait for the specified thread to exit. +*/ +extern Status_t +vs_thread_join (Thread_t *handle, void **value_ptr); + +/* + ** set name for the calling thread +*/ +extern int vs_thread_setname(char* name); + +/*=== Threads ===*/ + +/*=== Pool Services ===*/ +#define VMEM_PAGE (0x00000008) /* Return page aligned chunks */ + + +#define DELETE_MARKER 0xCECE + +#ifndef USE_POOL_LOCK +#define USE_POOL_LOCK 1 +#endif + +#define OPAQUE_POOL_ELEMENTS (8U) + +typedef struct +{ + unsigned char name[VS_NAME_MAX]; + uint32_t options; + uint32_t magic; +#if USE_POOL_LOCK + Lock_t lock; +#endif /* USE_POOL_LOCK */ + size_t pagesize; + uint64_t opaque[OPAQUE_POOL_ELEMENTS]; +} +Pool_t; +/* + * vs_pool_create + * Create a memory allocation pool. Assign attributes to how memory is + * allocated out of the pool. + */ +Status_t vs_pool_create (Pool_t * handle, uint32_t options, + unsigned char *name, void *address, size_t size); +/* + * vs_pool_delete + * Release a pool. + */ +Status_t vs_pool_delete (Pool_t * handle); +/* + * vs_pool_alloc + * Allocate a sub-chunk from an existing pool. The region will be + * allocated according to the options given when the pool was created. + */ +Status_t vs_pool_alloc (Pool_t * handle, size_t length, void **loc); +/* + * vs_pool_free + * Release a chunk of memory allocated using vs_pool_alloc() + */ +Status_t vs_pool_free (Pool_t * handle, void *loc); +/* + * vs_pool_size + * Return current size of pool (for dev debug) + */ +Status_t vs_pool_size(Pool_t * handle, uint64_t *numBytesAlloc); + +/* + * vs_pool_page_size + * Obtain the native memory page size in bytes. + */ +size_t vs_pool_page_size (void); +/*=== Pool Services ===*/ + +/*=== Basic Allocation ==*/ + +#define vs_malloc(LENGTH) malloc(LENGTH) +#define vs_free(ADDR) free(ADDR) +/*=== Basic Allocation ==*/ + +/*=== Semaphores ===*/ +#define SEMAPHORE_MAGIC (0xCB283037UL) +#ifdef __VXWORKS__ +#include "semLib.h" +#else +#include +#endif + +typedef volatile struct +{ + uint32_t magic; +#ifdef __VXWORKS__ + SEM_ID semId; + int32_t count; +#else +sem_t osdSema; +#endif +} +Sema_t; + +// +// MWHEINZ FIXME: Why are the cs_ functions prototyped here and not in cs_g.h? +// +#define CS_SEMA_WAIT_FOREVER -1 +#define CS_SEMA_NO_WAIT 0 +extern Status_t cs_sema_create (Sema_t * handle, uint32_t count); +extern Status_t cs_sema_delete (Sema_t * handle); +extern Status_t cs_vsema (Sema_t * handle); +extern Status_t cs_psema (Sema_t * handle); +extern Status_t cs_sema_getcount(Sema_t * handle, int *cnt); +/* wait on a semaphore for desired number of seconds */ +extern Status_t cs_psema_wait (Sema_t * handle, int timeout); +/*=== Semaphores ===*/ + +/*=== String Operations ===*/ +/* max/min values for uint*_t and int*_t */ +#ifndef UINT8_MAX +#define UINT8_MAX 255 +#endif + +#ifndef UINT8_MIN +#define UINT8_MIN 0 +#endif + +#ifndef INT8_MAX +#define INT8_MAX 127 +#endif + +#ifndef INT8_MIN +#define INT8_MIN (-128) +#endif + +#ifndef UINT16_MAX +#define UINT16_MAX 65535 +#endif + +#ifndef UINT16_MIN +#define UINT16_MIN 0 +#endif + +#ifndef INT16_MAX +#define INT16_MAX 32767 +#endif + +#ifndef INT16_MIN +#define INT16_MIN (-32768) +#endif + +#ifndef UINT32_MAX +#define UINT32_MAX 4294967295U +#endif + +#ifndef UINT32_MIN +#define UINT32_MIN 0 +#endif + +#ifndef INT32_MAX +#define INT32_MAX 2147483647 +#endif + +#ifndef INT32_MIN +#define INT32_MIN (-INT32_MAX -1) +#endif + +#ifndef UINT64_MAX +#define UINT64_MAX 18446744073709551615ULL +#endif + +#ifndef UINT64_MIN +#define UINT64_MIN 0 +#endif + +#ifndef INT64_MAX +#define INT64_MAX 9223372036854775807LL +#endif + +#ifndef INT64_MIN +#define INT64_MIN (-INT64_MAX - 1LL) +#endif + +extern uint8_t cs_strtoui8 (const char *nptr, uint8_t return_error); +extern uint16_t cs_strtoui16 (const char *nptr, uint16_t return_error); +extern uint32_t cs_strtoui32 (const char *nptr, uint32_t return_error); +extern uint64_t cs_strtoui64 (const char *nptr, uint64_t return_error); +extern int8_t cs_strtoi8 (const char *nptr, int8_t return_error); +extern int16_t cs_strtoi16 (const char *nptr, int16_t return_error); +extern int32_t cs_strtoi32 (const char *nptr, int32_t return_error); +extern int64_t cs_strtoi64 (const char *nptr, int64_t return_error); +extern Status_t cs_parse_gid (const char * str, Gid_t gid); + +extern char *cs_getAidName(uint16_t, uint16_t); +extern char *cs_getMethodText(uint8_t); + +extern int cs_snprintfcat(char ** buf, size_t * len, char * fmt, ...) __attribute__((format(printf,3,4))); +/*=== String Operations ===*/ + +/*=== Computational Utility Functions ===*/ +extern uint32_t cs_numSwitches(uint32_t subnet_size); +extern uint32_t cs_numNodeRecords(uint32_t subnet_size); +extern uint32_t cs_numPortRecords(uint32_t subnet_size); +extern uint32_t cs_numLinkRecords(uint32_t subnet_size); +/*=== Computational Utility Functions ===*/ +#endif diff --git a/Esm/ib/src/config/Makefile b/Esm/ib/src/config/Makefile new file mode 100644 index 0000000..0d524df --- /dev/null +++ b/Esm/ib/src/config/Makefile @@ -0,0 +1,161 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** +# Makefile for SM Module + +# Include Make Control Settings +include $(TL_DIR)/$(PROJ_FILE_DIR)/Makesettings.project + +#=============================================================================# +# Definitions: +#-----------------------------------------------------------------------------# + +# Name of SubProjects +DS_SUBPROJECTS = +# name of executable or downloadable image +EXECUTABLE = # config$(EXE_SUFFIX) +# list of sub directories to build +DIRS = +# C files (.c) +CFILES = \ + fm_xml.c \ + fm_digest.c \ + # Add more c files here +# C++ files (.cpp) +CCFILES = \ + # Add more cpp files here +# lex files (.lex) +LFILES = \ + # Add more lex files here +# archive library files (basename, $ARFILES will add MOD_LIB_DIR/prefix and suffix) +LIBFILES= +# Windows Resource Files (.rc) +RSCFILES = +# Windows IDL File (.idl) +IDLFILE = +# Windows Linker Module Definitions (.def) file for dll's +DEFFILE = +# targets to build during INCLUDES phase (add public includes here) +INCLUDE_TARGETS = \ + fm_digest.h \ + # Add more h hpp files here +# Non-compiled files +MISC_FILES = +# all source files +SOURCES = $(CFILES) $(CCFILES) $(LFILES) $(RSCFILES) $(IDLFILE) +# Source files to include in DSP File +DSP_SOURCES = $(INCLUDE_TARGETS) $(SOURCES) $(MISC_FILES) \ + $(RSCFILES) $(DEFFILE) $(MAKEFILE) +# all object files +OBJECTS = $(CFILES:.c=$(OBJ_SUFFIX)) $(CCFILES:.cpp=$(OBJ_SUFFIX)) \ + $(LFILES:.lex=$(OBJ_SUFFIX)) +RSCOBJECTS = $(RSCFILES:.rc=$(RES_SUFFIX)) +# targets to build during LIBS phase +LIB_TARGETS_IMPLIB = +LIB_TARGETS_ARLIB = $(LIB_PREFIX)config$(ARLIB_SUFFIX) +LIB_TARGETS_EXP = $(LIB_TARGETS_IMPLIB:$(ARLIB_SUFFIX)=$(EXP_SUFFIX)) +LIB_TARGETS_MISC = +# targets to build during CMDS phase +CMD_TARGETS_SHLIB = +CMD_TARGETS_EXE = $(EXECUTABLE) +CMD_TARGETS_MISC = +# files to remove during clean phase +CLEAN_TARGETS_MISC = +CLEAN_TARGETS = $(OBJECTS) $(RSCOBJECTS) $(IDL_TARGETS) $(CLEAN_TARGETS_MISC) +# other files to remove during clobber phase +CLOBBER_TARGETS_MISC= +# sub-directory to install to within bin +BIN_SUBDIR = +# sub-directory to install to within include +INCLUDE_SUBDIR = + +# Additional Settings +#CLOCALDEBUG = User defined C debugging compilation flags [Empty] +#CCLOCALDEBUG = User defined C++ debugging compilation flags [Empty] +#CLOCAL = User defined C flags for compiling [Empty] +#CCLOCAL = User defined C++ flags for compiling [Empty] +#BSCLOCAL = User flags for Browse File Builder [Empty] +#DEPENDLOCAL = user defined makedepend flags [Empty] +#LINTLOCAL = User defined lint flags [Empty] +#LOCAL_INCLUDE_DIRS = User include directories to search for C/C++ headers [Empty] +#LDLOCAL = User defined C flags for linking [Empty] +#IMPLIBLOCAL = User flags for Object Lirary Manager [Empty] +#MIDLLOCAL = User flags for IDL compiler [Empty] +#RSCLOCAL = User flags for resource compiler [Empty] +#LOCALDEPLIBS = User libraries to include in dependencies [Empty] +#LOCALLIBS = User libraries to use when linking [Empty] +# (in addition to LOCALDEPLIBS) +#LOCAL_LIB_DIRS = User library directories for libpaths [Empty] + +CLOCAL = $(CPIE) +LOCALDEPLIBS = + +PROJ_SM_DIR ?= $(TL_DIR)/Esm/ib + +# Include Make Rules definitions and rules +ifneq "$(PROJ_SM_DIR)" "" +include $(PROJ_SM_DIR)/Makerules.module +endif + +#=============================================================================# +# Overrides: +#-----------------------------------------------------------------------------# +#CCOPT = # C++ optimization flags, default lets build config decide +#COPT = # C optimization flags, default lets build config decide +#SUBSYSTEM = Subsystem to build for (none, console or windows) [none] +# (Windows Only) +#USEMFC = How Windows MFC should be used (none, static, shared, no_mfc) [none] +# (Windows Only) +#=============================================================================# + +#=============================================================================# +# Rules: +#-----------------------------------------------------------------------------# +# process Sub-directories +include $(TL_DIR)/Makerules/Maketargets.toplevel + +# build cmds and libs +include $(TL_DIR)/Makerules/Maketargets.build + +# install for includes, libs and cmds phases +include $(TL_DIR)/Makerules/Maketargets.install + +# install for stage phase +#include $(TL_DIR)/Makerules/Maketargets.stage +STAGE:: + +# Unit test execution +#include $(TL_DIR)/Makerules/Maketargets.runtest + +clobber:: clobber_module + +#=============================================================================# + +#=============================================================================# +# DO NOT DELETE THIS LINE -- make depend depends on it. +#=============================================================================# diff --git a/Esm/ib/src/config/README b/Esm/ib/src/config/README new file mode 100644 index 0000000..75725df --- /dev/null +++ b/Esm/ib/src/config/README @@ -0,0 +1,41 @@ +/* BEGIN_ICS_COPYRIGHT10 **************************************** + +Copyright (c) 2015, Intel Corporation +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: +- Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. +- Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. +- Neither the name of Intel Corporation nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL INTEL, THE COPYRIGHT OWNER OR CONTRIBUTORS +BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. + +EXPORT LAWS: THIS LICENSE ADDS NO RESTRICTIONS TO THE EXPORT LAWS OF YOUR +JURISDICTION. It is licensee's responsibility to comply with any export +regulations applicable in licensee's jurisdiction. Under CURRENT (May 2000) +U.S. export regulations this software is eligible for export from the U.S. +and can be downloaded by or otherwise exported or reexported worldwide EXCEPT +to U.S. embargoed destinations which include Cuba, Iraq, Libya, North Korea, +Iran, Syria, Sudan, Afghanistan and any other country to which the U.S. has +embargoed goods and services. + +** END_ICS_COPYRIGHT10 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ +the XML config file parser and config services for the FM diff --git a/Esm/ib/src/config/fm_digest.c b/Esm/ib/src/config/fm_digest.c new file mode 100644 index 0000000..7a2b295 --- /dev/null +++ b/Esm/ib/src/config/fm_digest.c @@ -0,0 +1,70 @@ +/* BEGIN_ICS_COPYRIGHT5 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + * ** END_ICS_COPYRIGHT5 ****************************************/ + +#include "fm_digest.h" + +#include +#include +#include +#include +#include +#include +#include "ib_types.h" + +fm_digest_t * fm_digest_start(void) +{ + fm_digest_t * ctx = EVP_MD_CTX_create(); + if (!ctx) return NULL; + if (!EVP_DigestInit_ex(ctx, EVP_sha256(), NULL)) { + EVP_MD_CTX_destroy(ctx); + return NULL; + } + return ctx; +} + +int fm_digest_update(fm_digest_t *ctx, const void *data, size_t len) +{ + return EVP_DigestUpdate(ctx, data, len); +} + +int fm_digest_finish(fm_digest_t *ctx, uint8_t *digest) +{ + unsigned int len; + if (EVP_DigestFinal_ex(ctx, digest, &len) != 1) + return 0; + EVP_MD_CTX_destroy(ctx); + return 1; + +} + +int fm_digest_len(fm_digest_t *ctx) +{ + return EVP_MD_CTX_size(ctx); +} + diff --git a/Esm/ib/src/config/fm_digest.h b/Esm/ib/src/config/fm_digest.h new file mode 100644 index 0000000..7d6a41e --- /dev/null +++ b/Esm/ib/src/config/fm_digest.h @@ -0,0 +1,50 @@ +/* BEGIN_ICS_COPYRIGHT2 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT2 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +#ifndef _FM_DIGEST_HELPER_H_ +#define _FM_DIGEST_HELPER_H_ + +#include +#include +#include +#include + +typedef EVP_MD_CTX fm_digest_t; + +// maximum length in bytes of a hash across all supported digests +#define FM_DIGEST_MAX 32 + +fm_digest_t * fm_digest_start(void); +int fm_digest_update(fm_digest_t *ctx, const void *data, size_t len); +int fm_digest_finish(fm_digest_t *ctx, uint8_t *digest); +int fm_digest_len(fm_digest_t * ctx); + +#endif diff --git a/Esm/ib/src/config/fm_xml.c b/Esm/ib/src/config/fm_xml.c new file mode 100644 index 0000000..3acb6b1 --- /dev/null +++ b/Esm/ib/src/config/fm_xml.c @@ -0,0 +1,11195 @@ +/* BEGIN_ICS_COPYRIGHT5 **************************************** + +Copyright (c) 2015-2018, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + * ** END_ICS_COPYRIGHT5 ****************************************/ + +#include +#include +#include +#include +#include +#include +#include "if3.h" + + +#include "ib_sm.h" +#include + +#ifndef __VXWORKS__ +#include +#include // Needed for getFacility / showFacility +#include +#endif +#include +#include +#include +#include +#include +#define _GNU_SOURCE + +#include "fm_digest.h" + +#ifdef __VXWORKS__ +#include "Ism_Idb.h" +#include "ioLib.h" +#include "bspcommon/h/icsBspUtil.h" +#include "bspcommon/h/sysFlash.h" +#include "bspcommon/h/opafm_cfg.h" +#include "config_compression.h" +#include "ib_types.h" +#include "tms/common/rdHelper.h" +#include + +#include "sftp.h" +#include "bspcommon/h/configDirName.h" +extern STATUS rm (const char *fileName); + +void updateLastScpRetCode(scpFastFabricRetCode_t retCode) { + Sftp_updateLastScpRetCode(retCode); +} + +extern uint32_t sm_state; +extern size_t g_smPoolSize; +extern Status_t initSmMemoryPool(void); +extern Status_t freeSmMemoryPool(void); +extern Status_t vs_pool_delete (Pool_t * handle); +extern void* getEsmXmlParserMemory(uint32_t size, char* info); +extern void freeEsmXmlParserMemory(void *address, uint32_t size, char* info); +#if defined(__VXWORKS__) +extern void idbSmGetManagersToStart(int * pm, int * fe); +extern STATUS cmuRed_cfgIfMasterSyncSlavePEM(char *pem_filename); +extern STATUS cmuRed_cfgIfMasterSyncSlave(char *remote); +#endif + +static int debug_log = 0; +#define SCP_LOG( fmt, args... ) \ + do{ \ + if( debug_log ) { \ + sysPrintf( "[%08x] scp: " fmt "\n", taskIdSelf(), ## args ); \ + } \ + } while(0) + +uint32_t scpInProcess = 0; +#endif // __VXWORKS__ + +#define PORTS_ALLOC_UNIT 8 + +#ifndef __VXWORKS__ +extern int kmAdvancedFeatureVerification(char* keyString); +#define IFS_FM_CFG_NAME "/etc/opa-fm/opafm.xml" +#define FM_SSL_SECURITY_DIR "/usr/local/ssl/opafm" +#else +#define FM_SSL_SECURITY_DIR DIR_BASE_NAME +#endif + +static FMXmlCompositeConfig_t *configp = NULL; +static DGConfig_t *dgp; +static AppConfig_t *app; +static SMXmlConfig_t *smp; +static SMMcastDefGrp_t *mdgp; +static PmPortGroupXmlConfig_t *pgp; + +static SMMcastDefGrp_t mdgEmpty; + +static uint32_t instance; +static uint32_t common; +static uint32_t fm_instance; +static uint32_t end_instance; +static uint32_t full_parse; +static uint32_t preverify_parse; +static uint32_t embedded_call; +static uint32_t vfInstance; +static uint32_t qosInstance; +static uint32_t PmPgInstance; +static uint32_t PmPgMonitorInstance; +static uint32_t appInstance; +static uint32_t groupInstance; +static uint32_t fullMemInstance; +static uint32_t limitedMemInstance; +static uint32_t systemImageInstance; +static uint32_t nodeGuidInstance; +static uint32_t portGuidInstance; +static uint32_t nodeDescInstance; +static uint32_t includedGroupInstance; +static uint32_t serviceIdInstance; +static uint32_t serviceIdRangeInstance; +static uint32_t serviceIdMaskedInstance; +static uint32_t mgidInstance; +static uint32_t mgidRangeInstance; +static uint32_t mgidMaskedInstance; +static uint32_t dgMgidInstance; +static uint32_t dgMgidRangeInstance; +static uint32_t dgMgidMaskedInstance; +static uint32_t includedAppInstance; +static uint32_t defaultGroupInstance; +static uint32_t mlidSharedInstance; +static uint32_t feTrapSubInstance; + +static boolean newStyleVFs = FALSE; +static boolean oldStyleVFs = FALSE; + + +static XmlNode_t *last_node_description; +static RegExp_t *last_reg_expr; +static XmlIncGroup_t *last_included_group; + +static uint8_t xml_vf_debug; +static uint8_t xml_sm_debug; +static uint8_t xml_fe_debug; +static uint8_t xml_pm_debug; +static uint8_t xml_parse_debug; + +static uint32_t memory_limit; + +#ifdef XML_MEMORY +static uint8_t xml_memory_debug = 1; +#else +static uint8_t xml_memory_debug = 0; +#endif + +// Forward declared routines. +static VFConfig_t* getVfObject(void); +static QosConfig_t* getQosObject(void); +static DGConfig_t* getGroupObject(void); +static int8_t cloneGroup(DGConfig_t *source, DGConfig_t *dest, int freeObjectBeforeCopy); +static AppConfig_t *dupApplicationObject(AppConfig_t *obj); +static FSTATUS CheckMLIDShareOverlapping(uint32_t fm, FMXmlCompositeConfig_t *config); +static void freeApplicationObject(AppConfig_t *app); +static void freeQosgInfo(QosXmlConfig_t *qos); + + + +// callback functions for allocating/freeing memory +static void* (*get_memory)(uint32_t size, const char* info) = NULL; +static void (*free_memory)(void *address, uint32_t size, const char* info) = NULL; + +// memory usage tracking +static uint32_t memory; + +// parsing in process +static uint32_t parsingInProcess = 0; + +// function declarations - only ones that are required due to function ordering +static void freeGroupObject(DGConfig_t *group, uint8_t full); + +#ifndef XML_TEST +void XmlParsePrintError(const char *message) +{ + IB_LOG_ERROR0(Log_StrDup(message)); + fprintf(stderr, "%s\n", message); +} + + +static void XmlParsePrintWarning(const char *message) +{ + IB_LOG_WARN0(Log_StrDup(message)); + fprintf(stderr, "%s\n", message); +} +#endif + +// return buffer that is the uncompressed data from an XML config file +int getXMLConfigData(uint8_t *buffer, uint32_t bufflen, uint32_t *filelen) +{ + uint32_t nextByte = 0; + uint32_t index = 0; + + if (parsingInProcess || !buffer || !filelen) + return -1; + + // open the file +#ifdef __VXWORKS__ + if (scpInProcess) + return -1; + if(copyFile(IFS_FM_CFG_NAME, IFS_FM_CFG_NAME_UNCOMPRESSED, 1,NULL)) { + IB_LOG_ERROR("Error decompressing ESM config file! rc:",0x0020); + return -1; + } + FILE *file = fopen( IFS_FM_CFG_NAME_UNCOMPRESSED, "r" ); +#else + FILE *file = fopen( IFS_FM_CFG_NAME, "r" ); +#endif + + if (!file) { + IB_LOG_ERROR("Error opening ESM config file! rc:",0x0020); + return -1; + } + + while((nextByte = fgetc(file)) != EOF) { + buffer[index++] = nextByte; + if (index >= bufflen) { + *filelen = 0; + IB_LOG_ERROR("Buffer overrun geting ESM config file! rc:",0x0020); + fclose(file); + return -1; + } + } + *filelen = index; + + fclose(file); +#ifdef __VXWORKS__ + remove( IFS_FM_CFG_NAME_UNCOMPRESSED ); +#endif + + return 0; +} + +// take a buffer that is uncompressed and replace the XML config file +int putXMLConfigData(uint8_t *buffer, uint32_t filelen) +{ + uint32_t index = 0; + + if (parsingInProcess || !buffer || !filelen) + return -1; + + // open the file +#ifdef __VXWORKS__ + if (scpInProcess) + return -1; + scpInProcess = 1; + remove( IFS_FM_CFG_NAME_UNCOMPRESSED ); + FILE *file = fopen( IFS_FM_CFG_NAME_UNCOMPRESSED, "w"); + if (!file) { + IB_LOG_ERROR("Error opening ESM config file! rc:",0x0020); + scpInProcess = 0; + return -1; + } +#else + remove( IFS_FM_CFG_NAME ); + FILE *file = fopen( IFS_FM_CFG_NAME, "w"); + if (!file) { + IB_LOG_ERROR("Error opening ESM config file! rc:",0x0020); + return -1; + } +#endif + for (index = 0; index < filelen; index++) { + fputc(buffer[index], file); + } + fclose(file); +#ifdef __VXWORKS__ + if (copyCompressXMLConfigFile( IFS_FM_CFG_NAME_UNCOMPRESSED, IFS_FM_CFG_NAME) == 0) { + IB_LOG_ERROR("Error compressing ESM config file! rc:",0x0020); + return -1; + } + // will be cleared by copyCompressXMLConfigFile() but clear here anyway for symetry + scpInProcess = 0; +#endif + + return 0; +} + +// get memory for XML parsing etc... will get from pool if there is a registered +// memory function otherwise will malloc +static void* getXmlMemory(uint32_t size, const char* info) +{ + void* address; + + // if we will exceed memory limits then reject +#ifdef __VXWORKS__ + if (memory + size > memory_limit) + return NULL; +#endif + + // if allocation is from XML parser then do not do memory accounting + if (strcmp(info, "getParserMemory()") != 0) + memory += size; + + // if we have a valid callback function then use it + if (get_memory) + address = get_memory(size, info); + else + address = malloc(size); + + if (address) + memset(address, UNDEFINED_XML8, size); + else + fprintf(stderr, "Failed to allocate %u bytes for XML parser", (unsigned)size); + return address; +} + +// free memory from XML parsing etc... will return to pool if there is a registered +// memory function otherwise will call free +static void freeXmlMemory(void *address, uint32_t size, const char* info) +{ + if (!address) { +#ifdef XML_MEMORY + if (strcmp(info, "freeParserMemory()") != 0) + fprintf(stdout, "Memory address invalid in freeXmlMemory()\n"); +#endif + return; + } + + // if allocation is from XML parser then do not do memory accounting + if (strcmp(info, "freeParserMemory()") != 0) + memory -= size; + + // if we have a valid callback function then use it + if (free_memory) { + free_memory(address, size, info); + return; + } + free(address); +} + +// calculate the max size of an XML and VF configuration +uint32_t xml_compute_pool_size(uint8_t full) +{ + + // if full parse consider all FM instances + if (full) + return (XML_PARSE_MEMORY_LIMIT * (MAX_INSTANCES + 1)); + + // otherwise just a single FM instance + return XML_PARSE_MEMORY_LIMIT; +} + +// Logging macro for reRenderVirtualFabricsConfig +#define RENDER_VF_LOGGER(function, fmt...) \ + do { if (function != NULL) {\ + char error[256]; \ + snprintf(error, sizeof(error), ##fmt); \ + (*function)(error); \ + } } while (0) + + +// Checksum code + +static void *cksumBegin(void) +{ + fm_digest_t *ctx = fm_digest_start(); + + if (!ctx) { + fprintf(stderr, "%s: checksum algorithm initialization failed\n", __func__); + return NULL; + } + + return (void *)ctx; +} + +static void cksumData(void *ctx, void *block, uint32_t length) +{ + if (!ctx || !block || !length) return; + + fm_digest_update(ctx, block, length); +} + +static uint32_t cksumEnd(void *ctx) +{ + uint8_t digest[FM_DIGEST_MAX]; + uint32_t checksum = 0; + + if (!ctx) return 0; + + fm_digest_finish(ctx, digest); + + checksum = *(uint32_t *)digest; + + return checksum; +} + +#define CKSUM_MAX 3 +#define CKSUM_OVERALL (1<<0) +#define CKSUM_DISRUPT (1<<1) +#define CKSUM_CONSIST (1<<2) +#define CKSUM_OVERALL_DISRUPT (CKSUM_OVERALL|CKSUM_DISRUPT) +#define CKSUM_OVERALL_CONSIST (CKSUM_OVERALL|CKSUM_CONSIST) +#define CKSUM_OVERALL_DISRUPT_CONSIST (CKSUM_OVERALL|CKSUM_DISRUPT|CKSUM_CONSIST) + +#define CKSUM_STR(string, flags) AddToCksums(#string, string, strlen(string), flags) +#define CKSUM_DATA(data, flags) AddToCksums(#data, &data, sizeof(data), flags) +#ifndef __VXWORKS__ +#define BUFFSIZE 8192 +#define CKSUM_FILE(file, flags) do{ \ + int fd = open(file, O_RDONLY); \ + int len; \ + char filein[BUFFSIZE]; \ + if (fd >= 0) { \ + while((len = read(fd, filein, BUFFSIZE)) > 0) \ + AddToCksums(#file, filein, len, flags); \ + close(fd); \ + } \ + } while(0); +#else +#define CKSUM_FILE(file, flags) +#endif + +/* + * Generic 'DEFAULT' macro for all integer types. + */ +#define DEFAULT_INT(data, default) { \ + /* Do 'typeof((data))' to cast ~0 to the right size */ \ + if ( data == ((typeof((data)))~0) ) \ + data = default; \ +} + +#define DEFAULT_AND_CKSUM_INT(data,default,flags) { \ + DEFAULT_INT(data,default); \ + AddToCksums(#data,&data,sizeof(data),flags); } + +#define DEFAULT_STR(data, default) { if (!strlen(data)) StringCopy(data,default,sizeof(data)); } +#define DEFAULT_AND_CKSUM_STR(data, default, flags) { DEFAULT_STR(data, default); AddToCksums(#data, &data, strlen(data), flags); } + +static fm_digest_t *cksum_ctx[CKSUM_MAX]; + +static boolean BeginCksums(const char * scope) +{ + uint32_t i; + +#ifdef CHECKSUM_DEBUG + printf("CKSUM_BEGIN %s\n", scope); +#endif + + for (i = 0; i < CKSUM_MAX; i++) { + if (!(cksum_ctx[i] = cksumBegin())) { + while(i > 0) { + cksumEnd(cksum_ctx[--i]); + } + return 0; + } + } + return 1; +} + +static void AddToCksums(char *txt, void *block, uint32_t length, uint32_t flags) +{ + uint32_t i; + +#ifdef CHECKSUM_DEBUG + printf("AddToCksums %s:",txt); + for (i=0; i < length; i++) + printf("%02x",((unsigned char *)block)[i]); + printf("\n"); +#endif + for (i = 0; i < CKSUM_MAX; i++) { + if (flags & (1 << i)) { + cksumData(cksum_ctx[i], block, length); + } + } +} + +static void EndCksums(const char * scope, uint32_t *overall_checksum, uint32_t *disruptive_checksum, uint32_t *consistency_checksum) +{ + uint32_t csum0, csum1, csum2; + + csum0 = cksumEnd(cksum_ctx[0]); + if (overall_checksum) + *overall_checksum = csum0; + csum1 = cksumEnd(cksum_ctx[1]); + if (disruptive_checksum) + *disruptive_checksum = csum1; + csum2 = cksumEnd(cksum_ctx[2]); + if (consistency_checksum) + *consistency_checksum = csum2; + +#ifdef CHECKSUM_DEBUG + printf("CKSUM_END %s %d, %d, %d\n", scope, csum0, csum1, csum2); +#endif +} + +// Map handling routines +static boolean addMap(cl_qmap_t *map, uint64_t key) +{ + cl_map_item_t *cl_map_item; + + cl_map_item = getXmlMemory(sizeof(cl_map_item_t), "cl_map_item_t addMap()"); + if (!cl_map_item) { + fprintf(stdout, OUT_OF_MEMORY_RETURN); + return 0; + } + if (cl_qmap_insert(map, key, cl_map_item) != cl_map_item) { + // Duplicate + freeXmlMemory(cl_map_item, sizeof(cl_map_item_t), "cl_map_item_t addMap()"); + return 0; + } + return 1; +} + +// Perform a deep copy of a map +static uint32_t cloneMap(cl_qmap_t *dst, cl_qmap_t *src, void *compRoutine, void *dupRoutine) +{ + void *(*dupRoutineCall)(void *) = dupRoutine; + cl_map_item_t *cl_map_item; + char *obj; + uint32_t cnt = 0; + + cl_qmap_init(dst, compRoutine); + for_all_qmap_item(src, cl_map_item) { + if (dupRoutine) { + obj = dupRoutineCall(XML_QMAP_CHAR_CAST cl_qmap_key(cl_map_item)); + if (obj) cnt += addMap(dst, XML_QMAP_U64_CAST obj); + } else { + cnt += addMap(dst, cl_qmap_key(cl_map_item)); + } + } + return cnt; +} + +// Free all the memory associated with a map and all of it's contents +static void scrubMap(cl_qmap_t *map, void *freeRoutine) +{ + void (*freeRoutineCall)(void *) = freeRoutine; + cl_map_item_t *cl_map_item; + + for (cl_map_item = cl_qmap_head(map); + cl_map_item != cl_qmap_end(map); + cl_map_item = cl_qmap_head(map)) { + if (freeRoutine) + freeRoutineCall(XML_QMAP_CHAR_CAST cl_qmap_key(cl_map_item)); + cl_qmap_remove_item(map, cl_map_item); + freeXmlMemory(cl_map_item, sizeof(cl_map_item_t), "cl_map_item_t scrubMap()"); + } +} + +int compareName(IN const uint64 name1, IN const uint64 name2) +{ + if (!name1 || !name2) + return 0; + + return strncmp(XML_QMAP_VOID_CAST name1, XML_QMAP_VOID_CAST name2, MAX_VFABRIC_NAME); +} + +static void *getName(void) +{ + char *name; + + name = getXmlMemory(MAX_VFABRIC_NAME, "MAX_VFABRIC_NAME dupName()"); + if (!name) { + fprintf(stdout, OUT_OF_MEMORY_RETURN); + return NULL; + } + return name; +} + +static void *dupName(void *name) +{ + char *new_name; + + new_name = getName(); + if (!new_name) { + fprintf(stdout, OUT_OF_MEMORY_RETURN); + return NULL; + } + strncpy(new_name, name, MAX_VFABRIC_NAME); + return new_name; +} + +static void freeName(void *name) +{ + if (!name) return; + freeXmlMemory(name, MAX_VFABRIC_NAME, "MAX_VFABRIC_NAME freeName()"); +} + +// To be equal, the entire VFAppSid_t must match +static int compareAppSid(IN const uint64 sid1, IN const uint64 sid2) +{ + if (!sid1 || !sid2) + return 0; + + return memcmp(XML_QMAP_VOID_CAST sid1, XML_QMAP_VOID_CAST sid2, sizeof(VFAppSid_t)); +} + +static VFAppSid_t *getAppSid(void) +{ + VFAppSid_t *sid; + + sid = getXmlMemory(sizeof(VFAppSid_t), "VFAppSid_t getAppSid()"); + if (sid) memset(sid, 0, sizeof(VFAppSid_t)); + return sid; +} + +static void freeAppSid(void *sid) +{ + if (!sid) return; + freeXmlMemory(sid, sizeof(VFAppSid_t), "VFAppSid_t freeAppSid()"); +} + +// To be equal, the entire VFAppMgid_t must match +static int compareAppMgid(IN const uint64 mgid1, IN const uint64 mgid2) +{ + if (!mgid1 || !mgid2) + return 0; + + return memcmp(XML_QMAP_VOID_CAST mgid1, XML_QMAP_VOID_CAST mgid2, sizeof(VFAppMgid_t)); +} + +static VFAppMgid_t *getAppMgid(void) +{ + VFAppMgid_t *mgid; + + mgid = getXmlMemory(sizeof(VFAppMgid_t), "VFAppMgid_t getAppMgid()"); + if (mgid) memset(mgid, 0, sizeof(VFAppMgid_t)); + return mgid; +} + +static void freeAppMgid(void *mgid) +{ + if (!mgid) return; + freeXmlMemory(mgid, sizeof(VFAppMgid_t), "VFAppMgid_t freeAppMgid()"); +} + +// Allocate default Multicast Group object +static VFDg_t *getDMCG(void) +{ + VFDg_t *dmcg; + + dmcg = getXmlMemory(sizeof(VFDg_t), "VFDg_t getDMCG()"); + if (dmcg) { + memset(dmcg, 0, sizeof(VFDg_t)); + cl_qmap_init(&dmcg->mgidMap, compareAppMgid); + } + return dmcg; +} + +static void freeDMCG(void *ctx) +{ + VFDg_t *dmcg = ctx; + + if (!dmcg) return; + scrubMap(&dmcg->mgidMap, freeAppMgid); + freeXmlMemory(dmcg, sizeof(VFAppSid_t), "VFAppSid_t freeAppSid()"); +} + +static void freeAppConfigMap(AppXmlConfig_t *app_config) +{ + scrubMap(&app_config->appMap, freeApplicationObject); + app_config->appMapSize = 0; +} + +// For invalid options +static void InvalidOptionParserEnd(IXmlParserState_t *state, const IXML_FIELD *field, + void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + IXmlParserPrintWarning(state, "Tag has no affect in this context."); +} + +// parse U32 and indicate field was encountered +// this can be useful when there are two ways to specify the same capability +// and it must be known which way was encountered +// LogMask vs logLevel is one such good example +void ParamU32XmlParserEnd(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + uint32_t value; + + if (IXmlParseUint32(state, content, len, &value)) { + FmParamU32_t *p = (FmParamU32_t *)IXmlParserGetField(field, object); + p->value = value; + p->valid = 1; + } +} + +// Hfi must be converted from 1 relative in Xml to 0 relative in config +void HfiXmlParserEnd(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + uint32_t value; + + if (xml_parse_debug) + fprintf(stdout, "DecrementU32XmlParserEnd %s instance %u common %u\n", field->tag, (unsigned int)instance, (unsigned int)common); + + if (IXmlParseUint32(state, content, len, &value)) { + if (value == 0) { + IXmlParserPrintError(state, "Invalid %s tag value, cannot be zero", field->tag); + return; + } + uint32_t *p = (uint32_t *)IXmlParserGetField(field, object); + *p = value - 1; + } +} + +// Handle U32 percentage value (0-100) without trailing % symbol +void PercentageXmlParserEnd(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + uint32_t value; + + if (xml_parse_debug) + fprintf(stdout, "PercentageXmlParserEnd %s instance %u common %u\n", field->tag, (unsigned int)instance, (unsigned int)common); + + if (IXmlParseUint32(state, content, len, &value)) { + if (value > 100) { + IXmlParserPrintError(state, "Invalid %s tag value, must be 0-100", field->tag); + return; + } + uint32_t *p = (uint32_t *)IXmlParserGetField(field, object); + *p = value; + } +} + +void DedicatedVLMemMultiXmlParserEnd(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + uint32_t value; + + if (xml_parse_debug) + fprintf(stdout, "DedicatedVLMemMultiXmlParserEnd %s instance %u common %u\n", field->tag, (unsigned int)instance, (unsigned int)common); + + if (IXmlParseUint32(state, content, len, &value)) { + if (value > 255) { + IXmlParserPrintError(state, "Invalid %s tag value, must be 0-255", field->tag); + return; + } + uint32_t *p = (uint32_t *)IXmlParserGetField(field, object); + *p = value; + } +} + +// Validate pkey +void PKeyParserEnd(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + uint32_t *p = (uint32_t *)IXmlParserGetField(field, object); + uint32_t pkey; + char *sym; + + if (xml_parse_debug) + fprintf(stdout, "PKeyParserEnd %s instance %u common %u\n", field->tag, (unsigned int)instance, (unsigned int)common); + + if (!valid) { + fprintf(stderr, "Error processing XML %s tag\n",field->tag); + return; + } + + if (!content) { + IXmlParserPrintError(state, "Invalid %s tag value, cannot be empty", field->tag); + return; + } + + pkey = strtol(content, &sym, 16); + if (*sym) { + IXmlParserPrintError(state, "Invalid %s tag value, must be a hexadecimal value", field->tag); + } + + if (pkey == 0 || pkey > 0x7fff) { + IXmlParserPrintError(state, "Invalid %s tag value, must be in the range 0x0001-0x7fff\n", field->tag); + return; + } + *p = pkey; +} + +// Validate 8B pkey +void PKey8BParserEnd(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + uint32_t *p = (uint32_t *)IXmlParserGetField(field, object); + uint32_t pkey; + char *sym; + + if (xml_parse_debug) + fprintf(stdout, "PKey8BParserEnd %s instance %u common %u\n", field->tag, (unsigned int)instance, (unsigned int)common); + + if (!valid) { + fprintf(stderr, "Error processing XML %s tag\n",field->tag); + return; + } + + if (!content) { + IXmlParserPrintError(state, "Invalid %s tag value, cannot be empty", field->tag); + return; + } + + pkey = strtol(content, &sym, 16); + if (*sym) { + IXmlParserPrintError(state, "Invalid %s tag value, must be a hexadecimal value", field->tag); + } + + if (pkey != 0x0) { + if (pkey > 0x7FFE) { + IXmlParserPrintError(state, "Invalid %s tag value, must be in the range 0x0001-0x7ffe, or 0x0\n", field->tag); + return; + } + // SysAdmin specifies a limited member pkey. + // Make the pkey a full member before programming any ports. + pkey = MAKE_PKEY(1, pkey); + } + *p = pkey; +} + +// Validate 10B pkey +void PKey10BParserEnd(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + uint32_t *p = (uint32_t *)IXmlParserGetField(field, object); + uint32_t pkey; + char *sym; + + if (xml_parse_debug) + fprintf(stdout, "PKey10BParserEnd %s instance %u common %u\n", field->tag, (unsigned int)instance, (unsigned int)common); + + if (!valid) { + fprintf(stderr, "Error processing XML %s tag\n",field->tag); + return; + } + + if (!content) { + IXmlParserPrintError(state, "Invalid %s tag value, cannot be empty", field->tag); + return; + } + + pkey = strtol(content, &sym, 16); + if (*sym) { + IXmlParserPrintError(state, "Invalid %s tag value, must be a hexadecimal value", field->tag); + } + + if (pkey != 0x0) { + if (pkey > 0x7FFF) { + IXmlParserPrintError(state, "Invalid %s tag value, must be in the range 0x0001-0x7fff to enable, or 0x0 to disable\n", field->tag); + return; + } + + // Clear the low order 4-bits to determine the base value. + pkey &= 0x7FF0; + + // SysAdmin specifies a limited member pkey. + // Make the pkey a full member before programming any ports. + pkey = MAKE_PKEY(1, pkey); + } + *p = pkey; +} + +void MinSupportedVLsParserEnd(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + IXmlParserPrintWarning(state, "%s tag is deprecated. Minimum number of required VLs is calculated from configuration.", field->tag); +} + +// Convert to Log2 ceiling +void CeilLog2U8XmlParserEnd(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + uint8_t *p = (uint8_t *)IXmlParserGetField(field, object); + uint32_t val; + char *sym; + + if (xml_parse_debug) + fprintf(stdout, "CeilLog2U8XmlParserEnd %s instance %u common %u\n", field->tag, (unsigned int)instance, (unsigned int)common); + + if (!valid) { + fprintf(stderr, "Error processing XML %s tag\n",field->tag); + return; + } + if (!content) { + IXmlParserPrintError(state, "Invalid %s tag value, cannot be empty", field->tag); + return; + } + + val = strtol(content, &sym, 10); + if (*sym || val < 1 || val > 128) { + IXmlParserPrintError(state, "Invalid %s tag value, must be an integer in the range 1-128", field->tag); + return; + } else { + *p = CeilLog2(val); + } +} + +// Handle U8 percentage value (0-100) with trailing % symbol +void PercentU8XmlParserEnd(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + uint8_t *p = (uint8_t *)IXmlParserGetField(field, object); + uint32_t percent; + char *sym; + + if (xml_parse_debug) + fprintf(stdout, "PercentU8XmlParserEnd %s instance %u common %u\n", field->tag, (unsigned int)instance, (unsigned int)common); + + if (!valid) { + fprintf(stderr, "Error processing XML %s tag\n",field->tag); + return; + } + if (!content) { + IXmlParserPrintError(state, "Invalid %s tag value, cannot be empty", field->tag); + return; + } + + percent = strtol(content, &sym, 10); + if (*sym != '%') { + IXmlParserPrintError(state, "Invalid %s tag value, must be in %% example: 100%%", field->tag); + return; + } else { + if (percent > 100) { + IXmlParserPrintError(state, "Invalid %s tag value, must be 0-100%%", field->tag); + return; + } + *p = percent; + } +} + +void BasisU8XmlParserEnd(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + uint8_t *p = (uint8_t *)IXmlParserGetField(field, object); + + if (xml_parse_debug) + fprintf(stdout, "BasisU8XmlParserEnd %s instance %u common %u\n", field->tag, (unsigned int)instance, (unsigned int)common); + + if (!valid) { + fprintf(stderr, "Error processing XML %s tag\n",field->tag); + return; + } + if (!content) { + IXmlParserPrintError(state, "Invald %s tag value, cannot be empty", field->tag); + return; + } + + // congestion controls + if (strcasecmp(content, "qp") == 0) { + *p = 0; + } else if (strcasecmp(content, "sl") == 0) { + *p = 1; + } else { + IXmlParserPrintError(state, "Invalid %s tag value, must be either qp or sl", field->tag); + return; + } +} + +static void LidStrategyXmlParserEnd(IXmlParserState_t *state, + const IXML_FIELD *field, void *object, void *parent, + XML_Char *content, unsigned int len, boolean valid) +{ + uint32_t *p = (uint32_t *)IXmlParserGetField(field, object); + + if (!valid) { + fprintf(stderr, "Error processing XML %s tag\n",field->tag); + return; + } + if (!content) { + IXmlParserPrintError(state, "Invalid %s tag value, cannot be empty", field->tag); + return; + } + + if (!strcasecmp(content, "serial")) + *p = LID_STRATEGY_SERIAL; + else if (!strcasecmp(content, "topology")) + *p = LID_STRATEGY_TOPOLOGY; + else { + IXmlParserPrintError(state, "LidStrategy must be one of (serial,topology%s%s)", + "", + "" + ); + return; + } +} + +void MtuU8XmlParserEnd(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + uint8_t *p = (uint8_t *)IXmlParserGetField(field, object); + + if (xml_parse_debug) + fprintf(stdout, "MtuU8XmlParserEnd %s instance %u common %u\n", field->tag, (unsigned int)instance, (unsigned int)common); + + if (!valid) { + fprintf(stderr, "Error processing XML %s tag\n",field->tag); + return; + } + if (!content) { + IXmlParserPrintError(state, "Invalid %s tag value, cannot be empty", field->tag); + return; + } + + /* we restrict vFabric and Multicast group MTU to >= 2K MTU. This avoids + * potential issues with support for 1500 byte UDP payloads as well + * as ensuring all vFabrics are capable of sending 2K MADs + */ + if (!strcasecmp(content, "Unlimited")) *p = UNDEFINED_XML8; + else if (!strcasecmp(content, "2048")) *p = GetMtuFromBytes(2048); + else if (!strcasecmp(content, "4096")) *p = GetMtuFromBytes(4096); + else if (!strcasecmp(content, "8192")) *p = GetMtuFromBytes(8192); + else if (!strcasecmp(content, "10240")) *p = GetMtuFromBytes(10240); + else { + IXmlParserPrintError(state, "%s must be (2048, 4096, 8192, 10240, or Unlimited)", + field->tag); + return; + } +} + +void RateU8XmlParserEnd(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + uint8_t *p = (uint8_t *)IXmlParserGetField(field, object); + + if (xml_parse_debug) + fprintf(stdout, "RateU8XmlParserEnd %s instance %u common %u\n", field->tag, (unsigned int)instance, (unsigned int)common); + + if (!valid) { + fprintf(stderr, "Error processing XML %s tag\n",field->tag); + return; + } + + if (!content) { + IXmlParserPrintError(state, "Invalid %s tag value, cannot be empty", field->tag); + return; + } + + if (strcasecmp(content, "Unlimited") == 0) { + *p = UNDEFINED_XML8; + } else { + // convert to int + IXmlParseRateMult_Str(state, content, p); + } +} + +static int checkVFSID(VF_t *vf, uint64_t serviceId) +{ + cl_map_item_t *cl_map_item; + VFAppSid_t *a; + + for_all_qmap_ptr(&vf->apps.sidMap, cl_map_item, a) { + if ((!a->service_id_last && + (serviceId == a->service_id)) || + ((a->service_id <= serviceId) && + (a->service_id_last >= serviceId)) || + ((serviceId & a->service_id_mask) == + (a->service_id & a->service_id_mask))) + return TRUE; + } + return FALSE; +} + +// fill in log_masks. log_level and syslog_mode decide the value to +// be used for any unspecified log_masks +static void set_log_masks(uint32_t log_level, uint32_t syslog_mode, FmParamU32_t log_masks[VIEO_LAST_MOD_ID+1]) +{ + uint32_t modid; + uint32_t new_log_masks[VIEO_LAST_MOD_ID+1]; + + cs_log_set_log_masks(log_level, syslog_mode, new_log_masks); + for (modid=0; modid <= VIEO_LAST_MOD_ID; ++modid) { + // test for UNDEFINED_XML8 just in case + if (! log_masks[modid].valid || log_masks[modid].valid == UNDEFINED_XML8) { + log_masks[modid].value = new_log_masks[modid]; + } else { + // set VS_LOG_FATAL just to be safe, no use dying in silence + log_masks[modid].value |= VS_LOG_FATAL; + } + } +} + +// Clear FM config +void fmClearConfig(FMXmlConfig_t *fmp) +{ + if (!fmp) + return; + + memset(fmp->CoreDumpLimit, 0, sizeof(fmp->CoreDumpLimit)); + memset(fmp->CoreDumpDir, 0, sizeof(fmp->CoreDumpDir)); + memset(fmp->log_file, 0, sizeof(fmp->log_file)); + memset(fmp->fm_name, 0, sizeof(fmp->fm_name)); + memset(fmp->syslog_facility, 0, sizeof(fmp->syslog_facility)); + memset(fmp->log_masks, 0, sizeof(fmp->log_masks)); + memset(fmp->SslSecurityDir, 0, sizeof(fmp->SslSecurityDir)); + memset(fmp->SslSecurityFmCertificate, 0, sizeof(fmp->SslSecurityFmCertificate)); + memset(fmp->SslSecurityFmPrivateKey, 0, sizeof(fmp->SslSecurityFmPrivateKey)); + memset(fmp->SslSecurityFmCaCertificate, 0, sizeof(fmp->SslSecurityFmCaCertificate)); + memset(fmp->SslSecurityFmDHParameters, 0, sizeof(fmp->SslSecurityFmDHParameters)); + memset(fmp->SslSecurityFmCaCRL, 0, sizeof(fmp->SslSecurityFmCaCRL)); +} + +// initialize FM defaults +boolean fmInitConfig(FMXmlConfig_t *fmp, uint32_t instance) +{ + if (!fmp) + return 0; + + // FM values are not checksummed. + DEFAULT_INT(fmp->start, 0); // Instance defaults to disabled + DEFAULT_INT(fmp->hca, 0); + DEFAULT_INT(fmp->port, 1); + DEFAULT_INT(fmp->startup_retries, 5); + DEFAULT_INT(fmp->startup_stable_wait, 10); + DEFAULT_INT(fmp->subnet_size, DEFAULT_SUBNET_SIZE); + if (fmp->subnet_size > MAX_SUBNET_SIZE) { + IB_LOG_INFO_FMT(__func__, "FM subnet size is being adjusted from %u to %u", fmp->subnet_size, MAX_SUBNET_SIZE); + fmp->subnet_size = MAX_SUBNET_SIZE; + } + if (fmp->subnet_size < MIN_SUPPORTED_ENDPORTS) { + IB_LOG_WARN_FMT(__func__, "FM subnet size of %d is too small, setting to %d", fmp->subnet_size, MIN_SUPPORTED_ENDPORTS); + fmp->subnet_size = MIN_SUPPORTED_ENDPORTS; + } + + DEFAULT_INT(fmp->debug, 0); + DEFAULT_INT(fmp->debug_rmpp, 0); + DEFAULT_INT(fmp->priority, 0); + DEFAULT_INT(fmp->elevated_priority, 0); + DEFAULT_INT(fmp->log_level, 1); + DEFAULT_INT(fmp->syslog_mode, 0); + // after parsing is done, fill in unspecified log_masks based on log_level + set_log_masks(fmp->log_level, fmp->syslog_mode, fmp->log_masks); + DEFAULT_INT(fmp->config_consistency_check_level, DEFAULT_CCC_LEVEL); + DEFAULT_INT(fmp->subnet_prefix, 0); + DEFAULT_INT(fmp->port_guid, 0); + DEFAULT_STR(fmp->CoreDumpLimit, "0"); + DEFAULT_STR(fmp->CoreDumpDir, "/var/crash/opafm"); + DEFAULT_STR(fmp->syslog_facility, "local6"); + // FIXME: cjking - Temporary patch, default values for OpenSSL Security Support are to be determined + DEFAULT_INT(fmp->SslSecurityEnabled, 0); + DEFAULT_STR(fmp->SslSecurityDir, FM_SSL_SECURITY_DIR); + DEFAULT_STR(fmp->SslSecurityFmCertificate, "fm_cert.pem"); + DEFAULT_STR(fmp->SslSecurityFmPrivateKey, "fm_key.pem"); + DEFAULT_STR(fmp->SslSecurityFmCaCertificate, "fm_ca_cert.pem"); + DEFAULT_INT(fmp->SslSecurityFmCertChainDepth, 1); + DEFAULT_STR(fmp->SslSecurityFmDHParameters, "fm_dh_parms.pem"); + DEFAULT_INT(fmp->SslSecurityFmCaCRLEnabled, 0); + DEFAULT_STR(fmp->SslSecurityFmCaCRL, "fm_ca_crl.pem"); + return 1; +} + +boolean fmCopyConfig(FMXmlConfig_t *dst, FMXmlConfig_t *src) +{ + if (!src || !dst) + return 0; + + // Nothing to do if src and dst are the same. + if (src == dst) return 1; + + *dst = *src; + return 1; +} + +// Clear PM config +void pmClearConfig(PMXmlConfig_t *pmp) +{ + if (!pmp) + return; + + memset(pmp->log_file, 0, sizeof(pmp->log_file)); + memset(pmp->syslog_facility, 0, sizeof(pmp->syslog_facility)); + memset(pmp->log_masks, 0, sizeof(pmp->log_masks)); + memset(pmp->name, 0, sizeof(pmp->name)); + memset(pmp->shortTermHistory.StorageLocation, 0, sizeof(pmp->shortTermHistory.StorageLocation)); + + pmp->number_of_pm_groups = 0; + memset(pmp->pm_portgroups, 0, sizeof(pmp->pm_portgroups)); + + pmp->overall_checksum = pmp->disruptive_checksum = pmp->consistency_checksum = 0; +} + +boolean startPmChecksum(PMXmlConfig_t *pmp) +{ +#ifdef __VXWORKS__ + int startPM=1; + int startFE=1; +#endif + + if (!pmp) + return 0; + +#ifdef __VXWORKS__ + idbSmGetManagersToStart(&startPM, &startFE); + if (!startPM) + pmp->start = 0; +#endif + + DEFAULT_INT(pmp->start, 1); // PM defaults to enabled + if (!pmp->start) { // if Pm is diabled, set the checksums to 0 and return + pmp->overall_checksum = 0; + pmp->disruptive_checksum = 0; + pmp->consistency_checksum = 0; + return 0; + } + + if (!BeginCksums(__func__)) + return 0; + + return 1; +} + +void endPmChecksum(PMXmlConfig_t *pmp, uint32_t instance) +{ + + EndCksums(__func__, &pmp->overall_checksum, &pmp->disruptive_checksum, &pmp->consistency_checksum); + + if (xml_parse_debug) + fprintf(stdout, "Pm instance %u checksum overall %u disruptive %u consistency %u\n", (unsigned int)instance, + (unsigned int)pmp->overall_checksum, (unsigned int)pmp->disruptive_checksum, (unsigned int)pmp->consistency_checksum); +} + +// initialize PM defaults +boolean pmInitConfig(PMXmlConfig_t *pmp) +{ + int i; + + if (!pmp) + return 0; + + // if the pm is enabled, do CKSUM checks + CKSUM_DATA(pmp->start, CKSUM_OVERALL_DISRUPT_CONSIST); + DEFAULT_AND_CKSUM_INT(pmp->hca, 0, CKSUM_OVERALL_DISRUPT); + DEFAULT_AND_CKSUM_INT(pmp->port, 1, CKSUM_OVERALL_DISRUPT); + DEFAULT_AND_CKSUM_INT(pmp->port_guid, 0, CKSUM_OVERALL_DISRUPT); + + // Currently, dynamic changes to pm log_level are supported. + DEFAULT_AND_CKSUM_INT(pmp->log_level, 1, CKSUM_OVERALL); + // Dynamic changes to syslog_mode are not (yet) supported. + DEFAULT_AND_CKSUM_INT(pmp->syslog_mode, 0, CKSUM_OVERALL_DISRUPT); + // Dynamic manual changes to log_masks are not (yet) supported. + // Therefore, add the log_masks to the overall and disruptive + // checksums BEFORE updating them based on defaults, + // log_level, and syslog_mode. + CKSUM_DATA(pmp->log_masks, CKSUM_OVERALL_DISRUPT); + // after parsing is done, fill in unspecified log_masks based on log_level + set_log_masks(pmp->log_level, pmp->syslog_mode, pmp->log_masks); + DEFAULT_AND_CKSUM_INT(pmp->config_consistency_check_level, DEFAULT_CCC_LEVEL, CKSUM_OVERALL_DISRUPT_CONSIST); + + DEFAULT_AND_CKSUM_INT(pmp->priority, 0, CKSUM_OVERALL_DISRUPT); + DEFAULT_AND_CKSUM_INT(pmp->elevated_priority, 0, CKSUM_OVERALL_DISRUPT); + DEFAULT_AND_CKSUM_INT(pmp->timer, 60, CKSUM_OVERALL_DISRUPT_CONSIST); + DEFAULT_AND_CKSUM_INT(pmp->sweep_interval, 10, CKSUM_OVERALL_DISRUPT_CONSIST); + DEFAULT_AND_CKSUM_INT(pmp->ErrorClear, 7, CKSUM_OVERALL_DISRUPT_CONSIST); + DEFAULT_AND_CKSUM_INT(pmp->ClearDataXfer, 0, CKSUM_OVERALL_DISRUPT_CONSIST); + DEFAULT_AND_CKSUM_INT(pmp->Clear64bit, 0, CKSUM_OVERALL_DISRUPT_CONSIST); + DEFAULT_AND_CKSUM_INT(pmp->Clear32bit, 1, CKSUM_OVERALL_DISRUPT_CONSIST); + DEFAULT_AND_CKSUM_INT(pmp->Clear8bit, 1, CKSUM_OVERALL_DISRUPT_CONSIST); + DEFAULT_AND_CKSUM_INT(pmp->process_hfi_counters, 1, CKSUM_OVERALL_DISRUPT_CONSIST); + DEFAULT_AND_CKSUM_INT(pmp->process_vl_counters, 1, CKSUM_OVERALL_DISRUPT_CONSIST); + DEFAULT_AND_CKSUM_INT(pmp->process_errorinfo, 1, CKSUM_OVERALL_DISRUPT_CONSIST); + + DEFAULT_AND_CKSUM_INT(pmp->MaxRetries, PM_DEFAULT_MAX_ATTEMPTS, CKSUM_OVERALL_DISRUPT_CONSIST); + DEFAULT_AND_CKSUM_INT(pmp->RcvWaitInterval, PM_DEFAULT_RESP_TIMEOUT, CKSUM_OVERALL_DISRUPT_CONSIST); + DEFAULT_AND_CKSUM_INT(pmp->MinRcvWaitInterval, PM_DEFAULT_MIN_RESP_TIMEOUT, CKSUM_OVERALL_DISRUPT_CONSIST); + DEFAULT_AND_CKSUM_INT(pmp->SweepErrorsLogThreshold, PM_DEFAULT_SWEEP_ERRORS_LOG_THRESHOLD, CKSUM_OVERALL_DISRUPT_CONSIST); + DEFAULT_AND_CKSUM_INT(pmp->MaxParallelNodes, PM_DEFAULT_MAX_PARALLEL_NODES, CKSUM_OVERALL_DISRUPT_CONSIST); + DEFAULT_AND_CKSUM_INT(pmp->PmaBatchSize, PM_DEFAULT_PMA_BATCH_SIZE, CKSUM_OVERALL_DISRUPT_CONSIST); + + DEFAULT_AND_CKSUM_INT(pmp->freeze_frame_lease, PM_DEFAULT_FF_LEASE, CKSUM_OVERALL_DISRUPT_CONSIST); + DEFAULT_AND_CKSUM_INT(pmp->max_clients, PM_DEFAULT_PA_MAX_CLIENTS, CKSUM_OVERALL_DISRUPT_CONSIST); + DEFAULT_AND_CKSUM_INT(pmp->freeze_frame_images, PM_DEFAULT_FF_IMAGES, CKSUM_OVERALL_DISRUPT_CONSIST); + DEFAULT_AND_CKSUM_INT(pmp->total_images, MAX(pmp->freeze_frame_images + 2, PM_DEFAULT_TOTAL_IMAGES), CKSUM_OVERALL_DISRUPT_CONSIST); + DEFAULT_INT(pmp->image_update_interval, pmp->sweep_interval < 2 ? (pmp->sweep_interval + 1) / 2 : pmp->sweep_interval / 2); + + DEFAULT_AND_CKSUM_INT(pmp->thresholds.Integrity, 100, CKSUM_OVERALL_CONSIST); + DEFAULT_AND_CKSUM_INT(pmp->thresholds.Congestion, 100, CKSUM_OVERALL_CONSIST); + DEFAULT_AND_CKSUM_INT(pmp->thresholds.SmaCongestion, 100, CKSUM_OVERALL_CONSIST); + DEFAULT_AND_CKSUM_INT(pmp->thresholds.Bubble, 100, CKSUM_OVERALL_CONSIST); + DEFAULT_AND_CKSUM_INT(pmp->thresholds.Security, 10, CKSUM_OVERALL_CONSIST); + DEFAULT_AND_CKSUM_INT(pmp->thresholds.Routing, 100, CKSUM_OVERALL_CONSIST); + + DEFAULT_AND_CKSUM_INT(pmp->thresholdsExceededMsgLimit.Integrity, 10, CKSUM_OVERALL_DISRUPT); + DEFAULT_AND_CKSUM_INT(pmp->thresholdsExceededMsgLimit.Congestion, 0, CKSUM_OVERALL_DISRUPT); + DEFAULT_AND_CKSUM_INT(pmp->thresholdsExceededMsgLimit.SmaCongestion, 0, CKSUM_OVERALL_DISRUPT); + DEFAULT_AND_CKSUM_INT(pmp->thresholdsExceededMsgLimit.Bubble, 0, CKSUM_OVERALL_DISRUPT); + DEFAULT_AND_CKSUM_INT(pmp->thresholdsExceededMsgLimit.Security, 10, CKSUM_OVERALL_DISRUPT); + DEFAULT_AND_CKSUM_INT(pmp->thresholdsExceededMsgLimit.Routing, 10, CKSUM_OVERALL_DISRUPT); + + DEFAULT_AND_CKSUM_INT(pmp->integrityWeights.LocalLinkIntegrityErrors, 0, CKSUM_OVERALL_CONSIST); + DEFAULT_AND_CKSUM_INT(pmp->integrityWeights.PortRcvErrors, 100, CKSUM_OVERALL_CONSIST); + DEFAULT_AND_CKSUM_INT(pmp->integrityWeights.ExcessiveBufferOverruns, 100, CKSUM_OVERALL_CONSIST); + DEFAULT_AND_CKSUM_INT(pmp->integrityWeights.LinkErrorRecovery, 0, CKSUM_OVERALL_CONSIST); + DEFAULT_AND_CKSUM_INT(pmp->integrityWeights.LinkDowned, 25, CKSUM_OVERALL_CONSIST); + DEFAULT_AND_CKSUM_INT(pmp->integrityWeights.UncorrectableErrors, 100, CKSUM_OVERALL_CONSIST); + DEFAULT_AND_CKSUM_INT(pmp->integrityWeights.FMConfigErrors, 100, CKSUM_OVERALL_CONSIST); + DEFAULT_AND_CKSUM_INT(pmp->integrityWeights.LinkQualityIndicator, 40, CKSUM_OVERALL_CONSIST); + DEFAULT_AND_CKSUM_INT(pmp->integrityWeights.LinkWidthDowngrade, 100, CKSUM_OVERALL_CONSIST); + + DEFAULT_AND_CKSUM_INT(pmp->congestionWeights.PortXmitWait, 10, CKSUM_OVERALL_CONSIST); + DEFAULT_AND_CKSUM_INT(pmp->congestionWeights.SwPortCongestion, 100, CKSUM_OVERALL_CONSIST); + DEFAULT_AND_CKSUM_INT(pmp->congestionWeights.PortRcvFECN, 5, CKSUM_OVERALL_CONSIST); + DEFAULT_AND_CKSUM_INT(pmp->congestionWeights.PortRcvBECN, 1, CKSUM_OVERALL_CONSIST); + DEFAULT_AND_CKSUM_INT(pmp->congestionWeights.PortXmitTimeCong, 25, CKSUM_OVERALL_CONSIST); + DEFAULT_AND_CKSUM_INT(pmp->congestionWeights.PortMarkFECN, 25, CKSUM_OVERALL_CONSIST); + + DEFAULT_AND_CKSUM_INT(pmp->resolution.LocalLinkIntegrity, 8000000, CKSUM_OVERALL_DISRUPT_CONSIST); + DEFAULT_AND_CKSUM_INT(pmp->resolution.LinkErrorRecovery, 100000, CKSUM_OVERALL_DISRUPT_CONSIST); + + DEFAULT_AND_CKSUM_INT(pmp->errorinfo_thresholds.Integrity, UNDEFINED_XML16, CKSUM_OVERALL_DISRUPT); + DEFAULT_AND_CKSUM_INT(pmp->errorinfo_thresholds.Security, 10, CKSUM_OVERALL_DISRUPT); + DEFAULT_AND_CKSUM_INT(pmp->errorinfo_thresholds.Routing, 10, CKSUM_OVERALL_DISRUPT); + + for (i = 0; i < pmp->number_of_pm_groups; i++) { + if (pmp->pm_portgroups[i].Enabled) { + CKSUM_STR(pmp->pm_portgroups[i].Name, CKSUM_OVERALL_CONSIST); + CKSUM_DATA(pmp->pm_portgroups[i].Monitors, CKSUM_OVERALL_CONSIST); + } + } + + DEFAULT_AND_CKSUM_INT(pmp->debug, 0, CKSUM_OVERALL_DISRUPT); + DEFAULT_AND_CKSUM_INT(pmp->debug_rmpp, 0, CKSUM_OVERALL_DISRUPT); + DEFAULT_AND_CKSUM_INT(pmp->pm_debug_perf, 0, CKSUM_OVERALL_DISRUPT); + + DEFAULT_INT(pmp->subnet_size, DEFAULT_SUBNET_SIZE); + if (pmp->subnet_size > MAX_SUBNET_SIZE) { + IB_LOG_INFO_FMT(__func__, "PM subnet size is being adjusted from %u to %u", pmp->subnet_size, MAX_SUBNET_SIZE); + pmp->subnet_size = MAX_SUBNET_SIZE; + } + if (pmp->subnet_size < MIN_SUPPORTED_ENDPORTS) { + IB_LOG_WARN_FMT(__func__, "PM subnet size of %d is too small, setting to %d", pmp->subnet_size, MIN_SUPPORTED_ENDPORTS); + pmp->subnet_size = MIN_SUPPORTED_ENDPORTS; + } + CKSUM_DATA(pmp->subnet_size, CKSUM_OVERALL_DISRUPT_CONSIST); + + DEFAULT_AND_CKSUM_INT(pmp->shortTermHistory.enable, 1, CKSUM_OVERALL_DISRUPT_CONSIST); + if (pmp->shortTermHistory.enable) { + DEFAULT_AND_CKSUM_INT(pmp->shortTermHistory.imagesPerComposite, 3, CKSUM_OVERALL_DISRUPT_CONSIST); + DEFAULT_AND_CKSUM_INT(pmp->shortTermHistory.maxDiskSpace, 1024, CKSUM_OVERALL_DISRUPT_CONSIST); + DEFAULT_AND_CKSUM_STR(pmp->shortTermHistory.StorageLocation, "/var/lib/opa-fm", CKSUM_OVERALL_DISRUPT); + DEFAULT_AND_CKSUM_INT(pmp->shortTermHistory.totalHistory, 24, CKSUM_OVERALL_DISRUPT_CONSIST); + DEFAULT_AND_CKSUM_INT(pmp->shortTermHistory.compressionDivisions, 1, CKSUM_OVERALL_DISRUPT_CONSIST); + } + + DEFAULT_INT(pmp->SslSecurityEnabled, 0); + DEFAULT_STR(pmp->SslSecurityDir, FM_SSL_SECURITY_DIR); + DEFAULT_STR(pmp->SslSecurityFmCertificate, "fm_cert.pem"); + DEFAULT_STR(pmp->SslSecurityFmPrivateKey, "fm_key.pem"); + DEFAULT_STR(pmp->SslSecurityFmCaCertificate, "fm_ca_cert.pem"); + DEFAULT_INT(pmp->SslSecurityFmCertChainDepth, 1); + DEFAULT_STR(pmp->SslSecurityFmDHParameters, "fm_dh_parms.pem"); + DEFAULT_STR(pmp->SslSecurityFmCaCRL, "fm_ca_crl.pem"); + + if (pmp->image_update_interval >= pmp->sweep_interval) { + IB_LOG_WARN_FMT(__func__, "Image Update Interval (%d) cannot be >= than the Sweep Interval (%d)", pmp->image_update_interval, pmp->sweep_interval); + pmp->image_update_interval = (pmp->sweep_interval < 2 ? (pmp->sweep_interval + 1) / 2 : pmp->sweep_interval / 2); + IB_LOG_WARN_FMT(__func__, "Setting Image Update Interval to 1/2 Sweep Interval (%d) ", pmp->image_update_interval); + } + CKSUM_DATA(pmp->image_update_interval, CKSUM_OVERALL_DISRUPT_CONSIST); + + return 1; +} + +boolean pmCopyConfig(PMXmlConfig_t *dst, PMXmlConfig_t *src) +{ + if (!src || !dst) + return 0; + + // Nothing to do if src and dst are the same. + if (src == dst) return 1; + + *dst = *src; + return 1; +} + +// show the PM XML config +void pmShowConfig(PMXmlConfig_t *pmp) +{ + int i,j; +#ifndef __VXWORKS__ + uint32_t modid; +#endif + + if (!pmp) + return; + + printf("XML - hca %u\n", (unsigned int)pmp->hca); + printf("XML - port %u\n", (unsigned int)pmp->port); + printf("XML - port_guid %u\n", (unsigned int)pmp->port_guid); + + printf("XML - name %s\n", pmp->name); + printf("XML - log_file %s\n", pmp->log_file); +#ifndef __VXWORKS__ + printf("XML - syslog_facility %s\n", pmp->syslog_facility); + for (modid=0; modid<= VIEO_LAST_MOD_ID; ++modid) + printf("XML - log_mask[%u] 0x%x\n", modid, (unsigned int)pmp->log_masks[modid].value); +#endif + printf("XML - SslSecurityEnabled %u\n", pmp->SslSecurityEnabled); + printf("XML - SslSecurityDir %s\n", pmp->SslSecurityDir); + printf("XML - SslSecurityFmCertificate %s\n", pmp->SslSecurityFmCertificate); + printf("XML - SslSecurityFmPrivateKey %s\n", pmp->SslSecurityFmPrivateKey); + printf("XML - SslSecurityFmCaCertificate %s\n", pmp->SslSecurityFmCaCertificate); + printf("XML - SslSecurityFmCertChainDepth %u\n", pmp->SslSecurityFmCertChainDepth); + printf("XML - SslSecurityFmDHParameters %s\n", pmp->SslSecurityFmDHParameters); + printf("XML - SslSecurityFmCaCRLEnabled %u\n", pmp->SslSecurityFmCaCRLEnabled); + printf("XML - SslSecurityFmCaCRL %s\n", pmp->SslSecurityFmCaCRL); + + printf("XML - log_level %u\n", (unsigned int)pmp->log_level); + printf("XML - syslog_mode %u\n", (unsigned int)pmp->syslog_mode); + printf("XML - config_consistency_check_level %u\n", (unsigned int)pmp->config_consistency_check_level); + printf("XML - priority %u\n", (unsigned int)pmp->priority); + printf("XML - elevated_priority %u\n", (unsigned int)pmp->elevated_priority); + printf("XML - timer %u\n", (unsigned int)pmp->timer); + printf("XML - sweep_interval %u\n", (unsigned int)pmp->sweep_interval); + printf("XML - ErrorClear %u\n", (unsigned int)pmp->ErrorClear); + printf("XML - ClearDataXfer %u\n", (unsigned int)pmp->ClearDataXfer); + printf("XML - Clear64bit %u\n", (unsigned int)pmp->Clear64bit); + printf("XML - Clear32bit %u\n", (unsigned int)pmp->Clear32bit); + printf("XML - Clear8bit %u\n", (unsigned int)pmp->Clear8bit); + printf("XML - process_hfi_counters %u\n", (unsigned int)pmp->process_hfi_counters); + printf("XML - process_vl_counters %u\n", (unsigned int)pmp->process_vl_counters); + printf("XML - process_errorinfo %u\n", (unsigned int)pmp->process_errorinfo); + + printf("XML - MaxRetries %u\n", (unsigned int)pmp->MaxRetries); + printf("XML - RcvWaitInterval %u\n", (unsigned int)pmp->RcvWaitInterval); + printf("XML - MinRcvWaitInterval %u\n", (unsigned int)pmp->MinRcvWaitInterval); + printf("XML - SweepErrorsLogThreshold %u\n", (unsigned int)pmp->SweepErrorsLogThreshold); + printf("XML - MaxParallelNodes %u\n", (unsigned int)pmp->MaxParallelNodes); + + printf("XML - freeze_frame_lease %u\n", (unsigned int)pmp->freeze_frame_lease); + printf("XML - max_clients %u\n", (unsigned int)pmp->max_clients); + printf("XML - freeze_frame_images %u\n", (unsigned int)pmp->freeze_frame_images); + printf("XML - total_images %u\n", (unsigned int)pmp->total_images); + printf("XML - image_update_interval %u\n", (unsigned int)pmp->image_update_interval); + + printf("XML - thresholds.Integrity %u\n", (unsigned int)pmp->thresholds.Integrity); + printf("XML - thresholds.Congestion %u\n", (unsigned int)pmp->thresholds.Congestion); + printf("XML - thresholds.SmaCongestion %u\n", (unsigned int)pmp->thresholds.SmaCongestion); + printf("XML - thresholds.Bubble %u\n", (unsigned int)pmp->thresholds.Bubble); + printf("XML - thresholds.Security %u\n", (unsigned int)pmp->thresholds.Security); + printf("XML - thresholds.Routing %u\n", (unsigned int)pmp->thresholds.Routing); + + printf("XML - thresholdsExceededMsgLimit.Integrity %u\n", (unsigned int)pmp->thresholdsExceededMsgLimit.Integrity); + printf("XML - thresholdsExceededMsgLimit.Congestion %u\n", (unsigned int)pmp->thresholdsExceededMsgLimit.Congestion); + printf("XML - thresholdsExceededMsgLimit.SmaCongestion %u\n", (unsigned int)pmp->thresholdsExceededMsgLimit.SmaCongestion); + printf("XML - thresholdsExceededMsgLimit.Bubble %u\n", (unsigned int)pmp->thresholdsExceededMsgLimit.Bubble); + printf("XML - thresholdsExceededMsgLimit.Security %u\n", (unsigned int)pmp->thresholdsExceededMsgLimit.Security); + printf("XML - thresholdsExceededMsgLimit.Routing %u\n", (unsigned int)pmp->thresholdsExceededMsgLimit.Routing); + + printf("XML - integrityWeights.LocalLinkIntegrityErrors %u\n", (unsigned int)pmp->integrityWeights.LocalLinkIntegrityErrors); + printf("XML - integrityWeights.RcvErrors %u\n", (unsigned int)pmp->integrityWeights.PortRcvErrors); + printf("XML - integrityWeights.ExcessiveBufferOverruns %u\n", (unsigned int)pmp->integrityWeights.ExcessiveBufferOverruns); + printf("XML - integrityWeights.LinkErrorRecovery %u\n", (unsigned int)pmp->integrityWeights.LinkErrorRecovery); + printf("XML - integrityWeights.LinkDowned %u\n", (unsigned int)pmp->integrityWeights.LinkDowned); + printf("XML - integrityWeights.UncorrectableErrors %u\n", (unsigned int)pmp->integrityWeights.UncorrectableErrors); + printf("XML - integrityWeights.FMConfigErrors %u\n", (unsigned int)pmp->integrityWeights.FMConfigErrors); + printf("XML - integrityWeights.LinkQualityIndicator %u\n", (unsigned int)pmp->integrityWeights.LinkQualityIndicator); + printf("XML - integrityWeights.LinkWidthDowngrade %u\n", (unsigned int)pmp->integrityWeights.LinkWidthDowngrade); + + printf("XML - congestionWeights.XmitWaitPct %u\n", (unsigned int)pmp->congestionWeights.PortXmitWait); + printf("XML - congestionWeights.CongDiscards %u\n", (unsigned int)pmp->congestionWeights.SwPortCongestion); + printf("XML - congestionWeights.RcvFECNPct %u\n", (unsigned int)pmp->congestionWeights.PortRcvFECN); + printf("XML - congestionWeights.RcvBECNPct %u\n", (unsigned int)pmp->congestionWeights.PortRcvBECN); + printf("XML - congestionWeights.XmitTimeCongPct %u\n", (unsigned int)pmp->congestionWeights.PortXmitTimeCong); + printf("XML - congestionWeights.MarkFECNPct %u\n", (unsigned int)pmp->congestionWeights.PortMarkFECN); + + printf("XML - resolution.LocalLinkIntegrity %u\n", (unsigned int)pmp->resolution.LocalLinkIntegrity); + printf("XML - resolution.LinkErrorRecovery %u\n", (unsigned int)pmp->resolution.LinkErrorRecovery); + + printf("XML - errorinfo_thresholds.Integrity %u\n", (unsigned int)pmp->errorinfo_thresholds.Integrity); + printf("XML - errorinfo_thresholds.Security %u\n", (unsigned int)pmp->errorinfo_thresholds.Security); + printf("XML - errorinfo_thresholds.Routing %u\n", (unsigned int)pmp->errorinfo_thresholds.Routing); + + printf("XML - number_of_pm_groups %u\n", (unsigned int)pmp->number_of_pm_groups); + for (i = 0; i < pmp->number_of_pm_groups; i++) { + printf("XML - pm_portgroups[%d].Enabled %u\n", i, pmp->pm_portgroups[i].Enabled); + if (pmp->pm_portgroups[i].Enabled) { + printf("XML - pm_portgroups[%d].PmPortGroupName %.*s\n", i, (int)sizeof(pmp->pm_portgroups[i].Name), pmp->pm_portgroups[i].Name); + for (j=0; j < STL_PM_MAX_DG_PER_PMPG; j++) { + if (sizeof(pmp->pm_portgroups[i].Monitors[j].monitor)) { + printf("XML - pm_portgroups[%d].Monitors[%d].monitor %.*s\n", i, j, (int)sizeof(pmp->pm_portgroups[i].Monitors[j].monitor), pmp->pm_portgroups[i].Monitors[j].monitor); + } + } + } + } +/* + printf("XML - log_level %u\n", (unsigned int)pmp->log_level); +*/ +} + +// Clear FE config +void feClearConfig(FEXmlConfig_t *fep) +{ + if (!fep) + return; + + memset(fep->CoreDumpLimit, 0, sizeof(fep->CoreDumpLimit)); + memset(fep->CoreDumpDir, 0, sizeof(fep->CoreDumpDir)); + memset(fep->log_file, 0, sizeof(fep->log_file)); + memset(fep->name, 0, sizeof(fep->name)); + memset(fep->syslog_facility, 0, sizeof(fep->syslog_facility)); + memset(fep->log_masks, 0, sizeof(fep->log_masks)); +} + +static +boolean startFeChecksum(FEXmlConfig_t *fep) +{ +#ifdef __VXWORKS__ + int startPM=1; + int startFE=1; +#endif + + if (!fep) + return 0; + +#ifdef __VXWORKS__ + idbSmGetManagersToStart(&startPM, &startFE); + if (!startFE) + fep->start = 0; +#endif + DEFAULT_INT(fep->start, 0); // FE defaults to disabled + + if (!fep->start) { + return 0; + } + // No checksums for Fe + return 1; +} + +void endFeChecksum(FEXmlConfig_t *fep, uint32_t instance) +{ + // Nothing to do +} + +// initialize FE defaults +boolean feInitConfig(FEXmlConfig_t *fep) +{ + if (!fep) + return 0; + + DEFAULT_INT(fep->hca, 0); + DEFAULT_INT(fep->port, 1); + DEFAULT_INT(fep->port_guid, 0); + + DEFAULT_INT(fep->startup_retries, 5); + DEFAULT_INT(fep->startup_stable_wait, 10); + + // These are now processed when "fill" at end of parsing whole file + DEFAULT_INT(fep->login, 0); + + DEFAULT_INT(fep->subnet_size, DEFAULT_SUBNET_SIZE); + if (fep->subnet_size > MAX_SUBNET_SIZE) { + IB_LOG_INFO_FMT(__func__, "FE subnet size is being adjusted from %u to %u", fep->subnet_size, MAX_SUBNET_SIZE); + fep->subnet_size = MAX_SUBNET_SIZE; + } + if (fep->subnet_size < MIN_SUPPORTED_ENDPORTS) { + IB_LOG_WARN_FMT(__func__, "FE subnet size of %d is too small, setting to %d", fep->subnet_size, MIN_SUPPORTED_ENDPORTS); + fep->subnet_size = MIN_SUPPORTED_ENDPORTS; + } + + DEFAULT_INT(fep->debug, 0); + DEFAULT_INT(fep->debug_rmpp, 0); + DEFAULT_INT(fep->log_level, 1); + DEFAULT_INT(fep->syslog_mode, 0); + DEFAULT_INT(fep->listen, FE_LISTEN_PORT); + DEFAULT_INT(fep->window, FE_WIN_SIZE); + set_log_masks(fep->log_level, fep->syslog_mode, fep->log_masks); + DEFAULT_STR(fep->CoreDumpLimit, "0"); + DEFAULT_STR(fep->CoreDumpDir, "/var/crash/opafm"); + DEFAULT_STR(fep->syslog_facility, "local6"); + DEFAULT_INT(fep->manager_check_rate, 60000000); + DEFAULT_INT(fep->SslSecurityEnabled, 0); + if (fep->SslSecurityEnabled) { + DEFAULT_STR(fep->SslSecurityDir, FM_SSL_SECURITY_DIR); + DEFAULT_STR(fep->SslSecurityFmCertificate, "fm_cert.pem"); + DEFAULT_STR(fep->SslSecurityFmPrivateKey, "fm_key.pem"); + DEFAULT_STR(fep->SslSecurityFmCaCertificate, "fm_ca_cert.pem"); + DEFAULT_INT(fep->SslSecurityFmCertChainDepth, 1); + DEFAULT_STR(fep->SslSecurityFmDHParameters, "fm_dh_parms.pem"); + DEFAULT_INT(fep->SslSecurityFmCaCRLEnabled, 0); + DEFAULT_STR(fep->SslSecurityFmCaCRL, "fm_ca_crl.pem"); + } + + return 1; +} + +boolean feCopyConfig(FEXmlConfig_t *dst, FEXmlConfig_t *src) +{ + if (!src || !dst) + return 0; + + // Nothing to do if src and dst are the same. + if (src == dst) return 1; + + *dst = *src; + return 1; +} + +// show the FE XML config +void feShowConfig(FEXmlConfig_t *fep) +{ +#ifndef __VXWORKS__ + uint32_t modid; +#endif + + if (!fep) + return; + + printf("XML - hca %u\n", (unsigned int)fep->hca); + printf("XML - port %u\n", (unsigned int)fep->port); + printf("XML - port_guid %u\n", (unsigned int)fep->port_guid); + printf("XML - name %s\n", fep->name); + printf("XML - log_file %s\n", fep->log_file); + printf("XML - syslog_mode %u\n", (unsigned int)fep->syslog_mode); +#ifndef __VXWORKS__ + printf("XML - syslog_facility %s\n", fep->syslog_facility); + printf("XML - CoreDumpLimit %s\n", fep->CoreDumpLimit); + printf("XML - CoreDumpDir %s\n", fep->CoreDumpDir); + printf("XML - log_level %u\n", (unsigned int)fep->log_level); + for (modid = 0; modid<= VIEO_LAST_MOD_ID; ++modid) + printf("XML - log_mask[%u] 0x%x\n", modid, (unsigned int)fep->log_masks[modid].value); +#endif + printf("XML - SslSecurityEnabled %u\n", (unsigned int)fep->SslSecurityEnabled); + printf("XML - SslSecurityDir %s\n", fep->SslSecurityDir); + printf("XML - SslSecurityFmCertificate %s\n", fep->SslSecurityFmCertificate); + printf("XML - SslSecurityFmPrivateKey %s\n", fep->SslSecurityFmPrivateKey); + printf("XML - SslSecurityFmCaCertificate %s\n", fep->SslSecurityFmCaCertificate); + printf("XML - SslSecurityFmCertChainDepth %u\n", (unsigned int)fep->SslSecurityFmCertChainDepth); + printf("XML - SslSecurityFmDHParameters %s\n", fep->SslSecurityFmDHParameters); + printf("XML - SslSecurityFmCaCRLEnabled %u\n", (unsigned int)fep->SslSecurityFmCaCRLEnabled); + printf("XML - SslSecurityFmCaCRL %s\n", fep->SslSecurityFmCaCRL); + + printf("XML - listen %u\n", (unsigned int)fep->listen); + printf("XML - login %u\n", (unsigned int)fep->login); + printf("XML - window %u\n", (unsigned int)fep->window); + printf("XML - debug %u\n", (unsigned int)fep->debug); + printf("XML - debug_rmpp %u\n", (unsigned int)fep->debug_rmpp); + printf("XML - subnet_size %u\n", (unsigned int)fep->subnet_size); +} + + +void smFreeHypercubeRouting(SMXmlConfig_t *smp) +{ + SmSPRoutingCtrl_t *SPRoutingCtrl, *nextSPRoutingCtrl; + + memset(&smp->hypercubeRouting.routeLast.member, 0, + sizeof(smp->hypercubeRouting.routeLast.member)); + + SPRoutingCtrl = smp->hypercubeRouting.enhancedRoutingCtrl; + if (SPRoutingCtrl == (void *)~0ul) { + SPRoutingCtrl = NULL; + } + while (SPRoutingCtrl) { + int portsSize = ROUNDUP(SPRoutingCtrl->portCount, PORTS_ALLOC_UNIT); + + if (portsSize) { + freeXmlMemory(SPRoutingCtrl->ports, portsSize*sizeof(*SPRoutingCtrl->ports), + "SmSPRoutingPort_t *ports"); + } + nextSPRoutingCtrl = SPRoutingCtrl->next; + freeXmlMemory(SPRoutingCtrl, sizeof(SmSPRoutingCtrl_t), "SmSPRoutingCtrl_t *SPRoutingCtrl"); + SPRoutingCtrl = nextSPRoutingCtrl; + } + smp->hypercubeRouting.enhancedRoutingCtrl = NULL; +} + +// Clear SM configs +void smClearConfig(SMXmlConfig_t *smp) +{ + int i; + + if (!smp) + return; + + memset(smp->dumpCounters, 0, sizeof(smp->dumpCounters)); + memset(smp->log_file, 0, sizeof(smp->log_file)); + memset(smp->syslog_facility, 0, sizeof(smp->syslog_facility)); + memset(smp->log_masks, 0, sizeof(smp->log_masks)); + memset(smp->name, 0, sizeof(smp->name)); + memset(smp->routing_algorithm, 0, sizeof(smp->routing_algorithm)); + memset(smp->preDefTopo.topologyFilename, 0, sizeof(smp->preDefTopo.topologyFilename)); + memset(&smp->ftreeRouting.coreSwitches, 0, sizeof(smp->ftreeRouting.coreSwitches)); + memset(&smp->ftreeRouting.routeLast, 0, sizeof(smp->ftreeRouting.routeLast)); + + smp->dgRouting.dgCount = 0; + for (i = 0; i < MAX_DGROUTING_ORDER; i++) { + memset(&smp->dgRouting.dg[i], 0, sizeof(smp->dgRouting.dg[i])); + } + + smFreeHypercubeRouting(smp); +} + +static +boolean startSmChecksum(SMXmlConfig_t *smp) +{ + if (!smp) + return 0; + + DEFAULT_INT(smp->start, 1); // Sm defaults to enabled + if (!smp->start) { // if Sm is diabled, set the checksums to 0 and return + smp->overall_checksum = 0; + smp->disruptive_checksum = 0; + smp->consistency_checksum = 0; + return 0; + } + + if (!BeginCksums(__func__)) + return 0; + + return 1; +} + + +static +boolean endSmChecksum(SMXmlConfig_t *smp, uint32_t instance) +{ + if (!smp) + return 0; + + EndCksums(__func__, &smp->overall_checksum, &smp->disruptive_checksum, &smp->consistency_checksum); + if (xml_parse_debug) + fprintf(stdout, "Sm instance %u checksum overall %u disruptive %u consistency %u\n", (unsigned int)instance, + (unsigned int)smp->overall_checksum, (unsigned int)smp->disruptive_checksum, (unsigned int)smp->consistency_checksum); + return 1; +} + +// initialize SM defaults +static +boolean smInitConfig(SMXmlConfig_t *smp) +{ + uint32_t i; + SmSPRoutingCtrl_t *SPRoutingCtrl; + + if (!smp) + return 0; + + // if the sm is enabled, do CKSUM checks + CKSUM_DATA(smp->start, CKSUM_OVERALL_DISRUPT); + DEFAULT_AND_CKSUM_INT(smp->hca, 0, CKSUM_OVERALL_DISRUPT); + DEFAULT_AND_CKSUM_INT(smp->port, 1, CKSUM_OVERALL_DISRUPT); + DEFAULT_AND_CKSUM_INT(smp->port_guid, 0, CKSUM_OVERALL_DISRUPT); + + DEFAULT_AND_CKSUM_INT(smp->startup_retries, 5, CKSUM_OVERALL); + DEFAULT_AND_CKSUM_INT(smp->startup_stable_wait, 10, CKSUM_OVERALL); + + DEFAULT_AND_CKSUM_INT(smp->sm_key, 0x0ull, CKSUM_OVERALL_DISRUPT_CONSIST); + DEFAULT_AND_CKSUM_INT(smp->mkey, 0x0ull, CKSUM_OVERALL_DISRUPT_CONSIST); + DEFAULT_AND_CKSUM_INT(smp->timer, 300, CKSUM_OVERALL_DISRUPT_CONSIST); + + DEFAULT_INT(smp->IgnoreTraps, 0); + if (!smp->IgnoreTraps) { + DEFAULT_INT(smp->trap_hold_down, 1); + if (smp->timer && (smp->trap_hold_down > smp->timer)) { + IB_LOG_WARN_FMT(__func__,"TrapHoldDown exceeds SweepInterval. Ignoring Traps."); + smp->IgnoreTraps = 1; + } else { + CKSUM_DATA(smp->trap_hold_down, CKSUM_OVERALL_DISRUPT_CONSIST); + } + } + CKSUM_DATA(smp->IgnoreTraps, CKSUM_OVERALL_DISRUPT_CONSIST); + + DEFAULT_AND_CKSUM_INT(smp->max_retries, MAD_RETRIES, CKSUM_OVERALL_DISRUPT_CONSIST); + DEFAULT_AND_CKSUM_INT(smp->rcv_wait_msec, MAD_RCV_WAIT_MSEC, CKSUM_OVERALL_DISRUPT_CONSIST); + DEFAULT_AND_CKSUM_INT(smp->min_rcv_wait_msec, MAD_MIN_RCV_WAIT_MSEC, CKSUM_OVERALL_DISRUPT_CONSIST); + DEFAULT_AND_CKSUM_INT(smp->master_ping_interval, SM_CHECK_MASTER_INTERVAL, CKSUM_OVERALL_DISRUPT_CONSIST); + DEFAULT_AND_CKSUM_INT(smp->master_ping_max_fail, SM_CHECK_MASTER_MAX_COUNT, CKSUM_OVERALL_DISRUPT_CONSIST); + DEFAULT_AND_CKSUM_INT(smp->topo_errors_threshold, 8, CKSUM_OVERALL_DISRUPT_CONSIST); + DEFAULT_AND_CKSUM_INT(smp->topo_abandon_threshold, 2, CKSUM_OVERALL_DISRUPT_CONSIST); + DEFAULT_AND_CKSUM_INT(smp->switch_lifetime_n2, 13, CKSUM_OVERALL_DISRUPT_CONSIST); + DEFAULT_AND_CKSUM_INT(smp->hoqlife_n2, 8, CKSUM_OVERALL_DISRUPT_CONSIST); + DEFAULT_AND_CKSUM_INT(smp->vl15FlowControlDisable, 1, CKSUM_OVERALL_DISRUPT_CONSIST); // by default, VL15 flow ctrl disabled + DEFAULT_AND_CKSUM_INT(smp->vl15_credit_rate, 18, CKSUM_OVERALL_DISRUPT_CONSIST); + DEFAULT_AND_CKSUM_INT(smp->sa_resp_time_n2, 19, CKSUM_OVERALL_DISRUPT_CONSIST); + DEFAULT_AND_CKSUM_INT(smp->sa_packet_lifetime_n2, 16, CKSUM_OVERALL_DISRUPT_CONSIST); + DEFAULT_AND_CKSUM_INT(smp->vlstall, 7, CKSUM_OVERALL_DISRUPT_CONSIST); + DEFAULT_AND_CKSUM_INT(smp->db_sync_interval, 15, CKSUM_OVERALL_DISRUPT_CONSIST); + DEFAULT_AND_CKSUM_INT(smp->trap_threshold, SM_TRAP_THRESHOLD_DEFAULT, CKSUM_OVERALL_DISRUPT_CONSIST); + DEFAULT_AND_CKSUM_INT(smp->trap_threshold_min_count, SM_TRAP_THRESHOLD_COUNT_DEFAULT, CKSUM_OVERALL_DISRUPT_CONSIST); + DEFAULT_AND_CKSUM_INT(smp->trap_log_suppress_trigger_interval, SM_TRAP_LOG_SUPPRESS_TRIGGER_INTERVAL, CKSUM_OVERALL_DISRUPT); + DEFAULT_AND_CKSUM_INT(smp->mc_dos_threshold, 0, CKSUM_OVERALL_DISRUPT_CONSIST); + DEFAULT_AND_CKSUM_INT(smp->mc_dos_action, 0, CKSUM_OVERALL_DISRUPT_CONSIST); + DEFAULT_AND_CKSUM_INT(smp->mc_dos_interval, 60, CKSUM_OVERALL_DISRUPT_CONSIST); + DEFAULT_AND_CKSUM_INT(smp->node_appearance_msg_thresh, 0, CKSUM_OVERALL_DISRUPT_CONSIST); + DEFAULT_AND_CKSUM_INT(smp->spine_first_routing, 0, CKSUM_OVERALL_DISRUPT_CONSIST); + DEFAULT_AND_CKSUM_INT(smp->shortestPathBalanced, 1, CKSUM_OVERALL_DISRUPT_CONSIST); + DEFAULT_AND_CKSUM_INT(smp->lid, 0x0, CKSUM_OVERALL_DISRUPT); + DEFAULT_AND_CKSUM_INT(smp->P_Key_8B, 0, CKSUM_OVERALL_DISRUPT_CONSIST); + DEFAULT_AND_CKSUM_INT(smp->P_Key_10B, 0, CKSUM_OVERALL_DISRUPT_CONSIST); + + DEFAULT_INT(smp->lmc, 0x0); + DEFAULT_INT(smp->lmc_e0, 0x0); + if (smp->lmc > 7) { + IB_LOG_WARN_FMT(__func__, "'Lmc' option of %d is not valid; defaulting to 0", smp->lmc); + smp->lmc = 0; + } + if (smp->lmc_e0 > smp->lmc) { + IB_LOG_WARN_FMT(__func__, "'LmcE0' option of must be <= Lmc; defaulting to %d", smp->lmc); + smp->lmc_e0 = smp->lmc; + } + CKSUM_DATA(smp->lmc, CKSUM_OVERALL_DISRUPT_CONSIST); + CKSUM_DATA(smp->lmc_e0, CKSUM_OVERALL_DISRUPT_CONSIST); + + DEFAULT_INT(smp->subnet_size, DEFAULT_SUBNET_SIZE); + if (smp->subnet_size > MAX_SUBNET_SIZE) { + IB_LOG_INFO_FMT(__func__, "SM subnet size is being adjusted from %u to %u", smp->subnet_size, MAX_SUBNET_SIZE); + smp->subnet_size = MAX_SUBNET_SIZE; + } + if (smp->subnet_size < MIN_SUPPORTED_ENDPORTS) { + IB_LOG_WARN_FMT(__func__, "SM subnet size of %d is too small, setting to %d", smp->subnet_size, MIN_SUPPORTED_ENDPORTS); + smp->subnet_size = MIN_SUPPORTED_ENDPORTS; + } + CKSUM_DATA(smp->subnet_size, CKSUM_OVERALL_DISRUPT_CONSIST); + + DEFAULT_AND_CKSUM_STR(smp->syslog_facility, "local6", CKSUM_OVERALL_DISRUPT); + DEFAULT_AND_CKSUM_STR(smp->routing_algorithm, "shortestpath", CKSUM_OVERALL_DISRUPT_CONSIST); + + DEFAULT_INT(smp->SslSecurityEnabled, 0); + DEFAULT_STR(smp->SslSecurityDir, FM_SSL_SECURITY_DIR); + DEFAULT_STR(smp->SslSecurityFmCertificate, "fm_cert.pem"); + DEFAULT_STR(smp->SslSecurityFmPrivateKey, "fm_key.pem"); + DEFAULT_STR(smp->SslSecurityFmCaCertificate, "fm_ca_cert.pem"); + DEFAULT_INT(smp->SslSecurityFmCertChainDepth, 1); + DEFAULT_STR(smp->SslSecurityFmDHParameters, "fm_dh_parms.pem"); + DEFAULT_INT(smp->SslSecurityFmCaCRLEnabled, 0); + DEFAULT_STR(smp->SslSecurityFmCaCRL, "fm_ca_crl.pem"); + + DEFAULT_AND_CKSUM_INT(smp->debug, 0, CKSUM_OVERALL_DISRUPT); + DEFAULT_AND_CKSUM_INT(smp->debug_rmpp, 0, CKSUM_OVERALL_DISRUPT); + DEFAULT_AND_CKSUM_INT(smp->priority, 0, CKSUM_OVERALL_DISRUPT); + DEFAULT_AND_CKSUM_INT(smp->elevated_priority, 0, CKSUM_OVERALL_DISRUPT); + // Currently, dynamic changes to sm log_level are supported. + DEFAULT_AND_CKSUM_INT(smp->log_level, 1, CKSUM_OVERALL); + // Dynamic changes to syslog_mode are not (yet) supported. + DEFAULT_AND_CKSUM_INT(smp->syslog_mode, 0, CKSUM_OVERALL_DISRUPT); + // Dynamic manual changes to log_masks are not (yet) supported. + // Therefore, add the log_masks to the overall and disruptive + // checksums BEFORE updating them based on defaults, + // log_level, and syslog_mode. + CKSUM_DATA(smp->log_masks, CKSUM_OVERALL_DISRUPT); + // after parsing is done, fill in unspecified log_masks based on log_level + set_log_masks(smp->log_level, smp->syslog_mode, smp->log_masks); + DEFAULT_AND_CKSUM_INT(smp->config_consistency_check_level, DEFAULT_CCC_LEVEL, CKSUM_OVERALL_DISRUPT_CONSIST); + DEFAULT_AND_CKSUM_INT(smp->path_selection, PATH_MODE_MINIMAL, CKSUM_OVERALL_DISRUPT_CONSIST); + DEFAULT_AND_CKSUM_INT(smp->queryValidation, 0, CKSUM_OVERALL_DISRUPT_CONSIST); + DEFAULT_AND_CKSUM_INT(smp->enforceVFPathRecs, 1, CKSUM_OVERALL_DISRUPT_CONSIST); + + DEFAULT_INT(smp->sma_batch_size, 2); + DEFAULT_INT(smp->max_parallel_reqs, 3); + DEFAULT_INT(smp->max_supported_lid, SM_DEFAULT_MAX_LID); + if (smp->sma_batch_size == 0) + smp->sma_batch_size = 1; + if (smp->max_parallel_reqs == 0) + smp->max_parallel_reqs = 1; + if (smp->max_supported_lid == 0) + smp->max_supported_lid = SM_DEFAULT_MAX_LID; + smp->max_supported_lid |= 0x3FF; // Rounded up to 1K boundary. + CKSUM_DATA(smp->sma_batch_size, CKSUM_OVERALL_DISRUPT_CONSIST); + CKSUM_DATA(smp->max_parallel_reqs, CKSUM_OVERALL_DISRUPT_CONSIST); + CKSUM_DATA(smp->max_supported_lid, CKSUM_OVERALL_DISRUPT_CONSIST); + + + DEFAULT_AND_CKSUM_INT(smp->check_mft_responses, 1, CKSUM_OVERALL_DISRUPT_CONSIST); + DEFAULT_AND_CKSUM_INT(smp->sm_debug_perf, 0, CKSUM_OVERALL_DISRUPT); + DEFAULT_AND_CKSUM_INT(smp->sa_debug_perf, 0, CKSUM_OVERALL_DISRUPT); + DEFAULT_AND_CKSUM_INT(smp->sm_debug_vf, 0, CKSUM_OVERALL_DISRUPT); + DEFAULT_AND_CKSUM_INT(smp->sm_debug_routing, 0, CKSUM_OVERALL_DISRUPT); + DEFAULT_AND_CKSUM_INT(smp->sm_dsap_enabled, 0, CKSUM_OVERALL_DISRUPT_CONSIST); + DEFAULT_AND_CKSUM_INT(smp->sm_debug_lid_assign, 0, CKSUM_OVERALL_DISRUPT); + DEFAULT_AND_CKSUM_INT(smp->debug_jm, 0, CKSUM_OVERALL_DISRUPT); + DEFAULT_AND_CKSUM_INT(smp->sa_rmpp_checksum, 0, CKSUM_OVERALL_DISRUPT); + DEFAULT_AND_CKSUM_INT(smp->loop_test_on, 0, CKSUM_OVERALL_DISRUPT); + DEFAULT_AND_CKSUM_INT(smp->loop_test_fast_mode, 0, CKSUM_OVERALL_DISRUPT); + DEFAULT_AND_CKSUM_INT(smp->loop_test_packets, 0, CKSUM_OVERALL_DISRUPT); + DEFAULT_AND_CKSUM_INT(smp->non_resp_tsec, NONRESP_TIMEOUT, CKSUM_OVERALL_DISRUPT_CONSIST); + DEFAULT_AND_CKSUM_INT(smp->non_resp_max_count, NONRESP_MAXRETRY, CKSUM_OVERALL_DISRUPT_CONSIST); + DEFAULT_AND_CKSUM_INT(smp->monitor_standby_enable, 1, CKSUM_OVERALL_DISRUPT_CONSIST); + DEFAULT_AND_CKSUM_INT(smp->dynamic_port_alloc, 1, CKSUM_OVERALL_DISRUPT); + DEFAULT_AND_CKSUM_INT(smp->loopback_mode, 0, CKSUM_OVERALL_DISRUPT_CONSIST); + DEFAULT_AND_CKSUM_INT(smp->force_rebalance, 0, CKSUM_OVERALL_DISRUPT_CONSIST); + DEFAULT_AND_CKSUM_INT(smp->use_cached_node_data, 0, CKSUM_OVERALL_DISRUPT_CONSIST); + DEFAULT_AND_CKSUM_INT(smp->sma_spoofing_check, 1, CKSUM_OVERALL_DISRUPT_CONSIST); + DEFAULT_AND_CKSUM_INT(smp->hfi_link_policy.link_max_downgrade, 1, CKSUM_OVERALL_DISRUPT_CONSIST); + DEFAULT_AND_CKSUM_INT(smp->hfi_link_policy.width_policy.enabled, 1, CKSUM_OVERALL_DISRUPT_CONSIST); + DEFAULT_AND_CKSUM_INT(smp->hfi_link_policy.width_policy.policy, 0, CKSUM_OVERALL_DISRUPT_CONSIST); + DEFAULT_AND_CKSUM_INT(smp->hfi_link_policy.speed_policy.enabled, 0, CKSUM_OVERALL_DISRUPT_CONSIST); + DEFAULT_AND_CKSUM_INT(smp->hfi_link_policy.speed_policy.policy, 0, CKSUM_OVERALL_DISRUPT_CONSIST); + DEFAULT_AND_CKSUM_INT(smp->isl_link_policy.link_max_downgrade, 1, CKSUM_OVERALL_DISRUPT_CONSIST); + DEFAULT_AND_CKSUM_INT(smp->isl_link_policy.width_policy.enabled, 1, CKSUM_OVERALL_DISRUPT_CONSIST); + DEFAULT_AND_CKSUM_INT(smp->isl_link_policy.width_policy.policy, 0, CKSUM_OVERALL_DISRUPT_CONSIST); + DEFAULT_AND_CKSUM_INT(smp->isl_link_policy.speed_policy.enabled, 0, CKSUM_OVERALL_DISRUPT_CONSIST); + DEFAULT_AND_CKSUM_INT(smp->isl_link_policy.speed_policy.policy, 0, CKSUM_OVERALL_DISRUPT_CONSIST); + DEFAULT_AND_CKSUM_INT(smp->port_quarantine.enabled, 1, CKSUM_OVERALL_DISRUPT_CONSIST); + DEFAULT_AND_CKSUM_INT(smp->port_quarantine.flapping.window_size, 15, CKSUM_OVERALL_DISRUPT_CONSIST); + DEFAULT_AND_CKSUM_INT(smp->port_quarantine.flapping.high_thresh, 25, CKSUM_OVERALL_DISRUPT_CONSIST); + DEFAULT_AND_CKSUM_INT(smp->port_quarantine.flapping.low_thresh, 0, CKSUM_OVERALL_DISRUPT_CONSIST); + DEFAULT_AND_CKSUM_INT(smp->preemption.small_packet, SM_PREEMPT_SMALL_PACKET_DEF, CKSUM_OVERALL_DISRUPT_CONSIST); + DEFAULT_AND_CKSUM_INT(smp->preemption.large_packet, SM_PREEMPT_LARGE_PACKET_DEF, CKSUM_OVERALL_DISRUPT_CONSIST); + DEFAULT_AND_CKSUM_INT(smp->preemption.preempt_limit, SM_PREEMPT_LIMIT_DEF, CKSUM_OVERALL_DISRUPT_CONSIST); + DEFAULT_AND_CKSUM_INT(smp->congestion.enable, 0, CKSUM_OVERALL_DISRUPT_CONSIST); + smp->use_cached_hfi_node_data = 0; + if (smp->use_cached_node_data) { + smp->use_cached_hfi_node_data = 1; + } + if (smp->congestion.enable) { + DEFAULT_AND_CKSUM_INT(smp->congestion.debug, 0, CKSUM_OVERALL_DISRUPT); + DEFAULT_AND_CKSUM_INT(smp->congestion.sw.victim_marking_enable, 0, CKSUM_OVERALL_DISRUPT_CONSIST); + DEFAULT_INT(smp->congestion.sw.threshold, 8); + if (smp->congestion.sw.threshold > 15) { + IB_LOG_WARN_FMT(__func__, "FM CC SwitchCongestionSetting:Threshold %d exceeds max value. Setting to max value (15).", smp->congestion.sw.threshold); + smp->congestion.sw.threshold = 15; + } + CKSUM_DATA(smp->congestion.sw.threshold, CKSUM_OVERALL_DISRUPT_CONSIST); + DEFAULT_INT(smp->congestion.sw.packet_size, 0); + if (smp->congestion.sw.packet_size > 162) { + IB_LOG_WARN_FMT(__func__, "FM CC SwitchCongestionSetting:Packet Size Limit %d exceeds max value. Setting to max value (162).", smp->congestion.sw.packet_size); + smp->congestion.sw.packet_size = 162; + } + CKSUM_DATA(smp->congestion.sw.packet_size, CKSUM_OVERALL_DISRUPT_CONSIST); + DEFAULT_AND_CKSUM_INT(smp->congestion.sw.cs_threshold, 0, CKSUM_OVERALL_DISRUPT_CONSIST); + DEFAULT_AND_CKSUM_INT(smp->congestion.sw.cs_return_delay, 0, CKSUM_OVERALL_DISRUPT_CONSIST); + DEFAULT_INT(smp->congestion.sw.marking_rate, 0); + if (smp->congestion.sw.marking_rate > 255) { + IB_LOG_WARN_FMT(__func__, "FM CC SwitchCongestionSetting:Marking Rate %d exceeds max value. Setting to max value (255).", smp->congestion.sw.marking_rate); + smp->congestion.sw.marking_rate = 255; + } + CKSUM_DATA(smp->congestion.sw.marking_rate, CKSUM_OVERALL_DISRUPT_CONSIST); + DEFAULT_AND_CKSUM_INT(smp->congestion.ca.sl_based, 0, CKSUM_OVERALL_DISRUPT_CONSIST); + DEFAULT_AND_CKSUM_INT(smp->congestion.ca.increase, 5, CKSUM_OVERALL_DISRUPT_CONSIST); + DEFAULT_AND_CKSUM_INT(smp->congestion.ca.timer, 10, CKSUM_OVERALL_DISRUPT_CONSIST); + DEFAULT_AND_CKSUM_INT(smp->congestion.ca.threshold, 8, CKSUM_OVERALL_DISRUPT_CONSIST); + DEFAULT_AND_CKSUM_INT(smp->congestion.ca.min, 0, CKSUM_OVERALL_DISRUPT_CONSIST); + DEFAULT_INT(smp->congestion.ca.limit, 127); + + // limit is max index == max_entries-1 + //Enforcing implementation limit for congestion rather than architectural limit (CONGESTION_CONTROL_TABLE_ENTRIES_PER_MAD-1). + if (smp->congestion.ca.limit > CONGESTION_CONTROL_IMPLEMENTATION_LIMIT ) { + IB_LOG_WARN_FMT(__func__, "FM CC SwitchCongestionSetting:CCTI Limit %d exceeds implementation limit. Setting to implementation limit (%d).", smp->congestion.ca.limit, + CONGESTION_CONTROL_IMPLEMENTATION_LIMIT); + smp->congestion.ca.limit = (uint16_t)(CONGESTION_CONTROL_IMPLEMENTATION_LIMIT); + } + if (smp->congestion.ca.limit == 0) { + IB_LOG_WARN_FMT(__func__, "FM CC SwitchCongestionSetting:CCTI Lower limit cannot be 0, setting to 1."); + smp->congestion.ca.limit = (uint16_t)(1); + } + + CKSUM_DATA(smp->congestion.ca.limit, CKSUM_OVERALL_DISRUPT_CONSIST); + DEFAULT_AND_CKSUM_INT(smp->congestion.ca.desired_max_delay, 8000, CKSUM_OVERALL_DISRUPT_CONSIST); + } + + DEFAULT_AND_CKSUM_INT(smp->adaptiveRouting.enable, 0, CKSUM_OVERALL_DISRUPT_CONSIST); + if (smp->adaptiveRouting.enable) { + DEFAULT_AND_CKSUM_INT(smp->adaptiveRouting.debug, 0, CKSUM_OVERALL_DISRUPT); + DEFAULT_AND_CKSUM_INT(smp->adaptiveRouting.lostRouteOnly, 0, CKSUM_OVERALL_DISRUPT_CONSIST); + DEFAULT_AND_CKSUM_INT(smp->adaptiveRouting.algorithm, 2, CKSUM_OVERALL_DISRUPT_CONSIST); + DEFAULT_AND_CKSUM_INT(smp->adaptiveRouting.arFrequency, 4, CKSUM_OVERALL_DISRUPT_CONSIST); + DEFAULT_AND_CKSUM_INT(smp->adaptiveRouting.threshold, 3, CKSUM_OVERALL_DISRUPT_CONSIST); + } + + // Checksum only the enabled routing algorithm + if (!strcasecmp(smp->routing_algorithm, "fattree")) { + DEFAULT_AND_CKSUM_INT(smp->ftreeRouting.passthru, 0, CKSUM_OVERALL_DISRUPT_CONSIST); + DEFAULT_AND_CKSUM_INT(smp->ftreeRouting.converge, 0, CKSUM_OVERALL_DISRUPT_CONSIST); + DEFAULT_AND_CKSUM_INT(smp->ftreeRouting.debug, 0, CKSUM_OVERALL_DISRUPT); + DEFAULT_AND_CKSUM_INT(smp->ftreeRouting.tierCount, 0, CKSUM_OVERALL_DISRUPT_CONSIST); + DEFAULT_AND_CKSUM_INT(smp->ftreeRouting.fis_on_same_tier, 0, CKSUM_OVERALL_DISRUPT_CONSIST); + CKSUM_STR(smp->ftreeRouting.coreSwitches.member, CKSUM_OVERALL_DISRUPT_CONSIST); + CKSUM_STR(smp->ftreeRouting.routeLast.member, CKSUM_OVERALL_DISRUPT_CONSIST); + } + + + if (!strcasecmp(smp->routing_algorithm, "dgshortestpath")) { + for (i = 0; i < smp->dgRouting.dgCount; i++) { + CKSUM_STR(smp->dgRouting.dg[i].member, CKSUM_OVERALL_DISRUPT_CONSIST); + } + } + + if (!strcasecmp(smp->routing_algorithm, "hypercube")) { + DEFAULT_AND_CKSUM_INT(smp->hypercubeRouting.debug, 0, CKSUM_OVERALL_DISRUPT); + CKSUM_STR(smp->hypercubeRouting.routeLast.member, CKSUM_OVERALL_DISRUPT_CONSIST); + + SPRoutingCtrl = smp->hypercubeRouting.enhancedRoutingCtrl; + if (SPRoutingCtrl == (void *)~0ul) { + SPRoutingCtrl = NULL; + smp->hypercubeRouting.enhancedRoutingCtrl = NULL; + } + + while (SPRoutingCtrl) { + SmSPRoutingPort_t *ports = SPRoutingCtrl->ports; + int portCount = SPRoutingCtrl->portCount; + + CKSUM_STR(SPRoutingCtrl->switches.member, CKSUM_OVERALL_DISRUPT_CONSIST); + for (i = 0; i < portCount; i++, ports++) { + CKSUM_DATA(ports->pport, CKSUM_OVERALL_DISRUPT_CONSIST); + CKSUM_DATA(ports->vport, CKSUM_OVERALL_DISRUPT_CONSIST); + CKSUM_DATA(ports->cost, CKSUM_OVERALL_DISRUPT_CONSIST); + } + SPRoutingCtrl = SPRoutingCtrl->next; + } + } + + if (!strcasecmp(smp->routing_algorithm, "dor")) { + // If using dor, checksum the smDorRouting config. + DEFAULT_AND_CKSUM_INT(smp->smDorRouting.dimensionCount, 0, CKSUM_OVERALL_DISRUPT_CONSIST); + DEFAULT_AND_CKSUM_INT(smp->smDorRouting.numToroidal, 0, CKSUM_OVERALL_DISRUPT_CONSIST); + CKSUM_DATA(smp->smDorRouting.dimension, CKSUM_OVERALL_DISRUPT_CONSIST); + DEFAULT_AND_CKSUM_INT(smp->smDorRouting.escapeVLs, DEFAULT_ESCAPE_VLS_IN_USE, CKSUM_OVERALL_DISRUPT_CONSIST); + DEFAULT_AND_CKSUM_INT(smp->smDorRouting.faultRegions, DEFAULT_FAULT_REGIONS_IN_USE, CKSUM_OVERALL_DISRUPT_CONSIST); + CKSUM_STR(smp->smDorRouting.routeLast.member, CKSUM_OVERALL_DISRUPT_CONSIST); + DEFAULT_AND_CKSUM_INT(smp->smDorRouting.debug,0, CKSUM_OVERALL_DISRUPT); + DEFAULT_AND_CKSUM_INT(smp->smDorRouting.warn_threshold, DEFAULT_DOR_PORT_PAIR_WARN_THRESHOLD, CKSUM_OVERALL_DISRUPT); + DEFAULT_AND_CKSUM_INT(smp->smDorRouting.routingSCs, 0, CKSUM_OVERALL_DISRUPT_CONSIST); + CKSUM_DATA(smp->smDorRouting.topology, CKSUM_OVERALL_DISRUPT_CONSIST); + DEFAULT_AND_CKSUM_INT(smp->smDorRouting.overlayMCast, 0, CKSUM_OVERALL_DISRUPT_CONSIST); + } + + DEFAULT_AND_CKSUM_INT(smp->appliances.enable, 0, CKSUM_OVERALL_DISRUPT_CONSIST); + if (smp->appliances.enable) + for (i = 0; i < MAX_SM_APPLIANCES; i++) + DEFAULT_AND_CKSUM_INT(smp->appliances.guids[i], 0, CKSUM_OVERALL_DISRUPT_CONSIST); + + DEFAULT_INT(smp->preDefTopo.enabled, 0) +#ifdef __VXWORKS__ + if(smp->preDefTopo.enabled) { + smp->preDefTopo.enabled = 0; + IB_LOG_ERROR0("Pre Defined Topology: (Disabled) Not supported on embedded platforms."); + } +#endif + // If no pre-defined topology filename was provided, disable the feature + if (!strlen(smp->preDefTopo.topologyFilename)) { + if (smp->preDefTopo.enabled) + IB_LOG_ERROR0("Pre Defined Topology: (Disabled) Empty topology file path."); + smp->preDefTopo.enabled = 0; + } + + DEFAULT_AND_CKSUM_INT(smp->preDefTopo.enabled, 0, CKSUM_OVERALL_DISRUPT_CONSIST); + if(smp->preDefTopo.enabled) { + CKSUM_STR(smp->preDefTopo.topologyFilename, CKSUM_OVERALL_DISRUPT); + CKSUM_FILE(smp->preDefTopo.topologyFilename, CKSUM_OVERALL_DISRUPT_CONSIST); + DEFAULT_AND_CKSUM_INT(smp->preDefTopo.logMessageThreshold, 0, CKSUM_OVERALL_DISRUPT_CONSIST); + DEFAULT_AND_CKSUM_INT(smp->preDefTopo.fieldEnforcement.nodeDesc, FIELD_ENF_LEVEL_DISABLED, CKSUM_OVERALL_DISRUPT_CONSIST); + DEFAULT_AND_CKSUM_INT(smp->preDefTopo.fieldEnforcement.nodeGuid, FIELD_ENF_LEVEL_DISABLED, CKSUM_OVERALL_DISRUPT_CONSIST); + DEFAULT_AND_CKSUM_INT(smp->preDefTopo.fieldEnforcement.portGuid, FIELD_ENF_LEVEL_DISABLED, CKSUM_OVERALL_DISRUPT_CONSIST); + DEFAULT_AND_CKSUM_INT(smp->preDefTopo.fieldEnforcement.undefinedLink, FIELD_ENF_LEVEL_DISABLED, CKSUM_OVERALL_DISRUPT_CONSIST); + } + + DEFAULT_AND_CKSUM_INT(smp->multicast_mask, SM_DEFAULT_MULTICAST_MASK, CKSUM_OVERALL_DISRUPT_CONSIST); + if (smp->multicast_mask == 0 || smp->multicast_mask > 7) { + IB_LOG_ERROR_FMT(__func__,"Terminating FM: MulticastMask (%d) out of range, valid values 1-7.", smp->multicast_mask); + return 0; + } + + DEFAULT_AND_CKSUM_INT(smp->lid_strategy, LID_STRATEGY_SERIAL, CKSUM_OVERALL_DISRUPT_CONSIST); + if (smp->lid_strategy == LID_STRATEGY_TOPOLOGY && !smp->preDefTopo.enabled) { + IB_LOG_ERROR_FMT(__func__,"Terminating FM: Topology-LID strategy requires Pre Defined Topology enabled."); + return 0; + } + + if (smp->lid_strategy == LID_STRATEGY_TOPOLOGY && smp->lid != 0) { + IB_LOG_WARN_FMT(__func__, "LID strategy is Topology but user-specified" + " SM LID is non-zero. Ignoring user-specified SM LID."); + smp->lid = 0; + } + +#ifdef __VXWORKS__ + uint8_t testLmc = smp->lmc_e0; // Assume SM on enhanced SP0 + const char *lmcStr = "LmcE0"; +#else + uint8_t testLmc = smp->lmc; // Assume SM on HFI + const char *lmcStr = "Lmc"; +#endif + + // If user-defined SM LID is given, must be divisible by LMC + if (smp->lid_strategy == LID_STRATEGY_SERIAL && smp->lid != 0 && smp->lid % (1 << testLmc) != 0) { + IB_LOG_ERROR_FMT(__func__, "Terminating: User-specified SM LID" + " must be divisible by %d (%s is %d)", (1 << testLmc), lmcStr, testLmc); + return 0; + } + + // Verify that if DsapInUse is enabled, LidStrategy is set to Topology. + if ( (smp->sm_dsap_enabled == 1) && (smp->lid_strategy != LID_STRATEGY_TOPOLOGY) ) { + IB_LOG_ERROR_FMT(__func__, "LidStrategy must be set to Topology when DsapInUse is enabled"); + return 0; +} + + DEFAULT_AND_CKSUM_INT(smp->minSharedVLMem, 0, CKSUM_OVERALL_DISRUPT_CONSIST); + DEFAULT_AND_CKSUM_INT(smp->dedicatedVLMemMulti, 1, CKSUM_OVERALL_DISRUPT_CONSIST); + DEFAULT_AND_CKSUM_INT(smp->cableInfoPolicy, CIP_LINK, CKSUM_OVERALL_DISRUPT_CONSIST); + DEFAULT_AND_CKSUM_INT(smp->timerScalingEnable, 0, CKSUM_OVERALL_DISRUPT_CONSIST); + DEFAULT_AND_CKSUM_INT(smp->min_supported_vls, 8, CKSUM_OVERALL_DISRUPT_CONSIST); + DEFAULT_AND_CKSUM_INT(smp->max_fixed_vls, 8, CKSUM_OVERALL_DISRUPT_CONSIST); + DEFAULT_AND_CKSUM_INT(smp->allow_mixed_vls, 0, CKSUM_OVERALL_DISRUPT_CONSIST); + + CKSUM_DATA(smp->wireDepthOverride, CKSUM_OVERALL_DISRUPT_CONSIST); + CKSUM_DATA(smp->replayDepthOverride, CKSUM_OVERALL_DISRUPT_CONSIST); + + // If NoReplyIfBusy is set to 1, a MAD_STATUS_BUSY will not be returned to the SA requester. + DEFAULT_AND_CKSUM_INT(smp->NoReplyIfBusy, 0, CKSUM_OVERALL_DISRUPT_CONSIST); + + if ((smp->lft_multi_block == UNDEFINED_XML32) || (smp->lft_multi_block > (STL_MAX_PAYLOAD_SMP_DR/MAX_LFT_ELEMENTS_BLOCK))) + smp->lft_multi_block = STL_MAX_PAYLOAD_SMP_DR/MAX_LFT_ELEMENTS_BLOCK; + CKSUM_DATA(smp->lft_multi_block, CKSUM_OVERALL_DISRUPT_CONSIST); + DEFAULT_AND_CKSUM_INT(smp->use_aggregates, 1, CKSUM_OVERALL_DISRUPT_CONSIST); + DEFAULT_AND_CKSUM_INT(smp->optimized_buffer_control, 1, CKSUM_OVERALL_DISRUPT_CONSIST); + + DEFAULT_AND_CKSUM_INT(smp->forceAttributeRewrite, 0, CKSUM_OVERALL_DISRUPT_CONSIST); + DEFAULT_AND_CKSUM_INT(smp->skipAttributeWrite, 0, CKSUM_OVERALL_DISRUPT_CONSIST); + + if (smp->defaultPortErrorAction == UNDEFINED_XML32) { + // Making defaultPortErrorAction a _PortErrorAction would make more sense + // but I can't find guarantees IXML_FIELD(SMXmlConfig_t, defPortErrorAction) + // would coincide with the .AsReg32 field of _PortErrorAction + union _PortErrorAction defPea = { 0 }; + defPea.s.FmConfigErrorBadHeadDist = 1; + defPea.s.FmConfigErrorBadTailDist = 1; + defPea.s.FmConfigErrorBadCtrlDist = 1; + defPea.s.FmConfigErrorUnsupportedVLMarker = 1; + defPea.s.PortRcvErrorBadVLMarker = 1; + smp->defaultPortErrorAction = defPea.AsReg32; + } + CKSUM_DATA(smp->defaultPortErrorAction, CKSUM_OVERALL_DISRUPT_CONSIST); + + DEFAULT_AND_CKSUM_INT(smp->switchCascadeActivateEnable, 1, CKSUM_OVERALL_DISRUPT_CONSIST); + DEFAULT_AND_CKSUM_INT(smp->neighborNormalRetries, 2, CKSUM_OVERALL_DISRUPT_CONSIST); + DEFAULT_AND_CKSUM_INT(smp->terminateAfter, 0, CKSUM_OVERALL_DISRUPT_CONSIST); + DEFAULT_AND_CKSUM_INT(smp->psThreads, 4, CKSUM_OVERALL_DISRUPT_CONSIST); + DEFAULT_AND_CKSUM_INT(smp->portBounceLogLimit, PORT_BOUNCE_LOG_NO_LIMIT, CKSUM_OVERALL_DISRUPT_CONSIST); + // FIXME: cjking - Temporary patch for FPGA related PR-124905 + DEFAULT_AND_CKSUM_INT(smp->neighborFWAuthenEnable, 0, CKSUM_OVERALL_DISRUPT_CONSIST); + + DEFAULT_AND_CKSUM_INT(smp->cumulative_timeout_limit, 300 * VTIMER_1S, CKSUM_OVERALL_DISRUPT_CONSIST); + + CKSUM_STR(smp->dumpCounters, CKSUM_OVERALL_DISRUPT); + + + CKSUM_DATA(smp->subnet_prefix, CKSUM_OVERALL_DISRUPT_CONSIST); + + // Verify interdependencies + if (smp->lid >= smp->max_supported_lid) { + IB_LOG_ERROR_FMT(__func__, "Value LID (0x%x) needs to be less than MaximumLID (0x%x)\n",smp->lid,smp->max_supported_lid); + return 0; + } + if (smp->max_supported_lid > 0x00EFFFFF) { + // LID range from 0xF00000-0xFFFFFF are reserved for multicast operation in HW. + IB_LOG_ERROR_FMT(__func__, "MaximumLID (0x%x) setting is out of range.\n", smp->max_supported_lid); + return 0; + } + return 1; +} + +// Free SM configs +void smFreeConfig(SMXmlConfig_t *smp) +{ + smFreeHypercubeRouting(smp); + freeXmlMemory(smp, sizeof(SMXmlConfig_t), "SMXmlConfig_t smFreeConfig()"); +} + +// Copy SM configs +boolean smCopyConfig(SMXmlConfig_t *dst, SMXmlConfig_t *src) +{ + SmSPRoutingCtrl_t *SPRoutingCtrl; + SmSPRoutingCtrl_t **prev; + + if (!src || !dst) + return 0; + + // Nothing to do if src and dst are the same. + if (src == dst) return 1; + + // Copy everything first, then handle the qmap + *dst = *src; + + // Make a copy of the SPRoutingCtrl + SPRoutingCtrl = src->hypercubeRouting.enhancedRoutingCtrl; + prev = &dst->hypercubeRouting.enhancedRoutingCtrl; + if (SPRoutingCtrl == (void *)~0ul) { + SPRoutingCtrl = NULL; + } + while (SPRoutingCtrl) { + int portsSize = ROUNDUP(SPRoutingCtrl->portCount, PORTS_ALLOC_UNIT); + SmSPRoutingCtrl_t *dstSPRoutingCtrl; + + dstSPRoutingCtrl = getXmlMemory(sizeof(*dstSPRoutingCtrl), "SmSPRoutingCtrl_t *dstSPRoutingCtrl"); + if (!dstSPRoutingCtrl) { + fprintf(stderr, "%s: Memory limit exceeded for dstSPRoutingCtrl\n", + __func__); + return FALSE; + } + memcpy(dstSPRoutingCtrl, SPRoutingCtrl, sizeof(*dstSPRoutingCtrl)); + if (portsSize) { + SmSPRoutingPort_t *ports; + + ports = getXmlMemory(portsSize*sizeof(*ports), "SmSPRoutingPort_t *ports"); + if (!ports) { + freeXmlMemory(dstSPRoutingCtrl, sizeof(SmSPRoutingCtrl_t), "SmSPRoutingCtrl_t *dstSPRoutingCtrl"); + fprintf(stderr, "%s: Memory limit exceeded for ports\n", + __func__); + return FALSE; + } + memcpy(ports, SPRoutingCtrl->ports, portsSize*sizeof(*ports)); + dstSPRoutingCtrl->ports = ports; + } + *prev = dstSPRoutingCtrl; + prev = &dstSPRoutingCtrl->next; + + SPRoutingCtrl = SPRoutingCtrl->next; + } + + return 1; +} + +// show the SM XML config +void smShowConfig(SMXmlConfig_t *smp, SMDPLXmlConfig_t *dplp, SMMcastConfig_t *mcp, SmMcastMlidShare_t *mlsp) +{ + uint32_t i; + char str[32]; + SmSPRoutingCtrl_t *SPRoutingCtrl; + + if (!smp || !dplp || !mcp || !mlsp) + return; + + printf("XML - hca %u\n", (unsigned int)smp->hca); + printf("XML - port %u\n", (unsigned int)smp->port); + printf("XML - port_guid %u\n", (unsigned int)smp->port_guid); + printf("XML - name %s\n", smp->name); + printf("XML - sm_key 0x%16.16llx\n", (long long unsigned int)smp->sm_key); + printf("XML - mkey 0x%16.16llx\n", (long long unsigned int)smp->mkey); + printf("XML - timer %llu\n", (long long unsigned int)smp->timer); + printf("XML - IgnoreTraps %u\n", (unsigned int)smp->IgnoreTraps); + printf("XML - trap_hold_down %u\n", (unsigned int)smp->trap_hold_down); + printf("XML - max_retries %u\n", (unsigned int)smp->max_retries); + printf("XML - rcv_wait_msec %u\n", (unsigned int)smp->rcv_wait_msec); + printf("XML - min_rcv_wait_msec %u\n", (unsigned int)smp->min_rcv_wait_msec); + printf("XML - master_ping_interval %u\n", (unsigned int)smp->master_ping_interval); + printf("XML - master_ping_max_fail %u\n", (unsigned int)smp->master_ping_max_fail); + printf("XML - topo_errors_threshold %u\n", (unsigned int)smp->topo_errors_threshold); + printf("XML - topo_abandon_threshold %u\n", (unsigned int)smp->topo_abandon_threshold); + printf("XML - switch_lifetime_n2 %u\n", (unsigned int)smp->switch_lifetime_n2); + printf("XML - hoqlife_n2 %u\n", (unsigned int)smp->hoqlife_n2); + printf("XML - sa_resp_time_n2 %u\n", (unsigned int)smp->sa_resp_time_n2); + printf("XML - sa_packet_lifetime_n2 %u\n", (unsigned int)smp->sa_packet_lifetime_n2); + printf("XML - vlstall %u\n", (unsigned int)smp->vlstall); + printf("XML - db_sync_interval %u\n", (unsigned int)smp->db_sync_interval); + printf("XML - trap_threshold %u\n", (unsigned int)smp->trap_threshold); + printf("XML - trap_threshold_min_count %u\n", (unsigned int)smp->trap_threshold_min_count); + printf("XML - trap_log_suppress_trigger_interval %u\n", (unsigned int)smp->trap_log_suppress_trigger_interval); + printf("XML - mc_dos_threshold %u\n", (unsigned int)smp->mc_dos_threshold); + printf("XML - mc_dos_action %u\n", (unsigned int)smp->mc_dos_action); + printf("XML - mc_dos_interval %u\n", (unsigned int)smp->mc_dos_interval); + printf("XML - node_appearance_msg_thresh %u\n", (unsigned int)smp->node_appearance_msg_thresh); + printf("XML - spine_first_routing %u\n", (unsigned int)smp->spine_first_routing); + printf("XML - shortestPathBalanced %u\n", (unsigned int)smp->shortestPathBalanced); + printf("XML - lid 0x%x\n", (unsigned int)smp->lid); + printf("XML - lmc 0x%x\n", (unsigned int)smp->lmc); + printf("XML - lmc_e0 0x%x\n", (unsigned int)smp->lmc_e0); + printf("XML - subnet_size %u\n", (unsigned int)smp->subnet_size); +#ifndef __VXWORKS__ + printf("XML - syslog_facility %s\n", smp->syslog_facility); + for (i = 0; i <= VIEO_LAST_MOD_ID; ++i) + printf("XML - log_mask[%u] 0x%x\n", i, (unsigned int)smp->log_masks[i].value); +#endif + printf("XML - SslSecurityEnabled %u\n", (unsigned int)smp->SslSecurityEnabled); + printf("XML - SslSecurityDir %s\n", smp->SslSecurityDir); + printf("XML - SslSecurityFmCertificate %s\n", smp->SslSecurityFmCertificate); + printf("XML - SslSecurityFmPrivateKey %s\n", smp->SslSecurityFmPrivateKey); + printf("XML - SslSecurityFmCaCertificate %s\n", smp->SslSecurityFmCaCertificate); + printf("XML - SslSecurityFmCertChainDepth %u\n", (unsigned int)smp->SslSecurityFmCertChainDepth); + printf("XML - SslSecurityFmDHParameters %s\n", smp->SslSecurityFmDHParameters); + printf("XML - SslSecurityFmCaCRLEnabled %u\n", (unsigned int)smp->SslSecurityFmCaCRLEnabled); + printf("XML - SslSecurityFmCaCRL %s\n", smp->SslSecurityFmCaCRL); + + printf("XML - log_file %s\n", smp->log_file); + printf("XML - debug %u\n", (unsigned int)smp->debug); + printf("XML - debug_rmpp %u\n", (unsigned int)smp->debug_rmpp); + printf("XML - priority %u\n", (unsigned int)smp->priority); + printf("XML - elevated_priority %u\n", (unsigned int)smp->elevated_priority); + printf("XML - log_level %u\n", (unsigned int)smp->log_level); + printf("XML - syslog_mode %u\n", (unsigned int)smp->syslog_mode); + printf("XML - config_consistency_check_level %u\n", (unsigned int)smp->config_consistency_check_level); + printf("XML - routing_algorithm %s\n", smp->routing_algorithm); + printf("XML - path_selection %u\n", (unsigned int)smp->path_selection); + printf("XML - queryValidation %u\n", (unsigned int)smp->queryValidation); + printf("XML - enforceVFPathRecs %u\n", (unsigned int)smp->enforceVFPathRecs); + printf("XML - sma_batch_size %u\n", (unsigned int)smp->sma_batch_size); + printf("XML - max_parallel_reqs %u\n", (unsigned int)smp->max_parallel_reqs); + printf("XML - check_mft_responses %u\n", (unsigned int)smp->check_mft_responses); + printf("XML - sm_debug_perf %u\n", (unsigned int)smp->sm_debug_perf); + printf("XML - sa_debug_perf %u\n", (unsigned int)smp->sa_debug_perf); + printf("XML - sm_debug_vf %u\n", (unsigned int)smp->sm_debug_vf); + printf("XML - sm_debug_routing %u\n", (unsigned int)smp->sm_debug_routing); + printf("XML - sm_dsap_enabled %u\n", (unsigned int)smp->sm_dsap_enabled); + printf("XML - sm_debug_lid_assign %u\n", (unsigned int)smp->sm_debug_lid_assign); + printf("XML - debug_jm %u\n", (unsigned int)smp->debug_jm); + printf("XML - sa_rmpp_checksum %u\n", (unsigned int)smp->sa_rmpp_checksum); + printf("XML - loop_test_on %u\n", (unsigned int)smp->loop_test_on); + printf("XML - loop_test_fast_mode %u\n", (unsigned int)smp->loop_test_fast_mode); + printf("XML - loop_test_packets %u\n", (unsigned int)smp->loop_test_packets); + printf("XML - multicast_mask %u\n", (unsigned int)smp->multicast_mask); + printf("XML - lid_strategy %u\n", (unsigned int)smp->lid_strategy); + printf("XML - non_resp_tsec %u\n", (unsigned int)smp->non_resp_tsec); + printf("XML - non_resp_max_count %u\n", (unsigned int)smp->non_resp_max_count); + printf("XML - monitor_standby_enable %u\n", (unsigned int)smp->monitor_standby_enable); + printf("XML - dynamic_port_alloc %u\n", (unsigned int)smp->dynamic_port_alloc); + printf("XML - loopback_mode %u\n", (unsigned int)smp->loopback_mode); + printf("XML - force_rebalance %u\n", (unsigned int)smp->force_rebalance); + printf("XML - use_cached_node_data %u\n", (unsigned int)smp->use_cached_node_data); + printf("XML - NoReplyIfBusy %u\n", (unsigned int)smp->NoReplyIfBusy); + printf("XML - lft_multi_block %u\n", (unsigned int)smp->lft_multi_block); + printf("XML - use_aggregates %u\n", (unsigned int)smp->use_aggregates); + printf("XML - optimized_buffer_control %u\n", (unsigned int)smp->optimized_buffer_control); + printf("XML - sma_spoofing_check %u\n", (unsigned int)smp->sma_spoofing_check); + printf("XML - minSharedVLMem %u\n", (unsigned int)smp->minSharedVLMem); + printf("XML - dedicatedVLMemMulti %u\n", (unsigned int)smp->dedicatedVLMemMulti); + printf("XML - wireDepthOverride %d\n", (unsigned int)smp->wireDepthOverride); + printf("XML - replayDepthOverride %d\n", (unsigned int)smp->replayDepthOverride); + printf("XML - timerScalingEnable %d\n", (unsigned int) smp->timerScalingEnable); + printf("XML - min_supported_vls %d\n", (unsigned int)smp->min_supported_vls); + printf("XML - max_fixed_vls %d\n", (unsigned int)smp->max_fixed_vls); + printf("XML - allow_mixed_vls %d\n", (unsigned int)smp->allow_mixed_vls); + printf("XML - hfi_link_policy.link_max_downgrade 0x%x\n", (unsigned int)smp->hfi_link_policy.link_max_downgrade); + printf("XML - hfi_link_policy.link_width.enabled 0x%x\n", (unsigned int)smp->hfi_link_policy.width_policy.enabled); + printf("XML - hfi_link_policy.link_width.policy 0x%x\n", (unsigned int)smp->hfi_link_policy.width_policy.policy); + printf("XML - hfi_link_policy.link_speed.enabled 0x%x\n", (unsigned int)smp->hfi_link_policy.speed_policy.enabled); + printf("XML - hfi_link_policy.link_speed.policy 0x%x\n", (unsigned int)smp->hfi_link_policy.speed_policy.policy); + printf("XML - isl_link_policy.link_max_downgrade 0x%x\n", (unsigned int)smp->isl_link_policy.link_max_downgrade); + printf("XML - isl_link_policy.link_width.enabled 0x%x\n", (unsigned int)smp->isl_link_policy.width_policy.enabled); + printf("XML - isl_link_policy.link_width.policy 0x%x\n", (unsigned int)smp->isl_link_policy.width_policy.policy); + printf("XML - isl_link_policy.link_speed.enabled 0x%x\n", (unsigned int)smp->isl_link_policy.speed_policy.enabled); + printf("XML - isl_link_policy.link_speed.policy 0x%x\n", (unsigned int)smp->isl_link_policy.speed_policy.policy); + printf("XML - port_quarantine.enabled 0x%x\n", (unsigned int)smp->port_quarantine.enabled); + printf("XML - preemption.small_packet 0x%x\n", (unsigned int) smp->preemption.small_packet); + printf("XML - preemption.large_packet 0x%x\n", (unsigned int) smp->preemption.large_packet); + printf("XML - preemption.preempt_limit 0x%x\n", (unsigned int) smp->preemption.preempt_limit); + printf("XML - congestion.enable %u\n", (unsigned int)smp->congestion.enable); + printf("XML - congestion.debug %u\n", (unsigned int)smp->congestion.debug); + printf("XML - congestion.sw.victim_marking_enable %u\n", (unsigned int)smp->congestion.sw.victim_marking_enable); + printf("XML - congestion.sw.threshold %u\n", (unsigned int)smp->congestion.sw.threshold); + printf("XML - congestion.sw.packet_size %u\n", (unsigned int)smp->congestion.sw.packet_size); + printf("XML - congestion.sw.cs_threshold %u\n", (unsigned int)smp->congestion.sw.cs_threshold); + printf("XML - congestion.sw.cs_return_delay %u\n", (unsigned int)smp->congestion.sw.cs_return_delay); + printf("XML - congestion.sw.marking_rate %u\n", (unsigned int)smp->congestion.sw.marking_rate); + printf("XML - congestion.ca.increase %u\n", (unsigned int)smp->congestion.ca.increase); + printf("XML - congestion.ca.timer %u\n", (unsigned int)smp->congestion.ca.timer); + printf("XML - congestion.ca.threshold %u\n", (unsigned int)smp->congestion.ca.threshold); + printf("XML - congestion.ca.min %u\n", (unsigned int)smp->congestion.ca.min); + printf("XML - congestion.ca.limit %u\n", (unsigned int)smp->congestion.ca.limit); + printf("XML - congestion.ca.desired_max_delay %u\n", smp->congestion.ca.desired_max_delay); + + printf("XML - adaptiveRouting.enable %u\n", (unsigned int)smp->adaptiveRouting.enable); + printf("XML - adaptiveRouting.debug %u\n", (unsigned int)smp->adaptiveRouting.debug); + printf("XML - adaptiveRouting.lostRouteOnly %u\n", (unsigned int)smp->adaptiveRouting.lostRouteOnly); + printf("XML - adaptiveRouting.algorithm %u\n", (unsigned int)smp->adaptiveRouting.algorithm); + printf("XML - adaptiveRouting.arFrequency %u\n", (unsigned int)smp->adaptiveRouting.arFrequency); + printf("XML - adaptiveRouting.threshold %u\n", (unsigned int)smp->adaptiveRouting.threshold); + + printf("XML - ftreeRouting.passthru %u\n", (unsigned int)smp->ftreeRouting.passthru); + printf("XML - ftreeRouting.converge %u\n", (unsigned int)smp->ftreeRouting.converge); + printf("XML - ftreeRouting.debug %u\n", (unsigned int)smp->ftreeRouting.debug); + printf("XML - ftreeRouting.tierCount %u\n", (unsigned int)smp->ftreeRouting.tierCount); + printf("XML - ftreeRouting.fis_on_same_tier %u\n", (unsigned int)smp->ftreeRouting.fis_on_same_tier); + printf("XML - ftreeRouting.coreSwitches %s\n", smp->ftreeRouting.coreSwitches.member); + printf("XML - ftreeRouting.routeLast %s\n", smp->ftreeRouting.routeLast.member); + + SPRoutingCtrl = smp->hypercubeRouting.enhancedRoutingCtrl; + while (SPRoutingCtrl) { + SmSPRoutingPort_t *ports = SPRoutingCtrl->ports; + int portCount = SPRoutingCtrl->portCount; + + printf("XML - SPRoutingCtrl.switches = %s, pPort, vPort, cost:", SPRoutingCtrl->switches.member); + for (i = 0; i < portCount; i++, ports++) { + printf("XML %d %d %d\n", ports->pport, ports->vport, ports->cost); + } + SPRoutingCtrl = SPRoutingCtrl->next; + } + + + printf("XML - cableInfoPolicy %u\n", (unsigned int)smp->cableInfoPolicy); + printf("XML - terminateAfter %u\n", (unsigned int)smp->terminateAfter); + printf("XML - psThreads %u\n", (unsigned int)smp->psThreads); + printf("XML - dumpCounters %s\n", smp->dumpCounters); + + printf("XML - sm_mc_config.mcast_mlid_table_cap %u\n", (unsigned int)mcp->mcast_mlid_table_cap); + printf("XML - sm_mc_config.disable_mcast_check %u\n", (unsigned int)mcp->disable_mcast_check); + printf("XML - sm_mc_config.enable_pruning %u\n", (unsigned int)mcp->enable_pruning); + printf("XML - sm_mc_config.mcroot_select_algorithm %s\n", mcp->mcroot_select_algorithm); + printf("XML - sm_mc_config.mcroot_min_cost_improvement %s\n", mcp->mcroot_min_cost_improvement); + + StringCopy(str, "dynamicPlt", sizeof(str)); + for (i = 0; i < DYNAMIC_PACKET_LIFETIME_ARRAY_SIZE; i++) { + printf("XML - %s %u\n", str, (unsigned int)dplp->dp_lifetime[i]); + snprintf(str, 32, "dynamicPlt_%.2u", (unsigned int)(i + 1)); + } + + for (i = 0; i < MAX_SUPPORTED_MCAST_GRP_CLASSES; ++i) { + snprintf(str, 32, "mcastGrpMGidLimitMask_%u", (unsigned int)i); + printf("XML - %s %s\n", str, mlsp->mcastMlid[i].mcastGrpMGidLimitMaskConvert.value); + snprintf(str, 32, "mcastGrpMGidLimitValue_%u", (unsigned int)i); + printf("XML - %s %s\n", str, mlsp->mcastMlid[i].mcastGrpMGidLimitValueConvert.value); + snprintf(str, 32, "mcastGrpMGidLimitMax_%u", (unsigned int)i); + printf("XML - %s %u\n", str, (unsigned int)mlsp->mcastMlid[i].mcastGrpMGidLimitMax); + } +} + +static +void smDplClearConfig(SMDPLXmlConfig_t *smDpl) +{ + // Nothing to do +} + +static +boolean smDplInitConfig(SMDPLXmlConfig_t *smDpl) +{ + uint32_t i; + + if (!smDpl) + return 0; + + DEFAULT_AND_CKSUM_INT(smDpl->dp_lifetime[0], 0x01, CKSUM_OVERALL_DISRUPT_CONSIST); + for (i = 1; i < DYNAMIC_PACKET_LIFETIME_ARRAY_SIZE; i++) + DEFAULT_AND_CKSUM_INT(smDpl->dp_lifetime[i], 0x0, CKSUM_OVERALL_DISRUPT_CONSIST); + return 1; +} + +boolean smDplCopyConfig(SMDPLXmlConfig_t *dst, SMDPLXmlConfig_t *src) +{ + if (!src || !dst) + return 0; + + // Nothing to do if src and dst are the same. + if (src == dst) return 1; + + *dst = *src; + return 1; +} + +void smDplShowConfig(SMDPLXmlConfig_t *smDpl) +{ + // TODO +} + +static +void smMcClearConfig(SMMcastConfig_t *smMc) +{ + memset(smMc->mcroot_select_algorithm, 0, sizeof(smMc->mcroot_select_algorithm)); + memset(smMc->mcroot_min_cost_improvement, 0, sizeof(smMc->mcroot_min_cost_improvement)); +} + +static +boolean smMcInitConfig(SMMcastConfig_t *smMc) +{ + if (!smMc) + return 0; + + DEFAULT_AND_CKSUM_INT(smMc->disable_mcast_check, 0x0, CKSUM_OVERALL_DISRUPT_CONSIST); + DEFAULT_AND_CKSUM_INT(smMc->enable_pruning, 0, CKSUM_OVERALL_DISRUPT_CONSIST); + DEFAULT_AND_CKSUM_INT(smMc->mcast_mlid_table_cap, DEFAULT_SW_MLID_TABLE_CAP, CKSUM_OVERALL_DISRUPT_CONSIST); + CKSUM_STR(smMc->mcroot_select_algorithm, CKSUM_OVERALL_DISRUPT_CONSIST); + CKSUM_STR(smMc->mcroot_min_cost_improvement, CKSUM_OVERALL_DISRUPT_CONSIST); + return 1; +} + +boolean smMcCopyConfig(SMMcastConfig_t *dst, SMMcastConfig_t *src) +{ + if (!src || !dst) + return 0; + + // Nothing to do if src and dst are the same. + if (src == dst) return 1; + + *dst = *src; + return 1; +} + +void smMcShowConfig(SMMcastConfig_t *smMc) +{ + // TODO +} + +static +void smMlsClearConfig(SmMcastMlidShare_t *smMls) +{ + uint32_t i; + + // init Multicast MLIDShared values + smMls->number_of_shared = 0; + for (i = 0; i < MAX_SUPPORTED_MCAST_GRP_CLASSES_XML; i++) { + smMls->mcastMlid[i].enable = 0; + smMls->mcastMlid[i].mcastGrpMGidLimitMax = 0; + smMls->mcastMlid[i].mcastGrpMGidperPkeyMax = 0; + sprintf(&smMls->mcastMlid[i].mcastGrpMGidLimitMaskConvert.value[0], "00000000000000000000000000000000"); + sprintf(&smMls->mcastMlid[i].mcastGrpMGidLimitValueConvert.value[0], "00000000000000000000000000000000"); + } +} + +static +boolean smMlsInitConfig(SmMcastMlidShare_t *smMls) +{ + uint32_t i; + + if (!smMls) + return 0; + + for (i = 0; i < MAX_SUPPORTED_MCAST_GRP_CLASSES_XML; i++) { + CKSUM_DATA(smMls->mcastMlid[i].enable, CKSUM_OVERALL_DISRUPT_CONSIST); + CKSUM_DATA(smMls->mcastMlid[i].mcastGrpMGidLimitMax, CKSUM_OVERALL_DISRUPT_CONSIST); + CKSUM_DATA(smMls->mcastMlid[i].mcastGrpMGidperPkeyMax, CKSUM_OVERALL_DISRUPT_CONSIST); + CKSUM_DATA(smMls->mcastMlid[i].mcastGrpMGidLimitMaskConvert, CKSUM_OVERALL_DISRUPT_CONSIST); + CKSUM_DATA(smMls->mcastMlid[i].mcastGrpMGidLimitValueConvert, CKSUM_OVERALL_DISRUPT_CONSIST); + } + return 1; +} + +boolean smMlsCopyConfig(SmMcastMlidShare_t *dst, SmMcastMlidShare_t *src) +{ + if (!src || !dst) + return 0; + + // Nothing to do if src and dst are the same. + if (src == dst) return 1; + + *dst = *src; + return 1; +} + +void smMlsShowConfig(SmMcastMlidShare_t *smMls) +{ + // TODO +} + +static +void smMdgClearConfig(SMMcastDefGrpCfg_t *smMdg) +{ + uint32_t i; + + // init Default Group values + smMdg->number_of_groups = 0; + for (i = 0; i < MAX_DEFAULT_GROUPS; i++) { + memset(smMdg->group[i].virtual_fabric, 0, sizeof(smMdg->group[i].virtual_fabric)); + memset(smMdg->group[i].mgid, 0, sizeof(smMdg->group[i].mgid)); + memset(smMdg->group[i].mgid_range, 0, sizeof(smMdg->group[i].mgid_range)); + memset(smMdg->group[i].mgid_masked, 0, sizeof(smMdg->group[i].mgid_masked)); + } +} + +static +boolean smMdgInitConfig(SMMcastDefGrpCfg_t *smMdg) +{ + // Not checksummed? TODO + return 1; +} + +boolean smMdgCopyConfig(SMMcastDefGrpCfg_t *dst, SMMcastDefGrpCfg_t *src) +{ + if (!src || !dst) + return 0; + + // Nothing to do if src and dst are the same. + if (src == dst) return 1; + + *dst = *src; + return 1; +} + +void smMdgShowConfig(SMMcastDefGrpCfg_t *smMdg) +{ + // TODO +} + +static +void vfClearConfig(VFXmlConfig_t *vf) +{ + vf->number_of_vfs = 0; + + // clear all pointers to VirtualFabrics + memset(vf->vf, 0, sizeof(vf->vf)); +} + +static +boolean vfInitConfig(VFXmlConfig_t *vf) +{ + if (!vf) + return 0; + + // VF has no defaults + return 1; +} + +static +boolean vfCopyConfig(VFXmlConfig_t *dst, VFXmlConfig_t *src) +{ + int i; + + if (!src || !dst) + return 0; + + // Nothing to do if src and dst are the same. + if (src == dst) return 1; + + *dst = *src; + memset(dst->vf, 0, sizeof(dst->vf)); + dst->number_of_vfs = 0; + + for (i = 0; i < src->number_of_vfs; i++) { + if (NULL != (dst->vf[i] = getVfObject())) { + *dst->vf[i] = *src->vf[i]; + dst->number_of_vfs++; + } + } + if (dst->number_of_vfs == src->number_of_vfs) + return 1; + + return 0; +} + +// show the SM XML config +void vfShowConfig(VFXmlConfig_t *vf) +{ + uint32_t i, j; + + printf("XML - number_of_vfs %u\n", vf->number_of_vfs); + for (i = 0; i < vf->number_of_vfs; i++) { + printf("XML - vf[%d].name %s\n", i, vf->vf[i]->name); + printf("XML - vf[%d].enable %u\n", i, vf->vf[i]->enable); + printf("XML - vf[%d].standby %u\n", i, vf->vf[i]->standby); + printf("XML - vf[%d].pkey %u\n", i, vf->vf[i]->pkey); + printf("XML - vf[%d].security %u\n", i, vf->vf[i]->security); + printf("XML - vf[%d].qos_index %u\n", i, vf->vf[i]->qos_index); + printf("XML - vf[%d].qos_group %s\n", i, vf->vf[i]->qos_group); + printf("XML - vf[%d].number_of_full_members %u\n", i, vf->vf[i]->number_of_full_members); + for (j = 0; j < vf->vf[i]->number_of_full_members; j++) { + printf("XML - vf[%d].full_member[%d].member %s\n", i, j, vf->vf[i]->full_member[j].member); + } + printf("XML - vf[%d].number_of_limited_members %u\n", i, vf->vf[i]->number_of_limited_members); + for (j = 0; j < vf->vf[i]->number_of_limited_members; j++) { + printf("XML - vf[%d].limited_member[%d].member %s\n", i, j, vf->vf[i]->limited_member[j].member); + } + printf("XML - vf[%d].number_of_applications %u\n", i, vf->vf[i]->number_of_applications); + for (j = 0; j < vf->vf[i]->number_of_applications; j++) { + printf("XML - vf[%d].application[%d].application %s\n", i, j, vf->vf[i]->application[j].application); + } + printf("XML - vf[%d].max_mtu_int %u\n", i, (unsigned int)vf->vf[i]->max_mtu_int); + printf("XML - vf[%d].max_rate_int %u\n", i, (unsigned int)vf->vf[i]->max_rate_int); + printf("XML - vf[%d].max_rate_int %u\n", i, (unsigned int)vf->vf[i]->max_rate_int); + printf("XML - vf[%d].qos_enable %u\n", i, (unsigned int)vf->vf[i]->qos_enable); + printf("XML - vf[%d].base_sl %u\n", i, (unsigned int)vf->vf[i]->base_sl); + printf("XML - vf[%d].resp_sl %u\n", i, (unsigned int)vf->vf[i]->resp_sl); + printf("XML - vf[%d].mcast_sl %u\n", i, (unsigned int)vf->vf[i]->mcast_sl); + printf("XML - vf[%d].flowControlDisable %u\n", i, (unsigned int)vf->vf[i]->flowControlDisable); + printf("XML - vf[%d].percent_bandwidth %u\n", i, (unsigned int)vf->vf[i]->percent_bandwidth); + printf("XML - vf[%d].priority %u\n", i, (unsigned int)vf->vf[i]->priority); + printf("XML - vf[%d].pkt_lifetime_mult %u\n", i, (unsigned int)vf->vf[i]->pkt_lifetime_mult); + printf("XML - vf[%d].preempt_rank %u\n", i, (unsigned int)vf->vf[i]->preempt_rank); + printf("XML - vf[%d].hoqlife_vf %u\n", i, (unsigned int)vf->vf[i]->hoqlife_vf); + } + printf("XML - securityEnabled %u\n", (unsigned int)vf->securityEnabled); + printf("XML - qosEnabled %u\n", (unsigned int)vf->qosEnabled); +} + +static +void qosClearConfig(QosXmlConfig_t *qos) +{ + qos->number_of_qosgroups = 0; + + // clear all pointers to QosGroups + memset(qos->qosgroups, 0, sizeof(qos->qosgroups)); +} + +static +boolean qosInitConfig(QosXmlConfig_t *qosp) +{ + int i; + + if (!qosp) + return 0; + + for(i = 0 ; i < qosp->number_of_qosgroups; i++) { + QosConfig_t *qos; + + qos = qosp->qosgroups[i]; + + // Order matters! + + // Only checksum the explicit QOS groups. Implicit ones will + // be checksummed as part of the VFs in reRenderVirtualFabricsConfig + if (!strlen(qos->name)) continue; + + CKSUM_DATA(qos->name, CKSUM_OVERALL_DISRUPT_CONSIST); + CKSUM_DATA(qos->enable, CKSUM_OVERALL_DISRUPT_CONSIST); + CKSUM_DATA(qos->base_sl, CKSUM_OVERALL_DISRUPT_CONSIST); + CKSUM_DATA(qos->resp_sl, CKSUM_OVERALL_DISRUPT_CONSIST); + CKSUM_DATA(qos->mcast_sl, CKSUM_OVERALL_DISRUPT_CONSIST); + CKSUM_DATA(qos->flowControlDisable, CKSUM_OVERALL_DISRUPT_CONSIST); + CKSUM_DATA(qos->percent_bandwidth, CKSUM_OVERALL_CONSIST); + CKSUM_DATA(qos->priority, CKSUM_OVERALL_DISRUPT_CONSIST); + CKSUM_DATA(qos->preempt_rank, CKSUM_OVERALL_DISRUPT_CONSIST); + if (qos->pkt_lifetime_specified) + CKSUM_DATA(qos->pkt_lifetime_mult, CKSUM_OVERALL_DISRUPT_CONSIST); + if (qos->hoqlife_specified) + CKSUM_DATA(qos->hoqlife_qos, CKSUM_OVERALL_DISRUPT_CONSIST); + } + return 1; +} + +static +boolean qosCopyConfig(QosXmlConfig_t *dst, QosXmlConfig_t *src) +{ + int i; + + if (!src || !dst) + return 0; + + // Nothing to do if src and dst are the same. + if (src == dst) return 1; + + *dst = *src; + memset(dst->qosgroups, 0, sizeof(dst->qosgroups)); + dst->number_of_qosgroups = 0; + + for (i = 0; i < src->number_of_qosgroups; i++) { + if (NULL != (dst->qosgroups[i] = getQosObject())) { + *dst->qosgroups[i] = *src->qosgroups[i]; + dst->number_of_qosgroups++; + } + } + if (dst->number_of_qosgroups == src->number_of_qosgroups) + return 1; + + return 0; +} + +// show the SM XML config +void qosShowConfig(QosXmlConfig_t *qos) +{ + uint32_t i; + + printf("XML - number_of_qosgroups %u\n", qos->number_of_qosgroups); + for (i = 0; i < qos->number_of_qosgroups; i++) { + printf("XML - qosgroups[%d].name %s\n", i, qos->qosgroups[i]->name); + printf("XML - qosgroups[%d].enable %u\n", i, (unsigned int)qos->qosgroups[i]->enable); + printf("XML - qosgroups[%d].qos_enable %u\n", i, (unsigned int)qos->qosgroups[i]->qos_enable); + printf("XML - qosgroups[%d].private_group %u\n", i, (unsigned int)qos->qosgroups[i]->private_group); + printf("XML - qosgroups[%d].base_sl %u\n", i, (unsigned int)qos->qosgroups[i]->base_sl); + printf("XML - qosgroups[%d].resp_sl %u\n", i, (unsigned int)qos->qosgroups[i]->resp_sl); + printf("XML - qosgroups[%d].mcast_sl %u\n", i, (unsigned int)qos->qosgroups[i]->mcast_sl); + printf("XML - qosgroups[%d].flowControlDisable %u\n", i, (unsigned int)qos->qosgroups[i]->flowControlDisable); + printf("XML - qosgroups[%d].percent_bandwidth %u\n", i, (unsigned int)qos->qosgroups[i]->percent_bandwidth); + printf("XML - qosgroups[%d].priority %u\n", i, (unsigned int)qos->qosgroups[i]->priority); + printf("XML - qosgroups[%d].pkt_lifetime_mult %u\n", i, (unsigned int)qos->qosgroups[i]->pkt_lifetime_mult); + printf("XML - qosgroups[%d].preempt_rank %u\n", i, (unsigned int)qos->qosgroups[i]->preempt_rank); + printf("XML - qosgroups[%d].hoqlife_qos %u\n", i, qos->qosgroups[i]->hoqlife_qos); + printf("XML - qosgroups[%d].num_vfs %u\n", i, qos->qosgroups[i]->num_vfs); + } +} + +static +void appClearConfig(AppXmlConfig_t *app) +{ + // init the app map + cl_qmap_init(&app->appMap, compareName); + app->appMapSize = 0; +} + +static +boolean appInitConfig(AppXmlConfig_t *app) +{ + // App has no defaults + return 1; +} + +void appShowConfig(AppXmlConfig_t *app) +{ + cl_map_item_t *app_item; + cl_map_item_t *cl_map_item; + int i; + + printf("XML - appMapSize %u\n", app->appMapSize); + for_all_qmap_item(&app->appMap, app_item) { + AppConfig_t* appObj = XML_QMAP_VOID_CAST cl_qmap_key(app_item); + printf("XML - appMap[%s]->serviceIdMapSize %u\n", appObj->name, appObj->serviceIdMapSize); + for_all_qmap_item(&appObj->serviceIdMap, cl_map_item) { + printf("XML - appMap[%s]->serviceIdMap[0x%16.16llx]\n", appObj->name, (long long unsigned int)cl_qmap_key(cl_map_item)); + } + printf("XML - appMap[%s]->serviceIdRangeMapSize %u\n", appObj->name, appObj->serviceIdRangeMapSize); + char *range; + for_all_qmap_ptr(&appObj->serviceIdRangeMap, cl_map_item, range) { + printf("XML - appMap[%s]->serviceIdRangeMap[%s]\n", appObj->name, range); + } + printf("XML - appMap[%s]->serviceIdMaskedMapSize %u\n", appObj->name, appObj->serviceIdMaskedMapSize); + for_all_qmap_ptr(&appObj->serviceIdMaskedMap, cl_map_item, range) { + printf("XML - appMap[%s]->serviceIdMaskedMap[%s]\n", appObj->name, range); + } + printf("XML - appMap[%s]->number_of_mgids %u\n", appObj->name, appObj->number_of_mgids); + for (i = 0; i < appObj->number_of_mgids; i++) { + printf("XML - appMap[%s]->mgid[%i].mgid %s\n", appObj->name, i, appObj->mgid[i].mgid); + } + printf("XML - appMap[%s]->number_of_mgid_ranges %u\n", appObj->name, appObj->number_of_mgid_ranges); + for (i = 0; i < appObj->number_of_mgid_ranges; i++) { + printf("XML - appMap[%s]->mgid_range[%i].range %s\n", appObj->name, i, appObj->mgid_range[i].range); + } + printf("XML - appMap[%s]->number_of_mgid_maskeds %u\n", appObj->name, appObj->number_of_mgid_maskeds); + for (i = 0; i < appObj->number_of_mgid_maskeds; i++) { + printf("XML - appMap[%s]->mgid_masked[%i].masked %s\n", appObj->name, i, appObj->mgid_masked[i].masked); + } + printf("XML - appMap[%s]->number_of_included_apps %u\n", appObj->name, appObj->number_of_included_apps); + for (i = 0; i < appObj->number_of_included_apps; i++) { + printf("XML - appMap[%s]->included_app[%i].node %s\n", appObj->name, i, appObj->included_app[i].node); + } + printf("XML - appMap[%s]->select_sa %u\n", appObj->name, (unsigned int)appObj->select_sa); + printf("XML - appMap[%s]->select_unmatched_sid %u\n", appObj->name, (unsigned int)appObj->select_unmatched_sid); + printf("XML - appMap[%s]->select_unmatched_mgid %u\n", appObj->name, (unsigned int)appObj->select_unmatched_mgid); + printf("XML - appMap[%s]->select_pm %u\n", appObj->name, (unsigned int)appObj->select_pm); + } +} + +static +void dgClearConfig(DGXmlConfig_t *dg) +{ + memset(dg->dg, 0, sizeof(dg->dg)); + dg->number_of_dgs = 0; +} + +static +boolean dgInitConfig(DGXmlConfig_t *dgp) +{ + uint32_t i; + + if (!dgp) + return 0; + + for(i = 0 ; i < dgp->number_of_dgs; i++) { + DGConfig_t *dg; + cl_map_item_t *guidqp; + XmlNode_t *nodep; + XmlIncGroup_t *groupp; + + dg = dgp->dg[i]; + + // Because these are linked lists, order matters! + // The checksum will change if the order in the xml file changes. + // If they were maps, then order wouldn't matter. + CKSUM_DATA(dg->name, CKSUM_OVERALL_CONSIST); + for_all_qmap_item(&dg->system_image_guid, guidqp) { + uint64_t guid = cl_qmap_key(guidqp); + CKSUM_DATA(guid, CKSUM_OVERALL_CONSIST); + } + for_all_qmap_item(&dg->node_guid, guidqp) { + uint64_t guid = cl_qmap_key(guidqp); + CKSUM_DATA(guid, CKSUM_OVERALL_CONSIST); + } + for_all_qmap_item(&dg->port_guid, guidqp) { + uint64_t guid = cl_qmap_key(guidqp); + CKSUM_DATA(guid, CKSUM_OVERALL_CONSIST); + } + for (nodep = dg->node_description; nodep; nodep = nodep->next) { + CKSUM_DATA(nodep->node, CKSUM_OVERALL_CONSIST); + } + for (groupp = dg->included_group; groupp; groupp = groupp->next) { + CKSUM_DATA(groupp->group, CKSUM_OVERALL_CONSIST); + } + CKSUM_DATA(dg->select_all, CKSUM_OVERALL_CONSIST); + CKSUM_DATA(dg->select_self, CKSUM_OVERALL_CONSIST); + CKSUM_DATA(dg->select_hfi_direct_connect, CKSUM_OVERALL_CONSIST); + CKSUM_DATA(dg->select_swe0, CKSUM_OVERALL_CONSIST); + CKSUM_DATA(dg->select_all_mgmt_allowed, CKSUM_OVERALL_CONSIST); + CKSUM_DATA(dg->select_all_tfis, CKSUM_OVERALL_CONSIST); + CKSUM_DATA(dg->node_type_fi, CKSUM_OVERALL_CONSIST); + CKSUM_DATA(dg->node_type_sw, CKSUM_OVERALL_CONSIST); + } + return 1; +} + +boolean dgCopyConfig(DGXmlConfig_t *dst, DGXmlConfig_t *src) +{ + int i; + + if (!src || !dst) + return 0; + + // Nothing to do if src and dst are the same. + if (src == dst) return 1; + + dgClearConfig(dst); + for (i = 0; i < src->number_of_dgs; i++) { + if (NULL == (dst->dg[i] = getGroupObject())) break; + if (cloneGroup(src->dg[i], dst->dg[i], 0)) break; + dst->number_of_dgs++; + } + if (dst->number_of_dgs == src->number_of_dgs) return 1; + else return 0; +} + +boolean appCopyConfig(AppXmlConfig_t *dst, AppXmlConfig_t *src) +{ + if (!src || !dst) + return 0; + + // Nothing to do if src and dst are the same. + if (src == dst) return 1; + + *dst = *src; + cl_qmap_init(&dst->appMap, compareName); + dst->appMapSize = cloneMap(&dst->appMap, &src->appMap, compareName, dupApplicationObject); + return (dst->appMapSize == src->appMapSize); +} + + +// initialize XML data structures +static +boolean cloneFmInstance(FMXmlInstance_t *dst, FMXmlInstance_t *src) +{ + return fmCopyConfig(&dst->fm_config, &src->fm_config) && + smCopyConfig(&dst->sm_config, &src->sm_config) && + smDplCopyConfig(&dst->sm_dpl_config, &src->sm_dpl_config) && + smMcCopyConfig(&dst->sm_mc_config, &src->sm_mc_config) && + smMlsCopyConfig(&dst->sm_mls_config, &src->sm_mls_config) && + smMdgCopyConfig(&dst->sm_mdg_config, &src->sm_mdg_config) && + qosCopyConfig(&dst->qos_config, &src->qos_config) && + vfCopyConfig(&dst->vf_config, &src->vf_config) && + dgCopyConfig(&dst->dg_config, &src->dg_config) && + appCopyConfig(&dst->app_config, &src->app_config) && + pmCopyConfig(&dst->pm_config, &src->pm_config) && + feCopyConfig(&dst->fe_config, &src->fe_config) + + ; +} + +// initialize XML data structures +void xmlInitConfigInstance(FMXmlInstance_t *instance) +{ + // set all fields to 0xFF + memset(instance, UNDEFINED_XML8, sizeof(FMXmlInstance_t)); + + fmClearConfig(&instance->fm_config); + vfClearConfig(&instance->vf_config); + dgClearConfig(&instance->dg_config); + qosClearConfig(&instance->qos_config); + appClearConfig(&instance->app_config); + smClearConfig(&instance->sm_config); + smDplClearConfig(&instance->sm_dpl_config); + smMcClearConfig(&instance->sm_mc_config); + smMlsClearConfig(&instance->sm_mls_config); + smMdgClearConfig(&instance->sm_mdg_config); + pmClearConfig(&instance->pm_config); + feClearConfig(&instance->fe_config); +} + +// initialize XML data structures +void xmlInitConfig(void) +{ + // zero instance + instance = 0; + + common = 1; + vfInstance = 0; + qosInstance = 0; + appInstance = 0; + groupInstance = 0; + fullMemInstance = 0; + limitedMemInstance = 0; + systemImageInstance = 0; + nodeGuidInstance = 0; + portGuidInstance = 0; + nodeDescInstance = 0; + includedGroupInstance = 0; + serviceIdInstance = 0; + serviceIdRangeInstance = 0; + serviceIdMaskedInstance = 0; + mgidInstance = 0; + mgidRangeInstance = 0; + mgidMaskedInstance = 0; + dgMgidInstance = 0; + dgMgidRangeInstance = 0; + dgMgidMaskedInstance = 0; + includedAppInstance = 0; + defaultGroupInstance = 0; + mlidSharedInstance = 0; + PmPgInstance = 0; + PmPgMonitorInstance = 0; + + + last_node_description = NULL; + last_included_group = NULL; + +#ifdef XML_DEBUG + xml_vf_debug = 1; + xml_sm_debug = 1; + xml_fe_debug = 1; + xml_pm_debug = 1; + xml_parse_debug = 1; +#else + xml_vf_debug = 0; + xml_sm_debug = 0; + xml_fe_debug = 0; + xml_pm_debug = 0; + xml_parse_debug = 0; +#endif + + oldStyleVFs = FALSE; + newStyleVFs = FALSE; + + if (!configp->fm_instance_common) { + fprintf(stdout, "XML parse error - configp->fm_instance_common is NULL\n"); + return; + } + + // clear/set debug info + memset(&configp->xmlDebug, 0, sizeof(XmlDebug_t)); + configp->xmlDebug.xml_vf_debug = xml_vf_debug; + configp->xmlDebug.xml_sm_debug = xml_sm_debug; + configp->xmlDebug.xml_fe_debug = xml_fe_debug; + configp->xmlDebug.xml_pm_debug = xml_pm_debug; + configp->xmlDebug.xml_parse_debug = xml_parse_debug; + + xmlInitConfigInstance(configp->fm_instance_common); + + // initialize the empty multicast group structure + mdgEmpty = configp->fm_instance_common->sm_mdg_config.group[0]; +} + +static +void releaseFMXmlInstance(FMXmlInstance_t *inst, int freeInst) +{ + uint32_t i; + if (!inst) + return; + + for (i = 0; i < MAX_CONFIGURED_VFABRICS; i++) { + if (!inst->vf_config.vf[i]) + break; + freeXmlMemory(inst->vf_config.vf[i], sizeof(VFConfig_t), __func__); + inst->vf_config.vf[i] = NULL; + } + + freeDgInfo(&inst->dg_config); + freeQosgInfo(&inst->qos_config); + + freeAppConfigMap(&inst->app_config); + + + if (freeInst) + freeXmlMemory(inst, sizeof(FMXmlInstance_t), __func__); +} + +// release all memory in XML Configuration +void releaseXmlConfig(FMXmlCompositeConfig_t *config, uint32_t full) +{ + uint32_t fm; + + if (xml_parse_debug) + fprintf(stdout, "Releasing XML config in releaseXmlConfig()\n"); + + if (!config) + return; + + // free common XML objects + if (config->fm_instance_common && full_parse) { + releaseFMXmlInstance(config->fm_instance_common, 1); + } + config->fm_instance_common = NULL; + + // free specific XML objects + for (fm = fm_instance; fm < end_instance; fm++) { + if (!config->fm_instance[fm]) + continue; + + releaseFMXmlInstance(config->fm_instance[fm], full); + if (full) + config->fm_instance[fm] = NULL; + } + + if (full) { + freeXmlMemory(config, sizeof(FMXmlCompositeConfig_t), "FMXmlCompositeConfig_t releaseXmlConfig()"); + if (config == configp) + configp = NULL; + } + + // print memory info + if (xml_memory_debug) + fprintf(stdout, "Memory level %u full %u after releaseXmlConfig()\n", (unsigned int)memory, (unsigned int)full); +} + +// get VF object pointer and initialize data +static VFConfig_t* getVfObject(void) +{ + VFConfig_t *vfp; + int i; + + vfp = getXmlMemory(sizeof(VFConfig_t), "VFConfig_t getVfObject()"); + if (vfp == NULL) + return NULL; + + // set all fields to 0xFF + memset(vfp, UNDEFINED_XML8, sizeof(VFConfig_t)); + + // clear all string values in VirtualFabrics + memset(vfp->name, 0, sizeof(vfp->name)); + memset(vfp->full_member, 0, sizeof(vfp->full_member)); + memset(vfp->limited_member, 0, sizeof(vfp->limited_member)); + for (i = 0; i < MAX_VFABRIC_MEMBERS_PER_VF; i++) { + vfp->full_member[i].dg_index = -1; + vfp->limited_member[i].dg_index = -1; + } + memset(vfp->application, 0, sizeof(vfp->application)); + memset(vfp->qos_group, 0, sizeof(vfp->qos_group)); + + // make sure it is disabled + vfp->enable = 0; + vfp->standby = 0; + + return vfp; +} +static boolean getVfXmlMember(XMLMember_t *dg, XML_Char *content) +{ + DGXmlConfig_t *dg_config; + int i; + + dg->dg_index = -1; + + if (common) { + dg_config = &configp->fm_instance_common->dg_config; + } else if (configp->fm_instance[instance]) { + dg_config = &configp->fm_instance[instance]->dg_config; + } else { + // We don't care about this instance, so we don't have + // the device group list. Just tell the caller we found + // it. He won't know the difference since we're going + // to toss his data too. + return TRUE; + } + + for (i = 0; i < dg_config->number_of_dgs; i++) { + if (!dg_config->dg[i]) continue; + if (strcmp(dg_config->dg[i]->name, content)) continue; + + // Memeber Found in DG Config + StringCopy(dg->member, content, MAX_VFABRIC_NAME); + dg->dg_index = i; + return TRUE; + } + return FALSE; +} + +// free VF object +static void freeVfObject(VFConfig_t* vfp) +{ + freeXmlMemory(vfp, sizeof(VFConfig_t), "VFConfig_t freeVfObject"); +} + + +// get Group object pointer and initialize data +PmPortGroupXmlConfig_t* getPmPgObject(void) +{ + PmPortGroupXmlConfig_t *pmpgp; + int i; + + pmpgp = getXmlMemory(sizeof(PmPortGroupXmlConfig_t), "PmPortGroupXmlConfig_t getPmPgObject()"); + if (pmpgp == NULL) + return NULL; + + // set all fields to NULL + memset(pmpgp, 0, sizeof(PmPortGroupXmlConfig_t)); + for(i =0; i< STL_PM_MAX_DG_PER_PMPG; i++) + pmpgp->Monitors[i].dg_Index = UNDEFINED_XML16; + + return pmpgp; +} + +// get Group object pointer and initialize data +static DGConfig_t* getGroupObject(void) +{ + DGConfig_t *dgp; + + dgp = getXmlMemory(sizeof(DGConfig_t), "DGConfig_t getGroupObject()"); + if (dgp == NULL) + return NULL; + + // set all fields to 0xFF + memset(dgp, UNDEFINED_XML8, sizeof(DGConfig_t)); + + // clear all string values in VirtulFabric Groups + memset(dgp->name, 0, sizeof(dgp->name)); + + // clear device pointers + cl_qmap_init(&dgp->system_image_guid, NULL); + cl_qmap_init(&dgp->node_guid, NULL); + cl_qmap_init(&dgp->port_guid, NULL); + dgp->node_description = NULL; + dgp->reg_expr = NULL; + dgp->included_group = NULL; + + // default flags + dgp->select_all = 0; + dgp->select_self = 0; + dgp->select_hfi_direct_connect = 0; + dgp->select_swe0 = 0; + dgp->select_all_mgmt_allowed = 0; + dgp->select_all_tfis = 0; + dgp->node_type_fi = 0; + dgp->node_type_sw = 0; + + return dgp; +} + +// free Group object +static void freeGroupObject(DGConfig_t *group, uint8_t full) +{ + XmlNode_t *node; + XmlNode_t *lastNode; + RegExp_t *regEx; + RegExp_t *lastRegEx; + XmlIncGroup_t *incGroup; + XmlIncGroup_t *lastIncGroup; + + scrubMap(&group->system_image_guid, NULL); + scrubMap(&group->node_guid, NULL); + scrubMap(&group->port_guid, NULL); + + node = group->node_description; + while(node != NULL) { + lastNode = node->next; + freeXmlMemory(node, sizeof(XmlNode_t), "XmlNode_t freeGroupObject()"); + node = lastNode; + } + regEx = group->reg_expr; + while(regEx != NULL) { + lastRegEx = regEx->next; + freeXmlMemory(regEx, sizeof(RegExp_t), "RegExp_t freeGroupObject()"); + regEx = lastRegEx; + } + incGroup = group->included_group; + while(incGroup != NULL) { + lastIncGroup = incGroup->next; + freeXmlMemory(incGroup, sizeof(XmlIncGroup_t), "XmlIncGroup_t freeGroupObject()"); + incGroup = lastIncGroup; + } + + // if full free then free group object too - otherwise clear + if (full) + freeXmlMemory(group, sizeof(DGConfig_t), "DGConfig_t freeGroupObject()"); + else + memset(group, 0, sizeof(DGConfig_t)); +} + +// get QOS group object pointer and initialize data +static QosConfig_t* getQosObject(void) +{ + QosConfig_t *qosp; + + qosp = getXmlMemory(sizeof(QosConfig_t), "QosConfig_t getQosObject()"); + if (qosp == NULL) + return NULL; + + // set all fields to 0xFF + memset(qosp, UNDEFINED_XML8, sizeof(QosConfig_t)); + + // clear all string values in QOS Group + memset(qosp->name, 0, sizeof(qosp->name)); + + qosp->private_group = 0; + qosp->contains_mcast = 0; + qosp->requires_resp_sl = 0; + qosp->num_vfs = 0; + qosp->num_implicit_vfs = 0; + + // make sure it is disabled + qosp->enable = 0; + + return qosp; +} + +// free QOS group object +static void freeQosObject(QosConfig_t *qosp) +{ + freeXmlMemory(qosp, sizeof(QosConfig_t), "QosConfig_t freeQosObject()"); +} + +// get Application object pointer and initialize data +static AppConfig_t* getApplicationObject(void) +{ + AppConfig_t *app; + + app = getXmlMemory(sizeof(AppConfig_t), "AppConfig_t getApplicationObject()"); + if (app == NULL) + return NULL; + + // set all fields to 0xFF + memset(app, UNDEFINED_XML8, sizeof(AppConfig_t)); + + cl_qmap_init(&app->serviceIdMap, NULL); + app->serviceIdMapSize = 0; + + cl_qmap_init(&app->serviceIdRangeMap, compareName); + app->serviceIdRangeMapSize = 0; + + cl_qmap_init(&app->serviceIdMaskedMap, compareName); + app->serviceIdMaskedMapSize = 0; + + // clear all string values in VirtulFabric Applications + memset(app->name, 0, sizeof(app->name)); + memset(app->mgid, 0, sizeof(app->mgid)); + memset(app->mgid_range, 0, sizeof(app->mgid_range)); + memset(app->mgid_masked, 0, sizeof(app->mgid_masked)); + memset(app->included_app, 0, sizeof(app->included_app)); + + // default flags + app->select_sa = 0; + app->select_unmatched_sid = 0; + app->select_unmatched_mgid = 0; + app->select_pm = 0; + + + return app; +} + +// free Application object +static void freeApplicationObject(AppConfig_t *app) +{ + scrubMap(&app->serviceIdMap, NULL); + app->serviceIdMapSize = 0; + + scrubMap(&app->serviceIdRangeMap, freeName); + app->serviceIdRangeMapSize = 0; + + scrubMap(&app->serviceIdMaskedMap, freeName); + app->serviceIdMaskedMapSize = 0; + + + freeXmlMemory(app, sizeof(AppConfig_t), "AppConfig_t freeApplicationObject()"); +} + +// Copy Application object +static void cloneApplicationObject(AppConfig_t *dst, AppConfig_t *src) +{ + if (!src || !dst || (src == dst)) return; + + // Copy everything first, then handle the qmap + *dst = *src; + dst->serviceIdMapSize = cloneMap(&dst->serviceIdMap, &src->serviceIdMap, NULL, NULL); + dst->serviceIdRangeMapSize = cloneMap(&dst->serviceIdRangeMap, &src->serviceIdRangeMap, compareName, dupName); + dst->serviceIdMaskedMapSize = cloneMap(&dst->serviceIdMaskedMap, &src->serviceIdMaskedMap, compareName, dupName); + return; +} + +// Duplicate Application object +static AppConfig_t *dupApplicationObject(AppConfig_t *obj) +{ + AppConfig_t *new_obj; + + new_obj = getApplicationObject(); + if (!new_obj) return NULL; + + cloneApplicationObject(new_obj, obj); + return new_obj; +} + +// copy of Group Device Nodes +static int8_t cloneGroupDeviceNodes(XmlNode_t *source, XmlNode_t **dest) +{ + XmlNode_t *lastNode = NULL; + XmlNode_t *newNode = NULL; + XmlNode_t *nodePtr; + + if (source == NULL || dest == NULL) + return 0; + + nodePtr = source; + + while(nodePtr != NULL) { + newNode = getXmlMemory(sizeof(XmlNode_t), "XmlNode_t cloneGroupDeviceNodes()"); + if (newNode == NULL) + return -1; + StringCopy(newNode->node, nodePtr->node, MAX_VFABRIC_NAME); + newNode->next = NULL; + if (lastNode == NULL) + *dest = newNode; + else + lastNode->next = newNode; + lastNode = newNode; + nodePtr = nodePtr->next; + } + return 0; +} + +int8_t cloneGroupRegExpr(RegExp_t *source, RegExp_t **dest) +{ + RegExp_t *lastRegExpr = NULL; + RegExp_t *newRegExpr = NULL; + RegExp_t *regExprPtr; + + if (source == NULL || dest == NULL) + return 0; + + regExprPtr = source; + + while(regExprPtr != NULL) { + newRegExpr = getXmlMemory(sizeof(RegExp_t), "RegExp_t cloneGroupRegExpr()"); + if (newRegExpr == NULL) + return -1; + + memcpy(newRegExpr, regExprPtr, sizeof(RegExp_t)); + + newRegExpr->next = NULL; + if (lastRegExpr == NULL) + *dest = newRegExpr; + else + lastRegExpr->next = newRegExpr; + lastRegExpr = newRegExpr; + regExprPtr = regExprPtr->next; + } + return 0; +} + + +// copy of Group Included Groups +int8_t cloneGroupIncGroups(XmlIncGroup_t *source, XmlIncGroup_t **dest) +{ + XmlIncGroup_t *lastIncGroup = NULL; + XmlIncGroup_t *newIncGroup = NULL; + XmlIncGroup_t *incGroupPtr; + + if (source == NULL || dest == NULL) + return 0; + + incGroupPtr = source; + + while(incGroupPtr != NULL) { + newIncGroup = getXmlMemory(sizeof(XmlIncGroup_t), "XmlIncGroup_t cloneGroupIncGroups()"); + if (newIncGroup == NULL) + return -1; + StringCopy(newIncGroup->group, incGroupPtr->group, MAX_VFABRIC_NAME); + newIncGroup->dg_index = incGroupPtr->dg_index; + newIncGroup->next = NULL; + if (lastIncGroup == NULL) + *dest = newIncGroup; + else + lastIncGroup->next = newIncGroup; + lastIncGroup = newIncGroup; + incGroupPtr = incGroupPtr->next; + } + return 0; +} + +// copy Group +static int8_t cloneGroup(DGConfig_t *source, DGConfig_t *dest, int freeObjectBeforeCopy) +{ + if (freeObjectBeforeCopy) { + // first free devices from destination group if there are any + freeGroupObject(dest, /* full */ 0); + } + + // copy other info but null the pointers + *dest = *source; + + dest->node_description = NULL; + dest->reg_expr = NULL; + dest->included_group = NULL; + + dest->number_of_system_image_guids=cloneMap(&dest->system_image_guid, &source->system_image_guid, NULL, NULL); + dest->number_of_node_guids=cloneMap(&dest->node_guid, &source->node_guid, NULL, NULL); + dest->number_of_port_guids=cloneMap(&dest->port_guid, &source->port_guid, NULL, NULL); + + if (cloneGroupDeviceNodes(source->node_description, &dest->node_description) < 0) + return -1; + if (cloneGroupRegExpr(source->reg_expr, &dest->reg_expr) < 0) + return -1; + if (cloneGroupIncGroups(source->included_group, &dest->included_group) < 0) + return -1; + + return 0; +} + +// release QOS Group Memory +static void freeQosgInfo(QosXmlConfig_t *qos) +{ + uint32_t i; + for (i = 0; i < MAX_QOS_GROUPS; i++) { + if (!qos->qosgroups[i]) + break; + freeQosObject(qos->qosgroups[i]); + qos->qosgroups[i] = NULL; + } +} + +// release DG Group Memory +void freeDgInfo(DGXmlConfig_t *dg) +{ + uint32_t i; + for (i = 0; i < MAX_VFABRIC_GROUPS; i++) { + if (!dg->dg[i]) + break; + freeGroupObject(dg->dg[i], /* full */ 1); + dg->dg[i] = NULL; + } +} + +// verify and convert an SID Range or Masked value into an VFAppSid_t structure +int verifyAndConvertSidCompoundString(char *sidString, uint8_t range, VFAppSid_t *sidMapping) +{ + uint64 sidLower; + uint64 sidUpper; + char *operator = NULL; + + if (!sidString || !sidMapping) { + if (xml_parse_debug) + fprintf(stdout, "NULL pointer sent to verifyAndConvertSidCompoundString()\n"); + return -1; + } + + if (FSUCCESS != StringToUint64(&sidLower, sidString, &operator, 16, TRUE)) { + if (xml_parse_debug) + fprintf(stdout, "Illegal ServiceID length found in hex string %s in verifyAndConvertSidCompoundString\n", sidString); + return -1; + } + + if (range) { + if (*operator != '-') { + if (xml_parse_debug) + fprintf(stdout, "Illegal range operator found in hex string %s in verifyAndConvertSidCompoundString\n", sidString); + return -1; + } + } else { + if (*operator != '*') { + if (xml_parse_debug) + fprintf(stdout, "Illegal mask operator found in hex string %s in verifyAndConvertSidCompoundString\n", sidString); + return -1; + } + } + + if (FSUCCESS != StringToUint64(&sidUpper, operator+1, NULL, 16, TRUE)) { + if (xml_parse_debug) + fprintf(stdout, "Illegal ServiceID length found in hex string %s in verifyAndConvertSidCompoundString\n", sidString); + return -1; + } + +#ifdef XML_DEBUG +/* + fprintf(stdout, "sidLower 0x%llx sidUpper 0x%llx\n", sidLower, sidUpper); +*/ +#endif + + sidMapping->service_id = sidLower; + + if (range) { + sidMapping->service_id_last = sidUpper; + sidMapping->service_id_mask = UNDEFINED_XML64; + } else { + sidMapping->service_id_mask = sidUpper; + sidMapping->service_id_last = 0; + } + return 0; +} + +// verify and convert an MGID value into an VFAppMgid_t structure +int verifyAndConvertMGidString(char *mgidString, VFAppMgid_t *mgidMapping) +{ + uint64 mgid[2]; + + if (!mgidString || !mgidMapping) { + if (xml_parse_debug) + fprintf(stdout, "NULL pointer sent to verifyAndConvertMGidString()\n"); + return -1; + } + + if (FSUCCESS != StringToGid(&mgid[0], &mgid[1], mgidString, NULL, TRUE)) { + if (xml_parse_debug) { + fprintf(stdout, "Illegal MGID found in hex string %s\n", mgidString); + } + return -1; + } + +#ifdef XML_DEBUG +/* + fprintf(stdout, "MGID input string %s mgid[0] 0x%llx mgid[1] 0x%llx\n", mgidString, mgid[0], mgid[1]); +*/ +#endif + + mgidMapping->mgid[0] = mgid[0]; + mgidMapping->mgid[1] = mgid[1]; + mgidMapping->mgid_last[0] = 0; + mgidMapping->mgid_last[1] = 0; + mgidMapping->mgid_mask[0] = UNDEFINED_XML64; + mgidMapping->mgid_mask[1] = UNDEFINED_XML64; + + return 0; +} + +// verify and convert an MGID Range or Masked value into an VFAppMgid_t structure +int verifyAndConvertMGidCompoundString(char *mgidString, uint8_t range, VFAppMgid_t *mgidMapping) +{ + uint64 mgidLower[2]; + uint64 mgidUpper[2]; + char *operator = NULL; + + if (!mgidString || !mgidMapping) { + if (xml_parse_debug) + fprintf(stdout, "NULL pointer sent to verifyAndConvertMGidCompoundString()\n"); + return -1; + } + + if (FSUCCESS != StringToGid(&mgidLower[0], &mgidLower[1], mgidString, &operator, TRUE)) { + if (xml_parse_debug) + fprintf(stdout, "Illegal MGID found in hex string %s in verifyAndConvertMGidCompoundString\n", mgidString); + return -1; + } + + if (range) { + if (*operator != '-') { + if (xml_parse_debug) + fprintf(stdout, "Illegal range operator found in hex string %s in verifyAndConvertMGidCompoundString\n", mgidString); + return -1; + } + } else { + if (*operator != '*') { + if (xml_parse_debug) + fprintf(stdout, "Illegal mask operator found in hex string %s in verifyAndConvertMGidCompoundString\n", mgidString); + return -1; + } + } + if (FSUCCESS != StringToGid(&mgidUpper[0], &mgidUpper[1], operator+1, NULL, TRUE)) { + if (xml_parse_debug) + fprintf(stdout, "Illegal MGID found in hex string %s in verifyAndConvertMGidCompoundString\n", mgidString); + return -1; + } + +#ifdef XML_DEBUG +/* + fprintf(stdout, "mgidLower[0] 0x%llx mgidLower[1] 0x%llx mgidUpper[0] 0x%llx mgidUpper[1] 0x%llx\n", + mgidLower[0], mgidLower[1], mgidUpper[0], mgidUpper[1]); +*/ +#endif + + mgidMapping->mgid[0] = mgidLower[0]; + mgidMapping->mgid[1] = mgidLower[1]; + + if (range) { + mgidMapping->mgid_last[0] = mgidUpper[0]; + mgidMapping->mgid_last[1] = mgidUpper[1]; + mgidMapping->mgid_mask[0] = UNDEFINED_XML64; + mgidMapping->mgid_mask[1] = UNDEFINED_XML64; + } else { + mgidMapping->mgid_mask[0] = mgidUpper[0]; + mgidMapping->mgid_mask[1] = mgidUpper[1]; + mgidMapping->mgid_last[0] = 0; + mgidMapping->mgid_last[1] = 0; + } + return 0; +} + +void scrubVF(VF_t *vfp) +{ + VFDg_t *dgp; + + // free Application objects + scrubMap(&vfp->apps.sidMap, freeAppSid); + scrubMap(&vfp->apps.mgidMap, freeAppMgid); + + // free default group and associated MGID list + while (vfp->default_group) { + dgp = vfp->default_group->next_default_group; + freeDMCG(vfp->default_group); + vfp->default_group = dgp; + } +} + +// release all memory in Virtual Fabric Configuration in firmware +void releaseVirtualFabricsConfig(VirtualFabrics_t *vfsip) +{ + VF_t *vfp; + + if (xml_parse_debug) + fprintf(stdout, "Releasing Virtual Fabrics config in releaseVirtualFabricsConfig()\n"); + + if (!vfsip) + return; + + freeDgInfo(&vfsip->dg_config); + + uint32_t i; + + for (i = 0; i < vfsip->number_of_vfs_all && i < MAX_ENABLED_VFABRICS; i++) { + vfp = &vfsip->v_fabric_all[i]; + + scrubVF(vfp); + + + } + + // finally free the parent object + freeXmlMemory(vfsip, sizeof(VirtualFabrics_t), + "VirtualFabrics_t releaseVirtualFabricsConfig()"); + + // print memory info + if (xml_memory_debug) + fprintf(stdout, "Memory level %u after releaseVirtualFabricsConfig()\n", (unsigned int)memory); +} + +// create a checksum for one Virtual Fabric +void checksumOneVirtualFabricsConfig(VFConfig_t *vf, VF_t *vfp, uint8_t requires_resp_sl) +{ + VFAppSid_t *sidp; + VFAppMgid_t *mgidp; + VFDg_t *dgp; + cl_map_item_t *cl_map_item; + int i; + + if (!vfp) + return; + + int csum_type; + if (vfp->qos_implicit) { + // Only vfp->qos_implicit VFs can be disruptive. + csum_type = CKSUM_OVERALL_DISRUPT_CONSIST; + + // Only checksum these QOS parameters for VFs with implicit QOS groups + CKSUM_DATA(vf->qos_enable, csum_type); + CKSUM_DATA(requires_resp_sl, csum_type); + if (vf->qos_enable) { + CKSUM_DATA(vf->base_sl, csum_type); + CKSUM_DATA(vf->resp_sl, csum_type); + CKSUM_DATA(vf->mcast_sl, csum_type); + CKSUM_DATA(vf->flowControlDisable, csum_type); + CKSUM_DATA(vf->percent_bandwidth, CKSUM_OVERALL_CONSIST); + CKSUM_DATA(vf->priority, csum_type); + CKSUM_DATA(vf->pkt_lifetime_mult, csum_type); + CKSUM_DATA(vf->preempt_rank, csum_type); + CKSUM_DATA(vf->hoqlife_vf, csum_type); + } + } else { + csum_type = CKSUM_OVERALL_CONSIST; + if (vfp->standby) { + // If it is standby and non qos_implicit + // don't even bother checksumming it + return; + } + // For explicit QOS groups, just checksum the index + // The QOS parameters are part of the SM checksum + CKSUM_DATA(vfp->qos_index, csum_type); + } + + CKSUM_DATA(vfp->name, csum_type); + CKSUM_DATA(vfp->pkey, csum_type); + CKSUM_DATA(vfp->standby, CKSUM_OVERALL_CONSIST); + CKSUM_DATA(vfp->security, csum_type); + CKSUM_DATA(vfp->max_mtu_int, csum_type); + CKSUM_DATA(vfp->max_mtu_specified, csum_type); + CKSUM_DATA(vfp->max_rate_int, csum_type); + CKSUM_DATA(vfp->max_rate_specified, csum_type); + + for_all_qmap_ptr(&vfp->apps.sidMap, cl_map_item, sidp) { + CKSUM_DATA(*sidp, csum_type); + } + for_all_qmap_ptr(&vfp->apps.mgidMap, cl_map_item, mgidp) { + CKSUM_DATA(*mgidp, csum_type); + } + CKSUM_DATA(vfp->apps.select_sa, csum_type); + CKSUM_DATA(vfp->apps.select_unmatched_sid, csum_type); + CKSUM_DATA(vfp->apps.select_unmatched_mgid, csum_type); + CKSUM_DATA(vfp->apps.select_pm, csum_type); + + + CKSUM_DATA(vfp->number_of_full_members, csum_type); + for(i = 0; i < vfp->number_of_full_members; i++) { + CKSUM_DATA(vfp->full_member[i].member, csum_type); + } + CKSUM_DATA(vfp->number_of_limited_members, csum_type); + for(i = 0; i < vfp->number_of_limited_members; i++) { + CKSUM_DATA(vfp->limited_member[i].member, csum_type); + } + + for (dgp = vfp->default_group; dgp; dgp = dgp->next_default_group) { + + CKSUM_DATA(dgp->def_mc_create, csum_type); + + + CKSUM_DATA(dgp->def_mc_pkey, csum_type); + CKSUM_DATA(dgp->def_mc_mtu_int, csum_type); + CKSUM_DATA(dgp->def_mc_rate_int, csum_type); + CKSUM_DATA(dgp->def_mc_sl, csum_type); + CKSUM_DATA(dgp->def_mc_qkey, csum_type); + CKSUM_DATA(dgp->def_mc_fl, csum_type); + CKSUM_DATA(dgp->def_mc_tc, csum_type); + for_all_qmap_ptr(&dgp->mgidMap, cl_map_item, mgidp) { + CKSUM_DATA(*mgidp, csum_type); + } + } + + return; +} + +// create a total checksum for the Virtual Fabric database +static boolean checksumVirtualFabricsConfig(VFXmlConfig_t *vf_config, VirtualFabrics_t *vfsip) +{ + VF_t *vfp; + uint32_t i; + + if (!vfsip) + return FALSE; + + // Checksum each individual Virtual Fabric + for (i = 0; i < vfsip->number_of_vfs_all; i++) { + vfp = &vfsip->v_fabric_all[i]; + if (!BeginCksums(__func__)) + return FALSE; + + checksumOneVirtualFabricsConfig(vf_config->vf[i], vfp, vfsip->qos_all[vfp->qos_index].requires_resp_sl); + EndCksums(__func__, &vfp->overall_checksum, &vfp->disruptive_checksum, &vfp->consistency_checksum); + } + + // Checksum all of the Virtual Fabrics together + + if (!BeginCksums(__func__)) + return FALSE; + + // vfsip->securityEnabled // setup by SM + // vfsip->qosEnabled // setup by SM + + for (i = 0; i < vfsip->number_of_vfs_all; i++) { + vfp = &vfsip->v_fabric_all[i]; + checksumOneVirtualFabricsConfig(vf_config->vf[i], vfp, vfsip->qos_all[vfp->qos_index].requires_resp_sl); + } + + EndCksums(__func__, &vfsip->overall_checksum, &vfsip->disruptive_checksum, &vfsip->consistency_checksum); + + return TRUE; +} + +// find a pointer to a Application given the name +AppConfig_t* findAppPointer(FMXmlInstance_t *fm_instance, char *name) +{ + cl_map_item_t *app_item; + + if (xml_vf_debug) + fprintf(stdout, "findAppPointer() app %s\n", name); + + app_item = cl_qmap_get(&fm_instance->app_config.appMap, XML_QMAP_U64_CAST name); + if (app_item) + return XML_QMAP_VOID_CAST cl_qmap_key(app_item); + else + return NULL; +} + +// add to list of apps all included apps - this is a reccursive routine +static boolean includedApps(FMXmlInstance_t *fm_instance, AppConfig_t **list, AppConfig_t *parent, uint32_t *index, char *cfgtype, + IXmlParserPrintMessage printError, IXmlParserPrintMessage printWarning) +{ + AppConfig_t *included; + + uint32_t i; + uint32_t ii; + int32_t result; + uint32_t skip = 0; + + if (!parent || !list) { + fprintf(stdout, "Illegal call to includedApps()\n"); + return FALSE; + } + + if (xml_vf_debug) + fprintf(stdout, "includedApps() parent->name %s included apps %u index %u\n", + parent->name, (unsigned int)parent->number_of_included_apps, (unsigned int)*index); + + for (i = 0; i < parent->number_of_included_apps; i++) + { + // if we are at the end of the list then return + if (*index >= MAX_VFABRIC_APPS) { + RENDER_VF_LOGGER(printError, "%s: Maximum number of included Applications exceeded",cfgtype); + return FALSE; + } + + // if the parent does not have a name then parse error + if (strlen(parent->name) == 0) { + RENDER_VF_LOGGER(printError, "%s: Parent Application encountered without a name",cfgtype); + return FALSE; + } + + // if included does not have a name then parse error + if (strlen(parent->included_app[i].node) == 0) { + RENDER_VF_LOGGER(printError, "%s: Included Application encountered without a name",cfgtype); + return FALSE; + } + + // get a pointer to the included app + included = findAppPointer(fm_instance, parent->included_app[i].node); + + // if this app does not exist it is a parse error + if (included == NULL) { + RENDER_VF_LOGGER(printError, "%s: Application (%s) does not exist",cfgtype,parent->included_app[i].node); + return FALSE; + } + + if (xml_vf_debug) + fprintf(stdout, "includedApps() parent->name %s included name %s index %u\n", + parent->name, parent->included_app[i].node, (unsigned int)*index); + + // make sure this pointer is not already on the list + for (ii = 0; ii < MAX_VFABRIC_APPS; ii++) { + if (list + ii == NULL) + break; + if (included == *(list + ii)) { + RENDER_VF_LOGGER(printWarning, "%s: Application (%s) should not be included more than once - ignoring",cfgtype,included->name); + skip = 1; + } + } + + if (skip) + continue; + + // save app pointer on app list + list[*index] = included; + (*index)++; + + // recursively call this again for this included app + result = includedApps(fm_instance, list, included, index, cfgtype, printError, printWarning); + if (result < 0) + return FALSE; + } + return TRUE; +} + + +// verify VFs are congruent +static +boolean VerifyCongruentVF(VF_t *v_fp1, VF_t *v_fp2, VFDg_t *mcp) +{ + //checking PKey + if ((v_fp1->pkey != UNDEFINED_XML32) && (v_fp2->pkey != UNDEFINED_XML32) + && (PKEY_VALUE(v_fp1->pkey) != PKEY_VALUE(v_fp2->pkey))){ + return FALSE; + } + //check MTU + if ((GetBytesFromMtu(mcp->def_mc_mtu_int) > GetBytesFromMtu(v_fp1->max_mtu_int)) || + (GetBytesFromMtu(mcp->def_mc_mtu_int) > GetBytesFromMtu(v_fp2->max_mtu_int))) + return FALSE; + + // check rate + if ((IbStaticRateToMbps(mcp->def_mc_rate_int) > IbStaticRateToMbps(v_fp1->max_rate_int)) || + (IbStaticRateToMbps(mcp->def_mc_rate_int) > IbStaticRateToMbps(v_fp2->max_rate_int))) + return FALSE; + + // Check the SL's are the same + return (v_fp1->qos_index == v_fp2->qos_index); +} + + +// check for duplicate MGID's within all DefaultGroups in all VirtualFabrics including itself +FSTATUS checkDefaultGroupMGIDDuplicates(VirtualFabrics_t *vfsip, SMXmlConfig_t *smp, char *cfgtype, + IXmlParserPrintMessage printError, IXmlParserPrintMessage printWarning) +{ + uint32_t vf1, vf2; + VFDg_t *dg_ref; + VFDg_t *dg_check; + VFAppMgid_t *mgid_ref; + VFAppMgid_t *mgid_check; + cl_map_item_t *item1, *item2; + + // go to each MGID and make sure no other MGID is the same + for (vf1 = 0; vf1 < vfsip->number_of_vfs_all; vf1++) { + dg_ref = vfsip->v_fabric_all[vf1].default_group; + + while (dg_ref) { + if (dg_ref->def_mc_create) { + for_all_qmap_ptr(&dg_ref->mgidMap, item1, mgid_ref) { + for (vf2=0; vf2 < vfsip->number_of_vfs_all; vf2++) { + if (vf1 == vf2) {//verify this VF has no duplicate groups. + dg_check = dg_ref->next_default_group; + while (dg_check) { + if (dg_check->def_mc_create) { + for_all_qmap_ptr(&dg_check->mgidMap, item2, mgid_check) { + //do not allow duplicates in the same VF + if (mgid_ref->mgid[0] == mgid_check->mgid[0] && mgid_ref->mgid[1] == mgid_check->mgid[1]) { + RENDER_VF_LOGGER(printError, "%s: Duplicate MGID (0x%016"PRIx64":0x%016"PRIx64") in MulticastGroup definitions matching same VirtualFabric (%s)", + cfgtype, mgid_ref->mgid[0], mgid_ref->mgid[1], vfsip->v_fabric_all[vf2].name); + return FDUPLICATE; + } + } + } + dg_check = dg_check->next_default_group; + } + } + else { + dg_check = vfsip->v_fabric_all[vf2].default_group; + while (dg_check) { + if (dg_check->def_mc_create) { + for_all_qmap_ptr(&dg_check->mgidMap, item2, mgid_check) { + if (mgid_ref == mgid_check) continue; + if (mgid_ref->mgid[0] == mgid_check->mgid[0] && mgid_ref->mgid[1] == mgid_check->mgid[1]) { + if (!smp->enforceVFPathRecs) { + //verify VFs are congruent, if so, allow duplicates, otherwise fail config + if (!VerifyCongruentVF(&vfsip->v_fabric_all[vf1],&vfsip->v_fabric_all[vf2], dg_ref)) { + RENDER_VF_LOGGER(printError, "%s: Duplicate MGID (0x%016"PRIx64":0x%016"PRIx64") in MulticastGroup definitions for VirtualFabric (%s)", + cfgtype, mgid_ref->mgid[0], mgid_ref->mgid[1], vfsip->v_fabric_all[vf2].name); + return FDUPLICATE; + } + } + else { + RENDER_VF_LOGGER(printError, "%s: Duplicate MGID (0x%016"PRIx64":0x%016"PRIx64") in MulticastGroup definitions for VirtualFabric (%s)", + cfgtype, mgid_ref->mgid[0], mgid_ref->mgid[1], vfsip->v_fabric_all[vf2].name); + return FDUPLICATE; + } + } + } + } + dg_check = dg_check->next_default_group; + } + } + } + } + } + dg_ref = dg_ref->next_default_group; + } + } + return FSUCCESS; +} + +// find a pointer to a rendered Virtual Fabric given the name +VF_t* findVfPointer(VirtualFabrics_t* vf_config, char* virtualFabric) +{ + uint32_t i; + + if (vf_config == NULL || virtualFabric == NULL) + return NULL; + + for (i = 0; i < vf_config->number_of_vfs_all; i++) { + if (strcmp(virtualFabric, vf_config->v_fabric_all[i].name) == 0) + return &vf_config->v_fabric_all[i]; + } + + return NULL; +} + +static +boolean compareMap(cl_qmap_t *map1, cl_qmap_t *map2, cl_pfn_qmap_compare_key_t compare) +{ + cl_map_item_t *item1; + cl_map_item_t *item2; + uint64 key1; + uint64 key2; + + item1 = cl_qmap_head(map1); key1 = (uint64) cl_qmap_key(item1); + item2 = cl_qmap_head(map2); key2 = (uint64) cl_qmap_key(item2); + while((item1 != cl_qmap_end(map1)) + && (item2 != cl_qmap_end(map2))) { + if ((*compare)(key1, key2)) { + break; + } + item1 = cl_qmap_next(item1); key1 = (uint64) cl_qmap_key(item1); + item2 = cl_qmap_next(item2); key2 = (uint64) cl_qmap_key(item2); + } + if((item1 != cl_qmap_end(map1)) + || (item2 != cl_qmap_end(map2))) { + return FALSE; + } + return TRUE; +} + +static +boolean renderApps(FMXmlInstance_t *fm_instance, VF_t *vfip, VFConfig_t *vfp, char *cfgtype, + IXmlParserPrintMessage printError, IXmlParserPrintMessage printWarning) +{ + AppConfig_t *app_list[MAX_VFABRIC_APPS]; + AppConfig_t *parent_app; + uint32_t app_list_index; + uint32_t apps; + uint32_t apps_in_list; + + // if there are no apps to match this enabled VF then this is a parse error + if (vfp->number_of_applications == 0) { + RENDER_VF_LOGGER(printError, "%s: VF(%s) does not have any valid Applications specified in the configuration", cfgtype, vfp->name); + goto fail; + } + + // build a list of all applications and included application pointers + // if an app is encountered more than once disregard + memset(app_list, 0, sizeof(app_list)); + + app_list_index = 0; + for (apps = 0; apps < vfp->number_of_applications; apps++) { + app_list[app_list_index] = findAppPointer(fm_instance, vfp->application[apps].application); + if (app_list[app_list_index]) { + parent_app = app_list[app_list_index]; + app_list_index++; + if (!includedApps(fm_instance, app_list, parent_app, &app_list_index, cfgtype, printError, printWarning)) { + goto fail; + } + } else { + RENDER_VF_LOGGER(printError, "%s: VF(%s), no such Application(%s)", cfgtype, vfp->name, vfp->application[apps].application); + goto fail; + } + + } + apps_in_list = app_list_index; + + // now that we have the app list, create entries in internal database for service ID's + // and MGID's. + VFAppSid_t *sid; + VFAppMgid_t *mgid; + + uint32_t entry; + for (app_list_index = 0; app_list_index < apps_in_list; app_list_index++) { + cl_map_item_t *cl_map_item; + + // aggregate the flags for each parsed app into the internal app structure + vfip->apps.select_sa |= app_list[app_list_index]->select_sa; + vfip->apps.select_unmatched_sid |= app_list[app_list_index]->select_unmatched_sid; + vfip->apps.select_unmatched_mgid |= app_list[app_list_index]->select_unmatched_mgid; + + vfip->apps.select_pm |= app_list[app_list_index]->select_pm; + + // add all of the individual SID's to the list + for_all_qmap_item(&app_list[app_list_index]->serviceIdMap, cl_map_item) { + sid = getAppSid(); + if (!sid) { + RENDER_VF_LOGGER(printError, "%s: Can't get SID: %s", cfgtype, OUT_OF_MEMORY); + goto fail; + } + + // since this is a unique service ID set SID then set last to 0 to + // denote no range, and mask to UNDEFINED_XML64 to denote no mask + sid->service_id = cl_qmap_key(cl_map_item); + sid->service_id_last = 0; + sid->service_id_mask = UNDEFINED_XML64; + + if (!addMap(&vfip->apps.sidMap, XML_QMAP_U64_CAST sid)) { + freeAppSid(sid); + } else { + vfip->apps.sidMapSize++; + } + } + // add all of the SID ranges to the list + char *range; + for_all_qmap_ptr(&app_list[app_list_index]->serviceIdRangeMap, cl_map_item, range) { + sid = getAppSid(); + if (!sid) { + RENDER_VF_LOGGER(printError, "%s: Can't get SID range: %s", cfgtype, OUT_OF_MEMORY); + goto fail; + } + + // since this is a range of service ID's then set it up appropriately + verifyAndConvertSidCompoundString(range, /* range */ 1, sid); + + if (!addMap(&vfip->apps.sidMap, XML_QMAP_U64_CAST sid)) { + freeAppSid(sid); + } else { + vfip->apps.sidMapSize++; + } + } + // add all of the SID masked values to the list + char *masked; + for_all_qmap_ptr(&app_list[app_list_index]->serviceIdMaskedMap, cl_map_item, masked) { + sid = getAppSid(); + if (!sid) { + RENDER_VF_LOGGER(printError, "%s: Can't get masked SID: %s", cfgtype, OUT_OF_MEMORY); + goto fail; + } + + // since this is a masked service ID then set it up appropriately + verifyAndConvertSidCompoundString(masked, /* masked */ 0, sid); + + if (!addMap(&vfip->apps.sidMap, XML_QMAP_U64_CAST sid)) { + freeAppSid(sid); + } else { + vfip->apps.sidMapSize++; + } + } + // add all of the individual MGID's to the list + for (entry = 0; entry < app_list[app_list_index]->number_of_mgids; entry++) { + mgid = getAppMgid(); + if (!mgid) { + RENDER_VF_LOGGER(printError, "%s: Can't get Mgid: %s", cfgtype, OUT_OF_MEMORY); + goto fail; + } + + // since this is an individual MGID ID then set it up appropriately + verifyAndConvertMGidString(app_list[app_list_index]->mgid[entry].mgid, mgid); + + if (!addMap(&vfip->apps.mgidMap, XML_QMAP_U64_CAST mgid)) { + freeAppMgid(mgid); + } else { + vfip->apps.mgidMapSize++; + } + } + // add all of the MGID range values to the list + for (entry = 0; entry < app_list[app_list_index]->number_of_mgid_ranges; entry++) { + mgid = getAppMgid(); + if (!mgid) { + RENDER_VF_LOGGER(printError, "%s: Can't get Mgid range: %s", cfgtype, OUT_OF_MEMORY); + goto fail; + } + + // since this is an MGID range then set it up appropriately + verifyAndConvertMGidCompoundString(app_list[app_list_index]->mgid_range[entry].range, /* range */ 1, mgid); + + if (!addMap(&vfip->apps.mgidMap, XML_QMAP_U64_CAST mgid)) { + freeAppMgid(mgid); + } else { + vfip->apps.mgidMapSize++; + } + } + // add all of the MGID masked values to the list + for (entry = 0; entry < app_list[app_list_index]->number_of_mgid_maskeds; entry++) { + mgid = getAppMgid(); + if (!mgid) { + RENDER_VF_LOGGER(printError, "%s: Can't get masked Mgid: %s", cfgtype, OUT_OF_MEMORY); + goto fail; + } + + // since this is an MGID mask then set it up appropriately + verifyAndConvertMGidCompoundString(app_list[app_list_index]->mgid_masked[entry].masked, /* masked */ 0, mgid); + + if (!addMap(&vfip->apps.mgidMap, XML_QMAP_U64_CAST mgid)) { + freeAppMgid(mgid); + } else { + vfip->apps.mgidMapSize++; + } + } + } + return TRUE; +fail: + return FALSE; +} + +static +void isSelectAllOrMgmt(DGXmlConfig_t *dg_config, int dgIdx, boolean *all, boolean *allMgmt) +{ + XmlIncGroup_t *groupp; + + if ((all && !*all) || (allMgmt && !*allMgmt)) { + if (all) { + *all |= dg_config->dg[dgIdx]->select_all; + } + + if (allMgmt) { + *allMgmt |= dg_config->dg[dgIdx]->select_all_mgmt_allowed; + } + for (groupp = dg_config->dg[dgIdx]->included_group; groupp; groupp = groupp->next) { + isSelectAllOrMgmt(dg_config, groupp->dg_index, all, allMgmt); + if ((!all || *all) && (!allMgmt || *allMgmt)) return; + } + } + return; +} + +static +int sortedMembers(DGXmlConfig_t *dg_config, XMLMember_t *dest, XMLMember_t *src, int num, boolean *all, boolean *allMgmt) +{ + int i, j; + XMLMember_t *last, *next; + int copied = 0; + + last = NULL; + for (i = 0; i < num; i++) { + next = NULL; + for (j = 0; j < num; j++) { + if ((!last || strcmp(src[j].member, last->member) > 0) && (!next || strcmp(src[j].member, next->member) < 0)) { + next = &src[j]; + } + } + if (next) { + memcpy((void *)&dest[copied], (void *)next, sizeof(XMLMember_t)); + last = next; + isSelectAllOrMgmt(dg_config, dest[copied].dg_index, all, allMgmt); + copied++; + } + } + return copied; +} + +static +boolean compareMembers(XMLMember_t *oldMembers, int numOld, XMLMember_t *newMembers, int numNew) +{ + // Compare the old and new Member lists + int i = 0; + if (numOld == numNew) { + for (i = 0; i < numOld; i++) { + if (strcmp(oldMembers[i].member, newMembers[i].member)) { + return FALSE; + } + } + return TRUE; + } + return FALSE; +} + +static +boolean reRenderVirtualFabric(VirtualFabrics_t *oldVfsip, VirtualFabrics_t *vfsip, FMXmlInstance_t *fm_instance, uint32_t vfIdx, char *cfgtype, + boolean *is_all_or_allmgmt_full, boolean *is_all_full_or_limited, IXmlParserPrintMessage printError, IXmlParserPrintMessage printWarning) +{ + if (!vfsip || !fm_instance) + return FALSE; + + VFConfig_t *vfp = fm_instance->vf_config.vf[vfIdx]; + VF_t *vfip = &vfsip->v_fabric_all[vfIdx]; + + DEBUG_ASSERT(vfp->qos_index < vfsip->number_of_qos_all); + QosConfig_t *qosip = &vfsip->qos_all[vfp->qos_index]; + + if (vfsip->number_of_vfs_all >= MAX_ENABLED_VFABRICS) { + RENDER_VF_LOGGER(printError, "%s: No more than %d Virtual Fabrics can be enabled in the configuration", cfgtype, MAX_ENABLED_VFABRICS); + goto fail; + } + + // save settings for this VF + StringCopy(vfip->name, vfp->name, MAX_VFABRIC_NAME); + vfip->index = vfIdx; + vfip->pkey = vfp->pkey; + vfip->qos_index = vfp->qos_index; + vfip->qos_implicit = vfp->qos_implicit; + vfip->standby = vfp->standby; + vfip->security = vfp->security; + + if (vfp->max_mtu_int != UNDEFINED_XML8) { + vfip->max_mtu_int = vfp->max_mtu_int; + vfip->max_mtu_specified = 1; + } else { + vfip->max_mtu_int = STL_MTU_MAX; + vfip->max_mtu_specified = 0; + } + + if (vfp->max_rate_int != UNDEFINED_XML8) { + vfip->max_rate_int = vfp->max_rate_int; + vfip->max_rate_specified = 1; + } else { + vfip->max_rate_int = IB_STATIC_RATE_MAX; + vfip->max_rate_specified = 0; + } + + if (!renderApps(fm_instance, vfip, vfp, cfgtype, printError, printWarning)) { + goto fail; + } + //MC groups will be initialized after all the VFs are done, in the meantime + vfip->number_of_default_groups = 0; + + // if there are no full or limited members to match this enabled VF then this is a parse error + if (vfp->number_of_full_members == 0 && vfp->number_of_limited_members == 0) { + RENDER_VF_LOGGER(printError, "%s: VF(%s) does not have any valid Members or LimitedMembers specified in the configuration", cfgtype, vfp->name); + goto fail; + } + + // Alphabetize the full and limited members so the user can reorder them without triggering a config change + boolean all = FALSE, allMgmt = FALSE, *allp = NULL, *allMgmtp = NULL; + if (PKEY_VALUE(vfip->pkey) == STL_DEFAULT_PKEY) { + allp = &all; allMgmtp = &allMgmt; + } + vfip->number_of_full_members = sortedMembers(&vfsip->dg_config, vfip->full_member, vfp->full_member, vfp->number_of_full_members, allp, allMgmtp); + *is_all_or_allmgmt_full = all | allMgmt; + vfip->number_of_limited_members = sortedMembers(&vfsip->dg_config, vfip->limited_member, vfp->limited_member, vfp->number_of_limited_members, allp, NULL); + *is_all_full_or_limited = all; + + uint8_t requires_resp_sl = 0; + + qosip->contains_mcast |= (vfip->apps.mgidMapSize != 0) || vfip->apps.select_unmatched_mgid; + + VF_t *oldVfip = NULL; + + // If this is a reconfigure, check the new VF against the old one + // oldVfsip will be set if this is a reconfigure + if (oldVfsip) { + // Try to find this VF in the old configuration + oldVfip = findVfPointer(oldVfsip, vfp->name); + if (oldVfip) { + vfip->reconf_idx.old_index = oldVfip->index; + if (vfip->standby && !oldVfip->standby) { + oldVfip->reconf_idx.new_index = (uint32_t)(-1); + } else if (!vfip->standby && oldVfip->standby) { + vfip->reconf_idx.old_index = (uint32_t)(-1); + } + // Make sure that changes (if any) are valid + if (vfip->qos_implicit || oldVfip->qos_implicit) { + // not much is allowed to change for qos_implicit VFs + if (vfip->pkey != oldVfip->pkey + || vfip->qos_index != oldVfip->qos_index + || vfip->qos_implicit != oldVfip->qos_implicit + || vfip->security != oldVfip->security + || vfip->max_mtu_specified != oldVfip->max_mtu_specified + || vfip->max_rate_specified != oldVfip->max_rate_specified + || vfip->max_mtu_int != oldVfip->max_mtu_int + || vfip->max_rate_int != oldVfip->max_rate_int) { + RENDER_VF_LOGGER(printError, "%s: Invalid changes to VF(%s).",cfgtype, vfip->name); + goto fail; + } + // Compare the old and new Apps + if (!compareMap(&vfip->apps.sidMap, &oldVfip->apps.sidMap, compareAppSid) + || !compareMap(&vfip->apps.mgidMap, &oldVfip->apps.mgidMap, compareAppMgid)) { + RENDER_VF_LOGGER(printError, "%s: Cannot change VF(%s) applications", cfgtype, vfp->name); + goto fail; + } + if (!compareMembers(oldVfip->full_member, oldVfip->number_of_full_members, vfip->full_member, vfip->number_of_full_members)) { + RENDER_VF_LOGGER(printError, "%s: Invalid changes to VF(%s) members.",cfgtype, vfip->name); + goto fail; + } + if (!compareMembers(oldVfip->limited_member, oldVfip->number_of_limited_members, vfip->limited_member, vfip->number_of_limited_members)) { + RENDER_VF_LOGGER(printError, "%s: Invalid changes to VF(%s) limited members.",cfgtype, vfip->name); + goto fail; + } + } else { + if (!vfip->standby && !oldVfip->standby) { + // Some things can't be changed while active + if (vfip->pkey != oldVfip->pkey + || vfip->qos_index != oldVfip->qos_index + || vfip->security != oldVfip->security + || vfip->max_mtu_specified != oldVfip->max_mtu_specified + || vfip->max_rate_specified != oldVfip->max_rate_specified + || vfip->max_mtu_int != oldVfip->max_mtu_int + || vfip->max_rate_int != oldVfip->max_rate_int) { + RENDER_VF_LOGGER(printError, "%s: Invalid changes to active VF(%s).",cfgtype, vfip->name); + goto fail; + } + // Compare the old and new Apps + if (!compareMap(&vfip->apps.sidMap, &oldVfip->apps.sidMap, compareAppSid) + || !compareMap(&vfip->apps.mgidMap, &oldVfip->apps.mgidMap, compareAppMgid)) { + RENDER_VF_LOGGER(printError, "%s: Cannot change VF(%s) applications", cfgtype, vfp->name); + goto fail; + } + if (PKEY_VALUE(vfip->pkey) == STL_DEFAULT_PKEY ) { + // Can't change members of Active Admin VFs + if (!compareMembers(oldVfip->full_member, oldVfip->number_of_full_members, vfip->full_member, vfip->number_of_full_members)) { + RENDER_VF_LOGGER(printError, "%s: Invalid changes to Admin VF(%s) members.",cfgtype, vfip->name); + goto fail; + } + if (!compareMembers(oldVfip->limited_member, oldVfip->number_of_limited_members, vfip->limited_member, vfip->number_of_limited_members)) { + RENDER_VF_LOGGER(printError, "%s: Invalid changes to Admin VF(%s) limited members.",cfgtype, vfip->name); + goto fail; + } + } + } + } + } else { + // Make sure that adding this VF is valid + if (PKEY_VALUE(vfip->pkey) == STL_DEFAULT_PKEY) { + RENDER_VF_LOGGER(printError, "%s: Cannot add VF(%s) Administrator PKey.",cfgtype, vfip->name); + goto fail; + } + if (vfip->qos_implicit) { + RENDER_VF_LOGGER(printError, "%s: Cannot add VF(%s) with explicit QOS settings.",cfgtype, vfip->name); + goto fail; + } + vfip->reconf_idx.old_index = (uint32_t)(-1); + } + if (requires_resp_sl && qosip->base_sl == qosip->resp_sl) { + RENDER_VF_LOGGER(printError, "%s: VF(%s) QOSGroup(%s) requires a unique RespSL", cfgtype, vfip->name, qosip->name); + goto fail; + } + if (requires_resp_sl && qosip->base_sl != UNDEFINED_XML8 && qosip->resp_sl == UNDEFINED_XML8){ + RENDER_VF_LOGGER(printError, "%s: VF(%s) QOSGroup(%s) specifies BaseSL, but missing required RespSL", cfgtype, vfip->name, qosip->name); + goto fail; + } + } else { + qosip->requires_resp_sl |= requires_resp_sl; + if (requires_resp_sl && qosip->base_sl != UNDEFINED_XML8 && qosip->resp_sl == UNDEFINED_XML8){ + RENDER_VF_LOGGER(printError, "%s: VF(%s) QOSGroup(%s) specifies BaseSL, but missing required RespSL", cfgtype, vfip->name, qosip->name); + goto fail; + } + if (!vfip->standby) { + vfip->reconf_idx.old_index = (uint32_t)(-1); + } + } + vfsip->number_of_vfs_all++; + + return TRUE; + +fail: + return FALSE; +} + +static void fillInQosDefaults(QosConfig_t *qosp) +{ + if (qosp->flowControlDisable == UNDEFINED_XML8) { + qosp->flowControlDisable = 0; + } + if (qosp->priority == UNDEFINED_XML8) { + qosp->priority = 0; + } + if (qosp->pkt_lifetime_mult == UNDEFINED_XML8) { + qosp->pkt_lifetime_mult = CeilLog2(1); + qosp->pkt_lifetime_specified = 0; + } + if (qosp->preempt_rank == UNDEFINED_XML8 ) { + qosp->preempt_rank = 0; + } +} + +static +boolean reRenderQosGroups(VirtualFabrics_t *vfsip, VirtualFabrics_t *oldVfsip, FMXmlInstance_t *fm_instance, char *cfgtype, + uint32_t *qos_bw, uint32_t *num_qos_wo_bw, boolean *non_qos, IXmlParserPrintMessage printError, IXmlParserPrintMessage printWarning) +{ + *qos_bw = 0; + *num_qos_wo_bw = 0; + *non_qos = FALSE; + + if (oldVfsip) { + if (fm_instance->qos_config.number_of_qosgroups != oldVfsip->number_of_qos_all) { + if (fm_instance->qos_config.number_of_qosgroups > oldVfsip->number_of_qos_all) { + RENDER_VF_LOGGER(printError, "%s: New configuration adds %d QOS groups", cfgtype, + fm_instance->qos_config.number_of_qosgroups - oldVfsip->number_of_qos_all); + } else { + RENDER_VF_LOGGER(printError, "%s: New configuration deletes %d QOS groups", cfgtype, + oldVfsip->number_of_qos_all - fm_instance->qos_config.number_of_qosgroups); + } + goto fail; + } + } + uint32_t qosIdx; + for (qosIdx = 0; qosIdx < fm_instance->qos_config.number_of_qosgroups; qosIdx++) { + QosConfig_t *qosp = fm_instance->qos_config.qosgroups[qosIdx]; + QosConfig_t *qosip = &vfsip->qos_all[qosIdx]; + + *qosip = *qosp; + fillInQosDefaults(qosip); + if (oldVfsip) { + // QOS groups aren't allowed to be added, or deleted, and must be in the same order + QosConfig_t *oldQosip = &oldVfsip->qos_all[qosIdx]; + if (!strncmp(oldQosip->name, "", sizeof(oldQosip->name))) { + // Old group is Implicit + if (strlen(qosip->name)) { + RENDER_VF_LOGGER(printError, "%s: QOSGroups cannot be added", cfgtype); + goto fail; + } + } else { + // Old group is named + if (strncmp(oldQosip->name, qosip->name, sizeof(oldQosip->name))) { + RENDER_VF_LOGGER(printError, "%s: QOSGroups cannot be removed", cfgtype); + goto fail; + } + } + if (oldQosip->qos_enable != qosip->qos_enable + || oldQosip->private_group != qosip->private_group + || oldQosip->base_sl_specified != qosip->base_sl_specified + || (oldQosip->base_sl_specified && oldQosip->base_sl != qosip->base_sl) + || oldQosip->resp_sl_specified != qosip->resp_sl_specified + || (oldQosip->resp_sl_specified && oldQosip->resp_sl != qosip->resp_sl) + || oldQosip->mcast_sl_specified != qosip->mcast_sl_specified + || (oldQosip->mcast_sl_specified && oldQosip->mcast_sl != qosip->mcast_sl) + || oldQosip->flowControlDisable != qosip->flowControlDisable + || oldQosip->priority != qosip->priority + || oldQosip->preempt_rank != qosip->preempt_rank + || oldQosip->pkt_lifetime_specified != qosip->pkt_lifetime_specified + || (oldQosip->pkt_lifetime_specified && oldQosip->pkt_lifetime_mult != qosip->pkt_lifetime_mult) + || oldQosip->hoqlife_specified != qosip->hoqlife_specified + || (oldQosip->hoqlife_specified && oldQosip->hoqlife_qos != qosip->hoqlife_qos)) { + if (strlen(oldQosip->name)) + RENDER_VF_LOGGER(printError, "%s: QOSGroups cannot be modified", cfgtype); + else + RENDER_VF_LOGGER(printError, "%s: VF Qos parameters cannot be modified", cfgtype); + goto fail; + } + // On a reconfigure, SLs are already allocated. + qosip->base_sl = oldQosip->base_sl; + qosip->resp_sl = oldQosip->resp_sl; + qosip->mcast_sl = oldQosip->mcast_sl; + qosip->contains_mcast = oldQosip->contains_mcast; + qosip->requires_resp_sl = oldQosip->requires_resp_sl; + } + + // Unused qosgroups hang around, but get no bandwidth + if (!qosip->num_vfs) qosip->percent_bandwidth = 0; + + // Inherit default values from SM Instance if not yet defined by QOSGroup + if (!qosip->hoqlife_specified) qosip->hoqlife_qos = fm_instance->sm_config.hoqlife_n2; + + if (!qosip->qos_enable) { + *non_qos = TRUE; + } else if (!qosip->priority) { + if (qosip->percent_bandwidth == UNDEFINED_XML8) { + if (qosip->num_vfs != qosip->num_implicit_vfs) { + *num_qos_wo_bw += 1; + } else { + qosip->percent_bandwidth = 0; + } + } else { + *qos_bw += qosip->percent_bandwidth; + } + } + + // if it doesn't have a name, give it one (not unique) + if (!strlen(qosp->name)) { + StringCopy(qosip->name, "", sizeof(qosip->name)); + } + + vfsip->number_of_qos_all++; + } + return TRUE; +fail: + return FALSE; +} + +static +VirtualFabrics_t* allocateVirtualFabricsConfig(void) +{ + VirtualFabrics_t *vfsip; + + vfsip = getXmlMemory(sizeof(VirtualFabrics_t), "VirtualFabrics_t allocateVirtualFabricsConfig()"); + if (!vfsip) + return NULL; + // clear all data + memset(vfsip, 0, sizeof(VirtualFabrics_t)); + + uint32_t vfIdx; + for (vfIdx = 0; vfIdx < MAX_ENABLED_VFABRICS; vfIdx++) { + VF_t *vfip = &vfsip->v_fabric_all[vfIdx]; + vfip->apps.sidMapSize = 0; + cl_qmap_init(&vfip->apps.sidMap, compareAppSid); + + vfip->apps.mgidMapSize = 0; + cl_qmap_init(&vfip->apps.mgidMap, compareAppMgid); + } + + return vfsip; +} + +VirtualFabrics_t* reRenderVirtualFabricsConfig(uint32_t fm, VirtualFabrics_t *oldVfsip, FMXmlCompositeConfig_t *config, + IXmlParserPrintMessage printError, IXmlParserPrintMessage printWarning) +{ + uint32_t qosIdx; + + uint8_t isPAAssigned = 0; + uint8_t isPMAssigned = 0; + uint8_t isSAAssigned = 0; + + char cfgtype[80]; + + + if (oldVfsip) { + snprintf(cfgtype, sizeof(cfgtype), "Dynamic reconfiguration:"); + } else { + snprintf(cfgtype, sizeof(cfgtype), "VirtualFabric configuration:"); + } + + // if there is no config data for this instance then we are done + if (config->fm_instance[fm] == NULL) + return FALSE; + + FMXmlInstance_t *fm_instance = config->fm_instance[fm]; + VirtualFabrics_t *vfsip; + // get memory for the main VF structure + vfsip = allocateVirtualFabricsConfig(); + if (!vfsip) + return NULL; + + if (!dgCopyConfig(&vfsip->dg_config, &fm_instance->dg_config)) { + goto fail; + } + + uint32_t qos_bw = 0; + uint32_t num_qos_wo_bw = 0; + boolean non_qos = FALSE; + + if (!reRenderQosGroups(vfsip, oldVfsip, fm_instance, cfgtype, &qos_bw, &num_qos_wo_bw, &non_qos, printError, printWarning)) { + goto fail; + } + + uint32_t vf_bw = 0; + uint32_t num_vf_wo_bw = 0; + uint32_t vfIdx; + for (vfIdx = 0; vfIdx < fm_instance->vf_config.number_of_vfs; vfIdx++) { + VFConfig_t *vfp = fm_instance->vf_config.vf[vfIdx]; + // Keep track of bandwidth in use by VFs, and number + // of VFs that need bandwidth. + // Standby VFs, and VFs that specify QOSGroups by name don't get bandwidth + if (!vfp->standby && vfp->qos_implicit) { + QosConfig_t *qosip = &vfsip->qos_all[vfp->qos_index]; + // High priority and nonQos VFs don't get bandwidth shares + if (!qosip->priority && qosip->qos_enable) { + if (vfp->percent_bandwidth != UNDEFINED_XML8) { + vf_bw += vfp->percent_bandwidth; + } else { + num_vf_wo_bw++; + } + } + } + + boolean is_all_or_allmgmt_full = FALSE; + boolean is_all_full_or_limited = FALSE; + if (!reRenderVirtualFabric(oldVfsip, vfsip, fm_instance, vfIdx, cfgtype, &is_all_or_allmgmt_full, &is_all_full_or_limited, printError, printWarning)) { + goto fail; + } + + VF_t *vfip = &vfsip->v_fabric_all[vfIdx]; + // If this is a Default VF, make sure that SA, PM, or PA is included. + if (PKEY_VALUE(vfip->pkey) == STL_DEFAULT_PKEY) { + if (vfip->apps.select_sa || checkVFSID(vfip, STL_PM_SERVICE_ID) || + vfip->apps.select_pm + + ) { + if (!vfip->standby) { + if (vfip->apps.select_sa) isSAAssigned++; + if (checkVFSID(vfip, STL_PM_SERVICE_ID)) isPAAssigned++; + if (vfip->apps.select_pm) isPMAssigned++; + } + } else { + RENDER_VF_LOGGER(printError, "%s: VF(%s) using the Mgmt Pkey must have , , " + "or PA Service ID configured in an Application", cfgtype, vfip->name); + goto fail; + } + // make sure that either All or AllMgmtAllowed is included in Admin fabric - this rule was added + // to make sure IBTA works for PR112665 + if (!is_all_or_allmgmt_full) { + RENDER_VF_LOGGER(printError, "%s: VF(%s) must have or configured in a Member", + cfgtype, vfip->name); + goto fail; + } + } else if (vfip->apps.select_sa || checkVFSID(vfip, STL_PM_SERVICE_ID) || + vfip->apps.select_pm + + ) { + RENDER_VF_LOGGER(printError, "%s: VF(%s) including , , " + "or PA Service ID configured in an Application must use Mgmt Pkey", + cfgtype, vfip->name); + goto fail; + } + + // make sure that All is included as a full or limited member if this virtual fabric includes SA or PM- this rule was added + // to make sure IBTA works for PR112665 + if (vfip->apps.select_sa || vfip->apps.select_pm) { + if (!is_all_full_or_limited) { + RENDER_VF_LOGGER(printError, "%s: VF(%s) includes application (%s), must contain a device group which contains " + " as a Member or LimitedMember", cfgtype, vfip->name, + vfip->apps.select_sa?(vfip->apps.select_pm?"SA and PM":"SA"):"PM"); + goto fail; + } + } + // also part of PR112665 - make sure only 1 Active VF has the in an application + if (isSAAssigned > 1) { + RENDER_VF_LOGGER(printError, "%s: Only one Virtual Fabric can have configured in an Application", cfgtype); + goto fail; + } + + // DN 441 - make sure only 1 VF has + if (isPMAssigned > 1) { + RENDER_VF_LOGGER(printError, "%s: Only one Virtual Fabric can have configured in an Application", cfgtype); + goto fail; + } + + + } + + if (!isSAAssigned) { + RENDER_VF_LOGGER(printError, "%s: An Active Virtual Fabric must exist with configured in an Application.", cfgtype); + goto fail; + } + if (!isPMAssigned) { + RENDER_VF_LOGGER(printError, "%s: An Active Virtual Fabric must exist with configured in an Application.", cfgtype); + goto fail; + } + if (!isPAAssigned) { + RENDER_VF_LOGGER(printError, "%s: An Active Default Virtual Fabric must exist with PA Service ID configured in an Application.", cfgtype); + goto fail; + } + + if (oldVfsip) { + // Validate VFs that have been deleted + uint32_t oldVfIdx; + uint32_t lastImplicit = 0; + for (oldVfIdx = 0; oldVfIdx < oldVfsip->number_of_vfs_all; oldVfIdx++) { + VF_t *oldVfip = &oldVfsip->v_fabric_all[oldVfIdx]; + VF_t *vfip = findVfPointer(vfsip, oldVfip->name); + if (!vfip) { + // VF was in old array, not in current list + if (oldVfip->qos_implicit) { + // Not allowed to delete VFs with explicit QOS parameters + RENDER_VF_LOGGER(printError, "%s: Cannot delete VF(%s) with explicit QOS parameters", cfgtype, oldVfip->name); + goto fail; + } + oldVfip->reconf_idx.new_index = (uint32_t)(-1); + } else { + if (!vfip->standby) + oldVfip->reconf_idx.new_index = vfip->index; + + if (oldVfip->qos_implicit) { + // Make sure VFs with explicit QOS aren't reordered during reconfiguration + if (vfip->index < lastImplicit) { + RENDER_VF_LOGGER(printError, "%s: Cannot reorder VFs(%s, %s) with explicit QOS parameters", + cfgtype, vfip->name,vfsip->v_fabric_all[lastImplicit].name); + goto fail; + } + lastImplicit = vfip->index; + } + } + } + } + + // Match Mc Groups to VFs + FSTATUS status=FSUCCESS; + int default_group; + + uint32_t mg, mgj; + //match explicit MGIDs with VFs + for (default_group = 0; default_group < fm_instance->sm_mdg_config.number_of_groups; default_group++) { + mdgp = &fm_instance->sm_mdg_config.group[default_group]; + if (mdgp->def_mc_create == 0) + continue; + // first assign VFs to all explicit MC groups + if (mdgp->number_of_mgids > 0 && mdgp->number_of_mgids <= MAX_VFABRIC_DG_MGIDS) { + // check that the MGID is not duplicated within the group section + for (mg=0; (mg < mdgp->number_of_mgids && mdgp->number_of_mgids <= MAX_VFABRIC_DG_MGIDS); mg++) + for (mgj=0; (mgj < mdgp->number_of_mgids && mdgp->number_of_mgids <= MAX_VFABRIC_DG_MGIDS); mgj++) { + if (mg == mgj) continue; + if (strncmp(mdgp->mgid[mg].mgid,mdgp->mgid[mgj].mgid, sizeof(mdgp->mgid[mg].mgid)) == 0) { + RENDER_VF_LOGGER(printError, "%s: Multicast group matching XML parse error - Duplicate MGIDs in the same section.", cfgtype); + goto fail; + } + } + + + status = MatchExplicitMGIDtoVF(mdgp, vfsip, FALSE /* update_active_vfabrics */, fm_instance->sm_config.enforceVFPathRecs); + + if (status != FSUCCESS) { + switch (status) { + case FUNAVAILABLE: + RENDER_VF_LOGGER(printError, "%s: Multicast group matching XML parse error - MC Groups could not be created, not enough memory.", cfgtype); + break; + case FINVALID_PARAMETER: + RENDER_VF_LOGGER(printError, "%s: Multicast group matching XML parse error - All explicit MGIDs must match some application.", cfgtype); + break; + case FINVALID_STATE: + RENDER_VF_LOGGER(printError, "%s: Multicast group matching XML parse error - Explicit MGID matches more than a single VF.", cfgtype); + break; + case FNOT_FOUND: + RENDER_VF_LOGGER(printError, "%s: Multicast group matching XML parse error - Explicit MGID did not match any enabled VF.", cfgtype); + break; + default: + RENDER_VF_LOGGER(printError, "%s: Multicast group matching XML parse error - Unknown failure.", cfgtype); + break; + } + goto fail; + } + + } + } + + //match implicit MGIDs with VFs + for (default_group = 0; default_group < fm_instance->sm_mdg_config.number_of_groups; default_group++) { + mdgp = &fm_instance->sm_mdg_config.group[default_group]; + // first assign VFs to all implicit MC groups + if (mdgp->number_of_mgids == 0) { + + status = MatchImplicitMGIDtoVF(mdgp, vfsip); + if (status != FSUCCESS) { + switch (status) { + case FUNAVAILABLE: + RENDER_VF_LOGGER(printError, "%s: Multicast group matching XML parse error - Implicit MC Groups could not be created, not enough memory.", cfgtype); + goto fail; + break; + case FNOT_FOUND: + RENDER_VF_LOGGER(printWarning, "%s: Multicast group matching XML parse error - Implicit MC Groups did not match any enabled VF.", cfgtype); + continue; + default: + RENDER_VF_LOGGER(printError, "%s: Multicast group matching XML parse error - Unknown failure.", cfgtype); + goto fail; + break; + } + } + } + } + // check for duplicate MGID's in all default group + status = checkDefaultGroupMGIDDuplicates(vfsip, &fm_instance->sm_config, cfgtype, printError, printWarning); + if (status != FSUCCESS) + goto fail; + + + // check multicast groups have not been added, removed, or changed for a VF + if (oldVfsip) { + uint32_t oldVfIdx; + for (oldVfIdx = 0; oldVfIdx < oldVfsip->number_of_vfs_all; oldVfIdx++) { + VF_t *oldVfip = &oldVfsip->v_fabric_all[oldVfIdx]; + VF_t *vfip = findVfPointer(vfsip, oldVfip->name); + if (!vfip || (!vfip->qos_implicit && (vfip->standby || oldVfip->standby))) + continue; + + if (vfip->number_of_default_groups == oldVfip->number_of_default_groups) { + VFDg_t *dgp; + VFDg_t *oldDgp; + for (dgp = vfip->default_group, oldDgp = oldVfip->default_group; + dgp && oldDgp; + dgp = dgp->next_default_group, oldDgp = oldDgp->next_default_group) { + if (dgp->def_mc_create != oldDgp->def_mc_create + || dgp->def_mc_pkey != oldDgp->def_mc_pkey + || dgp->def_mc_mtu_int != oldDgp->def_mc_mtu_int + || dgp->def_mc_rate_int != oldDgp->def_mc_rate_int + || dgp->def_mc_qkey != oldDgp->def_mc_qkey + || dgp->def_mc_fl != oldDgp->def_mc_fl + || dgp->def_mc_tc != oldDgp->def_mc_tc + || !compareMap(&dgp->mgidMap, &oldDgp->mgidMap, compareAppMgid)) { + RENDER_VF_LOGGER(printError, "%s: Cannot change VF(%s) multicast groups", cfgtype, oldVfip->name); + goto fail; + } + } + } else { + if (vfip->number_of_default_groups > oldVfip->number_of_default_groups) { + RENDER_VF_LOGGER(printError, "%s: Cannot add multicast groups to VF(%s)", cfgtype, oldVfip->name); + } else { + RENDER_VF_LOGGER(printError, "%s: Cannot remove multicast groups from VF(%s)", cfgtype, oldVfip->name); + } + goto fail; + } + } + } + + + // Allocate bandwidth to QOS groups + // Must have 5% for non QOS, and 1% for each + // VF with implicit QOS group and no bandwidth + // and each QOS group with no bandwidth + uint32_t needed_bw = (non_qos?5:0) + num_vf_wo_bw + num_qos_wo_bw; + uint32_t total_bw = vf_bw + qos_bw; + + if (total_bw > 100) { + RENDER_VF_LOGGER(printError, "%s: Total user-specified bandwidth for all active, enabled VFs and QOSGroups (%d) cannot exceed 100%%", cfgtype, total_bw); + goto fail; + } + + if ((total_bw + needed_bw) > 100) { + RENDER_VF_LOGGER(printError, "%s: Need %d%% available bandwidth for QOSGroups and Virtual Fabrics that cannot" + " or do not specify bandwidth. Available remaining bandwidth is %d%%", + cfgtype, needed_bw, 100 - total_bw); + goto fail; + } + + if (needed_bw > 0) { + // Assign the free Bandwidth + uint32_t split = 100 - total_bw; + uint32_t slices = (non_qos?1:0) + num_vf_wo_bw + num_qos_wo_bw; + uint32_t non_qos_bw=0; + + if (non_qos) { + // NonQos gets any extra bandwidth + non_qos_bw = split - (split / slices) * (slices - 1); + if (non_qos_bw < 5) non_qos_bw = 5; + split = split - non_qos_bw; + slices--; + } + + if (non_qos || num_qos_wo_bw) { + for (qosIdx = 0; qosIdx < vfsip->number_of_qos_all; qosIdx++) { + QosConfig_t *qosip = &vfsip->qos_all[qosIdx]; + + if (!qosip->num_vfs || qosip->priority) continue; + + if (!qosip->qos_enable) { + qosip->percent_bandwidth = non_qos_bw; + } else if (qosip->percent_bandwidth == UNDEFINED_XML8) { + // The only Qos groups with undefined bandwidth + // are ones with at least one VF referencing them + // by name. + qosip->percent_bandwidth = split / slices; + split -= split / slices; + slices--; + } + } + } + for (vfIdx = 0; vfIdx < vfsip->number_of_vfs_all; vfIdx++) { + VFConfig_t *vfp = fm_instance->vf_config.vf[vfIdx]; + QosConfig_t *qosip = &vfsip->qos_all[vfp->qos_index]; + + if (vfp->standby) continue; + if (!vfp->qos_implicit || !qosip->qos_enable || qosip->priority) continue; + + if (vfp->percent_bandwidth == UNDEFINED_XML8) { + qosip->percent_bandwidth += split / slices; + split -= split / slices; + slices--; + } else { + qosip->percent_bandwidth += vfp->percent_bandwidth; + } + } + } + // Make sure every in-use QOSgroup got some bandwidth + for (qosIdx = 0; qosIdx < vfsip->number_of_qos_all; qosIdx++) { + QosConfig_t *qosip = &vfsip->qos_all[qosIdx]; + + if (!qosip->num_vfs || qosip->priority) continue; + if (qosip->percent_bandwidth == 0 || qosip->percent_bandwidth == UNDEFINED_XML8) { + RENDER_VF_LOGGER(printError, "%s: Cannot allocate 0 bandwidth to an active QOSGroup", cfgtype); + goto fail; + } + } + + if (xml_vf_debug) + fprintf(stdout, "Number of Virtual Fabrics %u\n", (unsigned int)vfsip->number_of_vfs_all); + + // calculate Virtual Fabric database checksum + if (vfsip) { + if (!checksumVirtualFabricsConfig(&fm_instance->vf_config, vfsip)) + goto fail; + } + + if (xml_memory_debug) + fprintf(stdout, "Memory level %u after reRenderVirtualFabricsConfig()\n", (unsigned int)memory); + + return vfsip; + +fail: + if (vfsip) + releaseVirtualFabricsConfig(vfsip); + return NULL; +} + +// conversion utility to render XML captured data into a more application readable format +VirtualFabrics_t* renderVirtualFabricsConfig(uint32_t fm, FMXmlCompositeConfig_t *config, + IXmlParserPrintMessage printError, IXmlParserPrintMessage printWarning) +{ + return reRenderVirtualFabricsConfig(fm, NULL, config, printError, printWarning); +} + + +#ifndef __VXWORKS__ +// Syslog Facilities lookup table +static struct log_facility { + char *name; + int facility; +} log_facilities[] = { + { "auth", LOG_AUTH }, + { "authpriv", LOG_AUTHPRIV }, + { "cron", LOG_CRON }, + { "daemon", LOG_DAEMON }, + { "ftp", LOG_FTP }, + { "kern", LOG_KERN }, + { "local0", LOG_LOCAL0 }, + { "local1", LOG_LOCAL1 }, + { "local2", LOG_LOCAL2 }, + { "local3", LOG_LOCAL3 }, + { "local4", LOG_LOCAL4 }, + { "local5", LOG_LOCAL5 }, + { "local6", LOG_LOCAL6 }, + { "local7", LOG_LOCAL7 }, + { "lpr", LOG_LPR }, + { "mail", LOG_MAIL }, + { "news", LOG_NEWS }, + { "syslog", LOG_SYSLOG }, + { "user", LOG_USER }, + { "uucp", LOG_UUCP }, + { NULL, 0 } +}; + +// Translate Syslog Facility string to a integer value +int getFacility(char* name, uint8_t test) +{ + struct log_facility* p; + + if (!name) + return -1; + + for (p = log_facilities; p->name != NULL; ++p) { + if (strcmp(name, p->name) == 0) + return p->facility; + } + // if not testing then return the default if not found + if (!test) + return LOG_LOCAL6; + return -1; +} + +// Show possible Facility settings +char* showFacilities(char *facility, size_t size) +{ + struct log_facility* p; + int res = 0; + + if (!facility) + return NULL; + + facility[0] = 0; + + for (p = log_facilities; p->name != NULL; ++p) { + res = snprintf(facility, size, "%s%s", p->name, ((p + 1)->name != NULL) ? ", " : ""); + if(res > 0 && res < size) + size -= res; + else + break; + } + return facility; +} +#endif + +static IXML_FIELD SmDPLifetimeFields[] = { + { tag:"Enable", format:'u', IXML_FIELD_INFO(SMDPLXmlConfig_t, dp_lifetime[0]) }, + { tag:"Hops01_Int", format:'u', IXML_FIELD_INFO(SMDPLXmlConfig_t, dp_lifetime[1]) }, + { tag:"Hops01", format:'k', IXML_FIELD_INFO(SMDPLXmlConfig_t, dp_lifetime[1]), end_func:IXmlParserEndTimeoutMult32_Str }, + { tag:"Hops02_Int", format:'u', IXML_FIELD_INFO(SMDPLXmlConfig_t, dp_lifetime[2]) }, + { tag:"Hops02", format:'k', IXML_FIELD_INFO(SMDPLXmlConfig_t, dp_lifetime[2]), end_func:IXmlParserEndTimeoutMult32_Str }, + { tag:"Hops03_Int", format:'u', IXML_FIELD_INFO(SMDPLXmlConfig_t, dp_lifetime[3]) }, + { tag:"Hops03", format:'k', IXML_FIELD_INFO(SMDPLXmlConfig_t, dp_lifetime[3]), end_func:IXmlParserEndTimeoutMult32_Str }, + { tag:"Hops04_Int", format:'u', IXML_FIELD_INFO(SMDPLXmlConfig_t, dp_lifetime[4]) }, + { tag:"Hops04", format:'k', IXML_FIELD_INFO(SMDPLXmlConfig_t, dp_lifetime[4]), end_func:IXmlParserEndTimeoutMult32_Str }, + { tag:"Hops05_Int", format:'u', IXML_FIELD_INFO(SMDPLXmlConfig_t, dp_lifetime[5]) }, + { tag:"Hops05", format:'k', IXML_FIELD_INFO(SMDPLXmlConfig_t, dp_lifetime[5]), end_func:IXmlParserEndTimeoutMult32_Str }, + { tag:"Hops06_Int", format:'u', IXML_FIELD_INFO(SMDPLXmlConfig_t, dp_lifetime[6]) }, + { tag:"Hops06", format:'k', IXML_FIELD_INFO(SMDPLXmlConfig_t, dp_lifetime[6]), end_func:IXmlParserEndTimeoutMult32_Str }, + { tag:"Hops07_Int", format:'u', IXML_FIELD_INFO(SMDPLXmlConfig_t, dp_lifetime[7]) }, + { tag:"Hops07", format:'k', IXML_FIELD_INFO(SMDPLXmlConfig_t, dp_lifetime[7]), end_func:IXmlParserEndTimeoutMult32_Str }, + { tag:"Hops08_Int", format:'u', IXML_FIELD_INFO(SMDPLXmlConfig_t, dp_lifetime[8]) }, + { tag:"Hops08", format:'k', IXML_FIELD_INFO(SMDPLXmlConfig_t, dp_lifetime[8]), end_func:IXmlParserEndTimeoutMult32_Str }, + { tag:"Hops09_Int", format:'u', IXML_FIELD_INFO(SMDPLXmlConfig_t, dp_lifetime[9]) }, + { tag:"Hops09", format:'k', IXML_FIELD_INFO(SMDPLXmlConfig_t, dp_lifetime[9]), end_func:IXmlParserEndTimeoutMult32_Str }, + { NULL } +}; + +// Sm "DynamicPacketLifetime" start tag +static void* SmDPLifetimeXmlParserStart(IXmlParserState_t *state, void *parent, const char **attr) +{ + SMDPLXmlConfig_t *dplp = getXmlMemory(sizeof(SMDPLXmlConfig_t), "SMDPLXmlConfig_t SmDPLifetimeXmlParserStart()"); + + if (xml_parse_debug) + fprintf(stdout, "SmDPLifetimeXmlParserStart instance %u common %u\n", (unsigned int)instance, (unsigned int)common); + + if (!dplp) { + PRINT_MEMORY_ERROR; + return NULL; + } + + // inherit the values of config items already set + if (!common && configp->fm_instance[instance]) + *dplp = configp->fm_instance[instance]->sm_dpl_config; + else + *dplp = configp->fm_instance_common->sm_dpl_config; + + return dplp; // will be passed to SmDPLifetimeXmlParserEnd as object +} + +// Sm "DynamicPacketLifetime" end tag +static void SmDPLifetimeXmlParserEnd(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + SMDPLXmlConfig_t *dplp = (SMDPLXmlConfig_t *)IXmlParserGetField(field, object); + + if (xml_parse_debug) + fprintf(stdout, "SmDPLifetimeXmlParserEnd instance %u common %u\n", (unsigned int)instance, (unsigned int)common); + + if (!valid) { + fprintf(stderr, "Error processing XML Sm DynamicPacketLifetime tag\n"); + } else { + // as needed process or validate self consistency of config + } + + if (common) { + // save the common settings for this instance + configp->fm_instance_common->sm_dpl_config = *dplp; + } else if (configp->fm_instance[instance]) { + // save the Sm config for this instance + configp->fm_instance[instance]->sm_dpl_config = *dplp; + } + + freeXmlMemory(dplp, sizeof(SMDPLXmlConfig_t), "SMDPLXmlConfig_t SmDPLifetimeXmlParserEnd()"); +} + + + +// "Sm/Appliances" start tag +static void* SmAppliancesXmlParserStart(IXmlParserState_t *state, void *parent, const char **attr) +{ + return &((SMXmlConfig_t *)parent)->appliances; +} + +static IXML_FIELD SmAppliancesFields[] = { + { tag:"Enable", format:'u', IXML_FIELD_INFO(SmAppliancesXmlConfig_t, enable) }, + { tag:"Appliance01", format:'h', IXML_FIELD_INFO(SmAppliancesXmlConfig_t, guids[0]) }, + { tag:"Appliance02", format:'h', IXML_FIELD_INFO(SmAppliancesXmlConfig_t, guids[1]) }, + { tag:"Appliance03", format:'h', IXML_FIELD_INFO(SmAppliancesXmlConfig_t, guids[2]) }, + { tag:"Appliance04", format:'h', IXML_FIELD_INFO(SmAppliancesXmlConfig_t, guids[3]) }, + { tag:"Appliance05", format:'h', IXML_FIELD_INFO(SmAppliancesXmlConfig_t, guids[4]) }, + { NULL } +}; + +const char* +SmPreDefFieldEnfToText(FieldEnforcementLevel_t fieldEnfLevel) { + switch(fieldEnfLevel) { + case(FIELD_ENF_LEVEL_DISABLED): return "Disabled"; + case(FIELD_ENF_LEVEL_WARN): return "Warn"; + case(FIELD_ENF_LEVEL_ENABLED): return "Enabled"; + default: return "Unknown"; + } +} + +static void* SmPreDefTopoXmlParserStart(IXmlParserState_t *state, void *parent, const char **attr) +{ + return &((SMXmlConfig_t*)parent)->preDefTopo; +} + +static void* SmPreDefTopoFieldEnfXmlParserStart(IXmlParserState_t *state, void *parent, const char **attr) +{ + return &((SmPreDefTopoXmlConfig_t*)parent)->fieldEnforcement; +} + +static void SmPreDefTopoFieldEnfParserEnd(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) { + FieldEnforcementLevel_t* fel = (FieldEnforcementLevel_t*)IXmlParserGetField(field, object); + + if (0 == strcasecmp(content, "Disabled")) { + *fel = FIELD_ENF_LEVEL_DISABLED; + } else if (0 == strcasecmp(content, "Warn")) { + *fel = FIELD_ENF_LEVEL_WARN; + } else if (0 == strcasecmp(content, "Enabled")) { + *fel = FIELD_ENF_LEVEL_ENABLED; + } else { + IXmlParserPrintError(state, "FieldEnforcementLevel(s) must be (Disabled, Warn, or Enabled)"); + return; + } +} + +static void SmPreDefTopoXmlParserEnd(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + if ((configp->fm_instance_common->sm_config.preDefTopo.fieldEnforcement.undefinedLink == FIELD_ENF_LEVEL_DISABLED) && + ((configp->fm_instance_common->sm_config.preDefTopo.fieldEnforcement.nodeGuid > FIELD_ENF_LEVEL_DISABLED) || + (configp->fm_instance_common->sm_config.preDefTopo.fieldEnforcement.portGuid > FIELD_ENF_LEVEL_DISABLED) || + (configp->fm_instance_common->sm_config.preDefTopo.fieldEnforcement.nodeDesc > FIELD_ENF_LEVEL_DISABLED))){ + IXmlParserPrintWarning(state, "UndefinedLink is disabled. Disabling NodeDesc/NodeGUID/PortGUID."); + configp->fm_instance_common->sm_config.preDefTopo.fieldEnforcement.nodeGuid = FIELD_ENF_LEVEL_DISABLED; + configp->fm_instance_common->sm_config.preDefTopo.fieldEnforcement.nodeDesc = FIELD_ENF_LEVEL_DISABLED; + configp->fm_instance_common->sm_config.preDefTopo.fieldEnforcement.portGuid = FIELD_ENF_LEVEL_DISABLED; + } +} + +static IXML_FIELD SmPreDefTopoFieldEnfFields[] = { + { tag:"NodeGUID", format:'k', end_func:SmPreDefTopoFieldEnfParserEnd, IXML_FIELD_INFO(SmPreDefTopoFieldEnfXmlConfig_t, nodeGuid) }, + { tag:"NodeDesc", format:'k', end_func:SmPreDefTopoFieldEnfParserEnd, IXML_FIELD_INFO(SmPreDefTopoFieldEnfXmlConfig_t, nodeDesc) }, + { tag:"PortGUID", format:'k', end_func:SmPreDefTopoFieldEnfParserEnd, IXML_FIELD_INFO(SmPreDefTopoFieldEnfXmlConfig_t, portGuid) }, + { tag:"UndefinedLink", format:'k', end_func:SmPreDefTopoFieldEnfParserEnd, IXML_FIELD_INFO(SmPreDefTopoFieldEnfXmlConfig_t, undefinedLink) }, + { NULL } +}; + +static IXML_FIELD SmPreDefTopoFields[] = { + { tag:"Enabled", format:'u', IXML_FIELD_INFO(SmPreDefTopoXmlConfig_t, enabled) }, + { tag:"Enable", format:'u', IXML_FIELD_INFO(SmPreDefTopoXmlConfig_t, enabled) }, + { tag:"TopologyFilename", format:'s', IXML_FIELD_INFO(SmPreDefTopoXmlConfig_t, topologyFilename) }, + { tag:"LogMessageThreshold", format:'u', IXML_FIELD_INFO(SmPreDefTopoXmlConfig_t, logMessageThreshold) }, + { tag:"FieldEnforcement", format:'k', subfields:SmPreDefTopoFieldEnfFields, start_func:SmPreDefTopoFieldEnfXmlParserStart }, + { NULL } +}; + +static void NormalizeGuidStringParserEnd(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + char *p = (char *)IXmlParserGetField(field, object); + uint64_t mgid1, mgid2; + + if (xml_parse_debug) + fprintf(stdout, "NormalizeGuidStringParserEnd instance %u common %u\n", (unsigned int)instance, (unsigned int)common); + + if (!valid){ + fprintf(stderr, "Error processing XML %s tag\n", field->tag); + return; + } + + if (FSUCCESS != StringToGid(&mgid1, &mgid2, content, NULL, TRUE)) { + IXmlParserPrintError(state, "Error processing XML %s tag value, \"%s\"",field->tag,content); + return; + } + sprintf(p, "%16.16llx%16.16llx", + (long long unsigned int)mgid1, (long long unsigned int)mgid2); +} + +static void MLIDShareMGidLimitParserEnd(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + uint32_t value; + + if (xml_parse_debug) + fprintf(stdout, "%s instance %u common %u\n", __func__, (unsigned int)instance, (unsigned int)common); + + if (!IXmlParseUint32(state, content, len, &value)) { + fprintf(stderr, "Error processing XML %s tag\n", field->tag); + return; + } + + if (value == 0) { + IXmlParserPrintError(state, "Error processing XML %s tag: value (%u) must be greater than 0\n", field->tag, value); + return; + } + + *(uint32_t *)IXmlParserGetField(field, object) = value; +} + + + +// fields within Sm Multicast "MLIDShare" tag +static IXML_FIELD SmMcastMlidShareFields[] = { + { tag:"Enable", format:'h', IXML_FIELD_INFO(SmMcastMlidShared_t, enable) }, + { tag:"MGIDMask", format:'K', IXML_FIELD_INFO(SmMcastMlidShared_t, mcastGrpMGidLimitMaskConvert), end_func:NormalizeGuidStringParserEnd }, + { tag:"MGIDValue", format:'K', IXML_FIELD_INFO(SmMcastMlidShared_t, mcastGrpMGidLimitValueConvert), end_func:NormalizeGuidStringParserEnd }, + { tag:"MaxMLIDs", format:'U', IXML_FIELD_INFO(SmMcastMlidShared_t, mcastGrpMGidLimitMax), end_func:MLIDShareMGidLimitParserEnd }, + { tag:"MaxMLIDsPerPKey", format:'u', IXML_FIELD_INFO(SmMcastMlidShared_t, mcastGrpMGidperPkeyMax) }, + { NULL } +}; + +// Sm "MLIDShare" start tag +static void* SmMcastMlidShareXmlParserStart(IXmlParserState_t *state, void *parent, const char **attr) +{ + SmMcastMlidShared_t *dmsp = getXmlMemory(sizeof(SmMcastMlidShared_t), "SmMcastMlidShared_t SmMcastMlidShareXmlParserStart()"); + + if (xml_parse_debug) + fprintf(stdout, "SmMcastMlidShareXmlParserStart instance %u mlidSharedInstance %u common %u\n", + (unsigned int)instance, (unsigned int)mlidSharedInstance, (unsigned int)common); + + if (!dmsp) { + PRINT_MEMORY_ERROR; + return NULL; + } + + // inherit the values of config items already set + if (!common && configp->fm_instance[instance]) + *dmsp = configp->fm_instance[instance]->sm_mls_config.mcastMlid[mlidSharedInstance]; + else + *dmsp = configp->fm_instance_common->sm_mls_config.mcastMlid[mlidSharedInstance]; + + return dmsp; // will be passed to SmMcastMlidShareXmlParserEnd as object +} + +// Sm "MLIDShare" end tag +static void SmMcastMlidShareXmlParserEnd(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + SmMcastMlidShared_t *dmsp = (SmMcastMlidShared_t*)IXmlParserGetField(field, object); + uint32_t i; + char check[MAX_VFABRIC_NAME]; + + if (xml_parse_debug) + fprintf(stdout, "SmMcastMlidShareXmlParserEnd instance %u mlidSharedInstance %u common %u\n", + (unsigned int)instance, (unsigned int)mlidSharedInstance, (unsigned int)common); + + // check next MLIDShare instance + if (mlidSharedInstance >= MAX_SUPPORTED_MCAST_GRP_CLASSES_XML) { + IXmlParserPrintError(state, "Maximum number of MLIDShare instances exceeded"); + freeXmlMemory(dmsp, sizeof(SmMcastMlidShared_t), "SmMcastMlidShared_t SmMcastMlidShareXmlParserEnd()"); + return; + } + + if (!valid) { + fprintf(stderr, "Error processing XML Sm MLIDShare tag\n"); + } + + // if enabled then check for duplicate settings + if (dmsp->enable) { + for (i = 0; i < mlidSharedInstance; i++) { + if (common) + StringCopy(check, configp->fm_instance_common->sm_mls_config.mcastMlid[i].mcastGrpMGidLimitValueConvert.value, sizeof(check)); + else + StringCopy(check, configp->fm_instance[instance]->sm_mls_config.mcastMlid[i].mcastGrpMGidLimitValueConvert.value, sizeof(check)); + if (strcasecmp(dmsp->mcastGrpMGidLimitValueConvert.value, check) == 0) { + IXmlParserPrintError(state, "Duplicate MGID %s encountered in MLIDShare tag", dmsp->mcastGrpMGidLimitValueConvert.value); + freeXmlMemory(dmsp, sizeof(SmMcastMlidShared_t), "SmMcastMlidShared_t SmMcastMlidShareXmlParserEnd()"); + return; + } + } + } + + // only save if enabled + if (dmsp->enable) { + if (common) { + if (dmsp->mcastGrpMGidLimitMax < dmsp->mcastGrpMGidperPkeyMax) { + IXmlParserPrintError(state, "Max. number of shared MLIDs per Pkey (%d) must be smaller than total number of MLIDShare (%d)", + dmsp->mcastGrpMGidperPkeyMax, dmsp->mcastGrpMGidLimitMax); + freeXmlMemory(dmsp, sizeof(SmMcastMlidShared_t), "SmMcastMlidShared_t SmMcastMlidShareXmlParserEnd()"); + return; + } + // save the common settings for this instance + configp->fm_instance_common->sm_mls_config.mcastMlid[mlidSharedInstance] = *dmsp; + } else if (configp->fm_instance[instance]) { + if (dmsp->mcastGrpMGidLimitMax < dmsp->mcastGrpMGidperPkeyMax) { + IXmlParserPrintError(state, "Max. number of shared MLIDs per Pkey (%d) must be smaller than total number of MLIDShare (%d)", + dmsp->mcastGrpMGidperPkeyMax, dmsp->mcastGrpMGidLimitMax); + freeXmlMemory(dmsp, sizeof(SmMcastMlidShared_t), "SmMcastMlidShared_t SmMcastMlidShareXmlParserEnd()"); + return; + } + // save the Sm config for this instance + configp->fm_instance[instance]->sm_mls_config.mcastMlid[mlidSharedInstance] = *dmsp; + } + // index to next MLIDShare instance + mlidSharedInstance++; + } + + freeXmlMemory(dmsp, sizeof(SmMcastMlidShared_t), "SmMcastMlidShared_t SmMcastMlidShareXmlParserEnd()"); +} + +// "DefaultGroup MGID" end tag +static void VfDgMGidEnd(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + if (xml_parse_debug) + fprintf(stdout, "VfDgMGidEnd instance %u defaultGroupInstance %u dgMgidInstance %u common %u\n", + (unsigned int)instance, (unsigned int)defaultGroupInstance, (unsigned int)dgMgidInstance, (unsigned int)common); + + // check for max + if (dgMgidInstance >= MAX_VFABRIC_DG_MGIDS) { + IXmlParserPrintError(state, "Maximum number of MulticastGroup MGID instances exceeded"); + return; + } + + if (!valid) { + fprintf(stderr, "Error processing XML MGID tag\n"); + } else if (!content || !mdgp || strlen(content) > MAX_VFABRIC_NAME - 1) { + IXmlParserPrintError(state, "Bad %s content \"%s\"", field->tag, content); + return; + } + + // save away the MGID to the parent structure + snprintf(mdgp->mgid[dgMgidInstance].mgid, sizeof(mdgp->mgid[dgMgidInstance].mgid), "%s", content); + + // test conversion + VFAppMgid_t mgidMapping; + if (verifyAndConvertMGidString(content, &mgidMapping) < 0) { + IXmlParserPrintError(state, "Bad MGID format %s", content); + return; + } + + // index to next MGID instance + dgMgidInstance++; +} + +// fields within Sm Multicast "DefaultGroup" tag +static IXML_FIELD SmMcastDgFields[] = { + { tag:"Create", format:'u', IXML_FIELD_INFO(SMMcastDefGrp_t, def_mc_create) }, + { tag:"VirtualFabric", format:'s', IXML_FIELD_INFO(SMMcastDefGrp_t, virtual_fabric) }, + { tag:"PKey", format:'h', IXML_FIELD_INFO(SMMcastDefGrp_t, def_mc_pkey), end_func:PKeyParserEnd}, + { tag:"MTU_Int", format:'u', IXML_FIELD_INFO(SMMcastDefGrp_t, def_mc_mtu_int) }, + { tag:"MTU", format:'k', IXML_FIELD_INFO(SMMcastDefGrp_t, def_mc_mtu_int), end_func:MtuU8XmlParserEnd }, + { tag:"Rate_Int", format:'u', IXML_FIELD_INFO(SMMcastDefGrp_t, def_mc_rate_int) }, + { tag:"Rate", format:'k', IXML_FIELD_INFO(SMMcastDefGrp_t, def_mc_rate_int), end_func:RateU8XmlParserEnd }, + { tag:"SL", format:'h', IXML_FIELD_INFO(SMMcastDefGrp_t, def_mc_sl) }, + { tag:"QKey", format:'h', IXML_FIELD_INFO(SMMcastDefGrp_t, def_mc_qkey) }, +// parsing is kept although the tag was removed from the xml file + { tag:"FlowLabel", format:'h', IXML_FIELD_INFO(SMMcastDefGrp_t, def_mc_fl) }, + { tag:"TClass", format:'h', IXML_FIELD_INFO(SMMcastDefGrp_t, def_mc_tc) }, + { tag:"MGID", format:'k', end_func:VfDgMGidEnd }, + { NULL } +}; + +// Sm "MulticastGroup" start tag +static void* SmMcastDgXmlParserStart(IXmlParserState_t *state, void *parent, const char **attr) +{ + if (xml_parse_debug) + fprintf(stdout, "SmMcastDgXmlParserStart instance %u defaultGroupInstance %u common %u\n", + (unsigned int)instance, (unsigned int)defaultGroupInstance, (unsigned int)common); + + mdgp = getXmlMemory(sizeof(SMMcastDefGrp_t), "SMMcastDefGrp_t SmMcastDgXmlParserStart()"); + + if (!mdgp) { + PRINT_MEMORY_ERROR; + return NULL; + } + + *mdgp = mdgEmpty; + + // clear instances + dgMgidInstance = 0; + dgMgidRangeInstance = 0; + dgMgidMaskedInstance = 0; + + return mdgp; // will be passed to SmMcastDgXmlParserEnd as object +} + +// Sm "MulticastGroup" end tag +static void SmMcastDgXmlParserEnd(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + if (xml_parse_debug) + fprintf(stdout, "SmMcastDgXmlParserEnd instance %u defaultGroupInstance %u common %u\n", + (unsigned int)instance, (unsigned int)defaultGroupInstance, (unsigned int)common); + + mdgp = (SMMcastDefGrp_t *)IXmlParserGetField(field, object); + + if (!valid) { + fprintf(stderr, "Error processing XML Sm MulticastGroup tag\n"); + goto cleanup; + } + + // if the group is disabled; skip it + if (mdgp->def_mc_create == 0) { + if (xml_parse_debug) + fprintf(stdout, "MulticastGroup ingnored: Create == 0\n"); + goto cleanup; + } + + if (mdgp->def_mc_create == UNDEFINED_XML32) + mdgp->def_mc_create=1; + + if (mdgp->def_mc_mtu_int == UNDEFINED_XML8) + mdgp->def_mc_mtu_int = IB_MTU_2048; + + if (mdgp->def_mc_rate_int == UNDEFINED_XML8) + mdgp->def_mc_rate_int =IB_STATIC_RATE_25G; + + if (mdgp->def_mc_qkey == UNDEFINED_XML32) + mdgp->def_mc_qkey=0; + if (mdgp->def_mc_fl == UNDEFINED_XML32) + mdgp->def_mc_fl=0; + if (mdgp->def_mc_tc == UNDEFINED_XML32) + mdgp->def_mc_tc=0; + + // check for max (AFTER skipping uncreatable groups) + if (defaultGroupInstance >= MAX_DEFAULT_GROUPS) { + PRINT_MEMORY_ERROR; + goto cleanup; + } + + if (mdgp->def_mc_sl != UNDEFINED_XML8 && mdgp->def_mc_sl >= STL_CONFIGURABLE_SLS) { + IXmlParserPrintError(state, "MulticastGroup SL must be in range 0-%u.", (STL_CONFIGURABLE_SLS - 1)); + goto cleanup; + } + + // keep track of the number of elements + mdgp->number_of_mgids = dgMgidInstance; + mdgp->number_of_mgid_ranges = dgMgidRangeInstance; + mdgp->number_of_mgid_maskeds = dgMgidMaskedInstance; + + if (common) { + // save the common settings for this instance + configp->fm_instance_common->sm_mdg_config.group[defaultGroupInstance] = *mdgp; + } else if (configp->fm_instance[instance]) { + // save the Sm config for this instance + configp->fm_instance[instance]->sm_mdg_config.group[defaultGroupInstance] = *mdgp; + } + + // index to next DefaultGroup instance + defaultGroupInstance++; + +cleanup: + freeXmlMemory(mdgp, sizeof(SMMcastDefGrp_t), "SMMcastDefGrp_t SmMcastDgXmlParserEnd()"); +} + +static IXML_FIELD SmMcastFields[] = { + { tag:"DisableStrictCheck", format:'u', IXML_FIELD_INFO(SMMcastConfig_t, disable_mcast_check) }, + { tag:"EnablePruning", format:'u', IXML_FIELD_INFO(SMMcastConfig_t, enable_pruning) }, + { tag:"MLIDTableCap", format:'u', IXML_FIELD_INFO(SMMcastConfig_t, mcast_mlid_table_cap) }, + { tag:"RootSelectionAlgorithm", format:'s', IXML_FIELD_INFO(SMMcastConfig_t, mcroot_select_algorithm) }, + { tag:"MinCostImprovement", format:'s', IXML_FIELD_INFO(SMMcastConfig_t, mcroot_min_cost_improvement) }, + { tag:"MLIDShare", format:'k', subfields:SmMcastMlidShareFields, start_func:SmMcastMlidShareXmlParserStart, end_func:SmMcastMlidShareXmlParserEnd }, + { tag:"MulticastGroup", format:'k', subfields:SmMcastDgFields, start_func:SmMcastDgXmlParserStart, end_func:SmMcastDgXmlParserEnd }, + { NULL } +}; + +// Sm "Multicast" start tag +static void* SmMcastXmlParserStart(IXmlParserState_t *state, void *parent, const char **attr) +{ + SMMcastConfig_t *mcp = getXmlMemory(sizeof(SMMcastConfig_t), "SMMcastConfig_t SmMcastXmlParserStart()"); + + if (xml_parse_debug) + fprintf(stdout, "SmMcastXmlParserStart instance %u common %u\n", (unsigned int)instance, (unsigned int)common); + + if (!mcp) { + PRINT_MEMORY_ERROR; + return NULL; + } + + // inherit the values of config items already set + if (!common && configp->fm_instance[instance]) + *mcp = configp->fm_instance[instance]->sm_mc_config; + else + *mcp = configp->fm_instance_common->sm_mc_config; + + if (common) { + // clear instance + defaultGroupInstance = 0; + mlidSharedInstance = 0; + } else if (configp->fm_instance[instance]) { + defaultGroupInstance = configp->fm_instance[instance]->sm_mdg_config.number_of_groups; + mlidSharedInstance = configp->fm_instance[instance]->sm_mls_config.number_of_shared; + } else { + defaultGroupInstance = 0; + mlidSharedInstance = 0; + } + + return mcp; // will be passed to SmMcastXmlParserEnd as object +} + +// Sm "Multicast" end tag +static void SmMcastXmlParserEnd(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + SMMcastConfig_t *mcp = (SMMcastConfig_t*)IXmlParserGetField(field, object); + + if (xml_parse_debug) + fprintf(stdout, "SmMcastXmlParserEnd instance %u common %u\n", (unsigned int)instance, (unsigned int)common); + + if (!valid) { + fprintf(stderr, "Error processing XML Sm Multicast tag\n"); + } else { + // as needed process or validate self consistency of config + } + + if (common) { + // save the common settings for this instance + configp->fm_instance_common->sm_mc_config = *mcp; + } else if (configp->fm_instance[instance]) { + // save the Sm config for this instance + configp->fm_instance[instance]->sm_mc_config = *mcp; + } + + // save the number of default groups and MLIDShared instances + if (common) { + configp->fm_instance_common->sm_mdg_config.number_of_groups = defaultGroupInstance; + configp->fm_instance_common->sm_mls_config.number_of_shared = mlidSharedInstance; + } else if (configp->fm_instance[instance]) { + configp->fm_instance[instance]->sm_mdg_config.number_of_groups = defaultGroupInstance; + configp->fm_instance[instance]->sm_mls_config.number_of_shared = mlidSharedInstance; + } + + freeXmlMemory(mcp, sizeof(SMMcastConfig_t), "SMMcastConfig_t SmMcastXmlParserEnd()"); +} + +static void* SmLinkWidthPolicyXmlParserStart(IXmlParserState_t *state, void *parent, const char **attr) +{ + return &((SMLinkPolicyXmlConfig_t *)parent)->width_policy; +} + +static void* SmLinkSpeedPolicyXmlParserStart(IXmlParserState_t *state, void *parent, const char **attr) +{ + return &((SMLinkPolicyXmlConfig_t *)parent)->speed_policy; +} + +// fields within "Sm/LinkPolicy" tag + +static void SmLinkSpeedPolicyXmlParserEnd(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + uint16_t *p = (uint16_t *)IXmlParserGetField(field, object); + + if (xml_parse_debug) + fprintf(stdout, "SmLinkSpeedQuarantineXmlParserEnd instance %u common %u\n", (unsigned int)instance, (unsigned int)common); + + if (!valid) { + fprintf(stderr, "Error processing XML Sm %s tag\n", field->tag); + return; + } + if (!content) { + IXmlParserPrintError(state, "Invalid Sm %s tag value, cannot be empty", field->tag); + return; + } + + if (0 == strcasecmp(content, "Supported")) { + *p=0; + } else { + IXmlParserPrintError(state, "Invalid Value for Link Speed Policy: %s\n", content); + return; + } +} + +static void SmLinkWidthPolicyXmlParserEnd(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + uint16_t *p = (uint16_t *)IXmlParserGetField(field, object); + + if (xml_parse_debug) + fprintf(stdout, "SmLinkWidthQuarantineXmlParserEnd instance %u common %u\n", (unsigned int)instance, (unsigned int)common); + + if (!valid){ + fprintf(stderr, "Error processing XML Sm %s tag\n", field->tag); + return; + } + if (!content) { + IXmlParserPrintError(state, "Invalid Sm %s tag value, cannot be empty", field->tag); + return; + } + + //If content is not "Supported, it must be a valid number. + if (0 == strcasecmp(content, "Supported")) { + *p=0; + } else if (0 == strcasecmp(content, "4x")) { + *p=STL_LINK_WIDTH_4X; + } else if (0 == strcasecmp(content, "2x")) { + *p=STL_LINK_WIDTH_2X; + } else if (0 == strcasecmp(content, "3x")) { + *p=STL_LINK_WIDTH_3X; + } else { + IXmlParserPrintError(state, "Invalid Value for width Quarantine Policy: %s\n", content); + return; + } +} + + +static IXML_FIELD SmLinkSpeedPolicyFields[] = { + { tag:"Enable", format:'u', IXML_FIELD_INFO(SMPolicyConfig_t, enabled) }, + { tag:"Policy", format:'k', IXML_FIELD_INFO(SMPolicyConfig_t, policy), end_func:SmLinkSpeedPolicyXmlParserEnd}, + { NULL } +}; + +static IXML_FIELD SmLinkWidthPolicyFields[] = { + { tag:"Enable", format:'u', IXML_FIELD_INFO(SMPolicyConfig_t, enabled)}, + { tag:"Policy", format:'k', IXML_FIELD_INFO(SMPolicyConfig_t, policy), end_func:SmLinkWidthPolicyXmlParserEnd}, + { NULL } +}; + +static IXML_FIELD SmLinkPolicyFields[] = { + { tag:"MaxDroppedLanes", format:'u', IXML_FIELD_INFO(SMLinkPolicyXmlConfig_t, link_max_downgrade)}, + { tag:"SpeedPolicy", format:'k', subfields:SmLinkSpeedPolicyFields, start_func:SmLinkSpeedPolicyXmlParserStart}, + { tag:"WidthPolicy", format:'k', subfields:SmLinkWidthPolicyFields, start_func:SmLinkWidthPolicyXmlParserStart}, + { NULL } +}; + +static void * SmPortFlappingXmlParserStart(IXmlParserState_t *state, void *parent, const char **attr) +{ + return &((SMPortQuarantineXmlConfig_t *)parent)->flapping; +} + +static IXML_FIELD SmPortFlappingFields[] = { + + { tag:"WindowSize", format:'u', IXML_FIELD_INFO(SMFlappingXmlConfig_t, window_size) }, + { tag:"HighThreshold", format:'u', IXML_FIELD_INFO(SMFlappingXmlConfig_t, high_thresh) }, + { tag:"LowThreshold", format:'u', IXML_FIELD_INFO(SMFlappingXmlConfig_t, low_thresh) }, + {NULL} +}; + +static IXML_FIELD SmPortQuarantineFields[] = { + { tag:"Enable", format:'u', IXML_FIELD_INFO(SMPortQuarantineXmlConfig_t, enabled) }, + { tag:"Flapping", format:'k', subfields:SmPortFlappingFields, start_func:SmPortFlappingXmlParserStart}, + {NULL} +}; + +// "Sm/HFILink Policy" start tag +static void* SmHFILinkPolicyXmlParserStart(IXmlParserState_t *state, void *parent, const char **attr) +{ + return &((SMXmlConfig_t *)parent)->hfi_link_policy; +} + +// "Sm/ISLLink Policy" start tag +static void* SmISLLinkPolicyXmlParserStart(IXmlParserState_t *state, void *parent, const char **attr) +{ + return &((SMXmlConfig_t *)parent)->isl_link_policy; +} + +static void* SmPortQuarantineParserStart(IXmlParserState_t *state, void *parent, const char **attr) +{ + return &((SMXmlConfig_t *)parent)->port_quarantine; +} + + +static int minMaxNumString(IXmlParserState_t *state, const IXML_FIELD *field, char *str, uint32_t min, uint32_t max, uint32_t inc, boolean allowZero, uint32_t inf) +{ + int value; + char *c; + + if (!strcasecmp(str,"MIN")) return min; + else if (!strcasecmp(str,"MAX")) return max; + else if (inf > 0 && !strcasecmp(str,"INF")) return inf; + + value = strtol(str,&c,10); + if (*c) { + IXmlParserPrintError(state, "Invalid Sm %s tag value, \"%s\"", field->tag, str); + return -1; + } + if (value == 0 && allowZero) return 0; + if (value < min) { + IXmlParserPrintWarning(state, "%s tag value (%d) less than minimum (%d), using minimum",field->tag,value,min); + value = min; + } + if (value > max) { + IXmlParserPrintWarning(state, "%s tag value (%d) greater than maximum (%d), using maximum",field->tag,value,max); + value = max; + } + if (value % inc) { + int rounded = ROUNDUP(value, inc); + IXmlParserPrintWarning(state, "%s tag value (%d), rounding to multiple of %d, using (%d)",field->tag,value,inc,rounded); + value = rounded; + } + return value; +} + +static void PreemptSmallPktParserEnd(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + uint32_t *p = (uint32_t *)IXmlParserGetField(field, object); + + if (xml_parse_debug) + fprintf(stdout, "PreemptSmallPktParserEnd instance %u common %u\n", (unsigned int)instance, (unsigned int)common); + + if (!valid){ + fprintf(stderr, "Error processing XML Sm %s tag\n", field->tag); + return; + } + if (!content) { + IXmlParserPrintError(state, "Invalid Sm %s tag value, cannot be empty", field->tag); + return; + } + *p = minMaxNumString(state, field, content, SM_PREEMPT_SMALL_PACKET_MIN, SM_PREEMPT_SMALL_PACKET_MAX, SM_PREEMPT_SMALL_PACKET_INC, FALSE, 0); +} + +static void PreemptLargePktParserEnd(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + uint32_t *p = (uint32_t *)IXmlParserGetField(field, object); + + if (xml_parse_debug) + fprintf(stdout, "PreemptLargePktParserEnd instance %u common %u\n", (unsigned int)instance, (unsigned int)common); + + if (!valid){ + fprintf(stderr, "Error processing XML Sm %s tag\n", field->tag); + return; + } + if (!content) { + IXmlParserPrintError(state, "Invalid Sm %s tag value, cannot be empty", field->tag); + return; + } + *p = minMaxNumString(state, field, content, SM_PREEMPT_LARGE_PACKET_MIN, SM_PREEMPT_LARGE_PACKET_MAX, SM_PREEMPT_LARGE_PACKET_INC, FALSE, 0); +} + +static void PreemptLimitParserEnd(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + uint32_t *p = (uint32_t *)IXmlParserGetField(field, object); + + if (xml_parse_debug) + fprintf(stdout, "PreemptLimitParserEnd instance %u common %u\n", (unsigned int)instance, (unsigned int)common); + + if (!valid){ + fprintf(stderr, "Error processing XML Sm %s tag\n", field->tag); + return; + } + if (!content) { + IXmlParserPrintError(state, "Invalid Sm %s tag value, cannot be empty", field->tag); + return; + } + *p = minMaxNumString(state, field, content, SM_PREEMPT_LIMIT_MIN, SM_PREEMPT_LIMIT_MAX, SM_PREEMPT_LIMIT_INC, TRUE, SM_PREEMPT_LIMIT_INF); +} + +// fields within "Sm/Preemption" tag +static IXML_FIELD SmPreemptionFields[] = { + { tag:"SmallPacket", format:'k', IXML_FIELD_INFO(SMPreemptionXmlConfig_t, small_packet), end_func:PreemptSmallPktParserEnd }, + { tag:"LargePacket", format:'k', IXML_FIELD_INFO(SMPreemptionXmlConfig_t, large_packet), end_func:PreemptLargePktParserEnd }, + { tag:"PreemptLimit", format:'k', IXML_FIELD_INFO(SMPreemptionXmlConfig_t, preempt_limit), end_func:PreemptLimitParserEnd }, + { NULL } +}; + +// "Sm/Preemption" start tag +static void* SmPreemptionXmlParserStart(IXmlParserState_t *state, void *parent, const char **attr) +{ + SMPreemptionXmlConfig_t *preemption = &((SMXmlConfig_t *)parent)->preemption; + + // Initialize defaults + return preemption; +} + +// fields within "Sm/Congestion/Sw" tag +static IXML_FIELD SmSwCongestionFields[] = { + { tag:"VictimMarkingEnable", format:'u', IXML_FIELD_INFO(SmSwCongestionXmlConfig_t, victim_marking_enable) }, + { tag:"Threshold", format:'u', IXML_FIELD_INFO(SmSwCongestionXmlConfig_t, threshold) }, + { tag:"PacketSize", format:'u', IXML_FIELD_INFO(SmSwCongestionXmlConfig_t, packet_size) }, + { tag:"CsThreshold", format:'u', IXML_FIELD_INFO(SmSwCongestionXmlConfig_t, cs_threshold) }, + { tag:"CsReturnDelay", format:'u', IXML_FIELD_INFO(SmSwCongestionXmlConfig_t, cs_return_delay) }, + { tag:"MarkingRate", format:'u', IXML_FIELD_INFO(SmSwCongestionXmlConfig_t, marking_rate) }, + { NULL } +}; + +// "Sm/Congestion/Sw" start tag +static void* SmSwCongestionXmlParserStart(IXmlParserState_t *state, void *parent, const char **attr) +{ + return &((SmCongestionXmlConfig_t *)parent)->sw; +} + +// fields within "Sm/Congestion/Ca" tag +static IXML_FIELD SmCaCongestionFields[] = { + { tag:"Basis", format:'k', IXML_FIELD_INFO(SmCaCongestionXmlConfig_t, sl_based), end_func:BasisU8XmlParserEnd }, + { tag:"Increase", format:'u', IXML_FIELD_INFO(SmCaCongestionXmlConfig_t, increase) }, + { tag:"Timer", format:'u', IXML_FIELD_INFO(SmCaCongestionXmlConfig_t, timer) }, + { tag:"Threshold", format:'u', IXML_FIELD_INFO(SmCaCongestionXmlConfig_t, threshold) }, + { tag:"Min", format:'u', IXML_FIELD_INFO(SmCaCongestionXmlConfig_t, min) }, + { tag:"Limit", format:'u', IXML_FIELD_INFO(SmCaCongestionXmlConfig_t, limit) }, + { tag:"DesiredMaxDelay", format:'u', IXML_FIELD_INFO(SmCaCongestionXmlConfig_t, desired_max_delay) }, + { NULL } +}; + +// "Sm/Congestion/Ca" start tag +static void* SmCaCongestionXmlParserStart(IXmlParserState_t *state, void *parent, const char **attr) +{ + return &((SmCongestionXmlConfig_t *)parent)->ca; +} + +// fields within "Sm/CongestionControl" tag +static IXML_FIELD SmCongestionFields[] = { + { tag:"Enable", format:'u', IXML_FIELD_INFO(SmCongestionXmlConfig_t, enable) }, + { tag:"Debug", format:'u', IXML_FIELD_INFO(SmCongestionXmlConfig_t, debug) }, + { tag:"Switch", format:'k', subfields:SmSwCongestionFields, start_func:SmSwCongestionXmlParserStart }, + { tag:"Fi", format:'k', subfields:SmCaCongestionFields, start_func:SmCaCongestionXmlParserStart }, + { NULL } +}; + + +// "Sm/Congestion" start tag +static void* SmCongestionXmlParserStart(IXmlParserState_t *state, void *parent, const char **attr) +{ + return &((SMXmlConfig_t *)parent)->congestion; +} + + +// fields within "Sm/Mesh/Torus " tag +static void SmPortPairEnd(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + int port1, port2; + SmDimension_t *dim = (SmDimension_t*)parent; + + if (xml_parse_debug) + fprintf(stdout, "SmPortPairEnd instance %u common %u\n", + (unsigned int)instance, (unsigned int)common); + + if (!valid) { + fprintf(stderr, "Error processing XML PortPair tag\n"); + return; + } else if (!content || !dim || strlen(content) > 8) { + IXmlParserPrintError(state, "Bad %s content \"%s\"", field->tag, content); + return; + } + + if (dim->portCount >= MAX_SWITCH_PORTS) { + IXmlParserPrintError(state, "PortPair configured exceeds max allowed %d", dim->portCount); + return; + } + + if (sscanf(content, "%d,%d", &port1, &port2) != 2) { + IXmlParserPrintError(state, "PortPair %s is formatted incorrectly, expecting: port1,port2", content); + return; + } + + if ((port1 > 255) || (port2 > 255)) { + IXmlParserPrintError(state, "PortPair %s is out of range (>255)", content); + return; + } + + dim->portPair[dim->portCount].port1 = port1; + dim->portPair[dim->portCount].port2 = port2; + dim->portCount++; +} + +static void* SmDimensionStart(IXmlParserState_t *state, void *parent, const char **attr) +{ + SmDorRouting_t *dor = (SmDorRouting_t*)parent; + + if (xml_parse_debug) + fprintf(stdout, "SmDimensionStart instance %u common %u\n", + (unsigned int)instance, (unsigned int)common); + + if (!dor) + return NULL; + + if (dor->dimensionCount >= MAX_DOR_DIMENSIONS) { + IXmlParserPrintError(state, "Dimensions configured exceeds max allowed %d", dor->dimensionCount); + return NULL; + } + + dor->dimensionCount++; + return &(dor->dimension[dor->dimensionCount-1]); +} + +static void SmDorRouteLastEnd(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + SmDorRouting_t *dor = (SmDorRouting_t*)parent; + + if (!valid) { + fprintf(stderr, "Error processing XML RouteLast tag\n"); + } else if (!content || !dor || strlen(content) > MAX_VFABRIC_NAME) { + IXmlParserPrintError(state, "Bad RouteLast group name"); + return; + } else if (!getVfXmlMember(&dor->routeLast, content)) { + IXmlParserPrintError(state, "Device Group (%s) was not found", content); + return; + } +} + +static void* SmDorRoutingXmlParserStart(IXmlParserState_t *state, void *parent, const char **attr) +{ + SmDorRouting_t *dor = getXmlMemory(sizeof(SmDorRouting_t), "SmDorRouting_t SmDorRoutingXmlParserStart()"); + + if (xml_parse_debug) + fprintf(stdout, "SmDorRoutingXmlParserStart instance %u common %u\n", + (unsigned int)instance, (unsigned int)common); + + if (!dor) { + PRINT_MEMORY_ERROR; + return NULL; + } + + memset(dor, 0, sizeof(SmDorRouting_t)); + + dor->warn_threshold = DEFAULT_DOR_PORT_PAIR_WARN_THRESHOLD; + dor->escapeVLs = DEFAULT_ESCAPE_VLS_IN_USE; + dor->faultRegions = DEFAULT_FAULT_REGIONS_IN_USE; + + return dor; +} + +static void SmDorRoutingXmlParserEnd(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + + uint8_t portsInUse[256]; + int nonToroidalEdges = 0; + int configFailed = 0; + int port, dim; + + if (xml_parse_debug) + fprintf(stdout, "SmDorRoutingXmlParserEnd instance %u common %u\n", + (unsigned int)instance, (unsigned int)common); + + SMXmlConfig_t *smp = (SMXmlConfig_t*)parent; + SmDorRouting_t *dor = (SmDorRouting_t*)IXmlParserGetField(field, object); + + if (!dor) return; + + if (dor->dimensionCount == 0) { + IXmlParserPrintError(state, "dor algorithm selected but no dimensions specified!"); + } + + memset (portsInUse, 0, sizeof(portsInUse)); + + for (dim=0; dimdimensionCount; dim++) { + if (dor->dimension[dim].portCount == 0) { + IXmlParserPrintError(state, "MeshTorusTopology Dimension must be configured with a PortPair."); + break; + } + + if (dor->dimension[dim].toroidal) { + dor->numToroidal++; + } else { + nonToroidalEdges = 1; + } + + if (dor->dimension[dim].length == 0) + IXmlParserPrintError(state, "The length of the dimension must be specified"); + + // Verify no overlap for port pairs + for (port=0; portdimension[dim].portCount; port++) { + if (dor->dimension[dim].toroidal && dor->dimension[dim].portPair[port].port1 == + dor->dimension[dim].portPair[port].port2) { + configFailed = 1; + IXmlParserPrintError(state, "Port %d is used for both ports in dimension pair, hyperlink cannot be toroidal", + dor->dimension[dim].portPair[port].port1); + } + if (!dor->dimension[dim].toroidal && dor->dimension[dim].length > 2 + && dor->dimension[dim].portPair[port].port1 == + dor->dimension[dim].portPair[port].port2) { + configFailed = 1; + IXmlParserPrintError(state, "Port %d is used for both ports in" + " dimension pair, hyperlink cannot have a dimension length > 2", + dor->dimension[dim].portPair[port].port1); + } + if (portsInUse[dor->dimension[dim].portPair[port].port1] || portsInUse[dor->dimension[dim].portPair[port].port2]) { + configFailed = 1; + if (portsInUse[dor->dimension[dim].portPair[port].port1]) + IXmlParserPrintError(state, "Port %d is used in multiple dimension pairs", + dor->dimension[dim].portPair[port].port1); + if (portsInUse[dor->dimension[dim].portPair[port].port2]) + IXmlParserPrintError(state, "Port %d is used in multiple dimension pairs", + dor->dimension[dim].portPair[port].port2); + break; + } + portsInUse[dor->dimension[dim].portPair[port].port1] = 1; + portsInUse[dor->dimension[dim].portPair[port].port2] = 1; + } + if (configFailed) break; + } + + if (dor->numToroidal > MAX_TOROIDAL_DIMENSIONS) { + IXmlParserPrintError(state, "The number of dimensions that may be configured as toroidal is limited to "add_quotes(MAX_TOROIDAL_DIMENSIONS)"."); + } + + if (dor->numToroidal && nonToroidalEdges) { + dor->topology = DOR_PARTIAL_TORUS; + } else if (dor->numToroidal) { + dor->topology = DOR_TORUS; + } else { + dor->topology = DOR_MESH; + } + + if (dor->topology == DOR_MESH) { + dor->routingSCs = dor->escapeVLs ? 2 : 1; + } else { + dor->routingSCs = dor->escapeVLs ? 4 : 2; + } + + smp->smDorRouting = *dor; + + freeXmlMemory(dor, sizeof(SmDorRouting_t), "SmDorRouting_t SmDorRoutingXmlParserEnd()"); +} + +static IXML_FIELD SmDimensionFields[] = { + { tag:"Toroidal", format:'u', IXML_FIELD_INFO(SmDimension_t, toroidal) }, + { tag:"Length", format:'u', IXML_FIELD_INFO(SmDimension_t, length) }, + { tag:"PortPair", format:'s', end_func:SmPortPairEnd }, + { NULL } +}; + +static IXML_FIELD SmDorRoutingFields[] = { + { tag:"Debug", format:'u', IXML_FIELD_INFO(SmDorRouting_t, debug) }, + { tag:"UseEscapeVLs", format:'u', IXML_FIELD_INFO(SmDorRouting_t, escapeVLs) }, + { tag:"UseFaultRegions", format:'u', IXML_FIELD_INFO(SmDorRouting_t, faultRegions) }, + { tag:"Dimension", format:'k', subfields:SmDimensionFields, start_func:SmDimensionStart }, + { tag:"RouteLast", format:'k', end_func:SmDorRouteLastEnd }, + { tag:"WarnThreshold", format:'u', IXML_FIELD_INFO(SmDorRouting_t, warn_threshold) }, + { tag:"OverlayMulticast", format:'u', IXML_FIELD_INFO(SmDorRouting_t, overlayMCast) }, + { NULL } +}; + +// fields within "Sm/Adaptive Routing" tag +static IXML_FIELD SmAdaptiveRoutingFields[] = { + { tag:"Enable", format:'u', IXML_FIELD_INFO(SmAdaptiveRoutingXmlConfig_t, enable) }, + { tag:"Debug", format:'u', IXML_FIELD_INFO(SmAdaptiveRoutingXmlConfig_t, debug) }, + { tag:"Algorithm", format:'u', IXML_FIELD_INFO(SmAdaptiveRoutingXmlConfig_t, algorithm) }, + { tag:"LostRouteOnly", format:'u', IXML_FIELD_INFO(SmAdaptiveRoutingXmlConfig_t, lostRouteOnly) }, + { tag:"ARFrequency", format:'u', IXML_FIELD_INFO(SmAdaptiveRoutingXmlConfig_t, arFrequency) }, + { tag:"Threshold", format:'u', IXML_FIELD_INFO(SmAdaptiveRoutingXmlConfig_t, threshold) }, + { NULL } +}; + +static void* SmFtreeRoutingXmlParserStart(IXmlParserState_t *state, void *parent, const char **attr) +{ + SmFtreeRouting_t *p = &((SMXmlConfig_t *)parent)->ftreeRouting; + return p; +} + +static void SmFtreeCoreSwitchEnd(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + SmFtreeRouting_t *ftreeRouting = (SmFtreeRouting_t*)parent; + + if (!valid) { + fprintf(stderr, "Error processing XML CoreSwitch tag\n"); + } else if (!content || !ftreeRouting || strlen(content) > MAX_VFABRIC_NAME) { + IXmlParserPrintError(state, "Bad CoreSwitch group name"); + return; + } else if (!getVfXmlMember(&ftreeRouting->coreSwitches, content)) { + IXmlParserPrintError(state, "Device Group (%s) was not found", content); + return; + } +} + +static void SmFtreeRouteLastEnd(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + SmFtreeRouting_t *ftreeRouting = (SmFtreeRouting_t*)parent; + + if (!valid) { + fprintf(stderr, "Error processing XML RouteLast tag\n"); + } else if (!content || !ftreeRouting || strlen(content) > MAX_VFABRIC_NAME) { + IXmlParserPrintError(state, "Bad RouteLast group name"); + return; + } else if (!getVfXmlMember(&ftreeRouting->routeLast, content)) { + IXmlParserPrintError(state, "Device Group (%s) was not found", content); + return; + } +} + +static void SmFtreeRoutingXmlParserEnd(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + if (!valid) { + fprintf(stderr, "Error processing XML Sm FtreeRouting tag\n"); + } +} + +static IXML_FIELD SmFtreeRoutingFields[] = { + { tag:"Debug", format:'u', IXML_FIELD_INFO(SmFtreeRouting_t, debug) }, + { tag:"PassThrough", format:'u', IXML_FIELD_INFO(SmFtreeRouting_t, passthru) }, + { tag:"Converge", format:'u', IXML_FIELD_INFO(SmFtreeRouting_t, converge) }, + { tag:"FIsOnSameTier", format:'u', IXML_FIELD_INFO(SmFtreeRouting_t, fis_on_same_tier) }, + { tag:"TierCount", format:'u', IXML_FIELD_INFO(SmFtreeRouting_t, tierCount) }, + { tag:"CoreSwitches", format:'k', end_func:SmFtreeCoreSwitchEnd }, + { tag:"RouteLast", format:'k', end_func:SmFtreeRouteLastEnd }, + { NULL } +}; + + +static void* DGRoutingOrderXmlParserStart(IXmlParserState_t *state, void *parent, const char **attr) +{ + SmDGRouting_t *p = (SmDGRouting_t *)parent; + p->dgCount = 0; + return p; +} + +static void DGRoutingOrderXmlParserEnd(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + if (!valid) { + fprintf(stderr, "Error processing XML DGRouting RoutingOrder tag\n"); + } +} + +static void* SmDGRoutingXmlParserStart(IXmlParserState_t *state, void *parent, const char **attr) +{ + // Initialize structure to NULL. + SmDGRouting_t *p = &((SMXmlConfig_t *)parent)->dgRouting; + memset(p,0,sizeof(SmDGRouting_t)); + + return p; +} + +static void SmDGRoutingXmlParserEnd(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + if (!valid) { + fprintf(stderr, "Error processing XML Sm DGRouting tag\n"); + } +} + +static void DGRoutingDeviceGroupEnd(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + SmDGRouting_t *p = (SmDGRouting_t *)parent; + + if (!valid) { + fprintf(stderr, "Error processing XML DGRouting RoutingOrder DeviceGroup tag\n"); + return; + } else if (p->dgCount >= MAX_DGROUTING_ORDER) { + IXmlParserPrintError(state, "Error processing XML DGRouting RoutingOrder too many DeviceGroup tags\n"); + return; + } else if (!getVfXmlMember(&p->dg[p->dgCount], content)) { + IXmlParserPrintError(state, "Device Group (%s) was not found", content); + return; + } + p->dgCount++; +} + +static IXML_FIELD DGRoutingOrderFields[] = { + { tag:"DeviceGroup", format:'k', end_func:DGRoutingDeviceGroupEnd } +}; + +static IXML_FIELD SmDGRoutingFields[] = { + { tag:"RoutingOrder", format:'k', subfields:DGRoutingOrderFields, start_func:DGRoutingOrderXmlParserStart, end_func:DGRoutingOrderXmlParserEnd }, + { NULL } +}; + +static IXML_FIELD XmlSPRoutingPortFields[] = { + { tag:"pPort", format:'u', IXML_FIELD_INFO(SmSPRoutingPort_t, pport) }, + { tag:"vPort", format:'u', IXML_FIELD_INFO(SmSPRoutingPort_t, vport) }, + { tag:"Cost", format:'u', IXML_FIELD_INFO(SmSPRoutingPort_t, cost) }, + { NULL } +}; + +static void XmlSProutingSwitchesEnd(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + SmSPRoutingCtrl_t *routingData = (SmSPRoutingCtrl_t*)parent; + + if (!valid) { + fprintf(stderr, "Error processing XML Enhanced Hypercube Routing Control Switches tag\n"); + } else if (!content || !routingData || strlen(content) > MAX_VFABRIC_NAME) { + IXmlParserPrintError(state, "Bad Enhanced Hypercube Routing Control Switches group name"); + return; + } else if (!getVfXmlMember(&routingData->switches, content)) { + IXmlParserPrintError(state, "Device Group (%s) was not found", content); + return; + } +} + +static void XmlSPRoutingPortParserEnd(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + SmSPRoutingPort_t *PortData = object; + uint8_t pport = PortData->pport; + uint8_t vport = PortData->vport; + uint16_t cost = PortData->cost; + SmSPRoutingCtrl_t *SPRoutingCtrl = parent; + portMap_t *pportMap = SPRoutingCtrl->pportMap; + portMap_t *vportMap = SPRoutingCtrl->vportMap; + SmSPRoutingPort_t *ports = SPRoutingCtrl->ports; + uint16_t portCount = SPRoutingCtrl->portCount; + uint16_t portsSize = ROUNDUP(portCount, PORTS_ALLOC_UNIT); + + if (xml_parse_debug) { + fprintf(stdout, "%s %s instance %u common %u\n", __FUNCTION__, + field->tag, (unsigned int)instance, (unsigned int)common); + } + + MemoryDeallocate(PortData); + if (!valid) { + fprintf(stderr, "Error processing XML %s tag\n", field->tag); + return; + } + + if (pport >= MAX_SWITCH_PORTS) { + IXmlParserPrintError(state, "bad pPort %d", pport); + return; + } + if (vport >= MAX_SWITCH_PORTS) { + IXmlParserPrintError(state, "bad vPort %d", vport); + return; + } + + // check for duplicates + + if (pport) { + if (portMapTest(pportMap, pport)) { + IXmlParserPrintError(state, "pPort %d already specified", pport); + return; + } + portMapSet(pportMap, pport); + } + + if (vport) { + if (portMapTest(vportMap, vport)) { + IXmlParserPrintError(state, "vPort %d already specified", vport); + return; + } + portMapSet(vportMap, vport); + } + + if (portCount >= portsSize) { + portsSize += PORTS_ALLOC_UNIT; + ports = getXmlMemory(portsSize*sizeof(*ports), "SmSPRoutingPort_t *ports"); + if (!ports) { + PRINT_MEMORY_ERROR; + return; + } + if (portCount) { + memcpy(ports, SPRoutingCtrl->ports, portCount*sizeof(*ports)); + freeXmlMemory(SPRoutingCtrl->ports, portCount*sizeof(*ports), + "SmSPRoutingPort_t *ports"); + } + SPRoutingCtrl->ports = ports; + } + ports += portCount; + ports->pport = pport; + ports->vport = vport; + ports->cost = cost; + SPRoutingCtrl->portCount++; +}; + +static IXML_FIELD XmlSPRoutingCtrlFields[] = { + { tag:"Switches", format:'k', end_func:XmlSProutingSwitchesEnd }, + { tag:"PortData", format:'k', size:sizeof(SmSPRoutingPort_t), subfields:XmlSPRoutingPortFields, start_func:IXmlParserStartStruct, end_func:XmlSPRoutingPortParserEnd }, + { NULL } +}; + +static void XmlSPRoutingCtrlParserEnd(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + SmSPRoutingCtrl_t *XmlSPRoutingCtrl = object; + XMLMember_t switches = XmlSPRoutingCtrl->switches; + SmHypercubeRouting_t *ehc = (SmHypercubeRouting_t*)parent; + SmSPRoutingCtrl_t **prev = &ehc->enhancedRoutingCtrl; + SmSPRoutingCtrl_t *SPRoutingCtrl = ehc->enhancedRoutingCtrl; + + if (xml_parse_debug) { + fprintf(stdout, "%s %s instance %u common %u\n", __FUNCTION__, + field->tag, (unsigned int)instance, (unsigned int)common); + } + + if (!valid) { + fprintf(stderr, "Error processing XML %s tag\n", field->tag); + goto done; + } + + // see if we already have this GUID + while (SPRoutingCtrl) { + if (strcmp(SPRoutingCtrl->switches.member, switches.member) == 0) { + if (strlen(switches.member) == 0) { + IXmlParserPrintError(state, "Multiple Enhanced Hypercube Routing Control default groups encountered, only one default group allowed."); + } else { + IXmlParserPrintError(state, "Duplicate Enhanced Hypercube Routing Control Switches groups (%s) encountered", + switches.member); + } + goto done; + } + prev = &SPRoutingCtrl->next; + SPRoutingCtrl = *prev; + } + SPRoutingCtrl = getXmlMemory(sizeof(*SPRoutingCtrl), "SmSPRoutingCtrl_t *SPRoutingCtrl"); + if (!SPRoutingCtrl) { + PRINT_MEMORY_ERROR; + goto done; + } + *SPRoutingCtrl = *XmlSPRoutingCtrl; + *prev = SPRoutingCtrl; + +done: + MemoryDeallocate(XmlSPRoutingCtrl); +} + +static void* SmHypercubeRoutingXmlParserStart(IXmlParserState_t *state, void *parent, const char **attr) +{ + SmHypercubeRouting_t *p = &((SMXmlConfig_t *)parent)->hypercubeRouting; + return p; +} + +static void SmHypercubeRoutingXmlParserEnd(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + if (!valid) { + fprintf(stderr, "Error processing XML Sm Enhanced Hypercube tag\n"); + } +} + +static void SmHyperRouteLastEnd(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + SmHypercubeRouting_t *p = &((SMXmlConfig_t *)parent)->hypercubeRouting; + + if (!valid) { + fprintf(stderr, "Error processing XML Hypercube RouteLast tag\n"); + } else if (!content || !p || strlen(content) > MAX_VFABRIC_NAME) { + IXmlParserPrintError(state, "Bad RouteLast group name"); + return; + } else if (!getVfXmlMember(&p->routeLast, content)) { + IXmlParserPrintError(state, "Device Group (%s) was not found", content); + return; + } +} + +static IXML_FIELD SmHypercubeRoutingFields[] = { + { tag:"Debug", format:'u', IXML_FIELD_INFO(SmHypercubeRouting_t, debug) }, + { tag:"RouteLast", format:'k', end_func:SmHyperRouteLastEnd }, + { tag:"EnhancedRoutingCtrl", format:'k', size:sizeof(SmSPRoutingCtrl_t), subfields:XmlSPRoutingCtrlFields, start_func:IXmlParserStartStruct, end_func:XmlSPRoutingCtrlParserEnd }, + { NULL } +}; + +// "Sm/AdaptiveRouting" start tag +static void* SmAdaptiveRoutingXmlParserStart(IXmlParserState_t *state, void *parent, const char **attr) +{ + return &((SMXmlConfig_t *)parent)->adaptiveRouting; +} + +// "Sm/AdaptiveRouting" end tag +static void SmAdaptiveRoutingXmlParserEnd(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + SmAdaptiveRoutingXmlConfig_t *p = (SmAdaptiveRoutingXmlConfig_t*)IXmlParserGetField(field, object); + if (!valid) { + fprintf(stderr, "Error processing XML Sm AdaptiveRouting tag\n"); + return; + } + // Not sure we should validate the threshold here and only here + // since there may be other places AR can be enabled + // + // AR has 16 congestion levels but the user can only specify 8 of those + // [0,7] where 0 means 'use SMA/firmware default' + else if (p->enable && (p->threshold > 7)) { + if (p->threshold == UNDEFINED_XML8) p->threshold = 0; + else IXmlParserPrintError(state, "Adaptive Routing threshold must be in the range 0-7"); + } + + if (p->algorithm > 2) {// 2 is the maximum defined right now + IXmlParserPrintError(state, "Adaptive Routing algorithm must be 0, 1 or 2."); + p->algorithm = 0; + return; + } +} + +// "PathSelection" end tag +static void SmPathSelectionParserEnd(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + uint32_t *p = (uint32_t *)IXmlParserGetField(field, object); + + if (0 == strcasecmp(content, "minimal")) { + *p = PATH_MODE_MINIMAL; + } else if (0 == strcasecmp(content, "pairwise")) { + *p = PATH_MODE_PAIRWISE; + } else if (0 == strcasecmp(content, "orderall")) { + *p = PATH_MODE_ORDERALL; + } else if (0 == strcasecmp(content, "srcdstall")) { + *p = PATH_MODE_SRCDSTALL; + } else { + IXmlParserPrintError(state, "PathSelection must be (Minimal, Pairwise, Orderall or SrcDstAll)"); + return; + } +} + +static void SmCIPParserEnd(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + uint8_t i = CIP_NONE; + + while (isspace(*content)) content++; + + if (0 == strcasecmp(content, "ByPort")) i = CIP_PORT; + else if (0 == strcasecmp(content, "ByLink")) i = CIP_LINK; + else if(0 == strcasecmp(content, "None")) i = CIP_NONE; + else { + IXmlParserPrintError(state, "CableInfoPolicy must be (ByPort, ByLink, None)"); + return; + } + + *(uint8_t *)IXmlParserGetField(field, object) = i; + + return; +} + +// Validate a LID against the range 0x0 - (0xf0000000-1). +static void SmUnicastLidXmlParserEnd(IXmlParserState_t *state, + const IXML_FIELD *field, void *object, void *parent, XML_Char *content, + unsigned len, boolean valid) +{ + uint64_t long_lid; + uint32_t *real_lid = (uint32_t *)IXmlParserGetField(field, object); + + if (! IXmlParseUint64(state, content, len, &long_lid)) { + return; + } + + if (long_lid >= STL_LID_MULTICAST_BEGIN) { + IXmlParserPrintError(state, "Value out of range"); + return; + } + + *real_lid = (uint32_t)long_lid; + return; +} + +// Validate the sweep interval against the range [0,3-86400] +static void SmSweepIntervalParserEnd(IXmlParserState_t *state, + const IXML_FIELD *field, void *object, void *parent, XML_Char *content, + unsigned len, boolean valid) +{ + uint64_t timer; + + if (!IXmlParseUint64(state, content, len, &timer)) { + return; + } + + if (timer > SM_MAX_SWEEPRATE || (timer < SM_MIN_SWEEPRATE && timer != SM_NO_SWEEP)) { + IXmlParserPrintError(state, "Sm SweepInterval must either be %u or in the range of %u-%u", + SM_NO_SWEEP, SM_MIN_SWEEPRATE, SM_MAX_SWEEPRATE); + return; + } + + *(uint64_t *)IXmlParserGetField(field, object) = timer; +} + +static void CumulativeTimeoutLimitParserEnd(IXmlParserState_t *state, + const IXML_FIELD *field, void *object, void *parent, XML_Char *content, + unsigned len, boolean valid) +{ + uint64_t value; + + if (!IXmlParseUint64(state, content, len, &value)) { + return; + } + + *(uint64_t *)IXmlParserGetField(field, object) = value * VTIMER_1S; +} + +// fields within "Sm" tag +static IXML_FIELD SmFields[] = { + { tag:"Start", format:'u', IXML_FIELD_INFO(SMXmlConfig_t, start) }, + { tag:"SmKey", format:'u', IXML_FIELD_INFO(SMXmlConfig_t, sm_key) }, + { tag:"MKey", format:'u', IXML_FIELD_INFO(SMXmlConfig_t, mkey) }, + { tag:"StartupRetries", format:'u', IXML_FIELD_INFO(SMXmlConfig_t, startup_retries) }, + { tag:"StartupStableWait", format:'u', IXML_FIELD_INFO(SMXmlConfig_t, startup_stable_wait) }, + { tag:"SweepInterval", format:'k', IXML_FIELD_INFO(SMXmlConfig_t, timer), end_func:SmSweepIntervalParserEnd }, + { tag:"IgnoreTraps", format:'u', IXML_FIELD_INFO(SMXmlConfig_t, IgnoreTraps) }, + { tag:"TrapHoldDown", format:'u', IXML_FIELD_INFO(SMXmlConfig_t, trap_hold_down) }, + { tag:"MaxAttempts", format:'u', IXML_FIELD_INFO(SMXmlConfig_t, max_retries) }, + { tag:"RespTimeout", format:'u', IXML_FIELD_INFO(SMXmlConfig_t, rcv_wait_msec) }, + { tag:"MinRespTimeout", format:'u', IXML_FIELD_INFO(SMXmlConfig_t, min_rcv_wait_msec) }, + { tag:"MasterPingInterval", format:'u', IXML_FIELD_INFO(SMXmlConfig_t, master_ping_interval) }, + { tag:"MasterPingMaxFail", format:'u', IXML_FIELD_INFO(SMXmlConfig_t, master_ping_max_fail) }, + { tag:"DbSyncInterval", format:'u', IXML_FIELD_INFO(SMXmlConfig_t, db_sync_interval) }, + { tag:"SweepErrorsThreshold", format:'u', IXML_FIELD_INFO(SMXmlConfig_t, topo_errors_threshold) }, + { tag:"SweepAbandonThreshold", format:'u', IXML_FIELD_INFO(SMXmlConfig_t, topo_abandon_threshold) }, + { tag:"SwitchLifetime_Int", format:'k', IXML_FIELD_INFO(SMXmlConfig_t, switch_lifetime_n2), end_func:IXmlParserEndHoqTimeout_Int }, + { tag:"SwitchLifetime", format:'k', IXML_FIELD_INFO(SMXmlConfig_t, switch_lifetime_n2), end_func:IXmlParserEndHoqTimeout_Str }, + { tag:"HoqLife_Int", format:'k', IXML_FIELD_INFO(SMXmlConfig_t, hoqlife_n2), end_func:IXmlParserEndHoqTimeout_Int }, + { tag:"HoqLife", format:'k', IXML_FIELD_INFO(SMXmlConfig_t, hoqlife_n2), end_func:IXmlParserEndHoqTimeout_Str }, + { tag:"VL15FlowControlDisable", format:'u', IXML_FIELD_INFO(SMXmlConfig_t, vl15FlowControlDisable) }, + { tag:"VL15CreditRate", format:'u', IXML_FIELD_INFO(SMXmlConfig_t, vl15_credit_rate) }, + { tag:"SaRespTime_Int", format:'u', IXML_FIELD_INFO(SMXmlConfig_t, sa_resp_time_n2) }, + { tag:"SaRespTime", format:'k', IXML_FIELD_INFO(SMXmlConfig_t, sa_resp_time_n2), end_func:IXmlParserEndTimeoutMult32_Str }, + { tag:"PacketLifetime_Int", format:'u', IXML_FIELD_INFO(SMXmlConfig_t, sa_packet_lifetime_n2) }, + { tag:"PacketLifetime", format:'k', IXML_FIELD_INFO(SMXmlConfig_t, sa_packet_lifetime_n2), end_func:IXmlParserEndTimeoutMult32_Str }, + { tag:"VLStallCount", format:'u', IXML_FIELD_INFO(SMXmlConfig_t, vlstall) }, + { tag:"McDosThreshold", format:'u', IXML_FIELD_INFO(SMXmlConfig_t, mc_dos_threshold) }, + { tag:"McDosAction", format:'u', IXML_FIELD_INFO(SMXmlConfig_t, mc_dos_action) }, + { tag:"McDosInterval", format:'u', IXML_FIELD_INFO(SMXmlConfig_t, mc_dos_interval) }, + { tag:"TrapThreshold", format:'u', IXML_FIELD_INFO(SMXmlConfig_t, trap_threshold) }, + { tag:"TrapThresholdMinCount", format:'u', IXML_FIELD_INFO(SMXmlConfig_t, trap_threshold_min_count) }, + { tag:"TrapLogSuppressTriggerInterval", format:'u', IXML_FIELD_INFO(SMXmlConfig_t, trap_log_suppress_trigger_interval) }, + { tag:"NodeAppearanceMsgThreshold", format:'u', IXML_FIELD_INFO(SMXmlConfig_t, node_appearance_msg_thresh) }, + { tag:"SpineFirstRouting", format:'u', IXML_FIELD_INFO(SMXmlConfig_t, spine_first_routing) }, + { tag:"ShortestPathBalanced", format:'u', IXML_FIELD_INFO(SMXmlConfig_t, shortestPathBalanced) }, + { tag:"PathSelection", format:'u', IXML_FIELD_INFO(SMXmlConfig_t, path_selection), end_func:SmPathSelectionParserEnd }, + { tag:"QueryValidation", format:'u', IXML_FIELD_INFO(SMXmlConfig_t, queryValidation) }, + { tag:"EnforceVFPathRecord", format:'u', IXML_FIELD_INFO(SMXmlConfig_t, enforceVFPathRecs) }, + { tag:"SmaBatchSize", format:'u', IXML_FIELD_INFO(SMXmlConfig_t, sma_batch_size) }, + { tag:"MaxParallelReqs", format:'u', IXML_FIELD_INFO(SMXmlConfig_t, max_parallel_reqs) }, + { tag:"CheckMftResponses", format:'u', IXML_FIELD_INFO(SMXmlConfig_t, check_mft_responses) }, + { tag:"MonitorStandby", format:'u', IXML_FIELD_INFO(SMXmlConfig_t, monitor_standby_enable) }, + { tag:"Lmc", format:'u', IXML_FIELD_INFO(SMXmlConfig_t, lmc) }, + { tag:"LmcE0", format:'u', IXML_FIELD_INFO(SMXmlConfig_t, lmc_e0) }, + { tag:"SubnetSize", format:'u', IXML_FIELD_INFO(SMXmlConfig_t, subnet_size) }, + { tag:"Debug", format:'u', IXML_FIELD_INFO(SMXmlConfig_t, debug) }, + { tag:"RmppDebug", format:'u', IXML_FIELD_INFO(SMXmlConfig_t, debug_rmpp) }, + { tag:"Priority", format:'u', IXML_FIELD_INFO(SMXmlConfig_t, priority) }, + { tag:"ElevatedPriority", format:'u', IXML_FIELD_INFO(SMXmlConfig_t, elevated_priority) }, + { tag:"LogLevel", format:'u', IXML_FIELD_INFO(SMXmlConfig_t, log_level) }, + { tag:"LogMode", format:'u', IXML_FIELD_INFO(SMXmlConfig_t, syslog_mode) }, + { tag:"SyslogFacility", format:'s', IXML_FIELD_INFO(SMXmlConfig_t, syslog_facility) }, + { tag:"SslSecurityEnabled", format:'u', IXML_FIELD_INFO(SMXmlConfig_t, SslSecurityEnabled) }, + { tag:"SslSecurityEnable", format:'u', IXML_FIELD_INFO(SMXmlConfig_t, SslSecurityEnabled) }, +#ifndef __VXWORKS__ + { tag:"SslSecurityDir", format:'s', IXML_FIELD_INFO(SMXmlConfig_t, SslSecurityDir) }, +#endif + { tag:"SslSecurityFmCertificate", format:'s', IXML_FIELD_INFO(SMXmlConfig_t, SslSecurityFmCertificate) }, + { tag:"SslSecurityFmPrivateKey", format:'s', IXML_FIELD_INFO(SMXmlConfig_t, SslSecurityFmPrivateKey) }, + { tag:"SslSecurityFmCaCertificate", format:'s', IXML_FIELD_INFO(SMXmlConfig_t, SslSecurityFmCaCertificate) }, + { tag:"SslSecurityFmCertChainDepth", format:'u', IXML_FIELD_INFO(SMXmlConfig_t, SslSecurityFmCertChainDepth) }, + { tag:"SslSecurityFmDHParameters", format:'s', IXML_FIELD_INFO(SMXmlConfig_t, SslSecurityFmDHParameters) }, + { tag:"SslSecurityFmCaCRLEnabled", format:'u', IXML_FIELD_INFO(SMXmlConfig_t, SslSecurityFmCaCRLEnabled) }, + { tag:"SslSecurityFmCaCRLEnable", format:'u', IXML_FIELD_INFO(SMXmlConfig_t, SslSecurityFmCaCRLEnabled) }, + { tag:"SslSecurityFmCaCRL", format:'s', IXML_FIELD_INFO(SMXmlConfig_t, SslSecurityFmCaCRL) }, + { tag:"LID", format:'k', IXML_FIELD_INFO(SMXmlConfig_t, lid), end_func:SmUnicastLidXmlParserEnd }, + { tag:"SmPerfDebug", format:'u', IXML_FIELD_INFO(SMXmlConfig_t, sm_debug_perf) }, + { tag:"SaPerfDebug", format:'u', IXML_FIELD_INFO(SMXmlConfig_t, sa_debug_perf) }, + { tag:"SaRmppChecksum", format:'u', IXML_FIELD_INFO(SMXmlConfig_t, sa_rmpp_checksum) }, + { tag:"LoopTestOn", format:'u', IXML_FIELD_INFO(SMXmlConfig_t, loop_test_on) }, + { tag:"LoopTestFastMode", format:'u', IXML_FIELD_INFO(SMXmlConfig_t, loop_test_fast_mode) }, + { tag:"LoopTestPackets", format:'u', IXML_FIELD_INFO(SMXmlConfig_t, loop_test_packets) }, + { tag:"MulticastMask", format:'u', IXML_FIELD_INFO(SMXmlConfig_t, multicast_mask) }, + { tag:"LidStrategy", format:'k', IXML_FIELD_INFO(SMXmlConfig_t, lid_strategy), end_func:LidStrategyXmlParserEnd }, + { tag:"DsapInUse", format:'u', IXML_FIELD_INFO(SMXmlConfig_t, sm_dsap_enabled) }, + { tag:"CS_LogMask", format:'u', IXML_FIELD_INFO(SMXmlConfig_t, log_masks[VIEO_CS_MOD_ID]), end_func:ParamU32XmlParserEnd }, + { tag:"MAI_LogMask", format:'u', IXML_FIELD_INFO(SMXmlConfig_t, log_masks[VIEO_MAI_MOD_ID]), end_func:ParamU32XmlParserEnd }, + { tag:"CAL_LogMask", format:'u', IXML_FIELD_INFO(SMXmlConfig_t, log_masks[VIEO_CAL_MOD_ID]), end_func:ParamU32XmlParserEnd }, + { tag:"DVR_LogMask", format:'u', IXML_FIELD_INFO(SMXmlConfig_t, log_masks[VIEO_DRIVER_MOD_ID]), end_func:ParamU32XmlParserEnd }, + { tag:"IF3_LogMask", format:'u', IXML_FIELD_INFO(SMXmlConfig_t, log_masks[VIEO_IF3_MOD_ID]), end_func:ParamU32XmlParserEnd }, + { tag:"SM_LogMask", format:'u', IXML_FIELD_INFO(SMXmlConfig_t, log_masks[VIEO_SM_MOD_ID]), end_func:ParamU32XmlParserEnd }, + { tag:"SA_LogMask", format:'u', IXML_FIELD_INFO(SMXmlConfig_t, log_masks[VIEO_SA_MOD_ID]), end_func:ParamU32XmlParserEnd }, + { tag:"PM_LogMask", format:'u', IXML_FIELD_INFO(SMXmlConfig_t, log_masks[VIEO_PM_MOD_ID]), end_func:ParamU32XmlParserEnd }, + { tag:"PA_LogMask", format:'u', IXML_FIELD_INFO(SMXmlConfig_t, log_masks[VIEO_PA_MOD_ID]), end_func:ParamU32XmlParserEnd }, + { tag:"BM_LogMask", format:'u', IXML_FIELD_INFO(SMXmlConfig_t, log_masks[VIEO_BM_MOD_ID]), end_func:ParamU32XmlParserEnd }, + { tag:"FE_LogMask", format:'u', IXML_FIELD_INFO(SMXmlConfig_t, log_masks[VIEO_FE_MOD_ID]), end_func:ParamU32XmlParserEnd }, + { tag:"APP_LogMask", format:'u', IXML_FIELD_INFO(SMXmlConfig_t, log_masks[VIEO_APP_MOD_ID]), end_func:ParamU32XmlParserEnd }, + + + { tag:"LogFile", format:'s', IXML_FIELD_INFO(SMXmlConfig_t, log_file) }, + { tag:"NonRespTimeout", format:'u', IXML_FIELD_INFO(SMXmlConfig_t, non_resp_tsec) }, + { tag:"NonRespMaxCount", format:'u', IXML_FIELD_INFO(SMXmlConfig_t, non_resp_max_count) }, + { tag:"DynamicPortAlloc", format:'u', IXML_FIELD_INFO(SMXmlConfig_t, dynamic_port_alloc) }, + { tag:"LoopbackMode", format:'u', IXML_FIELD_INFO(SMXmlConfig_t, loopback_mode) }, + { tag:"ForceRebalance", format:'u', IXML_FIELD_INFO(SMXmlConfig_t, force_rebalance) }, + { tag:"UseCachedNodeData", format:'u', IXML_FIELD_INFO(SMXmlConfig_t, use_cached_node_data) }, + { tag:"DynamicPacketLifetime", format:'k', subfields:SmDPLifetimeFields, start_func:SmDPLifetimeXmlParserStart, end_func:SmDPLifetimeXmlParserEnd }, + { tag:"Multicast", format:'k', subfields:SmMcastFields, start_func:SmMcastXmlParserStart, end_func:SmMcastXmlParserEnd }, + { tag:"RoutingAlgorithm", format:'s', IXML_FIELD_INFO(SMXmlConfig_t, routing_algorithm) }, + { tag:"DebugJm", format:'u', IXML_FIELD_INFO(SMXmlConfig_t, debug_jm) }, + { tag:"HFILinkPolicy", format:'k', subfields:SmLinkPolicyFields, start_func:SmHFILinkPolicyXmlParserStart }, + { tag:"ISLLinkPolicy", format:'k', subfields:SmLinkPolicyFields, start_func:SmISLLinkPolicyXmlParserStart }, + { tag:"LongTermPortQuarantine", format:'k', subfields:SmPortQuarantineFields, start_func:SmPortQuarantineParserStart }, + { tag:"Preemption", format:'k', subfields:SmPreemptionFields, start_func:SmPreemptionXmlParserStart }, + { tag:"CongestionControl", format:'k', subfields:SmCongestionFields, start_func:SmCongestionXmlParserStart }, + { tag:"AdaptiveRouting", format:'k', subfields:SmAdaptiveRoutingFields, start_func:SmAdaptiveRoutingXmlParserStart, end_func:SmAdaptiveRoutingXmlParserEnd }, + { tag:"FatTreeTopology", format:'k', subfields:SmFtreeRoutingFields, start_func:SmFtreeRoutingXmlParserStart, end_func:SmFtreeRoutingXmlParserEnd }, + { tag:"DGShortestPathTopology", format:'k', subfields:SmDGRoutingFields, start_func:SmDGRoutingXmlParserStart, end_func:SmDGRoutingXmlParserEnd }, + { tag:"HypercubeTopology", format:'k', subfields:SmHypercubeRoutingFields, start_func:SmHypercubeRoutingXmlParserStart, end_func:SmHypercubeRoutingXmlParserEnd }, + { tag:"MeshTorusTopology", format:'k', subfields:SmDorRoutingFields, start_func:SmDorRoutingXmlParserStart, end_func:SmDorRoutingXmlParserEnd }, + { tag:"DebugVf", format:'u', IXML_FIELD_INFO(SMXmlConfig_t, sm_debug_vf) }, + { tag:"DebugRouting", format:'u', IXML_FIELD_INFO(SMXmlConfig_t, sm_debug_routing) }, + { tag:"DebugLidAssign", format:'u', IXML_FIELD_INFO(SMXmlConfig_t, sm_debug_lid_assign) }, + { tag:"NoReplyIfBusy", format:'u', IXML_FIELD_INFO(SMXmlConfig_t, NoReplyIfBusy) }, + { tag:"LftMultiblock", format:'u', IXML_FIELD_INFO(SMXmlConfig_t, lft_multi_block) }, + { tag:"UseAggregateMADs", format:'u', IXML_FIELD_INFO(SMXmlConfig_t, use_aggregates) }, + { tag:"OptimizedBufferControl", format:'u', IXML_FIELD_INFO(SMXmlConfig_t, optimized_buffer_control) }, + { tag:"SmaSpoofingCheck", format:'u', IXML_FIELD_INFO(SMXmlConfig_t, sma_spoofing_check) }, + { tag:"MinSharedVLMem", format:'u', IXML_FIELD_INFO(SMXmlConfig_t, minSharedVLMem), end_func:PercentageXmlParserEnd }, + { tag:"DedicatedVLMemMulti", format:'u', IXML_FIELD_INFO(SMXmlConfig_t, dedicatedVLMemMulti), end_func:DedicatedVLMemMultiXmlParserEnd }, + { tag:"WireDepthOverride", format:'d', IXML_FIELD_INFO(SMXmlConfig_t, wireDepthOverride) }, + { tag:"ReplayDepthOverride", format:'d', IXML_FIELD_INFO(SMXmlConfig_t, replayDepthOverride) }, + { tag:"TimerScalingEnable", format:'u', IXML_FIELD_INFO(SMXmlConfig_t, timerScalingEnable) }, + { tag:"SmAppliances", format:'k', subfields:SmAppliancesFields, start_func:SmAppliancesXmlParserStart }, + { tag:"CableInfoPolicy", format:'k', end_func:SmCIPParserEnd, IXML_FIELD_INFO(SMXmlConfig_t, cableInfoPolicy) }, + { tag:"ForceAttributeRewrite", format:'u', IXML_FIELD_INFO(SMXmlConfig_t, forceAttributeRewrite) }, + { tag:"SkipAttributeWrite", format:'u', IXML_FIELD_INFO(SMXmlConfig_t, skipAttributeWrite) }, + { tag:"DefaultPortErrorAction", format:'u', IXML_FIELD_INFO(SMXmlConfig_t, defaultPortErrorAction) }, + { tag:"SwitchCascadeActivateEnable", format:'u', IXML_FIELD_INFO(SMXmlConfig_t, switchCascadeActivateEnable) }, + { tag:"NeighborNormalRetries", format:'u', IXML_FIELD_INFO(SMXmlConfig_t, neighborNormalRetries) }, + { tag:"PreDefinedTopology", format:'k', subfields:SmPreDefTopoFields, start_func:SmPreDefTopoXmlParserStart, end_func:SmPreDefTopoXmlParserEnd }, + { tag:"TerminateAfter", format:'u', IXML_FIELD_INFO(SMXmlConfig_t, terminateAfter) }, + { tag:"PsThreads", format:'u', IXML_FIELD_INFO(SMXmlConfig_t, psThreads) }, + { tag:"DumpCounters", format:'s', IXML_FIELD_INFO(SMXmlConfig_t, dumpCounters) }, + { tag:"PortBounceLogLimit", format:'u', IXML_FIELD_INFO(SMXmlConfig_t, portBounceLogLimit) }, + { tag:"NeighborFWAuthenEnable", format:'u', IXML_FIELD_INFO(SMXmlConfig_t, neighborFWAuthenEnable) }, + { tag:"MinSupportedVLs", format:'u', IXML_FIELD_INFO(SMXmlConfig_t, min_supported_vls), end_func:MinSupportedVLsParserEnd }, + { tag:"MaxFixedVLs", format:'u', IXML_FIELD_INFO(SMXmlConfig_t, max_fixed_vls) }, + { tag:"AllowMixedVLs", format:'u', IXML_FIELD_INFO(SMXmlConfig_t, allow_mixed_vls) }, + { tag:"PKey_8B", format:'h', IXML_FIELD_INFO(SMXmlConfig_t, P_Key_8B), end_func:PKey8BParserEnd}, + { tag:"PKey_10B", format:'h', IXML_FIELD_INFO(SMXmlConfig_t, P_Key_10B), end_func:PKey10BParserEnd}, + { tag:"CumulativeTimeoutLimit", format:'u', IXML_FIELD_INFO(SMXmlConfig_t, cumulative_timeout_limit), end_func:CumulativeTimeoutLimitParserEnd }, + { NULL } +}; + +// "Sm" start tag +static void* SmXmlParserStart(IXmlParserState_t *state, void *parent, const char **attr) +{ + SMXmlConfig_t *smp = getXmlMemory(sizeof(SMXmlConfig_t), "SMXmlConfig_t SmXmlParserStart()"); + + if (xml_parse_debug) + fprintf(stdout, "SmXmlParserStart instance %u common %u\n", (unsigned int)instance, (unsigned int)common); + + if (!smp) { + PRINT_MEMORY_ERROR; + return NULL; + } + + // inherit the values of config items already set + if (!common && configp->fm_instance[instance]) + smCopyConfig(smp, &configp->fm_instance[instance]->sm_config); + else + smCopyConfig(smp, &configp->fm_instance_common->sm_config); + + return smp; // will be passed to SmXmlParserStartEnd as object +} + +// "Sm" end tag +static void SmXmlParserEnd(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + smp = (SMXmlConfig_t*)IXmlParserGetField(field, object); +#ifndef __VXWORKS__ + char facility[256]; +#endif + + if (xml_parse_debug) + fprintf(stdout, "SmXmlParserEnd instance %u common %u\n", (unsigned int)instance, (unsigned int)common); + + if (!valid) { + fprintf(stderr, "Error processing XML Sm tag\n"); + } else { + + if(smp->port_quarantine.enabled && smp->port_quarantine.flapping.high_thresh < + smp->port_quarantine.flapping.low_thresh){ + IXmlParserPrintError(state, "Sm PortQuarantine Flapping high threshold must be greater than or equal to low threshold"); + freeXmlMemory(smp, sizeof(SMXmlConfig_t), "SMXmlConfig_t SmXmlParserEnd()"); + return; + + } + + if (smp->priority != UNDEFINED_XML32 && smp->priority > MAX_PRIORITY) { + IXmlParserPrintError(state, "Sm Priority must be in the range of 0-15"); + freeXmlMemory(smp, sizeof(SMXmlConfig_t), "SMXmlConfig_t SmXmlParserEnd()"); + return; + } + if (smp->elevated_priority != UNDEFINED_XML32 && smp->elevated_priority > MAX_PRIORITY) { + IXmlParserPrintError(state, "Sm ElevatedPriority must be in the range of 0-15"); + freeXmlMemory(smp, sizeof(SMXmlConfig_t), "SMXmlConfig_t SmXmlParserEnd()"); + return; + } + if (smp->vl15_credit_rate != UNDEFINED_XML32 && smp->vl15_credit_rate > MAX_VL15_CREDIT_RATE) { + IXmlParserPrintError(state, "Sm VL15CreditRate must be in the range of 0-21"); + freeXmlMemory(smp, sizeof(SMXmlConfig_t), "SMXmlConfig_t SmXmlParserEnd()"); + return; + } + +#ifndef __VXWORKS__ + if (strlen(smp->syslog_facility) && getFacility(smp->syslog_facility, /* test */ 1) < 0) { + IXmlParserPrintError(state, "Sm SyslogFacility must be set to one of the following - %s", showFacilities(facility, sizeof(facility))); + freeXmlMemory(smp, sizeof(SMXmlConfig_t), "SMXmlConfig_t SmXmlParserEnd()"); + return; + } +#endif + + + // Add check to see that lft_multi_block is not less than the minimum value of 1 + if (smp->lft_multi_block <= 0) { + IXmlParserPrintError(state, "LftMultiblock cannot be less than 1"); + freeXmlMemory(smp, sizeof(SMXmlConfig_t), "SMXmlConfig_t SmXmlParserEnd()"); + return; + } + + } + if (common) { + smCopyConfig(&configp->fm_instance_common->sm_config, smp); + } else if (configp->fm_instance[instance]) { + // save the Sm config for this instance + smCopyConfig(&configp->fm_instance[instance]->sm_config, smp); + } + smFreeConfig(smp); +} + +// "FeTrapNumberParserEnd" end tag +static void FeTrapNumberParserEnd(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + uint16_t *trap_nums = (uint16_t *)parent; + uint16 trap_num; + + // Check if 'All' is supplied + if (strcasecmp(content, "All") == 0) { + trap_num = TRAP_ALL; // TRAP_ALL Will Register for All Traps + // Else check if valid uint16 number + } else if (!IXmlParseUint16(state, content, len, &trap_num)) { + return; + } + + if (feTrapSubInstance >= FE_MAX_TRAP_SUBS && trap_num != TRAP_ALL) { + IXmlParserPrintWarning(state, "Trap Subscriptions Limit Excceded, only %u Subscriptions. Trap %u will be ignored", + FE_MAX_TRAP_SUBS, trap_num); + return; + } + + // Validate Trap Number + switch (trap_num) { + case MAD_SMT_PORT_UP: + case MAD_SMT_PORT_DOWN: + case MAD_SMT_MCAST_GRP_CREATED: + case MAD_SMT_MCAST_GRP_DELETED: + case MAD_SMT_UNPATH: + case MAD_SMT_REPATH: + case MAD_SMT_PORT_CHANGE: + case MAD_SMT_LINK_INTEGRITY: + case MAD_SMT_BUF_OVERRUN: + case MAD_SMT_FLOW_CONTROL: + case MAD_SMT_CAPABILITYMASK_CHANGE: + case MAD_SMT_SYSTEMIMAGEGUID_CHANGE: + case MAD_SMT_BAD_MKEY: + case MAD_SMT_BAD_PKEY: + case MAD_SMT_BAD_QKEY: + case MAD_SMT_BAD_PKEY_ONPORT: + case STL_SMA_TRAP_LINK_WIDTH: + case STL_TRAP_COST_MATRIX_CHANGE: + // Check if 1st value is Not All Trap value; else skip + if (trap_nums[0] != TRAP_ALL) { + // Add Trap number to List and Inc Trap Count + trap_nums[feTrapSubInstance] = trap_num; + feTrapSubInstance++; + } + break; + case TRAP_ALL: + // If All Traps value, Wipe Traps and only have All Traps value in first slot + feTrapSubInstance = 1; + trap_nums[0] = TRAP_ALL; + break; + default: + IXmlParserPrintError(state, "Trap %u is not valid/supported", trap_num); + } + return; +} +static IXML_FIELD FeTrapSubsFields[] = { + { tag:"TrapNumber", format:'k', end_func:FeTrapNumberParserEnd }, + { NULL } +}; +// "FeTrapSubs" start tag +static void* FeTrapSubsXmlParserStart(IXmlParserState_t *state, void *parent, const char **attr) +{ + FEXmlConfig_t *fep = (FEXmlConfig_t *)parent; + uint16_t *trap_nums = (uint16_t *)getXmlMemory(FE_MAX_TRAP_SUBS * sizeof(uint16_t), "trap_nums FeTrapSubsXmlParserStart()"); + + if (!trap_nums) { + PRINT_MEMORY_ERROR; + return NULL; + } + + memset(trap_nums, 0, FE_MAX_TRAP_SUBS * sizeof(uint16_t)); + + fep->trap_count = feTrapSubInstance = 0; + + return trap_nums; +} +// "FeTrapSubs" end tag +static void FeTrapSubsXmlParserEnd(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + FEXmlConfig_t *fep = (FEXmlConfig_t *)parent; + uint16_t *trap_nums = (uint16_t *)object; + + if (valid) { + int i = 0; + for (; i < feTrapSubInstance; i++) { + fep->trap_nums[i] = trap_nums[i]; + } + for (; i < FE_MAX_TRAP_SUBS; i++) { + fep->trap_nums[i] = 0; + } + fep->trap_count = feTrapSubInstance; + } + + freeXmlMemory(trap_nums, FE_MAX_TRAP_SUBS * sizeof(uint16_t), "trap_nums FeTrapSubsXmlParserEnd()"); + + return; +} +// fields within "Fe" tag +static IXML_FIELD FeFields[] = { + { tag:"Start", format:'u', IXML_FIELD_INFO(FEXmlConfig_t, start) }, + { tag:"TcpPort", format:'u', IXML_FIELD_INFO(FEXmlConfig_t, listen) }, + // Unsupported in 4.4 - PR 109767 + // { tag:"Login", format:'u', IXML_FIELD_INFO(FEXmlConfig_t, login) }, + { tag:"SubnetSize", format:'u', IXML_FIELD_INFO(FEXmlConfig_t, subnet_size) }, + { tag:"StartupRetries", format:'u', IXML_FIELD_INFO(FEXmlConfig_t, startup_retries) }, + { tag:"StartupStableWait", format:'u', IXML_FIELD_INFO(FEXmlConfig_t, startup_stable_wait) }, + { tag:"CoreDumpDir", format:'s', IXML_FIELD_INFO(FEXmlConfig_t, CoreDumpDir) }, + { tag:"CoreDumpLimit", format:'s', IXML_FIELD_INFO(FEXmlConfig_t, CoreDumpLimit) }, + { tag:"Debug", format:'u', IXML_FIELD_INFO(FEXmlConfig_t, debug) }, + { tag:"RmppDebug", format:'u', IXML_FIELD_INFO(FEXmlConfig_t, debug_rmpp) }, + { tag:"LogLevel", format:'u', IXML_FIELD_INFO(FEXmlConfig_t, log_level) }, + { tag:"LogMode", format:'u', IXML_FIELD_INFO(FEXmlConfig_t, syslog_mode) }, + { tag:"SyslogFacility", format:'s', IXML_FIELD_INFO(FEXmlConfig_t, syslog_facility) }, + { tag:"TrapSubscriptions", format:'k', subfields:FeTrapSubsFields, start_func:FeTrapSubsXmlParserStart, end_func:FeTrapSubsXmlParserEnd }, + { tag:"SslSecurityEnabled", format:'u', IXML_FIELD_INFO(FEXmlConfig_t, SslSecurityEnabled) }, + { tag:"SslSecurityEnable", format:'u', IXML_FIELD_INFO(FEXmlConfig_t, SslSecurityEnabled) }, +#ifndef __VXWORKS__ + { tag:"SslSecurityDir", format:'s', IXML_FIELD_INFO(FEXmlConfig_t, SslSecurityDir) }, +#endif + { tag:"SslSecurityFmCertificate", format:'s', IXML_FIELD_INFO(FEXmlConfig_t, SslSecurityFmCertificate) }, + { tag:"SslSecurityFmPrivateKey", format:'s', IXML_FIELD_INFO(FEXmlConfig_t, SslSecurityFmPrivateKey) }, + { tag:"SslSecurityFmCertChainDepth", format:'u', IXML_FIELD_INFO(FEXmlConfig_t, SslSecurityFmCertChainDepth) }, + { tag:"SslSecurityFmDHParameters", format:'s', IXML_FIELD_INFO(FEXmlConfig_t, SslSecurityFmDHParameters) }, + { tag:"SslSecurityFmCaCRLEnabled", format:'u', IXML_FIELD_INFO(FEXmlConfig_t, SslSecurityFmCaCRLEnabled) }, + { tag:"SslSecurityFmCaCRLEnable", format:'u', IXML_FIELD_INFO(FEXmlConfig_t, SslSecurityFmCaCRLEnabled) }, + { tag:"SslSecurityFmCaCRL", format:'s', IXML_FIELD_INFO(FEXmlConfig_t, SslSecurityFmCaCRL) }, + { tag:"CS_LogMask", format:'u', IXML_FIELD_INFO(FEXmlConfig_t, log_masks[VIEO_CS_MOD_ID]), end_func:ParamU32XmlParserEnd }, + { tag:"MAI_LogMask", format:'u', IXML_FIELD_INFO(FEXmlConfig_t, log_masks[VIEO_MAI_MOD_ID]), end_func:ParamU32XmlParserEnd }, + { tag:"CAL_LogMask", format:'u', IXML_FIELD_INFO(FEXmlConfig_t, log_masks[VIEO_CAL_MOD_ID]), end_func:ParamU32XmlParserEnd }, + { tag:"DVR_LogMask", format:'u', IXML_FIELD_INFO(FEXmlConfig_t, log_masks[VIEO_DRIVER_MOD_ID]), end_func:ParamU32XmlParserEnd }, + { tag:"IF3_LogMask", format:'u', IXML_FIELD_INFO(FEXmlConfig_t, log_masks[VIEO_IF3_MOD_ID]), end_func:ParamU32XmlParserEnd }, + { tag:"SM_LogMask", format:'u', IXML_FIELD_INFO(FEXmlConfig_t, log_masks[VIEO_SM_MOD_ID]), end_func:ParamU32XmlParserEnd }, + { tag:"SA_LogMask", format:'u', IXML_FIELD_INFO(FEXmlConfig_t, log_masks[VIEO_SA_MOD_ID]), end_func:ParamU32XmlParserEnd }, + { tag:"PM_LogMask", format:'u', IXML_FIELD_INFO(FEXmlConfig_t, log_masks[VIEO_PM_MOD_ID]), end_func:ParamU32XmlParserEnd }, + { tag:"PA_LogMask", format:'u', IXML_FIELD_INFO(FEXmlConfig_t, log_masks[VIEO_PA_MOD_ID]), end_func:ParamU32XmlParserEnd }, + { tag:"BM_LogMask", format:'u', IXML_FIELD_INFO(FEXmlConfig_t, log_masks[VIEO_BM_MOD_ID]), end_func:ParamU32XmlParserEnd }, + { tag:"FE_LogMask", format:'u', IXML_FIELD_INFO(FEXmlConfig_t, log_masks[VIEO_FE_MOD_ID]), end_func:ParamU32XmlParserEnd }, + { tag:"APP_LogMask", format:'u', IXML_FIELD_INFO(FEXmlConfig_t, log_masks[VIEO_APP_MOD_ID]), end_func:ParamU32XmlParserEnd }, + + + { tag:"LogFile", format:'s', IXML_FIELD_INFO(FEXmlConfig_t, log_file) }, + { tag:"Window", format:'u', IXML_FIELD_INFO(FEXmlConfig_t, window) }, + { tag:"ManagerCheckRate", format:'u', IXML_FIELD_INFO(FEXmlConfig_t, manager_check_rate) }, + { NULL } +}; + +// "Fe" start tag +static void* FeXmlParserStart(IXmlParserState_t *state, void *parent, const char **attr) +{ + FEXmlConfig_t *fep = getXmlMemory(sizeof(FEXmlConfig_t), "FEXmlConfig_t FeXmlParserStart()"); + + if (xml_parse_debug) + fprintf(stdout, "FeXmlParserStart instance %u common %u\n", (unsigned int)instance, (unsigned int)common); + + if (!fep) { + PRINT_MEMORY_ERROR; + return NULL; + } + + // inherit the values of config items already set + if (!common && configp->fm_instance[instance]) + *fep = configp->fm_instance[instance]->fe_config; + else + *fep = configp->fm_instance_common->fe_config; + + return fep; // will be passed to FeXmlParserStartEnd as object +} + +// "Fe" end tag +static void FeXmlParserEnd(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + FEXmlConfig_t *fep = (FEXmlConfig_t*)IXmlParserGetField(field, object); +#ifndef __VXWORKS__ + char facility[256]; +#endif + + if (xml_parse_debug) + fprintf(stdout, "FeXmlParserEnd instance %u common %u\n", (unsigned int)instance, (unsigned int)common); + + if (!valid) { + fprintf(stderr, "Error processing XML Fe tag\n"); + } else { + if (strlen(fep->CoreDumpLimit) && vs_getCoreDumpLimit(fep->CoreDumpLimit, NULL) < 0) { + IXmlParserPrintError(state, "Invalid Fe CoreDumpLimit: '%s'", fep->CoreDumpLimit); + freeXmlMemory(fep, sizeof(FEXmlConfig_t), "FEXmlConfig_t FeXmlParserEnd()"); + return; + } +#ifndef __VXWORKS__ + if (strlen(fep->syslog_facility) && getFacility(fep->syslog_facility, /* test */ 1) < 0) { + IXmlParserPrintError(state, "Fe SyslogFacility must be set to one of the following - %s", showFacilities(facility, sizeof(facility))); + freeXmlMemory(fep, sizeof(FEXmlConfig_t), "FEXmlConfig_t FeXmlParserEnd()"); + return; + } +#endif + // If Not Supplied Enable Current Default of Traps 64 & 65 + if (fep->trap_count == UNDEFINED_XML32) { + memset(&fep->trap_nums[0], 0, FE_MAX_TRAP_SUBS * sizeof(uint16_t)); + fep->trap_count = 2; + fep->trap_nums[0] = MAD_SMT_PORT_UP; + fep->trap_nums[1] = MAD_SMT_PORT_DOWN; + } + } + + if (common) { + configp->fm_instance_common->fe_config = *fep; + } else if (configp->fm_instance[instance]) { + // save the Fe config for this instance + configp->fm_instance[instance]->fe_config = *fep; + } + + freeXmlMemory(fep, sizeof(FEXmlConfig_t), "FEXmlConfig_t FeXmlParserEnd()"); +} +static void PmSweepIntervalParserEnd(IXmlParserState_t *state, + const IXML_FIELD *field, void *object, void *parent, XML_Char *content, + unsigned len, boolean valid) +{ + uint16 SweepInterval; + + if (!IXmlParseUint16(state, content, len, &SweepInterval)) { + return; + } + + if (SweepInterval > PM_MAX_SWEEPRATE || SweepInterval < PM_MIN_SWEEPRATE) { + IXmlParserPrintError(state, "Pm SweepInterval (%u) must be in the range of %u-%u seconds", + SweepInterval, PM_MIN_SWEEPRATE, PM_MAX_SWEEPRATE); + return; + } + + *(uint16 *)IXmlParserGetField(field, object) = SweepInterval; +} + +static void PmSweepErrorInfoThresholdsParserEnd(IXmlParserState_t *state, + const IXML_FIELD *field, void *object, void *parent, XML_Char *content, + unsigned len, boolean valid) +{ + uint32 threshold = 0; + if (!strcasecmp(content, "Unlimited")) { + threshold = UNDEFINED_XML32; + } else if (!IXmlParseUint32(state, content, len, &threshold)) { + return; + } + + *(uint32 *)IXmlParserGetField(field, object) = threshold; +} + + +static void* PmSweepErrorInfoThresholdsXmlParserStart(IXmlParserState_t *state, void *parent, const char **attr) +{ + return &((PMXmlConfig_t *)parent)->errorinfo_thresholds; +} + +// SweepErrorInfoLogThresholds +static IXML_FIELD PmSweepErrorInfoThresholds[] = { + { tag:"Integrity", format:'u', IXML_FIELD_INFO(PmSweepErrorInfoThresholds_t, Integrity), end_func:PmSweepErrorInfoThresholdsParserEnd }, + { tag:"Security", format:'u', IXML_FIELD_INFO(PmSweepErrorInfoThresholds_t, Security), end_func:PmSweepErrorInfoThresholdsParserEnd }, + { tag:"Routing", format:'u', IXML_FIELD_INFO(PmSweepErrorInfoThresholds_t, Routing), end_func:PmSweepErrorInfoThresholdsParserEnd }, + { NULL } +}; + + +// fields within "Pm/Thresholds" tag +static IXML_FIELD PmThresholdsFields[] = { + { tag:"Integrity", format:'u', IXML_FIELD_INFO(PmThresholdsXmlConfig_t, Integrity) }, + { tag:"Congestion", format:'u', IXML_FIELD_INFO(PmThresholdsXmlConfig_t, Congestion) }, + { tag:"SmaCongestion", format:'u', IXML_FIELD_INFO(PmThresholdsXmlConfig_t, SmaCongestion) }, + { tag:"Bubble", format:'u', IXML_FIELD_INFO(PmThresholdsXmlConfig_t, Bubble) }, + { tag:"Security", format:'u', IXML_FIELD_INFO(PmThresholdsXmlConfig_t, Security) }, + { tag:"Routing", format:'u', IXML_FIELD_INFO(PmThresholdsXmlConfig_t, Routing) }, + { NULL } +}; + +// "Pm/Thresholds" start tag +static void* PmThresholdsXmlParserStart(IXmlParserState_t *state, void *parent, const char **attr) +{ + return &((PMXmlConfig_t *)parent)->thresholds; +} + +// fields within "Pm/ThresholdsExceededMsgLimit" tag +static IXML_FIELD PmThresholdsExceededMsgLimitFields[] = { + { tag:"Integrity", format:'u', IXML_FIELD_INFO(PmThresholdsExceededMsgLimitXmlConfig_t, Integrity) }, + { tag:"Congestion", format:'u', IXML_FIELD_INFO(PmThresholdsExceededMsgLimitXmlConfig_t, Congestion) }, + { tag:"SmaCongestion", format:'u', IXML_FIELD_INFO(PmThresholdsExceededMsgLimitXmlConfig_t, SmaCongestion) }, + { tag:"Bubble", format:'u', IXML_FIELD_INFO(PmThresholdsExceededMsgLimitXmlConfig_t, Bubble) }, + { tag:"Security", format:'u', IXML_FIELD_INFO(PmThresholdsExceededMsgLimitXmlConfig_t, Security) }, + { tag:"Routing", format:'u', IXML_FIELD_INFO(PmThresholdsExceededMsgLimitXmlConfig_t, Routing) }, + { NULL } +}; + +// "Pm/ThresholdsExceededMsgLimit" start tag +static void* PmThresholdsExceededMsgLimitXmlParserStart(IXmlParserState_t *state, void *parent, const char **attr) +{ + return &((PMXmlConfig_t *)parent)->thresholdsExceededMsgLimit; +} + +// fields within "Pm/IntegrityWeights" tag +static IXML_FIELD PmIntegrityWeightsFields[] = { + { tag:"LocalLinkIntegrityErrors", format:'u', IXML_FIELD_INFO(PmIntegrityWeightsXmlConfig_t, LocalLinkIntegrityErrors) }, + { tag:"RcvErrors", format:'u', IXML_FIELD_INFO(PmIntegrityWeightsXmlConfig_t, PortRcvErrors) }, + { tag:"ExcessiveBufferOverruns", format:'u', IXML_FIELD_INFO(PmIntegrityWeightsXmlConfig_t, ExcessiveBufferOverruns) }, + { tag:"LinkErrorRecovery", format:'u', IXML_FIELD_INFO(PmIntegrityWeightsXmlConfig_t, LinkErrorRecovery) }, + { tag:"LinkDowned", format:'u', IXML_FIELD_INFO(PmIntegrityWeightsXmlConfig_t, LinkDowned) }, + { tag:"UncorrectableErrors", format:'u', IXML_FIELD_INFO(PmIntegrityWeightsXmlConfig_t, UncorrectableErrors) }, + { tag:"FMConfigErrors", format:'u', IXML_FIELD_INFO(PmIntegrityWeightsXmlConfig_t, FMConfigErrors) }, + { tag:"LinkQualityIndicator", format:'u', IXML_FIELD_INFO(PmIntegrityWeightsXmlConfig_t, LinkQualityIndicator) }, + { tag:"LinkWidthDowngrade", format:'u', IXML_FIELD_INFO(PmIntegrityWeightsXmlConfig_t, LinkWidthDowngrade) }, + { NULL } +}; + +// "Pm/IntegrityWeights" start tag +static void* PmIntegrityWeightsXmlParserStart(IXmlParserState_t *state, void *parent, const char **attr) +{ + return &((PMXmlConfig_t *)parent)->integrityWeights; +} + +// fields within "Pm/CongestionWeights" tag +static IXML_FIELD PmCongestionWeightsFields[] = { + { tag:"XmitWaitPct", format:'u', IXML_FIELD_INFO(PmCongestionWeightsXmlConfig_t, PortXmitWait) }, + { tag:"CongDiscards", format:'u', IXML_FIELD_INFO(PmCongestionWeightsXmlConfig_t, SwPortCongestion) }, + { tag:"RcvFECNPct", format:'u', IXML_FIELD_INFO(PmCongestionWeightsXmlConfig_t, PortRcvFECN) }, + { tag:"RcvBECNPct", format:'u', IXML_FIELD_INFO(PmCongestionWeightsXmlConfig_t, PortRcvBECN) }, + { tag:"XmitTimeCongPct", format:'u', IXML_FIELD_INFO(PmCongestionWeightsXmlConfig_t, PortXmitTimeCong) }, + { tag:"MarkFECNPct", format:'u', IXML_FIELD_INFO(PmCongestionWeightsXmlConfig_t, PortMarkFECN) }, + { NULL } +}; + +// "Pm/CongestionWeights" start tag +static void* PmCongestionWeightsXmlParserStart(IXmlParserState_t *state, void *parent, const char **attr) +{ + return &((PMXmlConfig_t *)parent)->congestionWeights; +} + +// fields within the "Pm/Resolution" tag +static IXML_FIELD PmResolutionFields[] = { + { tag:"LocalLinkIntegrity", format:'u', IXML_FIELD_INFO(PmResolutionXmlConfig_t, LocalLinkIntegrity) }, + { tag:"LinkErrorRecovery", format:'u', IXML_FIELD_INFO(PmResolutionXmlConfig_t, LinkErrorRecovery) }, + { NULL } +}; + +static void* PmResolutionXmlParserStart(IXmlParserState_t *state, void *parent, const char **attr) +{ + return &((PMXmlConfig_t *)parent)->resolution; +} + +// fields withing "Pm/ShortTermHistory" tag +static IXML_FIELD PmShortTermHistoryFields[] = { + { tag:"Enable", format:'u', IXML_FIELD_INFO(PmShortTermHistoryXmlConfig_t, enable) }, + { tag:"StorageLocation", format:'s', IXML_FIELD_INFO(PmShortTermHistoryXmlConfig_t, StorageLocation) }, + { tag:"TotalHistory", format:'u', IXML_FIELD_INFO(PmShortTermHistoryXmlConfig_t, totalHistory) }, + { tag:"ImagesPerComposite", format:'u', IXML_FIELD_INFO(PmShortTermHistoryXmlConfig_t, imagesPerComposite) }, + { tag:"MaxDiskSpace", format:'u', IXML_FIELD_INFO(PmShortTermHistoryXmlConfig_t, maxDiskSpace) }, + { tag:"CompressionDivisions", format:'u', IXML_FIELD_INFO(PmShortTermHistoryXmlConfig_t, compressionDivisions) }, + { NULL } +}; + +// "Pm/ShortTermHistory" start tag +static void* PmShortTermHistoryXmlParserStart(IXmlParserState_t *state, void *parent, const char **attr) +{ + return &((PMXmlConfig_t *)parent)->shortTermHistory; +} + +// "Pm/ShortTermHistory" end tag +static void PmShortTermHistoryXmlParserEnd(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + PmShortTermHistoryXmlConfig_t *p = (PmShortTermHistoryXmlConfig_t*)IXmlParserGetField(field, object); + + if (!valid) { + fprintf(stderr, "Error processing XML Short Term History tag\n"); + } else { + if (embedded_call && p && p->enable) { + // Parsing an ESM configuration file, Short Term History feature + // not supported + p->enable = 0; + // print message to standard output + IXmlParserPrintWarning(state, "Short Term History has been disabled, not supported for ESM"); +#ifdef __VXWORKS__ + // log the message + IB_LOG_WARN0("Short Term History has been disabled, not supported for ESM"); +#endif + } + } +} + +// fields within "Pm" tag +static IXML_FIELD PmFields[] = { + { tag:"Start", format:'u', IXML_FIELD_INFO(PMXmlConfig_t, start) }, + { tag:"SubnetSize", format:'u', IXML_FIELD_INFO(PMXmlConfig_t, subnet_size) }, + { tag:"SslSecurityEnabled", format:'u', IXML_FIELD_INFO(PMXmlConfig_t, SslSecurityEnabled) }, + { tag:"SslSecurityEnable", format:'u', IXML_FIELD_INFO(PMXmlConfig_t, SslSecurityEnabled) }, +#ifndef __VXWORKS__ + { tag:"SslSecurityDir", format:'s', IXML_FIELD_INFO(PMXmlConfig_t, SslSecurityDir) }, +#endif + { tag:"SslSecurityFmCertificate", format:'s', IXML_FIELD_INFO(PMXmlConfig_t, SslSecurityFmCertificate) }, + { tag:"SslSecurityFmPrivateKey", format:'s', IXML_FIELD_INFO(PMXmlConfig_t, SslSecurityFmPrivateKey) }, + { tag:"SslSecurityFmCaCertificate", format:'s', IXML_FIELD_INFO(PMXmlConfig_t, SslSecurityFmCaCertificate) }, + { tag:"SslSecurityFmCertChainDepth", format:'u', IXML_FIELD_INFO(PMXmlConfig_t, SslSecurityFmCertChainDepth) }, + { tag:"SslSecurityFmDHParameters", format:'s', IXML_FIELD_INFO(PMXmlConfig_t, SslSecurityFmDHParameters) }, + { tag:"SslSecurityFmCaCRLEnabled", format:'u', IXML_FIELD_INFO(PMXmlConfig_t, SslSecurityFmCaCRLEnabled) }, + { tag:"SslSecurityFmCaCRLEnable", format:'u', IXML_FIELD_INFO(PMXmlConfig_t, SslSecurityFmCaCRLEnabled) }, + { tag:"SslSecurityFmCaCRL", format:'s', IXML_FIELD_INFO(PMXmlConfig_t, SslSecurityFmCaCRL) }, + { tag:"ServiceLease", format:'u', IXML_FIELD_INFO(PMXmlConfig_t, timer) }, + { tag:"SweepInterval", format:'u', IXML_FIELD_INFO(PMXmlConfig_t, sweep_interval), end_func:PmSweepIntervalParserEnd }, + { tag:"ErrorClear", format:'u', IXML_FIELD_INFO(PMXmlConfig_t, ErrorClear) }, + { tag:"ClearDataXfer", format:'u', IXML_FIELD_INFO(PMXmlConfig_t, ClearDataXfer) }, + { tag:"Clear64bit", format:'u', IXML_FIELD_INFO(PMXmlConfig_t, Clear64bit) }, + { tag:"Clear32bit", format:'u', IXML_FIELD_INFO(PMXmlConfig_t, Clear32bit) }, + { tag:"Clear8bit", format:'u', IXML_FIELD_INFO(PMXmlConfig_t, Clear8bit) }, + { tag:"ProcessVLCounters", format:'u', IXML_FIELD_INFO(PMXmlConfig_t, process_vl_counters) }, + { tag:"ProcessHFICounters", format:'u', IXML_FIELD_INFO(PMXmlConfig_t, process_hfi_counters) }, + { tag:"ProcessErrorInfo", format:'u', IXML_FIELD_INFO(PMXmlConfig_t, process_errorinfo) }, + { tag:"MaxAttempts", format:'u', IXML_FIELD_INFO(PMXmlConfig_t, MaxRetries) }, + { tag:"RespTimeout", format:'u', IXML_FIELD_INFO(PMXmlConfig_t, RcvWaitInterval) }, + { tag:"MinRespTimeout", format:'u', IXML_FIELD_INFO(PMXmlConfig_t, MinRcvWaitInterval) }, + { tag:"SweepErrorsLogThreshold", format:'u', IXML_FIELD_INFO(PMXmlConfig_t, SweepErrorsLogThreshold) }, + { tag:"MaxParallelNodes", format:'u', IXML_FIELD_INFO(PMXmlConfig_t, MaxParallelNodes) }, + { tag:"PmaBatchSize", format:'u', IXML_FIELD_INFO(PMXmlConfig_t, PmaBatchSize) }, + { tag:"FreezeFrameLease", format:'u', IXML_FIELD_INFO(PMXmlConfig_t, freeze_frame_lease) }, + { tag:"TotalImages", format:'u', IXML_FIELD_INFO(PMXmlConfig_t, total_images) }, + { tag:"FreezeFrameImages", format:'u', IXML_FIELD_INFO(PMXmlConfig_t, freeze_frame_images) }, + { tag:"MaxClients", format:'u', IXML_FIELD_INFO(PMXmlConfig_t, max_clients) }, + { tag:"ImageUpdateInterval", format:'u', IXML_FIELD_INFO(PMXmlConfig_t, image_update_interval) }, + { tag:"Thresholds", format:'k', subfields:PmThresholdsFields, start_func:PmThresholdsXmlParserStart }, + { tag:"ThresholdsExceededMsgLimit", format:'k', subfields:PmThresholdsExceededMsgLimitFields, start_func:PmThresholdsExceededMsgLimitXmlParserStart }, + { tag:"IntegrityWeights", format:'k', subfields:PmIntegrityWeightsFields, start_func:PmIntegrityWeightsXmlParserStart }, + { tag:"CongestionWeights", format:'k', subfields:PmCongestionWeightsFields, start_func:PmCongestionWeightsXmlParserStart }, + { tag:"Resolution", format:'k', subfields:PmResolutionFields, start_func:PmResolutionXmlParserStart }, + { tag:"SweepErrorInfoLogThresholds", format:'k', subfields:PmSweepErrorInfoThresholds, start_func:PmSweepErrorInfoThresholdsXmlParserStart }, + { tag:"Debug", format:'u', IXML_FIELD_INFO(PMXmlConfig_t, debug) }, + { tag:"RmppDebug", format:'u', IXML_FIELD_INFO(PMXmlConfig_t, debug_rmpp) }, + { tag:"PmPerfDebug", format:'u', IXML_FIELD_INFO(PMXmlConfig_t, pm_debug_perf) }, + { tag:"Priority", format:'u', IXML_FIELD_INFO(PMXmlConfig_t, priority) }, + { tag:"ElevatedPriority", format:'u', IXML_FIELD_INFO(PMXmlConfig_t, elevated_priority) }, + { tag:"LogLevel", format:'u', IXML_FIELD_INFO(PMXmlConfig_t, log_level) }, + { tag:"LogMode", format:'u', IXML_FIELD_INFO(PMXmlConfig_t, syslog_mode) }, + { tag:"SyslogFacility", format:'s', IXML_FIELD_INFO(PMXmlConfig_t, syslog_facility) }, + { tag:"CS_LogMask", format:'u', IXML_FIELD_INFO(PMXmlConfig_t, log_masks[VIEO_CS_MOD_ID]), end_func:ParamU32XmlParserEnd }, + { tag:"MAI_LogMask", format:'u', IXML_FIELD_INFO(PMXmlConfig_t, log_masks[VIEO_MAI_MOD_ID]), end_func:ParamU32XmlParserEnd }, + { tag:"CAL_LogMask", format:'u', IXML_FIELD_INFO(PMXmlConfig_t, log_masks[VIEO_CAL_MOD_ID]), end_func:ParamU32XmlParserEnd }, + { tag:"DVR_LogMask", format:'u', IXML_FIELD_INFO(PMXmlConfig_t, log_masks[VIEO_DRIVER_MOD_ID]), end_func:ParamU32XmlParserEnd }, + { tag:"IF3_LogMask", format:'u', IXML_FIELD_INFO(PMXmlConfig_t, log_masks[VIEO_IF3_MOD_ID]), end_func:ParamU32XmlParserEnd }, + { tag:"SM_LogMask", format:'u', IXML_FIELD_INFO(PMXmlConfig_t, log_masks[VIEO_SM_MOD_ID]), end_func:ParamU32XmlParserEnd }, + { tag:"SA_LogMask", format:'u', IXML_FIELD_INFO(PMXmlConfig_t, log_masks[VIEO_SA_MOD_ID]), end_func:ParamU32XmlParserEnd }, + { tag:"PM_LogMask", format:'u', IXML_FIELD_INFO(PMXmlConfig_t, log_masks[VIEO_PM_MOD_ID]), end_func:ParamU32XmlParserEnd }, + { tag:"PA_LogMask", format:'u', IXML_FIELD_INFO(PMXmlConfig_t, log_masks[VIEO_PA_MOD_ID]), end_func:ParamU32XmlParserEnd }, + { tag:"BM_LogMask", format:'u', IXML_FIELD_INFO(PMXmlConfig_t, log_masks[VIEO_BM_MOD_ID]), end_func:ParamU32XmlParserEnd }, + { tag:"FE_LogMask", format:'u', IXML_FIELD_INFO(PMXmlConfig_t, log_masks[VIEO_FE_MOD_ID]), end_func:ParamU32XmlParserEnd }, + { tag:"APP_LogMask", format:'u', IXML_FIELD_INFO(PMXmlConfig_t, log_masks[VIEO_APP_MOD_ID]), end_func:ParamU32XmlParserEnd }, + + + { tag:"LogFile", format:'s', IXML_FIELD_INFO(PMXmlConfig_t, log_file) }, + { tag:"ShortTermHistory", format:'k', subfields:PmShortTermHistoryFields, start_func:PmShortTermHistoryXmlParserStart, end_func:PmShortTermHistoryXmlParserEnd }, + { NULL } +}; + +// "Pm" start tag +static void* PmXmlParserStart(IXmlParserState_t *state, void *parent, const char **attr) +{ + PMXmlConfig_t *pmp = getXmlMemory(sizeof(PMXmlConfig_t), "PMXmlConfig_t PmXmlParserStart()"); + + if (xml_parse_debug) + fprintf(stdout, "PmXmlParserStart instance %u common %u\n", (unsigned int)instance, (unsigned int)common); + + if (!pmp) { + PRINT_MEMORY_ERROR; + return NULL; + } + + // inherit the values of config items already set + if (!common && configp->fm_instance[instance]) + *pmp = configp->fm_instance[instance]->pm_config; + else + *pmp = configp->fm_instance_common->pm_config; + + return pmp; // will be passed to PmXmlParserStartEnd as object +} + +// "Pm" end tag +static void PmXmlParserEnd(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + PMXmlConfig_t *pmp = (PMXmlConfig_t*)IXmlParserGetField(field, object); +#ifndef __VXWORKS__ + char facility[256]; +#endif + + if (xml_parse_debug) + fprintf(stdout, "PmXmlParserEnd instance %u common %u\n", (unsigned int)instance, (unsigned int)common); + + if (!valid) { + fprintf(stderr, "Error processing XML Pm tag\n"); + } else { + if (pmp->priority != UNDEFINED_XML32 && pmp->priority > MAX_PRIORITY) { + IXmlParserPrintError(state, "Pm Priority must be in the range of 0-15"); + freeXmlMemory(pmp, sizeof(PMXmlConfig_t), "PMXmlConfig_t PmXmlParserEnd()"); + return; + } + if (pmp->elevated_priority != UNDEFINED_XML32 && pmp->elevated_priority > MAX_PRIORITY) { + IXmlParserPrintError(state, "Pm ElevatedPriority must be in the range of 0-15"); + freeXmlMemory(pmp, sizeof(PMXmlConfig_t), "PMXmlConfig_t PmXmlParserEnd()"); + return; + } +#ifndef __VXWORKS__ + if (strlen(pmp->syslog_facility) && getFacility(pmp->syslog_facility, /* test */ 1) < 0) { + IXmlParserPrintError(state, "Pm SyslogFacility must be set to one of the following - %s", showFacilities(facility, sizeof(facility))); + freeXmlMemory(pmp, sizeof(PMXmlConfig_t), "PMXmlConfig_t PmXmlParserEnd()"); + return; + } +#endif + } + + if (common) { + configp->fm_instance_common->pm_config = *pmp; + } else if (configp->fm_instance[instance]) { + // save the Pm config for this instance + configp->fm_instance[instance]->pm_config = *pmp; + } + + freeXmlMemory(pmp, sizeof(PMXmlConfig_t), "PMXmlConfig_t PmXmlParserEnd()"); +} + + + +#define SID_PARSE_SUCCESS 0 +#define SID_PARSE_FAIL 1 +#define SID_PARSE_DUP 2 + +static int ServiceIdEnd(IXmlParserState_t *state, cl_qmap_t *dst, + XML_Char *content, unsigned len, boolean valid, boolean asString) +{ + uint64_t sid; + + if (!valid) { + fprintf(stderr, "Error processing XML ServiceId tag\n"); + return SID_PARSE_FAIL; + } else if (!content) { + IXmlParserPrintError(state, "ServiceId cannot be null"); + return SID_PARSE_FAIL; + } else if (strlen(content) > MAX_VFABRIC_NAME - 1) { + IXmlParserPrintError(state, "ServiceId is too long"); + return SID_PARSE_FAIL; + } + + if (FSUCCESS != StringToUint64(&sid, content, NULL, 16, TRUE)) { + IXmlParserPrintError(state, "ServiceId %s is formatted incorrectly", content); + return SID_PARSE_FAIL; + } + + if (dst) { + if (asString) { + char *sidStr = dupName(content); + if (!sidStr) { + PRINT_MEMORY_ERROR; + return SID_PARSE_FAIL; + } + + if (!addMap(dst, XML_QMAP_U64_CAST sidStr)) { + freeName(sidStr); + return SID_PARSE_DUP; + } + } else if (!addMap(dst, sid)) { + return SID_PARSE_DUP; + } + } + + return SID_PARSE_SUCCESS; +} + +// "ServiceIdRange" end tag +static int ServiceIdRangeEnd(IXmlParserState_t *state, cl_qmap_t *dst, + XML_Char *content, unsigned len, boolean valid) +{ + if (!valid) { + fprintf(stderr, "Error processing XML ServiceIdRange tag\n"); + } else if (!content || strlen(content) > MAX_VFABRIC_NAME - 1) { + IXmlParserPrintError(state, "ServiceIdRange is too long"); + return SID_PARSE_FAIL; + } + + // test conversion + VFAppSid_t sidMapping; + if (verifyAndConvertSidCompoundString(content, 1, &sidMapping) < 0) { + IXmlParserPrintError(state, "Bad ServiceIdRange format, \"%s\"", content); + return SID_PARSE_FAIL; + } + + if (dst) { + char *range = dupName(content); + if (!range) { + PRINT_MEMORY_ERROR; + return SID_PARSE_FAIL; + } + + if (!addMap(dst, XML_QMAP_U64_CAST range)) { + freeName(range); + return SID_PARSE_DUP; + } + } + + return SID_PARSE_SUCCESS; +} + +// "ServiceIdMasked" end tag +static int ServiceIdMaskedEnd(IXmlParserState_t *state, cl_qmap_t *dst, + XML_Char *content, unsigned len, boolean valid) +{ + if (!valid) { + fprintf(stderr, "Error processing XML ServiceIdMasked tag\n"); + } else if (!content || strlen(content) > MAX_VFABRIC_NAME - 1) { + IXmlParserPrintError(state, "ServiceIdMasked is too long"); + return SID_PARSE_FAIL; + } + + // test conversion + VFAppSid_t sidMapping; + if (verifyAndConvertSidCompoundString(content, 0, &sidMapping) < 0) { + IXmlParserPrintError(state, "Bad ServiceIdMasked format, \"%s\"", content); + return SID_PARSE_FAIL; + } + + if (dst) { + char *masked; + masked = dupName(content); + if (!masked) { + PRINT_MEMORY_ERROR; + return SID_PARSE_FAIL; + } + + if (!addMap(dst, XML_QMAP_U64_CAST masked)) { + freeName(masked); + return SID_PARSE_DUP; + } + } + + return SID_PARSE_SUCCESS; +} + +// "ServiceId" end tag +static void VfAppServiceIdEnd(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + if (!app) { + IXmlParserPrintError(state, "Parser internal error"); + return; + } + + if (xml_parse_debug) + fprintf(stdout, "VfAppServiceIdEnd instance %u appInstance %u serviceIdInstance %u common %u\n", + (unsigned int)instance, (unsigned int)appInstance, (unsigned int)serviceIdInstance, (unsigned int)common); + + // check for max + if (serviceIdInstance >= MAX_VFABRIC_APP_SIDS) { + PRINT_MEMORY_ERROR; + return; + } + + if (!ServiceIdEnd(state, &app->serviceIdMap, content, len, valid, 0)) { + app->serviceIdMapSize++; + serviceIdInstance++; + } +} + +// "ServiceIdRange" end tag +static void VfAppServiceIdRangeEnd(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + if (!app) { + IXmlParserPrintError(state, "Parser internal error"); + return; + } + + if (xml_parse_debug) + fprintf(stdout, "VfAppServiceIdRangeEnd instance %u appInstance %u serviceIdRangeInstance %u common %u\n", + (unsigned int)instance, (unsigned int)appInstance, (unsigned int)serviceIdRangeInstance, (unsigned int)common); + + // check for max + if (serviceIdRangeInstance >= MAX_VFABRIC_APP_SIDS) { + IXmlParserPrintError(state, "Too many service IDs ranges in Application definition"); + return; + } + + if (!ServiceIdRangeEnd(state, &app->serviceIdRangeMap, content, len, valid)) { + app->serviceIdRangeMapSize++; + serviceIdRangeInstance++; + } +} + +// "ServiceIdMasked" end tag +static void VfAppServiceIdMaskedEnd(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + if (!app) { + IXmlParserPrintError(state, "Parser internal error"); + return; + } + + if (xml_parse_debug) + fprintf(stdout, "VfAppServiceIdMaskedEnd instance %u appInstance %u " + "serviceIdMaskedInstance %u common %u\n", (unsigned int)instance, + (unsigned int)appInstance, (unsigned int)serviceIdMaskedInstance, + (unsigned int)common); + + // check for max + if (serviceIdMaskedInstance >= MAX_VFABRIC_APP_SIDS) { + IXmlParserPrintError(state, "Too many service IDs masks in Application definition"); + return; + } + + if (!ServiceIdMaskedEnd(state, &app->serviceIdMaskedMap, content, len, valid)) { + app->serviceIdMaskedMapSize++; + serviceIdMaskedInstance++; + } +} + +// "MGID" end tag +static void VfAppMGidEnd(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + if (xml_parse_debug) + fprintf(stdout, "VfAppMGidEnd instance %u appInstance %u mgidInstance %u common %u\n", + (unsigned int)instance, (unsigned int)appInstance, (unsigned int)mgidInstance, (unsigned int)common); + + // check for max + if (mgidInstance >= MAX_VFABRIC_APP_MGIDS) { + IXmlParserPrintError(state, "Too many multicast GIDs in Application definition"); + return; + } + + if (!valid) { + fprintf(stderr, "Error processing XML MGID tag\n"); + } else if (!content || !app || strlen(content) > MAX_VFABRIC_NAME - 1) { + IXmlParserPrintError(state, "Bad %s content \"%s\"", field->tag, content); + return; + } + + // save away the MGID to the parent structure + snprintf(app->mgid[mgidInstance].mgid, sizeof(app->mgid[mgidInstance].mgid), "%s", content); + + // test conversion + VFAppMgid_t mgidMapping; + if (verifyAndConvertMGidString(content, &mgidMapping) < 0) { + IXmlParserPrintError(state, "Bad MGID format %s", content); + return; + } + + // index to next MGID instance + mgidInstance++; +} + +// "MGIDRange" end tag +static void VfAppMGidRangeEnd(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + if (xml_parse_debug) + fprintf(stdout, "VfAppMGidRangeEnd instance %u appInstance %u mgidRangeInstance %u common %u\n", + (unsigned int)instance, (unsigned int)appInstance, (unsigned int)mgidRangeInstance, (unsigned int)common); + + // check for max + if (mgidRangeInstance >= MAX_VFABRIC_APP_MGIDS) { + IXmlParserPrintError(state, "Too many multicast ranges in Application definition"); + return; + } + + if (!valid) { + fprintf(stderr, "Error processing XML MGIDRange tag\n"); + } else if (!content || !app || strlen(content) > MAX_VFABRIC_APP_ELEMENT - 1) { + IXmlParserPrintError(state, "Bad %s content \"%s\"", field->tag, content); + return; + } + + // save away the MGIDRange to the parent structure + snprintf(app->mgid_range[mgidRangeInstance].range, sizeof(app->mgid_range[mgidRangeInstance].range), "%s", content); + + // test conversion + VFAppMgid_t mgidMapping; + if (verifyAndConvertMGidCompoundString(content, 1, &mgidMapping) < 0) { + IXmlParserPrintError(state, "Bad MGIDRange format, \"%s\"", content); + return; + } + + // index to next MGIDRange instance + mgidRangeInstance++; +} + +// "MGIDMasked" end tag +static void VfAppMGidMaskedEnd(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + if (xml_parse_debug) + fprintf(stdout, "VfAppMGidMaskedEnd instance %u appInstance %u mgidMaskedInstance %u common %u\n", + (unsigned int)instance, (unsigned int)appInstance, (unsigned int)mgidMaskedInstance, (unsigned int)common); + + // check for max + if (mgidMaskedInstance >= MAX_VFABRIC_APP_MGIDS) { + IXmlParserPrintError(state, "Too many multicast masks in Application definition"); + return; + } + + if (!valid) { + fprintf(stderr, "Error processing XML MGIDMasked tag\n"); + } else if (!content || !app || strlen(content) > MAX_VFABRIC_APP_ELEMENT - 1) { + IXmlParserPrintError(state, "Bad %s content \"%s\"", field->tag, content); + return; + } + + // save away the MGIDMasked to the parent structure + snprintf(app->mgid_masked[mgidMaskedInstance].masked, sizeof(app->mgid_masked[mgidMaskedInstance].masked), "%s", content); + + // test conversion + VFAppMgid_t mgidMapping; + if (verifyAndConvertMGidCompoundString(content, 0, &mgidMapping) < 0) { + IXmlParserPrintError(state, "Bad MGIDMasked format %s", content); + return; + } + + // index to next MGIDMasked instance + mgidMaskedInstance++; +} + +// "IncludeApplication" end tag +static void VfAppIncludedApplicationEnd(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + if (xml_parse_debug) + fprintf(stdout, "VfAppIncludedApplicationEnd instance %u appInstance %u includedAppInstance %u common %u\n", + (unsigned int)instance, (unsigned int)appInstance, (unsigned int)includedAppInstance, (unsigned int)common); + + // check for max + if (includedAppInstance >= MAX_INCLUDED_APPS) { + PRINT_MEMORY_ERROR; + return; + } + + if (!valid) { + fprintf(stderr, "Error processing XML IncludeApplication tag\n"); + } else if (!content || !app || strlen(content) > MAX_VFABRIC_NAME) { + IXmlParserPrintError(state, "Bad %s content \"%s\"", field->tag, content); + return; + } + + // save away the IncludedApplication to the parent structure + snprintf(app->included_app[includedAppInstance].node, sizeof(app->included_app[includedAppInstance].node), "%s", content); + + // index to next IncludedApplication instance + includedAppInstance++; +} + +// "Select" end tag +static void VfAppSelectEnd(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + if (xml_parse_debug) + fprintf(stdout, "VfAppSelectEnd instance %u appInstance %u common %u\n", + (unsigned int)instance, (unsigned int)appInstance, (unsigned int)common); + + if (!valid) { + fprintf(stderr, "Error processing XML Application Select tag\n"); + } else if (!content || !app || strlen(content) > MAX_VFABRIC_NAME - 1) { + IXmlParserPrintError(state, "Bad %s content \"%s\"", field->tag, content); + return; + } + + if (strcasecmp(content, "SA") == 0) + app->select_sa |= 1; + else if (strcasecmp(content, "UnmatchedServiceID") == 0) + app->select_unmatched_sid |= 1; + else if (strcasecmp(content, "UnmatchedMGID") == 0) + app->select_unmatched_mgid |= 1; + else if (strcasecmp(content, "PM") == 0) + app->select_pm |= 1; + + + else { + IXmlParserPrintError(state, "Illegal Application Select setting of (%s)", content); + return; + } +} + +// fields within "Application" tag +static IXML_FIELD VfAppFields[] = { + { tag:"Name", format:'s', IXML_FIELD_INFO(AppConfig_t, name) }, + { tag:"ServiceID", format:'k', end_func:VfAppServiceIdEnd }, + { tag:"ServiceIDRange", format:'k', end_func:VfAppServiceIdRangeEnd }, + { tag:"ServiceIDMasked", format:'k', end_func:VfAppServiceIdMaskedEnd }, + { tag:"MGID", format:'k', end_func:VfAppMGidEnd }, + { tag:"MGIDRange", format:'k', end_func:VfAppMGidRangeEnd }, + { tag:"MGIDMasked", format:'k', end_func:VfAppMGidMaskedEnd }, + { tag:"IncludeApplication", format:'k', end_func:VfAppIncludedApplicationEnd }, + { tag:"Select", format:'k', end_func:VfAppSelectEnd}, + { NULL } +}; + +// "Application" start tag +static void* VfAppXmlParserStart(IXmlParserState_t *state, void *parent, const char **attr) +{ + // check for max + if (appInstance >= MAX_VFABRIC_APPS) { + IXmlParserPrintError(state, "Too many Application definitions"); + return NULL; + } + + app = getApplicationObject(); + + if (xml_parse_debug) + fprintf(stdout, "VfAppXmlParserStart instance %u appInstance %u common %u\n", (unsigned int)instance, (unsigned int)appInstance, (unsigned int)common); + + if (!app) { + PRINT_MEMORY_ERROR; + return NULL; + } + + // clear instances + serviceIdInstance = 0; + serviceIdRangeInstance = 0; + serviceIdMaskedInstance = 0; + mgidInstance = 0; + mgidRangeInstance = 0; + mgidMaskedInstance = 0; + includedAppInstance = 0; + + return app; // will be passed to VfAppXmlParserEnd as object +} + +// "Application" end tag +static void VfAppXmlParserEnd(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + app = (AppConfig_t*)IXmlParserGetField(field, object); + uint32_t i; + + if (xml_parse_debug) + fprintf(stdout, "VfAppXmlParserEnd instance %u appInstance %u common %u\n", (unsigned int)instance, (unsigned int)appInstance, (unsigned int)common); + + if (!valid) { + fprintf(stderr, "Error processing XML Application tag\n"); + freeApplicationObject(app); + return; + } + + FMXmlInstance_t *instancep; + if (common) instancep = configp->fm_instance_common; + else instancep = configp->fm_instance[instance]; + + if (!instancep) { + // We don't care about this instance + freeApplicationObject(app); + return; + } + + // Verify that the application has a name + if (strlen(app->name) == 0) { + IXmlParserPrintError(state, "Virtual Fabric Application must have a name"); + freeApplicationObject(app); + return; + } + + // keep track of the number of elements + app->number_of_mgids = mgidInstance; + app->number_of_mgid_ranges = mgidRangeInstance; + app->number_of_mgid_maskeds = mgidMaskedInstance; + app->number_of_included_apps = includedAppInstance; + + // Validate the includedApps exist + for (i = 0; i < app->number_of_included_apps; i++) { + if (cl_qmap_get(&instancep->app_config.appMap, XML_QMAP_U64_CAST app->included_app[i].node) + == cl_qmap_end(&instancep->app_config.appMap)) { + // Not Found + IXmlParserPrintError(state, "Included application (%s) is not defined", app->included_app[i].node); + freeApplicationObject(app); + return; + } + } + + /* Finally, add it to the common map */ + if (!addMap(&instancep->app_config.appMap, XML_QMAP_U64_CAST app)) { + // Couldn't add, must be a duplicate name + IXmlParserPrintError(state, "Duplicate Virtual Fabric Application (%s) encountered", app->name); + freeApplicationObject(app); + return; + } + instancep->app_config.appMapSize++; + + // index to next App instance + appInstance++; +} + +// fields within "Applications" tag +static IXML_FIELD VfsAppFields[] = { + { tag:"Application", format:'k', subfields:VfAppFields, start_func:VfAppXmlParserStart, end_func:VfAppXmlParserEnd }, + { NULL } +}; + +// "Applications" start tag +static void* VfsAppXmlParserStart(IXmlParserState_t *state, void *parent, const char **attr) +{ + if (xml_parse_debug) + fprintf(stdout, "VfsAppXmlParserStart instance %u common %u\n", (unsigned int)instance, (unsigned int)common); + + if (common) { + // reset App index + appInstance = 0; + } else if (configp->fm_instance[instance]) { + // since apps can be inherited from common see how many we have now so we + // can continue to grow the list + appInstance = configp->fm_instance[instance]->app_config.appMapSize; + } else { + appInstance = 0; + } + + return NULL; +} + +// "Applications" end tag +static void VfsAppXmlParserEnd(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + if (xml_parse_debug) + fprintf(stdout, "VfsAppXmlParserEnd instance %u common %u\n", (unsigned int)instance, (unsigned int)common); + + if (!valid) { + fprintf(stderr, "Error processing XML Applications tag\n"); + } else { + // as needed process or validate self consistency of config + } +} + +// "SystemImageGUID" end tag +static void VfGroupSystemImageGuidEnd(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + uint64_t guid; + + if (xml_parse_debug) + fprintf(stdout, "VfGroupSystemImageGuidEnd instance %u groupInstance %u systemImageInstance %u common %u\n", + (unsigned int)instance, (unsigned int)groupInstance, (unsigned int)systemImageInstance, (unsigned int)common); + + if (!valid) { + fprintf(stderr, "Error processing XML SystemImageGUID tag\n"); + return; + } else if (!content || !dgp || strlen(content) > MAX_VFABRIC_NAME - 1) { + IXmlParserPrintError(state, "Bad %s content \"%s\"", field->tag, content); + return; + } + + // save away the SystemImageGUID to the parent structure if it is a valid string + if (FSUCCESS != StringToUint64(&guid, content, NULL, 16, TRUE)) { + IXmlParserPrintError(state, "SystemImageGUID %s is formatted incorrectly", content); + return; + } + + addMap(&dgp->system_image_guid, guid); + + // index to next SystemImageGUID instance + systemImageInstance++; +} + +// "NodeGUID" end tag +static void VfGroupNodeGuidEnd(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + uint64_t guid; + + if (xml_parse_debug) + fprintf(stdout, "VfGroupNodeGuidEnd instance %u groupInstance %u nodeGuidInstance %u common %u\n", + (unsigned int)instance, (unsigned int)groupInstance, (unsigned int)nodeGuidInstance, (unsigned int)common); + + if (!valid) { + fprintf(stderr, "Error processing XML NodeGUID tag\n"); + return; + } else if (!content || !dgp || strlen(content) > MAX_VFABRIC_NAME - 1) { + IXmlParserPrintError(state, "Bad %s content \"%s\"", field->tag, content); + return; + } + + // save away the NodeGUID to the parent structure if it is a valid string + if (FSUCCESS != StringToUint64(&guid, content, NULL, 16, TRUE)) { + IXmlParserPrintError(state, "NodeGUID %s is formatted incorrectly", content); + return; + } + + addMap(&dgp->node_guid, guid); + + // index to next NodeGUID instance + nodeGuidInstance++; +} + +// "PortGUID" end tag +static void VfGroupPortGuidEnd(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + uint64_t guid; + + if (xml_parse_debug) + fprintf(stdout, "VfGroupPortGuidEnd instance %u groupInstance %u portGuidInstance %u common %u\n", + (unsigned int)instance, (unsigned int)groupInstance, (unsigned int)portGuidInstance, (unsigned int)common); + + if (!valid) { + fprintf(stderr, "Error processing XML PortGUID tag\n"); + return; + } else if (!content || !dgp || strlen(content) > MAX_VFABRIC_NAME - 1) { + IXmlParserPrintError(state, "Bad %s content \"%s\"", field->tag, content); + return; + } + + // save away the NodeGUID to the parent structure if it is a valid string + if (FSUCCESS != StringToUint64(&guid, content, NULL, 16, TRUE)) { + IXmlParserPrintError(state, "PortGUID %s is formatted incorrectly", content); + return; + } + + addMap(&dgp->port_guid, guid); + + portGuidInstance++; +} + +// "NodeDesc" end tag +static void VfGroupNodeDescEnd(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + XmlNode_t *temp_node_description; + + if (xml_parse_debug) + fprintf(stdout, "VfGroupNodeDescEnd instance %u groupInstance %u nodeDescInstance %u common %u\n", + (unsigned int)instance, (unsigned int)groupInstance, (unsigned int)nodeDescInstance, (unsigned int)common); + + if (!valid) { + fprintf(stderr, "Error processing XML NodeDesc tag\n"); + } else if (!content || !dgp || strlen(content) > MAX_VFABRIC_NAME) { + IXmlParserPrintError(state, "Bad %s content \"%s\"", field->tag, content); + return; + } + + // save away the NodeDesc to the parent structure + temp_node_description = getXmlMemory(sizeof(XmlNode_t), "XmlNode_t VfGroupNodeDescEnd()"); + if (!temp_node_description) { + PRINT_MEMORY_ERROR; + return; + } + snprintf(temp_node_description->node, sizeof(temp_node_description->node), "%s", content); + temp_node_description->next = NULL; + + if (last_node_description == NULL) + dgp->node_description = temp_node_description; + else + last_node_description->next = temp_node_description; + + last_node_description = temp_node_description; + + //allocate memory used for saving off converted regular expression of this node description + RegExp_t *temp_reg_expr; + + // save away the RegEx to the parent structure + temp_reg_expr = getXmlMemory(sizeof(RegExp_t), "RegExp_t VfGroupNodeDescEnd()"); + if (!temp_reg_expr) { + PRINT_MEMORY_ERROR; + return; + } + + temp_reg_expr->next = NULL; + + if (last_reg_expr == NULL) + dgp->reg_expr = temp_reg_expr; + else + last_reg_expr->next = temp_reg_expr; + + last_reg_expr = temp_reg_expr; + + + // index to next NodeDesc instance + nodeDescInstance++; +} + +// "IncludedGroup" end tag +static void VfGroupIncludedGroupEnd(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + XmlIncGroup_t *temp_included_group; + + if (xml_parse_debug) + fprintf(stdout, "VfGroupIncludedGroupEnd instance %u groupInstance %u includedGroupInstance %u common %u\n", + (unsigned int)instance, (unsigned int)groupInstance, (unsigned int)includedGroupInstance, (unsigned int)common); + + // check for max + if (includedGroupInstance >= MAX_INCLUDED_GROUPS) { + PRINT_MEMORY_ERROR; + return; + } + + if (!valid) { + fprintf(stderr, "Error processing XML IncludeGroup tag\n"); + } else if (!content || !dgp || strlen(content) > MAX_VFABRIC_NAME) { + IXmlParserPrintError(state, "Bad %s content \"%s\"", field->tag, content); + return; + } + + // save away the IncludedGroup to the parent structure + temp_included_group = getXmlMemory(sizeof(XmlIncGroup_t), "XmlIncGroup_t VfGroupIncludedGroupEnd()"); + if (!temp_included_group) { + PRINT_MEMORY_ERROR; + return; + } + snprintf(temp_included_group->group, sizeof(temp_included_group->group), "%s", content); + temp_included_group->next = NULL; + + if (last_included_group == NULL) + dgp->included_group = temp_included_group; + else + last_included_group->next = temp_included_group; + + last_included_group = temp_included_group; + + // index to next IncludedGroup instance + includedGroupInstance++; +} + +// "Select" end tag +static void VfGroupSelectEnd(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + if (xml_parse_debug) + fprintf(stdout, "VfGroupSelectEnd instance %u groupInstance %u common %u\n", + (unsigned int)instance, (unsigned int)groupInstance, (unsigned int)common); + + if (!valid) { + fprintf(stderr, "Error processing XML DeviceGroup Select tag\n"); + } else if (!content || !dgp || strlen(content) > MAX_VFABRIC_NAME - 1) { + IXmlParserPrintError(state, "Bad %s content \"%s\"", field->tag, content); + return; + } + + if (strcasecmp(content, "All") == 0) + dgp->select_all |= 1; + else if (strcasecmp(content, "Self") == 0) + dgp->select_self |= 1; + else if (strcasecmp(content, "AllSMs") == 0) { + fprintf(stderr, "Warning: AllSMs select tag is deprecated; selecting AllMgmtAllowed instead\n"); + dgp->select_all_mgmt_allowed |= 1; + } else if (strcasecmp(content, "HFIDirectConnect") == 0) + dgp->select_hfi_direct_connect |= 1; + else if (strcasecmp(content, "SWE0") == 0) + dgp->select_swe0 |= 1; + else if (strcasecmp(content, "AllMgmtAllowed") == 0) + dgp->select_all_mgmt_allowed |= 1; + else if (strcasecmp(content, "TFIs") == 0) + dgp->select_all_tfis |= 1; + + + else { + IXmlParserPrintError(state, "Illegal DeviceGroup Select setting of (%s)", content); + return; + } +} + +// "NodeType" end tag +static void VfGroupNodeTypeEnd(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + if (xml_parse_debug) + fprintf(stdout, "VfGroupNodeTypeEnd instance %u groupInstance %u common %u\n", + (unsigned int)instance, (unsigned int)groupInstance, (unsigned int)common); + + if (!valid) { + fprintf(stderr, "Error processing XML DeviceGroup NodeType tag\n"); + } else if (!content || !dgp || strlen(content) > MAX_VFABRIC_NAME - 1) { + IXmlParserPrintError(state, "Bad %s content \"%s\"", field->tag, content); + return; + } + + if (strcasecmp(content, "FI") == 0) + dgp->node_type_fi |= 1; + else if (strcasecmp(content, "SW") == 0) + dgp->node_type_sw |= 1; + else { + IXmlParserPrintError(state, "Illegal DeviceGroup NodeType setting of (%s)", content); + return; + } +} + +// fields within "DeviceGroup" tag +static IXML_FIELD VfGroupFields[] = { + { tag:"Name", format:'s', IXML_FIELD_INFO(DGConfig_t, name) }, + { tag:"SystemImageGUID", format:'h', end_func:VfGroupSystemImageGuidEnd }, + { tag:"NodeGUID", format:'k', end_func:VfGroupNodeGuidEnd }, + { tag:"PortGUID", format:'k', end_func:VfGroupPortGuidEnd }, + { tag:"NodeDesc", format:'k', end_func:VfGroupNodeDescEnd }, + { tag:"IncludeGroup", format:'k', end_func:VfGroupIncludedGroupEnd }, + { tag:"NodeType", format:'k', end_func:VfGroupNodeTypeEnd }, + { tag:"Select", format:'k', end_func:VfGroupSelectEnd }, + { NULL } +}; + +// "DeviceGroup" start tag +static void* VfGroupXmlParserStart(IXmlParserState_t *state, void *parent, const char **attr) +{ + // check for max + if (groupInstance >= MAX_VFABRIC_GROUPS) { + IXmlParserPrintError(state, "Too many DeviceGroup definitions"); + return NULL; + } + + dgp = getGroupObject(); + + if (xml_parse_debug) + fprintf(stdout, "VfGroupXmlParserStart instance %u groupInstance %u common %u\n", (unsigned int)instance, (unsigned int)groupInstance, (unsigned int)common); + + if (!dgp) { + PRINT_MEMORY_ERROR; + return NULL; + } + + if (common) { + // inherit the values of the common Group + if (configp->fm_instance_common->dg_config.dg[groupInstance] == NULL) { + configp->fm_instance_common->dg_config.dg[groupInstance] = getGroupObject(); + if (configp->fm_instance_common->dg_config.dg[groupInstance] == NULL) { + freeGroupObject(dgp, /* full */ 1); + PRINT_MEMORY_ERROR; + return NULL; + } + } + // copy Group + if (cloneGroup(configp->fm_instance_common->dg_config.dg[groupInstance], dgp, 1) < 0) { + freeGroupObject(dgp, /* full */ 1); + PRINT_MEMORY_ERROR; + return NULL; + } + } else if (configp->fm_instance[instance]) { + // inherit the values of Group for this instance + if (configp->fm_instance[instance]->dg_config.dg[groupInstance] == NULL) { + configp->fm_instance[instance]->dg_config.dg[groupInstance] = getGroupObject(); + if (configp->fm_instance[instance]->dg_config.dg[groupInstance] == NULL) { + freeGroupObject(dgp, /* full */ 1); + PRINT_MEMORY_ERROR; + return NULL; + } + } + // copy Group + if (cloneGroup(configp->fm_instance[instance]->dg_config.dg[groupInstance], dgp, 1) < 0) { + freeGroupObject(dgp, /* full */ 1); + PRINT_MEMORY_ERROR; + return NULL; + } + } + + // clear instances + systemImageInstance = 0; + nodeGuidInstance = 0; + portGuidInstance = 0; + nodeDescInstance = 0; + includedGroupInstance = 0; + + // clear tail pointers + last_node_description = NULL; + last_reg_expr = NULL; + last_included_group = NULL; + + return dgp; // will be passed to VfGroupXmlParserEnd as object +} + +// "DeviceGroup" end tag +static void VfGroupXmlParserEnd(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + dgp = (DGConfig_t*)IXmlParserGetField(field, object); + uint32_t i; + + if (xml_parse_debug) + fprintf(stdout, "VfGroupXmlParserEnd instance %u groupInstance %u common %u\n", (unsigned int)instance, (unsigned int)groupInstance, (unsigned int)common); + + if (!valid) { + fprintf(stderr, "Error processing XML DeviceGroup tag\n"); + freeGroupObject(dgp, /* full */ 1); + return; + } + + FMXmlInstance_t *instancep; + if (common) instancep = configp->fm_instance_common; + else instancep = configp->fm_instance[instance]; + + if (!instancep) { + // We don't care about this instance + freeGroupObject(dgp, /* full */ 1); + return; + } + + // Verify that the group has a name + if (strlen(dgp->name) == 0) { + IXmlParserPrintError(state, "Virtual Fabric DeviceGroup must have a name"); + freeGroupObject(dgp, /* full */ 1); + return; + } + // If it has a name check for duplicates + for (i = 0; i < groupInstance; i++) { + if (strcmp(dgp->name, instancep->dg_config.dg[i]->name) == 0) { + IXmlParserPrintError(state, "Duplicate Virtual Fabric DeviceGroup (%s) encountered", dgp->name); + freeGroupObject(dgp, /* full */ 1); + return; + } + } + // Does this group include any undefined groups? + XmlIncGroup_t *incgrp = dgp->included_group; + while(incgrp) { + for (i = 0; i < groupInstance; i++) { + if (strcmp(incgrp->group, instancep->dg_config.dg[i]->name) == 0) { + incgrp->dg_index = i; + break; + } + } + if (i == groupInstance) { + IXmlParserPrintError(state, "Included group (%s) is not defined", incgrp->group); + freeGroupObject(dgp, /* full */ 1); + return; + } + incgrp = incgrp->next; + } + dgp->dg_index = (int)groupInstance; + // keep track of the number of elements + dgp->number_of_system_image_guids = systemImageInstance; + dgp->number_of_node_guids = nodeGuidInstance; + dgp->number_of_port_guids = portGuidInstance; + dgp->number_of_node_descriptions = nodeDescInstance; + dgp->number_of_included_groups = includedGroupInstance; + + if (common) { + // save the common settings for this instance + if (instancep->dg_config.dg[groupInstance] == NULL) { + instancep->dg_config.dg[groupInstance] = getGroupObject(); + if (instancep->dg_config.dg[groupInstance] == NULL) { + freeGroupObject(dgp, /* full */ 1); + PRINT_MEMORY_ERROR; + return; + } + } + // copy Group + if (cloneGroup(dgp, instancep->dg_config.dg[groupInstance], 1) < 0) { + freeGroupObject(dgp, /* full */ 1); + PRINT_MEMORY_ERROR; + return; + } + } else { + // save the group config for this instance + if (instancep->dg_config.dg[groupInstance] == NULL) { + instancep->dg_config.dg[groupInstance] = getGroupObject(); + if (instancep->dg_config.dg[groupInstance] == NULL) { + freeGroupObject(dgp, /* full */ 1); + PRINT_MEMORY_ERROR; + return; + } + } + // copy Group + if (cloneGroup(dgp, instancep->dg_config.dg[groupInstance], 1) < 0) { + freeGroupObject(dgp, /* full */ 1); + PRINT_MEMORY_ERROR; + return; + } + } + + // index to next Group instance + groupInstance++; + + freeGroupObject(dgp, /* full */ 1); +} + +// fields within "DeviceGroups" tag +static IXML_FIELD VfsGroupsFields[] = { + { tag:"DeviceGroup", format:'k', subfields:VfGroupFields, start_func:VfGroupXmlParserStart, end_func:VfGroupXmlParserEnd }, + { NULL } +}; + +// "DeviceGroups" start tag +static void* VfsGroupsXmlParserStart(IXmlParserState_t *state, void *parent, const char **attr) +{ + if (xml_parse_debug) + fprintf(stdout, "VfsGroupsXmlParserStart instance %u common %u\n", (unsigned int)instance, (unsigned int)common); + + if (common) { + // reset Group index + groupInstance = 0; + } else if (configp->fm_instance[instance]) { + // since groups can be inherited from common see how many we have now so we + // can continue to grow the list + groupInstance = configp->fm_instance[instance]->dg_config.number_of_dgs; + } else { + groupInstance = 0; + } + + return NULL; +} + +// "DeviceGroups" end tag +static void VfsGroupsXmlParserEnd(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + if (xml_parse_debug) + fprintf(stdout, "VfsGroupsXmlParserEnd instance %u common %u\n", (unsigned int)instance, (unsigned int)common); + + if (!valid) { + fprintf(stderr, "Error processing XML DeviceGroups tag\n"); + } else { + // as needed process or validate self consistency of config + } + + // save the number of accumulated groups + if (common) { + configp->fm_instance_common->dg_config.number_of_dgs = groupInstance; + } else if (configp->fm_instance[instance]) { + configp->fm_instance[instance]->dg_config.number_of_dgs = groupInstance; + } +} + +// "Member" end tag +static void VfMemberEnd(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + VFConfig_t *vfp = (VFConfig_t *) parent; + if (xml_parse_debug) + fprintf(stdout, "VfMemberEnd instance %u vfInstance %u fullMemInstance %u common %u\n", + (unsigned int)instance, (unsigned int)vfInstance, (unsigned int)fullMemInstance, (unsigned int)common); + + // check for max + if (fullMemInstance >= MAX_VFABRIC_MEMBERS_PER_VF) { + IXmlParserPrintError(state, "Too many members in VirtualFabric definition"); + return; + } + + if (!valid) { + fprintf(stderr, "Error processing XML Member tag\n"); + } else if (!content || strlen(content) > MAX_VFABRIC_NAME) { + IXmlParserPrintError(state, "Bad %s content \"%s\"", field->tag, content); + return; + } else if (!getVfXmlMember(&vfp->full_member[fullMemInstance], content)) { + IXmlParserPrintError(state, "Device Group (%s) was not found", content); + return; + } + + // index to next Member instance + fullMemInstance++; +} + +// "LimitedMember" end tag +static void VfLimitedMemberEnd(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + VFConfig_t *vfp = (VFConfig_t *) parent; + if (xml_parse_debug) + fprintf(stdout, "VfLimitedMemberEnd instance %u vfInstance %u limitedMemInstance %u common %u\n", + (unsigned int)instance, (unsigned int)vfInstance, (unsigned int)limitedMemInstance, (unsigned int)common); + + // check for max + if (limitedMemInstance >= MAX_VFABRIC_MEMBERS_PER_VF) { + IXmlParserPrintError(state, "Too many limited members in VirtualFabric definition"); + return; + } + + if (!valid) { + fprintf(stderr, "Error processing XML LimitedMember tag\n"); + } else if (!content || strlen(content) > MAX_VFABRIC_NAME) { + IXmlParserPrintError(state, "Bad %s content \"%s\"", field->tag, content); + return; + } else if (!getVfXmlMember(&vfp->limited_member[limitedMemInstance], content)) { + IXmlParserPrintError(state, "Device Group (%s) was not found", content); + return; + } + + // index to next LimitedMember instance + limitedMemInstance++; +} + +// "Application" end tag +static void VfApplicationsEnd(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + VFConfig_t *vfp = (VFConfig_t *) parent; + if (xml_parse_debug) + fprintf(stdout, "VfApplicationsEnd instance %u vfInstance %u appInstance %u common %u\n", + (unsigned int)instance, (unsigned int)vfInstance, (unsigned int)appInstance, (unsigned int)common); + + // check for max + if (appInstance >= MAX_VFABRIC_APPS_PER_VF) { + IXmlParserPrintError(state, "Too many applications in VirtualFabric definition"); + return; + } + + if (!valid) { + fprintf(stderr, "Error processing XML VirtualFabric Application tag\n"); + } else if (!content || strlen(content) > MAX_VFABRIC_NAME) { + IXmlParserPrintError(state, "Bad %s content \"%s\"", field->tag, content); + return; + } + + // save away the Application to the parent structure + snprintf(vfp->application[appInstance].application, sizeof(vfp->application[appInstance].application), "%s", content); + + // index to next Application instance + appInstance++; +} + +// fields within "VirtualFabric" tag +static IXML_FIELD VfFields[] = { + { tag:"Name", format:'s', IXML_FIELD_INFO(VFConfig_t, name) }, + { tag:"Enable", format:'u', IXML_FIELD_INFO(VFConfig_t, enable) }, + { tag:"Standby", format:'u', IXML_FIELD_INFO(VFConfig_t, standby) }, + { tag:"PKey", format:'h', IXML_FIELD_INFO(VFConfig_t, pkey), end_func:PKeyParserEnd}, + { tag:"Security", format:'u', IXML_FIELD_INFO(VFConfig_t, security) }, + { tag:"Member", format:'k', end_func:VfMemberEnd }, + { tag:"LimitedMember", format:'k', end_func:VfLimitedMemberEnd }, + { tag:"Application", format:'k', end_func:VfApplicationsEnd }, + { tag:"MaxMTU", format:'k', IXML_FIELD_INFO(VFConfig_t, max_mtu_int), end_func:MtuU8XmlParserEnd }, + { tag:"MaxRate", format:'k', IXML_FIELD_INFO(VFConfig_t, max_rate_int), end_func:RateU8XmlParserEnd }, + { tag:"QOSGroup", format:'s', IXML_FIELD_INFO(VFConfig_t, qos_group) }, +// Deprecated VF Fields. These are superceded by QOSGroups + { tag:"BaseSL", format:'u', IXML_FIELD_INFO(VFConfig_t, base_sl) }, + { tag:"MulticastSL", format:'u', IXML_FIELD_INFO(VFConfig_t, mcast_sl) }, + { tag:"FlowControlDisable", format:'u', IXML_FIELD_INFO(VFConfig_t, flowControlDisable) }, + { tag:"QOS", format:'u', IXML_FIELD_INFO(VFConfig_t, qos_enable) }, + { tag:"Bandwidth", format:'k', IXML_FIELD_INFO(VFConfig_t, percent_bandwidth), end_func:PercentU8XmlParserEnd }, + { tag:"HighPriority", format:'u', IXML_FIELD_INFO(VFConfig_t, priority) }, + { tag:"PktLifeTimeMult", format:'u', IXML_FIELD_INFO(VFConfig_t, pkt_lifetime_mult), end_func:CeilLog2U8XmlParserEnd }, + { tag:"PreemptRank", format:'u', IXML_FIELD_INFO(VFConfig_t, preempt_rank) }, + { tag:"HoqLife_Int", format:'k', IXML_FIELD_INFO(VFConfig_t, hoqlife_vf), end_func:IXmlParserEndHoqTimeout_Int }, + { tag:"HoqLife", format:'k', IXML_FIELD_INFO(VFConfig_t, hoqlife_vf), end_func:IXmlParserEndHoqTimeout_Str }, +// End of deprecated fields + { NULL } +}; + +// "VirtualFabric" start tag +static void* VfXmlParserStart(IXmlParserState_t *state, void *parent, const char **attr) +{ + VFConfig_t *vfp; + + if (xml_parse_debug) + fprintf(stdout, "VfXmlParserStart instance %u vfInstance %u common %u\n", (unsigned int)instance, (unsigned int)vfInstance, (unsigned int)common); + + vfp = getVfObject(); + + if (!vfp) { + PRINT_MEMORY_ERROR; + return NULL; + } + + // clear member instances + fullMemInstance = 0; + limitedMemInstance = 0; + appInstance = 0; + + return vfp; // will be passed to VfXmlParserEnd as object +} + +static VFConfig_t* findVfByName(VFXmlConfig_t* vf_config, char* virtualFabric) +{ + uint32_t i; + + if (vf_config == NULL || virtualFabric == NULL) + return NULL; + + for (i = 0; i < vf_config->number_of_vfs; i++) { + if (strcmp(virtualFabric, vf_config->vf[i]->name) == 0) { + return vf_config->vf[i]; + } + } + return NULL; +} + +static VFConfig_t* findVfByPkey(VFXmlConfig_t* vf_config, int pkey) +{ + uint32_t i; + + if (vf_config == NULL) + return NULL; + + for (i = 0; i < vf_config->number_of_vfs; i++) { + if (vf_config->vf[i]->pkey == UNDEFINED_XML32) continue; + if (PKEY_VALUE(pkey) == PKEY_VALUE(vf_config->vf[i]->pkey)) { + return vf_config->vf[i]; + } + } + return NULL; +} + +static boolean validateQosSettings(IXmlParserState_t *state, QosXmlConfig_t *qos_config, QosConfig_t *qosp) +{ + // QOS Enable + if (qosp->qos_enable == UNDEFINED_XML8) { + qosp->qos_enable = 0; + } else if (qosp->qos_enable > 1) { + IXmlParserPrintError(state, "QOS(%s) must be 0(disabled) or 1(enabled)", qosp->name); + goto fail; + } + if (!qosp->qos_enable) { + if (qosp->base_sl != UNDEFINED_XML8) { + IXmlParserPrintWarning(state, "QOS disabled, ignoring BaseSL setting (%d)", qosp->base_sl); + qosp->base_sl = UNDEFINED_XML8; + } + if (qosp->resp_sl != UNDEFINED_XML8 ) { + IXmlParserPrintWarning(state, "QOS disabled, ignoring RespSL setting (%u)", qosp->resp_sl); + qosp->resp_sl = UNDEFINED_XML8; + } + if (qosp->mcast_sl != UNDEFINED_XML8 ) { + IXmlParserPrintWarning(state, "QOS disabled, ignoring MulticastSL setting (%u)", qosp->mcast_sl); + qosp->mcast_sl = UNDEFINED_XML8; + } + if (qosp->flowControlDisable != UNDEFINED_XML8) { + IXmlParserPrintWarning(state, "QOS disabled, ignoring FlowControlDisable setting (%u)", qosp->flowControlDisable); + qosp->flowControlDisable = UNDEFINED_XML8; + } + if (qosp->priority != UNDEFINED_XML8) { + IXmlParserPrintWarning(state, "QOS disabled, ignoring HighPriority setting (%u)", qosp->priority); + qosp->priority = UNDEFINED_XML8; + } + if (qosp->pkt_lifetime_mult != UNDEFINED_XML8) { + IXmlParserPrintWarning(state, "QOS disabled, ignoring PktLifeTimeMult setting (%d)", qosp->pkt_lifetime_mult); + qosp->pkt_lifetime_mult = UNDEFINED_XML8; + } + if (qosp->preempt_rank != UNDEFINED_XML8 ) { + IXmlParserPrintWarning(state, "QOS disabled, ignoring PreemptRank setting (%d)", qosp->preempt_rank); + qosp->preempt_rank = UNDEFINED_XML8; + } + if (qosp->hoqlife_qos != UNDEFINED_XML32 ) { + IXmlParserPrintWarning(state, "QOS disabled, ignoring HoqLife setting (%d)", qosp->hoqlife_qos); + qosp->hoqlife_qos = UNDEFINED_XML32; + } + } + // validate BaseSL + if (qosp->base_sl != UNDEFINED_XML8) { + if (qosp->base_sl > (STL_CONFIGURABLE_SLS - 1)) { + IXmlParserPrintError(state, "BaseSL(%u) must be 0-%u", qosp->base_sl, (STL_CONFIGURABLE_SLS - 1)); + goto fail; + } + } + qosp->base_sl_specified = qosp->base_sl != UNDEFINED_XML8; + // validate RespSL + if (qosp->resp_sl != UNDEFINED_XML8 ) { + if (qosp->resp_sl > (STL_CONFIGURABLE_SLS - 1)) { + IXmlParserPrintError(state, "RespSL(%u) must be 0-%u", qosp->resp_sl, (STL_CONFIGURABLE_SLS - 1)); + goto fail; + } + if (!qosp->base_sl_specified) { + IXmlParserPrintError(state, "RespSL(%u) specified, but no BaseSL", qosp->resp_sl); + goto fail; + } + if (qosp->base_sl == qosp->resp_sl) { + // If the resp_sl is the same as base_sl, it's not really in use + qosp->resp_sl = UNDEFINED_XML8; + } + } + qosp->resp_sl_specified = qosp->resp_sl != UNDEFINED_XML8; + // validate MulticastSL + if (qosp->mcast_sl != UNDEFINED_XML8 ) { + if (qosp->mcast_sl > (STL_CONFIGURABLE_SLS - 1)) { + IXmlParserPrintError(state, "MulticastSL(%u) must be 0-%u", qosp->mcast_sl, (STL_CONFIGURABLE_SLS - 1)); + goto fail; + } + if (!qosp->base_sl_specified) { + IXmlParserPrintError(state, "MulticastSL(%u) specified, but no BaseSL", qosp->mcast_sl); + goto fail; + } + if (qosp->base_sl == qosp->mcast_sl) { + // If the mcast_sl is the same as base_sl, it's not really in use + qosp->mcast_sl = UNDEFINED_XML8; + } + } + qosp->mcast_sl_specified = qosp->mcast_sl != UNDEFINED_XML8; + if (qosp->resp_sl_specified && qosp->mcast_sl_specified && (qosp->resp_sl == qosp->mcast_sl)) { + IXmlParserPrintError(state, "MulticastSL (%d) also specified as RespSL",qosp->resp_sl); + goto fail; + } + // validate FlowControlDisable + if (qosp->flowControlDisable != UNDEFINED_XML8) { + if (qosp->flowControlDisable > 1) { + IXmlParserPrintError(state, "FlowControlDisable(%u) must be 0(no) or 1(yes)", qosp->flowControlDisable); + goto fail; + } + } + // validate Priority + if (qosp->priority != UNDEFINED_XML8) { + if (qosp->priority > 1) { + IXmlParserPrintError(state, "HighPriority(%u) must be 0(no) or 1(yes)", qosp->priority); + goto fail; + } else if (qosp->priority && qosp->percent_bandwidth != UNDEFINED_XML8) { + IXmlParserPrintWarning(state, "QOS High Priority, ignoring Bandwidth setting (%d)", qosp->percent_bandwidth); + qosp->percent_bandwidth = UNDEFINED_XML8; + } + } + // validate Bandwidth + if (qosp->percent_bandwidth != UNDEFINED_XML8) { + if (qosp->percent_bandwidth == 0) { + IXmlParserPrintError(state, "Bandwidth(%u%%) must be in the range of 1-100%%", qosp->percent_bandwidth); + goto fail; + } + } + // validate PktLifeTimeMult + if (qosp->pkt_lifetime_mult != UNDEFINED_XML8) { + qosp->pkt_lifetime_specified = 1; + } + // validate Preemption + if (qosp->preempt_rank != UNDEFINED_XML8 ) { + if (qosp->preempt_rank > 127) { + IXmlParserPrintError(state, "Preemption Rank must in the range of 0-127"); + goto fail; + } + } + // validate Head of Queue life + if (qosp->hoqlife_qos != UNDEFINED_XML32 ) { + qosp->hoqlife_specified = 1; + } else { + qosp->hoqlife_specified = 0; + } + return TRUE; + +fail: + return FALSE; +} + +static inline boolean matchingQosSettings(QosConfig_t *qos1, QosConfig_t *qos2) +{ + if (!qos1->qos_enable && !qos2->qos_enable) { + // Non QOS groups always match + return TRUE; + } + if (qos1->qos_enable == qos2->qos_enable + && qos1->flowControlDisable == qos2->flowControlDisable + && qos1->priority == qos2->priority + && qos1->pkt_lifetime_mult == qos2->pkt_lifetime_mult + && qos1->preempt_rank == qos2->preempt_rank + && qos1->hoqlife_qos == qos2->hoqlife_qos) { + return TRUE; + } + return FALSE; +} + +// Return true if qos2 shares any SLs with qos1 +static inline boolean conflictingQosSLs(IXmlParserState_t *state, QosConfig_t *qos1, QosConfig_t *qos2) +{ + // A QOS group can't conflict with itself + if (qos1 == qos2) return FALSE; + + // Non QOS groups never conflict + if (!qos1->qos_enable && !qos2->qos_enable) return FALSE; + + // Otherwise, make sure qos2's SLs are unique + if (qos2->base_sl_specified) { + if (qos2->base_sl == qos1->base_sl) { + IXmlParserPrintError(state, "BaseSL (%d) already in use",qos1->base_sl); + return TRUE; + } else if (qos2->base_sl == qos1->resp_sl) { + IXmlParserPrintError(state, "BaseSL (%d) previously specified as RespSL",qos2->base_sl); + return TRUE; + } else if (qos2->base_sl == qos1->mcast_sl) { + IXmlParserPrintError(state, "BaseSL (%d) previously specified as MulticastSL",qos2->base_sl); + return TRUE; + } + } + if (qos2->resp_sl_specified) { + if (qos2->resp_sl == qos1->resp_sl) { + IXmlParserPrintError(state, "RespSL (%d) already in use",qos2->resp_sl); + return TRUE; + } else if (qos2->resp_sl == qos1->base_sl) { + IXmlParserPrintError(state, "RespSL (%d) previously specified as BaseSL",qos2->resp_sl); + return TRUE; + } else if (qos2->resp_sl == qos1->mcast_sl) { + IXmlParserPrintError(state, "RespSL (%d) previously specified as MulticastSL",qos2->resp_sl); + return TRUE; + } + } + if (qos2->mcast_sl_specified) { + if (qos2->mcast_sl == qos1->mcast_sl) { + IXmlParserPrintError(state, "MulticastSL (%d) already in use",qos2->mcast_sl); + return TRUE; + } else if (qos2->mcast_sl == qos1->base_sl) { + IXmlParserPrintError(state, "MulticastSL (%d) previously specified as BaseSL",qos2->mcast_sl); + return TRUE; + } else if (qos2->mcast_sl == qos1->resp_sl) { + IXmlParserPrintError(state, "MulticastSL (%d) previously specified as RespSL",qos2->mcast_sl); + return TRUE; + } + } + return FALSE; +} + +static inline boolean compatibleQosSLs(QosConfig_t *qos1, QosConfig_t *qos2, boolean named) +{ + if (!qos1->qos_enable && !qos2->qos_enable) { + // Non QOS groups are automatically compatible + return TRUE; + } + if (qos1->private_group || qos2->private_group) { + // Private QOS groups never match + return FALSE; + } + // To be compatible, they must both have the same defined base_sl + if (qos1->base_sl == UNDEFINED_XML8 || (qos1->base_sl != qos2->base_sl)) { + return FALSE; + } + // To be compatible, either they must have the same resp_sl + // or only one may have a resp_sl. If named, then qos2 + // must be the one with a resp_sl + if (qos1->resp_sl != qos2->resp_sl) { + if (qos1->resp_sl != UNDEFINED_XML8 && qos2->resp_sl != UNDEFINED_XML8) return FALSE; + if (named && qos1->resp_sl != UNDEFINED_XML8) return FALSE; + } + // To be compatible, either they must have the same mcast_sl + // or only one may have a mcast_sl. If named, then qos2 + // must be the one with a mcast_sl + if (qos1->mcast_sl != qos2->mcast_sl) { + if (qos1->mcast_sl != UNDEFINED_XML8 && qos2->mcast_sl != UNDEFINED_XML8) return FALSE; + if (named && qos1->mcast_sl != UNDEFINED_XML8) return FALSE; + } + return TRUE; +} + +static inline uint32_t findQosGroupByName(QosXmlConfig_t *qos_config, char *name) +{ + int i; + + // Find the index of the QOSGroup + for (i = 0; i < qos_config->number_of_qosgroups; i++) { + if (!strncmp(name, qos_config->qosgroups[i]->name, MAX_VFABRIC_NAME)) { + return i; + } + } + return UNDEFINED_XML32; +} + +static inline uint32_t findNonQosGroup(QosXmlConfig_t *qos_config) +{ + uint32_t i; + + // Find the index of the QOSGroup + for (i = 0; i < qos_config->number_of_qosgroups; i++) { + if (!qos_config->qosgroups[i]->qos_enable) { + // already have a nonQos group, use that one + return i; + } + } + return UNDEFINED_XML32; +} + +static boolean validateQosSLs(IXmlParserState_t *state, QosXmlConfig_t *qos_config, QosConfig_t *qosp) +{ + int i; + + // Make sure SLs are unique + for (i = 0; i < qos_config->number_of_qosgroups; i++) { + if (conflictingQosSLs(state, qos_config->qosgroups[i], qosp)) + return FALSE; + } + return TRUE; +} + +static inline boolean mergeQosGroups(IXmlParserState_t *state, QosConfig_t *qosp, QosXmlConfig_t *qos_config, uint32_t qos_index) +{ + if (qos_index >= MAX_QOS_GROUPS) return FALSE; + + QosConfig_t *mergedQos = qos_config->qosgroups[qos_index]; + + if (mergedQos->percent_bandwidth == UNDEFINED_XML8) { + mergedQos->percent_bandwidth = qosp->percent_bandwidth; + } + if (strlen(qosp->name) && !strlen(mergedQos->name)) { + StringCopy(mergedQos->name, qosp->name, sizeof(mergedQos->name)); + } + if (!mergedQos->resp_sl_specified) { + mergedQos->resp_sl = qosp->resp_sl; + mergedQos->resp_sl_specified = qosp->resp_sl_specified; + } + if (!mergedQos->mcast_sl_specified) { + mergedQos->mcast_sl = qosp->mcast_sl; + mergedQos->mcast_sl_specified = qosp->mcast_sl_specified; + mergedQos->contains_mcast |= qosp->mcast_sl_specified; + } + + // Make sure the merged qos is still valid + return validateQosSettings(state, qos_config, mergedQos) && validateQosSLs(state, qos_config, mergedQos); +} + +static uint32_t findCompatibleNamedQosGroup(IXmlParserState_t *state, QosXmlConfig_t *qos_config, QosConfig_t *qosp) +{ + uint32_t i; + + // Try to find a matching QOSGroup using these SLs + for (i = 0; i < MIN(MAX_QOS_GROUPS,qos_config->number_of_qosgroups); i++) { + if (qos_config->qosgroups[i]->private_group) { + // Can't share a private QOS group + continue; + } + if (strlen(qos_config->qosgroups[i]->name) != 0) { + if (compatibleQosSLs(qosp, qos_config->qosgroups[i], TRUE)) { + if (matchingQosSettings(qos_config->qosgroups[i], qosp)) { + return i; + } + } + } + } + return UNDEFINED_XML32; +} + +static uint32_t findCompatibleUnnamedQosGroup(IXmlParserState_t *state, QosXmlConfig_t *qos_config, QosConfig_t *qosp) +{ + uint32_t i; + + // Try to find a matching QOSGroup using these SLs + for (i = 0; i < MIN(MAX_QOS_GROUPS,qos_config->number_of_qosgroups); i++) { + if (qos_config->qosgroups[i]->private_group) { + // Can't share a private QOS group + continue; + } + if (strlen(qos_config->qosgroups[i]->name) == 0) { + if (compatibleQosSLs(qosp, qos_config->qosgroups[i], FALSE)) { + if (matchingQosSettings(qos_config->qosgroups[i], qosp)) { + return i; + } + } + } + } + return UNDEFINED_XML32; +} + +/* + * A VirtualFabric specified QOS parameters (which are deprecated). + * See if they match an existing QOSGroup. If so, return index. + * Otherwise, add a new QOSGroup, and return the index. + * If the QOS parameters, are invalid, or conflict with another + * QOSGroup, return UNDEFINED_XML32. + */ +static uint32_t assignQosGroupFromVfp(IXmlParserState_t *state, QosXmlConfig_t *qos_config, VFConfig_t *vfp) +{ + uint32_t qos_index = UNDEFINED_XML32; + + QosConfig_t *qosp = getQosObject(); + if (!qosp) { + PRINT_MEMORY_ERROR; + return UNDEFINED_XML32; + } + + // Get values from vfp. + qosp->enable = 1; + qosp->qos_enable = vfp->qos_enable; + qosp->base_sl = vfp->base_sl; + qosp->resp_sl = vfp->resp_sl; + qosp->mcast_sl = vfp->mcast_sl; + qosp->flowControlDisable= vfp->flowControlDisable; + qosp->priority = vfp->priority; + qosp->pkt_lifetime_mult = vfp->pkt_lifetime_mult; + qosp->preempt_rank = vfp->preempt_rank; + qosp->percent_bandwidth = UNDEFINED_XML8; + qosp->hoqlife_qos = vfp->hoqlife_vf; + + if (!vfp->qos_enable && (vfp->percent_bandwidth != UNDEFINED_XML8)) { + IXmlParserPrintWarning(state, "QOS disabled, ignoring Bandwidth setting (%d)", vfp->percent_bandwidth); + vfp->percent_bandwidth = UNDEFINED_XML8; + } + if (!validateQosSettings(state, qos_config, qosp)) goto fail; + + // Handle NonQOS First + if (!qosp->qos_enable) { + if ((qos_index = findNonQosGroup(qos_config)) == UNDEFINED_XML32) { + goto newgroup; + } + // All nonQos groups are the same, so merge won't really do anything + goto mergegroups; + } else if (qosp->base_sl == UNDEFINED_XML8) { + // If the VF specified QOS, but did not specify any SLs, + // Then it must be assigned a unique QOSGroup so it gets + // it's own SLs to preserve the legacy behavior (without + // QOSGroups). + qosp->private_group = TRUE; + goto newgroup; + } else { + // Try to find a matching QOSGroup using these SLs + if (((qos_index = findCompatibleNamedQosGroup(state, qos_config, qosp)) != UNDEFINED_XML32) + || ((qos_index = findCompatibleUnnamedQosGroup(state, qos_config, qosp)) != UNDEFINED_XML32)) { + // found a compatible group, merge them together + goto mergegroups; + } else { + // Couldn't find a compatible QOS Group + // Add this QOS group to the list + goto newgroup; + } + } + +newgroup: + // Make sure the SLs are unique to this QOSGroup + if (!validateQosSLs(state, qos_config, qosp)) goto fail; + + if (qos_config->number_of_qosgroups >= MAX_QOS_GROUPS) { + IXmlParserPrintError(state, "Too many implicit QOS Groups"); + goto fail; + } + qos_index = qos_config->number_of_qosgroups++; + qos_config->qosgroups[qos_index] = qosp; + return qos_index; + +mergegroups: + if (!mergeQosGroups(state, qosp, qos_config, qos_index)) goto fail; + freeQosObject(qosp); + return qos_index; + +fail: + freeQosObject(qosp); + return UNDEFINED_XML32; +} + +// "VirtualFabric" end tag +static void VfXmlParserEnd(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + VFConfig_t *vfp = (VFConfig_t*)object; + VFXmlConfig_t *vf_config = (VFXmlConfig_t *)parent; + + if (xml_parse_debug) + fprintf(stdout, "VfXmlParserEnd instance %u vfInstance %u common %u\n", (unsigned int)instance, (unsigned int)vfInstance, (unsigned int)common); + + if (!valid) { + fprintf(stderr, "Error processing XML VirtualFabric tag\n"); + goto fail; + } + // If we don't care about this instance, or if vf is not enabled, just skip it + if (!vf_config || !vfp->enable) { + freeVfObject(vfp); + return; + } + // This VF is enabled, check the limit (NOTE: could still be in standby) + if (vfInstance >= MAX_CONFIGURED_VFABRICS) { + IXmlParserPrintError(state, "Too many Virtual Fabrics configured"); + goto fail; + } + // Verify that the VF has a name + if (strlen(vfp->name) == 0) { + IXmlParserPrintError(state, "Virtual Fabric must have a name"); + goto fail; + } + // If it has a name check for duplicates + if (findVfByName(vf_config, vfp->name) != NULL) { + IXmlParserPrintError(state, "Duplicate VirtualFabric (%s) encountered", vfp->name); + goto fail; + } + + // keep track of the number of elements + vfp->number_of_full_members = fullMemInstance; + vfp->number_of_limited_members = limitedMemInstance; + vfp->number_of_applications = appInstance; + + if (vfp->number_of_full_members == 0 && vfp->number_of_limited_members == 0) { + IXmlParserPrintError(state, "Virtual Fabric (%s) must have either one or more Member or LimitedMember entries defined", vfp->name); + goto fail; + } + if (vfp->number_of_applications == 0) { + IXmlParserPrintError(state, "Virtual Fabric (%s) must have one or more Application entries defined", vfp->name); + goto fail; + } + + // VF Standby + if (vfp->standby > 1) { + IXmlParserPrintError(state, "Standby must be 0=disable 1=enable"); + goto fail; + } + + //security + if (vfp->security == UNDEFINED_XML32) + vfp->security = 0; + + if (!vfp->security && vfp->pkey != UNDEFINED_XML32) + vfp->pkey = MAKE_PKEY(1, vfp->pkey); + + if (vfp->pkey != UNDEFINED_XML32) { + VFConfig_t * vf1 = findVfByPkey(vf_config, vfp->pkey); + if ((vf1 != NULL) && (vf1->security != vfp->security)) { + IXmlParserPrintWarning(state, " VirtualFabric(%s) and VF(%s) share same Pkey(0x%x) but different security settings", + vfp->name, vf1->name, vfp->pkey); + } + } + + // Calculate the qos_config given the vf_config + FMXmlInstance_t *instancep = (FMXmlInstance_t *)((char *)vf_config - offsetof(FMXmlInstance_t,vf_config)); + QosXmlConfig_t *qos_config = &instancep->qos_config; + + if (strlen(vfp->qos_group) != 0) { + vfp->qos_implicit = 0; + // QOSGroup is specified, make sure none of the deprecated QOS parameters are specified. + if (vfp->qos_enable != UNDEFINED_XML8 + || vfp->base_sl != UNDEFINED_XML8 + || vfp->resp_sl != UNDEFINED_XML8 + || vfp->mcast_sl != UNDEFINED_XML8 + || vfp->flowControlDisable != UNDEFINED_XML8 + || vfp->priority != UNDEFINED_XML8 + || vfp->pkt_lifetime_mult != UNDEFINED_XML8 + || vfp->preempt_rank != UNDEFINED_XML8 + || vfp->percent_bandwidth != UNDEFINED_XML8 + || vfp->hoqlife_vf != UNDEFINED_XML32) { + IXmlParserPrintError(state, "VirtualFabric cannot specify QOSGroup and explicit QOS parameters"); + goto fail; + } + // Find the index of the QOSGroup + vfp->qos_index = findQosGroupByName(qos_config, vfp->qos_group); + if (vfp->qos_index == UNDEFINED_XML32) { + IXmlParserPrintError(state, "QOSGroup %s undefined",vfp->qos_group); + goto fail; + } + if (vfp->pkey == UNDEFINED_XML32) { + IXmlParserPrintError(state, "VirtualFabric with QOSGroup must specify PKey"); + goto fail; + } + } else { + + // Prevent mixing of old and new style QOS parameters + if (newStyleVFs) { + IXmlParserPrintError(state, "Configuration includes QOSGroups section. Cannot also include VFs with explicit QOS parameters"); + goto fail; + } + oldStyleVFs = TRUE; + + vfp->qos_implicit = 1; + /* Configuration uses explicit VirtualFabric QOS Parameters. */ + vfp->qos_index = assignQosGroupFromVfp(state, qos_config, vfp); + if (vfp->qos_index == UNDEFINED_XML32) { + goto fail; + } + } + if (!vfp->standby) { + qos_config->qosgroups[vfp->qos_index]->num_vfs++; + if (vfp->qos_implicit) qos_config->qosgroups[vfp->qos_index]->num_implicit_vfs++; + } + + // VFConfig_t is good, save it + // index to next VF instance + vf_config->vf[vfInstance] = vfp; + vf_config->number_of_vfs = ++vfInstance; + return; + +fail: + freeVfObject(vfp); + return; +} + +// fields within "VirtualFabrics" tag +static IXML_FIELD VfsFields[] = { + { tag:"VirtualFabric", format:'k', subfields:VfFields, start_func:VfXmlParserStart, end_func:VfXmlParserEnd }, + { NULL } +}; + +// "VirtualFabrics" start tag +static void* VfsXmlParserStart(IXmlParserState_t *state, void *parent, const char **attr) +{ + VFXmlConfig_t *vf = NULL; + + if (xml_parse_debug) + fprintf(stdout, "VfsXmlParserStart instance %u common %u\n", (unsigned int)instance, (unsigned int)common); + + if (common) { + // reset VF index + vfInstance = 0; + vf = &configp->fm_instance_common->vf_config; + } else if (configp->fm_instance[instance]) { + // since virtual fabrics can be inherited from common see how many we have now so we + // can continue to grow the list + vfInstance = configp->fm_instance[instance]->vf_config.number_of_vfs; + vf = &configp->fm_instance[instance]->vf_config; + } else { + vfInstance = 0; + } + + return vf; +} + +// "VirtualFabrics" end tag +static void VfsXmlParserEnd(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + if (xml_parse_debug) + fprintf(stdout, "VfsXmlParserEnd instance %u common %u\n", (unsigned int)instance, (unsigned int)common); + + if (!valid) { + fprintf(stderr, "Error processing XML VirtualFabrics tag\n"); + } else { + // as needed process or validate self consistency of config + } + + // save the number of accumulated virtual fabrics + if (common) { + configp->fm_instance_common->vf_config.number_of_vfs = vfInstance; + } else if (configp->fm_instance[instance]) { + configp->fm_instance[instance]->vf_config.number_of_vfs = vfInstance; + } +} +// fields within "QOSGroup" tag +static IXML_FIELD QOSGroupFields[] = { + { tag:"Name", format:'s', IXML_FIELD_INFO(QosConfig_t, name) }, + { tag:"Enable", format:'u', IXML_FIELD_INFO(QosConfig_t, enable) }, + { tag:"BaseSL", format:'u', IXML_FIELD_INFO(QosConfig_t, base_sl) }, + { tag:"MulticastSL", format:'u', IXML_FIELD_INFO(QosConfig_t, mcast_sl) }, + { tag:"FlowControlDisable", format:'u', IXML_FIELD_INFO(QosConfig_t, flowControlDisable) }, + { tag:"Bandwidth", format:'k', IXML_FIELD_INFO(QosConfig_t, percent_bandwidth), end_func:PercentU8XmlParserEnd }, + { tag:"HighPriority", format:'u', IXML_FIELD_INFO(QosConfig_t, priority) }, + { tag:"PktLifeTimeMult", format:'k', IXML_FIELD_INFO(QosConfig_t, pkt_lifetime_mult), end_func:CeilLog2U8XmlParserEnd }, + { tag:"PreemptRank", format:'u', IXML_FIELD_INFO(QosConfig_t, preempt_rank) }, + { tag:"HoqLife_Int", format:'u', IXML_FIELD_INFO(QosConfig_t, hoqlife_qos) }, + { tag:"HoqLife", format:'k', IXML_FIELD_INFO(QosConfig_t, hoqlife_qos), end_func:IXmlParserEndHoqTimeout_Str }, + { NULL } +}; + +// "QOSGroup" start tag +static void* QOSGroupXmlParserStart(IXmlParserState_t *state, void *parent, const char **attr) +{ + QosConfig_t *qosp = getQosObject(); + + if (xml_parse_debug) + fprintf(stdout, "QOSGroupXmlParserStart instance %u qosInstance %u common %u\n", (unsigned int)instance, (unsigned int)qosInstance, (unsigned int)common); + + if (!qosp) { + PRINT_MEMORY_ERROR; + return NULL; + } + + qosp->qos_enable = 1; // Configured QOSGroups are always qos_enable TRUE + + return qosp; // will be passed to QOSGroupXmlParserEnd as object +} + +// "QOSGroup" end tag +static void QOSGroupXmlParserEnd(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + QosConfig_t *qosp = (QosConfig_t*)IXmlParserGetField(field, object); + uint32_t qos_index; + QosXmlConfig_t *qos_config = (QosXmlConfig_t *)parent; + + if (xml_parse_debug) + fprintf(stdout, "QosXmlParserEnd instance %u qosInstance %u common %u\n", (unsigned int)instance, (unsigned int)qosInstance, (unsigned int)common); + + if (!valid) { + fprintf(stderr, "Error processing XML QOSGroup tag\n"); + goto fail; + } + // If we don't care about this instance, or if qos group is not enabled, just skip it + if (!qos_config || !qosp->enable) { + freeQosObject(qosp); + return; + } + + // Prevent mixing of old and new style QOS parameters + if (oldStyleVFs) { + IXmlParserPrintError(state, "Configuration includes VFs with explicit QOS parameters. Cannot also include QOSGroups section"); + goto fail; + } + newStyleVFs = TRUE; + + // Don't check the limit until we know the QOSGroup is enabled + if (qosInstance >= MAX_QOS_GROUPS) { + IXmlParserPrintError(state, "Too many QOS Groups specified"); + goto fail; + } + // Verify that the QOSGroup has a name + if (strlen(qosp->name) == 0) { + IXmlParserPrintError(state, "Virtual Fabric must have a name"); + goto fail; + } + // Check the name for duplicates + qos_index = findQosGroupByName(qos_config, qosp->name); + if (qos_index != UNDEFINED_XML32) { + IXmlParserPrintError(state, "Duplicate QOSGroups (%s) encountered", qosp->name); + goto fail; + } + + if (!validateQosSettings(state, qos_config, qosp)) { + goto fail; + } + + // A VF may have created a unnamed QOS group with the same QOS values. + // If such a unnamed QOS group exists, merge this group with it. + if ((qos_index = findCompatibleUnnamedQosGroup(state, qos_config, qosp)) != UNDEFINED_XML32) { + if (!mergeQosGroups(state, qosp, qos_config, qos_index)) { + goto fail; + } + freeQosObject(qosp); + return; + } + + if (!validateQosSLs(state, qos_config, qosp)) { + goto fail; + } + + // QosConfig_t is good, save it + // index to next QOS instance + qos_config->qosgroups[qosInstance] = qosp; + qos_config->number_of_qosgroups = ++qosInstance; + + return; + +fail: + freeQosObject(qosp); + return; +} + + +// fields within "QOSGroups" tag +static IXML_FIELD QOSGroupsFields[] = { + { tag:"QOSGroup", format:'k', subfields:QOSGroupFields, start_func:QOSGroupXmlParserStart, end_func:QOSGroupXmlParserEnd }, + { NULL } +}; + +// "QOSGroups" start tag +static void* QOSGroupsXmlParserStart(IXmlParserState_t *state, void *parent, const char **attr) +{ + QosXmlConfig_t *qos = NULL; + + if (xml_parse_debug) + fprintf(stdout, "QOSGroupsXmlParserStart instance %u common %u\n", (unsigned int)instance, (unsigned int)common); + + if (common) { + // reset QOS index + qosInstance = 0; + qos = &configp->fm_instance_common->qos_config; + } else if (configp->fm_instance[instance]) { + // since virtual fabrics can be inherited from common see how many we have now so we + // can continue to grow the list + qosInstance = configp->fm_instance[instance]->qos_config.number_of_qosgroups; + qos = &configp->fm_instance[instance]->qos_config; + } else { + qosInstance = 0; + } + + return qos; +} + +// "QOSGroups" end tag +static void QOSGroupsXmlParserEnd(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + if (xml_parse_debug) + fprintf(stdout, "QOSGroupsXmlParserEnd instance %u common %u\n", (unsigned int)instance, (unsigned int)common); + + if (!valid) { + fprintf(stderr, "Error processing XML QOSGroups tag\n"); + } else { + // as needed process or validate self consistency of config + } + + // save the number of accumulated QOSGroups + if (common) { + configp->fm_instance_common->qos_config.number_of_qosgroups = qosInstance; + } else if (configp->fm_instance[instance]) { + configp->fm_instance[instance]->qos_config.number_of_qosgroups = qosInstance; + } +} + + +// "PmPortGroup/Monitor" end tag +static void PmPgMonitorEnd(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + int i = 0; + boolean isMonitorValid = 0; + if (xml_parse_debug) + fprintf(stdout, "PmPgMonitorEnd instance %u PmPgInstance %u PmPgMonitorInstance %u common %u\n", + (unsigned int)instance, (unsigned int)vfInstance, (unsigned int)PmPgMonitorInstance, (unsigned int)common); + + // check for max + if (PmPgMonitorInstance >= STL_PM_MAX_DG_PER_PMPG) { + PRINT_MEMORY_ERROR; + return; + } + + if (!valid) { + fprintf(stderr, "Error processing XML PM PortGroup Monitor tag\n"); + } else if (!content || !pgp || strlen(content) > STL_PM_GROUPNAMELEN) { + IXmlParserPrintError(state, "Bad %s content \"%s\"", field->tag, content); + return; + } + + // save away the Application to the parent structure + snprintf(pgp->Monitors[PmPgMonitorInstance].monitor, sizeof(pgp->Monitors[PmPgMonitorInstance].monitor), "%s", content); + for (i=0; i < MAX_VFABRIC_GROUPS ; i++) { + if (configp->fm_instance_common->dg_config.dg[i]->name) { + if (strcmp(pgp->Monitors[PmPgMonitorInstance].monitor, configp->fm_instance_common->dg_config.dg[i]->name) == 0) { + isMonitorValid = 1; + pgp->Monitors[PmPgMonitorInstance].dg_Index = i; + break; + } + else + isMonitorValid = 0; + } + } + if(isMonitorValid == 1) + // index to next Application instance + PmPgMonitorInstance++; + else { + IXmlParserPrintError(state, "Monitor %s is not a valid device group\n ", pgp->Monitors[PmPgMonitorInstance].monitor); + return; + } + +} + +// fields within "PmPortGroup" tag +static IXML_FIELD PmPgFields[] = { + { tag:"Enabled", format:'u', IXML_FIELD_INFO(PmPortGroupXmlConfig_t, Enabled) }, + { tag:"Enable", format:'u', IXML_FIELD_INFO(PmPortGroupXmlConfig_t, Enabled) }, + { tag:"Name", format:'s', IXML_FIELD_INFO(PmPortGroupXmlConfig_t, Name) }, + { tag:"Monitor", format:'k', end_func:PmPgMonitorEnd }, + { NULL } +}; + +// "PmPortGroup" start tag +static void* PmPgXmlParserStart(IXmlParserState_t *state, void *parent, const char **attr) +{ + pgp = getPmPgObject(); + + if (xml_parse_debug) + fprintf(stdout, "PmPgXmlParserStart instance %u PmPgInstance %u common %u\n", (unsigned int)instance, (unsigned int)PmPgInstance, (unsigned int)common); + + if (!pgp) { + PRINT_MEMORY_ERROR; + return NULL; + } + + // clear instances + PmPgMonitorInstance = 0; + + return pgp; // will be passed to PmPgXmlParserEnd as object +} + +// "PmPortGroup" end tag +static void PmPgXmlParserEnd(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + pgp = (PmPortGroupXmlConfig_t*)IXmlParserGetField(field, object); + uint32_t i; + char *reservedGroups[] = {"All", "HFIs", "SWs"}; + + if (xml_parse_debug) + fprintf(stdout, "PmPgXmlParserEnd instance %u PmPgInstance %u common %u\n", (unsigned int)instance, (unsigned int)PmPgInstance, (unsigned int)common); + + if (!valid) { + fprintf(stderr, "Error processing XML PmPortGroup tag\n"); + } else { + // Verify that the port group has a name + if (strlen(pgp->Name) == 0) { + IXmlParserPrintError(state, "PmPortGroup must have a name"); + freeXmlMemory(pgp, sizeof(PmPortGroupXmlConfig_t), "PmPortGroupXmlConfig_t PmPgXmlParserEnd()"); + return; + } + if (pgp->Enabled == 0) { + //TODO: ACG: Display Message? + // duplicates allowed if not enabled + freeXmlMemory(pgp, sizeof(PmPortGroupXmlConfig_t), "PmPortGroupXmlConfig_t PmPgXmlParserEnd()"); + return; + } + // check for max + if (PmPgInstance >= STL_PM_MAX_CUSTOM_PORT_GROUPS) { + IXmlParserPrintError(state, "Max Custom PmPortGroups (%u) reached", STL_PM_MAX_CUSTOM_PORT_GROUPS); + freeXmlMemory(pgp, sizeof(PmPortGroupXmlConfig_t), "PmPortGroupXmlConfig_t PmPgXmlParserEnd()"); + return; + } + // If it has a name check for duplicates + for (i = 0; i < PmPgInstance; i++) { + if (common) { + if (strcmp(pgp->Name, configp->fm_instance_common->pm_config.pm_portgroups[i].Name) == 0) { + IXmlParserPrintError(state, "Duplicate PmPortGroup (%s) encountered", pgp->Name); + freeXmlMemory(pgp, sizeof(PmPortGroupXmlConfig_t), "PmPortGroupXmlConfig_t PmPgXmlParserEnd()"); + return; + } + } else if (configp->fm_instance[instance]) { + if (strcmp(pgp->Name, configp->fm_instance[instance]->pm_config.pm_portgroups[i].Name) == 0) { + IXmlParserPrintError(state, "Duplicate PmPortGroup (%s) encountered", pgp->Name); + freeXmlMemory(pgp, sizeof(PmPortGroupXmlConfig_t), "PmPortGroupXmlConfig_t PmPgXmlParserEnd()"); + return; + } + } + } + // Check the name is not a reserved group + for (i = 0; i < 3; i++) { + if (strcmp(pgp->Name, reservedGroups[i]) == 0) { + IXmlParserPrintError(state, "PmPortGroup (%s) cannot have name of a default port group (All, HFIs, SWs)", pgp->Name); + freeXmlMemory(pgp, sizeof(PmPortGroupXmlConfig_t), "PmPortGroupXmlConfig_t PmPgXmlParserEnd()"); + return; + } + } + } + + // keep track of the number of elements + + + if (common) { + configp->fm_instance_common->pm_config.pm_portgroups[PmPgInstance] = *pgp; + } else if (configp->fm_instance[instance]) { + // inherit the values of PmPortGroup for this instance + configp->fm_instance[instance]->pm_config.pm_portgroups[PmPgInstance]= *pgp; + } + + // index to next PmPortGroup instance + PmPgInstance++; + + freeXmlMemory(pgp, sizeof(PmPortGroupXmlConfig_t), "PmPortGroupXmlConfig_t PmPgXmlParserEnd()"); +} + +// fields within "PmPortGroups" tag +static IXML_FIELD PmPgsFields[] = { + { tag:"PmPortGroup", format:'k', subfields:PmPgFields, start_func:PmPgXmlParserStart, end_func:PmPgXmlParserEnd }, + { NULL } +}; + +// "PmPortGroups" start tag +static void* PmPgsXmlParserStart(IXmlParserState_t *state, void *parent, const char **attr) +{ + if (xml_parse_debug) + fprintf(stdout, "PmPgsXmlParserStart instance %u common %u\n", (unsigned int)instance, (unsigned int)common); + + if (common) { + // reset PmPg index + PmPgInstance = 0; + } else if (configp->fm_instance[instance]) { + // since PortGroups can be inherited from common see how many we have now so we + // can continue to grow the list + PmPgInstance = configp->fm_instance[instance]->pm_config.number_of_pm_groups; + } else { + PmPgInstance = 0; + } + + return NULL; +} + +// "PmPortGroups" end tag +static void PmPgsXmlParserEnd(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + if (xml_parse_debug) + fprintf(stdout, "PmPgsXmlParserEnd instance %u common %u\n", (unsigned int)instance, (unsigned int)common); + + if (!valid) { + fprintf(stderr, "Error processing XML PmPortGroups tag\n"); + } else { + // as needed process or validate self consistency of config + } + + // save the number of accumulated pm port groups + if (common) { + configp->fm_instance_common->pm_config.number_of_pm_groups = PmPgInstance; + } else if (configp->fm_instance[instance]) { + configp->fm_instance[instance]->pm_config.number_of_pm_groups = PmPgInstance; + } +} + +// fields within "Shared" Fm tags +static IXML_FIELD FmSharedFields[] = { + { tag:"Start", format:'u', IXML_FIELD_INFO(FMXmlConfig_t, start) }, + { tag:"Name", format:'s', IXML_FIELD_INFO(FMXmlConfig_t, fm_name) }, + { tag:"SubnetSize", format:'u', IXML_FIELD_INFO(FMXmlConfig_t, subnet_size) }, + { tag:"StartupRetries", format:'u', IXML_FIELD_INFO(FMXmlConfig_t, startup_retries) }, + { tag:"StartupStableWait", format:'u', IXML_FIELD_INFO(FMXmlConfig_t, startup_stable_wait) }, + { tag:"CoreDumpDir", format:'s', IXML_FIELD_INFO(FMXmlConfig_t, CoreDumpDir) }, + { tag:"CoreDumpLimit", format:'s', IXML_FIELD_INFO(FMXmlConfig_t, CoreDumpLimit) }, + { tag:"Debug", format:'u', IXML_FIELD_INFO(FMXmlConfig_t, debug) }, + { tag:"RmppDebug", format:'u', IXML_FIELD_INFO(FMXmlConfig_t, debug_rmpp) }, + { tag:"Priority", format:'u', IXML_FIELD_INFO(FMXmlConfig_t, priority) }, + { tag:"ElevatedPriority", format:'u', IXML_FIELD_INFO(FMXmlConfig_t, elevated_priority) }, + { tag:"LogLevel", format:'u', IXML_FIELD_INFO(FMXmlConfig_t, log_level) }, + { tag:"LogFile", format:'s', IXML_FIELD_INFO(FMXmlConfig_t, log_file) }, + { tag:"LogMode", format:'u', IXML_FIELD_INFO(FMXmlConfig_t, syslog_mode) }, + { tag:"CS_LogMask", format:'u', IXML_FIELD_INFO(FMXmlConfig_t, log_masks[VIEO_CS_MOD_ID]), end_func:ParamU32XmlParserEnd }, + { tag:"MAI_LogMask", format:'u', IXML_FIELD_INFO(FMXmlConfig_t, log_masks[VIEO_MAI_MOD_ID]), end_func:ParamU32XmlParserEnd }, + { tag:"CAL_LogMask", format:'u', IXML_FIELD_INFO(FMXmlConfig_t, log_masks[VIEO_CAL_MOD_ID]), end_func:ParamU32XmlParserEnd }, + { tag:"DVR_LogMask", format:'u', IXML_FIELD_INFO(FMXmlConfig_t, log_masks[VIEO_DRIVER_MOD_ID]), end_func:ParamU32XmlParserEnd }, + { tag:"IF3_LogMask", format:'u', IXML_FIELD_INFO(FMXmlConfig_t, log_masks[VIEO_IF3_MOD_ID]), end_func:ParamU32XmlParserEnd }, + { tag:"SM_LogMask", format:'u', IXML_FIELD_INFO(FMXmlConfig_t, log_masks[VIEO_SM_MOD_ID]), end_func:ParamU32XmlParserEnd }, + { tag:"SA_LogMask", format:'u', IXML_FIELD_INFO(FMXmlConfig_t, log_masks[VIEO_SA_MOD_ID]), end_func:ParamU32XmlParserEnd }, + { tag:"PM_LogMask", format:'u', IXML_FIELD_INFO(FMXmlConfig_t, log_masks[VIEO_PM_MOD_ID]), end_func:ParamU32XmlParserEnd }, + { tag:"PA_LogMask", format:'u', IXML_FIELD_INFO(FMXmlConfig_t, log_masks[VIEO_PA_MOD_ID]), end_func:ParamU32XmlParserEnd }, + { tag:"BM_LogMask", format:'u', IXML_FIELD_INFO(FMXmlConfig_t, log_masks[VIEO_BM_MOD_ID]), end_func:ParamU32XmlParserEnd }, + { tag:"FE_LogMask", format:'u', IXML_FIELD_INFO(FMXmlConfig_t, log_masks[VIEO_FE_MOD_ID]), end_func:ParamU32XmlParserEnd }, + { tag:"APP_LogMask", format:'u', IXML_FIELD_INFO(FMXmlConfig_t, log_masks[VIEO_APP_MOD_ID]), end_func:ParamU32XmlParserEnd }, + + + { tag:"SyslogFacility", format:'s', IXML_FIELD_INFO(FMXmlConfig_t, syslog_facility) }, + { tag:"ConfigConsistencyCheckLevel", format:'u', IXML_FIELD_INFO(FMXmlConfig_t, config_consistency_check_level) }, + { tag:"SslSecurityEnabled", format:'u', IXML_FIELD_INFO(FMXmlConfig_t, SslSecurityEnabled) }, + { tag:"SslSecurityEnable", format:'u', IXML_FIELD_INFO(FMXmlConfig_t, SslSecurityEnabled) }, +#ifndef __VXWORKS__ + { tag:"SslSecurityDir", format:'s', IXML_FIELD_INFO(FMXmlConfig_t, SslSecurityDir) }, +#endif + { tag:"SslSecurityFmCertificate", format:'s', IXML_FIELD_INFO(FMXmlConfig_t, SslSecurityFmCertificate) }, + { tag:"SslSecurityFmPrivateKey", format:'s', IXML_FIELD_INFO(FMXmlConfig_t, SslSecurityFmPrivateKey) }, + { tag:"SslSecurityFmCaCertificate", format:'s', IXML_FIELD_INFO(FMXmlConfig_t, SslSecurityFmCaCertificate) }, + { tag:"SslSecurityFmCertChainDepth", format:'u', IXML_FIELD_INFO(FMXmlConfig_t, SslSecurityFmCertChainDepth) }, + { tag:"SslSecurityFmDHParameters", format:'s', IXML_FIELD_INFO(FMXmlConfig_t, SslSecurityFmDHParameters) }, + { tag:"SslSecurityFmCaCRLEnabled", format:'u', IXML_FIELD_INFO(FMXmlConfig_t, SslSecurityFmCaCRLEnabled) }, + { tag:"SslSecurityFmCaCRLEnable", format:'u', IXML_FIELD_INFO(FMXmlConfig_t, SslSecurityFmCaCRLEnabled) }, + { tag:"SslSecurityFmCaCRL", format:'s', IXML_FIELD_INFO(FMXmlConfig_t, SslSecurityFmCaCRL) }, + { tag:"Hfi", format:'u', IXML_FIELD_INFO(FMXmlConfig_t, hca), end_func:HfiXmlParserEnd }, + { tag:"Port", format:'u', IXML_FIELD_INFO(FMXmlConfig_t, port) }, + { tag:"SubnetPrefix", format:'h', IXML_FIELD_INFO(FMXmlConfig_t, subnet_prefix) }, + { tag:"PortGUID", format:'h', IXML_FIELD_INFO(FMXmlConfig_t, port_guid) }, + { NULL } +}; + +// Fm Shared start tag +static void* FmSharedXmlParserStart(IXmlParserState_t *state, void *parent, const char **attr) +{ + FMXmlConfig_t *fmp = getXmlMemory(sizeof(FMXmlConfig_t), "FMXmlConfig_t FmSharedXmlParserStart()"); + + if (xml_parse_debug) + fprintf(stdout, "FmSharedXmlParserStart instance %u common %u\n", (unsigned int)instance, (unsigned int)common); + + if (!fmp) { + PRINT_MEMORY_ERROR; + return NULL; + } + + // inherit the values of the common Fm + *fmp = configp->fm_instance_common->fm_config; + + // set fields that can be overridden per instance of FM to see if we've actually read any real values + // default for Fm.Name + sprintf(fmp->fm_name, "fm%u", (unsigned)instance); + + fmp->debug = UNDEFINED_XML32; + fmp->debug_rmpp = UNDEFINED_XML32; + fmp->subnet_size = UNDEFINED_XML32; + fmp->priority = UNDEFINED_XML32; + fmp->elevated_priority = UNDEFINED_XML32; + fmp->log_level = UNDEFINED_XML32; + fmp->syslog_mode = UNDEFINED_XML32; + memset(fmp->log_masks, 0, sizeof(fmp->log_masks)); + fmp->config_consistency_check_level = UNDEFINED_XML32; + memset(fmp->log_file, 0, sizeof(fmp->log_file)); + memset(fmp->CoreDumpLimit, 0, sizeof(fmp->CoreDumpLimit)); + memset(fmp->CoreDumpDir, 0, sizeof(fmp->CoreDumpDir)); + memset(fmp->syslog_facility, 0, sizeof(fmp->syslog_facility)); + fmp->SslSecurityEnabled = UNDEFINED_XML32; + fmp->SslSecurityFmCertChainDepth = UNDEFINED_XML32; + memset(fmp->SslSecurityDir, 0, sizeof(fmp->SslSecurityDir)); + memset(fmp->SslSecurityFmCertificate, 0, sizeof(fmp->SslSecurityFmCertificate)); + memset(fmp->SslSecurityFmPrivateKey, 0, sizeof(fmp->SslSecurityFmPrivateKey)); + memset(fmp->SslSecurityFmCaCertificate, 0, sizeof(fmp->SslSecurityFmCaCertificate)); + memset(fmp->SslSecurityFmDHParameters, 0, sizeof(fmp->SslSecurityFmDHParameters)); + fmp->SslSecurityFmCaCRLEnabled = UNDEFINED_XML32; + memset(fmp->SslSecurityFmCaCRL, 0, sizeof(fmp->SslSecurityFmCaCRL)); + + return fmp; // will be passed to SharedFmXmlParserEnd as object +} + +// FM Shared end tag +static void FmSharedXmlParserEnd(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + FMXmlConfig_t *fmp = (FMXmlConfig_t*)IXmlParserGetField(field, object); + SMXmlConfig_t *smp; + PMXmlConfig_t *pmp; + FEXmlConfig_t *fep; + + +#ifndef __VXWORKS__ + char facility[256]; +#endif + uint32_t modid; + + if (xml_parse_debug) + fprintf(stdout, "FmSharedXmlParserEnd instance %u common %u\n", (unsigned int)instance, (unsigned int)common); + + if (!valid) { + fprintf(stderr, "Error processing XML Fm Shared tag\n"); + } else { + if (fmp->priority != UNDEFINED_XML32 && fmp->priority > MAX_PRIORITY) { + IXmlParserPrintError(state, "Fm Shared Priority must be in the range of 0-15"); + freeXmlMemory(fmp, sizeof(FMXmlConfig_t), "FMXmlConfig_t FmSharedXmlParserEnd()"); + return; + } + if (fmp->elevated_priority != UNDEFINED_XML32 && fmp->elevated_priority > MAX_PRIORITY) { + IXmlParserPrintError(state, "Fm Shared ElevatedPriority must be in the range of 0-15"); + freeXmlMemory(fmp, sizeof(FMXmlConfig_t), "FMXmlConfig_t FmSharedXmlParserEnd()"); + return; + } + if (strlen(fmp->CoreDumpLimit) && vs_getCoreDumpLimit(fmp->CoreDumpLimit, NULL) < 0) { + IXmlParserPrintError(state, "Invalid Fm CoreDumpLimit: '%s'", fmp->CoreDumpLimit); + freeXmlMemory(fmp, sizeof(FMXmlConfig_t), "FMXmlConfig_t FmSharedXmlParserEnd()"); + return; + } +#ifndef __VXWORKS__ + if (strlen(fmp->syslog_facility) && getFacility(fmp->syslog_facility, /* test */ 1) < 0) { + IXmlParserPrintError(state, "Fm SyslogFacility must be set to one of the following - %s", showFacilities(facility, sizeof(facility))); + freeXmlMemory(fmp, sizeof(FMXmlConfig_t), "FMXmlConfig_t FmSharedXmlParserEnd()"); + return; + } +#endif + if (fmp->config_consistency_check_level != UNDEFINED_XML32 ) { + if (fmp->config_consistency_check_level == NO_CHECK_CCC_LEVEL){ + XmlParsePrintWarning("Fm ConfigConsistencyCheckLevel = 0 is deprecated. Switched to 1"); + fmp->config_consistency_check_level = CHECK_NO_ACTION_CCC_LEVEL; + } else if(fmp->config_consistency_check_level > CHECK_ACTION_CCC_LEVEL) { + IXmlParserPrintError(state, "Fm ConfigConsistencyCheckLevel must be set to 1 or 2"); + freeXmlMemory(fmp, sizeof(FMXmlConfig_t), "FMXmlConfig_t FmSharedXmlParserEnd()"); + return; + } + } + } + + // save Fm config data for this instance + if (configp->fm_instance[instance]) { + + configp->fm_instance[instance]->fm_config = *fmp; + + if (xml_parse_debug) + fprintf(stdout, "FM start = %u instance %u\n", (unsigned int)configp->fm_instance[instance]->fm_config.start, (unsigned int)instance); + + // get pointers to each applications shared config data + smp = &configp->fm_instance[instance]->sm_config; + pmp = &configp->fm_instance[instance]->pm_config; + fep = &configp->fm_instance[instance]->fe_config; + + + // inherit shared Fm settings into specific settings for this instance + if (fmp->subnet_size != UNDEFINED_XML32) { + smp->subnet_size = fmp->subnet_size; + pmp->subnet_size = fmp->subnet_size; + fep->subnet_size = fmp->subnet_size; + } + + if (fmp->debug != UNDEFINED_XML32) { + smp->debug = fmp->debug; + pmp->debug = fmp->debug; + fep->debug = fmp->debug; + } + + if (fmp->debug_rmpp != UNDEFINED_XML32) { + smp->debug_rmpp = fmp->debug_rmpp; + pmp->debug_rmpp = fmp->debug_rmpp; + fep->debug_rmpp = fmp->debug_rmpp; + } + + if (fmp->priority != UNDEFINED_XML32) { + smp->priority = fmp->priority; + pmp->priority = fmp->priority; + } + + if (fmp->elevated_priority != UNDEFINED_XML32) { + smp->elevated_priority = fmp->elevated_priority; + pmp->elevated_priority = fmp->elevated_priority; + } + + if (fmp->hca != UNDEFINED_XML32) { + smp->hca = fmp->hca; + pmp->hca = fmp->hca; + fep->hca = fmp->hca; + + } + + if (fmp->port != UNDEFINED_XML32) { + smp->port = fmp->port; + pmp->port = fmp->port; + fep->port = fmp->port; + + } + + if (fmp->port_guid != UNDEFINED_XML64) { + smp->port_guid = fmp->port_guid; + pmp->port_guid = fmp->port_guid; + fep->port_guid = fmp->port_guid; + + } + + if (fmp->subnet_prefix != UNDEFINED_XML64) { + smp->subnet_prefix = fmp->subnet_prefix; + } + + if (strlen(fmp->fm_name)) { + snprintf(smp->name, MAX_VFABRIC_NAME, "%s_sm", fmp->fm_name); + snprintf(pmp->name, MAX_VFABRIC_NAME, "%s_pm", fmp->fm_name); + snprintf(fep->name, MAX_VFABRIC_NAME, "%s_fe", fmp->fm_name); + + } + + if (fmp->log_level != UNDEFINED_XML32) { + smp->log_level = fmp->log_level; + pmp->log_level = fmp->log_level; + fep->log_level = fmp->log_level; + } + for (modid=0; modid <= VIEO_LAST_MOD_ID; ++modid) { + // test for UNDEFINED_XML8 just in case + if (fmp->log_masks[modid].valid && fmp->log_masks[modid].valid != UNDEFINED_XML8) { + smp->log_masks[modid] = fmp->log_masks[modid]; + pmp->log_masks[modid] = fmp->log_masks[modid]; + fep->log_masks[modid] = fmp->log_masks[modid]; + } + } + + if (strlen(fmp->CoreDumpLimit)) { + StringCopy(smp->CoreDumpLimit, fmp->CoreDumpLimit, STRING_SIZE); + } + + if (strlen(fmp->CoreDumpDir)) { + StringCopy(smp->CoreDumpDir, fmp->CoreDumpDir, FILENAME_SIZE); + } + + if (strlen(fmp->log_file)) { + StringCopy(smp->log_file, fmp->log_file, LOGFILE_SIZE); + StringCopy(pmp->log_file, fmp->log_file, LOGFILE_SIZE); + StringCopy(fep->log_file, fmp->log_file, LOGFILE_SIZE); + } + + if (strlen(fmp->syslog_facility)) { + StringCopy(smp->syslog_facility, fmp->syslog_facility, STRING_SIZE); + StringCopy(pmp->syslog_facility, fmp->syslog_facility, STRING_SIZE); + StringCopy(fep->syslog_facility, fmp->syslog_facility, STRING_SIZE); + } + + if (fmp->syslog_mode != UNDEFINED_XML32) { + smp->syslog_mode = fmp->syslog_mode; + pmp->syslog_mode = fmp->syslog_mode; + fep->syslog_mode = fmp->syslog_mode; + } + + if (fmp->config_consistency_check_level != UNDEFINED_XML32) { + smp->config_consistency_check_level = fmp->config_consistency_check_level; + pmp->config_consistency_check_level = fmp->config_consistency_check_level; + } + + if (fmp->SslSecurityEnabled != UNDEFINED_XML32) { + smp->SslSecurityEnabled = fmp->SslSecurityEnabled; + pmp->SslSecurityEnabled = fmp->SslSecurityEnabled; + fep->SslSecurityEnabled = fmp->SslSecurityEnabled; + } + if (strlen(fmp->SslSecurityDir)) { + StringCopy(smp->SslSecurityDir, fmp->SslSecurityDir, sizeof(smp->SslSecurityDir)); + StringCopy(pmp->SslSecurityDir, fmp->SslSecurityDir, sizeof(pmp->SslSecurityDir)); + StringCopy(fep->SslSecurityDir, fmp->SslSecurityDir, sizeof(fep->SslSecurityDir)); + } + + if (strlen(fmp->SslSecurityFmCertificate)) { + StringCopy(smp->SslSecurityFmCertificate, fmp->SslSecurityFmCertificate, sizeof(smp->SslSecurityFmCertificate)); + StringCopy(pmp->SslSecurityFmCertificate, fmp->SslSecurityFmCertificate, sizeof(pmp->SslSecurityFmCertificate)); + StringCopy(fep->SslSecurityFmCertificate, fmp->SslSecurityFmCertificate, sizeof(fep->SslSecurityFmCertificate)); + } + + if (strlen(fmp->SslSecurityFmPrivateKey)) { + StringCopy(smp->SslSecurityFmPrivateKey, fmp->SslSecurityFmPrivateKey, sizeof(smp->SslSecurityFmPrivateKey)); + StringCopy(pmp->SslSecurityFmPrivateKey, fmp->SslSecurityFmPrivateKey, sizeof(pmp->SslSecurityFmPrivateKey)); + StringCopy(fep->SslSecurityFmPrivateKey, fmp->SslSecurityFmPrivateKey, sizeof(fep->SslSecurityFmPrivateKey)); + } + + if (strlen(fmp->SslSecurityFmCaCertificate)) { + StringCopy(smp->SslSecurityFmCaCertificate, fmp->SslSecurityFmCaCertificate, sizeof(smp->SslSecurityFmCaCertificate)); + StringCopy(pmp->SslSecurityFmCaCertificate, fmp->SslSecurityFmCaCertificate, sizeof(pmp->SslSecurityFmCaCertificate)); + StringCopy(fep->SslSecurityFmCaCertificate, fmp->SslSecurityFmCaCertificate, sizeof(fep->SslSecurityFmCaCertificate)); + } + + if (fmp->SslSecurityFmCertChainDepth != UNDEFINED_XML32) { + smp->SslSecurityFmCertChainDepth = fmp->SslSecurityFmCertChainDepth; + pmp->SslSecurityFmCertChainDepth = fmp->SslSecurityFmCertChainDepth; + fep->SslSecurityFmCertChainDepth = fmp->SslSecurityFmCertChainDepth; + } + + if (strlen(fmp->SslSecurityFmDHParameters)) { + StringCopy(smp->SslSecurityFmDHParameters, fmp->SslSecurityFmDHParameters, sizeof(smp->SslSecurityFmDHParameters)); + StringCopy(pmp->SslSecurityFmDHParameters, fmp->SslSecurityFmDHParameters, sizeof(pmp->SslSecurityFmDHParameters)); + StringCopy(fep->SslSecurityFmDHParameters, fmp->SslSecurityFmDHParameters, sizeof(fep->SslSecurityFmDHParameters)); + } + + if (fmp->SslSecurityFmCaCRLEnabled != UNDEFINED_XML32) { + smp->SslSecurityFmCaCRLEnabled = fmp->SslSecurityFmCaCRLEnabled; + pmp->SslSecurityFmCaCRLEnabled = fmp->SslSecurityFmCaCRLEnabled; + fep->SslSecurityFmCaCRLEnabled = fmp->SslSecurityFmCaCRLEnabled; + } + + if (strlen(fmp->SslSecurityFmCaCRL)) { + StringCopy(smp->SslSecurityFmCaCRL, fmp->SslSecurityFmCaCRL, sizeof(smp->SslSecurityFmCaCRL)); + StringCopy(pmp->SslSecurityFmCaCRL, fmp->SslSecurityFmCaCRL, sizeof(pmp->SslSecurityFmCaCRL)); + StringCopy(fep->SslSecurityFmCaCRL, fmp->SslSecurityFmCaCRL, sizeof(fep->SslSecurityFmCaCRL)); + } + } + + freeXmlMemory(fmp, sizeof(FMXmlConfig_t), "FMXmlConfig_t FmSharedXmlParserEnd()"); +} + +// fields within "Fm" tags +static IXML_FIELD FmFields[] = { + { tag:"Shared", format:'K', subfields:FmSharedFields, start_func:FmSharedXmlParserStart, end_func:FmSharedXmlParserEnd }, + { tag:"Sm", format:'K', subfields:SmFields, start_func:SmXmlParserStart, end_func:SmXmlParserEnd }, + { tag:"Fe", format:'K', subfields:FeFields, start_func:FeXmlParserStart, end_func:FeXmlParserEnd }, + { tag:"Pm", format:'K', subfields:PmFields, start_func:PmXmlParserStart, end_func:PmXmlParserEnd }, + + + { tag:"Applications", format:'k', subfields:VfsAppFields, start_func:VfsAppXmlParserStart, end_func:VfsAppXmlParserEnd }, + { tag:"DeviceGroups", format:'k', subfields:VfsGroupsFields, start_func:VfsGroupsXmlParserStart, end_func:VfsGroupsXmlParserEnd }, + { tag:"VirtualFabrics", format:'k', subfields:VfsFields, start_func:VfsXmlParserStart, end_func:VfsXmlParserEnd }, + + + { tag:"QOSGroups", format:'k', subfields:QOSGroupsFields, start_func:QOSGroupsXmlParserStart, end_func:QOSGroupsXmlParserEnd}, + { tag:"PmPortGroups", format:'k', subfields:PmPgsFields, start_func:PmPgsXmlParserStart, end_func:PmPgsXmlParserEnd }, + { NULL } +}; + +// Fm start tag +static void* FmXmlParserStart(IXmlParserState_t *state, void *parent, const char **attr) +{ + if (xml_parse_debug) + fprintf(stdout, "FmXmlParserStart instance %u\n", (unsigned int)instance); + + // Only allocate if doing a full parse + if (full_parse) { + // Allocate new instance + configp->fm_instance[instance] = getXmlMemory(sizeof(FMXmlInstance_t), "FMXmlInstance_t FmXmlParserStart()"); + if (!configp->fm_instance[instance]) { + PRINT_MEMORY_ERROR; + return NULL; + } + + // Init new instance with clone from Common + if (!cloneFmInstance(configp->fm_instance[instance], configp->fm_instance_common)) { + freeXmlMemory(configp->fm_instance[instance], sizeof(FMXmlInstance_t), "FMXmlInstance_t FmXmlParserStart()" ); + // TODO: Did all the memory get freed? Can this fail (other than running out of memory)? Can the SM continue? + configp->fm_instance[instance] = NULL; + return NULL; + } + } + common = 0; // all parsing is for FM now + return configp->fm_instance[instance]; +} + +static FSTATUS assign_pkey(uint32 *pkeys, int *numpk, uint32 *candidate) +{ + uint32 pk=0; + + while ( pk < *numpk && pk < MAX_ENABLED_VFABRICS){ + if ((*candidate) == pkeys[pk]) { + (*candidate)++; + pk=0; + } + else pk++; + } + if (pk >= MAX_ENABLED_VFABRICS) + return FERROR; + + pkeys[pk]=(*candidate); + (*numpk)++; + return FSUCCESS; +} + +static FSTATUS CheckAllVFsSecurity (VFXmlConfig_t *vf_c) +{ +//find if there are any VF with security enabled + boolean VF_security = FALSE; + int i; + + for(i=0; i< vf_c->number_of_vfs && i < MAX_CONFIGURED_VFABRICS + && !VF_security; i++) { + if (vf_c->vf[i]->security) + VF_security = TRUE; + } + vf_c->securityEnabled = VF_security; + return FSUCCESS; +} + +static IXmlParserState_t *render_logger_state = NULL; +static void renderVfLoggerError(const char *msg) +{ + if (render_logger_state) + IXmlParserPrintError(render_logger_state, msg); +} + +static void renderVfLoggerWarning(const char *msg) +{ + if (render_logger_state) + IXmlParserPrintWarning(render_logger_state, msg); +} + +// FM end tag +static void FmXmlParserEnd(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + if (xml_parse_debug) + fprintf(stdout, "FmXmlParserEnd instance %u\n", (unsigned int)instance); + + // instances are limited + if (instance >= MAX_INSTANCES) { + IXmlParserPrintError(state, "Maximum number of Fm instances exceeded"); + return; + } + + if (!valid) { + fprintf(stderr, "Error processing XML Fm tag\n"); + } else if (full_parse || instance == fm_instance) { + // verify the Virtual Fabrics Configuration if this is an instance we care about + FMXmlInstance_t *instancep = configp->fm_instance[instance]; + + // fill in configuration parameters that have not been read from the configuration and also + // calculate the checksums for each component + + if (!fmInitConfig(&instancep->fm_config, instance)) { + IXmlParserPrintError(state, "Virtual Fabrics XML parse error."); + return; + } + + + // If startup_retries or startup_stable_wait is not set for a component + // use the value set for the Fm instance. If the value is also not + // set for the Fm instance, it will be set to the default value + // when the component InitConfig routine is called below. + if (instancep->sm_config.startup_retries == UNDEFINED_XML32) + instancep->sm_config.startup_retries = instancep->fm_config.startup_retries; + if (instancep->fe_config.startup_retries == UNDEFINED_XML32) + instancep->fe_config.startup_retries = instancep->fm_config.startup_retries; + + + if (instancep->sm_config.startup_stable_wait == UNDEFINED_XML32) + instancep->sm_config.startup_stable_wait = instancep->fm_config.startup_stable_wait; + if (instancep->fe_config.startup_stable_wait == UNDEFINED_XML32) + instancep->fe_config.startup_stable_wait = instancep->fm_config.startup_stable_wait; + + + + // If an instance is disabled, disable all of the components in the instance + if (!instancep->fm_config.start) { + instancep->sm_config.start = 0; + instancep->pm_config.start = 0; + instancep->fe_config.start = 0; + + } + + + // Calculate checksums, and initialize defaults + if (startSmChecksum(&instancep->sm_config)) { + boolean fail; + fail = !smInitConfig(&instancep->sm_config) + || !smDplInitConfig(&instancep->sm_dpl_config) + || !smMcInitConfig(&instancep->sm_mc_config) + || !smMlsInitConfig(&instancep->sm_mls_config) + || !smMdgInitConfig(&instancep->sm_mdg_config) + || !dgInitConfig(&instancep->dg_config) + || !appInitConfig(&instancep->app_config) + || !qosInitConfig(&instancep->qos_config) + || !vfInitConfig(&instancep->vf_config); + endSmChecksum(&instancep->sm_config, instance); + if (fail) { + IXmlParserPrintError(state, "SM configuration error."); + return; + } + } + if (startPmChecksum(&instancep->pm_config)) { + boolean fail; + fail = !pmInitConfig(&instancep->pm_config); + endPmChecksum(&instancep->pm_config, instance); + if (fail) { + IXmlParserPrintError(state, "PM configuration error."); + return; + } + } + if (startFeChecksum(&instancep->fe_config)) { + boolean fail; + fail = !feInitConfig(&instancep->fe_config); + endFeChecksum(&instancep->fe_config, instance); + if (fail) { + IXmlParserPrintError(state, "FE configuration error."); + return; + } + } + + + //check if MLIDShare overlap + if (CheckMLIDShareOverlapping(instance, configp) != FSUCCESS) { + IXmlParserPrintError(state, "MLIDShare XML parse error - MLIDShare is allowing same MGID to match two different MLIDShare groups"); + return; + } + + //assign pkeys to VFs + uint32 vfs_pkeys[MAX_ENABLED_VFABRICS]; + int i, default_Pkey=0; + uint32 candidate_Pkey=1; // 1 is for Default fabric + int num_pkey=0; + + if (instancep->vf_config.number_of_vfs > MAX_ENABLED_VFABRICS) { + IXmlParserPrintError(state, "No more than %u Virtual Fabrics can be enabled in the configuration.", MAX_ENABLED_VFABRICS); + return; + } + + CheckAllVFsSecurity(&instancep->vf_config); + //save all already known pkeys + for(i=0; i< instancep->vf_config.number_of_vfs && i < MAX_CONFIGURED_VFABRICS; i++) { + if (!instancep->vf_config.vf[i]->enable) + continue; + if (instancep->vf_config.vf[i]->pkey != UNDEFINED_XML32) { + if (num_pkey >= MAX_ENABLED_VFABRICS){ + IXmlParserPrintError(state, "Unable to allocate Pkey to vf. Pkey table full."); + return; + } + vfs_pkeys[num_pkey++]= PKEY_VALUE(instancep->vf_config.vf[i]->pkey); + } + } // for end + // before doing anything else, assign missing pkeys here... except disabled VFs + for(i=0; i< instancep->vf_config.number_of_vfs && i < MAX_CONFIGURED_VFABRICS; i++) { + if (!instancep->vf_config.vf[i]->enable) + continue; + if (instancep->vf_config.vf[i]->pkey == UNDEFINED_XML32) { + if (instancep->vf_config.vf[i]->security){ + // assign unique pkey + if (num_pkey >= MAX_ENABLED_VFABRICS){ + IXmlParserPrintError(state, "Unable to allocate Pkey to VF. Pkey table full."); + return; + } + if (assign_pkey(vfs_pkeys, &num_pkey, &candidate_Pkey)!= FSUCCESS) { + IXmlParserPrintError(state, "Unable to allocate Pkey to VF. Pkey table full."); + return; + } + instancep->vf_config.vf[i]->pkey = candidate_Pkey; + } // end if current VF has security set + else { // find a pkey and use it as default pkey for all VF that do not have security set + if (default_Pkey ==0) { + if (num_pkey >= MAX_ENABLED_VFABRICS){ + IXmlParserPrintError(state, "Unable to allocate Pkey to VF. Pkey table full."); + return; + } + if (assign_pkey(vfs_pkeys, &num_pkey, &candidate_Pkey)!= FSUCCESS) { + IXmlParserPrintError(state, "Unable to allocate Pkey to VF. Pkey table full."); + return; + } + default_Pkey=candidate_Pkey; + } + instancep->vf_config.vf[i]->pkey = MAKE_PKEY(1, default_Pkey); + } // end else + }// end if pkeys are undefined + } // finished assigning pkeys to all VF in config file. + + if (preverify_parse && instancep->sm_config.start) { + render_logger_state = state; + VirtualFabrics_t *vf_config = renderVirtualFabricsConfig(instance, configp, renderVfLoggerError, renderVfLoggerWarning); + if (vf_config) { + releaseVirtualFabricsConfig(vf_config); + } + } + } + // index to next instance + instance++; + return; +} + +// fields within Common "Shared" +static IXML_FIELD CommonSharedFields[] = { + { tag:"Start", format:'k', start_func:NULL, end_func:InvalidOptionParserEnd }, + { tag:"Debug", format:'u', IXML_FIELD_INFO(FMXmlConfig_t, debug) }, + { tag:"RmppDebug", format:'u', IXML_FIELD_INFO(FMXmlConfig_t, debug_rmpp) }, + { tag:"SubnetSize", format:'u', IXML_FIELD_INFO(FMXmlConfig_t, subnet_size) }, + { tag:"StartupRetries", format:'u', IXML_FIELD_INFO(FMXmlConfig_t, startup_retries) }, + { tag:"StartupStableWait", format:'u', IXML_FIELD_INFO(FMXmlConfig_t, startup_stable_wait) }, + { tag:"CoreDumpDir", format:'s', IXML_FIELD_INFO(FMXmlConfig_t, CoreDumpDir) }, + { tag:"CoreDumpLimit", format:'s', IXML_FIELD_INFO(FMXmlConfig_t, CoreDumpLimit) }, + { tag:"SslSecurityEnabled", format:'u', IXML_FIELD_INFO(FMXmlConfig_t, SslSecurityEnabled) }, + { tag:"SslSecurityEnable", format:'u', IXML_FIELD_INFO(FMXmlConfig_t, SslSecurityEnabled) }, +#ifndef __VXWORKS__ + { tag:"SslSecurityDir", format:'s', IXML_FIELD_INFO(FMXmlConfig_t, SslSecurityDir) }, +#endif + { tag:"SslSecurityFmCertificate", format:'s', IXML_FIELD_INFO(FMXmlConfig_t, SslSecurityFmCertificate) }, + { tag:"SslSecurityFmPrivateKey", format:'s', IXML_FIELD_INFO(FMXmlConfig_t, SslSecurityFmPrivateKey) }, + { tag:"SslSecurityFmCaCertificate", format:'s', IXML_FIELD_INFO(FMXmlConfig_t, SslSecurityFmCaCertificate) }, + { tag:"SslSecurityFmCertChainDepth", format:'u', IXML_FIELD_INFO(FMXmlConfig_t, SslSecurityFmCertChainDepth) }, + { tag:"SslSecurityFmDHParameters", format:'s', IXML_FIELD_INFO(FMXmlConfig_t, SslSecurityFmDHParameters) }, + { tag:"SslSecurityFmCaCRLEnabled", format:'u', IXML_FIELD_INFO(FMXmlConfig_t, SslSecurityFmCaCRLEnabled) }, + { tag:"SslSecurityFmCaCRLEnable", format:'u', IXML_FIELD_INFO(FMXmlConfig_t, SslSecurityFmCaCRLEnabled) }, + { tag:"SslSecurityFmCaCRL", format:'s', IXML_FIELD_INFO(FMXmlConfig_t, SslSecurityFmCaCRL) }, + { tag:"Priority", format:'u', IXML_FIELD_INFO(FMXmlConfig_t, priority) }, + { tag:"ElevatedPriority", format:'u', IXML_FIELD_INFO(FMXmlConfig_t, elevated_priority) }, + { tag:"LogLevel", format:'u', IXML_FIELD_INFO(FMXmlConfig_t, log_level) }, + { tag:"LogFile", format:'s', IXML_FIELD_INFO(FMXmlConfig_t, log_file) }, + { tag:"LogMode", format:'u', IXML_FIELD_INFO(FMXmlConfig_t, syslog_mode) }, + { tag:"CS_LogMask", format:'u', IXML_FIELD_INFO(FMXmlConfig_t, log_masks[VIEO_CS_MOD_ID]), end_func:ParamU32XmlParserEnd }, + { tag:"MAI_LogMask", format:'u', IXML_FIELD_INFO(FMXmlConfig_t, log_masks[VIEO_MAI_MOD_ID]), end_func:ParamU32XmlParserEnd }, + { tag:"CAL_LogMask", format:'u', IXML_FIELD_INFO(FMXmlConfig_t, log_masks[VIEO_CAL_MOD_ID]), end_func:ParamU32XmlParserEnd }, + { tag:"DVR_LogMask", format:'u', IXML_FIELD_INFO(FMXmlConfig_t, log_masks[VIEO_DRIVER_MOD_ID]), end_func:ParamU32XmlParserEnd }, + { tag:"IF3_LogMask", format:'u', IXML_FIELD_INFO(FMXmlConfig_t, log_masks[VIEO_IF3_MOD_ID]), end_func:ParamU32XmlParserEnd }, + { tag:"SM_LogMask", format:'u', IXML_FIELD_INFO(FMXmlConfig_t, log_masks[VIEO_SM_MOD_ID]), end_func:ParamU32XmlParserEnd }, + { tag:"SA_LogMask", format:'u', IXML_FIELD_INFO(FMXmlConfig_t, log_masks[VIEO_SA_MOD_ID]), end_func:ParamU32XmlParserEnd }, + { tag:"PM_LogMask", format:'u', IXML_FIELD_INFO(FMXmlConfig_t, log_masks[VIEO_PM_MOD_ID]), end_func:ParamU32XmlParserEnd }, + { tag:"PA_LogMask", format:'u', IXML_FIELD_INFO(FMXmlConfig_t, log_masks[VIEO_PA_MOD_ID]), end_func:ParamU32XmlParserEnd }, + { tag:"BM_LogMask", format:'u', IXML_FIELD_INFO(FMXmlConfig_t, log_masks[VIEO_BM_MOD_ID]), end_func:ParamU32XmlParserEnd }, + { tag:"FE_LogMask", format:'u', IXML_FIELD_INFO(FMXmlConfig_t, log_masks[VIEO_FE_MOD_ID]), end_func:ParamU32XmlParserEnd }, + { tag:"APP_LogMask", format:'u', IXML_FIELD_INFO(FMXmlConfig_t, log_masks[VIEO_APP_MOD_ID]), end_func:ParamU32XmlParserEnd }, + + + { tag:"SyslogFacility", format:'s', IXML_FIELD_INFO(FMXmlConfig_t, syslog_facility) }, + { tag:"ConfigConsistencyCheckLevel", format:'u', IXML_FIELD_INFO(FMXmlConfig_t, config_consistency_check_level) }, + { NULL } +}; + +// Common Shared start tag +static void* CommonSharedXmlParserStart(IXmlParserState_t *state, void *parent, const char **attr) +{ + FMXmlConfig_t *fmp = getXmlMemory(sizeof(FMXmlConfig_t), "FMXmlConfig_t CommonSharedXmlParserStart()"); + + if (xml_parse_debug) + fprintf(stdout, "CommonSharedXmlParserStart instance %u common %u\n", (unsigned int)instance, (unsigned int)common); + + if (!fmp) { + PRINT_MEMORY_ERROR; + return NULL; + } + + // inherit the values of the common Fm + *fmp = configp->fm_instance_common->fm_config; + + return fmp; // will be passed to CommonXmlParserEnd as object +} + +// Common Shared end tag +static void CommonSharedXmlParserEnd(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + FMXmlConfig_t *fmp = (FMXmlConfig_t*)IXmlParserGetField(field, object); + SMXmlConfig_t *smp; + PMXmlConfig_t *pmp; + FEXmlConfig_t *fep; +#ifndef __VXWORKS__ + char facility[256]; +#endif + uint32_t modid; + + if (xml_parse_debug) + fprintf(stdout, "CommonSharedXmlParserEnd instance %u common %u\n", (unsigned int)instance, (unsigned int)common); + + if (!valid) { + fprintf(stderr, "Error processing XML Common Shared tag\n"); + } else { + if (fmp->priority != UNDEFINED_XML32 && fmp->priority > MAX_PRIORITY) { + IXmlParserPrintError(state, "Common Shared Priority must be in the range of 0-15"); + freeXmlMemory(fmp, sizeof(FMXmlConfig_t), "FMXmlConfig_t CommonSharedXmlParserEnd()"); + return; + } + if (fmp->elevated_priority != UNDEFINED_XML32 && fmp->elevated_priority > MAX_PRIORITY) { + IXmlParserPrintError(state, "Common Shared ElevatedPriority must be in the range of 0-15"); + freeXmlMemory(fmp, sizeof(FMXmlConfig_t), "FMXmlConfig_t CommonSharedXmlParserEnd()"); + return; + } + if (strlen(fmp->CoreDumpLimit) && vs_getCoreDumpLimit(fmp->CoreDumpLimit, NULL) < 0) { + IXmlParserPrintError(state, "Invalid Fm CoreDumpLimit: '%s'", fmp->CoreDumpLimit); + freeXmlMemory(fmp, sizeof(FMXmlConfig_t), "FMXmlConfig_t CommonSharedXmlParserEnd()"); + return; + } +#ifndef __VXWORKS__ + if (strlen(fmp->syslog_facility) && getFacility(fmp->syslog_facility, /* test */ 1) < 0) { + IXmlParserPrintError(state, "Common Shared SyslogFacility must be set to one of the following - %s", showFacilities(facility, sizeof(facility))); + freeXmlMemory(fmp, sizeof(FMXmlConfig_t), "FMXmlConfig_t CommonSharedXmlParserEnd()"); + return; + } +#endif + if (fmp->config_consistency_check_level != UNDEFINED_XML32) { + if (fmp->config_consistency_check_level == NO_CHECK_CCC_LEVEL) { + XmlParsePrintWarning("SM ConfigConsistencyCheckLevel = 0 is deprecated. Switched to 1"); + fmp->config_consistency_check_level = CHECK_NO_ACTION_CCC_LEVEL; + } else if (fmp->config_consistency_check_level > CHECK_ACTION_CCC_LEVEL) { + IXmlParserPrintError(state, "Sm ConfigConsistencyCheckLevel must be set to 1 or 2"); + freeXmlMemory(fmp, sizeof(FMXmlConfig_t), "FMXmlConfig_t CommonSharedXmlParserEnd()"); + return; + } + + } + } + + // save in common config + configp->fm_instance_common->fm_config = *fmp; + + // inherit common settings into specific Sm settings + smp = &configp->fm_instance_common->sm_config; + smp->subnet_size = fmp->subnet_size; + smp->debug = fmp->debug; + smp->debug_rmpp = fmp->debug_rmpp; + smp->priority = fmp->priority; + smp->elevated_priority = fmp->elevated_priority; + smp->log_level = fmp->log_level; + StringCopy(smp->CoreDumpLimit, fmp->CoreDumpLimit, STRING_SIZE); + StringCopy(smp->CoreDumpDir, fmp->CoreDumpDir, FILENAME_SIZE); + StringCopy(smp->log_file, fmp->log_file, LOGFILE_SIZE); + smp->syslog_mode = fmp->syslog_mode; + for (modid=0; modid <= VIEO_LAST_MOD_ID; ++modid) + smp->log_masks[modid] = fmp->log_masks[modid]; + StringCopy(smp->syslog_facility, fmp->syslog_facility, STRING_SIZE); + smp->config_consistency_check_level = fmp->config_consistency_check_level; + smp->SslSecurityEnabled = fmp->SslSecurityEnabled; + StringCopy(smp->SslSecurityDir, fmp->SslSecurityDir, sizeof(smp->SslSecurityDir)); + StringCopy(smp->SslSecurityFmCertificate, fmp->SslSecurityFmCertificate, sizeof(smp->SslSecurityFmCertificate)); + StringCopy(smp->SslSecurityFmPrivateKey, fmp->SslSecurityFmPrivateKey, sizeof(smp->SslSecurityFmPrivateKey)); + StringCopy(smp->SslSecurityFmCaCertificate, fmp->SslSecurityFmCaCertificate, sizeof(smp->SslSecurityFmCaCertificate)); + smp->SslSecurityFmCertChainDepth = fmp->SslSecurityFmCertChainDepth; + StringCopy(smp->SslSecurityFmDHParameters, fmp->SslSecurityFmDHParameters, sizeof(smp->SslSecurityFmDHParameters)); + smp->SslSecurityFmCaCRLEnabled = fmp->SslSecurityFmCaCRLEnabled; + StringCopy(smp->SslSecurityFmCaCRL, fmp->SslSecurityFmCaCRL, sizeof(smp->SslSecurityFmCaCRL)); + + // inherit common settings into specific Pm settings + pmp = &configp->fm_instance_common->pm_config; + pmp->subnet_size = fmp->subnet_size; + pmp->debug = fmp->debug; + pmp->debug_rmpp = fmp->debug_rmpp; + pmp->priority = fmp->priority; + pmp->elevated_priority = fmp->elevated_priority; + pmp->log_level = fmp->log_level; + StringCopy(pmp->log_file, fmp->log_file, LOGFILE_SIZE); + pmp->syslog_mode = fmp->syslog_mode; + for (modid=0; modid <= VIEO_LAST_MOD_ID; ++modid) + pmp->log_masks[modid] = fmp->log_masks[modid]; + StringCopy(pmp->syslog_facility, fmp->syslog_facility, STRING_SIZE); + pmp->SslSecurityEnabled = fmp->SslSecurityEnabled; + StringCopy(pmp->SslSecurityDir, fmp->SslSecurityDir, sizeof(pmp->SslSecurityDir)); + StringCopy(pmp->SslSecurityFmCertificate, fmp->SslSecurityFmCertificate, sizeof(pmp->SslSecurityFmCertificate)); + StringCopy(pmp->SslSecurityFmPrivateKey, fmp->SslSecurityFmPrivateKey, sizeof(pmp->SslSecurityFmPrivateKey)); + StringCopy(pmp->SslSecurityFmCaCertificate, fmp->SslSecurityFmCaCertificate, sizeof(pmp->SslSecurityFmCaCertificate)); + pmp->SslSecurityFmCertChainDepth = fmp->SslSecurityFmCertChainDepth; + StringCopy(pmp->SslSecurityFmDHParameters, fmp->SslSecurityFmDHParameters, sizeof(pmp->SslSecurityFmDHParameters)); + pmp->SslSecurityFmCaCRLEnabled = fmp->SslSecurityFmCaCRLEnabled; + StringCopy(pmp->SslSecurityFmCaCRL, fmp->SslSecurityFmCaCRL, sizeof(pmp->SslSecurityFmCaCRL)); + + // inherit common settings into specific Fe settings + fep = &configp->fm_instance_common->fe_config; + fep->subnet_size = fmp->subnet_size; + fep->debug = fmp->debug; + fep->debug_rmpp = fmp->debug_rmpp; + fep->log_level = fmp->log_level; + StringCopy(fep->CoreDumpLimit, fmp->CoreDumpLimit, STRING_SIZE); + StringCopy(fep->CoreDumpDir, fmp->CoreDumpDir, FILENAME_SIZE); + StringCopy(fep->log_file, fmp->log_file, LOGFILE_SIZE); + fep->syslog_mode = fmp->syslog_mode; + for (modid=0; modid <= VIEO_LAST_MOD_ID; ++modid) + fep->log_masks[modid] = fmp->log_masks[modid]; + StringCopy(fep->syslog_facility, fmp->syslog_facility, STRING_SIZE); + fep->SslSecurityEnabled = fmp->SslSecurityEnabled; + StringCopy(fep->SslSecurityDir, fmp->SslSecurityDir, sizeof(fep->SslSecurityDir)); + StringCopy(fep->SslSecurityFmCertificate, fmp->SslSecurityFmCertificate, sizeof(fep->SslSecurityFmCertificate)); + StringCopy(fep->SslSecurityFmPrivateKey, fmp->SslSecurityFmPrivateKey, sizeof(fep->SslSecurityFmPrivateKey)); + StringCopy(fep->SslSecurityFmCaCertificate, fmp->SslSecurityFmCaCertificate, sizeof(fep->SslSecurityFmCaCertificate)); + fep->SslSecurityFmCertChainDepth = fmp->SslSecurityFmCertChainDepth; + StringCopy(fep->SslSecurityFmDHParameters, fmp->SslSecurityFmDHParameters, sizeof(fep->SslSecurityFmDHParameters)); + fep->SslSecurityFmCaCRLEnabled = fmp->SslSecurityFmCaCRLEnabled; + StringCopy(fep->SslSecurityFmCaCRL, fmp->SslSecurityFmCaCRL, sizeof(fep->SslSecurityFmCaCRL)); + + freeXmlMemory(fmp, sizeof(FMXmlConfig_t), "FMXmlConfig_t CommonSharedXmlParserEnd()"); +} + +// fields within "Common" +static IXML_FIELD CommonFields[] = { + { tag:"Shared", format:'K', subfields:CommonSharedFields, start_func:CommonSharedXmlParserStart, end_func:CommonSharedXmlParserEnd }, + { tag:"Sm", format:'K', subfields:SmFields, start_func:SmXmlParserStart, end_func:SmXmlParserEnd }, + { tag:"Fe", format:'K', subfields:FeFields, start_func:FeXmlParserStart, end_func:FeXmlParserEnd }, + { tag:"Pm", format:'K', subfields:PmFields, start_func:PmXmlParserStart, end_func:PmXmlParserEnd }, + + + { tag:"Applications", format:'k', subfields:VfsAppFields, start_func:VfsAppXmlParserStart, end_func:VfsAppXmlParserEnd }, + { tag:"DeviceGroups", format:'k', subfields:VfsGroupsFields, start_func:VfsGroupsXmlParserStart, end_func:VfsGroupsXmlParserEnd }, + { tag:"VirtualFabrics", format:'k', subfields:VfsFields, start_func:VfsXmlParserStart, end_func:VfsXmlParserEnd }, + { tag:"QOSGroups", format:'k', subfields:QOSGroupsFields, start_func:QOSGroupsXmlParserStart, end_func:QOSGroupsXmlParserEnd}, + { tag:"PmPortGroups", format:'k', subfields:PmPgsFields, start_func:PmPgsXmlParserStart, end_func:PmPgsXmlParserEnd }, + { NULL } +}; + +// Common Shared start tag +static void* CommonXmlParserStart(IXmlParserState_t *state, void *parent, const char **attr) +{ + common = 1; // all parsing is for Common now + return configp->fm_instance_common; +} + +// Common Shared end tag +static void CommonXmlParserEnd(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + if (!valid) { + fprintf(stderr, "Error processing XML Common tag\n"); + } +} + +static IXML_FIELD XmlDebugFields[] = { + { tag:"All", format:'u', IXML_FIELD_INFO(XmlDebug_t, xml_all_debug) }, + { tag:"Vf", format:'u', IXML_FIELD_INFO(XmlDebug_t, xml_vf_debug) }, + { tag:"Sm", format:'u', IXML_FIELD_INFO(XmlDebug_t, xml_sm_debug) }, + { tag:"Fe", format:'u', IXML_FIELD_INFO(XmlDebug_t, xml_fe_debug) }, + { tag:"Pm", format:'u', IXML_FIELD_INFO(XmlDebug_t, xml_pm_debug) }, + { tag:"Parse", format:'u', IXML_FIELD_INFO(XmlDebug_t, xml_parse_debug) }, + { NULL } +}; + +// XML Debug start tag +static void *XmlDebugParserStart(IXmlParserState_t *state, void *parent, const char **attr) +{ + XmlDebug_t *xdp = getXmlMemory(sizeof(XmlDebug_t), "XmlDebug_t XmlDebugParserStart()"); + + if (!xdp) { + PRINT_MEMORY_ERROR; + return NULL; + } + memset(xdp, 0, sizeof(XmlDebug_t)); + return xdp; +} + +// XML Debug end tag +static void XmlDebugParserEnd(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + XmlDebug_t *xdp = (XmlDebug_t*)IXmlParserGetField(field, object); + +#ifdef XML_DEBUG + xdp->xml_all_debug = 1; +#endif + + if (xdp->xml_all_debug) { + xdp->xml_vf_debug = 1; + xdp->xml_sm_debug = 1; + xdp->xml_fe_debug = 1; + xdp->xml_pm_debug = 1; + xdp->xml_parse_debug = 1; + } + configp->xmlDebug = *xdp; + xml_vf_debug = xdp->xml_vf_debug; + xml_sm_debug = xdp->xml_sm_debug; + xml_fe_debug = xdp->xml_fe_debug; + xml_pm_debug = xdp->xml_pm_debug; + xml_parse_debug = xdp->xml_parse_debug; + + freeXmlMemory(xdp, sizeof(XmlDebug_t), "XmlDebug_t XmlDebugParserEnd()"); +} + +static IXML_FIELD ConfigFields[] = { + { tag:"XmlDebug", format:'k', subfields:XmlDebugFields, start_func:XmlDebugParserStart, end_func:XmlDebugParserEnd }, + { tag:"Common", format:'K', subfields:CommonFields, start_func:CommonXmlParserStart, end_func:CommonXmlParserEnd }, + { tag:"Fm", format:'K', subfields:FmFields, start_func:FmXmlParserStart, end_func:FmXmlParserEnd }, + { NULL } +}; + +// Config start tag +static void *ConfigXmlParserStart(IXmlParserState_t *state, void *parent, const char **attr) +{ + return NULL; // no need for parent tag +} + +// Config end tag +static void ConfigXmlParserEnd(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + if (!valid) { + fprintf(stderr, "Error processing XML Config tag\n"); + } else { + // as needed process or validate self consistency of config + } + +} + +// top level tag +static IXML_FIELD TopLevelFields[] = { + { tag:"Config", format:'K', subfields:ConfigFields, start_func:ConfigXmlParserStart, end_func:ConfigXmlParserEnd }, + { NULL } +}; + +// print debug info +void printXmlDebug(FMXmlCompositeConfig_t *config, uint32_t fm) +{ + unsigned int i, j; + cl_map_item_t *cl_map_item; + uint32_t qos_idx; + + // render config data into internal application structure + VirtualFabrics_t *test = renderVirtualFabricsConfig(fm, config, NULL, NULL); + + fprintf(stdout, "Printing out the test VF configuration for FM %u from printXmlDebug()\n", (unsigned int)fm); + + // if it failed get out of here + if (!test) { + fprintf(stdout, "Test Virtual Fabric could not be created\n"); + return; + } + + for (i = 0; i < test->number_of_vfs_all; i++) { + if (test->v_fabric_all[i].standby) continue; + qos_idx = test->v_fabric_all[i].qos_index; + + fprintf(stdout, "VF %u name %s\n", i, test->v_fabric_all[i].name); + fprintf(stdout, "VF %u index %u\n", i, (unsigned int)test->v_fabric_all[i].index); + fprintf(stdout, "VF %u pkey 0x%x\n", i, (unsigned int)test->v_fabric_all[i].pkey); + fprintf(stdout, "VF %u security %u\n", i, test->v_fabric_all[i].security); + fprintf(stdout, "VF %u qos_index %u\n", i, test->v_fabric_all[i].qos_index); + fprintf(stdout, "VF %u flowControlDisable %u\n", i, test->qos_all[qos_idx].flowControlDisable); + fprintf(stdout, "VF %u max_mtu_int %u\n", i, test->v_fabric_all[i].max_mtu_int); + fprintf(stdout, "VF %u max_rate_int %u\n", i, test->v_fabric_all[i].max_rate_int); + + fprintf(stdout, "VF %u app select_sa %u\n", i, test->v_fabric_all[i].apps.select_sa); + fprintf(stdout, "VF %u app select_unmatched_sid %u\n", i, test->v_fabric_all[i].apps.select_unmatched_sid); + fprintf(stdout, "VF %u app select_unmatched_mgid %u\n", i, test->v_fabric_all[i].apps.select_unmatched_mgid); + fprintf(stdout, "VF %u app select_pm %u\n", i, test->v_fabric_all[i].apps.select_pm); + + + fprintf(stdout, "VF %u app sidMapSize %u\n", i, (unsigned int)test->v_fabric_all[i].apps.sidMapSize); + VFAppSid_t *sid; + for_all_qmap_ptr(&test->v_fabric_all[i].apps.sidMap, cl_map_item, sid) { + fprintf(stdout, "VF %u app service_id 0x%16.16llx\n", i, + (long long unsigned int)sid->service_id); + fprintf(stdout, "VF %u app service_id_last 0x%16.16llx\n", i, + (long long unsigned int)sid->service_id_last); + fprintf(stdout, "VF %u app service_id_mask 0x%16.16llx\n", i, + (long long unsigned int)sid->service_id_mask); + } + + fprintf(stdout, "VF %u app mgidMapSize %u\n", i, (unsigned int)test->v_fabric_all[i].apps.mgidMapSize); + VFAppMgid_t *mgid; + for_all_qmap_ptr(&test->v_fabric_all[i].apps.mgidMap, cl_map_item, mgid) { + mgid = XML_QMAP_VOID_CAST cl_qmap_key(cl_map_item); + fprintf(stdout, "VF %u app mgid 0x%16.16llx:0x%16.16llx\n", i, + (long long unsigned int)mgid->mgid[0], (long long unsigned int)mgid->mgid[1]); + fprintf(stdout, "VF %u app mgid_last 0x%16.16llx:0x%16.16llx\n", i, + (long long unsigned int)mgid->mgid_last[0], (long long unsigned int)mgid->mgid_last[1]); + fprintf(stdout, "VF %u app mgid_mask 0x%16.16llx:0x%16.16llx\n", i, + (long long unsigned int)mgid->mgid_mask[0], (long long unsigned int)mgid->mgid_mask[1]); + } + + + for(j = 0; j < test->v_fabric_all[i].number_of_full_members; j++) { + fprintf(stdout, "VF %u full_member[%u]: DeviceGroup(%u): %s\n", i, j, test->v_fabric_all[i].full_member[j].dg_index, + test->v_fabric_all[i].full_member[j].member); + } + + for(j = 0; j < test->v_fabric_all[i].number_of_limited_members; j++) { + fprintf(stdout, "VF %u limited_member[%u]: DeviceGroup(%u): %s\n", i, j, test->v_fabric_all[i].limited_member[j].dg_index, + test->v_fabric_all[i].limited_member[j].member); + } + + fprintf(stdout, "VF %u number of multicast_groups %u\n", i, + (unsigned int)test->v_fabric_all[i].number_of_default_groups); + VFDg_t *default_group = test->v_fabric_all[i].default_group; + uint32_t index = 0; + while (default_group) { + fprintf(stdout, "VF %u multicast_group %u def_mc_create %u\n", i, (unsigned int)index, default_group->def_mc_create); + fprintf(stdout, "VF %u multicast_group %u def_mc_pkey 0x%x\n", i, (unsigned int)index, (unsigned int)default_group->def_mc_pkey); + fprintf(stdout, "VF %u multicast_group %u def_mc_mtu_int %u\n", i, (unsigned int)index, default_group->def_mc_mtu_int); + fprintf(stdout, "VF %u multicast_group %u def_mc_rate_int %u\n", i, (unsigned int)index, default_group->def_mc_rate_int); + fprintf(stdout, "VF %u multicast_group %u def_mc_sl %u\n", i, (unsigned int)index, (unsigned int)default_group->def_mc_sl); + fprintf(stdout, "VF %u multicast_group %u def_mc_qkey %u\n", i, (unsigned int)index, (unsigned int)default_group->def_mc_qkey); + fprintf(stdout, "VF %u multicast_group %u def_mc_fl %u\n", i, (unsigned int)index, (unsigned int)default_group->def_mc_fl); + fprintf(stdout, "VF %u multicast_group %u def_mc_tc %u\n", i, (unsigned int)index, (unsigned int)default_group->def_mc_tc); + + fprintf(stdout, "VF %u multicast_group %u mgidMapSize %u\n", i, (unsigned int)index, (unsigned int)default_group->mgidMapSize); + VFAppMgid_t *mgid; + for_all_qmap_ptr(&default_group->mgidMap, cl_map_item, mgid) { + fprintf(stdout, "VF %u multicast_group %u mgid 0x%16.16llx:0x%16.16llx\n", i, (unsigned int)index, + (long long unsigned int)mgid->mgid[0], (long long unsigned int)mgid->mgid[1]); + fprintf(stdout, "VF %u multicast_group %u mgid_last 0x%16.16llx:0x%16.16llx\n", i, (unsigned int)index, + (long long unsigned int)mgid->mgid_last[0], (long long unsigned int)mgid->mgid_last[1]); + fprintf(stdout, "VF %u multicast_group %u mgid_mask 0x%16.16llx:0x%16.16llx\n", i, (unsigned int)index, + (long long unsigned int)mgid->mgid_mask[0], (long long unsigned int)mgid->mgid_mask[1]); + } + default_group = default_group->next_default_group; + index++; + } + fprintf(stdout, "VF %u Checksum %u\n", i, (unsigned int)test->v_fabric_all[i].consistency_checksum); + } + + fprintf(stdout, "VF database Checksum %u\n", (unsigned int)test->consistency_checksum); + + // free memory from test + if (test != NULL) { + releaseVirtualFabricsConfig(test); + test = NULL; + } +} + +#ifdef __VXWORKS__ +void* getParserMemory(size_t size) +{ + void* memory; + memory = getXmlMemory((uint32_t)size, "getParserMemory()"); + + if (memory == NULL) + return NULL; + + memset(memory, 0, size); + + return memory; +} + +void* reallocParserMemory(void* ptr, size_t size) +{ + freeXmlMemory(ptr, 0, "freeParserMemory()"); + return getXmlMemory((uint32_t)size, "getParserMemory()"); +} + +void freeParserMemory(void* ptr) +{ + return freeXmlMemory(ptr, 0, "freeParserMemory()"); +} +#endif + +// main parser +FSTATUS XmlParseFmConfig(const char *input_file, IXmlParserFlags_t flags) +{ +#ifdef XML_TEST + return IXmlParseInputFile(input_file, flags, TopLevelFields, NULL, NULL, NULL, NULL, NULL, NULL); +#else +#ifndef __VXWORKS__ + return IXmlParseInputFile(input_file, flags, TopLevelFields, NULL, NULL, XmlParsePrintError, XmlParsePrintWarning, NULL, NULL); +#else + XML_Memory_Handling_Suite memsuite; + memsuite.malloc_fcn = &getParserMemory; + memsuite.realloc_fcn = &reallocParserMemory; + memsuite.free_fcn = &freeParserMemory; + return IXmlParseInputFile(input_file, flags, TopLevelFields, NULL, NULL, XmlParsePrintError, XmlParsePrintWarning, NULL, NULL, &memsuite); +#endif +#endif +} + +// initialize memory get function for parsing XML +void initXmlPoolGetCallback(void *function) +{ + get_memory = function; +} + +// initialize memory free function +void initXmlPoolFreeCallback(void *function) +{ + free_memory = function; +} + +#ifdef __VXWORKS__ +// generate default XML configuration file +int generateDefaultXmlConfig(uint8_t cli) +{ + + scpInProcess = 1; + + /* check for XML reset from CLI and previous default XML file name */ + if (cli && FileExists(IFS_FM_CFG_NAME_OLD)) { + /* remove old default XML filename */ + FileRemove(IFS_FM_CFG_NAME_OLD); + //sysPrintf("[%s] removed %s \n",__FUNCTION__,IFS_FM_CFG_NAME_OLD); + } + + if (!FileExists(IFS_FM_CFG_NAME)) { + + /* check for previous default XML file name */ + if (FileExists(IFS_FM_CFG_NAME_OLD)) { + /* make a copy of existing XML config file, use new name */ + //sysPrintf("[%s] making copy of %s \n",__FUNCTION__,IFS_FM_CFG_NAME_OLD); + if (copyFile( IFS_FM_CFG_NAME_OLD, IFS_FM_CFG_NAME, 0,NULL)) + XmlParsePrintError("Error duplicating old XML config file"); + } + else { + /* generate the XML config from the embedded default file in xml_data array */ + sysPrintf("[%s] generate default %s\n",__FUNCTION__,IFS_FM_CFG_NAME); + FileRemove(IFS_FM_CFG_NAME_UNCOMPRESSED); + if (FileWriteBin( IFS_FM_CFG_NAME_UNCOMPRESSED, xml_data, sizeof(xml_data)) != sizeof(xml_data)) { + scpInProcess = 0; + XmlParsePrintError("Error generating XML config file"); + return -1; + } + if (copyFile(IFS_FM_CFG_NAME_UNCOMPRESSED, IFS_FM_CFG_NAME, -1,NULL)) { + scpInProcess = 0; + XmlParsePrintError("Error copying generated XML config file"); + remove(IFS_FM_CFG_NAME_UNCOMPRESSED); + return -1; + } + } + + // mirror the XML file to remote CPU - if this is not a multi-CPU system then + // the call will simply return without doing any mirroring +#if defined(__VXWORKS__) + if (cli) + cmuRed_cfgIfMasterSyncSlave(NULL); +#endif + } + + scpInProcess = 0; + return 0; +} + +#endif + +// call entry point for parsing the opafm.xml configuration file - will +// return data in FMXmlCompositeConfig_t struct +FMXmlCompositeConfig_t* parseFmConfig(char *filename, uint32_t flags, uint32_t fm, uint32_t full, uint32_t preverify, uint32_t embedded) +{ + uint32_t i; + + if (!filename || strlen(filename) == 0) + filename = IFS_FM_CFG_NAME; + + if (parsingInProcess) { + fprintf(stdout, "Unable to parse XML file while another parse in in progress\n"); + return NULL; + } + + parsingInProcess = 1; + embedded_call = embedded; + +#ifdef __VXWORKS__ + FILE *aFile; + i = 100; + while (i) { + aFile = fopen( IFS_FM_CFG_NAME_NEW, "r"); + if (aFile != NULL) { + if (i == 100) + fprintf(stdout, "Temporary file %s encountered - waiting to parse %s\n", IFS_FM_CFG_NAME_NEW, IFS_FM_CFG_NAME); + fclose(aFile); + vs_thread_sleep(1000000); + i--; + } else { + break; + } + } + + // generate a default if need be + if (generateDefaultXmlConfig( /* not a cli command */ 0)) { + fprintf(stdout, "Unable to parse XML file since a default file cannot be generated\n"); + return NULL; + } +#endif + + // clear the memory counter + memory = 0; + + // calculate memory limit + memory_limit = xml_compute_pool_size(full); + + if (xml_memory_debug) { + fprintf(stdout, "Memory level %u before parseFmConfig()\n", (unsigned int)memory); + } + + // get memory for composite struct + configp = getXmlMemory(sizeof(FMXmlCompositeConfig_t), "FMXmlCompositeConfig_t parseFmConfig()"); + if (!configp) { + fprintf(stdout, OUT_OF_MEMORY_RETURN); + parsingInProcess = 0; + return NULL; + } + + // get memory for common Fm instance if we are doing a full parse + configp->fm_instance_common = getXmlMemory(sizeof(FMXmlInstance_t), "FMXmlInstance_t parseFmConfig()"); + if (!configp->fm_instance_common) { + fprintf(stdout, OUT_OF_MEMORY_RETURN); + goto failure; + } + + // set instance info - if called with full then data for all FM instances will be + // returned in data structure pointed to by the FMXmlCompositeConfig_t* + full_parse = full; + preverify_parse = preverify; + if (!full_parse) { + fm_instance = fm; + end_instance = fm + 1; + } else { + fm_instance = 0; + end_instance = MAX_INSTANCES; + } + + for (i = 0; i < MAX_INSTANCES; i++) + configp->fm_instance[i] = NULL; + + // if we are not doing a full parse then the common instance can become the same as the single instance + // we are parsing + if (!full) + configp->fm_instance[fm] = configp->fm_instance_common; + + // init config + xmlInitConfig(); + + // parse opafm.xml file + if (xml_parse_debug) + fprintf(stdout, "\nParsing %s...\n", filename); + + if (FSUCCESS != XmlParseFmConfig(filename, (IXmlParserFlags_t)flags)) { + if (xml_parse_debug) + fprintf(stdout, "\nParsing %s failed\n", filename); + goto failure; + } + configp->num_instances = instance; + + // print out some debug info + if (xml_parse_debug || xml_vf_debug) + printXmlDebug(configp, fm); + + if (xml_memory_debug) + fprintf(stdout, "Memory level %u after parseFmConfig()\n", (unsigned int)memory); + + parsingInProcess = 0; + return configp; +failure: + releaseXmlConfig(configp, /* full */ 1); + configp = NULL; + parsingInProcess = 0; + return NULL; +} + +#ifdef __VXWORKS__ +// call from CLI to verify XML config file +// return codes +// 0 Ok +// 1 Parse error - do a logShow to see error +// 2 SM is busy doing a sweep +// 3 File does not exist +// 4 Cannot get memory to parse +// 5 Bad pointer to filename +uint8_t +verifyFmConfig(char* filename, uint32_t flags) +{ + FMXmlCompositeConfig_t* verify; + FILE* cFile; + + if (filename == NULL) + return 5; + + if (parsingInProcess) { + if (xml_parse_debug) + fprintf(stdout, "Cannot verify configuration file %s when the parser is busy parsing another file\n", filename); + return 2; + } + + // verify existance of filename if backup + cFile = fopen(filename, "r"); + if (cFile == NULL) { + fprintf(stdout, "XML configuration file %s not found in verifyFmConfig()\n", filename); + return 3; + } + fclose(cFile); + + // if we are in the Discovery state then do not allow verification and rejest + if (get_memory && sm_state == SM_STATE_DISCOVERING) { + if (xml_parse_debug) + fprintf(stdout, "Cannot verify configuration file %s when Subnet Manager is changing state\n", filename); + return 2; + } + + // for now the only file to verify is the one in /rfa1 + verify = parseFmConfig(filename, (IXmlParserFlags_t)flags, 0, /* full */ 0, /* preverify */ 1, /* embedded */ 1); + + // verification failed if a valid FMXmlCompositeConfig_t pointer was not + if (verify == NULL) + return 1; + + // release memory and destroy memory pool + releaseXmlConfig(verify, /* full */ 1); + + return 0; +} + +int copyPEMFile(char *src, char *pem_filename) { + char fn[64]; + + /* copy new file replacing old one */ + snprintf(fn, sizeof(fn),"%s/%s.pem", DIR_BASE_NAME, pem_filename); + if (vcopy(src, fn, FALSE) != OK) { + sysPrintf("%s %d vcopy %s to %s failed\n", __FUNCTION__, __LINE__, src, fn); + updateLastScpRetCode(SCP_FF_ERR_XML_UPDATE); + rm(src); + return 0; + } + + // mirror the XML file to remote CPU - if this is not a multi-CPU system then + // the call will simply return without doing any mirroring +#if defined(__VXWORKS__) + cmuRed_cfgIfMasterSyncSlavePEM(pem_filename); +#endif + + rm(src); + updateLastScpRetCode(SCP_FF_ERR_OK); + SCP_LOG( "Copy file %s to %s successful.", src, fn); + return 1; +} + +/*********************************** + +This function will: + 1 - copy (src) [/firmware/opafm.xml] file to compressed file + [/firmware/temp.xml.z] + 2 - check max compressed file size limit + 2a - If file size too big, reove both files + 3 - verify XML config file. If invalid remove both files + 4 - if ok, copy file to flash [//opafm.xml.z]. + 5 - remove src file + +*************************/ +int copyCompressXMLConfigFile(char *src, char *dst_unused_param) { + long fileSize=0; + uint8_t ret; + + if (parsingInProcess) { + XmlParsePrintError("scp: unable to compress XML config file while parser is in the process of parsing a file already"); + updateLastScpRetCode(SCP_FF_ERR_XML_UPDATE); + sysPrintf ("scp:Unable to compress into %s while parser is in the process of parsing a file already\n",IFS_FM_CFG_NAME_TEMP); + return 0; + } + + scpInProcess = 1; + + if (copyFile(src, IFS_FM_CFG_NAME_TEMP,-1,&fileSize)) { + XmlParsePrintError("scp: unable to compress XML config file"); + updateLastScpRetCode(SCP_FF_ERR_XML_UPDATE); + sysPrintf ("scp:Unable to compress into %s\n", IFS_FM_CFG_NAME_TEMP); + rm(src); + scpInProcess = 0; + return 0; + } + if (fileSize>MAX_XML_COMPRESSED_FILE_SIZE) { + XmlParsePrintError("scp: compressed XML config file exceeds max size"); + updateLastScpRetCode(SCP_FF_ERR_XML_UPDATE); + sysPrintf ("scp:Compressed file size exceeds limit of %ld\n",MAX_XML_COMPRESSED_FILE_SIZE); + rm(src); + rm(IFS_FM_CFG_NAME_TEMP); + scpInProcess = 0; + return 0; + } + + ret=verifyFmConfig( IFS_FM_CFG_NAME_TEMP, 0); + if (!ret) { + SCP_LOG( "XML parsed ok!"); + } else { + XmlParsePrintError("scp: Invalid XML config file!"); + updateLastScpRetCode(SCP_FF_ERR_XML_UPDATE); + sysPrintf("scp: Invalid XML config file!\n"); + rm(src); + rm(IFS_FM_CFG_NAME_TEMP); + scpInProcess = 0; + return 0; + } + + SCP_LOG( "Removing old config file %s.",IFS_FM_CFG_NAME); + rm(IFS_FM_CFG_NAME); + + SCP_LOG( "copying over %s to %s.",IFS_FM_CFG_NAME_TEMP, IFS_FM_CFG_NAME); + if (copyFile( IFS_FM_CFG_NAME_TEMP, IFS_FM_CFG_NAME, 0,NULL)) { + XmlParsePrintError("scp: unable to copy compressed XML config file to destination"); + updateLastScpRetCode(SCP_FF_ERR_XML_UPDATE); + sysPrintf("scp:Unable to copy %s to %s\n", IFS_FM_CFG_NAME_TEMP, IFS_FM_CFG_NAME); + rm(src); + rm(IFS_FM_CFG_NAME_TEMP); + scpInProcess = 0; + return 0; + } + + ret=verifyFmConfig( IFS_FM_CFG_NAME, 0); + if (!ret) { + SCP_LOG( "XML parsed ok on second pass!"); + } else { + XmlParsePrintError("scp: Invalid XML new config file on second pass!"); + updateLastScpRetCode(SCP_FF_ERR_XML_UPDATE); + sysPrintf("scp: Invalid XML new config file in second pass!\n"); + rm(src); + rm(IFS_FM_CFG_NAME_TEMP); + rm(IFS_FM_CFG_NAME); + scpInProcess = 0; + return 0; + } + + rm(src); + rm(IFS_FM_CFG_NAME_TEMP); + + // mirror the XML file to remote CPU - if this is not a multi-CPU system then + // the call will simply return without doing any mirroring +#if defined(__VXWORKS__) + cmuRed_cfgIfMasterSyncSlave(NULL); +#endif + + updateLastScpRetCode(SCP_FF_ERR_OK); + + scpInProcess = 0; + + return 1; // no errors encountered +} + +// are we in the process of SCP'ing an XML config ? +uint32_t scpXmlInProcess(void) { + return scpInProcess; +} + +#endif + +#ifdef XML_TEST + +int main() +{ + FMXmlCompositeConfig_t config; + + fprintf(stdout, "Address of config = %x\n", (uint)&g_config); + + parseFmConfig(&config, IFS_FM_CFG_NAME, IXML_PARSER_FLAG_NONE, 0, /* full */ 1, /* preverify */ 1, /* embedded */ 0 ); + printXmlDebug(&config, 0); + + exit(0); +} +#endif + +static boolean verifyrange (uint64_t mgidRangeInitH, uint64_t mgidRangeInitL, uint64_t mgidRangeLastH, uint64_t mgidRangeLastL, + uint64_t mcgidH, uint64_t mcgidL) +{ + //check upper limit + if (mgidRangeLastH < mcgidH) + return FALSE; + else if (mgidRangeLastH == mcgidH) { + if (mcgidL > mgidRangeLastL) + return FALSE; + } + //check lower limit + if (mgidRangeInitH < mcgidH) + return TRUE; + else { + if (mgidRangeInitH == mcgidH) { + if (mcgidL < mgidRangeInitL) + return FALSE; + else return TRUE; + } + else return FALSE; + } +} + +static boolean checkMC_VFProperties (SMMcastDefGrp_t *mcp, VirtualFabrics_t *v_fabricp, int vf) +{ + VF_t *v_fp = &v_fabricp->v_fabric_all[vf]; + + + // check the VirtualFabric name + if (strlen(mcp->virtual_fabric) > 0 && strncmp(mcp->virtual_fabric, v_fp->name, sizeof(mcp->virtual_fabric)) != 0) { + return FALSE; + } + + //check pkey + if (mcp->def_mc_pkey != UNDEFINED_XML32 && v_fp->pkey != UNDEFINED_XML32 && + PKEY_VALUE(mcp->def_mc_pkey) != PKEY_VALUE(v_fp->pkey)) { + return FALSE; + } + + //check MTU + if (GetBytesFromMtu(mcp->def_mc_mtu_int) > GetBytesFromMtu(v_fp->max_mtu_int)) + return FALSE; + + // check rate + if (IbStaticRateToMbps(mcp->def_mc_rate_int) > IbStaticRateToMbps(v_fp->max_rate_int)){ + return FALSE; + } + // Check the SL's are the same + if (mcp->def_mc_sl != UNDEFINED_XML8) { + if (v_fabricp->qos_all[v_fp->qos_index].qos_enable != 0) { + if (v_fabricp->qos_all[v_fp->qos_index].mcast_sl != UNDEFINED_XML8) { + if (mcp->def_mc_sl != v_fabricp->qos_all[v_fp->qos_index].mcast_sl) + return FALSE; + } + else if (mcp->def_mc_sl != v_fabricp->qos_all[v_fp->qos_index].base_sl) + return FALSE; + } + else + return FALSE; + } + return TRUE; +} + +static boolean searchMgidsThruAppsinVF (VF_t *vf_p, uint64_t mcgidh, uint64_t mcgidl) +{ + int mgidsV = 0; + VFAppMgid_t *mgidp; + cl_map_item_t *cl_map_item; + + // searching through mgids in applications of this VF + for_all_qmap_ptr(&vf_p->apps.mgidMap, cl_map_item, mgidp) { + //if there is a mask + if ((mgidp->mgid_mask[0] != 0xFFFFFFFFFFFFFFFFULL) || (mgidp->mgid_mask[1] != 0xFFFFFFFFFFFFFFFFULL)) { + if (((mgidp->mgid[0] == (mcgidh & mgidp->mgid_mask[0]))) && + ((mgidp->mgid[1] == (mcgidl & mgidp->mgid_mask[1])))) + mgidsV++; + }//if there is a range + else if ((mgidp->mgid_last[0] != 0) || (mgidp->mgid_last[1] != 0)) { + if (verifyrange(mgidp->mgid[0], mgidp->mgid[1], mgidp->mgid_last[0], mgidp->mgid_last [1],mcgidh, mcgidl)) + mgidsV++; + }//if there is a single value + else if ((mgidp->mgid[0] == mcgidh) && (mgidp->mgid[1] == mcgidl)) + mgidsV++; + } + + if (mgidsV > 0) + return TRUE; + else + return FALSE; +} + +boolean PreCreateMCGroup (SMMcastDefGrp_t *mdgp, VirtualFabrics_t *matched_vfp, uint32_t vf) +{ + // create default group + VFDg_t *dgip, *dgi; + // go ahead and build the default group info + VFAppMgid_t *mgidp; + VF_t * matched_vf = &matched_vfp->v_fabric_all[vf]; + dgip = getDMCG(); /// type VFDg_t + if (!dgip) { + return FALSE; + } + + dgip->def_mc_create = mdgp->def_mc_create; + +// UNDEFINED_32XML were filled with default values before + uint32_t pkey = MAKE_PKEY(1, matched_vf->pkey); + dgip->def_mc_pkey = pkey; + dgip->def_mc_mtu_int = mdgp->def_mc_mtu_int; + dgip->def_mc_rate_int = mdgp->def_mc_rate_int; + dgip->def_mc_sl = mdgp->def_mc_sl; // assignment of SL, if undefined, will + // be taken care later by the SM + dgip->def_mc_qkey = mdgp->def_mc_qkey; + dgip->def_mc_fl = mdgp->def_mc_fl; + dgip->def_mc_tc = mdgp->def_mc_tc; + + + // add all of the individual MGID's to the list + uint32_t entry; + for (entry = 0; (entry < mdgp->number_of_mgids && mdgp->number_of_mgids <= MAX_VFABRIC_DG_MGIDS); entry++) { + mgidp = getAppMgid(); + if (!mgidp) { + freeDMCG(dgip); + return FALSE; // + } + + // since this is an individual MGID ID then set it up appropriately + verifyAndConvertMGidString(mdgp->mgid[entry].mgid, mgidp); + + // if first one on list then place at head + if (addMap(&dgip->mgidMap, XML_QMAP_U64_CAST mgidp)) { + dgip->mgidMapSize++; + } else { + freeAppMgid(mgidp); + } + } + + /* If not first Default Group Append to List */ + if (matched_vf->default_group) { + /* Get Tail Default Group */ + for (dgi = matched_vf->default_group; dgi->next_default_group; dgi = dgi->next_default_group); + /* Append to Tail of Default Group List */ + dgi->next_default_group = dgip; + } else { + matched_vf->default_group = dgip; + } + + matched_vf->number_of_default_groups++; + return TRUE; +} + +// MatchExplicitMGIDtoVF() +// +// Called by reRenderVirtualFabricsConfig() prior to its cloneVF() loop: +// (caller specifies update_active_vfabrics=FALSE) +// (if matching VF found, this function updates the corresponding +// v_fabric_all[] default group list) +// Called by renderVirtualEthernetsConfig after reRenderVirtualFabricsConfig(): +// (caller specifies update_active_vfabrics=TRUE) +// (if matching VF found, updates the corresponding v_fabric_all[] AND +// v_fabric_all[] default group lists). +FSTATUS MatchExplicitMGIDtoVF (SMMcastDefGrp_t *mdgp, VirtualFabrics_t *v_fabricp, boolean update_active_vfabrics, int enforceVFPathRecs) +// now we need to associate a Multicast Group with a VirtualFabric +{ uint32_t number_of_vfs = 0; + uint32_t mg,i,j; + int vf = -1; + int matched_vf[MAX_ENABLED_VFABRICS] = {0}; + uint64 mcgid[2]; + boolean matchedAllMgids = TRUE; + + // all fabrics that get here are enabled (include Active and Standby) + for (i=0; i < v_fabricp->number_of_vfs_all && i < MAX_ENABLED_VFABRICS; i++) { + if (!checkMC_VFProperties(mdgp, v_fabricp,i)) + continue; + matchedAllMgids = TRUE; + for (mg = 0; (mg < mdgp->number_of_mgids && mdgp->number_of_mgids <= MAX_VFABRIC_DG_MGIDS); mg++) { + StringToGid(&mcgid[0], &mcgid[1], mdgp->mgid[mg].mgid, NULL, TRUE); + //verify MGID matching by Application otherwise check unmatched + // search for the applications that are in the VF + // there is none >> fail config + if (searchMgidsThruAppsinVF(&v_fabricp->v_fabric_all[i], mcgid[0], mcgid[1])) + continue; + else if (v_fabricp->v_fabric_all[i].apps.select_unmatched_mgid){ + //check if no other VF contains the application gid + boolean matchedOtherVF=FALSE; + for (j=0; j < v_fabricp->number_of_vfs_all && j < MAX_ENABLED_VFABRICS; j++) { + if (i==j) continue; + if (searchMgidsThruAppsinVF(&v_fabricp->v_fabric_all[j], mcgid[0], mcgid[1])) { + matchedOtherVF=TRUE; + break; + } + } + if (matchedOtherVF) { + matchedAllMgids=FALSE; + break; + } + } + else { + matchedAllMgids=FALSE; + break; + } + } + if (matchedAllMgids) { + matched_vf[i] = 1; + number_of_vfs++; + if (vf == -1) vf = i; // Shortcut for later, save first matching VF. + } + }// end of searching for a single VF to match a MC group for explicit groups + + if (enforceVFPathRecs && number_of_vfs > 1) { // if more than one fail config + return FINVALID_STATE; + } + + if (number_of_vfs == 0) {// if not matched then fail + return FNOT_FOUND; + } + + /* This snippet below will copy the McGroups to all VFs that match. + However, note that the if check above that checks if the number of matching VFs + is more than 1. This check above makes sure that current behavior of one VF + per McGroup is maintained unless enforceVFPathRecs is false, by which multiple + VFs can then match an McGroup. */ + for (; vf < v_fabricp->number_of_vfs_all && vf < MAX_ENABLED_VFABRICS && number_of_vfs > 0; ++vf) { + if (matched_vf[vf] != 0) { + // If this is the first time creating this group + if (!PreCreateMCGroup(mdgp, v_fabricp, vf)) { + return FUNAVAILABLE; + } + --number_of_vfs; + } + } + return FSUCCESS; +}// end of MatchExplicitGIDtoVF + +static boolean FindApp(VirtualFabrics_t *v_fabp, VF_t *v_fab, uint64_t mgh, uint64_t mgl) +{ + boolean matchedMgids=TRUE; + int k; + + if (searchMgidsThruAppsinVF(v_fab, mgh,mgl)) { + return matchedMgids; + } + else if (v_fab->apps.select_unmatched_mgid){ + //check if no other VF contains the application gid + boolean matchedOtherVF=FALSE; + for (k=0; k < v_fabp->number_of_vfs_all && k < MAX_ENABLED_VFABRICS; k++) { + if (searchMgidsThruAppsinVF(&v_fabp->v_fabric_all[k], mgh, mgl)) { + matchedOtherVF=TRUE; + break; + } + } + if (matchedOtherVF) + matchedMgids=FALSE; + } + else + matchedMgids=FALSE; + + return matchedMgids; +} + +FSTATUS MatchImplicitMGIDtoVF(SMMcastDefGrp_t *mdgp, VirtualFabrics_t *v_fabricp) +{ +#define MAX_NUM_IMPLICIT_MCG 4 + + typedef struct implicitMgid_t { + uint64_t Prefix; + uint64_t Postfix; + } implicitMgid; + + int i,j; + uint32_t number_of_vfs = 0; + boolean matchedAllMgids = TRUE; + boolean matchedIPv4Mgids = TRUE; + boolean matchedIPv6Mgids = TRUE; + implicitMgid mgids[8]; + uint64_t broadcast = 0x00000000ffffffff; + uint64_t allNodes = 0x0000000000000001; + uint64_t allRouters = 0x0000000000000002; + uint64_t other = 0x0000000000000016; + uint64_t mcastDns = 0x00000000000000fb; + uint64_t IPv4 = 0xff12401b00000000ull; + uint64_t IPv6 = 0xff12601b00000000ull; + + memset(mgids, 0, sizeof(mgids)); + + mgids[0].Postfix = broadcast; + mgids[1].Postfix = allNodes; + mgids[2].Postfix = other; + mgids[3].Postfix = mcastDns; + mgids[4].Postfix = allNodes; + mgids[5].Postfix = allRouters; + mgids[6].Postfix = mcastDns; + mgids[7].Postfix = other; + + for (i=0; i < v_fabricp->number_of_vfs_all && i < MAX_ENABLED_VFABRICS; i++) { + if (!checkMC_VFProperties (mdgp, v_fabricp,i)) + continue; + matchedIPv4Mgids = TRUE; + for (j=0; jv_fabric_all[i].pkey); + mgids[j].Prefix = IPv4 | (pkey << 16 ); + matchedIPv4Mgids = FindApp(v_fabricp, &v_fabricp->v_fabric_all[i], mgids[j].Prefix, mgids[j].Postfix); + } + matchedIPv6Mgids = TRUE; + for (j=MAX_NUM_IMPLICIT_MCG; j< 2*MAX_NUM_IMPLICIT_MCG && matchedIPv6Mgids ; j++){ + uint32_t pkey = MAKE_PKEY(1, v_fabricp->v_fabric_all[i].pkey); + mgids[j].Prefix = IPv6 | (pkey << 16 ); + matchedIPv6Mgids = FindApp(v_fabricp, &v_fabricp->v_fabric_all[i], mgids[j].Prefix, mgids[j].Postfix); + } + + int MGIdx=0; + int number_matched = 0; + if (matchedIPv4Mgids) { + for (j=0; jmgid[MGIdx++].mgid,"0x%016"PRIx64":0x%016"PRIx64, mgids[j].Prefix, mgids[j].Postfix); + number_matched = number_matched + MAX_NUM_IMPLICIT_MCG; + } + if (matchedIPv6Mgids) { + for (j=MAX_NUM_IMPLICIT_MCG; j< 2* MAX_NUM_IMPLICIT_MCG; j++) + sprintf(mdgp->mgid[MGIdx++].mgid,"0x%016"PRIx64":0x%016"PRIx64, mgids[j].Prefix, mgids[j].Postfix); + number_matched = number_matched + MAX_NUM_IMPLICIT_MCG; + } + matchedAllMgids = matchedIPv4Mgids || matchedIPv6Mgids; + + if (matchedAllMgids) { + mdgp->number_of_mgids=number_matched; + number_of_vfs++; + if (!PreCreateMCGroup(mdgp, v_fabricp, i)) + return FUNAVAILABLE; + } + }// create a group for all matched VF's + + if (number_of_vfs == 0) // not matched + return FNOT_FOUND; + + mdgp->number_of_mgids=0; + return FSUCCESS; +} + + +//check if MLIDShare overlap +static FSTATUS CheckMLIDShareOverlapping(uint32_t fm, FMXmlCompositeConfig_t *config) +{ + SmMcastMlidShared_t *dmsp_ref, *dmsp_check; + uint32_t i,mlidSharedInstance; + uint32_t numshared; + uint64_t val0H, val0L, val1H, val1L; + IB_GID mask_ref, mask_check; + IB_GID value_ref, value_check; + FSTATUS status; + + if (!common && config->fm_instance[fm]) + numshared = config->fm_instance[fm]->sm_mls_config.number_of_shared; + else + numshared = config->fm_instance_common->sm_mls_config.number_of_shared; + + + + for (mlidSharedInstance=0; mlidSharedInstance < (numshared-1) && mlidSharedInstance < MAX_SUPPORTED_MCAST_GRP_CLASSES_XML; mlidSharedInstance++) { + // inherit the values of config items already set + if (!common && config->fm_instance[fm]) + dmsp_ref = &config->fm_instance[fm]->sm_mls_config.mcastMlid[mlidSharedInstance]; + else + dmsp_ref = &config->fm_instance_common->sm_mls_config.mcastMlid[mlidSharedInstance]; + + if (dmsp_ref->enable) { + //for the dmsp_ref + /* grab the mask */ + if ((status = cs_parse_gid(dmsp_ref->mcastGrpMGidLimitMaskConvert.value, mask_ref.Raw)) != VSTATUS_OK) { + IB_LOG_ERROR_FMT(__func__, "Bad value for MGIDMask in MLIDShare %d: %s", mlidSharedInstance, + dmsp_ref->mcastGrpMGidLimitMaskConvert.value); + continue; + } + BSWAP_IB_GID(&mask_ref); + + if ((mask_ref.AsReg64s.H == 0) && (mask_ref.AsReg64s.L == 0)) + continue; + + /* grab the value */ + if ((status = cs_parse_gid(dmsp_ref->mcastGrpMGidLimitValueConvert.value, value_ref.Raw)) != VSTATUS_OK) { + IB_LOG_ERROR_FMT(__func__, "Bad value for MGIDValue in MLIDShare %d: %s", mlidSharedInstance, + dmsp_ref->mcastGrpMGidLimitValueConvert.value); + continue; + } + BSWAP_IB_GID(&value_ref); + + for (i = mlidSharedInstance+1; i < numshared && i < MAX_SUPPORTED_MCAST_GRP_CLASSES_XML ; i++) { + if (!common && config->fm_instance[fm]) + dmsp_check = &config->fm_instance[fm]->sm_mls_config.mcastMlid[i]; + else + dmsp_check = &config->fm_instance_common->sm_mls_config.mcastMlid[i]; + + if (dmsp_check->enable) { + //for the dmsp_check + /* grab the mask */ + if ((status = cs_parse_gid(dmsp_check->mcastGrpMGidLimitMaskConvert.value, mask_check.Raw)) != VSTATUS_OK) { + IB_LOG_ERROR_FMT(__func__, "Bad value for MGIDMask in MLIDShare %d: %s", mlidSharedInstance, + dmsp_check->mcastGrpMGidLimitMaskConvert.value); + continue; + } + BSWAP_IB_GID(&mask_check); + + /* grab the value */ + if ((status = cs_parse_gid(dmsp_check->mcastGrpMGidLimitValueConvert.value, value_check.Raw)) != VSTATUS_OK) { + IB_LOG_ERROR_FMT(__func__, "Bad value for MGIDValue in MLIDShare %d: %s", mlidSharedInstance, + dmsp_check->mcastGrpMGidLimitValueConvert.value); + continue; + } + BSWAP_IB_GID(&value_check); + + if ((mask_check.AsReg64s.H == 0) && (mask_check.AsReg64s.L == 0)) + continue; + + val0H = value_ref.AsReg64s.H & mask_check.AsReg64s.H; + val0L = value_ref.AsReg64s.L & mask_check.AsReg64s.L; + val1H = value_check.AsReg64s.H & mask_ref.AsReg64s.H; + val1L = value_check.AsReg64s.L & mask_ref.AsReg64s.L; + + if (((val0H ^ val1H) == 0) && ((val0L ^ val1L) == 0)) { + return FERROR; + } + } //end if enable check + }// for end check + } //end if enable ref + } //for end ref + status = FSUCCESS; + return status; +} diff --git a/Esm/ib/src/cs/Makefile b/Esm/ib/src/cs/Makefile new file mode 100644 index 0000000..28f56ce --- /dev/null +++ b/Esm/ib/src/cs/Makefile @@ -0,0 +1,164 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2018, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** +# Makefile for SM Module + +# Include Make Control Settings +include $(TL_DIR)/$(PROJ_FILE_DIR)/Makesettings.project + +#=============================================================================# +# Definitions: +#-----------------------------------------------------------------------------# + +# Name of SubProjects +DS_SUBPROJECTS = +# name of executable or downloadable image +EXECUTABLE = # Sm$(EXE_SUFFIX) +# list of sub directories to build +DIRS = +# C files (.c) +CFILES = \ + cs_sema.c cs_context.c cs_queue.c cs_hashtable.c\ + cs_string.c vs_pool_common.c \ + cs_bitset.c \ + vs_thr_common.c \ + cs_utility.c cs_csm_log.c \ + cs_sockwrap.c cs_vesw.c + # Add more c files here +# C++ files (.cpp) +CCFILES = \ + # Add more cpp files here +# lex files (.lex) +LFILES = \ + # Add more lex files here +# archive library files (basename, $ARFILES will add MOD_LIB_DIR/prefix and suffix) +LIBFILES= +# Windows Resource Files (.rc) +RSCFILES = +# Windows IDL File (.idl) +IDLFILE = +# Windows Linker Module Definitions (.def) file for dll's +DEFFILE = +# targets to build during INCLUDES phase (add public includes here) +INCLUDE_TARGETS = \ + # Add more h hpp files here +# Non-compiled files +MISC_FILES = +# all source files +SOURCES = $(CFILES) $(CCFILES) $(LFILES) $(RSCFILES) $(IDLFILE) +# Source files to include in DSP File +DSP_SOURCES = $(INCLUDE_TARGETS) $(SOURCES) $(MISC_FILES) \ + $(RSCFILES) $(DEFFILE) $(MAKEFILE) +# all object files +OBJECTS = $(CFILES:.c=$(OBJ_SUFFIX)) $(CCFILES:.cpp=$(OBJ_SUFFIX)) \ + $(LFILES:.lex=$(OBJ_SUFFIX)) +RSCOBJECTS = $(RSCFILES:.rc=$(RES_SUFFIX)) +# targets to build during LIBS phase +LIB_TARGETS_IMPLIB = +LIB_TARGETS_ARLIB = $(LIB_PREFIX)cs$(ARLIB_SUFFIX) +LIB_TARGETS_EXP = $(LIB_TARGETS_IMPLIB:$(ARLIB_SUFFIX)=$(EXP_SUFFIX)) +LIB_TARGETS_MISC = +# targets to build during CMDS phase +CMD_TARGETS_SHLIB = +CMD_TARGETS_EXE = $(EXECUTABLE) +CMD_TARGETS_MISC = +# files to remove during clean phase +CLEAN_TARGETS_MISC = +CLEAN_TARGETS = $(OBJECTS) $(RSCOBJECTS) $(IDL_TARGETS) $(CLEAN_TARGETS_MISC) +# other files to remove during clobber phase +CLOBBER_TARGETS_MISC= +# sub-directory to install to within bin +BIN_SUBDIR = +# sub-directory to install to within include +INCLUDE_SUBDIR = + +# Additional Settings +#CLOCALDEBUG = User defined C debugging compilation flags [Empty] +#CCLOCALDEBUG = User defined C++ debugging compilation flags [Empty] +#CLOCAL = User defined C flags for compiling [Empty] +#CCLOCAL = User defined C++ flags for compiling [Empty] +#BSCLOCAL = User flags for Browse File Builder [Empty] +#DEPENDLOCAL = user defined makedepend flags [Empty] +#LINTLOCAL = User defined lint flags [Empty] +#LOCAL_INCLUDE_DIRS = User include directories to search for C/C++ headers [Empty] +#LDLOCAL = User defined C flags for linking [Empty] +#IMPLIBLOCAL = User flags for Object Lirary Manager [Empty] +#MIDLLOCAL = User flags for IDL compiler [Empty] +#RSCLOCAL = User flags for resource compiler [Empty] +#LOCALDEPLIBS = User libraries to include in dependencies [Empty] +#LOCALLIBS = User libraries to use when linking [Empty] +# (in addition to LOCALDEPLIBS) +#LOCAL_LIB_DIRS = User library directories for libpaths [Empty] + +CLOCAL = $(CPIE) +LOCALDEPLIBS = + +PROJ_SM_DIR ?= $(TL_DIR)/Esm/ib + +# Include Make Rules definitions and rules +ifneq "$(PROJ_SM_DIR)" "" +LOCAL_INCLUDE_DIRS=$(MOD_DIR)/src/smi/include $(MOD_DIR)/src/pm/include +include $(PROJ_SM_DIR)/Makerules.module +endif +#=============================================================================# +# Overrides: +#-----------------------------------------------------------------------------# +#CCOPT = # C++ optimization flags, default lets build config decide +#COPT = # C optimization flags, default lets build config decide +#SUBSYSTEM = Subsystem to build for (none, console or windows) [none] +# (Windows Only) +#USEMFC = How Windows MFC should be used (none, static, shared, no_mfc) [none] +# (Windows Only) +#=============================================================================# + +#=============================================================================# +# Rules: +#-----------------------------------------------------------------------------# +# process Sub-directories +include $(TL_DIR)/Makerules/Maketargets.toplevel + +# build cmds and libs +include $(TL_DIR)/Makerules/Maketargets.build + +# install for includes, libs and cmds phases +include $(TL_DIR)/Makerules/Maketargets.install + +# install for stage phase +#include $(TL_DIR)/Makerules/Maketargets.stage +STAGE:: + +# Unit test execution +#include $(TL_DIR)/Makerules/Maketargets.runtest + +clobber:: clobber_module + +#=============================================================================# + +#=============================================================================# +# DO NOT DELETE THIS LINE -- make depend depends on it. +#=============================================================================# diff --git a/Esm/ib/src/cs/README b/Esm/ib/src/cs/README new file mode 100644 index 0000000..c57b094 --- /dev/null +++ b/Esm/ib/src/cs/README @@ -0,0 +1,45 @@ +/* BEGIN_ICS_COPYRIGHT10 **************************************** + +Copyright (c) 2015, Intel Corporation +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: +- Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. +- Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. +- Neither the name of Intel Corporation nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL INTEL, THE COPYRIGHT OWNER OR CONTRIBUTORS +BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. + +EXPORT LAWS: THIS LICENSE ADDS NO RESTRICTIONS TO THE EXPORT LAWS OF YOUR +JURISDICTION. It is licensee's responsibility to comply with any export +regulations applicable in licensee's jurisdiction. Under CURRENT (May 2000) +U.S. export regulations this software is eligible for export from the U.S. +and can be downloaded by or otherwise exported or reexported worldwide EXCEPT +to U.S. embargoed destinations which include Cuba, Iraq, Libya, North Korea, +Iran, Syria, Sudan, Afghanistan and any other country to which the U.S. has +embargoed goods and services. + +** END_ICS_COPYRIGHT10 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ +Component Services and OS obstraction for FM + +This library is supported by code in vxworks or ibaccess trees to +complete the OS specific aspects of the OS abstraction. +Some OS independent utility data structures are also provided here. diff --git a/Esm/ib/src/cs/cs_bitset.c b/Esm/ib/src/cs/cs_bitset.c new file mode 100644 index 0000000..9a073fb --- /dev/null +++ b/Esm/ib/src/cs/cs_bitset.c @@ -0,0 +1,474 @@ +/* BEGIN_ICS_COPYRIGHT5 **************************************** + +Copyright (c) 2015-2018, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + * ** END_ICS_COPYRIGHT5 ****************************************/ + +//===========================================================================// +// // +// FILE NAME // +// cs_bitset.c // +// // +// DESCRIPTION // +// Bitset handling methods. // +// // +// DATA STRUCTURES // +// None // +// // +// DEPENDENCIES // +// cs_bitset.h // +// // +// // +//===========================================================================// + +#include "os_g.h" +#include "cs_log.h" +#include "ib_status.h" +#include "cs_bitset.h" + +size_t bitset_nset(bitset_t *bitset) { + return bitset->nset_m; +} + +static void _bitset_mask_off_unused_bits(bitset_t *bitset) { + + uint32_t bits_left = bitset->nbits_m % 32; + if (bits_left) { + // Mask off the unused bits + uint32_t mask = (1 << bits_left) - 1; + bitset->bits_m[bitset->nwords_m-1] &= mask; + } +} + +int bitset_init(Pool_t* pool, bitset_t *bitset, size_t nbits) { + Status_t status; + + bitset->pool_m = pool; + bitset->bits_m = NULL; + bitset->nset_m = 0; + bitset->nbits_m = nbits; + bitset->nwords_m = (nbits/32); + if (nbits%32) { + bitset->nwords_m++; + } + status = vs_pool_alloc(pool, sizeof(uint32_t)*bitset->nwords_m, (void *)&bitset->bits_m); + if (status != VSTATUS_OK) { + IB_LOG_ERRORRC("can't allocate space for bitset, rc:", status); + memset(bitset, 0, sizeof(bitset_t)); + return 0; + } + memset(bitset->bits_m, 0, sizeof(uint32_t)*bitset->nwords_m); + return 1; +} + +size_t count_nset(bitset_t* bitset) { + size_t bits_left = bitset->nbits_m; + size_t i = 0; + size_t nset = 0; + + if (!bitset->bits_m) { + IB_LOG_INFINI_INFO0("bad bits"); + return 0; + } + for (i = 0; bits_left >= 32; i++, bits_left -= 32) { + uint32_t word = bitset->bits_m[i]; + nset += __builtin_popcount(word); + } + if (bits_left > 0) { + uint32_t mask = (1 << bits_left) - 1; + nset += __builtin_popcount(bitset->bits_m[i] & mask); + //bits_left = 0; + } + return nset; +} + + +int bitset_resize(bitset_t *bitset, size_t n) { + Status_t status; + size_t orig_nbits = bitset->nbits_m; + size_t orig_nset = bitset->nset_m; + size_t orig_nwords = bitset->nwords_m; + uint32_t *orig_bits = bitset->bits_m; + + if (n == bitset->nbits_m) return 1; + + bitset->bits_m = NULL; + + if (!bitset_init(bitset->pool_m, bitset, n)) { + bitset->nbits_m = orig_nbits; + bitset->nset_m = orig_nset; + bitset->nwords_m = orig_nwords; + bitset->bits_m = orig_bits; + return 0; + } + + if (!orig_bits) return 1; + + if (n > orig_nbits) { + memcpy(bitset->bits_m, orig_bits, orig_nwords*sizeof(uint32_t)); + bitset->nset_m = orig_nset; + } else { + memcpy(bitset->bits_m, orig_bits, bitset->nwords_m*sizeof(uint32_t)); + _bitset_mask_off_unused_bits(bitset); + bitset->nset_m = count_nset(bitset); + } + + if ((status = vs_pool_free(bitset->pool_m, orig_bits)) != VSTATUS_OK) { + IB_LOG_ERRORRC("can't free allocated space for bitset, rc:", status); + } + return 1; +} + +void bitset_free(bitset_t *bitset) { + Status_t status; + + if (bitset->bits_m) { + if ((status = vs_pool_free(bitset->pool_m, bitset->bits_m)) != VSTATUS_OK) { + IB_LOG_ERRORRC("can't free allocated space for bitset, rc:", status); + } + } + memset(bitset, 0, sizeof(bitset_t)); +} + +void bitset_clear_all(bitset_t *bitset) { + if (bitset->bits_m) { + memset(bitset->bits_m, 0, sizeof(uint32_t)*bitset->nwords_m); + } + bitset->nset_m = 0; +} + +void bitset_set_all(bitset_t *bitset) { + if (bitset->bits_m) { + memset(bitset->bits_m, 0xff, sizeof(uint32_t)*bitset->nwords_m); + bitset->nset_m = bitset->nbits_m; + _bitset_mask_off_unused_bits(bitset); + } +} + +void bitset_copy(bitset_t *bitset1, bitset_t *bitset2) { + + if (!bitset1->bits_m) return; + if (!bitset2->bits_m) return; + + if (bitset1->nbits_m != bitset2->nbits_m) { + bitset_resize(bitset1, bitset2->nbits_m); + } + + if (bitset1->nbits_m != bitset2->nbits_m) return; + + memcpy(bitset1->bits_m, bitset2->bits_m, sizeof(uint32_t)*bitset1->nwords_m); + bitset1->nset_m = bitset2->nset_m; +} + +int bitset_clear(bitset_t *bitset, unsigned bit) { + int rc = 0; + + if (bitset->bits_m && (bit < bitset->nbits_m)) { + if ((bitset->bits_m[bit/32] & (1<bits_m[bit/32] ^= (1<nset_m--; + } + rc = 1; + } + return rc; +} + +int bitset_set(bitset_t *bitset, unsigned bit) { + int rc = 0; + + if (bitset->bits_m && (bit < bitset->nbits_m)) { + if ((bitset->bits_m[bit/32] & (1<bits_m[bit/32] |= (1<nset_m++; + } + rc = 1; + } + return rc; +} + +int bitset_test(bitset_t *bitset, unsigned bit) { + int rc = 0; + + if (bitset->bits_m && (bit < bitset->nbits_m)) { + rc = (bitset->bits_m[bit/32] & (1<nbits_m != b->nbits_m) || + (a->nset_m != b->nset_m) || + (a->nwords_m != b->nwords_m) || + !a->bits_m || + !b->bits_m) { + return 0; + } + + for (word = 0; word < a->nwords_m; word++) { + if (a->bits_m[word] != b->bits_m[word]) return 0; + } + return 1; +} + + +int bitset_find_first_one(bitset_t *bitset) { + return bitset_find_next_one(bitset, 0); +} + +int bitset_find_next_one(bitset_t *bitset, unsigned bit) { + + if (bitset && bitset->bits_m && (bit < bitset->nbits_m)) { + unsigned i_word; + uint32_t mask = (1 << (bit % 32)) - 1; + unsigned bits = bitset->nbits_m % 32; + uint32_t word; + for (i_word = bit / 32; i_word < bitset->nwords_m; i_word++) { + if (i_word == (bitset->nwords_m - 1) && bits != 0) { + /* Handle last Word if not 32bits */ + mask |= ~((1 << bits) -1); + } + word = bitset->bits_m[i_word] & ~mask; + if (word != 0) { + return (i_word * 32) + __builtin_ctz(word); + } + mask = 0; + } + } + return -1; +} + +int bitset_find_last_one(bitset_t *bitset) { + + if (bitset && bitset->bits_m && bitset->nset_m) { + int i_word; + unsigned bits = bitset->nbits_m % 32; + uint32_t mask = (uint32_t)(-1); + if (bits) mask = (1 << bits) - 1; + for (i_word = bitset->nwords_m-1; i_word >= 0; i_word--) { + uint32_t word = bitset->bits_m[i_word] & mask; + if (word) { + return (i_word * 32) + (32 - 1 - __builtin_clz(word)); + } + mask = (uint32_t)(-1); + } + } + return -1; +} + +int bitset_find_first_zero(bitset_t *bitset) { + return bitset_find_next_zero(bitset, 0); +} + +int bitset_find_next_zero(bitset_t *bitset, unsigned bit) { + + if (bitset && bitset->bits_m && (bit < bitset->nbits_m)) { + unsigned i_word; + uint32_t mask = (1 << (bit % 32)) - 1; + unsigned bits = bitset->nbits_m % 32; + uint32_t word; + for (i_word = bit/32; i_word < bitset->nwords_m; i_word++) { + if (i_word == (bitset->nwords_m - 1) && bits != 0) { + /* Handle last Word if not 32bits */ + mask |= ~((1 << bits) -1); + } + word = bitset->bits_m[i_word] | mask; + if (word != (uint32_t)(-1)) { + return (i_word * 32) + __builtin_ctz(~word); + } + mask = 0; + } + } + return -1; +} + +int bitset_find_last_zero(bitset_t *bitset) { + + if (bitset && bitset->bits_m && (bitset->nset_m != bitset->nbits_m)) { + int i_word; + unsigned bits = bitset->nbits_m % 32; + uint32_t mask = 0; + if (bits) mask = (1 << bits) - 1; + else bits = 32; + for (i_word = bitset->nwords_m - 1; i_word >= 0; i_word--) { + uint32_t word = bitset->bits_m[i_word] | mask; + if (word != (uint32_t)(-1)) { + return (i_word * 32) + (bits - 1 - __builtin_clz(~word)); + } + bits = 32; + mask = 0; + } + } + return -1; +} + +size_t bitset_nbits(bitset_t *bitset) { + return bitset->nbits_m; +} + +// +// This uses log level INFINI_INFO and should probably only +// be called under debug mode. +// +void bitset_info_log(bitset_t* bitset, char* prelude) { + char* string = NULL; + char* s = NULL; + int first = 1; + int range = 0; + int range_start = -1; + int prev = -1; + int bit = -1; + size_t max_str_len = bitset->nset_m*5+1; + int res = 0; + Status_t status; + + if (!bitset) return; + + if (bitset->bits_m == NULL) { + IB_LOG_INFINI_INFO_FMT( __func__, "NOBITS"); + return; + } + + if (bitset->nset_m == 0) { + if (prelude) { + IB_LOG_INFINI_INFO_FMT(__func__, "%s ", prelude); + } else { + IB_LOG_INFINI_INFO_FMT(__func__, ""); + } + return; + + } else if (!bitset->pool_m || (bitset->nset_m>500)) { + if (prelude) { + IB_LOG_INFINI_INFO_FMT(__func__, "%s, nset= %d", prelude, (int)bitset->nset_m); + } else { + IB_LOG_INFINI_INFO_FMT(__func__, "nset= %d", (int)bitset->nset_m); + } + return; + } + + status = vs_pool_alloc(bitset->pool_m, max_str_len, (void *)&string); + if (status != VSTATUS_OK) { + if (prelude) { + IB_LOG_INFINI_INFO_FMT(__func__, "%s, nset= %d", prelude, (int)bitset->nset_m); + } else { + IB_LOG_INFINI_INFO_FMT(__func__, "nset= %d", (int)bitset->nset_m); + } + return; + } + string[0] = '\0'; + s = string; + + bit = bitset_find_first_one(bitset); + + while (bit != -1) { + if (first) { + res = cs_snprintfcat(&s, &max_str_len, "%d", bit); + if (res == 0) + break; + else if (res < 0) + goto bail; + + first = 0; + } else { + if (range && (prev != bit-1)) { + range = 0; + if ((prev - range_start) > 1) { + res = cs_snprintfcat(&s, &max_str_len, "-%d,%d", prev, bit); + } else { + res = cs_snprintfcat(&s, &max_str_len, ",%d,%d", prev, bit); + } + if (res == 0) + break; + else if (res < 0) + goto bail; + + prev = -1; + range_start = -1; + } else if (!range && (prev == bit-1)) { + range_start = prev; + range = 1; + } else if (!range) { + res = cs_snprintfcat(&s, &max_str_len, ",%d", bit); + if (res == 0) + break; + else if (res < 0) + goto bail; + } + } + prev = bit; + bit = bitset_find_next_one(bitset, bit+1); + } + + if (range && (prev != -1)) { + if ((prev - range_start) > 1) { + res = cs_snprintfcat(&s, &max_str_len, "-%d", prev); + } else { + res = cs_snprintfcat(&s, &max_str_len, ",%d", prev); + } + if (res < 0) + goto bail; + } + +bail: + if (prelude) { + IB_LOG_INFINI_INFO_FMT(__func__, "%s %s", prelude, string); + } else { + IB_LOG_INFINI_INFO_FMT(__func__, "%s", string); + } + + if ((status = vs_pool_free(bitset->pool_m, string)) != VSTATUS_OK) { + IB_LOG_ERRORRC("can't free allocated space for bitset log, rc:", status); + } +} + +int bitset_test_intersection(bitset_t * a, bitset_t * b) { + int i = 0; + + if (a->nwords_m != b->nwords_m) + return 0; + + for (i = 0; i < a->nwords_m; ++i) { + if (a->bits_m[i] & b->bits_m[i]) + return 1; + } + + return 0; +} + +int bitset_set_intersection(bitset_t * a, bitset_t * b, bitset_t * result) { + int i; + + if (!a->bits_m || !b->bits_m || !result->bits_m) return -1; + if (a->nwords_m != b->nwords_m || a->nwords_m != result->nwords_m) return -1; + + for (i = 0; i < a->nwords_m; ++i) { + result->bits_m[i] = a->bits_m[i] & b->bits_m[i]; + } + + result->nset_m = count_nset(result); + + return result->nset_m; +} diff --git a/Esm/ib/src/cs/cs_context.c b/Esm/ib/src/cs/cs_context.c new file mode 100644 index 0000000..888535e --- /dev/null +++ b/Esm/ib/src/cs/cs_context.c @@ -0,0 +1,795 @@ +/* BEGIN_ICS_COPYRIGHT5 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + * ** END_ICS_COPYRIGHT5 ****************************************/ + +//===========================================================================// +// +// FILE NAME +// cs_context.c +// +// DESCRIPTION +// This module provides a generic implementation of a context pool to be +// used for reliable trasmission of single packet mads only. +// +// DATA STRUCTURES +// NONE +// +// FUNCTIONS +// NONE +// +// DEPENDENCIES +// ib_types.h +// ib_mad.h +// ib_status.h +// +// +//===========================================================================// + +#include "os_g.h" +#include "ib_types.h" +#include "vs_g.h" +#include "cs_g.h" +#include "cs_log.h" +#include "ib_mad.h" +#include "ib_status.h" +#include "cs_context.h" +#include "mai_g.h" +#include "ib_generalServices.h" + +#include "sm_counters.h" +#include "pm_counters.h" + +extern uint32_t smDebugPerf; + +// +// delete a context entry +// +static void cntxt_delete_entry ( cntxt_entry_t **listCntx, cntxt_entry_t *entry ) { + if (*listCntx == entry) { + *listCntx = (*listCntx)->next; + } else { + if (entry->prev) entry->prev->next = entry->next; + if (entry->next) entry->next->prev = entry->prev; + } + entry->next = NULL; + entry->prev = NULL; + //IB_LOG_INFINI_INFO("deleted context from list, index=", entry->index); +} + + +// +// insert a context entry into head of list +// +static void cntxt_insert_head ( cntxt_entry_t **listCntx, cntxt_entry_t *entry ) { + if ( *listCntx ) (*listCntx)->prev = entry; + entry->next = *listCntx; + (*listCntx) = entry; + entry->prev = NULL; +} + +void cs_cntxt_lock( generic_cntxt_t *cntx ) { + vs_lock(&cntx->lock); +} + +void cs_cntxt_unlock( generic_cntxt_t *cntx ) { + vs_unlock(&cntx->lock); +} + +// +// Complete initialization of a context entry and put it on hash list. +// Very simple hashing implemented. This function is modular and can be +// changed to use any algorithm, if hashing turns out to be bad. +// +static void cntxt_reserve( cntxt_entry_t *a_cntxt, generic_cntxt_t *cntx ) { + int bucket ; + + DEBUG_ASSERT(a_cntxt->alloced); + DEBUG_ASSERT(! a_cntxt->hashed); + DEBUG_ASSERT(! a_cntxt->releasing); + + a_cntxt->lid = a_cntxt->mad.addrInfo.dlid; // destination lid message is for + a_cntxt->tid = a_cntxt->mad.base.tid; + a_cntxt->RespTimeout = cntx->defaultTimeout; + + // This context needs to be inserted into the hash table + if (cntx->hashTableDepth > 1) + bucket = a_cntxt->lid % cntx->hashTableDepth; + else + bucket = 0; + a_cntxt->hashed = 1 ; + vs_time_get( &a_cntxt->tstamp ); + cntxt_insert_head( &cntx->hash[ bucket ], a_cntxt ); +} + +// remove context entry from hash list +static void cntxt_unhash( cntxt_entry_t *entry, generic_cntxt_t *cntx) +{ + int bucket ; + + DEBUG_ASSERT(entry->alloced); + if( entry->hashed ) { + if (cntx->hashTableDepth > 1) + bucket = entry->lid % cntx->hashTableDepth; + else + bucket = 0; + entry->hashed = 0 ; + cntxt_delete_entry( &cntx->hash[ bucket ], entry ); + } + entry->prev = NULL; + entry->next = NULL; +} + +// +// clear context entry and put back on pool free list +// +void cs_cntxt_retire_nolock( cntxt_entry_t *entry, generic_cntxt_t *cntx ) +{ uint16_t index=0; + + //IB_LOG_INFINI_INFOX("retiring context at address=", (LogVal_t)entry); + cntxt_unhash( entry, cntx); + + index = entry->index; // save entry index + // Reset all fields + memset ((void *)entry, 0, sizeof(cntxt_entry_t)); + entry->index = index; // put index back + // put back on free list + //entry->alloced = 0; // already zeroed by memset + //entry->releasing = 0; // already zeroed by memset + cntxt_insert_head( &cntx->free_list, entry ); + ++cntx->numFree; + --cntx->numAlloc; + + //IB_LOG_INFINI_INFO("context back on free list, index=", entry->index); + // wake up the waiter if one + if (cntx->numWaiters) { + //IB_LOG_INFINI_INFO("Waking up context queue user, current num waiters=", cntx->numWaiters); + --cntx->numWaiters; + (void)cs_vsema(&cntx->freeContextWaitSema); + } +} + +void cs_cntxt_retire( cntxt_entry_t *entry, generic_cntxt_t *cntx ) +{ + Status_t status; + + IB_ENTER(__func__, entry, cntx, 0, 0 ); + + if ((status = vs_lock(&cntx->lock)) != VSTATUS_OK) { + IB_LOG_ERRORRC("Failed to lock context rc:", status); + } else { + cs_cntxt_retire_nolock(entry, cntx); + if (vs_unlock(&cntx->lock)) { + IB_LOG_ERROR0("Failed to unlock context"); + } + } + + IB_EXIT0( "cs_cntxt_retire" ); +} + +// This is only valid for use within a cntxt callback, it will reuse the +// context and prevent the cntxt_release function (which invoked the callback) +// from freeing entry +void cs_entxt_reuse_nolock( cntxt_entry_t *entry, generic_cntxt_t *cntx, Mai_t *mad ) { + uint16_t index=entry->index; // save entry index + + DEBUG_ASSERT(entry->alloced); + DEBUG_ASSERT(! entry->hashed); + // Reset all fields + memset ((void *)entry, 0, sizeof(cntxt_entry_t)); + entry->index = index; // put index back + entry->alloced = 1; // restore alloced + //entry->releasing = 0; // already zeroed by memset above + if (mad) { + // save the output mad + memcpy((void *)&entry->mad, mad, sizeof(Mai_t)); + cntxt_reserve( entry, cntx ); // we could wait until send_mad + } +} + +// +// find context entry matching input mad +// +static cntxt_entry_t *cntxt_find( Mai_t* mad, generic_cntxt_t *cntx ) { + int bucket; + cntxt_entry_t* a_cntxt = NULL; + cntxt_entry_t* req_cntxt = NULL; + + // Search the hash table for the context + if (cntx->hashTableDepth > 1) + bucket = mad->addrInfo.slid % cntx->hashTableDepth; + else + bucket = 0; + + for (a_cntxt = cntx->hash[ bucket ]; a_cntxt ; a_cntxt = a_cntxt->next) { + if( a_cntxt->lid == mad->addrInfo.slid && + MAI_MASK_TID(a_cntxt->tid) == MAI_MASK_TID(mad->base.tid) ) { + req_cntxt = a_cntxt; + break ; + } + } +#if 0 + // Table is sorted with respect to timeout + if( req_cntxt ) { + // Touch current context + vs_time_get( &req_cntxt->tstamp ); + cntxt_delete_entry( &cntx->hash[ bucket ], req_cntxt ); + cntxt_insert_head( &cntx->hash[ bucket ], req_cntxt ); + } +#endif + return req_cntxt; +} // end cntxt_find + + +// +// release a context entry +// This takes it off the hash list, invokes the callback and puts a_cntxt +// back on the free list. As needed waiters are woken. +// +static Status_t cntxt_release( cntxt_entry_t *a_cntxt, generic_cntxt_t *cntx, Status_t s, Mai_t *mad ) { + + //IB_LOG_INFINI_INFOLX("releasing context index=", a_cntxt->index); + cntxt_unhash( a_cntxt, cntx); + a_cntxt->releasing = 1; + + if (a_cntxt->senderWantsResponse && cntx->resp_queue) { + Status_t status; + + // presently the combination of a resp_queue and a callback are not + // allowed, this is mainly bacause if the callback retired or reused + // the a_cntxt, the cntxt_entry on the resp_queue would be stale + ASSERT(a_cntxt->callback == NULL); + // post the response on the response queue + if (mad) { + memcpy((void *)&a_cntxt->mad, (void *)mad, sizeof(Mai_t)); + } else { + a_cntxt->mad.type = MAI_TYPE_ERROR; + } + // provided resp_queue is sized the same as dispatcher, this should + // not fail + if ((status = cs_queue_Enqueue((cs_QueueElement_ptr)a_cntxt, cntx->resp_queue)) != VSTATUS_OK) { + IB_LOG_ERRORRC("unable to queue mad response for user, rc:", status); + DEBUG_ASSERT(0); + cs_cntxt_retire_nolock( a_cntxt, cntx ); + } + } else { + if (a_cntxt->callback != NULL) + a_cntxt->callback(a_cntxt, s, a_cntxt->callback_data, mad); + + // if callback retires, reuses and/or re-gets the context, releasing + // will be reset, in which case we leave the context unchanged. + // note that since we have lock, if callback retires context it can't be + // reclaimed and race with this test. + if( a_cntxt->releasing) { + cs_cntxt_retire_nolock( a_cntxt, cntx ); + //IB_LOG_INFINI_INFOLX("successfully released the context, num free now=", cntx->numFree); + } + } + return VSTATUS_OK ; +} + +// +// output the mad associated with the context +// assumes caller already had lock +// +Status_t cs_cntxt_send_mad_nolock (cntxt_entry_t *entry, generic_cntxt_t *cntx) { + Status_t status; + uint32_t datalen; + + if (! entry->hashed) + cntxt_reserve( entry, cntx ); // clears sendFailed + else + entry->sendFailed = 0; + + //if (entry->retries == 0) { + //IB_LOG_INFINI_INFOLX("sending notice mad, TID=", entry->tid); + //} else { + //IB_LOG_INFINI_INFOLX("resending sending notice mad, TID=", entry->tid); + //} + + if ( (entry->mad.base.mclass == MAD_CV_SUBN_LR) + || (entry->mad.base.mclass == MAD_CV_SUBN_DR) ) + { + if (entry->retries) { + INCREMENT_COUNTER(smCounterPacketRetransmits); + } + INCREMENT_COUNTER(smCounterSmPacketTransmits); + } else if (entry->mad.base.mclass == MAD_CV_PERF) + { + if (entry->retries) { + INCREMENT_PM_COUNTER(pmCounterPacketRetransmits); + } + INCREMENT_PM_COUNTER(pmCounterPmPacketTransmits); + } + + //if (cntx->timeoutAdder) printf("mad_send tid=0x%lx timeout=%lu\n", entry->mad.base.tid, entry->RespTimeout); + entry->retries++; +#if 0 // simulate failed sends to aid debug +if (entry->mad.base.mclass == 0x4) { +static unsigned count = 0; +//if (count > 200) { +if (count > 200 && count % 5 < 2) { + count++; + entry->sendFailed = 1; // will avoid timeoutAddr + return VSTATUS_BAD; + //return VSTATUS_OK; // pretend to send, let timeout cover us +} else { +count++; +} +} +#endif + if (entry->mad.base.mclass == MAD_CV_PERF || entry->mad.base.mclass == MAD_CV_SUBN_ADM + ) { + datalen = MIN((uint32_t)entry->mad.datasize, STL_GS_DATASIZE); + if ((status = mai_send_stl_timeout(cntx->ibHandle, &entry->mad, &datalen, entry->RespTimeout)) != VSTATUS_OK) { + IB_LOG_ERROR_FMT(__func__, + "status %d sending %s[%s] MAD length %u in context entry[%d] to LID[0x%x], TID 0x%.16"CS64"X", + status, cs_getMethodText(entry->mad.base.method), + cs_getAidName(entry->mad.base.mclass, entry->mad.base.aid), (uint32)entry->mad.datasize, + entry->index, entry->mad.addrInfo.dlid, entry->tid); + entry->sendFailed = 1; + } + return status; + } + if ((status = mai_send_timeout(cntx->ibHandle, &entry->mad, entry->RespTimeout)) != VSTATUS_OK) { + IB_LOG_ERROR_FMT(__func__, + "status %d sending %s[%s] MAD in context entry[%d] to LID[0x%x], TID 0x%.16"CS64"X", + status, cs_getMethodText(entry->mad.base.method), + cs_getAidName(entry->mad.base.mclass, entry->mad.base.aid), + entry->index, entry->mad.addrInfo.dlid, entry->tid); + entry->sendFailed = 1; + } + return status; +} + +// +// get global context pool +// +Pool_t *cs_cntxt_get_global_pool (generic_cntxt_t *cntx) { + return cntx->globalPool; +} + +// +// init a context pool for use +// +Status_t cs_cntxt_instance_init (Pool_t *pool, generic_cntxt_t *cntx, uint64_t timeout) { + Status_t status; + uint32_t poollen; + int i; + cntxt_entry_t *entry; + + IB_ENTER(__func__, cntx, 0, 0, 0 ); + + if (cntx->resp_queue) { + if (cs_queue_Capacity(cntx->resp_queue) < cntx->poolSize) { + IB_LOG_ERROR_FMT(__func__, "resp_queue too small: %d need %d", cs_queue_Capacity(cntx->resp_queue), cntx->poolSize); + return VSTATUS_ILLPARM; + } + } + poollen = sizeof(cntxt_entry_t) * cntx->poolSize; + //IB_LOG_INFINI_INFO("generic_cntxt_t size ", sizeof(generic_cntxt_t)); + //IB_LOG_INFINI_INFO("cntxt_entry_t size ", sizeof(cntxt_entry_t)); + IB_LOG_VERBOSE("allocating context pool size ", poollen); + status = vs_pool_alloc( pool, poollen, (void *)&cntx->pool ); + if (status != VSTATUS_OK) { + IB_LOG_ERRORRC("can't allocate context pool, rc:", status); + return status; + } + //IB_LOG_INFINI_INFOX("cntx->pool = ", (uint32_t)cntx->pool); + memset( cntx->pool, 0, poollen); + cntx->globalPool = pool; // set global memory pool to use for queued messages + cntx->defaultTimeout = timeout; + cntx->numAlloc = 0; + cntx->numFree = cntx->poolSize; + cntx->free_list = NULL; + entry = (cntxt_entry_t *)cntx->pool; + for( i = 0, entry = (cntxt_entry_t *)cntx->pool; i < cntx->poolSize ; i++, entry++ ) { + //IB_LOG_INFINI_INFOX("entry ptr=", (uint32_t)entry); + entry->index = i+1; // for debug/tracking purposes + cntxt_insert_head(&cntx->free_list, entry); + } + // initialize queue lock + status = vs_lock_init(&cntx->lock, VLOCK_FREE, VLOCK_THREAD); + if (status != VSTATUS_OK) { + IB_LOG_ERRORRC("can't initialize context pool lock rc:", status); + vs_pool_free( pool, (void *)cntx->pool ); + } + // create the free context wait semaphore + if ((status = cs_sema_create(&cntx->freeContextWaitSema, 0)) != VSTATUS_OK) { + IB_FATAL_ERROR_NODUMP("cs_cntx_instance_init: can't initialize context semaphore"); + } + + IB_EXIT(__func__, status ); + return status; +} + + +// +// output the mad associated with the context +// +Status_t cs_cntxt_send_mad (cntxt_entry_t *entry, generic_cntxt_t *cntx) { + Status_t status; + + IB_ENTER(__func__, entry, cntx, 0, 0 ); + + if ((status = vs_lock(&cntx->lock)) != VSTATUS_OK) { + IB_LOG_ERRORRC("Failed to lock context rc:", status); + } else { + if ((status = cs_cntxt_send_mad_nolock(entry, cntx)) != VSTATUS_OK) { + IB_LOG_ERRORRC("can't send MAD rc:", status); + } + if (vs_unlock(&cntx->lock)) { + IB_LOG_ERROR0("Failed to unlock context"); + } + } + + IB_EXIT(__func__, 0 ); + return status; +} + +// TBD - could the timeout calculation part of this be shared with SM +// non-dispatched timeouts too? +// +// This routine processes a timed out context entry. It either performs +// the next retry or reports the entry as timedout and releases the entry. +// If a retry is attempted but fails, VSTATUS_BAD is returned and the +// caller can decide if a release or delay for later attempt is appropriate +// If entry exhausted retries, VSTATUS_TIMEOUT is returned +// If retry is successfully initiated, VSTATUS_OK is returned. +// cntxt_release will need to be invoked by caller as appropriate +static +Status_t cs_cntxt_timeout_entry(cntxt_entry_t *tout_cntxt, generic_cntxt_t *cntx, + uint64_t timenow) { + uint64_t timeout=0; + Status_t status; + + //if (cntx->timeoutAdder) printf("cs_cntxt_timeout_entry tid=0x%lx\n", tout_cntxt->tid); + + // Touch the entry + tout_cntxt->tstamp = timenow; + + /* If using stepped retries, update the entry's RespTimeout to the + * new time out value + */ + if (cntx->MinRespTimeout) { + /* PR 110945 - Stepped and randomized retries */ + tout_cntxt->cumulative_timeout += tout_cntxt->RespTimeout; + /* For each attempt, use an increasing multiple of MinRespTimeout as the timeout*/ + timeout = (tout_cntxt->retries+1)*cntx->MinRespTimeout; + /* Randomize timeout value within +/- 20% of the timeout*/ + timeout = GET_RANDOM((timeout + (timeout/5)), (timeout - (timeout/5))); + /* Make sure this timeout value doesn't cause cumulative_timeout + * to overshoot the total timeout + * If it will cause an overshoot, then just use whatever is left + * from the total timeout + */ + if ((tout_cntxt->cumulative_timeout < tout_cntxt->totalTimeout) && + ((tout_cntxt->cumulative_timeout + timeout) > tout_cntxt->totalTimeout)) { + timeout = tout_cntxt->totalTimeout - tout_cntxt->cumulative_timeout; + /* if the timeout left is less than min, set it to the min. This will cause cumulative_timeout to overshoot + * total_timeout by a bit, but that should be OK */ + if (timeout < cntx->MinRespTimeout) + timeout = cntx->MinRespTimeout; + } + + tout_cntxt->RespTimeout = timeout; + } + + /* retry sending or release if max retries (no stepped retry logic) + * or max timeout (stepped retry logic) has exhausted + */ + if ((cntx->MinRespTimeout == 0) && (tout_cntxt->retries < cntx->maxRetries)) { + /*no stepped retry logic, so retry till we reach maxRetries */ + //if (cntx->timeoutAdder) printf("retry send, tid=0x%lx timeout=%ld\n", tout_cntxt->tid, tout_cntxt->RespTimeout/1000); + if ((status = cs_cntxt_send_mad_nolock (tout_cntxt, cntx)) != VSTATUS_OK) { + IB_LOG_ERRORRC("can't resend notice reliably rc:", status); + return VSTATUS_BAD; // send failed + } + } else if ((cntx->MinRespTimeout != 0) && (tout_cntxt->cumulative_timeout < tout_cntxt->totalTimeout)) { + /*stepped retry logic is being used, so retry till cumulative timeout + * reaches total timeout + */ + //if (cntx->timeoutAdder) printf("retry send, tid=0x%lx timeout=%ld\n", tout_cntxt->tid, tout_cntxt->RespTimeout/1000); + if ((status = cs_cntxt_send_mad_nolock (tout_cntxt, cntx)) != VSTATUS_OK) { + IB_LOG_ERRORRC("can't resend notice reliably rc:", status); + return VSTATUS_BAD; // send failed + } + } else { + /* retries exhausted, report failure */ + if ((tout_cntxt->mad.base.mclass == MAD_CV_SUBN_LR) + || (tout_cntxt->mad.base.mclass == MAD_CV_SUBN_DR) ) { + if (smDebugPerf) { + // exhausted the retries, release the context + IB_LOG_INFINI_INFO_FMT(__func__, "no response to %s of %s from lid 0x%x, TID 0x%.16"CS64"X", + cs_getMethodText(tout_cntxt->mad.base.method), cs_getAidName(tout_cntxt->mad.base.mclass, tout_cntxt->mad.base.aid), + tout_cntxt->lid, tout_cntxt->tid); + } + INCREMENT_COUNTER(smCounterSmTxRetriesExhausted); + } else if (tout_cntxt->mad.base.mclass == MAD_CV_PERF) { + INCREMENT_PM_COUNTER(pmCounterPmTxRetriesExhausted); + } + //if (cntx->timeoutAdder) printf("retries exhausted tid=0x%lx\n", tout_cntxt->tid); + return VSTATUS_TIMEOUT; + } + return VSTATUS_OK; +} + +/* + * Age context and do resends for those that timed out + * + * Returns the smallest time left for the context that is going to expire next. + */ +uint64_t cs_cntxt_age(generic_cntxt_t *cntx) +{ + cntxt_entry_t* a_cntxt = NULL ; + cntxt_entry_t* tout_cntxt ; + int i; + Status_t status; + uint64_t timenow=0, smallest_timeleft=0, time_left=0; + + IB_ENTER(__func__, cntx, 0, 0, 0 ); + + if ((status = vs_lock(&cntx->lock)) != VSTATUS_OK) { + IB_LOG_ERRORRC("Failed to lock context rc:", status); + } else { + vs_time_get( &timenow ); + for (i = 0; i < cntx->hashTableDepth; i++) { + a_cntxt = (cntxt_entry_t *)cntx->hash[ i ]; + while( a_cntxt ) { + // if a send failed, use normal timeouts. If send did not + // fail, we use timeoutAdder. timeoutAdder will be 0 if this + // is our primary aging mechanism. If we are using OFED + // timeouts, timeoutAdder will allow this mechanism to + // be a safety net in case OFED fails to provide a return MAD + uint64_t timeoutAdder= a_cntxt->sendFailed?0:cntx->timeoutAdder; + // Iterate before the pointers are destroyed + tout_cntxt = a_cntxt; + a_cntxt = a_cntxt->next; + //IB_LOG_INFINI_INFO("checking context index ", tout_cntxt->index); + if ( timenow - tout_cntxt->tstamp >= tout_cntxt->RespTimeout + timeoutAdder) { + // Timeout this entry + //if (cntx->timeoutAdder) printf("Entry aged out: tid=0x%lx send failed=%d delta=%lu adder=%lu\n", tout_cntxt->tid, tout_cntxt->sendFailed, timenow - tout_cntxt->tstamp, timeoutAdder); + +#if 0 + // Get timed out entry to head of hash + cntxt_delete_entry( &cntx->hash[ i ], tout_cntxt ); + cntxt_insert_head( &cntx->hash[ i ], tout_cntxt ); +#endif + + status = cs_cntxt_timeout_entry(tout_cntxt, cntx, timenow); + if (status == VSTATUS_TIMEOUT + || (cntx->errorOnSendFail && status != VSTATUS_OK)) { + /*if this context is being released, don't consider + * it for smallest_timeleft calculation + */ + cntxt_release( tout_cntxt, cntx, status, NULL ); + continue; + } + // If errorOnSendFail = 0, for send errors (VSTATUS_BAD) + // we leave entry in hash and will retry it next time + // timeout expires. + // Successful retry (VSTATUS_OK) also stays on hash + } + + /* check remaining time for this context before it times out */ + time_left = tout_cntxt->RespTimeout - (timenow - tout_cntxt->tstamp); + time_left += tout_cntxt->sendFailed?0:cntx->timeoutAdder; + + /* if it is the context with the smallest time left for its + * timeout, then update smallest_timeleft + */ + if (smallest_timeleft) { + if ( time_left < smallest_timeleft) + smallest_timeleft = time_left; + } else { + /* smallest_timeleft is 0, no previous time_left values */ + smallest_timeleft = time_left; + } + } + } + if (vs_unlock(&cntx->lock)) { + IB_LOG_ERROR0("Failed to unlock context"); + } + } + IB_EXIT(__func__, 0 ); + return smallest_timeleft; +} + +cntxt_entry_t* +cs_cntxt_get_nolock( Mai_t* mad, generic_cntxt_t *cntx, boolean wait ) +{ + uint64_t now; + cntxt_entry_t *req_cntxt = NULL; + + IB_ENTER(__func__, mad, cntx, 0, 0 ); + + vs_time_get( &now ); + // Allocate a new context + req_cntxt = cntx->free_list; + if( req_cntxt != NULL ) { + // remove from free list + cntxt_delete_entry( &cntx->free_list, req_cntxt ); + // increment number allocated + ++cntx->numAlloc; + --cntx->numFree; + // reserve the context + req_cntxt->alloced = 1; + req_cntxt->totalTimeout = cntx->totalTimeout; + if (mad) { + // save the output mad + memcpy((void *)&req_cntxt->mad, mad, sizeof(Mai_t)); + cntxt_reserve( req_cntxt, cntx ); // we could wait until send_mad + } + //IB_LOG_INFINI_INFO("context allocated, num free now ", cntx->numFree); + } else if (wait) { + ++cntx->numWaiters; + } else { + IB_LOG_INFINI_INFO0("no free context available at this time"); + } + + IB_EXIT(__func__, req_cntxt ); + return req_cntxt ; +} + +cntxt_entry_t* +cs_cntxt_get( Mai_t* mad, generic_cntxt_t *cntx, boolean wait ) +{ + cntxt_entry_t *req_cntxt = NULL; + Status_t status; + + IB_ENTER(__func__, mad, cntx, 0, 0 ); + + if ((status = vs_lock(&cntx->lock)) != VSTATUS_OK) { + IB_LOG_ERRORRC("Failed to lock context rc:", status); + } else { + req_cntxt = cs_cntxt_get_nolock(mad, cntx, wait ); + if ((status = vs_unlock(&cntx->lock)) != VSTATUS_OK) { + IB_LOG_ERRORRC("Failed to unlock context rc:", status); + } + } + IB_EXIT(__func__, req_cntxt ); + return req_cntxt ; +} + +// +// wait for a free context +// +cntxt_entry_t* +cs_cntxt_get_wait( Mai_t* mad, generic_cntxt_t *cntx ) +{ + cntxt_entry_t *req_cntxt = NULL; + + IB_ENTER(__func__, mad, cntx, 0, 0 ); + + while (req_cntxt == NULL) { + req_cntxt = cs_cntxt_get(mad, cntx, TRUE); + // wait on sema if required + if (req_cntxt == NULL) { + //IB_LOG_INFINI_INFO0("no free context available at this time, WAITING...."); + (void)cs_psema(&cntx->freeContextWaitSema); + } + } + + IB_EXIT(__func__, req_cntxt ); + return req_cntxt ; +} + +// +// got a response to a outbound MAD, release the appropriate context +// +void cs_cntxt_find_release (Mai_t *mad, generic_cntxt_t *cntx) { + cntxt_entry_t *entry = NULL; + Status_t status = 0; + + IB_ENTER(__func__, cntx, 0, 0, 0 ); + + if ((status = vs_lock(&cntx->lock)) != VSTATUS_OK) { + IB_LOG_ERRORRC("Failed to lock context rc:", status); + } else { + if ((entry = cntxt_find( mad, cntx)) != NULL) { + //IB_LOG_INFINI_INFOLX("trying to release context with tid ", entry->tid); + cntxt_release( entry, cntx, VSTATUS_OK, mad ); + } else { + IB_LOG_INFO_FMT(__func__, "discarding unexpected response: Class: 0x%x Attr: 0x%x SLID: 0x%x TID: "FMT_U64, mad->base.mclass, mad->base.aid, mad->addrInfo.slid, mad->base.tid); + } + if (vs_unlock(&cntx->lock)) { + IB_LOG_ERROR0("Failed to unlock context"); + } + } + + IB_EXIT(__func__, 0 ); +} + + +// +// got indication that outbound MAD failed to send or never got a response. +// Identify appropriate context and either fail it or start retries +void cs_cntxt_find_release_error (Mai_t *mad, generic_cntxt_t *cntx) { + cntxt_entry_t *entry = NULL; + Status_t status = 0; + + IB_ENTER(__func__, cntx, 0, 0, 0 ); + + //if (cntx->timeoutAdder) printf("cs_cntxt_find_release_error tid=0x%lx\n", mad->base.tid); + if ((status = vs_lock(&cntx->lock)) != VSTATUS_OK) { + IB_LOG_ERRORRC("Failed to lock context rc:", status); + } else { + if ((entry = cntxt_find( mad, cntx)) != NULL) { + uint64_t timenow; + vs_time_get( &timenow ); + status = cs_cntxt_timeout_entry(entry, cntx, timenow); + + if (status == VSTATUS_TIMEOUT + || (cntx->errorOnSendFail && status != VSTATUS_OK)) { + cntxt_release( entry, cntx, status, NULL ); + } + } else { + IB_LOG_INFO_FMT(__func__, "discarding unexpected error: Class: 0x%x Attr: 0x%x SLID: 0x%x TID: "FMT_U64, mad->base.mclass, mad->base.aid, mad->addrInfo.slid, mad->base.tid); + } + if (vs_unlock(&cntx->lock)) { + IB_LOG_ERROR0("Failed to unlock context"); + } + } + + IB_EXIT(__func__, 0 ); +} + + +// +// free context pool +// +Status_t +cs_cntxt_instance_free (Pool_t *pool, generic_cntxt_t *cntx) { + Status_t status = 0; + + IB_ENTER(__func__, pool, cntx, 0, 0 ); + + vs_lock_delete (&cntx->lock); + status = vs_pool_free( pool, (void *)cntx->pool ); + if (status != VSTATUS_OK) { + IB_LOG_ERRORRC("can't free context pool, rc:", status); + } + (void)cs_sema_delete (&cntx->freeContextWaitSema); + memset((void *)cntx, 0, sizeof(generic_cntxt_t)); + + IB_EXIT(__func__, status ); + return status; +} + +// +// simple setter for caller-specified callback +// +void cs_cntxt_set_callback(cntxt_entry_t *cntxt, cntxt_callback_t cb, void *data) +{ + if (cb == NULL) { + cntxt->callback = cntxt->callback_data = NULL; + } else { + cntxt->callback = cb; + cntxt->callback_data = data; + } +} + diff --git a/Esm/ib/src/cs/cs_csm_log.c b/Esm/ib/src/cs/cs_csm_log.c new file mode 100644 index 0000000..8fa0308 --- /dev/null +++ b/Esm/ib/src/cs/cs_csm_log.c @@ -0,0 +1,400 @@ +/* BEGIN_ICS_COPYRIGHT5 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + * ** END_ICS_COPYRIGHT5 ****************************************/ + +#include +#include +#include +#include + +#include "ib_types.h" +#include "cs_log.h" +#include "cs_csm_log.h" +#include "cs_g.h" + +#ifdef __VXWORKS__ + +#include "ESM_Messages.h" + +#else + +#include +#include + +#define FORMAT1 "%s; MSG:%s|SM:%s|COND:%s|NODE:%s:port %u:"FMT_U64"|LINKEDTO:%s:port %u:"FMT_U64"|DETAIL:%s" +#define FORMAT2 "%s; MSG:%s|SM:%s|COND:%s|NODE:%s:port %u:"FMT_U64"|DETAIL:%s" +#define FORMAT3 "%s; MSG:%s|SM:%s|COND:%s|DETAIL:%s" + +static const char * severityStrings[CSM_SEV_MAX] = { + "", // 0th string reserved + "INFORMATION", + "NOTICE", + "WARNING", + "ERROR", +}; +#endif + +// Note that MSG_BUFFER_SZ is huge... We probably want to rethink this at some point +#define MSG_BUFFER_SZ 1024 +#define MAX_SM_DESCRIPTION_SZ 256 +#define DEFAULT_SM_DESCRIPTION "Default SM" +#define MSG_FIELD_SEPARATOR '|' +#define MSG_NODE_SEPARATOR ':' + +static const char translationFromChars[] = { MSG_FIELD_SEPARATOR, MSG_NODE_SEPARATOR }; +static const char translationToChars[] = { ' ', ' ' }; +static const char DefaultDesc[] = DEFAULT_SM_DESCRIPTION; +static char smDescription [MAX_SM_DESCRIPTION_SZ] = DEFAULT_SM_DESCRIPTION ":port 1"; +static SmCsmNodeId_t myNodeId; + +static const char * conditionStrings[CSM_COND_MAX] = { + "", // 0th string reserved + "#1 Redundancy lost", + "#2 Redundancy restored", + "#3 Appearance in fabric", + "#4 Disappearance from fabric", + "#5 SM state to master", + "#6 SM state to standby", + "#7 SM shutdown", + "#8 Fabric initialization error", + "#9 Link integrity/symbol error", + "#10 Security error", + "#11 Other Exception", + "#12 Fabric Summary", + "#13 SM state to inactive", + "#14 SM standby configuration inconsistency", + "#15 SM standby virtual fabric configuration inconsistency", + "#16 BM secondary configuration inconsistency", + "#17 PM secondary configuration inconsistency", + "#18 Master SM deactivating standby that is not responding", + "#19 EM secondary configuration inconsistency", +}; + + +static void convertChars(char * str, int numVals, const char fromValues[], const char toValues[]) +{ + int i = 0, j = 0; + + if (str == NULL) + return; + + for (i = 0; i < strlen(str); ++i) + { + for (j = 0; j < numVals; ++j) + { + if (str[i] == fromValues[j]) + str[i] = toValues[j]; + } + } +} + +/* + * Returns the SM Node description that was set by smCsmSetLogSmDesc for + * use by the actual logging functions + */ +SmCsmNodeId_t * getMyCsmNodeId(void) +{ + return &myNodeId; +} + +/* + * sets the SM description for CSM logging + */ +int smCsmSetLogSmDesc(const char * nodeDesc, int port, uint64_t guid) +{ + int rc = 0; + + if (nodeDesc == NULL) + nodeDesc = DefaultDesc; + + StringCopy(myNodeId.description, nodeDesc, 64); + + convertChars(myNodeId.description, sizeof(translationFromChars), + translationFromChars, translationToChars); + + myNodeId.port = port; + myNodeId.guid = guid; +#ifdef __VXWORKS__ + sprintf(smDescription, "%s:port %d", myNodeId.description, port); +#else + snprintf(smDescription, MAX_SM_DESCRIPTION_SZ, "%s:port %d", myNodeId.description, port); +#endif + + return rc; +} + +void smCsmFormatNodeId(SmCsmNodeId_t * id, uint8_t * desc, int port, uint64_t guid) +{ + StringCopy(id->description, (char *)desc, 64); + + convertChars(id->description, sizeof(translationFromChars), + translationFromChars, translationToChars); + + id->port = port; + id->guid = guid; +} + + +#ifdef __VXWORKS__ +static int smCsmLogHelper(SmCsmMsgType_t msgType, const char * smDesc, const char * condition, + const char * nodeDesc, const char * linkedToDesc, const char * details) +{ + switch (msgType) + { + case CSM_SEV_INFO: + if (linkedToDesc != NULL) + { + ESM_LOG_CSM_ESM_INFO_TWO(smDesc, condition, Log_StrDup(nodeDesc), + Log_StrDup(linkedToDesc), + Log_StrDup(details)); + } else if(nodeDesc != NULL) + { + ESM_LOG_CSM_ESM_INFO_ONE(smDesc, condition, Log_StrDup(nodeDesc), + Log_StrDup(details)); + + } else + { + ESM_LOG_CSM_ESM_INFO_ZERO(smDesc, condition, + Log_StrDup(details)); + } + break; + + case CSM_SEV_NOTICE: + if (linkedToDesc != NULL) + { + ESM_LOG_FINAL_CSM_ESM_NOTICE_TWO(smDesc, condition, Log_StrDup(nodeDesc), + Log_StrDup(linkedToDesc), + Log_StrDup(details)); + } else if(nodeDesc != NULL) + { + ESM_LOG_FINAL_CSM_ESM_NOTICE_ONE(smDesc, condition, Log_StrDup(nodeDesc), + Log_StrDup(details)); + + } else + { + ESM_LOG_FINAL_CSM_ESM_NOTICE_ZERO(smDesc, condition, + Log_StrDup(details)); + } + break; + + case CSM_SEV_WARNING: + if (linkedToDesc != NULL) + { + ESM_LOG_FINAL_CSM_ESM_WARNING_TWO(smDesc, condition, Log_StrDup(nodeDesc), + Log_StrDup(linkedToDesc), + Log_StrDup(details)); + } else if(nodeDesc != NULL) + { + ESM_LOG_FINAL_CSM_ESM_WARNING_ONE(smDesc, condition, Log_StrDup(nodeDesc), + Log_StrDup(details)); + + } else + { + ESM_LOG_FINAL_CSM_ESM_WARNING_ZERO(smDesc, condition, + Log_StrDup(details)); + } + break; + + case CSM_SEV_ERROR: /* fall through to default case */ + default: + if (linkedToDesc != NULL) + { + ESM_LOG_FINAL_CSM_ESM_ERROR_TWO(smDesc, condition, Log_StrDup(nodeDesc), + Log_StrDup(linkedToDesc), + Log_StrDup(details)); + } else if(nodeDesc != NULL) + { + ESM_LOG_FINAL_CSM_ESM_ERROR_ONE(smDesc, condition, Log_StrDup(nodeDesc), + Log_StrDup(details)); + + } else + { + ESM_LOG_FINAL_CSM_ESM_ERROR_ZERO(smDesc, condition, + Log_StrDup(details)); + } + break; + } + return 0; +} +#endif + +/* + * Logs a csm message + */ +int smCsmLogMessage( SmCsmMsgType_t msgType, SmCsmMsgCondition_t cond, + SmCsmNodeId_t * node, SmCsmNodeId_t * linkedTo, + char * detailFmt, ... ) +{ + int rc = 0; + va_list ap; + +#ifdef __VXWORKS__ + char detailBuffer[MSG_BUFFER_SZ]; + if (detailFmt != NULL) + { + StringCopy(detailBuffer, "|DETAIL:", sizeof(detailBuffer)); + va_start(ap, detailFmt); + vsprintf(detailBuffer + strlen(detailBuffer), detailFmt, ap); + va_end(ap); + } else + { + detailBuffer[0] = '\0'; + } + + if (node == NULL) + { + smCsmLogHelper(msgType, smDescription, conditionStrings[cond], + NULL, NULL, detailBuffer); + } else + { + char nodeDescBuffer[100]; + sprintf(nodeDescBuffer, "%s:port %u:"FMT_U64, + node->description, node->port, node->guid); + + if (linkedTo == NULL) + { + smCsmLogHelper(msgType, smDescription, conditionStrings[cond], nodeDescBuffer, + NULL, detailBuffer); + } else + { + char linkedToDescBuffer[100]; + sprintf(linkedToDescBuffer, "%s:port %u:"FMT_U64, + linkedTo->description, linkedTo->port, linkedTo->guid); + + smCsmLogHelper(msgType, smDescription, conditionStrings[cond], nodeDescBuffer, + linkedToDescBuffer, detailBuffer); + } + } + +#else + char buffer[MSG_BUFFER_SZ]; + int priority = LOG_ERR; + int flush = 0; + extern FILE *log_file; // from vslog.c + extern int output_fd; // from vslog.c + extern int logMode; // from vslog.c + FILE *f = NULL; + extern uint32_t log_to_console; + + switch (msgType) { + case CSM_SEV_INFO: + priority = LOG_INFO; + if((VS_LOG_CSM_INFO & cs_log_masks[VIEO_APP_MOD_ID]) == 0) + return 0; + flush = 0; + break; + + case CSM_SEV_NOTICE: + priority = LOG_NOTICE; + if((VS_LOG_CSM_NOTICE & cs_log_masks[VIEO_APP_MOD_ID]) == 0) + return 0; + flush = 1; + break; + + case CSM_SEV_WARNING: + priority = LOG_WARNING; + if((VS_LOG_CSM_WARN & cs_log_masks[VIEO_APP_MOD_ID]) == 0) + return 0; + flush = 1; + break; + + case CSM_SEV_ERROR: + default: + priority = LOG_ERR; + if((VS_LOG_CSM_ERROR & cs_log_masks[VIEO_APP_MOD_ID]) == 0) + return 0; + flush = 1; + break; + } + + if (node != NULL) + { + if (linkedTo != NULL) + { + snprintf(buffer, MSG_BUFFER_SZ, FORMAT1, myNodeId.description, + severityStrings[msgType], smDescription, conditionStrings[cond], + node->description, node->port, node->guid, + linkedTo->description, linkedTo->port, linkedTo->guid, + detailFmt); + } else + { + snprintf(buffer, MSG_BUFFER_SZ, FORMAT2, myNodeId.description, + severityStrings[msgType], smDescription, conditionStrings[cond], + node->description, node->port, node->guid, + detailFmt); + } + } else + { + snprintf(buffer, MSG_BUFFER_SZ, FORMAT3, myNodeId.description, + severityStrings[msgType], smDescription, conditionStrings[cond], + detailFmt); + } + if(log_to_console){ + f = stdout; + } else if(output_fd != -1) { + f = log_file; + } + if(f) + { + time_t theCalTime=0; + struct tm *locTime; + char strTime[28]; + + time(&theCalTime); + locTime = localtime(&theCalTime); + if (locTime) { + size_t l = strftime(strTime, + sizeof(strTime), + "%a %b %d %H:%M:%S %Y", + locTime); + if (l==0) { + strncpy(strTime,"(unknown)", sizeof(strTime)); + } + } else { + strncpy(strTime,"(unknown)", sizeof(strTime)); + } + // TBD - later output in one print so can't intermingle with others + fprintf(f, "%s: ", strTime); + va_start(ap, detailFmt); + vfprintf(f, buffer, ap); + va_end(ap); + fputc('\n', f); + if (flush) + fflush(f); + } + if(output_fd == -1 || (logMode & 0x2) == 0) + { + va_start(ap, detailFmt); + vsyslog(priority, buffer, ap); + va_end(ap); + } + +#endif + + return rc; +} diff --git a/Esm/ib/src/cs/cs_hashtable.c b/Esm/ib/src/cs/cs_hashtable.c new file mode 100644 index 0000000..cbac4ef --- /dev/null +++ b/Esm/ib/src/cs/cs_hashtable.c @@ -0,0 +1,348 @@ +/* BEGIN_ICS_COPYRIGHT5 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + * ** END_ICS_COPYRIGHT5 ****************************************/ + +#define INLINE +#include "cs_hashtable.h" +#include +#include +#include +#include + +/* + * prime table + */ +static const uint32_t primes[] = { +53, 97, 193, 389, +769, 1543, 3079, 6151, +12289, 24593, 49157, 98317, +196613, 393241, 786433, 1572869, +3145739, 6291469, 12582917, 25165843, +50331653, 100663319, 201326611, 402653189, +805306457, 1610612741 +}; +const uint32_t prime_table_length = sizeof(primes)/sizeof(primes[0]); +#define MAX_LOAD_FACTOR_NUMERATOR 8 +#define MAX_LOAD_FACTOR_DENOMINATOR 10 +static int32_t cs_hashtable_expand(struct cs_hashtable *h); + +/* + * cs_create_hashtable + */ +struct cs_hashtable * +cs_create_hashtable(const char *name, + uint32_t minsize, + uint64_t (*hashf) (void*), + int32_t (*eqf) (void*,void*), + CS_Hash_KeyType_t keytype) +{ + struct cs_hashtable *h; + uint32_t pindex; + + /* Check requested hashtable isn't too large */ + if (minsize > (1u << 30)) return NULL; + + /* Enforce size as prime */ + for (pindex=0; pindex < prime_table_length; pindex++) { + if (primes[pindex] > minsize) break; + } + + h = (struct cs_hashtable *)malloc(sizeof(struct cs_hashtable)); + if (NULL == h) return NULL; + + memset(h, 0, sizeof(*h)); + h->name = name; + h->primeindex = pindex - 1; + h->hashfn = hashf; + h->eqfn = eqf; + h->keyType = keytype; + if (cs_hashtable_expand(h) == 0) { + free(h); + return NULL; + } + return h; +} + +/* + * hash + */ +static uint64_t +_hash(struct cs_hashtable *h, void *k) +{ + /* + * Aim to protect against poor hash functions by adding logic here + * - logic taken from java 1.4 hashtable source + */ + uint64_t i = h->hashfn(k); + i += ~(i << 9); + i ^= ((i >> 14) | (i << 18)); /* >>> */ + i += (i << 4); + i ^= ((i >> 10) | (i << 22)); /* >>> */ + return i; +} + +/* + * cs_hashtable_expand + */ +static int32_t +cs_hashtable_expand(struct cs_hashtable *h) +{ + /* Double the size of the table to accomodate more entries */ + struct hash_entry **newtable; + struct hash_entry *e; + uint32_t newsize; + uint32_t index; + /* Check we're not hitting max capacity */ + if (h->primeindex == (prime_table_length - 1)) + return 0; + newsize = primes[++(h->primeindex)]; +// sysPrintf("%s h=%p(%s) primeindex=%lu newsize=%lu\n", __FUNCTION__, h, h->name, h->primeindex, newsize); + + /* malloc table */ + newtable = (struct hash_entry **)malloc(newsize * sizeof(struct hash_entry *)); + if (NULL == newtable) { + (h->primeindex)--; + return 0; + } + memset(newtable, 0, newsize * sizeof(struct hash_entry *)); + for (e = h->listHead; e != NULL; e = e->listNext) { + index = indexFor(newsize, e->h); + e->hashNext = newtable[index]; + newtable[index] = e; + } + if (h->table) + free(h->table); + h->table = newtable; + h->tablelength = newsize; + h->loadlimit = ((uint64_t)newsize * MAX_LOAD_FACTOR_NUMERATOR) / MAX_LOAD_FACTOR_DENOMINATOR; + return -1; +} + +/* + * cs_hashtable_insert + */ +int32_t +cs_hashtable_insert(struct cs_hashtable *h, void *k, void *v) +{ + /* This method allows duplicate keys - but they shouldn't be used */ + uint32_t index; + struct hash_entry *e; +// sysPrintf("%s h=%p(%s) k=%p v=%p ra=%p\n", __FUNCTION__, h, h->name, k, v, __builtin_return_address(0)); + if (++h->entrycount > h->loadlimit) { + /* Ignore the return value. If expand fails, we should + * still try cramming just this value into the existing table + * -- we may not have memory for a larger table, but one more + * element may be ok. Next time we insert, we'll try expanding again.*/ + cs_hashtable_expand(h); + } + /* retrieve a free hash_entry or allocate a new one */ + if ((e = h->freeHead) == NULL) { + e = (struct hash_entry *)malloc(sizeof(struct hash_entry)); + if (NULL == e) { /* out of memory */ + --h->entrycount; + return 0; + } + } else + h->freeHead = e->listNext; + + e->h = _hash(h,k); + //IB_LOG_INFINI_INFOLX("key is", e->h); + index = indexFor(h->tablelength,e->h); + e->k = k; + e->v = v; + e->hashNext = h->table[index]; + h->table[index] = e; + e->listNext = NULL; + if (h->listHead == NULL) { + h->listHead = h->listTail = e; + e->listPrev = NULL; + } else { + e->listPrev = h->listTail; + h->listTail = h->listTail->listNext = e; + } + return -1; +} + +/* + * cs_hashtable_search + */ +void *cs_hashtable_search(struct cs_hashtable *h, void *k) +{ + struct hash_entry *e; + uint64_t hashvalue = _hash(h,k); + + for(e = h->table[indexFor(h->tablelength,hashvalue)]; e != NULL; e = e->hashNext) { + /* Check hash value to short circuit heavier comparison */ + if ((hashvalue == e->h) && (h->eqfn(k, e->k))) + return e->v; + } + return NULL; +} + +void cs_hashentry_delete(struct cs_hashtable *h, struct hash_entry *e) { + h->entrycount--; + if (e == h->listHead) + h->listHead = e->listNext; + if (e == h->listTail) + h->listTail = e->listPrev; + if (e->listPrev != NULL) + e->listPrev->listNext = e->listNext; + if (e->listNext != NULL) + e->listNext->listPrev = e->listPrev; + if (h->keyType == CS_HASH_KEY_ALLOCATED) freekey(e->k); + e->listNext = h->freeHead; + h->freeHead = e; +} +/* + * cs_hashtable_remove + * returns value associated with key + */ +void *cs_hashtable_remove(struct cs_hashtable *h, void *k) { + /* TODO: consider compacting the table when the load factor drops enough, + * or provide a 'compact' method. */ + + struct hash_entry *e; + struct hash_entry **pE; + void *v; + uint64_t hashvalue = _hash(h,k); + + pE = &(h->table[indexFor(h->tablelength,hashvalue)]); + for(e = *pE; e != NULL; e = e->hashNext) { + /* Check hash value to short circuit heavier comparison */ + if ((hashvalue == e->h) && (h->eqfn(k, e->k))) { + *pE = e->hashNext; + v = e->v; + cs_hashentry_delete(h, e); + return v; + } + pE = &(e->hashNext); + } + return NULL; +} + +/* + * cs_hashtable_destroy + */ +void cs_hashtable_destroy(struct cs_hashtable *h, int32_t free_values) +{ + struct hash_entry *e; + struct hash_entry *listNext; + + for(e = h->freeHead; e != NULL; e = listNext) { + listNext = e->listNext; + free(e); + } + + for(e = h->listHead; e != NULL; e = listNext) { + listNext = e->listNext; + if (h->keyType == CS_HASH_KEY_ALLOCATED) freekey(e->k); + if (free_values) + free(e->v); + free(e); + } + free(h->table); + free(h); +} + + +/* + * cs_hashtable_change + * + * function to change the value associated with a key, where there already + * exists a value bound to the key in the hashtable. + * Source due to Holger Schemel. + * + */ +int32_t +cs_hashtable_change(struct cs_hashtable *h, void *k, void *v) +{ + struct hash_entry *e; + uint64_t hashvalue = _hash(h,k); + + for(e = h->table[indexFor(h->tablelength,hashvalue)]; e != NULL; e = e->hashNext) { + /* Check hash value to short circuit heavier comparison */ + if ((hashvalue == e->h) && (h->eqfn(k, e->k))) { + free(e->v); + e->v = v; + return -1; + } + } + return 0; +} + +/* + * remove - remove the entry at the current iterator position + * and advance the iterator, if there is a successive + * element. + * If you want the value, read it before you remove: + * beware memory leaks if you don't. + * Returns zero if end of iteration. + */ +int32_t +cs_hashtable_iterator_remove(struct cs_hashtable_itr *itr) { + struct cs_hashtable *h = itr->h; + struct hash_entry *removeEntry = itr->e; + struct hash_entry *e; + struct hash_entry **pE; + int32_t ret; + + ret = cs_hashtable_iterator_advance(itr); + + pE = &(h->table[indexFor(h->tablelength,_hash(h,removeEntry->k))]); + for(e = *pE; e != NULL; e = e->hashNext) { + if (e == removeEntry) { + *pE = e->hashNext; + cs_hashentry_delete(h, e); + break; + } + pE = &(e->hashNext); + } + return ret; +} + +/* + * cs_hashtable_iterator_search + * returns zero if not found + */ +int32_t +cs_hashtable_iterator_search(struct cs_hashtable_itr *itr, + struct cs_hashtable *h, void *k) { + struct hash_entry *e; + uint64_t hashvalue = _hash(h,k); + + for(e = h->table[indexFor(h->tablelength,hashvalue)]; e != NULL; e = e->hashNext) { + /* Check hash value to short circuit heavier comparison */ + if ((hashvalue == e->h) && (h->eqfn(k, e->k))) { + itr->e = e; + itr->h = h; + return -1; + } + } + return 0; +} + diff --git a/Esm/ib/src/cs/cs_queue.c b/Esm/ib/src/cs/cs_queue.c new file mode 100644 index 0000000..cb8d2cb --- /dev/null +++ b/Esm/ib/src/cs/cs_queue.c @@ -0,0 +1,232 @@ +/* BEGIN_ICS_COPYRIGHT5 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + * ** END_ICS_COPYRIGHT5 ****************************************/ + +#include "vs_g.h" +#include "cs_g.h" +#include "cs_log.h" +#include "ib_status.h" +#include "cs_queue.h" + +#define MinQueueSize ( 5 ) + +int cs_queue_IsEmpty( cs_Queue_ptr Q ) { + return (Q->Size == 0); +} + + +int cs_queue_IsFull( cs_Queue_ptr Q ) { + return (Q->Size == Q->Capacity); +} + + +cs_Queue_ptr cs_queue_CreateQueue( Pool_t *pool, uint32_t MaxElements ) { + cs_Queue_ptr que=NULL; + Status_t status; + int qsize; + + if( MaxElements < MinQueueSize ) { + IB_LOG_ERROR( "Queue size is too small (minimum of 5 entries required):", MaxElements ); + return que; + } + + status = vs_pool_alloc( pool, sizeof(cs_QueueRecord_t), (void *)&que ); + if (status != VSTATUS_OK) { + IB_LOG_ERRORRC("can't allocate space for Queue, rc:", status); + return NULL; + } + // allocate space for array of element pointers + qsize = sizeof(cs_QueueElement_ptr) * MaxElements; + status = vs_pool_alloc( pool, qsize, (void **)&que->qData ); + if (status != VSTATUS_OK) { + IB_LOG_ERRORRC("can't allocate space for Queue data, rc:", status); + status = vs_pool_free( pool, (void *)que ); + if (status != VSTATUS_OK) { + IB_LOG_ERRORRC("can't free Queue space, rc:", status); + } + return NULL; + } + // initialize queue lock + status = vs_lock_init(&que->lock, VLOCK_FREE, VLOCK_THREAD); + if (status != VSTATUS_OK) { + IB_FATAL_ERROR_NODUMP("cs_queue_CreateQueue: can't initialize SM trap forwarding queue lock"); + vs_pool_free( pool, (void *)que ); + vs_pool_free( pool, (void *)que->qData ); + que = NULL; + } else { + que->Capacity = MaxElements; + cs_queue_MakeEmpty( que ); + IB_LOG_VERBOSE_FMT(__func__, + "Created Queue with entry count of %d and total Queue aize of %d", + que->Capacity, qsize); + } + return que; +} + + +void cs_queue_MakeEmpty( cs_Queue_ptr Q ) +{ + Q->Size = 0; + Q->Front = 1; + Q->Rear = 0; +} + + +void cs_queue_DisposeQueue( Pool_t *pool, cs_Queue_ptr Q ) +{ + Status_t status; + + if( Q != NULL ) + { + vs_lock_delete (&Q->lock); + if ((status = vs_pool_free( pool, (void *)Q->qData )) != VSTATUS_OK) { + IB_LOG_ERRORRC("can't free Queue data, rc:", status); + } + if ((status = vs_pool_free( pool, (void *)Q )) != VSTATUS_OK) { + IB_LOG_ERRORRC("can't free Queue, rc:", status); + } + } + Q = NULL; +} + + +static int Succ( int Value, int Capacity ) +{ + if( ++Value == Capacity ) + Value = 0; + return Value; +} + +// enqueue entry at rear of queue +Status_t cs_queue_Enqueue( cs_QueueElement_ptr X, cs_Queue_ptr Q ) +{ + Status_t status = VSTATUS_OK; + unint *ptr=Q->qData; + + if ((status = vs_lock(&Q->lock)) != VSTATUS_OK) { + IB_LOG_ERRORRC("Failed to lock queue rc:", status); + } else { + if( cs_queue_IsFull( Q ) ) { + IB_LOG_ERROR0("Queue is full "); + // Cleanup (unlock) and exit + if ((status = vs_unlock(&Q->lock)) != VSTATUS_OK) { + IB_LOG_ERRORRC("Failed to unlock queue rc:", status); + } + return(VSTATUS_BAD); + } else { + Q->Size++; + Q->Rear = Succ( Q->Rear, Q->Capacity ); + ptr[Q->Rear] = (unint)X; + //IB_LOG_INFINI_INFO("inserted entry on Queue index ", Q->Rear); + if (X == NULL) { + IB_LOG_ERROR0("pointer to data on queue is NULL"); + } else { + //IB_LOG_INFINI_INFOX("pointer to data on queue is ", (uint32_t)X); + //IB_LOG_INFINI_INFOX("ptr to qdata[Q->Rear]=", (uint32_t)&ptr[Q->Rear]); + } + } + if ((status = vs_unlock(&Q->lock)) != VSTATUS_OK) { + IB_LOG_ERRORRC("Failed to unlock queue rc:", status); + } + } + return status; +} + +// get the entry at front of queue but don't dequeue it +cs_QueueElement_ptr cs_queue_Front( cs_Queue_ptr Q ) +{ + Status_t status = VSTATUS_OK; + cs_QueueElement_ptr X=NULL; + unint *ptr=Q->qData; + + if ((status = vs_lock(&Q->lock)) != VSTATUS_OK) { + IB_LOG_ERRORRC("Failed to lock queue rc:", status); + } else { + if( !cs_queue_IsEmpty( Q ) ) { + X = (cs_QueueElement_ptr)ptr[ Q->Front ]; + if (X == NULL) { + IB_LOG_ERROR0("pointer to data on queue is NULL"); + } else { + //IB_LOG_INFINI_INFO("returning Queue entry #", Q->Front); + //IB_LOG_INFINI_INFOX("returning entry qdata[Q->Front]=", (uint32_t)X); + } + } + if ((status = vs_unlock(&Q->lock)) != VSTATUS_OK) { + IB_LOG_ERRORRC("Failed to unlock queue rc:", status); + } + } + + return X; +} + +// remove the entry at front of queue +void cs_queue_Dequeue( cs_Queue_ptr Q ) +{ + Status_t status = VSTATUS_OK; + + if ((status = vs_lock(&Q->lock)) != VSTATUS_OK) { + IB_LOG_ERRORRC("Failed to lock queue rc:", status); + } else { + if( !cs_queue_IsEmpty( Q ) ) { + Q->Size--; + //IB_LOG_INFINI_INFO("removing Queue entry #", Q->Front); + Q->Front = Succ( Q->Front, Q->Capacity ); + //IB_LOG_INFINI_INFO("free Queue entry count=", (Q->Capacity - Q->Size)); + } + if ((status = vs_unlock(&Q->lock)) != VSTATUS_OK) { + IB_LOG_ERRORRC("Failed to unlock queue rc:", status); + } + } +} + +// dequeue and return the entry at front of quque +cs_QueueElement_ptr cs_queue_FrontAndDequeue( cs_Queue_ptr Q ) +{ + cs_QueueElement_ptr X = NULL; + Status_t status = VSTATUS_OK; + unint *ptr=Q->qData; +// int front=0; + + if ((status = vs_lock(&Q->lock)) != VSTATUS_OK) { + IB_LOG_ERRORRC("Failed to lock queue rc:", status); + } else { + if( !cs_queue_IsEmpty( Q ) ) { +// front = Q->Front; + Q->Size--; + X = (cs_QueueElement_ptr)ptr[ Q->Front ]; + Q->Front = Succ( Q->Front, Q->Capacity ); + //IB_LOG_INFINI_INFO("returning Queue entry #", front); + if (X == NULL) IB_LOG_ERROR0("pointer to data on queue is NULL"); + } + if ((status = vs_unlock(&Q->lock)) != VSTATUS_OK) { + IB_LOG_ERRORRC("Failed to unlock queue rc:", status); + } + } + return X; +} + diff --git a/Esm/ib/src/cs/cs_sema.c b/Esm/ib/src/cs/cs_sema.c new file mode 100644 index 0000000..6f151ba --- /dev/null +++ b/Esm/ib/src/cs/cs_sema.c @@ -0,0 +1,513 @@ +/* BEGIN_ICS_COPYRIGHT5 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + * ** END_ICS_COPYRIGHT5 ****************************************/ + +/*********************************************************************** +* +* FILE NAME +* cs_sema.c +* +* DESCRIPTION +* This file contains the implementation of the Counting Semaphores +* services. +* +* DATA STRUCTURES +* +* FUNCTIONS +* cs_sema_create +* cs_sema_delete +* cs_vsema +* cs_psema +* +* DEPENDENCIES +* cs_g.h +* +* +* HISTORY +* +* NAME DATE REMARKS +* MGR 03/14/02 Initial creation of file. +* MGR 03/26/02 Corrected lint errors. +* MGR 04/18/02 PR1728. vs_psema should return VSTATUS_AGAIN +* error code, if thread has been killed. +* MGR 04/23/02 PR1742. Added fix for blocking of cs_psema; +* cs_vsema should release lock if count goes to 1. +* +***********************************************************************/ +#include "ib_types.h" +#include "ib_status.h" +#include "cs_g.h" +#include "vs_g.h" +#include "cs_log.h" +#define function __FUNCTION__ +#ifdef __LINUX__ +#include +#elif defined(__VXWORKS__) +#include +#endif +#ifdef LOCAL_MOD_ID +#undef LOCAL_MOD_ID +#endif +#define LOCAL_MOD_ID VIEO_CS_MOD_ID + + +/********************************************************************** +* +* FUNCTION +* cs_sema_create +* +* DESCRIPTION +* Initialize a counting semaphore object for use. +* +* INPUTS +* handle - A pointer to a semaphore object to be filled in by +* the routine. +* count - The initial value for the semaphore. +* +* OUTPUTS +* Status_t - On success VSTATUS_OK is returned, otherwise +* the cause of the error. +* +* +* HISTORY +* +* NAME DATE REMARKS +* MGR 03/14/02 Initial creation of function. +* +**********************************************************************/ +Status_t +cs_sema_create (Sema_t *handle, + uint32_t count) +{ + Status_t rc; + + IB_ENTER (function, + (unint)handle, + (uint32_t)count, + (uint32_t)0U, + (uint32_t)0U); + + /* + ** Validate handle + */ + if (handle == (Sema_t *) 0) + { + IB_LOG_ERROR0 ("NULL handle pointer"); + IB_EXIT (function, VSTATUS_ILLPARM); + return VSTATUS_ILLPARM; + } + +#ifdef __VXWORKS__ + handle->magic = SEMAPHORE_MAGIC; + handle->semId = semCCreate(SEM_Q_FIFO, count); + handle->count = count; + if (!handle->semId) + { + IB_LOG_ERROR0 ("failed to allocate semaphore"); + rc = VSTATUS_ILLPARM; + IB_EXIT(function, rc); + return rc; + } +#else + // LINUX USER SEMA + handle->magic = SEMAPHORE_MAGIC; + if (sem_init((sem_t *)&handle->osdSema, 0, 0) != 0) + { + IB_LOG_ERROR0 ("failed to allocate semaphore"); + rc = VSTATUS_ILLPARM; + IB_EXIT(function, rc); + return rc; + } +#endif // vxworks + + IB_EXIT (function, VSTATUS_OK); + return VSTATUS_OK; +} + +/********************************************************************** +* +* FUNCTION +* cs_sema_delete +* +* DESCRIPTION +* Delete a counting semaphore object. +* +* INPUTS +* handle - A pointer to a semaphore object filled in by the +* cs_sema_create() call. +* +* OUTPUTS +* Status_t - On success VSTATUS_OK is returned, otherwise +* the cause of the error. +* +* +* HISTORY +* +* NAME DATE REMARKS +* MGR 03/14/02 Initial creation of function. +* +**********************************************************************/ +Status_t +cs_sema_delete (Sema_t *handle) +{ + Status_t rc; + + IB_ENTER (function, + (unint)handle, + (uint32_t)0U, + (uint32_t)0U, + (uint32_t)0U); + + /* + ** Validate handle + */ + if (handle == (Sema_t *) 0) + { + IB_LOG_ERROR0 ("NULL handle pointer"); + IB_EXIT (function, VSTATUS_ILLPARM); + return VSTATUS_ILLPARM; + } + + if (handle->magic != SEMAPHORE_MAGIC) + { + IB_LOG_ERRORX ("Invalid semaphore specified:", handle->magic); + IB_EXIT (function, VSTATUS_NXIO); + return VSTATUS_NXIO; + } + +#ifdef __VXWORKS__ + if (!handle->semId) + { + IB_LOG_ERROR0 ("NULL semaphore"); + rc = VSTATUS_ILLPARM; + IB_EXIT(function, rc); + return rc; + } + if (ERROR == semDelete(handle->semId)) + { + IB_LOG_ERROR0 ("failed to delete semaphore"); + rc = VSTATUS_ILLPARM; + IB_EXIT(function, rc); + return rc; + } + handle->semId = NULL; + handle->count = 0; +#else + // LINUX USER SEMA + if (sem_destroy((sem_t *)&handle->osdSema) != 0) { + IB_LOG_ERROR0 ("failed to delete semaphore"); + rc = VSTATUS_ILLPARM; + IB_EXIT(function, rc); + return rc; + } + memset((void *)&handle->osdSema, 0, sizeof(sem_t)); +#endif + + IB_LOG_INFO ("semaphore deleted", (unint)handle); + + IB_EXIT (function, VSTATUS_OK); + return VSTATUS_OK; +} + +/********************************************************************** +* +* FUNCTION +* cs_vsema +* +* DESCRIPTION +* Increment a semaphore (post or give operation) +* +* INPUTS +* handle - A pointer to a semaphore object filled in by the +* cs_sema_create() call. +* +* OUTPUTS +* Status_t - On success VSTATUS_OK is returned, otherwise +* the cause of the error. +* +* +* HISTORY +* +* NAME DATE REMARKS +* MGR 03/14/02 Initial creation of function. +* MGR 04/23/02 PR1742. Added fix for blocking or cs_psema; +* cs_vsema should release lock if count goes to 1. +* +**********************************************************************/ +Status_t +cs_vsema (Sema_t *handle) +{ + Status_t rc; + + IB_ENTER (function, + (unint)handle, + (uint32_t)0U, + (uint32_t)0U, + (uint32_t)0U); + + /* + ** Validate handle + */ + if (handle == (Sema_t *) 0) + { + IB_LOG_ERROR0 ("NULL handle pointer"); + IB_EXIT (function, VSTATUS_ILLPARM); + return VSTATUS_ILLPARM; + } + + if (handle->magic != SEMAPHORE_MAGIC) + { + IB_LOG_ERRORX ("Invalid semaphore specified:", handle->magic); + IB_EXIT (function, VSTATUS_NXIO); + return VSTATUS_NXIO; + } + +#ifdef __VXWORKS__ + if (ERROR == semGive(handle->semId)) + { + IB_LOG_ERROR0 ("Failed to give semaphore"); + rc = VSTATUS_NXIO; + IB_EXIT(function, rc); + return rc; + } + handle->count++; +#else + // LINUX USER SEMA + if (sem_post((sem_t *)&handle->osdSema) != 0) { + IB_LOG_ERROR0 ("Failed to give/post semaphore"); + rc = VSTATUS_NXIO; + IB_EXIT(function, rc); + return rc; + } +#endif + + IB_EXIT (function, VSTATUS_OK); + return VSTATUS_OK; +} + +/********************************************************************** +* +* FUNCTION +* cs_psema +* +* DESCRIPTION +* Decrement a semaphore (wait or take operation) +* +* INPUTS +* handle - A pointer to a semaphore object filled in by the +* cs_sema_create() call. +* +* OUTPUTS +* Status_t - On success VSTATUS_OK is returned, otherwise +* the cause of the error. +* +* +* HISTORY +* +* NAME DATE REMARKS +* MGR 03/14/02 Initial creation of function. +* MGR 04/18/02 PR1728. vs_psema should return VSTATUS_AGAIN +* error code, if thread has been killed. +* +**********************************************************************/ +Status_t +cs_psema_wait (Sema_t *handle, int timeout) +{ + Status_t rc=VSTATUS_OK; + + IB_ENTER (function, (unint)handle, 0U, 0U, 0U); + + /* Validate handle */ + if (handle == (Sema_t *) 0) + { + IB_LOG_ERROR0 ("NULL handle pointer"); + IB_EXIT (function, VSTATUS_ILLPARM); + return VSTATUS_ILLPARM; + } + + if (handle->magic != SEMAPHORE_MAGIC) + { + IB_LOG_ERRORX ("Invalid semaphore specified:", handle->magic); + IB_EXIT (function, VSTATUS_NXIO); + return VSTATUS_NXIO; + } + + if (timeout == CS_SEMA_WAIT_FOREVER) { + return(cs_psema(handle)); + } else { +#ifdef __VXWORKS__ + if (ERROR == semTake(handle->semId, timeout*sysClkRateGet())) + { + IB_LOG_WARN0("Timed out trying to take semaphore"); + rc = VSTATUS_NXIO; + } else { + handle->count--; + } +#elif defined (__LINUX__) + // LINUX USER SEMA + int i=0, rc=-1; + do { + rc = sem_trywait((sem_t *)&handle->osdSema); + ++i; + (void)vs_thread_sleep(VTIMER_1S); + } while (imagic != SEMAPHORE_MAGIC) + { + IB_LOG_ERRORX ("Invalid semaphore specified:", handle->magic); + IB_EXIT (function, VSTATUS_NXIO); + return VSTATUS_NXIO; + } + +#ifdef __VXWORKS__ + if (ERROR == semTake(handle->semId, WAIT_FOREVER)) + { + IB_LOG_ERROR0 ("Failed to take semaphore"); + rc = VSTATUS_NXIO; + IB_EXIT(function, rc); + return rc; + } + handle->count--; +#else + // LINUX USER SEMA + if (sem_wait((sem_t *)&handle->osdSema) != 0) { + IB_LOG_ERROR0 ("Failed to take semaphore"); + rc = VSTATUS_NXIO; + IB_EXIT(function, rc); + return rc; + } +#endif + + IB_EXIT (function, VSTATUS_OK); + return VSTATUS_OK; +} + +/********************************************************************** +* +* FUNCTION +* cs_sema_getcount +* +* DESCRIPTION +* return counting semaphore count +* +* INPUTS +* handle - A pointer to a semaphore object filled in by the +* cs_sema_create() call. +* +* OUTPUTS +* int - semaphore count +* +* +* HISTORY +* +* NAME DATE REMARKS +* JMS 02/20/07 Initial creation of function. +* +**********************************************************************/ +Status_t cs_sema_getcount(Sema_t *handle, int *semCount) +{ + Status_t rc = VSTATUS_OK; + + IB_ENTER (function, (unint)handle, 0U, 0U, 0U); + + /* Validate handle */ + if (handle == (Sema_t *) 0) { + IB_LOG_ERROR0 ("NULL handle pointer"); + rc = VSTATUS_ILLPARM; + } else if (handle->magic != SEMAPHORE_MAGIC) { + IB_LOG_ERRORX ("Invalid semaphore specified:", handle->magic); + rc = VSTATUS_NXIO; + } else { +#ifdef __VXWORKS__ + *semCount = handle->count; +#elif defined (__LINUX__) + if ((sem_getvalue((sem_t *)&handle->osdSema, semCount)) != 0) + { + IB_LOG_ERROR0 ("Failed to get semaphore count"); + rc = VSTATUS_NXIO; + } +#endif + } + IB_EXIT (function, rc); + return rc; +} diff --git a/Esm/ib/src/cs/cs_sockwrap.c b/Esm/ib/src/cs/cs_sockwrap.c new file mode 100644 index 0000000..0519bfc --- /dev/null +++ b/Esm/ib/src/cs/cs_sockwrap.c @@ -0,0 +1,425 @@ +/* BEGIN_ICS_COPYRIGHT5 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + * ** END_ICS_COPYRIGHT5 ****************************************/ + +/******************************************************************************* + * @file cs_sockwrap.c + * + * @brief + * This file contains some socket creation routines for server and client + * AF_UNIX type sockets. + * The routines are supposed to be used on both Unix and Vxworks but the + * structure of the socket addresss strings passed to the routines differs + * between the operating systems. + * In UNIX the structure of the strings is supposed to be generally of the + * form "/var/tmp/" and in VXWORKS the string should + * take the form "/comp/socket/0xNumber" where 0xNumber is a string + * representation of a 16 bit number is hexadecimal form. + ******************************************************************************* + */ + +#include +#include +#include +#include +#include "cs_sockwrap.h" +#include +#include "cs_g.h" +#include +#include + +#define QLEN 10 + + +#define CLI_PERM S_IRWXU /* rwx for user only */ + +#define MAXWAIT 30 + + +/* + * @brief + * + * cs_local_comm_init -- + * + * This function takes a string as an argument and creates a AF_UNIX + * socket with the string supplied to it as the address in the socket + * structure. + * This routine is to be called by a program that needs a server socket. + * + * @param[in] name pointer to unique socket address string + * + * @return * socket descriptor on sucess or (-1) on failure + * + * NOTE: For VxWorks socket support, please refer to the WindRiver Network Stack + * Programmer's Guide 6.9 (Section 5.3 - Working with Local Domain Sockets) + * + */ +int +cs_local_comm_init(const char *name) +{ + int fd; + int len; + int err; + struct sockaddr_un un; + + if (strlen(name) >= (sizeof(un.sun_path) )) { + errno = ENAMETOOLONG; + return(-1); + } + + /* create a UNIX domain stream socket */ +#ifdef __LINUX__ + if ((fd = socket(AF_UNIX, SOCK_SEQPACKET, 0)) < 0) { +#else + if ((fd = socket(AF_LOCAL, SOCK_SEQPACKET, 0)) < 0) { +#endif + return(fd); + } + + unlink(name); /* in case it already exists */ + + /* fill in socket address structure */ + memset(&un, 0, sizeof(un)); + snprintf(un.sun_path, sizeof(un.sun_path), "%s", name); + +#ifdef __LINUX__ + un.sun_family = AF_UNIX; + len = offsetof(struct sockaddr_un, sun_path) + strlen(name); +#else + un.sun_family = AF_LOCAL; + len = sizeof(struct sockaddr_un); + un.sun_len = len; +#endif + + /* bind the name */ + if (bind(fd, (struct sockaddr *)&un, len) < 0) { + goto errout; + } + + if (listen(fd, QLEN) < 0) { /* tell kernel we're a server */ + goto errout; + } + return(fd); + +errout: + err = errno; + close(fd); + errno = err; + return(-1); +} + + +/* + * @brief + * + * cs_local_comm_accept -- + * + * This function takes a socket descriptor as an argument and waits for + * a client connectio to arrive on it. It accepts the new connection + * checks for to see if the connection is via a socket and whether it + * is writeable and returns with the new socket descriptor if everything + * is successful + * + * @param[in] listenfd socket to listen for a connection on + * + * @return socket descriptor on sucess or (-1) on failure + * + */ +int +cs_local_comm_accept(int listenfd) +{ + int clifd; + socklen_t len; + struct sockaddr_un un; + char *name; +#ifdef __LINUX__ + int err; + struct stat statbuf; +#endif + + /* allocate enough space for longest name plus terminating null */ + if ((name = malloc(sizeof(un.sun_path) + 1)) == NULL) + assert(name); + len = sizeof(un); + if ((clifd = accept(listenfd, (struct sockaddr *)&un, &len)) < 0) { + free(name); + return (clifd); + } + + len -= offsetof(struct sockaddr_un, sun_path); /* len of pathname */ + StringCopy(name, un.sun_path, len); + +#ifdef __LINUX__ + if (stat(name, &statbuf) < 0) { + goto errout; + } + + /* check path to make sure its a socket and writable */ + if (S_ISSOCK(statbuf.st_mode) == 0) { + errno = ENOTSOCK; /* not a socket */ + goto errout; + } + + if ((statbuf.st_mode & (S_IRWXG | S_IRWXO)) || + (statbuf.st_mode & S_IRWXU) != S_IRWXU) { + errno = EPERM; + goto errout; + } +#endif + + unlink(name); + free(name); + return(clifd); + +#ifdef __LINUX__ +errout: + err = errno; + close(clifd); + free(name); + errno = err; + return(-1); +#endif +} + + + + +/* + * @brief + * + * cs_local_comm_connect -- + * + * This function takes two string arguments which + * are AF_UNIX socket addresses creates a new socket + * and connects to a specified server socket. + * + * @param[in] srvaddr Server socket address string + * @param[in] claddr Client socket address string + * + * @return socket descriptor on sucess or (-1) on failure + * + * NOTE: For VxWorks socket support, please refer to the WindRiver Network Stack + * Programmer's Guide 6.9 (Section 5.3 - Working with Local Domain Sockets) + * + */ +int +cs_local_comm_connect(const char *srvaddr, const char *claddr) +{ + int fd, len, err; + struct sockaddr_un un, sun; + int do_unlink = 0; + + if ((strlen(srvaddr) >= (sizeof(un.sun_path)) || + (strlen(claddr) >= sizeof(un.sun_path)))) { + errno = ENAMETOOLONG; + return(-1); + } + + /* create a UNIX domain stream socket */ +#ifdef __LINUX__ + if ((fd = socket(AF_UNIX, SOCK_SEQPACKET, 0)) < 0) { +#else + if ((fd = socket(AF_LOCAL, SOCK_SEQPACKET, 0)) < 0) { +#endif + return(-1); + } + + /* fill socket address structure with our address */ + memset(&un, 0, sizeof(un)); + StringCopy(un.sun_path, claddr, sizeof(un.sun_path)); + +#ifdef __LINUX__ + un.sun_family = AF_UNIX; + len = offsetof(struct sockaddr_un, sun_path) + strlen(un.sun_path); + unlink(un.sun_path); /* in case it already exists */ +#else + un.sun_family = AF_LOCAL; + len = sizeof(struct sockaddr_un); + un.sun_len = len; +#endif + + if (bind(fd, (struct sockaddr *)&un, len) < 0) { + goto errout; + } + +#ifdef __LINUX__ + if (chmod(un.sun_path, CLI_PERM) < 0) { + do_unlink = 1; + goto errout; + } +#endif + + /* fill socket address structure with server's address */ + memset(&sun, 0, sizeof(sun)); + StringCopy(sun.sun_path, srvaddr, sizeof(un.sun_path)); + +#ifdef __LINUX__ + sun.sun_family = AF_UNIX; + len = offsetof(struct sockaddr_un, sun_path) + strlen(srvaddr); +#else + sun.sun_family = AF_LOCAL; + len = sizeof(struct sockaddr_un); + sun.sun_len = len; +#endif + if (connect(fd, (struct sockaddr *)&sun, len) < 0) { + do_unlink = 1; + goto errout; + } + return(fd); + +errout: + err = errno; + close(fd); + if (do_unlink) + unlink(un.sun_path); + errno = err; + return(-1); +} + +/** + * @brief + * cs_comm_connect -- + * + * This function creates a socket with characteristics of the type requested + * and then connects to the specified channel using that socket. An explicit + * bind by the client is not done as the connect will bind a default address. + * If the connection fails because of an unready or a busy server it retries + * the connection in an exponential form. + * + * @param[in] domain Socket domain + * @param[in] type Socket type + * @param[in] protocol Usually 0 + * @param[in] srv_addr sockaddr structure of server + * @param[in] srv_len len of server sockaddr + * + * + * @return socket fd is successful, -1 if not + */ +static int +cs_comm_connect(int domain, int type, int protocol, + const struct sockaddr *srv_addr, socklen_t srv_len) +{ + int wait = 0; + int fd = -1; + + if ((fd = socket(domain, type, protocol) <0)) { + return (-1); + } + + while (wait++ < MAXWAIT) { + if (connect(fd, srv_addr, srv_len) == 0) { + return (fd); + }else { + if (errno != ETIMEDOUT && + errno != ECONNREFUSED) { + goto exit_func; + } + } + + sleep(MAXWAIT - wait); + } +exit_func: + close(fd); + return (-1); + +} + +/** + * @brief + * cs_tcp_comm_connect -- + * + * This function initiates a tcp connect stream connection. + * Used for demo purposes at this point. + * + * @param[in] srv_addr sockaddr structure of server + * @param[in] srv_len len of server sockaddr + * + * @return socket fd is successful, -1 if not + */ +int +cs_tcp_comm_connect(const struct sockaddr *srv_addr, socklen_t srv_len) +{ + return (cs_comm_connect(AF_INET, SOCK_STREAM, 0, srv_addr, srv_len)); +} + +/** + * @brief + * cs_udp_comm_connect -- + * + * This function initiates a udp connect stream connection. + * Used for demo purposes at this point. + * + * @param[in] srv_addr sockaddr structure of server + * @param[in] srv_len len of server sockaddr + * + * @return socket fd is successful, -1 if not + */ +int +cs_udp_comm_connect(const struct sockaddr *srv_addr, socklen_t srv_len) +{ + return (cs_comm_connect(AF_INET, SOCK_DGRAM, 0, srv_addr, srv_len)); +} + +/** + * @brief + * + * cs_set_fd_non_block -- + * + * This function sets the fd passed in to non-blocking. + * + * @params[in] fd file descriptor + * + * @return 1 on success, (-1) on failure + * + */ +int +cs_set_fd_non_block(int fd) +{ + /* TBD on vxworks */ +#ifdef __LINUX__ + int options; + + if ((options = fcntl(fd, F_GETFL)) < 0) { + IB_LOG_ERROR_FMT(__func__, "fcntl get Error %s\n", + strerror(errno)); + return (-1); + } + + options |= O_NONBLOCK; + + if (fcntl(fd, F_SETFL, options) < 0) { + IB_LOG_ERROR_FMT(__func__, "fcntl set Error %s\n", + strerror(errno)); + return (-1); + } +#endif + + return (1); +} + + diff --git a/Esm/ib/src/cs/cs_string.c b/Esm/ib/src/cs/cs_string.c new file mode 100644 index 0000000..af358de --- /dev/null +++ b/Esm/ib/src/cs/cs_string.c @@ -0,0 +1,1463 @@ +/* BEGIN_ICS_COPYRIGHT5 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + * ** END_ICS_COPYRIGHT5 ****************************************/ + +/*********************************************************************** +* +* FILE NAME +* cs_string.c +* +* DESCRIPTION +* This file contains the implementation of the String Conversion +* services. +* +* DATA STRUCTURES +* +* FUNCTIONS +* cs_strtoui8 +* cs_strtoui16 +* cs_strtoui32 +* cs_strtoui64 +* cs_strtoi8 +* cs_strtoi16 +* cs_strtoui32 +* cs_strtoi64 +* cs_parse_gid +* +* DEPENDENCIES +* cs_g.h +* +* +* HISTORY +* +* NAME DATE REMARKS +* MGR 05/01/02 PR1754. Initial creation of file. +* MGR 05/06/02 PR1754. Added support for functions. +* MGR 05/07/02 PR1812. Clean-up lint errors. +* +***********************************************************************/ +#include "ib_types.h" +#include "ib_status.h" +#include "cs_g.h" +#include "vs_g.h" +#include "cs_log.h" +#include +#define function __FUNCTION__ +#ifdef LOCAL_MOD_ID +#undef LOCAL_MOD_ID +#endif +#define LOCAL_MOD_ID VIEO_CS_MOD_ID + + + + +/********************************************************************** +* +* FUNCTION +* cs_strtoui8 +* +* DESCRIPTION +* Convert a string to an unsigned 8-bit integer. +* +* INPUTS +* nptr - A pointer to the string to convert. +* return_error - Value to return on error. +* +* OUTPUTS +* cvalue - On success, the converted value is returned. +* +* +* HISTORY +* +* NAME DATE REMARKS +* MGR 05/01/02 Initial creation of function. +* +**********************************************************************/ +uint8_t +cs_strtoui8 (const char *nptr, uint8_t return_error) +{ + uint32_t base = 0; + int overflow = 0; + uint8_t digit; + uint8_t cvalue = 0; + uint32_t maxdiv; + uint32_t maxrem; + + IB_ENTER (function, + (unint)nptr, + (uint32_t)return_error, + (uint32_t)0U, + (uint32_t)0U); + + /* + ** Validate string pointer + */ + if (nptr == (char *)0) + { + IB_LOG_ERROR0 ("NULL pointer"); + IB_EXIT (function, (uint32_t)return_error); + return return_error; + } + + /* + ** Skip leading spaces + */ + while (*nptr == ' ') + { + nptr++; + } + + /* + ** Allow a leading '+'; however negative values are not allowed. + */ + if (*nptr == '+') + { + nptr++; + } + else if (*nptr == '-') + { + IB_LOG_ERROR0 ("negative values are invalid"); + IB_EXIT (function, (uint32_t)return_error); + return return_error; + } + + /* + * Determine the base + */ + if (*nptr != '0') + { + /* decimal string */ + base = 10; + IB_LOG_INFO ("string is decimal", (uint32_t)base); + } + else + { + /* first 'real' character is a 0 */ + if (nptr[1] == 'X' || nptr[1] == 'x') + { + /* hexadecimal string */ + base = 16; + nptr += 2; + IB_LOG_INFO ("string is hexadecimal", (uint32_t)base); + } + else + { + /* decimal string */ + base = 10; + IB_LOG_INFO ("string is decimal", (uint32_t)base); + } + } + + maxdiv = UINT8_MAX / base; + maxrem = UINT8_MAX % base; + + while ((digit = *nptr) != '\0') + { + if (digit >= '0' && digit < ('0' + base)) + { + digit -= '0'; + } + else + { + if (base > 10) + { + if (digit >= 'a' && digit < ('a' + (base - 10))) + { + digit = digit - 'a' + 10; + } + else if (digit >= 'A' && digit < ('A' + (base - 10))) + { + digit = digit - 'A' + 10; + } + else + { + IB_LOG_ERROR ("invalid digit:", (uint32_t)digit); + IB_EXIT (function, (uint32_t)return_error); + return return_error; + } + } + else + { + IB_LOG_ERROR ("invalid digit:", (uint32_t)digit); + IB_EXIT (function, (uint32_t)return_error); + return return_error; + } + } + + if (cvalue > maxdiv || (cvalue == maxdiv && digit > maxrem)) + { + overflow = 1; + } + + cvalue = (cvalue * base) + digit; + nptr++; + } + + if (overflow) + { + IB_LOG_ERROR0 ("string value is too large"); + IB_EXIT (function, (uint32_t)return_error); + return return_error; + } + + IB_EXIT (function, (uint32_t)cvalue); + return cvalue; +} + +/********************************************************************** +* +* FUNCTION +* cs_strtoui16 +* +* DESCRIPTION +* Convert a string to an unsigned 16-bit integer. +* +* INPUTS +* nptr - A pointer to the string to convert. +* return_error - Value to return on error. +* +* OUTPUTS +* cvalue - On success, the converted value is returned. +* +* +* HISTORY +* +* NAME DATE REMARKS +* MGR 05/01/02 Initial creation of function. +* +**********************************************************************/ +uint16_t +cs_strtoui16 (const char *nptr, uint16_t return_error) +{ + uint32_t base = 0; + int overflow = 0; + uint8_t digit; + uint16_t cvalue = 0; + uint32_t maxdiv; + uint32_t maxrem; + + IB_ENTER (function, + (unint)nptr, + (uint32_t)return_error, + (uint32_t)0U, + (uint32_t)0U); + + /* + ** Validate string pointer + */ + if (nptr == (char *)0) + { + IB_LOG_ERROR0 ("NULL pointer"); + IB_EXIT (function, (uint32_t)return_error); + return return_error; + } + + /* + ** Skip leading spaces + */ + while (*nptr == ' ') + { + nptr++; + } + + /* + ** Allow a leading '+'; however negative values are not allowed. + */ + if (*nptr == '+') + { + nptr++; + } + else if (*nptr == '-') + { + IB_LOG_ERROR0 ("negative values are invalid"); + IB_EXIT (function, (uint32_t)return_error); + return return_error; + } + + /* + * Determine the base + */ + if (*nptr != '0') + { + /* decimal string */ + base = 10; + IB_LOG_INFO ("string is decimal", (uint32_t)base); + } + else + { + /* first 'real' character is a 0 */ + if (nptr[1] == 'X' || nptr[1] == 'x') + { + /* hexadecimal string */ + base = 16; + nptr += 2; + IB_LOG_INFO ("string is hexadecimal", (uint32_t)base); + } + else + { + /* decimal string */ + base = 10; + IB_LOG_INFO ("string is decimal", (uint32_t)base); + } + } + + maxdiv = UINT16_MAX / base; + maxrem = UINT16_MAX % base; + + while ((digit = *nptr) != '\0') + { + if (digit >= '0' && digit < ('0' + base)) + { + digit -= '0'; + } + else + { + if (base > 10) + { + if (digit >= 'a' && digit < ('a' + (base - 10))) + { + digit = digit - 'a' + 10; + } + else if (digit >= 'A' && digit < ('A' + (base - 10))) + { + digit = digit - 'A' + 10; + } + else + { + IB_LOG_ERROR ("invalid digit:", (uint32_t)digit); + IB_EXIT (function, (uint32_t)return_error); + return return_error; + } + } + else + { + IB_LOG_ERROR ("invalid digit:", (uint32_t)digit); + IB_EXIT (function, (uint32_t)return_error); + return return_error; + } + } + + if (cvalue > maxdiv || (cvalue == maxdiv && digit > maxrem)) + { + overflow = 1; + } + + cvalue = (cvalue * base) + digit; + nptr++; + } + + if (overflow) + { + IB_LOG_ERROR0 ("string value is too large"); + IB_EXIT (function, (uint32_t)return_error); + return return_error; + } + + IB_EXIT (function, (uint32_t)cvalue); + return cvalue; +} + +/********************************************************************** +* +* FUNCTION +* cs_strtoui32 +* +* DESCRIPTION +* Convert a string to an unsigned 32-bit integer. +* +* INPUTS +* nptr - A pointer to the string to convert. +* return_error - Value to return on error. +* +* OUTPUTS +* cvalue - On success, the converted value is returned. +* +* +* HISTORY +* +* NAME DATE REMARKS +* MGR 05/01/02 Initial creation of function. +* +**********************************************************************/ +uint32_t +cs_strtoui32 (const char *nptr, uint32_t return_error) +{ + uint32_t base = 0; + int overflow = 0; + uint8_t digit; + uint32_t cvalue = 0; + uint32_t maxdiv; + uint32_t maxrem; + + IB_ENTER (function, + (unint)nptr, + (uint32_t)return_error, + (uint32_t)0U, + (uint32_t)0U); + + /* + ** Validate string pointer + */ + if (nptr == (char *)0) + { + IB_LOG_ERROR0 ("NULL pointer"); + IB_EXIT (function, (uint32_t)return_error); + return return_error; + } + + /* + ** Skip leading spaces + */ + while (*nptr == ' ') + { + nptr++; + } + + /* + ** Allow a leading '+'; however negative values are not allowed. + */ + if (*nptr == '+') + { + nptr++; + } + else if (*nptr == '-') + { + IB_LOG_ERROR0 ("negative values are invalid"); + IB_EXIT (function, (uint32_t)return_error); + return return_error; + } + + /* + * Determine the base + */ + if (*nptr != '0') + { + /* decimal string */ + base = 10; + IB_LOG_INFO ("string is decimal", (uint32_t)base); + } + else + { + /* first 'real' character is a 0 */ + if (nptr[1] == 'X' || nptr[1] == 'x') + { + /* hexadecimal string */ + base = 16; + nptr += 2; + IB_LOG_INFO ("string is hexadecimal", (uint32_t)base); + } + else + { + /* decimal string */ + base = 10; + IB_LOG_INFO ("string is decimal", (uint32_t)base); + } + } + + maxdiv = UINT32_MAX / base; + maxrem = UINT32_MAX % base; + + while ((digit = *nptr) != '\0') + { + if (digit >= '0' && digit < ('0' + base)) + { + digit -= '0'; + } + else + { + if (base > 10) + { + if (digit >= 'a' && digit < ('a' + (base - 10))) + { + digit = digit - 'a' + 10; + } + else if (digit >= 'A' && digit < ('A' + (base - 10))) + { + digit = digit - 'A' + 10; + } + else + { + IB_LOG_ERROR ("invalid digit:", (uint32_t)digit); + IB_EXIT (function, (uint32_t)return_error); + return return_error; + } + } + else + { + IB_LOG_ERROR ("invalid digit:", (uint32_t)digit); + IB_EXIT (function, (uint32_t)return_error); + return return_error; + } + } + + if (cvalue > maxdiv || (cvalue == maxdiv && digit > maxrem)) + { + overflow = 1; + } + + cvalue = (cvalue * base) + digit; + nptr++; + } + + if (overflow) + { + IB_LOG_ERROR0 ("string value is too large"); + IB_EXIT (function, (uint32_t)return_error); + return return_error; + } + + IB_EXIT (function, (uint32_t)cvalue); + return cvalue; +} + +/********************************************************************** +* +* FUNCTION +* cs_strtoui64 +* +* DESCRIPTION +* Convert a string to an unsigned 64-bit integer. +* +* INPUTS +* nptr - A pointer to the string to convert. +* return_error - Value to return on error. +* +* OUTPUTS +* cvalue - On success, the converted value is returned. +* +* +* HISTORY +* +* NAME DATE REMARKS +* MGR 05/01/02 Initial creation of function. +* PJG 05/28/02 PR2166 Suffix 64-bit constants with ll to +* eliminate warnings. +* +**********************************************************************/ +uint64_t +cs_strtoui64 (const char *nptr, uint64_t return_error) +{ + uint32_t base = 0; + int overflow = 0; + uint8_t digit; + uint64_t cvalue = 0; + uint64_t maxdiv = 0; + uint64_t maxrem = 0; + + IB_ENTER (function, + (unint)nptr, + (uint32_t)return_error, + (uint32_t)0U, + (uint32_t)0U); + + /* + ** Validate string pointer + */ + if (nptr == (char *)0) + { + IB_LOG_ERROR0 ("NULL pointer"); + IB_EXIT (function, (uint32_t)return_error); + return return_error; + } + + /* + ** Skip leading spaces + */ + while (*nptr == ' ') + { + nptr++; + } + + /* + ** Allow a leading '+'; however negative values are not allowed. + */ + if (*nptr == '+') + { + nptr++; + } + else if (*nptr == '-') + { + IB_LOG_ERROR0 ("negative values are invalid"); + IB_EXIT (function, (uint32_t)return_error); + return return_error; + } + + /* + * Determine the base + */ + if (*nptr != '0') + { + /* decimal string */ + base = 10; + IB_LOG_INFO ("string is decimal", (uint32_t)base); + } + else + { + /* first 'real' character is a 0 */ + if (nptr[1] == 'X' || nptr[1] == 'x') + { + /* hexadecimal string */ + base = 16; + nptr += 2; + IB_LOG_INFO ("string is hexadecimal", (uint32_t)base); + } + else + { + /* decimal string */ + base = 10; + IB_LOG_INFO ("string is decimal", (uint32_t)base); + } + } + + /* Hardcode these values since it causes module load errors */ + if (base == 10) + { + maxdiv = 1844674407370955161ll; + maxrem = 5; + } + else if (base == 16) + { + maxdiv = 1152921504606846975ll; + maxrem = 15; + } + + while ((digit = *nptr) != '\0') + { + if (digit >= '0' && digit < ('0' + base)) + { + digit -= '0'; + } + else + { + if (base > 10) + { + if (digit >= 'a' && digit < ('a' + (base - 10))) + { + digit = digit - 'a' + 10; + } + else if (digit >= 'A' && digit < ('A' + (base - 10))) + { + digit = digit - 'A' + 10; + } + else + { + IB_LOG_ERROR ("invalid digit:", (uint32_t)digit); + IB_EXIT (function, (uint32_t)return_error); + return return_error; + } + } + else + { + IB_LOG_ERROR ("invalid digit:", (uint32_t)digit); + IB_EXIT (function, (uint32_t)return_error); + return return_error; + } + } + + if (cvalue > maxdiv || (cvalue == maxdiv && digit > maxrem)) + { + overflow = 1; + } + + cvalue = (cvalue * base) + digit; + nptr++; + } + + if (overflow) + { + IB_LOG_ERROR0 ("string value is too large"); + IB_EXIT (function, (uint32_t)return_error); + return return_error; + } + + IB_EXIT (function, (uint32_t)cvalue); + return cvalue; +} + +/********************************************************************** +* +* FUNCTION +* cs_strtoi8 +* +* DESCRIPTION +* Convert a string to a signed 8-bit integer. +* +* INPUTS +* nptr - A pointer to the string to convert. +* return_error - Value to return on error. +* +* OUTPUTS +* cvalue - On success, the converted value is returned. +* +* +* HISTORY +* +* NAME DATE REMARKS +* MGR 05/01/02 Initial creation of function. +* +**********************************************************************/ +int8_t +cs_strtoi8 (const char *nptr, int8_t return_error) +{ + int base = 0; + int negate = 0; + int8_t cvalue = 0; + int8_t digit; + + IB_ENTER (function, + nptr, + (uint32_t)(int32_t)return_error, + 0U, + 0U); + + /* + ** Validate string pointer + */ + if (nptr == (char *)0) + { + IB_LOG_ERROR0 ("NULL pointer"); + IB_EXIT (function, (uint32_t)(int32_t)return_error); + return return_error; + } + + /* + ** Skip leading spaces + */ + while (*nptr == ' ') + { + nptr++; + } + + /* + ** Allow a leading '+'; however negative values are not allowed. + */ + if (*nptr == '+') + { + nptr++; + } + else if (*nptr == '-') + { + negate = 1; + nptr++; + } + + /* + * Determine the base + */ + if (*nptr != '0') + { + /* decimal string */ + base = 10; + IB_LOG_INFO ("string is decimal", (uint32_t)base); + } + else + { + /* first 'real' character is a 0 */ + if (nptr[1] == 'X' || nptr[1] == 'x') + { + /* hexadecimal string */ + base = 16; + nptr += 2; + IB_LOG_INFO ("string is hexadecimal", (uint32_t)base); + } + else + { + /* decimal string */ + base = 10; + IB_LOG_INFO ("string is decimal", (uint32_t)base); + } + } + + while ((digit = *nptr) != '\0') + { + if (digit >= '0' && digit < ('0' + base)) + { + digit -= '0'; + } + else + { + if (base > 10) + { + if (digit >= 'a' && digit < ('a' + (base - 10))) + { + digit = digit - 'a' + 10; + } + else if (digit >= 'A' && digit < ('A' + (base - 10))) + { + digit = digit - 'A' + 10; + } + else + { + IB_LOG_ERROR ("invalid digit:", (uint32_t)(int32_t)digit); + IB_EXIT (function, (uint32_t)(int32_t)return_error); + return return_error; + } + } + else + { + IB_LOG_ERROR ("invalid digit:", (uint32_t)(int32_t)digit); + IB_EXIT (function, (uint32_t)(int32_t)return_error); + return return_error; + } + } + + if (negate == 1) + { + digit = -digit; + if ((cvalue > (INT8_MIN / base)) || + ((cvalue == (INT8_MIN / base)) && (digit >= (INT8_MIN % base)))) + { + cvalue = cvalue * base; + cvalue += digit; + } + else + { + IB_LOG_ERROR0 ("string value is too small"); + IB_EXIT (function, (uint32_t)(int32_t)return_error); + return return_error; + } + } + else + { + if ((cvalue < (INT8_MAX / base)) || + ((cvalue == (INT8_MAX / base)) && (digit <= (INT8_MAX % base)))) + { + cvalue = cvalue * base; + cvalue += digit; + } + else + { + IB_LOG_ERROR0 ("string value is too large"); + IB_EXIT (function, (uint32_t)(int32_t)return_error); + return return_error; + } + } + nptr++; + } + + IB_EXIT (function, (uint32_t)(int32_t)cvalue); + return cvalue; +} + +/********************************************************************** +* +* FUNCTION +* cs_strtoi16 +* +* DESCRIPTION +* Convert a string to a signed 16-bit integer. +* +* INPUTS +* nptr - A pointer to the string to convert. +* return_error - Value to return on error. +* +* OUTPUTS +* cvalue - On success, the converted value is returned. +* +* +* HISTORY +* +* NAME DATE REMARKS +* MGR 05/01/02 Initial creation of function. +* +**********************************************************************/ +int16_t +cs_strtoi16 (const char *nptr, int16_t return_error) +{ + int base = 0; + int negate = 0; + int16_t cvalue = 0; + int8_t digit; + + IB_ENTER (function, + (unint)nptr, + (uint32_t)(int32_t)return_error, + (uint32_t)0U, + (uint32_t)0U); + + /* + ** Validate string pointer + */ + if (nptr == (char *)0) + { + IB_LOG_ERROR0 ("NULL pointer"); + IB_EXIT (function, (uint32_t)(int32_t)return_error); + return return_error; + } + + /* + ** Skip leading spaces + */ + while (*nptr == ' ') + { + nptr++; + } + + /* + ** Allow a leading '+'; however negative values are not allowed. + */ + if (*nptr == '+') + { + nptr++; + } + else if (*nptr == '-') + { + negate = 1; + nptr++; + } + + /* + * Determine the base + */ + if (*nptr != '0') + { + /* decimal string */ + base = 10; + IB_LOG_INFO ("string is decimal", (uint32_t)base); + } + else + { + /* first 'real' character is a 0 */ + if (nptr[1] == 'X' || nptr[1] == 'x') + { + /* hexadecimal string */ + base = 16; + nptr += 2; + IB_LOG_INFO ("string is hexadecimal", (uint32_t)base); + } + else + { + /* decimal string */ + base = 10; + IB_LOG_INFO ("string is decimal", (uint32_t)base); + } + } + + while ((digit = *nptr) != '\0') + { + if (digit >= '0' && digit < ('0' + base)) + { + digit -= '0'; + } + else + { + if (base > 10) + { + if (digit >= 'a' && digit < ('a' + (base - 10))) + { + digit = digit - 'a' + 10; + } + else if (digit >= 'A' && digit < ('A' + (base - 10))) + { + digit = digit - 'A' + 10; + } + else + { + IB_LOG_ERROR ("invalid digit:", (uint32_t)(int32_t)digit); + IB_EXIT (function, (uint32_t)(int32_t)return_error); + return return_error; + } + } + else + { + IB_LOG_ERROR ("invalid digit:", (uint32_t)(int32_t)digit); + IB_EXIT (function, (uint32_t)(int32_t)return_error); + return return_error; + } + } + + if (negate == 1) + { + digit = -digit; + if ((cvalue > (INT16_MIN / base)) || + ((cvalue == (INT16_MIN / base)) && (digit >= (INT16_MIN % base)))) + { + cvalue = cvalue * base; + cvalue += digit; + } + else + { + IB_LOG_ERROR0 ("string value is too small"); + IB_EXIT (function, (uint32_t)(int32_t)return_error); + return return_error; + } + } + else + { + if ((cvalue < (INT16_MAX / base)) || + ((cvalue == (INT16_MAX / base)) && (digit <= (INT16_MAX % base)))) + { + cvalue = cvalue * base; + cvalue += digit; + } + else + { + IB_LOG_ERROR0 ("string value is too large"); + IB_EXIT (function, (uint32_t)(int32_t)return_error); + return return_error; + } + } + nptr++; + } + + IB_EXIT (function, (uint32_t)(int32_t)cvalue); + return cvalue; +} + +/********************************************************************** +* +* FUNCTION +* cs_strtoi32 +* +* DESCRIPTION +* Convert a string to a signed 32-bit integer. +* +* INPUTS +* nptr - A pointer to the string to convert. +* return_error - Value to return on error. +* +* OUTPUTS +* cvalue - On success, the converted value is returned. +* +* +* HISTORY +* +* NAME DATE REMARKS +* MGR 05/01/02 Initial creation of function. +* +**********************************************************************/ +int32_t +cs_strtoi32 (const char *nptr, int32_t return_error) +{ + int base = 0; + int negate = 0; + int32_t cvalue = 0; + int8_t digit; + + IB_ENTER (function, + (unint)nptr, + (uint32_t)return_error, + (uint32_t)0U, + (uint32_t)0U); + + /* + ** Validate string pointer + */ + if (nptr == (char *)0) + { + IB_LOG_ERROR0 ("NULL pointer"); + IB_EXIT (function, (uint32_t)return_error); + return return_error; + } + + /* + ** Skip leading spaces + */ + while (*nptr == ' ') + { + nptr++; + } + + /* + ** Allow a leading '+'; however negative values are not allowed. + */ + if (*nptr == '+') + { + nptr++; + } + else if (*nptr == '-') + { + negate = 1; + nptr++; + } + + /* + * Determine the base + */ + if (*nptr != '0') + { + /* decimal string */ + base = 10; + IB_LOG_INFO ("string is decimal", (uint32_t)base); + } + else + { + /* first 'real' character is a 0 */ + if (nptr[1] == 'X' || nptr[1] == 'x') + { + /* hexadecimal string */ + base = 16; + nptr += 2; + IB_LOG_INFO ("string is hexadecimal", (uint32_t)base); + } + else + { + /* decimal string */ + base = 10; + IB_LOG_INFO ("string is decimal", (uint32_t)base); + } + } + + while ((digit = *nptr) != '\0') + { + if (digit >= '0' && digit < ('0' + base)) + { + digit -= '0'; + } + else + { + if (base > 10) + { + if (digit >= 'a' && digit < ('a' + (base - 10))) + { + digit = digit - 'a' + 10; + } + else if (digit >= 'A' && digit < ('A' + (base - 10))) + { + digit = digit - 'A' + 10; + } + else + { + IB_LOG_ERROR ("invalid digit:", (uint32_t)(int32_t)digit); + IB_EXIT (function, (uint32_t)return_error); + return return_error; + } + } + else + { + IB_LOG_ERROR ("invalid digit:", (uint32_t)(int32_t)digit); + IB_EXIT (function, (uint32_t)return_error); + return return_error; + } + } + + if (negate == 1) + { + digit = -digit; + if ((cvalue > (INT32_MIN / base)) || + ((cvalue == (INT32_MIN / base)) && (digit >= (INT32_MIN % base)))) + { + cvalue = cvalue * base; + cvalue += digit; + } + else + { + IB_LOG_ERROR0 ("string value is too small"); + IB_EXIT (function, (uint32_t)return_error); + return return_error; + } + } + else + { + if ((cvalue < (INT32_MAX / base)) || + ((cvalue == (INT32_MAX / base)) && (digit <= (INT32_MAX % base)))) + { + cvalue = cvalue * base; + cvalue += digit; + } + else + { + IB_LOG_ERROR0 ("string value is too large"); + IB_EXIT (function, (uint32_t)return_error); + return return_error; + } + } + nptr++; + } + + IB_EXIT (function, (uint32_t)cvalue); + return cvalue; +} + +/********************************************************************** +* +* FUNCTION +* cs_strtoi64 +* +* DESCRIPTION +* Convert a string to a signed 64-bit integer. +* +* INPUTS +* nptr - A pointer to the string to convert. +* return_error - Value to return on error. +* +* OUTPUTS +* cvalue - On success, the converted value is returned. +* +* +* HISTORY +* +* NAME DATE REMARKS +* MGR 05/01/02 Initial creation of function. +* PJG 05/28/02 PR2166 Suffix 64-bit constants with ll to +* eliminate warnings. +* +**********************************************************************/ +int64_t +cs_strtoi64 (const char *nptr, int64_t return_error) +{ + int base = 0; + int negate = 0; + int8_t digit; + int64_t cvalue = 0; + + IB_ENTER (function, + (unint)nptr, + (uint32_t)return_error, + (uint32_t)0U, + (uint32_t)0U); + + /* + ** Validate string pointer + */ + if (nptr == (char *)0) + { + IB_LOG_ERROR0 ("NULL pointer"); + IB_EXIT (function, (uint32_t)return_error); + return return_error; + } + + /* + ** Skip leading spaces + */ + while (*nptr == ' ') + { + nptr++; + } + + /* + ** Allow a leading '+'; however negative values are not allowed. + */ + if (*nptr == '+') + { + nptr++; + } + else if (*nptr == '-') + { + negate = 1; + nptr++; + } + + /* + * Determine the base + */ + if (*nptr != '0') + { + /* decimal string */ + base = 10; + IB_LOG_INFO ("string is decimal", (uint32_t)base); + } + else + { + /* first 'real' character is a 0 */ + if (nptr[1] == 'X' || nptr[1] == 'x') + { + /* hexadecimal string */ + base = 16; + nptr += 2; + IB_LOG_INFO ("string is hexadecimal", (uint32_t)base); + } + else + { + /* decimal string */ + base = 10; + IB_LOG_INFO ("string is decimal", (uint32_t)base); + } + } + + while ((digit = *nptr) != '\0') + { + if (digit >= '0' && digit < ('0' + base)) + { + digit -= '0'; + } + else + { + if (base > 10) + { + if (digit >= 'a' && digit < ('a' + (base - 10))) + { + digit = digit - 'a' + 10; + } + else if (digit >= 'A' && digit < ('A' + (base - 10))) + { + digit = digit - 'A' + 10; + } + else + { + IB_LOG_ERROR ("invalid digit:", (uint32_t)(int32_t)digit); + IB_EXIT (function, (uint32_t)return_error); + return return_error; + } + } + else + { + IB_LOG_ERROR ("invalid digit:", (uint32_t)(int32_t)digit); + IB_EXIT (function, (uint32_t)return_error); + return return_error; + } + } + + if (negate == 1) + { + digit = -digit; + if ((cvalue > -922337203685477580ll) || + ((cvalue == -922337203685477580ll) && (digit >= -8))) + { + cvalue = cvalue * base; + cvalue += digit; + } + else + { + IB_LOG_ERROR0 ("string value is too small"); + IB_EXIT (function, (uint32_t)return_error); + return return_error; + } + } + else + { + if ((cvalue < 922337203685477580ll) || + ((cvalue == 922337203685477580ll) && (digit <= 7))) + { + cvalue = cvalue * base; + cvalue += digit; + } + else + { + IB_LOG_ERROR0 ("string value is too large"); + IB_EXIT (function, (uint32_t)return_error); + return return_error; + } + } + nptr++; + } + + IB_EXIT (function, (uint32_t)cvalue); + return cvalue; +} + +//==============================================================================// +// +// FUNCTION +// cs_parse_gid +// +// DESCRIPTION +// Converts an asci representation of a GID in hex of the format: +// (0[xX])?[[:hex:]]{32} +// into a Gid_t. Returns VSTATUS_OK upon success. +// +// INPUTS +// str - the string to parse +// gid - the gid in which to store the value +// +// OUTPUTS +// +// +// HISTORY +// +// NAME DATE REMARKS +// +//==============================================================================// +Status_t +cs_parse_gid(const char * str, Gid_t gid) +{ + uint8_t * tmp = (uint8_t *) gid; + int i = 0; + const char * myPtr = NULL; + char myNum[3]; + Status_t rc = VSTATUS_OK; + + IB_ENTER(__FUNCTION__, str, gid, 0, 0); + + if ( (str[0] == '0') + && ( (str[1] == 'x') || (str[1] == 'X') ) ) + myPtr = str + 2; + else + myPtr = str; + + if (strlen(myPtr) == 32) + { + for (i = 0; i < 16; ++i) + { + memcpy(myNum, myPtr + (i << 1), 2); + myNum[2] = '\0'; + + tmp[i] = strtoul(myNum, NULL, 16); + } + } else + { + rc = VSTATUS_ILLPARM; + } + + IB_EXIT(__FUNCTION__, rc); + return rc; +} + +/********************************************************************** +* +* DESCRIPTION +* Invokes snprintf to append the format string into the +* passed buffer. Will adjust the provided buffer pointer +* to just beyond the concatenated portion, and decrement +* len accordingly, such that a chain of invocations function +* as appends. +* +* INPUTS +* buf - Pointer to the output buffer. Will be incremented by +* the number of bytes written. +* len - Pointer to the remaining length. Will be decremented by +* the number of bytes written. +* fmt - printf-style format string. +* ... - pritnf-style format string arguments. +* +* OUTPUTS +* Returns the return value of printf. +* +**********************************************************************/ +int cs_snprintfcat(char ** buf, size_t * len, char * fmt, ...) +{ + if (!buf || !len || !fmt || !*len) + return 0; + + va_list(args); + va_start(args, fmt); + int n = vsnprintf(*buf, *len, fmt, args); + va_end(args); + + if (n <= 0) return n; + + // printf returns number of bytes that *would* be written. + // correct to actual bytes written + size_t m = MIN((size_t)n, *len); + + *buf += m; + *len -= m; + + return n; +} + diff --git a/Esm/ib/src/cs/cs_utility.c b/Esm/ib/src/cs/cs_utility.c new file mode 100644 index 0000000..dd0c0ac --- /dev/null +++ b/Esm/ib/src/cs/cs_utility.c @@ -0,0 +1,712 @@ +/* BEGIN_ICS_COPYRIGHT5 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + * ** END_ICS_COPYRIGHT5 ****************************************/ + +//==============================================================================// +// // +// FILE NAME // +// cs_utility.c // +// // +// DESCRIPTION // +// This file contains miscellaneous utility routiness. // +// // +// DATA STRUCTURES // +// None // +// // +// FUNCTIONS // +// bm_log write out logging information // +// // +// DEPENDENCIES // +// // +// HISTORY // +// // +// NAME DATE REMARKS // +// sjb 04/09/04 Initial creation of file. // +// // +//==============================================================================// + + +#include +#include +#include +#include "cs_log.h" +#include "cs_queue.h" +#include "stl_mad_priv.h" +#include "ib_mad.h" +#include "ib_sa.h" +#include "stl_pa_priv.h" +#include "sm_l.h" +#include "stl_sa_priv.h" + + +#include "mai_g.h" +#include "sm_dbsync.h" +#include "if3.h" + + +uint32_t cs_log_masks[VIEO_LAST_MOD_ID+1] = { + DEFAULT_LOG_MASK, // VIEO_NONE_MOD_ID for vs_syslog_output_message + 0, // VIEO_CS_MOD_ID /* Library Modules */ + DEFAULT_LOG_MASK, // VIEO_MAI_MOD_ID + DEFAULT_LOG_MASK, // VIEO_CAL_MOD_ID + DEFAULT_LOG_MASK, // VIEO_DRIVER_MOD_ID + DEFAULT_LOG_MASK, // VIEO_IF3_MOD_ID + DEFAULT_LOG_MASK, // VIEO_SM_MOD_ID /* Subnet Mgr */ + DEFAULT_LOG_MASK, // VIEO_SA_MOD_ID /* Subnet Administrator */ + DEFAULT_LOG_MASK, // VIEO_PM_MOD_ID /* Performance Mgr */ + DEFAULT_LOG_MASK, // VIEO_PA_MOD_ID /* Performance Administrator */ + DEFAULT_LOG_MASK, // VIEO_BM_MOD_ID /* Baseboard Mgr */ + DEFAULT_LOG_MASK, // VIEO_FE_MOD_ID /* Fabric Executive */ + DEFAULT_LOG_MASK, // VIEO_APP_MOD_ID /* Generic VIEO mod id */ +}; + +// module name in form of "name: ", useful for messages where name is optional +// for VIEO_NONE_MOD_ID, returns "" +const char * +cs_log_get_module_prefix(uint32_t modid) +{ + switch (modid) { + case VIEO_NONE_MOD_ID: return ""; + case VIEO_CS_MOD_ID: return "CS: "; + case VIEO_MAI_MOD_ID: return "MAI: "; + case VIEO_CAL_MOD_ID: return "CAL: "; + case VIEO_DRIVER_MOD_ID:return "DVR: "; + case VIEO_IF3_MOD_ID: return "IF3: "; + case VIEO_SM_MOD_ID: return "SM: "; + case VIEO_SA_MOD_ID: return "SA: "; + case VIEO_PM_MOD_ID: return "PM: "; + case VIEO_PA_MOD_ID: return "PA: "; + case VIEO_BM_MOD_ID: return "BM: "; + case VIEO_FE_MOD_ID: return "FE: "; + case VIEO_APP_MOD_ID: return "APP: "; + default: return "Unkwn: "; + } +} + +// module name in simple form, useful to put in middle of other messages +// names provided also match prefixes used in LogMask config file names +// for VIEO_NONE_MOD_ID, returns "NONE" +const char * +cs_log_get_module_name(uint32_t modid) +{ + switch (modid) { + case VIEO_NONE_MOD_ID: return "NONE"; + case VIEO_CS_MOD_ID: return "CS"; + case VIEO_MAI_MOD_ID: return "MAI"; + case VIEO_CAL_MOD_ID: return "CAL"; + case VIEO_DRIVER_MOD_ID:return "DVR"; + case VIEO_IF3_MOD_ID: return "IF3"; + case VIEO_SM_MOD_ID: return "SM"; + case VIEO_SA_MOD_ID: return "SA"; + case VIEO_PM_MOD_ID: return "PM"; + case VIEO_PA_MOD_ID: return "PA"; + case VIEO_BM_MOD_ID: return "BM"; + case VIEO_FE_MOD_ID: return "FE"; + case VIEO_APP_MOD_ID: return "APP"; + default: return "Unkwn"; + } +} + +// convert module name to modid +// names provided also match prefixes used in LogMask config file names +uint32_t +cs_log_get_module_id(const char * mod) +{ + uint32_t modid; + + for (modid = 0 ; modid <= VIEO_LAST_MOD_ID; modid++) { + if (modid == VIEO_NONE_MOD_ID) + continue; + if (0 == strcmp(cs_log_get_module_name(modid), mod)) + return modid; + } + return 0; // VIEO_NONE_MOD_ID +} + +const char* +cs_log_get_sev_name(uint32_t sev) +{ + switch (sev) { + case VS_LOG_NONE: return ""; + case VS_LOG_FATAL: return "FATAL"; + case VS_LOG_CSM_ERROR: return "ERROR"; + case VS_LOG_CSM_WARN: return "WARN "; + case VS_LOG_CSM_NOTICE: return "NOTIC"; + case VS_LOG_CSM_INFO: return "INFO "; + case VS_LOG_ERROR: return "ERROR"; + case VS_LOG_WARN: return "WARN "; + case VS_LOG_NOTICE: return "NOTIC"; + case VS_LOG_INFINI_INFO:return "PROGR"; + case VS_LOG_INFO: return "INFO "; + case VS_LOG_VERBOSE: return "VBOSE"; + case VS_LOG_DATA: return "DATA "; + case VS_LOG_DEBUG1: return "DBG1 "; + case VS_LOG_DEBUG2: return "DBG2 "; + case VS_LOG_DEBUG3: return "DBG3 "; + case VS_LOG_DEBUG4: return "DBG4 "; + case VS_LOG_ENTER: return "ENTER"; + case VS_LOG_ARGS: return "ARGS "; + case VS_LOG_EXIT: return "EXIT "; + default: return "UNKWN"; + } +} + +// translate level and mode to a sev_mask and a mod_mask of modules +// which sev_mask should be set for. modules not in mod_mask +// should get a sev_mask of 0 +static void +cs_log_translate_level(uint32_t level, int mode, + uint32_t *mod_mask, uint32_t *sev_mask) +{ + switch(level) + { + case 5: + /* All of the modules on. */ + *mod_mask = VS_MOD_ALL; + break; + default: + *mod_mask = (VS_MOD_ALL & ~(1< MIN_SWITCH_PORTS) { + tiers++; + subnet_size /= (MIN_SWITCH_PORTS/2); + } + return tiers; +} + +// assuming a fat tree topology with switches of size MIN_SWITCH_PORTS +// compute number of switches in a typical FBB fabric +uint32_t cs_numSwitches(uint32_t subnet_size) +{ + // edge switches (and intermediate tiers) + uint32_t edge_sw = (subnet_size + (MIN_SWITCH_PORTS/2)-1)/(MIN_SWITCH_PORTS/2); + uint32_t tiers = cs_numTiers(subnet_size); + + // core/spine is half as many switches as edge + return (edge_sw * (tiers-1)) + (edge_sw/2); +} + +// assuming a fat tree topology with switches of size MIN_SWITCH_PORTS +// compute number of node records (1 per CA port, 1 per switch) +// in a typical FBB fabric +uint32_t cs_numNodeRecords(uint32_t subnet_size) +{ + return subnet_size + cs_numSwitches(subnet_size); +} + +// assuming a fat tree topology with switches of size MIN_SWITCH_PORTS +// compute number of port records (1 per CA port, 1 per switch port) +// in a typical FBB fabric +// (this will be slightly high for larger switches since there will +// be fewer switches (less switch port 0), less tiers and potentially +// fewer ISLs (hence fewer switch ports). +uint32_t cs_numPortRecords(uint32_t subnet_size) +{ + // +1 is for port 0 of switch chips + return subnet_size + cs_numSwitches(subnet_size) * (MIN_SWITCH_PORTS+1); +} + +// assuming a fat tree topology with switches of size MIN_SWITCH_PORTS +// compute number of links records (ISL and CA to Switch) +// in a typical FBB fabric +uint32_t cs_numLinkRecords(uint32_t subnet_size) +{ + // standard switching tiers calculation is a hair too low, so increase + // the number of switching tiers to accommodate the number of links records. + return (cs_numTiers(subnet_size) + 2)*subnet_size; +} diff --git a/Esm/ib/src/cs/cs_vesw.c b/Esm/ib/src/cs/cs_vesw.c new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/Esm/ib/src/cs/cs_vesw.c diff --git a/Esm/ib/src/cs/vs_pool_common.c b/Esm/ib/src/cs/vs_pool_common.c new file mode 100644 index 0000000..08f6747 --- /dev/null +++ b/Esm/ib/src/cs/vs_pool_common.c @@ -0,0 +1,503 @@ +/* BEGIN_ICS_COPYRIGHT5 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + * ** END_ICS_COPYRIGHT5 ****************************************/ + +/*********************************************************************** +* +* FILE NAME +* vs_pool_common.c +* +* DESCRIPTION +* This file contains vs_pool common routines. +* +* DATA STRUCTURES +* +* FUNCTIONS +* +* DEPENDENCIES +* +* +* HISTORY +* +* NAME DATE REMARKS +* DKJ 03/06/02 Initial creation of file. +* DKJ 03/26/02 LINT cleanup +* DKJ 04/01/02 PR1676. OS API 2.0g updates +***********************************************************************/ +#include +#include "cs_log.h" +#define function __FUNCTION__ +#ifdef LOCAL_MOD_ID +#undef LOCAL_MOD_ID +#endif +#define LOCAL_MOD_ID VIEO_CS_MOD_ID +extern Status_t vs_implpool_create (Pool_t *, uint32_t, + unsigned char *, void *, size_t); +extern Status_t vs_implpool_delete (Pool_t *); +extern Status_t vs_implpool_alloc (Pool_t *, size_t, void **); +extern Status_t vs_implpool_free (Pool_t *, void *); +extern Status_t vs_implpool_size (Pool_t *, uint64_t *); + +#define VSPOOL_MAGIC ((uint32_t) 0xDCADFEEDU) +/********************************************************************** +* +* FUNCTION +* vs_pool_create +* +* DESCRIPTION +* Does fundamental common validation for vs_pool_create +* parameters and invokes environment specific implmentation. +* +* INPUTS +* +* OUTPUTS +* Status_t - On success VSTATUS_OK is returned, otherwise +* the cause of the error. +* +* +* HISTORY +* +* NAME DATE REMARKS +* DKJ 03/07/02 Initial creation of function. +* DKJ 03/21/02 Updated prototype +**********************************************************************/ +Status_t +vs_pool_create (Pool_t * handle, uint32_t options, + unsigned char * name, void *address, size_t size) +{ + Status_t rc; + size_t namesize; + const uint32_t valid_options = 0; + + IB_ENTER (function, (unint) handle, options, (unint) address, + (uint32_t) size); + + if (handle == 0) + { + IB_LOG_ERROR0 ("handle is null"); + IB_EXIT (function, VSTATUS_ILLPARM); + return VSTATUS_ILLPARM; + } + (void) memset (handle, 0, sizeof (Pool_t)); + +#if USE_POOL_LOCK + rc = vs_lock_init (&handle->lock, VLOCK_LOCKED, VLOCK_THREAD); + if (rc != VSTATUS_OK) + { + IB_LOG_ERRORRC("vs_lock_init failed rc:", rc); + IB_EXIT (function, VSTATUS_NOMEM); + return VSTATUS_NOMEM; + } +#endif /* USE_POOL_LOCK */ + + if (name == 0) + { +#if USE_POOL_LOCK + (void) vs_unlock (&handle->lock); + (void) vs_lock_delete (&handle->lock); +#endif /* USE_POOL_LOCK */ + IB_LOG_ERROR0 ("name is null"); + IB_EXIT (function, VSTATUS_ILLPARM); + return VSTATUS_ILLPARM; + } + + for (namesize = (size_t) 0U; namesize < sizeof (handle->name); namesize++) + { + handle->name[namesize] = name[namesize]; + if (name[namesize] == (unsigned char) 0x00U) + { + break; + } + } + + if (namesize >= sizeof (handle->name)) + { +#if USE_POOL_LOCK + (void) vs_unlock (&handle->lock); + (void) vs_lock_delete (&handle->lock); +#endif /* USE_POOL_LOCK */ + IB_LOG_ERROR0 ("name doesn't contain a terminator"); + IB_EXIT (function, VSTATUS_ILLPARM); + return VSTATUS_ILLPARM; + } + + if ((options & ~valid_options) != (uint32_t) 0x00U) + { +#if USE_POOL_LOCK + (void) vs_unlock (&handle->lock); + (void) vs_lock_delete (&handle->lock); +#endif /* USE_POOL_LOCK */ + IB_LOG_ERROR ("Invalid options specified: ", options); + IB_EXIT (function, VSTATUS_ILLPARM); + return VSTATUS_ILLPARM; + } + handle->options = options; + + if (size == (size_t) 0x00U) + { +#if USE_POOL_LOCK + (void) vs_unlock (&handle->lock); + (void) vs_lock_delete (&handle->lock); +#endif /* USE_POOL_LOCK */ + IB_LOG_ERROR0 ("Pool size is zero"); + IB_EXIT (function, VSTATUS_ILLPARM); + return VSTATUS_ILLPARM; + } + +#ifdef __VXWORKS__ + /* cap size on VxWorks only */ + + if (size > (size_t) 0xFFFFFFF0U) + { +#if USE_POOL_LOCK + (void) vs_unlock (&handle->lock); + (void) vs_lock_delete (&handle->lock); +#endif /* USE_POOL_LOCK */ + IB_LOG_ERROR ("Pool size is too big: high:", (uint32_t) (size)); + IB_LOG_ERROR ("Pool size is too big: low:", (uint32_t) (size)); + IB_EXIT (function, VSTATUS_ILLPARM); + return VSTATUS_ILLPARM; + } +#endif + + handle->pagesize = vs_pool_page_size (); + + if ((options & VMEM_PAGE) == VMEM_PAGE) + { + if (size < handle->pagesize) + { +#if USE_POOL_LOCK + (void) vs_unlock (&handle->lock); + (void) vs_lock_delete (&handle->lock); +#endif /* USE_POOL_LOCK */ + IB_LOG_ERROR ("size is less than pagesize:", size); + IB_EXIT (function, VSTATUS_NOMEM); + return VSTATUS_NOMEM; + } + } + + rc = vs_implpool_create (handle, options, name, address, size); + if (rc == VSTATUS_OK) + { + handle->magic = VSPOOL_MAGIC; +#if USE_POOL_LOCK + (void) vs_unlock (&handle->lock); +#endif /* USE_POOL_LOCK */ + } + else + { +#if USE_POOL_LOCK + (void) vs_unlock (&handle->lock); + (void) vs_lock_delete (&handle->lock); +#endif /* USE_POOL_LOCK */ + } + + IB_EXIT (function, rc); + return rc; +} + +/********************************************************************** +* +* FUNCTION +* vs_pool_delete +* +* DESCRIPTION +* Does fundamental common validation for vs_pool_delete +* parameters and invokes environment specific implmentation. +* +* INPUTS +* +* OUTPUTS +* Status_t - On success VSTATUS_OK is returned, otherwise +* the cause of the error. +* +* +* HISTORY +* +* NAME DATE REMARKS +* DKJ 03/07/02 Initial creation of function. +**********************************************************************/ +Status_t +vs_pool_delete (Pool_t * handle) +{ + Status_t rc; + + IB_ENTER (function, (unint) handle, (uint32_t) 0U, (uint32_t) 0U, + (uint32_t) 0U); + + if (handle == 0) + { + IB_LOG_ERROR0 ("handle is null"); + IB_EXIT (function, VSTATUS_ILLPARM); + return VSTATUS_ILLPARM; + } + + if (handle->magic != VSPOOL_MAGIC) + { + IB_LOG_ERRORX ("invalid handle magic:", handle->magic); + IB_EXIT (function, VSTATUS_ILLPARM); + return VSTATUS_ILLPARM; + } + +#if USE_POOL_LOCK + rc = vs_lock (&handle->lock); + if (rc != VSTATUS_OK) + { + IB_LOG_ERRORRC("vs_lock failed rc:", rc); + IB_EXIT (function, VSTATUS_NXIO); + return VSTATUS_NXIO; + } +#endif /* USE_POOL_LOCK */ + + rc = vs_implpool_delete (handle); + if (rc == VSTATUS_OK) + { + handle->magic = ~VSPOOL_MAGIC; +#if USE_POOL_LOCK + (void) vs_unlock (&handle->lock); + (void) vs_lock_delete (&handle->lock); +#endif /* USE_POOL_LOCK */ + } + else + { +#if USE_POOL_LOCK + (void) vs_unlock (&handle->lock); +#endif /* USE_POOL_LOCK */ + } + (void) memset (handle, 0, sizeof (Pool_t)); + + IB_EXIT (function, rc); + return rc; +} + +/********************************************************************** +* +* FUNCTION +* vs_pool_alloc +* +* DESCRIPTION +* Does fundamental common validation for vs_pool_alloc +* parameters and invokes environment specific implmentation. +* +* INPUTS +* +* OUTPUTS +* Status_t - On success VSTATUS_OK is returned, otherwise +* the cause of the error. +* +* +* HISTORY +* +* NAME DATE REMARKS +* DKJ 03/07/02 Initial creation of function. +**********************************************************************/ +Status_t +vs_pool_alloc (Pool_t * handle, size_t length, void **loc) +{ + Status_t rc; + + IB_ENTER (function, (unint) handle, (uint32_t) length, (unint) loc, + (uint32_t) 0U); + + if (handle == 0) + { + IB_LOG_ERROR0 ("handle is null"); + IB_EXIT (function, VSTATUS_ILLPARM); + return VSTATUS_ILLPARM; + } + + if (handle->magic != VSPOOL_MAGIC) + { + IB_LOG_ERRORX ("invalid handle magic:", handle->magic); + IB_EXIT (function, VSTATUS_ILLPARM); + return VSTATUS_ILLPARM; + } + + if (loc == 0) + { + IB_LOG_ERROR0 ("loc is null"); + IB_EXIT (function, VSTATUS_ILLPARM); + return VSTATUS_ILLPARM; + } + + if (length == (size_t) 0x00U) + { + IB_LOG_ERROR0 ("length is zero"); + IB_EXIT (function, VSTATUS_ILLPARM); + return VSTATUS_ILLPARM; + } + +#if USE_POOL_LOCK + rc = vs_lock (&handle->lock); + if (rc != VSTATUS_OK) + { + IB_LOG_ERRORRC("vs_lock failed rc:", rc); + IB_EXIT (function, VSTATUS_NXIO); + return VSTATUS_NXIO; + } +#endif /* USE_POOL_LOCK */ + + rc = vs_implpool_alloc (handle, length, loc); + +#if USE_POOL_LOCK + (void) vs_unlock (&handle->lock); +#endif /* USE_POOL_LOCK */ + IB_EXIT (function, rc); + return rc; +} + +/********************************************************************** +* +* FUNCTION +* vs_pool_free +* +* DESCRIPTION +* Does fundamental common validation for vs_pool_free +* parameters and invokes environment specific implmentation. +* +* INPUTS +* +* OUTPUTS +* Status_t - On success VSTATUS_OK is returned, otherwise +* the cause of the error. +* +* +* HISTORY +* +* NAME DATE REMARKS +* DKJ 03/07/02 Initial creation of function. +**********************************************************************/ +Status_t +vs_pool_free (Pool_t * handle, void *loc) +{ + Status_t rc; + + IB_ENTER (function, (unint) handle, (unint) loc, (uint32_t) 0U, + (uint32_t) 0U); + + if (handle == 0) + { + IB_LOG_ERROR0 ("handle is null"); + IB_EXIT (function, VSTATUS_ILLPARM); + return VSTATUS_ILLPARM; + } + + if (handle->magic != VSPOOL_MAGIC) + { + IB_LOG_ERRORX ("invalid handle magic:", handle->magic); + IB_EXIT (function, VSTATUS_ILLPARM); + return VSTATUS_ILLPARM; + } + + if (loc == 0) + { + IB_LOG_ERROR0 ("loc is null"); + IB_EXIT (function, VSTATUS_ILLPARM); + return VSTATUS_ILLPARM; + } + +#if USE_POOL_LOCK + rc = vs_lock (&handle->lock); + if (rc != VSTATUS_OK) + { + IB_LOG_ERRORRC("vs_lock failed rc:", rc); + IB_EXIT (function, VSTATUS_NXIO); + return VSTATUS_NXIO; + } +#endif /* USE_POOL_LOCK */ + + rc = vs_implpool_free (handle, loc); + +#if USE_POOL_LOCK + (void) vs_unlock (&handle->lock); +#endif /* USE_POOL_LOCK */ + IB_EXIT (function, rc); + return rc; +} + +/********************************************************************** +* +* FUNCTION +* vs_pool_size +* +* DESCRIPTION +* Does fundamental common validation for vs_pool_size +* parameters and invokes environment specific implmentation. +* +* INPUTS +* +* OUTPUTS +* number of bytes allocated from pool. +**********************************************************************/ +Status_t +vs_pool_size (Pool_t * handle, uint64_t *numBytesAlloc) +{ + Status_t rc; + + IB_ENTER (function, (unint) handle, 0, 0, 0); + + if (handle == 0) + { + IB_LOG_ERROR0 ("handle is null"); + IB_EXIT (function, VSTATUS_ILLPARM); + return VSTATUS_ILLPARM; + } + + if (handle->magic != VSPOOL_MAGIC) + { + IB_LOG_ERRORX ("invalid handle magic:", handle->magic); + IB_EXIT (function, VSTATUS_ILLPARM); + return VSTATUS_ILLPARM; + } + + if (numBytesAlloc == 0) + { + IB_LOG_ERROR0 ("numBytesAlloc is null"); + IB_EXIT (function, VSTATUS_ILLPARM); + return VSTATUS_ILLPARM; + } + +#if USE_POOL_LOCK + rc = vs_lock (&handle->lock); + if (rc != VSTATUS_OK) + { + IB_LOG_ERRORRC("vs_lock failed rc:", rc); + *numBytesAlloc = 0; + IB_EXIT (function, VSTATUS_NXIO); + return VSTATUS_NXIO; + } +#endif /* USE_POOL_LOCK */ + + rc = vs_implpool_size (handle, numBytesAlloc); + +#if USE_POOL_LOCK + (void) vs_unlock (&handle->lock); +#endif /* USE_POOL_LOCK */ + IB_EXIT (function, rc); + return rc; +} diff --git a/Esm/ib/src/cs/vs_thr_common.c b/Esm/ib/src/cs/vs_thr_common.c new file mode 100644 index 0000000..e3d047e --- /dev/null +++ b/Esm/ib/src/cs/vs_thr_common.c @@ -0,0 +1,618 @@ +/* BEGIN_ICS_COPYRIGHT5 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + * ** END_ICS_COPYRIGHT5 ****************************************/ + +/*********************************************************************** +* +* FILE NAME +* vs_thr_common.c +* +* DESCRIPTION +* This file contains the API entry and validation common among +* all thread environments. It will invoke the private +* implementation specific version of the API. +* +* General non-platform specific helpers are available as well. +* +* DATA STRUCTURES +* +* FUNCTIONS +* vs_thread_create() +* +* DEPENDENCIES +* vs_g.h +* +* +* HISTORY +* +* NAME DATE REMARKS +* SFW 03/05/02 Initial creation of file. +* PJG 04/01/02 PR 1676. vs_thread_sleep prototype per OS API 2.0g +***********************************************************************/ +#include "ib_types.h" +#include "ib_status.h" +#include "vs_g.h" +#include "cs_g.h" +#include "cs_log.h" +#define function __FUNCTION__ + +#ifdef LOCAL_MOD_ID +#undef LOCAL_MOD_ID +#endif +#define LOCAL_MOD_ID VIEO_CS_MOD_ID + +/* +** Implmentation specific entry points. +*/ +extern Status_t +impl_vs_thread_create (Thread_t *thr, + unsigned char *name, + void (*start_function)(uint32_t, uint8_t **), + uint32_t argc, + uint32_t argv_copy, + uint8_t *argv[], + size_t stack_size); + +extern Status_t +impl_vs_thread_name (Threadname_t *name); + +extern const char* +impl_vs_thread_name_str (void); + +extern Status_t +impl_vs_thread_groupname (Threadname_t name, + Threadname_t *grpname); + +extern Status_t +impl_vs_thread_exit (Thread_t *thr); + +extern Status_t +impl_vs_thread_kill (Thread_t *thr); + +extern void +impl_vs_thread_sleep (uint64_t sleep_time); + +extern Status_t +impl_vs_thread_join(Thread_t *thr, + void **value_ptr); + +extern int +impl_vs_thread_setname(char *name); + +/********************************************************************** +* +* FUNCTION +* vs_real_thread_create +* +* DESCRIPTION +* Does the actual thread creation; called only by vs_thread_create() +* and vs_thread_create2(). +* +**********************************************************************/ +static Status_t +vs_real_thread_create (Thread_t *thr, + unsigned char *name, + void (*start_function)(uint32_t, uint8_t **), + uint32_t argc, + uint32_t argv_copy, + uint8_t *argv[], + size_t stack_size) +{ + uint32_t count; + Status_t status; + + + IB_ENTER (function, (unint) thr, (unint) name, + (unint) start_function, (uint32_t) argc); + + /* + ** Verify required pointer arguments. + */ + if (thr == 0) + { + IB_LOG_ERROR0 ("Thread_t parameter is null"); + IB_EXIT (function, VSTATUS_ILLPARM); + return VSTATUS_ILLPARM; + } + + if (name == 0) + { + IB_LOG_ERROR0 ("name parameter is null"); + IB_EXIT (function, VSTATUS_ILLPARM); + return VSTATUS_ILLPARM; + } + + if (start_function == 0) + { + IB_LOG_ERROR0 ("startup function parameter is null"); + IB_EXIT (function, VSTATUS_ILLPARM); + return VSTATUS_ILLPARM; + } + + /* + ** Look for inconsistencies in argc and argv. + */ + for (count = 0U; count < argc; count++) + { + if (!argv || !argv[count]) + { + IB_LOG_ERROR0 ("argc and argv[] are inconsistent"); + IB_EXIT (function, VSTATUS_ILLPARM); + return VSTATUS_ILLPARM; + } + } + + if (stack_size == (size_t) 0U) + { + IB_LOG_ERROR0 ("stack_size parameter is null"); + IB_EXIT (function, VSTATUS_ILLPARM); + return VSTATUS_ILLPARM; + } + + /* + ** Zero the Thread control object and initialize. + */ + memset(thr, 0, sizeof(Thread_t)); + + /* + ** Move in the name, validate name length is < VS_NAME_MAX. + */ + for (count = 0U; count < VS_NAME_MAX; count++) + { + thr->name[count] = name[count]; + if (name[count] == (unsigned char) 0U) + break; + } + + if (count >= VS_NAME_MAX) + { + IB_LOG_ERROR0("name too big"); + IB_EXIT(function, VSTATUS_ILLPARM); + return VSTATUS_ILLPARM; + } + + /* + ** Invoke environment specific implmentation and return status. + */ + status = impl_vs_thread_create (thr, name, start_function, + argc, argv_copy, argv, + stack_size); + + IB_EXIT (function, status); + return status; +} + +/********************************************************************** +* +* FUNCTION +* vs_thread_create +* +* DESCRIPTION +* Does fundamental common validation for vs_thread_create +* parameters and invokes environment specific implmentation. +* +* INPUTS +* +* OUTPUTS +* Status_t - On success VSTATUS_OK is returned, otherwise +* the cause of the error. +* +* +* HISTORY +* +* NAME DATE REMARKS +* SFW 03/05/02 Initial creation of function. +* DKJ 04/04/02 PR1676. OS API 2.0g update +**********************************************************************/ +Status_t +vs_thread_create (Thread_t *thr, + unsigned char *name, + void (*start_function)(uint32_t, uint8_t **), + uint32_t argc, + uint8_t *argv[], + size_t stack_size) +{ + Status_t status; + + IB_ENTER (function, (unint) thr, (unint) name, + (unint) start_function, (uint32_t) argc); + + status = vs_real_thread_create(thr, + name, + start_function, + argc, + 0, /* do not copy argv */ + argv, + stack_size); + IB_EXIT (function, status); + return status; +} + +/********************************************************************** +* +* FUNCTION +* vs_thread_create2 +* +* DESCRIPTION +* Same as vs_thread_create() except that the argv vector +* is copied. This allows the caller to safely pass in an argv +* created on the stack without worrying about it becoming +* a dangling pointer. +* +* INPUTS +* same as vs_thread_create +* +* OUTPUTS +* same as vs_thread_create +* +**********************************************************************/ +Status_t +vs_thread_create2 (Thread_t *thr, + unsigned char *name, + void (*start_function)(uint32_t, uint8_t **), + uint32_t argc, + uint8_t *argv[], + size_t stack_size) +{ + Status_t status; + + IB_ENTER (function, (unint) thr, (unint) name, + (unint) start_function, (uint32_t) argc); + + status = vs_real_thread_create(thr, + name, + start_function, + argc, + 1, /* copy argv */ + argv, + stack_size); + IB_EXIT (function, status); + return status; +} + +/********************************************************************** +* +* FUNCTION +* vs_thread_name +* +* DESCRIPTION +* Return the globally unique thread name opaque identifier for +* the currently executing thread. When running in interrupt context, +* the identifier VTRHREAD_INTERRUPT is returned. +* +* INPUTS +* +* OUTPUTS +* Status_t - On success VSTATUS_OK is returned, otherwise +* the cause of the error. +* +* +* HISTORY +* +* NAME DATE REMARKS +* SFW 03/05/02 Initial creation of function. +**********************************************************************/ +Status_t +vs_thread_name (Threadname_t *name) +{ + Status_t status; + + IB_ENTER (function, (unint) name, (uint32_t) 0U, (uint32_t) 0U, + (uint32_t) 0U); + + /* + ** Verify required pointer arguments. + */ + if (name == 0) + { + IB_LOG_ERROR0 ("name parameter is null"); + IB_EXIT (function, VSTATUS_ILLPARM); + return VSTATUS_ILLPARM; + } + + /* + ** Invoke environment specific implmentation and return status. + */ + status = impl_vs_thread_name(name); + + IB_EXIT (function, status); + return status; +} + +/********************************************************************** +* +* FUNCTION +* vs_thread_name_str +* +* DESCRIPTION +* Return the globally unique thread name string for +* the currently executing thread. +* +* INPUTS +* +* OUTPUTS +* thread name string +* +* +* HISTORY +* +* NAME DATE REMARKS +* SFW 03/05/02 Initial creation of function. +**********************************************************************/ +const char* +vs_thread_name_str (void) +{ + /* + ** Invoke environment specific implmentation + */ + return impl_vs_thread_name_str(); +} + +/********************************************************************** +* +* FUNCTION +* vs_thread_groupname +* +* DESCRIPTION +* Return the globaly unique opaque thread group id for the +* running user thread. +* +* INPUTS +* +* OUTPUTS +* Status_t - On success VSTATUS_OK is returned, otherwise +* the cause of the error. +* +* +* HISTORY +* +* NAME DATE REMARKS +* SFW 03/05/02 Initial creation of function. +**********************************************************************/ +Status_t +vs_thread_groupname (Threadname_t name, Threadname_t *grpname) +{ + Status_t status; + + IB_ENTER (function, name, (unint) grpname, (uint32_t) 0U, + (uint32_t) 0U); + + /* + ** Verify required pointer arguments. + */ + if (grpname == 0) + { + IB_LOG_ERROR0 ("group name parameter is null"); + IB_EXIT (function, VSTATUS_ILLPARM); + return VSTATUS_ILLPARM; + } + + /* + ** Invoke environment specific implmentation and return status. + */ + status = impl_vs_thread_groupname(name, grpname); + + IB_EXIT (function, status); + return status; +} + +/********************************************************************** +* +* FUNCTION +* vs_thread_exit +* +* DESCRIPTION +* Exit the currently running thread. +* +* INPUTS +* +* OUTPUTS +* Status_t - On success does not return, otherwise +* the cause of the error. +* +* +* HISTORY +* +* NAME DATE REMARKS +* SFW 03/06/02 Initial creation of function. +**********************************************************************/ +Status_t +vs_thread_exit (Thread_t *handle) +{ + Status_t status; + + IB_ENTER (function, (unint) handle, (uint32_t) 0U, (uint32_t) 0U, + (uint32_t) 0U); + + /* + ** Verify required pointer arguments. + */ + if (handle == 0) + { + IB_LOG_ERROR0 ("handle parameter is null"); + IB_EXIT (function, VSTATUS_ILLPARM); + return VSTATUS_ILLPARM; + } + + /* + ** Invoke environment specific implmentation and return status. + */ + status = impl_vs_thread_exit(handle); + + IB_EXIT (function, status); + return status; +} + +/********************************************************************** +* +* FUNCTION +* vs_thread_kill +* +* DESCRIPTION +* Kill the specified thread. +* +* INPUTS +* +* OUTPUTS +* Status_t - On success VSTATUS_OK is returned, otherwise +* the cause of the error. +* +* +* HISTORY +* +* NAME DATE REMARKS +* SFW 03/06/02 Initial creation of function. +**********************************************************************/ +Status_t +vs_thread_kill (Thread_t *handle) +{ + Status_t status; + + IB_ENTER (function, (unint) handle, (uint32_t) 0U, (uint32_t) 0U, + (uint32_t) 0U); + + /* + ** Verify required pointer arguments. + */ + if (handle == 0) + { + IB_LOG_ERROR0 ("handle parameter is null"); + IB_EXIT (function, VSTATUS_ILLPARM); + return VSTATUS_ILLPARM; + } + + /* + ** Invoke environment specific implmentation and return status. + */ + status = impl_vs_thread_kill(handle); + + IB_EXIT (function, status); + return status; +} + +/********************************************************************** +* +* FUNCTION +* vs_thread_sleep +* +* DESCRIPTION +* Sleep for the specified number of microseconds. +* +* INPUTS +* +* OUTPUTS +* Status_t - On success VSTATUS_OK is returned, otherwise +* the cause of the error. +* +* +* HISTORY +* +* NAME DATE REMARKS +* SFW 03/06/02 Initial creation of function. +* PJG 04/02/02 PR 1676. vs_thread_sleep prototype per OS API 2.0g +**********************************************************************/ +void +vs_thread_sleep (uint64_t sleep_time) +{ + + IB_ENTER (function, (uint32_t) sleep_time, (uint32_t) 0U, (uint32_t) 0U, + (uint32_t) 0U); + + /* + ** Invoke environment specific implmentation. + */ + impl_vs_thread_sleep(sleep_time); + + IB_EXIT (function, VSTATUS_OK); + return; +} + +/********************************************************************** +* +* FUNCTION +* vs_thread_join +* +* DESCRIPTION +* Wait for the specified thread to exit. +* +* INPUTS +* +* OUTPUTS +* Status_t - On success VSTATUS_OK is returned, otherwise +* the cause of the error. +* +* +* HISTORY +* +* NAME DATE REMARKS +* SR 10/24/16 Initial creation of function. +**********************************************************************/ +Status_t +vs_thread_join (Thread_t *handle, void **value_ptr) +{ + Status_t status; + + IB_ENTER (function, (unint) handle, (unint) value_ptr, (uint32_t) 0U, + (uint32_t) 0U); + + /* + ** Verify required pointer arguments. + */ + if (handle == 0) + { + IB_LOG_ERROR0 ("handle parameter is null"); + IB_EXIT (function, VSTATUS_ILLPARM); + return VSTATUS_ILLPARM; + } + + /* + ** Invoke environment specific implmentation and return status. + */ + status = impl_vs_thread_join(handle, value_ptr); + + IB_EXIT (function, status); + return status; +} +/********************************************************************** +* +* FUNCTION +* vs_thread_name_str +* +* DESCRIPTION +* Sets a globally unique thread name string for +* the currently executing thread. +* +* INPUTS +* thread name string +* OUTPUTS +* Upon success returns 0 +**********************************************************************/ +int vs_thread_setname(char* name) +{ + return impl_vs_thread_setname(name); +} diff --git a/Esm/ib/src/ibaccess/Makefile b/Esm/ib/src/ibaccess/Makefile new file mode 100644 index 0000000..242b346 --- /dev/null +++ b/Esm/ib/src/ibaccess/Makefile @@ -0,0 +1,164 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** +# Makefile for SM Module + +# Include Make Control Settings +include $(TL_DIR)/$(PROJ_FILE_DIR)/Makesettings.project + +#=============================================================================# +# Definitions: +#-----------------------------------------------------------------------------# + +# Name of SubProjects +DS_SUBPROJECTS = +# name of executable or downloadable image +EXECUTABLE = # Sm$(EXE_SUFFIX) +# list of sub directories to build +DIRS = +# C files (.c) +CFILES = \ + cs_mad_openib.c \ + vs_evt.c \ + vs_lck.c \ + vs_pool.c \ + vs_thr.c \ + vs_utility.c + # Add more c files here +# C++ files (.cpp) +CCFILES = \ + # Add more cpp files here +# lex files (.lex) +LFILES = \ + # Add more lex files here +# archive library files (basename, $ARFILES will add MOD_LIB_DIR/prefix and suffix) +LIBFILES = +# Windows Resource Files (.rc) +RSCFILES = +# Windows IDL File (.idl) +IDLFILE = +# Windows Linker Module Definitions (.def) file for dll's +DEFFILE = +# targets to build during INCLUDES phase (add public includes here) +INCLUDE_TARGETS = \ + # Add more h hpp files here +# Non-compiled files +MISC_FILES = +# all source files +SOURCES = $(CFILES) $(CCFILES) $(LFILES) $(RSCFILES) $(IDLFILE) +# Source files to include in DSP File +DSP_SOURCES = $(INCLUDE_TARGETS) $(SOURCES) $(MISC_FILES) \ + $(RSCFILES) $(DEFFILE) $(MAKEFILE) +# all object files +OBJECTS = $(CFILES:.c=$(OBJ_SUFFIX)) $(CCFILES:.cpp=$(OBJ_SUFFIX)) \ + $(LFILES:.lex=$(OBJ_SUFFIX)) +RSCOBJECTS = $(RSCFILES:.rc=$(RES_SUFFIX)) +# targets to build during LIBS phase +LIB_TARGETS_IMPLIB = +LIB_TARGETS_ARLIB = $(LIB_PREFIX)ibaccess$(ARLIB_SUFFIX) +LIB_TARGETS_EXP = $(LIB_TARGETS_IMPLIB:$(ARLIB_SUFFIX)=$(EXP_SUFFIX)) +LIB_TARGETS_MISC = +# targets to build during CMDS phase +CMD_TARGETS_SHLIB = +CMD_TARGETS_EXE = $(EXECUTABLE) +CMD_TARGETS_MISC = +# files to remove during clean phase +CLEAN_TARGETS_MISC = +CLEAN_TARGETS = $(OBJECTS) $(RSCOBJECTS) $(IDL_TARGETS) $(CLEAN_TARGETS_MISC) +# other files to remove during clobber phase +CLOBBER_TARGETS_MISC= +# sub-directory to install to within bin +BIN_SUBDIR = +# sub-directory to install to within include +INCLUDE_SUBDIR = + +# Additional Settings +#CLOCALDEBUG = User defined C debugging compilation flags [Empty] +#CCLOCALDEBUG = User defined C++ debugging compilation flags [Empty] +#CLOCAL = User defined C flags for compiling [Empty] +#CCLOCAL = User defined C++ flags for compiling [Empty] +#BSCLOCAL = User flags for Browse File Builder [Empty] +#DEPENDLOCAL = user defined makedepend flags [Empty] +#LINTLOCAL = User defined lint flags [Empty] +#LOCAL_INCLUDE_DIRS = User include directories to search for C/C++ headers [Empty] +#LDLOCAL = User defined C flags for linking [Empty] +#IMPLIBLOCAL = User flags for Object Lirary Manager [Empty] +#MIDLLOCAL = User flags for IDL compiler [Empty] +#RSCLOCAL = User flags for resource compiler [Empty] +#LOCALDEPLIBS = User libraries to include in dependencies [Empty] +#LOCALLIBS = User libraries to use when linking [Empty] +# (in addition to LOCALDEPLIBS) +#LOCAL_LIB_DIRS = User library directories for libpaths [Empty] + +CLOCAL = $(CPIE) +LOCALDEPLIBS = + +PROJ_SM_DIR ?= $(TL_DIR)/Esm/ib + +# Include Make Rules definitions and rules +ifneq "$(PROJ_SM_DIR)" "" +include $(PROJ_SM_DIR)/Makerules.module +endif + +#=============================================================================# +# Overrides: +#-----------------------------------------------------------------------------# +#CCOPT = # C++ optimization flags, default lets build config decide +#COPT = # C optimization flags, default lets build config decide +#SUBSYSTEM = Subsystem to build for (none, console or windows) [none] +# (Windows Only) +#USEMFC = How Windows MFC should be used (none, static, shared, no_mfc) [none] +# (Windows Only) +#=============================================================================# + +#=============================================================================# +# Rules: +#-----------------------------------------------------------------------------# +# process Sub-directories +include $(TL_DIR)/Makerules/Maketargets.toplevel + +# build cmds and libs +include $(TL_DIR)/Makerules/Maketargets.build + +# install for includes, libs and cmds phases +include $(TL_DIR)/Makerules/Maketargets.install + +# install for stage phase +#include $(TL_DIR)/Makerules/Maketargets.stage +STAGE:: + +# Unit test execution +#include $(TL_DIR)/Makerules/Maketargets.runtest + +clobber:: clobber_module + +#=============================================================================# + +#=============================================================================# +# DO NOT DELETE THIS LINE -- make depend depends on it. +#=============================================================================# diff --git a/Esm/ib/src/ibaccess/README b/Esm/ib/src/ibaccess/README new file mode 100644 index 0000000..b395aae --- /dev/null +++ b/Esm/ib/src/ibaccess/README @@ -0,0 +1,42 @@ +/* BEGIN_ICS_COPYRIGHT10 **************************************** + +Copyright (c) 2015, Intel Corporation +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: +- Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. +- Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. +- Neither the name of Intel Corporation nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL INTEL, THE COPYRIGHT OWNER OR CONTRIBUTORS +BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. + +EXPORT LAWS: THIS LICENSE ADDS NO RESTRICTIONS TO THE EXPORT LAWS OF YOUR +JURISDICTION. It is licensee's responsibility to comply with any export +regulations applicable in licensee's jurisdiction. Under CURRENT (May 2000) +U.S. export regulations this software is eligible for export from the U.S. +and can be downloaded by or otherwise exported or reexported worldwide EXCEPT +to U.S. embargoed destinations which include Cuba, Iraq, Libya, North Korea, +Iran, Syria, Sudan, Afghanistan and any other country to which the U.S. has +embargoed goods and services. + +** END_ICS_COPYRIGHT10 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ +OS and IB stack specific code for OPENIB stack on linux +Directory name is a misnomer, no longer IbAccess on Linux diff --git a/Esm/ib/src/ibaccess/cs_mad_openib.c b/Esm/ib/src/ibaccess/cs_mad_openib.c new file mode 100644 index 0000000..3b29884 --- /dev/null +++ b/Esm/ib/src/ibaccess/cs_mad_openib.c @@ -0,0 +1,1109 @@ +/* BEGIN_ICS_COPYRIGHT5 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + * ** END_ICS_COPYRIGHT5 ****************************************/ + +#include +#include +#include +#include +#include +#include "opamgt_priv.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//============================================================================== + +#define IB_ISSM_DEVICEPATH_MAXLEN 32 + +//============================================================================== + +//============================================================================== + +#define IB_HANDLE2DEV(handle) (( (handle) >> 8) & 0xFF) +#define IB_HANDLE2PORT(handle) (( (handle) ) & 0xFF) + +#define IB_MAKEHANDLE(dev, port) \ + ((((dev) & 0xff) << 8) | ((port) & 0xff)) + +#define IB_FROMHANDLE(handle, dev, port) \ + dev = IB_HANDLE2DEV(handle); \ + port = IB_HANDLE2PORT(handle); + +//============================================================================== + +static uint8_t ib_truescale_oui[] = {OUI_TRUESCALE_0, OUI_TRUESCALE_1, OUI_TRUESCALE_2}; + +typedef struct +{ + FILE *fp; + Lock_t lock; +} ib_issm_t; + +static ib_issm_t ib_issm; + +static struct omgt_class_args sm_class_args[] = { + { IB_BASE_VERSION, MAD_CV_SUBN_DR, 1, + .is_responding_client=1, .is_trap_client=1, .is_report_client=0, .kernel_rmpp=0, .oui=0, .use_methods=0 }, + { IB_BASE_VERSION, MAD_CV_SUBN_LR, 1, + .is_responding_client=1, .is_trap_client=1, .is_report_client=0, .kernel_rmpp=0, .oui=0, .use_methods=0}, + { STL_BASE_VERSION, MAD_CV_SUBN_DR, STL_SM_CLASS_VERSION, + .is_responding_client=1, .is_trap_client=1, .is_report_client=0, .kernel_rmpp=0, .oui=0, .use_methods=0 }, + { STL_BASE_VERSION, MAD_CV_SUBN_LR, STL_SM_CLASS_VERSION, + .is_responding_client=1, .is_trap_client=1, .is_report_client=0, .kernel_rmpp=0, .oui=0, .use_methods=0 }, + { STL_BASE_VERSION, MAD_CV_VENDOR_DBSYNC, STL_SA_CLASS_VERSION, + .oui=ib_truescale_oui, .use_methods=1, + .methods={ FE_MNGR_PROBE_CMD, FE_MNGR_CLOSE_CMD, + FM_CMD_SHUTDOWN, SA_CM_GET, SA_CM_SET, SA_CM_GETTABLE }}, + { STL_BASE_VERSION, MAD_CV_SUBN_ADM, STL_SA_CLASS_VERSION, + .oui=0, .use_methods=1, + .methods={ SA_CM_GET, SA_CM_SET, SA_CM_GETTABLE, + SA_CM_GETTRACETABLE, SA_CM_GETMULTI, SA_CM_DELETE }}, + { IB_BASE_VERSION, MAD_CV_SUBN_ADM, IB_SUBN_ADM_CLASS_VERSION, + .oui=0, .use_methods=1, + .methods={ SA_CM_GET, SA_CM_SET, SA_CM_GETTABLE, + SA_CM_GETTRACETABLE, SA_CM_GETMULTI, SA_CM_DELETE }}, + { 0 } +}; + +static struct omgt_class_args fe_class_args[] = { + { IB_BASE_VERSION, MAD_CV_VENDOR_FE, 1, + .kernel_rmpp=0, .oui=ib_truescale_oui, .use_methods=1, + .methods={ FE_MNGR_PROBE_CMD, + FE_MNGR_CLOSE_CMD, FM_CMD_SHUTDOWN, RMPP_CMD_GET, RMPP_CMD_GETTABLE }}, + { IB_BASE_VERSION, MAD_CV_VFI_PM, 1, + .kernel_rmpp=0, .oui=ib_truescale_oui, .use_methods=1, + .methods={ FE_CMD_RESP, RMPP_CMD_GET, RMPP_CMD_GETTABLE }}, + { 0 } +}; + +static struct omgt_class_args fe_proc_class_args[] = { + { IB_BASE_VERSION, MAD_CV_VENDOR_FE, 1, + .kernel_rmpp=0, .oui=ib_truescale_oui, .use_methods=1, + .methods={ FE_MNGR_PROBE_CMD, + FE_MNGR_CLOSE_CMD, FM_CMD_SHUTDOWN, RMPP_CMD_GET, RMPP_CMD_GETTABLE }}, + { STL_BASE_VERSION, MAD_CV_VFI_PM, STL_PM_CLASS_VERSION, + .kernel_rmpp=0, .oui=ib_truescale_oui, .use_methods=1, + .methods={ FE_CMD_RESP }}, + { IB_BASE_VERSION, MAD_CV_SUBN_DR, 1, + .is_responding_client=0, .is_trap_client=0, .is_report_client=0, .kernel_rmpp=0, .oui=0, .use_methods=0 }, + { IB_BASE_VERSION, MAD_CV_SUBN_LR, 1, + .is_responding_client=0, .is_trap_client=0, .is_report_client=0, .kernel_rmpp=0, .oui=0, .use_methods=0}, + { STL_BASE_VERSION, MAD_CV_SUBN_DR, STL_SM_CLASS_VERSION, + .is_responding_client=0, .is_trap_client=0, .is_report_client=0, .kernel_rmpp=0, .oui=0, .use_methods=0 }, + { STL_BASE_VERSION, MAD_CV_SUBN_LR, STL_SM_CLASS_VERSION, + .is_responding_client=0, .is_trap_client=0, .is_report_client=0, .kernel_rmpp=0, .oui=0, .use_methods=0 }, + { STL_BASE_VERSION, MAD_CV_SUBN_ADM, STL_SA_CLASS_VERSION, + .is_responding_client=0, .is_trap_client=0, .is_report_client=0, .kernel_rmpp=0, .oui=0, .use_methods=0 }, + { IB_BASE_VERSION, MAD_CV_SUBN_ADM, IB_SUBN_ADM_CLASS_VERSION, + .is_responding_client=0, .is_trap_client=0, .is_report_client=0, .kernel_rmpp=0, .oui=0, .use_methods=0 }, + { 0 } +}; + +static struct omgt_class_args pm_class_args[] = { + { STL_BASE_VERSION, MAD_CV_VFI_PM, STL_PM_CLASS_VERSION, + .kernel_rmpp = 0, .oui=ib_truescale_oui, .use_methods=1, + .methods={ FE_MNGR_PROBE_CMD, FE_MNGR_CLOSE_CMD, FM_CMD_SHUTDOWN, + STL_PA_CMD_GET, STL_PA_CMD_SET, STL_PA_CMD_GETTABLE }}, + { STL_BASE_VERSION, MAD_CV_PERF, STL_PM_CLASS_VERSION, + .is_responding_client=0, .is_trap_client=0, .is_report_client=0, .kernel_rmpp=0, .oui=0, .use_methods=0}, + { 0 } +}; + + +int ib_instrumentJmMads = 0; + +/** TODO: currently there is only one open to the opamgt later (translated into only one open file + * handle to the ib_umad driver) and shared by all the threads spawned in Esm/ib/src/ibaccess/smi/sm/sm_main.c, + * which is the reason behind the complicated filtering mechanism in the upper MAI layer. To streamline + * the operation, the field in struct mai_dc->hndl can be replaced with struct omgt_port * so that each + * thread that calls mai_open() can have a separate port open in opamgt (i.e., a separate file handle + * to the ib_umad driver): mai_open() -> mai_get_dc() -> ib_attach_sma(), the last function (ib_attach_sma) + * should call omgt_open_port_by_num(). Similarly, ib_detach_sma should call omgt_close_port() to close + * the corresponding port. In addition, all the sending/receiving function (ib_recv_sma, etc) should + * be modified to carrry the struct omgt_port * parameter install of the IBhandle parameter). Of course, + * the ib_init_devport() and ib_init_guid() should not be used any more or modified not to call the + * omgt_open_port_xx() function. + * Note: the xx_mai_to_wire() or xx_wire_to_mai function + * involve buffer copying, which is bad for performance. + * */ +struct omgt_port *g_port_handle = NULL; + +//============================================================================== + +// We're hacking into MAI internals here. In the case of local packets, we +// just call mai_mad_process to short-circuit the path. +extern int mai_mad_process(Mai_t *mad, int *filterMatch); + +extern uint32_t smDebugPerf; +extern uint32_t sm_debug; + +//============================================================================== + +static Status_t ib_mai_to_wire(Mai_t *mad, uint8_t *buf); +static Status_t stl_wire_to_mai(uint8_t *buf, Mai_t *mad, int len); +static void stl_mad_to_mai(MAD* mad, Mai_t *mai); +static Status_t stl_mai_to_wire(Mai_t *mad, uint8_t *buf, uint32_t *bufLen); + +//============================================================================== +// ib_init_common +//============================================================================== +static Status_t ib_init_common(void) +{ + Status_t status; + + ib_issm.fp = NULL; + status = vs_lock_init(&ib_issm.lock, VLOCK_FREE, VLOCK_THREAD); + if (status != VSTATUS_OK) { + IB_LOG_ERRORRC("can't initialize issm device lock; rc:", status); + return status; + } + + return VSTATUS_OK; +} + +//============================================================================== +// ib_init_devport +//============================================================================== +Status_t +ib_init_devport(uint32_t *devp, uint32_t *portp, uint64_t *Guidp, struct omgt_params *session_params) +{ + OMGT_STATUS_T status; + + IB_ENTER(__func__, devp, portp, Guidp, 0); + + // Check if the port is opened or + if (g_port_handle) { + uint64_t port_guid = 0; + int32_t hfi_num = -1; + uint8_t port_num = 0; + (void)omgt_port_get_port_guid(g_port_handle, &port_guid); + (void)omgt_port_get_hfi_num(g_port_handle, &hfi_num); + (void)omgt_port_get_hfi_port_num(g_port_handle, &port_num); + IB_LOG_ERROR_FMT(__func__, "one port (%d/%d GUID 0x%.16"CS64"x) is already opened", + hfi_num, port_num, port_guid); + return VSTATUS_BUSY; + } + status = ib_init_common(); + if (status != VSTATUS_OK) { + IB_EXIT(__func__, status); + return status; + } + + + if (Guidp != NULL && *Guidp != 0ULL) { + status = omgt_open_port_by_guid(&g_port_handle, *Guidp, session_params); + if (status != FSUCCESS) { + IB_LOG_ERROR_FMT(__func__, + "Failed to bind to GUID 0x%.16"CS64"x; status: %u", + *Guidp, status); + IB_EXIT(__func__, VSTATUS_BAD); + return VSTATUS_BAD; + } + // note that the opamgt interface uses 1-based devices + if (devp != NULL) { + (void)omgt_port_get_hfi_num(g_port_handle, (int32_t *)devp); + (*devp)--; + } + if (portp != NULL) { + uint8_t port_num = 0; + (void)omgt_port_get_hfi_port_num(g_port_handle, &port_num); + *portp = port_num; + } + } else if (devp != NULL && portp != NULL) { + // note that the opamgt interface uses 1-based devices + status = omgt_open_port_by_num(&g_port_handle, *devp + 1, *portp, session_params); + if (status != FSUCCESS) { + // PR 128290 - MWHEINZ - This is a bit of a hack. Some parts of + // the stack use 0-based counting of ports and devices but other + // parts use 1-based. We assume the caller of this function + // is using zero-based counting, so we add 1 when we call + // omgt_open_port_by_num(), but we also assume the user is + // expecting a 1-based device number in their error messages. + IB_LOG_ERROR_FMT(__func__, + "Failed to bind to device %d, port %d; status: %u", + *devp + 1, *portp, status); + IB_EXIT(__func__, VSTATUS_BAD); + return VSTATUS_BAD; + } + if (Guidp != NULL) { + (void)omgt_port_get_port_guid(g_port_handle, Guidp); + } + } else { + IB_LOG_ERROR_FMT(__func__, + "Neither Guid nor device and port were supplied"); + IB_EXIT(__func__, VSTATUS_BAD); + return VSTATUS_BAD; + } + + IB_EXIT(__func__, VSTATUS_OK); + return VSTATUS_OK; +} + +//============================================================================== +// ib_refresh_devport +//============================================================================== +Status_t +ib_refresh_devport(void) +{ + IB_ENTER(__func__, 0, 0, 0, 0); + + if (omgt_mad_refresh_port_pkey(g_port_handle) < 0) { + IB_LOG_ERROR_FMT(__func__, + "Failed to refresh UMAD pkeys"); + IB_EXIT(__func__, VSTATUS_BAD); + return VSTATUS_BAD; + } + IB_EXIT(__func__, VSTATUS_OK); + return VSTATUS_OK; +} + +//============================================================================== +// ib_shutdown +//============================================================================== +Status_t ib_shutdown(void) +{ + IB_ENTER(__func__, 0, 0, 0, 0); + + ib_disable_is_sm(); + omgt_close_port(g_port_handle); + g_port_handle = NULL; + + IB_EXIT(__func__, 0); + return VSTATUS_OK; +} + +//============================================================================== +// ib_register_sm +//============================================================================== +Status_t +ib_register_sm(int queue_size) +{ + FSTATUS status; + + status = omgt_bind_classes(g_port_handle, sm_class_args); + if (status != FSUCCESS) { + IB_LOG_ERROR("Failed to register management classes;", + status); + IB_EXIT(__func__, status); + return status; + } + + IB_EXIT(__func__, status); + return status; +} + +//============================================================================== +// ib_register_fe +//============================================================================== +Status_t +ib_register_fe(int queue_size, uint8_t thread) +{ + FSTATUS status; + + IB_ENTER(__func__, 0, 0, 0, 0); + + status = omgt_bind_classes(g_port_handle, (thread) ? fe_class_args : fe_proc_class_args); + if (status != FSUCCESS) { + IB_LOG_ERROR("Failed to register FE management classes;", + status); + IB_EXIT(__func__, status); + return status; + } + + IB_EXIT(__func__, status); + return status; +} + + +//============================================================================== +// ib_register_pm +//============================================================================== +Status_t +ib_register_pm(int queue_size) +{ + FSTATUS status; + + IB_ENTER(__func__, 0, 0, 0, 0); + + status = omgt_bind_classes(g_port_handle, pm_class_args); + if (status != FSUCCESS) { + IB_LOG_ERROR("Failed to register PM management classes;", + status); + IB_EXIT(__func__, status); + return status; + } + + IB_EXIT(__func__, status); + return status; +} + + + +//============================================================================== +static void +dump_mad(uint8_t *buf, int len, char *prefix) +{ + int i; + char s[1024], *s0 = s; + memset(s, 0, sizeof(s)); + for (i = 0; i < len; ++i) { + sprintf(s0, "%02x", *(buf + i)); s0 += 2; + if (i % 4 == 3) { sprintf(s0, " "); s0 += 1; } + if (i % 16 == 15) { IB_LOG_INFINI_INFO_FMT( __func__, "%s%s", prefix, s); s0 = s; memset(s, 0, sizeof(s)); } + } +} + +//============================================================================== +// ib_recv_sma +//============================================================================== +Status_t +ib_recv_sma(IBhandle_t handle, Mai_t *mai, uint64_t timeout) +{ + FSTATUS status; + Status_t rc; + uint8_t *buf = NULL; + size_t len = 0; + int dev, port; + int issmi; + struct omgt_mad_addr addr; + + IB_ENTER(__func__, handle, mai, timeout, 0); + + IB_FROMHANDLE(handle, dev, port); + + // wait for inbound mad, no timeout + memset (&addr, 0, sizeof(addr)); + retry: + do { + status = omgt_recv_mad_alloc(g_port_handle, &buf, &len, timeout, &addr); + } + while (status == FNOT_DONE); + + // FSUCCESS - got a packet + // FTIMEOUT - wait for response timed out, get header of our request + // FREJECT - unexpected error processing a previous send or its response + // get back at least header of our request + if (status != FSUCCESS && status != FTIMEOUT && status != FREJECT) { + // unexpected problem getting packets + IB_LOG_ERRORSTR("Recieved SMA status:", iba_fstatus_msg(status)); + IB_EXIT(__func__, VSTATUS_BAD); + return VSTATUS_BAD; + } + + if (len < sizeof(MAD_COMMON)) { + // if too small we can't deal with it and must discard it + if (buf) + free(buf); + IB_LOG_ERROR_FMT(__func__, "bad size: %lu status: %s", (unsigned long)len, iba_fstatus_msg(status)); + goto retry; + } +#ifdef DEBUG + else if (len > sizeof(MAD_COMMON) + STL_MAD_PAYLOAD_SIZE) { + // unexpected, we'll ignore the extra bytes of payload + IB_LOG_INFO_FMT(__func__, "large size: %lu status: %s", (unsigned long)len, iba_fstatus_msg(status)); + } +#endif + + // transfer STL packet to MAI structure + rc = stl_wire_to_mai(buf, mai, len); + free(buf); + + if (status == FTIMEOUT || status == FREJECT) { + // extern const char *iba_fstatus_msg(int); + // printf("omgt_recv TYPE_ERROR: status=%s class=0x%x attr=0x%x method=0x%x\n", + // iba_fstatus_msg(status),mai->base.mclass, mai->base.aid, mai->base.method); + // this is a packet we tried to send but failed to send or + // failed to get a response for + mai->type = MAI_TYPE_ERROR; + + // added info message as part of PR 115443 to show that the request timed out + if (status == FTIMEOUT && sm_debug && smDebugPerf) { + IB_LOG_INFINI_INFO_FMT(__func__, "FTIMEOUT of packet status=%s class=0x%x attr=0x%x method=0x%x TID=0x%.16"CS64"X\n", + iba_fstatus_msg(status), mai->base.mclass, mai->base.aid, mai->base.method, mai->base.tid); + } + } + + if (rc != VSTATUS_OK) { + IB_LOG_ERRORRC("Error converting MAD from wire format; rc:", rc); + IB_EXIT(__func__, rc); + return rc; + } + + // SMP's are SMI, all else is GSI + issmi = ((mai->base.mclass == MAD_CV_SUBN_LR || mai->base.mclass == MAD_CV_SUBN_DR) + ? 1 : 0); + + // fill in core MAI structure + mai->dev = dev; + mai->port = port; + mai->qp = issmi ? 0 : 1; + mai->active |=(MAI_ACT_DEV | MAI_ACT_PORT | MAI_ACT_QP); + + // fill in packet header data + mai->addrInfo.qkey = addr.qkey; + mai->addrInfo.srcqp = addr.qpn; + mai->addrInfo.destqp = mai->qp; + mai->addrInfo.pkey = addr.pkey; + mai->addrInfo.sl = addr.sl; + + if(mai->base.mclass == MAD_CV_SUBN_DR && ((DRStlSmp_t*)(mai->data))->DrSLID == STL_LID_PERMISSIVE && ((DRStlSmp_t*)(mai->data))->DrSLID == STL_LID_PERMISSIVE){ + mai->addrInfo.slid = STL_LID_PERMISSIVE; + mai->addrInfo.dlid = STL_LID_PERMISSIVE; + } else { + mai->addrInfo.slid = addr.lid; + mai->addrInfo.dlid = addr.lid; + } + + /* + if (qp == 1) + IB_LOG_WARN_FMT( __func__, "SL is %d (qp=%d, pkey=0x%x, slid= %d)", mai->addrInfo.sl, mai->qp, addr.pkey, mai->addrInfo.slid); + */ + + mai->active |=MAI_ACT_ADDRINFO; + + if (ib_instrumentJmMads + && mai->base.mclass == 0x03 && mai->base.aid == 0xffb2) { + IB_LOG_INFINI_INFO_FMT(__func__, + "Received: mclass 0x%02x method 0x%02x aid 0x%04x amod 0x%08x", + mai->base.mclass, mai->base.method, mai->base.aid, mai->base.amod); + dump_mad(mai->data, (IB_SA_FULL_HEADER_SIZE + IB_SAMAD_DATA_COUNT), " "); + } + + IB_EXIT(__func__, VSTATUS_OK); + return VSTATUS_OK; +} + +//============================================================================== +// stl_send_sma +//============================================================================== +Status_t +stl_send_sma(IBhandle_t handle, Mai_t * mai, uint64_t timeout) +{ + FSTATUS status; + Status_t rc; + uint32_t bufLen = 0; + uint8_t buf[STL_MAX_MAD_DATA]; + int filterMatch; + int adjusted_timeout; + struct omgt_mad_addr addr; + + IB_ENTER(__func__, handle, mai, 0, 0); + + ASSERT(mai != NULL); + + if (mai->type == MAI_TYPE_INTERNAL) { + IB_LOG_VERBOSE_FMT(__func__, "local delivery for MAD to 0x%08x on QP %d", + mai->addrInfo.dlid, mai->qp); + // for local delivery + (void)mai_mad_process(mai, &filterMatch); + IB_EXIT(__func__, VSTATUS_OK); + return VSTATUS_OK; + } + + if ( ib_instrumentJmMads + && mai->base.mclass == 0x03 && mai->base.aid == 0xffb2) { + IB_LOG_INFINI_INFO_FMT( __func__, + "Sent: mclass 0x%02x method 0x%02x aid 0x%04x amod 0x%08x", + mai->base.mclass, mai->base.method, mai->base.aid, mai->base.amod); + dump_mad(mai->data, sizeof(mai->data), " "); + } + + switch (mai->base.bversion) { + case STL_BASE_VERSION: + rc = stl_mai_to_wire(mai, buf, &bufLen); + break; + case IB_BASE_VERSION: + rc = ib_mai_to_wire(mai, buf); + bufLen = IB_MAX_MAD_DATA; + break; + default: + rc = VSTATUS_ILLPARM; + break; + } + + if (rc != VSTATUS_OK) { + IB_LOG_ERRORRC("converting MAD to wire format; rc:", rc); + IB_EXIT(__func__, rc); + return rc; + } + + // only send a timeout that is 90% of what the caller thinks it should be. + // this is to give OFED a moment to clear the MAD off the send list before + // the caller retries. without this, the caller's retry might be rejected + // as a duplicate if it comes in too quickly + // TBD - once all callers fixed, use timeout as given + adjusted_timeout = (int)(timeout * 9 / 10 * VTIMER_1_MILLISEC / VTIMER_1S); + if (adjusted_timeout <= 0 && timeout > 0) + adjusted_timeout=1; + + memset(&addr, 0, sizeof(addr)); + addr.lid = mai->addrInfo.dlid; + addr.qpn = mai->addrInfo.destqp; + addr.qkey = mai->addrInfo.qkey; + addr.pkey = mai->addrInfo.pkey; + addr.sl = mai->addrInfo.sl; + //IB_LOG_INFINI_INFO_FMT(__func__, "Sending MAD of size %d bytes", bufLen); + status = omgt_send_mad2(g_port_handle, (void*)buf, bufLen, &addr, adjusted_timeout, 0); + if (status != FSUCCESS) { + if (mai->addrInfo.srcqp != 1) { + IB_LOG_INFO("Error sending packet via OPENIB interface; status:", status); + } else { + IB_LOG_INFO_FMT(__func__, + "Error sending packet via OPENIB interface; status: %u (sl= %d, pkey= 0x%x)", + status, mai->addrInfo.sl, mai->addrInfo.pkey); + } + IB_EXIT(__func__, VSTATUS_BAD); + return VSTATUS_BAD; + } + + IB_EXIT(__func__, VSTATUS_OK); + return VSTATUS_OK; +} + +//============================================================================== +// ib_attach_sma +//============================================================================== +Status_t +ib_attach_sma(int16_t dev, int8_t port, uint32_t qpn, + IBhandle_t *handlep, uint8_t *nodeTypep) +{ + FSTATUS status; + uint8_t type; + + IB_ENTER(__func__, dev, port, qpn, 0); + + if (handlep != NULL) + *handlep = IB_MAKEHANDLE(dev, port); + + if (nodeTypep != NULL) + { + status = omgt_port_get_node_type(g_port_handle, &type); + if (status == FSUCCESS) + *nodeTypep = type; + else + { + IB_LOG_WARN("failed to get node type; status:", status); + IB_EXIT(__func__, VSTATUS_BAD); + return VSTATUS_BAD; + } + } + + IB_EXIT(__func__, VSTATUS_OK); + return VSTATUS_OK; +} + +//============================================================================== +// ib_detach_sma +//============================================================================== +Status_t +ib_detach_sma(IBhandle_t handle) +{ + return VSTATUS_OK; +} + +//============================================================================== +// ib_init_sma +//============================================================================== +Status_t +ib_init_sma(uint32_t maxMadBuffers) +{ + return VSTATUS_OK; +} + +//============================================================================== +// ib_term_sma +//============================================================================== +Status_t +ib_term_sma(void) +{ + return VSTATUS_OK; +} + +//============================================================================== +// ib_shutdown_all +//============================================================================== +void +ib_shutdown_all(void) +{ +} + +//============================================================================== +// ib_enable_is_sm +//============================================================================== +Status_t ib_enable_is_sm(void) +{ + Status_t status; + FSTATUS rc; + char dev[IB_ISSM_DEVICEPATH_MAXLEN+1]; + + IB_ENTER(__func__, 0, 0, 0, 0); + + status = vs_lock(&ib_issm.lock); + if (status != VSTATUS_OK) { + vs_unlock(&ib_issm.lock); + IB_LOG_WARNRC("failed to acquire issm lock; rc:", status); + IB_EXIT(__func__, status); + return status; + } + + rc = omgt_get_issm_device(g_port_handle, dev, IB_ISSM_DEVICEPATH_MAXLEN); + if (rc != FSUCCESS) { + IB_LOG_WARN("failed to resolve ISSM device name; status:", status); + IB_EXIT(__func__, VSTATUS_BAD); + return VSTATUS_BAD; + } + + // if already open, silently skip + if (ib_issm.fp == NULL) { + ib_issm.fp = fopen(dev, "rb"); + if (ib_issm.fp == NULL) { + vs_unlock(&ib_issm.lock); + IB_LOG_WARN0("failed to open issm device"); + IB_EXIT(__func__, VSTATUS_BAD); + return VSTATUS_BAD; + } + } + + vs_unlock(&ib_issm.lock); + + IB_EXIT(__func__, VSTATUS_OK); + return VSTATUS_OK; +} + +//============================================================================== +// ib_disable_is_sm +//============================================================================== +Status_t ib_disable_is_sm(void) +{ + Status_t status; + IB_ENTER(__func__, 0, 0, 0, 0); + + status = vs_lock(&ib_issm.lock); + if (status != VSTATUS_OK) { + IB_LOG_WARNRC("failed to acquire issm lock; rc:", status); + IB_EXIT(__func__, status); + return status; + } + + if (ib_issm.fp != NULL) { + fclose(ib_issm.fp); + ib_issm.fp = NULL; + } + + vs_unlock(&ib_issm.lock); + + IB_EXIT(__func__, VSTATUS_OK); + return VSTATUS_OK; +} + +//============================================================================== +// stl_mad_to_mai +//============================================================================== +static void stl_mad_to_mai(MAD* mad, Mai_t *mai) +{ + mai->base.bversion = mad->common.BaseVersion; + mai->base.mclass = mad->common.MgmtClass; + mai->base.cversion = mad->common.ClassVersion; + mai->base.method = mad->common.mr.AsReg8; + if (mad->common.MgmtClass == MCLASS_SM_DIRECTED_ROUTE) { + mai->base.status = mad->common.u.DR.s.Status; + mai->base.hopCount = mad->common.u.DR.HopCount; + mai->base.hopPointer = mad->common.u.DR.HopPointer; + } else + mai->base.status = mad->common.u.NS.Status.AsReg16; + mai->base.tid = mad->common.TransactionID; + mai->base.aid = mad->common.AttributeID; + mai->base.amod = mad->common.AttributeModifier; +} + +//============================================================================== +// ib_mai_to_wire +//============================================================================== +static Status_t +ib_mai_to_wire(Mai_t *mad, uint8_t *buf) +{ + int isDrouted; + uint32_t mask = 0; + + IB_ENTER(__func__, mad, buf, 0, 0); + + // Validate the obvious parameters + if (mad == NULL) { + IB_LOG_ERROR0("Invalid parameter: 'mad'"); + IB_EXIT(__func__, VSTATUS_ILLPARM); + return VSTATUS_ILLPARM; + } + + // Make sure we have a MAD header + mask = MAI_ACT_TYPE; + if ((mad->active & mask) != mask) { + IB_LOG_ERROR0("MAI_ACT_TYPE not active!"); + IB_EXIT(__func__, VSTATUS_INVALID_MADT); + return VSTATUS_INVALID_MADT; + } + + // Validate the type of MAD + switch (mad->type) { + case MAI_TYPE_EXTERNAL: + IB_LOG_INFO("Type is MAD", mad->type); + // MADs require these fields + mask = MAI_ACT_ADDRINFO; + if ((mad->active & mask) != mask) { + IB_LOG_ERROR("Invalid Mai_t:", mad->active); + IB_EXIT(__func__, VSTATUS_INVALID_MAD); + return VSTATUS_INVALID_MAD; + } + break; + default: + IB_LOG_ERROR("Invalid MAD type:", mad->type); + IB_EXIT(__func__, VSTATUS_INVALID_TYPE); + return VSTATUS_INVALID_TYPE; + } + + // Figure out about Direct Routed or LID routed + isDrouted = 0; /* Assume we are LID routed */ + if (mad->base.mclass == MAD_CV_SUBN_DR) + isDrouted = 1; + + // Setup reasonable defaults + // Check for 'Reserved' values in management class + if ( mad->base.mclass == 0 || mad->base.mclass == 2 + || (mad->base.mclass >= 0x50 && mad->base.mclass <= 0x80) + || mad->base.mclass >= 0x82) + { + IB_LOG_ERROR("Reserved management class:", + mad->base.mclass); + IB_EXIT(__func__, VSTATUS_INVALID_MCLASS); + return VSTATUS_INVALID_MCLASS; + } + + mad->base.bversion = MAD_BVERSION; + mad->base.rsvd3 = 0; + + // copy MAD base header + if (mad->active & MAI_ACT_BASE) { + // Display the base header + if (IB_LOG_IS_INTERESTED(VS_LOG_INFO)) { + IB_LOG_INFO("Base BaseVersion ", mad->base.bversion); + IB_LOG_INFO(" MgmtClass ", mad->base.mclass); + IB_LOG_INFO(" ClassVersion ", mad->base.cversion); + IB_LOG_INFO(" Method ", mad->base.method); + IB_LOG_INFO(" Status ", mad->base.status); + IB_LOG_INFO(" HopPointer ", mad->base.hopPointer); + IB_LOG_INFO(" HopCount ", mad->base.hopCount); + IB_LOG_INFOLX(" TID ", mad->base.tid & 0xffffffffu); + IB_LOG_INFO(" AttributeID ", mad->base.aid); + IB_LOG_INFO(" AttributeMod ", mad->base.amod); + IB_LOG_INFO_FMT(__func__,"FullTID: 0x%016"CS64"x", mad->base.tid); + } + + if (isDrouted) { + // clear status and ensure return bit is set if necessary + mad->base.status = mad->base.method == MAD_CM_GET_RESP + ? MAD_DR_RETURN : MAD_DR_INITIAL; + } + + memcpy(buf, &mad->base, sizeof(mad->base)); + (void)BSWAP_MAD_HEADER((MAD *)buf); + } + + // Copy data to the end of the wire buffer + if (!(mad->active & MAI_ACT_DATA) && mad->datasize <= 0) { + IB_LOG_ERROR("datasize size indeterminate:", mad->datasize); + IB_EXIT(__func__, VSTATUS_INVALID_MADLEN); + return VSTATUS_INVALID_MADLEN; + } else { + // we are constrained to send the number of bytes of the supported + // payload at all times + if (mad->datasize && mad->datasize > IB_MAD_PAYLOAD_SIZE) { + IB_LOG_ERROR("datasize out of range:", mad->datasize); + IB_EXIT(__func__, VSTATUS_TOO_LARGE); + return VSTATUS_TOO_LARGE; + } else { + // MAI_ACT_DATA not active; send the payload balance + mad->datasize = IB_MAD_PAYLOAD_SIZE; + } + + memcpy(buf + sizeof(MAD_COMMON), mad->data, mad->datasize); + + if (isDrouted) { + // magic numbers: DR LIDs are 32 bytes into a DR SMP header and + // are 2 bytes long each + *(uint16_t*)(buf + 32) = hton16(*(uint16_t*)(buf + 32)); + *(uint16_t*)(buf + 34) = hton16(*(uint16_t*)(buf + 34)); + } + } + + // VENDOR MAD HACK: + // We use SA MAD headers for vendor classes, but the new vendor range + // requires a specific header with an OUI field 37 bytes into the MAD. + // In the SA header, this would be in the middle of the SM Key. Since + // we're not using anything past the RMPP header for vendor traffic, we'll + // just write the OUI directly into the MAD. + if ( mad->base.mclass >= IBA_VENDOR_RANGE2_START + && mad->base.mclass <= IBA_VENDOR_RANGE2_END) + memcpy(buf + 37, ib_truescale_oui, 3); + // END HORRIBLE HORRIBLE HACK + + IB_EXIT(__func__, VSTATUS_OK); + return VSTATUS_OK; +} + +//============================================================================== +// stl_mai_to_wire +//============================================================================== +static Status_t +stl_mai_to_wire(Mai_t *mad, uint8_t *buf, uint32_t *bufLen) +{ + int isDrouted; + uint32_t mask = 0; + + IB_ENTER(__func__, mad, buf, 0, 0); + + // Validate the obvious parameters + if (mad == NULL) { + IB_LOG_ERROR0("Invalid parameter: 'mad'"); + IB_EXIT(__func__, VSTATUS_ILLPARM); + return VSTATUS_ILLPARM; + } + + // Make sure we have a MAD header + mask = MAI_ACT_TYPE; + if ((mad->active & mask) != mask) { + IB_LOG_ERROR0("MAI_ACT_TYPE not active!"); + IB_EXIT(__func__, VSTATUS_INVALID_MADT); + return VSTATUS_INVALID_MADT; + } + + // Validate the type of MAD + switch (mad->type) { + case MAI_TYPE_EXTERNAL: + IB_LOG_INFO("Type is MAD", mad->type); + // MADs require these fields + mask = MAI_ACT_ADDRINFO; + if ((mad->active & mask) != mask) { + IB_LOG_ERROR("Invalid Mai_t:", mad->active); + IB_EXIT(__func__, VSTATUS_INVALID_MAD); + return VSTATUS_INVALID_MAD; + } + break; + default: + IB_LOG_ERROR("Invalid MAD type:", mad->type); + IB_EXIT(__func__, VSTATUS_INVALID_TYPE); + return VSTATUS_INVALID_TYPE; + } + + // Figure out about Direct Routed or LID routed + isDrouted = 0; /* Assume we are LID routed */ + if (mad->base.mclass == MAD_CV_SUBN_DR) + isDrouted = 1; + + // Setup reasonable defaults + // Check for 'Reserved' values in management class + if (mad->base.mclass == 0 || mad->base.mclass == 2 + || (mad->base.mclass >= 0x50 && mad->base.mclass <= 0x80) + || mad->base.mclass >= 0x82) { + IB_LOG_ERROR("Reserved management class:", + mad->base.mclass); + IB_EXIT(__func__, VSTATUS_INVALID_MCLASS); + return VSTATUS_INVALID_MCLASS; + } + + mad->base.bversion = STL_BASE_VERSION; + mad->base.rsvd3 = 0; + + // copy MAD base header + if (mad->active & MAI_ACT_BASE) { + // Display the base header + if (IB_LOG_IS_INTERESTED(VS_LOG_INFO)) { + IB_LOG_INFO("Base BaseVersion ", mad->base.bversion); + IB_LOG_INFO(" MgmtClass ", mad->base.mclass); + IB_LOG_INFO(" ClassVersion ", mad->base.cversion); + IB_LOG_INFO(" Method ", mad->base.method); + IB_LOG_INFO(" Status ", mad->base.status); + IB_LOG_INFO(" HopPointer ", mad->base.hopPointer); + IB_LOG_INFO(" HopCount ", mad->base.hopCount); + IB_LOG_INFOLX(" TID ", mad->base.tid & 0xffffffffu); + IB_LOG_INFO(" AttributeID ", mad->base.aid); + IB_LOG_INFO(" AttributeMod ", mad->base.amod); + IB_LOG_INFO_FMT(__func__, "FullTID: 0x%016"CS64"x", mad->base.tid); + } + + if (isDrouted) { + // clear status and ensure return bit is set if necessary + mad->base.status = mad->base.method == MAD_CM_GET_RESP + ? MAD_DR_RETURN : MAD_DR_INITIAL; + } + + memcpy(buf, &mad->base, sizeof(mad->base)); + (void)BSWAP_MAD_HEADER((MAD *)buf); + } + + // Copy data to the end of the wire buffer + if (!(mad->active & MAI_ACT_DATA) && mad->datasize <= 0) { + IB_LOG_ERROR("datasize size indeterminate:", mad->datasize); + IB_EXIT(__func__, VSTATUS_INVALID_MADLEN); + return VSTATUS_INVALID_MADLEN; + } else { + if (mad->datasize) { + // assume the datasize field is valid + if (mad->datasize > STL_MAD_PAYLOAD_SIZE) { + IB_LOG_ERROR("datasize out of range:", mad->datasize); + IB_EXIT(__func__, VSTATUS_TOO_LARGE); + return VSTATUS_TOO_LARGE; + } + } else { + // in order to handle requests from legacy code, check validity of + // the datasize field. if not valid then, set the datasize to max payload size; + // otherwise datasize field is valid indicating a payload with no data. + if (!(mad->active & MAI_ACT_DATASIZE)) + mad->datasize = STL_MAD_PAYLOAD_SIZE; + } + + *bufLen = MAD_BASEHDR_SIZE + mad->datasize; + memcpy(buf + MAD_BASEHDR_SIZE, mad->data, mad->datasize); + + if (isDrouted) { + STL_SMP *smp = (STL_SMP *)buf; + +#if CPU_LE + smp->M_Key = ntoh64(smp->M_Key); + smp->SmpExt.DirectedRoute.DrSLID = ntoh32(smp->SmpExt.DirectedRoute.DrSLID); + smp->SmpExt.DirectedRoute.DrDLID = ntoh32(smp->SmpExt.DirectedRoute.DrDLID); +#endif + } + } + + // VENDOR MAD HACK: + // We use SA MAD headers for vendor classes, but the new vendor range + // requires a specific header with an OUI field 37 bytes into the MAD. + // In the SA header, this would be in the middle of the SM Key. Since + // we're not using anything past the RMPP header for vendor traffic, we'll + // just write the OUI directly into the MAD. + if (mad->base.mclass >= IBA_VENDOR_RANGE2_START + && mad->base.mclass <= IBA_VENDOR_RANGE2_END) { + memcpy(buf + 37, ib_truescale_oui, 3); + } + // END HORRIBLE HORRIBLE HACK + + IB_EXIT(__func__, VSTATUS_OK); + return VSTATUS_OK; +} + +//============================================================================== +// stl_wire_to_mai +//============================================================================== +static Status_t +stl_wire_to_mai(uint8_t *buf, Mai_t *mad, int len) +{ + IB_ENTER(__func__, 0, 0, 0, 0); + + // Validate the obvious parameters + if (mad == NULL) { + IB_LOG_ERROR0("NULL mad pointer passed"); + IB_EXIT(__func__, VSTATUS_ILLPARM); + return VSTATUS_ILLPARM; + } + if (buf == NULL) { + IB_LOG_ERROR0("NULL buf pointer passed"); + IB_EXIT(__func__, VSTATUS_ILLPARM); + return VSTATUS_ILLPARM; + } + + // clear out the active mask on the Mai_t struct + memset(mad, 0, sizeof(Mai_t)); + + mad->type = MAI_TYPE_EXTERNAL; // Assume type MAD until told otherwise + mad->active = MAI_ACT_TYPE; + + (void)BSWAP_MAD_HEADER((MAD *)buf); + (void)stl_mad_to_mai((MAD *)buf, mad); + + // convert the data only if we can identify the header + if (mad->base.bversion != MAD_BVERSION && mad->base.bversion != STL_BASE_VERSION) { + IB_LOG_ERROR("Unknown MAD version:", mad->base.bversion); + return VSTATUS_BAD; + } + + // Check for 'Reserved' values in management class + if (mad->base.mclass == 0 || mad->base.mclass == 2 + || (mad->base.mclass >= 0x50 && mad->base.mclass <= 0x80) + || mad->base.mclass >= 0x82) { + IB_LOG_ERROR("Reserved management class:", + mad->base.mclass); + return VSTATUS_BAD; + } + + if (mad->base.mclass == MAD_CV_SUBN_DR + && mad->base.hopPointer > IBA_MAX_PATHSIZE) { + IB_LOG_ERROR("Unexpected hopPointer value:", + mad->base.hopPointer); + return VSTATUS_BAD; + } + + // We can safely say the MAD header is valid now. + mad->active |= MAI_ACT_BASE; + if (IB_LOG_IS_INTERESTED(VS_LOG_INFO)) { + IB_LOG_INFO("Base BaseVersion ", mad->base.bversion); + IB_LOG_INFO(" MgmtClass ", mad->base.mclass); + IB_LOG_INFO(" ClassVersion ", mad->base.cversion); + IB_LOG_INFO(" Method ", mad->base.method); + IB_LOG_INFO(" Status ", mad->base.status); + IB_LOG_INFO(" HopPointer ", mad->base.hopPointer); + IB_LOG_INFO(" HopCount ", mad->base.hopCount); + IB_LOG_INFOLX(" TID ", mad->base.tid); + IB_LOG_INFO(" AttributeID ", mad->base.aid); + IB_LOG_INFO(" AttributeMod ", mad->base.amod); + IB_LOG_INFO_FMT(__func__, "FullTID: 0x%016"CS64"x", mad->base.tid); + } + + // Copy the data, if no data leave it zeroed from memset above + if (len > MAD_BASEHDR_SIZE) { + memcpy(mad->data, buf + MAD_BASEHDR_SIZE, len - MAD_BASEHDR_SIZE); + mad->datasize = len - MAD_BASEHDR_SIZE; + } else { + mad->datasize = 0; + } + + (void)vs_time_get(&mad->intime); + + mad->active |= MAI_ACT_DATA | MAI_ACT_TSTAMP | MAI_ACT_FMASK; + + IB_EXIT(__func__, VSTATUS_OK); + return VSTATUS_OK; +} + diff --git a/Esm/ib/src/ibaccess/cs_util.h b/Esm/ib/src/ibaccess/cs_util.h new file mode 100755 index 0000000..3a4ceed --- /dev/null +++ b/Esm/ib/src/ibaccess/cs_util.h @@ -0,0 +1,74 @@ +/* BEGIN_ICS_COPYRIGHT2 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + * ** END_ICS_COPYRIGHT2 ****************************************/ + +//======================================================================= +// / +// FILE NAME / +// cs_util.h / +// / +// DESCRIPTION / +// / +// This is the OPA FM common services transport utility header / +// / +// DATA STRUCTURES / +// [global component data structures defined in this file] / +// / +// DEPENDENCIES / +// none / +// / +// HISTORY / +// / +// NAME DATE REMARKS / +// trp 01/24/01 Initial creation of file. / +// trp 02/05/01 Changed IBerror_t to Status_t / +// trp 02/05/01 Removed cs_mad stuff / +// trp 02/09/01 Moved VIEO specific stuff here / +// trp 02/13/01 Added prototypes for media to/from struct funcs / +// trp 02/14/01 Moved prototypes for media to/from to tapi / +// trp 03/14/01 Changed cs_tapi to cs_g for newly merged headers / +// trp 04/16/01 Removed vs_pkt.h include / +// trp 05/31/01 Added cep create/destroy prototypes / +// / +//======================================================================= + +#ifndef _CS_UTIL_H +#define _CS_UTIL_H + +#include "cs_g.h" +#include "cs_ds.h" + + +Status_t cs_clone_hca (CShca_t *hp, CShca_t **clonep); +Status_t cs_get_con_t_ptr ( CShca_t *hp, CScon_t **cpp); +Status_t cs_get_pathp (CScon_t *conp, uint8_t flag, CSpath_t **pathp); +void cs_mad_dump (Mai_t *pkt); + + +#endif // _CS_UTIL_H + diff --git a/Esm/ib/src/ibaccess/vs_evt.c b/Esm/ib/src/ibaccess/vs_evt.c new file mode 100644 index 0000000..3880663 --- /dev/null +++ b/Esm/ib/src/ibaccess/vs_evt.c @@ -0,0 +1,626 @@ + +/* BEGIN_ICS_COPYRIGHT5 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + * ** END_ICS_COPYRIGHT5 ****************************************/ + +/************************************************************************ +* +* FILE NAME +* vs_evt.c +* +* DESCRIPTION +* Implemenation of Common Services Events +* +* DATA STRUCTURES +* None +* +* FUNCTIONS +* vs_event_create Create an event object. +* vs_event_wait Wait for an event. +* vs_event_post Post an event. +* vs_event_delete Delete an event. +* +* DEPENDENCIES +* Nucleus Plus RTOS. +* +* +***********************************************************************/ + +#include +#include +#include +#include +#include +#include "ib_types.h" +#include "ib_status.h" +#include "vs_g.h" +#include "cs_g.h" +#include "cs_log.h" +#include + +/* log as Common Services Mudule */ +#undef LOCAL_MOD_ID +#define LOCAL_MOD_ID VIEO_CS_MOD_ID + +/* + * Implementation private data structure + */ +#define IMPLPRIV_EVENT_MAGIC ((uint32_t) 0x688294CCU) +#define OP_OR 1 +#define OP_AND 2 +#define MAX_THREAD_WAIT 25 /* Max number of threads that can wait on an event */ +#define MAX_EVENTS 32 + +typedef struct +{ + pthread_mutex_t mutex; + pthread_cond_t cond; + uint32_t count; +} MaskList_Event_t; + +typedef struct { + uint32_t magic; + int id; +} Implpriv_Event_t; + +typedef struct MaskList_s { + MaskList_Event_t event[MAX_EVENTS]; + int id; + struct MaskList_s *prev; + struct MaskList_s *next; +} MaskList_t; + + + +MaskList_t *MaskList_Head; +Lock_t maskList_sem; +Lock_t eventArray[MAX_EVENTS]; +int currentId; +int maskListInited = 0; + + +Status_t deleteMask(int id); +Status_t createMask(void); +Status_t vs_evt_MaskListInit(void); +Status_t sendEvent(int id, Eventset_t mask); +Status_t sendWakeAllEvent(int id, Eventset_t mask); +Status_t getEvent(int id, Eventset_t mask, int ticks); + + +/*********************************************************************************/ + +Status_t +vs_event_create (Event_t * ec, unsigned char name[], Eventset_t state) +{ + static const char function[] = "vs_event_create"; + uint32_t namesize; + Implpriv_Event_t *implpriv; + + IB_ENTER (function, (unint) ec, (unint) name, (uint32_t) state, + (uint32_t) 0U); + + if (ec == 0) + { + IB_LOG_ERROR0 ("Event_t parameter is null"); + IB_EXIT (function, VSTATUS_ILLPARM); + return VSTATUS_ILLPARM; + } + + if (name == 0) + { + IB_LOG_ERROR0 ("name parameter is null"); + IB_EXIT (function, VSTATUS_ILLPARM); + return VSTATUS_ILLPARM; + } + + for (namesize = 0U; namesize < VS_NAME_MAX; namesize++) + { + if (name[namesize] == (unsigned char) 0x00) + { + (void) memmove (ec->name, name, namesize + 1U); + break; + } + } + + if (namesize >= VS_NAME_MAX) + { + IB_LOG_ERROR0 ("name doesn't contain a terminator"); + IB_EXIT (function, VSTATUS_ILLPARM); + return VSTATUS_ILLPARM; + } + + /* + ** this is a run-time check to ensure that the opaque section of Event_t + ** is large enough to contain the Implementation private data structure. + ** If this test fails, adjust the OPAQUE_EVENT_SIZE_WORDS define in + ** cs_g.h and rebuild. + */ + if (sizeof (Implpriv_Event_t) > sizeof (ec->opaque)) + { + IB_LOG_ERROR ("Implpriv_Event_t too big:", sizeof (Implpriv_Event_t)); + IB_EXIT (function, VSTATUS_ILLPARM); + return VSTATUS_ILLPARM; + } + + /* + ** this is a run-time check to make sure that the event array is supported by + ** the ATI implementation. + */ + if (sizeof (Eventset_t) > sizeof (uint32_t)) + { + IB_LOG_ERROR0 ("Implpriv_Event_t does not support size of event array."); + IB_EXIT (function, VSTATUS_NODEV); + return VSTATUS_NODEV; + } + + implpriv = (Implpriv_Event_t *) (void *) & ec->opaque; + memset(implpriv, 0, sizeof(*implpriv)); + + implpriv->magic = IMPLPRIV_EVENT_MAGIC; + ec->event_handle = ec; + IB_LOG_INFO("handle: ", ec->event_handle); + + if((implpriv->id = createMask()) == 0){ + IB_LOG_ERROR0 ("Mask Creation Failed"); + IB_EXIT (function, VSTATUS_NODEV); + return VSTATUS_NODEV; + } + + + + IB_EXIT (function, VSTATUS_OK); + return VSTATUS_OK; +} + +Status_t +vs_event_delete (Event_t * ec) +{ + static const char function[] = "vs_event_delete"; + Implpriv_Event_t *implpriv; + + if (ec == 0) + { + IB_LOG_ERROR0 ("handle parameter is null"); + IB_EXIT (function, VSTATUS_ILLPARM); + return VSTATUS_ILLPARM; + } + + implpriv = (Implpriv_Event_t *) (void *) & ec->opaque; + if (implpriv->magic != IMPLPRIV_EVENT_MAGIC) + { + IB_LOG_ERRORX ("Invalid magic:", implpriv->magic); + IB_EXIT (function, VSTATUS_NXIO); + return VSTATUS_NXIO; + } + + implpriv->magic = ~IMPLPRIV_EVENT_MAGIC; + ec->event_handle = 0; + + deleteMask(implpriv->id); + implpriv->id = 0; + + IB_EXIT (function, VSTATUS_OK); + return VSTATUS_OK; +} + +Status_t +vs_event_post (Evt_handle_t handle, uint32_t option, + Eventset_t mask) +{ + static const char function[] = "vs_event_post"; + Event_t *ec; + Implpriv_Event_t *implpriv; + + IB_ENTER (function, (unint) handle, option, (uint32_t) mask, 0U); + + if (handle == 0) + { + IB_LOG_ERROR0 ("handle parameter is null"); + IB_EXIT (function, VSTATUS_ILLPARM); + return VSTATUS_ILLPARM; + } + + if (mask == (Eventset_t) 0x00U) + { + IB_LOG_ERROR0 ("mask parameter is zero"); + IB_EXIT (function, VSTATUS_ILLPARM); + return VSTATUS_ILLPARM; + } + + if ((option != VEVENT_WAKE_ONE) && (option != VEVENT_WAKE_ALL)) + { + IB_LOG_ERROR ("Invalid option:", option); + IB_EXIT (function, VSTATUS_ILLPARM); + return VSTATUS_ILLPARM; + } + + ec = (Event_t *) handle; + implpriv = (Implpriv_Event_t *) (void *) & ec->opaque; + + if (implpriv->magic != IMPLPRIV_EVENT_MAGIC) + { + IB_LOG_ERRORX ("Invalid magic:", implpriv->magic); + IB_EXIT (function, VSTATUS_NXIO); + return VSTATUS_NXIO; + } + + if (ec->event_handle != handle) + { + IB_LOG_ERRORX ("Invalid handle:", (unint) ec->event_handle); + IB_EXIT (function, VSTATUS_NXIO); + return VSTATUS_NXIO; + } + + if(option == VEVENT_WAKE_ALL){ + // printf("vs_event_post: Wake ALL %s\n", taskName(taskIdSelf())); + // printf("vs_event_post: Wake ALL %s mask 0x%x\n", taskName(taskIdSelf()),(unsigned int)mask); + IB_LOG_INFO ("VEVENT_WAKE_ALL", mask); + sendWakeAllEvent(implpriv->id,mask); + }else{ + /* Get the number of pending threads */ + //printf("vs_event_post: Wake One %s mask 0x%x\n", taskName(taskIdSelf()),(unsigned int)mask); + IB_LOG_INFO ("VEVENT_WAKE_ONE", mask); + sendEvent(implpriv->id,mask); + } + + + IB_EXIT (function, VSTATUS_OK); + return VSTATUS_OK; +} + +Status_t +vs_event_wait (Evt_handle_t handle, uint64_t timeout, + Eventset_t mask, Eventset_t * events) +{ + static const char function[] = "vs_event_wait"; + Event_t *ec; + int ticks; + Implpriv_Event_t *implpriv; + Status_t rc; + + IB_ENTER (function, (unint) handle, timeout, + (uint32_t) mask, 0); + + if (handle == 0) + { + IB_LOG_ERROR0 ("handle parameter is null"); + IB_EXIT (function, VSTATUS_ILLPARM); + return VSTATUS_ILLPARM; + } + + ec = (Event_t *) handle; + implpriv = (Implpriv_Event_t *) (void *) & ec->opaque; + if (implpriv->magic != IMPLPRIV_EVENT_MAGIC) + { + IB_LOG_ERRORX ("Invalid magic:", implpriv->magic); + IB_EXIT (function, VSTATUS_NXIO); + return VSTATUS_NXIO; + } + + if (mask == (Eventset_t) 0x00U) + { + IB_LOG_ERROR0 ("mask parameter is zero"); + IB_EXIT (function, VSTATUS_ILLPARM); + return VSTATUS_ILLPARM; + } + + if (events == (Eventset_t *) 0) + { + IB_LOG_ERROR0 ("events parameter is null"); + IB_EXIT (function, VSTATUS_ILLPARM); + return VSTATUS_ILLPARM; + } + if(timeout == 0) + { + ticks = -1; + } + else + { + ticks = timeout; + } + + rc = getEvent(implpriv->id, mask, ticks); + if(rc == VSTATUS_OK){ + //printf("Task %s consumed: mask: 0x%x\n", taskName(taskIdSelf()), (unsigned int)mask); + } + + + + IB_EXIT (function, rc); + return rc; +} + + +int getMaskIndex(Eventset_t mask){ + int i=0; + for(i=0;isemId[i]); + } +} + +MaskList_t* getLocalMaskList(int id){ + MaskList_t *temp; + + vs_lock(&maskList_sem); + + if(MaskList_Head != 0){ + for(temp = MaskList_Head; temp != NULL; temp = temp->next){ + if(id == temp->id){ + vs_unlock(&maskList_sem); + return temp; + } + } + } + + vs_unlock(&maskList_sem); + return 0; +} + +Status_t sendEvent(int id, Eventset_t mask){ + MaskList_t *temp; + Status_t rc = VSTATUS_BAD; + int index; + + if((index = getMaskIndex(mask)) == -1){ + IB_LOG_ERROR0("Mask is either NULL or out of range"); + return VSTATUS_BAD; + } + + if((temp = getLocalMaskList(id)) != 0){ + (void)pthread_mutex_lock (&temp->event[index].mutex); + temp->event[index].count++; + (void)pthread_cond_broadcast (&temp->event[index].cond); + (void)pthread_mutex_unlock (&temp->event[index].mutex); + rc = VSTATUS_OK; + } + + return rc; +} + +Status_t sendWakeAllEvent(int id, Eventset_t mask){ + MaskList_t *temp; + Status_t rc = VSTATUS_BAD; + int index; + + if((index = getMaskIndex(mask)) == -1){ + IB_LOG_ERROR0("Mask is either NULL or out of range"); + return VSTATUS_BAD; + } + + if((temp = getLocalMaskList(id)) != 0){ + (void)pthread_mutex_lock (&temp->event[index].mutex); + /* Not sure if we should increment the count here or not */ + /* temp->event[index].count++; */ + (void)pthread_cond_broadcast (&temp->event[index].cond); + (void)pthread_mutex_unlock (&temp->event[index].mutex); + rc = VSTATUS_OK; + } + + return rc; +} + +Status_t getEvent(int id, Eventset_t mask, int ticks){ + MaskList_t *temp; + Status_t rc = VSTATUS_BAD; + int index; + struct timespec abstime; + struct timeval now; + + gettimeofday(&now, NULL); + abstime.tv_sec = now.tv_sec + (ticks/1000000); + abstime.tv_nsec = (now.tv_usec + (ticks % 1000000)) * 1000; + // handle carry from nsec to sec + if (abstime.tv_nsec > 1000000000) { + abstime.tv_sec++; + abstime.tv_nsec -= 1000000000; + } + + if((index = getMaskIndex(mask)) == -1){ + IB_LOG_ERROR0("Mask is either NULL or out of range"); + return VSTATUS_BAD; + } + + if((temp = getLocalMaskList(id)) != 0){ + (void)pthread_mutex_lock (&temp->event[index].mutex); + if(temp->event[index].count){ + /* Event was posted before we waited on it */ + temp->event[index].count--; + rc = VSTATUS_OK; + }else{ + if(pthread_cond_timedwait(&temp->event[index].cond, &temp->event[index].mutex, &abstime) != 0){ + rc = VSTATUS_TIMEOUT; + }else{ + rc = VSTATUS_OK; + if(temp->event[index].count) + temp->event[index].count--; + + } + } + (void)pthread_mutex_unlock (&temp->event[index].mutex); + } + + + return rc; +} + + + + + +Status_t deleteMask(int id){ + MaskList_t *temp; + Status_t rc = VSTATUS_BAD; + + if(vs_lock(&maskList_sem) != VSTATUS_OK){ + return VSTATUS_BAD; + } + + if(MaskList_Head != 0){ + for(temp = MaskList_Head; temp != NULL; temp = temp->next){ + if(id == temp->id){ + if((temp->next == NULL) && (temp->prev == NULL)){ // Only link in list. + cleanMask(temp); + free(temp); + MaskList_Head = NULL; + }else if(temp->next == NULL){ // Last link in list + temp->prev->next = NULL; + cleanMask(temp); + free(temp); + }else if(temp->prev == NULL){ // First Link in list + MaskList_Head = temp->next; + temp->next->prev = NULL; + cleanMask(temp); + free(temp); + }else{ // In the middle of the list. + temp->prev->next = temp->next; + temp->next->prev = temp->prev; + cleanMask(temp); + free(temp); + } + rc = VSTATUS_OK; + break; + } + } + } + vs_unlock (&maskList_sem); + return rc; +} + +Status_t createMask(){ + MaskList_t *temp = NULL; + int i; + + vs_evt_MaskListInit(); + + if(vs_lock(&maskList_sem) != VSTATUS_OK){ + return VSTATUS_BAD; + } + currentId++; + + if((temp = calloc(1,sizeof(MaskList_t))) == NULL){ + IB_LOG_ERROR0("Could not allocate space!"); + vs_unlock (&maskList_sem); + return 0; + } + + temp->next = NULL; + temp->prev = NULL; + temp->id = currentId; + for(i=0;ievent[i].mutex, NULL) != 0){ + IB_LOG_ERROR0("Error while initializing mutexes!"); + vs_unlock (&maskList_sem); + free(temp); + return 0; + } + (void)pthread_mutex_lock (&temp->event[i].mutex); + /* Initialize the condition. This is used to signal waiting threads the event occured. */ + (void)pthread_cond_init (&temp->event[i].cond, NULL); + temp->event[i].count = 0; + (void)pthread_mutex_unlock (&temp->event[i].mutex); + } + + if(MaskList_Head != 0){ + MaskList_Head->prev = temp; + temp->next = MaskList_Head; + MaskList_Head = temp; + }else{ + MaskList_Head = temp; + } + + vs_unlock (&maskList_sem); + + return temp->id; +} + +Status_t vs_evt_MaskListInit(){ + if(maskListInited != 0){ + return VSTATUS_OK; + } + currentId = 0; + + if(vs_lock_init (&maskList_sem, VLOCK_FREE, VLOCK_THREAD) != VSTATUS_OK){ + return VSTATUS_BAD; + } + + maskListInited = 1; + return VSTATUS_OK; +} +#if 0 +void dumpMaskListInfo(){ + MaskList_t *temp; + int i; + + semTake(maskList_sem, WAIT_FOREVER); + + if(MaskList_Head != 0){ + for(temp = MaskList_Head; temp != NULL; temp = temp->next){ + //printf("Mask %x \n",temp->id); + for(i=0;isemId[i],1); + } + } + } + + semGive(maskList_sem); + +} + +void vs_evt_cleanMaskList(){ + int id = 0; + + while(1){ + semTake(maskList_sem, WAIT_FOREVER); + if(MaskList_Head != 0){ + id = MaskList_Head->id; + }else{ + id = -1; + } + semGive(maskList_sem); + + if(id > 0){ + deleteMask(id); + }else{ + break; + } + } +} + +#endif diff --git a/Esm/ib/src/ibaccess/vs_lck.c b/Esm/ib/src/ibaccess/vs_lck.c new file mode 100644 index 0000000..2f1c2ca --- /dev/null +++ b/Esm/ib/src/ibaccess/vs_lck.c @@ -0,0 +1,1059 @@ +/* BEGIN_ICS_COPYRIGHT5 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + * ** END_ICS_COPYRIGHT5 ****************************************/ + +/*********************************************************************** +* +* FILE NAME +* vs_lck.c +* +* DESCRIPTION +* This file contains the Linux User implementation of the vs_lock +* services. +* +* DATA STRUCTURES +* +* FUNCTIONS +* vs_lock_init +* vs_lock_delete +* vs_lock +* vs_unlock +* vs_spinlock +* vs_spinunlock +* +* DEPENDENCIES +* vs_g.h +* cs_g.h +* cs_log.h +* +* +* HISTORY +* +* NAME DATE REMARKS +* MGR 03/01/02 Initial creation of file. +* MGR 03/13/02 Added spinlock recursion support. +* MGR 03/21/02 Added fix for bug, where only one thread waiting +* on the thread lock was woken when lock was deleted. +* MGR 03/26/02 Corrected lint errors. +* MGR 04/04/02 PR1676. Rev G, CS API required changes. +* MGR 04/10/02 PR1716. Fixed spinlocks to block until freed by +* the owning thread. +* MGR 05/13/02 PR1812. Clean-up lint errors/warnings. +* +***********************************************************************/ +#ifdef BUILD_RHEL4 +#define _POSIX_C_SOURCE 200112L +#endif +#include +#include +#include +#include +#include +#include "ib_types.h" +#include "ib_status.h" +#include "vs_g.h" +#include "cs_g.h" +#include "cs_log.h" +#ifdef LOCAL_MOD_ID +#undef LOCAL_MOD_ID +#endif +#define LOCAL_MOD_ID VIEO_CS_MOD_ID +/* +#include +*/ +#include +#include "iba/public/ispinlock.h" + +/* +** Implementation private data structure +*/ +typedef struct +{ + uint8_t name[VS_NAME_MAX]; + union { + struct { // for THREAD + pthread_mutex_t mutex; + } lock; + struct { // for RWTHREAD + pthread_rwlock_t rwlock; + ATOMIC_UINT reader_count; + } rwlock; + struct { // for recursive SPIN + pthread_mutex_t mutex; + pthread_cond_t cond; + Threadname_t owner_thread; + uint32_t spin_count; + } spin; + } u; +} Implpriv_Lock_t; + + +/********************************************************************** +* +* FUNCTION +* vs_lock_init +* +* DESCRIPTION +* Initialize a thread or spin lock. +* +* INPUTS +* handle - A pointer to a lock control block. +* state - The initial state of the lock, VLOCK_LOCKED or VLOCK_FREE. +* type - type of lock to create, VLOCK_SPIN, VLOCK_THREAD, VLOCK_RWTHREAD +* +* OUTPUTS +* Status_t - On success VSTATUS_OK is returned, otherwise +* the cause of the error. +* +* +* HISTORY +* +* NAME DATE REMARKS +* MGR 03/01/02 Initial creation of function. +* MGR 03/13/02 Added spinlock recursion support. +* MGR 04/04/02 PR1676. Rev G, CS API required changes. +* +**********************************************************************/ +Status_t +vs_lock_init (Lock_t *handle, + unsigned int state, + unsigned int type) +{ + Status_t rc; + Implpriv_Lock_t *implpriv; + static const char function[] = "vs_lock_init"; + + IB_ENTER (function, + (unint)handle, + (uint32_t)state, + (uint32_t)type, + (uint32_t)0U); + + /* + ** Validate parameters + */ + if (handle == NULL) + { + IB_LOG_ERROR0 ("NULL handle pointer"); + IB_EXIT (function, VSTATUS_ILLPARM); + return VSTATUS_ILLPARM; + } + + if ((state != VLOCK_LOCKED) && (state != VLOCK_FREE)) + { + IB_LOG_ERROR ("invalid state:", state); + IB_EXIT (function, VSTATUS_ILLPARM); + return VSTATUS_ILLPARM; + } + + if ((type != VLOCK_SPIN) && (type != VLOCK_THREAD) + && (type != VLOCK_RWTHREAD)) + { + IB_LOG_ERROR ("invalid type:", type); + IB_EXIT (function, VSTATUS_ILLPARM); + return VSTATUS_ILLPARM; + } + + /* + ** Ensure opaque section of Lock_t is large enough to + ** contain the Implementation private data structure. + */ + if ((sizeof(Implpriv_Lock_t)) > (sizeof(handle->opaque))) + { + IB_LOG_ERROR("Implpriv_Lock_t too large:", (sizeof(Implpriv_Lock_t))); + IB_FATAL_ERROR_NODUMP("Implpriv_Lock_t too large"); + IB_EXIT (function, VSTATUS_ILLPARM); + return VSTATUS_ILLPARM; + } + + /* + ** Do initial setup + */ + // TBD - can we drop implpriv part for vs_lock and simply declare + // an OS specific Lock_t + memset ((void *)handle, 0, sizeof(Lock_t)); + implpriv = (Implpriv_Lock_t *)handle->opaque; + memcpy ((void *)implpriv->name, "VIEO_lock", 9); + + if (type == VLOCK_THREAD) + { + /* setup thread lock */ + if (pthread_mutex_init (&implpriv->u.lock.mutex, NULL) != 0) + { + IB_LOG_ERROR0 ("Unable to initialize lock"); + IB_EXIT (function, VSTATUS_ILLPARM); + return VSTATUS_ILLPARM; + } + + handle->type = VLOCK_THREAD; + handle->magic = VLOCK_THREADLOCK_MAGIC; + + if (state == VLOCK_LOCKED) + { + (void)pthread_mutex_lock (&implpriv->u.lock.mutex); + handle->status = VLOCK_LOCKED; + } + else + { + handle->status = VLOCK_FREE; + } + } + else if (type == VLOCK_RWTHREAD) + { + /* setup RW thread lock */ + if (pthread_rwlock_init (&implpriv->u.rwlock.rwlock, NULL) != 0) + { + IB_LOG_ERROR0 ("Unable to initialize lock"); + IB_EXIT (function, VSTATUS_ILLPARM); + return VSTATUS_ILLPARM; + } + handle->status = VLOCK_FREE; + AtomicWrite(&implpriv->u.rwlock.reader_count, 0); + + if (state == VLOCK_LOCKED) + { + pthread_rwlock_wrlock(&implpriv->u.rwlock.rwlock); + handle->status = VLOCK_LOCKED; + } + + handle->type = VLOCK_RWTHREAD; + handle->magic = VLOCK_RWTHREADLOCK_MAGIC; + } + else + { + /* setup spinlock */ + if (pthread_mutex_init (&implpriv->u.spin.mutex, NULL) != 0) + { + IB_LOG_ERROR0 ("Unable to initialize lock"); + IB_EXIT (function, VSTATUS_ILLPARM); + return VSTATUS_ILLPARM; + } + + (void)pthread_mutex_lock (&implpriv->u.spin.mutex); + (void)pthread_cond_init (&implpriv->u.spin.cond, NULL); + handle->status = VLOCK_FREE; + + /* initialize count and owner thread */ + implpriv->u.spin.spin_count = 0; + implpriv->u.spin.owner_thread = (uint64_t)0ULL; + + if (state == VLOCK_LOCKED) + { + /* set the lock to show in-use */ + implpriv->u.spin.spin_count++; + handle->status = VLOCK_LOCKED; + + /* set the thread name */ + rc = vs_thread_name (&implpriv->u.spin.owner_thread); + if (rc != VSTATUS_OK) + { + IB_LOG_ERROR0 ("Unable to set owner_thread"); + } + else + { + //IB_LOG_INFO ("owner_thread", (uint32_t)implpriv->owner_thread); + } + } + //IB_LOG_INFO ("implpriv->spin_count =", implpriv->spin_count); + + handle->type = VLOCK_SPIN; + handle->magic = VLOCK_SPINLOCK_MAGIC; + (void)pthread_mutex_unlock (&implpriv->u.spin.mutex); + } + + //IB_LOG_INFO ("handle->type =", handle->type); + //IB_LOG_INFO ("handle->status =", handle->status); + //IB_LOG_INFO ("handle->magic =", handle->magic); + + IB_EXIT (function, VSTATUS_OK); + return VSTATUS_OK; +} + +/********************************************************************** +* +* FUNCTION +* vs_lock_delete +* +* DESCRIPTION +* Delete a lock previously initialized with vs_lock_init(). +* +* INPUTS +* handle - A pointer to the lock control block filled in by +* the vs_lock_init() call. +* +* OUTPUTS +* Status_t - On success VSTATUS_OK is returned, otherwise +* the cause of the error. +* +* +* HISTORY +* +* NAME DATE REMARKS +* MGR 03/01/02 Initial creation of function. +* +**********************************************************************/ +Status_t +vs_lock_delete (Lock_t *handle) +{ + Implpriv_Lock_t *implpriv; + static const char function[] = "vs_lock_delete"; + + IB_ENTER (function, + (unint)handle, + (uint32_t)0U, + (uint32_t)0U, + (uint32_t)0U); + + /* + ** Validate handle + */ + if (handle == NULL) + { + IB_LOG_ERROR0 ("NULL handle pointer"); + IB_EXIT (function, VSTATUS_ILLPARM); + return VSTATUS_ILLPARM; + } + + if (handle->type != VLOCK_THREAD && handle->type != VLOCK_RWTHREAD && + handle->type != VLOCK_SPIN) + { + IB_LOG_INFINI_INFO ("Lock type is not thread lock or spinlock type:", handle->type); + IB_EXIT (function, VSTATUS_ILLPARM); + return VSTATUS_ILLPARM; + } + + if (handle->magic != VLOCK_THREADLOCK_MAGIC && + handle->magic != VLOCK_RWTHREADLOCK_MAGIC && + handle->magic != VLOCK_SPINLOCK_MAGIC) + { + IB_LOG_ERRORX ("Lock does not exist magic:", handle->magic); + IB_EXIT (function, VSTATUS_ILLPARM); + return VSTATUS_ILLPARM; + } + + /* + ** Delete/Invalidate the lock + */ + implpriv = (Implpriv_Lock_t *)handle->opaque; + if (handle->type == VLOCK_RWTHREAD) { + // getting the lock here is a bit of a hack to limit shutdown sequencing + // problems + vs_wrlock(handle); + handle->type = 0xFFFFFFFF; + handle->status = 0xFFFFFFFF; + handle->magic = 0; + // pthread_rwlock_destroy (&implpriv->u.rwlock.rwlock); // TBD paranoia + } else if (handle->type == VLOCK_THREAD) { + (void)pthread_mutex_lock (&implpriv->u.lock.mutex); + handle->type = 0xFFFFFFFF; + handle->status = 0xFFFFFFFF; + handle->magic = 0; + (void)pthread_mutex_unlock (&implpriv->u.lock.mutex); + /* pthread_mutex_destroy (&implpriv->u.lock.mutex); tmp */ + } else { // SPIN + (void)pthread_mutex_lock (&implpriv->u.spin.mutex); + handle->type = 0xFFFFFFFF; + handle->status = 0xFFFFFFFF; + handle->magic = 0; + + /* + ** Awaken all sleeping threads + */ + //IB_LOG_INFO0 ("waking threads waiting on lock"); + (void)pthread_cond_broadcast (&implpriv->u.spin.cond); + + (void)pthread_mutex_unlock (&implpriv->u.spin.mutex); + /* pthread_mutex_destroy (&implpriv->u.spin.mutex); tmp */ + } + + IB_EXIT (function, VSTATUS_OK); + return VSTATUS_OK; +} + +/********************************************************************** +* +* FUNCTION +* vs_lock +* +* DESCRIPTION +* Acquire a thread lock. +* +* INPUTS +* handle - A pointer to the thread lock control object filled in +* by vs_lock_init(). +* +* OUTPUTS +* Status_t - On success VSTATUS_OK is returned, otherwise +* the cause of the error. +* +* NOTES +* * handle->status is only maintained for debug asserts, as we +* rely directly on pthreads for locking state. +* * vs_lock_delete can not call pthread_mutex_destroy, as the mutex +* is intended to remain valid in order to handle racing locks and +* deletes (themselves a sign that we need to cleanup shutdown +* logic, as this case should be undefined). +* +* HISTORY +* +* NAME DATE REMARKS +* MGR 03/01/02 Initial creation of function. +* MGR 03/21/02 Added fix for bug, where only one thread waiting +* on the thread lock was woken when lock was deleted. +* +**********************************************************************/ +Status_t +vs_lock (Lock_t *handle) +{ + Implpriv_Lock_t *implpriv; + static const char function[] = "vs_lock"; + + IB_ENTER (function, + (unint)handle, + (uint32_t)0U, + (uint32_t)0U, + (uint32_t)0U); + + /* + ** Validate handle + */ + if (handle == NULL) + { + IB_LOG_ERROR0 ("NULL handle pointer"); + IB_EXIT (function, VSTATUS_ILLPARM); + return VSTATUS_ILLPARM; + } + + if (handle->type == VLOCK_RWTHREAD) + return vs_wrlock(handle); // safety valve in case wrong call used + + if (handle->type != VLOCK_THREAD) + { + IB_LOG_ERROR ("Lock type is not thread lock type:", handle->type); + IB_EXIT (function, VSTATUS_ILLPARM); + return VSTATUS_ILLPARM; + } + + if (handle->magic != VLOCK_THREADLOCK_MAGIC) + { + IB_LOG_ERRORX("Lock does not exist magic:", handle->magic); + IB_EXIT(function, VSTATUS_ILLPARM); + return VSTATUS_ILLPARM; + } + + /* + ** Lock the lock + */ + implpriv = (Implpriv_Lock_t *)handle->opaque; + (void)pthread_mutex_lock (&implpriv->u.lock.mutex); + + if (handle->magic != VLOCK_THREADLOCK_MAGIC) + { + (void)pthread_mutex_unlock(&implpriv->u.lock.mutex); + IB_LOG_ERRORX("Lock deleted during acquisition attempt magic:", handle->magic); + IB_EXIT(function, VSTATUS_ILLPARM); + return VSTATUS_ILLPARM; + } + + DEBUG_ASSERT(handle->status == VLOCK_FREE); + handle->status = VLOCK_LOCKED; + + IB_EXIT (function, VSTATUS_OK); + return VSTATUS_OK; +} + +/********************************************************************** +* +* FUNCTION +* vs_unlock +* +* DESCRIPTION +* Release the thread lock associated with the handle. +* +* INPUTS +* handle - A pointer to a thread lock control object filled in +* by vs_lock_init(). +* +* OUTPUTS +* Status_t - On success VSTATUS_OK is returned, otherwise +* the cause of the error. +* +* +* HISTORY +* +* NAME DATE REMARKS +* MGR 03/01/02 Initial creation of function. +* +**********************************************************************/ +Status_t +vs_unlock (Lock_t *handle) +{ + Implpriv_Lock_t *implpriv; + static const char function[] = "vs_unlock"; + + IB_ENTER (function, + (unint)handle, + (uint32_t)0U, + (uint32_t)0U, + (uint32_t)0U); + + /* + ** Validate handle + */ + if (handle == NULL) + { + IB_LOG_ERROR0 ("NULL handle pointer"); + IB_EXIT (function, VSTATUS_ILLPARM); + return VSTATUS_ILLPARM; + } + + if (handle->type == VLOCK_RWTHREAD) + return vs_rwunlock(handle); // safety valve in case wrong call used + + if (handle->type != VLOCK_THREAD) + { + IB_LOG_ERROR ("Lock type is not thread lock type:", handle->type); + IB_EXIT (function, VSTATUS_ILLPARM); + return VSTATUS_ILLPARM; + } + + if (handle->magic != VLOCK_THREADLOCK_MAGIC) + { + IB_LOG_ERRORX ("Lock does not exist magic:", handle->magic); + IB_EXIT (function, VSTATUS_ILLPARM); + return VSTATUS_ILLPARM; + } + + /* + ** Unlock the lock + */ + implpriv = (Implpriv_Lock_t *)handle->opaque; + DEBUG_ASSERT(handle->status == VLOCK_LOCKED); + handle->status = VLOCK_FREE; + (void)pthread_mutex_unlock (&implpriv->u.lock.mutex); + + IB_EXIT (function, VSTATUS_OK); + return VSTATUS_OK; +} + +/********************************************************************** +* +* FUNCTION +* vs_wrlock +* +* DESCRIPTION +* Acquire a rw thread lock. +* +* INPUTS +* handle - A pointer to the rw thread lock control object filled in +* by vs_lock_init(). +* +* OUTPUTS +* Status_t - On success VSTATUS_OK is returned, otherwise +* the cause of the error. +* +* HISTORY +* +* NAME DATE REMARKS +* +**********************************************************************/ +Status_t +vs_wrlock (Lock_t *handle) +{ + Implpriv_Lock_t *implpriv; + static const char function[] = "vs_wrlock"; + + IB_ENTER (function, + (unint)handle, + (uint32_t)0U, + (uint32_t)0U, + (uint32_t)0U); + + /* + ** Validate handle + */ + if (handle == NULL) + { + IB_LOG_ERROR0 ("NULL handle pointer"); + IB_EXIT (function, VSTATUS_ILLPARM); + return VSTATUS_ILLPARM; + } + + if (handle->type != VLOCK_RWTHREAD) + { + IB_LOG_ERROR ("Lock type is not rw thread lock type:", handle->type); + IB_EXIT (function, VSTATUS_ILLPARM); + return VSTATUS_ILLPARM; + } + + if (handle->magic != VLOCK_RWTHREADLOCK_MAGIC) + { + IB_LOG_ERRORX ("Lock does not exist magic:", handle->magic); + IB_EXIT (function, VSTATUS_ILLPARM); + return VSTATUS_ILLPARM; + } + + /* + ** Lock the lock + */ + implpriv = (Implpriv_Lock_t *)handle->opaque; + pthread_rwlock_wrlock(&implpriv->u.rwlock.rwlock); + handle->status = VLOCK_LOCKED; + DEBUG_ASSERT(0 == AtomicRead(&implpriv->u.rwlock.reader_count)); + + IB_EXIT (function, VSTATUS_OK); + return VSTATUS_OK; +} + +/********************************************************************** +* +* FUNCTION +* vs_rdlock +* +* DESCRIPTION +* Acquire a rw thread lock. +* +* INPUTS +* handle - A pointer to the rw thread lock control object filled in +* by vs_lock_init(). +* +* OUTPUTS +* Status_t - On success VSTATUS_OK is returned, otherwise +* the cause of the error. +* +* HISTORY +* +* NAME DATE REMARKS +* +**********************************************************************/ +Status_t +vs_rdlock (Lock_t *handle) +{ + Implpriv_Lock_t *implpriv; + static const char function[] = "vs_rdlock"; + + IB_ENTER (function, + (unint)handle, + (uint32_t)0U, + (uint32_t)0U, + (uint32_t)0U); + + /* + ** Validate handle + */ + if (handle == NULL) + { + IB_LOG_ERROR0 ("NULL handle pointer"); + IB_EXIT (function, VSTATUS_ILLPARM); + return VSTATUS_ILLPARM; + } + + if (handle->type != VLOCK_RWTHREAD) + { + IB_LOG_ERROR ("Lock type is not rw thread lock type:", handle->type); + IB_EXIT (function, VSTATUS_ILLPARM); + return VSTATUS_ILLPARM; + } + + if (handle->magic != VLOCK_RWTHREADLOCK_MAGIC) + { + IB_LOG_ERRORX ("Lock does not exist magic:", handle->magic); + IB_EXIT (function, VSTATUS_ILLPARM); + return VSTATUS_ILLPARM; + } + + /* + ** Lock the lock + */ + implpriv = (Implpriv_Lock_t *)handle->opaque; + pthread_rwlock_rdlock(&implpriv->u.rwlock.rwlock); + AtomicIncrementVoid(&implpriv->u.rwlock.reader_count); + DEBUG_ASSERT(handle->status != VLOCK_LOCKED); + + IB_EXIT (function, VSTATUS_OK); + return VSTATUS_OK; +} + +/********************************************************************** +* +* FUNCTION +* vs_rwunlock +* +* DESCRIPTION +* Release the rw thread lock associated with the handle. +* +* INPUTS +* handle - A pointer to a rw thread lock control object filled in +* by vs_lock_init(). +* +* OUTPUTS +* Status_t - On success VSTATUS_OK is returned, otherwise +* the cause of the error. +* +* +* HISTORY +* +* NAME DATE REMARKS +* MGR 03/01/02 Initial creation of function. +* +**********************************************************************/ +Status_t +vs_rwunlock (Lock_t *handle) +{ + Implpriv_Lock_t *implpriv; + static const char function[] = "vs_rwunlock"; + + IB_ENTER (function, + (unint)handle, + (uint32_t)0U, + (uint32_t)0U, + (uint32_t)0U); + + /* + ** Validate handle + */ + if (handle == NULL) + { + IB_LOG_ERROR0 ("NULL handle pointer"); + IB_EXIT (function, VSTATUS_ILLPARM); + return VSTATUS_ILLPARM; + } + + if (handle->type != VLOCK_RWTHREAD) + { + IB_LOG_ERROR ("Lock type is not rw thread lock type:", handle->type); + IB_EXIT (function, VSTATUS_ILLPARM); + return VSTATUS_ILLPARM; + } + + if (handle->magic != VLOCK_RWTHREADLOCK_MAGIC) + { + IB_LOG_ERRORX ("Lock does not exist magic:", handle->magic); + IB_EXIT (function, VSTATUS_ILLPARM); + return VSTATUS_ILLPARM; + } + + /* + ** Unlock the lock + */ + implpriv = (Implpriv_Lock_t *)handle->opaque; + if (handle->status == VLOCK_FREE) { + // we must have a rdlock + DEBUG_ASSERT(0 != AtomicRead(&implpriv->u.rwlock.reader_count)); + AtomicDecrementVoid(&implpriv->u.rwlock.reader_count); + (void)pthread_rwlock_unlock (&implpriv->u.rwlock.rwlock); + } else { + // we must have a wrlock + DEBUG_ASSERT(0 == AtomicRead(&implpriv->u.rwlock.reader_count)); + handle->status = VLOCK_FREE; + (void)pthread_rwlock_unlock (&implpriv->u.rwlock.rwlock); + } + + //IB_LOG_INFO ("handle->status =", handle->status); + + IB_EXIT (function, VSTATUS_OK); + return VSTATUS_OK; +} + +// TBD - this is nice, supports recursive locks +// but its not implemented for vxWorks and is not used +// perhaps delete. +// Also thread_mutex allows a PTHREAD_MUTEX_RECURSIVE option +/********************************************************************** +* +* FUNCTION +* vs_spinlock +* +* DESCRIPTION +* Acquire a spin lock. +* +* INPUTS +* handle - A pointer to the spin lock control object filled in +* by vs_lock_init(). +* +* OUTPUTS +* Status_t - On success VSTATUS_OK is returned, otherwise +* the cause of the error. +* +* +* HISTORY +* +* NAME DATE REMARKS +* MGR 03/01/02 Initial creation of function. +* MGR 03/13/02 Added recursion support. +* MGR 04/10/02 PR1716. Block until spinlock is freed by owner, +* either via vs_spinunlock or vs_lock_delete. +* +**********************************************************************/ +Status_t +vs_spinlock (Lock_t *handle) +{ + uint32_t wake_me_up = 0; + Status_t rc; + Implpriv_Lock_t *implpriv; + Threadname_t current_thread_name; + static const char function[] = "vs_spinlock"; + + IB_ENTER (function, + (unint)handle, + (uint32_t)0U, + (uint32_t)0U, + (uint32_t)0U); + + /* + ** Validate handle + */ + if (handle == NULL) + { + IB_LOG_ERROR0 ("NULL handle pointer"); + IB_EXIT (function, VSTATUS_ILLPARM); + return VSTATUS_ILLPARM; + } + + if (handle->type != VLOCK_SPIN) + { + IB_LOG_ERROR ("Lock type is not spinlock type:", handle->type); + IB_EXIT (function, VSTATUS_ILLPARM); + return VSTATUS_ILLPARM; + } + + if (handle->magic != VLOCK_SPINLOCK_MAGIC) + { + IB_LOG_ERRORX ("Lock does not exist magic:", handle->magic); + IB_EXIT (function, VSTATUS_ILLPARM); + return VSTATUS_ILLPARM; + } + + /* + ** Lock the lock + */ + implpriv = (Implpriv_Lock_t *)handle->opaque; + (void)pthread_mutex_lock (&implpriv->u.spin.mutex); + + if (handle->status == VLOCK_LOCKED) + { + //IB_LOG_INFO ("lock is currently locked", handle->status); + + /* + ** Get current thread name + */ + rc = vs_thread_name (¤t_thread_name); + if (rc != VSTATUS_OK) + { + IB_LOG_ERRORRC("vs_thread_name error rc:", rc); + (void)pthread_mutex_unlock (&implpriv->u.spin.mutex); + IB_EXIT (function, VSTATUS_NXIO); + return VSTATUS_NXIO; + } + + //IB_LOG_INFO ("thread owning lock", (uint32_t)implpriv->u.spin.owner_thread); + //IB_LOG_INFO ("current thread", (uint32_t)current_thread_name); + + if (implpriv->u.spin.owner_thread == current_thread_name) + { + /* we are the owners of the lock, update counter */ + implpriv->u.spin.spin_count++; + //IB_LOG_INFO ("current thread owns lock", (uint32_t)current_thread_name); + //IB_LOG_INFO ("implpriv->spin_count =", implpriv->u.spin.spin_count); + //IB_LOG_INFO ("handle->status", handle->status); + + (void)pthread_mutex_unlock (&implpriv->u.spin.mutex); + IB_EXIT (function, VSTATUS_OK); + return VSTATUS_OK; + } + else + { + /* wait until we are woken, either by vs_lock_delete or vs_spinunlock */ + while (handle->status == VLOCK_LOCKED) + { + //IB_LOG_INFO0 ("lock is locked and we are not owner; going to sleep"); + wake_me_up = (uint32_t)1U; + (void)pthread_cond_wait (&implpriv->u.spin.cond, &implpriv->u.spin.mutex); + } + } + } + + if (wake_me_up == (uint32_t)1U) + { + //IB_LOG_INFO0 ("thread has woken up"); + } + + if (handle->magic == VLOCK_SPINLOCK_MAGIC) + { + //IB_LOG_INFO ("lock has been freed, locking", handle->status); + + handle->status = VLOCK_LOCKED; + implpriv->u.spin.spin_count = 1; + //IB_LOG_INFO ("implpriv->spin_count =", implpriv->u.spin.spin_count); + + /* set the thread name */ + rc = vs_thread_name (&implpriv->u.spin.owner_thread); + if (rc != VSTATUS_OK) + { + IB_LOG_ERROR0 ("Unable to set owner_thread"); + } + else + { + //IB_LOG_INFO ("setting owner_thread", (uint32_t)implpriv->u.spin.owner_thread); + } + } + else + { + (void)pthread_mutex_unlock (&implpriv->u.spin.mutex); + IB_LOG_ERROR0 ("Lock no longer exists"); + IB_EXIT (function, VSTATUS_NXIO); + return VSTATUS_NXIO; + } + + //IB_LOG_INFO ("handle->status", handle->status); + (void)pthread_mutex_unlock (&implpriv->u.spin.mutex); + + IB_EXIT (function, VSTATUS_OK); + return VSTATUS_OK; +} + +/********************************************************************** +* +* FUNCTION +* vs_spinunlock +* +* DESCRIPTION +* Release the spin lock associated with the handle. +* +* INPUTS +* handle - A pointer to the spin lock control object filled in +* by vs_lock_init(). +* +* OUTPUTS +* Status_t - On success VSTATUS_OK is returned, otherwise +* the cause of the error. +* +* +* HISTORY +* +* NAME DATE REMARKS +* MGR 03/01/02 Initial creation of function. +* MGR 03/13/02 Added recursion support. +* MGR 04/10/02 PR1716. Wake blocking thread after unwinding. +* +**********************************************************************/ +Status_t +vs_spinunlock (Lock_t *handle) +{ + Status_t rc; + Implpriv_Lock_t *implpriv; + Threadname_t current_thread_name; + static const char function[] = "vs_spinunlock"; + + IB_ENTER (function, + (unint)handle, + (uint32_t)0U, + (uint32_t)0U, + (uint32_t)0U); + + /* + ** Validate handle + */ + if (handle == NULL) + { + IB_LOG_ERROR0 ("NULL handle pointer"); + IB_EXIT (function, VSTATUS_ILLPARM); + return VSTATUS_ILLPARM; + } + + if (handle->type != VLOCK_SPIN) + { + IB_LOG_ERROR ("Lock type is not spinlock type:", handle->type); + IB_EXIT (function, VSTATUS_ILLPARM); + return VSTATUS_ILLPARM; + } + + if (handle->magic != VLOCK_SPINLOCK_MAGIC) + { + IB_LOG_ERRORX ("Lock does not exist magic:", handle->magic); + IB_EXIT (function, VSTATUS_ILLPARM); + return VSTATUS_ILLPARM; + } + + implpriv = (Implpriv_Lock_t *)handle->opaque; + (void)pthread_mutex_lock (&implpriv->u.spin.mutex); + + if (implpriv->u.spin.spin_count < 1) + { + /* lock is already free */ + (void)pthread_mutex_unlock (&implpriv->u.spin.mutex); + IB_LOG_ERROR0 ("Attempting to unlock already free lock"); + IB_EXIT (function, VSTATUS_NXIO); + return VSTATUS_NXIO; + } + + /* we can only unlock if we are the owner */ + //IB_LOG_INFO0 ("lock is locked"); + rc = vs_thread_name (¤t_thread_name); + if (rc != VSTATUS_OK) + { + (void)pthread_mutex_unlock (&implpriv->u.spin.mutex); + IB_LOG_ERRORRC("vs_thread_name error rc:", rc); + IB_EXIT (function, VSTATUS_NXIO); + return VSTATUS_NXIO; + } + + //IB_LOG_INFO ("thread owning lock", (uint32_t)implpriv->u.spin.owner_thread); + //IB_LOG_INFO ("current thread", (uint32_t)current_thread_name); + + if (implpriv->u.spin.owner_thread != current_thread_name) + { + (void)pthread_mutex_unlock (&implpriv->u.spin.mutex); + IB_LOG_ERRORX ("current thread does not own lock. owner:", + (uint32_t)implpriv->u.spin.owner_thread); + IB_EXIT (function, VSTATUS_NXIO); + return VSTATUS_NXIO; + } + + /* decrement counter */ + //IB_LOG_INFO ("current thread owns lock", (uint32_t)current_thread_name); + implpriv->u.spin.spin_count--; + //IB_LOG_INFO ("implpriv->spin_count =", implpriv->u.spin.spin_count); + + if (!implpriv->u.spin.spin_count) + { + /* lock has completely un-nested */ + //IB_LOG_INFO0 ("lock has completed un-nested"); + handle->status = VLOCK_FREE; + implpriv->u.spin.owner_thread = (uint64_t)0ULL; + + /* awaken a sleeping thread */ + (void)pthread_cond_signal (&implpriv->u.spin.cond); + } + + //IB_LOG_INFO ("handle->status =", handle->status); + (void)pthread_mutex_unlock (&implpriv->u.spin.mutex); + + IB_EXIT (function, VSTATUS_OK); + return VSTATUS_OK; +} diff --git a/Esm/ib/src/ibaccess/vs_pool.c b/Esm/ib/src/ibaccess/vs_pool.c new file mode 100644 index 0000000..aa9924c --- /dev/null +++ b/Esm/ib/src/ibaccess/vs_pool.c @@ -0,0 +1,430 @@ +/* BEGIN_ICS_COPYRIGHT5 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + * ** END_ICS_COPYRIGHT5 ****************************************/ + +//======================================================================= +// / +// FILE NAME / +// pool.c / +// / +// DESCRIPTION / +// This is the pool CS routines. / +// / +// DATA STRUCTURES / +// None / +// / +// FUNCTIONS / +// vs_pool_create initialize the pool subsystem / +// vs_pool_delete delete a pool subsystem / +// vs_pool_alloc allocate a buffer / +// vs_pool_free free a buffer / +// / +// DEPENDENCIES / +// ib_status.h / +// cs_g.h / +// / +// / +// HISTORY / +// / +// NAME DATE REMARKS / +// jsy 02/06/01 Initial creation of file. / +// jsy 03/14/01 Added additional checks. / +// dkj 02/07/02 PR 468. Added vs_pool_page_size() / +// dkj 04/01/02 PR 1676. Updated vs_pool_page_size to OS API 2.0g / +//======================================================================= + +#include +#include +#include +#include +#include + +// PAGE_SIZE and asm/page.h no longer supported on Linux +#ifndef PAGE_SIZE +#include +#define PAGE_SIZE getpagesize() +#endif + +#include "ib_status.h" +#include "cs_g.h" +#include "cs_log.h" + +#ifdef LOCAL_MOD_ID +#undef LOCAL_MOD_ID +#endif +#define LOCAL_MOD_ID VIEO_CS_MOD_ID + +#ifdef __GNUC__ +#define function __FUNCTION__ +#else +#define function "vs_implpool function" +#endif + +/* + * PBuffer_t linked list tricks Valgrind into thinking memory + * is still reachable + * */ +#ifndef USE_PBUFFER_LIST +#define USE_PBUFFER_LIST 0 +#endif + +/* + * buffer pool structure +*/ +typedef struct _PBuffer { +#if USE_PBUFFER_LIST + struct _PBuffer *next, *prev; +#endif /* USE_PBUFFER_LIST */ + uint8_t *addr1; // address of the user buffer + uint16_t sentinel; // to track double delete + uint32_t size; +} PBuffer_t; + +typedef struct +{ + uint64_t numBytesAlloc; // amount allocated from pool +#if USE_PBUFFER_LIST + PBuffer_t *buffers; +#endif /* USE_PBUFFER_LIST */ +} Implpriv_Pool_t; + + +/* + * These defines control checks made during allocations and frees + */ + +/* Add an extra eight bytes (sizeof uint64_t) to allocation size - + * This was the way the original allocation code worked. + */ +#ifndef PAD_ALLOCATIONS +#define PAD_ALLOCATIONS 1 +#endif + +/* Aborts if an overwrite of the buffer is detected when it is freed */ +#ifndef ABORT_ON_OVERWRITE +#define ABORT_ON_OVERWRITE 0 +#endif + +/* Aborts if a buffer is freed for a second time */ +#ifndef ABORT_ON_DOUBLE_FREE +#define ABORT_ON_DOUBLE_FREE 1 +#endif + +/* Zeros out memory on both allocation and free */ +#ifndef ZERO_FREED_MEM +#define ZERO_FREED_MEM 1 +#endif + +#if (ABORT_ON_OVERWRITE) +static const uint32_t sentinel0 = 0xB00A110C; +static const uint32_t sentinel1 = 0xE00A110C; +#endif + +Status_t +vs_implpool_create(Pool_t *poolp, uint32_t options, uint8_t *name, void *address, uint32_t size) { + + IB_ENTER (function, poolp, options, address, size); + + /* Check to be sure that we have a valid Pool_t */ + + if (poolp == NULL) { + IB_EXIT (function, VSTATUS_ILLPARM); + return(VSTATUS_ILLPARM); + } + + /* + ** this is a run-time check to ensure that the opaque section of Pool_t + ** is large enough to contain the Implementation private data structure. + ** If this test fails, adjust the OPAQUE_POOL_ELEMENTS define in + ** vs_g.h and rebuild. + */ + if(sizeof (Implpriv_Pool_t) > sizeof (poolp->opaque)) + { + IB_LOG_ERROR ("Implpriv_Pool_t too big:", sizeof (Implpriv_Pool_t)); + IB_EXIT (function, VSTATUS_ILLPARM); + return VSTATUS_ILLPARM; + } + + /* Initialize the pool */ + // caller has already zeroed *poolp + strncpy((char*)poolp->name, (char *)name, VS_NAME_MAX); + poolp->options = options; +#if USE_PBUFFER_LIST + ((Implpriv_Pool_t*)poolp->opaque)->buffers = NULL; +#endif /* USE_PBUFFER_LIST */ + + IB_EXIT (function, VSTATUS_OK); + return(VSTATUS_OK); +} + + +Status_t +vs_implpool_delete(Pool_t *poolp) { + IB_ENTER (function, poolp, 0, 0, 0); + + /* Check to be sure that we have a valid Pool_t */ + if (poolp == NULL) { + IB_EXIT (function, VSTATUS_ILLPARM); + return(VSTATUS_ILLPARM); + } + +#if USE_PBUFFER_LIST + PBuffer_t *bufferp; + Implpriv_Pool_t *impl = (Implpriv_Pool_t*) poolp->opaque; + + /* Delete all of the buffers remaining in the pool */ + while ((bufferp = impl->buffers) != NULL) { + impl->buffers = bufferp->next; + +#if (ZERO_FREED_MEM) + memset(bufferp, 0, bufferp->size); +#endif + + free((void *)bufferp); + } +#endif + + IB_EXIT (function, VSTATUS_OK); + return(VSTATUS_OK); +} + +#define AtomicAdd64(p,a) __sync_add_and_fetch((p),(a)) +#define AtomicSubtract64(p,a) __sync_sub_and_fetch((p),(a)) + + +Status_t +vs_implpool_alloc(Pool_t *poolp, uint32_t reqSize, void **address) { + uint32_t bytes; + PBuffer_t *bufferp; + + IB_ENTER (function, poolp, reqSize, address, 0); + + /* Check to be sure that we have a valid Pool_t */ + if (poolp == NULL) { + IB_EXIT (function, VSTATUS_ILLPARM); + return(VSTATUS_ILLPARM); + } +// TBD - don't need Buffer_t header for normal case below, could save space + + DEBUG_ASSERT(reqSize < UINT32_MAX); + + /* See if we can get a buffer */ +#if (PAD_ALLOCATIONS) + /* This is the original calculation for number of bytes to allocate... + * Note the extra padding. This is sloppy. Also note that if both + * PAD_ALLOCATIONS and ABORT_ON_OVERWRITE are defined, that the sentinels + * are added to the the buffer _before_ the padding. + */ + DEBUG_ASSERT((UINT32_MAX - reqSize) >= (sizeof(PBuffer_t) + sizeof(uint64_t))); + bytes = sizeof(PBuffer_t) + reqSize + sizeof(uint64_t); +#else + DEBUG_ASSERT((UINT32_MAX - reqSize) >= sizeof(PBuffer_t)); + bytes = sizeof(PBuffer_t) + reqSize; +#endif + +#if (ABORT_ON_OVERWRITE) + bytes += (3 * sizeof(uint32_t)); +#endif + + bufferp = (PBuffer_t *) malloc(bytes); + if (bufferp == NULL) { + IB_EXIT (function, VSTATUS_NOMEM); + return(VSTATUS_NOMEM); + } + +// TBD vxworks doesn't do memset + memset((void *)bufferp, 0, bytes); + + bufferp->sentinel = DELETE_MARKER; + bufferp->addr1 = (uint8_t *)(bufferp+1); // JSY - fix + bufferp->size = bytes; + +#if (ABORT_ON_OVERWRITE) + /* We copy a constant value to the beginning of the buffer + * and a constant value to the end of the buffer, followed by the size + * of the buffer again. This allows us to make sure that we haven't + * overwritten the beginning or end of the allocated region when + * its freed. + * + * We memcpy here rather than cast and assign b/c these values may + * not necessarily be aligned, and that may cause problems on some + * architectures. + */ + memcpy(bufferp->addr1, &sentinel0, sizeof(uint32_t)); + + /* adjust addr1 to account for the sentinel */ + bufferp->addr1 += sizeof(uint32_t); + + memcpy(bufferp->addr1 + reqSize, &sentinel1, sizeof(uint32_t)); + memcpy(bufferp->addr1 + reqSize + sizeof(uint32_t), + &bytes, sizeof(uint32_t)); +#endif + +#if USE_PBUFFER_LIST + Implpriv_Pool_t *impl = (Implpriv_Pool_t*)poolp->opaque; + bufferp->next = impl->buffers; + bufferp->prev = NULL; + if (impl->buffers != NULL) + impl->buffers->prev = bufferp; + impl->buffers = bufferp; +#endif /* USE_PBUFFER_LIST */ + *address = bufferp->addr1; + +#if USE_POOL_LOCK + ((Implpriv_Pool_t *)poolp->opaque)->numBytesAlloc += bufferp->size; +#else + uint64_t *ba = &((Implpriv_Pool_t*)poolp->opaque)->numBytesAlloc; + AtomicAdd64(ba, bufferp->size); +#endif /* USE_POOL_LOCK */ + + IB_EXIT (function, VSTATUS_OK); + return(VSTATUS_OK); +} + +static void freeBuffer(PBuffer_t * bufferp) +{ +#if (ABORT_ON_OVERWRITE) + uint32_t value = 0; +#endif + + IB_ENTER(function, bufferp, 0, 0, 0); + +#if (ABORT_ON_OVERWRITE) + /* Check whether we overwrote the beginning or the end of the + * allocated region + */ + memcpy(&value, bufferp->addr1 - sizeof(uint32_t), sizeof(uint32_t)); + assert(value == sentinel0); + +#if (PAD_ALLOCATIONS) + bufferp->size -= sizeof(uint64_t); +#endif /* PAD_ALLOCATIONS */ + + memcpy(&value, ((uint8_t *) bufferp) + bufferp->size + - (2 * sizeof(uint32_t)), sizeof(uint32_t)); + assert(value == sentinel1); + + memcpy(&value, ((uint8_t *) bufferp) + bufferp->size - sizeof(uint32_t), + sizeof(uint32_t)); + +#if (PAD_ALLOCATIONS) + bufferp->size += sizeof(uint64_t); +#endif /* PAD_ALLOCATIONS */ + + assert(value == bufferp->size); +#endif /* ABORT_ON_OVERWRITE */ + +#if (ZERO_FREED_MEM) + memset(bufferp, 0, bufferp->size); +#endif + free(bufferp); + + IB_EXIT(function, VSTATUS_OK); +} + +Status_t +vs_implpool_free(Pool_t *poolp, void *address) { + PBuffer_t *bufferp; + + IB_ENTER (function, poolp, address, 0,0); + + /* Check to be sure that we have a valid Pool_t */ + if (poolp == NULL) { + IB_EXIT (function, VSTATUS_ILLPARM); + return(VSTATUS_ILLPARM); + } + + /* Check to be sure that the address is a real one */ + if (address == NULL) { + IB_EXIT (function, VSTATUS_ILLPARM); + return(VSTATUS_ILLPARM); + } + +# if (ABORT_ON_OVERWRITE) + address -= sizeof(uint32_t); +# endif + + // Pointer to the PBuffer_t should be at (address - sizeof(PBuffer_T)) + bufferp = (((PBuffer_t*) address) - 1); + + if (bufferp->sentinel != DELETE_MARKER) { +#if (ABORT_ON_DOUBLE_FREE) + /* Couldn't find the required buffer */ + IB_FATAL_ERROR("vs_implpool_free: could not find buffer to free"); +#endif + IB_EXIT (function, VSTATUS_ILLPARM); + return(VSTATUS_ILLPARM); + } + + bufferp->sentinel = 0; + +#if USE_PBUFFER_LIST + Implpriv_Pool_t *impl = (Implpriv_Pool_t*)poolp->opaque; + if (bufferp->prev) { + bufferp->prev->next = bufferp->next; + } else { + impl->buffers = bufferp->next; // at head of list + } + if (bufferp->next) { + bufferp->next->prev = bufferp->prev; + } +#endif /* USE_PBUFFER_LIST */ + +#if USE_POOL_LOCK + ((Implpriv_Pool_t *)poolp->opaque)->numBytesAlloc -= bufferp->size; +#else + uint64_t *ba = &((Implpriv_Pool_t*)poolp->opaque)->numBytesAlloc; + AtomicSubtract64(ba, bufferp->size); +#endif + + freeBuffer(bufferp); + IB_EXIT (function, VSTATUS_OK); + return VSTATUS_OK; +} + +/********************************************************************** +* +* FUNCTION +* vs_implpool_size +* +* OUTPUTS +* number of bytes allocated from pool. +**********************************************************************/ +Status_t +vs_implpool_size(Pool_t *poolp, uint64_t *numBytesAlloc) +{ + // caller already validated poolp and size + *numBytesAlloc = ((Implpriv_Pool_t *)poolp->opaque)->numBytesAlloc; + return VSTATUS_OK; +} + +size_t vs_pool_page_size (void) { + IB_ENTER (function, (uint32_t) 0U, (uint32_t) 0U, (uint32_t) 0U, (uint32_t) 0U); + IB_EXIT (function, (size_t) PAGE_SIZE); + return (size_t) PAGE_SIZE; +} diff --git a/Esm/ib/src/ibaccess/vs_thr.c b/Esm/ib/src/ibaccess/vs_thr.c new file mode 100644 index 0000000..364b021 --- /dev/null +++ b/Esm/ib/src/ibaccess/vs_thr.c @@ -0,0 +1,733 @@ +/* BEGIN_ICS_COPYRIGHT5 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + * ** END_ICS_COPYRIGHT5 ****************************************/ + +/*********************************************************************** +* +* FILE NAME +* vs_thr.c +* +* DESCRIPTION +* This file contains the Linux user space implementation of the +* vs_thread services. +* +* DATA STRUCTURES +* +* FUNCTIONS +* +* DEPENDENCIES +* vs_g.h +* +* +* HISTORY +* +* NAME DATE REMARKS +* SFW 03/08/02 Initial creation of file. +* SFW 03/10/02 Initial functions all passing testcases. +* MGR 04/19/02 Changed pthread_kill call to pthread_cancel. +***********************************************************************/ +#include +#include +#include +#include +#include +#include +#include +#include +#if 0 +#include +#endif + +#include "ib_types.h" +#include "ib_status.h" +#include "vs_g.h" +#include "cs_g.h" +#include "cs_log.h" + +#ifdef LOCAL_MOD_ID +#undef LOCAL_MOD_ID +#endif +#define LOCAL_MOD_ID VIEO_CS_MOD_ID +/* +#include +*/ +#include + +/* +** Implementation private data structure for Linux Kernel Thread +*/ +#define IMPLPRIV_THREAD_MAGIC ((uint32_t) 0x217B3135U) + +typedef struct { + uint32_t magic; + void (*start_function)(uint32_t, uint8_t **); + pthread_t thread; + Threadname_t create_pid; + Threadname_t create_ppid; + uint32_t argc; + uint8_t argv_copied; + uint8_t **argv; + uint32_t dead; + pthread_cond_t dead_cond; + pthread_mutex_t dead_mutex; + pthread_attr_t attr; + char name[64]; +} Implpriv_Thread_t; + +/* +** Local prototypes +*/ +int +impl_vs_thread_start (void *); + +//static __thread char *thread_name; +// +int name_key_init = 0; +pthread_key_t name_key; + +void vs_thread_key_init(void) +{ + (void)pthread_key_create(&name_key, NULL); + (void)pthread_setspecific(name_key, "main"); + name_key_init = 1; +} + + +/********************************************************************** +* +* FUNCTION +* impl_vs_thread_create +* +* DESCRIPTION +* Linux specific implementation of the vs_thread_create() function. +* The supplied stack parameters are not used in the Linux user space +* implementation. +* +* This routine is called by the vs_thread_create() API. +* +* INPUTS +* +* OUTPUTS +* Status_t - On success VSTATUS_OK is returned, otherwise +* the cause of the error. +* +* +* HISTORY +* +* NAME DATE REMARKS +* SFW 03/10/02 Initial creation of function. +* DKJ 04/04/02 PR1676. OS API 2.0g updates +**********************************************************************/ +Status_t +impl_vs_thread_create (Thread_t *thr, + unsigned char *name, + void (*start_function)(uint32_t, uint8_t **), + uint32_t argc, + uint32_t argv_copy, + uint8_t *argv[], + size_t stack_size) +{ + static const char function[] = "impl_vs_thread_create"; + Implpriv_Thread_t *impl; + Status_t status = VSTATUS_OK; + int pstatus; + /*struct sched_param schedParams;*/ + + IB_ENTER (function, (unint) thr, (unint) name, + (unint) start_function, (uint32_t) argc); + + /* + ** This is a run-time check to ensure that the opaque section of + ** Thread_t is large enough to contain the Implementation private + ** data structure. If this test fails, adjust the OPAQUE_EVENT_SIZE_WORDS + ** define in vs_g.h and rebuild. + */ + if (sizeof(Implpriv_Thread_t) > sizeof (thr->opaque)) + { + IB_LOG_ERROR ("Implementation specific data to big:", + sizeof(Implpriv_Thread_t)); + IB_EXIT (function, VSTATUS_ILLPARM); + return VSTATUS_ILLPARM; + } + if (! name_key_init) + vs_thread_key_init(); + + /* + ** Do the real Linux kernel specific stuff here + */ + impl = (Implpriv_Thread_t *) & thr->opaque[0]; + + impl->magic = IMPLPRIV_THREAD_MAGIC; + impl->start_function = start_function; + strncpy(impl->name, (const char*)name, sizeof(impl->name)-1); + impl->name[sizeof(impl->name)-1] = '\0'; + + /* + ** If the argv vector is to be copied, malloc a single + ** chunk of memory for it. It will be freed by a cleanup + ** handler (installed by impl_vs_thread_start) when + ** the thread exits. + */ + if (argv_copy) + { + int i, size = 0; + uint8_t **new_argv; + char *p; + + for (i = 0; i < argc; ++i) + { + size += (int)strlen((void *)argv[i])+1; + } + + new_argv = (uint8_t **)malloc(argc*sizeof(void *) + size); + if (new_argv == NULL) + { + IB_LOG_ERROR0("Could not malloc memory for argv copy"); + return VSTATUS_NOMEM; + } + + p = (char *)(new_argv + argc); /* Put env right after argv vector. */ + for (i = 0; i < argc; ++i) + { + new_argv[i] = (void *)p; + StringCopy(p, (void *)argv[i], size); + p += strlen((void *)argv[i])+1; + size -= (strlen((void *)argv[i])+1); + } + impl->argv = new_argv; + impl->argv_copied = 1; + } + else + { + impl->argv = argv; + impl->argv_copied = 0; + } + impl->argc = argc; + + + /* + ** Initialize dead flag and associated condition variable and + ** mutex. These are used to ensure only one thread is ever + ** allowed to kill the target thread. + */ + impl->dead = 0; + pthread_cond_init(&impl->dead_cond, NULL); + pthread_mutex_init(&impl->dead_mutex, NULL); + /* switch to default thread create with no attributes */ + #if 0 + pthread_attr_init(&impl->attr); + pthread_attr_setstack(&impl->attr,stack,stack_size); + if(thr->priority != 0) + { + schedParams.sched_priority = thr->priority; + pthread_attr_setschedparam(&impl->attr,&schedParams); + pthread_attr_setinheritsched (&impl->attr,PTHREAD_EXPLICIT_SCHED); + pthread_attr_setschedpolicy(&impl->attr, SCHED_RR); + } + + /* + ** Start the thread. + */ + pstatus = pthread_create(&impl->thread, &impl->attr, + (void * (*)(void *))impl_vs_thread_start, + (void *) impl); + #endif + /* cannot send local impl pointer as argument, maybe gone before thread starts */ + pstatus = pthread_create(&impl->thread, NULL, + (void *)impl_vs_thread_start, + (void *)thr->opaque); + if (pstatus) + { + status = (pstatus == EAGAIN) ? VSTATUS_OK : VSTATUS_BAD; + IB_LOG_ERROR("Thread creation failed errno:", (uint32_t) pstatus); + IB_LOG_ERRORRC("Thread creation rc:", status); + } + + impl->create_pid = (Threadname_t) impl->thread; + impl->create_ppid = (Threadname_t) (int64_t) getppid(); + + IB_LOG_INFINI_INFOLX("new thread's name", (uint64_t) impl->create_pid); + IB_LOG_INFINI_INFOLX("new thread's pid ", (uint64_t) getpid()); + IB_LOG_INFINI_INFOLX("new thread's group", (uint64_t) impl->create_ppid); + IB_EXIT (function, status); + return status; +} + +/********************************************************************** +* +* FUNCTION +* impl_vs_thread_name +* +* DESCRIPTION +* Linux user space specific implementation of the vs_thread_name(). +* This routine is called by the vs_thread_create() API. +* +* INPUTS +* +* OUTPUTS +* Status_t - On success VSTATUS_OK is returned, otherwise +* the cause of the error. +* +* +* HISTORY +* +* NAME DATE REMARKS +* SFW 03/10/02 Initial creation of function. +**********************************************************************/ +Status_t +impl_vs_thread_name (Threadname_t *name) +{ + static const char function[] = "impl_vs_thread_name"; + + IB_ENTER (function, (unint) name, (uint32_t) 0U, (uint32_t) 0U, + (uint32_t) 0U); + + /* + ** Remember parms validated by API. + ** Return the thread ID + */ + //*name = (Threadname_t) (int64_t) getpid(); + *name = (Threadname_t) pthread_self(); + + IB_EXIT (function, VSTATUS_OK); + return VSTATUS_OK; +} + +const char *impl_vs_thread_name_str (void) +{ + //return thread_name; + if (! name_key_init) { + return "main"; + } else { + char* name = pthread_getspecific(name_key); + return (name)?name:""; + } +} + +/********************************************************************** +* +* FUNCTION +* impl_vs_thread_groupname +* +* DESCRIPTION +* Linux kernel specific implementation of the vs_thread_groupname() +* API. This routine is called by the vs_thread_create() API. +* +* INPUTS +* +* OUTPUTS +* Status_t - On success VSTATUS_OK is returned, otherwise +* the cause of the error. +* +* +* HISTORY +* +* NAME DATE REMARKS +* SFW 03/10/02 Initial creation of function. +**********************************************************************/ +Status_t +impl_vs_thread_groupname (Threadname_t name, Threadname_t *grpname) +{ + static const char function[] = "impl_vs_thread_groupname"; + + IB_ENTER (function, name, (unint) grpname, (uint32_t) 0U, + (uint32_t) 0U); + + /* + ** Remember parms validated by API. + ** Return the process pid + */ + *grpname = (Threadname_t) (int64_t) getpid(); + + IB_EXIT (function, VSTATUS_OK); + return VSTATUS_OK; +} + +/********************************************************************** +* +* FUNCTION +* impl_vs_thread_exit +* +* DESCRIPTION +* Linux user space specific implementation of the vs_thread_exit() +* API. This routine is called by the vs_thread_exit() API. +* +* INPUTS +* +* OUTPUTS +* Status_t - On success VSTATUS_OK is returned, otherwise +* the cause of the error. +* +* +* HISTORY +* +* NAME DATE REMARKS +* SFW 03/10/02 Initial creation of function. +**********************************************************************/ +Status_t +impl_vs_thread_exit (Thread_t *handle) +{ + static const char function[] = "impl_vs_thread_exit"; + + IB_ENTER (function, (unint) handle, (uint32_t) 0U, (uint32_t) 0U, + (uint32_t) 0U); + + /* + ** This will cause the thread's cleanup handler, + ** impl_vs_thread_exit_handler(), to be called. + ** That's where all thread cleanup is done. + */ + pthread_exit(NULL); + + /* + ** Should not return to here! + */ + IB_EXIT (function, VSTATUS_BAD); + return VSTATUS_BAD; +} + +/********************************************************************** +* +* FUNCTION +* impl_vs_thread_kill +* +* DESCRIPTION +* Linux user space specific implementation of the vs_thread_kill() +* API. This routine is called by the vs_thread_kill() API. +* +* INPUTS +* +* OUTPUTS +* Status_t - On success VSTATUS_OK is returned, otherwise +* the cause of the error. +* +* +* HISTORY +* +* NAME DATE REMARKS +* SFW 03/08/02 Initial creation of function. +* MGR 04/19/02 Changed pthread_kill call to pthread_cancel, +* since pthread_kill was terminating program. +**********************************************************************/ +Status_t +impl_vs_thread_kill (Thread_t *handle) +{ + static const char function[] = "impl_vs_thread_kill"; + Implpriv_Thread_t *impl; + Status_t status; + int pstatus; + + IB_ENTER (function, (unint) handle, (uint32_t) 0U, (uint32_t) 0U, + (uint32_t) 0U); + + /* + ** Remember parms validated by API. + */ + + /* + ** This is a run-time check to ensure that the opaque section of + ** Thread_t is large enough to contain the Implementation private + ** data structure. If this test fails, adjust the OPAQUE_EVENT_SIZE_WORDS + ** define in vs_g.h and rebuild. + */ + if (sizeof(Implpriv_Thread_t) > sizeof (handle->opaque)) + { + IB_LOG_ERROR ("Implementation specific data to big:", + sizeof(Implpriv_Thread_t)); + IB_EXIT (function, VSTATUS_ILLPARM); + return VSTATUS_ILLPARM; + } + + /* + ** Do the real Linux kernel specific stuff here + */ + impl = (Implpriv_Thread_t *) & handle->opaque[0]; + + /* + ** Validate magic + */ + if (impl->magic != IMPLPRIV_THREAD_MAGIC) + { + IB_LOG_ERRORX ("Bad thread control block:", impl->magic); + IB_EXIT (function, VSTATUS_ILLPARM); + return VSTATUS_ILLPARM; + } + + /* + ** If the thread is already dead or if another killer is + ** killing the thread, don't bother. + */ + pthread_mutex_lock(&impl->dead_mutex); + if (!impl->dead) { + IB_LOG_INFO("Kill Threadname", (uint32_t) impl->create_pid); + impl->dead = 1; + pstatus = pthread_cancel(impl->thread); + if (pstatus) + { + pthread_mutex_unlock(&impl->dead_mutex); + status = (pstatus == ESRCH) ? VSTATUS_ILLPARM : VSTATUS_BAD; + IB_LOG_ERROR("Thread killed failed errno:", (uint32_t) pstatus); + IB_LOG_ERRORRC("Thread killed failed rc:", status); + IB_EXIT(function, status); + return status; + } + pthread_cond_wait(&impl->dead_cond, &impl->dead_mutex); + } + else { + pthread_mutex_unlock(&impl->dead_mutex); + } + + IB_EXIT (function, VSTATUS_OK); + return VSTATUS_OK; +} + +/********************************************************************** +* +* FUNCTION +* impl_vs_thread_sleep +* +* DESCRIPTION +* Linux user space specific implementation of the vs_thread_sleep() +* API. This routine is called by the vs_thread_sleep() API. +* +* INPUTS +* +* OUTPUTS +* Status_t - On success VSTATUS_OK is returned, otherwise +* the cause of the error. +* +* +* HISTORY +* +* NAME DATE REMARKS +* SFW 03/10/02 Initial creation of function. +* PJG 04/02/02 PR 1676. vs_thread_sleep prototype per OS API 2.0g +**********************************************************************/ +void +impl_vs_thread_sleep (uint64_t sleep_time) +{ + static const char function[] = "impl_vs_thread_sleep"; + struct timespec ts; + struct timespec ts_actual; + long micro_seconds; + + IB_ENTER (function, sleep_time, 0U, 0U, 0U); + + /* + ** Remember parms validated by API. + */ + ts.tv_sec = (time_t) (sleep_time / 1000000ULL); + micro_seconds = (long) (sleep_time % 1000000ULL); + ts.tv_nsec = micro_seconds * 1000; + (void) nanosleep( &ts, &ts_actual); + + IB_EXIT (function, VSTATUS_OK); + return; +} + +/********************************************************************** +* +* FUNCTION +* argv_free +* +* DESCRIPTION +* Cleanup function called when a thread is killed or exits normally. +* I.e., any thread exit will funnel through here. +* +* INPUTS +* Pointer to impl structure. +* +* OUTPUTS +* - +* +* +**********************************************************************/ +static void +impl_vs_thread_exit_handler(void *arg) +{ + Implpriv_Thread_t *thr_impl = (Implpriv_Thread_t *)arg; + static const char function[] = "impl_vs_thread_exit_handler"; + + IB_ENTER (function, (unint) thr_impl, 0U, 0U, 0U); + + /* + ** If argv was copied, free it now. + */ + if (thr_impl->argv_copied) { + IB_LOG_INFO("freeing argv", thr_impl->argv); + free(thr_impl->argv); + } + + /* + ** Set our dead flag to 1, telling any would-be killers not + ** to bother. Also signal any waiting killers that we're now dead. + */ + pthread_mutex_lock(&thr_impl->dead_mutex); + thr_impl->dead = 1; + pthread_cond_broadcast(&thr_impl->dead_cond); + pthread_mutex_unlock(&thr_impl->dead_mutex); + + IB_EXIT (function, (uint32_t) 0U); +} + +/********************************************************************** +* +* FUNCTION +* impl_vs_thread_start +* +* DESCRIPTION +* Linux user space specific helper to wrap the start a thread. +* +* INPUTS +* +* OUTPUTS +* Status_t - On success VSTATUS_OK is returned, otherwise +* the cause of the error. +* +* +* HISTORY +* +* NAME DATE REMARKS +* SFW 03/10/02 Initial creation of function. +**********************************************************************/ +int +impl_vs_thread_start (void *impl) +{ + static const char function[] = "impl_vs_thread_start"; + Implpriv_Thread_t *thr_impl = (Implpriv_Thread_t *)impl; + + IB_ENTER (function, 0U, 0U, 0U, 0U); + + /* + ** Only called by kernel create function. + */ + if (!thr_impl) + { + IB_LOG_ERROR0("Internal logic error, no create data"); + IB_EXIT (function, VSTATUS_ILLPARM); + return -1; + } + (void)pthread_setspecific(name_key, thr_impl->name); + //thread_name = thr_impl->name; + + /* + ** Enable thread cancellation and make it immediate -- this + ** enables a vs_thread_kill() to kill the thread on-demand + ** without waiting for the target thread to reach a + ** cancellation point. + */ + pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); + pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL); + + /* + ** Bracket the thread entry point with the installation/removal + ** of a cleanup handler. If the thread exits normally or is + ** killed, the cleanup handler will be called. + */ + pthread_cleanup_push(impl_vs_thread_exit_handler, thr_impl); + + thr_impl->start_function(thr_impl->argc, thr_impl->argv); + pthread_exit(NULL); /* Will call impl_vs_thread_exit_handler() */ + + pthread_cleanup_pop(0); + + /*NOTREACHED*/ + return 0; +} + +/********************************************************************** +* +* FUNCTION +* impl_vs_thread_join +* +* DESCRIPTION +* Linux user space specific implementation of the vs_thread_join() +* API. This routine is called by the vs_thread_join() API. +* +* INPUTS +* +* OUTPUTS +* Status_t - On success VSTATUS_OK is returned, otherwise +* the cause of the error. +* +* +* HISTORY +* +* NAME DATE REMARKS +* SR 10/24/16 Initial creation of function. +**********************************************************************/ +Status_t +impl_vs_thread_join (Thread_t *handle, void **value_ptr) +{ + static const char function[] = "impl_vs_thread_join"; + Status_t status; + Implpriv_Thread_t *impl; + + IB_ENTER (function, (unint)handle, (unint) value_ptr, (uint32_t) 0U, + (uint32_t) 0U); + + impl = (Implpriv_Thread_t *)handle->opaque; + + if (!impl) + { + IB_LOG_ERROR0("Internal logic error, no create data"); + IB_EXIT (function, VSTATUS_ILLPARM); + return -1; + } + + status = pthread_join(impl->thread, NULL); + + IB_EXIT (function, status); + return status; +} +/********************************************************************* + * + * FUNCTION + * impl_vs_thread_setname(char *name) + * + * DESCRIPTION + * Linux User Space implementation of vs_thread_setname() API. + * Sets the name of the calling thread in the thread specific + * storage. + * INPUTS + * pointer to char* to the name of the thread. + * + * OUTPUTS + * + * + *********************************************************************/ +int +impl_vs_thread_setname(char *name) +{ + int rc = 0; + if(name_key_init) + { + rc = pthread_setspecific(name_key, name); + } + return rc; +} diff --git a/Esm/ib/src/ibaccess/vs_utility.c b/Esm/ib/src/ibaccess/vs_utility.c new file mode 100644 index 0000000..5b5146a --- /dev/null +++ b/Esm/ib/src/ibaccess/vs_utility.c @@ -0,0 +1,191 @@ +/* BEGIN_ICS_COPYRIGHT5 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + * ** END_ICS_COPYRIGHT5 ****************************************/ + +//======================================================================= +// / +// FILE NAME / +// vs_utility.c / +// / +// DESCRIPTION / +// This is the CS routines which don't fit a common category. / +// / +// DATA STRUCTURES / +// None / +// / +// FUNCTIONS / +// vs_enter log an entry into a routine / +// vs_exit log an exit from a routine / +// vs_time_get get the current epoch time / +// / +// DEPENDENCIES / +// ib_mad.h / +// ib_status.h / +// / +// / +// HISTORY / +// / +// NAME DATE REMARKS / +// jsy 02/14/01 Initial creation of file. / +// jsy 04/04/01 Added vs_getpid function. / +// trp 08/20/01 Removed vs_getpid (vs_thread_name) is one to use / +//======================================================================= +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "ib_mad.h" +#include "ib_status.h" +#include "cs_g.h" +#include "cs_log.h" +#include +#ifdef LOCAL_MOD_ID +#undef LOCAL_MOD_ID +#endif +#define LOCAL_MOD_ID VIEO_CS_MOD_ID + +//----------------------------------------------------------------------------// + +Status_t +vs_time_get(uint64_t *address) +{ + uint64_t usecs; + struct timespec now; + + if (address == 0) + { + return(VSTATUS_ILLPARM); + } + clock_gettime(CLOCK_MONOTONIC, &now); + usecs = now.tv_sec; + usecs *= 1000000; + usecs += (now.tv_nsec/1000); + /*round up anything greater than 0.5 usecs*/ + if (now.tv_nsec % 1000 > 500) + usecs++; + + *address = usecs; + + return(VSTATUS_OK); +} + +/* + * vs_stdtime_get - get current time as a time_t, seconds since 1970 + */ +Status_t +vs_stdtime_get(time_t *address) +{ + if (-1 == time(address)) + return VSTATUS_BAD; + return(VSTATUS_OK); +} + +// Translate CoreDumpLimit string to a rlimit value +// returns 0 on success, -1 on error +// value argument is optional, if NULL just checks str is valid CoreDumpLimit +// str can be a byte count or "unlimited" +int vs_getCoreDumpLimit(const char* str, uint64_t* value) +{ + uint64_t rlimit; + + if (!str) + return -1; + + if (! strlen(str)) + return -1; + + if (strcasecmp(str, "unlimited") == 0) { + rlimit = RLIM_INFINITY; + } else { + if (FSUCCESS != StringToUint64Bytes(&rlimit, str, NULL, 0, TRUE)) + return -1; + // treat small values as Megabytes + if (rlimit < 8192) + rlimit = rlimit * (1024*1024); + } + + if (value) + *value = rlimit; + return 0; +} + +/* + * vs_init_coredump_settings - setup coredump config for this process + * note this changes the current directory + */ +void vs_init_coredump_settings(const char* mgr, const char* limit, const char *dir) +{ + struct rlimit rlimit; + char buf[140]; + struct stat statbuf; + + rlimit.rlim_max = RLIM_SAVED_MAX; + if (0 != vs_getCoreDumpLimit(limit, &rlimit.rlim_cur)) { + // parser should have already validated, but just to be safe + snprintf(buf, sizeof(buf), "%s: Disabling CoreDumps: Invalid CoreDumpLimit: '%s'", + mgr, limit); + vs_log_output_message(buf, FALSE); + rlimit.rlim_cur = 0; limit = "0"; + } else if (rlimit.rlim_cur == 0) { + snprintf(buf, sizeof(buf), "%s: Disabling CoreDumps: CoreDumpLimit: %s", mgr, limit); + vs_log_output_message(buf, FALSE); + } else if (strlen(dir) == 0 || 0 == strcmp(dir, "/dev/null")) { + snprintf(buf, sizeof(buf), "%s: Disabling CoreDumps: No CoreDumpDir", mgr); + vs_log_output_message(buf, FALSE); + rlimit.rlim_cur = 0; limit = "0"; + } else { + if (-1 == stat(dir, &statbuf)) { + if (mkdir(dir, 0644) != 0) { + snprintf(buf, sizeof(buf), "%s: Disabling CoreDumps: Unable to create CoreDumpDir: '%s' %m", mgr, dir); + vs_log_output_message(buf, FALSE); + rlimit.rlim_cur = 0; limit = "0"; + } + } else if (! S_ISDIR(statbuf.st_mode)) { + snprintf(buf, sizeof(buf), "%s: Disabling CoreDumps: CoreDumpDir is not a directory: '%s'", mgr, dir); + vs_log_output_message(buf, FALSE); + rlimit.rlim_cur = 0; limit = "0"; + } + if (0 != chdir(dir)) { + snprintf(buf, sizeof(buf), "%s: Disabling CoreDumps: Unable to cd CoreDumpDir: '%s' %m", mgr, dir); + vs_log_output_message(buf, FALSE); + rlimit.rlim_cur = 0; limit = "0"; + } + } + if (setrlimit(RLIMIT_CORE, &rlimit) != 0) { + snprintf(buf, sizeof(buf), "%s: Unable to change CoreDumpLimit to '%s' %m", mgr, limit); + vs_log_output_message(buf, FALSE); + } else if (rlimit.rlim_cur) { + snprintf(buf, sizeof(buf), "%s: Enabling CoreDumps to %s up to %s bytes", mgr, dir, limit); + vs_log_output_message(buf, FALSE); + } +} diff --git a/Esm/ib/src/linux/log/common/sqlite_messagelog.c b/Esm/ib/src/linux/log/common/sqlite_messagelog.c new file mode 100644 index 0000000..b26c322 --- /dev/null +++ b/Esm/ib/src/linux/log/common/sqlite_messagelog.c @@ -0,0 +1,29 @@ +/* BEGIN_ICS_COPYRIGHT5 **************************************** + +Copyright (c) 2018, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + * ** END_ICS_COPYRIGHT5 ****************************************/ + diff --git a/Esm/ib/src/linux/log/common/sqlite_messagelog.h b/Esm/ib/src/linux/log/common/sqlite_messagelog.h new file mode 100644 index 0000000..38c1915 --- /dev/null +++ b/Esm/ib/src/linux/log/common/sqlite_messagelog.h @@ -0,0 +1,32 @@ +/* BEGIN_ICS_COPYRIGHT5 **************************************** + +Copyright (c) 2018, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + * ** END_ICS_COPYRIGHT5 ****************************************/ +#ifndef _DBMLS_H_ +#define _DBMLS_H_ + +#endif /* _DBMLS_H_ */ diff --git a/Esm/ib/src/linux/log/common/vslog.c b/Esm/ib/src/linux/log/common/vslog.c new file mode 100644 index 0000000..bc5ba32 --- /dev/null +++ b/Esm/ib/src/linux/log/common/vslog.c @@ -0,0 +1,518 @@ +/* BEGIN_ICS_COPYRIGHT5 **************************************** + +Copyright (c) 2018, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + * ** END_ICS_COPYRIGHT5 ****************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include "sys/file.h" +#include +#include +#include +#include +#include + +#include +#include "ib_types.h" +#include "ib_status.h" +#include "cs_g.h" +#include "cs_log.h" +#include "vslog_l.h" + + +uint32_t log_to_console = 0; + +int logMode = 0; +uint32_t logLevel=1; // just used for show_masks option +FILE *log_file = NULL; +int output_fd = -1; + +#define MAX_SYSLOG_NAME 64 +char vs_log_syslog_name[MAX_SYSLOG_NAME + 1] = "opafm"; +uint32_t syslog_facility = LOG_LOCAL6; + +int vs_log_initialized; + +#define min(a,b) (((a)<(b))?(a):(b)) + +void vs_log_set_log_mode(int mode) +{ + logMode = mode; +} + +int +vs_log_get_syslog_level(uint32_t sev) +{ + switch(sev) { + case VS_LOG_NONE: return LOG_INFO; + case VS_LOG_FATAL: return LOG_CRIT; + case VS_LOG_CSM_ERROR: return LOG_ERR; + case VS_LOG_CSM_WARN: return LOG_WARNING; + case VS_LOG_CSM_NOTICE: return LOG_NOTICE; + case VS_LOG_CSM_INFO: return LOG_INFO; + case VS_LOG_ERROR: return LOG_ERR; + case VS_LOG_WARN: return LOG_WARNING; + case VS_LOG_NOTICE: return LOG_NOTICE; + case VS_LOG_INFINI_INFO: return LOG_INFO; + case VS_LOG_INFO: return LOG_DEBUG; + case VS_LOG_VERBOSE: return LOG_DEBUG; + case VS_LOG_DATA: return LOG_DEBUG; + case VS_LOG_DEBUG1: return LOG_DEBUG; + case VS_LOG_DEBUG2: return LOG_DEBUG; + case VS_LOG_DEBUG3: return LOG_DEBUG; + case VS_LOG_DEBUG4: return LOG_DEBUG; + case VS_LOG_ENTER: return LOG_DEBUG; + case VS_LOG_ARGS: return LOG_DEBUG; + case VS_LOG_EXIT: return LOG_DEBUG; + default: return LOG_DEBUG; + } +} + +// avoid conflict with vssappl.c fprintf version used in tests +#ifdef LINUX_USR_REL +void +vs_log_output(uint32_t sev, /* severity */ + uint32_t modid, /* optional Module id */ + const char *function, /* optional function name */ + const char *vf, /* optional vFabric name */ + const char *format, ... + ) +{ + char buffer[1024]; + va_list args; + FILE *f = NULL; + char vfstr[128]; + + va_start(args, format); + (void) vsnprintf (buffer, sizeof(buffer), format, args); + va_end (args); + buffer[sizeof(buffer)-1] = '\0'; + + if (vf) + snprintf(vfstr, sizeof(vfstr), "[VF:%s] ", vf); + else + *vfstr='\0'; + + if(log_to_console){ + f = stdout; + } else if(output_fd != -1) { + f = log_file; + } + + if (f) { + struct tm *locTime; + char strTime[28]; + time_t theCalTime=0; + uint32_t pid; + size_t lt=0; + + time(&theCalTime); + locTime = localtime(&theCalTime); + if (locTime) { + lt = strftime(strTime, + sizeof(strTime), + "%a %b %d %H:%M:%S %Y", + locTime); + } + if (lt==0) { + strncpy(strTime,"(unknown)", sizeof(strTime)); + } + + (void)vs_log_thread_pid(&pid); + + fprintf(f, "%s: %s(%u): %s[%s]: %s%s%s%s%s\n", + strTime, vs_log_syslog_name, pid, + cs_log_get_sev_name(sev), vs_thread_name_str(), + cs_log_get_module_prefix(modid), vfstr, + function?function:"", function?": ":"", + buffer); + if (! sev || (sev & NONDEBUG_LOG_MASK)) + fflush(f); + } else { + syslog(vs_log_get_syslog_level(sev), "%s[%s]: %s%s%s%s%s", + cs_log_get_sev_name(sev), vs_thread_name_str(), + cs_log_get_module_prefix(modid), vfstr, + function?function:"", function?": ":"", + buffer); + } + + +} +#endif + +/* Outputs a messages to the syslog regardless of settings */ +/* Also outputs to LogFile if configured */ +void +vs_log_output_message(char *msg, int show_masks) +{ + if (show_masks) { + uint32_t log_masks[VIEO_LAST_MOD_ID+1]; + uint32_t modid; + + cs_log_set_log_masks(logLevel, logMode, log_masks); + vs_log_output(VS_LOG_NONE, VIEO_NONE_MOD_ID,NULL,NULL, + "%s LogLevel: %u LogMode: %u", msg, logLevel, logMode); + for (modid=0; modid <= VIEO_LAST_MOD_ID; ++modid) { + if ( modid == VIEO_NONE_MOD_ID) + continue; + if (log_masks[modid] != cs_log_masks[modid]) + vs_log_output(VS_LOG_NONE, VIEO_NONE_MOD_ID,NULL,NULL, + "%s %s_LogMask: 0x%x", msg, cs_log_get_module_name(modid), cs_log_masks[modid]); + } + } else { + vs_log_output(VS_LOG_NONE, VIEO_NONE_MOD_ID,NULL,NULL, "%s", msg); + } +} + +void +vs_log_output_memory(uint32_t sev, /* severity */ + uint32_t modid, /* optional Module id */ + const char *function, /* optional function name */ + const char *vf, /* optional vFabric name */ + const char *prefix, + const void* addr, + uint32_t len + ) +{ + char hex_buffer[80]; + unsigned hex_offset = 0; + char char_buffer[80]; + unsigned char_offset = 0; + unsigned offset; + const uint8_t *p = (uint8_t*)addr; + + if (! len) { + vs_log_output(sev, modid, function, vf, "%s: length is 0", prefix); + return; + } + + for (offset=0; offset < len; offset++ ) { + if ((offset & 15) == 0 && offset != 0 ) { + vs_log_output(sev, modid, function, vf, "%s: 0x%4.4x%s %s", prefix, offset-16, hex_buffer, char_buffer); + hex_offset = char_offset = 0; + } + hex_offset += sprintf(&hex_buffer[hex_offset], " %2.2x", p[offset]); + if (p[offset] >= ' ' && p[offset] <= '~') + char_offset += sprintf(&char_buffer[char_offset], "%c", p[offset]); + else + char_offset += sprintf(&char_buffer[char_offset], "."); + } + if (offset & 15) { + // output residual + uint32 pad = 16 - (offset & 15); + hex_offset += sprintf(&hex_buffer[hex_offset], "%*s", pad*3, ""); + vs_log_output(sev, modid, function, vf, "%s: 0x%4.4x%s %s", prefix, offset&~15, hex_buffer, char_buffer); + } +} + +#if 0 +// -------------------------------------------------------------------- +// vs_log_time_get +// -------------------------------------------------------------------- +// Return a 64 bit number of uSecs since some epoch. This function +// returns a monotonically increasing sequence. +// +// INPUTS +// loc Where to put the time value +// +// RETURNS +// VSTATUS_OK +// VSTATUS_ILLPARM +// -------------------------------------------------------------------- +Status_t +vs_log_time_get(uint64_t * loc) +{ + struct timeval tv; + + if (NULL == loc) + { + return VSTATUS_ILLPARM; + } + + gettimeofday(&tv, NULL); + *loc = ((uint64_t) (tv.tv_sec) * 1000000L) + (uint64_t) tv.tv_usec; + + return (VSTATUS_OK); +} +#endif + + +// -------------------------------------------------------------------- +// vs_log_thread_pid +// -------------------------------------------------------------------- +// Return the PID for the current thread. +// +// INPUTS +// Pointer to PID +// +// RETURNS +// VSTATUS_OK +// -------------------------------------------------------------------- +Status_t +vs_log_thread_pid(uint32_t * pid) +{ + + if (pid == NULL) + { + return (VSTATUS_ILLPARM); + } + + *pid = (uint32_t) getpid(); + return (VSTATUS_OK); +} + +//-------------------------------------------------------------------- +// vs_fatal_error +//-------------------------------------------------------------------- +// This function will panic() the process and report through the trace +// system a reason. The trace log (if being used) will be preserved so +// that perhaps a debugger can be connected to the system to figure out +// what went wrong. +// +// INPUTS +// string Pointer to string. Truncated to 63 characters +// +// RETURNS +// NEVER RETURNS +//-------------------------------------------------------------------- +void +vs_fatal_error (uint8_t * string) +{ + /* make sure we get an entry to syslog, */ + /* just in case logging not fully initialzed */ + openlog("FATAL:", (LOG_NDELAY | LOG_PID), LOG_USER); + syslog(LOG_CRIT, "%s", string); + closelog(); + + abort(); +} + + +#if 0 +/* + * vslog_time_cvt + * Converts usec to hr:min:sec + * + * INPUTS + * + * RETURNS + * + * + */ +void +vslog_time_cvt(uint64_t val, + uint64_t * hh, uint64_t * mm, uint64_t * ss, uint64_t * us) +{ + + uint64_t t, + tmp_us = 1000000ull; + + *us = (val % tmp_us); + t = (val / (tmp_us)); /* get seconds */ + *ss = (t % (60ull)); + t = (t / 60ull); /* get minutes */ + *mm = ((t) % (60ull)); + t = ((t) / (60ull)); /* get hrs */ + *hh = (t % (24ull)); +} +#endif + + +/* + * vs_log_init + * + */ +Status_t +vs_log_usr_init(void) +{ + if (strlen(vs_log_syslog_name) == 0) + sprintf(vs_log_syslog_name,"opafm"); + //printf("openlog(%s, %x, %u)\n", vs_log_syslog_name, (LOG_CONS | LOG_PID), syslog_facility); + openlog(vs_log_syslog_name, (LOG_CONS | LOG_PID), syslog_facility); + vs_log_initialized = 1; + return VSTATUS_OK; +} + +/* + * vs_log_control + * Function used to pass cmds to the logging subsystem. + * + * INPUTS + * cmd Defines the action to carried out in the subsystem + * arg1 First arg type + * arg2 Second arg + * + * cmd == VS_LOG_STARTSYSLOG + * + * arg1, arg2 and arg3 is NULL. + * + * cmd == VS_LOG_SETFACILITY + * + * arg1 Contains facility + * arg2 and arg3 is NULL. + * + * cmd == VS_LOG_SETMASK + * + * arg1 Contains a new log_masks array + * arg2 log_level + * arg3 kernel module filter mask. + * + * RETURNS + * VSTATUS_OK + * VSTATUS_BAD + */ + +Status_t +vs_log_control(int cmd, void *arg1, void *arg2, void *arg3) +{ + Status_t status; + FILE *old_log_file, *temp_file; + int old_output_fd, temp_fd; + + status = VSTATUS_BAD; + + switch (cmd) + { + case VS_LOG_STARTSYSLOG: + { + if (! vs_log_initialized) + (void) vs_log_usr_init(); + if (vs_log_initialized) + status = VSTATUS_OK; + else + return VSTATUS_BAD; + } + break; + case VS_LOG_SETFACILITY: + { + syslog_facility = (uint32_t) (unint)arg1; + } + break; + case VS_LOG_SETMASK: + { + + if (arg1) + memcpy(cs_log_masks, (uint32_t*)arg1, sizeof(cs_log_masks)); + logLevel = (uint32_t) (unint)arg2; + log_to_console = (int)(unint)arg3; + + status = VSTATUS_OK; + } + break; + case VS_LOG_SETOUTPUTFILE: + { + old_log_file = log_file; + old_output_fd = output_fd; + + if((arg1 != NULL) && (strlen(arg1) > 0)) + { + + temp_fd = open((char*)arg1, + O_WRONLY | O_CREAT| O_APPEND, + S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); + + if(temp_fd == -1) + { + status = VSTATUS_BAD; + } + else + { + status = VSTATUS_OK; + if((temp_file = fdopen(temp_fd, (void *)"a")) == NULL) + { + close(temp_fd); + temp_fd = -1; + status = VSTATUS_BAD; + } + + + } + if(status != VSTATUS_OK) + { + syslog(LOG_ERR,"Failed to open output log file: %s\n",(char*)arg1); + printf("Failed to open output log file: %s\n",(char*)arg1); + + } else + { + FILE *tempf; + + // Remap stdout and stderr to our logfile to catch lower level messages + tempf = freopen((char*)arg1, (void *)"a", stdout); + if (!tempf) { + syslog(LOG_ERR,"Failed to redirect stdout to %s\n",(char*)arg1); + printf("Failed to redirect stdout to %s\n",(char*)arg1); + } + tempf = freopen((char*)arg1, (void *)"a", stderr); + if (!tempf) { + syslog(LOG_ERR,"Failed to redirect stderr to %s\n",(char*)arg1); + printf("Failed to redirect stderr to %s\n",(char*)arg1); + } + + output_fd = temp_fd; + + log_file = temp_file; + if(old_output_fd != -1) + { + if(old_log_file != NULL) + fclose(log_file); + log_file = NULL; + close(old_output_fd); + old_output_fd = -1; + } + } + } + + } + break; + case VS_LOG_SETSYSLOGNAME: + { + if((arg1 != NULL) && (strlen((char*)arg1) <= MAX_SYSLOG_NAME)) + { + snprintf(vs_log_syslog_name, sizeof(vs_log_syslog_name), "%s",(char *)arg1); + } + else + { + return VSTATUS_BAD; + } + } + break; + default: + return VSTATUS_BAD; + } + return status; +} + +FILE* vs_log_get_logfile_fd(void) +{ + return log_file; +} + diff --git a/Esm/ib/src/linux/log/include/vslog_l.h b/Esm/ib/src/linux/log/include/vslog_l.h new file mode 100755 index 0000000..9921872 --- /dev/null +++ b/Esm/ib/src/linux/log/include/vslog_l.h @@ -0,0 +1,141 @@ +/* BEGIN_ICS_COPYRIGHT2 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + * ** END_ICS_COPYRIGHT2 ****************************************/ + +#ifndef __VS_LOGL__ +#define __VS_LOGL__ + +#define MASK_UPDATE_INTERVAL (200) + +#define MAX_FILTER_PID (32) + +#define DEFAULT_VALUE (-1) /* default value use to initialize variables */ + +#if defined(__LINUX__) + +#include +#define MOD64(x,y) ((x)%(y)) +#define PDEBUG1 printf + + + +#if 0 +#define USR_LOG_DEBUG +#endif + +#endif + +#define MAX_MOD_FPID (8) +#define MAX_MODULE_NAMES (32) + + +typedef struct _assoc { + uint32_t modid; + uint8_t name[6]; + /* True, to filter out process ID traces associated with ID */ + int filter_pid; + /* pids associated with module */ + + uint32_t pids[MAX_MOD_FPID]; + + /* number of valid pids in pids array */ + int pid_cnt; + +} VslogModNameId_t; + + +#define MAX_MOD_EXFPID (16) + +typedef struct _assoc_ex { + uint32_t modid; + uint8_t name[6+1]; + /* True, to filter out process ID traces associated with ID */ + int filter_pid; + /* pids associated with module */ + + uint32_t pids[MAX_MOD_EXFPID]; + + /* number of valid pids in pids array */ + int pid_cnt; + +} VslogExModNameId_t; + + +#if 0 +//-------------------------------------------------------------------- +// vs_log_time_get +//-------------------------------------------------------------------- +// Return a 64 bit number of uSecs since some epoch. This function +// returns a monotonically increasing sequence. +// +// INPUTS +// loc Where to put the time value +// +// RETURNS +// VSTATUS_OK +// VSTATUS_ILLPARM +//-------------------------------------------------------------------- +Status_t +vs_log_time_get (uint64_t * loc); +#endif + + +//-------------------------------------------------------------------- +// vs_log_thread_pid +//-------------------------------------------------------------------- +// Return the current thread's PID. +// +// INPUTS +// tag Pointer to pid var +// +// RETURNS +// VSTATUS_OK +//-------------------------------------------------------------------- +Status_t +vs_log_thread_pid (uint32_t * tag); + + +#if 0 +/* + * vslog_time_cvt + * Converts us tho hr:min:sec + * + * INPUTS + * + * RETURNS + * + * + */ +void vslog_time_cvt(uint64_t val, + uint64_t *hr, + uint64_t *min, + uint64_t *sec, + uint64_t *us); +#endif + +#endif /* _VS_LOGL_ */ diff --git a/Esm/ib/src/linux/log/usr/Makefile b/Esm/ib/src/linux/log/usr/Makefile new file mode 100755 index 0000000..8058a04 --- /dev/null +++ b/Esm/ib/src/linux/log/usr/Makefile @@ -0,0 +1,161 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** +# Makefile for SM Module + +# Include Make Control Settings +include $(TL_DIR)/$(PROJ_FILE_DIR)/Makesettings.project + +#=============================================================================# +# Definitions: +#-----------------------------------------------------------------------------# + +# Name of SubProjects +DS_SUBPROJECTS = +# name of executable or downloadable image +EXECUTABLE = # Sm$(EXE_SUFFIX) +# list of sub directories to build +DIRS = +# C files (.c) +CFILES = \ + vslog.c \ + sqlite_messagelog.c + # Add more c files here +# C++ files (.cpp) +CCFILES = \ + # Add more cpp files here +# lex files (.lex) +LFILES = \ + # Add more lex files here +# archive library files (basename, $ARFILES will add MOD_LIB_DIR/prefix and suffix) +LIBFILES = +# Windows Resource Files (.rc) +RSCFILES = +# Windows IDL File (.idl) +IDLFILE = +# Windows Linker Module Definitions (.def) file for dll's +DEFFILE = +# targets to build during INCLUDES phase (add public includes here) +INCLUDE_TARGETS = \ + # Add more h hpp files here +# Non-compiled files +MISC_FILES = +# all source files +SOURCES = $(CFILES) $(CCFILES) $(LFILES) $(RSCFILES) $(IDLFILE) +# Source files to include in DSP File +DSP_SOURCES = $(INCLUDE_TARGETS) $(SOURCES) $(MISC_FILES) \ + $(RSCFILES) $(DEFFILE) $(MAKEFILE) +# all object files +OBJECTS = $(CFILES:.c=$(OBJ_SUFFIX)) $(CCFILES:.cpp=$(OBJ_SUFFIX)) \ + $(LFILES:.lex=$(OBJ_SUFFIX)) +RSCOBJECTS = $(RSCFILES:.rc=$(RES_SUFFIX)) +# targets to build during LIBS phase +LIB_TARGETS_IMPLIB = +LIB_TARGETS_ARLIB = $(LIB_PREFIX)vslogu$(ARLIB_SUFFIX) +LIB_TARGETS_EXP = $(LIB_TARGETS_IMPLIB:$(ARLIB_SUFFIX)=$(EXP_SUFFIX)) +LIB_TARGETS_MISC = +# targets to build during CMDS phase +CMD_TARGETS_SHLIB = +CMD_TARGETS_EXE = $(EXECUTABLE) +CMD_TARGETS_MISC = +# files to remove during clean phase +CLEAN_TARGETS_MISC = +CLEAN_TARGETS = $(OBJECTS) $(RSCOBJECTS) $(IDL_TARGETS) $(CLEAN_TARGETS_MISC) +# other files to remove during clobber phase +CLOBBER_TARGETS_MISC= +# sub-directory to install to within bin +BIN_SUBDIR = +# sub-directory to install to within include +INCLUDE_SUBDIR = + +# Additional Settings +#CLOCALDEBUG = User defined C debugging compilation flags [Empty] +#CCLOCALDEBUG = User defined C++ debugging compilation flags [Empty] +#CLOCAL = User defined C flags for compiling [Empty] +#CCLOCAL = User defined C++ flags for compiling [Empty] +#BSCLOCAL = User flags for Browse File Builder [Empty] +#DEPENDLOCAL = user defined makedepend flags [Empty] +#LINTLOCAL = User defined lint flags [Empty] +#LOCAL_INCLUDE_DIRS = User include directories to search for C/C++ headers [Empty] +#LDLOCAL = User defined C flags for linking [Empty] +#IMPLIBLOCAL = User flags for Object Lirary Manager [Empty] +#MIDLLOCAL = User flags for IDL compiler [Empty] +#RSCLOCAL = User flags for resource compiler [Empty] +#LOCALDEPLIBS = User libraries to include in dependencies [Empty] +#LOCALLIBS = User libraries to use when linking [Empty] +# (in addition to LOCALDEPLIBS) +#LOCAL_LIB_DIRS = User library directories for libpaths [Empty] + +CLOCAL = -DUSER_EXIT_ENABLED -DLINUX_USR_REL $(CPIE) +LOCALDEPLIBS = +PROJ_SM_DIR ?= $(TL_DIR)/Esm/ib + +# pick up vslog.c +# Include Make Rules definitions and rules +ifneq "$(PROJ_SM_DIR)" "" +LOCAL_INCLUDE_DIRS=$(MOD_DIR)/src/linux/log/include +VPATH=$(MOD_DIR)/src/linux/log/common +include $(PROJ_SM_DIR)/Makerules.module +endif + +#=============================================================================# +# Overrides: +#-----------------------------------------------------------------------------# +#CCOPT = # C++ optimization flags, default lets build config decide +#SUBSYSTEM = Subsystem to build for (none, console or windows) [none] +# (Windows Only) +#USEMFC = How Windows MFC should be used (none, static, shared, no_mfc) [none] +# (Windows Only) +#=============================================================================# + +#=============================================================================# +# Rules: +#-----------------------------------------------------------------------------# +# process Sub-directories +include $(TL_DIR)/Makerules/Maketargets.toplevel + +# build cmds and libs +include $(TL_DIR)/Makerules/Maketargets.build + +# install for includes, libs and cmds phases +include $(TL_DIR)/Makerules/Maketargets.install + +# install for stage phase +#include $(TL_DIR)/Makerules/Maketargets.stage +STAGE:: + +# Unit test execution +#include $(TL_DIR)/Makerules/Maketargets.runtest + +clobber:: clobber_module + +#=============================================================================# + +#=============================================================================# +# DO NOT DELETE THIS LINE -- make depend depends on it. +#=============================================================================# diff --git a/Esm/ib/src/linux/startup/fm_config/Makefile b/Esm/ib/src/linux/startup/fm_config/Makefile new file mode 100644 index 0000000..c4108fa --- /dev/null +++ b/Esm/ib/src/linux/startup/fm_config/Makefile @@ -0,0 +1,177 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2018, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** +# Makefile for SM Module + +# Include Make Control Settings +include $(TL_DIR)/$(PROJ_FILE_DIR)/Makesettings.project + +#=============================================================================# +# Definitions: +#-----------------------------------------------------------------------------# + +# Name of SubProjects +DS_SUBPROJECTS = +# name of executable or downloadable image +EXECUTABLE = # Sm$(EXE_SUFFIX) +# list of sub directories to build +DIRS = +# C files (.c) +CFILES = config_convert.c config_check.c + # Add more c files here +# C++ files (.cpp) +CCFILES = \ + # Add more cpp files here +# lex files (.lex) +LFILES = \ + # Add more lex files here +# archive library files (basename, $ARFILES will add MOD_LIB_DIR/prefix and suffix) +LIBFILES = +# Windows Resource Files (.rc) +RSCFILES = +# Windows IDL File (.idl) +IDLFILE = +# Windows Linker Module Definitions (.def) file for dll's +DEFFILE = +# targets to build during INCLUDES phase (add public includes here) +INCLUDE_TARGETS = \ + # Add more h hpp files here +# Non-compiled files +MISC_FILES = +# all source files +SOURCES = $(CFILES) $(CCFILES) $(LFILES) $(RSCFILES) $(IDLFILE) +# Source files to include in DSP File +DSP_SOURCES = $(INCLUDE_TARGETS) $(SOURCES) $(MISC_FILES) \ + $(RSCFILES) $(DEFFILE) $(MAKEFILE) +# all object files +OBJECTS = $(CFILES:.c=$(OBJ_SUFFIX)) $(CCFILES:.cpp=$(OBJ_SUFFIX)) \ + $(LFILES:.lex=$(OBJ_SUFFIX)) +RSCOBJECTS = $(RSCFILES:.rc=$(RES_SUFFIX)) +# targets to build during LIBS phase +LIB_TARGETS_IMPLIB = +#LIB_TARGETS_ARLIB = $(LIB_PREFIX)name$(ARLIB_SUFFIX) +LIB_TARGETS_ARLIB = +LIB_TARGETS_EXP = $(LIB_TARGETS_IMPLIB:$(ARLIB_SUFFIX)=$(EXP_SUFFIX)) +LIB_TARGETS_MISC = +# targets to build during CMDS phase +CMD_TARGETS_SHLIB = +CMD_TARGETS_EXE = $(EXECUTABLE) +CMD_TARGETS_MISC = config_diff config_generate opafmconfigpp \ + $(BUILDDIR)/config_check $(BUILDDIR)/config_convert +# files to remove during clean phase +CLEAN_TARGETS_MISC = +CLEAN_TARGETS = $(OBJECTS) $(RSCOBJECTS) $(IDL_TARGETS) $(CLEAN_TARGETS_MISC) +# other files to remove during clobber phase +CLOBBER_TARGETS_MISC= +# sub-directory to install to within bin +BIN_SUBDIR = +# sub-directory to install to within include +INCLUDE_SUBDIR = + +# Additional Settings +#CLOCALDEBUG = User defined C debugging compilation flags [Empty] +#CCLOCALDEBUG = User defined C++ debugging compilation flags [Empty] +#CLOCAL = User defined C flags for compiling [Empty] +#CCLOCAL = User defined C++ flags for compiling [Empty] +#BSCLOCAL = User flags for Browse File Builder [Empty] +#DEPENDLOCAL = user defined makedepend flags [Empty] +#LINTLOCAL = User defined lint flags [Empty] +#LOCAL_INCLUDE_DIRS = User include directories to search for C/C++ headers [Empty] +#DLOCAL = User defined C flags for linking [Empty] +#IMPLIBLOCAL = User flags for Object Lirary Manager [Empty] +#MIDLLOCAL = User flags for IDL compiler [Empty] +#RSCLOCAL = User flags for resource compiler [Empty] +#LOCALDEPLIBS = User libraries to include in dependencies [Empty] +#LOCALLIBS = User libraries to use when linking [Empty] +# (in addition to LOCALDEPLIBS) +LOCAL_LIB_DIRS = /usr/lib64 + +CLOCAL = $(CPIE) +LOCALDEPLIBS = cs ibaccess config public vslogu Xml +LOCALLIBS = rt crypto + +ifneq "$(BUILD_TARGET_OS)" "VXWORKS" +LOCALLIBS+= expat +endif + +PROJ_SM_DIR ?= $(TL_DIR)/Esm/ib + +# Include Make Rules definitions and rules +ifneq "$(PROJ_SM_DIR)" "" +include $(PROJ_SM_DIR)/Makerules.module +endif + +#=============================================================================# +# Overrides: +#-----------------------------------------------------------------------------# +#CCOPT = # C++ optimization flags, default lets build config decide +#COPT = # C optimization flags, default lets build config decide +#SUBSYSTEM = Subsystem to build for (none, console or windows) [none] +# (Windows Only) +#USEMFC = How Windows MFC should be used (none, static, shared, no_mfc) [none] +# (Windows Only) +#=============================================================================# + +#=============================================================================# +# Rules: +#-----------------------------------------------------------------------------# +# process Sub-directories +include $(TL_DIR)/Makerules/Maketargets.toplevel + +# build cmds and libs +include $(TL_DIR)/Makerules/Maketargets.build + +# install for includes, libs and cmds phases +include $(TL_DIR)/Makerules/Maketargets.install + +$(BUILDDIR)/config_check: $(BUILDDIR)/config_check.o + $(VS)$(CC) $(LDFLAGS)$@ $(BUILDDIR)/config_check.o $(LDLIBS) + +$(BUILDDIR)/config_convert: $(BUILDDIR)/config_convert.o + $(VS)$(CC) $(LDFLAGS)$@ $(BUILDDIR)/config_convert.o $(LDLIBS) + +# install for stage phase +#include $(TL_DIR)/Makerules/Maketargets.stage +STAGE:: + $(VS)$(STAGE_INSTALL) $(STAGE_INSTALL_DIR_OPT) $(PROJ_STAGE_DIR)/etc \ + $(BUILDDIR)/config_check config_generate $(BUILDDIR)/config_convert \ + config_diff opafmconfigpp +# $(VS)$(STAGE_INSTALL) $(STAGE_INSTALL_DIR_OPT) $(PROJ_STAGE_IMAGE_DIR)/etc \ +# config_diff config_generate \ +# $(BUILDDIR)/config_check $(BUILDDIR)/config_convert + +# Unit test execution +#include $(TL_DIR)/Makerules/Maketargets.runtest + +clobber:: clobber_module + +#=============================================================================# + +#=============================================================================# +# DO NOT DELETE THIS LINE -- make depend depends on it. +#=============================================================================# diff --git a/Esm/ib/src/linux/startup/fm_config/config_check.c b/Esm/ib/src/linux/startup/fm_config/config_check.c new file mode 100644 index 0000000..2e4fa83 --- /dev/null +++ b/Esm/ib/src/linux/startup/fm_config/config_check.c @@ -0,0 +1,522 @@ +/* BEGIN_ICS_COPYRIGHT5 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT5 ****************************************/ + +//==============================================================================// +// // +// FILE NAME // +// config_check.c // +// // +// DESCRIPTION // +// This file parses and verifies the opafm.xml config file // +// // +// DATA STRUCTURES // +// None // +//==============================================================================// + + +#include + +#include +#include +#include +#include +#include +#include +#include +#include "cs_g.h" +#include + +#ifndef FALSE +#define FALSE 0 +#endif + +#ifndef TRUE +#define TRUE 1 +#endif + +#define MAX_INSTANCES 8 +#define FM_CONFIG_FILENAME "/etc/opa-fm/opafm.xml" + +uint8_t debug; // debugging mode - default is FALSE +uint8_t checksum; // checksum mode - default is FALSE +uint8_t embedded; // is it called internally ?- default is FALSE +char config_file [PATH_MAX+1]; // location and name of the config file +char reconfig_file [PATH_MAX+1]; // location and name of the reconfig file +Pool_t startup_pool; // a generic pool for malloc'ing memory +#define PROG_NAME_MAX 25 +char prog_name[PROG_NAME_MAX+1]; + +int instance = 0; + +// XML configuration data structure +FMXmlCompositeConfig_t *xml_config = NULL; +FMXmlCompositeConfig_t *xml_reconfig = NULL; +FMXmlConfig_t *fmp; +SMXmlConfig_t *smp; +PMXmlConfig_t *pmp; +FEXmlConfig_t *fep; + +void Usage (void); +Status_t alloc_mem (void); +void free_mem (void); +void check_multicast_VFs (int num_instances, VirtualFabrics_t **vf_configs); +void print_startup_information (void); +void print_checksum_information (int num_instances, VirtualFabrics_t **vf_configs); +void* getXmlParserMemory(uint32_t size, char* info); +void freeXmlParserMemory(void *address, uint32_t size, char* info); + +//command line options +struct option options[]={ + {"help", no_argument, NULL, '$'}, + {0} +}; + +void +Usage (void) +{ + printf ("Usage %s [-s] [-c config_file] [-v] [-d] [-r reconfig_file]\n", prog_name); + printf (" or %s --help\n",prog_name); + printf ("\n"); + printf (" -c config file (default=" FM_CONFIG_FILENAME ")\n"); + printf (" -v display debugging and status information\n"); + printf (" -s strict check mode (validate multicast and VF settings)\n"); + printf (" This option will point out inconsistencies or\n"); + printf (" invalid settings in VF and multicast config.\n"); + printf (" -d display configuration checksum information\n"); + printf (" -r reconfig_file verify that reconfig_file is valid for dynamical reconfiguration\n"); + printf ("\n"); + printf ("Examples:\n"); + printf (" %s\n", prog_name); + printf (" %s -v\n", prog_name); + printf (" %s -sv\n", prog_name); + // Note - the -e option is not presented to user since it is for embedded use only + exit(2); +} + + +void +Usage_full (void) +{ + printf ("Usage %s [-s] [-c config_file] [-v] [-d] [-r reconfig_file]\n", prog_name); + printf (" or %s --help\n",prog_name); + printf ("\n"); + printf (" -c config file (default=" FM_CONFIG_FILENAME ")\n"); + printf (" -v display debugging and status information\n"); + printf (" -s strict check mode (validate multicast and VF settings)\n"); + printf (" This is option will point out inconsistencies or\n"); + printf (" invalid settings in VF and multicast config.\n"); + printf (" -d display configuration checksum information\n"); + printf (" -r reconfig_file verify that reconfig_file is valid for dynamical reconfiguration\n"); + printf ("\n"); + printf (" %s parses and verifies the configuration file of a FM.\n", prog_name); + printf ("Displays debugging and status information.\n"); + printf ("\n"); + printf ("Examples:\n"); + printf (" %s\n", prog_name); + printf (" %s -v\n", prog_name); + printf (" %s -sv\n", prog_name); + // Note - the -e option is not presented to user since it is for embedded use only + exit(0); +} + +static void print_warn(const char *msg) +{ + fprintf(stdout, "FM Instance %d: WARNING: %s\n",instance,msg); +} + +static void print_error(const char *msg) +{ + fprintf(stdout, "FM Instance %d: ERROR: %s\n",instance,msg); +} + +int +main (int argc, char *argv []) { + int c; // used to parse the command line + char tmp[PATH_MAX+1]; + char * ptr; + int index; + int ret = 0; + IXmlParserFlags_t parser_flags = IXML_PARSER_FLAG_NONE; + + debug = FALSE; + checksum = FALSE; + embedded = FALSE; + strncpy (config_file, FM_CONFIG_FILENAME, PATH_MAX); + strncpy (reconfig_file, "", PATH_MAX); + strncpy (tmp, argv[0], PATH_MAX); + tmp[PATH_MAX] = 0; + ptr = strrchr(tmp, '/'); + strncpy (prog_name, ptr ? ptr+1 : tmp, PROG_NAME_MAX); + prog_name[PROG_NAME_MAX]=0; + + VirtualFabrics_t *vf_configs[MAX_INSTANCES] = { NULL }; + VirtualFabrics_t *vf_reconfigs[MAX_INSTANCES] = { NULL }; + + while ((c = getopt_long (argc, argv, "c:vsder:", options, &index)) != -1) { + switch (c) { + case '$': + Usage_full (); + break; + // input config file + case 'c': + StringCopy(config_file, optarg, sizeof(config_file)); + break; + case 'v': + debug = TRUE; + break; + case 's': + parser_flags = IXML_PARSER_FLAG_STRICT; + break; + case 'd': + checksum = TRUE; + break; + case 'e': + embedded = TRUE; + break; + case 'r': + StringCopy(reconfig_file, optarg, sizeof(reconfig_file)); + break; + default: + fprintf(stderr, "invalid argument -%c\n", c); + Usage (); + } + } + if (optind < argc) { + Usage (); + } + + // Allocate memory for reading and parsing the config file. + if (alloc_mem () != VSTATUS_OK) { + exit(1); + } + + //if (read_info_file() != VSTATUS_OK) { + // exit(1); + //} + + // init callback function for XML parser so it can get pool memory + initXmlPoolGetCallback(&getXmlParserMemory); + initXmlPoolFreeCallback(&freeXmlParserMemory); + + // parse the XML config file + xml_config = parseFmConfig(config_file, parser_flags, /* instance does not matter for startup */ 0, /* full */ 1, /* preverify */ 0, /* embedded */ embedded); + if (!xml_config) { + fprintf(stdout, "Could not open or there was a parse error while reading configuration file ('%s')\n", config_file); + ret = 1; + goto failed; + } + + for (instance = 0; instance < xml_config->num_instances; instance++) { + vf_configs[instance] = renderVirtualFabricsConfig(instance, xml_config, print_error, print_warn); + if (vf_configs[instance] == NULL) { + fprintf(stdout, "FM instance %d of configuration file ('%s) is invalid.\n",instance,config_file); + ret = 1; + goto failed; + } + } + + if (parser_flags & IXML_PARSER_FLAG_STRICT) { + check_multicast_VFs(xml_config->num_instances, vf_configs); + } + + if (debug) { + fprintf(stdout, "Successfully parsed %s\n", config_file); + print_startup_information(); + } + + if (checksum) + print_checksum_information(xml_config->num_instances, vf_configs); + + // parse the new XML config file, if specified + if (strlen(reconfig_file)) { + xml_reconfig = parseFmConfig(reconfig_file, parser_flags, 0, /* full */ 1, /* preverify */ 0, /* embedded */ embedded); + if (!xml_reconfig) { + fprintf(stdout, "Could not open or there was a parse error while reading configuration file ('%s')\n", reconfig_file); + ret = 1; + goto failed; + } + + for (instance = 0; instance < xml_config->num_instances; instance++) { + vf_reconfigs[instance] = reRenderVirtualFabricsConfig(instance, vf_configs[instance], xml_reconfig, print_error, print_warn); + if (vf_reconfigs[instance] == NULL) { + fprintf(stdout, "Reconfiguration to file ('%s') for instance %d is invalid\n",reconfig_file,instance); + ret = 1; + goto failed; + } + } + } + +failed: + // if we have XML configs then release them + if (xml_reconfig != NULL) { + for (instance = 0; instance < xml_reconfig->num_instances; instance++) { + if (vf_reconfigs[instance]) { + releaseVirtualFabricsConfig(vf_reconfigs[instance]); + vf_reconfigs[instance] = NULL; + } + } + releaseXmlConfig(xml_reconfig, /* full */ 1); + xml_config = NULL; + } + if (xml_config != NULL) { + for (instance = 0; instance < xml_config->num_instances; instance++) { + if (vf_configs[instance]) { + releaseVirtualFabricsConfig(vf_configs[instance]); + vf_configs[instance] = NULL; + } + } + releaseXmlConfig(xml_config, /* full */ 1); + xml_config = NULL; + } + + // Delete a pool of memory to work with. + free_mem (); + + exit(ret); +} + +// get memory for XML parser +void* +getXmlParserMemory(uint32_t size, char* info) { + void *address; + Status_t status; + +#ifdef XML_MEMORY + printf("called getXmlParserMemory() size (%u) (%s) from config_check.c\n", size, info); +#endif + status = vs_pool_alloc(&startup_pool, size, (void*)&address); + if (status != VSTATUS_OK || !address) + return NULL; + return address; +} + +// free memory for XML parser +void +freeXmlParserMemory(void *address, uint32_t size, char* info) { + +#ifdef XML_MEMORY + printf("called freeXmlParserMemory() size (%u) (%s) from config_check.c\n", size, info); +#endif + vs_pool_free(&startup_pool, address); +} + +//------------------------------------------------------------------------------// +// // +// Routine : alloc_mem // +// // +// Description : Allocate memory. // +// Input : None // +// Output : Status of the startup process // +// 0 - memory was allocated // +// 1 - error allocating memory // +// // +//------------------------------------------------------------------------------// + +Status_t +alloc_mem (void) { + uint32_t pool_size; + Status_t status; + +// +// Create a pool of memory to work with. +// + + // calculate pool size for all instances since this is the initial parsing + // check for all instances of FM and VF configuration. + pool_size = xml_compute_pool_size(/* for all instances of sm */ 1); + status = vs_pool_create (&startup_pool, 0, (uint8_t *)"startup_pool", NULL, pool_size); + if (status != VSTATUS_OK) { + fprintf ( stderr, "Could not create a pool (status = %d)\n", status); + return (VSTATUS_BAD); + } + + return (VSTATUS_OK); +} + + +//------------------------------------------------------------------------------// +// // +// Routine : free_mem // +// // +// Description : Free up allocated memory. // +// Input : None // +// Output : None // +// // +//------------------------------------------------------------------------------// + +void +free_mem (void) { + + (void) vs_pool_delete (&startup_pool); + + return; +} + +//------------------------------------------------------------------------------// +// // +// Routine : check_multicast_VFs // +// // +// Description : do strict checking of consistency of multicast and VFs +// Input : None // +// Output : None // +// // +//------------------------------------------------------------------------------// + +void +check_multicast_VFs (int num_instances, VirtualFabrics_t **vf_configs) { + uint16_t i; + + for (i = 0; i < num_instances; i++) + { + FMXmlInstance_t *fmip = xml_config->fm_instance[i]; + smp = &xml_config->fm_instance[i]->sm_config; + uint32_t j; + + fmp = &fmip->fm_config;; + + // if not starting instance of FM then continue to next FM instance + if (!fmp->start) + continue; + + for (j=0; j< fmip->sm_mdg_config.number_of_groups; ++j) { + SMMcastDefGrp_t *mdgp = &fmip->sm_mdg_config.group[j]; + if (! mdgp->def_mc_create) + continue; + if (strlen(mdgp->virtual_fabric)) { + if (! findVfPointer(vf_configs[i], mdgp->virtual_fabric)) { + fprintf(stdout,"Warning: FM instance %u (%s) MulticastGroup Ignored\n references undefined VirtualFabric: %s\n", + i, fmp->fm_name, mdgp->virtual_fabric); + } + } + if (mdgp->def_mc_pkey != 0xffffffff) { + uint32_t vf; + int match = 0; + for (vf=0; vf < vf_configs[i]->number_of_vfs_all; vf++) { + if (vf_configs[i]->v_fabric_all[vf].standby) continue; + if (PKEY_VALUE(vf_configs[i]->v_fabric_all[vf].pkey) == PKEY_VALUE(mdgp->def_mc_pkey)) { + match=1; + break; + } + } + if (! match) { + fprintf(stdout,"Warning: FM instance %u (%s) MulticastGroup Ignored\n references undefined VirtualFabric PKey: 0x%x\n", + i, fmp->fm_name, mdgp->def_mc_pkey); + } + } + } + } +} + +//------------------------------------------------------------------------------// +// // +// Routine : print_startup_information // +// // +// Description : Add a line of startup information to our data structures. // +// Input : None // +// Output : None // +// // +//------------------------------------------------------------------------------// + +void +print_startup_information (void) { + uint16_t i; + + for (i = 0; i < MAX_INSTANCES; i++) + { + if (!xml_config->fm_instance[i]) continue; + fmp = &xml_config->fm_instance[i]->fm_config; + smp = &xml_config->fm_instance[i]->sm_config; + pmp = &xml_config->fm_instance[i]->pm_config; + fep = &xml_config->fm_instance[i]->fe_config; + + // if none of these are set, then it was not in config file + if (! fmp->start + && fmp->hca == 0xffffffff && fmp->port == 0xffffffff + && fmp->port_guid == 0xffffffffffffffffULL) + continue; + + fprintf(stdout,"FM instance %u (%s) will%s be started\n", + i, fmp->fm_name, fmp->start?"":" not"); + + // if not starting instance of FM then continue to next FM instance + if (!fmp->start) + continue; + + if (fmp->port_guid) { + fprintf(stdout, " PortGuid: 0x%016"PRIx64"\n", fmp->port_guid); + } else { + fprintf(stdout, " HFI: %u Port: %u\n", fmp->hca, fmp->port); + } + + fprintf(stdout, " SM will%s be started\n", + smp->start?"":" not"); + + //fprintf(stdout, " PM will%s be started\n", + // pmp->start?"":" not"); + + fprintf(stdout, " FE will%s be started\n", + fep->start?"":" not"); + } +} + +//------------------------------------------------------------------------------// +// // +// Routine : print_checksum_information // +// // +// Description : Prints checksums of each parsed XML component// +// Input : None // +// Output : None // +// // +//------------------------------------------------------------------------------// + +void +print_checksum_information (int num_instances, VirtualFabrics_t **vf_configs) { + uint16_t i; + uint16_t v; + + fprintf(stdout,"\n"); + for (i = 0; i < num_instances; i++) { + + fmp = &xml_config->fm_instance[i]->fm_config;; + smp = &xml_config->fm_instance[i]->sm_config; + pmp = &xml_config->fm_instance[i]->pm_config; + fep = &xml_config->fm_instance[i]->fe_config; + + fprintf(stdout,"FM instance %u\n", i); + fprintf(stdout, " SM overall checksum %8u consistency checksum %8u\n", smp->overall_checksum, smp->consistency_checksum); + fprintf(stdout, " PM overall checksum %8u consistency checksum %8u\n", pmp->overall_checksum, pmp->consistency_checksum); + fprintf(stdout, " VF database consistency checksum %8u\n", vf_configs[i]->consistency_checksum); + for (v = 0; v < vf_configs[i]->number_of_vfs_all; v++) { + if (vf_configs[i]->v_fabric_all[v].standby) continue; + fprintf(stdout, " VF %s consistency checksum %8u\n", vf_configs[i]->v_fabric_all[v].name, + vf_configs[i]->v_fabric_all[v].consistency_checksum); + } + fprintf(stdout,"\n"); + } +} diff --git a/Esm/ib/src/linux/startup/fm_config/config_convert.c b/Esm/ib/src/linux/startup/fm_config/config_convert.c new file mode 100644 index 0000000..bc23aec --- /dev/null +++ b/Esm/ib/src/linux/startup/fm_config/config_convert.c @@ -0,0 +1,1684 @@ +/* BEGIN_ICS_COPYRIGHT5 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT5 ****************************************/ + +//==============================================================================// +// // +// FILE NAME // +// config_convert.c // +// // +// DESCRIPTION // +// Convert an iview_fm.config file to a opafm.xml file using +// opafm_src.xml file as a guide on how to translate +// This capability used to be used for upgrades from old iview_fm +// releases, but is also a convenient way to generate new FM config +// files with just a few changes relative to the default. +// The FM config generate tools use this mechanism. +// // +// opafm_src.xml (SRC) lines can be in one of the following formats: +// valueOut +// valueOut +// valueOut +// valueOut +// +// +// +// +// +// +// +// text +// text +// text with nothing in col 120+ +// +// iview_fm.config (OLD) is old style format, essentially a bash script of +// comments or oldKey=oldValue +// +// oldValue conversion: +// oldKey can optionally include a format conversion. Format conversion +// occurs for the oldValue prior to comparing it to valueOut and defaultValue +// The following format conversions are supported: +// :hex - output as hex +// :dec - output as dec +// :mtu - convert an MTU enum to byte count (256, 2048, ...) +// :rate - convert a rate enum to rate text (5g, 10g, ...) +// :plus - add one to old value +// :gid - convert 128 bit number into 64:64 format +// :2n - convert a 2^n timeout multiplier to actual time (8ms, 33ms, ...) +// :2ninf - convert a 2^n timeout multiplier to actual time (8ms, 33ms, ...) +// but, values >= IB_LIFETIME_MAX (19) output as "infinite" +// +// Rules for conversion: +// - SRC text >= col 120 is never output, nor is trailing whitespace <= col 119 +// - SRC Lines with nothing in col 120+ are output as is +// - for lines with oldKey control in col 120+, comparision is described +// below and will control edit/deletion of lines based on oldKey's value +// - lines with text in col 120+ which do not match one of the above formats +// is a fatal error. +// comparison is against valueOut. If no match, output oldValue +// ...oldKey==defaultValue--> +// comparison is against valueOut and defaultValue. Match if == either. +// If no match, output oldValue +// ...oldKey^=defaultValue--> +// comparison is exclusively against defaultValue. +// If no match, output oldValue +// ...oldKey^=--> +// Only test oldKey presence. If present, output oldValue. +// ...#oldKey#=--> +// Only test oldKey presence. If present, output unmodified text +// Otherwise delete line. +// ...#oldKey#!--> +// Only test oldKey presence. If not present, output unmodified text +// Otherwise delete line. +// +// Usage model: +// valueOut +// +// +// use one of the above when valueOut has same default as OldValue did +// +// OldKey is compared to valueOut, if oldKey missing, treat as match +// First - replace with oldKey's value if no match +// Second - uncomment with oldKey's value if no match +// Third - if match, delete line. +// Otherwise uncomment with oldKey's value +// +// valueOut +// +// +// use one of the above when valueOut has a different default +// than oldValue did and want to keep new default unless user edited +// oldValue in old config file +// Also in this case, if oldKey has valueOut, config left as default +// (possibly commented out) +// +// OldKey is compared to valueOut and defaultValue treat as == either, +// if oldKey missing treat as match +// First - replace with oldKey's value if no match +// Second - uncomment with oldKey's value if no match +// Third - if match, delete line. +// Otherwise uncomment with oldKey's value +// +// valueOut +// +// +// use one of the above when valueOut has a different default +// than oldValue did and want to keep new default unless user edited +// oldValue in old config file +// Also in this case, if oldKey is not compared to valueOut +// (possibly commented out) +// This format is most useful for showing commented out samples +// were sample valueOut is not defaultValue +// +// OldKey is only compared to defaultValue, if oldKey missing +// treat as match +// First - replace with oldKey's value if no match +// Second - uncomment with oldKey's value if no match +// Third - if match, delete line. +// Otherwise uncomment with oldKey's value +// +// valueOut +// +// +// use one of the above when valueOut was commented out in old config +// and want to keep new example unless user provided an oldValue +// in old config file +// Also in this case, if oldKey is not compared to valueOut +// (possibly commented out) +// This format is most useful for showing commented out samples +// were sample valueOut was commented out in old config +// +// OldKey is only tested for presence in old config +// First - replace with oldKey's value if oldKey present +// Second - uncomment with oldKey's value if oldkey present +// Third - if oldKey not present, delete line. +// Otherwise uncomment with oldKey's value +// +// text +// use this for any text (comments, block start tags, block end tags) +// which should be output only if oldKey exists in the old config file +// +// oldKey is only tested for presence in old config +// text is output (unchanged) if oldKey is present, otherwise delete line +// +// text +// use this for any text (comments, block start tags, block end tags) +// which should be output only if oldKey not in the old config file +// +// oldKey is only tested for presence in old config +// text is output (unchanged) if oldKey not present, otherwise delete line +// +// The #oldKey style should be used for lines in SRC which are for conversion +// but are not desired in the opafm.xml file unless required +// This can be used to avoid clutter while still supporting full conversion +// of old parameters +// +// DATA STRUCTURES // +// None // +// // +// FUNCTIONS // +// main main method that convert the old ocnfig file into the // +// new XML format. // +// // +// DEPENDENCIES // +// ??? // +// // +// // +// HISTORY // +// // +// NAME DATE REMARKS // +// pjs 10/15/08 Initial creation of file. // +// // +//==============================================================================// + +#include +#include +#include +#include +#include +#include + +#include "cs_g.h" +#include "iba/ib_helper.h" +#include "iba/stl_helper.h" + +#ifndef FALSE + #define FALSE 0 +#endif + +#ifndef TRUE + #define TRUE 1 +#endif + + +#define MAX_INSTANCES 8 +#define MAX_DETAIL 2048 +#define MAX_START 256 +#define MAX_UNIQUE 1024 + +typedef struct _Ag_Man { + uint8_t instance; // instance number + uint8_t system [4]; // Agent or Manager identifier + uint8_t key [100]; // key + uint8_t value [100]; // value +} Ag_Man_t; + +uint8_t debug; // debugging mode - default is FALSE + +char config_file [256]; // location and name of the config file +uint8_t read_buffer [256]; // a buffer for reading the file a line-at-a-time +uint8_t buffer [256]; // cleaned up read_buffer +uint32_t line_number; // line number in config file + +uint8_t line_instance; // instance number +uint8_t line_system [4]; // Agent or Manager +uint8_t line_key [100]; // key, of key=value pair +uint8_t line_value [200]; // value, of key=value pair + +uint16_t ag_man_detail_count; // number of entries - detail record +uint16_t ag_man_start_count; // number of entries - start records +uint16_t ag_man_unique_count; // number of entries - unique system/instance pairs + +Ag_Man_t *ag_man_detail; // Agent and Manager information - detail records +Ag_Man_t *ag_man_start; // Agent and Manager information - start records +Ag_Man_t *ag_man_unique; // Agent and Manager information - unique system/instance +Ag_Man_t *ag_manp; // Agent and Manager information - temp pointer + +FILE *fd_config; // file handle for reading the config file + + +// STARTUP-related function prototypes. + +Status_t readAndParseConfigFile (bool_t debug); + +#define OLD_TAG_COL 120 +void dump_ap(char *desc,int line, Ag_Man_t *ap); + +void configConvertUsage(void); +Status_t convertSrcXmlFile (char *,int); +Ag_Man_t * find_detail_rec (char *system, int instance, char*key); +int parseLine(char *lineIn,int lineNumber, char *tagOut, char *valueOut, char *first, char *last, char* firstTag, char* lastTag, char *oldKey, char *defaultValue, int *exclusiveDefault, int *presence, int buf_sizes); +char* getOldValue(char *keyDescIn,int); +int matching_system (Ag_Man_t *ag_start, char *which_one); + +int g_debug = FALSE; + +//------------------------------------------------------------------------------// +// // +// Routine : main (entry point for Linux) // +// // +// Description : Entry point for utility // +// Pre-process : None // +// Input : Command-line arguments // +// Output : A general status indicator // +// 0 - conversion ran to completion // +// 1 - an error was found during conversion // +// Post-process : Call startup_main function readAndParseConfigFile to parse the// +// vieo_fm.rc.config file then call convertSrcXmlFile to write // +// out the XML data to stdout // +// Reference : // +// // +//------------------------------------------------------------------------------// + +int main (int argc, char *argv []) +{ + Status_t status; // return status from startup_main + int c; + char* oldFile; + char* xmlFile; + int showMissing=FALSE; + + while (-1 != (c = getopt(argc, argv, "dD"))) { + switch (c) { + case 'd': + showMissing = TRUE; + break; + case 'D': + g_debug = TRUE; + break; + default: + configConvertUsage(); + break; + } + } + if (argc - optind != 2) { + configConvertUsage(); + } + oldFile = argv[optind++]; + xmlFile = argv[optind++]; + +// +// Default values. +// + + debug = FALSE; + line_number = 0; + + snprintf(config_file, 256, "%s", oldFile); + + status=readAndParseConfigFile(FALSE); + if (status!=VSTATUS_OK) + { + exit (status); + } + + status=convertSrcXmlFile(xmlFile,showMissing); + exit(status); +} + +//------------------------------------------------------------------------------// +// // +// Routine : configConvertUsage // +// // +// Description : Print the usage parameters for config_convert. // +// Pre-process : None // +// Input : None // +// Output : None // +// Post-process : None // +// Reference : // +// // +//------------------------------------------------------------------------------// + +void configConvertUsage (void) +{ + fprintf (stderr,"Usage: config_convert [-d] [-D] old_file src_xml_file\n"); + fprintf (stderr," -d show tags not found in old file\n"); + fprintf (stderr," -D extra debug output to stderr\n"); + fprintf (stderr," old_file old iview_fm.config style file to convert\n"); + fprintf (stderr," src_xml_file new opafm_src.xml style file to guide conversion\n"); + fprintf (stderr,"The old_file (typically iview_fm.config) from an older release is converted\n"); + fprintf (stderr,"to an XML file for this release, using src_xml_file\n"); + fprintf (stderr,"(typically opafm_src.xml) to define how to translate parameters\n"); + exit(2); +} + +//------------------------------------------------------------------------------// +// // +// Routine : convertSrcXmlFile // +// // +// Description : read in the xml src file and replace the tags in col with the // +// spaces and put the data from the old config into the tag on the left// +// +// Pre-process : None // +// Input : None // +// Output : None // +// Post-process : None // +// Reference : // +// // +//------------------------------------------------------------------------------// + +Status_t convertSrcXmlFile (char *xmlFileIn,int showMissing) +{ + char buffIn[255]; + + FILE *xmlIn=fopen(xmlFileIn,"rt"); + if (xmlIn==NULL) + { + fprintf(stderr,"Unable to open file %s\n",xmlFileIn); + exit(1); + } + int lineNumber=1; + while (!feof(xmlIn)) + { + if (fgets(buffIn,255,xmlIn)==0) + { + break; + } + char tag[255]; + char value[255]; + char first[255]; + char last[255]; + char firstTag[255]; + char lastTag[255]; + char oldKey[255]; + char defaultValue[255]; + int exclusiveDefault; + int presence; + + if (g_debug) + fprintf(stderr, "%s\n", buffIn); + if (parseLine(buffIn,lineNumber++,tag,value,first,last,firstTag, lastTag, oldKey,defaultValue, &exclusiveDefault, &presence, 255)) + { + char* oldValue=getOldValue(oldKey,showMissing); + if (g_debug) { + fprintf(stderr, "tag =%s\n", tag); + fprintf(stderr, "value =%s\n", value); + fprintf(stderr, "first =%s\n", first); + fprintf(stderr, "last =%s\n", last); + fprintf(stderr, "firstTag =%s\n", firstTag); + fprintf(stderr, "lastTag =%s\n", lastTag); + fprintf(stderr, "oldKey =%s\n", oldKey); + fprintf(stderr, "defaultValue=%s\n", defaultValue); + fprintf(stderr, "oldValue =%s\n", (oldValue)?oldValue:""); + fprintf(stderr, "exclusive =%d\n", exclusiveDefault); + fprintf(stderr, "presence =%d\n", presence); + } + if (presence > 0) { + // text + // key starting with # means to skip line if old not present + if (oldValue || oldKey[0] != '#') { + fprintf(stdout,"%s\n",first); + if (g_debug) fprintf(stderr,"%s\n",first); + } + } else if (presence < 0) { + // text + // key starting with # means to skip line if old present + if (! oldValue || oldKey[0] != '#') { + fprintf(stdout,"%s\n",first); + if (g_debug) fprintf(stderr,"%s\n",first); + } + } else if (oldValue==NULL || (! exclusiveDefault && 0==strcmp(value,oldValue))) + { + // parameter not in old config or same as new config + // key starting with # means to skip line if default + if (oldKey[0] != '#') { + // output default XML + fprintf(stdout,"%s%s%s\n",first,value,last); + if (g_debug) fprintf(stderr,"%s%s%s\n",first,value,last); + } + } else if (strlen(defaultValue)==0) { + // valueOut + // valueOut + // valueOut + // + // + // + // value doesn't match, no defaultValue + // output XML replacing valueOut with oldValue + fprintf(stdout,"%s%s%s\n",firstTag,oldValue,lastTag); + if (g_debug) fprintf(stderr,"%s%s%s\n",firstTag,oldValue,lastTag); + } else if (strcmp(defaultValue,oldValue)==0) { + // valueOut + // valueOut + // + // + // oldValue matches defaultValue + // key starting with # means to skip line if default + if (oldKey[0] != '#') { + // output default XML + fprintf(stdout,"%s%s%s\n",first,value,last); + if (g_debug) fprintf(stderr,"%s%s%s\n",first,value,last); + } + } else { + // valueOut + // valueOut + // + // + // oldValue doesn't match defaultValue + // output XML replacing valueOut with oldValue + fprintf(stdout,"%s%s%s\n",firstTag,oldValue,lastTag); + if (g_debug) fprintf(stderr,"%s%s%s\n",firstTag,oldValue,lastTag); + } + } + else + { + // this line doens't have a tag in col 120 so dump it back out + fprintf(stdout,"%s",buffIn); + } + } + + fclose(xmlIn); + return VSTATUS_OK; +} + + +int getOldUllValue(Ag_Man_t *sp, unsigned long long *pValue) +{ + char *p; + errno = 0; + *pValue=strtoull((char*)sp->value, &p, 0); + if (errno || *p) { + fprintf(stderr,"WARNING: invalid value for %s_%d_%s=%s\n", + sp->system, sp->instance, sp->key, sp->value); + return FALSE; + } + return TRUE; +} + +typedef enum { + FORMAT_NONE=0, + FORMAT_HEX, + FORMAT_DEC, + FORMAT_MTU, + FORMAT_RATE, + FORMAT_PLUS, + FORMAT_2N, + FORMAT_2NINF, + FORMAT_GID, +} OldFormat_t; + +char *formatOldValue(Ag_Man_t *sp, OldFormat_t format) +{ + static char buf[50]; // used for edited values + unsigned long long value; + unsigned long long value2; + + switch (format) { + default: + case FORMAT_NONE: + return (char*)sp->value; + case FORMAT_HEX: + if (FALSE == getOldUllValue(sp, &value)) + return (char*)sp->value; + snprintf(buf,sizeof(buf),"0x%Lx",value); + return buf; + case FORMAT_DEC: + if (FALSE == getOldUllValue(sp, &value)) + return (char*)sp->value; + snprintf(buf,sizeof(buf),"%Ld",value); + return buf; + case FORMAT_MTU: + if (FALSE == getOldUllValue(sp, &value)) + return (char*)sp->value; + snprintf(buf, 50, "%s", IbMTUToText((IB_MTU)value)); + return buf; + case FORMAT_RATE: + if (FALSE == getOldUllValue(sp, &value)) + return (char*)sp->value; + if (value == IB_STATIC_RATE_DONTCARE) + return (char*)sp->value; + snprintf(buf,sizeof(buf),"%s",StlStaticRateToText((IB_STATIC_RATE)value)); + return buf; + case FORMAT_PLUS: + if (FALSE == getOldUllValue(sp, &value)) + return (char*)sp->value; + snprintf(buf,sizeof(buf),"%lld",value+1); + return buf; + case FORMAT_2N: + case FORMAT_2NINF: + // do the 2^n conversion. + if (FALSE == getOldUllValue(sp, &value)) + return (char*)sp->value; + if (format == FORMAT_2NINF && value > IB_LIFETIME_MAX) + return "infinite"; + FormatTimeoutMult(buf,value); + /* compress out whitespace */ + int s=0; int d=0; + do { + if (buf[s] != ' ') + buf[d++] = buf[s]; + } while (buf[s++]); + return buf; + case FORMAT_GID: + { + char *p; + + // compress out whitespace + int s=0; int d=0; + do { + if (d >= sizeof(buf)) { + fprintf(stderr,"WARNING: invalid value for %s_%d_%s=%s\n", + sp->system, sp->instance, sp->key, sp->value); + return (char*)sp->value; + } + if (sp->value[s] != ' ') + buf[d++] = sp->value[s]; + } while (sp->value[s++]); + + int len = strlen(buf); + if (len != 34) { + fprintf(stderr,"WARNING: invalid value for %s_%d_%s=%s\n", + sp->system, sp->instance, sp->key, sp->value); + return (char*)sp->value; + } + + // get last 16 hex digits + errno = 0; + value2=strtoull(buf+18, &p, 16); + if (errno || *p) { + fprintf(stderr,"WARNING invalid value for %s_%d_%s=%s\n", + sp->system, sp->instance, sp->key, sp->value); + return (char*)sp->value; + } + + // get first 16 hex digits + buf[18] = '\0'; + errno = 0; + value=strtoull(buf, &p, 16); + if (errno || *p) { + fprintf(stderr,"WARNING invalid value for %s_%d_%s=%s\n", + sp->system, sp->instance, sp->key, sp->value); + return (char*)sp->value; + } + snprintf(buf,sizeof(buf),"0x%016llx:0x%016llx",value,value2); + return buf; + } + } +} + +//------------------------------------------------------------------------------// +// // +// Routine : getOldValue // +// // +// Description : Given a key like SM_0_debug retrieve the data form Ag_Man_t // +// structs. // +// Pre-process : readAndParseConfigFile should have been called // +// Input : keyDescIn old config key with optional format descriptor // +// Input : showMissing ouput to stderr the keys that were not found in // +// the old config file. Debug only // +// Output : None // +// Post-process : None // +// Reference : // +// // +//------------------------------------------------------------------------------// +char* getOldValue(char *keyDescIn,int showMissing) +{ + char system[3]; + static const int INSTANCE_LEN=10; + char instance[INSTANCE_LEN+1]; + static const int KEY_LEN=50; + char keyIn[KEY_LEN+1]; + char key[KEY_LEN+1]; + OldFormat_t format = FORMAT_NONE; + + // strip format specified off keyIn + if (keyDescIn[0] == '#') + strncpy(keyIn, keyDescIn+1, KEY_LEN); + else + strncpy(keyIn, keyDescIn, KEY_LEN); + + keyIn[sizeof(keyIn)-1]='\0'; + + char *formatDelim=strchr(keyIn, ':'); + if (formatDelim) { + *formatDelim++='\0'; + if (0==strcmp(formatDelim, "hex")) + format = FORMAT_HEX; + else if (0==strcmp(formatDelim, "dec")) + format = FORMAT_DEC; + else if (0==strcmp(formatDelim, "mtu")) + format = FORMAT_MTU; + else if (0==strcmp(formatDelim, "rate")) + format = FORMAT_RATE; + else if (0==strcmp(formatDelim, "plus")) + format = FORMAT_PLUS; + else if (0==strcmp(formatDelim, "2n")) + format = FORMAT_2N; + else if (0==strcmp(formatDelim, "2ninf")) + format = FORMAT_2NINF; + else if (0==strcmp(formatDelim, "gid")) + format = FORMAT_GID; + else { + fprintf(stderr,"Invalid format: (%s) %s\n",formatDelim, keyDescIn); + exit(1); + } + } + + // Is is of this type SS_I_KEY? + if ((keyIn[2]=='_')&&(keyIn[4]=='_')) + { + //Parse out the system, instance an key + StringCopy(system,keyIn,sizeof(system)); + + char *secondUnderScore=strchr(&keyIn[3],'_'); + if (!secondUnderScore) return NULL; + + int len=(int)(secondUnderScore-&keyIn[3]); + if (len>=INSTANCE_LEN) return NULL; + + StringCopy(instance,&keyIn[3],sizeof(instance)); + + StringCopy(key,secondUnderScore+1,sizeof(key)); + + // fprintf(stdout,"tag:%s sys:%s, instance:%s, key:%s\n",keyIn,system,instance,key); + int instanceValue=atoi(instance); + //get the data out of the structs + if (strncmp(key,"start",6)==0) + { + uint16_t i; + Ag_Man_t *ap; + // find a start record + for (i = 0, ap = ag_man_start; i < ag_man_start_count; i++, ap++) + { + if (matching_system (ap, (void *)system)) + { + if (ap->instance == instanceValue) + { + return "1"; + } + } + } + return "0"; + } + Ag_Man_t *sp=find_detail_rec(system,instanceValue,key); + if (sp!=NULL) + return formatOldValue(sp, format); + // Couldn't find the variable. Display to the user if they set -d + if (showMissing) + { + fprintf(stderr,"Unable to find %s %s,%d,%s\n",keyIn,system,instanceValue,key); + } + } + else + { + int i=0; + // special tags are in all caps + for (i=0;isystem) == 0) + { + if (instance == ag_detail->instance) + { + if (strcasecmp((char*)ag_detail->key,key)==0) + { + return ag_detail; + } + } + } + } + + return NULL; +} + +//------------------------------------------------------------------------------// +// // +// Routine : parseLine // +// // +// Description : Parse a line of the src xml file // +// Lines can be in one of 5 formats: +// valueOut +// valueOut +// valueOut +// +// +// +// text with nothing in col 120+ +// +// Note: + // + // + if (strstr(&line[OLD_TAG_COL-1],""); + if (endOfComment==NULL) + { + fprintf(stderr,"Missing close of comment on line %d\n",lineNumber); + exit(1); + } + int oldKeyLength=(int)(endOfComment-&line[OLD_TAG_COL+3]); + if (oldKeyLength<1) + { + fprintf(stderr,"Empty comment starting at column %d on line %d\n",OLD_TAG_COL, lineNumber); + exit(1); + } + char* equals=strstr(&line[OLD_TAG_COL+3],"^="); + if (equals != NULL) + *exclusiveDefault=1; + else if (NULL != (equals=strstr(&line[OLD_TAG_COL+3],"#="))) + *presence=1; + else if (NULL != (equals=strstr(&line[OLD_TAG_COL+3],"#!"))) + *presence=-1; + else + equals=strstr(&line[OLD_TAG_COL+3],"=="); + if (equals!=NULL) + { + if (equals>=endOfComment) + { + fprintf(stderr,"== after close of comment on line %d\n",lineNumber); + exit(1); + } + *equals='\0'; + equals+=2; + int defLen=endOfComment-equals; + if (defLen) + strncpy(defaultValue,equals,defLen); + defaultValue[defLen]='\0'; + oldKeyLength-=2+strlen(defaultValue); + } + else + { + *defaultValue='\0'; + } + strncpy(oldKey,&line[OLD_TAG_COL+3],oldKeyLength); + oldKey[oldKeyLength]='\0'; + + char lineIn[OLD_TAG_COL+1]; + strncpy(lineIn,line,OLD_TAG_COL); + lineIn[OLD_TAG_COL-1]='\0'; + + if (*presence) { + // text + // text + // simple case, we need to output first and firstTag but "" for all else + StringCopy(first,lineIn, buf_size); + int firstLen = strlen(first); + while (firstLen > 1 && first[firstLen-1]==' ') + { + first[--firstLen]='\0'; + } + StringCopy(tagOut,"", buf_size); + StringCopy(valueOut,"", buf_size); + StringCopy(last,"", buf_size); + StringCopy(firstTag, first, buf_size); + StringCopy(lastTag, last, buf_size); + return 1; + } + + // for lines with a oldKey, we expect to find either: + // value + // + static const int TAG_LENGTH=128; + char tag[TAG_LENGTH]; + char tag2[TAG_LENGTH]; + char *leftBracket1=strchr(lineIn,'<'); + char *startValue; + int valueLength; + if (leftBracket1==NULL) + { + fprintf(stderr,"Missing start of tag on line %d\n%s\n",lineNumber,line); + exit(1); + } + if (leftBracket1[1]=='!') + { + //then this is the start of a comment. skip ahead to the tag. + leftBracket1=strchr(leftBracket1+1,'<'); + if (leftBracket1==NULL) + { + fprintf(stderr,"Missing start of tag on line %d\n%s\n",lineNumber,line); + exit(1); + } + } + char*rightBracket1=strstr(leftBracket1,">"); + if (rightBracket1==NULL) + { + fprintf(stderr,"Left bracket with no right bracket on line %d\n%s\n",lineNumber,line); + exit(1); + } + int tagLength=(int)(rightBracket1-leftBracket1)-1; + if (tagLength<0||tagLength>TAG_LENGTH) + { + fprintf(stderr,"Invalid tag length %d\n%s\n",lineNumber,line); + exit(1); + } + StringCopy(tag,leftBracket1+1,tagLength < sizeof(tag) ? (tagLength+1) : sizeof(tag)); + startValue=rightBracket1+1; + char *leftBracket2=strstr(rightBracket1+1,""); + if (rightBracket2==NULL) + { + fprintf(stderr,"No right bracket on closing tag on line %d\n%s\n",lineNumber,line); + exit(1); + } + int tagLength2=(int)((rightBracket2-leftBracket2)-2); + if (tagLength!=tagLength2) + { + fprintf(stderr,"Closing tag does not match opening tag on line %d. %d!=%d\n%s\n",lineNumber,tagLength,tagLength2,line); + fprintf(stderr,"left=%s right=%s",tag,rightBracket2); + exit(1); + } + StringCopy(tag2,leftBracket2+2,tagLength < sizeof(tag2) ? (tagLength+1) : sizeof(tag2)); + if (strncmp(tag,tag2,tagLength)!=0) + { + fprintf(stderr,"Closing tag does not match opening tag on line %d. %s!=%s\n%s\n",lineNumber,tag,tag2,line); + exit(1); + } + int firstLen=rightBracket1-lineIn+1; + strncpy(first,lineIn,firstLen); + first[firstLen]='\0'; + + int lastLen=strlen(lineIn)-(firstLen+valueLength); + strncpy(last,&lineIn[firstLen+valueLength],lastLen); + last[lastLen]='\0'; + while (lastLen > 1 && last[lastLen-1]==' ') + { + last[--lastLen]='\0'; + } + + strncpy(tagOut,tag,255); + strncpy(valueOut,startValue,valueLength); + valueOut[valueLength]='\0'; + + // output firstTag and lastTag as Uncommented versions of first and last + char *commentStart=strstr(first,""); // start of comment close + if (commentStart==NULL) + { + fprintf(stderr,"Missing close comment for commented out tag. Line %d\n",lineNumber-1); + exit(1); + } + StringCopy(lastTag, last, commentStart-last+1); + StringCopy(lastTag+(commentStart-last), commentStart+3, buf_size - (commentStart-last)); + lastLen = strlen(lastTag); + while (lastLen > 1 && lastTag[lastLen-1]==' ') + { + lastTag[--lastLen]='\0'; + } + + StringCopy(tagOut,tag,255); + } + + return 1; +} + +//------------------------------------------------------------------------------// +// // +// Routine : dump_ap // +// Description : dump a record of Ag_Man_t to stderr (for debug only) // +// // +// Pre-process : none // +//------------------------------------------------------------------------------// +void dump_ap(char *desc,int line, Ag_Man_t *ap) +{ + fprintf(stderr, "%s(%d)= instance %u system %s key %s value %s", desc,line, + (uint32_t)ap->instance, + (char*)ap->system, (char*)ap->key, ap->value); +} + + +//==============================================================================// +// This parses the vieo_fm.config file +// // + +Status_t alloc_mem (void); +void free_mem (void); +Status_t read_line (void); +Status_t parse (void); +int is_special (void); +int is_valid (void); +int is_manager (void); +Status_t add_information (void); +int matching_system (Ag_Man_t *ag_start, char *which_one); +void log_debug (char *format, ...); +void log_error (char *format, ...); + +//------------------------------------------------------------------------------// +// // +// Routine : alloc_mem // +// // +// Description : Allocate memory. // +// Input : None // +// Output : Status of the startup process // +// 0 - memory was allocated // +// 1 - error allocating memory // +// // +//------------------------------------------------------------------------------// + +Status_t +alloc_mem (void) { + +// +// Allocate enough space for 2,048 lines of detailed config information. +// + + ag_man_detail = (Ag_Man_t*)malloc (MAX_DETAIL * sizeof (Ag_Man_t)); + if (NULL == ag_man_detail) { + return (VSTATUS_BAD); + } + ag_manp = ag_man_detail; + ag_man_detail_count = 0; + +// +// Allocate enough space for 256 Agents and Managers to start +// + + ag_man_start = (Ag_Man_t*)malloc (MAX_START * sizeof (Ag_Man_t)); + if (NULL == ag_man_start) { + free ((void *)ag_man_detail); + return (VSTATUS_BAD); + } + ag_man_start_count = 0; + +// +// Allocate enough space for 1,024 unique system/instance. +// + + ag_man_unique = (Ag_Man_t*)malloc (MAX_UNIQUE * sizeof (Ag_Man_t)); + if (NULL == ag_man_unique) { + free ((void *)ag_man_start); + free ((void *)ag_man_detail); + return (VSTATUS_BAD); + } + ag_man_unique_count = 0; + + return (VSTATUS_OK); +} + + +//------------------------------------------------------------------------------// +// // +// Routine : free_mem // +// // +// Description : Free up allocated memory. // +// Input : None // +// Output : None // +// // +//------------------------------------------------------------------------------// + +void +free_mem (void) { + + free ((void *)ag_man_unique); + free ((void *)ag_man_start); + free ((void *)ag_man_detail); + + return; +} + + +//------------------------------------------------------------------------------// +// // +// Routine : read_line // +// // +// Description : Read a line of input, ignoring blank lines and lines that // +// start with a pound sign (#). // +// Input : None // +// Output : Status of the startup process // +// 0 - a line of content was read // +// 1 - found EOF // +// // +//------------------------------------------------------------------------------// + +Status_t +read_line (void) { + uint8_t *slash; // start of line comments + uint8_t *start; // start of read buffer + uint8_t *stop; // end of read buffer + Status_t status; // return code status + + while (TRUE) { + // clean memory is good memory + memset (read_buffer, 0, 256); + memset (buffer, 0, 256); + + // NULL means we read past EOF + if (fgets ((void *)read_buffer, 255, fd_config) == NULL) { + status = VSTATUS_BAD; + break; + } + line_number++; + + start = read_buffer; + stop = read_buffer + strlen ((void *)read_buffer); + + // terminate after line comments (//) + slash = (uint8_t *)strstr ((void *)start, "//"); + if (slash != NULL) { + *slash = '\0'; + stop = read_buffer + strlen ((void *)read_buffer); + } + + // remove leading whitespace + while (isspace (*start)) { + start++; + } + + // ignore lines that start with a pound sign (#) + if (*start == '#') { + continue; + } + + // remove trailing whitespace + while (stop > start && isspace (*--stop)) { + *stop = '\0'; + } + + // ignore blank lines + if (*start == '\0') { + continue; + } + + // we have a line of input to work with + strncpy ((void *)buffer, (void *)start, 256); + + // see if we found an EOF (used by ATI) + if (strncasecmp ((void *)buffer, "EOF", 3) == 0) { + status = VSTATUS_BAD; + } else { + status = VSTATUS_OK; + } + break; + } + + return (status); +} + +//------------------------------------------------------------------------------// +// // +// Routine : parse // +// // +// Description : Parse a line of input and create data structures. // +// Input : None // +// Output : None, bad lines are printed and dropped // +// // +//------------------------------------------------------------------------------// + +Status_t +parse (void) { + Status_t status; + +// +// Capture special lines before we toss them, i.e., VIEO_FM_BASE=some_directory. +// + + if (is_special () == TRUE) { + return (VSTATUS_OK); + } + +// +// Might be a good line, see if it's a valid format (system_instance_key=value). +// + + if (is_valid () == FALSE) { +// log_debug ("Warning: invalid configuration data, line %d\nLine : %s\n\n", line_number, read_buffer); + return (VSTATUS_OK); + } + +// +// Add this information to the data structures +// + + status = add_information (); + + return (status); +} + +static void setBase(char *mgr, int instance) { + memset (line_system, 0, 4); + strncpy ((void *)line_system, mgr, 2); + line_instance = instance; + (void) add_information (); +} +//------------------------------------------------------------------------------// +// // +// Routine : is_special // +// // +// Description : Look for 'special' lines. // +// Input : None // +// Output : TRUE - special line found // +// FALSE - nothing special here // +// // +//------------------------------------------------------------------------------// + +int +is_special (void) { + char *equals; // location of equals sign (=) + uint8_t subnetSize[16]; // subnet size + uint8_t syslogMode[16]; // syslog mode + int i; + + if (strncasecmp ((void *)buffer, "HARDWARE_MFG", 12) == 0) { + return (TRUE); + } else if (strncasecmp ((void *)buffer, "HARDWARE_TYPE", 13) == 0) { + return (TRUE); + } else if (strncasecmp ((void *)buffer, "START_AFTER_ERROR", 17) == 0) { + return (TRUE); + } else if (strncasecmp ((void *)buffer, "STARTUP_LOG", 11) == 0) { + return (TRUE); + } else if (strncasecmp ((void *)buffer, "SUBNET_SIZE", 11) == 0) { + equals = index ((void *)buffer, '='); + if (equals == NULL) { + // no equals sign (=) + return (FALSE); + } + // we'll use VIEO_FM_BASE for creating the output file + StringCopy ((void *)subnetSize, equals + 1, sizeof(subnetSize)); + /* add SUBNET_SIZE to each manager environment */ + memset (line_key, 0, 100); + StringCopy ((void *)line_key, "SUBNET_SIZE", strlen("SUBNET_SIZE") + 1); + memset (line_value, 0, 200); + strncpy ((void *)line_value, (void *)subnetSize, 128); + for (i = 0; i < MAX_INSTANCES; i++) { + setBase("sm", i); + setBase("bm", i); + setBase("pm", i); + setBase("fe", i); + } + return (TRUE); + } else if (strncasecmp ((void *)buffer, "SYSLOG_MODE", 11) == 0) { + equals = index ((void *)buffer, '='); + if (equals == NULL) { + // no equals sign (=) + return (FALSE); + } + /* add SYSLOG_MODE to each manager's environment */ + StringCopy ((void *)syslogMode, equals + 1, sizeof(syslogMode)); + memset (line_key, 0, 100); + StringCopy ((void *)line_key, "SYSLOG_MODE", strlen("SYSLOG_MODE") + 1); + memset (line_value, 0, 200); + strncpy ((void *)line_value, (void *)syslogMode, 16); + for (i = 0; i < MAX_INSTANCES; i++) { + setBase("sm", i); + setBase("bm", i); + setBase("pm", i); + setBase("fe", i); + } + return (TRUE); + } + + return (FALSE); +} + + +//------------------------------------------------------------------------------// +// // +// Routine : is_valid // +// // +// Description : Make a best-effort to validate the format of the line. It // +// should contain a key=value. Where the key is three parts: // +// system_instance_dbkey. 'System' is either an Agent or a // +// Manager identifier. 'Instance' is a number from 0-255 // +// inclusive. 'db_key' is a arbitrary string. // +// Input : None // +// Output : TRUE - looks like a valid line // +// FALSE - something wierd is going on here // +// // +//------------------------------------------------------------------------------// + +int +is_valid (void) { + int scan_count; // number of sscanf parameters + int instance; // instance number (0 - 256) + char *equals; // location of equals sign (=) + char *underscore_1; // location of underscore (_) + char *underscore_2; // location of underscore (_) + char scan_system [256]; // Agent or Manager indicator + char scan_instance [256]; // instance number + char scan_key [256]; // key + char scan_value [256]; // value + +// +// See if this is a Manager. +// + + if (!is_manager ()) { + // not an Manager line + return (FALSE); + } + +// +// Find the first underscore (_), it terminates the 'system'. +// + + underscore_1 = index ((void *)buffer, '_'); + if (underscore_1 == NULL) { + // no first underscore, bad news + return (FALSE); + } + *underscore_1 = ' '; + underscore_1++; + +// +// Find the second underscore, it separates the 'system' from the 'instance'. +// + + underscore_2 = index (underscore_1, '_'); + if (underscore_2 == NULL) { + // no second underscore, bad news + return (FALSE); + } + *underscore_2 = ' '; + underscore_2++; + +// +// Find the equals sign (=), it separates the 'variable' from the 'value'. +// + + equals = index (underscore_2, '='); + if (equals == NULL) { + // no equals sign between the variable and the value + return (FALSE); + } + *equals = ' '; + +// +// Extract elements of the string. +// + + scan_count = sscanf ((void *)buffer, "%255s %255s %255s %255s", scan_system, scan_instance, scan_key, scan_value); + if (scan_count != 4) { + // need 4 sets of information (system instance key value) + return (FALSE); + } + scan_system[255]=0; + scan_instance[255]=0; + scan_key[255]=0; + scan_value[255]=0; + +// +// Convert the instance number to an integer. +// + + scan_count = sscanf (scan_instance, "%d", &instance); + if (scan_count != 1) { + // couldn't scan an instance number + return (FALSE); + } + + if (instance < 0 || instance > 255) { + // instance number out of range + return (FALSE); + } + +// +// Save the system (Agent or Manager) information. +// + + memset (line_system, 0, 4); + strncpy ((void *)line_system, scan_system, 3); + +// +// Save the instance number. +// + + line_instance = instance; + +// +// Save the key information. +// + + memset (line_key, 0, 100); + strncpy ((void *)line_key, scan_key, 99); + +// +// Save the parameter (value) information. +// + + memset (line_value, 0, 200); + strncpy ((void *)line_value, scan_value, 199); + + return (TRUE); +} + + +//------------------------------------------------------------------------------// +// // +// Routine : is_manager // +// // +// Description : Determine if this is a Manager line. // +// Managers are: BM, FE, PM, SM // +// Input : None // +// Output : TRUE - contains a Manager identifier // +// FALSE - not a Manager identifier // +// // +//------------------------------------------------------------------------------// + +int +is_manager (void) { + + if (strncasecmp ((void *)buffer, "BM", 2) == 0) { + return (TRUE); + } else if (strncasecmp ((void *)buffer, "FE", 2) == 0) { + return (TRUE); + } else if (strncasecmp ((void *)buffer, "PM", 2) == 0) { + return (TRUE); + } else if (strncasecmp ((void *)buffer, "SM", 2) == 0) { + return (TRUE); + } else { + return (FALSE); + } +} + +//------------------------------------------------------------------------------// +// // +// Routine : add_information // +// // +// Description : Add a line of information to our data structures. // +// Input : None // +// Output : None // +// // +//------------------------------------------------------------------------------// + +Status_t +add_information (void) { + uint16_t i; + Ag_Man_t *ap; + + +// +// Keep track of the Agents and Managers that are specifically started (...start=yes). +// + if ((strcasecmp ((void *)line_key, "start") == 0) && (strcasecmp ((void *)line_value, "yes") == 0)) { + // find a start record + for (i = 0, ap = ag_man_start; i < ag_man_start_count; i++, ap++) { + if (matching_system (ap, (void *)line_system)) { + if (ap->instance == line_instance) { + // already have this one recorded + return (VSTATUS_OK); + } + } + } + + // need to add a new starter record + ap->instance = line_instance; + strncpy ((void *)ap->system, (void *)line_system, 3); + ag_man_start_count++; + + if (ag_man_start_count > MAX_START) { + log_error ("Warning: too many 'start=yes' entries, line %d\nLine : %s\n", line_number, read_buffer); + return (VSTATUS_BAD); + } + return (VSTATUS_OK); + } + + +// +// Add to the detailed information. +// + + ag_manp->instance = line_instance; + + strncpy ((void *)ag_manp->system, (void *)line_system, 3); + strncpy ((void *)ag_manp->key, (void *)line_key, 99); + strncpy ((void *)ag_manp->value, (void *)line_value, 99); + + ag_manp++; + ag_man_detail_count++; + + if (ag_man_detail_count > MAX_DETAIL) { + log_error ("Warning: too many detailed entries, line %d\nLine : %s\n", line_number, read_buffer); + return (VSTATUS_BAD); + } + +// +// See if we need to add this to the unique information. +// Unique information is a unique system (BM, PM, SM) and instance identifier. +// + + for (i = 0, ap = ag_man_unique; i < ag_man_unique_count; i++, ap++) { + if (matching_system (ap, (void *)line_system)) { + if (ap->instance == line_instance) { + // already have this one recorded + return (VSTATUS_OK); + } + } + } + +// +// Add to the unique information. +// + + ap->instance = line_instance; + strncpy ((void *)ap->system, (void *)line_system, 3); + ag_man_unique_count++; + + if (ag_man_unique_count > MAX_UNIQUE) { + log_error ("Warning: too many unique entries, line %d\nLine : %s\n", line_number, read_buffer); + return (VSTATUS_BAD); + } + + return (VSTATUS_OK); +} + + +int +matching_system (Ag_Man_t *ag_start, char *which_one) { + + if (strcasecmp ((void *)ag_start->system, which_one) == 0) { + return (TRUE); + } else { + return (FALSE); + } +} + +//------------------------------------------------------------------------------// +// // +// Routine : log_debug // +// // +// Description : Print debugging information. Instead of embedding printf // +// statments everywhere, we'll do all printing from one routine // +// so that in the future we can re-direct output to some other // +// device if we're not Linux-based. // +// Input : A format and argument list, like printf // +// Output : None // +// // +//------------------------------------------------------------------------------// + +void +log_debug (char *format, ...) { + va_list args; + + if (debug == TRUE) { + va_start (args, format); + (void) vprintf (format, args); + va_end (args); + } + + return; +} + + +//------------------------------------------------------------------------------// +// // +// Routine : log_error // +// // +// Description : Print error information. Instead of embedding printf // +// statments everywhere, we'll do all printing from one routine // +// so that in the future we can re-direct output to some other // +// device if we're not Linux-based. // +// Input : A format and argument list, like printf // +// Output : None // +// // +//------------------------------------------------------------------------------// + +void +log_error (char *format, ...) { + va_list args; + + va_start (args, format); + (void) vprintf (format, args); + va_end (args); + + return; +} + +Status_t readAndParseConfigFile(bool_t debug) +{ +// +// Open the config file. +// + + fd_config = fopen (config_file, "r"); + if (fd_config == NULL) { + log_error ("Could not open the config file ('%s') for reading\n", config_file); + return (VSTATUS_BAD); + } + +// +// Allocate memory for reading and parsing the config file. +// + if (alloc_mem () != VSTATUS_OK) { + return (VSTATUS_BAD); + } + +// +// Read the config file, parse the lines, and create data structures. +// + int line=0; + while (read_line () == VSTATUS_OK) { + if (debug) fprintf(stdout,"test line %d->%s\n",line++,buffer); + if (parse () != VSTATUS_OK) { + break; + } + } +// +// Close the config file. +// + (void) fclose (fd_config); + return VSTATUS_OK; +} diff --git a/Esm/ib/src/linux/startup/fm_config/config_diff.sh b/Esm/ib/src/linux/startup/fm_config/config_diff.sh new file mode 100755 index 0000000..671daee --- /dev/null +++ b/Esm/ib/src/linux/startup/fm_config/config_diff.sh @@ -0,0 +1,142 @@ +#!/bin/bash +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] + +TEMP1="$(mktemp)" +TEMP2="$(mktemp)" +PROG_NAME=$0 +trap "rm -f $TEMP1 $TEMP2; exit 1" SIGHUP SIGTERM SIGINT +trap "rm -f $TEMP1 $TEMP2" EXIT + +Usage() +{ + echo "Usage: $(basename $PROG_NAME) [-f][-l] [-d 'diff_args'] file1 file2" >&2 + echo " or $(basename $PROG_NAME) --help" >&2 + echo " " >&2 + echo " --help - produce full help text" >&2 + echo " -f - filter out FM parameters which are not part of consistency check" >&2 + echo " Removes config tags that do not cause consistency checks on the" >&2 + echo " FM to fail from diff" >&2 + echo " -l - include comments in XML to indicate original line numbers" >&2 + echo " -d 'diff_args' - additional arguments to diff command" >&2 + echo " e.g. -uw for unified format ignoring whitespace." >&2 + echo " " >&2 + exit 2 +} + +Usage_full() +{ + echo "Usage: $(basename $PROG_NAME) [-f][-l] [-d 'diff_args'] file1 file2" >&2 + echo " or $(basename $PROG_NAME) --help" >&2 + echo " " >&2 + echo " --help - produce full help text" >&2 + echo " -f - filter out FM parameters which are not part of consistency check" >&2 + echo " Removes config tags that do not cause consistency checks on the" >&2 + echo " FM to fail from diff" >&2 + echo " -l - include comments in XML to indicate original line numbers" >&2 + echo " -d 'diff_args' - additional arguments to diff command" >&2 + echo " e.g. -uw for unified format ignoring whitespace." >&2 + echo " " >&2 + echo "$(basename $PROG_NAME) performs a difference between two config files corresponding" >&2 + echo "to two FM instances described by file1 and file2" >&2 + echo " " >&2 + echo "Examples:" >&2 + echo " $(basename $PROG_NAME) /etc/opa-fm/opafm.xml /usr/share/opa-fm/opafm.xml" >&2 + echo " $(basename $PROG_NAME) -f /etc/opa-fm/opafm.xml /usr/share/opa-fm/opafm.xml" >&2 + echo " $(basename $PROG_NAME) -d -uw /etc/opa-fm/opafm.xml /usr/share/opa-fm/opafm.xml" >&2 + exit 0 + +} + +# Main function + +if [ x"$1" = "x--help" ] +then + Usage_full +fi + +IFS_FM_BASE=/usr/lib/opa-fm +tooldir=$IFS_FM_BASE/bin + +if [ x"$1" = "x--help" ] +then + Usage +fi + +filter=n +filter_args= +diff_args= +while getopts fld: param +do + case $param in + f) filter=y;; + l) filter_args="$filter_args -l";; + d) diff_args="$diff_args $OPTARG";; + ?) Usage;; + esac +done +shift $((OPTIND -1)) + +if [ $# -lt 2 ] +then + Usage +fi +file1=$1 +file2=$2 + +if [ ! -e $file1 ] +then + echo "$file1: Not Found" >&2 + Usage +fi +if [ ! -e $file2 ] +then + echo "$file2: Not Found" >&2 + Usage +fi + +if [ x"$filter" = xy ] +then + filter_args="$filter_args -s Start -s Hca -s Port -s Debug -s RmppDebug -s Priority -s ElevatedPriority -s LogLevel -s LogFile -s LogMode -s SyslogFacility +-s *_LogMask -s Name -s PortGUID -s Sm.TrapLogSuppressTriggerInterval -s Sm.SmPerfDebug -s Sm.SaPerfDebug -s Sm.DebugDor -s Sm.DebugVf -s Sm.DebugJm -s Sm.DebugLidAssign -s Sm.LoopTestOn -s Sm.LoopTestPacket -s Sm.LID -s Sm.DynamicPortAlloc -s Sm.SaRmppChecksum -s Pm.ThresholdsExceededMsgLimit -s Pm.SweepErrorsLogThreshold -s Bm.DebugFlag -s Fe.TcpPort" +fi + +$tooldir/opafmxmlfilter -i 4 $filter_args $file1 > $TEMP1 +[ $? != 0 ] && exit 1 + +$tooldir/opafmxmlfilter -i 4 $filter_args $file2 > $TEMP2 +[ $? != 0 ] && exit 1 + +diff $diff_args $TEMP1 $TEMP2 +res=$? + +rm -f $TEMP1 $TEMP +exit $res diff --git a/Esm/ib/src/linux/startup/fm_config/config_generate.sh b/Esm/ib/src/linux/startup/fm_config/config_generate.sh new file mode 100755 index 0000000..8f6a779 --- /dev/null +++ b/Esm/ib/src/linux/startup/fm_config/config_generate.sh @@ -0,0 +1,720 @@ +#!/bin/bash +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2018, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] + +TEMP="$(mktemp)" +trap "rm -f $TEMP; exit 1" SIGHUP SIGTERM SIGINT +trap "rm -f $TEMP" EXIT + +IFS_FM_BASE=/usr/lib/opa-fm +tooldir=$IFS_FM_BASE/bin +OPAFM_SRC=/usr/share/opa-fm/opafm_src.xml +CONFIG_XML=/etc/opa-fm/opafm.xml +esm=n + +Usage() +{ + exitcode=$1 + if [ "$exitcode" == "" ] + then + exitcode=2 + fi + echo "Usage: config_generate [-e] [-s source_file] dest_file" >&2 + echo " or" >&2 + echo " config_generate --help" >&2 + echo " --help - produce full help text" >&2 + echo " -e - generate file for embedded FM, default is to generate for host FM" >&2 + echo " -s - source opafm XML file (default=$OPAFM_SRC)" >&2 + exit $exitcode +} + +if [ x"$1" = "x--help" ] +then + Usage 0 +fi + +while getopts "es:" param +do + case $param in + e) esm=y;; + s) OPAFM_SRC=$OPTARG;; + ?) Usage;; + esac +done +shift $((OPTIND -1)) + +if [ $# -lt 1 ] +then + echo "Error: No destination file specified." >&2 + Usage +fi +dest_file=$1 + +if [ ! -f "$OPAFM_SRC" ] +then + echo "Error: source file not found: \"$OPAFM_SRC\"" >&2 + exit 1 +fi + +print_separator() +{ + echo "-------------------------------------------------------------------------------" +} + +# global $ans set to 1 for yes or 0 for no +get_yes_no() +{ + local prompt default input + prompt="$1" + default="$2" + while true + do + input= + echo -n "$prompt [$default]:" + read input + if [ "x$input" = x ] + then + input="$default" + fi + case "$input" in + [Yy]*) ans=1; break;; + [Nn]*) ans=0; break;; + esac + done +} + +# global $ans set to value input +get_number() +{ + local prompt default input min max + prompt="$1" + default="$2" + min="$3" + max="$4" + while true + do + input= + echo -n "$prompt [$default]:" + read input + if [ "x$input" = x ] + then + input="$default" + fi + if [ "$input" -lt $min -o "$input" -gt $max ] 2>/dev/null + then + echo "Input must be number $min to $max. Invalid Input: $input" + else + ans=$input + break + fi + done +} + +# global $ans set to value input +get_string() +{ + local prompt default input + prompt="$1" + default="$2" + while true + do + input= + echo -n "$prompt [$default]:" + read input + if [ "x$input" = x ] + then + input="$default" + fi + ans=$input + break + done +} + +# global $ans set to value input +#get_choice() +#{ +# local prompt default input +# prompt="$1" +# default="$2" +# PS3="$prompt ($default recommended): " +# select input in $choices +# do +# case "$input" in +# gcc|pathscale|pgi|intel) ans=$input; break;; +# esac +# done +#} + +# global $ans set to value input +mtu[1]="256" +mtu[2]="512" +mtu[3]="1024" +mtu[4]="2048" +mtu[5]="4096" +get_mtu() +{ + local prompt default input + prompt="$1" + default="$2" + + # set default in case cntrl-D entered + case "$default" in + 2048) ans=4;; # convert to IBTA enum + 4096) ans=5;; # convert to IBTA enum + esac + + PS3="$prompt ($default recommended): " + select input in 2048 4096 + do + case "$input" in + 2048) ans=4; break;; # convert to IBTA enum + 4096) ans=5; break;; # convert to IBTA enum + esac + done +} + +# global $ans set to value input +rate[1]="25g" +rate[2]="50g" +rate[3]="75g" +rate[4]="100g" + +get_rate() +{ + local prompt default input + prompt="$1" + default="$2" + + # set default in case cntrl-D entered + case "$default" in + '25g') ans=1;; + '50g') ans=2;; + '75g') ans=3;; + '100g') ans=4;; + esac + + PS3="$prompt ($default recommended): " + select input in '25g' '50g' '75g' '100g' + do + case "$input" in + '25g') ans=1; break;; + '50g') ans=2; break;; + '75g') ans=3; break;; + '100g') ans=4; break;; + esac + done +} + +enable_instance() +{ + local instance + instance=$1 + + fm_enabled[$instance]=1 + echo "SM_${instance}_start=yes" >> $TEMP + + enable_default=y + get_yes_no "Should PM instance $instance (${fm_device[$instance]}) be enabled" $enable_default + if [ "$ans" -eq 1 ] + then + echo " Enabling Start of PM instance $instance" + echo "PM_${instance}_start=yes" >> $TEMP + fi + + enable_default=n + get_yes_no "Should FE instance $instance (${fm_device[$instance]}) be enabled" $enable_default + if [ "$ans" -eq 1 ] + then + echo " Enabling Start of FE instance $instance" + echo "FE_${instance}_start=yes" >> $TEMP + fi + +} + +set_instance_priority() +{ + local instance priority + instance=$1 + priority=$2 + + echo "SM_${instance}_priority=$priority" >> $TEMP + #echo "PM_${instance}_priority=$priority" >> $TEMP + #echo "BM_${instance}_priority=$priority" >> $TEMP + #echo "FE_${instance}_priority=$priority" >> $TEMP +} + +if [ -e $dest_file ] +then + if [ ! -f $dest_file ] + then + echo "Error: $dest_file exists but is not a file" >&2 + exit 1 + fi + get_yes_no "Overwrite existing $dest_file" "n" + if [ $ans -eq 0 ] + then + exit 0 + fi +fi + +# FM instance HFIs +fm_hfi[0]=1 +fm_hfi[1]=1 +fm_hfi[2]=2 +fm_hfi[3]=2 +# FM instance Ports +fm_port[0]=1 +fm_port[1]=2 +fm_port[2]=1 +fm_port[3]=2 +# which instances are enabled +fm_enabled[0]=0 +fm_enabled[1]=0 +fm_enabled[2]=0 +fm_enabled[3]=0 +# default names for instances +fm_name[0]=fm0 +fm_name[1]=fm1 +fm_name[2]=fm2 +fm_name[3]=fm3 +# FM device descriptions +fm_device[0]="HFI ${fm_hfi[0]} Port ${fm_port[0]}" +fm_device[1]="HFI ${fm_hfi[1]} Port ${fm_port[1]}" +fm_device[2]="HFI ${fm_hfi[2]} Port ${fm_port[2]}" +fm_device[3]="HFI ${fm_hfi[3]} Port ${fm_port[3]}" + +fm_allinstances="all FM instances" + +# start to build $TEMP file with answers +rm -f $TEMP +print_separator +echo "FM resources and buffering are scaled to match the anticipated maximum size" +echo "of the fabric. The size is specified in terms of the number of HFIs in" +echo "a single fabric." +if [ "$esm" = y ] +then + echo "For Embedded Fabric Manager, its recommended to use a value of 100 or less." + get_number "Anticipated maximum fabric size" 100 0 100 +else + echo "For Host Fabric Manager, its recommended to use a value of 2560 or larger." + get_number "Anticipated maximum fabric size" 2560 0 10000 +fi +echo " Setting SubnetSize to $ans" +echo "SUBNET_SIZE=$ans" >> $TEMP + +print_separator +echo "LMC is used to control the number of LIDs per HFI." +echo "Multiple LIDs can be used to permit multiple routes between endpoints." +echo "This permits selected applications (such as MPIs using Intel(R) PSM) to" +echo "optimize performance and/or resiliency by using dispersive routing." +get_number "LMC value to use (there will be 2^LMC LIDs per HFI)" 0 0 7 +echo " Setting Lmc to $ans" +echo " There will be $((2**$ans)) LIDs per HFI" +echo "SM_0_lmc=$ans" >> $TEMP # sets for all instances + +print_separator +echo "Adaptive routing permits Intel(R) Omni-Path Architecture switches to dynamically adjust routing" +echo "based on traffic patterns and hence reduce congestion and improve overall" +echo "cluster performance and efficiency." +get_yes_no "Should Adaptive Routing be enabled" "n" +echo " Setting AdaptiveRouting.Enable to $ans" +echo "SM_0_ar_enable=$ans" >> $TEMP # sets for all instances +if [ "$ans" -eq 1 ] +then + echo "Adaptive routing will always route around failed or down links." + echo "In addition adapting routing around congestion can be enabled." + get_yes_no "Should Adaptive Routing around congestion be enabled" "n" + echo " Setting AdaptiveRouting.LostRouteOnly to $ans" + echo "SM_0_ar_lost_route_only=$ans" >> $TEMP # sets for all instances + + echo "Adaptive routing will always permit adapting among links between neighbor" + echo "switch ASICs. In addition for pure CLOS/Fat Tree topologies, adaptions can be" + echo "enabled to occur at all levels in the tree and across all ISLs." + get_yes_no "Should full CLOS/Fat Tree Adaptive Routing be enabled" "n" + echo " Setting AdaptiveRouting.Tier1FatTree to $ans" + echo "SM_0_ar_tier1_fat_tree=$ans" >> $TEMP # sets for all instances +fi + +if [ "$esm" != y ] +then + print_separator + echo "The FM logging has two possible modes." + echo "In Normal mode, logging includes user actionable events and other FM" + echo "messages such as sweep progress, internal warnings and errors, etc." + echo "In Quiet mode, only user actionable events are logged." + get_yes_no "Should Quiet Mode be used" "n" + echo " Setting LogMode to $ans" # 0=Normal, 1=Quiet +else + ans=0 +fi + +print_separator +echo "When nodes appear or disappear from the fabric, a message is logged." +echo "A Threshold can be configured to limit the number of such messages per sweep." +echo "This Threshold can help to avoid excessive messages when fabric changes occur." +get_number "Node Appearance Log Message Threshold" 100 +echo " Setting NodeAppearanceMsgThreshold to $ans" +echo "SM_0_node_appearance_msg_thresh=$ans" >> $TEMP # sets for all instances + +if [ "$esm" = y ] +then + enable_instance 0 + instances="0" + num_instances=1 + fm_device[0]="Switch Port 0" + fm_allinstances="this FM" +else + print_separator + echo "By default a FM node will run a single FM on the 1st Port of the 1st HFI." + echo "However, in larger configurations, a single FM node may be used to" + echo "manage multiple fabrics. Each such fabric would be contected to a different" + echo "HFI port. Each HFI port is associated with a different FM instance." + num_instances=0 + default=y + for instance in 0 1 2 3 + do + get_yes_no "Should FM instance $instance (${fm_device[$instance]}) be enabled" $default + + if [ "$ans" -eq 1 ] + then + echo " Enabling Start of SM instance $instance" + enable_instance $instance + instances="$instances $instance" + num_instances=$(($num_instances + 1)) + fi + + default=n # only default to instance 0 enabled + + done +fi + +print_separator +if [ "$esm" = y ] +then + echo "Each FM can have a name." +else + echo "Each FM instance can have a unique name. The name will appear as part" + echo "of all syslog entries generated by the given FM instance." +fi +for instance in $instances +do + get_string "Name for FM instance $instance (${fm_device[$instance]})" "fm$instance" + echo " Setting Name of FM instance $instance to $ans" + echo "SM_${instance}_name=$ans" >> $TEMP + fm_name[$instance]="$ans" +done + +print_separator +echo "The FM configures the rate and MTU used for IPoIB multicast." +echo "The rate selected must be no greater than the rate of the slowest link" +echo "in the fabric(s)." +echo "The MTU selected must be no greater than the MTU of the smallest MTU link" +echo "in the fabric(s)." +echo "When selecting the rate and MTU, HFIs which won't run IPoIB can be ignored." +echo "However all Switches must be operating with at least the rate and MTU selected." +echo +if [ $num_instances -eq 1 ] +then + same_rate=1 + same_mtu=1 +else + get_yes_no "Will the same IPoIB Rate be used for $fm_allinstances" "y" + same_rate=$ans + get_yes_no "Will the same IPoIB MTU be used for $fm_allinstances" "y" + same_mtu=$ans +fi +if [ $same_rate -eq 1 ] +then + get_rate "IPoIB rate for $fm_allinstances" '25g' + rate=$ans +fi +if [ $same_mtu -eq 1 ] +then + get_mtu "IPoIB MTU for $fm_allinstances" 2048 + mtu=$ans +fi +if [ $same_mtu -eq 1 -a $same_rate -eq 1 ] +then + echo " Setting MulticastGroup.MTU to ${mtu[$mtu]}" + echo " Setting MulticastGroup.Rate to ${rate[$rate]}" + echo "SM_0_def_mc_mtu=$mtu" >> $TEMP # sets for all instances + echo "SM_0_def_mc_rate=${rate[$rate]}" >> $TEMP # sets for all instances +else + for instance in $instances + do + if [ $same_rate -eq 0 ] + then + get_rate "IPoIB rate for FM instance $instance (${fm_name[$instance]}) (${fm_device[$instance]})" '25g' + rate=$ans + fi + if [ $same_mtu -eq 0 ] + then + get_mtu "IPoIB MTU for FM instance $instance (${fm_name[$instance]}) (${fm_device[$instance]})" 2048 + mtu=$ans + fi + echo " Setting MulticastGroup.Rate for FM instance $instance to ${rate[$rate]}" + echo " Setting MulticastGroup.MTU for FM instance $instance to ${mtu[$mtu]}" + if [ $instance -eq 0 ] + then + echo "SM_0_def_mc_mtu=$mtu" >> $TEMP + echo "SM_0_def_mc_rate=${rate[$rate]}" >> $TEMP + else + echo "SM_${instance}_def_mc_create=0x1" >> $TEMP + #echo "SM_${instance}_def_mc_pkey=0xffff" >> $TEMP + echo "SM_${instance}_def_mc_mtu=$mtu" >> $TEMP + echo "SM_${instance}_def_mc_rate=${rate[$rate]}" >> $TEMP + #echo "SM_${instance}_def_mc_sl=0x0" >> $TEMP + echo "SM_${instance}_def_mc_qkey=0x0" >> $TEMP + echo "SM_${instance}_def_mc_fl=0x0" >> $TEMP + echo "SM_${instance}_def_mc_tc=0x0" >> $TEMP + fi + done +fi + +print_separator +echo "The FM supports failover. The FM to be preferred as the primary can be" +echo "selected per FM instance." +echo "If no preferred primary is selected, FMs will negotiate based on HFI GUIDs." +get_yes_no "Do you want to configure a preferred primary or secondary FM" "n" +if [ $ans -eq 1 ] +then + if [ $num_instances -eq 1 ] + then + ans=1 + else + get_yes_no "Will the same FM Failover Priority be used for $fm_allinstances" "y" + fi + if [ $ans -eq 1 ] + then + get_yes_no "Will this FM be the preferred primary" "y" + if [ $ans -eq 1 ] + then + set_instance_priority 0 8 # sets for all instances + echo " Setting Priority of SM and PM to 8" + else + set_instance_priority 0 1 # sets for all instances + echo " Setting Priority of SM and PM to 1" + fi + else + for instance in $instances + do + get_yes_no "Will FM instance $instance (${fm_name[$instance]}) (${fm_device[$instance]}) be the preferred primary" "y" + if [ $ans -eq 1 ] + then + echo " Setting Priority of FM instance $instance SM and PM to 8" + set_instance_priority $instance 8 # sets for all instances + else + echo " Setting Priority of FM instance $instance SM and PM to 1" + set_instance_priority $instance 1 # sets for all instances + fi + done + fi +fi + +print_separator +echo "The FM supports sticky failover. When enabled Sticky failover will" +echo "prevent a master FM from relinquishing control even if the preferred" +echo "primary FM comes online. This can prevent situations where a bouncing" +echo "preferred primary repeatedly takes over then fails." +get_yes_no "Should Sticky Failover be enabled" "n" +if [ $ans -eq 1 ] +then + echo "SM_0_elevated_priority=14" >> $TEMP # sets for all instances + echo "PM_0_elevated_priority=14" >> $TEMP # sets for all instances + #echo "BM_0_elevated_priority=14" >> $TEMP # sets for all instances + #echo "FE_0_elevated_priority=14" >> $TEMP # sets for all instances + echo " Setting ElevatedPriority of SM and PM to 14" +fi + +print_separator +echo "Each fabric in a cluster must have a unique 64 bit subnet prefix." +echo "The subnet prefix must be consistently configured on all FMs which" +echo "manage the given fabric (eg. on the primary and secondaries)." +echo "To simplify input, you will be prompted for the upper bits for the cluster" +echo "then you will be prompted for the lower bits for each instance." +echo "The two values will be ORed together to form the subnet prefix for each fabric." +get_string "Subnet Prefix upper bits for cluster" "0xfe80000000000000" +upper=$ans +for instance in $instances +do + if [ $num_instances -eq 1 ] + then + default="0x0" + else + default="0x100$instance" + fi + get_string "Subnet Prefix lower bits for FM instance $instance (${fm_name[$instance]}) (${fm_device[$instance]})" "$default" + prefix=$(perl -e "use bignum; printf '0x%016Lx', $upper | $ans;") + echo " Setting SubnetPrefix of FM instance $instance to $prefix" + echo "SM_${instance}_gidprefix=$prefix" >> $TEMP +done + +print_separator +echo "The Fabric Manager includes a Performance Manager (PM) which can" +echo "monitor the data movement and error counters in all devices." +echo "The PM monitors the counters periodically and computes the delta for counters." +echo "If the PM Sweep Interval is set to 0, no automatic sweeps occur." +echo "The PM SweepInterval must be >0 when using tools such as opatop." +get_number "PM Sweep Interval in seconds" 10 +echo " Setting Pm.SweepInterval to $ans" +echo "PM_0_SweepInterval=$ans" >> $TEMP # sets for all instances + +if [ $ans -ne 0 ] +then + print_separator + echo "When a port exceeds the threshold for Integrity, Security or Routing errors" + echo "a message is logged." + echo "A Threshold can be configured to limit the number of such messages per sweep." + echo "This Threshold can help to avoid excessive messages." + get_number "PM Error Threshold Exceeded Log Message Limit" 10 + echo " Setting ThresholdsExceededMsgLimit.Integrity to $ans" + echo "PM_0_ThresholdsExceededMsgLimit_Integrity=$ans" >> $TEMP # sets for all instances + echo " Setting ThresholdsExceededMsgLimit.Security to $ans" + echo "PM_0_ThresholdsExceededMsgLimit_Security=$ans" >> $TEMP # sets for all instances + echo " Setting ThresholdsExceededMsgLimit.Routing to $ans" + echo "PM_0_ThresholdsExceededMsgLimit_Routing=$ans" >> $TEMP # sets for all instances + + print_separator + echo "The PM can retain some recent history in memory." + echo "This history can then be viewed in tools such as opatop." + echo "For each historical sweep both the topology and performance data is retained." + echo "Each such dataset is referred to as an Image" + echo "The values will be adjusted based on the number of concurrent PA clients expected." + if [ "$esm" = y ] + then + get_number "How many concurrent clients are expected?" 3 3 4 + else + get_number "How many concurrent clients are expected?" 3 3 20 + fi + echo " Setting Pm.MaxClients to $ans" + echo "PM_0_MaxClients=$ans" >> $TEMP # sets for all instances + + # FF must be >= MaxClients*2 -1 + # Total must be >= FF+2 + min_ff=$(($ans * 2 -1)) + min_tot=$((min_ff + 2)) + def_tot=10 + [ $min_tot -gt $def_tot ] && def_tot=$min_tot + if [ "$esm" = y ] + then + get_number "How many images should be retained?" $def_tot $min_tot 10 + else + get_number "How many images should be retained?" $def_tot $min_tot 100000 + fi + + echo " Setting Pm.TotalImages to $ans" + echo "PM_0_TotalImages=$ans" >> $TEMP # sets for all instances + + # pick a reasonable number of freeze frame images + if [ "$ans" -le 10 ] + then + ff=$min_ff # base on MaxClients + elif [ "$ans" -lt 50 ] + then + ff=$(($ans / 2)) # have a reasonably large supply + [ $ff -lt 8 ] && ff=8 # make sure 11-16 have as much as 10 images + else + ff=25 + fi + [ $ff -lt $min_ff ] && ff=$min_ff + ans=$ff + + # pick a reasonable number of freeze frame images + #if [ "$ans" -le 10 ] + #then + # ff=$(($ans -2)) # allocate max allowed + #elif [ "$ans" -lt 50 ] + #then + # ff=$(($ans / 2)) # have a reasonably large supply + # [ $ff -lt 8 ] && ff=8 # make sure 11-16 have as much as 10 images + #else + # ff=25 + #fi + #ans=$ff + + #print_separator + #echo "Tools such as opatop freeze historical images when viewed and can" + #echo "also bookmark images for later viewing during a session". + #echo "Multiple concurrent opatop sessions could each have unique frozen images." + #if [ "$esm" = y ] + #then + # get_number "How many frozen/bookmarked images should be allowed" 5 2 8 + #else + # get_number "How many frozen/bookmarked images should be allowed" 5 2 99998 + #fi + echo " Setting Pm.FreezeFrameImages to $ans" + echo "PM_0_FreezeFrameImages=$ans" >> $TEMP # sets for all instances + +fi + +print_separator +get_yes_no "Should SslSecurityEnable be enabled" "y" +if [ "$ans" -eq 0 ] +then + echo " Setting SslSecurityEnable to 0" + echo "FE_0_ssl_security_enable=0" >> $TEMP +fi + +print_separator +echo "By default, VirtualFabrics set their QoS parameters within" +echo "their own configuration. Alternatively, QOSGroups can be enabled." +echo "This creates a set of QoS policies the fabric will adhere to," +echo "and each VirtualFabric will associate with one of the enabled" +echo "QOSGroups. This is ideal for Multi-Tenant environments, where" +echo "VirtualFabrics can be added and removed dynamically as long as they" +echo "specify an existing QOSGroup." +if [ "$esm" = y ] +then + echo "Warning: Dynamic configuration is not supported on ESM" +fi +get_yes_no "Should QOSGroups be enabled" "n" +if [ "$ans" -eq 1 ] +then + echo " Configuring VirtualFabrics to use QOSGroups" + echo "SM_0_mt_enable=yes" >> $TEMP +fi + +print_separator +$tooldir/config_convert $TEMP $OPAFM_SRC > $dest_file +echo "Generated $dest_file" +if [ "$esm" = y ] +then + echo "To activate this configuration, $dest_file must be transferred to" + echo "the chassis and the FM must be restarted." + echo "The fastfabric TUI provides an easy way to do this." +elif [ "$dest_file" != "$CONFIG_XML" ] +then + echo "To activate this configuration, $dest_file must be copied to" + echo "$CONFIG_XML and the FM must be restarted." +else + echo "To activate this configuration, the FM must be restarted." +fi +rm -f $TEMP diff --git a/Esm/ib/src/linux/startup/fm_config/opafmconfigpp.sh b/Esm/ib/src/linux/startup/fm_config/opafmconfigpp.sh new file mode 100755 index 0000000..d257d35 --- /dev/null +++ b/Esm/ib/src/linux/startup/fm_config/opafmconfigpp.sh @@ -0,0 +1,205 @@ +#!/bin/bash +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2018, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] +PROG_NAME=$0 + +TEMP_CONFIG="$(mktemp opafm-XXXXXX.xml)" +TEMP_CHECK="check.${TEMP_CONFIG}.out" + +Handle_Exit() +{ + RET=$? + if [ $RET -ne 2 ]; then + rm -f $TEMP_CONFIG $TEMP_CHECK + fi +} +Handle_Signal() +{ + rm -f $TEMP_CONFIG $TEMP_CHECK + exit 1 +} +trap "Handle_Exit" EXIT +trap "Handle_Signal" SIGHUP SIGTERM SIGINT + +PP_FILE=/etc/opa-fm/opafm_pp.xml +OUTPUT_XML=/etc/opa-fm/opafm.xml +BACKUP=0 +SKIP_CHECK=0 +FORCE_WR=0 + +Usage() +{ + echo "Usage: $(basename $PROG_NAME) [-p ppfile] [-o output] [-b] [-s] [-f] [-h]" >&2 + echo " " >&2 + echo " -p File to preprocess [Default=\"${PP_FILE}\"]" >&2 + echo " -o Output XML file [Default=\"${OUTPUT_XML}\"]" >&2 + echo " -b Backup old output file if exists [Default=${BACKUP}]" >&2 + echo " -s Skip running Config Check on output [Default=${SKIP_CHECK}]" >&2 + echo " -f Force overwrite of old output file [Default=${FORCE_WR}]" >&2 + echo " -h Print this help message" >&2 + echo "Notes:" >&2 + echo " Output file will contain 2 comments at the top to indicate it was" >&2 + echo " generated and the local time it was generated" >&2 + echo " The special include comments should follow this style: " >&2 + echo " " >&2 + echo " " >&2 + echo " Examples: " >&2 + echo " " >&2 + echo " " >&2 + echo " " >&2 + echo " " >&2 + echo " Include comments will be replaced with contents of given directories" >&2 + echo " " >&2 + + exit 1 +} + +# This function will parse the given file (ARG 1) and echo to stdout +Parse_PP() +{ + if [ ! -f "$1" ]; then + echo "Error: preprocess file could not be found: \"$1\"" >&2 + exit 1 + fi + + echo "Parsing $1 ..." >&2 + + # Keep first line at top of file + sed -n "1p" $1 + + # Add Generated Comments to the Top of the File + echo "" + echo "" + + # start at line 2 + LN=2 + + # Parse the rest of the pp file + sed "1d" $1 | while IFS= read -r line; do + + DG_DIR=$(echo $line | \ + sed -n "s/^[[:space:]]*<[!]--[[:space:]]*INCLUDE:DG_DIR=\(.*\)-->/\1/p" | \ + sed "s/[[:space:]]*$//") # Trailing whitespace needs to be run again + if [ -d "$DG_DIR" ]; then + echo "Found DG_DIR at line $LN, Adding DeviceGroups from \"$DG_DIR\"" >&2 + cat "${DG_DIR}"/* + continue + fi + VF_DIR=$(echo $line | \ + sed -n "s/^[[:space:]]*<[!]--[[:space:]]*INCLUDE:VF_DIR=\(.*\)-->/\1/p" | \ + sed "s/[[:space:]]*$//") + if [ -d "$VF_DIR" ]; then + echo "Found VF_DIR at line $LN, Adding VirtualFabrics from \"$VF_DIR\"" >&2 + cat "${VF_DIR}"/* + continue + fi + echo "$line" + LN=$((LN +1)) + done +} + +# This function will attempt to copy the Temp XML file (ARG 2) to the +# Output XML file (ARG 3) and if needed backup (ARG 1) the old Output XML file +Config_Copy() +{ + BK=$1 + IN_XML=$2 + OUT_XML=$3 + + if [ -f "$OUT_XML" -a $BK -eq 1 ]; then + echo "Backing up old $OUT_XML to ${OUT_XML}.bak" + cp "$OUT_XML" "${OUT_XML}.bak" + fi + cp "$IN_XML" "$OUT_XML" +} + +while getopts ":hp:o:bfs" opt; do + case $opt in + h) + Usage + ;; + p) + PP_FILE=$OPTARG + ;; + o) + OUTPUT_XML=$OPTARG + ;; + b) + BACKUP=1 + ;; + f) + FORCE_WR=1 + ;; + s) + SKIP_CHECK=1 + ;; + ?) + echo "Error: $OPTARG is not a valid argument!" >&2 + Usage + esac +done +shift $((OPTIND -1)) + +if [ ! -f "$PP_FILE" ]; then + echo "Error: preprocess file not found: \"$PP_FILE\"" >&2 + Usage +fi + +while [ $FORCE_WR -eq 0 -a $BACKUP -eq 0 -a -f "$OUTPUT_XML" ]; do + echo "Warning: $OUTPUT_XML will be overwritten!" + echo -n "Do you want to continue? [y/n] " + read INPUT + if [[ $INPUT =~ [nN] ]]; then + exit 0 + elif [[ $INPUT =~ [yY] ]]; then + break + fi +done + +Parse_PP "$PP_FILE" > "$TEMP_CONFIG" + +if [ $SKIP_CHECK -ne 1 ]; then + echo "Checking Config ..." >&2 + # Check Config (-s/strict = MC and VF checking) + /usr/lib/opa-fm/bin/config_check -c "$TEMP_CONFIG" -s 2>&1 | tee "$TEMP_CHECK" + # Get return code from config_check + RET=${PIPESTATUS[0]} + if [ $RET -eq 0 ]; then + echo "Config Check Passed!" + else + echo "Error: Config Check Failed: Review \"$TEMP_CHECK\"" >&2 + exit 2 + fi +fi + +Config_Copy $BACKUP "$TEMP_CONFIG" "$OUTPUT_XML" + +exit 0 diff --git a/Esm/ib/src/pm/include/pa_access.h b/Esm/ib/src/pm/include/pa_access.h new file mode 100644 index 0000000..e610981 --- /dev/null +++ b/Esm/ib/src/pm/include/pa_access.h @@ -0,0 +1,390 @@ +/* BEGIN_ICS_COPYRIGHT3 **************************************** + +Copyright (c) 2015-2018, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT3 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +#ifndef _PAACCESS_H +#define _PAACCESS_H + +#include + +#include +#include +#include +#include +#include +#include +#define _GNU_SOURCE + +#include +#include +#include "pm_topology.h" + +#ifdef __cplusplus +extern "C" { +#endif + +// DEFINES + +#define BAD_IMAGE_ID (uint64)-1 + +#define PA_INC_COUNTER_NO_OVERFLOW(cntr, max) do { if (cntr >= max) { cntr = max; } else { cntr++; } } while(0) + +// DATA TYPES + +typedef struct _pmNameListEntry_s { + char Name[STL_PM_GROUPNAMELEN]; // \0 terminated +} PmNameListEntry_t; + +typedef struct _pmGroupList_s { + uint32 NumGroups; + PmNameListEntry_t *GroupList; +} PmGroupList_t; + +typedef struct _pmGroupInfo_s { + char groupName[STL_PM_GROUPNAMELEN]; // \0 terminated + uint32 NumIntPorts; + uint32 NumExtPorts; + PmUtilStats_t IntUtil; // when both ports in group + PmUtilStats_t SendUtil; // send from group to outside + PmUtilStats_t RecvUtil; // recv by group from outside + // for Internal (in-group) we count one each port (both are in group) + // for External (between-group), we count worst of our port and its neighbor + PmErrStats_t IntErr;// in group + PmErrStats_t ExtErr;// between groups + uint8 MinIntRate; + uint8 MaxIntRate; + uint8 MinExtRate; + uint8 MaxExtRate; +} PmGroupInfo_t; + +typedef struct _pmPortConfig_s { + STL_LID lid; + uint8 portNum; + uint8 reserved2[3]; + uint64 guid; + char nodeDesc[64]; // can be 64 char w/o \0 +} PmPortConfig_t; + +typedef struct _pmGroupConfig_s { + char groupName[STL_PM_GROUPNAMELEN]; // \0 terminated + uint32 NumPorts; + uint32 portListSize; + PmPortConfig_t *portList; +} PmGroupConfig_t; + +typedef struct _pmFocusPortEntry_s { + STL_LID lid; + uint8 portNum; + uint8 rate; // IB_STATIC_RATE + uint8 maxVlMtu; // enum STL MTU + uint8 neighborPortNum; + STL_LID neighborLid; + uint8 localStatus:4; + uint8 neighborStatus:4; + uint8 reserved[3]; + uint64 value[MAX_NUM_FOCUS_PORT_TUPLES]; + uint64 guid; + char nodeDesc[64]; // can be 64 char w/o \0 + uint64 neighborValue[MAX_NUM_FOCUS_PORT_TUPLES]; + uint64 neighborGuid; + char neighborNodeDesc[64]; // can be 64 char w/o \0 +} PmFocusPortEntry_t; + +typedef struct _pmFocusPorts_s { + char name[STL_PM_GROUPNAMELEN]; // \0 terminated + uint32 NumPorts; + uint32 portCntr; + PmFocusPortEntry_t *portList; +} PmFocusPorts_t; + +typedef struct _focusArrayItem_s { + uint64 localValue; + uint64 neighborValue; + STL_LID localLID; + STL_LID neighborLID; + PmPort_t *localPort; + PmPort_t *neighborPort; +} focusArrayItem_t; + +typedef struct smInfo_s { + STL_LID smLid; // implies port, 0 if empty record + uint8 priority:4; // present priority + uint8 state:4; // present state + uint8 portNumber; + uint8 reserved2; + uint64 smPortGuid; + char smNodeDesc[64]; // can be 64 char w/o \0 +} PmSmInfo_t; + +typedef struct _pmImageInfo_s { + uint64 sweepStart; + uint32 sweepDuration; + uint16 numHFIPorts; +// TFI not included in Gen1 +// uint16 numTFIPorts; + uint16 numSwitchNodes; + uint32 numSwitchPorts; + uint32 numLinks; + uint32 numSMs; + uint32 numNoRespNodes; + uint32 numNoRespPorts; + uint32 numSkippedNodes; + uint32 numSkippedPorts; + uint32 numUnexpectedClearPorts; + uint32 imageInterval; + PmSmInfo_t SMInfo[2]; +} PmImageInfo_t; + +typedef struct _pmVFList_s { + uint32 NumVFs; + PmNameListEntry_t *VfList; // \0 terminated +} PmVFList_t; + +typedef struct _pmVFConfig_s { + char vfName[STL_PM_VFNAMELEN]; // \0 terminated + uint32 NumPorts; + uint32 portListSize; + PmPortConfig_t *portList; +} PmVFConfig_t; + +typedef struct _pmVFInfo_s { + char vfName[STL_PM_VFNAMELEN]; // \0 terminated + uint32 NumPorts; + PmUtilStats_t IntUtil; // when both ports in group + PmErrStats_t IntErr; + uint8 MinIntRate; + uint8 MaxIntRate; +} PmVFInfo_t; + +typedef struct _pmNodeInfo_s { + STL_LID nodeLid; + uint8 nodeType; + uint8 reserved2[3]; + uint64 nodeGuid; + uint64 portSelectMask[4]; + char nodeDesc[64]; // can be 64 char w/o \0 +} PmNodeInfo_t; + + +typedef struct _pmGroupNodeInfo_s { + char groupName[STL_PM_GROUPNAMELEN]; // \0 terminated + uint32 NumNodes; + PmNodeInfo_t *nodeList; +} PmGroupNodeInfo_t; + +typedef struct _pmLinkInfo_s { + STL_LID fromLid; + STL_LID toLid; + uint8 fromPort; + uint8 toPort; + uint8 mtu:4; + uint8 activeSpeed:4; + uint8 txLinkWidthDowngradeActive:4; + uint8 rxLinkWidthDowngradeActive:4; + uint8 localStatus:4; + uint8 neighborStatus:4; + uint8 reserved2[3]; +} PmLinkInfo_t; + + +typedef struct _pmGroupLinkInfo_s { + char groupName[STL_PM_GROUPNAMELEN]; // \0 terminated + uint32 NumLinks; + PmLinkInfo_t *linkInfoList; +} PmGroupLinkInfo_t; + + +// FUNCTION PROTOTYPES + +/* BEGIN pa_utility.c */ +const char *FSTATUS_ToString(FSTATUS status); + +FSTATUS FindImage(Pm_t *pm, uint8 type, STL_PA_IMAGE_ID_DATA imageId, uint32 *imageIndex, + uint64 *retImageId, PmHistoryRecord_t **record, const char **msg, uint8 *clientId, + PmCompositeImage_t **cimg); +FSTATUS FindPmImage(const char *func, Pm_t *pm, STL_PA_IMAGE_ID_DATA req_img, + STL_PA_IMAGE_ID_DATA *rsp_img, PmImage_t **pm_image, uint32 *imageIndex, + boolean *requiresLock); + +int getCachedCimgIdx(Pm_t *pm, PmCompositeImage_t *cimg); +uint64 BuildFreezeFrameImageId(Pm_t *pm, uint32 freezeIndex, uint8 clientId, uint32 *imageTime); +FSTATUS LocateGroup(PmImage_t *pmimagep, const char *groupName, int *groupIndex); +FSTATUS LocateVF(PmImage_t *pmimagep, const char *vfName, int *vfIdx); +/* END pa_utility.c */ + +// Note - API expects caller to define a Pm_t structure, which apps will do for now +// Later, PM will handle this, and the parameter can be removed + +// get group list - caller declares Pm_T and PmGroupList_t, and passes pointers +FSTATUS paGetGroupList(Pm_t *pm, PmGroupList_t *GroupList, STL_PA_IMAGE_ID_DATA imageId, + STL_PA_IMAGE_ID_DATA *returnImageId); + +// get group info - caller declares Pm_T and PmGroupInfo_t, and passes pointers +FSTATUS paGetGroupInfo(Pm_t *pm, char *groupName, PmGroupInfo_t *pmGroupInfo, + STL_PA_IMAGE_ID_DATA imageId, STL_PA_IMAGE_ID_DATA *returnImageId); + +// get group config - caller declares Pm_T and PmGroupConfig_t, and passes pointers +FSTATUS paGetGroupConfig(Pm_t *pm, char *groupName, PmGroupConfig_t *pmGroupConfig, + STL_PA_IMAGE_ID_DATA imageId, STL_PA_IMAGE_ID_DATA *returnImageId); + +// get group node info - caller declares Pm_T and PmGroupConfig_t, and passes pointers +FSTATUS paGetGroupNodeInfo(Pm_t *pm, char *groupName, uint64 nodeGUID, STL_LID nodeLID, + char *nodeDesc, PmGroupNodeInfo_t *pmGroupNodeInfo, STL_PA_IMAGE_ID_DATA imageId, + STL_PA_IMAGE_ID_DATA *returnImageId); + +// get group link info - caller declares Pm_T and PmGroupConfig_t, and passes pointers +FSTATUS paGetGroupLinkInfo(Pm_t *pm, char *groupName, STL_LID inputLID, uint8 inputPort, + PmGroupLinkInfo_t *pmGroupLinkInfo, STL_PA_IMAGE_ID_DATA imageId, STL_PA_IMAGE_ID_DATA *returnImageId); + +// get port stats - caller declares Pm_T and PmCompositePortCounters_t +// delta - 1 requests delta counters, 0 gets raw total +// userCntrs - 1 requests PA user controled counters, 0 gets Pm Controlled Image Counters. if 1 delta and ofset must be 0 +FSTATUS paGetPortStats(Pm_t *pm, STL_LID lid, uint8 portNum, PmCompositePortCounters_t *portCountersP, + uint32 delta, uint32 userCntrs, STL_PA_IMAGE_ID_DATA imageId, uint32 *flagsp, + STL_PA_IMAGE_ID_DATA *returnImageId); + +// Clear Running totals for a port. This simulates a PMA clear so +// that tools like opareport can work against the Running totals +FSTATUS paClearPortStats(Pm_t *pm, STL_LID lid, uint8 portNum, + CounterSelectMask_t select); + +// Clear Running totals for all Ports. This simulates a PMA clear so +// that tools like opareport can work against the Running totals +FSTATUS paClearAllPortStats(Pm_t *pm, CounterSelectMask_t select); + +FSTATUS paFreezeFrameRenew(Pm_t *pm, STL_PA_IMAGE_ID_DATA *imageId); + +FSTATUS paFreezeFrameRelease(Pm_t *pm, STL_PA_IMAGE_ID_DATA *imageId); + +FSTATUS paFreezeFrameCreate(Pm_t *pm, STL_PA_IMAGE_ID_DATA imageId, STL_PA_IMAGE_ID_DATA *retImageId); + +FSTATUS paFreezeFrameMove(Pm_t *pm, STL_PA_IMAGE_ID_DATA ffImageId, STL_PA_IMAGE_ID_DATA imageId, + STL_PA_IMAGE_ID_DATA *returnImageId); + +FSTATUS paGetFocusPorts(Pm_t *pm, char *groupName, PmFocusPorts_t *pmFocusPorts, + STL_PA_IMAGE_ID_DATA imageId, STL_PA_IMAGE_ID_DATA *returnImageId, uint32 select, + uint32 start, uint32 range); + +FSTATUS paGetExtFocusPorts(Pm_t *pm, char *groupName, PmFocusPorts_t *pmFocusPorts, + STL_PA_IMAGE_ID_DATA imageId, STL_PA_IMAGE_ID_DATA *returnImageId, uint32 select, + uint32 start, uint32 range); + +FSTATUS paGetMultiFocusPorts(Pm_t *pm, char *groupName, PmFocusPorts_t *pmFocusPorts, + STL_PA_IMAGE_ID_DATA imageId, STL_PA_IMAGE_ID_DATA *returnImageId, uint32 start, + uint32 range, STL_FOCUS_PORT_TUPLE *tple, uint8 oper); + +FSTATUS paGetImageInfo(Pm_t *pm, STL_PA_IMAGE_ID_DATA imageId, PmImageInfo_t *imageInfo, + STL_PA_IMAGE_ID_DATA *returnImageId); + +// get vf list - caller declares Pm_T and PmGroupList_t, and passes pointers +FSTATUS paGetVFList(Pm_t *pm, PmVFList_t *pmVFList, STL_PA_IMAGE_ID_DATA imageId, + STL_PA_IMAGE_ID_DATA *returnImageId); + +// get vf config - caller declares Pm_T and PmVFConfig_t, and passes pointers +FSTATUS paGetVFConfig(Pm_t *pm, char *vfName, uint64 vfSid, PmVFConfig_t *pmVFConfig, + STL_PA_IMAGE_ID_DATA imageId, STL_PA_IMAGE_ID_DATA *returnImageId); + +// get vf info - caller declares Pm_T and PmGroupInfo_t, and passes pointers +FSTATUS paGetVFInfo(Pm_t *pm, char *vfName, PmVFInfo_t *pmVFInfo, STL_PA_IMAGE_ID_DATA imageId, + STL_PA_IMAGE_ID_DATA *returnImageId); + +// get vf port stats - caller declares Pm_T and PmCompositeVLCounters_t +// delta - 1 requests delta counters, 0 gets raw total +// userCntrs - 1 requests PA user controled counters, 0 gets Pm Controlled Image Counters. if 1 delta and ofset must be 0 +FSTATUS paGetVFPortStats(Pm_t *pm, STL_LID lid, uint8 portNum, char *vfName, + PmCompositeVLCounters_t *vfPortCountersP, uint32 delta, uint32 userCntrs, + STL_PA_IMAGE_ID_DATA imageId, uint32 *flagsp, STL_PA_IMAGE_ID_DATA *returnImageId); + +FSTATUS paClearVFPortStats(Pm_t *pm, STL_LID lid, uint8 portNum, STLVlCounterSelectMask select, + char *vfName); + +FSTATUS paGetVFFocusPorts(Pm_t *pm, char *vfName, PmFocusPorts_t *pmVFFocusPorts, + STL_PA_IMAGE_ID_DATA imageId, STL_PA_IMAGE_ID_DATA *returnImageId, uint32 select, + uint32 start, uint32 range); + +FSTATUS paGetExtVFFocusPorts(Pm_t *pm, char *vfName, PmFocusPorts_t *pmVFFocusPorts, + STL_PA_IMAGE_ID_DATA imageId, STL_PA_IMAGE_ID_DATA *returnImageId, uint32 select, + uint32 start, uint32 range); + +static inline boolean pa_valid_port(PmPort_t *pmportp, boolean sth) { + if (!pmportp || + /* if this is a sth image, the port may be 'empty' but not null + 'Empty' ports should be excluded from the count, and can be + indentified by their having a port num and guid of 0 */ + (sth && !pmportp->guid && !pmportp->portNum)) return FALSE; + return TRUE; +} + +static inline uint8_t pa_get_port_status(PmPort_t *pmportp, uint32_t imageIndex) +{ + PmPortImage_t *portImage; + if (!pmportp) { + return STL_PA_FOCUS_STATUS_TOPO_FAILURE; + } else if (pmportp->u.s.PmaAvoid) { + // This means the PM was told to ignore this port during a sweep + return STL_PA_FOCUS_STATUS_PMA_IGNORE; + } else { + portImage = &pmportp->Image[imageIndex]; + if (portImage->u.s.queryStatus != PM_QUERY_STATUS_OK) { + // This means there was a failure during the PM sweep when querying this port + return STL_PA_FOCUS_STATUS_PMA_FAILURE; + } else if (portImage->u.s.UnexpectedClear) { + // This means unexpected clear was set + return STL_PA_FOCUS_STATUS_UNEXPECTED_CLEAR; + } + } + return STL_PA_FOCUS_STATUS_OK; +} + +/* PA STH MACROs for loops */ +#define for_some_pmports_sth(PMNODE, PMPORT, PORTNUM, START, END, STH_BOOL) \ + for (PORTNUM = START, PMPORT = pm_get_port(PMNODE, PORTNUM); \ + PORTNUM <= END; \ + ++PORTNUM, PMPORT = pm_get_port(PMNODE, PORTNUM)) \ + if (pa_valid_port(PMPORT, STH_BOOL)) + +#define for_all_pmports_sth(PMNODE, PMPORT, PORTNUM, STH_BOOL) \ + for_some_pmports_sth(PMNODE, PMPORT, PORTNUM, pm_get_port_idx(PMNODE), (PMNODE)->numPorts, STH_BOOL) + +/** Example usage: + * + * for_all_pmnodes(pmimagep, pmnodep lid) { + * for_all_pmports(pmnodep, pmportp, portnum, sth) { + * portImage = &pmportp->Image[imageIndex]; + * // DO WORK + * } + * } + */ +#ifdef __cplusplus +}; +#endif + +#endif /* _PAACCESS_H */ + diff --git a/Esm/ib/src/pm/include/pa_l.h b/Esm/ib/src/pm/include/pa_l.h new file mode 100644 index 0000000..72b0531 --- /dev/null +++ b/Esm/ib/src/pm/include/pa_l.h @@ -0,0 +1,97 @@ +/* BEGIN_ICS_COPYRIGHT2 **************************************** + +Copyright (c) 2015-2018, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT2 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ +#ifndef _PA_L_H_ +#define _PA_L_H_ + +#include "ib_const.h" +#include "stl_types.h" +#include "cs_g.h" +#include "cs_hashtable.h" + + +#define PA_SRV_MAX_RECORD_SZ 512 + +typedef struct pa_cntxt { + uint64_t tstamp ; + uint64_t tid ; // Tid for hash table search + STL_LID lid ; // Lid for hash table search + uint16_t method; // initial method requested by initiator + IBhandle_t sendFd; // mai handle to use for sending packets (fd_sa for 1st seg and fd_pa_w threafter) + uint8_t hashed ; // Entry is inserted into the hash table + uint32_t ref ; // Reference count for the structure + uint32_t reqDataLen; // length of the getMulti request MAD + char* reqData ; // Data pointer for input getMulti MAD + char* data ; // Data pointer for MAD rmpp response + uint32_t len ; // Length of the MAD response + uint16_t attribLen; // num 8-byte words from start of one attrib to start of next + Mai_t mad ; + /* 1.1 related fields */ + uint32_t WF; // Window First: segNum that is first packet in current window + uint32_t WL; // Window Last: segNum that is last packet in current window + uint32_t NS; // Next segNum to be tranmitted by Sender + uint32_t ES; // segNum expected next (Receiver side) + uint16_t isDS; // Double sided getMulti in effect + uint16_t reqInProg; // receipt of request in progress + uint64_t RespTimeout;// current response timeout value (13.6.3.1) + uint64_t tTime; // total transaction timeout value (13.6.3.2) + uint16_t retries; // retry count + uint16_t last_ack; // last segment number acked + uint16_t segTotal; // total segments in response + struct pa_cntxt *next ; // Link List next pointer + struct pa_cntxt *prev ; // Link List prev pointer + uint8_t chkSum; // checksum of rmpp response + //SACacheEntry_t *cache; // pointer to cache structure if applicable + Status_t (*freeDataFunc)(struct pa_cntxt *); // func to call to free data. may + // either free locally allocated data, or defer to + // the cache mechanism to decref the cache + //Status_t (*processFunc)(Mai_t *, struct pa_cntxt *); // function to call + // to process the incoming packet. +} pa_cntxt_t ; + +typedef enum { + ContextAllocated = 1, // new context allocated + ContextNotAvailable = 2, // out of context + ContextExist = 3, // general duplicate request + ContextExistGetMulti = 4 // existing getMult request +} PAContextGet_t; + +extern uint32_t pa_max_cntxt; +extern uint32_t pa_data_length; + +extern void pa_delete_filters(void); +extern Status_t pa_process_mad(Mai_t *maip, pa_cntxt_t* sa_cntxt); +extern pa_cntxt_t * pa_mngr_get_cmd(Mai_t * mad, uint8_t * processMad); +extern Status_t pa_mngr_open_cnx(void); +extern void pa_mngr_close_cnx(void); +extern void pa_main_kill(void); + +#endif // _PA_L_H_ + diff --git a/Esm/ib/src/pm/include/pa_server.h b/Esm/ib/src/pm/include/pa_server.h new file mode 100644 index 0000000..5d52f47 --- /dev/null +++ b/Esm/ib/src/pm/include/pa_server.h @@ -0,0 +1,59 @@ +/* BEGIN_ICS_COPYRIGHT3 **************************************** + +Copyright (c) 2015-2018, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT3 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +#ifndef _PASERVER_H +#define _PASERVER_H + +Status_t pa_getClassPortInfoResp(Mai_t *maip, pa_cntxt_t* pa_cntxt); +Status_t pa_getGroupListResp(Mai_t *maip, pa_cntxt_t* pa_cntxt); +Status_t pa_getPortCountersResp(Mai_t *maip, pa_cntxt_t* pa_cntxt); +Status_t pa_getGroupInfoResp(Mai_t *maip, pa_cntxt_t* pa_cntxt); +Status_t pa_getGroupConfigResp(Mai_t *maip, pa_cntxt_t* pa_cntxt); +Status_t pa_getGroupNodeInfoResp(Mai_t *maip, pa_cntxt_t* pa_cntxt); +Status_t pa_getGroupLinkInfoResp(Mai_t *maip, pa_cntxt_t* pa_cntxt); +Status_t pa_clrPortCountersResp(Mai_t *maip, pa_cntxt_t* pa_cntxt); +Status_t pa_clrAllPortCountersResp(Mai_t *maip, pa_cntxt_t* pa_cntxt); +Status_t pa_getPmConfigResp(Mai_t *maip, pa_cntxt_t* pa_cntxt); +Status_t pa_freezeImageResp(Mai_t *maip, pa_cntxt_t* pa_cntxt); +Status_t pa_releaseImageResp(Mai_t *maip, pa_cntxt_t* pa_cntxt); +Status_t pa_renewImageResp(Mai_t *maip, pa_cntxt_t* pa_cntxt); +Status_t pa_getFocusPortsResp(Mai_t *maip, pa_cntxt_t* pa_cntxt); +Status_t pa_getFocusPortsMultiSelectResp(Mai_t *maip, pa_cntxt_t* pa_cntxt); +Status_t pa_getImageInfoResp(Mai_t *maip, pa_cntxt_t* pa_cntxt); +Status_t pa_moveFreezeImageResp(Mai_t *maip, pa_cntxt_t* pa_cntxt); +Status_t pa_getVFListResp(Mai_t *maip, pa_cntxt_t* pa_cntxt); +Status_t pa_getVFInfoResp(Mai_t *maip, pa_cntxt_t* pa_cntxt); +Status_t pa_getVFConfigResp(Mai_t *maip, pa_cntxt_t* pa_cntxt); +Status_t pa_getVFPortCountersResp(Mai_t *maip, pa_cntxt_t* pa_cntxt); +Status_t pa_clrVFPortCountersResp(Mai_t *maip, pa_cntxt_t* pa_cntxt); +Status_t pa_getVFFocusPortsResp(Mai_t *maip, pa_cntxt_t* pa_cntxt); + +#endif /* _PASERVER_H */ diff --git a/Esm/ib/src/pm/include/pa_sth_old.h b/Esm/ib/src/pm/include/pa_sth_old.h new file mode 100644 index 0000000..a207135 --- /dev/null +++ b/Esm/ib/src/pm/include/pa_sth_old.h @@ -0,0 +1,193 @@ +/* BEGIN_ICS_COPYRIGHT7 **************************************** + +Copyright (c) 2015-2018, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT7 ****************************************/ + +#include "pm_topology.h" + +#include "iba/public/ipackon.h" + +#define MAX_VFABRICS_OLD 32 // MAX_VFABRICS old value + +typedef struct PmUtilStats_oldv10_s { + uint64 TotMBps; + uint64 TotKPps; + uint32 AvgMBps; + uint32 MinMBps; + + uint32 MaxMBps; + uint32 BwPorts[STL_PM_UTIL_BUCKETS]; + uint32 AvgKPps; + + uint32 MinKPps; + uint32 MaxKPps; + + uint16 pmaNoRespPorts; + uint16 topoIncompPorts; + uint32 reserved; +} PACK_SUFFIX PmUtilStats_oldv10_t; +typedef struct ErrorSummary_oldv10_s { + uint32 Integrity; + uint32 Congestion; + uint32 SmaCongestion; + uint32 Bubble; + uint32 Security; + uint32 Routing; + uint16 UtilizationPct10; + uint16 DiscardsPct10; + uint32 Reserved; +} PACK_SUFFIX ErrorSummary_oldv10_t; +typedef struct ErrorBucket_oldv10_s { + uint32 Integrity; + uint32 Congestion; + uint32 SmaCongestion; + uint32 Bubble; + uint32 Security; + uint32 Routing; +} PACK_SUFFIX ErrorBucket_oldv10_t; +typedef struct PmErrStats_oldv10_s { + ErrorSummary_oldv10_t Max; + ErrorBucket_oldv10_t Ports[STL_PM_CATEGORY_BUCKETS]; +} PACK_SUFFIX PmErrStats_oldv10_t; + +typedef struct PmCompositeVF_oldv10_s { + char name[MAX_VFABRIC_NAME]; + uint32 numPorts; + uint8 isActive; + uint8 minIntRate; + uint8 maxIntRate; + uint8 reserved; + PmUtilStats_oldv10_t intUtil; + PmErrStats_oldv10_t intErr; +} PACK_SUFFIX PmCompositeVF_oldv10_t; + +typedef struct PmCompositeGroups_oldv10_s { + char name[STL_PM_GROUPNAMELEN]; + uint32 numIntPorts; + uint32 numExtPorts; + uint8 minIntRate; + uint8 maxIntRate; + uint8 minExtRate; + uint8 maxExtRate; + uint32 reserved; + PmUtilStats_oldv10_t intUtil; + PmUtilStats_oldv10_t sendUtil; + PmUtilStats_oldv10_t recvUtil; + PmErrStats_oldv10_t intErr; + PmErrStats_oldv10_t extErr; +} PACK_SUFFIX PmCompositeGroup_oldv10_t; + +typedef struct PmCompositePort_oldv10_s { + uint64 guid; + union { + uint32 AsReg32; + struct {IB_BITFIELD11(uint32, + active:1, // is port IB_PORT_ACTIVE (SW port 0 fixed up) + mtu:4, // enum IB_MTU - due to actual range, 3 bits + txActiveWidth:4, // LinkWidthDowngrade.txActive + rxActiveWidth:4, // LinkWidthDowngrade.rxActive + activeSpeed:3, // LinkSeed.Active + Initialized:1, // has group membership been initialized + queryStatus:2, // PMA query or clear result + UnexpectedClear:1, // PMA Counters unexpectedly cleared + gotDataCntrs:1, // Were Data Counters updated + gotErrorCntrs:1, // Were Error Counters updated + Reserved:10) + } + s; + } u; + STL_LID neighborLid; + + PORT portNum; + PORT neighborPort; + uint8 InternalBitMask; + uint8 numGroups; + uint8 groups[PM_MAX_GROUPS_PER_PORT]; + + uint32 numVFs; + uint32 vlSelectMask; + + CounterSelectMask_t clearSelectMask; + uint32 reserved99; + + PmCompositeVfvlmap_t compVfVlmap[MAX_VFABRICS_OLD]; + + PmCompositePortCounters_t stlPortCounters; + PmCompositeVLCounters_t stlVLPortCounters[MAX_PM_VLS]; + PmCompositePortCounters_t DeltaStlPortCounters; + PmCompositeVLCounters_t DeltaStlVLPortCounters[MAX_PM_VLS]; +} PACK_SUFFIX PmCompositePort_oldv10_t; + +typedef struct PmCompositeNode_oldv10_s { + uint64 NodeGUID; + uint64 SystemImageGUID; + char nodeDesc[STL_NODE_DESCRIPTION_ARRAY_SIZE]; + STL_LID lid; + uint8 nodeType; + uint8 numPorts; + + uint8 Reserved; + + uint8 reserved; + //PmCompositePort_oldv10_t **ports; +} PACK_SUFFIX PmCompositeNode_oldv10_t; + +typedef struct PmCompositeImage_oldv10_s { + PmFileHeader_t header; + uint64 sweepStart; + uint32 sweepDuration; + uint8 reserved[2]; + uint16 HFIPorts; + uint16 switchNodes; + uint16 reserved2; + uint32 switchPorts; + uint32 numLinks; + uint32 numSMs; + uint32 noRespNodes; + uint32 noRespPorts; + uint32 skippedNodes; + uint32 skippedPorts; + uint32 unexpectedClearPorts; + uint32 downgradedPorts; + uint32 numGroups; + uint32 numVFs; + uint32 numVFsActive; + STL_LID maxLid; + uint32 numPorts; + PmCompositeSmInfo_t SMs[PM_HISTORY_MAX_SMS_PER_COMPOSITE]; + uint32 reserved3; + PmCompositeGroup_oldv10_t allPortsGroup; + PmCompositeGroup_oldv10_t groups[PM_MAX_GROUPS]; + PmCompositeVF_oldv10_t VFs[MAX_VFABRICS_OLD]; + //PmCompositeNode_t **nodes; +} PACK_SUFFIX PmCompositeImage_oldv10_t; + +#include "iba/public/ipackoff.h" + +size_t PaSthOldCompositePortToCurrent(PmCompositePort_t *curr, uint8_t *buf); +size_t PaSthOldCompositeNodeToCurrent(PmCompositeNode_t *curr, uint8_t *buf); +size_t PaSthOldCompositeImageToCurrent(PmCompositeImage_t *curr, uint8_t *buf); diff --git a/Esm/ib/src/pm/include/pm_counters.h b/Esm/ib/src/pm/include/pm_counters.h new file mode 100644 index 0000000..59bf7e1 --- /dev/null +++ b/Esm/ib/src/pm/include/pm_counters.h @@ -0,0 +1,293 @@ +/* BEGIN_ICS_COPYRIGHT2 **************************************** + +Copyright (c) 2015-2018, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT2 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +//===========================================================================// +// +// FILE NAME +// pm_counters.h +// +// DESCRIPTION +// +// DATA STRUCTURES +// None +// +// FUNCTIONS +// None +// +// DEPENDENCIES +// ispinlock.h - for ATOMIC_UINT operations +// +// +//===========================================================================// + + +#ifndef _PM_COUNTERS_H_ +#define _PM_COUNTERS_H_ 1 + +#include "ispinlock.h" +#include "ib_mad.h" +#include "ib_sa.h" +#include "mai_g.h" +#include "iba/stl_pa_priv.h" + +// +// PM Counter Definitions +// +typedef enum _pmCounters { + pmCounterPmSweeps, + pmCounterPmNoRespPorts, + pmCounterPmNoRespNodes, + pmCounterPmUnexpectedClearPorts, + + // Total PM Class Packet Transmits + pmCounterPmPacketTransmits, + + // PMA Retries/Failures + pmCounterPacketRetransmits, + pmCounterPmTxRetriesExhausted, + + // PMA Method/Attributes + pmCounterGetClassPortInfo, // Get(ClassPortInfo) + pmCounterGetPortStatus, // Get(PortStatus) + pmCounterSetClearPortStatus, // Set(ClearPortStatus) + pmCounterGetDataPortCounters, // Get(DataPortCounters) + pmCounterGetErrorPortCounters, // Get(ErrorPortCounters) + pmCounterGetErrorInfo, // Get(ErrorInfo) + pmCounterSetErrorInfo, // Set(ErrorInfo) + + pmCounterRxGetResp, + + // PMA Response Status codes + pmCounterRxPmaMadStatusBusy, + pmCounterRxPmaMadStatusRedirect, + pmCounterRxPmaMadStatusBadClass, + pmCounterRxPmaMadStatusBadMethod, + pmCounterRxPmaMadStatusBadAttr, + pmCounterRxPmaMadStatusBadField, + pmCounterRxPmaMadStatusUnknown, + + // PA Queries + pmCounterPaRxGetClassPortInfo, + pmCounterPaRxGetGrpList, + pmCounterPaRxGetGrpInfo, + pmCounterPaRxGetGrpCfg, + pmCounterPaRxGetPortCtrs, + pmCounterPaRxClrPortCtrs, + pmCounterPaRxClrAllPortCtrs, + pmCounterPaRxGetPmConfig, + pmCounterPaRxFreezeImage, + pmCounterPaRxReleaseImage, + pmCounterPaRxRenewImage, + pmCounterPaRxGetFocusPorts, + pmCounterPaRxGetImageInfo, + pmCounterPaRxMoveFreezeFrame, + pmCounterPaRxGetVFList, + pmCounterPaRxGetVFInfo, + pmCounterPaRxGetVFCfg, + pmCounterPaRxGetVFPortCtrs, + pmCounterPaRxClrVFPortCtrs, + pmCounterPaRxGetVFFocusPorts, + pmCounterPaRxGetFocusPortsMultiSelect, + pmCounterPaRxGetGrpNodeInfo, + pmCounterPaRxGetGrpLinkInfo, + + // Weird conditions + pmCounterPaDuplicateRequests, + pmCounterPaDeadRmppPacket, + pmCounterPaDroppedRequests, + pmCounterPaContextNotAvailable, + + // PA RMPP Operations + pmCounterPaRmppTxRetries, + pmCounterRmppStatusStopNoresources, + //pmCounterRmppStatusAbortTimeTooLong, // Not used anywhere + pmCounterRmppStatusAbortInconsistentLastPayloadLength, + pmCounterRmppStatusAbortInconsistentFirstSegnum, + pmCounterRmppStatusAbortBadType, + pmCounterRmppStatusAbortNewWindowLastTooSmall, + pmCounterRmppStatusAbortSegnumTooBig, + //pmCounterRmppStatusAbortIllegalStatus, // Not used anywhere + pmCounterRmppStatusAbortUnsupportedVersion, + pmCounterRmppStatusAbortTooManyRetries, + pmCounterRmppStatusAbortUnspecified, + + // PA Request Response Stuff + pmCountersPaTxRespMadStatusBusy, + pmCountersPaTxRespMadStatusRedirect, + pmCountersPaTxRespMadStatusBadClass, + pmCountersPaTxRespMadStatusBadMethod, + pmCountersPaTxRespMadStatusBadAttr, + pmCountersPaTxRespMadStatusBadField, + pmCountersPaTxRespMadStatusPaUnavailable, + pmCountersPaTxRespMadStatusPaNoGroup, + pmCountersPaTxRespMadStatusPaNoPort, + pmCountersPaTxRespMadStatusStlPaNoVf, + pmCountersPaTxRespMadStatusStlPaInvalidParam, + pmCountersPaTxRespMadStatusStlPaNoImage, + pmCountersPaTxRespMadStatusStlPaNoData, + pmCountersPaTxRespMadStatusStlPaBadData, + + pmCountersPaTxRespMadStatusUnknown, + + pmCountersMax // Last value +} pm_counters_t; + +typedef enum _pm_peak_counters { + pmMaxPaContextsInUse, + pmMaxPaContextsFree, + pmMaxSweepTime, // in ms + + pmPeakCountersMax // Last value +} pm_peak_counters_t; + +typedef struct _pm_counter { + char * name; + ATOMIC_UINT sinceLastSweep; + ATOMIC_UINT lastSweep; + ATOMIC_UINT total; +} pm_counter_t; + +// +// These are the arrays that contain the counter values... They're definition +// is in pm_counters.c. If you add a counter to either list, be sure to +// add a description for it in pm_counters.c +// +// The pmCounters array is used for strictly incrementing counters (i.e. +// one's that you'll use the INCREMENT_PM_COUNTERS() function for. The +// pmPeakCounters array is for counters that you'll want to use the +// SET_PEAK_COUNTER() function on. +// +extern pm_counter_t pmCounters[pmCountersMax]; +extern pm_counter_t pmPeakCounters[pmPeakCountersMax]; + +// +// This function increments a counter in the pmCounters array +// +static __inline__ +void INCREMENT_PM_COUNTER(pm_counters_t counter) { + AtomicIncrementVoid(&pmCounters[counter].sinceLastSweep); + AtomicIncrementVoid(&pmCounters[counter].total); +} + +// +// This function compares and sets a value in the pmPeakCounters array if +// it's greater that the current value. +// +static __inline__ +void SET_PM_PEAK_COUNTER(pm_peak_counters_t counter, const uint32 value) { + uint32 tmp; + + do { + tmp = AtomicRead(&pmPeakCounters[counter].sinceLastSweep); + } while ( (value > tmp) + && ! AtomicCompareStore(&pmPeakCounters[counter].sinceLastSweep, + tmp, value)); + + do { + tmp = AtomicRead(&pmPeakCounters[counter].total); + } while ( (value > tmp) + && ! AtomicCompareStore(&pmPeakCounters[counter].total, + tmp, value)); +} + +// +// Convenience function for processing a mad status return code. +// +static __inline__ +void INCREMENT_PM_MAD_STATUS_COUNTERS(Mai_t * mad) { + if (mad->base.mclass == MAD_CV_VFI_PM) { + switch (mad->base.status) { + case MAD_STATUS_OK: + break; + case MAD_STATUS_BUSY: + INCREMENT_PM_COUNTER(pmCountersPaTxRespMadStatusBusy); break; + case MAD_STATUS_REDIRECT: + INCREMENT_PM_COUNTER(pmCountersPaTxRespMadStatusRedirect); break; + case MAD_STATUS_BAD_CLASS: + INCREMENT_PM_COUNTER(pmCountersPaTxRespMadStatusBadClass); break; + case MAD_STATUS_BAD_METHOD: + INCREMENT_PM_COUNTER(pmCountersPaTxRespMadStatusBadMethod); break; + case MAD_STATUS_BAD_ATTR: + INCREMENT_PM_COUNTER(pmCountersPaTxRespMadStatusBadAttr); break; + case MAD_STATUS_BAD_FIELD: + INCREMENT_PM_COUNTER(pmCountersPaTxRespMadStatusBadField); break; + case STL_MAD_STATUS_STL_PA_UNAVAILABLE: + INCREMENT_PM_COUNTER(pmCountersPaTxRespMadStatusPaUnavailable); break; + case STL_MAD_STATUS_STL_PA_NO_GROUP: + INCREMENT_PM_COUNTER(pmCountersPaTxRespMadStatusPaNoGroup); break; + case STL_MAD_STATUS_STL_PA_NO_PORT: + INCREMENT_PM_COUNTER(pmCountersPaTxRespMadStatusPaNoPort); break; + case STL_MAD_STATUS_STL_PA_NO_VF: + INCREMENT_PM_COUNTER(pmCountersPaTxRespMadStatusStlPaNoVf); break; + case STL_MAD_STATUS_STL_PA_INVALID_PARAMETER: + INCREMENT_PM_COUNTER(pmCountersPaTxRespMadStatusStlPaInvalidParam); break; + case STL_MAD_STATUS_STL_PA_NO_IMAGE: + INCREMENT_PM_COUNTER(pmCountersPaTxRespMadStatusStlPaNoImage); break; + case STL_MAD_STATUS_STL_PA_NO_DATA: + INCREMENT_PM_COUNTER(pmCountersPaTxRespMadStatusStlPaNoData); break; + case STL_MAD_STATUS_STL_PA_BAD_DATA: + INCREMENT_PM_COUNTER(pmCountersPaTxRespMadStatusStlPaBadData); break; + default: + INCREMENT_PM_COUNTER(pmCountersPaTxRespMadStatusUnknown); break; + } + } else { // PMA Status + switch (mad->base.status & ~MAD_STATUS_D_BIT) { + case MAD_STATUS_OK: + break; + case MAD_STATUS_BUSY: + INCREMENT_PM_COUNTER(pmCounterRxPmaMadStatusBusy); break; + case MAD_STATUS_REDIRECT: + INCREMENT_PM_COUNTER(pmCounterRxPmaMadStatusRedirect); break; + case MAD_STATUS_BAD_CLASS: + INCREMENT_PM_COUNTER(pmCounterRxPmaMadStatusBadClass); break; + case MAD_STATUS_BAD_METHOD: + INCREMENT_PM_COUNTER(pmCounterRxPmaMadStatusBadMethod); break; + case MAD_STATUS_BAD_ATTR: + INCREMENT_PM_COUNTER(pmCounterRxPmaMadStatusBadAttr); break; + case MAD_STATUS_BAD_FIELD: + INCREMENT_PM_COUNTER(pmCounterRxPmaMadStatusBadField); break; + default: + INCREMENT_PM_COUNTER(pmCounterRxPmaMadStatusUnknown); break; + } + } +} + +// Function prototypes +extern void pm_init_counters(void); +extern void pm_process_sweep_counters(void); +extern void pm_reset_counters(void); +extern void pm_print_counters_to_stream(FILE * out); + +#ifndef __VXWORKS__ +extern char * pm_print_counters_to_buf(void); +#endif + +#endif // _PM_COUNTERS_H_ diff --git a/Esm/ib/src/pm/include/pm_l.h b/Esm/ib/src/pm/include/pm_l.h new file mode 100644 index 0000000..b12cfbf --- /dev/null +++ b/Esm/ib/src/pm/include/pm_l.h @@ -0,0 +1,72 @@ +/* BEGIN_ICS_COPYRIGHT2 **************************************** + +Copyright (c) 2015-2018, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT2 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ +#ifndef _PM_L_H_ +#define _PM_L_H_ + +#include /* Global common services functions */ +#include +#include +#include "iquickmap.h" +#include "pm_counters.h" +#include "fm_xml.h" + +// 200 bytes per port is more than our current data structures need by a +// reasonable margin (approx 1k for 24 ports). +#define PM_MAX_DATA_LEN (36*200) + +/* + * PM debug flag + * re-routes all verbose messages to InfiniInfo level + */ +void pmDebugOn(void); +void pmDebugOff(void); +uint32_t pmDebugGet(void); + +/* debug trace control for embeded PM */ +#define _PM_TRACE(l) (l == 0) ? VS_LOG_VERBOSE : VS_LOG_INFINI_INFO + +// lease time for FreezeFrame, if idle more than this, discard Freeze +extern int pm_shutdown; +extern Pool_t pm_pool; + + +#define DEFAULT_INTERVAL_USEC (2000000) // 2sec + +#define PM_CONN_ATTEMPTS (10) //how often to try to open connection +#define PM_CONN_INTERVAL (10000000) //interval bettween attempts + +extern void PmEngineStart(void); +extern void PmEngineStop(void); +extern boolean PmEngineRunning(void); + +extern void pm_update_dyn_config(PMXmlConfig_t *new_pm_config); + +#endif diff --git a/Esm/ib/src/pm/include/pm_topology.h b/Esm/ib/src/pm/include/pm_topology.h new file mode 100644 index 0000000..1564174 --- /dev/null +++ b/Esm/ib/src/pm/include/pm_topology.h @@ -0,0 +1,1618 @@ +/* BEGIN_ICS_COPYRIGHT7 **************************************** + +Copyright (c) 2015-2018, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT7 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +#ifndef _PM_TOPOLOGY_H +#define _PM_TOPOLOGY_H + +#include "sm_l.h" +#include "pm_l.h" +#include +#include +#include +#include +#include +#include +#include +#define _GNU_SOURCE +#include +#include +#include +#include // for ATOMIC_UINT +#include // for cl_qmap_t +#include +#include "cs_context.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#include "iba/public/ipackon.h" + + // used to mark unused entries in history and freezeFrame + // also used in LastSweepIndex to indicate no sweeps done yet +#define PM_IMAGE_INDEX_INVALID 0xffffffff + +// Used By Get/Clear Vf PortCounters to Access VL 15 Counters +#define HIDDEN_VL15_VF "HIDDEN_VL15_VF" +#define PA_ALL_GROUP_NAME "All" + +// special ImageId of 0 is used to access live data +// -1 is used to request Images by time +// other non-zero values are of the format below +// This is an opaque format, the only user known ImageIds are 0 to access +// live data and -1 (0xffffffffffffffff) for images by time +#define IMAGEID_LIVE_DATA 0 // 64 bit ImageId to access live data +#define IMAGEID_ABSOLUTE_TIME -1 // 64 bit ImageID to request image by time + +// values for ImageId.s.type field, used to determine which table to look in, or +// to determine if an image came from disk. +#define IMAGEID_TYPE_ANY 0 // Matches any image ID type +#define IMAGEID_TYPE_FREEZE_FRAME 1 // client requested Freeze Frame +#define IMAGEID_TYPE_HISTORY 2 // last sweep and recent history +#define IMAGEID_TYPE_HISTORY_DISK 3 // Recent history *disk only* + +#define IMAGEID_MAX_INSTANCE_ID 256 // 8 bit field + +typedef union { + uint64_t AsReg64; + struct { + // this is opaque so bitt order doesn't matter, but we use IB_BITFIELD + // so its more readable when displayed as a uint64 in debug logging + IB_BITFIELD5(uint64, + type:2, // type of image + clientId:6, // bit number of client within Freeze Ref Count + sweepNum:32, // NumSweeps to provide uniqueness + instanceId:8, // instanceId ot provide uniqueness between PM instances + index:16 // look aside index + ) + } s; +} ImageId_t; + +// TBD - if we malloc Pm_t.Groups[], maybe number of groups could be dynamic +#define PM_MAX_GROUPS 10 // max user configured groups +#define PM_MAX_GROUPS_PER_PORT 4 // we keep this small to bound compute needs + // 4 groups plus the All group gives max of 5 groups per port + // IntLinkFlags must be at least this many bits, presently 8 bits + // and portImage->numGroups must be able to hold this value + +// how much beyond maxLid to allocate to allow for growth without realloc +#define PM_LID_MAP_SPARE 512 +// how much below maxLid to trigger free +#define PM_LID_MAP_FREE_THRESHOLD 1024 +// TBD - pre-size based on subnet size? Or perhaps have above be a function +// of subnet size? + +#ifdef __VXWORKS__ +/* Use 1000 to match HSM's define for MAX_VABRICS which is a redefinition + * of MAX_ENABLED_VFABRICS. MAX_ENABLED_VFABRICS is defined in fm_xml.h. + */ +#define MAX_PM_COMP_VFABRICS 1000 +#else /* __VXWORKS__ */ +#define MAX_PM_COMP_VFABRICS MAX_VFABRICS +#endif /* __VXWORKS__ */ + +extern uint32_t g_pmDebugPerf; + +// This is a consolidation of the counters of interest from PortStatus +// We use the same datatypes for each counter (hence same range) as in PMA +typedef struct PmCompositePortCounters_s { + uint8 PortNumber; + uint8 Reserved[3]; + uint32 VLSelectMask; + uint64 PortXmitData; + uint64 PortRcvData; + uint64 PortXmitPkts; + uint64 PortRcvPkts; + uint64 PortMulticastXmitPkts; + uint64 PortMulticastRcvPkts; + uint64 PortXmitWait; + uint64 SwPortCongestion; + uint64 PortRcvFECN; + uint64 PortRcvBECN; + uint64 PortXmitTimeCong; + uint64 PortXmitWastedBW; + uint64 PortXmitWaitData; + uint64 PortRcvBubble; + uint64 PortMarkFECN; + uint64 PortRcvConstraintErrors; + uint64 PortRcvSwitchRelayErrors; + uint64 PortXmitDiscards; + uint64 PortXmitConstraintErrors; + uint64 PortRcvRemotePhysicalErrors; + uint64 LocalLinkIntegrityErrors; + uint64 PortRcvErrors; + uint64 ExcessiveBufferOverruns; + uint64 FMConfigErrors; + uint32 LinkErrorRecovery; + uint32 LinkDowned; + uint8 UncorrectableErrors; + union { + uint8 AsReg8; + struct { +#if CPU_BE + uint8 NumLanesDown:4; + uint8 Reserved:1; + uint8 LinkQualityIndicator:3; +#else + uint8 LinkQualityIndicator:3; + uint8 Reserved:1; + uint8 NumLanesDown:4; +#endif // CPU_BE + } s; + } lq; + + uint8 Reserved2[30]; + +} PmCompositePortCounters_t; + +typedef struct _vls_pctrs PmCompositeVLCounters_t; + + +typedef struct PmCompositeVfvlmap_s { + uint32 vlmask; + uint32 VF; //index into vf array +} PmCompositeVfvlmap_t; + +typedef struct _port_error_info PmCompositeErrorInfo_t; + +#define UPDATE_MAX(max, cnt) do { if (cnt > max) max = cnt; } while (0) +#define UPDATE_MIN(min, cnt) do { if (cnt < min) min = cnt; } while (0) + + +// for tracking Bandwidth utilization, we use MB/s in uint32 containers +// for reference the maximum theoretical MB/s is as follows: +// where MB = 1024*1024 Bytes +// Max MBps 1x SDR=238 +// Max MBps 4x SDR=953 +// Max MBps 4x DDR=1907 +// Max MBps 4x QDR=3814 +// Max MBps 8x QDR=7629 +// Max MBps 8x EDR=15258 +// Max MBps 8x HDR=30516 +// Max MBps 12x HDR=45768 + +// for tracking packet rate, we use Kilo packet/s units in uint32 containers +// where KP = 1024 packets +// Max KPps 1x SDR=8704 +// Max KPps 4x SDR=34852 +// Max KPps 4x DDR=69741 +// Max KPps 4x QDR=139483 +// Max KPps 8x QDR=279003 +// Max KPps 8x EDR=558006 +// Max KPps 8x HDR=1116013 +// Max KPps 12x HDR=1673801 + +// number of errors of each "error class" per interval (NOT per second). +// tracked per "half link". Problem is associated with direction +// having problem, we associate count with "destination" port although +// both sides can be partial causes. +// counters are same size as PMA(PortCounters) since beyond that +// PMA will peg counter for given analysis interval +typedef struct ErrorSummary_s { + uint32 Integrity; + uint32 Congestion; + uint32 SmaCongestion; + uint32 Bubble; + uint32 Security; + uint32 Routing; + + uint16 UtilizationPct10; /* in units of 10% */ + uint16 DiscardsPct10; /* in units of 10% */ + uint32 Reserved; +} PACK_SUFFIX ErrorSummary_t; + +// weight to use for each Integrity counter in weighted sum +typedef struct IntegrityWeights_s { + uint8 LocalLinkIntegrityErrors; + uint8 PortRcvErrors; + uint8 ExcessiveBufferOverruns; + uint8 LinkErrorRecovery; + uint8 LinkDowned; + uint8 UncorrectableErrors; + uint8 FMConfigErrors; + uint8 LinkQualityIndicator; + uint8 LinkWidthDowngrade; +} IntegrityWeights_t; + +// weight to use for each Congestion counter in weighted sum +typedef struct CongestionWeights_s { + uint8 PortXmitWait; + uint8 SwPortCongestion; + uint8 PortRcvFECN; + uint8 PortRcvBECN; + uint8 PortXmitTimeCong; + uint8 PortMarkFECN; +} CongestionWeights_t; + +// this type counts number of ports in given "% bucket" of util/errors +// for a 20K node fabric with 4 FBB tiers, we can have 60K links with 120K ports +// hence we need a uint32 +typedef uint32 pm_bucket_t; + +// number of ports in this bucket for each class of errors +// error class association to PMA Counters is same as in ErrorSummary_t +// determination of % (to select bucket) is based on configured threshold +typedef struct ErrorBucket_s { + pm_bucket_t Integrity; + pm_bucket_t Congestion; + pm_bucket_t SmaCongestion; + pm_bucket_t Bubble; + pm_bucket_t Security; + pm_bucket_t Routing; +} PACK_SUFFIX ErrorBucket_t; + +// summary of utilization statistics for a group of ports +typedef struct PmUtilStats_s { + // internal intermediate data + // TBD - might be useful to report for Ext of groups like SWs and HFIs + uint64 TotMBps; // Total of MBps of all selected ports, used to compute Avg + uint64 TotKPps; // Total of KPps of all selected ports, used to compute Avg + + // bandwidth + uint32 AvgMBps; // average MB per second of all selected ports + uint32 MinMBps; // minimum MB per second of all selected ports + uint32 MaxMBps; // maximum MB per second of all selected ports + + // Counter below counts number of ports within given % of BW utilization + pm_bucket_t BwPorts[STL_PM_UTIL_BUCKETS]; + + // packets/sec tracking + uint32 AvgKPps; // average kilo packets/sec of all selected ports + uint32 MinKPps; // minimum kilo packets/sec of all selected ports + uint32 MaxKPps; // maximum kilo packets/sec of all selected ports + + uint16 pmaNoRespPorts; // Number of ports with failures but were still able + // to be included in Group/Vf Stats + uint16 topoIncompPorts; // Number of ports with failures that were not able + // to be included in Group/Vf Stats + // buckets for packets/sec % don't make much sense since theroretical + // limit is a function of packet size, hence confusing to report + + uint32 reserved; + +} PACK_SUFFIX PmUtilStats_t; + +// summary of error statistics for a group of ports +typedef struct PmErrStats_s { + // For between-group stats, we take Max of us and our neighbor + // In context of Errors, Avg and Min is of limited value, hopefully + // very few ports have errors so Avg would be low and Min would be 0 + // hence we only track Max + ErrorSummary_t Max; // maximum of each count for all selected ports + + // Number of "half-links"/ports exceeding threshold + // for between-group buckets, we count one using the worst port in link + // for in-group we count one for each port in group + // buckets are based on % of configured threshold, + // last bucket is for >=100% of threshold + ErrorBucket_t Ports[STL_PM_CATEGORY_BUCKETS];// in group +} PACK_SUFFIX PmErrStats_t; + +struct PmPort_s; +struct PmImage_s; +typedef boolean (*PmComparePortFunc_t)(struct PmImage_s *pmimagep, struct PmPort_s *pmportp, char *groupName); + +// a group is a set of ports. A given link can be: +// in-group - both ports are within the same group +// between-group - one port is in and one port is outside +// in which case we talk about Send/Recv direction relative to group +// This allows customers to monitor traffic across selected links (such as +// to/from storage) by putting only 1 port of link in a given group +// +// For error statistics, root cause is less obvious, so when going between-group +// we consider an error on either side of the link as an error associated with +// the External Errors +// +// Should be able to fit in a single MAD all the Internal Stats +// (Ports, Util, Errors) 168 bytes +// On external stats +// (Ports, SendUtil, RecvUtil, Errors) 232 bytes +typedef struct PmGroup_s { + // configuration - unchanging, no lock needed + char Name[STL_PM_GROUPNAMELEN]; // \0 terminated + uint32_t pg_index; // index into PmImage_t.Groups[] + + // function to decide if new ports in topology should be added to group + PmComparePortFunc_t ComparePortFunc; + + // dg_index from pm_config + uint16 dg_index[STL_PM_MAX_DG_PER_PMPG]; // (-1)0xFFFF = not used +} PmGroup_t; + +typedef struct PmGroupImage_s { + uint32 NumIntPorts; // # of ports in group for links in-group + uint32 NumExtPorts; // # of ports in group for links between-group + + // statistics + PmUtilStats_t IntUtil; // when both ports in group + PmUtilStats_t SendUtil; // send from group to outside + PmUtilStats_t RecvUtil; // recv by group from outside + +// TBD better wording, don't want customer to confuse Internal to a group +// with Internal to a chassis + // for Internal (in-group) we count one each port (both are in group) + // for External (between-group), we count worst of our port and its neighbor + PmErrStats_t IntErr;// in group + PmErrStats_t ExtErr;// between groups + uint8 MinIntRate; + uint8 MaxIntRate; + uint8 MinExtRate; + uint8 MaxExtRate; + uint32 padding; // for alignment +} PmGroupImage_t; + +typedef struct PmVF_s { + char Name[MAX_VFABRIC_NAME]; // \0 terminated + uint8 isActive; +} PmVF_t; + +typedef struct PmVFImage_s { + uint32 NumPorts; // # of ports in VF + + // statistics + PmUtilStats_t IntUtil; // all stats for VF are internal + + PmErrStats_t IntErr;// in VF + + uint8 MinIntRate; + uint8 MaxIntRate; +} PmVFImage_t; + +// for FI, one instance per Active Port +// for Switch, one instance per Switch +// This is not persee a node, but really a lid'ed port +typedef struct PmNode_s { + ATOMIC_UINT refCount; + cl_map_item_t AllNodesEntry; // engine use only, key is portGuid + + // these fields do not change and are tracked once for the Node + Guid_t NodeGUID; + Guid_t SystemImageGUID; +// TBD - track system image guid? + STL_NODE_DESCRIPTION nodeDesc; // we keep latest name, rarely changes + uint32 changed_count; // topology_changed_count when last saw node + uint32 deviceRevision; // NodeInfo.Device Revision + union { + struct PmPort_s **swPorts; // for switches only + // sized by numPorts + // some may be NULL + struct PmPort_s *caPortp; // for FI and RTR + // exactly 1 port per FI tracked per PmNode_t + // one PmNode_t per active FI port + } up; + + uint8 nodeType; // for switches only + uint8 numPorts; + // keep latest flags here, they rarely change + union { + uint16 AsReg16; + struct { + uint16 PmaAvoid:1; // node does not have a working PMA or + // PM sweeping has been disabled for this Node + uint16 PmaGotClassPortInfo:1; // has Pma capabilities been init'ed + + uint16 Reserved:14; // 14 spare bits + + } s; + } u; + + // Path Information to talk to Node's PMA + // we keep latest information here, only used when doing current sweep + STL_LID dlid; // for PMA Redirect + uint16 pkey; // for PMA Redirect + uint32 qpn:24; // for PMA Redirect + uint32 sl:4; // set when update_path + uint32 qkey; // for PMA Redirect + + // per Image data protected by Pm.Image[].imageLock + // must be last in structure so can dynamically size total images in future + struct PmNodeImage_s { + // can change per sweep, so track per sweep and can be Freeze Framed + STL_LID lid; // for switch, its lid of port 0 + } Image[1]; // sized when allocate PmNode_t +} PmNode_t; + +typedef struct PmNodeImage_s PmNodeImage_t; + +// queryStatus for Port +#define PM_QUERY_STATUS_OK 0x0 // query success (or not yet attempted) +#define PM_QUERY_STATUS_SKIP 0x1 // port skipped, no PMA or filtered +#define PM_QUERY_STATUS_FAIL_QUERY 0x2 // failed to get port counters, + // path, or classportinfo +#define PM_QUERY_STATUS_FAIL_CLEAR 0x3 // query ok, but failed clear + +typedef struct _vfmap { + uint32 vlmask; +} vfmap_t; + +typedef union { + uint32 AsReg32; + struct { IB_BITFIELD8(uint32, + UtilBucket:4, // MBps utilization bucket: 0 - PM_UTIL_BUCKETS-1 + // Error Buckets (0-PM_ERR_BUCKETS-1) + + IntegrityBucket:3, // Integrity + CongestionBucket:3, // Congestion + SmaCongestionBucket:3, // SMA Congestion + BubbleBucket:3, // Bubble + SecurityBucket:3, // Security + RoutingBucket:3, // Routing + Reserved:10) + } s; +} BucketMask_t; + +// This tracks Switch, FI and router ports +typedef struct PmPort_s { + // these fields do not change and are tracked once for the Port + Guid_t guid; // can be 0 for switch portNum != 0 + PmNode_t *pmnodep; + uint32 capmask; // keep latest, rarely changes + + uint8 portNum; + // keep latest status here, they rarely change + union { + uint8 AsReg8; + struct { IB_BITFIELD2(uint8, + PmaAvoid:1, // PM should not sweep PMA on this Port + Reserved:7) + } s; + } u; + + // lid/portnum of neighbor is temp data only used while doing sweep + STL_LID neighbor_lid; + PORT neighbor_portNum; // only valid if neighbor_lid != 0 + + bitset_t dgMember; // Copy of DeviceGroup Memebership from SM + + // count warnings + uint32 groupWarnings; + + // protected by Pm_t.totalsLock + PmCompositePortCounters_t StlPortCountersTotal; // running total + PmCompositeVLCounters_t StlVLPortCountersTotal[MAX_PM_VLS]; + // somehow configure this based on pm_config.process_vl_counters + + // per Image data protected by Pm.Image[].imageLock + // must be last in structure so can dynamically size total images in future + struct PmPortImage_s { + union { + uint32 AsReg32; + struct { IB_BITFIELD12(uint32, + active:1, // is port IB_PORT_ACTIVE (SW port 0 fixed up) + mtu:4, // enum IB_MTU - due to actual range, 3 bits + txActiveWidth:4, // LinkWidthDowngrade.txActive + rxActiveWidth:4, // LinkWidthDowngrade.rxActive + activeSpeed:3, // LinkSeed.Active + Initialized:1, // has group membership been initialized + queryStatus:2, // PMA query or clear result + UnexpectedClear:1, // PMA Counters unexpectedly cleared + gotDataCntrs:1, // Were Data Counters updated + gotErrorCntrs:1, // Were Error Counters updated + gotErrorInfo:1, // Was Error Info captured + Reserved:9) + } s; + } u; + struct PmPort_s *neighbor; // Pointer to Neighbor Port + + PmGroup_t *Groups[PM_MAX_GROUPS_PER_PORT]; // PortGroups (In additon to All) this port is a member of. + uint8 numGroups; // Number of PortGroups + uint8 InternalBitMask; // If Port is Internal to PortGroup Bit Mask (this and neighbor in group) + + uint32 numVFs; // Number of VFs + vfmap_t vfvlmap[MAX_VFABRICS]; // VFs this port is a member of. + + uint32_t vlSelectMask; // Aggreate of Active VLs used by VFs (also VL 15) + CounterSelectMask_t clearSelectMask; // Counter Mask of Counters Cleared after the above data was recorded + + // Raw PortCounters + PmCompositePortCounters_t StlPortCounters; // Port Level Counters + PmCompositeVLCounters_t StlVLPortCounters[MAX_PM_VLS]; // VL Level Counters + // Delta PortCounters + PmCompositePortCounters_t DeltaStlPortCounters; // Port Level Counters + PmCompositeVLCounters_t DeltaStlVLPortCounters[MAX_PM_VLS]; // VL Level Counters + + PmCompositeErrorInfo_t ErrorInfo; + + } Image[1]; // sized when allocate PmPort_t +} PmPort_t; + +#define PM_PORT_ERROR_SUMMARY(portImage, lli, ler) \ + ((portImage)->StlPortCounters.PortRcvConstraintErrors + \ + (portImage)->StlPortCounters.PortRcvSwitchRelayErrors + \ + (portImage)->StlPortCounters.PortRcvSwitchRelayErrors + \ + (portImage)->StlPortCounters.PortXmitDiscards + \ + (portImage)->StlPortCounters.PortXmitConstraintErrors + \ + (portImage)->StlPortCounters.PortRcvRemotePhysicalErrors + \ + ((portImage)->StlPortCounters.LocalLinkIntegrityErrors >> (lli?(lli + RES_ADDER_LLI):0)) + \ + (portImage)->StlPortCounters.PortRcvErrors + \ + (portImage)->StlPortCounters.ExcessiveBufferOverruns + \ + (portImage)->StlPortCounters.FMConfigErrors + \ + ((portImage)->StlPortCounters.LinkErrorRecovery >> (ler?(ler + RES_ADDER_LER):0)) + \ + (portImage)->StlPortCounters.LinkDowned + \ + (portImage)->StlPortCounters.UncorrectableErrors) + + +typedef struct PmPortImage_s PmPortImage_t; + +// FI port or 1st Port of switch +#define pm_node_lided_port(pmnodep) \ + ((pmnodep->nodeType == STL_NODE_SW) \ + ?pmnodep->up.swPorts[0]:pmnodep->up.caPortp) + +// Image States +#define PM_IMAGE_INVALID 0 // uninitialized +#define PM_IMAGE_VALID 1 // valid, available for PA queries +#define PM_IMAGE_INPROGRESS 2 // in process of being swept + +// The dispatcher allows the PM to issue multiple requests in parallel +// A DispatcherNode is retained for each Node being queried in parallel +// (up to MaxParallelNodes) +// Within each DispatcherNode a list of DispatcherPorts is retained for each +// Port in the node being queries in parallel (up to PmaBatchSize) +typedef enum { + PM_DISP_PORT_NONE = 0, + PM_DISP_PORT_GET_PORTSTATUS = 1, // Get(PortStatus) outstanding + PM_DISP_PORT_GET_PORTCOUNTERS = 2, // Get(PortCounters) outstanding + PM_DISP_PORT_DONE = 3, // all processing done for this port +} PmDispPortState_t; + +struct PmDispatcherNode_s; + +// Return Values for MergePortIntoPacket() +#define PM_DISP_SW_MERGE_DONE 0 +#define PM_DISP_SW_MERGE_ERROR 1 +#define PM_DISP_SW_MERGE_CONTINUE 2 +#define PM_DISP_SW_MERGE_NOMERGE 3 + +typedef struct PmDispatcherPort_s { + PmPort_t *pmportp; + struct PmDispatcherSwitchPort_s *dispNodeSwPort; + struct PmDispatcherNode_s *dispnode; // setup once at boot + PmPortImage_t *pPortImage; + PmPortImage_t *pPortImagePrev; +} PmDispatcherPort_t; + +typedef struct PmDispatcherPacket_s { + uint64 PortSelectMask[4]; // Ports in Packet + uint32 VLSelectMask; + uint8 numPorts; + uint8 numVLs; + struct PmDispatcherNode_s *dispnode; // setup once at boot + PmDispatcherPort_t *DispPorts; +} PmDispatcherPacket_t; + +typedef enum { + PM_DISP_NODE_NONE = 0, + PM_DISP_NODE_CLASS_INFO = 1, // Get(ClassPortInfo) outstanding + // Ports[0] has request + PM_DISP_NODE_GET_DATACOUNTERS = 2, // Getting Data Counters for Ports[] + PM_DISP_NODE_GET_ERRORCOUNTERS = 3, // Getting Error Counters for Ports[] + PM_DISP_NODE_CLR_PORT_STATUS = 4, // Clearing Counters for Ports[] + PM_DISP_NODE_GET_ERRORINFO = 5, // Getting ErrorInfo for Ports[] + PM_DISP_NODE_CLR_ERRORINFO = 6, // Clearing ErrorInfo for Ports[] + PM_DISP_NODE_DONE = 7, // all processing done for this node +} PmDispNodeState_t; + +struct Pm_s; + +typedef struct PmDispatcherSwitchPort_s { + uint8 portNum; + union { + uint8 AsReg8; + struct { + uint8 IsDispatched:1; // Port has been dispatched + uint8 DoNotMerge:1; // Query failed, retry with out mergeing to isolate port + uint8 NeedsClear:1; // Replaces 256-bit mask in Node Struct. + uint8 NeedsError:1; + uint8 Skip:1; // Any other reason we should skip this packet. + uint8 NeedsErrorInfo:1; + uint8 NeedsClearErrorInfo:1; + uint8 Reserved:1; + } s; + } flags; + uint8 NumVLs; // Number of active VLs in the Mask + + uint32 VLSelectMask; // VLSelect Mask associated with port. +} PmDispatcherSwitchPort_t; + +typedef struct PmDispatcherNode_s { + struct { + PmNode_t *pmnodep; + PmDispNodeState_t state; + union { + uint8 AsReg8; + struct { + uint8 failed:1; + uint8 redirected:1; // got PMA redirect response + uint8 needError:1; // Summary NeedsError from PmDispatcherSwitchPort_t + uint8 needClearSome:1; + uint8 canClearAll:1; + uint8 needErrorInfo:1; // Summary NeedsError from PmDispatcherSwitchPort_t + uint8 needClearErrorInfo:1; // Summary NeedsError from PmDispatcherSwitchPort_t + // 1 spare bits + } s; + } u; + uint32 clearCounterSelect; // assumed to be same for all ports + uint8 numOutstandingPackets; // num packets in Dispatcher.Nodes[].Packets + uint8 numPorts; // pmnodep structs sometimes wrong; NOW HFI=1 (always) and SW=pmnodep->numPorts+1 to include port 0 + struct PmDispatcherSwitchPort_s *nextPort; // next port to be dispatched within activePorts + PmDispatcherSwitchPort_t *activePorts; // Array of Structures to keep track usefull information relating to a port + } info; + struct Pm_s *pm; // setup once at boot + PmDispatcherPacket_t *DispPackets; // allocated array of PmaBatchSize +} PmDispatcherNode_t; + +typedef struct PmImage_s { + // These fields are protected by Pm.stateLock + uint8 state; // Image State + uint8 nextClientId;// next clientId for FreezeFrame of this image + uint32 sweepNum; // NumSweeps when we did this sweep + uint32 historyIndex;// history index corresponding to this image + uint64 ffRefCount; // 1 bit per FF clientId, indicates image in + // use by FreezeFrame with given ClientId + // when 0, no FreezeFrames reference this Image + time_t lastUsed; // timestamp of last reference, used to age FF + + + Lock_t imageLock; // Lock image data (except state and imageId). + // also protects Port.Image, Node.Image + // and Group.Image for given imageIndex + + // for rapid lookup, we index by LID. < 48K LIDs, so mem size tolerable + // We dynamic allocate and size based on old_topology.maxLid + // allocates PM_LID_MAP_SPARE extra when grows and only releases when + // more than PM_LIB_MAP_FREE_THRESHOLD decrease in maxLid, hence + // avoiding resizing for minor fabric changes. +// TBD - SM LidMap could similarly use an array for rapid lookup +// and keep lidmap, maxlid, size per sweep + PmNode_t **LidMap; + STL_LID lidMapSize; // number of entries allocated in LidMap + STL_LID maxLid; + + time_t sweepStart; // when started sweep, seconds since 1970 + uint32 sweepDuration; // in usec + uint32 imageInterval; // in sec + + // counts of devices found during this sweep + uint16 HFIPorts; // count of active HFI ports +// TFI not included in Gen1 +// uint16 TFIPorts; // count of active TFI ports + uint16 SwitchNodes; // count of Switch Nodes + uint32 SwitchPorts; // count of Switch Ports (includes Port 0) + uint32 NumLinks; // count of links (includes internal) + uint32 NumSMs; // count of SMs (including us) + struct PmSmInfo { + STL_LID smLid; // implies port, 0 if empty record + uint8 priority:4; // present priority + uint8 state:4; // present state + } SMs[2]; // track just master and 1st secondary + // summary of errors during of sweep + // Nodes = Switch Node or a FI Port + uint32 NoRespNodes; // failed to get path or access PMA >=1 port + uint32 NoRespPorts; // failed to get path or access PMA + uint32 SkippedNodes; // Skipped all ports on Node + uint32 SkippedPorts; // No PMA or filtered + uint32 UnexpectedClearPorts; // Ports which whose counters decreased + uint32 DowngradedPorts; // Ports whose Link Width has been downgraded + uint32 ErrorInfoPorts; + + // User Configured Groups + HFIs and SWs (All is implied) + uint32 NumGroups; + PmGroup_t Groups[PM_MAX_GROUPS]; + + uint32 NumVFs; + uint32 NumVFsActive; + PmVF_t VFs[MAX_VFABRICS]; +} PmImage_t; + +// --------------- Short-Term PA History -------------------- +//TBD: OPA_VERSION_MAJOR should be moved to a more generic location +#define OPA_VERSION_MAJOR 10 +#define PM_HISTORY_VERSION (11 | (OPA_VERSION_MAJOR << 24)) +// Old version currently supported by PA +#define PM_HISTORY_VERSION_OLD 10 + +#define PM_HISTORY_FILENAME_LEN 136 // max length of full filepath + // MUST BE MULTIPLE OF 8 +#define PM_HISTORY_MAX_IMAGES_PER_COMPOSITE 60 +#define PM_HISTORY_MAX_SMS_PER_COMPOSITE 2 +#define PM_HISTORY_MAX_LOCATION_LEN 111 + +#define PM_MAX_COMPRESSION_DIVISIONS 32 +#define PM_HISTORY_STHFILE_LEN 15 // the exact length of the filename, not full path + +typedef struct PmCompositePort_s { + uint64 guid; + union { + uint32 AsReg32; + struct { IB_BITFIELD11(uint32, + active:1, // is port IB_PORT_ACTIVE (SW port 0 fixed up) + mtu:4, // enum IB_MTU - due to actual range, 3 bits + txActiveWidth:4, // LinkWidthDowngrade.txActive + rxActiveWidth:4, // LinkWidthDowngrade.rxActive + activeSpeed:3, // LinkSeed.Active + Initialized:1, // has group membership been initialized + queryStatus:2, // PMA query or clear result + UnexpectedClear:1, // PMA Counters unexpectedly cleared + gotDataCntrs:1, // Were Data Counters updated + gotErrorCntrs:1, // Were Error Counters updated + Reserved:10) + } s; + } u; + STL_LID neighborLid; + + PORT portNum; + PORT neighborPort; + uint8 InternalBitMask; + uint8 numGroups; + uint8 groups[PM_MAX_GROUPS_PER_PORT]; + + uint32 numVFs; + uint32 vlSelectMask; + + CounterSelectMask_t clearSelectMask; + uint32 reserved99; + + PmCompositeVfvlmap_t compVfVlmap[MAX_PM_COMP_VFABRICS]; + + PmCompositePortCounters_t stlPortCounters; + PmCompositeVLCounters_t stlVLPortCounters[MAX_PM_VLS]; + PmCompositePortCounters_t DeltaStlPortCounters; + PmCompositeVLCounters_t DeltaStlVLPortCounters[MAX_PM_VLS]; +} PACK_SUFFIX PmCompositePort_t; + +typedef struct PmCompositeNode_s { + uint64 NodeGUID; + uint64 SystemImageGUID; + char nodeDesc[STL_NODE_DESCRIPTION_ARRAY_SIZE]; + STL_LID lid; + uint8 nodeType; + uint8 numPorts; + + uint8 Reserved; + + uint8 reserved; + PmCompositePort_t **ports; +} PACK_SUFFIX PmCompositeNode_t; + +typedef struct PmCompositeVF_s { + char name[MAX_VFABRIC_NAME]; + uint8 isActive; + uint8 reserved[7]; +} PACK_SUFFIX PmCompositeVF_t; + +typedef struct PmCompositeGroups_s { + char name[STL_PM_GROUPNAMELEN]; +} PACK_SUFFIX PmCompositeGroup_t; + +typedef struct PmHistoryHeaderCommon_s { + uint32 historyVersion; // Must remain fixed for all versions + uint32 imageTime; + char filename[PM_HISTORY_FILENAME_LEN]; + uint64 timestamp; + uint8 isCompressed; + uint8 reserved2; + uint16 imagesPerComposite; + uint32 imageSweepInterval; + uint64 imageIDs[PM_HISTORY_MAX_IMAGES_PER_COMPOSITE]; +} PACK_SUFFIX PmHistoryHeaderCommon_t; + +typedef struct PmFileHeader_s { + PmHistoryHeaderCommon_t common; + uint64 flatSize; + uint8 numDivisions; + uint8 reserved[7]; + uint64 divisionSizes[PM_MAX_COMPRESSION_DIVISIONS]; +} PACK_SUFFIX PmFileHeader_t; + +typedef struct PmCompositeSmInfo_s { + STL_LID smLid; // implies port, 0 if empty record +#if CPU_BE + uint8 priority:4; // present priority + uint8 state:4; // present state +#else + uint8 state:4; + uint8 priority:4; +#endif + uint8 reserved[3]; +} PACK_SUFFIX PmCompositeSmInfo_t; + +typedef struct PmCompositeImage_s { + PmFileHeader_t header; + uint64 sweepStart; + uint32 sweepDuration; + uint8 reserved[2]; + uint16 HFIPorts; + uint16 switchNodes; + uint16 reserved2; + uint32 switchPorts; + uint32 numLinks; + uint32 numSMs; + uint32 noRespNodes; + uint32 noRespPorts; + uint32 skippedNodes; + uint32 skippedPorts; + uint32 unexpectedClearPorts; + uint32 downgradedPorts; + uint32 numGroups; + uint32 numVFs; + uint32 numVFsActive; + STL_LID maxLid; + uint32 numPorts; + PmCompositeSmInfo_t SMs[PM_HISTORY_MAX_SMS_PER_COMPOSITE]; + uint32 reserved3; + PmCompositeGroup_t groups[PM_MAX_GROUPS]; + PmCompositeVF_t VFs[MAX_PM_COMP_VFABRICS]; + PmCompositeNode_t **nodes; +} PACK_SUFFIX PmCompositeImage_t; + +#define INDEX_NOT_IN_USE 0xffffffff +typedef struct PmHistoryRecord_s { + PmHistoryHeaderCommon_t header; + uint32 index; + struct _imageEntry { + cl_map_item_t historyImageEntry; // key is image ID + uint32 inx; + } historyImageEntries[PM_HISTORY_MAX_IMAGES_PER_COMPOSITE]; + cl_map_item_t imageTimeEntry; +} PmHistoryRecord_t; + +typedef struct _imageEntry PmHistoryImageEntry_t; + +typedef struct PmShortTermHistory_s { + char filepath[PM_HISTORY_MAX_LOCATION_LEN]; + PmCompositeImage_t *currentComposite; + uint8 compositeWritten; + uint32 currentRecordIndex; + uint64 totalDiskUsage; + cl_qmap_t historyImages; // map of all short term history Records, keyed by image IDs + cl_qmap_t imageTimes; // map of all short term history images, keyed by start time + uint32 totalHistoryRecords; + uint8 currentInstanceId; + struct _cached_images { + PmCompositeImage_t **cachedComposite; // Array of allocated Frozen STH CompImages + time_t *lastUsed; // Array of last time used for the same index image + PmHistoryRecord_t **records; // Array to indicate what record is frozen in above arrays + } CachedImages; + struct _loaded_image { + PmImage_t *img; + PmHistoryRecord_t *record; // pointer to record of the loaded image + time_t lastUsed; // time of last access. + } LoadedImage; + char **invalidFiles; // keeps track of history filenames with a version mismatch + uint32 oldestInvalid; // index of the oldest invalid file + PmHistoryRecord_t **historyRecords; +} PmShortTermHistory_t; + +// ---------------------------------------------------------- +typedef struct PmDispPerfMap_s { + uint16 phase_aid; + uint8 phase_node_type; + uint8 phase_method; + size_t phase_offset; +} PmDispPerfMap_t; + +typedef struct PmDispatcherPerfPhase_s { + uint64_t phase_start; + uint64_t phase_end; + uint64_t min_roundtrip_time; + uint64_t max_roundtrip_time; + uint64_t sum_roundtrip_time; + uint64_t phase_count; +} PmDispatcherPerfPhase_t; +typedef struct PmDispatcherPerf_s { + uint64_t callback_calc_time; + PmDispatcherPerfPhase_t hfi_get_cpi; + PmDispatcherPerfPhase_t sw_get_cpi; + PmDispatcherPerfPhase_t hfi_get_cntrs; + PmDispatcherPerfPhase_t sw_get_data_cntrs; + PmDispatcherPerfPhase_t sw_get_error_cntrs; + PmDispatcherPerfPhase_t hfi_clr_cntrs; + PmDispatcherPerfPhase_t sw_clr_cntrs; + PmDispatcherPerfPhase_t hfi_get_error_info; + PmDispatcherPerfPhase_t sw_get_error_info; + PmDispatcherPerfPhase_t hfi_set_error_info; + PmDispatcherPerfPhase_t sw_set_error_info; +} PmDispatcherPerf_t; + +// high level PM configuration and statistics +typedef struct Pm_s { + ATOMIC_UINT refCount; // used to avoid race between engine shutdown + // and PA client. Counts number of PA client + // queries in progress. + Lock_t stateLock; // a RWTHREAD_LOCK. + // Protects: LastSweepIndex, NumSweeps, + // lastHistoryIndex, history[], freezeFrames[] + // and the following Image[] fields: + // state, nextClientId, sweepNum, ffRefCount, + // lastUsed, historyIndex + uint32 LastSweepIndex; // last completed sweep, see PM_SWEEP_INDEX_INVALID + uint32 lastHistoryIndex;// history index corresponding to lastSweepIndex + uint32 NumSweeps; // total sweeps completed, only written by engine thread + + Lock_t totalsLock; // a RWTHREAD_LOCK. + // Protects: PmPort_t.PortCountersTotal + + // these are look aside buffers to translate from a ImageId to an ImageIndex + uint32 *history; // exclusively for HISTORY + uint32 *freezeFrames; // exclusively for FREEZE_FRAME + + // configuration settings + uint32 pmFlags; // configured (see stl_pa_types.h pmFlags for a list) + uint16 interval; // Sweep Interval (in seconds) + ErrorSummary_t Thresholds; // Category Threshold Values + IntegrityWeights_t integrityWeights; // Weight applied to Counters before calculating Category + CongestionWeights_t congestionWeights; // Weight applied to Counters before calculating Category + CounterSelectMask_t clearCounterSelect; // List of counters to check against ClearThreshold + PmCompositePortCounters_t ClearThresholds; // MAX_VALUE * (ErrorClear/8) + uint16 ErrorClear; // Number of 8ths before we clear a counter + // Copy from pm_config + uint32 NumGroups; // User Configured Groups + HFIs and SWs (All is implied) + PmGroup_t Groups[PM_MAX_GROUPS]; + + // keep these as scratch area for use by current sweep, not kept per image + // private to engine thread, not protected by lock + STL_LID pm_slid; // SLID for packets we send + uint32 changed_count; // last pass synchronized topology with SM + uint32 SweepIndex; // sweep in progress, no lock needed + cl_qmap_t AllNodes; // all PmNode_t keyed by portGuid, engine use only + + // these are private to engine, used to hold sizes for various structures + // to account for the current pm_total_images value being used + uint32 PmPortSize; // PmPort_t size + uint32 PmNodeSize; // PmNode_t size + + struct PmDispatcher_s { + generic_cntxt_t cntx; + PmDispatcherPerf_t perf_stats; + Event_t sweepDone; + uint8 postedEvent; // have we posted the sweepDone event + STL_LID nextLid; + uint16 numOutstandingNodes; // num nodes in Dispatcher.Nodes + PmDispatcherNode_t *DispNodes; // allocated array of PmMaxParallelNodes + } Dispatcher; + + PmShortTermHistory_t ShortTermHistory; + + // must be last in structure so can dynamically size total images in future + PmImage_t *Image; +} Pm_t; + +typedef struct PmVFFocusPortComputeData_s { + uint32 imageInterval; + int vfIdx; + CongestionWeights_t congestionWeights; +} PmVFFocusPortComputeData_t; + +static __inline +void +BSWAP_PM_COMPOSITE_VFVLMAP(PmCompositeVfvlmap_t *Dest, uint32 numVFs) +{ +#if CPU_LE + uint32 i; + + for (i = 0; i < numVFs; i++) { + Dest[i].vlmask = ntoh32(Dest[i].vlmask); + } +#endif +} // End of BSWAP_PM_COMPOSITE_VFVLMAP + +static __inline +void +BSWAP_PM_COMPOSITE_PORT_COUNTERS(PmCompositePortCounters_t *Dest) +{ +#if CPU_LE + Dest->VLSelectMask = ntoh32(Dest->VLSelectMask); + Dest->PortXmitData = ntoh64(Dest->PortXmitData); + Dest->PortRcvData = ntoh64(Dest->PortRcvData); + Dest->PortXmitPkts = ntoh64(Dest->PortXmitPkts); + Dest->PortRcvPkts = ntoh64(Dest->PortRcvPkts); + Dest->PortMulticastXmitPkts = ntoh64(Dest->PortMulticastXmitPkts); + Dest->PortMulticastRcvPkts = ntoh64(Dest->PortMulticastRcvPkts); + Dest->SwPortCongestion = ntoh64(Dest->SwPortCongestion); + Dest->SwPortCongestion = ntoh64(Dest->SwPortCongestion); + Dest->PortRcvFECN = ntoh64(Dest->PortRcvFECN); + Dest->PortRcvBECN = ntoh64(Dest->PortRcvBECN); + Dest->PortXmitTimeCong = ntoh64(Dest->PortXmitTimeCong); + Dest->PortXmitWastedBW = ntoh64(Dest->PortXmitWastedBW); + Dest->PortXmitWaitData = ntoh64(Dest->PortXmitWaitData); + Dest->PortRcvBubble = ntoh64(Dest->PortRcvBubble); + Dest->PortMarkFECN = ntoh64(Dest->PortMarkFECN); + Dest->PortRcvConstraintErrors = ntoh64(Dest->PortRcvConstraintErrors); + Dest->PortRcvSwitchRelayErrors = ntoh64(Dest->PortRcvSwitchRelayErrors); + Dest->PortXmitDiscards = ntoh64(Dest->PortXmitDiscards); + Dest->PortXmitConstraintErrors = ntoh64(Dest->PortXmitConstraintErrors); + Dest->PortRcvRemotePhysicalErrors = ntoh64(Dest->PortRcvRemotePhysicalErrors); + Dest->LocalLinkIntegrityErrors = ntoh64(Dest->LocalLinkIntegrityErrors); + Dest->PortRcvErrors = ntoh64(Dest->PortRcvErrors); + Dest->ExcessiveBufferOverruns = ntoh64(Dest->ExcessiveBufferOverruns); + Dest->FMConfigErrors = ntoh64(Dest->FMConfigErrors); + Dest->LinkErrorRecovery = ntoh32(Dest->LinkErrorRecovery); + Dest->LinkDowned = ntoh32(Dest->LinkDowned); + + +#endif +} // End of BSWAP_PM_COMPOSITE_PORT_COUNTERS + +static __inline +void +BSWAP_PM_COMPOSITE_VL_COUNTERS(PmCompositeVLCounters_t *Dest, uint32 numVLs) +{ +#if CPU_LE + uint32 i; + + for (i = 0; i < numVLs; i++) { + Dest[i].PortVLXmitData = ntoh64(Dest[i].PortVLXmitData); + Dest[i].PortVLRcvData = ntoh64(Dest[i].PortVLRcvData); + Dest[i].PortVLXmitPkts = ntoh64(Dest[i].PortVLXmitPkts); + Dest[i].PortVLRcvPkts = ntoh64(Dest[i].PortVLRcvPkts); + Dest[i].PortVLXmitWait = ntoh64(Dest[i].PortVLXmitWait); + Dest[i].SwPortVLCongestion = ntoh64(Dest[i].SwPortVLCongestion); + Dest[i].PortVLRcvFECN = ntoh64(Dest[i].PortVLRcvFECN); + Dest[i].PortVLRcvBECN = ntoh64(Dest[i].PortVLRcvBECN); + Dest[i].PortVLXmitTimeCong = ntoh64(Dest[i].PortVLXmitTimeCong); + Dest[i].PortVLXmitWastedBW = ntoh64(Dest[i].PortVLXmitWastedBW); + Dest[i].PortVLXmitWaitData = ntoh64(Dest[i].PortVLXmitWaitData); + Dest[i].PortVLRcvBubble = ntoh64(Dest[i].PortVLRcvBubble); + Dest[i].PortVLMarkFECN = ntoh64(Dest[i].PortVLMarkFECN); + Dest[i].PortVLXmitDiscards = ntoh64(Dest[i].PortVLXmitDiscards); + } +#endif +} // End of BSWAP_PM_COMPOSITE_VL_COUNTERS + +// Composite Ports are flattened (not array of pointers) +static __inline +void +BSWAP_PM_COMPOSITE_PORT(PmCompositePort_t *Dest, uint32 numPorts) +{ +#if CPU_LE + uint32 i; + + for (i = 0; i < numPorts; i++) { + Dest[i].guid = ntoh64(Dest[i].guid); + + Dest[i].u.AsReg32 = ntoh32(Dest[i].u.AsReg32); + Dest[i].neighborLid = ntoh32(Dest[i].neighborLid); + + Dest[i].vlSelectMask = ntoh32(Dest[i].vlSelectMask); + Dest[i].clearSelectMask.AsReg32 = ntoh32(Dest[i].clearSelectMask.AsReg32); + + BSWAP_PM_COMPOSITE_VFVLMAP(Dest[i].compVfVlmap, MAX_VFABRICS); + + BSWAP_PM_COMPOSITE_PORT_COUNTERS(&Dest[i].stlPortCounters); + BSWAP_PM_COMPOSITE_VL_COUNTERS(Dest[i].stlVLPortCounters, MAX_PM_VLS); + + BSWAP_PM_COMPOSITE_PORT_COUNTERS(&Dest[i].DeltaStlPortCounters); + BSWAP_PM_COMPOSITE_VL_COUNTERS(Dest[i].DeltaStlVLPortCounters, MAX_PM_VLS); + } +#endif +} // End of BSWAP_PM_COMPOSITE_PORT + +// Composite Nodes are flattened (not array of pointers) +static __inline +void +BSWAP_PM_COMPOSITE_NODE(PmCompositeNode_t *Dest, uint32 numNodes) +{ +#if CPU_LE + PmCompositeNode_t *cnode = Dest; + uint32 i, numPorts; + + for (i = 0; i < numNodes; i++) { + numPorts = (cnode->nodeType == STL_NODE_SW ? cnode->numPorts+1 : cnode->numPorts); + cnode->NodeGUID = ntoh64(cnode->NodeGUID); + cnode->SystemImageGUID = ntoh64(cnode->SystemImageGUID); + cnode->lid = ntoh32(cnode->lid); + BSWAP_PM_COMPOSITE_PORT((PmCompositePort_t *)&cnode->ports, numPorts); + // Calc address of next (flattened) composite node + cnode = (PmCompositeNode_t *)((size_t)cnode + + (sizeof(PmCompositeNode_t) - sizeof(PmCompositePort_t **)) + + (sizeof(PmCompositePort_t) * numPorts)); + } +#endif +} // End of BSWAP_PM_COMPOSITE_NODE + +static __inline +void +BSWAP_PM_COMPOSITE_SM_INFO(PmCompositeSmInfo_t *Dest, uint32 numSMs) +{ +#if CPU_LE + uint32 i; + for (i = 0; i < numSMs; i++) + Dest[i].smLid = ntoh32(Dest[i].smLid); +#endif +} // End of BSWAP_PM_COMPOSITE_SM_INFO + +static __inline +void +BSWAP_PM_HISTORY_VERSION(uint32 *Dest) +{ +#if CPU_LE + *Dest = ntoh32(*Dest); +#endif +} // End of BSWAP_PM_HISTORY_VERSION + +static __inline +void +BSWAP_PM_HISTORY_HEADER_COMMON(PmHistoryHeaderCommon_t *Dest) +{ +#if CPU_LE + uint32 i; + + BSWAP_PM_HISTORY_VERSION(&Dest->historyVersion); + Dest->imageTime = ntoh32(Dest->imageTime); + Dest->timestamp = ntoh64(Dest->timestamp); + Dest->imagesPerComposite = ntoh16(Dest->imagesPerComposite); + Dest->imageSweepInterval = ntoh32(Dest->imageSweepInterval); + for (i = 0; i < PM_HISTORY_MAX_IMAGES_PER_COMPOSITE; i++) + Dest->imageIDs[i] = ntoh64(Dest->imageIDs[i]); + +#endif +} // End of BSWAP_PM_HISTORY_HEADER_COMMON + +static __inline +void +BSWAP_PM_FILE_HEADER(PmFileHeader_t *Dest) +{ +#if CPU_LE + uint32 i; + + BSWAP_PM_HISTORY_HEADER_COMMON(&Dest->common); + Dest->flatSize = ntoh64(Dest->flatSize); + for (i = 0; i < PM_MAX_COMPRESSION_DIVISIONS; i++) + Dest->divisionSizes[i] = ntoh64(Dest->divisionSizes[i]); +#endif +} // End of BSWAP_PM_FILE_HEADER + +// Byte-swap flattened Composite Image +static __inline +void +BSWAP_PM_COMPOSITE_IMAGE_FLAT(PmCompositeImage_t *Dest, boolean hton /*, uint32 historyVersion*/) +{ +#if CPU_LE + uint32 numNodes; + PmCompositeNode_t *cnodes = (PmCompositeNode_t *)&Dest->nodes; + + // Note that header is swapped independently + if (hton) { + numNodes = Dest->maxLid + 1; + Dest->maxLid = ntoh32(Dest->maxLid); + } else { + Dest->maxLid = ntoh32(Dest->maxLid); + numNodes = Dest->maxLid + 1; + } + Dest->sweepStart = ntoh64(Dest->sweepStart); + Dest->sweepDuration = ntoh32(Dest->sweepDuration); + Dest->HFIPorts = ntoh16(Dest->HFIPorts); + Dest->switchNodes = ntoh16(Dest->switchNodes); + Dest->switchPorts = ntoh32(Dest->switchPorts); + Dest->numLinks = ntoh32(Dest->numLinks); + Dest->numSMs = ntoh32(Dest->numSMs); + Dest->noRespNodes = ntoh32(Dest->noRespNodes); + Dest->noRespPorts = ntoh32(Dest->noRespPorts); + Dest->skippedNodes = ntoh32(Dest->skippedNodes); + Dest->skippedPorts = ntoh32(Dest->skippedPorts); + Dest->unexpectedClearPorts = ntoh32(Dest->unexpectedClearPorts); + Dest->downgradedPorts = ntoh32(Dest->downgradedPorts); + Dest->numGroups = ntoh32(Dest->numGroups); + Dest->numVFs = ntoh32(Dest->numVFs); + Dest->numVFsActive = ntoh32(Dest->numVFsActive); + Dest->numPorts = ntoh32(Dest->numPorts); + BSWAP_PM_COMPOSITE_SM_INFO(Dest->SMs, PM_HISTORY_MAX_SMS_PER_COMPOSITE); + + BSWAP_PM_COMPOSITE_NODE(cnodes, numNodes); +#endif +} // End of BSWAP_PM_COMPOSITE_IMAGE_FLAT + +void clearLoadedImage(PmShortTermHistory_t *sth); +size_t computeCompositeSize(void); +FSTATUS decompressAndReassemble(unsigned char *input_data, size_t input_size, uint8 divs, size_t *input_sizes, unsigned char *output_data, size_t output_size); +FSTATUS rebuildComposite(PmCompositeImage_t *cimg, unsigned char *data, uint32 history_version); +void writeImageToBuffer(Pm_t *pm, uint32 histindex, uint8_t isCompressed, uint8_t *buffer, uint32_t *bIndex); +void PmFreeComposite(PmCompositeImage_t *cimg); +FSTATUS PmLoadComposite(Pm_t *pm, PmHistoryRecord_t *record, PmCompositeImage_t **cimg); +FSTATUS PmFreezeComposite(Pm_t *pm, PmHistoryRecord_t *record, int *idx); +FSTATUS PmFreezeCurrent(Pm_t *pm, int *idx); +void PmReconstituteVFImage(PmCompositeVF_t *cVF, PmVF_t *pmVFP); +void PmReconstituteGroupImage(PmCompositeGroup_t *cgroup, PmGroup_t *pmGroupP); +PmPort_t *PmReconstitutePortImage(PmImage_t *img, PmCompositePort_t *cport); +PmNode_t *PmReconstituteNodeImage(PmImage_t *img, PmCompositeNode_t *cnode); +PmImage_t *PmReconstituteImage(PmCompositeImage_t *cimg); +FSTATUS PmReconstitute(PmShortTermHistory_t *sth, PmCompositeImage_t *cimg); + +// Lock Heirachy (acquire in this order): +// SM topology locks +// Pm.stateLock +// Image.imageLock for freeze frames, (in index order, low to high) +// Image.imageLock for sweeps, (in index order, most recent to oldest) +// Pm.totalsLock +// +// Pm.stateLock is a rwlock, protects: +// LastSweepIndex, NumSweeps, lastHistoryIndex, history[], freezeFrames[] +// and the following Image[] fields: +// state, nextClientId, sweepNum, ffRefCount, lastUsed, historyIndex +// Note that NumSweeps and LastSweepIndex are only changed by engine thread, +// hence engine thread can safely read it without a lock +// Pm.SweepIndex is for use by engine only, no lock needed +// +// Pm.Image[index].imageLock is a rwlock, protects: +// all data in image (including PmPort_t.Image[index], PmNode_t.Image[index] +// and Pmgroup_t.Image[index] +// except for fields protected by Pm.stateLock +// pa_access must have this lock and verify state == VALID +// Engine must get this lock in order to update topology or per image stats +// +// Pm.totalsLock is a rwlock, protects: +// PmPort_t.PortCountersTotal +// +// INPROGRESS state helps avoid clients blocking for long duration once +// engine starts sweep. It can also be used in ASSERTs as a secondary check +// to make sure clients are accessing valid data. +// Algorithm for stateLock allows client to check state before tring to +// get imageLock. +// +// pa_access query (for lastsweep, history or freeze frame query): +// rdlock Pm.stateLock +// index= convert image Id using Pm.LastSweepIndex //copy to local while locked +// if Pm.Image[index].state != VALID - error +// (client should not access a freeze area until gets response) +// rdlock Pm.Image[index].imageLock +// rwunlock Pm.stateLock +// if accessing PortCountersTotal, rdlock Pm.totalsLock (wrlock to clear Total) +// analyze data in Pm.Image[index] +// if accessed PortCountersTotal, rwunlock Pm.totalsLock +// rwunlock Pm.Image[index].imageLock +// +// Engine Sweep +// wrlock Pm.stateLock +// index=Pm.SweepIndex // engine can access SweepIndex anytime w/o a lock +// Pm.Image[index].state = INPROGRESS +// wrlock Pm.Image[index].imageLock // make sure clients out +// rwunlock Pm.stateLock - we have in progress flag set +// perform sweep - since it is the "active sweep" pa_access should not try to +// lock it while we sweep, INPROGRESS also protects it +// if alloc or resize lidmap, set to NULLs. +// As populate, inc ref count on node +// when done building lidmap, if have old lidmap to free, dec ref counts +// and free nodes now 0, then free lidmap +// rwunlock Pm.Image[index].imageLock +// wrlock Pm.stateLock +// Pm.Image[index].state = VALID +// update Pm.lastSweepIndex +// rwunlock Pm.stateLock +// +// PA client Freeze Frame (very similar to engine sweeps): +// wrlock Pm.stateLock +// image = requested input image (must not be a freeze frame) +// if Pm.Image[image].state != VALID - error +// pick a Pm.freezeFrames[] to use (one with INVALID or already +// pointing to image) +// while searching, mark as invalid any freezeFrames which are stale +// pick next unused clientId in Pm.Image, set Image[image].ffRefCount bit +// Pm.freezeFrames[] = image +// rwunlock Pm.stateLock +// +// freeze Frame release: +// index must specify a freeze frame type image +// wrlock Pm.stateLock +// if Pm.Image[index].state == INVALID or INPROGRESS - error +// reset Pm.Image[index].ffRefCount bit for Freeze Frame Client Id +// rwunlock Pm.stateLock +// +// shutdown synchronization between PA and Engine +// Pm.refCount counts when PA is in PM, so don't free PM while client is +// still using. +// Engine shutdown: +// set not running +// wait for refCount to be 0 +// PmDestroy +// if want to be paranoid, could wrlock each image before try to free +// that way can be really sure no one is inside the image +// PA client packet processing: +// increment Pm refCount +// check is running - dec refCount, fail query +// do normal processing algorithm: +// lock Pm.stateLock +// process state +// lock imageLock +// unlock Pm.stateLock +// process image +// send response packet +// unlock imageLock +// dec refCount + +// +// PA protocol updates: +// - can specify freeze frame index +// - can specify history index 0 to N +// - bit to indicate if given index is history or freeze frame +// - in sweep summary query, have timestamps, maxLids, etc + +#define PM_ENGINE_STOPPED 0 +#define PM_ENGINE_STARTED 1 +#define PM_ENGINE_STOPPING 2 +extern int g_pmEngineState; + +extern boolean g_pmAsyncRcvThreadRunning; +extern Sema_t g_pmAsyncRcvSema; // indicates AsyncRcvThread is ready +extern IBhandle_t hpma, pm_fd; + +#define PM_ALLBITS_SET(select, mask) (((select) & (mask)) == (mask)) + +// Lookup a node in pmImage based on lid +// caller should have pmImage->imageLock held +PmNode_t *pm_find_node(PmImage_t *pmimagep, STL_LID lid); + +// Lookup a port in pmImage based on lid and portNum +// does not have to be a "lid"'ed port +// caller should have pmImage->imageLock held +PmPort_t *pm_find_port(PmImage_t *pmImage, STL_LID lid, uint8 portNum); + +// Lookup a node in Pm Topology based on nodeguid +PmNode_t *pm_find_nodeguid(Pm_t *pm, uint64 nodeGUID); + +// Clear Running totals for a given Node. This simulates a PMA clear so +// that tools like opareport can work against the Running totals until we +// have a history feature. +// caller must have totalsLock held for write +FSTATUS PmClearNodeRunningCounters(PmNode_t *pmnodep, CounterSelectMask_t select); +FSTATUS PmClearNodeRunningVFCounters(Pm_t *pm, PmNode_t *pmnodep, STLVlCounterSelectMask select, + int vfIdx, boolean useHiddenVF); + +// in mad_info.c +void PmUpdateNodePmaCapabilities(PmNode_t *pmnodep, Node_t *nodep, boolean ProcessHFICounters); +void PmUpdatePortPmaCapabilities(PmPort_t *pmportp, Port_t *portp); + +// pm_mad.c +FSTATUS ProcessPmaClassPortInfo(PmNode_t* pmnodep, STL_CLASS_PORT_INFO *classp); + +// pm_dispatch.c +Status_t PmDispatcherInit(Pm_t *pm); +void PmDispatcherDestroy(Pm_t *pm); +FSTATUS PmSweepAllPortCounters(Pm_t *pm); + +static __inline boolean isErrorInfoNeeded(Pm_t *pm, + PmCompositePortCounters_t *curr, PmCompositePortCounters_t *prev) +{ + if ((pm->pmFlags & STL_PM_PROCESS_ERRORINFO) == 0) return FALSE; + if (!prev) return TRUE; + + // Some counters can be cleared on link bounce, so just check if they are + // different instead of current greater than previous. +#define IS_DIFF_VAL(cntr) if (curr->cntr != prev->cntr) return TRUE + IS_DIFF_VAL(LinkDowned); + IS_DIFF_VAL(PortRcvErrors); + IS_DIFF_VAL(ExcessiveBufferOverruns); + IS_DIFF_VAL(PortXmitConstraintErrors); + IS_DIFF_VAL(PortRcvConstraintErrors); + IS_DIFF_VAL(PortRcvSwitchRelayErrors); + IS_DIFF_VAL(UncorrectableErrors); + IS_DIFF_VAL(FMConfigErrors); +#undef IS_DIFF_VAL + + return FALSE; +} + +static __inline boolean isErrorInfoStatusSet(PmCompositeErrorInfo_t *pErrorInfo) +{ + if (pErrorInfo->PortRcvErrorInfo.s.Status) return TRUE; + if (pErrorInfo->ExcessiveBufferOverrunInfo.s.Status) return TRUE; + if (pErrorInfo->PortXmitConstraintErrorInfo.s.Status) return TRUE; + if (pErrorInfo->PortRcvConstraintErrorInfo.s.Status) return TRUE; + if (pErrorInfo->PortRcvSwitchRelayErrorInfo.s.Status) return TRUE; + if (pErrorInfo->UncorrectableErrorInfo.s.Status) return TRUE; + if (pErrorInfo->FMConfigErrorInfo.s.Status) return TRUE; + + return FALSE; +} + + +// pm_async_rcv.c +extern generic_cntxt_t *pm_async_send_rcv_cntxt; +void pm_async_rcv(uint32_t argc, uint8_t ** argv); +void pm_async_rcv_kill(void); + +#define PM_Filter_Init(FILTERP) { \ + Filter_Init(FILTERP, 0, 0); \ + \ + (FILTERP)->active |= MAI_ACT_ADDRINFO; \ + (FILTERP)->active |= MAI_ACT_BASE; \ + (FILTERP)->active |= MAI_ACT_TYPE; \ + (FILTERP)->active |= MAI_ACT_DATA; \ + (FILTERP)->active |= MAI_ACT_DEV; \ + (FILTERP)->active |= MAI_ACT_PORT; \ + (FILTERP)->active |= MAI_ACT_QP; \ + (FILTERP)->active |= MAI_ACT_FMASK; \ + \ + (FILTERP)->type = MAI_TYPE_EXTERNAL; \ + \ + (FILTERP)->dev = pm_config.hca; \ + (FILTERP)->port = (pm_config.port == 0) ? MAI_TYPE_ANY : pm_config.port; \ + (FILTERP)->qp = 1; \ +} + +// pm_sweep.c +void PmClearAllNodes(Pm_t *pm); +void PmSkipPort(Pm_t *pm, PmPort_t *pmportp); +void PmSkipNode(Pm_t *pm, PmNode_t *pmnodep); + +void PmFailPort(Pm_t *pm, PmPort_t *pmportp, uint8 queryStatus, uint8 method, uint16 aid); +void PmFailPacket(Pm_t *pm, PmDispatcherPacket_t *disppacket, uint8 queryStatus, uint8 method, uint16 aid); +void PmFailNode(Pm_t *pm, PmNode_t *pmnodep, uint8 queryStatus, uint8 method, uint16 aid); + +// pm_debug.c +void DisplayPm(Pm_t *pm); + +uint32 computeSendMBps(Pm_t *pm, uint32 imageIndex, PmPort_t *port, void *data); +uint32 computeSendKPkts(Pm_t *pm, uint32 imageIndex, PmPort_t *port, void *data); +uint32 computeIntegrity(Pm_t *pm, uint32 imageIndex, PmPort_t *port, void *data); +uint32 computeCongestion(Pm_t *pm, uint32 imageIndex, PmPort_t *port, void *data); +uint32 computeSmaCongestion(Pm_t *pm, uint32 imageIndex, PmPort_t *port, void *data); +uint32 computeBubble(Pm_t *pm, uint32 imageIndex, PmPort_t *port, void *data); +uint32 computeSecurity(Pm_t *pm, uint32 imageIndex, PmPort_t *port, void *data); +uint32 computeRouting(Pm_t *pm, uint32 imageIndex, PmPort_t *port, void *data); +uint32 computeUtilizationPct10(Pm_t *pm, uint32 imageIndex, PmPort_t *port, void *data); +uint32 computeDiscardsPct10(Pm_t *pm, uint32 imageIndex, PmPort_t *port, void *data); +uint32 computeVFSendMBps(Pm_t *pm, uint32 imageIndex, PmPort_t *port, void *data); +uint32 computeVFSendKPkts(Pm_t *pm, uint32 imageIndex, PmPort_t *port, void *data); +uint32 computeVFCongestion(Pm_t *pm, uint32 imageIndex, PmPort_t *port, void *data); +uint32 computeVFBubble(Pm_t *pm, uint32 imageIndex, PmPort_t *port, void *data); +uint32 computeVFUtilizationPct10(Pm_t *pm, uint32 imageIndex, PmPort_t *port, void *data); + + +// Given a MBps transfer rate and a theoretical maxMBps, compute the +// utilization bucket number from 0 to PM_UTIL_BUCKETS-1 +static __inline uint8 ComputeUtilBucket(uint32 SendMBps, uint32 maxMBps) +{ + if (maxMBps) { + // directly compute bucket to reduce overflow chances + uint8 utilBucket = (SendMBps * STL_PM_UTIL_BUCKETS) / maxMBps; + if (utilBucket >= STL_PM_UTIL_BUCKETS) + return STL_PM_UTIL_BUCKETS-1; + else + return utilBucket; + } else { + return 0; + } +} + +// Given a Counter Category Value and a threshold, compute the bucket number +// from 0 to PM_ERR_BUCKETS-1 +static __inline uint8 ComputeErrBucket(uint32 errCnt, uint32 errThreshold) +{ + uint8 errBucket; + if (! errThreshold) return 0; + + errBucket = (errCnt * (STL_PM_CATEGORY_BUCKETS-1)) / errThreshold; + if (errBucket >= STL_PM_CATEGORY_BUCKETS) + return STL_PM_CATEGORY_BUCKETS-1; + else + return errBucket; +} + +void PmPrintExceededPort(char *buf, size_t bufSize, PmPort_t *pmportp, uint32 index, const char *statistic, uint32 threshold, uint32 value); +void PmPrintExceededPortDetailsIntegrity(char *exceededMessage, Pm_t *pm, PmPort_t *pmportp, PmPort_t *pmportneighborp, uint32 imageIndex); +void PmPrintExceededPortDetailsCongestion(char *exceededMessage, Pm_t *pm, PmPort_t *pmportp, PmPort_t *pmportneighborp, uint32 imageIndex); +void PmPrintExceededPortDetailsSmaCongestion(char *exceededMessage, Pm_t *pm, PmPort_t *pmportp, PmPort_t *pmportneighborp, uint32 imageIndex); +void PmPrintExceededPortDetailsBubble(char *exceededMessage, Pm_t *pm, PmPort_t *pmportp, PmPort_t *pmportneighborp, uint32 imageIndex); +void PmPrintExceededPortDetailsSecurity(char *exceededMessage, Pm_t *pm, PmPort_t *pmportp, PmPort_t *pmportneighborp, uint32 imageIndex); +void PmPrintExceededPortDetailsRouting(char *exceededMessage, Pm_t *pm, PmPort_t *pmportp, PmPort_t *pmportneighborp, uint32 imageIndex); +void PmFinalizePortStats(Pm_t *pm, PmPort_t *portp, uint32 index); +boolean PmTabulatePort(Pm_t *pm, PmPort_t *portp, uint32 index, + uint32 *counterSelect); +void ClearGroupStats(PmGroupImage_t *groupImage); +void ClearVFStats(PmVFImage_t *vfImage); +void FinalizeGroupStats(PmGroupImage_t *groupImage); +void PmClearPortImage(PmPortImage_t *portImage); +void FinalizeVFStats(PmVFImage_t *vfImage); + +uint32_t PmCalculateRate(uint32_t speed, uint32_t width); +void UpdateInGroupStats(Pm_t *pm, uint32 imageIndex, PmPort_t *port, PmGroupImage_t *groupImage, uint32 imageInterval); +void UpdateExtGroupStats(Pm_t *pm, uint32 imageIndex, PmPort_t *port, PmGroupImage_t *groupImage, uint32 imageInterval); +void UpdateVFStats(Pm_t *pm, uint32 imageIndex, PmPort_t *port, PmVFImage_t *vfImage, uint32 imageInterval); + +// Clear Running totals for a given Port. This simulates a PMA clear so +// that tools like opareport can work against the Running totals until we +// have a history feature. +// caller must have totalsLock held for write +extern FSTATUS PmClearPortRunningCounters(PmPort_t *pmportp, CounterSelectMask_t select); +extern FSTATUS PmClearPortRunningVFCounters(Pm_t *pm, PmPort_t *pmportp, STLVlCounterSelectMask select, int vfIdx, boolean useHiddenVF); + +// ? PMA Counter control allows interval and auto restart of counters, can remove +// effect of PMA packet delays, etc. Should we use it? Does HW support it? + +// compute theoretical limits for each rate +//extern void PM_InitLswfToMBps(void); +// ideally should be static, extern due to split of sweep.c and calc.c +uint32 s_StaticRateToMBps[IB_STATIC_RATE_MAX+1]; + +// This group of functions accept an index into the pmportp->Groups[] +// caller should search for appropriate entry in array to act on +// adds a port to a group. used by PmAddExtPort and PmAddIntPort +void PmAddPortToGroupIndex(PmPortImage_t* portImage, uint32 grpIndex, PmGroup_t *groupp, boolean internal); + +boolean PmIsPortInGroup(PmImage_t *pmimagep, PmPortImage_t *portImage, + int groupIndex, boolean isAllGroup, boolean *isInternal); +boolean PmIsPortInVF(PmImage_t *pmimagep, PmPortImage_t *portImage, + int vfIndex); + +// adds a port to a group where the neighbor of the port WILL NOT be in +// the given group +void PmAddExtPortToGroupIndex(PmPortImage_t* portImage, uint32 grpIndex, PmGroup_t *groupp, uint32 imageIndex); + +// adds a port to a group where the neighbor of the port WILL be in +// the given group +// This DOES NOT add the neighbor. Caller must do that separately. +void PmAddIntPortToGroupIndex(PmPortImage_t* portImage, uint32 grpIndex, PmGroup_t *groupp, uint32 imageIndex); + +// compute reasonable clearThresholds based on given threshold and weights +// This can be used to initialize clearThreshold and then override just +// a few of the computed defaults in the even user wanted to control just a few +// and default the rest +void PmComputeClearThresholds(PmCompositePortCounters_t *clearThresholds, + CounterSelectMask_t *select, uint8 errorClear); + +// build counter select to use when clearing counters +void PM_BuildClearCounterSelect(CounterSelectMask_t *select, boolean clearXfer, boolean clear64bit, + boolean clear32bit, boolean clear8bit); + +// insert a shortterm history file from the Master PM into the local history filelist +FSTATUS injectHistoryFile(Pm_t *pm, char *filename, uint8_t *buffer, uint32_t filelen); + +void PmDispatcherPerfInit(PmDispatcherPerf_t *perf); + + + +// PM Loop MACROS +#define for_some_pmnodes(PMIMAGE, PMNODE, LID, START, END) \ + for (LID = START, PMNODE = (PMIMAGE)->LidMap[LID]; LID <= END; ++LID, PMNODE = (PMIMAGE)->LidMap[LID]) \ + if (PMNODE) + +#define for_all_pmnodes(PMIMAGE, PMNODE, LID) \ + for_some_pmnodes(PMIMAGE, PMNODE, LID, 1, (PMIMAGE)->maxLid) + +#define pm_get_port(PMNODE, PORTNUM) ((PMNODE)->nodeType == STL_NODE_SW ? (PMNODE)->up.swPorts[PORTNUM] : (PMNODE)->up.caPortp) +#define pm_get_port_idx(PMNODE) ((PMNODE)->nodeType == STL_NODE_SW ? 0 : 1) + +#define for_some_pmports(PMNODE, PMPORT, PORTNUM, START, END) \ + for (PORTNUM = START, PMPORT = pm_get_port(PMNODE, PORTNUM); \ + PORTNUM <= END; \ + ++PORTNUM, PMPORT = pm_get_port(PMNODE, PORTNUM)) + +#define for_all_pmports(PMNODE, PMPORT, PORTNUM) \ + for_some_pmports(PMNODE, PMPORT, PORTNUM, pm_get_port_idx(PMNODE), (PMNODE)->numPorts) + +#include "iba/public/ipackoff.h" + +#ifdef __cplusplus +}; +#endif + +#endif /* _PM_TOPOLOGY_H */ diff --git a/Esm/ib/src/smi/include/README b/Esm/ib/src/smi/include/README new file mode 100644 index 0000000..e666c8e --- /dev/null +++ b/Esm/ib/src/smi/include/README @@ -0,0 +1,41 @@ +/* BEGIN_ICS_COPYRIGHT10 **************************************** + +Copyright (c) 2015, Intel Corporation +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: +- Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. +- Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. +- Neither the name of Intel Corporation nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL INTEL, THE COPYRIGHT OWNER OR CONTRIBUTORS +BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. + +EXPORT LAWS: THIS LICENSE ADDS NO RESTRICTIONS TO THE EXPORT LAWS OF YOUR +JURISDICTION. It is licensee's responsibility to comply with any export +regulations applicable in licensee's jurisdiction. Under CURRENT (May 2000) +U.S. export regulations this software is eligible for export from the U.S. +and can be downloaded by or otherwise exported or reexported worldwide EXCEPT +to U.S. embargoed destinations which include Cuba, Iraq, Libya, North Korea, +Iran, Syria, Sudan, Afghanistan and any other country to which the U.S. has +embargoed goods and services. + +** END_ICS_COPYRIGHT10 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ +include files internal to the SM/SA diff --git a/Esm/ib/src/smi/include/sa_l.h b/Esm/ib/src/smi/include/sa_l.h new file mode 100644 index 0000000..1e2e0af --- /dev/null +++ b/Esm/ib/src/smi/include/sa_l.h @@ -0,0 +1,432 @@ +/* BEGIN_ICS_COPYRIGHT2 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT2 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +//===========================================================================// +// // +// FILE NAME // +// sa_l.h // +// // +// DESCRIPTION // +// This file contains the localized SA definitions. These definitions // +// do NOT appear in the IBTA specs. They are implementation dependent. // +// // +// DATA STRUCTURES // +// None // +// // +// FUNCTIONS // +// None // +// // +// DEPENDENCIES // +// ib_mad.h // +// ib_status.h // +// ib_const.h // +// sm_pool.h // +// sm_event.h // +// sm_thread.h // +// // +// // +//===========================================================================// + +#ifndef _SA_L_H_ +#define _SA_L_H_ + +#include "ib_const.h" +#include "ib_types.h" +#include "cs_g.h" +#include "cs_hashtable.h" + +// JSY - this is temporary +#define mai_poll(FD, MAIP) mai_recv(FD, MAIP, 1) + +/* Fake portGuid to use when auto-creating the multicast group */ +#define SA_FAKE_MULTICAST_GROUP_MEMBER 0x00066A00FACADE01ull + +// +// This struct is for the queued MAD requests to the SA> +// +#define SA_MADS 256 + +typedef struct { + Mai_t mad; + uint64_t timer; +} SAQueue_t; + +#define SA_Queue_Empty() (sarp == sawp) +#define SA_Queue_Full() (((sarp+1) == sawp) || \ + ((sarp == &sa_queue[SA_MADS-1]) && \ + (sawp == &sa_queue[0]))) +#define SA_Queue_Inc(QP) ((QP) != &sa_queue[SA_MADS - 1]) ? \ + (QP)+1 : &sa_queue[0] + + +// +// A frequently used debugging macro. +// +#define SAPrint(HDR, MAIP) \ + printf("%s: %02x %04x %08x %016Lx -> %02x\n", (HDR), \ + (MAIP)->base.method, \ + (MAIP)->base.aid, \ + (MAIP)->base.amod, \ + (MAIP)->base.tid, \ + (MAIP)->base.status); + +// +// Comparison mask definitions. +// +// These arrays contain the number of bytes to compare for the template +// query case. +// +typedef struct _FieldMask { + uint16_t offset; // offset from 'bit 0' + uint16_t length; // number of bits in field +} FieldMask_t; + +// +// Scratch pad for template queries. +// +extern uint8_t template_mask[4096]; +extern uint32_t template_offset; +extern uint32_t template_length; +extern FieldMask_t *template_fieldp; + +// +// SA Caching +// + +#define SA_NUM_CACHES 2 // number of cached query types + +#define SA_CACHE_FI_NODES 0 // all NodeRecords where NodeType == FI +#define SA_CACHE_SWITCH_NODES 1 // all NodeRecords where NodeType == Switch + +#define SA_CACHE_CLEAN_INTERVAL 30*VTIMER_1S // time between clearing of the + // "previous" list of in-use elements + +#define SA_CACHE_NAME_LEN 16 // max length of cache name + +// represents a cache containing the response data for a specific SA query +typedef struct SACacheEntry { + char name[SA_CACHE_NAME_LEN]; // name of cache for debugging + uint8_t valid; // true if cache contains data + uint8_t transient; // marks a temporary cache structure + uint8_t *data; // wire-ready cached data + uint32_t len; // length of cached data + uint32_t refCount; // # of outstanding references to this cache + uint32_t records; // number of records represented by this cache + struct SACacheEntry *next; // used for "previous" list +} SACacheEntry_t; + +// consolidation of cached data sets into a single structure +typedef struct { + SACacheEntry_t *current[SA_NUM_CACHES]; // array of current caches + SACacheEntry_t *build[SA_NUM_CACHES]; // array of caches being built in new topology + SACacheEntry_t *previous; // linked list of all previous caches still in + // use. should be minimal as all queries using + // the caches should finish between sweeps + Lock_t lock; // lock mediating topology and query threads +} SACache_t; + +// prototype of function to be called to build each cache +typedef Status_t (*SACacheBuildFunc_t)(SACacheEntry_t *, Topology_t *); + +// +// Authentication structure. +// +typedef struct { + STL_LID lid; // 16 bit Lid + Node_t *nodep; // node for this Lid + Port_t *portp; // port on the node for this Lid + PKey_t pKeys[SM_PKEYS]; // PKeys for comparison + uint32_t numKeys; +} Authenticator_t; + +#define SA_CNTXT_HASH_TABLE_DEPTH 64 +extern uint32_t sa_max_cntxt; +extern uint32_t sa_data_length; // maximum SA response size +extern uint32_t sa_max_ib_path_records;// maximum IB path records in one response +#define SA_CNTXT_MAX_GUIDINFO 256 +#define SA_CNTXT_MAX_STANDARD 256 +typedef struct sa_cntxt { + uint64_t tstamp ; + uint64_t tid ; // Tid for hash table search + STL_LID lid ; // Lid for hash table search + uint16_t method; // initial method requested by initiator + IBhandle_t sendFd; // mai handle to use for sending packets (fd_sa for 1st seg and fd_sa_w threafter) + uint8_t hashed ; // Entry is inserted into the hash table + uint32_t ref ; // Reference count for the structure + uint32_t reqDataLen; // length of the getMulti request MAD + char* reqData ; // Data pointer for input getMulti MAD + char* data ; // Data pointer for MAD rmpp response + uint32_t len ; // Length of the MAD response + uint16_t attribLen; // num 8-byte words from start of one attrib to start of next + Mai_t mad ; + /* 1.1 related fields */ + uint32_t WF; // Window First: segNum that is first packet in current window + uint32_t WL; // Window Last: segNum that is last packet in current window + uint32_t NS; // Next segNum to be tranmitted by Sender + uint32_t ES; // segNum expected next (Receiver side) + uint16_t isDS; // Double sided getMulti in effect + uint16_t reqInProg; // receipt of request in progress + uint64_t RespTimeout;// current response timeout value (13.6.3.1) + uint64_t tTime; // total transaction timeout value (13.6.3.2) + uint16_t retries; // retry count + uint16_t last_ack; // last segment number acked + uint16_t segTotal; // total segments in response + struct sa_cntxt *next ; // Link List next pointer + struct sa_cntxt *prev ; // Link List prev pointer + uint8_t chkSum; // checksum of rmpp response + SACacheEntry_t *cache; // pointer to cache structure if applicable + Status_t (*freeDataFunc)(struct sa_cntxt *); // func to call to free data. may + // either free locally allocated data, or defer to + // the cache mechanism to decref the cache + Status_t (*processFunc)(Mai_t *, struct sa_cntxt *); // function to call + // to process the incoming packet. +} sa_cntxt_t ; + +// +// Macros for SA filter creation. +// +#define SA_Filter_Init(FILTERP) { \ + Filter_Init(FILTERP, 0, 0); \ + \ + (FILTERP)->active |= MAI_ACT_ADDRINFO; \ + (FILTERP)->active |= MAI_ACT_BASE; \ + (FILTERP)->active |= MAI_ACT_TYPE; \ + (FILTERP)->active |= MAI_ACT_DATA; \ + (FILTERP)->active |= MAI_ACT_DEV; \ + (FILTERP)->active |= MAI_ACT_PORT; \ + (FILTERP)->active |= MAI_ACT_QP; \ + (FILTERP)->active |= MAI_ACT_FMASK; \ + \ + (FILTERP)->type = MAI_TYPE_EXTERNAL; \ + (FILTERP)->type = MAI_TYPE_ANY; /* JSY - temp fix for CAL */ \ + \ + (FILTERP)->dev = sm_config.hca; \ + (FILTERP)->port = (sm_config.port == 0) ? MAI_TYPE_ANY : sm_config.port; \ + (FILTERP)->qp = 1; \ +} + +typedef enum { + ContextAllocated = 1, // new context allocated + ContextNotAvailable = 2, // out of context + ContextExist = 3, // general duplicate request + ContextExistGetMulti = 4 // existing getMult request +} SAContextGet_t; + +// +// Rate macros - these allow us to compare rates easily +// +#define linkrate_eq(r1, r2) ((r1) == (r2)) +#define linkrate_ne(r1, r2) ((r1) != (r2)) +#define linkrate_lt(r1, r2) (StlStaticRateToMbps(r1) < StlStaticRateToMbps(r2)) +#define linkrate_le(r1, r2) (StlStaticRateToMbps(r1) <= StlStaticRateToMbps(r2)) +#define linkrate_gt(r1, r2) (StlStaticRateToMbps(r1) > StlStaticRateToMbps(r2)) +#define linkrate_ge(r1, r2) (StlStaticRateToMbps(r1) >= StlStaticRateToMbps(r2)) + +// iterators to help construct Path Record responses +typedef struct lid_iterator_s { + STL_LID src_start; + STL_LID src_endp1; + STL_LID src_lmc_mask; + STL_LID dst_start; + STL_LID dst_endp1; + STL_LID dst_lmc_mask; + STL_LID slid; + STL_LID dlid; + uint8 phase; + uint8 end_phase; +} lid_iterator_t; + +// these are defined in fm_xml.h +//#define PATH_MODE_MINIMAL 0 // no more than 1 path per lid +//#define PATH_MODE_PAIRWISE 1 // cover every lid on "bigger side" exactly once +//#define PATH_MODE_ORDERALL 2 // PAIRWISE, then all src, all dst (skip dups) +//#define PATH_MODE_SRCDSTALL 3 // all src, all dst + +void lid_iterator_init(lid_iterator_t *iter, + Port_t *src_portp, STL_LID src_start_lid, STL_LID src_lid_len, + Port_t *dst_portp, STL_LID dst_start_lid, STL_LID dst_lid_len, + int path_mode, + STL_LID *slid, STL_LID *dlid); +int lid_iterator_done(lid_iterator_t *iter); +void lid_iterator_next(lid_iterator_t *iter, STL_LID *slid, STL_LID *dlid); +// This handles 1 fixed lid, 1 GID or wildcard style queries. +// src is the fixed side, dst is the iterated side. +// doesn't really matter if src is source or dest and visa versa +void lid_iterator_init1(lid_iterator_t *iter, + Port_t *src_portp, STL_LID slid, STL_LID src_lid_start, STL_LID src_lid_len, + Port_t *dst_portp, STL_LID dst_lid_start, STL_LID dst_lid_len, + int path_mode, + STL_LID *dlid); +int lid_iterator_done1(lid_iterator_t *iter); +void lid_iterator_next1(lid_iterator_t *iter, STL_LID *dlid); + +// +// External declarations. +// +extern SubscriberTable_t saSubscribers; +extern ServiceRecTable_t saServiceRecords; +extern uint32_t saDebugRmpp; // controls output of SA INFO RMPP+ messages +extern uint32_t saRmppCheckSum; // rmppp response checksum control +extern uint8_t *sa_data; +extern SACache_t saCache; +extern SACacheBuildFunc_t saCacheBuildFunctions[]; + +// +// Prototypes +// +Status_t sa_SubscriberInit(void); +void sa_SubscriberDelete(void); +void sa_SubscriberClear(void); +Status_t sa_ServiceRecInit(void); +void sa_ServiceRecDelete(void); +void sa_ServiceRecClear(void); +Status_t sa_McGroupInit(void); +void sa_McGroupDelete(void); +Status_t sa_Authenticate_Path(STL_LID, STL_LID); +Status_t sa_Authenticate_Access(uint32_t, STL_LID, STL_LID, STL_LID); +Status_t sa_Compare_Node_Port_PKeys(Node_t*, Port_t*); +Status_t sa_Compare_Port_PKeys(Port_t*, Port_t*); +uint32_t saDebugPerf; // control SA performance messages; default is off + +Status_t sa_data_offset(uint16_t class, uint16_t type); +Status_t sa_create_template_mask(uint16_t, uint64_t); +Status_t sa_template_test_mask(uint64_t, uint8_t *, uint8_t **, uint32_t, uint32_t, uint32_t *); +Status_t sa_template_test(uint8_t *, uint8_t **, uint32_t, uint32_t, uint32_t *); +Status_t sa_template_test_noinc(uint8_t *, uint8_t *, uint32_t); +void sa_increment_and_pad(uint8_t **, uint32_t, uint32_t, uint32_t *); +Status_t sa_check_len(uint8_t *, uint32_t, uint32_t); + +Status_t sa_getMulti_resend_ack(sa_cntxt_t *); +Status_t sa_send_reply(Mai_t *, sa_cntxt_t*); +Status_t sa_send_multi(Mai_t *, sa_cntxt_t*); +Status_t sa_send_single(Mai_t *, sa_cntxt_t*); + +Status_t sa_ClassPortInfo(Mai_t *, sa_cntxt_t* ); +Status_t sa_InformInfo(Mai_t *, sa_cntxt_t* ); +Status_t sa_InformRecord(Mai_t *, sa_cntxt_t* ); +Status_t sa_LFTableRecord(Mai_t *, sa_cntxt_t* ); + + +Status_t sa_LinkRecord(Mai_t *, sa_cntxt_t* ); +Status_t sa_McMemberRecord(Mai_t *, sa_cntxt_t* ); +Status_t sa_MFTableRecord(Mai_t *, sa_cntxt_t* ); +Status_t sa_NodeRecord(Mai_t *, sa_cntxt_t* ); +Status_t sa_PartitionRecord(Mai_t *, sa_cntxt_t* ); +Status_t sa_PathRecord(Mai_t *, sa_cntxt_t* ); +Status_t sa_PortInfoRecord(Mai_t *, sa_cntxt_t* ); +Status_t sa_SAResponse(Mai_t *, sa_cntxt_t* ); +Status_t sa_SCSCTableRecord(Mai_t *, sa_cntxt_t* ); +Status_t sa_SLSCTableRecord(Mai_t *, sa_cntxt_t* ); +Status_t sa_SCSLTableRecord(Mai_t *, sa_cntxt_t* ); +Status_t sa_SCVLTableRecord(Mai_t *, sa_cntxt_t* ); +Status_t sa_SMInfoRecord(Mai_t *, sa_cntxt_t* ); +Status_t sa_ServiceRecord(Mai_t *, sa_cntxt_t* ); +Status_t sa_ServiceRecord_Age(uint32_t *); +Status_t sa_SwitchInfoRecord(Mai_t *, sa_cntxt_t* ); +Status_t sa_Trap(Mai_t *); +Status_t sa_VLArbitrationRecord(Mai_t *, sa_cntxt_t* ); + + +Status_t sa_TraceRecord(Mai_t *, sa_cntxt_t* ); +Status_t sa_VFabricRecord(Mai_t *, sa_cntxt_t* ); +Status_t sa_JobManagement(Mai_t *, sa_cntxt_t* ); +Status_t sa_FabricInfoRecord(Mai_t *, sa_cntxt_t* ); +Status_t sa_QuarantinedNodeRecord(Mai_t *, sa_cntxt_t* ); +Status_t sa_CongInfoRecord(Mai_t *, sa_cntxt_t* ); +Status_t sa_CableInfoRecord(Mai_t *, sa_cntxt_t* ); +Status_t sa_SwitchCongRecord(Mai_t *, sa_cntxt_t* ); +Status_t sa_SwitchPortCongRecord(Mai_t *, sa_cntxt_t* ); +Status_t sa_HFICongRecord(Mai_t *, sa_cntxt_t* ); +Status_t sa_HFICongCtrlRecord(Mai_t *, sa_cntxt_t* ); +Status_t sa_BufferControlTableRecord(Mai_t *, sa_cntxt_t* ); +Status_t sa_PortGroupRecord(Mai_t *, sa_cntxt_t* ); +Status_t sa_PortGroupFwdRecord(Mai_t *, sa_cntxt_t* ); +Status_t sa_DeviceGroupMemberRecord(Mai_t *, sa_cntxt_t * ); +Status_t sa_DeviceGroupNameRecord(Mai_t *, sa_cntxt_t * ); +Status_t sa_DeviceTreeMemberRecord(Mai_t *, sa_cntxt_t * ); +Status_t sa_NodeRecord_BuildCACache(SACacheEntry_t *, Topology_t *); +Status_t sa_NodeRecord_BuildSwitchCache(SACacheEntry_t *, Topology_t *); + +Status_t sa_SwitchCostRecord(Mai_t *, sa_cntxt_t* ); + +Status_t pathrecord_userexit(uint8_t *, uint32_t *); +Status_t multipathrecord_userexit(uint8_t *, uint32_t *); +Status_t servicerecord_userexit(Mai_t *); +Status_t tracerecord_userexit(uint8_t *, uint32_t *); + +Status_t sa_process_getmulti(Mai_t *, sa_cntxt_t*); +Status_t sa_process_mad(Mai_t *, sa_cntxt_t*); +Status_t sa_process_inflight_rmpp_request(Mai_t *, sa_cntxt_t*); +void sa_main_reader(uint32_t, uint8_t **); +void sa_main_writer(uint32_t argc, uint8_t ** argv); +void sa_cntxt_age(void); +sa_cntxt_t* sa_cntxt_find( Mai_t* ); +SAContextGet_t sa_cntxt_get( Mai_t*, void**); +Status_t sa_cntxt_release( sa_cntxt_t* ); +Status_t sa_cntxt_reserve( sa_cntxt_t* ); +Status_t sa_cntxt_data( sa_cntxt_t*, void*, uint32_t ); +Status_t sa_cntxt_data_cached(sa_cntxt_t *, void *, uint32_t, SACacheEntry_t *); +void sa_cntxt_clear(void); +Status_t sa_SetDefBcGrp( void ); + +Status_t sa_cache_init(void); +Status_t sa_cache_alloc_transient(SACacheEntry_t *[], int, SACacheEntry_t **); +Status_t sa_cache_get(int, SACacheEntry_t **); +void sa_cache_clean(void); +Status_t sa_cache_release(SACacheEntry_t *); +Status_t sa_cache_cntxt_free(sa_cntxt_t *); + +char * sa_getMethodText(int method); +char * sa_getAidName(uint16_t aid); + +void dumpGid(IB_GID gid); +void dumpGuid(Guid_t guid); +void dumpBytes(uint8_t * bytes, size_t num_bytes); +void dumpHWords(uint16_t * hwords, size_t num_hwords); +void dumpWords(uint32_t * words, size_t num_words); +void dumpGuids(Guid_t * guids, size_t num_guids); + +STL_SERVICE_RECORD* getNextService(uint64_t *serviceId, IB_GID *serviceGid, uint16_t *servicep_key, STL_SERVICE_RECORD *pSrp); +STL_SERVICE_RECORD* getService(uint64_t *serviceId, IB_GID *serviceGid, uint16_t *servicep_key, STL_SERVICE_RECORD *pSrp); + +McGroup_t* getBroadCastGroup(IB_GID * pGid, McGroup_t *pGroup); +McGroup_t* getNextBroadCastGroup(IB_GID * pGid, McGroup_t *pGroup); +McMember_t* getBroadCastGroupMember(IB_GID * pGid, uint32_t index, McMember_t *pMember); +McMember_t* getNextBroadCastGroupMember(IB_GID * pGid, uint32_t *index, McMember_t *pMember); +Status_t clearBroadcastGroups(int); // TRUE=recreate broadcast group + +Status_t sa_McMemberRecord_Set(Topology_t *topop, Mai_t *maip, uint32_t *records); +Status_t sa_McMemberRecord_Delete(Topology_t *topop, Mai_t *maip, uint32_t *records); + +Status_t sm_sa_forward_trap(STL_NOTICE *noticep); + +#endif // _SA_L_H_ + diff --git a/Esm/ib/src/smi/include/sm_activate.h b/Esm/ib/src/smi/include/sm_activate.h new file mode 100644 index 0000000..8298e65 --- /dev/null +++ b/Esm/ib/src/smi/include/sm_activate.h @@ -0,0 +1,52 @@ +/* BEGIN_ICS_COPYRIGHT2 **************************************** + +Copyright (c) 2018, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT2 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +#if !defined(_SM_ACTIVATE_H_) +#define _SM_ACTIVATE_H_ + +#include "sm_parallelsweep.h" + +typedef struct ActivationRetry { + uint8_t attempts; + uint32_t failures; + MUTEX mutex; +} ActivationRetry_t; + +typedef struct ActivationRetry * pActivationRetry_t; + +Status_t sweep_arm(SweepContext_t *); +Status_t sweep_activate(SweepContext_t *); + +Status_t sm_activate_port(SmMaiHandle_t *fd, Topology_t *topop, Node_t *nodep, + Port_t *portp, uint8_t forceReregister, + pActivationRetry_t retry); +Status_t sm_set_all_reregisters(void); +#endif diff --git a/Esm/ib/src/smi/include/sm_ar.h b/Esm/ib/src/smi/include/sm_ar.h new file mode 100755 index 0000000..750ea27 --- /dev/null +++ b/Esm/ib/src/smi/include/sm_ar.h @@ -0,0 +1,33 @@ +/* BEGIN_ICS_COPYRIGHT2 **************************************** + +Copyright (c) 2018, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT2 ****************************************/ +#ifndef _SM_AR_H_ +#define _SM_AR_H_ +Status_t parallel_ar(ParallelSweepContext_t *psc); +#endif + diff --git a/Esm/ib/src/smi/include/sm_cable_info.h b/Esm/ib/src/smi/include/sm_cable_info.h new file mode 100644 index 0000000..19e1f78 --- /dev/null +++ b/Esm/ib/src/smi/include/sm_cable_info.h @@ -0,0 +1,32 @@ +/* BEGIN_ICS_COPYRIGHT2 **************************************** + +Copyright (c) 2018, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT2 ****************************************/ +#ifndef _SM_CABLE_INFO_H_ +#define _SM_CABLE_INFO_H_ +Status_t parallel_cable_info(SweepContext_t *); +#endif diff --git a/Esm/ib/src/smi/include/sm_congestion.h b/Esm/ib/src/smi/include/sm_congestion.h new file mode 100755 index 0000000..a016b76 --- /dev/null +++ b/Esm/ib/src/smi/include/sm_congestion.h @@ -0,0 +1,32 @@ +/* BEGIN_ICS_COPYRIGHT2 **************************************** + +Copyright (c) 2018, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT2 ****************************************/ +#ifndef _SM_CONGESTION_H_ +#define _SM_CONGESTION_H_ +Status_t parallel_congestion(ParallelSweepContext_t *psc); +#endif diff --git a/Esm/ib/src/smi/include/sm_counters.h b/Esm/ib/src/smi/include/sm_counters.h new file mode 100644 index 0000000..83c7da9 --- /dev/null +++ b/Esm/ib/src/smi/include/sm_counters.h @@ -0,0 +1,484 @@ +/* BEGIN_ICS_COPYRIGHT2 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT2 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +//===========================================================================// +// +// FILE NAME +// sm_counters.h +// +// DESCRIPTION +// +// DATA STRUCTURES +// None +// +// FUNCTIONS +// None +// +// DEPENDENCIES +// ispinlock.h - for ATOMIC_UINT operations +// +// +//===========================================================================// + + +#ifndef _SM_COUNTERS_H_ +#define _SM_COUNTERS_H_ 1 + +#include "ispinlock.h" +#include "ib_mad.h" +#include "ib_sa.h" +#include "mai_g.h" + +// +// SM Counter Definitions +// +typedef enum _smCounters { + // State transitions + smCounterSmStateToDiscovering, + smCounterSmStateToMaster, + smCounterSmStateToStandby, + smCounterSmStateToInactive, + + // Basic Packet Info + smCounterSmPacketTransmits, + smCounterDirectRoutePackets, + smCounterLidRoutedPackets, + smCounterPacketRetransmits, + smCounterSmTxRetriesExhausted, + + // SMA Method/Attributes + smCounterGetNotice, // Get(Notice) + smCounterSetNotice, // Set(Notice) + + // Traps Received + smCounterTrapsReceived, + smCounterTrapPortUp, // Trap 64 + smCounterTrapPortDown, // Trap 65 + smCounterTrapMcGrpCreate, // Trap 66 + smCounterTrapMcGrpDel, // Trap 67 + smCounterTrapUnPath, // Trap 68 + smCounterTrapRePath, // Trap 69 + smCounterTrapPortStateChg, // Trap 128 + smCounterTrapLinkIntegrity, // Trap 129 + smCounterTrapBufOverrun, // Trap 130 + smCounterTrapFlowControl, // Trap 131 + smCounterTrapLocalChg, // Trap 144 + smCounterTrapSysImgChg, // Trap 145 + smCounterTrapBadMKey, // Trap 256 + smCounterTrapBadPKey, // Trap 257 + smCounterTrapBadQKey, // Trap 258 + smCounterTrapBadPKeySwPort, // Trap 259 + smCounterTrapLinkWidthDowngrade, // Trap 2048 + smCounterTrapCostMatrixChange, // Trap 2049 + + smCounterTrapsRepressed, + smCounterGetNodeDescription, // No set + smCounterGetNodeInfo, // No set + smCounterGetSwitchInfo, + smCounterSetSwitchInfo, + smCounterGetPortInfo, + smCounterSetPortInfo, + smCounterGetPortStateInfo, + smCounterSetPortStateInfo, + smCounterGetPKeyTable, + smCounterSetPKeyTable, + smCounterGetSL2SCMappingTable, + smCounterSetSL2SCMappingTable, + smCounterGetSC2SLMappingTable, + smCounterSetSC2SLMappingTable, + smCounterGetSC2VLtMappingTable, + smCounterSetSC2VLtMappingTable, + smCounterGetSC2VLntMappingTable, + smCounterSetSC2VLntMappingTable, + smCounterGetSC2VLrMappingTable, + smCounterSetSC2VLrMappingTable, + smCounterGetSC2SCMappingTable, + smCounterSetSC2SCMappingTable, + smCounterSetSC2SCMultiSet, + smCounterGetVLArbitrationTable, + smCounterSetVLArbitrationTable, + smCounterGetLft, + smCounterSetLft, + smCounterGetMft, + smCounterSetMft, + smCounterGetAggregate, + smCounterSetAggregate, + smCounterGetLedInfo, + smCounterSetLedInfo, + smCounterGetCableInfo, // No Set + smCounterRxGetSmInfo, // SmInfo is an oddball + smCounterGetSmInfo, + smCounterRxSetSmInfo, + smCounterSetSmInfo, + smCounterTxGetRespSmInfo, + smCounterGetPG, + smCounterSetPG, + smCounterGetPGft, + smCounterSetPGft, + smCounterGetBufferControlTable, + smCounterSetBufferControlTable, + smCounterGetARLidMask, + smCounterSetARLidMask, + + // CCA SMA Counters + smCounterGetCongestionInfo, + smCounterGetHfiCongestionSetting, + smCounterSetHfiCongestionSetting, + smCounterGetHfiCongestionControl, + smCounterSetHfiCongestionControl, + smCounterGetSwitchCongestionSetting, + smCounterSetSwitchCongestionSetting, + smCounterGetSwitchPortCongestionSetting, + + smCounterRxGetResp, + + // SMA Response Status codes + smCounterRxSmaMadStatusBusy, + smCounterRxSmaMadStatusRedirect, + smCounterRxSmaMadStatusBadClass, + smCounterRxSmaMadStatusBadMethod, + smCounterRxSmaMadStatusBadAttr, + smCounterRxSmaMadStatusBadField, + smCounterRxSmaMadStatusUnknown, + + // SA Queries + smCounterSaRxGetClassPortInfo, + smCounterSaTxReportNotice, + smCounterSaRxSetInformInfo, + smCounterSaRxGetNodeRecord, + smCounterSaRxGetTblNodeRecord, + smCounterSaRxGetPortInfoRecord, + smCounterSaRxGetTblPortInfoRecord, + + smCounterSaRxGetSc2ScMappingRecord, + smCounterSaRxGetTblSc2ScMappingRecord, + smCounterSaRxGetSl2ScMappingRecord, + smCounterSaRxGetTblSl2ScMappingRecord, + smCounterSaRxGetSc2SlMappingRecord, + smCounterSaRxGetTblSc2SlMappingRecord, + smCounterSaRxGetSc2VltMappingRecord, + smCounterSaRxGetTblSc2VltMappingRecord, + smCounterSaRxGetSc2VlntMappingRecord, + smCounterSaRxGetTblSc2VlntMappingRecord, + smCounterSaRxGetSc2VlrMappingRecord, + smCounterSaRxGetTblSc2VlrMappingRecord, + + smCounterSaRxGetSwitchInfoRecord, + smCounterSaRxGetTblSwitchInfoRecord, + smCounterSaRxGetLftRecord, + smCounterSaRxGetTblLftRecord, + smCounterSaRxGetMftRecord, + smCounterSaRxGetTblMftRecord, + + smCounterSaRxGetVlArbTableRecord, + smCounterSaRxGetTblVlArbTableRecord, + smCounterSaRxGetSmInfoRecord, + smCounterSaRxGetTblSmInfoRecord, + smCounterSaRxGetInformInfoRecord, + smCounterSaRxGetTblInformInfoRecord, + + smCounterSaRxGetLinkRecord, + smCounterSaRxGetTblLinkRecord, + smCounterSaRxGetServiceRecord, + smCounterSaRxSetServiceRecord, + smCounterSaRxGetTblServiceRecord, + smCounterSaRxDeleteServiceRecord, + + smCounterSaRxGetPKeyTableRecord, + smCounterSaRxGetTblPKeyTableRecord, + smCounterSaRxGetPathRecord, + smCounterSaRxGetTblPathRecord, + smCounterSaRxGetMcMemberRecord, + smCounterSaRxSetMcMemberRecord, + smCounterSaRxGetTblMcMemberRecord, + smCounterSaRxDeleteMcMemberRecord, + smCounterSaRxGetTraceRecord, + smCounterSaRxGetMultiPathRecord, + smCounterSaRxGetVfRecord, + smCounterSaRxGetTblVfRecord, + smCounterSaRxGetFabricInfoRecord, + + smCounterSaRxGetQuarantinedNodeRecord, + smCounterSaRxGetTblQuarantinedNodeRecord, + smCounterSaRxGetCongInfoRecord, + smCounterSaRxGetTblCongInfoRecord, + smCounterSaRxGetSwitchCongRecord, + smCounterSaRxGetTblSwitchCongRecord, + smCounterSaRxGetSwitchPortCongRecord, + smCounterSaRxGetTblSwitchPortCongRecord, + smCounterSaRxGetHFICongRecord, + smCounterSaRxGetTblHFICongRecord, + smCounterSaRxGetHFICongCtrlRecord, + smCounterSaRxGetTblHFICongCtrlRecord, + + smCounterSaRxGetBfrCtrlRecord, + smCounterSaRxGetTblBfrCtrlRecord, + smCounterSaRxGetCableInfoRecord, + smCounterSaRxGetTblCableInfoRecord, + + smCounterSaRxGetPortGroupRecord, + smCounterSaRxGetTblPortGroupRecord, + smCounterSaRxGetPortGroupFwdRecord, + smCounterSaRxGetTblPortGroupFwdRecord, + + smCounterSaRxGetSwitchCostRecord, + smCounterSaRxGetTblSwitchCostRecord, + + smCounterSaRxReportResponse, + + smCounterSaRxGetDgMemberRecord, + smCounterSaRxGetTblDgMemberRecord, + smCounterSaRxGetDgNameRecord, + smCounterSaRxGetTblDgNameRecord, + + smCounterSaRxGetDtMemberRecord, + smCounterSaRxGetTblDtMemberRecord, + + // Weird conditions + smCounterSaDuplicateRequests, + smCounterSaDeadRmppPacket, + smCounterSaDroppedRequests, + smCounterSaContextNotAvailable, + + // GetMulti Request stuff + smCounterSaGetMultiNonRmpp, + smCounterSaRxGetMultiInboundRmppAbort, + smCounterSaTxGetMultiInboundRmppAbort, + smCounterSaTxGetMultiAckRetries, + + // SA RMPP Operations + smCounterSaRmppTxRetries, + smCounterRmppStatusStopNoresources, + smCounterRmppStatusAbortInconsistentLastPayloadLength, + + smCounterRmppStatusAbortInconsistentFirstSegnum, + + smCounterRmppStatusAbortBadType, + smCounterRmppStatusAbortNewWindowLastTooSmall, + + smCounterRmppStatusAbortSegnumTooBig, + + smCounterRmppStatusAbortUnsupportedVersion, + + smCounterRmppStatusAbortTooManyRetries, + + smCounterRmppStatusAbortUnspecified, + + // SA Request Response Stuff + smCountersSaTxRespMadStatusBusy, + smCountersSaTxRespMadStatusRedirect, + smCountersSaTxRespMadStatusBadClass, + smCountersSaTxRespMadStatusBadMethod, + smCountersSaTxRespMadStatusBadAttr, + smCountersSaTxRespMadStatusBadField, + smCountersSaTxRespMadStatusSaNoResources, + smCountersSaTxRespMadStatusSaReqInvalid, + smCountersSaTxRespMadStatusSaNoRecords, + smCountersSaTxRespMadStatusSaTooManyRecs, + smCountersSaTxRespMadStatusSaReqInvalidGid, + smCountersSaTxRespMadStatusSaReqInsufficientComponents, + + smCountersSaTxRespMadStatusUnknown, + + // DB Sync Stuff + smCountersDbSyncSendCmd, + smCountersDbSyncSendCmdFailure, + smCountersDbSyncRcvData, + smCountersDbSyncRcvDataFailure, + smCountersDbSyncReply, + smCountersDbSyncReplyFailure, + +#if 0 + // Job Management + smCounterJmRequests, + smCounterJmErrors, + smCounterJmReqClassPortInfo, + smCounterJmReqCreateJob, + smCounterJmReqSetUseMatrix, + smCounterJmReqPollReady, + smCounterJmReqCompleteJob, + smCounterJmReqGetGuidList, + smCounterJmReqGetSwitchMap, + smCounterJmReqGetCostMatrix, + smCounterJmReqGetUseMatrix, + smCounterJmReqGetJobs, +#endif + + smCountersMax // Last value +} sm_counters_t; + +typedef enum _sm_peak_counters { + smMaxSaContextsInUse, + smMaxSaContextsFree, + smMaxSweepTime, // in milliseconds + + smPeakCountersMax // Last value +} sm_peak_counters_t; + +typedef struct _sm_counter { + char * name; + ATOMIC_UINT sinceLastSweep; + ATOMIC_UINT lastSweep; + ATOMIC_UINT total; +} sm_counter_t; + +// +// These are the arrays that contain the counter values... They're definition +// is in sm_counters.c. If you add a counter to either list, be sure to +// add a description for it in sm_counters.c +// +// The smCounters array is used for strictly incrementing counters (i.e. +// one's that you'll use the INCREMENT_COUNTERS() function for. The +// smPeakCounters array is for counters that you'll want to use the +// SET_PEAK_COUNTER() function on. +// +extern sm_counter_t smCounters[smCountersMax]; +extern sm_counter_t smPeakCounters[smPeakCountersMax]; + +// +// This function increments a counter in the smCounters array +// +static __inline__ +void INCREMENT_COUNTER(sm_counters_t counter) { + AtomicIncrementVoid(&smCounters[counter].sinceLastSweep); + AtomicIncrementVoid(&smCounters[counter].total); +} + +// +// This function compares and sets a value in the smPeakCounters array if +// it's greater that the current value. +// +static __inline__ +void SET_PEAK_COUNTER(sm_peak_counters_t counter, const uint32 value) { + uint32 tmp; + + do { + tmp = AtomicRead(&smPeakCounters[counter].sinceLastSweep); + } while ( (value > tmp) + && ! AtomicCompareStore(&smPeakCounters[counter].sinceLastSweep, + tmp, value)); + + do { + tmp = AtomicRead(&smPeakCounters[counter].total); + } while ( (value > tmp) + && ! AtomicCompareStore(&smPeakCounters[counter].total, + tmp, value)); +} + +// +// Convenience function for processing a mad status return code. +// +static __inline__ +void INCREMENT_MAD_STATUS_COUNTERS(Mai_t * mad) { + if (mad->base.mclass == MAD_CV_SUBN_ADM) { + switch (mad->base.status) { + case MAD_STATUS_OK: + break; + case MAD_STATUS_BUSY: + INCREMENT_COUNTER(smCountersSaTxRespMadStatusBusy); + break; + case MAD_STATUS_REDIRECT: + INCREMENT_COUNTER(smCountersSaTxRespMadStatusRedirect); + break; + case MAD_STATUS_BAD_CLASS: + INCREMENT_COUNTER(smCountersSaTxRespMadStatusBadClass); + break; + case MAD_STATUS_BAD_METHOD: + INCREMENT_COUNTER(smCountersSaTxRespMadStatusBadMethod); + break; + case MAD_STATUS_BAD_ATTR: + INCREMENT_COUNTER(smCountersSaTxRespMadStatusBadAttr); + break; + case MAD_STATUS_BAD_FIELD: + INCREMENT_COUNTER(smCountersSaTxRespMadStatusBadField); + break; + case MAD_STATUS_SA_NO_RESOURCES: + INCREMENT_COUNTER(smCountersSaTxRespMadStatusSaNoResources); + break; + case MAD_STATUS_SA_REQ_INVALID: + INCREMENT_COUNTER(smCountersSaTxRespMadStatusSaReqInvalid); + break; + case MAD_STATUS_SA_NO_RECORDS: + INCREMENT_COUNTER(smCountersSaTxRespMadStatusSaNoRecords); + break; + case MAD_STATUS_SA_TOO_MANY_RECS: + INCREMENT_COUNTER(smCountersSaTxRespMadStatusSaTooManyRecs); + break; + case MAD_STATUS_SA_REQ_INVALID_GID: + INCREMENT_COUNTER(smCountersSaTxRespMadStatusSaReqInvalidGid); + break; + case MAD_STATUS_SA_REQ_INSUFFICIENT_COMPONENTS: + INCREMENT_COUNTER(smCountersSaTxRespMadStatusSaReqInsufficientComponents); + break; + default: + INCREMENT_COUNTER(smCountersSaTxRespMadStatusUnknown); + break; + } + } else { // SMA Status + switch (mad->base.status & ~MAD_STATUS_D_BIT) { + case MAD_STATUS_OK: + break; + case MAD_STATUS_BUSY: + INCREMENT_COUNTER(smCounterRxSmaMadStatusBusy); + break; + case MAD_STATUS_REDIRECT: + INCREMENT_COUNTER(smCounterRxSmaMadStatusRedirect); + break; + case MAD_STATUS_BAD_CLASS: + INCREMENT_COUNTER(smCounterRxSmaMadStatusBadClass); + break; + case MAD_STATUS_BAD_METHOD: + INCREMENT_COUNTER(smCounterRxSmaMadStatusBadMethod); + break; + case MAD_STATUS_BAD_ATTR: + INCREMENT_COUNTER(smCounterRxSmaMadStatusBadAttr); + break; + case MAD_STATUS_BAD_FIELD: + INCREMENT_COUNTER(smCounterRxSmaMadStatusBadField); + break; + default: + INCREMENT_COUNTER(smCounterRxSmaMadStatusUnknown); + break; + } + } +} + +// Function prototypes +extern void sm_init_counters(void); +extern void sm_process_sweep_counters(void); +extern void sm_reset_counters(void); +extern void sm_print_counters_to_stream(FILE * out); + +#ifndef __VXWORKS__ +extern char * sm_print_counters_to_buf(void); +#endif + +#endif // _SM_COUNTERS_H_ diff --git a/Esm/ib/src/smi/include/sm_dbsync.h b/Esm/ib/src/smi/include/sm_dbsync.h new file mode 100644 index 0000000..95adad7 --- /dev/null +++ b/Esm/ib/src/smi/include/sm_dbsync.h @@ -0,0 +1,369 @@ +/* BEGIN_ICS_COPYRIGHT2 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT2 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +//===========================================================================// +// +// FILE NAME +// sm_dbsync.h +// +// DESCRIPTION +// This file contains the localized SM data base synchronization definitions. +// +// DATA STRUCTURES +// NONE +// +// FUNCTIONS +// NONE +// +// DEPENDENCIES +// ib_types.h +// ib_mad.h +// ib_status.h +// +// +//===========================================================================// +#ifndef _SM_DBSYNC_H_ +#define _SM_DBSYNC_H_ + +#include "os_g.h" +#include "sm_parallelsweep.h" + +// +// SM DBSYNC structure conversion routines +// +#define SMDBSYNC_NSIZE 84 +#define SMDBSYNC_CCC_NSIZE 56 +#define SMDBSYNC_SEND_FILE_NSIZE 100 + +#define SM_DBSYNC_VERSION 1 +#define SM_DBSYNC_UNKNOWN 0xffffffff + +typedef enum { + DBSYNC_AID_SYNC = 1, + DBSYNC_AID_GROUP, + DBSYNC_AID_SERVICE, + DBSYNC_AID_INFORM, + DBSYNC_AID_MCROOT, + DBSYNC_AID_DATELINE +} DBSyncAid_t; /* Attribute ID (or cmd) to send */ + +typedef enum { + DBSYNC_AMOD_GET = 1, /* get the contents of a dataset */ + DBSYNC_AMOD_SET, /* replace entire dataset with input */ + DBSYNC_AMOD_ADD, /* add (or update existing) a record to the dataset */ + DBSYNC_AMOD_DELETE, /* delete a record from the dataset */ + DBSYNC_AMOD_GET_CCC, /* get the config consistency check data */ + DBSYNC_AMOD_SEND_FILE, /* send a file to standby SM */ + DBSYNC_AMOD_RECONFIG /* request standby SM read local config file */ +} DBSyncAmod_t; /* modifier to AID (cmd) to send */ + +typedef enum { + DBSYNC_CAP_UNKNOWN = 0, + DBSYNC_CAP_ASKING, + DBSYNC_CAP_NOTSUPPORTED, + DBSYNC_CAP_SUPPORTED +} DBSyncCap_t; + +typedef enum { + DBSYNC_STAT_UNINITIALIZED = 0, + DBSYNC_STAT_INPROGRESS, + DBSYNC_STAT_SYNCHRONIZED, + DBSYNC_STAT_FAILURE +} DBSyncStat_t; + +typedef enum { + DBSYNC_TYPE_GET_CAPABILITY = 1, + DBSYNC_TYPE_FULL, + DBSYNC_TYPE_UPDATE, + DBSYNC_TYPE_DELETE, + DBSYNC_TYPE_BROADCAST_FILE, + DBSYNC_TYPE_RECONFIG +} DBSyncType_t; + +typedef enum { + DBSYNC_DATATYPE_NONE, + DBSYNC_DATATYPE_ALL, + DBSYNC_DATATYPE_INFORM, + DBSYNC_DATATYPE_GROUP, + DBSYNC_DATATYPE_SERVICE, + DBSYNC_DATATYPE_MCROOT, + DBSYNC_DATATYPE_FILE, + DBSYNC_DATATYPE_DATELINE_GUID +} DBSyncDatTyp_t; + +/* + * Fabric SM's hash table + */ + typedef struct { + CS_HashTablep smMap; /* pointer to hash map of SM's currently in fabric */ + SMDBCCCSync_t ourChecksums; + Lock_t smLock; /* exclusive lock for when manipulating hash table */ + } SmTable_t; + + typedef struct { + DBSyncStat_t syncStatus; /* 0=un-initialized, 1=in progress, 2=synchronized, 3=failure */ + uint32_t syncFailCount; /* count of consecutive sync attempt failures */ + time_t timeSyncFail; /* time of last sync attempt failure */ + time_t timeLastSync; /* time of last scheduled sync - 0 if never sync'd */ + } SmSyncStat_t; +typedef SmSyncStat_t *SmSyncStatp; /* pointer to sync status structure */ + +typedef struct { + uint8 firstUpdateState; // present state +} PmDbSync_t; +typedef PmDbSync_t *PmDbSyncp; + +#define DBSYNC_MAX_GET_CAP_ATTEMPTS 2 /* try the GET a few times before saying dbsync not supported by SM */ +#define DBSYNC_MAX_FAIL_SYNC_ATTEMPTS 3 /* try to sync a few times before giving up */ +#define DBSYNC_TIME_BETWEEN_SYNC_FAILURES 60 /* retry interval if were in failure status */ + +typedef struct { + uint64_t portguid; /* port guid of SM node (used as hash key) */ + STL_LID lid; /* lid of SM - may not be set yet */ + DBSyncCap_t syncCapability; /* 0=unknown, 1=not supported, 2=supported */ + + SMDBSync_t dbsync; /* db sync data of SM node */ + SMDBCCCSync_t dbsyncCCC; /* db sync CCC data of SM node */ + PmDbSync_t pmdbsync; /* db sync data of the PM node */ + uint8_t configDiff; /* is the config different from master */ + STL_SMINFO_RECORD smInfoRec; /* smInfoRecs of SM instance */ + uint8_t nodeDescString[ND_LEN+1]; /* node description of SM node */ + uint8_t path[64]; /* directed path to SM node */ + uint8_t portNumber; /* port Number of remote node - used only for reporting */ + uint8_t isEmbedded; /* 1: SM is embedded */ + uint64_t lastHello; /* if standby, last hello check */ +} SmRec_t; +typedef SmRec_t *SmRecp; /* sm record pointer type */ +typedef uint64_t SmRecKey_t; /* sm record key type */ +typedef SmRecKey_t *SmRecKeyp; /* pointer to sm record key */ + +/* FIXME PR123899 - convert felib to STL sized MADs. */ +typedef uint8_t SMSyncData_t[200]; /* opaque holder of data to sync */ + +typedef struct { + DBSyncType_t type; /* 1=get capability, 2=full sync, 3=update, 4=delete */ + DBSyncDatTyp_t datatype; /* 1=all (full sync only), 2=InformInfo, 3=groups, 4=services */ + uint64_t portguid; /* portguid of standby SM */ + STL_LID standbyLid; /* lid of the standby SM */ + uint8_t isEmbedded; /* 1: standby SM is embedded */ + SMSyncData_t data; /* opaque data buffer to hold specific sync data */ +}SMSyncReq_t; +typedef SMSyncReq_t *SMSyncReqp; /* Sm Sync Request pointer type */ + +// +// Multicast dbsync structure +// + +typedef struct { + uint8_t mGid[16]; + uint32_t members_full; + uint32_t qKey; + uint16_t pKey; + STL_LID mLid; + uint8_t mtu; + uint8_t rate; + uint8_t life; + uint8_t sl; + uint32_t flowLabel; + uint8_t hopLimit; + uint8_t tClass; + uint8_t scope; + uint8_t filler; + uint16_t membercount; + uint32_t index_pool; /* Next index to use for new Mc Member records */ +} McGroupSync_t; + +//********** SM topology asynchronous send receive response queue ********** +extern cs_Queue_ptr sm_dbsync_queue; +#define SM_DBSYNC_QUEUE_SIZE 128 + +/* SM table */ +extern SmTable_t smRecords; +extern int dbsync_main_exit; /* dbsync thread exit flag */ +extern int dbsync_initialized_flag; /* dbsync initialized indicator */ + +static __inline +void +BSWAPCOPY_SM_DBSYNC_DATA(SMDBSyncp Src, SMDBSyncp Dest) +{ + memcpy(Dest, Src, sizeof(*Src)); + + Dest->version = ntoh32(Dest->version); + Dest->fullSyncStatus = ntoh32(Dest->fullSyncStatus); + Dest->fullSyncFailCount = ntoh32(Dest->fullSyncFailCount); + Dest->fullTimeSyncFail = ntoh32(Dest->fullTimeSyncFail); + Dest->fullTimeLastSync = ntoh32(Dest->fullTimeLastSync); + Dest->informSyncStatus = ntoh32(Dest->informSyncStatus); + Dest->informSyncFailCount = ntoh32(Dest->informSyncFailCount); + Dest->informTimeSyncFail = ntoh32(Dest->informTimeSyncFail); + Dest->informTimeLastSync = ntoh32(Dest->informTimeLastSync); + + Dest->groupSyncStatus = ntoh32(Dest->groupSyncStatus); + Dest->groupSyncFailCount = ntoh32(Dest->groupSyncFailCount); + Dest->groupTimeSyncFail = ntoh32(Dest->groupTimeSyncFail); + Dest->groupTimeLastSync = ntoh32(Dest->groupTimeLastSync); + + Dest->serviceSyncStatus = ntoh32(Dest->serviceSyncStatus); + Dest->serviceSyncFailCount = ntoh32(Dest->serviceSyncFailCount); + Dest->serviceTimeSyncFail = ntoh32(Dest->serviceTimeSyncFail); + Dest->serviceTimeLastSync = ntoh32(Dest->serviceTimeLastSync); + + Dest->mcrootSyncStatus = ntoh32(Dest->mcrootSyncStatus); + Dest->mcrootSyncFailCount = ntoh32(Dest->mcrootSyncFailCount); + Dest->mcrootTimeSyncFail = ntoh32(Dest->mcrootTimeSyncFail); + Dest->mcrootTimeLastSync = ntoh32(Dest->mcrootTimeLastSync); + + Dest->datelineGuidSyncStatus = ntoh32(Dest->datelineGuidSyncStatus); + Dest->datelineGuidSyncFailCount = ntoh32(Dest->datelineGuidSyncFailCount); + Dest->datelineGuidTimeSyncFail = ntoh32(Dest->datelineGuidTimeSyncFail); + Dest->datelineGuidTimeLastSync = ntoh32(Dest->datelineGuidTimeLastSync); +} + +static __inline +void +BSWAPCOPY_SM_DBSYNC_CCC_DATA(SMDBCCCSyncp Src, SMDBCCCSyncp Dest) +{ + memcpy(Dest, Src, sizeof(*Src)); + + Dest->protocolVersion = ntoh32(Dest->protocolVersion); + Dest->smVfChecksum = ntoh32(Dest->smVfChecksum); + Dest->smConfigChecksum = ntoh32(Dest->smConfigChecksum); + Dest->pmConfigChecksum = ntoh32(Dest->pmConfigChecksum); + Dest->emConfigChecksum = ntoh32(Dest->emConfigChecksum); + + Dest->spare1 = ntoh32(Dest->spare1); + Dest->spare2 = ntoh32(Dest->spare2); + Dest->spare3 = ntoh32(Dest->spare3); + Dest->spare4 = ntoh32(Dest->spare4); + Dest->spare5 = ntoh32(Dest->spare5); + Dest->spare6 = ntoh32(Dest->spare6); + Dest->spare7 = ntoh32(Dest->spare7); +} + +static __inline +void +BSWAPCOPY_SM_DBSYNC_FILE_DATA(SMDBSyncFilep Src, SMDBSyncFilep Dest) +{ + memcpy(Dest, Src, sizeof(*Src)); + + Dest->version = ntoh32(Dest->version); + Dest->length = ntoh32(Dest->length); + Dest->activate = ntoh32(Dest->activate); + Dest->type = ntoh32(Dest->type); + Dest->size = ntoh32(Dest->size); + Dest->spare1 = ntoh32(Dest->spare1); + Dest->spare2 = ntoh32(Dest->spare2); + Dest->spare3 = ntoh32(Dest->spare3); + Dest->spare4 = ntoh32(Dest->spare4); +} + +static __inline +void +BSWAPCOPY_SM_DBSYNC_SUBSKEY_DATA(SubscriberKeyp Src, SubscriberKeyp Dest) +{ + memcpy(Dest, Src, sizeof(*Src)); + + Dest->lid = ntoh32(Dest->lid); + Dest->trapnum = ntoh16(Dest->trapnum); + Dest->qpn = ntoh32(Dest->qpn); + Dest->pkey = ntoh16(Dest->pkey); + Dest->qkey = ntoh32(Dest->qkey); + Dest->startLid = ntoh32(Dest->startLid); + Dest->endLid = ntoh32(Dest->endLid); +} + +static __inline +void +BSWAPCOPY_SM_DBSYNC_MC_GROUP_DATA(McGroupSync_t *Src, McGroupSync_t *Dest) +{ + memcpy(Dest, Src, sizeof(*Src)); + + Dest->members_full = ntoh32(Dest->members_full); + Dest->qKey = ntoh32(Dest->qKey); + Dest->pKey = ntoh16(Dest->pKey); + Dest->mLid = ntoh32(Dest->mLid); + Dest->flowLabel = ntoh32(Dest->flowLabel); + Dest->membercount = ntoh16(Dest->membercount); + Dest->index_pool = ntoh32(Dest->index_pool); +} + +static __inline +void +BSWAPCOPY_SM_DBSYNC_RECORD_CNT(uint32_t *Src, uint32_t *Dest) +{ + memcpy(Dest, Src, sizeof(*Src)); + + *Dest = ntoh32(*Dest); +} + +/* + * Sm dbsync prototypes +*/ +void sm_dbsync(uint32_t, uint8_t **); /* sm db sync main function */ +Status_t sm_dbsync_filter_add(IBhandle_t fd, Filter_t *filter, uint8_t mclass, + uint8_t method, uint16_t aid, uint32_t amod, uint64_t tid, const char *subRoutine); +void sm_dbsync_queueMsg(DBSyncType_t syncType, DBSyncDatTyp_t syncDataTye, STL_LID lid, Guid_t portguid, uint8_t isEmbedded, SMSyncData_t); +void sm_dbsync_addSm(Node_t *, Port_t *, STL_SMINFO_RECORD *); +void sm_dbsync_deleteSm(uint64_t); +void sm_dbsync_updateSm(SmRecKey_t, STL_SM_INFO *); +Status_t sm_dbsync_fullSyncCheck(SmRecKey_t); +Status_t sm_dbsync_upSmDbsync(SmRecKey_t, SMDBSyncp); +Status_t sm_dbsync_upSmDbsyncCap(SmRecKey_t, DBSyncCap_t); +Status_t sm_dbsync_upSmDbsyncStat(SmRecKey_t, DBSyncDatTyp_t, DBSyncStat_t); +Status_t sm_dbsync_configCheck(SmRecKey_t, SMDBCCCSyncp); +Status_t sm_dbsync_disableStandbySm(SmRecp, SmCsmMsgCondition_t); +DBSyncStat_t sm_dbsync_getSmDbsyncStat(SmRecKey_t); +Status_t sm_dbsync_getSmDbsync(SmRecKey_t, SMDBSyncp); +boolean sm_dbsync_isUpToDate(SmRecKey_t, char **reason); +DBSyncCap_t sm_dbsync_getDbsyncSupport(SmRecKey_t); +Status_t sm_dbsync_checksums(uint32_t vfCsum, uint32_t smCsum, uint32_t pmCsum); +Status_t sm_dbsync_em_checksums(uint32_t emCsum); +Status_t sm_dbsync_recInit(void); +void sm_dbsync_kill(void); +void sm_dbsync_init(void); +void sm_dbsync_recDelete(void); +void sm_dbsync_recClear(void); +void sm_dbsync_procReq(void); +int sm_dbsync_getSmCount(void); +int sm_dbsync_getActiveSmCount(void); +Status_t sm_dbsync_upsmlist(SweepContext_t *); +Status_t sm_dbsync_syncService(DBSyncType_t, OpaServiceRecordp); +Status_t sm_dbsync_syncInform(DBSyncType_t, SubscriberKeyp, STL_INFORM_INFO_RECORD *); +Status_t sm_dbsync_syncGroup(DBSyncType_t, IB_GID*); +Status_t sm_dbsync_syncMCRoot(DBSyncType_t synctype); +Status_t sm_dbsync_syncFile(DBSyncType_t synctype, SMDBSyncFile_t*); +Status_t sm_dbsync_syncDatelineSwitchGUID(DBSyncType_t); +void sm_dbsync_showSms(void); +void sm_dbsync_standbyHello(SmRecKey_t); +void sm_dbsync_standbyCheck(void); +int sm_send_pm_image(uint64_t portguid, uint32_t histindex, char *histImgFile); +int sm_send_pm_image_complete(uint64_t portguid, Status_t status); +#endif // _SM_DBSYNC_H_ diff --git a/Esm/ib/src/smi/include/sm_df.h b/Esm/ib/src/smi/include/sm_df.h new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/Esm/ib/src/smi/include/sm_df.h diff --git a/Esm/ib/src/smi/include/sm_discovery.h b/Esm/ib/src/smi/include/sm_discovery.h new file mode 100644 index 0000000..316dc2b --- /dev/null +++ b/Esm/ib/src/smi/include/sm_discovery.h @@ -0,0 +1,38 @@ +/* BEGIN_ICS_COPYRIGHT2 **************************************** + +Copyright (c) 2018, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT2 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +#if !defined(_SM_DISCOVERY_H_) +#define _SM_DISCOVERY_H_ + +Status_t sm_setup_local_node(Topology_t * topop, FabricData_t * pdtop); +Status_t sweep_discovery(SweepContext_t *); + +#endif diff --git a/Esm/ib/src/smi/include/sm_dor.h b/Esm/ib/src/smi/include/sm_dor.h new file mode 100644 index 0000000..ff59fe6 --- /dev/null +++ b/Esm/ib/src/smi/include/sm_dor.h @@ -0,0 +1,163 @@ +/* BEGIN_ICS_COPYRIGHT2 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT2 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +//===========================================================================// +// +// FILE NAME +// sm_dor.h +// +// DESCRIPTION +// This file contains the SM Dor/Torus Routing SM definitions. +// +//===========================================================================// + +#ifndef _SM_DOR_H_ +#define _SM_DOR_H_ + + +#define SM_DOR_MAX_TOROIDAL_DIMENSIONS 6 + +// DorBitMaps are indexed by ij using switch indexes. +// +// When switches disappear from the fabric and sm_compactSwitchSpace() runs +// it changes switch indices and the max switch count. This compaction is +// done after the closure bit maps were allocated and set based on +// the old max switch count. Though the closure bit maps are altered +// to take into account the change in switch indices (done in process_swIdx_change), +// the bit map space isn't reallocated, so any index calculations should be based +// on the old count of switches when the closure was computed + +#define DorBitMapsIndex(X,Y) (((X) * (((DorTopology_t *)(sm_topop->routingModule->data))->closure_max_sws)) + (Y)) + +static __inline__ void ijSet(uint32* ijBitmap, int ij) { + ijBitmap[ij >> 5] |= 1 << (ij & 0x1f); +} + +static __inline__ void ijClear(uint32* ijBitmap, int ij) { + ijBitmap[ij >> 5] &= ~((uint32_t)(1 << (ij & 0x1f))); +} + +static __inline__ int ijTest(uint32* ijBitmap, int ij) { + return ((ijBitmap[ij >> 5] & (1 << (ij & 0x1f))) ? 1 : 0); +} + +// DOR Topology Information +// +typedef struct _DorNode { + int8_t coords[SM_DOR_MAX_DIMENSIONS]; + Node_t *node; + int multipleBrokenDims; + struct _DorNode *left[SM_DOR_MAX_DIMENSIONS]; + struct _DorNode *right[SM_DOR_MAX_DIMENSIONS]; +} DorNode_t; + +typedef struct _DorTopology { + // mesh sizing + uint8_t numDimensions; + uint8_t dimensionLength[SM_DOR_MAX_DIMENSIONS]; + // per-dimension coordinate bounds. coordinates are assumed + // contiguous within these bounds + int8_t coordMaximums[SM_DOR_MAX_DIMENSIONS]; + int8_t coordMinimums[SM_DOR_MAX_DIMENSIONS]; + // keep track of coords measured in mesh dimension + int8_t measuredMaximums[SM_DOR_MAX_DIMENSIONS]; + int8_t measuredMinimums[SM_DOR_MAX_DIMENSIONS]; + // for each dimension, true if toroidal + uint8_t toroidal[SM_DOR_MAX_DIMENSIONS]; + // the configured number of toroidal dimensions + uint8_t numToroidal; + // count of toroidal dimensions found till now + uint8_t toroidal_count; + // minimum number of SCs required to route the fabric correctly + uint8_t minReqScs; + // maps the index of all dimensions to an index into only the + // toroidal dimensions + uint8_t toroidalMap[SM_DOR_MAX_DIMENSIONS]; + // flat 2d bitfield indexed on switch indices marking whether + // the cycle-free DOR path is realizable between nodes + size_t dorClosureSize; + uint32_t *dorLeft; + uint32_t *dorRight; + uint32_t *dorBroken; + uint32_t closure_max_sws; //the switch count when the closures were computed + DorNode_t *datelineSwitch; +} DorTopology_t; + +typedef enum { + DorAny = 0, + DorLeft = 1, + DorRight = 2, +} DorDirection; + +static __inline__ int dorClosure(DorTopology_t* dorTop, int i, int j) { + int ij = DorBitMapsIndex(i, j); + if (i == j) return 1; + return (ijTest(dorTop->dorLeft, ij) || ijTest(dorTop->dorRight, ij)); +} + +//===========================================================================// +// DOR COORDINATE ASSIGNMENT +// +typedef struct _detected_dim { + uint8_t dim; + uint64_t neighbor_nodeGuid; + uint8_t port; + uint8_t neighbor_port; + int pos; + Node_t *neighbor_nodep; +} detected_dim_t; + +#define PORT_PAIR_WARN_ARR_SIZE 40 +#define PORT_PAIR_WARN_IDX(X,Y) (((X) * PORT_PAIR_WARN_ARR_SIZE) + (Y)) + +typedef enum { + DIM_LOOKUP_RVAL_FOUND, + DIM_LOOKUP_RVAL_NOTFOUND, + DIM_LOOKUP_RVAL_INVALID +} DimLookupRval_t; + +typedef struct _DorDimension { + uint8_t ingressPort; + uint8_t dimension; + int8_t direction; + uint8_t hyperlink; + cl_map_obj_t portObj; +} DorDimension_t; + +typedef struct _DorDiscoveryState { + uint8_t nextDimension; + uint8_t toroidalOverflow; + uint8_t scsAvailable; // min of SC support of all fabric ISLs + DorDimension_t *dimensionMap[256]; // indexed by egress port +} DorDiscoveryState_t; + + +#endif diff --git a/Esm/ib/src/smi/include/sm_jm.h b/Esm/ib/src/smi/include/sm_jm.h new file mode 100644 index 0000000..811f8c3 --- /dev/null +++ b/Esm/ib/src/smi/include/sm_jm.h @@ -0,0 +1,258 @@ +/* BEGIN_ICS_COPYRIGHT2 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT2 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +#ifndef _SM_MPI_H_ +#define _SM_MPI_H_ + +#include "sm_l.h" + +//============================================================================= +// GENERAL CONSTANTS +// + +#define JM_CVERSION 1 + +//============================================================================= +// PROTOCOL CONSTANTS +// + +#define JM_MAX_MESSAGE_ID 0x000a + +#define JM_MSG_CLASS_PORT_INFO 0x0001 +#define JM_MSG_CREATE_JOB 0x0002 +#define JM_MSG_SET_USE_MATRIX 0x0003 +#define JM_MSG_POLL_READY 0x0004 +#define JM_MSG_COMPLETE_JOB 0x0005 +#define JM_MSG_GET_GUID_LIST 0x0006 +#define JM_MSG_GET_SWITCH_MAP 0x0007 +#define JM_MSG_GET_COST_MATRIX 0x0008 +#define JM_MSG_GET_USE_MATRIX 0x0009 +#define JM_MSG_GET_JOBS 0x000a + +#define JM_STATUS_OK 0x00000000 +#define JM_STATUS_PARTIAL 0x00000001 +#define JM_STATUS_ERROR 0x00000002 +#define JM_STATUS_INVALID_ID 0x00000003 + +//============================================================================= +// WIRE/INPUT STRUCTURES +// + +typedef struct _JmWireGuidList { + uint16_t count; + uint64_t * entries; +} JmWireGuidList_t; + +typedef struct _JmWireUseElement { + uint16_t bursty : 1; + uint16_t swidx : 15; + STL_LID dlid; + uint8_t use; +} JmWireUseElement_t; + +typedef struct _JmWireUseMatrix { + uint16_t multiplier; + uint8_t base; + uint16_t count; + JmWireUseElement_t * elements; +} JmWireUseMatrix_t; + +typedef struct _JmWireJobOptions { + uint16_t rsvd : 15; + uint16_t no_create : 1; +} JmWireJobOptions_t; + +typedef struct _JmWireJobParams { + char name[65]; + char appName[65]; + uint64_t pid; + uint64_t uid; +} JmWireJobParams_t; + +typedef struct _JmWireJobInfo { + uint64_t id; + uint64_t timestamp; + uint16_t rsvd : 14; + uint16_t routed : 1; + uint16_t has_use : 1; + JmWireJobParams_t params; +} JmWireJobInfo_t; + +typedef struct _JmMsgReqCreate { + JmWireJobOptions_t options; + JmWireJobParams_t params; + JmWireGuidList_t guids; +} JmMsgReqCreate_t; + +typedef struct _JmMsgReqGenericQuery { + uint64_t id; +} JmMsgReqGenericQuery_t; + +typedef struct _JmMsgReqSetUseMatrix { + uint64_t id; + JmWireUseMatrix_t matrix; +} JmMsgReqSetUseMatrix_t; + +typedef struct _JmMsgRespGetJobsContext { + uint16_t count; + uint8_t * buf; + int bpos; + int blen; +} JmMsgRespGetJobsContext_t; + +//============================================================================= +// CORE JOB MANAGEMENT STRUCTURES +// + +typedef struct _JmUseElement { + // true if bursy, otherwise sustained + uint16_t bursty : 1; + // index of the source switch + uint16_t swidx : 15; + // lid of the destination + STL_LID dlid; + // relative weight of path with respect to other paths + uint8_t use; +} JmUseElement_t; + +typedef struct _JmUseMatrix { + // scales the specified use_elements (leaving unspecified + // elements alone) + uint16_t multiplier; + // base value for non-specified elements + uint8_t base; + // number of elements in sparse use matrix input + uint16_t count; + // elements of the use matrix, one per switch/dlid pair + JmUseElement_t * elements; +} JmUseMatrix_t; + +typedef enum { + JM_STATE_UNINITIALIZED = 0, + JM_STATE_CANCELLED = 1, + JM_STATE_COMPLETE = 2, + JM_STATE_INITIALIZED = 3, + JM_STATE_ROUTED = 4, + JM_STATE_USE_AVAILABLE = 5 +} JmState_t; + +typedef enum { + JM_POLL_NOT_READY = 0, + JM_POLL_READY = 1 +} JmPollStatus_t; + +typedef struct _JmPort { + // guid as specified in input + uint64_t guid; + // port in old topology (if exists) + Port_t *portp; + // job-specific switch index + uint16_t jobSwIdx; +} JmPort_t; + +typedef struct _JmEntry { + // unique identifier for the job + uint64_t id; + // timestamp of job creation in seconds since 1970 + uint64_t timestamp; + // user-specified job metadata + JmWireJobParams_t params; + // state of the job + JmState_t state; + // topology passcount associated with job creation + uint32_t passcount; + // the number of end ports in the job + uint16_t portCount; + // the number of edge switches in the job + uint16_t switchCount; + // list of ports assigned to the job + // [length = portCount] + JmPort_t * ports; + // the mapping from job-specific switch indices to + // topology-specific switch indices + // [length = switchCount] + uint16_t * jobSwToTopoSwMap; + // the use matrix (if present) + JmWireUseMatrix_t useMatrix; +} JmEntry_t; + +typedef struct _JmTable { + // mutex protecting job table + Lock_t lock; + // set of jobs by JobID + CS_HashTable_t * jobs; +} JmTable_t; + +//============================================================================= +// FUNCTIONS DECLARATIONS +// + +// sm_jm.c + +typedef Status_t (*sm_jm_start_func_t)(uint32_t, void *); +typedef Status_t (*sm_jm_iter_func_t)(JmEntry_t *, void *); + +Status_t sm_jm_init_job_table(void); +void sm_jm_destroy_job_table(void); +Status_t sm_jm_iterate_over_jobs(sm_jm_start_func_t, sm_jm_iter_func_t, void *); +Status_t sm_jm_insert_job(JmEntry_t *); +Status_t sm_jm_remove_job(JmEntry_t *); +Status_t sm_jm_lookup_job(uint64_t, JmEntry_t **); +Status_t sm_jm_alloc_job(JmEntry_t **); +Status_t sm_jm_free_job(JmEntry_t *); +Status_t sm_jm_fill_ports(Topology_t *, JmMsgReqCreate_t *, JmEntry_t *, uint16_t *); +Status_t sm_jm_get_cost(Topology_t *, JmEntry_t *, uint16_t **, int *); +void sm_jm_free_cost(uint16_t *); + +// sm_jm_wire.c + +void sm_jm_free_resp(uint8_t *); + +Status_t sm_jm_decode_req_generic_query(uint8_t *, int, JmMsgReqGenericQuery_t *); + +Status_t sm_jm_decode_req_create(uint8_t *, int, JmMsgReqCreate_t *); +void sm_jm_free_req_create(JmMsgReqCreate_t *); +Status_t sm_jm_encode_resp_create(JmEntry_t *, uint16_t *, int, uint8_t **, int *); + +Status_t sm_jm_decode_req_set_use_matrix(uint8_t *, int, JmMsgReqSetUseMatrix_t *); + +Status_t sm_jm_encode_resp_poll(JmEntry_t *, uint8_t **, int *); + +Status_t sm_jm_encode_resp_get_guid_list(JmEntry_t *, uint8_t **, int *); +Status_t sm_jm_encode_resp_get_switch_map(JmEntry_t *, uint8_t **, int *); +Status_t sm_jm_encode_resp_get_cost_matrix(JmEntry_t *, uint16_t *, int, uint8_t **, int *); +Status_t sm_jm_encode_resp_get_use_matrix(JmEntry_t *, uint8_t **, int *); + +Status_t sm_jm_encode_resp_get_jobs_start(uint32_t, void *); +Status_t sm_jm_encode_resp_get_jobs_iter(JmEntry_t *, void *); + +#endif // _SM_MPI_H_ + diff --git a/Esm/ib/src/smi/include/sm_l.h b/Esm/ib/src/smi/include/sm_l.h new file mode 100644 index 0000000..35aef1d --- /dev/null +++ b/Esm/ib/src/smi/include/sm_l.h @@ -0,0 +1,3159 @@ +/* BEGIN_ICS_COPYRIGHT2 **************************************** + +Copyright (c) 2015-2018, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT2 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +//===========================================================================// +// // +// FILE NAME // +// sm_l.h // +// // +// DESCRIPTION // +// This file contains the localized SM definitions. These definitions // +// do NOT appear in the IBTA specs. They are implementation dependent. // +// // +// DATA STRUCTURES // +// None // +// // +// FUNCTIONS // +// None // +// // +// DEPENDENCIES // +// ib_mad.h // +// ib_status.h // +// ib_const.h // +// // +// // +//===========================================================================// + +#ifndef _SM_L_H_ +#define _SM_L_H_ + +#include +#include +#include +#include "ib_types.h" +#include "ispinlock.h" +#include "ib_mad.h" +#include "ib_status.h" +#include "ib_sm.h" +#include "ib_sa.h" +#include "cs_context.h" +#include "mai_g.h" +#include "cs_g.h" +#include "cs_log.h" +#include "cs_bitset.h" +#include "mai_g.h" +#include "sm_maihandle.h" +#include "ifs_g.h" + +#include "ilist.h" +#include "iquickmap.h" +#include +#include + +#ifdef __VXWORKS__ +#include "regexp.h" +#else +#include "regex.h" +#endif + +#include +#include "topology.h" + +#include "sm_parallelsweep.h" + +#define SM_PKEYS 64 + +#ifdef __VXWORKS__ +#define SM_NODE_NUM 500 +#else +#define SM_NODE_NUM 5000 +#endif + +#define USE_FIXED_SCVL_MAPS + +// Support for STL MTU enum, which allows for 8k and 10k +// In the SM MC Spanning tree, a tree is maintained for each MTU +// and the original code uses the MTU enum as an index. +// This concept works, except that when iterating through loops, the +// unused values must be skipped. +// NOTE: This function will return values greater than the max mtu +// to allow for..loop termination. +static __inline__ int getNextMTU(int mtu) { + if (mtu == IB_MTU_4096) { + return (STL_MTU_8192); + } else { + return (mtu+1); + } +} + +// NOTE: This function will return values less than the lowest mtu +// to allow for..loop termination. +static __inline__ int getPrevMTU(int mtu) { + if (mtu == STL_MTU_8192) { + return (IB_MTU_4096); + } else { + return (mtu-1); + } +} + + +static __inline__ uint32_t getCongTableSize(uint8_t numBlocks) { + return (CONGESTION_CONTROL_TABLE_CCTILIMIT_SZ + sizeof(STL_HFI_CONGESTION_CONTROL_TABLE_BLOCK) * numBlocks); +} + +static __inline__ uint32_t getCongrefTableSize(uint8_t numBlocks) { + return (sizeof(uint32) + CONGESTION_CONTROL_TABLE_CCTILIMIT_SZ + sizeof(STL_HFI_CONGESTION_CONTROL_TABLE_BLOCK) * numBlocks); +} + + +#define MAX_VFABRICS MAX_ENABLED_VFABRICS +#define DEFAULT_DEVGROUP_ID 0xffff +#define DEFAULT_PKEY 0x7fff +#define INVALID_PKEY 0 +#define FULL_MEMBER 0x8000 +#define ALL_GUIDS 0xffffffffffffffff +#define NULL_SERVICE_MASK 0xffffffffffffffff +#define UNDEFINED_PKEY 0xffffffff +#define PKEY_TYPE_FULL 1 + +#define TITAN_SYSTEM_IMAGE_BASIC 0x00066A00E0000000ll +#define QLOGIC_SYSTEM_IMAGE_BASIC 0x00066A0000000000ll + +// +// These pools are referenced by the macros below +// +extern Pool_t sm_pool; + +/* + * Revert to using pure DR after SmaEnableLRDR_MAX_RETRIES-1 attempts. + */ +#define SmaEnableLRDR_FALLBACK_OPTION 2 +#define SmaEnableLRDR_MAX_RETRIES 3 //total retries while using LR-DR SMPs approach + +extern Sema_t topo_terminated_sema; +extern int activateInProgress; +extern int isSweeping; +extern int forceRebalanceNextSweep; +extern int topology_changed; /* indicates a change in the topology during discovery */ +extern int topology_changed_count; /* how many times has topology changed */ +extern int topology_switch_port_changes; /* indicates there are switches with switch port change flag set */ +extern int topology_cost_path_changes; +extern int routing_recalculated; /* indicates all routing tables have been recalculated this sweep */ +extern uint32_t topology_port_bounce_log_num; /* Number of times a log message has been generated about a port bounce this sweep*/ +extern bitset_t old_switchesInUse; +extern bitset_t new_switchesInUse; +extern bitset_t new_endnodesInUse; +extern SMXmlConfig_t sm_config; + +extern FabricData_t preDefTopology; + +//********** SM topology asynchronous send receive context ********** +extern generic_cntxt_t sm_async_send_rcv_cntxt; +//********** SM topology asynchronous send receive response queue ********** +extern cs_Queue_ptr sm_async_rcv_resp_queue; + +//Link policy violation types used in portData->linkPolicyViolation +#define LINK_POLICY_VIOLATION_SUP 0x1 +#define LINK_POLICY_VIOLATION_MIN 0x2 + + +// +// Internal data structures for simplicity. +// + +#define DEFAULT_LOOP_PATH_LENGTH 3 +#define DEFAULT_LOOP_INJECT_EACH_SWEEP 1 + +// +// Loop test path structure +// +typedef struct _LoopPath { + STL_LID lid; // lid assigned to the path + uint16_t startNodeno;// node number of start/end of loop in topology + // path from SM node to loop node and loop from node back to itself + uint16_t nodeIdx[64];// index of node (node number) in topology + uint8_t path[64]; // port through node + struct _LoopPath *next; // pointer to next loop path +} LoopPath_t; + +#define PORT_GUIDINFO_DEFAULT_RECORDS 1 // Maximum records is normally 8 +#define IB_VLARB_COUNT 5 + +//inLoopCount is 8 bits hence max value is 255 +//Increment such that, overflow doesn't result in the value becoming 0 as +//zero value of inLoopCount would be considered as the port not being in any loop +#define INC_IN_LOOP_COUNT(P) (P = (P == 255) ? 1 : (P+1)) + +// maximum times do immediate resweep after an individual port fails to move +// to the proper state after requesting it to move to Armed or Active. +// Once this count is exceeded, the fabric will not be reswept until the next +// normally scheduled fabric sweep or fabric port change. +#define ACTIVATE_RETRY_LIMIT 3 + +typedef struct { + uint8 refcount; + uint8 buffer[128]; +} CableInfo_t; + + +#define MAX_NODE_DESC_ENTRIES 30 +typedef struct { + int numPortRanges; + int port1[MAX_NODE_DESC_ENTRIES]; + int port2[MAX_NODE_DESC_ENTRIES]; +} PortRangeInfo_t; + +typedef struct { + STL_VLARB_TABLE_ELEMENT vlarbLow[STL_MAX_LOW_CAP]; + STL_VLARB_TABLE_ELEMENT vlarbHigh[STL_MAX_LOW_CAP]; + STL_VLARB_TABLE_ELEMENT vlarbPre[STL_MAX_PREEMPT_CAP]; +} VlarbTableData; + +typedef struct _PortDataVLArb { + uint32 vlarbMatrix[STL_MAX_VLS]; + union { + VlarbTableData vlarb; + } u; +} PortDataVLArb; + +typedef struct _PortDataSCSCMapPortMask { + LIST_ITEM SCSCMapItem; + STL_PORTMASK outports[STL_MAX_PORTMASK]; + STL_SCSCMAP *SCSCMap; +} PortDataSCSCMapPortMask; + +// +// Persistent Topology API +// + +typedef enum { + POPO_QUARANTINE_NONE = 0, + POPO_QUARANTINE_SHORT = 1, + POPO_QUARANTINE_LONG = 2, +} PopoQuarantineType_t; + +typedef enum { + POPO_LONGTERM_NONE = 0, + POPO_LONGTERM_FLAPPING = 1, + POPO_LONGTERM_PERSISTENT_TIMEOUT = 2, //Not Implemented. Future Work +} PopoLongTermQuarantineReason_t; + +typedef struct { + PopoLongTermQuarantineReason_t reason; + uint64_t monitoredTime; //timestamp port was placed in monitor state + uint64_t quarantinedTime;//Timestamp port was placed in quarantine state + void *data; //Data specific to quarantine reason about state over sliding window +} PopoPortLongTermData_t; + + + +typedef struct { + struct _PopoNode * ponodep; + uint8_t portNum; + STL_PORT_STATES portStates; + struct { + PopoQuarantineType_t type; + boolean monitored; + PopoPortLongTermData_t longTermData; //Tracks data for monitored/long term quarantined ports + LIST_ITEM quarantineEntry; //Entry for either shorterm or longterm quarantine list. Cannot be in both. + LIST_ITEM monitorEntry; //Entry for monitored list. + } quarantine; + struct { + uint8_t reregisterPending:1; // True if we need to send a PortInfo with ClientReregister + } registration; + struct { + uint8_t updateLog:1; + STL_LINKDOWN_REASON ldr_log[STL_NUM_LINKDOWN_REASONS]; + } ldr; +} PopoPort_t; + +typedef struct _PopoNode { + cl_map_item_t nodesEntry; + struct { + uint32_t pass; + uint8_t nodeType; + uint8_t numPorts; + uint64_t guid; + } info; + struct { + uint32_t nrSweepNum; //Sweep number of last failure + uint16_t nrCount; // Number of sweeps a Node Fails a get + uint64_t nrTime; // Timestamp of first failure to respond + } nonresp; + struct { + uint8_t errorCount; + } quarantine; + PopoPort_t ports[0]; +} PopoNode_t; + +typedef struct { + Lock_t lock; + cl_qmap_t nodes; + struct { + // the cumulative time spent in timeouts during this sweep + ATOMIC_UINT cumulativeTimeout; + // indicates a trap is pending; tracks whether a trap was received + // at any point in a series of failed sweeps, and indicates that a + // resweep should be scheduled + boolean trapPending; + } errors; + struct { + QUICK_LIST monitored; //Ports that are being considered for inclusion in longTerm quarantine. + QUICK_LIST shortTerm; //Ports that will be quarantined only until the next successful SM sweep + QUICK_LIST longTerm; //Ports that will be quarantined for multiple sweeps until underlying condition resolves + } quarantine; + struct { + uint64_t sweepStart; // Sweep start (in seconds) used by LinkdownReason Log + } ldr; +} Popo_t; + +typedef struct { + uint32 refCount; + STL_HFI_CONGESTION_CONTROL_TABLE hfiCongCon; +} HfiCongestionControlTableRefCount_t; + +// +// Per Port structure. +// +typedef struct _PortData { + uint64_t guid; // port GUID + uint64_t gidPrefix; // Gid Prefix + uint8_t gid[16]; // Gid (network byte order) + uint32_t capmask; // capability mask + uint16_t capmask3; // capability mask3 +// lid, lmc and vl could be much smaller fields, lid=16bits, lmc=3, vls=3 bits + STL_LID lid; // base lid + uint8_t lmc; // LMC for this port + uint8_t vl0; // VLs supported + uint8_t vl1; // VLs actual + uint8_t mtuSupported:4; // MTUs supported + uint8_t maxVlMtu:4; // Largest mtu of VLs/VFs on this port. + uint8_t rate; // static rate of link (speed*width) + uint16_t portSpeed; // calculated portSpeed used in cost (stored due to high usage) + uint8_t guidCap; // # of GUIDs + uint8_t numFailedActivate; // how many times has sm_activate_port + // failed to activate this port + uint32_t flags; // local flags + STL_LID pLid; // Persistent lid + STL_PKEY_ELEMENT pPKey[SM_PKEYS];// Persistent PKeys + bitset_t pkey_idxs; // Persistent number of PKeys + uint64_t trapWindowStartTime;//timestamp of last trap within the thresholdWindow + uint32_t trapWindowCount;/* trap counter maintained during the thresholdWindow for + disabling runaway ports */ + uint64_t lastTrapTime; //time stamp of last trap + uint8_t suppressTrapLog; // if set to 1, trap info of this port will not be logged + uint8_t logSuppressedTrapCount; // count of traps while logging is suppressed + uint8_t logTrapSummaryThreshold;/*threshold of traps when summary of traps + should be logged even if logging is suppressed*/ + uint8_t mcDeleteCount; + uint64_t mcDeleteStartTime; + STL_PORT_INFO portInfo; // PortInfo (for SA) + + PortDataVLArb curArb; // Current values on SMA + PortDataVLArb *newArb; // Not yet set on SMA + + STL_SLSCMAP slscMap; // SL2SC mapping table + STL_SCSLMAP scslMap; // SC2SL mapping table + STL_SCVLMAP scvltMap; + STL_SCVLMAP scvlntMap; + STL_SCVLMAP scvlrMap; + QUICK_LIST scscMapList[2]; // 0 is regular, 1 is Ext + + STL_BUFFER_CONTROL_TABLE bufCtrlTable; + HfiCongestionControlTableRefCount_t *congConRefCount; // HFI Port or EH SWP 0 only. + STL_SWITCH_PORT_CONGESTION_SETTING_ELEMENT swPortCongSet; // Switch port only. + + bitset_t vfMember; + bitset_t qosMember; + bitset_t dgMember; // Bitset indicating the index values of all device groups. + bitset_t fullPKeyMember; + STL_LID lidsRouted; // Number of lids routed through this port + STL_LID baseLidsRouted; // Number of base lids routed through this port + + /* Flags*/ + uint8_t qosHfiFilter:1; + uint8_t isIsl:1; // Switch port is linked to another switch + uint8_t uplink:1; // Uplink port in fat tree + uint8_t downlink:1; // Downlink port in fat tree + uint8_t delayedPkeyWrite:1; // True if Pkeys need to be wrote after topo release + + uint8_t inLoopCount; //number of times this port has been included in a loop as part of loop test + + /// Shared cable information; use sm_CableInfo_*() functions to create and manage + CableInfo_t * cableInfo; + + uint8_t neighborQuarantined; + uint8_t linkPolicyViolation:2; //port outside speed/width policy. + //bit[0]: link below max supported + //bit[1]: port below minimum allowed + + cl_map_obj_t mapObj; // quickmap item to sort on GUIDs + + struct _Node *nodePtr; // Ptr to the node record this port belongs. + //void *pmData; // Pointer to Pm per port Data + + /** + Whether stored values are up-to date with values on SMA. + Not the same as whether values on SMA match the expected or correct values. + */ + struct { + uint8_t slsc:1; + uint8_t scsl:1; + uint8_t scvlt:1; + uint8_t scvlnt:1; + uint8_t scvlr:1; + uint8_t scsc:1; + uint8_t vlarbLow:1; + uint8_t vlarbHigh:1; + uint8_t vlarbPre:1; + uint8_t vlarbMatrix:1; + uint8_t pkeys:1; + uint8_t bfrctrl:1; + } current; + + struct { + uint8_t init:1; + uint8_t slsc:1; + uint8_t scsl:1; + uint8_t portInfo:1; + } dirty; + + struct { + STL_SLSCMAP * slsc; + STL_SCSLMAP * scsl; + } changes; + + void *routingData; // Private data used by topology algorithm. + uint16_t routingCost; // Used for enhanced hypercube + int32_t initWireDepth; // Initial wire depth to use for buffer calculations. +} PortData_t; + +// This structure is retained for all switch ports and has summary information +typedef struct _Port { + uint8_t index; // my port number + uint8_t state; // portState (IB_PORT_DOWN ... IB_PORT_ACTIVE) + uint32_t nodeno; // node index of other end + uint32_t portno; // port index of other end + uint8_t path[64]; // path to get to this port + PopoPort_t *poportp; // pointer to persistent port structure + PortData_t *portData; // Pointer to additional port related fields. + // may be NULL when dynamic port alloc enabled + // TBD - is dynamic port alloc needed? Should it + // be removed and this changed to a structure + // instead of a pointer? +} Port_t; + +// +// Per Node structure. +// + +static __inline__ STL_LID STL_GET_UNICAST_LID_MAX(void) { + return (sm_config.max_supported_lid); +} +#define MAX_SIZE_MFT ((STL_LID_MULTICAST_END-STL_LID_MULTICAST_BEGIN)+1) +#ifdef __VXWORKS__ +#define MAX_MCAST_MGIDS 1000 +#else +#define MAX_MCAST_MGIDS 20000 +#endif +typedef struct _Node { + uint32_t index; // index in linked list + uint32_t oldIndex; // index in linked list in old topology + uint16_t swIdx; // switch index in switch list + uint32_t flags; // FabricExec flags + STL_NODE_INFO nodeInfo; // NodeInfo (for SA) + STL_NODE_DESCRIPTION nodeDesc; // NodeInfo (for SA) + STL_SWITCH_INFO switchInfo; // SwitchInfo (for SA) // TBD make a pointer and only allocate for switches + STL_PORT_STATE_INFO *portStateInfo; + STL_CONGESTION_INFO congestionInfo; + uint8_t path[64]; // directed path to this node + PORT *lft; + + + STL_PORTMASK **mft; // 2D array of port masks for MFT. + STL_PORTMASK *pgt; // 1D array of port masks for Port Group Table. + uint8_t pgtLen; // Current length of PGT. + PORT *pgft; ///< Port Group Forwarding Table + uint32_t pgftSize; ///< amount of memory allocated for pgft; should track actual memory allocation, not highest entry in use + Port_t *port; // ports on this node + bitset_t activePorts; + bitset_t initPorts; + + + + bitset_t vfMember; + bitset_t fullPKeyMember; + bitset_t dgMembership; + uint8_t asyncReqsSupported; // number of async requests node can handle + uint8_t asyncReqsOutstanding; // number of async requests on the wire + uint8_t portsInInit; + uint8_t activeVLs; + uint8_t arbCap; // capability of switch internal + uint8_t vlCap; // capability of switch internal + uint8_t numISLs; + uint8_t tier; // tier switch resides on in fat tree + uint16_t tierIndex; // switch index within it's tier + uint8_t uplinkTrunkCnt; // number of uplink ports in trunk group + STL_LID numLidsRouted; // used to build balanced LFTs. + STL_LID numBaseLidsRouted; // used to build balanced LFTs when LMC enabled. + char* nodeDescString; // Only used when nodeDesc is 64 chars (not null terminated). + cl_map_obj_t mapObj; // Quickmap item to sort on guids + cl_map_obj_t nodeIdMapObj; // Quickmap item to sort on guids + cl_map_obj_t mapQuarantinedObj; // Quickmap item to sort on guids + cl_map_obj_t switchLidMapObj; // Quickmap item to sort switch lids + PopoNode_t *ponodep; // pointer to persistent node structure + void *routingData; // Routing specific data. + + /* There exist a case where these are both used (Enhanced SWP0 switch). We'll just + store both */ + STL_HFI_CONGESTION_SETTING hfiCongestionSetting; + STL_SWITCH_CONGESTION_SETTING swCongestionSetting; + + struct _Node *next; // linked list pointer (for_all_nodes()) + struct _Node *prev; // linked list pointer (for_all_nodes()) + struct _Node *type_next; // linked list pointer (NodeType based) + struct _Node *type_prev; // linked list pointer (NodeType based) + struct _Node *sw_next; // linked list pointer (tier based) + struct _Node *sw_prev; // linked list pointer (tier based) + struct _Node *old; // Pointer to a copy of this node in an older topology. MAY BE NULL. + + /* Flags*/ + uint8_t initDone:1; //temporary flag during sweep that indicates if the switch is initialized + uint8_t noLRDRSupport:1; //indicates that the switch is not handling LR DR packets correctly*/ + uint8_t hasSendOnlyMember:1; //switch has a multicast sendonly member attached */ + uint8_t mftChange:1; // indicates if mft of switch has to be completely reprogrammed + uint8_t mftPortMaskChange:1;// indicates if mft entries of switch have changed since last sweep + uint8_t arChange:1; // indicates adaptive routing tables of switch need to be programmed, leave pause if set + uint8_t arSupport:1; // indicates switch supports adaptive routing + uint8_t congConfigDone:1; // indicates if this node's congestion control configuration is done. + uint8_t oldExists:1; // this node is also in the old topology + uint8_t uniformVL:1; + uint8_t deltasRequired:1; // indicates a node was added to the switch + uint8_t vlArb:1; + uint8_t internalLinks:1; + uint8_t externalLinks:1; + uint8_t edgeSwitch:1; // switch has HFIs attached + uint8_t skipBalance:1; + uint8_t routingRecalculated:1; // routing has been recalculated during this sweep + uint8_t nodeDescChgTrap:1; + uint8_t mcSpanningChkDone:1; //indicates switch has been checked as part of spanning tree construction + //uint8_t pmFlags; // PM flag - TBD how many bits needed + uint8_t slscChange:1; //indicates if sl2sc of the node needs to be programmed + uint8_t aggregateEnable:1; +} Node_t; + +typedef struct _QuarantinedNode { + Node_t * authenticNode; + Port_t * authenticNodePort; + Node_t * quarantinedNode; + uint32 quarantineReasons; + STL_EXPECTED_NODE_INFO expNodeInfo; + struct _QuarantinedNode *next; // linked list pointer + struct _QuarantinedNode *prev; // linked list pointer +} QuarantinedNode_t; + +typedef struct _SwitchList +{ + Node_t *switchp; + struct _SwitchList *next; + uint8_t parent_portno; //port number of parent switch through which switchp was added to the list +} SwitchList_t; + +/* + * The set of quickmaps and ordered device groups associated with a topology + * structure. + * + * NOTA BENE: The deviceGroup[] array has one more member than the + * deviceGroupName[] or deviceGroupIndex[] arrays. This is to allow all + * un-weighted LIDs to be routed correctly. + */ +typedef struct _DGTopology { + uint8_t dgCount; + uint8_t allGroup; + char deviceGroupName[MAX_DGROUTING_ORDER][MAX_VFABRIC_NAME]; + uint16_t deviceGroupIndex[MAX_DGROUTING_ORDER]; + cl_qmap_t deviceGroup[MAX_DGROUTING_ORDER+1]; +} DGTopology; + +typedef struct { + uint8_t * path; + STL_LID slid; + STL_LID dlid; +} SmpAddr_t; + +// uint8_t *, STL_LID, STL_LID +#define SMP_ADDR_CREATE(PATH, SLID, DLID) { (PATH), (SLID), (DLID) } + +// uint8_t * +#define SMP_ADDR_CREATE_DR(PATH) { (PATH), STL_LID_PERMISSIVE, STL_LID_PERMISSIVE } +// uint8_t *, STL_LID, STL_LID +#define SMP_ADDR_CREATE_LRDR(PATH, SLID, DLID) { (PATH), (SLID), (DLID) } +// STL_LID, STL_LID +#define SMP_ADDR_CREATE_LR(SLID, DLID) { NULL, (SLID), (DLID) } + +// SmpAddr_t *, uint8_t * +#define SMP_ADDR_SET_DR(ADDR, PATH) \ + do { \ + (ADDR)->path = (PATH); \ + (ADDR)->slid = STL_LID_PERMISSIVE; \ + (ADDR)->dlid = STL_LID_PERMISSIVE; \ + } while(0) +// SmpAddr_t *, uint8_t *, STL_LID, STL_LID +#define SMP_ADDR_SET_LRDR(ADDR, PATH, SLID, DLID) \ + do { \ + (ADDR)->path = (PATH); \ + (ADDR)->slid = (SLID); \ + (ADDR)->dlid = (DLID); \ + } while(0) +// SmpAddr_t *, STL_LID, STL_LID +#define SMP_ADDR_SET_LR(ADDR, SLID, DLID) \ + do { \ + (ADDR)->path = NULL; \ + (ADDR)->slid = (SLID); \ + (ADDR)->dlid = (DLID); \ + } while(0) + +// SmpAddr_t * +#define SMP_ADDR_IS_LRDR(ADDR) \ + ((ADDR)->path && (ADDR)->slid != STL_LID_PERMISSIVE && (ADDR)->dlid != STL_LID_PERMISSIVE) + +// +// Path Matrix Port Masks +// + +/** + Path matrix portmask array length in units of 64 bits. + Separate from STL_MAX_PORTMASK to limit the size of path matrix. + */ +#define SM_PATH_MAX_PORTMASK ((MAX_STL_PORTS + 63) / 64) + +/** + Fixed-size portmask used by the path matrix. + + Local path helpers interpret ports as 1-255 and 0 as not found, + unlike stl_helper which encodes 0-254 (with 255 as not found). + This allows 64 port switches to be encoded in a single uint64. + */ +typedef struct _SmPathPortmask { + uint64_t masks[SM_PATH_MAX_PORTMASK]; +} SmPathPortmask_t; + +#define SM_PATH_PORTMASK_EMPTY ((SmPathPortmask_t){{0}}) + +static __inline__ void sm_path_portmask_set(SmPathPortmask_t * ports, int port) { + assert(0 < port && port <= MAX_STL_PORTS); + ports->masks[(port - 1) / 64] |= (uint64_t)1 << ((port - 1) % 64); +} + +static __inline__ void sm_path_portmask_clear(SmPathPortmask_t * ports, int port) { + assert(0 < port && port <= MAX_STL_PORTS); + ports->masks[(port - 1) / 64] &= ~((uint64_t)1 << ((port - 1) % 64)); +} + +static __inline__ void sm_path_portmask_merge(SmPathPortmask_t * dst, SmPathPortmask_t * src) { + int i; + for (i = 0; i < SM_PATH_MAX_PORTMASK; ++i) + dst->masks[i] |= src->masks[i]; +} + +static __inline__ int sm_path_portmask_pop_first(SmPathPortmask_t * ports) { + int i, base, bit; + for (i = base = 0; i < SM_PATH_MAX_PORTMASK; ++i, base += 64) { + bit = __builtin_ffsll(ports->masks[i]); + if (bit) { + ports->masks[i] ^= (uint64_t)1 << (bit - 1); + return base + bit; + } + } + return 0; +} + +/** + The array offset to the i-th block of destination switches. + */ +#define SM_PATH_OFFSET(I, NumSwitches) ((I) * (NumSwitches)) + +/** + The span of switches and ports for the i-th source switch in bytes. + */ +#define SM_PATH_SWITCH_SPAN(NumSwitches) ((NumSwitches) * sizeof(SmPathPortmask_t)) + +/** + The size of the path matrix in bytes. + */ +#define SM_PATH_SIZE(NumSwitches) ((NumSwitches) * SM_PATH_SWITCH_SPAN(NumSwitches)) + +// +// Routing structures +// + +#define SM_DOR_MAX_DIMENSIONS 6 +#define SM_DOR_MAX_WARN_THRESHOLD 255 /*size of warning counter in sm_dor.c is 1 byte*/ + +struct _Topology; +struct _VlVfMap; +struct _VlQosMap; +struct _VlBwMap; +struct Qos; +struct _RoutingModule; +struct SwitchportToNextGuid; + +typedef struct _RoutingFuncs { + Status_t (*pre_process_discovery)(struct _Topology *, void **); + Status_t (*discover_node)(struct _Topology *, struct _Node *, void *); + Status_t (*discover_node_port)(struct _Topology *, struct _Node *, struct _Port *, void *); + Status_t (*post_process_discovery)(struct _Topology *, Status_t, void *); + + /* These functions allow topology-specific code to examine the new + * topology and the old topology and determine if the SM needs to update + * the routing tables of the switches. Implementations should set the + * rebalance flag to non-zero if updates are needed, but should not + * modify it if no update is needed. + */ + Status_t (*post_process_routing)(struct _Topology *, struct _Topology *, int * rebalance); + Status_t (*post_process_routing_copy)(struct _Topology *, struct _Topology *, int * rebalance); + + // Allows for topology specific intialization and calculation of the cost matrix used + // to calculate routes. + Status_t (*allocate_cost_matrix)(struct _Topology *); + Status_t (*initialize_cost_matrix)(struct _Topology *); + Status_t (*calculate_cost_matrix)(struct _Topology *, int switches, unsigned short * cost, SmPathPortmask_t *); + + int (*routing_mode) (void); + + + boolean (*extended_scsc_in_use) (void); + + /** + Indicates DR routing initialization is required instead of LRDR. + */ + boolean (*requires_dr) (struct _Topology *, Node_t *); + + + /** + Copy xFT from src to dest where src is assumed to be a predecessor of dest. + + See @fn sm_routing_func_copy_routing_lfts() for a typical implementation. + + @return VSTATUS_OK if no problems occurred, non-OK otherwise. + */ + Status_t (*copy_routing)(struct _Topology * src, struct _Topology * dest); + + /** + Perform routing algorithm/topology-specific xFT (LFT, MFT, PGT, PGFT) initialization for switches. Implementation should do initialization necessary for SM to send LID-routed to any switch. + + See @fn topology_setup_switches_LR_DR() + + @param routing_needed [in,out] As input, true indicates xFT initialization is needed to all nodes, false only to new nodes. + @param rebalance [out] Implementation should set this to '1' (really non-zero) if + + @return VSTATUS_OK on success, non-OK to indicate a fatal error. + */ + Status_t (*init_switch_routing)(struct _Topology * topop, int * routing_needed, int * rebalance); + Status_t (*setup_switches_lrdr)(struct _Topology *, int, int); + + // Optionally override this function to change the order in which routing tables are built. + // Leave null to accept the default function. + Status_t (*calculate_routes)(struct _Topology *, struct _Node *); + + /** + @param switchp the destination switch + @param nodep the source node or switch + @param orig_port the port from which LFT and PGT/PGFTs are built. + */ + Status_t (*setup_xft)(struct _Topology *, struct _Node *, struct _Node *, struct _Port *, uint8_t *); + int (*select_ports)(struct _Topology *, Node_t *, int, struct SwitchportToNextGuid *, boolean); + + /** + Compute the portgroup assignments on @c srcSw for all equally-best paths from @c srcSw to + @c dstSw and the end nodes attached to @c dstSw. + + Implementations may accept only switch pairs or (switch, node) pairs, although obviously + node pairs don't make particular sense. Implementation should set @c switchp->arChange to 1 + if either the PGT or PGFT were changed in the process. + + Optional for a topology module; NULL indiciates not implemented. + + @param [optional, out] portnos + @return VSTATUS_OK on success, something else if srcSw and dstSw aren't switches or if other bad stuff happens. + */ + Status_t (*setup_pgs)(struct _Topology *topop, struct _Node * srcSw, struct _Node * dstSw); + + int (*get_port_group)(struct _Topology *, struct _Node *, struct _Node *, uint8_t *); + Status_t (*select_slsc_map)(struct _Topology *, struct _Node *, struct _Port *, struct _Port *, STL_SLSCMAP *); + Status_t (*select_scsl_map)(struct _Topology *, struct _Node *, struct _Port *, struct _Port *, STL_SCSLMAP *); + Status_t (*select_scsc_map)(struct _Topology *, struct _Node *, int, int *, STL_SCSC_MULTISET** scscmap); + Status_t (*select_scvl_map)(struct _Topology *, struct _Node *, struct _Port *, struct _Port *, STL_SCVLMAP *); + Status_t (*select_vlvf_map)(struct _Topology *, struct _Node *, struct _Port *, struct _VlVfMap *); + Status_t (*select_vlqos_map)(struct _Topology *, struct _Node *, struct _Port *, struct _VlQosMap *); + Status_t (*select_vlbw_map)(struct _Topology *, struct _Node *, struct _Port *, struct _VlBwMap *); + Status_t (*select_scvlr_map)(struct _Topology *, uint8_t, STL_SCVLMAP *); + + Status_t (*fill_stl_vlarb_table)(struct _Topology *, struct _Node *, struct _Port *, struct _PortDataVLArb * arb); + Status_t (*select_path_lids)(struct _Topology *, struct _Port *, STL_LID, struct _Port *, STL_LID, STL_LID[], uint8_t *, STL_LID[], uint8_t *); + Status_t (*process_swIdx_change) (struct _Topology *, int old_idx, int new_idx, int last_idx); + + + /** + Used to determine if fabric change requires fabric routing reprogramming. + */ + int (*check_switch_path_change) (struct _Topology *, struct _Topology *, struct _Node *); + + /** + Predicate function to determine if any routing recalculation is required. + + Implementation should return zero if no recalculation is required, non-zero otherwise. + */ + boolean (*needs_routing_recalc)(struct _Topology * topop, Node_t * nodep); + + boolean (*can_send_partial_routes)(void); + + /** + Used by sm_routing_func_select_ports to determine spine first routing + */ + boolean (*do_spine_check)(struct _Topology *topop, Node_t *switchp); + + /** + Differ by write of LFT + */ + Status_t (*write_minimal_routes)(struct _Topology *, struct _Node *, SmpAddr_t *); + Status_t (*write_full_routes_LR)(struct _Topology *, struct _SwitchList *, int); + Status_t (*route_old_switch)(struct _Topology *, struct _Topology *, struct _Node *); + + /** + Override the building of the multicast spanning trees. + */ + void (*build_spanning_trees)(void); + + /** + Used to determine if local switch change requires routing change. + */ + boolean (*handle_fabric_change)(struct _Topology *, struct _Node *, struct _Node *); + + /** + QOS functions + */ + + /** + Implementation should assign/adjust bandwidth on virtual fabrics objects in + @c VirtualFabrics->v_fabric_all. Unassigned bandwidth indicated by + @c VF_t.percent_bandwidth == UNDEFINED_XML8. + */ + Status_t (*update_bw)(struct _RoutingModule *rm, VirtualFabrics_t *VirtualFabrics); + + /** + Compute global SLSC mppings. Only applicable to implementations + that use a single SLSC map for all SLSC-eligible ports. + */ + Status_t (*assign_scs_to_sls)(struct _RoutingModule *rm, VirtualFabrics_t *VirtualFabrics); + + /** + Assign SLs to VF_t objects in @c VirtualFabrics. + */ + Status_t (*assign_sls)(struct _RoutingModule *rm, VirtualFabrics_t *VirtualFabrics); + + /** + Does this routing algorithm require multicast isolation + */ + boolean (*mcast_isolation_required)(void); + + /** + Minimum number of vls supported by routing algorithm + Note: 1 vl is always supported, even though min_vls may return more than 1 + */ + int (*min_vls)(void); + + /** + Maximum number of vls supported by routing algorithm + */ + int (*max_vls)(void); + + /** + Number of routing SCs required by SL. mc_sl should be true if SL is for + multicast, false otherwise. + */ + int (*num_routing_scs)(int sl, boolean mc_sl); + + /** + Delete any routing data associated with a node in the topology. + */ + void (*delete_node)(struct _Node *); + + /** + Number of VLs that can be shared between the same SL type of different + QoS groups. + */ + int (*oversubscribe_factor)(int sl, boolean mc_sl); + + /** + Multiple routing SCs are used, but okay to overlay mcast with ucast. + */ + boolean (*overlay_mcast)(void); + + /** + Process XML config to see that it is valid. + */ + Status_t (*process_xml_config)(void); + +} RoutingFuncs_t; + +typedef struct _RoutingModule { + const char * name; + + RoutingFuncs_t funcs; + + // Private data used by topology algorithm. + void *data; + + /** + Initialize new instance @c dest to be a copy of @c src. Implementation is responsible for all fields in @c dest. If no implementation is provided, caller should do a memcpy(dest, src, size). + + Caller should not expect implementation to handle @c dest with non-NULL pointer members (@c dest has already been initialized). + + Typically only called at the start of a new sweep when there is a need to copy data gathered in the prior sweep to the current sweep. + + @return VSTATUS_Ok on success or non-OK to indicate failure. + */ + Status_t (*copy)(struct _RoutingModule * dest, const struct _RoutingModule * src); + + /** + Called when module is released , usually at end of sweep (see @fn topology_release_saved_topology() and @fn topology_clearNew()) or when a module is unloaded. + Note that release() can be called without unload() being called. + + Implementation is responsible for lifetime of fields of @c rm but not lifetime of @c rm itself. + + See also @fn RoutingFuncs_t::destroy(). release() will be called after destroy(). + + @return VSTATUS_OK on success or non-OK if an unrecoverable runtime error occurs. + */ + Status_t (*release)(struct _RoutingModule * rm); + +} RoutingModule_t; + +/** + Function type for initializing RoutingModule_t instance. Instance is already allocated, factory function should initialize the instance fields and do any allocation for the fields. + + @return VSTATUS_OK on success, non-OK on failure. +*/ +typedef Status_t (*routing_mod_factory)(RoutingModule_t * module); + +Status_t sm_routing_addModuleFac(const char * name, routing_mod_factory fac); + +/** + Allocate and initialize module instance using factory function associated with @c name. + + @param module [out] Location to store pointer to newly-allocated module. +*/ +Status_t sm_routing_makeModule(const char * name, RoutingModule_t ** module); + +/** + Allocate and initialize routing module instance as copy of @srcMod. + Does copy of @c srcMod using @c srcMod->copy if @c srcMod->copy is non-NULL. + Does memcpy(*newMod, srcMod) otherwise. + + @param newMod [out] Location to store pointer to newly-allocated module. +*/ +Status_t sm_routing_makeCopy(RoutingModule_t **newMod, RoutingModule_t *srcMod); +/** + Free routing module memory. Prefer this to direct vs_pool_free() since internal memory management details may change. + + @param module [out] If @c *module is freed, @c *module will be set to NULL. + + @return VSTATUS_ILLPARM if either @c module or @c *module is NULL. VSTATUS_OK otherwise. +*/ +Status_t sm_routing_freeModule(RoutingModule_t ** module); + +typedef struct _PreDefTopoLogCounts { + uint32_t totalLogCount; + uint32_t nodeDescWarn; + uint32_t nodeDescQuarantined; + uint32_t nodeGuidWarn; + uint32_t nodeGuidQuarantined; + uint32_t portGuidWarn; + uint32_t portGuidQuarantined; + uint32_t undefinedLinkWarn; + uint32_t undefinedLinkQuarantined; +} PreDefTopoLogCounts; + + +// +// Per Topology structure. +// +typedef struct _Topology { + uint32_t num_nodes; // count of how many nodes have been found + uint32_t num_sws; // count of how many switch chips have been found + uint32_t max_sws; // size of the switch index space (including sparseness) + uint32_t num_ports; // num of live ports in fabric (init state or better) + uint32_t num_endports; // num end ports (init state or better) + uint32_t num_quarantined_nodes; // count of how many nodes have been found + uint32_t nodeno; // node index of new node + uint32_t portno; // port index of new node + uint32_t state; // SM state + STL_LID maxLid; // maximum Lid assigned + + uint16_t *cost; // array for path resolution (cost matrix) + SmPathPortmask_t *path; // array for path resolution (next-hop matrix, each entry is a portmask of best next hops) + + Node_t *node_head; // linked list of nodes + Node_t *node_tail; // ditto + Node_t *ca_head; // linked list ofFI nodes + Node_t *ca_tail; // ditto + Node_t *switch_head; // linked list of SWITCH nodes + Node_t *switch_tail; // ditto + QuarantinedNode_t *quarantined_node_head; // linked list of nodes that failed authentication + QuarantinedNode_t *quarantined_node_tail; // linked list of nodes that failed authentication + Node_t *tier_head[MAX_TIER]; // array of linked lists of switches indexed by tier + Node_t *tier_tail[MAX_TIER]; // ditto + uint8_t minTier; // minimum tier one or more switches are assigned to + uint8_t maxTier; // Maximum tier one or more switches are assigned to + + size_t bytesCost; // cost/path array length + size_t bytesPath; + uint8_t sm_path[72]; // DR path to SM (STANDBY mode only) + uint32_t sm_count; // actCount of master SM (STANDBY mode only) + uint64_t sm_key; // the smKey of the master SM (STANDBY mode only) + uint16_t numSm; // number of SMs in fabric + //uint16_t numMasterSms; // number of master SMs in fabric + //TopologySm_t smRecs[SM_MAX_SUPPORTED]; // list of SMs in topology + uint32_t numRemovedPorts; // number of ports removed during discovery + // loop test variables + uint16_t numLoopPaths; // number of loop paths in fabric + LoopPath_t *loopPaths; // loop paths in fabric + Node_t **nodeArray; // Array of all nodes + cl_qmap_t *nodeMap; // Sorted GUID tree of all nodes + cl_qmap_t *portMap; // Sorted GUID tree of all ports + cl_qmap_t *nodeIdMap; // Sorted Node tree based on the locally assigned node id. + cl_qmap_t *quarantinedNodeMap; // Sorted GUID tree of all nodes + uint8_t maxMcastMtu; // Maximum MTU supported by fabric for multicast traffic + uint8_t maxMcastRate; // Maximum rate supported by fabric for multicast traffic + uint8_t maxISLMtu; // Maximum ISL MTU value seen in the fabric + uint8_t maxISLRate; // Maximum ISL rate value seen in the fabric + uint8_t qosEnforced; // QoS is being enforced based on fabric parameters + + /// Allocated in sm_routing_makeModule(), freed in either topology_release_saved_topology() and/or topology_clearNew() + RoutingModule_t * routingModule; + + uint64_t sweepStartTime; + uint64_t lastNDTrapTime; + + bitset_t deltaLidBlocks; + // Was bitset_init(...&deltaLidBlocks) called? + uint8_t deltaLidBlocks_init; + + VirtualFabrics_t *vfs_ptr; + + // Per sweep pre-defined topology log counts + PreDefTopoLogCounts preDefLogCounts; + + /// Store link down reasons for ports that disappeared; + /// see LdrCacheEntry_t + cl_qmap_t *ldrCache; + + + /// Store switch lids for efficient cost queries + cl_qmap_t * switchLids; +#ifdef __VXWORKS__ + uint8_t pad[8192]; // general scratch pad area for ESM +#endif +} Topology_t; + +Status_t sm_lidmap_alloc(void); +void sm_lidmap_free(void); +Status_t sm_lidmap_reset(void); +Status_t sm_lidmap_update_missing(void); + +struct MissingLidEntry; + +typedef struct { + Guid_t guid; // guid for this index (ie, Lid) + uint32_t pass; // last pass count I saw this Guid + Node_t *oldNodep; // active pointer to node in old topology + cl_map_obj_t mapObj; // for storing this item in the GuidToLidMap tree + struct MissingLidEntry *missing; + + /* + * the following fields are for topology thread use only + * They are transient and are valid only when SM is discovering + */ + Node_t *newNodep; // pointer to node in new topology + Port_t *newPortp; +} LidMap_t; + +typedef struct MissingLidEntry { + LidMap_t *lm; + struct MissingLidEntry *prev; + struct MissingLidEntry *next; +} MissingLidEntry_t; + +// +// Multicast structures. +// +typedef struct _McMember { + struct _McMember *next; + STL_LID slid; + uint8_t proxy; + uint8_t state; + uint64_t nodeGuid; + uint64_t portGuid; + STL_MCMEMBER_RECORD record; + uint32_t index; /* Used by OOB mgmt interface to track record */ +} McMember_t; + +#define MCMEMBER_STATE_FULL_MEMBER 0x01 +#define MCMEMBER_STATE_NON_MEMBER 0x02 +#define MCMEMBER_STATE_SENDONLY_MEMBER 0x04 + +typedef enum { + McGroupBehaviorStrict = 0, + McGroupBehaviorRelaxed = 1, + McGroupBehaviorSpanningTree = 2, +} McGroupJoinBehavior; + +typedef enum { + McGroupUnrealizable = (1 << 0), // Signifies that the group has become unrealizable +} McGroupFlags; + +typedef struct _McGroup { + struct _McGroup *next; + IB_GID mGid; + uint32_t members_full; + uint32_t qKey; + uint16_t pKey; + STL_LID mLid; + uint8_t mtu; + uint8_t rate; + uint8_t life; + uint8_t sl; + uint32_t flowLabel; + uint8_t hopLimit; + uint8_t tClass; + uint8_t scope; + McMember_t *mcMembers; + uint32_t index_pool; /* Next index to use for new Mc Member records */ + bitset_t vfMembers; + bitset_t new_vfMembers; + McGroupFlags flags; // Flags associated with this group +} McGroup_t; + +#if defined(__VXWORKS__) +#define SM_STACK_SIZE (29 * 1024) +#else +#define SM_STACK_SIZE (256 * 1024) +#endif +// +// Thread structure. +// +typedef struct { + Thread_t handle; + Threadname_t name; + void (*function)(uint32_t, uint8_t **); + uint8_t *id; +} SMThread_t; + +#define SM_THREAD_SA_READER 0 +#define SM_THREAD_SA_WRITER 1 +#define SM_THREAD_TOPOLOGY 2 +#define SM_THREAD_ASYNC 3 +#define SM_THREAD_DBSYNC 4 +#define SM_THREAD_TOP_RCV 5 +#define SM_THREAD_PM 6 +#define SM_THREAD_EM 7 + + +#ifndef FE_THREAD_SUPPORT_ENABLED +#define SM_THREAD_MAX SM_THREAD_EM +#else +#define SM_THREAD_FE (SM_THREAD_EM + 1) +#define SM_THREAD_MAX SM_THREAD_FE +#endif + +// +// Removed fabric entities +// + +typedef enum { + SM_REMOVAL_REASON_INVALID = 0, + SM_REMOVAL_REASON_1X_LINK, + SM_REMOVAL_REASON_TRAP_SUPPRESS, + SM_REMOVAL_REASON_MC_DOS, +} RemovedEntityReason_t; + +typedef struct _RemovedPort { + uint64_t guid; + uint32_t index; + RemovedEntityReason_t reason; + struct _RemovedPort *next; +} RemovedPort_t; + +typedef struct { + uint64_t guid; + STL_NODE_DESCRIPTION desc; + cl_map_obj_t mapObj; + RemovedPort_t *ports; +} RemovedNode_t; + +typedef struct { + cl_qmap_t nodeMap; + Lock_t lock; + uint8_t initialized; +} RemovedEntities_t; + +// +// throttling MAD dispatcher +// + +// actual timeout passed to vs_event_wait in the wait loop +#define SM_DISPATCH_EVENT_TIMEOUT VTIMER_1S + +// number of loops (roughly each of length EVENT_TIMEOUT) that can pass with +// the dispatcher state remaining unchanged before we give up and assume +// that the dispatcher has stalled (likely due to a leak in the async +// context code) +#define SM_DISPATCH_STALL_THRESHOLD 7 // (0 - 255) + +typedef struct sm_dispatch_send_params { + SmMaiHandle_t *fd; + uint32_t method; + uint32_t aid; + uint32_t amod; + uint8_t *path; + STL_LID slid; + STL_LID dlid; + uint8_t buffer[STL_MAD_PAYLOAD_SIZE]; + uint32_t bufferLength; + uint64_t mkey; + uint32_t reply; + uint8_t bversion; + cntxt_callback_t callback; + void *callbackContext; +} sm_dispatch_send_params_t; + +typedef struct sm_dispatch_req { + sm_dispatch_send_params_t sendParams; + Node_t *nodep; + uint64_t sendTime; + uint32_t sweepPasscount; + struct sm_dispatch *disp; + struct sm_dispatch_req *next, *prev; + LIST_ITEM item; +} sm_dispatch_req_t; + +// we use sm_async_send_rcv_cntxt.lock to protect this structure +typedef struct sm_dispatch { + int initialized; + uint32_t reqsOutstanding; + uint32_t reqsSupported; + uint32_t sweepPasscount; + Event_t evtEmpty; + struct sm_dispatch_req *queueHead, *queueTail; + QUICK_LIST queue; +} sm_dispatch_t; + +// Adaptive Routing control settings +typedef struct { + uint8_t enable; + uint8_t debug; + uint8_t lostRouteOnly; + uint8_t algorithm; + uint8_t arFrequency; + uint8_t threshold; +} SmAdaptiveRouting_t; + +// +// Used for LMC port selection during routing +// + +typedef struct SwitchportToNextGuid +{ + uint64_t guid; + uint64_t sysGuid; + uint16_t sortIndex; + Port_t *portp; + Node_t *nextSwp; +} SwitchportToNextGuid_t; + +// +// Use for slsc/vlarb setup +// +typedef struct _VlVfMap +{ + bitset_t vf[STL_MAX_VLS]; +} VlVfMap_t; + +typedef struct _VlBwMap +{ + boolean has_qos; + uint8_t qos[STL_MAX_VLS]; + uint8_t bw[STL_MAX_VLS]; + uint8_t highPriority[STL_MAX_VLS]; +} VlBwMap_t; + +// +// Use for vlarb/bw setup +// +typedef struct _VlarbList +{ + uint8_t cap; // Low BW cap + uint8_t mtu; // MTU of this port + STL_VLARB_TABLE_ELEMENT vlarbLow[STL_MAX_LOW_CAP]; // vlarb bw table + struct _VlarbList *next; +} VlarbList_t; + + +typedef struct Qos +{ + uint8_t numVLs; + uint8_t activeVLs; + STL_SCVLMAP scvl; /* scvlr = scvl */ + bitset_t highPriorityVLs; + bitset_t lowPriorityVLs; + uint8_t dimensions; // used for dor only + VlBwMap_t vlBandwidth; + uint8_t weightMultiplier; // used for STL1 vlarb + VlVfMap_t vlvf; + VlarbList_t *vlarbList; // Used to cache common vlarb bw data +} Qos_t; + +typedef enum { + SM_SWEEP_REASON_INIT = 0, + SM_SWEEP_REASON_SCHEDULED, + SM_SWEEP_REASON_RECONFIG, + SM_SWEEP_REASON_MCMEMBER, + SM_SWEEP_REASON_ACTIVATE_FAIL, + SM_SWEEP_REASON_ROUTING_FAIL, + SM_SWEEP_REASON_MC_ROUTING_FAIL, + SM_SWEEP_REASON_UNEXPECTED_BOUNCE, + SM_SWEEP_REASON_LOCAL_PORT_FAIL, + SM_SWEEP_REASON_STATE_TRANSITION, + SM_SWEEP_REASON_SECONDARY_TROUBLE, + SM_SWEEP_REASON_MASTER_TROUBLE, + SM_SWEEP_REASON_UPDATED_STANDBY, + SM_SWEEP_REASON_HANDOFF, + SM_SWEEP_REASON_UNEXPECTED_SM, + SM_SWEEP_REASON_FORCED, + SM_SWEEP_REASON_INTERVAL_CHANGE, + SM_SWEEP_REASON_FAILED_SWEEP, + SM_SWEEP_REASON_TRAP_EVENT, + SM_SWEEP_REASON_UNQUARANTINE, + SM_SWEEP_REASON_UNDETERMINED +} SweepReason_t; + +extern SweepReason_t sm_resweep_reason; + +static __inline__ void setResweepReason(SweepReason_t reason) { + if (sm_resweep_reason == SM_SWEEP_REASON_UNDETERMINED) + sm_resweep_reason = reason; +} + +// +// IEEE defined OUIs +// +#define OUI_INTEL 0x00d0b7 + +#define INCR_PORT_COUNT(TP,NP) { \ + TP->num_ports++; \ + if (NP->nodeInfo.NodeType == NI_TYPE_CA) { \ + TP->num_endports++; \ + } \ +} + +#define DECR_PORT_COUNT(TP,NP) { \ + TP->num_ports--; \ + if (NP->nodeInfo.NodeType == NI_TYPE_CA) { \ + TP->num_endports--; \ + } \ +} + +// +// Macros for path resolution. +// +// +/* using switches only in floyd algo, requiring index in switch list instead of node index */ +#define Index(X,Y) ((X) * sm_topop->max_sws + (Y)) +#define Cost_Infinity (32767) /* small enough to ensure that inf+inf does not overflow */ +#define Min(X,Y) ((X) < (Y) ? (X) : (Y)) +#define Max(X,Y) ((X) > (Y) ? (X) : (Y)) + +#define PathToPort(NP,PP) ((NP)->nodeInfo.NodeType == NI_TYPE_SWITCH ? \ + (NP)->path : (PP)->path) + +// +// Macros for SM filter creation. +// +#define SM_Filter_Init(FILTERP) { \ + Filter_Init(FILTERP, 0, 0); \ + \ + (FILTERP)->active |= MAI_ACT_ADDRINFO; \ + (FILTERP)->active |= MAI_ACT_BASE; \ + (FILTERP)->active |= MAI_ACT_TYPE; \ + (FILTERP)->active |= MAI_ACT_DATA; \ + (FILTERP)->active |= MAI_ACT_DEV; \ + (FILTERP)->active |= MAI_ACT_PORT; \ + (FILTERP)->active |= MAI_ACT_QP; \ + (FILTERP)->active |= MAI_ACT_FMASK; \ + \ + (FILTERP)->type = MAI_TYPE_EXTERNAL; \ + \ + (FILTERP)->dev = sm_config.hca; \ + (FILTERP)->port = (sm_config.port == 0) ? MAI_TYPE_ANY : sm_config.port; \ + (FILTERP)->qp = 0; \ +} + +// +// Macros for Node enqueueing. +// +#define Node_Enqueue(TOPOP,NODEP,HEAD,TAIL) { \ + if (TOPOP->TAIL == NULL) { \ + NODEP->next = NULL; \ + NODEP->prev = NULL; \ + TOPOP->HEAD = NODEP; \ + TOPOP->TAIL = NODEP; \ + } else { \ + NODEP->next = NULL; \ + NODEP->prev = TOPOP->TAIL; \ + (TOPOP->TAIL)->next = NODEP; \ + TOPOP->TAIL = NODEP; \ + } \ +} + +#define Node_Enqueue_Type(TOPOP,NODEP,HEAD,TAIL) { \ + if (TOPOP->TAIL == NULL) { \ + NODEP->type_next = NULL; \ + NODEP->type_prev = NULL; \ + TOPOP->HEAD = NODEP; \ + TOPOP->TAIL = NODEP; \ + } else { \ + NODEP->type_next = NULL; \ + NODEP->type_prev = TOPOP->TAIL; \ + (TOPOP->TAIL)->type_next = NODEP; \ + TOPOP->TAIL = NODEP; \ + } \ +} + +#define Node_Dequeue_Type(TOPOP,NODEP,HEAD,TAIL) { \ + if (NODEP->type_prev) \ + NODEP->type_prev->type_next = NODEP->type_next; \ + if (NODEP->type_next) \ + NODEP->type_next->type_prev = NODEP->type_prev; \ + if (TOPOP->HEAD == NODEP) \ + TOPOP->HEAD = NODEP->type_next; \ + if (TOPOP->TAIL == NODEP) \ + TOPOP->TAIL = NODEP->type_prev; \ + NODEP->type_next = NODEP->type_prev = NULL; \ +} + + +// +// Macros for allocating Nodes and Ports. +// +#define sm_dynamic_port_alloc() \ + (sm_config.dynamic_port_alloc) + +#define STL_MFTABLE_POSITION_COUNT 4 + +static __inline__ int bitsForInteger(int x) { + int i=0; + + while (x > 0) { + x /= 2; + i++; + } + return i; +} + + +// +// Topology traversal macros. +// +#define for_all_nodes(TP,NP) \ + for (NP = (TP)->node_head; NP != NULL; NP = NP->next) + +#define for_all_ca_nodes(TP,NP) \ + for (NP = (TP)->ca_head; NP != NULL; NP = NP->type_next) + +#define for_all_tier_switches(TP,NP, tier) \ + for (NP = (TP)->tier_head[tier]; NP != NULL; NP = NP->sw_next) + +#define for_all_switch_nodes(TP,NP) \ + for (NP = (TP)->switch_head; NP != NULL; NP = NP->type_next) + +#define for_switch_list_switches(HD, NP) \ + for (NP = (HD); NP != NULL; NP = NP->next) + + +#define for_all_quarantined_nodes(TP,NP) \ + for (NP = (TP)->quarantined_node_head; NP != NULL; NP = NP->next) + +#define for_each_list_item(LIST, ITEM) \ + for (ITEM = QListHead(LIST); ITEM != NULL; ITEM = QListNext(LIST, ITEM)) + +// --------------------------------------------------------------------------- // +static __inline__ int sm_valid_port(const Port_t * portp) { + return ((portp != NULL) && (portp->portData != NULL)); +} + +static __inline__ int sm_valid_port_mgmt_allowed_pkey(Port_t * portp) { + if (portp->portData->pPKey[STL_DEFAULT_FM_PKEY_IDX].AsReg16 == STL_DEFAULT_FM_PKEY || + portp->portData->pPKey[STL_DEFAULT_CLIENT_PKEY_IDX].AsReg16 == STL_DEFAULT_FM_PKEY) + return 1; + else + return 0; +} + + +static inline +const char * sm_fwd_table_type_str(Topology_t *topop) +{ + return "LFT"; +} + +#ifndef __VXWORKS__ +static inline Port_t * sm_get_port(const Node_t *nodep, uint32_t portIndex) { + if (portIndex <= nodep->nodeInfo.NumPorts) { + return &nodep->port[portIndex]; + } + return NULL; +} +#else +Port_t * sm_get_port(const Node_t *nodep, uint32_t portIndex); +#endif + +static __inline__ int Is_Switch_Queued(Topology_t *tp, Node_t *nodep) { + int t; + if (nodep->sw_prev) return 1; + for (t=0; ttier_head[t] == nodep) return 1; + } + return 0; +} + +static __inline__ STL_LID sm_port_top_lid(Port_t * portp) { + return ((!portp) ? 0 : portp->portData->lid + (1 << portp->portData->lmc) - 1); +} + +static __inline__ boolean is_cc_supported_by_enhanceport0(Node_t *nodep) { + if (nodep->switchInfo.u2.s.EnhancedPort0 && (nodep->congestionInfo.ControlTableCap != 0)) { + return TRUE; + } + return FALSE; +} + +#define PORT_A0(NP) \ + ((NP->nodeInfo.NodeType == NI_TYPE_SWITCH) ? 0 : 1) + +#define PORT_A1(NP) \ + NP->nodeInfo.NumPorts + +#define for_all_ports(NP,PP) \ + if((PP = sm_get_port(NP,PORT_A0(NP))) == NULL) {} \ + else for (;PP <= sm_get_port(NP,PORT_A1(NP)); PP++) + + +// --------------------------------------------------------------------------- // +// useful when sm_find_node_and_port_lid has returned a matching port (MPP) +// and want to walk all matching ports in given device. For a HFI this walks +// just the matched port (since other ports will have different LIDs) and for +// a switch it matches all ports (since only port 0 had a LID) +#define PORT_A0_MATCHED(NP, MPP) \ + ((NP->nodeInfo.NodeType == NI_TYPE_SWITCH) ? 0 : MPP->index) + +#define PORT_A1_MATCHED(NP, MPP) \ + ((NP->nodeInfo.NodeType == NI_TYPE_SWITCH) ? NP->nodeInfo.NumPorts : MPP->index) + +#define for_all_matched_ports(NP,PP,MPP) \ + if((PP = sm_get_port(NP,PORT_A0_MATCHED(NP, MPP))) == NULL) {} \ + else for (;PP <= sm_get_port(NP,PORT_A1_MATCHED(NP, MPP)); PP++) + +// --------------------------------------------------------------------------- // + +#define PORT_E0(NP) \ + ((NP->nodeInfo.NodeType == NI_TYPE_SWITCH) ? 0 : 1) + +#define PORT_E1(NP) \ + ((NP->nodeInfo.NodeType == NI_TYPE_SWITCH) ? 0 : NP->nodeInfo.NumPorts) + +#define for_all_end_ports(NP,PP) \ + if((PP = sm_get_port(NP,PORT_E0(NP))) == NULL) {} \ + else for (;PP <= sm_get_port(NP,PORT_E1(NP)); PP++) + +#define for_all_end_ports2Nodes(NP1, PP1, NP2, PP2) \ + if ((PP1 = sm_get_port(NP1,PORT_E0(NP1))) == NULL || (PP2 = sm_get_port(NP2,PORT_E0(NP2))) == NULL) {}\ + else for (;PP1 <= sm_get_port(NP1,PORT_E1(NP1)); PP1++, PP2++) + +static __inline__ Port_t * sm_get_node_end_port(Node_t *nodep) { + Port_t *portp = NULL; + for_all_end_ports(nodep, portp) { + if(sm_valid_port(portp)) + return portp; + } + return NULL; +} +// --------------------------------------------------------------------------- // + +#define PORT_P0(NP) \ + ((NP->nodeInfo.NodeType == NI_TYPE_SWITCH) ? 1 : 1) + +#define PORT_P1(NP) \ + NP->nodeInfo.NumPorts + +#define for_all_physical_ports(NP,PP) \ + if((PP = sm_get_port(NP,PORT_P0(NP))) == NULL) {} \ + else for (;PP <= sm_get_port(NP,PORT_P1(NP)); PP++) + +// --------------------------------------------------------------------------- // + +#define PORT_S0(NP) \ + ((NP->nodeInfo.NodeType == NI_TYPE_SWITCH) ? 0 : 1) + +#define PORT_S1(NP) \ + ((NP->nodeInfo.NodeType == NI_TYPE_SWITCH) ? 0 : NP->nodeInfo.NumPorts) + +#define for_all_sma_ports(NP,PP) \ + if((PP = sm_get_port(NP,PORT_S0(NP))) == NULL) {} \ + else for (;PP <= sm_get_port(NP,PORT_S1(NP)); PP++) + +// --------------------------------------------------------------------------- // + +#define for_all_port_lids(PP,X) \ + for ((X) = (PP)->portData->lid; (X) < (int)((PP)->portData->lid + (1 << (PP)->portData->lmc)); (X)++) + +// --------------------------------------------------------------------------- // + +// +// Macros for allocating Multicast Groups and Members +// +#define McGroup_Enqueue(GROUPP) { \ + if (sm_McGroups == NULL) { \ + GROUPP->next = NULL; \ + sm_McGroups = GROUPP; \ + } else { \ + GROUPP->next = sm_McGroups; \ + sm_McGroups = GROUPP; \ + } \ +} + +#define McGroup_Dequeue(GROUPP) { \ + McGroup_t *localGroup; \ + \ + if (sm_McGroups == GROUPP) { \ + sm_McGroups = (GROUPP)->next; \ + } else { \ + for_all_multicast_groups(localGroup) { \ + if (localGroup->next == GROUPP) { \ + localGroup->next = (GROUPP)->next; \ + break; \ + } \ + } \ + } \ +} + +#define McGroup_Create(GROUPP) { \ + size_t local_size; \ + Status_t local_status; \ + \ + local_size = sizeof(McGroup_t) + 16; \ + local_status = vs_pool_alloc(&sm_pool, local_size, (void *)&GROUPP); \ + if (local_status != VSTATUS_OK) { \ + IB_FATAL_ERROR_NODUMP("can't allocate space"); \ + } \ + \ + memset((void *)GROUPP, 0, local_size); \ + if (!bitset_init(&sm_pool, &GROUPP->vfMembers, MAX_VFABRICS)) { \ + IB_FATAL_ERROR_NODUMP("McGroup_Create: can't allocate space"); \ + } \ + if (!bitset_init(&sm_pool, &GROUPP->new_vfMembers, MAX_VFABRICS)) { \ + IB_FATAL_ERROR_NODUMP("McGroup_Create: can't allocate space"); \ + } \ + McGroup_Enqueue(GROUPP); \ + ++sm_numMcGroups; \ +} + +#define McGroup_Delete(GROUPP) { \ + Status_t local_status; \ + \ + --sm_numMcGroups; \ + \ + sm_multicast_decommision_group(GROUPP); \ + McGroup_Dequeue(GROUPP); \ + bitset_free(&GROUPP->vfMembers); \ + bitset_free(&GROUPP->new_vfMembers); \ + local_status = vs_pool_free(&sm_pool, (void *)GROUPP); \ + if (local_status != VSTATUS_OK) { \ + IB_FATAL_ERROR("can't free space"); \ + } \ +} + +#define McMember_Enqueue(GROUPP,MEMBERP) { \ + if (GROUPP->mcMembers == NULL) { \ + MEMBERP->next = NULL; \ + GROUPP->mcMembers = MEMBERP; \ + } else { \ + MEMBERP->next = GROUPP->mcMembers; \ + GROUPP->mcMembers = MEMBERP; \ + } \ +} + +#define McMember_Dequeue(GROUPP,MEMBERP) { \ + McMember_t *localMember; \ + \ + if ((GROUPP)->mcMembers == MEMBERP) { \ + (GROUPP)->mcMembers = (MEMBERP)->next; \ + } else { \ + for_all_multicast_members(GROUPP, localMember) { \ + if (localMember->next == MEMBERP) { \ + localMember->next = (MEMBERP)->next; \ + break; \ + } \ + } \ + } \ +} + +#define McMember_Create(GROUPP,MEMBERP) { \ + size_t local_size; \ + Status_t local_status; \ + \ + local_size = sizeof(McMember_t) + 16; \ + local_status = vs_pool_alloc(&sm_pool, local_size, (void *)&MEMBERP); \ + if (local_status != VSTATUS_OK) { \ + IB_FATAL_ERROR_NODUMP("can't allocate space"); \ + } \ + \ + memset((void *)MEMBERP, 0, local_size); \ + MEMBERP->index = ++GROUPP->index_pool; \ + McMember_Enqueue(GROUPP, MEMBERP); \ +} + +#define McMember_Delete(GROUPP,MEMBERP) { \ + Status_t local_status; \ + \ + McMember_Dequeue(GROUPP, MEMBERP); \ + local_status = vs_pool_free(&sm_pool, (void *)MEMBERP); \ + if (local_status != VSTATUS_OK) { \ + IB_FATAL_ERROR("can't free space"); \ + } \ +} + +// --------------------------------------------------------------------------- // + +#define for_all_multicast_groups(GP) \ + for (GP = sm_McGroups; GP != NULL; GP = GP->next) + +// --------------------------------------------------------------------------- // + +#define for_all_multicast_members(GP,MP) \ + for (MP = GP->mcMembers; MP != NULL; MP = MP->next) + +// --------------------------------------------------------------------------- // + +// +// Miscellaneous macros +// +#define IsDirectConnected(SN,SP,DN,DP) \ + ((((SP)->nodeno == (DN)->index) && ((SP)->portno == (DP)->index)) && \ + (((DP)->nodeno == (SN)->index) && ((DP)->portno == (SP)->index))) + +// Cost should be evenly divisable by (width * SpeedFactor) +#define SpeedWidth_to_Cost(X) ((X) ? 1200/(X) : 1200) + +static __inline__ uint8_t sm_GetLsf(STL_PORT_INFO *portInfo) { + switch (portInfo->LinkSpeed.Active) { + case STL_LINK_SPEED_25G: return 25; + default: + DEBUG_ASSERT(FALSE); + return 25; + } +} + +static __inline__ uint64_t sm_GetBandwidth(STL_PORT_INFO *portInfo) { + uint64_t speed; + + switch (portInfo->LinkSpeed.Active) { + case STL_LINK_SPEED_25G: speed = 25781250000LL; break; + default: + DEBUG_ASSERT(FALSE); + speed = 25781250000LL; + break; + } + + // Calculate bytes/sec BW: speed * width * 64/66 (encoding overhead) * 1/8 (bits to bytes) + return speed * StlLinkWidthToInt(portInfo->LinkWidth.Active)*4/33;; +} + +static __inline__ uint16_t sm_GetSpeed(PortData_t *portData) { + return (sm_GetLsf(&portData->portInfo) * StlLinkWidthToInt(portData->portInfo.LinkWidth.Active)); +} + +static __inline__ uint16_t sm_GetCost(PortData_t *portData) { + return (SpeedWidth_to_Cost(sm_GetSpeed(portData))); +} + +static __inline__ char* sm_nodeDescString(Node_t *nodep) { + return ((nodep->nodeDescString) ? nodep->nodeDescString : (char *)nodep->nodeDesc.NodeString); +} + +static __inline__ int sm_stl_port(Port_t *portp) { + return (portp->portData->portInfo.PortLinkMode.s.Active & STL_PORT_LINK_MODE_STL); +} + +static __inline__ int sm_IsInterleaveEnabled(STL_PORT_INFO *portInfo) { + return(portInfo->PortMode.s.IsVLMarkerEnabled || + portInfo->FlitControl.Interleave.s.MaxNestLevelTxEnabled); +} + +static __inline__ int sm_IsVLrSupported(const Node_t *nodep, const Port_t *portp) { + + if (nodep->nodeInfo.NodeType == NI_TYPE_SWITCH) { + Port_t * port0 = sm_get_port(nodep, 0); + if (sm_valid_port(port0) && port0->state > IB_PORT_DOWN && + port0->portData->portInfo.CapabilityMask3.s.IsVLrSupported) + return 1; + + } else if (portp->portData->portInfo.CapabilityMask3.s.IsVLrSupported) + return 1; + + return 0; +} + +static __inline__ int sm_stl_appliance(uint64 nodeGuid) { + int i, appliance = 0; + + if (sm_config.appliances.enable && nodeGuid) { + for (i = 0; i < MAX_SM_APPLIANCES; i++) { + if (sm_config.appliances.guids[i] == nodeGuid) + appliance = 1; + } + } + + return appliance; +} + +static __inline__ int sm_is_scae_allowed(Node_t * nodep) { + return sm_config.switchCascadeActivateEnable == SCAE_ALL + || (sm_config.switchCascadeActivateEnable == SCAE_SW_ONLY && nodep->nodeInfo.NodeType == STL_NODE_SW); +} + +static __inline__ boolean is_swport(Port_t *portp) { + return portp->portData->nodePtr->nodeInfo.NodeType == NI_TYPE_SWITCH; +} + +static __inline__ boolean is_hfiport(Port_t *portp) { + return portp->portData->nodePtr->nodeInfo.NodeType == NI_TYPE_CA; +} + +static __inline__ boolean is_swport0(Port_t *portp) { + return (portp->portData->nodePtr->nodeInfo.NodeType == NI_TYPE_SWITCH && portp->index == 0); +} + +static __inline__ boolean is_extswport(Port_t *portp) { + return (portp->portData->nodePtr->nodeInfo.NodeType == NI_TYPE_SWITCH && portp->index > 0); +} + +// --------------------------------------------------------------------------- // + +// +// Externs +// +extern SMXmlConfig_t sm_config; +extern PMXmlConfig_t pm_config; +extern FEXmlConfig_t fe_config; + + +extern SMDPLXmlConfig_t sm_dpl_config; +extern SMMcastConfig_t sm_mc_config; +extern SmMcastMlidShare_t sm_mls_config; +extern SMMcastDefGrpCfg_t sm_mdg_config; + +extern uint32_t sm_needed_vls; +extern uint32_t sm_def_mc_group; +extern uint8_t sm_env[32]; +extern STL_LID sm_lid; +extern STL_LID sm_lmc_0_freeLid_hint; +extern STL_LID sm_lmc_e0_freeLid_hint; +extern STL_LID sm_lmc_freeLid_hint; +extern uint32_t sm_state; +extern uint32_t sm_prevState; +extern int sm_saw_another_sm; +extern int sm_hfi_direct_connect; +extern uint8_t sm_mkey_protect_level; +extern uint16_t sm_mkey_lease_period; +extern uint64_t sm_masterCheckInterval; +extern uint32_t sm_masterCheckMaxFail; +extern uint32_t sm_mcDosThreshold; +extern uint32_t sm_mcDosAction; +extern uint64_t sm_mcDosInterval; +extern uint64_t sm_portguid; +extern STL_SM_INFO sm_smInfo; +extern uint32_t sm_masterStartTime; +extern uint8_t sm_description[65]; +extern LidMap_t * lidmap; +extern cl_qmap_t * sm_GuidToLidMap; + +extern uint32_t topology_passcount; + +extern boolean vf_config_changed; +extern boolean reconfig_in_progress; +extern Lock_t old_topology_lock; // a RW Thread Lock +extern Lock_t new_topology_lock; // a Thread Lock + +extern Lock_t handover_sent_lock; +extern uint32_t handover_sent; +extern uint32_t triggered_handover; + +#ifdef __LINUX__ +extern Lock_t linux_shutdown_lock; // a RW Thread Lock +#endif + +extern Topology_t old_topology; +extern Topology_t sm_newTopology; +extern Topology_t *sm_topop; + +extern boolean sweepsPaused; + +extern sm_dispatch_t sm_asyncDispatch; + +extern int topology_main_exit; + +extern uint32_t sm_log_level; +extern uint32_t sm_log_level_override; +extern uint32_t sm_log_masks[VIEO_LAST_MOD_ID+1]; +extern int sm_log_to_console; +extern char sm_config_filename[256]; + +extern Sema_t topology_sema; +extern Sema_t topology_rcv_sema; +extern uint64_t topology_sema_setTime; +extern uint64_t topology_sema_runTime; +extern uint64_t topology_wakeup_time; +extern uint32_t sm_debug; +extern uint32_t smDebugPerf; // control SM/SA performance messages; default off in ESM +extern uint32_t smFabricDiscoveryNeeded; // smFabricDiscoveryNeeded is shared between threads to synchronize sweeps +extern uint64_t lastTimeDiscoveryRequested; // lastTimeDiscoveryRequested is shared between threads to synchronize sweeps +extern uint32_t smDebugDynamicAlloc; // control SM/SA memory allocation messages; default off in ESM +extern uint32_t sm_trapThreshold; // threshold of traps/min for port auto-disable +extern uint32_t sm_trapThreshold_minCount; //minimum number of traps to validate sm_trapThreshold +extern uint64_t sm_trapThresholdWindow; // time window for observing traps in milliseconds +extern STL_LID sm_mcast_mlid_table_cap; + +extern uint16_t sm_masterSmSl; +extern bitset_t sm_linkSLsInuse; +extern int sm_QosConfigChange; + +extern SmAdaptiveRouting_t sm_adaptiveRouting; + +extern uint32_t sm_useIdealMcSpanningTreeRoot; +extern uint32_t sm_mcSpanningTreeRoot_useLeastWorstCaseCost; +extern uint32_t sm_mcSpanningTreeRoot_useLeastTotalCost; +extern uint32_t sm_mcRootCostDeltaThreshold; +/************ Multicast Globals *********************************/ +extern uint32_t sm_numMcGroups; +extern ATOMIC_UINT sm_McGroups_Need_Prog; +extern McGroup_t *sm_McGroups; +extern Lock_t sm_McGroups_lock; + +extern uint64_t sm_mcSpanningTreeRootGuid; +extern Lock_t sm_mcSpanningTreeRootGuidLock; +/************ DOR Globals ***************************************/ +extern Lock_t sm_datelineSwitchGUIDLock; +extern uint64_t sm_datelineSwitchGUID; + +/************ dynamic update of switch config parms *************/ +extern uint8_t sa_dynamicPlt[]; + +/************ loop test externs from sm_userexits ***************/ +extern STL_LID loopPathLidStart; +extern STL_LID loopPathLidEnd; +extern int esmLoopTestOn; +extern int esmLoopTestAllowAdaptiveRouting; +extern int esmLoopTestFast; +extern int esmLoopTestNumPkts; +extern int esmLoopTestPathLen; +extern uint32_t esmLoopTestTotalPktsInjected; +extern int esmLoopTestInjectNode; +extern uint8_t esmLoopTestInjectEachSweep; +extern uint8_t esmLoopTestForceInject; +extern int esmLoopTestMinISLRedundancy; + +extern Popo_t sm_popo; + +// +// Miscellaneous stuff. +// +//#define MAD_RETRIES 4 // moved to "ib/include/ib_const.h" + +static __inline__ void block_sm_exit(void) { + #ifdef __LINUX__ + vs_rdlock(&linux_shutdown_lock); + #endif +} + +static __inline__ void unblock_sm_exit(void) { + #ifdef __LINUX__ + vs_rwunlock(&linux_shutdown_lock); + #endif +} + + +// +// Convenience macros for Get(*) and Set(*) +// +Status_t SM_Get_NodeDesc(SmMaiHandle_t *, uint32_t, SmpAddr_t *, STL_NODE_DESCRIPTION *); +Status_t SM_Get_NodeInfo(SmMaiHandle_t *, uint32_t, SmpAddr_t *, STL_NODE_INFO *); +Status_t SM_Get_PortInfo(SmMaiHandle_t *, uint32_t, SmpAddr_t *, STL_PORT_INFO *); +Status_t SM_Set_PortInfo(SmMaiHandle_t *, uint32_t, SmpAddr_t *, STL_PORT_INFO *, uint64_t, uint32_t *); +Status_t SM_Set_PortInfo_Dispatch(SmMaiHandle_t *, uint32_t amod, SmpAddr_t *addr, STL_PORT_INFO *pip, uint64_t mkey, Node_t *nodep, sm_dispatch_t *disp, cntxt_callback_t callback, void *cb_data); +Status_t SM_Get_PortStateInfo(SmMaiHandle_t *, uint32_t, SmpAddr_t *, STL_PORT_STATE_INFO *); +Status_t SM_Get_PortStateInfo_Dispatch(SmMaiHandle_t *fd, uint32_t amod, SmpAddr_t *addr, Node_t *nodep, sm_dispatch_t *disp, cntxt_callback_t callback, void *cb_data); +Status_t SM_Set_PortStateInfo(SmMaiHandle_t *, uint32_t, SmpAddr_t *, STL_PORT_STATE_INFO *, uint64_t); +Status_t SM_Get_SwitchInfo(SmMaiHandle_t *, uint32_t, SmpAddr_t *, STL_SWITCH_INFO *); +Status_t SM_Set_SwitchInfo(SmMaiHandle_t *, uint32_t, SmpAddr_t *, STL_SWITCH_INFO *, uint64_t); +Status_t SM_Get_SMInfo(SmMaiHandle_t *, uint32_t, SmpAddr_t *, STL_SM_INFO *); +Status_t SM_Set_SMInfo(SmMaiHandle_t *, uint32_t, SmpAddr_t *, STL_SM_INFO *, uint64_t); +Status_t SM_Get_VLArbitration(SmMaiHandle_t *, uint32_t, SmpAddr_t *, STL_VLARB_TABLE *); +Status_t SM_Set_VLArbitration(SmMaiHandle_t *fd, uint32_t amod, SmpAddr_t *, STL_VLARB_TABLE *vlp, size_t vlpSize, uint64_t mkey); + +Status_t SM_Get_SLSCMap(SmMaiHandle_t *fd, uint32_t amod, SmpAddr_t *, STL_SLSCMAP *slscp); +Status_t SM_Set_SLSCMap(SmMaiHandle_t *fd, uint32_t amod, SmpAddr_t *, STL_SLSCMAP *slscp, uint64_t mkey); +Status_t SM_Get_SCSLMap(SmMaiHandle_t *, uint32_t, SmpAddr_t *, STL_SCSLMAP *); +Status_t SM_Set_SCSLMap(SmMaiHandle_t *, uint32_t, SmpAddr_t *, STL_SCSLMAP *, uint64_t); +Status_t SM_Get_SCVLtMap(SmMaiHandle_t *, uint32_t, SmpAddr_t *, STL_SCVLMAP *); +Status_t SM_Set_SCVLtMap(SmMaiHandle_t *, uint32_t, SmpAddr_t *, STL_SCVLMAP *, uint64_t); +Status_t SM_Get_SCVLntMap(SmMaiHandle_t *, uint32_t, SmpAddr_t *, STL_SCVLMAP *); +Status_t SM_Set_SCVLntMap(SmMaiHandle_t *, uint32_t, SmpAddr_t *, STL_SCVLMAP *, uint64_t); +Status_t SM_Get_SCVLrMap(SmMaiHandle_t *, uint32_t, SmpAddr_t *, STL_SCVLMAP *); +Status_t SM_Set_SCVLrMap(SmMaiHandle_t *, uint32_t, SmpAddr_t *, STL_SCVLMAP *, uint64_t); +Status_t SM_Set_SCSC(SmMaiHandle_t *, uint32_t, SmpAddr_t *, STL_SCSCMAP *, uint64_t); +Status_t SM_Set_SCSCMultiSet(SmMaiHandle_t *fd, uint32_t, SmpAddr_t *, STL_SCSC_MULTISET *, uint64_t); +Status_t SM_Set_LFT(SmMaiHandle_t *, uint32_t, SmpAddr_t *, STL_LINEAR_FORWARDING_TABLE *, uint64_t); +Status_t SM_Set_LFT_Dispatch(SmMaiHandle_t *, uint32_t, SmpAddr_t *, STL_LINEAR_FORWARDING_TABLE *, uint16_t, uint64_t, Node_t *, sm_dispatch_t *); + + +Status_t SM_Set_MFT_Dispatch(SmMaiHandle_t *, uint32_t, SmpAddr_t *, STL_MULTICAST_FORWARDING_TABLE *, uint64_t, Node_t *, sm_dispatch_t *); +Status_t SM_Get_PKeyTable(SmMaiHandle_t * fd, uint32_t amod, SmpAddr_t *addr, STL_PARTITION_TABLE *pkp); +Status_t SM_Set_PKeyTable(SmMaiHandle_t * fd, uint32_t amod, SmpAddr_t *addr, STL_PARTITION_TABLE *pkp, uint64_t); +Status_t SM_Set_PKeyTable_Dispatch(SmMaiHandle_t * fd, uint32_t amod, SmpAddr_t *addr, STL_PARTITION_TABLE *pkp, uint64_t mkey, Node_t *nodep, sm_dispatch_t *disp, cntxt_callback_t callback, void *cb_data); +Status_t SM_Get_PortGroup(SmMaiHandle_t * fd, uint32_t amod, SmpAddr_t *addr, STL_PORT_GROUP_TABLE *pgp, uint8_t blocks); +Status_t SM_Set_PortGroup(SmMaiHandle_t * fd, uint32_t amod, SmpAddr_t *addr, STL_PORT_GROUP_TABLE *pgp, uint8_t blocks, uint64_t mkey); +Status_t SM_Get_PortGroupFwdTable(SmMaiHandle_t * fd, uint32_t amod, SmpAddr_t *addr, STL_PORT_GROUP_FORWARDING_TABLE *pp, uint8_t blocks); +Status_t SM_Set_PortGroupFwdTable(SmMaiHandle_t * fd, uint32_t amod, SmpAddr_t *addr, STL_PORT_GROUP_FORWARDING_TABLE *pp, uint8_t blocks, uint64_t mkey); +Status_t SM_Get_BufferControlTable(SmMaiHandle_t * fd, uint32_t amod, SmpAddr_t *addr, STL_BUFFER_CONTROL_TABLE pbct[]); +Status_t SM_Set_BufferControlTable(SmMaiHandle_t * fd, uint32_t amod, SmpAddr_t *addr, STL_BUFFER_CONTROL_TABLE pbct[], uint64_t mkey, uint32_t* madStatus); +Status_t SM_Get_CongestionInfo(SmMaiHandle_t * fd, uint32_t amod, SmpAddr_t *addr, STL_CONGESTION_INFO * congestionInfo); +Status_t SM_Get_HfiCongestionSetting(SmMaiHandle_t * fd, uint32_t amod, SmpAddr_t *addr, STL_HFI_CONGESTION_SETTING *hfics); +Status_t SM_Set_HfiCongestionSetting(SmMaiHandle_t * fd, uint32_t amod, SmpAddr_t *addr, STL_HFI_CONGESTION_SETTING *hfics, uint64_t mkey); +Status_t SM_Get_HfiCongestionControl(SmMaiHandle_t * fd, uint32_t amod, SmpAddr_t *addr, STL_HFI_CONGESTION_CONTROL_TABLE *hficct); +Status_t SM_Set_HfiCongestionControl(SmMaiHandle_t * fd, uint16 CCTI_Limit, const uint8_t numBlocks, uint32_t amod, SmpAddr_t *addr, STL_HFI_CONGESTION_CONTROL_TABLE_BLOCK *hficct, uint64_t mkey); +Status_t SM_Get_SwitchCongestionSetting(SmMaiHandle_t * fd, uint32_t amod, SmpAddr_t *addr, STL_SWITCH_CONGESTION_SETTING *swcs); +Status_t SM_Set_SwitchCongestionSetting(SmMaiHandle_t * fd, uint32_t amod, SmpAddr_t *addr, STL_SWITCH_CONGESTION_SETTING *swcs, uint64_t mkey); +Status_t SM_Get_SwitchPortCongestionSetting(SmMaiHandle_t * fd, uint32_t amod, SmpAddr_t *addr, STL_SWITCH_PORT_CONGESTION_SETTING *swpcs); +Status_t SM_Get_LedInfo(SmMaiHandle_t * fd, uint32_t amod, SmpAddr_t *addr, STL_LED_INFO *li); +Status_t SM_Set_LedInfo(SmMaiHandle_t * fd, uint32_t amod, SmpAddr_t *addr, STL_LED_INFO *li, uint64_t mkey); + +/** + Do an SMA Get(CableInfo) on the specified endpoint. + + Operates in 64-byte half-pages even though CableInfo is stored in 128-byte pages. + + @param startSeg the starting 64-byte segment + @param segCount the number of 64-byte segments to request + @param [out] ci points to start of output. Must have enough space for all request segments. + @param [out] madStatus The MAD status of the Get(CableInfo); set to 0 at start +*/ +Status_t SM_Get_CableInfo(SmMaiHandle_t * fd, uint8_t portIdx, uint8_t startSeg, uint8_t segCount, SmpAddr_t *addr, STL_CABLE_INFO * ci, uint32_t * madStatus); + +/** + Perform Get(Aggregate) with the requests in [start, end). See @c SM_Aggregate_impl() for more details. +*/ +Status_t +SM_Get_Aggregate_LR(SmMaiHandle_t * fd, STL_AGGREGATE * start, STL_AGGREGATE * end, + size_t lastSegReqLen, STL_LID srcLid, STL_LID destLid, STL_AGGREGATE ** lastSeg, + uint32_t * madStatus); + +/** + Perform Set(Aggregate) with the requests in [start, end). See @c SM_Aggregate_impl() for more details. +*/ +Status_t +SM_Set_Aggregate_LR(SmMaiHandle_t * fd, STL_AGGREGATE * start, STL_AGGREGATE * end, + STL_LID srcLid, STL_LID destLid, uint64_t mkey, STL_AGGREGATE ** lastSeg, uint32_t * madStatus); + +/** + Perform DR Get(Aggregate) with the requests in [start, end). See @c SM_Aggregate_impl() for more details. +*/ +Status_t +SM_Get_Aggregate_DR(SmMaiHandle_t * fd, STL_AGGREGATE * start, STL_AGGREGATE * end, + size_t lastSegReqLen, uint8_t *path, STL_AGGREGATE ** lastSeg, uint32_t * madStatus); + +// +// Multicast data structures. +// +typedef struct _McNode { + int32_t index; // node index + int32_t nodeno; // closest node in the tree + int32_t portno; // port on closest node + int32_t height; // distance from the root + struct _McNode *parent; // parent in spanning tree + STL_LID mft_mlid_init; +} McNode_t; + +typedef struct _McSpanningTree { + int32_t num_nodes; + McNode_t *nodes; + STL_LID first_mlid; + uint32_t reserved; // Padding to make the size a multiple of 8 bytes +} McSpanningTree_t; + +typedef struct McSpaningTrees { + McSpanningTree_t *spanningTree; + uint8_t copy; // Is this a shallow copy of another tree? +} McSpanningTrees_t; + + +// +// Externs. +// +extern SMThread_t * sm_threads; + +extern SmMaiHandle_t *fd_sa; +extern SmMaiHandle_t *fd_sa_writer; +extern SmMaiHandle_t *fd_multi; +extern SmMaiHandle_t *fd_async; +extern SmMaiHandle_t *fd_async_request; +extern SmMaiHandle_t *fd_saTrap; +extern SmMaiHandle_t *fd_policy; +extern SmMaiHandle_t *fd_topology; +extern SmMaiHandle_t *fd_loopTest; +extern SmMaiHandle_t *fd_atopology; +extern SmMaiHandle_t *fd_flapping_port; + +extern int ib_mad_dump_flag; // JSY - debug only + +extern McSpanningTree_t **uniqueSpanningTrees; +extern int uniqueSpanningTreeCount; + +extern Node_t *sm_mcSpanningTreeRootSwitch; +extern uint64_t sm_mcSpanningTreeRootGuid; + +extern Status_t sm_update_mc_groups(VirtualFabrics_t *newVF, VirtualFabrics_t *oldVF); + + +// +// Prototypes. +// +const char *sm_getStateText (uint32_t state); +Status_t sa_Get_PKeys(STL_LID, uint16_t *, uint32_t *); +Status_t sa_Compare_PKeys(STL_PKEY_ELEMENT *, STL_PKEY_ELEMENT *); +Status_t sa_Compare_Node_PKeys(Node_t *, Node_t *); +Status_t sa_Compare_Port_PKeys(Port_t *port1, Port_t *port2); + +uint8_t linkWidthToRate(PortData_t *portData); + +Status_t sm_mkey_check(Mai_t *, uint64_t *); +Status_t sm_dump_mai(const char *, Mai_t *); +Status_t sm_transition(uint32_t); + +Status_t sm_error(Status_t); +Status_t sm_start_thread(SMThread_t *); + +Status_t mai_reply(IBhandle_t, Mai_t *); +Status_t mai_stl_reply(IBhandle_t, Mai_t *, uint32_t); +// +// sm_topology.c prototypes +// + +extern void sm_request_resweep(int, int, SweepReason_t); +extern void sm_trigger_sweep(SweepReason_t); +extern void sm_discovery_needed(const char*, STL_LID); + +// +// sm_async.c prototypes +// +void async_init(void); +void async_main(uint32_t, uint8_t **); +int sm_send_xml_file(uint8_t); + +// +// sm_fsm prototypes +// +extern Status_t state_event_mad(Mai_t *); +extern Status_t state_event_timeout(void); + +// +// sm_qos +// +void sm_setup_SC2VL(VirtualFabrics_t *); + +Status_t sm_select_vlvf_map(Topology_t *, Node_t *, Port_t *, VlVfMap_t *); +Status_t sm_select_vlbw_map(Topology_t *, Node_t *, Port_t *, VlBwMap_t *); +Status_t sm_fill_stl_vlarb_table(Topology_t *, Node_t *, Port_t *, struct _PortDataVLArb *); +Status_t sm_select_slsc_map(Topology_t *, Node_t *, Port_t *, Port_t *, STL_SLSCMAP *); +Status_t sm_select_scsl_map(Topology_t *, Node_t *, Port_t *, Port_t *, STL_SCSLMAP *); +Status_t sm_select_scvlr_map(Topology_t *, uint8_t, STL_SCVLMAP *); +Status_t sm_select_scvl_map(Topology_t *, Node_t *, Port_t *, Port_t *, STL_SCVLMAP *); +void sm_destroy_qos(void); + +// +// sm_topology_rcv.c prototypes +// +void topology_rcv(uint32_t, uint8_t **); + +// +// sm_utility.c prototypes. +// + +#define WAIT_FOR_REPLY 0 +#define RCV_REPLY_AYNC 1 +#define WANT_REPLY_ON_QUEUE 2 + +void sm_portinfo_nop_init(STL_PORT_INFO *pi); + +Status_t sm_calculate_lft(Topology_t *topop, Node_t *switchp); +Status_t sm_write_minimal_lft_blocks(Topology_t *topop, Node_t *switchp, SmpAddr_t * addr); +Status_t sm_write_full_lfts_by_block_LR(Topology_t *topop, SwitchList_t *swlist, int rebalance); +/// Recomputes and sends LFTs, PGTs, and PGFTs +Status_t sm_setup_lft(Topology_t *, Node_t *); +Status_t sm_send_lft(Topology_t *, Node_t *); +Status_t sm_setup_lft_deltas(Topology_t *, Topology_t *, Node_t *); +Status_t sm_send_partial_lft(Topology_t *, Node_t *, bitset_t *); +Status_t sm_calculate_all_lfts(Topology_t *); + +Status_t sm_select_path_lids(Topology_t *, Port_t *, STL_LID, Port_t *, STL_LID , STL_LID *, uint8_t *, STL_LID *, uint8_t *); + +Status_t sm_get_stl_attribute(SmMaiHandle_t * fd, uint32_t aid, uint32_t amod, SmpAddr_t * addr, uint8_t *buffer, uint32_t *bufferLength); +Status_t sm_set_stl_attribute(SmMaiHandle_t *, uint32_t, uint32_t, SmpAddr_t *, uint8_t *, uint32_t *, uint64_t); +Status_t sm_set_stl_attribute_mad_status(SmMaiHandle_t *, uint32_t, uint32_t, SmpAddr_t *, uint8_t *, uint32_t *, uint64_t, uint32_t*); + +Status_t sm_get_stl_attribute_async_dispatch(SmMaiHandle_t *, uint32_t, uint32_t, SmpAddr_t *, uint8_t *, uint32_t *, Node_t *, sm_dispatch_t *, cntxt_callback_t, void *); +Status_t sm_set_stl_attribute_async_dispatch(SmMaiHandle_t *, uint32_t, uint32_t, SmpAddr_t *, uint8_t *, uint32_t *, uint64_t, Node_t *, sm_dispatch_t *, cntxt_callback_t, void *); +/** + * Simple generic response check function for the dispatcher callback function + * to use. + * + * @param cntxt generic callback struct containg send context which contains + * request mad. + * @param status Context status returned + * @param nodep optional Pointer to node (for Node GUID and Description) + * @param portp optional Pointer to port (for port number) + * @param mad response mad + * + * @return boolean TRUE if context status and MAD status OK otherwise FALSE + */ +boolean sm_callback_check(cntxt_entry_t *cntxt, Status_t status, Node_t *nodep, Port_t *portp, Mai_t *mad); + +Status_t sm_send_stl_request(SmMaiHandle_t * fd, uint32_t method, uint32_t aid, uint32_t amod, SmpAddr_t * addr, uint8_t *buffer, uint32_t *bufferLength, uint64_t mkey, uint32_t *madStatus); +Status_t sm_send_stl_request_impl(SmMaiHandle_t *, uint32_t, uint32_t, uint32_t, SmpAddr_t *, uint32_t, uint8_t *, uint32_t *, uint32_t, uint64_t, cntxt_callback_t, void *, uint32_t *); +int sm_find_cached_node_port(Node_t *cnp, Port_t *cpp, Node_t **nodep, Port_t **portp); +int sm_find_cached_neighbor(Node_t *cnp, Port_t *cpp, Node_t **nodep, Port_t **portp); +void sm_get_nonresp_cache_node_port(Node_t *cnp, Port_t *cpp, Node_t **nodep, Port_t **portp); +Status_t sm_check_Master(void); +Status_t sm_initialize_port(ParallelSweepContext_t *psc, SmMaiHandle_t *, Topology_t *, Node_t *, Port_t *, SmpAddr_t *); +Status_t sm_initialize_port_LR_DR(ParallelSweepContext_t *psc, SmMaiHandle_t *fd, Topology_t *topop, Node_t *nodep, Port_t *portp); +Status_t sm_initialize_switch_LR_DR(Topology_t *topop, Node_t *nodep, STL_LID parent_switch_lid, uint8_t parent_portno, int routing_needed); +Status_t sm_prep_switch_layer_LR_DR(Topology_t *topop, Node_t *nodep, SwitchList_t *swlist_head, int rebalance); +Status_t sm_setup_switches_lrdr_wave_discovery_order(Topology_t *topop, int rebalance, int routing_needed); + +//Methods for dynamic reconfiguration +void sm_config_apply(FMXmlCompositeConfig_t *xml_config); +void pm_config_apply(FMXmlCompositeConfig_t *xml_config); +void fe_config_apply(FMXmlCompositeConfig_t *xml_config); +boolean sm_config_valid(FMXmlCompositeConfig_t *xml_config, VirtualFabrics_t* newVfPtr, VirtualFabrics_t* oldVfPtr); +boolean pm_config_valid(FMXmlCompositeConfig_t *xml_config); +boolean fe_config_valid(FMXmlCompositeConfig_t *xml_config); + + +/** + Update SLSC, SCSL, SCVLt/nt, and VLArb values on @c nodep with values from old topology and/or SMA at @c smaportp. + + For switches, get values for all ports via @c smaportp. For HFIs, get values only for @c smaportp. + + @return VSTATUS_OK if all values were updated successfully, something else otherwise. +*/ +Status_t +sm_node_updateFields(SmMaiHandle_t * fd, STL_LID slid, Node_t * nodep, Port_t * smaportp); + +/** + Updates cableInfo stored in @c portp->portData->cableInfo using SMA Get(CableInfo). + + Allocates memory for @c portp->portData->cableInfo if not already allocated; otherwise uses existing memory. + + @return VSTATUS_OK on success, VSTATUS_NOSUPPORT if @c portp does not support Get(CableInfo), or VSTATUS_BAD on runtime error. +*/ +Status_t sm_update_cableinfo(ParallelSweepContext_t *, SmMaiHandle_t *, Topology_t *, Node_t *, Port_t * portp); + +Status_t sm_get_node_port_states(SmMaiHandle_t * fd, Topology_t *, Node_t *, Port_t *, uint8_t *, STL_PORT_STATE_INFO **, ParallelSweepContext_t *psc); +Status_t sm_set_node_port_states(SmMaiHandle_t * fd, Topology_t *, Node_t *, Port_t *, uint8_t *, uint32_t, uint32_t, STL_PORT_STATE_INFO **); +Status_t sm_disable_port(Topology_t *, Node_t *, Port_t *); +Status_t sm_bounce_port(Topology_t *, Node_t *, Port_t *); +Status_t sm_bounce_link(Topology_t *, Node_t *, Port_t *); +Status_t sm_bounce_all_switch_ports(SmMaiHandle_t * fd, Topology_t *topop, Node_t *nodep, Port_t *portp, uint8_t *path, ParallelSweepContext_t *psc); +Status_t sm_get_CapabilityMask(SmMaiHandle_t *, uint8_t, uint32_t *); +Status_t sm_set_CapabilityMask(SmMaiHandle_t *, uint8_t, uint32_t); +Node_t *sm_find_guid(Topology_t *, uint64_t); +Node_t *sm_find_node_by_name(Topology_t * topop, char *name); +Node_t *sm_find_quarantined_guid(Topology_t *topop, uint64_t guid); +Node_t *sm_find_next_guid(Topology_t *, uint64_t); +Node_t *sm_find_node(Topology_t *, int32_t); +Node_t *sm_find_node_by_path(Topology_t *, Node_t *, uint8_t *); +Port_t *sm_find_node_port(Topology_t *, Node_t *, int32_t); +Node_t *sm_find_switch(Topology_t *, uint16_t); +Node_t *sm_find_port_node(Topology_t *, Port_t *); +Port_t *sm_find_port(Topology_t *, int32_t, int32_t); +Port_t *sm_find_port_guid(Topology_t *, uint64_t); +Port_t *sm_find_port_peer(Topology_t *topop, uint64_t node_guid, int32_t port_no); +Port_t *sm_find_active_port_guid(Topology_t *, uint64_t); +Port_t *sm_find_port_lid(Topology_t *, STL_LID); +Port_t *sm_find_active_port_lid(Topology_t *, STL_LID); +Port_t *sm_find_node_and_port_lid(Topology_t *, STL_LID, Node_t **); +Port_t *sm_find_neighbor_node_and_port(Topology_t *, Port_t *, Node_t **); +Status_t sm_find_node_and_port_pair_lid(Topology_t *, STL_LID, uint32_t, Node_t **, Port_t **, Port_t **, Node_t **, Port_t **, Port_t **); +void sm_dump_node_map(Topology_t *topop); + +/* + * lidmap functions + */ +boolean sm_get_expected_lid_lmc(const Port_t *pp, STL_LID *expLid, uint8_t *expLmc); + +typedef enum { + LIDCHECK_OK = 0, + LIDCHECK_OUTOFRANGE = 1, // outside unicast range + LIDCHECK_OFFLMC = 2, // LID is not % lid_offset (usually 1 << LMC) + LIDCHECK_UNAVAIL = 3 // LID is assigned to another port +} LidCheck_t; +LidCheck_t sm_check_lid(const Port_t *pp, STL_LID lid, uint8_t lmc); + +/** + * @return number of LIDs newly-registered to @c portp + * or -1 on error. + */ +int sm_set_lid(Port_t * portp, STL_LID lid, uint8_t lmc); + +Status_t sm_update_or_assign_lid(Port_t *pp, boolean assignIfFail, int *newLidCount, Node_t *neighbor); + +void sm_setTrapThreshold(uint32_t, uint32_t); +void sm_removedEntities_init(void); +void sm_removedEntities_destroy(void); +Status_t sm_removedEntities_reportPort(Node_t *, Port_t *, RemovedEntityReason_t); +Status_t sm_removedEntities_clearNode(Node_t *); +Status_t sm_removedEntities_clearPort(Node_t *, Port_t *); +void sm_removedEntities_displayPorts(void); +void sm_elevatePriority(void); +void sm_restorePriority(void); +void sm_restorePriorityOnly(void); +void sm_compactSwitchSpace(Topology_t *, bitset_t *); +void sm_clearSwitchPortChange(Topology_t *topop); +void sm_log_topology(Topology_t *); +Status_t sm_activate_switch(Topology_t *, Node_t *); +int sm_select_port(Topology_t *, Node_t *, int, uint8_t *); +int sm_select_ports(Topology_t *, Node_t *, int, SwitchportToNextGuid_t *); +void sm_balance_ports(SwitchportToNextGuid_t *, int); +void smLogHelper(uint32_t, const char *, char *, int, uint64_t, char *, uint32_t); +Status_t sm_get_uninit_connected_switch_list(Topology_t *topop, Node_t *nodep, SwitchList_t **swlist_head); +void sm_delete_switch_list(SwitchList_t *sw); +uint8_t is_switch_on_list(SwitchList_t *swlist_head, Node_t *switchp); +Status_t sm_set_linkinit_reason(Node_t *nodep, Port_t *portp, uint8_t initReason); +Status_t sm_verifyPortSpeedAndWidth(Topology_t *topop, Node_t *nodep, Port_t *portp); +Status_t sm_enable_port_led(SmMaiHandle_t * fd, Node_t *nodep, Port_t *portp, boolean enabled); +void sm_mark_link_down(Topology_t *topop, Port_t *portp); +void sm_mark_switch_down(Topology_t *topop, Node_t *swnodep); +Status_t sm_mark_new_endnode(Node_t * nodep); + +// +// sm_routing.c prototypes +// + +int sm_get_route(Topology_t *, Node_t *, uint8_t, STL_LID, uint8_t*); +uint8_t sm_get_slsc(Topology_t *, Port_t*, uint8_t); +Status_t sm_routing_copy_cost_matrix(Topology_t *src_topop, Topology_t *dst_topop); +Status_t sm_routing_prep_new_switch(Topology_t *topop, Node_t *nodep, SmpAddr_t *addr); +Status_t sm_routing_route_switch_LR(Topology_t *topop, SwitchList_t *swlist, int rebalance); +Status_t sm_routing_route_new_switch_LR(Topology_t *topop, SwitchList_t *swlist, int rebalance); +Status_t sm_routing_route_old_switch(Topology_t *src_topop, Topology_t *dst_topop, Node_t *nodep); +int sm_balance_base_lids(SwitchportToNextGuid_t *ordered_ports, int olen); +Status_t sm_routing_init(void); + + +// +// sm_routing_funcs.c prototypes +// +extern Status_t sm_routing_func_pre_process_discovery_noop(Topology_t *topop, void **outContext); +extern Status_t sm_routing_func_discover_node_noop(Topology_t *topop, Node_t *nodep, void *context); +extern Status_t sm_routing_func_discover_node_port_noop(Topology_t *topop, Node_t *nodep, Port_t *portp, void *context); +extern Status_t sm_routing_func_post_process_discovery_noop(Topology_t *topop, Status_t discoveryStatus, void *context); +extern Status_t sm_routing_func_post_process_routing_noop(Topology_t *topop, Topology_t *old_topop, int *rebalance); +extern Status_t sm_routing_func_post_process_routing_copy_noop(Topology_t *src_topop, Topology_t *dst_topop, int *rebalance); +extern Status_t sm_routing_func_alloc_cost_matrix_floyds(Topology_t *topop); +extern Status_t sm_routing_func_init_cost_matrix_floyds(Topology_t *topop); +extern Status_t sm_routing_func_calc_cost_matrix_floyds(Topology_t * topop, int switches, unsigned short * cost, SmPathPortmask_t * path); +extern int sm_routing_func_routing_mode_noop(void); +extern int sm_routing_func_routing_mode_linear(void); +extern boolean sm_routing_func_false(void); +extern boolean sm_routing_func_true(void); +extern boolean sm_routing_func_false(void); +extern boolean sm_routing_func_true(void); +extern Status_t sm_routing_func_copy_routing_noop(Topology_t *src_topop, Topology_t *dst_topop); +extern Status_t sm_routing_func_copy_routing_lfts(Topology_t *src_topop, Topology_t *dst_topop); +extern Status_t sm_routing_func_init_switch_routing_lfts(Topology_t * topop, int * routing_needed, int * rebalance); +extern Status_t sm_routing_func_calculate_lft(Topology_t * topop, Node_t * switchp); +extern Status_t sm_routing_func_setup_xft(Topology_t *topop, Node_t *switchp, Node_t *nodep, Port_t *orig_portp, uint8_t *portnos); +extern int sm_routing_func_select_ports(Topology_t *topop, Node_t *switchp, int endIndex, SwitchportToNextGuid_t *ordered_ports, boolean selectBest); +extern Status_t sm_routing_func_setup_pgs(struct _Topology *topop, struct _Node * srcSw, struct _Node * dstSw); +extern int sm_routing_func_get_port_group(Topology_t *topop, Node_t *switchp, Node_t *nodep, uint8_t *portnos); +extern Status_t sm_routing_func_select_slsc_map(Topology_t *topop, Node_t *nodep, Port_t *in_portp, Port_t *out_portp, STL_SLSCMAP *outSlscMap); +extern Status_t sm_routing_func_select_scsl_map(Topology_t *topop, Node_t *nodep, Port_t *in_portp, Port_t *out_portp, STL_SCSLMAP *outScslMap); +extern Status_t sm_routing_func_select_scsc_map(Topology_t *topop, Node_t *switchp, int getSecondary, int *numBlocks, STL_SCSC_MULTISET** scscmap); +extern Status_t sm_routing_func_select_scvl_map_fixedmap(Topology_t *topop, Node_t *nodep, Port_t *in_portp, Port_t *out_portp, STL_SCVLMAP *outScvlMap); +extern Status_t sm_routing_func_select_vlvf_map(Topology_t *topop, Node_t *nodep, Port_t *portp, VlVfMap_t * vlvfmap); +extern Status_t sm_routing_func_select_vlbw_map(Topology_t *topop, Node_t *nodep, Port_t *portp, VlBwMap_t * vlvfmap); +extern Status_t sm_routing_func_select_scvlr_map(Topology_t *topop, uint8_t vlCap, STL_SCVLMAP *outScvlMap); +extern Status_t sm_routing_func_fill_stl_vlarb_table(Topology_t *topop, Node_t *nodep, Port_t *portp, PortDataVLArb* arbp); +extern Status_t sm_routing_func_select_path_lids(Topology_t *topop, Port_t *srcPortp, STL_LID slid, Port_t *dstPortp, STL_LID dlid, STL_LID *outSrcLids, uint8_t *outSrcLen, STL_LID *outDstLids, uint8_t *outDstLen); +extern Status_t sm_routing_func_select_updn_path_lids_noop(Topology_t *topop, Port_t *srcPortp, Port_t *dstPortp, STL_LID *outSrcLid, STL_LID *outDstLid); +extern Status_t sm_routing_func_process_swIdx_change_noop(Topology_t * topop, int old_idx, int new_idx, int last_idx); +extern int sm_routing_func_check_switch_path_change(Topology_t * oldtp, Topology_t * newtp, Node_t *switchp); +extern boolean sm_routing_func_needs_routing_recalc_false(Topology_t * topop, Node_t * nodep); +extern boolean sm_routing_func_needs_routing_recalc_true(Topology_t * topop, Node_t * nodep); +extern boolean sm_routing_func_needs_lft_recalc(Topology_t * topop, Node_t * nodep); +extern boolean sm_routing_func_do_spine_check(Topology_t * topop, Node_t * switchp); +extern Status_t sm_routing_func_write_minimal_lft_blocks(Topology_t * topop, Node_t * switchp, SmpAddr_t * addr); +extern Status_t sm_routing_func_write_full_lfts_LR(Topology_t * topop, SwitchList_t * swlist, int rebalance); +extern Status_t sm_routing_func_route_old_switch(Topology_t *src_topop, Topology_t *dst_topop, Node_t *nodep); +extern boolean sm_routing_func_handle_fabric_change(Topology_t *topop, Node_t *oldSwitchp, Node_t *switchp); +extern Status_t sm_routing_func_update_bw(RoutingModule_t *rm, VirtualFabrics_t *VirtualFabrics); +extern Status_t sm_routing_func_assign_scs_to_sls_fixedmap(RoutingModule_t *rm, VirtualFabrics_t *VirtualFabrics); +extern Status_t sm_routing_func_assign_scs_to_sls_nonfixedmap(RoutingModule_t *rm, VirtualFabrics_t *VirtualFabrics); +extern Status_t sm_routing_func_assign_sls(RoutingModule_t *rm, VirtualFabrics_t *VirtualFabrics); +extern int sm_routing_func_min_vls(void); +extern int sm_routing_func_max_vls(void); +extern int sm_routing_func_one_routing_scs(int sl, boolean mc_sl); +extern int sm_routing_func_no_oversubscribe(int sl, boolean mc_sl); +extern Status_t sm_routing_func_process_xml_config_noop(void); +// +// sm_shortestpath.c prototypes +// + +Status_t sm_shortestpath_init(void); + +// +// sm_fattree.c prototypes +// + +Status_t sm_fattree_init(void); + +// +// sm_dgmh.c prototypes +// + +Status_t sm_dgmh_init(void); + +// +// sm_hypercube.c prototypes +// + +Status_t sm_hypercube_init(void); + +// +// sm_dor.c prototypes +// +// +Status_t sm_dor_init(void); + + + +// +// sm_dispatch.c prototypes +// + +void sm_dispatch_destroy(sm_dispatch_t *disp); +Status_t sm_dispatch_new_req(sm_dispatch_t *, sm_dispatch_send_params_t *, Node_t *, sm_dispatch_req_t **); +Status_t sm_dispatch_enqueue(sm_dispatch_req_t *req); +Status_t sm_dispatch_init(sm_dispatch_t *disp, uint32_t reqsSupported); +Status_t sm_dispatch_wait(sm_dispatch_t *disp); +void sm_dispatch_clear(sm_dispatch_t *disp); +Status_t sm_dispatch_update(sm_dispatch_t *disp); +void sm_dispatch_bump_passcount(sm_dispatch_t *disp); + +// +// sm_partMgr.c prototypes +// + +int checkPKey(uint16_t); +int smCheckPortPKey(uint16_t, Port_t*); + +uint16_t smGetPortPkey(uint16_t, Port_t*); + +Status_t setPKey(uint32_t, uint16_t, int); +Status_t sm_set_portPkey(ParallelSweepContext_t *psc, SmMaiHandle_t *, Topology_t *, Node_t *, Port_t *, Node_t *, Port_t *, SmpAddr_t *, uint8_t*, uint16_t*); +Status_t sm_set_local_port_pkey(STL_NODE_INFO *nodeInfop); +Status_t sm_set_delayed_pkeys(void); + +uint16_t getDefaultPKey(void); +uint16_t getPKey(uint8_t); // getPKey is needed for esm (sm mib). + +uint16_t smGetRequestPkeyIndex(uint8_t, STL_LID); +uint16_t smGetCommonPKey(Port_t*, Port_t*); +int smValidatePortPKey(uint16_t, Port_t*); +int smValidatePortPKey2Way(uint16_t, Port_t*, Port_t*); + +void smGetVfMaxMtu(Port_t*, Port_t*, STL_MCMEMBER_RECORD*, uint8_t*, uint8_t*); + +// validate serviceId for VF. Also covers the unmatchedSid option +Status_t smVFValidateVfServiceId(int vf, uint64_t serviceId); +Status_t smVFValidateVfMGid(VirtualFabrics_t *VirtualFabrics, int vf, uint64_t mGid[2]); +Status_t smGetValidatedVFs(Port_t*, Port_t*, uint16_t, uint8_t, uint8_t, uint64_t, uint8_t, bitset_t*); +Status_t smVFValidateMcGrpCreateParams(Port_t * joiner, Port_t * requestor, + STL_MCMEMBER_RECORD * mcMemberRec, bitset_t * vfMembers); +void smVerifyMcastPkey(uint64_t*, uint16_t); +void smSetupNodeVFs(Node_t *nodep); +void smSetupNodeDGs(Node_t *nodep); +boolean smEvaluateNodeDG(Node_t* nodep, int dgIdxToEvaluate, PortRangeInfo_t* portInfo); +boolean smEvaluatePortDG(Node_t* nodep, Port_t* portp, int dgIdxToEvaluate, bitset_t* dgMemberForPort, bitset_t* dgsEvaluated); +void smLogVFs(void); +char* smGetVfName(uint16_t); + +// +// sm_ar.c prototypes +// Send PGT and PGFT to node if necessary. +// +Status_t sm_AdaptiveRoutingSwitchUpdate(ParallelSweepContext_t *, SmMaiHandle_t *, Topology_t*, Node_t*); +uint8_t sm_VerifyAdaptiveRoutingConfig(Node_t *p); + +// +// sm_multicast.c prototypes +// + +extern IB_GID nullGid; + +// +// mLid usage structure +// +typedef struct { + cl_map_item_t PKeyItem; + uint16_t PKey; + uint16_t PKeyCount; +} PKeyUsage_t; + +typedef struct { + STL_LID lid; + uint16_t usageCount; +} LidUsage_t; + + +typedef struct { + cl_map_item_t mapItem; // Map item for group class usageMap + uint32_t lidsUsed; // number of lids in the lid class + uint16_t pKey; // pkey for this lid class + uint16_t mtu; // mtu for this lid class + uint16_t rate; // rate for this lid class + // array of Lids & their usage counts in this lid class + LidUsage_t * lids; +} LidClass_t; + +typedef struct { + // Maximum number of mLids that this group class + // can use before the SM starts reusing mLids for + // multiple MC groups. A value of zero effectively + // disables mLid agragation. + uint32_t maximumLids; + + // Number of mLids currently in use by the group class + uint32_t currentLids; + // Number of mlids that can be shared within the same PKey + uint32_t maximumLidsperPkey; + + // Mask and value for MGid's belonging to this group class + IB_GID mask; + IB_GID value; + + // QMap of LidClass_t structure, indexed by {pkey, mtu, rate} + cl_qmap_t usageMap; + // QMap of PKeyUsage_t structure, indexed by {pkey} + cl_qmap_t PKeyUsageMap; +} McGroupClass_t; + +typedef struct { + ParallelSweepContext_t *psc; +} SweepContext_t; + +/** + Allocate a @c CableInfo_t on the heap and initialize the reference count to 1. +*/ +CableInfo_t * sm_CableInfo_init(void); + +/** + @return A pointer to the same data as @c ci (may even be @c ci) or NULL if the data could not be copied (reference count exhausted). +*/ +CableInfo_t * sm_CableInfo_copy(CableInfo_t * ci); + +/** + Decrement ci->refcount by one and free @c ci and its members + if ci->refcount == 0. + + @param ci Created with @c sm_CableInfo_init() + + @return @c ci or NULL if @c ci was freed because reference count hit 0. +*/ +CableInfo_t * sm_CableInfo_free(CableInfo_t * ci); + +/** + Does @c port support Get(CableInfo)? + + @c port must not be port 0, be a QSFP connector, and @c port->portData must be allocated. + + Does not check whether port state is high enough for an SMA Get() to succeed. +*/ +boolean sm_Port_t_IsCableInfoSupported(Port_t * port); + +/** + Mark @c port as supporting or not supporting Get(CableInfo). + + Implementation uses a special address that does not point to a valid CableInfo_t (or possibly valid memory). Use @c sm_Port_t_IsCableInfoSupported() to check if the port may have valid cable data before assuming a non-NULL port->portData->cableInfo pointer means that the data is valid. + + Frees non-null CableInfo associated with @c port when going from supported -> !supported. +*/ +void sm_Port_t_SetCableInfoSupported(Port_t * port, boolean supported); + +// If new_pg is not found in pgp, adds it to pgp, updates length, and set +// index to the index of the new port group and returns 1. +// If it *is* already found in pgp, index points to the existing group and +// returns 0. If new_pg cannot be added (because length == cap), returns -1. +int sm_Push_Port_Group(STL_PORTMASK pgp[], STL_PORTMASK new_pg, + uint8_t *index, uint8_t *length, uint8_t cap); + +// Takes a set of ports and builds an STL Port Mask from them. +STL_PORTMASK sm_Build_Port_Group(SwitchportToNextGuid_t *ordered_ports, + int olen); + +// Methods used for device group membership evaluation +int smGetDgIdx(DGXmlConfig_t *dg_config, char* dgName); +boolean isDgMember(int dgIdx, PortData_t* portDataPtr); +boolean convertWildcardedString(char* inStr, char* outStr, RegexBracketParseInfo_t* regexInfo); +boolean isCharValid(char inChar); +boolean processBracketSyntax(char* inputStr, int inputLen, int* curIdxPtr, RegexBracketParseInfo_t* regexInfo, boolean isPortRange); +boolean isNumberInRange(char* number, RegexBracketParseInfo_t* regexInfo, int bracketIdx); +void initializeRegexStruct(RegExp_t* regExprPtr); +void printRegexStruct(RegexBracketParseInfo_t* regexInfo); + + +Status_t sm_ideal_spanning_tree(McSpanningTree_t *mcST, int filter_mtu_rate, int32_t mtu, int32_t rate, int num_nodes, int *complete); +Status_t sm_spanning_tree(int32_t, int32_t, int *); +void sm_build_spanning_trees(void); +void sm_spanning_tree_resetGlobals(void); +Status_t sm_multicast_add_group_class(IB_GID mask, IB_GID value, STL_LID maxLidsi, uint32_t maxLidsPkey); +Status_t sm_multicast_set_default_group_class(STL_LID maxLids, uint32_t maxLidsPKey); +Status_t sm_multicast_sync_lid(IB_GID mGid, PKey_t pKey, uint8_t mtu, uint8_t rate, STL_LID lid); +Status_t sm_multicast_check_sync_consistancy(McGroupClass_t * groupClass, PKey_t pKey, + uint8_t mtu, uint8_t rate, STL_LID lid); +STL_LID sm_multicast_get_max_lid(void); +void sm_multicast_mark_lid_in_use(STL_LID mlid); +Status_t sm_multicast_gid_check(IB_GID); +Status_t sm_multicast_gid_assign(uint32_t, IB_GID); +Status_t sm_multicast_gid_valid(uint8_t, IB_GID); +Status_t sm_calculate_mfts(void); +Status_t sm_set_all_mft(int force, Topology_t *curr_tp, Topology_t *prev_tp); +Status_t sm_multicast_switch_mft_copy(void); +McGroup_t *sm_find_multicast_gid(IB_GID); +Status_t sm_multicast_assign_lid(IB_GID mGid, PKey_t pKey, uint8_t mtu, uint8_t rate, STL_LID requestedLid, STL_LID * lid); +Status_t sm_multicast_decommision_group(McGroup_t * group); +McGroup_t *sm_find_next_multicast_gid(IB_GID); +McMember_t *sm_find_multicast_member(McGroup_t *, IB_GID); +McMember_t *sm_find_multicast_member_by_index(McGroup_t *mcGroup, uint32_t index); +McMember_t *sm_find_next_multicast_member_by_index(McGroup_t *mcGroup, uint32_t index); +void sm_multicast_init_mlid_list(void); +void sm_multicast_destroy_mlid_list(void); + +void topology_main(uint32_t, uint8_t **); +Status_t sweep_userexit(SweepContext_t *); +Status_t forwarding_userexit(uint16_t *, int16_t *); +Status_t authorization_userexit(void); +Status_t license_userexit(void); +Status_t loopTest_userexit_findPaths(Topology_t *); +void loopTest_userexit_updateLft(Topology_t *, Node_t *); +void printDgVfMemberships(void); + +// +// Startup and shutdown control values. +// +#define SM_CONTROL_SHUTDOWN 0x01 +#define SM_CONTROL_STANDBY 0x02 +#define SM_CONTROL_RESTART 0x03 +#define SM_CONTROL_HEARTBEAT 0x04 +#define SM_CONTROL_REGISTER 0x05 +#define SM_CONTROL_RECONFIG 0x06 + +Status_t sm_control(Mai_t *); +Status_t sm_control_shutdown(Mai_t *); +Status_t sm_control_standby(Mai_t *); +Status_t sm_control_restart(Mai_t *); +Status_t sm_control_heartbeat(Mai_t *); +Status_t sm_control_register(Mai_t *); +Status_t sm_control_reconfig(void); +Status_t sm_control_init(void); +Status_t sm_control_notify(void); + +#ifdef __VXWORKS__ +void idbSetSmState(ulong_t newState); +uint32_t idbGetSmSweepRate(); +uint32_t idbGetSmPriority(); +uint32_t idbSetSmPriority(uint32_t newPriority); +uint32_t idbSetSmElevatedPriority(uint32_t value); +uint32_t idbGetSmElevatedPriority(); +uint64_t idbGetSmKey(); +uint32_t idbSetSmKey(uint64_t newSmkey); +uint64_t idbGetSmMKey(); +uint32_t idbSetSmMKey(uint64_t newSmkey); +uint8_t idbGetSmSwitchLifetime(); +uint32_t idbSetSmSwitchLifetime(uint8_t newSwitchLifetime); +uint8_t idbGetSmHoqLife(); +uint32_t idbSetSmHoqLife(uint8_t newHoqLife); +uint8_t idbGetSmVLStall(); +uint32_t idbSetSmVLStall(uint8_t newVLStall); +uint32_t idbGetSmSubnetSize(); +uint32_t idbSetSmSubnetSize(uint32_t newSubnetSize); +uint32_t idbGetSmLMC(); +uint32_t idbSetSmLMC(uint32_t newLMC); +uint32_t idbSetSmLidOffset(uint32_t offset); +uint32_t idbGetSmLidOffset(); +uint32_t idbSetSmTopoErrorThreshold(uint32_t value); +uint32_t idbGetSmTopoErrorThreshold(); +uint32_t idbSetSmTopoAbandonThreshold(uint32_t value); +uint32_t idbGetSmTopoAbandonThreshold(); +uint32_t idbSetSmMaxRetries(uint32_t value); +uint32_t idbGetSmMaxRetries(); +uint32_t idbSetSmRcvWaitTime(uint32_t value); +uint32_t idbGetSmRcvWaitTime(); +uint32_t idbSetSmNonrespDropTime(uint32_t value); +uint32_t idbGetSmNonrespDropTime(); +uint32_t idbSetSmNonrespDropSweeps(uint32_t value); +uint32_t idbGetSmNonrespDropSweeps(); +uint32_t idbSetSmLogLevel(uint32_t value); +uint32_t idbGetSmLogLevel(); +uint32_t idbSetSmLogFilter(uint32_t value); +uint32_t idbGetSmLogFilter(); +uint32_t idbSetSmLogMask(uint32_t value); +uint32_t idbGetSmLogMask(); +uint32_t idbSetSmMcLidTableCap(uint32_t value); +uint32_t idbGetSmMcLidTableCap(); +uint32_t idbSetSmDefMcGrpPKey(uint32_t value); +uint32_t idbGetSmDefMcGrpPKey(); +uint32_t idbSetSmDefMcGrpQKey(uint32_t value); +uint32_t idbGetSmDefMcGrpQKey(); +uint32_t idbSetSmDefMcGrpMtu(uint32_t value); +uint32_t idbGetSmDefMcGrpMtu(); +uint32_t idbSetSmDefMcGrpRate(uint32_t value); +uint32_t idbGetSmDefMcGrpRate(); +uint32_t idbSetSmDefMcGrpSl(uint32_t value); +uint32_t idbGetSmDefMcGrpSl(); +uint32_t idbSetSmDefMcGrpFlowLabel(uint32_t value); +uint32_t idbGetSmDefMcGrpFlowLabel(); +uint32_t idbSetSmDefMcGrpTClass(uint32_t value); +uint32_t idbGetSmDefMcGrpTClass(); +uint32_t idbSetSmLoopTestPackets(uint32_t value); +uint32_t idbGetSmLoopTestPackets(); +uint32_t idbSetSmMasterPingInterval(uint32_t value); +uint32_t idbGetSmMasterPingInterval(); +uint32_t idbSetSmMaxMasterPingFailures(uint32_t value); +uint32_t idbGetSmMaxMasterPingFailures(); +uint32_t idbSetSmDbSyncInterval(uint32_t value); +uint32_t idbGetSmDbSyncInterval(); +uint32_t idbSetSmStartAtBootSelector(uint32_t value); +uint32_t idbGetSmStartAtBootSelector(); +uint32_t idbGetSmDbSyncInterval(); +uint32_t idbSetSmDbSyncInterval(uint32_t); +uint64_t idbGetGidPrefix(); +uint32_t idbSetGidPrefix(uint64_t prefix); +uint32_t idbGetRmppAlt(); +uint32_t idbGetLegacyHwSupport(); +uint32_t idbGetFullPkeySupport(); +uint32_t idbGetVlArbSupport(); +uint32_t idbGetEnhPortZeroSupport(); +uint32_t idbGetMcGrpCreate(); +uint32_t idbGetDynamicPltSupport(); +uint32_t idbGetSmPltValue(uint32_t index); +uint32_t idbGetSmPerfDebug(); +uint32_t idbGetSaPerfDebug(); +uint32_t idbGetRmppDebug(); +uint32_t idbGetRmppChksumDebug(); +uint32_t idbGetTopologyDebug(); +uint32_t idbGetLooptest(); +uint32_t idbSetSmTrapThreshold(uint32_t value); +uint32_t idbGetSmTrapThreshold(); +uint32_t idbSetSmAppearanceMsgThresh(uint32_t value); +uint32_t idbGetSmAppearanceMsgThresh(); +uint32_t idbGetDisableCommonMcastMtuAndRate(void); +#else +Status_t sm_dump_state(const char * dumpDir); +#endif + + +/** + Common switch LFT allocation code; frees LFT if already allocated. + Uses switchp->..LinearFDBTop for size. Rounds up to the next MAX_LFT_ELEMENTS_BLOCK entries. Sets all entries to 0xFF. + + @param outSize [optional, output only] Amount of memory that was allocated. + @return VSTATUS_OK on successful allocation, or the status that vs_pool_alloc() returned on error. +*/ +Status_t sm_Node_init_lft(Node_t * switchp, size_t * outSize); + +void sm_node_release_changes(Node_t * nodep); + +Status_t sm_port_init_changes(Port_t * portp); +void sm_port_release_changes(Port_t * portp); + +///@return number of remaining references to the PGFT +uint32 sm_Node_release_pgft(Node_t * node); + +/** + Get the PGFT for @c node; should be preferred to direct access since it allows for deferred allocation meaning the memory isn't allocated until it's needed. + + Memsets memory to 0 first time it needs to be allocated. Does not allocate memory if capability mask for @c node indicates adaptive routing is not supported on it. +*/ +const PORT * sm_Node_get_pgft(const Node_t * node); + +/** + Get PGFT for writing, create if it does not exist already. +*/ +PORT * sm_Node_get_pgft_wr(Node_t * node); +/** + Copy PGFT from @c src to @c dest. Allocate if @c src does not already have a PGFT, free existing memory otherwise. + + @return PGFT of @c dest +*/ +PORT * sm_Node_copy_pgft(Node_t * dest, const Node_t * src); + +/// @return amount of memory allocated in bytes or 0 if not allocated +size_t sm_Node_get_pgft_size(const Node_t * node); + +/// @return Amount of memory that should be allocated for PGFT on @c node +size_t sm_Node_compute_pgft_size(const Node_t * node); + +/** + Invalidate (reset to PODs) the PGT and PGFT mappings on @c node. Modifies the + state of PGT and PGFT on @c node but does not generate or send the MADs necessary + to change these on the SMA. +*/ +void sm_Node_invalidate_pgs(Node_t * node); + +Status_t sm_Node_prune_portgroups(Node_t * newSw); + +void sm_set_log_level(uint32_t log_level); +void sm_set_log_mode(uint32_t log_mode); +void sm_set_log_mask(const char* mod, uint32_t mask); +void sm_init_log_setting(void); + +uint32_t sm_getSweepRate(void); +void sm_setSweepRate(uint32_t rate); +void sm_forceSweep(const char* reason); +uint32_t sm_util_isTopologyValid(void); +uint32_t sm_util_get_state(void); +uint32_t sm_util_get_passcount(void); +uint32_t sm_get_smPerfDebug(void); +uint32_t sa_get_saPerfDebug(void); +void smPerfDebugToggle(void); +void saPerfDebugToggle(void); +void saRmppDebugToggle(void); +void smForceRebalanceToggle(void); +void sm_get_smAdaptiveRouting(fm_ar_config_t *); +void smAdaptiveRoutingUpdate(uint32_t, fm_ar_config_t); +void smPauseResumeSweeps(boolean); +void smProcessReconfigureRequest(void); +PortData_t *sm_alloc_port(Topology_t *topop, Node_t *nodep, uint32_t portIndex); +void sm_free_port(Topology_t *topop, Port_t * portp); +void sm_node_free_port(Topology_t *topop, Node_t *nodep); +Status_t sm_build_node_array(Topology_t *topop); +Status_t sm_clearIsSM(void); +extern uint8_t sm_isActive(void); +extern uint8_t sm_isDeactivated(void); +extern uint8_t sm_isMaster(void); +#ifdef __LINUX__ +extern void sm_wait_ready(uint32_t modid); +extern uint8_t sm_isValidCoreDumpConfigSettings(uint32_t modid, const char *limit, const char *dir); +extern uint8_t sm_isValidLogConfigSettings(uint32_t modid, uint32_t logLevel, uint32_t logMode, uint32_t log_masks[VIEO_LAST_MOD_ID+1], char *logFile, char *syslogFacility); +extern void sm_getLogConfigSettings(uint32_t *logLevel, uint32_t *logMode, uint32_t log_masks[VIEO_LAST_MOD_ID+1], char *logFile, char *syslogFacility); +#endif +extern uint8_t sm_isValidDeviceConfigSettings(uint32_t modid, uint32_t device, uint32_t port, uint64_t portGuid); +extern void sm_getDeviceConfigSettings(uint32_t *device, uint32_t *port, uint64_t *portGuid); +extern uint8_t sm_isValidMasterConfigSettings(uint32_t modid, int priority, int elevated_priority); +extern void sm_getMasterConfigSettings(uint32_t *priority, uint32_t *elevated_priority); +extern uint8_t sm_isValidSubnetSizeConfigSetting(uint32_t modid, uint32_t subnet_size); +extern void sm_getSubnetSizeConfigSetting(uint32_t *subnet_size); +extern int smValidateGsiMadPKey(Mai_t *maip, uint8_t mgmntAllowedRequired, uint8_t antiSpoof); + +extern void sm_copyPortDataSCSCMap(Port_t *sportp, Port_t *dportp, int extended); +extern void sm_addPortDataSCSCMap(Port_t *portp, uint8_t outport, int extended, const STL_SCSCMAP *pSCSC); +extern STL_SCSCMAP * sm_lookupPortDataSCSCMap(Port_t *portp, uint8_t outport, int extended); + +extern Status_t sm_get_buffer_control_tables(SmMaiHandle_t * fd_topology, Node_t *nodep, uint8_t start_port, uint8_t end_port); + +extern void sm_set_force_attribute_rewrite(uint32_t force_attr_rewrite); +extern void sm_set_skip_attribute_write(uint32_t skip_attr_write); + +/** + Compare XmitQ values for VLs [0, @c actVlCount) and VL15. +*/ +boolean sm_eq_XmitQ(const struct XmitQ_s * a, const struct XmitQ_s * b, uint8 actVlCount); + +int sm_evalPreemptLargePkt(int cfgLarge, Node_t * nodep); +int sm_evalPreemptSmallPkt(int cfgSmall, Node_t * nodep); +int sm_evalPreemptLimit(int cfgLimit, Node_t * nodep); + +/** + Alloc portp->portData->newArb on demand and return pointer or null if !sm_port_valid(portp) +*/ +struct _PortDataVLArb * sm_port_getNewArb(Port_t * portp); + +/** + Release portp->portData->newArb if allocated. +*/ +void sm_port_releaseNewArb(Port_t * portp); + +// +// persistent topology api +// + +extern void sm_popo_init(Popo_t * popop); +extern void sm_popo_destroy(Popo_t * popop); +extern void sm_popo_report(Popo_t * popop); +extern PopoNode_t * sm_popo_get_node(Popo_t * popop, const STL_NODE_INFO * nodeInfo); +extern PopoPort_t * sm_popo_get_port(Popo_t * popop, PopoNode_t * ponodep, uint8_t port); + +extern boolean sm_popo_is_port_quarantined(Popo_t * popop, Port_t * portp); +extern boolean sm_popo_is_port_monitored(Popo_t * popop, Port_t * portp); +extern boolean sm_popo_is_port_quarantined_unsafe(Popo_t * popop, Port_t * portp); +extern boolean sm_popo_is_port_monitored_unsafe(Popo_t * popop, Port_t * portp); +extern boolean sm_popo_is_node_quarantined(Popo_t * popop, uint64_t guid); +extern boolean sm_popo_clear_short_quarantine(Popo_t * popop); + +extern PopoQuarantineType_t sm_popo_get_quarantine_type(Popo_t * popop, Port_t * portp); +extern PopoLongTermQuarantineReason_t sm_popo_get_quarantine_reason(Popo_t * popop, Port_t * portp); +extern PopoQuarantineType_t sm_popo_get_quarantine_type_unsafe(Popo_t * popop, Port_t * portp); +extern PopoLongTermQuarantineReason_t sm_popo_get_quarantine_reason_unsafe(Popo_t * popop, Port_t * portp); +extern void sm_popo_get_ldr_log(Popo_t * popop, Port_t * portp, STL_LINKDOWN_REASON *log); +extern uint64_t sm_popo_get_sweep_start(Popo_t * popop); + +extern boolean sm_popo_find_lastest_ldr(Popo_t * popop, Port_t * portp, STL_LINKDOWN_REASON *ldr); + +extern void sm_popo_clear_cache_nonresp(Popo_t *popop, Node_t *nodep); +extern boolean sm_popo_is_nonresp_this_sweep(Popo_t *popop, Node_t *nodep); +extern boolean sm_popo_use_cache_nonresp(Popo_t * popop, Node_t *nodep); +extern boolean sm_popo_inc_and_use_cache_nonresp(Popo_t * popop, Node_t *nodep, Status_t *retStatus); + +extern uint64_t sm_popo_scale_timeout(Popo_t * popop, uint64_t timeout); +extern void sm_popo_report_timeout(Popo_t * popop, uint64_t timeout); +extern Status_t sm_popo_port_error(Popo_t * popop, Topology_t * topop, Port_t * portp, Status_t status); +extern void sm_popo_reset_errors(Popo_t * popop); +extern boolean sm_popo_should_abandon(Popo_t * popop); +extern void sm_popo_report_trap(Popo_t * popop); +extern void sm_popo_update_node(PopoNode_t * ponodep); +extern void sm_popo_end_sweep(Popo_t * popop); +extern void sm_popo_begin_sweep(Popo_t *popop, uint64_t start_sweep); + +extern void sm_popo_monitor_port(Popo_t *popop, Port_t *portp, PopoLongTermQuarantineReason_t reason); +extern void sm_popo_update_node_port_states(Popo_t *popop, Node_t * nodep, STL_PORT_STATE_INFO *psi); +extern void sm_popo_update_port_state(Popo_t *popop, Port_t *portp, STL_PORT_STATES *pstatep); +extern void sm_popo_update_port_state_with_ldr(Popo_t *popop, Port_t *portp, STL_PORT_STATES *pstatep, + uint8_t ldr, uint8_t nldr); +extern void sm_popo_clear_port_trappedDown(Popo_t * popop); + +/** + * popo locks should not be taken for calling the above popo APIs unless + * needLock is set to FALSE in API call. popo locks are publicly available + * for popo extensions that directly modify popo protected state + */ +extern void sm_popo_lock(Popo_t * popop); +extern void sm_popo_unlock(Popo_t * popop); + + +//port Flapping API +extern boolean sm_flap_report_port_change_trap(Popo_t *popop, Node_t *nodep); +extern void sm_flap_state_handler(Popo_t *popop, PopoPort_t *poportp); +extern void sm_flap_gc(PopoPort_t *poportp); + + +static inline +Node_t * Node_Create(Topology_t *topop, const STL_NODE_INFO *nodeInfo, + uint8 nodeType, uint8 portCount, const STL_NODE_DESCRIPTION *nodeDesc, boolean authentic) +{ + int local_i; + size_t local_size; + Status_t local_status; + //char nodeDescStr[STL_NODE_DESCRIPTION_ARRAY_SIZE+1]; + char nodeDescStr[ND_LEN+1]; + Node_t *nodep = NULL; + + local_size = sizeof(Node_t) + (portCount * sizeof(Port_t)) + 16; + local_status = vs_pool_alloc(&sm_pool, local_size, (void *)&nodep); + if (local_status == VSTATUS_OK) { + memset((void *)nodep, 0, local_size); + nodep->nodeInfo = *nodeInfo; + nodep->nodeDesc = *nodeDesc; + memcpy(nodeDescStr, nodeDesc->NodeString, ND_LEN); + if (strlen(nodeDescStr) == ND_LEN) { + local_status = vs_pool_alloc(&sm_pool, ND_LEN+1, (void *)&nodep->nodeDescString); + if (local_status != VSTATUS_OK) { + IB_FATAL_ERROR_NODUMP("Can't allocate space for node's description"); + } + memcpy((void *)nodep->nodeDescString, nodeDescStr, ND_LEN+1); + } + if (authentic) { + if (nodeType == NI_TYPE_CA) { + Node_Enqueue_Type(topop, nodep, ca_head, ca_tail); + } else if (nodeType == NI_TYPE_SWITCH) { + if (sm_mcast_mlid_table_cap) { + local_status = vs_pool_alloc(&sm_pool, sizeof(STL_PORTMASK*) * sm_mcast_mlid_table_cap, (void*)&nodep->mft); + if (local_status == VSTATUS_OK) { + local_status = vs_pool_alloc(&sm_pool, sizeof(STL_PORTMASK) * sm_mcast_mlid_table_cap * STL_MFTABLE_POSITION_COUNT, (void*)&nodep->mft[0]); + if (local_status == VSTATUS_OK) { + memset((void *)nodep->mft[0], 0, (sizeof(STL_PORTMASK) * sm_mcast_mlid_table_cap * STL_MFTABLE_POSITION_COUNT)); + for (local_i = 1; local_i < sm_mcast_mlid_table_cap; ++local_i) { + nodep->mft[local_i] = nodep->mft[local_i - 1] + STL_MFTABLE_POSITION_COUNT; + } + Node_Enqueue_Type(topop, nodep, switch_head, switch_tail); + } else { + IB_FATAL_ERROR_NODUMP("Can't allocate space for node's mft"); + } + } else { + IB_FATAL_ERROR_NODUMP("Can't allocate space for node's mft pointers"); + } + } else { + Node_Enqueue_Type(topop, nodep, switch_head, switch_tail); + } + } + if (!bitset_init(&sm_pool, &nodep->activePorts, portCount) || + !bitset_init(&sm_pool, &nodep->initPorts, portCount) || + + !bitset_init(&sm_pool, &nodep->vfMember, MAX_VFABRICS) || + !bitset_init(&sm_pool, &nodep->fullPKeyMember, MAX_VFABRICS) || + !bitset_init(&sm_pool, &nodep->dgMembership, MAX_VFABRIC_GROUPS)) { + IB_FATAL_ERROR_NODUMP("Can't allocate space for node's activePorts"); + } + if (local_status == VSTATUS_OK) { + + Node_Enqueue(topop, nodep, node_head, node_tail); + + } + } + if (local_status == VSTATUS_OK) { + nodep->port = (Port_t *)(nodep+1); + nodep->uniformVL = 1; + nodep->ponodep = sm_popo_get_node(&sm_popo, nodeInfo); + for (local_i = 0; local_i < (int)(portCount); local_i++) { + (nodep->port)[local_i].state = IB_PORT_NOP; + (nodep->port)[local_i].path[0] = 0xff; + (nodep->port)[local_i].index = local_i; + (nodep->port)[local_i].nodeno = -1; + (nodep->port)[local_i].portno = -1; + (nodep->port)[local_i].poportp = sm_popo_get_port(&sm_popo, nodep->ponodep, local_i); + if (sm_dynamic_port_alloc() && !(topop->num_nodes == 0 && local_i == sm_config.port)) { + (nodep->port)[local_i].portData = NULL; + continue; + } + + if (((nodep->port)[local_i].portData = sm_alloc_port(topop, nodep, local_i)) == NULL) { + if (topop->num_nodes == 0 && local_i == sm_config.port) { + IB_FATAL_ERROR_NODUMP("Can't allocate SM port for the node"); + } else { + IB_FATAL_ERROR_NODUMP("Can't allocate port for the node"); + } + } + } + (nodep->port)[0].nodeno = topop->num_nodes; + (nodep->port)[0].portno = 0; + } + } else { + IB_FATAL_ERROR_NODUMP("can't allocate space"); + } + + return nodep; +} + +static inline +void Node_Delete(Topology_t *topop, Node_t *nodep) +{ + // TODO should not FATAL_ERROR when freeing unless it's a truly + // unrecoverable-from problem. Consider that passing a NULL pointer + // into vs_pool_free() will return VSTATUS_ILLPARM + Status_t local_status; + + if (nodep->mft) { + local_status = vs_pool_free(&sm_pool, nodep->mft[0]); + if (local_status != VSTATUS_OK) { + IB_FATAL_ERROR("Failed to free node's mft"); + } + local_status = vs_pool_free(&sm_pool, nodep->mft); + if (local_status != VSTATUS_OK) { + IB_FATAL_ERROR("Failed to free node's mft pointers"); + } + } + if (nodep->lft) { + local_status = vs_pool_free(&sm_pool, nodep->lft); + if (local_status != VSTATUS_OK) { + IB_FATAL_ERROR("Failed to free node's lft"); + } + } + if (nodep->pgt) { + vs_pool_free(&sm_pool, nodep->pgt); + } + if (nodep->pgft) { + sm_Node_release_pgft(nodep); + } + if (nodep->routingData) { + topop->routingModule->funcs.delete_node(nodep); + } + if (nodep->nodeDescString) { + vs_pool_free(&sm_pool, nodep->nodeDescString); + } + if (nodep->portStateInfo) { + vs_pool_free(&sm_pool, nodep->portStateInfo); + } + bitset_free(&nodep->activePorts); + bitset_free(&nodep->initPorts); + + bitset_free(&nodep->vfMember); + bitset_free(&nodep->fullPKeyMember); + bitset_free(&nodep->dgMembership); + sm_node_free_port(topop, nodep); + sm_node_release_changes((nodep)); + local_status = vs_pool_free(&sm_pool, (void *)nodep); + if (local_status != VSTATUS_OK) { + IB_FATAL_ERROR("can't free space"); + } +} + +static inline +void Node_Quarantined_Delete(Topology_t *topop, QuarantinedNode_t *nodep) +{ + if (nodep->quarantinedNode) { + Node_Delete(topop, nodep->quarantinedNode); + } + + if (vs_pool_free(&sm_pool, nodep)) + IB_FATAL_ERROR("can't free space"); +} + +#endif // _SM_L_H_ diff --git a/Esm/ib/src/smi/include/sm_lid_assignment.h b/Esm/ib/src/smi/include/sm_lid_assignment.h new file mode 100644 index 0000000..ec278cc --- /dev/null +++ b/Esm/ib/src/smi/include/sm_lid_assignment.h @@ -0,0 +1,33 @@ +/* BEGIN_ICS_COPYRIGHT2 **************************************** + +Copyright (c) 2018, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT2 ****************************************/ + +#ifndef _SM_LID_ASSIGNMENT_H_ +#define _SM_LID_ASSIGNMENT_H_ +Status_t parallel_endnode_lid_assignments(SweepContext_t *); +#endif diff --git a/Esm/ib/src/smi/include/sm_maihandle.h b/Esm/ib/src/smi/include/sm_maihandle.h new file mode 100644 index 0000000..9272620 --- /dev/null +++ b/Esm/ib/src/smi/include/sm_maihandle.h @@ -0,0 +1,40 @@ +/* BEGIN_ICS_COPYRIGHT7 **************************************** + +Copyright (c) 2018, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT7 ****************************************/ + +#include "ib_status.h" + +typedef struct { + IBhandle_t fdMai; + boolean enforceTimeoutLimit; + +} SmMaiHandle_t; + + +Status_t sm_mai_handle_open(uint32_t qp, uint32_t dev, uint32_t port, boolean enforceTimeoutLimit, SmMaiHandle_t **fd); +Status_t sm_mai_handle_close(SmMaiHandle_t **fd); diff --git a/Esm/ib/src/smi/include/sm_mf.h b/Esm/ib/src/smi/include/sm_mf.h new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/Esm/ib/src/smi/include/sm_mf.h diff --git a/Esm/ib/src/smi/include/sm_parallelsweep.h b/Esm/ib/src/smi/include/sm_parallelsweep.h new file mode 100644 index 0000000..4086293 --- /dev/null +++ b/Esm/ib/src/smi/include/sm_parallelsweep.h @@ -0,0 +1,202 @@ +/* BEGIN_ICS_COPYRIGHT2 **************************************** + +Copyright (c) 2018, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT2 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +//===========================================================================// +// FILE NAME +// sm_parallelsweep.h +// +// DESCRIPTION +// Data structures and functions needed to add support for multi-threading +// to the FM sweep. +// +// NOTES ON THE LOCKING MODEL USED IN SM PARALLEL SWEEP (AKA "PSC"): +// +// PSC uses two mutexes to serialize access to data. The critical_mutex +// and the topology_mutex. In addition, it uses the LOCKED_QUICK_LIST to +// serialize access to the mai_pool. +// +// The critical_mutex is used to serialize access to the internals of the +// PSC context and data, such as the counters and the work queue (we +// can't use a LOCKED_QUICK_LIST for the work queue because we need to +// "peek" at items without removing them). +// +// The topology_mutex is used to enforce serial access to global FM data +// structures - notably the old and new topologies. +// +// CORRECT USE OF THE SM PARALLEL SWEEP API: +// +// 1. Don't directly access work items without removing them from the queue +// first. The moment an item is posted to the queue, other threads may +// begin operating on it, possibly even freeing it. It's not a pretty look, +// don't do it! +// +// 2. The FM was not designed for multi-threaded operation. At all. +// Therefore, the basic model of parallelism is for a PSC worker to grab +// the topology mutex (psc_lock()) the moment it begins operating, only +// releasing that mutex at the moment the worker sends a MAD, and +// re-acquiring the mutex the moment the send completes. You can consider +// releasing the mutex in other contexts IFF you are very, very sure that +// nothing in the code being executed will alter global data and that no +// other active workers will do so either. (For example, if the activate +// port code only reads the topology, and doesn't write to it, we could +// dispense with calling psc_unlock() and psc_lock(). +// +//===========================================================================// + +#if !defined(_SM_PARALLELSWEEP_H_) +#define _SM_PARALLELSWEEP_H_ + +#if !defined(__VXWORKS__) +#define ENABLE_MULTITHREADED +#endif + +#include "ilist.h" +#include "iquickmap.h" +#ifdef ENABLE_MULTITHREADED +#include "imutex.h" +#include "ithreadpool.h" +#endif + +// A single IB file descriptor, allocated by the MAI layer. +typedef struct { + LIST_ITEM item; // Used to list the item in the mai_pool. + SmMaiHandle_t *fd; // An open, ready-to-use IB file descriptor. +} MaiPool_t; + +// Global data for the work pool threads +typedef struct { + QUICK_LIST work_queue; // List of items waiting to be worked. +#ifdef ENABLE_MULTITHREADED + LOCKED_QUICK_LIST mai_pool; // List of available MAI handles. + THREAD_POOL worker_pool; // OS-abstract set of threads. + unsigned num_threads; // The # of threads allocated to the pool. + unsigned active_threads; // The # of threads currently processing + // work items. + + EVENT wait_event; // Triggered when callbacks complete. + MUTEX critical_mutex; // Used to serialize access to context data + // so that API functions will see a + // consistent view of the context. + + MUTEX topology_mutex; // Used to serialize access to the global + // topology structure. + // TODO: Should topology_mutex be global? +#else + MaiPool_t *mai_fd; // Replaces MAI pool when single threaded. +#endif + + Status_t status; // Used by users to track error status. + // Not used by sm_parallelsweep itself. + boolean running; // Set to true when the workers should be + // removing items from the work queue. +} ParallelSweepContext_t; + +// Prototype for work-item specific worker functions. +// +// The worker threads themselves are generic to all parts of the sweep and are +// only responsible for initially acquiring the work item and the +// topology_mutex and then pass control to the PsWorker_t function contained +// with the work item itself. The arguments are a pointer to the (shared) +// ParallelSweepContext_t and a pointer to the work item to be processed. +struct ParallelWorkItem_s; +typedef void (*PsWorker_t)(ParallelSweepContext_t* context, + struct ParallelWorkItem_s* item); + +// A single work item. API users might wrap this with an outer structure +// to pass additional data to the worker function. +typedef struct ParallelWorkItem_s { + LIST_ITEM item; // Used to list the item in the work_queue. + boolean blocking; // Work item acts as a barrier operation. + PsWorker_t workfunc; // Function to operate on this item. +} ParallelWorkItem_t; + +// Acquire or release the PSC mutex. The model should be that a worker +// acquires the mutex and holds it unless it is absolutely sure it will not +// be accessing global data. +void psc_lock(ParallelSweepContext_t *psc); +void psc_unlock(ParallelSweepContext_t *psc); + +// Used by the worker function to get a private MAI handle. +MaiPool_t *psc_get_mai(ParallelSweepContext_t *psc); +void psc_free_mai(ParallelSweepContext_t *psc, MaiPool_t *mpp); + +// psc_trigger wakes up the worker threads to look for new work items. +void psc_trigger(ParallelSweepContext_t *psc); + +// psc_wait allows another process to wait for worker callbacks to announce +// they are done. Note that work items may be added to a queue even after +// a callback announces it is done. Returns non-zero if a worker thread +// has reported an error. +Status_t psc_wait(ParallelSweepContext_t *psc); + +// Tells the parallel workers to start or stop running. psc_go() also +// clears any existing status codes. +void psc_go(ParallelSweepContext_t *psc); +void psc_stop(ParallelSweepContext_t *psc); + +// Gets or Sets the status variable in the context. Setting the status has no +// effect if the current status is already != VSTATUS_OK. +Status_t psc_get_status(ParallelSweepContext_t *psc); +void psc_set_status(ParallelSweepContext_t *psc, Status_t status); + +// Adds an item to the work queue and triggers the workers. +// Nota Bene: the caller should not access the work item after queueing it! +void psc_add_work_item(ParallelSweepContext_t *psc, + ParallelWorkItem_t *item); + +// Adds an item to the work queue without triggering the workers. +void psc_add_work_item_no_trigger(ParallelSweepContext_t *psc, + ParallelWorkItem_t *item); + +// Adds an item to the work queue as blocking. Does not trigger the workers. +// Nota Bene: the caller should not access the work item after queueing it! +void psc_add_barrier(ParallelSweepContext_t *psc, + ParallelWorkItem_t *item); + +// Flushes the work queue and frees the work items using vs_pool_free. +// If the work items were not allocated with vs_pool_alloc or if there +// is additional bookkeeping required for the work items, do not use +// this function. Has the side effect of telling the workers to stop running. +// +void psc_drain_work_queue(ParallelSweepContext_t *psc); + +// Allocates and initializes a PSC. +ParallelSweepContext_t *psc_init(void); + +// Shuts down the worker threads and releases the MAI handles, then destroys +// the parallel context. The work queue should be drained before calling this +// function. +void psc_cleanup(ParallelSweepContext_t *psc); + +// Returns !0 if the workers have not been told to stop. +boolean psc_is_running(ParallelSweepContext_t *psc); + +#endif diff --git a/Esm/ib/src/smi/include/sm_pkeys.h b/Esm/ib/src/smi/include/sm_pkeys.h new file mode 100644 index 0000000..836c60d --- /dev/null +++ b/Esm/ib/src/smi/include/sm_pkeys.h @@ -0,0 +1,37 @@ +/* BEGIN_ICS_COPYRIGHT2 **************************************** + +Copyright (c) 2018, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT2 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +#if !defined(_SM_PKEYS_H_) +#define _SM_PKEYS_H_ + +Status_t sweep_get_pkey(SweepContext_t *); + +#endif diff --git a/Esm/ib/src/smi/include/sm_qos.h b/Esm/ib/src/smi/include/sm_qos.h new file mode 100644 index 0000000..7da372a --- /dev/null +++ b/Esm/ib/src/smi/include/sm_qos.h @@ -0,0 +1,54 @@ +/* BEGIN_ICS_COPYRIGHT1 **************************************** + +Copyright (c) 2015-2018, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT1 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +#ifndef _SM_QOS_H_ +#define _SM_QOS_H_ + +#define SCVLMAP_BASE 8 +#define SCVLMAP_MAX_INDEX 32 + +// Used for routing modules +Status_t sm_assign_scs_to_sls_FixedMap(RoutingModule_t *rm, VirtualFabrics_t *VirtualFabrics); +Status_t sm_assign_scs_to_sls_NonFixedMap(RoutingModule_t *rm, VirtualFabrics_t *VirtualFabrics); + +extern uint8_t sm_SLtoSC[STL_MAX_SLS]; +extern uint8_t sm_SCtoSL[STL_MAX_SCS]; +extern Status_t sm_node_handleGetRespAggr(Node_t *, Port_t *, STL_AGGREGATE *, STL_AGGREGATE *); + +void sm_printf_vf_debug(VirtualFabrics_t *vfs); + +Qos_t* sm_get_qos(uint8_t vl); + +void sm_fill_SCVLMap(Qos_t *qos); + +Status_t sweep_assignments_vlarb(SweepContext_t *); +Status_t sweep_assignments_buffer_control(SweepContext_t *); +#endif //_SM_QOS_H_ diff --git a/Esm/ib/src/smi/include/sm_switch_info.h b/Esm/ib/src/smi/include/sm_switch_info.h new file mode 100644 index 0000000..5ffaf8b --- /dev/null +++ b/Esm/ib/src/smi/include/sm_switch_info.h @@ -0,0 +1,37 @@ +/* BEGIN_ICS_COPYRIGHT2 **************************************** + +Copyright (c) 2018, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT2 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +#if !defined(_SM_SWITCH_INFO_H_) +#define _SM_SWITCH_INFO_H_ + +Status_t sweep_assignments_switchinfo(SweepContext_t *); + +#endif diff --git a/Esm/ib/src/smi/include/sm_timesync.h b/Esm/ib/src/smi/include/sm_timesync.h new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/Esm/ib/src/smi/include/sm_timesync.h diff --git a/Esm/ib/src/smi/include/sm_update_fields.h b/Esm/ib/src/smi/include/sm_update_fields.h new file mode 100644 index 0000000..d7b9495 --- /dev/null +++ b/Esm/ib/src/smi/include/sm_update_fields.h @@ -0,0 +1,37 @@ +/* BEGIN_ICS_COPYRIGHT2 **************************************** + +Copyright (c) 2018, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT2 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +#if !defined(_SM_UPDATE_FIELDS_H_) +#define _SM_UPDATE_FIELDS_H_ + +Status_t sweep_assignments_update_fields(SweepContext_t *); + +#endif diff --git a/Esm/ib/src/smi/include/stl_cca.h b/Esm/ib/src/smi/include/stl_cca.h new file mode 100644 index 0000000..8edfc35 --- /dev/null +++ b/Esm/ib/src/smi/include/stl_cca.h @@ -0,0 +1,47 @@ +/* BEGIN_ICS_COPYRIGHT7 **************************************** + +Copyright (c) 2015-2018, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT7 ****************************************/ + +#ifndef _STL_CCA_H_ +#define _STL_CCA_H_ + +#include "ib_macros.h" +#include "sm_l.h" + + +Status_t stl_sm_cca_hfi_ref_acquire(HfiCongestionControlTableRefCount_t** congConRefCount, uint32_t tableSize); +HfiCongestionControlTableRefCount_t* stl_sm_cca_hfi_ref_copyptr(HfiCongestionControlTableRefCount_t* congConRefCount); +void stl_sm_cca_hfi_ref_release(HfiCongestionControlTableRefCount_t** congConRefCount); + +Status_t stl_sm_cca_configure_hfi(ParallelSweepContext_t *psc, SmMaiHandle_t *fd, Node_t *nodep); +Status_t stl_sm_cca_configure_sw(ParallelSweepContext_t *psc, SmMaiHandle_t *fd, Node_t *nodep); +Status_t stl_sm_cca_copy_hfi_data(Node_t *nodep); +Status_t stl_sm_cca_copy_sw_data(Node_t *nodep); +Status_t sm_cong_config_copy(void); + +#endif diff --git a/Fd/buildFeatureDefs b/Fd/buildFeatureDefs new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/Fd/buildFeatureDefs diff --git a/Fd/buildFeatureDefs.base b/Fd/buildFeatureDefs.base new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/Fd/buildFeatureDefs.base diff --git a/IbAccess/Common/Ibt/Bma/README b/IbAccess/Common/Ibt/Bma/README new file mode 100644 index 0000000..e29d2f5 --- /dev/null +++ b/IbAccess/Common/Ibt/Bma/README @@ -0,0 +1,4 @@ +Baseboard Management Agent + +Much of the real work is done via OS-specific BmaShim interfaces in +IbAccess/*/Ibt/Bma. diff --git a/IbAccess/Common/Ibt/Bma/bma_provider.h b/IbAccess/Common/Ibt/Bma/bma_provider.h new file mode 100644 index 0000000..71f3fcf --- /dev/null +++ b/IbAccess/Common/Ibt/Bma/bma_provider.h @@ -0,0 +1,155 @@ +/* BEGIN_ICS_COPYRIGHT4 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT4 ****************************************/ +/* [ICS VERSION STRING: unknown] */ + +#ifndef _IBA_IB_BMA_SHIM_H_ +#define _IBA_IB_BMA_SHIM_H_ + +#include "bmamain.h" +#include "ib_bm.h" + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#if 0 +typedef enum { + Ok = 0x00, /* Ok */ + UnspErr = 0x01, /* Unspecified Error */ + CmeBusy = 0x02, /* CME Busy */ + MmeBusy = 0x03, /* MME Busy */ + ComNotSupported = 0x04, /* Command not supported */ + IllReqParam = 0x05, /* Illegal Request Parameter */ + GenCompLow = 0x06, /* Generic Completion status range low */ + GenCompHigh = 0xbf, /* Generic Completion status range high */ + WriteProtect = 0x40, /* Write protected */ + NACKed = 0x41, /* NACK'd */ + BusErr = 0x42, /* BUS Error */ + Busy = 0x43, /* Busy */ + InvVPDDevSel = 0x44, /* Invalid VPD Device Selector */ + IllOffset = 0x45, /* Illegal Offset */ + IllByteCount = 0x46, /* Illegal Byte Count */ + VendSpecLow = 0x47, /* Vendor Specified range low (vendor ID as in Module info */ + VendSpecHigh = 0xff /* Vendor Specified range high */ +} Bma_CompStatus_t; + +#endif + +uint8 +BmaProvider_WriteVPD +( + uint8 device, /* Device Selector / Address */ + uint16 data_size, /* Size of the data to write */ + uint16 data_offset, /* Offset into the SEEPROM to write the data? */ + uint8 *data /* Pointer to the data buffer */ +); + +uint8 +BmaProvider_ReadVPD +( + uint8 device, /* Device Selector / Address */ + uint16 data_size, /* Size of the data to read */ + uint16 data_offset, /* Offset into the SEEPROM to write the data? */ + uint8 *data /* Pointer to the data buffer */ +); + +uint8 +BmaProvider_GetModuleStatus +( + uint8 *data /* Pointer to the data buffer */ +); + +#if 0 +// this is a callback from the shim to the agent to generate a trap +// not currently supported +extern uint8 +BmaProvider_SendTrap +( + /* Note: See Table 211 in section: 16.2.3.2 in vol 1-1 for details of valid values in these fields. */ + uint8 data_length, /* Size of the data buffer */ + uint8 trap_type, + uint32 type_modifier, /* Note: only bottom 24 bits are actually used. */ + uint8 *data /* Pointer to the data buffer */ +); + +// not currently supported +uint8 +BmaProvider_Ib2IbML +( + uint8 addr, /* Device Selector / Address */ + uint16 writeLength, /* Length of the data to write */ + uint8 * pWriteBuffer, /* Pointer to the write data buffer */ + uint16 * pReadLength, /* Pointer to the length of the data to read */ + uint8 * pReadBuffer /* Pointer to the read data buffer */ +); + +// not currently supported +uint8 +BmaProvider_GetModulePMControl +( + uint8 *data /* Pointer to the data buffer */ +); + +// not currently supported +uint8 +BmaProvider_SetModuleState +( + uint8 removalControl /* Removal Control request byte */ +); + +// not currently supported +uint8 +BmaProvider_SetModuleAttention +( + uint8 moduleAttention /* Module Attention request byte */ +); + +// not currently supported +uint8 +BmaProvider_SetModulePMControl +( + uint8 moduleControl /* Module Control request byte */ +); +#endif + +uint8 +BmaProvider_OemCmd +( + uint32 vendorId, /* IN: OUI of the vendor */ + uint8 in_length, /* IN: number of bytes in input buffer */ + const uint8* in_data, /* IN: input data */ + uint8* out_length, /* OUT: number of bytes in output buffer */ + uint8* out_data /* OUT: output data (up to BM_OEM_RSP_MAX_BYTES bytes) */ +); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* _IBA_IB_BMA_SHIM_H_ */ diff --git a/IbAccess/Common/Ibt/Bma/bmacallb.c b/IbAccess/Common/Ibt/Bma/bmacallb.c new file mode 100644 index 0000000..262609d --- /dev/null +++ b/IbAccess/Common/Ibt/Bma/bmacallb.c @@ -0,0 +1,706 @@ +/* BEGIN_ICS_COPYRIGHT4 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT4 ****************************************/ + +// Private header file +#include "bmamain.h" +#include "bmadebug.h" +#include "bma_provider.h" + +static void BmaSetClassPortInfo(BM_MAD* pMad, BMA_PORT_INFO* pPortInfo); +static void BmaGetClassPortInfo(BM_MAD* pMad, BMA_PORT_INFO* pPortInfo); +static void BmaSetBKeyInfo(BM_MAD* pMad, BMA_PORT_INFO* pPortInfo); +static void BmaGetBKeyInfo(BM_MAD* pMad, BMA_PORT_INFO* pPortInfo); +static void BmaWriteVpd(BM_MAD* pMad, BMA_PORT_INFO* pPortInfo); +static void BmaReadVpd(BM_MAD* pMad, BMA_PORT_INFO* pPortInfo); +static void BmaGetModuleStatus(BM_MAD* pMad, BMA_PORT_INFO* pPortInfo); +static void BmaOem(BM_MAD* pMad, BMA_PORT_INFO* pPortInfo); + +// +// GsaSendCompleteCallback +// +// GSA called this routine when a send datagram is completed. +// +// INPUTS: +// +// +// +// OUTPUTS: +// +// None. +// +// RETURNS: +// +// FSUCCESS - Indicates a successful load. +// +// IRQL: +// +// This routine is called at IRQL_PASSIVE_LEVEL. +// + + +void +BmaSendCallback( + void *ServiceContext, + IBT_DGRM_ELEMENT *pDgrmList + ) +{ + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, BmaSendCompleteCallback); + + // Return the element list to the free pool. + iba_gsi_dgrm_pool_put(pDgrmList); + + //DbgMessage(VERBOSE, ("BmaSendCallback: Returning.\n")); + _DBG_LEAVE_LVL(_DBG_LVL_FUNC_TRACE); + + return; + +} // BmaSendCompleteCallback() + + +////////////////////////////////////////////////////////////////////////// +// BmaRecvCallback +// +// GSA calls this routine when a Bma datagram is received. +// +// INPUTS: +// +// +// +// OUTPUTS: +// +// None. +// +// RETURNS: +// +// FSUCCESS - Indicates a successful load. +// +// IRQL: +// +// This routine is called at IRQL_PASSIVE_LEVEL. +// + +FSTATUS +BmaRecvCallback( + void *ServiceContext, + IBT_DGRM_ELEMENT *pDgrmList + ) +{ + FSTATUS status; + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, BmaRecvCallback); + + ASSERT(pDgrmList); + + // Sanity checks + if (ServiceContext != g_BmaGlobalInfo) + { + _DBG_ERROR((" Invalid CM Context passed in!!!\n", _DBG_PTR(ServiceContext))); + + _DBG_LEAVE_LVL(_DBG_LVL_FUNC_TRACE); + + status = FINVALID_PARAMETER; + } + else if (! CmdThreadQueue(&g_BmaGlobalInfo->RecvThread, pDgrmList)) + status = FINSUFFICIENT_RESOURCES; + else + status = FPENDING; + + _DBG_LEAVE_LVL(_DBG_LVL_FUNC_TRACE); + + return status; +} + +void BmaFreeCallback(IN void* Context, IN void* Cmd) +{ + IBT_DGRM_ELEMENT *pDgrmList = (IBT_DGRM_ELEMENT*)Cmd; + ASSERT(Context == g_BmaGlobalInfo); + + DgrmPoolPut(pDgrmList); +} + +void BmaThreadCallback(IN void* Context, IN void* Cmd) +{ + IBT_DGRM_ELEMENT *pDgrmList = (IBT_DGRM_ELEMENT*)Cmd; + IBT_DGRM_ELEMENT *pRecvDgrm; + IBT_DGRM_ELEMENT *pSendDgrm; + BM_MAD *pMad=NULL; + BM_MAD *pBmGmp; + FSTATUS fstatus; + IB_HANDLE qp1Handle; + uint8 portNumber; + uint32 Count; + boolean BKeyMatch; + BMA_DEV_INFO *pDevInfo; + BMA_PORT_INFO *pPortInfo; + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, BmaThreadCallback); + + ASSERT(Context == g_BmaGlobalInfo); + + // + // iterate thru each datagrams/mads in the list + // + for (pRecvDgrm = pDgrmList; + pRecvDgrm != NULL; + pRecvDgrm = (IBT_DGRM_ELEMENT *)pRecvDgrm->Element.pNextElement) + { + + // Verify the size of this datagram. + if (pRecvDgrm->TotalRecvSize != MAD_BLOCK_SIZE + sizeof(IB_GRH)) + { + _DBG_ERROR((" Datagram passed less than 256 bytes \n", + _DBG_PTR(pRecvDgrm), pRecvDgrm->TotalRecvSize)); + // Drop this datagram. + continue; + } + + ASSERT(pRecvDgrm->Element.pBufferList); + ASSERT(GsiDgrmGetRecvGrh(pRecvDgrm)); + pMad = (BM_MAD*)GsiDgrmGetRecvMad(pRecvDgrm); + if (!pMad) + { + _DBG_ERROR((" Empty MAD passed in!\n", _DBG_PTR(pRecvDgrm))); + continue; + } + + // Sanity checks. + if ( (pMad->common.BaseVersion != IB_BASE_VERSION) || + (pMad->common.MgmtClass != MCLASS_BM) || + (pMad->common.ClassVersion != IB_BM_CLASS_VERSION) ) + { + _DBG_ERROR((" Invalid base version, mgmt class or class version \n", + _DBG_PTR(pMad), + pMad->common.BaseVersion, + pMad->common.MgmtClass, + pMad->common.ClassVersion)); + // Drop this datagram. + continue; + } + + if ( FSUCCESS != GetGsiContextFromPortGuid(pRecvDgrm->PortGuid, &qp1Handle, &portNumber) ) + { + // Drop this datagram. + continue; + } + + SpinLockAcquire( &g_BmaGlobalInfo->DevListLock ); + // below this point use "goto nextpacket" to drop the packet + pDevInfo = g_BmaGlobalInfo->DevList; + pPortInfo = NULL; + // find the port info, this list should be really short, so this isn't as bad as it looks + while (pDevInfo && !pPortInfo) + { + unsigned i; + for (i = 0; i < pDevInfo->NumPorts; i++) + { + if ( pDevInfo->Port[i].Guid == pRecvDgrm->PortGuid ) + { + pPortInfo = &pDevInfo->Port[i]; + break; + } + } + if (!pPortInfo) + pDevInfo = pDevInfo->Next; + } + if (!pPortInfo) + { + // bad port, drop this datagram + goto nextpacket; + } + + BSWAP_BM_HDR( &pMad->BmHdr ); + + switch ( pMad->common.mr.AsReg8 ) + { + case BASEMGT_GET: + case BASEMGT_SET: + switch (pMad->common.AttributeID) + { + // case BM_ATTRIB_ID_NOTICE: // only if notice queue supported + case BM_ATTRIB_ID_CLASS_PORTINFO: + case BM_ATTRIB_ID_BKEY_INFO: + // ok + break; + default: + // Drop this datagram (or return an error). + _DBG_ERROR((" Invalid attribute for method %x\n", pMad->common.mr.AsReg8)); + goto nextpacket; + } + break; + + case BASEMGT_TRAP_REPRESS: + // TODO: No reply, handle right here? (do we need to check the BKey?) + if (pMad->common.AttributeID != BM_ATTRIB_ID_NOTICE) { + goto nextpacket; + } + break; + + case BASEMGT_SEND: + switch (pMad->common.AttributeID) + { + case BM_ATTRIB_ID_WRITE_VPD: + case BM_ATTRIB_ID_READ_VPD: + case BM_ATTRIB_ID_GET_MODULE_STATUS: + case BM_ATTRIB_ID_OEM: + // ok + break; + // not currently supported, but could be + case BM_ATTRIB_ID_RESET_IBML: + case BM_ATTRIB_ID_SET_MODULE_PM_CONTROL: + case BM_ATTRIB_ID_GET_MODULE_PM_CONTROL: + case BM_ATTRIB_ID_SET_UNIT_PM_CONTROL: + case BM_ATTRIB_ID_GET_UNIT_PM_CONTROL: + case BM_ATTRIB_ID_SET_IOC_PM_CONTROL: + case BM_ATTRIB_ID_GET_IOC_PM_CONTROL: + case BM_ATTRIB_ID_SET_MODULE_STATE: + case BM_ATTRIB_ID_SET_MODULE_ATTENTION: + case BM_ATTRIB_ID_IB2IBML: + case BM_ATTRIB_ID_IB2CME: + case BM_ATTRIB_ID_IB2MME: + default: + // Drop this datagram (or return an error). + _DBG_ERROR((" Invalid attribute for method %x\n", pMad->common.mr.AsReg8)); + goto nextpacket; + } + break; + + // we should never get these on incoming packets + case BASEMGT_REPORT: + case BASEMGT_REPORT_RESP: + case BASEMGT_GET_RESP: + case BASEMGT_TRAP: + default: + // Drop this datagram. + _DBG_ERROR((" Invalid method %x\n", pMad->common.mr.AsReg8)); + goto nextpacket; + } + + // + // looks good, check the key + // + BKeyMatch = ( pPortInfo->BKey == 0 ) || ( pMad->BmHdr.BKey == pPortInfo->BKey ) || + (( pMad->common.mr.AsReg8 == BASEMGT_GET ) && ( !pPortInfo->BKeyProtect )); + + if (!BKeyMatch && ( pMad->common.mr.AsReg8 != BASEMGT_GET )) + { + if (pPortInfo->BKeyViolations < 0xffff) + pPortInfo->BKeyViolations++; + // TODO: Send BMA_TRAP_BAD_BKEY, and schedule to be repeated + if (pPortInfo->BKeyLease) { + // TODO: Start countdown timer for BKeyLease seconds + } + // Drop this datagram + goto nextpacket; + } + + // + // Process the valid mad + // + if (g_BmaGlobalInfo->DgrmPoolHandle != NULL) + { + // Obtain a send datagram element. + Count = 1; + fstatus = iba_gsi_dgrm_pool_get( + g_BmaGlobalInfo->DgrmPoolHandle, + &Count, + &pSendDgrm); + if (fstatus != FSUCCESS) + { + _DBG_ERROR(("BmaRecvCallback: GsiDgrmPoolGet unsuccessful.\n")); + // Drop this datagram. + goto nextpacket; + } + } + else + { + _DBG_ERROR(("BmaRecvCallback: DgrmPoolHandle == NULL.\n")); + // Drop this datagram. + goto nextpacket; + } + + // Set endpoint information. + GsiDgrmAddrCopy(pSendDgrm, pRecvDgrm); + + // Set the response datagram size. + pSendDgrm->Element.pBufferList->ByteCount = MAD_BLOCK_SIZE; + + // Initalize a pointer to the send perf management packet. + pBmGmp = (BM_MAD*)GsiDgrmGetSendMad(pSendDgrm); + + // Initialize the send GMP. + MemoryCopy((char*)pBmGmp, (char*)pMad, sizeof(BM_MAD)); + pBmGmp->common.u.NS.Status.AsReg16 = MAD_STATUS_SUCCESS; + + if (fstatus == FSUCCESS) + { + // swap BMData to host byte order + switch (pBmGmp->common.AttributeID) + { + case BM_ATTRIB_ID_CLASS_PORTINFO: + if ( pMad->common.mr.AsReg8 == BASEMGT_SET ) { + BSWAP_IB_CLASS_PORT_INFO((IB_CLASS_PORT_INFO*)&pBmGmp->BMData); + BmaSetClassPortInfo(pBmGmp, pPortInfo); + } + else { + BmaGetClassPortInfo(pBmGmp, pPortInfo); + } + BSWAP_IB_CLASS_PORT_INFO((IB_CLASS_PORT_INFO*)&pBmGmp->BMData); + break; + + case BM_ATTRIB_ID_BKEY_INFO: + if ( pMad->common.mr.AsReg8 == BASEMGT_SET ) { + BSWAP_BKEY_INFO((BKEY_INFO*)&pBmGmp->BMData); + BmaSetBKeyInfo(pBmGmp, pPortInfo); + } + else { + BmaGetBKeyInfo(pBmGmp, pPortInfo); + } + if (!BKeyMatch) { + ((BKEY_INFO*)&pBmGmp->BMData)->B_Key = 0; + } + BSWAP_BKEY_INFO((BKEY_INFO*)&pBmGmp->BMData); + break; + + case BM_ATTRIB_ID_WRITE_VPD: + if (pMad->common.AttributeModifier == BM_ATTRIB_MOD_REQUEST) { + BSWAP_BM_SEND((BM_SEND*)&pBmGmp->BMData); + BmaWriteVpd(pBmGmp, pPortInfo); + BSWAP_BM_SEND((BM_SEND*)&pBmGmp->BMData); + } + else { + pBmGmp->common.u.NS.Status.AsReg16 = MAD_STATUS_INVALID_ATTRIB; + } + // Set the AttributModifier bit to reflect a BMSEND response. + pBmGmp->common.AttributeModifier = BM_ATTRIB_MOD_RESPONSE; + break; + + case BM_ATTRIB_ID_READ_VPD: + if (pMad->common.AttributeModifier == BM_ATTRIB_MOD_REQUEST) { + BSWAP_BM_SEND((BM_SEND*)&pBmGmp->BMData); + BmaReadVpd(pBmGmp, pPortInfo); + BSWAP_BM_SEND((BM_SEND*)&pBmGmp->BMData); + } + else { + pBmGmp->common.u.NS.Status.AsReg16 = MAD_STATUS_INVALID_ATTRIB; + } + // Set the AttributModifier bit to reflect a BMSEND response. + pBmGmp->common.AttributeModifier = BM_ATTRIB_MOD_RESPONSE; + break; + + case BM_ATTRIB_ID_GET_MODULE_STATUS: + if (pMad->common.AttributeModifier == BM_ATTRIB_MOD_REQUEST) { + BSWAP_BM_SEND((BM_SEND*)&pBmGmp->BMData); + BmaGetModuleStatus(pBmGmp, pPortInfo); + BSWAP_BM_SEND((BM_SEND*)&pBmGmp->BMData); + } + else { + pBmGmp->common.u.NS.Status.AsReg16 = MAD_STATUS_INVALID_ATTRIB; + } + // Set the AttributModifier bit to reflect a BMSEND response. + pBmGmp->common.AttributeModifier = BM_ATTRIB_MOD_RESPONSE; + break; + + case BM_ATTRIB_ID_OEM: + if (pMad->common.AttributeModifier == BM_ATTRIB_MOD_REQUEST) { + BSWAP_BM_SEND((BM_SEND*)&pBmGmp->BMData); + BmaOem(pBmGmp, pPortInfo); + BSWAP_BM_SEND((BM_SEND*)&pBmGmp->BMData); + } + // Set the AttributModifier bit to reflect a BMSEND response. + pBmGmp->common.AttributeModifier = BM_ATTRIB_MOD_RESPONSE; + break; + + // not yet supported: + case BM_ATTRIB_ID_NOTICE: + // Invalid attribute + pBmGmp->common.u.NS.Status.AsReg16 = MAD_STATUS_UNSUPPORTED_METHOD_ATTRIB; + break; + + case BM_ATTRIB_ID_RESET_IBML: + case BM_ATTRIB_ID_SET_MODULE_PM_CONTROL: + case BM_ATTRIB_ID_GET_MODULE_PM_CONTROL: + case BM_ATTRIB_ID_SET_UNIT_PM_CONTROL: + case BM_ATTRIB_ID_GET_UNIT_PM_CONTROL: + case BM_ATTRIB_ID_SET_IOC_PM_CONTROL: + case BM_ATTRIB_ID_GET_IOC_PM_CONTROL: + case BM_ATTRIB_ID_SET_MODULE_STATE: + case BM_ATTRIB_ID_SET_MODULE_ATTENTION: + case BM_ATTRIB_ID_IB2IBML: + case BM_ATTRIB_ID_IB2CME: + case BM_ATTRIB_ID_IB2MME: + default: + // Invalid attribute + pBmGmp->common.u.NS.Status.AsReg16 = MAD_STATUS_UNSUPPORTED_METHOD_ATTRIB; + // Set the AttributModifier bit to reflect a BMSEND response. + pBmGmp->common.AttributeModifier = BM_ATTRIB_MOD_RESPONSE; + break; + } + } + + BSWAP_BM_HDR( &pBmGmp->BmHdr ); + + // Send the response datagram. + fstatus = iba_gsi_post_send(g_BmaGlobalInfo->GsaHandle, pSendDgrm); + if (fstatus != FSUCCESS) + { + iba_gsi_dgrm_pool_put(pSendDgrm); + } + +nextpacket: + SpinLockRelease( &g_BmaGlobalInfo->DevListLock ); + } // for + + DgrmPoolPut(pDgrmList); + + _DBG_LEAVE_LVL(_DBG_LVL_FUNC_TRACE); +} // BmaRecvCallback() + + +static void +BmaSetClassPortInfo(BM_MAD* pMad, BMA_PORT_INFO* pPortInfo) +{ + IB_CLASS_PORT_INFO* pClassPortInfo = (IB_CLASS_PORT_INFO*)&pMad->BMData; + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, BmaSetClassPortInfo); + + // validate fields + if (pClassPortInfo->TrapLID && (!pClassPortInfo->u5.s.TrapQP || !(pClassPortInfo->Trap_Q_Key & 0x80000000))) + { + pMad->common.mr.AsReg8 = MMTHD_GET_RESP; + pMad->common.u.NS.Status.AsReg16 = MAD_STATUS_INVALID_ATTRIB; + } + else { + // apply, no locking necessary, Bma thread is only one to use + pPortInfo->Trap.GID = pClassPortInfo->TrapGID; + pPortInfo->Trap.TClass = pClassPortInfo->u4.s.TrapTClass; + pPortInfo->Trap.SL = pClassPortInfo->u4.s.TrapSL; + pPortInfo->Trap.FlowLabel = pClassPortInfo->u4.s.TrapFlowLabel; + pPortInfo->Trap.LID = pClassPortInfo->TrapLID; + pPortInfo->Trap.P_Key = pClassPortInfo->Trap_P_Key; + pPortInfo->Trap.HopLimit = pClassPortInfo->u5.s.TrapHopLimit; + pPortInfo->Trap.QP = pClassPortInfo->u5.s.TrapQP; + pPortInfo->Trap.Q_Key = pClassPortInfo->Trap_Q_Key; + + // generate response + BmaGetClassPortInfo(pMad, pPortInfo); + } + + _DBG_LEAVE_LVL(_DBG_LVL_FUNC_TRACE); +} + + +static void +BmaGetClassPortInfo(BM_MAD* pMad, BMA_PORT_INFO* pPortInfo) +{ + IB_CLASS_PORT_INFO* pClassPortInfo = (IB_CLASS_PORT_INFO*)&pMad->BMData; + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, BmaGetClassPortInfo); + + MemoryClear(pClassPortInfo, sizeof(*pClassPortInfo)); + pClassPortInfo->BaseVersion = IB_BASE_VERSION; + pClassPortInfo->ClassVersion = IB_BM_CLASS_VERSION; + pClassPortInfo->CapMask = CLASS_PORT_CAPMASK_TRAP; // TODO: Is this all? + pClassPortInfo->u1.s.RespTimeValue = PORT_RESP_TIME_VALUE_MAX; // 8 + + // setup trap info + pClassPortInfo->TrapGID = pPortInfo->Trap.GID; + pClassPortInfo->u4.s.TrapTClass = pPortInfo->Trap.TClass; + pClassPortInfo->u4.s.TrapSL = pPortInfo->Trap.SL; + pClassPortInfo->u4.s.TrapFlowLabel = pPortInfo->Trap.FlowLabel; + pClassPortInfo->TrapLID = pPortInfo->Trap.LID; + pClassPortInfo->Trap_P_Key = pPortInfo->Trap.P_Key; + pClassPortInfo->u5.s.TrapHopLimit = pPortInfo->Trap.HopLimit; + pClassPortInfo->u5.s.TrapQP = pPortInfo->Trap.QP; + pClassPortInfo->Trap_Q_Key = pPortInfo->Trap.Q_Key; + + pMad->common.mr.AsReg8 = MMTHD_GET_RESP; + + _DBG_LEAVE_LVL(_DBG_LVL_FUNC_TRACE); +} + +static void +BmaSetBKeyInfo(BM_MAD* pMad, BMA_PORT_INFO* pPortInfo) +{ + BKEY_INFO* pBKeyInfo = (BKEY_INFO*)&pMad->BMData; + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, BmaSetBKeyInfo); + + // Do set + pPortInfo->BKey = pBKeyInfo->B_Key; + pPortInfo->BKeyProtect = pBKeyInfo->u1.s.B_KeyProtectBit; + pPortInfo->BKeyLease = pBKeyInfo->B_KeyLeasePeriod; + + // Response + pBKeyInfo->B_KeyViolations = pPortInfo->BKeyViolations; + + pMad->common.mr.AsReg8 = MMTHD_GET_RESP; + + _DBG_LEAVE_LVL(_DBG_LVL_FUNC_TRACE); +} + +static void +BmaGetBKeyInfo(BM_MAD* pMad, BMA_PORT_INFO* pPortInfo) +{ + BKEY_INFO* pBKeyInfo = (BKEY_INFO*)&pMad->BMData; + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, BmaGetBKeyInfo); + + MemoryClear(pBKeyInfo, sizeof(*pBKeyInfo)); + + pBKeyInfo->B_Key = pPortInfo->BKey; + pBKeyInfo->u1.s.B_KeyProtectBit = pPortInfo->BKeyProtect; + pBKeyInfo->B_KeyLeasePeriod = pPortInfo->BKeyLease; + pBKeyInfo->B_KeyViolations = pPortInfo->BKeyViolations; + + pMad->common.mr.AsReg8 = MMTHD_GET_RESP; + + _DBG_LEAVE_LVL(_DBG_LVL_FUNC_TRACE); +} + +static void +BmaWriteVpd(BM_MAD* pMad, BMA_PORT_INFO* pPortInfo) +{ + BM_SEND* pBMSend = (BM_SEND*)&pMad->BMData; + uint16 seq = pBMSend->Sequence; + uint8 dev = BM_REQ_GET_VPD_DEVICE(pBMSend); + uint16 bytes = BM_REQ_GET_VPD_NUM_BYTES(pBMSend); + uint16 offset = BM_REQ_GET_VPD_OFFSET(pBMSend); + uint8 status = BM_STATUS_OK; + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, BmaWriteVpd); + + if ( bytes > BM_WRITE_VPD_MAX_BYTES ) + { + status = BM_STATUS_ILLEGAL_BYTE_COUNT; + } + else + { + status = BmaProvider_WriteVPD(dev, bytes, offset, BM_REQ_WRITE_VPD_DATA_PTR(pBMSend)); + } + + // build response packet + MemoryClear(pBMSend, sizeof(BM_SEND)); + pBMSend->Sequence = seq; + pBMSend->SourceDevice = BM_DEV_MME; + pBMSend->ParamCount = 1; + BM_RSP_SET_STATUS(pBMSend, status); + + _DBG_LEAVE_LVL(_DBG_LVL_FUNC_TRACE); +} + +static void +BmaReadVpd(BM_MAD* pMad, BMA_PORT_INFO* pPortInfo) +{ + BM_SEND* pBMSend = (BM_SEND*)&pMad->BMData; + uint16 seq = pBMSend->Sequence; + uint8 dev = BM_REQ_GET_VPD_DEVICE(pBMSend); + uint16 bytes = BM_REQ_GET_VPD_NUM_BYTES(pBMSend); + uint16 offset = BM_REQ_GET_VPD_OFFSET(pBMSend); + uint8 status = BM_STATUS_OK; + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, BmaReadVpd); + + MemoryClear(pBMSend, sizeof(BM_SEND)); + + if ( bytes > BM_READ_VPD_MAX_BYTES ) + { + status = BM_STATUS_ILLEGAL_BYTE_COUNT; + } + else + { + status = BmaProvider_ReadVPD(dev, bytes, offset, BM_RSP_READ_VPD_DATA_PTR(pBMSend)); + } + + // build response packet + pBMSend->Sequence = seq; + pBMSend->SourceDevice = BM_DEV_MME; + pBMSend->ParamCount = 1; + if (status == BM_STATUS_OK) + pBMSend->ParamCount += bytes; + + BM_RSP_SET_STATUS(pBMSend, status); + + _DBG_LEAVE_LVL(_DBG_LVL_FUNC_TRACE); +} + +static void +BmaGetModuleStatus(BM_MAD* pMad, BMA_PORT_INFO* pPortInfo) +{ + BM_SEND* pBMSend = (BM_SEND*)&pMad->BMData; + uint16 seq = pBMSend->Sequence; + uint8 status = BM_STATUS_OK; + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, BmaGetModuleStatus); + + MemoryClear(pBMSend, sizeof(BM_SEND)); + + status = BmaProvider_GetModuleStatus(BM_RSP_MODULE_STATUS_DATA_PTR(pBMSend)); + + // build response packet + pBMSend->Sequence = seq; + pBMSend->SourceDevice = BM_DEV_MME; + pBMSend->ParamCount = BM_GET_MODULE_STATUS_BYTES; + + BM_RSP_SET_STATUS(pBMSend, status); + + _DBG_LEAVE_LVL(_DBG_LVL_FUNC_TRACE); +} + +static void +BmaOem(BM_MAD* pMad, BMA_PORT_INFO* pPortInfo) +{ + BM_SEND* pBMSend = (BM_SEND*)&pMad->BMData; + uint16 seq = pBMSend->Sequence; + uint8 status = BM_STATUS_OK; + uint32 vendor = BM_REQ_GET_OEM_VENDOR_ID(pBMSend); + uint8 numBytes = BM_REQ_GET_OEM_NUM_BYTES(pBMSend); + uint8 rspBuf[BM_OEM_RSP_MAX_BYTES]; + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, BmaOem); + + if (numBytes > BM_OEM_REQ_MAX_BYTES) { + numBytes = 0; + status = BM_STATUS_ILLEGAL_BYTE_COUNT; + } + else { + status = BmaProvider_OemCmd(vendor, numBytes, BM_REQ_OEM_DATA_PTR(pBMSend), &numBytes, rspBuf); + } + + // build response packet + pBMSend->Sequence = seq; + pBMSend->SourceDevice = BM_DEV_MME; + + BM_RSP_SET_OEM_NUM_BYTES(pBMSend, numBytes); + BM_RSP_SET_STATUS(pBMSend, status); + BM_RSP_SET_OEM_VENDOR_ID(pBMSend, vendor); + MemoryCopy(BM_RSP_OEM_DATA_PTR(pBMSend), rspBuf, min(numBytes, sizeof(pBMSend->Parameters) - 4)); + + _DBG_LEAVE_LVL(_DBG_LVL_FUNC_TRACE); +} + diff --git a/IbAccess/Common/Ibt/Bma/bmadebug.h b/IbAccess/Common/Ibt/Bma/bmadebug.h new file mode 100644 index 0000000..62a449b --- /dev/null +++ b/IbAccess/Common/Ibt/Bma/bmadebug.h @@ -0,0 +1,48 @@ +/* BEGIN_ICS_COPYRIGHT4 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT4 ****************************************/ +/* [ICS VERSION STRING: unknown] */ + +// Suppress duplicate loading of this file +#ifndef _IBA_BMA_DEBUG_H_ +#define _IBA_BMA_DEBUG_H_ + +#undef _ib_dbg_params +#define _ib_dbg_params Bma_debug_params +#ifndef Bma_debug_params + extern IB_DBG_PARAMS Bma_debug_params; +#endif + +// +// Debug Levels +// +#define _DBG_LVL_MAIN 0x00000001 +#define _DBG_LVL_CLASS 0x00000002 + + +#endif // _IBA_GSA_DEBUG_H_ diff --git a/IbAccess/Common/Ibt/Bma/bmamain.c b/IbAccess/Common/Ibt/Bma/bmamain.c new file mode 100644 index 0000000..d6b1ead --- /dev/null +++ b/IbAccess/Common/Ibt/Bma/bmamain.c @@ -0,0 +1,486 @@ +/* BEGIN_ICS_COPYRIGHT4 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT4 ****************************************/ + +#include "bmamain.h" +#include "bmadebug.h" +#include "bma_provider.h" +#include "bspcommon/h/usrBootManager.h" +#include "bspcommon/ibml/h/icsApi.h" + +// +// Debug params +// +#if ICS_LOGGING +_IB_DBG_PARAM_BLOCK(_DBG_LVL_ALL, _DBG_BREAK_ENABLE, BMA_TAG, "Bma", MOD_BMA, Bma); +#else +_IB_DBG_PARAM_BLOCK((_DBG_LVL_FATAL | _DBG_LVL_ERROR), _DBG_BREAK_ENABLE, BMA_TAG, "Bma"); +#endif + +// +// Global Info +// +BMA_GLOBAL_INFO *g_BmaGlobalInfo; + +// +// Stored settings +// +BMA_GLOBAL_CONFIG_PARAMETERS g_BmaSettings = BMA_DEFAULT_SETTINGS; + + +// +// BmaLoad +// +// This routine is called by the VCA Init when the driver is first loaded. +// This routine is to create and initialize the BMA agent global data structures. +// +// INPUTS: +// +// ComponentInfo - Address of IBT_COMPONENT_INFO that needs to be updated +// with this driver's specific handlers for add/remove of a channel adapter +// device as well as the overall driver unload handler. +// +// OUTPUTS: +// +// None. +// +// RETURNS: +// +// FSUCCESS - Indicates a successful load. +// + +FSTATUS +BmaLoad( + IN IBT_COMPONENT_INFO *ComponentInfo + ) +{ + FSTATUS status = FSUCCESS; + extern uint32 BmaDbg; +#ifdef IB_TRACE + extern uint32 BmaTrace; +#endif + + + _DBG_ENTER_LVL(_DBG_LVL_MAIN, BMALoad); + _DBG_INIT; + + __DBG_LEVEL__ = BmaDbg; +#ifdef IB_TRACE + __DBG_TRACE_LEVEL__ = BmaTrace; +#endif +#if defined(IB_DEBUG) || defined(DBG) + MsgOut ("Bma:DebugFlags = 0x%8x\n", __DBG_LEVEL__); +#endif + +#if defined(VXWORKS) + _DBG_PRINT(_DBG_LVL_MAIN, + (" InfiniBand Baseboard Management Class agent. Built %s %s\n",\ + __DATE__, __TIME__ )); +#else + _DBG_PRINT(_DBG_LVL_MAIN, + (" InfiniBand Baseboard Management Class agent. Built %s %s\n",\ + _DBG_PTR(__DATE__), _DBG_PTR(__TIME__) )); +#endif + + _TRC_REGISTER(); + + // + // Establish dispatch entry points for the functions supported. + // + + MemoryClear( ComponentInfo, sizeof(IBT_COMPONENT_INFO) ); + + ComponentInfo->AddDevice = BmaAddDevice; + ComponentInfo->RemoveDevice = BmaRemoveDevice; + ComponentInfo->Unload = BmaUnload; + + + // + // Read any registry parameters for the driver which may be present. + // + //BmaReadRegistryParameters(); + + // + // This function is called to initialize the GSA subsystem. This must be + // called only once and if the function does not return success, the + // caller must unload the component containing GSA or else not use the + // GSA functionality since GSA will not be available. + // + // We are being asked to do a one-time initialization. Here we initialize + // the list of channel adapters as well as initialize the list of service + // classes as well as initialize the spin locks guarding these lists. + // + + + // + // Allocate space for Global data + // + + g_BmaGlobalInfo = (BMA_GLOBAL_INFO*)MemoryAllocateAndClear( + sizeof(BMA_GLOBAL_INFO), FALSE, BMA_TAG ); + if ( NULL != g_BmaGlobalInfo ) + { + + // + // initialize global data + // + + g_BmaGlobalInfo->binitsuccess = FALSE; + + SpinLockInitState( &g_BmaGlobalInfo->DevListLock ); + if( !SpinLockInit( &g_BmaGlobalInfo->DevListLock ) ) + { + _DBG_ERROR(( "Unable to initialize spin locks!\n" )); + status = FINSUFFICIENT_RESOURCES; + goto fail_lock; + } + + // + // Recv Queue and Thread + // + CmdThreadInitState(&g_BmaGlobalInfo->RecvThread); + if ( ! CmdThreadCreate(&g_BmaGlobalInfo->RecvThread, + THREAD_PRI_HIGH, "Bma", (CMD_THREAD_CALLBACK)BmaThreadCallback, + (CMD_THREAD_CALLBACK)BmaFreeCallback, (void*)g_BmaGlobalInfo)) + { + _DBG_ERROR(("BmaMain: Unable to Create RecvThread\n")); + status = FINSUFFICIENT_RESOURCES; + goto fail_thread; + } + + + // initialize this general service class manager with GSI + status = iba_gsi_register_class(MCLASS_BM, + IB_BM_CLASS_VERSION, + GSI_REGISTER_RESPONDER, // Register as a Responder + FALSE, // No SAR cap needed + g_BmaGlobalInfo, // Context + BmaSendCallback, + BmaRecvCallback, + &g_BmaGlobalInfo->GsaHandle); + + if (status != FSUCCESS) + { + CmdThreadDestroy(&g_BmaGlobalInfo->RecvThread); +fail_thread: + SpinLockDestroy( &g_BmaGlobalInfo->DevListLock ); +fail_lock: + MemoryDeallocate(g_BmaGlobalInfo); + g_BmaGlobalInfo = NULL; + + _DBG_ERROR(("BmaMain: Unable to register with GSA!!! \n", status)); + + _DBG_LEAVE_EXT(_DBG_LVL_FUNC_TRACE); + + return status; + } + + } + else + { + status = FINSUFFICIENT_RESOURCES; + _DBG_PRINT(_DBG_LVL_MAIN,("Not enough memory!\n")); + } + + + _DBG_LEAVE_LVL(_DBG_LVL_MAIN); + + return status; +} + + +// +// BmaUnload +// +// This routine should release resources allocated in the BmaLoad function. +// Also, since their is a single instance of the service for all channel +// adapters in the system, it will also release resources allocated in the +// BmaAddDevice function. +// +// INPUTS: +// +// None. +// +// OUTPUTS: +// +// None. +// +// RETURNS: +// +// None +// +// +void +BmaUnload(void) +{ + + _DBG_ENTER_LVL(_DBG_LVL_MAIN, BmaUnload); + + _TRC_UNREGISTER(); + + if ( g_BmaGlobalInfo ) + { + + // Destroy the datagram pool + if ( g_BmaGlobalInfo->DgrmPoolHandle ) + iba_gsi_destroy_dgrm_pool( g_BmaGlobalInfo->DgrmPoolHandle ); + + // Deregister this class agent with the GSA + if ( g_BmaGlobalInfo->GsaHandle ) + iba_gsi_deregister_class(g_BmaGlobalInfo->GsaHandle); + + // + // Recv Thread + // + CmdThreadDestroy(&g_BmaGlobalInfo->RecvThread); + + // + // Ca List Members + // + while ( g_BmaGlobalInfo->DevList ) + { + BmaRemoveDevice( g_BmaGlobalInfo->DevList->CaGuid, NULL ); + } + + // + // Ca List Lock + // + SpinLockDestroy( &g_BmaGlobalInfo->DevListLock ); + + + // + // Free up global memory + // + MemoryDeallocate( g_BmaGlobalInfo ); + g_BmaGlobalInfo = NULL; + + } // if g_BmaGlobalInfo + + _DBG_LEAVE_LVL(_DBG_LVL_MAIN); + + +} + + +////////////////////////////////////////////////////////////////////////// +// BmaAddDevice() +// +// This routine is called once for every new device added. +// +// INPUTS: +// CaGuid - the channel adapters GUID +// +// OUTPUTS: +// +// None. Although function is defined to return context value, this +// value is not set since their is nothing specifically allocated for +// each new channel adapter, so nothing is done in the BmaRemoveDevice +// function that needs the context. +// +// RETURNS: +// +// FSUCCESS - Indicates a successful initialization. +// +// +FSTATUS +BmaAddDevice( + IN EUI64 CaGuid, + OUT void **Context + ) +{ + FSTATUS status = FSUCCESS; + uint32 BufferSize; + BMA_DEV_INFO *pDevInfo=NULL; + + _DBG_ENTER_LVL(_DBG_LVL_MAIN, BmaAddDevice); + + ASSERT(g_BmaGlobalInfo); + + if (!g_BmaGlobalInfo->binitsuccess) + { + // Create the datagram pool + BufferSize = sizeof(MAD); + status = iba_gsi_create_dgrm_pool(g_BmaGlobalInfo->GsaHandle, + g_BmaSettings.MaxNDgrm, + 1, + &BufferSize, + 0, //1, + &g_BmaGlobalInfo->DgrmPoolHandle + ); + if (status != FSUCCESS) + { + // Cleanup + iba_gsi_deregister_class(g_BmaGlobalInfo->GsaHandle); + + MemoryDeallocate(g_BmaGlobalInfo); + + g_BmaGlobalInfo = NULL; + + _DBG_ERROR(("Unable to create BMA datagram pool!!! \n", status)); + } + else + { + g_BmaGlobalInfo->binitsuccess = TRUE; + } + + } + + if (g_BmaGlobalInfo->binitsuccess) + { + pDevInfo = (BMA_DEV_INFO*)MemoryAllocateAndClear(sizeof(BMA_DEV_INFO), FALSE, BMA_TAG ); + + if (pDevInfo) + { + IB_CA_ATTRIBUTES CaAttributes; + + pDevInfo->CaGuid = CaGuid; + status = iba_query_ca_by_guid_alloc(CaGuid, &CaAttributes); + if ( status == FSUCCESS ) + { + pDevInfo->NumPorts = CaAttributes.Ports; + pDevInfo->Port = (BMA_PORT_INFO*) + MemoryAllocateAndClear(sizeof(BMA_PORT_INFO)*pDevInfo->NumPorts, FALSE, BMA_TAG); + if (pDevInfo->Port) + { + IB_PORT_ATTRIBUTES *pPortAttr; + unsigned i; + + for ( i = 0, pPortAttr = CaAttributes.PortAttributesList; + i < pDevInfo->NumPorts; + i++, pPortAttr = pPortAttr->Next ) + { + // Traps disabled by default, Trap settings are all zero + // BKey, BKeyProtect, BKeyViolations, and BKeyLease all init to zero + pDevInfo->Port[i].Guid = pPortAttr->GUID; + } + + MemoryDeallocate(CaAttributes.PortAttributesList); + + // Success, add this CA to the list + SpinLockAcquire( &g_BmaGlobalInfo->DevListLock ); + pDevInfo->Next = g_BmaGlobalInfo->DevList; + g_BmaGlobalInfo->DevList = pDevInfo; + SpinLockRelease( &g_BmaGlobalInfo->DevListLock ); + } + else + { + _DBG_ERROR(("MemAlloc failed for Port List!\n")); + status = FINSUFFICIENT_MEMORY; + } + } + else + { + _DBG_ERROR(("CA Query Failed!\n")); + MemoryDeallocate(pDevInfo); + } + } + else + { + _DBG_ERROR(("MemAlloc failed for pDevInfo!\n")); + status = FINSUFFICIENT_MEMORY; + } + } + + _DBG_LEAVE_LVL(_DBG_LVL_MAIN); + + return status; + +} // BmaAddDevice() + + +////////////////////////////////////////////////////////////////////////// +// BmaRemoveDevice() +// +// This routine is called once for every CA device being removed. Nothing +// is performed in this function. All cleanup is performed in the BmaUnload +// function. +// +// INPUTS: +// CaGuid - the channel adapters GUID +// Context - driver defined unique context for this CA +// +// OUTPUTS: +// +// None. +// +// RETURNS: +// +// FSUCCESS - Indicates a successful initialization. +// +// +FSTATUS +BmaRemoveDevice( + IN EUI64 CaGuid, + IN void *Context + ) +{ + FSTATUS status = FSUCCESS; + BMA_DEV_INFO *pDevInfo=NULL; + + _DBG_ENTER_LVL(_DBG_LVL_MAIN, BmaRemoveDevice); + + ASSERT(g_BmaGlobalInfo); + + SpinLockAcquire( &g_BmaGlobalInfo->DevListLock ); + pDevInfo = g_BmaGlobalInfo->DevList; + if ( g_BmaGlobalInfo->DevList->CaGuid == CaGuid ) + { + g_BmaGlobalInfo->DevList = pDevInfo->Next; + } + else + { + while ( pDevInfo->Next ) + { + if ( pDevInfo->Next->CaGuid == CaGuid ) + { + BMA_DEV_INFO *Found = pDevInfo->Next; + pDevInfo->Next = Found->Next; + pDevInfo = Found; + break; + } + pDevInfo = pDevInfo->Next; + } + } + SpinLockRelease( &g_BmaGlobalInfo->DevListLock ); + + if (pDevInfo && pDevInfo->CaGuid == CaGuid) + { + MemoryDeallocate( pDevInfo->Port ); + MemoryDeallocate( pDevInfo ); + } + else + { + _DBG_ERROR(("Unable to find Ca with GUID 0x%"PRIx64"\n", CaGuid)); + status = FERROR; + } + + _DBG_LEAVE_LVL(_DBG_LVL_MAIN); + + return status; + +} // BmaRemoveDevice() diff --git a/IbAccess/Common/Ibt/Bma/bmamain.h b/IbAccess/Common/Ibt/Bma/bmamain.h new file mode 100644 index 0000000..a5667af --- /dev/null +++ b/IbAccess/Common/Ibt/Bma/bmamain.h @@ -0,0 +1,259 @@ +/* BEGIN_ICS_COPYRIGHT4 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT4 ****************************************/ +/* [ICS VERSION STRING: unknown] */ + +#ifndef _IBA_IB_BMA_MAIN_H_ +#define _IBA_IB_BMA_MAIN_H_ + + +#include "datatypes.h" +#include "ib_types.h" +#include "ib_debug_osd.h" +#include "vpi_export.h" +#include "ib_gsi.h" +#include "ib_ibt.h" +#include "ib_mad.h" +#include "ib_generalServices.h" +#include "vca_export.h" +#include "statustext.h" +#include "ispinlock.h" +#include "ilist.h" +#include "icmdthread.h" +#include "ibyteswap.h" +#include "ib_bm.h" +#include "imemory.h" +#include "gsadebug.h" +#if defined(_DBG_LVL_PKTDUMP) +/* We want to use the _DBG_LVL_PKTDUMP for sma and not gsa */ +#undef _DBG_LVL_PKTDUMP +#endif +#include "smadebug.h" +#include "gsamain.h" +#include "smamain.h" + +#ifdef __cplusplus +extern "C" { +#endif + +// +// Definitions +// + +#define BMA_TAG MAKE_MEM_TAG(B,m,a,M) + +#define BMA_MAX_NDGRM 128 + +// +// Performance management data structures and definitions. +// + +typedef void +(*BMA_SEND_CALLBACK)( + IN void *ServiceContext, + IN IBT_DGRM_ELEMENT *DgrmList + ); + +typedef FSTATUS +(*BMA_RECEIVE_CALLBACK)( + IN void *ServiceContext, + IN IBT_DGRM_ELEMENT *DgrmList + ); + +// +// GSA_GLOBAL_INFO +// +// This structure is used to keep track of global information and tie the +// various lists maintained into meaningful related entities. There is only +// one instance of this structure per the whole of GSA activeCAlist is used +// to link the list of all CA's in the system. Every time a CA is added, a +// new CA structure is created and linked to the end of this field in a +// LIFO fashion. +// +// calock is used to guard access to the above list ( activeCAlist ). +// +// activeserviceclasslist is used to link the list of all registered service +// classes. Every time a unique service class is registered, a service class +// registration record ( GSA_SERVICE_CLASS_INFO ) is created and linked to +// this list in a LIFO fashion. +// +// activeserviceclasslistlock is used to guard access to the list of service +// classes ( activeserviceclasslist ). +// +// uinumberofcas is the number of cas in the list ActiveCAList. +// if binitsuccess is set to TRUE, it means that GSA was successful in +// initializing properly ( one-time initialization ). +// The interfaces of GSA MUST check this state before providing any +// useful functionality. +// if FALSE, GSA services are not available. +// +// ConfigParam contains the list of configuration parameters used to configure +// GSA. These values might be read from registry or from local configuration +// file(s) , depending on the platform we are running on. +// +// +typedef struct _BMA_GLOBAL_INFO +{ + + void* GsaHandle; // Handle for Device Management Class service with GSA + + boolean binitsuccess; + + IB_HANDLE DgrmPoolHandle; + + CMD_THREAD RecvThread; + + struct _BMA_DEV_INFO * DevList; + + unsigned NumCA; + + SPIN_LOCK DevListLock; + +} BMA_GLOBAL_INFO; + +// +// Per-device info +// +typedef struct _BMA_DEV_INFO +{ + struct _BMA_DEV_INFO * Next; + + struct _BMA_PORT_INFO * Port; + + unsigned NumPorts; + + EUI64 CaGuid; + +} BMA_DEV_INFO; + + +// +// Per-port info +// +typedef struct _BMA_PORT_INFO +{ + EUI64 Guid; + // trap settings + struct { + IB_GID GID; + uint32 TClass : 8; + uint32 SL : 4; + uint32 FlowLabel : 20; + uint16 LID; + uint16 P_Key; + uint32 HopLimit : 8; + uint32 QP : 24; + uint32 Q_Key; + } Trap; + uint64 BKey; + boolean BKeyProtect; + uint16 BKeyViolations; + uint16 BKeyLease; +} BMA_PORT_INFO; + +// +// extern declaration for our global information structure +// +#ifndef g_BmaGlobalInfo +extern BMA_GLOBAL_INFO *g_BmaGlobalInfo; +#endif + +typedef struct _BMA_GLOBAL_CONFIG_PARAMETERS +{ + uint32 MaxNDgrm; +} BMA_GLOBAL_CONFIG_PARAMETERS; + +#define BMA_DEFAULT_SETTINGS { BMA_MAX_NDGRM } + +#ifndef g_BmaSettings +extern BMA_GLOBAL_CONFIG_PARAMETERS g_BmaSettings; +#endif + + +// +// Function declarations +// +// bmamain.c +FSTATUS +BmaLoad( + IN IBT_COMPONENT_INFO *ComponentInfo + ); + +void +BmaUnload(void); + +FSTATUS +BmaAddDevice( + IN EUI64 CaGuid, + OUT void **Context + ); + +FSTATUS +BmaRemoveDevice( + IN EUI64 CaGuid, + IN void *Context + ); + +// bmacallb.c + +void +BmaSendCallback( + void *ServiceContext, + IBT_DGRM_ELEMENT *pDgrmList + ); + +void +BmaFreeCallback( + IN void* Context, + IN void* Cmd + ); + +void +BmaThreadCallback( + IN void* Context, + IN void* Cmd + ); + +FSTATUS +BmaRecvCallback( + void *ServiceContext, + IBT_DGRM_ELEMENT *pDgrmList + ); + +FSTATUS +BmaProcessDevMgmtGet( + PDM_MAD pMad, + IBT_DGRM_ELEMENT *pRecvDgrm, + IBT_DGRM_ELEMENT *pSendDgrm + ); + +#ifdef __cplusplus +} +#endif + +#endif // _IBA_IB_BMA_MAIN_H_ diff --git a/IbAccess/Common/Ibt/Cm/APM.Design.txt b/IbAccess/Common/Ibt/Cm/APM.Design.txt new file mode 100644 index 0000000..a79eaff --- /dev/null +++ b/IbAccess/Common/Ibt/Cm/APM.Design.txt @@ -0,0 +1,372 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +#[ICS VERSION STRING: unknown] +Initial cut, no support for reloading path, just for load a new Alt path +when in Migrated + +Inbound LAP would be in a dgrm? No need to copy til accept? + +in cep: + PrimaryPath + AlternatePath + +CmMigrated(cep) // path has migrated, later hook directly to Async event callback + // CMS_LAP_RCVD, CMS_LAP_SENT do not have a valid alt path + if cep->State != FCM_CONNECT_ESTABLISHED + FINVALID_STATE // race of migration with LAP may have occurred + if cep->AlternatePath.lid == 0 + FINVALID_STATE + cep->PrimaryPath = cep->AlternatePath + clear cep->AlternatePath + recompute CM timeouts using new PrimaryPath's PktLifeTime + adjust remote path for future dgrms to use new primary + + +Active Side: + +CmConnect + save PrimaryPath and AlternatePath to CEP from REQ + +CmAltPathRequest(cep, Info.Lap) + if Info.AlternatePath == cep->PrimaryPath + FINVALID_ARGUMENTS or other error + // Note State==LAP_SENT invalid case, must complete present exchange + if State != CMS_CONNECT_ESTABLISHED + FINVALID_STATE + if ! APM available from REP (Rep->FailoverAccepted=1) + error + if Mode != ACTIVE + FINVALID_STATE + TBD disable allowing reload of path to avoid races??? (fail if AltValid?) + if cep->AlternatePath.lid != 0 + error // reload of path case + verify alternate path - SGID on same Ca, SGidIndex valid, PKey Valid + error if not + SendLAP + move to CMS_LAP_SENT + clear retry counter + start LAP timer + +ProcessApr + case CMS_LAP_SENT, CMS_MRA_LAP_RCVD + ASSERT Mode == ACTIVE + if APStatus == 0 + cep->AlternatePath = AlternatePath from cep->pDgrmElement->LAP + save APR Dgrm (prepareDgrm, DgrmCopyAddrAndMad) to cep->pDgrmElement + stop timer + move to FCM_CONNECT_ESTABLISHED + set notify CME_RCVD_APR + other states + discard + +ProcessMraLap + case CMS_LAP_SENT + State = MRA_LAP_RCVD + restart timer + case MRA_LAP_RCVD + discard + other states + discard + +TimerCallback + case CMS_LAP_SENT/MRA_LAP_RCVD + resend LAP, retry count + if retry exceeded + move to CMS_CONNECT_ESTABLISHED + set CME_TIMEOUT_LAP + + +Other aspects of LAP_SENT/MRA_LAP_RCVD + DREQ, CmCancel, CmDisconnect processed same as CONNECT_ESTABLISHED + CmAltPathReply - not allowed, FINVALID_STATE + CmGetConnInfo - error + CmMigrated - error + cep->AlternatePath.lid == 0 in this state + if get a REP and need to resend RTU, send one with no private data + - Dgrm for send was replaced with LAP Dgrm + - must still keep LAP Dgrm as cep->pDgrmElement for LAP retries + + +Passive Side: + +ProcessReq + reverse sense and save PrimaryPath and AlternatePath to CEP from REQ + +CmAltPathReply(Info.Apr) + case CMS_LAP_RCVD + if APR.Status == 0 + cep->AlternatePath = Path in pCEP->pDgrmElement->LAP + SendAPR + cep->State = FCM_CONNECT_ESTABLISHED + +CmGetConnInfo + case CMS_LAP_RCVD: + if CME_RCVD_LAP + ASSERT(cep->Mode == PASSIVE) + Copy into Info.Lap (inbound LAP in pCEP->pDgrmElement) + return FCM_ALTPATH_REQUEST + case CMS_CONNECT_ESTABLISHED: + if CME_RCVD_APR + ASSERT(cep->Mode == ACTIVE) + // AltPath returned for convenience of appl + if Info.Apr.APStatus == 0 + Copy into Info.Apr (inbound APR and cep->AlternatePath) + return FCM_ALTPATH_REPLY + else + Copy into Info.Apr (inbound APR) // AlternatePath not avail + return FCM_ALTPATH_REJECT + if CME_TIMEOUT_LAP // should we disconnect when this happens? + ASSERT(cep->Mode == ACTIVE) + return FCM_ALTPATH_TIMEOUT + +ProcessLap + case CMS_CONNECT_ESTABLISHED + if Mode != PASSIVE + discard (or REJ?) + if ! APM available from REP (Rep->FailoverAccepted=1) + REJ + if LAP->AlternatePath == cep->PrimaryPath + REJ + if LAP->AlternatePath == cep->AlternatePath + APR it, no callback (duplicate) + reverse path for response + TBD disable allowing reload of path to avoid races??? (fail if AltValid?) + if cep->AlternatePath.lid != 0 + REJ + verify alternate path - SGID on same Ca, SGidIndex valid, PKey Valid + error if not + // hang onto LAP + PrepareCepDgrm + DgrmCopyAddrAndMad(pCep->pDgrmElement, pMad, pRemoteDgrm); + state = CMS_LAP_RCVD + notify CME_RCVD_LAP + // no provision for MRA of LAP, but throughout code treat + // MRA_LAP_SENT as LAP_RCVD + case LAP_RCVD + ASSERT Mode == PASSIVE + if LAP->AlternatePath == cep->PrimaryPath + REJ + if LAP matches pCep->pDgrmElement->LAP + APR it, no callback (duplicate) + reverse path for response + REJ + ?? or disconnect? slow APR vs new LAP issue + other states + discard + +Other aspects of LAP_RCVD/MRA_LAP_SENT + DREQ, CmCancel, CmDisconnect processed same as CONNECT_ESTABLISHED + CmAltPathReply - used to accept/reject LAP, see other notes + CmGetConnInfo - CME_RCVD_LAP, otherwise same as CONNECT_ESTABLISHED + CmMigrated - ? error + cep->AltPathValid always 0 in this state + +Sequences: + Server Client + <--- LAP + APR ---> lost + <---- LAP retries + APR ----------------> +duplicate LAP receipt must resend APR, cep stays connected + + + <--- LAP + APR ---> slow + <---- LAP retry + APR ----------------> +get 2nd APR, client must discard + +broken for delayed APR, no way to identify if APR correlated to LAP +(all CM messages for a given CEP use same transaction ID) + <--- LAP1 + APR1 ---> slow + <---- LAP1 retry + APR1 ----------------> <---- LAP2 + APR1 mistaken as APR for LAP2 +Resolution: do not allow an alterate path to be replaced, require a +migrated event before hand. This is not a complete resolution, but will +make this a less likely timing window + +broken for delayed APR, no way to identify if APR correlated to LAP +(all CM messages for a given CEP use same transaction ID) + <--- LAP1 + APR1 ---> very slow + <---- LAP1 retry exceeded, timeout + <---- LAP2 + APR1 mistaken as APR for LAP2 +Resolution: treate timeout as indication server does not support APM + +Basic Sequences: +load new path (valid if don't have (Migrated) present alt path): + Server Client + CmLoadAltPath + <--- LAP + FCM_ALTPATH_REQUEST + if good + QpModify, new alt path, Rearm + CmAltPathReply, good status + APR ---> + FCM_ALTPATH_REPLY + QpModify, new alt path, Rearm + +Reject new path: + Server Client + CmLoadAltPath + <--- LAP + FCM_ALTPATH_REQUEST + if not good + CmAltPathReply, bad status + APR/Error ---> + FCM_ALTPATH_REJECT + // leave QP w/no alt path + +Timeout new path: + Server Client + CmLoadAltPath + <--- LAP + no response or lost LAP + FCM_ALTPATH_TIMEOUT + // leave QP w/no alt path + We cannot match a late APR with proper LAP. + ???timeout may need to be a disconnect situation? + +Migrate: + Server Client + QP handshake ---> <---- QP handshake + Async Event callback Async Event callback + CmMigrated CmMigrated + After migrated, neither side has a valid alternate path + future CM messages will use new PrimaryPath (and its timeouts) + ?? does kernel get callbacks for all QPs (user and kernel) + if so we could hook Async Event now quite easily + +Situtations to review: + Must allow load of new alternate path even if present altpath one is valid + - migrated while LAP in progress + ? more interaction with CmMigrated? + how is arm/rearm/migrated QP states interact + what if LAP/APR retries in progress before or after migrate + what path to use if LAP in progress or does QPModify make + alt path invalid until LAP sequence completed + <-- LAP + <--- CmMigrated + APR ----> + CmMigrated ---> + Migrated beats APR to client? Which alt path is used? Or should + QpModify be used by appl prior to LAP to invalidate AltPath + while negotiate a new one + + <--LAP + CmMigrated --> + APR ---> + If QpModify prior to LAP made alt path invalid, migrated could + not occur after LAP. Don't allow CmMigrated call if + !AltPathValid + + <-- LAP + APR --> lost + CmMigrated --> + + Check QP maybe if: + Server Client + QpModify, new alt path, disable migration + CmLoadAltPath + <--- LAP + FCM_ALTPATH_REQUEST + if good + QpModify, new alt path + CmAltPathReply, good status + APR ---> + else + QpModify, no alt path + CmAltPathReply, bad status + APR/error --> + FCM_ALTPATH_REPLY + QpModify, enable migration + provided QP handshake occurs for migration, above would + prevent migrated from occuring during LAP sequence + failure of LAP on client would leave QP w/o migration enabled + cep->AltValid cleared on LAP send/receipt + cep->AltValid set on APR send/receipt (or in REQ/REP w/alt) + + - decision to propose a new alt path while LAP in progress + - esp is active side timed out and passive has LAP queued waiting + callback to CmAltPathReply it + +Old Basic Sequences: +load new path (valid if have or don't have present alt path): + Server Client + QpModify, new alt path, disable migration + CmLoadAltPath + <--- LAP + FCM_ALTPATH_REQUEST + if good + QpModify, new alt path + CmAltPathReply, good status + APR ---> + FCM_ALTPATH_REPLY + QpModify, enable migration + +Reject new path: + Server Client + QpModify, new alt path, disable migration + CmLoadAltPath + <--- LAP + FCM_ALTPATH_REQUEST + if not good + QpModify, no alt path + CmAltPathReply, bad status + APR/error ---> + FCM_ALTPATH_REJECT + // leave QP w/migration disabled + +Timeout new path: + Server Client + QpModify, new alt path, disable migration + CmLoadAltPath + <--- LAP + no response or lost LAP + FCM_ALTPATH_TIMEOUT + // leave QP w/migration disabled + Note, late APR would be discarded by client. + What if APR was way late and client had a new LAP in progress? + Can we match APR exactly to a LAP to ensure don't treat late + APR as a match for newer LAP? If not, timeout may need to + be a disconnect situations? + +Migrate: + Server Client + QP handshake ---> <---- QP handshake + Async Event callback Async Event callback + CmMigrated CmMigrated + After migrated, neither side has a valid alternate path + future CM messages will use new PrimaryPath (and its timeouts) + ?? does kernel get callbacks for all QPs (user and kernel) + if so we could hook Async Event now quite easily diff --git a/IbAccess/Common/Ibt/Cm/CM_notes.txt b/IbAccess/Common/Ibt/Cm/CM_notes.txt new file mode 100644 index 0000000..d655f41 --- /dev/null +++ b/IbAccess/Common/Ibt/Cm/CM_notes.txt @@ -0,0 +1,106 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +#[ICS VERSION STRING: unknown] +CM_notes.txt + +Build label "Cm062201" +---------------------- + +- Clarified size of struct member field using bitfield length. +Remove Reserved fields and packing requirement. + +- Added code to handle comm established event on RQ (-D_CM_EVENT_ON_QP_). + +- Allow upto 92 bytes and private data offset for discriminator matching (ModifyCEP()). + +- Fixed SendSIDR_RESP() copy private data. + +- Fixed FormatRTU() to access RTU struct instead of DREQ + +- Cleanup SIDR_REQ_INFO. Removed unnecessary fields. + +- Added more printout + + +Build label "Cm062501" +---------------------- + +- Allow the SID namespace to be reuse within the port namespace i.e. +2 instances of the service can listen on the same SID +but different port LID/GID. CaGuid must be specified. + +- RequestMatch() simplify listen/peer request matching + +- Fixed rounding up in TimeoutTimeToMult() + +- Cleanup printout in ProcessMadCallback() + + +Build label "Cm062701" +---------------------- +- Fixed #8819. Use DListIterate() instead of while loop. Do not destroy the cep +object since the user may have reference to it. +- Destroyed the spinlock during CmDestroy() +- Initialized the global event obj before usage in CmWait() + + +Build label "Cm062801" or "TSL3_5" +---------------------- +- CmDeviceDestroy() - set the next ptr to prev only when entry is removed. Also, +we cannot just remove the obj, we must either cancel, disconnect or ignore it. +- CancelP() - wrong list +- CmDestroy() - No need to walk thru the lists. This is done in CmDeviceDestroy() +- CancelA() - Added CMS_SIDR_REQ_SENT case + + +Build label "Cm070901" +---------------------- +- CmDestroy() - Undo the change in prev label. Walk thru all the lists and destroy the cep obj. +- CmDestroy() - Must wait for all callbacks to return. Move DgrmDestroyPool() to here from CmDeviceDestroy() +- CancelA() - Allow cancel operation in CMS_DREQ_SENT, CMS_DREQ_RCVD and CMS_TIMEWAIT states +- CmSystemCallback() - Check if cep obj is marked for destruction before callback + + +Build label "Cm071101" +---------------------- +- During device removal, call user callback with FCM_DISCONNECTED status when connections are established already. Move code from CancelA() to ShutdownA(). +Added SYSE_DISCONNECT event + + +Build label "Cm072401" +---------------------- +- Added code to handle MRA msg + + +TTD +--- + +Check CaGUID is specified when port addr is specified +Make callbackrefcnt a more generic version to include handle refcnt diff --git a/IbAccess/Common/Ibt/Cm/CM_readme.txt b/IbAccess/Common/Ibt/Cm/CM_readme.txt new file mode 100644 index 0000000..ca7d377 --- /dev/null +++ b/IbAccess/Common/Ibt/Cm/CM_readme.txt @@ -0,0 +1,39 @@ +IBA SDK3 Communication Manager(CM) Component Release Notes +____________________________________________________________________ + + + +A) VERSION NOTES +____________________________________________________________________ +SDK3 + + +B) FEATURES +____________________________________________________________________ +The CM component is implemented according to IB spec 1.0A. +It supports both client/server and peer-to-peer connection +models. It also support Service ID Resolution (SIDR) protocol. +The CM can be accessed via user-mode or kernel-mode. +The CM supports all required messages (REQ, REP, REJ..) defined in IB spec +including SIDR messages. The optional LAP and APR messages are not supported. + +C) KNOWN ISSUES +____________________________________________________________________ +VIPL has reported seeing connection callback delays on Saber-RX system. Please +consult VIPL notes to workaround this issue. + +VIPL has reported seeing CmCreateCEP() fail on multiple adapters environment. +There is no resolution at this point other than a reboot. + +SIDR Query timing out. Increase the SidrReqTimeoutMs registry value. + + +D) GENERAL NOTES +____________________________________________________________________ +The CM component is part of the IBT driver stack. The CM can be accessed directly via the CM API. + + +E) INSTALLATION NOTES +____________________________________________________________________ +The CM component is installed as part of the IBT driver stack. No additional +installation is required. diff --git a/IbAccess/Common/Ibt/Cm/Cm.dsp b/IbAccess/Common/Ibt/Cm/Cm.dsp new file mode 100644 index 0000000..2b725dd --- /dev/null +++ b/IbAccess/Common/Ibt/Cm/Cm.dsp @@ -0,0 +1,63 @@ +# Microsoft Developer Studio Project File - Name="Cm" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Generic Project" 0x010a + +CFG=Cm - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "Cm.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "Cm.mak" CFG="Cm - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "Cm - Win32 Release" (based on "Win32 (x86) Generic Project") +!MESSAGE "Cm - Win32 Debug" (based on "Win32 (x86) Generic Project") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +MTL=midl.exe + +!IF "$(CFG)" == "Cm - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Target_Dir "" + +!ELSEIF "$(CFG)" == "Cm - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Cm___Win32_Debug" +# PROP BASE Intermediate_Dir "Cm___Win32_Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "" +# PROP Intermediate_Dir "" +# PROP Target_Dir "" + +!ENDIF + +# Begin Target + +# Name "Cm - Win32 Release" +# Name "Cm - Win32 Debug" +# End Target +# End Project diff --git a/IbAccess/Common/Ibt/Cm/Cm.dsw b/IbAccess/Common/Ibt/Cm/Cm.dsw new file mode 100644 index 0000000..e346d20 --- /dev/null +++ b/IbAccess/Common/Ibt/Cm/Cm.dsw @@ -0,0 +1,77 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "Cm"=.\Cm.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "Cmkernel"=.\Cmkernel.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "Cmlib"=.\Cmlib.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "Cmtest"=..\..\..\WinUser\Ibt\Cm\Cmtest\Cmtest.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "Cmuser"=.\Cmuser.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/IbAccess/Common/Ibt/Cm/Cmkernel.dsp b/IbAccess/Common/Ibt/Cm/Cmkernel.dsp new file mode 100644 index 0000000..cbc8f00 --- /dev/null +++ b/IbAccess/Common/Ibt/Cm/Cmkernel.dsp @@ -0,0 +1,95 @@ +# Microsoft Developer Studio Project File - Name="Cmkernel" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Generic Project" 0x010a + +CFG=Cmkernel - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "Cmkernel.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "Cmkernel.mak" CFG="Cmkernel - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "Cmkernel - Win32 Release" (based on "Win32 (x86) Generic Project") +!MESSAGE "Cmkernel - Win32 Debug" (based on "Win32 (x86) Generic Project") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +MTL=midl.exe + +!IF "$(CFG)" == "Cmkernel - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Target_Dir "" + +!ELSEIF "$(CFG)" == "Cmkernel - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Cmkernel___Win32_Debug" +# PROP BASE Intermediate_Dir "Cmkernel___Win32_Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "" +# PROP Intermediate_Dir "" +# PROP Target_Dir "" + +!ENDIF + +# Begin Target + +# Name "Cmkernel - Win32 Release" +# Name "Cmkernel - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "*.c" +# Begin Source File + +SOURCE=..\..\..\Win2K\Ibt\Cm\cm_common.c +# End Source File +# Begin Source File + +SOURCE=..\..\..\Win2K\Ibt\Cm\cm_kernel.c +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "*.h" +# Begin Source File + +SOURCE=..\..\..\Win2K\Ibt\Cm\cm_ioctl.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Win2K\Ibt\Cm\cm_kernel.h +# End Source File +# End Group +# Begin Source File + +SOURCE=..\..\..\Win2K\Ibt\Cm\makefile +# End Source File +# Begin Source File + +SOURCE=..\..\..\Win2K\Ibt\Cm\sources +# End Source File +# End Target +# End Project diff --git a/IbAccess/Common/Ibt/Cm/Cmlib.dsp b/IbAccess/Common/Ibt/Cm/Cmlib.dsp new file mode 100644 index 0000000..5d149a5 --- /dev/null +++ b/IbAccess/Common/Ibt/Cm/Cmlib.dsp @@ -0,0 +1,123 @@ +# Microsoft Developer Studio Project File - Name="Cmlib" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Generic Project" 0x010a + +CFG=Cmlib - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "Cmlib.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "Cmlib.mak" CFG="Cmlib - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "Cmlib - Win32 Release" (based on "Win32 (x86) Generic Project") +!MESSAGE "Cmlib - Win32 Debug" (based on "Win32 (x86) Generic Project") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +MTL=midl.exe + +!IF "$(CFG)" == "Cmlib - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Target_Dir "" + +!ELSEIF "$(CFG)" == "Cmlib - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "" +# PROP Intermediate_Dir "" +# PROP Target_Dir "" + +!ENDIF + +# Begin Target + +# Name "Cmlib - Win32 Release" +# Name "Cmlib - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "*.c" +# Begin Source File + +SOURCE=.\cm_active.c +# End Source File +# Begin Source File + +SOURCE=.\cm_api.c +# End Source File +# Begin Source File + +SOURCE=.\cm_gsa.c +# End Source File +# Begin Source File + +SOURCE=.\cm_msg.c +# End Source File +# Begin Source File + +SOURCE=.\cm_passive.c +# End Source File +# Begin Source File + +SOURCE=.\cm_test.c +# End Source File +# Begin Source File + +SOURCE=.\sidr_api.c +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "*.h" +# Begin Source File + +SOURCE=.\cm_common.h +# End Source File +# Begin Source File + +SOURCE=.\cm_msg.h +# End Source File +# Begin Source File + +SOURCE=.\cm_private.h +# End Source File +# Begin Source File + +SOURCE=..\..\Inc\ib_cm.h +# End Source File +# End Group +# Begin Source File + +SOURCE=.\CM_notes.txt +# End Source File +# Begin Source File + +SOURCE=.\CM_readme.txt +# End Source File +# End Target +# End Project diff --git a/IbAccess/Common/Ibt/Cm/Cmuser.dsp b/IbAccess/Common/Ibt/Cm/Cmuser.dsp new file mode 100644 index 0000000..636a20b --- /dev/null +++ b/IbAccess/Common/Ibt/Cm/Cmuser.dsp @@ -0,0 +1,79 @@ +# Microsoft Developer Studio Project File - Name="Cmuser" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Generic Project" 0x010a + +CFG=Cmuser - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "Cmuser.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "Cmuser.mak" CFG="Cmuser - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "Cmuser - Win32 Release" (based on "Win32 (x86) Generic Project") +!MESSAGE "Cmuser - Win32 Debug" (based on "Win32 (x86) Generic Project") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +MTL=midl.exe + +!IF "$(CFG)" == "Cmuser - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Target_Dir "" + +!ELSEIF "$(CFG)" == "Cmuser - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Target_Dir "" + +!ENDIF + +# Begin Target + +# Name "Cmuser - Win32 Release" +# Name "Cmuser - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "*.c" +# Begin Source File + +SOURCE=..\..\..\WinUser\Ibt\Cm\cm_user.c +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "*.h" +# Begin Source File + +SOURCE=..\..\..\WinUser\Ibt\Cm\cm_user.h +# End Source File +# End Group +# End Target +# End Project diff --git a/IbAccess/Common/Ibt/Cm/README b/IbAccess/Common/Ibt/Cm/README new file mode 100644 index 0000000..f95e20e --- /dev/null +++ b/IbAccess/Common/Ibt/Cm/README @@ -0,0 +1,3 @@ +Communications Manager + +Performs connection establishment protocol for IB's RC QPs diff --git a/IbAccess/Common/Ibt/Cm/cm_active.c b/IbAccess/Common/Ibt/Cm/cm_active.c new file mode 100644 index 0000000..296278e --- /dev/null +++ b/IbAccess/Common/Ibt/Cm/cm_active.c @@ -0,0 +1,2087 @@ +/* BEGIN_ICS_COPYRIGHT4 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT4 ****************************************/ + +// Public header file +#include "ib_cm.h" + +// Private header file +#include "cm_private.h" + + + +////////////////////////////////////////////////////////////////////////// +// Connect +// +// This routine is called by CmConnect() and CmConnectPeer() +// +// INPUTS: +// +// +// +// OUTPUTS: +// +// None. +// +// RETURNS: +// +// FSUCCESS. +// +// IRQL: +// +// This routine is called at IRQL_PASSIVE_LEVEL with ListLock held +// +FSTATUS +Connect( + CM_CEP_OBJECT* pCEP, + const CM_REQUEST_INFO* pConnectRequest, + boolean bPeer, // TRUE if peer connect, FALSE otherwise + PFN_CM_CALLBACK pfnConnectCB, + void* Context + ) +{ + FSTATUS Status=FSUCCESS; + IB_PORT_ATTRIBUTES *pPortAttr=NULL; + uint32 pktlifetime=0; + uint64 pktlifetime_us=0; + uint32 req_timeout_ms=0; + uint64 turnaround_time_us; + IB_CA_ATTRIBUTES *pCaAttr = NULL; + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, Connect); + + DEBUG_ASSERT(pCEP->State == CMS_IDLE); + if (pCEP->State != CMS_IDLE) + { + _DBG_ERROR((" invalid State for Connect!!! <%d>\n", + _DBG_PTR(pCEP), pCEP->State)); + Status = FINVALID_PARAMETER; + goto fail_type; + } + + if (pCEP->Type != CM_RC_TYPE + && pCEP->Type != CM_UC_TYPE + && pCEP->Type != CM_RD_TYPE + ) + { + _DBG_WARN((" invalid Type for Connect!!! <%d>\n", + _DBG_PTR(pCEP), pCEP->Type)); + Status = FINVALID_PARAMETER; + goto fail_type; + } + if (pConnectRequest->CEPInfo.QPN == 0 + && pConnectRequest->CEPInfo.LocalEECN == 0) + { + _DBG_WARN((" invalid QPN/EECN for Connect!!! \n", + _DBG_PTR(pCEP))); + Status = FINVALID_PARAMETER; + goto fail_type; + } + if (pConnectRequest->SID == 0) + { + _DBG_WARN((" invalid SID for Connect!!! <%"PRIx64">\n", + _DBG_PTR(pCEP), pConnectRequest->SID)); + Status = FINVALID_PARAMETER; + goto fail_type; + } + // Set up addressing information + pCEP->LocalEndPoint.CaGUID = pConnectRequest->CEPInfo.CaGUID; + pCEP->bPeer = bPeer; + + // Set up Bind address, especially important for Peer connect + // which will end up on ListenMap which is keyed by + // SID, Local&Remote LID&GID, EndPoint and Private Data Discriminator + + pCEP->SID = pConnectRequest->SID; + + CopyPathInfoToCepPath(&pCEP->PrimaryPath, &pConnectRequest->PathInfo, + pConnectRequest->CEPInfo.AckTimeout); + Status = iba_find_ca_gid2(&pConnectRequest->PathInfo.Path.SGID, + pConnectRequest->CEPInfo.CaGUID, + &pCEP->PrimaryPath.LocalPortGuid, + &pCEP->PrimaryPath.LocalGidIndex, &pPortAttr, + &pCaAttr); + if (Status != FSUCCESS) + { + _DBG_WARN((" FindCaGid() failed!!! <%s>\n", + _DBG_PTR(pCEP), _DBG_PTR(FSTATUS_MSG(Status)))); + Status = FINVALID_PARAMETER; + goto fail_port; + } + // as a safety feature we quietly downgrade the RDMA Read resources to + // match the CA capabilities + if (pCEP->Type == CM_RC_TYPE) { + pCEP->LocalInitiatorDepth = MIN(pCaAttr->MaxQPInitiatorDepth, + pConnectRequest->CEPInfo.OfferedInitiatorDepth); + pCEP->LocalResponderResources = MIN(pCaAttr->MaxQPResponderResources, + pConnectRequest->CEPInfo.OfferedResponderResources); + } else if (pCEP->Type == CM_RD_TYPE) { + pCEP->LocalInitiatorDepth = MIN(pCaAttr->MaxEECInitiatorDepth, + pConnectRequest->CEPInfo.OfferedInitiatorDepth); + pCEP->LocalResponderResources = MIN(pCaAttr->MaxEECResponderResources, + pConnectRequest->CEPInfo.OfferedResponderResources); + } else { + pCEP->LocalInitiatorDepth = 0; + pCEP->LocalResponderResources = 0; + } + if (! LookupPKey(pPortAttr, pConnectRequest->PathInfo.Path.P_Key, FALSE, &pCEP->PrimaryPath.PkeyIndex)) + { + _DBG_WARN((" LookupPKey() failed!!!\n", _DBG_PTR(pCEP))); + Status = FINVALID_PARAMETER; + goto fail_port; + } + pCEP->PrimaryPath.LocalPathBits = LidToPathBits(pCEP->PrimaryPath.LocalLID, pPortAttr->Address.LMC); + MemoryDeallocate(pPortAttr); + pPortAttr = NULL; + + if (pConnectRequest->AlternatePathInfo.Path.SLID != 0) + { + if (pConnectRequest->PathInfo.Path.P_Key + != pConnectRequest->AlternatePathInfo.Path.P_Key) + { + Status = FINVALID_PARAMETER; + goto fail_port; + } + CopyPathInfoToCepPath(&pCEP->AlternatePath, &pConnectRequest->AlternatePathInfo, + pConnectRequest->CEPInfo.AlternateAckTimeout); + Status = iba_find_ca_gid(&pConnectRequest->AlternatePathInfo.Path.SGID, + pConnectRequest->CEPInfo.CaGUID, + &pCEP->AlternatePath.LocalPortGuid, + &pCEP->AlternatePath.LocalGidIndex, &pPortAttr, NULL); + if (Status != FSUCCESS) + { + _DBG_WARN((" Alternate FindCaGid() failed!!! <%s>\n", + _DBG_PTR(pCEP), _DBG_PTR(FSTATUS_MSG(Status)))); + Status = FINVALID_PARAMETER; + goto fail_port; + } + if (! LookupPKey(pPortAttr, pConnectRequest->AlternatePathInfo.Path.P_Key, FALSE, &pCEP->AlternatePath.PkeyIndex)) + { + _DBG_WARN((" Alternate LookupPKey() failed!!!\n", + _DBG_PTR(pCEP))); + Status = FINVALID_PARAMETER; + goto fail_port; + } + pCEP->AlternatePath.LocalPathBits = LidToPathBits(pCEP->AlternatePath.LocalLID, pPortAttr->Address.LMC); + MemoryDeallocate(pPortAttr); + pPortAttr = NULL; + } else { + MemoryClear(&pCEP->AlternatePath, sizeof(pCEP->AlternatePath)); + } + + pCEP->Mtu = pConnectRequest->PathInfo.Path.Mtu; + pCEP->PartitionKey = pConnectRequest->PathInfo.Path.P_Key; + + pCEP->TargetAckDelay = pCaAttr->LocalCaAckDelay; // best guess to start + + MemoryDeallocate(pCaAttr); + pCaAttr = NULL; + + // save info for later + pCEP->LocalRetryCount = pConnectRequest->CEPInfo.RetryCount; + pCEP->LocalRecvPSN= pConnectRequest->CEPInfo.StartingPSN; + + // Bind the local endpoint addr to the object + pCEP->LocalEndPoint.QPN = pConnectRequest->CEPInfo.QPN; + pCEP->LocalEndPoint.EECN = pConnectRequest->CEPInfo.LocalEECN; + + pCEP->RemoteEndPoint.QPN = pCEP->RemoteEndPoint.EECN = 0; + + // make sure LocalEndPoint is unique + if (! CM_MapTryInsert(&gCM->LocalEndPointMap, (uintn)pCEP, + &pCEP->LocalEndPointMapEntry, "LOCAL_END_POINT_LIST", pCEP)) + { + Status = FCM_ADDR_INUSE; + goto fail_endpoint; + } + // For peer connection, put it onto the LISTEN list + // this also makes sure the bound listen address is unique + // Once we associate the CEP with a remote end point, we will remove the CEP + // from the LISTEN list. For the passive end, we will put it onto the + // PENDING list to facilitate CmAccept issuing REP + if (bPeer && ! CM_MapTryInsert(&gCM->ListenMap, (uintn)pCEP, + &pCEP->MapEntry, "LISTEN_LIST", pCEP)) + { + Status = FCM_ADDR_INUSE; + goto fail; + } + + pCEP->EventFlags = 0; + pCEP->RetryCount = 0; + DListInit(&pCEP->PendingList); + + pCEP->Mode = CM_MODE_ACTIVE; + pCEP->bFailoverSupported = TRUE; // assume the best until we know better + + // The comm ID is set here so that each connect request is unique since + // user can reuse the object. This prevents duplicate msg arriving for + // previous connect request using the same object. + AssignLocalCommID(pCEP); + pCEP->TransactionID = (pCEP->LocalCommID)<<8; + _DBG_INFO((" Comm ID set at .\n", + _DBG_PTR(pCEP), pCEP->LocalCommID)); + + pCEP->QKey = pConnectRequest->CEPInfo.QKey; + + pktlifetime = pConnectRequest->PathInfo.Path.PktLifeTime; + if (pktlifetime > 31) + pktlifetime = 31; + pCEP->PktLifeTime = pktlifetime; + pCEP->Timewait = pConnectRequest->CEPInfo.AckTimeout; + if (pCEP->Timewait < pCEP->PktLifeTime+1) + { + // round up Timewait to at least be 2*PktLifeTime + // TBD could add in LocalCaAckDelay and adjust + // AckTimeout as well + pCEP->Timewait = pCEP->PktLifeTime+1; // log2 so +1 is *2 + } + + // Round-trip time in usec + pktlifetime_us = TimeoutMultToTimeInUsec(pktlifetime); + + // turnaround_time_us should include CM and appl software time and + // the hfi hardware Ca Ack Delay + if (pCEP->turnaround_time_us) + { + turnaround_time_us = pCEP->turnaround_time_us; // CEP specific time + } else { + turnaround_time_us = gCM->turnaround_time_us; // use heuristic + } + + // The remote timeout is used by the remote CM to determine if it should + // send an MRA, in theory turnaround_time_us should be anticipated + // turnaround time of remote end. + pCEP->RemoteCMTimeout = TimeoutTimeToMult(turnaround_time_us); + + // The local timeout is used to timeout all waits for responses + // from request packets (REQ, REP, LAP, DREQ), it is the time a remote + // CM can expect our local CM to respond within (including fabric time) + pCEP->LocalCMTimeout = TimeoutTimeToMult(turnaround_time_us + pktlifetime_us*2); + + pCEP->MaxCMRetries = gCmParams.MaxReqRetry; + + _DBG_INFO((" Timeout setting .\n", + _DBG_PTR(pCEP), pCEP->PktLifeTime, pktlifetime_us*2, + turnaround_time_us, pCEP->LocalCMTimeout, pCEP->RemoteCMTimeout)); + + // Save user callback info + pCEP->pfnUserCallback = pfnConnectCB; + pCEP->UserContext = Context; + + // If CEP is being reused, it may have a send still in progress or it + // may not have a Dgrm any longer + if (pCEP->pDgrmElement && CmDgrmIsInUse(pCEP->pDgrmElement)) { + _DBG_INFO((" Releasing the dgrm .\n", + _DBG_PTR(pCEP), _DBG_PTR(pCEP->pDgrmElement))); + CmDgrmSetReleaseFlag(pCEP->pDgrmElement); + pCEP->pDgrmElement = NULL; + } + if (pCEP->pDgrmElement == NULL) + { + pCEP->pDgrmElement = CmDgrmGet(); + if (!pCEP->pDgrmElement) + { + _DBG_WARNING((" Connection attempt failed: Out of CM Dgrms!!!\n", + _DBG_PTR(pCEP))); + Status = FINSUFFICIENT_RESOURCES; + goto fail_dgrm; + } + } + + DEBUG_ASSERT(pCEP->pDgrmElement->Element.pBufferList->ByteCount == MAD_BLOCK_SIZE); + if (pCEP->pDgrmElement->Element.pBufferList->ByteCount != MAD_BLOCK_SIZE) { + _DBG_ERROR((" Disgarding Corrupt Datagram!!! pDgrmElement = %p, pCEP->pDgrmElement->Element.pBufferList = %p, pCEP->pDgrmElement->Element.pBufferList->ByteCount = %d\n", + _DBG_PTR(pCEP), + _DBG_PTR(pCEP->pDgrmElement), + _DBG_PTR(pCEP->pDgrmElement->Element.pBufferList), + pCEP->pDgrmElement->Element.pBufferList->ByteCount)); + Status = FINSUFFICIENT_RESOURCES; + pCEP->pDgrmElement = NULL; + goto fail_dgrm; + } + + // Format the REQ msg + FormatREQ((CM_MAD*)GsiDgrmGetSendMad(pCEP->pDgrmElement), + pConnectRequest, + pCEP->TransactionID, + pCEP->LocalCommID, + QP1_WELL_KNOWN_Q_KEY, + pCEP->Type, + pCEP->LocalCMTimeout, + pCEP->RemoteCMTimeout, + pCEP->MaxCMRetries, + pCEP->LocalInitiatorDepth, + pCEP->LocalResponderResources); + + // Setup the dgrm's dest addr + _DBG_INFO((" REQ's dgrm address field \n", + _DBG_PTR(pCEP), + pCEP->PrimaryPath.LocalPortGuid, + pCEP->PrimaryPath.RemoteLID, + pCEP->PrimaryPath.SL, + pCEP->PrimaryPath.LocalPathBits, + pCEP->PrimaryPath.StaticRate)); + + + CmDgrmAddrSet(pCEP->pDgrmElement, + pCEP->PrimaryPath.LocalPortGuid, + pCEP->PrimaryPath.RemoteLID, + pCEP->PrimaryPath.SL, + pCEP->PrimaryPath.LocalPathBits, + pCEP->PrimaryPath.StaticRate, + (! pCEP->PrimaryPath.bSubnetLocal), + pCEP->PrimaryPath.RemoteGID, + pCEP->PrimaryPath.FlowLabel, + pCEP->PrimaryPath.LocalGidIndex, + pCEP->PrimaryPath.HopLimit, + (uint8)pCEP->PrimaryPath.TClass, + pCEP->PrimaryPath.PkeyIndex); + + // Pass the REQ down to GSA. + // At this point, we may get the send or receive complete callback but the lock + // will prevent nested call. + // Also, we update the state and start the timer here instead of in the send callback + // because we assume the send is done here (i.e. unreliable send) + Status = CmDgrmSend(pCEP->pDgrmElement); + if (Status != FSUCCESS) + { + _DBG_WARN((" DgrmSend() failed for REQ!!! <%s>\n", + _DBG_PTR(pCEP), _DBG_PTR(FSTATUS_MSG(Status)))); + // fall through and let timer retry the send later + Status = FSUCCESS; + } else { + AtomicIncrementVoid(&gCM->Sent.Req); + } + _DBG_INFO((" REQ sent for .\n", + _DBG_PTR(pCEP), pCEP->LocalCommID, + pCEP->PrimaryPath.LocalLID, + pCEP->PrimaryPath.RemoteLID)); + + Status = FPENDING; + + CepSetState(pCEP, CMS_REQ_SENT); + + // Start the REQ timer. Use the Local CM timeout. + req_timeout_ms = TimeoutMultToTimeInMs(pCEP->LocalCMTimeout); + CmTimerStart(pCEP, req_timeout_ms, REQ_TIMER); + + _DBG_LEAVE_LVL(_DBG_LVL_FUNC_TRACE); + + return Status; + +fail_dgrm: + if (bPeer) + CM_MapRemoveEntry(&gCM->ListenMap, &pCEP->MapEntry, LISTEN_LIST, pCEP); + pCEP->Mode = CM_MODE_NONE; +fail: + CM_MapRemoveEntry(&gCM->LocalEndPointMap, &pCEP->LocalEndPointMapEntry, LOCAL_END_POINT_LIST, pCEP); +fail_endpoint: +fail_port: + if (pCaAttr != NULL) + MemoryDeallocate(pCaAttr); + if (pPortAttr != NULL) + MemoryDeallocate(pPortAttr); + // cleanup CEP + pCEP->bPeer = FALSE; + pCEP->SID = 0; + MemoryClear(&pCEP->PrimaryPath, sizeof(pCEP->PrimaryPath)); + MemoryClear(&pCEP->AlternatePath, sizeof(pCEP->AlternatePath)); + MemoryClear(&pCEP->LocalEndPoint, sizeof(pCEP->LocalEndPoint)); + MemoryClear(&pCEP->RemoteEndPoint, sizeof(pCEP->RemoteEndPoint)); + pCEP->Mtu = 0; + pCEP->PartitionKey = 0; + pCEP->LocalInitiatorDepth = 0; + pCEP->LocalResponderResources = 0; + pCEP->LocalRetryCount = 0; + pCEP->LocalRecvPSN = 0; + pCEP->TargetAckDelay = 0; +fail_type: + _DBG_LEAVE_LVL(_DBG_LVL_FUNC_TRACE); + + return Status; +} // Connect() + + +////////////////////////////////////////////////////////////////////////// +// GetConnInfo +// Supports Connection Info (for use in preparing callback arguments) +// for both Active and Passive sides. Where there are differences between +// active and passive behaviours, asserts or tests of pCEP->Mode are used +// +// +// INPUTS: +// +// +// +// OUTPUTS: +// +// None. +// +// RETURNS: +// +// FSUCCESS or FTIMEOUT. +// +// IRQL: +// +// This routine is called at IRQL_PASSIVE_LEVEL. with ListLock held +// +FSTATUS +GetConnInfo( + IN CM_CEP_OBJECT* pCEP, + OUT CM_CONN_INFO* pConnInfo + ) +{ + FSTATUS Status=FSUCCESS; + boolean bKeepQueued = FALSE; // should additional queued events be kept + CM_CEP_OBJECT* pCEPEntry = NULL; + DLIST_ENTRY* pListEntry = NULL; + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, GetConnInfo); + + pConnInfo->Status = 0; + + // Find out what state + switch (pCEP->State) + { + case CMS_IDLE: + if (BitTest(pCEP->EventFlags, SYSE_DISCONNECT)) + { + // CA has been removed + BitClear(pCEP->EventFlags, SYSE_DISCONNECT); + if (pCEP->bTimewaitCallback) + pConnInfo->Status = FCM_CA_REMOVED; + else + pConnInfo->Status = FCM_DISCONNECTED; // legacy API + } + else if (BitTest(pCEP->EventFlags, USRE_CANCEL)) + { + // user has cancelled listen, sidr_req or connect attempt + BitClear(pCEP->EventFlags, USRE_CANCEL); + pConnInfo->Status = FCM_CONNECT_CANCEL; + } + else if (BitTest(pCEP->EventFlags, CME_TIMEOUT_REQ)) + { + // We timed out on the REQ msg i.e. no REP/REJ msg received. + ASSERT(pCEP->Mode == CM_MODE_ACTIVE); + BitClear(pCEP->EventFlags, CME_TIMEOUT_REQ); + pConnInfo->Status = FCM_CONNECT_TIMEOUT; + } + else if (BitTest(pCEP->EventFlags, CME_TIMEOUT_REP)) + { + // We timed out while waiting for the RTU to arrive + ASSERT(pCEP->Mode == CM_MODE_PASSIVE); + BitClear(pCEP->EventFlags, CME_TIMEOUT_REP); + pConnInfo->Status = FCM_CONNECT_TIMEOUT; + } + else if (BitTest(pCEP->EventFlags, CME_RCVD_REJ)) + { + // a REJ was received + BitClear(pCEP->EventFlags, CME_RCVD_REJ); + + CopyMadToConnInfo(&pConnInfo->Info, + (CM_MAD*)GsiDgrmGetSendMad(pCEP->pDgrmElement)); + + pConnInfo->Status = FCM_CONNECT_REJECT; + bKeepQueued = TRUE; /* for RC_STALE, CME_TIMEOUT_TIMEWAIT queued */ + } + else if (BitTest(pCEP->EventFlags, CME_TIMEOUT_DREQ)) + { + // We timed out on the DREQ msg i.e. no DREP msg received. + BitClear(pCEP->EventFlags, CME_TIMEOUT_DREQ); + // FCM_DISCONNECTED is same value as FCM_DISCONNECT_TIMEOUT + pConnInfo->Status = FCM_DISCONNECTED; + } + else if (BitTest(pCEP->EventFlags, CME_RCVD_DREP)) + { + // received a DREP + BitClear(pCEP->EventFlags, CME_RCVD_DREP); + + CopyMadToConnInfo(&pConnInfo->Info, + (CM_MAD*)GsiDgrmGetSendMad(pCEP->pDgrmElement)); + + pConnInfo->Status = FCM_DISCONNECT_REPLY; + bKeepQueued = TRUE; /* leave CME_TIMEOUT_TIMEWAIT queued */ + } + else if (BitTest(pCEP->EventFlags, CME_RCVD_DREQ)) + { + // We received a DREQ but the user already sent a DREP + // odd sequence, user must have done CmDisconnect with a reply + // and it raced with a receipt of a DREQ + BitClear(pCEP->EventFlags, CME_RCVD_DREQ); + pConnInfo->Status = FCM_DISCONNECTED; + } + else if (BitTest(pCEP->EventFlags, CME_SIM_RCVD_DREQ)) + { + // We received a REJ but the user was already issuing a Disconnect + // odd sequence, user must have done CmDisconnect with a reply + // and it raced with a receipt of a REJ + BitClear(pCEP->EventFlags, CME_SIM_RCVD_DREQ); + pConnInfo->Status = FCM_DISCONNECTED; + } + else if (BitTest(pCEP->EventFlags, CME_TIMEOUT_TIMEWAIT)) + { + // Timewait state completed + BitClear(pCEP->EventFlags, CME_TIMEOUT_TIMEWAIT); + if (pCEP->bTimewaitCallback) + { + pConnInfo->Status = FCM_DISCONNECTED; + } else { + Status = FERROR; + } + } + else if (BitTest(pCEP->EventFlags, CME_RCVD_SIDR_RESP)) + { + // SIDR_RESP was received + ASSERT(pCEP->Mode == CM_MODE_ACTIVE); + BitClear(pCEP->EventFlags, CME_RCVD_SIDR_RESP); + + CopyMadToConnInfo(&pConnInfo->Info, + (CM_MAD*)GsiDgrmGetSendMad(pCEP->pDgrmElement)); + + if (pConnInfo->Info.SidrResponse.Status == SRS_VALID_QPN) + pConnInfo->Status = FSIDR_RESPONSE; + else + pConnInfo->Status = FSIDR_RESPONSE_ERR; + } + else if (BitTest(pCEP->EventFlags, CME_TIMEOUT_SIDR_REQ)) + { + // We timed out while waiting for a response to our sidr req + ASSERT(pCEP->Mode == CM_MODE_ACTIVE); + BitClear(pCEP->EventFlags, CME_TIMEOUT_SIDR_REQ); + pConnInfo->Status = FSIDR_REQUEST_TIMEOUT; + } else { + Status = FERROR; + } + break; + + case CMS_LISTEN: + case CMS_REQ_RCVD: + case CMS_MRA_REQ_SENT: + // We received a client connect or peer connect request. + ASSERT(pCEP->Mode == CM_MODE_PASSIVE); + //ASSERT(BitTest(pCEP->EventFlags, CME_RCVD_REQ)); + BitClear(pCEP->EventFlags, CME_RCVD_REQ); + + if (pCEP->State == CMS_LISTEN) + { + _DBG_INFO((" *** We received a connect request ***\n", + _DBG_PTR(pCEP))); + } else { + _DBG_INFO((" *** We received a peer request ***\n", + _DBG_PTR(pCEP))); + } + + // Get the new CEP object from the pending list + if (DListIsEmpty(&pCEP->PendingList)) + { + _DBG_WARNING((" Pending list is empty!\n", + _DBG_PTR(pCEP))); + + Status = FERROR; + break; + } + + pListEntry = DListGetNext(&pCEP->PendingList); + pCEPEntry = PARENT_STRUCT(pListEntry, CM_CEP_OBJECT, PendingListEntry); + + // Make sure this is not the same one we returned previously. This can + // happen if another request arrived before the user accept + /* + if (BitTest(pCEPEntry->EventFlags, USRE_WAIT)) + { + _DBG_WARNING((" Object is in signaled state but user is still processing the current event!\n", + _DBG_PTR(pCEP))); + + // The user is still processing the current one. To maintain FIFO order, + // we cannot notify the user of the new request until the current one is + // accepted, rejected or timed out. + Status = FERROR; + //bWaitAgain = TRUE; + break; + } + + // Mark it so that we dont return this again in another wait() + // We clear this in AcceptP() or RejectP() + //BitSet(pCEPEntry->EventFlags, USRE_WAIT); + */ + CopyMadToConnInfo(&pConnInfo->Info, + (CM_MAD*)GsiDgrmGetSendMad(pCEPEntry->pDgrmElement)); + + // port on which REQ arrived + pConnInfo->Info.Request.CEPInfo.PortGUID = pCEPEntry->pDgrmElement->PortGuid; + // when we processed REQ, we negotiated these down based on + // CA capabilities + pConnInfo->Info.Request.CEPInfo.OfferedInitiatorDepth = pCEPEntry->LocalResponderResources; + pConnInfo->Info.Request.CEPInfo.OfferedResponderResources = pCEPEntry->LocalInitiatorDepth; + pConnInfo->Status = FCM_CONNECT_REQUEST; + + break; + + case CMS_REP_RCVD: + case CMS_MRA_REP_SENT: + ASSERT(pCEP->Mode == CM_MODE_ACTIVE); + // We received a reply to our connect request + if (BitTest(pCEP->EventFlags, CME_RCVD_REP)) + { + BitClear(pCEP->EventFlags, CME_RCVD_REP); + CopyMadToConnInfo(&pConnInfo->Info, + (CM_MAD*)GsiDgrmGetSendMad(pCEP->pDgrmElement)); + pConnInfo->Status = FCM_CONNECT_REPLY; + } else { + Status = FERROR; + } + break; + + case CMS_ESTABLISHED: + if (BitTest(pCEP->EventFlags, CME_RCVD_RTU)) + { + // received the RTU for our REP + ASSERT(pCEP->Mode == CM_MODE_PASSIVE); + BitClear(pCEP->EventFlags, CME_RCVD_RTU); + CopyMadToConnInfo(&pConnInfo->Info, + (CM_MAD*)GsiDgrmGetSendMad(pCEP->pDgrmElement)); + pConnInfo->Status = FCM_CONNECT_ESTABLISHED; + } + else if (BitTest(pCEP->EventFlags, CME_RCVD_APR)) + { + ASSERT(pCEP->Mode == CM_MODE_ACTIVE); + BitClear(pCEP->EventFlags, CME_RCVD_APR); + CopyMadToConnInfo(&pConnInfo->Info, + (CM_MAD*)GsiDgrmGetSendMad(pCEP->pDgrmElement)); + if (pConnInfo->Info.AltPathReply.APStatus == APS_PATH_LOADED) + { + // we populate CEP with additional information to help + // application do ModifyQP + CopyCepPathToPathInfo(&pConnInfo->Info.AltPathReply.u.Alternate.PathInfo, + &pConnInfo->Info.AltPathReply.u.Alternate.AckTimeout, + &pCEP->AlternatePath); + + pConnInfo->Info.AltPathReply.u.Alternate.PathInfo.Path.Mtu = pCEP->Mtu; + pConnInfo->Info.AltPathReply.u.Alternate.PathInfo.Path.P_Key = pCEP->PartitionKey; + pConnInfo->Status = FCM_ALTPATH_REPLY; + } else { + pConnInfo->Status = FCM_ALTPATH_REJECT; + } + } + else if (BitTest(pCEP->EventFlags, CME_TIMEOUT_LAP)) + { + ASSERT(pCEP->Mode == CM_MODE_ACTIVE); + BitClear(pCEP->EventFlags, CME_TIMEOUT_LAP); + pConnInfo->Status = FCM_ALTPATH_TIMEOUT; + } else { + Status = FERROR; + } + break; + + case CMS_LAP_RCVD: + case CMS_MRA_LAP_SENT: + if (BitTest(pCEP->EventFlags, CME_RCVD_RTU)) + { + // RTU and LAP events are both queued + // by the time the signal is delivered to us + ASSERT(pCEP->Mode == CM_MODE_PASSIVE); + BitClear(pCEP->EventFlags, CME_RCVD_RTU); + // We have not yet delivered the RTU, however the pCEP->pDgrmElement + // is now the LAP, so we deliver an RTU with no private data + // (much the way a QP Async Event for Communication Established + // would simulate an RTU) + // this callback will be followed immediately by the + // LAP request + MemoryClear(&pConnInfo->Info.Rtu, sizeof(pConnInfo->Info.Rtu)); + pConnInfo->Status = FCM_CONNECT_ESTABLISHED; + bKeepQueued = TRUE; /* leave CME_RCVD_LAP queued */ + } + else if (BitTest(pCEP->EventFlags, CME_RCVD_LAP)) + { + // received LAP + BitClear(pCEP->EventFlags, CME_RCVD_LAP); + CopyMadToConnInfo(&pConnInfo->Info, + (CM_MAD*)GsiDgrmGetSendMad(pCEP->pDgrmElement)); + // additional fields in AltPathInfo + pConnInfo->Info.AltPathRequest.AlternatePathInfo.Path.P_Key= pCEP->PartitionKey; + pConnInfo->Info.AltPathRequest.AlternatePathInfo.Path.Mtu = pCEP->Mtu; + pConnInfo->Status = FCM_ALTPATH_REQUEST; + } else { + Status = FERROR; + } + break; + + case CMS_DREQ_RCVD: + if (BitTest(pCEP->EventFlags,CME_RCVD_RTU)) + { + // RTU and DREQ events are both queued + // by the time the signal is delivered to us + ASSERT(pCEP->Mode == CM_MODE_PASSIVE); + BitClear(pCEP->EventFlags,CME_RCVD_RTU); + // We have not yet delivered the RTU, however the pCEP->pDgrmElement + // is now the DREQ, so we deliver an RTU with no private data + // (much the way a QP Async Event for Communication Established + // would simulate an RTU) + // this callback will be followed immediately by the + // disconnect request + MemoryClear(&pConnInfo->Info.Rtu, sizeof(pConnInfo->Info.Rtu)); + pConnInfo->Status = FCM_CONNECT_ESTABLISHED; + bKeepQueued = TRUE; /* leave CME_RCVD_DREQ queued */ + } + else if (BitTest(pCEP->EventFlags, CME_RCVD_DREQ)) + { + // Received disconnect request + BitClear(pCEP->EventFlags, CME_RCVD_DREQ); + CopyMadToConnInfo(&pConnInfo->Info, + (CM_MAD*)GsiDgrmGetSendMad(pCEP->pDgrmElement)); + pConnInfo->Status = FCM_DISCONNECT_REQUEST; + } else { + Status = FERROR; + } + + break; + + case CMS_SIM_DREQ_RCVD: + if (BitTest(pCEP->EventFlags,CME_RCVD_RTU)) + { + // RTU and SIM DREQ events are both queued + // by the time the signal is delivered to us + // + // Note this is only applicable to passive side, in present code + // CMS_SIM_DREQ_RCVD could only happen on active side. However + // this is implemented for completeness and in case this state + // is later utilized for a passive side simulated DREQ as well + ASSERT(pCEP->Mode == CM_MODE_PASSIVE); + BitClear(pCEP->EventFlags,CME_RCVD_RTU); + // We have not yet delivered the RTU, however the pCEP->pDgrmElement + // is now the DREQ, so we deliver an RTU with no private data + // (much the way a QP Async Event for Communication Established + // would simulate an RTU) + // this callback will be followed immediately by the + // disconnect request + MemoryClear(&pConnInfo->Info.Rtu, sizeof(pConnInfo->Info.Rtu)); + pConnInfo->Status = FCM_CONNECT_ESTABLISHED; + bKeepQueued = TRUE; /* leave CME_SIM_RCVD_DREQ queued */ + } + else if (BitTest(pCEP->EventFlags, CME_SIM_RCVD_DREQ)) + { + // We received a REJ but are simulating a DREQ + MemoryClear(&pConnInfo->Info.DisconnectRequest, sizeof(pConnInfo->Info.DisconnectRequest)); + BitClear(pCEP->EventFlags, CME_SIM_RCVD_DREQ); + pConnInfo->Status = FCM_DISCONNECT_REQUEST; + } else { + Status = FERROR; + } + + break; + + case CMS_TIMEWAIT: + if (BitTest(pCEP->EventFlags, CME_RCVD_REJ)) + { + // a REJ was received (must be RC_STALE_CONN) + BitClear(pCEP->EventFlags, CME_RCVD_REJ); + CopyMadToConnInfo(&pConnInfo->Info, + (CM_MAD*)GsiDgrmGetSendMad(pCEP->pDgrmElement)); + pConnInfo->Status = FCM_CONNECT_REJECT; + } + else if (BitTest(pCEP->EventFlags, CME_TIMEOUT_REP)) + { + // timeout waiting for RTU + ASSERT(pCEP->Mode == CM_MODE_PASSIVE); + if (pCEP->bTimewaitCallback) + { + // wait until timewait finishes to provide FCM_CONNECT_TIMEOUT + Status = FERROR; + bKeepQueued = TRUE; /* keep CME_TIMEOUT_REP set till Idle */ + } else { + BitClear(pCEP->EventFlags, CME_TIMEOUT_REP); + pConnInfo->Status = FCM_CONNECT_TIMEOUT; + } + } + else if (BitTest(pCEP->EventFlags, CME_RCVD_DREP)) + { + // Received disconnect reply + BitClear(pCEP->EventFlags, CME_RCVD_DREP); + CopyMadToConnInfo(&pConnInfo->Info, + (CM_MAD*)GsiDgrmGetSendMad(pCEP->pDgrmElement)); + pConnInfo->Status = FCM_DISCONNECT_REPLY; + } + else if (BitTest(pCEP->EventFlags, CME_RCVD_DREQ)) + { + // We received a DREQ but the user already sent a DREP + // odd sequence, user must have done CmDisconnect with a reply + // and it raced with a receipt of a DREQ + BitClear(pCEP->EventFlags, CME_RCVD_DREQ); + if (pCEP->bTimewaitCallback) + { + // wait until timewait finishes to provide FCM_DISCONNECTED + Status = FERROR; + } else { + pConnInfo->Status = FCM_DISCONNECTED; + } + } + else if (BitTest(pCEP->EventFlags, CME_SIM_RCVD_DREQ)) + { + // We received a REJ but the user was already issuing a Disconnect + // odd sequence, user must have done CmDisconnect with a reply + // and it raced with a receipt of a REJ + BitClear(pCEP->EventFlags, CME_SIM_RCVD_DREQ); + if (pCEP->bTimewaitCallback) + { + // wait until timewait finishes to provide FCM_DISCONNECTED + Status = FERROR; + } else { + pConnInfo->Status = FCM_DISCONNECTED; + } + } + else if (BitTest(pCEP->EventFlags, CME_TIMEOUT_DREQ)) + { + // We timed out on the DREQ msg i.e. no DREP msg received. + BitClear(pCEP->EventFlags, CME_TIMEOUT_DREQ); + if (pCEP->bTimewaitCallback) + { + // wait until timewait finishes to provide FCM_DISCONNECTED + Status = FERROR; + } else { + // FCM_DISCONNECTED is same value as FCM_DISCONNECT_TIMEOUT + pConnInfo->Status = FCM_DISCONNECTED; + } + } else { + Status = FERROR; + } + + break; + + case CMS_REGISTERED: + ASSERT(pCEP->Mode == CM_MODE_PASSIVE); + if (BitTest(pCEP->EventFlags, CME_RCVD_SIDR_REQ)) + { + // Received SIDR request + BitClear(pCEP->EventFlags, CME_RCVD_SIDR_REQ); + + if (DListIsEmpty(&pCEP->PendingList)) + { + _DBG_WARNING((" Pending list is empty!\n", + _DBG_PTR(pCEP))); + Status = FERROR; + break; + } + + pListEntry = DListGetNext(&pCEP->PendingList); + pCEPEntry = PARENT_STRUCT(pListEntry, CM_CEP_OBJECT, PendingListEntry); + + // Make sure this is not the same one we returned previously + /* + if (BitTest(pCEPEntry->EventFlags, USRE_WAIT)) + { + _DBG_WARNING((" Object is in signaled state but user is still processing the current event!\n", + _DBG_PTR(pCEP))); + + // The user is still processing the current one. To maintain FIFO order, + // we cannot notify the user of the new request until the current one is + // accepted, rejected or timed out. + //bWaitAgain = TRUE; + Status = FERROR; + break; + } + + // Mark it so that we dont return this again in another wait() + // We clear this in SIDRResponse() + BitSet(pCEPEntry->EventFlags, USRE_WAIT); + */ + + CopyMadToConnInfo(&pConnInfo->Info, + (CM_MAD*)GsiDgrmGetSendMad(pCEPEntry->pDgrmElement)); + // Copy additional info to the SidrRequest. + pConnInfo->Info.SidrRequest.PathInfo.Path.DLID = pCEPEntry->PrimaryPath.RemoteLID; + pConnInfo->Info.SidrRequest.SID = pCEPEntry->SID; + pConnInfo->Info.SidrRequest.PortGuid = pCEPEntry->pDgrmElement->PortGuid; + pConnInfo->Info.SidrRequest.PathInfo.Path.NumbPath = 1; // only 1 path + pConnInfo->Info.SidrRequest.PathInfo.Path.SLID = pCEPEntry->pDgrmElement->PathBits; // TBD BUGBUG | local port BaseLID; + // IB does not have Static rate in UD LRH + // so we can't be sure what rate of remote port is + // we use a constant value for GSI QPs, so this is not accurate + pConnInfo->Info.SidrRequest.PathInfo.Path.Rate = pCEPEntry->pDgrmElement->StaticRate; + pConnInfo->Info.SidrRequest.PathInfo.Path.u2.s.SL = pCEPEntry->pDgrmElement->ServiceLevel; + // TBD CopyMadToConnInfo has set Path.Pkey based on SIDR_REQ + // alternately could lookup pDgrmElement->PkeyIndex + + if (pCEPEntry->pDgrmElement->GlobalRoute) + { + pConnInfo->Info.SidrRequest.PathInfo.bSubnetLocal = 0; + + memcpy(&pConnInfo->Info.SidrRequest.PathInfo.Path.DGID.Raw, pCEPEntry->pDgrmElement->GRHInfo.DestGID.Raw, sizeof(IB_GID)); + + // BUGBUG! + //memcpy(&pConnInfo->Info.SidrRequest.PathInfo.Path.SGID.Raw, + + pConnInfo->Info.SidrRequest.PathInfo.Path.SGID.Type.Global.SubnetPrefix = DEFAULT_SUBNET_PREFIX; + pConnInfo->Info.SidrRequest.PathInfo.Path.SGID.Type.Global.InterfaceID = pCEPEntry->pDgrmElement->PortGuid; + + pConnInfo->Info.SidrRequest.PathInfo.Path.u1.s.FlowLabel = pCEPEntry->pDgrmElement->GRHInfo.FlowLabel; + pConnInfo->Info.SidrRequest.PathInfo.Path.u1.s.HopLimit = pCEPEntry->pDgrmElement->GRHInfo.HopLimit; + pConnInfo->Info.SidrRequest.PathInfo.Path.TClass = pCEPEntry->pDgrmElement->GRHInfo.TrafficClass; + + } else { + pConnInfo->Info.SidrRequest.PathInfo.bSubnetLocal = 1; + } + + pConnInfo->Status = FSIDR_REQUEST; + } else { + Status = FERROR; + } + + break; + +#if 0 + case CMS_SIDR_RESP_RCVD: + // Received SIDR response + ASSERT(pCEP->Mode == CM_MODE_ACTIVE); + if (BitTest(pCEP->EventFlags, CME_RCVD_SIDR_RESP)) + { + BitClear(pCEP->EventFlags, CME_RCVD_SIDR_RESP); + + // Copy the SIDR response to user buffer + CopyMadToConnInfo(&pConnInfo->Info, + (CM_MAD*)GsiDgrmGetSendMad(pCEP->pDgrmElement)); + + pConnInfo->Status = FSIDR_RESPONSE; + } + else + { + Status = FERROR; + } + + break; +#endif + default: + + Status = FERROR; + break; + } // switch() + + // Clear the event flags + if (! bKeepQueued) + pCEP->EventFlags = 0; + if (pCEP->State == CMS_IDLE && pCEP->EventFlags == 0) + pCEP->Mode = CM_MODE_NONE; + + _DBG_LEAVE_LVL(_DBG_LVL_FUNC_TRACE); + + return Status; + +} // GetConnInfo() + + +////////////////////////////////////////////////////////////////////////// +// WaitA +// +// +// INPUTS: +// +// +// +// OUTPUTS: +// +// None. +// +// RETURNS: +// +// FSUCCESS or FTIMEOUT. +// +// IRQL: +// +// This routine is called at IRQL_PASSIVE_LEVEL. +// +FSTATUS +WaitA( + IN CM_CEP_OBJECT* pCEP, + OUT CM_CONN_INFO* pConnInfo, + uint32 Timeout_us // TODO: Put a max limit on this in addition to infinite + ) +{ + FSTATUS Status=FSUCCESS; + + uint32 WaitTimeUs=Timeout_us; + uint64 TimeoutUs=Timeout_us; + uint64 StartTimeUs=GetTimeStamp(); + + uint64 CurrTimeUs=0; + uint64 TimeElapsedUs=0; + + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, WaitA); + + +waitagain: + + // Update the timeout + if ((int32)WaitTimeUs != EVENT_NO_TIMEOUT) + { + if (CurrTimeUs >= StartTimeUs) + { + TimeElapsedUs = (CurrTimeUs - StartTimeUs); + } + else // wrap-around + { + TimeElapsedUs = (CurrTimeUs + ((uint64)(-1) - StartTimeUs)); + } + + if (TimeoutUs > TimeElapsedUs) + { + WaitTimeUs = (uint32) (TimeoutUs - TimeElapsedUs); + } + else + { + WaitTimeUs = 0; + } + } + + //_DBG_INFO((" Waiting on obj... \n", + // _DBG_PTR(pCEP), WaitTimeUs/1000, pCEP->LocalCommID, + // _DBG_PTR(CmGetStateString(pCEP->State)))); + + Status = EventWaitOn(pCEP->pEventObj, WaitTimeUs); + + //_DBG_INFO((" Waiting on obj... complete <%s %s>\n", + // _DBG_PTR(pCEP), _DBG_PTR(FSTATUS_MSG(Status)), + // _DBG_PTR(CmGetStateString(pCEP->State)))); + + if (Status == FTIMEOUT) + { + if (Timeout_us == 0) + { + //_DBG_INFO((" Obj state is nonsignaled.\n", + // _DBG_PTR(pCEP))); + } + else + { + _DBG_WARNING((" EventWaitOn() returns FTIMEOUT!\n", + _DBG_PTR(pCEP))); + } + + _DBG_LEAVE_LVL(_DBG_LVL_FUNC_TRACE); + + return FTIMEOUT; + } + + ASSERT(Status == FSUCCESS); + + _DBG_INFO((" Obj state is signaled <%s>.\n", _DBG_PTR(pCEP), + _DBG_PTR(CmGetStateString(pCEP->State)))); + + // Get mutual ex to the object + SpinLockAcquire(&gCM->ListLock); + + Status = GetConnInfo(pCEP, pConnInfo); + + if (Status != FSUCCESS) + { + // Handle the case when we get signal but we already process the event + // with the previous signal + // eg evt1 --> signal; evt2 --> signal + // ->wait() returned + _DBG_WARNING((" GetConnInfo() returns %s!\n", + _DBG_PTR(pCEP), _DBG_PTR(FSTATUS_MSG(Status)))); + + ASSERT(pConnInfo->Status == 0); + + SpinLockRelease(&gCM->ListLock); + + goto waitagain; + } + + SpinLockRelease(&gCM->ListLock); + + _DBG_LEAVE_LVL(_DBG_LVL_FUNC_TRACE); + + return Status; + +} // WaitA() + + +////////////////////////////////////////////////////////////////////////// +// AcceptA +// +// +// INPUTS: +// +// +// +// OUTPUTS: +// +// None. +// +// RETURNS: +// +// FSUCCESS - The function has completed successfully. For server, this indicates the initialization. +// >FCM_CONNECT_ESTABLISHED +// >FCM_CONNECT_REJECT +// >FCM_CONNECT_TIMEOUT +// >FCM_CONNECT_CANCEL +// +// FINVALID_STATE - The endpoint is not in the valid state for this call +// FERROR - Unable to send the reply ack packet +// FTIMEOUT - The timeout interval expires +// +// +// IRQL: +// +// This routine is called at IRQL_PASSIVE_LEVEL. +// +FSTATUS +AcceptA( + IN CM_CEP_OBJECT* pCEP, + IN CM_CONN_INFO* pSendConnInfo // Send RTU + ) +{ + FSTATUS Status=FSUCCESS; + + uint64 elapsed_us=0; + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, AcceptA); + + SpinLockAcquire(&gCM->ListLock); + + switch (pCEP->State) + { + case CMS_IDLE: + + if (BitTest(pCEP->EventFlags, USRE_CANCEL)) + { + Status = FCM_CONNECT_CANCEL; + } else { + Status = FERROR; + } + + break; + + case CMS_REP_RCVD: + case CMS_MRA_REP_SENT: + // + // Active accept - + // Accepting the connect reply on a connect or peer endpoint. + // Send a reply ack msg. + // + + // Update the turnaround time + elapsed_us = CmGetElapsedTime(pCEP); + gCM->turnaround_time_us = UpdateTurnaroundTime(gCM->turnaround_time_us, elapsed_us); + _DBG_INFO(("Update turnaround time .\n", gCM->turnaround_time_us)); + + // Prepare RTU + FormatRTU((CM_MAD*)GsiDgrmGetSendMad(pCEP->pDgrmElement), + pSendConnInfo?pSendConnInfo->Info.Rtu.PrivateData:NULL, + pSendConnInfo?CMM_RTU_USER_LEN:0, + pCEP->TransactionID, + pCEP->LocalCommID, + pCEP->RemoteCommID); + + _DBG_INFO((" RTU's dgrm address field \n", + _DBG_PTR(pCEP), + pCEP->pDgrmElement->PortGuid, + pCEP->pDgrmElement->RemoteLID, + pCEP->pDgrmElement->ServiceLevel, + pCEP->pDgrmElement->PathBits, + pCEP->pDgrmElement->StaticRate)); + + // Send out the RTU + Status = CmDgrmSend(pCEP->pDgrmElement); + if (Status != FSUCCESS) + { + // fall through and let timer retry the send later + _DBG_WARN((" DgrmSend() failed for RTU!!! <%s>\n", + _DBG_PTR(pCEP), _DBG_PTR(FSTATUS_MSG(Status)))); + Status = FSUCCESS; + } else { + AtomicIncrementVoid(&gCM->Sent.Rtu); + } + + // Update the status + Status = FCM_CONNECT_ESTABLISHED; + if (pSendConnInfo) + pSendConnInfo->Status = Status; + + CepSetState(pCEP, CMS_ESTABLISHED); + + _DBG_INFO((" *** Connection established *** .\n", + _DBG_PTR(pCEP), pCEP->LocalCommID, pCEP->RemoteCommID, + pCEP->PrimaryPath.LocalLID, pCEP->PrimaryPath.RemoteLID)); + break; + + default: + Status = FINVALID_STATE; + break; + + } // switch() + + SpinLockRelease(&gCM->ListLock); + + _DBG_LEAVE_LVL(_DBG_LVL_FUNC_TRACE); + + return Status; + +} // AcceptA() + + +////////////////////////////////////////////////////////////////////////// +// RejectA +// +// +// INPUTS: +// +// +// +// OUTPUTS: +// +// None. +// +// RETURNS: +// +// FSUCCESS. +// +// IRQL: +// +// This routine is called at IRQL_PASSIVE_LEVEL. +// +FSTATUS +RejectA( + IN CM_CEP_OBJECT* pCEP, + IN const CM_REJECT_INFO* pConnectReject + ) +{ + FSTATUS Status=FSUCCESS; + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, RejectA); + + switch (pCEP->State) + { + case CMS_IDLE: + + if (BitTest(pCEP->EventFlags, USRE_CANCEL)) + { + Status = FCM_CONNECT_CANCEL; + } else { + Status = FERROR; + } + break; + + case CMS_REP_RCVD: + case CMS_MRA_REP_SENT: + // + // Reject the connect reply from the server + // + + // Format the REJ msg + FormatREJ((CM_MAD*)GsiDgrmGetSendMad(pCEP->pDgrmElement), + CM_REJECT_REPLY, + (uint16)pConnectReject->Reason, + pConnectReject->RejectInfo, + pConnectReject->RejectInfoLen, + pConnectReject->PrivateData, + CMM_REJ_USER_LEN, + pCEP->TransactionID, + pCEP->LocalCommID, + pCEP->RemoteCommID); + + + + // Send out the REJ. We do not need to handle failures since + // the other end will eventually time-out if it does not received + // either RTU or REJ + Status = CmDgrmSend(pCEP->pDgrmElement); + if (Status != FSUCCESS) + { + // fall through and let timer retry the send later + _DBG_WARN((" DgrmSend() failed for REJ!!! <%s>\n", + _DBG_PTR(pCEP), _DBG_PTR(FSTATUS_MSG(Status)))); + Status = FSUCCESS; + } else { + AtomicIncrementVoid(&gCM->Sent.RejRep); + } + + _DBG_INFO((" REJ sent, rejecting REP .\n", + _DBG_PTR(pCEP), pCEP->LocalCommID, pCEP->RemoteCommID, + pCEP->PrimaryPath.LocalLID, + pCEP->PrimaryPath.RemoteLID, + pConnectReject->Reason)); + + CepToIdle(pCEP); + break; + + //case CMS_REQ_SENT: + //case CMS_REP_WAIT: + // TODO: Client canceling the pending connection attempt + //break; + + default: + + Status = FINVALID_STATE; + break; + + } // switch() + + _DBG_LEAVE_LVL(_DBG_LVL_FUNC_TRACE); + return Status; + +} // RejectA() + + +////////////////////////////////////////////////////////////////////////// +// CancelA +// CmCancel or CEPDestroy on an active CEP +// CA removal while connecting +// +// +// INPUTS: +// +// +// +// OUTPUTS: +// +// None. +// +// RETURNS: +// +// FSUCCESS. +// +// IRQL: +// +// This routine is called at IRQL_PASSIVE_LEVEL. +// +FSTATUS +CancelA( + IN CM_CEP_OBJECT* pCEP + ) +{ + FSTATUS Status=FPENDING; + + switch (pCEP->State) + { + case CMS_REQ_SENT: + case CMS_REP_WAIT: + // + // Cancel the connect request + // + + // Cancel the REQ timer + CmTimerStop(pCEP, REQ_TIMER); + + if (pCEP->bPeer && pCEP->RemoteEndPoint.CaGUID == 0) + { + CM_MapRemoveEntry(&gCM->ListenMap, &pCEP->MapEntry, LISTEN_LIST, pCEP); + } + CepToIdle(pCEP); + + // Set the cancel event + SetNotification(pCEP, USRE_CANCEL); + + break; + + case CMS_REP_RCVD: + case CMS_MRA_REP_SENT: + + // No need to check the return status. We are guaranteed to succeed + // since we are calling RejectA() within the lock (i.e. no state changed) + { + // keep const and static to save kernel stack space + static CM_REJECT_INFO ConnectReject = { + Reason:RC_USER_REJ + }; + + RejectA(pCEP, &ConnectReject); + } + // CEP is now Idle + + // Set the cancel event + SetNotification(pCEP, USRE_CANCEL); + + break; + + case CMS_SIDR_REQ_SENT: + + // Cancel the SIDR_REQ timer + CmTimerStop(pCEP, SIDR_REQ_TIMER); + + // Move from QUERY to INIT list + CM_MapRemoveEntry(&gCM->QueryMap, &pCEP->MapEntry, QUERY_LIST, pCEP); + // ClearEndPoint in CepToIdle is benign + CepToIdle(pCEP); + + // Set the cancel event + SetNotification(pCEP, USRE_CANCEL); + break; + + default: + + Status = FINVALID_STATE; + break; + + } // switch() + + return Status; + +} // CancelA() + + +// build QP Attributes to move QP to Init, RTR and RTS +// and prepare a Rtu +FSTATUS ProcessReplyA( + IN CM_CEP_OBJECT* pCEP, + OUT CM_PROCESS_REPLY_INFO* Info + ) +{ + FSTATUS Status=FSUCCESS; + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, ProcessReplyA); + + switch (pCEP->State) + { + case CMS_IDLE: + if (BitTest(pCEP->EventFlags, USRE_CANCEL)) + { + Status = FCM_CONNECT_CANCEL; + } else { + Status = FERROR; + } + break; + + case CMS_REP_RCVD: + case CMS_MRA_REP_SENT: + MemoryClear(Info, sizeof(*Info)); // just to be safe + // set up attributes to move QP to Init + // we used to return Init, but spec says this should be done before + // send REQ so we removed it to reduce size of return structure + //GetInitAttrFromCep(pCEP, &Info->QpAttrInit); + + // set up attributes to move QP to RTR + GetRtrAttrFromCep(pCEP, pCEP->bFailoverSupported, &Info->QpAttrRtr); + + // set up attributes to move QP to RTS + GetRtsAttrFromCep(pCEP, &Info->QpAttrRts); + break; + + default: + Status = FINVALID_STATE; + break; + } + + _DBG_LEAVE_LVL(_DBG_LVL_FUNC_TRACE); + + return Status; +} + +////////////////////////////////////////////////////////////////////////// +// AltPathRequestA +// +// Request a new alternate path +// Only allowed for Client/Active side of connection +// +// INPUTS: +// +// +// +// OUTPUTS: +// +// None. +// +// RETURNS: +// +// FPENDING - LAP queued to be sent. +// FINVALID_STATE - The endpoint is not in the valid state for this call +// FERROR - Unable to send the lap packet +// FINVALID_PARAMETER - invalid pLapInfo +// +// +// IRQL: +// +// This routine is called at IRQL_PASSIVE_LEVEL. +// +FSTATUS +AltPathRequestA( + IN CM_CEP_OBJECT* pCEP, + IN const CM_ALTPATH_INFO* pLapInfo // Send LAP + ) +{ + FSTATUS Status; + IB_PORT_ATTRIBUTES *pPortAttr=NULL; + uint8 LocalCaAckDelay; + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, AltPathRequestA); + + ASSERT(pCEP->Mode == CM_MODE_ACTIVE); + if (pCEP->State != CMS_ESTABLISHED) + { + Status = FINVALID_STATE; + goto done; + } + if (! pCEP->bFailoverSupported) + { + // Remote End REP did not accept Failover + Status = FINVALID_STATE; + goto done; + } +#if ! defined(CM_APM_RELOAD) + // do not allow alternate path to be reloaded + if (pCEP->AlternatePath.LocalLID != 0) + { + Status = FINVALID_STATE; + goto done; + } +#endif + if (0 == CompareCepPathToPathInfo(&pCEP->PrimaryPath, + &pLapInfo->AlternatePathInfo)) + { + Status = FINVALID_PARAMETER; + goto done; + } + Status = iba_find_ca_gid(&pLapInfo->AlternatePathInfo.Path.SGID, + pCEP->LocalEndPoint.CaGUID, + &pCEP->TempAlternateLocalPortGuid, + &pCEP->TempAlternateLocalGidIndex, &pPortAttr, + &LocalCaAckDelay); + if (Status != FSUCCESS) + { + Status = FINVALID_PARAMETER; + goto done; + } + if (! LookupPKey(pPortAttr, pCEP->PartitionKey, FALSE, &pCEP->TempAlternatePkeyIndex)) + { + Status = FINVALID_PARAMETER; + goto done; + } + pCEP->TempAlternateLocalPathBits = LidToPathBits(pLapInfo->AlternatePathInfo.Path.SLID, pPortAttr->Address.LMC); + pCEP->TempAlternateLocalAckTimeout = ComputeAckTimeout( + pLapInfo->AlternatePathInfo.Path.PktLifeTime, + pCEP->TargetAckDelay); + MemoryDeallocate(pPortAttr); + + // Prepare LAP + + // RTU could still be on send Q, get a fresh Dgrm if needed + Status = PrepareCepDgrm(pCEP); + if (Status != FSUCCESS) { + _DBG_WARNING((" Unable to send LAP: Out of CM Dgrms!!!\n", _DBG_PTR(pCEP))); + goto done; + } + + pCEP->bLapSent = 1; // pCEP->pDgrmElement is no longer an RTU + FormatLAP((CM_MAD*)GsiDgrmGetSendMad(pCEP->pDgrmElement), + pCEP->RemoteEndPoint.QPN, // TBD EECN + pCEP->RemoteCMTimeout, + pLapInfo, + (pLapInfo->AlternateAckTimeout + ?pLapInfo->AlternateAckTimeout + : ComputeAckTimeout( + pLapInfo->AlternatePathInfo.Path.PktLifeTime, + LocalCaAckDelay)), + pCEP->TransactionID, + pCEP->LocalCommID, + pCEP->RemoteCommID); + + _DBG_INFO((" LAP's dgrm address field \n", + _DBG_PTR(pCEP), + pCEP->pDgrmElement->PortGuid, + pCEP->pDgrmElement->RemoteLID, + pCEP->pDgrmElement->ServiceLevel, + pCEP->pDgrmElement->PathBits, + pCEP->pDgrmElement->StaticRate)); + + // Send out the LAP + Status = CmDgrmSend(pCEP->pDgrmElement); + if (Status != FSUCCESS) + { + // fall through and let timer retry the send later + _DBG_WARN((" DgrmSend() failed for LAP!!! <%s>\n", + _DBG_PTR(pCEP), _DBG_PTR(FSTATUS_MSG(Status)))); + Status = FSUCCESS; + } else { + AtomicIncrementVoid(&gCM->Sent.Lap); + } + + Status = FPENDING; + + CepSetState(pCEP, CMS_LAP_SENT); + + pCEP->RetryCount = 0; + CmTimerStart(pCEP, TimeoutMultToTimeInMs(pCEP->LocalCMTimeout), LAP_TIMER); + +done: + _DBG_LEAVE_LVL(_DBG_LVL_FUNC_TRACE); + return Status; + +} // AltPathRequestA() + + +// build QP Attributes to load new alternate path into QP +FSTATUS ProcessAltPathReplyA( + IN CM_CEP_OBJECT* pCEP, + IN const CM_ALTPATH_REPLY_INFO* AltPathReply, + OUT IB_QP_ATTRIBUTES_MODIFY* QpAttrRts + ) +{ + FSTATUS Status=FSUCCESS; + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, ProcessAltPathReplyA); + + ASSERT(pCEP->Mode == CM_MODE_ACTIVE); + if (pCEP->State != CMS_ESTABLISHED) + { + Status = FINVALID_STATE; + goto done; + } + + // possible risk - we trust pCEP->AlternatePath, however if the + // application issues a Lap and gets a reply before this function + // completes, the pCEP->AlternatePath and pCEP->TempAlternate fields + // could change on us. If this risk is real we would need to work + // strictly from the AltPathReply + MemoryClear(QpAttrRts, sizeof(*QpAttrRts)); // just to be safe + QpAttrRts->RequestState = QPStateReadyToSend; + QpAttrRts->APMState = APMStateRearm; + GetAVFromCepPath(&pCEP->AlternatePath, &QpAttrRts->AltDestAV); + QpAttrRts->AltPortGUID = pCEP->AlternatePath.LocalPortGuid; + QpAttrRts->AltPkeyIndex = pCEP->AlternatePath.PkeyIndex; + QpAttrRts->Attrs = IB_QP_ATTR_APMSTATE + | IB_QP_ATTR_ALTDESTAV|IB_QP_ATTR_ALTPORTGUID + | IB_QP_ATTR_ALTPKEYINDEX; + if (pCEP->Type != CM_UC_TYPE) { + QpAttrRts->AltLocalAckTimeout = pCEP->AlternatePath.LocalAckTimeout; + QpAttrRts->Attrs |= IB_QP_ATTR_ALTLOCALACKTIMEOUT; + } + // caller must iba_modify_qp(...) +done: + _DBG_LEAVE_LVL(_DBG_LVL_FUNC_TRACE); + + return Status; +} + +////////////////////////////////////////////////////////////////////////// +// MigratedA +// +// Inform CM that alternate path has been migrated to by client or server +// TBD - hook into Async Event callbacks +// +// INPUTS: +// +// +// +// OUTPUTS: +// +// None. +// +// RETURNS: +// +// FSUCCESS - CEP adjusted to reflect migration +// FINVALID_STATE - The endpoint is not in the valid state for this call +// +// +// IRQL: +// +// This routine is called at IRQL_PASSIVE_LEVEL. +// +FSTATUS +MigratedA( + IN CM_CEP_OBJECT* pCEP + ) +{ + FSTATUS Status = FSUCCESS; + uint64 old_acktimeout_us; + uint64 new_acktimeout_us; + uint64 timeout_us; + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, MigratedA); + + if (pCEP->State != CMS_ESTABLISHED) + { + // if CM_APM_RELOAD could be a race of migration with LAP + Status = FINVALID_STATE; + goto done; + } + + if (pCEP->AlternatePath.LocalLID == 0) + { + // No alternate path + Status = FINVALID_STATE; + goto done; + } + + // New path will have a different PktLifetime, so adjust our CM timers + // accordingly, AckTimeout has a 2*PktLifetime component + old_acktimeout_us = TimeoutMultToTimeInUsec(pCEP->PrimaryPath.AckTimeout); + new_acktimeout_us = TimeoutMultToTimeInUsec(pCEP->AlternatePath.AckTimeout); + + // LocalCMTimeout has a 2*PktLifetime component + timeout_us = TimeoutMultToTimeInUsec(pCEP->LocalCMTimeout) + + (new_acktimeout_us - old_acktimeout_us); + pCEP->LocalCMTimeout = TimeoutTimeToMult(timeout_us); + + // RemoteCMTimeout has no PktLifetime component + + pCEP->Timewait = pCEP->AlternatePath.LocalAckTimeout; + + // Ack timeout is calculated as round-trip + // This computation will be rounded up by CA Ack Delay/2 + if (pCEP->AlternatePath.AckTimeout >= 1) + { + // -1 for a log2 value is the same as /2 + pCEP->PktLifeTime = (pCEP->AlternatePath.AckTimeout -1); + } else { + pCEP->PktLifeTime = 0; + } + + pCEP->PrimaryPath = pCEP->AlternatePath; + MemoryClear(&pCEP->AlternatePath, sizeof(pCEP->AlternatePath)); + + // adjust remote path for future CM dgrms to use + CmDgrmAddrSet(pCEP->pDgrmElement, + pCEP->PrimaryPath.LocalPortGuid, + pCEP->PrimaryPath.RemoteLID, + pCEP->PrimaryPath.SL, + pCEP->PrimaryPath.LocalPathBits, + pCEP->PrimaryPath.StaticRate, + (! pCEP->PrimaryPath.bSubnetLocal), + pCEP->PrimaryPath.RemoteGID, + pCEP->PrimaryPath.FlowLabel, + pCEP->PrimaryPath.LocalGidIndex, + pCEP->PrimaryPath.HopLimit, + (uint8)pCEP->PrimaryPath.TClass, + pCEP->PrimaryPath.PkeyIndex); + +done: + _DBG_LEAVE_LVL(_DBG_LVL_FUNC_TRACE); + return Status; + +} // MigratedA() + +FSTATUS +MigratedReloadA( + IN CM_CEP_OBJECT* pCEP, + OUT CM_PATH_INFO* NewPrimaryPath OPTIONAL, + OUT CM_ALTPATH_INFO* AltPathRequest OPTIONAL + ) +{ + FSTATUS Status; + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, MigratedReloadA); + + ASSERT(pCEP->Mode == CM_MODE_ACTIVE); + if (NewPrimaryPath) + { + CopyCepPathToPathInfo(&NewPrimaryPath->PathInfo, + &NewPrimaryPath->AckTimeout, &pCEP->AlternatePath); + NewPrimaryPath->PathInfo.Path.P_Key = pCEP->PartitionKey; + NewPrimaryPath->PathInfo.Path.Mtu = pCEP->Mtu; + //NewPrimaryPath->PathInfo.Path.PktLifeTime may be inaccurate + } + if (AltPathRequest) + { + CopyCepPathToPathInfo(&AltPathRequest->AlternatePathInfo, + &AltPathRequest->AlternateAckTimeout, &pCEP->PrimaryPath); + AltPathRequest->AlternatePathInfo.Path.P_Key = pCEP->PartitionKey; + AltPathRequest->AlternatePathInfo.Path.Mtu = pCEP->Mtu; + //AltPathRequest->AlternatePathInfo.Path.PktLifeTime may be inaccurate + } + Status = MigratedA(pCEP); + + _DBG_LEAVE_LVL(_DBG_LVL_FUNC_TRACE); + return Status; +} // MigratedReloadA() + +////////////////////////////////////////////////////////////////////////// +// ShutdownA +// CA has been removed while disconnecting +// used for both Active and Passive CEPs +// +// +// INPUTS: +// +// +// +// OUTPUTS: +// +// None. +// +// RETURNS: +// +// FSUCCESS. +// +// IRQL: +// +// This routine is called at IRQL_PASSIVE_LEVEL. +// +FSTATUS +ShutdownA( + IN CM_CEP_OBJECT* pCEP + ) +{ + FSTATUS Status=FPENDING;//FSUCCESS; + + switch (pCEP->State) + { + case CMS_DREQ_SENT: + // Cancel the DREQ timer + CmTimerStop(pCEP, DREQ_TIMER); + /* FALLSTHROUGH */ + case CMS_DREQ_RCVD: + case CMS_SIM_DREQ_RCVD: + // Skip the CMS_TIMEWAIT, CA is gone + CepToIdle(pCEP); + + // Set the shutdown event + SetNotification(pCEP, SYSE_DISCONNECT); + + break; + + + case CMS_TIMEWAIT: + // Cancel the TIMEWAIT timer + CmTimerStop(pCEP, TIMEWAIT_TIMER); + + // Skip the CMS_TIMEWAIT, CA is gone + CepToIdle(pCEP); + + // Is this obj marked for destruction ? + if (BitTest(pCEP->EventFlags, USRE_DESTROY)) + { + // handle the case when the user callback returns and this routine + // gets run because the timewait timer expired. + // We let the CmSystemCallback() proceed with the destruction. + if (AtomicRead(&pCEP->CallbackRefCnt) == 0) + { + DestroyCEP(pCEP); + } + } else { + // make sure user gets an event to indicate end of timewait period + if (pCEP->bTimewaitCallback) + { + SetNotification(pCEP, SYSE_DISCONNECT); + } + } + Status = FSUCCESS; + break; + + default: + + Status = FINVALID_STATE; + break; + + } // switch() + + return Status; + +} // ShutdownA() + + +////////////////////////////////////////////////////////////////////////// +// DisconnectA +// User has called CmDisconnect +// used for both Active and Passive CEPs +// +// INPUTS: +// +// +// +// OUTPUTS: +// +// None. +// +// RETURNS: +// +// FSUCCESS. +// +// IRQL: +// +// This routine is called at IRQL_PASSIVE_LEVEL. +// +FSTATUS +DisconnectA( + IN CM_CEP_OBJECT* pCEP, + IN const CM_DREQUEST_INFO* pDRequest, // Send DREQ + IN const CM_DREPLY_INFO* pDReply // Send DREP + ) +{ + FSTATUS Status=FSUCCESS; // FPENDING ?? + + uint32 dreq_timeout_ms=0; + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, DisconnectA); + + + switch (pCEP->State) + { + case CMS_ESTABLISHED: + case CMS_LAP_SENT: + case CMS_MRA_LAP_RCVD: + case CMS_LAP_RCVD: + case CMS_MRA_LAP_SENT: + + if (pDRequest) + { + //pDRequest->Reserved3 = pCEP->LocalEndPoint.QPN; + + // an RTU or LAP/APR could be on the SendQ + // RTU --> + // DREQ --> + Status = PrepareCepDgrm(pCEP); + if (Status != FSUCCESS) { + _DBG_WARNING((" Unable to send DREQ: Out of CM Dgrms!!!\n", _DBG_PTR(pCEP))); + break; + } + + // Format the DREQ msg + FormatDREQ((CM_MAD*)GsiDgrmGetSendMad(pCEP->pDgrmElement), + pCEP->RemoteEndPoint.QPN, + pDRequest->PrivateData, + CMM_DREQ_USER_LEN, + pCEP->TransactionID, + pCEP->LocalCommID, + pCEP->RemoteCommID); + + // Send out the DREQ + Status = CmDgrmSend(pCEP->pDgrmElement); + if (Status != FSUCCESS) + { + // fall through and let timer retry the send later + _DBG_WARN((" DgrmSend() failed for DREQ!!! <%s>\n", + _DBG_PTR(pCEP), _DBG_PTR(FSTATUS_MSG(Status)))); + Status = FSUCCESS; + } else { + AtomicIncrementVoid(&gCM->Sent.Dreq); + } + + //Status = FPENDING; + if (pCEP->State == CMS_LAP_SENT + || pCEP->State == CMS_MRA_LAP_RCVD) + { + CmTimerStop(pCEP, REQ_TIMER); + } + + CepToDisconnecting(pCEP, CMS_DREQ_SENT); + + pCEP->RetryCount = 0; + dreq_timeout_ms = TimeoutMultToTimeInMs(pCEP->LocalCMTimeout); + CmTimerStart(pCEP, dreq_timeout_ms, DREQ_TIMER); + } + else + { + _DBG_ERROR((" Invalid state!!! <%s>\n", _DBG_PTR(pCEP), + _DBG_PTR(CmGetStateString(pCEP->State)))); + + Status = FINVALID_STATE; + } + + break; + + case CMS_DREQ_RCVD: + + if (pDReply) + { + // uncomment out these 3 lines to have DREQ processing time + // factored into average turnaround time + //uint64 elapsed_us; + //elapsed_us = CmGetElapsedTime(pCEP); + //gCM->turnaround_time_us = UpdateTurnaroundTime(gCM->turnaround_time_us, elapsed_us); + + // just in case a LAP/APR or DREQ is in Send Q + Status = PrepareCepDgrm(pCEP); + if (Status != FSUCCESS) { + _DBG_WARNING((" Unable to send DREP: Out of CM Dgrms!!!\n", _DBG_PTR(pCEP))); + break; + } + + // Format the DREP msg + FormatDREP((CM_MAD*)GsiDgrmGetSendMad(pCEP->pDgrmElement), + pDReply->PrivateData, + CMM_DREP_USER_LEN, + pCEP->TransactionID, + pCEP->LocalCommID, + pCEP->RemoteCommID); + + // Send out the DREP + Status = CmDgrmSend(pCEP->pDgrmElement); + if (Status != FSUCCESS) + { + // fall through when remote end retries, we will resend DREP + _DBG_WARN((" DgrmSend() failed for DREP!!! <%s>\n", + _DBG_PTR(pCEP), _DBG_PTR(FSTATUS_MSG(Status)))); + Status = FSUCCESS; + } else { + AtomicIncrementVoid(&gCM->Sent.Drep); + } + + CepToTimewait(pCEP); + } else { + _DBG_INFO((" Already disconnecting!!! <%s>\n", + _DBG_PTR(pCEP), _DBG_PTR(CmGetStateString(pCEP->State)))); + + Status = FCM_ALREADY_DISCONNECTING; + } + + break; + + case CMS_SIM_DREQ_RCVD: + // to handle the case of a REJ coming in after we sent RTU (possibly + // because server never got our RTU), we simulated an inbound DREQ and + // sent up a DISCONNECT_REQUEST callback. + // As a result the application will call CmDisconnect, + // but we don't want to put a DREP on the wire here. + // Instead we simply move to the timewait state. + // This permits the incoming REJ to simulate a DREQ API sequence. + + if (pDReply) + { + // uncomment out these 3 lines to have DREQ processing time + // factored into average turnaround time + //uint64 elapsed_us; + //elapsed_us = CmGetElapsedTime(pCEP); + //gCM->turnaround_time_us = UpdateTurnaroundTime(gCM->turnaround_time_us, elapsed_us); + + CepToTimewait(pCEP); + Status = FSUCCESS; + } else { + _DBG_INFO((" Already disconnecting!!! <%s>\n", + _DBG_PTR(pCEP), _DBG_PTR(CmGetStateString(pCEP->State)))); + + Status = FCM_ALREADY_DISCONNECTING; + } + break; + + default: + + _DBG_ERROR((" Invalid state!!! .\n", + _DBG_PTR(pCEP), pCEP->LocalCommID, + _DBG_PTR(CmGetStateString(pCEP->State)))); + + Status = FINVALID_STATE; + break; + + } // switch() + + _DBG_LEAVE_LVL(_DBG_LVL_FUNC_TRACE); + + return Status; + +} // DisconnectA() + + +// EOF diff --git a/IbAccess/Common/Ibt/Cm/cm_api.c b/IbAccess/Common/Ibt/Cm/cm_api.c new file mode 100644 index 0000000..3c75bf9 --- /dev/null +++ b/IbAccess/Common/Ibt/Cm/cm_api.c @@ -0,0 +1,3463 @@ +/* BEGIN_ICS_COPYRIGHT4 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT4 ****************************************/ + +// Public header file +#include "ib_cm.h" + +// Private header file +#include "cm_private.h" + +// +// Debug setting +// +#ifdef ICS_LOGGING +//_IB_DBG_PARAM_BLOCK((_DBG_LVL_FATAL | _DBG_LVL_ERROR), _DBG_BREAK_ENABLE, CM_MEM_TAG, "Cm", MOD_CM, Cm); +_IB_DBG_PARAM_BLOCK(_DBG_LVL_ALL, _DBG_BREAK_ENABLE, CM_MEM_TAG, "Cm", MOD_CM, Cm); +#else +_IB_DBG_PARAM_BLOCK(_DBG_LVL_ALL, _DBG_BREAK_DISABLE, CM_MEM_TAG, "CM"); +#endif + + +// +// CM setting (note on Linux Module parameters in CmLoad perform actual init +// of this structure) +// +CM_PARAMS gCmParams={CM_MAX_NDGRM, \ + CM_DGRM_INITIAL, \ + CM_DGRM_LOW_WATER, \ + CM_DGRM_INCREMENT, \ + CM_MAX_CONNECTIONS, \ + CM_REQ_RETRY, \ + CM_REP_RETRY, \ + CM_MAX_BACKLOG, \ + SIDR_REQ_TIMEOUT_MS, \ + CM_TURNAROUND_TIME_MS, \ + CM_MIN_TURNAROUND_TIME_MS, \ + CM_MAX_TURNAROUND_TIME_MS, \ + CM_REUSE_QP, \ + CM_DISABLE_VALIDATION }; + +// +// Global CM context - one per system +// +CM_GLOBAL_CONTEXT* gCM=NULL; + + +////////////////////////////////////////////////////////////////////////// +// CmInit +// +// This routine is called once during system initialization to initialize +// the CM's global context. +// +// INPUTS: +// +// +// OUTPUTS: +// +// None. +// +// RETURNS: +// +// FSUCCESS - Indicates a successful initialization. +// FERROR +// FINSUFFICIENT_RESOURCES +// +// IRQL: +// +// This routine is called at IRQL_PASSIVE_LEVEL. +// + +FSTATUS +CmInit( + IN IBT_COMPONENT_INFO *ComponentInfo + ) +{ + FSTATUS Status=FSUCCESS; + uint32 BufSize= sizeof(MAD); + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, CmInit); + + _TRC_REGISTER(); + + _DBG_INFO(("SilverStorm Technologies Inc. InfiniBand Communication Manager module... \n", _DBG_PTR(__DATE__), _DBG_PTR(__TIME__), _DBG_PTR(BLD_VERSION_STRING))); + + // Verify data structure sizes of msgs on the wire + if (sizeof(CM_MAD) > MAD_BLOCK_SIZE ) + { + _DBG_ERROR(("Invalid data structure sizes!!!\n")); + _DBG_ERROR(("CMM_REQ = %d\n", (int)sizeof(CMM_REQ))); + _DBG_ERROR(("CMM_REP = %d\n", (int)sizeof(CMM_REP))); + _DBG_ERROR(("CMM_REJ = %d\n", (int)sizeof(CMM_REJ))); + _DBG_ERROR(("CMM_RTU = %d\n", (int)sizeof(CMM_RTU))); + _DBG_ERROR(("CMM_MRA = %d\n", (int)sizeof(CMM_MRA))); + _DBG_ERROR(("CMM_DREQ = %d\n", (int)sizeof(CMM_DREQ))); + _DBG_ERROR(("CMM_DREP = %d\n", (int)sizeof(CMM_DREP))); + _DBG_ERROR(("CMM_SIDR_REQ = %d\n", (int)sizeof(CMM_SIDR_REQ))); + _DBG_ERROR(("CMM_SIDR_RESP = %d\n", (int)sizeof(CMM_SIDR_RESP))); + _DBG_ERROR(("CMM_LAP = %d\n", (int)sizeof(CMM_LAP))); + _DBG_ERROR(("CMM_APR = %d\n", (int)sizeof(CMM_APR))); + _DBG_ERROR(("CMM_MSG = %d\n", (int)sizeof(CMM_MSG))); + _DBG_ERROR(("CM_MAD = %d\n", (int)sizeof(CM_MAD))); + + return FERROR; + } + + if (gCM) + { + _DBG_ERROR((" Communication Manager module already initialized!!!\n", _DBG_PTR(gCM))); + + _DBG_LEAVE_LVL(_DBG_LVL_FUNC_TRACE); + + return FERROR; + } + + // Allocate the memory for the global context + gCM = (CM_GLOBAL_CONTEXT*)MemoryAllocate2AndClear(sizeof(CM_GLOBAL_CONTEXT), IBA_MEM_FLAG_PREMPTABLE, CM_MEM_TAG); + if (!gCM) + { + _DBG_ERROR(("Unable to allocate memory for cm global context!!!\n")); + Status = FINSUFFICIENT_MEMORY; + goto failalloc; + } + + // Initialize the global CM context + + // Set the comm ID to a pseudo-random number to prevent previous msg + // interpreted as valid msg. + gCM->CommID = (uint32)GetTimeStamp(); + + // set the StartPSN to a pseudo-random 24 bit number + gCM->StartPSN = (uint32)GetTimeStamp() & 0xffffff; + + gCM->Signature = GetTimeStampSec();//gCM->CommID; + + gCM->turnaround_time_us = MAX((uint64)gCmParams.TurnaroundTimeMs*1000, + (uint64)gCmParams.MinTurnaroundTimeMs*1000); + + // TBD error checks for Init routines below + EventInitState(&gCM->EventObj); + EventInit(&gCM->EventObj); + EventInitState(&gCM->CallbackEventObj); + EventInit(&gCM->CallbackEventObj); + + SpinLockInitState(&gCM->ListLock); + SpinLockInit(&gCM->ListLock); + SpinLockInitState(&gCM->DeviceListLock); + SpinLockInit(&gCM->DeviceListLock); + + QListInitState(&gCM->AllCEPs); + QListInit(&gCM->AllCEPs); + DListInit(&gCM->DeviceList); + + // keyed lists + CM_MapInit(&gCM->TimerMap, NULL); + CM_MapInit(&gCM->LocalCommIDMap, NULL); + CM_MapInit(&gCM->LocalEndPointMap, CepLocalEndPointCompare); + CM_MapInit(&gCM->RemoteEndPointMap, CepRemoteEndPointCompare); + + // State based lists + CM_MapInit(&gCM->QueryMap, NULL); + CM_MapInit(&gCM->ListenMap, CepListenAddrCompare); + + QListInitState(&gCM->ApcRetryList); + QListInit(&gCM->ApcRetryList); + TimerInitState(&gCM->ApcRetryTimer); + Status = TimerInit(&gCM->ApcRetryTimer, ApcRetryTimerCallback, NULL ); + if (!Status) + { + _DBG_ERROR(("!!!TimerInit() failed!!! <%s>\n", _DBG_PTR(FSTATUS_MSG(Status)))); + goto failtimer; + } + + // Register with GSA + Status = iba_gsi_register_class(MCLASS_COMM_MGT, + IB_COMM_MGT_CLASS_VERSION, + GSI_REGISTER_RESPONDER, // Register as a Responder + FALSE, // No SAR cap needed + gCM, // Context + GsaSendCompleteCallback, + GsaRecvCallback, + &gCM->GSAHandle); + + if (Status != FSUCCESS) + { + _DBG_ERROR((" Unable to register with GSA!!! <%s>\n", + _DBG_PTR(gCM), _DBG_PTR(FSTATUS_MSG(Status)))); + goto failregister; + } + + // Create the datagram pool + Status = iba_gsi_create_growable_dgrm_pool(gCM->GSAHandle, + gCmParams.PreallocDgrms, + 1, + &BufSize, + 0, + &gCM->GSADgrmPoolHandle); + if (Status != FSUCCESS) + { + _DBG_ERROR((" Unable to create datagram pool!!! <%s>\n", + _DBG_PTR(gCM), _DBG_PTR(FSTATUS_MSG(Status)))); + goto failpool; + } + + // + // Initialize system callback facility + // + + // If everything goes well, setup the minimum entry pts + ComponentInfo->AddDevice = CmDeviceInit; + ComponentInfo->RemoveDevice = CmDeviceDestroy; + ComponentInfo->Unload = CmDestroy; + + _DBG_INFO((" *** CM module setting ***\n", _DBG_PTR(gCM))); + + _DBG_INFO(("\t\tClass Id = %d\n", MCLASS_COMM_MGT)); + _DBG_INFO(("\t\tClass Version = %d\n", IB_COMM_MGT_CLASS_VERSION)); + + _DBG_INFO(("\t\tInitial lcid = 0x%x\n", gCM->CommID)); + _DBG_INFO(("\t\tInitial PSN = 0x%x\n", gCM->StartPSN)); + _DBG_INFO(("\t\tSignature = %u\n", gCM->Signature)); + _DBG_INFO(("\t\tCEP size = %u\n", (unsigned)sizeof(CM_CEP_OBJECT))); + + _DBG_INFO(("\t\tMaxDgrms = %u\n", gCmParams.MaxDgrms)); + _DBG_INFO(("\t\tPreallocDgrms = %u\n", gCmParams.PreallocDgrms)); + _DBG_INFO(("\t\tMinFreeDgrms = %u\n", gCmParams.MinFreeDgrms)); + _DBG_INFO(("\t\tDgrmIncrement = %u\n", gCmParams.DgrmIncrement)); + _DBG_INFO(("\t\tMaxConns = %u\n", gCmParams.MaxConns)); + _DBG_INFO(("\t\tMaxReqRetry = %u\n", gCmParams.MaxReqRetry)); + _DBG_INFO(("\t\tMaxRepRetry = %u\n", gCmParams.MaxRepRetry)); + _DBG_INFO(("\t\tMaxBackLog = %u\n", gCmParams.MaxBackLog)); + _DBG_INFO(("\t\tSidrReqTimeoutMs = %u\n", gCmParams.SidrReqTimeoutMs)); + _DBG_INFO(("\t\tTurnaroundTimeMs = %u\n", gCmParams.TurnaroundTimeMs)); + _DBG_INFO(("\t\tMinTurnaroundTimeMs = %u\n", gCmParams.MinTurnaroundTimeMs)); + _DBG_INFO(("\t\tMaxTurnaroundTimeMs = %u\n", gCmParams.MaxTurnaroundTimeMs)); + _DBG_INFO(("\t\tReuseQP = %u\n", gCmParams.ReuseQP)); + + _DBG_INFO((" *** CM module initialized successfully ***\n", _DBG_PTR(gCM))); + + _DBG_LEAVE_LVL(_DBG_LVL_FUNC_TRACE); + + return FSUCCESS; + +failpool: + iba_gsi_deregister_class(gCM->GSAHandle); +failregister: + TimerDestroy(&gCM->ApcRetryTimer); +failtimer: + SpinLockDestroy(&gCM->DeviceListLock); + SpinLockDestroy(&gCM->ListLock); + EventDestroy(&gCM->CallbackEventObj); + EventDestroy(&gCM->EventObj); + MemoryDeallocate(gCM); +failalloc: + _DBG_LEAVE_LVL(_DBG_LVL_FUNC_TRACE); + return Status; + +} // CmInit() + + +////////////////////////////////////////////////////////////////////////// +// CmDestroy() +// +// This routine is called once during system destruction to release any resources +// used by CM. +// +// INPUTS: +// +// +// OUTPUTS: +// +// None. +// +// RETURNS: +// +// FSUCCESS - Indicates a successful initialization. +// +// IRQL: +// +// This routine is called at IRQL_PASSIVE_LEVEL. +// + +void +CmDestroy( + ) +{ + LIST_ITEM* pListItem=NULL; + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, CmDestroy); + + // If there are oustanding callbacks, wait till those callbacks return + if (AtomicRead(&gCM->TotalCallbackRefCnt)) + { + _DBG_WARNING((" *** There are still outstanding callbacks in the queue ***\n", _DBG_PTR(gCM), AtomicRead(&gCM->TotalCallbackRefCnt))); + + EventWaitOn(&gCM->CallbackEventObj, EVENT_NO_TIMEOUT); + } + + // Cleanup and release the resources associated with the CEP objects + SpinLockAcquire(&gCM->ListLock); + + while ((pListItem = QListHead(&gCM->AllCEPs)) != NULL) + { + CM_CEP_OBJECT* pCEP= (CM_CEP_OBJECT*)QListObj(pListItem); + _DBG_WARNING((" *** Cleaning up...***\n", _DBG_PTR(pCEP), + _DBG_PTR(CmGetStateString(pCEP->State)))); + + switch (pCEP->State) + { + case CMS_IDLE: + break; + + // Listening + case CMS_LISTEN: + case CMS_REGISTERED: + ASSERT(! pCEP->bPeer); + while (!DListIsEmpty(&pCEP->PendingList)) + { + CM_CEP_OBJECT* pCEP1=NULL; + DLIST_ENTRY* pListEntry=NULL; + + pListEntry = DListGetNext(&pCEP->PendingList); + pCEP1 = PARENT_STRUCT(pListEntry, CM_CEP_OBJECT, PendingListEntry); + _DBG_WARNING((" *** Cleaning up...***\n", + _DBG_PTR(pCEP1), _DBG_PTR(CmGetStateString(pCEP1->State)))); + ASSERT(pCEP1->pParentCEP == pCEP); + CepRemoveFromPendingList(pCEP1); + CepToIdle(pCEP1); + DestroyCEP(pCEP1); + } + ASSERT(pCEP->PendingCount == 0); + CM_MapRemoveEntry(&gCM->ListenMap, &pCEP->MapEntry, LISTEN_LIST, pCEP); + break; + + // Pending Connection + case CMS_REQ_RCVD: // passive + case CMS_MRA_REQ_SENT: // passive + CepRemoveFromPendingList(pCEP); + break; + + // Connecting + case CMS_REQ_SENT: // active + case CMS_REP_WAIT: // active + if (pCEP->bPeer && pCEP->RemoteEndPoint.CaGUID == 0) + { + CM_MapRemoveEntry(&gCM->ListenMap, &pCEP->MapEntry, LISTEN_LIST, pCEP); + } + break; + + case CMS_REP_SENT: // passive + case CMS_MRA_REP_RCVD: // passive + case CMS_REP_RCVD: // active + case CMS_MRA_REP_SENT: // active + // connected + case CMS_ESTABLISHED: + case CMS_LAP_SENT: + case CMS_MRA_LAP_RCVD: + case CMS_LAP_RCVD: + case CMS_MRA_LAP_SENT: + // disconnecting + case CMS_DREQ_SENT: + case CMS_DREQ_RCVD: + case CMS_SIM_DREQ_RCVD: + case CMS_TIMEWAIT: + break; + + // SIDR query in progress + case CMS_SIDR_REQ_SENT: + CM_MapRemoveEntry(&gCM->QueryMap, &pCEP->MapEntry, QUERY_LIST, pCEP); + break; + + // SIDR response in progress + case CMS_SIDR_REQ_RCVD: + CepRemoveFromPendingList(pCEP); + break; + } + if (pCEP->State != CMS_IDLE) + CepToIdle(pCEP); + DestroyCEP(pCEP); + } + + ASSERT(QListIsEmpty(&gCM->AllCEPs)); + ASSERT(CM_MapIsEmpty(&gCM->TimerMap)); + ASSERT(CM_MapIsEmpty(&gCM->LocalCommIDMap)); + ASSERT(CM_MapIsEmpty(&gCM->LocalEndPointMap)); + ASSERT(CM_MapIsEmpty(&gCM->RemoteEndPointMap)); + ASSERT(CM_MapIsEmpty(&gCM->QueryMap)); + ASSERT(CM_MapIsEmpty(&gCM->ListenMap)); + ASSERT(QListIsEmpty(&gCM->ApcRetryList)); + + // Invalidate the signature so that user cannot use any cep handles it already has. + gCM->Signature = 0; + + SpinLockRelease(&gCM->ListLock); + + _TRC_UNREGISTER(); + + // Destroy the datagram pool + if (gCM->GSADgrmPoolHandle) + iba_gsi_destroy_dgrm_pool(gCM->GSADgrmPoolHandle); + + _DBG_INFO((" *** Deregister from GSA ***\n", + _DBG_PTR(gCM), _DBG_PTR(gCM->GSAHandle))); + + iba_gsi_deregister_class(gCM->GSAHandle); + + TimerDestroy(&gCM->ApcRetryTimer); + QListDestroy(&gCM->ApcRetryList); + + QListDestroy(&gCM->AllCEPs); + + SpinLockDestroy(&gCM->ListLock); + SpinLockDestroy(&gCM->DeviceListLock); + + EventDestroy(&gCM->EventObj); + EventDestroy(&gCM->CallbackEventObj); + + _DBG_INFO((" *** Free the cm context ***\n", _DBG_PTR(gCM))); + + MemoryDeallocate(gCM); + + gCM = NULL; + + _DBG_LEAVE_LVL(_DBG_LVL_FUNC_TRACE); + + return; + +} // CmDestroy() + + +////////////////////////////////////////////////////////////////////////// +// CmDeviceInit() +// +// This routine is called once for every new device added. +// +// INPUTS: +// +// +// OUTPUTS: +// +// None. +// +// RETURNS: +// +// FSUCCESS - Indicates a successful initialization. +// +// IRQL: +// +// This routine is called at IRQL_PASSIVE_LEVEL. +// +FSTATUS +CmDeviceInit( + IN EUI64 CaGuid, + OUT void **Context + ) +{ + CM_DEVICE_OBJECT* pDevice=NULL; + FSTATUS Status=FSUCCESS; + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, CmDeviceInit); + + //_DBG_BREAK; + + // Allocate the memory for the device context + pDevice = (CM_DEVICE_OBJECT*)MemoryAllocateAndClear(sizeof(CM_DEVICE_OBJECT), FALSE, CM_MEM_TAG); + if (!pDevice) + { + _DBG_ERROR((" Unable to allocate memory for device context!!!\n", _DBG_PTR(gCM))); + + _DBG_LEAVE_LVL(_DBG_LVL_FUNC_TRACE); + + return FINSUFFICIENT_MEMORY; + } + + // TODO: + // pDevice->pDeviceContext = ; + + pDevice->CaGUID = CaGuid; + +#ifdef _CM_EVENT_ON_QP_ + + Status = iba_open_ca( CaGuid, VpdCompletionCallback, VpdAsyncEventCallback, + pDevice, // Context + &pDevice->CaHandle); + if (Status != FSUCCESS) + { + + _DBG_ERROR((" Unable to create datagram pool!!! <%s>\n", + _DBG_PTR(gCM), _DBG_PTR(FSTATUS_MSG(Status)))); + goto failopen; + } + Status = SetCAInternal(pDevice->CaHandle); + if (FSUCCESS != Status) + { + _DBG_ERROR((" Unable to set CA as internal!!! <%s>\n", + _DBG_PTR(gCM), _DBG_PTR(FSTATUS_MSG(Status)))); + goto failinternal; + } + + iba_register_cm(pDevice->CaHandle); + + _DBG_INFO((" +++ Opening CA +++ \n", _DBG_PTR(pDevice), _DBG_PTR(pDevice->CaHandle))); + +#endif + + // Put it on the device list + SpinLockAcquire(&gCM->DeviceListLock); + + DListInsertTail(&gCM->DeviceList, &pDevice->DeviceListEntry, DEVICE_LIST, pDevice); + + SpinLockRelease(&gCM->DeviceListLock); + + *Context = (void*)pDevice; + + _DBG_INFO((" +++ Device Added +++ \n", _DBG_PTR(pDevice), CaGuid)); + +done: + _DBG_LEAVE_LVL(_DBG_LVL_FUNC_TRACE); + + return Status; + +failinternal: + (void)iba_close_ca(pDevice->CaHandle); +failopen: + MemoryDeallocate(pDevice); + goto done; +} // CmDeviceInit() + + +////////////////////////////////////////////////////////////////////////// +// CmDeviceDestroy() +// +// This routine is called once for every device removed. +// +// INPUTS: +// +// +// OUTPUTS: +// +// None. +// +// RETURNS: +// +// FSUCCESS - Indicates a successful initialization. +// +// IRQL: +// +// This routine is called at IRQL_PASSIVE_LEVEL. +// +FSTATUS +CmDeviceDestroy( + IN EUI64 CaGuid, + IN void *Context + ) +{ + CM_DEVICE_OBJECT* pDevice=(CM_DEVICE_OBJECT*)Context; + // keep this const and off stack to save kernel stack space + static CM_DREQUEST_INFO DisconnectReq = {{0}}; + LIST_ITEM* pListItem; + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, CmDeviceDestroy); + + if (!pDevice) + { + _DBG_LEAVE_LVL(_DBG_LVL_FUNC_TRACE); + + return FERROR; + } + + SpinLockAcquire(&gCM->ListLock); + + for (pListItem = QListHead(&gCM->AllCEPs); pListItem != NULL;) + { + CM_CEP_OBJECT* pCEP= (CM_CEP_OBJECT*)QListObj(pListItem); + pListItem = QListNext(&gCM->AllCEPs, pListItem); // in case we delete + if (pCEP->LocalEndPoint.CaGUID != pDevice->CaGUID) + continue; // skip, not on this device + + _DBG_INFO((" *** CA Device Removed ***\n", + _DBG_PTR(pCEP), _DBG_PTR(CmGetStateString(pCEP->State)))); + + // BUGBUG - these need to be reviewed and adjusted. Many of these + // would surprise an application. For example SYSE_DISCONNECT + // would cause a FCM_DISCONNECTED without a FCM_DISCONNECT_REQUEST + // so application would skip moving QP to Error. + // May be better to do these operations, move CEP to Idle + // and always set SYSE_DISCONNECT, then have SYSE_DISCONNECT return a + // unique error code. + switch (pCEP->State) + { + // not expected to have a LocalEndPoint.CaGUID assigned + case CMS_IDLE: + case CMS_REGISTERED: + ASSERT(0); + break; + + // Listening + case CMS_LISTEN: + ASSERT(! pCEP->bPeer); + ASSERT(pCEP->Mode == CM_MODE_PASSIVE); + (void)CancelP(pCEP); + // TBD SetNotification(pCEP, SYSE_DISCONNECT); + break; + + // Connecting + case CMS_REQ_SENT: // active + case CMS_REP_WAIT: // active + case CMS_REQ_RCVD: // passive + case CMS_MRA_REQ_SENT: // passive + case CMS_REP_SENT: // passive + case CMS_MRA_REP_RCVD: // passive + case CMS_REP_RCVD: // active + case CMS_MRA_REP_SENT: // active + // BUGBUG - for CMS_REQ_RCVD/MRA_REQ_SENT, user has been notified, + // they will callback against 1st in pending list + // which could be this one + if (pCEP->Mode == CM_MODE_PASSIVE) + (void)CancelP(pCEP); + else + (void)CancelA(pCEP); + // TBD SetNotification(pCEP, SYSE_DISCONNECT); + break; + + // connected + case CMS_ESTABLISHED: + case CMS_LAP_SENT: + case CMS_MRA_LAP_RCVD: + case CMS_LAP_RCVD: + case CMS_MRA_LAP_SENT: + (void)DisconnectA(pCEP, &DisconnectReq, NULL); + // TBD move to pCEP to Idle + // TBD SetNotification(pCEP, SYSE_DISCONNECT); + break; + + // disconnecting + case CMS_DREQ_SENT: + case CMS_DREQ_RCVD: + case CMS_SIM_DREQ_RCVD: + case CMS_TIMEWAIT: + (void)ShutdownA(pCEP); + break; + + // SIDR query in progress + case CMS_SIDR_REQ_SENT: + (void)CancelA(pCEP); + // TBD SetNotification(pCEP, CME_TIMEOUT_SIDR_REQ); + break; + + // SIDR response in progress + case CMS_SIDR_REQ_RCVD: + // TBD - user has been notified, they will callback + // against 1st in pending list which could be this one + (void)CancelP(pCEP); + break; + } + } + + SpinLockRelease(&gCM->ListLock); + + // Remove the device obj + SpinLockAcquire(&gCM->DeviceListLock); + + DListRemoveEntry(&pDevice->DeviceListEntry, DEVICE_LIST, pDevice); + + if (DListIsEmpty(&gCM->DeviceList)) + { + _DBG_INFO((" --- Removing last device --- \n", _DBG_PTR(pDevice), CaGuid)); + } + + SpinLockRelease(&gCM->DeviceListLock); + +#ifdef _CM_EVENT_ON_QP_ + + iba_close_ca( pDevice->CaHandle ); + + _DBG_INFO((" --- Closing CA --- \n", _DBG_PTR(pDevice), _DBG_PTR(pDevice->CaHandle))); + +#endif + + MemoryDeallocate(pDevice); + + _DBG_INFO((" --- Device Removed --- \n", _DBG_PTR(pDevice), CaGuid)); + + _DBG_LEAVE_LVL(_DBG_LVL_FUNC_TRACE); + + return FSUCCESS; + +} // CmDeviceDestroy() + + +////////////////////////////////////////////////////////////////////////// +// iba_cm_create_cep +// +// +// +// INPUTS: +// +// +// +// OUTPUTS: +// +// None. +// +// RETURNS: +// +// FSUCCESS. +// +// IRQL: +// +// This routine is called at IRQL_PASSIVE_LEVEL. +// +IB_HANDLE +iba_cm_create_cep( + CM_CEP_TYPE TransportServiceType + ) +{ + CM_CEP_OBJECT* pCEP=NULL; + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, iba_cm_create_cep); + + if (!gCM) + { + _DBG_ERROR(("CM Context not initialized!!!\n")); + _DBG_LEAVE_LVL(_DBG_LVL_FUNC_TRACE); + return NULL; + } + + SpinLockAcquire(&gCM->ListLock); + + pCEP = CreateCEP(TransportServiceType, NULL, NULL); + + SpinLockRelease(&gCM->ListLock); + + _DBG_LEAVE_LVL(_DBG_LVL_FUNC_TRACE); + return (IB_HANDLE)pCEP; + +} // iba_cm_create_cep() + + +IB_HANDLE +CmCreateCEPEx( + CM_CEP_TYPE TransportServiceType, + EVENT_HANDLE hEvent, + EVENT_HANDLE hWaitEvent + ) +{ + CM_CEP_OBJECT* pCEP=NULL; + + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, CmCreateCEPEx); + + if (!gCM) + { + _DBG_ERROR(("CM Context not initialized!!!\n")); + _DBG_LEAVE_LVL(_DBG_LVL_FUNC_TRACE); + return NULL; + } + + SpinLockAcquire(&gCM->ListLock); + + pCEP = CreateCEP(TransportServiceType, hEvent, hWaitEvent); + + SpinLockRelease(&gCM->ListLock); + + _DBG_LEAVE_LVL(_DBG_LVL_FUNC_TRACE); + return (IB_HANDLE)pCEP; + +} // CmCreateCEPEx() + + +////////////////////////////////////////////////////////////////////////// +// iba_cm_destroy_cep +// +// +// +// INPUTS: +// +// +// +// OUTPUTS: +// +// None. +// +// RETURNS: +// +// FSUCCESS. +// +// IRQL: +// +// This routine is called at IRQL_PASSIVE_LEVEL. +// +FSTATUS +iba_cm_destroy_cep(IB_HANDLE hCEP) +{ + CM_CEP_OBJECT* pCEP = (CM_CEP_OBJECT*)hCEP; + DLIST_ENTRY* pListEntry=NULL; + CM_CEP_OBJECT* pCEPEntry=NULL; + FSTATUS Status=FSUCCESS; + + // keep this const and off stack to save kernel stack space + static CM_REJECT_INFO RejectInfo = { + Reason:RC_USER_REJ, + RejectInfoLen:0, + }; + static CM_DREQUEST_INFO DisconnectReq = {{0}}; + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, iba_cm_destroy_cep); + + Status = ValidateCEPHandle(pCEP); + if (Status != FSUCCESS) + { + _DBG_WARN((" ValidateCEPHandle() failed!!! <%s>\n", + _DBG_PTR(pCEP), _DBG_PTR(FSTATUS_MSG(Status)))); + + _DBG_LEAVE_LVL(_DBG_LVL_FUNC_TRACE); + + return Status; + } + + SpinLockAcquire(&gCM->ListLock); + + switch (pCEP->State) + { + + case CMS_IDLE: + + // If a callback is in progress, we cannot destroy. Mark it and defer it to the callback + if (AtomicRead(&pCEP->CallbackRefCnt)) + { + BitSet(pCEP->EventFlags, USRE_DESTROY); + } else { + DestroyCEP(pCEP); + } + + break; + + case CMS_REQ_SENT: + case CMS_REP_WAIT: + + // Cancel the request and destroy the obj. + CancelA(pCEP); + + if (AtomicRead(&pCEP->CallbackRefCnt)) + { + BitSet(pCEP->EventFlags, USRE_DESTROY); + } else { + DestroyCEP(pCEP); + } + + break; + + case CMS_REP_RCVD: + case CMS_MRA_REP_SENT: + // Reject the reply and destroy the obj + RejectA(pCEP, &RejectInfo); + + // If a callback is in progress, we cannot destroy. Mark it and defer it to the callback + if (AtomicRead(&pCEP->CallbackRefCnt)) + { + BitSet(pCEP->EventFlags, USRE_DESTROY); + } else { + DestroyCEP(pCEP); + } + + break; + + case CMS_LISTEN: + case CMS_REQ_RCVD: + case CMS_MRA_REQ_SENT: + + CancelP(pCEP); + + // If a callback is in progress, we cannot destroy. Mark it and defer it to the callback + if (AtomicRead(&pCEP->CallbackRefCnt)) + { + BitSet(pCEP->EventFlags, USRE_DESTROY); + } else { + DestroyCEP(pCEP); + } + + break; + + case CMS_REP_SENT: + case CMS_MRA_REP_RCVD: + + CancelP(pCEP); + + // If a callback is in progress, we cannot destroy. Mark it and defer it to the callback + if (AtomicRead(&pCEP->CallbackRefCnt)) + { + BitSet(pCEP->EventFlags, USRE_DESTROY); + } else { + DestroyCEP(pCEP); + } + + break; + + case CMS_ESTABLISHED: + case CMS_LAP_SENT: + case CMS_MRA_LAP_RCVD: + case CMS_LAP_RCVD: + case CMS_MRA_LAP_SENT: + case CMS_DREQ_RCVD: + case CMS_SIM_DREQ_RCVD: + + // Let the CEP state determine if we are sending a DREQ or DREP + DisconnectA(pCEP, &DisconnectReq, (CM_DREPLY_INFO*)&DisconnectReq); + + _DBG_INFO((" *** CEP object marked for destruction *** .\n", + _DBG_PTR(pCEP), pCEP->LocalCommID, pCEP->RemoteCommID, + _DBG_PTR(CmGetStateString(pCEP->State)))); + + BitSet(pCEP->EventFlags, USRE_DESTROY); + + break; + + case CMS_DREQ_SENT: + case CMS_TIMEWAIT: + // + // We cant destroy the object until timewait expires. + // + _DBG_INFO((" *** CEP object marked for destruction *** .\n", + _DBG_PTR(pCEP), pCEP->LocalCommID, pCEP->RemoteCommID, + _DBG_PTR(CmGetStateString(pCEP->State)))); + + BitSet(pCEP->EventFlags, USRE_DESTROY); + + break; + + case CMS_SIDR_REQ_SENT: + // + // Cancel the sidr request + // + + // Cancel the SIDR_REQ timer + CmTimerStop(pCEP, SIDR_REQ_TIMER); + + // Move from QUERY to INIT list + CM_MapRemoveEntry(&gCM->QueryMap, &pCEP->MapEntry, QUERY_LIST, pCEP); + // ClearEndPoint in CepToIdle is benign + CepToIdle(pCEP); + + // Set the cancel event + // TBD this sets CallbackRefCnt and forces destroy to occur + // in callback path below + SetNotification(pCEP, USRE_CANCEL); + + // If a callback is in progress, we cannot destroy. Mark it and defer it to the callback + if (AtomicRead(&pCEP->CallbackRefCnt)) + { + BitSet(pCEP->EventFlags, USRE_DESTROY); + } else { + DestroyCEP(pCEP); + } + + break; + + /* + case CMS_SIDR_RESP_RCVD: + + // ClearEndPoint in CepToIdle is benign + CepToIdle(pCEP); + + // If a callback is in progress, we cannot destroy. Mark it and defer it to the callback + if (AtomicRead(&pCEP->CallbackRefCnt)) + { + BitSet(pCEP->EventFlags, USRE_DESTROY); + } else { + DestroyCEP(pCEP); + } + + break; + */ + + case CMS_REGISTERED: + // Clear the pending list + while (!DListIsEmpty(&pCEP->PendingList)) + { + pListEntry = DListGetNext(&pCEP->PendingList); + pCEPEntry = PARENT_STRUCT(pListEntry, CM_CEP_OBJECT, PendingListEntry); + + // Move from PENDING to INIT list and destroy it + ASSERT(pCEPEntry->pParentCEP == pCEP); + CepRemoveFromPendingList(pCEPEntry); + // ClearEndPoint in CepToIdle is benign + CepToIdle(pCEPEntry); + + // This will start the timer in timewait state + DestroyCEP(pCEPEntry); + } + ASSERT(pCEP->PendingCount == 0); + + // Move from LISTEN to IDLE + CM_MapRemoveEntry(&gCM->ListenMap, &pCEP->MapEntry, LISTEN_LIST, pCEP); + // ClearEndPoint in CepToIdle is benign + CepToIdle(pCEP); + + // Set the cancel event + // TBD this sets CallbackRefCnt and forces destroy to occur + // in callback path below + SetNotification(pCEP, USRE_CANCEL); + + // If a callback is in progress, we cannot destroy. + // Mark it and the callback will destroy it + if (AtomicRead(&pCEP->CallbackRefCnt)) + { + BitSet(pCEP->EventFlags, USRE_DESTROY); + } else { + DestroyCEP(pCEP); + } + + break; + + default: + + _DBG_WARNING((" - Invalid state to destroy cep!!", _DBG_PTR(pCEP))); + Status = FINVALID_STATE; + + break; + + } // switch() + + SpinLockRelease(&gCM->ListLock); + + _DBG_LEAVE_LVL(_DBG_LVL_FUNC_TRACE); + + return Status; + +} // iba_cm_destroy_cep() + + +////////////////////////////////////////////////////////////////////////// +// iba_cm_modify_cep +// +// +// +// INPUTS: +// +// +// +// OUTPUTS: +// +// None. +// +// RETURNS: +// +// FSUCCESS. +// +// IRQL: +// +// This routine is called at IRQL_PASSIVE_LEVEL. +// +FSTATUS +iba_cm_modify_cep( + IB_HANDLE hCEP, + uint32 AttrType, + const char* AttrValue, + uint32 AttrLen, + uint32 Offset + ) +{ + CM_CEP_OBJECT* pCEP = (CM_CEP_OBJECT*)hCEP; + FSTATUS Status=FSUCCESS; + uint32 Value=0; + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, iba_cm_modify_cep); + + Status = ValidateCEPHandle(pCEP); + if (Status != FSUCCESS) + { + _DBG_WARN((" ValidateCEPHandle() failed!!! <%s>\n", + _DBG_PTR(pCEP), _DBG_PTR(FSTATUS_MSG(Status)))); + goto done; + } + + SpinLockAcquire(&gCM->ListLock); + + if (AttrType == CM_FLAG_LISTEN_NODISCRIM) + { + _DBG_INFO((" Modifying CEP to listen with no discriminator parsing.\n", _DBG_PTR(pCEP))); + // must set before start listening + if (pCEP->State != CMS_IDLE) + { + Status = FINVALID_STATE; + goto unlock; + } + pCEP->DiscriminatorLen = 0; + pCEP->DiscrimPrivateDataOffset = 0; + if (pCEP->Discriminator) + { + MemoryDeallocate(pCEP->Discriminator); + pCEP->Discriminator = NULL; + } + } else if (AttrType == CM_FLAG_LISTEN_DISCRIM) { + uint8 *p; + // must set before start listening + if (pCEP->State != CMS_IDLE) + { + Status = FINVALID_STATE; + goto unlock; + } + if ((AttrLen + Offset) > CM_MAX_DISCRIMINATOR_LEN) + { + _DBG_ERROR((" - Invalid discriminator length and offset!!! \n", + _DBG_PTR(pCEP), AttrLen, Offset)); + Status = FINVALID_PARAMETER; + goto unlock; + } + p = (uint8*)MemoryAllocate(AttrLen, FALSE, CM_MEM_TAG); + if (p == NULL) + { + _DBG_ERROR((" - Unable to allocate discriminator!!! \n", + _DBG_PTR(pCEP), AttrLen)); + Status = FINSUFFICIENT_MEMORY; + goto unlock; + } + _DBG_INFO((" Modifying CEP to listen with discriminator parsing .\n", + _DBG_PTR(pCEP), AttrLen, Offset)); + pCEP->DiscrimPrivateDataOffset = (uint8)Offset; + pCEP->DiscriminatorLen = (uint8)AttrLen; + if (pCEP->Discriminator) + MemoryDeallocate(pCEP->Discriminator); + pCEP->Discriminator = p; + MemoryCopy(pCEP->Discriminator, AttrValue, AttrLen); + } else if (AttrType == CM_FLAG_LISTEN_BACKLOG) { + if (AttrLen != sizeof(uint32)) + { + Status = FINVALID_PARAMETER; + goto unlock; + } + MemoryCopy(&pCEP->ListenBackLog, AttrValue, AttrLen); + _DBG_INFO((" Modifying CEP to new backlog count .\n", _DBG_PTR(pCEP), pCEP->ListenBackLog)); + } else if (AttrType == CM_FLAG_SIDR_REGISTER_NOTIFY) { + if (AttrLen != sizeof(uint32)) + { + Status = FINVALID_PARAMETER; + goto unlock; + } + MemoryCopy(&Value, AttrValue, AttrLen); + pCEP->bSidrRegisterNotify = (boolean) Value; + _DBG_INFO((" Modifying CEP for Sidr Register notification .\n", _DBG_PTR(pCEP), pCEP->bSidrRegisterNotify)); + } else if (AttrType == CM_FLAG_ASYNC_ACCEPT) { + if (AttrLen != sizeof(uint32)) + { + Status = FINVALID_PARAMETER; + goto unlock; + } + MemoryCopy(&Value, AttrValue, AttrLen); + pCEP->bAsyncAccept = (boolean) Value; + _DBG_INFO((" Modifying CEP for Async Accept .\n", _DBG_PTR(pCEP), pCEP->bAsyncAccept)); + } else if (AttrType == CM_FLAG_TIMEWAIT_CALLBACK) { + if (AttrLen != sizeof(uint32)) + { + Status = FINVALID_PARAMETER; + goto unlock; + } + MemoryCopy(&Value, AttrValue, AttrLen); + pCEP->bTimewaitCallback = (boolean) Value; + _DBG_INFO((" Modifying CEP for Timewait Callback .\n", _DBG_PTR(pCEP), pCEP->bTimewaitCallback)); + } else if (AttrType == CM_FLAG_TURNAROUND_TIME) { + if (AttrLen != sizeof(uint32)) + { + Status = FINVALID_PARAMETER; + goto unlock; + } + MemoryCopy(&Value, AttrValue, AttrLen); + // lower bound is set by Cm parameters + pCEP->turnaround_time_us = MAX(Value, gCmParams.MinTurnaroundTimeMs*1000); + // application is trusted for upper bound, allows for some apps to + // indicate they are very slow + _DBG_INFO((" Modifying CEP for Turnaround time %"PRIu64" us.\n", _DBG_PTR(pCEP), pCEP->turnaround_time_us)); + } else if (AttrType == CM_FLAG_APM) { + if (AttrLen != sizeof(uint32)) + { + Status = FINVALID_PARAMETER; + goto unlock; + } + if (pCEP->Mode == CM_MODE_ACTIVE) + { + Status = FINVALID_STATE; + goto unlock; + } + MemoryCopy(&Value, AttrValue, AttrLen); + pCEP->bFailoverSupported = (boolean) Value; + _DBG_INFO((" Modifying CEP for APM .\n", _DBG_PTR(pCEP), pCEP->bFailoverSupported)); + } else { + Status = FINVALID_PARAMETER; + } + +unlock: + SpinLockRelease(&gCM->ListLock); + +done: + _DBG_LEAVE_LVL(_DBG_LVL_FUNC_TRACE); + + return Status; + +} // iba_cm_modify_cep() + +// help client build a connect request and QP Attrs to move QP to Init +FSTATUS iba_cm_prepare_request( + IN CM_CEP_TYPE TransportServiceType, + IN const IB_PATH_RECORD *Path, + IN OPTIONAL const IB_PATH_RECORD *AltPath, + OUT CM_PREPARE_REQUEST_INFO *Info + ) +{ + FSTATUS Status; + IB_CA_ATTRIBUTES *pCaAttr = NULL; + IB_PORT_ATTRIBUTES *pPortAttr = NULL; + + _DBG_ENTER_FUNC(iba_cm_prepare_request); + + if (TransportServiceType == CM_UD_TYPE || Info == NULL || Path == NULL) + { + Status= FINVALID_PARAMETER; + goto done; + } + + MemoryClear(Info, sizeof(*Info)); + // TBD RD not implemented/accurate + // find CA and port based on SGID + Status = iba_find_gid(&Path->SGID, &Info->Request.CEPInfo.CaGUID, + &Info->Request.CEPInfo.PortGUID, NULL, + &pPortAttr, &pCaAttr); + if (Status != FSUCCESS) + goto done; + + if (! LookupPKey(pPortAttr, Path->P_Key, FALSE, &Info->QpAttrInit.PkeyIndex)) + { + Status = FNOT_FOUND; + goto free; + } + if (pPortAttr) { + MemoryDeallocate(pPortAttr); + pPortAttr = NULL; + } + Info->QpAttrInit.RequestState = QPStateInit; + Info->QpAttrInit.PortGUID = Info->Request.CEPInfo.PortGUID; + Info->QpAttrInit.Attrs = (IB_QP_ATTR_PORTGUID|IB_QP_ATTR_PKEYINDEX); + // application must build AccessControl + + // CaGUID set above + Info->Request.CEPInfo.EndToEndFlowControl = (TransportServiceType != CM_UC_TYPE); + // PortGUID set above + SpinLockAcquire(&gCM->ListLock); + Info->Request.CEPInfo.StartingPSN = GenerateStartPSN(); + SpinLockRelease(&gCM->ListLock); + // provide sensible defaults for retry counts + Info->Request.CEPInfo.RetryCount = IB_MAX_RETRY_COUNT; + Info->Request.CEPInfo.RnrRetryCount = IB_RNR_RETRY_COUNT_INFINITE; + if (TransportServiceType == CM_RC_TYPE) { + Info->Request.CEPInfo.OfferedInitiatorDepth = pCaAttr->MaxQPInitiatorDepth; + Info->Request.CEPInfo.OfferedResponderResources = pCaAttr->MaxQPResponderResources; + } else if (TransportServiceType == CM_RD_TYPE) { + Info->Request.CEPInfo.OfferedInitiatorDepth = pCaAttr->MaxEECInitiatorDepth; + Info->Request.CEPInfo.OfferedResponderResources = pCaAttr->MaxEECResponderResources; + } else { + Info->Request.CEPInfo.OfferedInitiatorDepth = 0; + Info->Request.CEPInfo.OfferedResponderResources = 0; + } + Info->Request.CEPInfo.AckTimeout = ComputeAckTimeout(Path->PktLifeTime, + pCaAttr->LocalCaAckDelay); + Info->Request.PathInfo.bSubnetLocal = ! IsGlobalRoute(Path); + Info->Request.PathInfo.Path = *Path; + if (AltPath && AltPath->SLID) { + // we could let the Alt Path verify be defered to the iba_cm_connect + // however its better to check it now so the client can + // consider different path choices + Status = iba_find_ca_gid2(&AltPath->SGID, Info->Request.CEPInfo.CaGUID, + NULL, NULL, &pPortAttr, NULL); + if (Status != FSUCCESS) + goto free; + if ( Path->P_Key != AltPath->P_Key || + ! LookupPKey(pPortAttr, Path->P_Key, FALSE, NULL)) + { + Status = FNOT_FOUND; + goto free; + } + Info->Request.CEPInfo.AlternateAckTimeout = ComputeAckTimeout( + AltPath->PktLifeTime, pCaAttr->LocalCaAckDelay); + Info->Request.AlternatePathInfo.bSubnetLocal = ! IsGlobalRoute(AltPath); + Info->Request.AlternatePathInfo.Path = *AltPath; + } + // caller must set up + //Info->Request.SID + //Info->Request.CEPInfo.QKey - for RD + //Info->Request.CEPInfo.QPN + //Info->Request.CEPInfo.LocalEECN - for RD + //Info->Request.CEPInfo.RemoteEECN - for RD + // caller may adjust other fields, especially: + // Offered* - may adjust down + // AckTimeout/AlternateAckTimeout - may increase by recomputing + // using a larger value for LocalAckDelay for busy apps like oracle + // RetryCount, RnRRetryCount +free: + if (pCaAttr) + MemoryDeallocate(pCaAttr); + if (pPortAttr) + MemoryDeallocate(pPortAttr); +done: + _DBG_LEAVE_FUNC(); + return Status; +} + +////////////////////////////////////////////////////////////////////////// +// iba_cm_connect +// +// +// INPUTS: +// +// +// +// OUTPUTS: +// +// None. +// +// RETURNS: +// +// FSUCCESS. +// +// IRQL: +// +// This routine is called at IRQL_PASSIVE_LEVEL. +// +FSTATUS +iba_cm_connect( + IB_HANDLE hCEP, + const CM_REQUEST_INFO* pConnectRequest, + PFN_CM_CALLBACK pfnConnectCB, + void* Context + ) +{ + CM_CEP_OBJECT* pCEP=(CM_CEP_OBJECT*)hCEP; + FSTATUS Status = FSUCCESS; + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, iba_cm_connect); + + // Parameter check + Status = ValidateCEPHandle(pCEP); + if (Status != FSUCCESS) + { + _DBG_LEAVE_LVL(_DBG_LVL_FUNC_TRACE); + + return Status; + } + + Status = RequestCheck(pConnectRequest); + if (Status != FSUCCESS) + { + _DBG_LEAVE_LVL(_DBG_LVL_FUNC_TRACE); + + return Status; + } + + SpinLockAcquire(&gCM->ListLock); + + // We must be in idle state + if (pCEP->State != CMS_IDLE) + { + SpinLockRelease(&gCM->ListLock); + + _DBG_LEAVE_LVL(_DBG_LVL_FUNC_TRACE); + + return FINVALID_STATE; + } + + Status = Connect(pCEP, pConnectRequest, FALSE, pfnConnectCB, Context); + + SpinLockRelease(&gCM->ListLock); + + _DBG_LEAVE_LVL(_DBG_LVL_FUNC_TRACE); + + return Status; + +} // iba_cm_connect() + + +////////////////////////////////////////////////////////////////////////// +// iba_cm_connect_peer +// +// +// INPUTS: +// +// +// +// OUTPUTS: +// +// None. +// +// RETURNS: +// +// FSUCCESS. +// +// IRQL: +// +// This routine is called at IRQL_PASSIVE_LEVEL. +// +FSTATUS +iba_cm_connect_peer( + IB_HANDLE hCEP, + const CM_REQUEST_INFO* pConnectRequest, + PFN_CM_CALLBACK pfnConnectCB, + void* Context + ) +{ + CM_CEP_OBJECT* pCEP=(CM_CEP_OBJECT*)hCEP; + FSTATUS Status=FSUCCESS; + + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, iba_cm_connect_peer); + + // Parameter check + Status = ValidateCEPHandle(pCEP); + if (Status != FSUCCESS) + { + _DBG_LEAVE_LVL(_DBG_LVL_FUNC_TRACE); + + return Status; + } + + SpinLockAcquire(&gCM->ListLock); + + // We must be in idle state + if (pCEP->State != CMS_IDLE) + { + SpinLockRelease(&gCM->ListLock); + + _DBG_LEAVE_LVL(_DBG_LVL_FUNC_TRACE); + + return FINVALID_STATE; + } + + Status = Connect(pCEP, pConnectRequest, TRUE, pfnConnectCB, Context); + + SpinLockRelease(&gCM->ListLock); + + _DBG_LEAVE_LVL(_DBG_LVL_FUNC_TRACE); + + return Status; + +} // iba_cm_connect_peer() + + +////////////////////////////////////////////////////////////////////////// +// iba_cm_listen +// +// +// +// INPUTS: +// +// +// +// OUTPUTS: +// +// None. +// +// RETURNS: +// +// FSUCCESS. +// +// IRQL: +// +// This routine is called at IRQL_PASSIVE_LEVEL. +// +FSTATUS +iba_cm_listen( + IN IB_HANDLE hCEP, + IN const CM_LISTEN_INFO* pListenInfo, + IN PFN_CM_CALLBACK pfnListenCB, + IN void* Context + ) +{ + CM_CEP_OBJECT* pCEP=(CM_CEP_OBJECT*)hCEP; + + FSTATUS Status=FSUCCESS; +#ifndef _CM_DIRECTED_LISTENS_ + CM_LISTEN_INFO ListenInfo = *pListenInfo; +#endif + + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, iba_cm_listen); + + // + // Parameter check + // + Status = ValidateCEPHandle(pCEP); + if (Status != FSUCCESS) + { + _DBG_WARN((" ValidateCEPHandle failed!!! <%s >\n", + _DBG_PTR(pCEP), _DBG_PTR(FSTATUS_MSG(Status)))); + + return Status; + } + + // Backward compatibility. Otherwise, incoming requests will be dropped if + // caller does not clear the struct properly +#ifndef _CM_DIRECTED_LISTENS_ + ListenInfo.CaGUID = 0; + + ListenInfo.ListenAddr.Port.LID = 0; + memset(ListenInfo.ListenAddr.Port.GID.Raw, 0, sizeof(IB_GID)); + + ListenInfo.RemoteAddr.Port.LID = 0; + memset(ListenInfo.RemoteAddr.Port.GID.Raw, 0, sizeof(IB_GID)); +#endif + + // Acquire the lock since we need to check if the address space is already in use + // and we may need to move to LISTEN list + SpinLockAcquire(&gCM->ListLock); + + // We must be in idle state + if (pCEP->State != CMS_IDLE) + { + SpinLockRelease(&gCM->ListLock); + + _DBG_ERROR((" Invalid state!!! <%s>\n", + _DBG_PTR(pCEP), _DBG_PTR(CmGetStateString(pCEP->State)))); + + _DBG_LEAVE_LVL(_DBG_LVL_FUNC_TRACE); + + return FINVALID_STATE; + } + +#ifndef _CM_DIRECTED_LISTENS_ + Status = Listen(pCEP, &ListenInfo, pfnListenCB, Context); +#else + Status = Listen(pCEP, pListenInfo, pfnListenCB, Context); +#endif + + SpinLockRelease(&gCM->ListLock); + + _DBG_LEAVE_LVL(_DBG_LVL_FUNC_TRACE); + + return Status; + +} // iba_cm_listen() + + +////////////////////////////////////////////////////////////////////////// +// iba_cm_wait +// +// +// INPUTS: +// +// +// +// OUTPUTS: +// +// None. +// +// RETURNS: +// +// FSUCCESS. +// > +// +// +// FTIMEOUT +// +// IRQL: +// +// This routine is called at IRQL_PASSIVE_LEVEL. +// +FSTATUS +iba_cm_wait( + IB_HANDLE CEPHandleArray[], + CM_CONN_INFO* ConnInfoArray[], + uint32 ArrayCount, + uint32 Timeout_us + //EVENT_HANDLE hWaitEvent // Associate the array of handles to this event + ) +{ + uint32 i=0; + + FSTATUS Status=FSUCCESS; + boolean bSignaled=FALSE; + + uint32 WaitTimeUs=Timeout_us; + uint64 TimeoutUs=Timeout_us; + uint64 StartTimeUs=GetTimeStamp(); + + uint64 CurrTimeUs=0; + uint64 TimeElapsedUs=0; + + + _DBG_ENTER_EXT(_DBG_LVL_FUNC_TRACE, iba_cm_wait, == PASSIVE); + + _DBG_INFO(("iba_cm_wait() \n", ArrayCount, Timeout_us, GetTimeStamp())); + + if ( (ArrayCount == 0) || (ArrayCount > gCmParams.MaxConns) ) + return FINVALID_PARAMETER; + + //if ( (ArrayCount > 1) && (hWaitEvent == NULL) ) + // return FINVALID_PARAMETER; + + while (1) + { + // Update the timeout + if ((int32)WaitTimeUs != EVENT_NO_TIMEOUT) + { + if (CurrTimeUs >= StartTimeUs) + { + TimeElapsedUs = (CurrTimeUs - StartTimeUs); + } + else // wrap-around + { + TimeElapsedUs = (CurrTimeUs + ((uint64)(-1) - StartTimeUs)); + } + + if (TimeoutUs > TimeElapsedUs) + { + WaitTimeUs = (uint32) (TimeoutUs - TimeElapsedUs); + } + else + { + WaitTimeUs = 0; + } + } + + // Walk thru the array to see if the object is signaled + for (i=0; i < ArrayCount; i++) + { + // No need to check obj state if obj is marked for destruction + //if (BitTest((CM_CEP_OBJECT*)CEPHandleArray[i])->EventFlags, USRE_DESTROY)) + //{ + // continue; + //} + + // Associate the CEP object with wait event before + // we call wait() to prevent race condition + //SpinLockAcquire(&gCM->ListLock); + + // TODO: Should we checked to make sure we dont override an existing one ??? + // Otherwise, the other thread could wait forever ?? + ((CM_CEP_OBJECT*)CEPHandleArray[i])->pWaitEvent = &gCM->EventObj;//(EVENT*) hWaitEvent; + + //SpinLockRelease(&gCM->ListLock); + + // Specify 0 timeout as a side-effect to test the CEP object signaled state + // FSUCCESS means the obj is in signaled state, FTIMEOUT means the obj is not in signaled state + if (((CM_CEP_OBJECT*)CEPHandleArray[i])->Mode == CM_MODE_PASSIVE) + Status = WaitP((CM_CEP_OBJECT*)CEPHandleArray[i], ConnInfoArray[i], 0); + else + Status = WaitA((CM_CEP_OBJECT*)CEPHandleArray[i], ConnInfoArray[i], 0); + + // The obj is in signaled state + if (Status == FSUCCESS) + { + //_DBG_INFO((" Wait() returned \n", + // _DBG_PTR(CEPHandleArray[i]), i, + // _DBG_PTR(FSTATUS_MSG(Status)), + // ConnInfoArray[i]->Status)); + + Status = FCM_WAIT_OBJECT0 + i; + + // Event is signaled, there should be additional info in ConnInfo[] + bSignaled = TRUE; + break; + } + else + { + // Status is FTIMEOUT here + //_DBG_INFO((" Wait() returned <%s>\n", + // _DBG_PTR(CEPHandleArray[i]), + // _DBG_PTR(FSTATUS_MSG(Status)))); + + // No cep obj is signaled but if the event obj is signaled, we need to return it + Status = FCM_WAIT_OBJECT0 + ArrayCount; + } + } // for() + + // if no objects' state is signaled..go to wait, otherwise return to the caller + if (bSignaled) + break; + + _DBG_INFO(("Entering wait state \n", Timeout_us, GetTimeStamp())); + + // TODO: Decrement the timeout value + // Wait on all the specified objects using the wait event. + Status = EventWaitOn(&gCM->EventObj/*(EVENT*)hWaitEvent*/, Timeout_us); + bSignaled = TRUE; + _DBG_INFO(("Exiting wait state <%s, %"PRIu64"us>\n", + _DBG_PTR(FSTATUS_MSG(Status)), GetTimeStamp())); + + // We timed out, return to the caller + if (Status == FTIMEOUT) + break; + + } // while() + + _DBG_LEAVE_EXT(_DBG_LVL_FUNC_TRACE); + + return Status; + +} // iba_cm_wait() + + +// Process a inbound request for a server +FSTATUS iba_cm_process_request( + IN IB_HANDLE hCEP, + IN CM_REP_FAILOVER Failover, + OUT CM_PROCESS_REQUEST_INFO *Info + ) +{ + FSTATUS Status; + CM_CEP_OBJECT* pCEP = (CM_CEP_OBJECT*)hCEP; + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, iba_cm_process_request); + if (! Info) + { + Status = FINVALID_PARAMETER; + goto done; + } + Status = ValidateCEPHandle(pCEP); + if (Status != FSUCCESS) + { + _DBG_WARN((" ValidateCEPHandle failed!!! <%s >\n", + _DBG_PTR(pCEP), _DBG_PTR(FSTATUS_MSG(Status)))); + goto done; + } + + SpinLockAcquire(&gCM->ListLock); + if (pCEP->Mode == CM_MODE_PASSIVE) + Status = ProcessRequestP(pCEP, Failover, Info); + else + Status = FINVALID_STATE; + SpinLockRelease(&gCM->ListLock); +done: + _DBG_LEAVE_LVL(_DBG_LVL_FUNC_TRACE); + return Status; +} + +////////////////////////////////////////////////////////////////////////// +// iba_cm_accept +// +// Accept a Connection/Connection Response +// For a Client: +// Should be invoked as the result of a FCM_CONNECT_REPLY callback +// In which case this causes the RTU to be sent. +// pSendConnInfo contains the RTU and pRecvConnInfo is unused +// For a Server: +// Should be invoked as the result of a FCM_CONNECT_REQUEST callback +// In which case this causes the REP to be sent. +// if CM_FLAG_ASYNC_ACCEPT is set in the CEP: +// This returns immediately +// otherwise +// This synchronously waits for the RTU +// +// +// INPUTS: +// +// +// +// OUTPUTS: +// +// None. +// +// RETURNS: +// +// FSUCCESS - Client RTU queued to be sent. +// FPENDING - Server Async Accept, REP queued to be sent. +// FCM_CONNECT_ESTABLISHED - server REP sent and RTU received +// FCM_CONNECT_REJECT - server REP sent and REJ received +// FCM_CONNECT_TIMEOUT - server REP sent and timeout waiting for RTU +// FCM_CONNECT_CANCEL - server listen on this CEP has been cancelled +// +// FINVALID_STATE - The endpoint is not in the valid state for this call +// FERROR - Unable to send the reply ack packet +// FTIMEOUT - The timeout interval expires +// +// +// IRQL: +// +// This routine is called at IRQL_PASSIVE_LEVEL. +// +FSTATUS +iba_cm_accept( + IN IB_HANDLE hCEP, + IN CM_CONN_INFO* pSendConnInfo, // Send REP or RTU + OUT CM_CONN_INFO* pRecvConnInfo, // Rcvd RTU, REJ or TIMEOUT + IN PFN_CM_CALLBACK pfnCallback, + IN void* Context, + OUT IB_HANDLE* hNewCEP + ) +{ + CM_CEP_OBJECT* pCEP = (CM_CEP_OBJECT*)hCEP; + FSTATUS Status; + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, iba_cm_accept); + + Status = ValidateCEPHandle(pCEP); + if (Status != FSUCCESS) + { + _DBG_WARN((" ValidateCEPHandle failed!!! <%s >\n", + _DBG_PTR(pCEP), _DBG_PTR(FSTATUS_MSG(Status)))); + return Status; + } + + if (pCEP->Mode == CM_MODE_PASSIVE) + { + // If we are doing a client/server accept, we will be returning a handle + if (!pCEP->bPeer && hNewCEP == NULL) + { + return FINVALID_PARAMETER; + } + Status = AcceptP(pCEP, pSendConnInfo, pRecvConnInfo, pfnCallback, Context, (CM_CEP_OBJECT**)hNewCEP); + } else { + Status = AcceptA(pCEP, pSendConnInfo); + } + + _DBG_LEAVE_LVL(_DBG_LVL_FUNC_TRACE); + return Status; + +} // iba_cm_accept() + + + +////////////////////////////////////////////////////////////////////////// +// CmAcceptEx +// +// +// INPUTS: +// +// +// +// OUTPUTS: +// +// None. +// +// RETURNS: +// +// FSUCCESS - The function has completed successfully. For server, this indicates the initialization. +// >FCM_CONNECT_ESTABLISHED +// >FCM_CONNECT_REJECT +// >FCM_CONNECT_TIMEOUT +// >FCM_CONNECT_CANCEL +// +// FINVALID_STATE - The endpoint is not in the valid state for this call +// FERROR - Unable to send the reply ack packet +// FTIMEOUT - The timeout interval expires +// +// +// IRQL: +// +// This routine is called at IRQL_PASSIVE_LEVEL. +// +FSTATUS +CmAcceptEx( + IN IB_HANDLE hCEP, + IN CM_CONN_INFO* pSendConnInfo, // Send REP + IN EVENT_HANDLE hEvent, // For hNewCEP + IN EVENT_HANDLE hWaitEvent, // For hNewCEP + IN PFN_CM_CALLBACK pfnCallback, // For hNewCEP + IN void* Context, // For hNewCEP + OUT IB_HANDLE* hNewCEP + ) +{ + CM_CEP_OBJECT* pCEP = (CM_CEP_OBJECT*)hCEP; + FSTATUS Status; + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, CmAcceptEx); + + Status = ValidateCEPHandle(pCEP); + if (Status != FSUCCESS) + { + _DBG_WARN((" ValidateCEPHandle failed!!! <%s>\n", + _DBG_PTR(pCEP), _DBG_PTR(FSTATUS_MSG(Status)))); + return Status; + } + + if (pCEP->Mode == CM_MODE_PASSIVE) + { + // If we are doing a client/server accept, we will be returning a handle + if (!pCEP->bPeer && hNewCEP == NULL) + { + return FINVALID_PARAMETER; + } + + Status = AcceptP_Async(pCEP, pSendConnInfo, hEvent, hWaitEvent, pfnCallback, Context, FALSE, (CM_CEP_OBJECT**)hNewCEP); + } else { + Status = AcceptA(pCEP, pSendConnInfo); + } + + _DBG_LEAVE_LVL(_DBG_LVL_FUNC_TRACE); + return Status; + +} // CmAcceptEx() + + +////////////////////////////////////////////////////////////////////////// +// iba_cm_reject +// +// +// INPUTS: +// +// +// +// OUTPUTS: +// +// None. +// +// RETURNS: +// +// FSUCCESS. +// +// IRQL: +// +// This routine is called at IRQL_PASSIVE_LEVEL. +// +FSTATUS +iba_cm_reject( + IN IB_HANDLE hCEP, + IN const CM_REJECT_INFO* pConnectReject + ) +{ + CM_CEP_OBJECT* pCEP = (CM_CEP_OBJECT*)hCEP; + + FSTATUS Status=FSUCCESS; + + // + // Parameter check + // + Status = ValidateCEPHandle(pCEP); + if (Status != FSUCCESS) + return Status; + + SpinLockAcquire(&gCM->ListLock); + + if (pCEP->Mode == CM_MODE_PASSIVE) + Status = RejectP(pCEP, pConnectReject); + else + Status = RejectA(pCEP, pConnectReject); + + SpinLockRelease(&gCM->ListLock); + + return Status; + +} // iba_cm_reject() + + +////////////////////////////////////////////////////////////////////////// +// iba_cm_cancel +// +// +// INPUTS: +// +// +// +// OUTPUTS: +// +// None. +// +// RETURNS: +// +// FSUCCESS. +// +// IRQL: +// +// This routine is called at IRQL_PASSIVE_LEVEL. +// +FSTATUS +iba_cm_cancel( + IN IB_HANDLE hCEP + ) +{ + CM_CEP_OBJECT* pCEP = (CM_CEP_OBJECT*) hCEP; + + FSTATUS Status=FSUCCESS; + + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, iba_cm_cancel); + + // Parameter check + Status = ValidateCEPHandle(pCEP); + if (Status != FSUCCESS) + { + _DBG_WARN((" ValidateCEPHandle failed!!! <%s>\n", + _DBG_PTR(pCEP), _DBG_PTR(FSTATUS_MSG(Status)))); + + _DBG_LEAVE_LVL(_DBG_LVL_FUNC_TRACE); + return Status; + } + + SpinLockAcquire(&gCM->ListLock); + + if (pCEP->Mode == CM_MODE_PASSIVE) + Status = CancelP(pCEP); + else + Status = CancelA(pCEP); + + SpinLockRelease(&gCM->ListLock); + _DBG_LEAVE_LVL(_DBG_LVL_FUNC_TRACE); + + return Status; +} // iba_cm_cancel() + + +// build QP Attributes to move client QP to RTR and RTS +FSTATUS iba_cm_process_reply( + IN IB_HANDLE hCEP, + OUT CM_PROCESS_REPLY_INFO* Info + ) +{ + CM_CEP_OBJECT* pCEP = (CM_CEP_OBJECT*) hCEP; + FSTATUS Status=FSUCCESS; + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, iba_cm_process_reply); + + // Parameter check + if (! Info) + { + Status = FINVALID_PARAMETER; + goto done; + } + Status = ValidateCEPHandle(pCEP); + if (Status != FSUCCESS) + { + _DBG_WARN((" ValidateCEPHandle failed!!! <%s>\n", + _DBG_PTR(pCEP), _DBG_PTR(FSTATUS_MSG(Status)))); + goto done; + } + + SpinLockAcquire(&gCM->ListLock); + if (pCEP->Mode != CM_MODE_ACTIVE || pCEP->Type == CM_UD_TYPE) + { + Status = FINVALID_STATE; + } else { + Status = ProcessReplyA(pCEP, Info); + } + SpinLockRelease(&gCM->ListLock); +done: + _DBG_LEAVE_LVL(_DBG_LVL_FUNC_TRACE); + + return Status; +} + + +// build QP Attributes to move server QP to RTS for given CEP +FSTATUS iba_cm_prepare_rts( + IN IB_HANDLE hCEP, + OUT IB_QP_ATTRIBUTES_MODIFY *QpAttrRts + ) +{ + CM_CEP_OBJECT* pCEP = (CM_CEP_OBJECT*) hCEP; + FSTATUS Status=FSUCCESS; + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, iba_cm_prepare_rts); + + // Parameter check + if (QpAttrRts == NULL) + { + Status = FINVALID_PARAMETER; + goto done; + } + Status = ValidateCEPHandle(pCEP); + if (Status != FSUCCESS) + { + _DBG_WARN((" ValidateCEPHandle failed!!! <%s>\n", + _DBG_PTR(pCEP), _DBG_PTR(FSTATUS_MSG(Status)))); + goto done; + } + + SpinLockAcquire(&gCM->ListLock); + // TBD - could allow ACTIVE + if (pCEP->Mode != CM_MODE_PASSIVE) + { + Status = FINVALID_STATE; + goto unlock; + } + if (pCEP->Type == CM_UD_TYPE) + { + Status = FINVALID_STATE; + goto unlock; + } + // If allowed for Active these states are ok, probably wouldn't want to + // allow CMS_LAP_SENT, CMS_MRA_LAP_RCVD + // uncomment REP tests below to allow the RTS transtion anytime after + // sending the REP, however it is prefered to not move to RTS until + // the RTU is received + if (pCEP->State != CMS_ESTABLISHED && pCEP->State != CMS_LAP_RCVD + && pCEP->State != CMS_MRA_LAP_SENT + //&& pCEP->State != CMS_REP_SENT && pCEP->State != CMS_MRA_REP_RCVD + ) + { + Status = FINVALID_STATE; + goto unlock; + } + + //MemoryClear(QpAttrRts, sizeof(*QpAttrRts)); // not needed due to Attrs flags + GetRtsAttrFromCep(pCEP, QpAttrRts); +unlock: + SpinLockRelease(&gCM->ListLock); +done: + _DBG_LEAVE_LVL(_DBG_LVL_FUNC_TRACE); + + return Status; +} + +////////////////////////////////////////////////////////////////////////// +// iba_cm_altpath_request +// +// Request a new alternate path +// Only allowed for Client/Active side of connection +// +// INPUTS: +// +// +// +// OUTPUTS: +// +// None. +// +// RETURNS: +// +// FPENDING - LAP queued to be sent. +// FINVALID_STATE - The endpoint is not in the valid state for this call +// FERROR - Unable to send the lap packet +// FINVALID_ARGUMENTS - invalid pLapInfo +// +// +// IRQL: +// +// This routine is called at IRQL_PASSIVE_LEVEL. +// +FSTATUS +iba_cm_altpath_request( + IN IB_HANDLE hCEP, + IN const CM_ALTPATH_INFO* pLapInfo // Send LAP + ) +{ + CM_CEP_OBJECT* pCEP = (CM_CEP_OBJECT*)hCEP; + FSTATUS Status; + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, iba_cm_altpath_request); + + Status = ValidateCEPHandle(pCEP); + if (Status != FSUCCESS) + { + _DBG_WARN((" ValidateCEPHandle failed!!! <%s >\n", + _DBG_PTR(pCEP), _DBG_PTR(FSTATUS_MSG(Status)))); + return Status; + } + + SpinLockAcquire(&gCM->ListLock); + if (pCEP->Mode != CM_MODE_ACTIVE) + { + return FINVALID_STATE; + } else { + Status = AltPathRequestA(pCEP, pLapInfo); + } + SpinLockRelease(&gCM->ListLock); + + _DBG_LEAVE_LVL(_DBG_LVL_FUNC_TRACE); + return Status; + +} // iba_cm_altpath_request() + + +// build QP Attributes to load new alternate path into server QP +// and prepare a Reply +FSTATUS iba_cm_process_altpath_request( + IN IB_HANDLE hCEP, + IN CM_ALTPATH_INFO* AltPathRequest, + OUT CM_PROCESS_ALTPATH_REQUEST_INFO* Info + ) +{ + CM_CEP_OBJECT* pCEP = (CM_CEP_OBJECT*) hCEP; + FSTATUS Status=FSUCCESS; + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, iba_cm_process_altpath_request); + + // Parameter check + if (! AltPathRequest || ! Info) + { + Status = FINVALID_PARAMETER; + goto done; + } + Status = ValidateCEPHandle(pCEP); + if (Status != FSUCCESS) + { + _DBG_WARN((" ValidateCEPHandle failed!!! <%s>\n", + _DBG_PTR(pCEP), _DBG_PTR(FSTATUS_MSG(Status)))); + goto done; + } + + SpinLockAcquire(&gCM->ListLock); + if (pCEP->Mode != CM_MODE_PASSIVE || pCEP->Type == CM_UD_TYPE) + { + Status = FINVALID_STATE; + } else { + Status = ProcessAltPathRequestP(pCEP, AltPathRequest, Info); + } + SpinLockRelease(&gCM->ListLock); +done: + _DBG_LEAVE_LVL(_DBG_LVL_FUNC_TRACE); + + return Status; +} + + +////////////////////////////////////////////////////////////////////////// +// iba_cm_altpath_reply +// +// Reply to an alternate path request +// Only allowed for Server/Passive side of connection +// +// INPUTS: +// +// +// +// OUTPUTS: +// +// None. +// +// RETURNS: +// +// FSUCCESS - APR queued to be sent. +// FINVALID_STATE - The endpoint is not in the valid state for this call +// FERROR - Unable to send the apr packet +// +// +// IRQL: +// +// This routine is called at IRQL_PASSIVE_LEVEL. +// +FSTATUS +iba_cm_altpath_reply( + IN IB_HANDLE hCEP, + IN CM_ALTPATH_REPLY_INFO* pAprInfo // Send APR + ) +{ + CM_CEP_OBJECT* pCEP = (CM_CEP_OBJECT*)hCEP; + FSTATUS Status; + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, iba_cm_altpath_reply); + + Status = ValidateCEPHandle(pCEP); + if (Status != FSUCCESS) + { + _DBG_WARN((" ValidateCEPHandle failed!!! <%s >\n", + _DBG_PTR(pCEP), _DBG_PTR(FSTATUS_MSG(Status)))); + return Status; + } + + SpinLockAcquire(&gCM->ListLock); + if (pCEP->Mode != CM_MODE_PASSIVE) + { + return FINVALID_STATE; + } else { + Status = AltPathReplyP(pCEP, pAprInfo); + } + SpinLockRelease(&gCM->ListLock); + + _DBG_LEAVE_LVL(_DBG_LVL_FUNC_TRACE); + return Status; + +} // iba_cm_altpath_reply() + +// build QP Attributes to load new alternate path into client QP +FSTATUS iba_cm_process_altpath_reply( + IN IB_HANDLE hCEP, + IN const CM_ALTPATH_REPLY_INFO* AltPathReply, + OUT IB_QP_ATTRIBUTES_MODIFY* QpAttrRts + ) +{ + CM_CEP_OBJECT* pCEP = (CM_CEP_OBJECT*) hCEP; + FSTATUS Status=FSUCCESS; + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, iba_cm_process_altpath_reply); + + // Parameter check + if (! AltPathReply || ! QpAttrRts) + { + Status = FINVALID_PARAMETER; + goto done; + } + Status = ValidateCEPHandle(pCEP); + if (Status != FSUCCESS) + { + _DBG_WARN((" ValidateCEPHandle failed!!! <%s>\n", + _DBG_PTR(pCEP), _DBG_PTR(FSTATUS_MSG(Status)))); + goto done; + } + + SpinLockAcquire(&gCM->ListLock); + if (pCEP->Mode != CM_MODE_ACTIVE || pCEP->Type == CM_UD_TYPE) + { + Status = FINVALID_STATE; + } else { + Status = ProcessAltPathReplyA(pCEP, AltPathReply, QpAttrRts); + } + SpinLockRelease(&gCM->ListLock); +done: + _DBG_LEAVE_LVL(_DBG_LVL_FUNC_TRACE); + + return Status; +} + +////////////////////////////////////////////////////////////////////////// +// iba_cm_migrated +// +// Inform CM that alternate path has been migrated to by client or server +// +// INPUTS: +// +// +// +// OUTPUTS: +// +// None. +// +// RETURNS: +// +// FSUCCESS - CEP adjusted to reflect migration +// FINVALID_STATE - The endpoint is not in the valid state for this call +// +// +// IRQL: +// +// This routine is called at IRQL_PASSIVE_LEVEL. +// +FSTATUS +iba_cm_migrated( + IN IB_HANDLE hCEP + ) +{ + CM_CEP_OBJECT* pCEP = (CM_CEP_OBJECT*)hCEP; + FSTATUS Status; + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, iba_cm_migrated); + + Status = ValidateCEPHandle(pCEP); + if (Status != FSUCCESS) + { + _DBG_WARN((" ValidateCEPHandle failed!!! <%s >\n", + _DBG_PTR(pCEP), _DBG_PTR(FSTATUS_MSG(Status)))); + return Status; + } + + SpinLockAcquire(&gCM->ListLock); + Status = MigratedA(pCEP); + SpinLockRelease(&gCM->ListLock); + + _DBG_LEAVE_LVL(_DBG_LVL_FUNC_TRACE); + return Status; + +} // iba_cm_migrated() + +////////////////////////////////////////////////////////////////////////// +// iba_cm_migrated_reload +// +// Inform CM that alternate path has been migrated to by client +// and prepare a AltPath Request which has the old primary path +// +// INPUTS: +// +// +// +// OUTPUTS: +// +// None. +// +// RETURNS: +// +// FSUCCESS - CEP adjusted to reflect migration +// FINVALID_STATE - The endpoint is not in the valid state for this call +// +// +// IRQL: +// +// This routine is called at IRQL_PASSIVE_LEVEL. +// +FSTATUS +iba_cm_migrated_reload( + IN IB_HANDLE hCEP, + OUT CM_PATH_INFO* NewPrimaryPath OPTIONAL, + OUT CM_ALTPATH_INFO* AltPathRequest OPTIONAL + ) +{ + CM_CEP_OBJECT* pCEP = (CM_CEP_OBJECT*)hCEP; + FSTATUS Status; + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, iba_cm_migrated_reload); + + if (! AltPathRequest && ! NewPrimaryPath) + { + Status = FINVALID_PARAMETER; + goto done; + } + Status = ValidateCEPHandle(pCEP); + if (Status != FSUCCESS) + { + _DBG_WARN((" ValidateCEPHandle failed!!! <%s >\n", + _DBG_PTR(pCEP), _DBG_PTR(FSTATUS_MSG(Status)))); + goto done; + } + + SpinLockAcquire(&gCM->ListLock); + if (pCEP->Mode != CM_MODE_ACTIVE || pCEP->Type != CM_UD_TYPE) + { + Status = FINVALID_STATE; + } else { + Status = MigratedReloadA(pCEP, NewPrimaryPath, AltPathRequest); + } + SpinLockRelease(&gCM->ListLock); + +done: + _DBG_LEAVE_LVL(_DBG_LVL_FUNC_TRACE); + return Status; + +} // iba_cm_migrated_reload() + +////////////////////////////////////////////////////////////////////////// +// iba_cm_disconnect +// +// +// INPUTS: +// +// +// +// OUTPUTS: +// +// None. +// +// RETURNS: +// +// FSUCCESS. +// +// IRQL: +// +// This routine is called at IRQL_PASSIVE_LEVEL. +// +FSTATUS +iba_cm_disconnect( + IN IB_HANDLE hCEP, + IN const CM_DREQUEST_INFO* pDRequest, // Send DREQ + IN const CM_DREPLY_INFO* pDReply // Send DREP + ) +{ + CM_CEP_OBJECT* pCEP = (CM_CEP_OBJECT*) hCEP; + FSTATUS Status=FSUCCESS; + + // keep this const and off stack to save kernel stack space + static const CM_DREQUEST_INFO DisconnectReq = {{0}}; + + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, iba_cm_disconnect); + + // + // Parameter check + // + Status = ValidateCEPHandle(pCEP); + if (Status != FSUCCESS) + { + _DBG_WARN((" ValidateCEPHandle failed!!! <%s>\n", + _DBG_PTR(pCEP), _DBG_PTR(FSTATUS_MSG(Status)))); + + _DBG_LEAVE_LVL(_DBG_LVL_FUNC_TRACE); + return Status; + } + + // Allow both to be NULL or either one to be NULL + if (pDRequest == NULL) + { + if (pDReply == NULL) + { + // Let the CEP state determine if we are sending a DREQ or DREP + pDRequest = &DisconnectReq; + + pDReply = (CM_DREPLY_INFO*)&DisconnectReq; + } + } + else + { + if (pDReply) + { + _DBG_ERROR((" Invalid param!!!\n", _DBG_PTR(pCEP))); + + _DBG_LEAVE_LVL(_DBG_LVL_FUNC_TRACE); + + return FINVALID_PARAMETER; + } + } + + SpinLockAcquire(&gCM->ListLock); + + // DisconnectA() is applicable to both client and server endpoint + Status = DisconnectA(pCEP, pDRequest, pDReply); + + SpinLockRelease(&gCM->ListLock); + + _DBG_LEAVE_LVL(_DBG_LVL_FUNC_TRACE); + + return Status; + +} // iba_cm_disconnect() + + +FSTATUS +CmGetConnInfo( + IN IB_HANDLE hCEP, + OUT CM_CONN_INFO* pConnInfo + ) +{ + CM_CEP_OBJECT* pCEP = (CM_CEP_OBJECT*) hCEP; + FSTATUS Status=FSUCCESS; + + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, CmGetConnInfo); + + // + // Parameter check + // + Status = ValidateCEPHandle(pCEP); + if (Status != FSUCCESS) + { + _DBG_WARN((" ValidateCEPHandle failed!!! <%s>\n", + _DBG_PTR(pCEP), _DBG_PTR(FSTATUS_MSG(Status)))); + + _DBG_LEAVE_LVL(_DBG_LVL_FUNC_TRACE); + return Status; + } + + SpinLockAcquire(&gCM->ListLock); + + Status = GetConnInfo(pCEP, pConnInfo); + + SpinLockRelease(&gCM->ListLock); + + _DBG_LEAVE_LVL(_DBG_LVL_FUNC_TRACE); + + return Status; +} // CmGetConnInfo() + +////////////////////////////////////////////////////////////////////////// +// CreateCEP +// +// +// +// INPUTS: +// +// +// +// OUTPUTS: +// +// None. +// +// RETURNS: +// +// FSUCCESS. +// +// IRQL: +// +// This routine is called at IRQL_PASSIVE_LEVEL. +// +CM_CEP_OBJECT* +CreateCEP( + CM_CEP_TYPE TransportServiceType, + EVENT_HANDLE hEvent, + EVENT_HANDLE hWaitEvent + ) +{ + CM_CEP_OBJECT* pCEP=NULL; + FSTATUS Status=FSUCCESS; + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, CreateCEP); + + // Allocate memory for the CEP object + pCEP = (CM_CEP_OBJECT*)MemoryAllocateAndClear(sizeof(CM_CEP_OBJECT), FALSE, CM_MEM_TAG); + + if (!pCEP) + { + _DBG_ERROR(("MemoryAllocateAndClear() CEP failed!!!\n")); + goto fail_alloc; + } + pCEP->Signature = gCM->Signature; + + TimerInitState(&pCEP->TimerObj); + Status = TimerInit(&pCEP->TimerObj, CmTimerCallback, pCEP ); + if (!Status) + { + _DBG_ERROR((" !!!TimerInit() failed!!! - <%s>\n", + _DBG_PTR(pCEP), _DBG_PTR(FSTATUS_MSG(Status)))); + goto fail_timer; + } + + // Obtain callback item +#ifdef WINNT + pCEP->pCallbackItem = SysCallbackGet(IbtGlobal.DeviceObject); +#else + pCEP->pCallbackItem = SysCallbackGet(NULL); +#endif // WINNT + + if (pCEP->pCallbackItem == NULL) + { + _DBG_ERROR((" !!!SysCallbackGet() failed!!!\n", _DBG_PTR(pCEP))); + goto fail_syscallback; + } + + // Obtain a dgrm from the pool for this obj + // TODO: Delay this until user call Connect() or Listen() ??? + pCEP->pDgrmElement = CmDgrmGet(); + if (!pCEP->pDgrmElement) + { + _DBG_WARNING((" CEP Create failed: Out of CM Dgrms!!!\n", + _DBG_PTR(pCEP))); + goto fail_dgrm; + } + + _DBG_INFO((" obtained dgrm from pool .\n", + _DBG_PTR(pCEP), _DBG_PTR(pCEP->pDgrmElement))); + + if (hEvent) + { + pCEP->pEventObj = (EVENT*)hEvent; + OsWaitObjAddRef((OS_WAIT_OBJ_HANDLE)pCEP->pEventObj); + pCEP->bPrivateEvent = 0; // user event, don't touch in DestroyCEP + } else { + pCEP->pEventObj = EventAlloc(); + if (pCEP->pEventObj == NULL) + { + _DBG_ERROR(("MemoryAllocateAndClear() Event failed!!!\n")); + goto fail_event; + } + pCEP->bPrivateEvent = 1; // DestroyCEP must deallocate this event + } + + pCEP->pWaitEvent = (EVENT*)hWaitEvent; + + // Initialize the CEP object + pCEP->Type = TransportServiceType; + DListInit(&pCEP->PendingList); + DListInit(&pCEP->PendingListEntry); + + QListSetObj(&pCEP->AllCEPsItem, pCEP); + QListInsertTail(&gCM->AllCEPs, &pCEP->AllCEPsItem); + + CepSetState(pCEP, CMS_IDLE); + + _DBG_INFO((" *** NEW CEP object CREATED ***.\n", _DBG_PTR(pCEP))); + _DBG_LEAVE_LVL(_DBG_LVL_FUNC_TRACE); + return pCEP; + +fail_event: + CmDgrmPut(pCEP->pDgrmElement); +fail_dgrm: + SysCallbackPut(pCEP->pCallbackItem); +fail_syscallback: + TimerDestroy(&pCEP->TimerObj); +fail_timer: + pCEP->Signature =0; + MemoryDeallocate(pCEP); +fail_alloc: + _DBG_LEAVE_LVL(_DBG_LVL_FUNC_TRACE); + return NULL; + +} // CreateCEP() + + +// final part of destroying a CEP, called outside any possible timer callback +// context so we can safely destroy our Timer +void +ReapCEP( + IN LIST_ITEM *pItem + ) +{ + CM_CEP_OBJECT *pCEP = PARENT_STRUCT(pItem, CM_CEP_OBJECT, AllCEPsItem); + + _DBG_INFO((" - Destroying the timer obj \n", _DBG_PTR(pCEP), _DBG_PTR(&pCEP->TimerObj))); + TimerDestroy(&pCEP->TimerObj); + MemoryDeallocate(pCEP); +} + +////////////////////////////////////////////////////////////////////////// +// DestroyCEP +// +// +// +// INPUTS: +// +// +// +// OUTPUTS: +// +// None. +// +// RETURNS: +// +// FSUCCESS. +// +// IRQL: +// +// This routine is called at IRQL_PASSIVE_LEVEL. +// +FSTATUS +DestroyCEP(CM_CEP_OBJECT* pCEP) +{ + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, DestroyCEP); + + // Assert we are in IDLE state + ASSERT(pCEP->State == CMS_IDLE); + + // Assert no callback in progress or pending + ASSERT(AtomicRead(&pCEP->CallbackRefCnt) == 0); + + if (pCEP->ApcRetryCount) + { + QListRemoveItem(&gCM->ApcRetryList, &pCEP->ApcRetryListItem); + pCEP->ApcRetryCount = 0; + } + + // Assert no timeout in progress or pending + //ASSERT(pCEP->timeout_ms == 0); + if (pCEP->timeout_ms) + { + CmTimerStop(pCEP, LAST_KNOWN_TIMER); + } + + ASSERT(pCEP->LocalCommID == 0); + ASSERT(pCEP->LocalEndPoint.QPN == 0); + ASSERT(pCEP->LocalEndPoint.EECN == 0); + + if (pCEP->pDgrmElement) + { + _DBG_INFO((" Releasing the dgrm .\n", + _DBG_PTR(pCEP), _DBG_PTR(pCEP->pDgrmElement))); + CmDgrmRelease(pCEP->pDgrmElement); + } + + if (pCEP->bPrivateEvent) + { + _DBG_INFO((" - Deallocating the event obj \n", _DBG_PTR(pCEP), _DBG_PTR(pCEP->pEventObj))); + EventDealloc(pCEP->pEventObj); + } + else + { + OsWaitObjRemoveRef((OS_WAIT_OBJ_HANDLE)pCEP->pEventObj); + } + + pCEP->pEventObj = NULL; + + if (pCEP->pCallbackItem) + { + _DBG_INFO((" - Releasing the callback obj \n", _DBG_PTR(pCEP), _DBG_PTR(pCEP->pCallbackItem))); + SysCallbackPut(pCEP->pCallbackItem); + } + + QListRemoveItem(&gCM->AllCEPs, &pCEP->AllCEPsItem); + _DBG_INFO((" *** CEP object DESTROYED *** .\n", + _DBG_PTR(pCEP), pCEP->LocalCommID, pCEP->RemoteCommID, pCEP->EventFlags)); + + pCEP->Signature =0; + if (pCEP->Discriminator) + { + MemoryDeallocate(pCEP->Discriminator); + pCEP->Discriminator = NULL; + } + + // Defer to Reaper to complete destroy, we could be in a TIMEWAIT callback + ReaperQueue(&pCEP->AllCEPsItem, ReapCEP); + + _DBG_LEAVE_LVL(_DBG_LVL_FUNC_TRACE); + return FSUCCESS; + +} // DestroyCEP() + +uint32 SidrTimeout(IN CM_CEP_OBJECT* pCEP) +{ + // use our timeout (representing ~ CPU delays) + Round-trip time for fabric + if (pCEP->PktLifeTime >= 31) { + // odd case, avoid overflow + return TimeoutMultToTimeInMs(31); // this is 2.4 hrs !!!! + } else { + return gCmParams.SidrReqTimeoutMs + 2*TimeoutMultToTimeInMs(pCEP->PktLifeTime); + } +} + +// Queue an APC retry +void +QueueApcRetry(IN CM_CEP_OBJECT* pCEP) +{ + if (! pCEP->ApcRetryCount) + { + QListSetObj(&pCEP->ApcRetryListItem, pCEP); + QListInsertTail(&gCM->ApcRetryList, &pCEP->ApcRetryListItem); + } + pCEP->ApcRetryCount++; + if (! gCM->ApcRetryTimerRunning) + { + TimerStart(&gCM->ApcRetryTimer, CM_APC_RETRY_INTERVAL); + gCM->ApcRetryTimerRunning = 1; + } +} + +// APC Retry Timer handler +void +ApcRetryTimerCallback(IN void *Context) +{ + int count = 0; + LIST_ITEM* pListItem=NULL; + int thisPass = 0; // number processed so far in this pass through list + int listDepth = QListCount(&gCM->ApcRetryList); // length of list for this pass + int failCount = 0; // number that failed in this pass through list + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, ApcRetryTimerCallback); + + SpinLockAcquire(&gCM->ListLock); + if (TimerCallbackStopped(&gCM->ApcRetryTimer)) + goto done; // stale timer callback + + ASSERT(gCM->ApcRetryTimerRunning); + + // limit number of Apc retries we attempt per timer callback + // this way a swamped system won't stay in the Lock/IRQ too long + while (count < CM_APC_RETRY_LIMIT + && (pListItem = QListRemoveHead(&gCM->ApcRetryList)) != NULL) + { + CM_CEP_OBJECT* pCEP= (CM_CEP_OBJECT*)QListObj(pListItem); + + ASSERT(pCEP); + ASSERT(pCEP->ApcRetryCount); + if (BitTest(pCEP->EventFlags, USRE_DESTROY)) { + // the CEP is marked for destruction + // so don't attempt to issue callbacks against it anymore + pCEP->ApcRetryCount = 0; + _DBG_WARNING((" Object marked for destruction - skip APC retry <%s>\n", + _DBG_PTR(pCEP), _DBG_PTR(CmGetStateString(pCEP->State)))); + + } else { + if (--(pCEP->ApcRetryCount) != 0) { + // keep it on the list + QListInsertTail(&gCM->ApcRetryList, &pCEP->ApcRetryListItem); + } + if (FSUCCESS != ProcessApcRetry(pCEP)) + failCount++; + } + // optimize by not repeating processing if no progress is being made + if (++thisPass == listDepth) { + // we completed a pass through the list + if (failCount == listDepth) { + // every CEP failed to make progress, stop processing + break; + } + // initialize counters for next pass through the list + thisPass = 0; + listDepth = QListCount(&gCM->ApcRetryList); + failCount = 0; + } + count++; + } + if (! QListIsEmpty(&gCM->ApcRetryList)) + { + TimerStart(&gCM->ApcRetryTimer, CM_APC_RETRY_INTERVAL); + } else { + gCM->ApcRetryTimerRunning = 0; + } +done: + SpinLockRelease(&gCM->ListLock); + + _DBG_LEAVE_LVL(_DBG_LVL_FUNC_TRACE); +} + +// Clear Statistics +void +CmClearStats(void) +{ + // clear individually for a more atomic clear than memset would offer + AtomicWrite(&gCM->Sent.ClassPortInfo, 0); + AtomicWrite(&gCM->Sent.ClassPortInfoResp, 0); + AtomicWrite(&gCM->Sent.Req, 0); + AtomicWrite(&gCM->Sent.Rep, 0); + AtomicWrite(&gCM->Sent.Rtu, 0); + AtomicWrite(&gCM->Sent.MraReq, 0); + AtomicWrite(&gCM->Sent.MraRep, 0); + AtomicWrite(&gCM->Sent.MraLap, 0); + AtomicWrite(&gCM->Sent.Lap, 0); + AtomicWrite(&gCM->Sent.AprAcc, 0); + AtomicWrite(&gCM->Sent.AprRej, 0); + AtomicWrite(&gCM->Sent.RejReq, 0); + AtomicWrite(&gCM->Sent.RejRep, 0); + AtomicWrite(&gCM->Sent.Dreq, 0); + AtomicWrite(&gCM->Sent.Drep, 0); + AtomicWrite(&gCM->Sent.SidrReq, 0); + AtomicWrite(&gCM->Sent.SidrResp, 0); + AtomicWrite(&gCM->Sent.Failed, 0); + + AtomicWrite(&gCM->Recv.ClassPortInfo, 0); + AtomicWrite(&gCM->Recv.ClassPortInfoResp, 0); + AtomicWrite(&gCM->Recv.Req, 0); + AtomicWrite(&gCM->Recv.Rep, 0); + AtomicWrite(&gCM->Recv.Rtu, 0); + AtomicWrite(&gCM->Recv.MraReq, 0); + AtomicWrite(&gCM->Recv.MraRep, 0); + AtomicWrite(&gCM->Recv.MraLap, 0); + AtomicWrite(&gCM->Recv.Lap, 0); + AtomicWrite(&gCM->Recv.AprAcc, 0); + AtomicWrite(&gCM->Recv.AprRej, 0); + AtomicWrite(&gCM->Recv.RejReq, 0); + AtomicWrite(&gCM->Recv.RejRep, 0); + AtomicWrite(&gCM->Recv.Dreq, 0); + AtomicWrite(&gCM->Recv.Drep, 0); + AtomicWrite(&gCM->Recv.SidrReq, 0); + AtomicWrite(&gCM->Recv.SidrResp, 0); + AtomicWrite(&gCM->Recv.Failed, 0); +} + +// copy Path information from a Connect or LoadAltPath into the given +// CEP Path (can be pCEP->PrimaryPath or pCEP->AlternatePath) +// Context of path assumes Local is Source +void CopyPathInfoToCepPath(OUT CM_CEP_PATH *pCepPath, + IN const CM_CEP_PATHINFO *pPathInfo, IN uint8 AckTimeout) +{ + // caller handles pCepPath->LocalPortGuid; + pCepPath->LocalGID = pPathInfo->Path.SGID; + pCepPath->RemoteGID = pPathInfo->Path.DGID; + pCepPath->LocalLID = pPathInfo->Path.SLID; + pCepPath->RemoteLID = pPathInfo->Path.DLID; + pCepPath->FlowLabel = pPathInfo->Path.u1.s.FlowLabel; + pCepPath->StaticRate = pPathInfo->Path.Rate; + // caller handles pCepPath->PkeyIndex; + pCepPath->TClass = pPathInfo->Path.TClass; + pCepPath->SL = pPathInfo->Path.u2.s.SL; + // pCepPath->bSubnetLocal = (! IsGlobalRoute(&pPathInfo->Path)); + pCepPath->bSubnetLocal = pPathInfo->bSubnetLocal; + pCepPath->AckTimeout = AckTimeout; + // will factor in TargetAckDelay when get REP + pCepPath->LocalAckTimeout = pPathInfo->Path.PktLifeTime; + pCepPath->HopLimit = pPathInfo->Path.u1.s.HopLimit; + // caller handles pCepPath->LocalGidIndex; + // caller handles pCepPath->LocalPathBits; +} + +// build a QP Destination AV from a CEP Path +void GetAVFromCepPath(IN CM_CEP_PATH* CepPath, OUT IB_ADDRESS_VECTOR* DestAv) +{ + DestAv->PortGUID = CepPath->LocalPortGuid; // not needed, but doesn't hurt + DestAv->DestLID = CepPath->RemoteLID; + DestAv->PathBits = CepPath->LocalPathBits; + DestAv->ServiceLevel = CepPath->SL; + DestAv->StaticRate = CepPath->StaticRate; + DestAv->GlobalRoute = ! CepPath->bSubnetLocal; + if (DestAv->GlobalRoute) + { + DestAv->GlobalRouteInfo.DestGID = CepPath->RemoteGID; + DestAv->GlobalRouteInfo.FlowLabel = CepPath->FlowLabel; + DestAv->GlobalRouteInfo.SrcGIDIndex = CepPath->LocalGidIndex; + DestAv->GlobalRouteInfo.HopLimit = CepPath->HopLimit; + DestAv->GlobalRouteInfo.TrafficClass = CepPath->TClass; + } +} + +// copy Path information from CEP Path to PathInfo for +// a CM FCM_ALTPATH_REPLY callback. +// Context of path assumes Local is Source +void CopyCepPathToPathInfo(OUT CM_CEP_PATHINFO *pPathInfo, + OUT uint8* pAckTimeout, IN CM_CEP_PATH *pCepPath) +{ + pPathInfo->Path.SLID = pCepPath->LocalLID; + pPathInfo->Path.SGID = pCepPath->LocalGID; + pPathInfo->Path.DLID = pCepPath->RemoteLID; + pPathInfo->Path.DGID = pCepPath->RemoteGID; + pPathInfo->Path.NumbPath = 1; // Only one path + pPathInfo->Path.u1.s.FlowLabel = pCepPath->FlowLabel; + pPathInfo->Path.u1.s.HopLimit = pCepPath->HopLimit; + pPathInfo->Path.TClass = pCepPath->TClass; + pPathInfo->Path.u2.s.SL = pCepPath->SL; + pPathInfo->Path.Rate = pCepPath->StaticRate; + pPathInfo->Path.RateSelector = IB_SELECTOR_EQ; + //pPathInfo->Path.P_Key = caller copies from CEP + //pPathInfo->Path.Mtu = caller copies from CEP + pPathInfo->Path.MtuSelector = IB_SELECTOR_EQ; + *pAckTimeout = pCepPath->AckTimeout; + // AckTimeout/2 approximates PktLifeTime with roundup + if (pCepPath->AckTimeout > 1) + pPathInfo->Path.PktLifeTime = pCepPath->AckTimeout-1; + else + pPathInfo->Path.PktLifeTime = 0; + pPathInfo->Path.PktLifeTimeSelector = IB_SELECTOR_EQ; +} + +// compare Path information from a LoadAltPath to the given +// CEP Path (can be pCEP->PrimaryPath or pCEP->AlternatePath) +// Context of path assumes Local is Source +// we focus on parameters which truely indicate a different path +// returns 0 on match, 1 on no match +int CompareCepPathToPathInfo(IN const CM_CEP_PATH *pCepPath, + IN const CM_CEP_PATHINFO *pPathInfo) +{ + if (pCepPath->LocalLID != pPathInfo->Path.SLID) + return 1; + if (pCepPath->RemoteLID != pPathInfo->Path.DLID) + return 1; + // we must test GIDs, if ports are on different fabrics, the LIDs could + // match but the GIDs would be different + if (0 != MemoryCompare(&pCepPath->LocalGID, &pPathInfo->Path.SGID, sizeof(IB_GID))) + return 1; + if (0 != MemoryCompare(&pCepPath->RemoteGID, &pPathInfo->Path.DGID, sizeof(IB_GID))) + return 1; + if (pCepPath->bSubnetLocal != pPathInfo->bSubnetLocal) + return 1; + + // ignore minor parameters + //pCepPath->LocalPortGuid - implied by LocalGID + //pCepPath->FlowLabel = pPathInfo->Path.u1.s.FlowLabel; + //pCepPath->StaticRate = pPathInfo->Path.Rate; + //pCepPath->PkeyIndex = index of pPathInfo->Path.P_Key; + //pCepPath->TClass = pPathInfo->Path.TClass; + //pCepPath->SL = pPathInfo->Path.u2.s.SL; + // pCepPath->bSubnetLocal = (! IsGlobalRoute(&pPathInfo->Path)); + //pCepPath->AckTimeout = AckTimeout; + //pCepPath->HopLimit = pPathInfo->Path.u1.s.HopLimit; + //pCepPath->LocalGidIndex - implied by LocalGID + return 0; +} + +// +// build QP Attributes to move RC/UC/RD QP from Reset to Init +// +void GetInitAttrFromCep(IN CM_CEP_OBJECT* pCEP, + OUT IB_QP_ATTRIBUTES_MODIFY* QpAttrInit) +{ + QpAttrInit->RequestState = QPStateInit; + QpAttrInit->Attrs = (IB_QP_ATTR_PORTGUID|IB_QP_ATTR_PKEYINDEX); + QpAttrInit->PortGUID = pCEP->PrimaryPath.LocalPortGuid; + QpAttrInit->PkeyIndex = pCEP->PrimaryPath.PkeyIndex; + // application must build AccessControl + // application must iba_modify_qp(...) +} + + +// +// build QP Attributes to move RC/UC/RD QP from Init to RTR +// +void GetRtrAttrFromCep(IN CM_CEP_OBJECT* pCEP, boolean enableFailover, + OUT IB_QP_ATTRIBUTES_MODIFY* QpAttrRtr) +{ + // TBD - RD code here is not complete/accurate + QpAttrRtr->RequestState = QPStateReadyToRecv; + QpAttrRtr->RecvPSN = pCEP->LocalRecvPSN; + QpAttrRtr->DestQPNumber = pCEP->RemoteEndPoint.QPN; + GetAVFromCepPath(&pCEP->PrimaryPath, &QpAttrRtr->DestAV); + QpAttrRtr->PathMTU = pCEP->Mtu; + QpAttrRtr->Attrs = (IB_QP_ATTR_RECVPSN | IB_QP_ATTR_DESTQPNUMBER + | IB_QP_ATTR_DESTAV | IB_QP_ATTR_PATHMTU); + if (pCEP->Type == CM_RC_TYPE) { + QpAttrRtr->ResponderResources = pCEP->LocalResponderResources; + QpAttrRtr->Attrs |= IB_QP_ATTR_RESPONDERRESOURCES; + } + if (enableFailover && pCEP->AlternatePath.RemoteLID != 0) + { + GetAVFromCepPath(&pCEP->AlternatePath, &QpAttrRtr->AltDestAV); + QpAttrRtr->AltPortGUID = pCEP->AlternatePath.LocalPortGuid; + QpAttrRtr->AltPkeyIndex = pCEP->AlternatePath.PkeyIndex; + QpAttrRtr->Attrs |= IB_QP_ATTR_ALTDESTAV|IB_QP_ATTR_ALTPORTGUID + | IB_QP_ATTR_ALTPKEYINDEX; + } + // application must set + //QpAttr->MinRnrTimer + //QpAttr->Attrs |= IB_QP_ATTR_MINRNRTIMER; + // application must iba_modify_qp(...) +} + +// +// build QP Attributes to move RC/UC/RD QP from RTR to RTS +// +void GetRtsAttrFromCep(IN CM_CEP_OBJECT* pCEP, + OUT IB_QP_ATTRIBUTES_MODIFY* QpAttrRts) +{ + // TBD - RD code here is not complete/accurate + QpAttrRts->RequestState = QPStateReadyToSend; + QpAttrRts->SendPSN = pCEP->LocalSendPSN; + QpAttrRts->Attrs = IB_QP_ATTR_SENDPSN; + if (pCEP->Type != CM_UC_TYPE) { + QpAttrRts->FlowControl = TRUE; // always set + QpAttrRts->InitiatorDepth = pCEP->LocalInitiatorDepth; + QpAttrRts->LocalAckTimeout = pCEP->PrimaryPath.LocalAckTimeout; + QpAttrRts->RetryCount = pCEP->LocalRetryCount; + QpAttrRts->RnrRetryCount = pCEP->LocalRnrRetryCount; + QpAttrRts->Attrs |= (IB_QP_ATTR_INITIATORDEPTH + | IB_QP_ATTR_FLOWCONTROL | IB_QP_ATTR_LOCALACKTIMEOUT + | IB_QP_ATTR_RETRYCOUNT | IB_QP_ATTR_RNRRETRYCOUNT); + } + if (pCEP->bFailoverSupported && pCEP->AlternatePath.RemoteLID != 0) + { + QpAttrRts->APMState = APMStateRearm; + QpAttrRts->Attrs |= IB_QP_ATTR_APMSTATE; + if (pCEP->Type != CM_UC_TYPE) { + QpAttrRts->AltLocalAckTimeout = pCEP->AlternatePath.LocalAckTimeout; + QpAttrRts->Attrs |= IB_QP_ATTR_ALTLOCALACKTIMEOUT; + } + } +} + +// +// Recalculate the processing time +// +uint64 +UpdateTurnaroundTime(uint64 turnaround_us, uint64 elapsed_us) +{ + uint32 turnaround32_us=(uint32)turnaround_us; + uint32 elapsed32_us=(uint32)elapsed_us; + uint64 new_turnaround_us=0; + + // Handle max range + if (turnaround_us >= 0xFFFFFFFF) + return (uint64)0xFFFFFFFF; + + if (elapsed_us >= 0xFFFFFFFF) + return turnaround_us; + + new_turnaround_us = ((103 * turnaround32_us) + (25 * elapsed32_us)) /128; +#if 0 + // alternate heuristic, drive up faster than down + if (turnaround32_us > elapsed32_us) + { + // drive value down slowly, we could have some fast consumers + new_turnaround_us = turnaround32_us - (turnaround32_us - elapsed32_us)/32; + //printk("elapsed %"PRIu64" drop from %"PRIu64" to %"PRIu64"\n", elapsed_us, turnaround_us, new_turnaround_us); + } else { + // drive value up more quickly, avoid 64 bit divide, not in kernel + new_turnaround_us = ((103 * turnaround32_us) + (25 * elapsed32_us)) /128; + //printk("elapsed %"PRIu64" grow from %"PRIu64" to %"PRIu64"\n", elapsed_us, turnaround_us, new_turnaround_us); + } +#endif + + if (new_turnaround_us < gCmParams.MinTurnaroundTimeMs*1000) + new_turnaround_us = gCmParams.MinTurnaroundTimeMs*1000; + else if (new_turnaround_us > gCmParams.MaxTurnaroundTimeMs*1000) + new_turnaround_us = gCmParams.MaxTurnaroundTimeMs*1000; + + return new_turnaround_us; +} + +// Compute worst case service time for a CEP, used as part of +// computing service timeout for MRA +uint32 CepWorstServiceTimeMult(IN CM_CEP_OBJECT *pCEP) +{ + uint32 result; + + // service time is a local concept and does not include fabric time + if (pCEP->turnaround_time_us) + { + // appl supplied + result = TimeoutTimeToMult(pCEP->turnaround_time_us ); + } else { + // assume worst case is 8* our average turnaround + result = TimeoutTimeToMult( (gCM->turnaround_time_us*8) ); + } + return result; +} + +FSTATUS +RequestCheck(const CM_REQUEST_INFO* pRequest) +{ + // TODO: Verify SID + return FSUCCESS; + +} // RequestCheck() + +// assign/re-assign a unique LocalCommID to the given CEP +// must be called with ListLatch held +void AssignLocalCommID(IN CM_CEP_OBJECT* pCEP) +{ + if (pCEP->LocalCommID) + { + // we are re-assigning + CM_MapRemoveEntry(&gCM->LocalCommIDMap, &pCEP->LocalCommIDMapEntry, LOCAL_COMM_ID_LIST, pCEP); + } + // usually we won't see duplicates, but just in case we loop + // since we will run out of a lot of other resources before we have + // 4 billion CEPs, the loop is guaranteed to end + do { + pCEP->LocalCommID = ++(gCM->CommID); + } while ( pCEP->LocalCommID == 0 + || ! CM_MapTryInsert(&gCM->LocalCommIDMap, pCEP->LocalCommID, + &pCEP->LocalCommIDMapEntry, + "LOCAL_COMM_ID_LIST", pCEP)); +} + +// unassign/clear LocalCommID for the given CEP +// must be called with ListLatch held +void ClearLocalCommID(IN CM_CEP_OBJECT* pCEP) +{ + if (pCEP->LocalCommID) + { + CM_MapRemoveEntry(&gCM->LocalCommIDMap, &pCEP->LocalCommIDMapEntry, LOCAL_COMM_ID_LIST, pCEP); + pCEP->LocalCommID = 0; + } +} + +CM_CEP_OBJECT* FindLocalCommID(IN uint32 LocalCommID) +{ + CM_MAP_ITEM* pMapEntry = CM_MapGet(&gCM->LocalCommIDMap, (uint64)LocalCommID); + if (pMapEntry != CM_MapEnd(&gCM->LocalCommIDMap)) + return PARENT_STRUCT(pMapEntry, CM_CEP_OBJECT, LocalCommIDMapEntry); + else + return NULL; +} + +uint32 GenerateStartPSN() +{ + // a simple pseudo random number generator + gCM->StartPSN = (gCM->StartPSN+1025) & 0xffffff; + return gCM->StartPSN; +} + +// LocalEndPointMap Key Compare function +// +// CepLocalEndPointCompare - is used to insert cep entries into the LocalEndPointMap and +// is the primary key_compare function for the LocalEndPointMap +// +// Coallating order is: +// Local QPN +// Local EECN +// Local CaGUID + +// A qmap key_compare function to compare the end point address for +// two CEPs +// +// key1 - CEP1 pointer +// key2 - CEP2 pointer +// +// Returns: +// -1: cep1 end point address < cep2 end point address +// 0: cep1 end point address = cep2 end point address +// 1: cep1 end point address > cep2 end point address +int +CepLocalEndPointCompare(uint64 key1, uint64 key2) +{ + IN CM_CEP_OBJECT* pCEP1 = (CM_CEP_OBJECT*)(uintn)key1; + IN CM_CEP_OBJECT* pCEP2 = (CM_CEP_OBJECT*)(uintn)key2; + + if (pCEP1->LocalEndPoint.QPN < pCEP2->LocalEndPoint.QPN) + return -1; + else if (pCEP1->LocalEndPoint.QPN > pCEP2->LocalEndPoint.QPN) + return 1; + if (pCEP1->LocalEndPoint.EECN < pCEP2->LocalEndPoint.EECN) + return -1; + else if (pCEP1->LocalEndPoint.EECN > pCEP2->LocalEndPoint.EECN) + return 1; + if (pCEP1->LocalEndPoint.CaGUID < pCEP2->LocalEndPoint.CaGUID) + return -1; + else if (pCEP1->LocalEndPoint.CaGUID > pCEP2->LocalEndPoint.CaGUID) + return 1; + else + return 0; +} + +// A qmap key_compare function to search the LocalEndPointMap for a match with +// a given EndPoint +// +// key1 - CEP pointer +// key2 - CM_END_POINT pointer +// +// Returns: +// -1: cep1 remote address < req local address +// 0: cep1 remote address = req local address (accounting for wildcards) +// 1: cep1 remote address > req local address +// +int +CepAddrLocalEndPointCompare(uint64 key1, uint64 key2) +{ + IN CM_CEP_OBJECT* pCEP = (CM_CEP_OBJECT*)(uintn)key1; + IN CM_END_POINT* pEndPoint = (CM_END_POINT*)(uintn)key2; + + if (pCEP->LocalEndPoint.QPN < pEndPoint->QPN) + return -1; + else if (pCEP->LocalEndPoint.QPN > pEndPoint->QPN) + return 1; + if (pCEP->LocalEndPoint.EECN < pEndPoint->EECN) + return -1; + else if (pCEP->LocalEndPoint.EECN > pEndPoint->EECN) + return 1; + if (pCEP->LocalEndPoint.CaGUID < pEndPoint->CaGUID) + return -1; + else if (pCEP->LocalEndPoint.CaGUID > pEndPoint->CaGUID) + return 1; + else + return 0; +} + +// RemoteEndPointMap Key Compare function +// +// CepRemoteEndPointCompare - is used to insert cep entries into the RemoteEndPointMap and +// is the primary key_compare function for the RemoteEndPointMap +// +// Coallating order is: +// Remote QPN +// Remote EECN +// Remote CaGUID + +// A qmap key_compare function to compare the end point address for +// two CEPs +// +// key1 - CEP1 pointer +// key2 - CEP2 pointer +// +// Returns: +// -1: cep1 end point address < cep2 end point address +// 0: cep1 end point address = cep2 end point address +// 1: cep1 end point address > cep2 end point address +int +CepRemoteEndPointCompare(uint64 key1, uint64 key2) +{ + IN CM_CEP_OBJECT* pCEP1 = (CM_CEP_OBJECT*)(uintn)key1; + IN CM_CEP_OBJECT* pCEP2 = (CM_CEP_OBJECT*)(uintn)key2; + + if (pCEP1->RemoteEndPoint.QPN < pCEP2->RemoteEndPoint.QPN) + return -1; + else if (pCEP1->RemoteEndPoint.QPN > pCEP2->RemoteEndPoint.QPN) + return 1; + if (pCEP1->RemoteEndPoint.EECN < pCEP2->RemoteEndPoint.EECN) + return -1; + else if (pCEP1->RemoteEndPoint.EECN > pCEP2->RemoteEndPoint.EECN) + return 1; + if (pCEP1->RemoteEndPoint.CaGUID < pCEP2->RemoteEndPoint.CaGUID) + return -1; + else if (pCEP1->RemoteEndPoint.CaGUID > pCEP2->RemoteEndPoint.CaGUID) + return 1; + else + return 0; +} + +// A qmap key_compare function to search the RemoteEndPointMap for a match with +// a given REQ +// +// key1 - CEP pointer +// key2 - REQ pointer +// +// Returns: +// -1: cep1 remote address < req local address +// 0: cep1 remote address = req local address (accounting for wildcards) +// 1: cep1 remote address > req local address +// +int +CepReqRemoteEndPointCompare(uint64 key1, uint64 key2) +{ + IN CM_CEP_OBJECT* pCEP = (CM_CEP_OBJECT*)(uintn)key1; + IN CMM_REQ* pREQ = (CMM_REQ*)(uintn)key2; + + if (pCEP->RemoteEndPoint.QPN < pREQ->u1.s.LocalQPN) + return -1; + else if (pCEP->RemoteEndPoint.QPN > pREQ->u1.s.LocalQPN) + return 1; + if (pCEP->RemoteEndPoint.EECN < pREQ->u2.s.LocalEECN) + return -1; + else if (pCEP->RemoteEndPoint.EECN > pREQ->u2.s.LocalEECN) + return 1; + if (pCEP->RemoteEndPoint.CaGUID < pREQ->LocalCaGUID) + return -1; + else if (pCEP->RemoteEndPoint.CaGUID > pREQ->LocalCaGUID) + return 1; + else + return 0; +} + +// unassign/clear Local and Remote EndPoints for the given CEP +// must be called with ListLatch held +void ClearEndPoint(IN CM_CEP_OBJECT* pCEP) +{ + if (pCEP->LocalEndPoint.QPN || pCEP->LocalEndPoint.EECN) + { + // SIDRRegister sets QPN but does not put on LocalEndPointMap + if (pCEP->State != CMS_REGISTERED) + { + // If RC CM_REQ is rejected, sometimes local end point is not in map. + if (!CM_MapIsEmpty(&gCM->LocalEndPointMap)) + CM_MapRemoveEntry(&gCM->LocalEndPointMap, &pCEP->LocalEndPointMapEntry, LOCAL_END_POINT_LIST, pCEP); + } + pCEP->LocalEndPoint.QPN = pCEP->LocalEndPoint.EECN = 0; + pCEP->LocalEndPoint.CaGUID = 0; + } + if (pCEP->RemoteEndPoint.CaGUID) + { + CM_MapRemoveEntry(&gCM->RemoteEndPointMap, &pCEP->RemoteEndPointMapEntry, REMOTE_END_POINT_LIST, pCEP); + pCEP->RemoteEndPoint.QPN = pCEP->RemoteEndPoint.EECN = 0; + pCEP->RemoteEndPoint.CaGUID = 0; + } +} + +// CmGetStateString +// +// Returns an ascii string associated with the state +// +const char* +CmGetStateString(CM_CEP_STATE state) +{ + switch(state) + { + case CMS_IDLE: + return "CMS_IDLE"; + case CMS_LISTEN: + return "CMS_LISTEN"; + case CMS_REQ_SENT: + return "CMS_REQ_SENT"; + case CMS_REQ_RCVD: + return "CMS_REQ_RCVD"; + case CMS_REP_SENT: + return "CMS_REP_SENT"; + case CMS_REP_RCVD: + return "CMS_REP_RCVD"; + case CMS_MRA_REQ_SENT: + return "CMS_MRA_REQ_SENT"; + case CMS_MRA_REP_SENT: + return "CMS_MRA_REP_SENT"; + case CMS_REP_WAIT: + return "CMS_REP_WAIT"; + case CMS_MRA_REP_RCVD: + return "CMS_MRA_REP_RCVD"; + case CMS_LAP_SENT: + return "CMS_LAP_SENT"; + case CMS_MRA_LAP_SENT: + return "CMS_MRA_LAP_SENT"; + case CMS_LAP_RCVD: + return "CMS_LAP_RCVD"; + case CMS_MRA_LAP_RCVD: + return "CMS_MRA_LAP_RCVD"; + case CMS_ESTABLISHED: + return "CMS_ESTABLISHED"; + case CMS_DREQ_SENT: + return "CMS_DREQ_SENT"; + case CMS_DREQ_RCVD: + return "CMS_DREQ_RCVD"; + case CMS_SIM_DREQ_RCVD: + return "CMS_SIM_DREQ_RCVD"; + case CMS_TIMEWAIT: + return "CMS_TIMEWAIT"; + case CMS_REGISTERED: + return "CMS_REGISTERED"; + case CMS_SIDR_REQ_SENT: + return "CMS_SIDR_REQ_SENT"; + case CMS_SIDR_REQ_RCVD: + return "CMS_SIDR_REQ_RCVD"; + //case CMS_SIDR_RESP_SENT: + // return "CMS_SIDR_RESP_SENT"; + default: + return "Unknown State"; + } +} diff --git a/IbAccess/Common/Ibt/Cm/cm_common.c b/IbAccess/Common/Ibt/Cm/cm_common.c new file mode 100644 index 0000000..83b72a8 --- /dev/null +++ b/IbAccess/Common/Ibt/Cm/cm_common.c @@ -0,0 +1,290 @@ +/* BEGIN_ICS_COPYRIGHT6 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT6 ****************************************/ + +// Common code between user and kernel level CM +#include "ib_cm.h" + +// backwards compatibilty functions +IB_HANDLE +CmCreateCEP( + CM_CEP_TYPE TransportServiceType + ) +{ + return iba_cm_create_cep(TransportServiceType); +} + +FSTATUS +CmDestroyCEP(IB_HANDLE hCEP) +{ + return iba_cm_destroy_cep(hCEP); +} + +FSTATUS +CmModifyCEP( + IB_HANDLE hCEP, + uint32 AttrType, + const char* AttrValue, + uint32 AttrLen, + uint32 Offset + ) +{ + return iba_cm_modify_cep( hCEP, AttrType, AttrValue, AttrLen, Offset); +} + +FSTATUS +CmConnect( + IB_HANDLE hCEP, + const CM_REQUEST_INFO* pConnectRequest, + PFN_CM_CALLBACK pfnConnectCB, + void* Context + ) +{ + return iba_cm_connect(hCEP, pConnectRequest, pfnConnectCB, Context); +} + +FSTATUS +CmConnectPeer( + IB_HANDLE hCEP, + const CM_REQUEST_INFO* pConnectRequest, + PFN_CM_CALLBACK pfnConnectCB, + void* Context + ) +{ + return iba_cm_connect_peer( hCEP, pConnectRequest, pfnConnectCB, Context); +} + + +FSTATUS +CmListen( + IN IB_HANDLE hCEP, + IN const CM_LISTEN_INFO* pListenInfo, + IN PFN_CM_CALLBACK pfnListenCB, + IN void* Context + ) +{ + return iba_cm_listen( hCEP, pListenInfo, pfnListenCB, Context); +} + + +FSTATUS +CmWait( + IB_HANDLE CEPHandleArray[], + CM_CONN_INFO* ConnInfoArray[], + uint32 ArrayCount, + uint32 Timeout_us + //EVENT_HANDLE hWaitEvent // Associate the array of handles to this event + ) +{ + return iba_cm_wait(CEPHandleArray, ConnInfoArray, ArrayCount, Timeout_us); +} + + +FSTATUS +CmAccept( + IN IB_HANDLE hCEP, + IN CM_CONN_INFO* pSendConnInfo, // Send REP + OUT CM_CONN_INFO* pRecvConnInfo, // Rcvd RTU, REJ or TIMEOUT + IN PFN_CM_CALLBACK pfnCallback, + IN void* Context, + OUT IB_HANDLE* hNewCEP + ) +{ + return iba_cm_accept( hCEP, pSendConnInfo, pRecvConnInfo, pfnCallback, + Context, hNewCEP); +} + + + +FSTATUS +CmReject( + IN IB_HANDLE hCEP, + IN const CM_REJECT_INFO* pConnectReject + ) +{ + return iba_cm_reject( hCEP, pConnectReject); +} + +FSTATUS +CmCancel( + IN IB_HANDLE hCEP + ) +{ + return iba_cm_cancel( hCEP); +} + + +FSTATUS +CmDisconnect( + IN IB_HANDLE hCEP, + IN const CM_DREQUEST_INFO* pDRequest, // Send DREQ + IN const CM_DREPLY_INFO* pDReply // Send DREP + ) +{ + return iba_cm_disconnect( hCEP, pDRequest, pDReply); +} + + +FSTATUS +SIDRRegister( + IN IB_HANDLE hCEP, + IN const SIDR_REGISTER_INFO* pSIDRRegisterInfo, + PFN_CM_CALLBACK pfnLookupCallback, + void* Context + ) +{ + return iba_cm_sidr_register( hCEP, pSIDRRegisterInfo, pfnLookupCallback, + Context); +} + + +FSTATUS +SIDRDeregister( + IB_HANDLE hCEP + ) +{ + return iba_cm_sidr_deregister(hCEP); +} + + +FSTATUS +SIDRResponse( + IN IB_HANDLE hCEP, + const SIDR_RESP_INFO* pSIDRResponse + ) +{ + return iba_cm_sidr_response( hCEP, pSIDRResponse); +} + +FSTATUS +SIDRQuery( + IB_HANDLE hCEP, + const SIDR_REQ_INFO* pSIDRRequest, + PFN_CM_CALLBACK pfnQueryCB, + void* Context + ) +{ + return iba_cm_sidr_query( hCEP, pSIDRRequest, pfnQueryCB, Context); +} + +static const char* const CmRejectionCodeText[] = { + "Unknown CM Rejection Code", + "RC_NO_QP", + "RC_NO_EEC", + "RC_NO_RESOURCES", + "RC_TIMEOUT", + "RC_UNSUPPORTED_REQ", + "RC_INVALID_COMMID", + "RC_INVALID_COMMINST", + "RC_INVALID_SID", + "RC_INVALID_TSTYPE", + "RC_STALE_CONN", + "RC_INVALID_RDC", + "RC_PRIMARY_DGID_REJ", + "RC_PRIMARY_DLID_REJ", + "RC_INVALID_PRIMARY_SL", + "RC_INVALID_PRIMARY_TC", + "RC_INVALID_PRIMARY_HL", + "RC_INVALID_PRIMARY_PR", + "RC_ALTERNATE_DGID", + "RC_ALTERNATE_DLID", + "RC_INVALID_ALTERNATE_SL", + "RC_INVALID_ALTERNATE_TC", + "RC_INVALID_ALTERNATE_HL", + "RC_INVALID_ALTERNATE_PR", + "RC_CMPORT_REDIR", + "RC_INVALID_PATHMTU", + "RC_INSUFFICIENT_RESP_RES", + "RC_USER_REJ", + "RC_RNRCOUNT_REJ" +}; + +const char* iba_cm_rejection_code_msg(uint16 code) +{ + if (code >= (unsigned)(sizeof(CmRejectionCodeText)/sizeof(char*))) + return "Unknown CM Rejection Code"; + else + return CmRejectionCodeText[code]; +} + +static const char* const CmAprStatusText[] = { + "APS_PATH_LOADED", + "APS_INVALID_COMMID", + "APS_UNSUPPORTED_REQ", + "APS_REJECTED", + "APS_CMPORT_REDIR", + "APS_DUPLICATE_PATH", + "APS_ENDPOINT_MISMATCH", + "APS_REJECT_DLID", + "APS_REJECT_DGID", + "APS_REJECT_FL", + "APS_REJECT_TC", + "APS_REJECT_HL", + "APS_REJECT_PR", + "APS_REJECT_SL" +}; + +const char* iba_cm_apr_status_msg(uint16 code) +{ + if (code >= (unsigned)(sizeof(CmAprStatusText)/sizeof(char*))) + return "Unknown CM APS Status"; + else + return CmAprStatusText[code]; +} + +static const char* const CmSidrRespStatusText[] = { + "SRS_VALID_QPN", + "SRS_SID_NOT_SUPPORTED", + "SRS_S_PROVIDER_REJECTED", + "SRS_QP_UNAVAILABLE", + "SRS_REDIRECT", + "SRS_VERSION_NOT_SUPPORTED" + // 6-255 reserved +}; + +const char* iba_cm_sidr_resp_status_msg(uint8 code) +{ + if (code >= (unsigned)(sizeof(CmSidrRespStatusText)/sizeof(char*))) + return "Unknown CM SIDR Resp Status"; + else + return CmSidrRespStatusText[code]; +} + +static const char* const CmRepFailoverText[] = { + "CM_REP_FO_ACCEPTED", + "CM_REP_FO_NOT_SUPPORTED", + "CM_REP_FO_REJECTED_ALT" +}; + +const char* iba_cm_rep_failover_msg(uint8 code) +{ + if (code >= (unsigned)(sizeof(CmRepFailoverText)/sizeof(char*))) + return "Unknown CM Failover Reply"; + else + return CmRepFailoverText[code]; +} diff --git a/IbAccess/Common/Ibt/Cm/cm_common.h b/IbAccess/Common/Ibt/Cm/cm_common.h new file mode 100644 index 0000000..c6e87c9 --- /dev/null +++ b/IbAccess/Common/Ibt/Cm/cm_common.h @@ -0,0 +1,395 @@ +/* BEGIN_ICS_COPYRIGHT4 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT4 ****************************************/ +/* [ICS VERSION STRING: unknown] */ + +/* declarations shared by kernel and user mode CMs */ + +/* Suppress duplicate loading of this file */ +#ifndef _IBA_IB_CM_COMMON_H_ +#define _IBA_IB_CM_COMMON_H_ + + +#if defined (__cplusplus) +extern "C" { +#endif + +/* OS independent routines */ +#include "datatypes.h" +#include "ievent.h" +#include "itimer.h" +#include "imemory.h" +#include "ispinlock.h" +#include "idebug.h" +#include "ithread.h" +#include "isyscallback.h" +#include "iquickmap.h" +#include "imath.h" +#include "ib_cm.h" +#include "cm_params.h" + + +/************************************************************************* + * Defines + */ + +/* The following debug macros must be defined before including the "ib_debug.h" */ +#define _DBG_PRINT_EPILOG(LEVEL,STRING) +#define _DBG_PRINT_PROLOG(LEVEL,STRING) +#define _DBG_ERROR_EPILOG(LEVEL,STRING) +#define _DBG_ERROR_PROLOG(LEVEL,STRING) +#define _DBG_FATAL_EPILOG(LEVEL,STRING) +#define _DBG_FATAL_PROLOG(LEVEL,STRING) +#define _DBG_CHK_IRQL(IRQL) + +#include "ib_debug.h" + +#undef _ib_dbg_params +#define _ib_dbg_params cm_debug_params +extern IB_DBG_PARAMS cm_debug_params; + +/* Memory tag to use in all memory allocation */ +#define CM_MEM_TAG 0xbeef /*_ib_dbg_params.mem_tag */ + +/* Generic macros to test, set or clear bits */ +#define BitTest(a,b) ((a) & (b)) +#define BitSet(a,b) ((a) |= (b)) +#define BitClear(a,b) ((a) &= (~(b))) + +#define UNUSED_VAR(x) (void)(x) + +// forward type decl +struct _IBT_COMPONENT_INFO; + +/************************************************************************* + * Doubly link-list macros + */ +typedef struct DLIST_ENTRY { + struct DLIST_ENTRY *Next; + struct DLIST_ENTRY *Prev; +} DLIST_ENTRY, *PDLIST_ENTRY; + +/* + * void + * DListInit( + * PDLIST_ENTRY ListHead + * ); + */ +#define DLIST_INIT DListInit + +#define DListInit(ListHead) (\ + (ListHead)->Next = (ListHead)->Prev = (ListHead)) + + +/* + * boolean + * DListIsEmpty( + * PDLIST_ENTRY ListHead + * ); + */ +#define DLIST_IS_EMPTY DListIsEmpty + +#define DListIsEmpty(ListHead) \ + ((ListHead)->Next == (ListHead)) + + +/* + * PDLIST_ENTRY + * DListGetNext( + * PDLIST_ENTRY Entry + * ); + */ +#define DLIST_GET_NEXT DListGetNext + +#define DListGetNext(Entry) \ + (Entry)->Next + + +/* + * PDLIST_ENTRY + * DListGetPrev( + * PDLIST_ENTRY Entry + * ); + */ +#define DLIST_GET_PREV DListGetPrev + +#define DListGetPrev(Entry) \ + (Entry)->Prev + + +/* + * PDLIST_ENTRY + * DListGetHead( + * PDLIST_ENTRY ListHead + * ); + */ +#define DLIST_GET_HEAD DListGetHead + +#define DListGetHead(ListHead) \ + (ListHead)->Next + + + +/* + * PDLIST_ENTRY + * DListRemoveHead( + * PDLIST_ENTRY ListHead + * ); + */ + +#define DLIST_REMOVE_HEAD DListRemoveHead + +#define DListRemoveHead(ListHead, List, Obj) \ + (ListHead)->Next;\ + {DListRemoveEntry((ListHead)->Next, List, Obj)} + + +/* + * PDLIST_ENTRY + * DListRemoveTail( + * PDLIST_ENTRY ListHead + * ); + */ +#define DLIST_REMOVE_TAIL DListRemoveTail + +#define DListRemoveTail(ListHead, List, Obj) \ + (ListHead)->Prev;\ + {DListRemoveEntry((ListHead)->Prev, List, Obj)} + + +/* + * void + * DListRemoveEntry( + * PDLIST_ENTRY Entry + * ); + */ +#define DLIST_REMOVE_ENTRY DListRemoveEntry + +#define DListRemoveEntry(Entry, List, Obj) {\ + PDLIST_ENTRY pNext = (Entry)->Next;\ + PDLIST_ENTRY pPrev = (Entry)->Prev;\ + pPrev->Next = pNext;\ + pNext->Prev = pPrev;\ + DListInit(Entry);\ + _DBG_INFO((" --> Removed from " #List "\n", _DBG_PTR(Obj)));\ + } + +/* + * void + * DListInsertTail( + * PDLIST_ENTRY ListHead, + * PDLIST_ENTRY Entry + * ); + */ + +#define DLIST_INSERT_TAIL DListInsertTail + +#define DListInsertTail(ListHead, Entry, List, Obj) {\ + PDLIST_ENTRY pHead = (ListHead);\ + PDLIST_ENTRY pPrev = (ListHead)->Prev;\ + (Entry)->Next = pHead;\ + (Entry)->Prev = pPrev;\ + pPrev->Next = (Entry);\ + pHead->Prev = (Entry);\ + _DBG_INFO((" --> Insert into " #List "\n", _DBG_PTR(Obj)));\ + } + + +/* + * void + * DListInsertHead( + * PDLIST_ENTRY ListHead, + * PDLIST_ENTRY Entry + * ); + */ +#define DLIST_INSERT_HEAD DListInsertHead + +#define DListInsertHead(ListHead, Entry, List, Obj) {\ + PDLIST_ENTRY pHead = (ListHead);\ + PDLIST_ENTRY pNext = (ListHead)->Next;\ + (Entry)->Next = pNext;\ + (Entry)->Prev = pHead;\ + pNext->Prev = (Entry);\ + pHead->Next = (Entry);\ + _DBG_INFO((" --> Insert into " #List "\n", _DBG_PTR(Obj)));\ + } + + +/* + * void + * DListIterate( + * PDLIST_ENTRY anchor, + * PDLIST_ENTRY index, + * PDLIST_ENTRY listp + * ); + */ + +#define DLIST_ITERATE DListIterate + +#define DListIterate(anchor, index, listp) \ + (anchor) = (PDLIST_ENTRY)(listp); \ + for((index) = (anchor)->Next; (index) != (anchor); (index) = (index)->Next) + +/************************************************************************* + * Keyed Map macros + */ + +#define CM_MAP cl_qmap_t +#define CM_MAP_ITEM cl_map_item_t + +#define CM_MapInit(pMap, pFunc) cl_qmap_init(pMap, pFunc) +#define CM_MapHead(pMap) cl_qmap_head(pMap) +#define CM_MapEnd(pMap) cl_qmap_end(pMap) +#define CM_MapNext(pMapEntry) cl_qmap_next(pMapEntry) +#define CM_MapPrev(pMapEntry) cl_qmap_prev(pMapEntry) +#define CM_MapGet(pMap, Key) cl_qmap_get(pMap, Key) +#define CM_MapGetCompare(pMap, Key, pFunc) cl_qmap_get_compare(pMap, Key, pFunc) +#define CM_MapIsEmpty(pMap) cl_is_qmap_empty(pMap) + +#define CM_MapInsert(pMap, Key, pEntry, MapName, pCEP) {\ + CM_MAP_ITEM *pMapEntry; \ + pMapEntry = cl_qmap_insert(pMap, Key, pEntry); \ + /* If duplicate key, insert does nothing and returns existing entry */ \ + ASSERT(pMapEntry == pEntry); \ + _DBG_INFO((" --> Insert into " #MapName "\n", _DBG_PTR(pCEP)));\ + } + +#define CM_MapRemoveEntry(pMap, pEntry, MapName, pCEP) {\ + cl_qmap_remove_item(pMap, pEntry); \ + _DBG_INFO((" --> Removed from " #MapName "\n", _DBG_PTR(pCEP)));\ + } + + +/*************************************************************************/ + +/************************************************************************* + * Function prototypes + */ + + +/* + * CmInit + * + * Initialize the CM module. This should only be called once normally during + * system startup time. + * + * + * + * + * INPUTS: + * + * None. + * + * + * OUTPUTS: + * + * None. + * + * + * RETURNS: + * + * FSUCCESS + * FERROR + * FINSUFFICIENT_RESOURCES + * + */ +FSTATUS +CmInit( + IN struct _IBT_COMPONENT_INFO *ComponentInfo + ); + + +/* + * CmDestroy + * + * Destroy the CM module. This should only be called once normally during + * system shutdown time to cleanup any resources used by the CM. + * + * + * + * + * INPUTS: + * + * None. + * + * + * OUTPUTS: + * + * None. + * + * + * RETURNS: + * + * FSUCCESS + * FERROR + * + */ +void +CmDestroy( void ); + + +/* + * CmGetConnInfo + * + * This routine is used to retrieve the connection status and information + * on the specified endpoint. This is intended for Internal use only as part + * of generating the arguments for CM callbacks + * + * Internal use only + * + * INPUTS: + * + * hCEP - Handle to the CEP object. + * + * pConnInfo - Specify the buffer to store the connection information and status. + * + * OUTPUTS: + * + * None. + * + * + * RETURNS: + * + * FSUCCESS + * + * FERROR + * + */ +FSTATUS +CmGetConnInfo( + IN IB_HANDLE hCEP, + OUT CM_CONN_INFO* pConnInfo + ); + + +#if defined (__cplusplus) +}; +#endif + + +#endif /* _IBA_IB_CM_COMMON_H_ */ diff --git a/IbAccess/Common/Ibt/Cm/cm_gsa.c b/IbAccess/Common/Ibt/Cm/cm_gsa.c new file mode 100644 index 0000000..3354daa --- /dev/null +++ b/IbAccess/Common/Ibt/Cm/cm_gsa.c @@ -0,0 +1,5328 @@ +/* BEGIN_ICS_COPYRIGHT4 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT4 ****************************************/ + + +// Public header file +#include "ib_cm.h" + +// Private header file +#include "cm_private.h" + +static FSTATUS +ProcessRecvCmMad( + IN CM_MAD* pMad, + IN IBT_DGRM_ELEMENT* pRemoteDgrm + ); + +static FSTATUS +ProcessClassPortInfo( + CM_MAD* pMad, + IBT_DGRM_ELEMENT* pRemoteDgrm + ); + +static FSTATUS +ProcessReq( + CM_MAD* pMad, + IBT_DGRM_ELEMENT* pRemoteDgrm + ); + +static FSTATUS +ProcessReqPassive( + IN CM_CEP_OBJECT* pCEP, + IN CM_MAD* pMad, + IN IBT_DGRM_ELEMENT* pRemoteDgrm + ); + +static FSTATUS +ProcessReqPeer( + IN CM_CEP_OBJECT* pCEP, + IN CM_MAD* pMad, + IN IBT_DGRM_ELEMENT* pRemoteDgrm, + IN CM_CEP_OBJECT* pCEPReq + ); + +static FSTATUS +SaveReqToPassiveCEP( + IN CM_CEP_OBJECT* pCEP, + IN CMM_REQ* pREQ, + IN EUI64 CaGUID, + IN EUI64 PortGuid, // port which received REQ + OUT CM_REJECTION_CODE *RejReason // only returned on failure + ); + +static FSTATUS +ProcessReqDup( + IN CM_CEP_OBJECT* pCEP, + IN CM_MAD* pMad, + IN IBT_DGRM_ELEMENT* pRemoteDgrm + ); + +static FSTATUS +ProcessReqStale( + IN CM_CEP_OBJECT* pCEP, + IN CM_MAD* pMad, + IN IBT_DGRM_ELEMENT* pRemoteDgrm + ); + +static FSTATUS +ProcessRep( + CM_MAD* pMad, + IBT_DGRM_ELEMENT* pRemoteDgrm + ); + +static FSTATUS +ProcessRtu( + CM_MAD* pMad, + IBT_DGRM_ELEMENT* pRemoteDgrm + ); + +static FSTATUS +ProcessRtuPassive( + IN CM_CEP_OBJECT* pCEP, + IN CM_MAD* pMad, + IN IBT_DGRM_ELEMENT* pRemoteDgrm + ); + +static FSTATUS +ProcessRejReq( + CM_MAD* pMad, + IBT_DGRM_ELEMENT* pRemoteDgrm + ); + +static FSTATUS +ProcessRejRep( + CM_MAD* pMad, + IBT_DGRM_ELEMENT* pRemoteDgrm + ); + +static FSTATUS +ProcessMraReq( + CM_MAD* pMad, + IBT_DGRM_ELEMENT* pRemoteDgrm + ); + +static FSTATUS +ProcessMraRep( + CM_MAD* pMad, + IBT_DGRM_ELEMENT* pRemoteDgrm + ); + +static FSTATUS +ProcessMraLap( + CM_MAD* pMad, + IBT_DGRM_ELEMENT* pRemoteDgrm + ); + +static FSTATUS +ProcessLap( + CM_MAD* pMad, + IBT_DGRM_ELEMENT* pRemoteDgrm + ); + +static FSTATUS +ProcessApr( + CM_MAD* pMad, + IBT_DGRM_ELEMENT* pRemoteDgrm + ); + +static FSTATUS +ProcessDreq( + CM_MAD* pMad, + IBT_DGRM_ELEMENT* pRemoteDgrm + ); + +static FSTATUS +ProcessDreqCep( + IN CM_CEP_OBJECT* pCEP, + IN CM_MAD* pMad, + IN IBT_DGRM_ELEMENT* pRemoteDgrm + ); + +static FSTATUS +ProcessDrep( + CM_MAD* pMad, + IBT_DGRM_ELEMENT* pRemoteDgrm + ); + +static FSTATUS +ProcessSidrReq( + CM_MAD* pMad, + IBT_DGRM_ELEMENT* pRemoteDgrm + ); + +static FSTATUS +ProcessSidrResp( + CM_MAD* pMad, + IBT_DGRM_ELEMENT* pRemoteDgrm + ); + +static FSTATUS +ResendREQ( + IN CM_CEP_OBJECT* pCEP + ); + +static FSTATUS +ResendREP( + IN CM_CEP_OBJECT* pCEP + ); + +// +// DgrmDump +// +// Show the message type Sent/Received +// +// INPUTS: +// +// +// +// OUTPUTS: +// +// None. +// +// RETURNS: +// +// None +// +// IRQL: +// +// This routine is called at IRQL_PASSIVE_LEVEL. +// +void +DgrmDump(IBT_DGRM_ELEMENT* pDgrm, char* pStr, boolean bRecv) +{ + CM_MAD* pMad=NULL; + + if (bRecv) + pMad = (CM_MAD*)GsiDgrmGetRecvMad(pDgrm); + else + pMad = (CM_MAD*)GsiDgrmGetSendMad(pDgrm); + + switch (pMad->common.AttributeID) + { + case MCLASS_ATTRIB_ID_CLASS_PORT_INFO: + _DBG_INFO((" *** ClassPortInfo %s ***\n", + _DBG_PTR(pDgrm), _DBG_PTR(pStr))); + break; + + case MCLASS_ATTRIB_ID_REQ: + _DBG_INFO((" *** REQ %s ***\n", + _DBG_PTR(pDgrm), _DBG_PTR(pStr))); + break; + + case MCLASS_ATTRIB_ID_MRA: + _DBG_INFO((" *** MRA %s ***\n", + _DBG_PTR(pDgrm), _DBG_PTR(pStr))); + break; + + case MCLASS_ATTRIB_ID_REJ: + _DBG_INFO((" *** REJ %s ***\n", + _DBG_PTR(pDgrm), _DBG_PTR(pStr))); + break; + + case MCLASS_ATTRIB_ID_REP: + _DBG_INFO((" *** REP %s ***\n", + _DBG_PTR(pDgrm), _DBG_PTR(pStr))); + break; + + case MCLASS_ATTRIB_ID_RTU: + _DBG_INFO((" *** RTU %s ***\n", + _DBG_PTR(pDgrm), _DBG_PTR(pStr))); + break; + + case MCLASS_ATTRIB_ID_DREQ: + _DBG_INFO((" *** DREQ %s ***\n", + _DBG_PTR(pDgrm), _DBG_PTR(pStr))); + break; + + case MCLASS_ATTRIB_ID_DREP: + _DBG_INFO((" *** DREP %s ***\n", + _DBG_PTR(pDgrm), _DBG_PTR(pStr))); + break; + + case MCLASS_ATTRIB_ID_SIDR_REQ: + _DBG_INFO((" *** SIDR REQ %s ***\n", + _DBG_PTR(pDgrm), _DBG_PTR(pStr))); + //MsgOut("*** SIDR REQ %s Compl ***, Remote Lid=0x%x\n", _DBG_PTR(pStr), pDgrm->RemoteLID); + break; + + case MCLASS_ATTRIB_ID_SIDR_RESP: + _DBG_INFO((" *** SIDR RESP %s ***\n", + _DBG_PTR(pDgrm), _DBG_PTR(pStr))); + //MsgOut("*** SIDR RESP %s Compl ***, Remote Lid=0x%x\n", _DBG_PTR(pStr), pDgrm->RemoteLID); + break; + + case MCLASS_ATTRIB_ID_LAP: + _DBG_INFO((" *** LAP %s ***\n", + _DBG_PTR(pDgrm), _DBG_PTR(pStr))); + break; + + case MCLASS_ATTRIB_ID_APR: + _DBG_INFO((" *** APR %s ***\n", + _DBG_PTR(pDgrm), _DBG_PTR(pStr))); + break; + + default: + _DBG_INFO((" *** UNKNOWN %s ***\n", + _DBG_PTR(pDgrm), _DBG_PTR(pStr))); + break; + } + +} // DgrmDump() + +// +// VpdAsyncEventCallback +// +// VPD/VCA calls this routine when a RTU event is received on the receive QP +// or a Path Migrated event occurs +// +// INPUTS: +// +// +// +// OUTPUTS: +// +// None. +// +// RETURNS: +// +// FSUCCESS - Indicates a successful load. +// +// IRQL: +// +// This routine is called at IRQL_PASSIVE_LEVEL. +// +#ifdef _CM_EVENT_ON_QP_ + +void +VpdCompletionCallback( + IN void *CaContext, + IN void *CqContext + ) +{ + +} + +void +VpdAsyncEventCallback( + IN void *CaContext, + IN IB_EVENT_RECORD *EventRecord + ) +{ + CM_DEVICE_OBJECT* pDevice=(CM_DEVICE_OBJECT*)CaContext; + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, VpdAsyncEventCallback); + + _DBG_INFO((" Received Async Event Context), + EventRecord->EventType, EventRecord->EventCode)); + + // + // If we received a RTU event on the receive queue, we locate the appropriate + // CEP object using the QPN and transition the CEP state to established state + // + switch ( EventRecord->EventType ) + { + case AsyncEventRecvQ: + if (EventRecord->EventCode == IB_AE_RQ_COMM_ESTABLISHED) + { + CM_END_POINT EndPoint; + CM_MAP_ITEM* pMapEntry; + + EndPoint.CaGUID = pDevice->CaGUID; + // special Async event for CM, QPN is in Context + EndPoint.QPN = (uint32)(uintn)EventRecord->Context; + EndPoint.EECN = 0; + _DBG_INFO((" Received RTU event on RQ \n", + _DBG_PTR(pDevice), EndPoint.QPN, pDevice->CaGUID)); + SpinLockAcquire(&gCM->ListLock); + pMapEntry = CM_MapGetCompare(&gCM->LocalEndPointMap, (uintn)&EndPoint, + CepAddrLocalEndPointCompare); + if (pMapEntry != CM_MapEnd(&gCM->LocalEndPointMap)) + { + CM_CEP_OBJECT* pCEP; + FSTATUS Status; + + pCEP = PARENT_STRUCT(pMapEntry, CM_CEP_OBJECT, LocalEndPointMapEntry); + // Process as an RTU + Status = ProcessRtuPassive(pCEP, NULL, NULL); + if (Status == FSUCCESS) + { + _DBG_INFO((" RTU event on RQ processed successfully !\n", + _DBG_PTR(pDevice), _DBG_PTR(pCEP), + EndPoint.QPN, pDevice->CaGUID)); + } else if (Status != FINVALID_STATE) { + _DBG_WARNING((" RTU event on RQ dropped - unable to process it! <%s, qpn %u, ca guid 0x%"PRIx64" >\n", + _DBG_PTR(pDevice), _DBG_PTR(FSTATUS_MSG(Status)), + EndPoint.QPN, pDevice->CaGUID)); + } + } else { + _DBG_WARNING((" RTU event on RQ dropped - no match on QPN and CA GUID !\n", + _DBG_PTR(pDevice), EndPoint.QPN, pDevice->CaGUID)); + } + + SpinLockRelease(&gCM->ListLock); + } + break; + // TBD - case AsyncEventEE: +#if 0 + // disabled, this could be helpful for Server side, where there is + // no option. However for Client side we want to allow client to + // choose between iba_cm_migrated and iba_cm_migrated_reload + case AsyncEventPathMigrated: + { + CM_END_POINT EndPoint; + CM_MAP_ITEM* pMapEntry; + + EndPoint.CaGUID = pDevice->CaGUID; + // special Async event for CM, QPN is in Context + EndPoint.QPN = (uint32)(uintn)EventRecord->Context; + EndPoint.EECN = 0; + _DBG_INFO((" Received Path Migrated event \n", + _DBG_PTR(pDevice), EndPoint.QPN, pDevice->CaGUID)); + SpinLockAcquire(&gCM->ListLock); + pMapEntry = CM_MapGetCompare(&gCM->LocalEndPointMap, (uintn)&EndPoint, + CepAddrLocalEndPointCompare); + if (pMapEntry != CM_MapEnd(&gCM->LocalEndPointMap)) + { + CM_CEP_OBJECT* pCEP; + FSTATUS Status; + + pCEP = PARENT_STRUCT(pMapEntry, CM_CEP_OBJECT, LocalEndPointMapEntry); + //if (pCEP->Mode == CM_MODE_PASSIVE) + //and adjust iba_cm_migrated to be a noop for CM_MODE_PASSIVE + Status = MigratedA(pCEP); + if (Status == FSUCCESS) + { + _DBG_INFO((" Path Migrated event processed successfully !\n", + _DBG_PTR(pDevice), _DBG_PTR(pCEP), + EndPoint.QPN, pDevice->CaGUID)); + } else if (Status != FINVALID_STATE) { + _DBG_WARNING((" Path Migrated event dropped - unable to process it! <%s, qpn %u, ca guid 0x%"PRIx64" >\n", + _DBG_PTR(pDevice), _DBG_PTR(FSTATUS_MSG(Status)), + EndPoint.QPN, pDevice->CaGUID)); + } + } else { + _DBG_WARNING((" Path Migrated event dropped - no match on QPN and CA GUID !\n", + _DBG_PTR(pDevice), EndPoint.QPN, pDevice->CaGUID)); + } + + SpinLockRelease(&gCM->ListLock); + } + break; + // TBD - case AsyncEventEEPathMigrated: +#endif + default: + break; + } + + _DBG_LEAVE_LVL(_DBG_LVL_FUNC_TRACE); +} +#endif + + +// +// GsaSendCompleteCallback +// +// GSA called this routine when a send datagram is completed. +// +// INPUTS: +// +// +// +// OUTPUTS: +// +// None. +// +// RETURNS: +// +// FSUCCESS - Indicates a successful load. +// +// IRQL: +// +// This routine is called at IRQL_PASSIVE_LEVEL. +// + +void +GsaSendCompleteCallback( + void* Context, + IBT_DGRM_ELEMENT* pDgrmList + ) +{ + IBT_DGRM_ELEMENT* pDgrmElement=NULL; + IBT_DGRM_ELEMENT* pNextDgrmElement=NULL; + + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, GsaSendCompleteCallback); + + // Return the dgrm to the pool if it is not owned + SpinLockAcquire(&gCM->ListLock); + + pDgrmElement = pDgrmList; + while (pDgrmElement) + { + pNextDgrmElement = (IBT_DGRM_ELEMENT*) pDgrmElement->Element.pNextElement; + + DgrmDump(pDgrmElement, "Sent", 0); + + CmDgrmClearInUse(pDgrmElement); + pDgrmElement->Element.pNextElement = NULL; + if (CmDgrmIsReleaseFlagSet(pDgrmElement)) + { + _DBG_INFO((" Datagram returned to pool \n", + _DBG_PTR(pDgrmElement), _DBG_PTR(gCM->GSADgrmPoolHandle))); + + CmDgrmPut(pDgrmElement); + } else { + _DBG_INFO((" Datagram marked send done\n", + _DBG_PTR(pDgrmElement))); + } + pDgrmElement = pNextDgrmElement; + } + + SpinLockRelease(&gCM->ListLock); + _DBG_LEAVE_LVL(_DBG_LVL_FUNC_TRACE); + return; +} // GsaSendCompleteCallback() + + +////////////////////////////////////////////////////////////////////////// +// GsaRecvCallback +// +// GSA called this routine when a datagram is received. +// +// INPUTS: +// +// +// +// OUTPUTS: +// +// None. +// +// RETURNS: +// +// FSUCCESS - Indicates a successful load. +// +// IRQL: +// +// This routine is called at IRQL_PASSIVE_LEVEL. +// + +FSTATUS +GsaRecvCallback( + void* Context, + IBT_DGRM_ELEMENT* pDgrmList + ) +{ + IBT_DGRM_ELEMENT* pDgrmElement=NULL; + IBT_DGRM_ELEMENT* pNextDgrmElement=NULL; + + CM_MAD* pMad=NULL; + + uint8 BaseVer=0; + uint8 MgmtClass=0; + uint8 ClassVer=0; + + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, GsaRecvCallback); + + ASSERT(pDgrmList); + + // Sanity checks + if (Context != gCM) + { + _DBG_ERROR((" Invalid CM Context passed in!!!\n", _DBG_PTR(Context))); + _DBG_FSTATUS_RETURN_LVL(_DBG_LVL_FUNC_TRACE,FCOMPLETED); + return FCOMPLETED; + } + + // + // iterate thru each datagrams/mads in the list + // + for (pDgrmElement = pDgrmList; pDgrmElement; pDgrmElement = pNextDgrmElement) + { + pNextDgrmElement = (IBT_DGRM_ELEMENT*) pDgrmElement->Element.pNextElement; + + // Basic checks + /* MAD_BLOCK_SIZE(2048) + GRH (40) */ + if (pDgrmElement->Element.RecvByteCount > CM_DGRM_SIZE) + { + AtomicIncrementVoid(&gCM->Recv.Failed); + _DBG_WARNING((" Datagram passed more than %d bytes \n", + _DBG_PTR(pDgrmElement), + MAD_BLOCK_SIZE, + pDgrmElement->Element.RecvByteCount)); + continue; + } + + pMad = (CM_MAD*)GsiDgrmGetRecvMad(pDgrmElement); + if (!pMad) + { + AtomicIncrementVoid(&gCM->Recv.Failed); + _DBG_WARNING((" Empty MAD passed in!\n", _DBG_PTR(pDgrmElement))); + continue; + } + + MAD_GET_VERSION_INFO(pMad, &BaseVer, &MgmtClass, &ClassVer); + + + if ( (BaseVer != IB_BASE_VERSION) || + (MgmtClass != MCLASS_COMM_MGT) || + (ClassVer != IB_COMM_MGT_CLASS_VERSION)) + { + // BUGBUG IBTA 1.1 pg 623 12.11.2.1 says + // if SIDR_REQ, we need to respond with + // Sidr_Resp.Status = SRS_VERSION_NOT_SUPPORTED and put the highest + // version we support in AddInfo. Instead we discard here + // ?? such as response optional?? + AtomicIncrementVoid(&gCM->Recv.Failed); + _DBG_WARNING((" Invalid base version, mgmt class or class version \n", + _DBG_PTR(pMad), BaseVer, MgmtClass, ClassVer, + pDgrmElement->RemoteLID)); + continue; + } + + DgrmDump(pDgrmElement, "Received", 1); + // Other mad verification should be done by GSA. + + ConvertMadToHostByteOrder(pMad); + + ProcessRecvCmMad(pMad, pDgrmElement); + } + + // The pDgrmList would not be valid when this call returns + + _DBG_FSTATUS_RETURN_LVL(_DBG_LVL_FUNC_TRACE,FCOMPLETED); + return FCOMPLETED; + +} // GsaRecvCallback() + + +////////////////////////////////////////////////////////////////////////// +// ProcessRecvCmMad() +// +// +// INPUTS: +// +// +// +// OUTPUTS: +// +// None. +// +// RETURNS: +// +// FSUCCESS - Indicates a successful load. +// +// IRQL: +// +// This routine is called at IRQL_PASSIVE_LEVEL. +// + +FSTATUS +ProcessRecvCmMad( + CM_MAD* pMad, + IBT_DGRM_ELEMENT* pRemoteDgrm + ) +{ + FSTATUS Status=FSUCCESS; + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, ProcessRecvCmMad); + + SpinLockAcquire(&gCM->ListLock); + + switch (pMad->common.AttributeID) + { + case MCLASS_ATTRIB_ID_CLASS_PORT_INFO: // Class Port Info Received + AtomicIncrementVoid(&gCM->Recv.ClassPortInfo); + Status = ProcessClassPortInfo(pMad, pRemoteDgrm); + break; + + case MCLASS_ATTRIB_ID_REQ: // REQ Received + AtomicIncrementVoid(&gCM->Recv.Req); + Status = ProcessReq(pMad, pRemoteDgrm); + break; + + case MCLASS_ATTRIB_ID_REP: // REP Received + AtomicIncrementVoid(&gCM->Recv.Rep); + Status = ProcessRep(pMad, pRemoteDgrm); + break; + + case MCLASS_ATTRIB_ID_RTU: // RTU received + AtomicIncrementVoid(&gCM->Recv.Rtu); + Status = ProcessRtu(pMad, pRemoteDgrm); + break; + + case MCLASS_ATTRIB_ID_REJ: // REJ received + if (pMad->payload.REJ.MsgRejected == CM_REJECT_REQUEST) + { + AtomicIncrementVoid(&gCM->Recv.RejReq); + Status = ProcessRejReq(pMad, pRemoteDgrm); + } else if (pMad->payload.REJ.MsgRejected == CM_REJECT_REPLY) { + AtomicIncrementVoid(&gCM->Recv.RejRep); + Status = ProcessRejRep(pMad, pRemoteDgrm); + } + // TBD MsgRejected can be unknown when remote side is rejecting due + // to a timeout + break; + + case MCLASS_ATTRIB_ID_MRA: + if (pMad->payload.MRA.MsgMraed == CM_MRA_REQUEST) + { + AtomicIncrementVoid(&gCM->Recv.MraReq); + Status = ProcessMraReq(pMad, pRemoteDgrm); + } else if (pMad->payload.MRA.MsgMraed == CM_MRA_REPLY) { + AtomicIncrementVoid(&gCM->Recv.MraRep); + Status = ProcessMraRep(pMad, pRemoteDgrm); + } else if (pMad->payload.MRA.MsgMraed == CM_MRA_LAP) { + AtomicIncrementVoid(&gCM->Recv.MraLap); + Status = ProcessMraLap(pMad, pRemoteDgrm); + } + break; + + case MCLASS_ATTRIB_ID_LAP: // LAP received + AtomicIncrementVoid(&gCM->Recv.Lap); + Status = ProcessLap(pMad, pRemoteDgrm); + break; + + case MCLASS_ATTRIB_ID_APR: // APR received + if (pMad->payload.APR.APStatus == APS_PATH_LOADED) { + AtomicIncrementVoid(&gCM->Recv.AprAcc); + } else { + AtomicIncrementVoid(&gCM->Recv.AprRej); + } + Status = ProcessApr(pMad, pRemoteDgrm); + break; + + case MCLASS_ATTRIB_ID_DREQ: // DREQ received + AtomicIncrementVoid(&gCM->Recv.Dreq); + Status = ProcessDreq(pMad, pRemoteDgrm); + break; + + case MCLASS_ATTRIB_ID_DREP: // DREP received + AtomicIncrementVoid(&gCM->Recv.Drep); + Status = ProcessDrep(pMad, pRemoteDgrm); + break; + + case MCLASS_ATTRIB_ID_SIDR_REQ: // SIDR_REQ received + AtomicIncrementVoid(&gCM->Recv.SidrReq); + Status = ProcessSidrReq(pMad, pRemoteDgrm); + break; + + case MCLASS_ATTRIB_ID_SIDR_RESP: // SIDR_RESP received + AtomicIncrementVoid(&gCM->Recv.SidrResp); + Status = ProcessSidrResp(pMad, pRemoteDgrm); + break; + + default: + AtomicIncrementVoid(&gCM->Recv.Failed); + _DBG_ERROR((" Invalid attribute ID!!! \n", + _DBG_PTR(pMad), pMad->common.AttributeID)); + + break; + } + + SpinLockRelease(&gCM->ListLock); + _DBG_FSTATUS_RETURN_LVL(_DBG_LVL_FUNC_TRACE,Status); + return Status; + +} // ProcessRecvCmMad() + +////////////////////////////////////////////////////////////////////////// +// ProcessClassPortInfo() +// process an inbound ClassPortInfo +// +// +// INPUTS: +// +// +// +// OUTPUTS: +// +// None. +// +// RETURNS: +// +// +// IRQL: +// +// This routine is called at IRQL_DISPATCH_LEVEL. With ListLock held +// + +FSTATUS +ProcessClassPortInfo( + CM_MAD* pMad, + IBT_DGRM_ELEMENT* pRemoteDgrm + ) +{ + FSTATUS Status=FSUCCESS; + IBT_DGRM_ELEMENT* pDgrmElement=NULL; + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, ProcessClassPortInfo); + + _DBG_INFO((" ClassPortInfo received \n", + _DBG_PTR(pMad), pMad->common.mr.AsReg8, pRemoteDgrm->RemoteLID)); + + /* test AsReg8 so R bit included */ + if (pMad->common.mr.AsReg8 != MMTHD_GET + && pMad->common.mr.AsReg8 != MMTHD_SET) + { + _DBG_WARN((" Unexpected ClassPortInfo Method 0x%x!!! discarding .\n", + _DBG_PTR(pDgrmElement), pMad->common.mr.AsReg8, + pRemoteDgrm->RemoteLID)); + goto fail; + } + + pDgrmElement = CmDgrmGet(); + if (!pDgrmElement) + { + _DBG_WARNING(("failed to send ClassPortInfo: Out of CM Dgrms!\n")); + Status = FINSUFFICIENT_RESOURCES; + goto fail; + } + + GsiDgrmAddrCopy(pDgrmElement, pRemoteDgrm); + + FormatClassPortInfo((CM_MAD*)GsiDgrmGetSendMad(pDgrmElement), + pMad->common.TransactionID); + /* CM does not support traps, hence no fields to set. + * However, for a Set we still return a GetResp with our class info + */ + if (pMad->common.mr.AsReg8 == MMTHD_SET) { + ((CM_MAD*)GsiDgrmGetSendMad(pDgrmElement))->common.u.NS.Status.AsReg16 = hton16(MAD_STATUS_UNSUPPORTED_METHOD); + } + + // In SendComplete(), we return the dgrm to the pool + Status = CmDgrmSendAndRelease(pDgrmElement); + if (Status == FSUCCESS) + { + AtomicIncrementVoid(&gCM->Sent.ClassPortInfoResp); + } else { + + _DBG_WARN((" DgrmSend() failed!!! Unable to send ClassPortInfo .\n", + _DBG_PTR(pDgrmElement), + pRemoteDgrm->RemoteLID, _DBG_PTR(FSTATUS_MSG(Status)))); + + CmDgrmPut(pDgrmElement); + } + + // In SendComplete(), we return the dgrm to the pool +fail: + _DBG_LEAVE_LVL(_DBG_LVL_FUNC_TRACE); + + return Status; +} + +////////////////////////////////////////////////////////////////////////// +// ProcessReq() +// process an inbound REQ +// +// +// INPUTS: +// +// +// +// OUTPUTS: +// +// None. +// +// RETURNS: +// +// +// IRQL: +// +// This routine is called at IRQL_DISPATCH_LEVEL. With ListLock held +// + +FSTATUS +ProcessReq( + CM_MAD* pMad, + IBT_DGRM_ELEMENT* pRemoteDgrm + ) +{ + CM_CEP_OBJECT* pCEP=NULL; + CM_MAP_ITEM* pMapEntry = NULL; + boolean bFoundRemoteEndPoint=FALSE; + FSTATUS Status=FSUCCESS; + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, ProcessReq); + +#ifdef ICS_LOGGING + _DBG_INFO((" REQ received \n", + _DBG_PTR(pMad), + pMad->payload.REQ.LocalCommID, + pMad->payload.REQ.ServiceID, + pMad->payload.REQ.PrimaryLocalLID, + pMad->payload.REQ.PrimaryLocalGID.Type.Global.SubnetPrefix, + pMad->payload.REQ.PrimaryLocalGID.Type.Global.InterfaceID)); + + _DBG_INFO((" REQ received \n", + _DBG_PTR(pMad), + pMad->payload.REQ.LocalCommID, + pMad->payload.REQ.ServiceID, + pMad->payload.REQ.PrimaryRemoteLID, + pMad->payload.REQ.PrimaryRemoteGID.Type.Global.SubnetPrefix, + pMad->payload.REQ.PrimaryRemoteGID.Type.Global.InterfaceID)); +#else + _DBG_INFO((" REQ received \n", + _DBG_PTR(pMad), + pMad->payload.REQ.LocalCommID, + pMad->payload.REQ.ServiceID, + pMad->payload.REQ.PrimaryLocalLID, + pMad->payload.REQ.PrimaryLocalGID.Type.Global.SubnetPrefix, + pMad->payload.REQ.PrimaryLocalGID.Type.Global.InterfaceID, + pMad->payload.REQ.PrimaryRemoteLID, + pMad->payload.REQ.PrimaryRemoteGID.Type.Global.SubnetPrefix, + pMad->payload.REQ.PrimaryRemoteGID.Type.Global.InterfaceID)); +#endif + + if (pMad->payload.REQ.u3.s.TransportServiceType != CM_RC_TYPE + && pMad->payload.REQ.u3.s.TransportServiceType != CM_UC_TYPE + && pMad->payload.REQ.u3.s.TransportServiceType != CM_RD_TYPE + ) + { + _DBG_WARNING((" Invalid transport service type!\n", _DBG_PTR(pMad))); + + SendREJ(RC_INVALID_TSTYPE, + CM_REJECT_REQUEST, + pMad->common.TransactionID, + 0, + pMad->payload.REQ.LocalCommID, + pRemoteDgrm); + goto done; + } + + // first look for Remote Endpoint, this will catch duplicate and stale + // requests + pMapEntry = CM_MapGetCompare(&gCM->RemoteEndPointMap, (uintn)&pMad->payload.REQ, + CepReqRemoteEndPointCompare); + if (pMapEntry != CM_MapEnd(&gCM->RemoteEndPointMap)) + { + pCEP = PARENT_STRUCT(pMapEntry, CM_CEP_OBJECT, RemoteEndPointMapEntry); + bFoundRemoteEndPoint = TRUE; + } else { + // Look for the CEP object in the listen list + pMapEntry = CM_MapGetCompare(&gCM->ListenMap, (uintn)&pMad->payload.REQ, + CepReqAddrCompare); + if (pMapEntry != CM_MapEnd(&gCM->ListenMap)) + { + pCEP = PARENT_STRUCT(pMapEntry, CM_CEP_OBJECT, MapEntry); + } + } + if (! pCEP) + { + _DBG_WARN((" REQ dropped - no match found !\n", + _DBG_PTR(pMad), + pMad->payload.REQ.LocalCommID, + pMad->payload.REQ.ServiceID)); + + SendREJ(RC_INVALID_SID, + CM_REJECT_REQUEST, + pMad->common.TransactionID, + 0, + pMad->payload.REQ.LocalCommID, // The remote end's local comm id + pRemoteDgrm); + goto done; + } +#ifdef ICS_LOGGING + _DBG_INFO((" Matched REQ against LocalCommID, + pCEP->RemoteCommID, + pCEP->SID)); + + _DBG_INFO((" Matched REQ against " + "slid 0x%x sgid 0x%"PRIx64":0x%"PRIx64"\n", + _DBG_PTR(pCEP), + pCEP->PrimaryPath.LocalLID, + pCEP->PrimaryPath.LocalGID.Type.Global.SubnetPrefix, + pCEP->PrimaryPath.LocalGID.Type.Global.InterfaceID)); + + _DBG_INFO((" Matched REQ against " + "dlid 0x%x dgid 0x%"PRIx64":0x%"PRIx64">\n", + _DBG_PTR(pCEP), + pCEP->PrimaryPath.RemoteLID, + pCEP->PrimaryPath.RemoteGID.Type.Global.SubnetPrefix, + pCEP->PrimaryPath.RemoteGID.Type.Global.InterfaceID)); +#else + _DBG_INFO((" Matched REQ against \n", + _DBG_PTR(pCEP), + pCEP->LocalCommID, + pCEP->RemoteCommID, + pCEP->SID, + pCEP->PrimaryPath.LocalLID, + pCEP->PrimaryPath.LocalGID.Type.Global.SubnetPrefix, + pCEP->PrimaryPath.LocalGID.Type.Global.InterfaceID, + pCEP->PrimaryPath.RemoteLID, + pCEP->PrimaryPath.RemoteGID.Type.Global.SubnetPrefix, + pCEP->PrimaryPath.RemoteGID.Type.Global.InterfaceID)); +#endif + + if (! pCEP->bPeer) + { + Status = ProcessReqPassive(pCEP, pMad, pRemoteDgrm); + } else if (bFoundRemoteEndPoint) { + // Peer Connects could have multiple similar CEPs bound + // we must give priority to a CEP which has already + // started working on this connection, determined by checking + // remote End Point Address. + Status = ProcessReqPeer(pCEP, pMad, pRemoteDgrm, NULL); + } else { + // For fairness, we associate this inbound REQ with the + // earliest started REQ, hence minimizing the risk of timeouts. + // To find all possible CEPs, we scan to either side of the CEP + // we initially found as matching the bound address. + // While not discussed in the spec, for local loopback connections + // we make the association of a CEP to a remote end point in + // CMS_REQ_SENT state to ensure consistent active/passive roles. + // For remote connections we don't need this since CaGuid will + // cause consistent role assignments. + uint64 currtime_us = GetTimeStamp(); + uint64 max_elapsed = CmComputeElapsedTime(pCEP, currtime_us); + CM_MAP_ITEM* pMapEntry2 = NULL; + CM_CEP_OBJECT* pCEPReq = NULL; // local CEP which sent the REQ + ASSERT(pCEP->RemoteEndPoint.CaGUID == 0); + if (CepLocalEndPointMatchReq(pCEP, &pMad->payload.REQ)) + { + // the sender CEP, don't let it connect to itself + pCEPReq = pCEP; + pCEP = NULL; + } + for (pMapEntry2 = CM_MapPrev(pMapEntry); + pMapEntry2 != CM_MapEnd(&gCM->ListenMap); + pMapEntry2 = CM_MapPrev(pMapEntry2)) + { + CM_CEP_OBJECT* pCEP2; + pCEP2 = PARENT_STRUCT(pMapEntry2, CM_CEP_OBJECT, MapEntry); + if (CepReqAddrCompare((uintn)pCEP2, (uintn)&pMad->payload.REQ) == 0) + { + uint64 elapsed; + ASSERT(pCEP2->RemoteEndPoint.CaGUID == 0); + if (CepLocalEndPointMatchReq(pCEP2, &pMad->payload.REQ)) + { + // the sender CEP, don't let it connect to itself + pCEPReq = pCEP2; + continue; + } + elapsed = CmComputeElapsedTime(pCEP2, currtime_us); + if (pCEP == NULL || elapsed > max_elapsed) + { + max_elapsed = elapsed; + pCEP = pCEP2; + } + } else { + break; + } + } + for (pMapEntry2 = CM_MapNext(pMapEntry); + pMapEntry2 != CM_MapEnd(&gCM->ListenMap); + pMapEntry2 = CM_MapNext(pMapEntry2)) + { + CM_CEP_OBJECT* pCEP2; + pCEP2 = PARENT_STRUCT(pMapEntry2, CM_CEP_OBJECT, MapEntry); + if (CepReqAddrCompare((uintn)pCEP2, (uintn)&pMad->payload.REQ) == 0) + { + uint64 elapsed; + ASSERT(pCEP2->RemoteEndPoint.CaGUID == 0); + if (CepLocalEndPointMatchReq(pCEP2, &pMad->payload.REQ)) + { + // the sender CEP, don't let it connect to itself + pCEPReq = pCEP2; + continue; + } + elapsed = CmComputeElapsedTime(pCEP2, currtime_us); + if (pCEP == NULL || elapsed > max_elapsed) + { + max_elapsed = elapsed; + pCEP = pCEP2; + } + } else { + break; + } + } + if (pCEP != NULL) + Status = ProcessReqPeer(pCEP, pMad, pRemoteDgrm, pCEPReq); + else + Status = FNOT_FOUND; + } + + if (Status == FSUCCESS) + { + _DBG_INFO((" REQ processed successfully !\n", + _DBG_PTR(pMad), + pMad->payload.REQ.LocalCommID, + pMad->payload.REQ.ServiceID)); + } else if (Status == FNOT_FOUND) { + _DBG_WARNING((" REQ dropped - no match found !\n", + _DBG_PTR(pMad), + pMad->payload.REQ.LocalCommID, + pMad->payload.REQ.ServiceID)); + } else { + _DBG_WARNING((" REQ dropped - unable to process it! \n", + _DBG_PTR(pMad), + pMad->payload.REQ.LocalCommID, + pMad->payload.REQ.ServiceID, + _DBG_PTR(FSTATUS_MSG(Status)))); + } +done: + _DBG_FSTATUS_RETURN_LVL(_DBG_LVL_FUNC_TRACE,Status); + return Status; +} + +////////////////////////////////////////////////////////////////////////// +// ProcessReqPassive() +// +// This routine processes Req for a passive listening CEP +// +// +// RETURNS: +// +// FSUCCESS +// FERROR +// FINVALID_STATE +// FCM_INVALID_EVENT +// FINSUFFICIENT_RESOURCES +// +// IRQL: +// +// This routine is called at IRQL_DISPATCH_LEVEL. +// +FSTATUS +ProcessReqPassive( + IN CM_CEP_OBJECT* pCEP, + IN CM_MAD* pMad, + IN IBT_DGRM_ELEMENT* pRemoteDgrm + ) +{ + CM_CEP_OBJECT* pNewCEP=NULL; + CMM_MSG* pMsg = &pMad->payload; + FSTATUS Status=FSUCCESS; + uint32 worst_service_time_mult=0; + CM_REJECTION_CODE RejReason; + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, ProcessReqPassive); + + ASSERT(! pCEP->bPeer); + // any state other than CMS_LISTEN implies we have matched by + // Remote EndPoint rather than by bound address + switch (pCEP->State) + { + case CMS_IDLE: + ASSERT(0); + goto done; + break; + + // Listening + case CMS_LISTEN: + break; + + // Pending Connection + case CMS_REQ_RCVD: // passive + case CMS_MRA_REQ_SENT: // passive + // Connecting + case CMS_REQ_SENT: // active + case CMS_REP_WAIT: // active + case CMS_REP_SENT: // passive + case CMS_MRA_REP_RCVD: // passive + case CMS_REP_RCVD: // active + case CMS_MRA_REP_SENT: // active + // connected + case CMS_ESTABLISHED: + case CMS_LAP_SENT: + case CMS_MRA_LAP_SENT: + case CMS_LAP_RCVD: + case CMS_MRA_LAP_RCVD: + // disconnecting + case CMS_DREQ_SENT: + case CMS_DREQ_RCVD: + case CMS_SIM_DREQ_RCVD: + case CMS_TIMEWAIT: + if (pCEP->RemoteCommID == pMsg->REQ.LocalCommID) + { + // duplicate REQ + Status = ProcessReqDup(pCEP, pMad, pRemoteDgrm); + } else { + // A new request instance using an existing QPN/Port + Status = ProcessReqStale(pCEP, pMad, pRemoteDgrm); + } + goto done; + break; + + // SIDR + case CMS_REGISTERED: + case CMS_SIDR_REQ_SENT: + case CMS_SIDR_REQ_RCVD: + SendREJ(RC_INVALID_SID, CM_REJECT_REQUEST, pMad->common.TransactionID, 0, pMsg->REQ.LocalCommID, pRemoteDgrm); + goto done; + break; + } + + ASSERT(pCEP->State == CMS_LISTEN); + + // If we hit this backlog cnt, start rejecting the incoming connection + // since this listening endpoint maybe dead or very slow + if (pCEP->PendingCount >= (pCEP->ListenBackLog?pCEP->ListenBackLog:gCmParams.MaxBackLog)) + { + _DBG_ERROR((" Max pending count reached!!! \n", + _DBG_PTR(pCEP), pMsg->REQ.ServiceID, pCEP->LocalCommID, pMsg->REQ.LocalCommID, pCEP->PendingCount, pMsg->REQ.LocalCaGUID)); + + SendREJ(RC_NO_RESOURCES, CM_REJECT_REQUEST, pMad->common.TransactionID, 0, pMsg->REQ.LocalCommID, pRemoteDgrm); + Status = FOVERRUN; + goto done; + } + + // + // If we get here, this must be a new request. + // The processing below follows similarly to CreateCEP() and Connect(). + // + + // Create a new CEP object to represent this request and potentially a new connection + // TBD - we could require that TransportServiceType match that + // of listening CEP, for now we let server potentially listen for + // multiple service types on 1 CEP + pNewCEP = CreateCEP((CM_CEP_TYPE)pMsg->REQ.u3.s.TransportServiceType, NULL, NULL); + if (!pNewCEP) + { + _DBG_WARNING(("CreateCEP() failed!\n")); + + // Send a reject + SendREJ(RC_NO_RESOURCES, CM_REJECT_REQUEST, pMad->common.TransactionID, 0, pMsg->REQ.LocalCommID, pRemoteDgrm); + + Status = FINSUFFICIENT_RESOURCES; + goto done; + } + + (void)iba_get_ca_for_port(pRemoteDgrm->PortGuid, &pNewCEP->LocalEndPoint.CaGUID); + Status = SaveReqToPassiveCEP(pNewCEP, &pMsg->REQ, pNewCEP->LocalEndPoint.CaGUID, pRemoteDgrm->PortGuid, &RejReason); + if (Status != FSUCCESS) + { + _DBG_WARNING(("Gid/PKey validation() failed!\n")); + + // Send a reject + SendREJ(RejReason, CM_REJECT_REQUEST, pMad->common.TransactionID, 0, pMsg->REQ.LocalCommID, pRemoteDgrm); + DestroyCEP(pNewCEP); + goto done; + } + + // Move from IDLE to PENDING + CepAddToPendingList(pCEP, pNewCEP); + CepSetState(pNewCEP, CMS_REQ_RCVD); + + // Set the mode to passive since this is the server-side + pNewCEP->Mode = CM_MODE_PASSIVE; + + CmDgrmCopyAddrAndMad(pNewCEP->pDgrmElement, pMad, pRemoteDgrm); + + // Set various persistence info for this obj + AssignLocalCommID(pNewCEP); + pNewCEP->TransactionID = pMad->common.TransactionID; // active sets TID + pNewCEP->RemoteCommID = pMsg->REQ.LocalCommID; + + // Save the local endpoint addr based on the connect request. + // We will bind this object to the QPN when user Accept(). + pNewCEP->SID = pMsg->REQ.ServiceID; + pNewCEP->LocalEndPoint.EECN = pMsg->REQ.u3.s.RemoteEECN; + + // Save the remote endpoint addr based on the connect request + pNewCEP->RemoteEndPoint.CaGUID = pMsg->REQ.LocalCaGUID; + pNewCEP->RemoteEndPoint.QPN = pMsg->REQ.u1.s.LocalQPN; + pNewCEP->RemoteEndPoint.EECN = pMsg->REQ.u2.s.LocalEECN; + + // RemoteEndPoint is unique + CM_MapInsert(&gCM->RemoteEndPointMap, (uintn)pNewCEP, &pNewCEP->RemoteEndPointMapEntry, "REMOTE_END_POINT_LIST", pNewCEP); + + // inherit turnaround time for use in ServiceTime for MRA retries + // will update again when CmAccept to pick up any adjusted values + pNewCEP->turnaround_time_us = pCEP->turnaround_time_us; + + // No user callback info + pNewCEP->pfnUserCallback = NULL; + pNewCEP->UserContext = NULL; + + // compare RemoteCMTimeout to our Worst expected turnaround + // if necessary, output an MRA to be safe + worst_service_time_mult = CepWorstServiceTimeMult(pNewCEP); + if (pMsg->REQ.u3.s.RemoteCMTimeout < worst_service_time_mult) { + SendMRA(CM_MRA_REQUEST, worst_service_time_mult, + pNewCEP->TransactionID, pNewCEP->LocalCommID, + pNewCEP->RemoteCommID, pRemoteDgrm); + CepSetState(pNewCEP, CMS_MRA_REQ_SENT); + } + + CmStartElapsedTime(pNewCEP); // for turnaround computation + // Signal the listening obj if this is the first on the pending list + // otherwise, accept() or reject() will handle this + if (pCEP->PendingCount == 1) + { + SetNotification(pCEP, CME_RCVD_REQ); //EventSet(pCEP, CME_RCVD_REQ); + } + // At this point, the user accept(), reject() or a timeout occurs + +done: + _DBG_FSTATUS_RETURN_LVL(_DBG_LVL_FUNC_TRACE,Status); + return Status; + +} // ProcessReqPassive() + +////////////////////////////////////////////////////////////////////////// +// ProcessReqPeer() +// +// Process inbound REQ for a Peer Connect CEP +// +// +// RETURNS: +// +// FSUCCESS +// FERROR +// FINVALID_STATE +// FCM_INVALID_EVENT +// +// IRQL: +// +// This routine is called at IRQL_DISPATCH_LEVEL. +// +FSTATUS +ProcessReqPeer( + IN CM_CEP_OBJECT* pCEP, + IN CM_MAD* pMad, + IN IBT_DGRM_ELEMENT* pRemoteDgrm, + IN CM_CEP_OBJECT* pCEPReq + ) +{ + CMM_MSG* pMsg = &pMad->payload; + FSTATUS Status=FSUCCESS; + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, ProcessReqPeer); + + if (pCEP->State != CMS_REQ_SENT) + { + // we must have matched on Remote Address in ProcessReq + ASSERT(CepRemoteEndPointMatchReq(pCEP, &pMsg->REQ)); + if (pCEP->RemoteCommID == pMsg->REQ.LocalCommID) + { + Status = ProcessReqDup(pCEP, pMad, pRemoteDgrm); + } else { + // A new request instance using an existing QPN/Port ? + Status = ProcessReqStale(pCEP, pMad, pRemoteDgrm); + } + goto done; + } + + // + // New peer connect request - determine active or passive role + // + _DBG_INFO((" *** New peer request *** .\n", + _DBG_PTR(pCEP), pCEP->LocalCommID, pMsg->REQ.LocalCommID)); + + // There should NOT be anything on the PENDING list + if (!DListIsEmpty(&pCEP->PendingList)) + { + Status = FERROR; + goto done; + } + + // Set this end to active or passive + if (pCEP->LocalEndPoint.CaGUID < pMsg->REQ.LocalCaGUID) + { + // This endpoint takes the passive role + pCEP->Mode = CM_MODE_PASSIVE; + } else if (pCEP->LocalEndPoint.CaGUID > pMsg->REQ.LocalCaGUID) { + // This endpoint takes the active role + pCEP->Mode = CM_MODE_ACTIVE; + } else { + if (pCEP->LocalEndPoint.QPN < pMsg->REQ.u1.s.LocalQPN) + { + // This endpoint takes the passive role + pCEP->Mode = CM_MODE_PASSIVE; + } else if (pCEP->LocalEndPoint.QPN > pMsg->REQ.u1.s.LocalQPN) { + // This endpoint takes the active role + pCEP->Mode = CM_MODE_ACTIVE; + } else { + Status = FERROR; + goto done; + } + } + + // active sets paths and timeouts + // validate GID/PKey in REQ + if (pCEP->Mode == CM_MODE_PASSIVE) + { + CM_REJECTION_CODE RejReason; + + Status = SaveReqToPassiveCEP(pCEP, &pMsg->REQ, pCEP->LocalEndPoint.CaGUID, pRemoteDgrm->PortGuid, &RejReason); + if (Status != FSUCCESS) + { + _DBG_WARNING(("Gid/PKey validation() failed!\n")); + + // Send a reject + SendREJ(RejReason, CM_REJECT_REQUEST, pMad->common.TransactionID, 0, pMsg->REQ.LocalCommID, pRemoteDgrm); + // restore CEP, still waiting for valid Peer REQ + pCEP->Mode = CM_MODE_ACTIVE; + goto done; + } + } + + // for a local loopback connection we must ensure consistent + // interpretation of the the roles and consistent association + // of the end points, so we set the Remote EndPoint for both CEPs + if (pCEPReq != NULL) + { + // RemoteEndPoints must be unique since we know the local's + // are unique and we are a loopback + ASSERT(pCEP != pCEPReq); + if (pCEPReq->RemoteEndPoint.CaGUID == 0) + { + ASSERT(pCEPReq->State == CMS_REQ_SENT || pCEPReq->State == CMS_REP_WAIT); + CM_MapRemoveEntry(&gCM->ListenMap, &pCEPReq->MapEntry, LISTEN_LIST, pCEPReq); + pCEPReq->RemoteEndPoint.CaGUID = pCEP->LocalEndPoint.CaGUID; + pCEPReq->RemoteEndPoint.QPN = pCEP->LocalEndPoint.QPN; + pCEPReq->RemoteEndPoint.EECN = pCEP->LocalEndPoint.EECN; + CM_MapInsert(&gCM->RemoteEndPointMap, (uintn)pCEPReq, &pCEPReq->RemoteEndPointMapEntry, "REMOTE_END_POINT_LIST", pCEPReq); + } + + if (pCEP->RemoteEndPoint.CaGUID == 0) + { + CM_MapRemoveEntry(&gCM->ListenMap, &pCEP->MapEntry, LISTEN_LIST, pCEP); + pCEP->RemoteEndPoint.CaGUID = pMsg->REQ.LocalCaGUID; + pCEP->RemoteEndPoint.QPN = pMsg->REQ.u1.s.LocalQPN; + pCEP->RemoteEndPoint.EECN = pMsg->REQ.u2.s.LocalEECN; + CM_MapInsert(&gCM->RemoteEndPointMap, (uintn)pCEP, &pCEP->RemoteEndPointMapEntry, "REMOTE_END_POINT_LIST", pCEP); + } + } + + if (pCEP->Mode == CM_MODE_PASSIVE) + { + uint32 worst_service_time_mult; + + _DBG_INFO((" *** This peer endpoint takes the passive role *** .\n", + _DBG_PTR(pCEP), pCEP->LocalCommID, pMsg->REQ.LocalCommID)); + + pCEP->TransactionID = pMad->common.TransactionID; // active sets TID + + // Cancel the timer on REQ + CmTimerStop(pCEP, REQ_TIMER); + + CepAddToPendingList(pCEP, pCEP); // Peer is linked to self + CepSetState(pCEP, CMS_REQ_RCVD); + + // REQ --> + // REQ <-- + Status = PrepareCepDgrm(pCEP); + if (Status != FSUCCESS) + goto fail; + + // Save the request msg + CmDgrmCopyAddrAndMad(pCEP->pDgrmElement, pMad, pRemoteDgrm); + + // Save the rest of the request info to this endpoint + pCEP->RemoteCommID = pMsg->REQ.LocalCommID; + if (pCEP->RemoteEndPoint.CaGUID == 0) + { + // we looked up by RemoteEndPoint in ProcessReq + // and to get here we must not have found it as a dup + CM_MapRemoveEntry(&gCM->ListenMap, &pCEP->MapEntry, LISTEN_LIST, pCEP); + pCEP->RemoteEndPoint.CaGUID = pMsg->REQ.LocalCaGUID; + pCEP->RemoteEndPoint.QPN = pMsg->REQ.u1.s.LocalQPN; + pCEP->RemoteEndPoint.EECN = pMsg->REQ.u2.s.LocalEECN; + CM_MapInsert(&gCM->RemoteEndPointMap, (uintn)pCEP, &pCEP->RemoteEndPointMapEntry, "REMOTE_END_POINT_LIST", pCEP); + } + + // compare RemoteCMTimeout to our typical turnaround + // if necessary, output an MRA to be safe + worst_service_time_mult = CepWorstServiceTimeMult(pCEP); + if (pMsg->REQ.u3.s.RemoteCMTimeout < worst_service_time_mult) { + SendMRA(CM_MRA_REQUEST, worst_service_time_mult, + pCEP->TransactionID, pCEP->LocalCommID, + pCEP->RemoteCommID, pRemoteDgrm); + CepSetState(pCEP, CMS_MRA_REQ_SENT); + } + + CmStartElapsedTime(pCEP); // for turnaround computation + // Update the event flag of the listening obj + SetNotification(pCEP, CME_RCVD_REQ);//EventSet(pCEP, CME_RCVD_REQ); + + // At this point , the user accept(), reject() or a timeout occurs. + } else { + _DBG_INFO((" *** This peer endpoint takes the active role *** ,\n", + _DBG_PTR(pCEP), pCEP->LocalCommID, pMsg->REQ.LocalCommID)); + + // When the active peer receives a REQ, we resend the REQ to the + // passive peer to avoid waiting for the timeout to resend the REQ. + // This reduces the connection establishment time when we bring up + // the active peer then passive peer. + CmTimerStop(pCEP, REQ_TIMER); + ResendREQ(pCEP); + } + +done: + _DBG_FSTATUS_RETURN_LVL(_DBG_LVL_FUNC_TRACE,Status); + return Status; + +fail: + _DBG_WARNING((" REQ dropped - unable to process it! \n", + _DBG_PTR(pMad), pCEP->LocalCommID, pMsg->REQ.LocalCommID, + _DBG_PTR(FSTATUS_MSG(Status)))); + _DBG_FSTATUS_RETURN_LVL(_DBG_LVL_FUNC_TRACE,Status); + return Status; + +} // ProcessReqPeer() + +// Save REQ Path and timers into CEP +FSTATUS +SaveReqToPassiveCEP( + IN CM_CEP_OBJECT* pCEP, + IN CMM_REQ* pREQ, + IN EUI64 CaGUID, + IN EUI64 PortGuid, // port which received REQ + OUT CM_REJECTION_CODE *RejReason // only returned on failure + ) +{ + FSTATUS Status; + IB_PORT_ATTRIBUTES *pPortAttr = NULL; + EUI64 PrimaryLocalPortGuid; + uint8 PrimaryLocalGidIndex; + uint8 PrimaryLocalPathBits; + uint16 PrimaryPkeyIndex = 0; + EUI64 AlternateLocalPortGuid = 0; + uint8 AlternateLocalGidIndex = 0; + uint8 AlternateLocalPathBits = 0; + uint16 AlternatePkeyIndex = 0; + IB_CA_ATTRIBUTES *pCaAttr = NULL; + + // first validate REQ, don't change CEP til sure its valid + Status = iba_find_ca_gid2(&pREQ->PrimaryRemoteGID, CaGUID, + &PrimaryLocalPortGuid, &PrimaryLocalGidIndex, &pPortAttr, + &pCaAttr); + if (Status != FSUCCESS && gCmParams.DisableValidation) + { + pCaAttr = (IB_CA_ATTRIBUTES*)MemoryAllocate(sizeof(*pCaAttr), FALSE, CM_MEM_TAG); + Status = iba_query_port_by_guid_alloc(PortGuid, &pPortAttr); + if (pCaAttr == NULL || Status != FSUCCESS) { + *RejReason = RC_NO_RESOURCES; + Status = FINSUFFICIENT_MEMORY; + goto done; + } + pCaAttr->PortAttributesListSize = 0; + pCaAttr->PortAttributesList = NULL; + Status = iba_query_ca_by_guid(CaGUID, pCaAttr); + if (Status == FSUCCESS) + { + PrimaryLocalPortGuid = PortGuid; + PrimaryLocalGidIndex = 0; + } + } + if (Status != FSUCCESS || PrimaryLocalPortGuid != PortGuid) + { + *RejReason = RC_PRIMARY_DGID_REJ; + Status = FINVALID_PARAMETER; + goto done; + } + if (! ValidatePKey(pPortAttr, pREQ->PartitionKey, &PrimaryPkeyIndex)) + { + if (! gCmParams.DisableValidation) + { + *RejReason = RC_UNSUPPORTED_REQ; // TBD + Status = FINVALID_PARAMETER; + goto done; + } + Status = FSUCCESS; + PrimaryPkeyIndex = 0; // default + } + if (pPortAttr) + { + PrimaryLocalPathBits = LidToPathBits(pREQ->PrimaryRemoteLID, pPortAttr->Address.LMC); + MemoryDeallocate(pPortAttr); + } else { + PrimaryLocalPathBits = 0; + } + pPortAttr = NULL; + if (pREQ->AlternateRemoteLID != 0) + { + Status = iba_find_ca_gid(&pREQ->AlternateRemoteGID, CaGUID, + &AlternateLocalPortGuid, &AlternateLocalGidIndex, + &pPortAttr, NULL); + // DisableValidation does not apply, we need to know + // the alternate port Guid so we can failover the CM messages + // we cannot reliably go off the RemoteLID because ports + // could have same LID if they are on different fabrics + if (Status != FSUCCESS) + { + *RejReason = RC_ALTERNATE_DGID; + Status = FINVALID_PARAMETER; + goto done; + } + if (! ValidatePKey(pPortAttr, pREQ->PartitionKey, &AlternatePkeyIndex)) + { + if (! gCmParams.DisableValidation) + { + *RejReason = RC_UNSUPPORTED_REQ; // TBD + Status = FINVALID_PARAMETER; + goto done; + } + AlternatePkeyIndex = 0; // default + Status = FSUCCESS; + } + if (pPortAttr) + { + AlternateLocalPathBits = LidToPathBits(pREQ->AlternateRemoteLID, pPortAttr->Address.LMC); + MemoryDeallocate(pPortAttr); + } else { + AlternateLocalPathBits = 0; + } + pPortAttr = NULL; + } + + // Primary Path + pCEP->PrimaryPath.LocalPortGuid = PrimaryLocalPortGuid; + pCEP->PrimaryPath.LocalGID = pREQ->PrimaryRemoteGID; + pCEP->PrimaryPath.RemoteGID = pREQ->PrimaryLocalGID; + pCEP->PrimaryPath.LocalLID = pREQ->PrimaryRemoteLID; + pCEP->PrimaryPath.RemoteLID = pREQ->PrimaryLocalLID; + pCEP->PrimaryPath.FlowLabel = pREQ->u5.s.PrimaryFlowLabel; + pCEP->PrimaryPath.StaticRate = pREQ->u5.s.PrimaryPacketRate; + pCEP->PrimaryPath.TClass = pREQ->PrimaryTrafficClass; + pCEP->PrimaryPath.SL = pREQ->PrimarySL; + pCEP->PrimaryPath.bSubnetLocal = pREQ->PrimarySubnetLocal; + pCEP->PrimaryPath.AckTimeout = pREQ->PrimaryLocalAckTimeout; + pCEP->PrimaryPath.LocalAckTimeout = pREQ->PrimaryLocalAckTimeout; + pCEP->PrimaryPath.HopLimit = pREQ->PrimaryHopLimit; + pCEP->PrimaryPath.LocalGidIndex = PrimaryLocalGidIndex; + pCEP->PrimaryPath.LocalPathBits = PrimaryLocalPathBits; + pCEP->PrimaryPath.PkeyIndex = PrimaryPkeyIndex; + + // Alternate Path + pCEP->AlternatePath.LocalPortGuid = AlternateLocalPortGuid; + pCEP->AlternatePath.LocalGID = pREQ->AlternateRemoteGID; + pCEP->AlternatePath.RemoteGID = pREQ->AlternateLocalGID; + pCEP->AlternatePath.LocalLID = pREQ->AlternateRemoteLID; + pCEP->AlternatePath.RemoteLID = pREQ->AlternateLocalLID; + pCEP->AlternatePath.FlowLabel = pREQ->u6.s.AlternateFlowLabel; + pCEP->AlternatePath.StaticRate = pREQ->u6.s.AlternatePacketRate; + pCEP->AlternatePath.TClass = pREQ->AlternateTrafficClass; + pCEP->AlternatePath.SL = pREQ->AlternateSL; + pCEP->AlternatePath.bSubnetLocal = pREQ->AlternateSubnetLocal; + pCEP->AlternatePath.AckTimeout = pREQ->AlternateLocalAckTimeout; + pCEP->AlternatePath.LocalAckTimeout = pREQ->AlternateLocalAckTimeout; + pCEP->AlternatePath.HopLimit = pREQ->AlternateHopLimit; + pCEP->AlternatePath.LocalGidIndex = AlternateLocalGidIndex; + pCEP->AlternatePath.LocalPathBits = AlternateLocalPathBits; + pCEP->AlternatePath.PkeyIndex = AlternatePkeyIndex; + + // negotiate down before we present REQ to listener + if (pREQ->u3.s.TransportServiceType == CM_RC_TYPE) { + pCEP->LocalInitiatorDepth = MIN(pREQ->u1.s.OfferedResponderResources, + pCaAttr->MaxQPInitiatorDepth); + pCEP->LocalResponderResources = MIN(pREQ->u2.s.OfferedInitiatorDepth, + pCaAttr->MaxQPResponderResources); + } else if (pREQ->u3.s.TransportServiceType == CM_RD_TYPE) { + pCEP->LocalInitiatorDepth = MIN(pREQ->u1.s.OfferedResponderResources, + pCaAttr->MaxEECInitiatorDepth); + pCEP->LocalResponderResources = MIN(pREQ->u2.s.OfferedInitiatorDepth, + pCaAttr->MaxEECResponderResources); + } else { + pCEP->LocalInitiatorDepth = 0; + pCEP->LocalResponderResources = 0; + } + // Ack timeout is calculated as round-trip + // This computation will be rounded up by CA Ack Delay/2 + if (pREQ->PrimaryLocalAckTimeout >= 1) + { + // -1 for a log2 value is the same as /2 + pCEP->PktLifeTime = (pREQ->PrimaryLocalAckTimeout-1); + } else { + pCEP->PktLifeTime = 0; + } + + pCEP->TargetAckDelay = pCaAttr->LocalCaAckDelay;// application could round up + // save parameters to help us later + pCEP->LocalRnrRetryCount = pREQ->RnRRetryCount; + pCEP->LocalRetryCount = pREQ->u4.s.RetryCount; + pCEP->LocalSendPSN = pREQ->u4.s.StartingPSN; + + // timewait value. This will be updated when we send the REP + // If we get a REJ/RC_STALE_CONN, we will use this value for our Timewait + pCEP->Timewait = pREQ->PrimaryLocalAckTimeout; + + // If we are unable to process the REQ and send the REP before this timeout, + // we will send an MRA to prevent the other end from resending the REQ. + pCEP->RemoteCMTimeout = pREQ->u3.s.RemoteCMTimeout; + + // This timeout is used to set the RTU timeout when REP is sent out. + // If the time expires i.e. we did not received the RTU, we need to resend + // the REP. + pCEP->LocalCMTimeout = pREQ->u4.s.LocalCMTimeout; + + // How many times to retry the REP. We put a limit of CM_REP_RETRY for the server-side + // because the server should not be tied down doing retries. + pCEP->MaxCMRetries = (pREQ->MaxCMRetries > gCmParams.MaxRepRetry)?(gCmParams.MaxRepRetry):(pREQ->MaxCMRetries); + + pCEP->Mtu = pREQ->PathMTU; + pCEP->PartitionKey = pREQ->PartitionKey; +done: + if (pCaAttr) + MemoryDeallocate(pCaAttr); + if (pPortAttr) + MemoryDeallocate(pPortAttr); + return Status; +} + +// Process a Duplicate REQ +FSTATUS +ProcessReqDup( + IN CM_CEP_OBJECT* pCEP, + IN CM_MAD* pMad, + IN IBT_DGRM_ELEMENT* pRemoteDgrm + ) +{ + CMM_MSG* pMsg = &pMad->payload; + uint32 worst_service_time_mult; + uint64 new_turnaround; + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, ProcessReqDup); + + _DBG_WARNING((" Duplicate REQ detected in %s !\n", + _DBG_PTR(pCEP), _DBG_PTR(CmGetStateString(pCEP->State)), + pCEP->LocalCommID, pMsg->REQ.LocalCommID)); + + // TBD - CMS_REQ_RCVD - could MRA it here, instead we let CmAccept REP it + switch (pCEP->State) + { + case CMS_REP_SENT: + CmTimerStop(pCEP, REP_TIMER); + ResendREP(pCEP); + break; + case CMS_MRA_REQ_SENT: + // Update the turnaround time + new_turnaround = UpdateTurnaroundTime(gCM->turnaround_time_us, 2*CmGetElapsedTime(pCEP)); + if (new_turnaround > gCM->turnaround_time_us) + { + gCM->turnaround_time_us = new_turnaround; + } + worst_service_time_mult = CepWorstServiceTimeMult(pCEP); + SendMRA(CM_MRA_REQUEST, + MAX(worst_service_time_mult, pMsg->REQ.u3.s.RemoteCMTimeout), + pCEP->TransactionID, pCEP->LocalCommID, + pCEP->RemoteCommID, pRemoteDgrm); + break; + case CMS_REQ_RCVD: + new_turnaround = UpdateTurnaroundTime(gCM->turnaround_time_us, 2*CmGetElapsedTime(pCEP)); + if (new_turnaround > gCM->turnaround_time_us) + { + gCM->turnaround_time_us = new_turnaround; + } + worst_service_time_mult = CepWorstServiceTimeMult(pCEP); + if (pMsg->REQ.u3.s.RemoteCMTimeout < worst_service_time_mult) { + SendMRA(CM_MRA_REQUEST, worst_service_time_mult, + pCEP->TransactionID, pCEP->LocalCommID, + pCEP->RemoteCommID, pRemoteDgrm); + CepSetState(pCEP, CMS_MRA_REQ_SENT); + } + break; + default: + break; + } + + _DBG_FSTATUS_RETURN_LVL(_DBG_LVL_FUNC_TRACE,FSUCCESS); + return FSUCCESS; +} + +// Process a Stale REQ +FSTATUS +ProcessReqStale( + IN CM_CEP_OBJECT* pCEP, + IN CM_MAD* pMad, + IN IBT_DGRM_ELEMENT* pRemoteDgrm + ) +{ + FSTATUS Status = FSUCCESS; + CMM_MSG* pMsg = &pMad->payload; + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, ProcessReqStale); + + // A new request instance using an existing QPN/Port + _DBG_WARNING((" Stale REQ detected, send reject < lcid 0x%x rcid 0x%x %s>!\n", + _DBG_PTR(pCEP), pCEP->LocalCommID, pMsg->REQ.LocalCommID, + _DBG_PTR(CmGetStateString(pCEP->State)))); + + // TBD - should send REJ for all states? + switch (pCEP->State) + { + case CMS_REQ_RCVD: // passive + case CMS_MRA_REQ_SENT: // passive + // Connecting + case CMS_REQ_SENT: // active + case CMS_REP_WAIT: // active + case CMS_REP_SENT: // passive + case CMS_MRA_REP_RCVD: // passive + case CMS_REP_RCVD: // active + case CMS_MRA_REP_SENT: // active + case CMS_ESTABLISHED: // active + case CMS_LAP_SENT: // active + case CMS_MRA_LAP_RCVD: // active + case CMS_LAP_RCVD: // passive + case CMS_MRA_LAP_SENT: // passive + // Send a reject + SendREJ(RC_STALE_CONN, CM_REJECT_REQUEST, pMad->common.TransactionID, 0, pMsg->REQ.LocalCommID, pRemoteDgrm); + break; + default: + break; + } + + // TBD Disconnect local connection for other states? + switch (pCEP->State) + { + case CMS_ESTABLISHED: // active + case CMS_LAP_SENT: // active + case CMS_MRA_LAP_RCVD: // active + case CMS_LAP_RCVD: // passive + case CMS_MRA_LAP_SENT: // passive + // Additionally, we must send a DREQ to disconnect the previous + // connection instance at the remote endpoint. + SendDREQ(pCEP->RemoteEndPoint.QPN, pMad->common.TransactionID, + pCEP->LocalCommID, pCEP->RemoteCommID, pRemoteDgrm); + + // Notify local user existing connection is disconnected + // Fake out the new REQ as a DREQ for the connection + MemoryClear(pMad, sizeof(CM_MAD)); + pMad->payload.DREQ.LocalCommID = pCEP->RemoteCommID; + pMad->payload.DREQ.RemoteCommID = pCEP->LocalCommID; + pMad->payload.DREQ.u.s.RemoteQPNorEECN = pCEP->LocalEndPoint.QPN; + Status = ProcessDreqCep(pCEP, pMad, pRemoteDgrm); +// TBD we should provide a DREQ to our local app, but be in a DREQ_SENT state +// waiting for the DREP and retry the DREQ until we timeout or get a DREP + break; + default: + break; + } + _DBG_FSTATUS_RETURN_LVL(_DBG_LVL_FUNC_TRACE,Status); + return Status; +} + +////////////////////////////////////////////////////////////////////////// +// ProcessRep() +// process an inbound REP +// +// +// INPUTS: +// +// +// +// OUTPUTS: +// +// None. +// +// RETURNS: +// +// +// IRQL: +// +// This routine is called at IRQL_DISPATCH_LEVEL. With ListLock held +// + +FSTATUS +ProcessRep( + CM_MAD* pMad, + IBT_DGRM_ELEMENT* pRemoteDgrm + ) +{ + CM_CEP_OBJECT* pCEP=NULL; + FSTATUS Status=FSUCCESS; + uint32 worst_service_time_mult; + uint64 new_turnaround; + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, ProcessRep); + + _DBG_INFO((" REP received \n", + _DBG_PTR(pMad), + pMad->payload.REP.LocalCommID, + pMad->payload.REP.RemoteCommID)); + + pCEP = FindLocalCommID(pMad->payload.REP.RemoteCommID); + if (! pCEP) { + goto nomatch; + } + // TODO: Check the mad's addr with our endpoint's addr in addition to the comm ID, also validate RemoteCommID + // these should generate assorted REJ conditions if it doesn't match + switch (pCEP->State) + { + case CMS_REQ_SENT: + case CMS_REP_WAIT: + // Received the reply to our connect request + // notify user so they can CmAccept to cause an RTU + Status = PrepareCepDgrm(pCEP); + if (Status != FSUCCESS) + goto fail; + + if (pCEP->RemoteEndPoint.CaGUID == 0) + { + pCEP->RemoteEndPoint.CaGUID = pMad->payload.REP.LocalCaGUID; + pCEP->RemoteEndPoint.QPN = pMad->payload.REP.u1.s.LocalQPN; + pCEP->RemoteEndPoint.EECN = pMad->payload.REP.u2.s.LocalEECN; + + if (! CM_MapTryInsert(&gCM->RemoteEndPointMap, (uintn)pCEP, &pCEP->RemoteEndPointMapEntry, "REMOTE_END_POINT_LIST", pCEP)) + { + // unexpected remote end point, the new REP is stale + pCEP->RemoteEndPoint.CaGUID = 0; + pCEP->RemoteEndPoint.QPN = 0; + pCEP->RemoteEndPoint.EECN = 0; + goto stale; + } + if (pCEP->bPeer) + { + CM_MapRemoveEntry(&gCM->ListenMap, &pCEP->MapEntry, LISTEN_LIST, pCEP); + } + } else { + ASSERT(pCEP->bPeer); + // unexpected remote end point, the new REP is stale + if (! CepRemoteEndPointMatchRep(pCEP, &pMad->payload.REP)) + { + goto stale; + } + } + + CmTimerStop(pCEP, REQ_TIMER); // Cancel the timer on REQ + pCEP->RemoteCommID = pMad->payload.REP.LocalCommID; + if (pCEP->AlternatePath.LocalLID != 0) + { + if (pMad->payload.REP.FailoverAccepted != CM_REP_FO_ACCEPTED) + { + MemoryClear(&pCEP->AlternatePath, + sizeof(pCEP->AlternatePath)); + } + pCEP->bFailoverSupported &= IsFailoverSupported( + pMad->payload.REP.FailoverAccepted); + } + + // save arbitrated RDMA Read parameters + // previously we saved the values we sent, only allow decreases + // BUGBUG, technically we should REJ the REP if values are > + if (pMad->payload.REP.ArbInitiatorDepth < pCEP->LocalResponderResources) + pCEP->LocalResponderResources = pMad->payload.REP.ArbInitiatorDepth; + if (pMad->payload.REP.ArbResponderResources < pCEP->LocalInitiatorDepth) + pCEP->LocalInitiatorDepth = pMad->payload.REP.ArbResponderResources; + + // previously we estimated TargetAckDelay as LocalCaAckDelay + // now update CM timers to account for real TargetAckDelay + // some applications don't set TargetAckDelay properly + // so be conservative and only increase timeouts + if (pMad->payload.REP.TargetAckDelay > pCEP->TargetAckDelay) + { + uint64 delta = TimeoutMultToTimeInUsec(pMad->payload.REP.TargetAckDelay) + - TimeoutMultToTimeInUsec(pCEP->TargetAckDelay); + // technically LocalCMTimeout and RemoteCMTimeout do not + // have a target ack delay component, but to be safe we + // increase the timeout since CA processing overhead + // will be part of the service time + pCEP->LocalCMTimeout = TimeoutTimeToMult( + TimeoutMultToTimeInUsec(pCEP->LocalCMTimeout) + + delta); + pCEP->RemoteCMTimeout = TimeoutTimeToMult( + TimeoutMultToTimeInUsec(pCEP->RemoteCMTimeout) + + delta); + pCEP->Timewait = TimeoutTimeToMult( + TimeoutMultToTimeInUsec(pCEP->Timewait) + + delta); + pCEP->TargetAckDelay = pMad->payload.REP.TargetAckDelay; + } + + // save parameters for later + pCEP->LocalSendPSN = pMad->payload.REP.u3.s.StartingPSN; + pCEP->LocalRnrRetryCount = pMad->payload.REP.RnRRetryCount; + // when we sent REQ we saved PktLifeTime in LocalAckTimeout + // now factor in TargetAckDelay to get real timeout + pCEP->PrimaryPath.LocalAckTimeout = ComputeAckTimeout( + pCEP->PrimaryPath.LocalAckTimeout, + pCEP->TargetAckDelay); + if (pCEP->AlternatePath.LocalLID != 0) + { + pCEP->AlternatePath.LocalAckTimeout = ComputeAckTimeout( + pCEP->AlternatePath.LocalAckTimeout, + pCEP->TargetAckDelay); + } + + // Save the reply msg + CmDgrmCopyAddrAndMad(pCEP->pDgrmElement, pMad, pRemoteDgrm); + + CepSetState(pCEP, CMS_REP_RCVD); + + CmStartElapsedTime(pCEP); // for turnaround computation + + // Update the event flag + SetNotification(pCEP, CME_RCVD_REP); //EventSet(pCEP, CME_RCVD_REP); + break; + case CMS_REQ_RCVD: + case CMS_MRA_REQ_SENT: + case CMS_REP_SENT: + case CMS_MRA_REP_RCVD: + goto discard; + break; + case CMS_MRA_REP_SENT: + new_turnaround = UpdateTurnaroundTime(gCM->turnaround_time_us, 2*CmGetElapsedTime(pCEP)); + if (new_turnaround > gCM->turnaround_time_us) + { + gCM->turnaround_time_us = new_turnaround; + } + worst_service_time_mult = CepWorstServiceTimeMult(pCEP); + SendMRA(CM_MRA_REPLY, + MAX(worst_service_time_mult, pCEP->RemoteCMTimeout), + pCEP->TransactionID, pCEP->LocalCommID, + pCEP->RemoteCommID, pRemoteDgrm); + break; + case CMS_REP_RCVD: + new_turnaround = UpdateTurnaroundTime(gCM->turnaround_time_us, 2*CmGetElapsedTime(pCEP)); + if (new_turnaround > gCM->turnaround_time_us) + { + gCM->turnaround_time_us = new_turnaround; + } + worst_service_time_mult = CepWorstServiceTimeMult(pCEP); + // just in case remote end miscomputed RemoteCMTimeout + // we always send MRA in this case + SendMRA(CM_MRA_REPLY, + MAX(worst_service_time_mult, pCEP->RemoteCMTimeout), + pCEP->TransactionID, pCEP->LocalCommID, + pCEP->RemoteCommID, pRemoteDgrm); + CepSetState(pCEP, CMS_MRA_REP_SENT); + break; + case CMS_ESTABLISHED: + case CMS_LAP_SENT: + case CMS_MRA_LAP_RCVD: + // Resend the RTU + if (pCEP->bLapSent) + { + // pCEP->pDgrmElement is not RTU, send an empty RTU + SendRTU(pCEP->TransactionID, pCEP->LocalCommID, + pCEP->RemoteCommID, pRemoteDgrm); + break; + } + // Dgrm will be an RTU + // If dgrm is still in use (i.e. send pending), skip the retry + // because pDgrmElement is still on SendQ + if (!CmDgrmIsInUse(pCEP->pDgrmElement)) + { + ASSERT(GsiDgrmGetSendMad(pCEP->pDgrmElement)->common.AttributeID == MCLASS_ATTRIB_ID_RTU); + _DBG_INFO((" RTU resend \n", _DBG_PTR(pCEP), pCEP->LocalCommID, pCEP->RemoteCommID)); + Status = CmDgrmSend(pCEP->pDgrmElement); + if (FSUCCESS != Status) + { + // fall through and let timer retry the send later + _DBG_WARN((" DgrmSend() failed for RTU!!! <%s>\n", + _DBG_PTR(pCEP), _DBG_PTR(FSTATUS_MSG(Status)))); + Status = FSUCCESS; + } else { + AtomicIncrementVoid(&gCM->Sent.Rtu); + } + } else { + _DBG_WARNING((" Unable to resend RTU \n", _DBG_PTR(pCEP), pCEP->LocalCommID, pCEP->RemoteCommID)); + } + break; + case CMS_LAP_RCVD: + case CMS_MRA_LAP_SENT: + case CMS_DREQ_SENT: + case CMS_DREQ_RCVD: + goto discard; + break; + default: // timewait, SIM_DREQ_RCVD, SIDR, idle, listen + // invalid LocalCommID + goto nomatch; + break; + } + + _DBG_INFO((" REP processed successfully !\n", + _DBG_PTR(pMad), pMad->payload.REP.LocalCommID, + pMad->payload.REP.RemoteCommID)); + _DBG_FSTATUS_RETURN_LVL(_DBG_LVL_FUNC_TRACE,Status); + return Status; + +nomatch: + // REP did not match an active connection + _DBG_WARNING((" REP Rejected - no match found !\n", + _DBG_PTR(pMad), pMad->payload.REP.LocalCommID, + pMad->payload.REP.RemoteCommID)); + + SendREJ(RC_INVALID_COMMID, + CM_REJECT_REPLY, + pMad->common.TransactionID, + 0, + pMad->payload.REP.LocalCommID, // The remote end's local comm id + pRemoteDgrm); + + _DBG_FSTATUS_RETURN_LVL(_DBG_LVL_FUNC_TRACE,Status); + return Status; + +fail: + _DBG_WARNING((" REP dropped - unable to process it! \n", + _DBG_PTR(pMad), pMad->payload.REP.LocalCommID, + pMad->payload.REP.RemoteCommID, _DBG_PTR(FSTATUS_MSG(Status)))); + _DBG_FSTATUS_RETURN_LVL(_DBG_LVL_FUNC_TRACE,Status); + return Status; + +discard: + _DBG_WARNING((" REP discarded! \n", + _DBG_PTR(pMad), pMad->payload.REP.LocalCommID, + pMad->payload.REP.RemoteCommID, _DBG_PTR(CmGetStateString(pCEP->State)))); + _DBG_FSTATUS_RETURN_LVL(_DBG_LVL_FUNC_TRACE,Status); + return Status; + +stale: + _DBG_WARNING((" REP discarded - stale! \n", + _DBG_PTR(pMad), pMad->payload.REP.LocalCommID, + pMad->payload.REP.RemoteCommID, _DBG_PTR(CmGetStateString(pCEP->State)))); + SendREJ(RC_STALE_CONN, CM_REJECT_REPLY, pMad->common.TransactionID, + pCEP->LocalCommID, pMad->payload.REP.LocalCommID, pRemoteDgrm); + _DBG_FSTATUS_RETURN_LVL(_DBG_LVL_FUNC_TRACE,Status); + return Status; +} + +////////////////////////////////////////////////////////////////////////// +// ProcessRtu() +// process an inbound RTU +// +// +// INPUTS: +// +// +// +// OUTPUTS: +// +// None. +// +// RETURNS: +// +// +// IRQL: +// +// This routine is called at IRQL_DISPATCH_LEVEL. With ListLock held +// + +FSTATUS +ProcessRtu( + CM_MAD* pMad, + IBT_DGRM_ELEMENT* pRemoteDgrm + ) +{ + CM_CEP_OBJECT* pCEP=NULL; + FSTATUS Status=FSUCCESS; + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, ProcessRtu); + + _DBG_INFO((" RTU received \n", + _DBG_PTR(pMad), + pMad->payload.RTU.LocalCommID, + pMad->payload.RTU.RemoteCommID)); + + // Determine who received this CM MAD + pCEP = FindLocalCommID(pMad->payload.RTU.RemoteCommID); + if (! pCEP) + goto nomatch; + + // TODO: Check the mad's addr with our endpoint's addr in addition to the + // Local comm ID, also validate RemoteCommID + // these should generate assorted REJ conditions if it doesn't match + switch (pCEP->State) + { + // Connecting + case CMS_REP_SENT: + case CMS_MRA_REP_RCVD: + // Process the rtu + Status = ProcessRtuPassive(pCEP, pMad, pRemoteDgrm); + if (Status == FSUCCESS) + { + _DBG_INFO((" RTU processed successfully !\n", + _DBG_PTR(pMad), pMad->payload.RTU.LocalCommID, + pMad->payload.RTU.RemoteCommID)); + } else { + _DBG_WARNING((" RTU dropped - unable to process it! \n", + _DBG_PTR(pMad), pMad->payload.RTU.LocalCommID, + pMad->payload.RTU.RemoteCommID, _DBG_PTR(FSTATUS_MSG(Status)))); + } + break; + case CMS_REQ_SENT: + case CMS_REP_WAIT: + case CMS_REQ_RCVD: + case CMS_MRA_REQ_SENT: + case CMS_REP_RCVD: + case CMS_MRA_REP_SENT: + // discard RTU + _DBG_WARNING((" RTU Discarded - not expecting !\n", + _DBG_PTR(pMad), pMad->payload.RTU.LocalCommID, + pMad->payload.RTU.RemoteCommID)); + break; + // Connected + case CMS_ESTABLISHED: + case CMS_LAP_SENT: + case CMS_MRA_LAP_RCVD: + case CMS_LAP_RCVD: + case CMS_MRA_LAP_SENT: + case CMS_DREQ_SENT: + case CMS_DREQ_RCVD: + // discard RTU + _DBG_WARNING((" RTU Discarded - already connected !\n", + _DBG_PTR(pMad), pMad->payload.RTU.LocalCommID, + pMad->payload.RTU.RemoteCommID)); + break; + default: // timewait, SIM_DREQ_RCVD, SIDR, idle, listen + // invalid LocalCommID + goto nomatch; + break; + } + + _DBG_FSTATUS_RETURN_LVL(_DBG_LVL_FUNC_TRACE,Status); + return Status; + +nomatch: + _DBG_WARNING((" RTU dropped - no match found !\n", + _DBG_PTR(pMad), pMad->payload.RTU.LocalCommID, + pMad->payload.RTU.RemoteCommID)); + _DBG_FSTATUS_RETURN_LVL(_DBG_LVL_FUNC_TRACE,Status); + return Status; +} + + +////////////////////////////////////////////////////////////////////////// +// ProcessRtuPassive() +// +// This routine processes a RTU or a Async Connect Established event +// for the passive side of a connection +// +// pMad and pRemoteDgrm are NULL for the Async Connect Established event +// +// RETURNS: +// +// FSUCCESS +// FINVALID_STATE - QP not in CMS_REP_SENT/MRA_REP_RCVD +// (most likely already connected) +// FCM_INVALID_EVENT +// +// IRQL: +// +// This routine is called at IRQL_DISPATCH_LEVEL. +// +FSTATUS +ProcessRtuPassive( + IN CM_CEP_OBJECT* pCEP, + IN CM_MAD* pMad, + IN IBT_DGRM_ELEMENT* pRemoteDgrm + ) +{ + FSTATUS Status = FSUCCESS; + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, AcceptCallback); + + if (pCEP->State != CMS_REP_SENT && pCEP->State != CMS_MRA_REP_RCVD) + { + Status = FINVALID_STATE; + goto done; + } + + Status = PrepareCepDgrm(pCEP); + if (Status != FSUCCESS) + goto fail; + + // Stop the rtu timer. Otherwise, we will retry REP or drop the pending request entirely. + CmTimerStop(pCEP, REP_TIMER); + // Save the rtu msg +#ifdef _CM_EVENT_ON_QP_ + // If we get a RTU event on the QP, we clear the mad so that + // user knows there is no RTU payload available + if ( pRemoteDgrm == NULL) + { + MemoryClear(GsiDgrmGetSendMad(pCEP->pDgrmElement), sizeof(CM_MAD)); + } + else +#endif + { + CmDgrmCopyAddrAndMad(pCEP->pDgrmElement, pMad, pRemoteDgrm); + } + + CepSetState(pCEP, CMS_ESTABLISHED); + + if (pCEP->bAsyncAccept) + { + SetNotification(pCEP, CME_RCVD_RTU); // trigger callback + } else { + EventSet(pCEP, CME_RCVD_RTU, FALSE); // wakeup CmAccept wait + } + +done: + _DBG_FSTATUS_RETURN_LVL(_DBG_LVL_FUNC_TRACE,Status); + return Status; + +fail: + _DBG_WARNING((" RTU dropped - unable to process it! \n", + _DBG_PTR(pMad), pMad->payload.RTU.LocalCommID, + pMad->payload.RTU.RemoteCommID, _DBG_PTR(FSTATUS_MSG(Status)))); + _DBG_FSTATUS_RETURN_LVL(_DBG_LVL_FUNC_TRACE,Status); + return Status; +} // ProcessRtuPassive() + + +////////////////////////////////////////////////////////////////////////// +// ProcessRejReq() +// process an inbound REJ of a REQ +// +// +// INPUTS: +// +// +// +// OUTPUTS: +// +// None. +// +// RETURNS: +// +// +// IRQL: +// +// This routine is called at IRQL_DISPATCH_LEVEL. With ListLock held +// + +FSTATUS +ProcessRejReq( + CM_MAD* pMad, + IBT_DGRM_ELEMENT* pRemoteDgrm + ) +{ + CM_CEP_OBJECT* pCEP=NULL; + FSTATUS Status=FSUCCESS; + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, ProcessRejReq); + + // Rejecting a connect request or reply. + _DBG_INFO((" REJ REQ received \n", + _DBG_PTR(pMad), + pMad->payload.REJ.LocalCommID, + pMad->payload.REJ.RemoteCommID)); + + // Determine who received this CM MAD + pCEP = FindLocalCommID(pMad->payload.REJ.RemoteCommID); + if (! pCEP) + goto nomatch; + + // TODO: Check the mad's addr with our endpoint's addr in addition to the + // local comm ID, also validate RemoteCommID + // these should generate assorted REJ conditions if it doesn't match + switch (pCEP->State) + { + // Connecting + case CMS_REQ_SENT: + case CMS_REP_WAIT: + // If we received a REJ with RC_INVALID_SID, we ignore it for peer + // endpoint since we want to let the REQ timeout and resend. + if (pCEP->bPeer && pMad->payload.REJ.Reason == RC_INVALID_SID) + break; + + // Set the RemoteCommId based on the msg + // pCEP->RemoteCommID = pMad->payload.REJ.LocalCommID; + + // Make sure we dont overwrite it if in used + Status = PrepareCepDgrm(pCEP); + if (Status != FSUCCESS) + goto fail; + + // Cancel the timer on REQ + CmTimerStop(pCEP, REQ_TIMER); + // Save the reject msg. This will override the req msg + CmDgrmCopyAddrAndMad(pCEP->pDgrmElement, pMad, pRemoteDgrm); + if (pCEP->bPeer && pCEP->RemoteEndPoint.CaGUID == 0) + { + CM_MapRemoveEntry(&gCM->ListenMap, &pCEP->MapEntry, LISTEN_LIST, pCEP); + } + // Special case of rejection per IB spec + if (pMad->payload.REJ.Reason == RC_STALE_CONN) + { + CepToTimewait(pCEP); + } else { + CepToIdle(pCEP); + } + + // Update the event flag + SetNotification(pCEP, CME_RCVD_REJ); //EventSet(pCEP, CME_RCVD_REJ); + break; + + // the handling of a REJ while established (or in LAP states) + // is tricky. IBTA says to move to timewait + // However sending the application an FCM_DISCONNECTED without a + // FCM_DISCONNECT_REQUEST would confuse most applications. + // Instead we simulate a FCM_DISCONNECT_REQUEST, and move to + // SIM_DREQ_RCVD. When the application issues the Disconnect we + // will start the timewait + case CMS_LAP_SENT: + case CMS_MRA_LAP_RCVD: + CmTimerStop(pCEP, LAP_TIMER); + /* FALLSTHROUGH */ + case CMS_ESTABLISHED: + case CMS_LAP_RCVD: + case CMS_MRA_LAP_SENT: + // If we received a REJ in a connected state, the other side did + // not get the RTU. We need to treat this REJ as a DREQ. + + // Notify local user existing connection is disconnected + // Fake out the REJ as a DREQ for the connection + MemoryClear(pMad, sizeof(CM_MAD)); + pMad->payload.DREQ.LocalCommID = pCEP->RemoteCommID; + pMad->payload.DREQ.RemoteCommID = pCEP->LocalCommID; + pMad->payload.DREQ.u.s.RemoteQPNorEECN = pCEP->LocalEndPoint.QPN; + // Save the simulated disconnect msg. + CmDgrmCopyAddrAndMad(pCEP->pDgrmElement, pMad, pRemoteDgrm); + + // Move from CONNECTED to disconnecting + CepToDisconnecting(pCEP, CMS_SIM_DREQ_RCVD); + + CmStartElapsedTime(pCEP); // for turnaround computation + SetNotification(pCEP, CME_SIM_RCVD_DREQ); + break; + default: + goto discard; + break; + } + _DBG_INFO((" REJ REQ processed successfully !\n", + _DBG_PTR(pMad), pMad->payload.REJ.LocalCommID, pMad->payload.REJ.RemoteCommID)); + _DBG_FSTATUS_RETURN_LVL(_DBG_LVL_FUNC_TRACE,Status); + return Status; + +nomatch: + _DBG_WARNING((" REJ REQ dropped - no match found !\n", + _DBG_PTR(pMad), pMad->payload.REJ.LocalCommID, + pMad->payload.REJ.RemoteCommID)); + _DBG_FSTATUS_RETURN_LVL(_DBG_LVL_FUNC_TRACE,Status); + return Status; +fail: + _DBG_WARNING((" REJ REQ dropped - unable to process it! \n", + _DBG_PTR(pMad), pMad->payload.REJ.LocalCommID, + pMad->payload.REJ.RemoteCommID, _DBG_PTR(FSTATUS_MSG(Status)))); + _DBG_FSTATUS_RETURN_LVL(_DBG_LVL_FUNC_TRACE,Status); + return Status; +discard: + _DBG_WARNING((" REJ REQ discarded! \n", + _DBG_PTR(pMad), pMad->payload.REJ.LocalCommID, + pMad->payload.REJ.RemoteCommID, _DBG_PTR(CmGetStateString(pCEP->State)))); + _DBG_FSTATUS_RETURN_LVL(_DBG_LVL_FUNC_TRACE,Status); + return Status; +} + +////////////////////////////////////////////////////////////////////////// +// ProcessRejRep() +// process an inbound REJ of a REP +// +// +// INPUTS: +// +// +// +// OUTPUTS: +// +// None. +// +// RETURNS: +// +// +// IRQL: +// +// This routine is called at IRQL_DISPATCH_LEVEL. With ListLock held +// + +FSTATUS +ProcessRejRep( + CM_MAD* pMad, + IBT_DGRM_ELEMENT* pRemoteDgrm + ) +{ + CM_CEP_OBJECT* pCEP=NULL; + FSTATUS Status=FSUCCESS; + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, ProcessRejRep); + + // Rejecting a connect request or reply. + _DBG_INFO((" REJ REP received \n", + _DBG_PTR(pMad), + pMad->payload.REJ.LocalCommID, + pMad->payload.REJ.RemoteCommID)); + + // Determine who received this CM MAD + pCEP = FindLocalCommID(pMad->payload.REJ.RemoteCommID); + if (! pCEP) + goto nomatch; + + // TODO: Check the mad's addr with our endpoint's addr in addition to the + // local comm ID, also validate RemoteCommID + // these should generate assorted REJ conditions if it doesn't match + switch (pCEP->State) + { + // TBD - if in CMS_REQ_RCVD or CMD_MRA_REQ_SENT we have gotten a REJ + // before we processed the REQ (timeout by client or cancel by client) + // in which case we should move the CEP to idle (timewait should not + // apply since we didn't get far enough to provide stale QPN) + // user calls to iba_cm_accept or iba_cm_process_request should + // then fail with some error (FCM_CONNECT_REJECT or FINVALID_STATE) + // and cleanup the CEP. While in this state, attempts to send REJ + // or REP should fail or be ignored. + case CMS_REP_SENT: + case CMS_MRA_REP_RCVD: + Status = PrepareCepDgrm(pCEP); + if (Status != FSUCCESS) + goto fail; + // Stop the rtu timer. Otherwise, we will retry REP or drop the pending request entirely. + CmTimerStop(pCEP, REP_TIMER); + // Save the reject msg + CmDgrmCopyAddrAndMad(pCEP->pDgrmElement, pMad, pRemoteDgrm); + // Special case of rejection per IB spec + if (pMad->payload.REJ.Reason == RC_STALE_CONN) + { + CepToTimewait(pCEP); + } else { + CepToIdle(pCEP); + } + if (pCEP->bAsyncAccept) + { + SetNotification(pCEP, CME_RCVD_REJ); // callback + } else { + EventSet(pCEP, CME_RCVD_REJ, FALSE); // wakeup CmAccept + } + break; + default: + goto discard; + break; + } + + _DBG_INFO((" REJ REP processed successfully !\n", + _DBG_PTR(pMad), pMad->payload.REJ.LocalCommID, pMad->payload.REJ.RemoteCommID)); + _DBG_FSTATUS_RETURN_LVL(_DBG_LVL_FUNC_TRACE,Status); + return Status; + +nomatch: + _DBG_WARNING((" REJ REP dropped - no match found !\n", + _DBG_PTR(pMad), pMad->payload.REJ.LocalCommID, + pMad->payload.REJ.RemoteCommID)); + _DBG_FSTATUS_RETURN_LVL(_DBG_LVL_FUNC_TRACE,Status); + return Status; +discard: + _DBG_WARNING((" REJ REQ discarded! \n", + _DBG_PTR(pMad), pMad->payload.REJ.LocalCommID, + pMad->payload.REJ.RemoteCommID, _DBG_PTR(CmGetStateString(pCEP->State)))); + _DBG_FSTATUS_RETURN_LVL(_DBG_LVL_FUNC_TRACE,Status); + return Status; +fail: + _DBG_WARNING((" REJ REP dropped - unable to process it! \n", + _DBG_PTR(pMad), pMad->payload.REJ.LocalCommID, + pMad->payload.REJ.RemoteCommID, _DBG_PTR(FSTATUS_MSG(Status)))); + _DBG_FSTATUS_RETURN_LVL(_DBG_LVL_FUNC_TRACE,Status); + return Status; +} + +////////////////////////////////////////////////////////////////////////// +// ProcessMraReq() +// process an inbound MRA of a REQ +// +// +// INPUTS: +// +// +// +// OUTPUTS: +// +// None. +// +// RETURNS: +// +// +// IRQL: +// +// This routine is called at IRQL_DISPATCH_LEVEL. With ListLock held +// + +FSTATUS +ProcessMraReq( + CM_MAD* pMad, + IBT_DGRM_ELEMENT* pRemoteDgrm + ) +{ + CM_CEP_OBJECT* pCEP=NULL; + FSTATUS Status=FSUCCESS; + uint32 mra_timeout_ms=0; + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, ProcessMraReq); + + // MRAed a connect request. + _DBG_INFO((" MRA REQ received \n", + _DBG_PTR(pMad), + pMad->payload.MRA.LocalCommID, + pMad->payload.MRA.RemoteCommID)); + + // Determine who received this CM MAD + pCEP = FindLocalCommID(pMad->payload.MRA.RemoteCommID); + if (! pCEP) + goto nomatch; + // TODO: Check the mad's addr with our endpoint's addr in addition to the + // local comm ID, also validate RemoteCommID + // these should generate assorted REJ conditions if it doesn't match + switch (pCEP->State) + { + // Connecting + case CMS_REQ_SENT: + // Received the mra to the connect request + + // Cancel the timer on REQ + CmTimerStop(pCEP, REQ_TIMER); + // Set the RemoteCommId based on the msg + pCEP->RemoteCommID = pMad->payload.MRA.LocalCommID; + gCM->turnaround_time_us = UpdateTurnaroundTime(gCM->turnaround_time_us,TimeoutMultToTimeInUsec(pMad->payload.MRA.ServiceTimeout)); + // restart the timer, do NOT reset RetryCount + // allow for PktLifeTime in case MRA arrived faster than response + mra_timeout_ms = TimeoutMultToTimeInMs(pMad->payload.MRA.ServiceTimeout) + + TimeoutMultToTimeInMs(pCEP->PktLifeTime); + CmTimerStart(pCEP, mra_timeout_ms, MRA_TIMER); + _DBG_INFO((" MRA REQ processed successfully !\n", + _DBG_PTR(pMad), pMad->payload.MRA.LocalCommID, + pMad->payload.MRA.RemoteCommID)); + CepSetState(pCEP, CMS_REP_WAIT); + break; + + case CMS_REP_WAIT: + case CMS_REQ_RCVD: + case CMS_MRA_REQ_SENT: + case CMS_REP_SENT: + case CMS_MRA_REP_RCVD: + case CMS_REP_RCVD: + case CMS_MRA_REP_SENT: + default: // not connecting + goto discard; + break; + } + + _DBG_FSTATUS_RETURN_LVL(_DBG_LVL_FUNC_TRACE,Status); + return Status; + +nomatch: + _DBG_WARNING((" MRA REQ dropped - no match found !\n", + _DBG_PTR(pMad), pMad->payload.MRA.LocalCommID, + pMad->payload.MRA.RemoteCommID)); + _DBG_FSTATUS_RETURN_LVL(_DBG_LVL_FUNC_TRACE,Status); + return Status; + +discard: + _DBG_WARNING((" MRA REQ discarded! \n", + _DBG_PTR(pMad), pMad->payload.MRA.LocalCommID, + pMad->payload.MRA.RemoteCommID, _DBG_PTR(CmGetStateString(pCEP->State)))); + _DBG_FSTATUS_RETURN_LVL(_DBG_LVL_FUNC_TRACE,Status); + return Status; +} + + +////////////////////////////////////////////////////////////////////////// +// ProcessMraRep() +// process an inbound MRA of a REP +// +// +// INPUTS: +// +// +// +// OUTPUTS: +// +// None. +// +// RETURNS: +// +// +// IRQL: +// +// This routine is called at IRQL_DISPATCH_LEVEL. With ListLock held +// + +FSTATUS +ProcessMraRep( + CM_MAD* pMad, + IBT_DGRM_ELEMENT* pRemoteDgrm + ) +{ + CM_CEP_OBJECT* pCEP=NULL; + FSTATUS Status=FSUCCESS; + uint32 mra_timeout_ms=0; + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, ProcessMraRep); + + // MRAed a connect reply. + _DBG_INFO((" MRA REP received \n", + _DBG_PTR(pMad), + pMad->payload.MRA.LocalCommID, + pMad->payload.MRA.RemoteCommID)); + + // Determine who received this CM MAD + pCEP = FindLocalCommID(pMad->payload.MRA.RemoteCommID); + if (! pCEP) + goto nomatch; + // TODO: Check the mad's addr with our endpoint's addr in addition to the + // local comm ID, also validate RemoteCommID + // these should generate assorted REJ conditions if it doesn't match + switch (pCEP->State) + { + case CMS_REP_SENT: + // Stop the rtu timer. Otherwise, we will retry REP or drop the pending request entirely. + CmTimerStop(pCEP, REP_TIMER); + + gCM->turnaround_time_us = UpdateTurnaroundTime(gCM->turnaround_time_us,TimeoutMultToTimeInUsec(pMad->payload.MRA.ServiceTimeout)); + // restart the timer, do NOT reset RetryCount + // allow for PktLifeTime in case MRA arrived faster than response + mra_timeout_ms = TimeoutMultToTimeInMs(pMad->payload.MRA.ServiceTimeout) + + TimeoutMultToTimeInMs(pCEP->PktLifeTime); + CmTimerStart(pCEP, mra_timeout_ms, MRA_TIMER); + CepSetState(pCEP, CMS_MRA_REP_RCVD); + _DBG_INFO((" MRA REP processed successfully !\n", + _DBG_PTR(pMad), pMad->payload.MRA.LocalCommID, + pMad->payload.MRA.RemoteCommID)); + break; + default: + goto discard; + break; + } + + _DBG_FSTATUS_RETURN_LVL(_DBG_LVL_FUNC_TRACE,Status); + return Status; + +nomatch: + _DBG_WARNING((" MRA REP dropped - no match found !\n", + _DBG_PTR(pMad), pMad->payload.MRA.LocalCommID, + pMad->payload.MRA.RemoteCommID)); + _DBG_FSTATUS_RETURN_LVL(_DBG_LVL_FUNC_TRACE,Status); + return Status; +discard: + _DBG_WARNING((" MRA REP discarded! \n", + _DBG_PTR(pMad), pMad->payload.MRA.LocalCommID, + pMad->payload.MRA.RemoteCommID, _DBG_PTR(CmGetStateString(pCEP->State)))); + _DBG_FSTATUS_RETURN_LVL(_DBG_LVL_FUNC_TRACE,Status); + return Status; +} + +////////////////////////////////////////////////////////////////////////// +// ProcessMraLap() +// process an inbound MRA of a LAP +// +// +// INPUTS: +// +// +// +// OUTPUTS: +// +// None. +// +// RETURNS: +// +// +// IRQL: +// +// This routine is called at IRQL_DISPATCH_LEVEL. With ListLock held +// + +FSTATUS +ProcessMraLap( + CM_MAD* pMad, + IBT_DGRM_ELEMENT* pRemoteDgrm + ) +{ + CM_CEP_OBJECT* pCEP=NULL; + FSTATUS Status=FSUCCESS; + uint32 mra_timeout_ms=0; + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, ProcessMraLap); + + // MRAed a LAP. + _DBG_INFO((" MRA LAP received \n", + _DBG_PTR(pMad), + pMad->payload.MRA.LocalCommID, + pMad->payload.MRA.RemoteCommID)); + + // Determine who received this CM MAD + pCEP = FindLocalCommID(pMad->payload.MRA.RemoteCommID); + if (! pCEP) + goto nomatch; + switch (pCEP->State) + { + case CMS_LAP_SENT: + // Received the mra to the LAP + + // Cancel the timer on LAP + CmTimerStop(pCEP, LAP_TIMER); + + gCM->turnaround_time_us = UpdateTurnaroundTime(gCM->turnaround_time_us,TimeoutMultToTimeInUsec(pMad->payload.MRA.ServiceTimeout)); + // restart the timer, do NOT reset RetryCount + // allow for PktLifeTime in case MRA arrived faster than response + mra_timeout_ms = TimeoutMultToTimeInMs(pMad->payload.MRA.ServiceTimeout) + + TimeoutMultToTimeInMs(pCEP->PktLifeTime); + CmTimerStart(pCEP, mra_timeout_ms, MRA_TIMER); + _DBG_INFO((" MRA LAP processed successfully !\n", + _DBG_PTR(pMad), pMad->payload.MRA.LocalCommID, + pMad->payload.MRA.RemoteCommID)); + CepSetState(pCEP, CMS_MRA_LAP_RCVD); + break; + + case CMS_MRA_LAP_RCVD: + case CMS_LAP_RCVD: + case CMS_MRA_LAP_SENT: + default: + goto discard; + break; + } + _DBG_FSTATUS_RETURN_LVL(_DBG_LVL_FUNC_TRACE,Status); + return Status; + +nomatch: + _DBG_WARNING((" MRA LAP dropped - no match found !\n", + _DBG_PTR(pMad), pMad->payload.MRA.LocalCommID, + pMad->payload.MRA.RemoteCommID)); + _DBG_FSTATUS_RETURN_LVL(_DBG_LVL_FUNC_TRACE,Status); + return Status; + +discard: + _DBG_WARNING((" MRA LAP discarded! \n", + _DBG_PTR(pMad), pMad->payload.MRA.LocalCommID, + pMad->payload.MRA.RemoteCommID, _DBG_PTR(CmGetStateString(pCEP->State)))); + _DBG_FSTATUS_RETURN_LVL(_DBG_LVL_FUNC_TRACE,Status); + return Status; +} + +////////////////////////////////////////////////////////////////////////// +// ProcessLap() +// process an inbound LAP +// +// +// INPUTS: +// +// +// +// OUTPUTS: +// +// None. +// +// RETURNS: +// +// +// IRQL: +// +// This routine is called at IRQL_DISPATCH_LEVEL. With ListLock held +// + +FSTATUS +ProcessLap( + CM_MAD* pMad, + IBT_DGRM_ELEMENT* pRemoteDgrm + ) +{ + CM_CEP_OBJECT* pCEP=NULL; + FSTATUS Status=FSUCCESS; + uint32 worst_service_time_mult=0; + uint64 new_turnaround; + IB_PORT_ATTRIBUTES *pPortAttr = NULL; + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, ProcessLap); + + _DBG_INFO((" LAP received \n", + _DBG_PTR(pMad), + pMad->payload.LAP.LocalCommID, + pMad->payload.LAP.RemoteCommID)); + + // Determine who received this CM MAD + pCEP = FindLocalCommID(pMad->payload.LAP.RemoteCommID); + if (! pCEP) + goto nomatch; + + // TODO: Check the mad's addr with our endpoint's addr in addition to the + // Local comm ID, also validate RemoteCommID + // these should generate assorted REJ conditions if it doesn't match + switch (pCEP->State) + { + case CMS_REP_SENT: + case CMS_MRA_REP_RCVD: + // Must have lost the RTU, treat the LAP as an RTU and move forward + Status = ProcessRtuPassive(pCEP, NULL, NULL); + if (Status == FSUCCESS) + { + _DBG_INFO(("LAP recognized as RTU+LAP !\n", _DBG_PTR(pCEP))); + } else if (Status != FINVALID_STATE) { + goto fail; + } + /*FALLSTHROUGH*/ + case CMS_ESTABLISHED: + if (pCEP->Mode != CM_MODE_PASSIVE) + goto discard; // TBD could send APR rejection + + if (! pCEP->bFailoverSupported) + { + SendAPR(APS_UNSUPPORTED_REQ, pMad->common.TransactionID, + pCEP->LocalCommID, pCEP->RemoteCommID, pRemoteDgrm); + goto done; + } + + if (0 == CompareRcvdLAPToPath(&pMad->payload.LAP, &pCEP->PrimaryPath)) + { + SendAPR(APS_DUPLICATE_PATH, pMad->common.TransactionID, + pCEP->LocalCommID, pCEP->RemoteCommID, pRemoteDgrm); + goto done; + } + if (0 == CompareRcvdLAPToPath(&pMad->payload.LAP, &pCEP->AlternatePath)) + { + // duplicate LAP, respond again + SendAPR(APS_PATH_LOADED, pMad->common.TransactionID, + pCEP->LocalCommID, pCEP->RemoteCommID, pRemoteDgrm); + goto done; + } +#if ! defined(CM_APM_RELOAD) + if (pCEP->AlternatePath.LocalLID) + { + // reject, we can't reload a new alternate til we migrate + SendAPR(APS_REJECTED, pMad->common.TransactionID, + pCEP->LocalCommID, pCEP->RemoteCommID, pRemoteDgrm); + goto done; + } +#endif + Status = iba_find_ca_gid(&pMad->payload.LAP.AlternateRemoteGID, + pCEP->LocalEndPoint.CaGUID, + &pCEP->TempAlternateLocalPortGuid, + &pCEP->TempAlternateLocalGidIndex, &pPortAttr, NULL); + if (Status != FSUCCESS) + { + SendAPR(APS_REJECT_DGID, pMad->common.TransactionID, + pCEP->LocalCommID, pCEP->RemoteCommID, pRemoteDgrm); + goto done; + } + if (! ValidatePKey(pPortAttr, pCEP->PartitionKey, &pCEP->TempAlternatePkeyIndex)) + { + SendAPR(APS_REJECT_DGID, pMad->common.TransactionID, + pCEP->LocalCommID, pCEP->RemoteCommID, pRemoteDgrm); + goto done; + } + pCEP->TempAlternateLocalPathBits = LidToPathBits(pMad->payload.LAP.AlternateRemoteLID, pPortAttr->Address.LMC); + MemoryDeallocate(pPortAttr); + + Status = PrepareCepDgrm(pCEP); + if (Status != FSUCCESS) + goto fail; + + CmDgrmCopyAddrAndMad(pCEP->pDgrmElement, pMad, pRemoteDgrm); + + CepSetState(pCEP, CMS_LAP_RCVD); + + // compare RemoteCMTimeout to our typical turnaround + // if necessary, output an MRA to be safe + worst_service_time_mult = CepWorstServiceTimeMult(pCEP); + if (pMad->payload.LAP.u1.s.RemoteCMTimeout < worst_service_time_mult) { + SendMRA(CM_MRA_LAP, worst_service_time_mult, + pCEP->TransactionID, pCEP->LocalCommID, + pCEP->RemoteCommID, pRemoteDgrm); + CepSetState(pCEP, CMS_MRA_LAP_SENT); + } + SetNotification(pCEP, CME_RCVD_LAP); // trigger callback + break; + case CMS_LAP_RCVD: + case CMS_MRA_LAP_SENT: + ASSERT(pCEP->Mode == CM_MODE_PASSIVE); + if (0 == CompareRcvdLAPToPath(&pMad->payload.LAP, &pCEP->PrimaryPath)) + { + SendAPR(APS_DUPLICATE_PATH, pMad->common.TransactionID, + pCEP->LocalCommID, pCEP->RemoteCommID, pRemoteDgrm); + goto done; + } + if (0 == CompareLAP(&pMad->payload.LAP, + &((CM_MAD*)GsiDgrmGetSendMad(pCEP->pDgrmElement))->payload.LAP)) + { + // duplicate LAP + // Update the turnaround time + new_turnaround = UpdateTurnaroundTime(gCM->turnaround_time_us, 2*CmGetElapsedTime(pCEP)); + if (new_turnaround > gCM->turnaround_time_us) + { + gCM->turnaround_time_us = new_turnaround; + } + worst_service_time_mult = CepWorstServiceTimeMult(pCEP); + if (pCEP->State == CMS_MRA_LAP_SENT) + { + SendMRA(CM_MRA_LAP, worst_service_time_mult, + pCEP->TransactionID, pCEP->LocalCommID, + pCEP->RemoteCommID, pRemoteDgrm); + goto done; + } else if (pMad->payload.LAP.u1.s.RemoteCMTimeout < worst_service_time_mult) { + SendMRA(CM_MRA_LAP, worst_service_time_mult, + pCEP->TransactionID, pCEP->LocalCommID, + pCEP->RemoteCommID, pRemoteDgrm); + CepSetState(pCEP, CMS_MRA_LAP_SENT); + goto done; + } else { + goto discard; + } + } + + // TBD or disconnect + // if we are really slow, other end could timeout LAP + // and this could be a new LAP, in which case this APR/reject + // will happen, then we will send an APR and remote end will + // discard it, leaving local end with an alternate path + // and remote end with no alternate path + SendAPR(APS_REJECTED, pMad->common.TransactionID, + pCEP->LocalCommID, pCEP->RemoteCommID, pRemoteDgrm); + break; + default: + goto discard; + break; + } + +done: + _DBG_FSTATUS_RETURN_LVL(_DBG_LVL_FUNC_TRACE,Status); + return Status; + +fail: + _DBG_WARNING((" LAP dropped - unable to process it! \n", + _DBG_PTR(pMad), pMad->payload.LAP.LocalCommID, + pMad->payload.LAP.RemoteCommID, _DBG_PTR(FSTATUS_MSG(Status)))); + _DBG_FSTATUS_RETURN_LVL(_DBG_LVL_FUNC_TRACE,Status); + return Status; + +discard: + _DBG_WARNING((" LAP Discarded !\n", + _DBG_PTR(pMad), pMad->payload.LAP.LocalCommID, + pMad->payload.LAP.RemoteCommID)); + _DBG_FSTATUS_RETURN_LVL(_DBG_LVL_FUNC_TRACE,Status); + return Status; + +nomatch: + _DBG_WARNING((" LAP dropped - no match found !\n", + _DBG_PTR(pMad), pMad->payload.LAP.LocalCommID, + pMad->payload.LAP.RemoteCommID)); + SendAPR(APS_INVALID_COMMID, pMad->common.TransactionID, + pMad->payload.LAP.RemoteCommID, + pMad->payload.LAP.LocalCommID, pRemoteDgrm); + _DBG_FSTATUS_RETURN_LVL(_DBG_LVL_FUNC_TRACE,Status); + return Status; +} + + +////////////////////////////////////////////////////////////////////////// +// ProcessApr() +// process an inbound APR +// +// +// INPUTS: +// +// +// +// OUTPUTS: +// +// None. +// +// RETURNS: +// +// +// IRQL: +// +// This routine is called at IRQL_DISPATCH_LEVEL. With ListLock held +// + +FSTATUS +ProcessApr( + CM_MAD* pMad, + IBT_DGRM_ELEMENT* pRemoteDgrm + ) +{ + CM_CEP_OBJECT* pCEP=NULL; + FSTATUS Status=FSUCCESS; + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, ProcessApr); + + _DBG_INFO((" APR received \n", + _DBG_PTR(pMad), + pMad->payload.APR.LocalCommID, + pMad->payload.APR.RemoteCommID, + pMad->payload.APR.APStatus)); + + // Determine who received this CM MAD + pCEP = FindLocalCommID(pMad->payload.LAP.RemoteCommID); + if (! pCEP) + goto nomatch; + + // TODO: Check the mad's addr with our endpoint's addr in addition to the + // Local comm ID, also validate RemoteCommID + // these should generate assorted REJ conditions if it doesn't match + switch (pCEP->State) + { + case CMS_LAP_SENT: + case CMS_MRA_LAP_RCVD: + ASSERT(pCEP->Mode == CM_MODE_ACTIVE); + + Status = PrepareCepDgrm(pCEP); + if (Status != FSUCCESS) + goto fail; + + if (pMad->payload.APR.APStatus == APS_PATH_LOADED) + { + // Dgrm was byteswapped for send + ConvertMadToHostByteOrder(pMad); + + ASSERT(((CM_MAD*)GsiDgrmGetSendMad(pCEP->pDgrmElement))->common.AttributeID == MCLASS_ATTRIB_ID_LAP); + CopySentLAPToAltPath( + &((CM_MAD*)GsiDgrmGetSendMad(pCEP->pDgrmElement))->payload.LAP, + &pCEP->AlternatePath); + pCEP->AlternatePath.LocalPortGuid = pCEP->TempAlternateLocalPortGuid; + pCEP->AlternatePath.LocalGidIndex = pCEP->TempAlternateLocalGidIndex; + pCEP->AlternatePath.LocalPathBits = pCEP->TempAlternateLocalPathBits; + pCEP->AlternatePath.PkeyIndex = pCEP->TempAlternatePkeyIndex; + pCEP->AlternatePath.LocalAckTimeout = pCEP->TempAlternateLocalAckTimeout; + } + + //Save the APR + CmDgrmCopyAddrAndMad(pCEP->pDgrmElement, pMad, pRemoteDgrm); + + CmTimerStop(pCEP, LAP_TIMER); + CepSetState(pCEP, CMS_ESTABLISHED); + SetNotification(pCEP, CME_RCVD_APR); + _DBG_INFO((" APR processed successfully !\n", + _DBG_PTR(pMad), pMad->payload.APR.LocalCommID, + pMad->payload.APR.RemoteCommID)); + break; + default: + goto discard; + break; + } + + _DBG_FSTATUS_RETURN_LVL(_DBG_LVL_FUNC_TRACE,Status); + return Status; + +discard: + _DBG_WARNING((" APR Discarded !\n", + _DBG_PTR(pMad), pMad->payload.APR.LocalCommID, + pMad->payload.APR.RemoteCommID)); + _DBG_FSTATUS_RETURN_LVL(_DBG_LVL_FUNC_TRACE,Status); + return Status; + +fail: + _DBG_WARNING((" APR dropped - unable to process it! \n", + _DBG_PTR(pMad), pMad->payload.APR.LocalCommID, + pMad->payload.APR.RemoteCommID, _DBG_PTR(FSTATUS_MSG(Status)))); + _DBG_FSTATUS_RETURN_LVL(_DBG_LVL_FUNC_TRACE,Status); + return Status; + +nomatch: + // TBD - send APR with APStatus = 1 + _DBG_WARNING((" APR dropped - no match found !\n", + _DBG_PTR(pMad), pMad->payload.APR.LocalCommID, + pMad->payload.APR.RemoteCommID)); + _DBG_FSTATUS_RETURN_LVL(_DBG_LVL_FUNC_TRACE,Status); + return Status; +} + + +////////////////////////////////////////////////////////////////////////// +// ProcessDreq() +// process an inbound DREQ +// +// +// INPUTS: +// +// +// +// OUTPUTS: +// +// None. +// +// RETURNS: +// +// +// IRQL: +// +// This routine is called at IRQL_DISPATCH_LEVEL. With ListLock held +// + +FSTATUS +ProcessDreq( + CM_MAD* pMad, + IBT_DGRM_ELEMENT* pRemoteDgrm + ) +{ + CM_CEP_OBJECT* pCEP=NULL; + FSTATUS Status=FSUCCESS; + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, ProcessDreq); + + // + // Disconnect request - apply to ESTABLISHED list + // + _DBG_INFO((" DREQ received \n", + _DBG_PTR(pMad), + pMad->payload.DREQ.LocalCommID, + pMad->payload.DREQ.RemoteCommID)); + + // Determine who received this CM MAD + pCEP = FindLocalCommID(pMad->payload.DREQ.RemoteCommID); + if (! pCEP) + goto nomatch; + + // TODO: Check the mad's addr with our endpoint's addr in addition to the + // local comm ID, also validate RemoteCommID + // these should generate assorted REJ/error conditions if it doesn't match + switch (pCEP->State) + { + // Connected + case CMS_ESTABLISHED: + case CMS_LAP_SENT: + case CMS_MRA_LAP_RCVD: + case CMS_LAP_RCVD: + case CMS_MRA_LAP_SENT: + // TimeWait + case CMS_DREQ_SENT: + case CMS_DREQ_RCVD: + case CMS_SIM_DREQ_RCVD: // this is a little odd, since we got a REJ + // then a DREQ for connection, but it is + // what IBTA CM state machine says to do + case CMS_TIMEWAIT: + // Process the DREQ + Status = ProcessDreqCep(pCEP, pMad, pRemoteDgrm); + if (Status == FSUCCESS) + { + _DBG_INFO((" DREQ processed successfully !\n", + _DBG_PTR(pMad), pMad->payload.DREQ.LocalCommID, + pMad->payload.DREQ.RemoteCommID)); + } else { + _DBG_WARNING((" DREQ dropped - unable to processed it! \n", + _DBG_PTR(pMad), pMad->payload.DREQ.LocalCommID, + pMad->payload.DREQ.RemoteCommID, _DBG_PTR(FSTATUS_MSG(Status)))); + } + break; + default: + goto nomatch; + break; + } + _DBG_FSTATUS_RETURN_LVL(_DBG_LVL_FUNC_TRACE,Status); + return Status; + +nomatch: + _DBG_WARNING((" DREQ dropped - no match found !\n", + _DBG_PTR(pMad), pMad->payload.DREQ.LocalCommID, + pMad->payload.DREQ.RemoteCommID)); + _DBG_FSTATUS_RETURN_LVL(_DBG_LVL_FUNC_TRACE,Status); + return Status; +} + +////////////////////////////////////////////////////////////////////////// +// ProcessDreqCep() +// +// Process a valid DREQ received or simulated against a specific CEP. +// The ListLock must be obtained before calling this routine +// +// INPUTS: +// +// +// +// OUTPUTS: +// +// None. +// +// RETURNS: +// +// FSUCCESS. +// +// IRQL: +// +// This routine is called at IRQL_PASSIVE_LEVEL. +// +FSTATUS +ProcessDreqCep( + IN CM_CEP_OBJECT* pCEP, + IN CM_MAD* pMad, + IN IBT_DGRM_ELEMENT* pRemoteDgrm + ) +{ + FSTATUS Status=FSUCCESS; + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, ProcessDreqCep); + + switch (pCEP->State) + { + case CMS_LAP_SENT: + case CMS_MRA_LAP_RCVD: + CmTimerStop(pCEP, LAP_TIMER); + /* FALLSTHROUGH */ + case CMS_ESTABLISHED: + case CMS_LAP_RCVD: + case CMS_MRA_LAP_SENT: + // Save the disconnect msg. + CmDgrmCopyAddrAndMad(pCEP->pDgrmElement, pMad, pRemoteDgrm); + + // Move from CONNECTED to Disconnecting + CepToDisconnecting(pCEP, CMS_DREQ_RCVD); + + CmStartElapsedTime(pCEP); // for turnaround computation + // RTU followed immediately by a DREQ may queue 2 events + SetNotification(pCEP, CME_RCVD_DREQ); + break; + case CMS_DREQ_RCVD: + // Duplicate DREQ received. + _DBG_INFO((" Duplicate DREQ received in CMS_DREQ_RCVD .\n", + _DBG_PTR(pCEP), pCEP->LocalCommID, pCEP->RemoteCommID, + pCEP->PrimaryPath.LocalLID, pCEP->PrimaryPath.RemoteLID)); + break; + case CMS_DREQ_SENT: + _DBG_INFO((" DREQ received in CMS_DREQ_SENT .\n", + _DBG_PTR(pCEP), pCEP->LocalCommID, pCEP->RemoteCommID, + pCEP->PrimaryPath.LocalLID, pCEP->PrimaryPath.RemoteLID)); + + Status = PrepareCepDgrm(pCEP); + if (Status != FSUCCESS) + goto fail; + + CmTimerStop(pCEP, DREQ_TIMER); + // Save the disconnect request + CmDgrmCopyAddrAndMad(pCEP->pDgrmElement, pMad, pRemoteDgrm); + CepSetState(pCEP, CMS_DREQ_RCVD); + // Note that we may have reached the DREQ sent state via a + // CmDestroyCEP call from the proxy on behalf of a crashed app. + // In this case, we must continue the disconnect process or the CEP + // will never transition out of its current state. + if( !SetNotification(pCEP, CME_RCVD_DREQ) ) + { + CM_DREQUEST_INFO DisconnectReq; + MemoryClear(&DisconnectReq, sizeof(CM_DREQUEST_INFO)); + DisconnectA(pCEP, &DisconnectReq, (CM_DREPLY_INFO*)&DisconnectReq); + } + break; + case CMS_SIM_DREQ_RCVD: + case CMS_TIMEWAIT: + { + // Resend the DREP + + // If dgrm is still in use (i.e. send pending), skip the resend + // since it is likely the timeout is set too low + if (CmDgrmIsInUse(pCEP->pDgrmElement)) + goto done; + + if (GsiDgrmGetSendMad(pCEP->pDgrmElement)->common.AttributeID != MCLASS_ATTRIB_ID_DREP ) + { + // Format the DREP msg + FormatDREP((CM_MAD*)GsiDgrmGetSendMad(pCEP->pDgrmElement), + NULL, 0, + pCEP->TransactionID, + pCEP->LocalCommID, + pCEP->RemoteCommID); + } + + _DBG_INFO((" DREP resend in %s .\n", + _DBG_PTR(pCEP), _DBG_PTR(CmGetStateString(pCEP->State)), + pCEP->LocalCommID, + pCEP->PrimaryPath.LocalLID, pCEP->PrimaryPath.RemoteLID)); + Status = CmDgrmSend(pCEP->pDgrmElement); + if (FSUCCESS != Status) + { + // fall through and let timer retry the send later + _DBG_WARN((" DgrmSend() failed for DREP!!! <%s>\n", + _DBG_PTR(pCEP), _DBG_PTR(FSTATUS_MSG(Status)))); + Status = FSUCCESS; + } else { + AtomicIncrementVoid(&gCM->Sent.Drep); + } + break; + } + default: + break; + } + +done: + _DBG_FSTATUS_RETURN_LVL(_DBG_LVL_FUNC_TRACE,Status); + return Status; + +fail: + _DBG_WARNING((" DREQ dropped - unable to process it! \n", + _DBG_PTR(pMad), pMad->payload.DREQ.LocalCommID, + pMad->payload.DREQ.RemoteCommID, _DBG_PTR(FSTATUS_MSG(Status)))); + _DBG_FSTATUS_RETURN_LVL(_DBG_LVL_FUNC_TRACE,Status); + return Status; + +} // ProcessDreqCep() + + +////////////////////////////////////////////////////////////////////////// +// ProcessDrep() +// process an inbound DREP +// +// +// INPUTS: +// +// +// +// OUTPUTS: +// +// None. +// +// RETURNS: +// +// +// IRQL: +// +// This routine is called at IRQL_DISPATCH_LEVEL. With ListLock held +// + +FSTATUS +ProcessDrep( + CM_MAD* pMad, + IBT_DGRM_ELEMENT* pRemoteDgrm + ) +{ + CM_CEP_OBJECT* pCEP=NULL; + FSTATUS Status=FSUCCESS; + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, ProcessDrep); + + // + // Disconnect reply received - apply to TIMEWAIT list + // + _DBG_INFO((" DREP received \n", + _DBG_PTR(pMad), + pMad->payload.DREP.LocalCommID, + pMad->payload.DREP.RemoteCommID)); + + // Determine who received this CM MAD + pCEP = FindLocalCommID(pMad->payload.DREP.RemoteCommID); + if (! pCEP) + goto nomatch; + + // TODO: Check the mad's addr with our endpoint's addr in addition to the + // local comm ID, also validate RemoteCommID + // these should generate assorted REJ/error conditions if it doesn't match + switch (pCEP->State) + { + case CMS_DREQ_SENT: + Status = PrepareCepDgrm(pCEP); + if (Status != FSUCCESS) + goto fail; + + //Save the disconnect reply + CmDgrmCopyAddrAndMad(pCEP->pDgrmElement, pMad, pRemoteDgrm); + + CmTimerStop(pCEP, DREQ_TIMER); + CepToTimewait(pCEP); + SetNotification(pCEP, CME_RCVD_DREP); + _DBG_INFO((" DREP processed successfully !\n", + _DBG_PTR(pMad), pMad->payload.DREP.LocalCommID, + pMad->payload.DREP.RemoteCommID)); + break; + case CMS_DREQ_RCVD: + case CMS_SIM_DREQ_RCVD: + case CMS_TIMEWAIT: + default: + goto discard; + break; + } + _DBG_FSTATUS_RETURN_LVL(_DBG_LVL_FUNC_TRACE,Status); + return Status; + +nomatch: + _DBG_WARNING((" DREP dropped - no match found !\n", + _DBG_PTR(pMad), pMad->payload.DREP.LocalCommID, + pMad->payload.DREP.RemoteCommID)); + _DBG_FSTATUS_RETURN_LVL(_DBG_LVL_FUNC_TRACE,Status); + return Status; + +discard: + _DBG_WARNING((" DREP discarded! \n", + _DBG_PTR(pMad), pMad->payload.DREP.LocalCommID, + pMad->payload.DREP.RemoteCommID, _DBG_PTR(CmGetStateString(pCEP->State)))); + _DBG_FSTATUS_RETURN_LVL(_DBG_LVL_FUNC_TRACE,Status); + return Status; + +fail: + _DBG_WARNING((" DREP dropped - unable to processed it! \n", + _DBG_PTR(pMad), pMad->payload.DREP.LocalCommID, + pMad->payload.DREP.RemoteCommID, _DBG_PTR(FSTATUS_MSG(Status)))); + _DBG_FSTATUS_RETURN_LVL(_DBG_LVL_FUNC_TRACE,Status); + return Status; +} + +////////////////////////////////////////////////////////////////////////// +// ProcessSidrReq() +// +// +// INPUTS: +// +// +// +// OUTPUTS: +// +// None. +// +// RETURNS: +// +// +// IRQL: +// +// This routine is called at IRQL_PASSIVE_LEVEL. With ListLock held +// + +FSTATUS +ProcessSidrReq( + CM_MAD* pMad, + IBT_DGRM_ELEMENT* pRemoteDgrm + ) +{ + CM_CEP_OBJECT* pCEP=NULL; + CM_MAP_ITEM* pMapEntry = NULL; + boolean bFound=FALSE; + FSTATUS Status=FSUCCESS; + CM_CEP_OBJECT* pNewCEP=NULL; + DLIST_ENTRY* Anchor = NULL; + DLIST_ENTRY* Index = NULL; + boolean bDuplicate = FALSE; + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, ProcessSidrReq); + + // + // SIDR request received - apply to LISTEN list + // + _DBG_INFO((" SIDR_REQ received \n", + _DBG_PTR(pMad), + pMad->payload.SIDR_REQ.RequestID, + pMad->payload.SIDR_REQ.ServiceID)); + + // Look for the CEP object in the listen list + pMapEntry = CM_MapGetCompare(&gCM->ListenMap, (uintn)&pMad->payload.SIDR_REQ, + CepSidrReqAddrCompare); + if (pMapEntry != CM_MapEnd(&gCM->ListenMap)) + { + pCEP = PARENT_STRUCT(pMapEntry, CM_CEP_OBJECT, MapEntry); + if (pCEP->State == CMS_REGISTERED) + { + bFound = TRUE; + } + } + + if (!bFound) + { + _DBG_WARNING((" SIDR REQ dropped - no match found !\n", + _DBG_PTR(pMad), pMad->payload.SIDR_REQ.RequestID, pMad->payload.SIDR_REQ.ServiceID)); + + SendSIDR_RESP(pMad->payload.SIDR_REQ.ServiceID, + 0, 0, + SRS_SID_NOT_SUPPORTED, + NULL, 0, pMad->common.TransactionID, + pMad->payload.SIDR_REQ.RequestID, + pRemoteDgrm); + goto done; + } + + // Check for duplicate request in PENDING list + DListIterate(Anchor, Index, &pCEP->PendingList) + { + CM_CEP_OBJECT* pCEPEntry; + + pCEPEntry = PARENT_STRUCT(Index, CM_CEP_OBJECT, PendingListEntry); + + // We have to check GID, LID and RequestId to determine if + // this is a duplicate, most likely a retry by requestor + if ( (pCEPEntry->PrimaryPath.RemoteLID == pRemoteDgrm->RemoteLID) && + (! (pRemoteDgrm->GlobalRoute) || (MemoryCompare(pCEPEntry->PrimaryPath.RemoteGID.Raw, pRemoteDgrm->GRHInfo.DestGID.Raw, sizeof(IB_GID)) == 0)) && + (pCEPEntry->RemoteCommID == pMad->payload.SIDR_REQ.RequestID)) + { + bDuplicate = TRUE; + break; + } + } + + if (bDuplicate) + { + _DBG_WARNING((" SIDR REQ dropped - duplicates pending request! \n", + _DBG_PTR(pMad), pMad->payload.SIDR_REQ.RequestID, + pMad->payload.SIDR_REQ.ServiceID, _DBG_PTR(FSTATUS_MSG(Status)))); + //MsgOut("*** SIDR REQ Recv DUP Dropped ***, Remote Lid=0x%x\n", pRemoteDgrm->RemoteLID); + Status = FDUPLICATE; + goto done; + } + + // If we hit this backlog cnt, start dropping the incoming requests + // since this SIDR endpoint maybe dead or very slow + if (pCEP->PendingCount >= (pCEP->ListenBackLog?pCEP->ListenBackLog:gCmParams.MaxBackLog)) + { + _DBG_ERROR((" Max pending count reached!!! \n", + _DBG_PTR(pCEP), pMad->payload.SIDR_REQ.ServiceID, + pCEP->LocalCommID, pMad->payload.SIDR_REQ.RequestID, + pCEP->PendingCount)); + + Status = FOVERRUN; + goto dropreq; + } + + // Does the user want to be notified + if (! pCEP->bSidrRegisterNotify) + { + // User does not want to be notified. Send the SIDR_RESP. + Status = SendSIDR_RESP(pCEP->SID, + pCEP->LocalEndPoint.QPN, + pCEP->QKey, + SRS_VALID_QPN, + NULL, 0, + pMad->common.TransactionID, + pMad->payload.SIDR_REQ.RequestID, + pRemoteDgrm); + } else { + // Create a new object to represent this SIDR_REQ + pNewCEP = CreateCEP(CM_UD_TYPE, NULL, NULL); + if (pNewCEP == NULL) + { + Status = FINSUFFICIENT_RESOURCES; + goto dropreq; + } + + // Queue the request onto the "registered" object + CepAddToPendingList(pCEP, pNewCEP); + + CepSetState(pNewCEP, CMS_SIDR_REQ_RCVD); + + // Save the request msg to the new CEP obj. + CmDgrmCopyAddrAndMad(pNewCEP->pDgrmElement, pMad, pRemoteDgrm); + + (void)iba_get_ca_for_port(pRemoteDgrm->PortGuid, &pNewCEP->LocalEndPoint.CaGUID); + // Save the request id to reply to + pNewCEP->RemoteCommID = pMad->payload.SIDR_REQ.RequestID; + pNewCEP->TransactionID = pMad->common.TransactionID; + + pNewCEP->SID = pMad->payload.SIDR_REQ.ServiceID; + pNewCEP->PrimaryPath.RemoteLID = pRemoteDgrm->RemoteLID; + if (pRemoteDgrm->GlobalRoute) { + MemoryCopy(pNewCEP->PrimaryPath.RemoteGID.Raw, pRemoteDgrm->GRHInfo.DestGID.Raw, sizeof(IB_GID)); + } + + // Signal the registered object for user callback + SetNotification(pCEP, CME_RCVD_SIDR_REQ); + } + + if (Status == FSUCCESS) + { + _DBG_INFO((" SIDR REQ processed successfully !\n", + _DBG_PTR(pMad), pMad->payload.SIDR_REQ.RequestID, pMad->payload.SIDR_REQ.ServiceID)); + } else { + goto dropreq; + } + +done: + _DBG_FSTATUS_RETURN_LVL(_DBG_LVL_FUNC_TRACE,Status); + return Status; + +dropreq: + _DBG_WARNING((" SIDR REQ dropped - unable to process it! \n", + _DBG_PTR(pMad), pMad->payload.SIDR_REQ.RequestID, + pMad->payload.SIDR_REQ.ServiceID, _DBG_PTR(FSTATUS_MSG(Status)))); + + SendSIDR_RESP(pMad->payload.SIDR_REQ.ServiceID, + 0, 0, + SRS_S_PROVIDER_REJECTED, + NULL, 0, + pMad->common.TransactionID, + pMad->payload.SIDR_REQ.RequestID, + pRemoteDgrm); + _DBG_FSTATUS_RETURN_LVL(_DBG_LVL_FUNC_TRACE,Status); + return Status; +} + +////////////////////////////////////////////////////////////////////////// +// ProcessSidrResp() +// +// +// INPUTS: +// +// +// +// OUTPUTS: +// +// None. +// +// RETURNS: +// +// +// IRQL: +// +// This routine is called at IRQL_PASSIVE_LEVEL. With ListLock held +// + +FSTATUS +ProcessSidrResp( + CM_MAD* pMad, + IBT_DGRM_ELEMENT* pRemoteDgrm + ) +{ + CM_CEP_OBJECT* pCEP=NULL; + FSTATUS Status=FSUCCESS; + CM_MAP_ITEM* pMapEntry; + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, ProcessSidrResp); + + _DBG_INFO((" SIDR_RESP received \n", + _DBG_PTR(pMad), + pMad->payload.SIDR_RESP.RequestID, + pMad->payload.SIDR_RESP.ServiceID)); + + // Determine who received this CM MAD + pMapEntry = CM_MapGet(&gCM->QueryMap, (uint64)pMad->payload.SIDR_RESP.RequestID); + if (pMapEntry == CM_MapEnd(&gCM->QueryMap)) + { + // Not found + _DBG_WARNING((" SIDR RESP dropped - no match found !\n", + _DBG_PTR(pMad), pMad->payload.SIDR_RESP.RequestID, + pMad->payload.SIDR_RESP.ServiceID)); + goto done; + } + pCEP = PARENT_STRUCT(pMapEntry, CM_CEP_OBJECT, MapEntry); + ASSERT(pCEP->State == CMS_SIDR_REQ_SENT); + + Status = PrepareCepDgrm(pCEP); + if (Status != FSUCCESS) + goto fail; + + // Cancel the timer on QUERY + CmTimerStop(pCEP, SIDR_REQ_TIMER); + pCEP->RetryCount = 0; + + // Save the reply msg to the CEP obj. + CmDgrmCopyAddrAndMad(pCEP->pDgrmElement, pMad, pRemoteDgrm); + + // Move from QUERY to IDLE + CM_MapRemoveEntry(&gCM->QueryMap, &pCEP->MapEntry, QUERY_LIST, pCEP); + // ClearEndPoint in CepToIdle is benign + CepToIdle(pCEP);//CepSetState(pCEP, CMS_SIDR_RESP_RCVD); + + SetNotification(pCEP, CME_RCVD_SIDR_RESP); //EventSet(pCEP, CME_RCVD_SIDR_RESP); + _DBG_INFO((" SIDR RESP processed successfully !\n", + _DBG_PTR(pMad), pMad->payload.SIDR_RESP.RequestID, + pMad->payload.SIDR_RESP.ServiceID)); + +done: + _DBG_FSTATUS_RETURN_LVL(_DBG_LVL_FUNC_TRACE,Status); + return Status; + +fail: + _DBG_WARNING((" SIDR RESP dropped - unable to process it! \n", + _DBG_PTR(pMad), pMad->payload.SIDR_RESP.RequestID, + pMad->payload.SIDR_RESP.ServiceID, _DBG_PTR(FSTATUS_MSG(Status)))); + _DBG_FSTATUS_RETURN_LVL(_DBG_LVL_FUNC_TRACE,Status); + return Status; +} + + + +////////////////////////////////////////////////////////////////////////// +// CmTimerCallback() +// +// +// INPUTS: +// +// +// +// OUTPUTS: +// +// None. +// +// RETURNS: +// +// FSUCCESS. +// +// IRQL: +// +// This routine is called at IRQL_PASSIVE_LEVEL. +// +void +CmTimerCallback( + IN void* Context + ) +{ + CM_CEP_OBJECT* pCEP = (CM_CEP_OBJECT*)Context; + CM_MAP_ITEM* pMapEntry; + uint32 timeout_ms; + + FSTATUS Status=FSUCCESS; + + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, CmTimerCallback); + + //_DBG_INFO(("CmTimerCallback() - Curr thread %d\n", GetCurrentThreadId())) + + UNUSED_VAR(Status); + + SpinLockAcquire(&gCM->ListLock); + + // check the map to see if the CEP obj is on it. If the CEP obj is not here, + // ignore this timer callback since the timer has already been canceled. + pMapEntry = CM_MapGet(&gCM->TimerMap, (uint64)(uintn)pCEP); + if (pMapEntry == CM_MapEnd(&gCM->TimerMap)) + { + _DBG_WARNING((" Timer has stopped but the callback got fired. Ignore it! <%s timestamp %"PRIu64"us elapsed %"PRIu64"us>!\n", + _DBG_PTR(pCEP), _DBG_PTR(CmGetStateString(pCEP->State)), + GetTimeStamp(), CmGetElapsedTime(pCEP))); + goto unlock; + } + + if (TimerCallbackStopped(&pCEP->TimerObj)) + goto unlock; // stale timer callback + + // If we previously stop and restart the timer but the timer already fired, we will ignore it here. + /** + if (!CmTimerHasExpired(pCEP)) + { + _DBG_WARNING((" Timer has not expired. Ignore it! <%s timestamp %"PRIu64"us elapsed %"PRIu64"us>!\n", + _DBG_PTR(pCEP), _DBG_PTR(CmGetStateString(pCEP->State)), + GetTimeStamp(), CmGetElapsedTime(pCEP))); + goto unlock; + } + **/ + if (!CmTimerHasExpired(pCEP)) + { + _DBG_WARNING((" Timer has expired before its time! <%s interval %"PRIu64"us elapsed %"PRIu64"us>!\n", + _DBG_PTR(pCEP), _DBG_PTR(CmGetStateString(pCEP->State)), + (uint64)pCEP->timeout_ms*1000, CmGetElapsedTime(pCEP))); + } + + // Reset the timeout interval + CmTimerClear(pCEP); + + switch (pCEP->State) + { + case CMS_REQ_SENT: + case CMS_REP_WAIT: + // + // REQ timeout. Update the retry count and resend the REQ or + // complete the REQ with timeout status + // + _DBG_INFO((" <<\n", + _DBG_PTR(pCEP), pCEP->LocalCommID, + _DBG_PTR(CmGetStateString(pCEP->State)), GetTimeStamp())); + + if (pCEP->RetryCount < pCEP->MaxCMRetries) + { + pCEP->RetryCount++; + ResendREQ(pCEP); + } else { + _DBG_WARNING((" Max REQ retries reached \n", + _DBG_PTR(pCEP), pCEP->LocalCommID, pCEP->RetryCount)); + + if (pCEP->bPeer && pCEP->RemoteEndPoint.CaGUID == 0) + { + CM_MapRemoveEntry(&gCM->ListenMap, &pCEP->MapEntry, LISTEN_LIST, pCEP); + } + + // Send a reject indicating a timeout condition + // TBD include LocalCaGuid in addinfo + SendREJ(RC_TIMEOUT, + CM_REJECT_REPLY, + pCEP->TransactionID, + pCEP->LocalCommID, + pCEP->RemoteCommID, + pCEP->pDgrmElement); + + CepToIdle(pCEP); + pCEP->RetryCount = 0; + SetNotification(pCEP, CME_TIMEOUT_REQ); + } + + break; + + case CMS_REP_SENT: + case CMS_MRA_REP_RCVD: + // + // REP timeout. Update the retry count and resend the REP or + // complete the REP with timeout status + // + _DBG_INFO((" <<\n", + _DBG_PTR(pCEP), pCEP->LocalCommID, + _DBG_PTR(CmGetStateString(pCEP->State)), GetTimeStamp())); + + if (pCEP->RetryCount < pCEP->MaxCMRetries) + { + pCEP->RetryCount++; + ResendREP(pCEP); + } else { + _DBG_WARNING((" Max REP retries reached !\n", + _DBG_PTR(pCEP), pCEP->LocalCommID, pCEP->RetryCount)); + + // Send a reject indicating a timeout condition + SendREJ(RC_TIMEOUT, + CM_REJECT_REQUEST, + pCEP->TransactionID, + pCEP->LocalCommID, + pCEP->RemoteCommID, + pCEP->pDgrmElement); + + CepToTimewait(pCEP); + pCEP->RetryCount = 0; + + if (pCEP->bAsyncAccept && ! pCEP->bTimewaitCallback) + { + SetNotification(pCEP, CME_TIMEOUT_REP); // callback + } else { + // for sync accept we will wakeup CmAccept + // for Timewait, we set the event but defer the callback + // until timewait timer expires + EventSet(pCEP, CME_TIMEOUT_REP, FALSE); + } + } + break; + + case CMS_LAP_SENT: + case CMS_MRA_LAP_RCVD: + // + // LAP timeout. Update the retry count and resend the LAP or + // complete the LAP with timeout status + // + _DBG_INFO((" <<\n", + _DBG_PTR(pCEP), pCEP->LocalCommID, + _DBG_PTR(CmGetStateString(pCEP->State)), + GetTimeStamp())); + + if (pCEP->RetryCount < pCEP->MaxCMRetries) + { + pCEP->RetryCount++; + + // If dgrm is still in use (i.e. send pending), skip the retry + // because pDgrmElement is still on SendQ + // also it is likely the timeout is set too low + if (!CmDgrmIsInUse(pCEP->pDgrmElement)) + { + // The LAP is still valid in here + ASSERT(GsiDgrmGetSendMad(pCEP->pDgrmElement)->common.AttributeID == MCLASS_ATTRIB_ID_LAP ); + + _DBG_INFO((" LAP resend \n", + _DBG_PTR(pCEP), pCEP->LocalCommID, pCEP->RemoteCommID, + pCEP->PrimaryPath.LocalLID, pCEP->PrimaryPath.RemoteLID)); + + Status = CmDgrmSend(pCEP->pDgrmElement); + if (FSUCCESS != Status) + { + // fall through and let timer retry the send later + _DBG_WARN((" DgrmSend() failed for LAP!!! <%s>\n", + _DBG_PTR(pCEP), _DBG_PTR(FSTATUS_MSG(Status)))); + Status = FSUCCESS; + } else { + AtomicIncrementVoid(&gCM->Sent.Lap); + } + } + + CepSetState(pCEP, CMS_LAP_SENT); + // Restart the timer + timeout_ms = TimeoutMultToTimeInMs(pCEP->LocalCMTimeout); + CmTimerStart(pCEP, timeout_ms, LAP_TIMER); + } else { + _DBG_WARNING((" Max LAP retries reached !\n", + _DBG_PTR(pCEP), pCEP->LocalCommID, pCEP->RetryCount)); + + pCEP->bFailoverSupported = FALSE; + pCEP->RetryCount = 0; + CepSetState(pCEP, CMS_ESTABLISHED); + SetNotification(pCEP, CME_TIMEOUT_LAP); // callback + } + break; + + case CMS_DREQ_SENT: + // + // DREQ timeout. Update the retry count and resend the REQ or + // complete the REQ with timeout status + // + _DBG_INFO((" <<\n", + _DBG_PTR(pCEP), pCEP->LocalCommID, GetTimeStamp())); + + if (pCEP->RetryCount < pCEP->MaxCMRetries) + { + pCEP->RetryCount++; + + // If dgrm is still in use (i.e. send pending), skip the retry + // because pDgrmElement is still on SendQ + // also it is likely the timeout is set too low + if (!CmDgrmIsInUse(pCEP->pDgrmElement)) + { + // The DREQ msg is still valid in here + ASSERT(GsiDgrmGetSendMad(pCEP->pDgrmElement)->common.AttributeID == MCLASS_ATTRIB_ID_DREQ ); + + _DBG_INFO((" DREQ resend \n", + _DBG_PTR(pCEP), pCEP->LocalCommID, pCEP->RemoteCommID, + pCEP->PrimaryPath.LocalLID, pCEP->PrimaryPath.RemoteLID)); + + Status = CmDgrmSend(pCEP->pDgrmElement); + if (FSUCCESS != Status) + { + // fall through and let timer retry the send later + _DBG_WARN((" DgrmSend() failed for DREQ!!! <%s>\n", + _DBG_PTR(pCEP), _DBG_PTR(FSTATUS_MSG(Status)))); + Status = FSUCCESS; + } else { + AtomicIncrementVoid(&gCM->Sent.Dreq); + } + } + + // Restart the timer + timeout_ms = TimeoutMultToTimeInMs(pCEP->LocalCMTimeout); + + CmTimerStart(pCEP, timeout_ms, DREQ_TIMER); + } else { + _DBG_WARNING((" Max DREQ retries reached !\n", + _DBG_PTR(pCEP), pCEP->LocalCommID, pCEP->RetryCount)); + + // We hit max retries or we are unable to resend the REQ + CepToTimewait(pCEP); + + // for bTimewaitCallback, we will defer the FCM_DISCONNECTED + // callback until timewait expires + if (! pCEP->bTimewaitCallback) + { + SetNotification(pCEP, CME_TIMEOUT_DREQ); + } + } + break; + + case CMS_TIMEWAIT: + // + // TIMEWAIT expires. Go back to IDLE state. + // + _DBG_INFO((" <<\n", + _DBG_PTR(pCEP), pCEP->LocalCommID, GetTimeStamp())); + + CepToIdle(pCEP); + + // Reset the appropriate fields + + pCEP->LocalCMTimeout = pCEP->RemoteCMTimeout= 0; + pCEP->MaxCMRetries = 0; + pCEP->RetryCount = 0; + + // Is this obj marked for destruction ? + if (BitTest(pCEP->EventFlags, USRE_DESTROY)) + { + // The check here handles the case when the user callback returns + // and this routine gets + // run because the timewait timer expired. + // We let the CmSystemCallback() proceed with the destruction. + if (AtomicRead(&pCEP->CallbackRefCnt) == 0) + { + DestroyCEP(pCEP); + break; + } + } + + // set up for FCM_DISCONNECTED callback to tell user timewait is done + // and QP/CEP can now be reused + if (pCEP->bTimewaitCallback) + { + SetNotification(pCEP, CME_TIMEOUT_TIMEWAIT); + } + break; + + case CMS_SIDR_REQ_SENT: + _DBG_INFO((" <<\n", + _DBG_PTR(pCEP), pCEP->LocalCommID, GetTimeStamp())); + + if (pCEP->RetryCount < pCEP->MaxCMRetries) + { + pCEP->RetryCount++; + // If dgrm is still in use (i.e. send pending), skip the timeout since it is + // likely the timeout is set too low + if (!CmDgrmIsInUse(pCEP->pDgrmElement)) + { + // The SIDR_REQ msg is still valid in here + ASSERT(GsiDgrmGetSendMad(pCEP->pDgrmElement)->common.AttributeID == MCLASS_ATTRIB_ID_SIDR_REQ ); + + _DBG_INFO((" SIDR_REQ resend \n", + _DBG_PTR(pCEP), pCEP->LocalCommID, + pCEP->PrimaryPath.LocalLID, pCEP->PrimaryPath.RemoteLID)); + + Status = CmDgrmSend(pCEP->pDgrmElement); + if (FSUCCESS != Status) + { + // fall through and let timer retry the send later + _DBG_WARN((" DgrmSend() failed for SIDR_REQ!!! <%s>\n", + _DBG_PTR(pCEP), _DBG_PTR(FSTATUS_MSG(Status)))); + Status = FSUCCESS; + } else { + AtomicIncrementVoid(&gCM->Sent.SidrReq); + } + } + // Restart the timer + CmTimerStart(pCEP, SidrTimeout(pCEP), SIDR_REQ_TIMER); + } else { + _DBG_WARNING((" Max SIDR_REQ retries reached !\n", + _DBG_PTR(pCEP), pCEP->LocalCommID, pCEP->RetryCount)); + + // Move from QUERY to IDLE + CM_MapRemoveEntry(&gCM->QueryMap, &pCEP->MapEntry, QUERY_LIST, pCEP); + // ClearEndPoint in CepToIdle is benign + CepToIdle(pCEP); + pCEP->RetryCount = 0; + SetNotification(pCEP, CME_TIMEOUT_SIDR_REQ); //EventSet(pCEP, CME_TIMEOUT_SIDR_REQ); + } + + break; + + default: + _DBG_WARNING((" TIMEOUT not handled < timestamp %"PRIu64"us %s>!\n", + _DBG_PTR(pCEP), GetTimeStamp(), + _DBG_PTR(CmGetStateString(pCEP->State)))); + + break; + } // switch() + +unlock: + SpinLockRelease(&gCM->ListLock); + + _DBG_LEAVE_LVL(_DBG_LVL_FUNC_TRACE); + + return; + +} // CmTimerCallback() + + +////////////////////////////////////////////////////////////////////////// +// CmSystemCallback() +// +// +// INPUTS: +// +// +// +// OUTPUTS: +// +// None. +// +// RETURNS: +// +// FSUCCESS. +// +// IRQL: +// +// This routine is called at IRQL_PASSIVE_LEVEL. +// +void +CmSystemCallback(void *Key, void* Context) +{ + CM_CEP_OBJECT* pCEP=(CM_CEP_OBJECT*)Context; + + PFN_CM_CALLBACK pfnUserCB=NULL; + + CM_CONN_INFO *ConnInfo = NULL; + FSTATUS Status=FSUCCESS; + + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, CmSystemCallback); + + + _DBG_INFO((" System callback item dequeued. <%s cb item 0x%p cb refcnt %d>\n", + _DBG_PTR(pCEP), _DBG_PTR(CmGetStateString(pCEP->State)), + _DBG_PTR(pCEP->pCallbackItem), AtomicRead(&pCEP->CallbackRefCnt))); + + SpinLockAcquire(&gCM->ListLock); + + if (BitTest(pCEP->EventFlags, USRE_DESTROY)) + { + _DBG_WARNING((" Object marked for destruction - skip callback <%s>\n", + _DBG_PTR(pCEP), _DBG_PTR(CmGetStateString(pCEP->State)))); + + pfnUserCB = NULL; + } else { + ConnInfo = (CM_CONN_INFO*)MemoryAllocateAndClear(sizeof(*ConnInfo), FALSE, CM_MEM_TAG); + if (ConnInfo) + { + // Get the connection info + Status = GetConnInfo(pCEP, ConnInfo); + + if (Status != FSUCCESS) + { + // Skip the callback since GetConnInfo() failed (i.e. no status to report) + _DBG_WARNING((" No status to report - skip callback <%s>\n", + _DBG_PTR(pCEP), _DBG_PTR(CmGetStateString(pCEP->State)))); + + pfnUserCB = NULL; + } else { + // Save the callback func here before we release the lock + pfnUserCB = pCEP->pfnUserCallback; + } + } else { + // Skip the callback since GetConnInfo() failed (i.e. no status to report) + _DBG_WARN((" No status to report - skip callback <%s> - no memory\n", + _DBG_PTR(pCEP), _DBG_PTR(CmGetStateString(pCEP->State)))); + + pfnUserCB = NULL; + } + } + + SpinLockRelease(&gCM->ListLock); + + // there is a race here, since we have released the Lock, it is possible + // for user to Destroy the CEP here and race with this callback, in which + // case the callback hits the user after CmDestroyCEP has returned + // to the user. We can't hold the lock during the callback since that + // would prevent user from making Cm calls in their callback. + // however we cannot prevent CmDestroyCEP from being called before or during + // user callback + if (pfnUserCB) + { + _DBG_INFO((" Calling user callback...<%s %s context 0x%p>\n", + _DBG_PTR(pCEP), _DBG_PTR(CmGetStateString(pCEP->State)), + _DBG_PTR(FSTATUS_MSG(ConnInfo->Status)), _DBG_PTR(pCEP->UserContext))); + + pfnUserCB(pCEP, ConnInfo, pCEP->UserContext); + + _DBG_INFO((" Returning from user callback <%s>\n", + _DBG_PTR(pCEP), _DBG_PTR(CmGetStateString(pCEP->State)))); + } else { + _DBG_WARNING((" User callback function is NULL. Skip callback\n", _DBG_PTR(pCEP))); + } + if (ConnInfo) + { + MemoryDeallocate(ConnInfo); + } + + CmDoneCallback(pCEP); + _DBG_LEAVE_LVL(_DBG_LVL_FUNC_TRACE); + +} // CmSystemCallback() + +// decrement counters to reflect we completed present callback +// then check to see if there are more queued callbacks on the CEP +// if so schedule them +void +CmDoneCallback(CM_CEP_OBJECT* pCEP) +{ + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, ProcessQueuedCallbacks); + + // Determine if there is another callback pending + SpinLockAcquire(&gCM->ListLock); + + // Decrement the ref cnt to indicate no callback in progress + AtomicDecrementVoid(&pCEP->CallbackRefCnt); + AtomicDecrementVoid(&gCM->TotalCallbackRefCnt); + + // Is this obj marked for destruction ? + if (BitTest(pCEP->EventFlags, USRE_DESTROY)) + { + // Allow the caller to know that there is no callback event pending during unload process + if (pCEP->pCallbackEvent) + EventTrigger(pCEP->pCallbackEvent); + + AtomicWrite(&pCEP->CallbackRefCnt, 0); // we will start no more + if (pCEP->State == CMS_IDLE) + { + DestroyCEP(pCEP); + } else { + _DBG_WARNING((" Cannot destroy CEP obj in this state <%s cb refcnt %d>\n", + _DBG_PTR(pCEP), _DBG_PTR(CmGetStateString(pCEP->State)), + AtomicRead(&pCEP->CallbackRefCnt))); + } + } else { + // If there are still outstanding callback, queue the callback item + if (AtomicRead(&pCEP->CallbackRefCnt)) + { + _DBG_INFO((" Queuing callback item .\n", + _DBG_PTR(pCEP), _DBG_PTR(pCEP->pCallbackItem), + AtomicRead(&pCEP->CallbackRefCnt))); + + EventClear(&gCM->CallbackEventObj); + + if (pCEP->pCallbackEvent) + EventClear(pCEP->pCallbackEvent); + + AtomicIncrementVoid(&gCM->TotalCallbackRefCnt); + + // Queue the work item for user callback + SysCallbackQueue(pCEP->pCallbackItem, CmSystemCallback, pCEP, FALSE ); + } else { + _DBG_INFO((" No callback pending \n", + _DBG_PTR(pCEP), _DBG_PTR(pCEP->pCallbackItem), + AtomicRead(&pCEP->CallbackRefCnt))); + + // Allow the caller to know that there is no callback event pending during unload process + if (pCEP->pCallbackEvent) + EventTrigger(pCEP->pCallbackEvent); + } + } + + if (AtomicRead(&gCM->TotalCallbackRefCnt) == 0) + { + EventTrigger(&gCM->CallbackEventObj); + } + + SpinLockRelease(&gCM->ListLock); + _DBG_LEAVE_LVL(_DBG_LVL_FUNC_TRACE); +} + +// Make sure pCEP->pDgrmElement is available to retain a new message +// If its still busy (send in progress), we release the Dgrm (Send completion +// will free it) and get a new Dgrm for the CEP +// We do a GsiDgrmAddrCopy, however most callers of this +// function will copy over that address, however a few callers require the +// address to be copied. So its simpler to do the extra +// copy to reduce duplicate code. +FSTATUS +PrepareCepDgrm(CM_CEP_OBJECT* pCEP) +{ + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, PrepareCepDgrm); + + if (CmDgrmIsInUse(pCEP->pDgrmElement)) + { + IBT_DGRM_ELEMENT* pNewDgrm; + + _DBG_WARNING((" Dgrm is in use. Get a new one! \n", + _DBG_PTR(pCEP), _DBG_PTR(pCEP->pDgrmElement))); + pNewDgrm = CmDgrmGet(); + if (!pNewDgrm) + { + /* CmDgrmGet already output an error, caller will provide any further information */ + return FINSUFFICIENT_RESOURCES; + } + CmDgrmSetReleaseFlag(pCEP->pDgrmElement); + GsiDgrmAddrCopy(pNewDgrm, pCEP->pDgrmElement); + pCEP->pDgrmElement = pNewDgrm; + } + _DBG_LEAVE_LVL(_DBG_LVL_FUNC_TRACE); + return FSUCCESS; +} + +/* log messages to indicate why a CmDgrmGet Failed */ +void +CmDgrmGetFailed(void) +{ + uint32 savelast; + static uint32 lasttime = 0; + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, CmDgrmGetFailed); + /* to avoid flooding the log when huge app startup fails, we + * limit output of this message to 1 per second + */ + /* there is a possible race here, but on most systems assignment of + * uint32 is atomic, and worse case we output some extra log messages + * in addition the CM global lock should protect us + */ + savelast = lasttime; + lasttime = GetTimeStampSec(); + if (savelast != lasttime) { + uint32 total = iba_gsi_dgrm_pool_total(gCM->GSADgrmPoolHandle); + if (total < gCmParams.MaxDgrms) { + _DBG_ERROR(("CmDgrmGet: Temporarily Out of CM Dgrms: Allocated: %u CmMinFreeDgrms: %u CmDgrmIncrement: %u CmDgrmPreallocDgrms: %u\nThis error can be caused by excessive application connections or inadequate configuration of above values\n", + total, gCmParams.MinFreeDgrms, gCmParams.DgrmIncrement, + gCmParams.PreallocDgrms)); + } else { + _DBG_ERROR(("CmDgrmGet: Out of CM Dgrms, reached CmMaxDgrms limit of %u\nThis error can be caused by excessive application connections or inadequate configuration of CmMaxDgrms\n", gCmParams.MaxDgrms)); + } + } + _DBG_LEAVE_LVL(_DBG_LVL_FUNC_TRACE); +} + +////////////////////////////////////////////////////////////////////////// +// SendREJ() +// +// +// INPUTS: +// +// +// +// OUTPUTS: +// +// None. +// +// RETURNS: +// +// FSUCCESS. +// +// IRQL: +// +// This routine is called at IRQL_PASSIVE_LEVEL. +// +FSTATUS +SendREJ(CM_REJECTION_CODE Reason, + CMM_REJ_MSGTYPE MsgRejected, + uint64 TransactionID, + uint32 LocalCommID, + uint32 RemoteCommID, + IBT_DGRM_ELEMENT* pRemoteDgrm) +{ + FSTATUS Status=FSUCCESS; + IBT_DGRM_ELEMENT* pDgrmElement=NULL; + + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, SendREJ); + + // Send a reject + pDgrmElement = CmDgrmGet(); + if (!pDgrmElement) + { + _DBG_WARNING(("failed to send REJ: Out of CM Dgrms!\n")); + Status = FINSUFFICIENT_RESOURCES; + goto fail; + } + + GsiDgrmAddrCopy(pDgrmElement, pRemoteDgrm); + + // Format the REJ msg + FormatREJ((CM_MAD*)GsiDgrmGetSendMad(pDgrmElement), + (uint8)MsgRejected, + (uint16)Reason, + NULL, 0, + NULL, 0, + TransactionID, + LocalCommID, + RemoteCommID); + + // In SendComplete(), we return the dgrm to the pool + Status = CmDgrmSendAndRelease(pDgrmElement); + if (Status == FSUCCESS) + { + if (MsgRejected == CM_REJECT_REQUEST) + AtomicIncrementVoid(&gCM->Sent.RejReq); + else + AtomicIncrementVoid(&gCM->Sent.RejRep); +#ifdef ICS_LOGGING + _DBG_INFO((" REJ sent rejecting %s .\n", + _DBG_PTR(pDgrmElement), + _DBG_PTR((MsgRejected == CM_REJECT_REQUEST)?"REQ":"REP"), + LocalCommID, RemoteCommID, pRemoteDgrm->RemoteLID)); + + _DBG_INFO((" REJ sent rejecting %s reason %d %s\n", + _DBG_PTR(pDgrmElement), + _DBG_PTR((MsgRejected == CM_REJECT_REQUEST)?"REQ":"REP"), + Reason, _DBG_PTR(FSTATUS_MSG(Status)))); +#else + _DBG_INFO((" REJ sent rejecting %s .\n", + _DBG_PTR(pDgrmElement), + _DBG_PTR((MsgRejected == CM_REJECT_REQUEST)?"REQ":"REP"), + LocalCommID, RemoteCommID, pRemoteDgrm->RemoteLID, + Reason, _DBG_PTR(FSTATUS_MSG(Status)))); +#endif + + } else { + + _DBG_WARN((" DgrmSend() failed!!! Unable to send REJ .\n", + _DBG_PTR(pDgrmElement), LocalCommID, RemoteCommID, + pRemoteDgrm->RemoteLID, Reason, _DBG_PTR(FSTATUS_MSG(Status)))); + + CmDgrmPut(pDgrmElement); + } + + // In SendComplete(), we return the dgrm to the pool +fail: + _DBG_LEAVE_LVL(_DBG_LVL_FUNC_TRACE); + + return Status; + +} // SendREJ() + + +////////////////////////////////////////////////////////////////////////// +// SendMRA() +// +// +// INPUTS: +// +// +// +// OUTPUTS: +// +// None. +// +// RETURNS: +// +// FSUCCESS. +// +// IRQL: +// +// This routine is called at IRQL_PASSIVE_LEVEL. +// +FSTATUS +SendMRA(CMM_MRA_MSGTYPE MsgMraed, + uint8 ServiceTimeout, + uint64 TransactionID, + uint32 LocalCommID, + uint32 RemoteCommID, + IBT_DGRM_ELEMENT* pRemoteDgrm) +{ + FSTATUS Status=FSUCCESS; + IBT_DGRM_ELEMENT* pDgrmElement=NULL; + + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, SendMRA); + + // Send a mra + pDgrmElement = CmDgrmGet(); + if (!pDgrmElement) + { + _DBG_WARNING(("failed to send MRA: Out of CM Dgrms!\n")); + Status = FINSUFFICIENT_RESOURCES; + goto fail; + } + + GsiDgrmAddrCopy(pDgrmElement, pRemoteDgrm); + + // Format the MRA msg + FormatMRA((CM_MAD*)GsiDgrmGetSendMad(pDgrmElement), + (uint8)MsgMraed, + (uint8)ServiceTimeout, + NULL, 0, + TransactionID, + LocalCommID, + RemoteCommID); + + // In SendComplete(), we return the dgrm to the pool + Status = CmDgrmSendAndRelease(pDgrmElement); + if (Status == FSUCCESS) + { + if (MsgMraed == CM_MRA_REQUEST) + AtomicIncrementVoid(&gCM->Sent.MraReq); + else if (MsgMraed == CM_MRA_REPLY) + AtomicIncrementVoid(&gCM->Sent.MraRep); + else + AtomicIncrementVoid(&gCM->Sent.MraLap); +#ifdef ICS_LOGGING + _DBG_INFO((" MRA sent on %s .\n", + _DBG_PTR(pDgrmElement), + _DBG_PTR((MsgMraed == CM_MRA_REQUEST)?"REQ":"REP"), + LocalCommID, RemoteCommID, pRemoteDgrm->RemoteLID, ServiceTimeout)); + _DBG_INFO((" MRA sent on %s <%s>.\n", + _DBG_PTR(pDgrmElement), + _DBG_PTR((MsgMraed == CM_MRA_REQUEST)?"REQ":"REP"), + _DBG_PTR(FSTATUS_MSG(Status)))); + +#else + _DBG_INFO((" MRA sent on %s .\n", + _DBG_PTR(pDgrmElement), + _DBG_PTR((MsgMraed == CM_MRA_REQUEST)?"REQ":"REP"), + LocalCommID, RemoteCommID, pRemoteDgrm->RemoteLID, + ServiceTimeout, _DBG_PTR(FSTATUS_MSG(Status)))); +#endif + } else { + _DBG_WARN((" DgrmSend() failed!!! Unable to send MRA .\n", + _DBG_PTR(pDgrmElement), LocalCommID, RemoteCommID, + pRemoteDgrm->RemoteLID, ServiceTimeout, _DBG_PTR(FSTATUS_MSG(Status)))); + + CmDgrmPut(pDgrmElement); + } + + // In SendComplete(), we return the dgrm to the pool +fail: + _DBG_LEAVE_LVL(_DBG_LVL_FUNC_TRACE); + + return Status; +} // SendMRA() + +////////////////////////////////////////////////////////////////////////// +// ResendREQ() +// +// +// INPUTS: +// +// +// +// OUTPUTS: +// +// None. +// +// RETURNS: +// +// FSUCCESS. +// +// IRQL: +// +// This routine is called at IRQL_PASSIVE_LEVEL. +// +FSTATUS +ResendREQ(IN CM_CEP_OBJECT* pCEP) +{ + FSTATUS Status = FSUCCESS; + uint32 timeout_ms; + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, ResendREQ); + + // If dgrm is still in use (i.e. send pending), skip the retry + // because pDgrmElement is still on SendQ + // If this is not active Active Peer, it's likely the timeout is set too low + // We will let the timer try again later + if (!CmDgrmIsInUse(pCEP->pDgrmElement)) + { + // The REQ is still valid in here + ASSERT(GsiDgrmGetSendMad(pCEP->pDgrmElement)->common.AttributeID == MCLASS_ATTRIB_ID_REQ ); + + _DBG_WARNING((" REQ resend !\n", + _DBG_PTR(pCEP), pCEP->LocalCommID, pCEP->RetryCount)); + + Status = CmDgrmSend(pCEP->pDgrmElement); + if (FSUCCESS != Status) + { + // fall through and let timer retry the send later + _DBG_WARN((" DgrmSend() failed for REQ!!! <%s>\n", + _DBG_PTR(pCEP), _DBG_PTR(FSTATUS_MSG(Status)))); + Status = FSUCCESS; + } else { + AtomicIncrementVoid(&gCM->Sent.Req); + } + } + + CepSetState(pCEP, CMS_REQ_SENT); + + // Restart the timer + timeout_ms = TimeoutMultToTimeInMs(pCEP->LocalCMTimeout); + CmTimerStart(pCEP, timeout_ms, REQ_TIMER); + + _DBG_LEAVE_LVL(_DBG_LVL_FUNC_TRACE); + return Status; +} + + +////////////////////////////////////////////////////////////////////////// +// ResendREP() +// +// +// INPUTS: +// +// +// +// OUTPUTS: +// +// None. +// +// RETURNS: +// +// FSUCCESS. +// +// IRQL: +// +// This routine is called at IRQL_PASSIVE_LEVEL. +// +FSTATUS +ResendREP(IN CM_CEP_OBJECT* pCEP) +{ + FSTATUS Status = FSUCCESS; + uint32 timeout_ms; + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, ResendREP); + + // If dgrm is still in use (i.e. send pending), skip the retry + // because pDgrmElement is still on SendQ + // also it is likely the timeout is set too low + if (!CmDgrmIsInUse(pCEP->pDgrmElement)) + { + // The REP is still valid in here + ASSERT(GsiDgrmGetSendMad(pCEP->pDgrmElement)->common.AttributeID == MCLASS_ATTRIB_ID_REP ); + + _DBG_INFO((" REP resend \n", + _DBG_PTR(pCEP), pCEP->LocalCommID, pCEP->RemoteCommID, + pCEP->PrimaryPath.LocalLID, pCEP->PrimaryPath.RemoteLID)); + + Status = CmDgrmSend(pCEP->pDgrmElement); + if (FSUCCESS != Status) + { + // fall through and let timer retry the send later + _DBG_WARN((" DgrmSend() failed for REP!!! <%s>\n", + _DBG_PTR(pCEP), _DBG_PTR(FSTATUS_MSG(Status)))); + Status = FSUCCESS; + } else { + AtomicIncrementVoid(&gCM->Sent.Rep); + } + } + + CepSetState(pCEP, CMS_REP_SENT); + // Restart the timer + timeout_ms = TimeoutMultToTimeInMs(pCEP->LocalCMTimeout); + CmTimerStart(pCEP, timeout_ms, REP_TIMER); + + _DBG_LEAVE_LVL(_DBG_LVL_FUNC_TRACE); + return Status; +} + +////////////////////////////////////////////////////////////////////////// +// SendRTU() +// +// +// INPUTS: +// +// +// +// OUTPUTS: +// +// None. +// +// RETURNS: +// +// FSUCCESS. +// +// IRQL: +// +// This routine is called at IRQL_PASSIVE_LEVEL. +// +FSTATUS +SendRTU(uint64 TransactionID, + uint32 LocalCommID, + uint32 RemoteCommID, + IBT_DGRM_ELEMENT* pRemoteDgrm) +{ + FSTATUS Status=FSUCCESS; + IBT_DGRM_ELEMENT* pDgrmElement=NULL; + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, SendRTU); + + pDgrmElement = CmDgrmGet(); + if (!pDgrmElement) + { + _DBG_WARNING(("failed to send RTU: Out of CM Dgrms!\n")); + Status = FINSUFFICIENT_RESOURCES; + goto fail; + } + + GsiDgrmAddrCopy(pDgrmElement, pRemoteDgrm); + + // RTU with no private data + FormatRTU((CM_MAD*)GsiDgrmGetSendMad(pDgrmElement), + NULL, + 0, + TransactionID, + LocalCommID, + RemoteCommID); + + // In SendComplete(), we return the dgrm to the pool + Status = CmDgrmSendAndRelease(pDgrmElement); + if (Status == FSUCCESS) + { + AtomicIncrementVoid(&gCM->Sent.Rtu); + _DBG_INFO((" RTU sent .\n", + _DBG_PTR(pDgrmElement), + LocalCommID, RemoteCommID, pRemoteDgrm->RemoteLID)); + } else { + _DBG_ERROR((" DgrmSend() failed!!! Unable to send RTU .\n", + _DBG_PTR(pDgrmElement), LocalCommID, RemoteCommID, + pRemoteDgrm->RemoteLID, _DBG_PTR(FSTATUS_MSG(Status)))); + + CmDgrmPut(pDgrmElement); + } + + // In SendComplete(), we return the dgrm to the pool +fail: + _DBG_LEAVE_LVL(_DBG_LVL_FUNC_TRACE); + + return Status; + +} // SendRTU() + +////////////////////////////////////////////////////////////////////////// +// SendAPR() +// Send an APR to reject an inbound LAP +// +// +// INPUTS: +// +// +// +// OUTPUTS: +// +// None. +// +// RETURNS: +// +// FSUCCESS. +// +// IRQL: +// +// This routine is called at IRQL_PASSIVE_LEVEL. +// +FSTATUS +SendAPR(CM_APR_STATUS APStatus, + uint64 TransactionID, + uint32 LocalCommID, + uint32 RemoteCommID, + IBT_DGRM_ELEMENT* pRemoteDgrm) +{ + FSTATUS Status=FSUCCESS; + IBT_DGRM_ELEMENT* pDgrmElement=NULL; + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, SendAPR); + + // Send an APR + pDgrmElement = CmDgrmGet(); + if (!pDgrmElement) + { + _DBG_WARNING(("failed to send APR: Out of CM Dgrms!\n")); + Status = FINSUFFICIENT_RESOURCES; + goto fail; + } + + GsiDgrmAddrCopy(pDgrmElement, pRemoteDgrm); + + // Format the APR msg + FormatAPR((CM_MAD*)GsiDgrmGetSendMad(pDgrmElement), + APStatus, + NULL, 0, + NULL, 0, + TransactionID, + LocalCommID, + RemoteCommID); + + // In SendComplete(), we return the dgrm to the pool + Status = CmDgrmSendAndRelease(pDgrmElement); + if (Status == FSUCCESS) + { + if (APStatus == APS_PATH_LOADED) + AtomicIncrementVoid(&gCM->Sent.AprAcc); + else + AtomicIncrementVoid(&gCM->Sent.AprRej); + _DBG_INFO((" APR sent .\n", + _DBG_PTR(pDgrmElement), + LocalCommID, RemoteCommID, pRemoteDgrm->RemoteLID, + APStatus, _DBG_PTR(FSTATUS_MSG(Status)))); + + } else { + + _DBG_ERROR((" DgrmSend() failed!!! Unable to send APR .\n", + _DBG_PTR(pDgrmElement), LocalCommID, RemoteCommID, + pRemoteDgrm->RemoteLID, APStatus, _DBG_PTR(FSTATUS_MSG(Status)))); + + CmDgrmPut(pDgrmElement); + } + + // In SendComplete(), we return the dgrm to the pool +fail: + _DBG_LEAVE_LVL(_DBG_LVL_FUNC_TRACE); + + return Status; + +} // SendAPR() + +////////////////////////////////////////////////////////////////////////// +// SendSIDR_RESP() +// +// +// INPUTS: +// +// +// +// OUTPUTS: +// +// None. +// +// RETURNS: +// +// FSUCCESS. +// +// IRQL: +// +// This routine is called at IRQL_PASSIVE_LEVEL. +// +FSTATUS +SendSIDR_RESP(IN uint64 SID, + uint32 QPN, + uint32 QKey, + uint32 SIDRStatus, + const uint8* pPrivateData, + uint32 DataLen, + uint64 TransactionID, + uint32 RequestID, + IBT_DGRM_ELEMENT* pRemoteDgrm) +{ + FSTATUS Status=FSUCCESS; + IBT_DGRM_ELEMENT* pDgrmElement=NULL; + + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, SendSIDR_RESP); + + // Get a MAD datagram + pDgrmElement = CmDgrmGet(); + if (!pDgrmElement) + { + _DBG_WARNING(("failed to send SIDR_RESP: Out of CM Dgrms!\n")); + Status = FINSUFFICIENT_RESOURCES; + goto fail; + } + + // Setup the dgrm's dest addr + GsiDgrmAddrCopy(pDgrmElement, pRemoteDgrm); + + // Format the REJ msg + FormatSIDR_RESP((CM_MAD*)GsiDgrmGetSendMad(pDgrmElement), + SID, + QPN, + QKey, + SIDRStatus, + pPrivateData, + DataLen, + TransactionID, + RequestID); + + // In SendComplete(), we return the dgrm to the pool + Status = CmDgrmSendAndRelease(pDgrmElement); + if (Status == FSUCCESS) + { + AtomicIncrementVoid(&gCM->Sent.SidrResp); +#ifdef ICS_LOGGING + _DBG_INFO((" SIDR_RESP sent .\n", + _DBG_PTR(pDgrmElement), RequestID, SID, pRemoteDgrm->RemoteLID, QPN, QKey)); + _DBG_INFO((" SIDR_RESP sent .\n", + _DBG_PTR(pDgrmElement), RequestID, SIDRStatus, _DBG_PTR(FSTATUS_MSG(Status)))); + +#else + _DBG_INFO((" SIDR_RESP sent .\n", + _DBG_PTR(pDgrmElement), RequestID, SID, pRemoteDgrm->RemoteLID, QPN, + QKey, SIDRStatus, _DBG_PTR(FSTATUS_MSG(Status)))); +#endif + + } else { +#ifdef ICS_LOGGING + _DBG_WARN((" DgrmSend() failed!!! Unable to send SIDR_RESP .\n", + _DBG_PTR(pDgrmElement), RequestID, SID, pRemoteDgrm->RemoteLID, QPN, QKey )); + _DBG_WARN((" DgrmSend() failed!!! Unable to send SIDR_RESP .\n", + _DBG_PTR(pDgrmElement), RequestID, SIDRStatus, _DBG_PTR(FSTATUS_MSG(Status)))); + +#else + _DBG_WARN((" DgrmSend() failed!!! Unable to send SIDR_RESP .\n", + _DBG_PTR(pDgrmElement), RequestID, SID, pRemoteDgrm->RemoteLID, + QPN, QKey, SIDRStatus, _DBG_PTR(FSTATUS_MSG(Status)))); +#endif + CmDgrmPut(pDgrmElement); + } + + // In SendComplete(), we return the dgrm to the pool +fail: + _DBG_LEAVE_LVL(_DBG_LVL_FUNC_TRACE); + + return Status; + +} // SendSIDR_RESP() + +////////////////////////////////////////////////////////////////////////// +// SendDREQ() +// +// +// INPUTS: +// +// +// +// OUTPUTS: +// +// None. +// +// RETURNS: +// +// FSUCCESS. +// +// IRQL: +// +// This routine is called at IRQL_PASSIVE_LEVEL. +// +FSTATUS +SendDREQ(uint32 QPN, + uint64 TransactionID, + uint32 LocalCommID, + uint32 RemoteCommID, + IBT_DGRM_ELEMENT* pRemoteDgrm) +{ + FSTATUS Status=FSUCCESS; + IBT_DGRM_ELEMENT* pDgrmElement=NULL; + + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, SendDREQ); + + // Get a dgrm + pDgrmElement = CmDgrmGet(); + if (!pDgrmElement) + { + _DBG_WARNING(("failed to send DREQ: Out of CM Dgrms!\n")); + Status = FINSUFFICIENT_RESOURCES; + goto fail; + } + + // Setup the dgrm's dest addr + GsiDgrmAddrCopy(pDgrmElement, pRemoteDgrm); + + // Format the DREQ + FormatDREQ((CM_MAD*)GsiDgrmGetSendMad(pDgrmElement), + QPN, + NULL, 0, + TransactionID, + LocalCommID, + RemoteCommID); + + // Release back to the pool when send complete. + Status = CmDgrmSendAndRelease(pDgrmElement); + if (Status == FSUCCESS) + { + AtomicIncrementVoid(&gCM->Sent.Dreq); + _DBG_INFO((" DREQ sent .\n", + _DBG_PTR(pDgrmElement), LocalCommID, RemoteCommID, pRemoteDgrm->RemoteLID)); + } else { + _DBG_WARN((" DgrmSend() failed!!! Unable to send DREQ .\n", + _DBG_PTR(pDgrmElement), LocalCommID, RemoteCommID, pRemoteDgrm->RemoteLID)); + + CmDgrmPut(pDgrmElement); + } + + // In SendComplete(), we return the dgrm to the pool +fail: + _DBG_LEAVE_LVL(_DBG_LVL_FUNC_TRACE); + + return Status; + +} // SendDREQ() + + +////////////////////////////////////////////////////////////////////////// +// SendDREP() +// +// +// INPUTS: +// +// +// +// OUTPUTS: +// +// None. +// +// RETURNS: +// +// FSUCCESS. +// +// IRQL: +// +// This routine is called at IRQL_PASSIVE_LEVEL. +// +FSTATUS +SendDREP( uint64 TransactionID, + uint32 LocalCommID, + uint32 RemoteCommID, + IBT_DGRM_ELEMENT* pRemoteDgrm) +{ + FSTATUS Status=FSUCCESS; + IBT_DGRM_ELEMENT* pDgrmElement=NULL; + + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, SendDREP); + + // Get a dgrm + pDgrmElement = CmDgrmGet(); + if (!pDgrmElement) + { + _DBG_WARNING(("failed to send DREP: Out of CM Dgrms!\n")); + Status = FINSUFFICIENT_RESOURCES; + goto fail; + } + + // Setup the dgrm's dest addr + GsiDgrmAddrCopy(pDgrmElement, pRemoteDgrm); + + // Format the DREP + FormatDREP((CM_MAD*)GsiDgrmGetSendMad(pDgrmElement), + NULL, 0, + TransactionID, + LocalCommID, + RemoteCommID); + + // Release back to the pool when send complete. + Status = CmDgrmSendAndRelease(pDgrmElement); + if (Status == FSUCCESS) + { + AtomicIncrementVoid(&gCM->Sent.Drep); + _DBG_INFO((" DREP sent .\n", + _DBG_PTR(pDgrmElement), LocalCommID, RemoteCommID, pRemoteDgrm->RemoteLID)); + } else { + _DBG_WARN((" DgrmSend() failed!!! Unable to send DREP .\n", + _DBG_PTR(pDgrmElement), LocalCommID, RemoteCommID, pRemoteDgrm->RemoteLID)); + + CmDgrmPut(pDgrmElement); + } + + // In SendComplete(), we return the dgrm to the pool +fail: + _DBG_FSTATUS_RETURN_LVL(_DBG_LVL_FUNC_TRACE,Status); + return Status; + +} // SendDREP() + + +////////////////////////////////////////////////////////////////////////// +// SetNotification() +// +// Notify consumer of an event. If there is a user callback function, we +// will trigger a system callback. If there is no user callback function we +// will Trigger the event and allow the user to wait for it. +// +// INPUTS: +// +// +// +// OUTPUTS: +// +// None. +// +// RETURNS: +// +// FSUCCESS. +// +// IRQL: +// +// This routine is called at IRQL_PASSIVE_LEVEL. +// +boolean +SetNotification(CM_CEP_OBJECT* pCEP, uint32 EventType) +{ + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, SetNotification); + + // If this obj is marked for destruction, no need to notify + if (BitTest(pCEP->EventFlags, USRE_DESTROY)) + { + _DBG_LEAVE_LVL(_DBG_LVL_FUNC_TRACE); + + return FALSE; + } + + if (pCEP->pfnUserCallback) + { + // kernel mode consumer w/callback + BitSet(pCEP->EventFlags, EventType); + + // Increment the ref cnt so that we dont delete this obj + AtomicIncrementVoid(&pCEP->CallbackRefCnt); + + // Allow only 1 callback outstanding per CEP obj. This also serialize the + // callback notification per CEP + if (AtomicRead(&pCEP->CallbackRefCnt) == 1) + { + EventClear(&gCM->CallbackEventObj); + + if (pCEP->pCallbackEvent) + EventClear(pCEP->pCallbackEvent); + + AtomicIncrementVoid(&gCM->TotalCallbackRefCnt); + + // Queue the callback item for user callback + SysCallbackQueue(pCEP->pCallbackItem, CmSystemCallback, pCEP, FALSE ); + + _DBG_INFO((" Queuing callback item .\n", + _DBG_PTR(pCEP), _DBG_PTR(pCEP->pCallbackItem), + AtomicRead(&pCEP->CallbackRefCnt))); + } else { + _DBG_INFO((" There is already a callback outstanding .\n", + _DBG_PTR(pCEP), _DBG_PTR(pCEP->pCallbackItem), + AtomicRead(&pCEP->CallbackRefCnt))); + } + } + else + { + // user mode consumer or non-callback model + EventSet(pCEP, EventType, TRUE); + } + + _DBG_LEAVE_LVL(_DBG_LVL_FUNC_TRACE); + + return TRUE; + +} // SetNotification() + +// ListenMap Key Compare functions +// Three functions are provided: +// +// CepListenAddrCompare - is used to insert cep entries into the ListenMap and +// is the primary key_compare function for the ListenMap +// +// CepReqAddrCompare - is used to search the ListenMap as part of processing +// an inbound REQ +// +// CepSidrReqAddrCompare - is used to search the ListenMap as part of +// processing an inbound SIDR_REQ +// +// To provide the maximum flexibilty, the key for a CEP bound address is +// sophisticated and allows wildcarded/optional fields. This allows +// a listener to simply bind for all traffic of a given SID or to refine the +// scope by binding for traffic to/from specific addresses, or specific +// private data. The QPN/EECN/CaGUID aspect is used to allow multiple +// outbound Peer Connects to still be considered unique. +// +// The result of this approach is very flexible CM bind. The same SID +// can be used on different ports or between different node pairs for +// completely different meanings. However a SID used between a given +// pair of nodes must be used for a single model (Listen, Peer, Sidr) +// In addition for Peer connects, each connect must have a unique +// QPN/EECN/CaGUID. +// +// Comparision allows for wildcarding in all but SID +// A value of 0 is a wildcard. See ib_helper.h:WildcardGidCompare for +// the rules of GID comparision, which are more involved due to multiple Gid +// formats +// +// Field is Used by models as follows: +// Coallating order is: Listen Peer Connect Sidr Register +// SID Y Y Y +// local GID option Y future option +// local LID option Y future option +// QPN wildcard Y wildcard +// EECN wildcard Y wildcard +// CaGUID wildcard Y wildcard +// remote GID option Y future option +// remote LID option Y future option +// private data discriminator length option option option +// private data discriminator value option option option +// +// if bPeer is 0 for either CEP, the QPN, EECN and CaGUID are treated as a match +// +// FUTURE: add a sid masking option so can easily listen on a group +// of SIDs with 1 listen (such as if low bits of sid have a private meaning) +// +// FUTURE: add a pkey option so can easily listen on a partition +// +// FUTURE: for SIDR to support GID/LID they will have to come from the LRH +// and GRH headers to the CM mad. local GID and lid could be used to merely +// select the local port number + + +// A qmap key_compare function to compare the bound address for +// two listener, SIDR or Peer Connect CEPs +// +// key1 - CEP1 pointer +// key2 - CEP2 pointer +// +// Returns: +// -1: cep1 bind address < cep2 bind address +// 0: cep1 bind address = cep2 bind address (accounting for wildcards) +// 1: cep1 bind address > cep2 bind address +int +CepListenAddrCompare(uint64 key1, uint64 key2) +{ + IN CM_CEP_OBJECT* pCEP1 = (CM_CEP_OBJECT*)(uintn)key1; + IN CM_CEP_OBJECT* pCEP2 = (CM_CEP_OBJECT*)(uintn)key2; + int res; + + if (pCEP1->SID < pCEP2->SID) + return -1; + else if (pCEP1->SID > pCEP2->SID) + return 1; + res = WildcardGidCompare(&pCEP1->PrimaryPath.LocalGID, &pCEP2->PrimaryPath.LocalGID); + if (res != 0) + return res; + res = WildcardCompareU64(pCEP1->PrimaryPath.LocalLID, pCEP2->PrimaryPath.LocalLID); + if (res != 0) + return res; + if (pCEP1->bPeer && pCEP2->bPeer) + { + res = CompareU64(pCEP1->LocalEndPoint.QPN, pCEP2->LocalEndPoint.QPN); + if (res != 0) + return res; + res = CompareU64(pCEP1->LocalEndPoint.EECN, pCEP2->LocalEndPoint.EECN); + if (res != 0) + return res; + res = CompareU64(pCEP1->LocalEndPoint.CaGUID, pCEP2->LocalEndPoint.CaGUID); + if (res != 0) + return res; + } + res = WildcardGidCompare(&pCEP1->PrimaryPath.RemoteGID, &pCEP2->PrimaryPath.RemoteGID); + if (res != 0) + return res; + res = WildcardCompareU64(pCEP1->PrimaryPath.RemoteLID, pCEP2->PrimaryPath.RemoteLID); + if (res != 0) + return res; + // a length of 0 matches any private data, so this too is a wildcard compare + if (pCEP1->DiscriminatorLen == 0 || pCEP2->DiscriminatorLen == 0) + return 0; + res = CompareU64(pCEP1->DiscriminatorLen, pCEP2->DiscriminatorLen); + if (res != 0) + return res; + res = MemoryCompare(pCEP1->Discriminator, pCEP2->Discriminator, pCEP1->DiscriminatorLen); + return res; +} + +// A qmap key_compare function to search the ListenMap for a match with +// a given REQ +// +// key1 - CEP pointer +// key2 - REQ pointer +// +// Returns: +// -1: cep1 bind address < req remote address +// 0: cep1 bind address = req remote address (accounting for wildcards) +// 1: cep1 bind address > req remote address +// +// The QPN/EECN/CaGUID are not part of the search, hence multiple Peer Connects +// could be matched (and one which was started earliest should be then linearly +// searched for among the neighbors of the matching CEP) +int +CepReqAddrCompare(uint64 key1, uint64 key2) +{ + IN CM_CEP_OBJECT* pCEP = (CM_CEP_OBJECT*)(uintn)key1; + IN CMM_REQ* pREQ = (CMM_REQ*)(uintn)key2; + int res; + + if (pCEP->SID < pREQ->ServiceID) + return -1; + else if (pCEP->SID > pREQ->ServiceID) + return 1; + // local and remote is from perspective of sender (remote node in this + // case, so we compare local to remote and visa versa + res = WildcardGidCompare(&pCEP->PrimaryPath.LocalGID, &pREQ->PrimaryRemoteGID); + if (res != 0) + return res; + res = WildcardCompareU64(pCEP->PrimaryPath.LocalLID, pREQ->PrimaryRemoteLID); + if (res != 0) + return res; + // do not compare QPN/EECN/CaGUID + res = WildcardGidCompare(&pCEP->PrimaryPath.RemoteGID, &pREQ->PrimaryLocalGID); + if (res != 0) + return res; + res = WildcardCompareU64(pCEP->PrimaryPath.RemoteLID, pREQ->PrimaryLocalLID); + if (res != 0) + return res; + // a length of 0 matches any private data, so this too is a wildcard compare + if (pCEP->DiscriminatorLen == 0) + return 0; + res = MemoryCompare(pCEP->Discriminator, pREQ->PrivateData+pCEP->DiscrimPrivateDataOffset, pCEP->DiscriminatorLen); + return res; +} + +// A qmap key_compare function to search the ListenMap for a match with +// a given SIDR_REQ +// +// key1 - CEP pointer +// key2 - SIDR_REQ pointer +// +// Returns: +// -1: cep1 bind address < cep2 bind address +// 0: cep1 bind address = cep2 bind address (accounting for wildcards) +// 1: cep1 bind address > cep2 bind address +// +// The QPN/EECN/CaGUID are not part of the search. +int +CepSidrReqAddrCompare(uint64 key1, uint64 key2) +{ + IN CM_CEP_OBJECT* pCEP = (CM_CEP_OBJECT*)(uintn)key1; + IN CMM_SIDR_REQ* pSIDR_REQ = (CMM_SIDR_REQ*)(uintn)key2; + int res; + + if (pCEP->SID < pSIDR_REQ->ServiceID) + return -1; + else if (pCEP->SID > pSIDR_REQ->ServiceID) + return 1; + // GID and LIDs are wildcarded/not available at this time + // do not compare QPN/EECN/CaGUID + // a length of 0 matches any private data, so this too is a wildcard compare + if (pCEP->DiscriminatorLen == 0) + return 0; + res = MemoryCompare(pCEP->Discriminator, pSIDR_REQ->PrivateData+pCEP->DiscrimPrivateDataOffset, pCEP->DiscriminatorLen); + return res; +} + diff --git a/IbAccess/Common/Ibt/Cm/cm_msg.c b/IbAccess/Common/Ibt/Cm/cm_msg.c new file mode 100644 index 0000000..d328d76 --- /dev/null +++ b/IbAccess/Common/Ibt/Cm/cm_msg.c @@ -0,0 +1,1578 @@ +/* BEGIN_ICS_COPYRIGHT4 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT4 ****************************************/ + +// Public header file +#include "ib_cm.h" + +// Private header file +#include "cm_private.h" + + +////////////////////////////////////////////////////////////////////////// +// FormatClassPortInfo +// +// Format the ClassPortInfo message +// +// INPUTS: +// +// +// +// OUTPUTS: +// +// None. +// +// RETURNS: +// +// None. +// +// IRQL: +// +// This routine is called at IRQL_PASSIVE_LEVEL. +// + +void +FormatClassPortInfo(CM_MAD* Mad, + uint64 TransactionID) +{ + // Set up the mad header + MAD_SET_VERSION_INFO(Mad, IB_BASE_VERSION, MCLASS_COMM_MGT, IB_COMM_MGT_CLASS_VERSION); + + MAD_SET_ATTRIB_ID(Mad, MCLASS_ATTRIB_ID_CLASS_PORT_INFO); + + Mad->common.mr.AsReg8 = MMTHD_GET_RESP; + + MAD_SET_TRANSACTION_ID(Mad, TransactionID); + + // We do not implement GSI Redirection nor Traps for this class + MemoryClear(&Mad->payload, sizeof(Mad->payload)); + Mad->payload.ClassPortInfo.BaseVersion = IB_BASE_VERSION; + Mad->payload.ClassPortInfo.ClassVersion = IB_COMM_MGT_CLASS_VERSION; + Mad->payload.ClassPortInfo.CapMask = 0; + Mad->payload.ClassPortInfo.u1.s.RespTimeValue = PORT_RESP_TIME_VALUE_MAX; // 8 + DUMP_CLASS_PORT_INFO(&Mad->payload.ClassPortInfo); + + ConvertMadToNetworkByteOrder(Mad); + +} // FormatREQ() + + +////////////////////////////////////////////////////////////////////////// +// FormatREQ +// +// Format the REQ message +// +// INPUTS: +// +// +// +// OUTPUTS: +// +// None. +// +// RETURNS: +// +// None. +// +// IRQL: +// +// This routine is called at IRQL_PASSIVE_LEVEL. +// + +void +FormatREQ(CM_MAD* Mad, + const CM_REQUEST_INFO* pConnectRequest, + uint64 TransactionID, + uint32 LocalCommID, + uint32 CMQKey, + CM_CEP_TYPE Type, + uint32 LocalCMTimeout, + uint32 RemoteCMTimeout, + uint32 MaxCMRetries, + uint8 OfferedInitiatorDepth, + uint8 OfferedResponderResources) +{ + // Set up the mad header + MAD_SET_VERSION_INFO(Mad, IB_BASE_VERSION, MCLASS_COMM_MGT, IB_COMM_MGT_CLASS_VERSION); + + MAD_SET_ATTRIB_ID(Mad, MCLASS_ATTRIB_ID_REQ); // Connection request msg + + MAD_SET_METHOD_TYPE(Mad, MMTHD_SEND); + + MAD_SET_TRANSACTION_ID(Mad, TransactionID); + + // Set up the REQ msg + Mad->payload.REQ.LocalCommID = LocalCommID; + Mad->payload.REQ.Reserved1 = 0; + Mad->payload.REQ.ServiceID = pConnectRequest->SID; + Mad->payload.REQ.LocalCaGUID = pConnectRequest->CEPInfo.CaGUID; + Mad->payload.REQ.Reserved2 = 0; + Mad->payload.REQ.LocalQKey = pConnectRequest->CEPInfo.QKey; + Mad->payload.REQ.u1.s.LocalQPN = pConnectRequest->CEPInfo.QPN; + Mad->payload.REQ.u1.s.OfferedResponderResources = OfferedResponderResources; + Mad->payload.REQ.u2.s.LocalEECN = pConnectRequest->CEPInfo.LocalEECN; + Mad->payload.REQ.u2.s.OfferedInitiatorDepth = OfferedInitiatorDepth; + Mad->payload.REQ.u3.s.RemoteEECN = pConnectRequest->CEPInfo.RemoteEECN; + Mad->payload.REQ.u3.s.RemoteCMTimeout = RemoteCMTimeout; + Mad->payload.REQ.u3.s.TransportServiceType = (uint8)Type; + Mad->payload.REQ.u3.s.EndToEndFlowControl = pConnectRequest->CEPInfo.EndToEndFlowControl; + Mad->payload.REQ.u4.s.StartingPSN = pConnectRequest->CEPInfo.StartingPSN; + Mad->payload.REQ.u4.s.LocalCMTimeout = LocalCMTimeout; + Mad->payload.REQ.u4.s.RetryCount = pConnectRequest->CEPInfo.RetryCount; + Mad->payload.REQ.PartitionKey = pConnectRequest->PathInfo.Path.P_Key; + Mad->payload.REQ.PathMTU = pConnectRequest->PathInfo.Path.Mtu; + if (pConnectRequest->CEPInfo.RemoteEECN) + Mad->payload.REQ.RdcExists = 1; + else + Mad->payload.REQ.RdcExists = 0; + + Mad->payload.REQ.RnRRetryCount = (uint16)pConnectRequest->CEPInfo.RnrRetryCount; + Mad->payload.REQ.MaxCMRetries = (uint16)MaxCMRetries; + Mad->payload.REQ.Reserved3 = 0; + + Mad->payload.REQ.PrimaryLocalLID = pConnectRequest->PathInfo.Path.SLID; + Mad->payload.REQ.PrimaryRemoteLID = pConnectRequest->PathInfo.Path.DLID; + Mad->payload.REQ.PrimaryLocalGID = pConnectRequest->PathInfo.Path.SGID; + Mad->payload.REQ.PrimaryRemoteGID = pConnectRequest->PathInfo.Path.DGID; + + Mad->payload.REQ.u5.s.PrimaryFlowLabel = pConnectRequest->PathInfo.Path.u1.s.FlowLabel; + Mad->payload.REQ.u5.s.Reserved4 = 0; + Mad->payload.REQ.u5.s.PrimaryPacketRate = pConnectRequest->PathInfo.Path.Rate; + Mad->payload.REQ.PrimaryTrafficClass = pConnectRequest->PathInfo.Path.TClass; + Mad->payload.REQ.PrimaryHopLimit = pConnectRequest->PathInfo.Path.u1.s.HopLimit; + Mad->payload.REQ.PrimarySL = pConnectRequest->PathInfo.Path.u2.s.SL; + Mad->payload.REQ.PrimarySubnetLocal = pConnectRequest->PathInfo.bSubnetLocal; + Mad->payload.REQ.Reserved5 = 0; + Mad->payload.REQ.PrimaryLocalAckTimeout = pConnectRequest->CEPInfo.AckTimeout; + Mad->payload.REQ.Reserved6 = 0; + + + if (pConnectRequest->AlternatePathInfo.Path.SLID) // Alternate path is specified + { + Mad->payload.REQ.AlternateLocalLID = pConnectRequest->AlternatePathInfo.Path.SLID; + Mad->payload.REQ.AlternateRemoteLID = pConnectRequest->AlternatePathInfo.Path.DLID; + Mad->payload.REQ.AlternateLocalGID = pConnectRequest->AlternatePathInfo.Path.SGID; + Mad->payload.REQ.AlternateRemoteGID = pConnectRequest->AlternatePathInfo.Path.DGID; + + Mad->payload.REQ.u6.s.AlternateFlowLabel = pConnectRequest->AlternatePathInfo.Path.u1.s.FlowLabel; + Mad->payload.REQ.u6.s.Reserved7 = 0; + Mad->payload.REQ.u6.s.AlternatePacketRate = pConnectRequest->AlternatePathInfo.Path.Rate; + Mad->payload.REQ.AlternateTrafficClass = pConnectRequest->AlternatePathInfo.Path.TClass; + Mad->payload.REQ.AlternateHopLimit = pConnectRequest->AlternatePathInfo.Path.u1.s.HopLimit; + Mad->payload.REQ.AlternateSL = pConnectRequest->AlternatePathInfo.Path.u2.s.SL; + + Mad->payload.REQ.AlternateSubnetLocal = pConnectRequest->AlternatePathInfo.bSubnetLocal; + Mad->payload.REQ.Reserved8 = 0; + Mad->payload.REQ.AlternateLocalAckTimeout = pConnectRequest->CEPInfo.AlternateAckTimeout; + Mad->payload.REQ.Reserved9 = 0; + } + else + { + Mad->payload.REQ.AlternateLocalLID = 0; + Mad->payload.REQ.AlternateRemoteLID = 0; + MemoryClear(&Mad->payload.REQ.AlternateLocalGID.Raw, sizeof(IB_GID)); + MemoryClear(&Mad->payload.REQ.AlternateRemoteGID.Raw, sizeof(IB_GID)); + + Mad->payload.REQ.u6.s.AlternateFlowLabel = 0; + Mad->payload.REQ.u6.s.Reserved7 = 0; + Mad->payload.REQ.u6.s.AlternatePacketRate = 0; + Mad->payload.REQ.AlternateTrafficClass = 0; + Mad->payload.REQ.AlternateHopLimit = 0; + Mad->payload.REQ.AlternateSL = 0; + Mad->payload.REQ.AlternateSubnetLocal = 0; + Mad->payload.REQ.Reserved8 = 0; + Mad->payload.REQ.AlternateLocalAckTimeout = 0; + Mad->payload.REQ.Reserved9 = 0; + } + + memcpy(Mad->payload.REQ.PrivateData, pConnectRequest->PrivateData, CMM_REQ_USER_LEN); + + DUMP_REQ(&Mad->payload.REQ); + + ConvertMadToNetworkByteOrder(Mad); + +} // FormatREQ() + + +void +CopyREQToReqInfo( + const CMM_REQ* pREQ, + CM_REQUEST_INFO *pConnectRequest) +{ + // Primary path info + pConnectRequest->PathInfo.bSubnetLocal = (boolean)pREQ->PrimarySubnetLocal; + + pConnectRequest->PathInfo.Path.SLID = pREQ->PrimaryRemoteLID; + pConnectRequest->PathInfo.Path.SGID = pREQ->PrimaryRemoteGID; + + pConnectRequest->PathInfo.Path.DLID = pREQ->PrimaryLocalLID; + pConnectRequest->PathInfo.Path.DGID = pREQ->PrimaryLocalGID; + + pConnectRequest->PathInfo.Path.NumbPath = 1; // Only one path. + + pConnectRequest->PathInfo.Path.u1.s.FlowLabel = pREQ->u5.s.PrimaryFlowLabel; + pConnectRequest->PathInfo.Path.u1.s.HopLimit = pREQ->PrimaryHopLimit; + pConnectRequest->PathInfo.Path.TClass = (uint8)pREQ->PrimaryTrafficClass; + pConnectRequest->PathInfo.Path.u2.s.SL = (uint8)pREQ->PrimarySL; + pConnectRequest->PathInfo.Path.Rate = (uint8)pREQ->u5.s.PrimaryPacketRate; + pConnectRequest->PathInfo.Path.RateSelector = IB_SELECTOR_EQ; + + pConnectRequest->PathInfo.Path.P_Key = pREQ->PartitionKey; + pConnectRequest->PathInfo.Path.Mtu = (uint8)pREQ->PathMTU; + + pConnectRequest->PathInfo.Path.MtuSelector = IB_SELECTOR_EQ; + + // since exponent, subtracting 1 means divide by 2 + // this value ends up rounded up by Ca Ack Delay/2 + if (pREQ->PrimaryLocalAckTimeout >= 1) + { + pConnectRequest->PathInfo.Path.PktLifeTime = (pREQ->PrimaryLocalAckTimeout-1); + } else { + pConnectRequest->PathInfo.Path.PktLifeTime = 0; + } + + + pConnectRequest->PathInfo.Path.PktLifeTimeSelector = IB_SELECTOR_EQ; + + // Alternate path info + if (pREQ->AlternateLocalLID) + { + pConnectRequest->AlternatePathInfo.bSubnetLocal = (boolean)pREQ->AlternateSubnetLocal; + + pConnectRequest->AlternatePathInfo.Path.SLID = pREQ->AlternateRemoteLID; + pConnectRequest->AlternatePathInfo.Path.SGID = pREQ->AlternateRemoteGID; + + pConnectRequest->AlternatePathInfo.Path.DLID = pREQ->AlternateLocalLID; + pConnectRequest->AlternatePathInfo.Path.DGID = pREQ->AlternateLocalGID; + + + pConnectRequest->AlternatePathInfo.Path.NumbPath= 1; // Only one path. + pConnectRequest->AlternatePathInfo.Path.u1.s.FlowLabel = pREQ->u6.s.AlternateFlowLabel; + pConnectRequest->AlternatePathInfo.Path.u1.s.HopLimit = pREQ->AlternateHopLimit; + pConnectRequest->AlternatePathInfo.Path.TClass = (uint8)pREQ->AlternateTrafficClass; + pConnectRequest->AlternatePathInfo.Path.u2.s.SL = (uint8)pREQ->AlternateSL; + pConnectRequest->AlternatePathInfo.Path.Rate = (uint8)pREQ->u6.s.AlternatePacketRate; + pConnectRequest->AlternatePathInfo.Path.RateSelector= IB_SELECTOR_EQ; + + pConnectRequest->AlternatePathInfo.Path.P_Key = pREQ->PartitionKey; + pConnectRequest->AlternatePathInfo.Path.Mtu = (uint8)pREQ->PathMTU; + + pConnectRequest->AlternatePathInfo.Path.MtuSelector = IB_SELECTOR_EQ; + + // since exponent, subtracting 1 means divide by 2 + // this value ends up rounded up by Ca Ack Delay/2 + if (pREQ->AlternateLocalAckTimeout >= 1) + { + pConnectRequest->AlternatePathInfo.Path.PktLifeTime = (pREQ->AlternateLocalAckTimeout-1); + } else { + pConnectRequest->AlternatePathInfo.Path.PktLifeTime = 0; + } + } + else + { + pConnectRequest->AlternatePathInfo.bSubnetLocal = 0; + + pConnectRequest->AlternatePathInfo.Path.SLID = 0; + MemoryClear(&pConnectRequest->AlternatePathInfo.Path.SGID.Raw, sizeof(IB_GID)); + + pConnectRequest->AlternatePathInfo.Path.DLID = 0; + MemoryClear(&pConnectRequest->AlternatePathInfo.Path.DGID.Raw, sizeof(IB_GID)); + + pConnectRequest->AlternatePathInfo.Path.NumbPath = 0; + pConnectRequest->AlternatePathInfo.Path.u1.s.FlowLabel = 0; + pConnectRequest->AlternatePathInfo.Path.u1.s.HopLimit = 0; + pConnectRequest->AlternatePathInfo.Path.TClass = 0; + pConnectRequest->AlternatePathInfo.Path.u2.s.SL = 0; + pConnectRequest->AlternatePathInfo.Path.Rate = 0; + pConnectRequest->AlternatePathInfo.Path.RateSelector= 0; + + pConnectRequest->AlternatePathInfo.Path.P_Key = 0; + pConnectRequest->AlternatePathInfo.Path.Mtu = 0; + pConnectRequest->AlternatePathInfo.Path.MtuSelector = 0; + pConnectRequest->AlternatePathInfo.Path.PktLifeTime = 0; + } + + pConnectRequest->SID = pREQ->ServiceID; + pConnectRequest->CEPInfo.CaGUID = pREQ->LocalCaGUID; + pConnectRequest->CEPInfo.EndToEndFlowControl = (uint8)pREQ->u3.s.EndToEndFlowControl; + //pConnectRequest->CEPInfo.PortGUID = handled by caller + + // QP info + pConnectRequest->CEPInfo.StartingPSN = pREQ->u4.s.StartingPSN; + pConnectRequest->CEPInfo.QPN = pREQ->u1.s.LocalQPN; + pConnectRequest->CEPInfo.QKey = pREQ->LocalQKey; + pConnectRequest->CEPInfo.RetryCount = (uint8)pREQ->u4.s.RetryCount; + pConnectRequest->CEPInfo.RnrRetryCount = (uint8)pREQ->RnRRetryCount; + pConnectRequest->CEPInfo.AckTimeout = (uint8)pREQ->PrimaryLocalAckTimeout; + pConnectRequest->CEPInfo.AlternateAckTimeout = (uint8)pREQ->AlternateLocalAckTimeout; + pConnectRequest->CEPInfo.OfferedResponderResources = (uint8)pREQ->u1.s.OfferedResponderResources; + pConnectRequest->CEPInfo.OfferedInitiatorDepth = (uint8)pREQ->u2.s.OfferedInitiatorDepth; + + pConnectRequest->CEPInfo.LocalEECN = pREQ->u2.s.LocalEECN; + pConnectRequest->CEPInfo.RemoteEECN = pREQ->u3.s.RemoteEECN; + + memcpy(pConnectRequest->PrivateData, pREQ->PrivateData, CMM_REQ_USER_LEN); + + DUMP_REQ(pREQ); + +} // CopyREQToReqInfo() + + +////////////////////////////////////////////////////////////////////////// +// FormatREP +// +// Format the REP message +// +// INPUTS: +// +// +// +// OUTPUTS: +// +// None. +// +// RETURNS: +// +// None. +// +// IRQL: +// +// This routine is called at IRQL_PASSIVE_LEVEL. +// + +void +FormatREP(CM_MAD* Mad, + const CM_REPLY_INFO* pConnectReply, + uint64 TransactionID, + uint32 LocalCommID, + uint32 RemoteCommID, + uint64 LocalCaGUID + ) +{ + // Set up the mad header + MAD_SET_VERSION_INFO(Mad, IB_BASE_VERSION, MCLASS_COMM_MGT, IB_COMM_MGT_CLASS_VERSION); + + MAD_SET_ATTRIB_ID(Mad, MCLASS_ATTRIB_ID_REP); // Reply msg + + MAD_SET_METHOD_TYPE(Mad, MMTHD_SEND); + + MAD_SET_TRANSACTION_ID(Mad, TransactionID); + + // Set up the REP msg + Mad->payload.REP.LocalCommID = LocalCommID; + Mad->payload.REP.RemoteCommID = RemoteCommID; + Mad->payload.REP.LocalQKey = pConnectReply->QKey; + Mad->payload.REP.u1.s.LocalQPN = pConnectReply->QPN; + Mad->payload.REP.u1.s.Reserved1 = 0; + Mad->payload.REP.u2.s.LocalEECN = pConnectReply->EECN; + Mad->payload.REP.u2.s.Reserved2 = 0; + Mad->payload.REP.u3.s.StartingPSN = pConnectReply->StartingPSN; + Mad->payload.REP.u3.s.Reserved3 = 0; + Mad->payload.REP.ArbResponderResources = pConnectReply->ArbResponderResources; + Mad->payload.REP.ArbInitiatorDepth = pConnectReply->ArbInitiatorDepth; + Mad->payload.REP.TargetAckDelay = pConnectReply->TargetAckDelay; + Mad->payload.REP.FailoverAccepted = pConnectReply->FailoverAccepted; + Mad->payload.REP.EndToEndFlowControl = pConnectReply->EndToEndFlowControl; + Mad->payload.REP.RnRRetryCount = pConnectReply->RnRRetryCount; + Mad->payload.REP.Reserved4 = 0; + + Mad->payload.REP.LocalCaGUID = LocalCaGUID; + + memcpy(Mad->payload.REP.PrivateData, pConnectReply->PrivateData, CMM_REP_USER_LEN); + + DUMP_REP(&Mad->payload.REP); + + ConvertMadToNetworkByteOrder(Mad); + +} // FormatREP() + +void +CopyREPToRepInfo( + const CMM_REP *pREP, + CM_REPLY_INFO *pReplyInfo) +{ + pReplyInfo->QKey = pREP->LocalQKey; + + pReplyInfo->QPN = pREP->u1.s.LocalQPN; + + pReplyInfo->EECN = pREP->u2.s.LocalEECN; + + pReplyInfo->StartingPSN = pREP->u3.s.StartingPSN; + + pReplyInfo->ArbResponderResources = pREP->ArbResponderResources; + pReplyInfo->ArbInitiatorDepth = pREP->ArbInitiatorDepth; + pReplyInfo->TargetAckDelay = pREP->TargetAckDelay; + pReplyInfo->FailoverAccepted = pREP->FailoverAccepted; + pReplyInfo->EndToEndFlowControl = pREP->EndToEndFlowControl; + pReplyInfo->RnRRetryCount = pREP->RnRRetryCount; + pReplyInfo->CaGUID = pREP->LocalCaGUID; + + MemoryCopy( pReplyInfo->PrivateData, pREP->PrivateData, CMM_REP_USER_LEN ); + + DUMP_REP(pREP); + +} // CopyREPToRepInfo() + +void +FormatREJ(CM_MAD* Mad, + uint8 MsgRejected, // CMM_REJ_MSGTYPE + uint16 Reason, + const uint8* pRejectInfo, + uint32 RejectInfoLen, + const uint8* pPrivateData, + uint32 PrivateDataLen, + uint64 TransactionID, + uint32 LocalCommID, + uint32 RemoteCommID) +{ + // Set up the mad header + MAD_SET_VERSION_INFO(Mad, IB_BASE_VERSION, MCLASS_COMM_MGT, IB_COMM_MGT_CLASS_VERSION); + + MAD_SET_ATTRIB_ID(Mad, MCLASS_ATTRIB_ID_REJ); // reject msg + + MAD_SET_METHOD_TYPE(Mad, MMTHD_SEND); + + MAD_SET_TRANSACTION_ID(Mad, TransactionID); + + // Set up the REJ msg + Mad->payload.REJ.LocalCommID = LocalCommID; + Mad->payload.REJ.RemoteCommID = RemoteCommID; + + Mad->payload.REJ.MsgRejected = MsgRejected; + Mad->payload.REJ.Reserved1 = 0; + if (RejectInfoLen > CMM_REJ_ADD_INFO_LEN) + RejectInfoLen = CMM_REJ_ADD_INFO_LEN; + Mad->payload.REJ.RejectInfoLen = (uint8)RejectInfoLen; + Mad->payload.REJ.Reserved2 = 0; + Mad->payload.REJ.Reason = Reason; + + if (RejectInfoLen) + memcpy(Mad->payload.REJ.RejectInfo, pRejectInfo, RejectInfoLen); + + memset(&Mad->payload.REJ.RejectInfo[RejectInfoLen], 0, CMM_REJ_ADD_INFO_LEN - RejectInfoLen); + + if (PrivateDataLen) + memcpy(Mad->payload.REJ.PrivateData, pPrivateData, PrivateDataLen); + + memset(&Mad->payload.REJ.PrivateData[PrivateDataLen], 0, CMM_REJ_USER_LEN - PrivateDataLen); + + DUMP_REJ(&Mad->payload.REJ); + + ConvertMadToNetworkByteOrder(Mad); + +} // FormatREJ() + +void +CopyREJToRejectInfo( + const CMM_REJ* pREJ, + CM_REJECT_INFO *pRejectInfo) +{ + pRejectInfo->RejectInfoLen = MIN(pREJ->RejectInfoLen, CMM_REJ_USER_LEN); + + pRejectInfo->Reason = pREJ->Reason; + + memcpy(pRejectInfo->RejectInfo, pREJ->RejectInfo, pRejectInfo->RejectInfoLen); + + memcpy(pRejectInfo->PrivateData, pREJ->PrivateData, CMM_REJ_USER_LEN); + + DUMP_REJ(pREJ); + +} // CopyREJToRejectInfo + +void +FormatMRA(CM_MAD* Mad, + uint8 MsgMraed, // CMM_MRA_MSGTYPE + uint8 ServiceTimeout, + const uint8* pPrivateData, + uint32 PrivateDataLen, + uint64 TransactionID, + uint32 LocalCommID, + uint32 RemoteCommID) +{ + // Set up the mad header + MAD_SET_VERSION_INFO(Mad, IB_BASE_VERSION, MCLASS_COMM_MGT, IB_COMM_MGT_CLASS_VERSION); + + MAD_SET_ATTRIB_ID(Mad, MCLASS_ATTRIB_ID_MRA); + + MAD_SET_METHOD_TYPE(Mad, MMTHD_SEND); + + MAD_SET_TRANSACTION_ID(Mad, TransactionID); + + // Set up the MRA msg + Mad->payload.MRA.LocalCommID = LocalCommID; + Mad->payload.MRA.RemoteCommID = RemoteCommID; + + Mad->payload.MRA.MsgMraed = MsgMraed; + Mad->payload.MRA.Reserved1 = 0; + Mad->payload.MRA.ServiceTimeout = ServiceTimeout; + Mad->payload.MRA.Reserved2 = 0; + + if (PrivateDataLen) + memcpy(Mad->payload.MRA.PrivateData, pPrivateData, PrivateDataLen); + + memset(Mad->payload.MRA.PrivateData + PrivateDataLen, 0, CMM_MRA_USER_LEN - PrivateDataLen); + + ConvertMadToNetworkByteOrder(Mad); + +} // FormatMRA() + + +void +FormatRTU(CM_MAD* Mad, + const uint8* pPrivateData, + uint32 PrivateDataLen, + uint64 TransactionID, + uint32 LocalCommID, + uint32 RemoteCommID) +{ + // Set up the mad header + MAD_SET_VERSION_INFO(Mad, IB_BASE_VERSION, MCLASS_COMM_MGT, IB_COMM_MGT_CLASS_VERSION); + + MAD_SET_ATTRIB_ID(Mad, MCLASS_ATTRIB_ID_RTU); // Ready-to-use msg + + MAD_SET_METHOD_TYPE(Mad, MMTHD_SEND); + + MAD_SET_TRANSACTION_ID(Mad, TransactionID); + + Mad->payload.RTU.LocalCommID = LocalCommID; + Mad->payload.RTU.RemoteCommID = RemoteCommID; + + if (PrivateDataLen) + memcpy(Mad->payload.RTU.PrivateData, pPrivateData, PrivateDataLen); + + memset(Mad->payload.RTU.PrivateData + PrivateDataLen, 0, CMM_RTU_USER_LEN - PrivateDataLen); + + ConvertMadToNetworkByteOrder(Mad); + +} // FormatRTU() + +void +FormatLAP( + IN CM_MAD* Mad, + IN uint32 QPN, + IN uint32 RemoteCMTimeout, + IN const CM_ALTPATH_INFO* pAltPath, + IN uint8 AlternateAckTimeout, + IN uint64 TransactionID, + IN uint32 LocalCommID, + IN uint32 RemoteCommID + ) +{ + // Set up the mad header + MAD_SET_VERSION_INFO(Mad, IB_BASE_VERSION, MCLASS_COMM_MGT, IB_COMM_MGT_CLASS_VERSION); + + MAD_SET_ATTRIB_ID(Mad, MCLASS_ATTRIB_ID_LAP); // Load Alternate Path + + MAD_SET_METHOD_TYPE(Mad, MMTHD_SEND); + + MAD_SET_TRANSACTION_ID(Mad, TransactionID); + + Mad->payload.LAP.LocalCommID = LocalCommID; + Mad->payload.LAP.RemoteCommID = RemoteCommID; + Mad->payload.LAP.Reserved1 = 0; + Mad->payload.LAP.u1.s.RemoteQPNorEECN = QPN; + Mad->payload.LAP.u1.s.RemoteCMTimeout = RemoteCMTimeout; + Mad->payload.LAP.u1.s.Reserved2 = 0; + Mad->payload.LAP.Reserved3 = 0; + + Mad->payload.LAP.AlternateLocalLID = pAltPath->AlternatePathInfo.Path.SLID; + Mad->payload.LAP.AlternateRemoteLID = pAltPath->AlternatePathInfo.Path.DLID; + Mad->payload.LAP.AlternateLocalGID = pAltPath->AlternatePathInfo.Path.SGID; + Mad->payload.LAP.AlternateRemoteGID = pAltPath->AlternatePathInfo.Path.DGID; + + Mad->payload.LAP.u2.s.AlternateFlowLabel = pAltPath->AlternatePathInfo.Path.u1.s.FlowLabel; + Mad->payload.LAP.u2.s.Reserved4 = 0; + Mad->payload.LAP.u2.s.AlternateTrafficClass = pAltPath->AlternatePathInfo.Path.TClass; + Mad->payload.LAP.AlternateHopLimit = pAltPath->AlternatePathInfo.Path.u1.s.HopLimit; + Mad->payload.LAP.Reserved5 = 0; + Mad->payload.LAP.AlternatePacketRate = pAltPath->AlternatePathInfo.Path.Rate; + Mad->payload.LAP.AlternateSL = pAltPath->AlternatePathInfo.Path.u2.s.SL; + + Mad->payload.LAP.AlternateSubnetLocal = pAltPath->AlternatePathInfo.bSubnetLocal; + Mad->payload.LAP.Reserved6 = 0; + Mad->payload.LAP.AlternateLocalAckTimeout = AlternateAckTimeout; + Mad->payload.LAP.Reserved7 = 0; + + memcpy(Mad->payload.LAP.PrivateData, pAltPath->PrivateData, CMM_LAP_USER_LEN); + + ConvertMadToNetworkByteOrder(Mad); + + DUMP_LAP(&Mad->payload.LAP); +} + +void +CopyLAPToAltPathRequest( + IN const CMM_LAP* pLAP, + IN OUT CM_ALTPATH_INFO *pAltPath + ) +{ + pAltPath->AlternateAckTimeout= pLAP->AlternateLocalAckTimeout; + + pAltPath->AlternatePathInfo.Path.SLID= pLAP->AlternateLocalLID; + pAltPath->AlternatePathInfo.Path.DLID= pLAP->AlternateRemoteLID; + pAltPath->AlternatePathInfo.Path.SGID= pLAP->AlternateLocalGID; + pAltPath->AlternatePathInfo.Path.DGID= pLAP->AlternateRemoteGID; + pAltPath->AlternatePathInfo.Path.NumbPath = 1; // Only one path. + + pAltPath->AlternatePathInfo.Path.u1.s.FlowLabel=pLAP->u2.s.AlternateFlowLabel; + pAltPath->AlternatePathInfo.Path.TClass=pLAP->u2.s.AlternateTrafficClass; + pAltPath->AlternatePathInfo.Path.u1.s.HopLimit= pLAP->AlternateHopLimit; + pAltPath->AlternatePathInfo.Path.Rate= pLAP->AlternatePacketRate; + pAltPath->AlternatePathInfo.Path.RateSelector = IB_SELECTOR_EQ; + pAltPath->AlternatePathInfo.Path.u2.s.SL= pLAP->AlternateSL; + //pAltPath->AlternatePathInfo.Path.P_Key = caller handles + //pAltPath->AlternatePathInfo.Path.Mtu = caller handles + pAltPath->AlternatePathInfo.Path.MtuSelector = IB_SELECTOR_EQ; + + pAltPath->AlternatePathInfo.bSubnetLocal= pLAP->AlternateSubnetLocal; + + // since exponent, subtracting 1 means divide by 2 + // this value ends up rounded up by Ca Ack Delay/2 + if (pLAP->AlternateLocalAckTimeout >= 1) + { + pAltPath->AlternatePathInfo.Path.PktLifeTime = (pLAP->AlternateLocalAckTimeout-1); + } else { + pAltPath->AlternatePathInfo.Path.PktLifeTime = 0; + } + pAltPath->AlternatePathInfo.Path.PktLifeTimeSelector = IB_SELECTOR_EQ; + + memcpy(pAltPath->PrivateData, pLAP->PrivateData, CMM_LAP_USER_LEN); + + DUMP_LAP(pLAP); +} + +// performs copy of a received LAP to given AltPath +void +CopyRcvdLAPToAltPath( + IN const CMM_LAP* pLAP, + OUT CM_CEP_PATH *pAltPath + ) +{ + // caller handles pAltPath->LocalPortGuid + pAltPath->LocalGID = pLAP->AlternateRemoteGID; + pAltPath->RemoteGID = pLAP->AlternateLocalGID; + pAltPath->LocalLID = pLAP->AlternateRemoteLID; + pAltPath->RemoteLID = pLAP->AlternateLocalLID; + + pAltPath->FlowLabel=pLAP->u2.s.AlternateFlowLabel; + pAltPath->StaticRate= pLAP->AlternatePacketRate; + // caller handles pAltPath->PkeyIndex + pAltPath->TClass=pLAP->u2.s.AlternateTrafficClass; + pAltPath->SL= pLAP->AlternateSL; + pAltPath->bSubnetLocal= pLAP->AlternateSubnetLocal; + pAltPath->AckTimeout= pLAP->AlternateLocalAckTimeout; + pAltPath->LocalAckTimeout= pLAP->AlternateLocalAckTimeout; + pAltPath->Reserved = 0; + pAltPath->HopLimit= pLAP->AlternateHopLimit; + // caller handles pAltPath->LocalGidIndex +} + +// performs copy of a sent LAP to given AltPath +void +CopySentLAPToAltPath( + IN const CMM_LAP* pLAP, + OUT CM_CEP_PATH *pAltPath + ) +{ + // caller handles pAltPath->LocalPortGuid + pAltPath->LocalGID = pLAP->AlternateLocalGID; + pAltPath->RemoteGID = pLAP->AlternateRemoteGID; + pAltPath->LocalLID = pLAP->AlternateLocalLID; + pAltPath->RemoteLID = pLAP->AlternateRemoteLID; + + pAltPath->FlowLabel=pLAP->u2.s.AlternateFlowLabel; + pAltPath->StaticRate= pLAP->AlternatePacketRate; + // caller handles pAltPath->PkeyIndex + pAltPath->TClass=pLAP->u2.s.AlternateTrafficClass; + pAltPath->SL= pLAP->AlternateSL; + pAltPath->bSubnetLocal= pLAP->AlternateSubnetLocal; + pAltPath->AckTimeout= pLAP->AlternateLocalAckTimeout; + // caller handles pAltPath->LocalAckTimeout + pAltPath->Reserved = 0; + pAltPath->HopLimit= pLAP->AlternateHopLimit; + // caller handles pAltPath->LocalGidIndex +} + +// compares received LAP to given Path +// return 0 on match +int +CompareRcvdLAPToPath( + IN const CMM_LAP* pLAP, + IN const CM_CEP_PATH *pPath + ) +{ + if (pPath->LocalLID != pLAP->AlternateRemoteLID) + return 1; + if (pPath->RemoteLID != pLAP->AlternateLocalLID) + return 1; + // we must test GIDs, if ports are on different fabrics, the LIDs + // could match but the GIDs would be different + if (0 != MemoryCompare(&pPath->LocalGID, &pLAP->AlternateRemoteGID, sizeof(IB_GID))) + return 1; + if (0 != MemoryCompare(&pPath->RemoteGID, &pLAP->AlternateLocalGID, sizeof(IB_GID))) + return 1; + if (pPath->bSubnetLocal != pLAP->AlternateSubnetLocal) + return 1; + + // ignore minor parameters + //pPath->FlowLabel=pLAP->u2.s.AlternateFlowLabel; + //pPath->StaticRate= pLAP->AlternatePacketRate; + //pPath->TClass=pLAP->u2.s.AlternateTrafficClass; + //pPath->SL= pLAP->AlternateSL; + //pPath->AckTimeout= pLAP->AlternateLocalAckTimeout; + //pPath->HopLimit= pLAP->AlternateHopLimit; + return 0; +} + +// compares two LAPs +// return 0 on match +int +CompareLAP( + IN const CMM_LAP* pLAP1, + IN const CMM_LAP* pLAP2 + ) +{ + if (pLAP1->AlternateLocalAckTimeout != pLAP2->AlternateLocalAckTimeout) + return 1; + + if (pLAP1->AlternateLocalLID != pLAP2->AlternateLocalLID) + return 1; + if (pLAP1->AlternateRemoteLID != pLAP2->AlternateRemoteLID) + return 1; + if (0 != MemoryCompare(&pLAP1->AlternateLocalGID, &pLAP2->AlternateLocalGID, sizeof(IB_GID))) + return 1; + if (0 != MemoryCompare(&pLAP1->AlternateRemoteGID, &pLAP2->AlternateRemoteGID, sizeof(IB_GID))) + return 1; + if (pLAP1->u2.s.AlternateFlowLabel != pLAP2->u2.s.AlternateFlowLabel) + return 1; + if (pLAP1->u2.s.AlternateTrafficClass != pLAP2->u2.s.AlternateTrafficClass) + return 1; + if (pLAP1->AlternateHopLimit != pLAP2->AlternateHopLimit) + return 1; + if (pLAP1->AlternatePacketRate != pLAP2->AlternatePacketRate) + return 1; + if (pLAP1->AlternateSL != pLAP2->AlternateSL) + return 1; + if (pLAP1->AlternateSubnetLocal != pLAP2->AlternateSubnetLocal) + return 1; + if (0 != MemoryCompare(pLAP1->PrivateData, pLAP2->PrivateData, CMM_LAP_USER_LEN)) + return 1; + return 0; +} +void +FormatAPR( + IN CM_MAD* Mad, + IN CM_APR_STATUS APStatus, + IN const uint8* pAddInfo, + IN uint32 AddInfoLen, + IN const uint8* pPrivateData, + IN uint32 PrivateDataLen, + IN uint64 TransactionID, + IN uint32 LocalCommID, + IN uint32 RemoteCommID + ) +{ + // Set up the mad header + MAD_SET_VERSION_INFO(Mad, IB_BASE_VERSION, MCLASS_COMM_MGT, IB_COMM_MGT_CLASS_VERSION); + + MAD_SET_ATTRIB_ID(Mad, MCLASS_ATTRIB_ID_APR); // Alternate Path Reply + + MAD_SET_METHOD_TYPE(Mad, MMTHD_SEND); + + MAD_SET_TRANSACTION_ID(Mad, TransactionID); + + // Set up the APR msg + Mad->payload.APR.LocalCommID = LocalCommID; + Mad->payload.APR.RemoteCommID = RemoteCommID; + + Mad->payload.APR.APStatus = APStatus; + if (AddInfoLen > CMM_APR_ADD_INFO_LEN) + AddInfoLen = CMM_APR_ADD_INFO_LEN; + Mad->payload.APR.AddInfoLen = (uint8)AddInfoLen; + Mad->payload.APR.Reserved = 0; + + if (AddInfoLen) + memcpy(Mad->payload.APR.AddInfo, pAddInfo, AddInfoLen); + + memset(&Mad->payload.APR.AddInfo[AddInfoLen], 0, CMM_APR_ADD_INFO_LEN - AddInfoLen); + + if (PrivateDataLen) + memcpy(Mad->payload.APR.PrivateData, pPrivateData, PrivateDataLen); + + memset(&Mad->payload.APR.PrivateData[PrivateDataLen], 0, CMM_APR_USER_LEN - PrivateDataLen); + + DUMP_APR(&Mad->payload.APR); + + ConvertMadToNetworkByteOrder(Mad); +} + +void +CopyAPRToAltPathReply( + IN const CMM_APR* pAPR, + IN OUT CM_ALTPATH_REPLY_INFO *pAltPathReply + ) +{ + pAltPathReply->APStatus = pAPR->APStatus; + // for APS_PATH_LOADED, caller will populate PathInfo and AckTimeout + if (pAPR->APStatus != APS_PATH_LOADED) + { + pAltPathReply->u.AddInfo.Len = MIN(pAPR->AddInfoLen,CMM_APR_ADD_INFO_LEN); + pAltPathReply->u.AddInfo.Reserved = 0; + + memcpy(pAltPathReply->u.AddInfo.Info, pAPR->AddInfo, pAltPathReply->u.AddInfo.Len); + } + memcpy(pAltPathReply->PrivateData, pAPR->PrivateData, CMM_APR_USER_LEN); + + DUMP_APR(pAPR); +} + +void +FormatDREQ(CM_MAD* Mad, + uint32 RemoteQPNorEECN, + const uint8* pPrivateData, + uint32 PrivateDataLen, + uint64 TransactionID, + uint32 LocalCommID, + uint32 RemoteCommID) +{ + // Set up the mad header + MAD_SET_VERSION_INFO(Mad, IB_BASE_VERSION, MCLASS_COMM_MGT, IB_COMM_MGT_CLASS_VERSION); + + MAD_SET_ATTRIB_ID(Mad, MCLASS_ATTRIB_ID_DREQ); // Disconnect request msg + + MAD_SET_METHOD_TYPE(Mad, MMTHD_SEND); + + MAD_SET_TRANSACTION_ID(Mad, TransactionID); + + // Set up the DREQ msg + Mad->payload.DREQ.LocalCommID = LocalCommID; + Mad->payload.DREQ.RemoteCommID = RemoteCommID; + + Mad->payload.DREQ.u.s.RemoteQPNorEECN = RemoteQPNorEECN; + Mad->payload.DREQ.u.s.Reserved = 0; + + if (PrivateDataLen) + memcpy(Mad->payload.DREQ.PrivateData, pPrivateData, PrivateDataLen); + + memset(Mad->payload.DREQ.PrivateData + PrivateDataLen, 0, CMM_DREQ_USER_LEN - PrivateDataLen); + + DUMP_DREQ(&Mad->payload.DREQ); + + ConvertMadToNetworkByteOrder(Mad); + +} // FormatDREQ() + + +void +FormatDREP(CM_MAD* Mad, + const uint8* pPrivateData, + uint32 PrivateDataLen, + uint64 TransactionID, + uint32 LocalCommID, + uint32 RemoteCommID) + +{ + // Set up the mad header + MAD_SET_VERSION_INFO(Mad, IB_BASE_VERSION, MCLASS_COMM_MGT, IB_COMM_MGT_CLASS_VERSION); + + MAD_SET_ATTRIB_ID(Mad, MCLASS_ATTRIB_ID_DREP); // Disconnect reply msg + + MAD_SET_METHOD_TYPE(Mad, MMTHD_SEND); + + MAD_SET_TRANSACTION_ID(Mad, TransactionID); + + // Set up the DREP msg + Mad->payload.DREP.LocalCommID = LocalCommID; + Mad->payload.DREP.RemoteCommID = RemoteCommID; + + if (PrivateDataLen) + memcpy(Mad->payload.DREP.PrivateData, pPrivateData, PrivateDataLen); + + memset(Mad->payload.DREP.PrivateData + PrivateDataLen, 0, CMM_DREP_USER_LEN - PrivateDataLen); + + ConvertMadToNetworkByteOrder(Mad); + +} // FormatDREP() + + +void +FormatSIDR_REQ(CM_MAD* Mad, + uint64 SID, + uint16 PartitionKey, + const uint8* pPrivateData, + uint32 PrivateDataLen, + uint64 TransactionID, + uint32 RequestID) +{ + // Set up the mad header + MAD_SET_VERSION_INFO(Mad, IB_BASE_VERSION, MCLASS_COMM_MGT, IB_COMM_MGT_CLASS_VERSION); + + MAD_SET_ATTRIB_ID(Mad, MCLASS_ATTRIB_ID_SIDR_REQ); // SIDR request + + MAD_SET_METHOD_TYPE(Mad, MMTHD_SEND); + + MAD_SET_TRANSACTION_ID(Mad, TransactionID); + + // Set up the SIDR REQ + Mad->payload.SIDR_REQ.RequestID = RequestID; + Mad->payload.SIDR_REQ.PartitionKey= PartitionKey; + Mad->payload.SIDR_REQ.Reserved = 0; + Mad->payload.SIDR_REQ.ServiceID = SID; + + if (PrivateDataLen) + memcpy(Mad->payload.SIDR_REQ.PrivateData, pPrivateData, PrivateDataLen); + + memset(Mad->payload.SIDR_REQ.PrivateData + PrivateDataLen, 0, CMM_SIDR_REQ_USER_LEN - PrivateDataLen); + + DUMP_SIDR_REQ(&Mad->payload.SIDR_REQ); + + ConvertMadToNetworkByteOrder(Mad); + +} // FormatSIDR_REQ() + +void +CopySIDR_REQToSidrReqInfo( + const CMM_SIDR_REQ* pSIDR_REQ, + SIDR_REQ_INFO *pSidrReqInfo) +{ + pSidrReqInfo->SID = pSIDR_REQ->ServiceID; + pSidrReqInfo->PartitionKey = pSIDR_REQ->PartitionKey; + pSidrReqInfo->PathInfo.Path.P_Key = pSIDR_REQ->PartitionKey; + + memcpy(pSidrReqInfo->PrivateData, pSIDR_REQ->PrivateData, CMM_SIDR_REQ_USER_LEN); + + DUMP_SIDR_REQ(pSIDR_REQ); + +} // CopySIDR_REQToSidrReqInfo() + +void +FormatSIDR_RESP(CM_MAD* Mad, + uint64 SID, + uint32 QPN, + uint32 QKey, + uint32 Status, + const uint8* pPrivateData, + uint32 PrivateDataLen, + uint64 TransactionID, + uint32 RequestID) +{ + // Set up the mad header + MAD_SET_VERSION_INFO(Mad, IB_BASE_VERSION, MCLASS_COMM_MGT, IB_COMM_MGT_CLASS_VERSION); + + MAD_SET_ATTRIB_ID(Mad, MCLASS_ATTRIB_ID_SIDR_RESP); // SIDR response + + MAD_SET_METHOD_TYPE(Mad, MMTHD_SEND); + + MAD_SET_TRANSACTION_ID(Mad, TransactionID); + + // Set up the SIDR REP + Mad->payload.SIDR_RESP.RequestID = RequestID; + Mad->payload.SIDR_RESP.Status = Status; + Mad->payload.SIDR_RESP.AddInfoLen = 0; + Mad->payload.SIDR_RESP.Reserved = 0; + Mad->payload.SIDR_RESP.u.s.QPN = QPN; + Mad->payload.SIDR_RESP.u.s.Reserved2= 0; + Mad->payload.SIDR_RESP.ServiceID = SID; + Mad->payload.SIDR_RESP.QKey = QKey; + + // TODO: If we support redir, need to add the port info here + memset(Mad->payload.SIDR_RESP.AddInfo, 0, CMM_SIDR_RESP_ADD_INFO_LEN); + + if (PrivateDataLen) + memcpy(Mad->payload.SIDR_RESP.PrivateData, pPrivateData, PrivateDataLen); + + memset(Mad->payload.SIDR_RESP.PrivateData + PrivateDataLen, 0, CMM_SIDR_RESP_USER_LEN - PrivateDataLen); + + DUMP_SIDR_RESP(&Mad->payload.SIDR_RESP); + + ConvertMadToNetworkByteOrder(Mad); + +} // FormatSIDR_RESP() + +void +CopySIDR_RESPToSidrRespInfo( + const CMM_SIDR_RESP* pSIDR_RESP, + SIDR_RESP_INFO *pSidrRespInfo) +{ + pSidrRespInfo->QPN = pSIDR_RESP->u.s.QPN; + + pSidrRespInfo->QKey = pSIDR_RESP->QKey; + + pSidrRespInfo->Status = pSIDR_RESP->Status; + + memcpy(pSidrRespInfo->PrivateData, pSIDR_RESP->PrivateData, CMM_SIDR_RESP_USER_LEN); + + DUMP_SIDR_RESP(pSIDR_RESP); + +} // CopySIDR_RESPToSidrRespInfo() + + +FSTATUS +CopyMadToConnInfo( + CONN_INFO* pConnInfo, + const CM_MAD* pMad) +{ + FSTATUS Status=FSUCCESS; + uint32 AttrID=0; + + + MAD_GET_ATTRIB_ID(pMad, &AttrID); + + switch (AttrID) + { + case MCLASS_ATTRIB_ID_REQ: + CopyREQToReqInfo(&pMad->payload.REQ, &pConnInfo->Request); + break; + + case MCLASS_ATTRIB_ID_REP: + CopyREPToRepInfo(&pMad->payload.REP, &pConnInfo->Reply ); + break; + + case MCLASS_ATTRIB_ID_RTU: + // Copy the private data only + memcpy(pConnInfo->Rtu.PrivateData, pMad->payload.RTU.PrivateData, CM_RTU_INFO_USER_LEN); + break; + + case MCLASS_ATTRIB_ID_REJ: + CopyREJToRejectInfo(&pMad->payload.REJ, &pConnInfo->Reject); + break; + + case MCLASS_ATTRIB_ID_DREQ: + // Copy the private data only + memcpy(pConnInfo->DisconnectRequest.PrivateData, pMad->payload.DREQ.PrivateData, CM_DREQUEST_INFO_USER_LEN); + break; + + case MCLASS_ATTRIB_ID_DREP: + // Copy the private data only + memcpy(pConnInfo->DisconnectReply.PrivateData, pMad->payload.DREP.PrivateData, CM_DREPLY_INFO_USER_LEN); + break; + + case MCLASS_ATTRIB_ID_SIDR_REQ: + CopySIDR_REQToSidrReqInfo(&pMad->payload.SIDR_REQ, &pConnInfo->SidrRequest); + break; + + case MCLASS_ATTRIB_ID_SIDR_RESP: + CopySIDR_RESPToSidrRespInfo(&pMad->payload.SIDR_RESP, &pConnInfo->SidrResponse); + break; + + case MCLASS_ATTRIB_ID_MRA: + // no action needed, internally handled in CM + break; + + case MCLASS_ATTRIB_ID_LAP: + CopyLAPToAltPathRequest(&pMad->payload.LAP, &pConnInfo->AltPathRequest); + break; + + case MCLASS_ATTRIB_ID_APR: + CopyAPRToAltPathReply(&pMad->payload.APR, &pConnInfo->AltPathReply); + break; + + default: + Status = FCM_INVALID_EVENT; + break; + + } // switch() + + return Status; + +} // CopyMadToConnInfo() + + + +void +ConvertREQToNetworkOrder(CMM_REQ* pRequest) +{ + // Set up the REQ msg + pRequest->LocalCommID = hton32(pRequest->LocalCommID); + pRequest->Reserved1 = 0; + pRequest->ServiceID = hton64(pRequest->ServiceID); + pRequest->LocalCaGUID = hton64(pRequest->LocalCaGUID); + pRequest->Reserved2 = 0; + pRequest->LocalQKey = hton32(pRequest->LocalQKey); + + pRequest->u1.AsUint32 = hton32(pRequest->u1.AsUint32); + pRequest->u2.AsUint32 = hton32(pRequest->u2.AsUint32); + pRequest->u3.AsUint32 = hton32(pRequest->u3.AsUint32); + pRequest->u4.AsUint32 = hton32(pRequest->u4.AsUint32); + + pRequest->PartitionKey = hton16(pRequest->PartitionKey); + + pRequest->PrimaryLocalLID = hton16(pRequest->PrimaryLocalLID); + pRequest->PrimaryRemoteLID = hton16(pRequest->PrimaryRemoteLID); + + BSWAP_IB_GID(&pRequest->PrimaryLocalGID); + BSWAP_IB_GID(&pRequest->PrimaryRemoteGID); + + pRequest->u5.AsUint32 = hton32(pRequest->u5.AsUint32); + + pRequest->AlternateLocalLID = hton16(pRequest->AlternateLocalLID); + pRequest->AlternateRemoteLID = hton16(pRequest->AlternateRemoteLID); + + BSWAP_IB_GID(&pRequest->AlternateLocalGID); + BSWAP_IB_GID(&pRequest->AlternateRemoteGID); + + pRequest->u6.AsUint32 = hton32(pRequest->u6.AsUint32); + +} // ConvertREQToNetworkOrder() + +void +ConvertREPToNetworkOrder(CMM_REP* pReply) +{ + pReply->LocalCommID = hton32(pReply->LocalCommID); + pReply->RemoteCommID = hton32(pReply->RemoteCommID); + pReply->LocalQKey = hton32(pReply->LocalQKey); + + pReply->u1.AsUint32 = hton32(pReply->u1.AsUint32); + pReply->u2.AsUint32 = hton32(pReply->u2.AsUint32); + pReply->u3.AsUint32 = hton32(pReply->u3.AsUint32); + + + pReply->LocalCaGUID = hton64(pReply->LocalCaGUID); + +} // ConvertREPToNetworkOrder() + +void +ConvertLAPToNetworkOrder(CMM_LAP* pLap) +{ + pLap->LocalCommID = hton32(pLap->LocalCommID); + pLap->RemoteCommID = hton32(pLap->RemoteCommID); + + pLap->u1.AsUint32 = hton32(pLap->u1.AsUint32); + pLap->AlternateLocalLID = hton16(pLap->AlternateLocalLID); + pLap->AlternateRemoteLID = hton16(pLap->AlternateRemoteLID); + BSWAP_IB_GID(&pLap->AlternateLocalGID); + BSWAP_IB_GID(&pLap->AlternateRemoteGID); + pLap->u2.AsUint32 = hton32(pLap->u2.AsUint32); +} // ConvertLAPToNetworkOrder() + +void +ConvertToNetworkOrder(CM_MAD*pMad) +{ + uint32 AttrID=0; + + MAD_GET_ATTRIB_ID(pMad, &AttrID); + + switch (AttrID) + { + case MCLASS_ATTRIB_ID_CLASS_PORT_INFO: + + BSWAP_IB_CLASS_PORT_INFO((IB_CLASS_PORT_INFO*)&pMad->payload.ClassPortInfo); + break; + + case MCLASS_ATTRIB_ID_REQ: + + ConvertREQToNetworkOrder(&pMad->payload.REQ); + break; + + case MCLASS_ATTRIB_ID_REP: + + ConvertREPToNetworkOrder(&pMad->payload.REP); + break; + + case MCLASS_ATTRIB_ID_RTU: + + pMad->payload.RTU.LocalCommID = hton32(pMad->payload.RTU.LocalCommID); + pMad->payload.RTU.RemoteCommID = hton32(pMad->payload.RTU.RemoteCommID); + + break; + + case MCLASS_ATTRIB_ID_REJ: + + pMad->payload.REJ.LocalCommID = hton32(pMad->payload.REJ.LocalCommID); + pMad->payload.REJ.RemoteCommID = hton32(pMad->payload.REJ.RemoteCommID); + + pMad->payload.REJ.Reason = hton16(pMad->payload.REJ.Reason); + + break; + + case MCLASS_ATTRIB_ID_DREQ: + + pMad->payload.DREQ.LocalCommID = hton32(pMad->payload.DREQ.LocalCommID); + pMad->payload.DREQ.RemoteCommID = hton32(pMad->payload.DREQ.RemoteCommID); + pMad->payload.DREQ.u.AsUint32 = hton32(pMad->payload.DREQ.u.AsUint32); + + break; + + case MCLASS_ATTRIB_ID_DREP: + + pMad->payload.DREP.LocalCommID = hton32(pMad->payload.DREP.LocalCommID); + pMad->payload.DREP.RemoteCommID = hton32(pMad->payload.DREP.RemoteCommID); + + break; + + case MCLASS_ATTRIB_ID_SIDR_REQ: + + pMad->payload.SIDR_REQ.RequestID = hton32(pMad->payload.SIDR_REQ.RequestID); + pMad->payload.SIDR_REQ.PartitionKey = hton16(pMad->payload.SIDR_REQ.PartitionKey); + pMad->payload.SIDR_REQ.ServiceID = hton64(pMad->payload.SIDR_REQ.ServiceID); + + break; + + case MCLASS_ATTRIB_ID_SIDR_RESP: + + pMad->payload.SIDR_RESP.RequestID = hton32(pMad->payload.SIDR_RESP.RequestID); + + pMad->payload.SIDR_RESP.u.AsUint32 = hton32(pMad->payload.SIDR_RESP.u.AsUint32); + pMad->payload.SIDR_RESP.ServiceID = hton64(pMad->payload.SIDR_RESP.ServiceID); + + pMad->payload.SIDR_RESP.QKey = hton32(pMad->payload.SIDR_RESP.QKey); + + break; + + case MCLASS_ATTRIB_ID_MRA: + + pMad->payload.MRA.LocalCommID = hton32(pMad->payload.MRA.LocalCommID); + pMad->payload.MRA.RemoteCommID = hton32(pMad->payload.MRA.RemoteCommID); + + break; + + case MCLASS_ATTRIB_ID_LAP: + + ConvertLAPToNetworkOrder(&pMad->payload.LAP); + break; + + case MCLASS_ATTRIB_ID_APR: + + pMad->payload.APR.LocalCommID = hton32(pMad->payload.APR.LocalCommID); + pMad->payload.APR.RemoteCommID = hton32(pMad->payload.APR.RemoteCommID); + break; + + default: + break; + + + } // switch() + + return; + +} // ConvertToNetworkOrder() + +void +ConvertToHostOrder(CM_MAD* pMad) +{ + ConvertToNetworkOrder(pMad); +} // ConvertToHostOrder() + +#if defined( DBG ) || defined( IB_DEBUG ) + +void +DumpClassPortInfo(const IB_CLASS_PORT_INFO* pClassPortInfo) +{ + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, DumpClassPortInfo); + + _DBG_INFO(("\t\tClassPortInfo.BaseVersion = 0x%x\n", pClassPortInfo->BaseVersion)); + _DBG_INFO(("\t\tClassPortInfo.ClassVersion = 0x%x\n", pClassPortInfo->ClassVersion)); + _DBG_INFO(("\t\tClassPortInfo.CapMask = 0x%x\n", pClassPortInfo->CapMask)); + _DBG_INFO(("\t\tClassPortInfo.RespTimeValue = 0x%x\n", pClassPortInfo->u1.s.RespTimeValue)); + _DBG_LEAVE_LVL(_DBG_LVL_FUNC_TRACE); +} // DumpClassPortInfo() + +void +DumpREQ(const CMM_REQ* pREQ) +{ + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, DumpReq); + + _DBG_INFO(("\t\tREQ.LocalCommID = 0x%x\n", pREQ->LocalCommID)); + _DBG_INFO(("\t\tREQ.ServiceID = 0x%"PRIx64"\n", pREQ->ServiceID)); + _DBG_INFO(("\t\tREQ.LocalCaGUID = 0x%"PRIx64"\n", pREQ->LocalCaGUID)); + _DBG_INFO(("\t\tREQ.LocalQKey = 0x%x\n", pREQ->LocalQKey)); + + _DBG_INFO(("\t\tREQ.LocalQPN = 0x%x\n", pREQ->u1.s.LocalQPN)); + _DBG_INFO(("\t\tREQ.OfferedResponderResources = 0x%x\n", pREQ->u1.s.OfferedResponderResources)); + _DBG_INFO(("\t\tREQ.LocalEECN = 0x%x\n", pREQ->u2.s.LocalEECN)); + _DBG_INFO(("\t\tREQ.OfferedInitiatorDepth = 0x%x\n", pREQ->u2.s.OfferedInitiatorDepth)); + _DBG_INFO(("\t\tREQ.RemoteEECN = 0x%x\n", pREQ->u3.s.RemoteEECN)); + _DBG_INFO(("\t\tREQ.RemoteCMTimeout = 0x%x\n", pREQ->u3.s.RemoteCMTimeout)); + _DBG_INFO(("\t\tREQ.TransportServiceType = 0x%x\n", pREQ->u3.s.TransportServiceType)); + _DBG_INFO(("\t\tREQ.EndToEndFlowControl = 0x%x\n", pREQ->u3.s.EndToEndFlowControl)); + + _DBG_INFO(("\t\tREQ.StartingPSN = 0x%x\n", pREQ->u4.s.StartingPSN)); + _DBG_INFO(("\t\tREQ.LocalCMTimeout = 0x%x\n", pREQ->u4.s.LocalCMTimeout)); + _DBG_INFO(("\t\tREQ.RetryCount = 0x%x\n", pREQ->u4.s.RetryCount)); + _DBG_INFO(("\t\tREQ.PartitionKey = 0x%x\n", pREQ->PartitionKey)); + _DBG_INFO(("\t\tREQ.PathMTU = 0x%x\n", pREQ->PathMTU)); + _DBG_INFO(("\t\tREQ.RdcExists = 0x%x\n", pREQ->RdcExists)); + _DBG_INFO(("\t\tREQ.RnRRetryCount = 0x%x\n", pREQ->RnRRetryCount)); + _DBG_INFO(("\t\tREQ.MaxCMRetries = 0x%x\n", pREQ->MaxCMRetries)); + + _DBG_INFO(("\t\tREQ.PrimaryLocalLID = 0x%x\n", pREQ->PrimaryLocalLID)); + _DBG_INFO(("\t\tREQ.PrimaryLocalGID = Subnet Prefix (0x%"PRIx64") Interface ID(0x%"PRIx64")\n", + pREQ->PrimaryLocalGID.Type.Global.SubnetPrefix, pREQ->PrimaryLocalGID.Type.Global.InterfaceID)); + + _DBG_INFO(("\t\tREQ.PrimaryRemoteLID = 0x%x\n", pREQ->PrimaryRemoteLID)); + _DBG_INFO(("\t\tREQ.PrimaryRemoteGID = Subnet Prefix (0x%"PRIx64") Interface ID(0x%"PRIx64")\n", + pREQ->PrimaryRemoteGID.Type.Global.SubnetPrefix, pREQ->PrimaryRemoteGID.Type.Global.InterfaceID)); + _DBG_INFO(("\t\tREQ.PrimaryFlowLabel = 0x%x\n", pREQ->u5.s.PrimaryFlowLabel)); + _DBG_INFO(("\t\tREQ.PrimaryPacketRate = 0x%x\n", pREQ->u5.s.PrimaryPacketRate)); + _DBG_INFO(("\t\tREQ.PrimaryTrafficClass = 0x%x\n", pREQ->PrimaryTrafficClass)); + _DBG_INFO(("\t\tREQ.PrimaryHopLimit = 0x%x\n", pREQ->PrimaryHopLimit)); + _DBG_INFO(("\t\tREQ.PrimarySL = 0x%x\n", pREQ->PrimarySL)); + _DBG_INFO(("\t\tREQ.PrimarySubnetLocal = 0x%x\n", pREQ->PrimarySubnetLocal)); + _DBG_INFO(("\t\tREQ.PrimaryLocalAckTimeout = 0x%x\n", pREQ->PrimaryLocalAckTimeout)); + + if (pREQ->AlternateLocalLID) + { + _DBG_INFO(("\t\tREQ.AlternateLocalLID = 0x%x\n", pREQ->AlternateLocalLID)); + _DBG_INFO(("\t\tREQ.AlternateLocalGID = Subnet Prefix (0x%"PRIx64") Interface ID(0x%"PRIx64")\n", + pREQ->AlternateLocalGID.Type.Global.SubnetPrefix, pREQ->AlternateLocalGID.Type.Global.InterfaceID)); + + _DBG_INFO(("\t\tREQ.AlternateRemoteLID = 0x%x\n", pREQ->AlternateRemoteLID)); + _DBG_INFO(("\t\tREQ.AlternateRemoteGID = Subnet Prefix (0x%"PRIx64") Interface ID(0x%"PRIx64")\n", + pREQ->AlternateRemoteGID.Type.Global.SubnetPrefix, pREQ->AlternateRemoteGID.Type.Global.InterfaceID)); + _DBG_INFO(("\t\tREQ.AlternateFlowLabel = 0x%x\n", pREQ->u6.s.AlternateFlowLabel)); + _DBG_INFO(("\t\tREQ.AlternatePacketRate = 0x%x\n", pREQ->u6.s.AlternatePacketRate)); + _DBG_INFO(("\t\tREQ.AlternateTrafficClass = 0x%x\n", pREQ->AlternateTrafficClass)); + _DBG_INFO(("\t\tREQ.AlternateHopLimit = 0x%x\n", pREQ->AlternateHopLimit)); + _DBG_INFO(("\t\tREQ.AlternateSL = 0x%x\n", pREQ->AlternateSL)); + _DBG_INFO(("\t\tREQ.AlternateSubnetLocal = 0x%x\n", pREQ->AlternateSubnetLocal)); + _DBG_INFO(("\t\tREQ.AlternateLocalAckTimeout = 0x%x\n", pREQ->AlternateLocalAckTimeout)); + } + _DBG_LEAVE_LVL(_DBG_LVL_FUNC_TRACE); +} // DumpREQ() + +void +DumpReqInfo(const CM_REQUEST_INFO* pReqInfo) +{ + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, DumpReqInfo); + _DBG_INFO(("\t\tRequestInfo.PathInfo.bSubnetLocal = 0x%x\n", pReqInfo->PathInfo.bSubnetLocal)); + _DBG_INFO(("\t\tRequestInfo.PathInfo.Path.SLID = 0x%x\n", pReqInfo->PathInfo.Path.SLID)); + _DBG_INFO(("\t\tRequestInfo.PathInfo.Path.DLID = 0x%x\n", pReqInfo->PathInfo.Path.DLID)); + + _DBG_INFO(("\t\tRequestInfo.PathInfo.Path.u1.s.FlowLabel = 0x%x\n", pReqInfo->PathInfo.Path.u1.s.FlowLabel)); + _DBG_INFO(("\t\tRequestInfo.PathInfo.Path.u1.s.HopLimit = 0x%x\n", pReqInfo->PathInfo.Path.u1.s.HopLimit)); + _DBG_INFO(("\t\tRequestInfo.PathInfo.Path.TClass = 0x%x\n", pReqInfo->PathInfo.Path.TClass)); + _DBG_INFO(("\t\tRequestInfo.PathInfo.Path.u2.s.SL = 0x%x\n", pReqInfo->PathInfo.Path.u2.s.SL)); + _DBG_INFO(("\t\tRequestInfo.PathInfo.Path.Rate = 0x%x\n", pReqInfo->PathInfo.Path.Rate)); + _DBG_INFO(("\t\tRequestInfo.PathInfo.Path.P_Key = 0x%x\n", pReqInfo->PathInfo.Path.P_Key)); + _DBG_INFO(("\t\tRequestInfo.PathInfo.Path.Mtu = 0x%x\n", pReqInfo->PathInfo.Path.Mtu)); + _DBG_INFO(("\t\tRequestInfo.PathInfo.Path.PktLifeTime = 0x%x\n", pReqInfo->PathInfo.Path.PktLifeTime)); + + _DBG_INFO(("\t\tRequestInfo.CEPInfo.CaGUID = 0x%"PRIx64"\n", pReqInfo->CEPInfo.CaGUID)); + _DBG_INFO(("\t\tRequestInfo.CEPInfo.EndToEndFlowControl = 0x%x\n", pReqInfo->CEPInfo.EndToEndFlowControl)); + //_DBG_INFO(("\t\tRequestInfo.CEPInfo.PortGUID = 0x%"PRIx64"\n", pReqInfo->CEPInfo.PortGUID)); + _DBG_INFO(("\t\tRequestInfo.CEPInfo.StartingPSN = 0x%x\n", pReqInfo->CEPInfo.StartingPSN)); + _DBG_INFO(("\t\tRequestInfo.CEPInfo.QPN = 0x%x\n", pReqInfo->CEPInfo.QPN)); + _DBG_INFO(("\t\tRequestInfo.CEPInfo.QKey = 0x%x\n", pReqInfo->CEPInfo.QKey)); + _DBG_INFO(("\t\tRequestInfo.CEPInfo.RetryCount = 0x%x\n", pReqInfo->CEPInfo.RetryCount)); + _DBG_INFO(("\t\tRequestInfo.CEPInfo.RnrRetryCount = 0x%x\n", pReqInfo->CEPInfo.RnrRetryCount)); + _DBG_INFO(("\t\tRequestInfo.CEPInfo.AckTimeout = 0x%x\n", pReqInfo->CEPInfo.AckTimeout)); + _DBG_INFO(("\t\tRequestInfo.CEPInfo.AlternateAckTimeout = 0x%x\n", pReqInfo->CEPInfo.AlternateAckTimeout)); + _DBG_INFO(("\t\tRequestInfo.CEPInfo.OfferedResponderResources = 0x%x\n", pReqInfo->CEPInfo.OfferedResponderResources)); + _DBG_INFO(("\t\tRequestInfo.CEPInfo.OfferedInitiatorDepth = 0x%x\n", pReqInfo->CEPInfo.OfferedInitiatorDepth)); + _DBG_INFO(("\t\tRequestInfo.CEPInfo.LocalEECN = 0x%x\n", pReqInfo->CEPInfo.LocalEECN)); + _DBG_INFO(("\t\tRequestInfo.CEPInfo.RemoteEECN = 0x%x\n", pReqInfo->CEPInfo.RemoteEECN)); + + _DBG_LEAVE_LVL(_DBG_LVL_FUNC_TRACE); +} // DumpReqInfo() + + +void +DumpREP(const CMM_REP* pREP) +{ + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, DumpRep); + _DBG_INFO(("\t\tREP.LocalCommID = 0x%x\n", pREP->LocalCommID)); + _DBG_INFO(("\t\tREP.RemoteCommID = 0x%x\n", pREP->RemoteCommID)); + _DBG_INFO(("\t\tREP.LocalQKey = 0x%x\n", pREP->LocalQKey)); + _DBG_INFO(("\t\tREP.LocalQPN = 0x%x\n", pREP->u1.s.LocalQPN)); + _DBG_INFO(("\t\tREP.LocalEECN = 0x%x\n", pREP->u2.s.LocalEECN)); + _DBG_INFO(("\t\tREP.StartingPSN = 0x%x\n", pREP->u3.s.StartingPSN)); + _DBG_INFO(("\t\tREP.ArbResponderResources = 0x%x\n", pREP->ArbResponderResources)); + _DBG_INFO(("\t\tREP.ArbInitiatorDepth = 0x%x\n", pREP->ArbInitiatorDepth)); + _DBG_INFO(("\t\tREP.TargetAckDelay = 0x%x\n", pREP->TargetAckDelay)); + _DBG_INFO(("\t\tREP.EndToEndFlowControl = 0x%x\n", pREP->EndToEndFlowControl)); + _DBG_INFO(("\t\tREP.RnRRetryCount = 0x%x\n", pREP->RnRRetryCount)); + _DBG_INFO(("\t\tREP.LocalCaGUID = 0x%"PRIx64"\n", pREP->LocalCaGUID)); + + _DBG_LEAVE_LVL(_DBG_LVL_FUNC_TRACE); +} //DumpREP() + +void +DumpRepInfo(const CM_REPLY_INFO* pRepInfo) +{ + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, DumpRepInfo); + _DBG_INFO(("\t\tReplyInfo.QKey = 0x%x\n", pRepInfo->QKey)); + _DBG_INFO(("\t\tReplyInfo.QPN = %d\n", pRepInfo->QPN)); + _DBG_INFO(("\t\tReplyInfo.EECN = %d\n", pRepInfo->EECN)); + _DBG_INFO(("\t\tReplyInfo.StartingPSN = %d\n", pRepInfo->StartingPSN)); + _DBG_INFO(("\t\tReplyInfo.ArbResponderResources = %d\n", pRepInfo->ArbResponderResources)); + _DBG_INFO(("\t\tReplyInfo.ArbInitiatorDepth = %d\n", pRepInfo->ArbInitiatorDepth)); + _DBG_INFO(("\t\tReplyInfo.TargetAckDelay = %d\n", pRepInfo->TargetAckDelay)); + _DBG_INFO(("\t\tReplyInfo.FailoverAccepted = %d\n", pRepInfo->FailoverAccepted)); + _DBG_INFO(("\t\tReplyInfo.EndToEndFlowControl = %d\n", pRepInfo->EndToEndFlowControl)); + _DBG_INFO(("\t\tReplyInfo.RnRRetryCount = %d\n", pRepInfo->RnRRetryCount)); + _DBG_INFO(("\t\tReplyInfo.CaGUID = 0x%"PRIx64"\n", pRepInfo->CaGUID)); + _DBG_LEAVE_LVL(_DBG_LVL_FUNC_TRACE); +} // DumpRepInfo() + +void DumpREJ(const CMM_REJ* pREJ) +{ + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, DumpRej); + _DBG_INFO(("\t\tREJ.LocalCommID = 0x%x\n", pREJ->LocalCommID)); + _DBG_INFO(("\t\tREJ.RemoteCommID = 0x%x\n", pREJ->RemoteCommID)); + _DBG_INFO(("\t\tREJ.MsgRejected = 0x%x\n", pREJ->MsgRejected)); + _DBG_INFO(("\t\tREJ.RejectInfoLen = 0x%x\n", pREJ->RejectInfoLen)); + _DBG_INFO(("\t\tREJ.Reason = 0x%x\n", pREJ->Reason)); + + _DBG_LEAVE_LVL(_DBG_LVL_FUNC_TRACE); +} // DumpREJ() + +void +DumpRejInfo(const CM_REJECT_INFO* pRejectInfo) +{ + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, DumpRejInfo); + _DBG_INFO(("\t\tRejectInfo.RejectInfoLen = %d\n", pRejectInfo->RejectInfoLen)); + _DBG_INFO(("\t\tRejectInfo.Reason = %d\n", pRejectInfo->Reason)); + _DBG_LEAVE_LVL(_DBG_LVL_FUNC_TRACE); +} // DumpRejInfo() + +void +DumpLAP(const CMM_LAP* pLAP) +{ + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, DumpLAP); + _DBG_INFO(("\t\tLAP.LocalCommID = 0x%x\n", pLAP->LocalCommID)); + _DBG_INFO(("\t\tLAP.RemoteCommID = 0x%x\n", pLAP->RemoteCommID)); + _DBG_INFO(("\t\tLAP.RemoteQPNorEECN = 0x%x\n", pLAP->u1.s.RemoteQPNorEECN)); + _DBG_INFO(("\t\tLAP.RemoteCMTimeout = 0x%x\n", pLAP->u1.s.RemoteCMTimeout)); + _DBG_INFO(("\t\tLAP.AlternateLocalLID = 0x%x\n", pLAP->AlternateLocalLID)); + _DBG_INFO(("\t\tLAP.AlternateLocalGID = Subnet Prefix (0x%"PRIx64") Interface ID(0x%"PRIx64")\n", + pLAP->AlternateLocalGID.Type.Global.SubnetPrefix, pLAP->AlternateLocalGID.Type.Global.InterfaceID)); + + _DBG_INFO(("\t\tLAP.AlternateRemoteLID = 0x%x\n", pLAP->AlternateRemoteLID)); + _DBG_INFO(("\t\tLAP.AlternateRemoteGID = Subnet Prefix (0x%"PRIx64") Interface ID(0x%"PRIx64")\n", + pLAP->AlternateRemoteGID.Type.Global.SubnetPrefix, pLAP->AlternateRemoteGID.Type.Global.InterfaceID)); + _DBG_INFO(("\t\tLAP.AlternateFlowLabel = 0x%x\n", pLAP->u2.s.AlternateFlowLabel)); + _DBG_INFO(("\t\tLAP.AlternateTrafficClass = 0x%x\n", pLAP->u2.s.AlternateTrafficClass)); + _DBG_INFO(("\t\tLAP.AlternateHopLimit = 0x%x\n", pLAP->AlternateHopLimit)); + _DBG_INFO(("\t\tLAP.AlternatePacketRate = 0x%x\n", pLAP->AlternatePacketRate)); + _DBG_INFO(("\t\tLAP.AlternateSL = 0x%x\n", pLAP->AlternateSL)); + _DBG_INFO(("\t\tLAP.AlternateSubnetLocal = 0x%x\n", pLAP->AlternateSubnetLocal)); + _DBG_INFO(("\t\tLAP.AlternateLocalAckTimeout = 0x%x\n", pLAP->AlternateLocalAckTimeout)); + _DBG_LEAVE_LVL(_DBG_LVL_FUNC_TRACE); +} + +void +DumpLapInfo(const CM_ALTPATH_INFO* pLapInfo) +{ + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, DumpLapInfo); + _DBG_INFO(("\t\tLapInfo.AlternateAckTimeout = 0x%x\n", pLapInfo->AlternateAckTimeout)); + _DBG_INFO(("\t\tLapInfo.AlternatePathInfo.bSubnetLocal = 0x%x\n", pLapInfo->AlternatePathInfo.bSubnetLocal)); + _DBG_INFO(("\t\tLapInfo.AlternatePathInfo.Path.SLID = 0x%x\n", pLapInfo->AlternatePathInfo.Path.SLID)); + _DBG_INFO(("\t\tLapInfo.AlternatePathInfo.Path.DLID = 0x%x\n", pLapInfo->AlternatePathInfo.Path.DLID)); + + _DBG_INFO(("\t\tLapInfo.AlternatePathInfo.Path.u1.s.FlowLabel = 0x%x\n", pLapInfo->AlternatePathInfo.Path.u1.s.FlowLabel)); + _DBG_INFO(("\t\tLapInfo.AlternatePathInfo.Path.u1.s.HopLimit = 0x%x\n", pLapInfo->AlternatePathInfo.Path.u1.s.HopLimit)); + _DBG_INFO(("\t\tLapInfo.AlternatePathInfo.Path.TClass = 0x%x\n", pLapInfo->AlternatePathInfo.Path.TClass)); + _DBG_INFO(("\t\tLapInfo.AlternatePathInfo.Path.u2.s.SL = 0x%x\n", pLapInfo->AlternatePathInfo.Path.u2.s.SL)); + _DBG_INFO(("\t\tLapInfo.AlternatePathInfo.Path.Rate = 0x%x\n", pLapInfo->AlternatePathInfo.Path.Rate)); + _DBG_INFO(("\t\tLapInfo.AlternatePathInfo.Path.P_Key = 0x%x\n", pLapInfo->AlternatePathInfo.Path.P_Key)); + _DBG_INFO(("\t\tLapInfo.AlternatePathInfo.Path.Mtu = 0x%x\n", pLapInfo->AlternatePathInfo.Path.Mtu)); + _DBG_INFO(("\t\tLapInfo.AlternatePathInfo.Path.PktLifeTime = 0x%x\n", pLapInfo->AlternatePathInfo.Path.PktLifeTime)); + _DBG_LEAVE_LVL(_DBG_LVL_FUNC_TRACE); +} + +void DumpAPR(const CMM_APR* pAPR) +{ + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, DumpAPR); + _DBG_INFO(("\t\tAPR.LocalCommID = 0x%x\n", pAPR->LocalCommID)); + _DBG_INFO(("\t\tAPR.RemoteCommID = 0x%x\n", pAPR->RemoteCommID)); + _DBG_INFO(("\t\tAPR.APStatus = 0x%x\n", pAPR->APStatus)); + _DBG_INFO(("\t\tAPR.AddInfoLen = 0x%x\n", pAPR->AddInfoLen)); + _DBG_LEAVE_LVL(_DBG_LVL_FUNC_TRACE); +} // DumpAPR() + +void +DumpAprInfo(const CM_ALTPATH_REPLY_INFO* pAprInfo) +{ + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, DumpAprInfo); + _DBG_INFO(("\t\tAprInfo.u.AddInfo.Len = %d\n", pAprInfo->u.AddInfo.Len)); + _DBG_INFO(("\t\tAprInfo.APStatus = %d\n", pAprInfo->APStatus)); + _DBG_LEAVE_LVL(_DBG_LVL_FUNC_TRACE); +} // DumpAprInfo() + +void DumpDREQ(const CMM_DREQ* pDREQ) +{ + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, DumpDREQ); + _DBG_INFO(("\t\tDREQ.LocalCommID = 0x%x\n", pDREQ->LocalCommID)); + _DBG_INFO(("\t\tDREQ.RemoteCommID = 0x%x\n", pDREQ->RemoteCommID)); + _DBG_INFO(("\t\tDREQ.RemoteQPNorEECN = 0x%x\n", pDREQ->u.s.RemoteQPNorEECN)); + + _DBG_LEAVE_LVL(_DBG_LVL_FUNC_TRACE); +} // DumpDREQ() + +void +DumpDReqInfo(const CM_DREQUEST_INFO* pDReqInfo) +{ +} // DumpDReqInfo() + +void DumpSIDR_REQ(const CMM_SIDR_REQ* pSIDR_REQ) +{ + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, DumpSIDR_REQ); + _DBG_INFO(("\t\tSIDR_REQ.RequestID = 0x%x\n", pSIDR_REQ->RequestID)); + _DBG_INFO(("\t\tSIDR_REQ.PartitionKey = 0x%04x\n", pSIDR_REQ->PartitionKey)); + _DBG_INFO(("\t\tSIDR_REQ.ServiceID = 0x%"PRIx64"\n", pSIDR_REQ->ServiceID)); + + _DBG_LEAVE_LVL(_DBG_LVL_FUNC_TRACE); +} // DumpSIDR_REQ() + +void DumpSidrReqInfo(const SIDR_REQ_INFO* pSidrReqInfo) +{ + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, DumpSidrReqInfo); + _DBG_INFO(("\t\tSidrReqInfo.SID = 0x%"PRIx64"\n", pSidrReqInfo->SID)); + _DBG_INFO(("\t\tSidrReqInfo.PartitionKey = 0x%04x\n", pSidrReqInfo->PartitionKey)); + _DBG_INFO(("\t\tSidrReqInfo.PortGuid = 0x%"PRIx64"\n", pSidrReqInfo->PortGuid)); + _DBG_INFO(("\t\tSidrReqInfo.PathInfo.Path.DLID = 0x%x\n", pSidrReqInfo->PathInfo.Path.DLID)); + _DBG_INFO(("\t\tSidrReqInfo.PathInfo.Path.u2.s.SL = 0x%x\n", pSidrReqInfo->PathInfo.Path.u2.s.SL)); + _DBG_INFO(("\t\tSidrReqInfo.PathInfo.Path.Rate = 0x%x\n", pSidrReqInfo->PathInfo.Path.Rate)); + + _DBG_LEAVE_LVL(_DBG_LVL_FUNC_TRACE); +} // DumpSidrReqInfo() + +void DumpSIDR_RESP(const CMM_SIDR_RESP* pSIDR_RESP) +{ + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, DumpSIDR_RESP); + _DBG_INFO(("\t\tSIDR_RESP.RequestID = 0x%x\n", pSIDR_RESP->RequestID)); + _DBG_INFO(("\t\tSIDR_RESP.Status = 0x%x\n", pSIDR_RESP->Status)); + _DBG_INFO(("\t\tSIDR_RESP.AddInfoLen = 0x%x\n", pSIDR_RESP->AddInfoLen)); + _DBG_INFO(("\t\tSIDR_RESP.QPN = 0x%x\n", pSIDR_RESP->u.s.QPN)); + _DBG_INFO(("\t\tSIDR_RESP.ServiceID = 0x%"PRIx64"\n", pSIDR_RESP->ServiceID)); + _DBG_INFO(("\t\tSIDR_RESP.QKey = 0x%x\n", pSIDR_RESP->QKey)); + + _DBG_LEAVE_LVL(_DBG_LVL_FUNC_TRACE); +} // DumpSIDR_RESP() + +void DumpSidrRespInfo(const SIDR_RESP_INFO* pSidrRespInfo) +{ + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, DumpSidrRespInfo); + _DBG_INFO(("\t\tSidrRespInfo.QPN = 0x%x\n", pSidrRespInfo->QPN)); + _DBG_INFO(("\t\tSidrRespInfo.Status = 0x%x\n", pSidrRespInfo->Status)); + _DBG_INFO(("\t\tSidrRespInfo.QKey = 0x%x\n", pSidrRespInfo->QKey)); + + _DBG_LEAVE_LVL(_DBG_LVL_FUNC_TRACE); +} // DumpSidrRespInfo() + +#endif // #if defined( DBG ) || defined( IB_DEBUG ) diff --git a/IbAccess/Common/Ibt/Cm/cm_msg.h b/IbAccess/Common/Ibt/Cm/cm_msg.h new file mode 100644 index 0000000..2c9786d --- /dev/null +++ b/IbAccess/Common/Ibt/Cm/cm_msg.h @@ -0,0 +1,828 @@ +/* BEGIN_ICS_COPYRIGHT4 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT4 ****************************************/ +/* [ICS VERSION STRING: unknown] */ + +/* Suppress duplicate loading of this file */ +#ifndef _INSI_IB_CM_MSG_H_ +#define _INSI_IB_CM_MSG_H_ + + +#if defined (__cplusplus) +extern "C" { +#endif + +#include "datatypes.h" +#include "stl_types.h" +#include "stl_mad_priv.h" +#include "ibyteswap.h" + +#include "ib_generalServices.h" +#include "ib_cm.h" + +/**************************************************************************** + * IB CM attribute ID per 1.0a and 1.1 spec + */ + +#define MCLASS_ATTRIB_ID_CLASS_PORT_INFO 0x0001 + +#define MCLASS_ATTRIB_ID_REQ 0x0010 /* Connection Request */ +#define MCLASS_ATTRIB_ID_MRA 0x0011 /* Message Receipt Ack */ +#define MCLASS_ATTRIB_ID_REJ 0x0012 /* Connection Reject */ +#define MCLASS_ATTRIB_ID_REP 0x0013 /* Connection Reply */ +#define MCLASS_ATTRIB_ID_RTU 0x0014 /* Ready To Use */ +#define MCLASS_ATTRIB_ID_DREQ 0x0015 /* Disconnect Request */ +#define MCLASS_ATTRIB_ID_DREP 0x0016 /* Disconnect Reply */ +#define MCLASS_ATTRIB_ID_SIDR_REQ 0x0017 /* Service ID Resolution Req */ +#define MCLASS_ATTRIB_ID_SIDR_RESP 0x0018 /* Service ID Resolution Resp */ +#define MCLASS_ATTRIB_ID_LAP 0x0019 /* Load Alternate Path */ +#define MCLASS_ATTRIB_ID_APR 0x001A /* Alternate Path Response */ + + +/**************************************************************************** + * CMM_XXX + * IB-defined connection messages on the wire. Each message is a fixed 232 bytes + * in length and occupy the data portion of the CM_MAD. + */ + +/* Private/user data length in bytes */ +#define CMM_REQ_USER_LEN 92 +#define CMM_REP_USER_LEN 196 +#define CMM_REJ_USER_LEN 148 +#define CMM_RTU_USER_LEN 224 +#define CMM_MRA_USER_LEN 222 +#define CMM_DREQ_USER_LEN 220 +#define CMM_DREP_USER_LEN 224 +#define CMM_SIDR_REQ_USER_LEN 216 +#define CMM_SIDR_RESP_USER_LEN 136 +#define CMM_LAP_USER_LEN 168 +#define CMM_APR_USER_LEN 148 +#define CMM_REJ_ADD_INFO_LEN 72 /* Additional reject info length */ +#define CMM_SIDR_RESP_ADD_INFO_LEN 72 /* Additional Error Infomation length */ +#define CMM_APR_ADD_INFO_LEN 72 /* Additional Alt Path Resp info len */ + +typedef enum { + CM_REJECT_REQUEST=0, + CM_REJECT_REPLY, + CM_REJECT_UNKNOWN +} CMM_REJ_MSGTYPE; + +typedef enum { + CM_MRA_REQUEST=0, + CM_MRA_REPLY, + CM_MRA_LAP +} CMM_MRA_MSGTYPE; + +#include "ipackon.h" + +/* + * CMM_REQ - + * Connection request message (REQ) + */ +typedef struct _CMM_REQ { + + uint32 LocalCommID; + uint32 Reserved1; + uint64 ServiceID; + uint64 LocalCaGUID; + uint32 Reserved2; + uint32 LocalQKey; + union { + uint32 AsUint32; + struct { + IB_BITFIELD2(uint32, + LocalQPN:24, + OfferedResponderResources:8) + } PACK_SUFFIX s; + } u1; + + union { + uint32 AsUint32; + struct { + IB_BITFIELD2(uint32, + LocalEECN:24, + OfferedInitiatorDepth:8) + } PACK_SUFFIX s; + } u2; + + union { + uint32 AsUint32; + struct { + IB_BITFIELD4(uint32, + RemoteEECN:24, + RemoteCMTimeout:5, + TransportServiceType:2, + EndToEndFlowControl:1) + } PACK_SUFFIX s; + } u3; + + union { + uint32 AsUint32; + struct { + IB_BITFIELD3(uint32, + StartingPSN:24, + LocalCMTimeout:5, + RetryCount:3) + } PACK_SUFFIX s; + } u4; + + uint16 PartitionKey; + + IB_BITFIELD3(uint8, + PathMTU:4, /* see IB_MTU */ + RdcExists:1, + RnRRetryCount:3) + IB_BITFIELD2(uint8, + MaxCMRetries:4, + Reserved3:4) + + /* Primary Path Information */ + IB_LID PrimaryLocalLID; + IB_LID PrimaryRemoteLID; + IB_GID PrimaryLocalGID; + IB_GID PrimaryRemoteGID; + + union { + uint32 AsUint32; + + struct { + IB_BITFIELD3(uint32, + PrimaryFlowLabel:20, + Reserved4:6, + PrimaryPacketRate:6) + } PACK_SUFFIX s; + } u5; + + uint8 PrimaryTrafficClass; + uint8 PrimaryHopLimit; + IB_BITFIELD3(uint8, + PrimarySL:4, + PrimarySubnetLocal:1, + Reserved5:3) + IB_BITFIELD2(uint8, + PrimaryLocalAckTimeout:5, + Reserved6:3) + + /* Alternate Path Information */ + IB_LID AlternateLocalLID; + IB_LID AlternateRemoteLID; + IB_GID AlternateLocalGID; + IB_GID AlternateRemoteGID; + + union { + uint32 AsUint32; + struct { + IB_BITFIELD3(uint32, + AlternateFlowLabel:20, + Reserved7:6, + AlternatePacketRate:6) + } PACK_SUFFIX s; + } u6; + + uint8 AlternateTrafficClass; + uint8 AlternateHopLimit; + IB_BITFIELD3(uint8, + AlternateSL:4, + AlternateSubnetLocal:1, + Reserved8:3) + IB_BITFIELD2(uint8, + AlternateLocalAckTimeout:5, + Reserved9:3) + + uint8 PrivateData[CMM_REQ_USER_LEN]; /* User-specified data */ + +} PACK_SUFFIX CMM_REQ; + +/* + * CMM_REP - + * Connection reply message (REP) + */ +typedef struct _CMM_REP { + + uint32 LocalCommID; + uint32 RemoteCommID; + uint32 LocalQKey; + + union { + uint32 AsUint32; + struct { + IB_BITFIELD2(uint32, + LocalQPN:24, + Reserved1:8) + } PACK_SUFFIX s; + } u1; + + union { + uint32 AsUint32; + struct { + IB_BITFIELD2(uint32, + LocalEECN:24, + Reserved2:8) + } PACK_SUFFIX s; + } u2; + + + union { + uint32 AsUint32; + struct { + IB_BITFIELD2(uint32, + StartingPSN:24, + Reserved3:8) + } PACK_SUFFIX s; + } u3; + + + uint8 ArbResponderResources; + uint8 ArbInitiatorDepth; + + IB_BITFIELD3(uint8, + TargetAckDelay:5, + FailoverAccepted:2, /* a CMM_REP_FAILOVER enum */ + EndToEndFlowControl:1) + + IB_BITFIELD2(uint8, + RnRRetryCount:3, + Reserved4:5) + + uint64 LocalCaGUID; + + uint8 PrivateData[CMM_REP_USER_LEN]; /* User-specified data */ + +} PACK_SUFFIX CMM_REP; + +/* + * CMM_REJ - + * Connection reject message (REJ) + */ +typedef struct _CMM_REJ { + + uint32 LocalCommID; + uint32 RemoteCommID; + + IB_BITFIELD2(uint8, + MsgRejected:2, + Reserved1:6) + + IB_BITFIELD2(uint8, + RejectInfoLen:7, + Reserved2:1) + + uint16 Reason; + uint8 RejectInfo[CMM_REJ_ADD_INFO_LEN]; + + uint8 PrivateData[CMM_REJ_USER_LEN]; /* User-specified data */ + +} PACK_SUFFIX CMM_REJ; + +/* + * CMM_RTU - + * Connection ready-to-use message (RTU) + */ +typedef struct _CMM_RTU { + + uint32 LocalCommID; + uint32 RemoteCommID; + + uint8 PrivateData[CMM_RTU_USER_LEN]; /* User-specified data */ +} PACK_SUFFIX CMM_RTU; + + +/* + * CMM_MRA - + * Connection message receipt acknowledge (MRA) + */ +typedef struct _CMM_MRA { + + uint32 LocalCommID; + uint32 RemoteCommID; + + IB_BITFIELD2(uint8, + MsgMraed:2, + Reserved1:6) + + IB_BITFIELD2(uint8, + ServiceTimeout:5, + Reserved2:3) + + uint8 PrivateData[CMM_MRA_USER_LEN]; /* User-specified data */ + +} PACK_SUFFIX CMM_MRA; + +/* + * CMM_DREQ - + * Disconnect request message (DREQ) + */ +typedef struct _CMM_DREQ { + + uint32 LocalCommID; + uint32 RemoteCommID; + + union { + uint32 AsUint32; + struct { + IB_BITFIELD2(uint32, + RemoteQPNorEECN:24, + Reserved:8) + } PACK_SUFFIX s; + } u; + + uint8 PrivateData[CMM_DREQ_USER_LEN]; /* User-specified data */ + +} PACK_SUFFIX CMM_DREQ; + +/* + * CMM_DREP - + * Disconnect reply message (DREP) + */ +typedef struct _CMM_DREP { + + uint32 LocalCommID; + uint32 RemoteCommID; + + uint8 PrivateData[CMM_DREP_USER_LEN]; /* User-specified data */ +} PACK_SUFFIX CMM_DREP; + + +/* + * CMM_SIDR_REQ - + * Service ID resolution request message (SIDR_REQ) + */ +typedef struct _CMM_SIDR_REQ { + + uint32 RequestID; + uint16 PartitionKey; + uint16 Reserved; + + uint64 ServiceID; + uint8 PrivateData[CMM_SIDR_REQ_USER_LEN];/* User-specified data */ +} PACK_SUFFIX CMM_SIDR_REQ; + +/* + * CMM_SIDR_RESP - + * Service ID resolution reply message (SIDR_RESP) + */ +typedef struct _CMM_SIDR_RESP { + + uint32 RequestID; + /* need to pass AddInfo and Len to user in SIDR Resp API */ + uint8 Status; + uint8 AddInfoLen; /* Length of AddInfo in bytes */ + uint16 Reserved; + union { + uint32 AsUint32; + struct { + IB_BITFIELD2(uint32, + QPN:24, + Reserved2:8) + } PACK_SUFFIX s; + } u; + + uint64 ServiceID; + uint32 QKey; /* (24 bits) */ + + uint8 AddInfo[CMM_SIDR_RESP_ADD_INFO_LEN];/* Additional Info + * about a failure + * Status + */ + + uint8 PrivateData[CMM_SIDR_RESP_USER_LEN];/* User-specified data */ +} PACK_SUFFIX CMM_SIDR_RESP; + + + +/* + * CMM_LAP - + * Load alternate path message (LAP) + */ +typedef struct _CMM_LAP { + + uint32 LocalCommID; + uint32 RemoteCommID; + uint32 Reserved1;; + + union { + uint32 AsUint32; + struct { + IB_BITFIELD3(uint32, + RemoteQPNorEECN:24, + RemoteCMTimeout:5, + Reserved2:3) + } PACK_SUFFIX s; + } u1; + uint32 Reserved3; + IB_LID AlternateLocalLID; + IB_LID AlternateRemoteLID; + IB_GID AlternateLocalGID; + IB_GID AlternateRemoteGID; + + union { + uint32 AsUint32; + struct { + IB_BITFIELD3(uint32, + AlternateFlowLabel:20, + Reserved4:4, + AlternateTrafficClass:8) + } PACK_SUFFIX s; + } u2; + + uint8 AlternateHopLimit:8; + IB_BITFIELD2(uint8, + Reserved5:2, + AlternatePacketRate:6) + IB_BITFIELD3(uint8, + AlternateSL:4, + AlternateSubnetLocal:1, + Reserved6:3) + IB_BITFIELD2(uint8, + AlternateLocalAckTimeout:5, + Reserved7:3) + + uint8 PrivateData[CMM_LAP_USER_LEN]; /* User-specified data */ + +} PACK_SUFFIX CMM_LAP; + +/* + * CMM_APR - + * Alternate path response message (APR) + */ +typedef struct _CMM_APR { + + uint32 LocalCommID; + uint32 RemoteCommID; + uint8 AddInfoLen; /* Length of AddInfo in bytes */ + uint8 APStatus; + uint16 Reserved; + uint8 AddInfo[CMM_APR_ADD_INFO_LEN]; /* Additional Information + * about a failure APStatus + */ + + uint8 PrivateData[CMM_APR_USER_LEN]; /* User-specified data */ + +} PACK_SUFFIX CMM_APR; + +typedef union _CMM_MSG { + IB_CLASS_PORT_INFO ClassPortInfo; + CMM_REQ REQ; + CMM_REP REP; + CMM_REJ REJ; + CMM_RTU RTU; + CMM_DREQ DREQ; + CMM_DREP DREP; + CMM_MRA MRA; + CMM_LAP LAP; + CMM_APR APR; + CMM_SIDR_REQ SIDR_REQ; + CMM_SIDR_RESP SIDR_RESP; +} PACK_SUFFIX CMM_MSG; + + +/* + * CM_MAD - + * Connection Manager's Mgmt Datagram. This datagram is passed + * to GSI + */ +typedef struct _CM_MAD { + MAD_COMMON common; /* 24 bytes header */ + CMM_MSG payload;/* 232 bytes payload */ +} PACK_SUFFIX CM_MAD; + + +/* Wire format is BIG-ENDIAN */ +#if CPU_BE +#define ConvertMadToNetworkByteOrder(pMad) +#define ConvertMadToHostByteOrder(pMad) +#else +#define ConvertMadToNetworkByteOrder(pMad) ConvertToNetworkOrder(pMad) +#define ConvertMadToHostByteOrder(pMad) ConvertToHostOrder(pMad) +#endif /* CPU_LE */ + +/* + * based on value of FailoverAccepted in Rep, does remote endpoint + * support failover. This can be inconclusive if REQ did not provide an + * alternate path, it which case its likely the REP will accept it, + * but that doesn't mean the remote endpoint supports failover. + */ +static __inline +boolean IsFailoverSupported(uint8 FailoverAccepted) +{ + return (FailoverAccepted == CM_REP_FO_ACCEPTED + || FailoverAccepted == CM_REP_FO_REJECTED_ALT); +} + +#if defined( DBG ) || defined( IB_DEBUG ) +#define DUMP_CLASS_PORT_INFO(pClassPortInfo) DumpClassPortInfo(pClassPortInfo) +#define DUMP_REQ(pREQ) DumpREQ(pREQ) +#define DUMP_REP(pREP) DumpREP(pREP) +#define DUMP_REJ(pREJ) DumpREJ(pREJ) +#define DUMP_LAP(pREJ) DumpLAP(pREJ) +#define DUMP_APR(pREJ) DumpAPR(pREJ) +#define DUMP_DREQ(pDREQ) DumpDREQ(pDREQ) +#define DUMP_SIDR_REQ(pSIDR_REQ) DumpSIDR_REQ(pSIDR_REQ) +#define DUMP_SIDR_RESP(pSIDR_RESP) DumpSIDR_RESP(pSIDR_RESP) + +#define DUMP_REQ_INFO(pReqInfo) DumpReqInfo(pReqInfo) +#define DUMP_REP_INFO(pRepInfo) DumpRepInfo(pRepInfo) +#define DUMP_REJ_INFO(pRejInfo) DumpRejInfo(pRejInfo) +#define DUMP_LAP_INFO(pLapInfo) DumpLapInfo(pLapInfo) +#define DUMP_APR_INFO(pAprInfo) DumpAprInfo(pAprInfo) +#define DUMP_DREQ_INFO(pDReqInfo) DumpDReqInfo(pDReqInfo) +#define DUMP_SIDR_REQ_INFO(pSidrReqInfo) DumpSidrReqInfo(pSidrReqInfo) +#define DUMP_SIDR_RESP_INFO(pSidrRespInfo) DumpSidrRespInfo(pSidrRespInfo) + +#else +#define DUMP_CLASS_PORT_INFO(pClassPortInfo) +#define DUMP_REQ(pREQ) +#define DUMP_REP(pREP) +#define DUMP_REJ(pREJ) +#define DUMP_LAP(pREJ) +#define DUMP_APR(pREJ) +#define DUMP_DREQ(pDREQ) +#define DUMP_SIDR_REQ(pSIDR_REQ) +#define DUMP_SIDR_RESP(pSIDR_RESP) + +#define DUMP_REQ_INFO(pReqInfo) +#define DUMP_REP_INFO(pRepInfo) +#define DUMP_REJ_INFO(pRejInfo) +#define DUMP_LAP_INFO(pLapInfo) +#define DUMP_APR_INFO(pAprInfo) +#define DUMP_DREQ_INFO(pDReqInfo) +#define DUMP_SIDR_REQ_INFO(pSidrReqInfo) +#define DUMP_SIDR_RESP_INFO(pSidrRespInfo) +#endif + +/**************************************************************************** + * Private function prototypes + */ + +void +FormatClassPortInfo( + IN CM_MAD* Mad, + IN uint64 TransactionID + ); + +void +FormatREQ( + IN CM_MAD* Mad, + IN const CM_REQUEST_INFO* pRequest, + IN uint64 TransactionID, + IN uint32 LocalCommID, + IN uint32 CMQKey, + IN CM_CEP_TYPE Type, + IN uint32 LocalCMTimeout, + IN uint32 RemoteCMTimeout, + IN uint32 MaxCMRetries, + IN uint8 OfferedInitiatorDepth, + IN uint8 OfferedResponderResources + ); +void +CopyREQToReqInfo( + IN const CMM_REQ* pReq, + IN CM_REQUEST_INFO *pInfo + ); + +void +FormatREP( + IN CM_MAD* Mad, + IN const CM_REPLY_INFO* pConnectReply, + IN uint64 TransactionID, + IN uint32 LocalCommID, + IN uint32 RemoteCommID, + IN uint64 LocalCaGUID + ); + +void +CopyREPToRepInfo( + const IN CMM_REP *pREP, + IN OUT CM_REPLY_INFO *pReplyInfo + ); + + +void +FormatREJ( + IN CM_MAD* Mad, + IN uint8 MsgRejected, /* CMM_REJ_MSGTYPE */ + IN uint16 Reason, + IN const uint8* pRejectInfo, + IN uint32 RejectInfoLen, + IN const uint8* pPrivateData, + IN uint32 PrivateDataLen, + IN uint64 TransactionID, + IN uint32 LocalCommID, + IN uint32 RemoteCommID + ); + +void +CopyREJToRejectInfo( + IN const CMM_REJ* pREJ, + IN OUT CM_REJECT_INFO *pRejectInfo + ); + +void +FormatMRA( + IN CM_MAD* Mad, + IN uint8 MsgMraed, /* CMM_MRA_MSGTYPE */ + IN uint8 ServiceTimeout, + IN const uint8* pPrivateData, + IN uint32 PrivateDataLen, + IN uint64 TransactionID, + IN uint32 LocalCommID, + IN uint32 RemoteCommID + ); + +void +FormatRTU( + IN CM_MAD* Mad, + const uint8* pPrivateData, + uint32 PrivateDataLen, + IN uint64 TransactionID, + IN uint32 LocalCommID, + IN uint32 RemoteCommID + ); + +void +FormatLAP( + IN CM_MAD* Mad, + IN uint32 QPN, + IN uint32 RemoteCMTimeout, + IN const CM_ALTPATH_INFO* pAltPath, + IN uint8 AlternateAckTimeout, + IN uint64 TransactionID, + IN uint32 LocalCommID, + IN uint32 RemoteCommID + ); + +void +CopyLAPToAltPathRequest( + IN const CMM_LAP* pLAP, + IN OUT CM_ALTPATH_INFO *pAltPath + ); + +int +CompareLAP( + IN const CMM_LAP* pLAP1, + IN const CMM_LAP* pLAP2 + ); + +void +FormatAPR( + IN CM_MAD* Mad, + IN CM_APR_STATUS APStatus, + IN const uint8* pAddInfo, + IN uint32 AddInfoLen, + IN const uint8* pPrivateData, + IN uint32 PrivateDataLen, + IN uint64 TransactionID, + IN uint32 LocalCommID, + IN uint32 RemoteCommID + ); + +void +CopyAPRToAltPathReply( + IN const CMM_APR* pAPR, + IN OUT CM_ALTPATH_REPLY_INFO *pAltPathReply + ); + + +void +FormatDREQ( + IN CM_MAD* Mad, + IN uint32 QPN, + IN const uint8* pPrivateData, + IN uint32 PrivateDataLen, + IN uint64 TransactionID, + IN uint32 LocalCommID, + IN uint32 RemoteCommID + ); + +void +FormatDREP( + IN CM_MAD* Mad, + IN const uint8* pPrivateData, + IN uint32 PrivateDataLen, + IN uint64 TransactionID, + IN uint32 LocalCommID, + IN uint32 RemoteCommID + ); + +void +FormatSIDR_REQ( + IN CM_MAD* Mad, + IN uint64 SID, + IN uint16 PartitionKey, + IN const uint8* pPrivateData, + IN uint32 PrivateDataLen, + IN uint64 TransactionID, + IN uint32 RequestID + ); + +void +CopySIDR_REQToSidrReqInfo( + IN const CMM_SIDR_REQ* pSIDR_REQ, + IN OUT SIDR_REQ_INFO *pSidrReqInfo + ); + +void +FormatSIDR_RESP( + IN CM_MAD* Mad, + IN uint64 SID, + IN uint32 QPN, + IN uint32 QKey, + IN uint32 Status, + IN const uint8* pPrivateData, + IN uint32 PrivateDataLen, + IN uint64 TransactionID, + IN uint32 RequestID + ); + +void +CopySIDR_RESPToSidrRespInfo( + IN const CMM_SIDR_RESP* pSIDR_RESP, + IN OUT SIDR_RESP_INFO *pSidrRespInfo + ); + + +void +ConvertREQToNetworkOrder( + IN OUT CMM_REQ* pRequest + ); + +void +ConvertREPToNetworkOrder( + IN OUT CMM_REP* pReply + ); +void +ConvertLAPToNetworkOrder( + IN OUT CMM_LAP* pLap + ); + +void +ConvertToNetworkOrder( + IN OUT CM_MAD* pMad + ); + +void +ConvertToHostOrder( + IN OUT CM_MAD* pMad + ); + +#if defined( DBG ) || defined( IB_DEBUG ) + +void DumpClassPortInfo(const IB_CLASS_PORT_INFO* pClassPortInfo); +void DumpREQ(const CMM_REQ* pREQ); +void DumpReqInfo(const CM_REQUEST_INFO* pReqInfo); + +void DumpREP(const CMM_REP* pREP); +void DumpRepInfo(const CM_REPLY_INFO* pRepInfo); + +void DumpREJ(const CMM_REJ* pREJ); +void DumpRejInfo(const CM_REJECT_INFO* pRepInfo); + +void DumpLAP(const CMM_LAP* pLAP); +void DumpLapInfo(const CM_ALTPATH_INFO* pLapInfo); + +void DumpAPR(const CMM_APR* pAPR); +void DumpAprInfo(const CM_ALTPATH_REPLY_INFO* pAprInfo); + +void DumpDREQ(const CMM_DREQ* pDREQ); +void DumpDReqInfo(const CM_DREQUEST_INFO* pDReqInfo); + +void DumpSIDR_REQ(const CMM_SIDR_REQ* pSIDR_REQ); +void DumpSidrReqInfo(const SIDR_REQ_INFO* pSidrReqInfo); + +void DumpSIDR_RESP(const CMM_SIDR_RESP* pSIDR_RESP); +void DumpSidrRespInfo(const SIDR_RESP_INFO* pSidrRespInfo); + +#endif + +#if defined (__cplusplus) +}; +#endif + +#include "ipackoff.h" + +#endif /* _INSI_IB_CM_MSG_H_ */ diff --git a/IbAccess/Common/Ibt/Cm/cm_passive.c b/IbAccess/Common/Ibt/Cm/cm_passive.c new file mode 100644 index 0000000..293ef95 --- /dev/null +++ b/IbAccess/Common/Ibt/Cm/cm_passive.c @@ -0,0 +1,1379 @@ +/* BEGIN_ICS_COPYRIGHT4 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT4 ****************************************/ + +// Public header file +#include "ib_cm.h" + +// Private header file +#include "cm_private.h" + +////////////////////////////////////////////////////////////////////////// +// Listen +// +// Prepare CEP for Listening and put on ListenMap +// +// +// INPUTS: +// +// +// +// OUTPUTS: +// +// None. +// +// RETURNS: +// +// FSUCCESS. +// +// IRQL: +// +// This routine is called at IRQL_PASSIVE_LEVEL. +// Called with ListLock held, which protects lists and all CEPs +// +FSTATUS +Listen( + IN CM_CEP_OBJECT* pCEP, + IN CM_LISTEN_INFO* pListenInfo, + IN PFN_CM_CALLBACK pfnListenCB, + IN void* Context + ) +{ + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, Listen); + + // If we are binding to a specific port, we need the CaGUID of the port + // so that during CmRemoveDevice(), we can cancel this listen + pCEP->LocalEndPoint.CaGUID = pListenInfo->CaGUID; + ASSERT(! pCEP->bPeer); + + // Bind address is based on SID with secondary optional + // Local/Remote GID/LID and the Private Data Discriminator + // (set via CmModifyCEP) + // Hence more than one CEP could use the same SID, provided they have unique + // combinations of values for the other fields. Values of 0 + // represent wildcarding the given field (SID can't be wildcarded) + pCEP->SID = pListenInfo->ListenAddr.EndPt.SID; + pCEP->PrimaryPath.LocalLID = pListenInfo->ListenAddr.Port.LID; + pCEP->PrimaryPath.LocalGID = pListenInfo->ListenAddr.Port.GID; + + pCEP->PrimaryPath.RemoteLID = pListenInfo->RemoteAddr.Port.LID; + pCEP->PrimaryPath.RemoteGID = pListenInfo->RemoteAddr.Port.GID; + + pCEP->LocalEndPoint.QPN = pCEP->LocalEndPoint.EECN = 0; + pCEP->RemoteEndPoint.QPN = pCEP->RemoteEndPoint.EECN = 0; + + // add to ListenMap and make sure bound address is unique + if (! CM_MapTryInsert(&gCM->ListenMap, (uintn)pCEP, &pCEP->MapEntry, "LISTEN_LIST", pCEP)) + { + _DBG_WARNING((" Address in use!!!\n", _DBG_PTR(pCEP))); + // clear out CEP fields + MemoryClear(&pCEP->LocalEndPoint, sizeof(pCEP->LocalEndPoint)); + MemoryClear(&pCEP->RemoteEndPoint, sizeof(pCEP->RemoteEndPoint)); + MemoryClear(&pCEP->PrimaryPath, sizeof(pCEP->PrimaryPath)); + pCEP->LocalEndPoint.CaGUID = 0; + pCEP->SID = 0; + + _DBG_LEAVE_LVL(_DBG_LVL_FUNC_TRACE); + + return FCM_ADDR_INUSE; + } + + // LocalCommID for listening CEP is used only for debugging purposes + AssignLocalCommID(pCEP); + pCEP->TransactionID = 0; // not used, will use TID of remote client + + _DBG_INFO((" Comm ID set at .\n", + _DBG_PTR(pCEP), pCEP->LocalCommID)); + + pCEP->Mode = CM_MODE_PASSIVE; + pCEP->LocalCMTimeout = 0; + pCEP->RemoteCMTimeout = 0; + pCEP->MaxCMRetries = 0; + pCEP->EventFlags = 0; + pCEP->RetryCount = 0; + //pCEP->pWaitEvent = NULL; + DListInit(&pCEP->PendingList); + + if (pCEP->pDgrmElement) + { + // Return the datagram since listen objects do not use it + _DBG_INFO((" Releasing the dgrm .\n", + _DBG_PTR(pCEP), _DBG_PTR(pCEP->pDgrmElement))); + CmDgrmRelease(pCEP->pDgrmElement); + } + + // Save user callback info + pCEP->pfnUserCallback = pfnListenCB; + pCEP->UserContext = Context; + + CepSetState(pCEP, CMS_LISTEN); + + _DBG_INFO((" *** Listening on .***\n", + _DBG_PTR(pCEP), pListenInfo->ListenAddr.EndPt.SID, + pListenInfo->ListenAddr.Port.LID, + pCEP->PrimaryPath.LocalGID.Type.Global.SubnetPrefix, + pCEP->PrimaryPath.LocalGID.Type.Global.InterfaceID)); + + _DBG_LEAVE_LVL(_DBG_LVL_FUNC_TRACE); + + // At this point, we are listening for incoming connections on this obj. + return FPENDING; + +} // Listen() + + +// See GetConnInfo in cm_active.c for callback processing + +////////////////////////////////////////////////////////////////////////// +// WaitP +// +// +// INPUTS: +// +// +// +// OUTPUTS: +// +// None. +// +// RETURNS: +// +// FSUCCESS or FTIMEOUT. +// +// IRQL: +// +// This routine is called at IRQL_PASSIVE_LEVEL. +// +FSTATUS +WaitP( + IN CM_CEP_OBJECT* pCEP, + OUT CM_CONN_INFO* pConnInfo, + uint32 Timeout_us // TODO: Put a max limit on this in addition to infinite + ) +{ + FSTATUS Status=FSUCCESS; + + uint32 WaitTimeUs=Timeout_us; + uint64 TimeoutUs=Timeout_us; + uint64 StartTimeUs=GetTimeStamp(); + + uint64 CurrTimeUs=0; + uint64 TimeElapsedUs=0; + + //CMM_MSG* pMsg=&((CM_MAD*)GsiDgrmGetSendMad(pCEP->pDgrmElement))->payload; + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, WaitP); + +waitagain: + + // Update the timeout + if ((int32)WaitTimeUs != EVENT_NO_TIMEOUT) + { + if (CurrTimeUs >= StartTimeUs) + { + TimeElapsedUs = (CurrTimeUs - StartTimeUs); + } + else // wrap-around + { + TimeElapsedUs = (CurrTimeUs + ((uint64)(-1) - StartTimeUs)); + } + + if (TimeoutUs > TimeElapsedUs) + { + WaitTimeUs = (uint32) (TimeoutUs - TimeElapsedUs); + } + else + { + WaitTimeUs = 0; + } + } + + //_DBG_INFO((" Waiting on obj... \n", + // _DBG_PTR(pCEP), WaitTimeUs/1000, pCEP->LocalCommID, + // _DBG_PTR(CmGetStateString(pCEP->State)))); + + Status = EventWaitOn(pCEP->pEventObj, WaitTimeUs); + + //_DBG_INFO((" Waiting on obj... complete <%s %s>\n", + // _DBG_PTR(pCEP), _DBG_PTR(FSTATUS_MSG(Status)), + // _DBG_PTR(CmGetStateString(pCEP->State)))); + + if (Status == FTIMEOUT) + { + if (Timeout_us == 0) + { + //_DBG_INFO((" Obj state is nonsignaled.\n", _DBG_PTR(pCEP))); + } + else + { + _DBG_WARNING((" EventWaitOn() returns FTIMEOUT!\n", _DBG_PTR(pCEP))); + } + _DBG_LEAVE_LVL(_DBG_LVL_FUNC_TRACE); + + return FTIMEOUT; + } + + ASSERT(Status == FSUCCESS); + + _DBG_INFO((" Obj state is signaled <%s>.\n", + _DBG_PTR(pCEP), _DBG_PTR(CmGetStateString(pCEP->State)))); + + // Get mutual ex to the object + SpinLockAcquire(&gCM->ListLock); + + Status = GetConnInfo(pCEP, pConnInfo); + + if (Status != FSUCCESS) + { + // Handle the case when we get signal but we already process the event + // with the previous signal + // eg evt1 --> signal; evt2 --> signal + // ->wait() returned + _DBG_WARNING((" GetConnInfo() returns %s!\n", + _DBG_PTR(pCEP), _DBG_PTR(FSTATUS_MSG(Status)))); + + ASSERT(pConnInfo->Status == 0); + + SpinLockRelease(&gCM->ListLock); + + goto waitagain; + } + + SpinLockRelease(&gCM->ListLock); + + _DBG_LEAVE_LVL(_DBG_LVL_FUNC_TRACE); + + return Status; + +} // WaitP() + +// given a CEP for which a FCM_CONNECT_REQUEST has been reported +// fetch the head of the pending list +static FSTATUS +GetPendingCEP( + IN CM_CEP_OBJECT* pCEP, + OUT CM_CEP_OBJECT** ppCEPEntry + ) +{ + CM_CEP_OBJECT* pCEPEntry = NULL; + + DLIST_ENTRY* pListEntry=NULL; + FSTATUS Status=FSUCCESS; + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, GetPendingCEP); + + switch (pCEP->State) + { + case CMS_IDLE: + + if (BitTest(pCEP->EventFlags, USRE_CANCEL)) + { + // User cancelled the listen, but hasn't gotten callback yet + Status = FCM_CONNECT_CANCEL; + } else { + Status = FERROR; + } + break; + + case CMS_LISTEN: + case CMS_REQ_RCVD: // separate out for Peer, no PendingList need then + case CMS_MRA_REQ_SENT: // separate out for Peer, no PendingList need then + // could have listen get the pCEPEntry and then have common code + // with Peer REQ_RCVD/MRA_REQ_SENT cases + // + // Accepting new client or peer connection + // + if (pCEP->bPeer) + { + _DBG_INFO((" *** Accepting peer connection ***\n", _DBG_PTR(pCEP))); + } else { + _DBG_INFO((" *** Accepting client connection ***\n", _DBG_PTR(pCEP))); + } + + if (DListIsEmpty(&pCEP->PendingList)) + { + // If user reject() or cancel() and then call accept() + _DBG_WARNING((" Pending list is empty!\n", _DBG_PTR(pCEP))); + Status = FNOT_FOUND; + break; + } + + // Note: For peer-to-peer connection (bPeer == TRUE), the entry in the PENDING list + // is the same as the one passed in i.e. pCEP == pCEPEntry + pListEntry = DListGetNext(&pCEP->PendingList); + pCEPEntry = PARENT_STRUCT(pListEntry, CM_CEP_OBJECT, PendingListEntry); + ASSERT(pCEPEntry->pParentCEP == pCEP); + if (pCEP->bPeer) + { + ASSERT(pCEPEntry == pCEP); + } else { + ASSERT(pCEPEntry != pCEP); + } + + // Cannot accept until the user has been notify thru wait + /* + if (!BitTest(pCEPEntry->EventFlags, USRE_WAIT)) + { + _DBG_WARNING((" Cannot accept - User must call wait() before accept()!\n", + _DBG_PTR(pCEP))); + // Re-signal + EventSet(pCEP, CME_RCVD_REQ); + + Status = FUNAVAILABLE; + break; + } + + BitClear(pCEPEntry->EventFlags, USRE_WAIT); + */ + + // Make sure we havent timed-out or receive a reject + switch (pCEPEntry->State) + { + case CMS_REQ_RCVD: + case CMS_MRA_REQ_SENT: + *ppCEPEntry = pCEPEntry; + Status = FSUCCESS; + break; + + default: + Status = FINVALID_STATE; + break; + } + break; + default: + Status = FINVALID_STATE; + break; + } // switch() + + _DBG_LEAVE_LVL(_DBG_LVL_FUNC_TRACE); + + return Status; + +} // GetPendingCEP + +// process an inbound REQ for a passive CEP +FSTATUS +ProcessRequestP( + IN CM_CEP_OBJECT* pCEP, + IN CM_REP_FAILOVER Failover, + OUT CM_PROCESS_REQUEST_INFO *Info + ) +{ + FSTATUS Status; + IB_CA_ATTRIBUTES *pCaAttr = NULL; + CM_CEP_OBJECT* pCEPEntry; + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, ProcessRequestP); + + // TBD - RD code here is not complete/accurate + ASSERT(pCEP->Mode == CM_MODE_PASSIVE); + + Status = GetPendingCEP(pCEP, &pCEPEntry); + if (Status != FSUCCESS) + goto done; + if (pCEPEntry->Type == CM_UD_TYPE) + { + Status = FINVALID_STATE; + goto done; + } + if (Info == NULL) + { + Status = FINVALID_PARAMETER; + goto done; + } + MemoryClear(Info, sizeof(*Info)); // just to be safe + + // Child must inherit parent's setting for now + // Will be saved again when AcceptP + pCEPEntry->bFailoverSupported = pCEP->bFailoverSupported; + + // get ca Attr + pCaAttr = (IB_CA_ATTRIBUTES*)MemoryAllocate(sizeof(*pCaAttr), FALSE, CM_MEM_TAG); + if (pCaAttr == NULL) + { + Status = FINSUFFICIENT_MEMORY; + goto done; + } + pCaAttr->PortAttributesListSize = 0; + pCaAttr->PortAttributesList = NULL; + Status = iba_query_ca_by_guid(pCEPEntry->LocalEndPoint.CaGUID, pCaAttr); + if (Status != FINSUFFICIENT_MEMORY && Status != FSUCCESS) + goto done; + + // set up attributes to move QP to Init + GetInitAttrFromCep(pCEPEntry, &Info->QpAttrInit); + + // update LocalResponder/Initiator/SendPSN so we are ready in case + // application calls iba_cm_prepare_rts before doing iba_cm_accept + // Build Reply + pCEPEntry->LocalRecvPSN = Info->ReplyInfo.Info.Reply.StartingPSN = + GenerateStartPSN(); + // RDMA Read is not supported for UC, leave zero + if (pCEPEntry->Type != CM_UC_TYPE) { + pCEPEntry->LocalResponderResources = + Info->ReplyInfo.Info.Reply.ArbResponderResources = + MIN(pCEPEntry->LocalResponderResources, + pCaAttr->MaxQPResponderResources); + pCEPEntry->LocalInitiatorDepth = + Info->ReplyInfo.Info.Reply.ArbInitiatorDepth = + MIN(pCEPEntry->LocalInitiatorDepth, + pCaAttr->MaxQPInitiatorDepth); + } + Info->ReplyInfo.Info.Reply.TargetAckDelay = pCaAttr->LocalCaAckDelay; + // spec implies we should say NOT_SUPPORTED even if no alternate path + // was provided in REQ + if (pCaAttr->PathMigrationLevel == CAPathMigNone + || ! pCEPEntry->bFailoverSupported) + { + Info->ReplyInfo.Info.Reply.FailoverAccepted = CM_REP_FO_NOT_SUPPORTED; + } else { + Info->ReplyInfo.Info.Reply.FailoverAccepted = Failover; + } + // end to end credits and RNR not allowed for UC + if (pCEPEntry->Type != CM_UC_TYPE) { + // our CA supports RC credits + Info->ReplyInfo.Info.Reply.EndToEndFlowControl = TRUE; + Info->ReplyInfo.Info.Reply.RnRRetryCount = + pCEPEntry->LocalRnrRetryCount; // 1st guess + // caller must set approprite RnrRetryCount, this is just + // a wild guess, caller can set higher or lower + } + + // set up attributes to move QP to RTR + GetRtrAttrFromCep(pCEPEntry, + (Info->ReplyInfo.Info.Reply.FailoverAccepted == CM_REP_FO_ACCEPTED), + &Info->QpAttrRtr); +done: + if (pCaAttr) + MemoryDeallocate(pCaAttr); + _DBG_LEAVE_LVL(_DBG_LVL_FUNC_TRACE); + return Status; +} + +////////////////////////////////////////////////////////////////////////// +// AcceptP_Async +// +// +// INPUTS: +// +// +// +// OUTPUTS: +// +// None. +// +// RETURNS: +// +// FSUCCESS - The function has completed successfully. For server, this indicates the initialization. +// >FCM_CONNECT_ESTABLISHED +// >FCM_CONNECT_REJECT +// >FCM_CONNECT_TIMEOUT +// >FCM_CONNECT_CANCEL +// +// FINVALID_STATE - The endpoint is not in the valid state for this call +// FERROR - Unable to send the reply ack packet +// FTIMEOUT - The timeout interval expires +// +// +// IRQL: +// +// This routine is called at IRQL_PASSIVE_LEVEL. +// +FSTATUS +AcceptP_Async( + IN CM_CEP_OBJECT* pCEP, + IN const CM_CONN_INFO* pSendConnInfo, // Send REP + IN EVENT_HANDLE hEvent, + IN EVENT_HANDLE hWaitEvent, + IN PFN_CM_CALLBACK pfnCallback, + IN void* Context, + IN boolean willWait, + OUT CM_CEP_OBJECT** ppCEP + ) +{ + CM_CEP_OBJECT* pCEPEntry = NULL; + + FSTATUS Status=FSUCCESS; + + uint32 rep_timeout_ms=0; + uint64 elapsed_us=0; + uint8 timewait; + + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, AcceptP_Async); + + if (ppCEP) + { + *ppCEP = NULL; + } + + // Check QPN/EECN has been supplied + if (! pSendConnInfo || (pSendConnInfo->Info.Reply.QPN == 0 + && pSendConnInfo->Info.Reply.EECN == 0)) + { + Status = FINVALID_PARAMETER; + goto done; + } + + + SpinLockAcquire(&gCM->ListLock); + + Status = GetPendingCEP(pCEP, &pCEPEntry); + if (Status != FSUCCESS) + goto unlock; + + //BitClear(pCEPEntry->EventFlags, CME_REQ_RCVD); + + elapsed_us = CmGetElapsedTime(pCEPEntry); + + // Update the turnaround time + gCM->turnaround_time_us = UpdateTurnaroundTime(gCM->turnaround_time_us, elapsed_us); + + _DBG_INFO(("Update turnaround time .\n", gCM->turnaround_time_us)); + + // check RDMA Read parameters have not been incorrectly increased + if (pCEPEntry->LocalInitiatorDepth < + pSendConnInfo->Info.Reply.ArbInitiatorDepth + || pCEPEntry->LocalResponderResources < + pSendConnInfo->Info.Reply.ArbResponderResources) + { + Status = FINVALID_PARAMETER; + goto unlock; + } + + if (pCEPEntry->bPeer) + { + // API design decision, must use same EndPoint in CmAccept + // as did in original PeerConnect. We enforce this + // (as opposed to blindly replacing Reply or CEP info) + // to catch applications which end up with 2 QPs for the CEP + if (pCEPEntry->LocalEndPoint.QPN != pSendConnInfo->Info.Reply.QPN + || pCEPEntry->LocalEndPoint.EECN != pSendConnInfo->Info.Reply.EECN) + { + Status = FINVALID_PARAMETER; + goto unlock; + } + } else { + // Save the relevent user reply info to this object + pCEPEntry->LocalEndPoint.QPN = pSendConnInfo->Info.Reply.QPN; + pCEPEntry->LocalEndPoint.EECN = pSendConnInfo->Info.Reply.EECN; + if (! CM_MapTryInsert(&gCM->LocalEndPointMap, (uintn)pCEPEntry, + &pCEPEntry->LocalEndPointMapEntry, "LOCAL_END_POINT_LIST", pCEPEntry)) + { + Status = FCM_ADDR_INUSE; + pCEPEntry->LocalEndPoint.QPN = 0; + pCEPEntry->LocalEndPoint.EECN = 0; + goto unlock; + } + + // Save the disconnect callback + pCEPEntry->pfnUserCallback = pfnCallback; + pCEPEntry->UserContext = Context; + + pCEPEntry->bAsyncAccept = pCEP->bAsyncAccept; + pCEPEntry->bTimewaitCallback = pCEP->bTimewaitCallback; + pCEPEntry->bFailoverSupported = pCEP->bFailoverSupported; + pCEPEntry->turnaround_time_us = pCEP->turnaround_time_us; + + // Use this user-specified event obj instead of the one we created internally + if (hEvent) + { + OS_WAIT_OBJ_HANDLE hCEPEventObj = (OS_WAIT_OBJ_HANDLE)pCEPEntry->pEventObj; + boolean RemoveReference = FALSE; + + if (hCEPEventObj) + { + if (pCEPEntry->bPrivateEvent) + { + EventDealloc(pCEPEntry->pEventObj); + } + else + { + RemoveReference = TRUE; + } + } + + pCEPEntry->bPrivateEvent = 0; + + pCEPEntry->pEventObj = (EVENT*)hEvent; + + OsWaitObjAddRef((OS_WAIT_OBJ_HANDLE)pCEPEntry->pEventObj); + + if (RemoveReference) + { + OsWaitObjRemoveRef(hCEPEventObj); + } + } + + if (hWaitEvent) + { + pCEPEntry->pWaitEvent = (EVENT*)hWaitEvent; + } + } + + if (pCEP->AlternatePath.LocalLID != 0) + { + if (pSendConnInfo->Info.Reply.FailoverAccepted != CM_REP_FO_ACCEPTED) + { + MemoryClear(&pCEP->AlternatePath, sizeof(pCEP->AlternatePath)); + } + pCEPEntry->bFailoverSupported &= IsFailoverSupported( + pSendConnInfo->Info.Reply.FailoverAccepted); + } + + // save arbitrated RDMA Read parameters + pCEPEntry->LocalInitiatorDepth = + pSendConnInfo->Info.Reply.ArbInitiatorDepth; + pCEPEntry->LocalResponderResources = + pSendConnInfo->Info.Reply.ArbResponderResources; + if (pSendConnInfo->Info.Reply.TargetAckDelay > pCEP->TargetAckDelay) + { + pCEP->TargetAckDelay = pSendConnInfo->Info.Reply.TargetAckDelay; + } + pCEP->LocalRecvPSN = pSendConnInfo->Info.Reply.StartingPSN; + + // update timewait + // some applications don't set TargetAckDelay properly + // and to be safe we want our timewait to be no less than remote end + // so be conservative and only increase it, the computation below + // due to the round up of PktLifeTime, essentially always + // adds TargetAckDelay to the timewait + timewait = TimeoutTimeToMult( + (TimeoutMultToTimeInUsec(pCEPEntry->PktLifeTime)<<1) + + TimeoutMultToTimeInUsec(pCEP->TargetAckDelay)); + if (pCEPEntry->Timewait < timewait) + pCEPEntry->Timewait = timewait; + + FormatREP((CM_MAD*)GsiDgrmGetSendMad(pCEPEntry->pDgrmElement), + &pSendConnInfo->Info.Reply, + pCEPEntry->TransactionID, + pCEPEntry->LocalCommID, + pCEPEntry->RemoteCommID, + pCEPEntry->LocalEndPoint.CaGUID); + + _DBG_INFO((" REP's dgrm address field \n", + _DBG_PTR(pCEPEntry), + pCEPEntry->pDgrmElement->PortGuid, + pCEPEntry->pDgrmElement->RemoteLID, + pCEPEntry->pDgrmElement->ServiceLevel, + pCEPEntry->pDgrmElement->PathBits, + pCEPEntry->pDgrmElement->StaticRate)); + + // Send out the REP + Status = CmDgrmSend(pCEPEntry->pDgrmElement); + if (FSUCCESS != Status) + { + // fall through and let timer retry the send later + _DBG_WARN((" DgrmSend() failed for REP!!! <%s>\n", + _DBG_PTR(pCEP), _DBG_PTR(FSTATUS_MSG(Status)))); + Status = FSUCCESS; + } else { + AtomicIncrementVoid(&gCM->Sent.Rep); + } + + _DBG_INFO((" REP sent .\n", + _DBG_PTR(pCEPEntry), pCEPEntry->LocalCommID, pCEPEntry->RemoteCommID, + pCEPEntry->PrimaryPath.LocalLID, pCEPEntry->PrimaryPath.RemoteLID)); + + CepRemoveFromPendingList(pCEPEntry); + + CepSetState(pCEPEntry, CMS_REP_SENT); + + // For peer connection, leave the entry in the LISTEN list + + // Start timer to timeout the REP i.e. wait for the RTU msg to arrive + pCEPEntry->RetryCount = 0; + rep_timeout_ms = TimeoutMultToTimeInMs(pCEPEntry->LocalCMTimeout); + CmTimerStart(pCEPEntry, rep_timeout_ms, REP_TIMER); + + if (willWait) + { + // caller will be doing a WaitP + // prevent a callback until caller WaitP completes + AtomicIncrementVoid(&pCEPEntry->CallbackRefCnt); + AtomicIncrementVoid(&gCM->TotalCallbackRefCnt); + } + + // If another connection is pending for this server endpoint, + // we must set it again to wake up the Wait() + if (pCEP->PendingCount) + { + SetNotification(pCEP, CME_RCVD_REQ);//EventSet(pCEP, CME_RCVD_REQ); + } + + // Return the new CEP object to the user + if (ppCEP) + { + *ppCEP = pCEPEntry; + } + Status = FPENDING; + +unlock: + SpinLockRelease(&gCM->ListLock); +done: + _DBG_LEAVE_LVL(_DBG_LVL_FUNC_TRACE); + return Status; + +} // AcceptP_Asynch() + + +////////////////////////////////////////////////////////////////////////// +// AcceptP +// +// +// INPUTS: +// +// +// +// OUTPUTS: +// +// None. +// +// RETURNS: +// +// FCM_CONNECT_ESTABLISHED - Connection established +// FCM_CONNECT_REJECT - Connection rejected +// FCM_CONNECT_TIMEOUT - Connection timeout +// FCM_CONNECT_CANCEL - Connection cancel +// +// FINVALID_STATE - The endpoint is not in the valid state for this call +// FERROR - Nothing to accept, cannot accept, or unable to send the reply packet +// FTIMEOUT - The timeout interval expires +// +// +// IRQL: +// +// This routine is called at IRQL_PASSIVE_LEVEL. +// +FSTATUS +AcceptP( + IN CM_CEP_OBJECT* pCEP, + IN const CM_CONN_INFO* pSendConnInfo, // Send REP + OUT CM_CONN_INFO* pRecvConnInfo, // Rcvd RTU, REJ or TIMEOUT + IN PFN_CM_CALLBACK pfnCallback, + IN void* Context, + OUT CM_CEP_OBJECT** ppNewCEP + ) +{ + CM_CEP_OBJECT* pNewCEP=NULL; + FSTATUS Status=FSUCCESS; + uint32 rep_timeout_ms=0; + boolean bPeer = pCEP->bPeer; // save in case move Cep to Idle + + _DBG_ENTER_EXT(_DBG_LVL_FUNC_TRACE, AcceptP, == PASSIVE); + + UNUSED_VAR(rep_timeout_ms); + + if (! pRecvConnInfo && ! pCEP->bAsyncAccept) + { + Status = FINVALID_PARAMETER; + goto done; + } + // Accept client or peer connection. Send the REP to the remote client + // use ppNewCEP if not-NULL so caller gets updated while in Lock in + // AcceptP_Async + Status = AcceptP_Async(pCEP, pSendConnInfo, NULL, NULL, pfnCallback, Context, ! pCEP->bAsyncAccept, ppNewCEP?ppNewCEP:&pNewCEP); + + if (Status != FSUCCESS && Status != FPENDING) + goto done; + if (ppNewCEP) + pNewCEP = *ppNewCEP; + + if (bPeer) + { + ASSERT(pNewCEP == pCEP); + } + + if (pCEP->bAsyncAccept) + { + // we will provide a callback when RTU or REJ arrives or timeout + goto done; + } + + // Wait for RTU or REJ to arrive or timeout event to occur + // TODO: We should put a time limit here in case we dont get the timeout event ?? + Status = WaitP(pNewCEP, pRecvConnInfo, EVENT_NO_TIMEOUT); + //rep_timeout_ms = TimeoutMultToTimeInMs(pNewCEP->LocalCMTimeout); + //Status = WaitP(pNewCEP, pRecvConnInfo, 2*rep_timeout_ms, TRUE); + ASSERT(Status == FSUCCESS); + + // This is the status we returned to the caller + Status = pRecvConnInfo->Status; + + // Check the status here instead of the state since the status is what + // we return to the caller + if (Status == FCM_CONNECT_ESTABLISHED) + { + // + // Note: Though the status is established, the pNewCEP state may not be in + // CMS_ESTABLISHED since we may have already received a DREQ + // + _DBG_INFO((" *** Connection established *** .\n", + _DBG_PTR(pNewCEP), pNewCEP->LocalCommID, pNewCEP->RemoteCommID, + pNewCEP->PrimaryPath.LocalLID, pNewCEP->PrimaryPath.RemoteLID, + _DBG_PTR(CmGetStateString(pNewCEP->State)))); + + } else { + switch (Status) + { + case FCM_CONNECT_CANCEL: // USRE_CANCEL + _DBG_INFO((" *** Connection cancelled *** .\n", + _DBG_PTR(pNewCEP), pNewCEP->LocalCommID, pNewCEP->RemoteCommID, + _DBG_PTR(CmGetStateString(pNewCEP->State)), _DBG_PTR(FSTATUS_MSG(Status)))); + break; + + case FCM_CONNECT_REJECT: // CME_RCVD_REJ + _DBG_INFO((" *** Connection rejected *** .\n", + _DBG_PTR(pNewCEP), pNewCEP->LocalCommID, pNewCEP->RemoteCommID, + _DBG_PTR(CmGetStateString(pNewCEP->State)), _DBG_PTR(FSTATUS_MSG(Status)))); + break; + + case FCM_CONNECT_TIMEOUT: // CME_TIMEOUT_REP + _DBG_INFO((" *** Connection timed out *** .\n", + _DBG_PTR(pNewCEP), pNewCEP->LocalCommID, pNewCEP->RemoteCommID, + _DBG_PTR(CmGetStateString(pNewCEP->State)), _DBG_PTR(FSTATUS_MSG(Status)))); + break; + + case FCM_DISCONNECT_REQUEST: + _DBG_INFO((" *** Disconnecting *** .\n", + _DBG_PTR(pNewCEP), pNewCEP->LocalCommID, pNewCEP->RemoteCommID, + _DBG_PTR(CmGetStateString(pNewCEP->State)), _DBG_PTR(FSTATUS_MSG(Status)))); + break; + + case FCM_DISCONNECTED: + _DBG_INFO((" *** Disconnected *** .\n", + _DBG_PTR(pNewCEP), pNewCEP->LocalCommID, pNewCEP->RemoteCommID, + _DBG_PTR(CmGetStateString(pNewCEP->State)), _DBG_PTR(FSTATUS_MSG(Status)))); + break; + + default: + _DBG_INFO((" *** Connection ??? *** .\n", + _DBG_PTR(pNewCEP), pNewCEP->LocalCommID, pNewCEP->RemoteCommID, + _DBG_PTR(CmGetStateString(pNewCEP->State)), _DBG_PTR(FSTATUS_MSG(Status)))); + ASSERT(0); + break; + + } // switch() + + if (!bPeer) + { + // This is the one we created when a new connection request arrived + iba_cm_destroy_cep(pNewCEP); + } + if (ppNewCEP) + *ppNewCEP = NULL; + } + CmDoneCallback(pNewCEP); + +done: + _DBG_LEAVE_EXT(_DBG_LVL_FUNC_TRACE); + + return Status; + +} // AcceptP() + + +////////////////////////////////////////////////////////////////////////// +// RejectP +// +// +// INPUTS: +// +// +// +// OUTPUTS: +// +// None. +// +// RETURNS: +// +// FSUCCESS. +// +// IRQL: +// +// This routine is called at IRQL_PASSIVE_LEVEL. +// +FSTATUS +RejectP( + IN CM_CEP_OBJECT* pCEP, + IN const CM_REJECT_INFO* pConnectReject + ) +{ + CM_CEP_OBJECT* pCEPEntry = NULL; + DLIST_ENTRY* pListEntry=NULL; + FSTATUS Status=FSUCCESS; + boolean bPeer = pCEP->bPeer; // in case move Cep to Idle + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, RejectP); + + switch (pCEP->State) + { + case CMS_IDLE: + if (BitTest(pCEP->EventFlags, USRE_CANCEL)) + { + // User cancelled the listen, but hasn't gotten callback yet + Status = FCM_CONNECT_CANCEL; + } + else + { + Status = FERROR; + } + break; + + case CMS_LISTEN: + case CMS_REQ_RCVD: // TBD only occurs for actual CEP (can be Peer), separate out + case CMS_MRA_REQ_SENT: // TBD only occurs for actual CEP (can be Peer), separate out + // if separate out above and did same in AcceptP, won't need Peer on PendingList + + // + // Rejecting the incoming connect or peer request + // + if (DListIsEmpty(&pCEP->PendingList)) + { + // Nothing to reject + _DBG_WARNING((" Pending list is empty!\n", _DBG_PTR(pCEP))); + + Status = FNOT_FOUND; + break; + } + + // Pull the incoming connection + pListEntry = DListGetNext(&pCEP->PendingList); + pCEPEntry = PARENT_STRUCT(pListEntry, CM_CEP_OBJECT, PendingListEntry); + ASSERT(pCEPEntry->pParentCEP == pCEP); + + // Cannot reject until the user has been notify thru wait + /* + if (!BitTest(pCEPEntry->EventFlags, USRE_WAIT)) + { + Status = FUNAVAILABLE; + break; + } + + BitClear(pCEPEntry->EventFlags, USRE_WAIT); + */ + + ASSERT(pCEPEntry->State == CMS_REQ_RCVD || pCEPEntry->State == CMS_MRA_REQ_SENT); + // Format the REJ msg + FormatREJ((CM_MAD*)GsiDgrmGetSendMad(pCEPEntry->pDgrmElement), + CM_REJECT_REQUEST, + (uint16)pConnectReject->Reason, + &pConnectReject->RejectInfo[0], + pConnectReject->RejectInfoLen, + &pConnectReject->PrivateData[0], + CMM_REJ_USER_LEN, + pCEPEntry->TransactionID, + pCEPEntry->LocalCommID, + pCEPEntry->RemoteCommID); + + // Send out the REJ. We do not need to check the return since + // the other end will eventually timed-out if it does not received + // either RTU or REJ + Status = CmDgrmSend(pCEPEntry->pDgrmElement); + if (FSUCCESS != Status) + { + // fall through and let timer retry the send later + _DBG_WARN((" DgrmSend() failed for REJ!!! <%s>\n", + _DBG_PTR(pCEP), _DBG_PTR(FSTATUS_MSG(Status)))); + Status = FSUCCESS; + } else { + AtomicIncrementVoid(&gCM->Sent.RejReq); + } + + _DBG_INFO((" REJ sent, rejecting REQ .\n", + _DBG_PTR(pCEPEntry), pCEPEntry->LocalCommID, pCEPEntry->RemoteCommID, + pCEPEntry->PrimaryPath.LocalLID, pCEPEntry->PrimaryPath.RemoteLID, + pConnectReject->Reason)); + + // Move from PENDING to INIT list + CepRemoveFromPendingList(pCEPEntry); + CepToIdle(pCEPEntry); + + if (bPeer) + { + // For peer request, the user created the obj + ASSERT(pCEPEntry == pCEP); + } else { + // This is the one we created when a new connection request arrived + DestroyCEP(pCEPEntry); + } + + // If another connection is pending for this server endpoint, + // we must set it again to wake up the Wait() + if (pCEP->PendingCount) + { + SetNotification(pCEP, CME_RCVD_REQ);//EventSet(pCEP, CME_RCVD_REQ); + } + + break; + // TBD case CMS_REP_SENT: - allow and move to TimeWait, see Cancel + // TBD case CMS_MRA_REP_RCVD: - allow and move to TimeWait, see Cancel + + default: + + Status = FINVALID_STATE; + break; + + } // switch() + + _DBG_LEAVE_LVL(_DBG_LVL_FUNC_TRACE); + + return Status; + +} // RejectP() + +////////////////////////////////////////////////////////////////////////// +// CancelP +// CmCancel, DestroyCEP or remove CA while connecting +// +// Cancel processing of a passive side connection +// all local information is dropped, remote end is left to timeout +// user will get a FCM_CONNECT_CANCEL callback at which point user +// should destroy the now-idle CEP +// +// In general this should be used only to cancel listeners. +// Internally it is used to do a quick cleanup for a Destroyed CEP +// or the removal of a CA, hence it does not attempt to send a Reject +// Applications should generally use CmReject instead of this to +// properly reject connections. +// +// INPUTS: +// +// +// +// OUTPUTS: +// +// None. +// +// RETURNS: +// +// FSUCCESS. +// +// IRQL: +// +// This routine is called at IRQL_PASSIVE_LEVEL. +// +FSTATUS +CancelP( + IN CM_CEP_OBJECT* pCEP + ) +{ + FSTATUS Status=FPENDING; + + CM_CEP_OBJECT* pCEPEntry=NULL; + DLIST_ENTRY* pListEntry=NULL; + + switch (pCEP->State) + { + case CMS_LISTEN: + // + // Cancel the listen request + // + + // Clear the pending signal from the event obj since a REQ may be pending + // but before the signal is waited on + //CmEventReset(pCEP); + + //BitSet(pCEP->EventFlags, USRE_CANCEL); + + // Clear the pending list + while (!DListIsEmpty(&pCEP->PendingList)) + { + pListEntry = DListGetNext(&pCEP->PendingList); + pCEPEntry = PARENT_STRUCT(pListEntry, CM_CEP_OBJECT, PendingListEntry); + // Move from PENDING to INIT list and destroy it + ASSERT(pCEPEntry->pParentCEP == pCEP); + CepRemoveFromPendingList(pCEPEntry); + CepToIdle(pCEPEntry); + + // This will start the timer in timewait state + DestroyCEP(pCEPEntry); + } + ASSERT(pCEP->PendingCount == 0); + + // Move from LISTEN to IDLE + CM_MapRemoveEntry(&gCM->ListenMap, &pCEP->MapEntry, LISTEN_LIST, pCEP); + // ClearEndPoint in CepToIdle is benign + CepToIdle(pCEP); + + // Set the cancel event + SetNotification(pCEP, USRE_CANCEL); + + // This tells us that a callback is pending or we are in the callback + //if (AtomicRead(&pCEP->CallbackRefCnt)) + // Status = FPENDING; + + break; + + case CMS_REQ_RCVD: + case CMS_MRA_REQ_SENT: + // Internal use, removed CA or cancelling listening CEP + ASSERT(!pCEP->bPeer || (pCEP->LocalEndPoint.QPN || pCEP->LocalEndPoint.EECN)); + +#if 0 + // TBD - call RejectP, will end up in Idle +#else + // Move from PENDING to IDLE + CepRemoveFromPendingList(pCEP); + CepToIdle(pCEP); +#endif + + // Set the cancel event + SetNotification(pCEP, USRE_CANCEL); + + break; + + case CMS_REP_SENT: + case CMS_MRA_REP_RCVD: + // + // Cancel the connection while waiting for the RTU to arrive. + // + + // Cancel the timer for REP msg + CmTimerStop(pCEP, REP_TIMER); + + // Clear the pending signal from the event obj since a RTU may be pending + // but before the signal is waited on + //CmEventReset(pCEP); + + //BitSet(pCEP->EventFlags, USRE_CANCEL); +#if 0 + // TBD - we should do this + send a REJ (timeout or similar) - use RejectP + CepToTimewait(pCEP) + // if user wants a FCM_DISCONNECTED at end of timewait, lets not confuse + // them with a FCM_CONNECT_CANCEL callback before it + if (! pCEP->bTimewaitCallback) + { + if (pCEP->bAsyncAccept) + { + SetNotification(pCEP, USRE_CANCEL); // callback + } else { + EventSet(pCEP, USRE_CANCEL, FALSE); // wakeup CmAccept wait + } + } +#else + CepToIdle(pCEP); + + if (pCEP->bAsyncAccept) + { + SetNotification(pCEP, USRE_CANCEL); // callback + } else { + EventSet(pCEP, USRE_CANCEL, FALSE); // wakeup CmAccept wait + } +#endif + // This tells us that a callback is pending or we are in the callback + //if (AtomicRead(&pCEP->CallbackRefCnt)) + // Status = FPENDING; + + //if (BitTest(pCEP->EventFlags, USRE_WAIT)) + //{ + // Status = FPENDING; + //} + + //EventSet(pCEP, USRE_CANCEL); + + break; + + case CMS_SIDR_REQ_RCVD: + // Move from PENDING to INIT list + CepRemoveFromPendingList(pCEP); + // ClearEndPoint in CepToIdle is benign + CepToIdle(pCEP); + + // Set the cancel event - this CEP not user visible, so no callback + EventSet(pCEP, USRE_CANCEL, FALSE); + break; + + default: + + Status = FINVALID_STATE; + break; + + } // switch() + + return Status; + +} // CancelP() + +// build QP Attributes to load new alternate path into QP +// and prepare a Reply +FSTATUS ProcessAltPathRequestP( + IN CM_CEP_OBJECT* pCEP, + IN CM_ALTPATH_INFO* AltPathRequest, + OUT CM_PROCESS_ALTPATH_REQUEST_INFO* Info + ) +{ + FSTATUS Status=FSUCCESS; + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, ProcessAltPathRequestP); + + ASSERT(pCEP->Mode == CM_MODE_PASSIVE); + switch (pCEP->State) + { + case CMS_LAP_RCVD: + case CMS_MRA_LAP_SENT: + MemoryClear(Info, sizeof(*Info)); // just to be safe + Info->QpAttrRts.RequestState = QPStateReadyToSend; + Info->QpAttrRts.APMState = APMStateRearm; + GetAVFromPath2(0, &AltPathRequest->AlternatePathInfo.Path, NULL, + &Info->QpAttrRts.AltDestAV); + Info->QpAttrRts.AltDestAV.PortGUID = pCEP->TempAlternateLocalPortGuid; + Info->QpAttrRts.AltDestAV.GlobalRouteInfo.SrcGIDIndex = + pCEP->TempAlternateLocalGidIndex; + Info->QpAttrRts.AltDestAV.PathBits = pCEP->TempAlternateLocalPathBits; + Info->QpAttrRts.AltPortGUID = pCEP->TempAlternateLocalPortGuid; + Info->QpAttrRts.AltPkeyIndex = pCEP->TempAlternatePkeyIndex; + Info->QpAttrRts.Attrs = IB_QP_ATTR_APMSTATE + |IB_QP_ATTR_ALTDESTAV|IB_QP_ATTR_ALTPORTGUID + | IB_QP_ATTR_ALTPKEYINDEX; + if (pCEP->Type != CM_UC_TYPE) { + Info->QpAttrRts.AltLocalAckTimeout = AltPathRequest->AlternateAckTimeout; + Info->QpAttrRts.Attrs |= IB_QP_ATTR_ALTLOCALACKTIMEOUT; + } + Info->AltPathReply.APStatus = APS_PATH_LOADED; + // caller must iba_modify_qp(...) then iba_altpath_reply + break; + + default: + Status = FINVALID_STATE; + break; + } + _DBG_LEAVE_LVL(_DBG_LVL_FUNC_TRACE); + + return Status; +} + + +////////////////////////////////////////////////////////////////////////// +// AltPathReplyP +// +// Reply to an alternate path request +// Only allowed for Server/Passive side of connection +// +// INPUTS: +// +// +// +// OUTPUTS: +// +// None. +// +// RETURNS: +// +// FSUCCESS - APR queued to be sent. +// FINVALID_STATE - The endpoint is not in the valid state for this call +// FERROR - Unable to send the apr packet +// +// +// IRQL: +// +// This routine is called at IRQL_PASSIVE_LEVEL. +// +FSTATUS +AltPathReplyP( + IN CM_CEP_OBJECT* pCEP, + IN CM_ALTPATH_REPLY_INFO* pAprInfo // Send APR + ) +{ + FSTATUS Status; + CM_MAD* pMad = NULL; + //uint64 elapsed_us=0; + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, AltPathReplyP); + + ASSERT(pCEP->Mode == CM_MODE_PASSIVE); + switch (pCEP->State) + { + case CMS_LAP_RCVD: + case CMS_MRA_LAP_SENT: + pMad = (CM_MAD*)GsiDgrmGetSendMad(pCEP->pDgrmElement); + + if (pAprInfo->APStatus == APS_PATH_LOADED) + { + // still have the LAP we received, now we have + // accepted it as our alternate path + ASSERT(pMad->common.AttributeID == MCLASS_ATTRIB_ID_LAP); + CopyRcvdLAPToAltPath(&pMad->payload.LAP, &pCEP->AlternatePath); + pCEP->AlternatePath.LocalPortGuid = pCEP->TempAlternateLocalPortGuid; + pCEP->AlternatePath.LocalGidIndex = pCEP->TempAlternateLocalGidIndex; + pCEP->AlternatePath.LocalPathBits = pCEP->TempAlternateLocalPathBits; + pCEP->AlternatePath.PkeyIndex = pCEP->TempAlternatePkeyIndex; + } else if (pAprInfo->APStatus == APS_UNSUPPORTED_REQ) { + // in future no need to notify CEP of LAPs, it doesn't do APM + pCEP->bFailoverSupported = FALSE; + } + + // Update the turnaround time + // uncomment the 3 lines below to have LAP/APR response count toward + // average turnaround time + //elapsed_us = CmGetElapsedTime(pCEPEntry); + //gCM->turnaround_time_us = UpdateTurnaroundTime(gCM->turnaround_time_us, elapsed_us); + //_DBG_INFO(("Update turnaround time .\n", gCM->turnaround_time_us)); + + FormatAPR(pMad, (CM_APR_STATUS) pAprInfo->APStatus, + pAprInfo->u.AddInfo.Info, + pAprInfo->u.AddInfo.Len, + pAprInfo->PrivateData, + CM_APR_INFO_USER_LEN, + pCEP->TransactionID, + pCEP->LocalCommID, + pCEP->RemoteCommID); + + // Send out the APR + Status = CmDgrmSend(pCEP->pDgrmElement); + if (FSUCCESS != Status) + { + // fall through and let timer retry the send later + _DBG_WARN((" DgrmSend() failed for APR!!! <%s>\n", + _DBG_PTR(pCEP), _DBG_PTR(FSTATUS_MSG(Status)))); + Status = FSUCCESS; + } else { + if (pAprInfo->APStatus == APS_PATH_LOADED) + AtomicIncrementVoid(&gCM->Sent.AprAcc); + else + AtomicIncrementVoid(&gCM->Sent.AprRej); + } + + _DBG_INFO((" APR sent .\n", + _DBG_PTR(pCEP), pCEP->LocalCommID, pCEP->RemoteCommID, + pCEP->PrimaryPath.LocalLID, pCEP->PrimaryPath.RemoteLID)); + + CepSetState(pCEP, CMS_ESTABLISHED); + break; + default: + Status = FINVALID_STATE; + break; + } + + _DBG_LEAVE_LVL(_DBG_LVL_FUNC_TRACE); + return Status; + +} // AltPathReplyP() + +// EOF diff --git a/IbAccess/Common/Ibt/Cm/cm_private.h b/IbAccess/Common/Ibt/Cm/cm_private.h new file mode 100644 index 0000000..d500b3a --- /dev/null +++ b/IbAccess/Common/Ibt/Cm/cm_private.h @@ -0,0 +1,1411 @@ +/* BEGIN_ICS_COPYRIGHT4 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT4 ****************************************/ +/* [ICS VERSION STRING: unknown] */ + +/* CM data structures private to the kernel CM */ + +/* Suppress duplicate loading of this file */ +#ifndef _INSI_IB_CM_PRIVATE_H_ +#define _INSI_IB_CM_PRIVATE_H_ + + +#if defined (__cplusplus) +extern "C" { +#endif + +#include "bldver.h" + +/* OS independent routines */ +#include "datatypes.h" +#include "ievent.h" +#include "itimer.h" +#include "imemory.h" +#include "ispinlock.h" +#include "idebug.h" +#include "ithread.h" +#include "ireaper.h" +#include "isyscallback.h" +#include "ibyteswap.h" +#include "iquickmap.h" +#include "ilist.h" +#include "stl_types.h" +#include "stl_mad_priv.h" +#include "stl_helper.h" +#include "ib_gsi.h" +#include "ibt.h" +#include "cm_common.h" + +// Enable CM event handling, this allows COMM_ESTABLISHED event to +// be treated as an RTU +//#undef _CM_EVENT_ON_QP_ +#define _CM_EVENT_ON_QP_ + +#ifdef _CM_EVENT_ON_QP_ +#include "vpi.h" +#include "vpi_export.h" +#endif + +/* CM header files */ +#include "cm_common.h" +#include "cm_msg.h" + +#include "vca_export.h" /* IBT_COMPONENT_INFO is defined here */ + +/***************************************************************************** + * Defines + */ + + +/***************************************************************************** + * CM-fixed params + */ +#define CM_MAD_SIZE MAD_BLOCK_SIZE +#define CM_WELLKNOWN_QPN 1 /* QP 1 */ +#define CM_DGRM_SIZE CM_MAD_SIZE + sizeof(IB_GRH) + + /* Allow up to 92 bytes for discriminator value */ +#define CM_MAX_DISCRIMINATOR_LEN CMM_REQ_USER_LEN + + /* maximum Queued APC retries to process in a single timer event */ +#define CM_APC_RETRY_LIMIT 200 +#define CM_APC_RETRY_INTERVAL 100 /* ms */ + +/***************************************************************************** + * CM_EVENT - + * Events that affect the CEP state. + */ + + /* CM Message Events */ +#define CME_RCVD_REP 0x0001 /* Received reply msg */ +#define CME_RCVD_REQ 0x0002 /* Received request msg */ +#define CME_RCVD_MRA 0x0004 /* Received mra msg */ +#define CME_RCVD_REJ 0x0008 /* Received reject msg */ +#define CME_RCVD_RTU 0x0010 /* Received rtu msg */ +#define CME_RCVD_UMSG 0x0020 /* Received user data - NOT USED until verb send indication to CM */ +#define CME_RCVD_DREQ 0x0040 /* Received disconnect request msg */ +#define CME_RCVD_DREP 0x0080 /* Received disconnect reply msg */ +#define CME_RCVD_LAP 0x0100 /* Received lap msg */ +#define CME_RCVD_APR 0x0200 /* Received apr msg */ +#define CME_RCVD_SIDR_REQ 0x0400 /* Received sidr request msg */ +#define CME_RCVD_SIDR_RESP 0x0800 /* Received sidr response msg */ + +#define CME_TIMEOUT_REQ 0x1000 /* Request timeout (did not get REP) */ +#define CME_TIMEOUT_REP 0x2000 /* Reply timeout (did not get RTU) */ +#define CME_TIMEOUT_LAP 0x4000 /* Lap timeout (did not get APR) */ +#define CME_TIMEOUT_DREQ 0x8000 /* Disconnect request timeout */ +#define CME_TIMEOUT_TIMEWAIT 0x10000 /* Timewait timeout */ +#define CME_TIMEOUT_SIDR_REQ 0x20000 /* SIDR REQ timeout */ +#define CME_SIM_RCVD_DREQ 0x40000 /* simulating Received DREQ msg */ + + /* User Call Events */ +/*#define USRE_LISTEN 0x100000 */ +#define USRE_CONNECT 0x200000 +/*#define USRE_REGISTER 0x400000 */ +/*#define USRE_WAIT 0x800000 */ +#define USRE_DESTROY 0x1000000 +#define USRE_CANCEL 0x2000000 + + /* System Events */ +#define SYSE_DISCONNECT 0x4000000 +/*#define LAST_EVENT 0x80000000 */ + +/* + * Datagram flags + * CM uses the Dgrm->Element.Context field to hold these flags + */ +#define CM_DGRM_FLAG_IN_USE 0x0001 /* dgrm is send pending */ +#define CM_DGRM_FLAG_RELEASE 0x0002 /* return send dgrm to pool + * when send completes + */ + + +/***************************************************************************** + * CM_STATE - + * CEP object can be in different states depending on user input, + * messages coming in from the wire and timeout events + */ +typedef enum { + CMS_IDLE=1, + CMS_LISTEN, + CMS_REQ_SENT, + CMS_REQ_RCVD, + CMS_REP_SENT, + CMS_REP_RCVD, + CMS_MRA_REQ_SENT, + CMS_MRA_REP_SENT, + CMS_REP_WAIT, /* eg. CMS_MRA_REQ_RCVD */ + CMS_MRA_REP_RCVD, + CMS_ESTABLISHED, + CMS_LAP_SENT, + CMS_MRA_LAP_SENT, + CMS_LAP_RCVD, + CMS_MRA_LAP_RCVD, + CMS_DREQ_SENT, + CMS_DREQ_RCVD, + CMS_SIM_DREQ_RCVD, /* internal state, we simulated DREQ receipt + * possibly in response to receiving a REJ + * after user does a Disconnect or DestroyCEP + * we will move to Timewait + */ + CMS_TIMEWAIT, + /* states for UD SIDR CEPs */ + CMS_REGISTERED, + CMS_SIDR_REQ_SENT, + CMS_SIDR_REQ_RCVD, + /*CMS_SIDR_RESP_SENT, */ + /*CMS_SIDR_RESP_RCVD, */ +} CM_CEP_STATE; + +/***************************************************************************** + * CM_CEP_MODE - + * CEP object can be only be in 1 mode + */ +typedef enum { + CM_MODE_NONE=0, + CM_MODE_ACTIVE=1, + CM_MODE_PASSIVE, +} CM_CEP_MODE; + + +typedef struct _CM_MSG_COUNTS { + ATOMIC_UINT ClassPortInfo; + ATOMIC_UINT ClassPortInfoResp; + ATOMIC_UINT Req; + ATOMIC_UINT Rep; + ATOMIC_UINT Rtu; + ATOMIC_UINT MraReq; + ATOMIC_UINT MraRep; + ATOMIC_UINT MraLap; + ATOMIC_UINT Lap; + ATOMIC_UINT AprAcc; /* APR with good status */ + ATOMIC_UINT AprRej; /* APR with rejection status */ + ATOMIC_UINT RejReq; + ATOMIC_UINT RejRep; + ATOMIC_UINT Dreq; + ATOMIC_UINT Drep; + ATOMIC_UINT SidrReq; + ATOMIC_UINT SidrResp; + ATOMIC_UINT Failed; +} CM_MSG_COUNTS; + +/***************************************************************************** + * CM_GLOBAL_CONTEXT - + * Connection manager's global context. + * There is only 1 instance of this + */ +typedef struct _CM_GLOBAL_CONTEXT { + + IB_HANDLE GSAHandle; + + IB_HANDLE GSADgrmPoolHandle; + + /* Last LocalCommID value assigned, starts at a semi-random value */ + uint32 CommID; + + /* Last StartPSN value assigned, starts at a semi-random value */ + uint32 StartPSN; + + /* Sanity check. This is assigned at CM startup and each CEP object created is set to this value */ + uint32 Signature; + + /* Track the average local consumer processing turnaround time */ + uint64 turnaround_time_us; + + /* List of CAs */ + DLIST_ENTRY DeviceList; + SPIN_LOCK DeviceListLock; + + /* We use a single lock to provide access to the lists below. In essence, + * we are protecting the object too. In the future, we can let each list has + * its own lock to provide more concurrency. However, we will still need a common + * lock for all the lists so we can handle moving CEPs from one state to + * another (in which case the list it is on also changes). + */ + + SPIN_LOCK ListLock; + + QUICK_LIST AllCEPs; /* all the allocated CEPs */ + + CM_MAP TimerMap; /* key is CEP pointer */ + + /* Lists below are based on keys by which we lookup CEPs + * a given CEP will often be on multiple lists + */ + CM_MAP LocalCommIDMap; /* Key is LocalCommId */ + CM_MAP LocalEndPointMap; /* Key is LocalEndPoint + * not used for SIDR + */ + CM_MAP RemoteEndPointMap; /* Key is RemoteEndPoint */ + + /* Lists below are based on State of CEP + * outstanding SIDR requests from SIDRQuery are placed here + * CEPs in CMS_SIDR_REQ_SENT + * MapEntry in CEP used + */ + CM_MAP QueryMap; /* Key is LocalCommID */ + + /* Servers (CEPs in CMS_LISTEN), Sidr Listeners(CMS_REGISTERED) and + * Peer to Peer CEPs (CMS_REQ_SENT until a remote end point is associated) + * MapEntry in CEP used + */ + CM_MAP ListenMap; /* Key is bound listen address */ + + EVENT EventObj; + + EVENT CallbackEventObj; + + ATOMIC_UINT TotalCallbackRefCnt; + + /* If a single user application is heavily loaded with CM traffic, it + * could overflow its Apc buffer. In which case we keep track of + * such ceps here and attempt to retry the APC events periodically + * such that the CM event/callback is not lost + */ + QUICK_LIST ApcRetryList; /* CEPs which failed a PostApcRecord + * scheduled for retry later + */ + TIMER ApcRetryTimer; /* for ApcRetryList processing */ + uint8 ApcRetryTimerRunning;/* is timer running */ + + /* Statistics */ + CM_MSG_COUNTS Sent; + CM_MSG_COUNTS Recv; + +} CM_GLOBAL_CONTEXT; + + +/***************************************************************************** + * CM_DEVICE_OBJECT - + * Connection manager's device context. This is a per device context. + */ +typedef struct _CM_DEVICE_OBJECT { + + DLIST_ENTRY DeviceListEntry; + + uint32 Signature; /* From CM.Signature */ + + uint64 CaGUID; + +#ifdef _CM_EVENT_ON_QP_ + IB_HANDLE CaHandle; /* Returned from OpenCA() */ +#endif +} CM_DEVICE_OBJECT; + +/* A local or remote endpoint */ +typedef struct _CM_END_POINT { + uint64 CaGUID; /* Used by non-SIDR connection */ + uint32 QPN:24; + uint32 Reserved1:8; + uint32 EECN:24; + uint32 Reserved2:8; +} CM_END_POINT; + +/* portions of IB_PATH_RECORD which can vary between Primary and + * Alternate Path + */ +typedef struct _CM_CEP_PATH { + EUI64 LocalPortGuid; + IB_GID LocalGID; + IB_GID RemoteGID; + IB_LID LocalLID; + IB_LID RemoteLID; + + uint32 FlowLabel:20; + uint32 StaticRate:6; /* enum IB_STATIC_RATE */ + uint32 TClass:6; + + uint16 SL:4; + uint16 bSubnetLocal:1; + uint16 AckTimeout:5; /* what we put on wire */ + uint16 LocalAckTimeout:5; /* what we will use for our QP */ + uint16 Reserved:1; + + uint16 PkeyIndex; + uint8 HopLimit; + uint8 LocalGidIndex; /* for LocalGID */ + uint8 LocalPathBits; /* for LocalLID */ +} CM_CEP_PATH; + + +/***************************************************************************** + * CM_CEP_OBJECT - + * Connection endpoint object. This object holds various informations and state + * of a connection. + * + * List Usage: + * + * ListenMap: (uses CEP->MapEntry) + * CMS_REGISTERED, CMS_LISTEN + * CMS_REQ_SENT or CMS_MRA_REQ_RCVD for a Peer connect with no + * associated remote end point (eg. RemoteEndPoint.CaGUID == 0) + * PendingList: (uses CEP->ListEntry) + * CMS_REQ_RCVD are linked to parent (CMS_LISTEN) + * for Peer, parent is itself (linked to own list) + * CMS_SIDR_REQ_RCVD are linked to parent (CMS_REGISTERED) + * LocalCommIDMap (uses CEP->LocalCommIDMapEntry) + * all but CMS_REGISTERED, CMS_LISTEN, CMS_IDLE + * LocalEndPointMap (uses CEP->LocalEndPointMapEntry) + * CMS_REQ_SENT, ... + * RemoteEndPointMap (uses CEP->RemoteEndPointMapEntry) + * all but CMS_REGISTERED, CMS_LISTEN, CMS_IDLE + * Non-Peer Connect CMS_REQ_SENT + * Peer Connect CMS_REQ_SENT without associated remote end point + * ... + * QueryMap (uses CEP->MapEntry) + * CMS_SIDR_REQ_SENT + */ +typedef struct _CM_CEP_OBJECT { + EVENT * pWaitEvent; /* APC Event for User mode callbacks */ + + /* Event notification */ + EVENT * pEventObj; /* Event for use by CmWait for appls + * which do not want callbacks. + * bPrivateEvent indicates if this + * was supplied by appl + */ + + EVENT* pCallbackEvent; /* This is signaled when there is + * no outstanding callback. + */ + + TIMER TimerObj; /* for CM response timeouts/timewait */ + uint32 Signature; /* From CM.Signature */ + CM_CEP_STATE State; /* for CM State Machine */ + CM_CEP_MODE Mode; /* Active or passive */ + CM_CEP_TYPE Type; /* RC, UC, RD, UD */ + + uint32 EventFlags; /* indicates callback event */ + + uint8 bPeer:1; /* is this a Peer to Peer connect */ + uint8 bPrivateEvent:1;/* was pEventObj supplied by appl */ + /*uint8 bAutoCancel:1; */ + uint8 bAsyncAccept:1; /* CM_FLAG_ASYNC_ACCEPT */ + uint8 bSidrRegisterNotify:1; + uint8 RetryCount:4; /* retries done thus far for given msg */ + + uint8 ApcRetryCount; /* number of failed PostApcRecords */ + + uint64 timestamp_us; /* when timer started */ + uint32 timeout_ms; /* duration of timer */ + + uint64 turnaround_time_us; /* appl specific turnaround time */ + + uint32 ListenBackLog; /* maximum pending CEPs on a listener */ + /*uint32 TimerRefCnt; // When this obj is waited on, we increment this cnt to prevent deletion */ + + ATOMIC_UINT CallbackRefCnt; + /* Properties */ + uint32 LocalCommID; + uint32 RemoteCommID; + uint64 TransactionID; + + uint32 LocalCMTimeout:5; /* 4.096*2^n usec */ + uint32 RemoteCMTimeout:5; /* 4.096*2^n usec */ + uint32 bTimewaitCallback:1; + uint32 bFailoverSupported:1;/* best guess from REP */ + uint32 MaxCMRetries:4; + + /* PktLifeTime is not accurately available to the passive end + * so the value here is rounded up by using AckTimeout/2 + * Since this is used for CM timeouts, being conservative is fine + */ + uint16 PktLifeTime:5; /* 4.096*2^n usec */ + uint16 Timewait:5; /* 4.096*2^n usec */ + uint16 bLapSent:1; /* has a LAP been sent previously */ + uint16 TargetAckDelay:5; /* only useful for Active side */ + + CM_END_POINT LocalEndPoint; /* CaGuid used by non-SIDR connection */ + uint64 SID; + CM_END_POINT RemoteEndPoint; /* CaGuid used by non-SIDR connection */ + + CM_CEP_PATH PrimaryPath; + CM_CEP_PATH AlternatePath; + EUI64 TempAlternateLocalPortGuid; + uint8 TempAlternateLocalGidIndex; + uint8 TempAlternateLocalPathBits; + uint16 TempAlternatePkeyIndex; + uint8 TempAlternateLocalAckTimeout:5; + uint8 Reserved:3; + + uint32 QKey; /* Used by SIDR */ + uint16 PartitionKey; + uint8 LocalInitiatorDepth; // init depth we use in our QP + uint8 LocalResponderResources;// resp res we use in our QP + uint32 LocalRetryCount:3; // our send retry count + uint32 LocalRnrRetryCount:3; // our send RNR retry count + uint32 LocalSendPSN:24; // our 1st send PSN + uint32 Reserved2:2; + uint32 LocalRecvPSN:24; // our 1st expected recv PSN + uint32 Mtu:6; /* enum IB_MTU */ + uint32 Reserved3:2; + + LIST_ITEM AllCEPsItem; + LIST_ITEM ApcRetryListItem; + + CM_MAP_ITEM TimerMapEntry; /*gCM->TimerMap while timer running */ + + CM_MAP_ITEM MapEntry; /* ListenMap or QueryMap */ + CM_MAP_ITEM LocalCommIDMapEntry; + CM_MAP_ITEM LocalEndPointMapEntry; + CM_MAP_ITEM RemoteEndPointMapEntry; + + DLIST_ENTRY PendingList; /* Queued REQs not yet Accepted */ + uint32 PendingCount; + DLIST_ENTRY PendingListEntry; + struct _CM_CEP_OBJECT *pParentCEP; /* while on Pending List */ + + /* CM MAD is stored in here */ + IBT_DGRM_ELEMENT* pDgrmElement; + + /* The fields below are used for user notification */ + + /* User-specified callback function */ + SYS_CALLBACK_ITEM* pCallbackItem; + PFN_CM_CALLBACK pfnUserCallback; + void* UserContext; /* Passed to the user callback func */ + + /* Private Data discriminator for listener */ + uint8 *Discriminator; + uint8 DiscriminatorLen; + uint8 DiscrimPrivateDataOffset; +} CM_CEP_OBJECT; + + +/* Extern global var */ +extern CM_GLOBAL_CONTEXT* gCM; + +/***************************************************************************** + * + * Inline or macro routines + */ + +/* + * ValidateCEPHandle() + */ +static _inline FSTATUS +ValidateCEPHandle(IN IB_HANDLE hCEP) +{ + if (!gCM) + return FCM_NOT_INITIALIZED; + + if (hCEP == NULL) + return FINVALID_PARAMETER; + + /* Make sure this is a CEP_OBJECT */ + if (((CM_CEP_OBJECT*)hCEP)->Signature != gCM->Signature) + return FCM_INVALID_HANDLE; + + return FSUCCESS; +} /* ValidateCEPHandle() */ + +static _inline boolean +AltPathValid(IN CM_CEP_OBJECT* pCEP) +{ + return (pCEP->AlternatePath.LocalLID != 0); +} + + +/***************************************************************************** + * + * Events wrapper + */ +static _inline EVENT* +EventAlloc(void) +{ + EVENT* pEvent=NULL; + + pEvent = (EVENT*)MemoryAllocateAndClear(sizeof(EVENT), FALSE, CM_MEM_TAG); + if (pEvent) + { + if (EventInit(pEvent) != TRUE) + { + MemoryDeallocate(pEvent); + pEvent = NULL; + } + } + return pEvent; +} + +#define EventDealloc(pEvent) {\ + EventDestroy(pEvent);\ + MemoryDeallocate(pEvent);\ + pEvent = NULL;\ + } + +/* EventSet macro is OS dependent. It is moved to cm_private_osd.h */ + +/***************************************************************************** + * + * Datagram wrapper + */ + +/* + * CmDgrmCopyAddrAndMad() + */ +#define CmDgrmCopyAddrAndMad(pDgrmTo, pMad, pDgrmFrom) {\ + memcpy(GsiDgrmGetSendMad(pDgrmTo), pMad, sizeof(CM_MAD));\ + GsiDgrmAddrCopy(pDgrmTo, pDgrmFrom);\ + } + +/* + * CmDgrmAddrSet() + */ +#define CmDgrmAddrSet(pDgrmAddr, portguid, remotelid, servicelevel, pathbits, staticrate, globalr, dgid, fl, sgidindex, hop, tc, pkeyindex) {\ + (pDgrmAddr)->PathBits = (uint8)pathbits;\ + (pDgrmAddr)->StaticRate = (uint8)staticrate;\ + (pDgrmAddr)->PkeyIndex = pkeyindex;\ + (pDgrmAddr)->ServiceLevel = (uint8)servicelevel;\ + (pDgrmAddr)->PortGuid = portguid;\ + (pDgrmAddr)->RemoteLID = remotelid;\ + (pDgrmAddr)->RemoteQKey = QP1_WELL_KNOWN_Q_KEY;\ + (pDgrmAddr)->RemoteQP = CM_WELLKNOWN_QPN;\ + (pDgrmAddr)->GlobalRoute = globalr;\ + memcpy(&(pDgrmAddr)->GRHInfo.DestGID, &dgid, sizeof(IB_GID));\ + (pDgrmAddr)->GRHInfo.FlowLabel = fl;\ + (pDgrmAddr)->GRHInfo.SrcGIDIndex= sgidindex;\ + (pDgrmAddr)->GRHInfo.HopLimit = hop;\ + (pDgrmAddr)->GRHInfo.TrafficClass = tc;\ + } + +/* Release flag */ +#define CmDgrmSetReleaseFlag(pDgrm) \ + ( (pDgrm)->Element.pContext = (void*)( (uintn)((pDgrm)->Element.pContext) | CM_DGRM_FLAG_RELEASE) ) + +#define CmDgrmClearReleaseFlag(pDgrm) \ + ( (pDgrm)->Element.pContext = (void*)( (uintn)((pDgrm)->Element.pContext) & (~CM_DGRM_FLAG_RELEASE)) ) + +#define CmDgrmIsReleaseFlagSet(pDgrm) \ + ( ( (uintn)((pDgrm)->Element.pContext) & CM_DGRM_FLAG_RELEASE) ) + +/* In-use flag */ +#define CmDgrmSetInUse(pDgrm) \ + ( (pDgrm)->Element.pContext = (void*)( (uintn)((pDgrm)->Element.pContext) | CM_DGRM_FLAG_IN_USE) ) + +#define CmDgrmClearInUse(pDgrm) \ + ( (pDgrm)->Element.pContext = (void*)( (uintn)((pDgrm)->Element.pContext) & (~CM_DGRM_FLAG_IN_USE)) ) + +#define CmDgrmIsInUse(pDgrm) \ + ( ( (uintn)((pDgrm)->Element.pContext) & CM_DGRM_FLAG_IN_USE) ) + +/* + * CmDgrmSend() + */ +static _inline FSTATUS +CmDgrmSend(IBT_DGRM_ELEMENT* pDgrm) +{ + ASSERT(!CmDgrmIsInUse(pDgrm)); + CmDgrmSetInUse(pDgrm); + if (iba_gsi_post_send(gCM->GSAHandle, pDgrm) == FSUCCESS) + { + return FSUCCESS; + } + else + { + AtomicIncrement(&gCM->Sent.Failed); + CmDgrmClearInUse(pDgrm); + return FERROR; + } +} /* CmDgrmSend() */ + +/* + * CmDgrmSendAndRelease() + */ +static _inline FSTATUS +CmDgrmSendAndRelease(IBT_DGRM_ELEMENT* pDgrm) +{ + ASSERT(!CmDgrmIsInUse(pDgrm)); + CmDgrmSetInUse(pDgrm); + CmDgrmSetReleaseFlag(pDgrm); + if (iba_gsi_post_send(gCM->GSAHandle, pDgrm) == FSUCCESS) + { + return FSUCCESS; + } + else + { + CmDgrmClearReleaseFlag(pDgrm); + CmDgrmClearInUse(pDgrm); + return FERROR; + } +} /* CmDgrmSendAndRelease() */ + +extern void +CmDgrmGetFailed(void); + +/* + * CmDgrmGet() + */ +static _inline IBT_DGRM_ELEMENT* +CmDgrmGet(void) +{ + uint32 Count=1; + IBT_DGRM_ELEMENT* pDgrm=NULL; + + if (iba_gsi_dgrm_pool_get(gCM->GSADgrmPoolHandle, &Count, &pDgrm) == FSUCCESS) + { + ASSERT(pDgrm->Element.pContext == 0); + } else { + pDgrm = NULL; + CmDgrmGetFailed(); + } + iba_gsi_dgrm_pool_grow_as_needed(gCM->GSADgrmPoolHandle, + gCmParams.MinFreeDgrms, + gCmParams.MaxDgrms, gCmParams.DgrmIncrement); + return pDgrm; +} + +/* + * CmDgrmPut() + */ +#define CmDgrmPut(pDgrm) {\ + if (pDgrm) {\ + ASSERT(!CmDgrmIsInUse(pDgrm));\ + pDgrm->Element.pContext = 0;\ + iba_gsi_dgrm_pool_put(pDgrm);\ + pDgrm = NULL;\ + }\ + } + +#define CmDgrmRelease(pDgrm) {\ + if (pDgrm) { \ + if (CmDgrmIsInUse(pDgrm)) { \ + CmDgrmSetReleaseFlag(pDgrm); \ + } else { \ + CmDgrmPut(pDgrm); \ + } \ + pDgrm = NULL;\ + } \ +} + +FSTATUS +PrepareCepDgrm(CM_CEP_OBJECT* pCEP); + +/***************************************************************************** + */ + +#define CepSetState(pCEP, state) {\ + pCEP->State = state;\ + _DBG_INFO((" *** CEP STATE set to " #state " ***\n", _DBG_PTR(pCEP)));\ + } + +/* move a CEP from some other state to Idle, assumes CEP already removed + * from any state specific list/map for present state + */ +#define CepToIdle(pCEP) { \ + ASSERT(DListIsEmpty(&pCEP->PendingList)); \ + ASSERT(pCEP->PendingCount == 0); \ + ClearEndPoint(pCEP); \ + pCEP->bPeer = FALSE; \ + pCEP->LocalEndPoint.CaGUID = 0; \ + pCEP->bLapSent = 0; \ + pCEP->TargetAckDelay = 0; \ + ClearLocalCommID(pCEP); \ + CepSetState(pCEP, CMS_IDLE); \ + } + +#define CepAddToPendingList(pParent, pCEP) { \ + DListInsertTail(&pParent->PendingList, &pCEP->PendingListEntry, PENDING_LIST, pCEP); \ + ++(pParent->PendingCount); \ + pCEP->pParentCEP = pParent; \ + } + +#define CepRemoveFromPendingList(pCEP) { \ + DListRemoveEntry(&pCEP->PendingListEntry, PENDING_LIST, pCEP); \ + --(pCEP->pParentCEP->PendingCount); \ + pCEP->pParentCEP = NULL; \ + } + +/* move CEP to a disconnecting state (as provided) */ +#define CepToDisconnecting(pCEP, state) { \ + if (gCmParams.ReuseQP) \ + ClearEndPoint(pCEP); \ + CepSetState(pCEP, state); \ + } + +/* move a CEP from some other state to Timewait */ +#define CepToTimewait(pCEP) { \ + uint32 timewait_timeout_ms=0; \ +\ + if (gCmParams.ReuseQP) \ + ClearEndPoint(pCEP); \ + CepSetState(pCEP, CMS_TIMEWAIT); \ + /* Start the timewait timer to move back to IDLE */ \ + timewait_timeout_ms = TimeoutMultToTimeInMs(pCEP->Timewait); \ + CmTimerStart(pCEP, timewait_timeout_ms, TIMEWAIT_TIMER); \ + } + + +/***************************************************************************** + * + * TimeStamps for elapsed time computations + */ +static _inline uint64 +CmGetElapsedTime(CM_CEP_OBJECT* pCEP) +{ + uint64 currtime_us=GetTimeStamp(); + uint64 elapsed_us=0; + + if (currtime_us >= pCEP->timestamp_us) + elapsed_us = currtime_us - pCEP->timestamp_us; + else + elapsed_us = (currtime_us + ((uint64)(-1) - pCEP->timestamp_us)); + + return elapsed_us; +} + +static _inline uint64 +CmComputeElapsedTime(CM_CEP_OBJECT* pCEP, uint64 currtime_us) +{ + uint64 elapsed_us=0; + + if (currtime_us >= pCEP->timestamp_us) + elapsed_us = currtime_us - pCEP->timestamp_us; + else + elapsed_us = (currtime_us + ((uint64)(-1) - pCEP->timestamp_us)); + + return elapsed_us; +} + +#define CmStartElapsedTime(pCEP) \ + pCEP->timestamp_us = GetTimeStamp(); + +/***************************************************************************** + * + * Timers + */ +#define TIMER_RESOLUTION_US 0 + +static _inline boolean +CmTimerHasExpired(CM_CEP_OBJECT* pCEP) +{ + uint64 elapsed_us=0; + uint64 timeinterval_us=pCEP->timeout_ms*1000; + + elapsed_us = CmGetElapsedTime(pCEP); + + if (( (elapsed_us + TIMER_RESOLUTION_US) >= timeinterval_us) && timeinterval_us) + return TRUE; + else + return FALSE; +} + + +#define CmTimerStart(pCEP, interval_ms, type) {\ + ASSERT(interval_ms);\ + ASSERT(! pCEP->timeout_ms); \ + pCEP->timestamp_us = GetTimeStamp();\ + pCEP->timeout_ms = interval_ms;\ + _DBG_INFO((" >>>"#type " started .\n",\ + _DBG_PTR(pCEP), pCEP->LocalCommID, \ + _DBG_PTR(CmGetStateString(pCEP->State)), \ + pCEP->timeout_ms, pCEP->timestamp_us));\ + TimerStart(&pCEP->TimerObj, pCEP->timeout_ms);\ + CM_MapInsert(&gCM->TimerMap, (uint64)(uintn)pCEP, &pCEP->TimerMapEntry, TIMER_LIST, pCEP);\ + } + +#define CmTimerClear(pCEP) {\ + ASSERT(pCEP->timeout_ms); \ + pCEP->timeout_ms=0;\ + CM_MapRemoveEntry(&gCM->TimerMap, &pCEP->TimerMapEntry, TIMER_LIST, pCEP);\ + } + +#define CmTimerStop(pCEP, type) {\ + if (CmTimerHasExpired(pCEP))\ + {\ + _DBG_INFO((" <<<"#type " already expired .\n",\ + _DBG_PTR(pCEP), pCEP->LocalCommID, \ + _DBG_PTR(CmGetStateString(pCEP->State)), \ + GetTimeStamp()));\ + }\ + else\ + {\ + TimerStop(&pCEP->TimerObj);\ + _DBG_INFO((" <<<"#type " stopped .\n",\ + _DBG_PTR(pCEP), pCEP->LocalCommID, \ + _DBG_PTR(CmGetStateString(pCEP->State)), \ + GetTimeStamp()));\ + }\ + if (pCEP->timeout_ms) \ + CmTimerClear(pCEP);\ + } + +/*****************************************************************************/ +/* Private function prototypes */ + +/* Private routines - mostly not thread-safe */ +CM_CEP_OBJECT* +CreateCEP( + IN CM_CEP_TYPE TransportServiceType, + IN EVENT_HANDLE hEvent, + IN EVENT_HANDLE hWaitEvent + ); + +FSTATUS +DestroyCEP( + IN CM_CEP_OBJECT* pCEP + ); + +/* Helper routines */ +void AssignLocalCommID( + IN CM_CEP_OBJECT* pCEP + ); + +void ClearLocalCommID( + IN CM_CEP_OBJECT* pCEP + ); + +CM_CEP_OBJECT* FindLocalCommID( + IN uint32 LocalCommID + ); + +uint32 GenerateStartPSN(void); + +int +CepLocalEndPointCompare(uint64 key1, uint64 key2); + +int +CepAddrLocalEndPointCompare(uint64 key1, uint64 key2); + +int +CepRemoteEndPointCompare(uint64 key1, uint64 key2); + +void +ClearEndPoint( + IN CM_CEP_OBJECT* pCEP + ); + +void +DgrmDump( + IN IBT_DGRM_ELEMENT* pDgrm, + IN char* pStr, + IN boolean bRecv + ); + +FSTATUS +SendREJ( + IN CM_REJECTION_CODE Reason, + IN CMM_REJ_MSGTYPE MsgRejected, + IN uint64 TransactionID, + IN uint32 LocalCommID, + IN uint32 RemoteCommID, + IBT_DGRM_ELEMENT* pRemoteDgrm + ); + +FSTATUS +SendMRA( + IN CMM_MRA_MSGTYPE MsgMraed, + IN uint8 ServiceTimeout, + IN uint64 TransactionID, + IN uint32 LocalCommID, + IN uint32 RemoteCommID, + IBT_DGRM_ELEMENT* pRemoteDgrm + ); + +FSTATUS +SendRTU( + IN uint64 TransactionID, + IN uint32 LocalCommID, + IN uint32 RemoteCommID, + IBT_DGRM_ELEMENT* pRemoteDgrm + ); + +FSTATUS +SendAPR( + IN CM_APR_STATUS APStatus, + IN uint64 TransactionID, + IN uint32 LocalCommID, + IN uint32 RemoteCommID, + IBT_DGRM_ELEMENT* pRemoteDgrm + ); + +FSTATUS +SendSIDR_RESP( + IN uint64 SID, + IN uint32 QPN, + IN uint32 QKey, + IN uint32 Status, + IN const uint8* pPrivateData, + IN uint32 DataLen, + IN uint64 TransactionID, + IN uint32 RequestID, + IN IBT_DGRM_ELEMENT* pRemoteDgrm + ); + +FSTATUS +SendDREQ( + IN uint32 QPN, + IN uint64 TransactionID, + IN uint32 LocalCommID, + IN uint32 RemoteCommID, + IN IBT_DGRM_ELEMENT* pRemoteDgrm + ); + +FSTATUS +SendDREP( + IN uint64 TransactionID, + IN uint32 LocalCommID, + IN uint32 RemoteCommID, + IN IBT_DGRM_ELEMENT* pRemoteDgrm + ); + +FSTATUS +CopyMadToConnInfo( + CONN_INFO* pConnInfo, + const CM_MAD* pMad + ); + +uint32 SidrTimeout( + IN CM_CEP_OBJECT* pCEP + ); + +uint64 +UpdateTurnaroundTime( + IN uint64 turnaround_us, + IN uint64 elapsed_us + ); + +uint32 +CepWorstServiceTimeMult( + IN CM_CEP_OBJECT *pCEP + ); + +void +CmClearStats(void); + +FSTATUS +RequestCheck( + IN const CM_REQUEST_INFO* pRequest + ); + +boolean +SetNotification( + IN CM_CEP_OBJECT* pCEP, + uint32 EventType + ); + +void +QueueApcRetry( + IN CM_CEP_OBJECT* pCEP + ); + +void +ApcRetryTimerCallback( + IN void* Context + ); + +FSTATUS +GetConnInfo( + IN CM_CEP_OBJECT* pCEP, + OUT struct _CM_CONN_INFO* pConnInfo + ); + +void CopyPathInfoToCepPath( + OUT CM_CEP_PATH *pCepPath, + IN const CM_CEP_PATHINFO *pPathInfo, + IN uint8 AckTimeout + ); + +void GetAVFromCepPath( + IN CM_CEP_PATH* CepPath, + OUT IB_ADDRESS_VECTOR* DestAv + ); + +void CopyCepPathToPathInfo( + OUT CM_CEP_PATHINFO *pPathInfo, + OUT uint8* pAckTimeout, + IN CM_CEP_PATH *pCepPath + ); + +int CompareCepPathToPathInfo( + IN const CM_CEP_PATH *pCepPath, + IN const CM_CEP_PATHINFO *pPathInfo + ); + +void GetInitAttrFromCep( + IN CM_CEP_OBJECT* pCEP, + OUT IB_QP_ATTRIBUTES_MODIFY* QpAttrInit + ); + +void GetRtrAttrFromCep( + IN CM_CEP_OBJECT* pCEP, + boolean enableFailover, + OUT IB_QP_ATTRIBUTES_MODIFY* QpAttrRtr + ); + +void GetRtsAttrFromCep( + IN CM_CEP_OBJECT* pCEP, + OUT IB_QP_ATTRIBUTES_MODIFY* QpAttrRts + ); + +int +CepListenAddrCompare(uint64 key1, uint64 key2); + +int +CepReqAddrCompare(uint64 key1, uint64 key2); + +int +CepSidrReqAddrCompare(uint64 key1, uint64 key2); + +int +CepReqRemoteEndPointCompare(uint64 key1, uint64 key2); + +static __inline +boolean CepRemoteEndPointMatchReq(IN CM_CEP_OBJECT* pCEP, IN CMM_REQ *pREQ) +{ + return ( (pCEP->RemoteEndPoint.QPN == pREQ->u1.s.LocalQPN) && + (pCEP->RemoteEndPoint.EECN == pREQ->u2.s.LocalEECN) && + (pCEP->RemoteEndPoint.CaGUID == pREQ->LocalCaGUID)); +} + +static __inline +boolean CepRemoteEndPointMatchRep(IN CM_CEP_OBJECT* pCEP, IN CMM_REP *pREP) +{ + return ( (pCEP->RemoteEndPoint.QPN == pREP->u1.s.LocalQPN) && + (pCEP->RemoteEndPoint.EECN == pREP->u2.s.LocalEECN) && + (pCEP->RemoteEndPoint.CaGUID == pREP->LocalCaGUID)); +} + +static __inline +boolean CepLocalEndPointMatchReq(IN CM_CEP_OBJECT* pCEP, IN CMM_REQ *pREQ) +{ + return ( (pCEP->LocalEndPoint.CaGUID == pREQ->LocalCaGUID) && + (pCEP->LocalEndPoint.QPN == pREQ->u1.s.LocalQPN) && + (pCEP->LocalEndPoint.EECN == pREQ->u2.s.LocalEECN)); +} + +/* TBD move rest of CM_Map macros from cm_common.h */ +static __inline +boolean CM_MapTryInsert(CM_MAP* pMap, uint64 Key, CM_MAP_ITEM* pEntry, + const char* MapName, CM_CEP_OBJECT* pCEP) +{ + if (cl_qmap_insert(pMap, Key, pEntry) != pEntry) + return FALSE; + _DBG_INFO((" --> Insert into %s\n", _DBG_PTR(pCEP), _DBG_PTR(MapName))); + return TRUE; +} + +const char* +CmGetStateString(CM_CEP_STATE state); + +void +CopyRcvdLAPToAltPath( + IN const CMM_LAP* pLAP, + OUT CM_CEP_PATH *pAltPath + ); + +void +CopySentLAPToAltPath( + IN const CMM_LAP* pLAP, + OUT CM_CEP_PATH *pAltPath + ); + +int +CompareRcvdLAPToPath( + IN const CMM_LAP* pLAP, + IN const CM_CEP_PATH *pPath + ); + +/* Callback routines */ +#ifdef _CM_EVENT_ON_QP_ + +void +VpdCompletionCallback( + IN void *CaContext, + IN void *CqContext + ); + +void +VpdAsyncEventCallback( + IN void *CaContext, + IN IB_EVENT_RECORD *EventRecord + ); +#endif + +void +GsaSendCompleteCallback( + IN void* Context, + IN IBT_DGRM_ELEMENT* pDgrmList + ); + +FSTATUS +GsaRecvCallback( + IN void* Context, + IN IBT_DGRM_ELEMENT* pDgrmList + ); + +void +CmTimerCallback( + IN void* Context + ); + +void +CmSystemCallback( + IN void* Key, + IN void* Context + ); + +void +CmDoneCallback( + IN CM_CEP_OBJECT* pCEP + ); + +/* Client-side routines */ + +FSTATUS +Connect( + IN CM_CEP_OBJECT* pCEP, + IN const CM_REQUEST_INFO* pConnectRequest, + IN boolean bPeer, + IN PFN_CM_CALLBACK pfnConnectCB, + IN void* Context + ); + +FSTATUS +AcceptA( + IN CM_CEP_OBJECT* pCEP, + IN struct _CM_CONN_INFO* pSendConnInfo /* Send RTU */ + ); + +FSTATUS +RejectA( + IN CM_CEP_OBJECT* pCEP, + IN const CM_REJECT_INFO* pConnectReject + ); + +FSTATUS +WaitA( + IN CM_CEP_OBJECT* pCEP, + OUT struct _CM_CONN_INFO* pConnInfo, + IN uint32 Timeout_us + ); + +FSTATUS +CancelA( + IN CM_CEP_OBJECT* pCEP + ); + +FSTATUS +ProcessReplyA( + IN CM_CEP_OBJECT* pCEP, + OUT CM_PROCESS_REPLY_INFO* Info + ); + +FSTATUS +AltPathRequestA( + IN CM_CEP_OBJECT* pCEP, + IN const CM_ALTPATH_INFO* pLapInfo /* Send LAP */ + ); + +FSTATUS +ProcessAltPathReplyA( + IN CM_CEP_OBJECT* pCEP, + IN const CM_ALTPATH_REPLY_INFO* AltPathReply, + OUT IB_QP_ATTRIBUTES_MODIFY* QpAttrRts + ); + +FSTATUS +MigratedA( + IN CM_CEP_OBJECT* pCEP + ); + +FSTATUS +MigratedReloadA( + IN CM_CEP_OBJECT* pCEP, + OUT CM_PATH_INFO* NewPrimaryPath OPTIONAL, + OUT CM_ALTPATH_INFO* AltPathRequest OPTIONAL + ); + +FSTATUS +ShutdownA( + IN CM_CEP_OBJECT* pCEP + ); + +FSTATUS +DisconnectA( + IN CM_CEP_OBJECT* pCEP, + IN const CM_DREQUEST_INFO* pDRequest, /* Send DREQ */ + IN const CM_DREPLY_INFO* pDReply /* Send DREP */ + ); + +/* Server-side routines */ +FSTATUS +Listen( + IN CM_CEP_OBJECT* pCEP, + IN CM_LISTEN_INFO* pListenInfo, + IN PFN_CM_CALLBACK pfnListenCB, + IN void* Context + ); + +FSTATUS +WaitP( + IN CM_CEP_OBJECT* pCEP, + OUT struct _CM_CONN_INFO* pConnInfo, + IN uint32 Timeout_us + ); + +FSTATUS +ProcessRequestP( + IN CM_CEP_OBJECT* pCEP, + IN CM_REP_FAILOVER Failover, + OUT CM_PROCESS_REQUEST_INFO *Info + ); + +FSTATUS +AcceptP_Async( + IN CM_CEP_OBJECT* pCEP, + IN const struct _CM_CONN_INFO* pSendConnInfo, /* Send REP */ + IN EVENT_HANDLE hEvent, + IN EVENT_HANDLE hWaitEvent, + IN PFN_CM_CALLBACK pfnCallback, + IN void* Context, + IN boolean willWait, + OUT CM_CEP_OBJECT** ppCEP + ); + +FSTATUS +AcceptP( + IN CM_CEP_OBJECT* pCEP, + IN const struct _CM_CONN_INFO* pSendConnInfo, /* Send REP */ + OUT struct _CM_CONN_INFO* pRecvConnInfo, /* Recv RTU */ + IN PFN_CM_CALLBACK pfnCallback, + IN void* Context, + OUT CM_CEP_OBJECT** ppNewCEP + ); + +FSTATUS +RejectP( + IN CM_CEP_OBJECT* pCEP, + IN const CM_REJECT_INFO* pConnectReject + ); + +FSTATUS +CancelP( + IN CM_CEP_OBJECT* pCEP + ); + +FSTATUS +ProcessAltPathRequestP( + IN CM_CEP_OBJECT* pCEP, + IN CM_ALTPATH_INFO* AltPathRequest, + OUT CM_PROCESS_ALTPATH_REQUEST_INFO* Info + ); + +FSTATUS +AltPathReplyP( + IN CM_CEP_OBJECT* pCEP, + IN CM_ALTPATH_REPLY_INFO* pAprInfo /* Send APR */ + ); + +/* + * CmDeviceInit + * + * Init a device. This routine is called when a new device is detected and added. + * + * + * + * INPUTS: + * + * None. + * + * + * OUTPUTS: + * + * None. + * + * + * RETURNS: + * + * FSUCCESS + * FERROR + * + */ +FSTATUS +CmDeviceInit( + IN EUI64 CaGuid, + OUT void **Context + ); + + +/* + * CmDeviceDestroy + * + * Destroy the device. This routine is called when a device is removed. + * + * + * + * INPUTS: + * + * None. + * + * + * OUTPUTS: + * + * None. + * + * + * RETURNS: + * + * FSUCCESS + * FERROR + * + */ +FSTATUS +CmDeviceDestroy( + IN EUI64 CaGuid, + IN void *Context + ); + +/* Internal use only */ +IB_HANDLE +CmCreateCEPEx( + IN CM_CEP_TYPE TransportServiceType, + IN EVENT_HANDLE hEvent, + IN EVENT_HANDLE hWaitEvent + ); + + +FSTATUS +CmAcceptEx( + IN IB_HANDLE hCEP, + IN CM_CONN_INFO* pSendConnInfo, /* Send REP, Send RTU */ + IN EVENT_HANDLE hEvent, + IN EVENT_HANDLE hWaitEvent, + IN PFN_CM_CALLBACK pfnCallback, /* For hNewCEP */ + IN void* Context, + OUT IB_HANDLE* hNewCEP + ); + +/* This defines some OS specific macros and functions */ +#include "cm_private_osd.h" + +#if defined (__cplusplus) +}; +#endif + + +#endif /* _INSI_IB_CM_PRIVATE_H_ */ diff --git a/IbAccess/Common/Ibt/Cm/sidr_api.c b/IbAccess/Common/Ibt/Cm/sidr_api.c new file mode 100644 index 0000000..61178e7 --- /dev/null +++ b/IbAccess/Common/Ibt/Cm/sidr_api.c @@ -0,0 +1,534 @@ +/* BEGIN_ICS_COPYRIGHT4 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT4 ****************************************/ + +// Public header file +#include "ib_cm.h" + +// Private header file +#include "cm_private.h" + + +////////////////////////////////////////////////////////////////////////// +// iba_cm_sidr_register +// +// +// INPUTS: +// +// +// +// OUTPUTS: +// +// None. +// +// RETURNS: +// +// FSUCCESS. +// +// IRQL: +// +// This routine is called at IRQL_PASSIVE_LEVEL. +// +FSTATUS +iba_cm_sidr_register( + IN IB_HANDLE hCEP, + IN const SIDR_REGISTER_INFO* pSIDRRegisterInfo, + PFN_CM_CALLBACK pfnLookupCallback, + void* Context + ) +{ + CM_CEP_OBJECT* pCEP=(CM_CEP_OBJECT*)hCEP; + FSTATUS Status=FSUCCESS; + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, iba_cm_sidr_register); + + // + // Parameter check + // + Status = ValidateCEPHandle(pCEP); + if (Status != FSUCCESS) + { + _DBG_LEAVE_LVL(_DBG_LVL_FUNC_TRACE); + + return Status; + } + + SpinLockAcquire(&gCM->ListLock); + + // We must be in idle state + if (pCEP->State != CMS_IDLE) + { + SpinLockRelease(&gCM->ListLock); + + _DBG_LEAVE_LVL(_DBG_LVL_FUNC_TRACE); + + return FINVALID_STATE; + } + + pCEP->Mode = CM_MODE_PASSIVE; + + // Bind address is based on SID with secondary optional fields + // (most of which are not applicable for SIDR) + ASSERT(! pCEP->bPeer); + + // we do not put on LocalEndPoint map because multiple Service IDs could + // have the same QPN/EECN response. Also we never need to lookup nor + // verify LocalEndPoint for CMS_REGISTER'ed CEPs + MemoryClear(&pCEP->PrimaryPath, sizeof(pCEP->PrimaryPath)); + pCEP->LocalEndPoint.EECN = 0; + pCEP->LocalEndPoint.CaGUID = 0; + pCEP->Mtu = 0; // not used + pCEP->PartitionKey = 0; // not used + + pCEP->RemoteEndPoint.QPN = pCEP->RemoteEndPoint.EECN = 0; + pCEP->RemoteEndPoint.CaGUID = 0; + + pCEP->SID = pSIDRRegisterInfo->ServiceID; + pCEP->LocalEndPoint.QPN = pSIDRRegisterInfo->QPN; + + // add to ListenMap (which inbound SIDR_REQ will search) and + // make sure the bound address is unique + if (! CM_MapTryInsert(&gCM->ListenMap, (uintn)pCEP, &pCEP->MapEntry, + "LISTEN_LIST", pCEP)) + { + // undo settings + pCEP->SID = 0; + pCEP->LocalEndPoint.QPN = 0; + SpinLockRelease(&gCM->ListLock); + + _DBG_LEAVE_LVL(_DBG_LVL_FUNC_TRACE); + + return FCM_ADDR_INUSE; + } + + // This is used only for debugging purposes + AssignLocalCommID(pCEP); + pCEP->TransactionID = 0; // not used, we are passive side + + pCEP->QKey = pSIDRRegisterInfo->QKey; + pCEP->pfnUserCallback = pfnLookupCallback; + pCEP->UserContext = Context; + + // By default, bSidrRegisterNotify is 0. We reset this in SIDRDeregister() + if (pCEP->pfnUserCallback) + { + pCEP->bSidrRegisterNotify = 1; + } + + CepSetState(pCEP, CMS_REGISTERED); + + SpinLockRelease(&gCM->ListLock); + + _DBG_LEAVE_LVL(_DBG_LVL_FUNC_TRACE); + + return FSUCCESS; + +} // iba_cm_sidr_register() + + +////////////////////////////////////////////////////////////////////////// +// iba_cm_sidr_deregister +// +// +// INPUTS: +// +// +// +// OUTPUTS: +// +// None. +// +// RETURNS: +// +// FSUCCESS. +// +// IRQL: +// +// This routine is called at IRQL_PASSIVE_LEVEL. +// +FSTATUS +iba_cm_sidr_deregister( + IB_HANDLE hCEP + ) +{ + CM_CEP_OBJECT* pCEP=(CM_CEP_OBJECT*)hCEP; + CM_CEP_OBJECT* pCEPEntry=NULL; + + DLIST_ENTRY* pListEntry=NULL; + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, iba_cm_sidr_deregister); + + SpinLockAcquire(&gCM->ListLock); + if (pCEP->State != CMS_REGISTERED) + { + SpinLockRelease(&gCM->ListLock); + + _DBG_LEAVE_LVL(_DBG_LVL_FUNC_TRACE); + + return FINVALID_STATE; + } + + // not on LocalEndPointMap, so must clear before ClearEndPoint in CepToIdle + pCEP->LocalEndPoint.QPN = 0; + pCEP->LocalEndPoint.EECN = 0; + pCEP->bSidrRegisterNotify = 0; + + // Cleanup the pending list + while (!DListIsEmpty(&pCEP->PendingList)) + { + pListEntry = DListGetNext(&pCEP->PendingList); + pCEPEntry = PARENT_STRUCT(pListEntry, CM_CEP_OBJECT, PendingListEntry); + + // Move from PENDING to INIT list and destroy it + ASSERT(pCEPEntry->pParentCEP == pCEP); + CepRemoveFromPendingList(pCEPEntry); + // ClearEndPoint in CepToIdle is benign + CepToIdle(pCEPEntry); + + DestroyCEP(pCEPEntry); + } + ASSERT(pCEP->PendingCount == 0); + + // Move from LISTEN to IDLE + CM_MapRemoveEntry(&gCM->ListenMap, &pCEP->MapEntry, LISTEN_LIST, pCEP); + // ClearEndPoint in CepToIdle is benign + CepToIdle(pCEP); + + SpinLockRelease(&gCM->ListLock); + + _DBG_LEAVE_LVL(_DBG_LVL_FUNC_TRACE); + + return FSUCCESS; + +} // iba_cm_sidr_deregister() + + +////////////////////////////////////////////////////////////////////////// +// iba_cm_sidr_response +// +// +// INPUTS: +// +// +// +// OUTPUTS: +// +// None. +// +// RETURNS: +// +// FSUCCESS. +// +// IRQL: +// +// This routine is called at IRQL_PASSIVE_LEVEL. +// +FSTATUS +iba_cm_sidr_response( + IN IB_HANDLE hCEP, + IN const SIDR_RESP_INFO* pSIDRResponse + ) +{ + CM_CEP_OBJECT* pCEP = (CM_CEP_OBJECT*)hCEP; + CM_CEP_OBJECT* pCEPEntry = NULL; + + DLIST_ENTRY* pListEntry=NULL; + + uint32 Status=FSUCCESS; + + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, iba_cm_sidr_response); + + + // + // SIDR response - + // + SpinLockAcquire(&gCM->ListLock); + + if (pCEP->State != CMS_REGISTERED) + { + SpinLockRelease(&gCM->ListLock); + + _DBG_LEAVE_LVL(_DBG_LVL_FUNC_TRACE); + + return FINVALID_STATE; + } + + // Get the request we are responding to + if(DListIsEmpty(&pCEP->PendingList)) + { + SpinLockRelease(&gCM->ListLock); + + _DBG_LEAVE_LVL(_DBG_LVL_FUNC_TRACE); + + return FNOT_FOUND; + } + + pListEntry = DListGetNext(&pCEP->PendingList); + pCEPEntry = PARENT_STRUCT(pListEntry, CM_CEP_OBJECT, PendingListEntry); + + // Cannot accept until the user has been notify thru wait + /* + if (!BitTest(pCEPEntry->EventFlags, USRE_WAIT)) + { + SpinLockRelease(&gCM->ListLock); + _DBG_LEAVE_LVL(_DBG_LVL_FUNC_TRACE); + return FUNAVAILABLE; + } + + // Clear the flag + BitClear(pCEPEntry->EventFlags, USRE_WAIT); + */ + + // Move from the PENDING to INIT list + ASSERT(pCEPEntry->pParentCEP == pCEP); + CepRemoveFromPendingList(pCEPEntry); + // ClearEndPoint in CepToIdle is benign + CepToIdle(pCEPEntry); // CMS_SIDR_RESP_SENT + + // Send the SIDR response. + Status = SendSIDR_RESP(pCEP->SID, + pSIDRResponse->QPN, + pSIDRResponse->QKey, + pSIDRResponse->Status, + pSIDRResponse->PrivateData, + CMM_SIDR_RESP_USER_LEN, + pCEPEntry->TransactionID, + pCEPEntry->RemoteCommID, + pCEPEntry->pDgrmElement); + + // No further use for this obj. Destroy it. + DestroyCEP(pCEPEntry); + + // If there are other pending request, retrigger the event + if (pCEP->PendingCount) + { + //MsgOut("SIDR re-notify, pending not empty\n"); + SetNotification(pCEP, CME_RCVD_SIDR_REQ); //EventSet(pCEP, CME_RCVD_SIDR_REQ); + } + + SpinLockRelease(&gCM->ListLock); + + _DBG_LEAVE_LVL(_DBG_LVL_FUNC_TRACE); + + return Status; + +} // iba_cm_sidr_response() + + +////////////////////////////////////////////////////////////////////////// +// iba_cm_sidr_query +// +// +// INPUTS: +// +// +// +// OUTPUTS: +// +// None. +// +// RETURNS: +// +// FSUCCESS. +// +// IRQL: +// +// This routine is called at IRQL_PASSIVE_LEVEL. +// +FSTATUS +iba_cm_sidr_query( + IB_HANDLE hCEP, + const SIDR_REQ_INFO* pSIDRRequest, + PFN_CM_CALLBACK pfnQueryCB, + void* Context + ) +{ + CM_CEP_OBJECT* pCEP=(CM_CEP_OBJECT*)hCEP; + FSTATUS Status=FSUCCESS; + + uint8 SrcGidIndex=0; + IB_PORT_ATTRIBUTES *pPortAttr=NULL; + IB_LMC lmc; + EUI64 CaGuid; + uint16 PkeyIndex = 0; + IB_P_KEY PartitionKey; + + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, iba_cm_sidr_query); + + // Parameter check + Status = ValidateCEPHandle(pCEP); + if (Status != FSUCCESS) + goto done; + + Status = iba_get_ca_for_port(pSIDRRequest->PortGuid, &CaGuid); + if (Status != FSUCCESS) + goto done; + + // do these lookups outside the lock + Status = iba_find_ca_gid(&pSIDRRequest->PathInfo.Path.SGID, + CaGuid, NULL, + &SrcGidIndex, &pPortAttr, NULL); + if (Status != FSUCCESS) + { + _DBG_WARN((" FindCaGid() failed!!! <%s>\n", + _DBG_PTR(pCEP), _DBG_PTR(FSTATUS_MSG(Status)))); + Status = FINVALID_PARAMETER; + goto done; + } + + // if Partition key not specified, use P_Key from Path + PartitionKey = pSIDRRequest->PartitionKey; + if (0 == PartitionKey) + { + PartitionKey = pSIDRRequest->PathInfo.Path.P_Key; + } + if (! LookupPKey(pPortAttr, PartitionKey, FALSE, &PkeyIndex)) + { + _DBG_WARN((" LookupPKey() failed!!!\n", _DBG_PTR(pCEP))); + Status = FINVALID_PARAMETER; + MemoryDeallocate(pPortAttr); + goto done; + } + lmc = pPortAttr->Address.LMC; + MemoryDeallocate(pPortAttr); + pPortAttr = NULL; + + SpinLockAcquire(&gCM->ListLock); + + // If CEP is being reused, it may have a send still in progress or it + // may not have a Dgrm any longer + if (pCEP->pDgrmElement && CmDgrmIsInUse(pCEP->pDgrmElement)) { + _DBG_INFO((" Releasing the dgrm .\n", + _DBG_PTR(pCEP), _DBG_PTR(pCEP->pDgrmElement))); + CmDgrmSetReleaseFlag(pCEP->pDgrmElement); + pCEP->pDgrmElement = NULL; + } + if (pCEP->pDgrmElement == NULL) + { + pCEP->pDgrmElement = CmDgrmGet(); + if (!pCEP->pDgrmElement) + { + _DBG_WARNING((" Unable to send SIDR_REQ: Out of CM Dgrms!!!\n", + _DBG_PTR(pCEP))); + Status = FINSUFFICIENT_RESOURCES; + goto unlock; + } + } + + // Dgrm could be in use if we failed a SIDRQuery due to a timeout + // but still did not have the send completion + if (pCEP->State != CMS_IDLE || CmDgrmIsInUse(pCEP->pDgrmElement)) + { + Status = FINVALID_STATE; + goto unlock; + } + + pCEP->Mode = CM_MODE_ACTIVE; + ASSERT(! pCEP->bPeer); + + // This is the request ID + AssignLocalCommID(pCEP); + pCEP->TransactionID = pCEP->LocalCommID << 8; + + pCEP->pfnUserCallback = pfnQueryCB; + pCEP->UserContext = Context; + + // Setup the dgrm's dest addr + CmDgrmAddrSet(pCEP->pDgrmElement, + pSIDRRequest->PortGuid, + pSIDRRequest->PathInfo.Path.DLID, + pSIDRRequest->PathInfo.Path.u2.s.SL, + LidToPathBits(pSIDRRequest->PathInfo.Path.SLID, lmc), + pSIDRRequest->PathInfo.Path.Rate, + (!pSIDRRequest->PathInfo.bSubnetLocal), + pSIDRRequest->PathInfo.Path.DGID, + pSIDRRequest->PathInfo.Path.u1.s.FlowLabel, + (uint8)SrcGidIndex, + (uint8)pSIDRRequest->PathInfo.Path.u1.s.HopLimit, + (uint8)pSIDRRequest->PathInfo.Path.TClass, + PkeyIndex); + + // Format the SIDR REQ + FormatSIDR_REQ((CM_MAD*)GsiDgrmGetSendMad(pCEP->pDgrmElement), + pSIDRRequest->SID, + PartitionKey, + pSIDRRequest->PrivateData, + CMM_SIDR_REQ_USER_LEN, + pCEP->TransactionID, + pCEP->LocalCommID); + + pCEP->RetryCount = 0; + pCEP->MaxCMRetries = gCmParams.MaxReqRetry; + + // Send the SIDR REQ + Status = CmDgrmSend(pCEP->pDgrmElement); + if (Status != FSUCCESS) + { + // fall through and let timer retry the send later + _DBG_WARN((" DgrmSend() failed for SIDR_REQ!!! <%s>\n", + _DBG_PTR(pCEP), _DBG_PTR(FSTATUS_MSG(Status)))); + Status = FSUCCESS; + } else { + AtomicIncrementVoid(&gCM->Sent.SidrReq); + } + + // Move from IDLE to QUERY + CM_MapInsert(&gCM->QueryMap, pCEP->LocalCommID, &pCEP->MapEntry, QUERY_LIST, pCEP); + CepSetState(pCEP, CMS_SIDR_REQ_SENT); + + pCEP->pfnUserCallback = pfnQueryCB; + pCEP->UserContext = Context; + + pCEP->Mtu = 0; // not used + pCEP->PartitionKey = 0; // not used + pCEP->TargetAckDelay = 0; // not used + pCEP->PrimaryPath.LocalLID = pSIDRRequest->PathInfo.Path.SLID; + pCEP->PrimaryPath.LocalGID = pSIDRRequest->PathInfo.Path.SGID; + + pCEP->PrimaryPath.RemoteLID = pSIDRRequest->PathInfo.Path.DLID; + pCEP->PrimaryPath.RemoteGID = pSIDRRequest->PathInfo.Path.DGID; + if (pSIDRRequest->PathInfo.Path.PktLifeTime > 31) + { + pCEP->PktLifeTime = 31; // 2.4 hours !!!!! + } else { + pCEP->PktLifeTime = pSIDRRequest->PathInfo.Path.PktLifeTime; + } + + // Start the query timer to time out this request if the response doesnt come in + CmTimerStart(pCEP, SidrTimeout(pCEP), SIDR_REQ_TIMER); + Status = FPENDING; + +unlock: + SpinLockRelease(&gCM->ListLock); +done: + _DBG_LEAVE_LVL(_DBG_LVL_FUNC_TRACE); + return Status; + +} // iba_cm_sidr_query() diff --git a/IbAccess/Common/Ibt/Gsa/README b/IbAccess/Common/Ibt/Gsa/README new file mode 100644 index 0000000..f1ee2fe --- /dev/null +++ b/IbAccess/Common/Ibt/Gsa/README @@ -0,0 +1 @@ +Gsi multiplexor for QP1 Agents/Managers diff --git a/IbAccess/Common/Ibt/Gsa/gsacallb.c b/IbAccess/Common/Ibt/Gsa/gsacallb.c new file mode 100644 index 0000000..a399305 --- /dev/null +++ b/IbAccess/Common/Ibt/Gsa/gsacallb.c @@ -0,0 +1,639 @@ +/* BEGIN_ICS_COPYRIGHT4 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT4 ****************************************/ + + +#include "gsamain.h" + +#ifdef SA_ALLOC_DEBUG +extern IB_HANDLE sa_poolhandle; +#endif + +static __inline void +RemoveClientIdFromTID( + IN MAD_COMMON *pMadHdr + ) +{ + if (MAD_IS_RESPONSE((MAD*)pMadHdr)) + { + pMadHdr->TransactionID = (uint64)(pMadHdr->TransactionID + & 0xffffffffffffff00ll); + } +} + +// called in a thread context (GsaEventThread), so can preempt +void +GsaCompletionThreadCallback( + IN void *CaContext + ) +{ + SMA_CA_OBJ_PRIVATE *pCaObj = (SMA_CA_OBJ_PRIVATE *)CaContext; + + GsaCompletionCallback( CaContext, pCaObj->Qp1CqHandle ); +} + +// called in a thread context, so can preempt +void +GsaCompletionCallback( + IN void *CaContext, + IN IB_HANDLE CqHandle + ) +{ + FSTATUS status; + + IBT_DGRM_ELEMENT *pDgrm = NULL; + boolean bRearmed = FALSE; + + IBT_DGRM_ELEMENT_PRIV *pDgrmPrivate; + GSA_POST_SEND_LIST *pPostList; + MAD_COMMON *pMadHdr; + GSA_SERVICE_CLASS_INFO *classInfo; + IB_WORK_COMPLETION workCompletion; + uint8 clientId; + uint64 portGuid; + + _DBG_ENTER_LVL(_DBG_LVL_CALLBACK, GsaCompletionCallback); + // + // Processing completions on the CQ is done as follows: + // 1. Repeatedly Poll till all entries are done. + // 2. Rearm CQ and Poll again. If there are no more completions bail out. + // 3. If there are completions go back to step 1. + // 4. Skip step 2 and loop through 3. + // + // We follow these steps to optimize on hardware events and race + // conditions. + // + + while (1) + { +#ifdef SA_ALLOC_DEBUG + if (iba_gsi_dgrm_pool_count(sa_poolhandle) < 50) MsgOut("GSA Callback\n"); +#endif + // + // Loop and pull out all sends and receives + // + while ( FSUCCESS == (status = iba_poll_cq( CqHandle, &workCompletion )) ) + { + // fill in common values + pDgrm = (IBT_DGRM_ELEMENT *)((uintn)MASK_WORKREQID(workCompletion.WorkReqId)); + + // This should never happen. test for bad hardware + ASSERT ( pDgrm ); + if ( NULL == pDgrm ) + { + // + // This is for debug only. We should remove this conditional + // once the problem is debugged + // + _DBG_ERROR (("Spurious CQ Event!!!\n" + "\tCompleted WQE.....:(%s)\n" + "\tSTATUS............:x%x\n" + "\tLength............:x%x\n", + _DBG_PTR(((WCTypeSend == workCompletion.WcType) ? \ + "Send":"Recv")), + workCompletion.Status, + workCompletion.Length)); + + if ( WCTypeRecv == workCompletion.WcType ) + { + _DBG_ERROR (("\n" + "\tQP Number.........:x%x\n" + "\tSourceLID.........:x%x\n", + workCompletion.Req.RecvUD.SrcQPNumber, + workCompletion.Req.RecvUD.SrcLID)); + } + + _DBG_BREAK; + break; + } + + // process work completion + pDgrm->Element.Status = workCompletion.Status; + pDgrmPrivate = (IBT_DGRM_ELEMENT_PRIV *)pDgrm; + + _DBG_PRINT (_DBG_LVL_CALLBACK,( + "Completed %s WQE (%p):\n" + "\tSTATUS.......:x%X (%s)\n", + _DBG_PTR(((WCTypeSend == workCompletion.WcType) ? "Send":"Recv")), + _DBG_PTR(pDgrm), + workCompletion.Status, + _DBG_PTR(iba_wc_status_msg(workCompletion.Status)) )); + + if (IS_SQ_WORKREQID(workCompletion.WorkReqId)) + { +#ifdef SA_ALLOC_DEBUG + if (iba_gsi_dgrm_pool_count(sa_poolhandle) < 50) MsgOut("GSA Send Compl\n"); +#endif + + if (! pDgrm->Allocated) { + _DBG_ERROR(("GSI ERROR: Send Completion for non-allocated Dgrm, discard: pDgrm=%p completion type=%d OnrecvQ=%d\n", _DBG_PTR(pDgrm), workCompletion.WcType, pDgrm->OnRecvQ)); + if (Gsa_debug_params.debug_level & _DBG_LVL_STORE) + { + ASSERT(pDgrm->Allocated); + } + DEBUG_ASSERT(pDgrm->Allocated); + continue; + } + if (pDgrm->OnRecvQ) { + _DBG_ERROR(("GSI ERROR: Send Completion for Recv Q Dgrm, discard: pDgrm=%p completion type=%d\n", _DBG_PTR(pDgrm), workCompletion.WcType)); + if (Gsa_debug_params.debug_level & _DBG_LVL_STORE) + { + ASSERT(! pDgrm->OnRecvQ); + } + DEBUG_ASSERT(! pDgrm->OnRecvQ); + continue; + } + if (! pDgrm->OnSendQ) { + _DBG_ERROR(("GSI ERROR: Send Completion for non-OnSendQ Dgrm, discard: pDgrm=%p completion type=%d allocated=%d\n", _DBG_PTR(pDgrm), workCompletion.WcType, pDgrm->Allocated)); + if (Gsa_debug_params.debug_level & _DBG_LVL_STORE) + { + ASSERT(pDgrm->OnSendQ); + } + DEBUG_ASSERT(pDgrm->OnSendQ); + continue; + } + pDgrm->OnSendQ = FALSE; + + + // Handle common send completion. Only for SendInvalid + // will a Recv Pool Dgrm be used, we get correct pMadHdr + // mainly so log messages below are correct + if (((IBT_DGRM_ELEMENT_PRIV *)pDgrm)->MemPoolHandle->ReceivePool ) + pMadHdr = (MAD_COMMON *)GsiDgrmGetRecvMad(pDgrm); + else + pMadHdr = (MAD_COMMON *)GsiDgrmGetSendMad(pDgrm); + + BSWAP_MAD_HEADER ((MAD*)pMadHdr); + + pPostList = pDgrmPrivate->Base; + AtomicIncrementVoid( &pPostList->DgrmOut); + +#ifdef ICS_LOGGING + _DBG_PRINT (_DBG_LVL_CALLBACK,( + "Send Info:\n" + "\tClass........:x%x\n" + "\tResponseBit..:x%x\n" + "\tTID..........:x%"PRIx64"\n" + "Local\n" + "\tPathBits.....:x%X\n" + "Remote:\n" + "\tLID..........:x%X\n" + "\tQP...........:x%X\n", + (uint8)pMadHdr->MgmtClass, + pMadHdr->mr.s.R, + pMadHdr->TransactionID, + pDgrmPrivate->DgrmElement.PathBits, + pDgrmPrivate->DgrmElement.RemoteLID, + pDgrmPrivate->DgrmElement.RemoteQP + )); + + _DBG_PRINT (_DBG_LVL_CALLBACK,( + "Send Info:\n" + "\tClass........:x%x\n" + "\tResponseBit..:x%x\n" + "\tTID..........:x%"PRIx64"\n" + "Local\n" + "\tQKey.........:x%X\n" + "\tServiceLvl...:x%X\n" + "\tGlobalRoute..:%s\n", + (uint8)pMadHdr->MgmtClass, + pMadHdr->mr.s.R, + pMadHdr->TransactionID, + pDgrmPrivate->DgrmElement.RemoteQKey, + pDgrmPrivate->DgrmElement.ServiceLevel, + _DBG_PTR((pDgrmPrivate->DgrmElement.GlobalRoute ? "TRUE":"FALSE") ) + )); + +#else + _DBG_PRINT (_DBG_LVL_CALLBACK,( + "Send Info:\n" + "\tClass........:x%x\n" + "\tResponseBit..:x%x\n" + "\tTID..........:x%"PRIx64"\n" + "Local\n" + "\tPathBits.....:x%X\n" + "Remote:\n" + "\tLID..........:x%X\n" + "\tQP...........:x%X\n" + "\tQKey.........:x%X\n" + "\tServiceLvl...:x%X\n" + "\tRate.........:x%d\n" + "\tGlobalRoute..:%s\n", + (uint8)pMadHdr->MgmtClass, + pMadHdr->mr.s.R, + pMadHdr->TransactionID, + pDgrmPrivate->DgrmElement.PathBits, + pDgrmPrivate->DgrmElement.RemoteLID, + pDgrmPrivate->DgrmElement.RemoteQP, + pDgrmPrivate->DgrmElement.RemoteQKey, + pDgrmPrivate->DgrmElement.ServiceLevel, + pDgrmPrivate->DgrmElement.StaticRate, + (pDgrmPrivate->DgrmElement.GlobalRoute ? "TRUE":"FALSE") + )); + +#endif + // Send completion for Send initiated by RMPP protocol + if( pPostList->SARRequest) + { +#ifdef SA_ALLOC_DEBUG + if (iba_gsi_dgrm_pool_count(sa_poolhandle) < 50) MsgOut("GSA Send Compl: SAR\n"); +#endif + // send was posted by RMPP protocol handler + // let it process the completion + ProcessSARSendCompletion((MAD*)pMadHdr, pDgrm); + continue; + } + + // The datagram has been successfully sent. Reset the + // transaction ID to that specified by the user if this is + // not a response. Responses use the transaction ID from + // the original request. + if (MAD_IS_REQUEST((MAD*)pMadHdr)) + { + // Restore the original TID from the user. We cannot + // use the context manager here, since we may have already + // completed the request. (The associated receive may + // be processed before the send is completed.) + pMadHdr->TransactionID = pDgrmPrivate->SavedSendTid; + } + + // Free resources + ASSERT ( pDgrmPrivate->AvHandle ); + status = PutAV( NULL, pDgrmPrivate->AvHandle ); + classInfo = (GSA_SERVICE_CLASS_INFO*)pDgrmPrivate->MemPoolHandle->ServiceHandle; + if ( NULL == classInfo ) + { + // no associated class, must be a GSI initiated MAD + DEBUG_ASSERT(pPostList->DgrmIn == AtomicRead(&pPostList->DgrmOut)); + status = DgrmPoolPut( pPostList->DgrmList ); + continue; + } + + // Match all sends before callback + if ( pPostList->DgrmIn != AtomicRead(&pPostList->DgrmOut) ) + { +#ifdef SA_ALLOC_DEBUG + if (iba_gsi_dgrm_pool_count(sa_poolhandle) < 50) MsgOut("GSA Send Compl: more to do\n"); +#endif + _DBG_PRINT (_DBG_LVL_CALLBACK,( + "All sends not completed in send list:\n" + "\tTotal.....:%d\n" + "\tDone......:%d\n", + pPostList->DgrmIn, + AtomicRead(&pPostList->DgrmOut) )); + + continue; + } + + // Call user's send completion +#ifdef SA_ALLOC_DEBUG + if (iba_gsi_dgrm_pool_count(sa_poolhandle) < 50) MsgOut("GSA Send Compl: class callback: %p\n", classInfo->SendCompletionCallback); +#endif + if ( classInfo->SendCompletionCallback ) + { + (classInfo->SendCompletionCallback)( + classInfo->ServiceClassContext, + pPostList->DgrmList ); + } else { + status = DgrmPoolPut( pPostList->DgrmList ); + } // Class Callback + } else { + // Receive Completion processing + uint32 post_count; + IBT_BUFFER *Current = NULL; + uint32 Length = 0; +#ifdef SA_ALLOC_DEBUG + if (iba_gsi_dgrm_pool_count(sa_poolhandle) < 50) MsgOut("GSA Recv Compl\n"); +#endif + if (pDgrm->OnSendQ) { + _DBG_ERROR(("GSI ERROR: Recv Completion for Send Q Dgrm, discard: pDgrm=%p completion type=%d\n", _DBG_PTR(pDgrm), workCompletion.WcType)); + if (Gsa_debug_params.debug_level & _DBG_LVL_STORE) + { + ASSERT(! pDgrm->OnSendQ); + } + DEBUG_ASSERT(! pDgrm->OnSendQ); + continue; + } + if (! pDgrm->OnRecvQ) { + _DBG_ERROR(("GSI ERROR: Recv Completion for non-OnRecvQ Dgrm, discard: pDgrm=%p completion type=%d allocated=%d\n", _DBG_PTR(pDgrm), workCompletion.WcType, pDgrm->Allocated)); + if (Gsa_debug_params.debug_level & _DBG_LVL_STORE) + { + ASSERT(pDgrm->OnRecvQ); + } + DEBUG_ASSERT(pDgrm->OnRecvQ); + continue; + } + + if (! pDgrm->Allocated) { + _DBG_ERROR(("GSI ERROR: Completion for non-allocated Dgrm, discard: pDgrm=%p completion type=%d\n", _DBG_PTR(pDgrm), workCompletion.WcType)); + if (Gsa_debug_params.debug_level & _DBG_LVL_STORE) + { + ASSERT(pDgrm->Allocated); + } + DEBUG_ASSERT(pDgrm->Allocated); + pDgrm->OnRecvQ = FALSE; + continue; + } + pDgrm->OnRecvQ = FALSE; + + + status = DecrementGsiRecvQPostedForPortGuid( + pDgrm->PortGuid, &post_count); + _DBG_PRINT (_DBG_LVL_CALLBACK,("0x%"PRIx64": got post count of %u: %d\n",pDgrm->PortGuid, post_count, status)); + if (FSUCCESS == status + && post_count < g_GsaSettings.MinBuffersToPostPerPort + ) + { + // replenish to desired min + post_count = g_GsaSettings.MinBuffersToPostPerPort - post_count; + } else { + // can't be sure, just repost 1 + post_count = 1; + } + _DBG_PRINT (_DBG_LVL_CALLBACK,("computed post count of %u\n", post_count)); + + // Do not callback for QpFlush + if ( WRStatusWRFlushed == workCompletion.Status ) + { +#ifdef SA_ALLOC_DEBUG + if (iba_gsi_dgrm_pool_count(sa_poolhandle) < 50) MsgOut("GSA Recv Compl: Flush\n"); +#endif + _DBG_PRINT (_DBG_LVL_CALLBACK,("WRFlushed: skip users.\n")); + status = DgrmPoolPut( pDgrm ); + continue; + } + /* MADs can be of variable length */ + if ( workCompletion.Length > (sizeof(IB_GRH) + sizeof(MAD))) + { + _DBG_ERROR (( + "Invalid MAD receive length (%d bytes)! \n", + workCompletion.Length )); + status = DgrmPoolPut( pDgrm ); + continue; + } + // Overload base with SAR field + pDgrmPrivate->Base = 0; // not a SAR Receive Dgrm + + // Fill in bytes rcvd + pDgrm->TotalRecvSize = workCompletion.Length; + pDgrm->Element.RecvByteCount = workCompletion.Length; + + // Save GUID for a post since the user may FPENDING the Dgrm + portGuid = pDgrm->PortGuid; + + // GRH is first buffer, MAD is second + pDgrm->Element.pBufferList->ByteCount = sizeof(IB_GRH); + + Current = pDgrm->Element.pBufferList->pNextBuffer; + Length = workCompletion.Length - sizeof(IB_GRH); + + pMadHdr = (MAD_COMMON *)GsiDgrmGetRecvMad(pDgrm); + + while (Length && Current) + { + Current->ByteCount = (pMadHdr->BaseVersion == IB_BASE_VERSION) + ? MIN(Length, IB_MAD_BLOCK_SIZE) + : MIN(Length, STL_MAD_BLOCK_SIZE); + + if (__DBG_LEVEL__ & _DBG_LVL_PKTDUMP) + { + _DBG_DUMP_MEMORY(_DBG_LVL_PKTDUMP, ("Recv GSI MAD Packet"), + Current->pData, + MIN(Current->ByteCount, Length)); + } + + Length -= Current->ByteCount; + Current = Current->pNextBuffer; + } + + BSWAP_MAD_HEADER ((MAD*)pMadHdr); +#ifdef ICS_LOGGING + _DBG_PRINT (_DBG_LVL_CALLBACK,( + "Receive Info:\n" + "\tClass........:x%x\n" + "\tResponseBit..:x%x\n" + "\tTID..........:x%"PRIx64"\n" + "Local\n" + "\tPathBits.....:x%X\n" + "Remote:\n" + "\tLID..........:x%X\n" + "\tQP...........:x%X\n", + (uint8)pMadHdr->MgmtClass, + pMadHdr->mr.s.R, + pMadHdr->TransactionID, + workCompletion.Req.RecvUD.DestPathBits, + workCompletion.Req.RecvUD.SrcLID, + workCompletion.Req.RecvUD.SrcQPNumber + )); + _DBG_PRINT (_DBG_LVL_CALLBACK,( + "Receive Info:\n" + "\tClass........:x%x\n" + "\tResponseBit..:x%x\n" + "\tTID..........:x%"PRIx64"\n" + "Remote:\n" + "\tPKeyIndex....:x%X\n" + "\tServiceLvl...:x%X\n" + "\tGlobalRoute..:%s\n", + (uint8)pMadHdr->MgmtClass, + pMadHdr->mr.s.R, + pMadHdr->TransactionID, + workCompletion.Req.RecvUD.PkeyIndex, + workCompletion.Req.RecvUD.ServiceLevel, + _DBG_PTR((workCompletion.Req.RecvUD.Flags.s.GlobalRoute ? "TRUE":"FALSE")) + )); + +#else + _DBG_PRINT (_DBG_LVL_CALLBACK,( + "Receive Info:\n" + "\tClass........:x%x\n" + "\tResponseBit..:x%x\n" + "\tTID..........:x%"PRIx64"\n" + "Local\n" + "\tPathBits.....:x%X\n" + "Remote:\n" + "\tLID..........:x%X\n" + "\tQP...........:x%X\n" + "\tPKeyIndex....:x%X\n" + "\tServiceLvl...:x%X\n" + "\tGlobalRoute..:%s\n", + (uint8)pMadHdr->MgmtClass, + pMadHdr->mr.s.R, + pMadHdr->TransactionID, + workCompletion.Req.RecvUD.DestPathBits, + workCompletion.Req.RecvUD.SrcLID, + workCompletion.Req.RecvUD.SrcQPNumber, + workCompletion.Req.RecvUD.PkeyIndex, + workCompletion.Req.RecvUD.ServiceLevel, + (workCompletion.Req.RecvUD.Flags.s.GlobalRoute ? "TRUE":"FALSE") + )); + +#endif + // Port Number and Q pair are filled-up during + // Gsa's PostRecv + pDgrm->PathBits = workCompletion.Req.RecvUD.DestPathBits; + pDgrm->RemoteLID = workCompletion.Req.RecvUD.SrcLID; + pDgrm->RemoteQP = workCompletion.Req.RecvUD.SrcQPNumber; + pDgrm->RemoteQKey = QP1_WELL_KNOWN_Q_KEY; + pDgrm->PkeyIndex = workCompletion.Req.RecvUD.PkeyIndex; + pDgrm->ServiceLevel = workCompletion.Req.RecvUD.ServiceLevel; + // IB does not have Static rate in UD LRH + // so we can't be sure what rate of remote port is + // we use a constant value for GSI QPs + pDgrm->StaticRate = IB_STATIC_RATE_GSI; + pDgrm->GlobalRoute = workCompletion.Req.RecvUD.Flags.s.GlobalRoute; + + if (workCompletion.Req.RecvUD.Flags.s.GlobalRoute) + { + IB_GRH *pGrh = GsiDgrmGetRecvGrh(pDgrm); + BSWAP_IB_GRH ( pGrh); + pDgrm->GRHInfo.DestGID = pGrh->SGID; + pDgrm->GRHInfo.FlowLabel = pGrh->u1.s.FlowLabel; + pDgrm->GRHInfo.SrcGIDIndex = 0; // BUGBUG - lookup DGID + pDgrm->GRHInfo.HopLimit = pGrh->HopLimit; + pDgrm->GRHInfo.TrafficClass = pGrh->u1.s.TClass; + + _DBG_PRINT (_DBG_LVL_CALLBACK,( + "GRH Info:\n" + "\tDGID.........:x%"PRIx64":%"PRIx64"\n" + "\tSGID.........:x%"PRIx64":%"PRIx64"\n" + "\tPayload......:%d bytes\n", + pGrh->DGID.Type.Global.SubnetPrefix, + pGrh->DGID.Type.Global.InterfaceID, + pGrh->SGID.Type.Global.SubnetPrefix, + pGrh->SGID.Type.Global.InterfaceID, + pGrh->PayLen )); + } + + // + //TBD: + // Chain replies to process later + // + //pDgrm->pNextCompDgrm + + // For RMPP R bit be set in all packets which compose a response + // message Even ABORT, STOP, etc. + // transaction ID will be consistent in all packets for + // a given request/respone message pair. + // R bit be 0 in all packets which compose a request message + // event ACK, ABORT, STOP, etc + + // See if the received MAD was in response to a previously + // sent MAD request. + if (MAD_IS_RESPONSE((MAD*)pMadHdr)) + { + // Response to clients. client id was a field + // in the transaction ID sent on wire + clientId = (uint8)(pMadHdr->TransactionID & 0xff); + } else { + // This is a new request or not a request/response pair + // TID unmodified TID is visible to client (for a request + // TID was remotely generated and we can't modify) + clientId = MAX_CLIENT_ID; + status = FSUCCESS; + } + + // Validate Attributes to be processed + if( status == FSUCCESS ) + { + // Does the Client want us to do RMPP protocol for it? + if( IsSarClient( clientId, pMadHdr->MgmtClass ) ) + { + // Process the segment. If all segments have been + // received, pDgrm will be updated to point to the + // first segment. + status = ProcessSARRecvCompletion((MAD*)pMadHdr,&pDgrm); + if( status == FCOMPLETED ) + { + // remove clientid from all TIDs before give to user + IBT_ELEMENT *pElement; + for (pElement = &pDgrm->Element; pElement != NULL; pElement = pElement->pNextElement) + { + // first buffer is GRH, 2nd is start of MAD + RemoveClientIdFromTID( + (MAD_COMMON *) + pElement->pBufferList->pNextBuffer->pData); + } + + // adjust pMadHdr to be first in list of Dgrms, + // pDgrm could have been changed by SAR processing + pMadHdr = (MAD_COMMON *)GsiDgrmGetRecvMad(pDgrm); + } + } else { + // No SAR is needed. + + // remove clientid from TID before give to user + RemoveClientIdFromTID(pMadHdr); + status = FCOMPLETED; + } + + // Notify the user of fully received MADs. + if( status == FCOMPLETED ) + { + status = GsaNotifyClients( clientId, pMadHdr, pDgrm ); + } + + if (status == FNOT_FOUND) + { + // no client found + if (MAD_EXPECT_GET_RESP((MAD*)pMadHdr)) + { + // reply with a bad class version response + GsiSendInvalid(pDgrm); + } + status = FREJECT; // free dgrm below + } + // Free the datagram(s) if not required for SAR and not + // being used by the client. + if( status == FCOMPLETED || status == FREJECT ) + { + DgrmPoolPut( pDgrm ); + } + } + + // Post back a recv to Q + status = PostRecvMsgToPort( post_count, portGuid ); + } // recv + } // while loop + + if ( FNOT_DONE != status ) + { + _DBG_ERROR (("Got %s Status!!!\n", _DBG_PTR(FSTATUS_MSG(status)) )); + } + + // Rearm CQ for race conditions + if ( FALSE == bRearmed ) + { + status = iba_rearm_cq( CqHandle, CQEventSelNextWC ); + bRearmed = TRUE; + } else { + break; + } + } // while 1 + + _DBG_LEAVE_LVL(_DBG_LVL_CALLBACK); +} diff --git a/IbAccess/Common/Ibt/Gsa/gsaclass.c b/IbAccess/Common/Ibt/Gsa/gsaclass.c new file mode 100644 index 0000000..190f5be --- /dev/null +++ b/IbAccess/Common/Ibt/Gsa/gsaclass.c @@ -0,0 +1,598 @@ +/* BEGIN_ICS_COPYRIGHT4 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT4 ****************************************/ + +#include "gsamain.h" + + +// Manage list of Registered Gsa Class Clients/Managers + +// +// Function prototype. +// +boolean +FindMatchingClassMgr( + IN LIST_ITEM *pListItem, + IN void *Context ); + +FSTATUS +GetClientId( + IN OUT uint8 *pClientId + ); + +void +PutClientId( + IN uint8 ClientId + ); + + +// +// GsiRegisterClass +// +// GsiRegisterClass registers a management class with GSI. +// A class is identified by a unique id, a version. The class owner +// can also register a callback that can be used to indicate +// incoming packets targeted for this class and a callback to +// indicate post send completions. +// +// +// This function registers an agent defined by a management class. Any number +// of agents can register using the same management class. In addition, +// only one agent at the most may register as a class manager for the class +// by indicating Server in Flags. +// +// +// +// +// INPUTS: +// +// MgmtClass - Management class to be registered +// An 8-bit value indicating the management class. +// In debug mode, this value has to match one of the known +// values, else we print out an error and then return an +// error code. +// In release mode, we do not check these values. +// This is only to ensure that well-known agents +// register with us. +// +// MgmtClassVersion- Will be 1 for this version. +// +// Flags - Indicates if Server or client. If a server is already +// registered, this call will fail. +// If TRUE, indicates the registering agent is a class +// manager. When this is set to TRUE, +// +// GSI checks to see that there is no existing class manager +// for this class. If there is no existing class manager, +// this function proceeds else returns failure. +// +// +// - Indicates if client wishes to get unsolicited messages +// +// SARClient - TRUE indicates client needs SAR capability. +// +// ServiceContext - Caller defined context passed back in callbacks. +// +// SendCompletionCallback- Callback for all datagrams completions posted +// in send. +// +// ReceiveCallback - Callback for all datagrams received. +// +// +// +// OUTPUTS: +// +// ServiceHandle - Client unique handle returned to caller on successful +// registration. +// +// +// +// RETURNS: +// +// FSUCCESS +// FINVALID_PARAMETER +// FINSUFFICIENT_RESOURCES +// +// +FSTATUS +iba_gsi_register_class( + IN uint8 MgmtClass, + IN uint8 MgmtClassVersion, + IN GSI_REGISTRATION_FLAGS RegistrationFlags, + IN boolean SARClient, + IN void *ServiceContext, + IN GSI_SEND_COMPLETION_CALLBACK *SendCompletionCallback, + IN GSI_RECEIVE_CALLBACK *ReceiveCallback, + OUT IB_HANDLE *ServiceHandle + ) +{ + FSTATUS status; + GSA_SERVICE_CLASS_INFO *newclass = NULL; + + _DBG_ENTER_LVL (_DBG_LVL_CLASS, iba_gsi_register_class); + + // + // Grab registration lock. This is a lock that is global to the whole + // of GSI and guards the registered class table or list. + + // Allocate a class registration element. This element contains the + // following. + // + // Link element to link into a linked list. + // + // list of registered send buffers for this client. + // + // At any time, this list includes all the buffers that have been posted + // ( either during or during ) but not yet been + // processed. A buffer is considered processed once the CA to which the + // buffer has been posted is used for sending data and indicated back to + // the entity posting the buffer. + // + // list of registered receive buffers for this client. + // GSI provides facilities to allocate memory on behalf of a client and + // post WQE mapping that memory to a CA's QP1. In reality, the service + // agent ( "client" ) does not own this memory. The client only + // informs GSI to allocate some memory of certain length. This is useful + // when the client knows it is about to receive data and wants to ensure + // that enough buffers have been posted to receive data. + // There is no guarantee that these buffers are used to receive the data + // meant for a client. It is possible that data for another client was + // received in these buffers . Under these conditions, it is possible + // for the original client to lose the data since there was not enough + // buffer space. Since GSI is just providing access to QP1 + // ( for a given port on a given CA ), it is not possible for GSI to + // properly know the traffic patterns and actively post buffers. + // + // Client's context for this registration + // ( the "ServiceAgentContext" parameter ). + // Client's send completion and receive callbacks. + // + + + newclass = (GSA_SERVICE_CLASS_INFO*)MemoryAllocateAndClear(sizeof(GSA_SERVICE_CLASS_INFO), FALSE, GSA_MEM_TAG); + if ( NULL == newclass ) + { + status = FINSUFFICIENT_RESOURCES; + _DBG_ERROR (("FINSUFFICIENT_RESOURCES\n")); + } + else + { + status = FSUCCESS; + + newclass->MgmtClass = MgmtClass; + newclass->MgmtClassVersion = MgmtClassVersion; + newclass->RegistrationFlags = RegistrationFlags; + newclass->bSARRequired = SARClient; + + newclass->ServiceClassContext = ServiceContext; + newclass->ReceiveCompletionCallback = ReceiveCallback; + newclass->SendCompletionCallback = SendCompletionCallback; + + newclass->pGlobalInfo = g_GsaGlobalInfo; + +#if defined(DBG) || defined(IB_DEBUG) + newclass->SigInfo = GSA_CLASS_SIG; +#endif + // + // Insert this class onto the global list of service classes + // + SpinLockAcquire( &g_GsaGlobalInfo->ServiceClassListLock ); + + if (FSUCCESS != GetClientId( &newclass->ClientId )) + { + SpinLockRelease( &g_GsaGlobalInfo->ServiceClassListLock ); + MemoryDeallocate( newclass ); + + status = FINSUFFICIENT_RESOURCES; + _DBG_ERROR (("FINSUFFICIENT_RESOURCES\n")); + } + else + { + QListInsertHead( &g_GsaGlobalInfo->ServiceClassList, + &newclass->ListItem ); + SpinLockRelease( &g_GsaGlobalInfo->ServiceClassListLock ); + + _DBG_PRINT (_DBG_LVL_CLASS,( + "Registered Info...:\n" + "\tClass...........:x%x\n" + "\tClientID........:x%x\n" + "\tClassContext....:x%p\n" + "\tSAR capable.....:%s\n", + newclass->MgmtClass, + newclass->ClientId, + _DBG_PTR(newclass->ServiceClassContext), + _DBG_PTR(newclass->bSARRequired ? "TRUE":"FALSE" ))); + + _DBG_PRINT (_DBG_LVL_CLASS,( + "\tResponder.......:%s\n" + "\tTrapProcessor...:%s\n" + "\tReportProcessor.:%s\n", + _DBG_PTR(GSI_IS_RESPONDER(newclass->RegistrationFlags) + ? "TRUE":"FALSE"), + _DBG_PTR(GSI_IS_TRAP_PROCESSOR(newclass->RegistrationFlags) + ? "TRUE":"FALSE"), + _DBG_PTR(GSI_IS_REPORT_PROCESSOR(newclass->RegistrationFlags) + ? "TRUE":"FALSE"))); + + // + // Set capabilities in PortInfo through SMA. Enable class + // management support if not already enabled. + // + if( GSI_IS_RESPONDER(newclass->RegistrationFlags) ) + SetPortCapabilityMask( newclass->MgmtClass, TRUE ); + + *ServiceHandle = ( IB_HANDLE )newclass; + } + } + + _DBG_LEAVE_LVL (_DBG_LVL_CLASS); + return status; +} + + + + +// +// GsiDeregisterClass +// +// +// +// INPUTS: +// +// ServiceHandle - Handle returned upon a successful registration. +// +// +// +// OUTPUTS: +// +// None +// +// +// +// RETURNS: +// +// FSUCCESS +// FINVALID_PARAMETER +// FINSUFFICIENT_RESOURCES +// +// +FSTATUS +iba_gsi_deregister_class( + IN IB_HANDLE ServiceHandle + ) +{ + GSA_SERVICE_CLASS_INFO *pClassInfo; + LIST_ITEM *pListItem; + + _DBG_ENTER_LVL (_DBG_LVL_CLASS, iba_gsi_deregister_class); + + pClassInfo = (GSA_SERVICE_CLASS_INFO*)ServiceHandle; + ASSERT( pClassInfo ); + + _DBG_PRINT (_DBG_LVL_CLASS,( + "Registered Info...:\n" + "\tClass...........:x%x\n" + "\tClientID........:x%x\n" + "\tClassContext....:x%p\n" + "\tSAR capable.....:%s\n", + pClassInfo->MgmtClass, + pClassInfo->ClientId, + _DBG_PTR(pClassInfo->ServiceClassContext), + _DBG_PTR(pClassInfo->bSARRequired ? "TRUE":"FALSE") )); + + _DBG_PRINT (_DBG_LVL_CLASS,( + "\tResponder.......:%s\n" + "\tTrapProcessor...:%s\n" + "\tReportProcessor.:%s\n", + _DBG_PTR(GSI_IS_RESPONDER(pClassInfo->RegistrationFlags) + ? "TRUE":"FALSE"), + _DBG_PTR(GSI_IS_TRAP_PROCESSOR(pClassInfo->RegistrationFlags) + ? "TRUE":"FALSE"), + _DBG_PTR(GSI_IS_REPORT_PROCESSOR(pClassInfo->RegistrationFlags) + ? "TRUE":"FALSE"))); + +#if defined(DBG) || defined(IB_DEBUG) + if (pClassInfo->SigInfo != GSA_CLASS_SIG) + { + _DBG_ERROR (("Bad handle passed!\n")); + ASSERT(0); + } +#endif + + // Remove this class from the global list of service classes + SpinLockAcquire( &g_GsaGlobalInfo->ServiceClassListLock ); + + ASSERT( QListIsItemInList( &g_GsaGlobalInfo->ServiceClassList, + &pClassInfo->ListItem ) ); + QListRemoveItem( &g_GsaGlobalInfo->ServiceClassList, + &pClassInfo->ListItem ); + + PutClientId (pClassInfo->ClientId); + + SpinLockRelease( &g_GsaGlobalInfo->ServiceClassListLock ); + + // If this client was the last manager for this class, disable the + // port attributes for it. + if( GSI_IS_RESPONDER(pClassInfo->RegistrationFlags)) + { + // Client was a class manager. See if there is another one. + SpinLockAcquire( &g_GsaGlobalInfo->ServiceClassListLock ); + + pListItem = QListFindFromHead( &g_GsaGlobalInfo->ServiceClassList, + FindMatchingClassMgr, (void*)(uintn)pClassInfo->MgmtClass ); + + SpinLockRelease(&g_GsaGlobalInfo->ServiceClassListLock); + + // If we didn't find another class manager, disable the class on + // the port attributes. + if( !pListItem ) + SetPortCapabilityMask( pClassInfo->MgmtClass, FALSE ); + } + +#if defined(DBG) || defined(IB_DEBUG) + pClassInfo->SigInfo = 0; +#endif + + MemoryDeallocate( pClassInfo ); + + _DBG_LEAVE_LVL (_DBG_LVL_CLASS); + return FSUCCESS; +} + + + +// +// Return TRUE if the class information specified by pListItem is a class +// manager for the class specified by Context. +// +boolean +FindMatchingClassMgr( + IN LIST_ITEM *pListItem, + IN void *Context ) +{ + GSA_SERVICE_CLASS_INFO *pClassInfo; + + pClassInfo = (GSA_SERVICE_CLASS_INFO*)pListItem; + // we cast the generic void* supplied by the list search routines into + // the IBTA GSA Class Number + return( GSI_IS_RESPONDER(pClassInfo->RegistrationFlags) && + (pClassInfo->MgmtClass == (uint8)(uintn)Context) ); +} + +// +// Return FSUCCESS if an ID is found in list +// +FSTATUS +GetClientId( + IN OUT uint8 *pClientId + ) +{ + FSTATUS status = FERROR; + uint8 *pIdList = &g_GsaGlobalInfo->ClientIdArray[0]; + uint8 i; + + for ( i=0; iClientIdArray[0]; + + pIdList[ClientId]=0; +} + +// +// Return TRUE if the ClientId/MgmtClass wants GSI do to RMPP SAR +// ClientId - for inbound request packets, should be MAX_CLIENT_ID +// in which case if any manager has requested GSI to do SAR we return TRUE +// - for inbound response packets, should be client ID field out of TID +// in which case we look at the specific registration of the client +// +boolean +IsSarClient( + IN uint8 ClientId, + IN uint8 MgmtClass ) +{ + GSA_SERVICE_CLASS_INFO *pClassInfo; + LIST_ITEM *pListNext; + boolean bSARRequired = FALSE; + + _DBG_ENTER_LVL( _DBG_LVL_CALLBACK, GsaClientNeedsSAR ); + + SpinLockAcquire( &g_GsaGlobalInfo->ServiceClassListLock ); + + for( pListNext = QListHead( &g_GsaGlobalInfo->ServiceClassList ); + NULL != pListNext; + pListNext = QListNext( &g_GsaGlobalInfo->ServiceClassList, pListNext) ) + { + pClassInfo = PARENT_STRUCT( pListNext, + GSA_SERVICE_CLASS_INFO, ListItem ); + if (ClientId != MAX_CLIENT_ID) + { + // See if initiating client has requested GSI to do SAR + if( pClassInfo->ClientId == ClientId ) + { + bSARRequired = pClassInfo->bSARRequired; + break; + } + } else { + // See if class manager has requested GSI to do SAR + if ((MgmtClass == pClassInfo->MgmtClass) && + (GSI_IS_RESPONDER(pClassInfo->RegistrationFlags) && + pClassInfo->bSARRequired)) + { + bSARRequired = TRUE; + break; + } + } + } // class for loop + + SpinLockRelease( &g_GsaGlobalInfo->ServiceClassListLock ); + + _DBG_LEAVE_LVL( _DBG_LVL_CALLBACK ); + return bSARRequired; +} + + +// +// Call the clients of the GSA back with received messages. +// +FSTATUS +GsaNotifyClients( + IN uint8 ClientId, + IN MAD_COMMON *pMadHdr, + IN IBT_DGRM_ELEMENT *pDgrm ) +{ + FSTATUS status = FNOT_FOUND; + GSA_SERVICE_CLASS_INFO *pClassInfo; + LIST_ITEM *pListNext; + boolean isInterested; +#if defined(IB_DEBUG) || defined(DBG) + uint32 count = 0; +#endif + + _DBG_ENTER_LVL( _DBG_LVL_CALLBACK, GsaNotifyClients ); + ASSERT( pMadHdr && pDgrm ); + + // To do: coordinate callbacks with a client deregistering. This + // will require changes to the destruction model to be asynchronous. + SpinLockAcquire( &g_GsaGlobalInfo->ServiceClassListLock ); + for( pListNext = QListTail( &g_GsaGlobalInfo->ServiceClassList ); + NULL != pListNext; + pListNext = QListPrev( &g_GsaGlobalInfo->ServiceClassList, pListNext) ) + { + pClassInfo =PARENT_STRUCT(pListNext, GSA_SERVICE_CLASS_INFO, ListItem ); + + // See if this is a request or a response. + if (MAD_IS_RESPONSE((MAD*)pMadHdr)) + { + // Responses are only returned to the initiating client. + if( pClassInfo->ClientId == ClientId ) + { + SpinLockRelease( &g_GsaGlobalInfo->ServiceClassListLock ); + status = (pClassInfo->ReceiveCompletionCallback)( + pClassInfo->ServiceClassContext, pDgrm ); + break; + } + } else { + // New requests are directed to the responder or anyone who + // requires access to all unsolicited messages. + + isInterested = FALSE; + + if ( pMadHdr->MgmtClass == pClassInfo->MgmtClass ) { + boolean fanout; // distribute dgrm to all interested parties + + switch ( pMadHdr->mr.AsReg8 ) { + case MMTHD_REPORT: + isInterested = GSI_IS_REPORT_PROCESSOR( pClassInfo->RegistrationFlags ); + fanout = TRUE; + break; + + case MMTHD_TRAP: + isInterested = GSI_IS_TRAP_PROCESSOR( pClassInfo->RegistrationFlags ); + fanout = TRUE; + break; + + default: + isInterested = GSI_IS_RESPONDER( pClassInfo->RegistrationFlags ); + fanout = FALSE; + break; + } + + if ( isInterested ) { + FSTATUS ret; + + SpinLockRelease( &g_GsaGlobalInfo->ServiceClassListLock ); +#if defined(IB_DEBUG) ||defined( DBG) + if (fanout) + count++; +#endif + ret = ( pClassInfo->ReceiveCompletionCallback )( + pClassInfo->ServiceClassContext, pDgrm ); + + // If we are fanning out, we will provide it to all + // interested parties. However if someone keeps a reference + // (FPENDING), we can't give it to anyone else. Typically + // for traps and notices FCOMPLETED is returned which allows + // fanout to work. + // + // If we are not fanning out, only the first who reports + // FCOMPLETED or FPENDING will get it. + // + // For other cases we update final return status to reflect + // our best case result. (eg. we don't want to report + // NOT_FOUND if we found someone who FREJECT'ed it, etc). + if ( ret == FPENDING) { + status = FPENDING; + _DBG_PRINT (_DBG_LVL_CLASS,("FPENDING in GsaNotifyClients\n")); + break; // they grabbed reference, must stop + } else if (ret == FCOMPLETED) { + status = FCOMPLETED; + if (! fanout) + break; // only give to 1st who wants it + } else if (status == FNOT_FOUND) { + status = ret; // upgrade our return for FREJECT, etc. + } + + SpinLockAcquire( &g_GsaGlobalInfo->ServiceClassListLock ); + } + } + } + } + +#if defined(IB_DEBUG) || defined(DBG) + if (count) + _DBG_PRINT (_DBG_LVL_CLASS,("GsaNotifyClients: %d clients\n", count)); +#endif + // If we didn't find a client to hand the receive to, we're still holding + // the spinlock. + if( !pListNext ) + SpinLockRelease( &g_GsaGlobalInfo->ServiceClassListLock ); + + _DBG_LEAVE_LVL( _DBG_LVL_CALLBACK ); + return status; +} diff --git a/IbAccess/Common/Ibt/Gsa/gsadebug.h b/IbAccess/Common/Ibt/Gsa/gsadebug.h new file mode 100644 index 0000000..49baa43 --- /dev/null +++ b/IbAccess/Common/Ibt/Gsa/gsadebug.h @@ -0,0 +1,79 @@ +/* BEGIN_ICS_COPYRIGHT4 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT4 ****************************************/ +/* [ICS VERSION STRING: unknown] */ + +// Suppress duplicate loading of this file +#ifndef _IBA_GSA_DEBUG_H_ +#define _IBA_GSA_DEBUG_H_ + +#undef _ib_dbg_params +#define _ib_dbg_params Gsa_debug_params +#ifndef Gsa_debug_params + extern IB_DBG_PARAMS Gsa_debug_params; +#endif + +#define GSA_MEM_TAG MAKE_MEM_TAG(G,s,a,M) + +// +// Debug Levels +// +#define _DBG_LVL_MAIN 0x00000001 +#define _DBG_LVL_CLASS 0x00000002 +#define _DBG_LVL_MGMT 0x00000004 +#define _DBG_LVL_OSD 0x00000008 +#define _DBG_LVL_DEVICE 0x00000010 + +#define _DBG_LVL_POOL 0x00000020 +#define _DBG_LVL_STORE 0x00000040 + +#define _DBG_LVL_SEND 0x00000080 +#define _DBG_LVL_RECV 0x00000100 +#define _DBG_LVL_LOCAL 0x00000200 +#define _DBG_LVL_CALLBACK 0x00000400 +#define _DBG_LVL_PKTDUMP 0x00000800 + +#define _DBG_LVL_SAR_INFO 0x00004000 + + +#define _DBG_LVL_TEST 0x00010000 + +#ifdef IB_TRACE + +#define _TRC_LVL_STORE 0x00000040 + +#define _TRC_STORE(string) \ + _TRC_PRINT(_TRC_LVL_STORE, string) + +#else + +#define _TRC_STORE(string) + +#endif + +#endif // _IBA_GSA_DEBUG_H_ diff --git a/IbAccess/Common/Ibt/Gsa/gsadgrm.c b/IbAccess/Common/Ibt/Gsa/gsadgrm.c new file mode 100644 index 0000000..7a9b5fe --- /dev/null +++ b/IbAccess/Common/Ibt/Gsa/gsadgrm.c @@ -0,0 +1,838 @@ +/* BEGIN_ICS_COPYRIGHT4 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT4 ****************************************/ + + +#include "gsamain.h" + +// +// GsiCreateDgrmPool +// +// +// +// INPUTS: +// +// ServiceHandle - Handle returned upon registration +// +// ElementCount - Number of elements in pool +// +// BuffersPerElement- Number of buffers in each pool element +// +// BufferSizeArray[]- An array of buffers sizes. The length of this array must +// be equal to BuffersPerElement. +// +// ContextSize - Size of user context in each element +// +// +// +// OUTPUTS: +// +// DgrmPoolHandle - Opaque handle returned to identify datagram pool created +// +// +// +// RETURNS: +// +// FSUCCESS +// FINVALID_PARAMETER +// FINSUFFICIENT_RESOURCES +// +// +FSTATUS +iba_gsi_create_dgrm_pool( + IN IB_HANDLE ServiceHandle, + IN uint32 ElementCount, + IN uint32 BuffersPerElement, + IN uint32 BufferSizeArray[], + IN uint32 ContextSize, + OUT IB_HANDLE *DgrmPoolHandle + ) +{ + FSTATUS status; + + _DBG_ENTER_LVL(_DBG_LVL_POOL, iba_gsi_create_dgrm_pool); + + status = CreateDgrmPool( + ServiceHandle, + ElementCount, + BuffersPerElement, + BufferSizeArray, + ContextSize, + DgrmPoolHandle ); + +#if defined(DBG) || defined(IB_DEBUG) + if ( FSUCCESS == status ) + ((IBT_MEM_POOL *)*DgrmPoolHandle)->SigInfo = GSA_DGRM_SIG; +#endif + + _DBG_LEAVE_LVL(_DBG_LVL_POOL); + return status; +} + + +// +// GsiDestroyDgrmPool +// +// +// +// INPUTS: +// +// DgrmPoolHandle - Handle returned upon successful creation of Datagram pool +// +// +// +// OUTPUTS: +// +// None +// +// +// +// RETURNS: +// +// FSUCCESS +// FINVALID_PARAMETER +// FINSUFFICIENT_RESOURCES +// +// +FSTATUS +iba_gsi_destroy_dgrm_pool( + IN IB_HANDLE DgrmPoolHandle + ) +{ + FSTATUS status; + + _DBG_ENTER_LVL(_DBG_LVL_POOL, iba_gsi_destroy_dgrm_pool); + +#if defined(DBG) || defined(IB_DEBUG) + if (GSA_DGRM_SIG != ((IBT_MEM_POOL *)DgrmPoolHandle)->SigInfo ) + { + _DBG_ERROR(("Bad DgrmPool Handle passed by client!!!\n")); + _DBG_BREAK; + } +#else +#endif + + status = DestroyDgrmPool(DgrmPoolHandle); + + _DBG_LEAVE_LVL(_DBG_LVL_POOL); + return status; +} + + + +// +// GsiDgrmPoolGet +// +// +// +// INPUTS: +// +// DgrmPoolHandle - Handle returned upon successful creation of Datagram pool +// +// ElementCount - Number of elements to fetch from pool +// +// +// +// +// OUTPUTS: +// +// ElementCount - Number of elements fetched from pool +// +// DgrmList - Pointer holds the datagram list if successful +// +// +// +// RETURNS: +// +// FSUCCESS +// FINVALID_PARAMETER +// FINSUFFICIENT_RESOURCES +// +// +FSTATUS +iba_gsi_dgrm_pool_get( + IN IB_HANDLE DgrmPoolHandle, + IN OUT uint32 *ElementCount, + OUT IBT_DGRM_ELEMENT **DgrmList + ) +{ + FSTATUS status; + + _DBG_ENTER_LVL(_DBG_LVL_POOL, iba_gsi_dgrm_pool_get); + +#if defined(DBG) || defined(IB_DEBUG) + if (GSA_DGRM_SIG != ((IBT_MEM_POOL *)DgrmPoolHandle)->SigInfo ) + { + _DBG_ERROR(("Bad DgrmPool Handle passed by client!!!\n")); + _DBG_BREAK; + } +#else +#endif + + status = DgrmPoolGet( + DgrmPoolHandle, + ElementCount, + DgrmList ); + + _DBG_LEAVE_LVL(_DBG_LVL_POOL); + return status; +} + +// +// GsiDgrmPoolCount +// +// +// +// INPUTS: +// +// DgrmPoolHandle - Handle returned upon successful creation of Datagram pool +// +// +// +// OUTPUTS: +// +// +// RETURNS: +// +// Number of datagrams in the pool +// +uint32 +iba_gsi_dgrm_pool_count( + IN IB_HANDLE DgrmPoolHandle + ) +{ + uint32 rval; + _DBG_ENTER_LVL(_DBG_LVL_POOL, iba_gsi_dgrm_pool_count); + rval = DgrmPoolCount(DgrmPoolHandle); + _DBG_RETURN_LVL(_DBG_LVL_POOL, rval); + return rval; +} + +// +// GsiDgrmPoolTotal +// +// +// +// INPUTS: +// +// DgrmPoolHandle - Handle returned upon successful creation of Datagram pool +// +// +// +// OUTPUTS: +// +// +// RETURNS: +// +// Total Number of datagrams allocated in the pool +// +uint32 +iba_gsi_dgrm_pool_total( + IN IB_HANDLE DgrmPoolHandle + ) +{ + uint32 rval; + _DBG_ENTER_LVL(_DBG_LVL_POOL, iba_gsi_dgrm_pool_total); + rval = DgrmPoolTotal(DgrmPoolHandle); + _DBG_RETURN_LVL(_DBG_LVL_POOL, rval); + return rval; +} + +// +// GsiDgrmPoolPut +// +// +// +// INPUTS: +// +// DgrmList - Datagram elements to return back to pool +// +// +// +// OUTPUTS: +// +// None +// +// +// +// RETURNS: +// +// FSUCCESS +// FINVALID_PARAMETER +// FINSUFFICIENT_RESOURCES +// +// +FSTATUS +iba_gsi_dgrm_pool_put( + IN IBT_DGRM_ELEMENT *DgrmList + ) +{ + FSTATUS status; + + _DBG_ENTER_LVL(_DBG_LVL_POOL, iba_gsi_dgrm_pool_put); + + + status = DgrmPoolPut( DgrmList ); + + _DBG_LEAVE_LVL(_DBG_LVL_POOL); + return status; +} + +// +// CreateGrowableDgrmPool +// +// +// +// INPUTS: +// +// ServiceHandle - Handle returned upon registration +// +// ElementCount - Initial Number of elements in pool (can be 0) +// +// BuffersPerElement- Number of buffers in each pool element (required) +// +// BufferSizeArray[]- An array of buffers sizes. The length of this array must +// be equal to BuffersPerElement. (required) +// +// ContextSize - Size of user context in each element (required) +// +// +// +// OUTPUTS: +// +// DgrmPoolHandle - Opaque handle returned to identify datagram pool created +// +// +// +// RETURNS: +// +// FSUCCESS +// FINVALID_PARAMETER +// FINSUFFICIENT_RESOURCES +// +// + +FSTATUS +iba_gsi_create_growable_dgrm_pool( + IN IB_HANDLE ServiceHandle, + IN uint32 ElementCount, + IN uint32 BuffersPerElement, + IN uint32 BufferSizeArray[], + IN uint32 ContextSize, + OUT IB_HANDLE *DgrmPoolHandle + ) +{ + FSTATUS status; + + _DBG_ENTER_LVL(_DBG_LVL_POOL, iba_gsi_create_growable_dgrm_pool); + + status = CreateGrowableDgrmPool( + ServiceHandle, + ElementCount, + BuffersPerElement, + BufferSizeArray, + ContextSize, + DgrmPoolHandle ); + +#if defined(DBG) || defined(IB_DEBUG) + if ( FSUCCESS == status ) + ((IBT_MEM_POOL *)*DgrmPoolHandle)->SigInfo = GSA_DGRM_SIG; +#endif + + _DBG_LEAVE_LVL(_DBG_LVL_POOL); + return status; +} + +// +// DgrmPoolGrow +// Grow the size of a Growable Dgrm Pool +// This routine may preempt. +// +// +// INPUTS: +// DgrmPoolHandle - Opaque handle to datagram pool +// +// ELementCount - number of elements to add to pool +// +// +// +// OUTPUTS: +// +// None +// +// +// RETURNS: +// +// FSUCCESS +// FINVALID_PARAMETER +// FINSUFFICIENT_RESOURCES +// +FSTATUS +iba_gsi_dgrm_pool_grow( + IN IB_HANDLE DgrmPoolHandle, + IN uint32 ElementCount + ) +{ + FSTATUS status; + + _DBG_ENTER_LVL(_DBG_LVL_POOL, iba_gsi_dgrm_pool_grow); + +#if defined(DBG) || defined(IB_DEBUG) + if (GSA_DGRM_SIG != ((IBT_MEM_POOL *)DgrmPoolHandle)->SigInfo ) + { + _DBG_ERROR(("Bad DgrmPool Handle passed by client!!!\n")); + _DBG_BREAK; + } +#else +#endif + + status = DgrmPoolGrow( + DgrmPoolHandle, + ElementCount); + + _DBG_LEAVE_LVL(_DBG_LVL_POOL); + return status; +} + +// +// DgrmPoolGrowAsNeeded +// Checks Pool size and schedules a system callback to grow it as needed +// This routine does not preempt. +// +// +// INPUTS: +// DgrmPoolHandle - Opaque handle to datagram pool +// +// lowWater - if Dgrm Pool available < this, we will grow it +// +// maxElements - limit on size of Dgrm Pool, will not grow beyond this +// +// growIncrement - amount to grow by if we are growing +// +// +// +// OUTPUTS: +// +// None +// +// +// RETURNS: +// +// None +// +void +iba_gsi_dgrm_pool_grow_as_needed( + IN IB_HANDLE DgrmPoolHandle, + IN uint32 lowWater, + IN uint32 maxElements, + IN uint32 growIncrement + ) +{ + _DBG_ENTER_LVL(_DBG_LVL_POOL, iba_gsi_dgrm_pool_grow_as_needed); + +#if defined(DBG) || defined(IB_DEBUG) + if (GSA_DGRM_SIG != ((IBT_MEM_POOL *)DgrmPoolHandle)->SigInfo ) + { + _DBG_ERROR(("Bad DgrmPool Handle passed by client!!!\n")); + _DBG_BREAK; + } +#else +#endif + + DgrmPoolGrowAsNeeded( DgrmPoolHandle, lowWater, maxElements, + growIncrement); + + _DBG_LEAVE_LVL(_DBG_LVL_POOL); +} + +// +// iba_gsi_dgrm_len +// +// This reports the length of a Dgrm sequence as total of: +// GRH +// MAD_COMMON +// RMPP_HEADER +// class Header (SA, etc) +// RMPP_DATA (possibly large) +// returned messageSize will indicate the total size of the output. +// RmppHdr.PayloadLen will not be adjusted, it will still reflect the +// total RMPP_DATA which will account for a class Header in each +// packet. +// +// INPUTS: +// DgrmElement - A list of Datagrams that need to be analyzed +// ClassHeaderSize - size of class header +// this is expected to be in every RMPP packet +// immediately after the RMPP_HEADER +// size will account for one copy of the Class header +// from the 1st RMPP DATA of the message +// +// OUTPUTS: +// None +// +// RETURNS: +// Message Size. +// if invalid RMPP sequence, returns 0 +// +uint32 +iba_gsi_dgrm_len( + IN IBT_DGRM_ELEMENT *DgrmElement, + IN uint32 ClassHeaderSize + ) +{ + uint32 messageSize = 0; + IBT_BUFFER *pBufferHdr; + MAD_RMPP *pMadRmpp; + uint32 rmppGsDataSize; + + _DBG_ENTER_LVL(_DBG_LVL_POOL, iba_gsi_dgrm_len); + + // Calculate total bytes. + // Each buffer has a GRH+Mad Common Header+RMPP Header+ClassHeader+RMPP Data + // + // We report only one copy of the headers and coalesce the data + + pBufferHdr = DgrmElement->Element.pBufferList; + pMadRmpp = (MAD_RMPP*)pBufferHdr->pNextBuffer->pData;// 2nd buffer is MAD + + rmppGsDataSize = (pMadRmpp->common.BaseVersion == IB_BASE_VERSION) + ? IBA_RMPP_GS_DATASIZE : STL_RMPP_GS_DATASIZE; + + // Check overloaded field 'base' if the recvd data is SAR + + // indicates receive processing identified a multi-packet RMPP message + if ( ((IBT_DGRM_ELEMENT_PRIV *)DgrmElement)->Base ) + { + uint32 segs; + segs = (pMadRmpp->RmppHdr.u2.PayloadLen + rmppGsDataSize-1)/rmppGsDataSize; + // assumes last packet includes a full ClassHeader + // we saved total Data length into PayloadLen of first + messageSize = sizeof(IB_GRH) + sizeof(MAD_COMMON) + + sizeof(RMPP_HEADER) + + ClassHeaderSize + + pMadRmpp->RmppHdr.u2.PayloadLen - segs*ClassHeaderSize; + if ((pMadRmpp->RmppHdr.u2.PayloadLen -(segs-1)*rmppGsDataSize < ClassHeaderSize) + || (pMadRmpp->RmppHdr.u2.PayloadLen < ClassHeaderSize)) + { + _DBG_ERROR(("Bad RMPP Packet: Payloadlen does not allow for complete class header in last packet: segs=%u datasize=%u Payload=%u ClassHeader=%u\n", + segs, (unsigned)rmppGsDataSize, pMadRmpp->RmppHdr.u2.PayloadLen, ClassHeaderSize)); + goto fail; +#if 0 + // workaround, length doesn't allow for complete class + // header in final packet, so drop final packet + segs--; + messageSize = sizeof(IB_GRH) + sizeof(MAD_COMMON) + + sizeof(RMPP_HEADER) + + ClassHeaderSize + + TBD - downgrade PayloadLen by the fluff + pMadRmpp->RmppHdr.u2.PayloadLen - segs*ClassHeaderSize; + if (segs == 0) + { + _DBG_ERROR(("RMPP Bug: Payloadlen does not allow for any class headers: segs=%u datasize=%u Payload=%u ClassHeader=%u\n", + segs, IBA_RMPP_GS_DATASIZE, pMadRmpp->RmppHdr.u2.PayloadLen, ClassHeaderSize)); + goto fail; + } else { + ASSERT(! (pMadRmpp->RmppHdr.u2.PayloadLen -(segs-1)*IBA_RMPP_GS_DATASIZE < ClassHeaderSize)); + } +#endif + } + } else { + messageSize = sizeof(IB_GRH) + sizeof(MAD); + } + + _DBG_PRINT(_DBG_LVL_POOL,("Total bytes: %d\n", messageSize)); + + _DBG_LEAVE_LVL(_DBG_LVL_POOL); + return messageSize; + +fail: + _DBG_LEAVE_LVL(_DBG_LVL_POOL); + return 0; +} + +// +// GsiCoalesceDgrm +// +// The Coalesce function will create an output as follows: +// GRH +// MAD_COMMON +// RMPP_HEADER +// class Header (SA, etc) +// RMPP_DATA (possibly large) +// returned messageSize will indicate the total size of the output +// RmppHdr.PayloadLen will not be adjusted, it will reflect the +// total RMPP_DATA which will account for a class Header in each +// packet. +// +// INPUTS: +// DgrmElement - A list of Datagrams that need to be coalesced +// ppBuffer - *ppBuffer is Client buffer to coalesce to +// if *ppBuffer is NULL, this routine will +// compute the necessary size of the buffer and +// allocate it on behalf of the caller +// ClassHeaderSize - size of class header +// this is expected to be in every RMPP packet +// immediately after the RMPP_HEADER +// a copy of the Class header from the 1st RMPP +// DATA of the message will be included in the +// Coalesced output buffer +// MemAllocFlags - flags for memory allocate of buffer +// for larger responses, it is recommended caller +// be structured such that IBA_MEM_FLAG_PREEMPTABLE +// can be used +// +// OUTPUTS: +// None +// +// RETURNS: +// Message Size. +// if unable to allocate buffer, *ppBuffer is left as NULL +// if invalid RMPP sequence, returns 0. In which case *ppBuffer will be NULL. +// +uint32 +iba_gsi_coalesce_dgrm( + IN IBT_DGRM_ELEMENT *DgrmElement, + IN uint8 **ppBuffer, + IN uint32 ClassHeaderSize + ) +{ + return iba_gsi_coalesce_dgrm2(DgrmElement, ppBuffer, ClassHeaderSize, + IBA_MEM_FLAG_NONE); +} + +void +DumpDgrmElement( + IN IBT_DGRM_ELEMENT *DgrmElement + ) +{ + IBT_ELEMENT *pElement; + IBT_BUFFER *pBufferHdr; + MAD_RMPP *pMadRmpp; + uint32 packet = 0; + + _DBG_ENTER_LVL(_DBG_LVL_POOL, DumpDgrmElement); + + _DBG_ERROR(("DgrmElement %p DgrmElement->RecvByteCount %d\n", + _DBG_PTR(DgrmElement), DgrmElement->TotalRecvSize)); + + pElement = &DgrmElement->Element; + pBufferHdr = pElement->pBufferList; + pMadRmpp = (MAD_RMPP*)GsiDgrmGetRecvMad(DgrmElement); + while (pElement) + { + uint32 Length; + + _DBG_ERROR(("pElement %p packet %d Element RecvByteCount %d pMadRmpp %p\n", + _DBG_PTR(pElement), packet, pElement->RecvByteCount, _DBG_PTR(pMadRmpp))); + packet++; + + Length = pElement->RecvByteCount; + while (Length && pBufferHdr) + { + if (pBufferHdr->pData == pMadRmpp) + { + /* MAD fields */ + _DBG_ERROR(("Mad MgmtClass %d mr %x Status %d tid %"PRIx64" AttributeID %d\n", + pMadRmpp->common.MgmtClass, + pMadRmpp->common.mr.AsReg8, + pMadRmpp->common.u.NS.Status.AsReg16, + pMadRmpp->common.TransactionID, + pMadRmpp->common.AttributeID)); + + /* RMPP fields */ + _DBG_ERROR(("RmppType %u RmppFlags %x RmppStatus %u u1 %u u2 %u\n", + pMadRmpp->RmppHdr.RmppType, + pMadRmpp->RmppHdr.RmppFlags.AsReg8, + pMadRmpp->RmppHdr.RmppStatus, + pMadRmpp->RmppHdr.u1.AsReg32, + pMadRmpp->RmppHdr.u2.AsReg32)); + _DBG_ERROR(("pBufferHdr->pData %p ByteCount %d Length %d\n", + _DBG_PTR(pBufferHdr->pData), pBufferHdr->ByteCount, Length)); + if (g_GsaSettings.FullPacketDump) + { + BSWAP_RMPP_HEADER (&pMadRmpp->RmppHdr); + } + } + else + { + if (g_GsaSettings.FullPacketDump) + { + _DBG_ERROR(("pBufferHdr->pData %p ByteCount %d Length %d\n", + _DBG_PTR(pBufferHdr->pData), pBufferHdr->ByteCount, Length)); + } + } + + if (g_GsaSettings.FullPacketDump) + { + BSWAP_MAD_HEADER((MAD *)&pMadRmpp->common); + + _DBG_DUMP_MEMORY(_DBG_LVL_ERROR, ("Recv GSI Packet Buffer"), + pBufferHdr->pData, + MIN(pBufferHdr->ByteCount, Length)); + + BSWAP_MAD_HEADER((MAD *)&pMadRmpp->common); + } + + if (pBufferHdr->pData == pMadRmpp) + { + if (g_GsaSettings.FullPacketDump) + BSWAP_RMPP_HEADER (&pMadRmpp->RmppHdr); + } + + Length -= MIN(pBufferHdr->ByteCount,Length); + pBufferHdr = pBufferHdr->pNextBuffer; + } + + pElement = pElement->pNextElement; + if (pElement) + { + pBufferHdr = pElement->pBufferList; + pMadRmpp = (MAD_RMPP*)GsiDgrmGetRecvMad((IBT_DGRM_ELEMENT *)pElement); + } + } + _DBG_LEAVE_LVL(_DBG_LVL_POOL); +} + +uint32 +iba_gsi_coalesce_dgrm2( + IN IBT_DGRM_ELEMENT *DgrmElement, + IN uint8 **ppBuffer, + IN uint32 ClassHeaderSize, + IN uint32 MemAllocFlags + ) +{ + uint32 messageSize = 0; + uint32 byteCount, totalBytesToCopy; + IBT_ELEMENT *pElement; + IBT_BUFFER *pBufferHdr; + uint8 *pBuffer; + MAD_RMPP *pMadRmpp; +#ifdef TEST_DUMP + static int counter; +#endif + + _DBG_ENTER_LVL(_DBG_LVL_POOL, iba_gsi_coalesce_dgrm); + + pElement = &DgrmElement->Element; + pBufferHdr = pElement->pBufferList; + pMadRmpp = (MAD_RMPP*)pBufferHdr->pNextBuffer->pData;// 2nd buffer is MAD + + // Calculate total bytes to copy. + // Each buffer has a GRH+Mad Common Header+RMPP Header+ClassHeader+RMPP Data + // + // We copy only one copy of the headers and coalesce the data + messageSize = totalBytesToCopy = iba_gsi_dgrm_len(DgrmElement, ClassHeaderSize); + if (! messageSize) + goto fail; + _DBG_PRINT(_DBG_LVL_POOL,("Total bytes to copy: %d\n", totalBytesToCopy)); + + if (*ppBuffer == NULL) + { + *ppBuffer = (uint8*)MemoryAllocate2(totalBytesToCopy, MemAllocFlags, GSA_MEM_TAG); + if (*ppBuffer == NULL) + goto fail; + } + pBuffer = *ppBuffer; + + // Copy GRH + if (pBufferHdr->ByteCount != sizeof(IB_GRH)) { + _DBG_ERROR(("Bad buffer header size: %u expected %u\n", pBufferHdr->ByteCount, (unsigned)sizeof(IB_GRH))); + messageSize = 0; // indicate invalid packets + goto fail; + } + byteCount = pBufferHdr->ByteCount; + MemoryCopy( pBuffer, pBufferHdr->pData, byteCount ); + pBuffer += byteCount; + totalBytesToCopy -= byteCount; // keep count + pBufferHdr = pBufferHdr->pNextBuffer; + + // Copy Mad Common + RMPP Header + class header + first data area + byteCount = (totalBytesToCopy > pBufferHdr->ByteCount) ? \ + pBufferHdr->ByteCount:totalBytesToCopy; + MemoryCopy( pBuffer, pBufferHdr->pData, byteCount ); + pBuffer += byteCount; + totalBytesToCopy -= byteCount; // keep count + + // Walk all elements of RMPP list + while ( totalBytesToCopy ) + { + pElement = pElement->pNextElement; + + if ( NULL == pElement ) + { + _DBG_ERROR(("LIST ERROR DgrmElement %p ClassHeaderSize %d messageSize %d BytesLeft %d\n", + _DBG_PTR(DgrmElement), ClassHeaderSize, messageSize, totalBytesToCopy)); + DumpDgrmElement(DgrmElement); + messageSize = 0; // indicate invalid packets/buffers + goto fail; + } + else + { +#ifdef TEST_DUMP + if ((++counter%50) == 0) + { + _DBG_ERROR(("LIST ERROR DgrmElement %p ClassHeaderSize %d messageSize %d BytesLeft %d\n", + _DBG_PTR(DgrmElement), ClassHeaderSize, messageSize, totalBytesToCopy)); + DumpDgrmElement(DgrmElement); + messageSize = 0; // indicate invalid packets/buffers + goto fail; + } +#endif + } + + // skip GRH + pBufferHdr = pElement->pBufferList->pNextBuffer; + + pMadRmpp = (MAD_RMPP *)pBufferHdr->pData; + + // copy as much class data as is left in packet + // subtract common headers, if packet too small, don't copy anything + byteCount = (sizeof(MAD_COMMON) + sizeof(RMPP_HEADER) + ClassHeaderSize); + byteCount = (byteCount > pBufferHdr->ByteCount)? \ + 0:(pBufferHdr->ByteCount - byteCount); + + byteCount = (totalBytesToCopy > byteCount)?byteCount:totalBytesToCopy; + if (byteCount) + { + MemoryCopy( pBuffer, &pMadRmpp->Data[ClassHeaderSize], byteCount); + pBuffer += byteCount; + totalBytesToCopy -= byteCount; // keep count + } + } + _DBG_LEAVE_LVL(_DBG_LVL_POOL); + return messageSize; + +fail: + if (*ppBuffer) + { + MemoryDeallocate(*ppBuffer); + *ppBuffer = NULL; + } + _DBG_LEAVE_LVL(_DBG_LVL_POOL); + return messageSize; +} diff --git a/IbAccess/Common/Ibt/Gsa/gsamain.c b/IbAccess/Common/Ibt/Gsa/gsamain.c new file mode 100644 index 0000000..193c1a4 --- /dev/null +++ b/IbAccess/Common/Ibt/Gsa/gsamain.c @@ -0,0 +1,398 @@ +/* BEGIN_ICS_COPYRIGHT4 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT4 ****************************************/ + + +#include "gsamain.h" + + +#define MAX_TID_MAPPINGS 1000000 + + +// +// Globals +// + + +// +// Debug params +// +#ifdef ICS_LOGGING +_IB_DBG_PARAM_BLOCK((_DBG_LVL_FATAL|_DBG_LVL_ERROR), _DBG_BREAK_ENABLE, GSA_MEM_TAG, "Gsa", MOD_GSA, Gsa); +#else +_IB_DBG_PARAM_BLOCK((_DBG_LVL_FATAL|_DBG_LVL_ERROR), _DBG_BREAK_ENABLE, GSA_MEM_TAG, "Gsa"); +#endif + +// +// Global Info +// +GSA_GLOBAL_INFO *g_GsaGlobalInfo=NULL; + +// +// Stored settings +// + +GSA_GLOBAL_CONFIG_PARAMETERS g_GsaSettings = GSA_DEFAULT_SETTINGS; + + +// +// GsaLoad +// +// This routine is called by the VCA Init when the driver is first loaded. +// This routine is to create and initialize driver data structures. +// +// INPUTS: +// +// ComponentInfo - Component Info structure to common driver entry points. +// +// OUTPUTS: +// +// None. +// +// RETURNS: +// +// FSUCCESS - Indicates a successful load. +// + +FSTATUS +GSALoad( + IN IBT_COMPONENT_INFO *ComponentInfo + ) +{ + _DBG_ENTER_LVL (_DBG_LVL_MAIN, GSALoad); + _DBG_INIT; + +#if !defined(VXWORKS) + _DBG_PRINT (_DBG_LVL_MAIN, + (" InfiniBand General Services Agent. Built %s %s\n",\ + __DATE__, __TIME__ )); +#else + _DBG_PRINT (_DBG_LVL_MAIN, + (" InfiniBand General Services Agent. Built %s %s\n",\ + _DBG_PTR(__DATE__), _DBG_PTR(__TIME__) )); +#endif + + // + // Establish dispatch entry points for the functions supported. + // + MemoryClear( ComponentInfo, sizeof(IBT_COMPONENT_INFO) ); + + ComponentInfo->AddDevice = GsaAddDevice; + ComponentInfo->RemoveDevice = GsaRemoveDevice; + ComponentInfo->Unload = GSAUnload; + + GsaOsComponentInfo( ComponentInfo ); // Fill in OS specific entrypoints + + // + // This function is called to initialize the GSA subsystem. This must be + // called only once and if the function does not return success, the + // caller must unload the component containing GSA or else not use the + // GSA functionality since GSA will not be available. + // + // We are being asked to do a one-time initialization. Here we initialize + // the list of channel adapters as well as initialize the list of service + // classes as well as initialize the spin locks guarding these lists. + // + + // + // Allocate space for Global data + // + g_GsaGlobalInfo = (GSA_GLOBAL_INFO*)MemoryAllocateAndClear(sizeof(GSA_GLOBAL_INFO), FALSE, GSA_MEM_TAG); + if( NULL == g_GsaGlobalInfo ) + { + _DBG_ERROR(( "Not enough memory!\n" )); + _DBG_LEAVE_LVL(_DBG_LVL_MAIN); + return FINSUFFICIENT_RESOURCES; + } + + // + // Initialize the state of the global info. + // + SpinLockInitState( &g_GsaGlobalInfo->CaListLock ); + SpinLockInitState( &g_GsaGlobalInfo->ServiceClassListLock ); + SpinLockInitState( &g_GsaGlobalInfo->SARSendListLock ); + SpinLockInitState( &g_GsaGlobalInfo->SARRecvListLock ); + + QListInitState( &g_GsaGlobalInfo->ServiceClassList ); + QListInitState( &g_GsaGlobalInfo->SARSendList ); + QListInitState( &g_GsaGlobalInfo->SARRecvList ); + + // + // Initialize the global locks. + // + if( !SpinLockInit( &g_GsaGlobalInfo->CaListLock ) || + !SpinLockInit( &g_GsaGlobalInfo->ServiceClassListLock ) || + !SpinLockInit( &g_GsaGlobalInfo->SARSendListLock ) || + !SpinLockInit( &g_GsaGlobalInfo->SARRecvListLock ) ) + { + _DBG_ERROR(( "Unable to initialize spin locks!\n" )); + GSAUnload(); + _DBG_LEAVE_LVL(_DBG_LVL_MAIN); + return FERROR; + } + + if (FSUCCESS != CreateGlobalRecvQ()) + { + _DBG_ERROR(( "Unable to initialize global recvQ!\n" )); + GSAUnload(); + _DBG_LEAVE_LVL(_DBG_LVL_MAIN); + return FERROR; + } + + // + // initialize global data + // + + // + // Initialize global lists. + // + if ((QListInit( &g_GsaGlobalInfo->ServiceClassList ) == FALSE) || + (QListInit( &g_GsaGlobalInfo->SARSendList ) == FALSE) || + (QListInit( &g_GsaGlobalInfo->SARRecvList ) == FALSE)) + { + _DBG_ERROR(( "Failed to Initialize Global Lists!\n")); + GSAUnload(); + _DBG_LEAVE_LVL(_DBG_LVL_MAIN); + return FERROR; + } + + g_GsaGlobalInfo->ClientId = 0; + + // + // We are assuming that the Subnet Manager or the partition manager + // portion of the subnet manager has configured the partition table + // of each port in each ca that wants to communicate using QP1 + // in a way that the intersection of the partition tables of these + // ports is non-empty, which means that there is at least one common + // partition key across all ports. + // + + // + // Read Global settings in a OS specific calls + // + GsaInitGlobalSettings(); + + _TRC_REGISTER(); + +/* + // + // register for notifications + // + if( FSUCCESS != IbtRegisterNotify ( + GsaNotifyCallback, + NULL, // Context + IB_NOTIFY_PORT_DOWN | IB_NOTIFY_LID_EVENT + | IB_NOTIFY_ON_REGISTER, + &g_GsaGlobalInfo->NotifyHandle )) + { + _DBG_ERROR(("System unstable!!! " + "Could not hook for Notifications\n")); + + } +*/ + + _DBG_LEAVE_LVL(_DBG_LVL_MAIN); + return FSUCCESS; +} + + + + + +// +// GSAUnload +// +// This routine should release resources allocated in the SmaLoad function. +// +// INPUTS: +// +// None. +// +// OUTPUTS: +// +// None. +// +// RETURNS: +// +// None +// +// +void +GSAUnload(void) +{ + _DBG_ENTER_LVL(_DBG_LVL_MAIN, GSAUnload); + +#if 0 + // remove Notification Handle + if ( g_GsaGlobalInfo->NotifyHandle ) + IbtDeregisterNotify( g_GsaGlobalInfo->NotifyHandle ); +#endif + + _TRC_UNREGISTER(); + + // Clean up the global information if it exists. + if( !g_GsaGlobalInfo ) + { + _DBG_LEAVE_LVL(_DBG_LVL_MAIN); + return; + } + + DestroySARContexts(); + + // Empty Global list + if( g_GsaGlobalInfo->DgrmPoolRecvQ ) + { + DestroyGlobalRecvQ(); + } + + // Remove user list + QListDestroy( &g_GsaGlobalInfo->SARRecvList ); + QListDestroy( &g_GsaGlobalInfo->SARSendList ); + QListDestroy( &g_GsaGlobalInfo->ServiceClassList ); + + // Locks + SpinLockDestroy( &g_GsaGlobalInfo->SARRecvListLock ); + SpinLockDestroy( &g_GsaGlobalInfo->SARSendListLock ); + SpinLockDestroy( &g_GsaGlobalInfo->CaListLock ); + SpinLockDestroy( &g_GsaGlobalInfo->ServiceClassListLock ); + + + MemoryDeallocate( g_GsaGlobalInfo ); + g_GsaGlobalInfo = NULL; + + _DBG_LEAVE_LVL(_DBG_LVL_MAIN); +} + + + + +// +// GsaAddDevice +// +// This routine is called by the VCA Startdevice loop for all driver libs. +// The CA device that just started will be identified by its GUID. +// +// INPUTS: +// +// CaGUID - GUID to the CA that was added and started. +// +// OUTPUTS: +// +// None +// +// RETURNS: +// +// FSTATUS. +// +// + +FSTATUS +GsaAddDevice( + IN EUI64 CaGuid, + OUT void **Context + ) +{ + FSTATUS status = FSUCCESS; + + + + _DBG_ENTER_LVL(_DBG_LVL_MAIN, GsaAddDevice); + + + // + // Process this Channel Adapter. + // + + // + // Build CA list is done by SMA here + // + + // + // Query Ca Info and pre post to receive queue + // + status = PrepareCaForReceives(CaGuid); + + + _DBG_LEAVE_LVL(_DBG_LVL_MAIN); + + return status; +} + + +// +// GsaRemoveDevice +// +// This routine is called by the VCA Removedevice loop for all driver libs. +// The CA device that was removed will be identified by its GUID. +// +// INPUTS: +// +// CaGUID - GUID to the CA that was added and started. +// +// OUTPUTS: +// +// None. +// +// RETURNS: +// +// FSTATUS. +// +// + +FSTATUS +GsaRemoveDevice( + IN EUI64 CaGuid, + IN void *Context + ) +{ + + FSTATUS status = FSUCCESS; + + + _DBG_ENTER_LVL(_DBG_LVL_MAIN, GsaRemoveDevice); + + + // + // Note: + // The Remove Device routine in SMA deregisters all memory held by GSA + // and hence does not need a seperate remove call. + // The SMA also deletes QPs and CQs associated with GSA + // + + + // + // Rebuild CA list is done by SMA here + // + + + + _DBG_LEAVE_LVL(_DBG_LVL_MAIN); + + return status; +} + diff --git a/IbAccess/Common/Ibt/Gsa/gsamain.h b/IbAccess/Common/Ibt/Gsa/gsamain.h new file mode 100644 index 0000000..80ee06c --- /dev/null +++ b/IbAccess/Common/Ibt/Gsa/gsamain.h @@ -0,0 +1,490 @@ +/* BEGIN_ICS_COPYRIGHT4 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT4 ****************************************/ +/* [ICS VERSION STRING: unknown] */ + +#ifndef _IBA_IB_GSA_MAIN_H_ +#define _IBA_IB_GSA_MAIN_H_ + + +#include "datatypes.h" +#include "stl_types.h" +#include "stl_mad_priv.h" +#include "vpi.h" +#include "sma_osd.h" +#include "ib_debug_osd.h" +#include "vpi_export.h" +#include "ib_smi.h" +#include "ib_gsi.h" +#include "ib_ibt.h" +#include "ib_generalServices.h" +#include "gsadebug.h" +#include "vca_export.h" +#include "statustext.h" +#include "ibyteswap.h" +#include "ispinlock.h" +#include "isyscallback.h" +#include "ilist.h" +#include "itimer.h" +#include "imath.h" +#include "isyscallback.h" +#include "smagsa.h" +#include "gsi_params.h" + +#if defined (__cplusplus) +extern "C" { +#endif + + + +// +// Definitions +// + +#define MAX_CLIENT_ID 0xff + +#define GSA_RECVQ_LOW_WATER 50 // when to grow GlobalRecvQ Pool + +#if defined(DBG) || defined(IB_DEBUG) + +#define GSA_CLASS_SIG 0x73616c63 // 'salc' +#define GSA_DGRM_SIG 0x6d726764 // 'mrgd' + +#endif + + +// +// Structures +// +extern IBT_GLOBAL IbtGlobal; + + +// +// Structure to holds sends +// +typedef struct _GSA_POST_SEND_LIST { + uint32 DgrmIn; + ATOMIC_UINT DgrmOut; + IBT_DGRM_ELEMENT *DgrmList; + boolean SARRequest; +} GSA_POST_SEND_LIST; + + +// +// structure for memory pool +// +typedef struct _IBT_MEM_POOL { + struct _IBT_MEM_POOL *Next; // link to Growable Pool + struct _IBT_MEM_POOL *Parent; // our parent Growable Pool + SYS_CALLBACK_ITEM *CallbackItem; // used for Growable Pools + ATOMIC_UINT GrowScheduled; // used for Growable Pools + + SPIN_LOCK Lock; // lock + uint32 TotalElements; // No. of elements in pool + uint32 Elements; // Available for Gets + IBT_DGRM_ELEMENT *DgrmList; // datagram list + uint32 BuffersPerElement; + uint8 ReceivePool:1; // Send or receive pool + // default FALSE: + // SENDPool-Client buffer + uint8 Growable:1; // head of growable pool + GLOBAL_MEM_LIST *MemList; // global memlist; + void *UdBlock; // registered mem block + void *HeaderBlock; // header block + IB_HANDLE ServiceHandle; // user's handle + +#if defined(DBG) || defined(IB_DEBUG) + uint32 SigInfo; +#endif +} IBT_MEM_POOL; + + +typedef struct _IBT_DGRM_ELEMENT_PRIV { + IBT_DGRM_ELEMENT DgrmElement; + IBT_MEM_POOL *MemPoolHandle; + // TBD - replace this with a Union { pPostSendList; IsSarRecv } + GSA_POST_SEND_LIST *Base; // used for sends and recvs + // Sends: base to chain of + // multiple sends + // Recvs: Indicates SAR data + GSA_POST_SEND_LIST PostSendList; // The actual list + uint64 SavedSendTid; // User's TID on a send. + IB_HANDLE AvHandle; // AV Handle + IB_LOCAL_DATASEGMENT *DsList; // list to Data segments + struct _GSA_SAR_CONTEXT *pSarContext; // Pointer to context data + // for SAR +} IBT_DGRM_ELEMENT_PRIV; + + + +// +// GSA_GLOBAL_INFO +// +// This structure is used to keep track of global information and tie the +// various lists maintained into meaningful related entities. There is only +// one instance of this structure per the whole of GSA activeCAlist is used +// to link the list of all CA's in the system. Every time a CA is added, a +// new CA structure is created and linked to the end of this field in a +// LIFO fashion. +// +// calock is used to guard access to the above list ( activeCAlist ). +// +// ServiceClassList is used to link the list of all registered service +// classes. Every time a unique service class is registered, a service class +// registration record ( GSA_SERVICE_CLASS_INFO ) is created and linked to +// this list in a LIFO fashion. +// +// ServiceClassListLock is used to guard access to the list of service +// classes ( ServiceClassList ). +// +// The interfaces of GSA MUST check this state before providing any +// useful functionality. +// if FALSE, GSA services are not available. +// +// ConfigParam contains the list of configuration parameters used to configure +// GSA. These values might be read from registry or from local configuration +// file(s) , depending on the platform we are running on. +// +// +typedef struct _GSA_GLOBAL_INFO +{ + // + // this keeps track of internally generated client ids. Normally, a client id + // is an 8-bit value that is unique across a single management class. + // For now, this is unique across all management classes. + // + // ????TOBEDONE. + // Later, when we have more management classes , this needs to be + // changed so that they are unique across just one management class + // + + uint8 ClientId; + + + SPIN_LOCK CaListLock; + SMA_OBJECT SmObj; + + IB_HANDLE DgrmPoolRecvQ; + + SPIN_LOCK ServiceClassListLock; + QUICK_LIST ServiceClassList; + + // SAR Info + SPIN_LOCK SARSendListLock; + QUICK_LIST SARSendList; + SPIN_LOCK SARRecvListLock; + QUICK_LIST SARRecvList; + ATOMIC_UINT SARRecvDropped; + + //IB_HANDLE NotifyHandle; // Notification calls + + uint8 ClientIdArray[MAX_CLIENT_ID]; +} GSA_GLOBAL_INFO; + + + +// +// extern declaration for our global information structure +// +#ifndef g_GsaGlobalInfo +extern GSA_GLOBAL_INFO *g_GsaGlobalInfo; +#endif + +// +// GSA_SERVICE_CLASS_INFO +// +// +// This structure describes a registered service class . An instance of this +// is created every time a unique service class is registered. +// +// ListItem is used to link this registration record into a list. +// +// Serviceclasssendlist is the head of all send buffers submitted by +// the service class for sending. By definition these buffers are already +// registered with one or more CAs. +// +// serviceclassrecvlist is the head of all receive buffers submitted by +// the service class for receiving. By definition, these buffers are +// already registered with one or more CAs. +// +// describe the mgmt class and version +// registered by the service class. +// +// ServiceClassContext is the value supplied by the service class +// during registration. +// +// ReceiveCompletionCallback is the handler supplied by the service class +// that is used to indicate receive completions on behalf of this service +// class. +// +// sendcompletehandler is the handler supplied by the service class used +// to indicate send completions on behalf of this service class. +// +// Both ReceiveCompletionCallback and sendcompletehandler are +// supplied by the service class and are used by GSA to indicate the +// respective completion events. +// +// MiscEventHandler is used to indicate miscellaneous events. This handler +// is used to indicate the following events. +// CA being removed or disabled. In this case, the CA guid is provided +// as input. +// A port being disconnected. In this case, the port GUID and the CA GUID +// are provided as input. +// Other error events are also indicated. +// +typedef struct _GSA_SERVICE_CLASS_INFO +{ + LIST_ITEM ListItem; + + uint8 MgmtClass; + uint8 MgmtClassVersion; + + // Flags used to indicate responder, trap processor and report processor. + GSI_REGISTRATION_FLAGS RegistrationFlags; + + boolean bSARRequired; // TRUE for SAR support + + void *ServiceClassContext; + GSI_SEND_COMPLETION_CALLBACK *SendCompletionCallback; + GSI_RECEIVE_CALLBACK *ReceiveCompletionCallback; + + GSA_GLOBAL_INFO *pGlobalInfo; + + uint8 ClientId; + +#if defined(DBG) || defined(IB_DEBUG) + uint32 SigInfo; + ATOMIC_UINT ErrorMsgs; +#endif +} GSA_SERVICE_CLASS_INFO; + +// +// Function declarations +// +FSTATUS +GSALoad( + IN IBT_COMPONENT_INFO *ComponentInfo + ); + +void +GSAUnload(void); + +FSTATUS +GsaAddDevice( + IN EUI64 CaGuid, + OUT void **Context + ); + +FSTATUS +GsaRemoveDevice( + IN EUI64 CaGuid, + IN void *Context + ); + +void +GsaInitGlobalSettings(void); + +void +GsaOsComponentInfo( + IN IBT_COMPONENT_INFO *ComponentInfo + ); + +FSTATUS +PrepareCaForReceives( + IN EUI64 CaGuid + ); + +FSTATUS +GetCaContextFromAvInfo( + IN IB_ADDRESS_VECTOR *AvInfo, + IN uint32 CaMemIndex, + OUT IB_HANDLE *AvHandle, + OUT IB_HANDLE *Qp1Handle, + OUT IB_HANDLE *Cq1Handle, + OUT SPIN_LOCK **QpLock, + OUT IB_L_KEY *LKey + ); + +FSTATUS +GetGsiContextFromPortGuid( + IN EUI64 PortGuid, + OUT IB_HANDLE *Qp1Handle, + OUT uint8 *PortNumber + ); + +FSTATUS +CreateDgrmPool( + IN IB_HANDLE ServiceHandle, + IN uint32 ElementCount, + IN uint32 BuffersPerElement, + IN uint32 BufferSizeArray[], + IN uint32 ContextSize, + OUT IB_HANDLE *DgrmPoolHandle + ); + +FSTATUS +DestroyDgrmPool( + IN IB_HANDLE DgrmPoolHandle + ); + +FSTATUS +DgrmPoolGet( + IN IB_HANDLE DgrmPoolHandle, + IN OUT uint32 *ElementCount, + OUT IBT_DGRM_ELEMENT **DgrmList + ); + +void +DumpDgrmElement( + IN IBT_DGRM_ELEMENT *DgrmElement + ); + +uint32 +DgrmPoolCount( + IN IB_HANDLE DgrmPoolHandle + ); + +uint32 +DgrmPoolTotal( + IN IB_HANDLE DgrmPoolHandle + ); + +FSTATUS +DgrmPoolPut( + IN IBT_DGRM_ELEMENT *pDgrmList + ); + +FSTATUS +CreateGrowableDgrmPool( + IN IB_HANDLE ServiceHandle, + IN uint32 ElementCount, + IN uint32 BuffersPerElement, + IN uint32 BufferSizeArray[], + IN uint32 ContextSize, + OUT IB_HANDLE *DgrmPoolHandle + ); + +FSTATUS +DgrmPoolGrow( + IN IB_HANDLE DgrmPoolHandle, + IN uint32 ElementCount + ); + +void +DgrmPoolGrowAsNeeded( + IN IB_HANDLE DgrmPoolHandle, + IN uint32 lowWater, + IN uint32 maxElements, + IN uint32 growIncrement + ); + +FSTATUS +CreateGlobalRecvQ(void); + +FSTATUS +DgrmPoolAddToGlobalRecvQ( + IN uint32 ElementCount + ); + +void +GrowRecvQAsNeeded(void); + +void +DestroyGlobalRecvQ(void); + +FSTATUS +DecrementGsiRecvQPostedForPortGuid( + IN EUI64 PortGuid, + OUT uint32 *RecvQPosted + ); + +FSTATUS +PostRecvMsgToPort( + IN uint32 ElementCount, + IN EUI64 PortGuid + ); + +void +GsaNotifyCallback( + IN IB_NOTIFY_RECORD NotifyRecord + ); + +FSTATUS +GsaNotifyClients( + IN uint8 ClientId, + IN MAD_COMMON *pMadHdr, + IN IBT_DGRM_ELEMENT *pDgrm ); + +// has this client requested GSI to do RMPP protocol handling for it +boolean +IsSarClient( + IN uint8 ClientId, + IN uint8 MgmtClass ); + +// RMPP entry points, provided by the RMPP protocol provider + +// destroy all SAR Context data, used during Unload +void +DestroySARContexts(void); + +// RMPP Sender - initiate a transfer which may require RMPP +FSTATUS +DoSARSend( + IN GSA_SERVICE_CLASS_INFO *ServiceClass, + IN GSA_POST_SEND_LIST *PostList + ); + +// Common Completion Handlers for RMPP Sender and Receiver Contexts +FSTATUS +ProcessSARRecvCompletion ( + IN MAD *pMad, + IN IBT_DGRM_ELEMENT **ppDgrm + ); + +void +ProcessSARSendCompletion ( + IN MAD *pMad, + IN IBT_DGRM_ELEMENT *pDgrm + ); + +FSTATUS +GsiDoSendDgrm( + GSA_SERVICE_CLASS_INFO *ServiceClass, + IN GSA_POST_SEND_LIST *pPostList + ); + +void GsiSendInvalid( + IN IBT_DGRM_ELEMENT *pDgrm + ); + +#if defined (__cplusplus) +}; +#endif + + +#endif // _IBA_IB_GSA_MAIN_H_ diff --git a/IbAccess/Common/Ibt/Gsa/gsamgmt.c b/IbAccess/Common/Ibt/Gsa/gsamgmt.c new file mode 100644 index 0000000..1bd6dab --- /dev/null +++ b/IbAccess/Common/Ibt/Gsa/gsamgmt.c @@ -0,0 +1,596 @@ +/* BEGIN_ICS_COPYRIGHT4 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT4 ****************************************/ + + +#include "gsamain.h" + +void +GsaUpdateCaList(void) +{ + if (g_GsaGlobalInfo) + { + SpinLockAcquire( &g_GsaGlobalInfo->CaListLock ); + + if ( g_GsaGlobalInfo->SmObj.CaTbl ) + { + MemoryDeallocate( g_GsaGlobalInfo->SmObj.CaTbl ); + g_GsaGlobalInfo->SmObj.CaTbl = NULL; + /* for final RemoveDevice, NumCa = 0 and SmaCreateObj is a Noop + * for AddDevice SmaCreateSmaObj will reinitialize NumCa + */ + g_GsaGlobalInfo->SmObj.NumCa--; + } + + SmaCreateSmaObj( &g_GsaGlobalInfo->SmObj ); + + SpinLockRelease( &g_GsaGlobalInfo->CaListLock ); + + } +} + + +FSTATUS +PrepareCaForReceives( + IN EUI64 CaGuid + ) +{ + FSTATUS status = FSUCCESS; + SMA_PORT_TABLE_PRIV *pPortTblPriv = NULL; + uint32 i; + SMA_CA_TABLE *pCaTbl; + SMA_PORT_TABLE *pPortTbl; + SMA_CA_OBJ_PRIVATE *pCaObj; + uint8 j; + + + _DBG_ENTER_LVL(_DBG_LVL_MGMT, PrepareCaForReceives); + + + // + // Query CaGUID and PortInfo + // + + SpinLockAcquire( &g_GsaGlobalInfo->CaListLock ); + + pCaTbl = g_GsaGlobalInfo->SmObj.CaTbl; + + pCaObj = NULL; // init for parsing + + for ( i=0; iSmObj.NumCa; i++ ) + { + if ( CaGuid == pCaTbl->CaObj[i].CaGuid ) + { + pPortTbl = pCaTbl->CaObj[i].PortTbl; + pCaObj = (SMA_CA_OBJ_PRIVATE *)pCaTbl->CaObj[i].SmaCaContext; + pPortTblPriv = (SMA_PORT_TABLE_PRIV *)pCaObj->CaPublic.PortTbl; + break; + } + } // i + + SpinLockRelease( &g_GsaGlobalInfo->CaListLock ); + + + ASSERT( pPortTblPriv ); + + + // + // Post default msgs + // + + status = DgrmPoolAddToGlobalRecvQ( + g_GsaSettings.PreAllocRecvBuffersPerPort * pCaTbl->CaObj[i].Ports ); + + if ( FSUCCESS == status ) + { + for ( j=0; j< pCaTbl->CaObj[i].Ports; j++ ) + { + status = PostRecvMsgToPort( + g_GsaSettings.MinBuffersToPostPerPort, + pPortTblPriv->PortBlock[j].Public.GUID ); + } // j + + + // + // Rearm CQ to receive event notifications. + // The next Work Completion written to the CQ + // will generate an event + // + status = iba_rearm_cq( + pCaObj->Qp1CqHandle, + CQEventSelNextWC + ); + + + } + else + { + _DBG_ERROR(("Error in Global RecvQ!\n")); + } + + _DBG_LEAVE_LVL(_DBG_LVL_MGMT); + return status; + +} + + + +FSTATUS +GetCaContextFromAvInfo( + IN IB_ADDRESS_VECTOR *AvInfo, + IN uint32 CaMemIndex, + OUT IB_HANDLE *AvHandle, + OUT IB_HANDLE *Qp1Handle, + OUT IB_HANDLE *Cq1Handle, + OUT SPIN_LOCK **QpLock, + OUT IB_L_KEY *LKey + ) +{ + FSTATUS status=FSUCCESS; + SMA_CA_TABLE *pCaTbl; + SMA_PORT_TABLE *pPortTbl; + SMA_CA_OBJ_PRIVATE *pCaObj; + SMA_PORT_TABLE_PRIV *pPortTblPriv; + CA_MEM_LIST caMemList; + uint32 i; + uint8 j=0; + boolean bFound=FALSE; + + + _DBG_ENTER_LVL(_DBG_LVL_MGMT, GetCaContextFromAvInfo); + + // + // Init variables + // + *Qp1Handle = NULL; + *Cq1Handle = NULL; + *QpLock = NULL; + *LKey = 0; + + SpinLockAcquire( &g_GsaGlobalInfo->CaListLock ); + + // + // This lookup can be converted to hash table on GUIDs + // + + pCaTbl = g_GsaGlobalInfo->SmObj.CaTbl; + + for ( i=0; iSmObj.NumCa; i++ ) + { + pPortTbl = pCaTbl->CaObj[i].PortTbl; + for ( j=0; jCaObj[i].Ports; j++ ) + { + if ( AvInfo->PortGUID == pPortTbl->PortBlock[j].GUID ) + { + bFound = TRUE; + break; + } + } // j + + if ( TRUE == bFound ) + break; + } // i + + if ( TRUE == bFound ) + { + pCaObj = (SMA_CA_OBJ_PRIVATE *)pCaTbl->CaObj[i].SmaCaContext; + pPortTblPriv = (SMA_PORT_TABLE_PRIV *)pCaObj->CaPublic.PortTbl; + + // + // Only post to Qp not in error or destroy state + // hardware will handle active and armed tests, by commenting out + // we allow a down port to still be used to talk to itself for + // applications using IB for local communications + // + if ( /*(IB_PORT_ACTIVE == pPortTblPriv->PortBlock[j].Public.State + ||IB_PORT_ARMED == pPortTblPriv->PortBlock[j].Public.State ) && */ \ + ( QP_NORMAL == pPortTblPriv->PortBlock[j].Qp1Control )) + { + // + // Create AV only if requested + // + if ( NULL != AvHandle ) + { + //AvInfo->PortNumber = j + 1; + status = GetAV( pCaObj, AvInfo, AvHandle ); + } + + if ( FSUCCESS == status ) + { + *Qp1Handle = pPortTblPriv->PortBlock[j].Qp1Handle; + *Cq1Handle = pCaObj->Qp1CqHandle; + *QpLock = &pPortTblPriv->PortBlock[j].QpLock; + + GetMemInfoFromCaMemTable( pCaObj, CaMemIndex, &caMemList); + + *LKey = caMemList.LKey; + } + } + else + { + //_DBG_ERROR(("Port 0x%"PRIx64" Not Active\n", AvInfo->PortGUID)); + status = FINVALID_STATE; + } + } + else + { + //_DBG_ERROR(("Unable to find Ca for Port 0x%"PRIx64"\n", AvInfo->PortGUID)); + status = FINVALID_PARAMETER; + } + + SpinLockRelease( &g_GsaGlobalInfo->CaListLock ); + + _DBG_LEAVE_LVL(_DBG_LVL_MGMT); + return status; + +} + + +FSTATUS +GetGsiContextFromPortGuid( + IN EUI64 PortGuid, + OUT IB_HANDLE *Qp1Handle, + OUT uint8 *PortNumber + ) +{ + FSTATUS status=FSUCCESS; + SMA_CA_TABLE *pCaTbl; + SMA_PORT_TABLE *pPortTbl; + SMA_CA_OBJ_PRIVATE *pCaObj; + SMA_PORT_TABLE_PRIV *pPortTblPriv; + uint32 i; + uint8 j = 0; + boolean bFound=FALSE; + + + _DBG_ENTER_LVL(_DBG_LVL_MGMT, GetGsiContextFromPortGuid); + + // + // Init variables + // + *Qp1Handle = NULL; + + SpinLockAcquire( &g_GsaGlobalInfo->CaListLock ); + + // + // This lookup can be converted to hash table on GUIDs + // + + pCaTbl = g_GsaGlobalInfo->SmObj.CaTbl; + + for ( i=0; iSmObj.NumCa; i++ ) + { + pPortTbl = pCaTbl->CaObj[i].PortTbl; + for ( j=0; jCaObj[i].Ports; j++ ) + { + if ( PortGuid == pPortTbl->PortBlock[j].GUID ) + { + bFound = TRUE; + break; + } + } // j + + if ( TRUE == bFound ) + break; + } // i + + if ( TRUE == bFound ) + { + pCaObj = (SMA_CA_OBJ_PRIVATE *)pCaTbl->CaObj[i].SmaCaContext; + pPortTblPriv = (SMA_PORT_TABLE_PRIV *)pCaObj->CaPublic.PortTbl; + + // + // Only post to Qp not in error or destroy state + // hardware will handle active and armed tests, by commenting out + // we allow a down port to still be used to talk to itself for + // applications using IB for local communications + // + if (/*( IB_PORT_ACTIVE == pPortTblPriv->PortBlock[j].Public.State + || IB_PORT_ARMED == pPortTblPriv->PortBlock[j].Public.State ) &&*/ \ + ( QP_NORMAL == pPortTblPriv->PortBlock[j].Qp1Control )) + { + *PortNumber = j + 1; + *Qp1Handle = pPortTblPriv->PortBlock[j].Qp1Handle; + } else { + //_DBG_ERROR(("Port 0x%"PRIx64" Not Active\n", PortGuid)); + status = FINVALID_STATE; + } + } + else + { + status = FINVALID_PARAMETER; + } + + SpinLockRelease( &g_GsaGlobalInfo->CaListLock ); + + _DBG_LEAVE_LVL(_DBG_LVL_MGMT); + return status; +} + +FSTATUS +DecrementGsiRecvQPostedForPortGuid( + IN EUI64 PortGuid, + OUT uint32 *RecvQPosted + ) +{ + FSTATUS status=FSUCCESS; + SMA_CA_TABLE *pCaTbl; + SMA_PORT_TABLE *pPortTbl; + SMA_CA_OBJ_PRIVATE *pCaObj; + SMA_PORT_TABLE_PRIV *pPortTblPriv; + uint32 i; + uint8 j = 0; + boolean bFound=FALSE; + + _DBG_ENTER_LVL(_DBG_LVL_MGMT, DecrementGsiRecvQPostedForPortGuid); + + SpinLockAcquire( &g_GsaGlobalInfo->CaListLock ); + + // This lookup can be converted to hash table on GUIDs + pCaTbl = g_GsaGlobalInfo->SmObj.CaTbl; + + for ( i=0; iSmObj.NumCa; i++ ) + { + pPortTbl = pCaTbl->CaObj[i].PortTbl; + for ( j=0; jCaObj[i].Ports; j++ ) + { + if ( PortGuid == pPortTbl->PortBlock[j].GUID ) + { + bFound = TRUE; + break; + } + } // j + + if ( TRUE == bFound ) + break; + } // i + + if ( TRUE == bFound ) + { + pCaObj = (SMA_CA_OBJ_PRIVATE *)pCaTbl->CaObj[i].SmaCaContext; + pPortTblPriv = (SMA_PORT_TABLE_PRIV *)pCaObj->CaPublic.PortTbl; + + *RecvQPosted = --pPortTblPriv->PortBlock[j].Qp1RecvQPosted; + status = FSUCCESS; + } else { + status = FINVALID_PARAMETER; + } + + SpinLockRelease( &g_GsaGlobalInfo->CaListLock ); + + _DBG_LEAVE_LVL(_DBG_LVL_MGMT); + return status; +} + +FSTATUS +PostRecvMsgToPort( + IN uint32 ElementCount, + IN EUI64 PortGuid + ) +{ + FSTATUS status = FSUCCESS; + uint32 i, j; + IBT_DGRM_ELEMENT *pDgrmList, *pDgrmListLink; + IBT_DGRM_ELEMENT_PRIV *pIbDgrmList; + IB_WORK_REQ workRequest; + + SMA_CA_TABLE *pCaTbl; + CA_MEM_LIST caMemList; + SMA_PORT_TABLE *pPortTbl; + SMA_CA_OBJ_PRIVATE *pCaObj; + uint8 k=0; + boolean bFound; + IB_HANDLE qp1Handle = NULL; + IB_HANDLE qp1CqHandle = NULL; + SPIN_LOCK *qpLock = NULL; + + + _DBG_ENTER_LVL(_DBG_LVL_MGMT, PostRecvMsgToPort); + + + // + // Get elements from Pool + // + i = ElementCount; + status = DgrmPoolGet( + g_GsaGlobalInfo->DgrmPoolRecvQ, + &i, + &pDgrmList ); + // + // post to qp + // + if ( status == FSUCCESS ) + { + SMA_PORT_TABLE_PRIV *pPortTblPriv = NULL; + + + if (i < ElementCount) + _DBG_WARN(("Gsi PostRecv: Only allocated %d, requested %d elements\n", i, ElementCount)); + + // + // Query PortGUID + // + + SpinLockAcquire( &g_GsaGlobalInfo->CaListLock ); + + pCaTbl = g_GsaGlobalInfo->SmObj.CaTbl; + + pCaObj = NULL; // init for parsing + bFound = FALSE; + + for ( j=0; jSmObj.NumCa; j++ ) + { + pPortTbl = pCaTbl->CaObj[j].PortTbl; + for ( k=0; kCaObj[j].Ports; k++ ) + { + if ( PortGuid == pPortTbl->PortBlock[k].GUID ) + { + pCaObj = \ + (SMA_CA_OBJ_PRIVATE *)pCaTbl->CaObj[j].SmaCaContext; + pPortTblPriv = \ + (SMA_PORT_TABLE_PRIV *)pCaObj->CaPublic.PortTbl; + bFound = TRUE; + break; + } + } // j + + if ( TRUE == bFound ) + { + qp1Handle = pPortTblPriv->PortBlock[k].Qp1Handle; + qp1CqHandle = pCaObj->Qp1CqHandle; + qpLock = &pPortTblPriv->PortBlock[k].QpLock; + + // + // Fail request if Qp is in error or destory state + // + if ( QP_DESTROY == pPortTblPriv->PortBlock[k].Qp1Control ) + bFound = FALSE; + + break; + } + } // i + + SpinLockRelease( &g_GsaGlobalInfo->CaListLock ); + + ASSERT( pCaObj ); + + if ( FALSE == bFound ) + { + _DBG_PRINT( + _DBG_LVL_MGMT,(\ + "An active Port could not be found OR" + "Qp in Error on Port(?%d?)!\n", + k+1)); + + DgrmPoolPut( pDgrmList ); + } + else if ((NULL != qp1Handle) && (NULL != qpLock)) + { + while ( i ) + { + pDgrmListLink = \ + (IBT_DGRM_ELEMENT *)pDgrmList->Element.pNextElement; + pDgrmList->Element.pNextElement = NULL; // delink + + // + // fill in work request details + // + + pIbDgrmList = (IBT_DGRM_ELEMENT_PRIV *)pDgrmList; + workRequest.DSList = pIbDgrmList->DsList; + workRequest.Operation = WROpRecv; + pDgrmList->OnRecvQ = TRUE; + + + // + // Input values to process upon recv + // + + pIbDgrmList->DgrmElement.PortGuid = PortGuid; + + // These lines added since Verbs does not return the Q_Key + pIbDgrmList->DgrmElement.RemoteQP = 1; + pIbDgrmList->DgrmElement.RemoteQKey = QP1_WELL_KNOWN_Q_KEY; + + + // + // get LKey and Memory handles + // + + + // + // Create GRH header + // + GetMemInfoFromCaMemTable( + pCaObj, + pIbDgrmList->MemPoolHandle->MemList->CaMemIndex, + &caMemList + ); + + + // + // Add GRH and Data in one header since data is contiguous + // + workRequest.DSList[0].Address = \ + (uintn)pIbDgrmList->DgrmElement.Element.pBufferList->pData; + workRequest.DSList[0].Length = sizeof(IB_GRH)+sizeof(MAD); + workRequest.DSList[0].Lkey = caMemList.LKey; + + workRequest.DSListDepth = 1; + + + workRequest.MessageLen = sizeof(IB_GRH) + sizeof(MAD); + + // + // set Id to request stucture to unload + // + + ASSERT_VALID_WORKREQID((uintn)pIbDgrmList); + workRequest.WorkReqId = BUILD_RQ_WORKREQID((uintn)pIbDgrmList); + + + // + // Post on Recv + // + + SpinLockAcquire( qpLock ); + + status = iba_post_recv( qp1Handle, &workRequest); + + SpinLockRelease( qpLock ); + if (status != FSUCCESS) + { + _DBG_ERROR(("PostRecvMsgToPort: iba_post_recv failed %s(%d)\n", + _DBG_PTR(FSTATUS_MSG(status)), status)); + pDgrmList->OnRecvQ = FALSE; + DgrmPoolPut( pDgrmList ); + if (pDgrmListLink) + DgrmPoolPut(pDgrmListLink); + break; + } + ++(pPortTblPriv->PortBlock[k].Qp1RecvQPosted); + _DBG_PRINT(_DBG_LVL_MGMT,("0x%"PRIx64": after post count of %u\n",PortGuid, pPortTblPriv->PortBlock[k].Qp1RecvQPosted)); + pDgrmList = pDgrmListLink; + i--; + } // i loop + } + else + { + _DBG_ERROR(("Failed to post to port - null pointers.\n")); + status = FERROR; + } + } else { + _DBG_ERROR(("PostRecvMsgToPort: No more elements in Pool for %d elements!!!\n",ElementCount)); + } + + GrowRecvQAsNeeded(); + + _DBG_LEAVE_LVL(_DBG_LVL_MGMT); + return status; + +} diff --git a/IbAccess/Common/Ibt/Gsa/gsasar1.c b/IbAccess/Common/Ibt/Gsa/gsasar1.c new file mode 100644 index 0000000..f2cee22 --- /dev/null +++ b/IbAccess/Common/Ibt/Gsa/gsasar1.c @@ -0,0 +1,2543 @@ +/* BEGIN_ICS_COPYRIGHT4 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT4 ****************************************/ + + +#include "gsamain.h" + +#if ! IB1_1 + +// 1.0a RMPP protocal Segmentation And Reassembly + +// +// Definitions +// + +//#define TEST_SAR_RECV_DISCARD 7 // enables discard for testing of retries/resend +#undef TEST_SAR_RECV_DISCARD + +#define GSA_SAR_MAX_RETRIES_SEND 10 +#define GSA_SAR_MAX_RETRIES_RECV 1 + +#define GSA_LARGEST_SAR_BLOCK 32 * 1024 +#define GSA_SAR_TIME_SEND 1000 * 2 + +#if defined(DBG) || defined(IB_DEBUG) + +#define GSA_SAR_TIME_RECV 300000 + +#else + +#define GSA_SAR_TIME_RECV 1250 + +#endif + +#ifdef ICS_LOGGING +#define _DBG_PRINT_SAR_HEADERS( LEVEL, TITLE, pSAR_MAD, REMOTE_LID) \ + do { \ + _DBG_PRINT (LEVEL, ( \ + TITLE \ + "\tClass..........:x%x\n" \ + "\tRemoteLID......:x%x\n" \ + "\tSegment........:%d\n" \ + "\tPayloadLen.....:%d bytes\n", \ + pSAR_MAD->common.MgmtClass, \ + REMOTE_LID, \ + pSAR_MAD->Sar.SegmentNum, \ + pSAR_MAD->Sar.PayloadLen \ + )); \ + _DBG_PRINT (LEVEL, ( \ + TITLE \ + "\tFragmentFlag...:\n" \ + "\t\tFirstPkt..:x%x\n" \ + "\t\tLastPkt...:x%x\n" \ + "\t\tKeepAlive.:x%x\n" \ + "\t\tResendReq.:x%x\n" \ + "\t\tAck.......:x%x\n", \ + (pSAR_MAD->Sar.FragmentFlag.F.FirstPkt), \ + (pSAR_MAD->Sar.FragmentFlag.F.LastPkt), \ + (pSAR_MAD->Sar.FragmentFlag.F.KeepAlive), \ + (pSAR_MAD->Sar.FragmentFlag.F.ResendReq), \ + (pSAR_MAD->Sar.FragmentFlag.F.Ack) \ + )); \ + } while (0) +#else +#define _DBG_PRINT_SAR_HEADERS( LEVEL, TITLE, pSAR_MAD, REMOTE_LID) \ + _DBG_PRINT (LEVEL, ( \ + TITLE \ + "\tClass..........:x%x\n" \ + "\tRemoteLID......:x%x\n" \ + "\tSegment........:%d\n" \ + "\tPayloadLen.....:%d bytes\n" \ + "\tFragmentFlag...:\n" \ + "\t\tFirstPkt..:x%x\n" \ + "\t\tLastPkt...:x%x\n" \ + "\t\tKeepAlive.:x%x\n" \ + "\t\tResendReq.:x%x\n" \ + "\t\tAck.......:x%x\n", \ + (uint8)pSAR_MAD->common.MgmtClass, \ + REMOTE_LID, \ + pSAR_MAD->Sar.SegmentNum, \ + pSAR_MAD->Sar.PayloadLen, \ + (uint8)(pSAR_MAD->Sar.FragmentFlag.F.FirstPkt), \ + (uint8)(pSAR_MAD->Sar.FragmentFlag.F.LastPkt), \ + (uint8)(pSAR_MAD->Sar.FragmentFlag.F.KeepAlive), \ + (uint8)(pSAR_MAD->Sar.FragmentFlag.F.ResendReq), \ + (uint8)(pSAR_MAD->Sar.FragmentFlag.F.Ack) \ + )) +#endif + +// RMPP Sender/Receiver Context +// for Segmentation and Reassembly of IBTA 1.0a RMPP messages +typedef struct _GSA_SAR_CONTEXT { + + // Common info + LIST_ITEM ListItem; + SPIN_LOCK Lock; // lock + + uint32 RetryCount; + boolean ResendSent; // Resend request has been sent + + uint32 TotalSegs; // total no. of segments + uint32 CurrSeg; // current seg. sent + uint32 TotalDataSize; // size of data + uint16 Window; // Timeout value for multipacket MAD + + TIMER TimerObj; + uint64 TID; // Client TID + SYS_CALLBACK_ITEM *SysCBItem; // Syscallback item + uint8 MgmtClass; + + // recv info + IBT_DGRM_ELEMENT *RecvHead; + IBT_DGRM_ELEMENT *RecvTail; + uint16 NextWindow; // Timeout value for multipacket MAD + + + // send info + GSA_POST_SEND_LIST *PostList; + IB_HANDLE Qp1Handle; + SPIN_LOCK *QpLock; + + IB_L_KEY LKey; + IB_WORK_REQ WorkRequest; + + IB_LOCAL_DATASEGMENT *DataSeg; // pointer to data segment + uintn DataStart; // start of data + + +} GSA_SAR_CONTEXT; + +// +// Function prototypes. +// +// --------------------------------------------------------------------------- +// RMPP Sender +FSTATUS +SARPost( + IN GSA_SAR_CONTEXT *pSarContext + ); + +boolean +ResendReqSARSend ( + IN MAD_SAR *pMadSar, + IN IBT_DGRM_ELEMENT **ppDgrm + ); + +boolean +AckReqSARSend( + IN MAD_SAR *pMadSar, + IN IBT_DGRM_ELEMENT **ppDgrm + ); + +void +SARCloseSend( + IN GSA_SAR_CONTEXT *pSarContext, + IN boolean callbackUser + ); + +void +TimerCallbackSend( + IN void *TimerContext + ); + +// --------------------------------------------------------------------------- +// RMPP Receiver + +boolean +IsRmppMethod( + IN MAD_SAR *pMadSarHdr + ); + +FSTATUS +CreateSARRecv( + IN IBT_DGRM_ELEMENT *pDgrm + ); + +FSTATUS +SARRecv( + IN IBT_DGRM_ELEMENT **ppDgrm + ); + +void +SARSendSegments( + IN void *Key, + IN void *TimerContext + ); + +void +FragmentOptionsSARRecv ( + IN IBT_DGRM_ELEMENT *pDgrm, + IN FRAGMENT_FLAG FragmentFlag, + IN uint64 TransactionID, + IN uint32 SegmentNum + ); + +boolean +KeepAliveSARRecv ( + IN MAD_SAR *pMadSar, + IN IBT_DGRM_ELEMENT **ppDgrm + ); + +void +SendAckSARRecv ( + IN IBT_DGRM_ELEMENT *pDgrm + ); + +void +ResendReqSARRecv ( + IN IBT_DGRM_ELEMENT *pDgrm, + IN uint64 TransactionID, + IN uint32 SegmentNum + ); + +void +TimerCallbackRecv( + IN void *TimerContext + ); + +void +DestroyGsaTimer ( + IN GSA_SAR_CONTEXT *pSarContext + ); + +FSTATUS +RemoveSARListEntry( + IN LIST_ITEM *ListItem + ); + +// --------------------------------------------------------------------------- +// Externally visible common functions used by GSA + +// Destroy Contexts for any SAR in progress. +// designed to only be called in GsaUnload +// since RemoveDevice already destroyed QPs, we will not end up with +// new work on the list +void +DestroySARContexts() +{ + GSA_SAR_CONTEXT* pSarContext; + + _DBG_ENTER_LVL (_DBG_LVL_SAR_INFO, DestroySARContexts ); + + // destroy sends in progress + SpinLockAcquire( &g_GsaGlobalInfo->SARSendListLock); + while ( NULL != (pSarContext = (GSA_SAR_CONTEXT*)QListHead( &g_GsaGlobalInfo->SARSendList ))) + { + // BUGBUG there are races in SARCloseSend since no locks are held + // while it is called, context could go away or race with + // a timer. IB1.1 is our focus, so this will not be fixed + + // must release list lock so Context can remove itself from list + SpinLockRelease( &g_GsaGlobalInfo->SARSendListLock); + // call with list lock unheld + SARCloseSend(pSarContext, FALSE); + SpinLockAcquire( &g_GsaGlobalInfo->SARSendListLock); + } + SpinLockRelease( &g_GsaGlobalInfo->SARSendListLock); + + // destroy receives in progress + SpinLockAcquire( &g_GsaGlobalInfo->SARRecvListLock); + while ( NULL != (pSarContext = (GSA_SAR_CONTEXT*)QListHead( &g_GsaGlobalInfo->SARRecvList ))) + { + // BUGBUG there are races in DestroyGsaTimer since no locks are held + // while it is called, context could go away or race with + // a timer. IB1.1 is our focus, so this will not be fixed + + // must release list lock so Context can remove itself from list + SpinLockRelease( &g_GsaGlobalInfo->SARRecvListLock); + DgrmPoolPut( pSarContext->RecvHead ); + DestroyGsaTimer( pSarContext ); + SpinLockAcquire( &g_GsaGlobalInfo->SARRecvListLock); + } + SpinLockRelease( &g_GsaGlobalInfo->SARRecvListLock); + _DBG_LEAVE_LVL(_DBG_LVL_SAR_INFO); +} + +// Completion Handlers shared by RMPP Receiver and Sender + +// called on GSI Receive Q completion callback when a packet is received which +// is destined to a GSI Client who has requested GSI to do the +// RMPP Segmentation and Assembly +// This can be called for RMPP Contexts which are Senders or Receivers +FSTATUS +ProcessSARRecvCompletion ( + IN MAD *pMad, + IN IBT_DGRM_ELEMENT **ppDgrm + ) +{ + FSTATUS status; + IBT_DGRM_ELEMENT_PRIV *pDgrmPrivate; + MAD_SAR *pMadSar = (MAD_SAR*)pMad; + + _DBG_ENTER_LVL (_DBG_LVL_SAR_INFO, ProcessSARRecvCompletion ); + + pDgrmPrivate = (IBT_DGRM_ELEMENT_PRIV *)*ppDgrm; + + // Overload base if it is SAR data for Coalesce API + pDgrmPrivate->Base++; + + BSWAP_SAR_HEADER( &pMadSar->Sar ); + _DBG_PRINT_SAR_HEADERS( (_DBG_LVL_CALLBACK + _DBG_LVL_SAR_INFO), + "SAR Recv Info:\n", pMadSar, pDgrmPrivate->DgrmElement.RemoteLID); + // + // Check for KeepAlive packets - Receiver Context + // + if (pMadSar->Sar.FragmentFlag.F.KeepAlive) + { + _DBG_PRINT(_DBG_LVL_SAR_INFO, ( + "KeepAlive packet received. Restart timer\n" + )); + + if (TRUE == KeepAliveSARRecv( pMadSar, ppDgrm )) + { + DgrmPoolPut( *ppDgrm ); + status = FPENDING; // Do not callback user + } + else + { + status = FCOMPLETED; // Not GSI managed. pass it on + } + } + else + if (pMadSar->Sar.FragmentFlag.F.ResendReq) + { + // Resend Request - Sender Context + _DBG_PRINT(_DBG_LVL_SAR_INFO, ( + "** Resend Request packet received at segment %d." + "Reset segment number request **\n", + pMadSar->Sar.SegmentNum + )); + + if (TRUE == ResendReqSARSend( pMadSar, ppDgrm )) + { + DgrmPoolPut( *ppDgrm ); + status = FPENDING; // Do not callback user + } + else + { + status = FCOMPLETED; // Not GSI managed. pass it on + } + } + else + if (pMadSar->Sar.FragmentFlag.F.Ack) + { + // Ack - Sender Context + _DBG_PRINT(_DBG_LVL_SAR_INFO, ( + "** Ack packet received at segment %d\n", + pMadSar->Sar.SegmentNum + )); + + if (TRUE == AckReqSARSend( pMadSar, ppDgrm )) + { + DgrmPoolPut( *ppDgrm ); + status = FPENDING; // Do not callback user + } + else + { + status = FCOMPLETED; // Not GSI managed. pass it on + } + }else + if ( pMadSar->Sar.SegmentNum > 1 ) // Is it the first segment? + { + // Additional Data Block - Receiver Context + // + // No. It is a segment reassembly in progress. + // Add this segment to the others already received. + // + status = SARRecv( ppDgrm ); + } + else + { + // + // First SAR Data Block - Receiver Context + // Does the data contain segmented payload? + // + if ( 0 == pMadSar->Sar.SegmentNum ) + { +#if defined(DBG) || defined(IB_DEBUG) + // validate fragment flag + if ( pMadSar->Sar.FragmentFlag.F.FirstPkt || \ + pMadSar->Sar.FragmentFlag.F.LastPkt ) + { + _DBG_ERROR(( + "Received BAD SAR Header:FragmentFlag!!! Forced receive\n")); + //status = FREJECT; + } +#endif + + // There's only a single segment to receive. We're done. + // payload cannot be validated, undefined for non-multipacket + _DBG_PRINT(_DBG_LVL_SAR_INFO, ( + "Only one segment to receive\n")); + status = FCOMPLETED; + + // Send Ack on this msg + SendAckSARRecv(*ppDgrm); + + } + else + { + // multi-packet SAR + // Segment should be == 1. validate FragmentFlag + + // FirstPacket and LastPacket are set to 1 (Vol1.M.2) + if (( 1 == pMadSar->Sar.FragmentFlag.F.FirstPkt ) && \ + ( 1 == pMadSar->Sar.FragmentFlag.F.LastPkt )) + { + // single packet SAR. + _DBG_PRINT(_DBG_LVL_SAR_INFO, ( + "Only one segment to receive\n")); + // validate PayloadLen, SA can send bad packets + if ( pMadSar->Sar.PayloadLen > MAD_SAR_DATA_SIZE) + { + _DBG_ERROR(( + "Received BAD SAR Header: Payload too large <%d>!!! \n", + pMadSar->Sar.PayloadLen)); + status = FREJECT; + } else { + status = FCOMPLETED; + + // Send Ack on this msg + SendAckSARRecv(*ppDgrm); + } + } + else + // FirstPacket should be one and Last packet should not be set + if (( 1 != pMadSar->Sar.FragmentFlag.F.FirstPkt ) || \ + pMadSar->Sar.FragmentFlag.F.LastPkt ) + { + _DBG_ERROR(( + "Received BAD SAR Header:FragmentFlag!!! \n")); + status = FREJECT; + } + else + { + // Validate payload length + if ( pMadSar->Sar.PayloadLen > MAD_SAR_DATA_SIZE) + { + // Start the reassembly. + status = CreateSARRecv( *ppDgrm ); + } + else + { + // The size is too small. + _DBG_ERROR(("Received BAD SAR Header: Payload too small <%d>!!! \n", + pMadSar->Sar.PayloadLen)); + status = FREJECT; + } + } // FragmentFlag + } // segment == 1 + } // segment > 1 + + _DBG_LEAVE_LVL(_DBG_LVL_SAR_INFO); + return status; +} + +// called on GSI Send Q completion callback when a packet is received which +// is destined to a GSI Client who has requested GSI to do the +// RMPP Segmentation and Assembly +// This can be called for RMPP Contexts which are Senders or Receivers +void +ProcessSARSendCompletion ( + IN MAD *pMad, + IN IBT_DGRM_ELEMENT *pDgrm + ) +{ + FSTATUS status; + IBT_DGRM_ELEMENT_PRIV *pDgrmPrivate; + GSA_POST_SEND_LIST *pPostList; + MAD_SAR *pMadSar = (MAD_SAR*)pMad; + + _DBG_ENTER_LVL (_DBG_LVL_SAR_INFO, ProcessSARSendCompletion ); + + pDgrmPrivate = (IBT_DGRM_ELEMENT_PRIV *)pDgrm; + pPostList = pDgrmPrivate->Base; + BSWAP_SAR_HEADER (&pMadSar->Sar); + + // Check for Ack msg sent on behalf of RMPP Receiver + if( (pMadSar->Sar.FragmentFlag.F.Ack || \ + pMadSar->Sar.FragmentFlag.F.ResendReq) ) + { +#if defined(DBG) || defined(IB_DEBUG) + _DBG_PRINT_SAR_HEADERS( (_DBG_LVL_CALLBACK + _DBG_LVL_SAR_INFO), + "SAR Ack/ResendReq packet send completed\n", + pMadSar, pDgrmPrivate->DgrmElement.RemoteLID); +#endif + ASSERT ( pDgrmPrivate->AvHandle ); + status = PutAV( + NULL, + pDgrmPrivate->AvHandle ); + + // Just return to pool + status = DgrmPoolPut( pPostList->DgrmList ); + goto done; + } + + // must have been a send completion on behalf of RMPP Sender + // BUGBUG - race, what if Gsi client deregisters before send completion? + ASSERT(((GSA_SERVICE_CLASS_INFO*)pDgrmPrivate->MemPoolHandle->ServiceHandle)->bSARRequired); + + // BUGBUG If the completion had an error, such as flush for + // unloading module, we may attempt to send SAR here + // we should handle this special case and return to + // user callback with an error indication + // maybe we are ok, as we will post sends and get failures + // until SAR is completed. + + _DBG_PRINT_SAR_HEADERS( (_DBG_LVL_CALLBACK + _DBG_LVL_SAR_INFO), + "SAR send completed:\n", + pMadSar, pDgrmPrivate->DgrmElement.RemoteLID); + + SysCallbackQueue( + pDgrmPrivate->pSarContext->SysCBItem, + SARSendSegments, + pDgrmPrivate->pSarContext, + FALSE ); + +done: + _DBG_LEAVE_LVL(_DBG_LVL_SAR_INFO); +} + +// --------------------------------------------------------------------------- +// RMPP Sender + +// +// DoSARSend +// +// Used by GsiPostSendDgrm to perform a send for a class which +// has requested Segmentation And Reassembly to be performed for it +// by GSI +// +// +// INPUTS: +// +// ServiceClass - The clients class info +// +// PostList - Post list info +// +// +// +// OUTPUTS: +// +// None +// +// +// +// RETURNS: +// +// FCANCELED - Segmentation not required, GsiPostSendDgrm should just send +// the single packet request +// FSUCCESS - Segmentation and transmission process has begun +// other - unable to start transmission +// +FSTATUS +DoSARSend( + IN GSA_SERVICE_CLASS_INFO *ServiceClass, + IN GSA_POST_SEND_LIST *PostList + ) +{ + FSTATUS status = FSUCCESS; + + uint32 sendSize; + IBT_DGRM_ELEMENT_PRIV *pDgrmPrivate; + MAD_COMMON *pMadHdr; + MULTI_PKT_HDR *pSARHdr; + IBT_BUFFER *pBuffer; + uint32 dgrmMsgSize, dgrmCount; + IB_HANDLE qp1Handle, cqHandle; + SPIN_LOCK *qpLock; + IB_L_KEY memLKey; + GSA_SAR_CONTEXT *pSarContext; + IB_WORK_REQ *pWorkRequest; + IB_ADDRESS_VECTOR avInfo; + + _DBG_ENTER_LVL (_DBG_LVL_SAR_INFO, DoSARSend); + + + // + // Get total send requests + // + + pDgrmPrivate = (IBT_DGRM_ELEMENT_PRIV *)PostList->DgrmList; + pDgrmPrivate->Base = PostList; // link for receives + + pMadHdr = + (MAD_COMMON *)GsiDgrmGetSendMad(&pDgrmPrivate->DgrmElement); + + pSARHdr = + (MULTI_PKT_HDR *)((uintn)pMadHdr + sizeof(MAD_COMMON)); + + sendSize = + pSARHdr->PayloadLen + sizeof(MAD_COMMON) + sizeof(MULTI_PKT_HDR); + + + // + // Validate user buffer size with payload + // + pBuffer = pDgrmPrivate->DgrmElement.Element.pBufferList; + dgrmMsgSize = 0; + + while ( NULL != pBuffer ) + { + dgrmMsgSize += pBuffer->ByteCount; + pBuffer = pBuffer->pNextBuffer; + } + + for ( ;; ) + { + if ( sendSize > dgrmMsgSize ) + { + _DBG_ERROR (( + "User passed Payload that overruns buffer!!!\n" + "\tMsg size.........:x%x\n" + "\tBuffer size......:x%x\n", + sendSize, + dgrmMsgSize )); + + status = FINVALID_PARAMETER; + break; + } + + // + // Calculate segments to send + // + dgrmCount = 1; + + if ( sendSize > sizeof(MAD) ) + { + sendSize -= (sizeof(MAD_COMMON) + sizeof(MULTI_PKT_HDR)); + + if (!( sendSize % MAD_SAR_DATA_SIZE)) + dgrmCount--; + + dgrmCount += ( sendSize / MAD_SAR_DATA_SIZE); + + _DBG_PRINT(_DBG_LVL_SAR_INFO,( + "SAR segments = %d\n", + dgrmCount )); + } + else + { + _DBG_PRINT(_DBG_LVL_SAR_INFO,( + "Only one SAR segment\n" )); + } + + // + // Init SAR Hdr + // + pSARHdr->SegmentNum = 0; + + pSARHdr->FragmentFlag.AsReg8 = 0; + pSARHdr->Window = 0; + + + // + // If there are multiple SAR segments go here + // + if ( dgrmCount == 1 ) + { + status = FCANCELED; + _DBG_PRINT(_DBG_LVL_SAR_INFO,( + "No SAR required. Do a normal send\n" )); + + break; + } + + // send one at a time + PostList->DgrmIn = 1; + PostList->SARRequest = TRUE; + + // + // Fill in Address Vector Info + // + avInfo.PortGUID = pDgrmPrivate->DgrmElement.PortGuid; + avInfo.DestLID = pDgrmPrivate->DgrmElement.RemoteLID; + avInfo.PathBits = pDgrmPrivate->DgrmElement.PathBits; + avInfo.ServiceLevel = pDgrmPrivate->DgrmElement.ServiceLevel; + avInfo.StaticRate = pDgrmPrivate->DgrmElement.StaticRate; + avInfo.GlobalRoute = pDgrmPrivate->DgrmElement.GlobalRoute; + + if ( TRUE == avInfo.GlobalRoute ) + { + /* structure assignment */ + avInfo.GlobalRouteInfo = pDgrmPrivate->DgrmElement.GRHInfo; + } + + // + // Query transport specific info for all segments in one go + // + status = GetCaContextFromAvInfo( + &avInfo, + pDgrmPrivate->MemPoolHandle->MemList->CaMemIndex, + &pDgrmPrivate->AvHandle, + &qp1Handle, + &cqHandle, + &qpLock, + &memLKey ); + + if ( FSUCCESS != status ) + { + _DBG_ERROR (( + "Error in GetCaContextFromAvInfo()\n" )); + break; + } + + // + // If this is a request, save the user's transaction id + // and use our own. We will restore the user's transaction id + // when the request completes. If this is a response, we need to + // respond with the given transaction id, so that the remote side + // can match it with its original request. + if (MAD_IS_REQUEST((MAD*)pMadHdr)) + { + pMadHdr->TransactionID = (uint64)\ + (pMadHdr->TransactionID & 0xffffffffffffff00ll); + pMadHdr->TransactionID = \ + pMadHdr->TransactionID | ServiceClass->ClientId; + } + + pSarContext = (GSA_SAR_CONTEXT*)MemoryAllocateAndClear(sizeof(GSA_SAR_CONTEXT), FALSE, GSA_MEM_TAG); + if ( NULL == pSarContext ) + { + status = FINSUFFICIENT_RESOURCES; + _DBG_ERROR (( + "Not enough memory for Sar Context info!\n" )); + break; + } + + // + // Init Lock and Timer + // + SpinLockInitState( &pSarContext->Lock ); + SpinLockInit( &pSarContext->Lock ); + + TimerInitState(&pSarContext->TimerObj); + if (TRUE != TimerInit( + &pSarContext->TimerObj, + TimerCallbackSend, + pSarContext )) + { + status = FINSUFFICIENT_RESOURCES; + _DBG_ERROR (( + "TimerInit failed!\n" )); + + SpinLockDestroy( &pSarContext->Lock ); + MemoryDeallocate( pSarContext ); + break; + } + + // + // setup other fields + // + pSarContext->TotalSegs = dgrmCount; + pSarContext->CurrSeg = 0; + + pSarContext->TID = pMadHdr->TransactionID; + pSarContext->MgmtClass = pMadHdr->MgmtClass; + + pSarContext->Qp1Handle = qp1Handle; + pSarContext->QpLock = qpLock; + pSarContext->PostList = PostList; + + pBuffer = pDgrmPrivate->DgrmElement.Element.pBufferList; + + pSarContext->TotalDataSize = pSARHdr->PayloadLen; + pSarContext->DataStart = + (uintn)(pBuffer->pData) + \ + sizeof(MAD_COMMON) + \ + sizeof(MULTI_PKT_HDR); + + _DBG_PRINT (_DBG_LVL_SAR_INFO,( + "SAR Payload Length = x%x bytes\n",pSarContext->TotalDataSize )); + + // + // Format SAR header + // + pSARHdr->SegmentNum = 0; + pSARHdr->FragmentFlag.AsReg8 = 0; + pSARHdr->FragmentFlag.F.FirstPkt = 1; + + // + // Pre create work request since it is common for all segments + // + pWorkRequest = &pSarContext->WorkRequest; + + ASSERT_VALID_WORKREQID((uintn)pDgrmPrivate); + pWorkRequest->WorkReqId = BUILD_SQ_WORKREQID((uintn)pDgrmPrivate); + + // + // SAR will Always be 3: MAD_COMMON, SAR_HDR, DATA + // + pWorkRequest->DSListDepth = 3; + + pWorkRequest->DSList = pDgrmPrivate->DsList; + pWorkRequest->Req.SendUD.AVHandle = pDgrmPrivate->AvHandle; + + pWorkRequest->Operation = WROpSend; + + // zero out the options + pWorkRequest->Req.SendUD.Options.AsUINT16 = 0; + + pWorkRequest->Req.SendUD.Options.s.SignaledCompletion = TRUE; + + //pWorkRequest->Req.SendUD.Qkey = pDgrmPrivate->DgrmElement.RemoteQKey; + pWorkRequest->Req.SendUD.QPNumber = pDgrmPrivate->DgrmElement.RemoteQP; + pWorkRequest->Req.SendUD.Qkey = QP1_WELL_KNOWN_Q_KEY; + +#if defined(DBG) || defined(IB_DEBUG) + + if (!pWorkRequest->Req.SendUD.QPNumber) + { + AtomicIncrementVoid( &ServiceClass->ErrorMsgs ); + + if (!(AtomicRead(&ServiceClass->ErrorMsgs) % 20)) + { + _DBG_ERROR(( + "Invalid QPNumber/Q_Key(substitution provided):\n" + "\tClass...........:x%x\n" + "\tResponder.......:%s\n" + "\tTrapProcessor...:%s\n" + "\tReportProcessor.:%s\n" + "\tSARClient.......:%s\n" + "\tQPNumber........:x%x\n" + "\tQ_Key...........:x%x\n", + ServiceClass->MgmtClass, + GSI_IS_RESPONDER(ServiceClass->RegistrationFlags) + ? "TRUE":"FALSE", + GSI_IS_TRAP_PROCESSOR(ServiceClass->RegistrationFlags) + ? "TRUE":"FALSE", + GSI_IS_REPORT_PROCESSOR(ServiceClass->RegistrationFlags) + ? "TRUE":"FALSE", + ServiceClass->bSARRequired ? "TRUE":"FALSE", + pWorkRequest->Req.SendUD.QPNumber, + pWorkRequest->Req.SendUD.Qkey + )); + } + + pWorkRequest->Req.SendUD.Qkey = QP1_WELL_KNOWN_Q_KEY; + pWorkRequest->Req.SendUD.QPNumber = 1; + } + + if (pWorkRequest->Req.SendUD.QPNumber != 1) + { + _DBG_ERROR(( + "Send to RedirectedQP\n" + "\tQPNumber.....:x%x\n", + pWorkRequest->Req.SendUD.QPNumber + )); + } + +#endif + + // + // fill in scatter/gather DS list details + // + pWorkRequest->MessageLen = 0; + + // + // Fill in MAD Common info + // + pWorkRequest->DSList[0].Address = (uintn)pBuffer->pData; + pWorkRequest->DSList[0].Lkey = memLKey; + pWorkRequest->DSList[0].Length = sizeof(MAD_COMMON); + + // + // Fill in SAR Header info + // + pWorkRequest->DSList[1].Address = \ + (uintn)(pBuffer->pData) + sizeof(MAD_COMMON); + pWorkRequest->DSList[1].Lkey = memLKey; + pWorkRequest->DSList[1].Length = sizeof(MULTI_PKT_HDR); + + // + // Fill in Data info + // + pWorkRequest->DSList[2].Lkey = memLKey; + + pSarContext->DataSeg = &pWorkRequest->DSList[2]; + + // + // TBD: Add to master SAR send list + // + SpinLockAcquire( &g_GsaGlobalInfo->SARSendListLock ); + + QListInsertHead( + &g_GsaGlobalInfo->SARSendList, + &pSarContext->ListItem ); + + SpinLockRelease( &g_GsaGlobalInfo->SARSendListLock ); + + // + // Add timer to Dgrm internal list + // + pDgrmPrivate->pSarContext = pSarContext; + + pSarContext->SysCBItem = SysCallbackGet( + IbtGlobal.DeviceObject ); + if ( NULL == pSarContext->SysCBItem ) + { + status = FINSUFFICIENT_RESOURCES; + TimerDestroy( &pSarContext->TimerObj ); + SpinLockDestroy( &pSarContext->Lock ); + MemoryDeallocate ( pSarContext ); + _DBG_ERROR (( + "SysCallback Create failed! Dropping SAR send req.\n" )); + break; + } + + SARPost(pSarContext); + break; + } // for loop + + _DBG_LEAVE_LVL(_DBG_LVL_SAR_INFO); + return status; +} + + +FSTATUS +SARPost( + IN GSA_SAR_CONTEXT *pSarContext + ) +{ + FSTATUS status =FSUCCESS; + IBT_DGRM_ELEMENT_PRIV *pDgrmPrivate; + IB_LOCAL_DATASEGMENT *pDsList; + IB_WORK_REQ *pWorkRequest; + MULTI_PKT_HDR *pSARHdr; + uint32 bytesSent, bytesToSend; + + _DBG_ENTER_LVL (_DBG_LVL_SAR_INFO, SARPost); + + + SpinLockAcquire( &pSarContext->Lock ); + + pDgrmPrivate = + (IBT_DGRM_ELEMENT_PRIV *)pSarContext->PostList->DgrmList; + + pWorkRequest = &pSarContext->WorkRequest; + pSARHdr = \ + (MULTI_PKT_HDR *)((uintn)pWorkRequest->DSList[1].Address); + + // + // Calculate bytes to be sent + // + pDsList = pSarContext->DataSeg; + + bytesSent = pSarContext->CurrSeg * MAD_SAR_DATA_SIZE; + bytesToSend = pSarContext->TotalDataSize - bytesSent; + + pDsList->Address = pSarContext->DataStart + bytesSent; + pDsList->Length = MAD_SAR_DATA_SIZE; + + pWorkRequest->MessageLen= pDsList->Length + \ + sizeof(MAD_COMMON) + sizeof(MULTI_PKT_HDR); + + + // + // Check to see if we have multiple segments + // + if ( 0 != pSarContext->CurrSeg ) + { + pSARHdr->FragmentFlag.F.FirstPkt = 0; + + if ( pSarContext->CurrSeg+1 == pSarContext->TotalSegs ) + pSARHdr->FragmentFlag.F.LastPkt = 1; + } + else + { + // + // First segment. Validate payload needs multi segments + // + pSARHdr->FragmentFlag.F.FirstPkt = 1; + } + + AtomicIncrementVoid( &pSarContext->CurrSeg ); // advance to next level + pSARHdr->SegmentNum = pSarContext->CurrSeg; + + _DBG_PRINT (_DBG_LVL_SAR_INFO,( + "SAR Header Info:\n" + "\tPayloadLen...:%d bytes\n" + "\tSegment......:%d\n", + pSARHdr->PayloadLen, + pSARHdr->SegmentNum + )); + _DBG_PRINT (_DBG_LVL_SAR_INFO,( + "SAR Header Info (cont):\n" + "\tFragmentFlag.:\n" + "\t\tFirstPkt..:x%x\n" + "\t\tLastPkt...:x%x\n" + "\t\tKeepAlive.:x%x\n" + "\t\tResendReq.:x%x\n" + "\t\tAck.......:x%x\n", + (uint8)(pSARHdr->FragmentFlag.F.FirstPkt), + (uint8)(pSARHdr->FragmentFlag.F.LastPkt), + (uint8)(pSARHdr->FragmentFlag.F.KeepAlive), + (uint8)(pSARHdr->FragmentFlag.F.ResendReq), + (uint8)(pSARHdr->FragmentFlag.F.Ack) + )); + + AtomicWrite(&pSarContext->PostList->DgrmOut, 0); + + pSarContext->RetryCount = 0; + pSarContext->ResendSent = FALSE; + + // + // Byte order headers + // + BSWAP_MAD_HEADER ( (MAD*)((uintn)pWorkRequest->DSList[0].Address) ); + + BSWAP_SAR_HEADER ( pSARHdr ); + + + // + // Submit to verbs + // + SpinLockAcquire( pSarContext->QpLock ); + + status = iba_post_send( pSarContext->Qp1Handle, pWorkRequest ); + + SpinLockRelease( pSarContext->QpLock ); + + SpinLockRelease( &pSarContext->Lock ); + + _DBG_LEAVE_LVL (_DBG_LVL_SAR_INFO); + return status; +} + + +boolean +ResendReqSARSend( + IN MAD_SAR *pMadSar, + IN IBT_DGRM_ELEMENT **ppDgrm + ) +{ + IBT_DGRM_ELEMENT *pDgrm; + GSA_SAR_CONTEXT *pSarContext= NULL; + boolean bStatus = FALSE; + + LIST_ITEM *pListFirst, *pListNext; + + _DBG_ENTER_LVL (_DBG_LVL_SAR_INFO, ResendReqSARSend); + + + for ( ;; ) + { + pDgrm = *ppDgrm; + + _DBG_PRINT (_DBG_LVL_SAR_INFO,( + "Need to find TID x%"PRIx64"\n", + pMadSar->common.TransactionID )); + + SpinLockAcquire( &g_GsaGlobalInfo->SARSendListLock ); + + pListFirst = QListHead( &g_GsaGlobalInfo->SARSendList ); + + if ( pListFirst ) + { + pSarContext=NULL; + + while ( pListFirst ) + { + // + // Dump debug info + // + _DBG_PRINT (_DBG_LVL_SAR_INFO,( + "...TID %"PRIx64"\n", + ((GSA_SAR_CONTEXT*)pListFirst)->TID )); + + // + // IB defines a message as unique by the combination of + // + IB_GID from the GRH ( if applicable) TBD + // + SourceLID + // + TransactionID + // + + // NOTE:This check will only fail if 2 receives arrive + // from the same source on the same LID and the + // TransactionID is the same. + // Clients issuing multiple requests to a class + // manager at the same time must pass in unique TIDs + + if (( ((GSA_SAR_CONTEXT*)pListFirst)->TID == pMadSar->common.TransactionID ) && + ( ((GSA_SAR_CONTEXT*)pListFirst)->MgmtClass == pMadSar->common.MgmtClass ) && + ( ((GSA_SAR_CONTEXT *)pListFirst)->PostList->DgrmList->RemoteLID == pDgrm->RemoteLID )) + { + pSarContext = (GSA_SAR_CONTEXT *)pListFirst; + + SpinLockAcquire( &pSarContext->Lock ); + + // Reset Segment number to request + pSarContext->CurrSeg = pMadSar->Sar.SegmentNum-1; + + SpinLockRelease( &pSarContext->Lock ); + + bStatus = TRUE; + _DBG_PRINT (_DBG_LVL_SAR_INFO,( + "Timer restarted\n" )); + break; + } + + // + // Walk entire chain of devices + // + + pListNext = QListNext( + &g_GsaGlobalInfo->SARSendList, + pListFirst ); + + pListFirst = pListNext; + + } // while 1 + + // + // This is how we find the end of the list + // + _DBG_PRINT (_DBG_LVL_SAR_INFO,( + "Reached end of List\n" )); + } + + + // + // Release the lock that we acquired earlier + // + SpinLockRelease(&g_GsaGlobalInfo->SARSendListLock); + break; + + } // for loop + + _DBG_LEAVE_LVL(_DBG_LVL_SAR_INFO); + return (bStatus); +} + + +boolean +AckReqSARSend( + IN MAD_SAR *pMadSar, + IN IBT_DGRM_ELEMENT **ppDgrm + ) +{ + IBT_DGRM_ELEMENT *pDgrm; + GSA_SAR_CONTEXT *pSarContext= NULL; + boolean bStatus = FALSE; + + LIST_ITEM *pListFirst, *pListNext; + + _DBG_ENTER_LVL (_DBG_LVL_SAR_INFO, AckReqSARSend); + + + for ( ;; ) + { + pDgrm = *ppDgrm; + + _DBG_PRINT (_DBG_LVL_SAR_INFO,( + "Need to find TID x%"PRIx64"\n", + pMadSar->common.TransactionID )); + + SpinLockAcquire( &g_GsaGlobalInfo->SARSendListLock ); + + pListFirst = QListHead( &g_GsaGlobalInfo->SARSendList ); + + if ( pListFirst ) + { + pSarContext=NULL; + + while ( pListFirst ) + { + // + // Dump debug info + // + _DBG_PRINT (_DBG_LVL_SAR_INFO,( + "...TID %"PRIx64"\n", + ((GSA_SAR_CONTEXT *)pListFirst)->TID )); + + // + // IB defines a message as unique by the combination of + // + IB_GID from the GRH ( if applicable) TBD + // + SourceLID + // + TransactionID + // + + // NOTE:This check will only fail if 2 receives arrive + // from the same source on the same LID and the + // TransactionID is the same. + // Clients issuing multiple requests to a class + // manager at the same time must pass in unique TIDs + + if (( ((GSA_SAR_CONTEXT *)pListFirst)->TID == pMadSar->common.TransactionID ) && + ( ((GSA_SAR_CONTEXT *)pListFirst)->MgmtClass == pMadSar->common.MgmtClass ) && + ( ((GSA_SAR_CONTEXT *)pListFirst)->PostList->DgrmList->RemoteLID == pDgrm->RemoteLID )) + { + pSarContext = (GSA_SAR_CONTEXT *)pListFirst; + + SpinLockAcquire( &pSarContext->Lock ); + + // Close send timer + if ( pSarContext->TotalSegs == pSarContext->CurrSeg ) + { + SpinLockRelease( &pSarContext->Lock ); + SARCloseSend(pSarContext, TRUE); + } + else + { + // we never asked for this Ack, do nothing + SpinLockRelease( &pSarContext->Lock ); + } + + bStatus = TRUE; + _DBG_PRINT (_DBG_LVL_SAR_INFO,( + "Timer killed with Ack\n" )); + break; + } + + // + // Walk entire chain of devices + // + + pListNext = QListNext( + &g_GsaGlobalInfo->SARSendList, + pListFirst ); + + pListFirst = pListNext; + + } // while 1 + + // + // This is how we find the end of the list + // + _DBG_PRINT (_DBG_LVL_SAR_INFO,( + "Reached end of List\n" )); + } + else + { + // + // This list has already gone away. + // We return TRUE since SAR client. + // + bStatus = TRUE; // TBD BUGBUG - in consistent with not on list case + _DBG_PRINT (_DBG_LVL_SAR_INFO,( + "Info not in list. Delete anyway since SAR client\n" )); + } + + + // + // Release the lock that we acquired earlier + // + SpinLockRelease(&g_GsaGlobalInfo->SARSendListLock); + break; + + } // for loop + + _DBG_LEAVE_LVL(_DBG_LVL_SAR_INFO); + return (bStatus); +} + +// +// Close SAR send created +// +// + Destoy retry timer +// + Destroy AV +// + Destroy Syscallback +// + Call user or dump Dgrm +// + Free timer pool +// +void +SARCloseSend( + IN GSA_SAR_CONTEXT *pSarContext, + IN boolean callbackUser + ) +{ + IBT_DGRM_ELEMENT_PRIV *pDgrmPrivate; + GSA_SERVICE_CLASS_INFO *classInfo; + + _DBG_ENTER_LVL (_DBG_LVL_SAR_INFO, SARCloseSend); + + pDgrmPrivate = + (IBT_DGRM_ELEMENT_PRIV *)pSarContext->PostList->DgrmList; + + _DBG_PRINT (_DBG_LVL_SAR_INFO, + ("*** Killing Send retry timer ***\n")); + + TimerStop( &pSarContext->TimerObj ); // stop timer before destroy + TimerDestroy( &pSarContext->TimerObj ); // Destroy stops timer too + + PutAV( + NULL, + pDgrmPrivate->AvHandle ); + + // + // Remove from global list + // + SpinLockAcquire( &g_GsaGlobalInfo->SARSendListLock ); + + ASSERT (QListIsItemInList( + &g_GsaGlobalInfo->SARSendList, + &pSarContext->ListItem )); + + + if ( !QListIsItemInList( + &g_GsaGlobalInfo->SARSendList, + &pSarContext->ListItem )) + { + _DBG_ERROR(("Item not in Send List!!!\n")); + } + else + { + QListRemoveItem ( + &g_GsaGlobalInfo->SARSendList, + &pSarContext->ListItem ); + } + + SpinLockRelease(&g_GsaGlobalInfo->SARSendListLock); + + // + // CallUser + // + if (callbackUser) + { + classInfo = pDgrmPrivate->MemPoolHandle->ServiceHandle; + if ( classInfo->SendCompletionCallback ) + { + (classInfo->SendCompletionCallback)( classInfo->ServiceClassContext, + &pDgrmPrivate->DgrmElement ); + } else { + // return to pool + _DBG_PRINT (_DBG_LVL_SAR_INFO, ( + "No Class Agent for this SAR msg!\n")); + DgrmPoolPut( &pDgrmPrivate->DgrmElement ); + } + } else { + DgrmPoolPut( &pDgrmPrivate->DgrmElement ); + } + + SpinLockDestroy( &pSarContext->Lock ); // lock + SysCallbackPut( pSarContext->SysCBItem ); + MemoryDeallocate ( pSarContext ); + + _DBG_LEAVE_LVL(_DBG_LVL_SAR_INFO); + +} // SARCloseSend + + + + +// +// Callback invoked on SAR sends +// +// + There are no retires for send. +// + Completions for ISR callbacks trigger next send of segement. +// + Timer is fired after last send +// +void +SARSendSegments( + IN void *Key, + IN void *TimerContext + ) +{ + GSA_SAR_CONTEXT *pSarContext; + IBT_DGRM_ELEMENT_PRIV *pDgrmPrivate; + + + _DBG_ENTER_LVL (_DBG_LVL_SAR_INFO, SARSendSegments); + + pSarContext = TimerContext; + pDgrmPrivate = + (IBT_DGRM_ELEMENT_PRIV *)pSarContext->PostList->DgrmList; + + // + // Verify last completion status + // + if ( FSUCCESS != pDgrmPrivate->DgrmElement.Element.Status ) + { + _DBG_PRINT (_DBG_LVL_SAR_INFO, + ("*** Failed SAR send! Killing retry timer ***\n")); + + SARCloseSend( pSarContext, TRUE ); + } + else + { + // + // Are we in the last segment? + // + if ( pSarContext->TotalSegs == pSarContext->CurrSeg ) + { + _DBG_PRINT (_DBG_LVL_SAR_INFO, + ("*** Kicking off retry timer ***\n")); + + // + // Fire timer for retires and deliveries + // + TimerStart( &pSarContext->TimerObj, GSA_SAR_TIME_SEND ); + } + else + { + SARPost(pSarContext); + } + } + + _DBG_LEAVE_LVL (_DBG_LVL_SAR_INFO); + +} // SARSendSegments + + +// +// Timer callback invoked on SAR sends +// +// + Here the retry counter will stop posts if there is no completion. +// + The timer waits for the Isr routine's callback to update the send +// completions +// +void +TimerCallbackSend( + IN void *TimerContext + ) +{ + GSA_SAR_CONTEXT *pSarContext; + + + _DBG_ENTER_LVL (_DBG_LVL_SAR_INFO, TimerCallbackSend); + + pSarContext = TimerContext; + SARCloseSend( pSarContext, TRUE ); + + _DBG_LEAVE_LVL (_DBG_LVL_SAR_INFO); +} + + + +// --------------------------------------------------------------------------- +// RMPP Receiver + +boolean +IsRmppMethod( + IN MAD_SAR *pMadSarHdr + ) +{ + switch (pMadSarHdr->common.mr.AsReg8) + { + default: + return FALSE; + break; // do nothing + + case 0x92: // SubnAdminGetTableResp() + case 0x14: // SubnAdminGetMulti() + case 0x94: // SubnAdminGetMultiResp() + + return TRUE; + break; + } +} + +// +// Create SAR Timer for recv +// +FSTATUS +CreateSARRecv( + IN IBT_DGRM_ELEMENT *pDgrm + ) +{ + FSTATUS status; + MAD_SAR *pMadSARHdr; + GSA_SAR_CONTEXT *pSarContext; + + _DBG_ENTER_LVL (_DBG_LVL_SAR_INFO, CreateSARRecv); + + pMadSARHdr = (MAD_SAR *)GsiDgrmGetRecvMad(pDgrm); + + for ( ;; ) + { + // + // Inspect SAR received block for sanity + // + if ( pMadSARHdr->Sar.PayloadLen > GSA_LARGEST_SAR_BLOCK ) + { + _DBG_ERROR (( + "SAR Header contains a very large Payload(%d bytes)!\n" + "GSA Max payload setting (%d bytes) \n", + pMadSARHdr->Sar.PayloadLen, + GSA_LARGEST_SAR_BLOCK )); + + status = FREJECT; + break; + } + + if (( pMadSARHdr->Sar.PayloadLen > MAD_SAR_DATA_SIZE) && + ( pDgrm->TotalRecvSize < + (sizeof(IB_GRH) + sizeof(MAD_COMMON) + sizeof(MULTI_PKT_HDR)) )) + { + _DBG_ERROR (( + "Inconsistent SAR Header! \n" + "\tPayload in Hdr......:%d bytes\n" + "\tPayload received....:%d bytes\n", + pMadSARHdr->Sar.PayloadLen, + pDgrm->TotalRecvSize - \ + (sizeof(IB_GRH) + sizeof(MAD_COMMON) + sizeof(MULTI_PKT_HDR)) )); + + status = FREJECT; + break; + } + + + // + // Create Timer info + // + pSarContext = (GSA_SAR_CONTEXT*)MemoryAllocateAndClear(sizeof(GSA_SAR_CONTEXT), FALSE, GSA_MEM_TAG); + if ( NULL == pSarContext ) + { + _DBG_ERROR (( + "Not enough memory for Timer info! \n")); + status = FREJECT; + break; + } + + + // + // Init Lock and Timer + // + TimerInitState(&pSarContext->TimerObj); + if (TRUE != TimerInit( &pSarContext->TimerObj, + TimerCallbackRecv, + pSarContext )) + { + _DBG_ERROR (( + "TimerInit failed! \n" )); + MemoryDeallocate ( pSarContext ); + status = FREJECT; + break; + } + + + SpinLockInitState( &pSarContext->Lock ); + SpinLockInit( &pSarContext->Lock ); + + // + // setup other fields + // + pSarContext->TotalSegs = (pMadSARHdr->Sar.PayloadLen +MAD_SAR_DATA_SIZE-1)/ MAD_SAR_DATA_SIZE; + pSarContext->MgmtClass = pMadSARHdr->common.MgmtClass; + pSarContext->CurrSeg = 1; // already received one + pSarContext->TID = pMadSARHdr->common.TransactionID; + pSarContext->RecvHead = pSarContext->RecvTail = pDgrm; + pSarContext->TotalDataSize = pMadSARHdr->Sar.PayloadLen; + pSarContext->Window = pMadSARHdr->Sar.Window; + + if (pSarContext->Window) + { + if (pSarContext->Window <64) + pSarContext->Window = 64; + + pSarContext->NextWindow = pSarContext->Window; + pSarContext->NextWindow--; + } + + _DBG_PRINT (_DBG_LVL_SAR_INFO,( + "SAR Payload Length = x%x bytes\n", + pSarContext->TotalDataSize )); + + // remove clientid from TID + if (MAD_IS_RESPONSE((MAD*)pMadSARHdr)) + { + pMadSARHdr->common.TransactionID = (uint64)\ + (pMadSARHdr->common.TransactionID & 0xffffffffffffff00ll); + } + + // + // Add to Global SAR recv list + // + SpinLockAcquire( &g_GsaGlobalInfo->SARRecvListLock ); + + QListInsertHead( + &g_GsaGlobalInfo->SARRecvList, + &pSarContext->ListItem ); + + SpinLockRelease( &g_GsaGlobalInfo->SARRecvListLock ); + + // + // Start the timer to alert at the specified time. + // + if( !TimerStart( &pSarContext->TimerObj, GSA_SAR_TIME_RECV ) ) + { + _DBG_ERROR (( + "Error in Timer Start! \n")); + + SpinLockDestroy( &pSarContext->Lock ); + TimerDestroy( &pSarContext->TimerObj ); + + // + // Eject from Global SAR Q + // + RemoveSARListEntry( &pSarContext->ListItem ); + MemoryDeallocate ( pSarContext ); + status = FREJECT; + break; + } + + status = FPENDING; + break; + } // for loop + + _DBG_LEAVE_LVL(_DBG_LVL_SAR_INFO); + return status; +} + + +FSTATUS +SARRecv( + IN IBT_DGRM_ELEMENT **ppDgrm + ) +{ + IBT_DGRM_ELEMENT *pDgrm; + FSTATUS status; + GSA_SAR_CONTEXT *pSarContext= NULL; + + MAD_SAR *pMadSARHdr; + LIST_ITEM *pListFirst, *pListNext; + boolean bAckSent = FALSE; +#ifdef TEST_SAR_RECV_DISCARD + static int discard_counter = 0; +#endif + + _DBG_ENTER_LVL (_DBG_LVL_SAR_INFO, SARRecv); + + + for ( ;; ) + { + pDgrm = *ppDgrm; + pMadSARHdr = (MAD_SAR *)GsiDgrmGetRecvMad(pDgrm); + + _DBG_PRINT (_DBG_LVL_SAR_INFO,( + "Need to find TID x%"PRIx64"\n", + pMadSARHdr->common.TransactionID )); + + SpinLockAcquire( &g_GsaGlobalInfo->SARRecvListLock ); + + pListFirst = QListHead( &g_GsaGlobalInfo->SARRecvList ); + + if ( !pListFirst ) + { + // + // the list is empty + // +#ifdef TEST_SAR_RECV_DISCARD + _DBG_ERROR(("Empty Global List")); +#endif + _DBG_WARN(( + "Unexpected SAR Packet: No Entries in Global List! \n" + "\tClass........:x%x\n" + "\tAttributeID..:x%x\n" + "\tTID..........:x%"PRIx64"\n" + "\tSegment......:%d\n" + "\tPayloadLen...:%d bytes\n", + (uint8)pMadSARHdr->common.MgmtClass, + pMadSARHdr->common.AttributeID, + pMadSARHdr->common.TransactionID, + pMadSARHdr->Sar.SegmentNum, + pMadSARHdr->Sar.PayloadLen + )); + _DBG_WARN(( + "Unexpected SAR Packet: No Entries in Global List! (cont)\n" + "\tFragmentFlag.:\n" + "\t\tFirstPkt..:x%x\n" + "\t\tLastPkt...:x%x\n" + "\t\tKeepAlive.:x%x\n" + "\t\tResendReq.:x%x\n" + "\t\tAck.......:x%x\n", + (uint8)(pMadSARHdr->Sar.FragmentFlag.F.FirstPkt), + (uint8)(pMadSARHdr->Sar.FragmentFlag.F.LastPkt), + (uint8)(pMadSARHdr->Sar.FragmentFlag.F.KeepAlive), + (uint8)(pMadSARHdr->Sar.FragmentFlag.F.ResendReq), + (uint8)(pMadSARHdr->Sar.FragmentFlag.F.Ack) + )); + } + else + { + pSarContext=NULL; + + while ( pListFirst ) + { + // + // Dump debug info + // + _DBG_PRINT (_DBG_LVL_SAR_INFO,( + "...TID %"PRIx64"\n", + ((GSA_SAR_CONTEXT *)pListFirst)->TID )); + + // + // IB defines a message as unique by the combination of + // + IB_GID from the GRH ( if applicable) TBD + // + SourceLID + // + TransactionID + // + + // NOTE:This check will only fail if 2 receives arrive + // from the same source on the same LID and the + // TransactionID is the same. + // Clients issuing multiple requests to a class + // manager at the same time must pass in unique TIDs + + if (( ((GSA_SAR_CONTEXT *)pListFirst)->TID == pMadSARHdr->common.TransactionID ) && + ( ((GSA_SAR_CONTEXT *)pListFirst)->MgmtClass == pMadSARHdr->common.MgmtClass ) && + ( ((GSA_SAR_CONTEXT *)pListFirst)->RecvHead->RemoteLID == pDgrm->RemoteLID )) + { + pSarContext = (GSA_SAR_CONTEXT *)pListFirst; + break; + } + + // + // Walk entire chain of devices + // + + pListNext = QListNext( + &g_GsaGlobalInfo->SARRecvList, + pListFirst ); + + pListFirst = pListNext; + + } // while 1 + + // + // This is how we find the end of the list + // + _DBG_PRINT (_DBG_LVL_SAR_INFO,( + "Reached end of List\n" )); + if (NULL == pSarContext) + { +#ifdef TEST_SAR_RECV_DISCARD + _DBG_ERROR(("No recv Timer")); +#endif + _DBG_WARN (( + "Unexpected SAR Packet: No Recv Timer Queued in list! \n" + "\tClass........:x%x\n" + "\tAttributeID..:x%x\n" + "\tTID..........:x%"PRIx64"\n" + "\tSegment......:%d\n" + "\tPayloadLen...:%d bytes\n", + (uint8)pMadSARHdr->common.MgmtClass, + pMadSARHdr->common.AttributeID, + pMadSARHdr->common.TransactionID, + pMadSARHdr->Sar.SegmentNum, + pMadSARHdr->Sar.PayloadLen + )); + _DBG_WARN (( + "Unexpected SAR Packet: (cont)\n" + "\tFragmentFlag.:\n" + "\t\tFirstPkt..:x%x\n" + "\t\tLastPkt...:x%x\n" + "\t\tKeepAlive.:x%x\n" + "\t\tResendReq.:x%x\n" + "\t\tAck.......:x%x\n", + (uint8)(pMadSARHdr->Sar.FragmentFlag.F.FirstPkt), + (uint8)(pMadSARHdr->Sar.FragmentFlag.F.LastPkt), + (uint8)(pMadSARHdr->Sar.FragmentFlag.F.KeepAlive), + (uint8)(pMadSARHdr->Sar.FragmentFlag.F.ResendReq), + (uint8)(pMadSARHdr->Sar.FragmentFlag.F.Ack) + )); + } + } + + // + // Release the lock that we acquired earlier + // + SpinLockRelease(&g_GsaGlobalInfo->SARRecvListLock); + +#ifdef TEST_SAR_RECV_DISCARD + // discard occasional SAR packet received, will stress retry mechanism + if (NULL != pSarContext && ++discard_counter % TEST_SAR_RECV_DISCARD == 1) + { + _DBG_ERROR(("Test Discarding x%"PRIx64":%d\n", + pMadSARHdr->common.TransactionID, + pMadSARHdr->Sar.SegmentNum)); + _DBG_WARN (( + "Test Discarding:\n" + "\tClass........:x%x\n" + "\tAttributeID..:x%x\n" + "\tTID..........:x%"PRIx64"\n" + "\tSegment......:%d\n" + "\tPayloadLen...:%d bytes\n", + (uint8)pMadSARHdr->common.MgmtClass, + pMadSARHdr->common.AttributeID, + pMadSARHdr->common.TransactionID, + pMadSARHdr->Sar.SegmentNum, + pMadSARHdr->Sar.PayloadLen + )); + _DBG_WARN (( + "Test Discarding (cont):\n" + "\tFragmentFlag.:\n" + "\t\tFirstPkt..:x%x\n" + "\t\tLastPkt...:x%x\n" + "\t\tKeepAlive.:x%x\n" + "\t\tResendReq.:x%x\n" + "\t\tAck.......:x%x\n", + (uint8)(pMadSARHdr->Sar.FragmentFlag.F.FirstPkt), + (uint8)(pMadSARHdr->Sar.FragmentFlag.F.LastPkt), + (uint8)(pMadSARHdr->Sar.FragmentFlag.F.KeepAlive), + (uint8)(pMadSARHdr->Sar.FragmentFlag.F.ResendReq), + (uint8)(pMadSARHdr->Sar.FragmentFlag.F.Ack) + )); + pSarContext= NULL; + } +#endif + if ( NULL == pSarContext ) + { + AtomicIncrementVoid( &g_GsaGlobalInfo->SARRecvDropped ); + status = FREJECT; + + _DBG_PRINT(_DBG_LVL_SAR_INFO, ( + "*** SAR receive drop count (%d) msgs ***\n", + g_GsaGlobalInfo->SARRecvDropped)); + break; + } + + TimerStop( &pSarContext->TimerObj ); + // This is a hack. I suspect there are some concurrency problems + // in the existing algorithms. This ensures timer callback is not + // running while we do the code below. + // There is a small race if timer is in its 1st few lines of callback + // however that same race exists in the cases where we destroy the + // timer below. Given 1+ second timeout, race is minimal + SpinLockAcquire(&pSarContext->Lock); + SpinLockRelease(&pSarContext->Lock); + + // + // Check Window to send Ack's + // + if (pSarContext->Window) + { + pSarContext->NextWindow--; + if (!pSarContext->NextWindow) + { + // Send Ack + SendAckSARRecv(pDgrm); + + // Only Ack once even if last msg + bAckSent = TRUE; + + // Reset it for next Window + pSarContext->NextWindow = pSarContext->Window; + } + } + + // + // Is it the next segment in list? + // + if ( pMadSARHdr->Sar.SegmentNum == (pSarContext->CurrSeg + 1) ) + { +#ifdef TEST_SAR_RECV_DISCARD + _DBG_ERROR(("Got expected segment x%"PRIx64":%d\n", + pMadSARHdr->common.TransactionID, + pMadSARHdr->Sar.SegmentNum)); +#endif + // We have received the next expected segment. + // Chain receives and update counters + pSarContext->RecvTail->Element.pNextElement = (IBT_ELEMENT *)pDgrm; + pSarContext->RecvTail = pDgrm; + pSarContext->RecvHead->TotalRecvSize += pDgrm->Element.RecvByteCount; + + pSarContext->RetryCount = 0; + pSarContext->ResendSent = FALSE; + AtomicIncrementVoid( &pSarContext->CurrSeg ); + + // See if the reassembly has completed. + if (( pSarContext->CurrSeg == pSarContext->TotalSegs ) && \ + (!pMadSARHdr->Sar.FragmentFlag.F.LastPkt)) + { + _DBG_PRINT(_DBG_LVL_SAR_INFO, ( + "Variable payload length being received.\n" + "\tTotal Segs.......:%d\n" + "\tpayload Length...:%d bytes\n" + "\tWindow...........:%d\n", + pSarContext->TotalSegs, + pSarContext->TotalDataSize, + pSarContext->Window )); + } + + // account for variable payloads + if (pMadSARHdr->Sar.FragmentFlag.F.LastPkt) + { + // first defines payload len for SubnAdm(Config) and response + uint32 PayloadLen = ((MAD_SAR *)GsiDgrmGetRecvMad(pSarContext->RecvHead))->Sar.PayloadLen; + + // Send last Ack + if (TRUE != bAckSent) + SendAckSARRecv(pDgrm); + + // for Variable length SARs, the PayloadLen in the Last + // fragment takes precidence over the PayloadLen in the first + if (pMadSARHdr->common.mr.AsReg8 == SUBN_ADM_GETTABLE_RESP + || pMadSARHdr->common.mr.AsReg8 == SUBN_ADM_GETBULK_RESP) + { + // this is number of bytes in this fragment + // total payload is a function of number of segments + PayloadLen = ((MAD_SAR *)GsiDgrmGetRecvMad(pSarContext->RecvHead))->Sar.PayloadLen = + pMadSARHdr->Sar.PayloadLen + + (pMadSARHdr->Sar.SegmentNum-1) * MAD_SAR_DATA_SIZE; + } + + //validate Number of Segments against PayLoadLen + if ( pMadSARHdr->Sar.SegmentNum != + (PayloadLen +MAD_SAR_DATA_SIZE-1)/ MAD_SAR_DATA_SIZE) + { + // since we added to RecvHead, caller shouldn't free + status = FPENDING; + // HACK - just discard bad response caller will timeout + _DBG_ERROR(( + "SAR with Incorrect payload length received! .\n" + "\tTotal Segs.......:%d\n" + "\tpayload Length...:%d bytes\n" + "\tExpected Segs....:%d\n", + pMadSARHdr->Sar.SegmentNum, + PayloadLen, + (PayloadLen +MAD_SAR_DATA_SIZE-1)/ MAD_SAR_DATA_SIZE + )); + // Return the dropped datagram segments to the datagram pool. + DgrmPoolPut( pSarContext->RecvHead ); + AtomicIncrementVoid( &g_GsaGlobalInfo->SARRecvDropped ); + + _DBG_PRINT (_DBG_LVL_SAR_INFO, ( + "*** SAR receive drop count (%d) msgs ***\n", + g_GsaGlobalInfo->SARRecvDropped )); + + DestroyGsaTimer( pSarContext ); + } else { + + // The reassembly is complete. + // Invoke the user callback for the completed datagram. + status = FCOMPLETED; + + // remove clientid from TID + if( MAD_IS_RESPONSE((MAD*)pMadSARHdr)) + { + pMadSARHdr->common.TransactionID = (uint64)\ + (pMadSARHdr->common.TransactionID & 0xffffffffffffff00ll); + } + + // Return all segments to the user or back to the + // datagram pool. + *ppDgrm = pSarContext->RecvHead; + DestroyGsaTimer( pSarContext ); + } + } + else + { + // We are still missing segments. Wait until we receive + // them all. + status = FPENDING; + + // remove clientid from TID + if( MAD_IS_RESPONSE((MAD*)pMadSARHdr)) + { + pMadSARHdr->common.TransactionID = (uint64)\ + (pMadSARHdr->common.TransactionID & 0xffffffffffffff00ll); + } + + // restart timer + TimerStart( &pSarContext->TimerObj, GSA_SAR_TIME_RECV ); + } + } + else + { +#ifdef TEST_SAR_RECV_DISCARD + _DBG_ERROR(("Segment Mismatch x%"PRIx64":%d\n", + pMadSARHdr->common.TransactionID, + pMadSARHdr->Sar.SegmentNum)); +#endif + _DBG_WARN (( + "SAR Packet: Segment number mismatch! \n" + "\tClass........:x%x\n" + "\tAttributeID..:x%x\n" + "\tTID..........:x%"PRIx64"\n" + "\tSegment......:%d\n" + "\tPayloadLen...:%d bytes\n", + (uint8)pMadSARHdr->common.MgmtClass, + pMadSARHdr->common.AttributeID, + pMadSARHdr->common.TransactionID, + pMadSARHdr->Sar.SegmentNum, + pMadSARHdr->Sar.PayloadLen + )); + + _DBG_WARN (( + "SAR Packet: Segment number mismatch! (cont)\n" + "\tFragmentFlag.:\n" + "\t\tFirstPkt..:x%x\n" + "\t\tLastPkt...:x%x\n" + "\t\tKeepAlive.:x%x\n" + "\t\tResendReq.:x%x\n" + "\t\tAck.......:x%x\n", + (uint8)(pMadSARHdr->Sar.FragmentFlag.F.FirstPkt), + (uint8)(pMadSARHdr->Sar.FragmentFlag.F.LastPkt), + (uint8)(pMadSARHdr->Sar.FragmentFlag.F.KeepAlive), + (uint8)(pMadSARHdr->Sar.FragmentFlag.F.ResendReq), + (uint8)(pMadSARHdr->Sar.FragmentFlag.F.Ack) + )); + + if ( pMadSARHdr->Sar.SegmentNum > (pSarContext->CurrSeg + 1) ) + { + // + // Request resend seg from here + // + // NOTE: We continuosly send Resend requests for every bad + // packet since the previous resends may have been dropped. + // + if (! pSarContext->ResendSent) + { + pSarContext->ResendSent = TRUE; + pSarContext->RetryCount++; + ResendReqSARRecv(pDgrm, pSarContext->TID, pSarContext->CurrSeg+1); + } + // else timer will perform resend retries + } + else + { + _DBG_WARN (( "SAR: Old packet in transaction!!! \n")); + } + + // restart timer + TimerStart( &pSarContext->TimerObj, GSA_SAR_TIME_RECV ); + + status = FREJECT; + } + break; + + } // for loop + + _DBG_LEAVE_LVL(_DBG_LVL_SAR_INFO); + return status; +} + + +boolean +KeepAliveSARRecv( + IN MAD_SAR *pMadSar, + IN IBT_DGRM_ELEMENT **ppDgrm + ) +{ + IBT_DGRM_ELEMENT *pDgrm; + GSA_SAR_CONTEXT *pSarContext= NULL; + boolean bStatus = FALSE; + + LIST_ITEM *pListFirst, *pListNext; + + _DBG_ENTER_LVL (_DBG_LVL_SAR_INFO, KeepAliveSARRecv); + + + for ( ;; ) + { + pDgrm = *ppDgrm; + + _DBG_PRINT (_DBG_LVL_SAR_INFO,( + "Need to find TID x%"PRIx64"\n", + pMadSar->common.TransactionID )); + + SpinLockAcquire( &g_GsaGlobalInfo->SARRecvListLock ); + + pListFirst = QListHead( &g_GsaGlobalInfo->SARRecvList ); + + if ( pListFirst ) + { + pSarContext=NULL; + + while ( pListFirst ) + { + // + // Dump debug info + // + _DBG_PRINT (_DBG_LVL_SAR_INFO,( + "...TID %"PRIx64"\n", + ((GSA_SAR_CONTEXT *)pListFirst)->TID )); + + // + // IB defines a message as unique by the combination of + // + IB_GID from the GRH ( if applicable) TBD + // + SourceLID + // + TransactionID + // + + // NOTE:This check will only fail if 2 receives arrive + // from the same source on the same LID and the + // TransactionID is the same. + // Clients issuing multiple requests to a class + // manager at the same time must pass in unique TIDs + + if (( ((GSA_SAR_CONTEXT *)pListFirst)->TID == pMadSar->common.TransactionID ) && + ( ((GSA_SAR_CONTEXT *)pListFirst)->MgmtClass == pMadSar->common.MgmtClass ) && + ( ((GSA_SAR_CONTEXT *)pListFirst)->RecvHead->RemoteLID == pDgrm->RemoteLID )) + { + pSarContext = (GSA_SAR_CONTEXT *)pListFirst; + TimerStop( &pSarContext->TimerObj ); + TimerStart( &pSarContext->TimerObj, GSA_SAR_TIME_RECV ); + bStatus = TRUE; + + _DBG_PRINT (_DBG_LVL_SAR_INFO,( + "Timer restarted\n" )); + break; + } + + // + // Walk entire chain of devices + // + + pListNext = QListNext( + &g_GsaGlobalInfo->SARRecvList, + pListFirst ); + + pListFirst = pListNext; + + } // while 1 + + // + // This is how we find the end of the list + // + _DBG_PRINT (_DBG_LVL_SAR_INFO,( + "Reached end of List\n" )); + } + + + // + // Release the lock that we acquired earlier + // + SpinLockRelease(&g_GsaGlobalInfo->SARRecvListLock); + break; + + } // for loop + + _DBG_LEAVE_LVL(_DBG_LVL_SAR_INFO); + return (bStatus); +} + + +// uses pDgrm as a template for building a SAR Ack or resend request +// SAR Flags, SegmentNum and TID are from arguments +// rest is from pDgrm +// R bit is inverted +// pDgrm is unaffected +void +FragmentOptionsSARRecv ( + IN IBT_DGRM_ELEMENT *pDgrm, + IN FRAGMENT_FLAG FragmentFlag, // Ack or Resend? + IN uint64 TransactionID, + IN uint32 SegmentNum + ) +{ + FSTATUS status = FSUCCESS; + uint32 i; + IBT_DGRM_ELEMENT *pDgrmList; + IB_WORK_REQ workRequest; + + IB_HANDLE qp1Handle = NULL, avHandle; + SPIN_LOCK *qpLock = NULL; + IB_HANDLE cq1Handle = NULL; + + GSA_POST_SEND_LIST *pPostList; + IBT_DGRM_ELEMENT_PRIV *pDgrmPrivate; + IB_LOCAL_DATASEGMENT *pDsList; + MAD_SAR *pMadSarHdr; + ADDRESS_VECTOR avInfo; + IB_L_KEY LKey; + + + _DBG_ENTER_LVL(_DBG_LVL_SAR_INFO, FragmentOptionsSARRecv); + + i = 1; + status = DgrmPoolGet( g_GsaGlobalInfo->DgrmPoolRecvQ, &i, &pDgrmList ); + if (FSUCCESS != status || i != 1) + { + _DBG_ERROR(("No more elements in Pool!!!\n")); + goto done; + } + ASSERT(NULL != pDgrmList); + + // + // Copy Data for Ack/ResendReq packet and set SAR flags + // + pMadSarHdr = (MAD_SAR*)GsiDgrmGetSendMad(pDgrmList); + + MemoryCopy( pMadSarHdr, GsiDgrmGetRecvMad(pDgrm), sizeof(MAD) ); + + // Invert R bit + pMadSarHdr->common.mr.s.R = ! pMadSarHdr->common.mr.s.R; + pMadSarHdr->common.TransactionID = TransactionID; + + // For Ack, First/Last/Resend should not be set + pMadSarHdr->Sar.FragmentFlag.AsReg8 = 0; + if (FragmentFlag.F.Ack) + pMadSarHdr->Sar.FragmentFlag.F.Ack = 1; + else if (FragmentFlag.F.ResendReq) + pMadSarHdr->Sar.FragmentFlag.F.ResendReq = 1; + pMadSarHdr->Sar.SegmentNum = SegmentNum; + pMadSarHdr->Sar.PayloadLen = 0; + + // Byte order headers + BSWAP_MAD_HEADER ((MAD*)&pMadSarHdr->common); + BSWAP_SAR_HEADER (&pMadSarHdr->Sar); + + // Set remote info + // incomplete and not needed since we PostSend directly + //pDgrmList->PortGuid = pDgrm->PortGuid; + //pDgrmList->RemoteLID = pDgrm->RemoteLID; + //pDgrmList->RemoteQKey = pDgrm->RemoteQKey; + //pDgrmList->RemoteQP = pDgrm->RemoteQP; + + // + // Create Av Info + // + avInfo.PortGUID = pDgrm->PortGuid; + avInfo.DestLID = pDgrm->RemoteLID; + avInfo.PathBits = pDgrm->PathBits; + avInfo.ServiceLevel = pDgrm->ServiceLevel; + avInfo.StaticRate = pDgrm->StaticRate; + avInfo.GlobalRoute = pDgrm->GlobalRoute; + + if ( TRUE == avInfo.GlobalRoute ) + { + avInfo.GlobalRouteInfo.DestGID = GsiDgrmGetRecvGrh(pDgrm)->SGID; + avInfo.GlobalRouteInfo.FlowLabel = pDgrm->GRHInfo.FlowLabel; + avInfo.GlobalRouteInfo.SrcGIDIndex = pDgrm->GRHInfo.SrcGIDIndex; + avInfo.GlobalRouteInfo.HopLimit = pDgrm->GRHInfo.HopLimit; + avInfo.GlobalRouteInfo.TrafficClass = pDgrm->GRHInfo.TrafficClass; + } + + // + // post to qp + // + pDgrmPrivate = (IBT_DGRM_ELEMENT_PRIV *)pDgrmList; + status = GetCaContextFromPortGuid(&avInfo, + pDgrmPrivate->MemPoolHandle->MemList->CaMemIndex, + &avHandle, &qp1Handle, &cq1Handle, &qpLock, &LKey); + if (FSUCCESS != status) + { + _DBG_PRINT( _DBG_LVL_MGMT,(\ + "An active Port could not be found OR" + "Qp in Error on Port(x%"PRIx64")!\n", pDgrm->PortGuid)); + + DgrmPoolPut( pDgrmList ); + } else { + + // + // fill in work request details + // + + // + // generate a PostSendList from the first datagram in post + // + pPostList = &pDgrmPrivate->PostSendList; + + // + // Fill in list details + // + + pPostList->DgrmIn = 0; + AtomicWrite(&pPostList->DgrmOut, 0); + pPostList->DgrmList = pDgrmList; + pPostList->SARRequest = TRUE; + + pDgrmPrivate->Base = pPostList;// link for receives + + ASSERT_VALID_WORKREQID((uintn)pDgrmPrivate); + workRequest->WorkReqId = BUILD_SQ_WORKREQID((uintn)pDgrmPrivate); + workRequest.DSListDepth = \ + pDgrmPrivate->MemPoolHandle->BuffersPerElement; + + workRequest.DSList = pDsList = pDgrmPrivate->DsList; + + workRequest.Operation = WROpSend; + + // zero out the options + workRequest.Req.SendUD.Options.AsUINT16 = 0; + workRequest.Req.SendUD.Options.s.SignaledCompletion = TRUE; + + // + // Fill in user settings + // + workRequest.Req.SendUD.QPNumber = pDgrm->RemoteQP; + workRequest.Req.SendUD.Qkey = pDgrm->RemoteQKey; + + ASSERT (pDgrm->RemoteQP); + + pDgrmPrivate->AvHandle = workRequest.Req.SendUD.AVHandle = avHandle; + + // + // fill in scatter/gather Ds list details + // + workRequest.DSListDepth = 1; + + // + // Fill in MAD Common info + // + pDsList[0].Address = (uintn)pMadSarHdr; + pDsList[0].Lkey = LKey; + pDsList[0].Length = sizeof(MAD); + + workRequest.MessageLen = sizeof(MAD); + + + // + // Submit to verbs + // + SpinLockAcquire( qpLock ); + status = iba_post_send( qp1Handle, &workRequest ); + SpinLockRelease( qpLock ); + } + +done: + _DBG_LEAVE_LVL(_DBG_LVL_SAR_INFO); +} + + +void +SendAckSARRecv ( + IN IBT_DGRM_ELEMENT *pDgrm + ) +{ + FRAGMENT_FLAG fragFlags; + MAD_SAR *pMadSarHdr; + + + _DBG_ENTER_LVL(_DBG_LVL_SAR_INFO, SendAckSARRecv); + + pMadSarHdr = (MAD_SAR*)GsiDgrmGetRecvMad(pDgrm); + + if (TRUE == IsRmppMethod(pMadSarHdr)) + { + _DBG_PRINT (_DBG_LVL_SAR_INFO,( + "SAR Packet: Sending Ack\n" + "\tClass........:x%x\n" + "\tAttributeID..:x%x\n" + "\tTID..........:x%"PRIx64"\n" + "\tSegment......:%d\n" + "\tWindow.......:%d\n", + (uint8)pMadSarHdr->common.MgmtClass, + pMadSarHdr->common.AttributeID, + pMadSarHdr->common.TransactionID, + pMadSarHdr->Sar.SegmentNum, + pMadSarHdr->Sar.Window + )); + + fragFlags.AsReg8 = 0; + fragFlags.F.Ack = 1; + + FragmentOptionsSARRecv ( + pDgrm, + fragFlags, + pMadSarHdr->common.TransactionID, + pMadSarHdr->Sar.SegmentNum); + } + + _DBG_LEAVE_LVL(_DBG_LVL_SAR_INFO); +} + +void +ResendReqSARRecv ( + IN IBT_DGRM_ELEMENT *pDgrm, + IN uint64 TransactionID, + IN uint32 SegmentNum + ) +{ + FRAGMENT_FLAG fragFlags; + MAD_SAR *pMadSARHdr; + + _DBG_ENTER_LVL (_DBG_LVL_SAR_INFO, ResendReqSARRecv ); + + pMadSARHdr = (MAD_SAR *)GsiDgrmGetRecvMad(pDgrm); +#ifdef TEST_SAR_RECV_DISCARD + _DBG_ERROR(("Requesting Resend of x%"PRIx64":%d\n", + TransactionID, + SegmentNum)); +#endif + _DBG_WARN (( + "SAR Packet: Requesting Resend\n" + "\tClass........:x%x\n" + "\tAttributeID..:x%x\n" + "\tTID..........:x%"PRIx64"\n" + "\tSegment......:%d\n", + (uint8)pMadSARHdr->common.MgmtClass, + pMadSARHdr->common.AttributeID, + TransactionID, + SegmentNum + )); + + fragFlags.AsReg8 = 0; + fragFlags.F.ResendReq = 1; + + FragmentOptionsSARRecv ( + pDgrm, + fragFlags, + TransactionID, + SegmentNum); + + _DBG_LEAVE_LVL(_DBG_LVL_SAR_INFO); +} + + + + +// +// Remove from Global SAR recv Q +// +FSTATUS +RemoveSARListEntry( + IN LIST_ITEM *ListItem + ) +{ + FSTATUS status = FSUCCESS; + + + _DBG_ENTER_LVL(_DBG_LVL_SAR_INFO, RemoveSARListEntry); + + SpinLockAcquire( &g_GsaGlobalInfo->SARRecvListLock ); + + ASSERT (QListIsItemInList( + &g_GsaGlobalInfo->SARRecvList, + ListItem )); + + + if ( !QListIsItemInList( + &g_GsaGlobalInfo->SARRecvList, + ListItem )) + { + status = FINVALID_PARAMETER; + _DBG_ERROR(("Item not in List!!!\n")); + } + else + { + QListRemoveItem ( + &g_GsaGlobalInfo->SARRecvList, + ListItem ); + } + + SpinLockRelease(&g_GsaGlobalInfo->SARRecvListLock); + + + _DBG_LEAVE_LVL(_DBG_LVL_SAR_INFO); + + return FSUCCESS; +} + + +// +// Timer callback invoked on SAR Recvs +// +void +TimerCallbackRecv( + IN void *TimerContext + ) +{ + GSA_SAR_CONTEXT *pSarContext; + + _DBG_ENTER_LVL (_DBG_LVL_SAR_INFO, TimerCallbackRecv); + + pSarContext = TimerContext; + + //ASSERT( pSarContext->CurrSeg != pSarContext->TotalSegs ); + +#ifdef TEST_SAR_RECV_DISCARD + _DBG_ERROR(("Timer expired\n")); +#endif + SpinLockAcquire(&pSarContext->Lock); + // unfortunately we do not have a retry mechanism for loss + // of first packet, we would need to resend the original request + // which is long gone at this point, so we let those return failure + // to caller + if (pSarContext->CurrSeg > 0) + { + ASSERT(pSarContext->RecvHead != NULL); + if (++pSarContext->RetryCount < 7) + { + IBT_DGRM_ELEMENT *pDgrm; + + // use 1st valid Dgrm we received for this transaction as template + // for resend. Only SAR Header and path information is used + pDgrm = pSarContext->RecvHead; + pSarContext->ResendSent = TRUE; + ResendReqSARRecv(pDgrm, pSarContext->TID, pSarContext->CurrSeg+1); + // restart timer + TimerStart( &pSarContext->TimerObj, GSA_SAR_TIME_RECV ); + SpinLockRelease(&pSarContext->Lock); + goto done; + } + } + SpinLockRelease(&pSarContext->Lock); + + // The datagram has timed out, abort the reassembly. + _DBG_ERROR (( "SAR Retries Exceeded! \n" )); + _DBG_PRINT (_DBG_LVL_SAR_INFO, ( + "SAR msg dropped on retries!\n" )); + + // Return the dropped datagram segments to the datagram pool. + DgrmPoolPut( pSarContext->RecvHead ); + AtomicIncrementVoid( &g_GsaGlobalInfo->SARRecvDropped ); + + _DBG_PRINT (_DBG_LVL_SAR_INFO, ( + "*** SAR receive drop count (%d) msgs ***\n", + g_GsaGlobalInfo->SARRecvDropped )); + + DestroyGsaTimer( pSarContext ); + +done: + _DBG_LEAVE_LVL(_DBG_LVL_SAR_INFO); +} + + +void +DestroyGsaTimer( + IN GSA_SAR_CONTEXT *pSarContext ) +{ + // Stop timer before destroy to avoid race conditions + //TimerStop( &Timer->TimerObj ); + + // Destroy the timer object. + TimerDestroy( &pSarContext->TimerObj ); + + // Remove the GSA timer information from the global SAR recv list. + RemoveSARListEntry( &pSarContext->ListItem ); + + // Destroy the timer's lock. + SpinLockDestroy(&pSarContext->Lock); + MemoryDeallocate( pSarContext ); +} + +#endif // IB1_1 diff --git a/IbAccess/Common/Ibt/Gsa/gsasar2.c b/IbAccess/Common/Ibt/Gsa/gsasar2.c new file mode 100644 index 0000000..de6c7b2 --- /dev/null +++ b/IbAccess/Common/Ibt/Gsa/gsasar2.c @@ -0,0 +1,2946 @@ +/* BEGIN_ICS_COPYRIGHT4 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT4 ****************************************/ + + +#include "gsamain.h" +#include "ithread.h" +#include "ireaper.h" + +//#define VALIDATE_SAR_LIST + +#if defined( DBG) ||defined( IB_DEBUG) +#define STATIC +#else +//#define STATIC static // TBD use STATIC throughout?? +#define STATIC +#endif + +#if defined( DBG) ||defined( IB_DEBUG) +ATOMIC_UINT SarContexts; +ATOMIC_UINT ActiveSarContexts; +#endif + +// 1.1 RMPP protocal Segmentation And Reassembly + +// TBD - when to print Atomic_Read(&g_GsaGlobalInfo->SARRecvDropped ) + +// Note when a transaction gets started but ultimately fails, we do not +// notify the user (typically Subnet Driver). This lets the normal timeout +// handling treat it the same as a transaction for which no response was +// received. This permits a backoff time (due to timeout), during which the +// remote note (SA) will have some time to recover from its situation. + +// +// Definitions +// + +#if defined( DBG) || defined( IB_DEBUG) +extern uint32 RmppRecvDiscardFreq; // enables discard for testing of retries/resend +extern uint32 RmppSendDiscardFreq; // enables discard for testing of retries/resend +#endif +// we advertize at most RmppWindowSize +// when window we have advertized reaches RmppWindowLowWater +// we readvertize RmppWindowSize +// if equal, there is no low water effect +// if both 1, we ack every packet +// Depending on design of sender, the RmppWindowLowWater may have no effect +// many senders will simply post everything on their send Q and hence an +// early ack actually makes more work for them than an ack at RmppWindowSize +extern uint32 RmppWindowSize; +extern uint32 RmppWindowLowWater; +extern uint32 RmppStrict; +extern uint32 RmppMaxReceive; + + // spec does not define max retries, but other equations for total timeout + // imply a retry count of 8 +#define GSA_SAR_MAX_RETRIES_SEND 8 //our choice + + // RESP_TIMEOUT includes RESP_TIMEOUT_MULT factor as well + // as packet lifetime + // BUGBUG - need packet lifetime component in calculation + // for now using hard coded 2*(1 second value for packet lifetime) +#define GSA_SAR_DEFAULT_RESP_TIMEOUT (4300+2000) // ms per IBTA 1.1 +#define GSA_SAR_DEFAULT_RESP_TIMEOUT_MULT 20 // ms per IBTA 1.1 +#define GSA_SAR_DEFAULT_TOTAL_TIMEOUT 40000 // ms per IBTA 1.1 +#define GSA_SAR_RECV_RESP_TIMEOUT_MULT 17 // our choice + // RESP_TIMEOUT includes RESP_TIMEOUT_MULT factor as well + // as packet lifetime + // BUGBUG - need packet lifetime component in calculation + // for now using hard coded 1 second value for packet lifetime +#define GSA_SAR_RECV_RESP_TIMEOUT (537+2000) // ms + +#ifdef ICS_LOGGING +#define _DBG_PRINT_RMPP_HEADERS( LEVEL, TITLE, pRMPP_MAD, REMOTE_LID) \ + do { \ + _DBG_PRINT ((LEVEL), ( \ + TITLE \ + "\tClass..........:x%x\n" \ + "\tRemoteLID......:x%x\n" \ + "\tRmppType.......:%d\n" \ + "\tRmppStatus.....:%d\n" \ + "\tSegmentNum.....:%d\n" \ + "\tPayLoadLen/WL..:%d\n", \ + (pRMPP_MAD)->common.MgmtClass, \ + (REMOTE_LID), \ + (pRMPP_MAD)->RmppHdr.RmppType, \ + (pRMPP_MAD)->RmppHdr.RmppStatus, \ + (pRMPP_MAD)->RmppHdr.u1.SegmentNum, \ + (pRMPP_MAD)->RmppHdr.u2.PayloadLen \ + )); \ + _DBG_PRINT ((LEVEL), ( \ + TITLE \ + "\tFlags..........:\n" \ + "\t\tFirstPkt..:%d\n" \ + "\t\tLastPkt...:%d\n" \ + "\t\tActive....:%d\n" \ + "\t\tRRespTime.:%d\n", \ + (pRMPP_MAD)->RmppHdr.RmppFlags.s.FirstPkt, \ + (pRMPP_MAD)->RmppHdr.RmppFlags.s.LastPkt, \ + (pRMPP_MAD)->RmppHdr.RmppFlags.s.Active, \ + (pRMPP_MAD)->RmppHdr.RmppFlags.s.RRespTime \ + )); \ + } while (0) +#else +#define _DBG_PRINT_RMPP_HEADERS( LEVEL, TITLE, pRMPP_MAD, REMOTE_LID) \ + _DBG_PRINT ((LEVEL), ( \ + TITLE \ + "\tClass..........:x%x\n" \ + "\tRemoteLID......:x%x\n" \ + "\tRmppType.......:%d\n" \ + "\tRmppStatus.....:%d\n" \ + "\tSegmentNum.....:%d\n" \ + "\tPayLoadLen/WL..:%d\n" \ + "\tFlags..........:\n" \ + "\t\tFirstPkt..:%d\n" \ + "\t\tLastPkt...:%d\n" \ + "\t\tActive....:%d\n" \ + "\t\tRRespTime.:%d\n", \ + (pRMPP_MAD)->common.MgmtClass, \ + (REMOTE_LID), \ + (pRMPP_MAD)->RmppHdr.RmppType, \ + (pRMPP_MAD)->RmppHdr.RmppStatus, \ + (pRMPP_MAD)->RmppHdr.u1.SegmentNum, \ + (pRMPP_MAD)->RmppHdr.u2.PayloadLen, \ + (pRMPP_MAD)->RmppHdr.RmppFlags.s.FirstPkt, \ + (pRMPP_MAD)->RmppHdr.RmppFlags.s.LastPkt, \ + (pRMPP_MAD)->RmppHdr.RmppFlags.s.Active, \ + (pRMPP_MAD)->RmppHdr.RmppFlags.s.RRespTime \ + )) +#endif + +// state for an RMPP Context (basically which circle in IBTA 1.1 flow +// diagrams the context is "waiting" in +typedef enum { + IB_RMPP_STATE_CREATED = 0, // processing 1st packet + IB_RMPP_STATE_ACTIVE = 1, // in fig 176 or 178 circle - main flow + IB_RMPP_STATE_DONE = 2, // GotLast, handing up + IB_RMPP_STATE_TIMEWAIT = 3, // in fig 175 circle - term flow + IB_RMPP_STATE_TIMEWAIT_RECV = 4,// in fig 177 circle - recv term flow + IB_RMPP_STATE_DESTROY = 5 // being destroyed +} RMPP_CONTEXT_STATE; + +// RMPP Sender/Receiver context +// for Segmentation and Reassembly of IBTA 1.1 RMPP messages +// Lock Heirachy (in order they can be acquired): +// Global Context List Lock +// SarContext.Lock +// Qp1Lock +typedef struct _GSA_SAR_CONTEXT { + // Common info + LIST_ITEM ListItem; + SPIN_LOCK Lock; // lock + // key to context list is TID & MgmtClass & (LID or GID) + // These are invariant once created, hence RmppFindContext + // can test these without getting Lock + uint64 TID; // Client TID + uint8 MgmtClass; + // if GID is part of key, RemoteLID=LID_RESERVED + // if LID is part of key, RemoteGID is 0, LID is valid + IB_LID RemoteLID; + IB_GID RemoteGID; + + // RMPP Defined protocol state + // segment number mgmt and windowing + uint32 WindowFirst; // WF - sender only + uint32 WindowLast; // WL + union { + uint32 NextToSend; // NS - sender only + uint32 ExpectedSeg; // ES - receiver only + }; + + // negotiated timeouts + uint32 RespTimeout; // ms + uint32 TotalTimeout; // ms - receiver only + uint8 Direction:1; // present transfer dir +#define IB_SAR_DIR_SENDER 0 +#define IB_SAR_DIR_RECEIVER 1 + uint8 IsDoubleSided:1; + uint8 State:3; // RMPP_CONTEXT_STATE + + uint32 TotalSegs; // total no. of segments + uint32 TotalDataSize; // size of data + + TIMER Timer; + ATOMIC_UINT RefCount; + + // TBD - pointer to Gsi registered service this transaction is on behalf of + // for R=0, it will be the requestor of the transaction from the original + // send + // for R=1, it will be the class manager + // we should get RespTimeout for receiver, total transaction timeout, etc + // from the GSI registered service entry + + // TBD - Sender saves Qp1 info on 1st send + // however receiver looks up per ack sent + // perhaps receiver could save qp handles here + // BUGBUG - both sender and receiver are likely to have problems if + // CA goes away mid transaction. receiver might be a little better though + // TBD - hold AV in this structure and free when free context + // instead of allocate/free per packet sent. + + // TBD - union of sender and receiver context fields below? + + // Receiver Context Info + IBT_DGRM_ELEMENT *RecvHead; // list of good MADs recv'd + IBT_DGRM_ELEMENT *RecvTail; // list of good MADs recv'd + + // Sender Context Info + // sender determines Qp and builds a WorkRequest during GsiPostSend + // a single MAD is on SendQ at a time and the WorkRequest + // is re-used on send completion + // User will have provided a single send image as: + // MAD HEADER + // RMPP HEADER + // DATA - may be larger than a single packet + // BUGBUG - TBD - SA_HDR follows RMPP and is not a standard + // GSA header size + uint32 RetryCount; // number of retries w/o ACK + GSA_POST_SEND_LIST *PostList; // from original DoSARSend + SYS_CALLBACK_ITEM *SysCBItem; // Syscallback item to invoke + // when send completes + // where to post our sends + IB_HANDLE Qp1Handle; + SPIN_LOCK *QpLock; + + IB_L_KEY LKey; + IB_WORK_REQ WorkRequest; // prebuilt WQE + + IB_LOCAL_DATASEGMENT *DataSeg; // ptr to data segment in WQE + uintn DataStart; // start of complete data +} GSA_SAR_CONTEXT; + +// +// Function prototypes. +// + +// --------------------------------------------------------------------------- +// Common RMPP Functions + +#if defined( DBG) ||defined( IB_DEBUG) +STATIC void AssertInvariants( GSA_SAR_CONTEXT* pSarContext ); +#else +static __inline void AssertInvariants( GSA_SAR_CONTEXT* pSarContext ) {} +#endif + +GSA_SAR_CONTEXT* +FindSarContext( + IN MAD_RMPP *pMadRmpp, + IN IBT_DGRM_ELEMENT *pDgrm, + IN boolean sender + ); + +STATIC +RMPP_STATUS +RmppMadCheck( + IN MAD_RMPP *pMadRmpp + ); + +STATIC +void +RmppTimerCallback( + IN void *TimerContext + ); + + +// --------------------------------------------------------------------------- +// RMPP Receiver + +//boolean +//IsRmppMethod( +// IN MAD_RMPP *pMadRmpp +// ); + +GSA_SAR_CONTEXT* +RmppReceiverCreateContext( + IN MAD_RMPP *pMadRmpp, + IN IBT_DGRM_ELEMENT **ppDgrm + ); + +FSTATUS +RmppReceiverProcessRecv ( + IN GSA_SAR_CONTEXT *pSarContext, + IN MAD_RMPP *pMadRmpp, + IN IBT_DGRM_ELEMENT **ppDgrm + ); + +void +RmppReceiverSendAckIfNeeded( + IN GSA_SAR_CONTEXT *pSarContext, + IN IBT_DGRM_ELEMENT *pDgrm + ); + +STATIC +FSTATUS +RmppReceiverGotLast( + IN GSA_SAR_CONTEXT *pSarContext, + IN MAD_RMPP *pMadRmpp, + IN IBT_DGRM_ELEMENT **ppDgrm + ); + +void +RmppReceiverTerminate( + IN GSA_SAR_CONTEXT *pSarContext, + IN RMPP_CONTEXT_STATE newState, + IN IBT_DGRM_ELEMENT *pDgrm + ); + +STATIC void SendRmppReply( + IN IBT_DGRM_ELEMENT *pDgrm, + IN RMPP_HEADER *pRmppHdr + ); + +STATIC void BuildRmppAck( + IN RMPP_HEADER *pRmppHdr, + IN uint8 RRespTime, + IN uint32 SegmentNum, + IN uint32 NewWindowLast + ); + +STATIC void BuildRmppStop( + IN RMPP_HEADER *pRmppHdr, + IN uint8 RmppStatus + ); + +STATIC void BuildRmppAbort( + IN RMPP_HEADER *pRmppHdr, + IN uint8 RmppStatus + ); + +STATIC void SendRmppAck( + IN GSA_SAR_CONTEXT *pSarContext, + IN IBT_DGRM_ELEMENT *pDgrm + ); + +STATIC void SendRmppStopReply( + IN IBT_DGRM_ELEMENT *pDgrm, + IN uint8 RmppStatus + ); + +STATIC void SendRmppAbortReply( + IN IBT_DGRM_ELEMENT *pDgrm, + IN uint8 RmppStatus + ); + +void +RmppReceiverTimerCallback( + IN GSA_SAR_CONTEXT *pSarContext + ); + +void +RmppReceiverReapContext( + IN LIST_ITEM *pItem + ); + +void +RmppReceiverDestroyContext ( + IN GSA_SAR_CONTEXT *pSarContext, + IN boolean stopTimer + ); + +FSTATUS +RemoveSARRecvListEntry( + IN LIST_ITEM *ListItem + ); + +// --------------------------------------------------------------------------- +// RMPP Sender +FSTATUS +SARPost( + IN GSA_SAR_CONTEXT *pSarContext + ); + +FSTATUS +RmppSenderProcessRecv ( + IN GSA_SAR_CONTEXT *pSarContext, + IN MAD_RMPP *pMadRmpp, + IN IBT_DGRM_ELEMENT **ppDgrm + ); + + +boolean +ResendReqSARSend ( + IN MAD_RMPP *pMadRmpp, + IN IBT_DGRM_ELEMENT **ppDgrm + ); + +boolean +AckReqSARSend( + IN MAD_RMPP *pMadRmpp, + IN IBT_DGRM_ELEMENT **ppDgrm + ); + +void +SARCloseSend( + IN GSA_SAR_CONTEXT *pSarContext + ); + +void +SARSendSegments( + IN void *Key, + IN void *TimerContext + ); + +void +RmppSenderTimerCallback( + IN GSA_SAR_CONTEXT *pSarContext + ); + +// --------------------------------------------------------------------------- +// Internal functions + +#ifdef VALIDATE_SAR_LIST +static +__inline +boolean +IsRecvSarListValid( + IN GSA_SAR_CONTEXT *pSarContext + ) +{ + IBT_ELEMENT *pElement = &pSarContext->RecvHead->Element; + IBT_BUFFER *pBufferHdr = pElement->pBufferList; + MAD_RMPP *pMadRmpp = (MAD_RMPP*)pBufferHdr->pNextBuffer->pData; + uint32_t SegmentCount = 1; + boolean result = TRUE; + + _DBG_ENTER_LVL ( _DBG_LVL_SAR_INFO, IsRecvSarListValid ); + if (pMadRmpp->RmppHdr.u1.SegmentNum != SegmentCount) + { + _DBG_ERROR(("Segment Number Mismatch in First Segment. Found %d\n", + pMadRmpp->RmppHdr.u1.SegmentNum)); + result = FALSE; + } + +// MsgOut("pMadRmpp->RmppHdr.u1.SegmentNum %d, SegmentCount %d\n", pMadRmpp->RmppHdr.u1.SegmentNum, SegmentCount); + + if (pElement->pNextElement == NULL) + { + if (pElement != &pSarContext->RecvTail->Element) + { + _DBG_ERROR(("Last Element In List Not Equal Tail. Expected %p Found %p\n", + &pSarContext->RecvTail->Element, pElement)); + result = FALSE; + } + +// MsgOut("pElement %p, RecvTail->Element %p\n", pElement, &pSarContext->RecvTail->Element); + } + + pElement = pElement->pNextElement; + + while (pElement) + { + SegmentCount++; + + pBufferHdr = pElement->pBufferList->pNextBuffer; + pMadRmpp = (MAD_RMPP *)pBufferHdr->pData; + + if (pMadRmpp->RmppHdr.u1.SegmentNum != SegmentCount) + { + _DBG_ERROR(("Segment Number Mismatch. Expected %d. Found %d\n", + SegmentCount, pMadRmpp->RmppHdr.u1.SegmentNum)); + result = FALSE; + } + +// MsgOut("pMadRmpp->RmppHdr.u1.SegmentNum %d, SegmentCount %d\n", pMadRmpp->RmppHdr.u1.SegmentNum, SegmentCount); + + if (pElement->pNextElement == NULL) + { + if (pElement != &pSarContext->RecvTail->Element) + { + _DBG_ERROR(("Last Element In List Not Equal Tail. Expected %p Found %p\n", + &pSarContext->RecvTail->Element, pElement)); + result = FALSE; + } + +// MsgOut("pElement %p, RecvTail->Element %p\n", pElement, &pSarContext->RecvTail->Element); + } + + pElement = pElement->pNextElement; + } + + if (SegmentCount != (pSarContext->ExpectedSeg - 1)) + { + _DBG_ERROR(("Expected %d segments. Found %d segments\n", (pSarContext->ExpectedSeg - 1), SegmentCount)); + result = FALSE; + } + +// MsgOut("Expected %d segments. Found %d segments\n", (pSarContext->ExpectedSeg - 1), SegmentCount); + + _DBG_LEAVE_LVL( _DBG_LVL_SAR_INFO ); + return result; +} +#endif // VALIDATE_SAR_LIST + +static +__inline +boolean +SarContextTimerArmed( + IN GSA_SAR_CONTEXT *pSarContext + ) +{ + return (pSarContext->State == IB_RMPP_STATE_ACTIVE + || pSarContext->State == IB_RMPP_STATE_TIMEWAIT + || pSarContext->State == IB_RMPP_STATE_TIMEWAIT_RECV); +} + + +STATIC +void +IncrementSarContextUsageCount( + IN GSA_SAR_CONTEXT *pSarContext + ) +{ + _DBG_ENTER_LVL ( _DBG_LVL_SAR_INFO, IncrementSarContextUsageCount ); + AtomicIncrementVoid( &pSarContext->RefCount ); + _DBG_LEAVE_LVL( _DBG_LVL_SAR_INFO ); +} + +STATIC +void +DecrementSarContextUsageCount( + IN GSA_SAR_CONTEXT *pSarContext + ) +{ + _DBG_ENTER_LVL ( _DBG_LVL_SAR_INFO, DecrementSarContextUsageCount ); + if ( AtomicDecrement( &pSarContext->RefCount ) == 0 ) + { +#if defined(DBG) ||defined( IB_DEBUG) + AtomicDecrementVoid(&ActiveSarContexts); + _DBG_PRINT(_DBG_LVL_SAR_INFO, + ("Unused Sar Context %p, total %d, active %d\n", _DBG_PTR(pSarContext), + AtomicRead(&SarContexts), AtomicRead(&ActiveSarContexts))); +#endif + // remove via reaper since we can be in our own timer callback here + ReaperQueue( &pSarContext->ListItem, RmppReceiverReapContext ); + } + _DBG_LEAVE_LVL( _DBG_LVL_SAR_INFO ); +} + +STATIC +boolean +StartSarContextTimer( + IN GSA_SAR_CONTEXT *pSarContext, + IN uint32 TimeOutMs + ) +{ + boolean rval; + + _DBG_ENTER_LVL ( _DBG_LVL_SAR_INFO, StartSarContextTimer ); + IncrementSarContextUsageCount( pSarContext ); + _DBG_PRINT(_DBG_LVL_SAR_INFO, + ("Sar Context %p: %d timer start\n", + _DBG_PTR(pSarContext), pSarContext->RefCount)); + rval = TimerStart( &pSarContext->Timer, TimeOutMs ); + _DBG_LEAVE_LVL( _DBG_LVL_SAR_INFO ); + + return ( rval ); +} + +STATIC +void +StopSarContextTimer( + IN GSA_SAR_CONTEXT *pSarContext + ) +{ + _DBG_ENTER_LVL ( _DBG_LVL_SAR_INFO, StopSarContextTimer ); + TimerStop( &pSarContext->Timer ); + if ( !TimerExpired( &pSarContext->Timer ) ) + { + DecrementSarContextUsageCount( pSarContext ); + _DBG_PRINT(_DBG_LVL_SAR_INFO, ("Sar Context %p: %d timer stopped\n", + _DBG_PTR(pSarContext), pSarContext->RefCount)); + } + _DBG_LEAVE_LVL( _DBG_LVL_SAR_INFO ); +} + +// --------------------------------------------------------------------------- +// Externally visible common functions used by GSA + +// Destroy Contexts for any SAR in progress. +// designed to only be called in GsaUnload +// since RemoveDevice already destroyed QPs, we will not end up with +// new work on the list +void +DestroySARContexts() +{ + GSA_SAR_CONTEXT* pSarContext; + + _DBG_ENTER_LVL (_DBG_LVL_SAR_INFO, DestroySARContexts ); + + // destroy sends in progress + SpinLockAcquire( &g_GsaGlobalInfo->SARSendListLock); + ASSERT(QListHead( &g_GsaGlobalInfo->SARSendList) == NULL); // no sends yet + SpinLockRelease( &g_GsaGlobalInfo->SARSendListLock); + + // destroy receives in progress + SpinLockAcquire( &g_GsaGlobalInfo->SARRecvListLock); + while ( NULL!=(pSarContext = + (GSA_SAR_CONTEXT*)QListHead(&g_GsaGlobalInfo->SARRecvList))) + { + _DBG_PRINT (_DBG_LVL_SAR_INFO,( "Destroy TID %"PRIx64"\n", pSarContext->TID )); + SpinLockAcquire( &pSarContext->Lock ); + if (pSarContext->State == IB_RMPP_STATE_DESTROY) + { + // destroy in progress, skip + SpinLockRelease( &pSarContext->Lock ); + + // must release list lock so Context can remove itself from list + SpinLockRelease( &g_GsaGlobalInfo->SARRecvListLock); + + // let DestroyContext we raced with have some time to complete + ThreadSuspend(1); + } else { + IncrementSarContextUsageCount( pSarContext ); + + // call with Context lock held (it releases), list lock unheld + RmppReceiverDestroyContext( pSarContext, TRUE ); + + // must release list lock so Context can remove itself from list + SpinLockRelease( &g_GsaGlobalInfo->SARRecvListLock); + + RemoveSARRecvListEntry( &pSarContext->ListItem ); + + RmppReceiverReapContext( &pSarContext->ListItem ); + } + SpinLockAcquire( &g_GsaGlobalInfo->SARRecvListLock); + } + SpinLockRelease( &g_GsaGlobalInfo->SARRecvListLock); + _DBG_LEAVE_LVL(_DBG_LVL_SAR_INFO); +} + +// Completion Handlers shared by RMPP Receiver and Sender + +// called on GSI Receive Q completion callback when a packet is received which +// is destined to a GSI Client who has requested GSI to do the +// RMPP Segmentation and Assembly +// we assume caller already verified and byte swapped MAD header +// This can be called for RMPP Contexts which are Senders or Receivers +// Returns: +// FCOMPLETED - SAR processing for this packet/transaction is done +// caller should pass *ppDgrm up to client +// Note *ppDgrm could now contain a completed RMPP message or +// a single packet which is not a multi-packet RMPP message +// FREJECT - packet is invalid and should be discarded by caller +// FPENDING - SAR processing has consumed packet +// caller should not free nor pass up to client +FSTATUS +ProcessSARRecvCompletion ( + IN MAD *pMad, + IN IBT_DGRM_ELEMENT **ppDgrm + ) +{ + FSTATUS status; + IBT_DGRM_ELEMENT_PRIV *pDgrmPrivate; + MAD_RMPP *pMadRmpp = (MAD_RMPP*)pMad; + GSA_SAR_CONTEXT *pSarContext = NULL; +#if defined( DBG) ||defined( IB_DEBUG) + static int recv_discard_counter = 0; +#endif + + _DBG_ENTER_LVL (_DBG_LVL_SAR_INFO, ProcessSARRecvCompletion ); + + pDgrmPrivate = (IBT_DGRM_ELEMENT_PRIV *)*ppDgrm; + + BSWAP_RMPP_HEADER( &pMadRmpp->RmppHdr ); + // IBTA 1.1 C13-21.1.3, pg 684 if Active == 0 ignore all other + // RMPP fields (even version) + if (! pMadRmpp->RmppHdr.RmppFlags.s.Active) + { + // BSWAP_RMPP_HEADER( &pMadRmpp->Sar ); // pass up as swapped + status = FCOMPLETED; // Single Packet, pass it on as is + goto done; + } + +#if defined( DBG) ||defined( IB_DEBUG) + // discard occasional SAR packet received, will stress retry mechanism + if (RmppRecvDiscardFreq + && ++recv_discard_counter % RmppRecvDiscardFreq == 1) + { + _DBG_PRINT_RMPP_HEADERS( _DBG_LVL_WARN, "Test Discarding Recv:\n", + pMadRmpp, (*ppDgrm)->RemoteLID); + goto discard; + } +#endif + + _DBG_PRINT_RMPP_HEADERS( (_DBG_LVL_CALLBACK + _DBG_LVL_SAR_INFO), + "RMPP Received:\n", pMadRmpp, pDgrmPrivate->DgrmElement.RemoteLID); + + // Overload base, set if it is SAR Receive data for to tell GsiCoalesceDgrm + // it has a SAR packet sequence to Coalesce + // if this was RMPP DATA , it will end up on RecvHead and ultimately + // in GsiCoalesceDgrm (or in TSL doing Coalesce), if it is an RMPP control + // packet (ACK, ABORT, etc) it will be freed long before Coalesce is called + pDgrmPrivate->Base = (GSA_POST_SEND_LIST*)1; + + // IBTA 1.1 Figure 174, pg 696 - RMPP Dispatcher + // We must use the R bit to determine our overall role in transaction + // (eg. requestor or responder). This is necessary because TIDs are only + // unique from a given requestor, so if we are both requestor and + // responder for a given class, there could be TID duplication between + // those roles. + // This is consistent with C15-0.1.18 in IBTA 1.1 which + // defines that all packets in a given direction shall have the + // same Method/R bit (it defines it by 2 specific attribute/responses) + // TBD can sender/receiver tables be moved out of gsamain.h into + // gsasar[12].c as static globals? How do we clean up tables if + // shutdown while transactions are in progress? + // Note we could be sender or receiver for either role!!! + if ( MAD_IS_RESPONSE(pMad)) + { + pSarContext = FindSarContext(pMadRmpp, *ppDgrm, FALSE); // requestor + if (pSarContext) + { + // pRmppContext->Lock is held + status = RmppReceiverProcessRecv (pSarContext, pMadRmpp, ppDgrm); + // pRmppContext->Lock was released in ProcessRecv + goto done; + } + } else { + pSarContext = FindSarContext(pMadRmpp, *ppDgrm, TRUE); // responder + if (pSarContext) + { + // pRmppContext->Lock is held + status = RmppSenderProcessRecv (pSarContext, pMadRmpp, ppDgrm); + // pRmppContext->Lock was released in ProcessRecv + goto done; + } + } + + // new RMPP context/transaction + + // IBTA 1.1 C13-21.1.4 - If Active=1 => Version must be 1 + // fig 174 Version Check + if ( RMPP_VERSION != pMadRmpp->RmppHdr.RmppVersion ) + { + _DBG_ERROR(( "Received Unsupported RMPP Version <%d>!!! \n", + pMadRmpp->RmppHdr.RmppVersion)); + SendRmppAbortReply(*ppDgrm, RMPP_STATUS_UNSUPPORTED_VERSION); + goto discard; + } + + // fig 174 Type=DATA & SegNo == 1 + if (RMPP_TYPE_DATA != pMadRmpp->RmppHdr.RmppType + || 1 != pMadRmpp->RmppHdr.u1.SegmentNum) + { + _DBG_ERROR(("Received Unexpected RMPP Packet !!! \n", + pMadRmpp->common.TransactionID, + pMadRmpp->RmppHdr.RmppType, pMadRmpp->RmppHdr.u1.SegmentNum)); + SendRmppAbortReply(*ppDgrm, RMPP_STATUS_BAD_RMPP_TYPE); + goto discard; + } + // Res Avail? + // I do this a little out of order, it makes more sense to check + // we have a valid data packet (Seg=1, Type=1) in Fig 174 + // before we go and interpret the contents + // Since our resource exhaustion can't be predicted by a remote node + // this should still be compliant + + // PayloadLen can be 0 or the actual payload Length + if (pMadRmpp->RmppHdr.u2.PayloadLen > RmppMaxReceive) + { + _DBG_ERROR(( + "RMPP Header contains a very large Payload(%d bytes)!\n" + "GSA Max payload setting (RmppMaxReceive=%d bytes) \n", + pMadRmpp->RmppHdr.u2.PayloadLen, + RmppMaxReceive)); + SendRmppStopReply(*ppDgrm, RMPP_STATUS_RESOURCES_EXHAUSTED); + goto discard; + } + + // fig 174 - allocate receive context + pSarContext = RmppReceiverCreateContext( pMadRmpp, ppDgrm ); + if (pSarContext == NULL) + { + // error message already logged in CreateContext + SendRmppStopReply(*ppDgrm, RMPP_STATUS_RESOURCES_EXHAUSTED); + goto discard; + } + + // enter fig 176 at triangle B + // pRmppContext->Lock is held + status = RmppReceiverProcessRecv ( pSarContext, pMadRmpp, ppDgrm); + // pRmppContext->Lock was released in ProcessRecv + +done: + if ( pSarContext ) + { + DecrementSarContextUsageCount( pSarContext ); + _DBG_PRINT(_DBG_LVL_SAR_INFO,("Sar Context %p: %d done recv\n", + _DBG_PTR(pSarContext), pSarContext->RefCount)); + } + _DBG_LEAVE_LVL(_DBG_LVL_SAR_INFO); + return status; + +discard: + AtomicIncrementVoid( &g_GsaGlobalInfo->SARRecvDropped ); + _DBG_LEAVE_LVL(_DBG_LVL_SAR_INFO); + return FREJECT; +} + +// called on GSI Send Q completion callback when a packet is received which +// is destined to a GSI Client who has requested GSI to do the +// RMPP Segmentation and Assembly +// This can be called for RMPP Contexts which are Senders or Receivers +void +ProcessSARSendCompletion ( + IN MAD *pMad, + IN IBT_DGRM_ELEMENT *pDgrm + ) +{ + FSTATUS status; + IBT_DGRM_ELEMENT_PRIV *pDgrmPrivate; + GSA_POST_SEND_LIST *pPostList; + MAD_RMPP *pMadRmpp = (MAD_RMPP*)pMad; + + _DBG_ENTER_LVL (_DBG_LVL_SAR_INFO, ProcessSARSendCompletion ); + + pDgrmPrivate = (IBT_DGRM_ELEMENT_PRIV *)pDgrm; + pPostList = pDgrmPrivate->Base; + BSWAP_RMPP_HEADER (&pMadRmpp->RmppHdr); + + // Check for RMPP Control messages + if( pMadRmpp->RmppHdr.RmppType != RMPP_TYPE_DATA) + { +#if defined( DBG) ||defined( IB_DEBUG) + _DBG_PRINT_RMPP_HEADERS( (_DBG_LVL_CALLBACK + _DBG_LVL_SAR_INFO), + "RMPP Control packet send completed\n", + pMadRmpp, pDgrmPrivate->DgrmElement.RemoteLID); +#endif + ASSERT ( pDgrmPrivate->AvHandle ); + status = PutAV( + NULL, + pDgrmPrivate->AvHandle ); + + // Just return to pool + status = DgrmPoolPut( pPostList->DgrmList ); + goto done; + } + +#if 1 + ASSERT(0); // send not yet implemented +#else + + // TBD - make this a function in Sender code + + // must have been a send completion on behalf of RMPP Sender + // The Dgrm came from the Gsi Client's pool so we can check for + // information about the specific client + // TBD - how does GSI Deregister handle outstanding sends in the DgrmPool?? + ASSERT(((GSA_SERVICE_CLASS_INFO*)pDgrmPrivate->MemPoolHandle->ServiceHandle)->bSARRequired); + + // TBD - will need to handle case of a Sar Recv of ACK occurring + // before send completion, especially for final send of a message + // include a DoubleSided transaction + + // BUGBUG If the completion had an error, such as flush for + // unloading module, we may attempt to send SAR here + // we should handle this special case and return to + // user callback with an error indication + // maybe we are ok, as we will post sends and get failures + // until SAR is completed. + // fix Deregister to wait for all send buffers to be returned to + // pool before DestroyDgrmPool + + _DBG_PRINT_RMPP_HEADERS( (_DBG_LVL_CALLBACK + _DBG_LVL_SAR_INFO), + "SAR send completed:\n", + pMadRmpp, pDgrmPrivate->DgrmElement.RemoteLID); + + SysCallbackQueue( + pDgrmPrivate->pSarContext->SysCBItem, + SARSendSegments, + pDgrmPrivate->pSarContext, + FALSE ); +#endif + +done: + _DBG_LEAVE_LVL(_DBG_LVL_SAR_INFO); +} + +// --------------------------------------------------------------------------- +// Internal Common RMPP Functions + +#if defined( DBG) ||defined( IB_DEBUG) +STATIC void AssertInvariants( GSA_SAR_CONTEXT* pSarContext ) +{ + _DBG_ENTER_LVL (_DBG_LVL_SAR_INFO, AssertInvariants ); + // implicit limitation in protocol of 4 Billion fragments + // no problem since would need 1024G of RAM to compose such a message + if (IB_SAR_DIR_SENDER == pSarContext->Direction) + { + _DBG_PRINT( (_DBG_LVL_CALLBACK + _DBG_LVL_SAR_INFO), + ("WF=%d WL=%d NS=%d\n", + pSarContext->WindowFirst, + pSarContext->WindowLast, + pSarContext->NextToSend)); + // 1 <= WF <= NS <= WL+1 + // on sender don't track ES +#if 0 + ASSERT(1 <= pSarContext->WindowFirst); + ASSERT(pSarContext->WindowFirst <= pSarContext->WindowLast); + ASSERT(pSarContext->WindowFirst <= pSarContext->NextToSend); + ASSERT(pSarContext->NextToSend <= pSarContext->WindowLast+1); +#else + if ((! (1 <= pSarContext->WindowFirst)) + || (! (pSarContext->WindowFirst <= pSarContext->WindowLast)) + || (! (pSarContext->WindowFirst <= pSarContext->NextToSend)) + || (! (pSarContext->NextToSend <= pSarContext->WindowLast+1))) + { + _DBG_ERROR( ("AssertInvariants: WF=%d WL=%d NS=%d\n", + pSarContext->WindowFirst, + pSarContext->WindowLast, + pSarContext->NextToSend)); + } +#endif + } else { + _DBG_PRINT( (_DBG_LVL_CALLBACK + _DBG_LVL_SAR_INFO), + ("WL=%d ES=%d TotalSegs=%d\n", + pSarContext->WindowLast, + pSarContext->ExpectedSeg, + pSarContext->TotalSegs)); + // 1 <= WF <= NS <= WL+1 + // IBTA 1.1 says 1 <= WF <= ES < NS <= WL+1 + // on receiver we don't track WF nor NS so + // 1 <= ES < WL+1 + // however, we never let WL pass TotalSegs: + // if Total Segs!=0, ES could go 1 beyond TotalSegs hence: + // ES < max(WL+1, TotalSegs+2) + // else + // ES < WL+1 + // which yields + // 1 <= ES <= max(WL, TotalSegs+1) +#if 0 + ASSERT(1 <= pSarContext->ExpectedSeg); + ASSERT(pSarContext->ExpectedSeg <= MAX(pSarContext->WindowLast,pSarContext->TotalSegs+1); + // don't open window beyond total expected + ASSERT((! pSarContext->TotalSegs) + || pSarContext->WindowLast <= pSarContext->TotalSegs); +#else + if (! (1 <= pSarContext->ExpectedSeg)) + { + _DBG_ERROR( + ("AssertInvariants 1<=ES: WL=%d ES=%d TotalSegs=%d\n", + pSarContext->WindowLast, + pSarContext->ExpectedSeg, + pSarContext->TotalSegs)); + } + if (! (pSarContext->ExpectedSeg <= MAX(pSarContext->WindowLast, pSarContext->TotalSegs+1))) + { + _DBG_ERROR( + ("AssertInvariants ES<=MAX(WL,TS+1): WL=%d ES=%d TotalSegs=%d\n", + pSarContext->WindowLast, + pSarContext->ExpectedSeg, + pSarContext->TotalSegs)); + } + if (! ((! pSarContext->TotalSegs) + || pSarContext->WindowLast <= pSarContext->TotalSegs)) + { + _DBG_ERROR( + ("AssertInvariants !TS || WL<=TS: WL=%d ES=%d TotalSegs=%d\n", + pSarContext->WindowLast, + pSarContext->ExpectedSeg, + pSarContext->TotalSegs)); + } +#endif + } + _DBG_LEAVE_LVL(_DBG_LVL_SAR_INFO); +} +#endif + +// assumes pMadRmpp is MAD header from within pDgrm which we received +// sender - is this a sender or receiver context +// BUGBUG - gsamain.h has separate lists and locks for send/recv +// worse yet if a peer to peer RMPP protocol has requests initiated +// from both nodes at eachother with same TID at same time +// Context needs an additional aspect to its key. Since peer to peer +// protocol could be bi-directional, may really need to key off of +// R bit and who initiated connection. For now sender indicates if +// we initiated context or remote node did. This is not properly +// implemented yet for the case of a bi-directional request +// because sender flag may not be set when we start to receive response. +// really need just one list with a flag in context which can be used +// to distinguish sense of context. Ask Lamprey. +// returns NULL if no matching context is found +// if found, returns with pSarContext locked, but global list unlocked +GSA_SAR_CONTEXT* +FindSarContext( + IN MAD_RMPP *pMadRmpp, + IN IBT_DGRM_ELEMENT *pDgrm, + IN boolean sender + ) +{ + GSA_SAR_CONTEXT *pSarContext; + LIST_ITEM *pListNext; + QUICK_LIST *pList; + SPIN_LOCK *pListLock; + + _DBG_ENTER_LVL (_DBG_LVL_SAR_INFO, FindSarContext); + + _DBG_PRINT (_DBG_LVL_SAR_INFO,( + "Need to find TID x%"PRIx64"\n", + pMadRmpp->common.TransactionID )); + // BUGBUG - HACK for now + if (sender) + { + pListLock = &g_GsaGlobalInfo->SARSendListLock; + pList = &g_GsaGlobalInfo->SARSendList; + } else { + pListLock = &g_GsaGlobalInfo->SARRecvListLock; + pList = &g_GsaGlobalInfo->SARRecvList; + } + + SpinLockAcquire( pListLock ); + + for ( pListNext = QListHead( pList ); + pListNext != NULL; + pListNext = QListNext( pList, pListNext )) + { + pSarContext = (GSA_SAR_CONTEXT*)pListNext; + _DBG_PRINT (_DBG_LVL_SAR_INFO,( "...TID %"PRIx64"\n", pSarContext->TID )); + + // + // IB defines an RMPP context as unique by the tuple: + // { MgmtClass, TID, LID } or { MgmtClass, TID, GID } + // To be IB Compliant, if a clients on given Node issue multiple + // requests to the same manager at the same time, the TIDs must + // be unique. Otherwise this test will locate an inaccurate Context + // TBD - BUGBUG - when create a new context lookup in here first and + // catch duplicates and provide error to local GSA client + + if (pSarContext->MgmtClass == pMadRmpp->common.MgmtClass + && pSarContext->TID == pMadRmpp->common.TransactionID + && ( pSarContext->RemoteLID == pDgrm->RemoteLID + || (pSarContext->RemoteLID == LID_RESERVED + && pDgrm->GlobalRoute + && 0 == MemoryCompare(&pSarContext->RemoteGID, &pDgrm->GRHInfo.DestGID, sizeof(IB_GID)) + ))) + { + IncrementSarContextUsageCount( pSarContext ); + _DBG_PRINT(_DBG_LVL_SAR_INFO,("Sar Context %p: %d found\n", + _DBG_PTR(pSarContext), pSarContext->RefCount)); + SpinLockRelease(pListLock); + SpinLockAcquire( &pSarContext->Lock ); + if (pSarContext->State != IB_RMPP_STATE_DESTROY) + { + goto found; + } else { + // destroy in progress, skip + SpinLockRelease( &pSarContext->Lock ); + DecrementSarContextUsageCount( pSarContext ); + _DBG_PRINT(_DBG_LVL_SAR_INFO, + ("Sar Context %p: %d found in destroy\n", + _DBG_PTR(pSarContext), pSarContext->RefCount)); + goto notfound; + } + } + } + + // not found in list + SpinLockRelease(pListLock); + +notfound: + pSarContext = NULL; + _DBG_INFO(( + "RMPP Packet: Context Not Found!\n" + "\tClass........:x%x\n" + "\tAttributeID..:x%x\n" + "\tTID..........:x%"PRIx64"\n" + "\tLID..........:x%x\n" + "\tGID..........:x%"PRIx64":%"PRIx64"\n", + pMadRmpp->common.MgmtClass, + pMadRmpp->common.AttributeID, + pMadRmpp->common.TransactionID, + pDgrm->RemoteLID, + pDgrm->GlobalRoute?pDgrm->GRHInfo.DestGID.Type.Global.SubnetPrefix:0, + pDgrm->GlobalRoute?pDgrm->GRHInfo.DestGID.Type.Global.InterfaceID:0 + )); + _DBG_PRINT_RMPP_HEADERS( _DBG_LVL_INFO, + "RMPP Packet: (cont)\n", pMadRmpp, pDgrm->RemoteLID); + +found: + _DBG_LEAVE_LVL(_DBG_LVL_SAR_INFO); + return pSarContext; +} + +// perform basic MAD validation on an RMPP MAD +// returns RMPP_STATUS value, RMPP_STATUS_NORMAL if packet is OK +STATIC +RMPP_STATUS +RmppMadCheck( + IN MAD_RMPP *pMadRmpp + ) +{ + uint32 rmppGsDataSize; + + _DBG_ENTER_LVL (_DBG_LVL_SAR_INFO, RmppMadCheck); + ASSERT(pMadRmpp->RmppHdr.RmppFlags.s.Active); // RecvCompletion checked this + if ( RMPP_VERSION != pMadRmpp->RmppHdr.RmppVersion ) + { + _DBG_ERROR(("Invalid RMPP Version <%d>!!! \n", + pMadRmpp->RmppHdr.RmppVersion)); + return RMPP_STATUS_UNSUPPORTED_VERSION; + } + switch (pMadRmpp->RmppHdr.RmppType) + { + case RMPP_TYPE_DATA: + if (RMPP_STATUS_NORMAL != pMadRmpp->RmppHdr.RmppStatus) + { + if (RmppStrict) + { + _DBG_ERROR(("RMPP DATA packet with Bad Status: %s <%d>!!! \n", + _DBG_PTR(iba_rmpp_status_msg((RMPP_STATUS)pMadRmpp->RmppHdr.RmppStatus)), + pMadRmpp->RmppHdr.RmppStatus)); + return RMPP_STATUS_ILLEGAL_STATUS; + } else { + _DBG_WARN(("RMPP DATA packet with Bad Status: %s <%d>\n", + _DBG_PTR(iba_rmpp_status_msg((RMPP_STATUS)pMadRmpp->RmppHdr.RmppStatus)), + pMadRmpp->RmppHdr.RmppStatus)); + } + } + if ((pMadRmpp->RmppHdr.u1.SegmentNum == 1) + != (pMadRmpp->RmppHdr.RmppFlags.s.FirstPkt == 1)) + { + _DBG_ERROR(("RMPP First DATA packet with Bad SegmentNum: <%d>!!! \n", + pMadRmpp->RmppHdr.u1.SegmentNum)); + return RMPP_STATUS_INCONSISTENT_FIRST; + } + if (pMadRmpp->RmppHdr.u1.SegmentNum == 0) + { + _DBG_ERROR(("RMPP DATA packet with Bad SegmentNum: <%d>!!! \n", + pMadRmpp->RmppHdr.u1.SegmentNum)); + return RMPP_STATUS_UNSPECIFIED; // TBD + } + // validate PayloadLen for a First packet + rmppGsDataSize = (pMadRmpp->common.BaseVersion == IB_BASE_VERSION) + ? IBA_RMPP_GS_DATASIZE : STL_RMPP_GS_DATASIZE; + if (pMadRmpp->RmppHdr.RmppFlags.s.FirstPkt + && ! pMadRmpp->RmppHdr.RmppFlags.s.LastPkt + && pMadRmpp->RmppHdr.u2.PayloadLen != 0 + && pMadRmpp->RmppHdr.u2.PayloadLen <= rmppGsDataSize) + { + _DBG_ERROR(("RMPP First DATA packet with Bad PayloadLen: <%d>!!! \n", + pMadRmpp->RmppHdr.u2.PayloadLen)); + return RMPP_STATUS_INCONSISTENT_PAYLOAD_LEN; + } + // validate PayloadLen for a Last packet + if (pMadRmpp->RmppHdr.RmppFlags.s.LastPkt + && ( pMadRmpp->RmppHdr.u2.PayloadLen == 0 + || pMadRmpp->RmppHdr.u2.PayloadLen > rmppGsDataSize)) + { + _DBG_ERROR(("RMPP Last DATA packet with Bad PayloadLen: <%d>!!! \n", + pMadRmpp->RmppHdr.u2.PayloadLen)); + return RMPP_STATUS_INCONSISTENT_PAYLOAD_LEN; + } + break; + case RMPP_TYPE_ACK: + if (RmppStrict && RMPP_STATUS_NORMAL != pMadRmpp->RmppHdr.RmppStatus) + { + _DBG_ERROR(("RMPP ACK with Bad Status: %s <%d>!!! \n", + _DBG_PTR(iba_rmpp_status_msg((RMPP_STATUS)pMadRmpp->RmppHdr.RmppStatus)), + pMadRmpp->RmppHdr.RmppStatus)); + return RMPP_STATUS_ILLEGAL_STATUS; + } + if (pMadRmpp->RmppHdr.RmppFlags.s.FirstPkt + || pMadRmpp->RmppHdr.RmppFlags.s.LastPkt) + { + // not sure what to send here, sounds good + _DBG_ERROR(("RMPP ACK with First or Last!!! \n")); + return RMPP_STATUS_BAD_RMPP_TYPE; + } + if (pMadRmpp->RmppHdr.u1.SegmentNum > pMadRmpp->RmppHdr.u2.NewWindowLast) + { + _DBG_ERROR(("RMPP ACK with New Window too small: Seg=%d, NWL=%d!!! \n", + pMadRmpp->RmppHdr.u1.SegmentNum, + pMadRmpp->RmppHdr.u2.NewWindowLast)); + return RMPP_STATUS_NEW_WL_TOO_SMALL; + } + break; + case RMPP_TYPE_STOP: + case RMPP_TYPE_ABORT: + // caller should not send an Abort/Stop in response to + // Abort/Stop, merely returning a non-Normal code should + // trigger caller to terminate and discard + if (RMPP_STATUS_NORMAL == pMadRmpp->RmppHdr.RmppStatus) + { + _DBG_ERROR(("RMPP %s with Bad Status: %s <%d>!!! \n", + _DBG_PTR((pMadRmpp->RmppHdr.RmppType==RMPP_TYPE_STOP) + ? "STOP":"ABORT"), + _DBG_PTR(iba_rmpp_status_msg((RMPP_STATUS)pMadRmpp->RmppHdr.RmppStatus)), + pMadRmpp->RmppHdr.RmppStatus)); + return RMPP_STATUS_ILLEGAL_STATUS; + } + if (pMadRmpp->RmppHdr.RmppFlags.s.FirstPkt + || pMadRmpp->RmppHdr.RmppFlags.s.LastPkt) + { + _DBG_ERROR(("RMPP %s with First or Last!!! \n", + _DBG_PTR((pMadRmpp->RmppHdr.RmppType==RMPP_TYPE_STOP) + ? "STOP":"ABORT"))); + // not sure what to send here, sounds good + return RMPP_STATUS_BAD_RMPP_TYPE; + } + break; + default: + _DBG_ERROR(("Invalid RMPP Type <%d>!!! \n", + pMadRmpp->RmppHdr.RmppType)); + return RMPP_STATUS_BAD_RMPP_TYPE; + } + if (RMPP_STATUS_START_RESERVED <= pMadRmpp->RmppHdr.RmppStatus + && pMadRmpp->RmppHdr.RmppStatus <= RMPP_STATUS_END_RESERVED) + { + _DBG_ERROR(("Invalid RMPP Status %s <%d>!!! \n", + _DBG_PTR(iba_rmpp_status_msg((RMPP_STATUS)pMadRmpp->RmppHdr.RmppStatus)), + pMadRmpp->RmppHdr.RmppStatus)); + return RMPP_STATUS_ILLEGAL_STATUS; + } + return RMPP_STATUS_NORMAL; +} + +// to support DoubleSided RMPP, we use a common timer +// hence we can use the same context twice +STATIC +void +RmppTimerCallback( + IN void *TimerContext + ) +{ + GSA_SAR_CONTEXT *pSarContext = (GSA_SAR_CONTEXT*)TimerContext; + + // if context is being destroyed, nothing to do here + if (pSarContext->State != IB_RMPP_STATE_DESTROY) + { + if (IB_SAR_DIR_SENDER == pSarContext->Direction) + { + RmppSenderTimerCallback(pSarContext); + } else { // receiver + RmppReceiverTimerCallback(pSarContext); + } + } +} + + +// --------------------------------------------------------------------------- +// RMPP Receiver + +// +// Create RMPP Context for a Receiver +// +// Returns: +// NULL - unable to create context +// ! NULL - a created context which is locked +GSA_SAR_CONTEXT* +RmppReceiverCreateContext( + IN MAD_RMPP *pMadRmpp, + IN IBT_DGRM_ELEMENT **ppDgrm + ) +{ + GSA_SAR_CONTEXT *pSarContext; + IBT_DGRM_ELEMENT *pDgrm = *ppDgrm; + + _DBG_ENTER_LVL (_DBG_LVL_SAR_INFO, RmppReceiverCreateContext); + + ASSERT(RMPP_TYPE_DATA == pMadRmpp->RmppHdr.RmppType); // caller checked + ASSERT(1 == pMadRmpp->RmppHdr.u1.SegmentNum); // caller checked + ASSERT(pMadRmpp->RmppHdr.RmppFlags.s.Active); // caller checked + + // Looks sane, lets create the context now + pSarContext = (GSA_SAR_CONTEXT*)MemoryAllocateAndClear(sizeof(GSA_SAR_CONTEXT), FALSE, GSA_MEM_TAG); + if ( NULL == pSarContext ) + { + _DBG_ERROR (( "Not enough memory for RMPP Context! \n")); + goto failedalloc; + } + + SpinLockInitState(&pSarContext->Lock); + TimerInitState(&pSarContext->Timer); + if ( TRUE != SpinLockInit( &pSarContext->Lock )) + { + _DBG_ERROR (( "RMPP Lock Init failed! \n" )); + goto failedlockinit; + } + if ( TRUE != TimerInit( &pSarContext->Timer, RmppTimerCallback, + pSarContext )) + { + _DBG_ERROR (( "RMPP Timer Init failed! \n" )); + goto failedtimerinit; + } + + pSarContext->TID = pMadRmpp->common.TransactionID; + pSarContext->MgmtClass = pMadRmpp->common.MgmtClass; + if (pDgrm->GlobalRoute) + { + pSarContext->RemoteLID = LID_RESERVED; + pSarContext->RemoteGID = pDgrm->GRHInfo.DestGID; + } else { + pSarContext->RemoteLID = pDgrm->RemoteLID; + MemoryClear(&pSarContext->RemoteGID, sizeof(pSarContext->RemoteGID)); + } + pSarContext->ExpectedSeg= 1; + pSarContext->WindowLast = 1; + // receiver controls the RRespTime. It is how fast sender + // can expect us to turnaround ACKs + // use our default + pSarContext->RespTimeout = GSA_SAR_DEFAULT_RESP_TIMEOUT; + pSarContext->TotalTimeout = GSA_SAR_DEFAULT_TOTAL_TIMEOUT; + pSarContext->Direction = IB_SAR_DIR_RECEIVER; + pSarContext->IsDoubleSided = 0; // BUGBUG but ok for SA responses + pSarContext->State= IB_RMPP_STATE_CREATED; // processing 1st packet + AtomicWrite( &pSarContext->RefCount, 0 ); + + // Add to Context to Global SAR recv list + SpinLockAcquire( &g_GsaGlobalInfo->SARRecvListLock ); + QListInsertHead( &g_GsaGlobalInfo->SARRecvList, &pSarContext->ListItem ); + IncrementSarContextUsageCount( pSarContext ); + _DBG_PRINT(_DBG_LVL_SAR_INFO,("Sar Context %p: %d add to list\n", + _DBG_PTR(pSarContext), pSarContext->RefCount)); + SpinLockRelease( &g_GsaGlobalInfo->SARRecvListLock ); + + AssertInvariants(pSarContext); + + SpinLockAcquire(&pSarContext->Lock); + + IncrementSarContextUsageCount( pSarContext ); + _DBG_PRINT(_DBG_LVL_SAR_INFO,("Sar Context %p: %d create ret\n", + _DBG_PTR(pSarContext), pSarContext->RefCount)); + +#if defined( DBG) ||defined( IB_DEBUG) + AtomicIncrement(&SarContexts); + AtomicIncrement(&ActiveSarContexts); + _DBG_PRINT(_DBG_LVL_SAR_INFO, + ("Created Sar Context %p, total %d active %d\n", _DBG_PTR(pSarContext), + AtomicRead(&SarContexts), AtomicRead(&ActiveSarContexts))); +#endif + _DBG_LEAVE_LVL(_DBG_LVL_SAR_INFO); + return pSarContext; + + // failures during creation of Context + // cleanup partially created context and send a Stop +failedtimerinit: + SpinLockDestroy( &pSarContext->Lock ); +failedlockinit: + MemoryDeallocate ( pSarContext ); +failedalloc: + _DBG_LEAVE_LVL(_DBG_LVL_SAR_INFO); + return NULL; +} + +// called with pSarContext Lock held, will unlock before returns +// Returns: +// FCOMPLETED - SAR processing for this packet/transaction is done +// caller should pass *ppDgrm up to client +// Note *ppDgrm could now contain a completed RMPP message or +// a single packet which is not a multi-packet RMPP message +// FREJECT - packet is invalid and should be discarded by caller +// FPENDING - SAR processing has consumed packet +// caller should not free nor pass up to client +FSTATUS +RmppReceiverProcessRecv ( + IN GSA_SAR_CONTEXT *pSarContext, + IN MAD_RMPP *pMadRmpp, + IN IBT_DGRM_ELEMENT **ppDgrm + ) +{ + IBT_DGRM_ELEMENT *pDgrm; + FSTATUS status; + RMPP_STATUS RmppStatus; + uint32 rmppGsDataSize; + + _DBG_ENTER_LVL (_DBG_LVL_SAR_INFO, RmppReceiverProcessRecv); + + pDgrm = *ppDgrm; + + // FindSarContext should have checked for Destroy + ASSERT(pSarContext->State != IB_RMPP_STATE_DESTROY); + + AssertInvariants(pSarContext); + // Mad OK fig 176 and fig 177 after get packet + if (pSarContext->RecvHead) + { + // verify Common Mad Header consistent with first mad in transaction + MAD_RMPP *pFirstMadRmpp = \ + (MAD_RMPP *)GsiDgrmGetRecvMad(pSarContext->RecvHead); + ASSERT(pFirstMadRmpp->common.MgmtClass == pMadRmpp->common.MgmtClass); + ASSERT(pFirstMadRmpp->common.TransactionID == pMadRmpp->common.TransactionID); + if (pFirstMadRmpp->common.BaseVersion != pMadRmpp->common.BaseVersion + || pFirstMadRmpp->common.ClassVersion != pMadRmpp->common.ClassVersion + || pFirstMadRmpp->common.mr.s.Method != pMadRmpp->common.mr.s.Method + || pFirstMadRmpp->common.mr.s.R != pMadRmpp->common.mr.s.R + // C15-0.1.18 + // Attribute contents in all but DATA packets shall be + // ignored. + || (pMadRmpp->RmppHdr.RmppType == RMPP_TYPE_DATA + && (pFirstMadRmpp->common.AttributeID!= pMadRmpp->common.AttributeID + || pFirstMadRmpp->common.AttributeModifier!= pMadRmpp->common.AttributeModifier)) + // don't check Status - TBD + ) + { + if (RmppStrict) + { + _DBG_ERROR(("Received RMPP with inconsistent Mad Header!!! \n")); + SendRmppAbortReply(*ppDgrm, RMPP_STATUS_UNSPECIFIED); + status = FREJECT; + goto terminate; + } else { + _DBG_WARN(("Received RMPP with inconsistent Mad Header!!! \n")); + } + } + // not sure how to do this, we use first failure status as overall + // mad status + if (pMadRmpp->common.u.NS.Status.AsReg16 != MAD_STATUS_SUCCESS + && pFirstMadRmpp->common.u.NS.Status.AsReg16 == MAD_STATUS_SUCCESS) + { + pFirstMadRmpp->common.u.NS.Status.AsReg16 = \ + pMadRmpp->common.u.NS.Status.AsReg16; + _DBG_WARN(("Received RMPP with different Mad Status than original Mad Header!!! \n")); + } + } + RmppStatus = RmppMadCheck(pMadRmpp); + if (RMPP_STATUS_NORMAL != RmppStatus) + { + // MadCheck already logged error message + SendRmppAbortReply(*ppDgrm, RmppStatus); + status = FREJECT; + goto terminate; + } + if (pSarContext->State == IB_RMPP_STATE_TIMEWAIT) + { + // were in wait circle on fig 175 + goto discard; + } else if (pSarContext->State == IB_RMPP_STATE_TIMEWAIT_RECV) { + // were in wait circle on fig 177 + if (pMadRmpp->RmppHdr.RmppType == RMPP_TYPE_DATA) + { + status = FREJECT; // discard + // ReceiverTerminate releases lock + RmppReceiverTerminate(pSarContext, IB_RMPP_STATE_TIMEWAIT_RECV, pDgrm); + AtomicIncrementVoid( &g_GsaGlobalInfo->SARRecvDropped ); + goto done_lockreleased; + } else if (pMadRmpp->RmppHdr.RmppType == RMPP_TYPE_ACK) { + if (pSarContext->IsDoubleSided) { + pSarContext->IsDoubleSided = FALSE; + // TBD - initialize sender context setting WF from packet + ASSERT(0); // sender not yet implemented + status = FREJECT; + goto terminate; + } else { + _DBG_ERROR(("Received Bad RMPP Type for Receiver TimeWait!!! \n")); + SendRmppAbortReply(*ppDgrm, RMPP_STATUS_BAD_RMPP_TYPE); + status = FREJECT; + goto terminate; + } + } else if (pMadRmpp->RmppHdr.RmppType == RMPP_TYPE_STOP // errata 3735 + || pMadRmpp->RmppHdr.RmppType == RMPP_TYPE_ABORT) { + status = FREJECT; + goto terminate; + } else { + _DBG_ERROR(("Received Bad RMPP Type <%d> for Receiver TimeWait!!! \n", + pMadRmpp->RmppHdr.RmppType)); + SendRmppAbortReply(*ppDgrm, RMPP_STATUS_BAD_RMPP_TYPE); + status = FREJECT; + goto terminate; + } + } else { + // were in wait circle on fig 176 + if (pMadRmpp->RmppHdr.RmppType == RMPP_TYPE_ABORT + || pMadRmpp->RmppHdr.RmppType == RMPP_TYPE_STOP) + { + _DBG_ERROR(("RMPP Transaction x%"PRIx64" %s: RMPP Status: %s <%d>!!!\n", + pMadRmpp->common.TransactionID, + _DBG_PTR((pMadRmpp->RmppHdr.RmppType==RMPP_TYPE_ABORT?"Aborted":"Stopped")), + _DBG_PTR(iba_rmpp_status_msg((RMPP_STATUS)pMadRmpp->RmppHdr.RmppStatus)), + pMadRmpp->RmppHdr.RmppStatus + )); + + status = FREJECT; + goto terminate; + } else if (pMadRmpp->RmppHdr.RmppType == RMPP_TYPE_ACK) { + goto discard; + } else { + ASSERT(pMadRmpp->RmppHdr.RmppType == RMPP_TYPE_DATA); + if (pMadRmpp->RmppHdr.u1.SegmentNum != pSarContext->ExpectedSeg) + { + SendRmppAck(pSarContext, pDgrm); + goto discard; + } + _DBG_PRINT(_DBG_LVL_SAR_INFO, ("Got expected segment x%"PRIx64":%d\n", + pMadRmpp->common.TransactionID, + pMadRmpp->RmppHdr.u1.SegmentNum)); + if (pMadRmpp->RmppHdr.u1.SegmentNum == 1) + { + // PayloadLen processing + // PayloadLen is 0 or exact payload size + // TBD - a ROUNDUP function + rmppGsDataSize = (pMadRmpp->common.BaseVersion == IB_BASE_VERSION) + ? IBA_RMPP_GS_DATASIZE : STL_RMPP_GS_DATASIZE; + pSarContext->TotalSegs = + (pMadRmpp->RmppHdr.u2.PayloadLen +rmppGsDataSize -1) + / rmppGsDataSize; + pSarContext->TotalDataSize= pMadRmpp->RmppHdr.u2.PayloadLen; + + _DBG_PRINT (_DBG_LVL_SAR_INFO,( "RMPP Payload Length = %d bytes\n", + pSarContext->TotalDataSize )); + // compute TTIME and set wait timer + // BUGBUG TBD need to get this from class registration + // if PacketLifetimes + RespTimes >= 1 second + // the equation on pg 691 quickly exceeds 320 sec + // so we just use the default + // The equation on pg 691 is problematic since we don't know + // packet lifetimes for the path (that's why we are doing SA + // query in the first place!!!) + pSarContext->TotalTimeout = GSA_SAR_DEFAULT_TOTAL_TIMEOUT; + ASSERT(pSarContext->State == IB_RMPP_STATE_CREATED); + if( !StartSarContextTimer( pSarContext, pSarContext->TotalTimeout)) + { + _DBG_ERROR (( "Error in Timer Start! \n")); + SendRmppStopReply(pDgrm, RMPP_STATUS_RESOURCES_EXHAUSTED); + status = FREJECT; + goto terminate; + } + pSarContext->State= IB_RMPP_STATE_ACTIVE; // in fig 176 Wait + _DBG_PRINT(_DBG_LVL_SAR_INFO, + ("Sar Context %p: started total timer, state=%d\n", + _DBG_PTR(pSarContext), pSarContext->State)); + // Store Data -> first packet in message + pSarContext->RecvHead = pSarContext->RecvTail = pDgrm; + } else { + ASSERT(pSarContext->RecvTail); + ASSERT(pDgrm->Element.pNextElement == NULL); + if (pSarContext->RecvTail->Element.pNextElement != NULL + || ((MAD_RMPP *)GsiDgrmGetRecvMad(pSarContext->RecvTail))->RmppHdr.u1.SegmentNum != (pSarContext->ExpectedSeg-1)) + { + _DBG_ERROR (("Datagram list corrupted pSarContext %p SegmentNum %d ExpectedSeg %d pNextElement %p\n", + _DBG_PTR(pSarContext), ((MAD_RMPP *)GsiDgrmGetRecvMad(pSarContext->RecvTail))->RmppHdr.u1.SegmentNum, + pSarContext->ExpectedSeg, _DBG_PTR(pSarContext->RecvTail->Element.pNextElement))); + DumpDgrmElement(pSarContext->RecvHead); + SendRmppStopReply(pDgrm, RMPP_STATUS_RESOURCES_EXHAUSTED); + status = FREJECT; + goto terminate; + } + // Store Data -> additional packet in message + pSarContext->RecvTail->Element.pNextElement = (IBT_ELEMENT *)pDgrm; + pSarContext->RecvTail = pDgrm; + pSarContext->RecvHead->TotalRecvSize += pDgrm->Element.RecvByteCount; + } + // ES++ + ++pSarContext->ExpectedSeg; + status = FPENDING; + +#ifdef VALIDATE_SAR_LIST +// MsgOut("SarContext is %svalid\n", IsRecvSarListValid(pSarContext)==TRUE ? "" : "NOT "); + if (IsRecvSarListValid(pSarContext) == FALSE) + { + _DBG_ERROR(("SarContext is NOT valid\n")); + } +#endif // VALIDATE_SAR_LIST + + if (pMadRmpp->RmppHdr.RmppFlags.s.LastPkt) + { + status = RmppReceiverGotLast(pSarContext, pMadRmpp, ppDgrm); + // since we stored the data above, on error we return FPENDING + // pDgrm will be freed when we destroy the Context + ASSERT(status != FREJECT); + goto done_lockreleased; + } + + // check if we already got as many as expected + if (pSarContext->TotalSegs != 0 + && pSarContext->ExpectedSeg > pSarContext->TotalSegs) + { + _DBG_ERROR(("Received non-Last Segment when expected Last <%d>!!! \n", + pMadRmpp->RmppHdr.u1.SegmentNum)); + SendRmppAbortReply(*ppDgrm, RMPP_STATUS_INCONSISTENT_PAYLOAD_LEN); + // since we stored the data above, on error we return FPENDING + // pDgrm will be freed when we destroy the Context + status = FPENDING; + goto terminate; + } + RmppReceiverSendAckIfNeeded(pSarContext, pDgrm); + goto done; + } + } +done: + SpinLockRelease(&pSarContext->Lock); +done_lockreleased: + _DBG_LEAVE_LVL(_DBG_LVL_SAR_INFO); + return status; + +discard: + SpinLockRelease(&pSarContext->Lock); + AtomicIncrementVoid( &g_GsaGlobalInfo->SARRecvDropped ); + _DBG_LEAVE_LVL(_DBG_LVL_SAR_INFO); + return FREJECT; + +terminate: + // ReceiverTerminate releases lock + RmppReceiverTerminate(pSarContext, IB_RMPP_STATE_TIMEWAIT, pDgrm); + AtomicIncrementVoid( &g_GsaGlobalInfo->SARRecvDropped ); + _DBG_LEAVE_LVL(_DBG_LVL_SAR_INFO); + return status; +} + +// received last packet +// called in RecvCompletionCallback for +// Last Pkt?=Yes at bottom of Fig 176 +// called with pSarContext Lock held, will unlock before returns +// returns: +// FPENDING - premature Last, we will terminate SAR context +// FCOMPLETED - good completion, *ppDgrm is list of all response data packets +STATIC +FSTATUS +RmppReceiverGotLast( + IN GSA_SAR_CONTEXT *pSarContext, + IN MAD_RMPP *pMadRmpp, + IN IBT_DGRM_ELEMENT **ppDgrm + ) +{ + uint32 rmppGsDataSize; + + _DBG_ENTER_LVL (_DBG_LVL_SAR_INFO, RmppReceiverGotLast); + + // check if got less than expected + if (pSarContext->TotalSegs != 0 + && pMadRmpp->RmppHdr.u1.SegmentNum != pSarContext->TotalSegs) + { + _DBG_ERROR(("Received Last Segment prematurely <%d>!!! \n", + pMadRmpp->RmppHdr.u1.SegmentNum)); + SendRmppAbortReply(*ppDgrm, RMPP_STATUS_INCONSISTENT_PAYLOAD_LEN); + goto terminate; + } + + // special Store Data processing for Last packet + // - prep for delivery to client + ASSERT(pMadRmpp->RmppHdr.RmppFlags.s.LastPkt); + ASSERT(pMadRmpp->RmppHdr.RmppType == RMPP_TYPE_DATA); + ASSERT(pSarContext->State == IB_RMPP_STATE_ACTIVE); + StopSarContextTimer( pSarContext ); // transaction done, stop TotalTimeout + pSarContext->State= IB_RMPP_STATE_DONE; // handing up message + + // compute overall payload size and put in first for use by client + // last indicates amount of data in itself + rmppGsDataSize = (pMadRmpp->common.BaseVersion == IB_BASE_VERSION) + ? IBA_RMPP_GS_DATASIZE : STL_RMPP_GS_DATASIZE; + ((MAD_RMPP *)GsiDgrmGetRecvMad(pSarContext->RecvHead))->RmppHdr.u2.PayloadLen = + (pMadRmpp->RmppHdr.u1.SegmentNum-1) * rmppGsDataSize + + pMadRmpp->RmppHdr.u2.PayloadLen; + + // Return all segments to the user + ASSERT(pSarContext->RecvHead); + *ppDgrm = pSarContext->RecvHead; + + // delink from SAR Context so termination won't affect + pSarContext->RecvHead = pSarContext->RecvTail = NULL; + + // ReceiverTerminate releases lock + RmppReceiverTerminate(pSarContext, IB_RMPP_STATE_TIMEWAIT_RECV, *ppDgrm); + + // caller will Invoke the user callback for the completed datagram. + _DBG_LEAVE_LVL(_DBG_LVL_SAR_INFO); + return FCOMPLETED; + +terminate: + // ReceiverTerminate releases lock + RmppReceiverTerminate(pSarContext, IB_RMPP_STATE_TIMEWAIT, *ppDgrm); + AtomicIncrementVoid( &g_GsaGlobalInfo->SARRecvDropped ); + _DBG_LEAVE_LVL(_DBG_LVL_SAR_INFO); + return FPENDING; +} + +// handles the Time To Ack? block in fig 176 +// pDgrm is used as template for ACK, but is unmodified +void +RmppReceiverSendAckIfNeeded( + IN GSA_SAR_CONTEXT *pSarContext, + IN IBT_DGRM_ELEMENT *pDgrm + ) +{ + _DBG_ENTER_LVL (_DBG_LVL_SAR_INFO, RmppReceiverSendAckIfNeeded); + if (pSarContext->ExpectedSeg > pSarContext->WindowLast) + { + // we must advance window + pSarContext->WindowLast = pSarContext->ExpectedSeg + RmppWindowSize-1; + } else if (pSarContext->WindowLast - (pSarContext->ExpectedSeg-1) >= RmppWindowLowWater) + { + // to keep things flowing, once we get to low water of window size + // we advance windowsize + pSarContext->WindowLast = pSarContext->ExpectedSeg + RmppWindowSize-1; + } else { + _DBG_LEAVE_LVL(_DBG_LVL_SAR_INFO); + return; + } + // don't let window go beyond last, may confuse sender + // before this test, caller should have checked for the error of + // !Last but beyond TotalSegs, + // so we know cutting back will still yield a valid WindowLast + if (pSarContext->TotalSegs + && pSarContext->WindowLast > pSarContext->TotalSegs) + { + pSarContext->WindowLast = pSarContext->TotalSegs; + } + AssertInvariants(pSarContext); + SendRmppAck(pSarContext, pDgrm); + _DBG_LEAVE_LVL(_DBG_LVL_SAR_INFO); +} + +// called to terminate a Receiver Transaction by moving to the specified +// TIMEWAIT or TIMEWAIT_RECV state +// must be called with pSarContext Lock held, will unlock before returns +// (and possibly destroy the context) +// caller should not access context after making this call +// pDgrm is a template for a possible Stop reply if problems occur +void +RmppReceiverTerminate( + IN GSA_SAR_CONTEXT *pSarContext, + IN RMPP_CONTEXT_STATE newState, + IN IBT_DGRM_ELEMENT *pDgrm + ) +{ + boolean timerArmed; + + _DBG_ENTER_LVL (_DBG_LVL_SAR_INFO, RmppReceiverTerminate); + ASSERT(newState == IB_RMPP_STATE_TIMEWAIT + || newState == IB_RMPP_STATE_TIMEWAIT_RECV); + timerArmed = SarContextTimerArmed(pSarContext); + _DBG_PRINT(_DBG_LVL_SAR_INFO, + ("Sar Context %p: ReceiverTerminate, state=%d, timerArmed=%d\n", + _DBG_PTR(pSarContext), pSarContext->State, timerArmed)); + pSarContext->State = newState; + if (newState == IB_RMPP_STATE_TIMEWAIT_RECV) + { + // top of fig 177 + SendRmppAck(pSarContext, pDgrm); + } else { + // top of fig 175 + } + + if (timerArmed) { + // no worry about timer removing last reference, we should also + // still be on RecvList + StopSarContextTimer( pSarContext ); + } + + // Return any queued datagram segments to the datagram pool. + if (pSarContext->RecvHead) + { + DgrmPoolPut( pSarContext->RecvHead ); + pSarContext->RecvHead = pSarContext->RecvTail = NULL; + } + + // wait timer <- Resp + if( !StartSarContextTimer( pSarContext, pSarContext->RespTimeout)) + { + // we send stop, if sender is done, this will be benign + // if sender never got our ack, they will know we have destroyed context + _DBG_ERROR (( "Error in Timer Start! \n")); + SendRmppStopReply(pDgrm, RMPP_STATUS_RESOURCES_EXHAUSTED); + RmppReceiverDestroyContext( pSarContext, FALSE); + RemoveSARRecvListEntry( &pSarContext->ListItem ); + } else { + SpinLockRelease(&pSarContext->Lock); + } + _DBG_LEAVE_LVL(_DBG_LVL_SAR_INFO); +} + +// Timer callback for RMPP Receiver Timeouts +void +RmppReceiverTimerCallback( + IN GSA_SAR_CONTEXT *pSarContext + ) +{ + _DBG_ENTER_LVL (_DBG_LVL_SAR_INFO, RmppReceiverTimerCallback); + + SpinLockAcquire(&pSarContext->Lock); + + if (TimerCallbackStopped(&pSarContext->Timer)) + { + // stale timer callback + SpinLockRelease(&pSarContext->Lock); + goto done; + } + + if (pSarContext->State == IB_RMPP_STATE_DESTROY) + { + _DBG_INFO(("RMPP Receiver Timeout in destroy State\n")); + SpinLockRelease(&pSarContext->Lock); + goto done; + } + if (pSarContext->State == IB_RMPP_STATE_TIMEWAIT + || pSarContext->State == IB_RMPP_STATE_TIMEWAIT_RECV) + { + // in circle in fig 177 + // simple timewait period is done + // don't assert invariants, could have aborted in a weird state + // RecvHead could be empty or full depending on when bad one occurred + _DBG_INFO(("RMPP Receiver TimeWait done\n")); + } else { + IBT_DGRM_ELEMENT *pDgrm = pSarContext->RecvHead; + // in circle in fig 176 + ASSERT(pSarContext->State == IB_RMPP_STATE_ACTIVE); + // total transaction timeout + ASSERT(pSarContext->RecvHead != NULL); // must have gotten at least 1 + AssertInvariants(pSarContext); + // use 1st valid Dgrm we received for this transaction as template + // for Abort. Only MAD Header and path information is used + _DBG_ERROR (( "RMPP Total Transaction Timeout ! \n", + pSarContext->TID, pSarContext->TotalTimeout)); + SendRmppAbortReply(pDgrm, RMPP_STATUS_TOTAL_TIME_TOO_LONG); + } + + RmppReceiverDestroyContext( pSarContext, FALSE ); + RemoveSARRecvListEntry( &pSarContext->ListItem ); + +done: + DecrementSarContextUsageCount( pSarContext ); + _DBG_PRINT(_DBG_LVL_SAR_INFO, ("Sar Context %p: %d timeout\n", + _DBG_PTR(pSarContext), pSarContext->RefCount)); + _DBG_LEAVE_LVL(_DBG_LVL_SAR_INFO); +} + +void +RmppReceiverReapContext( + IN LIST_ITEM *pItem + ) +{ + GSA_SAR_CONTEXT *pSarContext = PARENT_STRUCT(pItem, GSA_SAR_CONTEXT, ListItem); + + // Return any queued datagram segments to the datagram pool. + if (pSarContext->RecvHead) + { + DgrmPoolPut( pSarContext->RecvHead ); + pSarContext->RecvHead = pSarContext->RecvTail = NULL; + } + + SpinLockDestroy( &pSarContext->Lock ); + TimerDestroy( &pSarContext->Timer ); +#if defined( DBG) || defined(IB_DEBUG) + AtomicDecrement(&SarContexts); + _DBG_PRINT(_DBG_LVL_SAR_INFO, + ("Reaped Sar Context %p, total %d, active %d\n", _DBG_PTR(pSarContext), + AtomicRead(&SarContexts), AtomicRead(&ActiveSarContexts))); +#endif + MemoryDeallocate( pSarContext ); +} + +void +RmppReceiverDestroyContext( + IN GSA_SAR_CONTEXT *pSarContext, + IN boolean stopTimer + ) +{ + boolean timerArmed; + + // tell RmppFindContext and RmppTimerCallback to ignore this context + ASSERT(pSarContext->State != IB_RMPP_STATE_DESTROY); + timerArmed = SarContextTimerArmed(pSarContext); + pSarContext->State = IB_RMPP_STATE_DESTROY; + // Return any queued datagram segments to the datagram pool. + if (pSarContext->RecvHead) + { + DgrmPoolPut( pSarContext->RecvHead ); + pSarContext->RecvHead = pSarContext->RecvTail = NULL; + } + + SpinLockRelease(&pSarContext->Lock); + // since searches get list lock then sar lock, if a search finds us now + // we will be marked as destroy, so they will do nothing. however + // since we get list lock below to remove from list, we know search is + // done with us before we proceed to destroy ourselves + + if (stopTimer && timerArmed) + StopSarContextTimer( pSarContext ); + // Stop should have ensured timer callback will not be called from here on +} + +// +// Remove from Global SAR recv Q +// +FSTATUS +RemoveSARRecvListEntry( + IN LIST_ITEM *pItem + ) +{ + FSTATUS status = FSUCCESS; + + _DBG_ENTER_LVL(_DBG_LVL_SAR_INFO, RemoveSARRecvListEntry); + + SpinLockAcquire(&g_GsaGlobalInfo->SARRecvListLock); + ASSERT (QListIsItemInList( &g_GsaGlobalInfo->SARRecvList, pItem )); + if ( !QListIsItemInList( &g_GsaGlobalInfo->SARRecvList, pItem )) + { + status = FINVALID_PARAMETER; + _DBG_ERROR(("Item not in List!!!\n")); + } else { + GSA_SAR_CONTEXT *pSarContext = PARENT_STRUCT(pItem, GSA_SAR_CONTEXT, ListItem); + + QListRemoveItem ( &g_GsaGlobalInfo->SARRecvList, pItem ); + + // Decrement reference to context + DecrementSarContextUsageCount( pSarContext ); + _DBG_PRINT(_DBG_LVL_SAR_INFO,("Sar Context %p: %d remove from list\n", + _DBG_PTR(pSarContext), pSarContext->RefCount)); + } + SpinLockRelease(&g_GsaGlobalInfo->SARRecvListLock); + + _DBG_LEAVE_LVL(_DBG_LVL_SAR_INFO); + return status; +} + + +// called with pSarContext->Lock held, must release first +#if 0 +boolean +IsRmppMethod( + IN MAD_RMPP *pMadRmpp + ) +{ + switch (pMadRmpp->common.mr.AsReg8) + { + default: + return FALSE; + break; // do nothing + + BUGBUG - fix this, also use #defines + case 0x92: // SubnAdminGetTableResp() + case 0x14: // SubnAdminGetMulti() + case 0x94: // SubnAdminGetMultiResp() + + return TRUE; + break; + } +} +#endif + +STATIC void BuildRmppAck( + IN RMPP_HEADER *pRmppHdr, + IN uint8 RRespTime, + IN uint32 SegmentNum, + IN uint32 NewWindowLast + ) +{ + MemoryClear(pRmppHdr, sizeof(*pRmppHdr)); + pRmppHdr->RmppVersion = RMPP_VERSION; + pRmppHdr->RmppType = RMPP_TYPE_ACK; + pRmppHdr->RmppFlags.s.RRespTime = RRespTime; + pRmppHdr->RmppFlags.s.Active = 1; + pRmppHdr->RmppStatus = RMPP_STATUS_NORMAL; + pRmppHdr->u1.SegmentNum = SegmentNum; + pRmppHdr->u2.NewWindowLast = NewWindowLast; +} + +STATIC void BuildRmppStop( + IN RMPP_HEADER *pRmppHdr, + IN uint8 RmppStatus + ) +{ + MemoryClear(pRmppHdr, sizeof(*pRmppHdr)); + pRmppHdr->RmppVersion = RMPP_VERSION; + pRmppHdr->RmppType = RMPP_TYPE_STOP; + pRmppHdr->RmppFlags.s.RRespTime = RMPP_RRESPTIME_NONE; + pRmppHdr->RmppFlags.s.Active = 1; + pRmppHdr->RmppStatus = RmppStatus; +} + +STATIC void BuildRmppAbort( + IN RMPP_HEADER *pRmppHdr, + IN uint8 RmppStatus + ) +{ + MemoryClear(pRmppHdr, sizeof(*pRmppHdr)); + pRmppHdr->RmppVersion = RMPP_VERSION; + pRmppHdr->RmppType = RMPP_TYPE_ABORT; + pRmppHdr->RmppFlags.s.RRespTime = RMPP_RRESPTIME_NONE; + pRmppHdr->RmppFlags.s.Active = 1; + pRmppHdr->RmppStatus = RmppStatus; +} + +STATIC void SendRmppAck( + IN GSA_SAR_CONTEXT *pSarContext, + IN IBT_DGRM_ELEMENT *pDgrm + ) +{ + RMPP_HEADER RmppHdr; + + // 1 || to always specify + // lower risk in case SA forgot to test for RRESPTIME_NONE + if (1 || pSarContext->ExpectedSeg == 2) + { + // to avoid churn, we set RRespTime in our first ACK + // then we specify None + BuildRmppAck(&RmppHdr, GSA_SAR_RECV_RESP_TIMEOUT_MULT, + pSarContext->ExpectedSeg-1, pSarContext->WindowLast); + // now that we told sender, we can adjust out timeout for use + // in our timewait state + pSarContext->RespTimeout = GSA_SAR_RECV_RESP_TIMEOUT; + } else { + BuildRmppAck(&RmppHdr, RMPP_RRESPTIME_NONE, + pSarContext->ExpectedSeg-1, pSarContext->WindowLast); + } + SendRmppReply(pDgrm, &RmppHdr); +} + +STATIC void SendRmppStopReply( + IN IBT_DGRM_ELEMENT *pDgrm, + IN uint8 RmppStatus + ) +{ + RMPP_HEADER RmppHdr; + + BuildRmppStop(&RmppHdr, RmppStatus); + SendRmppReply(pDgrm, &RmppHdr); +} + +STATIC void SendRmppAbortReply( + IN IBT_DGRM_ELEMENT *pDgrm, + IN uint8 RmppStatus + ) +{ + RMPP_HEADER RmppHdr; + + BuildRmppAbort(&RmppHdr, RmppStatus); + SendRmppReply(pDgrm, &RmppHdr); +} + +// uses pDgrm as a template for building an RMPP reply +// (ABORT, STOP, ACK) +// MAD header and AV information is taken from pDgrm (including TID) +// with R bit inverted +// pRmppHdr is used entirely as given +// rest of MAD is zero'ed +// pDgrm is unaffected +STATIC void SendRmppReply( + IN IBT_DGRM_ELEMENT *pDgrm, + IN RMPP_HEADER *pRmppHdr + ) +{ + FSTATUS status = FSUCCESS; + uint32 i; + IBT_DGRM_ELEMENT *pDgrmList; + GSA_POST_SEND_LIST *pPostList; + MAD_RMPP *pMadRmpp; +#if defined(DBG) || defined(IB_DEBUG) + static int send_discard_counter = 0; +#endif + + _DBG_ENTER_LVL(_DBG_LVL_SAR_INFO, SendRmppReply); + +#if defined(DBG) || defined(IB_DEBUG) + if (RmppSendDiscardFreq) + { + // discard occasional SAR packet sent, will stress retry mechanism + if (++send_discard_counter % RmppSendDiscardFreq == 1) + { + _DBG_PRINT_RMPP_HEADERS( _DBG_LVL_WARN, "Test Discarding Send:\n", + (MAD_RMPP*)GsiDgrmGetRecvMad(pDgrm), pDgrm->RemoteLID); + goto done; + } + } +#endif + + i = 1; + status = DgrmPoolGet( g_GsaGlobalInfo->DgrmPoolRecvQ, &i, &pDgrmList ); + if (FSUCCESS != status || i != 1) + { + _DBG_ERROR(("SendRmppReply: No more elements in Pool!!!\n")); + goto done; + } + ASSERT(NULL != pDgrmList); + + pMadRmpp = (MAD_RMPP*)GsiDgrmGetRecvMad(pDgrmList); + + // Copy MAD Headers from template + MemoryCopy( pMadRmpp, GsiDgrmGetRecvMad(pDgrm), sizeof(MAD) ); + + // Invert R bit + pMadRmpp->common.mr.s.R = ! pMadRmpp->common.mr.s.R; + + pMadRmpp->RmppHdr = *pRmppHdr; // struct copy - RMPP header to use + MemoryClear(&pMadRmpp->Data[0], STL_RMPP_GS_DATASIZE); // no Data + ASSERT(RMPP_STATUS_NORMAL == RmppMadCheck(pMadRmpp)); + + // Set remote info + GsiDgrmAddrCopy(pDgrmList, pDgrm); + + // generate a PostSendList from the first datagram in post + pPostList = &(((IBT_DGRM_ELEMENT_PRIV *)pDgrmList)->PostSendList); + + // Fill in list details + pPostList->DgrmIn = 1; + AtomicWrite(&pPostList->DgrmOut, 0); + pPostList->DgrmList = pDgrmList; + pPostList->SARRequest = TRUE; + pPostList->DgrmList->Element.pBufferList->pNextBuffer->ByteCount = + pDgrm->Element.pBufferList->pNextBuffer->ByteCount; + + status = GsiDoSendDgrm( NULL, pPostList); + if (status != FSUCCESS) + { + // release AV + DgrmPoolPut( pDgrmList ); + } + +done: + _DBG_LEAVE_LVL(_DBG_LVL_SAR_INFO); +} + +// --------------------------------------------------------------------------- +// RMPP Sender + +// +// DoSARSend +// +// Used by GsiPostSendDgrm to perform a send for a class which +// has requested Segmentation And Reassembly to be performed for it +// by GSI +// +// +// INPUTS: +// +// ServiceClass - The clients class info +// +// PostList - Post list info +// +// +// +// OUTPUTS: +// +// None +// +// +// +// RETURNS: +// +// FCANCELED - Segmentation not required, GsiPostSendDgrm should just send +// the single packet request, header not swapped +// FSUCCESS - Segmentation and transmission process has begun, headers swapped +// other - unable to start transmission, headers not swapped +// +FSTATUS +DoSARSend( + IN GSA_SERVICE_CLASS_INFO *ServiceClass, + IN GSA_POST_SEND_LIST *PostList + ) +{ +#if 1 + // not yet implemented +#if 0 + // HACK to get further with broken SM, fill in RMPP Version + IBT_DGRM_ELEMENT_PRIV *pDgrmPrivate = + (IBT_DGRM_ELEMENT_PRIV *)PostList->DgrmList; + MAD_RMPP *pMadRmpp = + (MAD_RMPP *)GsiDgrmGetSendMad(&pDgrmPrivate->DgrmElement); + pMadRmpp->RmppHdr.RmppVersion = RMPP_VERSION; + BSWAP_RMPP_HEADER(&pMadRmpp->RmppHdr); +#endif + return FCANCELED; // assume not segmented +#else + FSTATUS status = FSUCCESS; + + uint32 sendSize; + IBT_DGRM_ELEMENT_PRIV *pDgrmPrivate; + MAD_COMMON *pMadHdr; + MULTI_PKT_HDR *pSARHdr; + IBT_BUFFER *pBuffer; + uint32 dgrmMsgSize, dgrmCount; + IB_HANDLE qp1Handle, cqHandle; + SPIN_LOCK *qpLock; + IB_L_KEY memLKey; + GSA_SAR_CONTEXT *pSarContext; + IB_WORK_REQ *pWorkRequest; + IB_ADDRESS_VECTOR avInfo; + + _DBG_ENTER_LVL (_DBG_LVL_SAR_INFO, DoSARSend); + + + TBD - here we want to see if this could have an RMPP response + or is DoubleSided, in either case we want to create the SarContext now + so its ready when receive comes in. We can create it as a receiver + or a sender context depending on whether this send needs RMPP + or just reponse needs RMPP + as part of creating context we need to verify the TID is unique. + if the TID is not unique, its OK, we need to enter a wait for the + context to complete its prior transaction then create a new context + perhaps a simple sleep/retry type or a timer doing that for us + perhaps a timer in our new context which starts out checking periodically + via RmppFindContext, then once its now found, it proceeds to add itself + to the global list and start its transaction + // + // Get total send requests + // + + pDgrmPrivate = (IBT_DGRM_ELEMENT_PRIV *)PostList->DgrmList; + pDgrmPrivate->Base = PostList; // link for receives + pDgrmPrivate->AvHandle = NULL; // so can trigger for clearup + + pMadHdr = + (MAD_COMMON *)GsiDgrmGetSendMad(&pDgrmPrivate->DgrmElement); + + pSARHdr = + (MULTI_PKT_HDR *)((uintn)pMadHdr + sizeof(MAD_COMMON)); + + sendSize = + pSARHdr->PayloadLen + sizeof(MAD_COMMON) + sizeof(MULTI_PKT_HDR); + + + // + // Validate user buffer size with payload + // + pBuffer = pDgrmPrivate->DgrmElement.Element.pBufferList; + dgrmMsgSize = 0; + + while ( NULL != pBuffer ) + { + dgrmMsgSize += pBuffer->ByteCount; + pBuffer = pBuffer->pNextBuffer; + } + + for ( ;; ) + { + if ( sendSize > dgrmMsgSize ) + { + _DBG_ERROR (( + "User passed Payload that overruns buffer!!!\n" + "\tMsg size.........:x%x\n" + "\tBuffer size......:x%x\n", + sendSize, + dgrmMsgSize )); + + status = FINVALID_PARAMETER; + break; + } + + // + // Calculate segments to send + // + dgrmCount = 1; + + if ( sendSize > sizeof(MAD) ) + { + sendSize -= (sizeof(MAD_COMMON) + sizeof(MULTI_PKT_HDR)); + + if (!( sendSize % MAD_SAR_DATA_SIZE)) + dgrmCount--; + + dgrmCount += ( sendSize / MAD_SAR_DATA_SIZE); + + _DBG_PRINT(_DBG_LVL_SAR_INFO,( + "SAR segments = %d\n", + dgrmCount )); + } + else + { + _DBG_PRINT(_DBG_LVL_SAR_INFO,( + "Only one SAR segment\n" )); + } + + // + // Init SAR Hdr + // + pSARHdr->SegmentNum = 0; + + pSARHdr->FragmentFlag.AsReg8 = 0; + pSARHdr->Window = 0; + + + // + // If there are multiple SAR segments go here + // + if ( dgrmCount == 1 ) + { + status = FCANCELED; + _DBG_PRINT(_DBG_LVL_SAR_INFO,( + "No SAR required. Do a normal send\n" )); + + break; + } + + // send one at a time + PostList->DgrmIn = 1; + PostList->SARRequest = TRUE; + + // TBD - could GsiDoSendDgrm be used here? + // or make some common routes with GsiDoSendDgrm? + // + // Fill in Address Vector Info + // + avInfo.PortGUID = pDgrmPrivate->DgrmElement.PortGuid; + avInfo.DestLID = pDgrmPrivate->DgrmElement.RemoteLID; + avInfo.PathBits = pDgrmPrivate->DgrmElement.PathBits; + avInfo.ServiceLevel = pDgrmPrivate->DgrmElement.ServiceLevel; + avInfo.StaticRate = pDgrmPrivate->DgrmElement.StaticRate; + avInfo.GlobalRoute = pDgrmPrivate->DgrmElement.GlobalRoute; + + if ( TRUE == avInfo.GlobalRoute ) + { + /* structure copy */ + avInfo.GlobalRouteInfo = pDgrmPrivate->DgrmElement.GRHInfo; + } + + // + // Query transport specific info for all segments in one go + // + status = GetCaContextFromAvInfo( + &avInfo, + pDgrmPrivate->MemPoolHandle->MemList->CaMemIndex, + &pDgrmPrivate->AvHandle, + &qp1Handle, + &cqHandle, + &qpLock, + &memLKey ); + + if ( FSUCCESS != status ) + { + _DBG_ERROR (( + "Error in GetCaContextFromPortGuid()\n" )); + break; + } + + // + // If this is a request, save the user's transaction id + // and use our own. We will restore the user's transaction id + // when the request completes. If this is a not a request, we let + // the client control the transaction ID, which may have been + // been remotely generated. + // + if( MAD_IS_REQUEST((MAD*)pMadHdr)) + { + pMadHdr->TransactionID = (uint64)\ + (pMadHdr->TransactionID & 0xffffffffffffff00ll); + pMadHdr->TransactionID = \ + pMadHdr->TransactionID | ServiceClass->ClientId; + } + + pSarContext = (GSA_SAR_CONTEXT*)MemoryAllocateAndClear(sizeof(GSA_SAR_CONTEXT), FALSE, GSA_MEM_TAG); + if ( NULL == pSarContext ) + { + status = FINSUFFICIENT_RESOURCES; + _DBG_ERROR (( + "Not enough memory for Sar Context info!\n" )); + break; + } + + // + // Init Lock and Timer + // + SpinLockInitState( &pSarContext->Lock ); + SpinLockInit( &pSarContext->Lock ); + + TimerInitState( &pSarContext->Timer); + if (TRUE != TimerInit( + &pSarContext->Timer, + TimerCallbackSend, + pSarContext )) + { + status = FINSUFFICIENT_RESOURCES; + _DBG_ERROR (( + "TimerInit failed!\n" )); + + SpinLockDestroy( &pSarContext->Lock ); + MemoryDeallocate( pSarContext ); + break; + } + + // + // setup other fields + // + pSarContext->TotalSegs = dgrmCount; + pSarContext->CurrSeg = 0; + + pSarContext->TID = pMadHdr->TransactionID; + pSarContext->MgmtClass = pMadHdr->MgmtClass; + if (PostList->DgrmList->GlobalRoute) + { + pSarContext->RemoteLID = LID_RESERVED; + pSarContext->RemoteGID = PostList->DgrmList->GRHInfo.DestGID; + } else { + pSarContext->RemoteLID = PostList->DgrmList->RemoteLID; + MemoryClear(&pSarContext->RemoteGID, sizeof(pSarContext->RemoteGID)); + } + + pSarContext->Qp1Handle = qp1Handle; + pSarContext->QpLock = qpLock; + pSarContext->PostList = PostList; + + pBuffer = pDgrmPrivate->DgrmElement.Element.pBufferList; + + pSarContext->TotalDataSize = pSARHdr->PayloadLen; + pSarContext->DataStart = + (uintn)(pBuffer->pData) + \ + sizeof(MAD_COMMON) + \ + sizeof(MULTI_PKT_HDR); + + _DBG_PRINT (_DBG_LVL_SAR_INFO,( + "SAR Payload Length = %d bytes\n",pSarContext->TotalDataSize )); + + // + // Format SAR header + // + pSARHdr->SegmentNum = 0; + pSARHdr->FragmentFlag.AsReg8 = 0; + pSARHdr->FragmentFlag.F.FirstPkt = 1; + + // + // Pre create work request since it is common for all segments + // + pWorkRequest = &pSarContext->WorkRequest; + + ASSERT_VALID_WORKREQID((uintn)pDgrmPrivate); + pWorkRequest->WorkReqId = BUILD_SQ_WORKREQID((uintn)pDgrmPrivate); + + // + // SAR will Always be 3: MAD_COMMON, SAR_HDR, DATA + // + pWorkRequest->DSListDepth = 3; + + pWorkRequest->DSList = pDgrmPrivate->DsList; + pWorkRequest->Req.SendUD.AVHandle = pDgrmPrivate->AvHandle; + + pWorkRequest->Operation = WROpSend; + + // zero out the options + pWorkRequest->Req.SendUD.Options.AsUINT16 = 0; + + pWorkRequest->Req.SendUD.Options.s.SignaledCompletion = TRUE; + + //pWorkRequest->Req.SendUD.Qkey = pDgrmPrivate->DgrmElement.RemoteQKey; + pWorkRequest->Req.SendUD.QPNumber = pDgrmPrivate->DgrmElement.RemoteQP; + pWorkRequest->Req.SendUD.Qkey = QP1_WELL_KNOWN_Q_KEY; + pWorkRequest->Req.SendUD.PkeyIndex = pDgrmPrivate->DgrmElement.PkeyIndex; + +#if defined(DBG) ||defined( IB_DEBUG) + + if (!pWorkRequest->Req.SendUD.QPNumber) + { + AtomicIncrementVoid( &ServiceClass->ErrorMsgs ); + + if (!(AtomicRead(&ServiceClass->ErrorMsgs) % 20)) + { + _DBG_ERROR(( + "Invalid QPNumber/Q_Key(substitution provided):\n" + "\tClass...........:x%x\n" + "\tResponder.......:%s\n" + "\tTrapProcessor...:%s\n" + "\tReportProcessor.:%s\n" + "\tSARClient.......:%s\n" + "\tQPNumber........:x%x\n" + "\tQ_Key...........:x%x\n", + ServiceClass->MgmtClass, + GSI_IS_RESPONDER(ServiceClass->RegistrationFlags) + ? "TRUE":"FALSE", + GSI_IS_TRAP_PROCESSOR(ServiceClass->RegistrationFlags) + ? "TRUE":"FALSE", + GSI_IS_REPORT_PROCESSOR(ServiceClass->RegistrationFlags) + ? "TRUE":"FALSE", + ServiceClass->bSARRequired ? "TRUE":"FALSE", + pWorkRequest->Req.SendUD.QPNumber, + pWorkRequest->Req.SendUD.Qkey + )); + } + + pWorkRequest->Req.SendUD.Qkey = QP1_WELL_KNOWN_Q_KEY; + pWorkRequest->Req.SendUD.QPNumber = 1; + } + + if (pWorkRequest->Req.SendUD.QPNumber != 1) + { + _DBG_ERROR(( + "Send to RedirectedQP\n" + "\tQPNumber.....:x%x\n", + pWorkRequest->Req.SendUD.QPNumber + )); + } + +#endif + + // + // fill in scatter/gather DS list details + // + pWorkRequest->MessageLen = 0; + + // + // Fill in MAD Common info + // + pWorkRequest->DSList[0].Address = (uintn)pBuffer->pData; + pWorkRequest->DSList[0].Lkey = memLKey; + pWorkRequest->DSList[0].Length = sizeof(MAD_COMMON); + + // + // Fill in SAR Header info + // + pWorkRequest->DSList[1].Address = \ + (uintn)(pBuffer->pData) + sizeof(MAD_COMMON); + pWorkRequest->DSList[1].Lkey = memLKey; + pWorkRequest->DSList[1].Length = sizeof(MULTI_PKT_HDR); + + // + // Fill in Data info + // + pWorkRequest->DSList[2].Lkey = memLKey; + + pSarContext->DataSeg = &pWorkRequest->DSList[2]; + + // + // TBD: Add to master SAR send list + // + SpinLockAcquire( &g_GsaGlobalInfo->SARSendListLock ); + + QListInsertHead( + &g_GsaGlobalInfo->SARSendList, + &pSarContext->ListItem ); + + SpinLockRelease( &g_GsaGlobalInfo->SARSendListLock ); + + // + // Add timer to Dgrm internal list + // + pDgrmPrivate->pSarContext = pSarContext; + + pSarContext->SysCBItem = SysCallbackGet( + IbtGlobal.DeviceObject ); + if ( NULL == pSarContext->SysCBItem ) + { + status = FINSUFFICIENT_RESOURCES; + TimerDestroy( &pSarContext->Timer ); + SpinLockDestroy( &pSarContext->Lock ); + MemoryDeallocate ( pSarContext ); + _DBG_ERROR (( + "SysCallback Create failed! Dropping SAR send req.\n" )); + break; + } + + SARPost(pSarContext); + break; + } // for loop + + if (status != FSUCESSS && status != FCANCELED) + { + if (pDgrmPrivate->AvHandle) + { + // release AV + (void)PutAV(NULL,pDgrmPrivate->AvHandle); + } + } + + _DBG_LEAVE_LVL(_DBG_LVL_SAR_INFO); + return status; +#endif +} + + +#if 0 // not yet implemented +FSTATUS +SARPost( + IN GSA_SAR_CONTEXT *pSarContext + ) +{ + FSTATUS status =FSUCCESS; + IBT_DGRM_ELEMENT_PRIV *pDgrmPrivate; + IB_LOCAL_DATASEGMENT *pDsList; + IB_WORK_REQ *pWorkRequest; + MULTI_PKT_HDR *pSARHdr; + uint32 bytesSent, bytesToSend; + + _DBG_ENTER_LVL (_DBG_LVL_SAR_INFO, SARPost); + + + SpinLockAcquire( &pSarContext->Lock ); + + pDgrmPrivate = + (IBT_DGRM_ELEMENT_PRIV *)pSarContext->PostList->DgrmList; + + pWorkRequest = &pSarContext->WorkRequest; + pSARHdr = \ + (MULTI_PKT_HDR *)((uintn)pWorkRequest->DSList[1].Address); + + // + // Calculate bytes to be sent + // + pDsList = pSarContext->DataSeg; + + bytesSent = pSarContext->CurrSeg * MAD_SAR_DATA_SIZE; + bytesToSend = pSarContext->TotalDataSize - bytesSent; + + pDsList->Address = pSarContext->DataStart + bytesSent; + pDsList->Length = MAD_SAR_DATA_SIZE; + + pWorkRequest->MessageLen= pDsList->Length + \ + sizeof(MAD_COMMON) + sizeof(MULTI_PKT_HDR); + + + // + // Check to see if we have multiple segments + // + if ( 0 != pSarContext->CurrSeg ) + { + pSARHdr->FragmentFlag.F.FirstPkt = 0; + + if ( pSarContext->CurrSeg+1 == pSarContext->TotalSegs ) + pSARHdr->FragmentFlag.F.LastPkt = 1; + } + else + { + // + // First segment. Validate payload needs multi segments + // + pSARHdr->FragmentFlag.F.FirstPkt = 1; + } + + AtomicIncrementVoid( &pSarContext->CurrSeg ); // advance to next level + pSARHdr->SegmentNum = pSarContext->CurrSeg; + + _DBG_PRINT (_DBG_LVL_SAR_INFO,( + "SAR Header Info:\n" + "\tPayloadLen...:%d bytes\n" + "\tSegment......:%d\n", + pSARHdr->PayloadLen, + pSARHdr->SegmentNum + )); + _DBG_PRINT (_DBG_LVL_SAR_INFO,( + "SAR Header Info (cont):\n" + "\tFragmentFlag.:\n" + "\t\tFirstPkt..:x%x\n" + "\t\tLastPkt...:x%x\n" + "\t\tKeepAlive.:x%x\n" + "\t\tResendReq.:x%x\n" + "\t\tAck.......:x%x\n", + (uint8)(pSARHdr->FragmentFlag.F.FirstPkt), + (uint8)(pSARHdr->FragmentFlag.F.LastPkt), + (uint8)(pSARHdr->FragmentFlag.F.KeepAlive), + (uint8)(pSARHdr->FragmentFlag.F.ResendReq), + (uint8)(pSARHdr->FragmentFlag.F.Ack) + )); + + AtomicWrite(&pSarContext->PostList->DgrmOut, 0); + pSarContext->RetryCount = 0; + pSarContext->ResendSent = FALSE; + + BSWAP_MAD_HEADER ( (MAD*)((uintn)pWorkRequest->DSList[0].Address) ); + BSWAP_SAR_HEADER ( pSARHdr ); + + pDgrmPrivate->DgrmElement.OnSendQ=TRUE; + SpinLockAcquire( pSarContext->QpLock ); + status = iba_post_send( pSarContext->Qp1Handle, pWorkRequest ); + SpinLockRelease( pSarContext->QpLock ); + + SpinLockRelease( &pSarContext->Lock ); + + if (status != FSUCCESS) + { + pDgrmPrivate->DgrmElement.OnSendQ=FALSE; + // swap header back to host order for consistency + BSWAP_MAD_HEADER ( (MAD*)((uintn)pWorkRequest->DSList[0].Address) ); + BSWAP_SAR_HEADER ( pSARHdr ); + } + + _DBG_LEAVE_LVL (_DBG_LVL_SAR_INFO); + return status; +} +#endif + + +#if 0 // not yet implemented +// returns TRUE if RMPP Context is found in which case it processes the +// resend request +// returns FALSE if RMPP Context is not found +boolean +ResendReqSARSend( + IN MAD_RMPP *pMadRmpp, + IN IBT_DGRM_ELEMENT **ppDgrm + ) +{ + GSA_SAR_CONTEXT *pSarContext= NULL; + boolean bStatus = FALSE; + + _DBG_ENTER_LVL (_DBG_LVL_SAR_INFO, ResendReqSARSend); + + pSarContext = FindSarContext(pMadRmpp, *ppDgrm, TRUE); // sender + if (pSarContext != NULL) + { + // Reset Segment number to request + pSarContext->CurrSeg = pMadRmpp->Sar.SegmentNum-1; + SpinLockRelease( &pSarContext->Lock ); + bStatus = TRUE; + _DBG_PRINT (_DBG_LVL_SAR_INFO,( "Timer restarted\n" )); + } + + _DBG_LEAVE_LVL(_DBG_LVL_SAR_INFO); + return (bStatus); +} +#endif + + +#if 0 // not yet implemented +// returns TRUE if RMPP Context is found in which case it processes the ack +// returns FALSE if RMPP Context is not found +boolean +AckReqSARSend( + IN MAD_RMPP *pMadRmpp, + IN IBT_DGRM_ELEMENT **ppDgrm + ) +{ + GSA_SAR_CONTEXT *pSarContext= NULL; + boolean bStatus = FALSE; + + _DBG_ENTER_LVL (_DBG_LVL_SAR_INFO, AckReqSARSend); + + pSarContext = FindSarContext(pMadRmpp, *ppDgrm, TRUE); // sender + + if (pSarContext != NULL ) + { + // Close send timer + if ( pSarContext->TotalSegs == pSarContext->CurrSeg ) + { + SpinLockRelease( &pSarContext->Lock ); + SARCloseSend(pSarContext); + } else { + // we never asked for this Ack, do nothing + SpinLockRelease( &pSarContext->Lock ); + } + + bStatus = TRUE; + _DBG_PRINT (_DBG_LVL_SAR_INFO,( "Timer killed with Ack\n" )); + } + + _DBG_LEAVE_LVL(_DBG_LVL_SAR_INFO); + return (bStatus); +} +#endif + +#if 0 // not yet implemented +// +// Close SAR send created +// +// + Destoy retry timer +// + Destroy AV +// + Destroy Syscallback +// + Call user or dump Dgrm +// + Free timer pool +// +void +SARCloseSend( + IN GSA_SAR_CONTEXT *pSarContext + ) +{ + IBT_DGRM_ELEMENT_PRIV *pDgrmPrivate; + GSA_SERVICE_CLASS_INFO *classInfo; + + _DBG_ENTER_LVL (_DBG_LVL_SAR_INFO, SARCloseSend); + + pDgrmPrivate = + (IBT_DGRM_ELEMENT_PRIV *)pSarContext->PostList->DgrmList; + + _DBG_PRINT (_DBG_LVL_SAR_INFO, + ("*** Killing Send retry timer ***\n")); + + StopSarContextTimer( pSarContext ); // stop timer before destroy + TimerDestroy( &pSarContext->Timer ); // Destroy stops timer too + + PutAV( + NULL, + pDgrmPrivate->AvHandle ); + + // + // Remove from global list + // + SpinLockAcquire( &g_GsaGlobalInfo->SARSendListLock ); + + ASSERT (QListIsItemInList( + &g_GsaGlobalInfo->SARSendList, + &pSarContext->ListItem )); + + + if ( !QListIsItemInList( + &g_GsaGlobalInfo->SARSendList, + &pSarContext->ListItem )) + { + _DBG_ERROR(("Item not in Send List!!!\n")); + } + else + { + QListRemoveItem ( + &g_GsaGlobalInfo->SARSendList, + &pSarContext->ListItem ); + } + + SpinLockRelease(&g_GsaGlobalInfo->SARSendListLock); + + // + // CallUser + // + classInfo = pDgrmPrivate->MemPoolHandle->ServiceHandle; + + if ( classInfo->SendCompletionCallback ) + { + (classInfo->SendCompletionCallback)( + classInfo->ServiceClassContext, + &pDgrmPrivate->DgrmElement ); + } + else + { + // + // return to pool + // + _DBG_PRINT (_DBG_LVL_SAR_INFO, ( + "No Class Agent for this SAR msg!\n")); + + DgrmPoolPut( &pDgrmPrivate->DgrmElement ); + } + + SpinLockDestroy( &pSarContext->Lock ); // lock + SysCallbackPut( pSarContext->SysCBItem ); + MemoryDeallocate ( pSarContext ); + + _DBG_LEAVE_LVL(_DBG_LVL_SAR_INFO); + +} // SARCloseSend +#endif + + +// +// Callback invoked on SAR sends +// +// + There are no retires for send. +// + Completions for ISR callbacks trigger next send of segement. +// + Timer is fired after last send +// +void +SARSendSegments( + IN void *Key, + IN void *TimerContext + ) +{ + ASSERT(0); // should not be called, send not yet implemented +#if 0 // not yet implemented + GSA_SAR_CONTEXT *pSarContext; + IBT_DGRM_ELEMENT_PRIV *pDgrmPrivate; + + + _DBG_ENTER_LVL (_DBG_LVL_SAR_INFO, SARSendSegments); + + pSarContext = TimerContext; + pDgrmPrivate = + (IBT_DGRM_ELEMENT_PRIV *)pSarContext->PostList->DgrmList; + + // + // Verify last completion status + // + if ( FSUCCESS != pDgrmPrivate->DgrmElement.Element.Status ) + { + _DBG_PRINT (_DBG_LVL_SAR_INFO, + ("*** Failed SAR send! Killing retry timer ***\n")); + + SARCloseSend( pSarContext ); + } + else + { + // + // Are we in the last segment? + // + if ( pSarContext->TotalSegs == pSarContext->CurrSeg ) + { + _DBG_PRINT (_DBG_LVL_SAR_INFO, + ("*** Kicking off retry timer ***\n")); + + // + // Fire timer for retires and deliveries + // + StartSarContextTimer( pSarContext, GSA_SAR_TIME_SEND ); + } + else + { + SARPost(pSarContext); + } + } + + _DBG_LEAVE_LVL (_DBG_LVL_SAR_INFO); +#endif + +} // SARSendSegments + + +#if 0 // not yet implemented +// +// Timer callback invoked on SAR sends +// +// + Here the retry counter will stop posts if there is no completion. +// + The timer waits for the Isr routine's callback to update the send +// completions +// +void +TimerCallbackSend( + IN void *TimerContext + ) +{ + GSA_SAR_CONTEXT *pSarContext; + + + _DBG_ENTER_LVL (_DBG_LVL_SAR_INFO, TimerCallbackSend); + + pSarContext = TimerContext; + // TBD, not fully implemented, review and how to use TimerCallbackStopped + // test within lock to prevent stale callbacks from executing + SARCloseSend( pSarContext ); + + _DBG_LEAVE_LVL (_DBG_LVL_SAR_INFO); +} +#endif + +FSTATUS +RmppSenderProcessRecv ( + IN GSA_SAR_CONTEXT *pSarContext, + IN MAD_RMPP *pMadRmpp, + IN IBT_DGRM_ELEMENT **ppDgrm + ) +{ + ASSERT(0); // should not get here, send not yet implemented + return FREJECT; +} + +void +RmppSenderTimerCallback( + IN GSA_SAR_CONTEXT *pSarContext + ) +{ + ASSERT(0); // should not get here, send not yet implemented +} diff --git a/IbAccess/Common/Ibt/Gsa/gsasend.c b/IbAccess/Common/Ibt/Gsa/gsasend.c new file mode 100644 index 0000000..4f85654 --- /dev/null +++ b/IbAccess/Common/Ibt/Gsa/gsasend.c @@ -0,0 +1,516 @@ +/* BEGIN_ICS_COPYRIGHT4 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT4 ****************************************/ + + +#include "gsamain.h" + + + +// +// GsiPostSendDgrm +// +// +// +// INPUTS: +// +// ServiceHandle - Handle returned upon registration +// +// DgrmList - List of datagram(s) to be posted for send +// each must have payload in network byte order +// however MAD and RMPP_HEADERs should be in host +// byte order. On success, GSI owns the buffer and +// will byte swap back the MAD header prior to send completion +// on failure the buffer will be restored to host byte order +// for the MAD and RMPP headers +// +// OUTPUTS: +// +// None +// +// +// +// RETURNS: +// +// FSUCCESS +// FINVALID_PARAMETER +// FINSUFFICIENT_RESOURCES +// FINVALID_STATE +// +FSTATUS +iba_gsi_post_send( + IN IB_HANDLE ServiceHandle, + IN IBT_DGRM_ELEMENT *DgrmList + ) +{ + FSTATUS status=FCANCELED; + GSA_POST_SEND_LIST *pPostList; + GSA_SERVICE_CLASS_INFO *serviceClass; + IBT_DGRM_ELEMENT_PRIV *pDgrmPrivate; + + _DBG_ENTER_LVL (_DBG_LVL_SEND, iba_gsi_post_send); + + serviceClass = (GSA_SERVICE_CLASS_INFO *)ServiceHandle; + pDgrmPrivate = (IBT_DGRM_ELEMENT_PRIV *)DgrmList; + +#if defined(DBG) || defined(IB_DEBUG) + if (GSA_CLASS_SIG != serviceClass->SigInfo ) + { + _DBG_ERROR (("Bad Class Handle passed by client!!!\n")); + _DBG_BREAK; + } + + if ( pDgrmPrivate->MemPoolHandle->ServiceHandle != serviceClass ) + { + _DBG_ERROR (("Dgrm List is not owned by given Class Handle!!!\n")); + _DBG_BREAK; + } +#endif + + // generate a PostSendList from the first datagram in post + pPostList = &pDgrmPrivate->PostSendList; + + // Fill in list details + pPostList->DgrmIn = 0; + AtomicWrite(&pPostList->DgrmOut, 0); + pPostList->DgrmList = DgrmList; + pPostList->SARRequest = FALSE; + + // Find out if client is a SAR client + if ( TRUE == serviceClass->bSARRequired ) + { + _DBG_PRINT(_DBG_LVL_SEND,( "SAR Client request\n" )); + status = DoSARSend( serviceClass, pPostList ); + } + + // We get here if non SAR client or if SAR request was not segmented + if ( FCANCELED == status ) + { + IBT_DGRM_ELEMENT *pDgrmPostList; + + // Get total send requests + pDgrmPostList = DgrmList; + while ( pDgrmPostList ) + { + pPostList->DgrmIn++; + pDgrmPostList = \ + (IBT_DGRM_ELEMENT *)pDgrmPostList->Element.pNextElement; + } + + status = GsiDoSendDgrm(serviceClass, pPostList); + } // SAR + + _DBG_LEAVE_LVL(_DBG_LVL_SEND); + return status; +} + + +// +// GsiDoSendDgrm +// +// +// +// INPUTS: +// +// ServiceClass - ServiceClass from registration +// if NULL, assumed to be Dgrms from global RecvQ +// and 2nd buffer is a single MAD to be posted +// +// pPostList - post list info. +// 1st pPostList->DgrmIn dgrms in this list will be posted. +// each must have payload in network byte order +// however MAD and RMPP_HEADERs should be in host +// byte order. On success, GSI owns the buffer and +// will byte swap back the MAD header prior to send completion +// on failure the buffer will be restored to host byte order +// for the MAD and RMPP headers +// +// OUTPUTS: +// +// None +// +// +// +// RETURNS: +// +// +FSTATUS +GsiDoSendDgrm( + GSA_SERVICE_CLASS_INFO *ServiceClass, + IN GSA_POST_SEND_LIST *pPostList + ) +{ + FSTATUS status = FINVALID_PARAMETER; // list empty + IBT_DGRM_ELEMENT_PRIV *pDgrmPrivate, *pDgrmPrivateNext; + IB_HANDLE qp1Handle, cqHandle; + SPIN_LOCK *qpLock; + IB_L_KEY memLKey; + MAD *pMad; + uint32 dgrmCount, i, dgrmFailed; + IB_WORK_REQ workRequest; + IB_ADDRESS_VECTOR avInfo; + + _DBG_ENTER_LVL (_DBG_LVL_SEND, GsiDoSendDgrm); + + pDgrmPrivate = (IBT_DGRM_ELEMENT_PRIV *)pPostList->DgrmList; + + dgrmCount = pPostList->DgrmIn; + dgrmFailed = 0; // set a count for bad requests + + while ( dgrmCount-- ) + { + pDgrmPrivateNext = (IBT_DGRM_ELEMENT_PRIV *) + pDgrmPrivate->DgrmElement.Element.pNextElement; + + pDgrmPrivate->Base = pPostList; // link for completion processing + + ASSERT_VALID_WORKREQID((uintn)pDgrmPrivate); + workRequest.WorkReqId = BUILD_SQ_WORKREQID((uintn)pDgrmPrivate); + workRequest.Operation = WROpSend; + + workRequest.DSList = pDgrmPrivate->DsList; + + // zero out the options + workRequest.Req.SendUD.Options.AsUINT16 = 0; + workRequest.Req.SendUD.Options.s.SignaledCompletion = TRUE; +#if INCLUDE_16B + workRequest.Req.SendUD.Options.s.SendFMH = 0; +#endif + + // Fill in user settings + workRequest.Req.SendUD.QPNumber = pDgrmPrivate->DgrmElement.RemoteQP; + // TBD check uses, may be safe to enable this line now + //workRequest.Req.SendUD.Qkey = pDgrmPrivate->DgrmElement.RemoteQKey; + workRequest.Req.SendUD.Qkey = QP1_WELL_KNOWN_Q_KEY; + workRequest.Req.SendUD.PkeyIndex= pDgrmPrivate->DgrmElement.PkeyIndex; + +#if defined(DBG) || defined(IB_DEBUG) + if (ServiceClass && !workRequest.Req.SendUD.QPNumber) + { + AtomicIncrement( &ServiceClass->ErrorMsgs ); + + if (!(AtomicRead(&ServiceClass->ErrorMsgs) % 20)) + { + _DBG_ERROR(( + "Invalid QPNumber/Q_Key(substitution provided):\n" + "\tClass..........:x%x\n" + "\tSARClient......:%s\n" + "\tQPNumber.......:x%x\n" + "\tQ_Key..........:x%x\n", + ServiceClass->MgmtClass, + _DBG_PTR(ServiceClass->bSARRequired ? "TRUE":"FALSE"), + workRequest.Req.SendUD.QPNumber, + workRequest.Req.SendUD.Qkey + )); + + _DBG_ERROR(( + "\tResponder......:%s\n" + "\tTrapProcessor..:%s\n" + "\tReportProcessor:%s\n", + _DBG_PTR(GSI_IS_RESPONDER(ServiceClass->RegistrationFlags) + ? "TRUE":"FALSE"), + _DBG_PTR(GSI_IS_TRAP_PROCESSOR(ServiceClass->RegistrationFlags) + ? "TRUE":"FALSE"), + _DBG_PTR(GSI_IS_REPORT_PROCESSOR(ServiceClass->RegistrationFlags) + ? "TRUE":"FALSE") + )); + } + + workRequest.Req.SendUD.Qkey = QP1_WELL_KNOWN_Q_KEY; + workRequest.Req.SendUD.QPNumber = 1; + } + ASSERT(workRequest.Req.SendUD.QPNumber); + + if (workRequest.Req.SendUD.QPNumber != 1) + { + _DBG_WARN(( + "Send to RedirectedQP\n" + "\tQPNumber.....:x%x\n", + workRequest.Req.SendUD.QPNumber + )); + } +#endif + // Fill in Address Vector Info + avInfo.PortGUID = pDgrmPrivate->DgrmElement.PortGuid; + avInfo.DestLID = pDgrmPrivate->DgrmElement.RemoteLID; + avInfo.PathBits = pDgrmPrivate->DgrmElement.PathBits; + avInfo.ServiceLevel = pDgrmPrivate->DgrmElement.ServiceLevel; + avInfo.StaticRate = pDgrmPrivate->DgrmElement.StaticRate; + avInfo.GlobalRoute = pDgrmPrivate->DgrmElement.GlobalRoute; + + if ( TRUE == avInfo.GlobalRoute ) + { + /* structure copy */ + avInfo.GlobalRouteInfo = pDgrmPrivate->DgrmElement.GRHInfo; + } + + status = GetCaContextFromAvInfo( + &avInfo, + pDgrmPrivate->MemPoolHandle->MemList->CaMemIndex, + &workRequest.Req.SendUD.AVHandle, + &qp1Handle, + &cqHandle, + &qpLock, + &memLKey ); + + if ( FSUCCESS == status ) + { + pDgrmPrivate->AvHandle = workRequest.Req.SendUD.AVHandle; + + // fill in scatter/gather Ds list details + if (! ServiceClass) + { + // Rmpp replies and GSI internal replies + IB_LOCAL_DATASEGMENT *pDsList = workRequest.DSList; + + ASSERT( pDgrmPrivate->MemPoolHandle->ReceivePool); + pMad = GsiDgrmGetRecvMad(&pDgrmPrivate->DgrmElement); + workRequest.DSListDepth = 1; + pDsList[0].Address = (uintn)pMad; + pDsList[0].Lkey = memLKey; + pDsList[0].Length = + GsiDgrmGetRecvMadByteCount(&pDgrmPrivate->DgrmElement); + workRequest.MessageLen = + GsiDgrmGetRecvMadByteCount(&pDgrmPrivate->DgrmElement); + } + else if ( TRUE != ServiceClass->bSARRequired ) + { + // Direct sends from other callers + IBT_BUFFER *pBuffer; + IB_LOCAL_DATASEGMENT *pDsList = workRequest.DSList; + + pBuffer = pDgrmPrivate->DgrmElement.Element.pBufferList; + + workRequest.DSListDepth = \ + pDgrmPrivate->MemPoolHandle->BuffersPerElement; + workRequest.MessageLen = 0; + for (i=0; ipData; + pDsList[i].Lkey = memLKey; + pDsList[i].Length = pBuffer->ByteCount; + + workRequest.MessageLen += pBuffer->ByteCount; + pBuffer = pBuffer->pNextBuffer; + } + + // Validate that buffers per element are sizeof MAD for non + // SAR clients + if ( workRequest.MessageLen > sizeof(MAD) ) + { + _DBG_ERROR(( + "Bad Non SAR Client posted buffer > sizeof(MAD)!\n")); + _DBG_BREAK; + } + pMad = GsiDgrmGetSendMad(&pDgrmPrivate->DgrmElement); + } else { + // invoked for single packet GSI SAR send + // SAR will Always be 3: MAD_COMMON, SAR_HDR, DATA + IBT_BUFFER *pBuffer; + + pBuffer = pDgrmPrivate->DgrmElement.Element.pBufferList; + workRequest.DSListDepth = 3; + + // Fill in MAD Common info + workRequest.DSList[0].Address = (uintn)pBuffer->pData; + workRequest.DSList[0].Lkey = memLKey; + workRequest.DSList[0].Length = sizeof(MAD_COMMON); + + // Fill in SAR Header info + workRequest.DSList[1].Address = \ + (uintn)(pBuffer->pData) + sizeof(MAD_COMMON); + workRequest.DSList[1].Lkey = memLKey; + workRequest.DSList[1].Length = sizeof(RMPP_HEADER); + + // Fill in Data info + workRequest.DSList[2].Address = \ + (uintn)(pBuffer->pData) + \ + sizeof(MAD_COMMON) + + sizeof(RMPP_HEADER); + workRequest.DSList[2].Lkey = memLKey; + workRequest.DSList[2].Length = pBuffer->ByteCount - + (sizeof(MAD_COMMON) + sizeof(RMPP_HEADER)); + + workRequest.MessageLen = pBuffer->ByteCount; + pMad = GsiDgrmGetSendMad(&pDgrmPrivate->DgrmElement); + } + + // Set Transaction ID + + // If this is a request, save the user's transaction id + // and use our own. We will restore the user's transaction id + // when the request completes. If this is not a request, + // we let the client control the transaction id which may have + // been remotely generated. + if( ServiceClass && MAD_IS_REQUEST(pMad)) + { + // We need to save the TID in case we receive the + // response before being notified that the send completed. + pDgrmPrivate->SavedSendTid = pMad->common.TransactionID; + + pMad->common.TransactionID = (uint64)\ + (pMad->common.TransactionID & 0xffffffffffffff00ll); + pMad->common.TransactionID = \ + pMad->common.TransactionID | ServiceClass->ClientId; + } + + // Make headers Network Byte order + BSWAP_MAD_HEADER(pMad); + if( (ServiceClass && ServiceClass->bSARRequired) ) + { + BSWAP_RMPP_HEADER ( + (RMPP_HEADER *)((uintn)workRequest.DSList[1].Address) ); + } else if( pPostList->SARRequest) { + // only applies to Rmpp Reply and Gsi reply + ASSERT(workRequest.DSListDepth == 1); + BSWAP_RMPP_HEADER ( + (RMPP_HEADER *)&(((MAD_RMPP*)pMad)->RmppHdr)); + } + +#if defined(DBG) || defined(IB_DEBUG) + if (__DBG_LEVEL__ & _DBG_LVL_PKTDUMP) + { + uint32 Length = workRequest.MessageLen; + IB_LOCAL_DATASEGMENT *Current = &workRequest.DSList[0]; + for (i = 0; i < workRequest.DSListDepth; i++,Current++) + { + _DBG_DUMP_MEMORY(_DBG_LVL_PKTDUMP, ("Send Packet"), (void *)(uintn)Current->Address, + MIN(Current->Length,Length)); + Length -= MIN(Current->Length,Length);; + } + } +#endif + + // Submit to verbs + pDgrmPrivate->DgrmElement.OnSendQ = TRUE; + SpinLockAcquire( qpLock ); + status = iba_post_send( qp1Handle, &workRequest ); + SpinLockRelease( qpLock ); + + if ( FSUCCESS != status ) + { + pDgrmPrivate->DgrmElement.OnSendQ = FALSE; + // restore headers to host Byte order + BSWAP_MAD_HEADER(pMad); + if( (ServiceClass && ServiceClass->bSARRequired) ) + { + BSWAP_RMPP_HEADER ( + (RMPP_HEADER *)((uintn)workRequest.DSList[1].Address) ); + } else if( pPostList->SARRequest) { + // only applies to Rmpp Reply and Gsi reply + ASSERT(workRequest.DSListDepth == 1); + BSWAP_RMPP_HEADER ( + (RMPP_HEADER *)&(((MAD_RMPP*)pMad)->RmppHdr)); + } + + // release AV + (void)PutAV(NULL,pDgrmPrivate->AvHandle); + pDgrmPrivate->DgrmElement.Element.Status = status; + AtomicIncrementVoid( &pPostList->DgrmOut ); + dgrmFailed++; + } + } else { + pDgrmPrivate->DgrmElement.Element.Status = status; + AtomicIncrementVoid( &pPostList->DgrmOut ); + dgrmFailed++; + } + + pDgrmPrivate = pDgrmPrivateNext; + } + + // If all requests failed, fail the call and pass it back to user. + // There is no way of passing all failed entries through the callback + if ( pPostList->DgrmIn && dgrmFailed == pPostList->DgrmIn ) + { + status = FINVALID_STATE; + } + + _DBG_LEAVE_LVL(_DBG_LVL_SEND); + return status; +} + +// uses pDgrm as a template for building an GET_RESP reply +// reporting a Invalid Class Version status +// MAD header and AV information is taken from pDgrm +// pDgrm is unaffected, assumes pDgrm is in Host byte order for +// MAD header and network byte order for rest of packet +void GsiSendInvalid( + IN IBT_DGRM_ELEMENT *pDgrm + ) +{ + FSTATUS status = FSUCCESS; + uint32 i; + IBT_DGRM_ELEMENT *pDgrmList; + GSA_POST_SEND_LIST *pPostList; + MAD *pMad; + + _DBG_ENTER_LVL(_DBG_LVL_SEND, GsiSendInvalid); + + i = 1; + status = DgrmPoolGet( g_GsaGlobalInfo->DgrmPoolRecvQ, &i, &pDgrmList ); + if (FSUCCESS != status || i != 1) + { + _DBG_ERROR(("GsiSendInvalid: No more elements in Pool!!!\n")); + goto done; + } + ASSERT(NULL != pDgrmList); + + // we are using a Recv Pool Dgrm + pMad = GsiDgrmGetRecvMad(pDgrmList); + + // Copy MAD Headers from template + MemoryCopy( pMad, GsiDgrmGetRecvMad(pDgrm), sizeof(MAD) ); + + pMad->common.mr.AsReg8 = MMTHD_GET_RESP; + pMad->common.u.NS.Status.AsReg16 = MAD_STATUS_UNSUPPORTED_CLASS_VER; + pMad->common.u.NS.Reserved1 = 0; + _DBG_INFO(("Invalid MAD: class %u\n", pMad->common.MgmtClass)); + // GsiDoSendDgrm will BSWAP_MAD_HEADER + + // Set remote info + GsiDgrmAddrCopy(pDgrmList, pDgrm); + + // generate a PostSendList from the first datagram in post + pPostList = &(((IBT_DGRM_ELEMENT_PRIV *)pDgrmList)->PostSendList); + + // Fill in list details + pPostList->DgrmIn = 1; + AtomicWrite(&pPostList->DgrmOut, 0); + pPostList->DgrmList = pDgrmList; + pPostList->SARRequest = FALSE; + + status = GsiDoSendDgrm( NULL, pPostList); + if (status != FSUCCESS) + { + // release AV + DgrmPoolPut( pDgrmList ); + } + +done: + _DBG_LEAVE_LVL(_DBG_LVL_SEND); +} diff --git a/IbAccess/Common/Ibt/Gsa/gsastore.c b/IbAccess/Common/Ibt/Gsa/gsastore.c new file mode 100644 index 0000000..f051306 --- /dev/null +++ b/IbAccess/Common/Ibt/Gsa/gsastore.c @@ -0,0 +1,1149 @@ +/* BEGIN_ICS_COPYRIGHT4 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT4 ****************************************/ + + +#include "gsamain.h" + + +#define VOID_PTR_INCR(ptr,incr) ptr=((void *)((char *)(ptr)+(incr))) + +static FSTATUS DestroyGrowableDgrmPool(IB_HANDLE DgrmPoolHandle); + +// +// CreateDgrmPool +// +// +// +// INPUTS: +// +// ServiceHandle - Handle returned upon registration +// +// ElementCount - Number of elements in pool +// +// BuffersPerElement- Number of buffers in each pool element +// +// BufferSizeArray[]- An array of buffers sizes. The length of this array must +// be equal to BuffersPerElement. +// +// ContextSize - Size of user context in each element +// +// +// +// OUTPUTS: +// +// DgrmPoolHandle - Opaque handle returned to identify datagram pool created +// +// +// +// RETURNS: +// +// FSUCCESS +// FINVALID_PARAMETER +// FINSUFFICIENT_RESOURCES +// +// + +FSTATUS +CreateDgrmPool( + IN IB_HANDLE ServiceHandle, + IN uint32 ElementCount, + IN uint32 BuffersPerElement, + IN uint32 BufferSizeArray[], + IN uint32 ContextSize, + OUT IB_HANDLE *DgrmPoolHandle + ) +{ + FSTATUS status = FSUCCESS; + void *pUdBlock = NULL; + void *pHeaderBlock = NULL; + GLOBAL_MEM_LIST *pMemList = NULL; + IBT_DGRM_ELEMENT *pPrevDgrmElement = NULL; + IBT_BUFFER *pPrevBuffer = NULL; + uint32 memSizeReg = 0; + uint32 memSizeHeaders = 0; + + IBT_MEM_POOL *dgrmPoolHandle; + IBT_DGRM_ELEMENT *pDgrmElement; + IBT_DGRM_ELEMENT_PRIV *pIbtDgrmElement; + IBT_BUFFER *pBuffer; + GSA_SERVICE_CLASS_INFO *serviceClass; + uint32 allignBytes; + uint32 i, j; + + _DBG_ENTER_LVL(_DBG_LVL_STORE, CreateDgrmPool); + + serviceClass = (GSA_SERVICE_CLASS_INFO *)ServiceHandle; + + // Do per element memory requirement calculations + // Calculate total buffer sizes + for (i=0; i MAD_BLOCK_SIZE: SAR + if ( memSizeReg > sizeof(MAD) ) + { + // Each block must contain MAD_BLOCK_SIZE + multiple of 192 bytes + + // TBD - BUGBUG - is this correct given compression + // have caller supply classHeaderSize as an argument or in + // class registration + // may need knowledge of classHeaderSize??? + uint32 classHeaderSize = (serviceClass->MgmtClass == MCLASS_SUBN_ADM)?sizeof(RMPP_HEADER)+sizeof(SA_HDR):sizeof(RMPP_HEADER); + + allignBytes = (sizeof(MAD) - \ + (sizeof(MAD_COMMON) + classHeaderSize)) - \ + ((memSizeReg - sizeof(MAD)) % (sizeof(MAD) - \ + (sizeof(MAD_COMMON) + classHeaderSize))); + + _DBG_PRINT(_DBG_LVL_STORE,( + "Registered memory (SAR) not a multiple of 256+192: " + "Adding (%d) bytes per element of size (%d)\n", + allignBytes, + memSizeReg)); + } + + memSizeReg += allignBytes; + } + + // Add context and reserved field sizes + memSizeHeaders += ContextSize; + + memSizeHeaders += (sizeof(IB_LOCAL_DATASEGMENT) * BuffersPerElement); + + // If client is type SAR allocate an addition SAR segment + if (( NULL != serviceClass ) && ( TRUE == serviceClass->bSARRequired )) + memSizeHeaders += (sizeof(IB_LOCAL_DATASEGMENT)*2); + + + memSizeHeaders += ( sizeof(IBT_DGRM_ELEMENT_PRIV) + \ + sizeof(IBT_BUFFER)*BuffersPerElement ); + + // + // Now calculate for all elements + // + memSizeReg *= ElementCount; + memSizeHeaders *= ElementCount; + + // + // Add handle space + // + memSizeHeaders += sizeof(IBT_MEM_POOL); + + _DBG_PRINT(_DBG_LVL_STORE,( + "Mem required: Headers(x%x) Buffers(x%x) for (x%x)Elements\n", + memSizeHeaders, memSizeReg, ElementCount)); + + + pUdBlock = MemoryAllocate2AndClear(memSizeReg, IBA_MEM_FLAG_PREMPTABLE|IBA_MEM_FLAG_PREFER_CONTIG, GSA_MEM_TAG); + if ( NULL != pUdBlock ) + { + // alloc memory for Headers + + pHeaderBlock = MemoryAllocate2AndClear(memSizeHeaders, IBA_MEM_FLAG_PREMPTABLE, GSA_MEM_TAG); + if ( NULL != pHeaderBlock ) + { + + // Create global memory block in memory list + + // To avoid a race if AddDevice between CreateGlobalMemList and + // RegisterMemGlobal, we hold the semaphore to block SmaAddDevice + // so we don't end up double registering memory as + // SmaAddDevice will register all MemGlobal blocks with the new CA + // The AcquireMemListMutex exposure is poor style, ultimately we + // should move this algorithm into smastore.c as it parallels + // SmaAllocToBin or better yet create a generic version of the + // SmaAllocToBin which meets the needs of this and Sma + + AcquireMemListMutex(); + + pMemList = CreateGlobalMemList( pUdBlock, memSizeReg, + pHeaderBlock, TRUE ); + if (NULL == pMemList) + { + ReleaseMemListMutex(); + } + } // pHeaderBlock + } // pUdBlock + + if ( ( NULL != pUdBlock ) && \ + ( NULL != pHeaderBlock ) && \ + ( NULL != pMemList ) ) + { + // set access level for memory region + + pMemList->AccessControl.AsUINT16 = 0; + pMemList->AccessControl.s.LocalWrite = 1; + + status = RegisterMemGlobal( + pMemList->VirtualAddr, + pMemList->Length, + pMemList->AccessControl, + &pMemList->CaMemIndex + ); + ReleaseMemListMutex(); + + if ( FSUCCESS == status ) + { + dgrmPoolHandle = (IBT_MEM_POOL*)pHeaderBlock; + + // Initialize handle + SpinLockInitState( &dgrmPoolHandle->Lock ); + SpinLockInit( &dgrmPoolHandle->Lock ); + + dgrmPoolHandle->ServiceHandle = ServiceHandle; + dgrmPoolHandle->TotalElements = \ + dgrmPoolHandle->Elements = \ + ElementCount; + VOID_PTR_INCR(pHeaderBlock,sizeof(IBT_MEM_POOL)); + dgrmPoolHandle->DgrmList = (IBT_DGRM_ELEMENT*)pHeaderBlock; + dgrmPoolHandle->UdBlock = pUdBlock; + dgrmPoolHandle->HeaderBlock = pHeaderBlock; + dgrmPoolHandle->MemList = pMemList; + dgrmPoolHandle->BuffersPerElement = BuffersPerElement; + dgrmPoolHandle->ReceivePool = FALSE; + + *DgrmPoolHandle = dgrmPoolHandle; // return value + + // Loop through all elements + pDgrmElement = (IBT_DGRM_ELEMENT*)pHeaderBlock; + VOID_PTR_INCR(pHeaderBlock,sizeof(IBT_DGRM_ELEMENT_PRIV)); + + // Do each element + for ( i=0; i< ElementCount; i++ ) + { + pDgrmElement->Allocated = FALSE; + pDgrmElement->Element.pBufferList = (IBT_BUFFER*)pHeaderBlock; + pBuffer = pDgrmElement->Element.pBufferList; + + // Do each buffer + for ( j=0; jpData = pUdBlock; + pBuffer->ByteCount = BufferSizeArray[j]; + + VOID_PTR_INCR(pUdBlock,pBuffer->ByteCount); + + VOID_PTR_INCR(pHeaderBlock,sizeof(IBT_BUFFER)); + pBuffer->pNextBuffer = (IBT_BUFFER*)pHeaderBlock; + + pPrevBuffer = pBuffer; + pBuffer = pBuffer->pNextBuffer; + } // j loop + + // Delink previous buffer + if (pPrevBuffer) + pPrevBuffer->pNextBuffer = NULL; + + // Do not update context info if zero + if ( 0 != ContextSize ) + { + pDgrmElement->Element.pContext = pHeaderBlock; + VOID_PTR_INCR(pHeaderBlock,ContextSize); + } + + // Insert MemHandles + pIbtDgrmElement = (IBT_DGRM_ELEMENT_PRIV *)pDgrmElement; + pIbtDgrmElement->MemPoolHandle = dgrmPoolHandle; + + // Add Ds list for quick sends + pIbtDgrmElement->DsList = (IB_LOCAL_DATASEGMENT *)pHeaderBlock; + VOID_PTR_INCR(pHeaderBlock,(sizeof(IB_LOCAL_DATASEGMENT) * BuffersPerElement)); + + // Skip SAR segment too + if (( NULL != serviceClass ) && \ + ( TRUE == serviceClass->bSARRequired )) + VOID_PTR_INCR(pHeaderBlock,(sizeof(IB_LOCAL_DATASEGMENT)*2)); + + // Create next link + pDgrmElement->Element.pNextElement = (IBT_ELEMENT*)pHeaderBlock; + VOID_PTR_INCR(pHeaderBlock,sizeof(IBT_DGRM_ELEMENT_PRIV)); + + pPrevDgrmElement = pDgrmElement; + pDgrmElement = \ + (IBT_DGRM_ELEMENT *)pDgrmElement->Element.pNextElement; + + // Add allignment adjustments + VOID_PTR_INCR(pUdBlock,allignBytes); + + } // i loop + + // Delink next for last element + if (pPrevDgrmElement) + pPrevDgrmElement->Element.pNextElement = NULL; + + } else { + // + // Remove memory from global list + // + DeleteGlobalMemList( pMemList ); + + MemoryDeallocate( pHeaderBlock ); + MemoryDeallocate( pUdBlock ); + + status = FINSUFFICIENT_RESOURCES; + } + } else { + // errors in allocations. free mem if allocated + _DBG_ERROR(( + "Could not allocate memory for x%x Elements\n", ElementCount)); + + // return module specific errors + status = FINSUFFICIENT_RESOURCES; + + // unwind + if ( NULL != pHeaderBlock ) + MemoryDeallocate( pHeaderBlock ); + if ( NULL != pUdBlock ) + MemoryDeallocate( pUdBlock ); + } + + + _DBG_LEAVE_LVL(_DBG_LVL_STORE); + return status; +} + + +// +// DestroyDgrmPool +// +// +// +// INPUTS: +// +// DgrmPoolHandle - Handle returned upon successful creation of Datagram pool +// +// +// +// OUTPUTS: +// +// None +// +// +// +// RETURNS: +// +// FSUCCESS +// FINVALID_PARAMETER +// FINSUFFICIENT_RESOURCES +// +// + +FSTATUS +DestroyDgrmPool( + IN IB_HANDLE DgrmPoolHandle + ) +{ + FSTATUS status = FSUCCESS; + IBT_MEM_POOL *dgrmPoolHandle; + + _DBG_ENTER_LVL(_DBG_LVL_STORE, DestroyDgrmPool); + + // Validate + dgrmPoolHandle = (IBT_MEM_POOL *)DgrmPoolHandle; + + if (dgrmPoolHandle->Growable) + { + // growable dgrm pool + return DestroyGrowableDgrmPool(DgrmPoolHandle); + } + + if ( dgrmPoolHandle->Elements == dgrmPoolHandle->TotalElements ) + { + + status = DeregisterMemGlobal( dgrmPoolHandle->MemList->CaMemIndex ); + status = DeleteGlobalMemList( dgrmPoolHandle->MemList ); + /* global receive pool destroyed its lock when creating dgrm pool */ + if ( ! dgrmPoolHandle->Parent ) + SpinLockDestroy( &dgrmPoolHandle->Lock ); + MemoryDeallocate(dgrmPoolHandle->UdBlock); + MemoryDeallocate(dgrmPoolHandle); + } + else + { + status = FINVALID_PARAMETER; + _DBG_ERROR(( + "User owns elements!!!\n" + "\tTotal elements....: %d\n" + "\tUnfreed elements..: %d\n" + "\tClass in error....: %x (%s)\n", \ + dgrmPoolHandle->TotalElements, + ( dgrmPoolHandle->TotalElements - dgrmPoolHandle->Elements ), + ((GSA_SERVICE_CLASS_INFO*)dgrmPoolHandle->ServiceHandle)->MgmtClass, + _DBG_PTR(GSI_IS_RESPONDER( + ((GSA_SERVICE_CLASS_INFO*)dgrmPoolHandle->ServiceHandle)-> + RegistrationFlags) ? "ServerClass":"ClientClass") + )); + + } + + _DBG_LEAVE_LVL(_DBG_LVL_STORE); + return status; +} + + + +// +// DgrmPoolGet +// +// +// +// INPUTS: +// +// DgrmPoolHandle - Handle returned upon successful creation of Datagram pool +// +// ElementCount - Number of elements to fetch from pool +// +// +// +// +// OUTPUTS: +// +// ElementCount - Number of elements fetched from pool +// +// DgrmList - Pointer holds the datagram list if successful +// +// +// +// RETURNS: +// +// FSUCCESS +// FINVALID_PARAMETER +// FINSUFFICIENT_RESOURCES +// +// + +FSTATUS +DgrmPoolGet( + IN IB_HANDLE DgrmPoolHandle, + IN OUT uint32 *ElementCount, + OUT IBT_DGRM_ELEMENT **DgrmList + ) +{ + FSTATUS status = FSUCCESS; + IBT_MEM_POOL *dgrmPoolHandle; + IBT_DGRM_ELEMENT *pDgrmList; + uint32 i; + + _DBG_ENTER_LVL(_DBG_LVL_STORE, DgrmPoolGet); + + dgrmPoolHandle = (IBT_MEM_POOL *)DgrmPoolHandle; + + // Validate input parameters + if ( !*ElementCount ) + { + status = FINVALID_PARAMETER; + _DBG_ERROR(("Client asked for 0 elements!\n")); + } + + if (FSUCCESS == status) + { + SpinLockAcquire( &dgrmPoolHandle->Lock ); + if ( 0 != dgrmPoolHandle->Elements ) + { + + _DBG_PRINT(_DBG_LVL_STORE,("Requested %d Dgrms\n", *ElementCount)); + + if ( *ElementCount > dgrmPoolHandle->Elements ) + *ElementCount = dgrmPoolHandle->Elements; + + ASSERT(dgrmPoolHandle->DgrmList); + + *DgrmList = dgrmPoolHandle->DgrmList; + pDgrmList = dgrmPoolHandle->DgrmList; + + if (pDgrmList->Allocated) + _DBG_ERROR(("GSI ERROR: Allocated Dgrm on Free list\n")); + if (pDgrmList->OnRecvQ) + _DBG_ERROR(("GSI ERROR: RecvQ Dgrm on Free list\n")); + if (pDgrmList->OnSendQ) + _DBG_ERROR(("GSI ERROR: SendQ Dgrm on Free list\n")); + if (Gsa_debug_params.debug_level & _DBG_LVL_STORE) + { + ASSERT(!pDgrmList->Allocated); + ASSERT(!pDgrmList->OnRecvQ); + ASSERT(!pDgrmList->OnSendQ); + } + DEBUG_ASSERT(!pDgrmList->Allocated); + DEBUG_ASSERT(!pDgrmList->OnRecvQ); + DEBUG_ASSERT(!pDgrmList->OnSendQ); + pDgrmList->Allocated = TRUE; + + for (i=1; i<*ElementCount; i++ ) + { + pDgrmList = (IBT_DGRM_ELEMENT *)pDgrmList->Element.pNextElement; + if (pDgrmList->Allocated) + _DBG_ERROR(("GSI ERROR: Allocated Dgrm on Free list\n")); + if (pDgrmList->OnRecvQ) + _DBG_ERROR(("GSI ERROR: RecvQ Dgrm on Free list\n")); + if (pDgrmList->OnSendQ) + _DBG_ERROR(("GSI ERROR: SendQ Dgrm on Free list\n")); + if (Gsa_debug_params.debug_level & _DBG_LVL_STORE) + { + ASSERT(!pDgrmList->Allocated); + ASSERT(!pDgrmList->OnRecvQ); + ASSERT(!pDgrmList->OnSendQ); + } + DEBUG_ASSERT(!pDgrmList->Allocated); + DEBUG_ASSERT(!pDgrmList->OnRecvQ); + DEBUG_ASSERT(!pDgrmList->OnSendQ); + pDgrmList->Allocated = TRUE; + } + + dgrmPoolHandle->DgrmList = \ + (IBT_DGRM_ELEMENT *)pDgrmList->Element.pNextElement; + pDgrmList->Element.pNextElement = NULL; // Delink + dgrmPoolHandle->Elements -= *ElementCount; // update count + + _TRC_STORE(("DgrmPoolGet: Handle %p ElementCount %d Elements %d\n", _TRC_PTR(dgrmPoolHandle), *ElementCount, dgrmPoolHandle->Elements)); + + _DBG_PRINT(_DBG_LVL_STORE, + ("[GET] UserDgrmList[x%p] HandleList[x%p]\n", + _DBG_PTR(pDgrmList), _DBG_PTR(dgrmPoolHandle->DgrmList))); + + SpinLockRelease( &dgrmPoolHandle->Lock ); + } else { + SpinLockRelease( &dgrmPoolHandle->Lock ); + status = FINSUFFICIENT_RESOURCES; + _DBG_PRINT(_DBG_LVL_STORE,("DgrmPoolGet: No more Dgrms in Pool!!!\n")); + } + } // param vaidation + + _DBG_LEAVE_LVL(_DBG_LVL_STORE); + return status; +} + +// +// DgrmPoolCount +// +// +// +// INPUTS: +// +// DgrmPoolHandle - Handle returned upon successful creation of Datagram pool +// +// RETURNS: +// +// Number of elements in the pool +// +uint32 +DgrmPoolCount( + IN IB_HANDLE DgrmPoolHandle + ) +{ + IBT_MEM_POOL *dgrmPoolHandle; + uint32 rval; + + _DBG_ENTER_LVL(_DBG_LVL_STORE, DgrmPoolCount); + dgrmPoolHandle = (IBT_MEM_POOL *)DgrmPoolHandle; + SpinLockAcquire( &dgrmPoolHandle->Lock ); + rval = dgrmPoolHandle != NULL?dgrmPoolHandle->Elements:0; + SpinLockRelease( &dgrmPoolHandle->Lock ); + _DBG_RETURN_LVL(_DBG_LVL_STORE, rval); + return rval; +} + + +// +// DgrmPoolTotal +// +// +// +// INPUTS: +// +// DgrmPoolHandle - Handle returned upon successful creation of Datagram pool +// +// RETURNS: +// +// Total Number of elements allocated in the pool +// +uint32 +DgrmPoolTotal( + IN IB_HANDLE DgrmPoolHandle + ) +{ + IBT_MEM_POOL *dgrmPoolHandle; + uint32 rval; + + _DBG_ENTER_LVL(_DBG_LVL_STORE, DgrmPoolCount); + dgrmPoolHandle = (IBT_MEM_POOL *)DgrmPoolHandle; + SpinLockAcquire( &dgrmPoolHandle->Lock ); + rval = dgrmPoolHandle != NULL?dgrmPoolHandle->TotalElements:0; + SpinLockRelease( &dgrmPoolHandle->Lock ); + _DBG_RETURN_LVL(_DBG_LVL_STORE, rval); + return rval; +} + + +// +// DgrmPoolPut +// +// +// +// INPUTS: +// +// DgrmList - Datagram elements to return back to pool +// +// +// +// OUTPUTS: +// +// None +// +// +// +// RETURNS: +// +// FSUCCESS +// FINVALID_PARAMETER +// FINSUFFICIENT_RESOURCES +// +// + +FSTATUS +DgrmPoolPut( + IN IBT_DGRM_ELEMENT *pDgrmList + ) +{ + FSTATUS status = FSUCCESS; + boolean bRecvPool = FALSE; + + IBT_MEM_POOL *dgrmPoolHandle; + IBT_DGRM_ELEMENT *p; + IBT_DGRM_ELEMENT *pLast = NULL; + uint32 i; + + _DBG_ENTER_LVL(_DBG_LVL_STORE, DgrmPoolPut); + + ASSERT(pDgrmList); + dgrmPoolHandle = ((IBT_DGRM_ELEMENT_PRIV *)pDgrmList)->MemPoolHandle; + + if ( TRUE == dgrmPoolHandle->ReceivePool ) + bRecvPool = TRUE; // Do this to fixup buffer sizes + // If the buffers are from a growable pool, use the parent handle instead + if (dgrmPoolHandle->Parent) + dgrmPoolHandle = dgrmPoolHandle->Parent; + + // Calculate number of returned buffers and cleanup size values in recvs + p = pDgrmList; + i=0; + while ( NULL != p ) + { + if (! p->Allocated) + _DBG_ERROR(("GSI ERROR: Freeing non-allocated Dgrm\n")); + if (p->OnRecvQ) + _DBG_ERROR(("GSI ERROR: Freeing RecvQ Dgrm\n")); + if (p->OnSendQ) + _DBG_ERROR(("GSI ERROR: Freeing SendQ Dgrm\n")); + if (Gsa_debug_params.debug_level & _DBG_LVL_STORE) + { + ASSERT(p->Allocated); + ASSERT(!p->OnRecvQ); + ASSERT(!p->OnSendQ); + } + DEBUG_ASSERT(p->Allocated); + DEBUG_ASSERT(!p->OnRecvQ); + DEBUG_ASSERT(!p->OnSendQ); + p->Allocated = FALSE; + if ( TRUE == bRecvPool ) + { + p->Element.pBufferList->pNextBuffer->ByteCount =sizeof(MAD); + + // TBD - can we drop the clear here? + MemoryClear( + p->Element.pBufferList->pNextBuffer->pData, + p->Element.pBufferList->pNextBuffer->ByteCount + ); + } + pLast = p; + p = (IBT_DGRM_ELEMENT *)p->Element.pNextElement; + i++; + } + + SpinLockAcquire( &dgrmPoolHandle->Lock ); + + // add back to head of dgrm pool + _DBG_PRINT(_DBG_LVL_STORE,("[PUT] (%d) Items to UserDgrmList[x%p] HandleList[x%p]\n", + i, _DBG_PTR(pDgrmList), _DBG_PTR(dgrmPoolHandle->DgrmList))); + ASSERT(pLast != NULL); + // &(DgrmList->Element) does not dereference DgrmList + pLast->Element.pNextElement = &(dgrmPoolHandle->DgrmList->Element); + dgrmPoolHandle->DgrmList = pDgrmList; + dgrmPoolHandle->Elements += i; // total up + + _TRC_STORE(("DgrmPoolPut: Handle %p freed %d Elements %d\n", _TRC_PTR(dgrmPoolHandle), i, dgrmPoolHandle->Elements)); + + SpinLockRelease( &dgrmPoolHandle->Lock ); + + _DBG_LEAVE_LVL(_DBG_LVL_STORE); + return status; +} + + +// +// CreateGrowableDgrmPool +// +// +// +// INPUTS: +// +// ServiceHandle - Handle returned upon registration +// +// ElementCount - Initial Number of elements in pool (can be 0) +// +// BuffersPerElement- Number of buffers in each pool element (required) +// +// BufferSizeArray[]- An array of buffers sizes. The length of this array must +// be equal to BuffersPerElement. (required) +// +// ContextSize - Size of user context in each element (required) +// +// +// +// OUTPUTS: +// +// DgrmPoolHandle - Opaque handle returned to identify datagram pool created +// +// +// +// RETURNS: +// +// FSUCCESS +// FINVALID_PARAMETER +// FINSUFFICIENT_RESOURCES +// +// + +FSTATUS +CreateGrowableDgrmPool( + IN IB_HANDLE ServiceHandle, + IN uint32 ElementCount, + IN uint32 BuffersPerElement, + IN uint32 BufferSizeArray[], + IN uint32 ContextSize, + OUT IB_HANDLE *DgrmPoolHandle + ) +{ + IBT_MEM_POOL *dgrmPoolHandle; + uint32 *pInfo; + uint32 i; + FSTATUS status = FSUCCESS; + + dgrmPoolHandle = (IBT_MEM_POOL*)MemoryAllocate2AndClear( + sizeof(IBT_MEM_POOL) + sizeof(uint32) + + BuffersPerElement*sizeof(uint32), + IBA_MEM_FLAG_PREMPTABLE|IBA_MEM_FLAG_PREFER_CONTIG, + GSA_MEM_TAG); + if (! dgrmPoolHandle) + goto failalloc; + + // Initialize handle + SpinLockInitState( &dgrmPoolHandle->Lock ); + if (! SpinLockInit( &dgrmPoolHandle->Lock )) + goto faillock; + dgrmPoolHandle->CallbackItem = SysCallbackGet(dgrmPoolHandle); + if (! dgrmPoolHandle->CallbackItem) + goto failsyscall; + + dgrmPoolHandle->Next = NULL; + AtomicWrite(&dgrmPoolHandle->GrowScheduled, 0); + dgrmPoolHandle->ServiceHandle = ServiceHandle; + dgrmPoolHandle->TotalElements = dgrmPoolHandle->Elements = 0; + dgrmPoolHandle->DgrmList = NULL; + dgrmPoolHandle->UdBlock = NULL; + dgrmPoolHandle->HeaderBlock = dgrmPoolHandle + 1;// space after IBT_MEM_POOL + dgrmPoolHandle->MemList = NULL; + dgrmPoolHandle->BuffersPerElement = BuffersPerElement; + dgrmPoolHandle->ReceivePool = FALSE; + dgrmPoolHandle->Growable = TRUE; + + pInfo = (uint32*)dgrmPoolHandle->HeaderBlock; + *pInfo++ = ContextSize; + for (i=0; iCallbackItem); +failsyscall: + SpinLockDestroy( &dgrmPoolHandle->Lock ); +faillock: + MemoryDeallocate(dgrmPoolHandle); +failalloc: + return FINSUFFICIENT_RESOURCES; +} + +// +// DgrmPoolGrow +// Grow the size of a Growable Dgrm Pool +// This routine may preempt. +// +// +// INPUTS: +// DgrmPoolHandle - Opaque handle to datagram pool +// +// ELementCount - number of elements to add to pool +// +// +// +// OUTPUTS: +// +// None +// +// +// RETURNS: +// +// FSUCCESS +// FINVALID_PARAMETER +// FINSUFFICIENT_RESOURCES +// +FSTATUS +DgrmPoolGrow( + IN IB_HANDLE DgrmPoolHandle, + IN uint32 ElementCount + ) +{ + FSTATUS status = FSUCCESS; + IBT_MEM_POOL *GrowDgrmPool = (IBT_MEM_POOL*)DgrmPoolHandle; + IBT_MEM_POOL *dgrmPoolHandle; + IBT_DGRM_ELEMENT *pDgrmList; + + _DBG_ENTER_LVL(_DBG_LVL_STORE, DgrmPoolGrow); + + if (! GrowDgrmPool->Growable) + { + status = FINVALID_PARAMETER; + goto done; + } + + status = CreateDgrmPool( + GrowDgrmPool->ServiceHandle, + ElementCount, + GrowDgrmPool->BuffersPerElement, + ((uint32*)GrowDgrmPool->HeaderBlock)+1, + *(uint32*)GrowDgrmPool->HeaderBlock, // ContextSize + (IB_HANDLE *)&dgrmPoolHandle ); + + if ( FSUCCESS != status ) + { + status = FINSUFFICIENT_RESOURCES; + goto done; + } + + SpinLockDestroy( &dgrmPoolHandle->Lock ); // we use parent's lock + // discard this lock + + // Add RecvQ boolean to DgrmHandle ( this is used in Put ) + dgrmPoolHandle->ReceivePool = GrowDgrmPool->ReceivePool; + + dgrmPoolHandle->Parent = GrowDgrmPool; + + // Now toss it in the global recvQ + SpinLockAcquire( &GrowDgrmPool->Lock ); + + // Attach to Global list + dgrmPoolHandle->Next = GrowDgrmPool->Next; + GrowDgrmPool->Next = dgrmPoolHandle; + + // Get end of list + pDgrmList = dgrmPoolHandle->DgrmList; + while ( NULL != pDgrmList->Element.pNextElement ) + { + pDgrmList = (IBT_DGRM_ELEMENT *)pDgrmList->Element.pNextElement; + } + + pDgrmList->Element.pNextElement = \ + (IBT_ELEMENT *)GrowDgrmPool->DgrmList; // link + + ASSERT(dgrmPoolHandle->TotalElements == dgrmPoolHandle->Elements); + GrowDgrmPool->TotalElements += dgrmPoolHandle->TotalElements; + GrowDgrmPool->Elements += dgrmPoolHandle->TotalElements; + + _TRC_STORE(("Adding %d Total %d To %p\n", dgrmPoolHandle->TotalElements, + GrowDgrmPool->Elements, _TRC_PTR(GrowDgrmPool))); + + GrowDgrmPool->DgrmList = dgrmPoolHandle->DgrmList;// add to parent Q + _DBG_INFO(("grew DgrmPool %p by %u now at %u\n", + _DBG_PTR(GrowDgrmPool), ElementCount, + GrowDgrmPool->TotalElements)); + + SpinLockRelease( &GrowDgrmPool->Lock ); + +done: + _DBG_LEAVE_LVL(_DBG_LVL_STORE); + return status; +} + +static FSTATUS +DestroyGrowableDgrmPool(IB_HANDLE DgrmPoolHandle) +{ + IBT_MEM_POOL *dgrmPoolHandle; + IBT_MEM_POOL *GrowDgrmPool = (IBT_MEM_POOL*)DgrmPoolHandle; + + _DBG_ENTER_LVL(_DBG_LVL_STORE, DestroyGrowableDgrmPool); + + SpinLockAcquire( &GrowDgrmPool->Lock ); + + if ( GrowDgrmPool->Elements != GrowDgrmPool->TotalElements ) { + SpinLockRelease( &GrowDgrmPool->Lock ); + return FINVALID_STATE; + } + + dgrmPoolHandle = GrowDgrmPool->Next; + while ( dgrmPoolHandle ) + { + // force a destroy by reporting all elements are put back in pool + + GrowDgrmPool->Next = dgrmPoolHandle->Next; + SpinLockRelease( &GrowDgrmPool->Lock ); + + dgrmPoolHandle->Elements = dgrmPoolHandle->TotalElements; + DestroyDgrmPool( dgrmPoolHandle ); + + SpinLockAcquire( &GrowDgrmPool->Lock ); + dgrmPoolHandle = GrowDgrmPool->Next; + } // while loop + + SpinLockRelease( &GrowDgrmPool->Lock ); + + SysCallbackPut(GrowDgrmPool->CallbackItem); + SpinLockDestroy( &GrowDgrmPool->Lock ); + MemoryDeallocate(GrowDgrmPool); + + _DBG_LEAVE_LVL(_DBG_LVL_STORE); + return FSUCCESS; +} + +// System Callback function to grow Dgrm Pool +static +void +GrowPoolSysCallback( + void* Key, //Functional Device OBJECT + void *Context) +{ + IBT_MEM_POOL *GrowDgrmPool = (IBT_MEM_POOL*)Key; + uint32 count = (uint32)(uintn)Context; + FSTATUS status; + + _DBG_ENTER_LVL(_DBG_LVL_STORE, GrowPoolSysCallback); + + _DBG_INFO(("growing DgrmPool %p by %u\n", _DBG_PTR(GrowDgrmPool), count)); + status = DgrmPoolGrow((IB_HANDLE)GrowDgrmPool, count); + if (status != FSUCCESS) { + _DBG_WARN(("Unable to grow DgrmPool %p: %s\n", _DBG_PTR(GrowDgrmPool), + _DBG_PTR(iba_fstatus_msg(status)))); + } + if (AtomicExchange(&GrowDgrmPool->GrowScheduled, 0) == 0) { + _DBG_ERROR(("GrowScheduled was 0\n")); + } + + _DBG_LEAVE_LVL(_DBG_LVL_STORE); +} + +// +// DgrmPoolGrowAsNeeded +// Checks Pool size and schedules a system callback to grow it as needed +// This routine does not preempt. +// +// +// INPUTS: +// DgrmPoolHandle - Opaque handle to datagram pool +// +// lowWater - if Dgrm Pool available < this, we will grow it +// +// maxElements - limit on size of Dgrm Pool, will not grow beyond this +// +// growIncrement - amount to grow by if we are growing +// +// +// +// OUTPUTS: +// +// None +// +// +// RETURNS: +// +// None +// +void +DgrmPoolGrowAsNeeded(IB_HANDLE DgrmPoolHandle, uint32 lowWater, + uint32 maxElements, uint32 growIncrement) +{ + IBT_MEM_POOL *GrowDgrmPool = (IBT_MEM_POOL*)DgrmPoolHandle; + + _DBG_ENTER_LVL(_DBG_LVL_STORE, DgrmPoolGrowAsNeeded); + if (DgrmPoolCount(DgrmPoolHandle) < lowWater + && DgrmPoolTotal(DgrmPoolHandle) < maxElements) + { + if (AtomicExchange(&GrowDgrmPool->GrowScheduled, 1) == 0) { + // now we have lock, double check Total + uint32 count = DgrmPoolTotal(DgrmPoolHandle); + if (count < maxElements) + { + count = maxElements - count; // max to grow + count = MIN(count, growIncrement); + SysCallbackQueue(GrowDgrmPool->CallbackItem, + GrowPoolSysCallback, + (void*)(uintn)count, FALSE); + } else { + /* release lock */ + if (AtomicExchange(&GrowDgrmPool->GrowScheduled, 0) == 0) { + _DBG_ERROR(("RecvQGrowScheduled was 0\n")); + } + } + } + } + _DBG_LEAVE_LVL(_DBG_LVL_STORE); +} + +// create the global GSA RecvQ Pool +FSTATUS +CreateGlobalRecvQ(void) +{ + FSTATUS status = FSUCCESS; + uint32 bufferSizeArray[2] = {sizeof(IB_GRH),sizeof(MAD)}; + + _DBG_ENTER_LVL(_DBG_LVL_STORE, CreateGlobalRecvQ); + + status = CreateGrowableDgrmPool( + NULL, + 0, + 2, // BuffersPerElement + bufferSizeArray, + 0, // ContextSize + &g_GsaGlobalInfo->DgrmPoolRecvQ); + if (FSUCCESS == status) + ((IBT_MEM_POOL*)g_GsaGlobalInfo->DgrmPoolRecvQ)->ReceivePool = TRUE; + + _DBG_LEAVE_LVL(_DBG_LVL_STORE); + return status; +} + +// grow the global GSA RecvQ Pool +FSTATUS +DgrmPoolAddToGlobalRecvQ( + IN uint32 ElementCount + ) +{ + FSTATUS status = FSUCCESS; + + if (DgrmPoolCount(g_GsaGlobalInfo->DgrmPoolRecvQ) <= ElementCount) + status = DgrmPoolGrow(g_GsaGlobalInfo->DgrmPoolRecvQ, ElementCount); + return status; +} + +// +// GrowRecvQAsNeeded +// Checks RecvQ size and schedules a system callback to grow it as needed +// +// +// +// INPUTS: +// +// None +// +// +// +// OUTPUTS: +// +// None +// +// +// RETURNS: +// +// None +// +void +GrowRecvQAsNeeded(void) +{ + DgrmPoolGrowAsNeeded(g_GsaGlobalInfo->DgrmPoolRecvQ, GSA_RECVQ_LOW_WATER, + g_GsaSettings.MaxRecvBuffers, + g_GsaSettings.PreAllocRecvBuffersPerPort); +} + +// +// DestroyGlobalRecvQ +// +// +// +// INPUTS: +// +// None +// +// +// +// OUTPUTS: +// +// None +// +// +// RETURNS: +// +// None +// +// + +void +DestroyGlobalRecvQ(void) +{ + _DBG_ENTER_LVL(_DBG_LVL_STORE, DestroyGlobalRecvQ); + + DestroyDgrmPool(g_GsaGlobalInfo->DgrmPoolRecvQ); + + _DBG_LEAVE_LVL(_DBG_LVL_STORE); +} diff --git a/IbAccess/Common/Ibt/Sma/README b/IbAccess/Common/Ibt/Sma/README new file mode 100644 index 0000000..c7fe9ca --- /dev/null +++ b/IbAccess/Common/Ibt/Sma/README @@ -0,0 +1,3 @@ +Subnet Management Agent + +The real work is done via GetSetMad in the Verbs Provider Driver diff --git a/IbAccess/Common/Ibt/Sma/ibnotify.c b/IbAccess/Common/Ibt/Sma/ibnotify.c new file mode 100644 index 0000000..e727f16 --- /dev/null +++ b/IbAccess/Common/Ibt/Sma/ibnotify.c @@ -0,0 +1,514 @@ +/* BEGIN_ICS_COPYRIGHT4 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT4 ****************************************/ + +#include "ibnotify.h" + +// +// Globals +// +IBT_NOTIFY_GROUP NotifyGroup; + + +// +// Initialize the Notify Group +// +//INPUT: +// Callback - when a new User is added to the Notify group, this routine +// is called to distribute initial events to User +void +IbtInitNotifyGroup ( + IN IB_ROOT_CALLBACK Callback + ) +{ + _DBG_ENTER_LVL( _DBG_LVL_IBT_API, IbtInitNotifyGroup ); + + ASSERT(! NotifyGroup.Initialized); + + MapInitState( &NotifyGroup.Lists ); + SpinLockInitState( &NotifyGroup.Lock ); + + if (MapInit( &NotifyGroup.Lists ) != FSUCCESS) + { + _DBG_ERROR (("Failed to Initialize Notification Map\n")); + goto done; + } + if (SpinLockInit( &NotifyGroup.Lock ) == FALSE) + { + _DBG_ERROR (("Failed to Initialize Notification lock\n")); + goto faillock; + } + + // Add root callback for new users + ASSERT ( Callback ); + NotifyGroup.RootCallback = Callback; + + NotifyGroup.Initialized = TRUE; + +done: + _DBG_LEAVE_LVL(_DBG_LVL_IBT_API); + return; + +faillock: + MapDestroy ( &NotifyGroup.Lists ); + goto done; +} + + +// +// Cleanup for shutdown +void +IbtDestroyNotifyGroup ( void ) +{ + QUICK_LIST *pList; + + _DBG_ENTER_LVL( _DBG_LVL_IBT_API, IbtDestroyNotifyGroup ); + + if (! NotifyGroup.Initialized) + goto done; + + // Empty list contents + SpinLockAcquire( &NotifyGroup.Lock ); + + while (NULL != (pList = (QUICK_LIST*)MapRemoveHead(&NotifyGroup.Lists))) + { + LIST_ITEM *pListItem; + + while (NULL != (pListItem = QListRemoveHead(pList))) + { + IBT_NOTIFY_USER_BLOCK *pUser = (IBT_NOTIFY_USER_BLOCK *)pListItem; + MemoryDeallocate( pUser ); + } + QListDestroy(pList); + MemoryDeallocate(pList); + } + NotifyGroup.Initialized = FALSE; + + SpinLockRelease( &NotifyGroup.Lock ); + + MapDestroy( &NotifyGroup.Lists ); + SpinLockDestroy( &NotifyGroup.Lock ); + +done: + _DBG_LEAVE_LVL(_DBG_LVL_IBT_API); +} + +// Notify all users in pList of pRec event +void +IbtNotifyList( + QUICK_LIST *pList, + IB_NOTIFY_RECORD *pRec + ) +{ + LIST_ITEM *pListFirst; + IBT_NOTIFY_USER_BLOCK *pUser; + + pListFirst = QListHead( pList ); + + while (pListFirst) + { + // If event has been subscribed by user, notify + if ( pRec->EventType & ((IBT_NOTIFY_USER_BLOCK *)pListFirst)->EventMask) + { + pUser = (IBT_NOTIFY_USER_BLOCK *)pListFirst; + pRec->Context = pUser->Context; + if (pUser->Locking == IB_NOTIFY_ASYNC) + { + pUser->RefCount++; + SpinLockRelease( &NotifyGroup.Lock ); + ( pUser->Callback )( *pRec ); + SpinLockAcquire( &NotifyGroup.Lock ); + pListFirst = QListNext( pList, pListFirst ); + if (--(pUser->RefCount) == 0) + { + QListRemoveItem ( pList, &pUser->ListItem ); + MemoryDeallocate( pUser ); + } + continue; + } else { + ASSERT(pUser->RefCount); + ( pUser->Callback )( *pRec ); + } + } + pListFirst = QListNext( pList, pListFirst ); + } +} + +// Notify all registered clients of an event against the given Guid +void +IbtNotifyGroup ( + IN EUI64 Guid, // Port/Node GUID + IN IB_NOTIFY_TYPE EventType // Type of event being reported + ) +{ + IB_NOTIFY_RECORD Rec; + QUICK_LIST* pList; + + _DBG_ENTER_LVL( _DBG_LVL_IBT_API, IbtNotifyGroup ); + + _DBG_PRINT( _DBG_LVL_IBT_API,( + "NotifyGroup\n" + "\tEventType...:%"PRIxN"\n" + "\tGUID........:x%016"PRIx64"\n", + EventType, + Guid )); + + if (! NotifyGroup.Initialized) + goto done; + + // Fill in common record info + Rec.Guid = Guid; + Rec.EventType = EventType; + + SpinLockAcquire( &NotifyGroup.Lock ); + + // iterate on List in Map for Guid, then map for Guid==0 + pList = (QUICK_LIST*)MapGet(&NotifyGroup.Lists, Guid); + if (pList != NULL) + { + IbtNotifyList(pList, &Rec); + } + + pList = (QUICK_LIST*)MapGet(&NotifyGroup.Lists, 0); + if (pList != NULL) + { + IbtNotifyList(pList, &Rec); + } + + SpinLockRelease( &NotifyGroup.Lock ); + +done: + _DBG_LEAVE_LVL(_DBG_LVL_IBT_API); +} + +// Send a notification to a single registered notify client +// used as part of RootCallback to send initial events to a newly +// registered client +// returns FALSE if client has deregistered itself in callback +boolean +IbtNotifyUserEvent ( + IN void *UserContext, + IN EUI64 Guid, // Port/Node GUID + IN IB_NOTIFY_TYPE EventType // Type of event being reported + ) +{ + IB_NOTIFY_RECORD Rec; + IBT_NOTIFY_USER_BLOCK *pUser = (IBT_NOTIFY_USER_BLOCK*)UserContext; + + _DBG_ENTER_LVL( _DBG_LVL_IBT_API, IbtNotifyUserEvent ); + + _DBG_PRINT( _DBG_LVL_IBT_API,( + "NotifyGroup\n" + "\tEventType...:%"PRIxN"\n" + "\tGUID........:x%016"PRIx64"\n", + EventType, + Guid )); + + if (! NotifyGroup.Initialized) + { + pUser = NULL; // no more notifications needed + goto done; + } + + // Fill in common record info + Rec.Guid = Guid; + Rec.EventType = EventType; + + SpinLockAcquire( &NotifyGroup.Lock ); + + // If event has been subscribed by user, notify + if ( ( EventType & pUser->EventMask ) + && (pUser->Guid == 0 || pUser->Guid == Guid)) + { + Rec.Context = pUser->Context; + if (pUser->Locking == IB_NOTIFY_ASYNC) + { + pUser->RefCount++; + SpinLockRelease( &NotifyGroup.Lock ); + ( pUser->Callback )( Rec ); + SpinLockAcquire( &NotifyGroup.Lock ); + if (--(pUser->RefCount) == 0) + { + QUICK_LIST* pList; + + pList = (QUICK_LIST*)MapGet(&NotifyGroup.Lists, pUser->Guid); + if (pList != NULL) + QListRemoveItem ( pList, &pUser->ListItem ); + MemoryDeallocate( pUser ); + pUser = NULL; + } + } else { + ASSERT(pUser->RefCount); + ( pUser->Callback )( Rec ); + } + } + + SpinLockRelease( &NotifyGroup.Lock ); + +done: + _DBG_LEAVE_LVL(_DBG_LVL_IBT_API); + return (pUser != NULL); +} + + + +// +// iba_register_notify +// +// The caller uses this API to register for notifications of IB type events +// +// +// INPUTS: +// +// Callback -Callback routine to be registered for notifications +// +// Context -User specified context to return in callbacks +// +// EventMask -Mask to subscribe to event types +// +// Locking -locking model for callback +// +// +// +// OUTPUTS: +// +// NotifyHandle -Notification handle on successful registration +// +// +// RETURNS: +// +// FSUCCESS +// FINSUFFICIENT_MEMORY +// +// +FSTATUS +iba_register_notify ( + IN IB_NOTIFY_CALLBACK Callback, + IN void *Context, + IN IB_NOTIFY_TYPE EventMask, + IN IB_NOTIFY_LOCKING Locking, + OUT IB_HANDLE *NotifyHandle + ) +{ + FSTATUS status = FSUCCESS; + + _DBG_ENTER_LVL( _DBG_LVL_IBT_API, iba_register_notify ); + status = iba_register_guid_notify(0, Callback, Context, EventMask, Locking, NotifyHandle); + _DBG_LEAVE_LVL(_DBG_LVL_IBT_API); + return status; +} + + +// +// iba_register_guid_notify +// +// The caller uses this API to register for notifications of IB type events +// +// +// INPUTS: +// +// Guid -Guid user is interested in +// +// Callback -Callback routine to be registered for notifications +// +// Context -User specified context to return in callbacks +// +// EventMask -Mask to subscribe to event types +// +// Locking -locking model for callback +// +// +// +// OUTPUTS: +// +// NotifyHandle -Notification handle on successful registration +// +// +// RETURNS: +// +// FSUCCESS +// FINSUFFICIENT_MEMORY +// +// +FSTATUS +iba_register_guid_notify ( + IN EUI64 Guid, + IN IB_NOTIFY_CALLBACK Callback, + IN void *Context, + IN IB_NOTIFY_TYPE EventMask, + IN IB_NOTIFY_LOCKING Locking, + OUT IB_HANDLE *NotifyHandle + ) +{ + FSTATUS status = FSUCCESS; + IBT_NOTIFY_USER_BLOCK *pUser; + QUICK_LIST *pList; + + _DBG_ENTER_LVL( _DBG_LVL_IBT_API, iba_register_notify ); + + if (! NotifyGroup.Initialized) + { + status = FINVALID_STATE; + goto done; + } + + // Allocate memory to hold user registration + pUser = (IBT_NOTIFY_USER_BLOCK*)MemoryAllocateAndClear( + sizeof(IBT_NOTIFY_USER_BLOCK), FALSE, + IBT_NOTIFY_TAG ); + if ( !pUser ) + { + status = FINSUFFICIENT_MEMORY; + _DBG_ERROR(("%s\n", _DBG_PTR(FSTATUS_MSG(status)))); + goto done; + } + + // Fill in user details + pUser->Guid = Guid; // all Guids + pUser->Callback = Callback; + pUser->Context = Context; + pUser->RefCount = 1; + pUser->EventMask = EventMask; + pUser->Locking = Locking; + + // Save user list in group + SpinLockAcquire( &NotifyGroup.Lock ); + pList = (QUICK_LIST*)MapGet(&NotifyGroup.Lists, Guid); + if (pList == NULL) + { + pList = (QUICK_LIST*)MemoryAllocateAndClear( sizeof(QUICK_LIST), FALSE, + IBT_NOTIFY_TAG ); + QListInitState(pList); + if (! QListInit(pList)) + { + status = FINSUFFICIENT_RESOURCES; + goto faillist; + } + status = MapInsert(&NotifyGroup.Lists, Guid, pList); + if (status != FSUCCESS) + { + goto failmap; + } + } + QListInsertHead( pList, &pUser->ListItem ); + SpinLockRelease( &NotifyGroup.Lock ); + + *NotifyHandle = pUser; + + _DBG_PRINT(_DBG_LVL_IBT_API,("Created entry x%p\n", _DBG_PTR(pUser))); + + if (EventMask & IB_NOTIFY_ON_REGISTER) + { + // Notify Root to pass user initial events + ASSERT (( NotifyGroup.RootCallback )); + ( NotifyGroup.RootCallback )( pUser ); + } + +done: + _DBG_LEAVE_LVL(_DBG_LVL_IBT_API); + return status; + +failmap: + QListDestroy(pList); +faillist: + MemoryDeallocate(pList); + goto done; +} + + + +// +// iba_deregister_notify +// +// The caller uses this API to Deregister previously registered notifications +// +// +// INPUTS: +// +// NotifyHandle -Handle returned on successful registration +// +// +// +// OUTPUTS: +// +// +// +// RETURNS: +// +// FSUCCESS +// FINVALID_PARAMETER +// FINSUFFICIENT_MEMORY +// +// +FSTATUS +iba_deregister_notify ( + IN IB_HANDLE NotifyHandle + ) +{ + FSTATUS status = FSUCCESS; + IBT_NOTIFY_USER_BLOCK *pUser = (IBT_NOTIFY_USER_BLOCK*)NotifyHandle; + QUICK_LIST *pList; + + + _DBG_ENTER_LVL( _DBG_LVL_IBT_API, iba_deregister_notify ); + + if (! NotifyGroup.Initialized) + { + // could have never registered if we didn't initialize + status = FINVALID_PARAMETER; + goto done; + } + SpinLockAcquire( &NotifyGroup.Lock ); + pList = (QUICK_LIST*)MapGet(&NotifyGroup.Lists, pUser->Guid); + ASSERT(pList); + if ( !QListIsItemInList( pList, &pUser->ListItem ) ) + { + status = FINVALID_PARAMETER; + _DBG_ERROR(("Could not deregister. Notification is not in List!!!\n")); + goto done; + } + if (pUser->Locking == IB_NOTIFY_ASYNC) + { + if (--(pUser->RefCount) != 0) + { + // in use in callback + goto done; + } + } else { + ASSERT(pUser->RefCount == 1); + } + + QListRemoveItem ( pList, &pUser->ListItem ); + MemoryDeallocate( pUser ); + +done: + SpinLockRelease( &NotifyGroup.Lock ); + + _DBG_LEAVE_LVL(_DBG_LVL_IBT_API); + return status; +} diff --git a/IbAccess/Common/Ibt/Sma/ibnotify.h b/IbAccess/Common/Ibt/Sma/ibnotify.h new file mode 100644 index 0000000..56d2319 --- /dev/null +++ b/IbAccess/Common/Ibt/Sma/ibnotify.h @@ -0,0 +1,128 @@ +/* BEGIN_ICS_COPYRIGHT4 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT4 ****************************************/ +/* [ICS VERSION STRING: unknown] */ + + +#ifndef __IBA_IB_IBNOTIFY_H__ +#define __IBA_IB_IBNOTIFY_H__ (1) + +#include "datatypes.h" +#include "stl_types.h" +#include "ib_debug.h" +#include "idebug_osd.h" +#include "statustext.h" +#include "ispinlock.h" +#include "ilist.h" +#include "imemory.h" +#include "imap.h" +#include "ibt.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +#define IBT_NOTIFY_TAG MAKE_MEM_TAG(I,b,t,R) + +// +// Forward declarations of Globals +// + +typedef +void +( *IB_ROOT_CALLBACK ) ( + IN void *Context + ); + +// +// Group block +// +typedef struct _IBT_NOTIFY_GROUP { + SPIN_LOCK Lock; + MAP_RES Lists; // key is Guid + IB_ROOT_CALLBACK RootCallback; + boolean Initialized; // was it initialized +} IBT_NOTIFY_GROUP; + +typedef struct _IBT_NOTIFY_USER_BLOCK { + LIST_ITEM ListItem; + + EUI64 Guid; // Guid user wants events for, 0 for all + IB_NOTIFY_CALLBACK Callback; // callback of user + void *Context; // user's context + uint32 RefCount; // Reference Count + IB_NOTIFY_TYPE EventMask; // event mask + IB_NOTIFY_LOCKING Locking; // locking model + +} IBT_NOTIFY_USER_BLOCK; + + +// +// Forward declarations of Functions +// + +void +IbtNotifyGroup( + IN EUI64 Guid, // Port/Node GUID + IN IB_NOTIFY_TYPE EventType // Type of event being reported + ); + +void +IbtInitNotifyGroup( + IN IB_ROOT_CALLBACK Callback + ); + +void +IbtDestroyNotifyGroup(void); + +boolean +IbtNotifyUserEvent( + IN void *UserContext, // User context passed by Register call + IN EUI64 Guid, // Port/Node GUID + IN IB_NOTIFY_TYPE EventType // Type of event being reported + ); + +// +// Debug specific info +// + +#define _DBG_PRINT_EPILOG(LEVEL,STRING) +#define _DBG_PRINT_PROLOG(LEVEL,STRING) +#define _DBG_ERROR_EPILOG(LEVEL,STRING) +#define _DBG_ERROR_PROLOG(LEVEL,STRING) +#define _DBG_FATAL_EPILOG(LEVEL,STRING) +#define _DBG_FATAL_PROLOG(LEVEL,STRING) + +#define _DBG_LVL_IBT_API 0x00002000 + +#ifdef __cplusplus +}; +#endif + +#endif // __IBA_IB_IBNOTIFY_H__ diff --git a/IbAccess/Common/Ibt/Sma/smaca.c b/IbAccess/Common/Ibt/Sma/smaca.c new file mode 100644 index 0000000..75f145e --- /dev/null +++ b/IbAccess/Common/Ibt/Sma/smaca.c @@ -0,0 +1,873 @@ +/* BEGIN_ICS_COPYRIGHT4 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT4 ****************************************/ + + +#include "smamain.h" +#include "gsi_params.h" + +extern uint32 CmMaxDgrms; + +FSTATUS +SmaDeviceReserve( + IN SMA_CA_OBJ_PRIVATE *CaObj + ) +{ + FSTATUS status = FSUCCESS; + IB_CA_ATTRIBUTES *pCaAttributes = NULL; + IB_PORT_ATTRIBUTES *pPortAttributesList= NULL; + SMA_PORT_TABLE_PRIV *pPortTbl = NULL; + uint32 qp0CqSize = 0; + IB_PORT_ATTRIBUTES *pTempPortAttributesList; + IB_QP_ATTRIBUTES_CREATE qpCreateAttributes; + IB_QP_ATTRIBUTES_QUERY qpAttributes; + uint32 i=0; + + _DBG_ENTER_LVL(_DBG_LVL_DEVICE, DeviceReserve); + + // query the device attributes from VCA + pCaAttributes = (IB_CA_ATTRIBUTES*)MemoryAllocateAndClear(sizeof(IB_CA_ATTRIBUTES), FALSE, SMA_MEM_TAG); + if ( !pCaAttributes ) + { + status = FINSUFFICIENT_MEMORY; + _DBG_ERROR (("MemAlloc failed for CaAttributes!\n" )); + goto failcaalloc; + } + + status = iba_query_ca(CaObj->CaHandle, pCaAttributes, NULL/*pContext*/); + if ( FSUCCESS != status ) + { + _DBG_ERROR (( + "iba_query_ca() failed with NULL PortAttribs! :%s\n", + _DBG_PTR(FSTATUS_MSG (status)) )); + goto failquery; + } + + pPortAttributesList = (IB_PORT_ATTRIBUTES*)MemoryAllocateAndClear(pCaAttributes->PortAttributesListSize, FALSE, SMA_MEM_TAG); + if ( !pPortAttributesList ) + { + status = FINSUFFICIENT_MEMORY; + _DBG_ERROR (( + "MemAlloc failed for PortAttributesList!\n" )); + goto failportalloc; + } + + _DBG_PRINT (_DBG_LVL_DEVICE,( + "Processing device CA :GUID(x%"PRIx64")\n", + CaObj->CaPublic.CaGuid )); + + // build list and add Port info and tag other requirements + pCaAttributes->PortAttributesList = pPortAttributesList; + pTempPortAttributesList = pPortAttributesList; + + status = iba_query_ca(CaObj->CaHandle, pCaAttributes, NULL/*pContext*/); + if ( FSUCCESS != status ) + { + _DBG_ERROR (( + "iba_query_ca() failed for PortAttribs!:%s\n", + _DBG_PTR(FSTATUS_MSG (status)) )); + goto failquery2; + } + + pPortTbl = (SMA_PORT_TABLE_PRIV*)MemoryAllocateAndClear(sizeof(SMA_PORT_BLOCK_PRIV) * pCaAttributes->Ports, FALSE, SMA_MEM_TAG); + if ( !pPortTbl ) + { + status = FINSUFFICIENT_MEMORY; + _DBG_ERROR (("MemAlloc failed for PortList!\n" )); + goto failtblalloc; + } + + // Reserve device resources + + // Fill in Ca details + CaObj->WorkReqId = 0; + + CaObj->Partitions = pCaAttributes->Partitions; + CaObj->AddressVectors = pCaAttributes->AddressVectors; + CaObj->CaPublic.Ports = pCaAttributes->Ports; + CaObj->CaPublic.Capabilities = pCaAttributes->Capabilities; + + // add port tables to list + CaObj->CaPublic.PortTbl = (SMA_PORT_TABLE *)pPortTbl; + + // Allocate PD Resource + status = iba_alloc_sqp_pd( + CaObj->CaHandle, +// BUGBUG - does not account for send buffers allocated by registering Gsa/Smi managers +// CM is likely to be the largest so we account for its Dgrms +// however for SMI and GSI the Recv buffers will not use AVs, so this is +// a reasonable guess +#ifdef BUILD_CM + g_Settings.MaxSMPs +g_GsaSettings.MaxRecvBuffers + + CmMaxDgrms, +#else + g_Settings.MaxSMPs +g_GsaSettings.MaxRecvBuffers, +#endif + &CaObj->PdHandle ); + if ( FSUCCESS != status ) + { + _DBG_ERROR (("AllocatePD() failed! :%s\n", + _DBG_PTR(FSTATUS_MSG (status)) )); + goto failpd; + } + + // Create One CQ per CA for SMA + status = iba_create_cq( + CaObj->CaHandle, + // CqReqSize + MIN(pCaAttributes->WorkCompletions, + (CaObj->CaPublic.Ports + * (g_Settings.SendQDepth + + g_Settings.RecvQDepth))), + (void *)QPTypeSMI, // Context + &CaObj->CqHandle, + &CaObj->CqSize ); + if ( FSUCCESS != status ) + { + _DBG_ERROR (( "iba_create_cq for SMA failed! :%s\n", + _DBG_PTR(FSTATUS_MSG (status)) )); + goto failcq; + } + + // Create One CQ per CA for GSA + status = iba_create_cq( + CaObj->CaHandle, + // CqReqSize + MIN(pCaAttributes->WorkCompletions, + (CaObj->CaPublic.Ports * (g_GsaSettings.SendQDepth+g_GsaSettings.RecvQDepth))), + (void *)QPTypeGSI, // Context + &CaObj->Qp1CqHandle, + &CaObj->Qp1CqSize ); + if ( FSUCCESS != status ) + { + _DBG_ERROR (( "iba_create_cq for GSA failed! :%s\n", + _DBG_PTR(FSTATUS_MSG (status)) )); + goto failcq2; + } + + // Get a Special QP each for SMA and GSA on each port + for ( i=0; i< CaObj->CaPublic.Ports; i++ ) + { + _DBG_PRINT(_DBG_LVL_DEVICE,( + "Processing device port(%d) :GUID(x%"PRIx64")\n", + i+1, + pTempPortAttributesList->GUID )); + + // Fill in per Port details + pPortTbl->PortBlock[i].Public.PortNumber = (uint8)i+1; + pPortTbl->PortBlock[i].Public.GUID = \ + pTempPortAttributesList->GUID; + pPortTbl->PortBlock[i].Public.NumGIDs = \ + pTempPortAttributesList->NumGIDs; + pPortTbl->PortBlock[i].Public.NumPKeys = \ + pTempPortAttributesList->NumPkeys; + + // fill in default Port state + pPortTbl->PortBlock[i].Public.State = \ + pTempPortAttributesList->PortState; + + // set QP attribs for SMA + qpCreateAttributes.Type = QPTypeSMI; + qpCreateAttributes.PDHandle = CaObj->PdHandle; + qpCreateAttributes.SendCQHandle = CaObj->CqHandle; + qpCreateAttributes.RecvCQHandle = CaObj->CqHandle; + + qpCreateAttributes.SendQDepth = + MIN(pCaAttributes->WorkReqs, g_Settings.SendQDepth); + qpCreateAttributes.RecvQDepth = + MIN(pCaAttributes->WorkReqs, g_Settings.RecvQDepth); + + qpCreateAttributes.SendDSListDepth = 1; + qpCreateAttributes.RecvDSListDepth = 2; + + qpCreateAttributes.CompletionFlags = IB_COMPL_CNTL_SEND; + + status = iba_create_special_qp( + CaObj->CaHandle, + pPortTbl->PortBlock[i].Public.GUID, + &qpCreateAttributes, + &pPortTbl->PortBlock[i].QpHandle, // Context + &pPortTbl->PortBlock[i].QpHandle, + &qpAttributes ); + if ( FSUCCESS != status ) + { + _DBG_ERROR (( + "CreateSpecialQP() failed on port(%d) for SMA :%s!\n", + i+1, + _DBG_PTR(FSTATUS_MSG (status)) )); + goto failsmi; + } + + + // set QP attribs for GSA + // Note: GSA QP created with fixed settings. Changes + // to QP and CQ size will be done in GSA module if applicable + qpCreateAttributes.Type = QPTypeGSI; + qpCreateAttributes.PDHandle = CaObj->PdHandle; + qpCreateAttributes.SendCQHandle = CaObj->Qp1CqHandle; + qpCreateAttributes.RecvCQHandle = CaObj->Qp1CqHandle; + + qpCreateAttributes.RecvDSListDepth = 2; //pCaAttributes->DSListDepth; + qpCreateAttributes.SendDSListDepth = 3; //pCaAttributes->DSListDepth; + qpCreateAttributes.RecvQDepth = + MIN(pCaAttributes->WorkReqs, g_GsaSettings.RecvQDepth); + qpCreateAttributes.SendQDepth = + MIN(pCaAttributes->WorkReqs, g_GsaSettings.SendQDepth); + + qpCreateAttributes.CompletionFlags = IB_COMPL_CNTL_SEND; + + status = iba_create_special_qp( + CaObj->CaHandle, + pPortTbl->PortBlock[i].Public.GUID, + &qpCreateAttributes, + &pPortTbl->PortBlock[i].Qp1Handle, // Context + &pPortTbl->PortBlock[i].Qp1Handle, + &qpAttributes ); + if ( FSUCCESS != status ) + { + _DBG_ERROR (( + "CreateSpecialQP() failed on port(%d) for GSA :%s!\n", + i+1, + _DBG_PTR(FSTATUS_MSG (status)) )); + goto failgsi; + } + + // Spinlock for Qp0 & Qp1 + SpinLockInitState( &pPortTbl->PortBlock[i].Qp0Lock ); + SpinLockInitState( &pPortTbl->PortBlock[i].QpLock ); + + if( !SpinLockInit( &pPortTbl->PortBlock[i].Qp0Lock ) ) + { + _DBG_ERROR(( "Unable to initialize spinlocks for Port(%d)!\n", i+1 )); + goto faillock0; + } + if ( !SpinLockInit( &pPortTbl->PortBlock[i].QpLock ) ) + { + _DBG_ERROR(( "Unable to initialize spinlocks for Port(%d)!\n", i+1 )); + goto faillock; + } + + // update info + pPortTbl->PortBlock[i].Qp0SendQDepth = \ + qpAttributes.SendQDepth; + AtomicWrite(&pPortTbl->PortBlock[i].Qp0SendQTop, + qpAttributes.SendQDepth); + pPortTbl->PortBlock[i].Qp0RecvQDepth = \ + qpAttributes.RecvQDepth; + AtomicWrite(&pPortTbl->PortBlock[i].Qp0RecvQTop, + qpAttributes.RecvQDepth); + + // keep count of All QP depths + qp0CqSize += pPortTbl->PortBlock[i].Qp0SendQDepth + \ + pPortTbl->PortBlock[i].Qp0RecvQDepth; + + // loop + pTempPortAttributesList = pTempPortAttributesList->Next; + + } // i loop + + // add port tables to list + CaObj->CaPublic.PortTbl = (SMA_PORT_TABLE *)pPortTbl; + + // SMA Only: GSA resize of QP and CQ handled in GSA module + // Resize CQ if necessary + // Validate CQ size depth with all Qp depths + _DBG_PRINT (_DBG_LVL_DEVICE, ( + "CqSize: \n" + "\tStored.......:%d\n" + "\tCalculated...:%d\n" + "\tResize.......:%s\n", + MIN(pCaAttributes->WorkCompletions, g_Settings.MaxCqSize), + qp0CqSize, + _DBG_PTR(qp0CqSize < MIN(pCaAttributes->WorkCompletions, g_Settings.MaxCqSize) ? "TRUE":"FALSE") )); + + // Update Cqsize only if we have allocated more than + // the h/w can achieve. + if ( qp0CqSize < MIN(pCaAttributes->WorkCompletions, g_Settings.MaxCqSize)) + { + status = iba_resize_cq( + CaObj->CqHandle, + MIN(pCaAttributes->WorkCompletions, g_Settings.MaxCqSize), + &CaObj->CqSize ); + if (FSUCCESS != status) + { + _DBG_ERROR (( + "iba_resize_cq() failed for SMA :%s!\n", + _DBG_PTR(FSTATUS_MSG (status)) )); + goto failresize; + } + } + MemoryDeallocate ( pPortAttributesList ); + MemoryDeallocate ( pCaAttributes ); + +done: + _DBG_LEAVE_LVL(_DBG_LVL_DEVICE); + return status; + +failresize: + --i; + SpinLockDestroy( &pPortTbl->PortBlock[i].QpLock ); +faillock: + SpinLockDestroy( &pPortTbl->PortBlock[i].Qp0Lock ); +faillock0: + iba_destroy_qp( pPortTbl->PortBlock[i].Qp1Handle ); +failgsi: + iba_destroy_qp( pPortTbl->PortBlock[i].QpHandle ); +failsmi: + while (i > 0) + { + --i; + SpinLockDestroy( &pPortTbl->PortBlock[i].QpLock ); + SpinLockDestroy( &pPortTbl->PortBlock[i].Qp0Lock ); + iba_destroy_qp( pPortTbl->PortBlock[i].Qp1Handle ); + iba_destroy_qp( pPortTbl->PortBlock[i].QpHandle ); + } + iba_destroy_cq( CaObj->Qp1CqHandle ); + CaObj->Qp1CqHandle = NULL; +failcq2: + iba_destroy_cq( CaObj->CqHandle ); + CaObj->CqHandle = NULL; +failcq: + iba_free_pd( CaObj->PdHandle ); + CaObj->PdHandle = NULL; +failpd: + MemoryDeallocate ( pPortTbl ); + CaObj->CaPublic.PortTbl = NULL; +failtblalloc: +failquery2: + MemoryDeallocate ( pPortAttributesList ); +failportalloc: +failquery: + MemoryDeallocate ( pCaAttributes ); +failcaalloc: + goto done; +} + + + +FSTATUS +SmaConfigQp( + IN IB_HANDLE QpHandle, + IN IB_QP_STATE QpState, + IN IB_QP_TYPE QpType + ) +{ + FSTATUS status = FSUCCESS; + IB_QP_ATTRIBUTES_MODIFY qpModAttributes; + + + _DBG_ENTER_LVL(_DBG_LVL_DEVICE, SmaConfigQp); + + + // set QP attribs based on transition and QpType + switch (QpState) + { + default: + _DBG_ERROR(("Invalid QP State requested!\n")); + status = FINVALID_SETTING; + goto done; + break; + + case QPStateInit: + { + qpModAttributes.RequestState = QPStateInit; + qpModAttributes.Attrs = (IB_QP_ATTR_PKEYINDEX + | IB_QP_ATTR_QKEY); + qpModAttributes.PkeyIndex = 0; // BUGBUG not applicable + if ( QPTypeSMI == QpType ) + qpModAttributes.Qkey = 0; + else + qpModAttributes.Qkey = QP1_WELL_KNOWN_Q_KEY; + } + break; + + case QPStateReadyToRecv: + { + qpModAttributes.RequestState = QPStateReadyToRecv; + qpModAttributes.Attrs = 0; + + } + break; + + case QPStateReadyToSend: + { + qpModAttributes.RequestState = QPStateReadyToSend; + qpModAttributes.Attrs = IB_QP_ATTR_SENDPSN; + qpModAttributes.SendPSN = 0x00000001; + } + break; + } // switch + + // transition QP states + status = iba_modify_qp( QpHandle, &qpModAttributes, NULL ); + if ( FSUCCESS != status ) + { + _DBG_ERROR(("Modify Qp failed!\n")); + } + +done: + _DBG_LEAVE_LVL(_DBG_LVL_DEVICE); + return status; +} + + + +FSTATUS +SmaDeviceConfig( + IN SMA_CA_OBJ_PRIVATE *CaObj, + IN IB_QP_TYPE QpType + ) +{ + FSTATUS status = FSUCCESS; + SMA_PORT_TABLE_PRIV *pPortTbl; + uint32 i; + + _DBG_ENTER_LVL(_DBG_LVL_DEVICE, SmaDeviceConfig); + + + pPortTbl = (SMA_PORT_TABLE_PRIV *)CaObj->CaPublic.PortTbl; + + // Loop thru' all QP0's + for ( i=0; i< CaObj->CaPublic.Ports; i++ ) + { + // set QP to Init state + status = SmaConfigQp( + (( QPTypeSMI == QpType ) ? \ + pPortTbl->PortBlock[i].QpHandle:pPortTbl->PortBlock[i].Qp1Handle), + QPStateInit, + QpType ); + if ( FSUCCESS != status ) + { + _DBG_ERROR(( + "Could not transition QP%s to Init on port %d!\n", + _DBG_PTR((( QPTypeSMI == QpType ) ? "0":"1")), + i+1)); + } else { + // transition QP states + + // RecvQ to RTR + status = SmaConfigQp( + (( QPTypeSMI == QpType ) ? \ + pPortTbl->PortBlock[i].QpHandle : \ + pPortTbl->PortBlock[i].Qp1Handle), + QPStateReadyToRecv, + QpType ); + if ( FSUCCESS == status ) + { + // SendQ to RTS + status = SmaConfigQp( + (( QPTypeSMI == QpType ) ? \ + pPortTbl->PortBlock[i].QpHandle : \ + pPortTbl->PortBlock[i].Qp1Handle), + QPStateReadyToSend, + QpType ); + if ( FSUCCESS != status ) + { + // BUGBUG: return module error + _DBG_ERROR(( + "Error transitioning QP%s on Port[%d] to RTS!\n", + _DBG_PTR((( QPTypeSMI == QpType ) ? "0":"1")), + i+1)); + } + } else { + // BUGBUG: return module error + _DBG_ERROR(( + "Error transitioning QP%s on Port[%d] to RTR!\n", + _DBG_PTR((( QPTypeSMI == QpType ) ? "0":"1")), + i+1)); + } + } // modify QP to hold CQ + } // for Port loop + + _DBG_LEAVE_LVL(_DBG_LVL_DEVICE); + return status; +} + + + +FSTATUS +GetAV( + IN SMA_CA_OBJ_PRIVATE *CaObj, + IN IB_ADDRESS_VECTOR *AvInfo, + OUT IB_HANDLE *AvHandle + ) +{ + FSTATUS status = FSUCCESS; + SMA_PORT_TABLE_PRIV *pPortTbl; + + _DBG_ENTER_LVL(_DBG_LVL_DEVICE, GetAV); + + pPortTbl = (SMA_PORT_TABLE_PRIV *)CaObj->CaPublic.PortTbl; + + // Create AV if one does not exist + _DBG_PRINT(_DBG_LVL_DEVICE,( + "AV Info:\n" + "Local:\n" + "\tPortGUID.....:x%"PRIx64"\n" + "\tPathBits.....:x%X\n" + "\tServiceLevel.:x%X\n" + "\tStaticRate...:x%X\n" + "Remote:\n" + "\tLID..........:x%X\n" + "\tGlobalRoute..:%s\n", + AvInfo->PortGUID, + AvInfo->PathBits, + AvInfo->ServiceLevel, + AvInfo->StaticRate, + AvInfo->DestLID, + _DBG_PTR(AvInfo->GlobalRoute == TRUE ? "TRUE":"FALSE" ))); + + // Add Global Routing Info if present + if (AvInfo->GlobalRoute) + { + _DBG_PRINT(_DBG_LVL_DEVICE,( + "Global Route Info:\n" + "\tFlowLabel....:x%X\n" + "\tHopLimit.....:x%X\n" + "\tSrcGIDIndex..:x%X\n" + "\tTrafficClass.:x%X\n", + AvInfo->GlobalRouteInfo.FlowLabel, + AvInfo->GlobalRouteInfo.HopLimit, + AvInfo->GlobalRouteInfo.SrcGIDIndex, + AvInfo->GlobalRouteInfo.TrafficClass )); + } + + status = iba_create_av( CaObj->CaHandle, CaObj->PdHandle, AvInfo, AvHandle); + + _DBG_LEAVE_LVL(_DBG_LVL_DEVICE); + return status; +} + + +FSTATUS +PutAV( + IN SMA_CA_OBJ_PRIVATE *CaObj, + IN IB_HANDLE AvHandle + ) +{ + FSTATUS status = FSUCCESS; + + _DBG_ENTER_LVL(_DBG_LVL_DEVICE, PutAV); + + // Destroy AV or cache it + + status = iba_destroy_av( AvHandle ); + + _DBG_LEAVE_LVL (_DBG_LVL_DEVICE); + return status; +} + + +void +NotifyIbtCallback ( + IN void *Context + ) +{ + SMA_CA_OBJ_PRIVATE *pCaObj; + SMA_PORT_TABLE_PRIV *pPortTbl; + SMA_PORT_BLOCK_PRIV *pPortBlock; + uint32 j; + + _DBG_ENTER_LVL(_DBG_LVL_DEVICE, NotifyIbtCallback); + + // Scan through all CA's + SpinLockAcquire(&g_Sma->CaListLock); + for (pCaObj = g_Sma->CaObj; pCaObj != NULL; pCaObj = pCaObj->Next) + { + boolean exists; + + pCaObj->UseCount++; + SpinLockRelease(&g_Sma->CaListLock); + + exists = IbtNotifyUserEvent( Context, + pCaObj->CaPublic.CaGuid, // Port/Node GUID + IB_NOTIFY_CA_ADD ); + if (! exists) + goto release; + + // Now notify about port events too + pPortTbl = (SMA_PORT_TABLE_PRIV *)pCaObj->CaPublic.PortTbl; + for ( j = 0; j< pCaObj->CaPublic.Ports ; j++ ) + { + pPortBlock = &pPortTbl->PortBlock[j]; + + if ( IB_PORT_ACTIVE == pPortBlock->Public.State ) + { + exists = IbtNotifyUserEvent( Context, + pPortBlock->Public.GUID,// Port/Node GUID + IB_NOTIFY_LID_EVENT ); + if (! exists) + goto release; + } + } + + SpinLockAcquire(&g_Sma->CaListLock); + pCaObj->UseCount--; + } + +done: + SpinLockRelease(&g_Sma->CaListLock); + _DBG_LEAVE_LVL (_DBG_LVL_DEVICE); + return; + +release: + SpinLockAcquire(&g_Sma->CaListLock); + pCaObj->UseCount--; + goto done; +} + +void +SetClassMask ( + IN uint8 Class, + IN boolean Enabled + ) +{ + switch (Class) + { + case MCLASS_COMM_MGT: + if ( TRUE == Enabled ) + g_Sma->IsConnectionManagementSupported = 1; + else + g_Sma->IsConnectionManagementSupported = 0; + break; + +#if 0 + case MCLASS_SNMP: + if ( TRUE == Enabled ) + g_Sma->IsSNMPTunnelingSupported = 1; + else + g_Sma->IsSNMPTunnelingSupported = 0; + break; + + case MCLASS_DEV_MGT: + if ( TRUE == Enabled ) + g_Sma->IsDeviceManagementSupported = 1; + else + g_Sma->IsDeviceManagementSupported = 0; + break; +#endif + + // + // TBD: + // Must handle vendor Classes here + //case MCLASS_X: + // + + default: + _DBG_PRINT(_DBG_LVL_DEVICE,( + "No capabilities for this Class [x%X]\n", + Class )); + } +} + +void +SetPortCapabilities ( void ) +{ + SMA_CA_OBJ_PRIVATE *pCaObj; + FSTATUS status; + SMA_PORT_TABLE_PRIV *pPortTbl; + SMA_PORT_BLOCK_PRIV *pPortBlock; + STL_SMP *pSmp; + STL_PORT_INFO *pPortInfo; + uint32 j; + uint8 portNo; + uint32 smps; + POOL_DATA_BLOCK *pSmpBlock; + + + _DBG_ENTER_LVL (_DBG_LVL_DEVICE, SetPortCapabilities); + + for ( ;; ) + { + smps = 1; + pSmpBlock = NULL; + + status = iba_smi_pool_get( + NULL, + &smps, + (SMP_BLOCK **)&pSmpBlock ); + + if ( (FSUCCESS != status) || (pSmpBlock == NULL) ) + { + _DBG_ERROR (( + "Could not Grab from Pool!\n" )); + break; + } + + pSmp = (STL_SMP*)pSmpBlock->Block.Smp; + pPortInfo = (STL_PORT_INFO*)pSmp->SmpExt.DirectedRoute.SMPData; + + // Scan through all CA's + SpinLockAcquire(&g_Sma->CaListLock); + for (pCaObj = g_Sma->CaObj; pCaObj != NULL; pCaObj = pCaObj->Next) + { + uint32 capMaskUpdate=0; + uint32 MadQueryLength; + + pCaObj->UseCount++; + SpinLockRelease(&g_Sma->CaListLock); + + // Set each port + pPortTbl = (SMA_PORT_TABLE_PRIV *)pCaObj->CaPublic.PortTbl; + + for ( j = 0; j< pCaObj->CaPublic.Ports ; j++ ) + { + pPortBlock = &pPortTbl->PortBlock[j]; + portNo = (uint8)j; // switch port zero + + // Format MAD get PortInfo + pSmp->common.BaseVersion = STL_BASE_VERSION; + pSmp->common.ClassVersion = STL_SM_CLASS_VERSION; + + pSmp->common.mr.AsReg8 = 0; + pSmp->common.mr.s.Method = MMTHD_GET; + + pSmp->SmpExt.DirectedRoute.DrDLID = STL_LID_PERMISSIVE; + pSmp->SmpExt.DirectedRoute.DrSLID = STL_LID_PERMISSIVE; + + pSmp->common.u.DR.s.Status = 0; + pSmp->common.u.DR.s.D = 0; + pSmp->common.u.DR.HopCount = 0; + pSmp->common.u.DR.HopPointer = 0; + //pSmp->common.TransactionID = 0; + pSmp->common.MgmtClass = MCLASS_SM_DIRECTED_ROUTE; + + pSmp->common.AttributeID = STL_MCLASS_ATTRIB_ID_PORT_INFO; + pSmp->common.AttributeModifier = 0x01000000 | portNo; + + STL_SMP_SET_LOCAL(pSmp); // local request + + MadQueryLength = sizeof(*pSmp) - STL_MAX_PAYLOAD_SMP_DR; + status = iba_get_set_mad( pPortBlock->QpHandle, portNo, + 0, // SLID ignored, local request + pSmp, + &MadQueryLength ); + if ( FSUCCESS != status ) + { + _DBG_ERROR (( + "Could not GET Port capabilities!\n" )); + break; + } + + // SWAP THE GETPORTINFO response + BSWAP_STL_PORT_INFO(pPortInfo); + ZERO_RSVD_STL_PORT_INFO(pPortInfo); + + // Set capability if necessary + if (g_Sma->IsConnectionManagementSupported && !pPortInfo->CapabilityMask.s.IsConnectionManagementSupported) { + pPortInfo->CapabilityMask.s.IsConnectionManagementSupported = \ + g_Sma->IsConnectionManagementSupported; + capMaskUpdate = 1; + } + if (g_Sma->IsDeviceManagementSupported && !pPortInfo->CapabilityMask.s.IsDeviceManagementSupported) { + pPortInfo->CapabilityMask.s.IsDeviceManagementSupported = \ + g_Sma->IsDeviceManagementSupported; + capMaskUpdate = 1; + } + if (!capMaskUpdate) + break; // nothing to change + + // Do not change other fields + pPortInfo->LinkWidth.Enabled = STL_LINK_WIDTH_NOP; + pPortInfo->PortStates.s.PortState = IB_PORT_NOP; + pPortInfo->PortStates.s.PortPhysicalState = IB_PORT_PHYS_NOP; + pPortInfo->s4.OperationalVL = 0; + pPortInfo->LinkSpeed.Enabled = IB_LINK_SPEED_NOP; + + // SWAP THE SET PORT INFO payload + BSWAP_STL_PORT_INFO(pPortInfo); + + // Set base MAD info + pSmp->common.BaseVersion = STL_BASE_VERSION; + pSmp->common.ClassVersion = STL_SM_CLASS_VERSION; + + pSmp->common.mr.AsReg8 = 0; + pSmp->common.mr.s.Method = MMTHD_SET; + + pSmp->SmpExt.DirectedRoute.DrDLID = STL_LID_PERMISSIVE; + pSmp->SmpExt.DirectedRoute.DrSLID = STL_LID_PERMISSIVE; + + pSmp->common.u.DR.s.Status = 0; + pSmp->common.u.DR.s.D = 0; + pSmp->common.u.DR.HopCount = 0; + pSmp->common.u.DR.HopPointer = 0; + //pSmp->common.TransactionID = 0; + pSmp->common.MgmtClass = MCLASS_SM_DIRECTED_ROUTE; + + pSmp->common.AttributeID = STL_MCLASS_ATTRIB_ID_PORT_INFO; + pSmp->common.AttributeModifier = 0x01000000 | portNo; + + STL_SMP_SET_LOCAL(pSmp); // local request + + MadQueryLength = sizeof(*pSmp) - STL_MAX_PAYLOAD_SMP_DR + sizeof(*pPortInfo); + status = iba_get_set_mad( pPortBlock->QpHandle, portNo, + 0, // SLID ignored, local request + pSmp, + &MadQueryLength ); + if ( FSUCCESS != status ) + break; + + } // loop j - ports + + SpinLockAcquire(&g_Sma->CaListLock); + pCaObj->UseCount--; + + if ( FSUCCESS != status ) + break; + + } // loop - CA's + SpinLockRelease(&g_Sma->CaListLock); + + status = iba_smi_pool_put( NULL, (SMP_BLOCK *)pSmpBlock ); + break; + } + + _DBG_LEAVE_LVL (_DBG_LVL_DEVICE); +} + +void +SetPortCapabilityMask ( + IN uint8 Class, + IN boolean Enabled + ) +{ + _DBG_ENTER_LVL (_DBG_LVL_DEVICE, SetPortCapabilityMask ); + + // Check init state of drivers + SetClassMask ( Class, Enabled ); + + if ( g_Sma->NumCa ) + { + SetPortCapabilities (); + } else { + _DBG_PRINT (_DBG_LVL_DEVICE, ( + "No devices present. Caching capabilities for an Add Device\n" )); + } + + _DBG_LEAVE_LVL (_DBG_LVL_DEVICE); +} diff --git a/IbAccess/Common/Ibt/Sma/smacallb.c b/IbAccess/Common/Ibt/Sma/smacallb.c new file mode 100644 index 0000000..56897e1 --- /dev/null +++ b/IbAccess/Common/Ibt/Sma/smacallb.c @@ -0,0 +1,1614 @@ +/* BEGIN_ICS_COPYRIGHT4 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT4 ****************************************/ + + +#include "smamain.h" + + +// +// SmaProcessLocalToSma +// +// Process Local SMP activity to SMA. +// Does a local Operation and sets internal states +// +// +// +// INPUTS: +// +// SmpBlock - SMP Block received +// +// OUTPUTS: +// +// TRUE/FALSE - TRUE: SMP processed and used +// - FALSE: Recycle SMP +// +// RETURNS: +// +// FSTATUS. +// +// IRQL: +// +// This routine is called at IRQL_DISPATCH_LEVEL. +// + +static boolean +SmaProcessLocalToSma( + IN POOL_DATA_BLOCK *SmpBlock + ) +{ + FSTATUS status = FSUCCESS; + STL_SMP *pSmp = (STL_SMP*)SmpBlock->Block.Smp; + SMA_CA_OBJ_PRIVATE *pCaObj; + SMA_PORT_TABLE_PRIV *pPortTbl; + SMA_PORT_BLOCK_PRIV *pPortBlock; + IB_PORT_STATE oldPortState; + boolean bStatus=TRUE; // default processed + uint8 portNo,oldLMC; + IB_LID oldLID, oldSmLID; + uint8 method; + boolean zero_lid; + + _DBG_ENTER_LVL( _DBG_LVL_CALLBACK, SmaProcessLocalToSma ); + + pCaObj = (SMA_CA_OBJ_PRIVATE *)SmpBlock->Block.SmaCaContext; + pPortTbl = (SMA_PORT_TABLE_PRIV *)pCaObj->CaPublic.PortTbl; + + /* special case, suppress INVALID_ATTRIB error message on Set(PortInfo) + * with 0 LID. This can occur for host SM when 1st starting only SM + * on fabric. What happens is SM sets capability mask using present LID + * which is 0 when HFI first comes up. + */ + zero_lid = (pSmp->common.mr.AsReg8 == MMTHD_SET + && pSmp->common.AttributeID == STL_MCLASS_ATTRIB_ID_PORT_INFO + && 0 == ((STL_PORT_INFO *)&pSmp->SmpExt.DirectedRoute.SMPData)->LID); + + // save method + method = pSmp->common.mr.AsReg8; + // clear Status + pSmp->common.u.DR.s.Status = MAD_STATUS_SUCCESS; + + if (pCaObj->CaPublic.Capabilities & CA_IS_ENHANCED_SWITCH_PORT0) + { + if (SmpBlock->Block.PortNumber != 0) + { + _DBG_ERROR(("SmpBlock->Block.PortNumber == %d, should be 0!\n", SmpBlock->Block.PortNumber)); + status = FERROR; + } + portNo = 0; + } else { + portNo = SmpBlock->Block.PortNumber - 1; + } + + // call verb + if (FSUCCESS == status) + { + status = iba_get_set_mad( + pPortTbl->PortBlock[portNo].QpHandle, + SmpBlock->Block.PortNumber, + SmpBlock->Block.SLID, + pSmp, + &SmpBlock->Block.SmpByteCount); + } + + if ( FSUCCESS != status ) + { + // FNOT_DONE indicates an internal MAD which we chose to quietly discard + if (FNOT_DONE != status) + { + _DBG_ERROR(("GetSetMad() failed with x%x!\n", status)); + } + + // return VPD reported status in status + SmpBlock->Block.Status = status; + bStatus = FALSE; + } + // we need to update port state view even if Mad returns + // INVALID_ATTRIB valid because it is reporting the new state + else if (pSmp->common.u.DR.s.Status == MAD_STATUS_SUCCESS + || pSmp->common.u.DR.s.Status == MAD_STATUS_INVALID_ATTRIB) + { + // Update internal states + switch ( pSmp->common.AttributeID ) + { + default: + { + break; + } + + case MCLASS_ATTRIB_ID_PORT_INFO: + { + // Update internal port state: LID, LMC, State + if (pCaObj->CaPublic.Capabilities & CA_IS_ENHANCED_SWITCH_PORT0) + { + if (pSmp->common.AttributeModifier != 0) + { + // Nothing to cache for switch ports other than 0 + break; + } + portNo = 0; // Switch port 0 is treated as first 0 in list + } else { + portNo = (uint8)(pSmp->common.AttributeModifier & 0x000000FF); + if (0 == portNo) // Is it the default port? + { + portNo = SmpBlock->Block.PortNumber - 1; // use in port + } else { + portNo--; // get zero based index into port tables + + // Check for invalid port number, GetSetMad should have + // already checked, so we do not expect the test below + // to fail. + if ( portNo >= pCaObj->CaPublic.Ports ) + { + _DBG_ERROR(("Invalid Port: %d\n", portNo+1)); + bStatus = FALSE; // SMP not processed + } + } + } + + if (bStatus) + { + STL_PORT_INFO *pPortInfo = + (STL_PORT_INFO *)&pSmp->SmpExt.DirectedRoute.SMPData; + BSWAP_STL_PORT_INFO(pPortInfo); + ZERO_RSVD_STL_PORT_INFO(pPortInfo); + pPortBlock = &pPortTbl->PortBlock[portNo]; + + // Before we update our internal state save + // old state for callbacks + oldPortState = pPortBlock->Public.State; + oldLID = pPortBlock->Public.Address.BaseLID; + oldLMC = pPortBlock->Public.Address.LMC; + oldSmLID = pPortBlock->SMLID; + + // Update internal state + pPortBlock->Public.Address.BaseLID = pPortInfo->LID; + pPortBlock->Public.Address.LMC = pPortInfo->s1.LMC; + pPortBlock->Public.State = (IB_PORT_STATE) pPortInfo->PortStates.s.PortState; + pPortBlock->SMLID = pPortInfo->MasterSMLID; + + // Notify users of a Port event + if ( oldPortState != pPortBlock->Public.State ) + { + if ( IB_PORT_ACTIVE == pPortBlock->Public.State ) + { + IbtNotifyGroup( pPortBlock->Public.GUID, + IB_NOTIFY_LID_EVENT ); + } + + // Here any other state will be a port down event + // An SM could change a port status from Active to + // Armed to reconfigure it. We take care of a case + // where connections were active and go down on an + // incoming ARM Smp that needs to report to Channel + // drivers that the port is down. + if (( IB_PORT_DOWN == pPortBlock->Public.State ) ||\ + ( IB_PORT_ACTIVE == oldPortState )) + { + IbtNotifyGroup( pPortBlock->Public.GUID, + IB_NOTIFY_PORT_DOWN ); + } + } else { + // Notify changes to Active LID/LMC when multipathing + // kicks in or on a SM takeover. + if ( IB_PORT_ACTIVE == pPortBlock->Public.State ) + { + if (( oldLID != pPortInfo->LID ) || \ + ( oldLMC != pPortInfo->s1.LMC )) + { + IbtNotifyGroup( pPortBlock->Public.GUID, + IB_NOTIFY_LID_EVENT ); + } else if ( oldSmLID != pPortInfo->MasterSMLID + || (method == MMTHD_SET && pPortInfo->Subnet.ClientReregister) ) + { + IbtNotifyGroup( pPortBlock->Public.GUID, + IB_NOTIFY_SM_EVENT ); + } + } + } + BSWAP_STL_PORT_INFO(pPortInfo); + } // valid portNo + + break; + } + + case STL_MCLASS_ATTRIB_ID_PART_TABLE: + if (bStatus && method == MMTHD_SET) + { + // Notify users of PKey event + if (pCaObj->CaPublic.Capabilities & CA_IS_ENHANCED_SWITCH_PORT0) + { + portNo = (pSmp->common.AttributeModifier >> 16) & 0x00FF; + if (portNo != 0) + { + break; + } + } else { + portNo = SmpBlock->Block.PortNumber - 1; // use in port + } + + pPortBlock = &pPortTbl->PortBlock[portNo]; + + // BUGBUG TBD compare PKeys and only notify if they changed + IbtNotifyGroup( pPortBlock->Public.GUID, IB_NOTIFY_PKEY_EVENT); + } + + break; + + } // switch + + if (pSmp->common.u.DR.s.Status == MAD_STATUS_INVALID_ATTRIB + && ! zero_lid) + { + _DBG_ERROR(("GetSetMad() returned MAD with Status x%x!\n", + pSmp->common.u.DR.s.Status)); + } + } else { + _DBG_ERROR(("GetSetMad() returned MAD with Status x%x!\n", + pSmp->common.u.DR.s.Status)); + } // GetSetMad status + + _DBG_RETURN_LVL(_DBG_LVL_CALLBACK, bStatus); + + return (bStatus); +} + +// +// SmaProcessSmaSmpRcvd +// +// Processes SMA SMP received. +// A check is done to verify the validity of the SMP. +// If the SMP needs further processing like a reply, this returns TRUE +// and the caller must ProcessSmiSmp and if appropriate +// post a reply on the SendQ of this port's QP. +// +// +// INPUTS: +// +// SmpBlock - SMP Block received +// +// OUTPUTS: +// +// TRUE/FALSE - TRUE: SMP processed and used +// - FALSE: Recycle SMP +// +// RETURNS: +// +// FSTATUS. +// +// IRQL: +// +// This routine is called at IRQL_DISPATCH_LEVEL. +// + +boolean +SmaProcessSmaSmpRcvd( + IN POOL_DATA_BLOCK *SmpBlock + ) +{ + STL_SMP *pSmp = (STL_SMP*)SmpBlock->Block.Smp; + SMA_CA_OBJ_PRIVATE *pCaObj; + SMA_PORT_TABLE_PRIV *pPortTbl; + boolean bProcess=TRUE; + + + _DBG_ENTER_LVL(_DBG_LVL_CALLBACK, SmaProcessSmaSmpRcvd); + + pCaObj = (SMA_CA_OBJ_PRIVATE *)SmpBlock->Block.SmaCaContext; + pPortTbl = (SMA_PORT_TABLE_PRIV *)pCaObj->CaPublic.PortTbl; + + + // M_Key check is expected to be done by SmaProcessLocalToSma + // it should keep track of the M_Key for each port and validate them + + bProcess = SmaProcessLocalToSma( SmpBlock ); + if ( TRUE == bProcess ) + { + + // + // Return info : + // Set HopPointer HopCount info + // + + // + // DLID = SLID of request + // + + if (SmpBlock->Block.SLID == 0) + { + // special case for locally generated Traps provided to us on + // QP0 by firmware. We send to SM. + if ( MCLASS_SM_DIRECTED_ROUTE == pSmp->common.MgmtClass ) + { + SmpBlock->Block.SLID = STL_LID_PERMISSIVE; + SmpBlock->Block.DLID = STL_LID_PERMISSIVE; + SmpBlock->Block.PathBits = 0; + } else { + SmpBlock->Block.DLID = pPortTbl[SmpBlock->Block.PortNumber - 1].PortBlock->SMLID; + SmpBlock->Block.PathBits = 0; // use our first lid + SmpBlock->Block.SLID = 0; // will fill in our lid below + } + } else { + // IBTA 1.1 14.2.2.3 C14-10 + // GetResp is set by GetSetMad for SMA packets + // D bit is set by GetSetMad for Directed Route SMA packets + // GetSetMad uses original SMP buffer, so other parts of Route + // are copied as is + // C14-11 2nd bullet + SmpBlock->Block.DLID = SmpBlock->Block.SLID; + SmpBlock->Block.SLID = 0; // will fill in our lid below + // PathBits of SLID will be from DestPathBits in request + } + + if ( MCLASS_SM_DIRECTED_ROUTE == pSmp->common.MgmtClass ) + { + if ( STL_LID_PERMISSIVE == pSmp->SmpExt.DirectedRoute.DrDLID) { + // IBTA 1.1 Sec 14.2.2.3 C14-11 + // the directed route part starts from the respondor node (us) + // LRH_SLID shall be the permissive lid or a lid of this port + // safest to use permissive lid, since we may not have a lid yet + SmpBlock->Block.SLID = STL_LID_PERMISSIVE; + } + } + + // + // If ( SLID != LID_PERMISSIVE ) + // SLID = Responder's LID + // + + if ( STL_LID_PERMISSIVE != SmpBlock->Block.SLID ) + { + uint8 lmc = pPortTbl[SmpBlock->Block.PortNumber - 1].PortBlock->Public.Address.LMC; + SmpBlock->Block.SLID = + PathBitsToLid(pPortTbl[SmpBlock->Block.PortNumber - 1].PortBlock->Public.Address.BaseLID, + SmpBlock->Block.PathBits, lmc); + _DBG_PRINT (_DBG_LVL_CALLBACK, ( + "Response lmc: %d\n" + "Pathbits: %d\n" + "SLID: %x\n", + lmc, + SmpBlock->Block.PathBits, + SmpBlock->Block.SLID)); + } + } + + _DBG_RETURN_LVL(_DBG_LVL_CALLBACK, bProcess); + + return (bProcess); + +} + +// Per SMI packet processing as defined in section 13.5.3.3 and 14.2.2 +// of IBTA 1.1 +// This should be used to process all SMP packets arriving at the SMI +// both from QP0, responses from the local SMA, and packets from SmaPostSend +// +// INPUTS: +// +// pCaObj - CA receiving block +// SmpBlock - SMP Block delivered to Smi +// FromWire - was SMP received on QP0 or delivered locally to SMI +// affects LID routed identification +// +// RETURNS: +// SMI_DISCARD - SMP should be discarded +// SMI_SEND - SMP should be sent on the wire via PortNumber in pSmpBlock +// SMI_TO_LOCAL_SM - SMP should be delivered to local SM +// SMI_TO_LOCAL - SMP should be delivered to local SM or SMA +// see SmaProcessLocalSmp +// SMI_LID_ROUTED - LID routed SMP, destination will depend on context of call +SMI_ACTION +SmaProcessSmiSmp( + IN SMA_CA_OBJ_PRIVATE *pCaObj, + IN OUT POOL_DATA_BLOCK *pSmpBlock, + IN boolean FromWire + ) +{ + IN STL_SMP *pSmp = (STL_SMP*)pSmpBlock->Block.Smp; + SMA_PORT_TABLE_PRIV *pPortTbl = (SMA_PORT_TABLE_PRIV *)pCaObj->CaPublic.PortTbl; + + _DBG_ENTER_LVL(_DBG_LVL_CALLBACK, SmaProcessSmiSmp); + + _DBG_PRINT (_DBG_LVL_CALLBACK, ( + "SMI Processing for:\n" + "\tClass........:x%x\n" + "\tAttribID.....:x%X\n" + "\tAttribModfier:x%X\n" + "\tMethod.......:x%X\n" + "\tResponseBit..:x%X\n" + "\tHopCount.....:x%X\n", + pSmp->common.MgmtClass, + pSmp->common.AttributeID, + pSmp->common.AttributeModifier, + pSmp->common.mr.s.Method, + pSmp->common.mr.s.R, + pSmp->common.u.DR.HopCount + )); + _DBG_PRINT (_DBG_LVL_CALLBACK, ( + "SMI Processing for (cont):\n" + "\tHopPointer...:x%X\n" + "\tDrSLID.......:x%X\n" + "\tDrDLID.......:x%X\n" + "\tTID..........:x%"PRIx64"\n" + "\tSLID.........:x%X\n" + "\tDLID.........:x%X\n", + pSmp->common.u.DR.HopPointer, + pSmp->SmpExt.DirectedRoute.DrSLID, + pSmp->SmpExt.DirectedRoute.DrDLID, + pSmp->common.TransactionID, + pSmpBlock->Block.SLID, + pSmpBlock->Block.DLID + )); + + // Algorithm for SMP handling per IBTA 1.1 Section 13.5.3.3 + // Rather than be elegant, the flow charts are followed fairly + // directly, allowing for easier code review and support. + // However, there are cases where the flow charts are in error + // in which case the text in 14.2.2 takes precedence. + // Assumes LRH, BTH and GRH checks are done in the Verbs + // Provider Driver + + // Figure 157, SMP Check 1 + if (pSmp->common.BaseVersion != STL_BASE_VERSION + || pSmp->common.ClassVersion != STL_SM_CLASS_VERSION) + { + // can optionally send a GetResp(MAD_STATUS_UNSUPPORTED_VER) + // however since we don't understand the header we could + // not effectively respond to directed route + // so better to discard + _DBG_PRINT (_DBG_LVL_CALLBACK,( + "Unsupported Base or Class Version [packet discarded]\n")); + goto discard; + } + if( pSmp->common.MgmtClass != MCLASS_SM_DIRECTED_ROUTE + && pSmp->common.MgmtClass != MCLASS_SM_LID_ROUTED ) + { + // drop packet, unknown class + _DBG_PRINT (_DBG_LVL_CALLBACK,( + "Invalid Mgmt Class on SMI [packet discarded]\n")); + goto discard; + } + + if( pSmp->common.MgmtClass != MCLASS_SM_DIRECTED_ROUTE ) + { + // LID routed, next check is MKey which is done in Verbs Driver/SMA + _DBG_PRINT (_DBG_LVL_CALLBACK,("LID routed SMP\n")); + goto lidsmp; + } + + // not in spec, but a necessary check so indexing + // based on HopPointer below doesn't overflow + if (pSmp->common.u.DR.HopCount > + sizeof(pSmp->SmpExt.DirectedRoute.InitPath) + || pSmp->common.u.DR.HopPointer > + sizeof(pSmp->SmpExt.DirectedRoute.InitPath)) + { + _DBG_ERROR(( + "HopPointer(%d) or HopCount(%d) exceeds array bounds!\n" + "Check your SMP values [packet discarded]\n", + pSmp->common.u.DR.HopPointer, + pSmp->common.u.DR.HopCount + )); + + goto discard; + } + + // Figure 161, SMP Direct Route Check 1 + if ( 0 == pSmp->common.u.DR.s.D) + { + if ( ! FromWire && STL_LID_PERMISSIVE != pSmp->SmpExt.DirectedRoute.DrSLID) + { + // IBTA 1.1 sec 14.2.2.1 + // For packets originated by a local SM + // if Directed Route Part does not start from requestor node + // process as LID routed + goto sendsmp; + } + // 14.2.2.2, C14-8, C14-9 + if (0 != pSmp->common.u.DR.HopCount + && 0 == pSmp->common.u.DR.HopPointer) + { + // SMP is at beginning of directed route + // C14-9 clause 1) + ++(pSmp->common.u.DR.HopPointer); + pSmpBlock->Block.SLID = STL_LID_PERMISSIVE; + // flow chart Figure 161 disagrees with text, Text has priority + //pSmpBlock->Block.DLID = pSmp->SmpExt.DirectedRoute.DrDLID; + pSmpBlock->Block.DLID = STL_LID_PERMISSIVE; + pSmpBlock->Block.PortNumber = pSmp->SmpExt.DirectedRoute.InitPath[pSmp->common.u.DR.HopPointer]; + goto sendsmp; + } + if (0 != pSmp->common.u.DR.HopCount + && 1 <= pSmp->common.u.DR.HopPointer + && pSmp->common.u.DR.HopPointer < + pSmp->common.u.DR.HopCount + ) + { + // SMP is at intermediate hop in directed route portion of path + // C14-9 clause 2) + if (pCaObj->CaPublic.Capabilities & CA_IS_ENHANCED_SWITCH_PORT0) + { + // Switch code here + pSmp->SmpExt.DirectedRoute.RetPath[pSmp->common.u.DR.HopPointer] = pSmpBlock->Block.PortNumber; + ++pSmp->common.u.DR.HopPointer; + pSmpBlock->Block.SLID = STL_LID_PERMISSIVE; + pSmpBlock->Block.DLID = STL_LID_PERMISSIVE; + pSmpBlock->Block.PortNumber = pSmp->SmpExt.DirectedRoute.InitPath[pSmp->common.u.DR.HopPointer]; + goto sendsmp; + } + else + { + // we are not a switch so we drop + _DBG_PRINT (_DBG_LVL_CALLBACK,( + "Invalid DR [packet discarded per Check 1]\n")); + goto discard; + } + } + // Figure 162 SMP Direct Route Check 2 + if (pSmp->common.u.DR.HopCount + == pSmp->common.u.DR.HopPointer) + { + // SMP is at end of directed route portion of path + // C14-9 clause 3) + if (0 != pSmp->common.u.DR.HopCount) + { + pSmp->SmpExt.DirectedRoute.RetPath[pSmp->common.u.DR.HopPointer] = pSmpBlock->Block.PortNumber; + } + ++(pSmp->common.u.DR.HopPointer); + + if (pCaObj->CaPublic.Capabilities & CA_IS_ENHANCED_SWITCH_PORT0) + { + if (STL_LID_PERMISSIVE == pSmp->SmpExt.DirectedRoute.DrDLID) + { + pSmpBlock->Block.SLID = STL_LID_PERMISSIVE; + } + else + { + pSmpBlock->Block.SLID = pPortTbl[0].PortBlock->Public.Address.BaseLID | + pSmpBlock->Block.PathBits; + } + } + else + { + // not a switch + if ( STL_LID_PERMISSIVE != pSmp->SmpExt.DirectedRoute.DrDLID) + { + _DBG_PRINT (_DBG_LVL_CALLBACK,( + "Invalid DR [packet discarded per Check 2]\n")); + goto discard; + } + //pSmpBlock->Block.SLID = LID_PERMISSIVE; // optional in spec + } + + pSmpBlock->Block.DLID = pSmp->SmpExt.DirectedRoute.DrDLID; + // Text in clause 3 has this additional test which is + // redundant with test above due to DLID assignment above + // for a CA DLID will be PERMISSIVE if get here + if ( STL_LID_PERMISSIVE == pSmpBlock->Block.DLID ) + { + // per path above, HopPointer is now HopCount+1 +#ifdef IB_DEBUG + ASSERT(pSmp->common.u.DR.HopCount+1 == pSmp->common.u.DR.HopPointer); +#endif + goto localsmp; + } else { +#ifdef IB_DEBUG + if (!(pCaObj->CaPublic.Capabilities & CA_IS_ENHANCED_SWITCH_PORT0)) + { + // can't get here given sequence of tests above for a CA + ASSERT(0); + } +#endif + goto sendsmp; + } + } else if ( pSmp->common.u.DR.HopPointer == pSmp->common.u.DR.HopCount+1 ) + { + // SMP is a local request to SM or SMA + // C14-9 clause 4) + goto localsmp; + } else { + // HopPointer is in range HopCount+1 SmpExt.DirectedRoute.DrDLID)) + { + // IBTA 1.1 sec 14.2.2.3 + // For packets originated by a local SMA or SM + // if Directed Route Part does not start from responder node + // process as LID routed + goto sendsmp; + } + // Figure 164 SMP Direct Route Check 4 + if (0 != pSmp->common.u.DR.HopCount + && pSmp->common.u.DR.HopPointer == + pSmp->common.u.DR.HopCount+1 + ) + { + // SMP is at beginning of directed route + // C14-13 clause 1) + --(pSmp->common.u.DR.HopPointer); + pSmpBlock->Block.SLID = STL_LID_PERMISSIVE; + pSmpBlock->Block.DLID = pSmp->SmpExt.DirectedRoute.DrDLID; + pSmpBlock->Block.PortNumber = pSmp->SmpExt.DirectedRoute.RetPath[pSmp->common.u.DR.HopPointer]; + goto sendsmp; + } else if (0 != pSmp->common.u.DR.HopCount + && 2 <= pSmp->common.u.DR.HopPointer + && pSmp->common.u.DR.HopPointer <= + pSmp->common.u.DR.HopCount + ) + { + // SMP is at an intermediate hop of directed route + // C14-13 clause 2) + if (pCaObj->CaPublic.Capabilities & CA_IS_ENHANCED_SWITCH_PORT0) + { + --pSmp->common.u.DR.HopPointer; + pSmpBlock->Block.SLID = STL_LID_PERMISSIVE; + pSmpBlock->Block.DLID = STL_LID_PERMISSIVE; + pSmpBlock->Block.PortNumber = pSmp->SmpExt.DirectedRoute.RetPath[pSmp->common.u.DR.HopPointer]; + } + else + { + // we are not a switch so we drop + _DBG_PRINT (_DBG_LVL_CALLBACK,( + "Invalid DR [packet discarded per Check 4]\n")); + goto discard; + } + } + // Figure 165 SMP Direct Route Check 5 + if ( 1 == pSmp->common.u.DR.HopPointer) + { + // SMP is at end of directed route part of path + // C14-13 clause 3) + --(pSmp->common.u.DR.HopPointer); + if (pCaObj->CaPublic.Capabilities & CA_IS_ENHANCED_SWITCH_PORT0) + { + if (STL_LID_PERMISSIVE == pSmp->SmpExt.DirectedRoute.DrSLID) + { + pSmpBlock->Block.SLID = STL_LID_PERMISSIVE; + } + else + { + pSmpBlock->Block.SLID = pPortTbl[0].PortBlock->Public.Address.BaseLID | + pSmpBlock->Block.PathBits; + } + } + else + { + // we are not a switch + if ( STL_LID_PERMISSIVE != pSmp->SmpExt.DirectedRoute.DrSLID) + { + _DBG_PRINT (_DBG_LVL_CALLBACK,( + "Invalid DR [packet discarded per Check 5]\n")); + goto discard; + } + pSmpBlock->Block.SLID = STL_LID_PERMISSIVE; + } + + pSmpBlock->Block.DLID = pSmp->SmpExt.DirectedRoute.DrSLID; + // Text in clause 3 has this additional test which is + // redundant with test above due to DLID assignment above + // for a CA DLID will be PERMISSIVE if get here + if ( STL_LID_PERMISSIVE == pSmpBlock->Block.DLID ) + { + // per path above, HopPointer is now HopCount+1 +#ifdef IB_DEBUG + ASSERT(pSmp->common.u.DR.HopPointer == 0); +#endif + goto localsm; + } else { +#ifdef IB_DEBUG + if (!(pCaObj->CaPublic.Capabilities & CA_IS_ENHANCED_SWITCH_PORT0)) + { + // can't get here given sequence of tests above for a CA + ASSERT(0); + } +#endif + goto sendsmp; + } + // Figure 166, SMP - Direct Route Check 6 + } else if ( 0 == pSmp->common.u.DR.HopPointer) + { + // SMP is to a local SM + // C14-13 clause 4) + goto localsm; + } else { + // means HopCount+2 <= HopPointer <= 255 + _DBG_PRINT (_DBG_LVL_CALLBACK,( + "Invalid DR [packet discarded per Check 6]\n")); + goto discard; + } + } + +lidsmp: + _DBG_RETURN_LVL(_DBG_LVL_CALLBACK, SMI_LID_ROUTED); + return SMI_LID_ROUTED; + +localsmp: + _DBG_RETURN_LVL(_DBG_LVL_CALLBACK, SMI_TO_LOCAL); + return SMI_TO_LOCAL; + +localsm: + _DBG_RETURN_LVL(_DBG_LVL_CALLBACK, SMI_TO_LOCAL_SM); + return SMI_TO_LOCAL_SM; + +sendsmp: + // validate output port number + // With the switch's built in SMA, we leave validation to the switch firmware + // On the host we handle it here + if (!(pCaObj->CaPublic.Capabilities & CA_IS_ENHANCED_SWITCH_PORT0) && + (pSmpBlock->Block.PortNumber < 1 || pSmpBlock->Block.PortNumber > pCaObj->CaPublic.Ports)) + { + _DBG_PRINT (_DBG_LVL_CALLBACK,( + "Invalid DR Port Number [packet discarded]\n")); + goto discard; + } + + _DBG_RETURN_LVL(_DBG_LVL_CALLBACK, SMI_SEND); + return SMI_SEND; + +discard: + _DBG_RETURN_LVL(_DBG_LVL_CALLBACK, SMI_DISCARD); + return SMI_DISCARD; +} + +// Process an SMP which is routed to a local SMA or SM +// returns action to be performed with SmpBlock +// SMI_TO_LOCAL_SM - pass on to SM +// SMI_DISCARD - discard packet +// SMI_SEND - Smp should be sent on the wire +// SMI_TO_LOCAL - never returned by this function +// SMI_LID_ROUTED - LID routed SMP to SMA, send response back to source +SMI_ACTION +SmaProcessLocalSmp( + IN SMA_CA_OBJ_PRIVATE *pCaObj, + IN POOL_DATA_BLOCK *pSmpBlock + ) +{ + STL_SMP *pSmp = (STL_SMP*)pSmpBlock->Block.Smp; + + _DBG_ENTER_LVL(_DBG_LVL_CALLBACK, SmaProcessLocalSmp); + // M_Key checks are done in GetSetMad, so we defer + // IBTA 1.1 Figure 158 SMP M_Key Check until we give to SMA + + // Sma Processes local Smps for the following: + // 1) It a a request and not a response + // 2) It is not a Trap (Trap does not have R bit set) + // 3) It is not a SM_INFO + + // This is based on IBTA 1.1 Figure 159 SMP Check 2 + // with some minor changes to the flow + + if (( MMTHD_TRAP == pSmp->common.mr.s.Method) + || ( MCLASS_ATTRIB_ID_SM_INFO == pSmp->common.AttributeID ) + || ( 0 != pSmp->common.mr.s.R ) + ) + { + // Traps, SM_INFO and Responses are destined to SM + // not destined to SMA, just pass to SM if any + _DBG_PRINT (_DBG_LVL_CALLBACK,( + "Trap, SMInfo or Response to SM\n")); + _DBG_RETURN_LVL(_DBG_LVL_CALLBACK, SMI_TO_LOCAL_SM); + return SMI_TO_LOCAL_SM; + } + + if ((MMTHD_GET == pSmp->common.mr.s.Method) + || (MMTHD_SET == pSmp->common.mr.s.Method) + || (MMTHD_TRAP_REPRESS == pSmp->common.mr.s.Method)) + { + SMI_ACTION SmiAction; + + // destined to SMA + if ( FALSE == SmaProcessSmaSmpRcvd(pSmpBlock)) + { + return SMI_DISCARD; + } + SmiAction = SmaProcessSmiSmp(pCaObj, pSmpBlock, FALSE); + + if (SMI_TO_LOCAL == SmiAction) + { + return SMI_TO_LOCAL_SM; + } + _DBG_RETURN_LVL(_DBG_LVL_CALLBACK, SmiAction); + return SmiAction; + } else { + // unexpected method - discard + _DBG_PRINT (_DBG_LVL_CALLBACK,( + "Unexpected Method [packet discarded]\n")); + _DBG_RETURN_LVL(_DBG_LVL_CALLBACK, SMI_DISCARD); + return SMI_DISCARD; + } +} + +// Add to list of completed Sends to be reported to SM +void +SmaAddToSendQ( + IN POOL_DATA_BLOCK *SmpBlock + ) +{ + FSTATUS status; + SMP_LIST *pSmpList; + STL_SMP *pSmp; + + // + // first free AV handle + // + if( NULL != SmpBlock->AvHandle ) + { + status = PutAV( + (SMA_CA_OBJ_PRIVATE*)SmpBlock->Block.SmaCaContext, + SmpBlock->AvHandle); + SmpBlock->AvHandle = 0; + } + + pSmpList = (SMP_LIST*)SmpBlock->Base; + + if ( NULL != pSmpList ) + { + // + // Increment recvd counter + // + AtomicIncrementVoid( &pSmpList->SmpsOut ); + + + // set error indicator. + if ( FSUCCESS != SmpBlock->Block.Status ) + pSmpList->SmpsInError = 1; + + // + // Byte order for user + // + BSWAP_MAD_HEADER( (MAD*)SmpBlock->Block.Smp); + + pSmp = (STL_SMP*)SmpBlock->Block.Smp; + +#ifdef ICS_LOGGING + _DBG_PRINT (_DBG_LVL_CALLBACK,( + "Completed Send Info:\n" + "\tClass........:x%x\n" + "\tMethod.......:x%X\n" + "\tResponseBit..:x%X\n" + "\tAttribID.....:x%X\n" + "\tAttribModfier;x%X\n" + "\tTID..........:x%"PRIx64"\n", + pSmp->common.MgmtClass, + pSmp->common.mr.s.Method, + pSmp->common.mr.s.R, + pSmp->common.AttributeID, + pSmp->common.AttributeModifier, + pSmp->common.TransactionID + )); + _DBG_PRINT (_DBG_LVL_CALLBACK,( + "Completed Send Info:\n" + "\tClass........:x%x\n" + "\tMethod.......:x%X\n" + "\tResponseBit..:x%X\n" + "\tAttribID.....:x%X\n" + "\tHopCount.....:x%X\n" + "\tHopPointer...:x%X\n", + pSmp->common.MgmtClass, + pSmp->common.mr.s.Method, + pSmp->common.mr.s.R, + pSmp->common.AttributeID, + pSmp->common.u.DR.HopCount, + pSmp->common.u.DR.HopPointer + )); +#else + _DBG_PRINT (_DBG_LVL_CALLBACK,( + "Completed Send Info:\n" + "\tClass........:x%x\n" + "\tMethod.......:x%X\n" + "\tResponseBit..:x%X\n" + "\tAttribID.....:x%X\n" + "\tAttribModfier;x%X\n" + "\tTID..........:x%"PRIx64"\n" + "\tHopCount.....:x%X\n" + "\tHopPointer...:x%X\n", + pSmp->common.MgmtClass, + pSmp->common.mr.s.Method, + pSmp->common.mr.s.R, + pSmp->common.AttributeID, + pSmp->common.AttributeModifier, + pSmp->common.TransactionID, + pSmp->common.u.DR.HopCount, + pSmp->common.u.DR.HopPointer + )); +#endif + if ( pSmpList->SmpsIn == AtomicRead(&pSmpList->SmpsOut) ) + { + + // + // signal caller? + // + + if ( pSmpList->PostCallback ) // callback user + { + + // + // If caller does not want the status, add to bin + // + + (pSmpList->PostCallback)( + pSmpList->Context, + pSmpList->SmpBlock); + + // + // Free list + // + + MemoryDeallocate( pSmpList ); + } + else + { + + // + // Do we have errors? + // + + if ( 0 != pSmpList->SmpsInError ) + { + if ( g_Sma->SmUserTbl ) + { + // + // we have an error ; call user + // + + if ( g_Sma->SmUserTbl->DefRecv.EventCallback ) + { + (g_Sma->SmUserTbl->DefRecv.EventCallback)( + EVENT_SEND_ERROR, + pSmpList->SmpBlock, + pSmpList->Context); + + // + // Free list + // + + MemoryDeallocate( pSmpList ); + pSmpList = NULL; + } + } + } + + // + // No errors, pass buffer to Bin + // + + if ( NULL != pSmpList ) + { + status = iba_smi_pool_put( NULL, pSmpList->SmpBlock); + + // + // Free list + // + + MemoryDeallocate( pSmpList ); + } + } // callback + } // In == Out + } + else + { + // + // Silently return/recycle SMP to pool + // + // We land here if it was an internal send or only one send + // + status = iba_smi_pool_put( NULL, (SMP_BLOCK *)SmpBlock); + } +} + + +void +SmaAddToRecvQ( + IN POOL_DATA_BLOCK *SmpBlock + ) +{ + + SpinLockAcquire( &g_Sma->RQ.Lock ); + + // + // Handle common recv completion + // + + if ( NULL != g_Sma->RQ.s.RECV.Tail ) + { + SmpBlock->Block.Prev = g_Sma->RQ.s.RECV.Tail; + g_Sma->RQ.s.RECV.Tail->Block.Next = SmpBlock; + g_Sma->RQ.s.RECV.Tail = SmpBlock; + } + else + { + g_Sma->RQ.s.RECV.Head = g_Sma->RQ.s.RECV.Tail = SmpBlock; + } + + g_Sma->RQ.Count++; + + SpinLockRelease( &g_Sma->RQ.Lock ); +} + + +void +SmaProcessCQ( + IN SMA_CA_OBJ_PRIVATE *CaObj, + IN OUT RECV_BLOCK *RecvBlock +) +{ + boolean bRearmed = FALSE; + FSTATUS status; + POOL_DATA_BLOCK *pSmpBlock; + STL_SMP *pSmp; + IB_WORK_COMPLETION workCompletion; + SMA_CA_OBJ_PRIVATE *pCaObj; + SMA_PORT_TABLE_PRIV *pCaPortTbl; + uint8 PortNumber; + SMI_ACTION SmiAction = SMI_TO_LOCAL_SM; + + + _DBG_ENTER_LVL(_DBG_LVL_CALLBACK, SmaProcessCQ); + + // + // Processing completions on the CQ is done as follows: + // 1. Repeatedly Poll till all entries are done. + // 2. Rearm CQ and Poll again. If there are no more completions bail out. + // 3. If there are completions go back to step 1. + // + // We follow these steps to optimize on hardware events and race + // conditions. + // + + while (1) + { + // + // Loop and pull out all sends and receives + // + while ( FSUCCESS == (status = iba_poll_cq( CaObj->CqHandle, &workCompletion )) ) + { + // + // fill in common values + // + + pSmpBlock = (POOL_DATA_BLOCK *)(uintn)MASK_WORKREQID(workCompletion.WorkReqId); + + ASSERT (pSmpBlock); + + if ( !pSmpBlock ) + { + _DBG_ERROR (("Spurious CQ Event!!!\n" + "\tCompleted WQE.....:(%s)\n" + "\tSTATUS............:x%x\n" + "\tLength............:x%x\n", + _DBG_PTR(((WCTypeSend == workCompletion.WcType) ? "Send":"Recv")), + workCompletion.Status, + workCompletion.Length )); + + if ( WCTypeRecv == workCompletion.WcType ) + { + _DBG_ERROR (("\n" + "\tQP Number.........:x%x\n" + "\tSourceLID.........:x%x\n", + workCompletion.Req.RecvUD.SrcQPNumber, + workCompletion.Req.RecvUD.SrcLID )); + } + + _DBG_BREAK; + break; + } + + pSmpBlock->Block.Status = workCompletion.Status; + PortNumber = pSmpBlock->Block.PortNumber; + + + _DBG_PRINT (_DBG_LVL_CALLBACK, ( + "Completed %s WQE (%p):\n" + "\tSTATUS.......:x%X (%s)\n" + "\tPort Number..:%d\n", + _DBG_PTR((IS_SQ_WORKREQID(workCompletion.WorkReqId) ? "Send":"Recv")), + _DBG_PTR(pSmpBlock), + pSmpBlock->Block.Status, + _DBG_PTR(iba_fstatus_msg(pSmpBlock->Block.Status)), + pSmpBlock->Block.PortNumber )); + + // + // Is it Send? + // + if (IS_SQ_WORKREQID(workCompletion.WorkReqId)) + { + // + // Handle common send completion + // + SmaAddToSendQ(pSmpBlock); + + } + else + { + boolean QpDestroy; + + // + // Its a receive! + // + + pSmpBlock->Block.SmpByteCount = workCompletion.Length - sizeof(IB_GRH); + pSmpBlock->Block.RecvByteCount = workCompletion.Length; + + // + // First update receive Q depth + // + pCaObj = (SMA_CA_OBJ_PRIVATE *)pSmpBlock->Block.SmaCaContext; + pCaPortTbl = (SMA_PORT_TABLE_PRIV *)pCaObj->CaPublic.PortTbl; + if (CaObj->CaPublic.Capabilities & CA_IS_ENHANCED_SWITCH_PORT0) + { + if (pSmpBlock->Block.PortNumber != 1) + { +#ifdef ICS_LOGGING + _DBG_WARNING(( "RecvQ Error: Bad Port Number of %d, should be 1\n", + pSmpBlock->Block.PortNumber)); +#else + _DBG_WARN(( "RecvQ Error: Bad Port Number of %d, should be 1\n", + pSmpBlock->Block.PortNumber)); +#endif + pSmpBlock->Block.PortNumber = 1; + } + } + QpDestroy = ( QP_DESTROY == pCaPortTbl[pSmpBlock->Block.PortNumber-1].PortBlock->Qp0Control ); + + AtomicIncrementVoid(&pCaPortTbl[pSmpBlock->Block.PortNumber-1].PortBlock->Qp0RecvQTop); + + if (pSmpBlock->Block.Status != FSUCCESS) + { + // In destroy state we expect to get back CQEs with Flush Status + if ( ! QpDestroy ) + { +#ifdef ICS_LOGGING + _DBG_WARNING(( "RecvQ Error: CQE Status %d\n", + pSmpBlock->Block.Status)); +#else + _DBG_WARN(( "RecvQ Error: CQE Status %d\n", + pSmpBlock->Block.Status)); +#endif + } + + SmiAction = SMI_DISCARD; + goto DoAction; + } + + // + // Fill in receive details + // + + // + // Port Number and Q pair are filled-up during the iba_smi_post_recv() + // + pSmpBlock->Block.SLID = workCompletion.Req.RecvUD.SrcLID; + if (pSmpBlock->Block.SLID == LID_PERMISSIVE) + pSmpBlock->Block.SLID = STL_LID_PERMISSIVE; + pSmpBlock->Block.PathBits = workCompletion.Req.RecvUD.DestPathBits; + pSmpBlock->Block.ServiceLevel = workCompletion.Req.RecvUD.ServiceLevel; + // BUGBUG - need to get GRH header out of workCompletion + + // IB does not have Static rate in UD LRH + // so we can't be sure what rate of remote port is + // we use a constant value for SMI QPs + pSmpBlock->Block.StaticRate = IB_STATIC_RATE_SMI; + _DBG_PRINT (_DBG_LVL_CALLBACK, ( + "Inbound PathBits: %d\n", + pSmpBlock->Block.PathBits)); + + pSmp = (STL_SMP*)pSmpBlock->Block.Smp; + // + // Network Byte order block, make Host Byte Order + // + BSWAP_STL_SMP_HEADER(pSmp); + + + + _DBG_PRINT (_DBG_LVL_CALLBACK, ( + "Receive Info:\n" + "\tClass........:x%x\n" + "\tAttribID.....:x%X\n" + "\tAttribModfier:x%X\n" + "\tMethod.......:x%X\n" + "\tResponseBit..:x%X\n" + "\tHopCount.....:x%X\n", + pSmp->common.MgmtClass, + pSmp->common.AttributeID, + pSmp->common.AttributeModifier, + pSmp->common.mr.s.Method, + pSmp->common.mr.s.R, + pSmp->common.u.DR.HopCount + )); + _DBG_PRINT (_DBG_LVL_CALLBACK, ( + "Receive Info (cont):\n" + "\tHopPointer...:x%X\n" + "\tTID..........:x%"PRIx64"\n" + "\tSLID.........:x%X\n", + pSmp->common.u.DR.HopPointer, + pSmp->common.TransactionID, + pSmpBlock->Block.SLID + )); + + // Trap with SLID 0 is a special case + // Firmware has provided a trap to us on QP0 + // which we need to send out + // use SmaProcessSmaSmpRcvd to allow the driver to complete + // setup of the mad. If driver does not want to send it + // FNOT_DONE is returned + if ( MMTHD_TRAP == pSmp->common.mr.s.Method + && 0 == pSmpBlock->Block.SLID) + { + // Let Driver fixup mad if needed + if (FALSE == SmaProcessSmaSmpRcvd(pSmpBlock)) + { + SmiAction = SMI_DISCARD; + } else { + // output on wire, assume its LID routed and valid + // so no need to do SmaProcessSmiSmp DR algorithms + // if its to our own LID (local SM), it will reappear + // on our recv queue and get to SM that way + SmiAction = SMI_SEND; + } + } else { + // Validate incoming Smp per common Header + // and Directed Route Checks + // LID routed SMPs are destined to local SMA/SM + SmiAction = SmaProcessSmiSmp(pCaObj, pSmpBlock, TRUE); + + if (SMI_TO_LOCAL == SmiAction + || SMI_LID_ROUTED == SmiAction) + { + SmiAction = SmaProcessLocalSmp(pCaObj, pSmpBlock); + if (SMI_LID_ROUTED == SmiAction) + { + // LID routed responses sent back to requestor + SmiAction = SMI_SEND; + } + } + } + +DoAction: + if (SmiAction == SMI_SEND) + { + // output on wire, DR processing already completed + pSmpBlock->Base = NULL; + pSmpBlock->CQTrigger = FALSE;// Do not ask for interrupt. + // Flush SMP in next cycle + + if (FSUCCESS != SmaPostSmp( pCaObj, pSmpBlock )) + { + // unable to send + SmiAction = SMI_DISCARD; + } + } + + if ( SMI_TO_LOCAL_SM == SmiAction ) + { + // Add to recv Q for SM, else (no SM) return to pool + if (( NULL != g_Sma->SmUserTbl ) + && ( NULL != g_Sma->SmUserTbl->DefRecv.RcvCallback ) ) + { + _DBG_PRINT (_DBG_LVL_CALLBACK,( + "Adding SMP to RQ\n" )); + + if ( NULL == RecvBlock->Head ) + { + RecvBlock->Head = RecvBlock->Tail = pSmpBlock; + } + else + { + RecvBlock->Tail->Block.Next = pSmpBlock; + pSmpBlock->Block.Prev = RecvBlock->Tail; + RecvBlock->Tail = pSmpBlock; + } + + RecvBlock->Count++; // keep count for quick q insertion + } + else + { + SmiAction = SMI_DISCARD; + } + } + + if (SMI_DISCARD == SmiAction) + { + status = iba_smi_pool_put( NULL, (SMP_BLOCK *)pSmpBlock); + } + + // + // Post a SMP to recvQ to recv new msgs + // + // only post if not in process of destroying QP + if ( workCompletion.Status != WRStatusWRFlushed && ! QpDestroy ) + { + status = iba_smi_post_recv( NULL, pCaObj, PortNumber, 1); + if ( FSUCCESS != status ) + { + _DBG_ERROR (( "Could not post to RecvQ!!!\n" )); + } + } + } // recv + + SmiAction = SMI_TO_LOCAL_SM; + + } // iba_poll_cq while loop + + + if ( FNOT_DONE != status ) + { + _DBG_ERROR (("Got %s Status!!!\n", _DBG_PTR(FSTATUS_MSG(status)) )); + } + + // + // Rearm CQ for race conditions + // + if ( FALSE == bRearmed ) + { + status = iba_rearm_cq( CaObj->CqHandle, CQEventSelNextWC); + bRearmed = TRUE; + } + else + { + break; + } + } // while 1 for ReArm + + _DBG_LEAVE_LVL(_DBG_LVL_CALLBACK); + +} + +// When CaContext != NULL, we are in a thread context, as such we can preempt +// note that SmaProcessCQ can call GetSetMad in the VPD which might prempt +void +SmaCompletionCallback( + IN void *CaContext + ) +{ + SMA_CA_OBJ_PRIVATE *pCaObj; + RECV_BLOCK recvBlock; + + _DBG_ENTER_LVL(_DBG_LVL_CALLBACK, SmaCompletionCallback); + + pCaObj = (SMA_CA_OBJ_PRIVATE*)CaContext; + + // Init Recv context + recvBlock.Head = recvBlock.Tail = NULL; + recvBlock.Count = 0; + + //lookup request and fill in appropriate post set + + if ( NULL != pCaObj ) + SmaProcessCQ(pCaObj, &recvBlock); + + // We optimize on Lock usage by taking from RQ + // then looking up client definitions + + SpinLockAcquire( &g_Sma->RQ.Lock ); + + // Move contents of RQ to recvBlock + if ( 0 != g_Sma->RQ.Count ) + { + if (recvBlock.Count) + { + // add recvBlock contents at end of RQ + g_Sma->RQ.s.RECV.Tail->Block.Next = recvBlock.Head; + recvBlock.Head->Block.Prev = g_Sma->RQ.s.RECV.Tail; + g_Sma->RQ.s.RECV.Tail = recvBlock.Tail; + } + + // recvBlock gets all of combined RQ + recvBlock.Head = g_Sma->RQ.s.RECV.Head; + recvBlock.Tail = g_Sma->RQ.s.RECV.Tail; + + g_Sma->RQ.s.RECV.Head = g_Sma->RQ.s.RECV.Tail = NULL; + + recvBlock.Count += g_Sma->RQ.Count; + g_Sma->RQ.Count = 0; + } + + SpinLockRelease( &g_Sma->RQ.Lock ); + + // Look up if we have receives and client defined + // Else recycle buffers + // + + // Process recvs, Distribute through User Callbacks + + if ( 0 != recvBlock.Count ) + { + if ( ( NULL != g_Sma->SmUserTbl ) && \ + ( NULL != g_Sma->SmUserTbl->DefRecv.RcvCallback ) ) + { + _DBG_PRINT(_DBG_LVL_CALLBACK, + ("Received[x%x] for Callback[x%p] Context[x%p]\n", + recvBlock.Count, + _DBG_PTR(g_Sma->SmUserTbl->DefRecv.RcvCallback), + _DBG_PTR(g_Sma->SmUserTbl->DefRecv.Context) + )); + + // call user callback + ( g_Sma->SmUserTbl->DefRecv.RcvCallback )( + g_Sma->SmUserTbl->DefRecv.Context, + (SMP_BLOCK *)recvBlock.Head); + } else { + // recycle buffers + SmaReturnToBin(recvBlock.Head); + } + } + + _DBG_LEAVE_LVL(_DBG_LVL_CALLBACK); +} + + + + +// +// The common completion event handler provided to the verbs consumer +// + +void +SmaGsaCompletionCallback( + IN void *CaContext, + IN void *CqContext + ) +{ + SMA_CA_OBJ_PRIVATE *pCaObj = (SMA_CA_OBJ_PRIVATE*)CaContext; + + _DBG_ENTER_LVL(_DBG_LVL_CALLBACK, SmaGsaCompletionCallback); + + if ( (void *)QPTypeSMI == CqContext ) + { + EventThreadSignal(&pCaObj->SmaEventThread); + } else if ( (void *)QPTypeGSI == CqContext ) { + EventThreadSignal(&pCaObj->GsaEventThread); + } + _DBG_LEAVE_LVL(_DBG_LVL_CALLBACK); +} + + + +// +// The asynchronous error handler provided to the verbs consumer +// + +void +SmaAsyncEventCallback( + IN void *CaContext, + IN IB_EVENT_RECORD *EventRecord + ) +{ + SMA_CA_OBJ_PRIVATE *pCaObj; + SMA_PORT_TABLE_PRIV *pPortTbl; + + _DBG_ENTER_LVL(_DBG_LVL_CALLBACK, SmaAsyncEventCallback); + + + _DBG_PRINT(_DBG_LVL_CALLBACK,(\ + "Received Async Event:\n" + "\tUserCaContext..: x%p\n" + "\tContext........: x%p\n" + "\tEventType......: x%x\n" + "\tEventCode......: x%x\n", + _DBG_PTR(CaContext), + _DBG_PTR(EventRecord->Context), + EventRecord->EventType, + EventRecord->EventCode)); + + + pCaObj = (SMA_CA_OBJ_PRIVATE*)CaContext; + pPortTbl = (SMA_PORT_TABLE_PRIV *)pCaObj->CaPublic.PortTbl; + + switch ( EventRecord->EventType ) + { + default: + break; + + case AsyncEventQP: + { + _DBG_PRINT(_DBG_LVL_CALLBACK,("AsyncEventQP\n")); + break; + } + + case AsyncEventSendQ: + { + _DBG_PRINT(_DBG_LVL_CALLBACK,("AsyncEventSendQ\n")); + break; + } + + case AsyncEventRecvQ: + { + _DBG_PRINT(_DBG_LVL_CALLBACK,("AsyncEventRecvQ\n")); + break; + } + + case AsyncEventCQ: + { + _DBG_PRINT(_DBG_LVL_CALLBACK,("AsyncEventCQ\n")); + break; + } + + case AsyncEventCA: + { + _DBG_PRINT(_DBG_LVL_CALLBACK,("AsyncEventCA\n")); + break; + } + + case AsyncEventPort: + { + uint8 portNo; + IB_PORT_STATE portState, oldPortState; + SMA_PORT_BLOCK_PRIV *pPortBlock; + + _DBG_PRINT(_DBG_LVL_CALLBACK,("AsyncEventPort\n")); + + // + // context field = 1 based port number + // event type = port event + // event code = port state + // + + portNo = (uint8)((uintn)EventRecord->Context); + portState = (IB_PORT_STATE)EventRecord->EventCode; + + pPortBlock = &pPortTbl->PortBlock[portNo-1]; + oldPortState = pPortBlock->Public.State; + pPortBlock->Public.State = portState; + + /* ignore port state Async events while shutting down CA */ + if ( pPortBlock->Qp0Control != QP_DESTROY + && oldPortState != portState ) + { + if ( IB_PORT_DOWN == portState ) + { + IbtNotifyGroup( + pPortBlock->Public.GUID, + IB_NOTIFY_PORT_DOWN ); + } + + if ( IB_PORT_ACTIVE == portState ) + { + IbtNotifyGroup( + pPortBlock->Public.GUID, + IB_NOTIFY_LID_EVENT ); + } + } + + break; + } + + case AsyncEventPathMigrated: + { + _DBG_PRINT(_DBG_LVL_CALLBACK,("AsyncEventPathMigrated\n")); + break; + } + } + + _DBG_LEAVE_LVL(_DBG_LVL_CALLBACK); +} + diff --git a/IbAccess/Common/Ibt/Sma/smadebug.h b/IbAccess/Common/Ibt/Sma/smadebug.h new file mode 100644 index 0000000..f5e15ef --- /dev/null +++ b/IbAccess/Common/Ibt/Sma/smadebug.h @@ -0,0 +1,76 @@ +/* BEGIN_ICS_COPYRIGHT4 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT4 ****************************************/ +/* [ICS VERSION STRING: unknown] */ + +// Suppress duplicate loading of this file +#ifndef _IBA_SMA_DEBUG_H_ +#define _IBA_SMA_DEBUG_H_ + +/* +#define IB_DBG_BLK Sma_debug_params + +#ifndef Sma_debug_params + extern IB_DBG_PARAMS Sma_debug_params; +#endif +*/ + +#undef _ib_dbg_params +#define _ib_dbg_params Sma_debug_params +#ifndef Sma_debug_params + extern IB_DBG_PARAMS Sma_debug_params; +#endif + +#define SMA_MEM_TAG MAKE_MEM_TAG(S,m,a,M) + + +// +// Debug Levels +// +#define _DBG_LVL_MAIN 0x00000001 +#define _DBG_LVL_OBJ 0x00000002 +#define _DBG_LVL_MGMT 0x00000004 +#define _DBG_LVL_OSD 0x00000008 +#define _DBG_LVL_DEVICE 0x00000010 + +#define _DBG_LVL_POOL 0x00000020 +#define _DBG_LVL_STORE 0x00000040 + +#define _DBG_LVL_SEND 0x00000080 +#define _DBG_LVL_RECV 0x00000100 +#define _DBG_LVL_LOCAL 0x00000200 +#define _DBG_LVL_CALLBACK 0x00000400 + +#define _DBG_LVL_IBT_CALL 0x00001000 +#define _DBG_LVL_IBT_TSM 0x00002000 +#define _DBG_LVL_IBT_API 0x00002000 +#define _DBG_LVL_PKTDUMP 0x00004000 /* dump MADs */ +#define _DBG_LVL_VPDSMA 0x00008000 + + +#endif // _IBA_SMA_DEBUG_H_ diff --git a/IbAccess/Common/Ibt/Sma/smagsa.h b/IbAccess/Common/Ibt/Sma/smagsa.h new file mode 100644 index 0000000..f71b335 --- /dev/null +++ b/IbAccess/Common/Ibt/Sma/smagsa.h @@ -0,0 +1,278 @@ +/* BEGIN_ICS_COPYRIGHT4 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT4 ****************************************/ +/* [ICS VERSION STRING: unknown] */ + +#ifndef _IBA_IB_SMA_GSA_H_ +#define _IBA_IB_SMA_GSA_H_ (1) // suppress duplicate loading of this file + + + + +#include "datatypes.h" +#include "stl_types.h" +#include "stl_mad_priv.h" +#include "vpi.h" +#include "ieventthread.h" + +#ifdef __cplusplus +extern "C" { +#endif + +// +// These definitions will not be exposed to the SM + +typedef struct _CA_MEM_LIST { + //void *Next; // Pointer to next mem list + //void *Prev; // pointer to previous CA + + void *VirtualAddr; + size_t Length; + IB_HANDLE MrHandle; + IB_L_KEY LKey; + IB_R_KEY RKey; +} CA_MEM_LIST; + + +typedef struct _CA_MEM_BLOCK { + IB_HANDLE MrHandle; + IB_L_KEY LKey; +// IB_R_KEY RKey; +} CA_MEM_BLOCK; + +typedef struct _CA_MEM_TABLE { + size_t Total; + size_t Current; + CA_MEM_BLOCK MemBlock[1]; +} CA_MEM_TABLE; + + +// +// Global Memory map +typedef struct _GLOBAL_MEM_LIST { + void *Next; // Pointer to next mem list + void *Prev; // pointer to previous CA + + void *VirtualAddr; // Memory for Registered memory + uintn Length; + void *HdrAddr; // Memory for block headers to + // hold registered mem + + uint32 CaMemIndex; // the holy memindex for all + // Mem handles, Lkeys + IB_ACCESS_CONTROL AccessControl;// Access control flags +} GLOBAL_MEM_LIST; + + +typedef enum { + QP_NORMAL = 0, + QP_ERROR, + QP_DESTROY +} GLOBAL_QP_CONTROL; + +/* we use the low bit of the WorkReqId to indicate recv vs send */ +#define ASSERT_VALID_WORKREQID(id) ASSERT(! ((id) & 1)); +#define BUILD_RQ_WORKREQID(id) (id) +#define BUILD_SQ_WORKREQID(id) ((id) | (uintn)1) +#define IS_SQ_WORKREQID(id) ((id) & 1) +#define IS_RQ_WORKREQID(id) ( ! ((id) & 1)) +#define MASK_WORKREQID(id) ((id) & ~(uintn)1) + +typedef struct _SMA_PORT_BLOCK_PRIV { + SMA_PORT_BLOCK Public; + + // Sma + IB_HANDLE QpHandle; + uint32 Qp0SendQDepth; // Maximum outstanding WRs permitted + // on the SendQ of the QP + uint32 Qp0RecvQDepth; // Maximum outstanding WRs permitted + // on the RecvQ + ATOMIC_UINT Qp0SendQTop; // Must match SendQDepth when Empty + ATOMIC_UINT Qp0RecvQTop; // Must match RecvQDepth when empty + + SPIN_LOCK Qp0Lock; // lock on Qp + GLOBAL_QP_CONTROL Qp0Control; // GlobalControl on Qp states + + IB_HANDLE AvHandle; // Permissive Handle + + + // Gsa + IB_HANDLE Qp1Handle; + uint32 Qp1SendQDepth; // Maximum outstanding WRs permitted + // on the SendQ of the QP + uint32 Qp1RecvQDepth; // Maximum outstanding WRs permitted + // on the RecvQ + uint32 Qp1RecvQPosted; // present number of WRs posted on RecvQ + SPIN_LOCK QpLock; // lock on Qp + GLOBAL_QP_CONTROL Qp1Control; // GlobalControl on Qp states + + IB_LID SMLID; // SM LID +} SMA_PORT_BLOCK_PRIV; + + +// +// An array of ports based on number of ports +// + +typedef struct _SMA_PORT_TABLE_PRIV { + SMA_PORT_BLOCK_PRIV PortBlock[1]; +} SMA_PORT_TABLE_PRIV; + + + +typedef struct _SMA_CA_OBJ_PRIVATE { + struct _SMA_CA_OBJ_PRIVATE *Prev; + struct _SMA_CA_OBJ_PRIVATE *Next; + + SMA_CA_OBJECT CaPublic; + + // private + IB_HANDLE CaHandle; // Handle to this CA returned by the VCA + + // Sma + IB_HANDLE CqHandle; + uint32 CqSize; // CQ depth + IB_HANDLE PdHandle; + EVENT_THREAD SmaEventThread; + + + // Gsa + IB_HANDLE Qp1CqHandle; + uint32 Qp1CqSize; // CQ depth + EVENT_THREAD GsaEventThread; + + // common + uint64 WorkReqId; // SMA numbering to be returned + // on work completion + + CA_MEM_TABLE *CaMemTbl; + uint32 Partitions; // Maximum number of partitions + uint32 AddressVectors; // Maximum number of Address Vectors + // which may be created + + uint32 UseCount; // for objects on g_Sma->CaObj list, number + // of active references + +} SMA_CA_OBJ_PRIVATE; + + +// Forward declarations + +FSTATUS +RegisterMemGlobal( + IN void *VirtualAddress, + IN size_t Length, + IN IB_ACCESS_CONTROL AccessControl, + OUT uint32 *CaMemIndex + ); + +FSTATUS +DeregisterMemGlobal( + IN uint32 CaMemIndex + ); + + +GLOBAL_MEM_LIST * +CreateGlobalMemList( + void *VirtualAddr, + uintn Length, + void *HdrAddr, + boolean HoldingMutex + ); + +void +AcquireMemListMutex(void); + +void +ReleaseMemListMutex(void); + +FSTATUS +DeleteGlobalMemList( + GLOBAL_MEM_LIST *MemList + ); + +FSTATUS +GetAV( + IN SMA_CA_OBJ_PRIVATE *CaObj, + IN IB_ADDRESS_VECTOR *AvInfo, + OUT IB_HANDLE *AvHandle + ); + +FSTATUS +PutAV( + IN SMA_CA_OBJ_PRIVATE *CaObj, + IN IB_HANDLE AvHandle + ); + + +void +SetPortCapabilityMask ( + IN uint8 Class, + IN boolean Enabled + ); + +FSTATUS +GetMemInfoFromCaMemTable( + IN SMA_CA_OBJ_PRIVATE *CaObj, + IN uint32 CaMemIndex, + OUT CA_MEM_LIST *CaMemList + ); + +FSTATUS +SmaCreateSmaObj( + IN OUT SMA_OBJECT *SmaObj + ); + + +FSTATUS +DeleteFromCaMemTable( + IN SMA_CA_OBJ_PRIVATE *CaObj, + IN uint32 CaMemIndex + ); + + +void +GsaCompletionThreadCallback( + IN void *CaContext // SMA_CA_OBJ_PRIVATE * + ); + +void +GsaCompletionCallback( + IN void *CaContext, // SMA_CA_OBJ_PRIVATE * + IN IB_HANDLE CqHandle + ); + + +void +GsaUpdateCaList(void); + +#ifdef __cplusplus +}; +#endif + +#endif // _IBA_IB_SMA_GSA_H_ diff --git a/IbAccess/Common/Ibt/Sma/smamain.c b/IbAccess/Common/Ibt/Sma/smamain.c new file mode 100644 index 0000000..78e880f --- /dev/null +++ b/IbAccess/Common/Ibt/Sma/smamain.c @@ -0,0 +1,485 @@ +/* BEGIN_ICS_COPYRIGHT4 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT4 ****************************************/ + +#include "smamain.h" + +// Globals + + +// Debug params +#ifdef ICS_LOGGING +_IB_DBG_PARAM_BLOCK((_DBG_LVL_FATAL|_DBG_LVL_ERROR), _DBG_BREAK_ENABLE, SMA_MEM_TAG, "Sma", MOD_SMA, Sma); +#else +_IB_DBG_PARAM_BLOCK((_DBG_LVL_FATAL|_DBG_LVL_ERROR), _DBG_BREAK_ENABLE, SMA_MEM_TAG, "Sma"); +#endif + +// Global Info +SMA_GLOBAL_INFO *g_Sma; + +// Stored settings +SMA_STORED_SETTINGS g_Settings = DEFAULT_SMA_SETTINGS; + + +// +// SmaLoad +// +// This routine is called by the VCA Init when the driver is first loaded. +// This routine is to create and initialize driver data structures. +// +// INPUTS: +// +// ComponentInfo - Pointer to ComponentInfo that is OS specific +// +// OUTPUTS: +// +// None. +// +// RETURNS: +// +// FSUCCESS - Indicates a successful load. +// +// IRQL: +// +// This routine is called at IRQL_PASSIVE_LEVEL. +// + +FSTATUS +SMALoad( + IN IBT_COMPONENT_INFO *ComponentInfo + ) +{ + FSTATUS status = FSUCCESS; + + _DBG_ENTER_LVL(_DBG_LVL_MAIN, SmaLoad); + _DBG_INIT; + + _TRC_REGISTER(); + +#if !defined(VXWORKS) + _DBG_PRINT(_DBG_LVL_MAIN, + (" InfiniBand Subnet Management Agent. Built %s %s\n",\ + __DATE__, __TIME__ )); +#else + _DBG_PRINT(_DBG_LVL_MAIN, + (" InfiniBand Subnet Management Agent. Built %s %s\n",\ + _DBG_PTR(__DATE__), _DBG_PTR(__TIME__) )); +#endif + + // Establish dispatch entry points for the functions supported. + MemoryClear( ComponentInfo, sizeof(IBT_COMPONENT_INFO) ); + + ComponentInfo->AddDevice = SmaAddDevice; + ComponentInfo->RemoveDevice = SmaRemoveDevice; + ComponentInfo->Unload = SMAUnload; + + // Read Global settings for the driver which may be set in a + // OS specific way. + SmaInitGlobalSettings(); + + // Allocate space for Global data + g_Sma = (SMA_GLOBAL_INFO*)MemoryAllocate2AndClear(sizeof(SMA_GLOBAL_INFO), IBA_MEM_FLAG_PREMPTABLE, SMA_MEM_TAG); + if ( NULL == g_Sma ) + { + _DBG_ERROR(("MemAlloc failed for g_Sma!\n")); + goto done; + } + + // initialize global data + g_Sma->NumCa = 0; + g_Sma->CaObj = NULL; + g_Sma->WorkReqRecv = g_Sma->WorkReqSend = NULL; + + g_Sma->SmUserTbl = NULL; + g_Sma->NumUser = 0; + + // SpinLockInitState( &g_Sma->Lock ) + // SpinLockInit( &g_Sma->Lock ) + + // Init Storage area for MADs + g_Sma->Bin.NumBlocks = 0; + g_Sma->Bin.Head = g_Sma->Bin.Tail = NULL; + g_Sma->Bin.MemList = NULL; + g_Sma->Bin.CurrentIndex = 0; // set start mem index + + // Locks + SpinLockInitState( &g_Sma->CaListLock ); + SpinLockInit( &g_Sma->CaListLock ); + SpinLockInitState( &g_Sma->Bin.Lock ); + SpinLockInit( &g_Sma->Bin.Lock ); + MutexInitState( &g_Sma->Bin.Mutex ); + MutexInit( &g_Sma->Bin.Mutex ); + SpinLockInitState( &g_Sma->RQ.Lock ); + SpinLockInit( &g_Sma->RQ.Lock ); + + // Init Global Ibt user group for notifications + IbtInitNotifyGroup(NotifyIbtCallback); + + // Allocate memory for Global GRH since the SMA does not need a GRH. + // This memory will automatically get mapped to all CA registrations. + g_Sma->GlobalGrh = CreateGlobalMemList( 0, sizeof(IB_GRH), 0, FALSE ); + if ( NULL == g_Sma->GlobalGrh ) + { + status = FINSUFFICIENT_RESOURCES; + goto failmemlist; + } + + g_Sma->GlobalGrh->VirtualAddr = MemoryAllocate2AndClear(sizeof(IB_GRH), IBA_MEM_FLAG_PREMPTABLE, SMA_MEM_TAG); + if ( NULL == g_Sma->GlobalGrh->VirtualAddr ) + { + status = FINSUFFICIENT_RESOURCES; + goto failgrhvirt; + } + g_Sma->GlobalGrh->AccessControl.AsUINT16 = 0; + g_Sma->GlobalGrh->AccessControl.s.LocalWrite = 1; + g_Sma->GlobalGrh->CaMemIndex = 0; + + // Increment index for future allocations + g_Sma->Bin.CurrentIndex++; + +done: + _DBG_LEAVE_LVL(_DBG_LVL_MAIN); + return status; + +failgrhvirt: + MemoryDeallocate( g_Sma->GlobalGrh ); +failmemlist: + IbtDestroyNotifyGroup(); + SpinLockDestroy( &g_Sma->RQ.Lock ); + MutexDestroy( &g_Sma->Bin.Mutex ); + SpinLockDestroy( &g_Sma->Bin.Lock ); + SpinLockDestroy( &g_Sma->CaListLock ); + MemoryDeallocate( g_Sma ); + goto done; +} + + +// +// SmaUnload +// +// This routine should release resources allocated in the SmaLoad function. +// +// INPUTS: +// +// None. +// +// OUTPUTS: +// +// None. +// +// RETURNS: +// +// FSUCCESS - Successful unload of SMA. +// +// This routine is called at IRQL_PASSIVE_LEVEL. +// +void +SMAUnload(void) +{ + GLOBAL_MEM_LIST *pMemList; + + _DBG_ENTER_LVL(_DBG_LVL_MAIN, SmaUnload); + + // there should be no CAs at this point, all VPD must be unloaded + // before IbAccess + ASSERT(0 == g_Sma->NumCa); + ASSERT(NULL == g_Sma->CaObj); + + // Free up global memory + // + //Note: Global Grh gets freed automatically here + for (pMemList = g_Sma->Bin.MemList; NULL != pMemList; ) + { + GLOBAL_MEM_LIST *pMemListNext; + pMemListNext = (GLOBAL_MEM_LIST*)pMemList->Next; + MemoryDeallocate( pMemList->VirtualAddr ); // registered SMP emm + if (pMemList->HdrAddr ) + MemoryDeallocate( pMemList->HdrAddr ); // SmpBlock memory + MemoryDeallocate( pMemList ); + pMemList = pMemListNext; + } + + _TRC_UNREGISTER(); + + // Remove user list + if ( NULL != g_Sma->SmUserTbl ) + MemoryDeallocate( g_Sma->SmUserTbl ); + + IbtDestroyNotifyGroup(); + + // Locks + MutexDestroy( &g_Sma->Bin.Mutex ); + SpinLockDestroy( &g_Sma->Bin.Lock ); + SpinLockDestroy( &g_Sma->RQ.Lock ); + SpinLockDestroy( &g_Sma->CaListLock ); + + MemoryDeallocate( g_Sma ); + + _DBG_LEAVE_LVL(_DBG_LVL_MAIN); +} + + +// +// SmaAddDevice +// +// This routine is called by the VCA Startdevice loop for all driver libs. +// The CA device that just started will be identified by its GUID. +// +// INPUTS: +// +// CaGUID - GUID to the CA that was added and started. +// +// OUTPUTS: +// +// None +// +// RETURNS: +// +// FSTATUS. +// +// IRQL: +// +// This routine is called at IRQL_PASSIVE_LEVEL. +// + +FSTATUS +SmaAddDevice( + IN EUI64 CaGuid, + OUT void **Context + ) +{ + FSTATUS status = FSUCCESS; + SMA_CA_OBJ_PRIVATE *pCaObj=NULL; + uint32 i; + + _DBG_ENTER_LVL(_DBG_LVL_MAIN, SmaAddDevice); + + pCaObj = (SMA_CA_OBJ_PRIVATE*)MemoryAllocateAndClear(sizeof(SMA_CA_OBJ_PRIVATE), FALSE, SMA_MEM_TAG); + if ( NULL == pCaObj ) + { + _DBG_ERROR(("MemAlloc failed for pCaObj/WorkReq!\n")); + status = FINSUFFICIENT_MEMORY; + goto done; + } + + pCaObj->CaPublic.CaGuid = CaGuid; + pCaObj->CaPublic.SmaCaContext = pCaObj; + + EventThreadInitState(&pCaObj->SmaEventThread); + if (! EventThreadCreate(&pCaObj->SmaEventThread, "Smi", + THREAD_PRI_VERY_HIGH, SmaCompletionCallback, pCaObj)) + { + _DBG_ERROR(("Sma Event Thread Create FAILED\n")); + goto failsmathread; + } + + EventThreadInitState(&pCaObj->GsaEventThread); + if (! EventThreadCreate(&pCaObj->GsaEventThread, "Gsi", + THREAD_PRI_VERY_HIGH, GsaCompletionThreadCallback, pCaObj)) + { + _DBG_ERROR(("Gsa Event Thread Create FAILED\n")); + goto failgsathread; + } + + status = iba_open_ca( CaGuid, SmaGsaCompletionCallback, + SmaAsyncEventCallback, pCaObj/*Context*/, &pCaObj->CaHandle); + if ( FSUCCESS != status ) + { + _DBG_ERROR(("OpenCA() failed!\n")); + goto failopen; + } + status = SetCAInternal(pCaObj->CaHandle); + if ( FSUCCESS != status ) + { + _DBG_ERROR(("SetCAInternal() failed!\n")); + goto failinternal; + } + + // Reserve CQ/QP/PD... + status = SmaDeviceReserve( pCaObj ); + if ( FSUCCESS != status ) + { + goto failreserve; + } + // we hold the Mutex across Bind and addition to Ca list + // so that CreateDgrmPool cannot race and cause double + // registration of memory in new DgrmPool + AcquireMemListMutex(); + status = SmaBindGlobalMem( pCaObj ); + if (status != FSUCCESS) + { + ReleaseMemListMutex(); + // TBD need to undo SmaDeviceReserve + goto failreserve; + } + + // lock + + // update global info + SpinLockAcquire(&g_Sma->CaListLock); + g_Sma->NumCa++; + pCaObj->Next = g_Sma->CaObj; + pCaObj->Prev = NULL; + if ( NULL != g_Sma->CaObj ) + g_Sma->CaObj->Prev = pCaObj; + g_Sma->CaObj = pCaObj; + pCaObj->UseCount++; // hold reference so we can use object below + SpinLockRelease(&g_Sma->CaListLock); + + ReleaseMemListMutex(); + + // QPConfig + status = SmaDeviceConfig( pCaObj, QPTypeSMI ); + status = SmaDeviceConfig( pCaObj, QPTypeGSI ); + + // Create GSA data structures + GsaUpdateCaList(); + + // Preallocate Buffers based on per device. + // If we know the amount of buffers we need per device and go ahead + // and allocate them in advance, subnet sweeps will not allocate + // any buffers in the speed path + // + // NOTE: This call can fail if there are no system resources + SmaAllocToBin( g_Settings.PreAllocSMPsPerDevice, FALSE ); + + // post some descriptors on recv side if port is up or something... + for (i=0; iCaPublic.Ports; i++) + { + status = iba_smi_post_recv( NULL, pCaObj, (uint8)(i+1), + g_Settings.MinSMPsToPostPerPort ); + } + + // Set Port capabilities across all CA's + SetPortCapabilities(); + + // Rearm CQ to receive event notifications. + // The next Work Completion written to the CQ + // will generate an event + status = iba_rearm_cq( pCaObj->CqHandle, CQEventSelNextWC); + SpinLockAcquire(&g_Sma->CaListLock); + pCaObj->UseCount--; + SpinLockRelease(&g_Sma->CaListLock); + + // Bind + + // unlock + + // notify users through callbacks! + IbtNotifyGroup( CaGuid, IB_NOTIFY_CA_ADD ); + // TBD - failure above causes bad status return here, can confuse caller + // also does not cleanup QPs, CQ, PD, MRs, buffers + // SmaRemoveCaObj might solve, but not clear if safe to call it + // need some peers to the SmaDeviceReserve and SmaDeviceConfig routines + // to undo their effects + +done: + _DBG_LEAVE_LVL(_DBG_LVL_MAIN); + + return status; + +failreserve: +failinternal: + iba_close_ca( pCaObj->CaHandle ); +failopen: + EventThreadDestroy(&pCaObj->GsaEventThread); +failgsathread: + EventThreadDestroy(&pCaObj->SmaEventThread); +failsmathread: + MemoryDeallocate( pCaObj ); + goto done; +} + + +// +// SmaRemoveDevice +// +// This routine is called by the VCA Removedevice loop for all driver libs. +// The CA device that was removed will be identified by its GUID. +// +// INPUTS: +// +// CaGUID - GUID to the CA that was added and started. +// +// OUTPUTS: +// +// None. +// +// RETURNS: +// +// FSTATUS. +// +// IRQL: +// +// This routine is called at IRQL_PASSIVE_LEVEL. +// + +FSTATUS +SmaRemoveDevice( + IN EUI64 CaGuid, + IN void *Context + ) +{ + FSTATUS status = FSUCCESS; + SMA_CA_OBJ_PRIVATE *pCaObj; + + _DBG_ENTER_LVL(_DBG_LVL_MAIN, SmaRemoveDevice); + + // notify users through callbacks + // SM should stop access to all registered memory on this Ca + IbtNotifyGroup( CaGuid, IB_NOTIFY_CA_REMOVE ); + + // lock + + // find CaObj + SpinLockAcquire(&g_Sma->CaListLock); + for (pCaObj = g_Sma->CaObj; NULL != pCaObj; pCaObj = pCaObj->Next) + { + if ( CaGuid == pCaObj->CaPublic.CaGuid ) + break; + } + + if ( NULL != pCaObj ) + { + pCaObj->UseCount++; + SpinLockRelease(&g_Sma->CaListLock); + status = SmaRemoveCaObj( pCaObj ); // will release reference to pCaObj + } else { + SpinLockRelease(&g_Sma->CaListLock); + _DBG_ERROR(("Could not find CA device!\n")); + } + + // Rebuild CA list for GSA + GsaUpdateCaList(); + + // unlock + + _DBG_LEAVE_LVL(_DBG_LVL_MAIN); + + return status; +} diff --git a/IbAccess/Common/Ibt/Sma/smamain.h b/IbAccess/Common/Ibt/Sma/smamain.h new file mode 100644 index 0000000..b415351 --- /dev/null +++ b/IbAccess/Common/Ibt/Sma/smamain.h @@ -0,0 +1,472 @@ +/* BEGIN_ICS_COPYRIGHT4 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT4 ****************************************/ +/* [ICS VERSION STRING: unknown] */ + +#ifndef _IBA_IB_SMA_SMAMAIN_H_ +#define _IBA_IB_SMA_SMAMAIN_H_ (1) // suppress duplicate loading of this file + + + + +#include "datatypes.h" +#include "stl_types.h" +#include "stl_mad_priv.h" +#include "vpi.h" +#include "sma_osd.h" +#include "ib_debug_osd.h" +#include "vpi_export.h" +#include "ib_smi.h" +#include "ibt.h" +#include "smadebug.h" +#include "vca_export.h" +#include "statustext.h" +#include "ibyteswap.h" +#include "ispinlock.h" +#include "ithread.h" +#include "imutex.h" +#include "ievent.h" +#include "imath.h" +#include "smagsa.h" +#include "ibnotify.h" +//#include "vpdmad_export.h" + +#ifdef __cplusplus +extern "C" { +#endif +// +// These definitions will not be exposed to the SM +// + + +// +// Global settings. Initialized at load time +// + +typedef struct _SMA_STORED_SETTINGS { + uint32 MaxCqSize; // Maximum size a CQ will have + + uint32 SendQDepth; + uint32 RecvQDepth; + + uint32 MaxUsers; // Maximum no. of SMI users supported. + uint32 PreAllocSMPsPerDevice; // Minimum SMPs to Preallocate + // at each AddDevice + uint32 MinSMPsPerAllocate; // Minimum no. of SMPs that will be + // allocated at a time. + // This will be rounded up to a page size. + uint32 MinSMPsToPostPerPort;// number of SMPs to post per port + uint32 MaxSMPs; // Maximum SMPs that can be allocated + // on a system + uint32 MemTableSize; // Size of memory table used across CA's +} SMA_STORED_SETTINGS; + + +// +// These settings are reflected as defaults into SMA_STORED_SETTINGS +// defined globally +// +#ifdef VXWORKS +#define DEFAULT_SMA_SETTINGS { \ + (4*1024), /* MaxCqSize */ \ + 64, 64, /* SendQDepth, RecvQDepth */ \ + 25, /* MaxUsers */ \ + ((32*1024)/sizeof(MAD)*8), /* PreAllocSMPsPerDevice = 128 */ \ + (32*1024)/sizeof(MAD), /* MinSMPsPerAllocate */ \ + 63, /* MinSMPsToPostPerPort */ \ + ((32*1024)/sizeof(MAD)*32), /* MaxSMPs = 512 */ \ + (32*1024) }; /* MemTableSize */ +#else +#define DEFAULT_SMA_SETTINGS { \ + (4*1024)*5, /* MaxCqSize */ \ + 64*5, 64*5, /* SendQDepth, RecvQDepth */ \ + 25, /* MaxUsers */ \ + ((4*1024)/sizeof(MAD)*8*2), /* PreAllocSMPsPerDevice = 256 */ \ + (4*1024)/sizeof(MAD)*2, /* MinSMPsPerAllocate = 32 */ \ + 63, /* MinSMPsToPostPerPort */ \ + ((4*1024)/sizeof(MAD)*32)*5,/* MaxSMPs = 512*5 */ \ + (4*1024) }; /* MemTableSize */ +#endif + + + +// +// User object maintained. This private structure is used internally +// +typedef struct _SMA_OBJECT_PRIVATE { + + // exposed to user + struct _SMA_OBJECT SmaObj; + + struct _u { + size_t UserNo; + SM_RCV_CALLBACK *RcvCallback; + void *Context; + SM_EVENT_CALLBACK *EventCallback; + }u; + +} SMA_OBJECT_PRIVATE; + +// User table +typedef struct _SMA_USER_TABLE { + size_t Total; + size_t Current; + + struct { + void *Context; + SM_RCV_CALLBACK *RcvCallback; + SM_EVENT_CALLBACK *EventCallback; + } DefRecv; + + SMA_OBJECT_PRIVATE *SmUser; +} SMA_USER_TABLE; + + +// Pool Memory +typedef struct _POOL_LIST { + void *Prev; + void *Next; +} POOL_LIST; + +typedef struct _POOL_DATA_BLOCK { + SMP_BLOCK Block; + + void *Base; // Base to _SMP_LIST + size_t CaMemIndex; // Memroy index for SMP enclosed + IB_HANDLE AvHandle; // AV Handle for sends + boolean CQTrigger; // Trigger CQ +}POOL_DATA_BLOCK; + +typedef struct _POOL_BIN { + // Lock heirachy, get in following order if need both + // Mutex + // then Lock + SPIN_LOCK Lock; // protects all but MemList and TotalAllocated + uint32 NumBlocks; + POOL_DATA_BLOCK *Head; + POOL_DATA_BLOCK *Tail; + uint32 CurrentIndex; + MUTEX Mutex; // protects MemList and TotalAllocated + GLOBAL_MEM_LIST *MemList; + uint32 TotalAllocated; +} POOL_BIN; + +typedef struct _UD_TOTAL_BLOCK { + MAD Mad; +} UD_TOTAL_BLOCK; + +typedef struct _SMP_LIST { + void *Next; // pointers maintained exclusively by SMA + void *Prev; // pointers maintained exclusively by SMA + + SMA_OBJECT *SmObject; // User's info + uint32 SmpsIn; // Total no. of SMPs in list + ATOMIC_UINT SmpsOut; // Reserved. + uint32 SmpsInError; // flag for errors. uint32 used instead + // of boolean for pointer alignment + SMP_BLOCK *SmpBlock; // An array of SMP blocks + + SM_POST_CALLBACK *PostCallback; + void *Context; // Context provided by caller to track + // Post requests (not used by SMA) +} SMP_LIST; + + +typedef struct _SMP_POOL { + uint32 NumSmps; // Total no. of SMPs in list + STL_SMP *Smp[1]; // An array of SMPs +} SMP_POOL; + +typedef struct _RECV_BLOCK { + POOL_DATA_BLOCK *Head; + POOL_DATA_BLOCK *Tail; + uint32 Count; +} RECV_BLOCK; + +typedef struct _SMA_Q { + SPIN_LOCK Lock; // Lock used to access database + uint32 Count; // number of items on Q + + union { + struct { + // posted to send + SMP_LIST *Head; + SMP_LIST *Tail; + // sent + } SEND; + + // posted to recv + // received + struct { + POOL_DATA_BLOCK *Head; + POOL_DATA_BLOCK *Tail; + } RECV; + } s; + +} SMA_Q; + + + + +// +// Global Info +// +typedef struct { +// SPIN_LOCK Lock; // Lock used to access database + + // Memory tables + uint32 NumCa; // Total CA's known + SMA_CA_OBJ_PRIVATE *CaObj; + SPIN_LOCK CaListLock; // protects NumCa, CaObj list and CaObj->UseCount + + // capabilities published on all CA ports + uint32 IsConnectionManagementSupported:1; + uint32 IsSNMPTunnelingSupported:1; + uint32 IsDeviceManagementSupported:1; + uint32 IsVendorClassSupported:1; + + IB_WORK_REQ *WorkReqSend; + IB_WORK_REQ *WorkReqRecv; + + // Global GRH used for all receives + GLOBAL_MEM_LIST *GlobalGrh; + + + // Memory container + POOL_BIN Bin; // Common Memory block area storage + + // Software Qs for SMI + //SMA_Q SQ; // Send Queue + SMA_Q RQ; // Recv Queue + + // user info + size_t NumUser; // no. of users + SMA_USER_TABLE *SmUserTbl; // Table to Sm users +} SMA_GLOBAL_INFO; + +typedef enum { + SMI_DISCARD =0, // discard packet + SMI_SEND, // output on wire + SMI_TO_LOCAL_SM, // provide to local SM + SMI_TO_LOCAL, // provide to local SMA/SM + SMI_LID_ROUTED // LID routed SMP, destination depends on context +} SMI_ACTION; + +#ifndef g_Sma + extern SMA_GLOBAL_INFO *g_Sma; +#endif + +#ifndef g_Settings + extern SMA_STORED_SETTINGS g_Settings; +#endif + +/* additional global parameters for VpdMad Sma handling */ +extern uint32 SmaTrapDisable; // Disable Sending of Traps +extern uint32 SmaTrapLimit; // Limit on Traps sent before internally repress +extern uint32 SmaMKeyCheck; // should MKey checking be enabled +extern uint32 SmaCache; // should SMA Caching be enabled + + +// Forward declarations +FSTATUS +SMALoad( + IN IBT_COMPONENT_INFO *ComponentInfo + ); + +void +SMAUnload(void); + +FSTATUS +SmaAddDevice( + IN EUI64 CaGuid, + OUT void **Context + ); + +FSTATUS +SmaRemoveDevice( + IN EUI64 CaGuid, + IN void *Context + ); + +FSTATUS +SmaPostReturnSmp( + IN SMA_CA_OBJ_PRIVATE *CaObj, + IN POOL_DATA_BLOCK *SmpBlock + ); + +FSTATUS +SmaPostSmp( + IN SMA_CA_OBJ_PRIVATE *CaObj, + IN POOL_DATA_BLOCK *Req + ); + +boolean +SmaProcessSmaSmpRcvd( + IN POOL_DATA_BLOCK *SmpBlock + ); + +SMI_ACTION +SmaProcessSmiSmp( + IN SMA_CA_OBJ_PRIVATE *pCaObj, + IN POOL_DATA_BLOCK *pSmpBlock, + IN boolean FromWire + ); + +SMI_ACTION +SmaProcessLocalSmp( + IN SMA_CA_OBJ_PRIVATE *pCaObj, + IN POOL_DATA_BLOCK *pSmpBlock + ); + +void +SmaAddToSendQ( + IN POOL_DATA_BLOCK *SmpBlock + ); + +void +SmaAddToRecvQ( + IN POOL_DATA_BLOCK *SmpBlock + ); + +void +SmaProcessCQ( + IN SMA_CA_OBJ_PRIVATE *CaObj, + IN OUT RECV_BLOCK *RecvBlock + ); + +void +SmaCompletionCallback( + IN void *CaContext // a SMA_CA_OBJ_PRIVATE* + ); + +void +SmaGsaCompletionCallback( + IN void *CaContext, + IN void *CqContext + ); + +void +SmaAsyncEventCallback( + IN void *CaContext, + IN IB_EVENT_RECORD *EventRecord + ); + +void +SmaCreateCaMemIndex( + IN SMA_CA_OBJ_PRIVATE *CaObj, + OUT uint32 *CaMemIndex + ); + +void +SmaDeleteCaMemIndex( + IN uint32 CaMemIndex + ); + +FSTATUS +SmaAddToCaMemTable( + IN SMA_CA_OBJ_PRIVATE *CaObj, + IN CA_MEM_LIST *CaMemList, + IN uint32 CaMemIndex + ); + + +FSTATUS +SmaBindGlobalMem( + IN SMA_CA_OBJ_PRIVATE *CaObj + ); + +FSTATUS +SmaRemoveCaObj( + IN SMA_CA_OBJ_PRIVATE *pCaObj + ); + + +FSTATUS +SmaDeviceReserve( + IN SMA_CA_OBJ_PRIVATE *CaObj + ); + +FSTATUS +SmaConfigQp( + IN IB_HANDLE QpHandle, + IN IB_QP_STATE QpState, + IN IB_QP_TYPE QpType + ); + +FSTATUS +SmaDeviceConfig( + IN SMA_CA_OBJ_PRIVATE *CaObj, + IN IB_QP_TYPE QpType + ); + +void +SetPortCapabilities ( void ); + + +// tSM +FSTATUS TSmThreadStart( void ); + +void TSmThreadStop( void ); + +FSTATUS +SmaAllocToBin( + IN uint32 NumMads, + IN boolean HoldingMutex + ); + +FSTATUS +SmaReturnToBin( + IN POOL_DATA_BLOCK *SmpBlockList + ); + +void +SmaInitGlobalSettings(void); + + +FSTATUS +SmaGrabFromBin( + IN OUT uint32 *NumMad, + IN OUT SMP_BLOCK *MadPool + ); + +FSTATUS +SmaRemoveFromBin(void); + + +void +NotifyIbtCallback( + IN void *Context + ); + + + +#ifdef __cplusplus +} +#endif + +#endif // _IBA_IB_SMA_SMAMAIN_H_ diff --git a/IbAccess/Common/Ibt/Sma/smamgmt.c b/IbAccess/Common/Ibt/Sma/smamgmt.c new file mode 100644 index 0000000..4ad55ed --- /dev/null +++ b/IbAccess/Common/Ibt/Sma/smamgmt.c @@ -0,0 +1,307 @@ +/* BEGIN_ICS_COPYRIGHT4 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT4 ****************************************/ + +#include "smamain.h" + + +extern IB_DBG_PARAMS Gsa_debug_params; + + +// +// SmaRemoveCaObj +// +// This routine frees resources allocated to a CaObject. +// +// INPUTS: +// +// Pointer to CaObj +// +// OUTPUTS: +// +// None. +// +// RETURNS: +// +// FSUCCESS - Successful freeing of Ca resources. +// +// NOTES: +// +// This routine can be called from SmaRemoveDevice() or SmaUnload() +// called with pCaObj UseCount held +// +FSTATUS +SmaRemoveCaObj( + IN SMA_CA_OBJ_PRIVATE *pCaObj + ) +{ + FSTATUS status = FSUCCESS; + CA_MEM_TABLE *caMemTbl; + SMA_PORT_TABLE_PRIV *pPortTbl; + uint32 i; + IB_QP_ATTRIBUTES_MODIFY qpModAttributes; + + _DBG_ENTER_LVL(_DBG_LVL_MGMT, SmaRemoveCaObj); + + pPortTbl = (SMA_PORT_TABLE_PRIV *)pCaObj->CaPublic.PortTbl; + + // Before destorying the Qps first flush them + for ( i=0; iCaPublic.Ports; i++ ) + { + // Before destroying the QP, set it to error state + // This should flush all pending completions in error + // Also, set internal state to destroy so that we + // do not post recv buffers + pPortTbl->PortBlock[i].Qp0Control = QP_DESTROY; + + qpModAttributes.RequestState = QPStateError; + qpModAttributes.Attrs = 0; + status =iba_modify_qp(pPortTbl->PortBlock[i].QpHandle,&qpModAttributes,NULL); + if ( FSUCCESS != status ) + { + _DBG_ERROR(( + "Could not ModifyQp (Qp0 on Port %d) to error state!!!\n", + i+1)); + } + + pPortTbl->PortBlock[i].Qp1Control = QP_DESTROY; + + qpModAttributes.RequestState = QPStateError; + qpModAttributes.Attrs = 0; + status=iba_modify_qp(pPortTbl->PortBlock[i].Qp1Handle,&qpModAttributes,NULL); + + if ( FSUCCESS != status ) + { + _DBG_ERROR(( + "Could not ModifyQp (Qp1 on Port %d) to error state!!!\n", + i+1)); + } + } + + // loop a few times to make sure all CQEs have come back + for (i=0; i<10; ++i) + { + // Wait for any interrupts to be processed + ThreadSuspend( 100 ); + + // Forcebly poll for any pending completions + SmaCompletionCallback( pCaObj ); + GsaCompletionCallback( pCaObj, pCaObj->Qp1CqHandle ); + } + + EventThreadStop(&pCaObj->GsaEventThread); + EventThreadStop(&pCaObj->SmaEventThread); + + // update global info + SpinLockAcquire(&g_Sma->CaListLock); + if ( NULL != pCaObj->Prev ) + pCaObj->Prev->Next = pCaObj->Next; + if ( NULL != pCaObj->Next ) + pCaObj->Next->Prev = pCaObj->Prev; + if ( g_Sma->CaObj == pCaObj ) + g_Sma->CaObj = g_Sma->CaObj->Next; + g_Sma->NumCa--; + pCaObj->UseCount--; + SpinLockRelease(&g_Sma->CaListLock); + + // wait for outstanding Uses to be done + // pCaObj->Next is still valid + while (1) + { + SpinLockAcquire(&g_Sma->CaListLock); + if (0 == pCaObj->UseCount) + break; + SpinLockRelease(&g_Sma->CaListLock); + ThreadSuspend(10); + } + SpinLockRelease(&g_Sma->CaListLock); + + // deregister all memory registered for this CA + caMemTbl = pCaObj->CaMemTbl; + if ( NULL != caMemTbl ) + { + for ( i=0; i < caMemTbl->Total; ++i ) + { + if ( NULL != caMemTbl->MemBlock[i].MrHandle ) + { + status = iba_deregister_mr( caMemTbl->MemBlock[i].MrHandle ); + + if ( FSUCCESS != status ) + { + _DBG_ERROR(("Could not Deregister Memory!\n")); + } + } + } // i loop + } + + // remove mem list + if ( pCaObj->CaMemTbl ) + MemoryDeallocate( pCaObj->CaMemTbl ); + + // destroy Qps + for ( i=0; iCaPublic.Ports; i++ ) + { + + iba_destroy_qp( pPortTbl->PortBlock[i].QpHandle ); // QP0 + iba_destroy_qp( pPortTbl->PortBlock[i].Qp1Handle ); // QP1 +// DestroyAV( pPortTbl->PortBlock[i].AvHandle ); // Permissive LID + + // Spinlock for Qp1 + SpinLockDestroy(&pPortTbl->PortBlock[i].QpLock); + SpinLockDestroy(&pPortTbl->PortBlock[i].Qp0Lock); + } + + // destroy Cqs + iba_destroy_cq( pCaObj->CqHandle ); + iba_destroy_cq( pCaObj->Qp1CqHandle ); + + //BUGBUG: + // destroy AVs if in Table Cache + + // destroy PDs + if ( pCaObj->PdHandle ) + iba_free_pd(pCaObj->PdHandle ); + + // close Ca + iba_close_ca( pCaObj->CaHandle ); + + EventThreadDestroy(&pCaObj->GsaEventThread); + EventThreadDestroy(&pCaObj->SmaEventThread); + + // remove sublists likePort info and tag other requirements + + // destroy Port tables + MemoryDeallocate( pCaObj->CaPublic.PortTbl ); + + + // de-allocate memory for CA_OBJ + MemoryDeallocate( pCaObj ); + + _DBG_LEAVE_LVL(_DBG_LVL_MGMT); + + return status; +} + + + +// +// SmaCreateSmaObj +// +// This routine creates a new instance for a new user on SmaOpen() +// +// INPUTS: +// +// Pointer to User Sma Object pointer +// +// OUTPUTS: +// +// Allocated SmaObj for user +// +// +// RETURNS: +// +// FSUCCESS - Successful freeing of Ca resources. +// +// NOTES: +// +// This routine can be called from SmaOpen() and SmaUpdateInfo() +// +FSTATUS +SmaCreateSmaObj( + IN OUT SMA_OBJECT *SmaObj + ) +{ + FSTATUS status = FSUCCESS; + SMA_CA_OBJ_PRIVATE *pCaObj; + size_t i, j, sizeSmObj=0; + SMA_OBJECT *pSmaObj; + SMA_CA_TABLE *pCaTblUsr; + SMA_PORT_TABLE *pCaPortTbl; + SMA_PORT_TABLE_PRIV *pPortTbl; + + _DBG_ENTER_LVL(_DBG_LVL_MGMT, SmaCreateSmaObj); + + // walk caObj list and calculate memory required + SpinLockAcquire(&g_Sma->CaListLock); + if (g_Sma->NumCa) + { + for (pCaObj = g_Sma->CaObj; pCaObj; pCaObj = pCaObj->Next) + { + sizeSmObj += ( sizeof( SMA_CA_OBJECT ) + + pCaObj->CaPublic.Ports * sizeof( SMA_PORT_BLOCK )); + } + + // Map this to our internal type + pSmaObj = SmaObj; + + // allocate memory + pSmaObj->CaTbl = (SMA_CA_TABLE*)MemoryAllocateAndClear(sizeSmObj, FALSE, SMA_MEM_TAG); + if ( NULL != pSmaObj->CaTbl ) + { + // create pointers + pCaTblUsr = pSmaObj->CaTbl; + pCaPortTbl = (SMA_PORT_TABLE *) &pSmaObj->CaTbl[g_Sma->NumCa]; + + // Fill in info + + // SmaObj + pSmaObj->NumCa = g_Sma->NumCa; + + // now the Ca's + for (i=0, pCaObj = g_Sma->CaObj; pCaObj; i++, pCaObj = pCaObj->Next) + { + // Get private port table + pPortTbl = (SMA_PORT_TABLE_PRIV *)pCaObj->CaPublic.PortTbl; + + // CaInfo + *pCaTblUsr[i].CaObj = pCaObj->CaPublic; + + // Port info + pCaTblUsr[i].CaObj->PortTbl = pCaPortTbl; + for ( j=0; jCaPublic.Ports; j++ ) + { + MemoryCopy( + &pCaTblUsr[i].CaObj->PortTbl[j], + &pPortTbl[j].PortBlock->Public, + sizeof( pPortTbl[j].PortBlock->Public )); + } + + // advance pointers + pCaPortTbl = &pCaPortTbl[pCaObj->CaPublic.Ports]; + } + } else { + _DBG_ERROR(("Could not Allocate Memory for SmaObj!\n")); + status = FERROR; + } + } // NumCa + SpinLockRelease(&g_Sma->CaListLock); + + + _DBG_LEAVE_LVL(_DBG_LVL_MGMT); + return status; +} diff --git a/IbAccess/Common/Ibt/Sma/smaobj.c b/IbAccess/Common/Ibt/Sma/smaobj.c new file mode 100644 index 0000000..4c1c23f --- /dev/null +++ b/IbAccess/Common/Ibt/Sma/smaobj.c @@ -0,0 +1,335 @@ +/* BEGIN_ICS_COPYRIGHT4 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT4 ****************************************/ + +#include "smamain.h" +#include "imath.h" + + +// +// Forward declarations +// + + + + +// +// SmaOpen +// +// Returns a pointer to an Object that that refereces in the SMA structures. +// The structures should be referenced as read-only. +// The SM can use the handles of CA/QP/CQ's for its own usage if required. +// No tracking of resources will be done if Handles are used. +// +// +// INPUTS: +// +// RcvCallback -Callback to be invoked if SMP's are received. +// +// EventCallback -Event callback for all events. +// +// Context -Global context +// +// +// OUTPUTS: +// +// SmObject -A pointer to an Object that references into the SMA +// structures. +// +// +// RETURNS: +// +// +// +FSTATUS +iba_smi_open( + IN SM_RCV_CALLBACK *RcvCallback, + IN SM_EVENT_CALLBACK *EventCallback, + IN void *Context, + OUT SMA_OBJECT **SmObject + ) +{ + FSTATUS status = FSUCCESS; + SMA_OBJECT_PRIVATE *pSmaObj; + + + _DBG_ENTER_LVL(_DBG_LVL_OBJ, iba_smi_open); + + // + // Param check + // + + + // + // lock + // + + if ( NULL == g_Sma->SmUserTbl ) + { + // This value should come from registry + g_Sma->SmUserTbl = (SMA_USER_TABLE*)MemoryAllocateAndClear( + sizeof( *(g_Sma->SmUserTbl) ) + + sizeof(*(g_Sma->SmUserTbl->SmUser))* g_Settings.MaxUsers + + sizeof(uint64), + FALSE, SMA_MEM_TAG); + + if ( NULL != g_Sma->SmUserTbl ) + { + //g_Sma->SmUserTbl->Current = 0; + g_Sma->SmUserTbl->Total = g_Settings.MaxUsers; + g_Sma->SmUserTbl->SmUser = (SMA_OBJECT_PRIVATE *) \ + ((uint8*)(g_Sma->SmUserTbl) + + ROUNDUPP2(sizeof( SMA_USER_TABLE ), sizeof(uint64))); + } + } + + if ( NULL != g_Sma->SmUserTbl ) + { + if (g_Sma->SmUserTbl->Current == g_Sma->SmUserTbl->Total ) + { + _DBG_ERROR(("Maximum users reached!\n")); + status = FERROR; + } + else + { + pSmaObj = &g_Sma->SmUserTbl->SmUser[g_Sma->SmUserTbl->Current]; + pSmaObj->u.UserNo = g_Sma->SmUserTbl->Current; + g_Sma->SmUserTbl->Current++; + + status = SmaCreateSmaObj( &pSmaObj->SmaObj ); + if ( FSUCCESS == status ) + { + + // + // Update callback info + // + + pSmaObj->u.RcvCallback = RcvCallback; +// pSmaObj->u.PostCallback = PostCallback; + pSmaObj->u.EventCallback = EventCallback; + pSmaObj->u.Context = Context; + + if ( RcvCallback ) + { + + // + // PS: There can only be one receive callback + // Set default values fr callback + // + + g_Sma->SmUserTbl->DefRecv.RcvCallback = RcvCallback; + g_Sma->SmUserTbl->DefRecv.Context = Context; + g_Sma->SmUserTbl->DefRecv.EventCallback = EventCallback; + } + + *SmObject = &pSmaObj->SmaObj; + g_Sma->NumUser++; // increment no. of user count + } + } + } + else + { + _DBG_ERROR(("MemAlloc failed for iba_smi_open!\n")); + } + + + // + // unlock + // + + + _DBG_LEAVE_LVL(_DBG_LVL_OBJ); + + return status; +} + + + +// +// SmaClose +// +// Dereferences usage of the SMA used previously by iba_smi_open(). +// No tracking of resources will be done if Handles are used. +// +// +// INPUTS: +// +// SmObject -Object returned in the Open call. +// +// +// OUTPUTS: +// +// +// RETURNS: +// +// +// +FSTATUS +iba_smi_close( + IN SMA_OBJECT *SmObject + ) +{ + FSTATUS status = FSUCCESS; + SMA_OBJECT_PRIVATE *pSmaObj; + + + _DBG_ENTER_LVL(_DBG_LVL_OBJ, iba_smi_close); + + + // + // Param check + // + + + // + // lock + // + + if ( NULL != g_Sma->SmUserTbl ) + { + pSmaObj = (SMA_OBJECT_PRIVATE *)SmObject; + + pSmaObj->u.UserNo = 0; + g_Sma->SmUserTbl->Current--; + + + // Update callback info + if ( pSmaObj->u.RcvCallback == \ + g_Sma->SmUserTbl->DefRecv.RcvCallback ) + { + // Deregister default callbacks + g_Sma->SmUserTbl->DefRecv.RcvCallback = NULL; + g_Sma->SmUserTbl->DefRecv.Context = NULL; + g_Sma->SmUserTbl->DefRecv.EventCallback = NULL; + } + + g_Sma->NumUser--; // Decrement no. of user count + + + // free user CA/port table + if ( pSmaObj->SmaObj.CaTbl ) + MemoryDeallocate( pSmaObj->SmaObj.CaTbl ); + } else { + _DBG_ERROR(("Could not locate userInfo!\n")); + } + + // unlock + + _DBG_LEAVE_LVL(_DBG_LVL_OBJ); + + return status; +} + + + +// +// SmaUpdateInfo +// +// The caller uses this function to update the SMA_OBJECT to reflect any +// changes to Channel adapters and their states. The call is done +// immedeatly after an state change event is received by the caller. +// +// +// INPUTS: +// +// SmObject -Object returned in the Open call. +// +// +// OUTPUTS: +// +// SmObject -Updated Object information. +// +// Event -Update information based on this event. +// +// RETURNS: +// +// +// +FSTATUS +iba_smi_update_info( + IN OUT SMA_OBJECT *SmObject + //IN SMA_EVENT_TYPE Event + ) +{ + FSTATUS status = FSUCCESS; + SMA_OBJECT *pSmaObj; + + + _DBG_ENTER_LVL(_DBG_LVL_OBJ, iba_smi_update_info); + + + // + // Param check + // + + + // + // lock + // + + + // + // BUGBUG: + // Lookup type of event + // + + // + // If event is Add device/ Remove device + // + + pSmaObj = SmObject; + + + // + // first free old table + // + + if( pSmaObj->CaTbl ) { + MemoryDeallocate( pSmaObj->CaTbl ); + pSmaObj->CaTbl = NULL; + pSmaObj->NumCa = 0; + } + + + // + // create new table + // + + status = SmaCreateSmaObj( pSmaObj ); + + + // + // unlock + // + + + _DBG_LEAVE_LVL(_DBG_LVL_OBJ); + + return status; +} + diff --git a/IbAccess/Common/Ibt/Sma/smapool.c b/IbAccess/Common/Ibt/Sma/smapool.c new file mode 100644 index 0000000..cb1553f --- /dev/null +++ b/IbAccess/Common/Ibt/Sma/smapool.c @@ -0,0 +1,300 @@ +/* BEGIN_ICS_COPYRIGHT4 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT4 ****************************************/ + +#include "smamain.h" + + +// +// Forward declarations +// + + + + +// +// Common buffer calls for Smp's on requested Hca +// +// +// +// Usage: +// +// The SMA allocates all SMP buffers for sends and receives. Since these +// buffers are of a constant size (MAD size), allocation size is known at +// all times and hence not specified in calls. +// +// The following rules apply for all SMP buffer usage: +// * Cut down the requirements on system memory is reduced by half as +// there is no copy administered between Sends and Receives. The same +// SMP buffers are passed to/from the hardware. All SMP buffers come +// from registered memory. +// * The buffers are not tied down to a particular Channel Adapter. Hence +// they can be sent to or received from any CA. The memory registration +// is taken care of by the SMA. +// * The buffers are not required to be maintained by the Subnet Manager. +// All tracking is done by the SMA. +// * Once a buffer is submitted by a SmaPost or SmaSetLocal call to the +// SMA, it will be not returned back. +// * There is no rule maintained as to the order of these buffers. The +// Subnet Manager cannot except the same buffers to be passed in +// by the SMA. +// * All buffers allocated and returned through any send/receive calls +// hold the same size and is equal to the size of a MAD structure of +// 256 bytes. +// * A buffer once allocated from pool can be rturned back to pool by +// SmaPost() and SmaReturnToPool(). +// +// + + +// +// SmaGrabFromPool +// +// The caller +// +// +// INPUTS: +// +// SmObject -Object returned in the Open call. +// +// NumSmps -Number of blocks of memory that the caller wants in +// SMP sizes. +// +// SmpPool -An array to hold the SMPs requested. +// +// +// OUTPUTS: +// +// SmpPool -Array filled with SMPs with total number allocated. +// +// +// RETURNS: +// +// +// +FSTATUS +iba_smi_pool_get( + IN SMA_OBJECT *SmObject, + IN OUT uint32 *NumSmps, + OUT SMP_BLOCK **SmpBlockList + ) +{ + FSTATUS status = FSUCCESS; + POOL_DATA_BLOCK *pMem, *pMemNext; + uint32 i; + + _DBG_ENTER_LVL(_DBG_LVL_POOL, iba_smi_pool_get); + + // + // Do param checks + // + if ( !*NumSmps ) + { + _DBG_LEAVE_LVL(_DBG_LVL_POOL); + return FERROR; + //*NumSmps = 1; // set minimal 1 to make SMPT work!! + } + + // + // look up bin + // + + // + // lock + // + + SpinLockAcquire( &g_Sma->Bin.Lock ); + + + // + // If we cannot satisfy request, try allocating from system + // + + + if ( g_Sma->Bin.NumBlocks < *NumSmps ) + { + // this is slightly complex however it avoids the need to get a + // semaphore for non-growth allocates + // the heirarchy requires we have the semaphore before the Lock + // and we need the lock to test NumBlocks + // we loop in case between Alloc and Lock someone takes all + // our new buffers (unlikely). Ultimately if the Alloc fails + // we must bail out + SpinLockRelease( &g_Sma->Bin.Lock ); + MutexAcquire( &g_Sma->Bin.Mutex ); + SpinLockAcquire( &g_Sma->Bin.Lock ); + while ( FSUCCESS == status && g_Sma->Bin.NumBlocks < *NumSmps ) + { + SpinLockRelease( &g_Sma->Bin.Lock ); + status = SmaAllocToBin( *NumSmps, TRUE ); + SpinLockAcquire( &g_Sma->Bin.Lock ); + } + MutexRelease( &g_Sma->Bin.Mutex ); + } + + // now have lock, don't have sema + + if ( FSUCCESS == status ) + { + // + // else return from bin + // + + pMem = g_Sma->Bin.Head; + + + // + // more than NumSmps in bin + // + + if ( g_Sma->Bin.NumBlocks > *NumSmps ) + { + pMemNext = pMem; + + for ( i=0; i< *NumSmps; i++ ) + { + pMemNext = (POOL_DATA_BLOCK*)pMemNext->Block.Next; + } + + + // + // update links + // + + // + // is it first link? + // + + ASSERT ((POOL_DATA_BLOCK *)pMemNext->Block.Prev); + + // + // No?, then break link and update ends + // + + ((POOL_DATA_BLOCK *)(pMemNext->Block.Prev))->Block.Next = NULL; + pMemNext->Block.Prev = NULL; // start of bin + + + // + // update bin + // + + g_Sma->Bin.Head = pMemNext; + g_Sma->Bin.NumBlocks -= *NumSmps; + + } + else + { + // + // <= Smps in bin + // + + *NumSmps = g_Sma->Bin.NumBlocks; + + + // + // update bin + // + + g_Sma->Bin.Head = g_Sma->Bin.Tail = NULL; + g_Sma->Bin.NumBlocks = 0; + } + + if ( 0 != *NumSmps ) + { + SMP_BLOCK *SmpBlock = (SMP_BLOCK *)pMem; + + for ( i=0; i< *NumSmps; i++ ) + { + SmpBlock->SmpByteCount = 0; + SmpBlock->RecvByteCount = 0; + SmpBlock = SmpBlock->Next; + } + + *SmpBlockList = (SMP_BLOCK *)pMem; + + _DBG_PRINT(_DBG_LVL_POOL,( + "pMem(x%p) Next(x%p) Prev(x%p)\n", + _DBG_PTR(pMem), _DBG_PTR(pMem->Block.Next), + _DBG_PTR(pMem->Block.Prev))); + + } + } // status + + SpinLockRelease( &g_Sma->Bin.Lock ); + + _DBG_LEAVE_LVL(_DBG_LVL_POOL); + + return status; +} + + + +// +// SmaReturnToPool +// +// The caller +// +// +// INPUTS: +// +// SmObject -Object returned in the Open call. +// +// SmpPool -An array of SMPs to be freed. +// +// +// OUTPUTS: +// +// +// RETURNS: +// +// +// + +FSTATUS +iba_smi_pool_put( + IN SMA_OBJECT *SmObject, + IN SMP_BLOCK *SmpBlockList + ) +{ + FSTATUS status=FSUCCESS; + + _DBG_ENTER_LVL(_DBG_LVL_POOL, iba_smi_pool_put); + + + // + // Do param checks + // + + + SmaReturnToBin((POOL_DATA_BLOCK *)SmpBlockList); + + _DBG_LEAVE_LVL(_DBG_LVL_POOL); + + return status; +} diff --git a/IbAccess/Common/Ibt/Sma/smarecv.c b/IbAccess/Common/Ibt/Sma/smarecv.c new file mode 100644 index 0000000..b85fe1f --- /dev/null +++ b/IbAccess/Common/Ibt/Sma/smarecv.c @@ -0,0 +1,302 @@ +/* BEGIN_ICS_COPYRIGHT4 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT4 ****************************************/ + +#include "smamain.h" + + +// +// Forward declarations +// + + + + + +// +// SmaPostRecv +// +// The caller can notify the SMA to recieve these many requests on this port. +// If the caller is expecting a known number of replies/receives, it should +// inform the SMA in advance to queue additional receives so as not to drop +// them. This call does not gaurantee that the SMA will not drop all incoming +// requests. However, it can help the SMA decide the traffic on this port. +// +// +// INPUTS: +// +// SmObject -Object returned in the Open call. +// +// SmaCaContext -Context to Channel Adapter. +// +// PortNumber -Port on Channel Adapter. +// +// NumSmps -Number of Smps that the caller is expecting on port +// specified. +// +// +// OUTPUTS: +// +// +// RETURNS: +// +// +// +FSTATUS +iba_smi_post_recv( + IN SMA_OBJECT *SmObject, + IN void *SmaCaContext, // Incoming CA + IN uint8 PortNumber, // Incoming Port + IN uint32 NumSmps // Expected Smp's to be received. + ) +{ + FSTATUS status = FERROR; + SMA_CA_OBJ_PRIVATE *pCaObj; + POOL_DATA_BLOCK *pSmpBlock = NULL; + POOL_DATA_BLOCK *pSmpBlockNext; + uint32 smps; + IB_WORK_REQ *workRequest; + SMA_PORT_TABLE_PRIV *pCaPortTbl=NULL; + CA_MEM_LIST caMemList; + IB_WORK_REQ wrq; + IB_LOCAL_DATASEGMENT dsList[2]; + + size_t i; + + + _DBG_ENTER_LVL(_DBG_LVL_RECV, iba_smi_post_recv); + + + // + // param check + // + + // + // lock + // + + pCaObj = (SMA_CA_OBJ_PRIVATE *)SmaCaContext; + + if ( NULL != pCaObj ) + { + // get port info + pCaPortTbl = (SMA_PORT_TABLE_PRIV *)pCaObj->CaPublic.PortTbl; + + // Only process Qp if not in Destory state + if ( QP_DESTROY != pCaPortTbl[PortNumber-1].PortBlock->Qp0Control ) + { + smps = AtomicRead(&pCaPortTbl[PortNumber-1].PortBlock->Qp0RecvQTop); + if (smps > NumSmps) + smps = NumSmps; + // Do not post if the q is full + if (smps) + { + status = iba_smi_pool_get( SmObject, &smps, + (SMP_BLOCK **)&pSmpBlock); + if ( FSUCCESS != status ) + { + _DBG_ERROR(("Not enough memory for SMPs!\n")); + } + } else { + _DBG_PRINT(_DBG_LVL_RECV,( + "Receive Q is full. No receives posted\n")); + status = FERROR; + } + } else { + _DBG_ERROR(("Qp in Destroy state!\n")); + status = FINVALID_STATE; + } + } else { + status = FERROR; // No Ca + } + + + if ( (NULL != pCaPortTbl) && + (FSUCCESS == status) && + (NULL != pSmpBlock) ) + { + // Fill in common work request info + MemoryClear(&wrq, sizeof(wrq)); + workRequest = &wrq; + workRequest->DSList = &dsList[0]; + workRequest->Operation = WROpRecv; + + + // + //BUGBUG: Do this in one go! + // + for ( i=0; iBlock.Next; + + pSmpBlock->Block.Next = pSmpBlock->Block.Prev = NULL; + + // + // set default return state + // + pSmpBlock->Block.Status = FNOT_DONE; + + + // + // Input values to process upon recv + // + + pSmpBlock->Block.SmaCaContext = pCaObj; + pSmpBlock->Block.PortNumber = PortNumber; + + // + // get LKey and Memory handles + // + + // + // Create GRH header + // + GetMemInfoFromCaMemTable( + pCaObj, + g_Sma->GlobalGrh->CaMemIndex, + &caMemList + ); + + + workRequest->DSList[0].Address = \ + (uintn) g_Sma->GlobalGrh->VirtualAddr; + workRequest->DSList[0].Length = sizeof(IB_GRH); + workRequest->DSList[0].Lkey = caMemList.LKey; + + + // + // Add other params before posting request + // + + GetMemInfoFromCaMemTable( + pCaObj, + pSmpBlock->CaMemIndex, + &caMemList + ); + + // + // The MAD block + // + workRequest->DSList[1].Address = \ + (uintn)pSmpBlock->Block.Smp; + workRequest->DSList[1].Length = sizeof(STL_SMP); + + workRequest->DSList[1].Lkey = caMemList.LKey; + + + workRequest->DSListDepth = 2; + workRequest->MessageLen = sizeof(IB_GRH) + sizeof(STL_SMP); + + // + // set Id to request stucture to unload + // + + ASSERT_VALID_WORKREQID((uintn)pSmpBlock); + workRequest->WorkReqId = BUILD_RQ_WORKREQID((uintn)pSmpBlock); + pCaObj->WorkReqId++; + + // + // Post on Recv + // + + AtomicDecrementVoid(&pCaPortTbl[PortNumber-1].PortBlock->Qp0RecvQTop); + + _DBG_PRINT(_DBG_LVL_RECV,( + "PostRecv(0x%p) Next(0x%p) Prev(0x%p)\n", + _DBG_PTR(pSmpBlock), + _DBG_PTR(pSmpBlock->Block.Next), + _DBG_PTR(pSmpBlock->Block.Prev) )); + + + SpinLockAcquire( &pCaPortTbl[PortNumber-1].PortBlock->Qp0Lock ); + + status = iba_post_recv( + pCaPortTbl[PortNumber-1].PortBlock->QpHandle, + workRequest + ); + SpinLockRelease( &pCaPortTbl[PortNumber-1].PortBlock->Qp0Lock ); + + // + // do all SMPs + // + + pSmpBlock = pSmpBlockNext; + } + } + + + // + // unlock + // + + + _DBG_LEAVE_LVL(_DBG_LVL_RECV); + + return status; +} + +// SmaRecv +// +// Returns any SMPs received. If the call is successful, the NumSmps will +// indicate the number of SMPS received and the SmpBlockList will hold +// a list of SmpBlocks received. +// +// +// INPUTS: +// +// SmObject -Object returned in the Open call. +// +// NumSmps -Number of SMPs received. +// +// SmpBlockList -A Linked list of receives with specific information. +// The list contains individual SMP_BLOCKs and the +// elements in list is indicated by NumSmps. +// +// +// OUTPUTS: +// +// +// RETURNS: +// FNOT_DONE - not implemented due to present SMI queing model +// hence never finds any data available to return +// +// +// +FSTATUS +iba_smi_recv( + IN SMA_OBJECT *SmObject, + IN uint32 *NumSmps, + OUT SMP_BLOCK **SmpBlockList + ) +{ + return FNOT_DONE; +} diff --git a/IbAccess/Common/Ibt/Sma/smasend.c b/IbAccess/Common/Ibt/Sma/smasend.c new file mode 100644 index 0000000..d786f79 --- /dev/null +++ b/IbAccess/Common/Ibt/Sma/smasend.c @@ -0,0 +1,663 @@ +/* BEGIN_ICS_COPYRIGHT4 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT4 ****************************************/ + +#include "smamain.h" + + + + +// +// SmaPostSend +// +// All SMPs are sent out by the SM with this call. The caller can send one +// to many SMPs by listing each SMP through a linked list of SMP_BLOCKs. +// The user will specify the total SMPs contained in the list. +// +// +// INPUTS: +// +// SmObject -Object returned in the Open call. +// +// NumSmps -Number of SMPs to send +// +// SmpBlockList -Linked list of send requests contained in SMP_BLOCKs +// +// PostCallback -A callback for SMPs Posted through SmpBlockList +// +// PostContext -user context that will be passed back on a post callback +// +// +// OUTPUTS: +// +// +// RETURNS: +// +// +// IRQL: +// +// + +FSTATUS +iba_smi_post_send( + IN SMA_OBJECT *SmObject, + IN uint32 NumSmps, + IN SMP_BLOCK *SmpBlockList, + IN SM_POST_CALLBACK *PostCallback, + IN void *PostContext + ) +{ + FSTATUS status = FSUCCESS; + boolean bLocal = TRUE; + + uint32 smps, tmpSmps; + POOL_DATA_BLOCK *pReq, *pSmpBlock; + SMA_CA_OBJ_PRIVATE *pCaObj; + SMA_PORT_TABLE_PRIV *pPortTbl; + SMP_LIST *pSmpList; + STL_SMP *pSmp; + uint8 portNo; + + + _DBG_ENTER_LVL ( _DBG_LVL_SEND, iba_smi_post_send ); + + + // Check params + smps = 0; + pReq = (POOL_DATA_BLOCK *)SmpBlockList; + + while ( smps < NumSmps ) + { + pSmp = (STL_SMP*)pReq->Block.Smp; + + if (pReq->Block.SmpByteCount == 0) + { + if (pSmp->common.BaseVersion == IB_BASE_VERSION) + pReq->Block.SmpByteCount = IB_MAD_BLOCK_SIZE; + else + pReq->Block.SmpByteCount = STL_MAD_BLOCK_SIZE; + } + + // Get CaContext + pCaObj = (SMA_CA_OBJ_PRIVATE *)pReq->Block.SmaCaContext; + + if ( NULL != pCaObj ) + { + + pPortTbl = (SMA_PORT_TABLE_PRIV *)pCaObj->CaPublic.PortTbl; + + // Check if Port number is valid + if (pCaObj->CaPublic.Capabilities & CA_IS_ENHANCED_SWITCH_PORT0) + { + if ( pReq->Block.PortNumber != 0 ) + { + // Error return, free buffers... + _DBG_ERROR (( "Invalid Port!\n" )); + pReq->Block.Status = status = FINVALID_PARAMETER; + break; + } + portNo = 0; + } + else if ( pReq->Block.PortNumber < 1 + || pReq->Block.PortNumber > pCaObj->CaPublic.Ports ) + { + // Error return, free buffers... + _DBG_ERROR (( "Invalid Port!\n" )); + pReq->Block.Status = status = FINVALID_PARAMETER; + break; + } + else + { + portNo = pReq->Block.PortNumber - 1; + } + + if ( QP_DESTROY == \ + pPortTbl[portNo].PortBlock->Qp0Control ) + { + _DBG_ERROR (( "Qp set to Destroy state!\n" )); + pReq->Block.Status = status = FINVALID_STATE; + break; + } + else + { + // check SLID, 0 is invalid also used as special internal value + if ( 0 == pReq->Block.SLID) + { + _DBG_ERROR (( "SLID 0 !\n" )); + pReq->Block.Status = status = FINVALID_PARAMETER; + break; + } + // Do some sanity checks for outgoing SMP from SM + if ( 1 == pSmp->common.mr.s.R ) + { + // Only SM_INFO can be passed up from SM as a Response + if ( MCLASS_ATTRIB_ID_SM_INFO != pSmp->common.AttributeID ) + { + _DBG_ERROR (( "R bit set!\n" )); + pReq->Block.Status = status = FINVALID_PARAMETER; + break; + } + + // Validate D bit, HopPointer and HopCount + // is per IBTA 1.1 sec 14.2.2.3 + if ( MCLASS_SM_DIRECTED_ROUTE == pSmp->common.MgmtClass ) + { + // D bit should be set + if ( 0 == pSmp->common.u.DR.s.D ) + { + _DBG_ERROR (( + "Status D bit mismatch!\n" )); + pReq->Block.Status = status = FINVALID_PARAMETER; + break; + } + +#if 0 // tests may not be valid if we use this interface to SMINFO ourselves + // HopCount cannot be zero at SM level in a response + if (0 == pSmp->common.u.DR.HopCount) + { + _DBG_ERROR (( + "HopCount zero response not available to SM!\n" )); + pReq->Block.Status = status = FINVALID_PARAMETER; + break; + } + + // HopPointer must be equal to HopCount + 1 + if (0 != pSmp->common.u.DR.HopCount) + { + if ( pSmp->common.u.DR.HopPointer != + (pSmp->common.u.DR.HopCount+1)) + { + _DBG_ERROR (( + "(HopPointer != HopCount+1) mismatch!\n" )); + pReq->Block.Status = status = FINVALID_PARAMETER; + break; + } + } // HC check +#endif + } // DR Smp check + } // R bit == 1 check + else + { + if ( MCLASS_SM_DIRECTED_ROUTE == pSmp->common.MgmtClass ) + { + // validate per IBTA 1.1 sec 14.2.2.1 + // D bit should be zero & HP should be zero + if ( 0 != ( pSmp->common.u.DR.s.D | \ + pSmp->common.u.DR.HopPointer )) + { + _DBG_ERROR (( + "Status D bit or HopPointer non-zero mismatch!\n" )); + pReq->Block.Status = status = FINVALID_PARAMETER; + break; + } + + // Local loopback check + if (( 0 == pSmp->common.u.DR.HopCount ) && \ + ( pReq->Block.DLID != STL_LID_PERMISSIVE )) + { + _DBG_ERROR (( + "Local loopback with DR DLID not Permissive!\n" )); + pReq->Block.Status = status = FINVALID_PARAMETER; + break; + } + } // DR Smp check + } // R bit == 0 check + } // Port check + } + else + { + _DBG_ERROR (( + "Bad CaContext!!!\n" )); + pReq->Block.Status = status = FINVALID_PARAMETER; + break; + } + + + // We need to trigger on a need basis to optimize interrupts. + // Look up port out usage + pReq->CQTrigger = TRUE; + + // Do all post requests + smps++; + pReq = (POOL_DATA_BLOCK*)pReq->Block.Next; + + } // Query all smps to be posted + + + // Only proceed if success + if ( FSUCCESS == status ) + { + // Load Smp list + smps = 0; + pSmpList = (SMP_LIST*)MemoryAllocateAndClear(sizeof(SMP_LIST), FALSE, SMA_MEM_TAG); + + if (pSmpList == NULL) { + status = FINSUFFICIENT_MEMORY; + goto exit; + } + + // Prepare Posts and send out + pSmpList->SmpsIn = NumSmps; // input + AtomicWrite(&pSmpList->SmpsOut, 0); // output + pSmpList->SmpsInError = 0; // errors + pSmpList->SmpBlock = SmpBlockList; + pSmpList->PostCallback = PostCallback; + pSmpList->Context = PostContext; + + // walk through list + pReq = (POOL_DATA_BLOCK *)SmpBlockList; + while ( smps < NumSmps ) + { + SMI_ACTION SmiAction; + + // link the list for active lookup in completions + pReq->Base = pSmpList; + pReq->Block.Status = 0; + + pSmp = (STL_SMP*)pReq->Block.Smp; + + // Get CaContext + pCaObj = (SMA_CA_OBJ_PRIVATE *)pReq->Block.SmaCaContext; + pPortTbl = (SMA_PORT_TABLE_PRIV *)pCaObj->CaPublic.PortTbl; + + // Clear out usage fields + pReq->AvHandle = 0; + + SmiAction = SmaProcessSmiSmp(pCaObj, pReq, FALSE); + + if (pCaObj->CaPublic.Capabilities & CA_IS_ENHANCED_SWITCH_PORT0) + { + portNo = 0; + } + else + { + portNo = pReq->Block.PortNumber - 1; + } + + // LID test below is not perfect since LMC should be included + // in computation. However if its wrong and we put on wire + // hardware should post back to us anyway, so not a big deal + if (SMI_TO_LOCAL == SmiAction + || SMI_TO_LOCAL_SM == SmiAction + || (SMI_LID_ROUTED == SmiAction + && pReq->Block.DLID == + (pPortTbl[portNo].PortBlock->Public.Address.BaseLID | pReq->Block.PathBits) + ) + ) + { + // Local loopback + tmpSmps = 1; + + // grab a memory block + status = iba_smi_pool_get( + SmObject, + &tmpSmps, + (SMP_BLOCK **)&pSmpBlock + ); + + if ( FSUCCESS == status ) + { + // Call internally and post on Recvd Q + MemoryCopy( + pSmpBlock->Block.Smp, + pReq->Block.Smp, + sizeof(STL_SMP) + ); + + // call common local function + pSmpBlock->Block.SmaCaContext = pReq->Block.SmaCaContext; + pSmpBlock->Block.PortNumber = pReq->Block.PortNumber; + pSmpBlock->Block.SmpByteCount = pReq->Block.SmpByteCount; + pSmpBlock->Block.SLID = pReq->Block.SLID; + pSmpBlock->Block.DLID = pReq->Block.DLID; + pSmpBlock->Block.PathBits = pReq->Block.PathBits; + pSmpBlock->Block.ServiceLevel = pReq->Block.ServiceLevel; + pSmpBlock->Block.StaticRate = pReq->Block.StaticRate; + + + if (SMI_TO_LOCAL == SmiAction || SMI_LID_ROUTED == SmiAction) + { + SmiAction = SmaProcessLocalSmp(pCaObj, pSmpBlock); + } + if (SMI_DISCARD == SmiAction) + { + (void)iba_smi_pool_put( + SmObject, + (SMP_BLOCK *)pSmpBlock); + } else { + // assume any SMI_TO_LOCAL, SMI_TO_LOCAL_SM or SMI_SEND + // or SMI_LID_ROUTED response + // needs to go back to the requestor + // so dump block in recv + SmaAddToRecvQ(pSmpBlock); + } + } + else + { + pReq->Block.Status = FINSUFFICIENT_MEMORY; + status = FSUCCESS; + } + + // Add to SendQ (eg. PostSend send completions) + SmaAddToSendQ( pReq ); + } + else if ((SMI_SEND == SmiAction) + || (SMI_LID_ROUTED == SmiAction)) + { + // Set local callback off + bLocal = FALSE; + + status = SmaPostSmp( + pCaObj, + pReq ); + if (FSUCCESS != status) + { + // discarded - unable to send + // Add to SendQ (eg. PostSend send completions) + SmaAddToSendQ( pReq ); + status = FSUCCESS; + } + } else { + // discarded + // Add to SendQ (eg. PostSend send completions) + SmaAddToSendQ( pReq ); + } + + + // Do all post requests + smps++; + pReq = (POOL_DATA_BLOCK*)pReq->Block.Next; + + } // Post all smps + + + // Add Smp block to global list + // Lock SmpList + // unlock block + + // If only local send do a manual recv completions + if ( TRUE == bLocal ) + { + SmaCompletionCallback( NULL ); + } + } + +exit: + _DBG_LEAVE_LVL(_DBG_LVL_SEND); + return status; +} + +// +// SmaPostSmp +// +// All SMPs Sent on the wire go through this call. This call is used by +// SmaPostSend() and Internal Callback reply sends as well as directed route +// sends +// +// INPUTS: +// +// CaObj -CA on which the SMP goes out +// Req -The SMP request being sent out +// CqTrigger -Do a ream of CQ if TRUE +// +// +// OUTPUTS: +// +// +// +// RETURNS: +// +// +// IRQL: +// +// + +FSTATUS +SmaPostSmp( + IN SMA_CA_OBJ_PRIVATE *CaObj, + IN POOL_DATA_BLOCK *Req + ) +{ + FSTATUS status; + IB_WORK_REQ *workRequest; + CA_MEM_LIST caMemList; + SMA_PORT_TABLE_PRIV *pPortTbl; + STL_SMP *pSmp; + IB_WORK_REQ wrq; + IB_LOCAL_DATASEGMENT dsList[1]; + IB_ADDRESS_VECTOR avInfo; + uint8 portNo; + + + + _DBG_ENTER_LVL ( _DBG_LVL_SEND, SmaPostSmp ); + + + MemoryClear(&wrq, sizeof(wrq)); + + workRequest = &wrq; + workRequest->DSList = &dsList[0]; + + pSmp = (STL_SMP*)Req->Block.Smp; + + +#ifdef IB_DEBUG + // + // Trap Debug Info + // + if ( MMTHD_TRAP == pSmp->common.mr.s.Method ) + { + BSWAP_MAD_HEADER( (MAD*)pSmp); + BSWAP_IB_NOTICE(((IB_NOTICE *)(pSmp->SmpExt.LIDRouted.SMPData))); + +#ifdef ICS_LOGGING + _DBG_PRINT(_DBG_LVL_CALLBACK, ( + ">>>>Trap Info:>>>>>\n" + "\tAttribModifier....: %x\n" + "\tStatus............: %x\n" + "\tIsGenericBit......: %x\n" + "\tTrapNumber........: %x\n" + "\tProducerType......: %x\n" + "\tType..............: %x\n", + pSmp->common.AttributeModifier, + pSmp->common.u.NS.Status.AsReg16, + ((IB_NOTICE *)(pSmp->SmpExt.LIDRouted.SMPData))->u.Generic.u.s.IsGeneric, + ((IB_NOTICE *)(pSmp->SmpExt.LIDRouted.SMPData))->u.Generic.TrapNumber, + ((IB_NOTICE *)(pSmp->SmpExt.LIDRouted.SMPData))->u.Generic.u.s.ProducerType, + ((IB_NOTICE *)(pSmp->SmpExt.LIDRouted.SMPData))->u.Generic.u.s.Type + )); + _DBG_PRINT(_DBG_LVL_CALLBACK, ( + ">>>>Trap Info (cont):>>>>>\n" + "\tIssuerLID.........: %x\n" + "\tNoticeCount.......: %x\n" + "\tNoticeToggle......: %x\n" + "\tdata..............: %x\n", + ((IB_NOTICE *)(pSmp->SmpExt.LIDRouted.SMPData))->IssuerLID, + ((IB_NOTICE *)(pSmp->SmpExt.LIDRouted.SMPData))->Stats.Count, + ((IB_NOTICE *)(pSmp->SmpExt.LIDRouted.SMPData))->Stats.Toggle, + ((IB_NOTICE *)(pSmp->SmpExt.LIDRouted.SMPData))->Data[0] + )); + + +#else + _DBG_PRINT (_DBG_LVL_CALLBACK, ( + ">>>>Trap Info:>>>>>\n" + "\tAttribModifier....: %x\n" + "\tStatus............: %x\n" + "\tIsGenericBit......: %x\n" + "\tTrapNumber........: %x\n" + "\tProducerType......: %x\n" + "\tType..............: %x\n" + "\tIssuerLID.........: %x\n" + "\tNoticeCount.......: %x\n" + "\tNoticeToggle......: %x\n" + "\tdata..............: %x\n", + pSmp->common.AttributeModifier, + pSmp->common.u.NS.Status.AsReg16, + ((IB_NOTICE *)(pSmp->SmpExt.LIDRouted.SMPData))->u.Generic.u.s.IsGeneric, + ((IB_NOTICE *)(pSmp->SmpExt.LIDRouted.SMPData))->u.Generic.TrapNumber, + ((IB_NOTICE *)(pSmp->SmpExt.LIDRouted.SMPData))->u.Generic.u.s.ProducerType, + ((IB_NOTICE *)(pSmp->SmpExt.LIDRouted.SMPData))->u.Generic.u.s.Type, + ((IB_NOTICE *)(pSmp->SmpExt.LIDRouted.SMPData))->IssuerLID, + ((IB_NOTICE *)(pSmp->SmpExt.LIDRouted.SMPData))->Stats.Count, + ((IB_NOTICE *)(pSmp->SmpExt.LIDRouted.SMPData))->Stats.Toggle, + ((IB_NOTICE *)(pSmp->SmpExt.LIDRouted.SMPData))->Data[0] + )); +#endif +#undef ProducerType + BSWAP_IB_NOTICE(((IB_NOTICE *)(pSmp->SmpExt.LIDRouted.SMPData))); + BSWAP_MAD_HEADER( (MAD*)pSmp); + } // trap info +#endif /* IB_DEBUG */ + + // + // get end-point info + // + pPortTbl = (SMA_PORT_TABLE_PRIV *)CaObj->CaPublic.PortTbl; + + if (CaObj->CaPublic.Capabilities & CA_IS_ENHANCED_SWITCH_PORT0) + { + portNo = 0; + } + else + { + portNo = Req->Block.PortNumber - 1; + } + + avInfo.PortGUID = pPortTbl->PortBlock[portNo].Public.GUID; + avInfo.DestLID = Req->Block.DLID; + avInfo.PathBits = Req->Block.PathBits; + avInfo.ServiceLevel = Req->Block.ServiceLevel; + avInfo.StaticRate = Req->Block.StaticRate; + avInfo.GlobalRoute = FALSE; + avInfo.GlobalRouteInfo.FlowLabel = 0; + + status = GetAV( + CaObj, + &avInfo, + &Req->AvHandle ); + + + if ( FSUCCESS == status ) + { + + // + // prepare the request + // + + workRequest->Operation = WROpSend; + + workRequest->DSList[0].Address = (uintn)Req->Block.Smp; + workRequest->DSList[0].Length = Req->Block.SmpByteCount; + + GetMemInfoFromCaMemTable( + CaObj, + Req->CaMemIndex, + &caMemList); + + workRequest->DSList[0].Lkey = caMemList.LKey; + + workRequest->DSListDepth = 1; + workRequest->MessageLen = Req->Block.SmpByteCount; + + workRequest->Req.SendUD.AVHandle= Req->AvHandle; + + // + //workRequest->Req.SendUD.ImmediateData = 0xdeadbeef; + // + workRequest->Req.SendUD.Options.AsUINT16 = 0; + workRequest->Req.SendUD.Options.s.SignaledCompletion= 1; +#if INCLUDE_16B + workRequest->Req.SendUD.Options.s.SendFMH = 0; +#endif + + // + // Shall be set to zero for SMPs! + // + workRequest->Req.SendUD.QPNumber = 0; + workRequest->Req.SendUD.Qkey = 0; + + // + // set Id to request stucture to unload + // + ASSERT_VALID_WORKREQID((uintn)Req); + workRequest->WorkReqId = BUILD_SQ_WORKREQID((uintn)Req); + CaObj->WorkReqId++; + + // + // Byte Order MAD Commen Header + // + BSWAP_STL_SMP_HEADER ((STL_SMP*)Req->Block.Smp); + +#if 0 + // + // yank request sends from pre-existing blocks. + // if they do not exist, create one. if the requirement + // is high, the new creation will satisfy the request + //WorkReq = SmObject->WorkReqSend; + // + if ( TRUE == Req->CQTrigger ) + { + + // + // The next Work Completion written to the + // CQ will generate an event + // + + status = iba_rearm_cq( + CaObj->CqHandle, + CQEventSelNextWC + ); + } +#endif + + SpinLockAcquire( &pPortTbl[portNo].PortBlock->Qp0Lock ); + + status = iba_post_send( + pPortTbl[portNo].PortBlock->QpHandle, + workRequest ); + + SpinLockRelease( &pPortTbl[portNo].PortBlock->Qp0Lock ); + + } + else + { + _DBG_ERROR (( + "AV error on LID = x%x! \n", + avInfo.DestLID )); + + } // AV handle + + if ( FSUCCESS != status ) + { + Req->Block.Status = status; + } + + _DBG_LEAVE_LVL (_DBG_LVL_SEND); + return status; +} diff --git a/IbAccess/Common/Ibt/Sma/smastore.c b/IbAccess/Common/Ibt/Sma/smastore.c new file mode 100644 index 0000000..92aa89c --- /dev/null +++ b/IbAccess/Common/Ibt/Sma/smastore.c @@ -0,0 +1,1232 @@ +/* BEGIN_ICS_COPYRIGHT4 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT4 ****************************************/ + +#include "smamain.h" + + + + +// +// RegisterMemGlobal +// +// Registers a given virtual address with all known Channel Adapters +// to the SMA +// +// Note: If we tweak the PdHandle to be unique for each client +// we can expose this function to clients. +// +// +// +// INPUTS: +// +// VirtualAddress -Address to register +// +// Length -amount of bytes to register in Length. +// +// AccessControl -Type of memory access. +// +// +// +// OUTPUTS: +// +// CaMemIndex -Global memory index that uniquely identifies this memory +// on all Channel Adapters +// +// +// RETURNS: +// +// +// +// caller cannot hold g_Sma->Bin.Lock, but may hold Mutex + +FSTATUS +RegisterMemGlobal( + IN void *VirtualAddress, + IN size_t Length, + IN IB_ACCESS_CONTROL AccessControl, + OUT uint32 *CaMemIndex + ) +{ + FSTATUS status = FSUCCESS; + SMA_CA_OBJ_PRIVATE *pCaObj; + CA_MEM_LIST caMemList; + boolean haveIndex = FALSE; + + + _DBG_ENTER_LVL(_DBG_LVL_STORE, RegisterMemGlobal); + + + // Register memory with all CA's + + SpinLockAcquire(&g_Sma->CaListLock); + for (pCaObj = g_Sma->CaObj; pCaObj; pCaObj = pCaObj->Next) + { + pCaObj->UseCount++; + SpinLockRelease(&g_Sma->CaListLock); + + if (! haveIndex) + { + // get an index for memory + SmaCreateCaMemIndex( pCaObj, CaMemIndex ); + haveIndex = TRUE; + } + + status = iba_register_mr( pCaObj->CaHandle, VirtualAddress, Length, + pCaObj->PdHandle, AccessControl, &caMemList.MrHandle, + &caMemList.LKey, &caMemList.RKey); + + // Check for return values + if ( FSUCCESS != status ) + { + _DBG_ERROR(("Could not register Memory!\n")); + goto failmr; + } + + status = SmaAddToCaMemTable( pCaObj, &caMemList, *CaMemIndex); + if ( FSUCCESS != status ) + { + _DBG_ERROR(("Could not add to Ca Mem Table!\n")); + goto failtbl; + } + + SpinLockAcquire(&g_Sma->CaListLock); + pCaObj->UseCount--; + + } // for I loop + SpinLockRelease(&g_Sma->CaListLock); + + if (! haveIndex) + { + // get an index for memory + SmaCreateCaMemIndex( NULL, CaMemIndex ); + } + +done: + _DBG_LEAVE_LVL(_DBG_LVL_STORE); + return status; + +failtbl: + (void)iba_deregister_mr(caMemList.MrHandle); + +failmr: + SpinLockAcquire(&g_Sma->CaListLock); + pCaObj->UseCount--; + // unwind other CA's + while (NULL != (pCaObj = pCaObj->Prev)) + { + pCaObj->UseCount++; + SpinLockRelease(&g_Sma->CaListLock); + + GetMemInfoFromCaMemTable( pCaObj, *CaMemIndex, &caMemList); + + (void)iba_deregister_mr(caMemList.MrHandle); + + DeleteFromCaMemTable( pCaObj, *CaMemIndex); + + SpinLockAcquire(&g_Sma->CaListLock); + pCaObj->UseCount--; + } + SpinLockRelease(&g_Sma->CaListLock); + + SmaDeleteCaMemIndex( *CaMemIndex ); + + goto done; +} + + +// +// DeregisterMemGlobal +// +// DeRegisters a given virtual address with all known Channel Adapters +// to the SMA. The address is defined by the Index it references. +// +// +// +// INPUTS: +// +// CaMemIndex -Global memory index that uniquely identifies this memory +// on all Channel Adapters +// +// +// +// OUTPUTS: +// +// +// +// RETURNS: +// +// +// + +FSTATUS +DeregisterMemGlobal( + IN uint32 CaMemIndex + ) +{ + FSTATUS status = FSUCCESS; + SMA_CA_OBJ_PRIVATE *pCaObj; + CA_MEM_LIST caMemList = { 0 }; /* keep compiler happy */ + + + _DBG_ENTER_LVL(_DBG_LVL_STORE, DeregisterMemGlobal); + + + // DeRegister memory with all CA's + + + // Loop through all CAs + SpinLockAcquire(&g_Sma->CaListLock); + for (pCaObj = g_Sma->CaObj; pCaObj; pCaObj = pCaObj->Next) + { + pCaObj->UseCount++; + SpinLockRelease(&g_Sma->CaListLock); + + GetMemInfoFromCaMemTable( pCaObj, CaMemIndex, &caMemList); + + iba_deregister_mr(caMemList.MrHandle); + + DeleteFromCaMemTable( pCaObj, CaMemIndex); + + SpinLockAcquire(&g_Sma->CaListLock); + pCaObj->UseCount--; + } + SpinLockRelease(&g_Sma->CaListLock); + + SmaDeleteCaMemIndex( CaMemIndex ); + + _DBG_LEAVE_LVL(_DBG_LVL_STORE); + return status; + +} + + +void +AcquireMemListMutex(void) +{ + MutexAcquire( &g_Sma->Bin.Mutex ); +} + +void +ReleaseMemListMutex(void) +{ + MutexRelease( &g_Sma->Bin.Mutex ); +} + +// +// CreateGlobalMemList +// +// Registers a given virtual address with all known Channel Adapters +// to the SMA. +// +// Note: If we tweak the PdHandle to be unique for each client +// we can expose this function to clients. +// +// +// INPUTS: +// +// VirtualAddress -Address to register +// +// Length -amount of bytes to register in Length. +// +// HeaderAddress -Address to block headers that hold registered mem +// +// HoldingMutex -is caller already holding g_Sma->Bin.Mutex (eg. MemListMutex) +// +// +// +// OUTPUTS: +// +// GlobalMemList -Global memory List that identifies memory across CA's +// +// +// RETURNS: +// +// +// + +GLOBAL_MEM_LIST * +CreateGlobalMemList( + void *VirtualAddr, + uintn Length, + void *HdrAddr, + boolean HoldingMutex + ) +{ + GLOBAL_MEM_LIST *pMemList; + + // + // Create global memory block in memory list + // + + pMemList = (GLOBAL_MEM_LIST*)MemoryAllocateAndClear(sizeof(GLOBAL_MEM_LIST), FALSE, SMA_MEM_TAG); + if ( NULL != pMemList ) + { + pMemList->VirtualAddr = VirtualAddr; + pMemList->Length = Length; + pMemList->HdrAddr = HdrAddr; + + pMemList->Prev = NULL; + + if (! HoldingMutex) + MutexAcquire( &g_Sma->Bin.Mutex ); + pMemList->Next = g_Sma->Bin.MemList; + if (g_Sma->Bin.MemList) + g_Sma->Bin.MemList->Prev = pMemList; + g_Sma->Bin.MemList = pMemList; + if (! HoldingMutex) + MutexRelease( &g_Sma->Bin.Mutex ); + } // pMemList + + return pMemList; +} + +// caller must not be holding g_Sma->Bin.Mutex +FSTATUS +DeleteGlobalMemList( + GLOBAL_MEM_LIST *MemList + ) +{ + FSTATUS status=FSUCCESS; + + MutexAcquire( &g_Sma->Bin.Mutex ); + + // + // Delete global memory block in memory list + // + + // + // delink from list first + // + + if ( NULL != MemList->Prev ) + { + ((GLOBAL_MEM_LIST *)MemList->Prev)->Next = MemList->Next; + } + + if ( NULL != MemList->Next ) + { + ((GLOBAL_MEM_LIST *)MemList->Next)->Prev = MemList->Prev; + } + + + // + // fix head of list if needed + // + + if ( MemList == g_Sma->Bin.MemList ) + { + g_Sma->Bin.MemList = (GLOBAL_MEM_LIST*)MemList->Next; + } + + MutexRelease( &g_Sma->Bin.Mutex ); + + // + // Free this block of mem + // + + MemoryDeallocate( MemList ); + + return status; +} + + + +// +// SmaGrabFromBin +// +// Grabs a specified number of MADs from pool. +// If the specified number of MADs are not available in pool, it is made +// available by more allocations. +// +// +// +// INPUTS: +// +// NumMad -Number of buffers requested in MAD sizes +// +// MadPool -Pointer to hold list of alloacted MAD buffers +// +// +// OUTPUTS: +// +// NumMad -Number of buffers allocated +// +// MadPool -Pointer holds list of alloacted MAD buffers +// +// +// RETURNS: +// +// +// + +#if 0 // not yet implemented, if'def out so get errors if anyone tried to use +FSTATUS +SmaGrabFromBin( + IN OUT uint32 *NumMad, + IN OUT SMP_BLOCK *MadPool + ) +{ + FSTATUS status = FSUCCESS; + + _DBG_ENTER_LVL(_DBG_LVL_STORE, SmaGrabFromBin); + + + SpinLockAcquire( &g_Sma->Bin.Lock ); + + SpinLockRelease( &g_Sma->Bin.Lock ); + + + _DBG_LEAVE_LVL(_DBG_LVL_STORE); + return status; +} +#endif + + + + + +// +// SmaReturnToBin +// +// Grabs a specified number of MADs from pool. +// If the specified number of MADs are not available in pool, it is made +// available by more allocations. +// +// +// +// INPUTS: +// +// NumMad -Number of buffers to free (in MAD sizes) +// +// MadPool -Pointer to list of MAD buffers to free +// +// +// OUTPUTS: +// +// +// RETURNS: +// +// +// +// + +FSTATUS +SmaReturnToBin( + IN POOL_DATA_BLOCK *SmpBlockList + ) +{ + FSTATUS status = FSUCCESS; + POOL_DATA_BLOCK *pMem, *pMemNext; + uint32 NumSmps; + + _DBG_ENTER_LVL(_DBG_LVL_STORE, SmaReturnToBin); + + + // + // lock + // + + SpinLockAcquire( &g_Sma->Bin.Lock ); + + + // + // return to bin + // + + pMemNext = g_Sma->Bin.Tail; // get system list + pMem = SmpBlockList; // load user list + + _DBG_PRINT(_DBG_LVL_STORE,( + "(FREE)pMem(x%p) Next(x%p) Prev(x%p)\n", + _DBG_PTR(pMem), _DBG_PTR(pMem->Block.Next), _DBG_PTR(pMem->Block.Prev))); + + + // + // add to system list + // + + pMem->Block.Prev = pMemNext; + if ( NULL == pMemNext ) + { + g_Sma->Bin.Head = pMem; + } + else + { + _DBG_PRINT(_DBG_LVL_STORE,( + "(TAIL)pMemNext(x%p) Next(x%p) Prev(x%p)\n", + _DBG_PTR(pMemNext), _DBG_PTR(pMemNext->Block.Next), _DBG_PTR(pMemNext->Block.Prev))); + + + pMemNext->Block.Next = pMem; + } + + + // + // count the SMPs returned + // + + NumSmps = 1; // start from here + pMem->Block.PathBits = 0; + pMem->Block.ServiceLevel = 0; + pMem->Block.StaticRate = 0; + pMem->Block.pSendContext = (void *)-1; //reset the sendcontext + + while ( NULL != pMem->Block.Next ) + { + NumSmps++; // keep counting + pMem = (POOL_DATA_BLOCK*)pMem->Block.Next; // loop + + pMem->Block.PathBits = 0; + pMem->Block.ServiceLevel = 0; + pMem->Block.StaticRate = 0; + pMem->Block.pSendContext = (void *)-1; //reset the sendcontext + } + + + // + // update system list + // + + g_Sma->Bin.Tail = pMem; + g_Sma->Bin.NumBlocks += NumSmps; + + _DBG_PRINT(_DBG_LVL_STORE,( + "x%x Free Smps in POOL\n", g_Sma->Bin.NumBlocks)); + + // + // Do house keeping + // TBD: Do we need to free memory not used? + // + + + // + // unlock + // + + SpinLockRelease( &g_Sma->Bin.Lock ); + + + _DBG_LEAVE_LVL(_DBG_LVL_STORE); + return status; + +} + + + + +// +// SmaAllocToBin +// +// Creates new entries in MAD pool. The number of new entries is specified +// as input. +// The functions adds the an average of the total number of MADs specified. +// The average is derived from a stored value that may be set at install +// time. +// +// In addition to the MAD buffer that is created in pool, a header is also +// allocated that will hold the transport header like the GRH and the +// data transfer values for send/recevies. +// +// Note: +// Lock taken by caller +// +// +// +// INPUTS: +// +// NumMads -Number of MADs buffers to create(in MAD sizes) +// +// HoldingMutex -is caller already holding g_Sma->Bin.Mutex +// +// Note: Caller must not be holding g_Sma->Bin.Lock +// +// OUTPUTS: +// +// +// RETURNS: +// +// +// +// + +FSTATUS +SmaAllocToBin( + IN uint32 NumMads, + IN boolean HoldingMutex + ) +{ + FSTATUS status = FSUCCESS; + UD_TOTAL_BLOCK *pUdBlock=NULL; + POOL_DATA_BLOCK *pSmpBlock=NULL; + GLOBAL_MEM_LIST *pMemList=NULL; + + POOL_DATA_BLOCK *pSmpBlockCurr; + POOL_DATA_BLOCK *pSmpBlockPrev, *pSmpBlockNext; + uint32 i, totalSmps; + + _DBG_ENTER_LVL(_DBG_LVL_STORE, SmaAllocToBin); + + + // + // lookup threshold level for smps in bin + // + + totalSmps = ( NumMads <= g_Settings.MinSMPsPerAllocate ? \ + g_Settings.MinSMPsPerAllocate: \ + ( NumMads + g_Settings.MinSMPsPerAllocate - \ + ( NumMads % g_Settings.MinSMPsPerAllocate ))); + + if (! HoldingMutex) + MutexAcquire( &g_Sma->Bin.Mutex ); + + if ( g_Settings.MaxSMPs < g_Sma->Bin.TotalAllocated + totalSmps ) + { + _DBG_ERROR(( + "MaxSMP allocation threshold (x%x) level reached\n", + g_Settings.MaxSMPs)); + + totalSmps = g_Settings.MaxSMPs - g_Sma->Bin.TotalAllocated; + } + + + // + // Allocate memory for SMPs + // + + // + // BUGBUG: We should allocate paged mem here for Win2K and lock it + // + + if ( totalSmps ) + { + pUdBlock = (UD_TOTAL_BLOCK*)MemoryAllocateAndClear( + totalSmps * sizeof(MAD), FALSE, SMA_MEM_TAG); + } + + if ( NULL != pUdBlock ) + { + + // + // alloc memory for POOL_DATA_BLOCKs + // + + pSmpBlock = (POOL_DATA_BLOCK*)MemoryAllocateAndClear( + totalSmps * sizeof(POOL_DATA_BLOCK), FALSE, SMA_MEM_TAG); + if ( NULL != pSmpBlock ) + { + + // + // Create global memory block in memory list + // + + pMemList = CreateGlobalMemList( + pUdBlock, + ( totalSmps * sizeof(MAD)), + pSmpBlock, + TRUE ); + } // pSmpBlock + } // pUdBlock + + if ( ( NULL != pUdBlock ) && \ + ( NULL != pSmpBlock ) && \ + ( NULL != pMemList ) ) + { + _DBG_PRINT(_DBG_LVL_STORE, + ("Total : requested(x%x), allocated(x%x)\n", \ + NumMads, totalSmps)); + _DBG_PRINT(_DBG_LVL_STORE, + ("Memory: pUdBlock(x%p), pSmpBlock(x%p)\n", \ + _DBG_PTR(pUdBlock), _DBG_PTR(pSmpBlock))); + + // + // set access level for memory region + // + + pMemList->AccessControl.AsUINT16 = 0; + pMemList->AccessControl.s.LocalWrite = 1; + + status = RegisterMemGlobal( + pMemList->VirtualAddr, + pMemList->Length, + pMemList->AccessControl, + &pMemList->CaMemIndex + ); + + if ( FSUCCESS == status ) + { + + // + // get pointers + // + + pSmpBlockCurr = pSmpBlock; + pSmpBlockPrev = NULL; // fill in g_Sma->Bin.Tail at end of loop + + + // + // update next value + // + + pSmpBlockNext = pSmpBlockCurr; + pSmpBlockNext++; + + for ( i=0; i< totalSmps; i++ ) + { + + // + // update current pointer values + // + + pSmpBlockCurr->Block.Smp = &pUdBlock->Mad; + //pSmpBlockCurr->Block.Grh = &pUdBlock->Grh; + //pSmpBlockCurr->Block.Lrh = &pUdBlock->Lrh; + + pSmpBlockCurr->Block.Prev = pSmpBlockPrev; + pSmpBlockCurr->Block.Next = pSmpBlockNext; + + + // + // Add Index for mem keys + // + + pSmpBlockCurr->CaMemIndex = pMemList->CaMemIndex; + + + // + // increment pointers + // + + pSmpBlockPrev = pSmpBlockCurr; + pSmpBlockCurr = pSmpBlockNext; + pSmpBlockNext++; + pUdBlock++; + + } // i loop + + + // + // Adjust and add to bin + // + + SpinLockAcquire( &g_Sma->Bin.Lock ); + + pSmpBlock->Block.Prev = g_Sma->Bin.Tail; // first of new + pSmpBlockPrev->Block.Next = NULL; // last of new + + if ( NULL == g_Sma->Bin.Head ) + { + g_Sma->Bin.Head = pSmpBlock; + } + else + { + g_Sma->Bin.Tail->Block.Next = pSmpBlock; + } + + g_Sma->Bin.Tail = pSmpBlockPrev; + g_Sma->Bin.NumBlocks += totalSmps; + SpinLockRelease( &g_Sma->Bin.Lock ); + + g_Sma->Bin.TotalAllocated += totalSmps; + } + } + else + { + + // + // errors in allocations. + // + + _DBG_ERROR(( + "Could not allocate memory for x%x SMPs; tried x%x\n\n", \ + NumMads, totalSmps)); + + // + // return module specific errors + // + + status = FINSUFFICIENT_MEMORY; + } + + if (status != FSUCCESS) + { + + // + // unwind + // + + if ( NULL != pMemList ) + { + g_Sma->Bin.MemList = (GLOBAL_MEM_LIST*)pMemList->Next; + MemoryDeallocate( pMemList ); + } + if ( NULL != pSmpBlock ) + MemoryDeallocate( pSmpBlock ); + if ( NULL != pUdBlock ) + MemoryDeallocate( pUdBlock ); + + } + + if (! HoldingMutex) + MutexRelease( &g_Sma->Bin.Mutex ); + + _DBG_LEAVE_LVL(_DBG_LVL_STORE); + return status; + +} + + + + +// +// SmaRemoveFromBin +// +// Note: +// Lock taken by caller +// +// +// +// INPUTS: +// +// +// +// OUTPUTS: +// +// +// RETURNS: +// +// +// +// + +#if 0 // not yet implemented, if'def out so get errors if anyone tried to use +FSTATUS +SmaRemoveFromBin(void) +{ + FSTATUS status = FSUCCESS; + + _DBG_ENTER_LVL(_DBG_LVL_STORE, SmaRemoveFromBin); + + + // + // SpinLockDestroy( g_Sma->Lock); + // + + + + _DBG_LEAVE_LVL(_DBG_LVL_STORE); + return status; + +} +#endif + + + + +// +// SmaCreateCaMemIndex +// +// Creates new entries in MAD pool. The number of new entries is specified +// as input. +// The functions adds the an average of the total number of MADs specified. +// The average is derived from a stored value that may be set at install +// time. +// +// In addition to the MAD buffer that is created in pool, a header is also +// allocated that will hold the transport header like the GRH and the +// data transfer values for send/recevies. +// +// Note: +// Lock taken by caller +// +// +// +// INPUTS: +// +// NumMads -Number of MADs buffers to create(in MAD sizes) +// +// +// OUTPUTS: +// +// +// RETURNS: +// +// +// +// +// +// Memory functions to Store, Get and delete registered memory info +// +// caller cannot hold g_Sma->Bin.Lock +void +SmaCreateCaMemIndex( + IN SMA_CA_OBJ_PRIVATE *CaObj, + OUT uint32 *CaMemIndex + ) +{ + CA_MEM_TABLE *pCaMemTbl; + + + _DBG_ENTER_LVL(_DBG_LVL_STORE, SmaCreateCaMemIndex); + + if (CaObj) + pCaMemTbl = CaObj->CaMemTbl; + else + pCaMemTbl = NULL; + + + SpinLockAcquire( &g_Sma->Bin.Lock ); + + // + // Allocate Index from global entry + // + + *CaMemIndex = g_Sma->Bin.CurrentIndex++; + + //_DBG_PRINT(_DBG_LVL_STORE,("MemIndex = x%x\n",*CaMemIndex)); + + // + // Is an Index available in table ? + // + + if ( NULL != pCaMemTbl ) + { + + // + // If index is from the middle, scan for new index + // + + while (0 != pCaMemTbl->MemBlock[g_Sma->Bin.CurrentIndex].LKey) + { + g_Sma->Bin.CurrentIndex++; + + // + // TBD:need logic here to scan from start + // + + // + // if the index is greater than what it can hold, a table + // will subsiquently be created + // + // if we have reached out, break + // + + if ( g_Sma->Bin.CurrentIndex > pCaMemTbl->Total ) + break; + } + } + SpinLockRelease( &g_Sma->Bin.Lock ); + + _DBG_LEAVE_LVL(_DBG_LVL_STORE); +} + +// caller cannot hold g_Sma->Bin.Lock +void +SmaDeleteCaMemIndex( + IN uint32 CaMemIndex + ) +{ + SpinLockAcquire( &g_Sma->Bin.Lock ); + + if ( g_Sma->Bin.CurrentIndex > CaMemIndex ) + g_Sma->Bin.CurrentIndex = CaMemIndex; + + SpinLockRelease( &g_Sma->Bin.Lock ); +} + + +FSTATUS +SmaAddToCaMemTable( + IN SMA_CA_OBJ_PRIVATE *CaObj, + IN CA_MEM_LIST *CaMemList, + IN uint32 CaMemIndex + ) +{ + FSTATUS status = FSUCCESS; + CA_MEM_TABLE *pCaMemTbl, *pNewCaMemTbl; + uint32 memSize; + boolean newTable=FALSE; + + + _DBG_ENTER_LVL(_DBG_LVL_STORE, SmaAddToCaMemTable); + + pCaMemTbl = CaObj->CaMemTbl; + + _DBG_PRINT(_DBG_LVL_STORE,(\ + "Index = x%x \n", + CaMemIndex)); + + // + // do we need a new table ? + // + + if (( NULL != pCaMemTbl ) && ( CaMemIndex > pCaMemTbl->Total )) + newTable = TRUE; + + + // + // Allocate table if it does not exist or if too small + // + + if (( NULL == pCaMemTbl ) || ( TRUE == newTable )) + { + + // + // calculate amount of memory needed + // + + memSize = g_Settings.MemTableSize; + if (TRUE == newTable) + { + memSize = (CaMemIndex + 1) * sizeof(CA_MEM_BLOCK); + + // + // adjust in page sizes set in global settings + // + + memSize += ((CaMemIndex + 1) * sizeof(CA_MEM_BLOCK) % \ + g_Settings.MemTableSize ); + } + + pNewCaMemTbl = (CA_MEM_TABLE*)MemoryAllocateAndClear(memSize, FALSE, SMA_MEM_TAG); + if ( NULL != pNewCaMemTbl ) + { + if (TRUE == newTable) + { + + // + // copy old entries + // + + MemoryCopy( + &pNewCaMemTbl->MemBlock[0], + &pCaMemTbl->MemBlock[0], + pCaMemTbl->Total*sizeof(CA_MEM_BLOCK) + ); + + + // + // free old table + // + + MemoryDeallocate( pCaMemTbl ); + } + + + // + // write down total entries + // + + pNewCaMemTbl->Total = (memSize)/sizeof(CA_MEM_BLOCK) - 1; + + + // + // reassign pointers + // + + pCaMemTbl = pNewCaMemTbl; + CaObj->CaMemTbl = pCaMemTbl; + } + else + { + status = FERROR; + } + } + + if ( FSUCCESS == status ) + { + + // + // ASSERT on out of table experience + // + + pCaMemTbl->MemBlock[CaMemIndex].MrHandle = CaMemList->MrHandle; + pCaMemTbl->MemBlock[CaMemIndex].LKey = CaMemList->LKey; + //pCaMemTbl->MemBlock[CaMemIndex].RKey = CaMemList->RKey; + } + + _DBG_LEAVE_LVL(_DBG_LVL_STORE); + return status; +} + + + + +FSTATUS +GetMemInfoFromCaMemTable( + IN SMA_CA_OBJ_PRIVATE *CaObj, + IN uint32 CaMemIndex, + OUT CA_MEM_LIST *CaMemList + ) +{ + FSTATUS status = FSUCCESS; + CA_MEM_TABLE *pCaMemTbl; + + + _DBG_ENTER_LVL(_DBG_LVL_STORE, GetMemInfoFromCaMemTable); + + pCaMemTbl = CaObj->CaMemTbl; + + _DBG_PRINT(_DBG_LVL_STORE,(\ + "Index = x%x\n", + CaMemIndex)); + + // + // Allocate table if it does not exist + // + + if ( NULL != pCaMemTbl ) + { + CaMemList->MrHandle = pCaMemTbl->MemBlock[CaMemIndex].MrHandle; + CaMemList->LKey = pCaMemTbl->MemBlock[CaMemIndex].LKey; +// CaMemList->RKey = pCaMemTbl->MemBlock[CaMemIndex].RKey; + } + else + { + status = FERROR; + } + + _DBG_LEAVE_LVL(_DBG_LVL_STORE); + return status; +} + +FSTATUS +DeleteFromCaMemTable( + IN SMA_CA_OBJ_PRIVATE *CaObj, + IN uint32 CaMemIndex + ) +{ + FSTATUS status = FSUCCESS; + CA_MEM_TABLE *pCaMemTbl; + + + _DBG_ENTER_LVL(_DBG_LVL_STORE, DeleteFromCaMemTable); + + pCaMemTbl = CaObj->CaMemTbl; + + // + // Allocate table if it does not exist + // + if ( NULL != pCaMemTbl ) + { + pCaMemTbl->MemBlock[CaMemIndex].MrHandle = NULL; + pCaMemTbl->MemBlock[CaMemIndex].LKey = 0; +// pCaMemTbl->MemBlock[CaMemIndex].RKey = 0; + } + else + { + status = FERROR; + } + + _DBG_LEAVE_LVL(_DBG_LVL_STORE); + return status; +} + + +// +// Register any registered memory with this CA +// caller cannot hold g_Sma->Bin.Lock +// caller must hold g_Sma->Bin.Mutex +FSTATUS +SmaBindGlobalMem( + IN SMA_CA_OBJ_PRIVATE *CaObj + ) +{ + FSTATUS status = FSUCCESS; + GLOBAL_MEM_LIST *pMemList; + CA_MEM_LIST caMemList; + + + _DBG_ENTER_LVL(_DBG_LVL_STORE, SmaBindGlobalMem); + + pMemList = g_Sma->Bin.MemList; + + while ( NULL != pMemList ) + { + + status = iba_register_mr( CaObj->CaHandle, pMemList->VirtualAddr, + pMemList->Length, CaObj->PdHandle, + pMemList->AccessControl, &caMemList.MrHandle, + &caMemList.LKey, &caMemList.RKey); + + // Check returns + if ( FSUCCESS != status ) + { + _DBG_ERROR(("Could not register Memory x%p!\n", + _DBG_PTR(pMemList->VirtualAddr))); + + // + // unwind + // + + while ( NULL != pMemList->Prev ) + { + pMemList = (GLOBAL_MEM_LIST*)pMemList->Prev; + + GetMemInfoFromCaMemTable( + CaObj, + pMemList->CaMemIndex, + &caMemList + ); + + iba_deregister_mr(caMemList.MrHandle); + + } + + + // + // remove the memlink + // + + if ( NULL != CaObj->CaMemTbl ) + MemoryDeallocate( CaObj->CaMemTbl ); + + break; + } + else + { + status = SmaAddToCaMemTable( + CaObj, + &caMemList, + pMemList->CaMemIndex + ); + } + + + // + // loop thru' all lists + // + + pMemList = (GLOBAL_MEM_LIST*)pMemList->Next; + + } // while loop + + _DBG_LEAVE_LVL(_DBG_LVL_STORE); + return status; + +} diff --git a/IbAccess/Common/Ibt/Vca/README b/IbAccess/Common/Ibt/Vca/README new file mode 100644 index 0000000..901f353 --- /dev/null +++ b/IbAccess/Common/Ibt/Vca/README @@ -0,0 +1,4 @@ +Kernel Virtual Channel Adapter - primary kernel interface for IB. + + driver or Vka -> Vca -> Vpd -> hardware + kernel diff --git a/IbAccess/Common/Ibt/Vca/ib_avtracker.c b/IbAccess/Common/Ibt/Vca/ib_avtracker.c new file mode 100644 index 0000000..5b2b3ad --- /dev/null +++ b/IbAccess/Common/Ibt/Vca/ib_avtracker.c @@ -0,0 +1,616 @@ +/* BEGIN_ICS_COPYRIGHT6 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT6 ****************************************/ + +/* AV Tracker to help manage AVs, especially multicast AVs + * + * The AV tracker is used to track the current AV to send to a destination. + * It also helps in handling the reference counting problem by + * tracking previous AVs until their reference count hits zero. + * + * Typically 1 AV Tracker would be created per destination (such as a MC group) + * and the current AV would reflect the latest AV for sending to that group. + * When path record queries or Multicast joins succeed, a corresponding AV + * should be created and IbAvTrackerSetCurrent. If the patch record is stale + * or the Multicast join is lost (port down, etc), the current should be cleared + * via IbAvTrackerClearCurrent. + * + * Of course, AVs cannot be destroyed until all send WQEs which use them have + * completed. To this end, the AV tracker keeps a reference count per AV + * and manages the destroy. Each time a send needs to occur to the destination, + * IbAvTrackerGetCurrent should be called. The incRef argument will cause the + * reference count for the AV to be incremented to prevent its destruction + * while in use. When the send completion occurs, IbAvTrackerDecRef should be + * called. This will destroy the AV when its count reaches 0 [SetCurrent counts + * as a reference so the current AV will not be destroyed by DecRef]. + * + * The actual meaning of references for GetCurrent/IncRef/DecRef is up to + * the caller. For example 1 reference count be counted per WQE. An + * alternative could be to count 1 reference per scheduled completion. + */ +#include "ib_debug.h" +#include "ib_debug_osd.h" +#include "ibt.h" + +#include "precomp.h" +#define ALLOC_TAG VCA_MEM_TAG + +/*++ + +Routine Description + zero out fields in AV_TRACKER + +Input: + pTracker: AV tracker object to initialize + +Output: + None +--*/ +void +IbAvTrackerInitState( + IN AV_TRACKER *pTracker + ) +{ + _DBG_ENTER_FUNC(IbAvTrackerInitState); + SpinLockInitState(&pTracker->lock); + pTracker->currentAV = NULL; + QListInitState(&pTracker->avList); + _DBG_LEAVE_FUNC(); +} + +/*++ + +Routine Description + Initialize AV_TRACKER + +Input: + pTracker: AV tracker object to initialize + caHandle: Open CA instance used to create AVs + pdHandle: PD instance used to create AVs + +Output: + status of the operation + +Additional Information: + caHandle and pdHandle are only used if IbAvTrackerMulticastCallback is used +--*/ +FSTATUS +IbAvTrackerInit( + IN AV_TRACKER *pTracker, + IN IB_HANDLE caHandle, + IN IB_HANDLE pdHandle + ) +{ + _DBG_ENTER_FUNC(IbAvTrackerInit); + if (! SpinLockInit(&pTracker->lock)) + goto faillock; + if (! QListInit(&pTracker->avList)) + goto faillist; + pTracker->caHandle = caHandle; + pTracker->pdHandle = pdHandle; + _DBG_LEAVE_FUNC(); + return FSUCCESS; + +faillist: + SpinLockDestroy(&pTracker->lock); +faillock: + _DBG_LEAVE_FUNC(); + return FERROR; +} + +/*++ + +Routine Description + Destroy AV_WRAP + +Input: + pAvWrap: AV tracked object to destroy + +Output: + None + +Additional Information: + destroys the AV and frees AV_WRAP + caller must have removed from avList first + +--*/ +static void +IbAvTrackerDestroyAV( + IN AV_WRAP *pAvWrap + ) +{ + _DBG_ENTER_FUNC(IbAvTrackerDestroyAV); + (void)iba_destroy_av(pAvWrap->avHandle); + MemoryDeallocate(pAvWrap); + _DBG_LEAVE_FUNC(); +} + +/*++ + +Routine Description + Destroy AV_TRACKER + +Input: + pTracker: AV tracker object to destroy + +Output: + status of the operation + +Additional Information: + Any AVs still in the IbAvTracker will be destroyed by this + operation. + +--*/ +void +IbAvTrackerDestroy( + IN AV_TRACKER *pTracker + ) +{ + LIST_ITEM *pItem; + + _DBG_ENTER_FUNC(IbAvTrackerDestroy); + SpinLockAcquire(&pTracker->lock); + while (NULL != (pItem=QListRemoveHead(&pTracker->avList))) + IbAvTrackerDestroyAV((AV_WRAP*)QListObj(pItem)); + SpinLockRelease(&pTracker->lock); + + SpinLockDestroy(&pTracker->lock); + pTracker->currentAV = NULL; + QListDestroy(&pTracker->avList); + _DBG_LEAVE_FUNC(); +} + + +/*++ + +Routine Description + Get current AV for tracker + +Input: + pTracker: AV tracker object to act on + incRef: should reference count for returned AV be incremented + +Output: + AV handle of current AV, can be NULL if no current AV + +Additional Information: + Current AV is the last one Created/Set for the tracker + This typically indicates the most recent path to the destination + +--*/ +IB_HANDLE +IbAvTrackerGetCurrent( + IN AV_TRACKER *pTracker, + IN boolean incRef + ) +{ + IB_HANDLE result = NULL; + AV_WRAP *currentAV; + + _DBG_ENTER_FUNC(IbAvTrackerGetCurrent); + SpinLockAcquire(&pTracker->lock); + currentAV = pTracker->currentAV; + if (currentAV) { + result = currentAV->avHandle; + if (incRef) + AtomicIncrement(¤tAV->refCount); + } + SpinLockRelease(&pTracker->lock); + _DBG_LEAVE_FUNC(); + return result; +} + +/*++ + +Routine Description + Find given AV in tracker + +Input: + pTracker: AV tracker object to act on + avHandle: AV handle to search for + +Output: + AV_WRAP for given AV (or NULL) + +Additional Information: + AV tracker lock must be held when called +--*/ +static AV_WRAP* +IbAvTrackerFindAV( + IN AV_TRACKER *pTracker, + IN IB_HANDLE avHandle + ) +{ + AV_WRAP *found; + LIST_ITEM *pItem; + + _DBG_ENTER_FUNC(IbAvTrackerFindAV); + /* typically we will be operating on currentAV */ + if (pTracker->currentAV && pTracker->currentAV->avHandle == avHandle) { + _DBG_LEAVE_FUNC(); + return pTracker->currentAV; + } + found = NULL; + for (pItem = QListHead(&pTracker->avList); pItem != NULL; pItem = QListNext(&pTracker->avList, pItem)) { + AV_WRAP* pAvWrap = (AV_WRAP*)QListObj(pItem); + if (pAvWrap->avHandle == avHandle) { + found = pAvWrap; + break; + } + } + _DBG_LEAVE_FUNC(); + return found; +} + +/*++ + +Routine Description + add given AV to tracker + +Input: + pTracker: AV tracker object to act on + avHandle: AV handle to add + +Output: + AV_WRAP for given AV (or NULL) + +Additional Information: + AV tracker lock must be held when called + avHandle must not already be in the list +--*/ +static AV_WRAP* +IbAvTrackerAddAV( + IN AV_TRACKER *pTracker, + IN IB_HANDLE avHandle + ) +{ + AV_WRAP *pAvWrap; + + _DBG_ENTER_FUNC(IbAvTrackerAddAV); + pAvWrap = (AV_WRAP*)MemoryAllocate2AndClear( + sizeof(AV_WRAP), IBA_MEM_FLAG_NONE, ALLOC_TAG); + if (! pAvWrap) + goto done; + ListItemInitState(&pAvWrap->listItem); + QListSetObj(&pAvWrap->listItem, pAvWrap); + pAvWrap->avHandle = avHandle; + AtomicWrite(&pAvWrap->refCount, 0); + QListInsertHead(&pTracker->avList, &pAvWrap->listItem); +done: + _DBG_LEAVE_FUNC(); + return pAvWrap; +} + +/*++ + +Routine Description + Clear current AV for tracker + +Input: + pTracker: AV tracker object to act on + +Output: + none + +Additional Information: + If there is no current AV, this is a noop + Reference count of current AV is decremented, if 0 its AV is destroyed + Otherwise its will not be destroyed until a future IbAvTrackerDecRef + +--*/ +void +IbAvTrackerClearCurrent( + IN AV_TRACKER *pTracker + ) +{ + AV_WRAP *currentAV; + + _DBG_ENTER_FUNC(IbAvTrackerClearCurrent); + SpinLockAcquire(&pTracker->lock); + currentAV = pTracker->currentAV; + if (! currentAV) + goto unlock; /* noop */ + pTracker->currentAV = NULL; + if (AtomicDecrement(¤tAV->refCount)) + goto unlock; /* leave in list, still has references */ + /* last reference removed, destroy AV and wrapper */ + QListRemoveItem(&pTracker->avList, ¤tAV->listItem); + IbAvTrackerDestroyAV(currentAV); +unlock: + SpinLockRelease(&pTracker->lock); + _DBG_LEAVE_FUNC(); + return; +} + +/*++ + +Routine Description + Set current AV for tracker + +Input: + pTracker: AV tracker object to act on + avHandle: AV to set as current AV + +Output: + status of the operation + +Additional Information: + If the given AV is not already in the tracker, it is added + If it is already current AV, this is a noop + If there is an existing different current AV, it is cleared first + +--*/ +FSTATUS +IbAvTrackerSetCurrent( + IN AV_TRACKER *pTracker, + IN IB_HANDLE avHandle + ) +{ + AV_WRAP *currentAV; + FSTATUS status = FSUCCESS; + + _DBG_ENTER_FUNC(IbAvTrackerSetCurrent); + ASSERT(avHandle); + SpinLockAcquire(&pTracker->lock); + currentAV = pTracker->currentAV; + if (currentAV) { + if (currentAV->avHandle == avHandle) + goto unlock; /* noop */ + /* clear currentAV */ + if (0 == AtomicDecrement(¤tAV->refCount)) { + /* last reference removed, destroy AV and wrapper */ + QListRemoveItem(&pTracker->avList, ¤tAV->listItem); + IbAvTrackerDestroyAV(currentAV); + } + } + pTracker->currentAV = IbAvTrackerFindAV(pTracker, avHandle); + if (! pTracker->currentAV) { + pTracker->currentAV = IbAvTrackerAddAV(pTracker, avHandle); + if (! pTracker->currentAV) { + status = FINSUFFICIENT_MEMORY; + goto unlock; + } + } + AtomicIncrementVoid(&pTracker->currentAV->refCount); +unlock: + SpinLockRelease(&pTracker->lock); + _DBG_LEAVE_FUNC(); + return status; +} + +/*++ + +Routine Description + increment reference count for an AV in tracker + +Input: + pTracker: AV tracker object to act on + avHandle: AV to increment reference count on + +Output: + status of operation + +Additional Information: + If the given AV is not already in the tracker, this fails + +--*/ +FSTATUS +IbAvTrackerIncRef( + IN AV_TRACKER *pTracker, + IN IB_HANDLE avHandle + ) +{ + AV_WRAP *pAvWrap; + FSTATUS status = FSUCCESS; + + _DBG_ENTER_FUNC(IbAvTrackerIncRef); + ASSERT(avHandle); + SpinLockAcquire(&pTracker->lock); + pAvWrap = IbAvTrackerFindAV(pTracker, avHandle); + if (! pAvWrap) { + status = FNOT_FOUND; + goto unlock; + } + AtomicIncrementVoid(&pAvWrap->refCount); +unlock: + SpinLockRelease(&pTracker->lock); + _DBG_LEAVE_FUNC(); + return status; +} + +/*++ + +Routine Description + decrement reference count for an AV in tracker + +Input: + pTracker: AV tracker object to act on + avHandle: AV to decrement reference count on + +Output: + status of operation + +Additional Information: + If the given AV is not already in the tracker, this fails + If reference count reaches 0, AV is removed from tracker and destroyed + +--*/ +FSTATUS +IbAvTrackerDecRef( + IN AV_TRACKER *pTracker, + IN IB_HANDLE avHandle + ) +{ + AV_WRAP *pAvWrap; + FSTATUS status = FSUCCESS; + + _DBG_ENTER_FUNC(IbAvTrackerDecRef); + ASSERT(avHandle); + SpinLockAcquire(&pTracker->lock); + pAvWrap = IbAvTrackerFindAV(pTracker, avHandle); + if (! pAvWrap) { + status = FNOT_FOUND; + goto unlock; + } + if (0 == AtomicDecrement(&pAvWrap->refCount)) { + /* last reference removed, destroy AV and wrapper */ + ASSERT(pAvWrap != pTracker->currentAV); + QListRemoveItem(&pTracker->avList, &pAvWrap->listItem); + IbAvTrackerDestroyAV(pAvWrap); + } +unlock: + SpinLockRelease(&pTracker->lock); + _DBG_LEAVE_FUNC(); + return status; +} + +/*++ + +Routine Description + subtract from reference count for an AV in tracker + +Input: + pTracker: AV tracker object to act on + avHandle: AV to decrement reference count on + count: amount to subtract from reference count + +Output: + status of operation + +Additional Information: + Can be used to aid reference counting when completion coallescing used + If the given AV is not already in the tracker, this fails + If reference count reaches 0, AV is removed from tracker and destroyed + +--*/ +FSTATUS +IbAvTrackerSubtractRef( + IN AV_TRACKER *pTracker, + IN IB_HANDLE avHandle, + IN uint32 count + ) +{ + AV_WRAP *pAvWrap; + FSTATUS status = FSUCCESS; + + _DBG_ENTER_FUNC(IbAvTrackerSubtractRef); + ASSERT(avHandle); + SpinLockAcquire(&pTracker->lock); + pAvWrap = IbAvTrackerFindAV(pTracker, avHandle); + if (! pAvWrap) { + status = FNOT_FOUND; + goto unlock; + } + if (0 == AtomicSubtract(&pAvWrap->refCount, count)) { + /* last reference removed, destroy AV and wrapper */ + ASSERT(pAvWrap != pTracker->currentAV); + QListRemoveItem(&pTracker->avList, &pAvWrap->listItem); + IbAvTrackerDestroyAV(pAvWrap); + } +unlock: + SpinLockRelease(&pTracker->lock); + _DBG_LEAVE_FUNC(); + return status; +} + +/*++ + +Routine Description + Av tracker routine which can be used for iba_sd_join_mcgroup callback + +Input: + pContext: AV tracker object to act on + Status: as provided from SD_MULTICAST_CALLBACK + State: as provided from SD_MULTICAST_CALLBACK + pMcMemberRecord: as provided from SD_MULTICAST_CALLBACK + +Output: + None + +Additional Information: + If the given AV is not already in the tracker, this fails + If reference count reaches 0, AV is removed from tracker and destroyed + +--*/ +void +IbAvTrackerMulticastCallback( + IN void *pContext, + IN FSTATUS Status, + IN MC_GROUP_STATE State, + IN IB_MCMEMBER_RECORD *pMcMemberRecord + ) +{ + AV_TRACKER *pTracker = (AV_TRACKER*)pContext; + + _DBG_ENTER_FUNC(IbAvTrackerMulticastCallback); + switch (State) { + case MC_GROUP_STATE_JOIN_FAILED: + _DBG_WARN(("Multicast join failed: MGID 0x%016"PRIx64":0x%016"PRIx64": %s (%d)\n", + pMcMemberRecord->RID.MGID.AsReg64s.H, + pMcMemberRecord->RID.MGID.AsReg64s.L, + _DBG_PTR(iba_fstatus_msg(Status)), Status)); + IbAvTrackerClearCurrent(pTracker); + break; + case MC_GROUP_STATE_AVAILABLE: + { + IB_ADDRESS_VECTOR av; + IB_HANDLE avHandle; + + _DBG_INFO(("Multicast available: MGID 0x%016"PRIx64":0x%016"PRIx64"\n", + pMcMemberRecord->RID.MGID.AsReg64s.H, + pMcMemberRecord->RID.MGID.AsReg64s.L)); + GetAVFromMcMemberRecord(pMcMemberRecord->RID.PortGID.Type.Global.InterfaceID, pMcMemberRecord, &av); + Status = iba_create_av(pTracker->caHandle, pTracker->pdHandle, + &av, &avHandle); + if (Status != FSUCCESS) { + _DBG_ERROR(("Unable to create AV for MGID 0x%016"PRIx64":0x%016"PRIx64": %s (%d)\n", + pMcMemberRecord->RID.MGID.AsReg64s.H, + pMcMemberRecord->RID.MGID.AsReg64s.L, + _DBG_PTR(iba_fstatus_msg(Status)), Status)); + IbAvTrackerClearCurrent(pTracker); + } else { + Status = IbAvTrackerSetCurrent(pTracker, avHandle); + _DBG_ERROR(("Unable to Set Current AV for MGID 0x%016"PRIx64":0x%016"PRIx64": %s (%d)\n", + pMcMemberRecord->RID.MGID.AsReg64s.H, + pMcMemberRecord->RID.MGID.AsReg64s.L, + _DBG_PTR(iba_fstatus_msg(Status)), Status)); + } + break; + } + + case MC_GROUP_STATE_UNAVAILABLE: + _DBG_INFO(("Multicast unavailable: MGID 0x%016"PRIx64":0x%016"PRIx64"\n", + pMcMemberRecord->RID.MGID.AsReg64s.H, + pMcMemberRecord->RID.MGID.AsReg64s.L)); + IbAvTrackerClearCurrent(pTracker); + break; + default: + _DBG_ERROR(("Unexpected multicast callback state: %d\n", State)); + } + _DBG_LEAVE_FUNC(); +} diff --git a/IbAccess/Common/Ibt/Vca/ibt_utils.c b/IbAccess/Common/Ibt/Vca/ibt_utils.c new file mode 100644 index 0000000..818d3db --- /dev/null +++ b/IbAccess/Common/Ibt/Vca/ibt_utils.c @@ -0,0 +1,1192 @@ +/* BEGIN_ICS_COPYRIGHT6 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT6 ****************************************/ + +// Common utility functions shared between user and kernel mode + +#include "imemory.h" +#include "ib_debug.h" +#include "ib_debug_osd.h" +#include "ib_generalServices.h" + +#include "precomp.h" +#define ALLOC_TAG VCA_MEM_TAG + +/*++ + +Routine Description + get the GUIDs of all the CAs on this host. + Allocates memory for the required size + caller must MemoryDeallocate(*CaGuidList) + +Input: + CaGuidList: Points to array where CaGuids are to be returned + CaCount: this is where the count of CA s to be returned + +Output: + status of the operation + +--*/ +FSTATUS +iba_get_caguids_alloc( + uint32 *CaCount, + EUI64 **CaGuidList + ) +{ + FSTATUS Status; + + _DBG_ENTER_FUNC(iba_get_caguids_alloc); + + if ( CaCount == NULL || CaGuidList == NULL ) + { + _DBG_ERROR(("null list ptr\n")); + Status = FINVALID_PARAMETER; + goto done; + } + + // First find out the size of memory needed + *CaCount = 0; + *CaGuidList = NULL; + Status = iba_get_caguids(CaCount, NULL); + if (Status != FINSUFFICIENT_MEMORY) { + _DBG_INFO(("Unexpected error from GetCaGuids\n")); + goto done; + } + + if (*CaCount <= 0) { + _DBG_INFO(("No CA reported by GetCaGuids\n")); + Status = FSUCCESS; + goto done; + } + + *CaGuidList = (EUI64*)MemoryAllocate(*CaCount * sizeof(EUI64), FALSE, ALLOC_TAG); + if (*CaGuidList == NULL) { + _DBG_ERROR(("Cant allocate memory for getting GetCaGuids\n")); + Status =FINSUFFICIENT_RESOURCES; + goto done; + } + + // Now make the query for all CA GUIDs + Status = iba_get_caguids(CaCount, *CaGuidList); + if (Status != FSUCCESS) { + MemoryDeallocate(*CaGuidList); + _DBG_INFO(("FSTATUS 0x%x from GetCaGuids\n", Status)); + *CaGuidList = NULL; + goto done; + } + +done: + _DBG_LEAVE_FUNC(); + return Status; +} + + +// Query a Ca by Guid and allocate the CaAttributes->PortAttributesList +// as needed to complete the full query of all ports on Ca +// caller must MemoryDeallocate CaAttributes->PortAttributesList +FSTATUS +iba_query_ca_by_guid_alloc( + IN EUI64 CaGuid, + OUT IB_CA_ATTRIBUTES *CaAttributes + ) +{ + FSTATUS status; + + _DBG_ENTER_FUNC(iba_query_ca_by_guid_alloc); + + // determine size of port attributes list + CaAttributes->PortAttributesListSize = 0; + CaAttributes->PortAttributesList = NULL; + status = iba_query_ca_by_guid(CaGuid, CaAttributes); + + if (status != FSUCCESS) + { + goto done; + } + + ASSERT(CaAttributes->PortAttributesListSize > 0); + + CaAttributes->PortAttributesList = (IB_PORT_ATTRIBUTES*)MemoryAllocate( + CaAttributes->PortAttributesListSize, FALSE, ALLOC_TAG); + if (CaAttributes->PortAttributesList == NULL) + { + _DBG_ERROR(("Cannot allocate memory for port attribs, CA <0x%016"PRIx64">\n", + CaGuid)); + CaAttributes->PortAttributesListSize = 0; + status = FINSUFFICIENT_MEMORY; + goto done; + } + + // Now get the actual port attributes + status = iba_query_ca_by_guid(CaGuid, CaAttributes); + if (status != FSUCCESS) + { + MemoryDeallocate(CaAttributes->PortAttributesList); + CaAttributes->PortAttributesListSize = 0; + CaAttributes->PortAttributesList = NULL; + goto done; + } + +done: + _DBG_LEAVE_FUNC(); + return(status); +} + + +// Query a Port by Guid and allocate the PortAttributes +// as needed to complete the full query of all ports on Ca +// caller must MemoryDeallocate *PortAttributes +FSTATUS +iba_query_port_by_guid_alloc( + IN EUI64 PortGuid, + OUT IB_PORT_ATTRIBUTES **PortAttributes + ) +{ + FSTATUS status; + uint32 PortAttrSize = 0; + + _DBG_ENTER_FUNC(iba_query_port_by_guid_alloc); + + *PortAttributes = NULL; + status = iba_query_port_by_guid(PortGuid, NULL, &PortAttrSize); + if (status != FINSUFFICIENT_MEMORY) // i.e. we should get FINSUFFICIENT_MEMORY + goto done; + + *PortAttributes = (IB_PORT_ATTRIBUTES*)MemoryAllocateAndClear(PortAttrSize, FALSE, ALLOC_TAG); + if (*PortAttributes == NULL) + { + status = FINSUFFICIENT_MEMORY; + goto done; + } + + status = iba_query_port_by_guid(PortGuid, *PortAttributes, &PortAttrSize); + if (status != FSUCCESS) + { + MemoryDeallocate(*PortAttributes); + *PortAttributes = NULL; + goto done; + } + +done: + _DBG_LEAVE_FUNC(); + + return status; +} + +/* translate port number into a port Guid + * + * INPUTS: + * caGuid - CA to check against + * port - 1-n, port within CA + * if 0, 1st active port + * + * OUTPUTS: + * *pPortGuid - port guid for specified port + * *pCaAttributes - attributes for CA, + * caller must MemoryDeallocate pCaAttributes->PortAttributesList + * *ppPortAtributes - attributes for port, caller must MemoryDeallocate + * *pPortCount - number of ports in CA + * + * RETURNS: + * FNOT_FOUND - *pPortCount still output + */ +FSTATUS iba_get_ca_portguid( + IN EUI64 caGuid, + IN uint32 port, + OUT EUI64 *pPortGuid OPTIONAL, + OUT IB_CA_ATTRIBUTES *pCaAttributes OPTIONAL, + OUT IB_PORT_ATTRIBUTES **ppPortAttributes OPTIONAL, + OUT uint32 *pPortCount OPTIONAL + ) +{ + IB_CA_ATTRIBUTES caAttribs; + IB_PORT_ATTRIBUTES *pPortAttribs; + FSTATUS status = FSUCCESS; + unsigned i; + + _DBG_ENTER_FUNC(iba_get_ca_portguid); + + _DBG_INFO(("iba_get_ca_portguid: Ca 0x%016"PRIx64"\n", caGuid)); + + memset(&caAttribs, 0, sizeof(caAttribs)); + caAttribs.PortAttributesList = NULL; + + status = iba_query_ca_by_guid_alloc(caGuid, &caAttribs); + if (status != FSUCCESS) + goto done; + + if (pPortCount) + *pPortCount = caAttribs.Ports; + + if (port > caAttribs.Ports) + { + // not on this CA + status = FNOT_FOUND; + goto done; + } + + pPortAttribs = caAttribs.PortAttributesList; + for (i = 1; i <= caAttribs.Ports; ++i) + { + if (i == port + || (port == 0 && pPortAttribs->PortState >= PortStateInit)) + { + // found it + if (pCaAttributes) { + *pCaAttributes = caAttribs; + caAttribs.PortAttributesList = NULL; // skip dealloc + } + if (pPortGuid) + *pPortGuid = pPortAttribs->GUID; + + if ( ppPortAttributes) { + uint32 size = IbPortAttributesSize(pPortAttribs); + *ppPortAttributes = (IB_PORT_ATTRIBUTES*)MemoryAllocate2AndClear( + size, IBA_MEM_FLAG_PREMPTABLE, ALLOC_TAG); + if (! *ppPortAttributes) { + status = FINSUFFICIENT_MEMORY; + goto done; + } + IbCopyPortAttributes(*ppPortAttributes, pPortAttribs, size); + (*ppPortAttributes)->Next = NULL; + } + goto done; + } + pPortAttribs = pPortAttribs->Next; + } + status = FNOT_FOUND; // could be port==0 case with no >=INIT ports + +done: + if (caAttribs.PortAttributesList) + MemoryDeallocate(caAttribs.PortAttributesList); + _DBG_LEAVE_FUNC(); + + return status; +} + +/* translate ca/port number into a port Guid + * + * INPUTS: + * ca - system wide CA number 1-n, if 0 port is a system wide port # + * port - 1-n, if ca is 0, system wide port number, otherwise port within CA + * if 0, 1st active port + * + * OUTPUTS: + * *pCaGuid - ca guid for specified port + * *pPortGuid - port guid for specified port + * *pCaAttributes - attributes for CA, + * caller must MemoryDeallocate pCaAttributes->PortAttributesList + * *ppPortAtributes - attributes for port, caller must MemoryDeallocate + * *pCaCount - number of CA in system + * *pPortCount - number of ports in system or CA (depends on ca input) + * + * RETURNS: + * FNOT_FOUND - *pCaCount and *pPortCount still output + * if ca == 0, *pPortCount = number of ports in system + * if ca < *pCaCount, *pPortCount = number of ports in CA + * otherwise *pPortCount will be 0 + * + */ +FSTATUS iba_get_portguid( + IN uint32 ca, + IN uint32 port, + OUT EUI64 *pCaGuid OPTIONAL, + OUT EUI64 *pPortGuid OPTIONAL, + OUT IB_CA_ATTRIBUTES *pCaAttributes OPTIONAL, + OUT IB_PORT_ATTRIBUTES **ppPortAttributes OPTIONAL, + OUT uint32 *pCaCount OPTIONAL, + OUT uint32 *pPortCount OPTIONAL + ) +{ + EUI64 *caGuids = NULL; + uint32 caCount; + FSTATUS status = FSUCCESS; + uint8 i; + + _DBG_ENTER_FUNC(iba_get_portguid); + + _DBG_INFO(("iba_get_portguid: ca %u, port %u\n", ca, port)); + + status = iba_get_caguids_alloc(&caCount, &caGuids); + if ((status != FSUCCESS) || (caGuids == NULL)) + goto done; + if (pCaCount) + *pCaCount = caCount; + if (pPortCount) + *pPortCount = 0; + + if (caCount == 0) + { + // no CAs found + status = FNOT_FOUND; + goto done; + } + + if (ca > 0) + { + // look for port number in a specific CA + if (ca > caCount) + { + // ca number too large + status = FNOT_FOUND; + goto done; + } + + status = iba_get_ca_portguid(caGuids[ca-1], port, pPortGuid, + pCaAttributes, ppPortAttributes, pPortCount); + if (FSUCCESS != status) + goto done; + if (pCaGuid) + *pCaGuid = caGuids[ca-1]; + } else { + // system wide port number encoding + uint32 totalPorts = 0; + status = FNOT_FOUND; + + for (i = 0; i < caCount; i++) + { + EUI64 portGuid; + uint32 portCount; + FSTATUS status2; + + status2 = iba_get_ca_portguid(caGuids[i], + port > totalPorts?port-totalPorts:port, + &portGuid, pCaAttributes, + ppPortAttributes, &portCount); + if (FNOT_FOUND == status && FSUCCESS == status2) { + // found the desired port + if (pPortGuid) + *pPortGuid = portGuid; + if (pCaGuid) + *pCaGuid = caGuids[i]; + ppPortAttributes = NULL; // avoid overwritting on next loop + pCaAttributes = NULL; // avoid overwritting on next loop + port = 1; // a simple valid value for subsequent loops + // we keep looping to count totalPorts + } + if (FNOT_FOUND != status2) { + status = status2; + goto done; + } + totalPorts += portCount; + } + if (pPortCount) + *pPortCount = totalPorts; + } +done: + if (caGuids) + MemoryDeallocate(caGuids); + + _DBG_LEAVE_FUNC(); + return status; +} + +/* format an error message when iba_get_portguid returns FNOT_FOUND + * + * INPUTS: + * ca, port - inputs provided to failed call to iba_get_portguid + * CaCount, PortCount - outputs returned by failed call to iba_get_portguid + * + * RETURNS: + * string formatted with error message. This is a pointer into a static + * string which will be invalidated upon next call to this function. + */ +const char* +iba_format_get_portguid_error( + IN uint32 ca, + IN uint32 port, + IN uint32 caCount, + IN uint32 portCount + ) +{ + static char errstr[80]; + + _DBG_ENTER_FUNC(iba_format_get_portguid_error); + if (ca) { + if (portCount) { + if (port) { + sprintf(errstr, "Invalid port number: %u, Ca %u only has %u Ports", + port, ca, portCount); + } else { + sprintf(errstr, "No Active Ports found on Ca %u", ca); + } + } else { + sprintf(errstr,"Invalid CA number: %u, only have %u CAs", + ca, caCount); + } + } else { + if (portCount) { + if (port) { + sprintf(errstr, "Invalid port number: %u, System only has %u Ports", + port, portCount); + } else { + sprintf(errstr, "No Active ports found in System"); + } + } else { + sprintf(errstr,"No CAs found in System"); + } + } + _DBG_LEAVE_FUNC(); + return errstr; +} + +// search Ports of a given CA to find the Port with the matching GID +// if PortAtttibutes is not NULL, allocated port attributes are +// returned and caller must MemoryDeallocate(*PortAttributes) +FSTATUS +iba_find_ca_gid( + IN const IB_GID *pGid, + IN EUI64 CaGuid, + OUT OPTIONAL EUI64 *pPortGuid, + OUT OPTIONAL uint8 *pGidIndex, + OUT OPTIONAL IB_PORT_ATTRIBUTES **PortAttributes, + OUT OPTIONAL uint8 *pLocalCaAckDelay + ) +{ + FSTATUS status; + IB_CA_ATTRIBUTES *CaAttributes = NULL; + + if (pLocalCaAckDelay) + *pLocalCaAckDelay = 0; + status = iba_find_ca_gid2(pGid, CaGuid, pPortGuid, pGidIndex, + PortAttributes, &CaAttributes); + if (status == FSUCCESS) { + if (pLocalCaAckDelay) + *pLocalCaAckDelay = CaAttributes->LocalCaAckDelay; + MemoryDeallocate(CaAttributes); + } + return status; +} + +// search Ports of a given CA to find the Port with the matching GID +// if PortAtttibutes is not NULL, allocated port attributes are +// returned and caller must MemoryDeallocate(*PortAttributes) +// if CaAttributes is not NULL, allocated CA attributes are +// returned and caller must MemoryDeallocate(*CaAttributes) +FSTATUS +iba_find_ca_gid2( + IN const IB_GID *pGid, + IN EUI64 CaGuid, + OUT OPTIONAL EUI64 *pPortGuid, + OUT OPTIONAL uint8 *pGidIndex, + OUT OPTIONAL IB_PORT_ATTRIBUTES **PortAttributes, + OUT OPTIONAL IB_CA_ATTRIBUTES **CaAttributes + ) +{ + IB_CA_ATTRIBUTES *caAttr = NULL; + IB_PORT_ATTRIBUTES *portAttr; + FSTATUS status; + unsigned i; + int32 index; + + _DBG_ENTER_FUNC(iba_find_ca_gid); + + if (pGidIndex) + *pGidIndex = 0; + if (pPortGuid) + *pPortGuid = 0; + if (PortAttributes) + *PortAttributes = NULL; + if (CaAttributes) + *CaAttributes = NULL; + + caAttr = (IB_CA_ATTRIBUTES*)MemoryAllocate(sizeof(*caAttr), FALSE, ALLOC_TAG); + if (caAttr == NULL) + { + status = FINSUFFICIENT_MEMORY; + goto done; + } + + status = iba_query_ca_by_guid_alloc(CaGuid, caAttr); + if (status != FSUCCESS) + goto free; + + status = FNOT_FOUND; + portAttr = caAttr->PortAttributesList; + for (i=0; i< caAttr->Ports; ++i, portAttr = portAttr->Next) + { + index = GetGidIndex(portAttr, pGid); + if (index != -1) + { + // found it + status = FSUCCESS; + if (pGidIndex) + *pGidIndex = (uint16)index; + if (pPortGuid) + *pPortGuid = portAttr->GUID; + if (PortAttributes) + { + size_t size = IbPortAttributesSize(portAttr); + *PortAttributes = (IB_PORT_ATTRIBUTES*)MemoryAllocate(size, FALSE, ALLOC_TAG); + if (*PortAttributes == NULL) + { + status = FINSUFFICIENT_MEMORY; + } else { + IbCopyPortAttributes(*PortAttributes, portAttr, size); + (*PortAttributes)->Next = NULL; + } + } + break; + } + } + MemoryDeallocate(caAttr->PortAttributesList); + caAttr->PortAttributesListSize = 0; + caAttr->PortAttributesList = NULL; +free: + if (status == FSUCCESS && CaAttributes) + *CaAttributes = caAttr; + else + MemoryDeallocate(caAttr); +done: + _DBG_LEAVE_FUNC(); + + return status; +} + +// search all Ports of all CAs to find the Port with the matching GID +// if PortAtttibutes is not NULL, allocated port attributes are +// returned and caller must MemoryDeallocate(*PortAttributes) +// if CaAttributes is not NULL, allocated CA attributes are +// returned and caller must MemoryDeallocate(*CaAttributes) +FSTATUS iba_find_gid( + IN const IB_GID *pGid, + OUT OPTIONAL EUI64 *pCaGuid, + OUT OPTIONAL EUI64 *pPortGuid, + OUT OPTIONAL uint8 *pGidIndex, + OUT OPTIONAL IB_PORT_ATTRIBUTES **PortAttributes, + OUT OPTIONAL IB_CA_ATTRIBUTES **CaAttributes + ) +{ + uint32 CaCount; + EUI64 *CaGuidList = NULL; + FSTATUS status; + uint32 i; + + _DBG_ENTER_FUNC(iba_find_gid); + + status = iba_get_caguids_alloc(&CaCount, &CaGuidList); + if ((status != FSUCCESS) || (CaGuidList == NULL)) + goto done; + + for (i=0; iRequestState = QPStateInit; + QpAttrInit->PortGUID = PortGuid; + QpAttrInit->PkeyIndex = PkeyIndex; + QpAttrInit->AccessControl = AccessControl; + QpAttrInit->Attrs = (IB_QP_ATTR_PORTGUID|IB_QP_ATTR_PKEYINDEX + | IB_QP_ATTR_ACCESSCONTROL); + if (Qkey) { // only valid for RD QPs + QpAttrInit->Qkey = Qkey; + QpAttrInit->Attrs |= IB_QP_ATTR_QKEY; + } + status = iba_modify_qp(QpHandle, QpAttrInit, QpAttributes); + MemoryDeallocate(QpAttrInit); +done: + _DBG_LEAVE_FUNC(); + return status; +} + +//initialize a previously created UD queue pair. +FSTATUS iba_ready_ud_qp( + IN IB_HANDLE QpHandle, + IN EUI64 PortGuid, + IN uint16 PkeyIndex, + IN IB_Q_KEY Qkey, + OUT OPTIONAL IB_QP_ATTRIBUTES_QUERY *QpAttributes + ) +{ + FSTATUS status; + IB_QP_ATTRIBUTES_MODIFY *QpAttrInit; + + static IB_QP_ATTRIBUTES_MODIFY QpAttrUdRtr = { + RequestState: QPStateReadyToRecv, + Attrs:0 + }; + static IB_QP_ATTRIBUTES_MODIFY QpAttrUdRts = { + RequestState: QPStateReadyToSend, + Attrs:IB_QP_ATTR_SENDPSN, + SendQDepth: 0, + RecvQDepth:0, + SendDSListDepth:0, + RecvDSListDepth:0, + PortGUID:0, + Qkey:0, + PkeyIndex:0, + AccessControl: {0}, + RecvPSN:0, + DestQPNumber:0, + PathMTU:0, + Reserved1:0, + Reserved2:0, + DestAV: {0}, + ResponderResources:0, + MinRnrTimer:0, + Reserved3:0, + AltPortGUID:0, + AltDestAV:{0}, + AltPkeyIndex:0, + Reserved4:0, + SendPSN:1 // not critical since no checking on receiver + }; + + _DBG_ENTER_FUNC(iba_init_qp); + QpAttrInit = (IB_QP_ATTRIBUTES_MODIFY*)MemoryAllocate2AndClear( + sizeof(*QpAttrInit), IBA_MEM_FLAG_PREMPTABLE|IBA_MEM_FLAG_SHORT_DURATION, ALLOC_TAG); + if (! QpAttrInit) { + status = FINSUFFICIENT_MEMORY; + goto done; + } + QpAttrInit->RequestState = QPStateInit; + QpAttrInit->PortGUID = PortGuid; + QpAttrInit->PkeyIndex = PkeyIndex; + QpAttrInit->Qkey = Qkey; + QpAttrInit->Attrs = (IB_QP_ATTR_PORTGUID|IB_QP_ATTR_PKEYINDEX + | IB_QP_ATTR_QKEY); + status = iba_modify_qp(QpHandle, QpAttrInit, QpAttributes); + MemoryDeallocate(QpAttrInit); + + if (status == FSUCCESS) + status = iba_modify_qp(QpHandle, &QpAttrUdRtr, QpAttributes); + + if (status == FSUCCESS) + status = iba_modify_qp(QpHandle, &QpAttrUdRts, QpAttributes); +done: + _DBG_LEAVE_FUNC(); + return status; +} + +// Reset and Reinitialize a previously initialized QP +FSTATUS iba_reinit_qp( + IN IB_HANDLE QpHandle, + OUT OPTIONAL IB_QP_ATTRIBUTES_QUERY *QpAttributes + ) +{ + FSTATUS status; + IB_QP_ATTRIBUTES_QUERY *QpAttrQuery = NULL; + IB_QP_ATTRIBUTES_MODIFY *QpAttrInit = NULL; + void* context; + + _DBG_ENTER_FUNC(iba_reinit_qp); + QpAttrQuery = (IB_QP_ATTRIBUTES_QUERY*)MemoryAllocate2AndClear( + sizeof(*QpAttrQuery), IBA_MEM_FLAG_PREMPTABLE|IBA_MEM_FLAG_SHORT_DURATION, ALLOC_TAG); + if (! QpAttrQuery) { + status = FINSUFFICIENT_MEMORY; + goto done; + } + QpAttrInit = (IB_QP_ATTRIBUTES_MODIFY*)MemoryAllocate2AndClear( + sizeof(*QpAttrInit), IBA_MEM_FLAG_PREMPTABLE|IBA_MEM_FLAG_SHORT_DURATION, ALLOC_TAG); + if (! QpAttrInit) { + status = FINSUFFICIENT_MEMORY; + goto done; + } + + status = iba_query_qp(QpHandle, QpAttrQuery, &context); + if (status != FSUCCESS) + goto done; + + status = iba_reset_qp(QpHandle, NULL); + if (status != FSUCCESS) + goto done; + + if ((QpAttrQuery->Attrs & (IB_QP_ATTR_PORTGUID|IB_QP_ATTR_PKEYINDEX + | IB_QP_ATTR_ACCESSCONTROL)) + != (IB_QP_ATTR_PORTGUID|IB_QP_ATTR_PKEYINDEX + | IB_QP_ATTR_ACCESSCONTROL)) + { + status = FINVALID_STATE; + goto done; + } + QpAttrInit->RequestState = QPStateInit; + QpAttrInit->PortGUID = QpAttrQuery->PortGUID; + QpAttrInit->PkeyIndex = QpAttrQuery->PkeyIndex; + QpAttrInit->AccessControl = QpAttrQuery->AccessControl; + QpAttrInit->Attrs = QpAttrQuery->Attrs & (IB_QP_ATTR_PORTGUID + | IB_QP_ATTR_PKEYINDEX | IB_QP_ATTR_ACCESSCONTROL + | IB_QP_ATTR_QKEY); + if (QpAttrInit->Attrs & IB_QP_ATTR_QKEY) { + // must be RD/UD QP + QpAttrInit->Qkey = QpAttrQuery->Qkey; + } + status = iba_modify_qp(QpHandle, QpAttrInit, QpAttributes); +done: + if (QpAttrQuery) + MemoryDeallocate(QpAttrQuery); + if (QpAttrInit) + MemoryDeallocate(QpAttrInit); + _DBG_LEAVE_FUNC(); + return status; +} + +// Move a QP to the Error State +FSTATUS +iba_error_qp( + IN IB_HANDLE QpHandle, + OUT OPTIONAL IB_QP_ATTRIBUTES_QUERY *QpAttributes + ) +{ + static IB_QP_ATTRIBUTES_MODIFY qpAttr = { + RequestState: QPStateError, + Attrs: 0 + }; + + return iba_modify_qp(QpHandle, &qpAttr, QpAttributes); +} + +// Move a QP to the Send Q Drain State +FSTATUS +iba_sendq_drain_qp( + IN IB_HANDLE QpHandle, + IN boolean EnableSQDAsyncEvent, + OUT OPTIONAL IB_QP_ATTRIBUTES_QUERY *QpAttributes + ) +{ + // keep structures const so we don't need locks + static IB_QP_ATTRIBUTES_MODIFY qpAttrEnable = { + RequestState: QPStateSendQDrain, + Attrs: IB_QP_ATTR_ENABLESQDASYNCEVENT, + SendQDepth:0, + RecvQDepth:0, + SendDSListDepth:0, + RecvDSListDepth:0, + PortGUID:0, + Qkey:0, + PkeyIndex:0, + AccessControl: { 0 }, + RecvPSN:0, + DestQPNumber:0, + PathMTU:0, + Reserved1:0, + Reserved2:0, + DestAV: { 0 }, + ResponderResources:0, + MinRnrTimer:0, + Reserved3:0, + AltPortGUID:0, + AltDestAV: { 0 }, + AltPkeyIndex: 0, + Reserved4: 0, + SendPSN: 0, + InitiatorDepth: 0, + LocalAckTimeout: 0, + RetryCount: 0, + RnrRetryCount: 0, + FlowControl:FALSE, + APMState:APMStateNoTransition, + AltLocalAckTimeout:0, + EnableSQDAsyncEvent: TRUE + }; + static IB_QP_ATTRIBUTES_MODIFY qpAttrDisable = { + RequestState: QPStateSendQDrain, + Attrs: IB_QP_ATTR_ENABLESQDASYNCEVENT, + SendQDepth:0, + RecvQDepth:0, + SendDSListDepth:0, + RecvDSListDepth:0, + PortGUID:0, + Qkey:0, + PkeyIndex:0, + AccessControl: { 0 }, + RecvPSN:0, + DestQPNumber:0, + PathMTU:0, + Reserved1:0, + Reserved2:0, + DestAV: { 0 }, + ResponderResources:0, + MinRnrTimer:0, + Reserved3:0, + AltPortGUID:0, + AltDestAV: { 0 }, + AltPkeyIndex: 0, + Reserved4: 0, + SendPSN: 0, + InitiatorDepth: 0, + LocalAckTimeout: 0, + RetryCount: 0, + RnrRetryCount: 0, + FlowControl:FALSE, + APMState:APMStateNoTransition, + AltLocalAckTimeout:0, + EnableSQDAsyncEvent: FALSE + }; + + return iba_modify_qp(QpHandle, + EnableSQDAsyncEvent?&qpAttrEnable:&qpAttrDisable, + QpAttributes); +} + +static const char* const WrOpText[] = { + "WROpSend", + "WROpRdmaWrite", + "WROpRecv", + "WROpRdmaRead", + "WROpMWBind", + "WROpFetchAdd", + "WROpCompareSwap", + "WROpRecvUnsignaled" +}; + +const char* iba_wr_op_msg(IB_WR_OP wr_op) +{ + if (wr_op < 0 || wr_op >= (int)(sizeof(WrOpText)/sizeof(char*))) + return "Unknown WR OP"; + else + return WrOpText[wr_op]; +} + +static const char* const WcStatusText[] = { + "WRStatusSuccess", + "WRStatusLocalLength", + "WRStatusLocalOp", + "WRStatusLocalProtection", + "WRStatusTransport", + "WRStatusWRFlushed", + "WRStatusRemoteConsistency", + "WRStatusMWBind", + "WRStatusRemoteAccess", + "WRStatusRemoteOp", + "WRStatusRemoteInvalidReq", + "WRStatusSeqErrRetry", + "WRStatusRnRRetry", + "WRStatusTimeoutRetry", + "WRStatusBadResponse", + "WRStatusInvalidLocalEEC", + "WRStatusInvalidLocalEECState", + "WRStatusInvalidLocalEECOp", + "WRStatusLocalRDDViolation", + "WRStatusRemoteInvalidRDReq", + "WRStatusLocalAccess", + "WRStatusRemoteAborted" +}; + +const char* iba_wc_status_msg(IB_WC_STATUS wc_status) +{ + if (wc_status < 0 || wc_status >= (int)(sizeof(WcStatusText)/sizeof(char*))) + return "Unknown WRStatus"; + else + return WcStatusText[wc_status]; +} + +static const char* const WcTypeText[] = { + "WCTypeSend", + "WCTypeRdmaWrite", + "WCTypeRecv", + "WCTypeRdmaRead", + "WCTypeMWBind", + "WCTypeFetchAdd", + "WCTypeCompareSwap" +}; + +const char* iba_wc_type_msg(IB_WC_TYPE wc_type) +{ + if (wc_type < 0 || wc_type >= (int)(sizeof(WcTypeText)/sizeof(char*))) + return "Unknown WCType"; + else + return WcTypeText[wc_type]; +} + +static const char* const WcRemoteOpText[] = { + "WCRemoteOpSend", + "WCRemoteOpRdmaWrite" +}; + +const char* iba_wc_remote_op_msg(IB_WC_REMOTE_OP wc_remote_op) +{ + if (wc_remote_op < 0 || wc_remote_op >= (int)(sizeof(WcRemoteOpText)/sizeof(char*))) + return "Unknown WCRemoteOp"; + else + return WcRemoteOpText[wc_remote_op]; +} + +static const char * const QpTypeText[] = { + "QPTypeReliableConnected", + "QPTypeUnreliableConnected", + "QPTypeReliableDatagram", + "QPTypeUnreliableDatagram", + "QPTypeSMI", + "QPTypeGSI", + "QPTypeRawDatagram", + "QPTypeRawIPv6", + "QPTypeRawEthertype" +}; + +const char* iba_qp_type_msg(IB_QP_TYPE qp_type) +{ + if (qp_type < 0 || qp_type >= (int)(sizeof(QpTypeText)/sizeof(char*))) + return "Unknown QpType"; + else + return QpTypeText[qp_type]; +} + +static const char * const QpStateText[] = { + "QPStateNoTransition", + "QPStateReset", + "QPStateInit", + "QPStateReadyToRecv", + "QPStateReadyToSend", + "QPStateSendQDrain", + "QPStateSendQError", + "QPStateError" +}; + +const char* iba_qp_state_msg(IB_QP_STATE qp_state) +{ + if (qp_state < 0 || qp_state >= (int)(sizeof(QpStateText)/sizeof(char*))) + return "Unknown QpState"; + else + return QpStateText[qp_state]; +} + +static const char * const QpApmStateText[] = { + "APMStateNoTransition", + "APMStateMigrated", + "APMStateRearm", + "APMStateArmed" +}; + +const char* iba_qp_apm_state_msg(IB_QP_APM_STATE qp_apm_state) +{ + if (qp_apm_state < 0 || qp_apm_state >= (int)(sizeof(QpApmStateText)/sizeof(char*))) + return "Unknown QpApmState"; + else + return QpApmStateText[qp_apm_state]; +} + +const char* iba_event_record_msg(IB_EVENT_RECORD *p_event) +{ + switch (p_event->EventType) + { + default: + return "Uknown Event"; + break; + case AsyncEventPathMigrated: + return "QP Path Migrated"; + break; + case AsyncEventEEPathMigrated: + return "EE Path Migrated"; + break; + case AsyncEventRecvQ: + switch (p_event->EventCode) + { + case IB_AE_RQ_PATH_MIG_ERR: + return "QP Path Migration Error"; + break; + case IB_AE_RQ_COMM_ESTABLISHED: + return "QP Communication Established"; + break; + case IB_AE_RQ_ERROR_STATE: + return "QP Error"; + break; + case IB_AE_RQ_WQE_ACCESS: + return "QP Local Access Violation"; + break; + default: + return "RQ Other Event"; + break; + } + break; + case AsyncEventSendQ: + switch (p_event->EventCode) + { + case IB_AE_SQ_DRAIN: + return "Send Q Drained"; + break; + default: + return "SQ Other Event"; + break; + } + break; + case AsyncEventCQ: + switch (p_event->EventCode) + { + case IB_AE_CQ_ACCESS_ERR: + return "CQ Access Error"; + break; + case IB_AE_CQ_OVERRUN: + return "CQ Overrun"; + break; + default: + return "CQ Other Event"; + break; + } + break; + case AsyncEventEE: + switch (p_event->EventCode) + { + case IB_AE_EE_PATH_MIG_ERR: + return "EEC Path Migration Error"; + break; + case IB_AE_EE_COMM_ESTABLISHED: + return "EEC Communication Established"; + break; + case IB_AE_EE_ERROR_STATE: + return "EEC Error"; + break; + default: + return "EEC Other Event"; + break; + } + break; + case AsyncEventCA: + { + return "CA Cat. Error"; + break; + } + case AsyncEventPort: + { + return "Port State Change"; + break; + } + } +} + +static const char * const MadInvalidFieldText[] = { + "Valid Field", // should not be used below + "Unsupported Class or Version", + "Unsupported Method", + "Unsupported Method/Attribute Combination", + "Reserved Invalid Field 4", + "Reserved Invalid Field 5", + "Reserved Invalid Field 6", + "Invalid Attribute or Attribute Modifier" +}; + +const char* iba_mad_status_msg(MAD_STATUS madStatus) +{ + if (madStatus.AsReg16 == MAD_STATUS_SUCCESS) + return "Success"; + else if (madStatus.S.Busy) + return "Busy"; + else if (madStatus.S.RedirectRqrd) + return "Redirection Required"; + else if (madStatus.S.InvalidField) + return MadInvalidFieldText[madStatus.S.InvalidField]; + else if (madStatus.S.ClassSpecific) + return "Class Specific Status"; + else + return "Unknown Mad Status"; +} + +// this function is useful when we have DR.s.Status which is a 15 bit bitfield +const char* iba_mad_status_msg2(uint16 madStatus) +{ + MAD_STATUS mad_status; + + mad_status.AsReg16 = madStatus; + return iba_mad_status_msg(mad_status); +} + +const char* iba_rmpp_status_msg(RMPP_STATUS rmppStatus) +{ + switch (rmppStatus) { + case RMPP_STATUS_NORMAL: + return "Normal"; + case RMPP_STATUS_RESOURCES_EXHAUSTED: + return "Resources Exhausted"; + case RMPP_STATUS_TOTAL_TIME_TOO_LONG: + return "Total Time Too Long"; + case RMPP_STATUS_INCONSISTENT_PAYLOAD_LEN: + return "Inconsistent Last and PayloadLength"; + case RMPP_STATUS_INCONSISTENT_FIRST: + return "Inconsistent First and SegmentNumber"; + case RMPP_STATUS_BAD_RMPP_TYPE: + return "Bad RMPPType"; + case RMPP_STATUS_NEW_WL_TOO_SMALL: + return "NewWindowLast Too Small"; + case RMPP_STATUS_SEGMENT_NUMBER_TOO_BIG: + return "SegmentNumber Too Big"; + case RMPP_STATUS_ILLEGAL_STATUS: + return "Illegal Status"; + case RMPP_STATUS_UNSUPPORTED_VERSION: + return "Unsupported Version"; + case RMPP_STATUS_TOO_MANY_RETRIES: + return "Too Many Retries"; + case RMPP_STATUS_UNSPECIFIED: + return "Unspecified"; + default: + if (rmppStatus >= 128 && rmppStatus <= 191) + return "Class Specific Status"; + else if (rmppStatus >= 192 && rmppStatus <= 255) + return "Vendor Specific Status"; + else + /* includes RMPP_STATUS_START_RESERVED - RMPP_STATUS_END_RESERVED */ + return "Unknown Rmpp Status"; + } +} diff --git a/IbAccess/Common/Ibt/Vca/vca_ibt.c b/IbAccess/Common/Ibt/Vca/vca_ibt.c new file mode 100644 index 0000000..fa70264 --- /dev/null +++ b/IbAccess/Common/Ibt/Vca/vca_ibt.c @@ -0,0 +1,492 @@ +/* BEGIN_ICS_COPYRIGHT4 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT4 ****************************************/ + + +#include "precomp.h" + + +// +// Forward declarations +// + +static uint32 +vcaCountCAList(void); + + +// +// +// + +FSTATUS +iba_get_caguids( + IN OUT uint32 *CaCount, + OUT EUI64 *CaGuidList + ) +{ + DEVICE_INFO *devInfo; + EUI64 *guidList = NULL, *pGuid; + uint32 caCount, count; + FSTATUS status = FSUCCESS; + + _DBG_ENTER_LVL(_DBG_LVL_PNP, iba_get_caguids); + + // CaCount may point to paged pool, so make a copy of it before + // raising IRQL. + caCount = *CaCount; + + SpinLockAcquire(&VcaGlobal.Lock); + + count = vcaCountCAList(); + + if ( caCount < count ) + { + // Return status indicating array is too small to hold list + status = FINSUFFICIENT_MEMORY; + } else { + // Array is sufficient to hold list + if ( CaGuidList == NULL ) + { + _DBG_ERROR(("null list ptr\n")); + status = FINVALID_PARAMETER; + } else if (count > 0) { + guidList = (EUI64*)MemoryAllocate2(count * sizeof(EUI64), IBA_MEM_FLAG_SHORT_DURATION, VCA_MEM_TAG); + + if ( guidList == NULL ) + { + status = FINSUFFICIENT_RESOURCES; + } else { + devInfo = VcaGlobal.DeviceList; + pGuid = guidList; + + while (devInfo != NULL) + { + *pGuid = devInfo->VpInterface.CaGUID; + pGuid++; + devInfo = devInfo->Next; + } + } + } + } + + SpinLockRelease(&VcaGlobal.Lock); + + // Always update count + *CaCount = count; + + if ( status == FSUCCESS ) + { + if (count > 0) + { + MemoryCopy(CaGuidList, guidList, count * sizeof(EUI64)); + MemoryDeallocate(guidList); + } + } + + _DBG_LEAVE_LVL(_DBG_LVL_PNP); + + return status; +} + + +// +// +// + +FSTATUS +iba_query_ca_by_guid( + IN EUI64 CaGuid, + OUT IB_CA_ATTRIBUTES *CaAttributes + ) +{ + DEVICE_INFO *devInfo; + FSTATUS status = FSUCCESS; + + _DBG_ENTER_LVL(_DBG_LVL_PNP, iba_query_ca_by_guid); + + if ( CaAttributes == NULL ) + { + _DBG_ERROR(("null attributes ptr\n")); + status = FINVALID_PARAMETER; + } else { + devInfo = vcaFindCA(CaGuid); + + if ( devInfo == NULL ) + { + status = FNOT_FOUND; + } else { + status = iba_query_ca( devInfo->VcaCaHandle, CaAttributes, NULL ); + } + } + + _DBG_LEAVE_LVL(_DBG_LVL_PNP); + + return status; +} + + + +// Get attributes of port with given PortGuid +FSTATUS +iba_query_port_by_guid( + IN EUI64 PortGuid, + OUT IB_PORT_ATTRIBUTES *PortAttributes, + IN OUT uint32 *ByteCount + ) +{ + DEVICE_INFO *devInfo; + IB_PORT_ATTRIBUTES *portAttributes = NULL; + uint32 portAttributesSize = 0; + FSTATUS status = FNOT_FOUND; + + _DBG_ENTER_LVL(_DBG_LVL_CALL, iba_query_port_by_guid); + + SpinLockAcquire(&VcaGlobal.Lock); + + for (devInfo = VcaGlobal.DeviceList; devInfo != NULL; + devInfo = devInfo->Next) + { + for ( portAttributes = devInfo->CaAttributes.PortAttributesList; + portAttributes != NULL; portAttributes = portAttributes->Next) + { + if ( portAttributes->GUID == PortGuid ) + { + portAttributesSize = IbPortAttributesSize(portAttributes); + + if ( *ByteCount < portAttributesSize ) + { + status = FINSUFFICIENT_MEMORY; + } else { + // get latest attributes + status = iba_query_ca(devInfo->VcaCaHandle, &devInfo->CaAttributes, NULL); + } + *ByteCount = portAttributesSize; + goto found; + } + } + } +found: + + if ( status == FSUCCESS ) + { + // Copy the port's attributes structure to the + // user's buffer. + if ( PortAttributes == NULL ) + { + status = FINVALID_PARAMETER; + } else { + IbCopyPortAttributes(PortAttributes, portAttributes, portAttributesSize); + PortAttributes->Next = NULL; + //MsgOut("Size=%d, CA Size = %d\n", portAttributesSize, devInfo->CaAttributes.PortAttributesListSize); + //MsgOut("GID[0]=0x%016"PRIx64":0x%016"PRIx64"\n", PortAttributes->GIDTable[0].Type.Global.SubnetPrefix, PortAttributes->GIDTable[0].Type.Global.InterfaceID); + //MsgOut("PKey[0]=0x%x\n", PortAttributes->PkeyTable[0]); + } + } + SpinLockRelease(&VcaGlobal.Lock); + + _DBG_LEAVE_LVL(_DBG_LVL_CALL); + + return status; +} + +// locate CaGuid with given PortGuid +FSTATUS +iba_get_ca_for_port( + IN EUI64 PortGuid, + OUT EUI64 *CaGuid + ) +{ + DEVICE_INFO *devInfo; + IB_PORT_ATTRIBUTES *portAttributes = NULL; + FSTATUS status = FNOT_FOUND; + + _DBG_ENTER_LVL(_DBG_LVL_CALL, iba_get_ca_for_port); + + SpinLockAcquire(&VcaGlobal.Lock); + + for (devInfo = VcaGlobal.DeviceList; devInfo != NULL; + devInfo = devInfo->Next) + { + for ( portAttributes = devInfo->CaAttributes.PortAttributesList; + portAttributes != NULL; + portAttributes = portAttributes->Next + ) + { + if ( portAttributes->GUID == PortGuid ) + { + status = FSUCCESS; + *CaGuid = devInfo->VpInterface.CaGUID; + goto found; + } + } + } +found: + SpinLockRelease(&VcaGlobal.Lock); + + _DBG_LEAVE_LVL(_DBG_LVL_CALL); + + return status; +} + +// update the CaAttributes for all CAs in VcaGlobal device list +// this will get us the latest port states +// To simplify processing in iba_select_ca, we set a high bit in the count +// to indicate if ports are inactive, in which case the given inactive +// port will be considered a high use port and we can test the bit at the end +static +FSTATUS +UpdateDeviceAttributes(void) +{ + FSTATUS status = FSUCCESS; + DEVICE_INFO *devInfo; + IB_PORT_ATTRIBUTES *portAttributes; + + _DBG_ENTER_LVL(_DBG_LVL_CALL, UpdateDeviceAttributes); + SpinLockAcquire(&VcaGlobal.Lock); + for (devInfo = VcaGlobal.DeviceList; devInfo != NULL; devInfo = devInfo->Next) + { + status = iba_query_ca(devInfo->VcaCaHandle, &devInfo->CaAttributes, NULL); + if ( status != FSUCCESS ) + { + _DBG_ERROR(("failed to query CA for port attributes\n")); + break; + } + /* assume inactive, clear flag if an active port is found */ + devInfo->CaSelectCount |= IBA_SELECT_INACTIVE; + for (portAttributes = devInfo->CaAttributes.PortAttributesList; + portAttributes != NULL; + portAttributes = portAttributes->Next + ) + { + if (portAttributes->PortState == PortStateActive) + { + devInfo->CaSelectCount &= ~IBA_SELECT_INACTIVE; + } + } + } + SpinLockRelease(&VcaGlobal.Lock); + _DBG_LEAVE_LVL(_DBG_LVL_CALL); + return status; +} + +/* + * iba_select_ca + * + * Track CA/ports being heavily used and aid in selection of least used one + * Usage models: + * pCaGuid = NULL invalid call + * *pCaGuid !=0 caller has specified a CA, API increases its count + * *pCaGuid ==0 API will recommend a CA and increase its count + * + * INPUTS: + * *pCaGuid - CA caller plans to use + * + * OUTPUTS: + * *pCaGuid - CA recommended for use (matches supplied *pCaGuid if input != 0) + * + * RETURNS: + * FNOT_FOUND - no such CA + * FINVALID_PARAMETER - invalid combination of arguments + * FINSUFFICIENT_RESOURCES - no CAs in system with active ports + * FERROR - other errors (unable to query CA attributes, etc) + */ + +FSTATUS +iba_select_ca( + IN OUT EUI64 *pCaGuid + ) +{ + FSTATUS status = FSUCCESS; + DEVICE_INFO *devInfo; + + _DBG_ENTER_LVL(_DBG_LVL_CALL, iba_select_ca); + if (! pCaGuid) + { + status = FINVALID_PARAMETER; + goto fail; + } + if (*pCaGuid == 0) { + // will need latest port states to properly select a CA + status = UpdateDeviceAttributes(); + if (FSUCCESS != status) + { + status = FERROR; + goto fail; + } + } + SpinLockAcquire(&VcaGlobal.Lock); + if (*pCaGuid != 0) { + // caller has specified a CA, find it + for (devInfo = VcaGlobal.DeviceList; + (devInfo != NULL) && (devInfo->VpInterface.CaGUID != *pCaGuid); + devInfo = devInfo->Next) + ; + if (NULL == devInfo) { + status = FNOT_FOUND; + goto unlock; + } + // devInfo is caller specified CA + devInfo->CaSelectCount++; + _DBG_INFO(("iba_select_ca for CA 0x%016"PRIx64": count=%u\n", + devInfo->VpInterface.CaGUID, devInfo->CaSelectCount)); + } else { + // caller wants us to select + DEVICE_INFO *minDevInfo = VcaGlobal.DeviceList; + + if (NULL == VcaGlobal.DeviceList) + { + status = FINSUFFICIENT_RESOURCES; + goto unlock; + } + // select CA with lowest overall use count + for (devInfo = VcaGlobal.DeviceList; devInfo != NULL; + devInfo = devInfo->Next) + { + if (devInfo->CaSelectCount < minDevInfo->CaSelectCount) + minDevInfo = devInfo; + } + devInfo = minDevInfo; // found recommended CA + if (devInfo->CaSelectCount & IBA_SELECT_INACTIVE) + { + status = FINSUFFICIENT_RESOURCES; + goto unlock; + } + devInfo->CaSelectCount++; + _DBG_INFO(("iba_select_ca picked CA 0x%016"PRIx64": count=%u\n", + devInfo->VpInterface.CaGUID, devInfo->CaSelectCount)); + *pCaGuid = devInfo->VpInterface.CaGUID; + } +unlock: + SpinLockRelease(&VcaGlobal.Lock); +fail: + _DBG_LEAVE_LVL(_DBG_LVL_CALL); + return status; +} + +/* + * iba_deselect_ca + * + * undo effects of iba_select_ca + * call should match the CaGUID from a previous iba_select_ca call + * + * INPUTS: + * CaGuid - CA output/selected via iba_select_ca + * + * OUTPUTS: + * None + * + * RETURNS: + * FNOT_FOUND - no such CA or Port, or PortGuid not within specified CA + * FINVALID_OPERATION - would result in negative use count + */ + +FSTATUS +iba_deselect_ca( + IN EUI64 CaGuid + ) +{ + FSTATUS status = FSUCCESS; + DEVICE_INFO *devInfo; + + _DBG_ENTER_LVL(_DBG_LVL_CALL, iba_deselect_ca); + if (! CaGuid) + { + status = FINVALID_PARAMETER; + goto fail; + } + SpinLockAcquire(&VcaGlobal.Lock); + for (devInfo = VcaGlobal.DeviceList; + (devInfo != NULL) && (devInfo->VpInterface.CaGUID != CaGuid); + devInfo = devInfo->Next) + ; + if (NULL == devInfo) { + status = FNOT_FOUND; + goto unlock; + } + // devInfo is caller specified CA + if (! (devInfo->CaSelectCount & ~IBA_SELECT_INACTIVE)) + { + status = FINVALID_OPERATION; + goto unlock; + } + devInfo->CaSelectCount--; + _DBG_INFO(("iba_deselect_ca CA 0x%016"PRIx64": count=%u\n", + devInfo->VpInterface.CaGUID, devInfo->CaSelectCount)); +unlock: + SpinLockRelease(&VcaGlobal.Lock); +fail: + _DBG_LEAVE_LVL(_DBG_LVL_CALL); + return status; +} + +// +// Support functions +// + +// locate device with given Guid +DEVICE_INFO * +vcaFindCA(IN EUI64 CaGuid) +{ + DEVICE_INFO *devInfo; + + _DBG_ENTER_LVL(_DBG_LVL_PNP, vcaFindCA); + + SpinLockAcquire(&VcaGlobal.Lock); + + for (devInfo = VcaGlobal.DeviceList; + (devInfo != NULL) && (devInfo->VpInterface.CaGUID != CaGuid); + devInfo = devInfo->Next) + ; + + SpinLockRelease(&VcaGlobal.Lock); + + _DBG_LEAVE_LVL(_DBG_LVL_PNP); + + return devInfo; +} + + +// count number of HFIs, caller must hold VcaGlobal.Lock +static uint32 +vcaCountCAList(void) +{ + DEVICE_INFO *devInfo; + uint32 count; + + _DBG_ENTER_LVL(_DBG_LVL_PNP, vcaCountCAList); + + count = 0; + for (devInfo = VcaGlobal.DeviceList; devInfo != NULL; + devInfo = devInfo->Next) + { + count++; + } + + _DBG_LEAVE_LVL(_DBG_LVL_PNP); + return count; +} diff --git a/IbAccess/Common/Ibt/Vca/vca_init.c b/IbAccess/Common/Ibt/Vca/vca_init.c new file mode 100644 index 0000000..2b432c4 --- /dev/null +++ b/IbAccess/Common/Ibt/Vca/vca_init.c @@ -0,0 +1,506 @@ +/* BEGIN_ICS_COPYRIGHT4 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT4 ****************************************/ + +#ifdef IB_DEBUG +#define ATOMIC_TEST 1 // perform tests of Atomics +#endif + +#include "precomp.h" + + +// +// Forward declarations +// + +FSTATUS +vcaResourceInit( + IN DEVICE_INFO *DevInfo + ); + +FSTATUS +vcaResourceFree( + IN DEVICE_INFO *DevInfo + ); + + + +#ifdef ALLOC_PRAGMA +#pragma alloc_text(PAGE, vcaResourceInit) +#pragma alloc_text(PAGE, vcaResourceFree) +#endif + + +// +// Globals +// + +VCA_GLOBAL VcaGlobal = +{ + NULL, + {} +}; + +#ifdef ICS_LOGGING +_IB_DBG_PARAM_BLOCK( (_DBG_LVL_FATAL | _DBG_LVL_ERROR), \ + _DBG_BREAK_DISABLE, VCA_MEM_TAG, "Vca", MOD_VCA, Vca); +#else +_IB_DBG_PARAM_BLOCK( (_DBG_LVL_FATAL | _DBG_LVL_ERROR), \ + _DBG_BREAK_DISABLE, VCA_MEM_TAG, "Vca"); +#endif +IBT_COMPONENT_INFO ComponentInfo[IbtMaxComponents]; + + +// +// The components of the IBT to be loaded. The structure is initialized in the +// platform specific code. +// + +extern IBT_LOAD ComponentLoad[]; + + +// +// Dummy callback routines for VCA internally allocated resources +// + +void +vcaCompletionCallback( + IN void *CaContext, + IN void *CqContext + ) +{ +} + +void +vcaAsyncEventCallback( + IN void *CaContext, + IN IB_EVENT_RECORD *EventRecord + ) +{ +} + + +// +// Perform initialization of the VCA for a new Channel Adapter +// + +FSTATUS +vcaInitCA( + IN DEVICE_INFO *DevInfo + ) +{ + int32 i; + FSTATUS status = FSUCCESS; + + _DBG_ENTER_EXT(_DBG_LVL_PNP, vcaInitCA, == PASSIVE); + + status = vcaResourceInit(DevInfo); + if (FSUCCESS != status) + goto failresource; + + status = vcaAddCA(DevInfo); + if (FSUCCESS != status) + goto failadd; + + for (i = 0; iVpInterface.CaGUID, + &DevInfo->ComponentCAContexts[i]); + if ( status != FSUCCESS ) + goto failcomp; + } + } + +done: + _DBG_LEAVE_EXT(_DBG_LVL_PNP); + + return status; + +failcomp: + /* i= component which failed */ + // in reverse order of Init + for (--i; i >= 0; i--) + { + if ( ComponentInfo[i].RemoveDevice != NULL ) + { + (void)(ComponentInfo[i].RemoveDevice)(DevInfo->VpInterface.CaGUID, + DevInfo->ComponentCAContexts[i]); + } + } + vcaRemoveCA(DevInfo); +failadd: + vcaResourceFree(DevInfo); +failresource: + goto done; +} + + +// +// +// Unwind from vcaInitCA's initialization of the VCA for a Channel Adapter +// + +FSTATUS +vcaFreeCA( + IN DEVICE_INFO *DevInfo + ) +{ + int i; + FSTATUS status = FSUCCESS; + + _DBG_ENTER_EXT(_DBG_LVL_PNP, vcaFreeCA, == PASSIVE); + + // in reverse order of Init + for (i = IbtMaxComponents-1; i >= 0; i--) + { + if ( ComponentInfo[i].RemoveDevice != NULL ) + { + status = (ComponentInfo[i].RemoveDevice)(DevInfo->VpInterface.CaGUID, + DevInfo->ComponentCAContexts[i]); + if (FSUCCESS != status) + break; + } + } + + // Free internal resources allocated on device and remove from the global + // device list. + vcaRemoveCA(DevInfo); + vcaResourceFree(DevInfo); + + _DBG_LEAVE_EXT(_DBG_LVL_PNP); + + return status; +} + + +// +// Fill out fields in DEVICE_INFO +// + +// this is called before adding the DevInfo to the global list +// it completes initialization of DevInfo Ca handle, and attributes +// it also ensures the CA has no port guids which duplicate existing port guids +FSTATUS +vcaResourceInit( + IN DEVICE_INFO *DevInfo + ) +{ + FSTATUS status = FSUCCESS; + IB_PORT_ATTRIBUTES *portAttributes; + + _DBG_ENTER_EXT(_DBG_LVL_PNP, vcaResourceInit, == PASSIVE); + + status = vcaOpenCa(DevInfo, vcaCompletionCallback, vcaAsyncEventCallback, + &DevInfo, &DevInfo->VcaCaHandle); + if ( status != FSUCCESS ) + { + _DBG_ERROR(("failed to open CA\n")); + goto failopen; + } + status = SetCAInternal(DevInfo->VcaCaHandle); + if ( status != FSUCCESS ) + { + _DBG_ERROR(("failed to set CA as Internal\n")); + goto failinternal; + } + + DevInfo->CaAttributes.PortAttributesListSize = 0; + DevInfo->CaAttributes.PortAttributesList = NULL; + status = iba_query_ca(DevInfo->VcaCaHandle, &DevInfo->CaAttributes, NULL); + if ( status != FSUCCESS ) + { + _DBG_ERROR(("failed to query CA\n")); + goto failquery; + } + if ( 0 == DevInfo->CaAttributes.Ports) + { + _DBG_ERROR(("CA reports No Ports\n")); + goto failquery; + } + if (0 == DevInfo->CaAttributes.PortAttributesListSize) + { + _DBG_ERROR(("CA reports No Port Attributes\n")); + goto failquery; + } + DevInfo->CaAttributes.PortAttributesList = + (IB_PORT_ATTRIBUTES*)MemoryAllocate2AndClear( + DevInfo->CaAttributes.PortAttributesListSize, + IBA_MEM_FLAG_PREMPTABLE, VCA_MEM_TAG); + if (! DevInfo->CaAttributes.PortAttributesList) + { + _DBG_ERROR(("failed to allocate memory for CA port attributes\n")); + status = FINSUFFICIENT_MEMORY; + goto failportalloc; + } + status = iba_query_ca(DevInfo->VcaCaHandle, &DevInfo->CaAttributes, NULL); + if ( status != FSUCCESS ) + { + _DBG_ERROR(("failed to query CA for port attributes\n")); + goto failqueryports; + } + + // make sure all the port GUIDs are unique + for ( portAttributes = DevInfo->CaAttributes.PortAttributesList; + portAttributes != NULL; + portAttributes = portAttributes->Next + ) + { + EUI64 caGuid; + + if (FSUCCESS == iba_get_ca_for_port(portAttributes->GUID, &caGuid)) + { + _DBG_ERROR(("Attempt to add CA 0x%016"PRIx64" with duplicate Port GUID: 0x%016"PRIx64"\n", + DevInfo->VpInterface.CaGUID, portAttributes->GUID)); + status = FDUPLICATE; + goto dupport; + } + } + +done: + _DBG_LEAVE_EXT(_DBG_LVL_PNP); + return status; + +dupport: +failqueryports: + MemoryDeallocate(DevInfo->CaAttributes.PortAttributesList); +failportalloc: +failquery: + DevInfo->CaAttributes.PortAttributesList = NULL; + DevInfo->CaAttributes.PortAttributesListSize = 0; +failinternal: + (void)iba_close_ca(DevInfo->VcaCaHandle); +failopen: + goto done; +} + + +// +// Free fields in DEVICE_INFO initialized by vcaResourceInit +// + +FSTATUS +vcaResourceFree( + IN DEVICE_INFO *DevInfo + ) +{ + FSTATUS status = FSUCCESS; + + _DBG_ENTER_EXT(_DBG_LVL_PNP, vcaResourceFree, == PASSIVE); + + ASSERT(DevInfo->CaAttributes.PortAttributesList); + MemoryDeallocate(DevInfo->CaAttributes.PortAttributesList); + + status = iba_close_ca(DevInfo->VcaCaHandle); + if ( status != FSUCCESS ) + { + _DBG_ERROR(("failed to close CA\n")); + } + + _DBG_LEAVE_EXT(_DBG_LVL_PNP); + + return status; +} + + +// +// +// + +FSTATUS +vcaLoad(EUI64 SystemImageGUID) +{ + int i; + FSTATUS status = FSUCCESS; + + _TRC_REGISTER(); + + // + // Initialize the lock on the device list + // + + SpinLockInitState(&VcaGlobal.Lock); + SpinLockInit(&VcaGlobal.Lock); + VcaGlobal.SystemImageGUID = SystemImageGUID; + + // Call load functions for each component of the IB Transport + MemoryClear(ComponentInfo, sizeof(IBT_COMPONENT_INFO) * IbtMaxComponents ); + + for (i = 0; i < IbtMaxComponents; i++) + { + if ( ComponentLoad[i] != NULL ) + { + status = (*ComponentLoad[i])(&ComponentInfo[i]); + + if ( status != FSUCCESS ) + { + break; + } + } + } + + if (status != FSUCCESS) + { + // Unload in reverse order of load + for (i = IbtMaxComponents-1; i >= 0; i--) + { + if (ComponentInfo[i].Unload != NULL) + { + (*ComponentInfo[i].Unload)(); + } + } + SpinLockDestroy(&VcaGlobal.Lock); + } + +#ifdef ATOMIC_TEST + // simple test of Atomic implementation + AtomicRunTest(); +#endif + return status; +} + + +void +vcaUnload() +{ + int i; + + _TRC_UNREGISTER(); + + // Unload in reverse order of load + for (i = IbtMaxComponents-1; i >= 0; i--) + { + if (ComponentInfo[i].Unload != NULL) + { + (*ComponentInfo[i].Unload)(); + } + } + SpinLockDestroy(&VcaGlobal.Lock); +} + + +FSTATUS +vcaAddCA(IN DEVICE_INFO *DevInfo) +{ + DEVICE_INFO *p; + FSTATUS status = FSUCCESS; + + _DBG_ENTER_EXT(_DBG_LVL_PNP, vcaAddCA, == PASSIVE); + + if (! DevInfo->VpInterface.PollAndRearmCQ) + DevInfo->VpInterface.PollAndRearmCQ = default_poll_and_rearm_cq; + + // Insert to tail of list + SpinLockAcquire(&VcaGlobal.Lock); + DevInfo->Next = NULL; + if ((p = VcaGlobal.DeviceList) == NULL) { + VcaGlobal.DeviceList = DevInfo; + } else { + while (TRUE) { + if (p->VpInterface.CaGUID == DevInfo->VpInterface.CaGUID) + { + _DBG_ERROR(("Attempt to add CA with duplicate CA GUID: 0x%016"PRIx64"\n", DevInfo->VpInterface.CaGUID)); + status = FDUPLICATE; + break; + } + if (p->Next == NULL) + break; + p = p->Next; + } + if (FSUCCESS == status) + { + ASSERT(p->Next == NULL); + p->Next = DevInfo; + } + } + SpinLockRelease(&VcaGlobal.Lock); + + _DBG_LEAVE_EXT(_DBG_LVL_PNP); + return status; +} + + +void +vcaRemoveCA(IN DEVICE_INFO *DevInfo) +{ + DEVICE_INFO *curDevInfo; + DEVICE_INFO *prevDevInfo; + + _DBG_ENTER_EXT(_DBG_LVL_PNP, vcaRemoveCA, == PASSIVE); + + SpinLockAcquire(&VcaGlobal.Lock); + + curDevInfo = VcaGlobal.DeviceList; + prevDevInfo = NULL; + + while ( curDevInfo != NULL ) + { + if ( curDevInfo == DevInfo ) + { + // Found CA to remove + if ( prevDevInfo ) + { + // CA is not at head of list, remove from within list + prevDevInfo->Next = curDevInfo->Next; + } else { + // CA head of list, remove from head + VcaGlobal.DeviceList = curDevInfo->Next; + } + break; + } + + // Traverse to next CA in list + prevDevInfo = curDevInfo; + curDevInfo = curDevInfo->Next; + } + + SpinLockRelease(&VcaGlobal.Lock); + + _DBG_LEAVE_EXT(_DBG_LVL_PNP); +} + +/* initialize the SystemImage Guid as needed. + * returns the SystemImageGuid, if the system image guid was not + * previously initialized, it uses the CaGuid + * This routine is intended for use within Verbs Providers + */ +EUI64 +VcaSystemImageGuid(IN EUI64 CaGuid) +{ + _DBG_ENTER_LVL(_DBG_LVL_PNP, VcaSystemImageGUID); + + SpinLockAcquire(&VcaGlobal.Lock); + + if (! VcaGlobal.SystemImageGUID) + VcaGlobal.SystemImageGUID = CaGuid; + SpinLockRelease(&VcaGlobal.Lock); + + /* safe outside lock since once set, won't change */ + return VcaGlobal.SystemImageGUID; +} diff --git a/IbAccess/Common/Ibt/Vca/vca_main.h b/IbAccess/Common/Ibt/Vca/vca_main.h new file mode 100644 index 0000000..dc9711a --- /dev/null +++ b/IbAccess/Common/Ibt/Vca/vca_main.h @@ -0,0 +1,110 @@ +/* BEGIN_ICS_COPYRIGHT4 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT4 ****************************************/ +/* [ICS VERSION STRING: unknown] */ + +#ifndef _IBA_VCA_MAIN_H_ +#define _IBA_VCA_MAIN_H_ (1) // suppress duplicate loading of this file + + +// +// External declarations of global variables +// + +extern struct _VCA_GLOBAL VcaGlobal; + + +// +// Constant definitions +// + +#define VCA_MEM_TAG MAKE_MEM_TAG(V,c,a,M) + + +// +// Forward declarations +// + +FSTATUS +vcaLoad(EUI64 SystemImageGUID); + +void +vcaUnload(void); + +FSTATUS +vcaInitCA( + IN DEVICE_INFO *DevInfo + ); + +FSTATUS +vcaAddCA( + IN DEVICE_INFO *DevInfo + ); + +void +vcaRemoveCA( + IN DEVICE_INFO *DevInfo + ); + +FSTATUS +vcaFreeCA( + IN DEVICE_INFO *DevInfo + ); + +DEVICE_INFO * +vcaFindCA( + IN EUI64 CaGuid + ); + +FSTATUS +default_poll_and_rearm_cq( + IN IB_HANDLE CqHandle, + IN IB_CQ_EVENT_SELECT EventSelect, + OUT IB_WORK_COMPLETION *WorkCompletion + ); + +FSTATUS +vcaOpenCa( + IN DEVICE_INFO *DevInfo, + IN IB_COMPLETION_CALLBACK CompletionCallback, + IN IB_ASYNC_EVENT_CALLBACK AsyncEventCallback, + IN void *Context, + OUT IB_HANDLE *CaHandle + ); + +// +// VCA global info +// + +typedef struct _VCA_GLOBAL { + DEVICE_INFO *DeviceList; // List of all known devices + SPIN_LOCK Lock; // Lock on device list + EUI64 SystemImageGUID; // global for platform +} VCA_GLOBAL; + +#endif // _IBA_VCA_MAIN_H_ diff --git a/IbAccess/Common/Ibt/Vca/vca_resources.h b/IbAccess/Common/Ibt/Vca/vca_resources.h new file mode 100644 index 0000000..b710efa --- /dev/null +++ b/IbAccess/Common/Ibt/Vca/vca_resources.h @@ -0,0 +1,56 @@ +/* BEGIN_ICS_COPYRIGHT4 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT4 ****************************************/ +/* [ICS VERSION STRING: unknown] */ + +#ifndef _IBA_IB_VCARESOURCES_H_ +#define _IBA_IB_VCARESOURCES_H_ (1) // suppress duplicate loading of this file + + +typedef struct { + IB_HANDLE VpHandle; + VPD_KM_INTERFACE *VpInterface; +} VCA_CA_CONTEXT, VCA_CQ_CONTEXT, VCA_PD_CONTEXT; + +typedef struct { + IB_HANDLE VpHandle; + VCA_PD_CONTEXT *VcaPdHandle; // Needed by QueryMemRegion + VPD_KM_INTERFACE *VpInterface; +} VCA_MR_CONTEXT, VCA_MW_CONTEXT,VCA_AV_CONTEXT; + +typedef struct { + IB_HANDLE VpHandle; + VCA_CQ_CONTEXT *VcaSendCQHandle; + VCA_CQ_CONTEXT *VcaRecvCQHandle; + VCA_PD_CONTEXT *VcaPdHandle; + VPD_KM_INTERFACE *VpInterface; + IB_QP_TYPE Type; +} VCA_QP_CONTEXT; + + +#endif // _IBA_IB_VCARESOURCES_H_ diff --git a/IbAccess/Common/Ibt/Vca/vca_vpi.c b/IbAccess/Common/Ibt/Vca/vca_vpi.c new file mode 100644 index 0000000..07e0365 --- /dev/null +++ b/IbAccess/Common/Ibt/Vca/vca_vpi.c @@ -0,0 +1,1813 @@ +/* BEGIN_ICS_COPYRIGHT4 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT4 ****************************************/ + + +#include "precomp.h" + +FSTATUS +iba_open_ca( + IN EUI64 CaGUID, + IN IB_COMPLETION_CALLBACK CompletionCallback, + IN IB_ASYNC_EVENT_CALLBACK AsyncEventCallback, + IN void *Context, + OUT IB_HANDLE *CaHandle + ) +{ + DEVICE_INFO *DevInfo; + + DevInfo = vcaFindCA(CaGUID); + + if ( DevInfo == NULL ) + return FINVALID_PARAMETER; + return vcaOpenCa(DevInfo, CompletionCallback, AsyncEventCallback, + Context, CaHandle); +} + +// internal function so we can open a CA and start using it before +// adding DevInfo to the global list +FSTATUS +vcaOpenCa( + IN DEVICE_INFO *DevInfo, + IN IB_COMPLETION_CALLBACK CompletionCallback, + IN IB_ASYNC_EVENT_CALLBACK AsyncEventCallback, + IN void *Context, + OUT IB_HANDLE *CaHandle + ) +{ + VCA_CA_CONTEXT *vcaCaContext; + FSTATUS status; + + if ( (vcaCaContext = (VCA_CA_CONTEXT*)MemoryAllocate2(sizeof(VCA_CA_CONTEXT), IBA_MEM_FLAG_PREMPTABLE, VCA_MEM_TAG)) == NULL ) + { + return FINSUFFICIENT_RESOURCES; + } + + MemoryClear(vcaCaContext, sizeof(VCA_CA_CONTEXT)); + + status = DevInfo->VpInterface.OpenCA(DevInfo->VpInterface.CaGUID, + CompletionCallback, + AsyncEventCallback, + Context, + &vcaCaContext->VpHandle); + + if (status == FSUCCESS) + { + // Save VP I/F so we can make direct calls from the handle + vcaCaContext->VpInterface = &DevInfo->VpInterface; + *CaHandle = (IB_HANDLE)vcaCaContext; + } else { + MemoryDeallocate(vcaCaContext); + } + + return status; +} + +FSTATUS +iba_query_ca( + IN IB_HANDLE CaHandle, + OUT IB_CA_ATTRIBUTES *CaAttributes, + OUT void **Context + ) +{ + VCA_CA_CONTEXT *vcaCaHandle = (VCA_CA_CONTEXT *)CaHandle; + + return vcaCaHandle->VpInterface->QueryCA(vcaCaHandle->VpHandle, + CaAttributes, + Context); +} + +FSTATUS +iba_query_ca2( + IN IB_HANDLE CaHandle, + OUT IB_CA_ATTRIBUTES2 *CaAttributes, + OUT void **Context + ) +{ + VCA_CA_CONTEXT *vcaCaHandle = (VCA_CA_CONTEXT *)CaHandle; + + return vcaCaHandle->VpInterface->QueryCA2(vcaCaHandle->VpHandle, + CaAttributes, + Context); +} + +FSTATUS +iba_set_compl_handler( + IN IB_HANDLE CaHandle, + IN IB_COMPLETION_CALLBACK CompletionCallback + ) +{ + VCA_CA_CONTEXT *vcaCaHandle = (VCA_CA_CONTEXT *)CaHandle; + + return vcaCaHandle->VpInterface->SetCompletionHandler(vcaCaHandle->VpHandle, + CompletionCallback); +} + + +FSTATUS +iba_set_async_event_handler( + IN IB_HANDLE CaHandle, + IN IB_ASYNC_EVENT_CALLBACK AsyncEventCallback + ) +{ + VCA_CA_CONTEXT *vcaCaHandle = (VCA_CA_CONTEXT *)CaHandle; + + return vcaCaHandle->VpInterface->SetAsyncEventHandler( + vcaCaHandle->VpHandle, + AsyncEventCallback); +} + +FSTATUS +iba_set_ca_context( + IN IB_HANDLE CaHandle, + IN void *Context + ) +{ + VCA_CA_CONTEXT *vcaCaHandle = (VCA_CA_CONTEXT *)CaHandle; + + return vcaCaHandle->VpInterface->SetCAContext( + vcaCaHandle->VpHandle, + Context); +} + +FSTATUS +SetCAInternal( + IN IB_HANDLE CaHandle + ) +{ + VCA_CA_CONTEXT *vcaCaHandle = (VCA_CA_CONTEXT *)CaHandle; + + return vcaCaHandle->VpInterface->SetCAInternal(vcaCaHandle->VpHandle); +} + +FSTATUS +iba_modify_ca( + IN IB_HANDLE CaHandle, + IN IB_CA_ATTRIBUTES *CaAttributes + ) +{ + VCA_CA_CONTEXT *vcaCaHandle = (VCA_CA_CONTEXT *)CaHandle; + + return vcaCaHandle->VpInterface->ModifyCA(vcaCaHandle->VpHandle, CaAttributes); +} + +FSTATUS +iba_close_ca( + IN IB_HANDLE CaHandle + ) +{ + VCA_CA_CONTEXT *vcaCaHandle = (VCA_CA_CONTEXT *)CaHandle; + FSTATUS status; + + status = vcaCaHandle->VpInterface->CloseCA(vcaCaHandle->VpHandle); + + if ( status == FSUCCESS ) + { + // Clear context so that future references fail + MemoryClear(vcaCaHandle, sizeof(VCA_CA_CONTEXT)); + MemoryDeallocate(vcaCaHandle); + } + + return status; +} + +// depricated interface +FSTATUS +AllocatePD( + IN IB_HANDLE CaHandle, + OUT IB_HANDLE *PdHandle + ) +{ + return iba_alloc_pd(CaHandle, DEFAULT_MAX_AVS_PER_PD, PdHandle); +} + +FSTATUS +iba_alloc_pd( + IN IB_HANDLE CaHandle, + IN uint32 MaxAVs, + OUT IB_HANDLE *PdHandle + ) +{ + VCA_CA_CONTEXT *vcaCaHandle = (VCA_CA_CONTEXT *)CaHandle; + VCA_PD_CONTEXT *vcaPdContext; + FSTATUS status; + + if ( (vcaPdContext = (VCA_PD_CONTEXT*)MemoryAllocate2(sizeof(VCA_PD_CONTEXT), IBA_MEM_FLAG_PREMPTABLE, VCA_MEM_TAG)) == NULL ) + { + return FINSUFFICIENT_RESOURCES; + } + + MemoryClear(vcaPdContext, sizeof(VCA_PD_CONTEXT)); + + status = vcaCaHandle->VpInterface->AllocatePD(vcaCaHandle->VpHandle, + MaxAVs, + &vcaPdContext->VpHandle); + + if (status == FSUCCESS) + { + // Save VP I/F so we can make direct calls from the handle + vcaPdContext->VpInterface = vcaCaHandle->VpInterface; + *PdHandle = (IB_HANDLE)vcaPdContext; + } else { + MemoryDeallocate(vcaPdContext); + } + + return status; +} + + +FSTATUS +iba_alloc_sqp_pd( + IN IB_HANDLE CaHandle, + IN uint32 MaxAVs, + OUT IB_HANDLE *PdHandle + ) +{ + VCA_CA_CONTEXT *vcaCaHandle = (VCA_CA_CONTEXT *)CaHandle; + VCA_PD_CONTEXT *vcaPdContext; + FSTATUS status; + + if ( (vcaPdContext = (VCA_PD_CONTEXT*)MemoryAllocate2(sizeof(VCA_PD_CONTEXT), IBA_MEM_FLAG_PREMPTABLE, VCA_MEM_TAG)) == NULL ) + { + return FINSUFFICIENT_RESOURCES; + } + + MemoryClear(vcaPdContext, sizeof(VCA_PD_CONTEXT)); + + if (! vcaCaHandle->VpInterface->AllocateSqpPD) + { + status = vcaCaHandle->VpInterface->AllocatePD(vcaCaHandle->VpHandle, + MaxAVs, + &vcaPdContext->VpHandle); + } else { + status = vcaCaHandle->VpInterface->AllocateSqpPD(vcaCaHandle->VpHandle, + MaxAVs, + &vcaPdContext->VpHandle); + } + + if (status == FSUCCESS) + { + // Save VP I/F so we can make direct calls from the handle + vcaPdContext->VpInterface = vcaCaHandle->VpInterface; + *PdHandle = (IB_HANDLE)vcaPdContext; + } else { + MemoryDeallocate(vcaPdContext); + } + + return status; +} + + +FSTATUS +iba_free_pd( + IN IB_HANDLE PdHandle + ) +{ + VCA_PD_CONTEXT *vcaPdHandle = (VCA_PD_CONTEXT *)PdHandle; + FSTATUS status; + + status = vcaPdHandle->VpInterface->FreePD(vcaPdHandle->VpHandle); + + if (status == FSUCCESS) + { + // Clear context so that future references fail + MemoryClear(vcaPdHandle, sizeof(VCA_PD_CONTEXT)); + MemoryDeallocate(vcaPdHandle); + } + return status; +} + +FSTATUS +iba_alloc_rdd( + IN IB_HANDLE CaHandle, + OUT IB_HANDLE *RddHandle + ) +{ + return FERROR; +} + +FSTATUS +iba_free_rdd( + IN IB_HANDLE RddHandle + ) +{ + return FERROR; +} + +FSTATUS +iba_create_av( + IN IB_HANDLE CaHandle, + IN IB_HANDLE PdHandle, + IN IB_ADDRESS_VECTOR *AddressVector, + OUT IB_HANDLE *AvHandle + ) +{ + VCA_CA_CONTEXT *vcaCaHandle = (VCA_CA_CONTEXT *)CaHandle; + VCA_PD_CONTEXT *vcaPdHandle = (VCA_PD_CONTEXT *)PdHandle; + VCA_AV_CONTEXT *vcaAvContext; + FSTATUS status; + + if ( (vcaAvContext = (VCA_AV_CONTEXT*)MemoryAllocate2(sizeof(VCA_AV_CONTEXT), IBA_MEM_FLAG_NONE, VCA_MEM_TAG)) == NULL ) + { + return FINSUFFICIENT_RESOURCES; + } + + MemoryClear(vcaAvContext, sizeof(VCA_AV_CONTEXT)); + + status = vcaCaHandle->VpInterface->CreateAV( + vcaCaHandle->VpHandle, + vcaPdHandle->VpHandle, + AddressVector, + &vcaAvContext->VpHandle); + + if (status == FSUCCESS) + { + // Save VP I/F so we can make direct calls from the handle + vcaAvContext->VpInterface = vcaCaHandle->VpInterface; + vcaAvContext->VcaPdHandle = vcaPdHandle; + *AvHandle = (IB_HANDLE)vcaAvContext; + } else { + MemoryDeallocate(vcaAvContext); + } + + return status; +} + +FSTATUS +iba_modify_av( + IN IB_HANDLE AvHandle, + IN IB_ADDRESS_VECTOR *AddressVector + ) +{ + VCA_AV_CONTEXT *vcaAvHandle = (VCA_AV_CONTEXT *)AvHandle; + + return vcaAvHandle->VpInterface->ModifyAV(vcaAvHandle->VpHandle, + AddressVector); +} + + +FSTATUS +iba_query_av( + IN IB_HANDLE AvHandle, + OUT IB_ADDRESS_VECTOR *AddressVector, + OUT IB_HANDLE *PdHandle + ) +{ + FSTATUS status; + VCA_AV_CONTEXT *vcaAvHandle = (VCA_AV_CONTEXT *)AvHandle; + + if ( (status = vcaAvHandle->VpInterface->QueryAV( + vcaAvHandle->VpHandle, + AddressVector, + PdHandle)) == FSUCCESS + + ) + { + *PdHandle = vcaAvHandle->VcaPdHandle; + } + return status; +} + + +FSTATUS +iba_destroy_av( + IN IB_HANDLE AvHandle + ) +{ + VCA_AV_CONTEXT *vcaAvHandle = (VCA_AV_CONTEXT *)AvHandle; + FSTATUS status; + + status = vcaAvHandle->VpInterface->DestroyAV(vcaAvHandle->VpHandle); + + if (status == FSUCCESS) + { + // Clear context so that future references fail + MemoryClear(vcaAvHandle, sizeof(VCA_AV_CONTEXT)); + MemoryDeallocate(vcaAvHandle); + } + + return status; +} + +FSTATUS +iba_create_qp( + IN IB_HANDLE CaHandle, + IN IB_QP_ATTRIBUTES_CREATE *QpCreateAttributes, + IN void *Context, + OUT IB_HANDLE *QpHandle, + OUT IB_QP_ATTRIBUTES_QUERY *QpAttributes + ) +{ + VCA_CA_CONTEXT *vcaCaHandle = (VCA_CA_CONTEXT *)CaHandle; + VCA_QP_CONTEXT *vcaQpContext; + VCA_PD_CONTEXT *vcaPdHandle; + FSTATUS status; + + if ( (vcaQpContext = (VCA_QP_CONTEXT*)MemoryAllocate2AndClear(sizeof(VCA_QP_CONTEXT), IBA_MEM_FLAG_PREMPTABLE, VCA_MEM_TAG)) == NULL ) + { + return FINSUFFICIENT_RESOURCES; + } + + // Translate PD handle to VP's + vcaPdHandle = (VCA_PD_CONTEXT *)QpCreateAttributes->PDHandle; + QpCreateAttributes->PDHandle = vcaPdHandle->VpHandle; + + // Translate the CQ handles to VP's + vcaQpContext->VcaSendCQHandle = + (VCA_CQ_CONTEXT *)QpCreateAttributes->SendCQHandle; + vcaQpContext->VcaRecvCQHandle = + (VCA_CQ_CONTEXT *)QpCreateAttributes->RecvCQHandle; + QpCreateAttributes->SendCQHandle = vcaQpContext->VcaSendCQHandle->VpHandle; + QpCreateAttributes->RecvCQHandle = vcaQpContext->VcaRecvCQHandle->VpHandle; + + status = vcaCaHandle->VpInterface->CreateQP(vcaCaHandle->VpHandle, + QpCreateAttributes, + Context, + &vcaQpContext->VpHandle, + QpAttributes); + + if (status == FSUCCESS) + { + // Save VP I/F so we can make direct calls from the handle + vcaQpContext->VpInterface = vcaCaHandle->VpInterface; + *QpHandle = (IB_HANDLE)vcaQpContext; // Handle returned is ptr to VCA QP context + + // Save the VCA's PD handle in the VCA's QP context and return it in + // the QP attributes structure + vcaQpContext->VcaPdHandle = vcaPdHandle; + QpAttributes->PDHandle = (IB_HANDLE)vcaPdHandle; + + // Replace the PD handle in the create attributes structure + QpCreateAttributes->PDHandle = (IB_HANDLE)vcaPdHandle; + + // Replace the CQ handles + QpCreateAttributes->SendCQHandle = vcaQpContext->VcaSendCQHandle; + QpCreateAttributes->RecvCQHandle = vcaQpContext->VcaRecvCQHandle; + + // Copy the VCA CQ handles to the Query member of the QP Attributes + // structure. + QpAttributes->SendCQHandle = vcaQpContext->VcaSendCQHandle; + QpAttributes->RecvCQHandle = vcaQpContext->VcaRecvCQHandle; + + // Save the QP type + vcaQpContext->Type = QpAttributes->Type; + } else { + MemoryDeallocate(vcaQpContext); + } + + return status; +} + + +FSTATUS +iba_modify_qp( + IN IB_HANDLE QpHandle, + IN IB_QP_ATTRIBUTES_MODIFY *QpModifyAttributes, + OUT OPTIONAL IB_QP_ATTRIBUTES_QUERY *QpAttributes + ) +{ + VCA_QP_CONTEXT *vcaQpHandle = (VCA_QP_CONTEXT *)QpHandle; + FSTATUS status; + + status = vcaQpHandle->VpInterface->ModifyQP(vcaQpHandle->VpHandle, + QpModifyAttributes, QpAttributes); + if ( status == FSUCCESS && QpAttributes) + { + // Fill in the translated handles + QpAttributes->SendCQHandle = vcaQpHandle->VcaSendCQHandle; + QpAttributes->RecvCQHandle = vcaQpHandle->VcaRecvCQHandle; + QpAttributes->PDHandle = vcaQpHandle->VcaPdHandle; + } + return status; +} + + +FSTATUS +iba_set_qp_context( + IN IB_HANDLE QpHandle, + IN void *Context + ) +{ + return ((VCA_QP_CONTEXT*)QpHandle)->VpInterface->SetQPContext( + ((VCA_QP_CONTEXT*)QpHandle)->VpHandle, + Context); +} + +FSTATUS +iba_query_qp( + IN IB_HANDLE QpHandle, + OUT IB_QP_ATTRIBUTES_QUERY *QpAttributes, + OUT void **Context + ) +{ + VCA_QP_CONTEXT *vcaQpHandle = (VCA_QP_CONTEXT *)QpHandle; + FSTATUS status = FSUCCESS; + + status = vcaQpHandle->VpInterface->QueryQP(vcaQpHandle->VpHandle, + QpAttributes, + Context); + + if ( status == FSUCCESS ) + { + // Fill in the translated handles + QpAttributes->SendCQHandle = vcaQpHandle->VcaSendCQHandle; + QpAttributes->RecvCQHandle = vcaQpHandle->VcaRecvCQHandle; + QpAttributes->PDHandle = vcaQpHandle->VcaPdHandle; + } + + return status; +} + +FSTATUS +iba_destroy_qp( + IN IB_HANDLE QpHandle + ) +{ + VCA_QP_CONTEXT *vcaQpHandle = (VCA_QP_CONTEXT *)QpHandle; + FSTATUS status; + + status = vcaQpHandle->VpInterface->DestroyQP(vcaQpHandle->VpHandle); + + if (status == FSUCCESS) + { + // Clear context so that future references fail + MemoryClear(vcaQpHandle, sizeof(VCA_QP_CONTEXT)); + MemoryDeallocate(vcaQpHandle); + } + + return status; +} + +FSTATUS +iba_create_special_qp( + IN IB_HANDLE CaHandle, + IN EUI64 PortGUID, + IN IB_QP_ATTRIBUTES_CREATE *QpCreateAttributes, + IN void *Context, + OUT IB_HANDLE *QpHandle, + OUT IB_QP_ATTRIBUTES_QUERY *QpAttributes + ) +{ + VCA_CA_CONTEXT *vcaCaHandle = (VCA_CA_CONTEXT *)CaHandle; + VCA_QP_CONTEXT *vcaQpContext; + VCA_PD_CONTEXT *vcaPdHandle; + FSTATUS status; + + if ( (vcaQpContext = (VCA_QP_CONTEXT*)MemoryAllocate2AndClear(sizeof(VCA_QP_CONTEXT), IBA_MEM_FLAG_PREMPTABLE, VCA_MEM_TAG)) == NULL ) + { + return FINSUFFICIENT_RESOURCES; + } + + // Translate PD handle to VP's + vcaPdHandle = (VCA_PD_CONTEXT *)QpCreateAttributes->PDHandle; + QpCreateAttributes->PDHandle = vcaPdHandle->VpHandle; + + // Translate the CQ handles to VP's + vcaQpContext->VcaSendCQHandle = + (VCA_CQ_CONTEXT *)QpCreateAttributes->SendCQHandle; + vcaQpContext->VcaRecvCQHandle = + (VCA_CQ_CONTEXT *)QpCreateAttributes->RecvCQHandle; + QpCreateAttributes->SendCQHandle = vcaQpContext->VcaSendCQHandle->VpHandle; + QpCreateAttributes->RecvCQHandle = vcaQpContext->VcaRecvCQHandle->VpHandle; + + status = vcaCaHandle->VpInterface->CreateSpecialQP(vcaCaHandle->VpHandle, + PortGUID, + QpCreateAttributes, + Context, + &vcaQpContext->VpHandle, + QpAttributes); + + if (status == FSUCCESS) + { + // Save VP I/F so we can make direct calls from the handle + vcaQpContext->VpInterface = vcaCaHandle->VpInterface; + *QpHandle = (IB_HANDLE)vcaQpContext; + + // Save the VCA's PD handle in the VCA's QP context and return it in + // the QP attributes structure. + vcaQpContext->VcaPdHandle = vcaPdHandle; + QpAttributes->PDHandle = (IB_HANDLE)vcaPdHandle; + + // Replace the CQ handles + QpCreateAttributes->SendCQHandle = vcaQpContext->VcaSendCQHandle; + QpCreateAttributes->RecvCQHandle = vcaQpContext->VcaRecvCQHandle; + + // Save the QP type + vcaQpContext->Type = QpAttributes->Type; + } else { + MemoryDeallocate(vcaQpContext); + } + return status; +} + +FSTATUS +iba_attach_qp_to_mcgroup( + IN IB_HANDLE QpHandle, +#if INCLUDE_16B + IN STL_LID McgDestLid, +#else + IN IB_LID McgDestLid, +#endif + IN IB_GID McgGID + ) +{ + return ((VCA_QP_CONTEXT*)QpHandle)->VpInterface->AttachQPToMulticastGroup( + ((VCA_QP_CONTEXT*)QpHandle)->VpHandle, + McgDestLid, McgGID); +} + +FSTATUS +iba_detach_qp_from_mcgroup( + IN IB_HANDLE QpHandle, +#if INCLUDE_16B + IN STL_LID McgDestLid, +#else + IN IB_LID McgDestLid, +#endif + IN IB_GID McgGID + ) +{ + return ((VCA_QP_CONTEXT*)QpHandle)->VpInterface->DetachQPFromMulticastGroup( + ((VCA_QP_CONTEXT*)QpHandle)->VpHandle, + McgDestLid, McgGID); +} + + +FSTATUS +iba_create_cq( + IN IB_HANDLE CaHandle, + IN uint32 CqReqSize, + IN void *Context, + OUT IB_HANDLE *CqHandle, + OUT uint32 *CqSize + ) +{ + VCA_CA_CONTEXT *vcaCaHandle = (VCA_CA_CONTEXT *)CaHandle; + VCA_CQ_CONTEXT *vcaCqContext; + FSTATUS status; + + if ( (vcaCqContext = (VCA_CQ_CONTEXT*)MemoryAllocate2(sizeof(VCA_CQ_CONTEXT), IBA_MEM_FLAG_PREMPTABLE, VCA_MEM_TAG)) == NULL ) + { + return FINSUFFICIENT_RESOURCES; + } + + MemoryClear(vcaCqContext, sizeof(VCA_CQ_CONTEXT)); + + status = vcaCaHandle->VpInterface->CreateCQ(vcaCaHandle->VpHandle, + CqReqSize, Context, + &vcaCqContext->VpHandle, CqSize); + if (status == FSUCCESS) + { + // Save VP I/F so we can make direct calls from the handle + vcaCqContext->VpInterface = vcaCaHandle->VpInterface; + *CqHandle = (IB_HANDLE)vcaCqContext; + } else { + MemoryDeallocate(vcaCqContext); + } + + return status; +} + + +FSTATUS +iba_resize_cq( + IN IB_HANDLE CqHandle, + IN uint32 CqReqSize, + OUT uint32 *CqSize + ) +{ + return ((VCA_CQ_CONTEXT*)CqHandle)->VpInterface->ResizeCQ( + ((VCA_CQ_CONTEXT*)CqHandle)->VpHandle, + CqReqSize, CqSize); +} + + +FSTATUS +iba_set_cq_context( + IN IB_HANDLE CqHandle, + IN void *Context + ) +{ + return ((VCA_CQ_CONTEXT*)CqHandle)->VpInterface->SetCQContext( + ((VCA_CQ_CONTEXT*)CqHandle)->VpHandle, + Context); +} + + +FSTATUS +iba_set_cq_compl_handler( + IN IB_HANDLE CqHandle, + IN IB_COMPLETION_CALLBACK CompletionCallback + ) +{ + return ((VCA_CQ_CONTEXT*)CqHandle)->VpInterface->SetCQCompletionHandler( + ((VCA_CQ_CONTEXT*)CqHandle)->VpHandle, + CompletionCallback); +} + + +FSTATUS +iba_query_cq( + IN IB_HANDLE CqHandle, + OUT uint32 *CqSize, + OUT void **Context + ) +{ + return ((VCA_CQ_CONTEXT*)CqHandle)->VpInterface->QueryCQ( + ((VCA_CQ_CONTEXT*)CqHandle)->VpHandle, + CqSize, Context); +} + + +FSTATUS +iba_destroy_cq( + IN IB_HANDLE CqHandle + ) +{ + VCA_CQ_CONTEXT *vcaCqHandle = (VCA_CQ_CONTEXT *)CqHandle; + FSTATUS status; + + status = vcaCqHandle->VpInterface->DestroyCQ(vcaCqHandle->VpHandle); + + if (status == FSUCCESS) + { + // Clear context so that future references fail + MemoryClear(vcaCqHandle, sizeof(VCA_CQ_CONTEXT)); + MemoryDeallocate(vcaCqHandle); + } + + return status; +} + + +FSTATUS +iba_register_mr( + IN IB_HANDLE CaHandle, + IN void *VirtualAddress, + IN uintn Length, + IN IB_HANDLE PdHandle, + IN IB_ACCESS_CONTROL AccessControl, + OUT IB_HANDLE *MrHandle, + OUT IB_L_KEY *Lkey, + OUT IB_R_KEY *Rkey + ) +{ + VCA_CA_CONTEXT *vcaCaHandle = (VCA_CA_CONTEXT *)CaHandle; + VCA_PD_CONTEXT *vcaPdHandle = (VCA_PD_CONTEXT *)PdHandle; + VCA_MR_CONTEXT *vcaMrContext; + FSTATUS status; + + if ( (vcaMrContext = (VCA_MR_CONTEXT*)MemoryAllocate2(sizeof(VCA_MR_CONTEXT), IBA_MEM_FLAG_PREMPTABLE, VCA_MEM_TAG)) == NULL ) + { + return FINSUFFICIENT_RESOURCES; + } + + MemoryClear(vcaMrContext, sizeof(VCA_MR_CONTEXT)); + + status = vcaCaHandle->VpInterface->RegisterMemRegion(vcaCaHandle->VpHandle, + VirtualAddress, + Length, + vcaPdHandle->VpHandle, + AccessControl, + &vcaMrContext->VpHandle, + Lkey, + Rkey); + + if (status == FSUCCESS) + { + // Save VP I/F so we can make direct calls from the handle. Save + // the PD handle in the MR handle for the modify and query mem + // region functions. + vcaMrContext->VpInterface = vcaCaHandle->VpInterface; + vcaMrContext->VcaPdHandle = vcaPdHandle; + *MrHandle = (IB_HANDLE)vcaMrContext; + } else { + MemoryDeallocate(vcaMrContext); + } + + return status; +} + +// depricated +FSTATUS +RegisterPhysMemRegion( + IN IB_HANDLE CaHandle, + IN void *ReqIoVirtualAddress, + IN void *PhysBufferList, + IN uint64 NumPhysBuffers, + IN uint32 IoVaOffset, + IN IB_HANDLE PdHandle, + IN IB_ACCESS_CONTROL AccessControl, + OUT IB_HANDLE *MrHandle, + OUT void **IoVirtualAddress, + OUT IB_L_KEY *Lkey, + OUT IB_R_KEY *Rkey + ) +{ + IB_VIRT_ADDR reqVa = (IB_VIRT_ADDR)(uintn)ReqIoVirtualAddress; + IB_VIRT_ADDR va; + FSTATUS status; + + status = iba_register_pmr(CaHandle, reqVa, + PhysBufferList, NumPhysBuffers, IoVaOffset, PdHandle, + AccessControl, MrHandle, &va, Lkey, Rkey); + if (status == FSUCCESS) + { + *IoVirtualAddress = (void*)(uintn)va; + if ((IB_VIRT_ADDR)(uintn)*IoVirtualAddress != va) + { + // we cannot fit the resulting va in a void* + (void)iba_deregister_mr(*MrHandle); + status = FERROR; + } + } + return status; +} + +FSTATUS +iba_register_pmr( + IN IB_HANDLE CaHandle, + IN IB_VIRT_ADDR ReqIoVirtualAddress, + IN void *PhysBufferList, + IN uint64 NumPhysBuffers, + IN uint32 IoVaOffset, + IN IB_HANDLE PdHandle, + IN IB_ACCESS_CONTROL AccessControl, + OUT IB_HANDLE *MrHandle, + OUT IB_VIRT_ADDR *IoVirtualAddress, + OUT IB_L_KEY *Lkey, + OUT IB_R_KEY *Rkey + ) +{ + VCA_CA_CONTEXT *vcaCaHandle = (VCA_CA_CONTEXT *)CaHandle; + VCA_PD_CONTEXT *vcaPdHandle = (VCA_PD_CONTEXT *)PdHandle; + VCA_MR_CONTEXT *vcaMrContext; + FSTATUS status; + + if ( (vcaMrContext = (VCA_MR_CONTEXT*)MemoryAllocate2(sizeof(VCA_MR_CONTEXT), IBA_MEM_FLAG_PREMPTABLE, VCA_MEM_TAG)) == NULL ) + { + return FINSUFFICIENT_RESOURCES; + } + + MemoryClear(vcaMrContext, sizeof(VCA_MR_CONTEXT)); + + status = vcaCaHandle->VpInterface->RegisterPhysMemRegion(vcaCaHandle->VpHandle, + ReqIoVirtualAddress, + PhysBufferList, + NumPhysBuffers, + IoVaOffset, + vcaPdHandle->VpHandle, + AccessControl, + &vcaMrContext->VpHandle, + IoVirtualAddress, + Lkey, + Rkey); + + if (status == FSUCCESS) + { + // Save VP I/F so we can make direct calls from the handle + vcaMrContext->VpInterface = vcaCaHandle->VpInterface; + vcaMrContext->VcaPdHandle = vcaPdHandle; + *MrHandle = (IB_HANDLE)vcaMrContext; + } else { + MemoryDeallocate(vcaMrContext); + } + + return status; +} + +FSTATUS +iba_register_contig_pmr( + IN IB_HANDLE CaHandle, + IN IB_VIRT_ADDR ReqIoVirtualAddress, + IN IB_MR_PHYS_BUFFER* PhysBufferList, + IN uint64 NumPhysBuffers, + IN uint32 IoVaOffset, + IN IB_HANDLE PdHandle, + IN IB_ACCESS_CONTROL AccessControl, + OUT IB_HANDLE *MrHandle, + OUT IB_VIRT_ADDR *IoVirtualAddress, + OUT IB_L_KEY *Lkey, + OUT IB_R_KEY *Rkey + ) +{ + VCA_CA_CONTEXT *vcaCaHandle = (VCA_CA_CONTEXT *)CaHandle; + VCA_PD_CONTEXT *vcaPdHandle = (VCA_PD_CONTEXT *)PdHandle; + VCA_MR_CONTEXT *vcaMrContext; + FSTATUS status; + + if ( (vcaMrContext = (VCA_MR_CONTEXT*)MemoryAllocate2(sizeof(VCA_MR_CONTEXT), IBA_MEM_FLAG_PREMPTABLE, VCA_MEM_TAG)) == NULL ) + { + return FINSUFFICIENT_RESOURCES; + } + + MemoryClear(vcaMrContext, sizeof(VCA_MR_CONTEXT)); + + status = vcaCaHandle->VpInterface->RegisterContigPhysMemRegion(vcaCaHandle->VpHandle, + ReqIoVirtualAddress, + PhysBufferList, + NumPhysBuffers, + IoVaOffset, + vcaPdHandle->VpHandle, + AccessControl, + &vcaMrContext->VpHandle, + IoVirtualAddress, + Lkey, + Rkey); + + if (status == FSUCCESS) + { + // Save VP I/F so we can make direct calls from the handle + vcaMrContext->VpInterface = vcaCaHandle->VpInterface; + vcaMrContext->VcaPdHandle = vcaPdHandle; + *MrHandle = (IB_HANDLE)vcaMrContext; + } else { + MemoryDeallocate(vcaMrContext); + } + + return status; +} + +// depricated +FSTATUS +QueryMemRegion( + IN IB_HANDLE MrHandle, + OUT void **VirtualAddress, + OUT uintn *Length, + OUT IB_HANDLE *PdHandle, + OUT IB_ACCESS_CONTROL *AccessControl, + OUT IB_L_KEY *Lkey, + OUT IB_R_KEY *Rkey + ) +{ + IB_VIRT_ADDR va; + uint64 length; + FSTATUS status; + + status = iba_query_mr(MrHandle, &va, &length, PdHandle, AccessControl, + Lkey, Rkey); + if (status == FSUCCESS) + { + // assume Va & Length fits, since must have registered successfully + *VirtualAddress = (void*)(uintn)va; + *Length = (uintn)length; + } + return status; +} + +FSTATUS +iba_query_mr( + IN IB_HANDLE MrHandle, + OUT IB_VIRT_ADDR *VirtualAddress, + OUT uint64 *Length, + OUT IB_HANDLE *PdHandle, + OUT IB_ACCESS_CONTROL *AccessControl, + OUT IB_L_KEY *Lkey, + OUT IB_R_KEY *Rkey + ) +{ + VCA_MR_CONTEXT *vcaMrHandle = (VCA_MR_CONTEXT *)MrHandle; + FSTATUS status; + + status = vcaMrHandle->VpInterface->QueryMemRegion(vcaMrHandle->VpHandle, + VirtualAddress, + Length, + PdHandle, + AccessControl, + Lkey, + Rkey); + + // Set PD handle to the VCA's PD handle + *PdHandle = (IB_HANDLE)vcaMrHandle->VcaPdHandle; + + return status; +} + + +FSTATUS +iba_deregister_mr( + IN IB_HANDLE MrHandle + ) +{ + VCA_MR_CONTEXT *vcaMrHandle = (VCA_MR_CONTEXT *)MrHandle; + FSTATUS status; + + status = vcaMrHandle->VpInterface->DeregisterMemRegion(vcaMrHandle->VpHandle); + + if (status == FSUCCESS) + { + // Clear context so that future references fail + MemoryClear(vcaMrHandle, sizeof(VCA_MR_CONTEXT)); + MemoryDeallocate(vcaMrHandle); + } + + return status; +} + +FSTATUS +iba_modify_mr( + IN IB_HANDLE MrHandle, + IN IB_MR_MODIFY_REQ ModifyReqType, + IN void *VirtualAddress OPTIONAL, + IN uintn Length OPTIONAL, + IN IB_HANDLE PdHandle OPTIONAL, + IN IB_ACCESS_CONTROL AccessControl OPTIONAL, + OUT IB_HANDLE *NewMrHandle, + OUT IB_L_KEY *Lkey, + OUT IB_R_KEY *Rkey + ) +{ + VCA_MR_CONTEXT *vcaMrHandle = (VCA_MR_CONTEXT *)MrHandle; + VCA_PD_CONTEXT *vcaPdHandle; + IB_HANDLE vpPdHandle = NULL; + FSTATUS status; + + if ( ModifyReqType.s.ProtectionDomain ) + { + vcaPdHandle = (VCA_PD_CONTEXT *)PdHandle; + vpPdHandle = vcaPdHandle->VpHandle; + + // Replace the current PdHandle in the MR context with the new + // PdHandle. Don't need to worry that the call may fail in the + // VP as if it does the MR is destroyed below. + vcaMrHandle->VcaPdHandle = vcaPdHandle; + } + + status = vcaMrHandle->VpInterface->ModifyMemRegion(vcaMrHandle->VpHandle, + ModifyReqType, + VirtualAddress, + Length, + vpPdHandle, + AccessControl, + &vcaMrHandle->VpHandle, + Lkey, + Rkey); + + if ( status == FSUCCESS ) + { + *NewMrHandle = MrHandle; + } else { + // On failure the existing MR is destroyed by the VP, so do the same + // here. + MemoryClear(vcaMrHandle, sizeof(VCA_MR_CONTEXT)); + MemoryDeallocate(vcaMrHandle); + *NewMrHandle = (IB_HANDLE)NULL; + } + + return status; +} + +// depricated +FSTATUS +ModifyPhysMemRegion( + IN IB_HANDLE MrHandle, + IN IB_MR_MODIFY_REQ ModifyReqType, + IN void *ReqIoVirtualAddress OPTIONAL, + IN void *PhysBufferList OPTIONAL, + IN uint64 NumPhysBuffers OPTIONAL, + IN uint32 IoVaOffset OPTIONAL, + IN IB_HANDLE PdHandle OPTIONAL, + IN IB_ACCESS_CONTROL AccessControl OPTIONAL, + OUT IB_HANDLE *NewMrHandle, + OUT void **IoVirtualAddress, + OUT IB_L_KEY *Lkey, + OUT IB_R_KEY *Rkey + ) +{ + IB_VIRT_ADDR reqVa = (IB_VIRT_ADDR)(uintn)ReqIoVirtualAddress; + IB_VIRT_ADDR va; + FSTATUS status; + + status = iba_modify_pmr(MrHandle, ModifyReqType, reqVa, + PhysBufferList, NumPhysBuffers, IoVaOffset, PdHandle, + AccessControl, NewMrHandle, &va, Lkey, + Rkey); + if (status == FSUCCESS) + { + *IoVirtualAddress = (void*)(uintn)va; + if ((IB_VIRT_ADDR)(uintn)*IoVirtualAddress != va) + { + // we cannot fit the resulting va in a void* + // + // On failure the existing MR is destroyed by the VP, so do the same + // here. + (void)iba_deregister_mr(*NewMrHandle); + status = FERROR; + } + } + return status; +} + +FSTATUS +iba_modify_pmr( + IN IB_HANDLE MrHandle, + IN IB_MR_MODIFY_REQ ModifyReqType, + IN IB_VIRT_ADDR ReqIoVirtualAddress OPTIONAL, + IN void *PhysBufferList OPTIONAL, + IN uint64 NumPhysBuffers OPTIONAL, + IN uint32 IoVaOffset OPTIONAL, + IN IB_HANDLE PdHandle OPTIONAL, + IN IB_ACCESS_CONTROL AccessControl OPTIONAL, + OUT IB_HANDLE *NewMrHandle, + OUT IB_VIRT_ADDR *IoVirtualAddress, + OUT IB_L_KEY *Lkey, + OUT IB_R_KEY *Rkey + ) +{ + VCA_MR_CONTEXT *vcaMrHandle = (VCA_MR_CONTEXT *)MrHandle; + VCA_PD_CONTEXT *vcaPdHandle; + IB_HANDLE vpPdHandle = NULL; + FSTATUS status; + + if ( ModifyReqType.s.ProtectionDomain ) + { + vcaPdHandle = (VCA_PD_CONTEXT *)PdHandle; + vpPdHandle = vcaPdHandle->VpHandle; + + // Replace the current PdHandle in the MR context with the new + // PdHandle. Don't need to worry that the call may fail in the + // VP as if it does the MR is destroyed below. + vcaMrHandle->VcaPdHandle = vcaPdHandle; + } + + status = vcaMrHandle->VpInterface->ModifyPhysMemRegion(vcaMrHandle->VpHandle, + ModifyReqType, + ReqIoVirtualAddress, + PhysBufferList, + NumPhysBuffers, + IoVaOffset, + vpPdHandle, + AccessControl, + &vcaMrHandle->VpHandle, + IoVirtualAddress, + Lkey, + Rkey); + + if ( status == FSUCCESS ) + { + *NewMrHandle = MrHandle; + } else { + // On failure the existing MR is destroyed by the VP, so do the same + // here. + MemoryClear(vcaMrHandle, sizeof(VCA_MR_CONTEXT)); + MemoryDeallocate(vcaMrHandle); + *NewMrHandle = (IB_HANDLE)NULL; + } + + return status; +} + + +FSTATUS +iba_modify_contig_pmr( + IN IB_HANDLE MrHandle, + IN IB_MR_MODIFY_REQ ModifyReqType, + IN IB_VIRT_ADDR ReqIoVirtualAddress OPTIONAL, + IN IB_MR_PHYS_BUFFER *PhysBufferList OPTIONAL, + IN uint64 NumPhysBuffers OPTIONAL, + IN uint32 IoVaOffset OPTIONAL, + IN IB_HANDLE PdHandle OPTIONAL, + IN IB_ACCESS_CONTROL AccessControl OPTIONAL, + OUT IB_HANDLE *NewMrHandle, + OUT IB_VIRT_ADDR *IoVirtualAddress, + OUT IB_L_KEY *Lkey, + OUT IB_R_KEY *Rkey + ) +{ + VCA_MR_CONTEXT *vcaMrHandle = (VCA_MR_CONTEXT *)MrHandle; + VCA_PD_CONTEXT *vcaPdHandle; + IB_HANDLE vpPdHandle = NULL; + FSTATUS status; + + if ( ModifyReqType.s.ProtectionDomain ) + { + vcaPdHandle = (VCA_PD_CONTEXT *)PdHandle; + vpPdHandle = vcaPdHandle->VpHandle; + + // Replace the current PdHandle in the MR context with the new + // PdHandle. Don't need to worry that the call may fail in the + // VP as if it does the MR is destroyed below. + vcaMrHandle->VcaPdHandle = vcaPdHandle; + } + + status = vcaMrHandle->VpInterface->ModifyContigPhysMemRegion(vcaMrHandle->VpHandle, + ModifyReqType, + ReqIoVirtualAddress, + PhysBufferList, + NumPhysBuffers, + IoVaOffset, + vpPdHandle, + AccessControl, + &vcaMrHandle->VpHandle, + IoVirtualAddress, + Lkey, + Rkey); + + if ( status == FSUCCESS ) + { + *NewMrHandle = MrHandle; + } else { + // On failure the existing MR is destroyed by the VP, so do the same + // here. + MemoryClear(vcaMrHandle, sizeof(VCA_MR_CONTEXT)); + MemoryDeallocate(vcaMrHandle); + *NewMrHandle = (IB_HANDLE)NULL; + } + + return status; +} + + +// depricated +FSTATUS +RegisterSharedMemRegion( + IN IB_HANDLE MrHandle, + IN void *VirtualAddress, + IN IB_HANDLE PdHandle, + IN IB_ACCESS_CONTROL AccessControl, + OUT IB_HANDLE *SharedMrHandle, + OUT void **SharedVirtualAddress, + OUT IB_L_KEY *Lkey, + OUT IB_R_KEY *Rkey + ) +{ + IB_VIRT_ADDR reqVa = (IB_VIRT_ADDR)(uintn)VirtualAddress; + IB_VIRT_ADDR va; + FSTATUS status; + + status = iba_register_smr(MrHandle, reqVa, PdHandle, AccessControl, + SharedMrHandle, &va, Lkey, Rkey); + if (status == FSUCCESS) + { + *SharedVirtualAddress = (void*)(uintn)va; + if ((IB_VIRT_ADDR)(uintn)*SharedVirtualAddress != va) + { + // we cannot fit the resulting va in a void* + // + // On failure the existing MR is destroyed by the VP, so do the same + // here. + (void)iba_deregister_mr(*SharedMrHandle); + status = FERROR; + } + } + return status; +} + +FSTATUS +iba_register_smr( + IN IB_HANDLE MrHandle, + IN IB_VIRT_ADDR VirtualAddress, + IN IB_HANDLE PdHandle, + IN IB_ACCESS_CONTROL AccessControl, + OUT IB_HANDLE *SharedMrHandle, + OUT IB_VIRT_ADDR *SharedVirtualAddress, + OUT IB_L_KEY *Lkey, + OUT IB_R_KEY *Rkey + ) +{ + VCA_MR_CONTEXT *vcaMrHandle = (VCA_MR_CONTEXT *)MrHandle; + VCA_PD_CONTEXT *vcaPdHandle = (VCA_PD_CONTEXT *)PdHandle; + VCA_MR_CONTEXT *vcaSharedMrContext; + FSTATUS status; + + // PD and MR must be on same HCA, we can at least make sure its + // same verbs driver here, verbs driver will need to confirm its same HCA + if (vcaMrHandle->VpInterface != vcaPdHandle->VpInterface) + return FINVALID_PARAMETER; + + if ( (vcaSharedMrContext = (VCA_MR_CONTEXT*)MemoryAllocate2(sizeof(VCA_MR_CONTEXT), IBA_MEM_FLAG_PREMPTABLE, VCA_MEM_TAG)) == NULL ) + { + return FINSUFFICIENT_RESOURCES; + } + + MemoryClear(vcaSharedMrContext, sizeof(VCA_MR_CONTEXT)); + + status = vcaMrHandle->VpInterface->RegisterSharedMemRegion(vcaMrHandle->VpHandle, + VirtualAddress, + vcaPdHandle->VpHandle, + AccessControl, + &vcaSharedMrContext->VpHandle, + SharedVirtualAddress, + Lkey, + Rkey); + + if (status == FSUCCESS) + { + // Save VP I/F so we can make direct calls from the handle + vcaSharedMrContext->VpInterface = vcaMrHandle->VpInterface; + vcaSharedMrContext->VcaPdHandle = vcaPdHandle; + *SharedMrHandle = (IB_HANDLE)vcaSharedMrContext; + } else { + MemoryDeallocate(vcaSharedMrContext); + } + + return status; +} + + +FSTATUS +iba_create_mw( + IN IB_HANDLE CaHandle, + IN IB_HANDLE PdHandle, + OUT IB_HANDLE *MwHandle, + OUT IB_R_KEY *Rkey + ) +{ + VCA_CA_CONTEXT *vcaCaHandle = (VCA_CA_CONTEXT *)CaHandle; + VCA_PD_CONTEXT *vcaPdHandle = (VCA_PD_CONTEXT *)PdHandle; + VCA_MW_CONTEXT *vcaMwContext; + FSTATUS status; + + if ( (vcaMwContext = (VCA_MW_CONTEXT*)MemoryAllocate2(sizeof(VCA_MW_CONTEXT), IBA_MEM_FLAG_PREMPTABLE, VCA_MEM_TAG)) == NULL ) + { + return FINSUFFICIENT_RESOURCES; + } + + MemoryClear(vcaMwContext, sizeof(VCA_MW_CONTEXT)); + + status = vcaCaHandle->VpInterface->CreateMemWindow(vcaCaHandle->VpHandle, + vcaPdHandle->VpHandle, + &vcaMwContext->VpHandle, + Rkey); + + if (status == FSUCCESS) + { + // Save VP I/F so we can make direct calls from the handle + vcaMwContext->VpInterface = vcaCaHandle->VpInterface; + vcaMwContext->VcaPdHandle = vcaPdHandle; + *MwHandle = (IB_HANDLE)vcaMwContext; + } else { + MemoryDeallocate(vcaMwContext); + } + + return status; +} + +FSTATUS +iba_query_mw( + IN IB_HANDLE MwHandle, + OUT IB_HANDLE *PdHandle, + OUT IB_R_KEY *Rkey + ) +{ + VCA_MW_CONTEXT *vcaMwHandle = (VCA_MW_CONTEXT *)MwHandle; + FSTATUS status; + + status = vcaMwHandle->VpInterface->QueryMemWindow(vcaMwHandle->VpHandle, + PdHandle, + Rkey); + + // Set the PD handle to the VCA's PD handle + *PdHandle = (IB_HANDLE)vcaMwHandle->VcaPdHandle; + + return status; +} + + +// depricated +FSTATUS +PostMemWindowBind( + IN IB_HANDLE QpHandle, + IN uint64 WorkReqId, + IN IB_HANDLE MwHandle, + IN IB_R_KEY CurrentRkey, + IN IB_HANDLE MrHandle, + IN IB_L_KEY MrLkey, + IN void *VirtualAddress, + IN uintn Length, + IN IB_ACCESS_CONTROL AccessControl, + IN IB_MW_BIND_OPTIONS Options, + OUT IB_R_KEY *NewRkey + ) +{ + return iba_post_bind_mw(QpHandle, WorkReqId, MwHandle, CurrentRkey, + MrHandle, MrLkey, (IB_VIRT_ADDR)(uintn)VirtualAddress, + (uint64)Length, AccessControl, Options, NewRkey); +} + +FSTATUS +iba_post_bind_mw( + IN IB_HANDLE QpHandle, + IN uint64 WorkReqId, + IN IB_HANDLE MwHandle, + IN IB_R_KEY CurrentRkey, + IN IB_HANDLE MrHandle, + IN IB_L_KEY MrLkey, + IN IB_VIRT_ADDR VirtualAddress, + IN uint64 Length, + IN IB_ACCESS_CONTROL AccessControl, + IN IB_MW_BIND_OPTIONS Options, + OUT IB_R_KEY *NewRkey + ) +{ + VCA_MW_CONTEXT *vcaMwHandle = (VCA_MW_CONTEXT *)MwHandle; + VCA_MR_CONTEXT *vcaMrHandle = (VCA_MR_CONTEXT *)MrHandle; + + return ((VCA_QP_CONTEXT*)QpHandle)->VpInterface->PostMemWindowBind( + ((VCA_QP_CONTEXT*)QpHandle)->VpHandle, + WorkReqId, + vcaMwHandle->VpHandle, + CurrentRkey, + vcaMrHandle->VpHandle, + MrLkey, + VirtualAddress, + Length, + AccessControl, + Options, + NewRkey); +} + +FSTATUS +iba_destroy_mw( + IN IB_HANDLE MwHandle + ) +{ + VCA_MW_CONTEXT *vcaMwHandle = (VCA_MW_CONTEXT *)MwHandle; + FSTATUS status; + + status = vcaMwHandle->VpInterface->DestroyMemWindow(vcaMwHandle->VpHandle); + + if ( status == FSUCCESS ) + { + // Clear context so that future references fail + MemoryClear(vcaMwHandle, sizeof(VCA_MW_CONTEXT)); + MemoryDeallocate(vcaMwHandle); + } + + return status; +} + + +FSTATUS +iba_post_send( + IN IB_HANDLE QpHandle, + IN IB_WORK_REQ *WorkRequest + ) +{ + IB_WORK_REQ2 WorkRequest2; + + // for speed in data path we don't validate handles + WorkRequest2.Next = NULL; + WorkRequest2.DSList = WorkRequest->DSList; + WorkRequest2.WorkReqId = WorkRequest->WorkReqId; + WorkRequest2.MessageLen = WorkRequest->MessageLen; + WorkRequest2.DSListDepth = WorkRequest->DSListDepth; + WorkRequest2.Operation = WorkRequest->Operation; + switch ( ((VCA_QP_CONTEXT*)QpHandle)->Type ) + { + case QPTypeReliableConnected: + case QPTypeUnreliableConnected: + switch (WorkRequest->Operation) + { + case WROpRdmaWrite: + case WROpRdmaRead: + WorkRequest2.Req.SendRC.RemoteDS = WorkRequest->Req.SendRC.RemoteDS; + case WROpSend: + WorkRequest2.Req.SendRC.Options = WorkRequest->Req.SendRC.Options; + WorkRequest2.Req.SendRC.ImmediateData = WorkRequest->Req.SendRC.ImmediateData; + break; + case WROpFetchAdd: + case WROpCompareSwap: + WorkRequest2.Req.AtomicRC.Options = WorkRequest->Req.AtomicRC.Options; + WorkRequest2.Req.AtomicRC.RemoteDS = WorkRequest->Req.AtomicRC.RemoteDS; + WorkRequest2.Req.AtomicRC.SwapAddOperand = WorkRequest->Req.AtomicRC.SwapAddOperand; + WorkRequest2.Req.AtomicRC.CompareOperand = WorkRequest->Req.AtomicRC.CompareOperand; + break; + default: + break; + } + break; + case QPTypeReliableDatagram: + return FINVALID_OPERATION; /* not supported */ + break; + case QPTypeUnreliableDatagram: + case QPTypeSMI: + case QPTypeGSI: + WorkRequest2.Req.SendUD.Options = WorkRequest->Req.SendUD.Options; + WorkRequest2.Req.SendUD.PkeyIndex = WorkRequest->Req.SendUD.PkeyIndex; + WorkRequest2.Req.SendUD.ImmediateData = WorkRequest->Req.SendUD.ImmediateData; + WorkRequest2.Req.SendUD.QPNumber = WorkRequest->Req.SendUD.QPNumber; + WorkRequest2.Req.SendUD.Qkey = WorkRequest->Req.SendUD.Qkey; + WorkRequest2.Req.SendUD.AVHandle = WorkRequest->Req.SendUD.AVHandle; + break; +#if defined(INCLUDE_STLEEP) + case QPTypeSTLEEP: + /* This should never happen as there are no send options defined for an IB_WORK_REQ */ + /* Must use IB_WORK_REQ2 and ib_post_send2 */ + sysPrintf("%s: Sends for QPTypeSTLEEP must be issued through ib_post_send2.\n", __func__); + return FERROR; + break; +#endif + case QPTypeRawDatagram: + case QPTypeRawIPv6: + case QPTypeRawEthertype: + WorkRequest2.Req.SendRawD.QPNumber = WorkRequest->Req.SendRawD.QPNumber; + WorkRequest2.Req.SendRawD.DestLID = WorkRequest->Req.SendRawD.DestLID; + WorkRequest2.Req.SendRawD.PathBits = WorkRequest->Req.SendRawD.PathBits; + WorkRequest2.Req.SendRawD.ServiceLevel = WorkRequest->Req.SendRawD.ServiceLevel; + WorkRequest2.Req.SendRawD.SignaledCompletion = WorkRequest->Req.SendRawD.SignaledCompletion; + WorkRequest2.Req.SendRawD.SolicitedEvent = WorkRequest->Req.SendRawD.SolicitedEvent; + WorkRequest2.Req.SendRawD.StaticRate = WorkRequest->Req.SendRawD.StaticRate; + WorkRequest2.Req.SendRawD.EtherType = WorkRequest->Req.SendRawD.EtherType; + break; + } + return ((VCA_QP_CONTEXT*)QpHandle)->VpInterface->PostSend( + ((VCA_QP_CONTEXT*)QpHandle)->VpHandle, &WorkRequest2, NULL); +} + +FSTATUS +iba_post_recv( + IN IB_HANDLE QpHandle, + IN IB_WORK_REQ *WorkRequest + ) +{ + IB_WORK_REQ2_RECV WorkRequest2; + + // for speed in data path we don't validate handles + WorkRequest2.Next = NULL; + WorkRequest2.DSList = WorkRequest->DSList; + WorkRequest2.WorkReqId = WorkRequest->WorkReqId; + WorkRequest2.MessageLen = WorkRequest->MessageLen; + WorkRequest2.DSListDepth = WorkRequest->DSListDepth; + WorkRequest2.Operation = WorkRequest->Operation; + /* no Req fields for Recv */ + return ((VCA_QP_CONTEXT*)QpHandle)->VpInterface->PostRecv( + ((VCA_QP_CONTEXT*)QpHandle)->VpHandle, + (IB_WORK_REQ2*)&WorkRequest2, NULL); +} + +FSTATUS +iba_post_send2( + IN IB_HANDLE QpHandle, + IN IB_WORK_REQ2*WorkRequestList, + OUT IB_WORK_REQ2 **FailedWorkRequest OPTIONAL + ) +{ + CpuPrefetch(WorkRequestList); + return ((VCA_QP_CONTEXT*)QpHandle)->VpInterface->PostSend( + ((VCA_QP_CONTEXT*)QpHandle)->VpHandle, + WorkRequestList, FailedWorkRequest); +} + +/* fetch a VPD AV Handle given a VCA AV handle in a IB_WORK_REQ2 */ +IB_HANDLE +GetVpdAvHandle(IN IB_HANDLE IbaAvHandle) +{ + return ((VCA_AV_CONTEXT *)IbaAvHandle)->VpHandle; +} + +FSTATUS +iba_post_recv2( + IN IB_HANDLE QpHandle, + IN IB_WORK_REQ2*WorkRequestList, + OUT IB_WORK_REQ2 **FailedWorkRequest OPTIONAL + ) +{ + CpuPrefetch(WorkRequestList); + return ((VCA_QP_CONTEXT*)QpHandle)->VpInterface->PostRecv( + ((VCA_QP_CONTEXT*)QpHandle)->VpHandle, + WorkRequestList, FailedWorkRequest); +} + +FSTATUS +iba_poll_cq( + IN IB_HANDLE CqHandle, + OUT IB_WORK_COMPLETION *WorkCompletion + ) +{ + CpuPrefetch(WorkCompletion); + return ((VCA_CQ_CONTEXT*)CqHandle)->VpInterface->PollCQ( + ((VCA_CQ_CONTEXT*)CqHandle)->VpHandle, + WorkCompletion); +} + +FSTATUS +iba_peek_cq( + IN IB_HANDLE CqHandle, + IN uint32 NumWC + ) +{ + return ((VCA_CQ_CONTEXT*)CqHandle)->VpInterface->PeekCQ( + ((VCA_CQ_CONTEXT*)CqHandle)->VpHandle, NumWC); +} + +FSTATUS +iba_poll_and_rearm_cq( + IN IB_HANDLE CqHandle, + IN IB_CQ_EVENT_SELECT EventSelect, + OUT IB_WORK_COMPLETION *WorkCompletion + ) +{ + return ((VCA_CQ_CONTEXT*)CqHandle)->VpInterface->PollAndRearmCQ( + ((VCA_CQ_CONTEXT*)CqHandle)->VpHandle, + EventSelect, WorkCompletion); +} + +FSTATUS +iba_rearm_cq( + IN IB_HANDLE CqHandle, + IN IB_CQ_EVENT_SELECT EventSelect + ) +{ + return ((VCA_CQ_CONTEXT*)CqHandle)->VpInterface->RearmCQ( + ((VCA_CQ_CONTEXT*)CqHandle)->VpHandle, + EventSelect); +} + + +FSTATUS +iba_rearm_n_cq( + IN IB_HANDLE CqHandle, + IN uint16 NumWC + ) +{ + return ((VCA_CQ_CONTEXT*)CqHandle)->VpInterface->RearmNCQ( + ((VCA_CQ_CONTEXT*)CqHandle)->VpHandle, NumWC); +} + + +FSTATUS +default_poll_and_rearm_cq( + IN IB_HANDLE CqHandle, + IN IB_CQ_EVENT_SELECT EventSelect, + OUT IB_WORK_COMPLETION *WorkCompletion + ) +{ + // simplistic implementation, not optimized + // a more optimized version would be: + // validate all handles and arguments - error returns as needed + // get entry from CQ (if any) + // if CQ has more entries + // return FSUCCESS + // RearmCQ + // if CQ is now empty (must check again after Rearm) + // if got a CQE above + // return FCOMPLETED + // else + // return FNOT_DONE + // else + // return FPOLL_NEEDED + + FSTATUS status; + + status = iba_poll_cq(CqHandle, WorkCompletion); + if (FNOT_DONE == status) + { + // CQ now empty + status = iba_rearm_cq(CqHandle, EventSelect); + if (FSUCCESS == status) + { + status = iba_poll_cq(CqHandle, WorkCompletion); + if (FSUCCESS == status) + status = FPOLL_NEEDED; + } + } + + return status; +} + +// +// Private interfaces for the SMA and CM +// + +FSTATUS +iba_get_set_mad( + IN IB_HANDLE QpHandle, + IN uint8 PortNumber, + IN STL_LID SLID, + IN STL_SMP *SmpInOut, + IN uint32 *SmpLength + ) +{ + FSTATUS rc; + + BSWAP_STL_SMP_HEADER(SmpInOut); + rc = ((VCA_QP_CONTEXT*)QpHandle)->VpInterface->GetSetMad( + ((VCA_QP_CONTEXT*)QpHandle)->VpHandle, + PortNumber, + SLID, + (void*)SmpInOut, + SmpLength); + BSWAP_STL_SMP_HEADER(SmpInOut); + + return rc; +} + + +FSTATUS +iba_register_cm( + IN IB_HANDLE CaHandle + ) +{ + VCA_CA_CONTEXT *vcaCaHandle = (VCA_CA_CONTEXT *)CaHandle; + + return vcaCaHandle->VpInterface->RegisterConnMgr(vcaCaHandle->VpHandle); +} + + +// +// Private interfaces to the user-mode VP component +// + + +FSTATUS +iba_query_ca_private_info( + IN IB_HANDLE CaHandle, + IN OUT uint32 *BufferSize, + OUT void *Buffer + ) +{ + VCA_CA_CONTEXT *vcaCaHandle = (VCA_CA_CONTEXT *)CaHandle; + + if (! vcaCaHandle->VpInterface->QueryCAPrivateInfo) + return FINVALID_OPERATION; + return vcaCaHandle->VpInterface->QueryCAPrivateInfo(vcaCaHandle->VpHandle, + BufferSize, + Buffer ); +} + + +FSTATUS +iba_query_pd_private_info( + IN IB_HANDLE PdHandle, + IN OUT uint32 *BufferSize, + OUT void *Buffer + ) +{ + if (! ((VCA_PD_CONTEXT*)PdHandle)->VpInterface->QueryPDPrivateInfo) + return FINVALID_OPERATION; + return ((VCA_PD_CONTEXT*)PdHandle)->VpInterface->QueryPDPrivateInfo( + ((VCA_PD_CONTEXT*)PdHandle)->VpHandle, + BufferSize, Buffer ); +} + +FSTATUS +iba_query_qp_private_info( + IN IB_HANDLE QpHandle, + IN OUT uint32 *BufferSize, + OUT void *Buffer + ) +{ + if (! ((VCA_QP_CONTEXT*)QpHandle)->VpInterface->QueryQPPrivateInfo) + return FINVALID_OPERATION; + return ((VCA_QP_CONTEXT*)QpHandle)->VpInterface->QueryQPPrivateInfo( + ((VCA_QP_CONTEXT*)QpHandle)->VpHandle, + BufferSize, Buffer ); +} + + +FSTATUS +iba_query_cq_private_info( + IN IB_HANDLE CqHandle, + IN OUT uint32 *BufferSize, + OUT void *Buffer + ) +{ + if ( ! ((VCA_CQ_CONTEXT*)CqHandle)->VpInterface->QueryCQPrivateInfo) + return FINVALID_OPERATION; + return ((VCA_CQ_CONTEXT*)CqHandle)->VpInterface->QueryCQPrivateInfo( + ((VCA_CQ_CONTEXT*)CqHandle)->VpHandle, + BufferSize, Buffer ); +} + + +FSTATUS +iba_query_av_private_info( + IN IB_HANDLE AvHandle, + IN OUT uint32 *BufferSize, + OUT void *Buffer + ) +{ + VCA_AV_CONTEXT *vcaAvHandle = (VCA_AV_CONTEXT *)AvHandle; + + if (! vcaAvHandle->VpInterface->QueryAVPrivateInfo) + return FINVALID_OPERATION; + return vcaAvHandle->VpInterface->QueryAVPrivateInfo(vcaAvHandle->VpHandle, + BufferSize, + Buffer ); +} diff --git a/IbAccess/Common/Ibt/Vca/vp_debug.h b/IbAccess/Common/Ibt/Vca/vp_debug.h new file mode 100644 index 0000000..d028873 --- /dev/null +++ b/IbAccess/Common/Ibt/Vca/vp_debug.h @@ -0,0 +1,118 @@ +/* BEGIN_ICS_COPYRIGHT6 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT6 ****************************************/ +/* [ICS VERSION STRING: unknown] */ + +// Suppress duplicate loading of this file +#ifndef _INTEL_VP_DEBUG_H_ +#define _INTEL_VP_DEBUG_H_ + + +#define _DBG_PRINT_EPILOG(LEVEL,STRING) +#define _DBG_PRINT_PROLOG(LEVEL,STRING) +#define _DBG_ERROR_EPILOG(LEVEL,STRING) +#define _DBG_ERROR_PROLOG(LEVEL,STRING) +#define _DBG_FATAL_EPILOG(LEVEL,STRING) +#define _DBG_FATAL_PROLOG(LEVEL,STRING) + +#include "ib_debug_osd.h" + +#if defined(IB_DEBUG) ||defined( DBG) // Define file contents only on checked builds + +// +// Range reserved for component specific values is 0x00000001 - 0x00FFFFFF +// +#define _DBG_LVL_CALL ((uint32)0x00000001) // exported call interface functions +#define _DBG_LVL_EVENT ((uint32)0x00000002) // Event Queue handling control path +#define _DBG_LVL_INTR ((uint32)0x00000004) // Interrupt handler +#define _DBG_LVL_TPT ((uint32)0x00000008) // TPT management +// +#define _DBG_LVL_MEM_ALLOC ((uint32)0x00000010) +#define _DBG_LVL_TIMERS ((uint32)0x00000020) +#define _DBG_LVL_SMP ((uint32)0x00000040) // SMP processing +#define _DBG_LVL_MAD ((uint32)0x00000080) // MAD processing +// +#define _DBG_LVL_PNP ((uint32)0x00000100) // Plug and Play decisions +#define _DBG_LVL_POWER ((uint32)0x00000200) // Power management decisions +#define _DBG_LVL_SYSTEM_CONTROL ((uint32)0x00000400) // System control decisions + +#define _DBG_ENTER _DBG_ENTER_EXT +#define _DBG_LEAVE _DBG_LEAVE_EXT + +#define _DBG_CALL(STRING) \ + _DBG_PRINT (_DBG_LVL_CALL, STRING); + +#define _DBG_EVENT(STRING) \ + _DBG_PRINT (_DBG_LVL_EVENT, STRING); + +#define _DBG_INTR(STRING) \ + _DBG_PRINT (_DBG_LVL_INTR, STRING); + +#define _DBG_TPT(STRING) \ + _DBG_PRINT (_DBG_LVL_TPT, STRING); + +#define _DBG_MEM_ALLOC(STRING) \ + _DBG_PRINT (_DBG_LVL_MEM_ALLOC, STRING); + +#define _DBG_PNP(STRING) \ + _DBG_PRINT (_DBG_LVL_PNP, STRING); + +#define _DBG_POWER(STRING) \ + _DBG_PRINT (_DBG_LVL_POWER, STRING); + +#define _DBG_SYSCTL(STRING) \ + _DBG_PRINT (_DBG_LVL_SYSTEM_CONTROL, STRING); + +#else // _DEBUG || DBG + +#include "ib_debug.h" + +#define _DBG_LVL_CALL 0 +#define _DBG_LVL_EVENT 0 +#define _DBG_LVL_INTR 0 +#define _DBG_LVL_TPT 0 +#define _DBG_LVL_MEM_ALLOC 0 +#define _DBG_LVL_TIMERS 0 +#define _DBG_LVL_SMP 0 +#define _DBG_LVL_MAD 0 +#define _DBG_LVL_PNP 0 +#define _DBG_LVL_POWER 0 +#define _DBG_LVL_SYSTEM_CONTROL 0 + +#define _DBG_PNP(STRING) +#define _DBG_POWER(STRING) +#define _DBG_SYSCTL(STRING) +#define _DBG_CALL(STRING) +#define _DBG_EVENT(STRING) +#define _DBG_INTR(STRING) +#define _DBG_TPT(STRING) + +#endif // _DEBUG || DBG + + +#endif // _INTEL_VP_DEBUG_H_ diff --git a/IbAccess/Common/Ibt/ibt.sln b/IbAccess/Common/Ibt/ibt.sln new file mode 100644 index 0000000..25de914 --- /dev/null +++ b/IbAccess/Common/Ibt/ibt.sln @@ -0,0 +1,33 @@ +Microsoft Visual Studio Solution File, Format Version 7.00 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cm", "Cm\cm.vcproj", "{E0AB4A3D-7415-4CF4-AC51-C95B4865AD5A}" +EndProject +Global + GlobalSection(SourceCodeControl) = preSolution + SccNumberOfProjects = 2 + SccProjectName0 = vendor/linux/Iba/Common/Ibt + SccLocalPath0 = . + SccProvider0 = MSSCCI:Jalindi\u0020Igloo + CanCheckoutShared = true + SolutionUniqueID = {17707F23-D962-4622-96E5-E2327B21077C} + SccProjectUniqueName1 = Cm\\cm.vcproj + SccLocalPath1 = . + CanCheckoutShared = true + SccProjectFilePathRelativizedFromConnection1 = Cm\\ + EndGlobalSection + GlobalSection(SolutionConfiguration) = preSolution + ConfigName.0 = Debug + ConfigName.1 = Release + EndGlobalSection + GlobalSection(ProjectDependencies) = postSolution + EndGlobalSection + GlobalSection(ProjectConfiguration) = postSolution + {E0AB4A3D-7415-4CF4-AC51-C95B4865AD5A}.Debug.ActiveCfg = Debug|Win32 + {E0AB4A3D-7415-4CF4-AC51-C95B4865AD5A}.Debug.Build.0 = Debug|Win32 + {E0AB4A3D-7415-4CF4-AC51-C95B4865AD5A}.Release.ActiveCfg = Release|Win32 + {E0AB4A3D-7415-4CF4-AC51-C95B4865AD5A}.Release.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + EndGlobalSection + GlobalSection(ExtensibilityAddIns) = postSolution + EndGlobalSection +EndGlobal diff --git a/IbAccess/Common/Inc/README b/IbAccess/Common/Inc/README new file mode 100644 index 0000000..5ac11f6 --- /dev/null +++ b/IbAccess/Common/Inc/README @@ -0,0 +1,32 @@ +// Defines APIs to IBAccess and datastructures used by the Interface + +// Common (User/Application or Kernel access) +ib_types.h - primary data types for IB +vpi.h - data types used as arguments to verbs +ib_mad.h - IB MAD packet headers +ib_pkt.h - IB Link, Network and Transport layer packet headers +ib_sm.h - SMA/SMI packets +ib_sd.h - Subnet Data interfaces for User and Kernel +ib_generalServices.h - GSI packet headers +ib_sa_records.h - SA packets + + +// For User/Application space access +uvca_exp.h - User Verbs +umadt.h - User SMI/GSI interface + +// For Kernel access +ibt.h - interface function tables +vpi_export.h - kernel verbs +ib_gsi.h - Kernel GSI +ib_smi.h - Kernel SMI +SvcLib.h - Kernel TSL +ib_cm.h - Kernel CM +ib_ibt.h - Kernel CA and Notification handling + + +// Omit +bldver.h - intel source version +ib_status.h - TBD defines to build FSTATUS codes +ib_helper.h - internal helper functions +ib_debug.h - internal debug interfaces diff --git a/IbAccess/Common/Inc/bldver.h b/IbAccess/Common/Inc/bldver.h new file mode 100644 index 0000000..30e1ef3 --- /dev/null +++ b/IbAccess/Common/Inc/bldver.h @@ -0,0 +1,65 @@ +/* BEGIN_ICS_COPYRIGHT3 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT3 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +#ifndef _IBA_BLD_VER_H_ +#define _IBA_BLD_VER_H_ + +#ifndef VXWORKS +#include "bldver_osd.h" +#else +/* ???? for vxworks ??? */ +#endif + +/* TBD BUGBUG should use patch_version compatible version strings */ +#ifdef MODULEVERSION +#define BLD_VER_STR(a) #a +#define BLD_VER_STR1(a) BLD_VER_STR(a) +#if defined(DBG) ||defined( IB_DEBUG) +#define BLD_VERSION_STRING "debug " BLD_VER_STR1(MODULEVERSION) +#else +#define BLD_VERSION_STRING BLD_VER_STR1(MODULEVERSION) +#endif +#else +#define BLD_VERSION_STRING "2.0" +#endif /* MODULEVERSION */ + +#undef VER_COMPANYNAME_STR +#define VER_COMPANYNAME_STR "Intel Corporation" + +#define VER_LEGALCOPYRIGHT_YEARS "2000-2001" +#define VER_LEGALCOPYRIGHT_STR "Copyright (C) " VER_LEGALCOPYRIGHT_YEARS " " VER_COMPANYNAME_STR + +#undef VER_PRODUCTVERSION_STR +#define VER_PRODUCTVERSION_STR BLD_VERSION_STRING +/* To be defined in the component's resource file */ +#undef VER_PRODUCTNAME_STR + +#endif /* _IBA_BLD_VER_H_ */ diff --git a/IbAccess/Common/Inc/cm_params.h b/IbAccess/Common/Inc/cm_params.h new file mode 100644 index 0000000..19e425a --- /dev/null +++ b/IbAccess/Common/Inc/cm_params.h @@ -0,0 +1,99 @@ +/* BEGIN_ICS_COPYRIGHT4 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT4 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +/* Suppress duplicate loading of this file */ +#ifndef _IBA_IB_CM_PARAMS_H_ +#define _IBA_IB_CM_PARAMS_H_ + + +#if defined (__cplusplus) +extern "C" { +#endif + +#include "datatypes.h" + +/* default values for CM tunable parameters */ +#define CM_MAX_NDGRM 30000 /* This should be >= # of QP */ +#define CM_MAX_CONNECTIONS 2048 /* CEP limit in CmWait */ +#define CM_REQ_RETRY 8 /* REQ and SIDR_REQ */ +#define CM_REP_RETRY 8 /* REP */ + /* controls over growth of Cm Dgrm Pool */ +#define CM_DGRM_INITIAL 2048 /* initial size */ +#define CM_DGRM_LOW_WATER 100 /* low water point */ +#define CM_DGRM_INCREMENT 500 /* amount to grow by */ + +/* Default Max backlog for a passive endpoint before we start */ +/* discarding incoming connection requests or mark the passive */ +/* endpoint as dead (adjustable per CEP via CmModifyCEP) */ +#define CM_MAX_BACKLOG 1024 + +/* Initial average turnaround time */ +#define CM_TURNAROUND_TIME_MS 60 /* 60 ms */ + +/* Default Min turnaround time setting (bounds avg and CmModifyCEP setting) */ +#define CM_MIN_TURNAROUND_TIME_MS 40 /* 40 ms */ + +/* Default Max turnaround time setting (bounds avg and CmModifyCEP setting) */ +#define CM_MAX_TURNAROUND_TIME_MS 4000 /* 4 seconds */ + +/* Default SIDR req timeout */ +#define SIDR_REQ_TIMEOUT_MS 8 /* 8 ms */ + +/* if 1, allow QP to be reused in TimeWait state */ +#define CM_REUSE_QP 0 + +/* if 1, don't check PKey and GID validity */ +#define CM_DISABLE_VALIDATION 0 + +typedef struct _CM_PARAMS { + uint32 MaxDgrms; + uint32 PreallocDgrms; + uint32 MinFreeDgrms; + uint32 DgrmIncrement; + uint32 MaxConns; + uint32 MaxReqRetry; + uint32 MaxRepRetry; + uint32 MaxBackLog; + uint32 SidrReqTimeoutMs; /* CPU processing part of timeout */ + uint32 TurnaroundTimeMs; + uint32 MinTurnaroundTimeMs; + uint32 MaxTurnaroundTimeMs; + uint32 ReuseQP; + uint32 DisableValidation; +} CM_PARAMS; + +extern CM_PARAMS gCmParams; + +#if defined (__cplusplus) +}; +#endif + +#endif /* _IBA_IB_CM_PARAMS_H_ */ diff --git a/IbAccess/Common/Inc/gsi_params.h b/IbAccess/Common/Inc/gsi_params.h new file mode 100644 index 0000000..b2e671f --- /dev/null +++ b/IbAccess/Common/Inc/gsi_params.h @@ -0,0 +1,97 @@ +/* BEGIN_ICS_COPYRIGHT4 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT4 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +/* Suppress duplicate loading of this file */ +#ifndef _INSI_IB_GSI_PARAMS_H_ +#define _INSI_IB_GSI_PARAMS_H_ + + +#if defined (__cplusplus) +extern "C" { +#endif + +#include "datatypes.h" + +/* + * Configuration Parameters + * + * WorkQEntries is the maximum number of entries on each WQ + * The smaller of this and the maximum described in the channel + * adapter attributes is used in the create attributes when creating + * a special QP. + */ + +typedef struct _GSA_GLOBAL_CONFIG_PARAMETERS { + uint32 SendQDepth; + uint32 RecvQDepth; + + /*uint32 DefaultQP1PKeyIndex; */ + + uint32 PreAllocRecvBuffersPerPort; /* Number of Buffers to create*/ + /* in Pool for each port */ + uint32 MinBuffersToPostPerPort; /* Number of buffers to post */ + /* per port */ + uint32 MaxRecvBuffers; /* Max. buffers that can be */ + /* allocated on a system */ + uint32 FullPacketDump; /* make error dump more verbose */ + /* BUGBUG, some of these are not used */ +} GSA_GLOBAL_CONFIG_PARAMETERS; + + +/* default values for GSI tunable parameters */ +/* module parameters can override */ +#define GSA_SENDQ_DEPTH 8192 +#define GSA_RECVQ_DEPTH 8192 +#ifdef VXWORKS +#define GSA_PREALLOC_RECV_PER_PORT 200 +#define GSA_MIN_RECV_PER_PORT 128 +#define GSA_MAX_RECV_BUFFERS 512 +#else +#define GSA_PREALLOC_RECV_PER_PORT 500 +#define GSA_MIN_RECV_PER_PORT 60 +#define GSA_MAX_RECV_BUFFERS 8000 +#endif + +#define GSA_DEFAULT_SETTINGS { \ + GSA_SENDQ_DEPTH, GSA_RECVQ_DEPTH, \ + /*0,*/ \ + GSA_PREALLOC_RECV_PER_PORT, \ + GSA_MIN_RECV_PER_PORT, \ + GSA_MAX_RECV_BUFFERS \ + } + +extern GSA_GLOBAL_CONFIG_PARAMETERS g_GsaSettings; + +#if defined (__cplusplus) +}; +#endif + +#endif /* _INSI_IB_GSI_PARAMS_H_ */ diff --git a/IbAccess/Common/Inc/ib_avtracker.h b/IbAccess/Common/Inc/ib_avtracker.h new file mode 100644 index 0000000..5434fc6 --- /dev/null +++ b/IbAccess/Common/Inc/ib_avtracker.h @@ -0,0 +1,317 @@ +/* BEGIN_ICS_COPYRIGHT3 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT3 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +#ifndef _IBA_IB_AVTRACKER_H_ +#define _IBA_IB_AVTRACKER_H_ + +/* AV Tracker to help manage AVs, especially multicast AVs + * + * The AV tracker is used to track the current AV to send to a destination. + * It also helps in handling the reference counting problem by + * tracking previous AVs until their reference count hits zero. + * + * Typically 1 AV Tracker would be created per destination (such as a MC group) + * and the current AV would reflect the latest AV for sending to that group. + * When path record queries or Multicast joins succeed, a corresponding AV + * should be created and IbAvTrackerSetCurrent. If the patch record is stale + * or the Multicast join is lost (port down, etc), the current should be cleared + * via IbAvTrackerClearCurrent. + * + * Of course, AVs cannot be destroyed until all send WQEs which use them have + * completed. To this end, the AV tracker keeps a reference count per AV + * and manages the destroy. Each time a send needs to occur to the destination, + * IbAvTrackerGetCurrent should be called. The incRef argument will cause the + * reference count for the AV to be incremented to prevent its destruction + * while in use. When the send completion occurs, IbAvTrackerDecRef should be + * called. This will destroy the AV when its count reaches 0 [SetCurrent counts + * as a reference so the current AV will not be destroyed by DecRef]. + * + * The actual meaning of references for GetCurrent/IncRef/DecRef is up to + * the caller. For example 1 reference count be counted per WQE. An + * alternative could be to count 1 reference per scheduled completion. + */ + +#include "iba/public/datatypes.h" +#include "iba/public/ilist.h" +#include "iba/public/ispinlock.h" +#include "iba/public/imemory.h" + +#if defined (__cplusplus) +extern "C" { +#endif + +/* private internal structure */ +typedef struct _AV_WRAP { + LIST_ITEM listItem; /* AV_TRACKER.avList entry */ + IB_HANDLE avHandle; + ATOMIC_UINT refCount; +} AV_WRAP; + +typedef struct _AV_TRACKER { + SPIN_LOCK lock; + AV_WRAP *currentAV; /* current AV for MC group */ + QUICK_LIST avList; /* list of all active AVs in tracker */ + IB_HANDLE caHandle; /* open CA to create AVs against */ + IB_HANDLE pdHandle; /* open PD to create AVs against */ +} AV_TRACKER; + +/*++ + +Routine Description + zero out fields in AV_TRACKER + +Input: + pTracker: AV tracker object to initialize + +Output: + None +--*/ +extern void +IbAvTrackerInitState( + IN AV_TRACKER *pTracker + ); + +/*++ + +Routine Description + Initialize AV_TRACKER + +Input: + pTracker: AV tracker object to initialize + caHandle: Open CA instance used to create AVs + pdHandle: PD instance used to create AVs + +Output: + status of the operation + +Additional Information: + caHandle and pdHandle are only used if IbAvTrackerMulticastCallback is used +--*/ +extern FSTATUS +IbAvTrackerInit( + IN AV_TRACKER *pTracker, + IN IB_HANDLE caHandle, + IN IB_HANDLE pdHandle + ); + +/*++ + +Routine Description + Destroy AV_TRACKER + +Input: + pTracker: AV tracker object to destroy + +Output: + status of the operation + +Additional Information: + Any AVs still in the IbAvTracker will be destroyed by this + operation. + +--*/ +extern void +IbAvTrackerDestroy( + IN AV_TRACKER *pTracker + ); + + +/*++ + +Routine Description + Get current AV for tracker + +Input: + pTracker: AV tracker object to act on + incRef: should reference count for returned AV be incremented + +Output: + AV handle of current AV, can be NULL if no current AV + +Additional Information: + Current AV is the last one Created/Set for the tracker + This typically indicates the most recent path to the destination + +--*/ +extern IB_HANDLE +IbAvTrackerGetCurrent( + IN AV_TRACKER *pTracker, + IN boolean incRef + ); + +/*++ + +Routine Description + Clear current AV for tracker + +Input: + pTracker: AV tracker object to act on + +Output: + none + +Additional Information: + If there is no current AV, this is a noop + Reference count of current AV is decremented, if 0 its AV is destroyed + Otherwise its will not be destroyed until a future IbAvTrackerDecRef + +--*/ +extern void +IbAvTrackerClearCurrent( + IN AV_TRACKER *pTracker + ); + +/*++ + +Routine Description + Set current AV for tracker + +Input: + pTracker: AV tracker object to act on + avHandle: AV to set as current AV + +Output: + status of the operation + +Additional Information: + If the given AV is not already in the tracker, it is added + If it is already current AV, this is a noop + If there is an existing different current AV, it is cleared first + +--*/ +extern FSTATUS +IbAvTrackerSetCurrent( + IN AV_TRACKER *pTracker, + IN IB_HANDLE avHandle + ); + +/*++ + +Routine Description + increment reference count for an AV in tracker + +Input: + pTracker: AV tracker object to act on + avHandle: AV to increment reference count on + +Output: + status of operation + +Additional Information: + If the given AV is not already in the tracker, this fails + +--*/ +extern FSTATUS +IbAvTrackerIncRef( + IN AV_TRACKER *pTracker, + IN IB_HANDLE avHandle + ); + +/*++ + +Routine Description + decrement reference count for an AV in tracker + +Input: + pTracker: AV tracker object to act on + avHandle: AV to decrement reference count on + +Output: + status of operation + +Additional Information: + If the given AV is not already in the tracker, this fails + If reference count reaches 0, AV is removed from tracker and destroyed + +--*/ +extern FSTATUS +IbAvTrackerDecRef( + IN AV_TRACKER *pTracker, + IN IB_HANDLE avHandle + ); + +/*++ + +Routine Description + subtract from reference count for an AV in tracker + +Input: + pTracker: AV tracker object to act on + avHandle: AV to decrement reference count on + count: amount to subtract from reference count + +Output: + status of operation + +Additional Information: + Can be used to aid reference counting when completion coallescing used + If the given AV is not already in the tracker, this fails + If reference count reaches 0, AV is removed from tracker and destroyed + +--*/ +extern FSTATUS +IbAvTrackerSubtractRef( + IN AV_TRACKER *pTracker, + IN IB_HANDLE avHandle, + IN uint32 count + ); +/*++ + +Routine Description + Av tracker routine which can be used for iba_sd_join_mcgroup callback + +Input: + pContext: AV tracker object to act on + Status: as provided from SD_MULTICAST_CALLBACK + State: as provided from SD_MULTICAST_CALLBACK + pMcMemberRecord: as provided from SD_MULTICAST_CALLBACK + +Output: + None + +Additional Information: + If the given AV is not already in the tracker, this fails + If reference count reaches 0, AV is removed from tracker and destroyed + +--*/ +extern void +IbAvTrackerMulticastCallback( + IN void *pContext, + IN FSTATUS Status, + IN MC_GROUP_STATE State, + IN IB_MCMEMBER_RECORD *pMcMemberRecord + ); + +#if defined (__cplusplus) +}; +#endif + +#endif /* _IBA_IB_AVTRACKER_H_ */ diff --git a/IbAccess/Common/Inc/ib_bm.h b/IbAccess/Common/Inc/ib_bm.h new file mode 100644 index 0000000..8f01e34 --- /dev/null +++ b/IbAccess/Common/Inc/ib_bm.h @@ -0,0 +1,320 @@ +/* BEGIN_ICS_COPYRIGHT3 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT3 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +#ifndef _IBA_IB_BM_H_ +#define _IBA_IB_BM_H_ (1) /* suppress duplicate loading of this file */ + +#include "iba/public/datatypes.h" +#include "iba/public/ibyteswap.h" +#include "iba/ib_generalServices.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#include "iba/public/ipackon.h" + +/* Baseboard Management methods */ +#define BASEMGT_GET 0x01 /* MMTHD_GET */ +#define BASEMGT_SET 0x02 /* MMTHD_SET */ +#define BASEMGT_SEND 0x03 /* MMTHD_SEND */ +#define BASEMGT_TRAP 0x05 /* MMTHD_TRAP */ +#define BASEMGT_REPORT 0x06 /* MMTHD_REPORT */ +#define BASEMGT_TRAP_REPRESS 0x07 /* MMTHD_TRAP_REPRESS */ +#define BASEMGT_GET_RESP 0x81 /* MMTHD_GET_RESP */ +#define BASEMGT_REPORT_RESP 0x86 /* MMTHD_REPORT_RESP */ + + +/* Baseboard Management Attributes IDs Attribute Modifier values */ +#define BM_ATTRIB_ID_CLASS_PORTINFO 0x0001 /* 0x0000_0000 */ +#define BM_ATTRIB_ID_NOTICE 0x0002 /* 0x0000_0000 */ +#define BM_ATTRIB_ID_BKEY_INFO 0x0010 /* 0x0000_0000 */ + +#define BM_ATTRIB_ID_WRITE_VPD 0x0020 /* 0x0000_0000-0x0000_0001*/ +#define BM_ATTRIB_ID_READ_VPD 0x0021 /* 0x0000_0000-0x0000_0001*/ +#define BM_ATTRIB_ID_RESET_IBML 0x0022 /* 0x0000_0000-0x0000_0001*/ +#define BM_ATTRIB_ID_SET_MODULE_PM_CONTROL 0x0023 /* 0x0000_0000-0x0000_0001*/ +#define BM_ATTRIB_ID_GET_MODULE_PM_CONTROL 0x0024 /* 0x0000_0000-0x0000_0001*/ +#define BM_ATTRIB_ID_SET_UNIT_PM_CONTROL 0x0025 /* 0x0000_0000-0x0000_0001*/ +#define BM_ATTRIB_ID_GET_UNIT_PM_CONTROL 0x0026 /* 0x0000_0000-0x0000_0001*/ +#define BM_ATTRIB_ID_SET_IOC_PM_CONTROL 0x0027 /* 0x0000_0000-0x0000_0001*/ +#define BM_ATTRIB_ID_GET_IOC_PM_CONTROL 0x0028 /* 0x0000_0000-0x0000_0001*/ +#define BM_ATTRIB_ID_SET_MODULE_STATE 0x0029 /* 0x0000_0000-0x0000_0001*/ +#define BM_ATTRIB_ID_SET_MODULE_ATTENTION 0x002a /* 0x0000_0000-0x0000_0001*/ +#define BM_ATTRIB_ID_GET_MODULE_STATUS 0x002b /* 0x0000_0000-0x0000_0001*/ +#define BM_ATTRIB_ID_IB2IBML 0x002c /* 0x0000_0000-0x0000_0001*/ +#define BM_ATTRIB_ID_IB2CME 0x002d /* 0x0000_0000-0x0000_0001*/ +#define BM_ATTRIB_ID_IB2MME 0x002e /* 0x0000_0000-0x0000_0001*/ +#define BM_ATTRIB_ID_OEM 0x002f /* 0x0000_0000-0x0000_0001*/ + + /* Baseboard Management Vendor ID */ +#define BM_OEM_TRUESCALE_VENDOR_ID_BYTE_0 0x00 +#define BM_OEM_TRUESCALE_VENDOR_ID_BYTE_1 0x06 +#define BM_OEM_TRUESCALE_VENDOR_ID_BYTE_2 0x6A + + /* Definitions moved to ib_mad.h header file */ +/*#define BM_ATTRIB_MOD_REQUEST 0x0000 */ +/*#define BM_ATTRIB_MOD_RESPONSE 0x0001 */ + +/* + * BMA Class Port Info + */ + + /* Class-specific Capability Mask bits */ +#define BM_CLASS_PORT_CAPMASK_IS_IBML_SUPPORTED 0x0100 +#define BM_CLASS_PORT_CAPMASK_IS_BKEY_NVRAM 0x0200 + +/* + * BMA Notices/Traps (Data field for IB_NOTICE, see ib_mad.h) + */ + + /* Trap Numbers */ +#define BMA_TRAP_BAD_BKEY 259 /* Any bad B_key */ +#define BMA_TRAP_BM_TRAP 260 /* BMA Trap */ + +/* bad B_Key, from attempted */ +/* with and */ +typedef struct _BMA_TRAP_DATA_BAD_BKEY { + uint16 RequestorLID; /* LID which attempted access */ + uint8 Method; + uint8 Reserved1; + uint16 AttributeID; + uint32 AttributeModifier; + union { + uint32 AsReg32; + + struct { +#if CPU_BE + uint32 Reserved2: 8; + uint32 SenderQP: 24; +#else + uint32 SenderQP: 24; + uint32 Reserved2: 8; +#endif + } s; + } u1; + uint64 B_Key; /* The 8-byte management key. */ + IB_GID SenderGID; +} PACK_SUFFIX BMA_TRAP_DATA_BAD_BKEY; + +/* BM Trap: */ + /* TrapType values in BMA_TRAP_DATA_BM_TRAP */ +typedef enum _BM_TRAP_TYPE { + BM_TRAP_TYPE_MME = 0x00, + BM_TRAP_TYPE_OEM_MME = 0x01, + BM_TRAP_TYPE_CME_RTR = 0x02, + BM_TRAP_TYPE_WRE = 0x03, + BM_TRAP_TYPE_CME = 0x04, + BM_TRAP_TYPE_OEM_CME = 0x05, + /* 0x05-0xff reserved */ +} BM_TRAP_TYPE; + +typedef struct _BMA_TRAP_DATA_BM_TRAP { + uint8 DataLength; + uint8 TrapType; + uint8 TrapTypeModifier[3]; + uint8 TrapData[49]; +} PACK_SUFFIX BMA_TRAP_DATA_BM_TRAP; + +/* + * BKeyInfo + */ +typedef struct _BKEY_INFO { + uint64 B_Key; /* The 8-byte management key. */ + union { + uint16 AsReg16; + + struct { +#if CPU_BE + uint16 B_KeyProtectBit: 1; + uint16 Reserved1: 15; +#else + uint16 Reserved1: 15; + uint16 B_KeyProtectBit: 1; +#endif + } s; + } u1; + uint16 B_KeyLeasePeriod; /* in seconds, 0=infinite */ + uint16 B_KeyViolations; /* read-only, 0xffff if not supported */ +} PACK_SUFFIX BKEY_INFO; + +/* + * All other BM operations (all use BASEMGT_SEND Method) + * Baseboard Management parameter size: Volume 2, Section 13.6.1.1, Table 135 + * The maximum length is 40 bytes in 1.2.1 spec. for the BMParameters field. + * In order to support IPv6 address for the BM OEM CHASSIS IP request, this + * field had to be extended; thereby, using some of the Reserve field, which + * follows the BMParameters field. The spec. indicates that this Reserve field + * is used as a filler to produce the required 192 byte MAD Data Field. Content is + * unspecified. + */ +typedef struct _BM_SEND { + uint16 Sequence; /* incremented on Requests */ + uint8 SourceDevice; /* IBML_DEV_ID for source device */ + uint8 ParamCount; /* number of bytes in Parameters field, 1-based */ + uint8 Parameters[64]; /* ParamCount command-specific parameters */ + uint8 Reserved[124]; /* Filler to produce the required 192 byte */ +} PACK_SUFFIX BM_SEND; + +typedef enum _BM_DEV_ID { + BM_DEV_UNSPECIFIED = 0x00, + BM_DEV_MME = 0xe0, + BM_DEV_CME = 0xe8, + BM_DEV_BM = 0xfe +} BM_DEV_ID; + +typedef enum _BM_OEM_TRUESCALE_METHOD { + BM_OEM_TRUESCALE_METHOD_GET = 0x0001, + BM_OEM_TRUESCALE_METHOD_SET = 0x0002 +} BM_OEM_TRUESCALE_METHOD; + +typedef enum _BM_OEM_TRUESCALE_ATTRIBUTE { + BM_OEM_TRUESCALE_ATTR_FT_STAT = 0x0001, + BM_OEM_TRUESCALE_ATTR_PS_STAT = 0x0002, + BM_OEM_TRUESCALE_ATTR_READ_VPD = 0x0003, + BM_OEM_TRUESCALE_ATTR_SLOT_STAT = 0x0004, + BM_OEM_TRUESCALE_ATTR_CHASSIS_IP = 0x0005, + BM_OEM_TRUESCALE_ATTR_EXT_SLOT_STAT = 0x0006 +} BM_OEM_TRUESCALE_ATTRIBUTE; + +typedef struct _BM_OEM_TRUESCALE_CMD { + uint8_t vendorId[3]; /* Vendor ID */ + uint8_t method; /* Get/Set method identifier */ + uint16_t attrId; /* Attribute identifier */ +} BM_OEM_TRUESCALE_CMD; + +/* + * BM OEM chassis IP address structure + */ +#define BM_OEM_CHASSIS_IP_LEN 46 // INET6_ADDRSTRLEN + +typedef struct _BM_OEM_TRUESCALE_CHASSIS_IP { + uint8_t chassisIP[BM_OEM_CHASSIS_IP_LEN]; +} BM_OEM_TRUESCALE_CHASSIS_IP; + + + +#define BM_REQ_GET_VPD_DEVICE(p) ((p)->Parameters[0]) +#define BM_REQ_GET_VPD_NUM_BYTES(p) (((uint16)(p)->Parameters[1] << 8) | ((uint16)(p)->Parameters[2]) ) +#define BM_REQ_GET_VPD_OFFSET(p) (((uint16)(p)->Parameters[3] << 8) | ((uint16)(p)->Parameters[4]) ) +#define BM_REQ_WRITE_VPD_DATA_PTR(p) (&(p)->Parameters[5]) +#define BM_RSP_SET_STATUS(p, v) ((p)->Parameters[0] = (v)) +#define BM_RSP_READ_VPD_DATA_PTR(p) (&(p)->Parameters[1]) +#define BM_RSP_MODULE_STATUS_DATA_PTR(p) (&(p)->Parameters[1]) + +#define BM_REQ_GET_OEM_VENDOR_ID(p) (((uint32)(p)->Parameters[0] << 16) | \ + ((uint32)(p)->Parameters[1] << 8) | ((uint32)(p)->Parameters[2]) ) +#define BM_REQ_GET_OEM_NUM_BYTES(p) ((p)->ParamCount - 3) +#define BM_REQ_OEM_DATA_PTR(p) (&(p)->Parameters[3]) +#define BM_RSP_SET_OEM_VENDOR_ID(p, v) (((p)->Parameters[1] = (((v) >> 16))), \ + ((p)->Parameters[2] = (((v) >> 8))), ((p)->Parameters[3] = (v))) +#define BM_RSP_SET_OEM_NUM_BYTES(p, n) ((p)->ParamCount = (n) + 4) +#define BM_RSP_OEM_DATA_PTR(p) (&(p)->Parameters[4]) +#define BM_RSP_GET_OEM_CHASSIS_IP(p, ipAddr) (memcpy((void *)ipAddr,(void *)&(p)->Parameters[7],(p)->ParamCount - 4)) + +#define BM_REQ_GET_OEM_VPD_SLOT_ID(p) (p[3]) +#define BM_REQ_GET_OEM_VPD_NUM_BYTES(p) (((uint16)p[4] << 8) | ((uint16)p[5]) ) +#define BM_REQ_GET_OEM_VPD_OFFSET(p) (((uint16)p[6] << 8) | ((uint16)p[7]) ) + +#define BM_REQ_GET_OEM_SLOT_GRP_ID(p) (p[3]) + +#define BM_WRITE_VPD_MAX_BYTES 35 +#define BM_READ_VPD_MAX_BYTES 39 +#define BM_GET_MODULE_STATUS_BYTES 6 +#define BM_OEM_REQ_MAX_BYTES 37 +#define BM_OEM_RSP_MAX_BYTES 192 +#define BM_OEM_READ_VPD_MAX_BYTES 36 +#define BM_OEM_SLOTS_STAT_MAX_CHASSIS 54 +#define BM_OEM_SLOTS_STAT_MAX_SLOTS 32 + +#define BM_STATUS_OK 0x00 +#define BM_STATUS_ERROR 0x01 +#define BM_STATUS_CME_BUSY 0x02 +#define BM_STATUS_MME_BUSY 0x03 +#define BM_STATUS_CMD_NOT_SUPPORTED 0x04 +#define BM_STATUS_ILLEGAL_PARAM 0x05 +#define BM_STATUS_WRITE_PROTECTED 0x40 +#define BM_STATUS_NACK 0x41 +#define BM_STATUS_BUS_ERROR 0x42 +#define BM_STATUS_BUSY 0x43 +#define BM_STATUS_INVALID_VPD 0x44 +#define BM_STATUS_ILLEGAL_OFFSET 0x45 +#define BM_STATUS_ILLEGAL_BYTE_COUNT 0x46 + +/* End of packed data structures */ +#include "iba/public/ipackoff.h" + + +/* Byte Swap macros - convert between host and network byte order */ + +static __inline void +BSWAP_BMA_TRAP_DATA_BAD_BKEY (BMA_TRAP_DATA_BAD_BKEY *pDest) +{ +#if CPU_LE + pDest->RequestorLID = ntoh16(pDest->RequestorLID); + pDest->AttributeID = ntoh16(pDest->AttributeID); + pDest->AttributeModifier = ntoh32(pDest->AttributeModifier); + pDest->u1.AsReg32 = ntoh32(pDest->u1.AsReg32); + pDest->B_Key = ntoh64(pDest->B_Key); + BSWAP_IB_GID(&pDest->SenderGID); +#endif +} + +static __inline void +BSWAP_BMA_TRAP_DATA_BM_TRAP (BMA_TRAP_DATA_BM_TRAP *pDest) +{ + /* all 8-bit data, nothing to swap */ +} + +static __inline void +BSWAP_BKEY_INFO (BKEY_INFO *pDest) +{ +#if CPU_LE + pDest->B_Key = ntoh64(pDest->B_Key); + pDest->u1.AsReg16 = ntoh16(pDest->u1.AsReg16); + pDest->B_KeyLeasePeriod = ntoh16(pDest->B_KeyLeasePeriod); + pDest->B_KeyViolations = ntoh16(pDest->B_KeyViolations); +#endif +} + +static __inline void +BSWAP_BM_SEND (BM_SEND *pDest) +{ +#if CPU_LE + pDest->Sequence = ntoh16(pDest->Sequence); +#endif +} + +#ifdef __cplusplus +} +#endif + +#endif /* _IBA_IB_BM_H_ */ diff --git a/IbAccess/Common/Inc/ib_cm.h b/IbAccess/Common/Inc/ib_cm.h new file mode 100644 index 0000000..601ca2d --- /dev/null +++ b/IbAccess/Common/Inc/ib_cm.h @@ -0,0 +1,2602 @@ +/* BEGIN_ICS_COPYRIGHT3 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT3 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +#ifndef _IBA_IB_CM_H_ +#define _IBA_IB_CM_H_ + +/* + * IB Communication/Connection Management API + */ + +/* + * Kernel and user-mode user shares the same header file/API + */ + +/****************************************************************************** + * CM overview + * + * The CM is designed such that applications can control the QP directly + * This permits the use of alternate verbs APIs, QP re-use, and other + * optimizations. + * + * New Applications should use the following flags (set via iba_cm_modify_cep): + * CM_FLAG_TIMEWAIT_CALLBACK - provides for IBTA compliance in timewait state + * CM_FLAG_ASYNC_ACCEPT - improves multi-CEP handling for listeners + * CM_FLAG_TURNAROUND_TIME - allows appl to specify its turnaround time + * CM_FLAG_LISTEN_BACKLOG - allow appl to specify maximum listener pending Q + * + * The CM offers 2 interfaces: + * 1. a direct interface via calls to the iba_cm_* routines + * 2. a function table interface which is SDK3 compatible + * new applications should use the direct interface. + * + * The CM is inheritly callback based. Callbacks occur in threads, so an + * application may perform operations in the callback (including + * iba_cm_destroy_cep). + * For applications which may establish more than 1 connection at a time, it + * is recommended the processing in the callback be limited to basic QP + * operations and the appropriate Cm call (iba_cm_accept, iba_cm_reject, etc). + * If callback processing is too lengthy, the remote endpoint may timeout. + * The TURNAROUND_TIME setting can be used to lengthen the timeouts. + * + * Internal to the CM protocol there is an MRA feature. This feature is hidden + * from the user and is automatically used by the CM based on the timeouts + * requested in a message and the TURNAROUND_TIME setting for the receiving CEP. + * Proper use of the TURNAROUND_TIME setting can prevent unnecessary retries and + * timeouts by the remote endpoint during connection establishment. + * + * All Cm calls are thread safe. + * + * When CM_FLAG_ASYNC_ACCEPT is used, all CM calls, except iba_cm_wait, are + * non-blocking. If CM_FLAG_ASYNC_ACCEPT is not used, the iba_cm_accept + * call in a server context (accepting a REQ and sending REP) will block waiting + * for the RTU. + * + * The application must explicitly iba_cm_destroy_cep for any CEPs it creates or + * which are returned to a listener by iba_cm_accept. Failure to do so will + * tie up CM resources until the application exits. Kernel mode drivers + * are totally responsible for their own cleanup and must be carefully + * coded not to leak CEPs. + * + * In many of the callbacks a Path Record is provided. The AckTimeout value + * given should be used for QP modifications. The PktLifeTime value supplied + * is rounded up and may include an extra CA Ack Delay/2 factor. As such + * it should not be used for QP timeouts. + * + * The CM supports 3 basic types of connections: + * 1. Client/Server RC/UC/RD connection + * 2. Peer to Peer (2 Clients) RC/UC/RD connection + * 3. Client/Server UD QP exchange via IBTA SIDR protocol + * + * ***************************************************************************** + * Client Server RC/UC/RD Connections + * ----------------------------------------------------------------------------- + * The Basic Sequence for connection establishment is as follows: + * (this assumes ASYNC_ACCEPT and TIMEWAIT_CALLBACK are enabled) + * Server Client + * iba_cm_create_cep iba_cm_create_cep + * iba_cm_listen + * iba_cm_prepare_request + * iba_cm_connect + * FCM_CONNECT_REQUEST callback + * iba_cm_process_request + * iba_cm_accept w/ reply data + * (iba_cm_accept returns new CEP) + * FCM_CONNECT_REPLY callback + * iba_cm_process_reply + * iba_cm_accept w/Rtu data + * (may now send on QP) + * FCM_CONNECT_ESTABLISHED callback + * iba_cm_prepare_rts + * (may now send on QP) + * + * (disconnect could be initiated by either side, client initiates below): + * iba_cm_disconnect w/request data + * FCM_DISCONNECT_REQUEST callback + * iba_cm_disconnect w/reply data + * + * (timewait delay occurs) + * FCM_DISCONNECTED callback FCM_DISCONNECTED callback + * (may now destroy/reuse CEP and QP) (may now destroy/reuse CEP and QP) + * + * (server processes other connections) + * (server now ready to exit) + * iba_cm_cancel on listening CEP + * (CM cleans up pending inbound connections) + * FCM_CONNECT_CANCEL callback + * (may now destroy/reuse listening CEP) + * + * ----------------------------------------------------------------------------- + * The Basic Sequence for connection rejection by server is as follows: + * (this assumes ASYNC_ACCEPT and TIMEWAIT_CALLBACK are enabled) + * iba_cm_create_cep iba_cm_create_cep + * iba_cm_listen + * iba_cm_prepare_request + * iba_cm_connect + * FCM_CONNECT_REQUEST callback + * iba_cm_reject + * FCM_CONNECT_REJECT callback + * (may now destroy/reuse CEP and QP) + * ----------------------------------------------------------------------------- + * The Basic Sequence for connection rejection by client is as follows: + * (this assumes ASYNC_ACCEPT and TIMEWAIT_CALLBACK are enabled) + * iba_cm_create_cep iba_cm_create_cep + * iba_cm_listen + * iba_cm_prepare_request + * iba_cm_connect + * FCM_CONNECT_REQUEST callback + * iba_cm_process_request + * iba_cm_accept w/ reply data + * (iba_cm_accept returns new CEP) + * FCM_CONNECT_REPLY callback + * iba_cm_reject + * (may now destroy/reuse CEP and QP) + * FCM_CONNECT_REJECT callback + * (may now destroy/reuse CEP and QP) + * ----------------------------------------------------------------------------- + * The Sequence for stale connection rejection by server is as follows: + * (this only occurs if client reuses QPs before the timewait period expires) + * (this assumes ASYNC_ACCEPT and TIMEWAIT_CALLBACK are enabled) + * iba_cm_create_cep iba_cm_create_cep + * iba_cm_listen + * iba_cm_prepare_request + * iba_cm_connect + * (internally CM identifies stale QP) + * FCM_CONNECT_REJECT callback + * w/RC_STALE_CONN reason + * (timewait delay occurs) + * FCM_DISCONNECTED callback + * (may now destroy/reuse CEP and QP) + * ----------------------------------------------------------------------------- + * The Sequence for stale connection rejection by client is as follows: + * (this only occurs if server reuses QPs before the timewait period expires) + * (this assumes ASYNC_ACCEPT and TIMEWAIT_CALLBACK are enabled) + * iba_cm_create_cep iba_cm_create_cep + * iba_cm_listen + * iba_cm_prepare_request + * iba_cm_connect + * FCM_CONNECT_REQUEST callback + * iba_cm_process_request + * iba_cm_accept w/ reply data + * (iba_cm_accept returns new CEP) + * (internally CM identifies stale QP) + * (CM discards REP, waits for a good one) + * (CM will retry until timeout or success) + * FCM_CONNECT_REJECT callback + * w/RC_STALE_CONN reason + * (timewait delay occurs) + * FCM_DISCONNECTED callback + * (may now destroy/reuse CEP and QP) + * + * ----------------------------------------------------------------------------- + * The Basic Sequence for connection timeout by client is as follows: + * (this assumes ASYNC_ACCEPT and TIMEWAIT_CALLBACK are enabled) + * (typically this occurs if there is no Server running, servers should + * not simply ignore CONNECT_REQUEST callbacks, as this will cause CEPs to + * be consumed until the server exits) + * Server Client + * iba_cm_create_cep iba_cm_create_cep + * iba_cm_listen + * iba_cm_prepare_request + * iba_cm_connect + * FCM_CONNECT_REQUEST callback + * (server fails to respond) + * FCM_CONNECT_TIMEOUT callback + * (may now destroy/reuse CEP and QP) + * + * ----------------------------------------------------------------------------- + * The Basic Sequence for connection timeout by server is as follows: + * (this assumes ASYNC_ACCEPT and TIMEWAIT_CALLBACK are enabled) + * (typically this occurs if the client has exited during connection, clients + * should not simply ignore CONNECT_REPLY callbacks, as this will cause CEPs + * to be consumed until the client exits) + * Server Client + * iba_cm_create_cep iba_cm_create_cep + * iba_cm_listen + * iba_cm_prepare_request + * iba_cm_connect + * FCM_CONNECT_REQUEST callback + * iba_cm_process_request + * iba_cm_accept w/ reply data + * (iba_cm_accept returns new CEP) + * FCM_CONNECT_REPLY callback + * (client fails to respond) + * FCM_CONNECT_TIMEOUT callback + * (may now destroy/reuse CEP and QP) + * + * + * ***************************************************************************** + * Peer to Peer RC Connections + * ----------------------------------------------------------------------------- + * The Basic Sequence for connection establishment is as follows: + * (ater initial iba_cm_connect_peer call, CM will internally assign one + * Peer a passive (listener-like) and one peer an active role. + * The sequence below shows the left most peer in the passive role) + * (this assumes ASYNC_ACCEPT and TIMEWAIT_CALLBACK are enabled) + * Peer Peer + * iba_cm_create_cep iba_cm_create_cep + * iba_cm_connect_peer + * iba_cm_prepare_request + * iba_cm_connect_peer + * FCM_CONNECT_REQUEST callback + * iba_cm_process_request + * iba_cm_accept w/ reply data + * (iba_cm_accept returns new CEP) + * FCM_CONNECT_REPLY callback + * iba_cm_process_reply + * iba_cm_accept w/Rtu data + * (may now send on QP) + * FCM_CONNECT_ESTABLISHED callback + * iba_cm_prepare_rts + * (may now send on QP) + * + * (disconnect could be initiated by either side, right Peer initiates below): + * iba_cm_disconnect w/request data + * FCM_DISCONNECT_REQUEST callback + * iba_cm_disconnect w/reply data + * + * (timewait delay occurs) + * FCM_DISCONNECTED callback FCM_DISCONNECTED callback + * (may now destroy/reuse CEP and QP) (may now destroy/reuse CEP and QP) + * + * ***************************************************************************** + * Alternate Path Migration + * ----------------------------------------------------------------------------- + * APM is allowed on a Client at any time. The Client drives all aspects of APM + * On a server, the CM_FLAG_APM must be set via iba_modify_cep. This can be + * set in the listener anytime prior to iba_cm_accept, in which case it will be + * inherited by all inbound ceps for that listener. It is generally best to set + * it immediately after iba_cm_create_cep. If CM_FLAG_APM is not + * set the CM will automatically reject inbound APM packets and the server + * will not get any APM callbacks. + * + * The Basic Sequence for loading an alternate path is as follows: + * Server Client + * iba_cm_altpath_request + * FCM_ALTPATH_REQUEST callback + * iba_cm_process_altpath_request + * modify QP with Alt path, Rearm APM + * iba_cm_altpath_reply + * w/ APStatus = APS_PATH_LOADED + * FCM_ALTPATH_REPLY callback + * iba_cm_process_altpath_reply + * modify QP with Alt path, Rearm APM + * ----------------------------------------------------------------------------- + * Any APStatus other than APS_PATH_LOADED is considered a rejection. + * The special case of APS_UNSUPPORTED_REQ indicates the server does not + * support APM at all, in which case the client will get an error return on + * future attempts at iba_cm_altpath_request and the server's stack will + * automatically reject any future alternate path requests. + * + * The Basic Sequence for the server rejecting an alternate path is as follows: + * Server Client + * iba_cm_altpath_request + * FCM_ALTPATH_REQUEST callback + * iba_cm_altpath_reply + * w/ APStatus != APS_PATH_LOADED + * FCM_ALTPATH_REJECT + * ----------------------------------------------------------------------------- + * The IBTA 1.1 CM protocol has limitations in associating LAPs and APR + * messages since the APR has no unique identifier to associate it with + * the proper LAP. Hence a late APR could be treated as a response to a later + * LAP and the endpoints would end up with inconsistent alternate paths. + * To avoid this issue, if a LAP times out, the client endpoint will + * consider this an indication the remote end point does not support + * APM. In which case the client will get an error return on + * future attempts at iba_cm_altpath_request. + * + * The Basic Sequence for the server not responding to an alternate path + * is as follows: + * Server Client + * iba_cm_altpath_request + * FCM_ALTPATH_REQUEST callback + * server fails to respond + * FCM_ALTPATH_TIMEOUT + * ----------------------------------------------------------------------------- + * The iba_cm_migrated call must be made by the ULP in reponse to + * a AsyncEventPathMigrated. However in the future this requirement may be + * removed for the server side, at which time the iba_cm_migrated call will + * become a noop for server CEPs. + * + * The Basic Sequence for a path migration is as follows: + * Server Client + * HCA migrate protocol HCA migrate protocol + * AsyncEventPathMigrated callback AsyncEventPathMigrated callback + * iba_cm_migrated iba_cm_migrated + * or + * iba_cm_migrated_reload + * iba_cm_altpath_request + * + * ***************************************************************************** + * Other Features + * ----------------------------------------------------------------------------- + * The iba_cm_reject and iba_cm_accept calls are intended for use as the direct + * result of a callback (as shown above). In addition if a client/server + * decides to terminate a connection establishment sequence, the iba_cm_cancel + * call can be used. This will trigger the cancellation or rejection of the + * connection (action taken depends on the state of the CEP). + * After the cancel operations complete, a FCM_CONNECT_CANCEL callback will + * be provided at which time the application can safely destroy/reuse the CEP + * and QP. + * + * If the iba_cm_cancel is not permitted for the present state (for example if + * the connection is already established), the FINVALID_STATE error code is + * returned and the application should use iba_cm_disconnect with a request. + * Should iba_cm_disconnect also return FINVALID_STATE, the disconnect is in + * progress and the application will ultimately get an FCM_DISCONNECTED callback + * when the disconnect sequence has completed. + * + * This approach allows the CEP and QP handling to be done directly as a + * result of callbacks and helps reduce concurrency issues in the + * application. Hence for a typical application, when a higher level + * decides to cancel a connection if should simply do: + * if (iba_cm_cancel(cep) != FSUCCESS) + * (request optional, can be NULL) + * (void)iba_cm_disconnect(cep, &request, NULL); + * This will ensure an appropriate final callback will occur for the CEP + * to trigger application cleanup. + * + * If the iba_cm_cancel happens to race with a callback thread, functions in the + * callback such as iba_cm_accept/iba_cm_reject may return FCM_CONNECT_CANCEL. + * In which case that callback need do not more work on the CEP/QP and a future + * FCM_CONNECT_CANCEL callback will occur to allow final cleanup. + * ----------------------------------------------------------------------------- + * As has been implied above, when using the TIMEWAIT_CALLBACK and ASYNC_ACCEPT + * options (recommended), the following events are considered the final + * events for a CEP. When these events occur, the application can destroy or + * reuse the CEP and corresponding QP. + * FCM_DISCONNECTED/FCM_DISCONNECT_TIMEOUT callback (both same value) + * iba_cm_reject returns FSUCCESS + * FCM_CONNECT_REJECT callback/return from iba_cm_accept (except RC_CONN_STALE) + * FCM_CONNECT_CANCEL callback/return from iba_cm_accept + * FCM_CONNECT_TIMEOUT callback/return from iba_cm_accept + * FCM_CA_REMOVED callback + * ----------------------------------------------------------------------------- + * CEP handles are validated on all calls. Hence if a CEP has been destroyed in + * another thread, any subsequenct calls against the CEP will return + * FCM_INVALID_HANDLE. + * + * + * ***************************************************************************** + * Typical RC/UC/RD Connection setup algorithms: + * ----------------------------------------------------------------------------- + * Server: + * iba_cm_create_cep + * uint32 value = 1; + * iba_cm_modify_cep(cep, CM_FLAG_ASYNC_ACCEPT, (char*)&value, + * sizeof(uint32), 0); + * iba_cm_modify_cep(cep, CM_FLAG_TIMEWAIT_CALLBACK, (char*)&value, + * sizeof(uint32),0); + * iba_cm_modify_cep(cep, CM_FLAG_APM, (char*)&value, + * sizeof(uint32),0); // allow APM + * value = max pending connect requests on CEP queue + * iba_cm_modify_cep(cep, CM_FLAG_LISTEN_BACKLOG, (char*)&value, + * sizeof(uint32), 0); + * if private data is to be part of bound listening address + * uint8 pattern[] = data pattern to listen for in REQ + * iba_cm_modify_cep(cep, CM_FLAG_LISTEN_DISCRIM, pattern, + * length of pattern, offset within REQ private data) + * create/get an application structure for use as listen context (if any) + * iba_cm_listen(cep, ListenRequest, callback, context) + * ----------------------------------------------------------------------------- + * Client or Peer to Peer: + * iba_cm_create_cep + * uint32 value = 1; + * iba_cm_modify_cep(cep, CM_FLAG_ASYNC_ACCEPT, (char*)&value, + * sizeof(uint32), 0); + * iba_cm_modify_cep(cep, CM_FLAG_TIMEWAIT_CALLBACK, (char*)&value, + * sizeof(uint32),0); + * obtain a IB_PATH_RECORD for path to server/peer + * iba_cm_prepare_request + * create/get a QP + * compose rest of Request based on QPN and desired SID + * move QP to Init (using QpAttrInit from iba_cm_prepare_request) + * create/get an application structure for use as context (if any) + * iba_cm_connect(cep, Request, callback, context) + * or + * iba_cm_connect_peer(cep, Request, callback, context) + * ***************************************************************************** + * + * Typical Connection teardown algorithms: + * ----------------------------------------------------------------------------- + * Client, Server or Peer to Peer: + * move QP to Error + * compose a DisconnectRequest + * iba_cm_disconnect(cep, DisconnectRequest, NULL) + * + * Some applications may chose to move the QP to QPStateSendQDrain and wait for + * the send Q to drain prior to performing the connection teardown sequence + * above. This way any final transfers on the connection will be guaranteed + * to have completed. + * + * Generally its desirable to move the QP through the error state on its way + * to Reset or being destroyed. This will cause all posted WQEs to be returned + * via completion callbacks with a WRStatusWRFlushed completion code. + * Most applications will actually delay the final QP destroy until the last + * such completion for the QP occurs. + * + * ***************************************************************************** + * Typical RC/UC/RD Callback handling algorithms: + * These algorithms are focused on CM and QP operations required in each + * callback. In addition there may be additional application specific functions + * (such as maintaining application state for a CEP, etc). + * ----------------------------------------------------------------------------- + * FCM_CONNECT_REQUEST - a REQ was received info->Info.Request supplied + * This will occur on a Server or a Peer to Peer CEP + * + * Algorithm: + * (this assumes ASYNC_ACCEPT and TIMEWAIT_CALLBACK are enabled) + * verify Info.Request is valid/acceptable to the Server + * validate alternate path + * if APM not supported, pass CM_REP_FO_NOT_SUPPORTED below + * if APM supported but path not acceptable, pass CM_REP_FO_REJECTED_ALT + * (not if CA does not support APM or CEP does not have CM_FLAG_APM set + * iba_cm_process_request will automatically handle) + * iba_cm_process_request(.., CM_REP_FO_*, ...) + * further adjust Reply and corresponding QpAttr if desired + * verify Reply->Arb is appropriate for RDMA Read needs + * create/get a QP + * fill in rest of reply (QPN, RnRRetryCount, PrivateData) + * for server (eg. non-peer), move QP to Init: + * set QpAttrInit->AccessControl + * move QP to Init state using QpAttrInit from iba_cm_process_request + * move QP to RTR state using QpAttrRtr from iba_cm_process_request + * create/get an application structure for use as context (if any) + * post recieve buffers + * if all the above is successful + * // async accept ignores 3rd argument of iba_cm_accept + * iba_cm_accept(cep, Reply, NULL, callback, context, &newcep) + * if failed + * iba_cm_reject(cep, RejectInfo) + * move QP to Error or Reset state (as needed) + * destroy/free QP (as needed) + * free context structure (as needed) + * else + * // at this point the application could begin to receive data on QP + * // such data receipt could race with the FCM_CONNECT_ESTABLISHED + * // callback + * // any future callbacks against newcep will be given to + * // callback with context + * else + * iba_cm_reject(cep, RejectInfo) + * move QP to Error or Reset state (as needed) + * destroy/free QP (as needed) + * free context structure (if any) + * ----------------------------------------------------------------------------- + * FCM_CONNECT_ESTABLISHED - a RTU was received info->Info.Rtu supplied + * In some cases an RTU is optional, in which case + * this callback may occur with a zeroed Rtu + * applications should not depend on the PrivateData + * in the RTU. + * This will occur on a Server or a Peer to Peer CEP + * + * Algorithm: + * Info.Rtu may contain private data, but cannot be depended on per IBTA + * iba_cm_prepare_rts + * move QP to RTS + * if above fails + * move QP to Error + * iba_cm_disconnect(cep, DisconnectRequest, NULL) + * else + * QP is now fully ready for use + * application may now perform PostSend + * ----------------------------------------------------------------------------- + * FCM_CONNECT_REPLY - a REP was received info->Info.Reply supplied + * This will occur on a Client or a Peer to Peer CEP + * + * Algorithm: + * verify Info.Reply is valid/acceptable to the Client/Peer + * verify Info.Reply.Arb* meets the RDMA Read needs of the Client/Peer + * iba_cm_process_reply + * post recieve buffers + * compose a Rtu (can be all zeros) + * move QP to RTR and RTS state using data from iba_cm_process_reply + * (Note: AckTimeout used for QP RTS is computed as: + * REQ's AckTimeout+Target Ack Delay -local CA Ack Delay + * or + * 2*PktLifetime + TargetAckDelay) + * if all the above is successful + * // async accept ignores 3rd argument of iba_cm_accept + * // RTU argument is optional, only needed if have RTU private data + * iba_cm_accept(cep, Rtu, NULL, NULL, NULL, NULL) + * if failed + * iba_cm_reject(cep, RejectInfo) + * move QP to Error or Reset + * Destroy/free QP + * iba_cm_destroy_cep + * free context structure + * else + * // application can now begin to send and receive data + * else + * iba_cm_reject(cep, RejectInfo) + * move QP to Error or Reset + * Destroy/free QP + * iba_cm_destroy_cep + * free context structure (if any) + * ----------------------------------------------------------------------------- + * FCM_CONNECT_TIMEOUT - timeout waiting for REP or RTU for connection + * no additional info->Info supplied + * This will occur on a Server, client or a Peer to Peer CEP + * + * Algorithm: + * move QP to Error or Reset state + * Destroy/free QP + * free context structure + * iba_cm_destroy_cep + * ----------------------------------------------------------------------------- + * FCM_CONNECT_REJECT - a REJ was received info->Info.Reject supplied + * For the RC_STALE_CONN rejection code, + * when CM_FLAG_TIMEWAIT_CALLBACK is set for a + * client/active peer or both CM_FLAG_ASYNC_ACCEPT and + * CM_FLAG_TIMEWAIT_CALLBACK are set for a + * server/passive peer, a FCM_DISCONNECTED + * callback will later occur at the end of Timewait + * For other rejection codes (or server/passive peer + * without both flags set), this is the final + * callback for the CEPs connection sequence + * This will occur on a Server, client or a Peer to Peer CEP + * + * Algorithm (assuming TIMEWAIT and ASYNC ACCEPT enable): + * move QP to Error or Reset state + * if info->Info.Reject != RC_STALE_CONN + * Destroy/free QP + * iba_cm_destroy_cep + * free context structure + * ----------------------------------------------------------------------------- + * FCM_ALTPATH_REQUEST - client has requested server to load an alternate path + * a LAP was received info->Info.AltPathRequest supplied + * This will occur on a Server, a passive Peer to Peer CEP + * + * Algorithm: + * validate new alternate path + * iba_cm_process_altpath_request + * modify QP, RTS to RTS, load new alternate path, QP migrate state to Rearm + * if any of above fails + * iba_cm_altpath_reply w/ APStatus != APS_PATH_LOADED + * else + * iba_cm_altpath_reply w/ APStatus = APS_PATH_LOADED + * ----------------------------------------------------------------------------- + * FCM_ALTPATH_REPLY - server has accepted alternate path requested + * a APR was received info->Info.AltPathReply supplied + * This will occur on a client, or a active Peer to Peer CEP + * + * Algorithm: + * iba_cm_process_altpath_reply + * modify QP, RTS to RTS, load new alternate path, QP migrate state to Rearm + * if fails + * iba_cm_disconnect + * ----------------------------------------------------------------------------- + * FCM_ALTPATH_REJECT - server has rejected alternate path requested + * a APR was received info->Info.AltPathReply supplied + * This will occur on a client, or a active Peer to Peer CEP + * + * Algorithm: + * no action needed + * could try a iba_cm_altpath_request with a different path + * ----------------------------------------------------------------------------- + * FCM_ALTPATH_TIMEOUT - server has not responded to alternate path requested + * This will occur on a client, or a active Peer to Peer CEP + * + * Algorithm: + * if server previously reponded to APM or ULP requires/expects APM + * it is best to iba_cm_disconnect + * alternately could proceed and assume server does not support APM + * ----------------------------------------------------------------------------- + * AsyncEventPathMigrated - QP Async Event callback from verbs interface + * This can occur on a Server, client or a Peer to Peer CEP for which an + * alternate path has been loaded into the QP + * + * Server/Passive Algorithm (or if Client does not want a new alternate path): + * iba_cm_migrated + * + * Client/Active Peer Algorithm: + * iba_cm_migrated_reload + * review/determine proper new alternate path (if any) + * iba_cm_altpath_request - restore a new alternate path + * ----------------------------------------------------------------------------- + * FCM_DISCONNECT_REQUEST - a DREQ was received info->Info.DisconnectRequest + * supplied. Beware there are situations where a DREQ + * is internally generated by the CM, in which case the + * private data will be all 0s + * This will occur on a Server, client or a Peer to Peer CEP + * + * Algorithm: + * move QP to Error + * optionally process PrivateData + * iba_cm_disconnect(cep, NULL, DisconnectReply) + * ----------------------------------------------------------------------------- + * FCM_DISCONNECT_REPLY - a DREP was received info->Info.DisconnectReply + * supplied + * This will occur on a Server, client or a Peer to Peer CEP + * which has initiated disconnect by + * iba_cm_disconnect(cep, DisconnectRequest, NULL) + * + * Algorithm: + * // QP should already be in Error state + * optionally process PrivateData + * ----------------------------------------------------------------------------- + * FCM_DISCONNECTED - disconnect sequence has completed (possibly with + * a timeout waiting for DREP), no additional + * info->Info supplied. + * (same value as FCM_DISCONNECT_TIMEOUT) + * This will occur on a Server, client or a Peer to Peer CEP + * + * Algorithm: + * move QP to Reset + * destroy/free QP + * iba_cm_destroy_cep + * free context structure + * ----------------------------------------------------------------------------- + * FCM_CA_REMOVED - CA was removed. Connection torn down. + * no additional info->Info supplied. + * This will occur on a Server, client or a Peer to Peer CEP + * + * Algorithm: + * CA is gone, no QP actions possible + * cleanup QP resources, buffers + * iba_cm_destroy_cep + * free context structure + * ----------------------------------------------------------------------------- + * FCM_CONNECT_CANCEL - iba_cm_cancel has completed cancelation of + * connect/listen no additional info->Info supplied + * For a listener CEP: + * iba_cm_destroy_cep + * free listener context structure + * + * For a client, server or Peer to Peer CEP: + * move QP to Error or Reset state + * Destroy/free QP + * iba_cm_destroy_cep + * free context structure + * + * ***************************************************************************** + * Client Server UD Connections + * ----------------------------------------------------------------------------- + * The Basic Sequence for connection establishment is as follows: + * Server Client + * iba_cm_create_cep iba_cm_create_cep + * iba_cm_sidr_register + * iba_cm_sidr_query + * optional FSIDR_REQUEST callback + * iba_cm_sidr_response w/ response data + * FSIDR_RESPONSE callback + * may destroy or re-use CEP + * + * For a UD QP, IBTA does not require any specific state transitions. + * Depending on the application, the UD QP could be created once at the + * start of the applications and moved immediately to RTS, or a separate + * UD QP could be created per inbound SIDR_REQUEST. Since there is no + * disconnect protocol defined for UD QPs, the application must determine + * how and when it will destroy the QP + * + * iba_cm_sidr_deregister will remove the effects of iba_cm_sidr_register. + * After it the server CEP may be destroyed. + * + * To reject an inbound FSIDR_REQUEST, use iba_cm_sidr_response and set + * SidrResponse.Status to an appropriate SIDR_RESP_STATUS value. + * + * + * ***************************************************************************** + * Typical Callback handling algorithms: + * FSIDR_REQUEST - a SIDR_REQ was received info->Info.SidrRequest + * supplied + * Only occurs on CEP which was iba_cm_sidr_register()'ed with a callback + * specified. + * Otherwise the CM will internally reply to SIDR_REQ messages using the + * data from iba_cm_sidr_register without involving the application + * + * Algorithm: + * compose response to SIDR_REQ + * iba_cm_sidr_response(cep, SidrResponse) + * ----------------------------------------------------------------------------- + * FSIDR_RESPONSE - a SIDR_RESP was received info->Info.SidrResponse + * supplied + * Only occurs on CEP which did iba_cm_sidr_query. + * + * Algorithm: + * application specific handling of SidrResponse + * CEP may now be freed or re-used for another + * iba_cm_sidr_query/iba_cm_connect/ib_cm_listen, etc + * ----------------------------------------------------------------------------- + * FSIDR_RESPONSE_ERR - a SIDR_RESP was received info->Info.SidrResponse + * supplied, info->Info.SidrResponse.Status != 0 + * Only occurs on CEP which did iba_cm_sidr_query. + * + * Algorithm: + * application specific handling of SidrResponse + * CEP may now be freed or re-used for another + * iba_cm_sidr_query/iba_cm_connect/ib_cm_listen, etc + * ----------------------------------------------------------------------------- + * FSIDR_REQUEST_TIMEOUT- timeout waiting for SIDR_RESP no additional + * info->Info supplied + * Only occurs on CEP which did iba_cm_sidr_query. + * + * Algorithm: + * application specific handling of SidrResponse + * CEP may now be freed or re-used for another + * iba_cm_sidr_query/iba_cm_connect/ib_cm_listen, etc + */ + + +#include "iba/public/datatypes.h" /* Portable datatypes */ +#include "iba/vpi.h" +#include "iba/stl_types.h" /* IB-defined types */ +#include "iba/ib_sa_records_priv.h" /* PATH_RECORD */ +#include "iba/ib_status.h" /* IB-defined status code */ + +#if defined (__cplusplus) +extern "C" { +#endif + +/***************************************************************************** + * CM-specific error & status code + */ + +#define FCM_BASE_STATUS 0 +#define FCM_NOT_INITIALIZED (SET_FSTATUS(FERROR, IB_MOD_CM, 1)) +#define FCM_INVALID_HANDLE (SET_FSTATUS(FERROR, IB_MOD_CM, 2)) +#define FCM_ADDR_INUSE (SET_FSTATUS(FERROR, IB_MOD_CM, 3)) +#define FCM_INVALID_EVENT (SET_FSTATUS(FERROR, IB_MOD_CM, 4)) +#define FCM_ALREADY_DISCONNECTING (SET_FSTATUS(FERROR, IB_MOD_CM, 5)) +#define FCM_CONNECT_DESTROY (SET_FSTATUS(FERROR, IB_MOD_CM, 6)) + +#define FCM_CONNECT_TIMEOUT (SET_FSTATUS(FTIMEOUT, IB_MOD_CM, 10)) +#define FSIDR_REQUEST_TIMEOUT (SET_FSTATUS(FTIMEOUT, IB_MOD_CM, 11)) + +#define FCM_CONNECT_REJECT (SET_FSTATUS(FREJECT, IB_MOD_CM, 13)) +#define FCM_CONNECT_CANCEL (SET_FSTATUS(FCANCELED, IB_MOD_CM, 14)) + +#define FCM_CONNECT_REPLY (SET_FSTATUS(FSUCCESS, IB_MOD_CM, 20)) +#define FCM_DISCONNECT_REQUEST (SET_FSTATUS(FSUCCESS, IB_MOD_CM, 21)) +#define FCM_DISCONNECT_REPLY (SET_FSTATUS(FSUCCESS, IB_MOD_CM, 22)) +#define FCM_CONNECT_REQUEST (SET_FSTATUS(FSUCCESS, IB_MOD_CM, 23)) +#define FCM_CONNECT_ESTABLISHED (SET_FSTATUS(FSUCCESS, IB_MOD_CM, 24)) +#define FCM_DISCONNECTED (SET_FSTATUS(FSUCCESS, IB_MOD_CM, 25)) +#define FSIDR_REQUEST (SET_FSTATUS(FSUCCESS, IB_MOD_CM, 26)) +#define FSIDR_RESPONSE (SET_FSTATUS(FSUCCESS, IB_MOD_CM, 27)) +#define FSIDR_RESPONSE_ERR (SET_FSTATUS(FERROR, IB_MOD_CM, 28)) +#define FCM_CA_REMOVED (SET_FSTATUS(FSUCCESS, IB_MOD_CM, 29)) +#define FCM_ALTPATH_REQUEST (SET_FSTATUS(FSUCCESS, IB_MOD_CM, 30)) +#define FCM_ALTPATH_REPLY (SET_FSTATUS(FSUCCESS, IB_MOD_CM, 31)) +#define FCM_ALTPATH_REJECT (SET_FSTATUS(FSUCCESS, IB_MOD_CM, 32)) +#define FCM_ALTPATH_TIMEOUT (SET_FSTATUS(FSUCCESS, IB_MOD_CM, 33)) + +/* Disconnect timeout is the same as disconnected since the user does not + * need to do any QP actions specific to the DREP timeout + * instead any QP actions should occur after the timewait completes + */ +#define FCM_DISCONNECT_TIMEOUT FCM_DISCONNECTED + +#define FCM_WAIT_OBJECT0 (SET_FSTATUS(FSUCCESS, IB_MOD_CM, 64)) + + +/****************************************************************************** + * User is allowed to piggyback private data along with CM messages. + * The following defined the max length in bytes of user data + * allowed for different types of CM messages + */ + +/* + * Private/user data length in bytes + */ +#define CM_REQUEST_INFO_USER_LEN 92 +#define CM_REPLY_INFO_USER_LEN 196 +#define CM_REJECT_INFO_USER_LEN 148 +#define CM_RTU_INFO_USER_LEN 224 +#define CM_DREQUEST_INFO_USER_LEN 220 +#define CM_DREPLY_INFO_USER_LEN 224 +#define SIDR_REQ_INFO_USER_LEN 216 +#define SIDR_RESP_INFO_USER_LEN 136 +#define CM_LAP_INFO_USER_LEN 168 +#define CM_APR_INFO_USER_LEN 148 + +#define CM_GEN_INFO_USER_LEN 224 /* Generic */ +#define CM_REJ_ADD_INFO_LEN 72 /* Additional reject info length */ +#define CM_APR_ADD_INFO_LEN 72 /* Additional apr info length */ + +/***************************************************************************** + * Forward decl. + */ +struct _CM_CONN_INFO; + +typedef struct _EVENT* EVENT_HANDLE; + + +/***************************************************************************** + * CM callback prototype + * + * INPUTS: + * + * hCEP - Handle to the CEP object. + * + * info - information about the event + * pointer is valid only duration of this call + * + * Context - user's context for CEP (as was specified in + * iba_cm_connect, iba_cm_accept, iba_cm_listen, etc) + * + * The info->Status indicates the callback event as follows: + * FCM_CONNECT_REQUEST - a REQ was received info->Info.Request supplied + * FCM_CONNECT_REPLY - a REP was received info->Info.Reply supplied + * FCM_CONNECT_ESTABLISHED - a RTU was received info->Info.Rtu supplied + * In some cases an RTU is optional, in which case + * this callback may occur with a zeroed Rtu + * applications should not depend on the PrivateData + * in the RTU. + * FCM_CONNECT_REJECT - a REJ was received info->Info.Reject supplied + * For the RC_STALE_CONN rejection code, + * when CM_FLAG_TIMEWAIT_CALLBACK is set for a + * client/active peer or both CM_FLAG_ASYNC_ACCEPT and + * CM_FLAG_TIMEWAIT_CALLBACK are set for a + * server/passive peer, a FCM_DISCONNECTED + * callback will later occur at the end of Timewait + * For other rejection codes (or server/passive peer + * without both flags set), this is the final + * callback for the CEPs connection sequence + * FCM_DISCONNECT_REQUEST - a DREQ was received info->Info.DisconnectRequest + * supplied. Beware there are situations where a DREQ + * is internally generated by the CM, in which case the + * private data will be all 0s + * FCM_DISCONNECT_REPLY - a DREP was received info->Info.DisconnectReply + * supplied + * FCM_CONNECT_CANCEL - iba_cm_cancel has completed cancelation of + * connect/listen no additional info->Info supplied + * FCM_DISCONNECTED - disconnect sequence has completed (possibly with + * a timeout waiting for DREP), no additional + * info->Info supplied. + * (same value as FCM_DISCONNECT_TIMEOUT) + * FCM_CONNECT_TIMEOUT - timeout waiting for REP or RTU for connection + * no additional info->Info supplied + * FSIDR_REQUEST - a SIDR_REQ was received info->Info.SidrRequest + * supplied + * FSIDR_RESPONSE - a SIDR_RESP was received info->Info.SidrResponse + * supplied + * FSIDR_RESPONSE_ERR - a SIDR_RESP was received info->Info.SidrResponse + * supplied, info->Info.SidrResponse.Status != 0 + * FSIDR_REQUEST_TIMEOUT- timeout waiting for SIDR_RESP no additional + * info->Info supplied + * FCM_CA_REMOVED - CA was removed. Connection torn down. + * no additional info->Info supplied. + * + * Internally the CM handles all retries, invalid/out of sequence messages + * and the appropriate state transitions. callbacks will only be issued + * once for a given message type and only when valid for the present + * state. + */ +typedef void (*PFN_CM_CALLBACK)( + IN IB_HANDLE hCEP, + IN struct _CM_CONN_INFO* info, + IN void* Context + ); + + +/***************************************************************************** + * CM_CEP_TYPE - + * Transport service type enum (used in CM API and on Wire in REQ) + */ +typedef enum { + CM_RC_TYPE=0, /* Reliable Connection */ + CM_UC_TYPE=1, /* Unreliable Connection */ + CM_RD_TYPE=2, /* Reliable Datagram */ + CM_UD_TYPE=3 /* Unreliable Datagram. */ +}CM_CEP_TYPE; + + +/***************************************************************************** + * CM_FLAG_XXX - options which can be set for a CEP via iba_cm_modify_cep + * Some of these are bit flags, but the primary use of this + * value is as an argument to iba_cm_modify_cep, in which case they need not + * be truely bit flags. + */ + /* Private data is not part of bound address (the default) */ +#define CM_FLAG_LISTEN_NODISCRIM 0x01 + /* Private data is part of bound address */ +#define CM_FLAG_LISTEN_DISCRIM 0x02 + + /* maximum pending CEPs on a listener or SIDR Registered CEP + * value is a uint32 count + * If set to 0, the CmMaxBackLog value will be used for the CEP + * (and any adjustments to CmMaxBackLog will take effect on all such CEPs) + */ +#define CM_FLAG_LISTEN_BACKLOG 0x04 + + /* Is user providing a callback for inbound SIDR REQ handling + * value is a uint32 flag with value of 0 or 1 (1-> enable) + */ +#define CM_FLAG_SIDR_REGISTER_NOTIFY 0x08 + + /* Does user want Passive iba_cm_accept to be Asynchronous? + * In which case a separate FCM_CONNECT_ESTABLISHED callback is + * given when RTU is received. + * It is recommended this option be enabled + * Value of this option is inheritted from a listener to the new CEPs + * at the time a REQ is accepted. + * value is a uint32 flag with value of 0 or 1 (1-> enable) + */ +#define CM_FLAG_ASYNC_ACCEPT 0x10 + + /* User can set their Application Turnaround Time (in usec) + * if set to 0, a heuristic average across all applications + * will be used. + * This value includes both software queuing time and appl processing time. + * For a client it is used to influence the timeouts specified + * in the connect request. + * For a listener this controls when an MRA is issued. + * Value of this option is inheritted from a listener to the new CEPs + * at the time a REQ is accepted. + * value is a uint32 in microseconds + */ +#define CM_FLAG_TURNAROUND_TIME 0x20 + + /* Does user want a FCM_DISCONNECTED callback only after the timewait + * period has expired? + * It is recommended this option be enabled + * Value of this option is inheritted from a listener to the new CEPs + * at the time a REQ is accepted. + * value is a uint32 flag with value of 0 or 1 (1-> enable) + * If set a QP/CEP can be safely reused after any of the following: + * FCM_DISCONNECTED/FCM_DISCONNECT_TIMEOUT callback (both same value) + * iba_cm_reject success + * FCM_CONNECT_REJECT callback/return from iba_cm_accept + * (except RC_STALE_CONN) + * - exception, for a server/passive peer without CM_FLAG_ASYNC_ACCEPT + * there will be no FCM_DISCONNECTED callback, timewait proceeds + * without notification as to when it completed + * FCM_CONNECT_CANCEL callback/return from iba_cm_accept + * FCM_CONNECT_TIMEOUT callback/return from iba_cm_accept + * FCM_CA_REMOVED callback + * If not set, the user is given no indication as to when the timewait + * has completed. The last event for a CEP could be any of the above or: + * FCM_DISCONNECT_REPLY callback + * FCM_DISCONNECT_REQUEST (caller should then iba_cm_disconnect w/ a reply) + */ +#define CM_FLAG_TIMEWAIT_CALLBACK 0x40 + + /* Does server support APM (Alternate Path Migration). + * If set the server could get FCM_ALTPATH_REQUEST callbacks + * flag is not allowed for clients, client's use of iba_cm_altpath_request + * and/or setting of an alternate path in iba_cm_connect will indicate + * if client supports APM + * Value of this option is inheritted from a listener to the new CEPs + * at the time a REQ is accepted. + * if server rejects an AltPathRequest with a APStatus of + * APS_UNSUPPORTED_REQ, this option is disabled. + */ +#define CM_FLAG_APM 0x80 + + + +/***************************************************************************** + * CM_REJECTION_CODE - + * Rejection reason code + */ +typedef enum { + RC_NO_QP=1, + RC_NO_EEC, + RC_NO_RESOURCES, + RC_TIMEOUT, + RC_UNSUPPORTED_REQ, + RC_INVALID_COMMID, + RC_INVALID_COMMINST, + RC_INVALID_SID, + RC_INVALID_TSTYPE, + RC_STALE_CONN, + RC_INVALID_RDC, + RC_PRIMARY_DGID_REJ, + RC_PRIMARY_DLID_REJ, + RC_INVALID_PRIMARY_SL, + RC_INVALID_PRIMARY_TC, + RC_INVALID_PRIMARY_HL, + RC_INVALID_PRIMARY_PR, + RC_ALTERNATE_DGID, + RC_ALTERNATE_DLID, + RC_INVALID_ALTERNATE_SL, + RC_INVALID_ALTERNATE_TC, + RC_INVALID_ALTERNATE_HL, + RC_INVALID_ALTERNATE_PR, + RC_CMPORT_REDIR, + RC_INVALID_PATHMTU, + RC_INSUFFICIENT_RESP_RES, + RC_USER_REJ, + RC_RNRCOUNT_REJ +} CM_REJECTION_CODE; + +/* convert CM_REJECTION_CODE to a string */ +IBA_API const char* iba_cm_rejection_code_msg(uint16 code); + + +/****************************************************************************** + * CM_APR_STATUS - + * APR APStatus + */ +typedef enum { + APS_PATH_LOADED = 0, + APS_INVALID_COMMID, + APS_UNSUPPORTED_REQ, + APS_REJECTED, + APS_CMPORT_REDIR, + APS_DUPLICATE_PATH, + APS_ENDPOINT_MISMATCH, + APS_REJECT_DLID, + APS_REJECT_DGID, + APS_REJECT_FL, + APS_REJECT_TC, + APS_REJECT_HL, + APS_REJECT_PR, + APS_REJECT_SL +} CM_APR_STATUS; + +/* convert CM_APR_STATUS to a string */ +IBA_API const char* iba_cm_apr_status_msg(uint16 code); + +/****************************************************************************** + * SIDR_RESP_STATUS - + * SIDR response status + */ +typedef enum { + SRS_VALID_QPN=0, + SRS_SID_NOT_SUPPORTED, + SRS_S_PROVIDER_REJECTED, + SRS_QP_UNAVAILABLE, + SRS_REDIRECT, + SRS_VERSION_NOT_SUPPORTED + /* 6-255 reserved */ +} SIDR_RESP_STATUS; + +/* convert SIDR_RESP_STATUS to a string */ +IBA_API const char* iba_cm_sidr_resp_status_msg(uint8 code); + + +/****************************************************************************** + * CM_CEP_PATHINFO - + * Path information use to establish the connection. + * + * Path is always presented from the perspective of the Client + * Hence SLID is Client LID and DLID is Server LID, etc. + */ +typedef struct _CM_CEP_PATHINFO { + /* If local, the global routing info will not be used below. This include */ + /* the GIDs, HopLimit, TrafficClass and FlowLabel. */ + boolean bSubnetLocal; + IB_PATH_RECORD Path; + +} CM_CEP_PATHINFO; + + +/****************************************************************************** + * CM_CEP_INFO - + * Local connection endpoint information. + * This local information is passed to the remote endpoint + * during connection establishment. + */ +typedef struct _CM_CEP_INFO { + + /* Client Side Channel Adapter GUID (also known as node GUID) */ + uint64 CaGUID; /* From NodeInfo.NodeGUID */ + boolean EndToEndFlowControl; /* Ca implements end-to-end flow control */ + /* Local Port information */ + uint64 PortGUID; /* unused on Client */ + /* (SGID/CaGUID implies) */ + /* returned on Server as Port for */ + /* which connection is being */ + /* made (based on DGID in REQ) */ + + /* Client Side QP & RD information */ + uint32 QKey; /* QP's QKey (for RD only) */ + uint32 QPN:24; /* QP Number */ + uint32 AckTimeout:5; /* Local ACK timeout (Application-defined) */ + uint32 RetryCount:3; /* Sequence error retry count (Application-defined) */ + uint32 StartingPSN:24; /* Starting PSN to use on the QP (Application-defined) */ + uint32 AlternateAckTimeout:5; /* Specify this if the alternate path is used */ + uint32 RnrRetryCount:3; /* Receiver Not Ready retry count (Application-defined) */ + + uint32 LocalEECN:24; + uint32 OfferedResponderResources:8; /* Application-defined */ + /* senders's desired */ + /* qpAttr->ResponderResources */ + + uint32 RemoteEECN:24; + uint32 OfferedInitiatorDepth:8; /* Application-defined */ + /* senders's desired */ + /* qpAttr->InitiatorDepth */ + +} CM_CEP_INFO; + +/****************************************************************************** + * CM_CEP_ADDR - + * Connection endpoint address. The CEP object is bound + * to this address during iba_cm_listen() + */ +typedef struct _CM_CEP_ADDR { + /* For ListenAddr, SID is used */ + /* For RemoteAddr, ignored */ + /* QPN, EECN fields are ignored, depricated */ + struct { + uint32 QPN:24; /* ignored, depricated */ + uint32 Reserved1:8; /* Padding */ + uint32 EECN:24; /* ignored, depricated */ + uint32 Reserved2:8; + uint64 SID; /* only used in ListenAddr */ + } EndPt; + + /* optionally limit listen to a specific GID or LID */ + /* if 0, will listen on all GIDs/LIDs */ + struct { + IB_GID GID; + IB_LID LID; + } Port; +} CM_CEP_ADDR; + + +/****************************************************************************** + * CM_LISTEN_INFO - + * Listen request info. Server specified the parameters to establish + * a local listening endpoint to accept incoming connections. + * No mapping + */ +typedef struct _CM_LISTEN_INFO { + uint64 CaGUID; /* must supply if listening on a specific port */ + CM_CEP_ADDR ListenAddr; + CM_CEP_ADDR RemoteAddr; +} CM_LISTEN_INFO; + + +/****************************************************************************** + * CM_REQUEST_INFO - + * Connect request info. Client specified the parameters to establish + * a connection between local and remote endpoint. + * Does NOT mapped directly to CMM_REQ + */ +typedef struct _CM_REQUEST_INFO { + + uint64 SID; + CM_CEP_INFO CEPInfo; /* Additonal local endpoint information */ + CM_CEP_PATHINFO PathInfo; /* Path info */ + CM_CEP_PATHINFO AlternatePathInfo; /* Alternate path info */ + + /* Additional user data that is sent across to the remote endpoint for */ + /* interpretion by the remote end user i.e. not interpreted by CM */ + uint8 PrivateData[CM_REQUEST_INFO_USER_LEN]; /* 92 bytes of private data */ + +} CM_REQUEST_INFO; + + +/****************************************************************************** + * CM_REP_FAILOVER + * values for FailoverAccepted field in REPLY_INFO + */ +typedef enum { + CM_REP_FO_ACCEPTED=0, + CM_REP_FO_NOT_SUPPORTED, + CM_REP_FO_REJECTED_ALT +} CM_REP_FAILOVER; + +/* convert CM_REP_FAILOVER to a string */ +IBA_API const char* iba_cm_rep_failover_msg(uint8 code); + +/****************************************************************************** + * CM_REPLY_INFO - + * Reply info. Use by server to reply to a connect request. + * Mapped directly to CMM_REP + */ +typedef struct _CM_REPLY_INFO { + + uint32 QKey; /* QP's QKey (for RD only) */ + + uint32 QPN:24; + uint32 Reserved1:8; + + uint32 EECN:24; + uint32 Reserved2:8; + + uint32 StartingPSN:24; + uint32 Reserved3:8; + + uint32 ArbResponderResources:8; /* senders's arbitrated + * qpAttr->ResponderResources + * receiver should validate and use + * to set its qpAttr->InitiatorDepth + */ + uint32 ArbInitiatorDepth:8; /* sender's arbitrated + * qpAttr->InitiatorDepth + * receiver should validate and use + * to set its + * qpAttr->ResponderResources + */ + uint32 TargetAckDelay:5; + uint32 FailoverAccepted:2; /* enum CM_REP_FAILOVER */ + uint32 EndToEndFlowControl:1; + uint32 RnRRetryCount:3; + uint32 Reserved4:5; + /* Server Side Channel Adapter GUID (also known as node GUID) */ + uint64 CaGUID; /* ignored in server accept, returned to client */ + uint8 PrivateData[CM_REPLY_INFO_USER_LEN]; + +} CM_REPLY_INFO; + +/****************************************************************************** + * CM_REJECT_INFO - + * Reject info. Use by server to reject a connect request or use + * by client to reject a connect reply. Mapped directly to CMM_REJ + */ +typedef struct _CM_REJECT_INFO { + + uint32 Reason:16; /* CM_REJECTION_CODE */ + uint32 RejectInfoLen:7; + uint32 Reserved1:9; + uint8 RejectInfo[CM_REJ_ADD_INFO_LEN]; /* 72 bytes */ + uint8 PrivateData[CM_REJECT_INFO_USER_LEN]; /* 148 bytes */ +} CM_REJECT_INFO; + + +/****************************************************************************** + * CM_RTU_INFO - + * Ready-to-use info. Use by client to accept the connect reply. + * Mapped directly to CMM_RTU + */ +typedef struct _CM_RTU_INFO { + uint8 PrivateData[CM_RTU_INFO_USER_LEN]; /* 224 bytes */ +} CM_RTU_INFO; + + +/****************************************************************************** + * CM_ALTPATH_INFO - + * Load Alternate Path info. Use by client to define a new alternate + * path for a QP which is using APM for resiliency + */ +typedef struct _CM_ALTPATH_INFO { + uint8 AlternateAckTimeout; + CM_CEP_PATHINFO AlternatePathInfo; + uint8 PrivateData[CM_LAP_INFO_USER_LEN]; /* 168 bytes */ +} CM_ALTPATH_INFO; + +/****************************************************************************** + * CM_ALTPATH_REPLY_INFO - + * Alternate Path Reply info. Use by server to accept/reject a + * a new alternate path for a QP which is using APM for resiliency. + * Also provided in callbacks to client. + * For client FCM_ALTPATH_REPLY callback with APStatus = APS_PATH_LOADED: + * Alternate.AckTimeout and Alternate.PathInfo will match + * value from original LAP, it is provided in the callback as a convenience so + * application need not keep a local copy + * For client FCM_ALTPATH_REJECT callback: + * APStatus != APS_PATH_LOADED and AddInfo is provided. + * For server calls to iba_cm_altpath_reply: + * only AddInfo field is used + */ +typedef struct _CM_ALTPATH_REPLY_INFO { + uint16 APStatus; /* CM_APR_STATUS */ + union { + struct { /* only for FCM_ALTPATH_REPLY w/ APStatus == APS_PATH_LOADED */ + CM_CEP_PATHINFO PathInfo; + uint8 AckTimeout; + } Alternate; + struct { /* for FCM_ALTPATH_REJECT or iba_altpath_reply */ + uint8 Len; + uint8 Reserved; + uint8 Info[CM_APR_ADD_INFO_LEN]; /* 72 bytes */ + } AddInfo; + } u; + uint8 PrivateData[CM_APR_INFO_USER_LEN]; /* 148 bytes */ +} CM_ALTPATH_REPLY_INFO; + + +/****************************************************************************** + * CM_DREQUEST_INFO - + * Disconnect request info. Use by client or server to disconnect an + * endpoint. Mapped directly to CMM_DREQ + */ +typedef struct _CM_DREQUEST_INFO { + uint8 PrivateData[CM_DREQUEST_INFO_USER_LEN]; /* 220 bytes */ +} CM_DREQUEST_INFO; + + +/****************************************************************************** + * CM_DREPLY_INFO - + * Disconnect reply info. Use by client or server to reply to a + * disconnect request. Mapped directly to CMM_DREP + */ +typedef struct _CM_DREPLY_INFO { + uint8 PrivateData[CM_DREPLY_INFO_USER_LEN]; /* 224 bytes */ +} CM_DREPLY_INFO; + + +/****************************************************************************** + * SIDR_RESP_INFO - + * SIDR response info. Use by UD server to response to a + * SIDR request. Mapped directly to CMM_SIDR_RESP + */ +typedef struct _SIDR_RESP_INFO { + + uint32 QPN:24; + uint32 Status:8; /* SIDR_RESP_STATUS */ + + uint32 QKey; + + /* 72 bytes of port info for redir or unsupported version. */ + /* This is hidden from the user, in future may need to expose. */ + + uint8 PrivateData[SIDR_RESP_INFO_USER_LEN]; /* 136 - 140 bytes */ + +} SIDR_RESP_INFO; + + +/****************************************************************************** + * SIDR_REQ_INFO - + * SIDR request info. Use by UD client to query a UD server. + * DOES NOT mapped directly to CMM_SIDR_RESP + */ +typedef struct _SIDR_REQ_INFO { + + uint64 SID; + uint64 PortGuid; + uint16 PartitionKey; /* PKey requested for Service */ + + CM_CEP_PATHINFO PathInfo; /* Path info */ + + uint8 PrivateData[SIDR_REQ_INFO_USER_LEN]; /* 216 bytes */ + +} SIDR_REQ_INFO; + + +/****************************************************************************** + * SIDR_REGISTER_INFO - + * SIDR register info. Use by UD server to register its SID. + * No mapping + */ +typedef struct _SIDR_REGISTER_INFO { + + uint64 ServiceID; + + uint32 QPN:24; + uint32 Reserved1:8; + + uint32 QKey; + +} SIDR_REGISTER_INFO; + + +/****************************************************************************** + * CM_CONN_INFO - + * Union of the above connection info + * when provided in a callback, the Status field indicates which structure + * is valid. + * When provided in the iba_cm_accept call, the state of the CEP implies the + * structure to use (eg. Reply on server side, Rtu on client side) + */ +typedef union _CONN_INFO { + CM_REQUEST_INFO Request; /* FCM_CONNECT_REQUEST */ + CM_REPLY_INFO Reply; /* FCM_CONNECT_REPLY */ + CM_RTU_INFO Rtu; /* FCM_CONNECT_ESTABLISHED */ + CM_REJECT_INFO Reject; /* FCM_CONNECT_REJECT */ + CM_ALTPATH_INFO AltPathRequest; /* FCM_ALTPATH_REQUEST */ + CM_ALTPATH_REPLY_INFO AltPathReply; /* FCM_ALTPATH_REPLY, FCM_ALTPATH_REJECT */ + CM_DREQUEST_INFO DisconnectRequest; /* FCM_DISCONNECT_REQUEST */ + CM_DREPLY_INFO DisconnectReply; /* FCM_DISCONNECT_REPLY */ + SIDR_REQ_INFO SidrRequest; /* FSIDR_REQUEST */ + SIDR_RESP_INFO SidrResponse; /* FSIDR_RESPONSE, FSIDR_RESPONSE_ERR */ + CM_LISTEN_INFO ListenRequest; /* internal use only */ + SIDR_REGISTER_INFO SidrRegister; /* internal use only */ + /* no data for: + * FCM_CONNECT_TIMEOUT + * FCM_CONNECT_CANCEL + * FCM_ALTPATH_TIMEOUT + * FCM_DISCONNECTED + * FCM_DISCONNECT_TIMEOUT + * FSIDR_REQUEST_TIMEOUT + * FCM_CA_REMOVED + */ +} CONN_INFO; + +typedef struct _CM_CONN_INFO { + FSTATUS Status; /* in output/callback tell field in union */ + CONN_INFO Info; +} CM_CONN_INFO; + + +/****************************************************************************** + * Function prototypes + */ + +/* + * iba_cm_create_cep/CmCreateCEP + * + * This routine creates a connection endpoint object (CEP). This object + * is used to establish a connection to the remote endpoint or listen for + * incoming connections on this endpoint. This object is also used to register + * the endpoint to resolve SIDR request + * + * + * + * INPUTS: + * + * TransportServiceType- Specify the transport service type, RC, UC, RD, UD + * + * + * OUTPUTS: + * + * None. + * + * + * RETURNS: + * + * A handle to the CEP object if successful. Otherwise, NULL + * + */ +typedef IB_HANDLE +(CM_CREATE_CEP)( + IN CM_CEP_TYPE TransportServiceType + ); +IBA_API CM_CREATE_CEP iba_cm_create_cep; +IBA_API CM_CREATE_CEP CmCreateCEP; /* for backward compatibility */ + + +/* + * iba_cm_destroy_cep/CmDestroyCEP + * + * This routine destroys the CEP object. This routine is called when the handle + * to the CEP object is no longer in use. + * + * + * + * INPUTS: + * + * hCEP - Handle to the CEP object that was returned in iba_cm_create_cep(). + * + * + * OUTPUTS: + * + * None. + * + * + * RETURNS: + * + * FSUCCESS + * + * FINVALID_STATE + * FCM_NOT_INITIALIZED + * FCM_INVALID_HANDLE + * + */ + +typedef FSTATUS +(CM_DESTROY_CEP)( + IN IB_HANDLE hCEP + ); +IBA_API CM_DESTROY_CEP iba_cm_destroy_cep; +IBA_API CM_DESTROY_CEP CmDestroyCEP; /* for backward compatibility */ + + +/* + * iba_cm_modify_cep/CmModifyCEP + * + * This routine modifies the attribute setting of a connection endpoint object (CEP). + * + * + * + * INPUTS: + * + * AttrType - Specify the attribute to modify + * AttrValue - Specify the new value of the attribute + * AttrLen - Specify the length in bytes of the new attribute value + * + * OUTPUTS: + * + * None. + * + * + * RETURNS: + * + * A handle to the CEP object if successful. Otherwise, NULL + * + */ +typedef FSTATUS +(CM_MODIFY_CEP)( + IN IB_HANDLE hCEP, + uint32 AttrType, + const char* AttrValue, + uint32 AttrLen, + uint32 Offset + ); +IBA_API CM_MODIFY_CEP iba_cm_modify_cep; +IBA_API CM_MODIFY_CEP CmModifyCEP; /* for backward compatibility */ + +/* + * iba_cm_prepare_request + * + * This routine is used by a client to help build a Connect Request for + * use in iba_cm_connect. It also builds the QP attributes to move the + * QP to Init. + * + * + * INPUTS: + * + * TransportServiceType- transport service type, RC, UC, RD, UD + * Path - Primary Path for connection + * data pointed to only used during duration of call + * AltPath - Alternate Path for connection + * data pointed to only used during duration of call + * + * OUTPUTS: + * Info - parameters to use to establish the connection. + * and move the QP to QPStateInit + * + * None. + * + * + * RETURNS: + * + * FSUCCESS + * FINVALID_PARAMETER + * FINSUFFICIENT_MEMORY + * FNOT_FOUND - bad SGID or PKey in Path/AltPath + * FCM_NOT_INITIALIZED + * FCM_INVALID_HANDLE + * + * This routine validates the SGID and PKey in Path and AltPath + * it also confirms the Path and AltPath SGIDs are both from the same CA + * if this returns FNOT_FOUND, the caller should consider using different + * Path/AltPath values and try again. + * + * The request is partially built. The following must be filled in: + * SID + * CEPInfo.QPN - RC/UC QPN + * CEPInfo.Qkey, LocalEECN, RemoteEECN - RD info + * + * The following are defaulted and may be adjusted by the caller: + * OfferedInitiatorDepth - set to max for CA + * OfferedResponderResources - set to max for CA + * AckTimeout/AlternateAckTimeout - computed using LocalCaAckDelay and + * PktLifeTime, selected applications may need to increase + * this value + * RetryCount - defaults to a reasonable value, appl may adjust down or up + * RnRRetryCount - defaults to infinite + * PrivateData - zeroed + * + * Per the IBTA spec, the QP should be moved to Init prior to calling + * iba_cm_connect/iba_cm_connect_peer. + * + * The application must complete the QpAttrInit as follows: + * QpAttrInit.AccessControl = desired settings + * QpAttrInit.Attrs |= IB_QP_ATTR_ACCESSCONTROL + */ +typedef struct _CM_PREPARE_REQUEST_INFO { + CM_REQUEST_INFO Request; /* for iba_cm_connect[_peer] */ + IB_QP_ATTRIBUTES_MODIFY QpAttrInit; /* to move QP to Init */ +} CM_PREPARE_REQUEST_INFO; + +typedef FSTATUS +(CM_PREPARE_REQUEST)( + IN CM_CEP_TYPE TransportServiceType, + IN const IB_PATH_RECORD *Path, + IN const IB_PATH_RECORD *AltPath OPTIONAL, + OUT CM_PREPARE_REQUEST_INFO *Info + ); +IBA_API CM_PREPARE_REQUEST iba_cm_prepare_request; + +/* + * iba_cm_connect/CmConnect + * + * This routine is used by a client to establish a connection to the remote + * server endpoint. + * + * + * INPUTS: + * + * hCEP - Handle to the CEP object that was returned in iba_cm_create_cep(). + * + * pConnectRequest - Specify the parameters to use to establish the connection. + * data pointed to only used during duration of call + * + * pfnConnectCB - Connection callback function. The CM notify the caller via this + * callback when a connect reply, reject or timeout occur. + * + * Context - This context is passed back in the callback routine. + * + * OUTPUTS: + * + * None. + * + * + * RETURNS: + * + * FPENDING + * + * FINVALID_STATE + * FINVALID_PARAMETER + * FCM_NOT_INITIALIZED + * FCM_INVALID_HANDLE + * FCM_ADDR_INUSE + * + */ +typedef FSTATUS +(CM_CONNECT)( + IN IB_HANDLE hCEP, + IN const CM_REQUEST_INFO* pConnectRequest, /* Send REQ */ + IN PFN_CM_CALLBACK pfnConnectCB, /* Recv REP, REJ */ + IN void* Context + ); +IBA_API CM_CONNECT iba_cm_connect; +IBA_API CM_CONNECT CmConnect; /* for backward compatibility */ + +/* + * iba_cm_connect_peer/CmConnectPeer + * + * This routine is used by a peer to establish a connection to another remote + * peer endpoint. + * + * + * INPUTS: + * + * hCEP - Handle to the CEP object that was returned in iba_cm_create_cep(). + * + * pPeerRequest - Specify the parameters to use to establish the connection. + * data pointed to only used during duration of call + * + * pfnPeerCB - Peer connection callback function. The CM notify the caller via this + * callback when a connect reply, reject or timeout occur. + * + * Context - This context is passed back in the callback routine. + * + * OUTPUTS: + * + * None. + * + * + * RETURNS: + * + * FPENDING + * + * FINVALID_STATE + * FINVALID_PARAMETER + * FCM_NOT_INITIALIZED + * FCM_INVALID_HANDLE + * FCM_ADDR_INUSE + * + */ +typedef FSTATUS +(CM_CONNECT_PEER)( + IN IB_HANDLE hCEP, + IN const CM_REQUEST_INFO* pPeerRequest, /* Send REQ */ + IN PFN_CM_CALLBACK pfnPeerCB, /* Recv REP, REJ */ + IN void* Context + ); +IBA_API CM_CONNECT_PEER iba_cm_connect_peer; +IBA_API CM_CONNECT_PEER CmConnectPeer; /* for backward compatibility */ + + +/* + * iba_cm_listen/CmListen + * + * This routine is used by a server to listen for incoming clients connections + * on the specified endpoint. + * + * + * INPUTS: + * + * hCEP - Handle to the CEP object that was returned in iba_cm_create_cep(). + * + * pListenRequest - Specify the parameters to listen for incoming connections on this + * endpoint. + * data pointed to only used during duration of call + * + * pfnListenCB - Listen callback function. The CM notify the caller via this + * callback when an incoming connection arrives on this endpoint. + * + * Context - This context is passed back in the callback routine. + * + * OUTPUTS: + * + * None. + * + * + * RETURNS: + * + * FPENDING + * + * FINVALID_STATE + * FINVALID_PARAMETER + * FCM_NOT_INITIALIZED + * FCM_INVALID_HANDLE + * FCM_ADDR_INUSE + * + */ +typedef FSTATUS +(CM_LISTEN)( + IN IB_HANDLE hCEP, + IN const CM_LISTEN_INFO* pListenRequest, + IN PFN_CM_CALLBACK pfnListenCB, /* Recv REQ */ + IN void* Context + ); +IBA_API CM_LISTEN iba_cm_listen; +IBA_API CM_LISTEN CmListen; /* for backward compatibility */ + + + +/* + * iba_cm_cancel/CmCancel + * + * This routine cancels a pending connect or listen request. + * + * + * INPUTS: + * + * hCEP - Handle to the CEP object used in iba_cm_connect() + * or iba_cm_listen(). + * + * + * OUTPUTS: + * + * None. + * + * + * RETURNS: + * + * FSUCCESS + * + * FPENDING + * FINVALID_STATE + * FINVALID_PARAMETER + * FCM_NOT_INITIALIZED + * FCM_INVALID_HANDLE + */ +typedef FSTATUS +(CM_CANCEL)( + IN IB_HANDLE hCEP + ); +IBA_API CM_CANCEL iba_cm_cancel; +IBA_API CM_CANCEL CmCancel; /* for backward compatibility */ + + +/* + * iba_cm_process_request + * + * Perform parameter negotiation and help build the Reply for a + * server which is processing an inbound FCM_CONNECT_REQUEST + * + * + * INPUTS: + * + * hCEP - Handle to the CEP object reported by FCM_CONNECT_REQUEST + * Failover - FailoverAccepted value desired in reply + * (ignored if failover is not supported by CEP or CA) + * + * + * OUTPUTS: + * + * Info - Information required to move QP to Init and RTR + * and majority of Reply for use in iba_cm_accept + * + * + * RETURNS: + * + * FSUCCESS + * + * FINVALID_STATE + * FINVALID_PARAMETER + * FINSUFFICIENT_MEMORY + * FNOT_FOUND + * FCM_CONNECT_CANCEL + * + * The reply is partially built. The following must be filled in: + * Reply.QPN - RC/UC QPN + * Reply.Qkey, EECN - RD info + * + * The following are defaulted and may be adjusted by the caller: + * ArbInitiatorDepth - negotiated based on max for CA + * ArbResponderResources - negotiated based on max for CA + * RnRRetryCount - defaults to value used by client side + * PrivateData - zeroed + * + * The application must complete the QpAttrInit as follows: + * QpAttrInit.AccessControl = desired settings + * QpAttrInit.Attrs |= IB_QP_ATTR_ACCESSCONTROL + * + * The application must complete the QpAttrRtr as follows: + * QpAttrRtr.MinRnrTimer = UsecToRnrNakTimer(appl desired value) + * QpAttrRtr.Attrs |= IB_QP_ATTR_MINRNRTIMER + */ + +typedef struct _CM_PROCESS_REQUEST_INFO { + CM_CONN_INFO ReplyInfo; + IB_QP_ATTRIBUTES_MODIFY QpAttrInit; + IB_QP_ATTRIBUTES_MODIFY QpAttrRtr; +} CM_PROCESS_REQUEST_INFO; + +typedef FSTATUS +(CM_PROCESS_REQUEST)( + IN IB_HANDLE hCEP, + IN CM_REP_FAILOVER Failover, + OUT CM_PROCESS_REQUEST_INFO*Info + ); +IBA_API CM_PROCESS_REQUEST iba_cm_process_request; + +/* + * iba_cm_accept/CmAccept + * + * This routine is used by a client to accept the connect reply from the server + * and set this endpoint into a connected state. This routine is used by a server to + * accept and reply to the client's connect request. + * + * + * INPUTS: (Server) + * + * hCEP - Handle to the CEP object. This handle must be the same + * handle passed to iba_cm_listen(). + * + * pSendConnInfo - Specify the reply info to send back to the remote client endpoint. + * data pointed to only used during duration of call + * + * pRecvConnInfo - Specify the returned rtu info from the remote client endpoint. + * endpoint. (if CM_FLAG_ASYNC_ACCEPT is set for CEP, this is + * not used) + * data pointed to only used during duration of call + * + * pfnCallback - Callback function to use for future events on this + * CEP (namely Disconnect, APM or for Async Accept, the + * connection establishment/failure). + * Ignored for Peer to Peer. + * + * Context - context for new CEP. not used for peer to peer. + * + * OUTPUTS: (Server) + * + * hNewCEP - Handle to the new CEP object that represent the new connection + * from client. (For peer to peer connections this is optional + * if provided nCEP will be returned here) + * When using Async Accept, the server must be ready for + * callbacks to occur immediately after iba_cm_accept. As such + * it is recommended that the pointer given here be the actual + * storage area for the new CEP handle (as opposed to a local + * temp variable). + * + * + * + * INPUTS: (Client) + * + * hCEP - Handle to the CEP object. This handle must be the same + * handle passed to iba_cm_connect(). + * + * pSendConnInfo - Specify the rtu info to send back to the remote server endpoint. + * If NULL a default (zero PrivateData) RTU will be sent + * + * pRecvConnInfo - Not used. + * + * pfnCallback - Not used. + * + * Context - Not used. + * + * + * OUTPUTS: (Client) + * + * hNewCEP - Not used. + * + * + * RETURNS: + * + * FSUCCESS - Client RTU queued to be sent. + * FCM_CONNECT_ESTABLISHED - server REP sent and RTU received + * FCM_CONNECT_REJECT - server REP sent and REJ received + * FCM_CONNECT_TIMEOUT - server REP sent and timeout waiting for RTU + * FCM_CONNECT_CANCEL - listen on this CEP has been canceled + * + * FERROR - Unable to send the reply ack packet + * FTIMEOUT - The timeout interval expires + * FINVALID_STATE - The endpoint is not in the valid state for this call + * FINVALID_PARAMETER + * FCM_NOT_INITIALIZED + * FCM_INVALID_HANDLE + * FPENDING - Server Async Accept, REP queued to be sent. + * + * + * + * IRQL: + * + */ +typedef FSTATUS +(CM_ACCEPT)( + IN IB_HANDLE hCEP, + IN CM_CONN_INFO* pSendConnInfo, /* Send REP, Send RTU */ + OUT CM_CONN_INFO* pRecvConnInfo, /* Recv RTU, Recv REJ */ + IN PFN_CM_CALLBACK pfnCallback, /* For hNewCEP */ + IN void* Context, /* For hNewCEP */ + OUT IB_HANDLE* hNewCEP + ); +IBA_API CM_ACCEPT iba_cm_accept; +IBA_API CM_ACCEPT CmAccept; /* for backward compatibility */ + + +/* + * iba_cm_reject/CmReject + * + * This routine is used by a client to reject the connect reply from the server . + * This routine is also used by a server to reject the incoming client's connect request. + * + * INPUTS: + * + * hCEP - Handle to the CEP object. + * + * pReject - Specify the reject info that will be send back to the remote endpoint. + * data pointed to only used during duration of call + * + * + * OUTPUTS: + * + * None. + * + * + * RETURNS: + * + * FSUCCESS + * + * FERROR + * FINVALID_STATE + * FINVALID_PARAMETER + * FCM_NOT_INITIALIZED + * FCM_INVALID_HANDLE + * + */ +typedef FSTATUS +(CM_REJECT)( + IN IB_HANDLE hCEP, + IN const CM_REJECT_INFO* pRejectInfo /* Send REJ */ + ); +IBA_API CM_REJECT iba_cm_reject; +IBA_API CM_REJECT CmReject; /* for backward compatibility */ + +/* + * iba_cm_process_reply + * + * This routine is used by a client to compose the QP Attributes to + * move to QPStateReadyToSend + * + * INPUTS: + * + * hCEP - Handle to the CEP object. + * + * + * OUTPUTS: + * + * Info - QP Attributes which should be used to move to RTS + * data pointed to only used during duration of call + * + * + * RETURNS: + * + * FSUCCESS + * + * FERROR + * FINVALID_STATE + * FINVALID_PARAMETER + * FCM_NOT_INITIALIZED + * FCM_INVALID_HANDLE + * + * + * The application must complete the QpAttrRtr as follows: + * QpAttrRtr.MinRnrTimer = UsecToRnrNakTimer(appl desired value) + * QpAttrRtr.Attrs |= IB_QP_ATTR_MINRNRTIMER + * + * The complete set of QpAttrRts attributes is generated. + */ +typedef struct _CM_PROCESS_REPLY_INFO { + IB_QP_ATTRIBUTES_MODIFY QpAttrRtr; + IB_QP_ATTRIBUTES_MODIFY QpAttrRts; +} CM_PROCESS_REPLY_INFO; + +typedef FSTATUS +(CM_PROCESS_REPLY)( + IN IB_HANDLE hCEP, + OUT CM_PROCESS_REPLY_INFO *Info + ); +IBA_API CM_PROCESS_REPLY iba_cm_process_reply; + + +/* + * iba_cm_prepare_rts + * + * This routine is used by a server to compose the QP Attributes to + * move to QPStateReadyToSend + * + * INPUTS: + * + * hCEP - Handle to the CEP object. + * + * + * OUTPUTS: + * + * QpAttrRts - QP Attributes which should be used to move to RTS + * + * + * RETURNS: + * + * FSUCCESS + * + * FERROR + * FINVALID_STATE + * FINVALID_PARAMETER + * FCM_NOT_INITIALIZED + * FCM_INVALID_HANDLE + * + * + * The completed set of required attributes is generated. + * If desired the application may add optional parameters + * such as MinRnrTimer, SendQ/RecvQDepth SendDSListDepth/RecvDSListDepth + */ +typedef FSTATUS +(CM_PREPARE_RTS)( + IN IB_HANDLE hCEP, + OUT IB_QP_ATTRIBUTES_MODIFY *QpAttrRts + ); +IBA_API CM_PREPARE_RTS iba_cm_prepare_rts; + +/* + * iba_cm_altpath_request/CmAltPathRequest + * + * Request a new alternate path + * Only allowed for Client/Active side of connection + * + * INPUTS: + * + * hCEP - Handle to the CEP object. + * pLapInfo - Information used to build the LAP to send + * if AlternateAckTimeout is 0, CM will + * compute an appropriate value based on + * PktLifeTime for the path and the LocalCaAckDelay + * data pointed to only used during duration of call + * + * + * OUTPUTS: + * + * None. + * + * RETURNS: + * + * FPENDING - LAP queued to be sent. + * FINVALID_STATE - The endpoint is not in the valid state for this call + * FERROR - Unable to send the lap packet + * FINVALID_ARGUMENTS - invalid Info.Lap + * + * + * IRQL: + * + * This routine is called at IRQL_PASSIVE_LEVEL. + */ +typedef FSTATUS +(CM_ALTPATH_REQUEST)( + IN IB_HANDLE hCEP, + IN const CM_ALTPATH_INFO* pLapInfo /* Send LAP */ + ); +IBA_API CM_ALTPATH_REQUEST iba_cm_altpath_request; + +/* + * iba_cm_process_altpath_request + * + * process a FCM_ALTPATH_REQUEST. This prepares the QP Attributes + * to set the new alternate path and prepares a Reply + * Only allowed for Server/Passive side of connection + * + * INPUTS: + * + * hCEP - Handle to the CEP object. + * AltPathRequest - AltPath Request we received + * data pointed to only used during duration of call + * + * + * OUTPUTS: + * + * Info - constructed QP Attributes and Alt Path Reply + * + * RETURNS: + * + * FINVALID_STATE - The endpoint is not in the valid state for this call + * FINVALID_PARAMETER + * FCM_NOT_INITIALIZED + * FCM_INVALID_HANDLE + * + * + * IRQL: + * + * This routine is called at IRQL_PASSIVE_LEVEL. + * + * The completed set of required attributes is generated. + * + * The reply which is prepared is a simple accept of the alternate path + * The following are defaulted and may be adjusted by the caller: + * PrivateData - zeroed + */ +typedef struct _CM_PROCESS_ALTPATH_REQUEST_INFO { + CM_ALTPATH_REPLY_INFO AltPathReply; + IB_QP_ATTRIBUTES_MODIFY QpAttrRts; +} CM_PROCESS_ALTPATH_REQUEST_INFO; + +typedef FSTATUS +(CM_PROCESS_ALTPATH_REQUEST)( + IN IB_HANDLE hCEP, + IN CM_ALTPATH_INFO* AltPathRequest, + OUT CM_PROCESS_ALTPATH_REQUEST_INFO* Info + ); +IBA_API CM_PROCESS_ALTPATH_REQUEST iba_cm_process_altpath_request; + +/* + * iba_cm_altpath_reply/CmAltPathReply + * + * Reply to an alternate path request + * Only allowed for Server/Passive side of connection + * + * INPUTS: + * + * hCEP - Handle to the CEP object. + * pAprInfo - AltPath Reply + * data pointed to only used during duration of call + * + * + * OUTPUTS: + * + * None. + * + * RETURNS: + * + * FSUCCESS - APR queued to be sent. + * FINVALID_STATE - The endpoint is not in the valid state for this call + * FERROR - Unable to send the apr packet + * + * + * IRQL: + * + * This routine is called at IRQL_PASSIVE_LEVEL. + */ +typedef FSTATUS +(CM_ALTPATH_REPLY)( + IN IB_HANDLE hCEP, + IN CM_ALTPATH_REPLY_INFO* pAprInfo /* Send APR */ + ); +IBA_API CM_ALTPATH_REPLY iba_cm_altpath_reply; + + +/* + * iba_cm_process_altpath_reply + * + * process a FCM_ALTPATH_REPLY. This prepares the QP Attributes + * to set the new alternate path + * Only allowed for Client/Active side of connection + * + * INPUTS: + * + * hCEP - Handle to the CEP object. + * AltPathReply - AltPath Reply we received + * data pointed to only used during duration of call + * + * + * OUTPUTS: + * + * QpAttrRts - constructed QP Attributes + * + * RETURNS: + * + * FINVALID_STATE - The endpoint is not in the valid state for this call + * FINVALID_PARAMETER + * FCM_NOT_INITIALIZED + * FCM_INVALID_HANDLE + * + * + * IRQL: + * + * This routine is called at IRQL_PASSIVE_LEVEL. + * + * The completed set of required attributes is generated. + */ +typedef FSTATUS +(CM_PROCESS_ALTPATH_REPLY)( + IN IB_HANDLE hCEP, + IN const CM_ALTPATH_REPLY_INFO* AltPathReply, + OUT IB_QP_ATTRIBUTES_MODIFY* QpAttrRts + ); +IBA_API CM_PROCESS_ALTPATH_REPLY iba_cm_process_altpath_reply; + +/* + * iba_cm_migrated/CmMigrated + * + * Inform CM that alternate path has been migrated to + * FUTURE for server side may be hooked into CM Async Event callbacks + * + * INPUTS: + * + * + * + * OUTPUTS: + * + * None. + * + * RETURNS: + * + * FSUCCESS - CEP adjusted to reflect migration + * FINVALID_STATE - The endpoint is not in the valid state for this call + * + * + * IRQL: + * + * This routine is called at IRQL_PASSIVE_LEVEL. + */ +typedef FSTATUS +(CM_MIGRATED)( + IN IB_HANDLE hCEP + ); +IBA_API CM_MIGRATED iba_cm_migrated; + + +/* + * iba_cm_migrated_reload + * + * Inform CM that alternate path has been migrated to + * and prepare a AltPath Request to load previous primary path + * as the new alternate path + * also returns new primary path + * + * This is useful is an application wants a simple dual path APM + * however this can be risky in that it assumes the old primary path will + * be restored as it was (which may not be the case if cables are moved + * or fabric is otherwise reconfigured to restore the old path) + * Alternately the AltPathRequest can also be used to simply resolve a new path + * to the old primary DGID and then update its Path before doing the + * iba_cm_altpath_request. The NewPrimaryPathInfo is also provided + * so the caller can select a path which is distinct from the New Primary Path + * + * This is a superset of the iba_cm_migrated + * + * INPUTS: + * + * + * + * OUTPUTS: + * + * NewPrimaryPath - new Primary Path (after migration) + * AckTimeout will be accurate + * however the PktLifeTime may not be + * AltPathRequest - a AltPath Request representing the old primary + * path. The Alternate AckTimeout will be accurate + * however the PktLifeTime may not be + * + * RETURNS: + * + * FSUCCESS - CEP adjusted to reflect migration + * FINVALID_STATE - The endpoint is not in the valid state for this call + * FINVALID_PARAMETER + * FCM_NOT_INITIALIZED + * FCM_INVALID_HANDLE + * + * + * IRQL: + * + * This routine is called at IRQL_PASSIVE_LEVEL. + */ + +typedef struct _CM_PATH_INFO { + CM_CEP_PATHINFO PathInfo; + uint8 AckTimeout; +} CM_PATH_INFO; + +typedef FSTATUS +(CM_MIGRATED_RELOAD)( + IN IB_HANDLE hCEP, + OUT CM_PATH_INFO* NewPrimaryPath OPTIONAL, + OUT CM_ALTPATH_INFO* AltPathRequest OPTIONAL + ); +IBA_API CM_MIGRATED_RELOAD iba_cm_migrated_reload; + +/* + * iba_cm_wait/CmWait + * + * For an application which wants to be single threaded, this can be used + * to wait for the next event on a set of CEPs and obtain the Callback info + * which would have been provided for any events on those CEPs. + * This routine is used by a caller to synchronous with its previous asynchronous operations without + * using the callback notification. The iba_cm_connect(), iba_cm_listen() + * and iba_cm_disconnect() are asynchronous in nature. + * + * INPUTS: + * + * CEPHandleArray[]- An array of handle to the CEP object to wait on. + * data pointed to only used during duration of call + * + * ConnInfoArray[] - An array of connection info buffers. + * data pointed to only used during duration of call + * + * ArrayCount - Number of CEP handle in CEPHandleArray[]. + * + * Timeout_us - Timeout interval. + * + * OUTPUTS: + * + * None. + * + * + * RETURNS: + * + * FSUCCESS + * + * FERROR + * FTIMEOUT + */ +typedef FSTATUS +(CM_WAIT)( + IN IB_HANDLE CEPHandleArray[], + OUT CM_CONN_INFO* ConnInfoArray[], + IN uint32 ArrayCount, + IN uint32 Timeout_us + ); +IBA_API CM_WAIT iba_cm_wait; +IBA_API CM_WAIT CmWait; /* for backward compatibility */ + + +/* + * iba_cm_disconnect/CmDisconnect + * + * This routine is used by a client or a server to close the current connection + * on the specified endpoint. + * + * INPUTS: + * + * hCEP - Handle to the CEP object. + * + * pDisconnectRequest - Specify the disconnect request. This request is send to the remote endpoint + * to inform it that this endpoint is closing down. + * data pointed to only used during duration of call + * + * pDisconnectReply - Specify the disconnect reply to the disconnect request. Caller call + * optionally this routine and passes in a reply to response to the + * disconnect notification. + * data pointed to only used during duration of call + * + * OUTPUTS: + * + * None. + * + * + * RETURNS: + * + * FSUCCESS + * + * FERROR + * FINVALID_STATE + * FINVALID_PARAMETER + * FCM_NOT_INITIALIZED + * FCM_INVALID_HANDLE + * FCM_ALREADY_DISCONNECTING + * + */ +typedef FSTATUS +(CM_DISCONNECT)( + IN IB_HANDLE hCEP, + IN const CM_DREQUEST_INFO* pDisconnectRequest, /* Send DREQ */ + IN const CM_DREPLY_INFO* pDisconnectReply /* Send DREP */ + ); +IBA_API CM_DISCONNECT iba_cm_disconnect; +IBA_API CM_DISCONNECT CmDisconnect; /* for backward compatibility */ + + +/* + * iba_cm_set_wait_obj/CmSetWaitObj + * + * Associate the specified endpoint with the event wait obj. + * This is useful for applications which want to implement their own + * synchronization mechanism based on their own event and iba_cm_wait instead + * of direct Cm callbacks. + * + * Not yet implemented + * + * INPUTS: + * + * hCEP - Handle to the CEP object. + * + * hWaitEvent - Event wait handle. + * + * OUTPUTS: + * + * None. + * + * + * RETURNS: + * + * FSUCCESS + * + * FERROR + */ +#if 0 +typedef FSTATUS +(CM_SET_WAIT_OBJ)( + IN IB_HANDLE hCEP, + IN EVENT_HANDLE hWaitEvent + ); +IBA_API CM_SET_WAIT_OBJ iba_cm_set_wait_obj; +IBA_API CM_SET_WAIT_OBJ CmSetWaitObj; /* for backward compatibility */ +#endif + +/* + * UD Service ID resolution routines + * + + * + * iba_cm_sidr_register/SIDRRegister + * + * This routine is used by a UD server to register its Service ID (SID) for + * the specified endpoint so that UD client can lookup the QPN the UD server is using. + * + * INPUTS: + * + * hCEP - Handle to the CEP object. This is the handle returned from iba_cm_create_cep(). + * + * pSIDRRegisterInfo - Registeration info. + * data pointed to only used during duration of call + * + * pfnQueryCallback - Query callback function. The CM notify the caller via this callback + * when an incoming SIDR query is made on this endpoint. This allows + * the UD server to "trap" the queries. + * + * Context - This context field is passed back in the callback routine. + * + * OUTPUTS: + * + * None. + * + * + * RETURNS: + * + * FSUCCESS + * + * FINVALID_STATE + * FINVALID_PARAMETER + * FCM_NOT_INITIALIZED + * FCM_INVALID_HANDLE + * FCM_ADDR_INUSE + */ +typedef FSTATUS +(CM_SIDR_REGISTER)( + IN IB_HANDLE hCEP, + IN const SIDR_REGISTER_INFO* pSIDRRegisterInfo, + IN PFN_CM_CALLBACK pfnQueryCallback, + IN void* Context + ); +IBA_API CM_SIDR_REGISTER iba_cm_sidr_register; +IBA_API CM_SIDR_REGISTER SIDRRegister; /* for backward compatibility */ + +/* + * iba_cm_sidr_deregister/SIDRDeregister + * + * Deregister the UD server's SID. + * + * INPUTS: + * + * hCEP - Handle to the CEP object. This is the handle that + * was passed to iba_cm_sidr_register(). + * + * OUTPUTS: + * + * None. + * + * + * RETURNS: + * + * FSUCCESS + * + * FINVALID_STATE + * FINVALID_PARAMETER + * FCM_NOT_INITIALIZED + * FCM_INVALID_HANDLE + */ +typedef FSTATUS +(CM_SIDR_DEREGISTER)( + IN IB_HANDLE hCEP + ); +IBA_API CM_SIDR_DEREGISTER iba_cm_sidr_deregister; +IBA_API CM_SIDR_DEREGISTER SIDRDeregister; /* for backward compatibility */ + + +/* + * iba_cm_sidr_response/SIDRResponse + * + * The routine is called to response to a SIDR query. + * + * INPUTS: + * + * hCEP - Handle to the registered CEP object. + * + * pSIDRResponse - SIDR response + * data pointed to only used during duration of call + * + * OUTPUTS: + * + * None. + * + * + * RETURNS: + * + * FSUCCESS + * + * FINVALID_STATE + * FINVALID_PARAMETER + * FCM_NOT_INITIALIZED + * FCM_INVALID_HANDLE + */ +typedef FSTATUS +(CM_SIDR_RESPONSE)( + IN IB_HANDLE hCEP, + IN const SIDR_RESP_INFO* pSIDRResponse /* Send SIDR_RESP */ + ); +IBA_API CM_SIDR_RESPONSE iba_cm_sidr_response; +IBA_API CM_SIDR_RESPONSE SIDRResponse; /* for backward compatibility */ + + + +/* + * iba_cm_sidr_query/SIDRQuery + * + * The routine is called to perform a SIDR query. + * + * INPUTS: + * + * hCEP - Handle to the CEP object. + * + * pSIDRRequest - SIDR request + * data pointed to only used during duration of call + * + * pfnQueryCallback - + * + * Context - This context field is passed back in the callback routine. + * + * OUTPUTS: + * + * None. + * + * + * RETURNS: + * + * FSUCCESS + * + * FINVALID_STATE + * FINVALID_PARAMETER + * FCM_NOT_INITIALIZED + * FCM_INVALID_HANDLE + */ +typedef FSTATUS +(CM_SIDR_QUERY)( + IN IB_HANDLE hCEP, + IN const SIDR_REQ_INFO* pSIDRRequest, /* Send SIDR_REQ */ + IN PFN_CM_CALLBACK pfnQueryCallback, /* Recv SIDR_RESP */ + IN void* Context + ); +IBA_API CM_SIDR_QUERY iba_cm_sidr_query; +IBA_API CM_SIDR_QUERY SIDRQuery; /* for backward compatibility */ + +#if defined (__cplusplus) +}; +#endif + +#endif /* _IBA_IB_CM_H_ */ diff --git a/IbAccess/Common/Inc/ib_debug.h b/IbAccess/Common/Inc/ib_debug.h new file mode 100644 index 0000000..5456d4c --- /dev/null +++ b/IbAccess/Common/Inc/ib_debug.h @@ -0,0 +1,832 @@ +/* BEGIN_ICS_COPYRIGHT3 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT3 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +/* Suppress duplicate loading of this file */ +#ifndef _IBA_IB_DEBUG_H_ +#define _IBA_IB_DEBUG_H_ + +/* + * GLOBAL LEVELS + * + * + * Range reserved for the component specific values is + * 0x00000001 - 0x00FFFFFF + */ + +#include "iba/public/statustext.h" + +#ifdef VXWORKS +#undef ICS_LOGGING +#define ICS_LOGGING 1 +#endif + +/* This macro helps to catch macro calls with too many arguments + * if arg is not 0, it should cause a syntax error + * by causing a 0x5 for a good arg, + * even numeric non-zero values will cause syntax errors + */ +#define _ICS_MUST_BE_ZERO(arg) \ + { if (arg##x5 != 0x5) \ + { \ + } \ + } + +#ifdef ICS_LOGGING +#include "Log.h" +#include "Osa_Context.h" + +/* Macro to cast a logging pointer argument as needed */ +#define _DBG_PTR(arg) LOG_PTR(arg) +#define _TRC_PTR(arg) LOG_PTR(arg) + +#else /* ICS_LOGGING */ + +#define _DBG_PTR(arg) (arg) +#define _TRC_PTR(arg) (arg) + +#endif /* ICS_LOGGING */ + +/* These levels are available in debug and release builds */ +#define _DBG_LVL_DISABLE 0 +#define _DBG_LVL_INFO 0x10000000 +#define _DBG_LVL_WARN 0x20000000 +#define _DBG_LVL_ERROR 0x40000000 +#define _DBG_LVL_FATAL 0x80000000 +#define _DBG_LVL_ALL 0xFFFFFFFF +#define _DBG_LVL_NONDEBUG 0xF0000000 /* options allowed in release build */ + +#if defined( DBG) || defined( IB_DEBUG) + +#define _DBG_LVL_FUNC_TRACE 0x01000000 +#define _DBG_LVL_MEM_TRACK 0x02000000 +#define _DBG_LVL_MASK _DBG_LVL_ALL /* levels to allow */ + +#else +/* disabled debug levels */ +#define _DBG_LVL_FUNC_TRACE 0 +#define _DBG_LVL_MEM_TRACK 0 +#define _DBG_LVL_MASK _DBG_LVL_NONDEBUG /* levels to allow */ + +#endif /* DBG || IB_DEBUG */ + +#ifdef IB_TRACE +#define _TRC_LVL_FUNC_TRACE 0x80000000 +#define _TRC_LVL_MEM_TRACK 0x40000000 +#define _TRC_LVL_MASK 0xffffffff +#else /* IB_TRACE */ +/* disable trace levels */ +#define _TRC_LVL_FUNC_TRACE 0 +#define _TRC_LVL_MEM_TRACK 0 +#define _TRC_LVL_MASK 0 +#endif /* IB_TRACE */ + +#define _DBG_BREAK_ENABLE TRUE +#define _DBG_BREAK_DISABLE FALSE + + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct _IB_DBG_PARAMS{ + uint32 debug_level; /* Current debug output level */ +#if defined(DBG) || defined( IB_DEBUG) || defined( ICS_LOGGING) + uint32 break_enable; /* Should breakpoints be taken? */ +#endif + uint32 mem_tag; /* memory tag value // should this be here? */ + char *module; /* name of component */ +#ifdef ICS_LOGGING + Mod_Id_t modId; /* ICS module Id of component */ +#endif + uint32 trace_level; /* Current trace output level */ + uint32 trace_id; /* registered trace id of component */ +} IB_DBG_PARAMS; + +#ifdef __cplusplus +}; +#endif + +/* + * Reference this macro in only one .c file of your component + * it builds the module specific debug table, such that macros below + * can determine the module Id, Mem Tag, etc. + * For ICS_LOGGING it also creates the Ics logging subsystem + * initialization code and string table with module Id + * MOD_PREFIX should be the unquoted mixed case prefix for the module. It will + * prefix the name of the Initialize method + * + * The use of this macro is typically done with _ib_dbg_params redefined + * as a module specific name, for uniqueness, so linker won't find duplicates + */ +#ifdef ICS_LOGGING +#define _IB_DBG_PARAM_BLOCK(LEVEL,BREAK,MEM_TAG,MOD_NAME,MOD_ID,MOD_PREFIX) \ + IB_DBG_PARAMS _ib_dbg_params = {LEVEL, BREAK, MEM_TAG, MOD_NAME ":",MOD_ID, 0, 0}; \ + static Log_StringEntry_t _ics_stringTable[] = \ + { \ + { LOG_BUILD_STRID(MOD_ID, 0), \ + { MOD_NAME, \ + } \ + } \ + }; \ + void MOD_PREFIX##_Initialize() \ + { \ + Log_AddStringTable(MOD_ID, _ics_stringTable, 1); \ + } \ + void MOD_PREFIX##_SetDebugLevel(uint32 level) \ + { \ + __DBG_LEVEL__ = level; \ + } \ + uint32 MOD_PREFIX##_GetDebugLevel() \ + { \ + return __DBG_LEVEL__; \ + } \ + void MOD_PREFIX##_SetBreakFlag(uint32 enable) \ + { \ + __DBG_BRK_LEVEL__ = enable; \ + } \ + uint32 MOD_PREFIX##_GetBreakFlag() \ + { \ + return __DBG_BRK_LEVEL__; \ + } +#else /* ICS_LOGGING */ +#if defined( DBG) ||defined( IB_DEBUG) +#define _IB_DBG_PARAM_BLOCK(LEVEL,BREAK,MEM_TAG,MOD_NAME) \ + IB_DBG_PARAMS _ib_dbg_params = {LEVEL, BREAK, MEM_TAG, MOD_NAME ":", 0, 0}; +#else +#define _IB_DBG_PARAM_BLOCK(LEVEL,BREAK,MEM_TAG,MOD_NAME) \ + IB_DBG_PARAMS _ib_dbg_params = {LEVEL, MEM_TAG, MOD_NAME ":", 0, 0}; +#endif /* DBG || IB_DEBUG */ +#endif /* ICS_LOGGING */ + +/* Declare debug param block as extern for those object modules + * not declaring the block. + */ +extern IB_DBG_PARAMS _ib_dbg_params; + +#define __DBG_LEVEL__ _ib_dbg_params.debug_level +#define __DBG_BRK_LEVEL__ _ib_dbg_params.break_enable +#define __DBG_MEM_TAG__ _ib_dbg_params.mem_tag +#define __MOD_NAME__ _ib_dbg_params.module +#define __MOD_ID__ _ib_dbg_params.modId +#define __DBG_TRACE_LEVEL__ _ib_dbg_params.trace_level +#define _DBG_DEFINE_FUNC(NAME) \ + static const char __FUNC__[] = #NAME; + +#ifdef ICS_LOGGING +/* ============================================================================= + * Here we go, it takes a lot of preprocessor work to translate the + * intel variable argument (fmt, args) style STRING arg into + * the ICS style fixed argument list, which also includes a module Id + */ + +#define _ICS_DBG3_CALL(suffix, fmt, arg1, arg2, arg3, arg4, arg5, arg6, arg7, extraargs...) \ + do { \ + _ICS_MUST_BE_ZERO(arg7) \ + LOG_##suffix(__MOD_ID__, fmt, arg1, arg2, arg3, arg4, arg5, arg6); \ + } while (0) + +/* we now have STRING as normal args, and can adjust + * get at least 6 real arguments (and a 7th zero to check for undesired extra + * arguments) to format string + */ +#define _ICS_DBG2_DUMP(fmt, args...) \ + _ICS_DBG3_CALL(DUMP, fmt, ## args, 0,0,0,0,0,0,0) +#define _ICS_DBG2_DEBUG1(fmt, args...) \ + _ICS_DBG3_CALL(DEBUG1, fmt, ## args, 0,0,0,0,0,0,0) +#define _ICS_DBG2_DEBUG2(fmt, args...) \ + _ICS_DBG3_CALL(DEBUG2, fmt, ## args, 0,0,0,0,0,0,0) +#define _ICS_DBG2_DEBUG3(fmt, args...) \ + _ICS_DBG3_CALL(DEBUG3, fmt, ## args, 0,0,0,0,0,0,0) +#define _ICS_DBG2_DEBUG4(fmt, args...) \ + _ICS_DBG3_CALL(DEBUG4, fmt, ## args, 0,0,0,0,0,0,0) +#define _ICS_DBG2_DEBUG5(fmt, args...) \ + _ICS_DBG3_CALL(DEBUG5, fmt, ## args, 0,0,0,0,0,0,0) + +/* redefine MsgOut from idebug.h for those that call it directly */ +#undef MsgOut +#define MsgOut(fmt, args...) \ + _ICS_DBG3_CALL(DUMP, fmt, ## args, 0,0,0,0,0,0,0) + +/* redefine DbgOut from idebug.h for those that call it directly */ +#undef DbgOut +#define DbgOut(fmt, args...) \ + _ICS_DBG3_CALL(DEBUG1, fmt, ## args, 0,0,0,0,0,0,0) + +/* grab () off string and use to form macro call, so we can extract args */ +#define _ICS_DBG_DUMP(STRING) \ + _ICS_DBG2_DUMP STRING +#define _ICS_DBG_DEBUG1(STRING) \ + _ICS_DBG2_DEBUG1 STRING +#define _ICS_DBG_DEBUG2(STRING) \ + _ICS_DBG2_DEBUG2 STRING +#define _ICS_DBG_DEBUG3(STRING) \ + _ICS_DBG2_DEBUG3 STRING +#define _ICS_DBG_DEBUG4(STRING) \ + _ICS_DBG2_DEBUG4 STRING +#define _ICS_DBG_DEBUG5(STRING) \ + _ICS_DBG2_DEBUG5 STRING + +/* translate from Intel LEVELs to Ics Severities + * switch statement should be dealing with constants and optimize into + * only 1 case worth of code. switch is needed since we can't + * slam the level into STRING within its parens + */ +#if defined(DBG) || defined(IB_DEBUG) +#define _ICS_DBG_OUT(LEVEL,STRING) \ + switch (LEVEL & _DBG_LVL_MASK) \ + { \ + case 0: \ + break; \ + case _DBG_LVL_FATAL: \ + _ICS_DBG_DUMP(STRING); \ + break; \ + case _DBG_LVL_ERROR: \ + _ICS_DBG_DEBUG1(STRING); \ + break; \ + case _DBG_LVL_WARN: \ + _ICS_DBG_DEBUG2(STRING); \ + break; \ + case _DBG_LVL_INFO: \ + _ICS_DBG_DEBUG3(STRING); \ + break; \ + case _DBG_LVL_MEM_TRACK: \ + _ICS_DBG_DEBUG4(STRING); \ + break; \ + default: \ + case _DBG_LVL_FUNC_TRACE: \ + _ICS_DBG_DEBUG5(STRING); \ + break; \ + } +#else +#define _ICS_DBG_OUT(LEVEL,STRING) \ + switch (LEVEL & _DBG_LVL_MASK) \ + { \ + case 0: \ + break; \ + case _DBG_LVL_FATAL: \ + _ICS_DBG_DUMP(STRING); \ + break; \ + case _DBG_LVL_ERROR: \ + _ICS_DBG_DEBUG1(STRING); \ + break; \ + case _DBG_LVL_WARN: \ + _ICS_DBG_DEBUG2(STRING); \ + break; \ + case _DBG_LVL_INFO: \ + _ICS_DBG_DEBUG3(STRING); \ + break; \ + default: \ + _ICS_DBG_DEBUG5(STRING); \ + break; \ + } +#endif + +/* PROLOG and EPILOG were used by this module, however all + * callers define them as empty macros + * Hence the use in the ICS_LOGGING version has been removed + * As a result the __DBG_LEVEL__ is not used, the ICS Logging controls + * are the primary and only control for these logging settings + * Hence the initial settings in TTS for __DBG_LEVEL__ are ignored + */ +#define _DBG_PRINT(LEVEL,STRING) _ICS_DBG_OUT(LEVEL,STRING) + +#define _DBG_DUMP_MEMORY(LEVEL,STRING,ADDR,LENGTH) \ + _ICS_DBG_OUT(LEVEL, ("%s:\n%F", _DBG_PTR(STRING), Log_MemoryDump(ADDR, LENGTH))) + +/* TBD - BUGBUG - need to translate DUMPFORMAT from _DBG_DUMP_FORMAT_* + * to LOG_DUMP_FORMAT_* + */ +#if 0 +#define _DBG_DUMP_MEMORY_FORMAT(LEVEL,STRING,ADDR,LENGTH,DUMPFORMAT) + _ICS_DBG_OUT(LEVEL, ("%s:\n%F", _DBG_PTR(STRING), Log_MemoryDumpFormat(ADDR, LENGTH,DUMPFORMAT))) +#endif + +#define _DBG_BREAK \ + if (__DBG_BRK_LEVEL__) \ + { \ + LOG_DUMP (__MOD_ID__, "=>Breakpoint at %s() in %s(%d)\n",_DBG_PTR(__FUNCTION__),_DBG_PTR(__FILE__),(uintn)__LINE__,0,0,0); \ + Osa_BreakPoint(); \ + } + +#define _DBG_INIT (void)0 + +#if defined(DBG) || defined(IB_DEBUG) +#define _ICS_DBG2_ENTER_FUNC(FORMAT, ARGS...) \ + _ICS_DBG3_CALL(DEBUG5, "%s(" FORMAT ") [\n", \ + _DBG_PTR(__FUNCTION__), ## ARGS,0,0,0,0,0,0,0) + +#define _ICS_DBG_ENTER_FUNC(STRING) _ICS_DBG2_ENTER_FUNC STRING +/* + * FOR DEBUG BUILDS + * Include One of these functions at the start of your function code + * This must follow the variable declarations but preceed any + * functional code in the function + */ +#define _DBG_ENTER_LVL(LEVEL,NAME) \ + _DBG_DEFINE_FUNC(NAME) \ + (void)__FUNC__; \ + _DBG_PRINT (LEVEL, ( "%s() [\n" , _DBG_PTR(__FUNCTION__) )); + +#define _DBG_ENTER_LVL_ARGS(LEVEL,NAME,STRING) \ + _DBG_DEFINE_FUNC(NAME) \ + (void)__FUNC__; \ + _ICS_DBG_ENTER_FUNC(STRING) + +#define _DBG_ENTER_FUNC(NAME) \ + _DBG_DEFINE_FUNC(NAME) \ + (void)__FUNC__; \ + _DBG_PRINT (_DBG_LVL_FUNC_TRACE, ("%s() [\n",_DBG_PTR(__FUNCTION__))); + +#define _DBG_ENTER_FUNC_ARGS(NAME, STRING) \ + _DBG_DEFINE_FUNC(NAME) \ + (void)__FUNC__; \ + _ICS_DBG_ENTER_FUNC(STRING) + +#define _DBG_ENTER_EXT(LEVEL,NAME,IRQL) \ + _DBG_DEFINE_FUNC(NAME) \ + (void)__FUNC__; \ + do { \ + _DBG_PRINT(LEVEL, ("%s() [\n",_DBG_PTR(__FUNCTION__))); \ + _DBG_CHK_IRQL(IRQL); \ + } while (0) + +#define _DBG_ENTER_EXT_ARGS(LEVEL,NAME,IRQL,STRING) \ + _DBG_DEFINE_FUNC(NAME) \ + (void)__FUNC__; \ + do { \ + _ICS_DBG_ENTER_FUNC(STRING); \ + _DBG_CHK_IRQL(IRQL); \ + } while (0) +#else +#define _ICS_DBG_ENTER_FUNC(STRING) (void)0 +/* + * FOR RELEASE BUILDS + * Include One of these functions at the start of your function code + * This must follow the variable declarations but preceed any + * functional code in the function + */ +#define _DBG_ENTER_LVL(LEVEL,NAME) \ + _DBG_PRINT (LEVEL, ( "%s() [\n" , _DBG_PTR(__FUNCTION__) )); + +#define _DBG_ENTER_LVL_ARGS(LEVEL,NAME,STRING) \ + _ICS_DBG_ENTER_FUNC(STRING) + +#define _DBG_ENTER_FUNC(NAME) \ + _DBG_PRINT (_DBG_LVL_FUNC_TRACE, ("%s() [\n",_DBG_PTR(__FUNCTION__))); + +#define _DBG_ENTER_FUNC_ARGS(NAME, STRING) \ + _ICS_DBG_ENTER_FUNC(STRING) + +#define _DBG_ENTER_EXT(LEVEL,NAME,IRQL) \ + do { \ + _DBG_PRINT(LEVEL, ("%s() [\n",_DBG_PTR(__FUNCTION__))); \ + _DBG_CHK_IRQL(IRQL); \ + } while (0) + +#define _DBG_ENTER_EXT_ARGS(LEVEL,NAME,IRQL,STRING) \ + do { \ + _ICS_DBG_ENTER_FUNC(STRING); \ + _DBG_CHK_IRQL(IRQL); \ + } while (0) +#endif /* release */ + + +/* + * Include one of these functions at the exit of your function + */ +#define _DBG_LEAVE_FUNC() \ + _DBG_PRINT (_DBG_LVL_FUNC_TRACE, ("%s() ]\n",_DBG_PTR(__FUNCTION__))); + +#define _DBG_RETURN_FUNC(VALUE) \ + _DBG_PRINT (_DBG_LVL_FUNC_TRACE, ("%s() returning 0x%x ]\n",_DBG_PTR(__FUNCTION__), VALUE)) + +#define _DBG_FSTATUS_RETURN_FUNC(STATUS) \ + _DBG_PRINT (_DBG_LVL_FUNC_TRACE, ("%s() returning %s (0x%x) ]\n",_DBG_PTR(__FUNCTION__), _DBG_PTR(iba_fstatus_msg(STATUS)), STATUS)) + +#define _DBG_LEAVE_LVL(LEVEL) \ + _DBG_PRINT (LEVEL, ("%s() ]\n",_DBG_PTR(__FUNCTION__))); + +#define _DBG_RETURN_LVL(LEVEL, VALUE) \ + _DBG_PRINT (LEVEL, ("%s() returning 0x%x ]\n",_DBG_PTR(__FUNCTION__), VALUE)) + +#define _DBG_FSTATUS_RETURN_LVL(LEVEL, STATUS) \ + _DBG_PRINT (LEVEL, ("%s() returning %s (0x%x) ]\n",_DBG_PTR(__FUNCTION__), _DBG_PTR(iba_fstatus_msg(STATUS)), STATUS)) + +#define _DBG_LEAVE_EXT _DBG_LEAVE_LVL +#define _DBG_RETURN_EXT _DBG_RETURN_LVL +#define _DBG_FSTATUS_RETURN_EXT _DBG_FSTATUS_RETURN_LVL + +#define _DBG_INFO(STRING) _DBG_PRINT (_DBG_LVL_INFO, STRING); + +#define _DBG_WARN(STRING) _ICS_DBG_OUT(_DBG_LVL_WARN,STRING) + +#define _DBG_OUT _DBG_INFO + +#define _DBG_ERROR(STRING) _ICS_DBG_OUT(_DBG_LVL_ERROR,STRING) + +#define _DBG_FATAL(STRING) \ + do { \ + _ICS_DBG_OUT(_DBG_LVL_FATAL,STRING) \ + _DBG_BREAK \ + } while(0) + +#define _DBG_MEM(STRING) _ICS_DBG_OUT(_DBG_LVL_MEM_TRACK,STRING) + +#define _DBG_STRDUP Log_StrDup + +#else /* ICS_LOGGING */ + +#define _DBG2_CALL(fmt, args...) \ + IbLogPrintf(_local_dbg_level, fmt, ## args); \ + +/* grab () off string and use to form macro call, so we can add to args */ +#define _DBG1_CALL(LEVEL, STRING) \ + do { \ + /* local is for _DBG2_CALL to use */ \ + /* compiler will not actually allocate stack space */ \ + uint32 _local_dbg_level = LEVEL; \ + _DBG2_CALL STRING \ + } while (0) + +#if defined(DBG) || defined( IB_DEBUG) +/* ============================================================================= + * In these function-like macros, we enclose the multi-line expansion with + * do {} while(0) This causes the macro to behave as a single statement + * and avoid surprises if the macro is used without {} in an if + * such as: + * if (x) + * _DBG_PRINT(("x is true\n")); + */ + +#define _DBG_PRINT(LEVEL,STRING) \ + do { \ + _DBG_PRINT_PROLOG(LEVEL,STRING) \ + if (__DBG_LEVEL__ & LEVEL) \ + { \ + _DBG1_CALL(LEVEL, (__MOD_NAME__)); \ + _DBG1_CALL(LEVEL, STRING); \ + } \ + _DBG_PRINT_EPILOG(LEVEL,STRING) \ + } while (0) + +#define _DBG_DUMP_MEMORY(LEVEL,STRING,ADDR,LENGTH) \ + do { \ + _DBG_PRINT_PROLOG(LEVEL,STRING) \ + if (__DBG_LEVEL__ & LEVEL) \ + { \ + _DBG1_CALL(LEVEL, (__MOD_NAME__)); \ + _DBG1_CALL(LEVEL, STRING); \ + DbgDump (LEVEL, ADDR, LENGTH,_DBG_DUMP_FORMAT_BYTES);\ + } \ + _DBG_PRINT_EPILOG(LEVEL,STRING) \ + } while (0) + +#define _DBG_DUMP_MEMORY_FORMAT(LEVEL,STRING,ADDR,LENGTH,DUMPFORMAT) \ + do { \ + _DBG_PRINT_PROLOG(LEVEL,STRING) \ + if (__DBG_LEVEL__ & LEVEL) \ + { \ + _DBG1_CALL(LEVEL, (__MOD_NAME__)); \ + _DBG1_CALL(LEVEL, STRING); \ + DbgDump (LEVEL, ADDR, LENGTH, DUMPFORMAT);\ + } \ + _DBG_PRINT_EPILOG(LEVEL,STRING) \ + } while (0) + +#define _DBG_BREAK \ + do { \ + if (__DBG_BRK_LEVEL__) \ + { \ + DbgOut ("=>Breakpoint at %s() in %s(%d)\n", \ + _DBG_PTR(__FUNC__),_DBG_PTR(__FILE__),__LINE__); \ + DbgBreakPoint(); \ + } \ + } while (0) + +/* + * This may be referenced at the start of your code like DriverEntry, main, etc. + * to locate the debug param block. + * + * Do not change the string. It will be used in debugger extensions. + */ +#define _DBG_INIT \ + do { \ + DbgOut ("[IbDebug] module %s at 0x%p\n", \ + _DBG_PTR(__MOD_NAME__), _DBG_PTR(&__DBG_LEVEL__)); \ + } while (0) + + + +/* + * Include One of these functions at the start of your function code + * This must follow the variable declarations but preceed any + * functional code in the function + */ + +#define _DBG_ENTER_LVL(LEVEL,NAME) \ + _DBG_DEFINE_FUNC(NAME); \ + _DBG_PRINT (LEVEL, ("%s() [\n",_DBG_PTR(__FUNC__))) + +#define _DBG_ENTER_LVL_ARGS(LEVEL,NAME,STRING) \ + _DBG_DEFINE_FUNC(NAME); \ + do { \ + _DBG_PRINT_PROLOG(LEVEL, ("%s() [\n", _DBG_PTR(__FUNC__))) \ + if (__DBG_LEVEL__ & LEVEL) \ + { \ + _DBG1_CALL(LEVEL, (__MOD_NAME__)); \ + _DBG1_CALL(LEVEL, ("%s(" ,_DBG_PTR(__FUNC__)) ); \ + _DBG1_CALL(LEVEL, STRING); \ + _DBG1_CALL(LEVEL, (") [\n")); \ + } \ + _DBG_PRINT_EPILOG(LEVEL,("%s() [\n", _DBG_PTR(__FUNC__))) \ + } while (0) + +#define _DBG_ENTER_FUNC(NAME) \ + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE,NAME) + +#define _DBG_ENTER_FUNC_ARGS(NAME, STRING) \ + _DBG_ENTER_LVL_ARGS(_DBG_LVL_FUNC_TRACE,NAME,STRING) + +#define _DBG_ENTER_EXT(LEVEL,NAME,IRQL) \ + _DBG_DEFINE_FUNC(NAME); \ + do { \ + _DBG_PRINT(LEVEL, ("%s() [\n",_DBG_PTR(__FUNC__))); \ + _DBG_CHK_IRQL(IRQL); \ + } while (0) + +#define _DBG_ENTER_EXT_ARGS(LEVEL,NAME,IRQL,STRING) \ + _DBG_DEFINE_FUNC(NAME); \ + do { \ + _DBG_PRINT_PROLOG(LEVEL, ("%s() [\n", _DBG_PTR(__FUNC__))) \ + if (__DBG_LEVEL__ & LEVEL) \ + { \ + _DBG1_CALL(LEVEL, (__MOD_NAME__)); \ + _DBG1_CALL(LEVEL, ("%s(" ,_DBG_PTR(__FUNC__)) ); \ + _DBG1_CALL(LEVEL, STRING); \ + _DBG1_CALL(LEVEL, (") [\n")); \ + } \ + _DBG_PRINT_EPILOG(LEVEL,("%s() [\n", _DBG_PTR(__FUNC__))) \ + _DBG_CHK_IRQL(IRQL); \ + } while (0) + +/* + * Include one of these functions at the exit of your function + */ +#define _DBG_LEAVE_FUNC() \ + _DBG_PRINT (_DBG_LVL_FUNC_TRACE, ("%s() ]\n",_DBG_PTR(__FUNC__))) + +#define _DBG_RETURN_FUNC(VALUE) \ + _DBG_PRINT (_DBG_LVL_FUNC_TRACE, ("%s() returning 0x%x ]\n",_DBG_PTR(__FUNC__), VALUE)) + +#define _DBG_FSTATUS_RETURN_FUNC(STATUS) \ + _DBG_PRINT (_DBG_LVL_FUNC_TRACE, ("%s() returning %s (0x%x) ]\n",_DBG_PTR(__FUNC__), _DBG_PTR(iba_fstatus_msg(STATUS)), STATUS)) + +#define _DBG_LEAVE_LVL(LEVEL) \ + _DBG_PRINT (LEVEL, ("%s() ]\n",_DBG_PTR(__FUNC__))) + +#define _DBG_RETURN_LVL(LEVEL, VALUE) \ + _DBG_PRINT (LEVEL, ("%s() returning 0x%x ]\n",_DBG_PTR(__FUNC__), VALUE)) + +#define _DBG_FSTATUS_RETURN_LVL(LEVEL, STATUS) \ + _DBG_PRINT (LEVEL, ("%s() returning %s (0x%x) ]\n",_DBG_PTR(__FUNC__), _DBG_PTR(iba_fstatus_msg(STATUS)), STATUS)) + +#define _DBG_LEAVE_EXT _DBG_LEAVE_LVL +#define _DBG_RETURN_EXT _DBG_RETURN_LVL +#define _DBG_FSTATUS_RETURN_EXT _DBG_FSTATUS_RETURN_LVL + + +#define _DBG_INFO(STRING) \ + _DBG_PRINT (_DBG_LVL_INFO, STRING) + +#define _DBG_WARN(STRING) \ + do { \ + _DBG_PRINT_PROLOG(_DBG_LVL_WARN,STRING) \ + if (__DBG_LEVEL__ & _DBG_LVL_WARN) \ + { \ + _DBG1_CALL(_DBG_LVL_WARN, ("%s%s() !WARNING! ", \ + _DBG_PTR(__MOD_NAME__),_DBG_PTR(__FUNC__))); \ + _DBG1_CALL(_DBG_LVL_WARN, STRING); \ + } \ + _DBG_PRINT_EPILOG(_DBG_LVL_WARN,STRING) \ + } while (0) + +#define _DBG_OUT _DBG_INFO + +#define _DBG_ERROR(STRING) \ + do { \ + _DBG_ERROR_PROLOG(_DBG_LVL_ERROR,STRING) \ + if (__DBG_LEVEL__ & _DBG_LVL_ERROR) \ + { \ + _DBG1_CALL(_DBG_LVL_ERROR, ("%s%s() !ERROR! ", \ + _DBG_PTR(__MOD_NAME__),_DBG_PTR(__FUNC__))); \ + _DBG1_CALL(_DBG_LVL_ERROR, STRING); \ + } \ + _DBG_ERROR_EPILOG(_DBG_LVL_ERROR,STRING) \ + } while (0) + +#define _DBG_FATAL(STRING) \ + do { \ + _DBG_FATAL_PROLOG(_DBG_LVL_FATAL,STRING) \ + if (__DBG_LEVEL__ & _DBG_LVL_FATAL) \ + { \ + _DBG1_CALL(_DBG_LVL_FATAL, ("%s%s() !!!FATAL ERROR!!! ",\ + _DBG_PTR(__MOD_NAME__),_DBG_PTR(__FUNC__))); \ + _DBG1_CALL(_DBG_LVL_FATAL, STRING); \ + _DBG_BREAK \ + } \ + _DBG_FATAL_EPILOG(_DBG_LVL_FATAL,STRING) \ + } while(0) + +#define _DBG_MEM(STRING) \ + do { \ + if (__DBG_LEVEL__ & _DBG_LVL_MEM_TRACK) \ + { \ + _DBG1_CALL(_DBG_LVL_MEM_TRACK, ("%s%s()[mem] ", \ + _DBG_PTR(__MOD_NAME__),_DBG_PTR(__FUNC__)));\ + _DBG1_CALL(_DBG_LVL_MEM_TRACK, STRING); \ + } \ + } while(0) + +#else /* DBG || IB_DEBUG */ + +/* ============================================================================= + * release builds include this + */ + +#define _DBG_PRINT(LEVEL,STRING) \ + do { \ + if (LEVEL) { \ + _DBG_PRINT_PROLOG(LEVEL,STRING) \ + if (__DBG_LEVEL__ & LEVEL & _DBG_LVL_MASK) \ + { \ + _DBG1_CALL(LEVEL, (__MOD_NAME__)); \ + _DBG1_CALL(LEVEL, STRING); \ + } \ + _DBG_PRINT_EPILOG(LEVEL,STRING) \ + } \ + } while (0) + +#define _DBG_DUMP_MEMORY(LEVEL,STRING,ADDR,LENGTH) \ + do { \ + if (LEVEL & _DBG_LVL_MASK) { \ + _DBG_PRINT_PROLOG(LEVEL,STRING) \ + if (__DBG_LEVEL__ & LEVEL) \ + { \ + _DBG1_CALL(LEVEL, (__MOD_NAME__)); \ + _DBG1_CALL(LEVEL, STRING); \ + DbgDump (LEVEL, ADDR, LENGTH,_DBG_DUMP_FORMAT_BYTES);\ + } \ + _DBG_PRINT_EPILOG(LEVEL,STRING) \ + } \ + } while (0) + +#define _DBG_DUMP_MEMORY_FORMAT(LEVEL,STRING,ADDR,LENGTH,DUMPFORMAT) \ + do { \ + if (LEVEL & _DBG_LVL_MASK) { \ + _DBG_PRINT_PROLOG(LEVEL,STRING) \ + _DBG_PRINT_PROLOG(LEVEL,STRING) \ + if (__DBG_LEVEL__ & LEVEL) \ + { \ + _DBG1_CALL(LEVEL, (__MOD_NAME__)); \ + _DBG1_CALL(LEVEL, STRING); \ + DbgDump (LEVEL, ADDR, LENGTH, DUMPFORMAT);\ + } \ + _DBG_PRINT_EPILOG(LEVEL,STRING) \ + } \ + } while (0) +#define _DBG_INIT (void)0 +#define _DBG_BREAK (void)0 +#define _DBG_ENTER_FUNC(NAME) (void)0 +#define _DBG_ENTER_FUNC_ARGS(NAME, STRING) (void)0 +#define _DBG_ENTER_EXT(LEVEL,NAME,IRQL) (void)0 +#define _DBG_ENTER_EXT_ARGS(LEVEL,NAME,IRQL,STRING) (void)0 +#define _DBG_ENTER_LVL(LEVEL,NAME) (void)0 +#define _DBG_ENTER_LVL_ARGS(LEVEL,NAME,STRING) (void)0 +#define _DBG_LEAVE_FUNC() (void)0 +#define _DBG_RETURN_FUNC(VALUE) (void)0 +#define _DBG_FSTATUS_RETURN_FUNC(STATUS) (void)0 +#define _DBG_LEAVE_LVL(LEVEL) (void)0 +#define _DBG_RETURN_LVL(LEVEL, VALUE) (void)0 +#define _DBG_FSTATUS_RETURN_LVL(LEVEL, STATUS) (void)0 +#define _DBG_LEAVE_EXT(LEVEL) (void)0 +#define _DBG_RETURN_EXT(LEVEL, VALUE) (void)0 +#define _DBG_FSTATUS_RETURN_EXT(LEVEL, STATUS) (void)0 + +#define _DBG_INFO(STRING) \ + _DBG_PRINT (_DBG_LVL_INFO, STRING) + +#define _DBG_WARN(STRING) \ + do { \ + _DBG_PRINT_PROLOG(_DBG_LVL_WARN,STRING) \ + if (__DBG_LEVEL__ & _DBG_LVL_WARN) \ + { \ + _DBG1_CALL(_DBG_LVL_WARN, ("%s !WARNING! ", \ + _DBG_PTR(__MOD_NAME__))); \ + _DBG1_CALL(_DBG_LVL_WARN, STRING); \ + } \ + _DBG_PRINT_EPILOG(_DBG_LVL_WARN,STRING) \ + } while (0) + +#define _DBG_ERROR(STRING) \ + do { \ + _DBG_ERROR_PROLOG(_DBG_LVL_ERROR,STRING) \ + if (__DBG_LEVEL__ & _DBG_LVL_ERROR) \ + { \ + _DBG1_CALL(_DBG_LVL_ERROR, ("%s !ERROR! ", \ + _DBG_PTR(__MOD_NAME__))); \ + _DBG1_CALL(_DBG_LVL_ERROR, STRING); \ + } \ + _DBG_ERROR_EPILOG(_DBG_LVL_ERROR,STRING) \ + } while (0) + +#define _DBG_FATAL(STRING) \ + do { \ + _DBG_FATAL_PROLOG(_DBG_LVL_FATAL,STRING) \ + if (__DBG_LEVEL__ & _DBG_LVL_FATAL) \ + { \ + _DBG1_CALL(_DBG_LVL_FATAL, ("%s !!!FATAL ERROR!!! ", \ + _DBG_PTR(__MOD_NAME__))); \ + _DBG1_CALL(_DBG_LVL_FATAL, STRING); \ + } \ + _DBG_FATAL_EPILOG(_DBG_LVL_FATAL,STRING) \ + } while(0) + +#define _DBG_MEM(STRING) (void)0 + +#endif /* DBG || IB_DEBUG */ + +#endif /* ICS_LOGGING */ + +#define _DBG_WARNING(STRING) _DBG_WARN(STRING) + +/* ------------------------------------------------------------------------- + * Tracing macros + */ +#ifdef IB_TRACE + +#ifdef ICS_LOGGING +#define _TRC_DBG_CALL(STRING) \ + _ICS_DBG2_DEBUG5 STRING +#define _TRC_REGISTER() (void)0 +#define _TRC_UNREGISTER() (void)0 + +#else /* ICS_LOGGING */ + +/* for simplicity for now + * trace calls from user space simply go to standard log (which could be stdout) + */ +#define _TRC_DBG_CALL(STRING) \ + do { \ + DbgOut("%s: ", __MOD_NAME__); \ + DbgOut STRING; \ + } while (0) +#define _TRC_REGISTER() (void)0 +#define _TRC_UNREGISTER() (void)0 + +#endif /* ICS_LOGGING */ + +#define _TRC_PRINT(LEVEL,STRING) \ + do { \ + if (LEVEL) { \ + if (__DBG_TRACE_LEVEL__ & LEVEL & _TRC_LVL_MASK) \ + { \ + _TRC_DBG_CALL(STRING); \ + } \ + } \ + } while (0) + +#else /* IB_TRACE */ +#define _TRC_REGISTER() (void)0 +#define _TRC_UNREGISTER() (void)0 +#define _TRC_PRINT(LEVEL,STRING) (void)0 +#endif /* IB_TRACE */ + +#endif /* _IBA_IB_DEBUG_H_ */ diff --git a/IbAccess/Common/Inc/ib_dm.h b/IbAccess/Common/Inc/ib_dm.h new file mode 100644 index 0000000..72f5984 --- /dev/null +++ b/IbAccess/Common/Inc/ib_dm.h @@ -0,0 +1,381 @@ +/* BEGIN_ICS_COPYRIGHT3 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT3 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +#ifndef _IBA_IB_DM_H_ +#define _IBA_IB_DM_H_ (1) /* suppress duplicate loading of this file */ + +#include "iba/public/datatypes.h" /* Portable datatypes */ +#include "iba/public/ibyteswap.h" +#include "iba/ib_generalServices.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* -------------------------------------------------------------------------- + * IBTA Device Management Class + * -------------------------------------------------------------------------- + */ + +/* Device Management methods */ +#define DEVMGT_GET MMTHD_GET +#define DEVMGT_SET MMTHD_SET +#define DEVMGT_GET_RESP MMTHD_GET_RESP +#define DEVMGT_TRAP MMTHD_TRAP +#define DEVMGT_TRAP_REPRESS MMTHD_TRAP_REPRESS +#define DEVMGT_REPORT MMTHD_REPORT +#define DEVMGT_REPORT_RESP MMTHD_REPORT_RESP + + +/* Device Management Attributes IDs */ /* Attribute Modifier values */ +#define DM_ATTRIB_ID_CLASS_PORTINFO 0x0001 /* 0x0000_0000 */ +#define DM_ATTRIB_ID_NOTICE 0x0002 /* 0x0000_0000 - 0xFFFF_FFFF */ +#define DM_ATTRIB_ID_IOUNIT_INFO 0x0010 /* 0x0000_0000 */ +#define DM_ATTRIB_ID_IOCONTROLLER_PROFILE 0x0011/* 0x0000_0001 - 0x0000_00FF */ + /* (IOC slot#) */ +#define DM_ATTRIB_ID_SERVICE_ENTRIES 0x0012 /* 0x0001_0000 - 0x00FF_FFFF */ +#define DM_ATTRIB_ID_DIAGNOSTIC_TIMEOUT 0x0020 /* 0x0000_0001 - 0xFFFF_FFFF */ + /* (time unit in millisec) */ +#define DM_ATTRIB_ID_PREPARE_TO_TEST 0x0021 /* 0x0000_0001 - 0xFFFF_FFFF */ +#define DM_ATTRIB_ID_TEST_DEVICE_ONCE 0x0022 /* 0x0000_0001 - 0xFFFF_FFFF */ +#define DM_ATTRIB_ID_TEST_DEVICE_LOOP 0x0023 /* 0x0000_0001 - 0xFFFF_FFFF */ +#define DM_ATTRIB_ID_DIAG_CODE 0x0024 /* 0x0000_0001 - 0xFFFF_FFFF */ +/* Reserved 0x0025 - 0xFEFF */ +/* Vendor Specific 0xFF00-0xFFFF */ +#define DM_ATTRIB_ID_VENDOR_MASK 0xff00 /* Vendor Specific Attrib IDs */ + +/* DM Class Specific MAD_STATUS (AsReg16) */ +#define MAD_STATUS_DM_IOC_NOT_RESPONDING 0x0100 +#define MAD_STATUS_DM_IOC_NO_SERVICE_ENTRIES 0x0200 + /* bits 10-14 reserved */ +#define MAD_STATUS_DM_IOC_GENERAL_FAILURE 0x8000 + +/* A series of 4-bit nibbles with each representing an IOC slot in the IOU. + * Each 4-bit nibble can take the following values. 0x2-0xE are reserved. + */ +#define IOC_NOT_INSTALLED 0x0 +#define IOC_INSTALLED 0x1 +/* reserved values for 0x02-0xE */ +#define SLOT_NOT_EXISTED 0xF + +/* The ControllerList nibble lists defined in IBA DM spec + * The high nibble has lower controller slot # + * + * (start of 1024bits) 0xXX XX XX XX XX ... + * slot # 01 23 45 67 89 ... + */ + +#define SLOT_INFO(clVal,slot) (((slot)-1)%2 ? ((clVal) & 0x0F) : \ + (((clVal) & 0xF0) >> 4)) +/* This macro gives the nibble of the specified IOC # */ +#define IOC_AT_SLOT(pIOUnitInfo,slot) \ + SLOT_INFO( (pIOUnitInfo)->ControllerList[((slot)-1)/2], slot) + +#define IOC_AT_SLOT_IS_PRESENT(pIOUnitInfo, slot) \ + (IOC_AT_SLOT(pIOUnitInfo, slot) == IOC_INSTALLED) + + +#define SET_IOC_AT_SLOT(pIOUnitInfo, slot, value) \ + ((pIOUnitInfo)->ControllerList[((slot)-1)/2] = (((slot)-1)%2 ? \ + (((pIOUnitInfo)->ControllerList[((slot)-1)/2] & 0xF0) \ + | ((value) & 0xF)) \ + : (((pIOUnitInfo)->ControllerList[((slot)-1)/2] & 0x0F) \ + | ((value) << 4)))) + + +/* -------------------------------------------------------------------------- + * DM Attribute Specific Data + * Declared in wire format + */ +#include "iba/public/ipackon.h" + +/* There is one IOUnitInfo per CA */ +typedef struct __IOUnitInfo { + uint16 Change_ID; /* monotonically incremented with rollover */ + /* by any change to ControllerList */ + uint8 MaxControllers; /* # of slots in Controller List */ + +#if CPU_BE + uint8 Resv :6; + uint8 DiagDeviceId:1; /* attr modifier in diag attrs is IOC Slot */ + uint8 OptionRom :1; /* 1 = present, 0 = absent */ + +#else /* CPU_LE */ + uint8 OptionRom :1; /* 1 = present, 0 = absent */ + uint8 DiagDeviceId:1; /* attr modifier in diag attrs is IOC Slot */ + uint8 Resv :6; +#endif + + uint8 ControllerList[128]; +} PACK_SUFFIX IOUnitInfo, *PIOUnitInfo; + + +/* There can be up to 255 IOCs per IOU. IOCs are identified by a 1 based + * slot number (1-255) + */ +#define DM_MAX_CONTROLLERS 255 +#define IOC_IDSTRING_SIZE 64 +typedef struct __IO_CONTROLLER_PROFILE { + uint64 IocGUID; /* USE EUI-64 GUID */ + + union { + uint32 AsUint32; + struct { + +#if CPU_BE + uint32 VendorId :24;/* IO Controller vendor, IEEE */ + uint32 Resv1 :8; +#else /* CPU_LE */ + uint32 Resv1 :8; + uint32 VendorId :24;/* IO Controller vendor, IEEE */ +#endif + + } v; + } ven; + +#define IocProfile_VendorId ven.v.VendorId + + uint32 DeviceId; /* a number assigned by the vendor */ + /* It can be used by an OS to select */ + /* a device driver. */ + uint16 DeviceVersion; /* device version assigned by vendor */ + uint16 Resv2; + + union { + uint32 AsUint32; + struct { + +#if CPU_BE + uint32 SubSystemVendorID :24;/* ID of the enclosure vendor, per IEEE */ + uint32 Resv :8; +#else /*CPU_LE */ + uint32 Resv :8; + uint32 SubSystemVendorID :24;/* ID of the enclosure vendor, per IEEE */ +#endif + + } s; + } sub; + +#define IocProfile_SubSystemVendorID sub.s.SubSystemVendorID + + uint32 SubSystemID; /* A number identifying the subsystem */ + /* where the controller resides */ + + uint16 IOClass; /* 0x0000-0xFFFE = Reserved pending */ + /* I/O class specification approval */ + /* 0xFFFF = vendor specific */ + + uint16 IOSubClass; /* 0x0000-0xFFFE = Reserved pending */ + /* I/O subclass specification approval */ + /* 0xFFFF = vendor specific */ + /* Must be 0xFFFF if IOClass = 0xFFFF */ + + uint16 Protocol; /* 0x0000-0xFFFE = Reserved pending */ + /* I/O subclass specification approval */ + /* 0xFFFF = vendor specific */ + /* Must be 0xFFFF if IOClass = 0xFFFF */ + + uint16 ProtocolVer; /* Protocol specific */ + + uint16 Resv5; + uint16 Resv6; + + uint16 SendMsgDepth; /* Max depth of the send message */ + /* queue */ + + uint8 Resv7; /* RDMAReadDepth was 16 bits in 1.0a */ + uint8 RDMAReadDepth; /* Max depth of the per-channel RDMA */ + /* read queue */ + + uint32 SendMsgSize; /* Max size of send messages in bytes */ + + uint32 RDMASize; /* Max size of outbound RDMA transfers */ + /* initiated by this IOC (in bytes) */ + + union { + uint8 CntlCapMask; + struct { + +#if CPU_BE + uint8 AF :1; /*bit 7:Atomic Operations from IOCs */ + uint8 AT :1; /* Atomic Operations to IOCs */ + uint8 WF :1; /* RDMA Write Requests from IOCs */ + uint8 WT :1; /* RDMA Write Requests to IOCs */ + uint8 RF :1; /* RDMA Read Requests from IOCs */ + uint8 RT :1; /* RDMA Read Requests to IOCs */ + uint8 SF :1; /* Send Messages from IOCs */ + uint8 ST :1; /*bit 0:Send Messages to IOCs */ + +#else /* CPU_LE */ + uint8 ST :1; /*bit 0:Send Messages to IOCs */ + uint8 SF :1; /* Send Messages from IOCs */ + uint8 RT :1; /* RDMA Read Requests to IOCs */ + uint8 RF :1; /* RDMA Read Requests from IOCs */ + uint8 WT :1; /* RDMA Write Requests to IOCs */ + uint8 WF :1; /* RDMA Write Requests from IOCs */ + uint8 AT :1; /* Atomic Operations to IOCs */ + uint8 AF :1; /*bit 7:Atomic Operations from IOCs */ +#endif + + } ctlrCapMask; + } ccm; + + uint8 Resv8; + uint8 ServiceEntries; /* Number of entries in the ServiceEntries table */ + uint8 Resv4[9]; + uint8 IDString[IOC_IDSTRING_SIZE];/* ASCII text string for identifying the */ + /* controller to operator */ +} PACK_SUFFIX IOC_PROFILE, *PIOC_PROFILE; + + +/* there can be up to 255 service entries per IOC. + * Services are identified by a 0 based service number 0-254 + * Note the IBTA spec is not clear if the 1st service is 0 or 1. At present + * all devices from SilverStorm, Mellanox and Engenio use 0 as the 1st service + */ + +/* create attribute modifier for DM_ATTRIB_ID_SERVICE_ENTRIES to select + * a range of service entries within an IOC (1 based IOC slot number) + */ +#define DM_ATTRIB_MODIFIER_SERVICE_ENTRIES(slot,first,last) \ + (((slot) << 16) | (first) | ((last) << 8)) + +/* extract parts of attribute modifier for a SERVICE_ENTRIES Attribute */ +#define DM_ATTRIB_MODIFIER_SERVICE_ENTRIES_SLOT(modifier) \ + (((modifier) >> 16) & 0xff) +#define DM_ATTRIB_MODIFIER_SERVICE_ENTRIES_FIRST(modifier) \ + ((modifier) & 0xff) +#define DM_ATTRIB_MODIFIER_SERVICE_ENTRIES_LAST(modifier) \ + (((modifier) >> 8) & 0xff) + +#define IOC_SERVICE_NAME_SIZE 40 +typedef struct __IOC_SERVICE { + + uchar Name[IOC_SERVICE_NAME_SIZE];/* Service name string in text format */ + uint64 Id; /* An identifier of the associated Service */ + +} PACK_SUFFIX IOC_SERVICE, *PIOC_SERVICE; + +typedef struct __IOC_SERVICE_ENTRIES { + + IOC_SERVICE ServiceEntry[4]; + +} PACK_SUFFIX DM_IOC_SERVICE_ENTRIES, *PDM_IOC_SERVICE_ENTRIES; + + +typedef struct __DIAGNOSTIC_TIMEOUT { + uint32 MaxDiagTime; /* Max time to finish the diagnotic operation */ + /* in milli-seconds */ +} PACK_SUFFIX DIAGNOSTIC_TIMEOUT, *PDIAGNOSTIC_TIMEOUT; + +typedef enum { + DM_DIAG_CODE_OPERATIONAL = 0x0000 + /* others are vendor specific */ +} DM_DIAG_CODE_VALUE; + +typedef struct __DIAG_CODE { + uint16 DiagCode; /* a DM_DIAG_CODE_VALUE */ + /* additional vendor specific data permitted */ +} PACK_SUFFIX DIAG_CODE, *PDIAG_CODE; + +/* End of packed data structures */ +#include "iba/public/ipackoff.h" + + +/* -------------------------------------------------------------------------- */ +/* Byte swap between cpu and network formats */ + +static __inline void +BSWAP_DM_IOUNIT_INFO (PIOUnitInfo pIOUnitInfo) +{ +#if CPU_LE + pIOUnitInfo->Change_ID = ntoh16(pIOUnitInfo->Change_ID); +#endif +} + +static __inline void +BSWAP_DM_IOC_PROFILE (PIOC_PROFILE pIOC_PROFILE) +{ +#if CPU_LE + pIOC_PROFILE->IocGUID = ntoh64(pIOC_PROFILE->IocGUID); + + pIOC_PROFILE->ven.AsUint32 = ntoh32(pIOC_PROFILE->ven.AsUint32); + pIOC_PROFILE->DeviceId = ntoh32(pIOC_PROFILE->DeviceId); + + pIOC_PROFILE->DeviceVersion = ntoh16(pIOC_PROFILE->DeviceVersion); + /* 16-bit Resv 2: should be all 0. */ + pIOC_PROFILE->sub.AsUint32 = ntoh32(pIOC_PROFILE->sub.AsUint32); + + pIOC_PROFILE->SubSystemID = ntoh32(pIOC_PROFILE->SubSystemID); + pIOC_PROFILE->IOClass = ntoh16(pIOC_PROFILE->IOClass); + pIOC_PROFILE->IOSubClass = ntoh16(pIOC_PROFILE->IOSubClass); + + pIOC_PROFILE->Protocol = ntoh16(pIOC_PROFILE->Protocol); + pIOC_PROFILE->ProtocolVer = ntoh16(pIOC_PROFILE->ProtocolVer); + + pIOC_PROFILE->SendMsgDepth = ntoh16(pIOC_PROFILE->SendMsgDepth); + pIOC_PROFILE->RDMAReadDepth = ntoh16(pIOC_PROFILE->RDMAReadDepth); + pIOC_PROFILE->SendMsgSize = ntoh32(pIOC_PROFILE->SendMsgSize); + + pIOC_PROFILE->RDMASize = ntoh32(pIOC_PROFILE->RDMASize); +#endif +} + +static __inline void +BSWAP_DM_IOC_SERVICE (PIOC_SERVICE pIOC_SERVICE) +{ +#if CPU_LE + pIOC_SERVICE->Id = ntoh64(pIOC_SERVICE->Id); +#endif +} + +static __inline void +BSWAP_DM_DIAGNOSTIC_TIMEOUT (PDIAGNOSTIC_TIMEOUT pDIAGNOSTIC_TIMEOUT) +{ +#if CPU_LE + pDIAGNOSTIC_TIMEOUT->MaxDiagTime = + ntoh32(pDIAGNOSTIC_TIMEOUT->MaxDiagTime); +#endif +} + +static __inline void +BSWAP_DM_DIAG_CODE (PDIAG_CODE pDIAG_CODE) +{ +#if CPU_LE + pDIAG_CODE->DiagCode = ntoh16(pDIAG_CODE->DiagCode); +#endif +} + +#ifdef __cplusplus +} +#endif + +#endif /* _IBA_IB_DM_H_ */ diff --git a/IbAccess/Common/Inc/ib_generalServices.h b/IbAccess/Common/Inc/ib_generalServices.h new file mode 100644 index 0000000..db39802 --- /dev/null +++ b/IbAccess/Common/Inc/ib_generalServices.h @@ -0,0 +1,387 @@ +/* BEGIN_ICS_COPYRIGHT3 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT3 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +#ifndef __IBA_IB_GENERAL_SERVICES_H__ +#define __IBA_IB_GENERAL_SERVICES_H__ (1) /* suppress duplicate loading of this file */ + +#include "iba/stl_mad_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* -------------------------------------------------------------------------- + * This header defines Class specific MAD packet formats for + * the IB General Services which are defined in IBTA 1.0a and 1.1 + * in Chapter 16 "General Services" + * For each class, there is an additional header file which documents + * specific attribute formats and Status codes specific to the class + * For example: + * ib_sa_records.h - subnet administration + */ + +/* these are valid in 1.0a and 1.1 + * however for 1.1, classes using RMPP have a smaller HDRSIZE and more DATA + */ +#define IBA_GS_HDRSIZE 64 /* common + class specific header */ +#define IBA_GS_DATASIZE (IB_MAD_BLOCK_SIZE - IBA_GS_HDRSIZE) /* what's left for class payload */ + +#define STL_GS_HDRSIZE 24 /* common header */ +#define STL_IBA_GS_DATASIZE (STL_MAD_BLOCK_SIZE - IBA_GS_HDRSIZE) +#define STL_GS_DATASIZE (STL_MAD_BLOCK_SIZE - STL_GS_HDRSIZE) + /* can include SAR header */ + +/* IBA_RMPP_GS* is computed below, these are here as a reminder for users */ +/*#define IBA_RMPP_GS_DATASIZE 220*//* what's left for class payload */ +/*#define IBA_RMPP_GS_HDRSIZE 36 *//* common + RMPP header */ +#define IBA_SUBN_ADM_HDRSIZE 56 /* common + class specific header */ +#define IBA_SUBN_ADM_DATASIZE (IB_MAD_BLOCK_SIZE - IBA_SUBN_ADM_HDRSIZE) /* what's left for class payload */ + +#define IB_SUBN_ADM_DATASIZE (IB_MAD_BLOCK_SIZE - (sizeof(MAD_COMMON) + sizeof(RMPP_HEADER) + sizeof(SA_HDR))) +#define STL_SUBN_ADM_DATASIZE (STL_MAD_BLOCK_SIZE - (sizeof(MAD_COMMON) + sizeof(RMPP_HEADER) + sizeof(SA_HDR))) + +#define STL_IBA_SUBN_ADM_DATASIZE STL_SUBN_ADM_DATASIZE + + + /* includes RMPP */ +/* -------------------------------------------------------------------------- */ +/* versions for class managers */ +#define IB_SUBN_ADM_CLASS_VERSION 2 /* Subnet Administration */ +#define IB_PERF_CLASS_VERSION 1 /* Performance Management */ +#define IB_BM_CLASS_VERSION 1 /* Baseboard Management */ +#define IB_DEV_MGT_CLASS_VERSION 1 /* Device Management */ + /* bad news, protocol */ + /* had changes in IBTA1.1 */ + /* but class revision did */ + /* not change */ +#define IB_CC_CLASS_VERSION 2 /* Congestion Control */ +#define IB_SNMP_CLASS_VERSION 1 /* SNMP Tunneling */ +#define IB_VENDOR_SPEC_CLASS_VERSION 1 /* Vendor Specific Management */ +#define IB_APP_SPEC_CLASS_VERSION 1 /* Application Specific */ +#define IB_COMM_MGT_CLASS_VERSION 2 /* Communication Management */ +#define IB_PA_CLASS_VERSION 2 /* Performance Analysis */ + +/* -------------------------------------------------------------------------- */ +/* wire protocol packets and sub-structures */ +#include "iba/public/ipackon.h" + +/*---------------------------------------------------------------- */ +/* RMPP (Reliable Multi-Packet Protocol) data structures */ +#define RMPP_VERSION 1 + +#ifndef RMPP_TYPE_DATA // workaround conflict with FM's ib_sa.h header +typedef enum { + RMPP_TYPE_NONE = 0, /* not an RMPP packet */ + RMPP_TYPE_DATA = 1, /* data from sender to receiver */ + RMPP_TYPE_ACK = 2, /* ack from receiver to sender */ + RMPP_TYPE_STOP = 3, + RMPP_TYPE_ABORT = 4 + /* 5-255 reserved */ +} RMPP_TYPE; +#endif + +#define RMPP_RRESPTIME_NONE 0x1f /* no time value provided */ + +typedef enum { + RMPP_STATUS_NORMAL = 0, /* no errors */ + RMPP_STATUS_RESOURCES_EXHAUSTED = 1, /* sender is out of resources */ + RMPP_STATUS_START_RESERVED = 2, /* 2-117 reserved */ + RMPP_STATUS_END_RESERVED = 117, + RMPP_STATUS_TOTAL_TIME_TOO_LONG = 118, /* total transaction timeout */ + RMPP_STATUS_INCONSISTENT_PAYLOAD_LEN = 119, + RMPP_STATUS_INCONSISTENT_FIRST = 120, + RMPP_STATUS_BAD_RMPP_TYPE = 121, + RMPP_STATUS_NEW_WL_TOO_SMALL = 122, + RMPP_STATUS_SEGMENT_NUMBER_TOO_BIG = 123, + RMPP_STATUS_ILLEGAL_STATUS = 124, + RMPP_STATUS_UNSUPPORTED_VERSION = 125, + RMPP_STATUS_TOO_MANY_RETRIES = 126, + RMPP_STATUS_UNSPECIFIED = 127 + /* 128-191 class specific */ + /* 192-255 vendor specific */ +} RMPP_STATUS; + +typedef union _RMPP_FLAG { + uint8 AsReg8; + struct { +#if CPU_BE + uint8 RRespTime:5; /* similar to ClassPortInfo:RespTimeValue */ + uint8 LastPkt:1; /* for RMPP_TYPE_DATA, is this last */ + uint8 FirstPkt:1; /* for RMPP_TYPE_DATA, is this first */ + uint8 Active:1; /* this is part of an RMPP transmission */ +#else + uint8 Active:1; /* this is part of an RMPP transmission */ + uint8 FirstPkt:1; /* for RMPP_TYPE_DATA, is this first */ + uint8 LastPkt:1; /* for RMPP_TYPE_DATA, is this last */ + uint8 RRespTime:5; /* similar to ClassPortInfo:RespTimeValue */ +#endif + } s; +} PACK_SUFFIX RMPP_FLAG; + +/* Note - the SA data structures defined here are not well aligned + * Also RMPP header is 12 bytes, affecting alignment of all that follows + * may need to re-visit in RISC environment + */ +typedef struct _RMPP_HEADER { + uint8 RmppVersion; /* version of RMPP implemented */ + /* must be 0 if RMPP_FLAG.Active=0 */ + uint8 RmppType; /* type of RMPP packet */ + RMPP_FLAG RmppFlags; + uint8 RmppStatus; + union { + uint32 AsReg32; + uint32 SegmentNum; /* DATA and ACK */ + uint32 Reserved1; /* ABORT and STOP */ + } u1; + union { + uint32 AsReg32; + uint32 PayloadLen; /* first and last DATA */ + uint32 NewWindowLast; /* ACK */ + uint32 Reserved2; /* ABORT, STOP and middle DATA */ + } u2; +} PACK_SUFFIX RMPP_HEADER, *PRMPP_HEADER; + +/* Common RMPP MAD packet */ +#define RMPP_GS_HDRSIZE (sizeof(MAD_COMMON)+sizeof(RMPP_HEADER)) +#define IBA_RMPP_GS_DATASIZE (IB_MAD_BLOCK_SIZE - RMPP_GS_HDRSIZE) +#define STL_RMPP_GS_DATASIZE (STL_MAD_BLOCK_SIZE - RMPP_GS_HDRSIZE) + +typedef struct _MAD_RMPP { + MAD_COMMON common; + RMPP_HEADER RmppHdr; + uint8 Data[STL_RMPP_GS_DATASIZE]; +} PACK_SUFFIX MAD_RMPP; + +/*---------------------------------------------------------------- */ +/* Subnet Administration MAD format - Class Version 2 */ +typedef struct _SA_HDR { + uint64 SmKey; /* SM_KEY */ + uint16 AttributeOffset;/* attribute record size in units of uint64's */ + uint16 Reserved; + uint64 ComponentMask; /* Component mask for query operation */ +} PACK_SUFFIX SA_HDR; + +typedef struct _SA_MAD_HDR { + RMPP_HEADER RmppHdr; /* RMPP header */ + SA_HDR SaHdr; /* SA class specific header */ +} PACK_SUFFIX SA_MAD_HDR; + +typedef struct _IB_SA_MAD { + RMPP_HEADER RmppHdr; /* RMPP header */ + SA_HDR SaHdr; /* SA class specific header */ + uint8 Data[STL_SUBN_ADM_DATASIZE]; +} PACK_SUFFIX IB_SA_MAD; + +typedef struct _SA_MAD { + MAD_COMMON common; /* Generic MAD Header */ + RMPP_HEADER RmppHdr; /* RMPP header */ + SA_HDR SaHdr; /* SA class specific header */ + uint8 Data[STL_SUBN_ADM_DATASIZE]; +} PACK_SUFFIX SA_MAD, *PSA_MAD; + +/* -------------------------------------------------------------------------- */ +/* BaseBoard Management MAD format */ +typedef struct _BM_HDR { + uint64 BKey; /* B_Key */ + uint8 Resv[32]; +} PACK_SUFFIX BM_HDR; + +typedef struct _BM_MAD { + MAD_COMMON common; /* Generic MAD Header */ + + BM_HDR BmHdr; /* class specific header */ + + uint8 BMData[STL_IBA_GS_DATASIZE]; /* Baseboard Management Data */ +} PACK_SUFFIX BM_MAD, *PBM_MAD; + +/* -------------------------------------------------------------------------- */ +/* Device Management MAD format */ +typedef struct _DM_MAD { + MAD_COMMON common; /* Generic MAD Header */ + + uint8 Resv[40]; /* class specific header */ + + uint8 DMData[IBA_GS_DATASIZE]; /* Device Management Data */ +} PACK_SUFFIX DM_MAD, *PDM_MAD; + +/* -------------------------------------------------------------------------- */ +/* CC MAD format (except CongestionLog attribute) */ +typedef struct _CC_HDR { + uint64 CC_Key; /* CC__Key */ + uint8 Resv[32]; +} PACK_SUFFIX CC_HDR; + +typedef struct _CC_MAD { + MAD_COMMON common; /* Generic MAD Header */ + + CC_HDR CCHdr; /* class specific header */ + + uint8 CCData[STL_IBA_GS_DATASIZE]; /* Congestion Control Data */ +} PACK_SUFFIX CC_MAD, *PCC_MAD; + +/* CC CongestionLog MAD format (only for CongestionLog attribute) */ +typedef struct _CC_LOG_MAD { + MAD_COMMON common; /* Generic MAD Header */ + uint64 CC_Key; /* CC__Key */ + + uint8 CCLogData[STL_IBA_GS_DATASIZE]; /* CongestionLog Data */ +} PACK_SUFFIX CC_LOG_MAD, *PCC_LOG_MAD; + +/* -------------------------------------------------------------------------- */ +/* SNMP Tunneling MAD format + * #### the multipacket MAD SAR protocol for SNMP tunneling data is different. + */ +typedef struct _SNMPTUNNEL_HDR { + uint8 Resv[32]; + uint32 RAddr; /* Raddress */ + uint8 PayloadLen; /* Payload length */ + uint8 SegmentNum; /* Segment number */ + uint16 SLID; /* Source LID */ +} PACK_SUFFIX SNMPTUNNEL_HDR; + +typedef struct _SNMPTUNNEL_MAD { + MAD_COMMON common; /* Generic MAD Header */ + + SNMPTUNNEL_HDR SnmpTunnelHdr; /* class specific header */ + + uint8 SNMPData[STL_IBA_GS_DATASIZE]; /* SNMP Tunneling Management Data */ +} PACK_SUFFIX SNMPTUNNEL_MAD, *PSNMPTUNNEL_MAD; + +/* -------------------------------------------------------------------------- */ +#if 0 // redefine in opaswcommon.h +/* Vendor Specific Management MAD format */ +typedef struct _VENDOR_MAD { + MAD_COMMON common; /* Generic MAD Header */ + + uint8 VendorData[STL_IBA_GS_DATASIZE]; /* Device Management Data */ +} PACK_SUFFIX VENDOR_MAD, *PVENDOR_MAD; +#endif + +/* values for class specific fields in MAD STATUS + * are defined in class manager specific header files + */ +#include "iba/public/ipackoff.h" + +/* convert RMPP Status to a string + * The string will only contain the message corresponding to the defined values + * callers should also display the hex value in the event a + * reserved, class or vendor specific value is returned by the manager/agent + */ +IBA_API const char* iba_rmpp_status_msg(RMPP_STATUS rmppStatus); + +/* -------------------------------------------------------------------------- */ +/* Swap between cpu and network byte order */ + +/* IBTA 1.1 */ +static __inline +void +BSWAP_RMPP_HEADER( + RMPP_HEADER *RmppHdr + ) +{ +#if CPU_LE + RmppHdr->u1.AsReg32 = ntoh32( RmppHdr->u1.AsReg32 ); + RmppHdr->u2.AsReg32 = ntoh32( RmppHdr->u2.AsReg32 ); +#endif +} + +static __inline +void +BSWAP_SA_HDR( + SA_HDR *SaHdr + ) +{ +#if CPU_LE + SaHdr->SmKey = ntoh64( SaHdr->SmKey ); + SaHdr->AttributeOffset = ntoh16( SaHdr->AttributeOffset ); + SaHdr->ComponentMask = ntoh64( SaHdr->ComponentMask ); +#endif +} + +static __inline +void +BSWAPCOPY_SA_HDR(SA_MAD_HDR *Src, SA_MAD_HDR *Dest) +{ + memcpy(Dest, Src, sizeof(SA_MAD_HDR)); + BSWAP_SA_HDR(&Dest->SaHdr); + BSWAP_RMPP_HEADER(&Dest->RmppHdr); +} + +static __inline +void +BSWAPCOPY_IB_SA_MAD(IB_SA_MAD *src, IB_SA_MAD *dst, size_t len) +{ + memcpy(dst, src, sizeof(SA_MAD_HDR)); + BSWAP_SA_HDR(&dst->SaHdr); + BSWAP_RMPP_HEADER(&dst->RmppHdr); + memcpy(&dst->Data, &src->Data, len); +} + + +static __inline +void +BSWAP_BM_HDR( + BM_HDR *BmHdr + ) +{ +#if CPU_LE + BmHdr->BKey = ntoh64( BmHdr->BKey ); +#endif +} + +static __inline +void +BSWAP_SNMPTUNNEL_HDR( + SNMPTUNNEL_HDR *SnmpTunnelHdr + ) +{ +#if CPU_LE + SnmpTunnelHdr->RAddr = ntoh32( SnmpTunnelHdr->RAddr ); + SnmpTunnelHdr->SLID = ntoh16( SnmpTunnelHdr->SLID ); +#endif +} + +static __inline +void +BSWAP_CC_HDR( + CC_HDR *CCHdr + ) +{ +#if CPU_LE + CCHdr->CC_Key = ntoh64( CCHdr->CC_Key ); +#endif +} + +#ifdef __cplusplus +} +#endif + +#endif /* __IBA_IB_GENERAL_SERVICES_H__ */ diff --git a/IbAccess/Common/Inc/ib_gsi.h b/IbAccess/Common/Inc/ib_gsi.h new file mode 100644 index 0000000..89e6bcd --- /dev/null +++ b/IbAccess/Common/Inc/ib_gsi.h @@ -0,0 +1,698 @@ +/* BEGIN_ICS_COPYRIGHT1 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT1 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +#ifndef _IBA_IB_GSI_H_ +#define _IBA_IB_GSI_H_ + + +#if defined(VXWORKS) + +/* Kernel mode GSI interfaces */ + +#include "iba/vpi.h" +#include "iba/stl_mad_priv.h" + +#if defined (__cplusplus) +extern "C" { +#endif + +typedef enum _GSI_REGISTRATION_FLAGS +{ + GSI_REGISTER_NONE = 0x00000000, + GSI_REGISTER_RESPONDER = 0x00000001, + GSI_REGISTER_TRAP_PROCESSOR = 0x00000002, + GSI_REGISTER_REPORT_PROCESSOR = 0x00000004 +} GSI_REGISTRATION_FLAGS; + +#define GSI_IS_RESPONDER(RegistrationFlags) \ + ((RegistrationFlags & GSI_REGISTER_RESPONDER) ? 1 : 0) + +#define GSI_IS_TRAP_PROCESSOR(RegistrationFlags) \ + ((RegistrationFlags & GSI_REGISTER_TRAP_PROCESSOR) ? 1 : 0) + +#define GSI_IS_REPORT_PROCESSOR(RegistrationFlags) \ + ((RegistrationFlags & GSI_REGISTER_REPORT_PROCESSOR) ? 1 : 0) + +/* + * Structures + */ + +typedef struct _IBT_BUFFER +{ + struct _IBT_BUFFER *pNextBuffer; + void *pData; + uint32 ByteCount; + +} IBT_BUFFER, *PIBT_BUFFER; + + +typedef struct _IBT_ELEMENT +{ + struct _IBT_ELEMENT *pNextElement; + IBT_BUFFER *pBufferList; + void *pContext; + + /* Completion information. */ + uint32 RecvByteCount; + FSTATUS Status; + +} IBT_ELEMENT, IBT_MSG_ELEMENT, + *PIBT_ELEMENT, *PIBT_MSG_ELEMENT; + +typedef struct _IBT_DGRM_ELEMENT +{ + /* The element must be first. */ + IBT_ELEMENT Element; + + /* Required for Sends/ returned on receives */ + uint32 RemoteQP; + uint32 RemoteQKey; + /* TBD - can use an IB_ADDRESS_VECTOR here instead */ + uint64 PortGuid; + IB_LID RemoteLID; + uint8 ServiceLevel; + uint8 PathBits; + uint8 StaticRate; /* enum IB_STATIC_RATE */ + uint16 PkeyIndex; + boolean GlobalRoute; + + /* Returned on receive completion. */ + uint32 TotalRecvSize; + + /* allocate/deallocate tripwire */ + + uint8 Allocated:1; + uint8 OnRecvQ:1; + uint8 OnSendQ:1; + uint8 reserved:5; + + /* Global routing information. */ + /* If GlobalRoute==true, GlobalRouteInfo structure is valid. */ + /* for received MADs, GRHInfo has already been translated to a sender */ + /* perspective (eg. SrcGIDIndex is local port, DestGID is remote port) */ + IB_GLOBAL_ROUTE_INFO GRHInfo; + +} IBT_DGRM_ELEMENT; + + +/* + * GsiDgrmAddrCopy() + * copy address information from one dgrm to another + */ +static __inline +void +GsiDgrmAddrCopy( IBT_DGRM_ELEMENT *pDgrmTo, IBT_DGRM_ELEMENT *pDgrmFrom) +{ + pDgrmTo->RemoteQP = pDgrmFrom->RemoteQP; + pDgrmTo->RemoteQKey = pDgrmFrom->RemoteQKey; + pDgrmTo->PortGuid = pDgrmFrom->PortGuid; + pDgrmTo->RemoteLID = pDgrmFrom->RemoteLID; + pDgrmTo->ServiceLevel = pDgrmFrom->ServiceLevel; + pDgrmTo->PathBits = pDgrmFrom->PathBits; + pDgrmTo->StaticRate = pDgrmFrom->StaticRate; + pDgrmTo->PkeyIndex = pDgrmFrom->PkeyIndex; + pDgrmTo->GlobalRoute = pDgrmFrom->GlobalRoute; + memcpy(&pDgrmTo->GRHInfo, &pDgrmFrom->GRHInfo, sizeof(pDgrmTo->GRHInfo)); +} + +/* For a GSI send Dgrm, the 1st buffer is the MAD packet */ +static __inline +MAD* +GsiDgrmGetSendMad(IBT_DGRM_ELEMENT *pDgrm) +{ + return (MAD*)(pDgrm->Element.pBufferList->pData); +} + +/* For a GSI Recv Dgrm, the 1st buffer is the GRH header */ +static __inline +IB_GRH* +GsiDgrmGetRecvGrh(IBT_DGRM_ELEMENT *pDgrm) +{ + return (IB_GRH*)(pDgrm->Element.pBufferList->pData); +} + +/* For a GSI Recv Dgrm, the 2nd buffer is the MAD packet */ +static __inline +MAD* +GsiDgrmGetRecvMad(IBT_DGRM_ELEMENT *pDgrm) +{ + return (MAD*)(pDgrm->Element.pBufferList->pNextBuffer->pData); +} + +static __inline +uint32 +GsiDgrmGetRecvMadByteCount(IBT_DGRM_ELEMENT *pDgrm) +{ + return pDgrm->Element.pBufferList->pNextBuffer->ByteCount; +} + +/* + * Callbacks + */ + + +/* + * GSI_SEND_COMPLETION_CALLBACK + * + * + * INPUTS: + * ServiceContext - Caller defined context used during register class + * DgrmList - Pointer to a single/pool of Datagram(s) completed in send + * + * OUTPUTS: + * None + * + * RETURNS: + * None + */ +typedef void +(GSI_SEND_COMPLETION_CALLBACK)( + IN void *ServiceContext, + IN IBT_DGRM_ELEMENT *DgrmList + ); + + + + +/* + * GSI_RECEIVE_CALLBACK + * + * + * INPUTS: + * ServiceContext - Caller defined context used during register class + * DgrmList - Pointer to a single/pool of Datagram(s) received + * + * OUTPUTS: + * None + * + * RETURNS: + * FCOMPLETED + * FPENDING + */ +typedef FSTATUS +(GSI_RECEIVE_CALLBACK)( + IN void *ServiceContext, + IN IBT_DGRM_ELEMENT *DgrmList + ); + + + +/* + * Registration and Class routines + */ + + +/* + * GsiRegisterClass + * + * GsiRegisterClass registers a management class with GSI. + * A class is identified by a unique id, a version. The class owner + * can also register a callback that can be used to indicate + * incoming packets targeted for this class and a callback to + * indicate post send completions. + * + * INPUTS: + * MgmtClass - Management class to be registered + * MgmtClassVersion- Will be 1 for this version. + * RegistrationFlags - Indicates if this is a Responder and/or a Trap Processor + * and/or a Report Processor. + * Responders, Trap/Report Processors register for and + * receive unsolicited messages. GSI supports multiple + * registrations per class. + * SARClient - TRUE indicates client needs SAR capability. + * ServiceContext - Caller defined context passed back in callbacks. + * SendCompletionCallback- Callback for all datagrams completions posted + * in send. + * ReceiveCallback - Callback for all datagrams received. + * + * OUTPUTS: + * ServiceHandle - Client unique handle returned to caller on successful + * registration. + * + * RETURNS: + * FSUCCESS + * FINVALID_PARAMETER + * FINSUFFICIENT_RESOURCES + */ +typedef FSTATUS +(GSI_REGISTER_CLASS)( + IN uint8 MgmtClass, + IN uint8 MgmtClassVersion, + IN GSI_REGISTRATION_FLAGS RegistrationFlags, + IN boolean SARClient, + IN void *ServiceContext, + IN GSI_SEND_COMPLETION_CALLBACK *SendCompletionCallback, + IN GSI_RECEIVE_CALLBACK *ReceiveCallback, + OUT IB_HANDLE *ServiceHandle + ); +IBA_API GSI_REGISTER_CLASS iba_gsi_register_class; + + +/* + * GsiDeregisterClass + * + * INPUTS: + * ServiceHandle - Handle returned upon a successful registration. + * + * OUTPUTS: + * None + * + * RETURNS: + * FSUCCESS + * FINVALID_PARAMETER + * FINSUFFICIENT_RESOURCES + */ +typedef FSTATUS +(GSI_DEREGISTER_CLASS)( + IN IB_HANDLE ServiceHandle + ); +IBA_API GSI_DEREGISTER_CLASS iba_gsi_deregister_class; + + +/* + * Pool management routines + */ + +/* + * GsiCreateDgrmPool + * + * INPUTS: + * ServiceHandle - Handle returned upon registration + * ElementCount - Number of elements in pool + * BuffersPerElement- Number of buffers in each pool element + * BufferSizeArray[]- An array of buffers sizes. The length of this array must + * be equal to BuffersPerElement. + * ContextSize - Size of user context in each element + * + * OUTPUTS: + * DgrmPoolHandle - Opaque handle returned to identify datagram pool created + * + * RETURNS: + * FSUCCESS + * FINVALID_PARAMETER + * FINSUFFICIENT_RESOURCES + */ +typedef FSTATUS +(GSI_CREATE_DGRM_POOL)( + IN IB_HANDLE ServiceHandle, + IN uint32 ElementCount, + IN uint32 BuffersPerElement, + IN uint32 BufferSizeArray[], + IN uint32 ContextSize, + OUT IB_HANDLE *DgrmPoolHandle + ); +IBA_API GSI_CREATE_DGRM_POOL iba_gsi_create_dgrm_pool; + + +/* + * GsiDestroyDgrmPool + * + * INPUTS: + * DgrmPoolHandle - Handle returned upon successful creation of Datagram pool + * + * OUTPUTS: + * None + * + * RETURNS: + * FSUCCESS + * FINVALID_PARAMETER + * FINSUFFICIENT_RESOURCES + */ +typedef FSTATUS +(GSI_DESTROY_DGRM_POOL)( + IN IB_HANDLE DgrmPoolHandle + ); +IBA_API GSI_DESTROY_DGRM_POOL iba_gsi_destroy_dgrm_pool; + + + +/* + * GsiDgrmPoolGet + * + * INPUTS: + * DgrmPoolHandle - Handle returned upon successful creation of Datagram pool + * ElementCount - Number of elements to fetch from pool + * + * OUTPUTS: + * ElementCount - Number of elements fetched from pool + * DgrmList - Pointer holds the datagram list if successful + * + * RETURNS: + * FSUCCESS + * FINVALID_PARAMETER + * FINSUFFICIENT_RESOURCES + */ +typedef FSTATUS +(GSI_DGRM_POOL_GET)( + IN IB_HANDLE DgrmPoolHandle, + IN OUT uint32 *ElementCount, + OUT IBT_DGRM_ELEMENT **DgrmList + ); +IBA_API GSI_DGRM_POOL_GET iba_gsi_dgrm_pool_get; + + +/* + * GsiDgrmPoolPut + * + * + * INPUTS: + * DgrmList - Datagram elements to return back to pool + * + * OUTPUTS: + * None + * + * RETURNS: + * FSUCCESS + * FINVALID_PARAMETER + * FINSUFFICIENT_RESOURCES + */ +typedef FSTATUS +(GSI_DGRM_POOL_PUT)( + IN IBT_DGRM_ELEMENT *DgrmList + ); +IBA_API GSI_DGRM_POOL_PUT iba_gsi_dgrm_pool_put; + + +/* + * GsiDgrmPoolCount + * + * INPUTS: + * DgrmPoolHandle - Handle returned upon successful creation of Datagram pool + * + * OUTPUTS: + * + * RETURNS: + * number of datagrams in the pool + */ +typedef uint32 +(GSI_DGRM_POOL_COUNT)( + IN IB_HANDLE DgrmPoolHandle + ); +IBA_API GSI_DGRM_POOL_COUNT iba_gsi_dgrm_pool_count; + + + +/* + * GsiDgrmPoolTotal + * + * INPUTS: + * DgrmPoolHandle - Handle returned upon successful creation of Datagram pool + * + * OUTPUTS: + * + * RETURNS: + * total number of datagrams allocated in the pool + */ +typedef uint32 +(GSI_DGRM_POOL_TOTAL)( + IN IB_HANDLE DgrmPoolHandle + ); +IBA_API GSI_DGRM_POOL_TOTAL iba_gsi_dgrm_pool_total; + + +/* + * CreateGrowableDgrmPool + * + * + * + * INPUTS: + * + * ServiceHandle - Handle returned upon registration + * + * ElementCount - Initial Number of elements in pool (can be 0) + * + * BuffersPerElement- Number of buffers in each pool element (required) + * + * BufferSizeArray[]- An array of buffers sizes. The length of this array must + * be equal to BuffersPerElement. (required) + * + * ContextSize - Size of user context in each element (required) + * + * + * + * OUTPUTS: + * + * DgrmPoolHandle - Opaque handle returned to identify datagram pool created + * + * + * + * RETURNS: + * + * FSUCCESS + * FINVALID_PARAMETER + * FINSUFFICIENT_RESOURCES + * + */ + +typedef FSTATUS +(GSI_CREATE_GROWABLE_DGRM_POOL)( + IN IB_HANDLE ServiceHandle, + IN uint32 ElementCount, + IN uint32 BuffersPerElement, + IN uint32 BufferSizeArray[], + IN uint32 ContextSize, + OUT IB_HANDLE *DgrmPoolHandle + ); +IBA_API GSI_CREATE_GROWABLE_DGRM_POOL iba_gsi_create_growable_dgrm_pool; + +/* + * DgrmPoolGrow + * Grow the size of a Growable Dgrm Pool + * This routine may preempt. + * + * + * INPUTS: + * DgrmPoolHandle - Opaque handle to datagram pool + * + * ELementCount - number of elements to add to pool + * + * + * + * OUTPUTS: + * + * None + * + * + * RETURNS: + * + * FSUCCESS + * FINVALID_PARAMETER + * FINSUFFICIENT_RESOURCES + */ +typedef FSTATUS +(GSI_DGRM_POOL_GROW)( + IN IB_HANDLE DgrmPoolHandle, + IN uint32 ElementCount + ); +IBA_API GSI_DGRM_POOL_GROW iba_gsi_dgrm_pool_grow; + +/* + * DgrmPoolGrowAsNeeded + * Checks Pool size and schedules a system callback to grow it as needed + * This routine does not preempt. + * + * + * INPUTS: + * DgrmPoolHandle - Opaque handle to datagram pool + * + * lowWater - if Dgrm Pool available < this, we will grow it + * + * maxElements - limit on size of Dgrm Pool, will not grow beyond this + * + * growIncrement - amount to grow by if we are growing + * + * + * + * OUTPUTS: + * + * None + * + * + * RETURNS: + * + * None + */ +typedef void +(GSI_DGRM_POOL_GROW_AS_NEEDED)( + IN IB_HANDLE DgrmPoolHandle, + IN uint32 lowWater, + IN uint32 maxElements, + IN uint32 growIncrement + ); +IBA_API GSI_DGRM_POOL_GROW_AS_NEEDED iba_gsi_dgrm_pool_grow_as_needed; + + +/* + * Post operation routines + */ + +/* + * GsiPostSendDgrm + * + * + * INPUTS: + * ServiceHandle - Handle returned upon registration + * DgrmList - List of datagram(s) to be posted for send + * each must have payload in network byte order + * however MAD and RMPP_HEADERs should be in host + * byte order. On success, GSI owns the buffer and + * will byte swap back the MAD header prior to send completion + * on failure the buffer will be restored to host byte order + * for the MAD and RMPP headers + * + * OUTPUTS: + * None + * + * RETURNS: + * FSUCCESS + * FINVALID_PARAMETER + * FINSUFFICIENT_RESOURCES + * FINVALID_STATE + */ +typedef FSTATUS +(GSI_POST_SEND_DGRM)( + IN IB_HANDLE ServiceHandle, + IN IBT_DGRM_ELEMENT *DgrmList + ); +IBA_API GSI_POST_SEND_DGRM iba_gsi_post_send; + + + + + +/* + * Helper functions + */ + +/* + * iba_gsi_dgrm_len + * + * This reports the length of a Dgrm sequence as total of: + * GRH + * MAD_COMMON + * RMPP_HEADER + * class Header (SA, etc) + * RMPP_DATA (possibly large) + * returned messageSize will indicate the total size of the output. + * RmppHdr.PayloadLen will not be adjusted, it will still reflect the + * total RMPP_DATA which will account for a class Header in each + * packet. + * + * INPUTS: + * DgrmElement - A list of Datagrams that need to be analyzed + * data pointed to only used during duration of call + * ClassHeaderSize - size of class header + * this is expected to be in every RMPP packet + * immediately after the RMPP_HEADER + * size will account for one copy of the Class header + * from the 1st RMPP DATA of the message + * + * OUTPUTS: + * None + * + * RETURNS: + * Message Size. + * if invalid RMPP sequence, returns 0 + */ +typedef uint32 +(GSI_DGRM_LEN)( + IN IBT_DGRM_ELEMENT *DgrmElement, + IN uint32 ClassHeaderSize + ); +IBA_API GSI_DGRM_LEN iba_gsi_dgrm_len; + + +/* + * GsiCoalesceDgrm + * + * The Coalesce function will create an output as follows: + * GRH + * MAD_COMMON + * RMPP_HEADER + * class Header (SA, etc) + * RMPP_DATA (possibly large) + * returned messageSize will indicate the total size of the output + * RmppHdr.PayloadLen will not be adjusted, it will reflect the + * total RMPP_DATA which will account for a class Header in each + * packet. + * + * INPUTS: + * DgrmElement - A list of Datagrams that need to be coalesced + * data pointed to only used during duration of call + * ppBuffer - *ppBuffer is Client buffer to coalesce to + * if *ppBuffer is NULL, this routine will + * compute the necessary size of the buffer and + * allocate it on behalf of the caller + * data pointed to only used during duration of call + * ClassHeaderSize - size of class header + * this is expected to be in every RMPP packet + * immediately after the RMPP_HEADER + * a copy of the Class header from the 1st RMPP + * DATA of the message will be included in the + * Coalesced output buffer + * MemAllocFlags - flags for memory allocate of buffer + * for larger responses, it is recommended caller + * be structured such that IBA_MEM_FLAG_PREEMPTABLE + * can be used + * + * OUTPUTS: + * None + * + * RETURNS: + * + * Message size. + * if unable to allocate buffer *ppBuffer is left NULL + * if invalid RMPP sequence, returns 0. In which case *ppBuffer will be NULL. + */ +typedef uint32 +(GSI_COALESCE_DGRM)( + IN IBT_DGRM_ELEMENT *DgrmElement, + IN uint8 **ppBuffer, + IN uint32 ClassHeaderSize + ); +IBA_API GSI_COALESCE_DGRM iba_gsi_coalesce_dgrm; + +typedef uint32 +(GSI_COALESCE_DGRM2)( + IN IBT_DGRM_ELEMENT *DgrmElement, + IN uint8 **ppBuffer, + IN uint32 ClassHeaderSize, + IN uint32 MemAllocFlags + ); +IBA_API GSI_COALESCE_DGRM2 iba_gsi_coalesce_dgrm2; + + +#if defined (__cplusplus) +}; +#endif + +#endif /* VXWORKS */ +#endif /* _IBA_IB_GSI_H_ */ diff --git a/IbAccess/Common/Inc/ib_helper.h b/IbAccess/Common/Inc/ib_helper.h new file mode 100644 index 0000000..98b6fc8 --- /dev/null +++ b/IbAccess/Common/Inc/ib_helper.h @@ -0,0 +1,1388 @@ +/* BEGIN_ICS_COPYRIGHT3 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT3 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +#ifndef _IBA_IB_HELPER_H_ +#define _IBA_IB_HELPER_H_ + +#include "iba/stl_types.h" +#include "iba/stl_sm_types.h" + +#include "iba/ib_mad.h" +#include "iba/public/imath.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* these helper functions are macros available only within ib_helper.h + * to protect them from misuse; they are undefined outside of ib_helper.h + */ + +/* convert mbps (10^6 bits/sec) to MBps (2^20 bytes/sec) + * speeds through QDR use 8b10b wire encoding ( * 1 / 10 ) + */ +#define IbmbpsToMBps(mbps) {\ + ((uint32)((((uint64)mbps / 10LL) * 1000000LL) / ( 1LL << 20))); \ +} + +/* convert mbps (10^6 bits/sec) to MBps (2^20 bytes/sec) for extended speeds + * extended speeds use 64b66b wire encoding ( * 8 / 66 ) + */ +#define IbmbpsToMBpsExt(mbps) {\ + ((uint32)(((uint64)mbps * 8LL * 1000000LL) / (66LL * (1LL << 20)))); \ +} + +/* these helper functions are simple, so they are done as inlines + * largely to avoid the need to export all these symbols from a + * kernel module or a library + */ + +/* + * Convert a IB_PORT_STATE to a constant string + */ +static __inline const char* +IbPortStateToText( IN IB_PORT_STATE state ) +{ + switch (state) + { + case IB_PORT_NOP: + return "Noop"; + case IB_PORT_DOWN: + return "Down"; + case IB_PORT_INIT: + return "Init"; + case IB_PORT_ARMED: + return "Armed"; + case IB_PORT_ACTIVE: + return "Active"; + default: + return "????"; + } +} + +/* + * Convert a IB_PORT_PHYS_STATE to a constant string + */ +static __inline const char* +IbPortPhysStateToText( IN IB_PORT_PHYS_STATE state ) +{ + switch (state) + { + case IB_PORT_PHYS_NOP: + return "Noop"; + case IB_PORT_PHYS_SLEEP: + return "Sleep"; + case IB_PORT_PHYS_POLLING: + return "Polling"; + case IB_PORT_PHYS_DISABLED: + return "Disabled"; + case IB_PORT_PHYS_TRAINING: + return "Training"; + case IB_PORT_PHYS_LINKUP: + return "LinkUp"; + case IB_PORT_PHYS_LINK_ERROR_RECOVERY: + return "Recovery"; + default: + return "????"; + } +} + +/* + * Convert a IB_PORT_PHYS_STATE for DownDefault to a constant string + */ +static __inline const char* +IbPortDownDefaultToText( IN IB_PORT_PHYS_STATE state ) +{ + switch (state) + { + case IB_PORT_PHYS_NOP: + return "Noop"; + case IB_PORT_PHYS_SLEEP: + return "Sleep"; + case IB_PORT_PHYS_POLLING: + return "Polling"; + default: + return "????"; + } +} + +/* + * Convert IB_MTU enumeration to a byte count + */ +static __inline uint16 +GetBytesFromMtu(uint8 mtu) +{ + switch (mtu) + { + default: + return 0; + case IB_MTU_256: + return 256; + case IB_MTU_512: + return 512; + case IB_MTU_1024: + return 1024; + case IB_MTU_2048: + return 2048; + case IB_MTU_4096: + return 4096; + case STL_MTU_8192: + return 8192; + case STL_MTU_10240: + return 10240; + } +} +/* Convert byte count to nearest IB_MTU enumeration (rounds up) + * (eg. returns IB MTU required to support packet sizes of "bytes") + */ +static __inline uint8 +GetMtuFromBytes(uint16 bytes) +{ + if (bytes <= 256) + return IB_MTU_256; + else if (bytes <= 512) + return IB_MTU_512; + else if (bytes <= 1024) + return IB_MTU_1024; + else if (bytes <= 2048) + return IB_MTU_2048; + else if (bytes <= 4096) + return IB_MTU_4096; + else if (bytes <= 8192) + return STL_MTU_8192; + else if (bytes <= 10240) + return STL_MTU_10240; + else + return IB_MTU_4096; +} + +/* Convert IB_MTU enumeration to text */ +static __inline const char* +IbMTUToText(IB_MTU mtu) +{ + switch ((int)mtu) + { + case STL_MTU_0: + default: + return "0"; + case IB_MTU_256: + return "256"; + case IB_MTU_512: + return "512"; + case IB_MTU_1024: + return "1024"; + case IB_MTU_2048: + return "2048"; + case IB_MTU_4096: + return "4096"; + case STL_MTU_8192: + return "8192"; + case STL_MTU_10240: + return "10240"; + } +} + +/* Convert static rate to text */ +static inline const char* +IbStaticRateToText(IB_STATIC_RATE rate) +{ + switch (rate) + { + case IB_STATIC_RATE_DONTCARE: + return "any"; + case IB_STATIC_RATE_1GB: + return "1g"; + case IB_STATIC_RATE_2_5G: + return "2.5g"; + case IB_STATIC_RATE_10G: + return "10g"; + case IB_STATIC_RATE_30G: + return "30g"; + case IB_STATIC_RATE_5G: + return "5g"; + case IB_STATIC_RATE_20G: + return "20g"; + case IB_STATIC_RATE_40G: + return "40g"; + case IB_STATIC_RATE_60G: + return "60g"; + case IB_STATIC_RATE_80G: + return "80g"; + case IB_STATIC_RATE_120G: + return "120g"; + case IB_STATIC_RATE_14G: + return "14g"; // 14.0625g + case IB_STATIC_RATE_25G: + return "25g"; // 25.78125g + case IB_STATIC_RATE_56G: + return "56g"; // 56.25g + case IB_STATIC_RATE_100G: + return "100g"; // 103.125g + case IB_STATIC_RATE_112G: + return "112g"; // 112.5g + case IB_STATIC_RATE_200G: + return "200g"; // 206.25g + case IB_STATIC_RATE_168G: + return "168g"; // 168.75g + case IB_STATIC_RATE_300G: + return "300g"; // 309.375g + default: + return "???"; + } +} + +/* convert static rate to mbps (10^6 bits/sec) units */ +static __inline uint32 +IbStaticRateToMbps(IB_STATIC_RATE rate) +{ + switch (rate) + { + default: + case IB_STATIC_RATE_DONTCARE: + return 10000; /* default to 10G */ + /* In other functions this is present wire speed */ + case IB_STATIC_RATE_1GB: + return 1000; + case IB_STATIC_RATE_2_5G: + return 2500; + case IB_STATIC_RATE_10G: + return 10000; + case IB_STATIC_RATE_30G: + return 30000; + case IB_STATIC_RATE_5G: + return 5000; + case IB_STATIC_RATE_20G: + return 20000; + case IB_STATIC_RATE_40G: + return 40000; + case IB_STATIC_RATE_60G: + return 60000; + case IB_STATIC_RATE_80G: + return 80000; + case IB_STATIC_RATE_120G: + return 120000; + case IB_STATIC_RATE_14G: + return 14062; + case IB_STATIC_RATE_25G: + return 25781; + case IB_STATIC_RATE_56G: + return 56250; + case IB_STATIC_RATE_100G: + return 103125; + case IB_STATIC_RATE_112G: + return 112500; + case IB_STATIC_RATE_200G: + return 206250; + case IB_STATIC_RATE_168G: + return 168750; + case IB_STATIC_RATE_300G: + return 309375; + } +} + +/* convert static rate to PMA million ticks/sec units + * tick = time to send 1 byte on wire + */ +static __inline uint32 +IbStaticRateToMTickps(IB_STATIC_RATE rate) +{ + if (rate <= IB_STATIC_RATE_LAST_QDR) + return (IbStaticRateToMbps(rate)/10); // 8b10b encoding + else + return ((IbStaticRateToMbps(rate)*8)/66); // 64b66b encoding +} + +/* convert static rate to MByte/sec units, M=2^20 */ +static __inline uint32 +IbStaticRateToMBps(IB_STATIC_RATE rate) +{ + if (rate <= IB_STATIC_RATE_LAST_QDR) + return (IbmbpsToMBps(IbStaticRateToMbps(rate))); + else + return (IbmbpsToMBpsExt(IbStaticRateToMbps(rate))); +} + +/* convert mbps (10^6 bits/sec) to static rate */ +static __inline IB_STATIC_RATE +IbMbpsToStaticRate(uint32 rate_mbps) +{ + /* 1Gb rate is obsolete */ + if (rate_mbps <= 2500) + return IB_STATIC_RATE_2_5G; + else if (rate_mbps <= 5000) + return IB_STATIC_RATE_5G; + else if (rate_mbps <= 10000) + return IB_STATIC_RATE_10G; + else if (rate_mbps <= 14062) + return IB_STATIC_RATE_14G; + else if (rate_mbps <= 20000) + return IB_STATIC_RATE_20G; + else if (rate_mbps <= 25781) + return IB_STATIC_RATE_25G; + else if (rate_mbps <= 30000) + return IB_STATIC_RATE_30G; + else if (rate_mbps <= 40000) + return IB_STATIC_RATE_40G; + else if (rate_mbps <= 56250) + return IB_STATIC_RATE_56G; + else if (rate_mbps <= 60000) + return IB_STATIC_RATE_60G; + else if (rate_mbps <= 80000) + return IB_STATIC_RATE_80G; + else if (rate_mbps <= 103125) + return IB_STATIC_RATE_100G; + else if (rate_mbps <= 112500) + return IB_STATIC_RATE_112G; + else if (rate_mbps <= 120000) + return IB_STATIC_RATE_120G; + else if (rate_mbps <= 168750) + return IB_STATIC_RATE_168G; + else if (rate_mbps <= 206250) + return IB_STATIC_RATE_200G; + else + return IB_STATIC_RATE_300G; +} + +/* convert link width to text + * 7 char output for Supported/Enabled Width (multi rate) + * 4 char output for Active Width (single rate or Noop) + */ +static __inline const char* +IbLinkWidthToText(IB_LINK_WIDTH width) +{ + return (width == IB_LINK_WIDTH_NOP)?"None": + (width == IB_LINK_WIDTH_1X)?"1x": + (width == IB_LINK_WIDTH_4X)?"4x": + (width == IB_LINK_WIDTH_8X)?"8x": + (width == IB_LINK_WIDTH_12X)?"12x": + (width == IB_LINK_WIDTH_1X+IB_LINK_WIDTH_4X)?"1-4x": + (width == IB_LINK_WIDTH_1X+IB_LINK_WIDTH_8X)?"1,8x": + (width == IB_LINK_WIDTH_1X+IB_LINK_WIDTH_12X)?"1,12x": + (width == IB_LINK_WIDTH_1X+IB_LINK_WIDTH_4X+IB_LINK_WIDTH_8X)?"1-8x": + (width == IB_LINK_WIDTH_1X+IB_LINK_WIDTH_4X+IB_LINK_WIDTH_12X)?"1,4,12x": + (width == IB_LINK_WIDTH_1X+IB_LINK_WIDTH_8X+IB_LINK_WIDTH_12X)?"1,8,12x": + (width == IB_LINK_WIDTH_1X+IB_LINK_WIDTH_4X+IB_LINK_WIDTH_8X+IB_LINK_WIDTH_12X)?"1-12x": + (width == IB_LINK_WIDTH_4X+IB_LINK_WIDTH_8X)?"4-8x": + (width == IB_LINK_WIDTH_4X+IB_LINK_WIDTH_12X)?"4,12x": + (width == IB_LINK_WIDTH_4X+IB_LINK_WIDTH_8X+IB_LINK_WIDTH_12X)?"4-12x": + (width == IB_LINK_WIDTH_8X+IB_LINK_WIDTH_12X)?"8-12x": + (width == IB_LINK_WIDTH_ALL_SUPPORTED)?"all": + "???"; +} + +/* determine if link width is a valid value for active link width */ +/* Active Link width can only have 1 bit set, Note that Enabled and Supported + * can have multiple bits set + */ +static __inline boolean +IbLinkWidthIsValidActive(IB_LINK_WIDTH width) +{ + switch (width) { + default: + return FALSE; + case IB_LINK_WIDTH_1X: + case IB_LINK_WIDTH_4X: + case IB_LINK_WIDTH_8X: + case IB_LINK_WIDTH_12X: + return TRUE; + } +} + +/* convert link width to integer multiplier */ +static __inline uint32 +IbLinkWidthToInt(IB_LINK_WIDTH width) +{ + switch (width) { + default: + case IB_LINK_WIDTH_1X: return 1; + case IB_LINK_WIDTH_4X: return 4; + case IB_LINK_WIDTH_8X: return 8; + case IB_LINK_WIDTH_12X: return 12; + } +} + +/* convert integer multiplier to link width */ +static __inline IB_LINK_WIDTH +IbIntToLinkWidth(uint32 width) +{ + if (width <= 1) + return IB_LINK_WIDTH_1X; + else if (width <= 4) + return IB_LINK_WIDTH_4X; + else if (width <= 8) + return IB_LINK_WIDTH_8X; + else + return IB_LINK_WIDTH_12X; +} + +/* compare 2 link widths and report expected operational width + * can be used to compare Enabled or Supported values in connected ports + */ +static __inline IB_LINK_WIDTH +IbExpectedLinkWidth(IB_LINK_WIDTH a, IB_LINK_WIDTH b) +{ + if ((IB_LINK_WIDTH_12X & a) && (IB_LINK_WIDTH_12X & b)) + return IB_LINK_WIDTH_12X; + else if ((IB_LINK_WIDTH_8X & a) && (IB_LINK_WIDTH_8X & b)) + return IB_LINK_WIDTH_8X; + else if ((IB_LINK_WIDTH_4X & a) && (IB_LINK_WIDTH_4X & b)) + return IB_LINK_WIDTH_4X; + else if ((IB_LINK_WIDTH_1X & a) && (IB_LINK_WIDTH_1X & b)) + return IB_LINK_WIDTH_1X; + else + return (IB_LINK_WIDTH)0; /* link should come up */ +} + +/* return the best link width set in the bit mask */ +static __inline IB_LINK_WIDTH +IbBestLinkWidth(IB_LINK_WIDTH width) +{ + if (IB_LINK_WIDTH_12X & width) + return IB_LINK_WIDTH_12X; + else if (IB_LINK_WIDTH_8X & width) + return IB_LINK_WIDTH_8X; + else if (IB_LINK_WIDTH_4X & width) + return IB_LINK_WIDTH_4X; + else if (IB_LINK_WIDTH_1X & width) + return IB_LINK_WIDTH_1X; + else + return (IB_LINK_WIDTH)0; /* no width? */ +} + +/* convert link speed to 12 character text (most are <= 10) */ +static __inline const char* +IbLinkSpeedToText(IB_LINK_SPEED speed) +{ + return (speed == IB_LINK_SPEED_NOP)?"None": + (speed == IB_LINK_SPEED_2_5G)?"2.5Gb": + (speed == IB_LINK_SPEED_2_5G+IB_LINK_SPEED_5G)?"2.5-5Gb": + (speed == IB_LINK_SPEED_2_5G+IB_LINK_SPEED_10G)?"2.5,10Gb": + (speed == IB_LINK_SPEED_2_5G+IB_LINK_SPEED_5G+IB_LINK_SPEED_10G)?"2.5-10Gb": + (speed == IB_LINK_SPEED_5G)?"5.0Gb": + (speed == IB_LINK_SPEED_5G+IB_LINK_SPEED_10G)?"5-10Gb": + (speed == IB_LINK_SPEED_10G)?"10.0Gb": + (speed == IB_LINK_SPEED_2_5G+IB_LINK_SPEED_14G)?"2.5,14Gb": + (speed == IB_LINK_SPEED_2_5G+IB_LINK_SPEED_5G+IB_LINK_SPEED_14G)?"2.5-5,14Gb": + (speed == IB_LINK_SPEED_2_5G+IB_LINK_SPEED_5G+IB_LINK_SPEED_10G+IB_LINK_SPEED_14G)?"2.5-14Gb": + (speed == IB_LINK_SPEED_2_5G+IB_LINK_SPEED_10G+IB_LINK_SPEED_14G)?"2.5,10-14G": + (speed == IB_LINK_SPEED_5G+IB_LINK_SPEED_10G+IB_LINK_SPEED_14G)?"5-14Gb": + (speed == IB_LINK_SPEED_5G+IB_LINK_SPEED_14G)?"5,14Gb": + (speed == IB_LINK_SPEED_10G+IB_LINK_SPEED_14G)?"10-14Gb": + (speed == IB_LINK_SPEED_14G)?"14.0Gb": + (speed == IB_LINK_SPEED_2_5G+IB_LINK_SPEED_25G)?"2.5,25Gb": + (speed == IB_LINK_SPEED_2_5G+IB_LINK_SPEED_5G+IB_LINK_SPEED_25G)?"2.5-5,25Gb": + (speed == IB_LINK_SPEED_2_5G+IB_LINK_SPEED_5G+IB_LINK_SPEED_10G+IB_LINK_SPEED_25G)?"2.5-10,25G": + (speed == IB_LINK_SPEED_2_5G+IB_LINK_SPEED_5G+IB_LINK_SPEED_10G+IB_LINK_SPEED_14G+IB_LINK_SPEED_25G)?"2.5-25Gb": + (speed == IB_LINK_SPEED_2_5G+IB_LINK_SPEED_5G+IB_LINK_SPEED_14G+IB_LINK_SPEED_25G)?"2.5-5,14-25G": + (speed == IB_LINK_SPEED_2_5G+IB_LINK_SPEED_10G+IB_LINK_SPEED_14G+IB_LINK_SPEED_25G)?"2.5,10-25G": + (speed == IB_LINK_SPEED_2_5G+IB_LINK_SPEED_14G+IB_LINK_SPEED_25G)?"2.5,14-25G": + (speed == IB_LINK_SPEED_2_5G+IB_LINK_SPEED_10G+IB_LINK_SPEED_25G)?"2.5,10,25G": + (speed == IB_LINK_SPEED_5G+IB_LINK_SPEED_25G)?"5.0,25Gb": + (speed == IB_LINK_SPEED_5G+IB_LINK_SPEED_10G+IB_LINK_SPEED_25G)?"5-10,25Gb": + (speed == IB_LINK_SPEED_5G+IB_LINK_SPEED_10G+IB_LINK_SPEED_14G+IB_LINK_SPEED_25G)?"5-25Gb": + (speed == IB_LINK_SPEED_5G+IB_LINK_SPEED_14G+IB_LINK_SPEED_25G)?"5,14-25Gb": + (speed == IB_LINK_SPEED_10G+IB_LINK_SPEED_14G+IB_LINK_SPEED_25G)?"10-25Gb": + (speed == IB_LINK_SPEED_14G+IB_LINK_SPEED_25G)?"14-25Gb": + (speed == IB_LINK_SPEED_10G+IB_LINK_SPEED_25G)?"10,25Gb": + (speed == IB_LINK_SPEED_25G)?"25.7Gb": + (speed == IB_LINK_SPEED_ALL_SUPPORTED)?"ALL": + "????"; +} + +/* determine if link speed is a valid value for active link speed */ +/* Active Link speed can only have 1 bit set, Note that Enabled and Supported + * can have multiple bits set + */ +static __inline boolean +IbLinkSpeedIsValidActive(IB_LINK_SPEED speed) +{ + switch (speed) { + default: + return FALSE; + case IB_LINK_SPEED_2_5G: + case IB_LINK_SPEED_5G: + case IB_LINK_SPEED_10G: + case IB_LINK_SPEED_14G: + case IB_LINK_SPEED_25G: + return TRUE; + } +} + +/* convert link speed to mbps (10^6 bits/sec) units */ +static __inline uint32 +IbLinkSpeedToMbps(IB_LINK_SPEED speed) +{ + switch (speed) { + default: + case IB_LINK_SPEED_2_5G: return 2500; + case IB_LINK_SPEED_5G: return 5000; + case IB_LINK_SPEED_10G: return 10000; + case IB_LINK_SPEED_14G: return 14062; + case IB_LINK_SPEED_25G: return 25781; + } +} + +/* convert mbps (10^6 bits/sec) to link speed */ +static __inline IB_LINK_SPEED +IbMbpsToLinkSpeed(uint32 speed) +{ + if (speed <= 2500) + return IB_LINK_SPEED_2_5G; + else if (speed <= 5000) + return IB_LINK_SPEED_5G; + else if (speed <= 10000) + return IB_LINK_SPEED_10G; + else if (speed <= 14062) + return IB_LINK_SPEED_14G; + else + return IB_LINK_SPEED_25G; +} + +/* compare 2 link speeds and report expected operational speed + * can be used to compare Enabled or Supported values in connected ports + */ +static __inline IB_LINK_SPEED +IbExpectedLinkSpeed(IB_LINK_SPEED a, IB_LINK_SPEED b) +{ + if ((IB_LINK_SPEED_25G & a) && (IB_LINK_SPEED_25G & b)) + return IB_LINK_SPEED_25G; + else if ((IB_LINK_SPEED_14G & a) && (IB_LINK_SPEED_14G & b)) + return IB_LINK_SPEED_14G; + else if ((IB_LINK_SPEED_10G & a) && (IB_LINK_SPEED_10G & b)) + return IB_LINK_SPEED_10G; + else if ((IB_LINK_SPEED_5G & a) && (IB_LINK_SPEED_5G & b)) + return IB_LINK_SPEED_5G; + else if ((IB_LINK_SPEED_2_5G & a) && (IB_LINK_SPEED_2_5G & b)) + return IB_LINK_SPEED_2_5G; + else + return (IB_LINK_SPEED)0; /* link should not come up */ +} + +/* return the best link speed set in the bit mask */ +static __inline IB_LINK_SPEED +IbBestLinkSpeed(IB_LINK_SPEED speed) +{ + if (IB_LINK_SPEED_25G & speed) + return IB_LINK_SPEED_25G; + else if (IB_LINK_SPEED_14G & speed) + return IB_LINK_SPEED_14G; + else if (IB_LINK_SPEED_10G & speed) + return IB_LINK_SPEED_10G; + else if (IB_LINK_SPEED_5G & speed) + return IB_LINK_SPEED_5G; + else if (IB_LINK_SPEED_2_5G & speed) + return IB_LINK_SPEED_2_5G; + else + return (IB_LINK_SPEED)0; /* no speed? */ +} + +/* convert link speed and width to mbps (10^6 bits/sec) */ +static __inline uint32 +IbLinkSpeedWidthToMbps(IB_LINK_SPEED speed, IB_LINK_WIDTH width) +{ + return IbLinkSpeedToMbps(speed) * IbLinkWidthToInt(width); +} + +/* convert link speed and width to Static Rate */ +static __inline IB_STATIC_RATE +IbLinkSpeedWidthToStaticRate(IB_LINK_SPEED speed, IB_LINK_WIDTH width) +{ + return IbMbpsToStaticRate(IbLinkSpeedWidthToMbps(speed, width)); +} + +/* convert static rate to InterPacketDelay (IPD) */ +static __inline uint8 +IbStaticRateToIpd(IB_STATIC_RATE rate, IB_LINK_WIDTH linkWidth, IB_LINK_SPEED linkSpeed) +{ + uint32 link_rate_mbps; + uint32 static_rate_mbps; + + if (rate == IB_STATIC_RATE_DONTCARE) + return 0; /* 100% speed */ + link_rate_mbps = IbLinkWidthToInt(linkWidth)*IbLinkSpeedToMbps(linkSpeed); + static_rate_mbps = IbStaticRateToMbps(rate); + + if (static_rate_mbps >= link_rate_mbps) + return 0; /* 100% speed */ + /* round up to handle odd ones like 8x rate over 12x link */ + return ((link_rate_mbps + (static_rate_mbps-1))/ static_rate_mbps) - 1; +} + +/* convert InterPacketDelay (IPD) to static rate */ +static __inline IB_STATIC_RATE +IbIpdToStaticRate(uint8 ipd, IB_LINK_WIDTH linkWidth, IB_LINK_SPEED linkSpeed) +{ + uint32 link_rate_mbps = IbLinkWidthToInt(linkWidth)*IbLinkSpeedToMbps(linkSpeed); + return IbMbpsToStaticRate(link_rate_mbps/(ipd+1)); +} + +/* convert IB_PORT_ATTRIBUTES.ActiveWidth to IB_LINK_WIDTH */ +static __inline IB_LINK_WIDTH +IbPortWidthToLinkWidth(uint8 width) +{ + switch (width) { + case PORT_WIDTH_1X: + return IB_LINK_WIDTH_1X; + default: + case PORT_WIDTH_4X: + return IB_LINK_WIDTH_4X; + case PORT_WIDTH_8X: + return IB_LINK_WIDTH_8X; + case PORT_WIDTH_12X: + return IB_LINK_WIDTH_12X; + } +} + +/* convert IB_PORT_ATTRIBUTES.ActiveSpeed to IB_LINK_SPEED */ +static __inline IB_LINK_SPEED +IbPortSpeedToLinkSpeed(uint8 speed) +{ + switch (speed) { + default: + case PORT_SPEED_2_5G: + return IB_LINK_SPEED_2_5G; + case PORT_SPEED_5G: + return IB_LINK_SPEED_5G; + case PORT_SPEED_10G: + return IB_LINK_SPEED_10G; + case PORT_SPEED_14G: + return IB_LINK_SPEED_14G; + case PORT_SPEED_25G: + return IB_LINK_SPEED_25G; + } +} + +/* convert IB_PORT_ATTRIBUTES.ActiveSpeed and ActiveWidth to Mbps */ +static __inline uint32 +IbPortSpeedWidthToMbps(uint8 speed, uint8 width) +{ + return IbLinkSpeedToMbps(IbPortSpeedToLinkSpeed(speed)) + * IbLinkWidthToInt(IbPortWidthToLinkWidth(width)); +} + +/* convert IB_PORT_ATTRIBUTES.ActiveSpeed and ActiveWidth to Static Rate */ +static __inline IB_STATIC_RATE +IbPortSpeedWidthToStaticRate(uint8 speed, uint8 width) +{ + return IbMbpsToStaticRate(IbPortSpeedWidthToMbps(speed, width)); +} + +// combine LinkSpeedActive and LinkSpeedExtActive +static __inline uint8 +PortDataGetLinkSpeedActiveCombined(PORT_INFO *portInfop) +{ + uint8 speed = portInfop->LinkSpeed.Active & 0x0F; + if (portInfop->CapabilityMask.s.IsExtendedSpeedsSupported) + speed |= (portInfop->LinkSpeedExt.Active << 4); + return(speed); +} + +// split LinkSpeedActive into LinkSpeedActive and LinkSpeedExtActive +static __inline void +PortDataSetLinkSpeedActiveSplit(uint8 speed, PORT_INFO *portInfop) +{ + portInfop->LinkSpeed.Active = speed & 0x0F; + portInfop->LinkSpeedExt.Active = speed >> 4; +} + +// combine LinkSpeedSupported and LinkSpeedExtSupported +static __inline uint8 +PortDataGetLinkSpeedSupportedCombined(PORT_INFO *portInfop) +{ + uint8 speed = portInfop->Link.SpeedSupported & 0x0F; + if (portInfop->CapabilityMask.s.IsExtendedSpeedsSupported) + speed |= (portInfop->LinkSpeedExt.Supported << 4); + return(speed); +} + +// split LinkSpeedSupported into LinkSpeedSupported and LinkSpeedExtSupported +static __inline void +PortDataSetLinkSpeedSupportedSplit(uint8 speed, PORT_INFO *portInfop) +{ + portInfop->Link.SpeedSupported = speed & 0x0F; + portInfop->LinkSpeedExt.Supported = speed >> 4; +} + +// combine LinkSpeedEnabled and LinkSpeedExtEnabled +static __inline uint8 +PortDataGetLinkSpeedEnabledCombined(PORT_INFO *portInfop) +{ + uint8 speed = portInfop->LinkSpeed.Enabled & 0x0F; + if (portInfop->CapabilityMask.s.IsExtendedSpeedsSupported) + speed |= (portInfop->LinkSpeedExt.Enabled << 4); + return(speed); +} + +// split LinkSpeedEnabled into LinkSpeedEnabled and LinkSpeedExtEnabled +static __inline void +PortDataSetLinkSpeedEnabledSplit(uint8 speed, PORT_INFO *portInfop) +{ + portInfop->LinkSpeed.Enabled = speed & 0x0F; + portInfop->LinkSpeedExt.Enabled = speed >> 4; +} + +/* convert Notice Type to text */ +static __inline const char* +IbNoticeTypeToText(IB_NOTICE_TYPE type) +{ + return (type == IB_NOTICE_FATAL? "Fatal": + type == IB_NOTICE_URGENT? "Urgent": + type == IB_NOTICE_SECURITY? "Security": + type == IB_NOTICE_SM? "SM": + type == IB_NOTICE_INFO? "Info": + type == IB_NOTICE_ALL? "All": "???"); +} + +/* convert MKey protect selection to text */ +static __inline const char* +IbMKeyProtectToText(IB_MKEY_PROTECT protect) +{ + return (protect == IB_MKEY_PROTECT_RO)?"Read-only": + (protect == IB_MKEY_PROTECT_HIDE)?"Hide": + (protect == IB_MKEY_PROTECT_SECURE)?"Secure":"????"; +} + +/* TBD - come back and do these a little more efficiently with a + * global array indexed by timeout_mult + */ + +#define IB_MAX_TIMEOUT_MULT_MS 8796093 /* 2.4 hr */ + +/* Convert Timeout value from 4.096usec * 2^timeout_mult + * to ms (which is units for Timers in Public) + */ +static __inline +uint32 TimeoutMultToTimeInMs(uint32 timeout_mult) +{ + /* all values are rounded up, comments reflect exact value */ + switch (timeout_mult) + { + case 0: + case 1: + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + return 1; /* < 1 ms, round up */ + case 8: + return 2; /* 1.048 ms */ + case 9: + return 3; /* 2.097 ms */ + case 10: + return 5; /* 4.197 ms */ + case 11: + return 9; /* 8.388 ms */ + case 12: + return 17; /* 16.777 ms */ + case 13: + return 34; /* 33.554 ms */ + case 14: + return 68; /* 67.1 ms */ + case 15: + return 135; /* 134.2 ms */ + case 16: + return 269; /* 268.4 ms */ + case 17: + return 537; /* 536.8 ms */ + case 18: + return 1074;/* 1.073 s */ + case 19: + return 2148;/* 2.148 s */ + case 20: + return 4295;/* 4.294 s */ + case 21: + return 8590;/* 8.589 s */ + case 22: + return 17180;/* 17.179 s */ + case 23: + return 34359;/* 34.359 s */ + case 24: + return 68720;/* 68.719 s */ + case 25: + return 137438;/* 2.2 minutes */ + case 26: + return 274877; /* 4.5 minutes */ + case 27: + return 549755; /* 9 minutes */ + case 28: + return 1099511; /* 18 minutes */ + case 29: + return 2199023; /* 0.6 hr */ + case 30: + return 4398046; /* 1.2 hr */ + default: /* PktLifeTime allows 6 bits in PathRecord */ + /* but anything beyond 2 hrs is an eternity */ + case 31: + return 8796093; /* 2.4 hr */ + } +} + +/* Convert Timeout value from 4.096usec * 2^timeout_mult to usec */ +static __inline +uint64 TimeoutMultToTimeInUsec(uint32 timeout_mult) +{ + /* all values are rounded up, comments reflect exact value */ + switch (timeout_mult) + { + case 0: + return 5; /* 4.096 usec */ + case 1: + return 9; /* 8.192 usec */ + case 2: + return 17; /* 16.384 usec */ + case 3: + return 33; /* 32.768 usec */ + case 4: + return 66; /* 65.536 usec */ + case 5: + return 132; /* 131.072 usec */ + case 6: + return 263; /* 262.144 usec */ + case 7: + return 525; /* 524.288 usec */ + case 8: + return 1048; /* 1.048 ms */ + case 9: + return 2097; /* 2.097 ms */ + case 10: + return 4197; /* 4.197 ms */ + case 11: + return 8388; /* 8.388 ms */ + default: + /* ms accuracy should be good enough for the rest */ + return ((uint64)TimeoutMultToTimeInMs(timeout_mult)*(uint64)1000); + } +} + +/* convert capability mask into a text representation */ +static __inline +void FormatCapabilityMask(char buf[80], IB_CAPABILITY_MASK cmask) +{ + snprintf(buf, 80, "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s", + cmask.s.IsClientReregistrationSupported?"CR ": "", + cmask.s.IsLinkRoundTripLatencySupported?"LR ": "", + cmask.s.IsBootManagementSupported?"BT ": "", + cmask.s.IsCapabilityMaskNoticeSupported?"CN ": "", + cmask.s.IsDRNoticeSupported?"DN ": "", + cmask.s.IsVendorClassSupported?"VDR ": "", + cmask.s.IsDeviceManagementSupported?"DM ": "", + cmask.s.IsReinitSupported?"RI ": "", + cmask.s.IsSNMPTunnelingSupported?"SNMP ": "", + cmask.s.IsConnectionManagementSupported?"CM ": "", + cmask.s.IsPKeySwitchExternalPortTrapSupported?"PST ": "", + cmask.s.IsSystemImageGuidSupported?"SIG ": "", + cmask.s.IsSMDisabled?"SMD ": "", + cmask.s.IsLEDInfoSupported?"LED ": "", + cmask.s.IsPKeyNVRAM?"PK ": "", + cmask.s.IsMKeyNVRAM?"MK ": "", + cmask.s.IsSLMappingSupported?"SL ": "", + cmask.s.IsAutomaticMigrationSupported?"APM ": "", + cmask.s.IsTrapSupported?"Trap ": "", + cmask.s.IsNoticeSupported?"Not ": "", + cmask.s.IsSM?"SM ": ""); +} + +#define FORMAT_MULT_THRESHOLD_FRACTION 1000 /* for fractions of a second */ +#define FORMAT_MULT_THRESHOLD 180 /* for seconds and minutes */ + +/* convert 4.096us*2^timeout to a reasonable value + * and format into a buffer as #### uu + * where uu is units and timeout is limited to 31 + * buffer will be exactly 7 characters + terminating \0 + */ +static __inline +void FormatTimeoutMult(char buf[8], uint8 timeout) +{ + uint64 time64 = 4096 * ((uint64)1<NumPkeys; i++ ) + { + /* Check for invalid PKey values. Invalid values have */ + /* the lower 15 bits set to zero. */ + if( !(pPortAttr->PkeyTable[i] & 0x7FFF) ) + continue; + + /* Compare the PKey value in the port's PKey table with */ + /* the value provided. */ + if( ((pPortAttr->PkeyTable[i] & 0xffff) == (PKeyValue & 0xffff)) ) + { + /* We found a match on the value. Copy the PKey index. */ + if( pPKeyIndex ) + *pPKeyIndex = i; + return TRUE; + } + } + + return FALSE; +} + +/* + * Returns TRUE if the PKey value is found in the specified port attributes. + * Sets the PKeyIndex output value, if any, if a match is found. + */ +static __inline boolean +LookupPKey( + IN const IB_PORT_ATTRIBUTES* const pPortAttr, + IN const IB_P_KEY PKeyValue, + IN const boolean masked, + OUT uint16* const pPKeyIndex OPTIONAL ) +{ + uint16 i; + uint16 mask = masked?0x7fff:0xffff; + + /* Search for the PKey index for the PKey value provided. */ + for( i = 0; i < pPortAttr->NumPkeys; i++ ) + { + /* Check for invalid PKey values. Invalid values have */ + /* the lower 15 bits set to zero. */ + if( !(pPortAttr->PkeyTable[i] & 0x7FFF) ) + continue; + + /* Compare the PKey value in the port's PKey table with */ + /* the value provided. */ + if( (pPortAttr->PkeyTable[i] & mask) == (PKeyValue & mask) ) + { + /* We found a match on the value. Copy the PKey index. */ + if( pPKeyIndex ) + *pPKeyIndex = i; + return TRUE; + } + } + + return FALSE; +} + +/* + * Return GID index if the GID is valid for the specified port attributes. + * Return -1 if invalid/not configured + */ +static __inline int32 +GetGidIndex( + IN const IB_PORT_ATTRIBUTES* const pPortAttr, + IN const IB_GID* const pGid ) +{ + uint8 i; + + /* Compare the port's GIDs to see if the requested GID matches. */ + for( i = 0; i < pPortAttr->NumGIDs; i++ ) + { + /* workaround SM's which forget to specify SubnetPrefix */ + if (pPortAttr->GIDTable[i].Type.Global.SubnetPrefix == 0) + { + if (pPortAttr->GIDTable[i].Type.Global.InterfaceID == + pGid->Type.Global.InterfaceID) + { + return i; + } + } else { + if( !MemoryCompare( &pPortAttr->GIDTable[i], + pGid, sizeof( IB_GID ) ) ) + { + return i; + } + } + } + + return -1; +} + +/* non-Wildcarded compare of 2 64 bit values + * Return: + * 0 : v1 == v2 + * -1: v1 < v2 + * 1 : v1 > v2 + */ +static __inline int +CompareU64(uint64 v1, uint64 v2) +{ + if (v1 == v2) + return 0; + else if (v1 < v2) + return -1; + else + return 1; +} + +/* Wildcarded compare of 2 64 bit values + * Return: + * 0 : v1 == v2 + * -1: v1 < v2 + * 1 : v1 > v2 + * if v1 or v2 is 0, they are considered wildcards and match any value + */ +static __inline int +WildcardCompareU64(uint64 v1, uint64 v2) +{ + if (v1 == 0 || v2 == 0 || v1 == v2) + return 0; + else if (v1 < v2) + return -1; + else + return 1; +} + +/* Compare Gid1 to Gid2 (host byte order) + * Return: + * 0 : Gid1 == Gid2 + * -1: Gid1 < Gid2 + * 1 : Gid1 > Gid2 + * This also allows for Wildcarded compare. + * A MC Gid with the lower 56 bits all 0, will match any MC gid + * A SubnetPrefix of 0 will match any top 64 bits of a non-MC gid + * A InterfaceID of 0 will match any low 64 bits of a non-MC gid + * Coallating order: + * non-MC Subnet Prefix (0 is wildcard and comes first) + * non-MC Interface ID (0 is wilcard and comes first) + * MC wildcard + * MC by value of low 56 bits (0 is wildcard and comes first) + */ +static __inline int +WildcardGidCompare(IN const IB_GID* const pGid1, IN const IB_GID* const pGid2 ) +{ + if (pGid1->Type.Multicast.s.FormatPrefix == IPV6_MULTICAST_PREFIX + && pGid2->Type.Multicast.s.FormatPrefix == IPV6_MULTICAST_PREFIX) + { + /* Multicast compare: compare low 120 bits, 120 bits of 0 is wildcard */ + uint64 h1 = pGid1->AsReg64s.H & ~IB_GID_MCAST_FORMAT_MASK_H; + uint64 h2 = pGid2->AsReg64s.H & ~IB_GID_MCAST_FORMAT_MASK_H; + /* check for 120 bits of wildcard */ + if ((h1 == 0 && pGid1->AsReg64s.L == 0) + || (h2 == 0 && pGid2->AsReg64s.L == 0)) + { + return 0; + } else if (h1 < h2) { + return -1; + } else if (h1 > h2) { + return 1; + } else { + return CompareU64(pGid1->AsReg64s.L, pGid1->AsReg64s.L); + } + } else if (pGid1->Type.Multicast.s.FormatPrefix == IPV6_MULTICAST_PREFIX) { + /* Gid1 is MC, Gid2 is other, treat MC as > others */ + return 1; + } else if (pGid2->Type.Multicast.s.FormatPrefix == IPV6_MULTICAST_PREFIX) { + /* Gid1 is other, Gid2 is MC, treat other as < MC */ + return -1; + } else { + /* Non-Multicast compare: compare high 64 bits */ + /* Note all other GID formats are essentially a prefix in upper */ + /* 64 bits and a identifier in the low 64 bits */ + /* so this covers link local, site local, global formats */ + int res = WildcardCompareU64(pGid1->AsReg64s.H, pGid2->AsReg64s.H); + if (res == 0) + { + return WildcardCompareU64(pGid1->AsReg64s.L, pGid2->AsReg64s.L); + } else { + return res; + } + } +} + +/* Compute the size of the port attributes structure in src + * It is assumed that the GID and PKey tables are after src + * Typically port attributes lists for a CA should be structured as: + * Port 1 Attributes + * Port 1 GID and PKey Tables + * Port 2 Attributes + * Port 2 GID and PKey Tables + * etc + */ +static __inline uint32 +IbPortAttributesSize(IN const IB_PORT_ATTRIBUTES* ptr) +{ + uint32 result, temp; + + /* this is best case size */ + result = sizeof(IB_PORT_ATTRIBUTES) + + sizeof(IB_GID) * ptr->NumGIDs + + sizeof(IB_P_KEY) * ptr->NumPkeys; + /* however VPD could add pad bytes for alignment */ + temp = (uint8*)(ptr->GIDTable + ptr->NumGIDs) - (uint8*)ptr; + result = MAX(result, temp); + temp = (uint8*)(ptr->PkeyTable + ptr->NumPkeys) - (uint8*)ptr; + result = MAX(result, temp); + return result; +} + +/* Copy the port attributes structure from src to dest for size bytes + * size must be computed using a function such as IbPortAttributesSize above. + * It is assumed that the GID and PKey tables are within size bytes from src. + * Typically port attributes lists for a CA should be structured as: + * Port 1 Attributes + * Port 1 GID and PKey Tables + * Port 2 Attributes + * Port 2 GID and PKey Tables + * etc + * dest->Next is set to NULL, caller must initialize if there is a Next + */ +static __inline void +IbCopyPortAttributes( + OUT IB_PORT_ATTRIBUTES *dest, + IN const IB_PORT_ATTRIBUTES* src, + IN uint32 size + ) +{ + MemoryCopy(dest, src, size); + dest->GIDTable = (IB_GID *)((uintn)dest + ((uintn)src->GIDTable - (uintn)src)); + dest->PkeyTable = (IB_P_KEY *)((uintn)dest + ((uintn)src->PkeyTable - (uintn)src)); + /*dest->Next = (IB_PORT_ATTRIBUTES*)((uintn)dest + size);*/ + dest->Next = NULL; +} + +#undef IbmbpsToMBps +#undef IbmbpsToMBpsExt + +#ifdef __cplusplus +}; +#endif + +#endif /* _IBA_IB_HELPER_H_ */ diff --git a/IbAccess/Common/Inc/ib_ibt.h b/IbAccess/Common/Inc/ib_ibt.h new file mode 100644 index 0000000..323b126 --- /dev/null +++ b/IbAccess/Common/Inc/ib_ibt.h @@ -0,0 +1,641 @@ +/* BEGIN_ICS_COPYRIGHT3 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT3 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +#ifndef __IBA_IB_IBT_H__ +#define __IBA_IB_IBT_H__ (1) + +#include "iba/stl_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * IB notification routines + */ + +/* + * Bit masks for event types subscribed and generated + */ + +typedef uintn IB_NOTIFY_TYPE; + +#define IB_NOTIFY_CA_ADD 0x00000001 /* A new adapter was added */ +#define IB_NOTIFY_CA_REMOVE 0x00000002 /* An adapter is being removed */ +#define IB_NOTIFY_PORT_DOWN 0x00000004 /* Link went down, sync loss */ +#define IB_NOTIFY_LID_EVENT 0x00000008 /* The specified port had a */ + /* LID/state/LMC change */ +#define IB_NOTIFY_SM_EVENT 0x00000010 /* A Subnet Manager has */ + /* programmed specified port */ +#define IB_NOTIFY_PKEY_EVENT 0x00000020 /* The Pkey for the specified */ + /* port has changed */ +#define IB_NOTIFY_PORT_UP 0x00000040 /* Link went up */ +#define IB_NOTIFY_ON_REGISTER 0x80000000 /* Notify immediately during */ + /* Registration of any */ + /* present state (eg. CA_ADD */ + /* for all active CAs and */ + /* LID_EVENT for all active */ + /* ports) */ +#define IB_NOTIFY_ANY 0x7FFFFFFF /* Receive notification for */ + /* all event types */ + /* note IB_NOTIFY_ON_REGISTER */ + /* is not included in this flag */ + +/* Notification callback style + * async - no locks are held during callback: + * - callback can deregister or do any other operations + * - callback could occur slightly after deregister, caller must handle + * sync - a lock is held during callback: + * - callback cannot deregister or do operations which may cause a notification + * (eg. send packets to local SMA) + * - callbacks will not occur after deregister + */ +typedef enum { + IB_NOTIFY_ASYNC, + IB_NOTIFY_SYNC +} IB_NOTIFY_LOCKING; + + +/* + * Notification record passed during a callback + */ + +typedef struct { + IB_NOTIFY_TYPE EventType; /* Type of event being reported */ + EUI64 Guid; /* Port/Node GUID, depends on event type */ + void *Context; /* User Context that was supplied */ + /* during the registration */ +} IB_NOTIFY_RECORD; + + +typedef +void +( *IB_NOTIFY_CALLBACK ) ( + IN IB_NOTIFY_RECORD NotifyRecord + ); + +/* + * iba_register_notify/RegisterNotify + * + * register for notifications of IB type events + * + * INPUTS: + * + * Callback -Callback routine to be registered for notifications + * Context -User specified context to return in callbacks + * EventMask -Mask to subscribe to event types + * Locking -Locking/Synchronization model + * + * OUTPUTS: + * + * NotifyHandle -Notification handle on successful registration + * + * RETURNS: + * + * FSUCCESS + * FINSUFFICIENT_MEMORY + */ + +typedef +FSTATUS +(IBT_REGISTER_NOTIFY) ( + IN IB_NOTIFY_CALLBACK Callback, + IN void *Context, + IN IB_NOTIFY_TYPE EventMask, + IN IB_NOTIFY_LOCKING Locking, + OUT IB_HANDLE *NotifyHandle + ); +IBA_API IBT_REGISTER_NOTIFY iba_register_notify; + + +/* + * iba_register_guid_notify/RegisterGuidNotify + * + * register for notifications of IB type events against a specific Node/Port + * Guid + * + * + * INPUTS: + * + * Guid -Guid to limit events to + * (Node Guid for CA events, Port Guid for other events) + * Callback -Callback routine to be registered for notifications + * Context -User specified context to return in callbacks + * EventMask -Mask to subscribe to event types + * Locking -Locking/Synchronization model + * + * OUTPUTS: + * + * NotifyHandle -Notification handle on successful registration + * + * RETURNS: + * + * FSUCCESS + * FINSUFFICIENT_MEMORY + * + */ + +typedef +FSTATUS +(IBT_REGISTER_GUID_NOTIFY) ( + IN EUI64 Guid, + IN IB_NOTIFY_CALLBACK Callback, + IN void *Context, + IN IB_NOTIFY_TYPE EventMask, + IN IB_NOTIFY_LOCKING Locking, + OUT IB_HANDLE *NotifyHandle + ); +IBA_API IBT_REGISTER_GUID_NOTIFY iba_register_guid_notify; + +/* + * iba_deregister_notify/DeregisterNotify + * + * Deregister previously registered notifications + * + * INPUTS: + * + * NotifyHandle -Notification handle returned on successful registration + * + * OUTPUTS: + * + * + * RETURNS: + * + * FSUCCESS + * FINVALID_PARAMETER + * FINSUFFICIENT_MEMORY + */ + +typedef +FSTATUS +(IBT_DEREGISTER_NOTIFY) ( + IN IB_HANDLE NotifyHandle + ); +IBA_API IBT_DEREGISTER_NOTIFY iba_deregister_notify; + +/* + * iba_get_caguids/GetCaGuids + * + * Get the list of CA's presently in the system + * + * INPUTS: + * CaCount - size of CaGuidList + * data pointed to only used during duration of call + * + * OUTPUTS: + * CaCount - total CAs in system (always returned, even if error status) + * CaGuidList - where to save CA Guids + * + * RETURNS: + * FINSUFFICIENT_MEMORY - CaGuidList too small for # of CAs in system + * FINVALID_PARAMETER - CaGuidList is NULL and CaCount was not 0 + */ + +typedef +FSTATUS +(IBT_GET_CA_GUIDS)( + IN OUT uint32 *CaCount, + OUT EUI64 *CaGuidList + ); +IBA_API IBT_GET_CA_GUIDS iba_get_caguids; + +/* + * iba_get_caguids_alloc/GetCaGuidsAlloc + * + * Get the list of CA's presently in the system and allocate *CaGuidList + * caller must MemoryDeallocate *CaGuidList + * + * INPUTS: + * + * OUTPUTS: + * CaCount - total CAs in system (always returned, even if error status) + * CaGuidList - where to save CA Guids + * + * RETURNS: + * FINSUFFICIENT_RESOURCES - can't allocate memory for list + * FINVALID_PARAMETER - CaCount or CaGuidList is NULL + */ + +typedef +FSTATUS +(IBT_GET_CA_GUIDS_ALLOC)( + OUT uint32 *CaCount, + OUT EUI64 **CaGuidList + ); +IBA_API IBT_GET_CA_GUIDS_ALLOC iba_get_caguids_alloc; + +/* + * iba_query_ca_by_guid/QueryCaByGuid + * + * Get CA attributes for CA with given Guid + * + * INPUTS: + * CaGuid - CA to query + * + * OUTPUTS: + * CaAttributes + * + * RETURNS: + * FINVALID_PARAMETER - CaAttributes is NULL + * FNOT_FOUND - no such CA + * otherwise status of QueryCA is returned + */ + +typedef +FSTATUS +(IBT_QUERY_CA_BY_GUID)( + IN EUI64 CaGuid, + OUT IB_CA_ATTRIBUTES *CaAttributes + ); +IBA_API IBT_QUERY_CA_BY_GUID iba_query_ca_by_guid; + +/* + * iba_query_ca_by_guid_alloc/QueryCaByGuidAlloc + * + * Get CA attributes for CA with given Guid and allocate + * CaAttributes->PortAttributesList + * caller must MemoryDeallocate CaAttributes->PortAttributesList + * + * INPUTS: + * CaGuid - CA to query + * + * OUTPUTS: + * CaAttributes + * + * RETURNS: + * FINVALID_PARAMETER - CaAttributes is NULL + * FNOT_FOUND - no such CA + * otherwise status of QueryCA is returned: + * FINSUFFICIENT_MEMORY - PortAttributesListSize too small + * ca attributes returned, but not port attributes + * FSUCCESS - ca and port attributes returned + */ + +typedef +FSTATUS +(IBT_QUERY_CA_BY_GUID_ALLOC)( + IN EUI64 CaGuid, + OUT IB_CA_ATTRIBUTES *CaAttributes + ); +IBA_API IBT_QUERY_CA_BY_GUID_ALLOC iba_query_ca_by_guid_alloc; + +/* + * iba_query_port_by_guid/QueryPortByGuid + * + * Get Port attributes for CA Port with given Guid + * + * INPUTS: + * PortGuid - CA Port to query + * ByteCount - size of PortAttributes + * + * OUTPUTS: + * PortAttributes + * ByteCount - space needed to hold PortAttributes + * + * RETURNS: + * FINSUFFICIENT_MEMORY - ByteCount insufficient + * FINSUFFICIENT_RESOURCES - unable to allocate internal memory needed + * FINVALID_PARAMETER - PortAttributes is NULL + * FNOT_FOUND - no such CA Port + * otherwise status of QueryCA is returned + */ + +typedef +FSTATUS +(IBT_QUERY_PORT_BY_GUID)( + IN EUI64 PortGuid, + OUT IB_PORT_ATTRIBUTES *PortAttributes, + IN OUT uint32 *ByteCount + ); +IBA_API IBT_QUERY_PORT_BY_GUID iba_query_port_by_guid; + +/* + * iba_query_port_by_guid/QueryPortByGuid + * + * Get Port attributes for CA Port with given Guid and allocate + * *PortAttributes + * caller must MemoryDeallocate *PortAttributes + * + * INPUTS: + * PortGuid - CA Port to query + * + * OUTPUTS: + * *PortAttributes + * + * RETURNS: + * FINSUFFICIENT_MEMORY - ByteCount insufficient + * FINSUFFICIENT_RESOURCES - unable to allocate internal memory needed + * FINVALID_PARAMETER - PortAttributes is NULL + * FNOT_FOUND - no such CA Port + * otherwise status of QueryCA is returned + */ + +typedef +FSTATUS +(IBT_QUERY_PORT_BY_GUID_ALLOC)( + IN EUI64 PortGuid, + OUT IB_PORT_ATTRIBUTES **PortAttributes + ); +IBA_API IBT_QUERY_PORT_BY_GUID_ALLOC iba_query_port_by_guid_alloc; + +/* translate port number into a port Guid + * + * INPUTS: + * caGuid - CA to check against + * port - 1-n, port within CA + * if 0, 1st active port + * + * OUTPUTS: + * *pPortGuid - port guid for specified port + * *pCaAttributes - attributes for CA, + * caller must MemoryDeallocate pCaAttributes->PortAttributesList + * *ppPortAtributes - attributes for port, caller must MemoryDeallocate + * *pPortCount - number of ports in CA + * + * RETURNS: + * FNOT_FOUND - *pPortCount still output + */ +typedef +FSTATUS +(IBT_GET_CA_PORTGUID)( + IN EUI64 caGuid, + IN uint32 port, + OUT EUI64 *pPortGuid OPTIONAL, + OUT IB_CA_ATTRIBUTES *pCaAttributes OPTIONAL, + OUT IB_PORT_ATTRIBUTES **ppPortAttributes OPTIONAL, + OUT uint32 *pPortCount OPTIONAL + ); +IBA_API IBT_GET_CA_PORTGUID iba_get_ca_portguid; + +/* translate ca/port number into a port Guid + * + * INPUTS: + * ca - system wide CA number 1-n, if 0 port is a system wide port # + * port - 1-n, if ca is 0, system wide port number, otherwise port within CA + * if 0, 1st active port + * + * OUTPUTS: + * *pCaGuid - ca guid for specified port + * *pPortGuid - port guid for specified port + * *pCaAttributes - attributes for CA, + * caller must MemoryDeallocate pCaAttributes->PortAttributesList + * *ppPortAtributes - attributes for port, caller must MemoryDeallocate + * *pCaCount - number of CA in system + * *pPortCount - number of ports in system or CA (depends on ca input) + * + * RETURNS: + * FNOT_FOUND - *pCaCount and *pPortCount still output + * if ca == 0, *pPortCount = number of ports in system + * if ca < *pCaCount, *pPortCount = number of ports in CA + * otherwise *pPortCount will be 0 + */ +typedef +FSTATUS +IBT_GET_PORTGUID( + IN uint32 ca, + IN uint32 port, + OUT EUI64 *pCaGuid OPTIONAL, + OUT EUI64 *pPortGuid OPTIONAL, + OUT IB_CA_ATTRIBUTES *pCaAttributes OPTIONAL, + OUT IB_PORT_ATTRIBUTES **ppPortAttributes OPTIONAL, + OUT uint32 *pCaCount OPTIONAL, + OUT uint32 *pPortCount OPTIONAL + ); +IBA_API IBT_GET_PORTGUID iba_get_portguid; + +/* format an error message when iba_get_portguid returns FNOT_FOUND + * + * INPUTS: + * ca, port - inputs provided to failed call to iba_get_portguid + * CaCount, PortCount - outputs returned by failed call to iba_get_portguid + * + * RETURNS: + * string formatted with error message. This is a pointer into a static + * string which will be invalidated upon next call to this function. + */ +typedef +const char* +IBT_FORMAT_GET_PORTGUID_ERROR( + IN uint32 ca, + IN uint32 port, + IN uint32 CaCount, + IN uint32 PortCount + ); +IBA_API IBT_FORMAT_GET_PORTGUID_ERROR iba_format_get_portguid_error; + +/* + * iba_find_ca_gid/FindCaGid + * + * search Ports of a given CA to find the Port with the matching GID + * + * INPUTS: + * pGid - GID to search for + * data pointed to only used during duration of call + * CaGuid - CA to search + * + * OUTPUTS: + * pPortGuid - port which GID was found on + * pGidIndex - index of GID within ports GID Table + * PortAttributes - attributes of port (caller must MemoryDeallocate) + * LocalCaAckDelay - corresponding field from CaAttributes + * + * RETURNS: + * FINSUFFICIENT_MEMORY - unable to allocate internal memory needed + * FINSUFFICIENT_RESOURCES - unable to allocate internal memory needed + * FNOT_FOUND - no such CA Port or no such CA + * otherwise status of QueryCA is returned + */ + +typedef +FSTATUS +(IBT_FIND_CA_GID)( + IN const IB_GID *pGid, + IN EUI64 CaGuid, + OUT EUI64 *pPortGuid OPTIONAL, + OUT uint8 *pGidIndex OPTIONAL, + OUT IB_PORT_ATTRIBUTES **PortAttributes OPTIONAL, + OUT uint8 *pLocalCaAckDelay OPTIONAL + ); +IBA_API IBT_FIND_CA_GID iba_find_ca_gid; + +/* + * iba_find_ca_gid2/FindCaGid2 + * + * search Ports of a given CA to find the Port with the matching GID + * + * INPUTS: + * pGid - GID to search for + * data pointed to only used during duration of call + * CaGuid - CA to search + * + * OUTPUTS: + * pPortGuid - port which GID was found on + * pGidIndex - index of GID within ports GID Table + * PortAttributes - attributes of port (caller must MemoryDeallocate) + * CaAttributes - CaAttributes (caller must MemoryDeallocate) + * + * RETURNS: + * FINSUFFICIENT_MEMORY - unable to allocate internal memory needed + * FINSUFFICIENT_RESOURCES - unable to allocate internal memory needed + * FNOT_FOUND - no such CA Port or no such CA + * otherwise status of QueryCA is returned + */ + +typedef +FSTATUS +(IBT_FIND_CA_GID2)( + IN const IB_GID *pGid, + IN EUI64 CaGuid, + OUT EUI64 *pPortGuid OPTIONAL, + OUT uint8 *pGidIndex OPTIONAL, + OUT IB_PORT_ATTRIBUTES **PortAttributes OPTIONAL, + OUT IB_CA_ATTRIBUTES **CaAttributes OPTIONAL + ); +IBA_API IBT_FIND_CA_GID2 iba_find_ca_gid2; + +/* + * iba_find_gid + * + * search Ports of all CAs to find the CA/Port with the matching GID + * + * INPUTS: + * pGid - GID to search for + * data pointed to only used during duration of call + * + * OUTPUTS: + * pCaGuid - CA which GID was found on + * pPortGuid - port which GID was found on + * pGidIndex - index of GID within ports GID Table + * PortAttributes - attributes of port (caller must MemoryDeallocate) + * CaAttributes - CaAttributes (caller must MemoryDeallocate) + * + * RETURNS: + * FINSUFFICIENT_MEMORY - unable to allocate internal memory needed + * FINSUFFICIENT_RESOURCES - unable to allocate internal memory needed + * FNOT_FOUND - no such CA Port + * otherwise status of QueryCA is returned + */ + +typedef +FSTATUS +(IBT_FIND_GID)( + IN const IB_GID *pGid, + OUT EUI64 *pCaGuid OPTIONAL, + OUT EUI64 *pPortGuid OPTIONAL, + OUT uint8 *pGidIndex OPTIONAL, + OUT IB_PORT_ATTRIBUTES **PortAttributes OPTIONAL, + OUT IB_CA_ATTRIBUTES **CaAttributes OPTIONAL + ); +IBA_API IBT_FIND_GID iba_find_gid; + +/* + * iba_get_ca_for_port/GetCaForPort + * + * Get CA Guid for given Port Guid + * + * INPUTS: + * PortGuid - Port to find CA for + * + * OUTPUTS: + * CaGuid - CA Guid for given port + * + * RETURNS: + * FINSUFFICIENT_RESOURCES - unable to allocate internal memory needed + * FNOT_FOUND - no such CA Port + * otherwise status of QueryCA is returned + */ + +typedef +FSTATUS +(IBT_GET_CA_FOR_PORT)( + IN EUI64 PortGuid, + OUT EUI64 *CaGuid + ); +IBA_API IBT_GET_CA_FOR_PORT iba_get_ca_for_port; + +/* + * iba_select_ca + * + * Track CA/ports being heavily used and aid in selection of least used one + * Usage models: + * pCaGuid = NULL invalid call + * *pCaGuid !=0 caller has specified a CA, API increases its count + * *pCaGuid ==0 API will recommend a CA and increase its count + * + * INPUTS: + * *pCaGuid - CA caller plans to use + * + * OUTPUTS: + * *pCaGuid - CA recommended for use (matches supplied *pCaGuid if input != 0) + * + * RETURNS: + * FNOT_FOUND - no such CA + * FINVALID_PARAMETER - invalid combination of arguments + * FINSUFFICIENT_RESOURCES - no CAs in system with active ports + * FERROR - other errors (unable to query CA attributes, etc) + */ + +typedef +FSTATUS +(IBT_SELECT_CA)( + IN OUT EUI64 *pCaGuid + ); +IBA_API IBT_SELECT_CA iba_select_ca; + +/* + * iba_deselect_ca + * + * undo effects of iba_select_ca + * call should match the CaGUID from a previous iba_select_ca call + * + * INPUTS: + * CaGuid - CA output/selected via iba_select_ca + * + * OUTPUTS: + * None + * + * RETURNS: + * FNOT_FOUND - no such CA or Port, or PortGuid not within specified CA + * FINVALID_OPERATION - would result in negative use count + */ + +typedef +FSTATUS +(IBT_DESELECT_CA)( + IN EUI64 CaGuid + ); +IBA_API IBT_DESELECT_CA iba_deselect_ca; + +#ifdef __cplusplus +}; +#endif + +#endif /* __IBA_IB_IBT_H__ */ diff --git a/IbAccess/Common/Inc/ib_mad.h b/IbAccess/Common/Inc/ib_mad.h new file mode 100644 index 0000000..b569781 --- /dev/null +++ b/IbAccess/Common/Inc/ib_mad.h @@ -0,0 +1,788 @@ +/* BEGIN_ICS_COPYRIGHT3 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT3 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +#ifndef __IBA_IB_MAD_H__ +#define __IBA_IB_MAD_H__ + +#include "iba/public/datatypes.h" + +/* Ths should be removed from here */ +#include "iba/stl_types.h" + +#include "iba/public/ibyteswap.h" +#include "iba/public/imemory.h" + +#if defined (__cplusplus) +extern "C" { +#endif + + +#include "iba/public/ipackon.h" + +/* -------------------------------------------------------------------------- + * Defines + */ + +// convert a 0-N bit number to a index and uint8 mask for access to +// multi-byte fields which are stored as uint8[] arrays for long bit masks +// Note for uint16, uint32 bytes, byte swapping has already been done so +// simple (1<common.mr.s.R == 0 \ + && (mad)->common.mr.s.Method != MMTHD_TRAP_REPRESS \ + && (mad)->common.mr.s.Method != MMTHD_SEND) \ + || (((mad)->common.MgmtClass == MCLASS_BM) && \ + ( (mad)->common.mr.s.Method == MMTHD_SEND && !((mad)->common.AttributeModifier & BM_ATTRIB_MOD_RESPONSE)))) + +/* mads for which a GET_RESP should be returned if validation fails */ +#define MAD_EXPECT_GET_RESP(mad) \ + ((mad)->common.mr.s.R == 0 \ + && ((mad)->common.mr.s.Method == MMTHD_GET \ + || (mad)->common.mr.s.Method == MMTHD_SET)) + +/* could optimize and skip MMTHD_SEND test below since R=1 -> != SEND + * however we play it safe in case remote node fails to initialize + * R bit for a SEND message. + */ +#define MAD_IS_RESPONSE(mad) \ + ((((mad)->common.mr.s.R \ + || (mad)->common.mr.s.Method == MMTHD_TRAP_REPRESS) \ + && (mad)->common.mr.s.Method != MMTHD_SEND) \ + || (((mad)->common.MgmtClass == MCLASS_BM) && \ + ((mad)->common.mr.s.Method == MMTHD_SEND && ((mad)->common.AttributeModifier & BM_ATTRIB_MOD_RESPONSE)))) + +/* SENDs are technically a 3rd type, not necessarily a request nor response */ +#define MAD_IS_SEND(mad) \ + ((mad)->common.mr.s.Method == MMTHD_SEND) + +#define MAD_SET_VERSION_INFO(mad, base_ver, mgmt_class, class_ver) {\ + (mad)->common.BaseVersion = base_ver; \ + (mad)->common.MgmtClass = mgmt_class; \ + (mad)->common.ClassVersion = class_ver; \ +} + +#define MAD_GET_VERSION_INFO(mad, base_ver, mgmt_class, class_ver) {\ + (*base_ver) = (mad)->common.BaseVersion; \ + (*mgmt_class) = (mad)->common.MgmtClass; \ + (*class_ver) = (mad)->common.ClassVersion; \ +} + +#define MAD_GET_STATUS(mad, status) {\ + (*status) = (mad)->common.u.NS.Status; \ +} + +#define MAD_SET_TRANSACTION_ID(mad, id) {\ + (mad)->common.TransactionID = id; \ +} + +#define MAD_GET_TRANSACTION_ID(mad, id) {\ + (*id) = (mad)->common.TransactionID; \ +} + +#define MAD_SET_ATTRIB_ID(mad, id) {\ + (mad)->common.AttributeID = id; \ +} + +#define MAD_GET_ATTRIB_ID(mad, id) {\ + (*id) = (mad)->common.AttributeID; \ +} + +#define MAD_SET_ATTRIB_MOD(mad, amod) {\ + (mad)->common.AttributeModifier = amod; \ +} + +#define MAD_GET_ATTRIB_MOD(mad, amod) {\ + (*amod) = (mad)->common.AttributeModifier; \ +} + +#define MAD_SET_METHOD_TYPE(mad, method) {\ + (mad)->common.mr.s.Method = method; \ +} + +#define MAD_GET_METHOD_TYPE(mad, method) {\ + (*method) = (mad)->common.mr.s.Method; \ +} + +/* + * ClassPortInfo + */ + +/* CapMask common bits */ +#define CLASS_PORT_CAPMASK_TRAP 0x0001 /* can generate traps */ +#define CLASS_PORT_CAPMASK_NOTICE 0x0002 /* implements Get/Set Notice */ + +/* mask for class specific bits */ +#define CLASS_PORT_CAPMASK_CLASS_SPECIFIC 0xff00 + +typedef struct _ClassPortInfo{ + uint8 BaseVersion; + uint8 ClassVersion; + uint16 CapMask; + + union { + uint32 AsReg32; + + struct { IB_BITFIELD2(uint32, + CapMask2: 27, + RespTimeValue: 5) + } PACK_SUFFIX s; + } u1; + + /* Define any re-direction. */ + IB_GID RedirectGID; + union { + uint32 AsReg32; + struct { IB_BITFIELD3(uint32, + RedirectTClass: 8, + RedirectSL: 4, + RedirectFlowLabel:20) + } PACK_SUFFIX s; + } u2; + IB_LID RedirectLID; + uint16 Redirect_P_Key; + union { + uint32 AsReg32; + struct { IB_BITFIELD2(uint32, + Reserved2: 8, + RedirectQP: 24) + } PACK_SUFFIX s; + } u3; + uint32 Redirect_Q_Key; + + /* Define any refor traps */ + IB_GID TrapGID; + union { + uint32 AsReg32; + struct { IB_BITFIELD3(uint32, + TrapTClass: 8, + TrapSL: 4, + TrapFlowLabel: 20) + } PACK_SUFFIX s; + } u4; + IB_LID TrapLID; + uint16 Trap_P_Key; + union { + uint32 AsReg32; + struct { IB_BITFIELD2(uint32, + TrapHopLimit: 8, + TrapQP: 24) + } PACK_SUFFIX s; + } u5; + uint32 Trap_Q_Key; + +} PACK_SUFFIX ClassPortInfo, IB_CLASS_PORT_INFO; + +/* Notice */ + +/* Channel adapters, switches, and routers implementing Notice attributes + * shall conform to the definition specified. + */ + +/* + * Node type info + */ +typedef enum _NODE_TYPE { + IBA_NODE_CHANNEL_ADAPTER = 1, + IBA_NODE_SWITCH = 2, + IBA_NODE_ROUTER = 3, +} NODE_TYPE; + + +/* + * Trap/Notice type + */ +typedef enum _NOTICE_TYPE { + IB_NOTICE_FATAL = 0, + IB_NOTICE_URGENT = 1, + IB_NOTICE_SECURITY = 2, + IB_NOTICE_SM = 3, + IB_NOTICE_INFO = 4, + IB_NOTICE_ALL = 0xFFFF +} IB_NOTICE_TYPE; + + + +/* + * Notice + */ +typedef struct _NOTICE { + + union { + /* Generic Notice attributes */ + struct /*_GENERIC*/ { + union { + uint32 AsReg32; + struct { IB_BITFIELD3(uint32, + IsGeneric: 1, /* 1= generic */ + Type : 7, /* IB_NOTICE_TYPE */ + ProducerType:24) /* NODE_TYPE */ + } PACK_SUFFIX s; + } u; + /* If generic, indicates a class-defined trap number. */ + /* Number 0xFFFF is reserved. */ + uint16 TrapNumber; + } PACK_SUFFIX Generic; + + /* Vendor specific Notice attributes */ + struct /*_VENDOR*/ { + union { + uint32 AsReg32; + struct { IB_BITFIELD3(uint32, + IsGeneric: 1, + Type : 7, + VendorID: 24) /* Vendor OUI */ + } PACK_SUFFIX s; + } u; + /* If not generic, this is Device ID information as assigned by */ + /* device manufacturer. */ + uint16 DeviceID; + } PACK_SUFFIX Vendor; + } u; + + /* Common Notice attributes */ + IB_LID IssuerLID; /* LID of requester */ + + /* Toggle: + * For Notices, alternates between zero and one after each Notice is + * cleared. + * For Traps, this shall be set to 0. + * + * Count: + * For Notices, indicates the number of notices queued on this channel + * adapter, switch, or router. + * For Traps, this shall be set to all zeroes. + */ + struct { IB_BITFIELD2(uint16, + Toggle :1, + Count :15) + } PACK_SUFFIX Stats; + + uint8 Data[54]; + IB_GID IssuerGID; + +} PACK_SUFFIX IB_NOTICE; + +/* + * Structure of the IB_NOTICE Data for the following traps: + * SMA_TRAP_GID_NOW_IN_SERVICE + * SMA_TRAP_GID_OUT_OF_SERVICE + * SMA_TRAP_ADD_MULTICAST_GROUP + * SMA_TRAP_DEL_MULTICAST_GROUP + */ +typedef struct _TRAPS_64_65_66_67_DETAILS +{ + uint8 Reserved[6]; + IB_GID GIDAddress; + uint8 Padding[32]; +} PACK_SUFFIX TRAPS_64_65_66_67_DETAILS, TRAP_64_DETAILS, TRAP_65_DETAILS, TRAP_66_DETAILS, TRAP_67_DETAILS; + +/* + * InformInfo + */ +typedef struct _INFORM_INFO { + IB_GID GID; /* specifies specific GID to subscribe for. */ + /* Set to zero if not desired. */ + IB_LID LIDRangeBegin; /* 0xFFFF encapsulates all LIDs */ + IB_LID LIDRangeEnd; + uint16 Reserved; + uint8 IsGeneric; /* 1 = forward generic traps */ + /* 0 = vendor specific */ + uint8 Subscribe; /* 1 = subscribe, 0 = unsubscribe */ + + uint16 Type; /* IB_NOTICE_TYPE */ + + union { + struct /*_GENERIC_II*/ { + uint16 TrapNumber; + union { + uint32 AsReg32; + struct { IB_BITFIELD3(uint32, + QPNumber:24, + Reserved:3, + RespTimeValue:5) + } PACK_SUFFIX s; + } u2; + union { + uint32 AsReg32; + struct { IB_BITFIELD2(uint32, + Reserved: 8, + ProducerType: 24) /* NODE_TYPE */ + } PACK_SUFFIX s; + } u; + } PACK_SUFFIX Generic; + + struct /*_VENDOR_II*/ { + uint16 DeviceID; + union { + uint32 AsReg32; + struct { IB_BITFIELD3(uint32, + QPNumber:24, + Reserved:3, + RespTimeValue:5) + } PACK_SUFFIX s; + } u2; + union { + uint32 AsReg32; + struct { IB_BITFIELD2(uint32, + Reserved: 8, + VendorID: 24) /* Vendor OUI */ + } PACK_SUFFIX s; + } u; + } PACK_SUFFIX Vendor; + } u; + +} PACK_SUFFIX IB_INFORM_INFO; +#include "iba/public/ipackoff.h" + + + +/* -------------------------------------------------------------------------- + * Swap between cpu and wire formats + */ +static __inline +void +BSWAP_MAD_HEADER( + MAD *Dest + ) +{ +#if CPU_LE + Dest->common.u.NS.Status.AsReg16 = ntoh16( Dest->common.u.NS.Status.AsReg16); + Dest->common.TransactionID = ntoh64(Dest->common.TransactionID); + Dest->common.AttributeID = ntoh16(Dest->common.AttributeID ); + Dest->common.AttributeModifier = ntoh32(Dest->common.AttributeModifier); +#endif +} + + +static __inline +void +BSWAP_IB_CLASS_PORT_INFO( + IB_CLASS_PORT_INFO *Dest + ) +{ +#if CPU_LE + Dest->CapMask = ntoh16(Dest->CapMask); + Dest->u1.AsReg32 = ntoh32(Dest->u1.AsReg32); + BSWAP_IB_GID(&Dest->RedirectGID); + Dest->u2.AsReg32 = ntoh32(Dest->u2.AsReg32); + Dest->RedirectLID = ntoh16(Dest->RedirectLID); + Dest->Redirect_P_Key = ntoh16(Dest->Redirect_P_Key); + Dest->u3.AsReg32 = ntoh32(Dest->u3.AsReg32); + Dest->Redirect_Q_Key = ntoh32(Dest->Redirect_Q_Key); + BSWAP_IB_GID(&Dest->TrapGID); + Dest->u4.AsReg32 = ntoh32(Dest->u4.AsReg32); + Dest->TrapLID = ntoh16(Dest->TrapLID); + Dest->Trap_P_Key = ntoh16(Dest->Trap_P_Key); + Dest->u5.AsReg32 = ntoh32(Dest->u5.AsReg32); + Dest->Trap_Q_Key = ntoh32(Dest->Trap_Q_Key); +#endif +} + +static __inline +void +BSWAP_IB_NOTICE( + IB_NOTICE *Dest + ) +{ +#if CPU_LE + /* Can do Generic since Vendor has same types, just different field names */ + Dest->u.Generic.u.AsReg32 = ntoh32(Dest->u.Generic.u.AsReg32); + Dest->u.Generic.TrapNumber = ntoh16(Dest->u.Generic.TrapNumber); + Dest->IssuerLID = ntoh16(Dest->IssuerLID); + BSWAP_IB_GID(&Dest->IssuerGID); +#endif +} + +/* + * Swaps the GIDAddress in the IB_NOTICE Data + */ +static __inline +void +BSWAP_TRAPS_64_65_66_67_DETAILS(TRAPS_64_65_66_67_DETAILS *Dest) +{ +#if CPU_LE + BSWAP_IB_GID(&Dest->GIDAddress); +#endif +} + +#define BSWAP_TRAP_64_DETAILS(Dest) BSWAP_TRAPS_64_65_66_67_DETAILS(Dest) +#define BSWAP_TRAP_65_DETAILS(Dest) BSWAP_TRAPS_64_65_66_67_DETAILS(Dest) +#define BSWAP_TRAP_66_DETAILS(Dest) BSWAP_TRAPS_64_65_66_67_DETAILS(Dest) +#define BSWAP_TRAP_67_DETAILS(Dest) BSWAP_TRAPS_64_65_66_67_DETAILS(Dest) + +static __inline +void +BSWAP_INFORM_INFO( + IB_INFORM_INFO *Dest + ) +{ +#if CPU_LE + BSWAP_IB_GID(&Dest->GID); + Dest->LIDRangeBegin = ntoh16(Dest->LIDRangeBegin); + Dest->LIDRangeEnd = ntoh16(Dest->LIDRangeEnd); + Dest->Type = ntoh16(Dest->Type); + /* Can do Generic since Vendor has same types, just different field names */ + Dest->u.Generic.TrapNumber = ntoh16(Dest->u.Generic.TrapNumber); + Dest->u.Generic.u2.AsReg32 = ntoh32(Dest->u.Generic.u2.AsReg32); + Dest->u.Generic.u.AsReg32 = ntoh32(Dest->u.Generic.u.AsReg32); +#endif +} + +#if defined (__cplusplus) +}; +#endif + + +#endif /* __IBA_IB_MAD_H__ */ diff --git a/IbAccess/Common/Inc/ib_pkt.h b/IbAccess/Common/Inc/ib_pkt.h new file mode 100644 index 0000000..ffd5d14 --- /dev/null +++ b/IbAccess/Common/Inc/ib_pkt.h @@ -0,0 +1,364 @@ +/* BEGIN_ICS_COPYRIGHT3 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT3 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +/* Infiniband low level Link, Network and Transport Layer headers. + * Generally these are handled by the CA hardware. However in some cases + * for special QPs, the Verbs Provider must hand build these headers. + * Hence this file provides a common implementation for them + * + * The GRH header is more visible and is defined in ib_types.h + */ + +#ifndef _IBA_IB_PKT_H_ +#define _IBA_IB_PKT_H_ (1) + +#include "iba/public/datatypes.h" +#include "iba/stl_types.h" +#include "iba/stl_helper.h" +#include "iba/public/ibyteswap.h" +#include "iba/public/imemory.h" +#include "iba/public/ispinlock.h" + +#if defined (__cplusplus) +extern "C" { +#endif + + +#include "iba/public/ipackon.h" + +/* + * IB packet headers + */ + +/* + * Local Route Header + */ +typedef struct _IB_LRH { + struct _IB_LRH_V { IB_BITFIELD2(uint8, + VL: 4, /* Virtual lane */ + LinkVersion: 4) /* Link version */ + } v; + + struct _IB_LRH_LNH { IB_BITFIELD3(uint8, + ServiceLevel: 4, /* service level */ + Reserved: 2, + LNH: 2) /* this field identifies the headers */ + /* that follow LRH */ + } l; + + IB_LID DestLID; /* destination LID */ + + union _IB_LRH_PKT { + uint16 AsUINT16; + + struct _IB_LRH_PKT_S {IB_BITFIELD2(uint16, + Reserved: 5, + Length: 11) /* Packet length. Identifies sizeof */ + /* packet in 4 byte increments. */ + /* This field includes first byte */ + /* of LRH to last byte before the */ + /* variant CRC. */ + } s; + } Packet; + + IB_LID SrcLID; /* source LID */ +} PACK_SUFFIX IB_LRH; + +/* + * Link Next Header types (LRH.l.LNH) + */ +typedef enum { + LNH_RAW_ETHERTYPE = 0, + LNH_RAW_GRH, + LNH_BTH, + LNH_GRH +} LNH; + +#define LRH_IS_GLOBAL(lrh) (lrh->l.LNH == LNH_GRH) + +static __inline void +BSWAP_IB_LRH( + IB_LRH *Header + ) +{ + Header->DestLID = ntoh16(Header->DestLID); + Header->Packet.AsUINT16 = ntoh16(Header->Packet.AsUINT16); + Header->SrcLID = ntoh16(Header->SrcLID); +} + + +/* Network Header (IB_GRH) is defined in ib_types.h + * The IB_GRH structure is more visible since it is the 1st 40 bytes of all + * UD receive buffers + */ + +/* + * Base Transport Header + */ +typedef struct _IB_BTH { + uint8 OpCode; + + struct _IB_BTH_V {IB_BITFIELD4(uint8, + SolicitedEvent: 1, + Migrate: 1, + PadCount: 2, + HeaderVersion: 4) /* Transport Header version */ + } v; + + IB_P_KEY Pkey; + + union _IB_BTH_QP { + uint32 AsUINT32; + + struct _IB_BTH_QP_S {IB_BITFIELD2(uint32, + Reserved: 8, + DestQPNumber: 24) + } s; + } Qp; + + union _IB_BTH_PSN { + uint32 AsUINT32; + + struct _IB_BTH_PSN_S {IB_BITFIELD3(uint32, + AckReq: 1, + Reserved: 7, + PSN: 24) + } s; + } Psn; + +} PACK_SUFFIX IB_BTH; + +/* opcode is composed of a 3 bit QP TYPE and a 5 bit message type */ +#define BTH_OPCODE_QP_TYPE_MASK 0xE0 +#define BTH_OPCODE_MSG_TYPE_MASK 0x1F + +/* value for upper 3 bits of BTH_OPCODE */ +typedef enum { + BTH_OPCODE_RC = 0x00, + BTH_OPCODE_UC = 0x20, + BTH_OPCODE_RD = 0x40, + BTH_OPCODE_UD = 0x60 + /* 0x80, 0xA0 reserved */ + /* 0xC0, 0xE0 manufacturer specific opcodes */ +} BTH_OPCODE_QP_TYPE; + + +/* value for low 5 bits of BTH_OPCODE */ +typedef enum { + BTH_OPCODE_SEND_FIRST=0x00, + BTH_OPCODE_SEND_MIDDLE=0x01, + BTH_OPCODE_SEND_LAST=0x02, + BTH_OPCODE_SEND_LAST_IMMED=0x03, + BTH_OPCODE_SEND_ONLY=0x04, + BTH_OPCODE_SEND_ONLY_IMMED=0x05, + BTH_OPCODE_RDMA_WRITE_FIRST=0x06, + BTH_OPCODE_RDMA_WRITE_MIDDLE=0x07, + BTH_OPCODE_RDMA_WRITE_LAST=0x08, + BTH_OPCODE_RDMA_WRITE_LAST_IMMED=0x09, + BTH_OPCODE_RDMA_WRITE_ONLY=0x0A, + BTH_OPCODE_RDMA_WRITE_ONLY_IMMED=0x0B, + BTH_OPCODE_RDMA_READ_REQ=0x0C, + BTH_OPCODE_RDMA_READ_RESP_FIRST=0x0D, + BTH_OPCODE_RDMA_READ_RESP_MIDDLE=0x0E, + BTH_OPCODE_RDMA_READ_RESP_LAST=0x0F, + BTH_OPCODE_RDMA_READ_RESP_ONLY=0x10, + BTH_OPCODE_ACK=0x11, + BTH_OPCODE_ATOMIC_ACK=0x12, + BTH_OPCODE_CMP_SWAP=0x13, + BTH_OPCODE_FETCH_ADD=0x14, + BTH_OPCODE_RESYNC=0x15, + /* 0x15 - 0x1f reserved */ +} BTH_OPCODE_MSG_TYPE; + +/* + * OpCode (BTH.OpCode) + * Note not all combinations of QP_TYPE and MSG_TYPE are valid + */ +#define BTH_OPCODE_RC_SEND_FIRST (BTH_OPCODE_RC|BTH_OPCODE_SEND_FIRST) +#define BTH_OPCODE_RC_SEND_MIDDLE (BTH_OPCODE_RC|BTH_OPCODE_SEND_MIDDLE) +#define BTH_OPCODE_RC_SEND_LAST (BTH_OPCODE_RC|BTH_OPCODE_SEND_LAST) +#define BTH_OPCODE_RC_SEND_LAST_IMMED (BTH_OPCODE_RC|BTH_OPCODE_SEND_LAST_IMMED) +#define BTH_OPCODE_RC_SEND_ONLY (BTH_OPCODE_RC|BTH_OPCODE_SEND_ONLY) +#define BTH_OPCODE_RC_SEND_ONLY_IMMED (BTH_OPCODE_RC | BTH_OPCODE_SEND_ONLY_IMMED) +#define BTH_OPCODE_RC_RDMA_WRITE_FIRST (BTH_OPCODE_RC | BTH_OPCODE_RDMA_WRITE_FIRST) +#define BTH_OPCODE_RC_RDMA_WRITE_MIDDLE (BTH_OPCODE_RC | BTH_OPCODE_RDMA_WRITE_MIDDLE) +#define BTH_OPCODE_RC_RDMA_WRITE_LAST (BTH_OPCODE_RC | BTH_OPCODE_RDMA_WRITE_LAST) +#define BTH_OPCODE_RC_RDMA_WRITE_LAST_IMMED (BTH_OPCODE_RC | BTH_OPCODE_RDMA_WRITE_LAST_IMMED) +#define BTH_OPCODE_RC_RDMA_WRITE_ONLY (BTH_OPCODE_RC | BTH_OPCODE_RDMA_WRITE_ONLY) +#define BTH_OPCODE_RC_RDMA_WRITE_ONLY_IMMED (BTH_OPCODE_RC | BTH_OPCODE_RDMA_WRITE_ONLY_IMMED) +#define BTH_OPCODE_RC_RDMA_READ_REQ (BTH_OPCODE_RC | BTH_OPCODE_RDMA_READ_REQ) +#define BTH_OPCODE_RC_RDMA_READ_RESP_FIRST (BTH_OPCODE_RC | BTH_OPCODE_RDMA_READ_RESP_FIRST) +#define BTH_OPCODE_RC_RDMA_READ_RESP_MIDDLE (BTH_OPCODE_RC | BTH_OPCODE_RDMA_READ_RESP_MIDDLE) +#define BTH_OPCODE_RC_RDMA_READ_RESP_LAST (BTH_OPCODE_RC | BTH_OPCODE_RDMA_READ_RESP_LAST) +#define BTH_OPCODE_RC_RDMA_READ_RESP_ONLY (BTH_OPCODE_RC | BTH_OPCODE_RDMA_READ_RESP_ONLY) +#define BTH_OPCODE_RC_ACK (BTH_OPCODE_RC | BTH_OPCODE_ACK) +#define BTH_OPCODE_RC_ATOMIC_ACK (BTH_OPCODE_RC | BTH_OPCODE_ATOMIC_ACK) +#define BTH_OPCODE_RC_CMP_SWAP (BTH_OPCODE_RC | BTH_OPCODE_CMP_SWAP) +#define BTH_OPCODE_RC_FETCH_ADD (BTH_OPCODE_RC | BTH_OPCODE_FETCH_ADD) + /* 0x15 - 0x1f reserved */ +#define BTH_OPCODE_UC_SEND_FIRST (BTH_OPCODE_UC | BTH_OPCODE_SEND_FIRST) +#define BTH_OPCODE_UC_SEND_MIDDLE (BTH_OPCODE_UC | BTH_OPCODE_SEND_MIDDLE) +#define BTH_OPCODE_UC_SEND_LAST (BTH_OPCODE_UC | BTH_OPCODE_SEND_LAST) +#define BTH_OPCODE_UC_SEND_LAST_IMMED (BTH_OPCODE_UC | BTH_OPCODE_SEND_LAST_IMMED) +#define BTH_OPCODE_UC_SEND_ONLY (BTH_OPCODE_UC | BTH_OPCODE_SEND_ONLY) +#define BTH_OPCODE_UC_SEND_ONLY_IMMED (BTH_OPCODE_UC | BTH_OPCODE_SEND_ONLY_IMMED) +#define BTH_OPCODE_UC_RDMA_WRITE_FIRST (BTH_OPCODE_UC | BTH_OPCODE_RDMA_WRITE_FIRST) +#define BTH_OPCODE_UC_RDMA_WRITE_MIDDLE (BTH_OPCODE_UC | BTH_OPCODE_RDMA_WRITE_MIDDLE) +#define BTH_OPCODE_UC_RDMA_WRITE_LAST (BTH_OPCODE_UC | BTH_OPCODE_RDMA_WRITE_LAST) +#define BTH_OPCODE_UC_RDMA_WRITE_LAST_IMMED (BTH_OPCODE_UC | BTH_OPCODE_RDMA_WRITE_LAST_IMMED) +#define BTH_OPCODE_UC_RDMA_WRITE_ONLY (BTH_OPCODE_UC | BTH_OPCODE_RDMA_WRITE_ONLY) +#define BTH_OPCODE_UC_RDMA_WRITE_ONLY_IMMED (BTH_OPCODE_UC | BTH_OPCODE_RDMA_WRITE_ONLY_IMMED) + /* 0x2C - 0x3f reserved */ +#define BTH_OPCODE_RD_SEND_FIRST (BTH_OPCODE_RD | BTH_OPCODE_SEND_FIRST) +#define BTH_OPCODE_RD_SEND_MIDDLE (BTH_OPCODE_RD | BTH_OPCODE_SEND_MIDDLE) +#define BTH_OPCODE_RD_SEND_LAST (BTH_OPCODE_RD | BTH_OPCODE_SEND_LAST) +#define BTH_OPCODE_RD_SEND_LAST_IMMED (BTH_OPCODE_RD | BTH_OPCODE_SEND_LAST_IMMED) +#define BTH_OPCODE_RD_SEND_ONLY (BTH_OPCODE_RD | BTH_OPCODE_SEND_ONLY) +#define BTH_OPCODE_RD_SEND_ONLY_IMMED (BTH_OPCODE_RD | BTH_OPCODE_SEND_ONLY_IMMED) +#define BTH_OPCODE_RD_RDMA_WRITE_FIRST (BTH_OPCODE_RD | BTH_OPCODE_RDMA_WRITE_FIRST) +#define BTH_OPCODE_RD_RDMA_WRITE_MIDDLE (BTH_OPCODE_RD | BTH_OPCODE_RDMA_WRITE_MIDDLE) +#define BTH_OPCODE_RD_RDMA_WRITE_LAST (BTH_OPCODE_RD | BTH_OPCODE_RDMA_WRITE_LAST) +#define BTH_OPCODE_RD_RDMA_WRITE_LAST_IMMED (BTH_OPCODE_RD | BTH_OPCODE_RDMA_WRITE_LAST_IMMED) +#define BTH_OPCODE_RD_RDMA_WRITE_ONLY (BTH_OPCODE_RD | BTH_OPCODE_RDMA_WRITE_ONLY) +#define BTH_OPCODE_RD_RDMA_WRITE_ONLY_IMMED (BTH_OPCODE_RD | BTH_OPCODE_RDMA_WRITE_ONLY_IMMED) +#define BTH_OPCODE_RD_RDMA_READ_REQ (BTH_OPCODE_RD | BTH_OPCODE_RDMA_READ_REQ) +#define BTH_OPCODE_RD_RDMA_READ_RESP_FIRST (BTH_OPCODE_RD | BTH_OPCODE_RDMA_READ_RESP_FIRST) +#define BTH_OPCODE_RD_RDMA_READ_RESP_MIDDLE (BTH_OPCODE_RD | BTH_OPCODE_RDMA_READ_RESP_MIDDLE) +#define BTH_OPCODE_RD_RDMA_READ_RESP_LAST (BTH_OPCODE_RD | BTH_OPCODE_RDMA_READ_RESP_LAST) +#define BTH_OPCODE_RD_RDMA_READ_RESP_ONLY (BTH_OPCODE_RD | BTH_OPCODE_RDMA_READ_RESP_ONLY) +#define BTH_OPCODE_RD_ACK (BTH_OPCODE_RD | BTH_OPCODE_ACK) +#define BTH_OPCODE_RD_ATOMIC_ACK (BTH_OPCODE_RD | BTH_OPCODE_ATOMIC_ACK) +#define BTH_OPCODE_RD_CMP_SWAP (BTH_OPCODE_RD | BTH_OPCODE_CMP_SWAP) +#define BTH_OPCODE_RD_FETCH_ADD (BTH_OPCODE_RD | BTH_OPCODE_FETCH_ADD) +#define BTH_OPCODE_RD_RESYNC (BTH_OPCODE_RD | BTH_OPCODE_RESYNC) + /* 0x56 - 0x5f reserved */ + /* 0x60 - 0x63 reserved */ +#define BTH_OPCODE_UD_SEND_ONLY (BTH_OPCODE_UD | BTH_OPCODE_SEND_ONLY) +#define BTH_OPCODE_UD_SEND_ONLY_IMMED (BTH_OPCODE_UD | BTH_OPCODE_SEND_ONLY_IMMED) + /* 0x66 - 0x7f reserved */ + /* 0x80 - 0xBF reserved */ + /* 0xC0 - 0xFF manufacturer specific codes */ + +static __inline void +BSWAP_IB_BTH( + IB_BTH *Header + ) +{ + Header->Pkey = ntoh16(Header->Pkey); + Header->Qp.AsUINT32 = ntoh32(Header->Qp.AsUINT32); + Header->Psn.AsUINT32 = ntoh32(Header->Psn.AsUINT32); +} + +/* + * Datagram Extended Transport Header + */ +typedef struct _IB_DETH { + IB_Q_KEY Qkey; + + union _IB_DETH_QP { + uint32 AsUINT32; + + struct _IB_DETH_QP_S {IB_BITFIELD2(uint32, + Reserved: 8, + SrcQPNumber: 24) + + } s; + } Qp; + +} PACK_SUFFIX IB_DETH; + +static __inline void +BSWAP_IB_DETH( + IB_DETH *Header + ) +{ + Header->Qkey = ntoh32(Header->Qkey); + Header->Qp.AsUINT32 = ntoh32(Header->Qp.AsUINT32); +} + +/* + * Swap Immediate Data + */ +static __inline void +BSWAP_IMMED_DATA( + uint32 *ImmDt + ) +{ + *ImmDt = ntoh32(*ImmDt); +} + +typedef struct _IB_LOCAL_PKT_HEADERS { + IB_LRH Lrh; + IB_BTH Bth; +} PACK_SUFFIX IB_LOCAL_PKT_HEADERS; + +typedef struct _IB_GLOBAL_PKT_HEADERS { + IB_LRH Lrh; + IB_GRH Grh; + IB_BTH Bth; +} PACK_SUFFIX IB_GLOBAL_PKT_HEADERS; + +typedef struct _IB_LOCAL_UD_HEADERS { + IB_LRH Lrh; + IB_BTH Bth; + IB_DETH Deth; +} PACK_SUFFIX IB_LOCAL_UD_HEADERS; + +typedef struct _IB_GLOBAL_UD_HEADERS { + IB_LRH Lrh; + IB_GRH Grh; + IB_BTH Bth; + IB_DETH Deth; +} PACK_SUFFIX IB_GLOBAL_UD_HEADERS; + +typedef struct _IB_LOCAL_UD_IMM_HEADERS { + IB_LRH Lrh; + IB_BTH Bth; + IB_DETH Deth; + uint32 ImmDt; +} PACK_SUFFIX IB_LOCAL_UD_IMM_HEADERS; + +typedef struct _IB_GLOBAL_UD_IMM_HEADERS { + IB_LRH Lrh; + IB_GRH Grh; + IB_BTH Bth; + IB_DETH Deth; + uint32 ImmDt; +} PACK_SUFFIX IB_GLOBAL_UD_IMM_HEADERS; + + +#include "iba/public/ipackoff.h" + +#if defined (__cplusplus) +}; +#endif + +#endif /* _IBA_IB_PKT_H_ */ diff --git a/IbAccess/Common/Inc/ib_rmpp.h b/IbAccess/Common/Inc/ib_rmpp.h new file mode 100644 index 0000000..35b2f25 --- /dev/null +++ b/IbAccess/Common/Inc/ib_rmpp.h @@ -0,0 +1,119 @@ +/* BEGIN_ICS_COPYRIGHT3 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT3 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +#ifndef _IBA_IB_RMPP_H_ +#define _IBA_IB_RMPP_H_ (1) /* suppress duplicate loading of this file */ + +#include "iba/public/datatypes.h" +#include "iba/public/ibyteswap.h" +#include "iba/ib_generalServices.h" + +#ifdef __cplusplus +extern "C" { +#endif + + + +/* RMPP Protocol methods */ +#define RMPP_CMD_GET (0x01) +#define RMPP_CMD_GET_RESP (0x81) +#define RMPP_CMD_SET (0x02) +#define RMPP_CMD_GETTABLE (0x12) +#define RMPP_CMD_GETTRACETABLE (0x13) +#define RMPP_CMD_GETTABLE_RESP (0x92) +#define RMPP_CMD_DELETE (0x15) // Request to delete an attribute +#define RMPP_CMD_DELETE_RESP (0x95) // Response to delete an attribute + +#define RMPP_CMD_FE_MNGR_PROBE_CMD (0x21) +#define RMPP_CMD_FE_MNGR_CLOSE_CMD (0x22) +#define RMPP_CMD_FE_SEND (0x24) +#define RMPP_CMD_FE_RESP (0x25) + +#define MAD_RMPP_REPLY 0x80 // Reply bit for methods + +#define RMPP_DATA_OFFSET 32 + +#define RMPP_CLASS_VERSION 0x01 + + +/* RMPP Protocol Response Structures */ +#define RMPP_REC_DESC_LEN 64 +#define RMPP_TABLE_REC_DATA_LEN 512 +#define RMPP_RECORD_NSIZE sizeof(rmppRecord_t) +#define RMPP_TABLE_RECORD_NSIZE sizeof(rmppTableRecord_t) + +typedef struct rmppRecord_s { + uint16_t fieldUint16; + uint16_t fieldFiller; + uint32_t fieldUint32; + uint64_t fieldUint64; + uint8_t desc[RMPP_REC_DESC_LEN]; +} rmppRecord_t; + +typedef struct rmppTableRecord_s { + uint16_t fieldUint16; + uint16_t fieldFiller; + uint32_t fieldUint32; + uint64_t fieldUint64; + uint8_t desc[RMPP_REC_DESC_LEN]; + uint8_t data[RMPP_TABLE_REC_DATA_LEN]; +} rmppTableRecord_t; + +typedef struct _RMPP_TABLE_RECORD_RESULTS { + uint32 NumrmppRecords; /* Number of PA Records returned */ + rmppTableRecord_t rmppRecords[1]; /* list of PA records returned */ +} RMPP_TABLE_RECORD_RESULTS, *PRMPP_TABLE_RECORD_RESULTS; + +static __inline void +BSWAP_RMPP_RECORD(rmppRecord_t *pRecord) +{ +#if CPU_LE + pRecord->fieldUint16 = ntoh16(pRecord->fieldUint16); + pRecord->fieldUint32 = ntoh32(pRecord->fieldUint32); + pRecord->fieldUint64 = ntoh64(pRecord->fieldUint64); +#endif /* CPU_LE */ +} + +static __inline void +BSWAP_RMPP_TABLE_RECORD(rmppTableRecord_t *pRecord) +{ +#if CPU_LE + pRecord->fieldUint16 = ntoh16(pRecord->fieldUint16); + pRecord->fieldUint32 = ntoh32(pRecord->fieldUint32); + pRecord->fieldUint64 = ntoh64(pRecord->fieldUint64); +#endif /* CPU_LE */ +} + +#ifdef __cplusplus +} +#endif + +#endif /* _IBA_IB_RMPP_H_ */ diff --git a/IbAccess/Common/Inc/ib_sa_records.h b/IbAccess/Common/Inc/ib_sa_records.h new file mode 100644 index 0000000..3c8e1d7 --- /dev/null +++ b/IbAccess/Common/Inc/ib_sa_records.h @@ -0,0 +1,722 @@ +/* BEGIN_ICS_COPYRIGHT3 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT3 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +#ifndef _IBA_IB_SA_RECORDS_H_ +#define _IBA_IB_SA_RECORDS_H_ + +/* IB Subnet Adminstration records and methods */ + +#include "iba/public/datatypes.h" /* Portable datatypes */ +#include "iba/stl_sm_types.h" +#ifndef IB_STACK_OPENIB +#include "iba/vpi.h" +#endif +#include "iba/public/ibyteswap.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#include "iba/public/ipackon.h" + +/* Subnet Administration methods */ +#define SUBN_ADM_GET 0x01 +#define SUBN_ADM_GET_RESP 0x81 +#define SUBN_ADM_SET 0x02 +#define SUBN_ADM_REPORT 0x06 +#define SUBN_ADM_REPORT_RESP 0x86 +#define SUBN_ADM_GETTABLE 0x12 +#define SUBN_ADM_GETTABLE_RESP 0x92 +#define SUBN_ADM_GETTRACETABLE 0x13 /* optional */ +#define SUBN_ADM_GETMULTI 0x14 /* optional */ +#define SUBN_ADM_GETMULTI_RESP 0x94 /* optional */ +#define SUBN_ADM_DELETE 0x15 +#define SUBN_ADM_DELETE_RESP 0x95 + +/* Subnet Administration Attribute IDs */ +#define SA_ATTRIB_CLASS_PORT_INFO 0x0001 +#define SA_ATTRIB_NOTICE 0x0002 +#define SA_ATTRIB_INFORM_INFO 0x0003 +#define SA_ATTRIB_NODE_RECORD 0x0011 +#define SA_ATTRIB_PORTINFO_RECORD 0x0012 +#define SA_ATTRIB_SWITCHINFO_RECORD 0x0014 +#define SA_ATTRIB_LINEAR_FWDTBL_RECORD 0x0015 +#define SA_ATTRIB_RANDOM_FWDTBL_RECORD 0x0016 +#define SA_ATTRIB_MCAST_FWDTBL_RECORD 0x0017 +#define SA_ATTRIB_SMINFO_RECORD 0x0018 +#define SA_ATTRIB_INFORM_INFO_RECORD 0x00F3 +#define SA_ATTRIB_LINK_RECORD 0x0020 +// was SA_ATTRIB_GUIDINFO_RECORD 0x0030 +#define SA_ATTRIB_SERVICE_RECORD 0x0031 +#define SA_ATTRIB_P_KEY_TABLE_RECORD 0x0033 +#define SA_ATTRIB_PATH_RECORD 0x0035 +#define SA_ATTRIB_VLARBTABLE_RECORD 0x0036 +#define SA_ATTRIB_MCMEMBER_RECORD 0x0038 +#define SA_ATTRIB_TRACE_RECORD 0x0039 +#define SA_ATTRIB_MULTIPATH_RECORD 0x003A +#define SA_ATTRIB_SERVICEASSOCIATION_RECORD 0x003B + +#define SA_ATTRIB_VFABRIC_RECORD 0xff02 +#define SA_ATTRIB_JOB_ROUTE_RECORD 0xFFB2 // Reserved AID used by opasadb_route + +#define SA_ATTRIB_CG_RECORD 0xff40 // Vendor unique collective group record +#define SA_ATTRIB_CG_STATUS_RECORD 0xff41 // Vendor unique collective group status record +#define SA_ATTRIB_CFT_RECORD 0xff42 // Vendor unique CFT record + +/* SA ClassSpecific MAD_STATUS (AsReg16) */ +#define MAD_STATUS_SA_NO_RESOURCES 0x0100 +#define MAD_STATUS_SA_REQ_INVALID 0x0200 +#define MAD_STATUS_SA_NO_RECORDS 0x0300 +#define MAD_STATUS_SA_TOO_MANY_RECORDS 0x0400 +#define MAD_STATUS_SA_REQ_INVALID_GID 0x0500 +#define MAD_STATUS_SA_REQ_INSUFFICIENT_COMPONENTS 0x0600 +/* 0x0700-0xff00 reserved */ + +/* SA specific CapMask bits for IB_CLASS_PORT_INFO */ +#define CLASS_PORT_CAPMASK_SA_OPTIONAL_RECORDS 0x00100 +#define CLASS_PORT_CAPMASK_SA_UD_MULTICAST 0x00200 +#define CLASS_PORT_CAPMASK_SA_MULTIPATH 0x00400 /*TraceRecord and MultiPathRecord */ +#define CLASS_PORT_CAPMASK_SA_REINIT 0x00800 +#define CLASS_PORT_CAPMASK2_SA_MCFDBTOP_SUPPORT 0x00008 + +/* --------------------------------------------------------------------------- + * Basic SA types and constants + */ + +/* selector for use in assorted queries for Mtu, Rate, Lifetime */ +typedef enum { + IB_SELECTOR_GT=0, + IB_SELECTOR_LT=1, + IB_SELECTOR_EQ=2, + IB_SELECTOR_MAX=3 /* largest available for Mtu/Rate, smallest packet life */ +} IB_SELECTOR; + +/* -------------------------------------------------------------------------- + * SA records themselves + */ + + +/* -------------------------------------------------------------------------- + * Path Record - describes path between 2 end nodes in the fabric + */ + +/* ComponentMask bits */ +/* + * CA13-6: The component mask bits for ServiceID8MSB and ServiceID56LSB + * shall have the same value. They shall be either both set to one or + * both cleared. + */ +#define IB_PATH_RECORD_COMP_SERVICEID 0x00000003 +#define IB_PATH_RECORD_COMP_DGID 0x00000004 +#define IB_PATH_RECORD_COMP_SGID 0x00000008 +#define IB_PATH_RECORD_COMP_DLID 0x00000010 +#define IB_PATH_RECORD_COMP_SLID 0x00000020 +#define IB_PATH_RECORD_COMP_RAWTRAFFIC 0x00000040 + /* reserved field 0x00000080 */ +#define IB_PATH_RECORD_COMP_FLOWLABEL 0x00000100 +#define IB_PATH_RECORD_COMP_HOPLIMIT 0x00000200 +#define IB_PATH_RECORD_COMP_TCLASS 0x00000400 +#define IB_PATH_RECORD_COMP_REVERSIBLE 0x00000800 +#define IB_PATH_RECORD_COMP_NUMBPATH 0x00001000 +#define IB_PATH_RECORD_COMP_PKEY 0x00002000 +#define IB_PATH_RECORD_COMP_QOS_CLASS 0x00004000 +#define IB_PATH_RECORD_COMP_SL 0x00008000 +#define IB_PATH_RECORD_COMP_MTUSELECTOR 0x00010000 +#define IB_PATH_RECORD_COMP_MTU 0x00020000 +#define IB_PATH_RECORD_COMP_RATESELECTOR 0x00040000 +#define IB_PATH_RECORD_COMP_RATE 0x00080000 +#define IB_PATH_RECORD_COMP_PKTLIFESELECTOR 0x00100000 +#define IB_PATH_RECORD_COMP_PKTLIFE 0x00200000 +#define IB_PATH_RECORD_COMP_PREFERENCE 0x00400000 + /* reserved field 0x00800000 */ +#define IB_PATH_RECORD_COMP_ALL 0x007fff7f + +typedef struct _IB_PATH_RECORD { + uint64 ServiceID; + IB_GID DGID; /* Destination GID */ + IB_GID SGID; /* Source GID */ + IB_LID DLID; /* Destination LID */ + IB_LID SLID; /* Source LID */ + union { + uint32 AsReg32; + struct { +#if CPU_BE + uint32 RawTraffic :1; /* 0 for IB Packet (P_Key must be valid) */ + /* 1 for Raw Packet (No P_Key) */ + uint32 Reserved :3; + uint32 FlowLabel :20; /* used in GRH */ + uint32 HopLimit :8; /* Hop limit used in GRH */ +#else + uint32 HopLimit :8; /* Hop limit used in GRH */ + uint32 FlowLabel :20; /* used in GRH */ + uint32 Reserved :3; + uint32 RawTraffic :1; /* 0 for IB Packet (P_Key must be valid) */ + /* 1 for Raw Packet (No P_Key) */ +#endif + } PACK_SUFFIX s; + } u1; + + uint8 TClass; /* Traffic Class used in GRH */ +#if CPU_BE + uint8 Reversible :1; + uint8 NumbPath :7; /* Max number of paths to (be) return(ed) */ + +#else /* CPU_BE */ + uint8 NumbPath :7; /* Max number of paths to (be) return(ed) */ + uint8 Reversible :1; +#endif /* CPU_BE */ + uint16 P_Key; /* Partition Key for this path */ + union { + uint16 AsReg16; + struct { +#if CPU_BE + uint16 QosType : 2; + uint16 Reserved2 : 2; + uint16 QosPriority : 8; + uint16 SL : 4; +#else + uint16 SL : 4; + uint16 QosPriority : 8; + uint16 Reserved2 : 2; + uint16 QosType : 2; +#endif + } PACK_SUFFIX s; + } u2; + +#if CPU_BE + uint8 MtuSelector :2; /* enum IB_SELECTOR */ + uint8 Mtu :6; /* enum IB_MTU */ +#else + uint8 Mtu :6; /* enum IB_MTU */ + uint8 MtuSelector :2; /* enum IB_SELECTOR */ +#endif + +#if CPU_BE + uint8 RateSelector:2; /* enum IB_SELECTOR */ + uint8 Rate :6; /* enum IB_STATIC_RATE */ +#else + uint8 Rate :6; /* enum IB_STATIC_RATE */ + uint8 RateSelector:2; /* enum IB_SELECTOR */ +#endif + + /* ***************************************** */ + /* *** User be aware that the CM LifeTime & */ + /* *** TimeOut values are only 5-bit wide. */ + /* ***************************************** */ + /* */ + /* Accumulated packet life time for the path specified by an enumeration */ + /* deried from 4.096 usec * 2^PktLifeTime */ +#if CPU_BE + uint8 PktLifeTimeSelector:2; /* enum IB_SELECTOR */ + uint8 PktLifeTime :6; +#else + uint8 PktLifeTime :6; + uint8 PktLifeTimeSelector:2; /* enum IB_SELECTOR */ +#endif + + uint8 Preference; /* 1.1 specific. see page 800 of volume 1 */ + uint8 Reserved2 [6]; +} PACK_SUFFIX IB_PATH_RECORD; + + +/* -------------------------------------------------------------------------- + * Node Record - describes a port on a node in the fabric + */ + +/* ComponentMask bits */ +#define IB_NODE_RECORD_COMP_LID 0x00000001 + /* reserved field 0x00000002 */ + /* fields in NodeInfo */ +#define IB_NODE_RECORD_COMP_BASEVERSION 0x00000004 +#define IB_NODE_RECORD_COMP_CLASSVERSION 0x00000008 +#define IB_NODE_RECORD_COMP_NODETYPE 0x00000010 +#define IB_NODE_RECORD_COMP_NUMPORTS 0x00000020 +#define IB_NODE_RECORD_COMP_SYSIMAGEGUID 0x00000040 +#define IB_NODE_RECORD_COMP_NODEGUID 0x00000080 +#define IB_NODE_RECORD_COMP_PORTGUID 0x00000100 +#define IB_NODE_RECORD_COMP_PARTITIONCAP 0x00000200 +#define IB_NODE_RECORD_COMP_DEVICEID 0x00000400 +#define IB_NODE_RECORD_COMP_REVISION 0x00000800 +#define IB_NODE_RECORD_COMP_LOCALPORTNUM 0x00001000 +#define IB_NODE_RECORD_COMP_VENDORID 0x00002000 + /* fields in Node Description */ +#define IB_NODE_RECORD_COMP_NODEDESC 0x00004000 + +typedef struct _IB_NODE_RECORD { + union { + uint32 AsReg32; + struct { +#if CPU_BE + uint32 LID:16; + uint32 Reserved:16; +#else + uint32 Reserved:16; + uint32 LID:16; +#endif + } PACK_SUFFIX s; + } RID; + NODE_INFO NodeInfoData; + NODE_DESCRIPTION NodeDescData; +} PACK_SUFFIX IB_NODE_RECORD; + + +/* -------------------------------------------------------------------------- + * PortInfo Record - detailed description of a port on a node in the fabric + */ + +/* ComponentMask bits */ +#define IB_PORTINFO_RECORD_COMP_ENDPORTLID 0x00000001 +#define IB_PORTINFO_RECORD_COMP_PORTNUM 0x00000002 + /* reserved field 0x00000004 */ + /* fields in PortInfo */ +#define IB_PORTINFO_RECORD_COMP_MKEY 0x00000008 +#define IB_PORTINFO_RECORD_COMP_GIDPREFIX 0x00000010 +#define IB_PORTINFO_RECORD_COMP_LID 0x00000020 +#define IB_PORTINFO_RECORD_COMP_MASTERSMLID 0x00000040 +#define IB_PORTINFO_RECORD_COMP_CAPABILITYMASK 0x00000080 +#define IB_PORTINFO_RECORD_COMP_DIAGCODE 0x00000100 +#define IB_PORTINFO_RECORD_COMP_MKEYLEASEPERIOD 0x00000200 +#define IB_PORTINFO_RECORD_COMP_LOCALPORTNUM 0x00000400 +#define IB_PORTINFO_RECORD_COMP_LINKWIDTHENABLED 0x00000800 +#define IB_PORTINFO_RECORD_COMP_LINKWIDTHSUPPORTED 0x00001000 +#define IB_PORTINFO_RECORD_COMP_LINKWIDTHACTIVE 0x00002000 +#define IB_PORTINFO_RECORD_COMP_LINKSPEEDSUPPORTED 0x00004000 +#define IB_PORTINFO_RECORD_COMP_PORTSTATE 0x00008000 +#define IB_PORTINFO_RECORD_COMP_PORTPHYSSTATE 0x00010000 +#define IB_PORTINFO_RECORD_COMP_LINKDOWNDEFAULTSTATE 0x00020000 +#define IB_PORTINFO_RECORD_COMP_MKEYPROTECTBITS 0x00040000 + /* reserved field 0x00080000 */ +#define IB_PORTINFO_RECORD_COMP_LMC 0x00100000 +#define IB_PORTINFO_RECORD_COMP_LINKSPEEDACTIVE 0x00200000 +#define IB_PORTINFO_RECORD_COMP_LINKSPEEDENABLED 0x00400000 +#define IB_PORTINFO_RECORD_COMP_NEIGHBORMTU 0x00800000 +#define IB_PORTINFO_RECORD_COMP_MASTERSMSL 0x01000000 +#define IB_PORTINFO_RECORD_COMP_VLCAP 0x02000000 + +/* Option bits */ +#define IB_PORTINFO_RECORD_OPTIONS_QDRNOTOVERLOADED 0x80 + +typedef struct _IB_PORTINFO_RECORD { + union { + uint32 AsReg32; + struct { +#if CPU_BE + uint32 EndPortLID:16; + uint32 PortNum:8; + uint32 Options:8; // Ver 1.2.1+ +#else + uint32 Options:8; + uint32 PortNum:8; + uint32 EndPortLID:16; +#endif + } PACK_SUFFIX s; + } RID; + PORT_INFO PortInfoData; +} PACK_SUFFIX IB_PORTINFO_RECORD; + +/* -------------------------------------------------------------------------- + * Inform Info (event subscription) Record - SA events which have been subscribed to + */ + +/* ComponentMask bits */ +#define IB_INFORMINFO_RECORD_COMP_SUBSCRIBERGID 0x00000001 +#define IB_INFORMINFO_RECORD_COMP_ENUM 0x00000002 + /* reserved field 0x00000004 */ + /* Inform Info fields */ +#define IB_INFORMINFO_RECORD_COMP_GID 0x00000008 +#define IB_INFORMINFO_RECORD_COMP_LIDRANGEBEGIN 0x00000010 +#define IB_INFORMINFO_RECORD_COMP_LIDRANGEEND 0x00000020 + /* reserved field 0x00000040 */ +#define IB_INFORMINFO_RECORD_COMP_ISGENERIC 0x00000080 +#define IB_INFORMINFO_RECORD_COMP_SUBSCRIBE 0x00000100 +#define IB_INFORMINFO_RECORD_COMP_TYPE 0x00000200 +#define IB_INFORMINFO_RECORD_COMP_TRAPNUMBER_DEVICEID 0x00000400 +#define IB_INFORMINFO_RECORD_COMP_QPN 0x00000800 + /* reserved field 0x00001000 */ +#define IB_INFORMINFO_RECORD_COMP_RESPTIMEVALUE 0x00002000 + /* reserved field 0x00004000 */ +#define IB_INFORMINFO_RECORD_COMP_PRODUCERTYPE_VENDORID 0x00008000 + +typedef struct _IB_INFORM_INFO_RECORD { + struct { + IB_GID SubscriberGID; + uint16 Enum; + } PACK_SUFFIX RID; + uint8 Reserved[6]; + IB_INFORM_INFO InformInfoData; /* InformInfo (event subscription) */ + /* for this port */ +} PACK_SUFFIX IB_INFORM_INFO_RECORD; + +/* -------------------------------------------------------------------------- + * Service Record - services provided by nodes in the fabric + */ + +/* ComponentMask bits */ +#define IB_SERVICE_RECORD_COMP_SERVICEID 0x00000001 +#define IB_SERVICE_RECORD_COMP_SERVICEGID 0x00000002 +#define IB_SERVICE_RECORD_COMP_SERVICEPKEY 0x00000004 + /* reserved field 0x00000008 */ +#define IB_SERVICE_RECORD_COMP_SERVICELEASE 0x00000010 +#define IB_SERVICE_RECORD_COMP_SERVICEKEY 0x00000020 +#define IB_SERVICE_RECORD_COMP_SERVICENAME 0x00000040 +#define IB_SERVICE_RECORD_COMP_SERVICEDATA8_1 0x00000080 +#define IB_SERVICE_RECORD_COMP_SERVICEDATA8_2 0x00000100 +#define IB_SERVICE_RECORD_COMP_SERVICEDATA8_3 0x00000200 +#define IB_SERVICE_RECORD_COMP_SERVICEDATA8_4 0x00000400 +#define IB_SERVICE_RECORD_COMP_SERVICEDATA8_5 0x00000800 +#define IB_SERVICE_RECORD_COMP_SERVICEDATA8_6 0x00001000 +#define IB_SERVICE_RECORD_COMP_SERVICEDATA8_7 0x00002000 +#define IB_SERVICE_RECORD_COMP_SERVICEDATA8_8 0x00004000 +#define IB_SERVICE_RECORD_COMP_SERVICEDATA8_9 0x00008000 +#define IB_SERVICE_RECORD_COMP_SERVICEDATA8_10 0x00010000 +#define IB_SERVICE_RECORD_COMP_SERVICEDATA8_11 0x00020000 +#define IB_SERVICE_RECORD_COMP_SERVICEDATA8_12 0x00040000 +#define IB_SERVICE_RECORD_COMP_SERVICEDATA8_13 0x00080000 +#define IB_SERVICE_RECORD_COMP_SERVICEDATA8_14 0x00100000 +#define IB_SERVICE_RECORD_COMP_SERVICEDATA8_15 0x00200000 +#define IB_SERVICE_RECORD_COMP_SERVICEDATA8_16 0x00400000 +#define IB_SERVICE_RECORD_COMP_SERVICEDATA8_ALL 0x007fff80 +#define IB_SERVICE_RECORD_COMP_SERVICEDATA16_1 0x00800000 +#define IB_SERVICE_RECORD_COMP_SERVICEDATA16_2 0x01000000 +#define IB_SERVICE_RECORD_COMP_SERVICEDATA16_3 0x02000000 +#define IB_SERVICE_RECORD_COMP_SERVICEDATA16_4 0x04000000 +#define IB_SERVICE_RECORD_COMP_SERVICEDATA16_5 0x08000000 +#define IB_SERVICE_RECORD_COMP_SERVICEDATA16_6 0x10000000 +#define IB_SERVICE_RECORD_COMP_SERVICEDATA16_7 0x20000000 +#define IB_SERVICE_RECORD_COMP_SERVICEDATA16_8 0x40000000 +#define IB_SERVICE_RECORD_COMP_SERVICEDATA16_ALL 0x7f800000 +#define IB_SERVICE_RECORD_COMP_SERVICEDATA32_1 0x80000000 +#define IB_SERVICE_RECORD_COMP_SERVICEDATA32_2 0x100000000ll +#define IB_SERVICE_RECORD_COMP_SERVICEDATA32_3 0x200000000ll +#define IB_SERVICE_RECORD_COMP_SERVICEDATA32_4 0x400000000ll +#define IB_SERVICE_RECORD_COMP_SERVICEDATA32_ALL 0x780000000ll +#define IB_SERVICE_RECORD_COMP_SERVICEDATA64_1 0x800000000ll +#define IB_SERVICE_RECORD_COMP_SERVICEDATA64_2 0x1000000000ll +#define IB_SERVICE_RECORD_COMP_SERVICEDATA64_ALL 0x1800000000ll + +#define SERVICE_LEASE_INFINITE 0xffffffff + +typedef struct _IB_SERVICE_RECORD { + struct { + uint64 ServiceID; + IB_GID ServiceGID; + uint16 ServiceP_Key; + } PACK_SUFFIX RID; + uint16 Reserved; + uint32 ServiceLease; /* Lease period remaining for this */ + /* service (in secconds). */ + uint8 ServiceKey[16]; /* binary service key */ + uint8 ServiceName[64]; /* UTF8 null terminated */ + uint8 ServiceData8[16]; + uint16 ServiceData16[8]; + uint32 ServiceData32[4]; + uint64 ServiceData64[2]; +} PACK_SUFFIX IB_SERVICE_RECORD; + +/* -------------------------------------------------------------------------- + * Service Association Record - map between service keys and names + */ + +/* ComponentMask bits */ +#define IB_SERVICEASSOC_RECORD_COMP_SERVICEKEY 0x00000001 +#define IB_SERVICEASSOC_RECORD_COMP_SERVICENAME 0x00000002 + +typedef struct _IB_SERVICEASSOCIATION_RECORD { + uint8 ServiceKey[16]; /* binary service key */ + uint8 ServiceName[16]; /* UTF8 null terminated */ +} PACK_SUFFIX IB_SERVICEASSOCIATION_RECORD; + + +/* -------------------------------------------------------------------------- + * Multicast Member Record - members in a multicast group + */ + +/* ComponentMask bits */ +#define IB_MCMEMBER_RECORD_COMP_MGID 0x00000001 +#define IB_MCMEMBER_RECORD_COMP_PORTGID 0x00000002 +#define IB_MCMEMBER_RECORD_COMP_QKEY 0x00000004 +#define IB_MCMEMBER_RECORD_COMP_MLID 0x00000008 +#define IB_MCMEMBER_RECORD_COMP_MTUSELECTOR 0x00000010 +#define IB_MCMEMBER_RECORD_COMP_MTU 0x00000020 +#define IB_MCMEMBER_RECORD_COMP_TCLASS 0x00000040 +#define IB_MCMEMBER_RECORD_COMP_PKEY 0x00000080 +#define IB_MCMEMBER_RECORD_COMP_RATESELECTOR 0x00000100 +#define IB_MCMEMBER_RECORD_COMP_RATE 0x00000200 +#define IB_MCMEMBER_RECORD_COMP_PKTLIFESELECTOR 0x00000400 +#define IB_MCMEMBER_RECORD_COMP_PKTLIFE 0x00000800 +#define IB_MCMEMBER_RECORD_COMP_SL 0x00001000 +#define IB_MCMEMBER_RECORD_COMP_FLOWLABEL 0x00002000 +#define IB_MCMEMBER_RECORD_COMP_HOPLIMIT 0x00004000 +#define IB_MCMEMBER_RECORD_COMP_SCOPE 0x00008000 +#define IB_MCMEMBER_RECORD_COMP_JOINSTATE 0x00010000 +#define IB_MCMEMBER_RECORD_COMP_PROXYJOIN 0x00020000 + /* reserved field 0x00040000 */ + +typedef struct _IB_MCMEMBER_RECORD { + struct { + IB_GID MGID; + IB_GID PortGID; + } PACK_SUFFIX RID; + uint32 Q_Key; /* Q_Key supplied at Multicast Group */ + /* creation time by the creator. */ + IB_LID MLID; /* Multicast LID. Assigned by SM/SA */ + /* at creation time. */ +#if CPU_BE + uint8 MtuSelector :2; /* enum IB_SELECTOR */ + uint8 Mtu :6; /* enum IB_MTU */ +#else + uint8 Mtu :6; /* enum IB_MTU */ + uint8 MtuSelector :2; /* enum IB_SELECTOR */ +#endif + uint8 TClass; /* GRH Traffic Class */ + uint16 P_Key; /* Partition Key */ +#if CPU_BE + uint8 RateSelector:2; /* enum IB_SELECTOR */ + uint8 Rate :6; /* enum IB_STATIC_RATE */ +#else + uint8 Rate :6; /* enum IB_STATIC_RATE */ + uint8 RateSelector:2; /* enum IB_SELECTOR */ +#endif + + /* ***************************************** */ + /* *** User be aware that the CM LifeTime & */ + /* *** TimeOut values are only 5-bit wide. */ + /* ***************************************** */ + /* */ + /* Accumulated packet life time for the path specified by an enumeration */ + /* deried from 4.096 usec * 2^PktLifeTime */ +#if CPU_BE + uint8 PktLifeTimeSelector:2; /* enum IB_SELECTOR */ + uint8 PktLifeTime :6; +#else + uint8 PktLifeTime :6; + uint8 PktLifeTimeSelector:2; /* enum IB_SELECTOR */ +#endif + union { + uint32 AsReg32; + struct { +#if CPU_BE + uint32 SL:4; + uint32 FlowLabel:20; + uint32 HopLimit:8; +#else + uint32 HopLimit:8; + uint32 FlowLabel:20; + uint32 SL:4; +#endif + } PACK_SUFFIX s; + } u1; +#if CPU_BE + uint8 Scope:4; + uint8 Reserved:1; + uint8 JoinSendOnlyMember:1; + uint8 JoinNonMember:1; + uint8 JoinFullMember:1; +#else + uint8 JoinFullMember:1; + uint8 JoinNonMember:1; + uint8 JoinSendOnlyMember:1; + uint8 Reserved:1; + uint8 Scope:4; +#endif +#if CPU_BE + uint8 ProxyJoin:1; + uint8 Reserved2:7; +#else + uint8 Reserved2:7; + uint8 ProxyJoin:1; +#endif + uint8 Reserved3[2]; /* TBD spec has odd size here */ +} PACK_SUFFIX IB_MCMEMBER_RECORD; + + + + +/* -------------------------------------------------------------------------- + * Trace Record - trace a path through the fabric + */ + +/* ComponentMask bits */ +#define IB_TRACE_RECORD_COMP_GIDPREFIX 0x00000001 +#define IB_TRACE_RECORD_COMP_IDGENERATION 0x00000002 + /* reserved field 0x00000004 */ +#define IB_TRACE_RECORD_COMP_NODETYPE 0x00000008 +#define IB_TRACE_RECORD_COMP_NODEID 0x00000010 +#define IB_TRACE_RECORD_COMP_CHASSISID 0x00000020 +#define IB_TRACE_RECORD_COMP_ENTRYPORTID 0x00000040 +#define IB_TRACE_RECORD_COMP_EXITPORTID 0x00000080 +#define IB_TRACE_RECORD_COMP_ENTRYPORT 0x00000100 +#define IB_TRACE_RECORD_COMP_EXITPORT 0x00000200 + +#define IB_TRACE_RECORD_COMP_ENCRYPT_MASK 0x55555555 + +typedef struct _IB_TRACE_RECORD { + uint64 GIDPrefix; /* subnet in which IDs are consistent */ + uint16 IDGeneration; + uint8 Reserved; + uint8 NodeType; /* see NODE_INFO */ + uint64 NodeID; + uint64 ChassisID; + uint64 EntryPortID; + uint64 ExitPortID; + uint8 EntryPort; + uint8 ExitPort; +} PACK_SUFFIX IB_TRACE_RECORD; + + +/* -------------------------------------------------------------------------- + * Multipath Record - a set of paths between nodes in the fabric + */ + +/* ComponentMask bits */ +#define IB_MULTIPATH_RECORD_COMP_RAWTRAFFIC 0x00000001 + /* reserved field 0x00000002 */ +#define IB_MULTIPATH_RECORD_COMP_FLOWLABEL 0x00000004 +#define IB_MULTIPATH_RECORD_COMP_HOPLIMIT 0x00000008 +#define IB_MULTIPATH_RECORD_COMP_TCLASS 0x00000010 +#define IB_MULTIPATH_RECORD_COMP_REVERSIBLE 0x00000020 +#define IB_MULTIPATH_RECORD_COMP_NUMBPATH 0x00000040 +#define IB_MULTIPATH_RECORD_COMP_PKEY 0x00000080 + /* reserved field 0x00000100 */ +#define IB_MULTIPATH_RECORD_COMP_SL 0x00000200 +#define IB_MULTIPATH_RECORD_COMP_MTUSELECTOR 0x00000400 +#define IB_MULTIPATH_RECORD_COMP_MTU 0x00000800 +#define IB_MULTIPATH_RECORD_COMP_RATESELECTOR 0x00001000 +#define IB_MULTIPATH_RECORD_COMP_RATE 0x00002000 +#define IB_MULTIPATH_RECORD_COMP_PKTLIFESELECTOR 0x00004000 +#define IB_MULTIPATH_RECORD_COMP_PKTLIFE 0x00008000 +#define IB_MULTIPATH_RECORD_COMP_SERVICEID8MSB 0x00010000 +#define IB_MULTIPATH_RECORD_COMP_INDEPENDENCESELECTOR 0x00020000 + /* reserved field 0x00040000 */ +#define IB_MULTIPATH_RECORD_COMP_SGIDCOUNT 0x00080000 +#define IB_MULTIPATH_RECORD_COMP_DGIDCOUNT 0x00100000 +#define IB_MULTIPATH_RECORD_COMP_SERVICEID56LSB 0x00200000 + /* SDGID list follows, no component mask bits */ + /* since SGID/DGIDCOUNT indicates number present */ + +// Convenience define that combines the 8MSB and 56LSB bits. +#define IB_MULTIPATH_RECORD_COMP_SERVICEID 0x00210000 + +// The most sgids or dgids you can have. Thus, the total # of GIDS is +// twice this. +#define IB_MULTIPATH_RECORD_MAX_GIDCOUNT 255 + +typedef struct _IB_MULTIPATH_RECORD { + union { + uint32 AsReg32; + struct { +#if CPU_BE + uint32 RawTraffic:1; + uint32 Reserved:3; + uint32 FlowLabel:20; + uint32 HopLimit:8; +#else + uint32 HopLimit:8; + uint32 FlowLabel:20; + uint32 Reserved:3; + uint32 RawTraffic:1; +#endif + } PACK_SUFFIX s; + } u1; + uint8 TClass; +#if CPU_BE + uint8 Reversible:1; + uint8 NumbPath:7; +#else + uint8 NumbPath:7; + uint8 Reversible:1; +#endif + uint16 P_Key; + union { + uint16 AsReg16; + struct { +#if CPU_BE + uint16 Reserved2:12; + uint16 SL:4; +#else + uint16 SL:4; + uint16 Reserved2:12; +#endif + } PACK_SUFFIX s; + } u2; +#if CPU_BE + uint8 MtuSelector :2; /* enum IB_SELECTOR */ + uint8 Mtu :6; /* enum IB_MTU */ +#else + uint8 Mtu :6; /* enum IB_MTU */ + uint8 MtuSelector :2; /* enum IB_SELECTOR */ +#endif + +#if CPU_BE + uint8 RateSelector:2; /* enum IB_SELECTOR */ + uint8 Rate :6; /* enum IB_STATIC_RATE */ +#else + uint8 Rate :6; /* enum IB_STATIC_RATE */ + uint8 RateSelector:2; /* enum IB_SELECTOR */ +#endif + + /* ***************************************** + * *** User be aware that the CM LifeTime & + * *** TimeOut values are only 5-bit wide. + * ***************************************** */ + /* Accumulated packet life time for the path specified by an enumeration */ + /* deried from 4.096 usec * 2^PktLifeTime */ +#if CPU_BE + uint8 PktLifeTimeSelector:2; /* enum IB_SELECTOR */ + uint8 PktLifeTime :6; +#else + uint8 PktLifeTime :6; + uint8 PktLifeTimeSelector:2; /* enum IB_SELECTOR */ +#endif + uint8 serviceID8msb; +#if CPU_BE + uint8 IndependenceSelector:2; /* 1->as fault independent as possible */ + /* 0,2,3 reserved */ + uint8 Reserved4:6; +#else + uint8 Reserved4:6; + uint8 IndependenceSelector:2; /* 1->as fault independent as possible */ + /* 0,2,3 reserved */ +#endif + uint8 SGIDCount; + uint8 DGIDCount; + uint8 serviceID56lsb[7]; + IB_GID GIDList[1]; /* SGIDCount source GIDs */ + /* followed by DGIDCount dest GIDs */ +} PACK_SUFFIX IB_MULTIPATH_RECORD; + +#include "iba/public/ipackoff.h" + +#ifdef __cplusplus +} +#endif + +#endif /* _IBA_IB_SA_RECORDS_H_ */ diff --git a/IbAccess/Common/Inc/ib_sa_records_priv.h b/IbAccess/Common/Inc/ib_sa_records_priv.h new file mode 100644 index 0000000..52b6a68 --- /dev/null +++ b/IbAccess/Common/Inc/ib_sa_records_priv.h @@ -0,0 +1,653 @@ +/* BEGIN_ICS_COPYRIGHT3 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT3 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +#ifndef _IBA_IB_SA_RECORDS_PRIV_H_ +#define _IBA_IB_SA_RECORDS_PRIV_H_ + +#include "iba/ib_sm_priv.h" +#include "iba/ib_sa_records.h" +#include "iba/stl_helper.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#include "iba/public/ipackon.h" + +static __inline void +BSWAP_IB_NODE_RECORD( + IB_NODE_RECORD *Dest + ) +{ +#if CPU_LE + Dest->RID.AsReg32 = ntoh32(Dest->RID.AsReg32); + BSWAP_NODE_INFO(&Dest->NodeInfoData); +#endif /* CPU_LE */ +} + +static __inline void +BSWAP_IB_PORTINFO_RECORD( + IB_PORTINFO_RECORD *Dest, int extended + ) +{ +#if CPU_LE + + Dest->RID.AsReg32 = ntoh32(Dest->RID.AsReg32); + BSWAP_PORT_INFO(&Dest->PortInfoData, extended); +#endif +} + +/* -------------------------------------------------------------------------- + * Switch Info Record - information about a switch in the fabric + */ + +/* ComponentMask bits */ +#define IB_SWITCHINFO_RECORD_COMP_LID 0x00000001 + /* reserved field 0x00000002*/ + /* switch info fields */ +#define IB_SWITCHINFO_RECORD_COMP_LINEARFDBCAP 0x00000004 +#define IB_SWITCHINFO_RECORD_COMP_RANDOMFDBCAP 0x00000008 +#define IB_SWITCHINFO_RECORD_COMP_MULTICASTFDBCAP 0x00000010 +#define IB_SWITCHINFO_RECORD_COMP_LINEARFDBTOP 0x00000020 +#define IB_SWITCHINFO_RECORD_COMP_DEFAULTPORT 0x00000040 +#define IB_SWITCHINFO_RECORD_COMP_DEFAULTMULTICASTPRIMARYPORT 0x00000080 +#define IB_SWITCHINFO_RECORD_COMP_DEFAULTMULTICASTNOTPRIMARYPORT 0x00000100 +#define IB_SWITCHINFO_RECORD_COMP_LIFETIMEVALUE 0x00000200 +#define IB_SWITCHINFO_RECORD_COMP_PORTSTATECHANGE 0x00000400 + /* reserved field 0x00000800*/ +#define IB_SWITCHINFO_RECORD_COMP_LIDSPERPORT 0x00001000 +#define IB_SWITCHINFO_RECORD_COMP_PARTITIONENFORCEMENTCAP 0x00002000 +#define IB_SWITCHINFO_RECORD_COMP_INBOUNDENFORCEMENTCAP 0x00004000 +#define IB_SWITCHINFO_RECORD_COMP_OUTBOUNDENFORCEMENTCAP 0x00008000 +#define IB_SWITCHINFO_RECORD_COMP_FILTERRAWINBOUNDCAP 0x00010000 +#define IB_SWITCHINFO_RECORD_COMP_FILTERRAWOUTBOUNDCAP 0x00020000 +#define IB_SWITCHINFO_RECORD_COMP_ENHANCEDPORT0 0x00040000 + /* reserved field 0x00080000*/ + +typedef struct _IB_SWITCHINFO_RECORD { + union { + uint32 AsReg32; + struct { +#if CPU_BE + uint32 LID:16; + uint32 Reserved:16; +#else + uint32 Reserved:16; + uint32 LID:16; +#endif + } PACK_SUFFIX s; + } RID; + SWITCH_INFO SwitchInfoData; +} PACK_SUFFIX IB_SWITCHINFO_RECORD; + +static __inline void +BSWAP_IB_SWITCHINFO_RECORD( + IB_SWITCHINFO_RECORD *Dest + ) +{ +#if CPU_LE + + Dest->RID.AsReg32 = ntoh32(Dest->RID.AsReg32); + BSWAP_SWITCH_INFO(&Dest->SwitchInfoData); +#endif +} + +/* -------------------------------------------------------------------------- + * Linear Forwarding Table Record - linear forwarding table for a switch in the fabric + */ + +/* ComponentMask bits */ +#define IB_LINEARFDB_RECORD_COMP_LID 0x00000001 +#define IB_LINEARFDB_RECORD_COMP_BLOCKNUM 0x00000002 + /* reserved field 0x00000004 */ + /* linear forwarding table fields */ + /* Note insufficient bits in component mask to select */ + /* all 64 entries in record */ + +typedef struct _IB_LINEAR_FDB_RECORD { + union { + uint32 AsReg32; + struct { +#if CPU_BE + uint32 LID:16; + uint32 BlockNum:16; +#else + uint32 BlockNum:16; + uint32 LID:16; +#endif + } PACK_SUFFIX s; + } RID; + uint32 Reserved; + FORWARDING_TABLE LinearFdbData; +} PACK_SUFFIX IB_LINEAR_FDB_RECORD; + +static __inline void +BSWAP_IB_LINEAR_FDB_RECORD( + IB_LINEAR_FDB_RECORD *Dest + ) +{ +#if CPU_LE + Dest->RID.AsReg32 = ntoh32(Dest->RID.AsReg32); + BSWAP_LINEAR_FWD_TABLE(&Dest->LinearFdbData); +#endif +} + +/* -------------------------------------------------------------------------- + * Random Forwarding Table Record - random forwarding table for a switch in the fabric + */ + +/* ComponentMask bits */ +#define IB_RANDOMFDB_RECORD_COMP_LID 0x00000001 +#define IB_RANDOMFDB_RECORD_COMP_BLOCKNUM 0x00000002 + /* reserved field 0x00000004 */ + /* random forwarding table fields */ + /* Note insufficient bits in component mask to select */ + /* all 5 fields in all 16 entries in record */ + +typedef struct _IB_RANDOM_FDB_RECORD { + union { + uint32 AsReg32; + struct { +#if CPU_BE + uint32 LID:16; + uint32 BlockNum:16; +#else + uint32 BlockNum:16; + uint32 LID:16; +#endif + } PACK_SUFFIX s; + } RID; + uint32 Reserved; + FORWARDING_TABLE RandomFdbData; +} PACK_SUFFIX IB_RANDOM_FDB_RECORD; + +static __inline void +BSWAP_IB_RANDOM_FDB_RECORD( + IB_RANDOM_FDB_RECORD *Dest + ) +{ +#if CPU_LE + Dest->RID.AsReg32 = ntoh32(Dest->RID.AsReg32); + BSWAP_RANDOM_FWD_TABLE(&Dest->RandomFdbData); +#endif +} + +/* -------------------------------------------------------------------------- + * Multicast Forwarding Table Record - multicast forwarding table for a + * switch in the fabric + */ + +/* ComponentMask bits */ +#define IB_MCASTFDB_RECORD_COMP_LID 0x00000001 +#define IB_MCASTFDB_RECORD_COMP_POSITION 0x00000002 + /* reserved field 0x00000004 */ +#define IB_MCASTFDB_RECORD_COMP_BLOCKNUM 0x00000008 + /* reserved field 0x00000010 */ + /* multicast forwarding table fields */ + /* limited value to select on these, so omitted defines */ + +typedef struct _IB_MCAST_FDB_RECORD { + union { + uint32 AsReg32; + struct { +#if CPU_BE + uint32 LID:16; + uint32 Position:4; + uint32 Reserved0:3; + uint32 BlockNum:9; +#else + uint32 BlockNum:9; + uint32 Reserved0:3; + uint32 Position:4; + uint32 LID:16; +#endif + } PACK_SUFFIX s; + } RID; + uint32 Reserved; + FORWARDING_TABLE MCastFdbData; +} PACK_SUFFIX IB_MCAST_FDB_RECORD; + +static __inline void +BSWAP_IB_MCAST_FDB_RECORD( + IB_MCAST_FDB_RECORD *Dest + ) +{ +#if CPU_LE + Dest->RID.AsReg32 = ntoh32(Dest->RID.AsReg32); + BSWAP_MCAST_FWD_TABLE(&Dest->MCastFdbData); +#endif +} + +/* -------------------------------------------------------------------------- + * VL Arbitration Table Record - VL priority controls for a port on a node in + * the fabric + */ + +/* ComponentMask bits */ +#define IB_VLARBTABLE_RECORD_COMP_LID 0x00000001 +#define IB_VLARBTABLE_RECORD_COMP_OUTPUTPORTNUM 0x00000002 +#define IB_VLARBTABLE_RECORD_COMP_BLOCKNUM 0x00000004 + /* reserved field 0x00000008 */ + /* Note insufficient bits in component mask to select */ + /* all 3 fields in all 32 entries in record */ + +typedef struct _IB_VLARBTABLE_RECORD { + union { + uint32 AsReg32; + struct { +#if CPU_BE + uint32 LID:16; + uint32 OutputPortNum:8; + uint32 BlockNum:8; +#else + uint32 BlockNum:8; + uint32 OutputPortNum:8; + uint32 LID:16; +#endif + } PACK_SUFFIX s; + } RID; + uint32 Reserved; + VLARBTABLE VLArbData; /* VLArbitration attribute */ +} PACK_SUFFIX IB_VLARBTABLE_RECORD; + +static __inline void +BSWAP_IB_VLARBTABLE_RECORD( + IB_VLARBTABLE_RECORD *Dest + ) +{ +#if CPU_LE + Dest->RID.AsReg32 = ntoh32(Dest->RID.AsReg32); + BSWAP_VLARBTABLE(&Dest->VLArbData); +#endif +} + +/* -------------------------------------------------------------------------- + * SM Info Record - basic information about an SM in the fabric + */ + +/* ComponentMask bits */ +#define IB_SMINFO_RECORD_COMP_LID 0x00000001 + /* reserved field 0x00000002 */ + /* SM Info fields */ +#define IB_SMINFO_RECORD_COMP_GUID 0x00000004 +#define IB_SMINFO_RECORD_COMP_SMKEY 0x00000008 +#define IB_SMINFO_RECORD_COMP_ACTCOUNT 0x00000010 +#define IB_SMINFO_RECORD_COMP_PRIORITY 0x00000020 +#define IB_SMINFO_RECORD_COMP_SMSTATE 0x00000040 + +typedef struct _IB_SMINFO_RECORD { + union { + uint32 AsReg32; + struct { +#if CPU_BE + uint32 LID:16; + uint32 Reserved:16; +#else + uint32 Reserved:16; + uint32 LID:16; +#endif + } PACK_SUFFIX s; + } RID; + SM_INFO SMInfoData; /* SMInfo attribute */ +} PACK_SUFFIX IB_SMINFO_RECORD; + +static __inline void +BSWAP_IB_SMINFO_RECORD( + IB_SMINFO_RECORD *Dest + ) +{ +#if CPU_LE + Dest->RID.AsReg32 = ntoh32(Dest->RID.AsReg32); + BSWAP_SM_INFO(&Dest->SMInfoData); +#endif +} + +/* -------------------------------------------------------------------------- + * P_Key Table Record - P-Key configuration for a port on a node in the fabric + */ + +/* ComponentMask bits */ +#define IB_PKEYTABLE_RECORD_COMP_LID 0x00000001 +#define IB_PKEYTABLE_RECORD_COMP_BLOCKNUM 0x00000002 +#define IB_PKEYTABLE_RECORD_COMP_PORTNUM 0x00000004 + /* reserved field 0x00000008 */ + /* P Key Table fields */ + /* limited value to select on these, so omitted defines */ + +typedef struct _IB_P_KEY_TABLE_RECORD { + union { + struct { + uint32 AsReg32; + uint8 Byte; + } PACK_SUFFIX s2; + struct { +#if CPU_BE + uint32 LID:16; + uint32 BlockNum:16; +#else + uint32 BlockNum:16; + uint32 LID:16; +#endif + uint8 PortNum; + } PACK_SUFFIX s; + } PACK_SUFFIX RID; + uint8 Reserved[3]; + PARTITION_TABLE PKeyTblData; /* PartitionTable for this port */ +} PACK_SUFFIX IB_P_KEY_TABLE_RECORD; + +static __inline void +BSWAP_IB_P_KEY_TABLE_RECORD( + IB_P_KEY_TABLE_RECORD *Dest + ) +{ +#if CPU_LE + Dest->RID.s2.AsReg32 = ntoh32(Dest->RID.s2.AsReg32); + BSWAP_PART_TABLE(&Dest->PKeyTblData); +#endif +} + +static __inline void +BSWAP_IB_INFORM_INFO_RECORD( + IB_INFORM_INFO_RECORD *Dest + ) +{ +#if CPU_LE + BSWAP_IB_GID(&Dest->RID.SubscriberGID); + Dest->RID.Enum = ntoh16(Dest->RID.Enum); + BSWAP_INFORM_INFO(&Dest->InformInfoData); +#endif +} + +/* -------------------------------------------------------------------------- + * Link Record - details about a link in the fabric + */ + +/* ComponentMask bits */ +#define IB_LINK_RECORD_COMP_FROMLID 0x00000001 +#define IB_LINK_RECORD_COMP_FROMPORT 0x00000002 +#define IB_LINK_RECORD_COMP_TOPORT 0x00000004 +#define IB_LINK_RECORD_COMP_TOLID 0x00000008 + +typedef struct _IB_LINK_RECORD { + struct { + uint16 FromLID; /* From this LID */ + uint8 FromPort; /* From port number */ + } PACK_SUFFIX RID; + uint8 ToPort; /* To port number */ + uint16 ToLID; /* To this LID */ +} PACK_SUFFIX IB_LINK_RECORD; + +static __inline void +BSWAP_IB_LINK_RECORD( + IB_LINK_RECORD *Dest + ) +{ +#if CPU_LE + Dest->RID.FromLID = ntoh16(Dest->RID.FromLID); + Dest->ToLID = ntoh16(Dest->ToLID); +#endif /* CPU_LE */ +} + +static __inline void +BSWAP_IB_SERVICE_RECORD( + IB_SERVICE_RECORD *Dest + ) +{ +#if CPU_LE + uint8 i; + + Dest->RID.ServiceID = ntoh64(Dest->RID.ServiceID); + BSWAP_IB_GID(&Dest->RID.ServiceGID); + Dest->RID.ServiceP_Key = ntoh16(Dest->RID.ServiceP_Key); + Dest->ServiceLease = ntoh32(Dest->ServiceLease); + ntoh(&Dest->ServiceKey[0], &Dest->ServiceKey[0], 16); + + for (i=0; i<8; ++i) + { + Dest->ServiceData16[i] = ntoh16(Dest->ServiceData16[i]); + } + for (i=0; i<4; ++i) + { + Dest->ServiceData32[i] = ntoh32(Dest->ServiceData32[i]); + } + for (i=0; i<2; ++i) + { + Dest->ServiceData64[i] = ntoh64(Dest->ServiceData64[i]); + } +#endif /* CPU_LE */ +} + +static __inline void +BSWAP_IB_MCMEMBER_RECORD( + IB_MCMEMBER_RECORD *Dest + ) +{ +#if CPU_LE + BSWAP_IB_GID(&Dest->RID.MGID); + BSWAP_IB_GID(&Dest->RID.PortGID); + Dest->Q_Key = ntoh32(Dest->Q_Key); + Dest->MLID = ntoh16(Dest->MLID); + Dest->P_Key = ntoh16(Dest->P_Key); + Dest->u1.AsReg32 = ntoh32(Dest->u1.AsReg32); +#endif /* CPU_LE */ +} + +static __inline void +BSWAPCOPY_IB_MCMEMBER_RECORD(IB_MCMEMBER_RECORD *Src, IB_MCMEMBER_RECORD *Dest) +{ + memcpy(Dest, Src, sizeof(IB_MCMEMBER_RECORD)); + BSWAP_IB_MCMEMBER_RECORD(Dest); +} + +static __inline void +BSWAP_IB_TRACE_RECORD( + IB_TRACE_RECORD *Dest + ) +{ +#if CPU_LE + Dest->GIDPrefix = ntoh64(Dest->GIDPrefix); + Dest->IDGeneration = ntoh16(Dest->IDGeneration); + Dest->NodeID = ntoh64(Dest->NodeID); + Dest->ChassisID = ntoh64(Dest->ChassisID); + Dest->EntryPortID = ntoh64(Dest->EntryPortID); + Dest->ExitPortID = ntoh64(Dest->ExitPortID); +#endif +} + +static __inline void +BSWAP_IB_MULTIPATH_RECORD( + IB_MULTIPATH_RECORD *Dest + ) +{ +#if CPU_LE + uint8 i; + Dest->u1.AsReg32 = ntoh32(Dest->u1.AsReg32); + Dest->P_Key = ntoh16(Dest->P_Key); + Dest->u2.AsReg16 = ntoh16(Dest->u2.AsReg16); + + /* TBD - sanity check Counts */ + for (i=0; i<(Dest->SGIDCount + Dest->DGIDCount); ++i) + { + BSWAP_IB_GID(&Dest->GIDList[i]); + } +#endif +} + +static __inline void +BSWAP_IB_PATH_RECORD( + IB_PATH_RECORD *Dest + ) +{ +#if CPU_LE + Dest->ServiceID = ntoh64(Dest->ServiceID); + BSWAP_IB_GID(&Dest->DGID); + BSWAP_IB_GID(&Dest->SGID); + + Dest->DLID = ntoh16(Dest->DLID); + Dest->SLID = ntoh16(Dest->SLID); + Dest->u1.AsReg32 = ntoh32(Dest->u1.AsReg32); + Dest->P_Key = ntoh16(Dest->P_Key); + Dest->u2.AsReg16 = ntoh16(Dest->u2.AsReg16); +#endif /* CPU_LE */ +} + +static __inline void +BSWAPCOPY_IB_PATH_RECORD( + IB_PATH_RECORD *Src, IB_PATH_RECORD *Dest + ) +{ + memcpy(Dest, Src, sizeof(IB_PATH_RECORD)); + BSWAP_IB_PATH_RECORD(Dest); +} + +/* determine if the given PATH_RECORD represents a global route + * (eg. where GRH is used to go through an IB Router) + */ +static __inline boolean +IsGlobalRoute( IN const IB_PATH_RECORD *pPathRecord) +{ + return (pPathRecord->u1.s.HopLimit > 1); +} + +/* compute LocalAckTimeout from PktLifeTime + * note PktLifetime is one directional on wire, while LocalAckTimeout is + * total round trip including CA Ack Delay + * for client REQ.AckTimeout, caAckDelay should be our local CA's AckDelay + * for client QP, use REP.TargetAckDelay + * for server QP, use REQ.AckTimeout directly (no need to call this) + * pktLifeTime, caAckDelay and returned values are IB timeout multipliers + */ +static __inline uint8 +ComputeAckTimeout(IN uint8 pktLifeTime, IN uint8 caAckDelay) +{ + /* return TimeoutTimeToMult(TimeoutMultToTimeInUsec(pktLifeTime)*2 */ + /* + TimeoutMultToTimeInUsec(caAckDelay)); */ + /*return MIN(pktLifeTime + 2, 0x1f); */ + uint8 ackTimeout; + + /* tests also handle if remote endpoint didn't set REP.TargetAckDelay */ + if (pktLifeTime+1 >= caAckDelay) + { + /* since its a log2 value, +1 doubles the timeout */ + /* Additional +1 is to account for remote CA Ack delay */ + ackTimeout = pktLifeTime+2; + } else { + /* since caAckDelay > 2*pktLifetime, +1 simply doubles ca Ack Delay */ + ackTimeout = caAckDelay+1; + } + /* limit value to 5 bits (approx 2.4 hours) */ + if (ackTimeout > 0x1f) + ackTimeout = 0x1f; + return ackTimeout; +} + +#ifndef IB_STACK_OPENIB +/* helper function, converts a PATH_RECORD to an IB_ADDRESS_VECTOR to facilitate + * connection establishment and UD traffic + * PathMTU is an IB_MTU enum + */ +static __inline void +GetAVFromPath2( IN uint64 PortGuid, /* only needed for UD AVs */ + IN const IB_PATH_RECORD *pPathRecord, + OUT uint8* PathMTU OPTIONAL, + OUT IB_ADDRESS_VECTOR* DestAv OPTIONAL ) +{ + if (DestAv) + { + DestAv->PortGUID = PortGuid; /* only needed for UD AVs */ + DestAv->DestLID = pPathRecord->DLID; + DestAv->PathBits = (uint8)(pPathRecord->SLID&IB_PATHBITS_MASK); + DestAv->ServiceLevel = pPathRecord->u2.s.SL; + DestAv->StaticRate = pPathRecord->Rate; + + /* Global route information. */ + DestAv->GlobalRoute = IsGlobalRoute(pPathRecord); + DestAv->GlobalRouteInfo.DestGID = pPathRecord->DGID; + DestAv->GlobalRouteInfo.FlowLabel = pPathRecord->u1.s.FlowLabel; + DestAv->GlobalRouteInfo.HopLimit = (uint8)pPathRecord->u1.s.HopLimit; + DestAv->GlobalRouteInfo.SrcGIDIndex = 0; /* BUGBUG assume 0 */ + DestAv->GlobalRouteInfo.TrafficClass = pPathRecord->TClass; + } + + /* Reliable connection information, N/A for UD */ + if (PathMTU) + *PathMTU = pPathRecord->Mtu; +} + +/* This function is depricated, will be dropped in 3.1 release, + * use GetAVFromPath2 above + */ +static __inline void +GetAVFromPath( IN uint64 PortGuid, /* only needed for UD AVs */ + IN const IB_PATH_RECORD *pPathRecord, + OUT uint8* PathMTU OPTIONAL, OUT uint8* LocalAckTimeout OPTIONAL, + OUT IB_ADDRESS_VECTOR* DestAv OPTIONAL ) +{ + GetAVFromPath2(PortGuid, pPathRecord, PathMTU, DestAv); + if (LocalAckTimeout) + *LocalAckTimeout = ComputeAckTimeout(pPathRecord->PktLifeTime, + TimeoutTimeToMult(8)); /* guess: 8 ms */ +} + +/* helper function, converts a MCMEMBER_RECORD to an IB_ADDRESS_VECTOR to + * facilitate UD traffic + */ +static __inline void +GetAVFromMcMemberRecord(EUI64 PortGuid, + IB_MCMEMBER_RECORD *pMcMemberRecord, + IB_ADDRESS_VECTOR *pDestAv ) +{ + if (pDestAv != NULL) + { + pDestAv->PortGUID = pMcMemberRecord->RID.PortGID.Type.Global.InterfaceID; + pDestAv->DestLID = pMcMemberRecord->MLID; +/* pDestAv->PathBits = (uint8)pPathRecord->SLID; */ + pDestAv->PathBits = 0; + pDestAv->ServiceLevel = pMcMemberRecord->u1.s.SL; + pDestAv->StaticRate = pMcMemberRecord->Rate; + + /* Global route information. */ + pDestAv->GlobalRoute = TRUE; + pDestAv->GlobalRouteInfo.DestGID = pMcMemberRecord->RID.MGID; + pDestAv->GlobalRouteInfo.FlowLabel = pMcMemberRecord->u1.s.FlowLabel; + pDestAv->GlobalRouteInfo.HopLimit = (uint8)pMcMemberRecord->u1.s.HopLimit; + pDestAv->GlobalRouteInfo.SrcGIDIndex = 0; /* BUGBUG assume 0 */ + pDestAv->GlobalRouteInfo.TrafficClass = pMcMemberRecord->TClass; + } +} + +#endif /* IB_STACK_OPENIB */ + +#ifdef __cplusplus +} +#endif + +#endif /* _IBA_IB_SA_RECORDS_PRIV_H_ */ diff --git a/IbAccess/Common/Inc/ib_sd.h b/IbAccess/Common/Inc/ib_sd.h new file mode 100644 index 0000000..84061a9 --- /dev/null +++ b/IbAccess/Common/Inc/ib_sd.h @@ -0,0 +1,786 @@ +/* BEGIN_ICS_COPYRIGHT3 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT3 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +#ifndef _IBA_IB_SD_H_ +#define _IBA_IB_SD_H_ + +/* IB Subnet Data Interface + * The subnet data interface provides a simplied interface to the SM/SA and + * automates queries, sets and deletes for commonly required information + * from the SM/SA. + * + * The subnet data interface automatically handles the following: + * - retries (client configurable) + * - timeouts (client configurable) + * - RMPP response coallessing and inter-record padding + * - extraction of selected fields from a query to provide a concise response + * to client + * - multi-tiered queries (get paths to a node, etc) + * + * New drivers/applications should use the iba_* functions. + * They can now be called directly. + */ + +#include +#include +#include +#ifndef IB_STACK_OPENIB +#if defined(VXWORKS) +#include +#ifdef BUILD_CM +#include +#endif +#endif + +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#define TIMEOUT_INFINITE 0 +#define RETRYCOUNT_INVALID 0xffffffff /* used internally to flag */ + /* lack of control parameters */ + +/* default command control parameters, used if not specified by client for + * open session nor for query/fabric operation calls + */ +#define DEFAULT_SD_TIMEOUT 20000 /* 20 Seconds */ +#define DEFAULT_SD_RETRY_COUNT 3 + +/* ClientDebug Flags, affects level of output to debug log for given client */ +#define SD_DBG_SILENT 0x00000000 +#define SD_DBG_ERROR 0x00000001 +#define SD_DBG_INFO 0x00000002 +#define SD_DBG_TRACE 0x00000004 +#define DBG_SILENT SD_DBG_SILENT/* DBG_SILENT is deprecated */ +#define DBG_ERROR SD_DBG_ERROR /* DBG_ERROR is deprecated*/ +#define DBG_INFO SD_DBG_INFO /* DBG_INFO is deprecated */ +#define DBG_TRACE SD_DBG_TRACE /* DBG_TRACE is deprecated*/ + +typedef void *CLIENT_HANDLE; + +/* parameters for query and fabric operation error handling */ +typedef struct _COMMAND_CONTROL_PARAMETERS { + uint32 RetryCount; /* 0=no retries, >=1 # retries if initial attempt fails */ + /* retries are only performed upon timeout */ + /* requests with a failed response are not retried */ + uint32 Timeout; /* in milliseconds */ +} COMMAND_CONTROL_PARAMETERS, *PCOMMAND_CONTROL_PARAMETERS; + +#define SD_OPTION_CACHED 0x00000001 /* No new query if info already available */ + +/* per client selection of default parameters for all queries */ +typedef struct _CLIENT_CONTROL_PARAMETERS { + COMMAND_CONTROL_PARAMETERS ControlParameters; + uint32 ClientDebugFlags; + uint32 OptionFlags; +} CLIENT_CONTROL_PARAMETERS, *PCLIENT_CONTROL_PARAMETERS; + +/* multicast flag values */ +#define MC_FLAG_NONE 0x0000 +#define MC_FLAG_WANT_UNAVAILABLE 0x0001 /* want callback when group becomes unavailable */ + +/* multicast group state values */ +typedef enum +{ + MC_GROUP_STATE_REQUEST_JOIN, + MC_GROUP_STATE_REQUEST_LEAVE, + MC_GROUP_STATE_JOIN_FAILED, + MC_GROUP_STATE_AVAILABLE, + MC_GROUP_STATE_UNAVAILABLE +} MC_GROUP_STATE; + +/* ---------------------------------------------------------------------------- + * QueryFabricInformation + * Data structures used to perform Queries of the SA/SM via one or more + * Get or GetTable RMPP sequences + */ + +/* QueryFabricInformation combinations Supported: + * + * InputType OutputType Query performed + * --------- ---------- --------------- + * NoInput Lids SA GetTable all NodeRecords + * NoInput SystemImageGuid SA GetTable all NodeRecords + * NoInput NodeGuids SA GetTable all NodeRecords + * NoInput PortGuids SA GetTable all NodeRecords + * NoInput NodeDesc SA GetTable all NodeRecords + * NoInput NodeRecord SA GetTable all NodeRecords + * NoInput PortInfoRecord SA GetTable all PortInfoRecords + * NoInput SMInfoRecord SA GetTable all SMInfoRecords + * NoInput LinkRecord SA GetTable all LinkRecords + * NoInput ServiceRecord SA GetTable all ServiceRecords + * NoInput McMemberRecord SA GetTable all McMemberRecords + * NoInput InformInfoRecord SA GetTable all InformInfoRecords + * + * NoInput PathRecord SA GetTable all NodeRecords + * followed by a SA GetTable PathRecords + * from the local PortGuid and each + * Remote PortGuid reported in NodeRecords + * + * NoInput SwitchInfoRecord SA GetTable all SwitchInfoRecords + * NoInput LinearFDBRecord SA GetTable all LinearFDBRecords + * NoInput RandomFDBRecord SA GetTable all RandomFDBRecords + * NoInput MCastFDBRecord SA GetTable all MCastFDBRecords + * NoInput VLArbTableRecord SA GetTable all VLArbTableRecords + * NoInput PKeyTableRecord SA GetTable all PKeyTableRecords + * NoInput GuidInfoRecord SA GetTable all GuidInfoRecords + * + * NodeType Lids SA GetTable NodeRecords of NodeType + * NodeType SystemImageGuid SA GetTable NodeRecords of NodeType + * NodeType NodeGuids SA GetTable NodeRecords of NodeType + * NodeType PortGuids SA GetTable NodeRecords of NodeType + * NodeType NodeDesc SA GetTable NodeRecords of NodeType + * NodeType NodeRecord SA GetTable NodeRecords of NodeType + * + * NodeType PathRecord SA GetTable NodeRecords of NodeType + * followed by a SA GetTable PathRecords + * from the local PortGuid and each + * Remote PortGuid reported in NodeRecords + * + * SystemImageGuid Lids SA GetTable NodeRecords with SystemImageGuid + * SystemImageGuid SystemImageGuid SA GetTable NodeRecords with SystemImageGuid + * SystemImageGuid NodeGuids SA GetTable NodeRecords with SystemImageGuid + * SystemImageGuid PortGuids SA GetTable NodeRecords with SystemImageGuid + * SystemImageGuid NodeDesc SA GetTable NodeRecords with SystemImageGuid + * SystemImageGuid NodeRecord SA GetTable NodeRecords with SystemImageGuid + * + * SystemImageGuid PathRecord SA GetTable NodeRecords with SystemImageGuid + * followed by a SA GetTable PathRecords + * from the local PortGuid and each + * Remote PortGuid reported in NodeRecords + * + * NodeGuid Lids SA GetTable NodeRecords with NodeGuid + * NodeGuid SystemImageGuid SA GetTable NodeRecords with NodeGuid + * NodeGuid NodeGuids SA GetTable NodeRecords with NodeGuid + * NodeGuid PortGuids SA GetTable NodeRecords with NodeGuid + * NodeGuid NodeDesc SA GetTable NodeRecords with NodeGuid + * NodeGuid NodeRecord SA GetTable NodeRecords with NodeGuid + * + * NodeGuid PathRecord SA GetTable NodeRecords with NodeGuid + * followed by a SA GetTable PathRecords + * from the local PortGuid and each + * Remote PortGuid reported in NodeRecords + * + * PortGuid Lids SA GetTable NodeRecords with PortGuid + * PortGuid SystemImageGuid SA GetTable NodeRecords with PortGuid + * PortGuid NodeGuids SA GetTable NodeRecords with PortGuid + * PortGuid PortGuids SA GetTable NodeRecords with PortGuid + * PortGuid NodeDesc SA GetTable NodeRecords with PortGuid + * + * PortGuid NodeRecord SA GetTable NodeRecords with PortGuid + * followed by a SA GetTable PathRecords + * from the local PortGuid and each + * Remote PortGuid reported in NodeRecords + * + * PortGuid PathRecord SA GetTable PathRecords + * from the local PortGuid to the + * given Remote PortGuid + * + * PortGuid ServiceRecord SA GetTable ServiceRecords + * provided by given PortGuid + * + * PortGuid McMemberRecord SA GetTable McMemberRecords + * for the given PortGuid + * + * PortGuid TraceRecord SA GetTraceTable TraceRecords + * from the local PortGuid to the + * given Remote PortGuid + * + * PortGuid InformInfoRecord SA GetTable InformInfoRecords + * for the given PortGuid + * + * PortGid PathRecord SA GetTable PathRecords + * from the local PortGuid to the + * given Remote PortGid + * + * PortGid ServiceRecord SA GetTable ServiceRecords + * provided by given PortGid + * + * PortGid McMemberRecord SA GetTable McMemberRecords + * for the given PortGid + * + * PortGid InformInfoRecord SA GetTable InformInfoRecords + * for the given PortGid + * + * PortGid TraceRecord SA GetTraceTable TraceRecords + * from the local PortGuid to the + * given Remote PortGid + * + * McGid McMemberRecord SA GetTable McMemberRecords + * for the given Multicast Gid + * + * PortGuidPair PathRecord SA GetTable PathRecords + * from the given source PortGuid to the + * given destination PortGuid + * + * PortGuidPair TraceRecord SA GetTraceTable TraceRecords + * from the given source PortGuid to the + * given destination PortGuid + * + * GidPair PathRecord SA GetTable PathRecords + * from the given source Gid to the + * given destination Gid + * + * GidPair TraceRecord SA GetTraceTable TraceRecords + * from the given source Gid to the + * given destination Gid + * + * PathRecord PathRecord SA GetTable PathRecords with PathRecord + * and component mask as given + * + * PathRecord TraceRecord SA GetTraceTable TraceRecords with PathRecord + * and component mask as given + * + * PortGuidList PathRecord SA GetTable MultiPathRecords + * from the given source PortGuids to the + * given destination PortGuids + * + * GidList PathRecord SA GetTable MultiPathRecords + * from the given source Gids to the + * given destination Gids + * + * MultiPathRecord PathRecord SA GetTable MultiPathRecords with + * MultiPathRecord and component mask as given + * + * Lid Lids SA GetTable NodeRecords with Lid + * Lid SystemImageGuid SA GetTable NodeRecords with Lid + * Lid NodeGuids SA GetTable NodeRecords with Lid + * Lid PortGuids SA GetTable NodeRecords with Lid + * Lid NodeDesc SA GetTable NodeRecords with Lid + * Lid NodeRecord SA GetTable NodeRecords with Lid + * + * Lid PathRecord SA GetTable NodeRecords with Lid + * followed by a SA GetTable PathRecords + * from the local PortGuid and each + * Remote PortGuid reported in NodeRecords + * + * Lid McMemberRecord SA GetTable McRecords with given MLid + * Lid SwitchInfoRecord SA GetTable SwitchInfoRecords with Lid + * Lid LinearFDBRecord SA GetTable LinearFDBRecords for switch Lid + * Lid RandomFDBRecord SA GetTable RandomFDBRecords for switch Lid + * Lid MCastFDBRecord SA GetTable MCastFDBRecords for switch Lid + * Lid VLArbTableRecord SA GetTable VLArbTableRecords with Lid + * Lid PKeyTableRecord SA GetTable PKeyTableRecords with Lid + * Lid GuidInfoRecord SA GetTable GuidInfoRecords with Lid + * + * NodeDesc Lids SA GetTable NodeRecords with NodeDesc + * NodeDesc SystemImageGuid SA GetTable NodeRecords with NodeDesc + * NodeDesc NodeGuids SA GetTable NodeRecords with NodeDesc + * NodeDesc PortGuids SA GetTable NodeRecords with NodeDesc + * NodeDesc NodeDesc SA GetTable NodeRecords with NodeDesc + * NodeDesc NodeRecord SA GetTable NodeRecords with NodeDesc + * + * NodeDesc PathRecord SA GetTable NodeRecords with NodeDesc + * followed by a SA GetTable PathRecords + * from the local PortGuid and each + * Remote PortGuid reported in NodeRecords + * + * ServiceRecord ServiceRecord SA GetTable ServiceRecords with + * ServiceRecord and component mask given + * + * McMemberRecord McMemberRecord SA GetTable McMemberRecords with + * McMemberRecord and component mask given + */ + +/* record query selector(s) for QueryFabricInformation + * next to each is listed the corresponding field in the QUERY_INPUT_VALUE + * union below which will be used + */ +typedef enum _QUERY_INPUT_TYPE +{ + InputTypeNoInput = 0, /* No input. returns all records */ + InputTypeNodeType = 1, /* NodeType */ + InputTypeSystemImageGuid = 2, /* Guid - a system Image guid */ + InputTypeNodeGuid = 3, /* Guid - a node guid */ + InputTypePortGuid = 4, /* Guid - a port guid */ + InputTypePortGid = 5, /* Gid - a gid associated with a port */ + InputTypeMcGid = 6, /* Gid - a multicast gid */ + InputTypePortGuidPair = 7, /* GuidPair - a pair of port guids */ + InputTypeGidPair = 8, /* GidPair - a pair of gids */ + InputTypePathRecord = 9, /* PathRecord */ + InputTypePathRecordNetworkOrder = 10, /* PathRecord in network byte order */ + InputTypeLid = 11, /* Lid - a lid in the local subnet */ + InputTypePKey = 12, /* PKey - a pkey */ + InputTypeSL = 13, /* SL - a service level */ + InputTypeIndex = 14, /* Index - an index associated with a VF */ + InputTypeServiceId = 15, /* ServiceId */ + InputTypeNodeDesc = 16, /* NodeDesc - a node description/name */ + InputTypeServiceRecord = 17, /* ServiceRecordValue - complete SA SERVICE_RECORD and component mask */ + InputTypeMcMemberRecord = 18, /* McMemberRecordValue - complete SA MCMEMBER_RECORD and component mask */ + InputTypePortGuidList = 19, /* GuidList - a list of port guids */ + InputTypeGidList = 20, /* GidList - a list of gids */ + InputTypeMultiPathRecord = 21, /* MultiPathRecord */ + InputTypeSourceGid = 22, + + InputTypeStlBase = 0x1000, + InputTypeDeviceGroup = (InputTypeStlBase+2), /* A single device group name */ + +} QUERY_INPUT_TYPE, *PQUERY_INPUT_TYPE; + +typedef struct _QueryInputString { + QUERY_INPUT_TYPE inputType; + const char *inputTypeStr; +} QueryInputString_t; + +/* convert QUERY_INPUT_TYPE to a string */ +IBA_API const char* iba_sd_query_input_type_msg(QUERY_INPUT_TYPE code); + +/* output type requested for QueryFabricInformation + * next to each is listed the corresponding structure below which will be used + * for output + */ +typedef enum _QUERY_RESULT_TYPE +{ + /* SA query results */ + OutputTypeSystemImageGuid = 0, /* GUID_RESULTS a set of system image GUIDs */ + OutputTypeNodeGuid = 1, /* GUID_RESULTS a set of node GUIDs */ + OutputTypePortGuid = 2, /* GUID_RESULTS a set of port GUIDs */ + OutputTypeLid = 3, /* LID_RESULTS is a set of LIDs */ + OutputTypeGid = 4, /* GID_RESULTS is a set of GIDs */ + OutputTypeNodeDesc = 5, /* NODEDESC_RESULTS set of node descr/names */ + OutputTypePathRecord = 6, /* PATH_RESULTS is set of path records */ + OutputTypePathRecordNetworkOrder = 7, /* PATH_RESULTS is set of path records in network byte order*/ + OutputTypeNodeRecord = 8, /* NODE_RECORD_RESULTS complete SA NodeRecords */ + OutputTypePortInfoRecord = 9, /* PORTINFO_RECORD_RESULTS complete SA PortInfoRecords */ + OutputTypeSMInfoRecord = 10, /* SMINFO_RECORD_RESULTS complete SA SMInfoRecords */ + OutputTypeLinkRecord = 11, /* LINK_RECORD_RESULTS complete SA LinkRecords */ + OutputTypeServiceRecord = 12, /* SERVICE_RECORD_RESULTS complete SA IB_SERVICE_RECORD */ + OutputTypeMcMemberRecord = 13, /* MCMEMBER_RECORD_RESULTS complete SA IB_MCMEMBER_RECORD */ + OutputTypeInformInfoRecord = 14, /* INFORM_INFO_RECORD_RESULTS complete SA IB_INFORM_INFO_RECORD */ + OutputTypeTraceRecord = 15, /* TRACE_RECORD_RESULTS is set of trace records */ + OutputTypeSwitchInfoRecord = 16, /* SWITCHINFO_RECORD_RESULTS is set of switch info records */ + OutputTypeLinearFDBRecord = 17, /* LINEAR_FDB_RECORD_RESULTS is set of linear FDB records */ + OutputTypeRandomFDBRecord = 18, /* RANDOM_FDB_RECORD_RESULTS is set of random FDB records */ + OutputTypeMCastFDBRecord = 19, /* MCAST_FDB_RECORD_RESULTS is set of multicast FDB records */ + OutputTypeVLArbTableRecord = 20, /* VLARBTABLE_RECORD_RESULTS is set of VL Arbitration records */ + OutputTypePKeyTableRecord = 21, /* PKEYTABLE_RECORD_RESULTS is set of VL Arbitration records */ + OutputTypeVfInfoRecord = 22, /* VF_RECORD_RESULTS is set of VF info records */ + OutputTypeClassPortInfo = 23, + + /* PA query results */ + OutputTypePaRecord = 24, /* PA_PACKET_RESULTS complete PA SinglePacketRespRecords */ + OutputTypePaTableRecord = 25, /* PA_TABLE_PACKET_RESULTS complete PA MultiPacketRespRecords */ + + /* New STL Types */ + OutputTypeStlBase = 0x1000, + OutputTypeStlNodeRecord = (OutputTypeStlBase+1), + OutputTypeStlNodeDesc = (OutputTypeStlBase+2), + OutputTypeStlPortInfoRecord = (OutputTypeStlBase+3), + OutputTypeStlSwitchInfoRecord = (OutputTypeStlBase+4), + OutputTypeStlPKeyTableRecord = (OutputTypeStlBase+5), + OutputTypeStlSLSCTableRecord = (OutputTypeStlBase+6), + OutputTypeStlSMInfoRecord = (OutputTypeStlBase+7), + OutputTypeStlLinearFDBRecord = (OutputTypeStlBase+8), + OutputTypeStlVLArbTableRecord = (OutputTypeStlBase+9), + OutputTypeStlLid = (OutputTypeStlBase+11), + OutputTypeStlMCastFDBRecord = (OutputTypeStlBase+12), + OutputTypeStlLinkRecord = (OutputTypeStlBase+13), + OutputTypeStlSystemImageGuid = (OutputTypeStlBase+14), + OutputTypeStlPortGuid = (OutputTypeStlBase+15), + OutputTypeStlNodeGuid = (OutputTypeStlBase+16), + OutputTypeStlInformInfoRecord = (OutputTypeStlBase+18), + OutputTypeStlVfInfoRecord = (OutputTypeStlBase+19), + OutputTypeStlTraceRecord = (OutputTypeStlBase+20), + OutputTypeStlQuarantinedNodeRecord = (OutputTypeStlBase+21), + OutputTypeStlCongInfoRecord = (OutputTypeStlBase+22), + OutputTypeStlSwitchCongRecord = (OutputTypeStlBase+23), + OutputTypeStlSwitchPortCongRecord = (OutputTypeStlBase+24), + OutputTypeStlHFICongRecord = (OutputTypeStlBase+25), + OutputTypeStlHFICongCtrlRecord = (OutputTypeStlBase+26), + OutputTypeStlBufCtrlTabRecord = (OutputTypeStlBase+27), + OutputTypeStlCableInfoRecord = (OutputTypeStlBase+28), + OutputTypeStlPortGroupRecord = (OutputTypeStlBase+29), + OutputTypeStlPortGroupFwdRecord = (OutputTypeStlBase+30), + OutputTypeStlSCSLTableRecord = (OutputTypeStlBase+31), + OutputTypeStlSCVLtTableRecord = (OutputTypeStlBase+32), + OutputTypeStlSCVLntTableRecord = (OutputTypeStlBase+33), + OutputTypeStlSCSCTableRecord = (OutputTypeStlBase+34), + OutputTypeStlClassPortInfo = (OutputTypeStlBase+35), + OutputTypeStlFabricInfoRecord = (OutputTypeStlBase+36), + OutputTypeStlSCVLrTableRecord = (OutputTypeStlBase+38), + OutputTypeStlDeviceGroupNameRecord = (OutputTypeStlBase+41), + OutputTypeStlDeviceGroupMemberRecord = (OutputTypeStlBase+42), + OutputTypeStlDeviceTreeMemberRecord = (OutputTypeStlBase+44), + OutputTypeStlSwitchCostRecord = (OutputTypeStlBase+53), + +} QUERY_RESULT_TYPE, *PQUERY_RESULT_TYPE; + +typedef struct _QueryOutputString { + QUERY_RESULT_TYPE outputType; + const char *outputTypeStr; +} QueryOutputString_t; + +/* convert QUERY_RESULT_TYPE to a string */ +IBA_API const char* iba_sd_query_result_type_msg(QUERY_RESULT_TYPE code); + +/* limit of 8 allows Multipath request to fit in a single output packet + * also allows QUERY_INPUT_VALUE to stay same overall size for backward + * compatibility + */ +#define MULTIPATH_GID_LIMIT 8 +/* input value for QueryFabricInformation, InputType selects field in union */ +typedef union _QUERY_INPUT_VALUE +{ + NODE_TYPE TypeOfNode; /* Query input is a node type */ + EUI64 Guid; /* Query input is a GUID */ + IB_GID Gid; /* Query input is a GID */ + struct /* Query input is a GUID pair */ + { + EUI64 SourcePortGuid; /* Query Input source port GUID */ + EUI64 DestPortGuid; /* Query Input destination port GUID */ + } PortGuidPair; + struct /* Query input is a GUID pair */ + { + IB_GID SourceGid; /* Query Input source GID */ + IB_GID DestGid; /* Query Input destination GID */ + } GidPair; + struct /* Query input is a GUID list */ + { + uint8 SourceGuidCount; /* number of Source GUIDs in GuidList */ + uint8 DestGuidCount; /* number of Dest GUIDs in GuidList */ + EUI64 GuidList[MULTIPATH_GID_LIMIT];/* Src GUIDs, followed by Dest GUIDs */ + } PortGuidList; + struct /* Query input is a GID list */ + { + uint8 SourceGidCount; /* number of Source GIDs in GidList */ + uint8 DestGidCount; /* number of Dest GIDs in GidList */ + IB_GID GidList[MULTIPATH_GID_LIMIT];/* Src GIDs, followed by Dest GIDs */ + } GidList; + + STL_LID Lid; /* Query input is a 32-bit LID */ + uint16 PKey; /* Query input is a pkey */ + uint8 SL; /* Query input is a SL */ + uint16 vfIndex; /* Query input is a vf index */ + uint64 ServiceId; /* Query input is a ServiceID */ + struct + { + uint64 ComponentMask; + IB_PATH_RECORD PathRecord; + } PathRecordValue; + struct + { + uint64 ComponentMask; + IB_MULTIPATH_RECORD MultiPathRecord; + /* Gids below allows up to 8 SGID and/or DGID in MultiPathRecord.GIDList */ + /* do not use Gids field directly, instead use */ + /* MultiPathRecord.GIDList[0-7] */ + IB_GID Gids[MULTIPATH_GID_LIMIT-1]; + } MultiPathRecordValue; + struct + { + uint32 NameLength; /* actual characters, no \0 terminator */ + uint8 Name[NODE_DESCRIPTION_ARRAY_SIZE]; /* not \0 terminated */ + } NodeDesc; + struct + { + uint64 ComponentMask; + IB_SERVICE_RECORD ServiceRecord; + } ServiceRecordValue; /* Use InputTypeServiceRecord */ + struct + { + uint64 ComponentMask; + IB_MCMEMBER_RECORD McMemberRecord; + } McMemberRecordValue; /* Use InputTypeMcMemberRecord */ + struct + { + uint32 NameLength; + char Name[MAX_DG_NAME]; + } DeviceGroup; +} QUERY_INPUT_VALUE, *PQUERY_INPUT_VALUE; + +/* description of a query for QueryFabricInformation */ +typedef struct _QUERY { + QUERY_INPUT_TYPE InputType; /* Type of input (i.e. query based on) */ + QUERY_RESULT_TYPE OutputType; /* Type of output (i.e. info requested) */ + QUERY_INPUT_VALUE InputValue; /* input record selection value input query */ +} QUERY, *PQUERY; + +/* value returned from a query + * Status is primary status + * When status is FERROR, MadStatus indicates 16 Status and 16 bit + * Reserved fields from MAD response (see MAD_COMMON.u.NS in ib_mad.h) + * Status is in least significant 16 bits, Reserved in upper 16 bits + */ +typedef struct _QUERY_RESULT_VALUES { + FSTATUS Status; /* overall result of query */ + uint32 MadStatus; /* for FSUCCESS or FERROR Status: */ + /* manager's Mad Status code from response */ + uint32 ResultDataSize; /* number of bytes in QueryResult */ + uint32 reserved; /* to force 64 bit alignment of QueryResult */ + uint8 QueryResult[1]; /* one of the RESULTS types below as selected by */ + /* OutputType in query */ +} QUERY_RESULT_VALUES, *PQUERY_RESULT_VALUES; + + +/* convert SD MadStatus (uint32 reported by SD) to a string + * The string will only contain the message corresponding to the defined values + * to be safe, callers should also display the hex value in the event a + * reserved or undefined value is returned by the manager + */ +IBA_API const char* iba_sd_mad_status_msg(uint32 code); + +/* -------------------------------------------------------------------------- + * Structures for Result types for QueryFabricInformation + * OutputType in query selects which record format will be returned + * in QueryResult + */ + +typedef struct _GUID_RESULTS { + uint32 NumGuids; /* Number of GUIDs returned */ + EUI64 Guids[1]; /* Start of the list of GUIDs returned */ +} GUID_RESULTS, *PGUID_RESULTS; + +typedef struct _LID_RESULTS { + uint32 NumLids; /* Number of LIDs returned */ + IB_LID Lids[1]; /* list of LIDs returned */ +} LID_RESULTS, *PLID_RESULTS; + +typedef struct _GID_RESULTS { + uint32 NumGids; /* Number of GIDs returned */ + IB_GID Gids[1]; /* list of GIDs returned */ +} GID_RESULTS, *PGID_RESULTS; + +typedef struct _PATH_RESULTS { + uint32 NumPathRecords; /* Number of PathRecords returned */ + IB_PATH_RECORD PathRecords[1]; /* list of path records returned */ +} PATH_RESULTS, *PPATH_RESULTS; + +typedef struct _NODE_RECORD_RESULTS { + uint32 NumNodeRecords; /* Number of NodeRecords returned */ + IB_NODE_RECORD NodeRecords[1]; /* list of Node records returned */ +} NODE_RECORD_RESULTS, *PNODE_RECORD_RESULTS; + +typedef struct _PORTINFO_RECORD_RESULTS { + uint32 NumPortInfoRecords; /* Number of PortInfoRecords returned */ + IB_PORTINFO_RECORD PortInfoRecords[1]; /* list of PortInfo records returned */ +} PORTINFO_RECORD_RESULTS, *PPORTINFO_RECORD_RESULTS; + +typedef struct _NODEDESC_RESULTS { + uint32 NumDescs; /* Number of NodeDescs returned */ + NODE_DESCRIPTION NodeDescs[1]; /* NodeDesc, not \0 terminated */ +} NODEDESC_RESULTS, *PNODEDESC_RESULTS; + +typedef struct _SERVICE_RECORD_RESULTS { + uint32 NumServiceRecords; /* Number of records returned */ + IB_SERVICE_RECORD ServiceRecords[1]; /* list of records returned */ +} SERVICE_RECORD_RESULTS, *PSERVICE_RECORD_RESULTS; + +typedef struct _MCMEMBER_RECORD_RESULTS { + uint32 NumMcMemberRecords; /* Number of records returned */ + IB_MCMEMBER_RECORD McMemberRecords[1]; /* list of records returned */ +} MCMEMBER_RECORD_RESULTS, *PMCMEMBER_RECORD_RESULTS; + +typedef struct _INFORM_INFO_RECORD_RESULTS { + uint32 NumInformInfoRecords; /* Number of records returned */ + IB_INFORM_INFO_RECORD InformInfoRecords[1];/* list of records returned */ +} INFORM_INFO_RECORD_RESULTS, *PINFORM_INFO_RECORD_RESULTS; + +typedef struct _IB_CLASS_PORT_INFO_RESULTS { + uint32 NumClassPortInfo; /* Number of records returned */ + IB_CLASS_PORT_INFO ClassPortInfo[1]; /* list of records returned */ +} IB_CLASS_PORT_INFO_RESULTS, *PIB_CLASS_PORT_INFO_RESULTS; + +/* =========================================================================== + * FabricOperation + * Data structures used to manage records in the SA/SM via Set or Delete + * for a fabric operation a single record is provided in conjunction with + * an operation to perform. In response a single record is returned. + * For some Set operations the SA may augment or modify the original record + * provided in which case the returned record is interesting. + * However for delete operations the record is generally uninteresting. + */ + +/* FabricOperations Supported: + * + * OperationType Operation performed + * ------------- ------------------- + * SetServiceRecord SA Set ServiceRecord with service record given + * creates a service record to register this node/port + * as providing the given service + * + * DeleteServiceRecord SA Delete ServiceRecord with service record given + * deletes a service record to indicate this node/port + * no longer provides the given service + * + * SetMcMemberRecord SA Set McMemberRecord with McMemberRecord given + * creates and/or joins a multicast group + * + * JoinMcGroup SA Set McMemberRecord with MGID and JoinState given + * joins an existing multicast group + * input is McJoinLeave, output is McMemberRecord + * + * LeaveMcGroup SA Delete McMemberRecord with MGID and JoinState given + * Leave an existing multicast group + * input is McJoinLeave, output is McMemberRecord + * + * DeleteMcMemberRecord SA Delete McMemberRecord with McMemberRecord given + * leaves and/or deletes a multicast group + * + * SetInfomInfo SA Set InformInfo with InformInfo given + * Subscribe for Traps/Notices to be sent to this port + */ + +/* Fabric Operation to perform */ +typedef enum _FABRIC_OPERATION_TYPE +{ + /* SA operations */ + FabOpSetServiceRecord =0, /* Set a service record */ + FabOpDeleteServiceRecord, /* Delete a service record */ + FabOpSetMcMemberRecord, /* Set a Multicast Member record */ + FabOpJoinMcGroup, /* Join a Multicast Group */ + FabOpLeaveMcGroup, /* Leave a Multicast Group */ + FabOpDeleteMcMemberRecord, /* Delete a Multicast Member record */ + FabOpSetInformInfo, /* Set InformInfo to register for notices */ +} FABRIC_OPERATION_TYPE; + +/* convert FABRIC_OPERATION_TYPE to a string */ +IBA_API const char* iba_sd_fabric_op_type_msg(FABRIC_OPERATION_TYPE code); + +/* value for a FabricOperation, used as input and output */ +typedef union _FABRIC_OPERATION_VALUE +{ + /* Data for SA operations */ + struct + { + uint64 ComponentMask; /* input only, only for DeleteServiceRecord */ + IB_SERVICE_RECORD ServiceRecord; + } ServiceRecordValue; + struct + { + uint64 ComponentMask; /* input only */ + IB_MCMEMBER_RECORD McMemberRecord; + } McMemberRecordValue; + struct { + IB_GID MGID; + uint8 JoinFullMember:1; + uint8 JoinNonMember:1; + uint8 JoinSendOnlyMember:1; + uint8 Reserved:5; + } McJoinLeave; + IB_INFORM_INFO InformInfo; +} FABRIC_OPERATION_VALUE; + +/* Data for a FabricOperation, also returned as result */ +typedef struct _FABRIC_OPERATION_DATA +{ + FABRIC_OPERATION_TYPE Type; + FABRIC_OPERATION_VALUE Value; +} FABRIC_OPERATION_DATA, *PFABRIC_OPERATION_DATA; + +/* =========================================================================== + * common (kernel/user) mode function interface + */ + +/* Register as a client with the Subnet Data Interface + * handle is returned which must be used in all subsequent calls on behalf + * of this registration + * pass a NULL to use default ClientParameters + * this does not preempt + * data pointed to only used during duration of call + */ +typedef FSTATUS + (SD_REGISTER)( + IN OUT CLIENT_HANDLE *ClientHandle, + IN PCLIENT_CONTROL_PARAMETERS pClientParameters OPTIONAL + ); +IBA_API SD_REGISTER iba_sd_register; + +/* DeRegister as a client with the Subnet Data Interface + * this does not preempt + */ +typedef FSTATUS + (SD_DEREGISTER)( + IN CLIENT_HANDLE ClientHandle + ); +IBA_API SD_DEREGISTER iba_sd_deregister; + +/* get present parameters to control queries/operations by client + * this does not preempt + * data pointed to only used during duration of call + */ +typedef FSTATUS + (SD_GET_CLIENT_CONTROL_PARAMETERS)( + IN CLIENT_HANDLE ClientHandle, + IN OUT PCLIENT_CONTROL_PARAMETERS pClientControlParameters + ); +IBA_API SD_GET_CLIENT_CONTROL_PARAMETERS iba_sd_get_client_control_parameters; + +/* set parameters to control queries/operations by client + * this does not preempt + * data pointed to only used during duration of call + */ +typedef FSTATUS + (SD_SET_CLIENT_CONTROL_PARAMETERS)( + IN CLIENT_HANDLE ClientHandle, + IN PCLIENT_CONTROL_PARAMETERS pClientControlParameters + ); +IBA_API SD_SET_CLIENT_CONTROL_PARAMETERS iba_sd_set_client_control_parameters; + +/* Callback made when a Report Request is received + * this callback occurs in a thread context, however it should not preempt + * for long durations + * data pointed to only valid during duration of call + */ +typedef + void (SD_REPORT_NOTICE_CALLBACK)( + IN void *pContext, /* as supplied at subscription time */ + IN IB_NOTICE *pNotice, /* IB_NOTICE record returned in the Report Request */ + IN EUI64 PortGuid /* Port Guid from which Report Request was received */ + ); +typedef SD_REPORT_NOTICE_CALLBACK *PREPORT_NOTICE_CALLBACK;/* deprecated */ + +/* Callback made in kernel mode when a multicast group's state changes + * this callback occurs in a thread context, however it should not preempt + * for long durations + * data pointed to only valid during duration of call + * + * There are three basic combinations of callback: + * State Status pMcMemberRecord + * MC_GROUP_STATE_JOIN_FAILED failure code Only fields from request are valid + * MC_GROUP_STATE_AVAILABLE FSUCCESS All fields valid, response from SA + * MC_GROUP_STATE_UNAVAILABLE N/A Only fields from request are valid + */ +typedef + void (SD_MULTICAST_CALLBACK)( + IN void *pContext, /* as supplied at group join time */ + IN FSTATUS Status, /* reason code */ + IN MC_GROUP_STATE State, /* current state of multicast group */ + IN IB_MCMEMBER_RECORD *pMcMemberRecord /* current member record settings */ + ); +typedef SD_MULTICAST_CALLBACK *PMULTICAST_CALLBACK;/* deprecated */ + +#ifdef __cplusplus +}; +#endif + +#endif /* _IBA_IB_SD_H_ */ diff --git a/IbAccess/Common/Inc/ib_sd_priv.h b/IbAccess/Common/Inc/ib_sd_priv.h new file mode 100644 index 0000000..193fd20 --- /dev/null +++ b/IbAccess/Common/Inc/ib_sd_priv.h @@ -0,0 +1,366 @@ +/* BEGIN_ICS_COPYRIGHT3 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT3 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +#ifndef _IBA_IB_SD_PRIV_H_ +#define _IBA_IB_SD_PRIV_H_ + +/* IB Subnet Data Interface + * The subnet data interface provides a simplied interface to the SM/SA and + * automates queries, sets and deletes for commonly required information + * from the SM/SA. + * + * The subnet data interface automatically handles the following: + * - retries (client configurable) + * - timeouts (client configurable) + * - RMPP response coallessing and inter-record padding + * - extraction of selected fields from a query to provide a concise response + * to client + * - multi-tiered queries (get paths to a node, etc) + * + * New drivers/applications should use the iba_* functions. + * They can now be called directly. + */ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct _SMINFO_RECORD_RESULTS { + uint32 NumSMInfoRecords; /* Number of SmInfoRecords returned */ + IB_SMINFO_RECORD SMInfoRecords[1]; /* list of SMInfo records returned */ +} SMINFO_RECORD_RESULTS, *PSMINFO_RECORD_RESULTS; + +typedef struct _LINK_RECORD_RESULTS { + uint32 NumLinkRecords; /* Number of SmInfoRecords returned */ + IB_LINK_RECORD LinkRecords[1]; /* list of SMInfo records returned */ +} LINK_RECORD_RESULTS, *PLINK_RECORD_RESULTS; + +typedef struct _TRACE_RECORD_RESULTS { + uint32 NumTraceRecords; /* Number of TraceRecords returned */ + IB_TRACE_RECORD TraceRecords[1]; /* list of trace records returned */ +} TRACE_RECORD_RESULTS, *PTRACE_RECORD_RESULTS; + +typedef struct _SWITCHINFO_RECORD_RESULTS { + uint32 NumSwitchInfoRecords; /* Number of SwitchInfoRecords returned */ + IB_SWITCHINFO_RECORD SwitchInfoRecords[1]; /* list of Switch Info records returned */ +} SWITCHINFO_RECORD_RESULTS, *PSWITCHINFO_RECORD_RESULTS; + +typedef struct _LINEAR_FDB_RECORD_RESULTS { + uint32 NumLinearFDBRecords; /* Number of LinearFDBRecords returned */ + IB_LINEAR_FDB_RECORD LinearFDBRecords[1]; /* list of Linear FDB records returned */ +} LINEAR_FDB_RECORD_RESULTS, *PLINEAR_FDB_RECORD_RESULTS; + +typedef struct _RANDOM_FDB_RECORD_RESULTS { + uint32 NumRandomFDBRecords; /* Number of RandomFDBRecords returned */ + IB_RANDOM_FDB_RECORD RandomFDBRecords[1]; /* list of Random FDB records returned */ +} RANDOM_FDB_RECORD_RESULTS, *PRANDOM_FDB_RECORD_RESULTS; + +typedef struct _MCAST_FDB_RECORD_RESULTS { + uint32 NumMCastFDBRecords; /* Number of MCastFDBRecords returned */ + IB_MCAST_FDB_RECORD MCastFDBRecords[1]; /* list of multicast FDB records returned */ +} MCAST_FDB_RECORD_RESULTS, *PMCAST_FDB_RECORD_RESULTS; + +typedef struct _VLARBTABLE_RECORD_RESULTS { + uint32 NumVLArbTableRecords; /* Number of VLArbTableRecords returned */ + IB_VLARBTABLE_RECORD VLArbTableRecords[1]; /* list of VL Arbitration table records returned */ +} VLARBTABLE_RECORD_RESULTS, *PVLARBTABLE_RECORD_RESULTS; + +typedef struct _PKEYTABLE_RECORD_RESULTS { + uint32 NumPKeyTableRecords; /* Number of PKeyTableRecords returned */ + IB_P_KEY_TABLE_RECORD PKeyTableRecords[1]; /* list of P-Key table records returned */ +} PKEYTABLE_RECORD_RESULTS, *PPKEYTABLE_RECORD_RESULTS; + +/* =========================================================================== + * kernel mode function interface + */ +#if defined(VXWORKS) + +/* return a list of the PortGuids for presently active ports + * caller must MemoryDeallocate(*ppLocalPortGuidsList) when done using it + * this does not preempt + * if no ports are found, can return FSUCCESS but with both outputs set to 0 + * data pointed to only used during duration of call + */ +typedef FSTATUS + (SDK_GET_LOCAL_PORT_GUIDS)( + IN OUT uint64 **ppLocalPortGuidsList, + IN OUT uint32 *LocalPortGuidsCount + ); +IBA_API SDK_GET_LOCAL_PORT_GUIDS iba_sd_get_local_port_guids_alloc; + +/* return a list of the PortGuids and SubnetPrefixes for presently active ports + * caller must MemoryDeallocate(*ppLocalPortGuidsList) and + * MemoryDeallocate(*ppLocalPortSubnetPrefixList) when done using it + * this does not preempt + * if no ports are found, can return FSUCCESS but with both outputs set to 0 + * data pointed to only used during duration of call + */ +typedef FSTATUS + (SDK_GET_LOCAL_PORT_GUIDS2)( + IN OUT uint64 **ppLocalPortGuidsList, + IN OUT uint64 **ppLocalPortSubnetPrefixList, + IN OUT uint32 *LocalPortGuidsCount + ); +IBA_API SDK_GET_LOCAL_PORT_GUIDS2 iba_sd_get_local_port_guids_alloc2; + +/* Callback made in kernel mode when a Query[Port]FabricInformation completes + * this callback occurs in a thread context, however it should not preempt + * for long durations + * data pointed to only valid during duration of call + */ +typedef + void (SDK_QUERY_CALLBACK)( + IN void *Context, /* as supplied in Query */ + IN PQUERY pInputQuery, /* input request */ + IN PQUERY_RESULT_VALUES pQueryResults /* results returned from Manager */ + ); +typedef SDK_QUERY_CALLBACK *PQUERY_CALLBACK;/* depricated */ + +/* perform a query of a manager (SA, etc) + * using 1st active port + * if pQueryControlParameters is NULL, values established for client session + * will be used + * this function does not preempt. When the operation completes a callback + * will occur with the result data. + * data pointed to only used during duration of call + */ +typedef FSTATUS + (SDK_QUERY_FABRIC_INFO)( + IN CLIENT_HANDLE ClientHandle, + IN PQUERY pQuery, /* query to make */ + IN SDK_QUERY_CALLBACK *Callback, /* called on completion */ + IN COMMAND_CONTROL_PARAMETERS *pQueryControlParameters OPTIONAL, + IN void *Context OPTIONAL/* context for callback */ + ); +IBA_API SDK_QUERY_FABRIC_INFO iba_sd_query_fabric_info; + +/* Same as QueryFabricInformation, except issued against a specific port */ +typedef FSTATUS + (SDK_QUERY_PORT_FABRIC_INFO)( + IN CLIENT_HANDLE ClientHandle, + IN EUI64 PortGuid, + IN PQUERY pQuery, + IN SDK_QUERY_CALLBACK *Callback, + IN COMMAND_CONTROL_PARAMETERS *pQueryControlParameters OPTIONAL, + IN void *Context OPTIONAL + ); +IBA_API SDK_QUERY_PORT_FABRIC_INFO iba_sd_query_port_fabric_info; + +/* Callback made in kernel mode when a [Port]FabricOperation completes + * this callback occurs in a thread context, however it should not preempt + * for long durations + * data pointed to only valid during duration of call + */ +typedef + void (SDK_FABRIC_OPERATION_CALLBACK)( + IN void* Context,/* as supplied in FabricOperation */ + IN FABRIC_OPERATION_DATA* pFabOp, /* contains response value */ + IN FSTATUS Status, /* overall result of query */ + IN uint32 MadStatus /* for FSUCCESS or FERROR Status: */ + /* manager's Mad Status code from resp */ + ); +typedef SDK_FABRIC_OPERATION_CALLBACK *PFABRIC_OPERATION_CALLBACK;/* depricated */ + +/* perform a fabric operation (eg. set/delete, etc) against a manager + * using 1st active port + * if pCmdControlParameters is NULL, values established for client session + * will be used + * this function does not preempt. When the operation completes a callback + * will occur with the result data. + * data pointed to only used during duration of call + */ +typedef FSTATUS + (SDK_FABRIC_OPERATION)( + IN CLIENT_HANDLE ClientHandle, + IN FABRIC_OPERATION_DATA* pFabOp, /* operation to perform */ + IN SDK_FABRIC_OPERATION_CALLBACK *Callback, + IN COMMAND_CONTROL_PARAMETERS* pCmdControlParameters OPTIONAL, + IN void* Context OPTIONAL + ); +IBA_API SDK_FABRIC_OPERATION iba_sd_fabric_operation; + +/* Same as FabricOperation, except issued against a specific port */ +typedef FSTATUS + (SDK_PORT_FABRIC_OPERATION)( + IN CLIENT_HANDLE ClientHandle, + IN EUI64 PortGuid, + IN FABRIC_OPERATION_DATA* pFabOp, /* operation to perform */ + IN SDK_FABRIC_OPERATION_CALLBACK *Callback, + IN COMMAND_CONTROL_PARAMETERS* pCmdControlParameters OPTIONAL, + IN void* Context OPTIONAL + ); +IBA_API SDK_PORT_FABRIC_OPERATION iba_sd_port_fabric_operation; + +/* subscribe for an SA Trap/Notice + * client will receive a callback when the given Trap/Notice is received + */ +typedef FSTATUS + (SDK_TRAP_NOTICE_SUBSCRIBE)( + IN CLIENT_HANDLE ClientHandle, + IN uint16 TrapNumber, + IN EUI64 PortGuid, + IN void *pContext, + IN SD_REPORT_NOTICE_CALLBACK *pReportNoticeCallback + ); +IBA_API SDK_TRAP_NOTICE_SUBSCRIBE iba_sd_trap_notice_subscribe; + +/* unsubscribe for an SA Trap/Notice + * this does not preempt + */ +typedef FSTATUS + (SDK_TRAP_NOTICE_UNSUBSCRIBE)( + IN CLIENT_HANDLE ClientHandle, + IN uint16 TrapNumber, + IN EUI64 PortGuid + ); +IBA_API SDK_TRAP_NOTICE_UNSUBSCRIBE iba_sd_trap_notice_unsubscribe; + +/* have any of the client's traps been successfully subscribed for + * this does not preempt + */ +typedef boolean + (SDK_PORT_TRAPS_SUBSCRIBED)( + IN EUI64 PortGuid + ); +IBA_API SDK_PORT_TRAPS_SUBSCRIBED iba_sd_port_traps_subscribed; + +/* Request join/create of a multicast group + * + * This version of the call uses the MGID as the group identifier + * + * SdClientHandle - handle from iba_sd_register + * McFlags - MC_FLAGS_* to control when get callbacks + * ComponentMask - indicate fields in pMcMemberRecord which are set + * pContext - user defined context pointer supplied to callback + * pMulticastCallback - callback function invoked when join state changes + * + * Since joins are per HCA port, this call handles multiple applications + * joining the same MC group and will only issue joins to the SM on the + * 1st application joining. Similarly iba_sd_leave_mcgroup will only issue + * the leave to the SM on last application leaving. + * + * Internally this call maintains the joined state and will rejoin when + * fabric events warrent, such as SM restart, port down and up, etc. + * + * this does not preempt + * data pointed to only used during duration of call + */ +typedef FSTATUS + (SDK_JOIN_MULTICAST_GROUP)( + IN CLIENT_HANDLE SdClientHandle, + IN uint16 McFlags, + IN uint64 ComponentMask, + IN IB_MCMEMBER_RECORD *pMcMemberRecord, + IN void *pContext, + IN SD_MULTICAST_CALLBACK *pMulticastCallback + ); +IBA_API SDK_JOIN_MULTICAST_GROUP iba_sd_join_mcgroup; + +/* Request join/create of a multicast group + * + * This version of the call uses the RID as the group identifier + * + * SdClientHandle - handle from iba_sd_register + * McFlags - MC_FLAGS_* to control when get callbacks + * ComponentMask - indicate fields in pMcMemberRecord which are set + * pContext - user defined context pointer supplied to callback + * pMulticastCallback - callback function invoked when join state changes + * + * Since joins are per HCA port, this call handles multiple applications + * joining the same MC group and will only issue joins to the SM on the + * 1st application joining. Similarly iba_sd_leave_mcgroup2 will only issue + * the leave to the SM on last application leaving. + * + * Internally this call maintains the joined state and will rejoin when + * fabric events warrent, such as SM restart, port down and up, etc. + * + * this does not preempt + * data pointed to only used during duration of call + */ +typedef FSTATUS + (SDK_JOIN_MULTICAST_GROUP2)( + IN CLIENT_HANDLE SdClientHandle, + IN uint16 McFlags, + IN uint64 ComponentMask, + IN IB_MCMEMBER_RECORD *pMcMemberRecord, + IN EUI64 EgressPortGUID, + IN void *pContext, + IN SD_MULTICAST_CALLBACK *pMulticastCallback + ); +IBA_API SDK_JOIN_MULTICAST_GROUP2 iba_sd_join_mcgroup2; + +/* Request leave of a multicast group which was previously joined via + * iba_sd_join_mcgroup + * + * Once this returns, no more callbacks will be issued for the given join. + * This call does not trigger a callback. + * + * This will only issue the leave to the SM on last application leaving the + * group. + * + * this does not preempt + */ +typedef FSTATUS + (SDK_LEAVE_MULTICAST_GROUP)( + IN CLIENT_HANDLE SdClientHandle, + IN IB_GID *pMGID + ); +IBA_API SDK_LEAVE_MULTICAST_GROUP iba_sd_leave_mcgroup; + +/* Request leave of a multicast group which was previously joined via + * iba_sd_join_mcgroup2 + * + * Once this returns, no more callbacks will be issued for the given join. + * This call does not trigger a callback. + * + * This will only issue the leave to the SM on last application leaving the + * group. + * + * this does not preempt + */ +typedef FSTATUS + (SDK_LEAVE_MULTICAST_GROUP2)( + IN CLIENT_HANDLE SdClientHandle, + IN IB_GID *pMGID, + IN IB_GID *pPortGID, + IN EUI64 EgressPortGUID + ); +IBA_API SDK_LEAVE_MULTICAST_GROUP2 iba_sd_leave_mcgroup2; + +#endif /* defined(VXWORKS) */ + +#ifdef __cplusplus +}; +#endif + +#endif /* _IBA_IB_SD_PRIV_H_ */ diff --git a/IbAccess/Common/Inc/ib_sm_priv.h b/IbAccess/Common/Inc/ib_sm_priv.h new file mode 100644 index 0000000..5d4e86a --- /dev/null +++ b/IbAccess/Common/Inc/ib_sm_priv.h @@ -0,0 +1,688 @@ +/* BEGIN_ICS_COPYRIGHT3 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT3 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +#ifndef __IBA_IB_SM_PRIV_H__ +#define __IBA_IB_SM_PRIV_H__ + +#include "iba/ib_sm_types.h" + +#if defined (__cplusplus) +extern "C" { +#endif + +#define OUI_TRUESCALE 0x00066a + +#include "iba/public/ipackon.h" + +/* ************************************************************************* + * SMPs + */ + +/* SMP Fields (LID Routed/Directed Route) */ +typedef struct _SMP { + + MAD_COMMON common; + uint64 M_Key; /* A 64 bit key, */ + /* employed for SM authentication */ + union { + struct _LIDRouted + { + uint8 Reserved3[32]; /* For aligning the SMP data field with */ + /* the directed route SMP data field */ + uint8 SMPData[64]; /* 64 byte field of SMP data used to */ + /* contain the methods attribute */ + uint8 Reserved4[128]; /* Reserved. Shall be set to 0 */ + } LIDRouted; + + struct _DirectedRoute + { + uint16 DrSLID; /* Directed route source LID */ + uint16 DrDLID; /* Directed route destination LID */ + uint8 Reserved2[28]; /* For the purpose of aligning the Data */ + /* field on a 64 byte boundary */ + + uint8 SMPData[64]; /* 64-byte field of SMP data used to */ + /* contain the methods attribute */ + uint8 InitPath[64]; /* 64-byte field containing the initial */ + /* directed path */ + uint8 RetPath[64]; /* 64-byte field containing the */ + /* returning directed path */ + } DirectedRoute; + }SmpExt; + +} PACK_SUFFIX SMP; + +#if 0 +#define SMP_SET_VERSION_INFO(smp, basever, mgmtcl, clver) {\ + MAD_SET_VERSION_INFO(smp, basever, mgmtcl, clver); \ +} + +#define SMP_GET_VERSION_INFO(smp, basever, mgmtcl, clver) {\ + MAD_GET_VERSION_INFO(smp, basever, mgmtcl, clver); \ +} +#endif + +#define SMP_GET_STATUS(smp, status) {\ + MAD_GET_STATUS(smp, status); \ +} + +#define SMP_GET_DR_STATUS(smp, status, d) { \ + (*status) = (smp)->common.u.DR.s.Status; \ + if( NULL != d){\ + (*d) = (smp)->common.u.DR.s.D; \ + }\ +} + +#define SMP_SET_HOP_POINTER(smp, hop_ptr) { \ + (smp)->common.u.DR.HopPointer = hop_ptr; \ +} + +#define SMP_GET_HOP_POINTER(smp, hop_ptr) { \ + (*hop_ptr) = (smp)->common.u.DR.HopPointer; \ +} + +#define SMP_SET_HOP_COUNT(smp, hop_count) { \ + (smp)->common.u.DR.HopCount = hop_count; \ +} + +#define SMP_GET_HOP_COUNT(smp, hop_count) { \ + (*hop_count) = (x)->common.u.DR.HopCount; \ +} + +#define SMP_SET_TRANSACTION_ID(smp, id) {\ + MAD_SET_TRANSACTION_ID(smp, id); \ +} + +#define SMP_GET_TRANSACTION_ID(smp, id) {\ + MAD_GET_TRANSACTION_ID(smp, id); \ +} + +#define SMP_SET_ATTRIB_ID(smp, id) {\ + MAD_SET_ATTRIB_ID(smp, id); \ +} + +#define SMP_GET_ATTRIB_ID(smp, id) {\ + MAD_GET_ATTRIB_ID(smp, id); \ +} + +#define SMP_SET_ATTRIB_MOD(smp, amod) {\ + MAD_SET_ATTRIB_MOD(smp, amod); \ +} + +#define SMP_GET_ATTRIB_MOD(smp, amod) {\ + MAD_GET_ATTRIB_MOD(smp, amod); \ +} + +#define SMP_SET_M_KEY(smp, mkey) {\ + (smp)->M_Key = mkey; \ +} + +#define SMP_GET_M_KEY(smp, mkey) {\ + (mkey) = (smp)->M_Key; \ +} + +#define SMP_LR_DATA SmpExt.LIDRouted.SMPData + +#define SMP_DR_DLID SmpExt.DirectedRoute.DrDLID +#define SMP_DR_SLID SmpExt.DirectedRoute.DrSLID +#define SMP_DR_DATA SmpExt.DirectedRoute.SMPData +#define SMP_DR_IPath SmpExt.DirectedRoute.InitPath +#define SMP_DR_RPath SmpExt.DirectedRoute.RetPath + + +/* ************************************************************************** + * Attribute specific SMP Packet Formats + */ + +/* + * SMA Notices/Traps (Data field for IB_NOTICE, see ib_mad.h) + */ + + /* Trap Numbers */ +#define SMA_TRAP_GID_NOW_IN_SERVICE 64 /* is now in service */ +#define SMA_TRAP_GID_OUT_OF_SERVICE 65 /* is out of service */ +#define SMA_TRAP_ADD_MULTICAST_GROUP 66 /* New multicast group with multicast address is now created */ +#define SMA_TRAP_DEL_MULTICAST_GROUP 67 /* New multicast group with multicast address is now deleted */ +#define SMA_TRAP_LINK_STATE 128 /* Switch port link state has changed */ +#define SMA_TRAP_LINK_INTEGRITY 129 /* Any link integrity threshold reached */ +#define SMA_TRAP_BUFFER_OVERRUN 130 /* Any buffer overrun threshold reached */ +#define SMA_TRAP_FLOW_WATCHDOG 131 /* Switch flow control update watchdog */ +#define SMA_TRAP_CHG_CAPABILITY 144 /* capability mask changed */ +#define SMA_TRAP_CHG_PLATGUID 145 /* platform (system) guid changed */ +#define SMA_TRAP_BAD_MKEY 256 /* Any bad M_key */ +#define SMA_TRAP_BAD_PKEY 257 /* Any bad P_key */ +#define SMA_TRAP_BAD_QKEY 258 /* Any bad Q_key */ +#define SMA_TRAP_SWITCH_BAD_PKEY 259 /* Switch bad P_key */ + +/* + * SwitchInfo + */ +typedef struct _SWITCH_INFO { + uint16 LinearFDBCap; /* Number of entries supported in the */ + /* Linear Unicast Forwarding Database */ + uint16 RandomFDBCap; /* Number of entries supported in the */ + /* Random Unicast Forwarding Database. */ + uint16 MulticastFDBCap; /* Number of entries supported in the */ + /* Multicast Forwarding Database */ + uint16 LinearFDBTop; /* Indicates the top of the linear */ + /* forwarding table. */ + uint8 DefaultPort; /* forward to this port all unicast */ + /* packets from other ports */ + /* whose DLID does not exist in the random */ + /* fwd table */ + uint8 DefaultMulticastPrimaryPort; + uint8 DefaultMulticastNotPrimaryPort; + union { + uint8 AsReg8; + struct { +#if CPU_BE + uint8 LifeTimeValue: 5; + uint8 PortStateChange: 1; + uint8 OptimizedSLVL: 2; +#else + uint8 OptimizedSLVL: 2; + uint8 PortStateChange:1; /* This bit is set to zero by a */ + /* management write. */ + uint8 LifeTimeValue: 5; /* Sets the time a packet can live in */ + /* the switch. See section XXX */ +#endif + } s; + } u1; + uint16 LIDsPerPort; /* specifies no. of LID/LMC combinations */ + /* that may be assigned */ + /* to a given link port for switches that */ + /* support the Random Forwarding database */ + /* model */ + uint16 PartitionEnforcementCap;/* Specifies the number of entries in the */ + /* partition enforcement table. */ + union { + uint8 AsReg8; + struct { +#if CPU_BE + uint8 InboundEnforcementCapable: 1; + uint8 OutboundEnforcementCapable: 1; + uint8 FilterRawPacketInboundCapable: 1; + uint8 FilterRawPacketOutboundCapable: 1; + uint8 EnhancedPort0: 1; + uint8 reserved: 3; +#else + uint8 reserved: 3; + uint8 EnhancedPort0: 1; + uint8 FilterRawPacketOutboundCapable: 1; + uint8 FilterRawPacketInboundCapable: 1; + uint8 OutboundEnforcementCapable: 1; + uint8 InboundEnforcementCapable: 1; +#endif /*CPU_BE */ + } s; + } u2; + + uint8 Reserved2; + + uint16 MulticastFDBTop; /* Indicates the top of the multicast */ + /* forwarding table. */ +} PACK_SUFFIX SWITCH_INFO; + + +/* + * GuidInfo + */ + +/* The GuidInfo Attribute allows the setting of GUIDs to an end port. */ +#define GUID_INFO_BLOCK_SIZE 8 +#define GUID_INFO_MAX_BLOCK_NUM 31 + +typedef struct _GUID_INFO { + /* Gid 0 in block 0 is Read only invariant value of the BASE GUID */ + uint64 Gid[GUID_INFO_BLOCK_SIZE]; +} PACK_SUFFIX GUID_INFO; + +/* + * PartitionTable + */ + +#define PARTITION_TABLE_BLOCK_SIZE 32 +#define PARTITION_TABLE_MAX_BLOCK_NUM 2047 + +typedef union _P_KeyBlock { + uint16 AsInt16; + + struct { + uint16 P_KeyBase: 15; /* Base value of the P_Key that */ + /* the endnode will use to check */ + /* against incoming packets */ + uint16 MembershipType: 1; /* 0 = Limited type */ + /* 1 = Full type */ + } p; + +} PACK_SUFFIX P_KEY_BLOCK; + +typedef struct _PARTITION_TABLE { + + P_KEY_BLOCK PartitionTableBlock[PARTITION_TABLE_BLOCK_SIZE]; /* List of P_Key Block elements */ + +} PACK_SUFFIX PARTITION_TABLE; + + + +/* + * ForwardingTable + */ + +typedef struct _LID_Port_Block { + uint16 LID; /* base LID */ + struct { +#if CPU_BE + uint8 Valid: 1; /* valid bit */ + uint8 LMC: 3; /* the LMC of this LID */ + uint8 reserved: 4; /* for alignment */ +#else + uint8 reserved: 4; /* for alignment */ + uint8 LMC: 3; /* the LMC of this LID */ + uint8 Valid: 1; /* valid bit */ +#endif + } s; + PORT Port; +} PACK_SUFFIX LID_PORT_BLOCK; + +typedef uint16 PORTMASK; /* port mask block element */ + +#define LFT_BLOCK_SIZE 64 +#define RFT_BLOCK_SIZE 16 +#define RFT_MAX_BLOCK_NUM 3071 +#define MFT_BLOCK_SIZE 32 +#define MFT_BLOCK_WIDTH 16 // width of portmask in bits +typedef struct _FORWARDING_TABLE { + + union { + + struct _Linear { + PORT LftBlock[64]; + } Linear; + + struct _Random { + LID_PORT_BLOCK RftBlock[16]; + } Random; + + struct _Multicast { + PORTMASK MftBlock[32]; + } Multicast; + } u; + +} PACK_SUFFIX FORWARDING_TABLE; + + + +/* + * SMInfo + */ + +typedef enum _SM_STATE { + SM_INACTIVE = 0, + SM_DISCOVERING, + SM_STANDBY, + SM_MASTER, + /* 4-255 - Reserved */ +} SM_STATE ; + +typedef struct _SM_INFO { + uint64 GUID; /* This SM's perception of the GUID */ + /* of the master SM. */ + uint64 SM_Key; /* Key of this SM. This is shown as 0 unless */ + /* the requesting SM is proven to be the */ + /* master, or the requester is otherwise */ + /* authenticated */ + uint32 ActCount; /* Counter that increments each time the SM */ + /* issues a SMP or performs other management */ + /* activities. Used as a 'heartbeat' indicator */ + /* by standby SMs. */ + struct { +#if CPU_BE + uint8 Priority: 4; + uint8 SMState: 4; +#else + uint8 SMState: 4; /* Enumerated value indicating this SM's state. */ + /* Enumerated as SM_STATE. */ + uint8 Priority: 4; /* Administratively assigned priority for this */ + /* SM. Can be reset by master SM. */ +#endif + } s; + +} PACK_SUFFIX SM_INFO; + +// SM Service Record +#define SM_SERVICE_ID (0x1100d03c34822222ull) +#define SM_CAPABILITY_NONE 0x00000000 +#define SM_CAPABILITY_VSWINFO 0x00000001 + +/* convert SM State to text */ +static __inline const char* +IbSMStateToText(SM_STATE state) +{ + return (state == SM_INACTIVE? "Inactive": + state == SM_DISCOVERING? "Discovering": + state == SM_STANDBY? "Standby": + state == SM_MASTER? "Master": "???"); +} + +/* + * VendorDiag + */ + +typedef enum { + DIAG_NODE_READY = 0, + DIAG_SELF_TEST, + DIAG_INIT, + DIAG_SOFT_ERROR, + DIAG_HARD_ERROR, + DIAG_RESERVED +} IB_DIAG_CODE; + +typedef struct _VendorDiag { + + union { + uint16 NextIndex; /* Next attribute Modifier to get to Diag Info. */ + /* Set to zero if this s last or only */ + /* diag data. */ + struct { +#if CPU_BE + uint16 UniversalDiagCode: 4; + uint16 VendorDiagCode: 11; + uint16 Chain: 1; +#else /* CPU_LE */ + uint16 Chain: 1; + uint16 VendorDiagCode: 11; + uint16 UniversalDiagCode: 4; +#endif + } s; + } u; + + uint8 DiagData[62]; /* Vendor specific diag info. Format undefined. */ + +} PACK_SUFFIX VendorDiag, VENDOR_DIAG; + + +/* + * Define VL Arbitration table. + */ +#define IB_VLARBTABLE_SIZE 32 + +typedef struct _VLArbBlock{ + struct { +#if CPU_BE + uint8 Reserved: 4; + uint8 VL: 4; +#else + uint8 VL: 4; + uint8 Reserved: 4; +#endif /*CPU_BE */ + } s; + + uint8 Weight; +} PACK_SUFFIX VLArbBlock; + +typedef struct _VLARBTABLE { + VLArbBlock ArbTable[IB_VLARBTABLE_SIZE]; +} PACK_SUFFIX VLARBTABLE; + +#define PGTABLE_LIST_COUNT 64 + +typedef struct _PORT_GROUP_TABLE { + uint8 PortGroup[PGTABLE_LIST_COUNT]; /* List of PortGroups indexed by port */ +} PACK_SUFFIX PORT_GROUP_TABLE; + +#define LIDMASK_LEN 64 + +typedef struct _ADAPTIVE_ROUTING_LIDMASK { + uint8 lidmask[LIDMASK_LEN]; // lidmask block of 512 lids +} PACK_SUFFIX ADAPTIVE_ROUTING_LIDMASK; + +#include "iba/public/ipackoff.h" + +static __inline void +BSWAP_SMP_HEADER( + SMP *Dest + ) +{ +#if CPU_LE + BSWAP_MAD_HEADER((MAD *)Dest); + + Dest->M_Key = ntoh64(Dest->M_Key); + Dest->SmpExt.DirectedRoute.DrSLID = \ + ntoh16(Dest->SmpExt.DirectedRoute.DrSLID); + Dest->SmpExt.DirectedRoute.DrDLID = \ + ntoh16(Dest->SmpExt.DirectedRoute.DrDLID); +#endif +} + +static __inline void +BSWAP_NODE_DESCRIPTION( + NODE_DESCRIPTION *Dest + ) +{ + /* pure text field, nothing to swap */ +} + + +static __inline void +BSWAP_NODE_INFO( + NODE_INFO *Dest + ) +{ +#if CPU_LE + Dest->SystemImageGUID = ntoh64(Dest->SystemImageGUID ); + Dest->NodeGUID = ntoh64(Dest->NodeGUID); + Dest->PortGUID = ntoh64(Dest->PortGUID); + Dest->PartitionCap = ntoh16(Dest->PartitionCap); + Dest->DeviceID = ntoh16(Dest->DeviceID); + Dest->Revision = ntoh32(Dest->Revision); + Dest->u1.AsReg32 = ntoh32(Dest->u1.AsReg32); +#endif +} + + +/* The extended flag should only be used when the PORT_INFO structure + * used contains the full set of fields. This is generally true for SMA + * operations, but when operating against SA PortInfoRecords the + * extra data may not be present + */ +static __inline void +BSWAP_PORT_INFO( + PORT_INFO *Dest, int extended + ) +{ +#if CPU_LE + Dest->M_Key = ntoh64(Dest->M_Key); + Dest->SubnetPrefix = ntoh64(Dest->SubnetPrefix); + Dest->LID = ntoh16(Dest->LID); + Dest->MasterSMLID = ntoh16(Dest->MasterSMLID); + Dest->CapabilityMask.AsReg32 = ntoh32(Dest->CapabilityMask.AsReg32); + Dest->DiagCode = ntoh16(Dest->DiagCode); + Dest->M_KeyLeasePeriod = ntoh16(Dest->M_KeyLeasePeriod); + Dest->Violations.M_Key = ntoh16(Dest->Violations.M_Key); + Dest->Violations.P_Key = ntoh16(Dest->Violations.P_Key); + Dest->Violations.Q_Key = ntoh16(Dest->Violations.Q_Key); + Dest->MaxCreditHint = ntoh16(Dest->MaxCreditHint); + Dest->Latency.LinkRoundTrip = + ((Dest->Latency.LinkRoundTrip & 0x0000FF) << 16) | + (Dest->Latency.LinkRoundTrip & 0x00FF00) | + ((Dest->Latency.LinkRoundTrip & 0xFF0000) >> 16); + if (extended) + Dest->CapabilityMask2 = ntoh16(Dest->CapabilityMask2); +#endif +} + + +static __inline void +BSWAP_PART_TABLE( + PARTITION_TABLE *Dest + ) +{ +#if CPU_LE + uint32 i; + + + for (i=0; i<32; i++) + { + Dest->PartitionTableBlock[i].AsInt16 = \ + ntoh16(Dest->PartitionTableBlock[i].AsInt16); + } +#endif +} + + +static __inline void +BSWAP_SWITCH_INFO( + SWITCH_INFO *Dest + ) +{ +#if CPU_LE + Dest->LinearFDBCap = ntoh16(Dest->LinearFDBCap); + Dest->RandomFDBCap = ntoh16(Dest->RandomFDBCap); + Dest->MulticastFDBCap = ntoh16(Dest->MulticastFDBCap); + Dest->LinearFDBTop = ntoh16(Dest->LinearFDBTop); + Dest->LIDsPerPort = ntoh16(Dest->LIDsPerPort); + Dest->PartitionEnforcementCap = ntoh16(Dest->PartitionEnforcementCap); + Dest->MulticastFDBTop = ntoh16(Dest->MulticastFDBTop); +#endif +} + +static __inline void +BSWAP_GUID_INFO( + GUID_INFO *Dest + ) +{ +#if CPU_LE + int i; + + for (i=0; iGid[i] = ntoh64(Dest->Gid[i]); + } +#endif +} + +static __inline void +BSWAP_VLARBTABLE( + VLARBTABLE *Dest + ) +{ + /* we laid this out in network byte order for intel compilers */ +} + +static __inline void +BSWAP_LINEAR_FWD_TABLE( + FORWARDING_TABLE *Dest + ) +{ +#if CPU_LE + /* nothing to do, PORT is only 1 byte */ +#endif +} + +static __inline void +BSWAP_RANDOM_FWD_TABLE( + FORWARDING_TABLE *Dest + ) +{ +#if CPU_LE +#if defined(VXWORKS) + uint32 i; +#else + uint i; +#endif + + for (i=0; i< 16; ++i) + { + Dest->u.Random.RftBlock[i].LID = ntoh16(Dest->u.Random.RftBlock[i].LID); + } +#endif +} + +static __inline void +BSWAP_MCAST_FWD_TABLE( + FORWARDING_TABLE *Dest + ) +{ +#if CPU_LE +#if defined(VXWORKS) + uint32 i; +#else + uint i; +#endif + + for (i=0; i< 32; ++i) + { + Dest->u.Multicast.MftBlock[i] = ntoh16(Dest->u.Multicast.MftBlock[i]); + } +#endif +} + +static __inline void +BSWAP_SM_INFO( + SM_INFO *Dest + ) +{ +#if CPU_LE + Dest->GUID = ntoh64(Dest->GUID); + Dest->SM_Key = ntoh64(Dest->SM_Key); + Dest->ActCount = ntoh32(Dest->ActCount); +#endif +} + +static __inline void +BSWAP_VENDOR_DIAG( + VENDOR_DIAG *Dest + ) +{ +#if CPU_LE + Dest->u.NextIndex = ntoh32(Dest->u.NextIndex); +#endif +} + +static __inline void +BSWAP_PORT_GROUP_TABLE( + PORT_GROUP_TABLE *Dest + ) +{ +} + +static __inline void +BSWAP_ADAPTIVE_ROUTING_LIDMASK( + ADAPTIVE_ROUTING_LIDMASK *Dest + ) +{ +} + +#if defined (__cplusplus) +}; +#endif + +#endif /* __IBA_IB_SM_PRIV_H__ */ diff --git a/IbAccess/Common/Inc/ib_sm_types.h b/IbAccess/Common/Inc/ib_sm_types.h new file mode 100644 index 0000000..c051deb --- /dev/null +++ b/IbAccess/Common/Inc/ib_sm_types.h @@ -0,0 +1,476 @@ +/* BEGIN_ICS_COPYRIGHT3 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT3 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +#ifndef __IBA_IB_SM_TYPES_H__ +#define __IBA_IB_SM_TYPES_H__ + +#include "iba/public/datatypes.h" +#include "iba/stl_mad_types.h" +#include "iba/public/ibyteswap.h" + +// CPU_LE code below can't get to uint typedef +#if defined(VXWORKS) +typedef unsigned int uint; +#endif + +#if defined (__cplusplus) +extern "C" { +#endif + +#include "iba/public/ipackon.h" + +/* + * Defines + */ + +#define IB_SM_CLASS_VERSION 1 /* Subnet Management */ + +/* SMP Attributes */ +#define MCLASS_ATTRIB_ID_NODE_DESCRIPTION 0x0010 /* Node description string */ +#define MCLASS_ATTRIB_ID_NODE_INFO 0x0011 /* Generic node data */ +#define MCLASS_ATTRIB_ID_SWITCH_INFO 0x0012 /* Switch information */ +/* 0x0013 reserved (was RouterInfo) */ +#define MCLASS_ATTRIB_ID_GUID_INFO 0x0014 /* Assigned GIDs */ +#define MCLASS_ATTRIB_ID_PORT_INFO 0x0015 /* Port Information */ +#define MCLASS_ATTRIB_ID_PART_TABLE 0x0016 /* Partition Table */ + +#define MCLASS_ATTRIB_ID_SL_VL_MAPPING_TABLE 0x0017 /* Service level to */ + /* Virtual Lane mapping info */ +#define MCLASS_ATTRIB_ID_VL_ARBITRATION 0x0018 /* List of weights */ +#define MCLASS_ATTRIB_ID_LINEAR_FWD_TABLE 0x0019 /* Linear forwarding table */ +#define MCLASS_ATTRIB_ID_RANDOM_FWD_TABLE 0x001A /* Random forwarding */ + /* database information */ +#define MCLASS_ATTRIB_ID_MCAST_FWD_TABLE 0x001B /* Multicast forwarding */ + /* database information */ + +#define MCLASS_ATTRIB_ID_SM_INFO 0x0020 /* Subnet Manager */ + /* Information */ +/* 0x0021 reserved - was RoutingInfo */ +#define MCLASS_ATTRIB_ID_VENDOR_DIAG 0x0030 /* Vendor specific */ + /* Diagnostic */ +#define MCLASS_ATTRIB_ID_LED_INFO 0x0031 /* Turn on/off LED */ + +#define MCLASS_ATTRIB_ID_PORT_LFT 0xff19 /* Port Linear forwarding table */ +#define MCLASS_ATTRIB_ID_PORT_GROUP 0xff21 /* Vendor Port Group Info */ +#define MCLASS_ATTRIB_ID_AR_LIDMASK 0xff22 /* LID Mask for Adaptive Routing */ + +#define MCLASS_ATTRIB_ID_COLLECTIVE_NOTICE 0xff40 /* Vendor unique collective notice */ +#define MCLASS_ATTRIB_ID_CMLIST 0xff41 /* Vendor unique collective multicast list */ +#define MCLASS_ATTRIB_ID_CFT 0xff42 /* Vendor unique collective forwarding table */ + +/* SMP Attribute Modifiers */ +#define MCLASS_ATTRIB_MOD_SUPPORTS_EXT_SPEEDS 0x80000000 /* SMSupportsExtendedLinkSpeeds */ + +typedef uint8 PORT; /* Convenience type. */ + +/* + * NodeInfo + */ +typedef struct _NODE_INFO { + + uint8 BaseVersion; /* Supported MAD Base Version. */ + uint8 ClassVersion; /* Supported Subnet Management Class */ + /* (SMP) Version. */ + uint8 NodeType; + uint8 NumPorts; /* Number of link ports on this node. */ + + /* note GUIDs on 4 byte boundary */ + uint64 SystemImageGUID; + + uint64 NodeGUID; /* GUID of the HCA, TCA, switch, */ + /* or router itself. */ + uint64 PortGUID; /* GUID of this end port itself. */ + + uint16 PartitionCap; /* Number of entries in the Partition Table */ + /* for end ports. */ + uint16 DeviceID; /* Device ID information as assigned by */ + /* device manufacturer. */ + uint32 Revision; /* Device revision, assigned by manufacturer. */ + + union { + uint32 AsReg32; + + struct { +#if CPU_BE + uint32 LocalPortNum: 8; /* The link port number this */ + uint32 VendorID: 24; /* Device vendor, per IEEE. */ +#else + uint32 VendorID: 24; /* Device vendor, per IEEE. */ + uint32 LocalPortNum: 8; /* The link port number this */ + /* SMP came on in. */ +#endif + } s; + } u1; + +} PACK_SUFFIX NODE_INFO; + + +/* + * NodeDescription + */ + +#define NODE_DESCRIPTION_ARRAY_SIZE 64 + +typedef struct _NODE_DESCRIPTION { + + /* Node String is an array of UTF-8 character that */ + /* describes the node in text format */ + /* Note that this string is NOT NULL TERMINATED! */ + uint8 NodeString[NODE_DESCRIPTION_ARRAY_SIZE]; + +} PACK_SUFFIX NODE_DESCRIPTION; + + + +/* + * PortInfo + */ + +#define PORT_RESP_TIME_VALUE_MAX 8 + + +/* Link width, indicated as follows: + * values are additive for Supported and Enabled fields + */ +typedef enum _IB_LINK_WIDTH { + IB_LINK_WIDTH_NOP = 0, /* no change, valid only for LinkWidthEnabled */ + IB_LINK_WIDTH_1X = 1, + IB_LINK_WIDTH_4X = 2, + IB_LINK_WIDTH_8X = 4, + IB_LINK_WIDTH_12X = 8, + IB_LINK_WIDTH_ALL_SUPPORTED = 255 /* valid only for LinkWidthEnabled */ +} IB_LINK_WIDTH; + + +/* Link speed, indicated as follows: + * values are additive for Supported and Enabled fields + * Link speed extended values (FDR/EDR) are also included; note however, that + * extended values appear in PORT_INFO in LinkSpeedExt + */ +typedef enum _IB_LINK_SPEED { + IB_LINK_SPEED_NOP = 0, /* no change, valid only for enabled */ + IB_LINK_SPEED_DEFAULT = 1, /* 2.5Gbps (SDR) */ /* depricated */ + IB_LINK_SPEED_2_5G = 1, /* 2.5Gbps (SDR) */ /* use this one */ + IB_LINK_SPEED_5G = 2, /* 5.0Gbps (DDR) */ + IB_LINK_SPEED_10G = 4, /* 10.0Gbps (QDR) */ + IB_LINK_SPEED_RESERVED = 8, /* Reserved */ + IB_LINK_SPEED_14G = 16, /* 14.0625 Gbps (FDR) */ + IB_LINK_SPEED_25G = 32, /* 25.78125 Gbps (EDR) */ + IB_LINK_SPEED_ALL_SUPPORTED = 63 /* valid only for LinkSpeedEnabled */ +} IB_LINK_SPEED; + +/* Port States */ +#define IB_PORT_NOP PortStateNop /* 0 - No state change */ +#define IB_PORT_DOWN PortStateDown /* 1 - Down */ + /* includes failed links */ +#define IB_PORT_INIT PortStateInit /* 2 - Initialize */ +#define IB_PORT_ARMED PortStateArmed /* 3 - Armed */ +#define IB_PORT_ACTIVE PortStateActive /* 4 - Active */ +#define IB_PORT_STATE_MAX PortStateMax /* Maximum Valid Value */ + /* reserved 5-15 */ + +typedef enum _IB_PORT_PHYS_STATE { + IB_PORT_PHYS_NOP = 0, /* 0 - No State change */ + IB_PORT_PHYS_SLEEP = 1, /* 1 - sleep */ + IB_PORT_PHYS_POLLING = 2, /* 2 - polling */ + IB_PORT_PHYS_DISABLED = 3, /* 3 - disabled */ + IB_PORT_PHYS_TRAINING = 4, /* 4 - port config training */ + IB_PORT_PHYS_LINKUP = 5, /* 5 - linkup */ + IB_PORT_PHYS_LINK_ERROR_RECOVERY = 6, /* 6 - Link error recovery */ + IB_PORT_PHYS_MAX = 6, /* Maximum Valid Value */ + IB_PORT_PHYS_RESERVED = 7 /* 7 - 15 - reserved, ignored */ +} IB_PORT_PHYS_STATE; + +/* IB_MTU is defined in ib_types.h */ + +#define IB_LIFETIME_MAX 19 /* max for HOQLife and LifeTimeValue, >19 -> Infinite */ + +/* Values for M_KeyProtectBits */ +typedef enum _IB_MKEY_PROTECT { + IB_MKEY_PROTECT_RO = 0, /* Get allows any MKey, Set protected */ + IB_MKEY_PROTECT_HIDE = 1, /* Get allows any MKey, Resp Hides, Set protected */ + IB_MKEY_PROTECT_SECURE = 2, /* Get/Set Protected */ + IB_MKEY_PROTECT_SECURE2 = 3 /* Get/Set Protected */ +} IB_MKEY_PROTECT; + +/* Capability Mask A bit set to 1 for affirmation of supported capability + * by a given port + */ +typedef union _CapabilityMask { + uint32 AsReg32; + struct { IB_BITFIELD31( uint32, + CmReserved6: 1, /* shall be zero */ + IsMulticastFDBTopSupported: 1, + IsMulticastPKeyTrapSuppressionSupported:1, + CmReserved5: 2, /* shall be zero */ + IsOtherLocalChangeNoticeSupported: 1, + IsClientReregistrationSupported: 1, + IsLinkRoundTripLatencySupported: 1, + IsBootManagementSupported: 1, + IsCapabilityMaskNoticeSupported: 1, + IsDRNoticeSupported: 1, + IsVendorClassSupported: 1, + IsDeviceManagementSupported: 1, + IsReinitSupported: 1, + IsSNMPTunnelingSupported: 1, + IsConnectionManagementSupported: 1, + IsCapabilityMask2Supported: 1, + IsExtendedSpeedsSupported: 1, + IsCableInfoSupported: 1, + IsPKeySwitchExternalPortTrapSupported:1, + IsSystemImageGuidSupported: 1, + IsSMDisabled: 1, + IsLEDInfoSupported: 1, + IsPKeyNVRAM: 1, /* P_Key in NVRAM */ + IsMKeyNVRAM: 1, /* M_Key in NVRAM */ + IsSLMappingSupported: 1, + IsAutomaticMigrationSupported: 1, + CmReserved2: 1, + IsTrapSupported: 1, + IsNoticeSupported: 1, + IsSM: 1, + CmReserved1: 1 ) + } s; +} IB_CAPABILITY_MASK; + +typedef struct _PORT_INFO { + + uint64 M_Key; /* The 8-byte management key. */ + uint64 SubnetPrefix; /* Subnet prefix for this port. */ + /* Set to default value of XXXXX if no */ + /* other subnet interaction. */ + /* GidPrefix ??? */ + uint16 LID; /* The base LID of this port. */ + uint16 MasterSMLID; /* The base LID of the master SM that is */ + /* managing this port. */ + IB_CAPABILITY_MASK CapabilityMask; /* port capabilities */ + uint16 DiagCode; /* Diagnostic code, Refer Node Diagnostics */ + uint16 M_KeyLeasePeriod; + + uint8 LocalPortNum; /* The link port number this SMP came on in. */ + + struct _LinkWidth { + uint8 Enabled; /* Enabled link width */ + uint8 Supported; /* Supported link width */ + uint8 Active; /* Currently active link width */ + } LinkWidth; + + + struct { +#if CPU_BE + uint8 SpeedSupported: 4; /* Supported link speed */ + uint8 PortState: 4; /* Port State. */ +#else + uint8 PortState: 4; /* Port State. */ + uint8 SpeedSupported: 4; /* Supported link speed */ +#endif +#if CPU_BE + uint8 PortPhysicalState: 4; + uint8 DownDefaultState: 4; +#else + uint8 DownDefaultState: 4; + uint8 PortPhysicalState: 4; +#endif + } Link; + + struct { +#if CPU_BE + uint8 M_KeyProtectBits: 2; /* see mgmt key usage */ + uint8 Reserved: 3; /* reserved, shall be zero */ + uint8 LMC: 3; /* LID mask for multipath support */ +#else + uint8 LMC: 3; /* LID mask for multipath support */ + uint8 Reserved: 3; /* reserved, shall be zero */ + uint8 M_KeyProtectBits: 2; /* see mgmt key usage */ +#endif + } s1; + + struct _LinkSpeed { +#if CPU_BE + uint8 Active: 4; /* Currently active link speed */ + uint8 Enabled: 4; /* Enabled link speed */ +#else + uint8 Enabled: 4; /* Enabled link speed */ + uint8 Active: 4; /* Currently active link speed */ +#endif + } LinkSpeed; + + struct { +#if CPU_BE + uint8 NeighborMTU: 4; + uint8 MasterSMSL: 4; +#else + uint8 MasterSMSL: 4; /* The adminstrative SL of the master */ + /* SM that is managing this port. */ + uint8 NeighborMTU: 4; /* MTU of neighbor endnode connected */ + /* to this port */ +#endif + } s2; + + + struct { + struct { +#if CPU_BE + uint8 Cap: 4; /* Virtual Lanes supported on this port */ + uint8 InitType: 4; /* IB_PORT_INIT_TYPE */ +#else + uint8 InitType: 4; /* IB_PORT_INIT_TYPE */ + uint8 Cap: 4; /* Virtual Lanes supported on this port */ +#endif + } s; + + uint8 HighLimit; /* Limit of high priority component of */ + /* VL Arbitration table */ + uint8 ArbitrationHighCap; + uint8 ArbitrationLowCap; + } VL; + + struct { +#if CPU_BE + uint8 InitTypeReply: 4; /* IB_PORT_INIT_TYPE */ + uint8 Cap: 4; /* Maximum MTU supported by this port. */ +#else + uint8 Cap: 4; /* Maximum MTU supported by this port. */ + uint8 InitTypeReply: 4; /* IB_PORT_INIT_TYPE */ +#endif + } MTU; + + struct { /* transmitter Queueing Controls */ +#if CPU_BE + uint8 VLStallCount: 3; + uint8 HOQLife: 5; +#else + uint8 HOQLife: 5; /* Applies to routers & switches only */ + uint8 VLStallCount: 3; /* Applies to switches only. */ +#endif + } XmitQ; + + struct { +#if CPU_BE + uint8 OperationalVL: 4; /* Virtual Lanes */ + uint8 PartitionEnforcementInbound: 1; + uint8 PartitionEnforcementOutbound: 1; + uint8 FilterRawInbound: 1; + uint8 FilterRawOutbound: 1; +#else + uint8 FilterRawOutbound: 1; + uint8 FilterRawInbound: 1; + uint8 PartitionEnforcementOutbound: 1; + uint8 PartitionEnforcementInbound: 1; + uint8 OperationalVL: 4; /* Virtual Lanes */ + /* operational on this port */ +#endif + } s3; + + struct _Violations { + uint16 M_Key; + uint16 P_Key; + uint16 Q_Key; + } Violations; + + uint8 GUIDCap; /* Number of GID entries supported in the */ + /* GIDInfo attribute */ + + + struct { +#if CPU_BE + uint8 ClientReregister: 1; + uint8 Reserved: 2; + uint8 Timeout: 5; +#else + uint8 Timeout: 5; /* Timer value used for subnet timeout */ + uint8 Reserved: 2; + uint8 ClientReregister: 1; +#endif + } Subnet; + + + struct { +#if CPU_BE + uint8 Reserved: 3; + uint8 TimeValue: 5; +#else + uint8 TimeValue: 5; + uint8 Reserved: 3; +#endif + + } Resp; + + struct _ERRORS { +#if CPU_BE + uint8 LocalPhys: 4; + uint8 Overrun: 4; +#else + uint8 Overrun: 4; + uint8 LocalPhys: 4; +#endif + } Errors; + + uint16 MaxCreditHint; /* Max Credit Hint */ + + struct _LATENCY { +#if CPU_BE + uint32 Reserved: 8; + uint32 LinkRoundTrip: 24; /* LinkRoundTripLatency */ +#else + uint32 LinkRoundTrip: 24; + uint32 Reserved: 8; +#endif + } Latency; + + uint16 CapabilityMask2; /* Capability Mask 2 */ + + struct _LinkSpeedExt { +#if CPU_BE + uint8 Active: 4; /* Currently active link speed extended */ + uint8 Supported: 4; /* Supported link speed extended */ +#else + uint8 Supported: 4; /* Supported link speed extended */ + uint8 Active: 4; /* Currently active link speed extended */ +#endif +#if CPU_BE + uint8 Reserved: 3; /* Reserved */ + uint8 Enabled: 5; /* Enabled link speed extended */ +#else + uint8 Enabled: 5; /* Enabled link speed extended */ + uint8 Reserved: 3; /* Reserved */ +#endif + } LinkSpeedExt; + +} PACK_SUFFIX PORT_INFO; + +#include "iba/public/ipackoff.h" + +#if defined (__cplusplus) +}; +#endif + +#endif /* __IBA_IB_SM_TYPES_H__ */ diff --git a/IbAccess/Common/Inc/ib_smi.h b/IbAccess/Common/Inc/ib_smi.h new file mode 100644 index 0000000..2fd8125 --- /dev/null +++ b/IbAccess/Common/Inc/ib_smi.h @@ -0,0 +1,522 @@ +/* BEGIN_ICS_COPYRIGHT1 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT1 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +#ifndef __IBA_IB_SMI_H__ +#define __IBA_IB_SMI_H__ (1) + + +#if defined(VXWORKS) + +/* kernel mode SMI Interfaces */ + +#include +#include "iba/stl_types.h" +#include "iba/stl_sm_types.h" + + +#if defined (__cplusplus) +extern "C" { +#endif + + +/* + * Defines + */ + + + +/* + * Interface Definitions + * + * The SM is a trusted client and the only client to the SMA. + * Since the data and structures maintained by SMA may be of interest + * to the SM and most times be duplicated, it may be desirable to share + * as much common info as possible between the two modules. + * The use of SMA_OBJECT helps attain this goal. Only those values that + * are of use to the SM are exposed, keeping the rest as private to SMA + * and opaque to SM. + */ + + +/* + * Per Port definitions + */ + +typedef struct _SMA_PORT_BLOCK { + EUI64 GUID; /* Port GUID */ + uint8 PortNumber; + + uint8 NumPKeys; /* Number of Pkeys in the Pkey table */ + uint8 NumGIDs; /* Number of GIDs in the GID table */ + + IB_PORT_STATE State; + IB_PORT_ADDRESS Address; /* Port addressing info */ + +#if 0 + /* these are not used */ + /* Sma */ + IB_HANDLE QpHandle; + uint32 SendQDepth; /* Maximum outstanding WRs permitted */ + /* on the SendQ of the QP */ + uint32 RecvQDepth; /* Maximum outstanding WRs permitted */ + /* on the RecvQ */ +#endif + +} SMA_PORT_BLOCK; + + +/* + * An array of ports based on number of ports + */ + +typedef struct _SMA_PORT_TABLE { + SMA_PORT_BLOCK PortBlock[1]; +} SMA_PORT_TABLE; + + +/* Per Channel Adapter List */ +typedef struct _SMA_CA_OBJECT { + /* */ + /* Ca Specifics */ + /* */ + + EUI64 CaGuid; /* Node GUID */ + void *SmaCaContext; /* Context that uniquely identifies a CA */ + uint32 Ports; /* Number of ports on this CA */ + IB_CA_CAPABILITIES Capabilities; /* Capabilities of this CA */ + + SMA_PORT_TABLE *PortTbl; +} SMA_CA_OBJECT; + + +typedef struct _SMA_CA_TABLE { + SMA_CA_OBJECT CaObj[1]; /* An array of Ca structures */ +} SMA_CA_TABLE; + + + +/* Sma data structure information */ +typedef struct _SMA_OBJECT { + uint32 NumCa; /* Total CA's known */ + SMA_CA_TABLE *CaTbl; /* Pointer to LList of CA structures */ +} SMA_OBJECT; + + + + + +/* All Send/Recvs use this block */ +typedef struct _SMP_BLOCK { + void *Next; /* pointers maintained exclusively by SMA */ + void *Prev; /* pointers maintained exclusively by SMA */ + + FSTATUS Status; + + void *pSendContext; + void *SmaCaContext; /* Context that identifies CA */ + uint8 PortNumber; + + uint32 SmpByteCount; /* Used size of *Smp in bytes */ + /* When zero indicates MAD_BLOCK_SIZE */ + uint32 RecvByteCount; /* Total size of receive completion */ + void *Smp; /* Pointer to SMP/MAD */ + STL_LID DLID; /* destination LID */ + STL_LID SLID; /* source LID */ + + IB_PATHBITS PathBits; /* path bits */ + uint8 StaticRate; /* enum IB_STATIC_RATE */ + IB_SL ServiceLevel; + + + IB_GRH *Grh; /* Pointer to GRH */ +} SMP_BLOCK; + + +/* + * Callback definitions + */ + +/* + * SM_RCV_CALLBACK + * + * The receive callback that will be invoked for SMP's received. + * There may be more than one receives in the list. The SM should + * lookup the list till a NULL pointer is obtained on search of + * the link list. + * + * INPUTS: + * Context -user's context supplied during SmaOpen() + * SmpBlockList -List of SMP's received. + * + * OUTPUTS: + * None + * + * RETURNS: + * + */ +typedef +void (SM_RCV_CALLBACK)( + IN void *Context, + IN SMP_BLOCK *SmpBlockList + ); + + +/* + * SM_POST_CALLBACK + * + * The Post callback that will be called on all successful posts. The + * callback will pass back the user's context and a list of SMP's that + * were previously posted. + * + * The callback is registered with SMA during SmaPostSend() + * + * INPUTS: + * PostContext -user's context supplied during the post. + * SmpBlockList -List of SMP's posted. + * + * OUTPUTS: + * None + * + * RETURNS: + * + */ +typedef +void (SM_POST_CALLBACK)( + IN void *PostContext, + IN SMP_BLOCK *SmpBlockList + ); + + +typedef enum _SMA_EVENT { + EVENT_PORT, + EVENT_CA, + EVENT_SEND_ERROR + /*EVENT_RECV_ERROR */ +} SMA_EVENT; + + + +/* + * SM_EVENT_CALLBACK + * + * The Event callback that will be called for any events generated as + * listed in SMA_EVENT. The callback will specify the type of event + * and cause with optional paramaters. + * + * INPUTS: + * EventCode -The type of event as listed in SMA_EVENT + * Cause -The cause can point out to a port number or SMP_BLOCK + * data pointed to only valid during duration of call + * Context -If a post error, the user's context supplied during + * the post. + * + * OUTPUTS: + * None + * + * RETURNS: + * + */ +typedef +void (SM_EVENT_CALLBACK)( + IN SMA_EVENT EventCode, /* event that occured */ + IN void *Cause, /* cause; can be Smp_block/port no */ + IN void *Context /* if PostSend */ + ); + + + +/* + * Interface API's + */ + +/* + * SmaOpen + * + * Returns a pointer to an Object that refereces the SMA structures. + * The structures should be referenced as read-only. + * The SM can use the handles of CA/QP/CQ's for its own usage if required. + * No tracking of resources will be done if Handles are used. + * + * INPUTS: + * RcvCallback -Callback to be invoked if SMP's are received. + * PostCallback -Callback to be invoked on completion of SMP's posted. + * EventCallback -Event callback for all events. + * Context -User's Global context supplied back in Event callback + * + * OUTPUTS: + * SmObject -A pointer to an Object that references into the + * SMA structures. + * + * RETURNS: + * + */ +typedef FSTATUS +(SMA_OPEN)( + IN SM_RCV_CALLBACK *RcvCallback, +/* IN SM_POST_CALLBACK *PostCallback, */ + IN SM_EVENT_CALLBACK *EventCallback, + IN void *Context, + OUT SMA_OBJECT **SmObject + ); +IBA_API SMA_OPEN iba_smi_open; + + +/* + * SmaClose + * + * Dereferences usage of the SMA used previously by SmaOpen(). + * No tracking of resources will be done if Handles are used. + * + * INPUTS: + * SmObject -Object returned in the Open call. + * + * OUTPUTS: + * + * RETURNS: + * + */ +typedef FSTATUS +(SMA_CLOSE)( + IN SMA_OBJECT *SmObject + ); +IBA_API SMA_CLOSE iba_smi_close; + + +/* + * SmaPostSend + * + * All SMPs are sent out by the SM with this call. The caller can send one + * to many SMPs by listing each SMP through a linked list of SMP_BLOCKs. + * The user will specify the total SMPs contained in the list. + * + * INPUTS: + * SmObject -Object returned in the Open call. + * NumSmps -Number of SMPs in the list + * SmpBlockList -Linked list of send requests contained in SMP_BLOCKs + * PostCallback -A callback for SMPs Posted through SmpBlockList + * PostContext -user context that will be passed back on a post callback + * + * OUTPUTS: + * + * + * RETURNS: + * + * + */ +typedef FSTATUS +(SMA_POST_SEND)( + IN SMA_OBJECT *SmObject, + IN uint32 NumSmps, + IN SMP_BLOCK *SmpBlockList, + IN SM_POST_CALLBACK *PostCallback, + IN void *PostContext + ); +IBA_API SMA_POST_SEND iba_smi_post_send; + + +/* + * SmaPostRecv + * + * The caller can notify the SMA to recieve these many requests on this port. + * If the caller is expecting a known number of replies/receives, it should + * inform the SMA in advance to queue additional receives so as not to drop + * them. This call does not gaurantee that the SMA will not drop all + * incoming requests. However, it can help the SMA decide the traffic + * on this port. + * + * INPUTS: + * SmObject -Object returned in the Open call. + * SmacaContext -Context to Channel Adapter to post receives on + * PortNumber -Incoming Port on Channel Adapter. + * NumSmps -Number of Smps that the caller is expecting on port + * specified. + * + * OUTPUTS: + * + * + * RETURNS: + * + * + */ +typedef FSTATUS +(SMA_POST_RECV)( + IN SMA_OBJECT *SmObject, + IN void *SmaCaContext, + IN uint8 PortNumber, + IN uint32 NumSmps + ); +IBA_API SMA_POST_RECV iba_smi_post_recv; + + +/* + * SmaRecv + * + * Returns any SMPs received. If the call is successful, the NumSmps will + * indicate the number of SMPS received and the SmpBlockList will hold + * a list of SmpBlocks received. + * + * INPUTS: + * SmObject -Object returned in the Open call. + * NumSmps -Number of SMPs received. + * SmpBlockList -A Linked list of receives with specific information. + * The list contains individual SMP_BLOCKs and the + * elements in list is indicated by NumSmps. + * + * OUTPUTS: + * + * + * RETURNS: + * + * + */ +typedef FSTATUS +(SMA_RECV)( + IN SMA_OBJECT *SmObject, + IN uint32 *NumSmps, + OUT SMP_BLOCK **SmpBlockList + ); +IBA_API SMA_RECV iba_smi_recv; + + + +/* + * Common buffer calls for Smp's on requested Hca + * + * + * Usage: + * + * The SMA allocates all SMP buffers for sends and receives. Since these buffers + * are of a constant size (MAD size), allocation size is known at all times and hence + * not specified in calls. + * + * The following rules apply for all SMP buffer usage: + * * Cut down the requirements on system memory is reduced by half as there is no + * copy administered between Sends and Receives. The same SMP buffers are + * passed to/from the hardware. All SMP buffers come from registered memory. + * * The buffers are not tied down to a particular Channel Adapter. Hence they can + * be sent to or received from any CA. The memory registration is taken care of + * by the SMA. + * * The buffers are not required to be maintained by the Subnet Manager. All + * tracking is done by the SMA. + * * Once a buffer is submitted by a SmaPost or SmaSetLocal call to the SMA, it + * will be not returned back. + * * There is no rule maintained as to the order of these buffers. The Subnet Manager + * cannot except the same buffers to be passed in by the SMA. + * * All buffers allocated and returned through any send/receive calls hold the same + * size and is equal to the size of a MAD structure of 256 bytes. + * * A buffer once allocated from pool can be rturned back to pool by SmaPost() and + * SmaReturnToPool(). + * + */ + + +/* + * SmaGrabFromPool + * + * The SM can request registered memory from the SMA using this call. This memory can + * be then used to send Smp's. All memory received from this call will be in Smp sizes. + * + * INPUTS: + * SmObject -Object returned in the Open call. + * NumSmps -Number of blocks of memory that the caller wants in SMP sizes. + * SmpBlockList -A pointer to hold the SMPs requested. + * + * OUTPUTS: + * NumSmps -Number of blocks of memory allocated. + * SmpBlockList -Pointer filled with the first SMP_BLOCK entry that contains + * the linked list of SMA_BLOCKs allocated. + * + * RETURNS: + * + */ +typedef FSTATUS +(SMA_GRAB_FROM_POOL)( + IN SMA_OBJECT *SmObject, + IN OUT uint32 *NumSmps, + OUT SMP_BLOCK **SmpBlockList + ); +IBA_API SMA_GRAB_FROM_POOL iba_smi_pool_get; + + +/* + * SmaReturnToPool + * + * The caller can release memory back to the SMA using this call. + * + * INPUTS: + * SmObject -Object returned in the Open call. + * SmpBlockList -A pointer to the linked list of SMA_BLOCKs to be freed. + * + * OUTPUTS: + * + * + * RETURNS: + * + */ +typedef FSTATUS +(SMA_RETURN_TO_POOL)( + IN SMA_OBJECT *SmObject, + IN SMP_BLOCK *SmpBlockList + ); +IBA_API SMA_RETURN_TO_POOL iba_smi_pool_put; + + +/* + * SmaUpdateInfo + * + * The caller uses this function to update the SMA_OBJECT to reflect any + * changes to Channel adapters and their states. The call is done + * immedeatly after an state change event is received by the caller. + * + * INPUTS: + * SmObject -Object returned in the Open call. + * + * OUTPUTS: + * SmObject -Updated Object information. + * Event -Update information based on this event. + * + * RETURNS: + * + * + */ +typedef FSTATUS +(SMA_UPDATE_INFO)( + IN OUT SMA_OBJECT *SmObject + /*IN SMA_EVENT_TYPE Event */ + ); +IBA_API SMA_UPDATE_INFO iba_smi_update_info; + +#if defined (__cplusplus) +}; +#endif + +#endif /* VXWORKS */ +#endif /* __IBA_IB_SMI_H__ */ diff --git a/IbAccess/Common/Inc/ib_status.h b/IbAccess/Common/Inc/ib_status.h new file mode 100644 index 0000000..ff8502c --- /dev/null +++ b/IbAccess/Common/Inc/ib_status.h @@ -0,0 +1,79 @@ +/* BEGIN_ICS_COPYRIGHT3 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT3 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +#ifndef _IBA_IB_STATUS_H_ +#define _IBA_IB_STATUS_H_ + +#include "iba/public/datatypes.h" + +/* + * The following values defines different IB software stack modules. + * These are the values that would be found in bits 16 - 23 + */ + +#define IB_MOD_VPI 0x01 /* Verbs provider Interface */ +#define IB_MOD_VCA 0x02 /* Verbs Consumer Agent */ +#define IB_MOD_VKA 0x03 /* Verbs Kernel Agent */ +#define IB_MOD_GSA 0x04 /* General Services Agent */ +#define IB_MOD_SMA 0x05 /* Subnet Management Agent */ +#define IB_MOD_TSL 0x06 /* IB Transport Services */ +#define IB_MOD_SM 0x07 /* Subnet Manager */ +#define IB_MOD_CM 0x08 /* Connection Manager */ + +/* + * The low 8 bits define generic codes defined in the datatypes.h + * file. The top 24bits are application specific. For IB error and status + * types we use the low 8 bits of this 24 bits for module identification. we + * use the values defined above. The low 16 bits are module specific + * error codes that the module can choose to implement in their own way + * as applicable. + * + * 31 16 8 0 + * +--------+--------+--------+--------+ + * | module err code | mod # | fstatus| + * +--------+--------+--------+--------+ + */ + +#define SET_FSTATUS(fstatus, mod, mstatus) \ + ((fstatus) & 0x000000FF) | \ + (((mod) << 8) & 0x0000FF00) | \ + (((mstatus) << 16) & 0xFFFF0000) + +#define GET_STATUS(fstatus) \ + (fstatus & 0x000000FF) + +#define GET_MODULE(fstatus) \ + ((fstatus & 0x0000FF00) >> 8) + +#define GET_MODERR(fstatus) \ + ((fstatus & 0xFFFF0000) >> 16) + +#endif /* _IBA_IB_STATUS_H_ */ diff --git a/IbAccess/Common/Inc/ib_types.h b/IbAccess/Common/Inc/ib_types.h new file mode 100644 index 0000000..6132cd2 --- /dev/null +++ b/IbAccess/Common/Inc/ib_types.h @@ -0,0 +1,769 @@ +/* BEGIN_ICS_COPYRIGHT3 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT3 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +#ifndef _IBA_IB_TYPES_H_ +#define _IBA_IB_TYPES_H_ + +/* Basic Infiniband data types */ + +#define IB1_1 1 /* set to 1 to build IB 1.1 compliant version, 0 for 1.0a */ + +#include "iba/public/datatypes.h" +#include "iba/public/ibyteswap.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct _PCI_DEVICE; + +typedef void *IB_HANDLE; + +typedef uint32 IB_L_KEY; +typedef uint32 IB_R_KEY; +typedef uint32 IB_Q_KEY; +typedef uint16 IB_P_KEY; +typedef uint16 IB_LID; +typedef uint8 IB_PATHBITS; +#define IB_PATHBITS_MASK 0x7f /* path bits are no more than 7 bits */ +typedef uint8 IB_LMC; +typedef uint8 IB_SL; +typedef uint64 IB_VIRT_ADDR; + +typedef uint64 EUI64; + +/* the well-known Q_Key for QP1. */ +#define QP1_WELL_KNOWN_Q_KEY 0x80010000U + +/* the default P_Key */ +#define DEFAULT_P_KEY 0xffffU + +/* -------------------------------------------------------------------------- */ +/* LID's */ + +#define LID_RESERVED 0U /* RESERVED; */ +#define LID_PERMISSIVE 0xffffU /* PROMISCUOUS; */ + +#define LID_UCAST_START 0x0001U +#define LID_UCAST_END 0xbfffU + +#define LID_MCAST_START 0xc000U +#define LID_MCAST_END 0xfffeU + + +/* -------------------------------------------------------------------------- */ +/* GID's */ +#define IPV6_LINK_LOCAL_PREFIX 0x3faU /* 1111111010b */ +#define IPV6_SITE_LOCAL_PREFIX 0x3fbU /* 1111111011b */ +#define IPV6_MULTICAST_PREFIX 0xffU /* 11111111b */ + +/* Multicast Flags definitions */ +#define IPV6_MCAST_FLAG_PERMANENT 0U +#define IPV6_MCAST_FLAG_TRANSIENT 1U + +/* Multicast Address Scope definitions */ +typedef enum { + IPV6_RESERVED_0 = 0, + IPV6_NODE_LOCAL, + IPV6_LINK_LOCAL, + IPV6_RESERVED_3, + IPV6_RESERVED_4, + IPV6_SITE_LOCAL, + IPV6_RESERVED_6, + IPV6_RESERVED_7, + IPV6_ORG_LOCAL, + IPV6_RESERVED_9, + IPV6_RESERVED_10, + IPV6_RESERVED_11, + IPV6_RESERVED_12, + IPV6_RESERVED_13, + IPV6_GLOBAL, + IPV6_RESERVED_15 +} IPV6_MCAST_SCOPE; + + +/* Default GID subnet prefix. Can be combined with the port GUID to form a */ +/* GID usable on the local subnet. */ +#define DEFAULT_SUBNET_PREFIX 0xFE80000000000000Ull + +/* format fields for each format type */ +#define IB_GID_FORMAT_LINK_LOCAL 0x3faU /* 10 bits */ +#define IB_GID_FORMAT_SITE_LOCAL 0x3fbU /* 10 bits */ +#define IB_GID_FORMAT_MCAST 0xffU /* 8 bits */ +#define IB_GID_MCAST_FLAG_T 0x01U /* if set, non-permanent MC GID */ + + /* values for scope other than those below are reserved */ +#define IB_GID_MCAST_SCOPE_LINK_LOCAL 0x2U +#define IB_GID_MCAST_SCOPE_SITE_LOCAL 0x5U +#define IB_GID_MCAST_SCOPE_ORG_LOCAL 0x8U +#define IB_GID_MCAST_SCOPE_GLOBAL 0xeU + +#define IB_GID_MCAST_FORMAT_MASK_H 0xFF00000000000000Ull +#define IB_GID_ALL_CA_MCAST_H 0xFF02000000000000Ull +#define IB_GID_ALL_CA_MCAST_L 0x0000000000000001Ull + +#define IB_QP_MCAST 0xffffffU /* dest QP for multicast */ + +#include "iba/public/ipackon.h" + +typedef union _IB_GID { + uchar Raw[16]; + struct { +#if CPU_BE + uint32 HH; + uint32 HL; + uint32 LH; + uint32 LL; +#else + uint32 LL; + uint32 LH; + uint32 HL; + uint32 HH; +#endif + } AsReg32s; + struct { +#if CPU_BE + uint64 H; + uint64 L; +#else + uint64 L; + uint64 H; +#endif + } AsReg64s; + union _IB_GID_TYPE { + struct { +#if CPU_BE + struct { + uint64 FormatPrefix: 10; + uint64 Reserved: 54; /* Must be zero */ + } s; + EUI64 InterfaceID; +#else + EUI64 InterfaceID; + struct { + uint64 Reserved: 54; /* Must be zero */ + uint64 FormatPrefix: 10; + } s; +#endif + } LinkLocal; + + struct { +#if CPU_BE + struct { + uint64 FormatPrefix: 10; + uint64 Reserved: 38; /* Must be zero */ + uint64 SubnetPrefix: 16; + } s; + EUI64 InterfaceID; +#else + EUI64 InterfaceID; + struct { + uint64 SubnetPrefix: 16; + uint64 Reserved: 38; /* Must be zero */ + uint64 FormatPrefix: 10; + } s; +#endif + } SiteLocal; + + struct { +#if CPU_BE + uint64 SubnetPrefix; + EUI64 InterfaceID; +#else + EUI64 InterfaceID; + uint64 SubnetPrefix; +#endif + } Global; + + struct { +#if CPU_BE + struct { + uint16 FormatPrefix: 8; + uint16 Flags: 4; + uint16 Scope: 4; + } s; + uchar GroupId[14]; +#else + uchar GroupId[14]; + struct { + uint16 Scope: 4; + uint16 Flags: 4; + uint16 FormatPrefix: 8; + } s; +#endif + } Multicast; + } Type; +} PACK_SUFFIX IB_GID; + + +/* + * The IB Global Route header found in the first 40 bytes of the first data + * segment on globally routed Unreliable Datagram messages. + * + * TBD - cleanup to use similar names to GlobalRouteInfo in vpi.h + */ + +typedef struct _IB_GRH { + union { + uint32 AsReg32; + + struct _S_GRH { +#if CPU_LE + uint32 FlowLabel: 20; /* This field identifies sequences of */ + /* packets requiring special handling. */ + uint32 TClass : 8; /* Traffic Class-This field is used by */ + /* IBA to communicate global service level */ + uint32 IPVer : 4; /* IP Version-This field indicates version */ + /* of the GRH */ +#else + uint32 IPVer : 4; /* IP Version-This field indicates version */ + /* of the GRH */ + uint32 TClass : 8; /* Traffic Class-This field is used by */ + /* IBA to communicate global service level */ + uint32 FlowLabel: 20; /* This field identifies sequences of */ + /* packets requiring special handling. */ +#endif + } s; + } u1; + + uint16 PayLen; /* Payload length -This field indicates the length of */ + /* the packet in bytes following the GRH. */ + /* This includes from the first byte after the end of */ + /* the GRH up to but not including either the VCRC */ + /* or any padding to achieve 4 byte length. */ + /* For raw packets with GRH, the padding is determined */ + /* from the lower two bits of this GRH:Payload length */ + /* field. (For IBA packets it is determined from the */ + /* pad field in the transport header.) Padding is */ + /* placed immediately before the VCRC field. */ + /* Note: GRH:PayLen is different from LRH:PkyLen. */ + uint8 NxtHdr; /* Next Header-This field identifies the header */ + /* following the GRH. This field is included for */ + /* compatibility with IPV6 headers. */ + /* It should indicate IBA transport. */ + uint8 HopLimit; /* Hop Limit-This field sets a strict bound on */ + /* the number of hops between subnets a packet */ + /* can make before being discarded. This is */ + /* enforced only by routers. */ + IB_GID SGID; /* Source GID-This field identifies the */ + /* Global Identifier (GID) for the port */ + /* which injected the packet into the network. */ + IB_GID DGID; /* Destination GID-This field identifies the GID */ + /* for the port which will consume */ + /* the packet from the network. */ +} PACK_SUFFIX IB_GRH; + +#include "iba/public/ipackoff.h" + +static __inline +void +BSWAP_IB_GID( + IB_GID *IbGid + ) +{ +#if CPU_LE + /* Swap all 128 bits */ + uint64 temp = IbGid->AsReg64s.L; + + IbGid->AsReg64s.L = ntoh64(IbGid->AsReg64s.H); + IbGid->AsReg64s.H = ntoh64(temp); +#endif +} + + + +static __inline +void +BSWAP_IB_GRH( + IB_GRH *Dest + ) +{ +#if CPU_LE + Dest->u1.AsReg32 = ntoh32(Dest->u1.AsReg32); + Dest->PayLen = ntoh16(Dest->PayLen); + + BSWAP_IB_GID(&Dest->SGID); + BSWAP_IB_GID(&Dest->DGID); +#endif +} + +/* MTU of neighbor endnode connected to this port: + * this enum is used for all SM and CM messages + * it is also used in other datatypes as noted below + */ +typedef enum _IB_MTU { + IB_MTU_256 = 1, + IB_MTU_512 = 2, + IB_MTU_1024 = 3, + IB_MTU_2048 = 4, + IB_MTU_4096 = 5, + IB_MTU_MAX = 5 + /* 0, 6 - 15 (or 63 in some packets): reserved */ +} IB_MTU; + + +/* Static rate for link. + * This enum is used in all SM, CM and ADDRESS_VECTOR APIs + */ +typedef enum _IB_STATIC_RATE { + IB_STATIC_RATE_DONTCARE = 0, /* allowed for SA query */ + /* for ADDRESS_VECTOR means local port rate */ + IB_STATIC_RATE_1GB = 1, /* obsolete, now reserved */ + IB_STATIC_RATE_1X = 2, /* depricated, use IB_STATIC_RATE_2_5G */ + IB_STATIC_RATE_2_5G = 2, /* 2.5 Gb/sec (1X SDR) */ + IB_STATIC_RATE_MIN = 2, /* lowest standard rate */ + IB_STATIC_RATE_4X = 3, /* depricated, use IB_STATIC_RATE_10G */ + IB_STATIC_RATE_10G = 3, /* 10.0 Gb/sec (4X SDR, 1X QDR) */ + IB_STATIC_RATE_12X = 4, /* depricated, use IB_STATIC_RATE_30G */ + IB_STATIC_RATE_30G = 4, /* 30.0 Gb/sec (12X SDR) */ + IB_STATIC_RATE_5G = 5, /* 5.0 Gb/sec (1X DDR) */ + IB_STATIC_RATE_20G = 6, /* 20.0 Gb/sec (4X DDR, 8X SDR) */ + IB_STATIC_RATE_40G = 7, /* 40.0 Gb/sec (4X QDR, 8X DDR) */ + IB_STATIC_RATE_60G = 8, /* 60.0 Gb/sec (12X DDR) */ + IB_STATIC_RATE_80G = 9, /* 80.0 Gb/sec (8X QDR) */ + IB_STATIC_RATE_120G = 10, /* 120.0 Gb/sec (12X QDR) */ + IB_STATIC_RATE_LAST_QDR = 10, /* last QDR value, all FDR/EDR must be after this */ + IB_STATIC_RATE_14G = 11, /* 14.0625 Gb/sec (1X FDR) */ + IB_STATIC_RATE_56G = 12, /* 56.25 Gb/sec (4X FDR) */ + IB_STATIC_RATE_112G = 13, /* 112.5 Gb/sec (8X FDR) */ + IB_STATIC_RATE_168G = 14, /* 168.75 Gb/sec (12X FDR) */ + IB_STATIC_RATE_25G = 15, /* 25.78125 Gb/sec (1X EDR) */ + IB_STATIC_RATE_100G = 16, /* 103.125 Gb/sec (4X EDR) */ + IB_STATIC_RATE_200G = 17, /* 206.25 Gb/sec (8X EDR) */ + IB_STATIC_RATE_300G = 18, /* 309.375 Gb/sec (12X EDR) */ + IB_STATIC_RATE_MAX = 18, /* highest standard rate */ + IB_STATIC_RATE_LAST = 18 /* last valid value */ + /* 19-63 reserved */ +} IB_STATIC_RATE; + +/* IB does not define rate for SMI/GSI packets and + * IB does not have Static rate in UD LRH + * so we can't be sure what rate of remote port is for SMI/GSI req/response + * we use a constant value for SMI/GSI QPs, this uses full port speed + * an alternative could be to use 1X speed to be conservative + * (GSI should not be a performance path?) + */ +#define IB_STATIC_RATE_GSI IB_STATIC_RATE_DONTCARE +#define IB_STATIC_RATE_SMI IB_STATIC_RATE_DONTCARE + +/* + * Per Channel Adapter definitions and data types + */ + +typedef enum { + CAAtomicNone, /* No Atomic operations supported. */ + CAAtomicLocal, /* Atomicity guaranteed only between QPs on this CA. */ + CAAtomicGlobal /* Atomicity guaranteed between CA and components that can */ + /* access the target memory. */ + /* of the atomic operation. */ +} IB_CA_ATOMIC_LVL; + +typedef enum { + CAPathMigNone, /* Channel Interface does not support path migration */ + CAPathMigAuto /* Automatic Path Migration supported by CI */ +} IB_CA_PATH_MIGRATION_LVL; + + +/* + * Port Attributes + */ + +/* + * Port LID and LMC values for addressing within the Subnet + */ +typedef struct _IB_PORT_ADDRESS { + IB_LID BaseLID; /* Base LID */ + IB_LMC LMC; /* LMC */ +} IB_PORT_ADDRESS; + +/* + * Info needed to reach the Subnet Manager for a port + */ +typedef struct _IB_PORT_SM_ADDRESS { + IB_LID LID; /* Base LID */ + IB_SL ServiceLevel; +} IB_PORT_SM_ADDRESS; + +/* + * IB Port States (matches values for SMA PortInfo.PortState) + */ +typedef enum _IB_PORT_STATE { + PortStateNop = 0, /* Noop - only for SMA Set */ + PortStateDown = 1, /* Down (includes failed links) */ + PortStateInit = 2, /* Initialize */ + PortStateArmed = 3, /* Armed */ + PortStateActive = 4, /* Active */ + PortStateMax = 4 /* Maximum Valid Value */ +} IB_PORT_STATE; + +/* Port Capabilities (a subset of those in IB_PORT_INFO) */ +typedef enum _IB_PORT_CAPABILITIES { + PORT_IS_SM = 0x00000001U, + PORT_IS_SM_DISABLED = 0x00000002U, + PORT_IS_SNMP_TUNNELING_SUPPORTED = 0x00000004U, + PORT_IS_DEVICE_MGMT_SUPPORTED = 0x00000008U, + PORT_IS_VENDOR_CLASS_SUPPORTED = 0x00000010U +} IB_PORT_CAPABILITIES; + +/* Port initialization type requested from SM */ +typedef enum _IB_PORT_INIT_TYPE { + PORT_INIT_TYPE_NOLOAD = 0x00000001U, + PORT_INIT_TYPE_PRESERVE_CONTENT = 0x00000002U, + PORT_INIT_TYPE_PRESERVE_PRESENCE = 0x00000004U, + PORT_INIT_TYPE_DO_NOT_RESUSCITATE = 0x00000008U +} IB_PORT_INIT_TYPE; + +/* Port Link Width Active */ +typedef enum _IB_PORT_WIDTH { + PORT_WIDTH_1X =0, + PORT_WIDTH_4X =1, + PORT_WIDTH_12X =2, + PORT_WIDTH_8X =3 +} IB_PORT_WIDTH; + +/* Port Link Speed Active */ +typedef enum _IB_PORT_SPEED { + PORT_SPEED_2_5G =0, + PORT_SPEED_5G =1, + PORT_SPEED_10G =2, + PORT_SPEED_14G =3, + PORT_SPEED_25G =4 +} IB_PORT_SPEED; + +/* + * This is the per port attributes structure. + * As there are two variable sized tables, pointers are used to reference into + * the tables as well as the beginning of the next port's attribute structure. + */ +typedef struct _IB_PORT_ATTRIBUTES { + struct _IB_PORT_ATTRIBUTES *Next; /* Pointer to the structure for the */ + /* next port. */ + /* Null if this is last port in list. */ + IB_GID *GIDTable; /* Pointer to the GID table */ + IB_P_KEY *PkeyTable; /* Pointer to the Pkey table */ + EUI64 GUID; /* Port GUID */ + uint32 VirtualLanes; /* Number of data virtual lanes */ + /* supported (from VLCap incl. VL 15) */ + /* 2, 3, 5, 9 or 16 */ + IB_PORT_STATE PortState; + IB_PORT_CAPABILITIES Capabilities; /* optional capabilities */ + IB_PORT_INIT_TYPE InitTypeReply; /* initialization type requested */ + uint32 QkeyViolationCounter; /* Invalid Qkey counter */ + uint16 PkeyViolationCounter; /* Invalid Pkey counter */ + uint8 NumPkeys; /* Number of Pkeys in the Pkey table */ + uint8 NumGIDs; /* Number of GIDs in the GID table */ + IB_PORT_ADDRESS Address; /* Port addressing info */ + uint8 ActiveWidth:2; /* IB_PORT_WIDTH enum */ + uint8 ActiveSpeed:3; /* IB_PORT_SPEED enum */ + uint8 Reserved:3; + IB_PORT_SM_ADDRESS SMAddress; /* SM info for the port */ + + uint8 SubnetTimeout; /* Specifies the maximum expected subnet */ + /* propagation delay, which depends upon the */ + /* configuration of the switches, to reach any */ + /* port in the subnet and shall also be used to */ + /* determine the maximum rate which SubnTraps() */ + /* can be sent from this port. */ + /* The duration of time is calculated based on */ + /* (4.096 uS * 2^SubnetTimeOut) */ + + uint8 RespTimeValue; /* Specifies the expected maximum time between */ + /* the port reception of a SMP and the */ + /* transmission of the associated response. */ + /* The duration of time is calculated based on */ + /* (4.096 uS * 2^RespTimeValue). */ + /* The default value shall be 8. */ + uint32 NeighborMTU; /* Maximum Transfer Unit (packet size) */ + /* which has been configured between this */ + /* port and the neighbor port */ + /* represented in bytes (256, 512, ... 4096) */ + uint32 MaxMTU; /* Maximum Transfer Unit supported */ + /* (packet size) from MTUCap */ + /* represented in bytes (256, 512, ... 4096) */ + uint64 MaxMessageLen; /* Maximum message length */ + /* add new fields here to ensure binary compatibility with existing code */ + + /* */ + /* The GID and Pkey tables are located here at the end of the port */ + /* attributes structure. The caller must allocate the space to hold the */ + /* tables at the end of this structure. The size indicated in */ + /* PortAttributesListSize will be used to determine the number of port */ + /* attributes structures that may be returned. */ + /* */ +} IB_PORT_ATTRIBUTES; + +/* Page size is 2K * 2^bit_position */ +#define IB_MR_PAGESIZE_MIN_LOG2 11 +#define IB_MR_PAGESIZE_MIN 2048 +#define IB_MR_PAGESIZE_2K 0x000000001U +#define IB_MR_PAGESIZE_4K 0x000000002U +#define IB_MR_PAGESIZE_8K 0x000000004U +#define IB_MR_PAGESIZE_16K 0x000000008U +#define IB_MR_PAGESIZE_32K 0x000000010U +#define IB_MR_PAGESIZE_64K 0x000000020U +#define IB_MR_PAGESIZE_128K 0x000000040U +#define IB_MR_PAGESIZE_256K 0x000000080U +#define IB_MR_PAGESIZE_512K 0x000000100U +#define IB_MR_PAGESIZE_1M 0x000000200U +#define IB_MR_PAGESIZE_2M 0x000000400U +#define IB_MR_PAGESIZE_4M 0x000000800U +#define IB_MR_PAGESIZE_8M 0x000001000U +#define IB_MR_PAGESIZE_16M 0x000002000U +#define IB_MR_PAGESIZE_32M 0x000004000U +#define IB_MR_PAGESIZE_64M 0x000008000U +#define IB_MR_PAGESIZE_128M 0x000010000U +#define IB_MR_PAGESIZE_256M 0x000020000U +#define IB_MR_PAGESIZE_512M 0x000040000U +#define IB_MR_PAGESIZE_1G 0x000080000U +#define IB_MR_PAGESIZE_2G 0x000100000U +#define IB_MR_PAGESIZE_4G 0x000200000U +#define IB_MR_PAGESIZE_8G 0x000400000U +#define IB_MR_PAGESIZE_16G 0x000800000U +#define IB_MR_PAGESIZE_32G 0x001000000U +#define IB_MR_PAGESIZE_64G 0x002000000U +#define IB_MR_PAGESIZE_128G 0x004000000U +#define IB_MR_PAGESIZE_256G 0x008000000U +#define IB_MR_PAGESIZE_512G 0x010000000U +#define IB_MR_PAGESIZE_1T 0x020000000U +#define IB_MR_PAGESIZE_2T 0x040000000U +#define IB_MR_PAGESIZE_4T 0x080000000U + +typedef uint32 IB_MR_PAGESIZES; + +typedef enum _IB_CA_CAPABILITIES { + CA_IS_SYSTEM_IMAGE_GUID_SUPPORTED = 0x00000001U, + CA_IS_INIT_TYPE_SUPPORTED = 0x00000002U, /* TBD ReInit? */ + CA_IS_PORT_ACTIVE_EVENT_SUPPORTED = 0x00000004U, + CA_IS_RNR_NAK_SUPPORTED = 0x00000008U, + CA_IS_AV_PORT_CHECK_SUPPORTED = 0x00000010U, + CA_IS_RC_PORT_CHANGE_SUPPORTED = 0x00000020U, + CA_IS_QP_MODIFY_NO_TRANSITION_SUPPORTED = 0x00000040U, + CA_IS_PKEY_VIOLATION_COUNTER_SUPPORTED = 0x00000080U, + CA_IS_QKEY_VIOLATION_COUNTER_SUPPORTED = 0x00000100U, + CA_IS_MODIFY_QDEPTH_SUPPORTED = 0x00000200U, + CA_IS_RAW_MULTICAST_SUPPORTED = 0x00000400U, + CA_IS_PORT_SHUTDOWN_SUPPORTED = 0x00000800U, + CA_IS_ENHANCED_SWITCH_PORT0 = 0x00001000U, + CA_IS_UNSIGNALED_RECV_SUPPORTED = 0x00002000U, + /* AV not used by hardware after iba_post_send */ + CA_IS_AV_SOFT = 0x00004000U +} IB_CA_CAPABILITIES; + +/* + * Channel Adapter Attributes + */ +typedef struct _IB_CA_ATTRIBUTES { + EUI64 GUID; + EUI64 SystemImageGuid; + uint32 VendorId; + uint16 DeviceId; + uint16 DeviceRevision; + uint32 QueuePairs; /* Number of QPs */ + uint32 WorkReqs; /* Max outstanding WRs permitted on any WQ */ + uint32 DSListDepth; /* Max depth of scatter/gather list on a WR */ + uint32 RDDSListDepth; /* Max depth of scatter list on an RD RQ WR */ + uint32 CompletionQueues; /* Number of CQs */ + uint32 WorkCompletions; /* Max number of WC/CQE per CQ */ + uint32 MemoryRegions; /* Max number of Memory Regions */ + uint8 NodeType; + uint8 Reserved10; + uint16 Reserved11; + uint64 MemRegionSize; /* Max size of a Memory Region */ + uint32 MemoryWindows; /* Max number of Memory Windows */ + uint32 ProtectionDomains; /* Number of Protection Domains */ + uint32 RDDomains; /* Number of Reliable Datagram Domains */ + IB_MR_PAGESIZES MemRegionPageSizes; /* The page sizes supported by the CA */ + /* memory management subsystem. */ + uint32 Ports; /* Number of ports */ + uint32 Partitions; /* Maximum number of partitions */ + uint32 MaxMTU; /* smallest of MaxMtu values for */ + /* all ports on CA */ + /* represented in bytes (256, 512, ... 4096) */ + uint64 MaxMessageLen; /* smallest of MaxMessageLen for all */ + /* ports on CA */ + IB_CA_CAPABILITIES Capabilities; /* optional capabilities */ + IB_CA_ATOMIC_LVL AtomicityLevel; /* Support level for atomic operations */ + uint8 LocalCaAckDelay; /* time for local CA to respond to */ + /* an inbound transport layer ACK or NAK */ + /* in 4.096*2^n usec units */ + uint8 MaxQPInitiatorDepth; /* Maximum number of RDMA reads */ + /* & Atomic Ops which can be outstanding */ + /* per QP as a requestor/initiator */ + uint8 MaxEECInitiatorDepth; /* Maximum number of RDMA reads */ + /* & Atomic Ops which can be outstanding */ + /* per EEC as a requestor/initiator */ + uint8 MaxQPResponderResources; /* Maximum number of RDMA reads */ + /* & Atomic Ops which can be outstanding */ + /* per QP as a responder */ + uint8 MaxEECResponderResources; /* Maximum number of RDMA reads */ + /* & Atomic Ops which can be outstanding */ + /* per EEC as a responder */ + uint8 Reserved1; + uint16 MaxRearmNumWC; /* Maximum value for NumWC argument */ + /* in iba_rearm_n_cq. If this value is 1 */ + /* then the CA does not support coallesing */ + /* completions and iba_rearm_n_cq is */ + /* functionally the same as */ + /* iba_rearm_cq(...,CQEventSelNextWC) */ + uint32 MaxCAResponderResources; /* Maximum number of RDMA reads */ + /* & Atomic Ops which can be outstanding */ + /* per CA as a responder */ + uint32 EEContexts; /* Max number of EE contexts */ + uint32 IPv6QPs; /* Max number of Raw IPv6 Datagram QPs */ + uint32 EthertypeQPs; /* Max number of Raw Ethertype Datagram QPs */ + uint32 MCastGroups; /* Max number of multicast groups */ + uint32 MCastQPs; /* Max number of QPs which may be attached */ + /* to multicast groups. */ + uint32 MCastGroupQPs; /* Max number of QPs per multicast group */ + uint32 AddressVectors; /* Max number of AVs which may be created */ + IB_CA_PATH_MIGRATION_LVL PathMigrationLevel; /* Support level for */ + /* failover/migration mechanisms. */ + /* The PortAttributesList may be null. If not null the size in bytes of */ + /* the buffer pointed to by PortAttributesList must be given in */ + /* PortAttributeListSize. If PortAttributesList is null, the size in bytes */ + /* of the area needed to hold the attributes information for all ports is */ + /* returned. */ + uint32 PortAttributesListSize; + IB_PORT_ATTRIBUTES *PortAttributesList; +} IB_CA_ATTRIBUTES; + +/* + * Update of IB_CA_ATTRIBUTES. NOTE: The structure is identical to + * IB_CA_ATTRIBUTES, but adds new fields to the end. + */ +typedef struct _IB_CA_ATTRIBUTES2 { + EUI64 GUID; + EUI64 SystemImageGuid; + uint32 VendorId; + uint16 DeviceId; + uint16 DeviceRevision; + uint32 QueuePairs; /* Number of QPs */ + uint32 WorkReqs; /* Max outstanding WRs permitted on any WQ */ + uint32 DSListDepth; /* Max depth of scatter/gather list on a WR */ + uint32 RDDSListDepth; /* Max depth of scatter list on an RD RQ WR */ + uint32 CompletionQueues; /* Number of CQs */ + uint32 WorkCompletions; /* Max number of WC/CQE per CQ */ + uint32 MemoryRegions; /* Max number of Memory Regions */ + uint8 NodeType; + uint8 Reserved10; + uint16 Reserved11; + uint64 MemRegionSize; /* Max size of a Memory Region */ + uint32 MemoryWindows; /* Max number of Memory Windows */ + uint32 ProtectionDomains; /* Number of Protection Domains */ + uint32 RDDomains; /* Number of Reliable Datagram Domains */ + IB_MR_PAGESIZES MemRegionPageSizes; /* The page sizes supported by the CA */ + /* memory management subsystem. */ + uint32 Ports; /* Number of ports */ + uint32 Partitions; /* Maximum number of partitions */ + uint32 MaxMTU; /* smallest of MaxMtu values for */ + /* all ports on CA */ + /* represented in bytes (256, 512, ... 4096) */ + uint64 MaxMessageLen; /* smallest of MaxMessageLen for all */ + /* ports on CA */ + IB_CA_CAPABILITIES Capabilities; /* optional capabilities */ + IB_CA_ATOMIC_LVL AtomicityLevel; /* Support level for atomic operations */ + uint8 LocalCaAckDelay; /* time for local CA to respond to */ + /* an inbound transport layer ACK or NAK */ + /* in 4.096*2^n usec units */ + uint8 MaxQPInitiatorDepth; /* Maximum number of RDMA reads */ + /* & Atomic Ops which can be outstanding */ + /* per QP as a requestor/initiator */ + uint8 MaxEECInitiatorDepth; /* Maximum number of RDMA reads */ + /* & Atomic Ops which can be outstanding */ + /* per EEC as a requestor/initiator */ + uint8 MaxQPResponderResources; /* Maximum number of RDMA reads */ + /* & Atomic Ops which can be outstanding */ + /* per QP as a responder */ + uint8 MaxEECResponderResources; /* Maximum number of RDMA reads */ + /* & Atomic Ops which can be outstanding */ + /* per EEC as a responder */ + uint8 Reserved1; + uint16 MaxRearmNumWC; /* Maximum value for NumWC argument */ + /* in iba_rearm_n_cq. If this value is 1 */ + /* then the CA does not support coallesing */ + /* completions and iba_rearm_n_cq is */ + /* functionally the same as */ + /* iba_rearm_cq(...,CQEventSelNextWC) */ + uint32 MaxCAResponderResources; /* Maximum number of RDMA reads */ + /* & Atomic Ops which can be outstanding */ + /* per CA as a responder */ + uint32 EEContexts; /* Max number of EE contexts */ + uint32 IPv6QPs; /* Max number of Raw IPv6 Datagram QPs */ + uint32 EthertypeQPs; /* Max number of Raw Ethertype Datagram QPs */ + uint32 MCastGroups; /* Max number of multicast groups */ + uint32 MCastQPs; /* Max number of QPs which may be attached */ + /* to multicast groups. */ + uint32 MCastGroupQPs; /* Max number of QPs per multicast group */ + uint32 AddressVectors; /* Max number of AVs which may be created */ + IB_CA_PATH_MIGRATION_LVL PathMigrationLevel; /* Support level for */ + /* failover/migration mechanisms. */ + /* The PortAttributesList may be null. If not null the size in bytes of */ + /* the buffer pointed to by PortAttributesList must be given in */ + /* PortAttributeListSize. If PortAttributesList is null, the size in bytes */ + /* of the area needed to hold the attributes information for all ports is */ + /* returned. */ + uint32 PortAttributesListSize; + IB_PORT_ATTRIBUTES *PortAttributesList; + + /* The PciDevice is provided to aid DMA mapping by kernel mode ULPs + * Use of this pointer must be done with care. The pointer cannot + * be used after the CA has been closed. NULL is returned for user space. + */ +#if defined(VXWORKS) + struct _PCI_DEVICE* PciDevice; +#else + void* PciDevice; +#endif + + /* Extra attributes: reserved for future expansion. */ + uint64 Reserved2; + uint64 Reserved3; + uint64 Reserved4; + uint64 Reserved5; + uint64 Reserved6; + uint64 Reserved7; + uint64 Reserved8; + uint64 Reserved9; +} IB_CA_ATTRIBUTES2; + +/* version of IbAccess stack itself, used to verify UVCA matches kernel stack + * version + */ +typedef enum { + IBT_VERSION_NONE = 0, + IBT_VERSION_LATEST = 5 +} IBT_VERSION; + +#ifdef __cplusplus +}; +#endif + +#endif /* _IBA_IB_TYPES_H_ */ diff --git a/IbAccess/Common/Inc/ibt.h b/IbAccess/Common/Inc/ibt.h new file mode 100644 index 0000000..eb79a1e --- /dev/null +++ b/IbAccess/Common/Inc/ibt.h @@ -0,0 +1,73 @@ +/* BEGIN_ICS_COPYRIGHT1 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT1 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +/* Suppress duplicate loading of this file */ +#ifndef _IBA_IBT_INTF_H_ +#define _IBA_IBT_INTF_H_ + +/* This is the primary include file for kernel mode access to + * the IbAccess APIs. It in turn includes all the files required to + * define the datatypes and interface functions which are exported. + */ + +#if defined(VXWORKS) +#include "iba/vpi_export.h" +#include "iba/public/statustext.h" +#include "iba/ib_ibt.h" +#include "iba/ib_gsi.h" +#include "iba/ib_smi.h" +#ifdef BUILD_CM +#include "iba/ib_cm.h" +#endif +#include "iba/stl_sd.h" +#include "iba/stl_pa_priv.h" +#include "iba/ib_avtracker.h" +#include "iba/umadt.h" +#ifdef BUILD_DMC +#include "iba/ib_dma.h" +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef BUILD_DMC +extern FSTATUS TtsInitialize(EUI64 SystemImageGUID, IOU_CALLBACK IouCallback, void* Context); +#else +extern FSTATUS TtsInitialize(EUI64 SystemImageGUID); +#endif + +#ifdef __cplusplus +}; +#endif + +#endif /* defined(VXWORKS) */ +#endif /* _IBA_IBT_INTF_H_ */ diff --git a/IbAccess/Common/Inc/ipublic.h b/IbAccess/Common/Inc/ipublic.h new file mode 100644 index 0000000..230b100 --- /dev/null +++ b/IbAccess/Common/Inc/ipublic.h @@ -0,0 +1,93 @@ +/* BEGIN_ICS_COPYRIGHT3 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT3 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +/* Main header for OS Abstraction layer */ + +#ifndef _IBA_IPUBLIC_H_ +#define _IBA_IPUBLIC_H_ + +#include "iba/public/datatypes.h" +#include "iba/public/ibyteswap.h" +#ifndef OPEN_SOURCE_12200 +#include "iba/public/iarray.h" +#include "iba/public/ibitvector.h" +#include "iba/public/icmdthread.h" +#include "iba/public/idebug.h" +#include "iba/public/ievent.h" +#include "iba/public/ieventthread.h" +#include "iba/public/iheapmanager.h" +#include "iba/public/imutex.h" +#include "iba/public/iobjmgr.h" +#include "iba/public/isemaphore.h" +#include "iba/public/ithread.h" +#endif +#ifndef IB_STACK_OPENIB +#include "iba/public/igrowpool.h" +#endif +#include "iba/public/ilist.h" +#ifndef IB_STACK_OPENIB +#include "iba/public/ihandletrans.h" +#endif +#if defined(VXWORKS) +#include "iba/public/iintrservicethread.h" +#endif +#ifndef IB_STACK_OPENIB +#include "iba/public/imap.h" +#endif +#include "iba/public/imath.h" +#include "iba/public/imemory.h" +#include "iba/public/imemtrack.h" +#ifndef IB_STACK_OPENIB +#include "iba/public/ipci.h" +#endif +#include "iba/public/iquickmap.h" +#if defined(VXWORKS) +#include "iba/public/ireaper.h" +#endif +#ifndef IB_STACK_OPENIB +#include "iba/public/ireqmgr.h" +#include "iba/public/iresmap.h" +#include "iba/public/iresmgr.h" +#endif +#include "iba/public/ispinlock.h" +#ifndef IB_STACK_OPENIB +#include "iba/public/isyscallback.h" +#endif +#if defined(VXWORKS) +#include "iba/public/isysutil.h" +#endif +#ifndef IB_STACK_OPENIB +#include "iba/public/ithreadpool.h" +#endif +#include "iba/public/itimer.h" +#include "iba/public/statustext.h" + +#endif /* _IBA_IPUBLIC_H_ */ diff --git a/IbAccess/Common/Inc/sd_params.h b/IbAccess/Common/Inc/sd_params.h new file mode 100644 index 0000000..07debac --- /dev/null +++ b/IbAccess/Common/Inc/sd_params.h @@ -0,0 +1,103 @@ +/* BEGIN_ICS_COPYRIGHT4 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT4 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +/* Suppress duplicate loading of this file */ +#ifndef _INSI_IB_SD_PARAMS_H_ +#define _INSI_IB_SD_PARAMS_H_ + + +#if defined (__cplusplus) +extern "C" { +#endif + +#include "datatypes.h" + + /* default client control options */ +#define SD_DEFAULT_RETRY_INTERVAL 10000 /* ms */ +#define SD_DEFAULT_RETRY_COUNT 3 +#if defined(DBG) ||defined( IB_DEBUG) +#define SD_DEFAULT_DEBUG_FLAGS 0xffffffff +#else +#define SD_DEFAULT_DEBUG_FLAGS 0 +#endif +#define SD_DEFAULT_OPTION_FLAGS 0 + + /* interval for checking queued queries and retries/timeouts in ms */ +#define SD_DEFAULT_TIME_INTERVAL 500 /*1000 */ + +/* max child queries in main queue, helps to prevent child queries from + * overrunning primary queries + */ +#define SD_DEFAULT_MAX_SUB_QUERY_QUEUED 10 + +#define SD_DEFAULT_MAX_SA_OUTSTANDING 1 + +#define SD_DEFAULT_SA_BUSY_BACKOFF 10000 /* ms */ +#define SD_DEFAULT_VALIDATE_NODE_RECORD 1 +#define SD_DEFAULT_DUMP_INVALID_NODE_RECORD 0 +#define SD_DEFAULT_MIN_PKTLIFETIME 60 /* ms */ + +typedef struct _SD_CONFIG_PARAMS { + /* parameters for queries where ClientControlParameters omitted */ + uint32 DefaultRetryCount; + uint32 DefaultRetryInterval; + uint32 DefaultDebugFlags; + uint32 DefaultOptionFlags; + + uint32 TimeInterval; /* retry/timeout check rate in ms */ + uint32 SaBusyBackoff; /* backoff before retries when Busy reported */ + uint32 ValidateNodeRecord; /* Validation of GUIDs in Node Record */ + uint32 DumpInvalidNodeRecord; /* Full dump of any Invalid Node Records */ + uint32 MinPktLifeTime; /* Minimum PathRecord.PktLifeTime to report, in ms */ + /* maximum outstanding queries/operations */ + uint32 MaxChildQuery; + uint32 MaxOutstanding; +} SD_CONFIG_PARAMS; + +#define SD_DEFAULT_CONFIG_PARAMS { \ + SD_DEFAULT_RETRY_INTERVAL, SD_DEFAULT_RETRY_COUNT, SD_DEFAULT_DEBUG_FLAGS, \ + SD_DEFAULT_OPTION_FLAGS, \ + SD_DEFAULT_TIME_INTERVAL, \ + SD_DEFAULT_SA_BUSY_BACKOFF, \ + SD_DEFAULT_VALIDATE_NODE_RECORD, \ + SD_DEFAULT_DUMP_INVALID_NODE_RECORD, \ + SD_DEFAULT_MIN_PKTLIFETIME, \ + SD_DEFAULT_MAX_SUB_QUERY_QUEUED, \ + SD_DEFAULT_MAX_SA_OUTSTANDING \ + } + +extern SD_CONFIG_PARAMS g_SdParams; + +#if defined (__cplusplus) +}; +#endif + +#endif /* _INSI_IB_SD_PARAMS_H_ */ diff --git a/IbAccess/Common/Inc/stl_ea_eostl.h b/IbAccess/Common/Inc/stl_ea_eostl.h new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/IbAccess/Common/Inc/stl_ea_eostl.h diff --git a/IbAccess/Common/Inc/stl_eepha_eostl.h b/IbAccess/Common/Inc/stl_eepha_eostl.h new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/IbAccess/Common/Inc/stl_eepha_eostl.h diff --git a/IbAccess/Common/Inc/stl_em_eostl.h b/IbAccess/Common/Inc/stl_em_eostl.h new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/IbAccess/Common/Inc/stl_em_eostl.h diff --git a/IbAccess/Common/Inc/stl_helper.h b/IbAccess/Common/Inc/stl_helper.h new file mode 100644 index 0000000..04309e9 --- /dev/null +++ b/IbAccess/Common/Inc/stl_helper.h @@ -0,0 +1,1845 @@ +/* BEGIN_ICS_COPYRIGHT7 **************************************** + +Copyright (c) 2015-2018, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT7 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +#ifndef _IBA_STL_HELPER_H_ +#define _IBA_STL_HELPER_H_ + +#include +#include +#include "ib_helper.h" +#include "iba/stl_sm_types.h" +#include "iba/stl_pa_types.h" + +#if defined(VXWORKS) +#include "private/stdioP.h" // pick up snprintf extern definition +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#define BYTES_PER_FLIT 8 + +/* + * STL defines an algorithmic relationship between NodeGUID and PortGUID + * Bit 30-31 of the NodeGUID always has 0 + * Bit 30-31 of the PortGUID has 0 for switch port 0, or the HFI port number - 1 + * These functions help translate from one to the other + */ +#define PORTGUID_PNUM_SHIFT 30 // low bit number +#define PORTGUID_PNUM_MASK (0x3ull << PORTGUID_PNUM_SHIFT) // bit field mask + +static __inline EUI64 PortGUIDtoNodeGUID(EUI64 portGUID) +{ + return portGUID & ~PORTGUID_PNUM_MASK; +} + +static __inline EUI64 NodeGUIDtoPortGUID(EUI64 nodeGUID, uint8 portnum) +{ + // assume portnum is valid, in which case it must be zero for switches + // or 1-4 (which we must convert to 0 relative) for HFIs + // hence avoiding the need for a NodeType argument to this function + if (portnum) portnum--; + + return (nodeGUID & ~PORTGUID_PNUM_MASK) + | (((EUI64)portnum << PORTGUID_PNUM_SHIFT) & PORTGUID_PNUM_MASK); +} + +/* + * Convert STL_PORT_STATE to a constant string + */ +static __inline const char * +StlPortStateToText(uint8_t state) +{ + return IbPortStateToText((IB_PORT_STATE)state); +} + +/* + * Convert STL_PORT_PHYS_STATE to a constant string + */ +static __inline const char* +StlPortPhysStateToText( uint8_t state ) +{ + switch (state) + { + case STL_PORT_PHYS_OFFLINE: + return "Offline"; + case STL_PORT_PHYS_TEST: + return "Test"; + } + return IbPortPhysStateToText((IB_PORT_PHYS_STATE)state); +} + + + +static __inline int IsPortInitialized(STL_PORT_STATES portStates) +{ + return (portStates.s.PortState == IB_PORT_ARMED + || portStates.s.PortState == IB_PORT_ACTIVE); +} + +static __inline uint32 StlMbpsToStaticRate(uint32 rate_mbps) +{ + /* 1Gb rate is obsolete */ + if (rate_mbps <= 2500) + return IB_STATIC_RATE_2_5G; + else if (rate_mbps <= 5000) + return IB_STATIC_RATE_5G; + else if (rate_mbps <= 10000) + return IB_STATIC_RATE_10G; + else if (rate_mbps <= 12500) + return IB_STATIC_RATE_14G; // STL_STATIC_RATE_12_5G; + else if (rate_mbps <= 14062) + return IB_STATIC_RATE_14G; + else if (rate_mbps <= 20000) + return IB_STATIC_RATE_20G; + else if (rate_mbps <= 25781) + return IB_STATIC_RATE_25G; + else if (rate_mbps <= 30000) + return IB_STATIC_RATE_30G; + else if (rate_mbps <= 37500) + return IB_STATIC_RATE_40G; // STL_STATIC_RATE_37_5G; + else if (rate_mbps <= 40000) + return IB_STATIC_RATE_40G; + else if (rate_mbps <= 50000) + return IB_STATIC_RATE_56G; // STL_STATIC_RATE_50G; + else if (rate_mbps <= 56250) + return IB_STATIC_RATE_56G; + else if (rate_mbps <= 60000) + return IB_STATIC_RATE_60G; + else if (rate_mbps <= 75000) + return IB_STATIC_RATE_80G; // STL_STATIC_RATE_75G; + else if (rate_mbps <= 80000) + return IB_STATIC_RATE_80G; + else if (rate_mbps <= 103125) + return IB_STATIC_RATE_100G; + else + return IB_STATIC_RATE_100G; +#if 0 + // future + else if (rate_mbps <= 225000) + return STL_STATIC_RATE_225G; + else if (rate_mbps <= 300000) + return IB_STATIC_RATE_300G; + else + return STL_STATIC_RATE_400G; +#endif +} + +/* Convert static rate to text */ +static __inline const char* +StlStaticRateToText(uint32 rate) +{ + switch (rate) + { + case IB_STATIC_RATE_DONTCARE: + return "any"; + case IB_STATIC_RATE_1GB: + return "1g"; + case IB_STATIC_RATE_2_5G: + return "2.5g"; + case IB_STATIC_RATE_10G: + return "10g"; + case IB_STATIC_RATE_30G: + return "30g"; + case IB_STATIC_RATE_5G: + return "5g"; + case IB_STATIC_RATE_20G: + return "20g"; + case IB_STATIC_RATE_40G: + return "37.5g"; // STL_STATIC_RATE_37_5G; + case IB_STATIC_RATE_60G: + return "60g"; + case IB_STATIC_RATE_80G: + return "75g"; // STL_STATIC_RATE_75G; + case IB_STATIC_RATE_120G: + return "120g"; + case IB_STATIC_RATE_14G: + return "12.5g"; // STL_STATIC_RATE_12_5G; + case IB_STATIC_RATE_25G: + return "25g"; // 25.78125g + case IB_STATIC_RATE_56G: + return "50g"; // STL_STATIC_RATE_50G; + case IB_STATIC_RATE_100G: + return "100g"; // 103.125g + case IB_STATIC_RATE_112G: + return "112g"; + case IB_STATIC_RATE_200G: + return "200g"; // 206.25g + case IB_STATIC_RATE_168G: + return "168g"; // 168.75g + case IB_STATIC_RATE_300G: + return "300g"; // 309.375g + default: + return "???"; + } +} + +static __inline uint32 StlLinkSpeedToMbps(uint32 speed) +{ + switch(speed) { + default: + case STL_LINK_SPEED_12_5G: return 12500; + case STL_LINK_SPEED_25G: return 25781; + } +} + +static __inline uint32 StlLinkWidthToInt(uint32 width) +{ + switch(width) { + default: + case STL_LINK_WIDTH_1X: return 1; + case STL_LINK_WIDTH_2X: return 2; + case STL_LINK_WIDTH_3X: return 3; + case STL_LINK_WIDTH_4X: return 4; + } +} + +static __inline uint32 StlStaticRateToMbps(IB_STATIC_RATE rate) +{ + switch(rate) { + case IB_STATIC_RATE_14G: // STL_STATIC_RATE_12_5G + return 12890; // half of 25781 (25G) + default: + case IB_STATIC_RATE_25G: + return 25781; + case IB_STATIC_RATE_40G: // STL_STATIC_RATE_37_5G + return 37500; + case IB_STATIC_RATE_56G: // STL_STATIC_RATE_50G + return 51562; + case IB_STATIC_RATE_80G: // STL_STATIC_RATE_75G + return 77343; + case IB_STATIC_RATE_100G: + return 103125; + case IB_STATIC_RATE_200G: + return 206250; + case IB_STATIC_RATE_300G: + return 309375; + } +} +/* convert data Mbps to wire MBps for stl + * speeds use 64b66b wire encoding mbps wire Megabit/s * 1Byte/8bits * 64 data bits / 66 wire bits = X data MegaByte/s + */ +#define StlmbpsToMBpsExt(mbps) { \ + ((uint32)((uint64)mbps * 8LL / 66LL)); \ +} + +/* convert static rate to MByte/sec units, M=10^6 */ +static __inline uint32 +StlStaticRateToMBps(IB_STATIC_RATE rate) +{ + return (StlmbpsToMBpsExt(StlStaticRateToMbps(rate))); +} + +/* return the best link speed between two ports. */ +static __inline uint32 +StlExpectedLinkSpeed(uint32 a, uint32 b) +{ + if ((STL_LINK_SPEED_25G & a) && (STL_LINK_SPEED_25G & b)) + return STL_LINK_SPEED_25G; + else if ((IB_LINK_SPEED_25G & a) && (IB_LINK_SPEED_25G & b)) + return IB_LINK_SPEED_25G; + else if ((IB_LINK_SPEED_14G & a) && (IB_LINK_SPEED_14G & b)) + return IB_LINK_SPEED_14G; + else if ((STL_LINK_SPEED_12_5G & a) && (STL_LINK_SPEED_12_5G & b)) + return STL_LINK_SPEED_12_5G; + else if ((IB_LINK_SPEED_10G & a) && (IB_LINK_SPEED_10G & b)) + return IB_LINK_SPEED_10G; + else if ((IB_LINK_SPEED_5G & a) && (IB_LINK_SPEED_5G & b)) + return IB_LINK_SPEED_5G; + else if ((IB_LINK_SPEED_2_5G & a) && (IB_LINK_SPEED_2_5G & b)) + return IB_LINK_SPEED_2_5G; + else + return 0; /* no speed? */ +} + +/* return the best link speed set in the bit mask */ +static __inline uint32 +StlBestLinkSpeed(uint32 speed) +{ + if (STL_LINK_SPEED_25G & speed) + return STL_LINK_SPEED_25G; + else if (IB_LINK_SPEED_25G & speed) + return IB_LINK_SPEED_25G; + else if (IB_LINK_SPEED_14G & speed) + return IB_LINK_SPEED_14G; + else if (STL_LINK_SPEED_12_5G & speed) + return STL_LINK_SPEED_12_5G; + else if (IB_LINK_SPEED_10G & speed) + return IB_LINK_SPEED_10G; + else if (IB_LINK_SPEED_5G & speed) + return IB_LINK_SPEED_5G; + else if (IB_LINK_SPEED_2_5G & speed) + return IB_LINK_SPEED_2_5G; + else + return 0; /* no speed? */ +} + +/* + * Return the best possible link width supported by or enabled in a port. + */ +static __inline uint32 +StlBestLinkWidth(uint32 a) +{ + if (STL_LINK_WIDTH_4X & a) + return STL_LINK_WIDTH_4X; + else if (STL_LINK_WIDTH_3X & a) + return STL_LINK_WIDTH_3X; + else if (STL_LINK_WIDTH_2X & a) + return STL_LINK_WIDTH_2X; + else if (STL_LINK_WIDTH_1X & a) + return STL_LINK_WIDTH_1X; + else + return 0; +} + +/* compare 2 link widths and report expected operational width + * can be used to compare Enabled or Supported values in connected ports + */ +static __inline uint16 +StlExpectedLinkWidth(uint32 a, uint32 b) +{ + if ((STL_LINK_WIDTH_4X & a) && (STL_LINK_WIDTH_4X & b)) + return STL_LINK_WIDTH_4X; + else if ((STL_LINK_WIDTH_3X & a) && (STL_LINK_WIDTH_3X & b)) + return STL_LINK_WIDTH_3X; + else if ((STL_LINK_WIDTH_2X & a) && (STL_LINK_WIDTH_2X & b)) + return STL_LINK_WIDTH_2X; + else if ((STL_LINK_WIDTH_1X & a) && (STL_LINK_WIDTH_1X & b)) + return STL_LINK_WIDTH_1X; + else + return STL_LINK_WIDTH_NOP; /* link should come up */ +} + +static __inline uint32 StlLinkSpeedWidthToMbps(uint32 speed, uint32 width) +{ + return StlLinkSpeedToMbps(speed) * StlLinkWidthToInt(width); +} + +static __inline uint32 StlLinkSpeedWidthToStaticRate(uint32 speed, uint32 width) +{ + return StlMbpsToStaticRate(StlLinkSpeedWidthToMbps(speed, width)); +} + +/** + * This is a kind of nasty macro which "exits" to the label "out" if the + * snprintf did not have enough room. It keeps the Print Functions below + * concise. But does have side effects of changing "n" and possibly vectoring + * out of the enclosing block. + */ +#define PRINT_OR_OUT(str, len, val) { \ + i = snprintf(str+n, len-n, val); \ + if (i >= len-n) { \ + DEBUG_ASSERT(0 == "IbPrint: ERROR buffer length short\n"); \ + goto out; \ + } \ + n+=i; \ + } + +/* convert link width to text */ +static __inline char* +StlLinkWidthToText(uint16_t w, char *buf, size_t len) +{ + int i, j, l; + +#define STL_WIDTH_TEXT_LENGTH 16 + + static const char *StlWidthText[STL_WIDTH_TEXT_LENGTH] = { + "1", "2", "3", "4", "?", "?", "?", "?", + "?", "?", "?", "?", "?", "?", "?", "?", + }; + + if (w == STL_LINK_WIDTH_NOP) { + snprintf(buf,len-1,"None"); + buf[len-1]=0; + } else { + l=len-4; // the max we can tack on in 1 pass is 3 bytes. + + // Loop terminates as soon as the width is zero. + for (i=0, j=0; w!=0 && i>=1) { + if (w & 1) { + if (j>0) buf[j++]=','; + j+=snprintf(buf+j,len-j,"%s", StlWidthText[i]); + } + } + } + return buf; +} + +// writes a text value for the provided link speed, or an error +// if the specified speed is unknown. +// +// NOTA BENE: This function will assert if the buffer is too short. The buffer +// should be at least 16 bytes long to hold the error message. +static __inline const char* +StlLinkSpeedToText(uint16_t speed, char *str, size_t len) +{ + size_t n = 0; + size_t i = 0; + + if (speed == STL_LINK_SPEED_NOP) { + PRINT_OR_OUT(str, len, "None"); + goto out; + } + + str[0] = '\0'; + + if (speed & STL_LINK_SPEED_12_5G) { + PRINT_OR_OUT(str, len, "12.5Gb,"); + speed = speed ^ STL_LINK_SPEED_12_5G; + } + if (speed & STL_LINK_SPEED_25G) { + PRINT_OR_OUT(str, len, "25Gb,"); + speed = speed ^ STL_LINK_SPEED_25G; + } + if (speed) { + i = snprintf(str+n, len-n, "Unk(0x%04X),", speed); + if (i >= len-n) { + DEBUG_ASSERT(0 == "IbPrint: ERROR buffer length short\n"); + goto out; + } + n+=i; + } + str[n-1] = 0; // Eliminate trailing comma +out: + return (str); +} + + +static __inline const char* +StlPortLinkModeToText(uint16_t mode, char *str, size_t len) +{ + size_t n = 0; + size_t i = 0; + + if (mode == STL_PORT_LINK_MODE_NOP) { + PRINT_OR_OUT(str, len, "Noop"); + goto out; + } + + str[0]='\0'; + + if (mode & STL_PORT_LINK_MODE_STL) + PRINT_OR_OUT(str, len, "STL,"); + str[n-1] = 0; // Eliminate trailing comma + +out: + return str; +} + +static __inline const char* +StlPortLtpCrcModeToText(uint16_t mode, char *str, size_t len) +{ + size_t n = 0; + size_t i = 0; + + if (mode == STL_PORT_LTP_CRC_MODE_NONE) { + PRINT_OR_OUT(str, len, "None"); + goto out; + } + + str[0]='\0'; + + if (mode & STL_PORT_LTP_CRC_MODE_14) + PRINT_OR_OUT(str, len, "14-bit,"); + if (mode & STL_PORT_LTP_CRC_MODE_16) + PRINT_OR_OUT(str, len, "16-bit,"); + if (mode & STL_PORT_LTP_CRC_MODE_48) + PRINT_OR_OUT(str, len, "48-bit,"); + if (mode & STL_PORT_LTP_CRC_MODE_12_16_PER_LANE) + PRINT_OR_OUT(str, len, "12-16/lane,"); + str[n-1] = 0; // Eliminate trailing comma + +out: + return str; +} + +static __inline const char* +StlLinkInitReasonToText(uint8 initReason) +{ + // all output strings are 13 characters or less + switch(initReason) { + case STL_LINKINIT_REASON_NOP: + return("None"); + case STL_LINKINIT_REASON_LINKUP: + return("LinkUp"); + case STL_LINKINIT_REASON_FLAPPING: + return("Flapping"); + case STL_LINKINIT_OUTSIDE_POLICY: + return("Out of policy"); + case STL_LINKINIT_QUARANTINED: + return("Quarantined"); + case STL_LINKINIT_INSUFIC_CAPABILITY: + return("Insuffic Cap"); + default: + return(" ???? "); + } +} + +static __inline const char* +StlLinkDownReasonToText(uint8 downReason) +{ + // all output strings are 13 characters or less + switch (downReason) { + case STL_LINKDOWN_REASON_NONE: + return("None"); + case STL_LINKDOWN_REASON_RCV_ERROR_0: + return("Rcv Error 0"); + case STL_LINKDOWN_REASON_BAD_PKT_LEN: + return("Bad Pkt Len"); + case STL_LINKDOWN_REASON_PKT_TOO_LONG: + return("Pkt Too Long"); + case STL_LINKDOWN_REASON_PKT_TOO_SHORT: + return("Pkt Too Short"); + case STL_LINKDOWN_REASON_BAD_SLID: + return("Bad slid"); + case STL_LINKDOWN_REASON_BAD_DLID: + return("Bad dlid"); + case STL_LINKDOWN_REASON_BAD_L2: + return("Bad L2"); + case STL_LINKDOWN_REASON_BAD_SC: + return("Bad SC"); + case STL_LINKDOWN_REASON_RCV_ERROR_8: + return("Rcv Error 8"); + case STL_LINKDOWN_REASON_BAD_MID_TAIL: + return("Bad Mid Tail"); + case STL_LINKDOWN_REASON_RCV_ERROR_10: + return("Rcv Error 10"); + case STL_LINKDOWN_REASON_PREEMPT_ERROR: + return("Preempt Error"); + case STL_LINKDOWN_REASON_PREEMPT_VL15: + return("Preempt VL15"); + case STL_LINKDOWN_REASON_BAD_VL_MARKER: + return("Bad VL Marker"); + case STL_LINKDOWN_REASON_RCV_ERROR_14: + return("Rcv Error 14"); + case STL_LINKDOWN_REASON_RCV_ERROR_15: + return("Rcv Error 15"); + case STL_LINKDOWN_REASON_BAD_HEAD_DIST: + return("Bad Head Dist"); + case STL_LINKDOWN_REASON_BAD_TAIL_DIST: + return("Bad Tail Dist"); + case STL_LINKDOWN_REASON_BAD_CTRL_DIST: + return("Bad Ctrl Dist"); + case STL_LINKDOWN_REASON_BAD_CREDIT_ACK: + return("Bad Cred Ack"); + case STL_LINKDOWN_REASON_UNSUPPORTED_VL_MARKER: + return("Unsup VL Mrkr"); + case STL_LINKDOWN_REASON_BAD_PREEMPT: + return("Bad Preempt"); + case STL_LINKDOWN_REASON_BAD_CONTROL_FLIT: + return("Bad Ctrl Flit"); + case STL_LINKDOWN_REASON_EXCEED_MULTICAST_LIMIT: + return("Exc MC Limit"); + case STL_LINKDOWN_REASON_RCV_ERROR_24: + return("Rcv Error 24"); + case STL_LINKDOWN_REASON_RCV_ERROR_25: + return("Rcv Error 25"); + case STL_LINKDOWN_REASON_RCV_ERROR_26: + return("Rcv Error 26"); + case STL_LINKDOWN_REASON_RCV_ERROR_27: + return("Rcv Error 27"); + case STL_LINKDOWN_REASON_RCV_ERROR_28: + return("Rcv Error 28"); + case STL_LINKDOWN_REASON_RCV_ERROR_29: + return("Rcv Error 29"); + case STL_LINKDOWN_REASON_RCV_ERROR_30: + return("Rcv Error 30"); + case STL_LINKDOWN_REASON_EXCESSIVE_BUFFER_OVERRUN: + return("Exc Buf OVR"); + case STL_LINKDOWN_REASON_UNKNOWN: + return("Unknown"); + case STL_LINKDOWN_REASON_REBOOT: + return("Reboot"); + case STL_LINKDOWN_REASON_NEIGHBOR_UNKNOWN: + return("Neigh Unknown"); + case STL_LINKDOWN_REASON_FM_BOUNCE: + return("FM Bounce"); + case STL_LINKDOWN_REASON_SPEED_POLICY: + return("Speed Policy"); + case STL_LINKDOWN_REASON_WIDTH_POLICY: + return("Width Policy"); + case STL_LINKDOWN_REASON_DISCONNECTED: + return("Disconnected"); + case STL_LINKDOWN_REASON_LOCAL_MEDIA_NOT_INSTALLED: + return("No Loc Media"); + case STL_LINKDOWN_REASON_NOT_INSTALLED: + return("Not Installed"); + case STL_LINKDOWN_REASON_CHASSIS_CONFIG: + return("Chassis Conf"); + case STL_LINKDOWN_REASON_END_TO_END_NOT_INSTALLED: + return("No End to End"); + case STL_LINKDOWN_REASON_POWER_POLICY: + return("Power Policy"); + case STL_LINKDOWN_REASON_LINKSPEED_POLICY: + return("Speed Policy"); + case STL_LINKDOWN_REASON_LINKWIDTH_POLICY: + return("Width_Policy"); + case STL_LINKDOWN_REASON_SWITCH_MGMT: + return("Switch Mgmt"); + case STL_LINKDOWN_REASON_SMA_DISABLED: + return("SMA Disabled"); + case STL_LINKDOWN_REASON_TRANSIENT: + return("Transient"); + default: + return " ???? "; + }; +} + +static __inline const char* +StlPortOfflineDisabledReasonToText(uint8 offlineReason) +{ + // all output strings are 13 characters or less + // same text as the relevant LinkDownReason subset + switch(offlineReason) { + case STL_OFFDIS_REASON_NONE: + return "None"; + case STL_OFFDIS_REASON_DISCONNECTED: + return "Disconnected"; + case STL_OFFDIS_REASON_LOCAL_MEDIA_NOT_INSTALLED: + return "No Loc Media"; + case STL_OFFDIS_REASON_NOT_INSTALLED: + return "Not installed"; + case STL_OFFDIS_REASON_CHASSIS_CONFIG: + return "Chassis Conf"; + case STL_OFFDIS_REASON_END_TO_END_NOT_INSTALLED: + return "No End to End"; + case STL_OFFDIS_REASON_POWER_POLICY: + return "Power Policy"; + case STL_OFFDIS_REASON_LINKSPEED_POLICY: + return "Speed Policy"; + case STL_OFFDIS_REASON_LINKWIDTH_POLICY: + return "Width Policy"; + case STL_OFFDIS_REASON_SWITCH_MGMT: + return "Switch Mgmt"; + case STL_OFFDIS_REASON_SMA_DISABLED: + return "SMA disabled"; + case STL_OFFDIS_REASON_TRANSIENT: + return "Transient"; + default: + return " ???? "; + }; +} + +static __inline const char* +StlRoutingModeToText(uint8 rmode) +{ + if (rmode & STL_ROUTE_LINEAR) + return "Linear"; + return "Unknown"; +} + +static __inline const char* +StlVLSchedulingConfigToText(STL_CAPABILITY_MASK3 cmask) +{ + // Note, this will change output for existing users when mode == VLArb + if (cmask.AsReg16) { + if (cmask.s.VLSchedulingConfig == STL_VL_SCHED_MODE_VLARB) + return "VLArb"; + else if (cmask.s.VLSchedulingConfig == STL_VL_SCHED_MODE_AUTOMATIC) + return "Automatic"; + } + return ""; +} + +static __inline +void FormatStlPortPacketFormat(char *buf, uint16_t packetFormat, int buflen) +{ + snprintf(buf, buflen, "%s%s%s%s%s", + packetFormat & STL_PORT_PACKET_FORMAT_8B ? "8B ":"", + packetFormat & STL_PORT_PACKET_FORMAT_9B ? "9B ":"", + packetFormat & STL_PORT_PACKET_FORMAT_10B? "10B ":"", + packetFormat & STL_PORT_PACKET_FORMAT_16B? "16B ":"", + packetFormat ? "":"-"); + buf[buflen-1] = '\0'; +} + +static __inline +const char *FormatStlVLSchedulingMode(uint8_t mode) +{ + switch (mode) { + case VL_SCHED_MODE_VLARB: + return "VLARB "; + case VL_SCHED_MODE_AUTOMATIC: + return "Auto "; + } + + return ""; +} + +static __inline +void FormatStlCapabilityMask3(char *buf, STL_CAPABILITY_MASK3 cmask, int buflen) +{ + if (cmask.AsReg16) { + snprintf(buf, buflen, "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s", + "", + "", + "", + cmask.s.IsMAXLIDSupported?"ML ":"", + "", + "", + FormatStlVLSchedulingMode(cmask.s.VLSchedulingConfig), + cmask.s.IsSnoopSupported?"SN ":"", + cmask.s.IsAsyncSC2VLSupported?"aSC2VL ":"", + cmask.s.IsAddrRangeConfigSupported?"ARC ":"", + cmask.s.IsPassThroughSupported?"PT ":"", + cmask.s.IsSharedSpaceSupported?"SS ":"", + cmask.s.IsSharedGroupSpaceSupported?"SG ":"", + cmask.s.IsVLMarkerSupported?"VLM ":"", + cmask.s.IsVLrSupported?"VLr":""); + buf[buflen-1] = '\0'; + } + else { + StringCopy(buf,"-",buflen); + } +} + + +static __inline +void FormatStlPortErrorAction(char *buf, const STL_PORT_INFO *pPortInfo, int buflen) +{ + snprintf(buf, buflen, "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s", + pPortInfo->PortErrorAction.s.ExcessiveBufferOverrun?"EBO":"", + pPortInfo->PortErrorAction.s.FmConfigErrorExceedMulticastLimit?"CE-EML":"", + pPortInfo->PortErrorAction.s.FmConfigErrorBadControlFlit?"CE-BCF":"", + pPortInfo->PortErrorAction.s.FmConfigErrorBadPreempt?"CE-BP":"", + pPortInfo->PortErrorAction.s.FmConfigErrorUnsupportedVLMarker?"CE-UVLM":"", + pPortInfo->PortErrorAction.s.FmConfigErrorBadCrdtAck?"CE-BCA":"", + pPortInfo->PortErrorAction.s.FmConfigErrorBadCtrlDist?"CE-BCD":"", + pPortInfo->PortErrorAction.s.FmConfigErrorBadTailDist?"CE-BTD":"", + pPortInfo->PortErrorAction.s.FmConfigErrorBadHeadDist?"CE-BHD":"", + pPortInfo->PortErrorAction.s.PortRcvErrorBadVLMarker?"R-BVLM":"", + pPortInfo->PortErrorAction.s.PortRcvErrorPreemptVL15?"R-PV15":"", + pPortInfo->PortErrorAction.s.PortRcvErrorPreemptError?"R-PE":"", + pPortInfo->PortErrorAction.s.PortRcvErrorBadMidTail?"R-BMT":"", + pPortInfo->PortErrorAction.s.PortRcvErrorBadSC?"R-BSC":"", + pPortInfo->PortErrorAction.s.PortRcvErrorBadL2?"R-BL2":"", + pPortInfo->PortErrorAction.s.PortRcvErrorBadDLID?"R-BDLID":"", + pPortInfo->PortErrorAction.s.PortRcvErrorBadSLID?"R-BSLID":"", + pPortInfo->PortErrorAction.s.PortRcvErrorPktLenTooShort?"R-LTS":"", + pPortInfo->PortErrorAction.s.PortRcvErrorPktLenTooLong?"R-LTL":"", + pPortInfo->PortErrorAction.s.PortRcvErrorBadPktLen?"R-BPL":""); + buf[buflen-1] = '\0'; +} + +static __inline +void FormatStlVLStalls(char *buf, const STL_PORT_INFO *pPortInfo, int buflen) +{ + // NOTO BENE: This code depends on VLStallCount being less than 8 bits long... + int i, l; + for (i = 0, l = 0; (i < STL_MAX_VLS) & (l<(buflen-3)); i++) { + l+=sprintf(&buf[i*2], "%2x", pPortInfo->XmitQ[i].VLStallCount); + } +} + +/** + Format the HOQLife information for VLs in the range [start, end) for output. Sets '\0' at end. Last VL may be truncated if space is exhausted. + + @return Index of highest VL that was formatted to @c buf. @c end indicates all were. +*/ +static __inline +int FormatStlVLHOQLife(char *buf, const STL_PORT_INFO *pPortInfo, int start, int end, int buflen) +{ + int i, l; + end = MIN(end, STL_MAX_VLS); + l = 0; + for (i = start; i < end; i++) { + if (i != start) { + if (l >= buflen) break; + l += snprintf(&buf[l], buflen - l, " "); + } + + if (l >= buflen) break; + l += snprintf(&buf[l], buflen - l, "0x%02x", pPortInfo->XmitQ[i].HOQLife); + } + + if (l >= buflen) + buf[buflen - 1] = '\0'; // ran out of space, cap it off + return i; +} + +static __inline const char* +StlQPServiceTypeToText(uint8_t code) +{ + switch (code) { + case CC_RC_TYPE: + return "Reliable Connection"; + case CC_UC_TYPE: + return "Unreliable Connection"; + case CC_RD_TYPE: + return "Reliable Datagram"; + case CC_UD_TYPE: + return "Unreliable Datagram"; + default: + return "Unknown"; + } +} + +// Cable info field definitions - lines 1, 2, and 3 + +#define STL_CIB_INDENT 6 + +#define STL_CIB_LINE1_FIELD1 (0 + STL_CIB_INDENT) +#define STL_CIB_LINE1_FIELD2 (19 + STL_CIB_INDENT) +#define STL_CIB_LINE1_FIELD3 (23 + STL_CIB_INDENT) +#define STL_CIB_LINE1_FIELD4 (41 + STL_CIB_INDENT) +#define STL_CIB_LINE1_FIELD5 (45 + STL_CIB_INDENT) +#define STL_CIB_LINE1_FIELD6 (63 + STL_CIB_INDENT) +#define STL_CIB_LINE1_FIELD7 (67 + STL_CIB_INDENT) +#define STL_CIB_LINE1_FIELD8 (69 + STL_CIB_INDENT) + +#define STL_CIB_LINE2_FIELD1 (0 + STL_CIB_INDENT) +#define STL_CIB_LINE2_FIELD2 (30 + STL_CIB_INDENT) +#define STL_CIB_LINE2_FIELD3 (34 + STL_CIB_INDENT) +#define STL_CIB_LINE2_FIELD4 (51 + STL_CIB_INDENT) +#define STL_CIB_LINE2_FIELD5 (55 + STL_CIB_INDENT) + +#define STL_CIB_LINE3_FIELD1 (0 + STL_CIB_INDENT) + +static __inline +int IsStlCableInfoActiveCable(uint8_t code_xmit) +{ + if ((code_xmit == STL_CIB_STD_TXTECH_CU_UNEQ) || + (code_xmit == STL_CIB_STD_TXTECH_CU_PASSIVEQ) || + (code_xmit > STL_CIB_STD_TXTECH_MAX)) + return 0; + else + return 1; + +} // End of IsStlCableInfoActiveCable() + +static __inline +int IsStlCableInfoCableLengthValid(uint8_t code_xmit, uint8_t code_connector) +{ + if ( (code_xmit == STL_CIB_STD_TXTECH_OTHER) || + ( (code_xmit <= STL_CIB_STD_TXTECH_1490_DFB) && + (code_connector != STL_CIB_STD_CONNECTOR_NO_SEP) ) || + (code_xmit > STL_CIB_STD_TXTECH_MAX) ) + return 0; + else + return 1; + +} // End of IsStlCableInfoCableLengthValid() + +static __inline +int IsStlCableInfoCableCertified(uint8_t code_cert) +{ + if (code_cert == STL_CIB_STD_OPA_CERTIFIED_CABLE) + return 1; + else + return 0; + +} // End of IsStlCableInfoCableLengthValid() + +static __inline +void StlCableInfoDecodeConnType(uint8_t connType, char *connTypeDesc) +{ + switch (connType) { + case STL_CIB_STD_QSFP: + case STL_CIB_STD_QSFP_PLUS: + case STL_CIB_STD_QSFP_28: + StringCopy(connTypeDesc, "QSFP", 5); + break; + case STL_CIB_STD_QSFP_DD: + StringCopy(connTypeDesc, "QSFP-DD", 8); + break; + default: + StringCopy(connTypeDesc, "Unknown", 8); + break; + } + return; +} // End of StlCableInfoDecodeConnType + +typedef struct { + boolean activeCable; + boolean cableLengthValid; + char cableTypeShortDesc[64]; + char connectorType[64]; +} CableTypeInfoType; + +static __inline +void StlCableInfoDecodeCableType(uint8_t cableType, uint8_t mediaConnType, uint8_t connType, CableTypeInfoType *cableTypeInfo) +{ + char connTypeDesc[16]; + + if (!cableTypeInfo) + return; + + // set defaults + cableTypeInfo->activeCable = 0; + cableTypeInfo->cableLengthValid = 0; + cableTypeInfo->cableTypeShortDesc[0] = 0; + memset(connTypeDesc, 0, sizeof(connTypeDesc)); + + StlCableInfoDecodeConnType(connType, connTypeDesc); + StringCopy(cableTypeInfo->cableTypeShortDesc, connTypeDesc, strlen(connTypeDesc)+1); + + if ((cableType <= STL_CIB_STD_TXTECH_1490_DFB) && (cableType != STL_CIB_STD_TXTECH_OTHER)) { + if (mediaConnType == STL_CIB_STD_CONNECTOR_NO_SEP) { + strncat(cableTypeInfo->cableTypeShortDesc, " AOC", strlen(" AOC") + 1); + cableTypeInfo->cableLengthValid = 1; + } else { + strncat(cableTypeInfo->cableTypeShortDesc, " Xcvr", strlen(" Xcvr") + 1); + cableTypeInfo->cableLengthValid = 0; + } + cableTypeInfo->activeCable = 1; + } else { + if (cableType >= STL_CIB_STD_TXTECH_CU_UNEQ) { + if (cableType <= STL_CIB_STD_TXTECH_CU_PASSIVEQ) { + strncat(cableTypeInfo->cableTypeShortDesc, " Copper", strlen(" Copper") + 1); + cableTypeInfo->activeCable = 0; + } else { + strncat(cableTypeInfo->cableTypeShortDesc, " ActCu", strlen(" ActCu") + 1); + cableTypeInfo->activeCable = 1; + } + cableTypeInfo->cableLengthValid = 1; + } + } + switch (mediaConnType) { + case STL_CIB_STD_CONNECTOR_MPO1x12: + StringCopy(cableTypeInfo->connectorType, "MPO 1x12", strlen("MPO 1x12")+1); + break; + case STL_CIB_STD_CONNECTOR_MPO2x16: + StringCopy(cableTypeInfo->connectorType, "MPO 2x16", strlen("MPO 2x16")+1); + break; + case STL_CIB_STD_CONNECTOR_NO_SEP: + StringCopy(cableTypeInfo->connectorType, "No separable connector", strlen("No separable connector")+1); + break; + case STL_CIB_STD_CONNECTOR_MXC2x16: + StringCopy(cableTypeInfo->connectorType, "MXC 2x16", strlen("MXC 2x16")+1); + break; + default: + StringCopy(cableTypeInfo->connectorType, "Unknown", strlen("Unknown")+1); + break; + } +} // End of StlCableInfoDecodeCableType() + +static __inline +void StlCableInfoBitRateToText(uint8_t code_low, uint8_t code_high, char *text_out) +{ + if (! text_out) + return; + if (code_low == STL_CIB_STD_RATELOW_EXCEED) + sprintf(text_out, "%u Gb", code_high / 4); + else + sprintf(text_out, "%u Gb", code_low / 10); + return; + +} // End of StlCableInfoBitRateToText() + +static __inline +const char * StlCableInfoOpaCertifiedRateToText(uint8_t code_rate) +{ + if (code_rate & STL_CIB_STD_OPACERTRATE_4X25G) + return "4x25G"; + else + return "Undefined"; + +} // End of StlCableInfoOpaCertifiedRateToText() + +static __inline +const char * StlCableInfoPowerClassToText(uint8_t code_low, uint8_t code_high) +{ + switch (code_high) { + case STL_CIB_STD_PWRHIGH_LEGACY: + switch (code_low) { + case STL_CIB_STD_PWRLOW_1_5: + return "Power Class 1, 1.5W max"; + case STL_CIB_STD_PWRLOW_2_0: + return "Power Class 2, 2.0W max"; + case STL_CIB_STD_PWRLOW_2_5: + return "Power Class 3, 2.5W max"; + case STL_CIB_STD_PWRLOW_3_5: + return "Power Class 4, 3.5W max"; + default: + return "Undefined"; + } + break; + case STL_CIB_STD_PWRHIGH_4_0: + return "Power Class 5, 4.0W max"; + case STL_CIB_STD_PWRHIGH_4_5: + return "Power Class 6, 4.5W max"; + case STL_CIB_STD_PWRHIGH_5_0: + return "Power Class 7, 5.0W max"; + default: + return "Undefined"; + } + +} // End of StlCableInfoPowerClassToText() + +static __inline +void StlCableInfoCableTypeToTextShort(uint8_t code_xmit, uint8_t code_connector, char *text_out) +{ + if (! text_out) + return; + if (code_xmit <= STL_CIB_STD_TXTECH_1490_DFB) { + if (code_xmit == STL_CIB_STD_TXTECH_OTHER) { + strcpy(text_out, "Other"); + return; + } + if (code_connector == STL_CIB_STD_CONNECTOR_NO_SEP) { + strcpy(text_out, "AOC"); + return; + } + strcpy(text_out, "OpticXcvr"); + return; + } + if (code_xmit <= STL_CIB_STD_TXTECH_CU_PASSIVEQ) { + strcpy(text_out, "PassiveCu"); + return; + } + if (code_xmit <= STL_CIB_STD_TXTECH_CU_LINACTEQ) { + strcpy(text_out, "ActiveCu"); + return; + } else { + strcpy(text_out, "Undefined"); + return; + } + +} // End of StlCableInfoCableTypeToTextShort() + +static __inline +void StlCableInfoCableTypeToTextLong(uint8_t code_xmit, uint8_t code_connector, char *text_out) +{ + if (! text_out) + return; + if ((code_xmit <= STL_CIB_STD_TXTECH_1490_DFB) && (code_xmit != STL_CIB_STD_TXTECH_OTHER)) { + if (code_connector == STL_CIB_STD_CONNECTOR_NO_SEP) + strcpy(text_out, "AOC, "); + else + strcpy(text_out, "Optical transceiver, "); + } + switch (code_xmit) { + case STL_CIB_STD_TXTECH_850_VCSEL: + strcat(text_out, "850nm VCSEL"); + break; + case STL_CIB_STD_TXTECH_1310_VCSEL: + strcat(text_out, "1310nm VCSEL"); + break; + case STL_CIB_STD_TXTECH_1550_VCSEL: + strcat(text_out, "1550nm VCSEL"); + break; + case STL_CIB_STD_TXTECH_1310_FP: + strcat(text_out, "1310nm FP"); + break; + case STL_CIB_STD_TXTECH_1310_DFB: + strcat(text_out, "1310nm DFB"); + break; + case STL_CIB_STD_TXTECH_1550_DFB: + strcat(text_out, "1550nm DFB"); + break; + case STL_CIB_STD_TXTECH_1310_EML: + strcat(text_out, "1310nm EML"); + break; + case STL_CIB_STD_TXTECH_1550_EML: + strcat(text_out, "1550nm EML"); + break; + case STL_CIB_STD_TXTECH_OTHER: + strcpy(text_out, "Other/Undefined"); + break; + case STL_CIB_STD_TXTECH_1490_DFB: + strcat(text_out, "1490nm DFB"); + break; + case STL_CIB_STD_TXTECH_CU_UNEQ: + strcpy(text_out, "Passive copper cable"); + break; + case STL_CIB_STD_TXTECH_CU_PASSIVEQ: + strcpy(text_out, "Equalized passive copper cable"); + break; + case STL_CIB_STD_TXTECH_CU_NFELIMACTEQ: + strcpy(text_out, "Active copper cable, TX and RX repeaters"); + break; + case STL_CIB_STD_TXTECH_CU_FELIMACTEQ: + strcpy(text_out, "Active copper cable, RX repeaters"); + break; + case STL_CIB_STD_TXTECH_CU_NELIMACTEQ: + strcpy(text_out, "Active copper cable, TX repeaters"); + break; + case STL_CIB_STD_TXTECH_CU_LINACTEQ: + strcpy(text_out, "Linear active copper cable"); + break; + default: + strcpy(text_out, "Undefined"); + break; + } // End of switch (code_xmit) + + return; + +} // End of StlCableInfoCableTypeToTextLong() + +static __inline +uint32_t StlCableInfoSMFLength(uint8_t code_len) +{ + return code_len; + +} // End of StlCableInfoSMFLength() + +static __inline +uint32_t StlCableInfoOM1Length(uint8_t code_len) +{ + return code_len; + +} // End of StlCableInfoOM1Length() + +static __inline +uint32_t StlCableInfoOM2Length(uint8_t code_len) +{ + return code_len; + +} // End of StlCableInfoOM2Length() + +static __inline +uint32_t StlCableInfoOM3Length(uint8_t code_len) +{ + return code_len * 2; + +} // End of StlCableInfoOM3Length() + +static __inline +uint32_t StlCableInfoOM4Length(uint8_t code_len, uint8_t code_valid) +{ + if (code_valid) + return code_len; + else + return code_len * 2; + +} // End of StlCableInfoOM4Length() + +static __inline +void StlCableInfoOM4LengthToText(uint8_t code_len, uint8_t code_valid, int max_chars, char *text_out) +{ + if (! text_out) + return; + snprintf(text_out, max_chars, "%um", StlCableInfoOM4Length(code_len,code_valid)); +} +#if 0 +// This macro is based on stl_sma.c/GET_LENGTH() but contains invalid logic +// for current CableInfo configurations +static __inline +void StlCableInfoCableLengthToText(uint8_t code_smf, uint8_t code_om1, uint8_t code_om2, uint8_t code_om3, uint8_t code_om4, char *text_out) +{ + if (! text_out) + return; + if (code_smf) + sprintf(text_out, "%3ukm", StlCableInfoSMFLength(code_smf)); + else if (code_om3) + sprintf(text_out, "%3um", StlCableInfoOM3Length(code_om3)); + else if (code_om2) + sprintf(text_out, "%3um", StlCableInfoOM2Length(code_om2)); + else if (code_om1) + sprintf(text_out, "%3um", StlCableInfoOM1Length(code_om1)); + else if (code_om4) + sprintf(text_out, "%3um", StlCableInfoOM4Length(code_om4)); + else + strcpy(text_out, ""); + return; + +} // End of StlCableInfoCableLengthToText() +#endif + +static __inline +void StlCableInfoDDCableLengthToText(uint8_t code_len, uint8_t code_valid, int max_chars, char *text_out) +{ + float computedLen; + uint8_t baseLen; + float multiplier = 1.0; + float factor; + int exponent; + int loopLim; + int i; + + + if (code_valid) { + + // code_len is 8-bits: + // Bits 7-6 are exponent for multiplier for base length as a power of 10 (after subtracting 1) + // Bits 5-0 are base length + + baseLen = code_len & 0x3f; + exponent = (code_len >> 6) - 1; + + if (exponent < 0) { + factor = 0.1; + loopLim = -1 * exponent; + } else { + factor = 10; + loopLim = exponent; + } + for (i = 0; i < loopLim; i++) + multiplier *= factor; + + computedLen = multiplier * baseLen; + + // if len <= 6.3, only display one decimal place + // otherwise display length as whole number + if (computedLen <= 6.3) + snprintf(text_out, max_chars, "%.1fm", computedLen); + else + snprintf(text_out, max_chars, "%dm", (uint32_t)computedLen); + } else { + strcpy(text_out, ""); + } + + return; + +} // End of StlCableInfoDDCableLengthToText() + +static __inline +void StlCableInfoDateCodeToText(uint8_t * code_date, char *text_out) +{ + if (! text_out) + return; + // Format date code as: 20YY/MM/DD LL (lot) + strcpy(text_out, "20xx/xx/xx-xx"); + text_out[2] = code_date[0]; + text_out[3] = code_date[1]; + text_out[5] = code_date[2]; + text_out[6] = code_date[3]; + text_out[8] = code_date[4]; + text_out[9] = code_date[5]; + text_out[11] = code_date[6]; + text_out[12] = code_date[7]; + text_out[13] = '\0'; + return; + +} // End of StlCableInfoOutputDateCodeToText() + +static __inline +void StlCableInfoTrimTrailingWS(char *string, size_t len) +{ + size_t i = len - 1; + + while (i > 0 && (isspace(string[i]) || string[i] == 0)) + i--; + + string[i + 1] = '\0'; +} // End of StlCableInfoTrimTrailingWS() + + +static __inline +const char * StlCableInfoCDRToText(uint8_t code_supp, uint8_t code_ctrl) +{ + if (! code_supp) + return "N/A"; + else if (code_ctrl) + return "On "; + else + return "Off"; + +} // End of StlCableInfoCDRToText() + +static __inline const char* +StlPortTypeToText(uint8_t code) +{ + switch(code) { + case STL_PORT_TYPE_DISCONNECTED: + return "Disconnected"; + case STL_PORT_TYPE_STANDARD: + return "Standard"; + case STL_PORT_TYPE_FIXED: + return "Fixed"; + case STL_PORT_TYPE_VARIABLE: + return "Variable"; + case STL_PORT_TYPE_SI_PHOTONICS: + return "Silicon Photonics"; + default: + return "Unknown"; + } +} + +static __inline uint32 StlLargePktLimitToBytes(uint8 largepktlimit) +{ + return (512 + (uint32)largepktlimit*512); +} + +static __inline uint8 StlBytesToLargePktLimit(uint32 bytes) +{ + bytes /= 512; + return bytes?bytes-1:0; // <=512 returned as 0 +} + +static __inline uint32 StlSmallPktLimitToBytes(uint8 smallpktlimit) +{ + return (32 + (uint32)smallpktlimit*32); +} + +static __inline uint8 StlBytesToSmallPktLimit(uint32 bytes) +{ + bytes /= 32; + return bytes?bytes-1:0; // <=32 returned as 0 +} + +static __inline uint32 StlPreemptionLimitToBytes(uint8 limit) +{ + // no ideal return for NONE, so use largest uint8 (can't fo uint32 as it would overflow buf[6] + if (limit == STL_PORT_PREEMPTION_LIMIT_NONE) return IB_UINT8_MAX; + return ((uint32)limit*256); +} + +static __inline uint8 StlBytesToPreemptionLimit(uint32 bytes) +{ + bytes /= 256; + return (bytes>=0xff)?STL_PORT_PREEMPTION_LIMIT_NONE:bytes; +} + +static __inline +void FormatStlPreemptionLimit(char buf[6], uint8 limit) +{ + if (limit == STL_PORT_PREEMPTION_LIMIT_NONE) + sprintf(buf, "%5s", "None"); + else + snprintf(buf, 6, "%5u", (unsigned int)StlPreemptionLimitToBytes(limit)); +} + +/* convert capability mask into a text representation */ +static __inline +void FormatStlCapabilityMask(char buf[80], STL_CAPABILITY_MASK cmask) +{ + snprintf(buf, 80, "%s%s%s%s%s%s%s", + cmask.s.IsCapabilityMaskNoticeSupported?"CN ": "", + cmask.s.IsVendorClassSupported?"VDR ": "", + cmask.s.IsDeviceManagementSupported?"DM ": "", + cmask.s.IsConnectionManagementSupported?"CM ": "", + cmask.s.IsAutomaticMigrationSupported?"APM ": "", + cmask.s.IsSM?"SM ": "", + cmask.AsReg32?"": "-"); +} + +/* convert Node Type to text */ +static __inline const char* +StlNodeTypeToText(NODE_TYPE type) +{ + return (type == STL_NODE_FI)?"FI": + (type == STL_NODE_SW)?"SW": "??"; +} + + +static __inline uint8 StlNeighNodeTypeToNodeType(NODE_TYPE type) +{ + + if(type==STL_NEIGH_NODE_TYPE_HFI) + return STL_NODE_FI; + else + return STL_NODE_SW; + +} + +static __inline const char* +StlLinkQualToText(uint8 linkQual) +{ + switch (linkQual) + { + case STL_LINKQUALITY_NONE: + return "Down"; + case STL_LINKQUALITY_BAD: + return "Bad"; + case STL_LINKQUALITY_POOR: + return "Poor"; + case STL_LINKQUALITY_GOOD: + return "Good"; + case STL_LINKQUALITY_VERY_GOOD: + return "VeryGood"; + case STL_LINKQUALITY_EXCELLENT: + return "Excellent"; + default: + return "???"; + } +} + + + +/* convert Neighbor node Type to text */ +static __inline const char* +OpaNeighborNodeTypeToText(uint8 ntype) +{ + return (ntype == STL_NEIGH_NODE_TYPE_HFI) ? "HFI": + (ntype == STL_NEIGH_NODE_TYPE_SW) ? "Switch" : "Unknown"; +} + +static __inline int +IsCableInfoAvailable(STL_PORT_INFO *portInfo) +{ + return (portInfo->PortPhysConfig.s.PortType == STL_PORT_TYPE_STANDARD + && ! ( (portInfo->PortStates.s.PortPhysicalState == STL_PORT_PHYS_OFFLINE || + portInfo->PortStates.s.PortPhysicalState == IB_PORT_PHYS_DISABLED) + && portInfo->PortStates.s.OfflineDisabledReason == STL_OFFDIS_REASON_LOCAL_MEDIA_NOT_INSTALLED)); +} + +static __inline uint8 +StlResolutionToShift(uint32 res, uint8 add) { +// shift = log2(res) - add + uint8 shift = FloorLog2(res); + if (shift > add) { + if ((shift - add) > 15) return 15; + else return shift - add; + } + else return 0; +} + +static __inline uint32 +StlShiftToResolution(uint8 shift, uint8 add) { +// res = 2^(shift + add) + if (shift) return (uint32)1<<(shift + add); + else return 0; +} + +static __inline const char* +StlVlarbSecToText (uint8 sec) { + switch (sec) { + case STL_VLARB_LOW_ELEMENTS: + return "Low"; + case STL_VLARB_HIGH_ELEMENTS: + return "High"; + case STL_VLARB_PREEMPT_ELEMENTS: + return "Preempt"; + case STL_VLARB_PREEMPT_MATRIX: + return "Preempt Matrix"; + default: + DEBUG_ASSERT(0); + return "Unknown"; + } +} + + + +static __inline int +StlNumVLsSetInVLSelectMask(const uint32 VLSelectMask) +{ + uint32_t vlmask; + int i; + int numSet=0; + + for (i=0, vlmask=VLSelectMask; (i <= STL_MAX_VLS) && vlmask; i++, vlmask >>= 1) { + if (vlmask & 1) numSet++; + } + return numSet; +} + +static __inline int +StlNumPortsSetInPortMask(const STL_PORTMASK* portSelectMask, const uint8_t totalPorts) +{ + uint64_t pmask; + int i; + int numSet=0; + + for (i=0; i <= totalPorts; i++) { + pmask = (uint64_t)(1) << (i % 64); + if (portSelectMask[3-(i/64)] & pmask) + numSet++; + } + return numSet; +} + +static __inline void +StlAddPortToPortMask(STL_PORTMASK* portSelectMask, const uint8_t port) +{ + uint64_t pmask = (uint64_t)(1) << (port % 64); + portSelectMask[3-(port/64)] |= pmask; +} + +static __inline void +StlClearPortInPortMask(STL_PORTMASK* portSelectMask, const uint8_t port) +{ + uint64_t pmask = (uint64_t)(1) << (port % 64); + if (portSelectMask[3-(port/64)] & pmask) + portSelectMask[3-(port/64)] ^= pmask; +} + +static __inline int +StlIsPortInPortMask(const STL_PORTMASK* portSelectMask, const uint8_t port) +{ + uint64_t pmask = (uint64_t)(1) << (port % 64); + return ((portSelectMask[3-(port/64)] & pmask) ? 1 : 0); +} + +static __inline void +StlSetAllPortsInPortMask(STL_PORTMASK* portSelectMask, const uint8_t numPorts) +{ + int i; + + for (i=0; i<= numPorts; i++) + StlAddPortToPortMask(portSelectMask, i); +} + +static __inline int +StlTestAndClearPortInPortMask(STL_PORTMASK* portSelectMask, const uint8_t port) +{ + uint64_t pmask = (uint64_t)(1) << (port % 64); + if (portSelectMask[3-(port/64)] & pmask) { + portSelectMask[3-(port/64)] ^= pmask; + return 1; + } + return 0; +} + +static __inline int +StlGetNextPortInPortMask(const STL_PORTMASK* portSelectMask, int port) +{ + uint64_t pmask; + int i; + + for (i=port; i <= MAX_STL_PORTS; i++) { + pmask = (uint64_t)(1) << (i % 64); + if (portSelectMask[3-(i/64)] & pmask) + return i; + } + return 0xff; +} +static __inline int +StlGetFirstPortInPortMask(const STL_PORTMASK* portSelectMask) +{ + return StlGetNextPortInPortMask(portSelectMask, 0); +} + +static __inline int +StlGetNextUnusedPortInPortMask(const STL_PORTMASK* portSelectMask, const uint8_t port) +{ + uint64_t pmask; + int i; + + for (i=port+1; i <= MAX_STL_PORTS; i++) { + pmask = (uint64_t)(1) << (i % 64); + if ((portSelectMask[3-(i/64)] & pmask) == 0) + return i; + } + return 0xff; +} + +static __inline int +StlCommonPortsInMasks(STL_PORTMASK* portSelectMask, const STL_PORTMASK* portSelectMask2) +{ + unsigned i; + for (i=0; i 1) { + if (first == last) + l += snprintf(&buf[l], buflen - l, ",%d", i); + else + l += snprintf(&buf[l], buflen - l, "-%d,%d", last, i); + first = i; + last = first; + } else { + last = i; + } + } + + if (first != last && last != -1) + l += snprintf(&buf[l], buflen - l, "-%d", last); + + if (l >= buflen) + buf[buflen - 1] = '\0'; // ran out of space, cap it off +} + +static __inline +FSTATUS StringToStlPortMask(STL_PORTMASK *portSelectMask, const char *buf) +{ + const char *pbuf = buf; + unsigned int lhs, rhs, i, j; + uint8 p; + char newString[80]; + const char delimiter = '-'; + char currChar; + memset(newString, 0, sizeof(newString)); + + //cut "ports:" off buf if necessary + if (strncmp(buf, "ports: ", 7) == 0) pbuf += 7; + + for(i=0; i < strlen(pbuf)+1; i++) { + currChar = pbuf[i]; + if(currChar == ',' || currChar == '\0') { + if(!newString[0]) continue; + if (strchr(newString, delimiter)) { + //for (lhs-rhs), add port to portmask + if(sscanf(newString, "%u-%u", &lhs, &rhs) != 2) + return FINVALID_PARAMETER; + if (lhs > MAX_STL_PORTS || rhs > MAX_STL_PORTS || lhs >= rhs) + return FINVALID_PARAMETER; + for (j=lhs; j<=rhs; j++) + StlAddPortToPortMask(portSelectMask, j); + } else { + if(FSUCCESS != StringToUint8(&p, newString, NULL, 0, TRUE) || p > MAX_STL_PORTS) + return FINVALID_PARAMETER; + StlAddPortToPortMask(portSelectMask, p); + } + memset(newString, 0, sizeof(newString)); + } + else + strncat(newString, &currChar, 1); + } + + return FSUCCESS; +} + + +static __inline +void FormatStlVLMask(char *buf, const uint32 vlmask, int buflen) +{ + int i, l; + l = 0; + int last=-1; + int first=0; + + for (i=0; i<32; i++) { + if ((vlmask & (1 << i)) == 0) continue; + if (last == -1) { + l += snprintf(&buf[l], buflen - l, "VLs: %d", i); + first = i; + last = first; + } else if ((i-last) > 1) { + if (first == last) + l += snprintf(&buf[l], buflen - l, ",%d", i); + else + l += snprintf(&buf[l], buflen - l, "-%d,%d", last, i); + first = i; + last = first; + } else { + last = i; + } + } + + if (first != last) + l += snprintf(&buf[l], buflen - l, "-%d", last); + + if (l >= buflen) + buf[buflen - 1] = '\0'; // ran out of space, cap it off +} + +static __inline void +FormatStlCounterSelectMask(char buf[128], CounterSelectMask_t mask) { + snprintf(buf, 128, "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s", + (mask.s.PortXmitData ? "TxD ": ""), + (mask.s.PortRcvData ? "RxD ": ""), + (mask.s.PortXmitPkts ? "TxP ": ""), + (mask.s.PortRcvPkts ? "RxP ": ""), + (mask.s.PortMulticastXmitPkts ? "MTxP ": ""), + (mask.s.PortMulticastRcvPkts ? "MRxP ": ""), + + (mask.s.PortXmitWait ? "TxW ": ""), + (mask.s.SwPortCongestion ? "CD ": ""), /* CongDiscards */ + (mask.s.PortRcvFECN ? "RxF ": ""), + (mask.s.PortRcvBECN ? "RxB ": ""), + (mask.s.PortXmitTimeCong ? "TxTC ": ""), + (mask.s.PortXmitWastedBW ? "WBW ": ""), + (mask.s.PortXmitWaitData ? "TxWD ": ""), + (mask.s.PortRcvBubble ? "RxBb ": ""), + (mask.s.PortMarkFECN ? "MkF ": ""), + (mask.s.PortRcvConstraintErrors ? "RxCE ": ""), + (mask.s.PortRcvSwitchRelayErrors ? "RxSR ": ""), + (mask.s.PortXmitDiscards ? "TxDc ": ""), + (mask.s.PortXmitConstraintErrors ? "TxCE ": ""), + (mask.s.PortRcvRemotePhysicalErrors ? "RxRP ": ""), + (mask.s.LocalLinkIntegrityErrors ? "LLI ": ""), + (mask.s.PortRcvErrors ? "RxE ": ""), + (mask.s.ExcessiveBufferOverruns ? "EBO ": ""), + (mask.s.FMConfigErrors ? "FMC ": ""), + (mask.s.LinkErrorRecovery ? "LER ": ""), + (mask.s.LinkDowned ? "LD ": ""), + (mask.s.UncorrectableErrors ? "Unc": "")); +} + +/** + * Compute difference of two sets of Port Counters + * + * @param data1 - pointer to later (end) set of STL_PORT_COUNTERS_DATA counters + * @param data2 - pointer to earlier (begin) set of STL_PORT_COUNTERS_DATA + * counters + * @param result - pointer to where result of data1 - data2 will be stored + * + * Note: data1 should be >= data2. If this is not the case, result will be + * value for data1 +*/ +static __inline CounterSelectMask_t DiffPACounters(STL_PORT_COUNTERS_DATA * data1, STL_PORT_COUNTERS_DATA * data2, STL_PORT_COUNTERS_DATA * result) +{ + CounterSelectMask_t mask = {0}; + +#define GET_DELTA_COUNTER(cntr, name) do { \ + if (data1->cntr < data2->cntr) { \ + mask.s.name = 1; \ + result->cntr = data1->cntr; \ + } else { \ + result->cntr = data1->cntr - data2->cntr; \ + } } while (0) + + GET_DELTA_COUNTER(linkErrorRecovery, LinkErrorRecovery); + GET_DELTA_COUNTER(linkDowned, LinkDowned); + GET_DELTA_COUNTER(portRcvErrors, PortRcvErrors); + GET_DELTA_COUNTER(portRcvRemotePhysicalErrors, PortRcvRemotePhysicalErrors); + GET_DELTA_COUNTER(portRcvSwitchRelayErrors, PortRcvSwitchRelayErrors); + GET_DELTA_COUNTER(portXmitDiscards, PortXmitDiscards); + GET_DELTA_COUNTER(portXmitConstraintErrors, PortXmitConstraintErrors); + GET_DELTA_COUNTER(portRcvConstraintErrors, PortRcvConstraintErrors); + GET_DELTA_COUNTER(localLinkIntegrityErrors, LocalLinkIntegrityErrors); + GET_DELTA_COUNTER(excessiveBufferOverruns, ExcessiveBufferOverruns); + GET_DELTA_COUNTER(portXmitData, PortXmitData); + GET_DELTA_COUNTER(portRcvData, PortRcvData); + GET_DELTA_COUNTER(portXmitPkts, PortXmitPkts); + GET_DELTA_COUNTER(portRcvPkts, PortRcvPkts); + GET_DELTA_COUNTER(portMulticastXmitPkts, PortMulticastXmitPkts); + GET_DELTA_COUNTER(portMulticastRcvPkts, PortMulticastRcvPkts); + GET_DELTA_COUNTER(portXmitWait, PortXmitWait); + GET_DELTA_COUNTER(swPortCongestion, SwPortCongestion); + GET_DELTA_COUNTER(portRcvFECN, PortRcvFECN); + GET_DELTA_COUNTER(portRcvBECN, PortRcvBECN); + GET_DELTA_COUNTER(portXmitTimeCong, PortXmitTimeCong); + GET_DELTA_COUNTER(portXmitWastedBW, PortXmitWastedBW); + GET_DELTA_COUNTER(portXmitWaitData, PortXmitWaitData); + GET_DELTA_COUNTER(portRcvBubble, PortRcvBubble); + GET_DELTA_COUNTER(portMarkFECN, PortMarkFECN); + GET_DELTA_COUNTER(fmConfigErrors, FMConfigErrors); + GET_DELTA_COUNTER(uncorrectableErrors, UncorrectableErrors); + result->lq.s.numLanesDown = MAX(data1->lq.s.numLanesDown, data2->lq.s.numLanesDown); + result->lq.s.linkQualityIndicator = MIN(data1->lq.s.linkQualityIndicator, data2->lq.s.linkQualityIndicator); + +#undef GET_DELTA_COUNTER + return mask; +} + +/** + * Compute difference of two sets of VF Port Counters + * + * @param data1 - pointer to later set of STL_PA_VF_PORT_COUNTERS_DATA counters + * @param data2 - pointer to earlier set of STL_PA_VF_PORT_COUNTERS_DATA counters + * @param result - pointer to where result of data1 - data2 will be stored + * + * Note: data1 should be >= data2. If this is not the case, result will be + * value for data1 + */ +static __inline CounterSelectMask_t DiffPAVFCounters(STL_PA_VF_PORT_COUNTERS_DATA * data1, STL_PA_VF_PORT_COUNTERS_DATA * data2, STL_PA_VF_PORT_COUNTERS_DATA * result) +{ +#define GET_DELTA_COUNTER(cntr, name) do { \ + if (data1->cntr < data2->cntr) { \ + mask.s.name = 1; \ + result->cntr = data1->cntr; \ + } else { \ + result->cntr = data1->cntr - data2->cntr; \ + } } while (0) + + CounterSelectMask_t mask = {0}; + + GET_DELTA_COUNTER(portVFXmitDiscards, PortXmitDiscards); + GET_DELTA_COUNTER(portVFXmitData, PortXmitData); + GET_DELTA_COUNTER(portVFRcvData, PortRcvData); + GET_DELTA_COUNTER(portVFXmitPkts, PortXmitPkts); + GET_DELTA_COUNTER(portVFRcvPkts, PortRcvPkts); + GET_DELTA_COUNTER(portVFXmitWait, PortXmitWait); + GET_DELTA_COUNTER(swPortVFCongestion, SwPortCongestion); + GET_DELTA_COUNTER(portVFRcvFECN, PortRcvFECN); + GET_DELTA_COUNTER(portVFRcvBECN, PortRcvBECN); + GET_DELTA_COUNTER(portVFXmitTimeCong, PortXmitTimeCong); + GET_DELTA_COUNTER(portVFXmitWastedBW, PortXmitWastedBW); + GET_DELTA_COUNTER(portVFXmitWaitData, PortXmitWaitData); + GET_DELTA_COUNTER(portVFRcvBubble, PortRcvBubble); + GET_DELTA_COUNTER(portVFMarkFECN, PortMarkFECN); + +#undef GET_DELTA_COUNTER + return mask; +} + +#if !defined(ROUNDUP) +#define ROUNDUP(val, align) ((((uintn)(val)+(uintn)(align)-1)/((uintn)align))*((uintn)(align))) +#endif + +#if !defined(ROUNDUP_TYPE) +#define ROUNDUP_TYPE(type, val, align) ((((val)-1) | ((type)((align)-1)))+1) +#endif + +/* Simplify accessing PORT(i%MAX_PORTS) data from a Block(i/MAX_PORTS) */ +#define STL_LFT_PORT_BLOCK(LftTable, i) \ + LftTable[i/MAX_LFT_ELEMENTS_BLOCK].LftBlock[i%MAX_LFT_ELEMENTS_BLOCK] +#define STL_PGFT_PORT_BLOCK(PgftTable, i) \ + PgftTable[i/NUM_PGFT_ELEMENTS_BLOCK].PgftBlock[i%NUM_PGFT_ELEMENTS_BLOCK] + + +static __inline uint8 +StlGetNumLanesDown(STL_PORT_INFO *portInfo) { + return (portInfo->LinkWidthDowngrade.RxActive < portInfo->LinkWidth.Active ? + StlLinkWidthToInt(portInfo->LinkWidth.Active) - + StlLinkWidthToInt(portInfo->LinkWidthDowngrade.RxActive) : 0); +} + + +#ifdef __cplusplus +}; +#endif + +#endif /* _IBA_STL_HELPER_H_ */ diff --git a/IbAccess/Common/Inc/stl_mad_priv.h b/IbAccess/Common/Inc/stl_mad_priv.h new file mode 100644 index 0000000..c640e12 --- /dev/null +++ b/IbAccess/Common/Inc/stl_mad_priv.h @@ -0,0 +1,139 @@ +/* BEGIN_ICS_COPYRIGHT7 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT7 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +#ifndef __IBA_STL_MAD_PRIV_H__ +#define __IBA_STL_MAD_PRIV_H__ + +#define STL_MAD_BLOCK_SIZE 2048 +#include "iba/stl_mad_types.h" +#include "iba/stl_types.h" +#include "iba/ib_types.h" +#include "iba/ib_mad.h" + +#if defined (__cplusplus) +extern "C" { +#endif + +/* + * MAD Base Fields + */ +typedef MAD STL_MAD; + +/* + * Convenience functions for converting MAD packets from host to network byte + * byte order (or vice-versa). + */ + +static __inline +void +BSWAP_STL_CLASS_PORT_INFO( + STL_CLASS_PORT_INFO *Dest + ) +{ +#if CPU_LE + Dest->CapMask = ntoh16(Dest->CapMask); + Dest->u1.AsReg32 = ntoh32(Dest->u1.AsReg32); + BSWAP_IB_GID(&Dest->RedirectGID); + Dest->u2.AsReg32 = ntoh32(Dest->u2.AsReg32); + Dest->RedirectLID = ntoh32(Dest->RedirectLID); + Dest->u3.AsReg32 = ntoh32(Dest->u3.AsReg32); + Dest->Redirect_Q_Key = ntoh32(Dest->Redirect_Q_Key); + BSWAP_IB_GID(&Dest->TrapGID); + Dest->u4.AsReg32 = ntoh32(Dest->u4.AsReg32); + Dest->TrapLID = ntoh32(Dest->TrapLID); + Dest->u5.AsReg32 = ntoh32(Dest->u5.AsReg32); + Dest->Trap_Q_Key = ntoh32(Dest->Trap_Q_Key); + Dest->Trap_P_Key = ntoh16(Dest->Trap_P_Key); + Dest->Redirect_P_Key = ntoh16(Dest->Redirect_P_Key); +#endif +} + + + +static __inline +void BSWAP_STL_NOTICE(STL_NOTICE * notice) +{ +#if CPU_LE + if (notice->Attributes.Generic.u.s.IsGeneric) { + notice->Attributes.Generic.u.AsReg32 = ntoh32(notice->Attributes.Generic.u.AsReg32); + notice->Attributes.Generic.TrapNumber = ntoh16(notice->Attributes.Generic.TrapNumber); + } + else { + notice->Attributes.Vendor.u.AsReg32 = ntoh32(notice->Attributes.Vendor.u.AsReg32); + notice->Attributes.Vendor.DeviceID = ntoh16(notice->Attributes.Vendor.DeviceID); + } + + notice->Stats.AsReg16 = ntoh16(notice->Stats.AsReg16); + notice->IssuerLID = ntoh32(notice->IssuerLID); + + BSWAP_IB_GID(¬ice->IssuerGID); +#endif +} + +static __inline +void BSWAPCOPY_STL_NOTICE(STL_NOTICE * src, STL_NOTICE * dst) +{ + memcpy(dst, src, sizeof(STL_NOTICE)); + (void)BSWAP_STL_NOTICE(dst); +} + +static __inline +void +BSWAP_STL_INFORM_INFO(STL_INFORM_INFO *dst) +{ +#if CPU_LE + BSWAP_IB_GID(&dst->GID); + + dst->LIDRangeBegin = ntoh32(dst->LIDRangeBegin); + dst->LIDRangeEnd = ntoh32(dst->LIDRangeEnd); + dst->Type = ntoh16(dst->Type); + dst->u.Generic.TrapNumber = ntoh16(dst->u.Generic.TrapNumber); + dst->u.Generic.u1.AsReg32 = ntoh32(dst->u.Generic.u1.AsReg32); + dst->u.Generic.u2.AsReg32 = ntoh32(dst->u.Generic.u2.AsReg32); +#endif +} + +static __inline +void +BSWAPCOPY_STL_INFORM_INFO(STL_INFORM_INFO *src, STL_INFORM_INFO *dst) +{ +#if CPU_LE + memcpy(dst, src, sizeof(STL_INFORM_INFO)); + BSWAP_STL_INFORM_INFO(dst); +#endif +} + +#if defined (__cplusplus) +}; +#endif + +#endif /* __IBA_STL_MAD_PRIV_H__ */ + diff --git a/IbAccess/Common/Inc/stl_mad_types.h b/IbAccess/Common/Inc/stl_mad_types.h new file mode 100644 index 0000000..cbacee9 --- /dev/null +++ b/IbAccess/Common/Inc/stl_mad_types.h @@ -0,0 +1,292 @@ +/* BEGIN_ICS_COPYRIGHT7 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT7 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +#ifndef __IBA_STL_MAD_TYPES_H__ +#define __IBA_STL_MAD_TYPES_H__ + +#include "iba/public/datatypes.h" +#include "iba/stl_types.h" +#include "iba/ib_mad.h" + +#if defined (__cplusplus) +extern "C" { +#endif + +#define STL_BASE_VERSION 0x80 + +/* + * STL equivalents of IBA_NODE_CHANNEL_ADAPTER and IBA_NODE_SWITCH. + */ +#define STL_NODE_FI 1 +#define STL_NODE_SW 2 + +/* + * The following MADs are generic across all management classes. + */ +#define STL_MCLASS_ATTRIB_ID_CLASS_PORT_INFO 0x0001 +#define STL_MCLASS_ATTRIB_ID_NOTICE 0x0002 +#define STL_MCLASS_ATTRIB_ID_INFORM_INFO 0x0003 + +/* + * Common ClassPortInfo Capability Bits + */ +#define STL_CLASS_PORT_CAPMASK_TRAP 0x0001 /* Can generate traps */ +#define STL_CLASS_PORT_CAPMASK_NOTICE 0x0002 /* Implements Get/Set Notice */ +#define STL_CLASS_PORT_CAPMASK_CM2 0x0004 /* Implements Additional Class Specific Capabilities (CapMask2) */ + +#include "iba/public/ipackon.h" + +/* + * Class Port Info: + * + * This attribute is needed only for use in fabrics that need long LIDs or + * more than 16 SLs or VLs. The default should be to continue to use the IB + * version. While Storm Lake does not support redirect, this attribute + * continues to contain redirect fields such that it can be a canonical + * representation of both IB and STL devices. The assorted redirect fields + * shall be 0 when the response is supplied by an STL device. + * + * STL Differences: + * RedirectLID is now 32 bits. + * TrapLID is now 32 bits. + * Redirect_P_Key moved for qword alignment. + * Trap_P_Key moved for qword alignment. + * RedirectSL and TrapSL moved to handle longer lengths. + */ + +typedef struct { + uint8 BaseVersion; // RO: Must be STL_BASE_VERSION + uint8 ClassVersion; // RO + + uint16 CapMask; // RO + + STL_FIELDUNION2(u1, 32, + CapMask2:27, // RO + RespTimeValue:5); // RO + + /* 8 bytes */ + + //Redirect attributes. + IB_GID RedirectGID; // RO + + /* 24 bytes */ + + STL_FIELDUNION3(u2, 32, + RedirectTClass:8, // RO + Reserved:4, // Old SL. Must be zero. + RedirectFlowLabel:20); // RO + + STL_LID RedirectLID; // Lengthened for STL. P_Key moved. + + /* 32 bytes */ + + STL_FIELDUNION3(u3, 32, + RedirectSL:5, // RO: Moved from old location. + Reserved2:3, // Must be zero. + RedirectQP:24) ; // RO + + uint32 Redirect_Q_Key; // RO + + /* 40 bytes */ + + //Settable attributes to tell Class agent where to send traps. + IB_GID TrapGID; // RW + + /* 56 bytes */ + + STL_FIELDUNION3(u4, 32, + TrapTClass:8, // RW + Reserved3:4, // Must be zero. + TrapFlowLabel:20); // RW + + STL_LID TrapLID; // Lengthened for STL. + + /* 64 bytes */ + + STL_FIELDUNION2(u5, 32, + TrapHopLimit:8, // RW + TrapQP:24); // RW + + uint32 Trap_Q_Key; // RW + + /* 72 bytes */ + + uint16 Trap_P_Key; // Moved for STL qword alignment. + uint16 Redirect_P_Key; // Moved for STL qword alignment. + + STL_FIELDUNION2(u6, 8, + TrapSL:5, // RW: Moved to accommodate larger size. + Reserved4:3); // Must be zero. + + uint8 Reserved5[3]; // Must be zero. + + /* 80 bytes */ + +} STL_CLASS_PORT_INFO; + +/* + * InformInfoRecord + * + * This should only be used for fabrics that need long LIDs. Smaller + * fabrics should continue to use the IB version. + * + * STL Differences: + * LIDRangeBegin is now 32 bits. + * LIDRangeEnd is now 32 bits. + * Reserved removed after LIDRangeEnd and added after Type + * to qword/word align bit fields. + */ +typedef struct { + IB_GID GID; // RW + + /* 16 bytes */ + + STL_LID LIDRangeBegin; // RW + STL_LID LIDRangeEnd; // RW + + /* 24 bytes */ + + uint8 IsGeneric; // RW + uint8 Subscribe; // RW + + uint16 Type; // RW + + uint16 Reserved1; // Must be zero. + + /* 30 bytes */ + + union { + struct { + uint16 TrapNumber; // RW + /* 32 bytes */ + STL_FIELDUNION3(u1, 32, + QPNumber:24, // RW + Reserved2:3, // Must be zero. + RespTimeValue:5); // RO + STL_FIELDUNION2(u2, 32, + Reserved3:8, // Must be zero. + ProducerType:24); // RW + } Generic; + + struct { + uint16 DeviceID; // RW + /* 32 bytes */ + STL_FIELDUNION3(u1, 32, + QPNumber:24, // RW + Reserved4:3, // Must be zero. + RespTimeValue:5); // RO + STL_FIELDUNION2(u2, 32, + Reserved5:8, // Must be zero. + VendorID:24); // RW + } Vendor; + } u; + + /* 40 bytes */ +} STL_INFORM_INFO; + + +/* + * Notice + * + * All STL fabrics should use the STL Notice structure when communicating with + * STL devices and applications. When forwarding notices to IB applications, + * the SM shall translate them into IB format, when IB equivalents exist. + * + * STL Differences: + * IssuerLID is now 32 bits. + * Moved fields to maintain word alignment. + * Data and ClassTrapSpecificData combined into a single field. + */ +typedef struct { + union { + /* Generic Notice attributes */ + struct /*_GENERIC*/ { + STL_FIELDUNION3(u, 32, + IsGeneric:1, // RO + Type:7, // RO + ProducerType:24); // RO + uint16 TrapNumber; // RO + } PACK_SUFFIX Generic; + + /* Vendor specific Notice attributes */ + struct /*_VENDOR*/ { + STL_FIELDUNION3(u, 32, + IsGeneric:1, // RO + Type:7, // RO + VendorID:24); // RO + uint16 DeviceID; // RO + } PACK_SUFFIX Vendor; + } PACK_SUFFIX Attributes; + + STL_FIELDUNION2(Stats, 16, + Toggle:1, // RW + Count:15); // RW + + /* 8 bytes */ + uint32 IssuerLID; // RO: Extended for STL + uint32 Reserved2; // Added for qword alignment + /* 16 bytes */ + IB_GID IssuerGID; // RO + /* 32 bytes */ + uint8 Data[64]; // RO. + /* 96 bytes */ + uint8 ClassData[0]; // RO. Variable length. +} PACK_SUFFIX STL_NOTICE; + +#include "iba/public/ipackoff.h" + +static __inline void +StlCommonClassPortInfoCapMask(char buf[80], uint16 cmask) +{ + if (!cmask) { + snprintf(buf, 80, "-"); + } else { + snprintf(buf, 80, "%s%s%s", + (cmask & STL_CLASS_PORT_CAPMASK_TRAP) ? "Trap " : "", + (cmask & STL_CLASS_PORT_CAPMASK_NOTICE) ? "Notice " : "", + (cmask & STL_CLASS_PORT_CAPMASK_CM2) ? "CapMask2 " : ""); + } +} + +static __inline void +StlCommonClassPortInfoCapMask2(char buf[80], uint32 cmask) +{ + if (!cmask) { + snprintf(buf, 80, "-"); + } else { + buf[0] = '\0'; + } +} + +#if defined (__cplusplus) +} +#endif +#endif diff --git a/IbAccess/Common/Inc/stl_pa_priv.h b/IbAccess/Common/Inc/stl_pa_priv.h new file mode 100644 index 0000000..86fcfb6 --- /dev/null +++ b/IbAccess/Common/Inc/stl_pa_priv.h @@ -0,0 +1,632 @@ +/* BEGIN_ICS_COPYRIGHT7 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT7 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +#ifndef _STL_PA_PRIV_H_ +#define _STL_PA_PRIV_H_ (1) /* suppress duplicate loading of this file */ + +#include "iba/stl_pa_types.h" +#include "iba/stl_mad_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +static __inline void +BSWAP_STL_PA_IMAGE_ID(STL_PA_IMAGE_ID_DATA *pRecord) +{ +#if CPU_LE + pRecord->imageNumber = ntoh64(pRecord->imageNumber); + pRecord->imageOffset = ntoh32(pRecord->imageOffset); + pRecord->imageTime.absoluteTime = ntoh32(pRecord->imageTime.absoluteTime); +#endif /* CPU_LE */ +} + +static __inline void +BSWAP_STL_PA_PM_GROUP_INFO(STL_PA_PM_GROUP_INFO_DATA *pRecord, boolean isRequest) +{ +#if CPU_LE + int i; + BSWAP_STL_PA_IMAGE_ID(&pRecord->imageId); + + if (isRequest) return; + + pRecord->numInternalPorts = ntoh32(pRecord->numInternalPorts); + pRecord->numExternalPorts = ntoh32(pRecord->numExternalPorts); + + pRecord->internalUtilStats.totalMBps = ntoh64(pRecord->internalUtilStats.totalMBps); + pRecord->internalUtilStats.totalKPps = ntoh64(pRecord->internalUtilStats.totalKPps); + pRecord->internalUtilStats.avgMBps = ntoh32(pRecord->internalUtilStats.avgMBps); + pRecord->internalUtilStats.minMBps = ntoh32(pRecord->internalUtilStats.minMBps); + pRecord->internalUtilStats.maxMBps = ntoh32(pRecord->internalUtilStats.maxMBps); + pRecord->internalUtilStats.numBWBuckets = ntoh32(pRecord->internalUtilStats.numBWBuckets); + for (i = 0; i < STL_PM_UTIL_BUCKETS; i++) + pRecord->internalUtilStats.BWBuckets[i] = ntoh32(pRecord->internalUtilStats.BWBuckets[i]); + pRecord->internalUtilStats.avgKPps = ntoh32(pRecord->internalUtilStats.avgKPps); + pRecord->internalUtilStats.minKPps = ntoh32(pRecord->internalUtilStats.minKPps); + pRecord->internalUtilStats.maxKPps = ntoh32(pRecord->internalUtilStats.maxKPps); + pRecord->internalUtilStats.pmaNoRespPorts = ntoh16(pRecord->internalUtilStats.pmaNoRespPorts); + pRecord->internalUtilStats.topoIncompPorts = ntoh16(pRecord->internalUtilStats.topoIncompPorts); + + pRecord->sendUtilStats.totalMBps = ntoh64(pRecord->sendUtilStats.totalMBps); + pRecord->sendUtilStats.totalKPps = ntoh64(pRecord->sendUtilStats.totalKPps); + pRecord->sendUtilStats.avgMBps = ntoh32(pRecord->sendUtilStats.avgMBps); + pRecord->sendUtilStats.minMBps = ntoh32(pRecord->sendUtilStats.minMBps); + pRecord->sendUtilStats.maxMBps = ntoh32(pRecord->sendUtilStats.maxMBps); + pRecord->sendUtilStats.numBWBuckets = ntoh32(pRecord->sendUtilStats.numBWBuckets); + for (i = 0; i < STL_PM_UTIL_BUCKETS; i++) + pRecord->sendUtilStats.BWBuckets[i] = ntoh32(pRecord->sendUtilStats.BWBuckets[i]); + pRecord->sendUtilStats.avgKPps = ntoh32(pRecord->sendUtilStats.avgKPps); + pRecord->sendUtilStats.minKPps = ntoh32(pRecord->sendUtilStats.minKPps); + pRecord->sendUtilStats.maxKPps = ntoh32(pRecord->sendUtilStats.maxKPps); + pRecord->sendUtilStats.pmaNoRespPorts = ntoh16(pRecord->sendUtilStats.pmaNoRespPorts); + pRecord->sendUtilStats.topoIncompPorts = ntoh16(pRecord->sendUtilStats.topoIncompPorts); + + pRecord->recvUtilStats.totalMBps = ntoh64(pRecord->recvUtilStats.totalMBps); + pRecord->recvUtilStats.totalKPps = ntoh64(pRecord->recvUtilStats.totalKPps); + pRecord->recvUtilStats.avgMBps = ntoh32(pRecord->recvUtilStats.avgMBps); + pRecord->recvUtilStats.minMBps = ntoh32(pRecord->recvUtilStats.minMBps); + pRecord->recvUtilStats.maxMBps = ntoh32(pRecord->recvUtilStats.maxMBps); + pRecord->recvUtilStats.numBWBuckets = ntoh32(pRecord->recvUtilStats.numBWBuckets); + for (i = 0; i < STL_PM_UTIL_BUCKETS; i++) + pRecord->recvUtilStats.BWBuckets[i] = ntoh32(pRecord->recvUtilStats.BWBuckets[i]); + pRecord->recvUtilStats.avgKPps = ntoh32(pRecord->recvUtilStats.avgKPps); + pRecord->recvUtilStats.minKPps = ntoh32(pRecord->recvUtilStats.minKPps); + pRecord->recvUtilStats.maxKPps = ntoh32(pRecord->recvUtilStats.maxKPps); + pRecord->recvUtilStats.pmaNoRespPorts = ntoh16(pRecord->recvUtilStats.pmaNoRespPorts); + pRecord->recvUtilStats.topoIncompPorts = ntoh16(pRecord->recvUtilStats.topoIncompPorts); + + pRecord->internalCategoryStats.categoryMaximums.integrityErrors = ntoh32(pRecord->internalCategoryStats.categoryMaximums.integrityErrors); + pRecord->internalCategoryStats.categoryMaximums.congestion = ntoh32(pRecord->internalCategoryStats.categoryMaximums.congestion); + pRecord->internalCategoryStats.categoryMaximums.smaCongestion = ntoh32(pRecord->internalCategoryStats.categoryMaximums.smaCongestion); + pRecord->internalCategoryStats.categoryMaximums.bubble = ntoh32(pRecord->internalCategoryStats.categoryMaximums.bubble); + pRecord->internalCategoryStats.categoryMaximums.securityErrors = ntoh32(pRecord->internalCategoryStats.categoryMaximums.securityErrors); + pRecord->internalCategoryStats.categoryMaximums.routingErrors = ntoh32(pRecord->internalCategoryStats.categoryMaximums.routingErrors); + + pRecord->internalCategoryStats.categoryMaximums.utilizationPct10 = ntoh16(pRecord->internalCategoryStats.categoryMaximums.utilizationPct10); + pRecord->internalCategoryStats.categoryMaximums.discardsPct10 = ntoh16(pRecord->internalCategoryStats.categoryMaximums.discardsPct10); + + for (i = 0; i < STL_PM_CATEGORY_BUCKETS; i++) { + pRecord->internalCategoryStats.ports[i].integrityErrors = ntoh32(pRecord->internalCategoryStats.ports[i].integrityErrors); + pRecord->internalCategoryStats.ports[i].congestion = ntoh32(pRecord->internalCategoryStats.ports[i].congestion); + pRecord->internalCategoryStats.ports[i].smaCongestion = ntoh32(pRecord->internalCategoryStats.ports[i].smaCongestion); + pRecord->internalCategoryStats.ports[i].bubble = ntoh32(pRecord->internalCategoryStats.ports[i].bubble); + pRecord->internalCategoryStats.ports[i].securityErrors = ntoh32(pRecord->internalCategoryStats.ports[i].securityErrors); + pRecord->internalCategoryStats.ports[i].routingErrors = ntoh32(pRecord->internalCategoryStats.ports[i].routingErrors); + } + + pRecord->externalCategoryStats.categoryMaximums.integrityErrors = ntoh32(pRecord->externalCategoryStats.categoryMaximums.integrityErrors); + pRecord->externalCategoryStats.categoryMaximums.congestion = ntoh32(pRecord->externalCategoryStats.categoryMaximums.congestion); + pRecord->externalCategoryStats.categoryMaximums.smaCongestion = ntoh32(pRecord->externalCategoryStats.categoryMaximums.smaCongestion); + pRecord->externalCategoryStats.categoryMaximums.bubble = ntoh32(pRecord->externalCategoryStats.categoryMaximums.bubble); + pRecord->externalCategoryStats.categoryMaximums.securityErrors = ntoh32(pRecord->externalCategoryStats.categoryMaximums.securityErrors); + pRecord->externalCategoryStats.categoryMaximums.routingErrors = ntoh32(pRecord->externalCategoryStats.categoryMaximums.routingErrors); + + pRecord->externalCategoryStats.categoryMaximums.utilizationPct10 = ntoh16(pRecord->externalCategoryStats.categoryMaximums.utilizationPct10); + pRecord->externalCategoryStats.categoryMaximums.discardsPct10 = ntoh16(pRecord->externalCategoryStats.categoryMaximums.discardsPct10); + + for (i = 0; i < STL_PM_CATEGORY_BUCKETS; i++) { + pRecord->externalCategoryStats.ports[i].integrityErrors = ntoh32(pRecord->externalCategoryStats.ports[i].integrityErrors); + pRecord->externalCategoryStats.ports[i].congestion = ntoh32(pRecord->externalCategoryStats.ports[i].congestion); + pRecord->externalCategoryStats.ports[i].smaCongestion = ntoh32(pRecord->externalCategoryStats.ports[i].smaCongestion); + pRecord->externalCategoryStats.ports[i].bubble = ntoh32(pRecord->externalCategoryStats.ports[i].bubble); + pRecord->externalCategoryStats.ports[i].securityErrors = ntoh32(pRecord->externalCategoryStats.ports[i].securityErrors); + pRecord->externalCategoryStats.ports[i].routingErrors = ntoh32(pRecord->externalCategoryStats.ports[i].routingErrors); + } + pRecord->maxInternalMBps = ntoh32(pRecord->maxInternalMBps); + pRecord->maxExternalMBps = ntoh32(pRecord->maxExternalMBps); +#endif /* CPU_LE */ +} + +static __inline void +BSWAP_STL_PA_GROUP_LIST(STL_PA_GROUP_LIST *pRecord) +{ +#if CPU_LE +#endif /* CPU_LE */ +} + +static __inline void +BSWAP_STL_PA_GROUP_CONFIG_REQ(STL_PA_PM_GROUP_CFG_REQ *pRecord) +{ +#if CPU_LE + BSWAP_STL_PA_IMAGE_ID(&pRecord->imageId); +#endif /* CPU_LE */ +} + +static __inline void +BSWAP_STL_PA_GROUP_CONFIG_RSP(STL_PA_PM_GROUP_CFG_RSP *pRecord) +{ +#if CPU_LE + BSWAP_STL_PA_IMAGE_ID(&pRecord->imageId); + pRecord->nodeGUID = ntoh64(pRecord->nodeGUID); + pRecord->nodeLid = ntoh32(pRecord->nodeLid); +#endif /* CPU_LE */ +} + +static __inline void +BSWAP_STL_PA_GROUP_NODE_INFO_REQ(STL_PA_GROUP_NODEINFO_REQ *pRecord) +{ +#if CPU_LE + BSWAP_STL_PA_IMAGE_ID(&pRecord->imageId); + pRecord->nodeGUID = ntoh64(pRecord->nodeGUID); + pRecord->nodeLID = ntoh32(pRecord->nodeLID); +#endif /* CPU_LE */ +} + +static __inline void +BSWAP_STL_PA_GROUP_NODE_INFO_RSP(STL_PA_GROUP_NODEINFO_RSP *pRecord) +{ +#if CPU_LE + int i; + + BSWAP_STL_PA_IMAGE_ID(&pRecord->imageId); + pRecord->nodeGUID = ntoh64(pRecord->nodeGUID); + pRecord->nodeLID = ntoh32(pRecord->nodeLID); + for (i = 0; i < 4; i++) + pRecord->portSelectMask[i] = ntoh64(pRecord->portSelectMask[i]); +#endif /* CPU_LE */ +} + +static __inline void +BSWAP_STL_PA_GROUP_LINK_INFO_REQ(STL_PA_GROUP_LINKINFO_REQ *pRecord) +{ +#if CPU_LE + BSWAP_STL_PA_IMAGE_ID(&pRecord->imageId); + pRecord->lid = ntoh32(pRecord->lid); +#endif /* CPU_LE */ +} + +static __inline void +BSWAP_STL_PA_GROUP_LINK_INFO_RSP(STL_PA_GROUP_LINKINFO_RSP *pRecord) +{ +#if CPU_LE + BSWAP_STL_PA_IMAGE_ID(&pRecord->imageId); + pRecord->fromLID = ntoh32(pRecord->fromLID); + pRecord->toLID = ntoh32(pRecord->toLID); +#endif /* CPU_LE */ +} + +static __inline void +BSWAP_STL_PA_PORT_COUNTERS(STL_PORT_COUNTERS_DATA *pRecord) +{ +#if CPU_LE + pRecord->nodeLid = ntoh32(pRecord->nodeLid); + pRecord->flags = ntoh32(pRecord->flags); + pRecord->portXmitData = ntoh64(pRecord->portXmitData); + pRecord->portRcvData = ntoh64(pRecord->portRcvData); + pRecord->portXmitPkts = ntoh64(pRecord->portXmitPkts); + pRecord->portRcvPkts = ntoh64(pRecord->portRcvPkts); + pRecord->portMulticastXmitPkts = ntoh64(pRecord->portMulticastXmitPkts); + pRecord->portMulticastRcvPkts = ntoh64(pRecord->portMulticastRcvPkts); + pRecord->localLinkIntegrityErrors = ntoh64(pRecord->localLinkIntegrityErrors); + pRecord->fmConfigErrors = ntoh64(pRecord->fmConfigErrors); + pRecord->portRcvErrors = ntoh64(pRecord->portRcvErrors); + pRecord->excessiveBufferOverruns = ntoh64(pRecord->excessiveBufferOverruns); + pRecord->portRcvConstraintErrors = ntoh64(pRecord->portRcvConstraintErrors); + pRecord->portRcvSwitchRelayErrors = ntoh64(pRecord->portRcvSwitchRelayErrors); + pRecord->portXmitDiscards = ntoh64(pRecord->portXmitDiscards); + pRecord->portXmitConstraintErrors = ntoh64(pRecord->portXmitConstraintErrors); + pRecord->portRcvRemotePhysicalErrors = ntoh64(pRecord->portRcvRemotePhysicalErrors); + pRecord->swPortCongestion = ntoh64(pRecord->swPortCongestion); + pRecord->portXmitWait = ntoh64(pRecord->portXmitWait); + pRecord->portRcvFECN = ntoh64(pRecord->portRcvFECN); + pRecord->portRcvBECN = ntoh64(pRecord->portRcvBECN); + pRecord->portXmitTimeCong = ntoh64(pRecord->portXmitTimeCong); + pRecord->portXmitWastedBW = ntoh64(pRecord->portXmitWastedBW); + pRecord->portXmitWaitData = ntoh64(pRecord->portXmitWaitData); + pRecord->portRcvBubble = ntoh64(pRecord->portRcvBubble); + pRecord->portMarkFECN = ntoh64(pRecord->portMarkFECN); + pRecord->linkErrorRecovery = ntoh32(pRecord->linkErrorRecovery); + pRecord->linkDowned = ntoh32(pRecord->linkDowned); + BSWAP_STL_PA_IMAGE_ID(&pRecord->imageId); +#endif /* CPU_LE */ +} + +static __inline void +BSWAP_STL_PA_CLR_PORT_COUNTERS(STL_CLR_PORT_COUNTERS_DATA *pRecord) +{ +#if CPU_LE + pRecord->NodeLid = ntoh32(pRecord->NodeLid); + pRecord->CounterSelectMask.AsReg32 = ntoh32(pRecord->CounterSelectMask.AsReg32); +#endif /* CPU_LE */ +} + +static __inline void +BSWAP_STL_PA_CLR_ALL_PORT_COUNTERS(STL_CLR_ALL_PORT_COUNTERS_DATA *pRecord) +{ +#if CPU_LE + pRecord->CounterSelectMask.AsReg32 = ntoh32(pRecord->CounterSelectMask.AsReg32); +#endif /* CPU_LE */ +} + +static __inline void +BSWAP_STL_PA_PM_CFG(STL_PA_PM_CFG_DATA *pRecord) +{ +#if CPU_LE + pRecord->sweepInterval = ntoh32(pRecord->sweepInterval); + pRecord->maxClients = ntoh32(pRecord->maxClients); + pRecord->sizeHistory = ntoh32(pRecord->sizeHistory); + pRecord->sizeFreeze = ntoh32(pRecord->sizeFreeze); + pRecord->lease = ntoh32(pRecord->lease); + pRecord->pmFlags = ntoh32(pRecord->pmFlags); + pRecord->categoryThresholds.integrityErrors = ntoh32(pRecord->categoryThresholds.integrityErrors); + pRecord->categoryThresholds.congestion = ntoh32(pRecord->categoryThresholds.congestion); + pRecord->categoryThresholds.smaCongestion = ntoh32(pRecord->categoryThresholds.smaCongestion); + pRecord->categoryThresholds.bubble = ntoh32(pRecord->categoryThresholds.bubble); + pRecord->categoryThresholds.securityErrors = ntoh32(pRecord->categoryThresholds.securityErrors); + pRecord->categoryThresholds.routingErrors = ntoh32(pRecord->categoryThresholds.routingErrors); + pRecord->memoryFootprint = ntoh64(pRecord->memoryFootprint); + pRecord->maxAttempts = ntoh32(pRecord->maxAttempts); + pRecord->respTimeout = ntoh32(pRecord->respTimeout); + pRecord->minRespTimeout = ntoh32(pRecord->minRespTimeout); + pRecord->maxParallelNodes = ntoh32(pRecord->maxParallelNodes); + pRecord->pmaBatchSize = ntoh32(pRecord->pmaBatchSize); + // ErrorClear is uint8 +#endif /* CPU_LE */ +} + +static __inline void +BSWAP_STL_PA_FOCUS_PORTS_REQ(STL_FOCUS_PORTS_REQ *pRecord) +{ +#if CPU_LE + pRecord->select = ntoh32(pRecord->select); + pRecord->start = ntoh32(pRecord->start); + pRecord->range = ntoh32(pRecord->range); + BSWAP_STL_PA_IMAGE_ID(&pRecord->imageId); +#endif +} + + +static __inline void +BSWAP_STL_PA_FOCUS_PORTS_MULTISELECT_REQ(STL_FOCUS_PORTS_MULTISELECT_REQ *pRecord) +{ +#if CPU_LE + int i; + pRecord->start = ntoh32(pRecord->start); + pRecord->range = ntoh32(pRecord->range); + for (i = 0; i < MAX_NUM_FOCUS_PORT_TUPLES; i++) { + pRecord->tuple[i].select = ntoh32(pRecord->tuple[i].select); + pRecord->tuple[i].argument = ntoh64(pRecord->tuple[i].argument); + } + BSWAP_STL_PA_IMAGE_ID(&pRecord->imageId); +#endif +} + + +static __inline void +BSWAP_STL_PA_FOCUS_PORTS_RSP(STL_FOCUS_PORTS_RSP *pRecord) +{ +#if CPU_LE + pRecord->nodeLid = ntoh32(pRecord->nodeLid); + pRecord->value = ntoh64(pRecord->value); + pRecord->neighborLid = ntoh32(pRecord->neighborLid); + pRecord->neighborValue = ntoh64(pRecord->neighborValue); + pRecord->nodeGUID = ntoh64(pRecord->nodeGUID); + pRecord->neighborGuid = ntoh64(pRecord->neighborGuid); + BSWAP_STL_PA_IMAGE_ID(&pRecord->imageId); +#endif /* CPU_LE */ +} + + +static __inline void +BSWAP_STL_PA_FOCUS_PORTS_MULTISELECT_RSP(STL_FOCUS_PORTS_MULTISELECT_RSP *pRecord) +{ +#if CPU_LE + int i; + pRecord->nodeLid = ntoh32(pRecord->nodeLid); + pRecord->neighborLid = ntoh32(pRecord->neighborLid); + pRecord->nodeGUID = ntoh64(pRecord->nodeGUID); + pRecord->neighborGuid = ntoh64(pRecord->neighborGuid); + for (i = 0; i < MAX_NUM_FOCUS_PORT_TUPLES; i++) { + pRecord->value[i] = ntoh64(pRecord->value[i]); + pRecord->neighborValue[i] = ntoh64(pRecord->neighborValue[i]); + } + + BSWAP_STL_PA_IMAGE_ID(&pRecord->imageId); +#endif /* CPU_LE */ +} + + +static __inline void +BSWAP_STL_PA_IMAGE_INFO(STL_PA_IMAGE_INFO_DATA *pRecord) +{ +#if CPU_LE + int i; + BSWAP_STL_PA_IMAGE_ID(&pRecord->imageId); + pRecord->sweepStart = ntoh64(pRecord->sweepStart); + pRecord->sweepDuration = ntoh32(pRecord->sweepDuration); + pRecord->numHFIPorts = ntoh16(pRecord->numHFIPorts); + pRecord->numSwitchNodes = ntoh16(pRecord->numSwitchNodes); + pRecord->numSwitchPorts = ntoh32(pRecord->numSwitchPorts); + pRecord->numLinks = ntoh32(pRecord->numLinks); + pRecord->numSMs = ntoh32(pRecord->numSMs); + pRecord->numNoRespNodes = ntoh32(pRecord->numNoRespNodes); + pRecord->numNoRespPorts = ntoh32(pRecord->numNoRespPorts); + pRecord->numSkippedNodes = ntoh32(pRecord->numSkippedNodes); + pRecord->numSkippedPorts = ntoh32(pRecord->numSkippedPorts); + pRecord->numUnexpectedClearPorts = ntoh32(pRecord->numUnexpectedClearPorts); + pRecord->imageInterval = ntoh32(pRecord->imageInterval); + for (i = 0; i < 2; i++) { + pRecord->SMInfo[i].lid = ntoh32(pRecord->SMInfo[i].lid); + pRecord->SMInfo[i].smPortGuid = ntoh64(pRecord->SMInfo[i].smPortGuid); + } +#endif /* CPU_LE */ +} + +static __inline void +BSWAP_STL_PA_MOVE_FREEZE(STL_MOVE_FREEZE_DATA *pRecord) +{ +#if CPU_LE + BSWAP_STL_PA_IMAGE_ID(&pRecord->oldFreezeImage); + BSWAP_STL_PA_IMAGE_ID(&pRecord->newFreezeImage); +#endif /* CPU_LE */ +} + +static __inline void +BSWAP_STL_PA_VF_LIST(STL_PA_VF_LIST *pRecord) +{ +#if CPU_LE +#endif /* CPU_LE */ +} + +static __inline void +BSWAP_STL_PA_VF_INFO(STL_PA_VF_INFO_DATA *pRecord, boolean isRequest) +{ +#if CPU_LE + int i; + BSWAP_STL_PA_IMAGE_ID(&pRecord->imageId); + + if (isRequest) return; + + pRecord->numPorts = ntoh32(pRecord->numPorts); + + pRecord->internalUtilStats.totalMBps = ntoh64(pRecord->internalUtilStats.totalMBps); + pRecord->internalUtilStats.totalKPps = ntoh64(pRecord->internalUtilStats.totalKPps); + pRecord->internalUtilStats.avgMBps = ntoh32(pRecord->internalUtilStats.avgMBps); + pRecord->internalUtilStats.minMBps = ntoh32(pRecord->internalUtilStats.minMBps); + pRecord->internalUtilStats.maxMBps = ntoh32(pRecord->internalUtilStats.maxMBps); + pRecord->internalUtilStats.numBWBuckets = ntoh32(pRecord->internalUtilStats.numBWBuckets); + for (i = 0; i < STL_PM_UTIL_BUCKETS; i++) + pRecord->internalUtilStats.BWBuckets[i] = ntoh32(pRecord->internalUtilStats.BWBuckets[i]); + pRecord->internalUtilStats.avgKPps = ntoh32(pRecord->internalUtilStats.avgKPps); + pRecord->internalUtilStats.minKPps = ntoh32(pRecord->internalUtilStats.minKPps); + pRecord->internalUtilStats.maxKPps = ntoh32(pRecord->internalUtilStats.maxKPps); + pRecord->internalUtilStats.pmaNoRespPorts = ntoh16(pRecord->internalUtilStats.pmaNoRespPorts); + pRecord->internalUtilStats.topoIncompPorts = ntoh16(pRecord->internalUtilStats.topoIncompPorts); + + pRecord->internalCategoryStats.categoryMaximums.integrityErrors = ntoh32(pRecord->internalCategoryStats.categoryMaximums.integrityErrors); + pRecord->internalCategoryStats.categoryMaximums.congestion = ntoh32(pRecord->internalCategoryStats.categoryMaximums.congestion); + pRecord->internalCategoryStats.categoryMaximums.smaCongestion = ntoh32(pRecord->internalCategoryStats.categoryMaximums.smaCongestion); + pRecord->internalCategoryStats.categoryMaximums.bubble = ntoh32(pRecord->internalCategoryStats.categoryMaximums.bubble); + pRecord->internalCategoryStats.categoryMaximums.securityErrors = ntoh32(pRecord->internalCategoryStats.categoryMaximums.securityErrors); + pRecord->internalCategoryStats.categoryMaximums.routingErrors = ntoh32(pRecord->internalCategoryStats.categoryMaximums.routingErrors); + + pRecord->internalCategoryStats.categoryMaximums.utilizationPct10 = ntoh16(pRecord->internalCategoryStats.categoryMaximums.utilizationPct10); + pRecord->internalCategoryStats.categoryMaximums.discardsPct10 = ntoh16(pRecord->internalCategoryStats.categoryMaximums.discardsPct10); + + for (i = 0; i < STL_PM_CATEGORY_BUCKETS; i++) { + pRecord->internalCategoryStats.ports[i].integrityErrors = ntoh32(pRecord->internalCategoryStats.ports[i].integrityErrors); + pRecord->internalCategoryStats.ports[i].congestion = ntoh32(pRecord->internalCategoryStats.ports[i].congestion); + pRecord->internalCategoryStats.ports[i].smaCongestion = ntoh32(pRecord->internalCategoryStats.ports[i].smaCongestion); + pRecord->internalCategoryStats.ports[i].bubble = ntoh32(pRecord->internalCategoryStats.ports[i].bubble); + pRecord->internalCategoryStats.ports[i].securityErrors = ntoh32(pRecord->internalCategoryStats.ports[i].securityErrors); + pRecord->internalCategoryStats.ports[i].routingErrors = ntoh32(pRecord->internalCategoryStats.ports[i].routingErrors); + } + + pRecord->maxInternalMBps = ntoh32(pRecord->maxInternalMBps); +#endif /* CPU_LE */ +} + +static __inline void +BSWAP_STL_PA_VF_CFG_REQ(STL_PA_VF_CFG_REQ *pRecord) +{ +#if CPU_LE + BSWAP_STL_PA_IMAGE_ID(&pRecord->imageId); +#endif /* CPU_LE */ +} + +static __inline void +BSWAP_STL_PA_VF_CFG_RSP(STL_PA_VF_CFG_RSP *pRecord) +{ +#if CPU_LE + pRecord->nodeGUID = ntoh64(pRecord->nodeGUID); + pRecord->nodeLid = ntoh32(pRecord->nodeLid); + BSWAP_STL_PA_IMAGE_ID(&pRecord->imageId); +#endif /* CPU_LE */ +} + +static __inline void +BSWAP_STL_PA_VF_PORT_COUNTERS(STL_PA_VF_PORT_COUNTERS_DATA *pRecord) +{ +#if CPU_LE + pRecord->nodeLid = ntoh32(pRecord->nodeLid); + pRecord->flags = ntoh32(pRecord->flags); + pRecord->portVFXmitData = ntoh64(pRecord->portVFXmitData); + pRecord->portVFRcvData = ntoh64(pRecord->portVFRcvData); + pRecord->portVFXmitPkts = ntoh64(pRecord->portVFXmitPkts); + pRecord->portVFRcvPkts = ntoh64(pRecord->portVFRcvPkts); + pRecord->portVFXmitDiscards = ntoh16(pRecord->portVFXmitDiscards); + pRecord->swPortVFCongestion = ntoh64(pRecord->swPortVFCongestion); + pRecord->portVFXmitWait = ntoh64(pRecord->portVFXmitWait); + pRecord->portVFRcvFECN = ntoh64(pRecord->portVFRcvFECN); + pRecord->portVFRcvBECN = ntoh64(pRecord->portVFRcvBECN); + pRecord->portVFXmitTimeCong = ntoh64(pRecord->portVFXmitTimeCong); + pRecord->portVFXmitWastedBW = ntoh64(pRecord->portVFXmitWastedBW); + pRecord->portVFXmitWaitData = ntoh64(pRecord->portVFXmitWaitData); + pRecord->portVFRcvBubble = ntoh64(pRecord->portVFRcvBubble); + pRecord->portVFMarkFECN = ntoh64(pRecord->portVFMarkFECN); + BSWAP_STL_PA_IMAGE_ID(&pRecord->imageId); +#endif /* CPU_LE */ +} + +static __inline void +BSWAP_STL_PA_CLEAR_VF_PORT_COUNTERS(STL_PA_CLEAR_VF_PORT_COUNTERS_DATA *pRecord) +{ +#if CPU_LE + pRecord->nodeLid = ntoh32(pRecord->nodeLid); + pRecord->vfCounterSelectMask.AsReg32 = ntoh32(pRecord->vfCounterSelectMask.AsReg32); +#endif /* CPU_LE */ +} + +static __inline void +BSWAP_STL_PA_VF_FOCUS_PORTS_REQ(STL_PA_VF_FOCUS_PORTS_REQ *pRecord) +{ +#if CPU_LE + pRecord->select = ntoh32(pRecord->select); + pRecord->start = ntoh32(pRecord->start); + pRecord->range = ntoh32(pRecord->range); + BSWAP_STL_PA_IMAGE_ID(&pRecord->imageId); +#endif +} + +static __inline void +BSWAP_STL_PA_VF_FOCUS_PORTS_RSP(STL_PA_VF_FOCUS_PORTS_RSP *pRecord) +{ +#if CPU_LE + pRecord->nodeLid = ntoh32(pRecord->nodeLid); + pRecord->value = ntoh64(pRecord->value); + pRecord->neighborLid = ntoh32(pRecord->neighborLid); + pRecord->neighborValue = ntoh64(pRecord->neighborValue); + pRecord->nodeGUID = ntoh64(pRecord->nodeGUID); + pRecord->neighborGuid = ntoh64(pRecord->neighborGuid); + BSWAP_STL_PA_IMAGE_ID(&pRecord->imageId); +#endif /* CPU_LE */ +} + +/* Performance Analysis Response Structures */ +typedef struct _STL_PA_GROUP_LIST_RESULTS { + uint32 NumGroupListRecords; /* Number of PA Records returned */ + STL_PA_GROUP_LIST GroupListRecords[1]; /* list of PA records returned */ +} STL_PA_GROUP_LIST_RESULTS, *PSTL_PA_GROUP_LIST_RESULTS; + +typedef struct _STL_PA_GROUP_INFO_RESULTS { + uint32 NumGroupInfoRecords; /* Number of PA Records returned */ + STL_PA_PM_GROUP_INFO_DATA GroupInfoRecords[1]; /* list of PA records returned */ +} STL_PA_GROUP_INFO_RESULTS, *PSTL_PA_GROUP_INFO_RESULTS; + +typedef struct _STL_PA_GROUP_CONFIG_RESULTS { + uint32 NumGroupConfigRecords; /* Number of PA Records returned */ + STL_PA_PM_GROUP_CFG_RSP GroupConfigRecords[1]; /* list of PA records returned */ +} STL_PA_GROUP_CONFIG_RESULTS, *PSTL_PA_GROUP_CONFIG_RESULTS; + +typedef struct _STL_PA_GROUP_NODEINFO_RESULTS { + uint32 NumGroupNodeInfoRecords; /* Number of PA Records returned */ + STL_PA_GROUP_NODEINFO_RSP GroupNodeInfoRecords[1]; /* list of PA records returned */ +} STL_PA_GROUP_NODEINFO_RESULTS, *PSTL_PA_GROUP_NODEINFO_RESULTS; + +typedef struct _STL_PA_GROUP_LINKINFO_RESULTS { + uint32 NumGroupLinkInfoRecords; /* Number of PA Records returned */ + STL_PA_GROUP_LINKINFO_RSP GroupLinkInfoRecords[1]; /* list of PA records returned */ +} STL_PA_GROUP_LINKINFO_RESULTS, *PSTL_PA_GROUP_LINKINFO_RESULTS; + +typedef struct _STL_PA_PORT_COUNTERS_RESULTS { + uint32 NumPortCountersRecords; /* Number of PA Records returned */ + STL_PORT_COUNTERS_DATA PortCountersRecords[1]; /* list of PA records returned */ +} STL_PA_PORT_COUNTERS_RESULTS, *PSTL_PA_PORT_COUNTERS_RESULTS; + +typedef struct _STL_PA_CLR_PORT_COUNTERS_RESULTS { + uint32 NumClrPortCountersRecords; /* Number of PA Records returned */ + STL_CLR_PORT_COUNTERS_DATA ClrPortCountersRecords[1]; /* list of PA records returned */ +} STL_PA_CLR_PORT_COUNTERS_RESULTS, *PSTL_PA_CLR_PORT_COUNTERS_RESULTS; + +typedef struct _STL_PA_CLR_ALL_PORT_COUNTERS_RESULTS { + uint32 NumClrAllPortCountersRecords; /* Number of PA Records returned */ + STL_CLR_ALL_PORT_COUNTERS_DATA ClrAllPortCountersRecords[1]; /* list of PA records returned */ +} STL_PA_CLR_ALL_PORT_COUNTERS_RESULTS, *PSTL_PA_CLR_ALL_PORT_COUNTERS_RESULTS; + +typedef struct _STL_PA_PM_CONFIG_RESULTS { + uint32 NumPmConfigRecords; /* Number of PA Records returned */ + STL_PA_PM_CFG_DATA PmConfigRecords[1]; /* list of PA records returned */ +} STL_PA_PM_CONFIG_RESULTS, *PSTL_PA_PM_CONFIG_RESULTS; + +typedef struct _STL_PA_IMAGE_ID_RESULTS { + uint32 NumImageIDRecords; /* Number of PA Records returned */ + STL_PA_IMAGE_ID_DATA ImageIDRecords[1]; /* list of PA records returned */ +} STL_PA_IMAGE_ID_RESULTS, *PSTL_PA_IMAGE_ID_RESULTS; + +typedef struct _STL_PA_FOCUS_PORTS_RESULTS { + uint32 NumFocusPortsRecords; /* Number of PA Records returned */ + STL_FOCUS_PORTS_RSP FocusPortsRecords[1]; /* list of PA records returned */ +} STL_PA_FOCUS_PORTS_RESULTS, *PSTL_PA_FOCUS_PORTS_RESULTS; + +typedef struct _STL_PA_FOCUS_PORTS_MULTISELECT_RESULTS { + uint32 NumFocusPortsRecords; /* Number of PA Records returned */ + STL_FOCUS_PORTS_MULTISELECT_RSP FocusPortsRecords[1]; /* list of PA records returned */ +} STL_PA_FOCUS_PORTS_MULTISELECT_RESULTS, *PSTL_PA_FOCUS_PORTS_RESULTS_MULTISELECT; + +typedef struct _STL_PA_IMAGE_INFO_RESULTS { + uint32 NumImageInfoRecords; /* Number of PA Records returned */ + STL_PA_IMAGE_INFO_DATA ImageInfoRecords[1]; /* list of PA records returned */ +} STL_PA_IMAGE_INFO_RESULTS, *PSTL_PA_IMAGE_INFO_RESULTS; + +typedef struct _STL_MOVE_FREEZE_RESULTS { + uint32 NumMoveFreezeRecords; /* Number of PA Records returned */ + STL_MOVE_FREEZE_DATA MoveFreezeRecords[1]; /* list of PA records returned */ +} STL_MOVE_FREEZE_RESULTS, *PSTL_PA_MOVE_FREEZE_RESULTS; + +typedef struct _STL_PA_VF_LIST_RESULTS { + uint32 NumVFListRecords; /* Number of PA Records returned */ + STL_PA_VF_LIST VFListRecords[1]; /* list of PA records returned */ +} STL_PA_VF_LIST_RESULTS, *PSTL_PA_VF_LIST_RESULTS; + +typedef struct _STL_PA_VF_INFO_RESULTS { + uint32 NumVFInfoRecords; /* Number of PA Records returned */ + STL_PA_VF_INFO_DATA VFInfoRecords[1]; /* list of PA records returned */ +} STL_PA_VF_INFO_RESULTS, *PSTL_PA_VF_INFO_RESULTS; + +typedef struct _STL_PA_VF_CONFIG_RESULTS { + uint32 NumVFConfigRecords; /* Number of PA Records returned */ + STL_PA_VF_CFG_RSP VFConfigRecords[1]; /* list of PA records returned */ +} STL_PA_VF_CONFIG_RESULTS, *PSTL_PA_VF_CONFIG_RESULTS; + +typedef struct _STL_PA_VF_FOCUS_PORTS_RESULTS { + uint32 NumVFFocusPortsRecords; /* Number of PA Records returned */ + STL_PA_VF_FOCUS_PORTS_RSP FocusPortsRecords[1]; /* list of PA records returned */ +} STL_PA_VF_FOCUS_PORTS_RESULTS, *PSTL_PA_VF_FOCUS_PORTS_RESULTS; + +typedef struct _STL_PA_GROUP_LIST2_RESULTS { + uint32 NumGroupList2Records; /* Number of PA Records returned */ + STL_PA_GROUP_LIST2 GroupList2Records[1]; /* list of PA records returned */ +} STL_PA_GROUP_LIST2_RESULTS, *PSTL_PA_GROUP_LIST2_RESULTS; + +typedef struct _STL_PA_VF_LIST2_RESULTS { + uint32 NumVFList2Records; /* Number of PA Records returned */ + STL_PA_VF_LIST2 VFList2Records[1]; /* list of PA records returned */ +} STL_PA_VF_LIST2_RESULTS, *PSTL_PA_VF_LIST2_RESULTS; + +/* PortXmitData and PortRcvData are in units of flits (8 bytes) */ +#define FLITS_PER_MiB ((uint64)1024*(uint64)1024/(uint64)8) +#define FLITS_PER_MB ((uint64)1000*(uint64)1000/(uint64)8) + +#ifdef __cplusplus +} +#endif + +#endif /* _STL_PA_PRIV_H_ */ diff --git a/IbAccess/Common/Inc/stl_pa_types.h b/IbAccess/Common/Inc/stl_pa_types.h new file mode 100644 index 0000000..8619c5c --- /dev/null +++ b/IbAccess/Common/Inc/stl_pa_types.h @@ -0,0 +1,877 @@ +/* BEGIN_ICS_COPYRIGHT7 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT7 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +#ifndef _STL_PA_TYPES_H_ +#define _STL_PA_TYPES_H_ (1) /* suppress duplicate loading of this file */ + +#include "iba/public/datatypes.h" +#include "iba/public/ibyteswap.h" +#include "iba/stl_mad_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#include "iba/public/ipackon.h" + +// XML Defines +#define STL_PM_MAX_DG_PER_PMPG 5 //Maximum number of Monitors allowed in a PmPortGroup + +/** PA MAD Payloads */ +#define STL_PM_GROUPNAMELEN 64 +#define STL_PM_NODEDESCLEN 64 +#define STL_PM_MAX_GROUPS 10 +#define STL_PM_VFNAMELEN 64 +#define STL_PM_MAX_VFS 32 + +#define STL_PM_UTIL_GRAN_PERCENT 10 /* granularity of utilization buckets */ +#define STL_PM_UTIL_BUCKETS (100 / STL_PM_UTIL_GRAN_PERCENT) + +#define STL_PM_CAT_GRAN_PERCENT 25 /* granularity of error buckets */ +#define STL_PM_CATEGORY_BUCKETS ((100 / STL_PM_CAT_GRAN_PERCENT) + 1) // extra bucket is for those over threshold + +/* ClassPortInfo Capability bits */ + +typedef STL_FIELDUNION8(STL_PA_CLASS_PORT_INFO_CAPABILITY_MASK, 16, + Reserved1: 2, /* start of class dependent bits */ + IsPerImageListsSupported: 1, /* query to get group/vf list from specific images */ + IsVFFocusTypesSupported: 1, /* VF level Focus types */ + IsTopologyInfoSupported: 1, /* query to get the topology info from PM */ + /* (GetGroupNodeInfo and GetGroupLinkInfo) */ + IsExtFocusTypesSupported: 1, /* RO - PA supports extended focus types */ + /* (unexpclrport, norespport and */ + /* skippedport) in GetFocusPorts and */ + /* adds GetFocusPortsMultiSelect */ + Reserved3: 1, + IsAbsTimeQuerySupported: 1, /* RO - PA supports AbsImageTime queries w/ absoluteTime in Image ID */ + Reserved2: 8); /* class independent bits*/ + +/* + * PA capability mask defines + */ +#define STL_PA_CPI_CAPMASK_ABSTIMEQUERY 0x0100 +#define STL_PA_CPI_CAPMASK_EXT_FOCUSTYPES 0x0400 +#define STL_PA_CPI_CAPMASK_TOPO_INFO 0x0800 +#define STL_PA_CPI_CAPMASK_VF_FOCUSTYPES 0x1000 +#define STL_PA_CPI_CAPMASK_IMAGE_LISTS 0x2000 + +static __inline void +StlPaClassPortInfoCapMask(char buf[80], uint16 cmask) +{ + if (!cmask) { + snprintf(buf, 80, "-"); + } else { + snprintf(buf, 80, "%s%s%s%s%s%s%s%s", + (cmask & STL_CLASS_PORT_CAPMASK_TRAP) ? "Trap " : "", + (cmask & STL_CLASS_PORT_CAPMASK_NOTICE) ? "Notice " : "", + (cmask & STL_CLASS_PORT_CAPMASK_CM2) ? "CapMask2 " : "", + /* Class Specific */ + (cmask & STL_PA_CPI_CAPMASK_ABSTIMEQUERY) ? "AbsTime " : "", + (cmask & STL_PA_CPI_CAPMASK_EXT_FOCUSTYPES) ? "ExtFocusTypes " : "", + (cmask & STL_PA_CPI_CAPMASK_TOPO_INFO) ? "TopologyInfo " : "", + (cmask & STL_PA_CPI_CAPMASK_VF_FOCUSTYPES) ? "VFFocusTypes " : "", + (cmask & STL_PA_CPI_CAPMASK_IMAGE_LISTS) ? "ImageLists " : ""); + } +} + +static __inline void +StlPaClassPortInfoCapMask2(char buf[80], uint32 cmask) +{ + if (!cmask) { + snprintf(buf, 80, "-"); + } else { + buf[0] = '\0'; + } +} + +// Check to see if the Focus Select has no Value +#define IS_FOCUS_SELECT_NO_VAL(SELECT) \ + ((SELECT == STL_PA_SELECT_UNEXP_CLR_PORT) || \ + (SELECT == STL_PA_SELECT_NO_RESP_PORT) || \ + (SELECT == STL_PA_SELECT_SKIPPED_PORT)) + +// Check to see if the Focus select is an UTIL BW category +#define IS_FOCUS_SELECT_UTIL(SELECT) \ + ((SELECT == STL_PA_SELECT_UTIL_HIGH) || \ + (SELECT == STL_PA_SELECT_UTIL_LOW) || \ + (SELECT == STL_PA_SELECT_VF_UTIL_HIGH) || \ + (SELECT == STL_PA_SELECT_VF_UTIL_LOW)) + +// Check to see if it is a VF Focus select +#define IS_VF_FOCUS_SELECT(SELECT) \ + ((SELECT == STL_PA_SELECT_VF_UTIL_HIGH) || \ + (SELECT == STL_PA_SELECT_VF_UTIL_LOW) || \ + (SELECT == STL_PA_SELECT_VF_UTIL_PKTS_HIGH) || \ + (SELECT == STL_PA_SELECT_CATEGORY_VF_BUBBLE) || \ + (SELECT == STL_PA_SELECT_CATEGORY_VF_CONG)) + +typedef struct _STL_PA_Group_List { + char groupName[STL_PM_GROUPNAMELEN]; // \0 terminated - actual number indicated by numGroups +} PACK_SUFFIX STL_PA_GROUP_LIST; + +#define PACLIENT_IMAGE_CURRENT 0 // imageNumber of most recent sweep image +#define PACLIENT_IMAGE_TIMED -1 // imageNumber of Image with particular time + +typedef struct _STL_PA_Image_ID_Data { + uint64 imageNumber; + int32 imageOffset; + union { + uint32 absoluteTime; + int32 timeOffset; + } PACK_SUFFIX imageTime; +} PACK_SUFFIX STL_PA_IMAGE_ID_DATA; + +/* Utilization statistical summary */ +typedef struct _STL_PA_PM_Util_Stats { + uint64 totalMBps; /* MB per sec */ + uint64 totalKPps; /* K pkts per sec */ + uint32 avgMBps; + uint32 minMBps; + uint32 maxMBps; + uint32 numBWBuckets; + uint32 BWBuckets[STL_PM_UTIL_BUCKETS]; + uint32 avgKPps; + uint32 minKPps; + uint32 maxKPps; + uint16 pmaNoRespPorts; + uint16 topoIncompPorts; +} PACK_SUFFIX STL_PA_PM_UTIL_STATS; + +/* Error statistical summary */ +typedef struct _STL_PA_PM_CATEGORY_SUMMARY { + uint32 integrityErrors; + uint32 congestion; + uint32 smaCongestion; + uint32 bubble; + uint32 securityErrors; + uint32 routingErrors; + + uint16 utilizationPct10; /* in units of 10% */ + uint16 discardsPct10; /* in units of 10% */ + uint16 reserved[6]; +} PACK_SUFFIX STL_PA_PM_CATEGORY_SUMMARY; + +typedef struct _STL_PM_CATEGORY_THRESHOLD { + uint32 integrityErrors; + uint32 congestion; + uint32 smaCongestion; + uint32 bubble; + uint32 securityErrors; + uint32 routingErrors; +} PACK_SUFFIX STL_PM_CATEGORY_THRESHOLD; + +typedef struct _STL_PM_CATEGORY_BUCKET { + uint32 integrityErrors; + uint32 congestion; + uint32 smaCongestion; + uint32 bubble; + uint32 securityErrors; + uint32 routingErrors; +} PACK_SUFFIX STL_PM_CATEGORY_BUCKET; + +typedef struct _STL_PM_CATEGORY_STATS { + STL_PA_PM_CATEGORY_SUMMARY categoryMaximums; + STL_PM_CATEGORY_BUCKET ports[STL_PM_CATEGORY_BUCKETS]; +} PACK_SUFFIX STL_PM_CATEGORY_STATS; + +typedef struct _STL_PA_Group_Info_Data { + char groupName[STL_PM_GROUPNAMELEN]; // \0 terminated. + STL_PA_IMAGE_ID_DATA imageId; + uint32 numInternalPorts; + uint32 numExternalPorts; + STL_PA_PM_UTIL_STATS internalUtilStats; + STL_PA_PM_UTIL_STATS sendUtilStats; + STL_PA_PM_UTIL_STATS recvUtilStats; + STL_PM_CATEGORY_STATS internalCategoryStats; + STL_PM_CATEGORY_STATS externalCategoryStats; + uint8 maxInternalRate; + uint8 minInternalRate; + uint8 maxExternalRate; + uint8 minExternalRate; + uint32 maxInternalMBps; + uint32 maxExternalMBps; +} PACK_SUFFIX STL_PA_PM_GROUP_INFO_DATA; + +typedef struct _STL_PA_Group_Cfg_Req { + char groupName[STL_PM_GROUPNAMELEN]; // \0 terminated. + STL_PA_IMAGE_ID_DATA imageId; +} PACK_SUFFIX STL_PA_PM_GROUP_CFG_REQ; + +typedef struct _STL_PA_Group_Cfg_Rsp { + STL_PA_IMAGE_ID_DATA imageId; + uint64 nodeGUID; + char nodeDesc[STL_PM_NODEDESCLEN]; // \0 terminated. + STL_LID nodeLid; + uint8 portNumber; + uint8 reserved[3]; +} PACK_SUFFIX STL_PA_PM_GROUP_CFG_RSP; + + +// STL_PORT_COUNTERS_DATA.flags +#define STL_PA_PC_FLAG_DELTA 0x00000001 // are these DELTA(1) or running totals +#define STL_PA_PC_FLAG_UNEXPECTED_CLEAR 0x00000002 // was there an unexpected clear +#define STL_PA_PC_FLAG_SHARED_VL 0x00000004 // for vf port counters, vl is shared >1 vf +#define STL_PA_PC_FLAG_USER_COUNTERS 0x00000008 // for PA user controlled running counters +#define STL_PA_PC_FLAG_CLEAR_FAIL 0x00000010 // indicates clear query failed however, data should be valid + + +typedef struct _STL_PORT_COUNTERS_DATA { + STL_LID nodeLid; + uint8 portNumber; + uint8 reserved[3]; + uint32 flags; + uint32 reserved1; + uint64 reserved3; + STL_PA_IMAGE_ID_DATA imageId; + uint64 portXmitData; + uint64 portRcvData; + uint64 portXmitPkts; + uint64 portRcvPkts; + uint64 portMulticastXmitPkts; + uint64 portMulticastRcvPkts; + uint64 localLinkIntegrityErrors; + uint64 fmConfigErrors; + uint64 portRcvErrors; + uint64 excessiveBufferOverruns; + uint64 portRcvConstraintErrors; + uint64 portRcvSwitchRelayErrors; + uint64 portXmitDiscards; + uint64 portXmitConstraintErrors; + uint64 portRcvRemotePhysicalErrors; + uint64 swPortCongestion; + uint64 portXmitWait; + uint64 portRcvFECN; + uint64 portRcvBECN; + uint64 portXmitTimeCong; + uint64 portXmitWastedBW; + uint64 portXmitWaitData; + uint64 portRcvBubble; + uint64 portMarkFECN; + uint32 linkErrorRecovery; + uint32 linkDowned; + uint8 uncorrectableErrors; + union { + uint8 AsReg8; + struct { IB_BITFIELD3(uint8, + numLanesDown : 4, + reserved : 1, + linkQualityIndicator : 3) + } PACK_SUFFIX s; + } lq; + uint8 reserved2[6]; +} PACK_SUFFIX STL_PORT_COUNTERS_DATA; + +typedef union { + uint32 AsReg32; + + struct stl_counter_select_mask { IB_BITFIELD28(uint32, + PortXmitData : 1, + PortRcvData : 1, + PortXmitPkts : 1, + PortRcvPkts : 1, + PortMulticastXmitPkts : 1, + PortMulticastRcvPkts : 1, + PortXmitWait : 1, + SwPortCongestion : 1, + PortRcvFECN : 1, + PortRcvBECN : 1, + PortXmitTimeCong : 1, + PortXmitWastedBW : 1, + PortXmitWaitData : 1, + PortRcvBubble : 1, + PortMarkFECN : 1, + PortRcvConstraintErrors : 1, + PortRcvSwitchRelayErrors : 1, + PortXmitDiscards : 1, + PortXmitConstraintErrors : 1, + PortRcvRemotePhysicalErrors : 1, + LocalLinkIntegrityErrors : 1, + PortRcvErrors : 1, + ExcessiveBufferOverruns : 1, + FMConfigErrors : 1, + LinkErrorRecovery : 1, + LinkDowned : 1, + UncorrectableErrors : 1, + Reserved : 5) + } PACK_SUFFIX s; + +} CounterSelectMask_t; + +typedef struct _STL_CLR_PORT_COUNTERS_DATA { + STL_LID NodeLid; + uint8 PortNumber; + uint8 Reserved[3]; + uint64 Reserved2; + CounterSelectMask_t CounterSelectMask; +} PACK_SUFFIX STL_CLR_PORT_COUNTERS_DATA; + +typedef struct _STL_CLR_ALL_PORT_COUNTERS_DATA { + CounterSelectMask_t CounterSelectMask; +} PACK_SUFFIX STL_CLR_ALL_PORT_COUNTERS_DATA; + +typedef struct _STL_INTEGRITY_WEIGHTS { + uint8 LocalLinkIntegrityErrors; + uint8 PortRcvErrors; + uint8 ExcessiveBufferOverruns; + uint8 LinkErrorRecovery; + uint8 LinkDowned; + uint8 UncorrectableErrors; + uint8 FMConfigErrors; + uint8 LinkQualityIndicator; + uint8 LinkWidthDowngrade; + uint8 reserved[7]; +} PACK_SUFFIX STL_INTEGRITY_WEIGHTS_T; + +typedef struct _STL_PM_CATEGORY_THRESHOLDS { + uint32 integrityErrors; + uint32 congestion; + uint32 smaCongestion; + uint32 bubble; + uint32 securityErrors; + uint32 routingErrors; +} PACK_SUFFIX STL_PM_CATEGORY_THRESHOLDS; + +typedef struct _STL_CONGESTION_WEIGHTS { + uint8 PortXmitWait; + uint8 SwPortCongestion; + uint8 PortRcvFECN; + uint8 PortRcvBECN; + uint8 PortXmitTimeCong; + uint8 PortMarkFECN; + uint16 reserved; +} PACK_SUFFIX STL_CONGESTION_WEIGHTS_T; + +/* + * PM configuration flags. + */ +#define STL_PM_NONE 0x0 +#define STL_PM_PROCESS_VL_COUNTERS 0x00000001 // Enable Processing of VL Counters +#define STL_PM_PROCESS_HFI_COUNTERS 0x00000002 // Enable Processing of HFI Counters +#define STL_PM_PROCESS_CLR_DATA_COUNTERS 0x00000004 // Enable Clearing of Data Counters +#define STL_PM_PROCESS_CLR_64BIT_COUNTERS 0x00000008 // Enable Clearing of 64 bit Error Counters +#define STL_PM_PROCESS_CLR_32BIT_COUNTERS 0x00000010 // Enable Clearing of 32 bit Error Counters +#define STL_PM_PROCESS_CLR_8BIT_COUNTERS 0x00000020 // Enable Clearing of 8 bit Error Counters +#define STL_PM_PROCESS_ERRORINFO 0x00000040 // Enable Getting/Clearing of Error Info + +static __inline +void StlFormatPmFlags(char buf[80], uint32 pmFlags) +{ + snprintf(buf, 80, "%s=%s %s=%s %s=%s %s=%s", + "ProcessHFICntrs", pmFlags & STL_PM_PROCESS_HFI_COUNTERS ? "On" : "Off", + "ProcessVLCntrs", pmFlags & STL_PM_PROCESS_VL_COUNTERS ? "On" : "Off", + "ClrDataCntrs", pmFlags & STL_PM_PROCESS_CLR_DATA_COUNTERS ? "On" : "Off", + "Clr64bitErrCntrs", pmFlags & STL_PM_PROCESS_CLR_64BIT_COUNTERS ? "On" : "Off"); +} + +static __inline +void StlFormatPmFlags2(char buf[80], uint32 pmFlags) +{ + snprintf(buf, 80, "%s=%s %s=%s %s=%s", + "Clr32bitErrCntrs", pmFlags & STL_PM_PROCESS_CLR_32BIT_COUNTERS ? "On" : "Off", + "Clr8bitErrCntrs", pmFlags & STL_PM_PROCESS_CLR_8BIT_COUNTERS ? "On" : "Off", + "ProcessErrorInfo", pmFlags & STL_PM_PROCESS_ERRORINFO ? "On" : "Off"); +} + +typedef struct _STL_PA_PM_Cfg_Data { + uint32 sweepInterval; + uint32 maxClients; + uint32 sizeHistory; + uint32 sizeFreeze; + uint32 lease; + uint32 pmFlags; + STL_CONGESTION_WEIGHTS_T congestionWeights; + STL_PM_CATEGORY_THRESHOLDS categoryThresholds; + STL_INTEGRITY_WEIGHTS_T integrityWeights; + uint64 memoryFootprint; + uint32 maxAttempts; + uint32 respTimeout; + uint32 minRespTimeout; + uint32 maxParallelNodes; + uint32 pmaBatchSize; + uint8 errorClear; + uint8 reserved[3]; +} PACK_SUFFIX STL_PA_PM_CFG_DATA; + +typedef struct _STL_MOVE_FREEZE_DATA { + STL_PA_IMAGE_ID_DATA oldFreezeImage; + STL_PA_IMAGE_ID_DATA newFreezeImage; +} PACK_SUFFIX STL_MOVE_FREEZE_DATA; + +#define STL_PA_SELECT_UNEXP_CLR_PORT 0x00010101 +#define STL_PA_SELECT_NO_RESP_PORT 0x00010102 +#define STL_PA_SELECT_SKIPPED_PORT 0x00010103 +#define STL_PA_SELECT_UTIL_HIGH 0x00020001 // highest first, descending +#define STL_PA_SELECT_UTIL_MC_HIGH 0x00020081 // not supported +#define STL_PA_SELECT_UTIL_PKTS_HIGH 0x00020082 +#define STL_PA_SELECT_VF_UTIL_HIGH 0x00020083 // Only used with VFs +#define STL_PA_SELECT_VF_UTIL_PKTS_HIGH 0x00020084 // Only used with VFs +#define STL_PA_SELECT_UTIL_LOW 0x00020101 // lowest first, ascending +#define STL_PA_SELECT_UTIL_MC_LOW 0x00020102 // not supported +#define STL_PA_SELECT_VF_UTIL_LOW 0x00020103 // Only used with VFs +#define STL_PA_SELECT_CATEGORY_INTEG 0x00030001 // hightest first, descending +#define STL_PA_SELECT_CATEGORY_CONG 0x00030002 +#define STL_PA_SELECT_CATEGORY_SMA_CONG 0x00030003 +#define STL_PA_SELECT_CATEGORY_BUBBLE 0x00030004 +#define STL_PA_SELECT_CATEGORY_SEC 0x00030005 +#define STL_PA_SELECT_CATEGORY_ROUT 0x00030006 +#define STL_PA_SELECT_CATEGORY_VF_CONG 0x00030007 // Only used with VFs +#define STL_PA_SELECT_CATEGORY_VF_BUBBLE 0x00030008 // Only used with VFs + +typedef struct _STL_FOCUS_PORTS_REQ { + char groupName[STL_PM_GROUPNAMELEN]; // \0 terminated + STL_PA_IMAGE_ID_DATA imageId; + uint32 select; + uint32 start; + uint32 range; +} PACK_SUFFIX STL_FOCUS_PORTS_REQ; + +typedef struct _STL_FOCUS_PORT_TUPLE { + uint32 select; + uint8 comparator; + uint8 reserved[3]; + uint64 argument; +} PACK_SUFFIX STL_FOCUS_PORT_TUPLE; + +#define MAX_NUM_FOCUS_PORT_TUPLES 8 + +#define FOCUS_PORTS_LOGICAL_OPERATOR_INVALID 0 +#define FOCUS_PORTS_LOGICAL_OPERATOR_AND 1 +#define FOCUS_PORTS_LOGICAL_OPERATOR_OR 2 + +#define FOCUS_PORTS_COMPARATOR_INVALID 0 +#define FOCUS_PORTS_COMPARATOR_GREATER_THAN 1 +#define FOCUS_PORTS_COMPARATOR_LESS_THAN 2 +#define FOCUS_PORTS_COMPARATOR_GREATER_THAN_OR_EQUAL 3 +#define FOCUS_PORTS_COMPARATOR_LESS_THAN_OR_EQUAL 4 + +typedef struct _STL_FOCUS_PORTS_MULTISELECT_REQ { + char groupName[STL_PM_GROUPNAMELEN]; // \0 terminated + STL_PA_IMAGE_ID_DATA imageId; + uint32 start; + uint32 range; + STL_FOCUS_PORT_TUPLE tuple[MAX_NUM_FOCUS_PORT_TUPLES]; + uint8 logical_operator; + uint8 reserved[7]; +} PACK_SUFFIX STL_FOCUS_PORTS_MULTISELECT_REQ; + +#define STL_PA_FOCUS_STATUS_OK 0 +#define STL_PA_FOCUS_STATUS_PMA_IGNORE 1 +#define STL_PA_FOCUS_STATUS_PMA_FAILURE 2 +#define STL_PA_FOCUS_STATUS_TOPO_FAILURE 3 +#define STL_PA_FOCUS_STATUS_UNEXPECTED_CLEAR 4 + +static __inline +const char* StlFocusStatusToText(uint8 status) +{ + switch (status) { + case STL_PA_FOCUS_STATUS_OK: return "OK"; + case STL_PA_FOCUS_STATUS_PMA_IGNORE: return "PMA Ignore"; + case STL_PA_FOCUS_STATUS_PMA_FAILURE: return "PMA Failure"; + case STL_PA_FOCUS_STATUS_TOPO_FAILURE: return "Topo Failure"; + case STL_PA_FOCUS_STATUS_UNEXPECTED_CLEAR: return "Unexp Clear"; + default: return "Unknown"; + } +} + +static __inline +const char* StlFocusAttributeToText(uint32 attribute) +{ + switch (attribute) { + case STL_PA_SELECT_UNEXP_CLR_PORT: return "Unexpected Clear"; + case STL_PA_SELECT_NO_RESP_PORT: return "No Response Ports"; + case STL_PA_SELECT_SKIPPED_PORT: return "Skipped Ports"; + case STL_PA_SELECT_UTIL_HIGH: return "High Utilization"; + case STL_PA_SELECT_UTIL_PKTS_HIGH: return "Packet Rate"; + case STL_PA_SELECT_UTIL_LOW: return "Low Utilization"; + case STL_PA_SELECT_VF_UTIL_HIGH: return "VF High Utilization"; + case STL_PA_SELECT_VF_UTIL_PKTS_HIGH: return "VF Packet Rate"; + case STL_PA_SELECT_VF_UTIL_LOW: return "VF Low Utilization"; + case STL_PA_SELECT_CATEGORY_INTEG: return "Integrity Errors"; + case STL_PA_SELECT_CATEGORY_CONG: return "Congestion"; + case STL_PA_SELECT_CATEGORY_SMA_CONG: return "SMA Congestion"; + case STL_PA_SELECT_CATEGORY_BUBBLE: return "Bubble"; + case STL_PA_SELECT_CATEGORY_SEC: return "Security Errors"; + case STL_PA_SELECT_CATEGORY_ROUT: return "Routing Errors"; + case STL_PA_SELECT_CATEGORY_VF_CONG: return "VF Congestion"; + case STL_PA_SELECT_CATEGORY_VF_BUBBLE:return "VF Bubble"; + default: return "Unknown"; + } +} + +static __inline +const char* StlComparatorToText(uint8 comparator) +{ + switch (comparator) { + case FOCUS_PORTS_COMPARATOR_GREATER_THAN: return "greater than"; + case FOCUS_PORTS_COMPARATOR_LESS_THAN: return "less than"; + case FOCUS_PORTS_COMPARATOR_GREATER_THAN_OR_EQUAL: return "greater than or equal to"; + case FOCUS_PORTS_COMPARATOR_LESS_THAN_OR_EQUAL: return "less than or equal to"; + case FOCUS_PORTS_COMPARATOR_INVALID: + default: return "invalid"; + } +} + +static __inline +const char* StlOperatorToText(uint8 logical_operator) +{ + switch (logical_operator) { + case FOCUS_PORTS_LOGICAL_OPERATOR_AND: return "AND"; + case FOCUS_PORTS_LOGICAL_OPERATOR_OR: return "OR"; + case FOCUS_PORTS_LOGICAL_OPERATOR_INVALID: + default: return "invalid"; + } +} + +typedef struct _STL_FOCUS_PORTS_RSP { + STL_PA_IMAGE_ID_DATA imageId; + STL_LID nodeLid; + uint8 portNumber; + uint8 rate; // IB_STATIC_RATE - 5 bit value + uint8 maxVlMtu; // enum IB_MTU - 4 bit value + IB_BITFIELD2(uint8, localStatus : 4, + neighborStatus : 4) + uint64 value; // list sorting factor + uint64 nodeGUID; + char nodeDesc[STL_PM_NODEDESCLEN]; // \0 terminated. + STL_LID neighborLid; + uint8 neighborPortNumber; + uint8 reserved3[3]; + uint64 neighborValue; + uint64 neighborGuid; + char neighborNodeDesc[STL_PM_NODEDESCLEN]; // \0 terminated. +} PACK_SUFFIX STL_FOCUS_PORTS_RSP; + +typedef struct _STL_FOCUS_PORTS_MULTISELECT_RSP { + STL_PA_IMAGE_ID_DATA imageId; + STL_LID nodeLid; + uint8 portNumber; + uint8 rate; // IB_STATIC_RATE - 5 bit value + uint8 maxVlMtu; // enum IB_MTU - 4 bit value + IB_BITFIELD2(uint8, localStatus : 4, + neighborStatus : 4) + uint64 value[MAX_NUM_FOCUS_PORT_TUPLES]; + uint64 nodeGUID; + char nodeDesc[STL_PM_NODEDESCLEN]; // \0 terminated. + STL_LID neighborLid; + uint8 neighborPortNumber; + uint8 reserved3[3]; + uint64 neighborValue[MAX_NUM_FOCUS_PORT_TUPLES]; + uint64 neighborGuid; + char neighborNodeDesc[STL_PM_NODEDESCLEN]; // \0 terminated. +} PACK_SUFFIX STL_FOCUS_PORTS_MULTISELECT_RSP; + +typedef struct _STL_SMINFO_DATA { + STL_LID lid; + IB_BITFIELD2(uint8, + priority : 4, + state : 4) + uint8 portNumber; + uint16 reserved; + uint64 smPortGuid; + char smNodeDesc[64]; // can be 64 char w/o \0 +} PACK_SUFFIX STL_SMINFO_DATA; + +typedef struct _STL_PA_IMAGE_INFO_DATA { + STL_PA_IMAGE_ID_DATA imageId; + uint64 sweepStart; + uint32 sweepDuration; + uint16 numHFIPorts; + uint16 reserved3; + uint16 reserved; + uint16 numSwitchNodes; + uint32 numSwitchPorts; + uint32 numLinks; + uint32 numSMs; + uint32 numNoRespNodes; + uint32 numNoRespPorts; + uint32 numSkippedNodes; + uint32 numSkippedPorts; + uint32 numUnexpectedClearPorts; + uint32 imageInterval; + STL_SMINFO_DATA SMInfo[2]; +} PACK_SUFFIX STL_PA_IMAGE_INFO_DATA; + +typedef struct _STL_PA_VF_LIST { + char vfName[STL_PM_VFNAMELEN]; // \0 terminated +} PACK_SUFFIX STL_PA_VF_LIST; + +typedef struct _STL_PA_VF_INFO_DATA { + char vfName[STL_PM_VFNAMELEN]; // \0 terminated + uint64 reserved; + STL_PA_IMAGE_ID_DATA imageId; + uint32 numPorts; + STL_PA_PM_UTIL_STATS internalUtilStats; + STL_PM_CATEGORY_STATS internalCategoryStats; + // these are added at the end to allow for forward and backward + // compatibility. + uint8 maxInternalRate; + uint8 minInternalRate; + uint32 maxInternalMBps; +} PACK_SUFFIX STL_PA_VF_INFO_DATA; + +typedef struct _STL_PA_VF_Cfg_Req { + char vfName[STL_PM_VFNAMELEN]; // \0 terminated + uint64 reserved; + STL_PA_IMAGE_ID_DATA imageId; +} PACK_SUFFIX STL_PA_VF_CFG_REQ; + +typedef struct _STL_PA_VF_Cfg_Rsp { + STL_PA_IMAGE_ID_DATA imageId; + uint64 nodeGUID; + char nodeDesc[STL_PM_NODEDESCLEN]; // \0 terminated. + STL_LID nodeLid; + uint8 portNumber; + uint8 reserved[3]; +} PACK_SUFFIX STL_PA_VF_CFG_RSP; + +typedef struct _STL_PA_VF_PORT_COUNTERS_DATA { + STL_LID nodeLid; + uint8 portNumber; + uint8 reserved[3]; + uint32 flags; + uint32 reserved1; + uint64 reserved3; + char vfName[STL_PM_VFNAMELEN]; // \0 terminated + uint64 reserved2; + STL_PA_IMAGE_ID_DATA imageId; + uint64 portVFXmitData; + uint64 portVFRcvData; + uint64 portVFXmitPkts; + uint64 portVFRcvPkts; + uint64 portVFXmitDiscards; + uint64 swPortVFCongestion; + uint64 portVFXmitWait; + uint64 portVFRcvFECN; + uint64 portVFRcvBECN; + uint64 portVFXmitTimeCong; + uint64 portVFXmitWastedBW; + uint64 portVFXmitWaitData; + uint64 portVFRcvBubble; + uint64 portVFMarkFECN; +} PACK_SUFFIX STL_PA_VF_PORT_COUNTERS_DATA; + +typedef union { + uint32 AsReg32; + struct { IB_BITFIELD15(uint32, + PortVLXmitData : 1, + PortVLRcvData : 1, + PortVLXmitPkts : 1, + PortVLRcvPkts : 1, + PortVLXmitDiscards : 1, + SwPortVLCongestion : 1, + PortVLXmitWait : 1, + PortVLRcvFECN : 1, + PortVLRcvBECN : 1, + PortVLXmitTimeCong : 1, + PortVLXmitWastedBW : 1, + PortVLXmitWaitData : 1, + PortVLRcvBubble : 1, + PortVLMarkFECN : 1, + reserved : 18) + } PACK_SUFFIX s; +} STLVlCounterSelectMask; + +typedef struct _STL_PA_CLEAR_VF_PORT_COUNTERS_DATA { + STL_LID nodeLid; + uint8 portNumber; + uint8 reserved[3]; + uint64 reserved4; + char vfName[STL_PM_VFNAMELEN]; // \0 terminated + uint64 reserved3; + STLVlCounterSelectMask vfCounterSelectMask; + uint32 reserved2; +} PACK_SUFFIX STL_PA_CLEAR_VF_PORT_COUNTERS_DATA; + +typedef struct _STL_PA_VF_FOCUS_PORTS_REQ { + char vfName[STL_PM_VFNAMELEN]; // \0 terminated + uint64 reserved; + STL_PA_IMAGE_ID_DATA imageId; + uint32 select; + uint32 start; + uint32 range; +} PACK_SUFFIX STL_PA_VF_FOCUS_PORTS_REQ; + +typedef struct _STL_PA_VF_FOCUS_PORTS_RSP { + STL_PA_IMAGE_ID_DATA imageId; + STL_LID nodeLid; + uint8 portNumber; + uint8 rate; // IB_STATIC_RATE - 5 bit value + uint8 maxVlMtu; // enum IB_MTU - 4 bit value + IB_BITFIELD2(uint8, localStatus : 4, + neighborStatus : 4) + uint64 value; // list sorting factor + uint64 nodeGUID; + char nodeDesc[STL_PM_NODEDESCLEN]; // \0 terminated. + STL_LID neighborLid; + uint8 neighborPortNumber; + uint8 reserved3[3]; + uint64 neighborValue; + uint64 neighborGuid; + char neighborNodeDesc[STL_PM_NODEDESCLEN]; // \0 terminated. +} PACK_SUFFIX STL_PA_VF_FOCUS_PORTS_RSP; + +typedef struct _STL_PA_Group_NodeInfo_Req { + char groupName[STL_PM_GROUPNAMELEN]; + STL_PA_IMAGE_ID_DATA imageId; + uint64 nodeGUID; + char nodeDesc[STL_PM_NODEDESCLEN]; + uint32 nodeLID; + uint32 reserved; +} PACK_SUFFIX STL_PA_GROUP_NODEINFO_REQ; + +typedef struct _STL_PA_Group_NodeInfo_Rsp { + STL_PA_IMAGE_ID_DATA imageId; + uint64 nodeGUID; + char nodeDesc[STL_PM_NODEDESCLEN]; + uint32 nodeLID; + uint8 nodeType; + uint8 reserved[3]; + uint64 portSelectMask[4]; +} PACK_SUFFIX STL_PA_GROUP_NODEINFO_RSP; + +typedef struct _STL_PA_Group_LinkInfo_Req { + STL_PA_IMAGE_ID_DATA imageId; + char groupName[STL_PM_GROUPNAMELEN]; + uint32 lid; + uint8 port; + uint8 reserved[3]; +} PACK_SUFFIX STL_PA_GROUP_LINKINFO_REQ; + +typedef struct _STL_PA_Group_LinkInfo_Rsp { + STL_PA_IMAGE_ID_DATA imageId; + uint32 fromLID; + uint32 toLID; + uint8 fromPort; + uint8 toPort; + IB_BITFIELD2( uint8, + mtu:4, + activeSpeed:4) + IB_BITFIELD2( uint8, + txLinkWidthDowngradeActive:4, + rxLinkWidthDowngradeActive:4) + IB_BITFIELD2(uint8, + localStatus : 4, + neighborStatus : 4) + uint8 reserved[3]; +} PACK_SUFFIX STL_PA_GROUP_LINKINFO_RSP; + + +typedef struct _STL_PA_GRP_LIST2 { + char groupName[STL_PM_GROUPNAMELEN]; // \0 terminated + STL_PA_IMAGE_ID_DATA imageId; +} PACK_SUFFIX STL_PA_GROUP_LIST2; + +typedef struct _STL_PA_VF_LIST2 { + char vfName[STL_PM_VFNAMELEN]; // \0 terminated + STL_PA_IMAGE_ID_DATA imageId; +} PACK_SUFFIX STL_PA_VF_LIST2; + + +/* End of packed data structures */ +#include "iba/public/ipackoff.h" + +/* Performance Analysis methods */ +#define STL_PA_CMD_GET (0x01) +#define STL_PA_CMD_SET (0x02) +#define STL_PA_CMD_GET_RESP (0x81) +#define STL_PA_CMD_GETTABLE (0x12) +#define STL_PA_CMD_GETTABLE_RESP (0x92) + +/* Performance Analysis attribute IDs */ +#define STL_PA_ATTRID_GET_CLASSPORTINFO 0x01 +#define STL_PA_ATTRID_GET_GRP_LIST 0xA0 +#define STL_PA_ATTRID_GET_GRP_INFO 0xA1 +#define STL_PA_ATTRID_GET_GRP_CFG 0xA2 +#define STL_PA_ATTRID_GET_PORT_CTRS 0xA3 +#define STL_PA_ATTRID_CLR_PORT_CTRS 0xA4 +#define STL_PA_ATTRID_CLR_ALL_PORT_CTRS 0xA5 +#define STL_PA_ATTRID_GET_PM_CONFIG 0xA6 +#define STL_PA_ATTRID_FREEZE_IMAGE 0xA7 +#define STL_PA_ATTRID_RELEASE_IMAGE 0xA8 +#define STL_PA_ATTRID_RENEW_IMAGE 0xA9 +#define STL_PA_ATTRID_GET_FOCUS_PORTS 0xAA +#define STL_PA_ATTRID_GET_IMAGE_INFO 0xAB +#define STL_PA_ATTRID_MOVE_FREEZE_FRAME 0xAC +#define STL_PA_ATTRID_GET_VF_LIST 0xAD +#define STL_PA_ATTRID_GET_VF_INFO 0xAE +#define STL_PA_ATTRID_GET_VF_CONFIG 0xAF +#define STL_PA_ATTRID_GET_VF_PORT_CTRS 0xB0 +#define STL_PA_ATTRID_CLR_VF_PORT_CTRS 0xB1 +#define STL_PA_ATTRID_GET_VF_FOCUS_PORTS 0xB2 +#define STL_PA_ATTRID_GET_FOCUS_PORTS_MULTISELECT 0xB4 +#define STL_PA_ATTRID_GET_GRP_NODE_INFO 0xB5 +#define STL_PA_ATTRID_GET_GRP_LINK_INFO 0xB6 +#define STL_PA_ATTRID_GET_GRP_LIST2 0xB7 +#define STL_PA_ATTRID_GET_VF_LIST2 0xB8 + +/* Performance Analysis MAD status values */ +#define STL_MAD_STATUS_STL_PA_UNAVAILABLE 0x0A00 // Engine unavailable +#define STL_MAD_STATUS_STL_PA_NO_GROUP 0x0B00 // No such group +#define STL_MAD_STATUS_STL_PA_NO_PORT 0x0C00 // Port not found +#define STL_MAD_STATUS_STL_PA_NO_VF 0x0D00 // VF not found +#define STL_MAD_STATUS_STL_PA_INVALID_PARAMETER 0x0E00 // Invalid parameter +#define STL_MAD_STATUS_STL_PA_NO_IMAGE 0x0F00 // Image not found +#define STL_MAD_STATUS_STL_PA_NO_DATA 0x1000 // No Data when port was not queried +#define STL_MAD_STATUS_STL_PA_BAD_DATA 0x1100 // Bad Data when query was unsuccessful + +/* PM Service Record values */ +#define STL_PM_SERVICE_NAME "Primary Intel OmniPath Performance Manager" +#define STL_PM_SERVICE_NAME_SEC "Secondary Intel OmniPath Performance Manager" +#define STL_PM_SERVICE_ID (0x1100d03c34845555ull) +#define STL_PM_SERVICE_ID_SEC (0x1100d03c34845555ull) +#define STL_PM_VERSION 0x01 +#define STL_PM_MASTER 0x01 /* master state */ +#define STL_PM_STANDBY 0x02 /* standby state */ + +#define STL_PA_DATA_OFFSET 32 + +#define STL_PA_CLASS_VERSION 0x80 + + + +/* LinkQualityIndicator values */ +#define STL_LINKQUALITY_EXCELLENT 5 /* working as intended */ +#define STL_LINKQUALITY_VERY_GOOD 4 /* slightly below preferred, */ + /* no action needed */ +#define STL_LINKQUALITY_GOOD 3 /* low end of acceptable, */ + /* recommend corrective action on */ + /* next maintenance window */ +#define STL_LINKQUALITY_POOR 2 /* below acceptable, */ + /* recommend timely corrective action */ +#define STL_LINKQUALITY_BAD 1 /* far below acceptable, */ + /* immediate corrective action */ +#define STL_LINKQUALITY_NONE 0 /* link down */ + +#ifdef __cplusplus +} +#endif + +#endif /* _STL_PA_TYPES_H_ */ diff --git a/IbAccess/Common/Inc/stl_pkt.h b/IbAccess/Common/Inc/stl_pkt.h new file mode 100644 index 0000000..c7bd29a --- /dev/null +++ b/IbAccess/Common/Inc/stl_pkt.h @@ -0,0 +1,243 @@ +/* BEGIN_ICS_COPYRIGHT5 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + * ** END_ICS_COPYRIGHT5 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +#ifndef _IBA_STL_PKT_H_ +#define _IBA_STL_PKT_H_ (1) + +#include "iba/ib_pkt.h" + +#if defined (__cplusplus) +extern "C" { +#endif + +#include "iba/public/ipackon.h" + +/* L2 Codes */ +#define STL_L2_8B 0x0 +#define STL_L2_10B 0x1 +#define STL_L2_16B 0x2 +#define STL_L2_9B 0x3 + +/* 9B LNH (L4) */ +#define STL_9B_LNH_BTH 0x2 +#define STL_9B_LNH_GRH 0x3 + +/* L4 Types */ +#define STL_L4_TYPE_FM (0x08) +#define STL_L4_TYPE_IB_LOCAL (0x09) +#define STL_L4_TYPE_IB_GLOBAL (0x0A) +#if defined(INCLUDE_STLEEP) +#define STL_L4_TYPE_STLEEP (0x78) +#define STL_L4_TYPE_STLEEP_EP (0x79) +#endif + + + +/* + * STL packet headers + */ + +/* + * 8B Header Format + */ +typedef struct _STL_8B_HDR { + STL_FIELDUNION4(u2, 32, + B:1, + L4:4, + Length:7, + SLID20:20); + STL_FIELDUNION6(u1, 32, + LT:1, + L2:2, + F:1, + RC:3, + SC:5, + DLID20:20); +} STL_8B_HDR; +static __inline void BSWAP_STL_8B_HDR( STL_8B_HDR *hdr) { +#if CPU_BE + hdr->u1.AsReg32 = le32toh(hdr->u1.AsReg32); + hdr->u2.AsReg32 = le32toh(hdr->u2.AsReg32); +#endif +} + +/* + * 9B Header Format + */ +typedef struct _STL_9B_HDR { + STL_FIELDUNION5(u1, 16, + LT:1, + L2:2, + Reserved_60_57:4, + ServiceChannel:5, + LinkVersion:4); + STL_FIELDUNION3(u2, 8, + ServiceLevel:4, + Reserved_43_42:2, + LNH:2); + STL_LID_16 DLID16; + STL_FIELDUNION2(u3, 16, + Reserved_23_20:4, + Length:12); + STL_LID_16 SLID16; +} STL_9B_HDR; + +static __inline void BSWAP_STL_9B_HDR( STL_9B_HDR *hdr) { +#if CPU_LE + hdr->u1.AsReg16 = ntoh16(hdr->u1.AsReg16); + hdr->DLID16 = ntoh16(hdr->DLID16); + hdr->u3.AsReg16 = ntoh16(hdr->u3.AsReg16); + hdr->SLID16 = ntoh16(hdr->SLID16); +#endif +} + +/* + * 10B Header Format + */ +typedef struct _STL_10B_HDR { + STL_FIELDUNION3(u2, 32, + B:1, + Length:11, + SLID20:20); + STL_FIELDUNION6(u1, 32, + LT:1, + L2:2, + F:1, + RC:3, + SC:5, + DLID20:20); + STL_FIELDUNION2(u3, 8, + Pkey:4, + L4:4); + uint8 Entropy; + +} STL_10B_HDR; + +static __inline void BSWAP_STL_10B_HDR( STL_10B_HDR *hdr) { +#if CPU_BE + hdr->u1.AsReg32 = le32toh(hdr->u1.AsReg32); + hdr->u2.AsReg32 = le32toh(hdr->u2.AsReg32); +#endif +} + +/* + * 16B Header Format + */ +typedef struct _STL_16B_HDR { + STL_FIELDUNION3(u2, 32, + B:1, + Length:11, + SLID_19_0:20); + STL_FIELDUNION6(u1, 32, + LT:1, + L2:2, + F:1, + RC:3, + SC:5, + DLID_19_0:20); + uint8 L4; + STL_FIELDUNION2(u3, 8, + DLID_23_20:4, + SLID_23_20:4); + uint16 Pkey; + uint16 Entropy; + uint8 Age; + uint8 Reserved; +} PACK_SUFFIX STL_16B_HDR; + +static __inline void BSWAP_STL_16B_HDR( STL_16B_HDR *hdr) { +#if CPU_BE + hdr->u1.AsReg32 = le32toh(hdr->u1.AsReg32); + hdr->u2.AsReg32 = le32toh(hdr->u2.AsReg32); + hdr->Entropy = le16toh(hdr->Entropy); + hdr->Pkey = le16toh(hdr->Pkey); +#endif +} + + +/* + * Base Transport Header for STL 16B + */ +typedef struct _STL_16B_BTH { + uint8 OpCode; + + struct _STL_16B_BTH_V {IB_BITFIELD3(uint8, + SolicitedEvent: 1, + PadCount: 3, + HeaderVersion: 4) /* Transport Header version */ + } v; + + uint16 Reserved; + + STL_FIELDUNION3(Qp, 32, + Migrate: 1, + Reserved: 7, + DestQPNumber: 24); + + STL_FIELDUNION2(Psn, 32, + AckReq: 1, + PSN: 31); +} PACK_SUFFIX STL_16B_BTH; +static __inline void BSWAP_STL_16B_BTH(STL_16B_BTH *bth) { +#if CPU_LE + bth->Qp.AsReg32 = ntoh32(bth->Qp.AsReg32); + bth->Psn.AsReg32 = ntoh32(bth->Psn.AsReg32); +#endif +} + + +/* + * L4 FM Header + */ +typedef struct _STL_FMH { + STL_FIELDUNION2(DestQP, 32, + Reserved: 8, + DestQPNumber: 24); + STL_FIELDUNION2(SrcQP, 32, + Reserved: 8, + SrcQPNumber: 24); +} PACK_SUFFIX STL_FMH; +static __inline void BSWAP_STL_FMH(STL_FMH *fm_hdr) { +#if CPU_LE + fm_hdr->DestQP.AsReg32 = ntoh32(fm_hdr->DestQP.AsReg32); + fm_hdr->SrcQP.AsReg32 = ntoh32(fm_hdr->SrcQP.AsReg32); +#endif +} + + +#include "iba/public/ipackoff.h" + +#if defined (__cplusplus) +}; +#endif + +#endif /* _IBA_STL_PKT_H_ */ + diff --git a/IbAccess/Common/Inc/stl_pm.h b/IbAccess/Common/Inc/stl_pm.h new file mode 100644 index 0000000..33be6cd --- /dev/null +++ b/IbAccess/Common/Inc/stl_pm.h @@ -0,0 +1,796 @@ +/* BEGIN_ICS_COPYRIGHT7 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT7 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +#ifndef __IBA_STL_PM_H__ +#define __IBA_STL_PM_H__ + +#include "iba/ib_generalServices.h" +#include "iba/stl_types.h" +#include "iba/stl_pa_types.h" +#include "iba/stl_helper.h" + +#if defined (__cplusplus) +extern "C" { +#endif + +#include "iba/public/ipackon.h" + +/* + * Defines + */ + +#define STL_PM_CLASS_VERSION 0x80 /* Performance Management version */ + +#define STL_PM_ATTRIB_ID_CLASS_PORTINFO 0x01 +#define STL_PM_ATTRIB_ID_PORT_STATUS 0x40 +#define STL_PM_ATTRIB_ID_CLEAR_PORT_STATUS 0x41 +#define STL_PM_ATTRIB_ID_DATA_PORT_COUNTERS 0x42 +#define STL_PM_ATTRIB_ID_ERROR_PORT_COUNTERS 0x43 +#define STL_PM_ATTRIB_ID_ERROR_INFO 0x44 + + +/* if AllPortSelect capability, use this as PortNum to operate on all ports */ +#define PM_ALL_PORT_SELECT 0xff + +enum PM_VLs { + PM_VL0 = 0, + PM_VL1 = 1, + PM_VL2 = 2, + PM_VL3 = 3, + PM_VL4 = 4, + PM_VL5 = 5, + PM_VL6 = 6, + PM_VL7 = 7, + PM_VL15 = 8, + MAX_PM_VLS = 9 +}; +static __inline uint32 vl_to_idx(uint32 vl) { + DEBUG_ASSERT(vl < PM_VL15 || vl == 15); + if (vl >= PM_VL15) return (uint32)PM_VL15; + return vl; +} +static __inline uint32 idx_to_vl(uint32 idx) { + DEBUG_ASSERT(idx < MAX_PM_VLS); + if (idx >= PM_VL15) return 15; + return idx; +} + +/* PortXmitData and PortRcvData are in units of flits (8 bytes) */ +#define FLITS_PER_MiB ((uint64)1024*(uint64)1024/(uint64)8) +#define FLITS_PER_MB ((uint64)1000*(uint64)1000/(uint64)8) + + +/* MAD status codes for PM */ +#define STL_PM_STATUS_REQUEST_TOO_LARGE 0x0100 /* response can't fit in a single MAD */ +#define STL_PM_STATUS_NUMBLOCKS_INCONSISTENT 0x0200 /* attribute modifier number of blocks inconsistent with number of ports/blocks in MAD */ +#define STL_PM_STATUS_OPERATION_FAILED 0x0300 /* an operation (such as clear counters) requested of the agent failed */ + + +static __inline void +StlPmClassPortInfoCapMask(char buf[80], uint16 cmask) +{ + if (!cmask) { + snprintf(buf, 80, "-"); + } else { + + snprintf(buf, 80, "%s%s%s", + (cmask & STL_CLASS_PORT_CAPMASK_TRAP) ? "Trap " : "", + (cmask & STL_CLASS_PORT_CAPMASK_NOTICE) ? "Notice " : "", + (cmask & STL_CLASS_PORT_CAPMASK_CM2) ? "CapMask2 " : ""); + } +} +static __inline void +StlPmClassPortInfoCapMask2(char buf[80], uint32 cmask) +{ + if (!cmask) { + snprintf(buf, 80, "-"); + } else { + buf[0] = '\0'; + } +} +static __inline const char * +StlPmMadMethodToText(uint8 method) { + switch (method) { + case MMTHD_GET: return "Get"; + case MMTHD_SET: return "Set"; + case MMTHD_GET_RESP: return "GetResp"; + default: return "Unknown"; + } +} +static __inline const char * +StlPmMadAttributeToText(uint16 aid) { + switch (aid) { + case STL_PM_ATTRIB_ID_CLASS_PORTINFO: return "ClassPortInfo"; + case STL_PM_ATTRIB_ID_PORT_STATUS: return "PortStatus"; + case STL_PM_ATTRIB_ID_CLEAR_PORT_STATUS: return "ClearPortStatus"; + case STL_PM_ATTRIB_ID_DATA_PORT_COUNTERS: return "DataPortCounters"; + case STL_PM_ATTRIB_ID_ERROR_PORT_COUNTERS: return "ErrorportCounters"; + case STL_PM_ATTRIB_ID_ERROR_INFO: return "ErrorInfo"; + default: return "Unknown"; + } +} + +/* MAD structure definitions */ +typedef struct _STL_PERF_MAD { + MAD_COMMON common; /* Generic MAD Header */ + + uint8 PerfData[STL_GS_DATASIZE]; /* Performance Management Data */ +} PACK_SUFFIX STL_PERF_MAD, *PSTL_PERF_MAD; + + +/* STL Port Counters - small request, large response */ +typedef struct _STL_Port_Status_Req { + uint8 PortNumber; + uint8 Reserved[3];; + uint32 VLSelectMask; +} PACK_SUFFIX STLPortStatusReq, STL_PORT_STATUS_REQ; + +typedef struct _STL_Port_Status_Rsp { + uint8 PortNumber; + uint8 Reserved[3]; + uint32 VLSelectMask; + uint64 PortXmitData; + uint64 PortRcvData; + uint64 PortXmitPkts; + uint64 PortRcvPkts; + uint64 PortMulticastXmitPkts; + uint64 PortMulticastRcvPkts; + uint64 PortXmitWait; + uint64 SwPortCongestion; + uint64 PortRcvFECN; + uint64 PortRcvBECN; + uint64 PortXmitTimeCong; + uint64 PortXmitWastedBW; + uint64 PortXmitWaitData; + + uint64 PortRcvBubble; + uint64 PortMarkFECN; + uint64 PortRcvConstraintErrors; + uint64 PortRcvSwitchRelayErrors; + uint64 PortXmitDiscards; + uint64 PortXmitConstraintErrors; + uint64 PortRcvRemotePhysicalErrors; + uint64 LocalLinkIntegrityErrors; + uint64 PortRcvErrors; + uint64 ExcessiveBufferOverruns; + uint64 FMConfigErrors; + uint32 LinkErrorRecovery; + uint32 LinkDowned; + uint8 UncorrectableErrors; + union { + uint8 AsReg8; + struct { IB_BITFIELD2(uint8, + Reserved : 5, + LinkQualityIndicator : 3) + } PACK_SUFFIX s; + } lq; + uint8 Reserved2[6]; + struct _vls_pctrs { + uint64 PortVLXmitData; + uint64 PortVLRcvData; + uint64 PortVLXmitPkts; + uint64 PortVLRcvPkts; + uint64 PortVLXmitWait; + uint64 SwPortVLCongestion; + uint64 PortVLRcvFECN; + uint64 PortVLRcvBECN; + uint64 PortVLXmitTimeCong; + uint64 PortVLXmitWastedBW; + uint64 PortVLXmitWaitData; + uint64 PortVLRcvBubble; + uint64 PortVLMarkFECN; + uint64 PortVLXmitDiscards; + } VLs[1]; /* n defined by number of bits in VLSelectmask */ +} PACK_SUFFIX STLPortStatusRsp, STL_PORT_STATUS_RSP; + +typedef struct _STL_Clear_Port_Status { + uint64 PortSelectMask[4]; + CounterSelectMask_t CounterSelectMask; +} PACK_SUFFIX STLClearPortStatus, STL_CLEAR_PORT_STATUS; + +/* The adders are added to the resolutions before performing the shift operation */ +#define RES_ADDER_LLI 8 +#define RES_ADDER_LER 2 + +/* STL Data Port Counters - small request, bigger response */ +typedef struct _STL_Data_Port_Counters_Req { + uint64 PortSelectMask[4]; /* signifies for which ports the PMA is to respond */ + uint32 VLSelectMask; /* signifies for which VLs the PMA is to respond */ + union { + uint32 AsReg32; + struct { IB_BITFIELD3(uint32, + Reserved : 24, + LocalLinkIntegrityResolution : 4, /* The PMA shall interpret the resolution fields as indicators of how many bits to right-shift */ + LinkErrorRecoveryResolution : 4) /* the corresponding counters before adding them to the PortErrorCounterSummary */ + } PACK_SUFFIX s; + } res; +} PACK_SUFFIX STLDataPortCountersReq, STL_DATA_PORT_COUNTERS_REQ; + +struct _vls_dpctrs { + uint64 PortVLXmitData; + uint64 PortVLRcvData; + uint64 PortVLXmitPkts; + uint64 PortVLRcvPkts; + uint64 PortVLXmitWait; + uint64 SwPortVLCongestion; + uint64 PortVLRcvFECN; + uint64 PortVLRcvBECN; + uint64 PortVLXmitTimeCong; + uint64 PortVLXmitWastedBW; + uint64 PortVLXmitWaitData; + uint64 PortVLRcvBubble; + uint64 PortVLMarkFECN; +}; + +struct _port_dpctrs { + uint8 PortNumber; + uint8 Reserved[3]; + union { + uint32 AsReg32; + struct { IB_BITFIELD2(uint32, + Reserved : 29, + LinkQualityIndicator : 3) + } PACK_SUFFIX s; + } lq; + uint64 PortXmitData; + uint64 PortRcvData; + uint64 PortXmitPkts; + uint64 PortRcvPkts; + uint64 PortMulticastXmitPkts; + uint64 PortMulticastRcvPkts; + uint64 PortXmitWait; + uint64 SwPortCongestion; + uint64 PortRcvFECN; + uint64 PortRcvBECN; + uint64 PortXmitTimeCong; + uint64 PortXmitWastedBW; + uint64 PortXmitWaitData; + uint64 PortRcvBubble; + uint64 PortMarkFECN; + uint64 PortErrorCounterSummary; /* sum of all error counters for port */ + struct _vls_dpctrs VLs[1]; /* actual array size defined by number of bits in VLSelectmask */ +}; + +typedef struct _STL_Data_Port_Counters_Rsp { + uint64 PortSelectMask[4]; + uint32 VLSelectMask; + union { + uint32 AsReg32; + struct { IB_BITFIELD3(uint32, + Reserved : 24, + LocalLinkIntegrityResolution : 4, + LinkErrorRecoveryResolution : 4) + } PACK_SUFFIX s; + } res; + struct _port_dpctrs Port[1]; /* actual array size defined by number of ports in attribute modifier */ +} PACK_SUFFIX STLDataPortCountersRsp, STL_DATA_PORT_COUNTERS_RSP; + +/* STL Error Port Counters - small request, bigger response */ + +typedef struct _STL_Error_Port_Counters_Req { + uint64 PortSelectMask[4]; /* signifies for which ports the PMA is to respond */ + uint32 VLSelectMask; /* signifies for which VLs the PMA is to respond */ + uint32 Reserved; +} PACK_SUFFIX STLErrorPortCountersReq, STL_ERROR_PORT_COUNTERS_REQ; + +struct _vls_epctrs { + uint64 PortVLXmitDiscards; +}; +struct _port_epctrs { + uint8 PortNumber; + uint8 Reserved[7]; + uint64 PortRcvConstraintErrors; + uint64 PortRcvSwitchRelayErrors; + uint64 PortXmitDiscards; + uint64 PortXmitConstraintErrors; + uint64 PortRcvRemotePhysicalErrors; + uint64 LocalLinkIntegrityErrors; + uint64 PortRcvErrors; + uint64 ExcessiveBufferOverruns; + uint64 FMConfigErrors; + uint32 LinkErrorRecovery; + uint32 LinkDowned; + uint8 UncorrectableErrors; + uint8 Reserved2[7]; + struct _vls_epctrs VLs[1]; +}; +typedef struct _STL_Error_Port_Counters_Rsp { + uint64 PortSelectMask[4]; /* echo from request */ + uint32 VLSelectMask; /* echo from request */ + uint32 Reserved; + struct _port_epctrs Port[1]; /* actual array size defined by number of ports in attribute modifier */ +} PACK_SUFFIX STLErrorPortCountersRsp, STL_ERROR_PORT_COUNTERS_RSP; + + +struct _port_error_info { + uint8 PortNumber; + uint8 Reserved[7]; + + /* PortRcvErrorInfo */ + struct { + struct { IB_BITFIELD3(uint8, + Status : 1, + Reserved : 3, + ErrorCode : 4) + } PACK_SUFFIX s; + union { + uint8 AsReg8[17]; /* 136 bits of error info */ + struct { + uint8 PacketFlit1[8]; /* first 64 bits of flit 1 */ + uint8 PacketFlit2[8]; /* first 64 bits of flit 2 */ + struct { IB_BITFIELD3(uint8, + Flit1Bits : 1, /* bit 64 of flit 1 */ + Flit2Bits : 1, /* bit 64 of flit 2 */ + Reserved : 6) + } PACK_SUFFIX s; + } PACK_SUFFIX EI1to12; /* error info for codes 1-12 */ + struct { + uint8 PacketBytes[8]; /* first 64 bits of VL Marker flit */ + struct { IB_BITFIELD2(uint8, + FlitBits : 1, /* bit 64 of VL Marker flit */ + Reserved : 7) + } PACK_SUFFIX s; + } PACK_SUFFIX EI13; /* error info for code 13 */ + } ErrorInfo; + uint8 Reserved[6]; + } PACK_SUFFIX PortRcvErrorInfo; + + /* ExcessiveBufferOverrunInfo */ + struct { + struct { IB_BITFIELD3(uint8, + Status : 1, + SC : 5, + Reserved : 2) + } PACK_SUFFIX s; + uint8 Reserved[7]; + } PACK_SUFFIX ExcessiveBufferOverrunInfo; + + /* PortXmitConstraintErrorInfo */ + struct { + struct { IB_BITFIELD2(uint8, + Status : 1, + Reserved : 7) + } PACK_SUFFIX s; + uint8 Reserved; + uint16 P_Key; + STL_LID SLID; + } PACK_SUFFIX PortXmitConstraintErrorInfo; + + /* PortRcvConstraintErrorInfo */ + struct { + struct { IB_BITFIELD3(uint8, + Status : 1, + Reserved : 3, + ErrorCode: 4) + } PACK_SUFFIX s; + uint8 Reserved; + uint16 P_Key; + STL_LID SLID; + } PACK_SUFFIX PortRcvConstraintErrorInfo; + + /* PortRcvSwitchRelayErrorInfo */ + struct { + struct { IB_BITFIELD3(uint8, + Status : 1, + RC : 3, + ErrorCode : 4) + } PACK_SUFFIX s; + uint8 SLID_23_16; + uint16 SLID_15_0; + union { + uint32 AsReg32; + struct { IB_BITFIELD2(uint32, + SC: 8, + DLID: 24) + } EI0; /* error code 0 */ + struct { + uint8 EgressPortNum; + uint8 DLID_23_16; + uint16 DLID_15_0; + } EI2; /* error code 2 */ + struct { + uint8 EgressPortNum; + uint8 SC; + uint16 Reserved; + } EI3; /* error code 3 */ + } ErrorInfo; + } PACK_SUFFIX PortRcvSwitchRelayErrorInfo; + + /* UncorrectableErrorInfo */ + struct { + struct { IB_BITFIELD3(uint8, + Status : 1, + Reserved : 3, + ErrorCode : 4) + } PACK_SUFFIX s; + uint8 Reserved; + } PACK_SUFFIX UncorrectableErrorInfo; + + /* FMConfigErrorInfo */ + struct { + struct { IB_BITFIELD3(uint8, + Status : 1, + Reserved : 3, + ErrorCode : 4) + } PACK_SUFFIX s; + union { + uint8 AsReg8; + struct { + uint8 Distance; + } EI0to2_8; /* error code 0-2,8 */ + struct { + uint8 VL; + } EI3to5; /* error code 3-5 */ + struct { + uint8 BadFlitBits; /* bits [63:56] of bad packet */ + } EI6; /* error code 6 */ + struct { + uint8 SC; + } EI7; /* error code 7 */ + } ErrorInfo; + } PACK_SUFFIX FMConfigErrorInfo; + uint32 Reserved2; +} PACK_SUFFIX; + +typedef union _STL_Error_Info_Mask { + uint32 AsReg32; + struct { IB_BITFIELD8(uint32, + PortRcvErrorInfo : 1, + ExcessiveBufferOverrunInfo : 1, + PortXmitConstraintErrorInfo : 1, + PortRcvConstraintErrorInfo : 1, + PortRcvSwitchRelayErrorInfo : 1, + UncorrectableErrorInfo : 1, + FMConfigErrorInfo : 1, + Reserved : 25) + } PACK_SUFFIX s; +} PACK_SUFFIX STLErrorInfoMask_t; + +typedef struct _STL_Error_Info_Req { + uint64 PortSelectMask[4]; /* signifies for which ports the PMA is to respond */ + STLErrorInfoMask_t ErrorInfoSelectMask; + uint32 Reserved; +} PACK_SUFFIX STLErrorInfoReq, STL_ERROR_INFO_REQ; + +typedef struct _STL_Error_Info_Rsp { + uint64 PortSelectMask[4]; /* signifies for which ports the PMA is to respond */ + STLErrorInfoMask_t ErrorInfoSelectMask; + uint32 Reserved; + struct _port_error_info Port[1]; /* x defined by number of ports in attribute modifier */ +} PACK_SUFFIX STLErrorInfoRsp, STL_ERROR_INFO_RSP; + + +/* Swap routines */ + +static __inline +void +BSWAP_STL_PORT_STATUS_REQ(STL_PORT_STATUS_REQ *Dest) +{ +#if CPU_LE + Dest->VLSelectMask = ntoh32(Dest->VLSelectMask); +#endif +} + +static __inline +void +BSWAP_STL_PORT_STATUS_RSP(STL_PORT_STATUS_RSP *Dest) +{ +#if CPU_LE + int i; + uint32 VLSelectMask; + + Dest->VLSelectMask = VLSelectMask = ntoh32(Dest->VLSelectMask); + Dest->PortXmitData = ntoh64(Dest->PortXmitData); + Dest->PortRcvData = ntoh64(Dest->PortRcvData); + Dest->PortXmitPkts = ntoh64(Dest->PortXmitPkts); + Dest->PortRcvPkts = ntoh64(Dest->PortRcvPkts); + Dest->PortMulticastXmitPkts = ntoh64(Dest->PortMulticastXmitPkts); + Dest->PortMulticastRcvPkts = ntoh64(Dest->PortMulticastRcvPkts); + Dest->PortXmitWait = ntoh64(Dest->PortXmitWait); + Dest->SwPortCongestion = ntoh64(Dest->SwPortCongestion); + Dest->PortRcvFECN = ntoh64(Dest->PortRcvFECN); + Dest->PortRcvBECN = ntoh64(Dest->PortRcvBECN); + Dest->PortXmitTimeCong = ntoh64(Dest->PortXmitTimeCong); + Dest->PortXmitWastedBW = ntoh64(Dest->PortXmitWastedBW); + Dest->PortXmitWaitData = ntoh64(Dest->PortXmitWaitData); + Dest->PortRcvBubble = ntoh64(Dest->PortRcvBubble); + Dest->PortMarkFECN = ntoh64(Dest->PortMarkFECN); + Dest->PortRcvConstraintErrors = ntoh64(Dest->PortRcvConstraintErrors); + Dest->PortRcvSwitchRelayErrors = ntoh64(Dest->PortRcvSwitchRelayErrors); + Dest->PortXmitDiscards = ntoh64(Dest->PortXmitDiscards); + Dest->PortXmitConstraintErrors = ntoh64(Dest->PortXmitConstraintErrors); + Dest->PortRcvRemotePhysicalErrors = ntoh64(Dest->PortRcvRemotePhysicalErrors); + Dest->LocalLinkIntegrityErrors = ntoh64(Dest->LocalLinkIntegrityErrors); + Dest->PortRcvErrors = ntoh64(Dest->PortRcvErrors); + Dest->ExcessiveBufferOverruns = ntoh64(Dest->ExcessiveBufferOverruns); + Dest->FMConfigErrors = ntoh64(Dest->FMConfigErrors); + Dest->LinkErrorRecovery = ntoh32(Dest->LinkErrorRecovery); + Dest->LinkDowned = ntoh32(Dest->LinkDowned); + /* Count the bits in the mask and process the VLs in succession */ + /* Assume that even though VL numbers may not be contiguous, that entries */ + /* in the array are */ + for (i = 0; VLSelectMask && i < 32; VLSelectMask >>= (uint32)1) { + if (VLSelectMask & (uint32)1) { + Dest->VLs[i].PortVLXmitData = ntoh64(Dest->VLs[i].PortVLXmitData); + Dest->VLs[i].PortVLRcvData = ntoh64(Dest->VLs[i].PortVLRcvData); + Dest->VLs[i].PortVLXmitPkts = ntoh64(Dest->VLs[i].PortVLXmitPkts); + Dest->VLs[i].PortVLRcvPkts = ntoh64(Dest->VLs[i].PortVLRcvPkts); + Dest->VLs[i].PortVLXmitWait = ntoh64(Dest->VLs[i].PortVLXmitWait); + Dest->VLs[i].SwPortVLCongestion = ntoh64(Dest->VLs[i].SwPortVLCongestion); + Dest->VLs[i].PortVLRcvFECN = ntoh64(Dest->VLs[i].PortVLRcvFECN); + Dest->VLs[i].PortVLRcvBECN = ntoh64(Dest->VLs[i].PortVLRcvBECN); + Dest->VLs[i].PortVLXmitTimeCong = ntoh64(Dest->VLs[i].PortVLXmitTimeCong); + Dest->VLs[i].PortVLXmitWastedBW = ntoh64(Dest->VLs[i].PortVLXmitWastedBW); + Dest->VLs[i].PortVLXmitWaitData = ntoh64(Dest->VLs[i].PortVLXmitWaitData); + Dest->VLs[i].PortVLRcvBubble = ntoh64(Dest->VLs[i].PortVLRcvBubble); + Dest->VLs[i].PortVLMarkFECN = ntoh64(Dest->VLs[i].PortVLMarkFECN); + Dest->VLs[i].PortVLXmitDiscards = ntoh64(Dest->VLs[i].PortVLXmitDiscards); + i++; + } + } +#endif +} + +static __inline void +BSWAP_STL_CLEAR_PORT_STATUS_REQ(STL_CLEAR_PORT_STATUS *Dest) +{ +#if CPU_LE + int i; + for (i = 0; i < 4; i++) + Dest->PortSelectMask[i] = ntoh64(Dest->PortSelectMask[i]); + Dest->CounterSelectMask.AsReg32 = ntoh32(Dest->CounterSelectMask.AsReg32); +#endif +} + +static __inline void +BSWAP_STL_DATA_PORT_COUNTERS_REQ(STL_DATA_PORT_COUNTERS_REQ *Dest) +{ +#if CPU_LE + int i; + for (i = 0; i < 4; i++) + Dest->PortSelectMask[i] = ntoh64(Dest->PortSelectMask[i]); + Dest->VLSelectMask = ntoh32(Dest->VLSelectMask); + Dest->res.AsReg32 = ntoh32(Dest->res.AsReg32); +#endif +} + +static __inline void +BSWAP_STL_DATA_PORT_COUNTERS_RSP(STL_DATA_PORT_COUNTERS_RSP *Dest) +{ +#if CPU_LE + int i, j; + uint8 PortCount = 0; + uint8 VlCount = 0; + uint64 PortSelectMask; + uint32 VLSelectMask; + struct _port_dpctrs *dPort; + + for (i = 0; i < 4; i++) { + PortSelectMask = Dest->PortSelectMask[3-i] = ntoh64(Dest->PortSelectMask[3-i]); + for (j = 0; PortSelectMask && j < 64; j++, PortSelectMask >>= (uint64)1) { + if (PortSelectMask & (uint64)1) PortCount++; + } + } + VLSelectMask = Dest->VLSelectMask = ntoh32(Dest->VLSelectMask); + for (i = 0; VLSelectMask && i < 32; i++, VLSelectMask >>= (uint32)1) { + if (VLSelectMask & (uint32)1) VlCount++; + } + Dest->res.AsReg32 = ntoh32(Dest->res.AsReg32); + + dPort = &Dest->Port[0]; + for (i = 0; i < PortCount; i++) { + dPort->lq.AsReg32 = ntoh32(dPort->lq.AsReg32); + dPort->PortXmitData = ntoh64(dPort->PortXmitData); + dPort->PortRcvData = ntoh64(dPort->PortRcvData); + dPort->PortXmitPkts = ntoh64(dPort->PortXmitPkts); + dPort->PortRcvPkts = ntoh64(dPort->PortRcvPkts); + dPort->PortMulticastXmitPkts = ntoh64(dPort->PortMulticastXmitPkts); + dPort->PortMulticastRcvPkts = ntoh64(dPort->PortMulticastRcvPkts); + dPort->PortXmitWait = ntoh64(dPort->PortXmitWait); + dPort->SwPortCongestion = ntoh64(dPort->SwPortCongestion); + dPort->PortRcvFECN = ntoh64(dPort->PortRcvFECN); + dPort->PortRcvBECN = ntoh64(dPort->PortRcvBECN); + dPort->PortXmitTimeCong = ntoh64(dPort->PortXmitTimeCong); + dPort->PortXmitWastedBW = ntoh64(dPort->PortXmitWastedBW); + dPort->PortXmitWaitData = ntoh64(dPort->PortXmitWaitData); + dPort->PortRcvBubble = ntoh64(dPort->PortRcvBubble); + dPort->PortMarkFECN = ntoh64(dPort->PortMarkFECN); + dPort->PortErrorCounterSummary = ntoh64(dPort->PortErrorCounterSummary); + for (j = 0; j < VlCount; j++) { + dPort->VLs[j].PortVLXmitData = ntoh64(dPort->VLs[j].PortVLXmitData); + dPort->VLs[j].PortVLRcvData = ntoh64(dPort->VLs[j].PortVLRcvData); + dPort->VLs[j].PortVLXmitPkts = ntoh64(dPort->VLs[j].PortVLXmitPkts); + dPort->VLs[j].PortVLRcvPkts = ntoh64(dPort->VLs[j].PortVLRcvPkts); + dPort->VLs[j].PortVLXmitWait = ntoh64(dPort->VLs[j].PortVLXmitWait); + dPort->VLs[j].SwPortVLCongestion = ntoh64(dPort->VLs[j].SwPortVLCongestion); + dPort->VLs[j].PortVLRcvFECN = ntoh64(dPort->VLs[j].PortVLRcvFECN); + dPort->VLs[j].PortVLRcvBECN = ntoh64(dPort->VLs[j].PortVLRcvBECN); + dPort->VLs[j].PortVLXmitTimeCong = ntoh64(dPort->VLs[j].PortVLXmitTimeCong); + dPort->VLs[j].PortVLXmitWastedBW = ntoh64(dPort->VLs[j].PortVLXmitWastedBW); + dPort->VLs[j].PortVLXmitWaitData = ntoh64(dPort->VLs[j].PortVLXmitWaitData); + dPort->VLs[j].PortVLRcvBubble = ntoh64(dPort->VLs[j].PortVLRcvBubble); + dPort->VLs[j].PortVLMarkFECN = ntoh64(dPort->VLs[j].PortVLMarkFECN); + } + dPort = (struct _port_dpctrs *)&dPort->VLs[VlCount]; + } +#endif +} + +static __inline void +BSWAP_STL_ERROR_PORT_COUNTERS_REQ(STL_ERROR_PORT_COUNTERS_REQ *Dest) +{ +#if CPU_LE + int i; + for (i = 0; i < 4; i++) + Dest->PortSelectMask[i] = ntoh64(Dest->PortSelectMask[i]); + Dest->VLSelectMask = ntoh32(Dest->VLSelectMask); +#endif +} + +static __inline void +BSWAP_STL_ERROR_PORT_COUNTERS_RSP(STL_ERROR_PORT_COUNTERS_RSP *Dest) +{ +#if CPU_LE + int i, j; + uint8 PortCount = 0; + uint8 VlCount = 0; + uint64 PortSelectMask; + uint32 VLSelectMask; + struct _port_epctrs *ePort; + + for (i = 0; i < 4; i++) { + PortSelectMask = Dest->PortSelectMask[3-i] = ntoh64(Dest->PortSelectMask[3-i]); + for (j = 0; PortSelectMask && j < 64; j++, PortSelectMask >>= (uint64)1) { + if (PortSelectMask & (uint64)1) PortCount++; + } + } + VLSelectMask = Dest->VLSelectMask = ntoh32(Dest->VLSelectMask); + for (i = 0; VLSelectMask && i < 32; i++, VLSelectMask >>= (uint32)1) { + if (VLSelectMask & (uint32)1) VlCount++; + } + + ePort = &Dest->Port[0]; + for (i = 0; i < PortCount; i++) { + ePort->PortRcvConstraintErrors = ntoh64(ePort->PortRcvConstraintErrors); + ePort->PortRcvSwitchRelayErrors = ntoh64(ePort->PortRcvSwitchRelayErrors); + ePort->PortXmitDiscards = ntoh64(ePort->PortXmitDiscards); + ePort->PortXmitConstraintErrors = ntoh64(ePort->PortXmitConstraintErrors); + ePort->PortRcvRemotePhysicalErrors = ntoh64(ePort->PortRcvRemotePhysicalErrors); + ePort->LocalLinkIntegrityErrors = ntoh64(ePort->LocalLinkIntegrityErrors); + ePort->PortRcvErrors = ntoh64(ePort->PortRcvErrors); + ePort->ExcessiveBufferOverruns = ntoh64(ePort->ExcessiveBufferOverruns); + ePort->FMConfigErrors = ntoh64(ePort->FMConfigErrors); + ePort->LinkErrorRecovery = ntoh32(ePort->LinkErrorRecovery); + ePort->LinkDowned = ntoh32(ePort->LinkDowned); + + for (j = 0; j < VlCount; j++) { + ePort->VLs[j].PortVLXmitDiscards = ntoh64(ePort->VLs[j].PortVLXmitDiscards); + } + ePort = (struct _port_epctrs *)(&ePort->VLs[VlCount]); + } +#endif +} + +static __inline void +BSWAP_STL_ERROR_INFO_REQ(STL_ERROR_INFO_REQ *Dest) +{ +#if CPU_LE + int i; + + for (i = 0; i < 4; i++) { + Dest->PortSelectMask[3-i] = ntoh64(Dest->PortSelectMask[3-i]); + } + Dest->ErrorInfoSelectMask.AsReg32 = ntoh32(Dest->ErrorInfoSelectMask.AsReg32); +#endif +} + +static __inline void +BSWAP_STL_ERROR_INFO_RSP(STL_ERROR_INFO_RSP *Dest) +{ +#if CPU_LE + int i, j; + uint8 PortCount = 0; + uint64 PortSelectMask; + + for (i = 0; i < 4; i++) { + PortSelectMask = Dest->PortSelectMask[3-i] = ntoh64(Dest->PortSelectMask[3-i]); + for (j = 0; PortSelectMask && j < 64; j++, PortSelectMask >>= (uint64)1) { + if (PortSelectMask & (uint64)1) PortCount++; + } + } + for (i = 0; i < PortCount; i++) { + Dest->Port[i].PortXmitConstraintErrorInfo.P_Key = ntoh16(Dest->Port[i].PortXmitConstraintErrorInfo.P_Key); + Dest->Port[i].PortXmitConstraintErrorInfo.SLID = ntoh32(Dest->Port[i].PortXmitConstraintErrorInfo.SLID); + Dest->Port[i].PortRcvConstraintErrorInfo.P_Key = ntoh16(Dest->Port[i].PortRcvConstraintErrorInfo.P_Key); + Dest->Port[i].PortRcvConstraintErrorInfo.SLID = ntoh32(Dest->Port[i].PortRcvConstraintErrorInfo.SLID); + + Dest->Port[i].PortRcvSwitchRelayErrorInfo.SLID_15_0 = ntoh16(Dest->Port[i].PortRcvSwitchRelayErrorInfo.SLID_15_0); + if (Dest->Port[i].PortRcvSwitchRelayErrorInfo.s.ErrorCode == 0) { + Dest->Port[i].PortRcvSwitchRelayErrorInfo.ErrorInfo.AsReg32 = ntoh32(Dest->Port[i].PortRcvSwitchRelayErrorInfo.ErrorInfo.AsReg32); + } else if (Dest->Port[i].PortRcvSwitchRelayErrorInfo.s.ErrorCode == 2) { + Dest->Port[i].PortRcvSwitchRelayErrorInfo.ErrorInfo.EI2.DLID_15_0 = ntoh16(Dest->Port[i].PortRcvSwitchRelayErrorInfo.ErrorInfo.EI2.DLID_15_0); + } + } + Dest->ErrorInfoSelectMask.AsReg32 = ntoh32(Dest->ErrorInfoSelectMask.AsReg32); +#endif +} + + +/** + * Copy data in a STL_PORT_STATUS_RSP variable into a STL_PORT_COUNTERS_DATA variable + * + * @param SrcPortStatus - pointer to STL_PORT_STATUS_RSP variable from which to copy + * @param DestPortCounters - pointer to STL_PORT_COUNTERS_DATA variable to copy to + * @param portInfo - optional pointer to STL_PORT_INFO varaible to gather numLanesDown from + * + */ +static __inline void StlPortStatusToPortCounters(STL_PORT_STATUS_RSP *SrcPortStatus, STL_PORT_COUNTERS_DATA *DestPortCounters, STL_PORT_INFO *portInfo) +{ + DestPortCounters->linkErrorRecovery = SrcPortStatus->LinkErrorRecovery; + DestPortCounters->linkDowned = SrcPortStatus->LinkDowned; + DestPortCounters->portRcvErrors = SrcPortStatus->PortRcvErrors; + DestPortCounters->portRcvRemotePhysicalErrors = SrcPortStatus->PortRcvRemotePhysicalErrors; + DestPortCounters->portRcvSwitchRelayErrors = SrcPortStatus->PortRcvSwitchRelayErrors; + DestPortCounters->portXmitDiscards = SrcPortStatus->PortXmitDiscards; + DestPortCounters->portXmitConstraintErrors = SrcPortStatus->PortXmitConstraintErrors; + DestPortCounters->portRcvConstraintErrors = SrcPortStatus->PortRcvConstraintErrors; + DestPortCounters->localLinkIntegrityErrors = SrcPortStatus->LocalLinkIntegrityErrors; + DestPortCounters->excessiveBufferOverruns = SrcPortStatus->ExcessiveBufferOverruns; + DestPortCounters->portXmitData = SrcPortStatus->PortXmitData; + DestPortCounters->portRcvData = SrcPortStatus->PortRcvData; + DestPortCounters->portXmitPkts = SrcPortStatus->PortXmitPkts; + DestPortCounters->portRcvPkts = SrcPortStatus->PortRcvPkts; + DestPortCounters->portMulticastXmitPkts = SrcPortStatus->PortMulticastXmitPkts; + DestPortCounters->portMulticastRcvPkts = SrcPortStatus->PortMulticastRcvPkts; + DestPortCounters->portXmitWait = SrcPortStatus->PortXmitWait; + DestPortCounters->swPortCongestion = SrcPortStatus->SwPortCongestion; + DestPortCounters->portRcvFECN = SrcPortStatus->PortRcvFECN; + DestPortCounters->portRcvBECN = SrcPortStatus->PortRcvBECN; + DestPortCounters->portXmitTimeCong = SrcPortStatus->PortXmitTimeCong; + DestPortCounters->portXmitWastedBW = SrcPortStatus->PortXmitWastedBW; + DestPortCounters->portXmitWaitData = SrcPortStatus->PortXmitWaitData; + DestPortCounters->portRcvBubble = SrcPortStatus->PortRcvBubble; + DestPortCounters->portMarkFECN = SrcPortStatus->PortMarkFECN; + DestPortCounters->fmConfigErrors = SrcPortStatus->FMConfigErrors; + DestPortCounters->uncorrectableErrors = SrcPortStatus->UncorrectableErrors; + DestPortCounters->lq.s.linkQualityIndicator = SrcPortStatus->lq.s.LinkQualityIndicator; + if (portInfo) { + DestPortCounters->lq.s.numLanesDown = StlGetNumLanesDown(portInfo); + } +} + +#include "iba/public/ipackoff.h" + +#if defined (__cplusplus) +}; +#endif + +#endif /* __IBA_STL_PM_H__ */ diff --git a/IbAccess/Common/Inc/stl_rmpp.h b/IbAccess/Common/Inc/stl_rmpp.h new file mode 100644 index 0000000..380d098 --- /dev/null +++ b/IbAccess/Common/Inc/stl_rmpp.h @@ -0,0 +1,155 @@ +/* BEGIN_ICS_COPYRIGHT7 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT7 ****************************************/ + +#ifndef __STL_RMPP_H__ +#define __STL_RMPP_H__ + +#include "iba/public/ipackon.h" +#include "ib_mad.h" + +#if defined (__cplusplus) +extern "C" { +#endif + +/* + * Base RMPP header + */ +typedef struct _STL_RMPP_DATA_HEADER { + uint8_t rmppVersion; + uint8_t rmppType; + union { + struct { + #if CPU_BE + uint8_t rmppRespTime : 5; + uint8_t rmppFlags : 3; + #else + uint8_t rmppFlags : 3; + uint8_t rmppRespTime : 5; + #endif + } tf; + uint8_t timeFlag; + } u; + uint8_t rmppStatus; + uint32_t segNum; + uint32_t length; +} STL_RMPP_DATA_HEADER ; + +typedef struct _STL_RMPP_ACK_HEADER { + uint8_t rmppVersion; + uint8_t rmppType; + union { + struct { + #if CPU_BE + uint8_t rmppRespTime : 5; + uint8_t rmppFlags : 3; + #else + uint8_t rmppFlags : 3; + uint8_t rmppRespTime : 5; + #endif + } tf; + uint8_t timeFlag; + } u; + uint8_t rmppStatus; + uint32_t segNum; + uint32_t newwindowlast; +} STL_RMPP_ACK_HEADER ; + +/* + * Vendor RMPP Header + */ +typedef struct _STL_RMPP_VENDOR_HEADER { + uint8_t rmppVersion; + uint8_t rmppType; + union { + struct { + #if CPU_BE + uint8_t rmppRespTime : 5; + uint8_t rmppFlags : 3; + #else + uint8_t rmppFlags : 3; + uint8_t rmppRespTime : 5; + #endif + } tf; + uint8_t timeFlag; + } u; + uint8_t rmppStatus; + uint32_t segNum; + uint32_t length; + uint8_t reserved; + uint8_t oui[3]; +} PACK_SUFFIX STL_RMPP_VENDOR_HEADER; + +#define STL_RMPP_VENDOR_DATA_LEN (STL_MAD_BLOCK_SIZE - \ + sizeof(STL_RMPP_VENDOR_HEADER) - \ + sizeof(MAD_COMMON)) +#define STL_RMPP_SIZEOF_OUI 4 + +typedef struct _STL_RMPP_VENDOR_MAD { + MAD_COMMON common; + STL_RMPP_VENDOR_HEADER header; + uint8_t data[STL_RMPP_VENDOR_DATA_LEN]; +} PACK_SUFFIX STL_RMPP_VENDOR_MAD; + +/* + * Contains the vendor header (RMPP + OUI) and the data portion + */ +typedef struct _STL_RMPP_VENDOR_PACKET { + STL_RMPP_VENDOR_HEADER header; + uint8_t data[STL_RMPP_VENDOR_DATA_LEN]; +} PACK_SUFFIX STL_RMPP_VENDOR_PACKET; + + +static __inline +void +BSWAPCOPY_STL_RMPP_VENDOR_HEADER(STL_RMPP_VENDOR_HEADER *src, + STL_RMPP_VENDOR_HEADER *dst) +{ + dst->rmppVersion = src->rmppVersion; + dst->rmppType = src->rmppType; + dst->rmppStatus = src->rmppStatus; + dst->u.timeFlag = src->u.timeFlag; + + dst->segNum = ntoh32(src->segNum); + dst->length = ntoh32(src->length); +} + +static __inline +void +BSWAPCOPY_STL_RMPP_VENDOR_PACKET(STL_RMPP_VENDOR_PACKET *src, + STL_RMPP_VENDOR_PACKET *dst, size_t len) +{ + BSWAPCOPY_STL_RMPP_VENDOR_HEADER(&src->header,&dst->header); + memcpy(&dst->data, &src->data, len); +} + +#if defined (__cplusplus) +} +#endif + +#endif diff --git a/IbAccess/Common/Inc/stl_sa_priv.h b/IbAccess/Common/Inc/stl_sa_priv.h new file mode 100644 index 0000000..02bd76a --- /dev/null +++ b/IbAccess/Common/Inc/stl_sa_priv.h @@ -0,0 +1,820 @@ +/* BEGIN_ICS_COPYRIGHT7 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT7 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +#ifndef __STL_SA_PRIV_H__ +#define __STL_SA_PRIV_H__ + +#include "iba/stl_mad_priv.h" +#include "iba/stl_sa_types.h" +#include "iba/ib_sa_records_priv.h" +#include "iba/stl_sm_priv.h" + +#if defined (__cplusplus) +extern "C" { +#endif + +// Replaces old Vieo macro that converts a single GID argument into two arguments +// that can be used in a print statement. +#define STLGIDPRINTARGS(GID) ntoh64((GID).Type.Global.SubnetPrefix), \ + ntoh64((GID).Type.Global.InterfaceID) + +#define STLGIDPRINTARGS2(GID) ntoh64(alignArray64(&GID[0])), ntoh64(alignArray64(&GID[8])) + +static __inline__ uint64_t +_alignArray64(uint8_t * array) { uint64_t rv; memcpy(&rv, array, sizeof(rv));return rv;} + +#include "iba/public/ipackon.h" + +/* + * SA Header + */ +typedef struct { + uint8_t rmppVersion; + uint8_t rmppType; + union { + struct { + #if CPU_BE + uint8_t rmppRespTime : 5; + uint8_t rmppFlags : 3; + #else + uint8_t rmppFlags : 3; + uint8_t rmppRespTime : 5; + #endif + } tf; + uint8_t timeFlag; + } u; + uint8_t rmppStatus; + uint32_t segNum; + uint32_t length; + uint64_t smKey; + uint16_t offset; + uint16_t rservd; + uint64_t mask; +} PACK_SUFFIX STL_SA_MAD_HEADER; + +#define STL_SA_DATA_LEN (STL_MAD_BLOCK_SIZE-sizeof(STL_SA_MAD_HEADER)-sizeof(MAD_COMMON)) + +typedef struct { + STL_SA_MAD_HEADER header; + uint8_t data[STL_SA_DATA_LEN]; +} PACK_SUFFIX STL_SA_MAD; + +static __inline void +BSWAPCOPY_STL_SA_MAD_HEADER(STL_SA_MAD_HEADER *src, STL_SA_MAD_HEADER *dst) +{ + dst->rmppVersion = src->rmppVersion; + dst->rmppType = src->rmppType; + dst->rmppStatus = src->rmppStatus; + dst->u.timeFlag = src->u.timeFlag; + + dst->segNum = ntoh32(src->segNum); + dst->length = ntoh32(src->length); + dst->smKey = ntoh64(src->smKey); + dst->offset = ntoh16(src->offset); + dst->rservd = ntoh16(src->rservd); + dst->mask = ntoh64(src->mask); +} + +static __inline void +BSWAPCOPY_STL_SA_MAD(STL_SA_MAD *src, STL_SA_MAD *dst, size_t len) +{ + BSWAPCOPY_STL_SA_MAD_HEADER(&src->header,&dst->header); + memcpy(&dst->data, &src->data, len); +} + +static __inline void +BSWAP_STL_NODE_RECORD(STL_NODE_RECORD *Dest) +{ + Dest->RID.LID = ntoh32(Dest->RID.LID); + BSWAP_STL_NODE_INFO(&Dest->NodeInfo); +} + +static __inline void +BSWAPCOPY_STL_NODE_RECORD(STL_NODE_RECORD *Src, STL_NODE_RECORD *Dest) +{ + Dest->RID.LID = ntoh32(Src->RID.LID); + BSWAPCOPY_STL_NODE_INFO(&Src->NodeInfo, &Dest->NodeInfo); + memcpy(&(Dest->NodeDesc), &(Src->NodeDesc), sizeof(STL_NODE_DESCRIPTION)); +} + +static __inline void +BSWAPCOPY_IB_NODE_RECORD(IB_NODE_RECORD *Src, IB_NODE_RECORD *Dest) +{ + Dest->RID.AsReg32 = ntoh32(Src->RID.AsReg32); + memcpy(&Dest->NodeInfoData,&Src->NodeInfoData,sizeof(NODE_INFO)); + BSWAP_NODE_INFO(&Dest->NodeInfoData); + memcpy(&(Dest->NodeDescData), &(Src->NodeDescData), sizeof(NODE_DESCRIPTION)); +} + +static __inline void +BSWAP_STL_PORTINFO_RECORD(STL_PORTINFO_RECORD *Dest) +{ +#if CPU_LE + int i; + + Dest->RID.EndPortLID = ntoh32(Dest->RID.EndPortLID); + BSWAP_STL_PORT_INFO(&Dest->PortInfo); + + for(i = 0; i < STL_NUM_LINKDOWN_REASONS; i++){ + Dest->LinkDownReasons[i].Timestamp = ntoh64(Dest->LinkDownReasons[i].Timestamp); + } +#endif +} + +static __inline void +BSWAP_STL_PARTITION_TABLE_RECORD(STL_P_KEY_TABLE_RECORD *Dest) +{ + Dest->RID.LID = ntoh32(Dest->RID.LID); + Dest->RID.Blocknum = ntoh16(Dest->RID.Blocknum); + BSWAP_STL_PARTITION_TABLE(&Dest->PKeyTblData); +} + +static __inline void +BSWAPCOPY_STL_PARTITION_TABLE_RECORD(STL_P_KEY_TABLE_RECORD *Src, STL_P_KEY_TABLE_RECORD *Dest) +{ + memcpy(Dest, Src, sizeof(STL_P_KEY_TABLE_RECORD)); + BSWAP_STL_PARTITION_TABLE_RECORD(Dest); +} + +static __inline void +BSWAP_STL_SC_MAPPING_TABLE_RECORD(STL_SC_MAPPING_TABLE_RECORD *Dest) +{ + Dest->RID.LID = ntoh32(Dest->RID.LID); +} + +static __inline void +BSWAPCOPY_STL_SC_MAPPING_TABLE_RECORD(STL_SC_MAPPING_TABLE_RECORD *Src, STL_SC_MAPPING_TABLE_RECORD *Dest) +{ + memcpy(Dest, Src, sizeof(STL_SC_MAPPING_TABLE_RECORD)); + BSWAP_STL_SC_MAPPING_TABLE_RECORD(Dest); +} + +static __inline void +BSWAP_STL_SL2SC_MAPPING_TABLE_RECORD(STL_SL2SC_MAPPING_TABLE_RECORD *Dest) +{ + Dest->RID.LID=ntoh32(Dest->RID.LID); +} + +static __inline void +BSWAPCOPY_STL_SL2SC_MAPPING_TABLE_RECORD(STL_SL2SC_MAPPING_TABLE_RECORD *Src, STL_SL2SC_MAPPING_TABLE_RECORD *Dest) +{ + memcpy(Dest, Src, sizeof(STL_SL2SC_MAPPING_TABLE_RECORD)); + BSWAP_STL_SL2SC_MAPPING_TABLE_RECORD(Dest); +} + +static __inline void +BSWAP_STL_SC2SL_MAPPING_TABLE_RECORD(STL_SC2SL_MAPPING_TABLE_RECORD *Dest) +{ + Dest->RID.LID=ntoh32(Dest->RID.LID); +} + +static __inline void +BSWAPCOPY_STL_SC2SL_MAPPING_TABLE_RECORD(STL_SC2SL_MAPPING_TABLE_RECORD *Src, STL_SC2SL_MAPPING_TABLE_RECORD *Dest) +{ + memcpy(Dest, Src, sizeof(STL_SC2SL_MAPPING_TABLE_RECORD)); + BSWAP_STL_SC2SL_MAPPING_TABLE_RECORD(Dest); +} + +static __inline void +BSWAP_STL_SC2VL_R_MAPPING_TABLE_RECORD(STL_SC2VL_R_MAPPING_TABLE_RECORD *Dest) +{ + Dest->RID.LID=ntoh32(Dest->RID.LID); +} + +static __inline void +BSWAPCOPY_STL_SC2VL_R_MAPPING_TABLE_RECORD(STL_SC2VL_R_MAPPING_TABLE_RECORD *Src, STL_SC2VL_R_MAPPING_TABLE_RECORD *Dest) +{ + memcpy(Dest, Src, sizeof(STL_SC2VL_R_MAPPING_TABLE_RECORD)); + BSWAP_STL_SC2VL_R_MAPPING_TABLE_RECORD(Dest); +} + +static __inline void +BSWAPCOPY_STL_SWITCHINFO_RECORD(STL_SWITCHINFO_RECORD *Src, STL_SWITCHINFO_RECORD *Dest) +{ + Dest->RID.LID = ntoh32(Src->RID.LID); + BSWAPCOPY_STL_SWITCH_INFO(&Src->SwitchInfoData, &Dest->SwitchInfoData); +} + +static __inline void +BSWAP_STL_SWITCHINFO_RECORD(STL_SWITCHINFO_RECORD *Dest) +{ + Dest->RID.LID = ntoh32(Dest->RID.LID); + BSWAP_STL_SWITCH_INFO(&Dest->SwitchInfoData); +} + +static __inline void +BSWAP_STL_LINEAR_FORWARDING_TABLE_RECORD(STL_LINEAR_FORWARDING_TABLE_RECORD *Dest) +{ + Dest->RID.LID = ntoh32(Dest->RID.LID); + (*(uint32*)((char *)Dest + sizeof(uint32))) = ntoh32(*(uint32*)((char *)Dest + sizeof(uint32))); + BSWAP_STL_LINEAR_FORWARDING_TABLE((STL_LINEAR_FORWARDING_TABLE *)Dest->LinearFdbData); +} + +static __inline void +BSWAPCOPY_STL_LINEAR_FORWARDING_TABLE_RECORD(STL_LINEAR_FORWARDING_TABLE_RECORD *Src, STL_LINEAR_FORWARDING_TABLE_RECORD *Dest) +{ + memcpy(Dest, Src, sizeof(STL_LINEAR_FORWARDING_TABLE_RECORD)); + BSWAP_STL_LINEAR_FORWARDING_TABLE_RECORD(Dest); +} + + +static __inline void +BSWAP_STL_MCFTB_RECORD(STL_MULTICAST_FORWARDING_TABLE_RECORD *Dest) +{ + int i; + Dest->RID.LID = ntoh32(Dest->RID.LID); + Dest->RID.u1.AsReg32 = ntoh32(Dest->RID.u1.AsReg32); + for (i = 0; i < STL_NUM_MFT_ELEMENTS_BLOCK; ++i) Dest->MftTable.MftBlock[i] = ntoh64(Dest->MftTable.MftBlock[i]); +} + +static __inline void +BSWAPCOPY_STL_MCFTB_RECORD(STL_MULTICAST_FORWARDING_TABLE_RECORD *Src, STL_MULTICAST_FORWARDING_TABLE_RECORD *Dest) +{ + memcpy(Dest, Src, sizeof(STL_MULTICAST_FORWARDING_TABLE_RECORD)); + BSWAP_STL_MCFTB_RECORD(Dest); +} + +static __inline void +BSWAP_STL_PORT_GROUP_TABLE_RECORD(STL_PORT_GROUP_TABLE_RECORD *Dest) +{ + int i; + Dest->RID.LID = ntoh32(Dest->RID.LID); + for (i = 0; i < STL_PGTB_NUM_ENTRIES_PER_BLOCK; ++i) Dest->GroupBlock[i] = ntoh64(Dest->GroupBlock[i]); +} + +static __inline void +BSWAPCOPY_STL_PORT_GROUP_TABLE_RECORD(STL_PORT_GROUP_TABLE_RECORD *Src, STL_PORT_GROUP_TABLE_RECORD *Dest) +{ + memcpy(Dest, Src, sizeof(STL_PORT_GROUP_TABLE_RECORD)); + BSWAP_STL_PORT_GROUP_TABLE_RECORD(Dest); +} + +static __inline void +BSWAP_STL_PORT_GROUP_FORWARDING_TABLE_RECORD(STL_PORT_GROUP_FORWARDING_TABLE_RECORD *Dest) +{ + Dest->RID.LID = ntoh32(Dest->RID.LID); + Dest->RID.u1.AsReg32 = ntoh32(Dest->RID.u1.AsReg32); +} + +static __inline void +BSWAPCOPY_STL_PORT_GROUP_FORWARDING_TABLE_RECORD(STL_PORT_GROUP_FORWARDING_TABLE_RECORD *Src, STL_PORT_GROUP_FORWARDING_TABLE_RECORD *Dest) +{ + memcpy(Dest, Src, sizeof(STL_PORT_GROUP_FORWARDING_TABLE_RECORD)); + BSWAP_STL_PORT_GROUP_FORWARDING_TABLE_RECORD(Dest); +} + +static __inline void +BSWAP_STL_VLARBTABLE_RECORD(STL_VLARBTABLE_RECORD *Dest) +{ + Dest->RID.LID = ntoh32(Dest->RID.LID); + BSWAP_STL_VLARB_TABLE(&Dest->VLArbTable, Dest->RID.BlockNum); +} + +static __inline void +BSWAPCOPY_STL_VLARBTABLE_RECORD(STL_VLARBTABLE_RECORD *Src, STL_VLARBTABLE_RECORD *Dest) +{ + memcpy(Dest, Src, sizeof(STL_VLARBTABLE_RECORD)); + BSWAP_STL_VLARBTABLE_RECORD(Dest); +} + + +static __inline void +BSWAP_STL_MCMEMBER_RECORD(STL_MCMEMBER_RECORD *Dest) +{ + uint64_t temp; + + temp = ntoh64(Dest->RID.MGID.AsReg64s.H); + Dest->RID.MGID.AsReg64s.H = ntoh64(Dest->RID.MGID.AsReg64s.L); + Dest->RID.MGID.AsReg64s.L = temp; + + temp = ntoh64(Dest->RID.PortGID.AsReg64s.H); + Dest->RID.PortGID.AsReg64s.H = ntoh64(Dest->RID.PortGID.AsReg64s.L); + Dest->RID.PortGID.AsReg64s.L = temp; + + Dest->Q_Key = ntoh32(Dest->Q_Key); + Dest->P_Key = ntoh16(Dest->P_Key); + *(uint32*)((uint8*)Dest + 44) = ntoh32( *(uint32*)( (uint8*)Dest + 44) ); + Dest->MLID = ntoh32(Dest->MLID); +} + +static __inline void +BSWAPCOPY_STL_MCMEMBER_RECORD(STL_MCMEMBER_RECORD *Src, STL_MCMEMBER_RECORD *Dest) +{ + memcpy(Dest, Src, sizeof(STL_MCMEMBER_RECORD)); + BSWAP_STL_MCMEMBER_RECORD(Dest); +} + +static __inline void +CONVERT_IB2STL_MCMEMBER_RECORD(IB_MCMEMBER_RECORD *Src, STL_MCMEMBER_RECORD *Dest) +{ + Dest->RID.MGID = Src->RID.MGID; + Dest->RID.PortGID = Src->RID.PortGID; + Dest->Q_Key = Src->Q_Key; + Dest->MLID = MCAST16_TO_MCAST32(Src->MLID); + Dest->MtuSelector = Src->MtuSelector; + Dest->Mtu = Src->Mtu; + Dest->TClass = Src->TClass; + Dest->P_Key = Src->P_Key; + Dest->RateSelector = Src->RateSelector; + Dest->Rate = Src->Rate; + Dest->PktLifeTimeSelector = Src->PktLifeTimeSelector; + Dest->PktLifeTime = Src->PktLifeTime; + Dest->SL = Src->u1.s.SL; + Dest->HopLimit = Src->u1.s.HopLimit; + Dest->Scope = Src->Scope; + Dest->JoinFullMember = Src->JoinFullMember; + Dest->JoinSendOnlyMember = Src->JoinSendOnlyMember; + Dest->JoinNonMember = Src->JoinNonMember; + Dest->ProxyJoin = Src->ProxyJoin; +} + +static __inline void +CONVERT_STL2IB_MCMEMBER_RECORD(STL_MCMEMBER_RECORD *Src, IB_MCMEMBER_RECORD *Dest) +{ + Dest->RID.MGID = Src->RID.MGID; + Dest->RID.PortGID = Src->RID.PortGID; + Dest->Q_Key = Src->Q_Key; + Dest->MLID = MCAST32_TO_MCAST16(Src->MLID); + Dest->MtuSelector = Src->MtuSelector; + Dest->Mtu = Src->Mtu; + Dest->TClass = Src->TClass; + Dest->P_Key = Src->P_Key; + Dest->RateSelector = Src->RateSelector; + Dest->Rate = Src->Rate; + Dest->PktLifeTimeSelector = Src->PktLifeTimeSelector; + Dest->PktLifeTime = Src->PktLifeTime; + Dest->u1.s.SL = Src->SL; + Dest->u1.s.FlowLabel = 0; + Dest->u1.s.HopLimit = Src->HopLimit; + Dest->Scope = Src->Scope; + Dest->JoinFullMember = Src->JoinFullMember; + Dest->JoinSendOnlyMember = Src->JoinSendOnlyMember; + Dest->JoinNonMember = Src->JoinNonMember; + Dest->ProxyJoin = Src->ProxyJoin; + Dest->Reserved = 0; + Dest->Reserved2 = 0; + Dest->Reserved3[0] = 0; + Dest->Reserved3[1] = 0; +} + +static __inline uint64 +REBUILD_COMPMSK_IB2STL_MCMEMBER_RECORD(uint64 mask) +{ + uint64 result = 0ull; + uint64 pos; + uint8 i; + + for (i = 0; i < 64; ++i) + { + pos = 1<member); + Dest->index = ntoh32(Dest->index); + Dest->slid = ntoh32(Dest->slid); + Dest->nodeGuid = ntoh64(Dest->nodeGuid); + Dest->portGuid = ntoh64(Dest->portGuid); +} + +static __inline void +BSWAPCOPY_STL_MCMEMBER_SYNCDB(STL_MCMEMBER_SYNCDB* Src, STL_MCMEMBER_SYNCDB* Dest) +{ + memcpy(Dest, Src, sizeof(STL_MCMEMBER_SYNCDB)); + BSWAP_STL_MCMEMBER_SYNCDB(Dest); +} + +static __inline void +BSWAP_STL_SMINFO_RECORD(STL_SMINFO_RECORD *Dest) +{ + Dest->RID.LID = ntoh32(Dest->RID.LID); + BSWAP_STL_SM_INFO(&Dest->SMInfo); +} + +static __inline void +BSWAPCOPY_STL_SMINFO_RECORD(STL_SMINFO_RECORD *Src, STL_SMINFO_RECORD *Dest) +{ + Dest->RID.LID = ntoh32(Src->RID.LID); + BSWAPCOPY_STL_SM_INFO(&Src->SMInfo, &Dest->SMInfo); +} + +static __inline void +BSWAP_STL_INFORM_INFO_RECORD(STL_INFORM_INFO_RECORD *Dest) +{ + Dest->RID.SubscriberLID = ntoh32(Dest->RID.SubscriberLID); + Dest->RID.Enum = ntoh16(Dest->RID.Enum); + BSWAP_STL_INFORM_INFO(&Dest->InformInfoData); +} + +static __inline void +BSWAPCOPY_STL_INFORM_INFO_RECORD(STL_INFORM_INFO_RECORD *Src, STL_INFORM_INFO_RECORD *Dest) +{ + Dest->RID.SubscriberLID = ntoh32(Src->RID.SubscriberLID); + Dest->RID.Enum = ntoh16(Src->RID.Enum); + BSWAPCOPY_STL_INFORM_INFO(&Src->InformInfoData, &Dest->InformInfoData); +} + +static __inline void +BSWAP_STL_LINK_RECORD(STL_LINK_RECORD *Dest) +{ + Dest->RID.FromLID = ntoh32(Dest->RID.FromLID); + Dest->ToLID = ntoh32(Dest->ToLID); +} + +static __inline void +BSWAPCOPY_STL_LINK_RECORD(STL_LINK_RECORD *Src, STL_LINK_RECORD *Dest) +{ + memcpy(Dest, Src, sizeof(STL_LINK_RECORD)); + BSWAP_STL_LINK_RECORD(Dest); +} + +static __inline void +BSWAP_STL_SERVICE_RECORD( STL_SERVICE_RECORD *Dest) +{ +#if CPU_LE + uint8 i; + + Dest->RID.ServiceID = ntoh64(Dest->RID.ServiceID); + Dest->RID.ServiceLID = ntoh32(Dest->RID.ServiceLID); + Dest->RID.ServiceP_Key = ntoh16(Dest->RID.ServiceP_Key); + BSWAP_IB_GID(&Dest->RID.ServiceGID); + + Dest->ServiceLease = ntoh32(Dest->ServiceLease); + ntoh(&Dest->ServiceKey[0], &Dest->ServiceKey[0], 16); + + Dest->Reserved = 0; + + for (i=0; i<8; ++i) + { + Dest->ServiceData16[i] = ntoh16(Dest->ServiceData16[i]); + } + for (i=0; i<4; ++i) + { + Dest->ServiceData32[i] = ntoh32(Dest->ServiceData32[i]); + } + for (i=0; i<2; ++i) + { + Dest->ServiceData64[i] = ntoh64(Dest->ServiceData64[i]); + } +#endif /* CPU_LE */ +} + +static __inline void BSWAPCOPY_STL_SERVICE_RECORD(STL_SERVICE_RECORD *Src, STL_SERVICE_RECORD *Dest) +{ + memcpy(Dest, Src, sizeof(STL_SERVICE_RECORD)); + BSWAP_STL_SERVICE_RECORD(Dest); +} + +static __inline void +BSWAP_STL_TRACE_RECORD(STL_TRACE_RECORD *Dest) +{ +#if CPU_LE + Dest->IDGeneration = ntoh16(Dest->IDGeneration); + Dest->ChassisID = ntoh64(Dest->ChassisID); + Dest->EntryPortID = ntoh64(Dest->EntryPortID); + Dest->ExitPortID = ntoh64(Dest->ExitPortID); +#endif /* CPU_LE */ +} + +static __inline void +BSWAPCOPY_STL_TRACE_RECORD(STL_TRACE_RECORD *Src, STL_TRACE_RECORD *Dest) +{ +#if CPU_LE + memcpy(Dest,Src,sizeof(STL_TRACE_RECORD)); + BSWAP_STL_TRACE_RECORD(Dest); +#endif /* CPU_LE */ +} + +static __inline void +BSWAP_STL_CABLE_INFO_RECORD(STL_CABLE_INFO_RECORD *Dest) +{ + Dest->LID = ntoh32(Dest->LID); + Dest->u1.AsReg16 = ntoh16(Dest->u1.AsReg16); +} + +static __inline void +BSWAPCOPY_STL_CABLE_INFO_RECORD(STL_CABLE_INFO_RECORD *Src, STL_CABLE_INFO_RECORD *Dest) +{ + *Dest = *Src; + BSWAP_STL_CABLE_INFO_RECORD(Dest); +} + +static __inline void +BSWAP_STL_VFINFO_RECORD(STL_VFINFO_RECORD *Dest) +{ + Dest->vfIndex = ntoh16(Dest->vfIndex); + Dest->pKey = ntoh16(Dest->pKey); + Dest->ServiceID = ntoh64(Dest->ServiceID); + BSWAP_IB_GID(&Dest->MGID); +} + +static __inline void +BSWAPCOPY_STL_VFINFO_RECORD(STL_VFINFO_RECORD *Src, STL_VFINFO_RECORD *Dest) +{ + *Dest = *Src; + BSWAP_STL_VFINFO_RECORD(Dest); + +} + +static __inline void +BSWAP_STL_QUARANTINED_NODE_RECORD(STL_QUARANTINED_NODE_RECORD *Dest) +{ + Dest->trustedLid = ntoh32(Dest->trustedLid); + Dest->trustedNodeGUID = ntoh64(Dest->trustedNodeGUID); + Dest->trustedNeighborNodeGUID = ntoh64(Dest->trustedNeighborNodeGUID); + Dest->quarantineReasons = ntoh32(Dest->quarantineReasons); + Dest->expectedNodeInfo.nodeGUID = ntoh64(Dest->expectedNodeInfo.nodeGUID); + Dest->expectedNodeInfo.portGUID = ntoh64(Dest->expectedNodeInfo.portGUID); + BSWAP_STL_NODE_INFO(&Dest->NodeInfo); +} + +static __inline void +BSWAPCOPY_STL_QUARANTINED_NODE_RECORD(STL_QUARANTINED_NODE_RECORD *Src, STL_QUARANTINED_NODE_RECORD *Dest) +{ + Dest->trustedLid = ntoh32(Src->trustedLid); + Dest->trustedNodeGUID = ntoh64(Src->trustedNodeGUID); + Dest->trustedPortNum = Src->trustedPortNum; + Dest->trustedNeighborNodeGUID = ntoh64(Src->trustedNeighborNodeGUID); + Dest->quarantineReasons = ntoh32(Src->quarantineReasons); + Dest->expectedNodeInfo.nodeGUID = ntoh64(Src->expectedNodeInfo.nodeGUID); + Dest->expectedNodeInfo.portGUID = ntoh64(Src->expectedNodeInfo.portGUID); + BSWAPCOPY_STL_NODE_INFO(&Src->NodeInfo, &Dest->NodeInfo); + memcpy(&(Dest->NodeDesc), &(Src->NodeDesc), sizeof(STL_NODE_DESCRIPTION)); + memcpy(&(Dest->expectedNodeInfo.nodeDesc), &(Src->expectedNodeInfo.nodeDesc), sizeof(STL_NODE_DESCRIPTION)); +} + +static __inline void +BSWAP_STL_CONGESTION_INFO_RECORD(STL_CONGESTION_INFO_RECORD *Dest) +{ + Dest->LID = ntoh32(Dest->LID); + Dest->reserved = ntoh32(Dest->reserved); + BSWAP_STL_CONGESTION_INFO(&Dest->CongestionInfo); +} + +static __inline void +BSWAPCOPY_STL_CONGESTION_INFO_RECORD(STL_CONGESTION_INFO_RECORD *Src, STL_CONGESTION_INFO_RECORD *Dest) +{ + Dest->LID = ntoh32(Src->LID); + Dest->reserved = ntoh32(Src->reserved); + memcpy(&(Dest->CongestionInfo), &(Src->CongestionInfo), sizeof(STL_CONGESTION_INFO)); + BSWAP_STL_CONGESTION_INFO(&Dest->CongestionInfo); +} + +static __inline void +BSWAP_STL_SWITCH_CONGESTION_SETTING_RECORD(STL_SWITCH_CONGESTION_SETTING_RECORD *Dest) +{ + Dest->LID = ntoh32(Dest->LID); + Dest->reserved = ntoh32(Dest->reserved); + BSWAP_STL_SWITCH_CONGESTION_SETTING(&Dest->SwitchCongestionSetting); +} +static __inline void +BSWAPCOPY_STL_SWITCH_CONGESTION_SETTING_RECORD(STL_SWITCH_CONGESTION_SETTING_RECORD *Src, STL_SWITCH_CONGESTION_SETTING_RECORD *Dest) +{ + Dest->LID = ntoh32(Src->LID); + Dest->reserved = ntoh32(Src->reserved); + memcpy(&(Dest->SwitchCongestionSetting), &(Src->SwitchCongestionSetting), sizeof(STL_SWITCH_CONGESTION_SETTING)); + BSWAP_STL_SWITCH_CONGESTION_SETTING(&Dest->SwitchCongestionSetting); +} + +static __inline void +BSWAP_STL_SWITCH_PORT_CONGESTION_SETTING_RECORD(STL_SWITCH_PORT_CONGESTION_SETTING_RECORD *Dest) +{ + Dest->RID.LID = ntoh32(Dest->RID.LID); + BSWAP_STL_SWITCH_PORT_CONGESTION_SETTING(&Dest->SwitchPortCongestionSetting, 1); +} +static __inline void +BSWAPCOPY_STL_SWITCH_PORT_CONGESTION_SETTING_RECORD(STL_SWITCH_PORT_CONGESTION_SETTING_RECORD *Src, STL_SWITCH_PORT_CONGESTION_SETTING_RECORD *Dest) +{ + *Dest = *Src; + BSWAP_STL_SWITCH_PORT_CONGESTION_SETTING_RECORD(Dest); +} + +static __inline void +BSWAP_STL_HFI_CONGESTION_SETTING_RECORD(STL_HFI_CONGESTION_SETTING_RECORD *Dest) +{ + Dest->LID = ntoh32(Dest->LID); + Dest->reserved = ntoh32(Dest->reserved); + BSWAP_STL_HFI_CONGESTION_SETTING(&Dest->HFICongestionSetting); +} +static __inline void +BSWAPCOPY_STL_HFI_CONGESTION_SETTING_RECORD(STL_HFI_CONGESTION_SETTING_RECORD *Src, STL_HFI_CONGESTION_SETTING_RECORD *Dest) +{ + Dest->LID = ntoh32(Src->LID); + Dest->reserved = ntoh32(Src->reserved); + memcpy(&(Dest->HFICongestionSetting), &(Src->HFICongestionSetting), sizeof(STL_HFI_CONGESTION_SETTING)); + BSWAP_STL_HFI_CONGESTION_SETTING(&Dest->HFICongestionSetting); +} + +static __inline void +BSWAP_STL_HFI_CONGESTION_CONTROL_TABLE_RECORD(STL_HFI_CONGESTION_CONTROL_TABLE_RECORD *Dest) +{ + Dest->RID.LID = ntoh32(Dest->RID.LID); + Dest->RID.BlockNum = ntoh16(Dest->RID.BlockNum); + Dest->reserved = ntoh16(Dest->reserved); + BSWAP_STL_HFI_CONGESTION_CONTROL_TABLE(&Dest->HFICongestionControlTable, 1); +} +static __inline void +BSWAPCOPY_STL_HFI_CONGESTION_CONTROL_TABLE_RECORD(STL_HFI_CONGESTION_CONTROL_TABLE_RECORD *Src, STL_HFI_CONGESTION_CONTROL_TABLE_RECORD *Dest) +{ + Dest->RID.LID = ntoh32(Src->RID.LID); + Dest->RID.BlockNum = ntoh16(Src->RID.BlockNum); + Dest->reserved = ntoh16(Src->reserved); + memcpy(&(Dest->HFICongestionControlTable), &(Src->HFICongestionControlTable), sizeof(STL_HFI_CONGESTION_CONTROL_TABLE)); + BSWAP_STL_HFI_CONGESTION_CONTROL_TABLE(&Dest->HFICongestionControlTable, 1); +} + +static __inline void +BSWAP_STL_BUFFER_CONTROL_TABLE_RECORD(STL_BUFFER_CONTROL_TABLE_RECORD *Dest) +{ + Dest->RID.LID = ntoh32(Dest->RID.LID); + BSWAP_STL_BUFFER_CONTROL_TABLE(&Dest->BufferControlTable); +} + +static __inline void +BSWAPCOPY_STL_BUFFER_CONTROL_TABLE_RECORD(STL_BUFFER_CONTROL_TABLE_RECORD *Src, STL_BUFFER_CONTROL_TABLE_RECORD *Dest) +{ + memcpy(Dest, Src, sizeof(STL_BUFFER_CONTROL_TABLE_RECORD)); + BSWAP_STL_BUFFER_CONTROL_TABLE_RECORD(Dest); +} + +static __inline void +BSWAP_STL_FABRICINFO_RECORD( + STL_FABRICINFO_RECORD *Dest + ) +{ +#if CPU_LE + Dest->NumHFIs = ntoh32(Dest->NumHFIs); + Dest->NumSwitches = ntoh32(Dest->NumSwitches); + Dest->NumInternalHFILinks = ntoh32(Dest->NumInternalHFILinks); + Dest->NumExternalHFILinks = ntoh32(Dest->NumExternalHFILinks); + Dest->NumInternalISLs = ntoh32(Dest->NumInternalISLs); + Dest->NumExternalISLs = ntoh32(Dest->NumExternalISLs); + Dest->NumDegradedHFILinks = ntoh32(Dest->NumDegradedHFILinks); + Dest->NumDegradedISLs = ntoh32(Dest->NumDegradedISLs); + Dest->NumOmittedHFILinks = ntoh32(Dest->NumOmittedHFILinks); + Dest->NumOmittedISLs = ntoh32(Dest->NumOmittedISLs); +#endif /* CPU_LE */ +} + + + +static __inline +void +BSWAP_STL_DEVICE_GROUP_NAME_RECORD(STL_DEVICE_GROUP_NAME_RECORD *Dest) +{ + +} + +static __inline +void +BSWAPCOPY_STL_DEVICE_GROUP_NAME_RECORD(STL_DEVICE_GROUP_NAME_RECORD *Src, STL_DEVICE_GROUP_NAME_RECORD *Dest) +{ + memcpy(Dest, Src, sizeof(STL_DEVICE_GROUP_NAME_RECORD)); + BSWAP_STL_DEVICE_GROUP_NAME_RECORD(Dest); +} + +static __inline +void +BSWAP_STL_DEVICE_GROUP_MEMBER_RECORD(STL_DEVICE_GROUP_MEMBER_RECORD *Dest) +{ + Dest->LID = ntoh32(Dest->LID); + Dest->GUID = ntoh64(Dest->GUID); +} + +static __inline +void +BSWAPCOPY_STL_DEVICE_GROUP_MEMBER_RECORD(STL_DEVICE_GROUP_MEMBER_RECORD *Src, STL_DEVICE_GROUP_MEMBER_RECORD *Dest) +{ + memcpy(Dest, Src, sizeof(STL_DEVICE_GROUP_MEMBER_RECORD)); + BSWAP_STL_DEVICE_GROUP_MEMBER_RECORD(Dest); +} + +static __inline void +BSWAP_STL_DEVICE_TREE_MEMBER_RECORD(STL_DEVICE_TREE_MEMBER_RECORD *Dest) +{ + uint32 i; + Dest->LID = ntoh32(Dest->LID); + Dest->GUID = ntoh64(Dest->GUID); + Dest->SystemImageGUID = ntoh64(Dest->SystemImageGUID); + for (i = 0; i < STL_MAX_PORTMASK; i++) { + Dest->portMaskAct[i] = ntoh64(Dest->portMaskAct[i]); + } + for (i = 0; i < STL_MAX_PORTMASK; i++) { + Dest->portMaskPortLinkMode[i] = ntoh64(Dest->portMaskPortLinkMode[i]); + } +} + +static __inline +void +BSWAPCOPY_STL_DEVICE_TREE_MEMBER_RECORD(STL_DEVICE_TREE_MEMBER_RECORD *Src, STL_DEVICE_TREE_MEMBER_RECORD *Dest) +{ + memcpy(Dest, Src, sizeof(STL_DEVICE_TREE_MEMBER_RECORD)); + BSWAP_STL_DEVICE_TREE_MEMBER_RECORD(Dest); +} + +#ifndef IB_MAX_UCAST_LID +#define IB_MAX_UCAST_LID 0xBFFF +#endif +/** + * If STL LID falls within the IB unicast LID range, + * just return the LID. If it falls outside the range + * return the last 14 bits of the LID + */ +#define STL_TO_IB_UCAST_LID(x) ((uint16) (((x) > IB_MAX_UCAST_LID) ?\ + ((x) & 0x3FFF) : (x))) +#define MAKE_OPA_GID_IID(lid) (((uint64)OUI_TRUESCALE << 40) | (uint64)(lid)) + + +static __inline void +BSWAP_STL_SWITCH_COST(STL_SWITCH_COST *cost) +{ + cost->DLID = ntoh32(cost->DLID); + cost->value = ntoh16(cost->value); +} + +static __inline void +BSWAP_STL_SWITCH_COST_RECORD(STL_SWITCH_COST_RECORD *record) +{ + int i; + + record->SLID = ntoh32(record->SLID); + for (i = 0; i < STL_SWITCH_COST_NUM_ENTRIES; ++i) { + BSWAP_STL_SWITCH_COST(record->Cost); + } +} + +// +// OpaServiceRecord_t - This is the same as the original with a +// timestamp appended. +// +typedef struct { + STL_SERVICE_RECORD serviceRecord; + uint64_t expireTime; + uint8_t pkeyDefined;// was the record created using pkey mask? +} OpaServiceRecord_t; +typedef OpaServiceRecord_t * OpaServiceRecordp; /* pointer to record */ + +#include "iba/public/ipackoff.h" + +#if defined (__cplusplus) +} +#endif +#endif //__STL_SA_PRIV_H__ + diff --git a/IbAccess/Common/Inc/stl_sa_types.h b/IbAccess/Common/Inc/stl_sa_types.h new file mode 100644 index 0000000..9e24d1b --- /dev/null +++ b/IbAccess/Common/Inc/stl_sa_types.h @@ -0,0 +1,1568 @@ +/* BEGIN_ICS_COPYRIGHT7 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT7 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +/* + * SA MADs + * + * General Notes: + * + * (1) Structures are defined in the most readable manner rather than + * what might be most useful for the coder or the compiler. Compiler + * hints (i.e., PACK_SUFFIX) are omitted, blocks of data may be + * defined as multi-dimensional arrays when useful, and so on. + * + * (2) An effort has been made to ensure that 32-bit fields fall on a 4 byte + * boundary and 64-bit fields fall on an 8 byte boundary. In addition, + * SA records are set as multiples of 8-bytes in order to preserve + * alignment across multi-record responses. + * + * (3) When extending a LID to 32-bits would break word alignment of other + * fields, the process was to: + * (a) First, remove existing reserved fields if this will restore + * alignment. + * (b) If (a) is not possible, consider moving fields if this will + * restore alignment. + * (c) If (b) fails, add new reserved fields to restore alignment. + * + * (4) In this document, attributes are listed in the same order they appear + * in the IB spec. Where a new attribute is added, it is added after + * the existing attribute it was modeled after. + * + * (5) The use of "Jumbo" (>256 byte) MADs are only used when needed. For + * table-based MADs, RMPP is the preferred solution. + * + */ + +#ifndef __STL_SA_H__ +#define __STL_SA_H__ + +#include "iba/stl_mad_types.h" +#include "iba/ib_sa_records.h" + +#if defined (__cplusplus) +extern "C" { +#endif + +#include "iba/public/ipackon.h" + +#define STL_SA_CLASS_VERSION 0x80 + +/* + * Subnet Administration Attribute IDs Adapted from IB + */ +#define STL_SA_ATTR_CLASS_PORT_INFO 0x0001 +#define STL_SA_ATTR_NOTICE 0x0002 +#define STL_SA_ATTR_INFORM_INFO 0x0003 +#define STL_SA_ATTR_NODE_RECORD 0x0011 +#define STL_SA_ATTR_PORTINFO_RECORD 0x0012 +#define STL_SA_ATTR_SC_MAPTBL_RECORD 0x0013 // REPLACES SL TO VL! +#define STL_SA_ATTR_SWITCHINFO_RECORD 0x0014 +#define STL_SA_ATTR_LINEAR_FWDTBL_RECORD 0x0015 +//#define STL_SA_ATTR_RANDOM_FWD_TBL_RECORD 0x0016 // Undefined in STL. +#define STL_SA_ATTR_MCAST_FWDTBL_RECORD 0x0017 +#define STL_SA_ATTR_SMINFO_RECORD 0x0018 +#define STL_SA_ATTR_LINK_SPD_WDTH_PAIRS_RECORD 0x0019 // Defined but never impl'ed +//Available 0x001A-0x001F +#define STL_SA_ATTR_LINK_RECORD 0x0020 +//#define STL_SA_ATTR_GUIDINFO_RECORD 0x0030 // Undefined in STL. +#define STL_SA_ATTR_SERVICE_RECORD 0x0031 +#define STL_SA_ATTR_P_KEY_TABLE_RECORD 0x0033 +#define STL_SA_ATTR_PATH_RECORD 0x0035 +#define STL_SA_ATTR_VLARBTABLE_RECORD 0x0036 +#define STL_SA_ATTR_MCMEMBER_RECORD 0x0038 +#define STL_SA_ATTR_TRACE_RECORD 0x0039 +#define STL_SA_ATTR_MULTIPATH_GID_RECORD 0x003A +#define STL_SA_ATTR_SERVICEASSOCIATION_RECORD 0x003B /* not implemented */ +//Available 0x003C-0x007F +#define STL_SA_ATTR_INFORM_INFO_RECORD 0x00F3 + +/* + * Subnet Administration Attribute IDs New for STL + */ +#define STL_SA_ATTR_SL2SC_MAPTBL_RECORD 0x0080 +#define STL_SA_ATTR_SC2SL_MAPTBL_RECORD 0x0081 +#define STL_SA_ATTR_SC2VL_NT_MAPTBL_RECORD 0x0082 +#define STL_SA_ATTR_SC2VL_T_MAPTBL_RECORD 0x0083 +#define STL_SA_ATTR_SC2VL_R_MAPTBL_RECORD 0x0084 +#define STL_SA_ATTR_PGROUP_FWDTBL_RECORD 0x0085 +#define STL_SA_ATTR_MULTIPATH_GUID_RECORD 0x0086 /* not implemented */ +#define STL_SA_ATTR_MULTIPATH_LID_RECORD 0x0087 /* not implemented */ +#define STL_SA_ATTR_CABLE_INFO_RECORD 0x0088 +#define STL_SA_ATTR_VF_INFO_RECORD 0x0089 // Previously vendor specific +#define STL_SA_ATTR_PORT_STATE_INFO_RECORD 0x008A +#define STL_SA_ATTR_PORTGROUP_TABLE_RECORD 0x008B +#define STL_SA_ATTR_BUFF_CTRL_TAB_RECORD 0x008C +#define STL_SA_ATTR_FABRICINFO_RECORD 0x008D +#define STL_SA_ATTR_QUARANTINED_NODE_RECORD 0x0090 // Previously vendor specific +#define STL_SA_ATTR_CONGESTION_INFO_RECORD 0x0091 // Previously vendor specific +#define STL_SA_ATTR_SWITCH_CONG_RECORD 0x0092 // Previously vendor specific +#define STL_SA_ATTR_SWITCH_PORT_CONG_RECORD 0x0093 // Previously vendor specific +#define STL_SA_ATTR_HFI_CONG_RECORD 0x0094 // Previously vendor specific +#define STL_SA_ATTR_HFI_CONG_CTRL_RECORD 0x0095 // Previously vendor specific + + + +#define STL_SA_ATTR_DG_MEMBER_RECORD 0x009B +#define STL_SA_ATTR_DG_NAME_RECORD 0x009C +#define STL_SA_ATTR_DT_MEMBER_RECORD 0x009D + + +#define STL_SA_ATTR_SWITCH_COST_RECORD 0x00A3 + +//#define STL_SA_ATTR_JOB_ROUTE_RECORD 0xffb2 // Never implemented. +//#define STL_SA_ATTR_CG_RECORD 0xff40 // Never implemented. +//#define STL_SA_ATTR_CG_STATUS_RECORD 0xff41 // Never implemented. +//#define STL_SA_ATTR_CFT_RECORD 0xff42 // Never implemented. + +/* Subnet Administration MAD status values */ +#define STL_MAD_STATUS_STL_SA_UNAVAILABLE 0x0100 // SA unavailable + +/* + * SA capability mask defines + */ +#define STL_SA_CAPABILITY_MULTICAST_SUPPORT 0x0200 +#define STL_SA_CAPABILITY_MULTIPATH_SUPPORT 0x0400 +#define STL_SA_CAPABILITY_PORTINFO_CAPMASK_MATCH 0x2000 +#define STL_SA_CAPABILITY_PA_SERVICES_SUPPORT 0x8000 + +/* 32 bit values, lower 27 bits are capabilities*/ +#define STL_SA_CAPABILITY2_QOS_SUPPORT 0x0000002 +#define STL_SA_CAPABILITY2_MFTTOP_SUPPORT 0x0000008 +#define STL_SA_CAPABILITY2_FULL_PORTINFO 0x0000040 +#define STL_SA_CAPABILITY2_EXT_SUPPORT 0x0000080 +#define STL_SA_CAPABILITY2_DGDTRECORD_SUPPORT 0x1000000 +#define STL_SA_CAPABILITY2_SWCOSTRECORD_SUPPORT 0x2000000 + +/* SA Capmask Bits to return on IB SA ClassPortInfo */ +#define IB_SA_CAPABILITY_MASK(capmask) (capmask & \ + (STL_CLASS_PORT_CAPMASK_TRAP | \ + STL_CLASS_PORT_CAPMASK_NOTICE | \ + STL_CLASS_PORT_CAPMASK_CM2 | \ + STL_SA_CAPABILITY_MULTICAST_SUPPORT | \ + STL_SA_CAPABILITY_MULTIPATH_SUPPORT | \ + STL_SA_CAPABILITY_PORTINFO_CAPMASK_MATCH | \ + STL_SA_CAPABILITY_PA_SERVICES_SUPPORT)) + +/* SA Capmask2 Bits to return on IB SA ClassPortInfo */ +#define IB_SA_CAPABILITY2_MASK(capmask) (capmask & \ + (STL_SA_CAPABILITY2_QOS_SUPPORT | \ + STL_SA_CAPABILITY2_MFTTOP_SUPPORT | \ + STL_SA_CAPABILITY2_FULL_PORTINFO | \ + STL_SA_CAPABILITY2_EXT_SUPPORT)) + +static __inline void +StlSaClassPortInfoCapMask(char buf[80], uint16 cmask) +{ + if (!cmask) { + snprintf(buf, 80, "-"); + } else { + snprintf(buf, 80, "%s%s%s%s%s%s%s", + (cmask & STL_CLASS_PORT_CAPMASK_TRAP) ? "Trap " : "", + (cmask & STL_CLASS_PORT_CAPMASK_NOTICE) ? "Notice " : "", + (cmask & STL_CLASS_PORT_CAPMASK_CM2) ? "CapMask2 " : "", + /* Class Specific */ + (cmask & STL_SA_CAPABILITY_MULTICAST_SUPPORT) ? "MultiCast " : "", + (cmask & STL_SA_CAPABILITY_MULTIPATH_SUPPORT) ? "MultiPath " : "", + (cmask & STL_SA_CAPABILITY_PORTINFO_CAPMASK_MATCH) ? "PortInfoMask " : "", + (cmask & STL_SA_CAPABILITY_PA_SERVICES_SUPPORT) ? "PartService " : ""); + } +} +static __inline void +StlSaClassPortInfoCapMask2(char buf[80], uint32 cmask) +{ + if (!cmask) { + snprintf(buf, 80, "-"); + } else { + snprintf(buf, 80, "%s%s%s%s%s%s", + (cmask & STL_SA_CAPABILITY2_QOS_SUPPORT) ? "QoS " : "", + (cmask & STL_SA_CAPABILITY2_MFTTOP_SUPPORT) ? "MFTTop " : "", + (cmask & STL_SA_CAPABILITY2_FULL_PORTINFO) ? "FullPortInfo " : "", + (cmask & STL_SA_CAPABILITY2_EXT_SUPPORT) ? "ExtSpeed " : "", + (cmask & STL_SA_CAPABILITY2_DGDTRECORD_SUPPORT) ? "DG/DT " : "", + (cmask & STL_SA_CAPABILITY2_SWCOSTRECORD_SUPPORT) ? "SwCost " : ""); + } +} + +/* + * NodeRecord + * + * STL Differences: + * Extended LID to 32 bits. + * Reserved added to 8-byte-align structures. + */ +typedef struct { + struct { + STL_LID LID; + } PACK_SUFFIX RID; + + uint32 Reserved; + + STL_NODE_INFO NodeInfo; + + STL_NODE_DESCRIPTION NodeDesc; + +} PACK_SUFFIX STL_NODE_RECORD; + +/* ComponentMask bits */ +#define STL_NODE_RECORD_COMP_LID 0x00000001 +/* reserved field 0x00000002 */ +#define STL_NODE_RECORD_COMP_BASEVERSION 0x00000004 +#define STL_NODE_RECORD_COMP_CLASSVERSION 0x00000008 +#define STL_NODE_RECORD_COMP_NODETYPE 0x00000010 +#define STL_NODE_RECORD_COMP_NUMPORTS 0x00000020 +/* reserved field 0x00000040 */ +#define STL_NODE_RECORD_COMP_SYSIMAGEGUID 0x00000080 +#define STL_NODE_RECORD_COMP_NODEGUID 0x00000100 +#define STL_NODE_RECORD_COMP_PORTGUID 0x00000200 +#define STL_NODE_RECORD_COMP_PARTITIONCAP 0x00000400 +#define STL_NODE_RECORD_COMP_DEVICEID 0x00000800 +#define STL_NODE_RECORD_COMP_REVISION 0x00001000 +#define STL_NODE_RECORD_COMP_LOCALPORTNUM 0x00002000 +#define STL_NODE_RECORD_COMP_VENDORID 0x00004000 +#define STL_NODE_RECORD_COMP_NODEDESC 0x00008000 + +/* + * PortInfoRecord + * + * STL Differences: + * EndPortLID extended to 32 bits. + * RID.Reserved field changed to a bitfield to comply with proposed + * IBTA 1.3 spec. + * Reserved added to qword-align PortInfoData. + * RID.PortNum for HFI will return HFI port number + */ +#define STL_NUM_LINKDOWN_REASONS 8 + +typedef struct { + uint8 Reserved[6]; + uint8 NeighborLinkDownReason; + uint8 LinkDownReason; + uint64 Timestamp; +} PACK_SUFFIX STL_LINKDOWN_REASON; + +/** + * Returns the next index in an array of STL_LINKDOWN_REASONS of size + * STL_NUM_LINKDOWN_REASONS to use. Uses the first free space or the + * LinkDownReason with the oldest timestamp. + */ +static __inline__ int STL_LINKDOWN_REASON_NEXT_INDEX(STL_LINKDOWN_REASON* ldr) { + int i; + int selectedIndex = 0; + uint64 earliestTimestamp = 0xffffffffffffffffll; + + for(i = 0; i < STL_NUM_LINKDOWN_REASONS; i++) { + if(ldr[i].Timestamp == 0) { + return i; + } else if(ldr[i].Timestamp < earliestTimestamp){ + selectedIndex = i; + earliestTimestamp = ldr[i].Timestamp; + } + } + + return selectedIndex; +} + +/** + * Returns the most recent stored LinkDownReason + */ +static __inline__ int STL_LINKDOWN_REASON_LAST_INDEX(STL_LINKDOWN_REASON* ldr) { + int i; + int selectedIndex = -1; + uint64 earliestTimestamp = 0x0ll; + + for(i = 0; i < STL_NUM_LINKDOWN_REASONS; i++) { + if(ldr[i].Timestamp > earliestTimestamp){ + selectedIndex = i; + earliestTimestamp = ldr[i].Timestamp; + } + } + + return selectedIndex; +} + +typedef struct { + struct { + STL_LID EndPortLID; + uint8 PortNum; /* for switch or HFI: port numnber */ + uint8 Reserved; + } PACK_SUFFIX RID; + + uint16 Reserved; + + STL_PORT_INFO PortInfo; + STL_LINKDOWN_REASON LinkDownReasons[STL_NUM_LINKDOWN_REASONS]; + +} PACK_SUFFIX STL_PORTINFO_RECORD; + +/* ComponentMask bits */ +/* + * The component mask bits for port info deviate from the IB standard + * because there are too many fields in port info to enumerate. At + * this time only the following mask bits are defined. All other bits + * are reserved for future expansion. + */ +#define STL_PORTINFO_RECORD_COMP_ENDPORTLID 0x0000000000000001ll +#define STL_PORTINFO_RECORD_COMP_PORTNUM 0x0000000000000002ll +#define STL_PORTINFO_RECORD_COMP_OPTIONS 0x0000000000000004ll +#define STL_PORTINFO_RECORD_COMP_CAPABILITYMASK 0x0000000000000008ll + +/* + * P_KeyTableRecord + * + * STL Differences: + * LID extended to 32 bits. + * Reserved shortened to restore alignment. + * RID.PortNum for HFI will return HFI port number + */ +typedef struct { + struct { + uint32 LID; + uint16 Blocknum; + uint8 PortNum; /* for switch or HFI: port numnber */ + } PACK_SUFFIX RID; + + uint8 Reserved; + + STL_PARTITION_TABLE PKeyTblData; + +} PACK_SUFFIX STL_P_KEY_TABLE_RECORD; + +#define STL_PKEYTABLE_RECORD_COMP_LID 0x00000001 +#define STL_PKEYTABLE_RECORD_COMP_BLOCKNUM 0x00000002 +#define STL_PKEYTABLE_RECORD_COMP_PORTNUM 0x00000004 + +/* + * SCMappingTableRecord + * + * Used for querying the SA for SC to SC Mapping information about a + * single input/output pair. + * + * + * STL Differences: + * LID extended to 32 bits. Each entry in the table is widened to 8 bits, + * the top 3 bits of each entry MUST be zero. This was done in + * preference to trying to pack 5 bit fields into multiples of 8 bits. + * + */ +typedef struct { + struct { + STL_LID LID; + uint8 InputPort; + uint8 OutputPort; + } PACK_SUFFIX RID; + IB_BITFIELD2(uint8, + RID_Secondary:1, + Reserved2:7); + uint8 Reserved; + + STL_SC Map[STL_MAX_SCS]; + +} PACK_SUFFIX STL_SC_MAPPING_TABLE_RECORD; + +#define STL_SC2SC_RECORD_COMP_LID 0x0000000000000001ull +#define STL_SC2SC_RECORD_COMP_INPUTPORT 0x0000000000000002ull +#define STL_SC2SC_RECORD_COMP_OUTPUTPORT 0x0000000000000004ull + +/* + * SL2SCMappingTableRecord + * + * STL Differences: + * New for STL. + */ +typedef struct { + struct { + STL_LID LID; + uint16 Reserved; + } PACK_SUFFIX RID; + + uint16 Reserved2; + + STL_SC SLSCMap[STL_MAX_SLS]; + +} PACK_SUFFIX STL_SL2SC_MAPPING_TABLE_RECORD; + +#define STL_SL2SC_RECORD_COMP_LID 0x0000000000000001ull + +/* + * SC2SLMappingTableRecord + * + * STL Differences: + * New for STL. + */ +typedef struct { + struct { + STL_LID LID; + uint16 Reserved; + } PACK_SUFFIX RID; + + uint16 Reserved2; + + STL_SL SCSLMap[STL_MAX_SCS]; + +} PACK_SUFFIX STL_SC2SL_MAPPING_TABLE_RECORD; + +#define STL_SC2SL_RECORD_COMP_LID 0x0000000000000001ull + +/* + * SC2VL Mapping Table Records + * + * There are three possible SC to VL mapping tables: NT, T and R. SC2VL_R + * will not be implemented in STL Gen 1. While they are all three separate + * SA MAD attributes, they all have identical structure. + */ +typedef struct { + struct { + STL_LID LID; + uint8 Port; /* for switch or HFI: port numnber */ + } PACK_SUFFIX RID; + + uint8 Reserved[3]; + + STL_VL SCVLMap[STL_MAX_SCS]; + +} PACK_SUFFIX STL_SC2VL_R_MAPPING_TABLE_RECORD; + +typedef STL_SC2VL_R_MAPPING_TABLE_RECORD STL_SC2PVL_T_MAPPING_TABLE_RECORD; +typedef STL_SC2VL_R_MAPPING_TABLE_RECORD STL_SC2PVL_NT_MAPPING_TABLE_RECORD; +typedef STL_SC2VL_R_MAPPING_TABLE_RECORD STL_SC2PVL_R_MAPPING_TABLE_RECORD; + +#define STL_SC2VL_R_RECORD_COMP_LID 0x0000000000000001ull +#define STL_SC2VL_R_RECORD_COMP_PORT 0x0000000000000002ull + +/* + * SwitchInfoRecord + * + * STL Differences + * Old LID/Reserved RID replaced with 32 bit LID. + * Reserved added to align SwitchInfoData. + */ +typedef struct { + struct { + STL_LID LID; + } PACK_SUFFIX RID; + + uint32 Reserved; + + STL_SWITCH_INFO SwitchInfoData; +} PACK_SUFFIX STL_SWITCHINFO_RECORD; + +#define STL_SWITCHINFO_RECORD_COMP_LID 0x0000000000000001ull +/* Reserved 0x0000000000000002ull */ +#define STL_SWITCHINFO_RECORD_COMP_LFDBCAP 0x0000000000000004ull +/* Reserved 0x0000000000000008ull */ +#define STL_SWITCHINFO_RECORD_COMP_MFDBCAP 0x0000000000000010ull +#define STL_SWITCHINFO_RECORD_COMP_LFDBTOP 0x0000000000000020ull +/* Reserved 0x0000000000000040ull */ +#define STL_SWITCHINFO_RECORD_COMP_MFDBTOP 0x0000000000000080ull +#define STL_SWITCHINFO_RECORD_COMP_COLLCAP 0x0000000000000100ull +#define STL_SWITCHINFO_RECORD_COMP_COLLTOP 0x0000000000000200ull +/* Reserved 0x0000000000000400ull */ +#define STL_SWITCHINFO_RECORD_COMP_IPPRIMARY 0x0000000000000800ull +#define STL_SWITCHINFO_RECORD_COMP_IPSECONDARY 0x0000000000001000ull +#define STL_SWITCHINFO_RECORD_COMP_PORTSTATECHG 0x0000000000020000ull +#define STL_SWITCHINFO_RECORD_COMP_LIFETIME 0x0000000000040000ull +#define STL_SWITCHINFO_RECORD_COMP_PENFCAP 0x0000000000080000ull +#define STL_SWITCHINFO_RECORD_COMP_PORTGROUPCAP 0x0000000000100000ull +#define STL_SWITCHINFO_RECORD_COMP_PORTGROUPTOP 0x0000000000200000ull +#define STL_SWITCHINFO_RECORD_COMP_RMODESUPPORTEED 0x0000000000400000ull +#define STL_SWITCHINFO_RECORD_COMP_RMODEENABLED 0x0000000000800000ull +/* Reserved 0x0000000001000000ull */ +/* Reserved 0x0000000002000000ull */ +/* Reserved 0x0000000004000000ull */ +/* Reserved 0x0000000008000000ull */ +#define STL_SWITCHINFO_RECORD_COMP_EP0 0x0000000010000000ull +/* Reserved 0x0000000020000000ull */ +/* Reserved 0x0000000040000000ull */ +#define STL_SWITCHINFO_RECORD_COMP_COLLMASK 0x0000000080000000ull +#define STL_SWITCHINFO_RECORD_COMP_MCMASK 0x0000000100000000ull +#define STL_SWITCHINFO_RECORD_COMP_ARLOSTONLY 0x0000000200000000ull +#define STL_SWITCHINFO_RECORD_COMP_ARPAUSE 0x0000000400000000ull +#define STL_SWITCHINFO_RECORD_COMP_ARENABLE 0x0000000800000000ull +#define STL_SWITCHINFO_RECORD_COMP_ARALGORITHM 0x0000001000000000ull +#define STL_SWITCHINFO_RECORD_COMP_ARFREQ 0x0000002000000000ull +#define STL_SWITCHINFO_RECORD_COMP_ARTHRESHOLD 0x0000004000000000ull +/* Reserved 0x0000008000000000ull */ +#define STL_SWITCHINFO_RECORD_COMP_CAPMASK 0x0000010000000000ull +#define STL_SWITCHINFO_RECORD_COMP_CMCOLLECTIVES 0x0000020000000000ull + +/* + * LFTRecord + * + * Blocks are still defined as 64 bytes long to be consistent with IB. + * + * STL Differences: + * + * LID extended to 32 bits. + * BlockNum extended to 18 bits. + */ +typedef struct { + struct { + STL_LID LID; + IB_BITFIELD2(uint32, + Reserved:14, + BlockNum:18); + } PACK_SUFFIX RID; + + /* 8 bytes */ + + uint8 LinearFdbData[64]; + + /* 72 bytes */ +} PACK_SUFFIX STL_LINEAR_FORWARDING_TABLE_RECORD; + +#define STL_LFT_RECORD_COMP_LID 0x0000000000000001ull +/* Reserved 0x0000000000000002ull */ +#define STL_LFT_RECORD_COMP_BLOCKNUM 0x0000000000000004ull + + +/* + * MFTRecord + * + * NOTES: + * In IB the width of the PORTMASK data type was defined as only 16 + * bits, requiring the SM to iterate over 3 different positions values + * to retrieve the MFTs for a 48-port switch. + * For this reason PORTMASK is now defined as 64 bits wide, eliminating + * the need to use the "position" attribute in the Gen 1 & Gen 2 + * generations of hardware. + * + * As above, a "block" is defined as 64 bytes; therefore a single block + * will contain 8 MFT records. The consumer should use GetTable() and + * RMPP to retrieve more than one block. As with the RFT, BlockNum is + * defined as 21 bits, providing for a total of 2^24 LIDs. + * + * STL Differences: + * PORTMASK is now 64 bits. + * LID is now 32 bits. + * Position is now 2 bits. + * Reserved is now 9 bits. + * BlockNum is now 21 bits. + * Reserved2 removed to preserve word alignment. + */ + +#define STL_MFTB_WIDTH 64 +#define STL_MFTB_MAX_POSITION 4 +typedef struct _STL_MULTICAST_FORWARDING_TABLE_RECORD { + struct { + STL_LID LID; // Port 0 of the switch. + + STL_FIELDUNION3(u1, 32, + Position:2, + Reserved:9, + BlockNum:21); + } PACK_SUFFIX RID; + + STL_MULTICAST_FORWARDING_TABLE MftTable; + +} PACK_SUFFIX STL_MULTICAST_FORWARDING_TABLE_RECORD; + +#define STL_MFTB_RECORD_COMP_LID 0x0000000000000001ull +#define STL_MFTB_RECORD_COMP_POSITIONl 0x0000000000000002ull +/* Reserved 0x0000000000000004ull */ +#define STL_MFTB_RECORD_COMP_BLOCKNUM 0x0000000000000008ull + +/* + * Port Group Table Record + * + * Defines which ports are associated with which port groups. + * For each query, BlockNum defines a block of port groups, from 0-31, + * with each block containing 8 port groups. Position identifies a group + * of ports with 0 being ports 1-64, 1 being ports 65-128, etc. + * + * This is nearly optimal; only switches that support more than 248 port groups + * will require two queries to read the entire table. + * + */ +#define STL_PGTB_NUM_ENTRIES_PER_BLOCK 8 +typedef struct { + struct { + STL_LID LID; + IB_BITFIELD3(uint16, + Position:2, + Reserved:9, + BlockNum:5); + } PACK_SUFFIX RID; + + uint16 Reserved2; + + STL_PORTMASK GroupBlock[STL_PGTB_NUM_ENTRIES_PER_BLOCK]; + +} PACK_SUFFIX STL_PORT_GROUP_TABLE_RECORD; + +#define STL_PGTB_RECORD_COMP_LID 0x0000000000000001ull +#define STL_PGTB_RECORD_COMP_POSITION 0x0000000000000002ull +#define STL_PGTB_RECORD_COMP_BLOCKNUM 0x0000000000000004ull + +/* + * Port Group Forwarding Table Record + * + * Maps LIDs to Port Groups. + * + * New for STL. Similar to the preceding forwarding table records. + * + */ + +#define STL_PGFDB_NUM_ENTRIES_PER_BLOCK 64 +typedef struct { + struct { + STL_LID LID; + + STL_FIELDUNION2(u1, 32, + Reserved:14, + BlockNum:18); + } PACK_SUFFIX RID; + + PORT PGFdbData[STL_PGFDB_NUM_ENTRIES_PER_BLOCK]; + +} PACK_SUFFIX STL_PORT_GROUP_FORWARDING_TABLE_RECORD; + +#define STL_PGFWDTB_RECORD_COMP_LID 0x0000000000000001ull +#define STL_PGFWDTB_RECORD_COMP_BLOCKNUM 0x0000000000000002ull + +/* + * VLArbitrationRecord + * + * STL Differences: + * Switch LID extended. + * Blocknum now defined as 0 - 3 as per the VL Arbitration Table MAD. + * Length of Low, High tables extended to 128 bytes. + * Preempt table added. + * RID.OutputPortNum for HFI will return port number + */ +typedef struct { + struct { + STL_LID LID; + uint8 OutputPortNum; /* for switch or HFI: port numnber */ + uint8 BlockNum; + } PACK_SUFFIX RID; + + uint16 Reserved; + + STL_VLARB_TABLE VLArbTable; + +} PACK_SUFFIX STL_VLARBTABLE_RECORD; +#define STL_VLARB_COMPONENTMASK_LID 0x0000000000000001ul +#define STL_VLARB_COMPONENTMASK_OUTPORTNUM 0x0000000000000002ul +#define STL_VLARB_COMPONENTMASK_BLOCKNUM 0x0000000000000004ul + + +/* + * MCMemberRecord + * + * STL Differences: + * MLID moved to new location for flit alignment. + * SL Lengthened to 5 bits. + * FlowLabel removed. + * Record is now 16 bits longer. + */ +typedef struct { + struct { + IB_GID MGID; + /* 16 bytes */ + + IB_GID PortGID; + + /* 32 bytes */ + + } PACK_SUFFIX RID; + + uint32 Q_Key; + + uint16 Reserved; // Used to be MLID. + + IB_BITFIELD2(uint8, + MtuSelector:2, + Mtu:6); + uint8 TClass; + + /* 40 bytes */ + uint16 P_Key; + + IB_BITFIELD2(uint8, + RateSelector:2, + Rate:6); + + IB_BITFIELD2(uint8, + PktLifeTimeSelector:2, + PktLifeTime:6); + + IB_BITFIELD3(uint32, + SL:5, + Reserved5:19, + HopLimit:8); + + /* 48 bytes */ + IB_BITFIELD5(uint8, + Scope:4, + Reserved4:1, + JoinSendOnlyMember:1, // NOTE: Treat these 4 JoinStates as 1 attr. + JoinNonMember:1, + JoinFullMember:1); + + IB_BITFIELD2(uint8, + ProxyJoin:1, + Reserved2:7); + + uint16 Reserved3; + + STL_LID MLID; // Moved for alignment. + + /* 56 bytes */ +} PACK_SUFFIX STL_MCMEMBER_RECORD; +#define STL_MCMEMBER_COMPONENTMASK_MGID 0x0000000000000001ull +#define STL_MCMEMBER_COMPONENTMASK_PORTGID 0x0000000000000002ull +#define STL_MCMEMBER_COMPONENTMASK_QKEY 0x0000000000000004ull +/* Reserved 0x0000000000000008ull */ +#define STL_MCMEMBER_COMPONENTMASK_MTU_SEL 0x0000000000000010ull +#define STL_MCMEMBER_COMPONENTMASK_MTU 0x0000000000000020ull +#define STL_MCMEMBER_COMPONENTMASK_OK_MTU ( STL_MCMEMBER_COMPONENTMASK_MTU_SEL \ + | STL_MCMEMBER_COMPONENTMASK_MTU ) +#define STL_MCMEMBER_COMPONENTMASK_TCLASS 0x0000000000000040ull +#define STL_MCMEMBER_COMPONENTMASK_PKEY 0x0000000000000080ull +#define STL_MCMEMBER_COMPONENTMASK_RATE_SEL 0x0000000000000100ull +#define STL_MCMEMBER_COMPONENTMASK_RATE 0x0000000000000200ull +#define STL_MCMEMBER_COMPONENTMASK_OK_RATE ( STL_MCMEMBER_COMPONENTMASK_RATE \ + | STL_MCMEMBER_COMPONENTMASK_RATE_SEL ) +#define STL_MCMEMBER_COMPONENTMASK_LIFE_SEL 0x0000000000000400ull +#define STL_MCMEMBER_COMPONENTMASK_LIFE 0x0000000000000800ull +#define STL_MCMEMBER_COMPONENTMASK_OK_LIFE ( STL_MCMEMBER_COMPONENTMASK_LIFE_SEL \ + | STL_MCMEMBER_COMPONENTMASK_LIFE ) +#define STL_MCMEMBER_COMPONENTMASK_SL 0x0000000000001000ull +/* Reserved 0x0000000000002000ull */ +#define STL_MCMEMBER_COMPONENTMASK_HOP 0x0000000000004000ull +#define STL_MCMEMBER_COMPONENTMASK_SCOPE 0x0000000000008000ull +/* Reserved 0x0000000000010000ull */ +#define STL_MCMEMBER_COMPONENTMASK_JNSTATE 0x0000000000020000ull +#define STL_MCMEMBER_COMPONENTMASK_OK_JOIN ( STL_MCMEMBER_COMPONENTMASK_MGID \ + | STL_MCMEMBER_COMPONENTMASK_JNSTATE \ + | STL_MCMEMBER_COMPONENTMASK_PORTGID ) +#define STL_MCMEMBER_COMPONENTMASK_PROXYJN 0x0000000000040000ull +#define STL_MCMEMBER_COMPONENTMASK_MLID 0x0000000000080000ull + +#define STL_MCMEMBER_COMPONENTMASK_OK_CREATE ( STL_MCMEMBER_COMPONENTMASK_PKEY \ + | STL_MCMEMBER_COMPONENTMASK_QKEY \ + | STL_MCMEMBER_COMPONENTMASK_SL \ + | STL_MCMEMBER_COMPONENTMASK_TCLASS \ + | STL_MCMEMBER_COMPONENTMASK_JNSTATE \ + | STL_MCMEMBER_COMPONENTMASK_PORTGID ) + +#define STL_MCMRECORD_GETJOINSTATE(REC) ( (REC)->JoinSendOnlyMember \ + | (REC)->JoinNonMember \ + | (REC)->JoinFullMember ) + +/* + * SMInfoRecord + * + * STL Differences: + * LID extended to 32 bits. + * Added Reserved to ensure word-alignment of SMInfo. + * Added Reserved2 to ensure word-alignment of GetTable() responses. + */ +typedef struct { + struct { + STL_LID LID; + } PACK_SUFFIX RID; + + uint32 Reserved; + + STL_SM_INFO SMInfo; + +} PACK_SUFFIX STL_SMINFO_RECORD; + +#define STL_SMINFO_RECORD_COMP_LID 0x0000000000000001ull +/* Reserved 0x0000000000000002ull */ +#define STL_SMINFO_RECORD_COMP_GUID 0x0000000000000004ull +#define STL_SMINFO_RECORD_COMP_SMKEY 0x0000000000000008ull +#define STL_SMINFO_RECORD_COMP_ACTCOUNT 0x0000000000000010ull +#define STL_SMINFO_RECORD_COMP_ETIME 0x0000000000000020ull +#define STL_SMINFO_RECORD_COMP_PRIORITY 0x0000000000000040ull +#define STL_SMINFO_RECORD_COMP_SMSTATEELEV 0x0000000000000080ull +#define STL_SMINFO_RECORD_COMP_SMSTATEINIT 0x0000000000000100ull +#define STL_SMINFO_RECORD_COMP_SMSTATECURR 0x0000000000000200ull + +/* + * InformInfoRecord + * + * Length is TBD. + * + * STL Differences: + * Replaced SubscriberGID with SubscriberLID. + * Reserved adjusted to preserve alignment. + * + */ +typedef struct { + struct { + STL_LID SubscriberLID; + uint16 Enum; + } PACK_SUFFIX RID; + + uint16 Reserved; + + STL_INFORM_INFO InformInfoData; +} PACK_SUFFIX STL_INFORM_INFO_RECORD; + +#define STL_INFORM_INFO_REC_COMP_SUBSCRIBER_LID 0x0000000000000001ll +#define STL_INFORM_INFO_REC_COMP_SUBSCRIBER_ENUM 0x0000000000000002ll +/* reserved 0x0000000000000004ll */ +#define STL_INFORM_INFO_REC_COMP_GID 0x0000000000000008ll +#define STL_INFORM_INFO_REC_COMP_LID_RANGE_BEGIN 0x0000000000000010ll +#define STL_INFORM_INFO_REC_COMP_LID_RANGE_END 0x0000000000000020ll +#define STL_INFORM_INFO_REC_COMP_LID_RANGE_GENERIC 0x0000000000000040ll +#define STL_INFORM_INFO_REC_COMP_LID_RANGE_SUBSCRIBE 0x0000000000000080ll +#define STL_INFORM_INFO_REC_COMP_LID_RANGE_TYPE 0x0000000000000100ll +/* reserved 0x0000000000000200ll */ +#define STL_INFORM_INFO_REC_COMP_LID_TRAP_NUMBER 0x0000000000000400ll +#define STL_INFORM_INFO_REC_COMP_LID_QPN 0x0000000000000800ll +/* reserved 0x0000000000001000ll */ +#define STL_INFORM_INFO_REC_COMP_LID_RESP_TIME 0x0000000000002000ll +/* reserved 0x0000000000004000ll */ +#define STL_INFORM_INFO_REC_COMP_LID_PRODUCER_TYPE 0x0000000000008000ll + +/* + * LinkRecord + * + * STL Differences: + * LIDs lengthened + * Reserved field added to preserve alignment. + * RID.FromPort and ToPort for HFI will return HFI port number + * LinkCondition field added to describe which link errors apply to the link when asking for this data. + * ErrorMask field added to provide detailed information on the particular errors that led to the LinkCondition error. + */ +typedef struct _STL_LINK_RECORD { + struct { + STL_LID FromLID; + uint8 FromPort; /* for switch or HFI: port number */ + } PACK_SUFFIX RID; + + uint8 ToPort; /* for switch or HFI: port number */ + + uint16 Reserved; + + STL_LID ToLID; +} PACK_SUFFIX STL_LINK_RECORD; + +#define STL_LINK_REC_COMP_FROM_LID 0x0000000000000001ll +#define STL_LINK_REC_COMP_FROM_PORT 0x0000000000000002ll +#define STL_LINK_REC_COMP_TO_PORT 0x0000000000000004ll +#define STL_LINK_REC_LINK_CONDITION 0x0000000000000008ll +#define STL_LINK_REC_COMP_TO_LID 0x0000000000000010ll +#define STL_LINK_REC_COMP_ERROR_MASK 0x0000000000000020ll + +/* These constants are used to describe the applicable link condition(s) */ +#define STL_LINK_REC_SLOWLINKS 0x0000000000000001ll +#define STL_LINK_REC_MISCONFIGLINKS 0x0000000000000002ll +#define STL_LINK_REC_MISCONNLINKS 0x0000000000000004ll + +/* + * ServiceRecord + * + * STL Differences + * Added of ServiceLID + * Moved Reserved field to maintain alignment. + */ +typedef struct { + struct { + uint64 ServiceID; + + STL_LID ServiceLID; + uint16 ServiceP_Key; + uint16 Reserved; + + IB_GID ServiceGID; + + } PACK_SUFFIX RID; + + uint32 ServiceLease; + + uint32 Reserved; + + uint8 ServiceKey[16]; + + uint8 ServiceName[64]; + + uint8 ServiceData8[16]; + + uint16 ServiceData16[8]; + + uint32 ServiceData32[4]; + + uint64 ServiceData64[2]; + +} PACK_SUFFIX STL_SERVICE_RECORD; + +#define STL_SERVICE_RECORD_COMP_SERVICEID 0x0000000000000001ull +#define STL_SERVICE_RECORD_COMP_SERVICELID 0x0000000000000002ull +#define STL_SERVICE_RECORD_COMP_SERVICEPKEY 0x0000000000000004ull +/* Reserved 0x0000000000000008ull */ +#define STL_SERVICE_RECORD_COMP_SERVICEGID 0x0000000000000010ull +#define STL_SERVICE_RECORD_COMP_SERVICELEASE 0x0000000000000020ull +/* Reserved 0x0000000000000040ull */ +#define STL_SERVICE_RECORD_COMP_SERVICEKEY 0x0000000000000080ull +#define STL_SERVICE_RECORD_COMP_SERVICENAME 0x0000000000000100ull +#define STL_SERVICE_RECORD_COMP_SERVICE_8_1 0x0000000000000200ull +#define STL_SERVICE_RECORD_COMP_SERVICE_8_2 0x0000000000000400ull +#define STL_SERVICE_RECORD_COMP_SERVICE_8_3 0x0000000000000800ull +#define STL_SERVICE_RECORD_COMP_SERVICE_8_4 0x0000000000001000ull +#define STL_SERVICE_RECORD_COMP_SERVICE_8_5 0x0000000000002000ull +#define STL_SERVICE_RECORD_COMP_SERVICE_8_6 0x0000000000004000ull +#define STL_SERVICE_RECORD_COMP_SERVICE_8_7 0x0000000000008000ull +#define STL_SERVICE_RECORD_COMP_SERVICE_8_8 0x0000000000010000ull +#define STL_SERVICE_RECORD_COMP_SERVICE_8_9 0x0000000000020000ull +#define STL_SERVICE_RECORD_COMP_SERVICE_8_10 0x0000000000040000ull +#define STL_SERVICE_RECORD_COMP_SERVICE_8_11 0x0000000000080000ull +#define STL_SERVICE_RECORD_COMP_SERVICE_8_12 0x0000000000100000ull +#define STL_SERVICE_RECORD_COMP_SERVICE_8_13 0x0000000000200000ull +#define STL_SERVICE_RECORD_COMP_SERVICE_8_14 0x0000000000400000ull +#define STL_SERVICE_RECORD_COMP_SERVICE_8_15 0x0000000000800000ull +#define STL_SERVICE_RECORD_COMP_SERVICE_8_16 0x0000000001000000ull +#define STL_SERVICE_RECORD_COMP_SERVICE_16_1 0x0000000002000000ull +#define STL_SERVICE_RECORD_COMP_SERVICE_16_2 0x0000000004000000ull +#define STL_SERVICE_RECORD_COMP_SERVICE_16_3 0x0000000008000000ull +#define STL_SERVICE_RECORD_COMP_SERVICE_16_4 0x0000000010000000ull +#define STL_SERVICE_RECORD_COMP_SERVICE_16_5 0x0000000020000000ull +#define STL_SERVICE_RECORD_COMP_SERVICE_16_6 0x0000000040000000ull +#define STL_SERVICE_RECORD_COMP_SERVICE_16_7 0x0000000080000000ull +#define STL_SERVICE_RECORD_COMP_SERVICE_16_8 0x0000000100000000ull +#define STL_SERVICE_RECORD_COMP_SERVICE_32_1 0x0000000200000000ull +#define STL_SERVICE_RECORD_COMP_SERVICE_32_2 0x0000000400000000ull +#define STL_SERVICE_RECORD_COMP_SERVICE_32_3 0x0000000800000000ull +#define STL_SERVICE_RECORD_COMP_SERVICE_32_4 0x0000001000000000ull +#define STL_SERVICE_RECORD_COMP_SERVICE_64_1 0x0000002000000000ull +#define STL_SERVICE_RECORD_COMP_SERVICE_64_2 0x0000004000000000ull + +/* + * ServiceAssociationRecord + * + * NOTE: No changes from IB version. + */ +typedef IB_SERVICEASSOCIATION_RECORD STL_SERVICEASSOCIATION_RECORD; + +/* + * TraceRecord + * + * STL Differences + * + * GIDPrefix deleted. + * EntryPort, ExitPort moved for alignment. + * Reserved2 added to word/qword-align NodeID. + */ +typedef struct { + uint16 IDGeneration; + uint8 Reserved; + uint8 NodeType; + uint8 EntryPort; + uint8 ExitPort; + uint16 Reserved2; + + uint64 NodeID; + uint64 ChassisID; + uint64 EntryPortID; + uint64 ExitPortID; + +} PACK_SUFFIX STL_TRACE_RECORD; + +/* + * MultiPathRecord + * + * STL Differences: + * RawTraffic is now reserved. + * Reserved2 moved, shortened. + * SL lengthened. + * L2 settings added. + * Reserved3 added to ensure alignment of gids. + */ +typedef struct { + IB_BITFIELD3(uint32, + Reserved1:4, + FlowLabel:20, + HopLimit:8); + + uint8 TClass; + + IB_BITFIELD2(uint8, + Reversible:1, + NumbPath:7); + + uint16 P_Key; + + IB_BITFIELD4(uint16, + QoSType:2, + QoSPriority:8, + Reserved2:1, + SL:5); + + IB_BITFIELD2(uint8, + MtuSelector:2, + Mtu:6); + + IB_BITFIELD2(uint8, + RateSelector:2, + Rate:6); + + IB_BITFIELD2(uint8, + PktLifeTimeSelector:2, + PktLifeTime:6); + + IB_BITFIELD3(uint8, + IndependenceSelector:2, + SGIDScope:3, + DGIDScope:3); + + uint8 SGIDCount; + + uint8 DGIDCount; + + uint64 ServiceID; + + IB_BITFIELD5(uint8, + L2_8B:1, // True if path supports this L2. + L2_10B:1, // True if path supports this L2. + L2_9B:1, // True if path supports this L2. + L2_16B:1, // True if path supports this L2. + Reserved:4); + + uint8 Reserved3[7]; + + IB_GID GIDList[0]; // SGIDCount + DGIDCount entries. +} PACK_SUFFIX STL_MULTIPATH_RECORD_GID; + +/* + * MultiPathRecord (GUID) + * + * STL Differences: + * New for STL + */ +typedef struct { + IB_BITFIELD3(uint32, + Reserved1:4, + FlowLabel:20, + HopLimit:8); + + uint8 TClass; + + IB_BITFIELD2(uint8, + Reversible:1, + NumbPath:7); + + uint16 P_Key; + + IB_BITFIELD4(uint16, + QoSType:2, + QoSPriority:8, + Reserved2:1, + SL:5); + + IB_BITFIELD2(uint8, + MtuSelector:2, + Mtu:6); + + IB_BITFIELD2(uint8, + RateSelector:2, + Rate:6); + + IB_BITFIELD2(uint8, + PktLifeTimeSelector:2, + PktLifeTime:6); + + IB_BITFIELD3(uint8, + IndependenceSelector:2, + SGUIDScope:3, + DGUIDScope:3); + + uint16 SGUIDCount; + + uint16 DGUIDCount; + + IB_BITFIELD5(uint8, + L2_8B:1, // True if path supports this L2. + L2_10B:1, // True if path supports this L2. + L2_9B:1, // True if path supports this L2. + L2_16B:1, // True if path supports this L2. + Reserved:4); + + uint8 Reserved3[5]; + + uint64 ServiceID; + + uint64 SubnetPrefix; + + uint64 GUIDList[0]; // SGUIDCount + DGUIDCount entries. +} PACK_SUFFIX STL_MULTIPATH_RECORD_GUID; + +/* + * MultiPathRecord (LID) + * + * STL Differences: + * New for STL + */ +typedef struct { + IB_BITFIELD3(uint32, + Reserved1:4, + FlowLabel:20, + HopLimit:8); + + uint8 TClass; + + IB_BITFIELD2(uint8, + Reversible:1, + NumbPath:7); + + uint16 P_Key; + + IB_BITFIELD4(uint16, + QoSType:2, + QoSPriority:8, + Reserved2:1, + SL:5); + + IB_BITFIELD2(uint8, + MtuSelector:2, + Mtu:6); + + IB_BITFIELD2(uint8, + RateSelector:2, + Rate:6); + + IB_BITFIELD2(uint8, + PktLifeTimeSelector:2, + PktLifeTime:6); + + IB_BITFIELD3(uint8, + IndependenceSelector:2, + SGUIDScope:3, + DGUIDScope:3); + + uint16 SLIDCount; + + uint16 DLIDCount; + + IB_BITFIELD5(uint8, + L2_8B:1, // True if path supports this L2. + L2_10B:1, // True if path supports this L2. + L2_9B:1, // True if path supports this L2. + L2_16B:1, // True if path supports this L2. + Reserved:4); + + uint8 Reserved3[5]; + + uint64 ServiceID; + + STL_LID LIDList[0]; // SLIDCount + DLIDCount entries +} PACK_SUFFIX STL_MULTIPATH_RECORD_LID; + +/* + * CableInfoRecord + * + * STL Differences: + * LID lengthened to 32 bits. + * Reserved2 field shortened from 20 bits to 4 to preserve word-alignment. + * RID.Port for HFI will return HFI port number + */ +#define STL_CIR_DATA_SIZE 64 +typedef struct { + struct { + STL_LID LID; + uint8 Port; /* for switch or HFI: port numnber */ + IB_BITFIELD2(uint8, + Length:7, + Reserved:1); + STL_FIELDUNION2(u1, 16, + Address:12, + PortType:4); /* Port type for response only */ + }; + + uint8 Data[STL_CIR_DATA_SIZE]; + +} PACK_SUFFIX STL_CABLE_INFO_RECORD; + +#define STL_CIR_COMP_LID 0x1ul +#define STL_CIR_COMP_PORT 0x2ul +#define STL_CIR_COMP_LEN 0x4ul +//Reserved 0x8ul +#define STL_CIR_COMP_ADDR 0x10ul +//Reserved2 0x20ul + +#define STL_VFABRIC_NAME_LEN 64 +/* + * VFInfoRecord + * + * STL Differences: + * Was a Vendor-specific MAD in IB + * SL lengthened to 5 bits. + * Reserved fields renamed. + * + * TBD - adjust to report multiple SLs (perhaps a mask) for TrafficClass + * concept in prep for STL2 + */ +typedef struct { + uint16 vfIndex; /* The index assigned to the VF */ + uint16 pKey; /* PKey associated with the VF */ + uint32 rsvd1; + + /* 8 bytes */ + + uint8 vfName[STL_VFABRIC_NAME_LEN]; /* The name of the VF. Must be \0 terminated. */ + + /* 72 bytes */ + + uint64 ServiceID; /* for query only */ + + /* 80 bytes */ + + IB_GID MGID; /* for query only */ + + /* 96 bytes */ + + struct { + IB_BITFIELD3(uint8, + selectFlags:2, /* 1 bit to indicate SL in queries, 1 bit for pkey */ + rsvd2:1, + slBase:5); /* service level - 5 bits */ + IB_BITFIELD3(uint8, + mtuSpecified:1, /* mtu specified for VF - 1 bit */ + rsvd3:1, + mtu:6); /* max mtu assigned to VF - 6 bits */ + + IB_BITFIELD3(uint8, + rateSpecified:1, /* rate specified for VF - 1 bit */ + rsvd4:1, + rate:6); /* max rate assigned to VF - 6 bits */ + + IB_BITFIELD3(uint8, + pktLifeSpecified:1, /* pkt life time specified for VF - 1 bit */ + rsvd5:4, + pktLifeTimeInc:3); /* pkt life time assigned to VF - 3 bits */ + } PACK_SUFFIX s1; + + uint8 optionFlags; /* security bit, QoS bit, reliable flow disable, 5 reserved */ + uint8 bandwidthPercent; /* bandwidth percentage, 8 bits */ + + IB_BITFIELD2(uint8, + rsvd6:7, + priority:1); /* priority, 1 bit */ + + uint8 routingSLs; /* Always 1 */ + + IB_BITFIELD2(uint8, + rsvd7:1, + preemptionRank:7); + + IB_BITFIELD2(uint8, + rsvd8:3, + hoqLife:5); + + IB_BITFIELD3(uint8, + slResponseSpecified:1, /* slResponse field is set - 1 bit */ + rsvd9:2, + slResponse:5); /* service level - 5 bits */ + + IB_BITFIELD3(uint8, + slMulticastSpecified:1, /* slMulticast field is set - 1 bit */ + rsvd10:2, + slMulticast:5); /* service level - 5 bits */ + + uint8 rsvd11[20]; + +} PACK_SUFFIX STL_VFINFO_RECORD; + +#define STL_VFINFO_REC_COMP_INDEX 0x0000000000000001ll +#define STL_VFINFO_REC_COMP_PKEY 0x0000000000000002ll +#define STL_VFINFO_REC_COMP_NAME 0x0000000000000008ll +#define STL_VFINFO_REC_COMP_SERVICEID 0x0000000000000010ll +#define STL_VFINFO_REC_COMP_MGID 0x0000000000000020ll +#define STL_VFINFO_REC_COMP_SL 0x0000000000000080ll + +/* selectFlags */ +#define STL_VFINFO_REC_SEL_PKEY_QUERY 0x01 +#define STL_VFINFO_REC_SEL_SL_QUERY 0x02 + +/* optionFlags */ +#define STL_VFINFO_REC_OPT_SECURITY 0x01 +#define STL_VFINFO_REC_OPT_QOS 0x02 +#define STL_VFINFO_REC_OPT_FLOW_DISABLE 0x04 + +/* + * QuarantinedNodeRecord + * + * STL Differences: + * New for STL + * + * NOTE: GET TABLE is the only supported method for this query. + * Component Mask must be zero. + */ + +#define STL_QUARANTINE_REASON_SPOOF_GENERIC 0x00000001 +#define STL_QUARANTINE_REASON_TOPO_NODE_GUID 0x00000002 +#define STL_QUARANTINE_REASON_TOPO_NODE_DESC 0x00000004 +#define STL_QUARANTINE_REASON_TOPO_PORT_GUID 0x00000008 +#define STL_QUARANTINE_REASON_TOPO_UNDEFINED_LINK 0x00000010 +#define STL_QUARANTINE_REASON_VL_COUNT 0x00000020 +#define STL_QUARANTINE_REASON_SMALL_MTU_SIZE 0x00000040 +#define STL_QUARANTINE_REASON_BAD_PACKET_FORMATS 0x00000080 +#define STL_QUARANTINE_REASON_MAXLID 0x00000100 +#define STL_QUARANTINE_REASON_UNKNOWN 0x00000000 + +typedef struct { + STL_NODE_DESCRIPTION nodeDesc; + uint64 nodeGUID; + uint64 portGUID; +} PACK_SUFFIX STL_EXPECTED_NODE_INFO; + +typedef struct { + STL_LID trustedLid; + uint8 trustedPortNum; + uint8 Reserved[3]; + uint64 trustedNodeGUID; + uint64 trustedNeighborNodeGUID; + + STL_NODE_DESCRIPTION NodeDesc; + STL_NODE_INFO NodeInfo; + + uint32 quarantineReasons; + // expectedNodeInfo only valid if quarantineReasons != 0 + STL_EXPECTED_NODE_INFO expectedNodeInfo; + +} PACK_SUFFIX STL_QUARANTINED_NODE_RECORD; + +/* + * Congestion Info Record + * + * STL Differences: + * Was Vendor Specific in IB. + */ +typedef struct { + STL_LID LID; + uint32 reserved; + STL_CONGESTION_INFO CongestionInfo; +} PACK_SUFFIX STL_CONGESTION_INFO_RECORD; + +#define CIR_COMPONENTMASK_COMP_LID 0x00000001 + +/* + * Switch Congestion Setting Record + * + * STL Differences: + * Was Vendor Specific in IB. + */ +typedef struct { /* all fields are RW */ + STL_LID LID; + uint32 reserved; + STL_SWITCH_CONGESTION_SETTING SwitchCongestionSetting; +} PACK_SUFFIX STL_SWITCH_CONGESTION_SETTING_RECORD; + +#define SWCSR_COMPONENTMASK_COMP_LID 0x00000001 + +/* + * Switch Port Congestion Setting Record + * + * STL Differences: + * Was Vendor Specific in IB. + */ +typedef struct { + struct { + STL_LID LID; + uint8 Port; + } PACK_SUFFIX RID; + + uint8 Reserved[3]; + + /* 8 bytes */ + + STL_SWITCH_PORT_CONGESTION_SETTING SwitchPortCongestionSetting; + +} PACK_SUFFIX STL_SWITCH_PORT_CONGESTION_SETTING_RECORD; + +#define SWPCSR_COMPONENTMASK_COMP_LID 0x00000001 +#define SWPCSR_COMPONENTMASK_COMP_PORT 0x00000002 + +/* + * HFI Congestion Setting Record + * + * STL Differences: + * Was Vendor Specific in IB. + */ +typedef struct { /* all fields are RW */ + STL_LID LID; + uint32 reserved; + STL_HFI_CONGESTION_SETTING HFICongestionSetting; +} PACK_SUFFIX STL_HFI_CONGESTION_SETTING_RECORD; + +#define HCSR_COMPONENTMASK_COMP_LID 0x00000001 + +/* + * HFI Congestion Control Table Record + * + * STL Differences: + * Was Vendor Specific in IB. + */ +typedef struct { /* all fields are RW */ + struct { + STL_LID LID; + uint16 BlockNum; + } PACK_SUFFIX RID; + uint16 reserved; + STL_HFI_CONGESTION_CONTROL_TABLE HFICongestionControlTable; +} PACK_SUFFIX STL_HFI_CONGESTION_CONTROL_TABLE_RECORD; +#define HCCTR_COMPONENTMASK_COMP_LID 0x00000001 +#define HCCTR_COMPONENTMASK_COMP_BLOCK 0x00000002 + +/* + * Buffer Control Table Record + * + * STL Differences: + * New for STL + * At this time, Component Mask is only supported for LID and Port. + */ +typedef struct { + struct { + STL_LID LID; + uint8 Port; /* for switch or HFI: port numnber */ + } PACK_SUFFIX RID; + + uint8 Reserved[3]; + + STL_BUFFER_CONTROL_TABLE BufferControlTable; + +} PACK_SUFFIX STL_BUFFER_CONTROL_TABLE_RECORD; + +#define BFCTRL_COMPONENTMASK_COMP_LID 0x00000001 +#define BFCTRL_COMPONENTMASK_COMP_PORT 0x00000002 + +/* + * FabricInfo Record + * + * STL Differences: + * New for STL + * supports only Get, Component Mask N/A + */ +typedef struct { + uint32 NumHFIs; /* HFI Nodes */ + uint32 NumSwitches; /* Switch Nodes (ASICs) */ + /* Internal = in same SystemImageGuid */ + /* HFI = HFI to switch and HFI to HFI links */ + /* ISL = switch to switch links */ + /* links which are Omitted will not be considered for Degraded checks */ + /* switch port 0 is not counted as a link */ + uint32 NumInternalHFILinks; /* HFI to switch (or HFI) links */ + uint32 NumExternalHFILinks; /* HFI to switch (or HFI) links */ + uint32 NumInternalISLs; /* switch to switch links */ + uint32 NumExternalISLs; /* switch to switch links */ + uint32 NumDegradedHFILinks; /* links with one or both sides below best enabled */ + uint32 NumDegradedISLs; /* links with one or both sides below best enabled */ + uint32 NumOmittedHFILinks; /* links quarantined or left in Init */ + uint32 NumOmittedISLs; /* links quarantined or left in Init */ + uint32 rsvd5[92]; +} PACK_SUFFIX STL_FABRICINFO_RECORD; + + +#define MAX_DG_NAME 64 + +/* + * DeviceGroupNameRecord + */ +typedef struct { + uint8 DeviceGroupName[MAX_DG_NAME]; /* Must be \0 terminated. */ +} PACK_SUFFIX STL_DEVICE_GROUP_NAME_RECORD; + + +#define STL_DEVICE_GROUP_COMPONENTMASK_LID 0x0000000000000001ull +#define STL_DEVICE_GROUP_COMPONENTMASK_PORT 0x0000000000000002ull +/* reserved field 0x0000000000000004ull */ +#define STL_DEVICE_GROUP_COMPONENTMASK_DGNAME 0x0000000000000008ull +#define STL_DEVICE_GROUP_COMPONENTMASK_GUID 0x0000000000000010ull +#define STL_DEVICE_GROUP_COMPONENTMASK_NODEDESC 0x0000000000000020ull + +/* + * DeviceGroupMemberRecord + */ +typedef struct { + STL_LID LID; + uint8 Port; + uint8 Reserved1[3]; + uint8 DeviceGroupName[MAX_DG_NAME]; /* Must be \0 terminated. */ + uint64 GUID; + STL_NODE_DESCRIPTION NodeDescription; +} PACK_SUFFIX STL_DEVICE_GROUP_MEMBER_RECORD; + +#define STL_DEVICE_TREE_COMPONENTMASK_LID 0x0000000000000001ull +#define STL_DEVICE_TREE_COMPONENTMASK_NUMPORTS 0x0000000000000002ull +#define STL_DEVICE_TREE_COMPONENTMASK_NODETYPE 0x0000000000000004ull +/* reserved field 0x0000000000000008ull */ +#define STL_DEVICE_TREE_COMPONENTMASK_PORTSTATEMASKACT 0x0000000000000010ull +#define STL_DEVICE_TREE_COMPONENTMASK_PORTSTATEMASKETH 0x0000000000000020ull +#define STL_DEVICE_TREE_COMPONENTMASK_GUID 0x0000000000000040ull +#define STL_DEVICE_TREE_COMPONENTMASK_SYSIMAGEGUID 0x0000000000000080ull +#define STL_DEVICE_TREE_COMPONENTMASK_NODEDESC 0x0000000000000100ull +/* reserved field 0x0000000000000200ull */ + +/* + * DeviceTreeMemberRecord + */ +typedef struct { + STL_LID LID; + uint8 NumPorts; + uint8 NodeType; + uint8 Reserved1[2]; + STL_PORTMASK portMaskAct[STL_MAX_PORTMASK]; + + STL_PORTMASK portMaskReserved[STL_MAX_PORTMASK]; + + STL_PORTMASK portMaskPortLinkMode[STL_MAX_PORTMASK]; + + uint64 GUID; + uint64 SystemImageGUID; + STL_NODE_DESCRIPTION NodeDescription; + uint64 Reserved2[4]; + +} PACK_SUFFIX STL_DEVICE_TREE_MEMBER_RECORD; + + +/* + * SwitchCost Record + */ +#define STL_SWITCH_COST_NUM_ENTRIES 64 +typedef struct _STL_SWITCH_COST { + STL_LID DLID; + uint16 value; + uint16 Reserved; +} PACK_SUFFIX STL_SWITCH_COST; + +typedef struct _STL_SWITCH_COST_RECORD { + STL_LID SLID; + STL_SWITCH_COST Cost[STL_SWITCH_COST_NUM_ENTRIES]; +} PACK_SUFFIX STL_SWITCH_COST_RECORD; + +#define STL_SWITCH_COST_REC_COMP_SLID 0x0000000000000001ull + +#if defined (__cplusplus) +} +#endif +#endif // __STL_SA_H__ diff --git a/IbAccess/Common/Inc/stl_sd.h b/IbAccess/Common/Inc/stl_sd.h new file mode 100644 index 0000000..1c6d541 --- /dev/null +++ b/IbAccess/Common/Inc/stl_sd.h @@ -0,0 +1,369 @@ +/* BEGIN_ICS_COPYRIGHT7 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + * ** END_ICS_COPYRIGHT7 ****************************************/ +/* [ICS VERSION STRING: unknown] */ + +#if !defined(__STL_SD_H__) +#define __STL_SD_H__ + +#include "iba/ib_sd.h" +#include "iba/stl_sa_types.h" + + +typedef union _OMGT_QUERY_INPUT_VALUE { + + /* SA Record OutputTypes */ + union _IbNodeRecord { + IB_LID Lid; /* InputType */ + EUI64 PortGUID; /* InputType */ + EUI64 NodeGUID; /* InputType */ + EUI64 SystemImageGUID; /* InputType */ + NODE_TYPE NodeType; /* InputType */ + char NodeDesc[STL_NODE_DESCRIPTION_ARRAY_SIZE]; /* InputType */ + } IbNodeRecord; /* OutputType */ + union _NodeRecord { + STL_LID Lid; /* InputType */ + EUI64 PortGUID; /* InputType */ + EUI64 NodeGUID; /* InputType */ + EUI64 SystemImageGUID; /* InputType */ + NODE_TYPE NodeType; /* InputType */ + char NodeDesc[STL_NODE_DESCRIPTION_ARRAY_SIZE]; /* InputType */ + } NodeRecord; /* OutputType */ + union _IbLidOnly { + IB_LID Lid; /* InputType */ + } IbPortInfoRecord; /* OutputType */ + union _LidOnly { + STL_LID Lid; /* InputType */ + } PortInfoRecord; /* OutputType */ + union _LinkRecord { + STL_LID Lid; + uint16 LinkConditionMask; + } LinkRecord; /* OutputType */ + union _LidOnly SwitchInfoRecord; /* OutputType */ + union _IbPathRecord { + IB_GID SourceGid; /* InputType None */ + struct { + uint8 SourceGuidCount; /* number of Source GUIDs in GuidList */ + uint8 DestGuidCount; /* number of Dest GUIDs in GuidList */ + EUI64 GuidList[MULTIPATH_GID_LIMIT]; /* Src GUIDs, followed by Dest GUIDs */ + EUI64 SharedSubnetPrefix; + } PortGuidList; /* InputType */ + struct { + uint8 SourceGidCount; /* number of Source GIDs in GidList */ + uint8 DestGidCount; /* number of Dest GIDs in GidList */ + IB_GID GidList[MULTIPATH_GID_LIMIT]; /* Src GIDs, followed by Dest GIDs */ + } GidList; /* InputType */ + struct { + uint64 ComponentMask; + IB_MULTIPATH_RECORD MultiPathRecord; + /* Gids below allows up to 8 SGID and/or DGID in MultiPathRecord.GIDList */ + /* do not use Gids field directly, instead use */ + /* MultiPathRecord.GIDList[0-7] */ + IB_GID Gids[MULTIPATH_GID_LIMIT-1]; + } MultiPathRecord; /* InputType */ + struct { + IB_GID SourceGid; + uint16 PKey; + } PKey; /* InputType */ + struct { + IB_GID SourceGid; + uint8 SL; + } SL; /* InputType */ + struct { + IB_GID SourceGid; + uint64 ServiceId; + } ServiceId; /* InputType */ + struct { + EUI64 SharedSubnetPrefix; + EUI64 SourcePortGuid; + EUI64 DestPortGuid; + } PortGuidPair, PortGuid; /* InputType */ + struct { + IB_GID SourceGid; + IB_GID DestGid; + } GidPair, PortGid; /* InputType */ + struct { + IB_GID SourceGid; + IB_LID DLid; + } Lid; /* InputType */ + struct { + uint64 ComponentMask; + IB_PATH_RECORD PathRecord; + } PathRecord; + } IbPathRecord; /* OutputType */ + union _IbPathRecord TraceRecord; /* OutputType */ + union _IbServiceRecord { + IB_GID ServiceGid; /* InputType */ + uint64 ServiceId; /* InputType */ + } IbServiceRecord; /* OutputType */ + union _IbMcMemberRecord { + IB_GID PortGid; /* InputType */ + IB_GID McGid; /* InputType */ + STL_LID Lid; /* InputType */ + uint8 SL; /* InputType */ + uint16 PKey; /* InputType */ + } IbMcMemberRecord; /* OutputType */ + union _IbInforInfoRecord { + IB_GID SubscriberGID; + } IbInformInfoRecord; + union _StlInforInfoRecord { + STL_LID SubscriberLID; + } StlInformInfoRecord; + union _LidOnly ScScTableRecord; + union _LidOnly SlScTableRecord; + union _LidOnly ScSlTableRecord; + union _LidOnly ScVlxTableRecord; + union _LidOnly VlArbTableRecord; + union _LidOnly PKeyTableRecord; + union _LidOnly LinFdbTableRecord; + union _LidOnly McFdbTableRecord; + union _VfInfoRecord { + uint16 PKey; + uint8 SL; + uint64 ServiceId; + IB_GID McGid; + uint16 vfIndex; + char vfName[STL_NODE_DESCRIPTION_ARRAY_SIZE]; + } VfInfoRecord; + union _LidOnly CongInfoRecord; + union _LidOnly SwCongRecord; + union _LidOnly SwPortCongRecord; + union _LidOnly HFICongRecord; + union _LidOnly HFICongCtrlRecord; + union _LidOnly BufCtrlTableRecord; + union _LidOnly CableInfoRecord; + union _LidOnly PortGroupRecord; + union _LidOnly PortGroupFwdRecord; + union _DgGrpMemberRecord { + STL_LID Lid; + EUI64 Guid; + char NodeDesc[STL_NODE_DESCRIPTION_ARRAY_SIZE]; /* InputType */ + char DeviceGroup[STL_NODE_DESCRIPTION_ARRAY_SIZE]; /* InputType */ + } DgGrpMemberRecord; + union _LidOnly DgTreeMemberRecord; + union _LidOnly SwitchCostRecord; +} OMGT_QUERY_INPUT_VALUE; + +typedef struct _OMGT_QUERY { + QUERY_INPUT_TYPE InputType; /* Type of input (i.e. query based on) */ + QUERY_RESULT_TYPE OutputType; /* Type of output (i.e. info requested) */ + OMGT_QUERY_INPUT_VALUE InputValue; /* input record selection value input query */ +} OMGT_QUERY, *POMGT_QUERY; + +/* SA Query Results Structs */ +typedef struct { + uint32 NumClassPortInfo; /* Should always be 1 or 0 */ + STL_CLASS_PORT_INFO ClassPortInfo; /* Should never have more than 1 */ +} STL_CLASS_PORT_INFO_RESULT, *PSTL_CLASS_PORT_INFO_RESULT; + +typedef struct { + uint32 NumFabricInfoRecords;/* Should always be 1 or 0 */ + STL_FABRICINFO_RECORD FabricInfoRecord; /* Should never have more than 1 */ +} STL_FABRICINFO_RECORD_RESULT, *PSTL_FABRICINFO_RECORD_RESULT; + +typedef struct { + uint32 NumNodeRecords; /* Number of NodeRecords returned */ + STL_NODE_RECORD NodeRecords[1]; /* list of Node records returned */ +} STL_NODE_RECORD_RESULTS, *PSTL_NODE_RECORD_RESULTS; + +typedef struct { + uint32 NumDescs; /* Number of NodeDescs returned */ + STL_NODE_DESCRIPTION NodeDescs[1]; /* (STL) NodeDesc, null terminated. */ +} STL_NODEDESC_RESULTS, *PSTL_NODEDESC_RESULTS; + +typedef struct { + uint32 NumPortInfoRecords; /* Number of PortInfoRecords returned */ + STL_PORTINFO_RECORD PortInfoRecords[1]; /* list of PortInfoRecords returned */ +} STL_PORTINFO_RECORD_RESULTS, *PSTL_PORTINFO_RECORD_RESULTS; + +typedef struct { + uint32 NumSwitchInfoRecords; + STL_SWITCHINFO_RECORD SwitchInfoRecords[1]; + +} STL_SWITCHINFO_RECORD_RESULTS, *PSTL_SWITCHINFO_RECORD_RESULTS; + +typedef struct { + uint32 NumPKeyTableRecords; + STL_P_KEY_TABLE_RECORD PKeyTableRecords[1]; + +} STL_PKEYTABLE_RECORD_RESULTS, *PSTL_PKEYTABLE_RECORD_RESULTS; + +typedef struct { + uint32 NumSCSCTableRecords; + STL_SC_MAPPING_TABLE_RECORD SCSCRecords[1]; +} STL_SC_MAPPING_TABLE_RECORD_RESULTS, *PSTL_SC_MAPPING_TABLE_RECORD_RESULTS; + +typedef struct { + uint32 NumSLSCTableRecords; + STL_SL2SC_MAPPING_TABLE_RECORD SLSCRecords[1]; +} STL_SL2SC_MAPPING_TABLE_RECORD_RESULTS, *PSTL_SL2SC_MAPPING_TABLE_RECORD_RESULTS; + +typedef struct { + uint32 NumSCSLTableRecords; + STL_SC2SL_MAPPING_TABLE_RECORD SCSLRecords[1]; +} STL_SC2SL_MAPPING_TABLE_RECORD_RESULTS, *PSTL_SC2SL_MAPPING_TABLE_RECORD_RESULTS; + +typedef struct { + uint32 NumSCVLtTableRecords; + STL_SC2PVL_T_MAPPING_TABLE_RECORD SCVLtRecords[1]; +} STL_SC2PVL_T_MAPPING_TABLE_RECORD_RESULTS, *PSTL_SC2PVL_T_MAPPING_TABLE_RECORD_RESULTS; + +typedef struct { + uint32 NumSCVLntTableRecords; + STL_SC2PVL_NT_MAPPING_TABLE_RECORD SCVLntRecords[1]; +} STL_SC2PVL_NT_MAPPING_TABLE_RECORD_RESULTS, *PSTL_SC2PVL_NT_MAPPING_TABLE_RECORD_RESULTS; + +typedef struct { + uint32 NumSCVLrTableRecords; + STL_SC2PVL_R_MAPPING_TABLE_RECORD SCVLrRecords[1]; +} STL_SC2PVL_R_MAPPING_TABLE_RECORD_RESULTS, *PSTL_SC2PVL_R_MAPPING_TABLE_RECORD_RESULTS; + +typedef struct { + uint32 NumLinearFDBRecords; + STL_LINEAR_FORWARDING_TABLE_RECORD LinearFDBRecords[1]; +} STL_LINEAR_FDB_RECORD_RESULTS, *PSTL_LINEAR_FDB_RECORD_RESULTS; + + +typedef struct { + uint32 NumSMInfoRecords; /* Number of SmInfoRecords returned */ + STL_SMINFO_RECORD SMInfoRecords[1]; /* list of SMInfoRecords returned */ +} STL_SMINFO_RECORD_RESULTS, *PSTL_SMINFO_RECORD_RESULTS; + +typedef struct { + uint32 NumVLArbTableRecords; + STL_VLARBTABLE_RECORD VLArbTableRecords[1]; +} STL_VLARBTABLE_RECORD_RESULTS, *PSTL_VLARBTABLE_RECORD_RESULTS; + + +typedef struct { + uint32 NumMcMemberRecords; + STL_MCMEMBER_RECORD McMemberRecords[1]; +} STL_MCMEMBER_RECORD_RESULTS, *PSTL_MCMEMBER_RECORD_RESULTS; + +typedef struct { + uint32 NumLids; + STL_LID Lids[1]; +} STL_LID_RESULTS, *PSTL_LID_RESULTS; + +typedef struct { + uint32 NumMCastFDBRecords; + STL_MULTICAST_FORWARDING_TABLE_RECORD MCastFDBRecords[1]; +} STL_MCAST_FDB_RECORD_RESULTS, *PSTL_MCAST_FDB_RECORD_RESULTS; + +typedef struct { + uint32 NumLinkRecords; + STL_LINK_RECORD LinkRecords[1]; +} STL_LINK_RECORD_RESULTS, *PSTL_LINK_RECORD_RESULTS; + +typedef struct { + uint32 NumServiceRecords; + STL_SERVICE_RECORD ServiceRecords[1]; +} STL_SERVICE_RECORD_RESULTS, *PSTL_SERVICE_RECORD_RESULTS; + +typedef struct { + uint32 NumInformInfoRecords; + STL_INFORM_INFO_RECORD InformInfoRecords[1]; +} STL_INFORM_INFO_RECORD_RESULTS, *PSTL_INFORM_INFO_RECORD_RESULTS; + +typedef struct { + uint32 NumVfInfoRecords; + STL_VFINFO_RECORD VfInfoRecords[1]; +} STL_VFINFO_RECORD_RESULTS, *PSTL_VFINFO_RECORD_RESULTS; + +typedef struct { + uint32 NumTraceRecords; + STL_TRACE_RECORD TraceRecords[1]; +} STL_TRACE_RECORD_RESULTS, *STL_PTRACE_RECORD_RESULTS; + +typedef struct { + uint32 NumQuarantinedNodeRecords; + STL_QUARANTINED_NODE_RECORD QuarantinedNodeRecords[1]; +} STL_QUARANTINED_NODE_RECORD_RESULTS, *PSTL_QUARANTINED_NODE_RECORD_RESULTS; + +typedef struct { + uint32 NumRecords; + STL_CONGESTION_INFO_RECORD Records[1]; +} STL_CONGESTION_INFO_RECORD_RESULTS, *PSTL_CONGESTION_INFO_RECORD_RESULTS; +typedef struct { + uint32 NumRecords; + STL_SWITCH_CONGESTION_SETTING_RECORD Records[1]; +} STL_SWITCH_CONGESTION_SETTING_RECORD_RESULTS, *PSTL_SWITCH_CONGESTION_SETTING_RECORD_RESULTS; +typedef struct { + uint32 NumRecords; + STL_SWITCH_PORT_CONGESTION_SETTING_RECORD Records[1]; +} STL_SWITCH_PORT_CONGESTION_SETTING_RECORD_RESULTS, *PSTL_SWITCH_PORT_CONGESTION_SETTING_RECORD_RESULTS; +typedef struct { + uint32 NumRecords; + STL_HFI_CONGESTION_SETTING_RECORD Records[1]; +} STL_HFI_CONGESTION_SETTING_RECORD_RESULTS, *PSTL_HFI_CONGESTION_SETTING_RECORD_RESULTS; +typedef struct { + uint32 NumRecords; + STL_HFI_CONGESTION_CONTROL_TABLE_RECORD Records[1]; +} STL_HFI_CONGESTION_CONTROL_TABLE_RECORD_RESULTS, *PSTL_HFI_CONGESTION_CONTROL_TABLE_RECORD_RESULTS; + +typedef struct { + uint32 NumBufferControlRecords; + STL_BUFFER_CONTROL_TABLE_RECORD BufferControlRecords[1]; +} STL_BUFFER_CONTROL_TABLE_RECORD_RESULTS, *PSTL_BUFFER_CONTROL_TABLE_RECORD_RESULTS; + +typedef struct { + uint32 NumCableInfoRecords; + STL_CABLE_INFO_RECORD CableInfoRecords[1]; +} STL_CABLE_INFO_RECORD_RESULTS, *PSTL_CABLE_INFO_RECORD_RESULTS; + +typedef struct { + uint32 NumRecords; + STL_PORT_GROUP_TABLE_RECORD Records[1]; +} STL_PORT_GROUP_TABLE_RECORD_RESULTS, *PSTL_PORT_GROUP_TABLE_RECORD_RESULTS; +typedef struct { + uint32 NumRecords; + STL_PORT_GROUP_FORWARDING_TABLE_RECORD Records[1]; +} STL_PORT_GROUP_FORWARDING_TABLE_RECORD_RESULTS, *PSTL_PORT_GROUP_FORWARDING_TABLE_RECORD_RESULTS; + +typedef struct { + uint32 NumRecords; + STL_DEVICE_GROUP_MEMBER_RECORD Records[1]; +} STL_DEVICE_GROUP_MEMBER_RECORD_RESULTS, *PSTL_DEVICE_GROUP_MEMBER_RECORD_RESULTS; + +typedef struct { + uint32 NumRecords; + STL_DEVICE_GROUP_NAME_RECORD Records[1]; +} STL_DEVICE_GROUP_NAME_RECORD_RESULTS, *PSTL_DEVICE_GROUP_NAME_RECORD_RESULTS; + +typedef struct { + uint32 NumRecords; + STL_DEVICE_TREE_MEMBER_RECORD Records[1]; +} STL_DEVICE_TREE_MEMBER_RECORD_RESULTS, *PSTL_DEVICE_TREE_MEMBER_RECORD_RESULTS; + + +typedef struct { + uint32 NumRecords; + STL_SWITCH_COST_RECORD Records[1]; +} STL_SWITCH_COST_RECORD_RESULTS, *PSTL_SWITCH_COST_RECORD_RESULTS; + +#endif diff --git a/IbAccess/Common/Inc/stl_sm_priv.h b/IbAccess/Common/Inc/stl_sm_priv.h new file mode 100644 index 0000000..466c69d --- /dev/null +++ b/IbAccess/Common/Inc/stl_sm_priv.h @@ -0,0 +1,960 @@ +/* BEGIN_ICS_COPYRIGHT7 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT7 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +#ifndef __IBA_STL_SM_PRIV_H__ +#define __IBA_STL_SM_PRIV_H__ + +#include "iba/stl_types.h" +#include "iba/ib_sm_priv.h" +#include "iba/stl_sm_types.h" + +#if defined (__cplusplus) +extern "C" { +#endif + +static __inline void +BSWAP_STL_TRAP_CHANGE_CAPABILITY_DATA(STL_TRAP_CHANGE_CAPABILITY_DATA *Src) +{ +#if CPU_LE + Src->Lid = ntoh32(Src->Lid); + Src->CapabilityMask.AsReg32 = ntoh32(Src->CapabilityMask.AsReg32); + Src->CapabilityMask3.AsReg16 = ntoh16(Src->CapabilityMask3.AsReg16); + + + Src->u.AsReg16 = ntoh16(Src->u.AsReg16); +#endif +} + +static __inline void +BSWAPCOPY_STL_TRAP_CHANGE_CAPABILITY_DATA(STL_TRAP_CHANGE_CAPABILITY_DATA *Src, + STL_TRAP_CHANGE_CAPABILITY_DATA *Dest) +{ + memcpy(Dest, Src, sizeof(STL_TRAP_CHANGE_CAPABILITY_DATA)); + BSWAP_STL_TRAP_CHANGE_CAPABILITY_DATA(Dest); +} + +static __inline void +BSWAP_STL_TRAP_BAD_KEY_DATA(STL_TRAP_BAD_KEY_DATA *Src) +{ +#if CPU_LE + uint64_t temp; + + Src->Lid1 = ntoh32(Src->Lid1); + Src->Lid2 = ntoh32(Src->Lid2); + Src->Key = ntoh32(Src->Key); + // u + // Reserved[3] + temp = ntoh64(Src->Gid1.AsReg64s.H); + Src->Gid1.AsReg64s.H = ntoh64(Src->Gid1.AsReg64s.L); + Src->Gid1.AsReg64s.L = temp; + temp = ntoh64(Src->Gid2.AsReg64s.H); + Src->Gid2.AsReg64s.H = ntoh64(Src->Gid2.AsReg64s.L); + Src->Gid2.AsReg64s.L = temp; + Src->qp1.AsReg32= ntoh32(Src->qp1.AsReg32); + Src->qp2.AsReg32= ntoh32(Src->qp2.AsReg32); +#endif +} + +static __inline void +BSWAPCOPY_STL_TRAP_BAD_KEY_DATA(STL_TRAP_BAD_KEY_DATA *Src, STL_TRAP_BAD_KEY_DATA *Dest) +{ + memcpy(Dest, Src, sizeof(STL_TRAP_BAD_KEY_DATA)); + BSWAP_STL_TRAP_BAD_KEY_DATA(Dest); +} + +static __inline void +BSWAP_STL_AGGREGATE_HEADER(STL_AGGREGATE *Dest) +{ +#if CPU_LE + Dest->AttributeID = ntoh16(Dest->AttributeID); + Dest->Result.AsReg16 = ntoh16(Dest->Result.AsReg16); + Dest->AttributeModifier = ntoh32(Dest->AttributeModifier); +#endif +} + +static __inline void +ZERO_RSVD_STL_AGGREGATE(STL_AGGREGATE *Dest) +{ + Dest->Result.s.Reserved = 0; +} + +/** + Zero & swap or swap & zero @c segCount segment headers in range [start, end) for network transport. + Stops swapping response on first error segment. When going from host to network order, + stops before swapping segment header to network order if segment header error flag is set. + + Stops when either: next segment is past @c end; @c *segCount segments have been processed; or @c seg->Result.s.Error is not zero. + + @param segCount [in, out] As input, number of segments in [start, end). As output, number of segments processed. + @param hton When true, swap host to network order, otherwise network to host. + + @return Pointer past the last good segment processed (also pointer to first bad segment in case of error). +*/ +static __inline STL_AGGREGATE * +BSWAP_ZERO_AGGREGATE_HEADERS(STL_AGGREGATE * start, STL_AGGREGATE * end, int * segCount, boolean hton) +{ + int count = 0; + STL_AGGREGATE * h = start; + + while (h < end && count < *segCount) { + if (hton) { + if (h->Result.s.Error) + break; + ZERO_RSVD_STL_AGGREGATE(h); + STL_AGGREGATE * next = STL_AGGREGATE_NEXT(h); + BSWAP_STL_AGGREGATE_HEADER(h); + h = next; + } + else { + BSWAP_STL_AGGREGATE_HEADER(h); + ZERO_RSVD_STL_AGGREGATE(h); + if (h->Result.s.Error) + break; + h = STL_AGGREGATE_NEXT(h); + } + ++count; + } + + *segCount = count; + return h; +} + +static __inline void +BSWAP_STL_DR_SMP(DRStlSmp_t *Dest) +{ +#if CPU_LE + Dest->M_Key = ntoh64(Dest->M_Key); + Dest->DrSLID = ntoh32(Dest->DrSLID); + Dest->DrDLID = ntoh32(Dest->DrDLID); +#endif +} + +static __inline void +BSWAPCOPY_STL_DR_SMP(DRStlSmp_t *Src, DRStlSmp_t *Dest) +{ + memcpy(Dest, Src, sizeof(DRStlSmp_t)); + (void)BSWAP_STL_DR_SMP(Dest); +} + +#define DRStlMad_Init(MAIP,METHOD,TID,AID,AMOD,MKEY,IPATH) { \ + DRStlSmp_t *drp; \ + \ + (void)memset((void *)&(MAIP)->base, 0, sizeof((MAIP)->base)); \ + \ + (MAIP)->active |= (MAI_ACT_BASE | MAI_ACT_DATA); \ + (MAIP)->base.bversion = STL_BASE_VERSION; \ + (MAIP)->base.mclass = MAD_CV_SUBN_DR; \ + (MAIP)->base.cversion = STL_SM_CLASS_VERSION; \ + (MAIP)->base.method = METHOD; \ + (MAIP)->base.status = 0; \ + (MAIP)->base.hopPointer = 0; \ + (MAIP)->base.hopCount = IPATH[0]; \ + (MAIP)->base.tid = TID; \ + (MAIP)->base.aid = AID; \ + (MAIP)->base.rsvd3 = 0; \ + (MAIP)->base.amod = AMOD; \ + \ + drp = (DRStlSmp_t *)(MAIP)->data; \ + (void)memset((void *)drp, 0, sizeof(*drp)); \ + \ + drp->M_Key = MKEY; \ + drp->DrSLID = STL_LID_PERMISSIVE; \ + drp->DrDLID = STL_LID_PERMISSIVE; \ + \ + (void)memcpy((void *)&drp->InitPath[1], (void *)&IPATH[1], IPATH[0]); \ +} + +#define LRDRStlMad_Init(MAIP,METHOD,TID,AID,AMOD,MKEY,IPATH,SLID) { \ + DRStlSmp_t *drp; \ + \ + (void)memset((void *)&(MAIP)->base, 0, sizeof((MAIP)->base)); \ + \ + (MAIP)->active |= (MAI_ACT_BASE | MAI_ACT_DATA); \ + (MAIP)->base.bversion = STL_BASE_VERSION; \ + (MAIP)->base.mclass = MAD_CV_SUBN_DR; \ + (MAIP)->base.cversion = STL_SM_CLASS_VERSION; \ + (MAIP)->base.method = METHOD; \ + (MAIP)->base.status = 0; \ + (MAIP)->base.hopPointer = 0; \ + (MAIP)->base.hopCount = IPATH[0]; \ + (MAIP)->base.tid = TID; \ + (MAIP)->base.aid = AID; \ + (MAIP)->base.rsvd3 = 0; \ + (MAIP)->base.amod = AMOD; \ + \ + drp = (DRStlSmp_t *)(MAIP)->data; \ + (void)memset((void *)drp, 0, sizeof(*drp)); \ + drp->M_Key = MKEY; \ + drp->DrSLID = SLID; \ + drp->DrDLID = STL_LID_PERMISSIVE; \ + \ + (void)memcpy((void *)&drp->InitPath[1], (void *)&IPATH[1], IPATH[0]); \ +} + +#define LRStlMad_Init(MAIP,MCLASS,METHOD,TID,AID,AMOD,MKEY) { \ + LRStlSmp_t *lrp; \ + \ + (void)memset((void *)&(MAIP)->base, 0, sizeof((MAIP)->base)); \ + \ + (MAIP)->active |= (MAI_ACT_BASE | MAI_ACT_DATA); \ + (MAIP)->base.bversion = STL_BASE_VERSION; \ + (MAIP)->base.mclass = MCLASS; \ + (MAIP)->base.cversion = MCLASS == MAD_CV_SUBN_ADM ? SA_MAD_CVERSION : STL_SM_CLASS_VERSION; \ + (MAIP)->base.method = METHOD; \ + (MAIP)->base.status = 0; \ + (MAIP)->base.hopPointer = 0; \ + (MAIP)->base.hopCount = 0; \ + (MAIP)->base.tid = TID; \ + (MAIP)->base.aid = AID; \ + (MAIP)->base.rsvd3 = 0; \ + (MAIP)->base.amod = AMOD; \ + \ + lrp = (LRStlSmp_t *)(MAIP)->data; \ + (void)memset((void *)lrp, 0, sizeof(*lrp)); \ + \ + lrp->M_Key = MKEY; \ +} + +static __inline uint8_t* stl_get_smp_data(STL_SMP *smp) +{ + if (smp->common.MgmtClass == MCLASS_SM_DIRECTED_ROUTE) { + return smp->SmpExt.DirectedRoute.SMPData; + } + return smp->SmpExt.LIDRouted.SMPData; +} + +static __inline size_t stl_get_smp_data_size(STL_SMP *smp) +{ + if (smp->common.MgmtClass == MCLASS_SM_DIRECTED_ROUTE) { + return STL_MAX_PAYLOAD_SMP_DR; + } + return STL_MAX_PAYLOAD_SMP_LR; +} + +static __inline size_t stl_get_smp_header_size(STL_SMP * smp) +{ + return sizeof(STL_SMP) - stl_get_smp_data_size(smp); +} + +static __inline uint8 +GET_STL_PORT_INFO_NeighborMTU(const STL_PORT_INFO *PortInfo, uint8 vl) { + if (vl & 0x01) + return(PortInfo->NeighborMTU[(vl & 0x1F) / 2].s.VL1_to_MTU); + else + return(PortInfo->NeighborMTU[(vl & 0x1F) / 2].s.VL0_to_MTU); +} + +static __inline void +PUT_STL_PORT_INFO_NeighborMTU(STL_PORT_INFO *PortInfo, uint8 vl, uint8 mtu) { + if (vl & 0x01) + PortInfo->NeighborMTU[(vl & 0x1F) / 2].s.VL1_to_MTU = mtu & 0x0F; + else + PortInfo->NeighborMTU[(vl & 0x1F) / 2].s.VL0_to_MTU = mtu & 0x0F; +} + +/* Is the Smp given from a local requestor (eg. on the same host such as a + * smp from IbAccess to its own local port or from a local SM) + * allow HopPointer to be 0 for direct use of GetSetMad and + * 1 for packets which passed through SMI prior to GetSetMad + */ +static __inline boolean +STL_SMP_IS_LOCAL(STL_SMP *Smp) +{ + return (( MCLASS_SM_DIRECTED_ROUTE == Smp->common.MgmtClass ) && + ( Smp->common.u.DR.HopPointer == 0 + || Smp->common.u.DR.HopPointer == 1) && + ( Smp->common.u.DR.HopCount == 0 )); +} + +static __inline void +STL_SMP_SET_LOCAL(STL_SMP *Smp) +{ + Smp->common.MgmtClass = MCLASS_SM_DIRECTED_ROUTE; + Smp->common.u.DR.HopPointer = 0; + Smp->common.u.DR.HopCount = 0; + Smp->SmpExt.DirectedRoute.DrSLID = STL_LID_PERMISSIVE; + Smp->SmpExt.DirectedRoute.DrDLID = STL_LID_PERMISSIVE; +} + +static __inline void +BSWAP_STL_SMP_HEADER(STL_SMP *Dest) +{ +#if CPU_LE + BSWAP_MAD_HEADER((MAD *)Dest); + + Dest->M_Key = ntoh64(Dest->M_Key); + if (Dest->common.MgmtClass == MCLASS_SM_DIRECTED_ROUTE) { + Dest->SmpExt.DirectedRoute.DrSLID = \ + ntoh32(Dest->SmpExt.DirectedRoute.DrSLID); + Dest->SmpExt.DirectedRoute.DrDLID = \ + ntoh32(Dest->SmpExt.DirectedRoute.DrDLID); + } +#endif +} + +static __inline void +BSWAPCOPY_STL_SMP(STL_SMP *Src, STL_SMP *Dest) +{ + memcpy(Dest, Src, sizeof(STL_SMP)); + (void)BSWAP_STL_SMP_HEADER(Dest); +} + +#define STL_BSWAP_SMP_HEADER BSWAP_STL_SMP_HEADER /* Temporary definition */ + +static __inline void +BSWAP_STL_TRAP_PORT_CHANGE_STATE_DATA(STL_TRAP_PORT_CHANGE_STATE_DATA * data) +{ +#if CPU_LE + data->Lid = ntoh32(data->Lid); +#endif +} + +static __inline void +BSWAP_STL_SMA_TRAP_DATA_LINK_WIDTH(STL_SMA_TRAP_DATA_LINK_WIDTH *Dest) +{ +#if CPU_LE + Dest->ReportingLID = ntoh32(Dest->ReportingLID); +#endif +} + + +static __inline void +BSWAP_STL_NODE_DESCRIPTION(STL_NODE_DESCRIPTION *Dest) +{ +#if CPU_LE + /* pure text field, nothing to swap */ +#endif +} + + +static __inline void +BSWAP_STL_NODE_INFO(STL_NODE_INFO *Dest) +{ +#if CPU_LE + Dest->SystemImageGUID = ntoh64(Dest->SystemImageGUID ); + Dest->NodeGUID = ntoh64(Dest->NodeGUID); + Dest->PortGUID = ntoh64(Dest->PortGUID); + Dest->PartitionCap = ntoh16(Dest->PartitionCap); + Dest->DeviceID = ntoh16(Dest->DeviceID); + Dest->Revision = ntoh32(Dest->Revision); + Dest->u1.AsReg32 = ntoh32(Dest->u1.AsReg32); +#endif +} + + +/* NOTE: for this implementation the cost of checking for and handling + * overlapping memory regions is assumed to be higher than warranted. + */ +static __inline void +BSWAPCOPY_STL_NODE_INFO(STL_NODE_INFO *Src, STL_NODE_INFO *Dest) +{ +if (Src != Dest) + (void)memcpy((void *)Dest, (void *)Src, sizeof(STL_NODE_INFO)); + BSWAP_STL_NODE_INFO(Dest); +} + +static __inline void +BSWAP_STL_SWITCH_INFO(STL_SWITCH_INFO *Dest) +{ +#if CPU_LE + Dest->LinearFDBCap = ntoh32(Dest->LinearFDBCap); + Dest->PortGroupFDBCap = ntoh32(Dest->PortGroupFDBCap); + Dest->MulticastFDBCap = ntoh32(Dest->MulticastFDBCap); + Dest->LinearFDBTop = ntoh32(Dest->LinearFDBTop); + Dest->MulticastFDBTop = ntoh32(Dest->MulticastFDBTop); + Dest->CollectiveCap = ntoh32(Dest->CollectiveCap); + Dest->CollectiveTop = ntoh32(Dest->CollectiveTop); + Dest->PartitionEnforcementCap = ntoh16(Dest->PartitionEnforcementCap); + Dest->AdaptiveRouting.AsReg16 = ntoh16(Dest->AdaptiveRouting.AsReg16); + Dest->CapabilityMask.AsReg16 = ntoh16(Dest->CapabilityMask.AsReg16); + Dest->CapabilityMaskCollectives.AsReg16 = ntoh16(Dest->CapabilityMaskCollectives.AsReg16); +#endif +} + +static __inline void +ZERO_RSVD_STL_SWITCH_INFO(STL_SWITCH_INFO * Dest) +{ + Dest->Reserved = 0; + + Dest->Reserved24 = 0; + Dest->Reserved26 = 0; + Dest->Reserved27 = 0; + + Dest->Reserved28 = 0; + Dest->Reserved21 = 0; + Dest->Reserved22 = 0; + Dest->Reserved23 = 0; + + Dest->u1.s.Reserved20 = 0; + + Dest->u2.s.Reserved20 = 0; + Dest->u2.s.Reserved21 = 0; + Dest->u2.s.Reserved22 = 0; + Dest->u2.s.Reserved23 = 0; + Dest->u2.s.Reserved = 0; + + Dest->MultiCollectMask.Reserved = 0; + Dest->AdaptiveRouting.s.Reserved = 0; + Dest->CapabilityMask.s.Reserved = 0; + Dest->CapabilityMaskCollectives.s.Reserved = 0; +} + +static __inline void +BSWAPCOPY_STL_SWITCH_INFO(STL_SWITCH_INFO *Src, STL_SWITCH_INFO *Dest) +{ + if (Src != Dest) memcpy((void *)Dest, (void *)Src, sizeof(STL_SWITCH_INFO)); + BSWAP_STL_SWITCH_INFO(Dest); +} + +static __inline void +BSWAP_STL_MKEY(uint64_t *mkey) +{ +#if CPU_LE + *mkey = ntoh64(*mkey); +#endif +} + +static __inline void +BSWAPCOPY_STL_MKEY(uint64_t *Src, uint64_t *Dest) +{ + if (Src != Dest) memcpy((void *)Dest, (void *)Src, sizeof(uint64_t)); + BSWAP_STL_MKEY(Dest); +} + +static __inline void +BSWAP_STL_PORT_INFO(STL_PORT_INFO *Dest) +{ +#if CPU_LE + Dest->LID = ntoh32(Dest->LID); + Dest->FlowControlMask = ntoh32(Dest->FlowControlMask); + Dest->VL.HighLimit = ntoh16(Dest->VL.HighLimit); + Dest->VL.PreemptingLimit = ntoh16(Dest->VL.PreemptingLimit); + Dest->PortStates.AsReg32 = ntoh32(Dest->PortStates.AsReg32); + Dest->P_Keys.P_Key_8B = ntoh16(Dest->P_Keys.P_Key_8B); + Dest->P_Keys.P_Key_10B = ntoh16(Dest->P_Keys.P_Key_10B); + Dest->Violations.M_Key = ntoh16(Dest->Violations.M_Key); + Dest->Violations.P_Key = ntoh16(Dest->Violations.P_Key); + Dest->Violations.Q_Key = ntoh16(Dest->Violations.Q_Key); + Dest->SM_TrapQP.AsReg32 = ntoh32(Dest->SM_TrapQP.AsReg32); + Dest->SA_QP.AsReg32 = ntoh32(Dest->SA_QP.AsReg32); + Dest->LinkSpeed.Supported = ntoh16(Dest->LinkSpeed.Supported); + Dest->LinkSpeed.Enabled = ntoh16(Dest->LinkSpeed.Enabled); + Dest->LinkSpeed.Active = ntoh16(Dest->LinkSpeed.Active); + Dest->LinkWidth.Supported = ntoh16(Dest->LinkWidth.Supported); + Dest->LinkWidth.Enabled = ntoh16(Dest->LinkWidth.Enabled); + Dest->LinkWidth.Active = ntoh16(Dest->LinkWidth.Active); + Dest->LinkWidthDowngrade.Supported = ntoh16(Dest->LinkWidthDowngrade.Supported); + Dest->LinkWidthDowngrade.Enabled = ntoh16(Dest->LinkWidthDowngrade.Enabled); + Dest->LinkWidthDowngrade.TxActive = ntoh16(Dest->LinkWidthDowngrade.TxActive); + Dest->LinkWidthDowngrade.RxActive = ntoh16(Dest->LinkWidthDowngrade.RxActive); + Dest->PortLinkMode.AsReg16 = ntoh16(Dest->PortLinkMode.AsReg16); + Dest->PortLTPCRCMode.AsReg16 = ntoh16(Dest->PortLTPCRCMode.AsReg16); + Dest->PortMode.AsReg16 = ntoh16(Dest->PortMode.AsReg16); + Dest->PortPacketFormats.Supported = ntoh16(Dest->PortPacketFormats.Supported); + Dest->PortPacketFormats.Enabled = ntoh16(Dest->PortPacketFormats.Enabled); + Dest->FlitControl.Interleave.AsReg16 = ntoh16(Dest->FlitControl.Interleave.AsReg16); + Dest->FlitControl.Preemption.MinInitial = ntoh16(Dest->FlitControl.Preemption.MinInitial); + Dest->FlitControl.Preemption.MinTail = ntoh16(Dest->FlitControl.Preemption.MinTail); + Dest->MaxLID = ntoh32(Dest->MaxLID); + Dest->PortErrorAction.AsReg32 = ntoh32(Dest->PortErrorAction.AsReg32); + Dest->M_KeyLeasePeriod = ntoh16(Dest->M_KeyLeasePeriod); + + + + Dest->BufferUnits.AsReg32 = ntoh32(Dest->BufferUnits.AsReg32); + Dest->MasterSMLID = ntoh32(Dest->MasterSMLID); + Dest->M_Key = ntoh64(Dest->M_Key); + Dest->SubnetPrefix = ntoh64(Dest->SubnetPrefix); + Dest->NeighborNodeGUID = ntoh64(Dest->NeighborNodeGUID); + Dest->CapabilityMask.AsReg32 = ntoh32(Dest->CapabilityMask.AsReg32); + Dest->CapabilityMask3.AsReg16 = ntoh16(Dest->CapabilityMask3.AsReg16); + Dest->OverallBufferSpace = ntoh16(Dest->OverallBufferSpace); + Dest->DiagCode.AsReg16 = ntoh16(Dest->DiagCode.AsReg16); +#endif +} + +static __inline void +ZERO_RSVD_STL_PORT_INFO(STL_PORT_INFO * Dest) +{ + Dest->VL.s2.Reserved = 0; + Dest->PortStates.s.Reserved = 0; + Dest->PortPhysConfig.s.Reserved = 0; + Dest->MultiCollectMask.Reserved = 0; + Dest->s2.Reserved = 0; + Dest->s1.Reserved = 0; + Dest->s3.Reserved20 = 0; + Dest->s3.Reserved21 = 0; + Dest->s4.Reserved = 0; + Dest->SM_TrapQP.s.Reserved = 0; + Dest->SA_QP.s.Reserved = 0; + Dest->PortLinkMode.s.Reserved = 0; + Dest->PortLTPCRCMode.s.Reserved = 0; + Dest->PortMode.s.Reserved = 0; + Dest->PortMode.s.Reserved2 = 0; + Dest->PortMode.s.Reserved3 = 0; + Dest->FlitControl.Interleave.s.Reserved = 0; + Dest->PortErrorAction.s.Reserved = 0; + Dest->PortErrorAction.s.Reserved2 = 0; + Dest->PortErrorAction.s.Reserved3 = 0; + Dest->PortErrorAction.s.Reserved4 = 0; + Dest->PassThroughControl.Reserved = 0; + Dest->BufferUnits.s.Reserved = 0; + + Dest->Reserved14 = 0; + Dest->BundleNextPort = 0; + Dest->BundleLane = 0; + // Reserved fields in the RO section + Dest->Reserved27 = 0; + Dest->Reserved28 = 0; + Dest->Reserved20 = 0; + + Dest->CapabilityMask.s.CmReserved6 = 0; + Dest->CapabilityMask.s.CmReserved24 = 0; + Dest->CapabilityMask.s.CmReserved5 = 0; + Dest->CapabilityMask.s.CmReserved23 = 0; + Dest->CapabilityMask.s.CmReserved22 = 0; + Dest->CapabilityMask.s.CmReserved21 = 0; + Dest->CapabilityMask.s.CmReserved25 = 0; + Dest->CapabilityMask.s.CmReserved2 = 0; + Dest->CapabilityMask.s.CmReserved20 = 0; + Dest->CapabilityMask.s.CmReserved1 = 0; + Dest->CapabilityMask3.s.CmReserved0 = 0; + Dest->CapabilityMask3.s.CmReserved1 = 0; + Dest->CapabilityMask3.s.CmReserved2 = 0; + Dest->CapabilityMask3.s.CmReserved3 = 0; + Dest->CapabilityMask3.s.CmReserved4 = 0; + Dest->PortNeighborMode.Reserved = 0; + Dest->MTU.Reserved20 = 0; + Dest->Resp.Reserved = 0; + Dest->Reserved24 = 0; + Dest->Reserved25 = 0; + + Dest->Reserved23 = 0; +} + +static __inline void +BSWAP_STL_PARTITION_TABLE(STL_PARTITION_TABLE *Dest) +{ +#if CPU_LE + uint32 i; + + for (i = 0; i < NUM_PKEY_ELEMENTS_BLOCK; i++) + { + Dest->PartitionTableBlock[i].AsReg16 = \ + ntoh16(Dest->PartitionTableBlock[i].AsReg16); + } +#endif +} + +static __inline void +BSWAPCOPY_STL_PARTITION_TABLE(STL_PARTITION_TABLE *Src, STL_PARTITION_TABLE *Dest) +{ + if (Src != Dest) memcpy(Dest, Src, sizeof(STL_PARTITION_TABLE)); + BSWAP_STL_PARTITION_TABLE(Dest); +} + + +static __inline void +BSWAP_STL_SLSCMAP(STL_SLSCMAP *Dest) +{ +#if CPU_LE + /* nothing to swap */ +#endif +} + +static __inline void +ZERO_RSVD_STL_SLSCMAP(STL_SLSCMAP * Dest) +{ + uint32 i; + for (i = 0; i < sizeof(Dest->SLSCMap)/sizeof(Dest->SLSCMap[0]); ++i) { + Dest->SLSCMap[i].Reserved = 0; + } +} + +static __inline void +BSWAP_STL_SCSCMAP(STL_SCSCMAP *Dest) +{ +#if CPU_LE + /* nothing to swap */ +#endif +} + + +static __inline void +BSWAP_STL_SCSLMAP(STL_SCSLMAP *Dest) +{ +#if CPU_LE + /* nothing to swap */ +#endif +} + +static __inline void +ZERO_RSVD_STL_SCSLMAP(STL_SCSLMAP *Dest) +{ + uint32 i; + for (i = 0; i < sizeof(Dest->SCSLMap)/sizeof(Dest->SCSLMap[0]); ++i) { + Dest->SCSLMap[i].Reserved = 0; + } +} + +static __inline void +BSWAP_STL_SCVLMAP(STL_SCVLMAP *Dest) +{ +#if CPU_LE + /* nothing to swap */ +#endif +} + +static __inline void +ZERO_RSVD_STL_SCVLMAP(STL_SCVLMAP *Dest) +{ + uint32 i; + for (i = 0; i < sizeof(Dest->SCVLMap)/sizeof(Dest->SCVLMap[0]); ++i) { + Dest->SCVLMap[i].Reserved = 0; + } +} +/* The section flag refers to which section of STL_VLARB_TABLE + * is to be swapped (see STL_VLARB_TABLE). Only the Preemption + * Matrix section (STL_VLARB_PREEMPT_MATRIX) requires action. + */ +static __inline void +BSWAP_STL_VLARB_TABLE(STL_VLARB_TABLE *Dest, int section) +{ +#if CPU_LE + uint32 i; + + if (section == STL_VLARB_PREEMPT_MATRIX) + { + for (i = 0; i < STL_MAX_VLS; i++) + Dest->Matrix[i] = ntoh32(Dest->Matrix[i]); + } +#endif +} + +static __inline void +ZERO_RSVD_STL_VLARB_TABLE(STL_VLARB_TABLE *Dest, uint8 section) +{ + if (section != STL_VLARB_PREEMPT_MATRIX) { + uint32 i; + for (i = 0; i < VLARB_TABLE_LENGTH; ++i) + Dest->Elements[i].s.Reserved = 0; + } +} + +static __inline void +BSWAP_STL_PORT_SELECTMASK(STL_PORTMASK *Dest) +{ +#if CPU_LE + unsigned int i; + + for (i=0; iIngressPortMask); + BSWAP_STL_PORT_SELECTMASK(Dest->EgressPortMask); +#endif +} + + +static __inline void +BSWAP_STL_LINEAR_FORWARDING_TABLE(STL_LINEAR_FORWARDING_TABLE *Dest) +{ +#if CPU_LE + /* nothing to swap */ +#endif +} + + +static __inline void +BSWAP_STL_MULTICAST_FORWARDING_TABLE(STL_MULTICAST_FORWARDING_TABLE *Dest) +{ +#if CPU_LE + uint32 i; + + for (i = 0; i < STL_NUM_MFT_ELEMENTS_BLOCK; i++) + { + Dest->MftBlock[i] = ntoh64(Dest->MftBlock[i]); + } +#endif +} + +static __inline void +BSWAP_STL_SM_INFO(STL_SM_INFO *Dest) +{ +#if CPU_LE + Dest->PortGUID = ntoh64(Dest->PortGUID); + Dest->SM_Key = ntoh64(Dest->SM_Key); + Dest->ActCount = ntoh32(Dest->ActCount); + Dest->ElapsedTime = ntoh32(Dest->ElapsedTime); + Dest->u.AsReg16 = ntoh16(Dest->u.AsReg16); +#endif +} + +static __inline void +BSWAPCOPY_STL_SM_INFO(STL_SM_INFO *Src, STL_SM_INFO *Dest) +{ + memcpy(Dest, Src, sizeof(STL_SM_INFO)); + BSWAP_STL_SM_INFO(Dest); +} + +static __inline const char* +StlSMStateToText(SM_STATE state) +{ + return ((state == SM_INACTIVE)? "Inactive": + (state == SM_DISCOVERING)? "Discovering": + (state == SM_STANDBY)? "Standby": + (state == SM_MASTER)? "Master": "???"); +} + +static __inline void +BSWAP_STL_LED_INFO(STL_LED_INFO *Dest) +{ +#if CPU_LE + Dest->u.AsReg32 = ntoh32(Dest->u.AsReg32); +#endif +} + +static __inline void +ZERO_RSVD_STL_LED_INFO(STL_LED_INFO *Dest) { + + Dest->u.s.Reserved = 0; + Dest->Reserved2 = 0; + +} + + +static __inline void +BSWAP_STL_CABLE_INFO(STL_CABLE_INFO *Dest) +{ +#if CPU_LE + /* nothing to swap */ +#endif +} + + +static __inline void +BSWAP_STL_AGGREGATE(STL_AGGREGATE *Dest) +{ +#if CPU_LE + Dest->AttributeID = ntoh16(Dest->AttributeID); + Dest->Result.AsReg16 = ntoh16(Dest->Result.AsReg16); + Dest->AttributeModifier = ntoh32(Dest->AttributeModifier); +#endif +} + + +/* num_ports is the number of port entries in STL_PORT_STATE_INFO */ +static __inline void +BSWAP_STL_PORT_STATE_INFO(STL_PORT_STATE_INFO *Dest, uint8 num_ports) +{ +#if CPU_LE + uint32 i; + + for (i = 0; i < num_ports; i++) + { + Dest[i].PortStates.AsReg32 = ntoh32(Dest[i].PortStates.AsReg32); + Dest[i].LinkWidthDowngradeTxActive = ntoh16(Dest[i].LinkWidthDowngradeTxActive); + Dest[i].LinkWidthDowngradeRxActive = ntoh16(Dest[i].LinkWidthDowngradeRxActive); + } +#endif +} + + +static __inline void +BSWAP_STL_PORT_GROUP_FORWARDING_TABLE(STL_PORT_GROUP_FORWARDING_TABLE *Dest) +{ +#if CPU_LE + /* nothing to swap */ +#endif +} + + +static __inline void +BSWAP_STL_PORT_GROUP_TABLE(STL_PORT_GROUP_TABLE *Dest) +{ +#if CPU_LE + uint32 i; + + for (i = 0; i < NUM_PGT_ELEMENTS_BLOCK; i++) + { + Dest->PgtBlock[i] = ntoh64(Dest->PgtBlock[i]); + } +#endif +} + +static __inline void +BSWAP_STL_BUFFER_CONTROL_TABLE(STL_BUFFER_CONTROL_TABLE *Dest) +{ +#if CPU_LE + uint32 i; + + Dest->TxOverallSharedLimit = ntoh16(Dest->TxOverallSharedLimit); + + for (i = 0; i < STL_MAX_VLS; i++) + { + Dest->VL[i].TxDedicatedLimit = ntoh16(Dest->VL[i].TxDedicatedLimit); + Dest->VL[i].TxSharedLimit = ntoh16(Dest->VL[i].TxSharedLimit); + } +#endif +} + +static __inline void +BSWAP_STL_CONGESTION_INFO(STL_CONGESTION_INFO *Dest) +{ +#if CPU_LE + Dest->CongestionInfo = ntoh16(Dest->CongestionInfo); +#endif +} + + +/* num_blocks is the number of blocks in STL_SWITCH_CONGESTION_LOG to swap */ +static __inline void +BSWAP_STL_SWITCH_CONGESTION_LOG(STL_SWITCH_CONGESTION_LOG *Dest) +{ +#if CPU_LE + uint32 i; + + Dest->LogEventsCounter = ntoh16(Dest->LogEventsCounter); + Dest->CurrentTimeStamp = ntoh32(Dest->CurrentTimeStamp); + + for (i = 0; i < STL_NUM_CONGESTION_LOG_ELEMENTS; i++) + { + Dest->CongestionEntryList[i].SLID = ntoh32(Dest->CongestionEntryList[i].SLID); + Dest->CongestionEntryList[i].DLID = ntoh32(Dest->CongestionEntryList[i].DLID); + Dest->CongestionEntryList[i].TimeStamp = ntoh32(Dest->CongestionEntryList[i].TimeStamp); + } +#endif +} + + +static __inline void +BSWAP_STL_SWITCH_CONGESTION_SETTING(STL_SWITCH_CONGESTION_SETTING *Dest) +{ +#if CPU_LE + Dest->Control_Map = ntoh32(Dest->Control_Map); + Dest->CS_ReturnDelay = ntoh16(Dest->CS_ReturnDelay); + Dest->Marking_Rate = ntoh16(Dest->Marking_Rate); +#endif +} + +static __inline void +ZERO_RSVD_STL_SWITCH_CONGESTION_SETTING(STL_SWITCH_CONGESTION_SETTING *Dest) +{ + Dest->Reserved = 0; + Dest->Reserved2 = 0; + Dest->Reserved3 = 0; +} + +/* num_ports is the number of ports in STL_SWITCH_PORT_CONGESTION_SETTING to swap */ +static __inline void +BSWAP_STL_SWITCH_PORT_CONGESTION_SETTING(STL_SWITCH_PORT_CONGESTION_SETTING *Dest, uint8 num_ports) +{ +#if CPU_LE + uint32 i; + + for (i = 0; i < num_ports; i++) + { + Dest->Elements[i].Marking_Rate = ntoh16(Dest->Elements[i].Marking_Rate); + } +#endif +} + + +/* num_blocks is the number of blocks in STL_HFI_CONGESTION_LOG to swap */ +static __inline void +BSWAP_STL_HFI_CONGESTION_LOG(STL_HFI_CONGESTION_LOG *Dest) +{ +#if CPU_LE + uint32 i; + + Dest->ThresholdEventCounter = ntoh16(Dest->ThresholdEventCounter); + Dest->CurrentTimeStamp = ntoh16(Dest->CurrentTimeStamp); + + for (i = 0; i < STL_NUM_CONGESTION_LOG_ELEMENTS; i++) + { + Dest->CongestionEntryList[i].Remote_LID_CN_Entry = + ntoh32(Dest->CongestionEntryList[i].Remote_LID_CN_Entry); + Dest->CongestionEntryList[i].TimeStamp_CN_Entry = + ntoh32(Dest->CongestionEntryList[i].TimeStamp_CN_Entry); + } +#endif +} + + +static __inline void +BSWAP_STL_HFI_CONGESTION_SETTING(STL_HFI_CONGESTION_SETTING *Dest) +{ +#if CPU_LE + uint32 i; + + Dest->Port_Control = ntoh16(Dest->Port_Control); + Dest->Control_Map = ntoh32(Dest->Control_Map); + + for (i = 0; i < STL_MAX_SLS; i++) + { + Dest->HFICongestionEntryList[i].CCTI_Timer = + ntoh16(Dest->HFICongestionEntryList[i].CCTI_Timer); + } +#endif +} + + +/* num_blocks is the number of blocks in STL_HFI_CONGESTION_CONTROL_TABLE to swap */ +static __inline void +BSWAP_STL_HFI_CONGESTION_CONTROL_TABLE(STL_HFI_CONGESTION_CONTROL_TABLE *Dest, uint8 num_blocks) +{ +#if CPU_LE + uint32 i,j; + + Dest->CCTI_Limit = ntoh16(Dest->CCTI_Limit); + + for(i = 0; i < num_blocks; ++i) { + for (j = 0; j < STL_NUM_CONGESTION_CONTROL_ELEMENTS_BLOCK_ENTRIES; ++j) { + Dest->CCT_Block_List[i].CCT_Entry_List[j].AsReg16 = + ntoh16(Dest->CCT_Block_List[i].CCT_Entry_List[j].AsReg16); + } + } +#endif +} + + +#if defined (__cplusplus) +}; +#endif + +#endif /* __IBA_STL_SM_PRIV_H__ */ diff --git a/IbAccess/Common/Inc/stl_sm_types.h b/IbAccess/Common/Inc/stl_sm_types.h new file mode 100644 index 0000000..143fb07 --- /dev/null +++ b/IbAccess/Common/Inc/stl_sm_types.h @@ -0,0 +1,2175 @@ +/* BEGIN_ICS_COPYRIGHT7 **************************************** + +Copyright (c) 2015-2018, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT7 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +#ifndef __IBA_STL_SM_TYPES_H__ +#define __IBA_STL_SM_TYPES_H__ + +#include "iba/stl_types.h" +#include "iba/ib_sm_types.h" + +#if defined (__cplusplus) +extern "C" { +#endif + +#include "iba/public/ipackon.h" + +/* + * Defines + */ + +#define STL_SM_CLASS_VERSION 0x80 /* Subnet Management */ + +/* SMP Attributes */ +#define STL_MCLASS_ATTRIB_ID_NODE_DESCRIPTION 0x0010 /* Node Description */ +#define STL_MCLASS_ATTRIB_ID_NODE_INFO 0x0011 /* Node Information */ +#define STL_MCLASS_ATTRIB_ID_SWITCH_INFO 0x0012 /* Switch Information */ +#define STL_MCLASS_ATTRIB_ID_PORT_INFO 0x0015 /* Port Information */ +#define STL_MCLASS_ATTRIB_ID_PART_TABLE 0x0016 /* Partition Table */ +#define STL_MCLASS_ATTRIB_ID_SL_SC_MAPPING_TABLE 0x0017 /* Service Level to */ + /* Service Channel Mapping Table */ +#define STL_MCLASS_ATTRIB_ID_VL_ARBITRATION 0x0018 /* Lists of VL Arbitration Weights */ +#define STL_MCLASS_ATTRIB_ID_LINEAR_FWD_TABLE 0x0019 /* Linear Forwarding Table */ +// reserved 0x001A /* (was) Random Forwarding Table */ +#define STL_MCLASS_ATTRIB_ID_MCAST_FWD_TABLE 0x001B /* Multicast Forwarding Table */ +#define STL_MCLASS_ATTRIB_ID_SM_INFO 0x0020 /* Subnet Manager Information */ +#define STL_MCLASS_ATTRIB_ID_LED_INFO 0x0031 /* Turn on/off beaconing LED */ +#define STL_MCLASS_ATTRIB_ID_CABLE_INFO 0x0032 /* Cable Information */ + +#define STL_MCLASS_ATTRIB_ID_AGGREGATE 0x0080 /* Aggregate */ +#define STL_MCLASS_ATTRIB_ID_SC_SC_MAPPING_TABLE 0x0081 /* Service Channel to */ + /* Service Channel Mapping Table */ +#define STL_MCLASS_ATTRIB_ID_SC_SL_MAPPING_TABLE 0x0082 /* Service Channel to */ + /* Service Level Mapping Table */ +#define STL_MCLASS_ATTRIB_ID_SC_VLR_MAPPING_TABLE 0x0083 /* Service Channel to Virtual */ + /* Lane Receive Mapping Table */ +#define STL_MCLASS_ATTRIB_ID_SC_VLT_MAPPING_TABLE 0x0084 /* Service Channel to Virtual */ + /* Lane Transmit Mapping Table */ +#define STL_MCLASS_ATTRIB_ID_SC_VLNT_MAPPING_TABLE 0x0085 /* Service Channel to Virtual */ + /* Lane Credit Return Mapping Table */ +#define STL_MCLASS_ATTRIB_ID_PORT_STATE_INFO 0x0087 /* Port State Information */ +#define STL_MCLASS_ATTRIB_ID_PORT_GROUP_FWD_TABLE 0x0088 /* Adaptive Routing Port Group Forwarding Table */ +#define STL_MCLASS_ATTRIB_ID_PORT_GROUP_TABLE 0x0089 /* Adaptive Routing Port Group Table */ +#define STL_MCLASS_ATTRIB_ID_BUFFER_CONTROL_TABLE 0x008A /* Buffer Control Table */ +#define STL_MCLASS_ATTRIB_ID_CONGESTION_INFO 0x008B /* Congestion Information */ +#define STL_MCLASS_ATTRIB_ID_SWITCH_CONGESTION_LOG 0x008C /* Congestion Log */ +#define STL_MCLASS_ATTRIB_ID_SWITCH_CONGESTION_SETTING 0x008D /* Switch Congestion Setting */ +#define STL_MCLASS_ATTRIB_ID_SWITCH_PORT_CONGESTION_SETTING 0x008E /* Switch Congestion Setting */ +#define STL_MCLASS_ATTRIB_ID_HFI_CONGESTION_LOG 0x008F /* Congestion Log */ +#define STL_MCLASS_ATTRIB_ID_HFI_CONGESTION_SETTING 0x0090 /* HFI Congestion Setting */ +#define STL_MCLASS_ATTRIB_ID_HFI_CONGESTION_CONTROL_TABLE 0x0091 /* HFI Congestion Control Table */ + +#define STL_MCLASS_ATTRIB_ID_SC_SC_MULTI_SET 0x0094 /* Service Channel to Service */ + +/* SMP Attribute Modifiers */ +#define STL_SM_CONF_START_ATTR_MOD 0x00000200 /* PortInfo & PortStateInfo Attr Mod Flag */ + + +/* ************************************************************************* + * SMPs + */ + +/* SMP Fields (LID Routed/Directed Route) */ + +#define STL_MAX_PAYLOAD_SMP_DR 1872 /* Max size of DR SMP payload */ +#define STL_MAX_PAYLOAD_SMP_LR 2016 /* Max size of LR SMP payload */ + +#define STL_MIN_SMP_DR_MAD (STL_MAD_BLOCK_SIZE - STL_MAX_PAYLOAD_SMP_DR) +#define STL_MIN_SMP_LR_MAD (STL_MAD_BLOCK_SIZE - STL_MAX_PAYLOAD_SMP_LR) + +typedef struct { + MAD_COMMON common; + uint64 M_Key; /* A 64 bit key, */ + /* employed for SM authentication */ + union { + struct _STL_LIDRouted { + uint8 SMPData[STL_MAX_PAYLOAD_SMP_LR]; /* Up to 'MAX' byte field of SMP */ + /* data used to contain the */ + /* method's attribute */ + } LIDRouted; + + struct _STL_DirectedRoute { + STL_LID DrSLID; /* Directed route source LID */ + STL_LID DrDLID; /* Directed route destination LID */ + uint8 InitPath[64]; /* 64-byte field containing the initial */ + /* directed path */ + uint8 RetPath[64]; /* 64-byte field containing the */ + /* returning directed path */ + uint8 Reserved2[8]; /* For the purpose of aligning the Data */ + /* field on a 16-byte boundary */ + + uint8 SMPData[STL_MAX_PAYLOAD_SMP_DR]; /* Up to 'MAX' byte field of SMP */ + /* data used to contain the */ + /* method's attribute */ + } DirectedRoute; + }SmpExt; + +} PACK_SUFFIX STL_SMP; + + +/* ************************************************************************** + * Attribute specific SMP Packet Formats + * + * In the attributes which follow member fields are marked (where appropriate) + * with usage information as: 'AccessType/NodeType/IB-Only'. AccessType + * refers to how members can be accessed; NodeType refers to which node + * types the member applies; IB-Only refers to members which have been + * deprecated for STL use but retained to report information about IB nodes. + * + * AccessType: Read Write ('RW'), Read Only ('RO') + * + * NodeType: HFI ('H'), External Switch Port ('S'), Base Switch Port 0 ('P'), + * Enhanced Switch Port 0 ('E'). NodeType is shown as a 4-character string + * with each character representing (in positional order) a node type 'HSPE'. + * If a node type is not applicable for a member, its character position is + * shown as '-' (ex. 'H-PE'). + * + * Power-On-Default values are shown as 'POD: xxx' + * Link-Up-Default values are shown as 'LUD: xxx' + * + * Member fields which require a link bounce for new values to become effective + * are marked 'LinkBounce' + */ + +/* + * SMA Notices/Traps (Data field for IB_NOTICE) + */ + +/* Trap Numbers */ +#define STL_TRAP_GID_NOW_IN_SERVICE 0x40 +#define STL_TRAP_GID_OUT_OF_SERVICE 0x41 +#define STL_TRAP_ADD_MULTICAST_GROUP 0x42 +#define STL_TRAP_DEL_MULTICAST_GROUP 0x43 +#define STL_TRAP_LINK_PORT_CHANGE_STATE 0x80 +#define STL_TRAP_LINK_INTEGRITY 0x81 +#define STL_TRAP_BUFFER_OVERRUN 0x82 +#define STL_TRAP_FLOW_WATCHDOG 0x83 +#define STL_TRAP_CHANGE_CAPABILITY 0x90 +#define STL_TRAP_CHANGE_SYSGUID 0x91 +#define STL_TRAP_BAD_M_KEY 0x100 +#define STL_TRAP_BAD_P_KEY 0x101 +#define STL_TRAP_BAD_Q_KEY 0x102 +#define STL_TRAP_SWITCH_BAD_PKEY 0x103 +#define STL_SMA_TRAP_LINK_WIDTH 0x800 +#define STL_TRAP_COST_MATRIX_CHANGE 0x801 + +typedef struct { + IB_GID Gid; +} PACK_SUFFIX STL_TRAP_GID; + +#define STL_TRAP_GID_NOW_IN_SERVICE_DATA STL_TRAP_GID +#define STL_TRAP_GID_OUT_OF_SERVICE_DATA STL_TRAP_GID +#define STL_TRAP_GID_ADD_MULTICAST_GROUP_DATA STL_TRAP_GID +#define STL_TRAP_GID_DEL_MULTICAST_GROUP_DATA STL_TRAP_GID + +typedef struct { + STL_LID Lid; +} PACK_SUFFIX STL_TRAP_PORT_CHANGE_STATE_DATA; + +typedef struct { + STL_LID Lid; + uint8 Port; +} PACK_SUFFIX STL_TRAP_LINK; +#define STL_TRAP_LINK_INTEGRITY_DATA STL_TRAP_LINK +#define STL_TRAP_BUFFER_OVERRUN_DATA STL_TRAP_LINK +#define STL_TRAP_FLOW_WATCHDOG_DATA STL_TRAP_LINK + +typedef STL_FIELDUNION16(STL_CAPABILITY_MASK, 32, + CmReserved6: 1, /* shall be zero */ + CmReserved24: 2, /* shall be zero */ + CmReserved5: 2, /* shall be zero */ + CmReserved23: 4, /* shall be zero */ + IsCapabilityMaskNoticeSupported: 1, + CmReserved22: 1, /* shall be zero */ + IsVendorClassSupported: 1, + IsDeviceManagementSupported: 1, + CmReserved21: 2, /* shall be zero */ + IsConnectionManagementSupported: 1, + CmReserved25: 10, /* shall be zero */ + IsAutomaticMigrationSupported: 1, + CmReserved2: 1, /* shall be zero */ + CmReserved20: 2, + IsSM: 1, + CmReserved1: 1 ); /* shall be zero */ + +/* Capability Mask 3 - a bit set to 1 for affirmation of supported capability + * by a given port + */ +typedef STL_FIELDUNION15(STL_CAPABILITY_MASK3, 16, + CmReserved0: 1, + CmReserved1: 1, + CmReserved2: 1, + IsMAXLIDSupported: 1, /* RO/H--- Does the HFI support the MAX */ + /* LID being configured */ + CmReserved3: 1, + CmReserved4: 1, + VLSchedulingConfig: 2, /* RO/H-PE VL Arbitration */ + /* see STL_VL_SCHEDULING_MODE */ + /* Port 0 indicates whole switch */ + IsSnoopSupported: 1, /* RO/--PE Packet snoop */ + /* Port 0 indicates whole switch */ + IsAsyncSC2VLSupported: 1, /* RO/H-PE Port 0 indicates whole switch */ + IsAddrRangeConfigSupported: 1, /* RO/H-PE Can addr range for Multicast */ + /* and Collectives be configured */ + /* Port 0 indicates whole switch */ + IsPassThroughSupported: 1, /* RO/--PE Packet pass through */ + /* Port 0 indicates whole switch */ + IsSharedSpaceSupported: 1, /* RO/H-PE Shared Space */ + /* Port 0 indicates whole switch */ + IsSharedGroupSpaceSupported:1, /* RO/H-PE Shared Space */ + /* Port 0 indicates whole switch */ + IsVLMarkerSupported: 1, /* RO/H-PE VL Marker */ + /* Port 0 indicates whole switch */ + IsVLrSupported: 1 ); /* RO/H-PE SC->VL_r table */ + + +typedef enum { + VL_SCHED_MODE_VLARB = 0, /* VL Arbitration Tables */ + VL_SCHED_MODE_AUTOMATIC = 2, /* harcoded, not configurable */ + /* reserved 3 */ +} STL_VL_SCHEDULING_MODE; + +typedef struct { + STL_LID Lid; + STL_CAPABILITY_MASK CapabilityMask; + uint16 Reserved; + STL_CAPABILITY_MASK3 CapabilityMask3; + STL_FIELDUNION5(u,16, + Reserved:12, + LinkWidthDowngradeEnabledChange:1, + LinkSpeedEnabledChange:1, + LinkWidthEnabledChange:1, + NodeDescriptionChange:1); + +} PACK_SUFFIX STL_TRAP_CHANGE_CAPABILITY_DATA; + +typedef struct { + uint64 SystemImageGuid; + STL_LID Lid; +} PACK_SUFFIX STL_TRAP_SYSGUID_CHANGE_DATA; + +typedef struct { + STL_LID Lid; + STL_LID DRSLid; + /* 8 bytes */ + uint8 Method; + STL_FIELDUNION3(u,8, + DRNotice:1, + DRPathTruncated:1, + DRHopCount:6); + uint16 AttributeID; + /* 12 bytes */ + uint32 AttributeModifier; + /* 16 bytes */ + uint64 MKey; + /* 24 bytes */ + uint8 DRReturnPath[30]; // We can make this longer.... + /* 54 bytes */ +} PACK_SUFFIX STL_TRAP_BAD_M_KEY_DATA; + +typedef struct { + STL_LID Lid1; + STL_LID Lid2; + /* 8 bytes */ + uint32 Key; // pkey or qkey + STL_FIELDUNION2(u,8, + SL:5, + Reserved:3); + uint8 Reserved[3]; + /* 16 bytes */ + IB_GID Gid1; + /* 32 bytes */ + IB_GID Gid2; + /* 48 bytes */ + STL_FIELDUNION2(qp1,32, + Reserved:8, + qp:24); + /* 52 bytes */ + STL_FIELDUNION2(qp2,32, + Reserved:8, + qp:24); + /* 56 bytes */ +} PACK_SUFFIX STL_TRAP_BAD_KEY_DATA; + +#define STL_TRAP_BAD_P_KEY_DATA STL_TRAP_BAD_KEY_DATA +#define STL_TRAP_BAD_Q_KEY_DATA STL_TRAP_BAD_KEY_DATA + +typedef struct { + STL_FIELDUNION9(u,16, + Lid1:1, Lid2:1, PKey:1, SL:1, + QP1:1, QP2:1, Gid1:1, Gid2:1, + Reserved:8); + uint16 PKey; + /* 4 bytes */ + STL_LID Lid1; + STL_LID Lid2; + STL_FIELDUNION2(u2,8, + SL:5, + Reserved:3); + uint8 Reserved[3]; + /* 16 bytes */ + IB_GID Gid1; + /* 32 bytes */ + IB_GID Gid2; + /* 48 bytes */ + STL_FIELDUNION2(qp1,32, + qp:24, + Reserved:8); + /* 52 bytes */ + STL_FIELDUNION2(qp2,32, + qp:24, + Reserved:8); + /* 56 bytes */ +} PACK_SUFFIX STL_TRAP_SWITCH_BAD_PKEY_DATA; + +/* LinkWidth of at least one port of switch at has changed */ +typedef struct { + STL_LID ReportingLID; +} PACK_SUFFIX STL_SMA_TRAP_DATA_LINK_WIDTH; + +/* + * NodeInfo + * + * Attribute Modifier as: 0 (not used) + */ +typedef struct { + + uint8 BaseVersion; /* RO Supported MAD Base Version */ + uint8 ClassVersion; /* RO Supported Subnet Management Class */ + /* (SMP) Version */ + uint8 NodeType; + uint8 NumPorts; /* RO Number of link ports on this node */ + + uint32 Reserved; + + uint64 SystemImageGUID; + + uint64 NodeGUID; /* RO GUID of the HFI or switch */ + + uint64 PortGUID; /* RO GUID of this end port itself */ + + uint16 PartitionCap; /* RO Number of entries in the Partition Table */ + /* for end ports */ + uint16 DeviceID; /* RO Device ID information as assigned by */ + /* device manufacturer */ + uint32 Revision; /* RO Device revision, assigned by manufacturer */ + + STL_FIELDUNION2(u1, 32, + LocalPortNum: 8, /* RO The link port number this */ + /* SMP came on in */ + VendorID: 24); /* RO Device vendor, per IEEE */ + +} PACK_SUFFIX STL_NODE_INFO; + +/* + * NodeDescription + * + * Attribute Modifier as: 0 (not used) + */ + +#define STL_NODE_DESCRIPTION_ARRAY_SIZE 64 + +typedef struct { + + /* Node String is an array of UTF-8 character that */ + /* describes the node in text format */ + /* Note that this string MUST BE NULL TERMINATED! */ + uint8 NodeString[STL_NODE_DESCRIPTION_ARRAY_SIZE]; /* RO */ + +} PACK_SUFFIX STL_NODE_DESCRIPTION; + + +/* + * SwitchInfo + * + * Attribute Modifier as: 0 (not used) + */ + +/* STL Routing Modes */ +#define STL_ROUTE_NOP 0 /* No change */ +#define STL_ROUTE_LINEAR 1 /* Linear routing algorithm */ + + + +typedef union { + uint16 AsReg16; + struct { IB_BITFIELD5( uint16, + Reserved: 12, + + IsExtendedSCSCSupported: 1, /* RO Extended SCSC */ + IsAddrRangeConfigSupported: 1, /* Can addr range for Multicast */ + /* and Collectives be configured */ + Reserved2: 1, + IsAdaptiveRoutingSupported: 1 ) + } s; +} SWITCH_CAPABILITY_MASK; + +typedef union { + uint16 AsReg16; + struct { + uint16 Reserved; + } s; +} CAPABILITY_MASK_COLLECTIVES; + +typedef struct { + uint32 LinearFDBCap; /* RO Number of entries supported in the */ + /* Linear Unicast Forwarding Database */ + uint32 PortGroupFDBCap; /* RO Number of entries supported in the */ + /* Port Group Forwarding Database */ + uint32 MulticastFDBCap; /* RO Number of entries supported in the */ + /* Multicast Forwarding Database */ + STL_LID LinearFDBTop; /* RW Indicates the maximum DLID programmed */ + /* in the routing tables */ + /* POD: 0 */ + STL_LID MulticastFDBTop; /* RW Indicates the top of the Multicast */ + /* Forwarding Table */ + /* POD: 0 */ + uint32 CollectiveCap; /* RO Number of entries supported in the */ + /* Collective Table */ + /* Reserved in Gen1 */ + STL_LID CollectiveTop; /* RW Indicates the top of the Collective Table */ + /* POD: 0 */ + /* Reserved in Gen1 */ + uint32 Reserved; + + STL_IPV6_IP_ADDR IPAddrIPV6; /* RO IP Address - IPV6 */ + + STL_IPV4_IP_ADDR IPAddrIPV4; /* RO IP Address - IPV4 */ + + uint32 Reserved26; + uint32 Reserved27; + + uint32 Reserved28; + uint8 Reserved21; + uint8 Reserved22; + uint8 Reserved23; + + union { + uint8 AsReg8; + struct { IB_BITFIELD3( uint8, + LifeTimeValue: 5, /* LifeTimeValue */ + PortStateChange: 1, /* RW This bit is set to zero by a */ + /* management write */ + Reserved20: 2 ) + } s; + } u1; + + uint16 Reserved24; + uint16 PartitionEnforcementCap; /* RO Specifies the number of entries in the */ + /* partition enforcement table */ + uint8 PortGroupCap; /* RO Specifies the maximum number of */ + /* entries in the port group table */ + uint8 PortGroupTop; /* RW The current number of entries in */ + /* port group table. */ + + struct { /* RW (see STL_ROUTING_MODE) */ + uint8 Supported; /* Supported routing mode */ + uint8 Enabled; /* Enabled routing mode */ + } RoutingMode; + + union { + uint8 AsReg8; + struct { IB_BITFIELD6( uint8, + Reserved20: 1, + Reserved21: 1, + Reserved22: 1, + Reserved23: 1, + EnhancedPort0: 1, + Reserved: 3 ) + } s; + } u2; + + struct { IB_BITFIELD3( uint8, /* Multicast/Collectives masks */ + Reserved: 2, + CollectiveMask: 3, /* RW Num of additional upper 1s in */ + /* Collective address */ + /* POD: 1 */ + /* Reserved in Gen1 */ + MulticastMask: 3 ) /* RW Num of upper 1s in Multicast address */ + /* POD: 4 */ + } MultiCollectMask; + + STL_FIELDUNION8(AdaptiveRouting, 16, + Enable: 1, /* RW Enable/Disable AR */ + Pause: 1, /* RW Pause AR when true */ + Algorithm: 3, /* RW 0 = Random, 1 = Greedy, */ + /* 2 = Random Greedy. */ + Frequency: 3, /* RW 0-7. Value expands to 2^F*64ms. */ + LostRoutesOnly: 1, /* RW. Indicates that AR should only be done */ + /* for failed links. */ + Threshold: 3, /* CCA-level at which switch uses AR. */ + Reserved2: 1, + Reserved: 3); + + SWITCH_CAPABILITY_MASK CapabilityMask; /* RO */ + + CAPABILITY_MASK_COLLECTIVES CapabilityMaskCollectives; /* RW */ +} PACK_SUFFIX STL_SWITCH_INFO; + + +/* + * PortInfo + * + * Attribute Modifier as: NNNN NNNN 0000 0000 0000 00SA PPPP PPPP + * N: Number of ports + * S=1: Start of SM configuration + * A=1: All ports starting at P (Set only) + * P: Port number (0 - management port, switches only; + * for HFIs P is ignored and the attribute is + * applicable only to the port that receives the packet) + */ + +/* STL_PORT_STATE values continue from IB_PORT_STATE */ +/* reserved 5-6 */ + +/* STL_PORT_PHYS_STATE values continue from IB_PORT_PHYS_STATE */ +/* reserved 7-8 */ +#define STL_PORT_PHYS_OFFLINE 9 /* offline */ +/* reserved 10 */ +#define STL_PORT_PHYS_TEST 11 /* test */ + +/* Offline Disabled Reason, indicated as follows: */ +#define STL_OFFDIS_REASON_NONE 0 /* Nop/No specified reason */ +#define STL_OFFDIS_REASON_DISCONNECTED 1 /* not connected in design*/ +#define STL_OFFDIS_REASON_LOCAL_MEDIA_NOT_INSTALLED 2 /* Module not installed + * in connector (QSFP, + * SiPh_x16, etc) */ +#define STL_OFFDIS_REASON_NOT_INSTALLED 3 /* internal link not + * installed, neighbor FRU + * absent */ +#define STL_OFFDIS_REASON_CHASSIS_CONFIG 4 /* Chassis mgmt forced + * offline due to incompat + * or absent neighbor FRU */ +/* reserved 5 */ +#define STL_OFFDIS_REASON_END_TO_END_NOT_INSTALLED 6 /* local module present + * but unable to detect + * end to optical link */ +/* reserved 7 */ +#define STL_OFFDIS_REASON_POWER_POLICY 8 /* enabling port would + * exceed power policy */ +#define STL_OFFDIS_REASON_LINKSPEED_POLICY 9 /* enabled speed unable to + * be met due to persistent + * cause */ +#define STL_OFFDIS_REASON_LINKWIDTH_POLICY 10 /* enabled width unable to + * be met due to persistent + * cause */ +/* reserved 11 */ +#define STL_OFFDIS_REASON_SWITCH_MGMT 12 /* user disabled via switch + * mangement interface + */ +#define STL_OFFDIS_REASON_SMA_DISABLED 13 /* user disabled via SMA + * Set to phys port state + * disabled */ +/* reserved 14 */ +#define STL_OFFDIS_REASON_TRANSIENT 15 /* Transient offline as part + * of sync with neighbor + * phys port state machine*/ + +/* Link Init Reason, indicated as follows: */ +#define STL_LINKINIT_REASON_NOP 0 /* None on Get/no change on Set */ +#define STL_LINKINIT_REASON_LINKUP 1 /* link just came up */ +/* values from 2-7 will not be altered by transistions from Polling to Linkup/Init */ +/* these can represent persistent reasons why the SM is ignoring a link */ +#define STL_LINKINIT_REASON_FLAPPING 2 /* FM ignoring flapping port */ +/* reserved 3-7 */ +/* values from 8-15 will be altered by transistions from Polling to LinkUp/Init */ +/* these can represent transient reasons why the SM is ignoring a link */ +#define STL_LINKINIT_OUTSIDE_POLICY 8 /* FM ignoring, width or speed outside FM configured policy */ +#define STL_LINKINIT_QUARANTINED 9 /* FM ignoring, quarantined for security */ +#define STL_LINKINIT_INSUFIC_CAPABILITY 10 /* FM ignoring, link has insufficient capabilities*/ + /* for FM configuration (eg. MTU too small etc) */ +/* reserved 11-15 */ + + +/* these correspond to locally initiated link bounce due to PortErrorAction */ +/* See Section 9.8.3, “Error Counters”, Table 9-23 */ +#define STL_LINKDOWN_REASON_NONE 0 /* No specified reason */ +#define STL_LINKDOWN_REASON_RCV_ERROR_0 1 +#define STL_LINKDOWN_REASON_BAD_PKT_LEN 2 +#define STL_LINKDOWN_REASON_PKT_TOO_LONG 3 +#define STL_LINKDOWN_REASON_PKT_TOO_SHORT 4 +#define STL_LINKDOWN_REASON_BAD_SLID 5 +#define STL_LINKDOWN_REASON_BAD_DLID 6 +#define STL_LINKDOWN_REASON_BAD_L2 7 +#define STL_LINKDOWN_REASON_BAD_SC 8 +#define STL_LINKDOWN_REASON_RCV_ERROR_8 9 +#define STL_LINKDOWN_REASON_BAD_MID_TAIL 10 +#define STL_LINKDOWN_REASON_RCV_ERROR_10 11 +#define STL_LINKDOWN_REASON_PREEMPT_ERROR 12 +#define STL_LINKDOWN_REASON_PREEMPT_VL15 13 +#define STL_LINKDOWN_REASON_BAD_VL_MARKER 14 +#define STL_LINKDOWN_REASON_RCV_ERROR_14 15 +#define STL_LINKDOWN_REASON_RCV_ERROR_15 16 +#define STL_LINKDOWN_REASON_BAD_HEAD_DIST 17 +#define STL_LINKDOWN_REASON_BAD_TAIL_DIST 18 +#define STL_LINKDOWN_REASON_BAD_CTRL_DIST 19 +#define STL_LINKDOWN_REASON_BAD_CREDIT_ACK 20 +#define STL_LINKDOWN_REASON_UNSUPPORTED_VL_MARKER 21 +#define STL_LINKDOWN_REASON_BAD_PREEMPT 22 +#define STL_LINKDOWN_REASON_BAD_CONTROL_FLIT 23 +#define STL_LINKDOWN_REASON_EXCEED_MULTICAST_LIMIT 24 +#define STL_LINKDOWN_REASON_RCV_ERROR_24 25 +#define STL_LINKDOWN_REASON_RCV_ERROR_25 26 +#define STL_LINKDOWN_REASON_RCV_ERROR_26 27 +#define STL_LINKDOWN_REASON_RCV_ERROR_27 28 +#define STL_LINKDOWN_REASON_RCV_ERROR_28 29 +#define STL_LINKDOWN_REASON_RCV_ERROR_29 30 +#define STL_LINKDOWN_REASON_RCV_ERROR_30 31 +#define STL_LINKDOWN_REASON_EXCESSIVE_BUFFER_OVERRUN 32 +/* the next two correspond to locally initiated intentional link down */ +#define STL_LINKDOWN_REASON_UNKNOWN 33 + /* code 33 is used for locally initiated link downs which don't */ + /* match any of these reason code */ +/* reserved 34 */ +#define STL_LINKDOWN_REASON_REBOOT 35 /* reboot or device reset */ +#define STL_LINKDOWN_REASON_NEIGHBOR_UNKNOWN 36 + /* This indicates the link down was not locally initiated */ + /* but no LinkGoingDown idle flit was received */ + /* See Section 6.3.11.1.2, "PlannedDownInform Substate" */ +/* reserved 37 - 38 */ +/*These correspond to locally initiated intentional link down */ +#define STL_LINKDOWN_REASON_FM_BOUNCE 39 /* FM initiated bounce */ + /* by transitioning from linkup to Polling */ +#define STL_LINKDOWN_REASON_SPEED_POLICY 40 /* link outside speed policy */ +#define STL_LINKDOWN_REASON_WIDTH_POLICY 41 /* link downgrade outside */ + /* LinkWidthDowngrade.Enabled policy */ +/* reserved 42-47 */ +/* these correspond to locally initiated link down via transition to Offline or Disabled */ +/* See Section 6.6.2, “Offline/Disabled Reasons”, Table 6-38*/ +/* All values in that section are provided for here, although in practice a few */ +/* such as 49 (Disconnected) represent links which can never reach LinkUp and hence */ +/* could not have a transition to LinkDown */ +/* reserved 48 */ +#define STL_LINKDOWN_REASON_DISCONNECTED 49 +#define STL_LINKDOWN_REASON_LOCAL_MEDIA_NOT_INSTALLED 50 +#define STL_LINKDOWN_REASON_NOT_INSTALLED 51 +#define STL_LINKDOWN_REASON_CHASSIS_CONFIG 52 +/* reserved 53 */ +#define STL_LINKDOWN_REASON_END_TO_END_NOT_INSTALLED 54 +/* reserved 55 */ +#define STL_LINKDOWN_REASON_POWER_POLICY 56 +#define STL_LINKDOWN_REASON_LINKSPEED_POLICY 57 +#define STL_LINKDOWN_REASON_LINKWIDTH_POLICY 58 +/* reserved 59 */ +#define STL_LINKDOWN_REASON_SWITCH_MGMT 60 +#define STL_LINKDOWN_REASON_SMA_DISABLED 61 +/* reserved 62 */ +#define STL_LINKDOWN_REASON_TRANSIENT 63 +/* reserved 64-255 */ + + +/* STL PORT TYPE values imply cable info availabilty and format */ +#define STL_PORT_TYPE_UNKNOWN 0 +#define STL_PORT_TYPE_DISCONNECTED 1 /* the port is not currently usable � CableInfo not available */ +#define STL_PORT_TYPE_FIXED 2 /* A fixed backplane port in a director class switch � All STL ASICS */ +#define STL_PORT_TYPE_VARIABLE 3 /* A backplane port in a blade system � possibly mixed configuration */ +#define STL_PORT_TYPE_STANDARD 4 /* implies a SFF-8636 defined format for CableInfo (QSFP) */ +#define STL_PORT_TYPE_SI_PHOTONICS 5 /* A silicon photonics module � + * implies TBD defined format for CableInfo as defined by Intel SFO group */ +/* 6 - 15 Reserved */ + +/* STL NEIGHBOR NODE TYPE indicate whether the neighbor is an HFI or + * a switch. */ +#define STL_NEIGH_NODE_TYPE_HFI 0 /* Gen 1 HFIs are considered "untrusted" */ +#define STL_NEIGH_NODE_TYPE_SW 1 /* Gen 1 Switches are considered "trusted" */ +/* Values 2 & 3 are reserved in Gen1. */ + +typedef union { + uint32 AsReg32; + struct { IB_BITFIELD8( uint32, /* Port states */ + Reserved: 9, + LEDEnabled: 1, /* RO/HS-- Set to 1 if the port LED is active. */ + IsSMConfigurationStarted: 1, /* RO/HS-E - POD/LUD: 0 */ + NeighborNormal: 1, /* RO/HS-- */ + /* POD/LUD: 0 */ + OfflineDisabledReason: 4, /* RO/HS-E Reason for Offline (see STL_OFFDIS_REASON_XXX) */ + Reserved2: 8, + PortPhysicalState: 4, /* RW/HS-E Port Physical State (see STL_PORT_PHYS_XXX) */ + PortState: 4 ) /* RW/HS-E Port State (see STL_PORT_XXX) */ + } s; +} STL_PORT_STATES; + +typedef union { + uint8 AsReg8; + struct { IB_BITFIELD2( uint8, /* RW/HS-E Neighbor MTU values per VL */ + /* LUD: 2048 MTU for STL VL15 */ + VL0_to_MTU: 4, + VL1_to_MTU: 4 ) + } s; +} STL_VL_TO_MTU; + +#define STL_VL0_VL31 6 + +/* STL Link speed, continued from IB_LINK_SPEED and indicated as follows: + * values are additive for Supported and Enabled fields + */ + +#define STL_LINK_SPEED_NOP 0 /* LinkSpeed.Enabled: no change */ + /* LinkSpeeed.Active: link is LinkDown*/ +#define STL_LINK_SPEED_12_5G 0x0001 /* 12.5 Gbps */ +#define STL_LINK_SPEED_25G 0x0002 /* 25.78125? Gbps (EDR) */ + + +/* STL Link width, continued from IB_LINK_WIDTH and indicated as follows: + * values are additive for Supported and Enabled fields + */ + + +#define STL_LINK_WIDTH_NOP 0 /* LinkWidth.Enabled: no changeon set (nop) */ + /* LinkWidth.Active: link is LinkDown*/ + /* LinkWidthDowngrade.Supported: unsupported */ + /* LinkWidthDowngrade.Enable: disabled */ + /* LinkWidthDowngrade.TxActive: link is LinkDown*/ + /* LinkWidthDowngrade.RxActive: link is LinkDown */ +#define STL_LINK_WIDTH_1X 0x0001 +#define STL_LINK_WIDTH_2X 0x0002 +#define STL_LINK_WIDTH_3X 0x0004 +#define STL_LINK_WIDTH_4X 0x0008 + +/* STL Port link mode, indicated as follows: + * values are additive for Supported and Enabled fields + */ +#define STL_PORT_LINK_MODE_NOP 0 /* No change */ +/* reserved 1 */ +/* reserved 2 */ +#define STL_PORT_LINK_MODE_STL 4 /* Port mode is STL */ + +/* STL Port link formats, indicated as follows: + * values are additive for Supported and Enabled fields + */ +#define STL_PORT_PACKET_FORMAT_NOP 0 /* No change */ +#define STL_PORT_PACKET_FORMAT_8B 1 /* Format 8B */ +#define STL_PORT_PACKET_FORMAT_9B 2 /* Format 9B */ +#define STL_PORT_PACKET_FORMAT_10B 4 /* Format 10B */ +#define STL_PORT_PACKET_FORMAT_16B 8 /* Format 16B */ + +/* STL Port LTP CRC mode, indicated as follows: + * values are additive for Supported and Enabled fields + */ +#define STL_PORT_LTP_CRC_MODE_NONE 0 /* No change */ +#define STL_PORT_LTP_CRC_MODE_14 1 /* 14-bit LTP CRC mode (optional) */ +#define STL_PORT_LTP_CRC_MODE_16 2 /* 16-bit LTP CRC mode */ +#define STL_PORT_LTP_CRC_MODE_48 4 /* 48-bit LTP CRC mode (optional) */ +#define STL_PORT_LTP_CRC_MODE_12_16_PER_LANE 8 /* 12/16-bit per lane LTP CRC mode */ + +/* STL Port Flit distance mode, indicated as follows: + * values are additive for Supported and Enabled fields + */ +#define STL_PORT_FLIT_DISTANCE_MODE_NONE 0 /* No change */ +#define STL_PORT_FLIT_DISTANCE_MODE_1 1 /* STL1 mode */ +#define STL_PORT_FLIT_DISTANCE_MODE_2 2 /* STL2 mode */ + +/* STL VL Scheduling mode, indicated as follows: + */ +#define STL_VL_SCHED_MODE_VLARB 0 /* Gen1 VLARB */ +#define STL_VL_SCHED_MODE_AUTOMATIC 2 /* hardcoded, not configurable */ + +/* STL Port Flit preemption limits of unlimited */ +#define STL_PORT_PREEMPTION_LIMIT_NONE 255 /* Unlimited */ + +#define BYTES_PER_LTP 128 + +/* NOTE - first-pass ordering of PortInfo members: + * 1 RW members before RO members; + * 2 Roughly prioritize RW and RO sections; + * 3 No separation of RO and RW members within sub-structures. + * + * Attribute Modifier as NNNN NNNN 0000 0000 0000 000A PPPP PPPP + * + * N = number of ports + * A = 1 - All ports starting at P + * P = port number + */ +typedef struct { + STL_LID LID; /* RW/HSPE H-PE: base LID of this node */ + /* POD: 0 */ + /* -S--: base LID of neighbor node */ + /* POD/LUD: 0 */ + + uint32 FlowControlMask; /* RW/-S-- Flow control mask (1 bit per VL) */ + /* POD/LUD: flow control enabled all VLs except VL15 */ + + struct { + uint8 PreemptCap; /* RO/HS-E size of Preempting VL Arbitration table */ + /* only used when VLSchedulingConfig */ + /* is VL_SCHED_MODE_VLARB, otherwise reserved */ + + struct { IB_BITFIELD2( uint8, + Reserved: 3, + Cap: 5 ) /* RO/HS-E Virtual Lanes supported on this port */ + } s2; + + uint16 HighLimit; /* RW/HS-E Limit of high priority component of */ + /* VL Arbitration table */ + /* only used when VLSchedulingConfig */ + /* is VL_SCHED_MODE_VLARB, otherwise reserved */ + /* POD: 0 */ + uint16 PreemptingLimit; /* RW/HS-E Limit of preempt component of */ + /* VL Arbitration table */ + /* only used when VLSchedulingConfig */ + /* is VL_SCHED_MODE_VLARB, otherwise reserved */ + /* POD: 0 */ + + union { + uint8 ArbitrationHighCap; /* RO/HS-E VL Arbitration table cap */ + /* only used when VLSchedulingConfig */ + /* is VL_SCHED_MODE_VLARB, otherwise reserved */ + }; + + uint8 ArbitrationLowCap; /* RO/HS-E VL Arbitration table cap */ + /* only used when VLSchedulingConfig */ + /* is VL_SCHED_MODE_VLARB, otherwise reserved */ + } VL; + + STL_PORT_STATES PortStates; /* Port states */ + + STL_FIELDUNION2(PortPhysConfig,8, + Reserved:4, /* Reserved */ + PortType:4); /* RO/HS-- PORT_TYPE */ + /* Switch port 0 shall report Fixed */ + /* reserved when PortLinkMode.Active is not STL */ + + struct { IB_BITFIELD3( uint8, /* Multicast/Collectives masks */ + Reserved: 2, + CollectiveMask: 3, /* RW/H--- Num of additional upper 1s in */ + /* Collective address */ + /* POD: 1 */ + /* Reserved in Gen1 */ + MulticastMask: 3 ) /* RW/H--- Num of upper 1s in Multicast address */ + /* POD: 4 */ + } MultiCollectMask; + + struct { IB_BITFIELD3( uint8, + M_KeyProtectBits: 2, /* RW/H-PE see mgmt key usage */ + Reserved: 2, /* reserved, shall be zero */ + LMC: 4 ) /* RW/HSPE LID mask for multipath support */ + /* H---: POD: 0 */ + /* --PE: POD/LUD: 0 */ + /* -S--: LID mask for Neighbor node */ + /* POD/LUD: 0 */ + } s1; + + struct { IB_BITFIELD2( uint8, + Reserved: 3, + MasterSMSL: 5 ) /* RW/H-PE The adminstrative SL of the master */ + /* SM that is managing this port */ + } s2; + + struct { IB_BITFIELD5( uint8, + LinkInitReason: 4, /*RW/HSPE POD: 1, see STL_LINKINIT_REASON */ + PartitionEnforcementInbound: 1, /* RW/-S-- */ + /* LUD: 1 neighbor is HFI, 0 else */ + PartitionEnforcementOutbound: 1, /* RW/-S-- */ + /* LUD: 1 neighbor is HFI, 0 else */ + Reserved20: 1, + Reserved21: 1 ) + } s3; + + struct { IB_BITFIELD2( uint8, + Reserved: 3, + OperationalVL: 5 ) /* RW/HS-E Virtual Lanes operational this port */ + } s4; + + struct { /* STL Partial P_Keys */ + uint16 P_Key_8B; /* RW/HS-E Implicit 8B P_Key */ + uint16 P_Key_10B; /* RW/HS-E Partial upper 10B P_Key */ + /* (12 bits, lower 4 bits reserved) */ + } P_Keys; /* POD/LUD: 0 */ + + struct { + uint16 M_Key; /* RW/H-PE */ + uint16 P_Key; /* RW/H-PE */ + uint16 Q_Key; /* RW/H-PE */ + } Violations; /* POD: 0 */ + + STL_FIELDUNION2(SM_TrapQP, 32, + Reserved: 8, + QueuePair: 24 ); /* RW/HS-E SM Trap QP. POD/LUD: 0 */ + + STL_FIELDUNION2(SA_QP, 32, + Reserved: 8, + QueuePair: 24 ); /* RW/HS-E SA QP. POD/LUD: 1 */ + + uint8 NeighborPortNum; /* RO/HS-- Port number of neighbor node */ + + uint8 LinkDownReason; /* RW/HS-E Link Down Reason (see STL_LINKDOWN_REASON_XXX) */ + /* POD: 0 */ + + uint8 NeighborLinkDownReason;/* RW/HS-E Neighbor Link Down Reason - STL_LINKDOWN_REASON */ + /* POD: 0 */ + + struct { IB_BITFIELD3( uint8, + ClientReregister: 1, /* RW/H-PE POD/LUD: 0 */ + MulticastPKeyTrapSuppressionEnabled:2, /* RW/H-PE */ + Timeout: 5 ) /* RW/H-PE Timer value used for subnet timeout */ + } Subnet; + + struct { /* Link speed (see STL_LINK_SPEED_XXX) LinkBounce */ + uint16 Supported; /* RO/HS-E Supported link speed */ + uint16 Enabled; /* RW/HS-E Enabled link speed POD: = supported */ + uint16 Active; /* RO/HS-E Active link speed */ + } LinkSpeed; + + struct { /* 9(12) of each 16 bits used (see STL_LINK_WIDTH_XXX) */ + /* LinkBounce */ + uint16 Supported; /* RO/HS-E Supported link width */ + uint16 Enabled; /* RW/HS-E Enabled link width POD: = supported */ + uint16 Active; /* RO/HS-E link width negotiated by LNI*/ + } LinkWidth; + + struct { /* Downgrade of link on error (see STL_LINK_WIDTH_XXX) */ + uint16 Supported; /* RO/HS-E Supported downgraded link width */ + uint16 Enabled; /* RW/HS-E Enabled link width downgrade */ + /* POD/LUD: = supported */ + uint16 TxActive; /* RO/HS-E Currently active link width in tx dir */ + uint16 RxActive; /* RO/HS-- Currently active link width in rx dir */ + } LinkWidthDowngrade; + + STL_FIELDUNION4(PortLinkMode,16, /* STL/Eth Port Link Modes */ + /* (see STL_PORT_LINK_MODE_XXX) */ + Reserved: 1, + Supported: 5, /* RO/HS-E Supported port link mode */ + Enabled: 5, /* RW/HS-E Enabled port link mode POD: from FW INI */ + Active: 5 ); /* RO/HS-E Active port link mode */ + + STL_FIELDUNION4(PortLTPCRCMode, 16, /* STL Port LTP CRC Modes */ + /* (see STL_PORT_LTP_CRC_MODE_XXX) */ + Reserved: 4, + Supported: 4, /* RO/HS-E Supported port LTP mode */ + /* reserved when PortLinkMode.Active is not STL */ + Enabled: 4, /* RW/HS-E Enabled port LTP mode POD: from FW INI */ + /* reserved when PortLinkMode.Active is not STL */ + Active: 4 ); /* RO/HS-E Active port LTP mode */ + /* reserved when PortLinkMode.Active is not STL */ + + STL_FIELDUNION7(PortMode, 16, /* General port modes */ + Reserved: 9, + IsActiveOptimizeEnabled: 1, /* RW/HS-- Optimized Active handling */ + /* POD/LUD: 0 */ + IsPassThroughEnabled: 1, /* RW/-S-- Pass-Through LUD: 0 */ + IsVLMarkerEnabled: 1, /* RW/HS-- VL Marker LUD: 0 */ + Reserved2: 2, + Is16BTrapQueryEnabled: 1, /* RW/H-PE 16B Traps & SA/PA Queries (else 9B) */ + /* LUD: 0 */ + Reserved3: 1 ); /* RW/-S-- SMA Security Checking */ + /* LUD: 1 */ + + struct { /* Packet formats */ + /* (see STL_PORT_PACKET_FORMAT_XXX) */ + uint16 Supported; /* RO/HSPE Supported formats */ + uint16 Enabled; /* RW/HSPE Enabled formats */ + } PortPacketFormats; + + struct { /* Flit control LinkBounce */ + union { + uint16 AsReg16; + struct { IB_BITFIELD5( uint16, /* Flit interleaving */ + Reserved: 2, + DistanceSupported: 2, /* RO/HS-E Supported Flit distance mode */ + /* (see STL_PORT_FLIT_DISTANCE_MODE_XXX) */ + DistanceEnabled: 2, /* RW/HS-E Enabled Flit distance mode */ + /* (see STL_PORT_FLIT_DISTANCE_MODE_XXX) */ + /* LUD: mode1 */ + MaxNestLevelTxEnabled: 5, /* RW/HS-E Max nest level enabled Flit Tx */ + /* LUD: 0 */ + MaxNestLevelRxSupported: 5 ) /* RO/HS-E Max nest level supported Flit Rx */ + } s; + } Interleave; + + struct Preemption_t { /* Flit preemption */ + uint16 MinInitial; /* RW/HS-E Min bytes before preemption Head Flit */ + /* Range 8 to 10240 bytes */ + uint16 MinTail; /* RW/HS-E Min bytes before preemption Tail Flit */ + /* Range 8 to 10240 bytes */ + uint8 LargePktLimit; /* RW/HS-E Size of packet that can be preempted */ + /* Packet Size >= 512+(512*LargePktLimit) */ + /* Packet Size Range >=512 to >=8192 bytes */ + uint8 SmallPktLimit; /* RW/HS-E Size of packet that can preempt */ + /* Packet Size <= 32+(32*SmallPktLimit) */ + /* Packet Size Range <=32 to <=8192 bytes */ + /* MaxSmallPktLimit sets upper bound allowed */ + uint8 MaxSmallPktLimit;/* RO/HS-E Max value for SmallPktLimit */ + /* Packet Size <= 32+(32*MaxSmallPktLimit) */ + /* Packet Size Range <=32 to <=8192 bytes */ + uint8 PreemptionLimit;/* RW/HS-E Num bytes of preemption */ + /* limit = (256*PreemptionLimit) */ + /* Limit range 0 to 65024, 0xff=unlimited */ + } Preemption; + + } FlitControl; + + STL_LID MaxLID; /* RW/H---: POD: 0xBFFF */ + + union _PortErrorAction { + uint32 AsReg32; + struct { IB_BITFIELD25( uint32, /* RW/HS-E Port Error Action Mask */ + /* POD: 0 */ + ExcessiveBufferOverrun: 1, + Reserved: 7, + FmConfigErrorExceedMulticastLimit: 1, + FmConfigErrorBadControlFlit: 1, + FmConfigErrorBadPreempt: 1, + FmConfigErrorUnsupportedVLMarker: 1, + FmConfigErrorBadCrdtAck: 1, + FmConfigErrorBadCtrlDist: 1, + FmConfigErrorBadTailDist: 1, + FmConfigErrorBadHeadDist: 1, + Reserved2: 2, + PortRcvErrorBadVLMarker: 1, + PortRcvErrorPreemptVL15: 1, + PortRcvErrorPreemptError: 1, + Reserved3: 1, + PortRcvErrorBadMidTail: 1, + PortRcvErrorReserved: 1, + PortRcvErrorBadSC: 1, + PortRcvErrorBadL2: 1, + PortRcvErrorBadDLID: 1, + PortRcvErrorBadSLID: 1, + PortRcvErrorPktLenTooShort: 1, + PortRcvErrorPktLenTooLong: 1, + PortRcvErrorBadPktLen: 1, + Reserved4: 1 ) + } s; + } PortErrorAction; + + struct { /* Pass through mode control */ + uint8 EgressPort; /* RW/-S-- Egress port: 0-disable pass through */ + /* LUD: 0 */ + + IB_BITFIELD2( uint8, + Reserved: 7, + DRControl: 1 ) /* RW/-S-- DR: 0-normal process, 1-repeat on egress port */ + /* LUD: 0 */ + + } PassThroughControl; + + uint16 M_KeyLeasePeriod; /* RW/H-PE LUD: 0 */ + + STL_FIELDUNION5(BufferUnits, 32, /* VL bfr & ack unit sizes (bytes) */ + Reserved: 9, + VL15Init: 12, /* RO/HS-E Initial VL15 units (N) */ + VL15CreditRate: 5, /* RW/HS-E VL15 Credit rate (32*2^N) */ + /* LUD: if neighbor is STL HFI: 18, otherwise 0 */ + CreditAck: 3, /* RO/HS-E Credit ack unit (BufferAlloc*2^N) */ + BufferAlloc: 3 ); /* RO/HS-E Buffer alloc unit (8*2^N) */ + + uint16 Reserved14; + uint8 BundleNextPort; /* RO/HS-- next logical port in a bundled connector */ + uint8 BundleLane; /* RO/HS-- first lane in connector associated with this port */ + + STL_LID MasterSMLID; /* RW/H-PE The base LID of the master SM that is */ + /* managing this port */ + /* POD/LUD: 0 */ + + uint64 M_Key; /* RW/H-PE The 8-byte management key */ + /* POD/LUD: 0 */ + + uint64 SubnetPrefix; /* RW/H-PE Subnet prefix for this port */ + /* Set to default value if no */ + /* other subnet interaction */ + /* POD: 0xf8000000:00000000 */ + + STL_VL_TO_MTU NeighborMTU[STL_MAX_VLS / 2]; /* RW/HS-E Neighbor MTU values per VL */ + /* VL15 LUD: 2048 STL mode */ + + struct XmitQ_s { IB_BITFIELD2( uint8, /* Transmitter Queueing Controls */ + /* per VL */ + VLStallCount: 3, /* RW/-S-- Applies to switches only */ + /* LUD: 7 */ + HOQLife: 5 ) /* RW/-S-- Applies to routers & switches only */ + /* LUD: infinite */ + } XmitQ[STL_MAX_VLS]; + +/* END OF RW SECTION */ + +/* BEGINNING OF RO SECTION */ + STL_IPV6_IP_ADDR IPAddrIPV6; /* RO/H-PE IP Address - IPV6 */ + + STL_IPV4_IP_ADDR IPAddrIPV4; /* RO/H-PE IP Address - IPV4 */ + + uint32 Reserved26; + uint32 Reserved27; + + uint32 Reserved28; + + uint64 NeighborNodeGUID; /* RO/-S-E GUID of neighbor connected to this port */ + + STL_CAPABILITY_MASK CapabilityMask; /* RO/H-PE Capability Mask */ + + uint16 Reserved20; + + STL_CAPABILITY_MASK3 CapabilityMask3; /* RO/H-PE Capability Mask 3 */ + + uint32 Reserved23; + + uint16 OverallBufferSpace; /* RO/HS-E Overall dedicated + shared space */ + + struct { /* most significant 8 bits of Replay depths */ + uint8 BufferDepthH; /* RO/HS-- Replay buffer depth MSB */ + /* reserved when PortLinkMode.Active is not STL */ + uint8 WireDepthH; /* RO/HS-- Replay wire depth MSB */ + /* reserved when PortLinkMode.Active is not STL */ + } ReplayDepthH; + + STL_FIELDUNION3(DiagCode, 16, /* RO/H-PE Diagnostic code, Refer Node Diagnostics */ + UniversalDiagCode: 4, + VendorDiagCode: 11, + Chain: 1 ); + + struct { /* least significant 8 bits of Replay depths */ + uint8 BufferDepth; /* RO/HS-E Replay buffer depth LSB */ + /* reserved when PortLinkMode.Active is not STL */ + uint8 WireDepth; /* RO/HS-E Replay wire depth LSB */ + /* reserved when PortLinkMode.Active is not STL */ + } ReplayDepth; + + struct { IB_BITFIELD4( uint8, /* RO/HS-E Port modes based on neighbor */ + Reserved: 4, + MgmtAllowed: 1, /* RO/H--- neighbor allows this node to be mgmt */ + /* Switch: mgmt is allowed for neighbor */ + /* EP0: mgmt is allowed for port */ + NeighborFWAuthenBypass: 1, /* RO/-S-E 0=Authenticated, 1=Not Authenticated */ + NeighborNodeType: 2 ) /* RO/-S-E 0=HFI (not trusted), 1=Switch (trusted) */ + } PortNeighborMode; + + struct { IB_BITFIELD2( uint8, + Reserved20: 4, + Cap: 4 ) /* RO/HS-E Max MTU supported by this port */ + } MTU; + + struct { IB_BITFIELD2( uint8, + Reserved: 3, + TimeValue: 5 ) /* RO/H-PE */ + } Resp; + + uint8 LocalPortNum; /* RO/HSPE The link port number this SMP came on in */ + + uint8 Reserved25; + uint8 Reserved24; + +} PACK_SUFFIX STL_PORT_INFO; + + +/* + * PartitionTable + * + * Attribute Modifier as: NNNN NNNN PPPP PPPP 0000 0BBB BBBB BBBB + * N: Number of blocks + * P: Port number (0 - management port, switches only; + * for HFIs P is ignored and the attribute is + * applicable only to the port that receives the packet) + * B: Block number + * + * The (max) PartitionTable is 2**16 entries (P_Keys) long, 16 bits wide. + * Each PartitionTable block is 32 entries long, 16 bits wide. The Partition + * Table is a linear array of blocks[2**11]. + */ + +#define NUM_PKEY_ELEMENTS_BLOCK (32) /* Num elements per block; currently same as IB */ +#define MAX_PKEY_BLOCK_NUM 0x7FF +#define PKEY_BLOCK_NUM_MASK 0x7FF +#define STL_DEFAULT_PKEY 0x7FFF +#define STL_DEFAULT_APP_PKEY 0x8001 +#define STL_DEFAULT_FM_PKEY 0xFFFF +#define STL_DEFAULT_CLIENT_PKEY 0x7FFF +#define STL_DEFAULT_APP_PKEY_IDX 0 +#define STL_DEFAULT_CLIENT_PKEY_IDX 1 +#define STL_DEFAULT_FM_PKEY_IDX 2 +#define STL_MIN_PKEY_COUNT 3 + +typedef union { + uint16 AsReg16; + struct { IB_BITFIELD2( uint16, + MembershipType: 1, /* 0=Limited, 1=Full */ + P_KeyBase: 15 ) /* Base value of the P_Key that */ + /* the endnode will use to check */ + /* against incoming packets */ + } s; + +} PACK_SUFFIX STL_PKEY_ELEMENT; + +#define STL_NUM_PKEY_BLOCKS_PER_DRSMP ((uint8_t)(STL_MAX_PAYLOAD_SMP_DR / sizeof(STL_PARTITION_TABLE))) +#define STL_NUM_PKEY_BLOCKS_PER_LID_SMP ((uint8_t)(STL_MAX_PAYLOAD_SMP_LR / sizeof(STL_PARTITION_TABLE))) + +typedef struct { + + STL_PKEY_ELEMENT PartitionTableBlock[NUM_PKEY_ELEMENTS_BLOCK]; /* RW List of P_Key Block elements */ + +} PACK_SUFFIX STL_PARTITION_TABLE; + + +/* + * SL_TO_SC Mapping table + * + * Attribute Modifier as: 0 (not used) + * + * This Attribute is used only for HFIs and switch port 0 + * + * Each block contains 32 bytes of SL->SC data, 1 byte per SL. + */ +typedef struct { + STL_SC SLSCMap[STL_MAX_SLS]; /* RW/HSPE */ + /* H---: POD: SLn_to_SCn (1-to-1) */ + +} PACK_SUFFIX STL_SLSCMAP; + +/* + * SC_TO_SC Mapping table + * + * Attribute Modifier as: NNNN NNNN 0000 00AB IIII IIII EEEE EEEE + * N: Number of blocks (egress ports (B=0), + * but if B=1 then ingress ports) + * A=1: All ingress ports starting at I (Set only; excludes port 0) + * B=1: All egress ports starting at E (Set only; excludes port 0) + * I: Ingress port number (0 - reserved, switches only) + * E: Egress port number (0 - reserved, switches only) + * + * This attribute is not applicable to HFIs. + * + * Each block contains 32 bytes of SC->SC data, 1 byte per SC. + */ +typedef struct { + STL_SC SCSCMap[STL_MAX_SCS]; /* RW/HSPE */ + /* -SPE: POD: SCn_to_SCn (1-to-1) */ + +} PACK_SUFFIX STL_SCSCMAP; + +#define STL_NUM_SCSC_BLOCKS_PER_DRSMP ((uint8_t)(STL_MAX_PAYLOAD_SMP_DR / sizeof(STL_SCSCMAP))) +#define STL_NUM_SCSC_BLOCKS_PER_LID_SMP ((uint8_t)(STL_MAX_PAYLOAD_SMP_LR / sizeof(STL_SCSCMAP))) + +/* + * SC_TO_SC MultiSet + * + * Attribute Modifier as: NNNN NNNN 0000 0000 0000 0000 0000 0000 + * N: Number of Multi-Set Blocks + * + * This attribute is not applicable to HFIs. + * + * Each block contains 32 bytes of SC->SC data, 1 byte per SC and ingress/egress port masks + */ + +typedef struct { + STL_PORTMASK IngressPortMask[STL_MAX_PORTMASK]; + STL_PORTMASK EgressPortMask[STL_MAX_PORTMASK]; + STL_SCSCMAP SCSCMap; /* RW/HSPE */ + /* -SPE: POD: SCn_to_SCn (1-to-1) */ +} PACK_SUFFIX STL_SCSC_MULTISET; + + +#define STL_NUM_SCSC_MULTI_BLOCKS_PER_DRSMP ((uint8_t)(STL_MAX_PAYLOAD_SMP_DR / sizeof(STL_SCSC_MULTISET))) +#define STL_NUM_SCSC_MULTI_BLOCKS_PER_LRSMP ((uint8_t)(STL_MAX_PAYLOAD_SMP_LR / sizeof(STL_SCSC_MULTISET))) + + +/* + * SC_TO_SL Mapping table + * + * Attribute Modifier as: 0 (not used) + * + * This Attribute is used only for HFIs and switch port 0 + * + * Each block contains 32 bytes of SC->SL data, 1 byte per SC. + */ +typedef struct { /* RW POD: SCn_to_SLn (1-to-1) */ + STL_SL SCSLMap[STL_MAX_SCS]; + +} PACK_SUFFIX STL_SCSLMAP; + +/* + * SC_TO_VL Mapping table + * + * Attribute Modifier as: NNNN NNNN 0000 0000 000Y 000A PPPP PPPP + * N: Number of blocks (ports) + * Y=1: Async update (Set of SC-to-VLt only with link state Armed or Active) + * A=1: All ports starting at P (Set only) + * P: Port number (0 - management port, switches only; + * for HFIs P is ignored and the attribute is + * applicable only to the port that receives the packet) + * + * Each block contains 32 bytes of SC->VL data, 1 byte per SC. + * + * NOTE: this attribute applies for all SC-to-VL tables (SC-to-VLr, SC-to-VLt, + * SC-to-VLnt); Port is ingress port or egress port as applicable. + */ +typedef struct { + STL_VL SCVLMap[STL_MAX_SCS]; /* RW/HSPE POD: SCn_to_VLn (1-to-1) */ + +} PACK_SUFFIX STL_SCVLMAP; + +#define STL_NUM_SCVL_BLOCKS_PER_DRSMP ((uint8_t)(STL_MAX_PAYLOAD_SMP_DR / sizeof(STL_SCVLMAP))) +#define STL_NUM_SCVL_BLOCKS_PER_LID_SMP ((uint8_t)(STL_MAX_PAYLOAD_SMP_LR / sizeof(STL_SCVLMAP))) + + +/* + * VL Arbitration Table (aka VL Arbitration Table 2) + * + * Attribute Modifier as: NNNN NNNN SSSS SSSS 0000 000A PPPP PPPP + * N: Number of ports + * S: Section of Table as: + * 0: Arbitration Low Elements + * 1: Arbitration High Elements + * 2: Preemption Elements + * 3: Preemption Matrix + * 4-255: Reserved + * A=1: All ports starting at P (Set only) + * P: Port number (0 - management port, switches only; + * for HFIs P is ignored and the attribute is + * applicable only to the port that receives the packet) + */ + +#define STL_MAX_LOW_CAP 128 /* Also applies to High but not Preempt */ +#define STL_MAX_PREEMPT_CAP 32 /* MAX Preempt table size is 32 */ +#define STL_VLARB_LOW_ELEMENTS 0 +#define STL_VLARB_HIGH_ELEMENTS 1 +#define STL_VLARB_PREEMPT_ELEMENTS 2 +#define STL_VLARB_PREEMPT_MATRIX 3 +#define STL_VLARB_NUM_SECTIONS 4 + +typedef struct { + struct { IB_BITFIELD2( uint8, + Reserved: 3, + VL: 5 ) /* RW */ + } s; + + uint8 Weight; /* RW */ + +} PACK_SUFFIX STL_VLARB_TABLE_ELEMENT; + +#define VLARB_TABLE_LENGTH 128 +typedef union { + STL_VLARB_TABLE_ELEMENT Elements[VLARB_TABLE_LENGTH]; /* RW */ + uint32 Matrix[STL_MAX_VLS]; /* RW */ + /* POD: 0 */ + +} PACK_SUFFIX STL_VLARB_TABLE; + +#define STL_NUM_VLARB_PORTS_PER_DRSMP ((uint8_t)(STL_MAX_PAYLOAD_SMP_DR / sizeof(STL_VLARB_TABLE))) +#define STL_NUM_VLARB_PORTS_PER_LID_SMP ((uint8_t)(STL_MAX_PAYLOAD_SMP_LR / sizeof(STL_VLARB_TABLE))) + + +/* + * Linear Forwarding Table (LFT) + * + * Attribute Modifier as: NNNN NNNN 0000 0ABB BBBB BBBB BBBB BBBB + * N: Number of blocks + * A=1: All blocks starting at B (Set only) + * B: Block number + * + * The (max) LFT is 2**24 entries (LIDs) long (STL_LID_24), 8 bits wide. + * Each LFT block is 64 entries long, 8 bits wide. The LFT is a + * linear array of blocks[2**18]. + */ + +#define MAX_LFT_ELEMENTS_BLOCK (64) /* Max elements per block; currently same as IB */ +#define MAX_LFT_BLOCK_NUM 0x3FFFF + +#define STL_NUM_LFT_BLOCKS_PER_DRSMP ((uint8_t)(STL_MAX_PAYLOAD_SMP_DR/MAX_LFT_ELEMENTS_BLOCK)) +typedef struct { + PORT LftBlock[MAX_LFT_ELEMENTS_BLOCK]; + +} PACK_SUFFIX STL_LINEAR_FORWARDING_TABLE; + + + +/* + * Multicast Forwarding Table (MFT) + * + * Attribute Modifier as: NNNN NNNN PP0A BBBB BBBB BBBB BBBB BBBB + * N: Number of blocks + * P: Position number + * A=1: All blocks starting at B (Set only) + * B: Block number + * + * The (max) MFT is 2**23 entries (LIDs) long (STL_LID_24 / 2), 256 bits wide. + * Each MFT block is 8 entries long, 64 bits wide. The MFT is a + * 2-dimensional array of blocks[2**20][4]. + */ + + +#define STL_NUM_MFT_ELEMENTS_BLOCK 8 /* Num elements per block */ +#define STL_NUM_MFT_POSITIONS_MASK 4 /* Num positions per 256-bit port mask */ +#define STL_MAX_MFT_BLOCK_NUM 0xFFFFF +#define STL_PORT_MASK_WIDTH 64 /* Width of STL_PORTMASK in bits */ +#define STL_MAX_PORTS 255 + +typedef struct { + STL_PORTMASK MftBlock[STL_NUM_MFT_ELEMENTS_BLOCK]; + +} PACK_SUFFIX STL_MULTICAST_FORWARDING_TABLE; + +#define STL_NUM_MFT_BLOCKS_PER_DRSMP ((uint8_t)(STL_MAX_PAYLOAD_SMP_DR/sizeof(STL_MULTICAST_FORWARDING_TABLE))) + +/* + * SMInfo + * + * Attribute Modifier as: 0 (not used) + */ +typedef struct { + uint64 PortGUID; /* RO This SM's perception of the PortGUID */ + /* of the master SM */ + uint64 SM_Key; /* RO Key of this SM. This is shown as 0 unless */ + /* the requesting SM is proven to be the */ + /* master, or the requester is otherwise */ + /* authenticated */ + uint32 ActCount; /* RO Counter that increments each time the SM */ + /* issues a SMP or performs other management */ + /* activities. Used as a 'heartbeat' indicator */ + /* by standby SMs */ + uint32 ElapsedTime; /* RO Time (in seconds): time Master SM has been */ + /* Master, or time since Standby SM was last */ + /* updated by Master */ + union { + uint16 AsReg16; + struct { IB_BITFIELD4( uint16, + Priority: 4, /* RO Administratively assigned priority for this */ + /* SM. Can be reset by master SM */ + ElevatedPriority: 4, /* RO This SM's elevated priority */ + InitialPriority: 4, /* RO This SM's initial priority */ + SMStateCurrent: 4 ) /* RO This SM's current state (see SM_STATE) */ + } s; + } u; + +} PACK_SUFFIX STL_SM_INFO; + + +/* + * LEDInfo + * + * Attribute Modifier as: NNNN NNNN 0000 0000 0000 000A PPPP PPPP + * N: Number of ports + * A=1: All ports starting at P (Set only) + * P: Port number (must be 0 for HFI) + */ + +typedef struct { + union { + uint32 AsReg32; + struct { IB_BITFIELD2( uint32, + LedMask: 1, /* RW POD: 0 */ + Reserved: 31 ); + } s; + } u; + uint32 Reserved2; + +} PACK_SUFFIX STL_LED_INFO; + +/* + * CableInfo + * + * Attribute Modifier as: 0AAA AAAA AAAA ALLL LLL0 0000 PPPP PPPP + * A: Starting address of cable data + * L: Length (bytes) of cable data - 1 + * (L+1 bytes of data read) + * P: Port number (0 - management port, switches only; + * for HFIs P is ignored and the attribute is + * applicable only to the port that receives the packet) + * + * NOTE: Cable Info is mapped onto a linear 4096-byte address space (0-4095). + * Cable Info can only be read within 128-byte pages; that is, a single + * read cannot cross a 128-byte (page) boundary. + */ +#define STL_CABLE_INFO_DATA_SIZE 64 +typedef struct { + uint8 Data[STL_CABLE_INFO_DATA_SIZE]; /* RO Cable Info data (up to 64 bytes) */ +} PACK_SUFFIX STL_CABLE_INFO; + +#define STL_CABLE_INFO_PAGESZ 128 +#define STL_CABLE_INFO_MAXADDR 4095 +#define STL_CABLE_INFO_MAXLEN 63 + +// Note: Even though the entire cable memory is available to be read, +// tools only interpret one page of cable info memory which contains +// relevant data. + +// These are for PortType Standard, uses of these can assume START and END +// will be on and STL_CABLE_INFO_DATA_SIZE boundary +#define STL_CIB_STD_LOW_PAGE_ADDR 0 +#define STL_CIB_STD_HIGH_PAGE_ADDR 128 +#define STL_CIB_STD_END_ADDR (STL_CIB_STD_HIGH_PAGE_ADDR+STL_CABLE_INFO_PAGESZ-1) +#define STL_CIB_STD_LEN (STL_CABLE_INFO_PAGESZ) + + +#define STL_CIB_STD_MAX_STRING 16 // Max ASCII string in STD CableInfo field + +// Byte 0 and byte 128: identifier (SFF-8024) +#define STL_CIB_STD_QSFP 0xC // QSFP transceiver identifier value +#define STL_CIB_STD_QSFP_PLUS 0xD // QSFP+ transceiver identifier value +#define STL_CIB_STD_QSFP_28 0x11 // QSFP28 transceiver identifier value +#define STL_CIB_STD_QSFP_DD 0x18 // QSFP-DD transceiver identifier value + +// Byte 129: pwr_class_low, pwr_class_high +#define STL_CIB_STD_PWRLOW_1_5 0 // Pwr class low class 1 (1.5 W) +#define STL_CIB_STD_PWRLOW_2_0 1 // Pwr class low class 2 (2.0 W) +#define STL_CIB_STD_PWRLOW_2_5 2 // Pwr class low class 3 (2.5 W) +#define STL_CIB_STD_PWRLOW_3_5 3 // Pwr class low class 4 (3.5 W) +#define STL_CIB_STD_PWRHIGH_LEGACY 0 // Pwr class high legacy settings +#define STL_CIB_STD_PWRHIGH_4_0 1 // Pwr class high class 5 (4.0 W) +#define STL_CIB_STD_PWRHIGH_4_5 2 // Pwr class high class 6 (4.5 W) +#define STL_CIB_STD_PWRHIGH_5_0 3 // Pwr class high class 7 (5.0 W) + +// Byte 130: connector +#define STL_CIB_STD_CONNECTOR_MPO1x12 0x0C // Connector type is MPO 1x12 +#define STL_CIB_STD_CONNECTOR_MPO2x16 0x0D // Connector type is MPO 2x16 +#define STL_CIB_STD_CONNECTOR_NO_SEP 0x23 // Connector type is non-separable +#define STL_CIB_STD_CONNECTOR_MXC2x16 0x24 // Connector type is MXC 2x16 + +// Byte 140: bit_rate_low +#define STL_CIB_STD_RATELOW_NONE 0 // Nominal bit rate low not specified +#define STL_CIB_STD_RATELOW_EXCEED 0xFF // Nominal bit rate low > 25.4 Gbps + +// Byte 147: dev_tech.xmit_tech +#define STL_CIB_STD_TXTECH_850_VCSEL 0x0 // Tx tech 850 nm VCSEL +#define STL_CIB_STD_TXTECH_1310_VCSEL 0x1 // Tx tech 1310 nm VCSEL +#define STL_CIB_STD_TXTECH_1550_VCSEL 0x2 // Tx tech 1550 nm VCSEL +#define STL_CIB_STD_TXTECH_1310_FP 0x3 // Tx tech 1310 nm FP +#define STL_CIB_STD_TXTECH_1310_DFB 0x4 // Tx tech 1310 nm DFB +#define STL_CIB_STD_TXTECH_1550_DFB 0x5 // Tx tech 1550 nm DFB +#define STL_CIB_STD_TXTECH_1310_EML 0x6 // Tx tech 1310 nm EML +#define STL_CIB_STD_TXTECH_1550_EML 0x7 // Tx tech 1550 nm EML +#define STL_CIB_STD_TXTECH_OTHER 0x8 // Tx tech Other/Undefined +#define STL_CIB_STD_TXTECH_1490_DFB 0x9 // Tx tech 1490 nm DFB +#define STL_CIB_STD_TXTECH_CU_UNEQ 0xA // Tx tech Cu unequalized +#define STL_CIB_STD_TXTECH_CU_PASSIVEQ 0xB // Tx tech Cu passive equalized +#define STL_CIB_STD_TXTECH_CU_NFELIMACTEQ 0xC // Tx tech Cu near & far end limiting active equalizers +#define STL_CIB_STD_TXTECH_CU_FELIMACTEQ 0xD // Tx tech Cu far end limiting active equalizers +#define STL_CIB_STD_TXTECH_CU_NELIMACTEQ 0xE // Tx tech Cu near end limiting active equalizers +#define STL_CIB_STD_TXTECH_CU_LINACTEQ 0xF // Tx tech Cu linear active equalizers +#define STL_CIB_STD_TXTECH_MAX 0xF // Tx tech max value + +// Byte 250: opa_cert_cable +#define STL_CIB_STD_OPA_CERTIFIED_CABLE 0xAB // OPA certified cable + +// Byte 252: opa_cert_data_rate +#define STL_CIB_STD_OPACERTRATE_4X25G 0x02 // Certified data rate 4x25G + +// The following structure represents CableInfo page 0 Lower in memory. +// (based on Rev 2.9.2 SFF-8636 memory map) +typedef struct { + uint8 ident; // 0: Identifier + uint8 status[2]; // 1-2: Status + uint8 interruptFlags[19]; // 3-21: Interrupt Flags + uint16 temperature; // 22-23: Module temperature + uint8 moduleMonitors1[2]; // 24-25: Module level Monitors + uint16 voltage; // 26-27: Supply Voltage + uint8 moduleMonitors2[6]; // 28-33: Module level Monitors + uint16 rxOpticalPwr1; // 34-35: rx Optical Power 1 + uint16 rxOpticalPwr2; // 36-37: rx Optical Power 2 + uint16 rxOpticalPwr3; // 38-39: rx Optical Power 3 + uint16 rxOpticalPwr4; // 40-41: rx Optical Power 4 + uint8 laneMonitors1[8]; // 42-49: Lane Specific Monitors + uint16 txOpticalPwr1; // 50-51: tx Optical Power 1 + uint16 txOpticalPwr2; // 52-53: tx Optical Power 2 + uint16 txOpticalPwr3; // 54-55: tx Optical Power 3 + uint16 txOpticalPwr4; // 56-57: tx Optical Power 4 + uint8 laneMonitors2[24]; // 34-81: Lane Specific Monitors + uint8 reserved1[4]; // 82-85: Reserved + uint8 controlBytes[14]; // 86-99: Control bytes + uint8 laneInterruptMasks[3]; // 100-102: Lane specific Indicator Interrupt Masks + uint8 moduleInterruptMasks[4];// 103-106: Module level interrupt masks + uint8 moduleProperties1[4]; // 107-110: Module Properties + uint8 assignedPCI[2]; // 111-112: Module type advertising code + uint8 moduleProperties2[3]; // 113-115: Module Properties + uint8 secondaryExtSpecCode; // 116: Secondary Extended Spec Compliance Code + uint8 reserved2[2]; // 117-118: Reserved + uint8 passwordChangeArea[4]; // 119-122: Password Change Area + uint8 passwordEntryArea[4]; // 123-126: Password Entry Area + uint8 pageSelectType; // 127: Page Select Type +} PACK_SUFFIX STL_CABLE_INFO_LOW0_STD; + +// The following structure represents STD CableInfo page 0 upper in memory. +// (based on SFF-8636 Rev 2-5) +typedef struct { + // Page 0 upper, bytes 128-255 + uint8 ident; // 128: Identifier + union { + uint8 AsReg8; + struct { IB_BITFIELD5( uint8, // 129: Extended identifier: + pwr_class_low: 2, // Power class low + other: 2, // Other settings + tx_cdr_supp: 1, // Tx CDR support + rx_cdr_supp: 1, // Rx CDR support + pwr_class_high: 2) // Power class low + } s; + } ext_ident; + uint8 connector; // 130: Connector (see STL_CIB_CONNECTOR_TYPE_xxx) + uint8 spec_comp[8]; // 131-138: Elec/optical compliance code + uint8 encode; // 139: Encoding algorithm + uint8 bit_rate_low; // 140: Nominal bit rate low (units 100 Mbps) + // (0xFF see bit_rate_high) + uint8 ext_rate_comp; // 141: Extended rate compliance code + uint8 len_smf; // 142: Link len SMF fiber (units km) + uint8 len_om3; // 143: Link len OM3 fiber (units 2m) + uint8 len_om2; // 144: Link len OM2 fiber (units 1m) + uint8 len_om1; // 145: Link len OM1 fiber (units 1m) + uint8 len_om4; // 146: Link len OM4 copper or fiber (units 1m or 2m) + union { + uint8 AsReg8; + struct { IB_BITFIELD2( uint8, // 147: Device technology: + xmit_tech: 4, // Transmitter technology + other: 4) // Other settings + } s; + } dev_tech; + uint8 vendor_name[16]; // 148-163: Vendor name + uint8 ext_mod; // 164: Extended module code + uint8 vendor_oui[3]; // 165-167: Vendor OUI + uint8 vendor_pn[16]; // 168-183: Vendor part number + uint8 vendor_rev[2]; // 184-185: Vendor revision + uint8 wave_atten[2]; // 186-187: Wave length (value/20 nm) or + // copper attenuation (units dB) + uint8 wave_tol[2]; // 188-189: Wave length tolerance (value/200 nm) + uint8 max_case_temp; // 190: Max case temperature (degrees C) + uint8 cc_base; // 191: Checksum addresses 128-190 + uint8 link_codes; // 192: Link codes + union { + uint8 AsReg8; + struct { IB_BITFIELD5( uint8, // 193: RxTx options: equalization & emphasis + reserved: 4, // Reserved + tx_inpeq_autadp_cap: 1, // Tx inp equal auto-adaptive capable + tx_inpeq_fixpro_cap: 1, // Tx inp equal fixed-prog capable + rx_outemp_fixpro_cap: 1, // Rx outp emphasis fixed-prog capable + rx_outamp_fixpro_cap: 1) // Rx outp amplitude fixed-prog capable + } s; + } rxtx_opt_equemp; + union { + uint8 AsReg8; + struct { IB_BITFIELD8( uint8, // 194: RxTx options: CDR, LOL, squelch + tx_cdr_ctrl: 1, // Tx CDR On/Off ctrl implemented + rx_cdr_ctrl: 1, // Rx CDR On/Off ctrl implemented + tx_cdr_lol: 1, // Tx CDR loss of lock flag implemented + rx_cdr_lol: 1, // Rx CDR loss of lock flag implemented + rx_squel_dis: 1, // Rx squelch disable implemented + rx_out_dis: 1, // Rx output disable implemented + tx_squel_dis: 1, // Tx squelch disable implemented + tx_squel: 1) // Tx squelch implemented + } s; + } rxtx_opt_cdrsquel; + union { + uint8 AsReg8; + struct { IB_BITFIELD8( uint8, // 195: MemTx options: pages 1 & 2, implementations + page_2: 1, // Mem page 2 implemented + page_1: 1, // Mem page 1 implemented + rate_sel: 1, // Rate select implemented + tx_dis: 1, // Tx disable implemented + tx_fault: 1, // Tx fault signal implemented + tx_squel_omapav: 1, // Tx squelch OMA/Pave + tx_los: 1, // Tx loss of signal implemented + reserved: 1) // Reserved + } s; + } memtx_opt_pagesquel; + uint8 vendor_sn[16]; // 196-211: Vendor serial number + uint8 date_code[8]; // 212-219: Vendor manufacture date code + uint8 diag_mon_type; // 220: Diagnostic monitoring type + uint8 options_enh; // 221: Enhanced options + uint8 bit_rate_high; // 222: Nominal bit rate high (units 250 Mbps) + // (see also bit_rate_low) + uint8 cc_ext; // 223: Checksum addresses 192-222 + uint8 vendor[26]; // 224-249: Vendor specific + uint8 opa_cert_cable; // 250: OPA certified cable (see STL_CIB_CERTIFIED_CABLE) + uint8 vendor2; // 251: Vendor specific + uint8 opa_cert_data_rate; // 252: OPA certified data rate + uint8 vendor3[3]; // 253-255: Vendor specific +} PACK_SUFFIX STL_CABLE_INFO_STD; + +// The following structure represents CableInfo page 0 Lower(DD) in memory. +// (based on Rev 3.0 Memory map) +typedef struct { + uint8 ident; // 0: Identifier + uint8 versionID; // 1: version ID + uint8 interrupt[2]; // 2-3: Flat mem, Interrupt + uint8 bankLaneFlag[4]; // 4-7: Bank Lane Flag summary + uint8 moduleFlags[6]; // 8-13: Module Flags + uint16 temperature; // 14-15: Module temperature + uint16 voltage; // 16-17: Supply Voltage + uint8 moduleMonitors[8]; // 14-25: Module Monitors + uint8 moduleGlobalCtrls[5]; // 26-30: Module Global Monitors + uint8 moduleMasks[6]; // 31-36: Module masks + uint8 reserved1[27]; // 37-63: Reserved + uint8 custom[21]; // 64-84: custom + uint8 moduleType; // 85: Module type advertising code + uint8 moduleHostMediaInf[32]; // 86-117: Module Host-Media Interface Options + uint8 password[8]; // 118-125: Password Area + uint8 bankSelectType; // 126: Bank Select Type + uint8 pageSelectType; // 127: Page Select Type +} PACK_SUFFIX STL_CABLE_INFO_LOW0_DD; + +// The following structure represents CableInfo page 0 upper (DD) in memory. +// (based on Rev 0.61 frozen memory map) +typedef struct { + uint8 ident; // 128: Identifier + uint8 vendor_name[16]; // 129-144: Vendor name + uint8 vendor_oui[3]; // 145-147: Vendor OUI + uint8 vendor_pn[16]; // 148-163: Vendor part number + uint8 vendor_rev[2]; // 164-165: Vendor revision + uint8 vendor_sn[16]; // 166-181: Vendor serial number + uint8 date_code[8]; // 182-189: Vendor manufacture date code + uint8 reserved1[11]; // 190-200: Reserved + uint8 powerMax; // 201: Max power dissipation, in 0.25W increments + uint8 cableLengthEnc; // 202: Cable assembly length + uint8 connector; // 203: Connector (see STL_CIB_CONNECTOR_TYPE_xxx) + uint8 reserved2[8]; // 204-211: Reserved + uint8 cable_type; // 212: Cable type (optics/passive/active Cu) + uint8 reserved3[43]; // 213-255: Reserved +} PACK_SUFFIX STL_CABLE_INFO_UP0_DD; + +/* + * Aggregate + * + * Attribute Modifier as: 0000 0000 0000 0000 0000 0000 NNNN NNNN + * N: Number of aggregated attributes + * (1-MAX_AGGREGATE_ATTRIBUTES) + * + * A wrapper attribute, containing a sequence of AttributeID/AttributeModifier/Payload + * segments. Each segment begins on an 8-byte boundary and contains a payload + * length specified by RequestLength (in 8-byte units). RequestLength is + * supplied by the Requester and specifies the amount of data in the request + * and the response. The offset from the beginning of one segment to the + * next is determined by RequestLength. If a request or response does not fit + * within RequestLength then an error is set in Status; response data is undefined + * in this situation. + */ + /* Max number of aggregate attributes */ +#define MAX_AGGREGATE_ATTRIBUTES (STL_MAX_PAYLOAD_SMP_DR / 16) +#define STL_MAX_PAYLOAD_AGGREGATE 1016 + +typedef struct { + uint16 AttributeID; + union { + uint16 AsReg16; + struct { IB_BITFIELD3( uint16, + Error: 1, /* 1: Error (Invalid AttributeID/Modifier, */ + /* RequestLength, Attribute Data) */ + Reserved: 8, + RequestLength: 7 ) /* Request length (8-byte units) */ + } s; + + } Result; + + uint32 AttributeModifier; + + uint8 Data[0]; +} PACK_SUFFIX STL_AGGREGATE; + +/* + * Returns a pointer to the first member of an aggregate MAD. + * Header must be in HOST byte order. + */ +#define STL_AGGREGATE_FIRST(smp) (STL_AGGREGATE*)((smp->common.MgmtClass == MCLASS_SM_LID_ROUTED)?(smp->SmpExt.LIDRouted.SMPData):(smp->SmpExt.DirectedRoute.SMPData)) + +/* + * Given an STL_AGGREGATE member, returns the next member. + * Member header must be in HOST byte order. Does not range check. + */ +#define STL_AGGREGATE_NEXT(pAggr) ((STL_AGGREGATE*)((uint8*)(pAggr)+((pAggr)->Result.s.RequestLength*8)+sizeof(STL_AGGREGATE))) + +/* + * PortStateInfo + * + * Attribute Modifier as: NNNN NNNN 0000 0000 0000 00S0 PPPP PPPP + * N: Number of ports + * S=1: Start of SM configuration + * P: Port number (0 - management port, switches only; + * for HFIs P is ignored and the attribute is + * applicable only to the port that receives the packet) + * + * A list of port state information, one entry per port (starting at port P). + */ +typedef struct { + STL_PORT_STATES PortStates; /* RW */ + uint16 LinkWidthDowngradeTxActive; /* RO */ + uint16 LinkWidthDowngradeRxActive; /* RO */ + +} PACK_SUFFIX STL_PORT_STATE_INFO; +#define STL_NUM_PORT_STATE_INFO_BLOCKS_PER_DRSMP ((uint8_t)(STL_MAX_PAYLOAD_SMP_DR / sizeof(STL_PORT_STATES))) +#define STL_NUM_PORT_STATE_INFO_BLOCKS_PER_LID_SMP ((uint8_t)(STL_MAX_PAYLOAD_SMP_LR / sizeof(STL_PORT_STATES))) + + +/* + * Port Group Forwarding Table (PGFT) + * + * Attribute Modifier as: NNNN NNNN 0000 0ABB BBBB BBBB BBBB BBBB + * N: Number of blocks + * A=1: All blocks starting at B (Set only) + * B: Block number + * + * The (max) PGFT is 2**24 entries (LIDs) long (STL_LID_24), 8 bits wide. + * Each PGFT block is 64 entries long, 8 bits wide. The PGFT is a + * linear array of blocks[2**18]. + */ + +#define NUM_PGFT_ELEMENTS_BLOCK 0x40 /* Num elements per block */ +#define DEFAULT_MAX_PGFT_BLOCK_NUM 0x80 /* Cap for alpha PRR is 128 blocks. */ +#define DEFAULT_MAX_PGFT_LID ((DEFAULT_MAX_PGFT_BLOCK_NUM * NUM_PGFT_ELEMENTS_BLOCK) - 1) +#define STL_NUM_PGFT_BLOCKS_PER_DRSMP ((uint8_t)(STL_MAX_PAYLOAD_SMP_DR/NUM_PGFT_ELEMENTS_BLOCK)) + +typedef struct { /* RW POD: PGFTn=0xFF */ + PORT PgftBlock[NUM_PGFT_ELEMENTS_BLOCK]; + +} PACK_SUFFIX STL_PORT_GROUP_FORWARDING_TABLE; + + +/* + * Port Group Table (PGT) + * + * Attribute Modifier as: NNNN NNNN PP00 0000 0000 0000 00AB BBBB + * N: Number of blocks + * P: Position number + * A=1: All blocks starting at B (Set only) + * B: Block number + * + * The PGT is 256 entries long, 256 bits wide. + * Each PGT block is 8 entries long, 64 bits wide. The PGT is a + * 2-dimensional array of blocks[32][4]. + */ + +#define NUM_PGT_ELEMENTS_BLOCK 8 /* Num elements per block */ +#define MAX_PGT_BLOCK_NUM 0x1F +#define MAX_PGT_ELEMENTS 256 +#define STL_NUM_PGTABLE_BLOCKS_PER_DRSMP ((uint8_t)(STL_MAX_PAYLOAD_SMP_DR/NUM_PGFT_ELEMENTS_BLOCK)) + +typedef struct { /* RW POD: PGTn=0 */ + STL_PORTMASK PgtBlock[NUM_PGT_ELEMENTS_BLOCK]; + +} PACK_SUFFIX STL_PORT_GROUP_TABLE; + + +/* + * BufferControlTable + * + * Attribute Modifier as: NNNN NNNN 0000 0000 0000 000A PPPP PPPP + * N: Number of ports + * A=1: All ports starting at P (Set only) + * P: Port number (0 - management port, switches only; + * for HFIs P is ignored and the attribute is + * applicable only to the port that receives the packet) + * Note: + * All receive values in buffer allocation units of this receiver + * All transmit values in buffer allocation units of neighbor receiver + */ +typedef struct { + uint16 Reserved; + uint16 TxOverallSharedLimit; /* RW Overall shared limit */ + + struct STL_BUFFER_CONTROL_TABLE_VL_s { /* Per VL data */ + uint16 TxDedicatedLimit; /* RW Dedicated limit */ + uint16 TxSharedLimit; /* RW Shared limit */ + } VL[STL_MAX_VLS]; + +} PACK_SUFFIX STL_BUFFER_CONTROL_TABLE; + +// NOTE: STL_BUFFER_CONTROL_TABLE is NOT 8 byte aligned. When doing multiblock queries, each block +// *MUST* be rounded to the nearest 8 byte boundary, or PRR will reject any SMA request for more than +// one block. In the future we may just want to pad out the structure, for now the following macros should +// be used when working with BCT blocks inside of SMAs. +#define STL_BFRCTRLTAB_PAD_SIZE ((sizeof(STL_BUFFER_CONTROL_TABLE)+7)&~0x7) +#define STL_NUM_BFRCTLTAB_BLOCKS_PER_DRSMP ((uint8_t)(STL_MAX_PAYLOAD_SMP_DR / STL_BFRCTRLTAB_PAD_SIZE)) +#define STL_NUM_BFRCTLTAB_BLOCKS_PER_LID_SMP ((uint8_t)(STL_MAX_PAYLOAD_SMP_LR / STL_BFRCTRLTAB_PAD_SIZE)) + +/* + * Congestion Info + * + * Attribute Modifier as: 0 (not used) + */ + +#define CC_CONGESTION_INFO_CREDIT_STARVATION 0x0001 /* Supports credit starvation (switch only) */ + +typedef struct { + uint16 CongestionInfo; /* RO Defined in IBTA V1.2.1 A10.4.3.3. */ + uint8 ControlTableCap; /* RO Number of supported entries in */ + /* HFI Congestion Control Table */ + uint8 CongestionLogLength; /* RO. Legal values are 0 <= N <= 96 */ +} STL_CONGESTION_INFO; + + +/* + * Switch Congestion Log + * + * Attribute Modifier as: 0 (not used) + * + * The Log is up to 96 entries long. Each Log is 96 entries long. + * If a request asks for more entries than the device supports, the + * remainder should be zero-filled. + */ + +#define STL_NUM_CONGESTION_LOG_ELEMENTS 96 /* Max num elements in log (SW and HFI) */ + +typedef struct { /* POD: 0 */ + STL_LID SLID; + STL_LID DLID; + + IB_BITFIELD2( uint8, + SC: 5, + Reserved: 3 ); + + uint8 Reserved2; + uint16 Reserved3; + + uint32 TimeStamp; + +} STL_SWITCH_CONGESTION_LOG_EVENT; + +typedef struct { /* RO */ + uint8 LogType; /* shall be 1 in response from a switch */ + uint8 CongestionFlags; + uint16 LogEventsCounter; /* POD: 0 */ + uint32 CurrentTimeStamp; /* POD: 0 */ + uint8 PortMap[256/8]; + + STL_SWITCH_CONGESTION_LOG_EVENT CongestionEntryList[STL_NUM_CONGESTION_LOG_ELEMENTS]; + +} PACK_SUFFIX STL_SWITCH_CONGESTION_LOG; + + +/* + * Switch Congestion Setting + * + * Attribute Modifier as: 0 (not used) + */ + +/* bitfields for Control_Map */ +#define CC_SWITCH_CONTROL_MAP_VICTIM_VALID 0x00000001 /* Victim_Mask */ +#define CC_SWITCH_CONTROL_MAP_CREDIT_VALID 0x00000002 /* Credit_Mask */ +#define CC_SWITCH_CONTROL_MAP_CC_VALID 0x00000004 /* Threshold & Packet_Size */ +#define CC_SWITCH_CONTROL_MAP_CS_VALID 0x00000008 /* CS_threshold & CS_ReturnDelay */ +#define CC_SWITCH_CONTROL_MAP_MARKING_VALID 0x00000010 /* Marking Rate */ + +typedef struct { /* RW */ + uint32 Control_Map; /* POD: 0 */ + uint8 Victim_Mask[256/8]; /* POD: 0 */ + uint8 Credit_Mask[256/8]; /* POD: 0 */ + + IB_BITFIELD2( uint8, + Threshold: 4, /* POD: 0 */ + Reserved: 4 ); + + uint8 Packet_Size; /* in 64 byte units */ + /* POD: 0 */ + + IB_BITFIELD2( uint8, + CS_Threshold: 4, /* POD: 0 */ + Reserved2: 4 ); + + uint8 Reserved3; + + uint16 CS_ReturnDelay; /* POD: 0 */ + uint16 Marking_Rate; /* POD: 0 */ + +} PACK_SUFFIX STL_SWITCH_CONGESTION_SETTING; + + +/* + * Switch Port Congestion Setting + * + * Attribute Modifier as: NNNN NNNN 0000 0000 0000 0000 PPPP PPPP + * N: Number of blocks + * P: Port number + */ + +// Values for Control_Type +#define SWITCH_PORT_CONGESTION_CONTROL_TYPE_CC 0 +#define SWITCH_PORT_CONGESTION_CONTROL_TYPE_STARVATION 1 + +typedef struct { + IB_BITFIELD4( uint8, /* POD: 0 */ + Valid: 1, + Control_Type: 1, + Reserved: 2, + Threshold: 4 ); /* 0-15 where 0 = no marking and */ + /* 15 = most aggressive */ + + uint8 Packet_Size; /* POD: 0. When Control_Type == 1 */ + /* this field is reserved. When Control*/ + /* _Type == 0, this field contains the */ + /* minimum size of a packet which may */ + /* be marked with a FECN. Packets */ + /* smaller than this size will not be */ + /* marked. Packet_Size is specified in */ + /* credits. */ + uint16 Marking_Rate; /* POD: 0. When Control_Type == 0 this */ + /* contains the port marking rate, */ + /* defined as the minimum number of */ + /* packets between marking eligible */ + /* packets with a FECN. */ +} PACK_SUFFIX STL_SWITCH_PORT_CONGESTION_SETTING_ELEMENT; + +typedef struct { /* RW */ + +STL_SWITCH_PORT_CONGESTION_SETTING_ELEMENT Elements[1]; + +} PACK_SUFFIX STL_SWITCH_PORT_CONGESTION_SETTING; + + +/* + * HFI Congestion Log + * + * Attribute Modifier as: 0 (not used) + * + * The Log is up to 96 entries long. Each Log is 96 entries long. + * If a request asks for more entries than the device supports, the + * remainder should be zero-filled. + */ +#define CC_RC_TYPE 0 +#define CC_UC_TYPE 1 +#define CC_RD_TYPE 2 +#define CC_UD_TYPE 3 + +typedef struct { /* POD: 0 */ + struct { + uint8 AsReg8s[3]; + } Local_QP_CN_Entry; /* 0->port threshold reached */ + + struct { + uint8 AsReg8s[3]; + } Remote_QP_Number_CN_Entry; /* 0 for UD */ + + IB_BITFIELD2( uint8, + SL_CN_Entry: 5, + Service_Type_CN_Entry: 3 ); + + uint8 Reserved; + + STL_LID Remote_LID_CN_Entry; /* IBTA already used 32 bits for this */ + + uint32 TimeStamp_CN_Entry; + +} PACK_SUFFIX STL_HFI_CONGESTION_LOG_EVENT; + +typedef struct { /* RO */ + uint8 LogType; /* shall be 0x2 in a response from an HFI */ + uint8 CongestionFlags; + uint16 ThresholdEventCounter; /* POD: 0 */ + uint32 CurrentTimeStamp; /* POD: 0 */ + uint8 ThresholdCongestionEventMap[STL_MAX_SLS/8]; /* 1 bit per SL */ + + STL_HFI_CONGESTION_LOG_EVENT CongestionEntryList[STL_NUM_CONGESTION_LOG_ELEMENTS]; + +} PACK_SUFFIX STL_HFI_CONGESTION_LOG; + +/* + * HFI Congestion Setting + * + * Attribute Modifier as: 0 (not used) + * + * This attribute applicable to HFIs or Enhanced Switch Port 0. + */ + +/* Port_Control field bit values */ +#define CC_HFI_CONGESTION_SETTING_SL_PORT 0x0001 /* SL/Port control */ + +typedef struct { + uint8 CCTI_Increase; /* POD: 0 */ + uint8 Reserved; + uint16 CCTI_Timer; /* POD: 0 */ + uint8 TriggerThreshold; /* POD: 0 */ + uint8 CCTI_Min; /* POD: 0 */ +} STL_HFI_CONGESTION_SETTING_ENTRY; + +typedef struct { /* RW */ + uint32 Control_Map; /* POD: 0 */ + uint16 Port_Control; /* POD: 0 */ + + STL_HFI_CONGESTION_SETTING_ENTRY HFICongestionEntryList[STL_MAX_SLS]; + +} PACK_SUFFIX STL_HFI_CONGESTION_SETTING; + + +/* + * HFI Congestion Control Table + * + * Attribute Modifier as: NNNN NNNN 0000 0000 0000 0000 BBBB BBBB + * N: Number of blocks + * B: Block number + * + * The HFI Congestion Control Table is up to 2**14 entries long. Each block + * is 64 entries long. Table is a linear array of blocks[2**8]. + */ + +#define STL_NUM_CONGESTION_CONTROL_ELEMENTS_BLOCK_ENTRIES 64 /* Num elements per block */ +#define STL_NUM_CONGESTION_CONTROL_ELEMENTS_BLOCKS 256 /* Max num blocks per table */ +#define STL_CONGESTION_CONTROL_ENTRY_MAX_VALUE 16384 /* 2**14 max multiplier value*/ + +typedef union { + uint16 AsReg16; + struct { IB_BITFIELD2( uint16, + CCT_Shift: 2, /* POD: 0 */ + CCT_Multiplier: 14 ); /* POD: 0 */ + } s; +} PACK_SUFFIX STL_HFI_CONGESTION_CONTROL_TABLE_ENTRY; + +typedef struct { + STL_HFI_CONGESTION_CONTROL_TABLE_ENTRY CCT_Entry_List[STL_NUM_CONGESTION_CONTROL_ELEMENTS_BLOCK_ENTRIES]; +} PACK_SUFFIX STL_HFI_CONGESTION_CONTROL_TABLE_BLOCK; + +typedef struct { /* RW */ + uint16 CCTI_Limit; /* POD: 0 */ + STL_HFI_CONGESTION_CONTROL_TABLE_BLOCK CCT_Block_List[1]; /* 1 or more blocks */ + +} PACK_SUFFIX STL_HFI_CONGESTION_CONTROL_TABLE; + +#define CONGESTION_CONTROL_TABLE_CCTILIMIT_SZ (sizeof(uint16)) + +/* this is conservative and considers the least payload */ +#define CONGESTION_CONTROL_TABLE_BLOCKS_PER_MAD \ + ((MIN(STL_MAX_PAYLOAD_SMP_DR, STL_MAX_PAYLOAD_SMP_LR) - CONGESTION_CONTROL_TABLE_CCTILIMIT_SZ) / sizeof(STL_HFI_CONGESTION_CONTROL_TABLE_BLOCK)) +#define CONGESTION_CONTROL_TABLE_ENTRIES_PER_MAD \ + (CONGESTION_CONTROL_TABLE_BLOCKS_PER_MAD * \ + STL_NUM_CONGESTION_CONTROL_ELEMENTS_BLOCK_ENTRIES) +#define CONGESTION_CONTROL_IMPLEMENTATION_LIMIT 895 + +typedef struct { + uint64 M_Key; /* A 64 bit key, */ + STL_LID DrSLID; /* Directed route source LID */ + STL_LID DrDLID; /* Directed route destination LID */ + uint8 InitPath[64]; /* 64-byte field containing the initial */ + /* directed path */ + uint8 RetPath[64]; /* 64-byte field containing the */ + /* returning directed path */ + uint8 Reserved2[8]; /* For the purpose of aligning the Data */ + /* field on a 16-byte boundary */ + uint8 SMPData[STL_MAX_PAYLOAD_SMP_DR]; /* Up to 'MAX' byte field of SMP */ + /* data used to contain the */ + /* method's attribute */ +} PACK_SUFFIX DRStlSmp_t; +#define STL_SMP_DR_HDR_LEN (sizeof(DRStlSmp_t) - STL_MAX_PAYLOAD_SMP_DR) + +typedef struct { + uint64 M_Key; /* A 64 bit key, */ + uint8 SMPData[STL_MAX_PAYLOAD_SMP_LR]; /* Up to 'MAX' byte field of SMP */ + /* data used to contain the */ + /* method's attribute */ + +} PACK_SUFFIX LRStlSmp_t; +#define STL_SMP_LR_HDR_LEN (sizeof(LRStlSmp_t) - STL_MAX_PAYLOAD_SMP_LR) + +#include "iba/public/ipackoff.h" + +#if defined (__cplusplus) +}; +#endif + +#endif /* __IBA_STL_SM_TYPES_H__ */ diff --git a/IbAccess/Common/Inc/stl_t.h b/IbAccess/Common/Inc/stl_t.h new file mode 100644 index 0000000..95cf23c --- /dev/null +++ b/IbAccess/Common/Inc/stl_t.h @@ -0,0 +1,57 @@ +/* BEGIN_ICS_COPYRIGHT5 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + * ** END_ICS_COPYRIGHT5 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +#ifndef _STL_H_ +#define _STL_H_ + +#include "iba/public/datatypes.h" +#include "iba/public/statustext.h" + +#include "iba/ib_ibt.h" + +#include "iba/stl_sa_priv.h" +#include "iba/stl_sd.h" + +#if defined(VXWORKS) +#ifdef BUILD_CM +#include "iba/ib_cm.h" +#endif +#else +#include "iba/ib_cm.h" +#endif +#include "iba/stl_pa_priv.h" +#include "iba/ib_types.h" + +#ifdef __cplusplus +}; +#endif + +#endif /* _STL_H_ */ diff --git a/IbAccess/Common/Inc/stl_types.h b/IbAccess/Common/Inc/stl_types.h new file mode 100644 index 0000000..2731c6a --- /dev/null +++ b/IbAccess/Common/Inc/stl_types.h @@ -0,0 +1,605 @@ +/* BEGIN_ICS_COPYRIGHT3 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT3 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +#ifndef _IBA_STL_TYPES_H_ +#define _IBA_STL_TYPES_H_ + +#include "iba/ib_types.h" + +/* Basic data types */ + +#ifdef __cplusplus +extern "C" { +#endif + +typedef uint16 STL_LID_16; /* Can replace IB_LID */ +typedef uint32 STL_LID_32; /* Max LID size */ +typedef uint32 STL_LID; /* Max LID size */ + +#define STL_MAX_SLS 32 /* Max number of SLs */ +#define STL_MAX_SCS 32 /* Max number of SCs */ +#define STL_MAX_VLS 32 /* Max number of VLs */ + + +#define MAX_STL_PORTS 64 +#define MAX_STL2_VLS 9 + + +typedef uint64 STL_PORTMASK; /* Port mask element */ + +#define STL_MAX_PORTMASK 256/(sizeof(STL_PORTMASK)*8) /* Max Ports in select */ +#define STL_PORT_SELECTMASK_SIZE (sizeof(STL_PORTMASK)*STL_MAX_PORTMASK) +#define STL_EXT_GID_INDEX 1 /* Index into GID table where extended LIDs are stored */ + +/* -------------------------------------------------------------------------- */ +/* LID's */ + +#define STL_LID_UNICAST_BEGIN 0x00000001U +#define STL_LID_UNICAST_END 0xbfffffffU +#define STL_LID_MULTICAST_BEGIN 0xf0000000U +#define STL_LID_MULTICAST_END 0xf0003ffeU +#define STL_LID_MULTICAST_MASK 0x00003fffU +#define STL_LID_MCAST_OFFSET_MASK STL_LID_MULTICAST_MASK +#define STL_LID_RESERVED 0x00000000U +#define STL_LID_PERMISSIVE 0xffffffffU +#define PERMISSIVE_LID_24BITS (STL_LID_PERMISSIVE & 0xffffff) + +#define MCAST32_TO_MCAST16(x) ((uint16_t)((x) & 0xffff) | 0xc000) +#define MCAST24_TO_MCAST16(x) MCAST32_TO_MCAST16(x) +#define MCAST20_TO_MCAST16(x) MCAST32_TO_MCAST16(x) + +#define MCAST16_TO_MCAST20(x) ((uint32_t)((x) & ~0xc000) | 0xf0000) +#define MCAST16_TO_MCAST24(x) ((uint32_t)((x) & ~0xc000) | 0xf00000) +#define MCAST16_TO_MCAST32(x) ((uint32_t)((x) & ~0xc000) | 0xf0000000) + +/* + * The IS_MCAST20,-24, and -32 macros below assume + * MultiCollectMask.MulticastMask = 4 + */ +#define IS_MCAST16(x) (((STL_LID)(x) & 0xffffc000) == 0x0000c000) +#define IS_MCAST20(x) (((STL_LID)(x) & 0xffff0000) == 0x000f0000) +#define IS_MCAST24(x) (((STL_LID)(x) & 0xfff00000) == 0x00f00000) +#define IS_MCAST32(x) (((STL_LID)(x) & 0xf0000000) == 0xf0000000) + +#define UCAST32_TO_UCAST16(x) (IB_LID)(x) +#define UCAST16_TO_UCAST32(x) (STL_LID)(((x) == LID_PERMISSIVE) ? STL_LID_PERMISSIVE:(x)) + +static inline STL_LID +IB2STL_LID(IB_LID ib_lid) { + if (IS_MCAST16(ib_lid)) return MCAST16_TO_MCAST32(ib_lid); + else return UCAST16_TO_UCAST32(ib_lid); +} + +static inline IB_LID +STL2IB_LID(STL_LID stl_lid) { + if (IS_MCAST32(stl_lid)) return MCAST32_TO_MCAST16(stl_lid); + else return UCAST32_TO_UCAST16(stl_lid); +} + +#include "iba/public/ipackon.h" + +/* STL IPV6 IP Address (128 bits) */ +typedef struct { + uint8 addr[16]; +} PACK_SUFFIX STL_IPV6_IP_ADDR; + +/* STL IPV4 IP Address (32 bits) */ +typedef struct { + uint8 addr[4]; +} PACK_SUFFIX STL_IPV4_IP_ADDR; + +typedef struct { IB_BITFIELD2( uint8, + Reserved: 3, + SL: 5 ) +} STL_SL; + +typedef struct { IB_BITFIELD2( uint8, + Reserved: 3, + SC: 5 ) +} STL_SC; + +typedef struct { IB_BITFIELD2( uint8, + Reserved: 3, + VL: 5 ) +} STL_VL; + +/* STL MTU values continue from IB_MTU */ +#define STL_MTU_0 0 +#define STL_MTU_8192 6 +#define STL_MTU_10240 7 +#define STL_MTU_MAX STL_MTU_10240 + +/* + * STL_FIELDUNIONx() macros are used to create bit-packed structures + * suitable for network-to-host byte conversion. They are similar to + * the older IB_BITFIELD() macros but automatically create the union + * and struct wrappers that are usually manually added to the bitfields. + * + * The resulting structures are identical in use to the old IB structures. + * + * All macros take the form: + * + * STL_FIELDUNIONx(name, len, field1, field2, ..., fieldx); + * + * Where "name" is the name of the union, len is a bit length, either + * 8, 16, 32 or 64, and the fields are the bit fields to be created. + * + * For example, this macro: + * + * STL_FIELDUNION3(q1, 32, QPN:24, Flag:1, Rsvd:7); + * + * Will expand into the following union: + * + * union { + * uint32 AsReg32; + * struct { + * uint32 QPN:24; + * uint32 Flag:1; + * uint32 Rsvd:7; + * } __attribute__((packed)) s; + * } __attribute__((packed)) a1; + * + */ +#define STL_UINT(len) uint##len +#define STL_ASREG(len) AsReg##len +#if CPU_BE + #define STL_FIELDUNION2(name, len,field1,field2) \ + union { \ + STL_UINT(len) STL_ASREG(len); \ + struct { \ + STL_UINT(len) field1; \ + STL_UINT(len) field2; \ + } PACK_SUFFIX s; \ + } PACK_SUFFIX name + #define STL_FIELDUNION3(name, len,field1,field2,field3) \ + union { \ + STL_UINT(len) STL_ASREG(len); \ + struct { \ + STL_UINT(len) field1; \ + STL_UINT(len) field2; \ + STL_UINT(len) field3; \ + } PACK_SUFFIX s; \ + } PACK_SUFFIX name + #define STL_FIELDUNION4(name, len,field1,field2,field3,field4) \ + union { \ + STL_UINT(len) STL_ASREG(len); \ + struct { \ + STL_UINT(len) field1; \ + STL_UINT(len) field2; \ + STL_UINT(len) field3; \ + STL_UINT(len) field4; \ + } PACK_SUFFIX s; \ + } PACK_SUFFIX name + #define STL_FIELDUNION5(name, len,field1,field2,field3,field4,field5) \ + union { \ + STL_UINT(len) STL_ASREG(len); \ + struct { \ + STL_UINT(len) field1; \ + STL_UINT(len) field2; \ + STL_UINT(len) field3; \ + STL_UINT(len) field4; \ + STL_UINT(len) field5; \ + } PACK_SUFFIX s; \ + } PACK_SUFFIX name + #define STL_FIELDUNION6(name, len,field1,field2,field3,field4,field5,field6) \ + union { \ + STL_UINT(len) STL_ASREG(len); \ + struct { \ + STL_UINT(len) field1; \ + STL_UINT(len) field2; \ + STL_UINT(len) field3; \ + STL_UINT(len) field4; \ + STL_UINT(len) field5; \ + STL_UINT(len) field6; \ + } PACK_SUFFIX s; \ + } PACK_SUFFIX name + #define STL_FIELDUNION7(name, len,field1,field2,field3,field4,field5,field6,field7) \ + union { \ + STL_UINT(len) STL_ASREG(len); \ + struct { \ + STL_UINT(len) field1; \ + STL_UINT(len) field2; \ + STL_UINT(len) field3; \ + STL_UINT(len) field4; \ + STL_UINT(len) field5; \ + STL_UINT(len) field6; \ + STL_UINT(len) field7; \ + } PACK_SUFFIX s; \ + } PACK_SUFFIX name + #define STL_FIELDUNION8(name, len, field1,field2,field3,field4,field5,field6,field7,field8) \ + union { \ + STL_UINT(len) STL_ASREG(len); \ + struct { \ + STL_UINT(len) field1; \ + STL_UINT(len) field2; \ + STL_UINT(len) field3; \ + STL_UINT(len) field4; \ + STL_UINT(len) field5; \ + STL_UINT(len) field6; \ + STL_UINT(len) field7; \ + STL_UINT(len) field8; \ + } PACK_SUFFIX s; \ + } PACK_SUFFIX name + #define STL_FIELDUNION9(name, len, field1,field2,field3,field4,field5,field6,field7,field8,field9) \ + union { \ + STL_UINT(len) STL_ASREG(len); \ + struct { \ + STL_UINT(len) field1; \ + STL_UINT(len) field2; \ + STL_UINT(len) field3; \ + STL_UINT(len) field4; \ + STL_UINT(len) field5; \ + STL_UINT(len) field6; \ + STL_UINT(len) field7; \ + STL_UINT(len) field8; \ + STL_UINT(len) field9; \ + } PACK_SUFFIX s; \ + } PACK_SUFFIX name + #define STL_FIELDUNION10(name, len, field1,field2,field3,field4,field5,field6,field7,field8,field9,field10) \ + union { \ + STL_UINT(len) STL_ASREG(len); \ + struct { \ + STL_UINT(len) field1; \ + STL_UINT(len) field2; \ + STL_UINT(len) field3; \ + STL_UINT(len) field4; \ + STL_UINT(len) field5; \ + STL_UINT(len) field6; \ + STL_UINT(len) field7; \ + STL_UINT(len) field8; \ + STL_UINT(len) field9; \ + STL_UINT(len) field10; \ + } PACK_SUFFIX s; \ + } PACK_SUFFIX name + #define STL_FIELDUNION11(name, len, field1,field2,field3,field4,field5,field6,field7,field8,field9,field10,field11) \ + union { \ + STL_UINT(len) STL_ASREG(len); \ + struct { \ + STL_UINT(len) field1; \ + STL_UINT(len) field2; \ + STL_UINT(len) field3; \ + STL_UINT(len) field4; \ + STL_UINT(len) field5; \ + STL_UINT(len) field6; \ + STL_UINT(len) field7; \ + STL_UINT(len) field8; \ + STL_UINT(len) field9; \ + STL_UINT(len) field10; \ + STL_UINT(len) field11; \ + } PACK_SUFFIX s; \ + } PACK_SUFFIX name + #define STL_FIELDUNION14(name, len, field1,field2,field3,field4,field5,field6,field7,field8,field9,field10,field11,field12,field13,field14) \ + union { \ + STL_UINT(len) STL_ASREG(len); \ + struct { \ + STL_UINT(len) field1; \ + STL_UINT(len) field2; \ + STL_UINT(len) field3; \ + STL_UINT(len) field4; \ + STL_UINT(len) field5; \ + STL_UINT(len) field6; \ + STL_UINT(len) field7; \ + STL_UINT(len) field8; \ + STL_UINT(len) field9; \ + STL_UINT(len) field10; \ + STL_UINT(len) field11; \ + STL_UINT(len) field12; \ + STL_UINT(len) field13; \ + STL_UINT(len) field14; \ + } PACK_SUFFIX s; \ + } PACK_SUFFIX name + #define STL_FIELDUNION15(name, len, field1,field2,field3,field4,field5,field6,field7,field8,field9,field10,field11,field12,field13,field14,field15) \ + union { \ + STL_UINT(len) STL_ASREG(len); \ + struct { \ + STL_UINT(len) field1; \ + STL_UINT(len) field2; \ + STL_UINT(len) field3; \ + STL_UINT(len) field4; \ + STL_UINT(len) field5; \ + STL_UINT(len) field6; \ + STL_UINT(len) field7; \ + STL_UINT(len) field8; \ + STL_UINT(len) field9; \ + STL_UINT(len) field10; \ + STL_UINT(len) field11; \ + STL_UINT(len) field12; \ + STL_UINT(len) field13; \ + STL_UINT(len) field14; \ + STL_UINT(len) field15; \ + } PACK_SUFFIX s; \ + } PACK_SUFFIX name + #define STL_FIELDUNION16(name, len, field1,field2,field3,field4,field5,field6,field7,field8,field9,field10,field11,field12,field13,field14,field15,field16) \ + union { \ + STL_UINT(len) STL_ASREG(len); \ + struct { \ + STL_UINT(len) field1; \ + STL_UINT(len) field2; \ + STL_UINT(len) field3; \ + STL_UINT(len) field4; \ + STL_UINT(len) field5; \ + STL_UINT(len) field6; \ + STL_UINT(len) field7; \ + STL_UINT(len) field8; \ + STL_UINT(len) field9; \ + STL_UINT(len) field10; \ + STL_UINT(len) field11; \ + STL_UINT(len) field12; \ + STL_UINT(len) field13; \ + STL_UINT(len) field14; \ + STL_UINT(len) field15; \ + STL_UINT(len) field16; \ + } PACK_SUFFIX s; \ + } PACK_SUFFIX name + #define STL_FIELDUNION17(name, len, field1,field2,field3,field4,field5,field6,field7,field8,field9,field10,field11,field12,field13,field14,field15,field16,field17) \ + union { \ + STL_UINT(len) STL_ASREG(len); \ + struct { \ + STL_UINT(len) field1; \ + STL_UINT(len) field2; \ + STL_UINT(len) field3; \ + STL_UINT(len) field4; \ + STL_UINT(len) field5; \ + STL_UINT(len) field6; \ + STL_UINT(len) field7; \ + STL_UINT(len) field8; \ + STL_UINT(len) field9; \ + STL_UINT(len) field10; \ + STL_UINT(len) field11; \ + STL_UINT(len) field12; \ + STL_UINT(len) field13; \ + STL_UINT(len) field14; \ + STL_UINT(len) field15; \ + STL_UINT(len) field16; \ + STL_UINT(len) field17; \ + } PACK_SUFFIX s; \ + } PACK_SUFFIX name +#else + #define STL_FIELDUNION2(name, len,field1,field2) \ + union { \ + STL_UINT(len) STL_ASREG(len); \ + struct { \ + STL_UINT(len) field2; \ + STL_UINT(len) field1; \ + } PACK_SUFFIX s; \ + } PACK_SUFFIX name + #define STL_FIELDUNION3(name, len,field1,field2,field3) \ + union { \ + STL_UINT(len) STL_ASREG(len); \ + struct { \ + STL_UINT(len) field3; \ + STL_UINT(len) field2; \ + STL_UINT(len) field1; \ + } PACK_SUFFIX s; \ + } PACK_SUFFIX name + #define STL_FIELDUNION4(name, len,field1,field2,field3,field4) \ + union { \ + STL_UINT(len) STL_ASREG(len); \ + struct { \ + STL_UINT(len) field4; \ + STL_UINT(len) field3; \ + STL_UINT(len) field2; \ + STL_UINT(len) field1; \ + } PACK_SUFFIX s; \ + } PACK_SUFFIX name + #define STL_FIELDUNION5(name, len,field1,field2,field3,field4,field5) \ + union { \ + STL_UINT(len) STL_ASREG(len); \ + struct { \ + STL_UINT(len) field5; \ + STL_UINT(len) field4; \ + STL_UINT(len) field3; \ + STL_UINT(len) field2; \ + STL_UINT(len) field1; \ + } PACK_SUFFIX s; \ + } PACK_SUFFIX name + #define STL_FIELDUNION6(name, len,field1,field2,field3,field4,field5,field6) \ + union { \ + STL_UINT(len) STL_ASREG(len); \ + struct { \ + STL_UINT(len) field6; \ + STL_UINT(len) field5; \ + STL_UINT(len) field4; \ + STL_UINT(len) field3; \ + STL_UINT(len) field2; \ + STL_UINT(len) field1; \ + } PACK_SUFFIX s; \ + } PACK_SUFFIX name + #define STL_FIELDUNION7(name, len,field1,field2,field3,field4,field5,field6,field7) \ + union { \ + STL_UINT(len) STL_ASREG(len); \ + struct { \ + STL_UINT(len) field7; \ + STL_UINT(len) field6; \ + STL_UINT(len) field5; \ + STL_UINT(len) field4; \ + STL_UINT(len) field3; \ + STL_UINT(len) field2; \ + STL_UINT(len) field1; \ + } PACK_SUFFIX s; \ + } PACK_SUFFIX name + #define STL_FIELDUNION8(name, len, field1,field2,field3,field4,field5,field6,field7,field8) \ + union { \ + STL_UINT(len) STL_ASREG(len); \ + struct { \ + STL_UINT(len) field8; \ + STL_UINT(len) field7; \ + STL_UINT(len) field6; \ + STL_UINT(len) field5; \ + STL_UINT(len) field4; \ + STL_UINT(len) field3; \ + STL_UINT(len) field2; \ + STL_UINT(len) field1; \ + } PACK_SUFFIX s; \ + } PACK_SUFFIX name + #define STL_FIELDUNION9(name, len, field1,field2,field3,field4,field5,field6,field7,field8,field9) \ + union { \ + STL_UINT(len) STL_ASREG(len); \ + struct { \ + STL_UINT(len) field9; \ + STL_UINT(len) field8; \ + STL_UINT(len) field7; \ + STL_UINT(len) field6; \ + STL_UINT(len) field5; \ + STL_UINT(len) field4; \ + STL_UINT(len) field3; \ + STL_UINT(len) field2; \ + STL_UINT(len) field1; \ + } PACK_SUFFIX s; \ + } PACK_SUFFIX name + #define STL_FIELDUNION10(name, len, field1,field2,field3,field4,field5,field6,field7,field8,field9,field10) \ + union { \ + STL_UINT(len) STL_ASREG(len); \ + struct { \ + STL_UINT(len) field10; \ + STL_UINT(len) field9; \ + STL_UINT(len) field8; \ + STL_UINT(len) field7; \ + STL_UINT(len) field6; \ + STL_UINT(len) field5; \ + STL_UINT(len) field4; \ + STL_UINT(len) field3; \ + STL_UINT(len) field2; \ + STL_UINT(len) field1; \ + } PACK_SUFFIX s; \ + } PACK_SUFFIX name + #define STL_FIELDUNION11(name, len, field1,field2,field3,field4,field5,field6,field7,field8,field9,field10,field11) \ + union { \ + STL_UINT(len) STL_ASREG(len); \ + struct { \ + STL_UINT(len) field11; \ + STL_UINT(len) field10; \ + STL_UINT(len) field9; \ + STL_UINT(len) field8; \ + STL_UINT(len) field7; \ + STL_UINT(len) field6; \ + STL_UINT(len) field5; \ + STL_UINT(len) field4; \ + STL_UINT(len) field3; \ + STL_UINT(len) field2; \ + STL_UINT(len) field1; \ + } PACK_SUFFIX s; \ + } PACK_SUFFIX name + #define STL_FIELDUNION14(name, len, field1,field2,field3,field4,field5,field6,field7,field8,field9,field10,field11,field12,field13,field14) \ + union { \ + STL_UINT(len) STL_ASREG(len); \ + struct { \ + STL_UINT(len) field14; \ + STL_UINT(len) field13; \ + STL_UINT(len) field12; \ + STL_UINT(len) field11; \ + STL_UINT(len) field10; \ + STL_UINT(len) field9; \ + STL_UINT(len) field8; \ + STL_UINT(len) field7; \ + STL_UINT(len) field6; \ + STL_UINT(len) field5; \ + STL_UINT(len) field4; \ + STL_UINT(len) field3; \ + STL_UINT(len) field2; \ + STL_UINT(len) field1; \ + } PACK_SUFFIX s; \ + } PACK_SUFFIX name + #define STL_FIELDUNION15(name, len, field1,field2,field3,field4,field5,field6,field7,field8,field9,field10,field11,field12,field13,field14,field15) \ + union { \ + STL_UINT(len) STL_ASREG(len); \ + struct { \ + STL_UINT(len) field15; \ + STL_UINT(len) field14; \ + STL_UINT(len) field13; \ + STL_UINT(len) field12; \ + STL_UINT(len) field11; \ + STL_UINT(len) field10; \ + STL_UINT(len) field9; \ + STL_UINT(len) field8; \ + STL_UINT(len) field7; \ + STL_UINT(len) field6; \ + STL_UINT(len) field5; \ + STL_UINT(len) field4; \ + STL_UINT(len) field3; \ + STL_UINT(len) field2; \ + STL_UINT(len) field1; \ + } PACK_SUFFIX s; \ + } PACK_SUFFIX name + #define STL_FIELDUNION16(name, len, field1,field2,field3,field4,field5,field6,field7,field8,field9,field10,field11,field12,field13,field14,field15,field16) \ + union { \ + STL_UINT(len) STL_ASREG(len); \ + struct { \ + STL_UINT(len) field16; \ + STL_UINT(len) field15; \ + STL_UINT(len) field14; \ + STL_UINT(len) field13; \ + STL_UINT(len) field12; \ + STL_UINT(len) field11; \ + STL_UINT(len) field10; \ + STL_UINT(len) field9; \ + STL_UINT(len) field8; \ + STL_UINT(len) field7; \ + STL_UINT(len) field6; \ + STL_UINT(len) field5; \ + STL_UINT(len) field4; \ + STL_UINT(len) field3; \ + STL_UINT(len) field2; \ + STL_UINT(len) field1; \ + } PACK_SUFFIX s; \ + } PACK_SUFFIX name + #define STL_FIELDUNION17(name, len, field1,field2,field3,field4,field5,field6,field7,field8,field9,field10,field11,field12,field13,field14,field15,field16,field17) \ + union { \ + STL_UINT(len) STL_ASREG(len); \ + struct { \ + STL_UINT(len) field17; \ + STL_UINT(len) field16; \ + STL_UINT(len) field15; \ + STL_UINT(len) field14; \ + STL_UINT(len) field13; \ + STL_UINT(len) field12; \ + STL_UINT(len) field11; \ + STL_UINT(len) field10; \ + STL_UINT(len) field9; \ + STL_UINT(len) field8; \ + STL_UINT(len) field7; \ + STL_UINT(len) field6; \ + STL_UINT(len) field5; \ + STL_UINT(len) field4; \ + STL_UINT(len) field3; \ + STL_UINT(len) field2; \ + STL_UINT(len) field1; \ + } PACK_SUFFIX s; \ + } PACK_SUFFIX name +#endif + +#include "iba/public/ipackoff.h" + +#ifdef __cplusplus +}; +#endif + +#endif /* _IBA_STL_TYPES_H_ */ diff --git a/IbAccess/Common/Inc/umadt.h b/IbAccess/Common/Inc/umadt.h new file mode 100644 index 0000000..1154f94 --- /dev/null +++ b/IbAccess/Common/Inc/umadt.h @@ -0,0 +1,612 @@ +/* BEGIN_ICS_COPYRIGHT2 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT2 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +#ifndef _IBA_UMADT_H_ +#define _IBA_UMADT_H_ + +#include +#include +#include +#include +#include + +#if defined (__cplusplus) +extern "C" { +#endif + +#define SEND_COMPLETION 1 +#define RECV_COMPLETION 2 +#define EVENT_COMPLETION 4 + +/* Typedefs */ +typedef void* MADT_HANDLE; +/*DataStructures */ + +/* ClassId is used to select between SMI and GSI as well as selecting + * which unsolicited inbound packets the consumer desires. + * For SMI, ClassId can be MCLASS_SM_LID_ROUTED or MCLASS_SM_DIRECTED_ROUTE + * either can receive SMI packets regardless of actual ClassId of packet + * This helps to reduce complexity in SM's using this interface + * Any other ClassId will register for the GSI interface + * + * The ClassId only affects inbound packets. The registration can be used + * to send any request packet in any class and corresponding responses + * (with same transaction id) will be returned to the sender. + * If registered for an SMI ClassId, all sends will be via QP0, if + * registered for a GSI ClassId all sends will be via the GSI QP. + * + * Unsolicited packets will be delivered based on their Method and R bit fields + * and the "is" flags below will select which packets a given consumer desires. + * A given unsolicited packet can be delivered to more than 1 consumer. + * + * A given registration is for a single local port, all sends and receives + * will be directed to that port. + */ +typedef struct RegisterClassStruct_ { + EUI64 PortGuid; /* PortGuid of local port */ + /* controls for unsolicited inbound packets */ + uint8 ClassId; /* Mgmt Class ID */ + uint8 ClassVersion; /* Mgmt Class version */ + boolean isResponder; /* True if this is a GSI Agent */ + boolean isTrapProcessor; /* True if GSI Trap msgs are handled */ + boolean isReportProcessor; /* True if GSI Report msgs are handled */ + /* queue sizing and management */ + uint32 SendQueueSize; /* SendQueueSize */ + uint32 RecvQueueSize; /* Receive Queue Size */ + boolean NotifySendCompletion; /* Notification for send completion */ + } RegisterClassStruct, *PRegisterClassStruct; + +typedef struct MadtStruct_ { + struct MadtStruct_ *FLink; /* Forward link */ + struct MadtStruct_ *BLink; /* Backward link */ + + /* Consumer context pointer (undefined on Receives) */ + uint64 Context; + + IB_GRH Grh; /* GRH */ + MAD IBMad; /* Management Data Gram */ + uint32 MadByteCount; /* Used size of IBMad in bytes */ + /* When zero indicates MAD_BLOCK_SIZE */ + } MadtStruct; + +typedef struct MadAddrStruct_ { + STL_LID DestLid; /* DLID */ + IB_PATHBITS PathBits; /* PathBits */ + uint8 StaticRate; /* The maximum static rate supported */ + /* enum IB_STATIC_RATE */ + union AddrType_ { + struct Smi_ { + STL_LID SourceLid; /* SLID */ + uint8 PortNumber; /* Incomming PortNumber */ + /* Returned on RecvCompletion */ + /* not required for Sends */ + }Smi; + struct Gsi_ { + uint32 RemoteQpNumber; /* RemoteQpNumber */ + uint32 RemoteQkey; /* RemoteQkey */ + IB_P_KEY PKey; /* Pkey for Send WQE */ + /* and Recv CQE */ + IB_SL ServiceLevel; + + /* Global routing information. */ + /* If GlobalRoute==true, GlobalRouteInfo structure is valid. */ + boolean GlobalRoute; + IB_GLOBAL_ROUTE_INFO GRHInfo; + }Gsi; + }AddrType; +}MadAddrStruct; + +typedef struct MadWorkCompletion_ { + + MadAddrStruct AddressInfo; + /* Completion Information */ + uint32 RecvByteCount; /* Received Byte count */ + FSTATUS Status; /*Status of this packet */ + + } MadWorkCompletion; + +typedef struct MadtEventRecordStruct_ { + uint32 ResourceType; + uint32 EventOrError; + }MadtEventRecordStruct; + +/* Function prototypes */ + +/* +* Register +* +* DESCRIPTION : +* +* This routine registers an agent or a manager with the associated QP. The +* returned MADT_HANDLE is later used to send and receive MAD's. +* This routine may be expected to perform a kernel mode context switch +* +* +* PARAMETERS : +* INPUTS : +* registerStruct : Data related to agent or manager being registered +* data pointed to only used during duration of call +* +* OUTPUTS: +* serviceHandle : The handle to the newly registered Agent +* or Manager +* +* RETURNS: +* FSUCCESS : Operation was successful +* FINVALID_PARAMETER : Invalid argumetns +* FINSUFFICIENT_RESOURCES : Insufficient resource +* +* Environment : User Mode +* +* NOTES: +*/ + +typedef +FSTATUS (UMADT_REGISTER)( + IN struct RegisterClassStruct_ *registerStruct, + OUT MADT_HANDLE *serviceHandle + ); +IBA_API UMADT_REGISTER iba_umadt_register; + +/* +* GetSendMad +* +* DESCRIPTION : +* +* This routine gets a MAD from the global MAD Pool which is a shared +* memory between provider and the proxy driver. The returned MAD is +* filled with data and is used in PostSend call. +* This routine will not perform a kernel mode context switch. +* +* +* PARAMETERS : +* INPUTS : +* serviceHandle : The handle got in Register Call +* madCount : Count of number of mads to return +* data pointed to only used during duration of call +* +* OUTPUTS: +* madCount : Count of number of mads returned +* mad : Returns pointer to MadtStruct +* +* RETURNS: +* FSUCCESS : Operation was successful +* FINVALID_PARAMETER : Invalid argumetns +* FUNAVAILABLE : SendMad unavailable +* +* Environment : User Mode +* +* NOTES: +*/ + +typedef +FSTATUS (UMADT_GETSENDMAD)( + IN MADT_HANDLE serviceHandle, + IN OUT uint32 *madCount, + OUT MadtStruct ** mad + ); +IBA_API UMADT_GETSENDMAD iba_umadt_get_sendmad; + +/* +* ReleaseSendMad +* +* DESCRIPTION : +* +* This routine puts back mads to the global mad pool. +* This routine will not perform a kernel mode context switch. +* +* +* PARAMETERS : +* INPUTS : +* serviceHandle : The handle got in Register Call +* mad : Pointer to MadtStruct +* data pointed to only used during duration of call +* +* OUTPUTS: +* None +* +* RETURNS: +* FSUCCESS : Operation was successful +* FINVALID_PARAMETER : Invalid argumetns +* Environment : User Mode +* +* NOTES: +*/ + + +typedef +FSTATUS (UMADT_RELEASESENDMAD)( + IN MADT_HANDLE serviceHandle, + IN MadtStruct *mad + ); +IBA_API UMADT_RELEASESENDMAD iba_umadt_release_sendmad; + +/* +* ReleaseRecvMad +* +* DESCRIPTION : +* +* This routine puts back mads to the global receive mad pool. +* This routine will not perform a kernel mode context switch. +* +* +* PARAMETERS : +* INPUTS : +* serviceHandle : The handle got in Register Call +* mad : Pointer to MadtStruct +* data pointed to only used during duration of call +* +* OUTPUTS: +* None +* +* RETURNS: +* FSUCCESS : Operation was successful +* FINVALID_PARAMETER : Invalid argumetns +* Environment : User Mode +* +* NOTES: +*/ + +typedef +FSTATUS (UMADT_RELEASERECVMAD)( + IN MADT_HANDLE serviceHandle, + IN MadtStruct *mad + ); +IBA_API UMADT_RELEASERECVMAD iba_umadt_release_recvmad; + +/* +* PostSend +* +* DESCRIPTION : +* +* This routine sends a management datatgram out on the wire. +* This routine may perform a kernel mode context switch. +* +* PARAMETERS : +* +* INPUTS +* serviceHandle : The handle got in Register Call +* mad : MAD info +* data pointed to only used during duration of call +* destAddr : MadAddrStruct info +* data pointed to only used during duration of call +* +* OUTPUTS: +* None +* +* RETURNS: +* FSUCCESS : Operation was successful +* FINVALID_PARAMETER : Invalid argumetns +* FERROR : Error while posting +* FINSUFFICIENT_RESOURCES : Insufficient resource +* +* Environment : User Mode +* +* NOTES: +*/ + +typedef +FSTATUS (UMADT_POSTSEND)( + IN MADT_HANDLE serviceHandle, + IN MadtStruct *mad, + IN MadAddrStruct *destAddr + ); +IBA_API UMADT_POSTSEND iba_umadt_post_send; + +/* +* PostRecv +* +* DESCRIPTION : +* +* This routine informs the kernen mode component to post additional receive +* buffers on the Queue pair described by the service handle +* +* This routine may perform a kernel mode context switch. +* +* PARAMETERS : +* +* INPUTS +* serviceHandle : The handle got in Register Call +* +* OUTPUTS: +* None +* +* RETURNS: +* FSUCCESS : Operation was successful +* FINVALID_PARAMETER : Invalid argumetns +* FERROR : Error while posting +* FINSUFFICIENT_RESOURCES : Insufficient resource +* +* Environment : User Mode +* +* NOTES: +*/ + +typedef +FSTATUS (UMADT_POSTRECV)( + IN MADT_HANDLE serviceHandle + ); +IBA_API UMADT_POSTRECV iba_umadt_post_recv; + +/* +* PollForSendCompletion +* +* DESCRIPTION : +* +* This routine polls for any send completion mads. +* This routine will not perform a kernel mode context switch. +* +* +* PARAMETERS : +* INPUTS : +* serviceHandle : The handle got in Register Call +* +* OUTPUTS: +* mad : MAD info +* destAddr : MadAddrStruct info +* +* RETURNS: +* FSUCCESS : Operation was successful +* FINVALID_PARAMETER : Invalid arguments +* FNOT_FOUND : No more to packets +* +* Environment : User Mode +* +* NOTES: +*/ + +typedef +FSTATUS (UMADT_POLLFORSENDCOMPLETION)( + IN MADT_HANDLE serviceHandle, + OUT MadtStruct **mad, + OUT MadWorkCompletion **ppWorkCompInfo + ); +IBA_API UMADT_POLLFORSENDCOMPLETION iba_umadt_poll_send_compl; + +/* +* PollForRecvCompletion +* +* DESCRIPTION : +* +* This routine polls and gets the receive completion mads. +* This routine will not perform a kernel mode context switch. +* +* +* PARAMETERS : +* +* INPUTS : +* serviceHandle : The handle got in Register Call +* +* OUTPUTS: +* mad : MAD info +* destAddr : MadAddrStruct info +* +* RETURNS: +* FSUCCESS : Operation was successful +* FINVALID_PARAMETER : Invalid argumetns +* FNOT_FOUND : No more to packets +* +* Environment : User Mode +* +* NOTES: +*/ + +typedef +FSTATUS (UMADT_POLLFORRECVCOMPLETION)( + IN MADT_HANDLE serviceHandle, + OUT MadtStruct **mad, + OUT MadWorkCompletion **ppWorkCompInfo + ); +IBA_API UMADT_POLLFORRECVCOMPLETION iba_umadt_poll_recv_compl; + + +/* +* PollForEvent +* +* DESCRIPTION : +* +* This routine gets the eventrecord +* This routine will not perform a kernel mode context switch. +* +* +* PARAMETERS : +* +* INPUTS : +* serviceHandle : The handle got in Register Call +* +* OUTPUTS: +* eventRecord : MadtEventRecordStruct +* +* RETURNS: +* FSUCCESS : Operation was successful +* FINVALID_PARAMETER : Invalid argumetns +* FNOT_FOUND : No more to packets +* +* Environment : User Mode +* +* NOTES: +*/ + +typedef +FSTATUS (UMADT_POLLFOREVENT)( + IN MADT_HANDLE serviceHandle, + OUT MadtEventRecordStruct *eventRecord + ); +/* not yet implemented */ +IBA_API UMADT_POLLFOREVENT iba_umadt_poll_event; + + +/* +* WaitForAnyCompletion +* +* DESCRIPTION : +* +* Blocks on an OS sync objects until a completion event occurs. +* This routine will not perform a kernel mode context switch. +* +* +* PARAMETERS : +* +* INPUTS : +* serviceHandle : The handle got in Register Call +* completionType : Bit map identifying the set of completion to wait on +* timeout : Time in ms to wait for an event +* +* OUTPUTS: +* None +* +* RETURNS: +* FSUCCESS : Operation was successful +* FTIMEOUT : Operation timedout +* FNOT_DONE : Operation terminated by signal +* +* Environment : User Mode +* +* NOTES: +*/ + +typedef +FSTATUS (UMADT_WAITFORANYCOMPLETION)( + IN MADT_HANDLE serviceHandle, + IN uint32 completionType, + IN uint32 timeout + ); +IBA_API UMADT_WAITFORANYCOMPLETION iba_umadt_wait_any_compl; + + +/* +* QueryOsSyncObject +* +* DESCRIPTION : +* +* This routine Queries the OS Specific synchronization object. +* This routine will not perform a kernel mode context switch. +* +* +* PARAMETERS : +* INPUTS : +* serviceHandle : The handle got in Register Call +* completionType : Bit map identifies the wait object to retrive +* +* OUTPUTS: +* syncType : Type of OS specific sync object +* syncObject : OS specific sync object +* +* RETURNS: +* FSUCCESS : Operation was successful +* FINVALID_PARAMETER : Invalid argumetns +* +* Environment : User Mode +* +* NOTES: +*/ + +typedef +FSTATUS (UMADT_QUERYOSSYNCOBJECT)( + IN MADT_HANDLE serviceHandle, + IN uint32 CompletionType, + OUT uint32 SyncType, + OUT void * syncObject + ); +/* not yet implemented */ +IBA_API UMADT_QUERYOSSYNCOBJECT iba_umadt_query_sync_object; + + +/* +* Deregister +* +* DESCRIPTION : +* +* This routine deregisters an agent or a manager associated with the +* service handle. +* This routine may be expected to perform a kernel mode context switch +* +* PARAMETERS : +* INPUTS : +* serviceHandle : The handle got in Register Call +* +* OUTPUTS: +* None +* +* RETURNS: +* FSUCCESS : Operation was successful +* FINVALID_PARAMETER : Invalid argumetns +* +* Environment : User Mode +* +* NOTES: +*/ + +typedef +FSTATUS (UMADT_DEREGISTER)( + IN MADT_HANDLE serviceHandle + ); +IBA_API UMADT_DEREGISTER iba_umadt_deregister; + +static __inline void +GetSmiAddrFromPath( IN const IB_PATH_RECORD *pPathRecord, + OUT MadAddrStruct *pAddrInfo + ) +{ + pAddrInfo->DestLid = pPathRecord->DLID; + pAddrInfo->PathBits = (uint8)(pPathRecord->SLID & IB_PATHBITS_MASK); + pAddrInfo->StaticRate = pPathRecord->Rate; + pAddrInfo->AddrType.Smi.SourceLid = pPathRecord->SLID; +} + +static __inline void +GetGsiAddrFromPath( IN const IB_PATH_RECORD *pPathRecord, + IN uint32 RemoteQPN, + IN IB_Q_KEY RemoteQkey, + OUT MadAddrStruct *pAddrInfo + ) +{ + pAddrInfo->DestLid = pPathRecord->DLID; + pAddrInfo->PathBits = (uint8)(pPathRecord->SLID & IB_PATHBITS_MASK); + pAddrInfo->StaticRate = pPathRecord->Rate; + pAddrInfo->AddrType.Gsi.RemoteQpNumber = RemoteQPN; + pAddrInfo->AddrType.Gsi.RemoteQkey= RemoteQkey; + pAddrInfo->AddrType.Gsi.ServiceLevel = pPathRecord->u2.s.SL; + pAddrInfo->AddrType.Gsi.PKey = pPathRecord->P_Key; + pAddrInfo->AddrType.Gsi.GlobalRoute = (pPathRecord->u1.s.HopLimit > 1); + pAddrInfo->AddrType.Gsi.GRHInfo.DestGID = pPathRecord->DGID; + pAddrInfo->AddrType.Gsi.GRHInfo.FlowLabel = pPathRecord->u1.s.FlowLabel; + pAddrInfo->AddrType.Gsi.GRHInfo.HopLimit = (uint8)pPathRecord->u1.s.HopLimit; + pAddrInfo->AddrType.Gsi.GRHInfo.SrcGIDIndex = 0; /* BUGBUG assume 0 */ + pAddrInfo->AddrType.Gsi.GRHInfo.TrafficClass = pPathRecord->TClass; +} + +#if defined (__cplusplus) +}; +#endif + + +#endif /* _IBA_UMADT_H_ */ diff --git a/IbAccess/Common/Inc/vpd_export.h b/IbAccess/Common/Inc/vpd_export.h new file mode 100644 index 0000000..799ccb3 --- /dev/null +++ b/IbAccess/Common/Inc/vpd_export.h @@ -0,0 +1,140 @@ +/* BEGIN_ICS_COPYRIGHT1 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT1 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +/* Suppress duplicate loading of this file */ +#ifndef _IBA_VPD_EXPORT_H_ +#define _IBA_VPD_EXPORT_H_ + +/* This file defines the API which must be provided by a kernel mode Verbs + * provider driver. + */ +#if defined(VXWORKS) +#include "iba/vpi_export.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* this number changes each time the structure below changes + * it is used to verify the VPD is the same revision as IbAccess + */ +typedef enum { + VPD_INTERFACE_VERSION_NONE=0, + VPD_INTERFACE_VERSION_3=3, + VPD_INTERFACE_VERSION_4=4, + VPD_INTERFACE_VERSION_5=5, + VPD_INTERFACE_VERSION_6=6, + VPD_INTERFACE_VERSION_7=7, + VPD_INTERFACE_VERSION_8=8, + VPD_INTERFACE_VERSION_9=9, + VPD_INTERFACE_VERSION_10=10, + VPD_INTERFACE_VERSION_LATEST=10 +} VPD_INTERFACE_VERSION; + +typedef struct _VPD_KM_INTERFACE { + EUI64 CaGUID; + + VPI_OPENCA *OpenCA; + VPI_QUERYCA *QueryCA; + VPI_SETCOMPLETIONHANDLER *SetCompletionHandler; + VPI_SETASYNCEVENTHANDLER *SetAsyncEventHandler; + VPI_SETCACONTEXT *SetCAContext; + VPI_SETCAINTERNAL *SetCAInternal; + VPI_MODIFYCA *ModifyCA; + VPI_CLOSECA *CloseCA; + VPI_ALLOCATEPD2 *AllocatePD; + VPI_ALLOCATESQPPD *AllocateSqpPD; + VPI_FREEPD *FreePD; + VPI_ALLOCATERDD *AllocateRDD; + VPI_FREERDD *FreeRDD; + VPI_CREATEAV *CreateAV; + VPI_MODIFYAV *ModifyAV; + VPI_QUERYAV *QueryAV; + VPI_DESTROYAV *DestroyAV; + VPI_CREATEQP *CreateQP; + VPI_MODIFYQP *ModifyQP; + VPI_SETQPCONTEXT *SetQPContext; + VPI_QUERYQP *QueryQP; + VPI_DESTROYQP *DestroyQP; + VPI_CREATESPECIALQP *CreateSpecialQP; + VPI_ATTACHQPTOMULTICASTGROUP2 *AttachQPToMulticastGroup; + VPI_DETACHQPFROMMULTICASTGROUP2 *DetachQPFromMulticastGroup; + VPI_CREATECQ *CreateCQ; + VPI_RESIZECQ *ResizeCQ; + VPI_SETCQCONTEXT *SetCQContext; + VPI_SETCQCOMPLETIONHANDLER *SetCQCompletionHandler; + VPI_QUERYCQ *QueryCQ; + VPI_DESTROYCQ *DestroyCQ; + VPI_REGISTERMEMREGION *RegisterMemRegion; + VPI_REGISTERPHYSMEMREGION2 *RegisterPhysMemRegion; + VPI_REGISTERCONTIGPHYSMEMREGION2 *RegisterContigPhysMemRegion; + VPI_QUERYMEMREGION2 *QueryMemRegion; + VPI_DEREGISTERMEMREGION *DeregisterMemRegion; + VPI_MODIFYMEMREGION *ModifyMemRegion; + VPI_MODIFYPHYSMEMREGION2 *ModifyPhysMemRegion; + VPI_MODIFYCONTIGPHYSMEMREGION2 *ModifyContigPhysMemRegion; + VPI_REGISTERSHAREDMEMREGION2 *RegisterSharedMemRegion; + VPI_CREATEMEMWINDOW *CreateMemWindow; + VPI_QUERYMEMWINDOW *QueryMemWindow; + VPI_POSTMEMWINDOWBIND2 *PostMemWindowBind; + VPI_DESTROYMEMWINDOW *DestroyMemWindow; + VPI_POSTSEND2 *PostSend; + VPI_POSTRECV2 *PostRecv; + VPI_POLLCQ *PollCQ; + VPI_PEEKCQ *PeekCQ; + VPI_REARMCQ *RearmCQ; + VPI_REARMNCQ *RearmNCQ; + + /* Private interfaces for the SMA, PMA and CM */ + VPI_GETSETMAD *GetSetMad; + VPI_REGISTERCONNMGR *RegisterConnMgr; + + /* Private interface to the user-mode VP component */ + VPI_QUERYCA_PRIVATE_INFO *QueryCAPrivateInfo; /* Optional */ + VPI_QUERYPD_PRIVATE_INFO *QueryPDPrivateInfo; /* Optional */ + VPI_QUERYQP_PRIVATE_INFO *QueryQPPrivateInfo; /* Optional */ + VPI_QUERYCQ_PRIVATE_INFO *QueryCQPrivateInfo; /* Optional */ + VPI_QUERYAV_PRIVATE_INFO *QueryAVPrivateInfo; /* Optional */ + + /* other new interfaces */ + VPI_POLLANDREARMCQ2 *PollAndRearmCQ; /* Optional */ + + VPI_QUERYCA2 *QueryCA2; + +} VPD_KM_INTERFACE; + +#ifdef __cplusplus +}; +#endif + +#endif /* defined(VXWORKS) */ + +#endif /* _IBA_VPD_EXPORT_H_ */ diff --git a/IbAccess/Common/Inc/vpi.h b/IbAccess/Common/Inc/vpi.h new file mode 100644 index 0000000..c019e36 --- /dev/null +++ b/IbAccess/Common/Inc/vpi.h @@ -0,0 +1,1387 @@ +/* BEGIN_ICS_COPYRIGHT3 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT3 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +#ifndef _IBA_VPI_H_ +#define _IBA_VPI_H_ + +/* + * This header file declares Common IB types used throughout IB verbs + * and Service Level Interface + */ + +#include "iba/stl_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/* + * Access controls. Applies to QPs, memory regions and memory windows. + * Selectors permit the indicated operation or access mode. + */ + +typedef union _IB_ACCESS_CONTROL { + uint16 AsUINT16; + struct _IB_ACCESS_CONTROL_S { + uint16 AtomicOp: 1; /* QP only - enable atomics (not on UC QP) */ + uint16 RdmaWrite: 1; /* Enable Remote RDMA Write */ + uint16 RdmaRead: 1; /* Enable Remote RDMA Read (not on UC QP) */ + uint16 LocalWrite: 1; /* MR/MW only, Enable HFI to write */ + uint16 Reserved: 11; + uint16 MWBindable: 1; /* MR only, can a MW be bound to MR */ + } s; +} IB_ACCESS_CONTROL; + + +/* + * Queue pair definitions and data types + */ + +/* + * Queue pair transport service and special types + */ + +typedef enum { + QPTypeReliableConnected, + QPTypeUnreliableConnected, + QPTypeReliableDatagram, + QPTypeUnreliableDatagram, + QPTypeSMI, + QPTypeGSI, +#if defined(INCLUDE_STLEEP) + QPTypeSTLEEP, +#endif + QPTypeRawDatagram, + QPTypeRawIPv6, + QPTypeRawEthertype +} IB_QP_TYPE; + +/* convert IB_QP_TYPE to a string */ +IBA_API const char* iba_qp_type_msg(IB_QP_TYPE qp_type); + +/* + * Queue pair states and state transitions + * used in Modify QP and Query QP operations + */ + +typedef enum { + QPStateNoTransition, + QPStateReset, /* After QP creation */ + QPStateInit, /* Posting of RecvQ WRs enabled */ + QPStateReadyToRecv, /* RecvQ active */ + QPStateReadyToSend, /* QP fully active */ + QPStateSendQDrain, /* Suspend SendQ processing */ + QPStateSendQError, /* SendQ in error - recovery possible depending upon */ + /* conditions. */ + QPStateError /* QP in failed state - must reset to proceed */ +} IB_QP_STATE; + +/* convert IB_QP_STATE to a string */ +IBA_API const char* iba_qp_state_msg(IB_QP_STATE qp_state); + +/* + * Completion Flags + * + * IB_COMPL_CNTL_FLAGS are or'ed into CompletionFlags + * These allow a QP to indicate if completions should be controllable per + * Work Request or should be unconditionally provided for all Work Requests. + * When a flag is set, the WR has control, when not set, all WR's will + * result in Completion Queue Entries. + * Regardless of the setting, failed Work Requests always generate a completion + * + * This replaced the old SendSignaledCompletions boolean_t. + * Provided application used TRUE/FALSE or 0/1 in SendCompletionFlags + * (which was a boolean_t), this will be binary and source code backward + * compatible. + * Applications which only set TRUE/FALSE will never set IB_COMPL_CNTL_RECV + * and will never see it returned + */ +typedef enum { + IB_COMPL_CNTL_SEND = 0x01U, /* Enables per WR signaled completions on SendQ */ + IB_COMPL_CNTL_RECV = 0x02U /* Enables per WR signaled completions on RecvQ. */ + /* invalid to set if */ + /* ! CA_IS_UNSIGNALED_RECV_SUPPORTED */ +} IB_COMPL_CNTL_FLAGS; + +/* + * States in the automatic path migration state machine. A verbs consumer may + * request transition to the migrated and rearm states. + */ + +typedef enum { + APMStateNoTransition, + APMStateMigrated, /* After QP creation */ + APMStateRearm, /* Loads specified alternate path address vector */ + /* to QP context. */ + APMStateArmed /* QP enabled for migration to alternate path */ +} IB_QP_APM_STATE; + +/* convert IB_QP_APM_STATE to a string */ +IBA_API const char* iba_qp_apm_state_msg(IB_QP_APM_STATE qp_apm_state); + +/* + * Global Routing details for use in Address vectors + * ultimately used to build GRH packet headers in packets which + * traverse IB routers between IB subnets + * SrcGIDIndex is always local port, DestGID is always remote port + */ +typedef struct _GLOBALROUTE_INFO { + IB_GID DestGID; /* Dest GID */ + uint32 FlowLabel; + uint8 SrcGIDIndex; /* Index into the local port's GID Table */ + uint8 HopLimit; + uint8 TrafficClass; +} IB_GLOBAL_ROUTE_INFO; + +/* + * The address vector used when creating address vector handles and passed to + * CreateQP for RC & UC transports. + */ +typedef struct _IB_ADDRESS_VECTOR { + EUI64 PortGUID; /* Used only on CreateAV, ModifyAV, QueryAV */ +#if INCLUDE_16B + STL_LID DestLID; /* Destination's LID */ +#else + IB_LID DestLID; /* Destination's LID */ +#endif + IB_PATHBITS PathBits; /* Combines with the base SrcLID to indicate */ + /* SrcLID for pkts */ + IB_SL ServiceLevel; + uint8 StaticRate; /* The maximum static rate supported by this */ + /* endpoint, enum IB_STATIC_RATE */ + boolean GlobalRoute; /* If true send Global Route header and the */ + /* GlobalRouteInfo structure is valid. */ + IB_GLOBAL_ROUTE_INFO GlobalRouteInfo; +} IB_ADDRESS_VECTOR; + +/* limit for RetryCount in QP (and CM messages which contain it) */ +#define IB_MAX_RETRY_COUNT 7 +/* limit for RnrRetryCount in QP (and CM messages which contain it) */ +#define IB_MAX_RNR_RETRY_COUNT 6 /* max which is not infinite */ +#define IB_RNR_RETRY_COUNT_INFINITE 7 /* retry forever */ + +/* Flags to indicate which attributes are given during queue pair Modify */ +typedef enum { + /* first set during create */ + IB_QP_ATTR_SENDQDEPTH =0x00000001U, + IB_QP_ATTR_RECVQDEPTH =0x00000002U, + IB_QP_ATTR_SENDDSLISTDEPTH =0x00000004U, + IB_QP_ATTR_RECVDSLISTDEPTH =0x00000008U, + /* first set in Reset->Init */ + IB_QP_ATTR_PORTGUID =0x00000010U, + IB_QP_ATTR_QKEY =0x00000020U, + IB_QP_ATTR_PKEYINDEX =0x00000040U, + IB_QP_ATTR_ACCESSCONTROL =0x00000080U, + /* first set in Init->RTR */ + IB_QP_ATTR_RECVPSN =0x00000100U, + IB_QP_ATTR_DESTQPNUMBER =0x00000200U, + IB_QP_ATTR_PATHMTU =0x00000400U, + IB_QP_ATTR_DESTAV =0x00000800U, + IB_QP_ATTR_RESPONDERRESOURCES =0x00001000U, + IB_QP_ATTR_MINRNRTIMER =0x00002000U, + /* first optional in Init->RTR */ + IB_QP_ATTR_ALTPORTGUID =0x00004000U, + IB_QP_ATTR_ALTDESTAV =0x00008000U, + IB_QP_ATTR_ALTPKEYINDEX =0x00010000U, + /* first set in RTR->RTS */ + IB_QP_ATTR_SENDPSN =0x00020000U, + IB_QP_ATTR_INITIATORDEPTH =0x00040000U, + IB_QP_ATTR_LOCALACKTIMEOUT =0x00080000U, + IB_QP_ATTR_RETRYCOUNT =0x00100000U, + IB_QP_ATTR_RNRRETRYCOUNT =0x00200000U, + IB_QP_ATTR_FLOWCONTROL =0x00400000U, + /* first optional in RTR->RTS */ + IB_QP_ATTR_APMSTATE =0x00800000U, + IB_QP_ATTR_ALTLOCALACKTIMEOUT =0x01000000U, + /* first set in RTS->SQD */ + IB_QP_ATTR_ENABLESQDASYNCEVENT =0x02000000U +} IB_QP_ATTRS; + +/* permitted Attributes in Modify per QP type */ +#define QP_ATTR_UD \ + ((IB_QP_ATTRS) \ + ( IB_QP_ATTR_SENDQDEPTH | IB_QP_ATTR_RECVQDEPTH \ + | IB_QP_ATTR_SENDDSLISTDEPTH | IB_QP_ATTR_RECVDSLISTDEPTH \ + | IB_QP_ATTR_PORTGUID | IB_QP_ATTR_QKEY | IB_QP_ATTR_PKEYINDEX \ + | IB_QP_ATTR_SENDPSN \ + | IB_QP_ATTR_ENABLESQDASYNCEVENT )) + /* TBD BUGBUG - SMI and GSI should not have PKey Index */ +#define QP_ATTR_SMI \ + ((IB_QP_ATTRS) \ + ( IB_QP_ATTR_SENDQDEPTH | IB_QP_ATTR_RECVQDEPTH \ + | IB_QP_ATTR_SENDDSLISTDEPTH | IB_QP_ATTR_RECVDSLISTDEPTH \ + | IB_QP_ATTR_QKEY | IB_QP_ATTR_PKEYINDEX \ + | IB_QP_ATTR_SENDPSN \ + | IB_QP_ATTR_ENABLESQDASYNCEVENT )) +#define QP_ATTR_GSI \ + ((IB_QP_ATTRS) \ + ( IB_QP_ATTR_SENDQDEPTH | IB_QP_ATTR_RECVQDEPTH \ + | IB_QP_ATTR_SENDDSLISTDEPTH | IB_QP_ATTR_RECVDSLISTDEPTH \ + | IB_QP_ATTR_QKEY | IB_QP_ATTR_PKEYINDEX \ + | IB_QP_ATTR_SENDPSN \ + | IB_QP_ATTR_ENABLESQDASYNCEVENT )) +#if defined(INCLUDE_STLEEP) +#define QP_ATTR_STLEEP \ + ((IB_QP_ATTRS) \ + ( IB_QP_ATTR_SENDQDEPTH | IB_QP_ATTR_RECVQDEPTH \ + | IB_QP_ATTR_SENDDSLISTDEPTH | IB_QP_ATTR_RECVDSLISTDEPTH \ + | IB_QP_ATTR_ENABLESQDASYNCEVENT )) +#endif +#define QP_ATTR_RD \ + ((IB_QP_ATTRS) \ + ( IB_QP_ATTR_SENDQDEPTH | IB_QP_ATTR_RECVQDEPTH \ + | IB_QP_ATTR_SENDDSLISTDEPTH | IB_QP_ATTR_RECVDSLISTDEPTH \ + | IB_QP_ATTR_QKEY | IB_QP_ATTR_ACCESSCONTROL \ + | IB_QP_ATTR_MINRNRTIMER \ + | IB_QP_ATTR_ENABLESQDASYNCEVENT )) +#define QP_ATTR_UC \ + ((IB_QP_ATTRS) \ + ( IB_QP_ATTR_SENDQDEPTH | IB_QP_ATTR_RECVQDEPTH \ + | IB_QP_ATTR_SENDDSLISTDEPTH | IB_QP_ATTR_RECVDSLISTDEPTH \ + | IB_QP_ATTR_PORTGUID | IB_QP_ATTR_PKEYINDEX \ + | IB_QP_ATTR_ACCESSCONTROL \ + | IB_QP_ATTR_RECVPSN | IB_QP_ATTR_DESTQPNUMBER | IB_QP_ATTR_PATHMTU \ + | IB_QP_ATTR_DESTAV \ + | IB_QP_ATTR_ALTPORTGUID | IB_QP_ATTR_ALTDESTAV | IB_QP_ATTR_ALTPKEYINDEX \ + | IB_QP_ATTR_SENDPSN | IB_QP_ATTR_APMSTATE \ + | IB_QP_ATTR_ENABLESQDASYNCEVENT )) +#define QP_ATTR_RC \ + ((IB_QP_ATTRS) \ + ( IB_QP_ATTR_SENDQDEPTH | IB_QP_ATTR_RECVQDEPTH \ + | IB_QP_ATTR_SENDDSLISTDEPTH | IB_QP_ATTR_RECVDSLISTDEPTH \ + | IB_QP_ATTR_PORTGUID | IB_QP_ATTR_PKEYINDEX \ + | IB_QP_ATTR_ACCESSCONTROL \ + | IB_QP_ATTR_RECVPSN | IB_QP_ATTR_DESTQPNUMBER | IB_QP_ATTR_PATHMTU \ + | IB_QP_ATTR_DESTAV | IB_QP_ATTR_RESPONDERRESOURCES \ + | IB_QP_ATTR_MINRNRTIMER \ + | IB_QP_ATTR_ALTPORTGUID | IB_QP_ATTR_ALTDESTAV | IB_QP_ATTR_ALTPKEYINDEX \ + | IB_QP_ATTR_SENDPSN | IB_QP_ATTR_INITIATORDEPTH \ + | IB_QP_ATTR_LOCALACKTIMEOUT | IB_QP_ATTR_RETRYCOUNT \ + | IB_QP_ATTR_RNRRETRYCOUNT | IB_QP_ATTR_FLOWCONTROL \ + | IB_QP_ATTR_APMSTATE | IB_QP_ATTR_ALTLOCALACKTIMEOUT \ + | IB_QP_ATTR_ENABLESQDASYNCEVENT )) + +#define QP_ATTR_RAWDG \ + ((IB_QP_ATTRS) \ + ( IB_QP_ATTR_SENDQDEPTH | IB_QP_ATTR_RECVQDEPTH \ + | IB_QP_ATTR_SENDDSLISTDEPTH | IB_QP_ATTR_RECVDSLISTDEPTH \ + | IB_QP_ATTR_QKEY | IB_QP_ATTR_PKEYINDEX \ + | IB_QP_ATTR_SENDPSN \ + | IB_QP_ATTR_ENABLESQDASYNCEVENT )) + +#define QP_ATTR_RAWIP \ + ((IB_QP_ATTRS) \ + ( IB_QP_ATTR_SENDQDEPTH | IB_QP_ATTR_RECVQDEPTH \ + | IB_QP_ATTR_SENDDSLISTDEPTH | IB_QP_ATTR_RECVDSLISTDEPTH \ + | IB_QP_ATTR_QKEY | IB_QP_ATTR_PKEYINDEX \ + | IB_QP_ATTR_SENDPSN \ + | IB_QP_ATTR_ENABLESQDASYNCEVENT )) + +#define QP_ATTR_RAWETH \ + ((IB_QP_ATTRS) \ + ( IB_QP_ATTR_SENDQDEPTH | IB_QP_ATTR_RECVQDEPTH \ + | IB_QP_ATTR_SENDDSLISTDEPTH | IB_QP_ATTR_RECVDSLISTDEPTH \ + | IB_QP_ATTR_QKEY | IB_QP_ATTR_PKEYINDEX \ + | IB_QP_ATTR_SENDPSN \ + | IB_QP_ATTR_ENABLESQDASYNCEVENT )) + +/* Manditory and optional attributes per QP state transition + * lists below when and'ed with attributes above per QP type + * yields the exact list of attributes for a given QP type and transition + */ +#define IB_QP_ANY_TO_RESET_MAND ((IB_QP_ATTRS)0) +#define IB_QP_ANY_TO_RESET_OPT ((IB_QP_ATTRS)0) + +#define IB_QP_RESET_TO_INIT_MAND \ + ((IB_QP_ATTRS) \ + ( IB_QP_ATTR_PORTGUID | IB_QP_ATTR_QKEY | IB_QP_ATTR_PKEYINDEX \ + | IB_QP_ATTR_ACCESSCONTROL )) +#define IB_QP_RESET_TO_INIT_OPT \ + ((IB_QP_ATTRS) \ + ( IB_QP_ATTR_SENDQDEPTH | IB_QP_ATTR_RECVQDEPTH \ + | IB_QP_ATTR_SENDDSLISTDEPTH | IB_QP_ATTR_RECVDSLISTDEPTH )) + +#define IB_QP_INIT_TO_INIT_MAND ((IB_QP_ATTRS)0) +#define IB_QP_INIT_TO_INIT_OPT \ + ((IB_QP_ATTRS) \ + ( IB_QP_ATTR_PORTGUID | IB_QP_ATTR_QKEY | IB_QP_ATTR_PKEYINDEX \ + | IB_QP_ATTR_ACCESSCONTROL \ + | IB_QP_ATTR_SENDQDEPTH | IB_QP_ATTR_RECVQDEPTH \ + | IB_QP_ATTR_SENDDSLISTDEPTH | IB_QP_ATTR_RECVDSLISTDEPTH )) + +#define IB_QP_INIT_TO_RTR_MAND \ + ((IB_QP_ATTRS) \ + ( IB_QP_ATTR_RECVPSN | IB_QP_ATTR_DESTQPNUMBER | IB_QP_ATTR_DESTAV \ + | IB_QP_ATTR_RESPONDERRESOURCES | IB_QP_ATTR_MINRNRTIMER \ + | IB_QP_ATTR_PATHMTU)) +#define IB_QP_INIT_TO_RTR_OPT \ + ((IB_QP_ATTRS) \ + ( IB_QP_ATTR_ALTDESTAV | IB_QP_ATTR_ALTPORTGUID \ + | IB_QP_ATTR_ALTPKEYINDEX \ + | IB_QP_ATTR_QKEY | IB_QP_ATTR_PKEYINDEX \ + | IB_QP_ATTR_ACCESSCONTROL \ + | IB_QP_ATTR_SENDQDEPTH | IB_QP_ATTR_RECVQDEPTH \ + | IB_QP_ATTR_SENDDSLISTDEPTH | IB_QP_ATTR_RECVDSLISTDEPTH )) + +#define IB_QP_RTR_TO_RTS_MAND \ + ((IB_QP_ATTRS) \ + ( IB_QP_ATTR_SENDPSN \ + | IB_QP_ATTR_INITIATORDEPTH \ + | IB_QP_ATTR_FLOWCONTROL | IB_QP_ATTR_LOCALACKTIMEOUT \ + | IB_QP_ATTR_RETRYCOUNT | IB_QP_ATTR_RNRRETRYCOUNT \ + )) +#define IB_QP_RTR_TO_RTS_OPT \ + ((IB_QP_ATTRS) \ + ( IB_QP_ATTR_APMSTATE | IB_QP_ATTR_ALTLOCALACKTIMEOUT \ + | IB_QP_ATTR_ACCESSCONTROL | IB_QP_ATTR_QKEY \ + | IB_QP_ATTR_ALTDESTAV | IB_QP_ATTR_ALTPORTGUID \ + | IB_QP_ATTR_ALTPKEYINDEX \ + | IB_QP_ATTR_MINRNRTIMER \ + | IB_QP_ATTR_SENDQDEPTH | IB_QP_ATTR_RECVQDEPTH \ + | IB_QP_ATTR_SENDDSLISTDEPTH | IB_QP_ATTR_RECVDSLISTDEPTH )) + +#define IB_QP_RTS_TO_RTS_MAND ((IB_QP_ATTRS)0) +#define IB_QP_RTS_TO_RTS_OPT \ + ((IB_QP_ATTRS) \ + ( IB_QP_ATTR_ACCESSCONTROL | IB_QP_ATTR_QKEY | IB_QP_ATTR_APMSTATE \ + | IB_QP_ATTR_ALTDESTAV | IB_QP_ATTR_ALTPORTGUID \ + | IB_QP_ATTR_ALTPKEYINDEX | IB_QP_ATTR_ALTLOCALACKTIMEOUT \ + | IB_QP_ATTR_MINRNRTIMER \ + | IB_QP_ATTR_SENDQDEPTH | IB_QP_ATTR_RECVQDEPTH \ + | IB_QP_ATTR_SENDDSLISTDEPTH | IB_QP_ATTR_RECVDSLISTDEPTH )) + +#define IB_QP_SQE_TO_RTS_MAND ((IB_QP_ATTRS)0) +#define IB_QP_SQE_TO_RTS_OPT \ + ((IB_QP_ATTRS) \ + ( IB_QP_ATTR_ACCESSCONTROL | IB_QP_ATTR_QKEY \ + | IB_QP_ATTR_MINRNRTIMER \ + | IB_QP_ATTR_SENDQDEPTH | IB_QP_ATTR_RECVQDEPTH \ + | IB_QP_ATTR_SENDDSLISTDEPTH | IB_QP_ATTR_RECVDSLISTDEPTH )) + +#define IB_QP_RTS_TO_SQD_MAND \ + ((IB_QP_ATTRS) \ + ( IB_QP_ATTR_ENABLESQDASYNCEVENT)) +#define IB_QP_RTS_TO_SQD_OPT ((IB_QP_ATTRS)0) + +#define IB_QP_SQD_TO_RTS_MAND ((IB_QP_ATTRS)0) +#define IB_QP_SQD_TO_RTS_OPT \ + ((IB_QP_ATTRS) \ + ( IB_QP_ATTR_DESTAV | IB_QP_ATTR_PORTGUID \ + | IB_QP_ATTR_RETRYCOUNT | IB_QP_ATTR_RNRRETRYCOUNT \ + | IB_QP_ATTR_FLOWCONTROL | IB_QP_ATTR_LOCALACKTIMEOUT \ + | IB_QP_ATTR_PATHMTU \ + | IB_QP_ATTR_ALTDESTAV | IB_QP_ATTR_ALTPORTGUID \ + | IB_QP_ATTR_ALTPKEYINDEX | IB_QP_ATTR_ALTLOCALACKTIMEOUT \ + | IB_QP_ATTR_APMSTATE | IB_QP_ATTR_RESPONDERRESOURCES \ + | IB_QP_ATTR_INITIATORDEPTH | IB_QP_ATTR_QKEY \ + | IB_QP_ATTR_PKEYINDEX | IB_QP_ATTR_ACCESSCONTROL \ + | IB_QP_ATTR_SENDQDEPTH | IB_QP_ATTR_RECVQDEPTH \ + | IB_QP_ATTR_SENDDSLISTDEPTH | IB_QP_ATTR_RECVDSLISTDEPTH \ + | IB_QP_ATTR_MINRNRTIMER)) + +#define IB_QP_ANY_TO_ERR_MAND ((IB_QP_ATTRS)0) +#define IB_QP_ANY_TO_ERR_OPT ((IB_QP_ATTRS)0) + +/* QP attributes for input to Create. */ +typedef struct _IB_QP_ATTRIBUTES_CREATE { + IB_QP_TYPE Type; /* RC, UC, RD, UD, RawD */ + IB_HANDLE SendCQHandle; /* Handle of CQ associated with SendQ */ + IB_HANDLE RecvCQHandle; /* Handle of CQ associated with RecvQ */ + IB_HANDLE PDHandle; /* Handle for Protection Domain */ + IB_HANDLE RDDHandle; /* Reliable Datagram Domain if RD QP */ + /* SendSignaledCompletions as a boolean is depricated */ + uint8 CompletionFlags;/* set bits in IB_COMPL_CNTL_FLAGS */ +#define SendSignaledCompletions CompletionFlags /* depricated */ + uint8 Reserved1; + uint16 Reserved2; + uint32 SendQDepth; /* Outstanding WRs permitted on SendQ */ + uint32 RecvQDepth; /* Outstanding WRs permitted on RecvQ */ + uint32 SendDSListDepth;/* Max depth of scatter/gather list */ + /* in a WR posted to SendQ */ + uint32 RecvDSListDepth;/* Max depth of scatter list for a WR */ + /* posted to RecvQ */ +} IB_QP_ATTRIBUTES_CREATE; + +/* QP attributes output by Create, Query and Modify */ +typedef struct _IB_QP_ATTRIBUTES_QUERY { + IB_QP_STATE State; /* Current QP state */ + boolean SendDraining; /* in SQD is Send Q still draining */ + uint8 Reserved1; + uint16 Reserved2; + /* first set during create */ + IB_QP_TYPE Type; /* RC, UC, RD, UD, RawD */ + uint32 QPNumber; + IB_HANDLE SendCQHandle; /* CQ Handle associated with SendQ */ + IB_HANDLE RecvCQHandle; /* CQ Handle associated with RecvQ */ + IB_HANDLE PDHandle; + IB_HANDLE RDDHandle; /* Reliable Datagram Domain if RD */ + /* SendSignaledCompletions as a boolean is depricated */ + uint8 CompletionFlags;/* set bits in IB_COMPL_CNTL_FLAGS */ +#define SendSignaledCompletions CompletionFlags /* depricated */ + uint8 Reserved3; + uint16 MaxInlineData; /* depricated, for VAPI compatibility */ + /* valid when SendDSListDepth is valid */ + uint32 Attrs; /* Flags to indicate the valid */ + /* attributes below. IB_QP_ATTRS */ + uint32 SendQDepth; /* Outstanding WRs permitted on SQ */ + uint32 RecvQDepth; /* Outstanding WRs permitted on RQ */ + uint32 SendDSListDepth;/* Max depth of scatter/gather list */ + /* in a WR posted to SendQ */ + uint32 RecvDSListDepth;/* Max depth of scatter list for a */ + /* WR posted to RecvQ */ + /* first set in Reset->Init */ + EUI64 PortGUID; /* QP is assigned to this port */ + uint16 PkeyIndex; /* Partition table entry in use */ + uint16 Reserved5; + IB_Q_KEY Qkey; /* Client-supplied key */ + IB_ACCESS_CONTROL AccessControl; + uint16 Reserved6; + /* first set in Init->RTR */ + uint32 RecvPSN; /* Expected PSN on receive */ + uint32 DestQPNumber; + uint8 PathMTU; /* an IB_MTU */ + uint8 Reserved7; + uint16 Reserved8; + IB_ADDRESS_VECTOR DestAV; /* Dest address vector for RC & UC */ + uint8 ResponderResources; /* Number of outstanding RDMA */ + /* Read & Atomic ops permitted by */ + /* this QP as responder */ + /* should be >= remote QPs */ + /* InitiatorDepth */ + uint8 MinRnrTimer; /* Receiver Not Ready NAK Timer */ + uint16 Reserved9; + /* first optional in Init->RTR */ + EUI64 AltPortGUID; /* Alternate path port */ + IB_ADDRESS_VECTOR AltDestAV; /* Alt path dest AV if RC */ + uint16 AltPkeyIndex; /* Alt path Partition table entry */ + uint16 Reserved10; + /* first set in RTR->RTS */ + uint32 SendPSN; /* Next PSN to transmit */ + uint8 InitiatorDepth; /* Number of outstanding RDMA */ + /* Read & Atomic which can be */ + /* outstanding with this QP */ + /* as a requestor/initiator */ + /* should be <= remote QPs */ + /* ResponderResources */ + uint8 LocalAckTimeout; + uint8 RetryCount; /* Sequence error retry count */ + uint8 RnrRetryCount; /* Receiver Not Ready retry count */ + boolean FlowControl; /* Does dest provide this endpoint */ + /* with end-to-end flow control */ + /* credits? */ + /* first optional in RTR->RTS */ + IB_QP_APM_STATE APMState; /* Current Automatic Path Migration */ + /* state. */ + uint8 AltLocalAckTimeout; + /* first set in RTS->SQD */ + boolean EnableSQDAsyncEvent; /* Only valid in SQD state */ +} IB_QP_ATTRIBUTES_QUERY; + +/* QP attributes input to Modify */ +typedef struct _IB_QP_ATTRIBUTES_MODIFY { + IB_QP_STATE RequestState; /* required */ + uint32 Attrs; /* Flags to indicate the supplied */ + /* attributes. IB_QP_ATTRS */ + /* only atttibutes below which have corresponding bit set */ + /* in Attrs will be processed. Others assumed to have undefined */ + /* value and will be ignored. Grouped by state 1st set in */ + + /* first set during create */ + uint32 SendQDepth; /* Outstanding WRs permitted on SQ */ + uint32 RecvQDepth; /* Outstanding WRs permitted on RQ */ + uint32 SendDSListDepth;/* Max depth of scatter/gather list */ + /* in a WR posted to SendQ */ + uint32 RecvDSListDepth;/* Max depth of scatter list */ + /* in a WR posted to RecvQ */ + /* first set in Reset->Init */ + EUI64 PortGUID; /* Port to use */ + IB_Q_KEY Qkey; + uint16 PkeyIndex; /* Partition table entry */ + IB_ACCESS_CONTROL AccessControl; + /* first set in Init->RTR */ + uint32 RecvPSN; /* Expected PSN on receive */ + uint32 DestQPNumber; + uint8 PathMTU; /* an IB_MTU */ + /* implicitly IB_MTU_256 for SMI/GSI */ + uint8 Reserved1; + uint16 Reserved2; + IB_ADDRESS_VECTOR DestAV; /* Dest AV for RC & UC */ + uint8 ResponderResources; /* for RC & RD */ + /* Number of outstanding RDMA */ + /* Read & Atomic ops permitted by */ + /* this QP as responder */ + /* should be >= remote QPs */ + /* InitiatorDepth */ + uint8 MinRnrTimer; /* Receiver Not Ready NAK Timer */ + /* for RC & UC only */ + uint16 Reserved3; + /* first optional in Init->RTR */ + EUI64 AltPortGUID; /* Alt path port */ + IB_ADDRESS_VECTOR AltDestAV; /* Alt path dest AV if RC */ + uint16 AltPkeyIndex; /* Alt path Partition */ + /* table entry to use */ + uint16 Reserved4; + /* first set in RTR->RTS */ + uint32 SendPSN; /* First PSN to transmit */ + uint8 InitiatorDepth; /* for RC & RD */ + /* Number of outstanding RDMA */ + /* Read & Atomic which can be */ + /* outstanding with this QP */ + /* as a requestor/initiator */ + /* should be <= remote QPs */ + /* ResponderResources */ + uint8 LocalAckTimeout;/* Local ACK timeout */ + uint8 RetryCount; /* Sequence error retry count */ + uint8 RnrRetryCount; /* Receiver Not Ready retry count */ + boolean FlowControl; /* Does dest provide this */ + /* endpoint with end-to-end */ + /* flow control credits? */ + /* first optional in RTR->RTS */ + IB_QP_APM_STATE APMState; /* Requested Auto Path Mig */ + /* state transition */ + uint8 AltLocalAckTimeout; + /* first set in RTS->SQD */ + boolean EnableSQDAsyncEvent; /* Async Event when QP */ + /* drained in SQD state */ +} IB_QP_ATTRIBUTES_MODIFY; + +/* + * Completion queue definitions and data types + */ + +/* + * Arms a completion queue for event generate on CQ update + */ + +typedef enum { + CQEventSelNextWC, /* The next work completion written to the CQ will */ + /* generate an event. */ + CQEventSelNextSolicited /* Only generates an event if the work completion */ + /* is for a received msg where the solicited event was */ + /* requested by the sender. */ +} IB_CQ_EVENT_SELECT; + + +/* + * Verbs consumer completion notification event and asynchronous event + * callbacks and associated data types. + */ + +/* + * Async event types. Generally the event type indicates the resource type + */ + +typedef enum { + AsyncEventQP = 1, + AsyncEventSendQ, + AsyncEventRecvQ, + AsyncEventCQ, + AsyncEventCA, + AsyncEventPort, /* Port moved to Active or non-active state */ + AsyncEventPathMigrated, /* APM has migrated QP to AlternatePath */ + AsyncEventEE, + AsyncEventEEPathMigrated +} IB_ASYNC_EVENT; + + + +/* + * Send queue async event codes + */ + +#define IB_AE_SQ_DOORBELL_OVRFLW 1 +#define IB_AE_SQ_WQE_ACCESS 2 /* local access violation */ +#define IB_AE_SQ_ERROR_STATE 3 +#define IB_AE_SQ_DRAIN 4 /* SendQ is drained when in SQD */ + +/* + * Recv queue async event codes + */ + +#define IB_AE_RQ_DOORBELL_OVRFLW 1 +#define IB_AE_RQ_WQE_ACCESS 2 /* local access violation */ +#define IB_AE_RQ_ERROR_STATE 3 +#define IB_AE_RQ_COMM_ESTABLISHED 4 /* 1st packet received in RTR */ +#define IB_AE_RQ_PATH_MIG_ERR 5 + +/* + * Completion queue async event codes + */ + +#define IB_AE_CQ_SW_ACCESS_INVALID_CQ 0 +#define IB_AE_CQ_HW_ACCESS_INVALID_CQ 1 +#define IB_AE_CQ_ACCESS_ERR IB_AE_CQ_HW_ACCESS_INVALID_CQ +#define IB_AE_CQ_PROT_INDEX_OB 2 +#define IB_AE_CQ_OVERRUN IB_AE_CQ_PROT_INDEX_OB +#define IB_AE_CQ_INVALID_TPT_ENTRY 3 +#define IB_AE_CQ_INVALID_PROT_DOMAIN 4 +#define IB_AE_CQ_NO_WRITE_ACCESS 5 + +/* EE async event codes */ +#define IB_AE_EE_ERROR_STATE 3 +#define IB_AE_EE_COMM_ESTABLISHED 4 /* 1st packet received in RTR */ +#define IB_AE_EE_PATH_MIG_ERR 5 + +/* IBTA Events are mapped as follows: + * IBTA Event EventType EventCode Context + * ---------------------------------------------------------------- + * Path Migrated PathMigrated 0 QP + * Path Mig Error RecvQ RQ_PATH_MIG_ERR QP + * Comm Established RecvQ RQ_COMM_ESTABLISHED QP + * Send Q Drained SendQ SQ_DRAIN QP + * CQ Access Error CQ CQ_ACCESS_ERR CQ + * CQ Overrun CQ CQ_OVERRUN CQ + * Local Q Cat. RecvQ RQ_ERROR_STATE QP + * Invalid Q Req RecvQ RQ_ERROR_STATE QP + * Local Q Acc Viol RecvQ RQ_WQE_ACCESS QP + * Local EE Cat. EE EE_ERROR_STATE EE + * EE Comm Est. EE EE_COMM_ESTABLISHED EE + * EE Path Migrated EEPathMigrated 0 EE + * EE Path Mig Err EE EE_PATH_MIG_ERR EE + * Local CA Cat. CA 0 None + * Port Active Port new port state Port Number + * Port Down Port new port state Port Number + * Other QP Error QP 0 QP + * + * Some QP errors are directed toward the RecvQ, RecvQ errors are also + * directed toward the CM to affect CEP state transitions + * + * Async event callbacks include the caller CA Context as an argument. + * In addition where indicated above, the EventRecord.Context has the + * caller context for the QP, CQ or EE. + */ + +/* + * Async event record format + */ +typedef struct _IB_EVENT_RECORD { + void *Context; /* Context assigned on resource open/create/set */ + /* context - QP, CQ, CA. */ + /* or for AsyncEventPort, 1 based port # */ + IB_ASYNC_EVENT EventType; + uint32 EventCode; /* Error or informational code specific to */ + /* resource generating async event. */ +} IB_EVENT_RECORD; + +/* convert IB_EVENT_RECORD to a string summarizing EventType/EventCode */ +IBA_API const char* iba_event_record_msg(IB_EVENT_RECORD *p_event); + +/* + * The completion event handler provided by the verbs consumer + */ + +typedef void +(*IB_COMPLETION_CALLBACK)( + IN void *CaContext, + IN void *CqContext + ); + +/* + * The asynchronous event handler provided by the verbs consumer + * data pointed to only valid during duration of call + */ + +typedef void +(*IB_ASYNC_EVENT_CALLBACK)( + IN void *CaContext, + IN IB_EVENT_RECORD *EventRecord + ); + + +/* + * Work request and work completion definitions and data types + */ + +/* + * Work request operation types + */ + +typedef enum { + WROpSend = 0, + WROpRdmaWrite, + WROpRecv, + WROpRdmaRead, + WROpMWBind, + WROpFetchAdd, + WROpCompareSwap, + WROpRecvUnsignaled /* When IB_COMPL_CNTL_RECV is set in QP CompletionFlags */ + /* this can be used to issue a Recv WR without */ + /* a completion */ + /* (For backward compatibility reasons the Recv */ + /* WR does not have an Options field) */ +} IB_WR_OP; + +/* convert IB_WR_OP to a string */ +IBA_API const char* iba_wr_op_msg(IB_WR_OP wr_op); + +/* + * Status codes found in work completions + */ + +typedef enum { + WRStatusSuccess, + WRStatusLocalLength, /* incoming RecvQ msg exceeded available data segs */ + /* the in RQ work request or max message for CA */ + /* outgoing SendQ msg exceeded max message for CA */ + WRStatusLocalOp, /* Internal QP consistency error */ + WRStatusLocalProtection,/* local Data Segment references invalid MR for */ + /* requested operation */ + WRStatusTransport, /* unknown transport error */ + WRStatusWRFlushed, /* work request was flushed before completing */ + WRStatusRemoteConsistency, + WRStatusMWBind, /* MW bind error, insufficient access rights */ + WRStatusRemoteAccess, /* remote mem access error on RDMA read/write or */ + /* atomic */ + WRStatusRemoteOp, /* local prot error on the remote RQ */ + WRStatusRemoteInvalidReq,/* remote endpt does not support this work req op */ + /* - too little buffers for new RDMA or Atomic */ + /* - RDMA length too large */ + /* - operation not supported by RQ */ + WRStatusSeqErrRetry, /* Sequence error retry limit exceeded */ + WRStatusRnRRetry, /* RnR NAK retry limit exceeded */ + WRStatusTimeoutRetry, /* Timeout error retry limit exceeded */ + WRStatusBadResponse, /* unexpected transport opcode returned */ + WRStatusInvalidLocalEEC,/* Invalid EE Context Number */ + WRStatusInvalidLocalEECState,/* Invalid operation for EE Context State */ + WRStatusInvalidLocalEECOp, /* internal EEC consistency error detected */ + WRStatusLocalRDDViolation, /* RDD for local QP doesn't match RDD */ + /* of remote EEC */ + WRStatusRemoteInvalidRDReq, /* remote rejected RD message */ + /* invalid QKey or RDD Violation */ + WRStatusLocalAccess, /* protection error on local data buffer */ + /* during processing of inbound RDMA Write w/immed */ + WRStatusRemoteAborted /* remote requestor aborted operation */ + /* - requester suspended */ + /* - requester moved QP to SQEr */ +} IB_WC_STATUS; + +/* convert IB_WC_STATE to a string */ +IBA_API const char* iba_wc_status_msg(IB_WC_STATUS wc_status); + +/* Pack the data segment structures, manually make sure multiple of 64 bits */ +#include "iba/public/ipackon.h" + +/* + * Each data segment is an element of a scatter/gather list and describes a + * local buffer. + */ + +typedef struct _IB_LOCAL_DATASEGMENT { + uint64 Address; + IB_L_KEY Lkey; + uint32 Length; +} PACK_SUFFIX IB_LOCAL_DATASEGMENT; + +/* + * This data segment describes the contiguous buffer on a remote endpoint + * which is the target of a read or write RDMA operation. + */ + +typedef struct _IB_REMOTE_DATASEGMENT { + uint64 Address; + IB_R_KEY Rkey; + uint32 Reserved; +} PACK_SUFFIX IB_REMOTE_DATASEGMENT; + +#include "iba/public/ipackoff.h" + +/* + * Options for send work queue requests. Also used on receive work queue + * completions to indicate the presence of immediate data or a solicited + * event. + */ + +typedef union _IB_SEND_OPTIONS { + uint16 AsUINT16; + struct _IB_SEND_OPTIONS_S { + uint16 Reserved1: 3; /* Must be zero */ + uint16 InlineData: 1; /* post as inline send or RDMA Write */ + /* L-Keys in DSList[] ignored */ + /* depricated, for VAPI */ + /* compatibility only */ + /* N/A for SMI/GSI nor Raw QPs */ + /* N/A for RdmaRead nor Atomics */ + uint16 ImmediateData: 1; /* N/A for RdmaRead nor Atomics */ + uint16 Fence: 1; /* only for RC and RD */ + uint16 SignaledCompletion: 1; /* Generate CQ entry on sendQ work */ + /* completion. */ + uint16 SolicitedEvent: 1; /* Generate solicited event at */ + /* destination. N/A for RdmaRead */ + /* nor Atomics */ +#if INCLUDE_16B + uint16 SendFMH: 1; /* Use 16b and FM Header for mad requests */ + uint16 Reserved2: 7; /* Must be zero */ +#else + uint16 Reserved2: 8; /* Must be zero */ +#endif + } s; +} IB_SEND_OPTIONS; + +/* + * Options for the bind operation + */ + +typedef union _IB_MW_BIND_OPTIONS { + uint16 AsUINT16; + struct _IB_MW_BIND_OPTIONS_S { + uint16 Reserved1: 5; /* Must be zero */ + uint16 Fence: 1; + uint16 SignaledCompletion: 1; /* Generate CQ entry on sendQ work */ + /* completion. */ + uint16 Reserved2: 9; /* Must be zero */ + } s; +} IB_MW_BIND_OPTIONS; + +/* + * The work request structure for all operations on the send and receive work + * queues. + */ + +/* this is depricated, use IB_WORK_REQ2 family of structures */ +typedef struct _IB_WORK_REQ { + uint64 WorkReqId; /* Consumer supplied value returned */ + /* on a work completion */ + uint32 DSListDepth;/* Number of data segments in */ + /* scatter/gather list. */ + IB_LOCAL_DATASEGMENT *DSList; /* Ptr to scatter/gather list */ + uint32 MessageLen; + IB_WR_OP Operation; + union _IB_WR_REQ_TYPE { + /* no additional information for Recv WQEs */ + struct _IB_SEND_CONNECTED { + uint32 ImmediateData; + IB_SEND_OPTIONS Options; + IB_REMOTE_DATASEGMENT RemoteDS; + } SendRC, SendUC; /* Send, RdmaRead, RdmaWrite */ + struct _IB_ATOMIC_RC { + IB_SEND_OPTIONS Options; + IB_REMOTE_DATASEGMENT RemoteDS; + uint64 SwapAddOperand; /* for CompareSwap or FetchAdd */ + uint64 CompareOperand; /* for CompareSwap only */ + } AtomicRC; /* CompareSwap, FetchAdd */ + struct _IB_SEND_UD { + uint32 ImmediateData; + IB_SEND_OPTIONS Options; + uint32 QPNumber; /* Dest QP number */ + IB_Q_KEY Qkey; + IB_HANDLE AVHandle; /* Handle to AV for dest */ + IB_P_KEY PkeyIndex; /* GSI only */ + } SendUD; /* Send */ + struct _IB_RECV_UD { + uint32 Reserved; + } RecvUD, RecvRC, RecvUC, RecvRD; + struct _IB_SEND_RD { /* not supported */ + uint32 ImmediateData; + IB_SEND_OPTIONS Options; + uint32 QPNumber; /* Dest QP number */ + IB_Q_KEY Qkey; + uint32 DestEECNumber; /* Dest EE Context number */ + IB_REMOTE_DATASEGMENT RemoteDS; + } SendRD; /* Send, RdmaRead, RdmaWrite */ + struct _IB_SEND_RAWD { + uint32 QPNumber; /* Dest QP number */ +#if INCLUDE_16B + STL_LID DestLID; /* Destination's Base LID */ +#else + IB_LID DestLID; /* Destination's Base LID */ +#endif + IB_PATHBITS PathBits; /* Combines with the base SrcLID to */ + /* determine SrcLID for pkts. */ + IB_SL ServiceLevel; /* For dest */ + uint8 SignaledCompletion:1; /* Generate CQ entry on sendQ work */ + /* completion. */ + uint8 SolicitedEvent:1; /* Generate solicited event at */ + /* destination. */ + uint8 StaticRate:6; /* The maximum static rate */ + /* enum IB_STATIC_RATE */ + uint16 EtherType; /* Ethernet type */ + } SendRawD; /* Send */ + struct _IB_MW_BIND_REQ { + IB_HANDLE MWHandle; + IB_R_KEY CurrentRkey; + IB_HANDLE MRHandle; + IB_LOCAL_DATASEGMENT MWBindSegment; + IB_ACCESS_CONTROL AccessControl; + IB_MW_BIND_OPTIONS Options; + IB_R_KEY NewRkey; + } MWBind; /* Bind */ + } Req; +} IB_WORK_REQ; + +/* Pack the work req structures so they can be overlaid, manually ensure + * natural alignment of all fields + */ +#include "iba/public/ipackon.h" + +/* supporting structures used in IB_WORK_REQ2 + * field names are upward compatible with IB_WORK_REQ, however have been + * reordered to optimize memory usage + */ +/* Send, RdmaRead, RdmaWrite for UC or RC QP */ +struct _IB_SEND_CONNECTED2 { + IB_SEND_OPTIONS Options; + uint16 Reserved1; + uint32 ImmediateData; + IB_REMOTE_DATASEGMENT RemoteDS; /* for RdmaRead/RdmaWrite only */ +} PACK_SUFFIX; +/* CompareSwap, FetchAdd for RC QP */ +struct _IB_ATOMIC_RC2 { + IB_SEND_OPTIONS Options; + uint16 Reserved1; + uint32 Reserved2; + IB_REMOTE_DATASEGMENT RemoteDS; + uint64 SwapAddOperand; /* for CompareSwap or FetchAdd */ + uint64 CompareOperand; /* for CompareSwap only */ +} PACK_SUFFIX; +/* Send for UD, SMI or GSI QP */ +struct _IB_SEND_UD2 { + IB_SEND_OPTIONS Options; + IB_P_KEY PkeyIndex; /* GSI only */ + uint32 ImmediateData; + uint32 QPNumber; /* Dest QP number */ + IB_Q_KEY Qkey; + IB_HANDLE AVHandle; /* Handle to AV for dest */ +} PACK_SUFFIX; +/* Send, RdmaRead, RdmaWrite for RD QP */ +struct _IB_SEND_RD2 { + IB_SEND_OPTIONS Options; + uint16 Reserved1; + uint32 ImmediateData; + uint32 QPNumber; /* Dest QP number */ + IB_Q_KEY Qkey; + uint32 DestEECNumber; /* Dest EE Context number */ + uint32 Reserved2; + IB_REMOTE_DATASEGMENT RemoteDS; /* for RdmaRead/RdmaWrite only */ +} PACK_SUFFIX; +/* CompareSwap, FetchAdd for RD QP */ +struct _IB_ATOMIC_RD2 { + IB_SEND_OPTIONS Options; + uint16 Reserved1; + uint32 QPNumber; /* Dest QP number */ + IB_Q_KEY Qkey; + uint32 DestEECNumber; /* Dest EE Context number */ + IB_REMOTE_DATASEGMENT RemoteDS; + uint64 SwapAddOperand; /* for CompareSwap or FetchAdd */ + uint64 CompareOperand; /* for CompareSwap only */ +} PACK_SUFFIX; +/* Send for Raw QP */ +struct _IB_SEND_RAWD2 { + uint32 QPNumber; /* Dest QP number */ +#if INCLUDE_16B + STL_LID DestLID; /* Destination's Base LID */ +#else + IB_LID DestLID; /* Destination's Base LID */ +#endif + IB_PATHBITS PathBits; /* Combines with the base SrcLID to */ + /* determine SrcLID for pkts. */ + IB_SL ServiceLevel; /* For dest */ + uint8 SignaledCompletion:1; /* Generate CQ entry on */ + /* SendQ work completion. */ + uint8 SolicitedEvent:1; /* Generate solicited event at */ + /* destination. */ + uint8 StaticRate:6;/* The maximum static rate */ + /* enum IB_STATIC_RATE */ + uint8 Reserved; + uint16 EtherType; /* Ethernet type */ +} PACK_SUFFIX; + +#if defined(INCLUDE_STLEEP) +/* Send for the STLEEP QP */ +struct _OPA_SEND_STLEEP2 { + IB_SEND_OPTIONS Options; +} PACK_SUFFIX; +#endif + +/* this family of structures allows for future addition of new fields as well + * as optimized memory usage by applications. The APIs accept a IB_WORK_REQ2 + * structure, however, an appropriate variation from the IB_WORK_REQ2_* below + * can be provided and cast. The variations below are all a subset of the main + * structure. The API will select the _IB_WR_REQ_TYPE in the union based + * on QP type and Operation. Use of additional fields in the individual REQ + * types is guided by Options selected. + * In the future the IB_WORK_REQ2 structure may have new Req fields added to the + * union or new fields may be added to individual request types. However + * binary compatibility will be maintained by only using fields indicated by + * the Options, QP Type and Operation. Applications must be careful to + * initialize the Operation and clear any unused or reserved bits in Options. + * Note with the exception of the new Next field, the field names have the same + * names as in IB_WORK_REQ, hence making it easier to migrate existing + * applications. + */ +typedef struct _IB_WORK_REQ2 { + struct _IB_WORK_REQ2 *Next; /* link to next WQE being posted + * allows for more efficient operation + * by posting multiple WQEs in 1 call + */ + IB_LOCAL_DATASEGMENT *DSList; /* Ptr to scatter/gather list */ + uint64 WorkReqId; /* Consumer supplied value returned */ + /* on a work completion */ + uint32 MessageLen; /* overall size of message */ + uint32 DSListDepth;/* Number of data segments in */ + /* scatter/gather list. */ + IB_WR_OP Operation; /* operation to perform */ + uint32 Reserved; /* 64 bit align Req union below */ + union _IB_WR_REQ_TYPE2 { + /* no additional information for Recv WQEs */ + struct _IB_SEND_CONNECTED2 SendRC, SendUC;/* Send,RdmaRead,RdmaWrite */ + struct _IB_ATOMIC_RC2 AtomicRC; /* CompareSwap, FetchAdd */ + struct _IB_SEND_UD2 SendUD; /* Send */ + struct _IB_SEND_RD2 SendRD; /* Send, RdmaRead, RdmaWrite */ + struct _IB_ATOMIC_RD2 AtomicRD; /* CompareSwap, FetchAdd */ + struct _IB_SEND_RAWD2 SendRawD; /* Send */ +#if defined(INCLUDE_STLEEP) + struct _OPA_SEND_STLEEP2 SendSTLEEP; /* Send */ +#endif + } PACK_SUFFIX Req; +} PACK_SUFFIX IB_WORK_REQ2; + +/* storage optimized subsets of IB_WORK_REQ2 */ + +/* receive WQE for any QP type */ +typedef struct _IB_WORK_REQ2_RECV { + struct _IB_WORK_REQ2 *Next; /* link to next WQE being posted + * allows for more efficient operation + * by posting multiple WQEs in 1 call + */ + IB_LOCAL_DATASEGMENT *DSList; /* Ptr to scatter/gather list */ + uint64 WorkReqId; /* Consumer supplied value returned */ + /* on a work completion */ + uint32 MessageLen; /* overall size of message */ + uint32 DSListDepth;/* Number of data segments in */ + /* scatter/gather list. */ + IB_WR_OP Operation; + /* no additional information for Recv WQEs */ +} PACK_SUFFIX IB_WORK_REQ2_RECV; + +/* Send, RdmaRead or RdmaWrite for RC or UC QP */ +typedef struct _IB_WORK_REQ2_RCUC_SEND { + struct _IB_WORK_REQ2 *Next; /* link to next WQE being posted + * allows for more efficient operation + * by posting multiple WQEs in 1 call + */ + IB_LOCAL_DATASEGMENT *DSList; /* Ptr to scatter/gather list */ + uint64 WorkReqId; /* Consumer supplied value returned */ + /* on a work completion */ + uint32 MessageLen; /* overall size of message */ + uint32 DSListDepth;/* Number of data segments in */ + /* scatter/gather list. */ + IB_WR_OP Operation; + uint32 Reserved; /* 64 bit align Req union below */ + union { + struct _IB_SEND_CONNECTED2 SendRC, SendUC;/* Send,RdmaRead,RdmaWrite */ + } PACK_SUFFIX Req; +} PACK_SUFFIX IB_WORK_REQ2_RCUC_SEND; + +/* any SendQ or RecvQ operation on a RC QP */ +typedef struct _IB_WORK_REQ2_RC { + struct _IB_WORK_REQ2 *Next; /* link to next WQE being posted + * allows for more efficient operation + * by posting multiple WQEs in 1 call + */ + IB_LOCAL_DATASEGMENT *DSList; /* Ptr to scatter/gather list */ + uint64 WorkReqId; /* Consumer supplied value returned */ + /* on a work completion */ + uint32 MessageLen; /* overall size of message */ + uint32 DSListDepth;/* Number of data segments in */ + /* scatter/gather list. */ + IB_WR_OP Operation; + uint32 Reserved; /* 64 bit align Req union below */ + union { + struct _IB_SEND_CONNECTED2 SendRC; /* Send, RdmaRead, RdmaWrite */ + struct _IB_ATOMIC_RC2 AtomicRC; /* CompareSwap, FetchAdd */ + /* no additional information for Recv WQEs */ + } PACK_SUFFIX Req; +} PACK_SUFFIX IB_WORK_REQ2_RC; + +/* any SendQ or RecvQ operation on a UD QP */ +typedef struct _IB_WORK_REQ2_UD { + struct _IB_WORK_REQ2 *Next; /* link to next WQE being posted + * allows for more efficient operation + * by posting multiple WQEs in 1 call + */ + IB_LOCAL_DATASEGMENT *DSList; /* Ptr to scatter/gather list */ + uint64 WorkReqId; /* Consumer supplied value returned */ + /* on a work completion */ + uint32 MessageLen; /* overall size of message */ + uint32 DSListDepth;/* Number of data segments in */ + /* scatter/gather list. */ + IB_WR_OP Operation; + uint32 Reserved; /* 64 bit align Req union below */ + union { + struct _IB_SEND_UD2 SendUD; /* Send */ + /* no additional information for Recv WQEs */ + } PACK_SUFFIX Req; +} PACK_SUFFIX IB_WORK_REQ2_UD; + +/* any SendQ or RecvQ operation on a UC QP */ +typedef struct _IB_WORK_REQ2_UC { + struct _IB_WORK_REQ2 *Next; /* link to next WQE being posted + * allows for more efficient operation + * by posting multiple WQEs in 1 call + */ + IB_LOCAL_DATASEGMENT *DSList; /* Ptr to scatter/gather list */ + uint64 WorkReqId; /* Consumer supplied value returned */ + /* on a work completion */ + uint32 MessageLen; /* overall size of message */ + uint32 DSListDepth;/* Number of data segments in */ + /* scatter/gather list. */ + IB_WR_OP Operation; + uint32 Reserved; /* 64 bit align Req union below */ + union { + struct _IB_SEND_CONNECTED2 SendUC;/* Send, RdmaWrite */ + /* no additional information for Recv WQEs */ + } PACK_SUFFIX Req; +} PACK_SUFFIX IB_WORK_REQ2_UC; + +/* Send on a RD QP */ +typedef struct _IB_WORK_REQ2_RD_SEND { + struct _IB_WORK_REQ2 *Next; /* link to next WQE being posted + * allows for more efficient operation + * by posting multiple WQEs in 1 call + */ + IB_LOCAL_DATASEGMENT *DSList; /* Ptr to scatter/gather list */ + uint64 WorkReqId; /* Consumer supplied value returned */ + /* on a work completion */ + uint32 MessageLen; /* overall size of message */ + uint32 DSListDepth;/* Number of data segments in */ + /* scatter/gather list. */ + IB_WR_OP Operation; + uint32 Reserved; /* 64 bit align Req union below */ + union { + struct _IB_SEND_RD2 SendRD; /* Send, RdmaRead, RdmaWrite */ + } PACK_SUFFIX Req; +} PACK_SUFFIX IB_WORK_REQ2_RD_SEND; + +/* any SendQ or RecvQ operation on a RD QP */ +typedef struct _IB_WORK_REQ2_RD { + struct _IB_WORK_REQ2 *Next; /* link to next WQE being posted + * allows for more efficient operation + * by posting multiple WQEs in 1 call + */ + IB_LOCAL_DATASEGMENT *DSList; /* Ptr to scatter/gather list */ + uint64 WorkReqId; /* Consumer supplied value returned */ + /* on a work completion */ + uint32 MessageLen; /* overall size of message */ + uint32 DSListDepth;/* Number of data segments in */ + /* scatter/gather list. */ + IB_WR_OP Operation; + uint32 Reserved; /* 64 bit align Req union below */ + union { + struct _IB_SEND_RD2 SendRD; /* Send, RdmaRead, RdmaWrite */ + struct _IB_ATOMIC_RD2 AtomicRD; /* CompareSwap, FetchAdd */ + /* no additional information for Recv WQEs */ + } PACK_SUFFIX Req; +} PACK_SUFFIX IB_WORK_REQ2_RD; + +/* any SendQ or RecvQ operation on a RAW QP */ +typedef struct _IB_WORK_REQ2_RAW { + struct _IB_WORK_REQ2 *Next; /* link to next WQE being posted + * allows for more efficient operation + * by posting multiple WQEs in 1 call + */ + IB_LOCAL_DATASEGMENT *DSList; /* Ptr to scatter/gather list */ + uint64 WorkReqId; /* Consumer supplied value returned */ + /* on a work completion */ + uint32 MessageLen; /* overall size of message */ + uint32 DSListDepth;/* Number of data segments in */ + /* scatter/gather list. */ + IB_WR_OP Operation; + uint32 Reserved; /* 64 bit align Req union below */ + union { + struct _IB_SEND_RAWD2 SendRawD; /* Send */ + /* no additional information for Recv WQEs */ + } PACK_SUFFIX Req; +} PACK_SUFFIX IB_WORK_REQ2_RAW; + +#if defined(INCLUDE_STLEEP) +/* any SendQ or RecvQ operation on the STLEEP QP */ +typedef struct _IB_WORK_REQ2_STLEEP { + struct _IB_WORK_REQ2 *Next; /* link to next WQE being posted + * allows for more efficient operation + * by posting multiple WQEs in 1 call + */ + IB_LOCAL_DATASEGMENT *DSList; /* Ptr to scatter/gather list */ + uint64 WorkReqId; /* Consumer supplied value returned */ + /* on a work completion */ + uint32 MessageLen; /* overall size of message */ + uint32 DSListDepth;/* Number of data segments in */ + /* scatter/gather list. */ + IB_WR_OP Operation; + uint32 Reserved; /* 64 bit align Req union below */ + union { + struct _OPA_SEND_STLEEP2 SendSTLEEP; /* Send */ + /* no additional information for Recv WQEs */ + } PACK_SUFFIX Req; +} PACK_SUFFIX IB_WORK_REQ2_STLEEP; +#endif + +#include "iba/public/ipackoff.h" + +/* + * Completion type indicating the local operation performed + */ + +typedef enum { + WCTypeSend = 0, /* SendQ */ + WCTypeRdmaWrite, /* SendQ */ + WCTypeRecv, /* RecvQ (WROpRecv or failed WROpRecvUnsignaled) */ + WCTypeRdmaRead, /* SendQ */ + WCTypeMWBind, /* SendQ */ + WCTypeFetchAdd, /* SendQ */ + WCTypeCompareSwap /* SendQ */ +} IB_WC_TYPE; + +/* convert IB_WC_TYPE to a string */ +IBA_API const char* iba_wc_type_msg(IB_WC_TYPE wc_type); + +typedef enum { + WCRemoteOpSend = 0, /* RecvQ remote did a send w/ or w/o immed */ + WCRemoteOpRdmaWrite /* RecvQ remote did RdmaWrite w/immed */ +} IB_WC_REMOTE_OP; + +/* convert IB_WC_REMOTE_OP to a string */ +IBA_API const char* iba_wc_remote_op_msg(IB_WC_REMOTE_OP wc_remote_op); + +/* + * Flags used to indicate conditions on completed receive work requests + */ + +typedef union _IB_RECV_FLAGS { + uint8 AsUINT8; + struct _IB_RECV_FLAGS_S { + uint8 GlobalRoute: 1; /* Global route header present in */ + /* consumer's data buffer. */ + uint8 Reserved: 7; + } s; +} IB_RECV_FLAGS; + +/* + * The work completion structure for all completed work requests + * + * This structure is a union to reduce overall size. Hence the caller + * must be aware of the QP type on receive completions in order to properly + * identify which fields in the union to use. + * + * The simple approach is to only put QPs of the same type on a given CQ + * (some Verbs drivers may force this limitation). + * + * An alternative is to use information in the WorkReqId (such as a session + * pointer, etc) to identify the QP type the completion is for. + * + * Note that information relevant to failed completions is mostly in common + * fields. The exception being the RemoteOp field for RC and UC recv failures. + * Hence there is no need for QP identification for most failures (such as + * WRStatusWRFlushed). + * + * if Status != WRStatusSuccess, only the following fields are guaranteed to + * be valid: WorkReqId, Status + */ + +typedef struct _IB_WORK_COMPLETION { + uint64 WorkReqId; /* Value supplied by the consumer on the WR */ + IB_WC_TYPE WcType; + IB_WC_STATUS Status; + uint32 Length; /* undefined on send completion for some HFIs */ + + /* the fields below are only defined on recv completions */ + union _IB_WC_REQ { + struct _IB_WC_RECV_CONNECTED { + IB_SEND_OPTIONS Options; /* Possible flags are ImmediateData */ + uint32 ImmediateData; + IB_WC_REMOTE_OP RemoteOp; + } RecvRC, RecvUC; + struct _IB_WC_RECV_UD { + IB_SEND_OPTIONS Options; /* Possible flags are ImmediateData */ + IB_RECV_FLAGS Flags; + uint32 ImmediateData; + uint32 SrcQPNumber; +#if INCLUDE_16B + STL_LID SrcLID; +#else + IB_LID SrcLID; +#endif + IB_P_KEY PkeyIndex; /* GSI only */ + IB_SL ServiceLevel; + IB_PATHBITS DestPathBits; + } RecvUD; + struct _IB_WC_RECV_RD { + IB_SEND_OPTIONS Options; /* Possible flags are ImmediateData */ + uint32 ImmediateData; + uint32 SrcQPNumber; + uint32 DestEECNumber; /* Dest EE Context number */ +#if INCLUDE_16B + STL_LID SrcLID; +#else + IB_LID SrcLID; +#endif + IB_SL ServiceLevel; + uint8 FreedResourceCount; + } RecvRD; + } Req; +} IB_WORK_COMPLETION; + + +/* + * Memory Region definitions + */ + +/* + * RegisterContigPhysMemRegion buffer list + */ + +typedef struct _IB_MR_PHYS_BUFFER { + uint64 PhysAddr; + uint64 Length; /* in bytes */ +} IB_MR_PHYS_BUFFER; + + +/* + * Modify Memory Region request type + */ + +typedef union _IB_MR_MODIFY_REQ { + uint16 AsUINT16; + struct _IB_MR_MODIFY_REQ_S { + uint16 Translation: 1; + uint16 ProtectionDomain: 1; + uint16 AccessControl: 1; + uint16 Reserved: 13; + } s; +} IB_MR_MODIFY_REQ; + +#define DEFAULT_MAX_AVS_PER_PD 256 /* default AV limit per PD if SDK3 API used */ + +#ifdef __cplusplus +}; +#endif + +#endif /* _IBA_VPI_H_ */ diff --git a/IbAccess/Common/Inc/vpi_export.h b/IbAccess/Common/Inc/vpi_export.h new file mode 100644 index 0000000..c0ee585 --- /dev/null +++ b/IbAccess/Common/Inc/vpi_export.h @@ -0,0 +1,2077 @@ +/* BEGIN_ICS_COPYRIGHT3 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT3 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +/* Suppress duplicate loading of this file */ +#ifndef _IBA_VPI_EXPORT_H_ +#define _IBA_VPI_EXPORT_H_ + +#include "iba/vpi.h" +#include "stl_types.h" +#include "stl_sm_priv.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* Verbs Provider interface. + * This is the interface provided by the access layer for use by kernel + * mode applications. + */ + +/* New drivers/applications should use the iba_* functions. + * They can now be called directly. + * In some cases there are not iba_* versions of the version 1 API + * in these cases the version 2 API for the given interface should be used. + */ + + +/* + * OpenCA/iba_open_ca + * + * Returns a handle to an open instance of a CA. The consumer may call this + * to retrieve a new open instance, and the number of open instances allowed + * is not fixed but is subject to available system resources. + * + * INPUTS: + * CaGUID - The Channel Adapter's EUI64 GUID identifier. + * CompletionCallback - Completion handler. One per open instance. + * AsyncEventCallback - Asynchronous Error handler. One per open instance. + * Context - Consumer supplied value to be returned on calls to the handlers + * to identify the associated CA to the consumer. + * + * OUTPUTS: + * CaHandle - Handle to the newly open instance of the CA. + * + * RETURNS: + * + */ + +typedef FSTATUS (VPI_OPENCA)( + IN EUI64 CaGUID, + IN IB_COMPLETION_CALLBACK CompletionCallback, + IN IB_ASYNC_EVENT_CALLBACK AsyncEventCallback, + IN void *Context, + OUT IB_HANDLE *CaHandle + ); +IBA_API VPI_OPENCA iba_open_ca; + +/* + * QueryCA/iba_query_ca + * + * Returns the capabilities of the CA and the Ports in the CA. + * + * INPUTS: + * CaHandle - Handle from a previous OpenCA + * + * OUTPUTS: + * CaAttributes - Where to put the attributes of the CA. + * The CaAttributes->PortAttributesList is where to store + * the port attributes. If NULL, this call will fail and + * will return the proper size needed in PortAttributesListSize. + * CaAttributes->PortAttributesListSize must indicate the + * size available at PortAttributesList. If too small, the call + * will fail and indicate the size needed via this field. + * Context - Consumer supplied context value + * + * RETURNS: + * FINSUFFICIENT_MEMORY - PortAttributesListSize too small + * ca attributes returned, but not port attributes + * FINVALID_PARAMETER - invalid argument + * FSUCCESS - ca and port attributes returned + * + */ + +typedef FSTATUS (VPI_QUERYCA)( + IN IB_HANDLE CaHandle, + OUT IB_CA_ATTRIBUTES *CaAttributes, + OUT void **Context + ); +IBA_API VPI_QUERYCA iba_query_ca; + +/* + * same as VPI_QUERYCA, but returns version #2 of the CA attributes. + */ +typedef FSTATUS (VPI_QUERYCA2)( + IN IB_HANDLE CaHandle, + OUT IB_CA_ATTRIBUTES2 *CaAttributes, + OUT void **Context + ); +IBA_API VPI_QUERYCA2 iba_query_ca2; + +/* + * SetCompletionHandler/iba_set_compl_handler + * + * Change the consumer-supplied completion handler for an open + * instance of the CA. + * + * INPUTS: + * CaHandle - Handle to an open instance of a CA. + * CompletionCallback - Completion handler. + * + * OUTPUTS: + * None. + * + * RETURNS: + * + */ + +typedef FSTATUS (VPI_SETCOMPLETIONHANDLER)( + IN IB_HANDLE CaHandle, + IN IB_COMPLETION_CALLBACK CompletionCallback + ); +IBA_API VPI_SETCOMPLETIONHANDLER iba_set_compl_handler; + +/* + * SetAsyncEventHandler/iba_set_async_event_handler + * + * Change the consumer-supplied asynchronous error handler for an open + * instance of the CA. + * + * INPUTS: + * CaHandle - Handle to an open instance of a CA. + * AsyncEventCallback - Async Error handler. + * + * OUTPUTS: + * None. + * + * RETURNS: + * + */ + +typedef FSTATUS (VPI_SETASYNCEVENTHANDLER)( + IN IB_HANDLE CaHandle, + IN IB_ASYNC_EVENT_CALLBACK AsyncEventCallback + ); +IBA_API VPI_SETASYNCEVENTHANDLER iba_set_async_event_handler; + +/* + * SetCAContext/iba_set_ca_context + * + * Change the consumer-supplied context value for an open instance of a CA. + * + * INPUTS: + * CaHandle - Handle to an open instance of a CA. + * Context - New context value. + * + * OUTPUTS: + * None. + * + * RETURNS: + * + */ + +typedef FSTATUS (VPI_SETCACONTEXT)( + IN IB_HANDLE CaHandle, + IN void *Context + ); +IBA_API VPI_SETCACONTEXT iba_set_ca_context; + +/*SetCAInternal + * + *mark a CA open instance as for internal stack use + * + * INPUTS: + * . CaHandle handle of the channel adapter + * + * OUTPUTS: + * None + * + * RETURNS: + * Status 'FSUCCESS' if instance updated appropriately + * else a relevant error status. + * + */ + +typedef FSTATUS (VPI_SETCAINTERNAL)( + IN IB_HANDLE CaHandle + ); +VPI_SETCAINTERNAL SetCAInternal; /* internal use only */ + +/* + * ModifyCA/iba_modify_ca + * + * Modifies CA attributes. + * + * INPUTS: + * CaHandle - Handle to an open instance of the CA. + * CaAttributes - new attribute settings + * data pointed to only used during duration of call + * + * OUTPUTS: + * None. + * + * RETURNS: + * + */ + +typedef FSTATUS (VPI_MODIFYCA)( + IN IB_HANDLE CaHandle, + IN IB_CA_ATTRIBUTES *CaAttributes + ); +IBA_API VPI_MODIFYCA iba_modify_ca; + +/*CloseCA/iba_close_ca + * + *Close the previously opened channel adapter. + * + * INPUTS: + * CaHandle handle of the channel adapter + * + * OUTPUTS: + * None + * + * RETURNS: + * Status 'FSUCCESS' if the specified channel adapter was + * closed successfully else a relevant error status. + * + */ +typedef FSTATUS (VPI_CLOSECA)( + IN IB_HANDLE CaHandle + ); +IBA_API VPI_CLOSECA iba_close_ca; + +/*AllocatePD2/iba_alloc_pd + * + *create a Protection Domain. + * + * INPUTS: + * . CaHandle handle of the channel adapter + * MaxAVs number of AV's user would like to be able to + * allocate within this PD + * + * OUTPUTS: + * PdHandle Pointer to the PD handle returned by this + * function. + * + * RETURNS: + * Status 'FSUCCESS' if the PD was created successfully + * else a relevant error status. + * + */ + +/* depricated, use ALLOCATEPD2 */ +typedef FSTATUS (VPI_ALLOCATEPD)( + IN IB_HANDLE CaHandle, + OUT IB_HANDLE *PdHandle + ); +VPI_ALLOCATEPD AllocatePD; /* internal use only, depricated */ + +/* Version2 of API, supports control on limit of Address Vectors in PD */ +typedef FSTATUS (VPI_ALLOCATEPD2)( + IN IB_HANDLE CaHandle, + IN uint32 MaxAVs, + OUT IB_HANDLE *PdHandle + ); +IBA_API VPI_ALLOCATEPD2 iba_alloc_pd; + +/* iba_alloc_sqp_pd + * + *create a Protection Domain for use by Special QPs. + *This PD will only be allowed to have Special QPs (no normal QPs) + *as such the hardware driver may be able to optimize handling of + *AVs and other resources + * + * INPUTS: + * . CaHandle handle of the channel adapter + * MaxAVs number of AV's user would like to be able to + * allocate within this PD + * + * OUTPUTS: + * PdHandle Pointer to the PD handle returned by this + * function. + * + * RETURNS: + * Status 'FSUCCESS' if the PD was created successfully + * else a relevant error status. + * + */ + +typedef FSTATUS (VPI_ALLOCATESQPPD)( + IN IB_HANDLE CaHandle, + IN uint32 MaxAVs, + OUT IB_HANDLE *PdHandle + ); +IBA_API VPI_ALLOCATESQPPD iba_alloc_sqp_pd; + +/*FreePD/iba_free_pd + * + *Destroy a previously created Protection Domain. + * + * INPUTS: + * PdHandle PD handle + * + * OUTPUTS: + * none + * RETURNS: + * Status 'FSUCCESS' if the PD was destroyed successfully + * else a relevant error status. + * + */ +typedef FSTATUS (VPI_FREEPD)( + IN IB_HANDLE PdHandle + ); +IBA_API VPI_FREEPD iba_free_pd; + +/* + * AllocateRDD/iba_alloc_rdd + * + * Allocates a Reliable Datagram Domain. + * + * INPUTS: + * CaHandle - Handle to an open instance of a CA. + * + * OUTPUTS: + * RddHandle - Handle to allocated RDD. + * + * RETURNS: + * + */ + +typedef FSTATUS (VPI_ALLOCATERDD)( + IN IB_HANDLE CaHandle, + OUT IB_HANDLE *RddHandle + ); +IBA_API VPI_ALLOCATERDD iba_alloc_rdd; + +/*FreeRDD/iba_free_rdd + * + *free a previously created RDD. + * + * INPUTS: + * RddHandle handle of the RDD + * + * OUTPUTS: + * None + * + * RETURNS: + * Status 'FSUCCESS' if the RDD was freed successfully + * else a relevant error status. + * + */ + +typedef FSTATUS (VPI_FREERDD)( + IN IB_HANDLE RddHandle + ); +IBA_API VPI_FREERDD iba_free_rdd; + +/*CreateAV/iba_create_av + * + *create an Address Vector. + * + * INPUTS: + * . CaHandle handle of the channel adapter + * PdHandle PD handle + * AddressVector pointer to the address vector structure. + * data pointed to only used during duration of call + * + * OUTPUTS: + * AvHandle Pointer to the AV handle returned by this + * function. + * + * RETURNS: + * Status 'FSUCCESS' if the Address Vector was created successfully + * else a relevant error status. + * + */ +typedef FSTATUS (VPI_CREATEAV)( + IN IB_HANDLE CaHandle, + IN IB_HANDLE PdHandle, + IN IB_ADDRESS_VECTOR *AddressVector, + OUT IB_HANDLE *AvHandle + ); +IBA_API VPI_CREATEAV iba_create_av; + +/*ModifyAV/iba_modify_av + * + *modify a previously created Address Vector. + * + * INPUTS: + * AvHandle AV handle. + * AddressVector pointer to the address vector + * structure + * data pointed to only used during duration of call + * + * OUTPUTS: none + * + * RETURNS: + * Status 'FSUCCESS' if the Address Vector was modified successfully + * else a relevant error status. + * + */ + +typedef FSTATUS (VPI_MODIFYAV)( + IN IB_HANDLE AvHandle, + IN IB_ADDRESS_VECTOR *AddressVector + ); +IBA_API VPI_MODIFYAV iba_modify_av; + + +/*QueryAV/iba_query_av + * + *query the attributes of a previously Address Vector. + * + * INPUTS: + * AvHandle AV handle. + * OUTPUTS: + * AddressVector pointer to the address vector + * structure + * + * RETURNS: + * Status 'FSUCCESS' if the Address Vector was queried successfully + * else a relevant error status. + * + */ + +typedef FSTATUS (VPI_QUERYAV)( + IN IB_HANDLE AvHandle, + OUT IB_ADDRESS_VECTOR *AddressVector, + OUT IB_HANDLE *PdHAndle + ); +IBA_API VPI_QUERYAV iba_query_av; + +/*DestroyAV/iba_destroy_av + * + *destroy a previously created Address Vector. + * + * INPUTS: + * . RddHandle handle of the RDD + * + * OUTPUTS: + * None + * + * RETURNS: + * Status 'FSUCCESS' if the Address vector was destroyed successfully + * else a relevant error status. + * + */ + +typedef FSTATUS (VPI_DESTROYAV)( + IN IB_HANDLE AvHandle + ); +IBA_API VPI_DESTROYAV iba_destroy_av; + +/* + * CreateQP/iba_create_qp + * + * Creates a Queue Pair. + * + * INPUTS: + * CaHandle - Handle to an open instance of the CA. + * QpCreateAttributes - Contains the values in the Create member of the + * attributes union to be used to configure the QP. + * data pointed to only used during duration of call + * Context - Consumer supplied value to be returned on when the asynchronous + * error callback is made for informational or error events on this QP. + * + * OUTPUTS: + * QpHandle - Handle to the QP returned. + * QpAttributes - Attributes upon completion of the operation residing in the + * the Query member of the attributes union. + * + * RETURNS: + * + */ + +typedef FSTATUS (VPI_CREATEQP)( + IN IB_HANDLE CaHandle, + IN IB_QP_ATTRIBUTES_CREATE *QpCreateAttributes, + IN void *Context, + OUT IB_HANDLE *QpHandle, + OUT IB_QP_ATTRIBUTES_QUERY *QpAttributes + ); +IBA_API VPI_CREATEQP iba_create_qp; + +/*ModifyQP/iba_modify_qp + * + *modify the attributes of a previously created queue pair. + * + * INPUTS: + * QpHandle queue pair handle. + * QpModifyAttributes Attributes to Modify + * data pointed to only used during duration of call + * OUTPUTS: + * QpAttributes Resulting attributes + * RETURNS: + * Status 'FSUCCESS' if the queue pair was modified successfully + * else a relevant error status. + * + */ + +typedef FSTATUS (VPI_MODIFYQP)( + IN IB_HANDLE QpHandle, + IN IB_QP_ATTRIBUTES_MODIFY *QpModifyAttributes, + OUT IB_QP_ATTRIBUTES_QUERY *QpAttributes OPTIONAL + ); +IBA_API VPI_MODIFYQP iba_modify_qp; + +/*ResetQp/iba_reset_qp + * + *reset a previously created queue pair. + *This is a simple wrapper for ib_modify_qp which sets up the QpAttributes + *to move the QP to the QPStateReset state + * + * INPUTS: + * QpHandle queue pair handle. + * OUTPUTS: + * QpAttributes Resulting attributes + * RETURNS: + * Status 'FSUCCESS' if the queue pair was modified successfully + * else a relevant error status. + * + */ +typedef FSTATUS (VPI_RESETQP)( + IN IB_HANDLE QpHandle, + OUT IB_QP_ATTRIBUTES_QUERY *QpAttributes OPTIONAL + ); +IBA_API VPI_RESETQP iba_reset_qp; + +/*InitQp/iba_init_qp + * + *initialize a previously created RC/UC/RD queue pair. + *This is a simple wrapper for ib_modify_qp which sets up the QpAttributes + *to move the QP to the QPStateInit state + * + * INPUTS: + * QpHandle queue pair handle. + * PortGuid port to use for QP + * PkeyIndex PKey Index + * AccessControl Access Control settings for QP + * Qkey RD QKey, set to 0 for RC/UC QPs + * OUTPUTS: + * QpAttributes Resulting attributes + * RETURNS: + * Status 'FSUCCESS' if the queue pair was modified successfully + * else a relevant error status. + * + */ +typedef FSTATUS (VPI_INITQP)( + IN IB_HANDLE QpHandle, + IN EUI64 PortGuid, + IN uint16 PkeyIndex, + IN IB_ACCESS_CONTROL AccessControl, + IN IB_Q_KEY Qkey OPTIONAL, + OUT IB_QP_ATTRIBUTES_QUERY *QpAttributes OPTIONAL + ); +IBA_API VPI_INITQP iba_init_qp; + +/*ReadyUdQp/iba_ready_ud_qp + * + *initialize a previously created UD queue pair. + *This is a simple wrapper for ib_modify_qp which sets up the QpAttributes + *to move the QP through the QPStateInit, RTR and RTS states + * + * INPUTS: + * QpHandle queue pair handle. + * PortGuid port to use for QP + * PkeyIndex PKey Index + * Qkey QKey + * OUTPUTS: + * QpAttributes Resulting attributes + * RETURNS: + * Status 'FSUCCESS' if the queue pair was modified successfully + * else a relevant error status. + * + */ +typedef FSTATUS (VPI_READYUDQP)( + IN IB_HANDLE QpHandle, + IN EUI64 PortGuid, + IN uint16 PkeyIndex, + IN IB_Q_KEY Qkey, + OUT IB_QP_ATTRIBUTES_QUERY *QpAttributes OPTIONAL + ); +IBA_API VPI_READYUDQP iba_ready_ud_qp; + +/*ReInitQp/iba_reinit_qp + * + *reset and re-initialize a previously created queue pair. + *This is a simple wrapper for ib_modify_qp which sets up the QpAttributes + *to move the QP to QPStateInit state via QPStateReset + *The present AccessControl, PortGuid, PKeyIndex and QKey settings + *are retained for the QP + * + * INPUTS: + * QpHandle queue pair handle. + * OUTPUTS: + * QpAttributes Resulting attributes + * RETURNS: + * Status 'FSUCCESS' if the queue pair was modified successfully + * else a relevant error status. + * + */ +typedef FSTATUS (VPI_REINITQP)( + IN IB_HANDLE QpHandle, + OUT IB_QP_ATTRIBUTES_QUERY *QpAttributes OPTIONAL + ); +IBA_API VPI_REINITQP iba_reinit_qp; + +/* + *ErrorQp/iba_error_qp + * + *move a previously created queue pair to QPStateError + *This is a simple wrapper for ib_modify_qp which sets up the QpAttributes + *to move the QP to the QPStateError state + * + * INPUTS: + * QpHandle queue pair handle. + * OUTPUTS: + * QpAttributes Resulting attributes + * RETURNS: + * Status 'FSUCCESS' if the queue pair was modified successfully + * else a relevant error status. + * + */ +typedef FSTATUS (VPI_ERRORQP)( + IN IB_HANDLE QpHandle, + OUT IB_QP_ATTRIBUTES_QUERY *QpAttributes OPTIONAL + ); +IBA_API VPI_ERRORQP iba_error_qp; + +/*SendQDrainQp/iba_sendq_drain_qp + * + *move a previously created queue pair to the QPStateSendQDrain state + *This is a simple wrapper for ib_modify_qp which sets up the QpAttributes + *to move the QP to the QPStateSendQDrain state + * + * INPUTS: + * QpHandle queue pair handle. + * EnableSQDAsyncEvent should async event be generated when Q has + * completed draining + * OUTPUTS: + * QpAttributes Resulting attributes + * RETURNS: + * Status 'FSUCCESS' if the queue pair was modified successfully + * else a relevant error status. + * + */ +typedef FSTATUS (VPI_SENDQDRAINQP)( + IN IB_HANDLE QpHandle, + IN boolean EnableSQDAsyncEvent, + OUT IB_QP_ATTRIBUTES_QUERY *QpAttributes OPTIONAL + ); +IBA_API VPI_SENDQDRAINQP iba_sendq_drain_qp; + +/* + * SetQPContext/iba_set_qp_context + * + * Changes the consumer-supplied context value for a QP to the supplied value. + * + * INPUTS: + * CaHandle - Handle to an open instance of a CA. + * Context - New context value. + * + * OUTPUTS: + * None. + * + * RETURNS: + * + */ + +typedef FSTATUS (VPI_SETQPCONTEXT)( + IN IB_HANDLE QpHandle, + IN void *Context + ); +IBA_API VPI_SETQPCONTEXT iba_set_qp_context; + + +/*QueryQP/iba_query_qp + * + *query the attributes of a specific queue pair. + * + * INPUTS: + * QpHandle queue pair handle. + * + * OUTPUTS: + * QpAttributes pointer to the queue pair attribute + * structure + * Context pointer to the pointer of the caller's context + * associated with the queue pair. The returned + * context value should be equal to the last value + * set by the user. + * RETURNS: + * Status 'FSUCCESS' if the queue pair attributes were retrieved + * successfully else a relevant error status. + * + */ + +typedef FSTATUS (VPI_QUERYQP)( + IN IB_HANDLE QpHandle, + OUT IB_QP_ATTRIBUTES_QUERY *QpAttributes, + OUT void **Context + ); +IBA_API VPI_QUERYQP iba_query_qp; + +/*DestroyQP/iba_destroy_qp + * + *destroy a previously created queue pair. + * + * INPUTS: + * QpHandle handle of the queue pair + * + * OUTPUTS: + * None + * + * RETURNS: + * Status 'FSUCCESS' if the queue pair was destroyed successfully + * else a relevant error status. + * + */ +typedef FSTATUS (VPI_DESTROYQP)( + IN IB_HANDLE QpHandle + ); +IBA_API VPI_DESTROYQP iba_destroy_qp; + +/* + * CreateSpecialQP/iba_create_special_qp + * + * Creates a special Queue Pair. + * + * INPUTS: + * CaHandle - Handle to an open instance of the CA. + * PortGUID - For SMI or GSI QPs the port must be given. This + * parameter is ignored for other Special QP types. + * QpCreateAttributes - Contains the values in the Create member of the + * attributes union to be used to configure the QP. + * data pointed to only used during duration of call + * Context - Consumer supplied value to be returned on when the asynchronous + * error callback is made for informational or error events on this QP. + * + * OUTPUTS: + * QpHandle - Handle to the QP returned. + * QpAttributes - Attributes upon completion of the operation residing in the + * the Query member of the attributes union. + * + * RETURNS: + * + */ + +typedef FSTATUS (VPI_CREATESPECIALQP)( + IN IB_HANDLE CaHandle, + IN EUI64 PortGUID, + IN IB_QP_ATTRIBUTES_CREATE *QpCreateAttributes, + IN void *Context, + OUT IB_HANDLE *QpHandle, + OUT IB_QP_ATTRIBUTES_QUERY *QpAttributes + ); +IBA_API VPI_CREATESPECIALQP iba_create_special_qp; + +/* + * AttachQPToMulticastGroup/iba_attach_qp_to_mcgroup + * + * Attach a UD QP the specified Multicast group, hence enabling receipt of + * multicast packets for the given group delivered to the CA to that QP. + * + * INPUTS: + * QpHandle - Handle to a UD QP + * McgDestLid - Multicast Group's DLID + * McgGID - Multicast Group's GID + * + * OUTPUTS: + * None. + * + * RETURNS: + * + */ + +typedef FSTATUS (VPI_ATTACHQPTOMULTICASTGROUP2)( + IN IB_HANDLE QpHandle, +#if INCLUDE_16B + IN STL_LID McgDestLid, +#else + IN IB_LID McgDestLid, +#endif + IN IB_GID McgGID + ); +IBA_API VPI_ATTACHQPTOMULTICASTGROUP2 iba_attach_qp_to_mcgroup; + +/* + * DetachQPFromMulticastGroup/iba_detach_qp_from_mcgroup + * + * Detach a UD QP from the specified Multicast group, hence disabling receipt of + * multicast packets for the given group delivered to the CA to that QP. + * + * INPUTS: + * QpHandle - Handle to a UD QP + * McgDestLid - Multicast Group's DLID + * McgGID - Multicast Group's GID + * + * OUTPUTS: + * None. + * + * RETURNS: + * + */ + +typedef FSTATUS (VPI_DETACHQPFROMMULTICASTGROUP2)( + IN IB_HANDLE QpHandle, +#if INCLUDE_16B + IN STL_LID McgDestLid, +#else + IN IB_LID McgDestLid, +#endif + IN IB_GID McgGID + ); +IBA_API VPI_DETACHQPFROMMULTICASTGROUP2 iba_detach_qp_from_mcgroup; + +/*CreateCQ/iba_create_cq + * + *create a completion queue. + * + * INPUTS: + * CaHandle handle of the channel adapter + * CqReqSize Required size of the CQ + * Context pointer to the caller's context. + * + * OUTPUTS: + * CqHandle pointer to the CQ handle returned by this + * function. + * CqSize pointer to the actual CQ size returned + * by this function. + * RETURNS: + * Status 'FSUCCESS' if the CQ was created successfully + * else a relevant error status. + * + */ +typedef FSTATUS (VPI_CREATECQ)( + IN IB_HANDLE CaHandle, + IN uint32 CqReqSize, + IN void *Context, + OUT IB_HANDLE *CqHandle, + OUT uint32 *CqSize + ); +IBA_API VPI_CREATECQ iba_create_cq; + +/*ResizeCQ/iba_resize_cq + * + * re size the CQ. + * + * INPUTS: + * . CqHandle handle of the completion queue + * CqReqSize required size of the CQ + * + * OUTPUTS: + * Cqsize pointer to the actual size returned by this + * function. + * + * RETURNS: + * Status 'FSUCCESS' if the QP was created successfully + * else a relevant error status. + * + * If FOVERRUN is returned, the new CQ size was not adequate to hold + * all the presently queued completions. In which case the CQ + * has been resized to the new size, however some completions + * have been discarded. + * + */ +typedef FSTATUS (VPI_RESIZECQ)( + IN IB_HANDLE CqHandle, + IN uint32 CqReqSize, + OUT uint32 *Cqsize + ); +IBA_API VPI_RESIZECQ iba_resize_cq; + +/* + * SetCQContext/iba_set_cq_context + * + * Changes the consumer-supplied context value for a CQ to the supplied value. + * + * INPUTS: + * CaHandle - Handle to an open instance of a CA. + * Context - New context value. + * + * OUTPUTS: + * + * None. + * + * RETURNS: + * + */ + +typedef FSTATUS (VPI_SETCQCONTEXT)( + IN IB_HANDLE CqHandle, + IN void *Context + ); +IBA_API VPI_SETCQCONTEXT iba_set_cq_context; + +/* + * iba_set_cq_compl_handler + * + * Changes the consumer-supplied completion handler for a CQ + * If a CQ completion handler is provided, the CA level completion handler + * for the given CQ will not be called. If a CQ handler is removed + * (set to NULL), the CA level completion handler will take effect again. + * + * INPUTS: + * CqHandle - Handle to a CQ + * CompletionCallback - Completion handler. + * + * OUTPUTS: + * None. + * + * RETURNS: + * + */ + +typedef FSTATUS (VPI_SETCQCOMPLETIONHANDLER)( + IN IB_HANDLE CqHandle, + IN IB_COMPLETION_CALLBACK CompletionCallback + ); +IBA_API VPI_SETCQCOMPLETIONHANDLER iba_set_cq_compl_handler; + +#if defined(VXWORKS) +/* + * Set the completion handler and context for the kernel CQ given a handle + * previously provided by iba_get_kernel_cq + * this function is depricated, it is only provided for backward compatibility + * with uDAPL + * + * INPUTS: + * CqHndl handle previously provided by iba_get_kernel_cq + * CompletionCallback kernel level callback function + * Context kernel level context value + * + * OUTPUTS: + * + * RETURNS: + * FSUCCESS if CqHndl is valid + * FINVALID_PARAMETER otherwise + */ + +typedef FSTATUS (VPI_SETKCQCOMPLETIONHANDLER) ( + IN uint32 CqHndl, + IN IB_COMPLETION_CALLBACK CompletionCallback, + IN void *Context + ); +IBA_API VPI_SETKCQCOMPLETIONHANDLER iba_set_k_cq_comp_handler; +#endif /* defined(VXWORKS) */ + +/*QueryCQ/iba_query_cq + * + *query the attributes of a specific completion queue. + * + * INPUTS: + * CqHandle CQ handle. + * + * OUTPUTS: + * CqSize pointer to the size of the CQ returned + * by this function. + * Context pointer to the pointer of the caller's context + * returned by this function. The context value + * should match the last context value set by the + * caller. + * RETURNS: + * Status 'FSUCCESS' if the queue pair attributes were retrieved + * successfully else a relevant error status. + * + */ +typedef FSTATUS (VPI_QUERYCQ)( + IN IB_HANDLE CqHandle, + OUT uint32 *Cqsize, + OUT void **Context + ); +IBA_API VPI_QUERYCQ iba_query_cq; + +/*DestroyCQ/iba_destroy_cq + * + *destroy a previously created completion queue. + * + * INPUTS: + * . CqHandle handle of the completion queue + * + * OUTPUTS: + * None + * + * RETURNS: + * Status 'FSUCCESS' if the completion queue was destroyed + * successfully else a relevant error status. + * + */ +typedef FSTATUS (VPI_DESTROYCQ)( + IN IB_HANDLE CqHandle + ); +IBA_API VPI_DESTROYCQ iba_destroy_cq; + +/*RegisterMemRegion/iba_register_mr + * + *register a memory region with the hardware. + * + * INPUTS: + * . CaHandle handle of the channel adapter + * VirtualAddress virtual address of the memory region. + * Length length of the memory region + * PdHandle PD handle + * AccessControl Access Control + * + * OUTPUTS: + * MrHandle handle associated with the memory region. + * Lkey pointer to the local key returned by the + * function + * Rkey pointer to the remote key returned by the + * function. + * + * RETURNS: + * Status 'FSUCCESS' if the memory region was registered successfully + * else a relevant error status. + * + */ +typedef FSTATUS (VPI_REGISTERMEMREGION)( + IN IB_HANDLE CaHandle, + IN void *VirtualAddress, + IN uintn Length, + IN IB_HANDLE PdHandle, + IN IB_ACCESS_CONTROL AccessControl, + OUT IB_HANDLE *MrHandle, + OUT IB_L_KEY *Lkey, + OUT IB_R_KEY *Rkey + ); +IBA_API VPI_REGISTERMEMREGION iba_register_mr; + + +/* + * RegisterPhysMemRegion/iba_register_pmr + * + * Registers a physical memory region. The physical memory region is defined + * by a list of physical buffers. The physical buffers must begin and end + * on an HFI page size boundary. + * + * INPUTS: + * CaHandle - Handle to an open instance of a Channel Adapter. + * ReqIoVirtualAddress - the virtual address the consumer request's be used to + * address the first byte of the registered memory region. + * PhysBufferList - array of the addresses of the physical memory buffers. + * Each buffer is a single physical CA page of memory + * (eg. using CA Page Size specified in IB_CA_ATTRIBUTES). + * NumPhysBuffers - Number of elements in the PhysBufferList array. + * IoVaOffset - Offset into the first buffer of the region's IoVirtualAddress. + * PdHandle - Handle of the Protection Domain to be used to register + * the memory. + * AccessControl - Selectors indicating the access control attributes for the + * Memory Region. + * + * OUTPUTS: + * MrHandle - The handle to the registered memory region. + * IoVirtualAddress - the virtual address the Verbs Provider has assigned to + * the first bytes of the registered memory region. + * Lkey - The local protection key for the memory region. + * Rkey - The remote protection key for the memory region. Only valid if RdmaWrite, + * RdmaRead, or AtomicOp access has been requested for the memory region. + * + * RETURNS: + * + */ + +typedef FSTATUS (VPI_REGISTERPHYSMEMREGION)( + IN IB_HANDLE CaHandle, + IN void *ReqIoVirtualAddress, + IN void *PhysBufferList, + IN uint64 NumPhysBuffers, + IN uint32 IoVaOffset, + IN IB_HANDLE PdHandle, + IN IB_ACCESS_CONTROL AccessControl, + OUT IB_HANDLE *MrHandle, + OUT void **IoVirtualAddress, + OUT IB_L_KEY *Lkey, + OUT IB_R_KEY *Rkey + ); +VPI_REGISTERPHYSMEMREGION RegisterPhysMemRegion; /* internal use only, depricated */ + +/* Version2 of API, supports 64 bit IO virtual addresses */ +typedef FSTATUS (VPI_REGISTERPHYSMEMREGION2)( + IN IB_HANDLE CaHandle, + IN IB_VIRT_ADDR ReqIoVirtualAddress, + IN void *PhysBufferList, + IN uint64 NumPhysBuffers, + IN uint32 IoVaOffset, + IN IB_HANDLE PdHandle, + IN IB_ACCESS_CONTROL AccessControl, + OUT IB_HANDLE *MrHandle, + OUT IB_VIRT_ADDR *IoVirtualAddress, + OUT IB_L_KEY *Lkey, + OUT IB_R_KEY *Rkey + ); +IBA_API VPI_REGISTERPHYSMEMREGION2 iba_register_pmr; + +/* + * RegisterContigPhysMemRegion/iba_register_contig_pmr + * + * Registers a physical memory region. The physical memory region is defined + * by a list of physically contiguous buffers. + * Each physical buffer must begin and end on an HFI page size boundary. + * + * INPUTS: + * CaHandle - Handle to an open instance of a Channel Adapter. + * ReqIoVirtualAddress - the virtual address the consumer request's be used to + * address the first byte of the registered memory region. + * PhysBufferList - array of buffer specifications for the physical memory + * buffers. Each buffer must start and end on a CA Physical Page boundary + * NumPhysBuffers - Number of elements in the PhysBufferList array. + * IoVaOffset - Offset into the first buffer of the region's IoVirtualAddress. + * PdHandle - Handle of the Protection Domain to be used to register + * the memory. + * AccessControl - Selectors indicating the access control attributes for the + * Memory Region. + * + * OUTPUTS: + * MrHandle - The handle to the registered memory region. + * IoVirtualAddress - the virtual address the Verbs Provider has assigned to + * the first bytes of the registered memory region. + * Lkey - The local protection key for the memory region. + * Rkey - The remote protection key for the memory region. Only valid if RdmaWrite, + * RdmaRead, or AtomicOp access has been requested for the memory region. + * + * RETURNS: + * + */ + +typedef FSTATUS (VPI_REGISTERCONTIGPHYSMEMREGION2)( + IN IB_HANDLE CaHandle, + IN IB_VIRT_ADDR ReqIoVirtualAddress, + IN IB_MR_PHYS_BUFFER* PhysBufferList, + IN uint64 NumPhysBuffers, + IN uint32 IoVaOffset, + IN IB_HANDLE PdHandle, + IN IB_ACCESS_CONTROL AccessControl, + OUT IB_HANDLE *MrHandle, + OUT IB_VIRT_ADDR *IoVirtualAddress, + OUT IB_L_KEY *Lkey, + OUT IB_R_KEY *Rkey + ); +IBA_API VPI_REGISTERCONTIGPHYSMEMREGION2 iba_register_contig_pmr; + +/*QueryMemRegion/iba_query_mr + * + *query the attributes of a previously registered memory region. + * + * INPUTS: + * MrHandle memory region handle. + * + * OUTPUTS: + * VirtualAddress pointer to starting virtual address of the + * memory region. + * Length length of the memory region + * PdHandle pointer to the PD handle + * AccessControl pointer to the access control word + * Lkey pointer to the local key + * Rkey pointer to the remote key + * RETURNS: + * Status 'FSUCCESS' if the memory region attributes were retrieved + * successfully else a relevant error status. + * + */ + +typedef FSTATUS (VPI_QUERYMEMREGION)( + IN IB_HANDLE MrHandle, + OUT void **VirtualAddress, + OUT uintn *Length, + OUT IB_HANDLE *PdHandle, + OUT IB_ACCESS_CONTROL *AccessControl, + OUT IB_L_KEY *Lkey, + OUT IB_R_KEY *Rkey + ); +VPI_QUERYMEMREGION QueryMemRegion; /* internal use only, depricated */ + +/* Version2 of API, supports 64 bit IO virtual addresses */ +typedef FSTATUS (VPI_QUERYMEMREGION2)( + IN IB_HANDLE MrHandle, + OUT IB_VIRT_ADDR *VirtualAddress, + OUT uint64 *Length, + OUT IB_HANDLE *PdHandle, + OUT IB_ACCESS_CONTROL *AccessControl, + OUT IB_L_KEY *Lkey, + OUT IB_R_KEY *Rkey + ); +IBA_API VPI_QUERYMEMREGION2 iba_query_mr; + +/*DeregisterMemRegion/iba_deregister_mr + * + *de-register the previously registered memory region. + * + * INPUTS: + * MrHandle handle of the memory region + * + * OUTPUTS: + * . None + * + * RETURNS: + * Status 'FSUCCESS' if the memory region was de-registered + * successfully else a relevant error status. + * + * + */ +typedef FSTATUS (VPI_DEREGISTERMEMREGION)( + IN IB_HANDLE MrHandle + ); +IBA_API VPI_DEREGISTERMEMREGION iba_deregister_mr; + +/* + * ModifyMemRegion/iba_modify_mr + * + * Modifies the attributes of an existing Memory Region. Any combination of + * attributes may be modified by the call. The attributes are Virtual Address + * with Length, Protection Domain, and Access Control selectors. + * + * If the Protection Domain handle is null for a modify Protection Domain + * request, the effect is to make the Memory Region inaccessible for all + * work request operations until a Protection Domain handle is provided on + * a subsequent ModifyMemRegion call. + * + * INPUTS: + * MrHandle - Handle to an Memory Region. Upon completion of this call this + * handle is no longer valid, regardless of the return status of the call. + * ModifyReqType - Indicates an attribute or a combination of attributes to + * modify. + * VirtualAddress - Virtual address of the first byte of the memory area + * to register. + * Length - With the Virtual Address, defines the memory area to register. + * ProtectionDomain - Handle of the Protection Domain to be used to register + * the memory. + * AccessControl - Selectors indicating the access control attributes for the + * Memory Region. + * + * OUTPUTS: + * NewMrHandle - The handle to the modified Memory Region. This handle must be + * used on future references to the Memory Region. On error this may be + * null, indicating no Memory Region was successfully returned and the + * previous Memory Region is no longer registered. + * + * RETURNS: + * + */ + +typedef FSTATUS (VPI_MODIFYMEMREGION)( + IN IB_HANDLE MrHandle, + IN IB_MR_MODIFY_REQ ModifyReqType, + IN void *VirtualAddress OPTIONAL, + IN uintn Length OPTIONAL, + IN IB_HANDLE PdHandle OPTIONAL, + IN IB_ACCESS_CONTROL AccessControl OPTIONAL, + OUT IB_HANDLE *NewMrHandle, + OUT IB_L_KEY *Lkey, + OUT IB_R_KEY *Rkey + ); +IBA_API VPI_MODIFYMEMREGION iba_modify_mr; + +/* + * ModifyPhysMemRegion/iba_modify_pmr + * + * Modifies the attributes of an existing Memory Region previously created + * by RegisterPhysMemRegion or RegisterContigPhysMemRegion. + * Any combination attributes may be modified by + * the call. The attributes are the physical buffer list, Protection Domain, + * and Access Control selectors. + * + * If the Protection Domain handle is null for a modify Protection Domain + * request, the effect is to make the Memory Region inaccessible for all + * work request operations until a Protection Domain handle is provided on + * a subsequent ModifyPhysMemRegion call. + * + * INPUTS: + * MrHandle - Handle to an Memory Region. Upon completion of this call this + * handle is no longer valid, regardless of the return status of the call. + * ModifyReqType - Indicates an attribute or a combination of attributes to + * modify. + * ReqIoVirtualAddress - Virtual address of the first byte of the memory + * area to register. + * NumPhysBuffers - With the Virtual Address, defines the memory area to register. + * IoVaOffset - Offset into the first buffer of the region's IoVirtualAddress. + * ProtectionDomain - Handle of the Protection Domain to be used to register + * the memory. + * AccessControl - Selectors indicating the access control attributes for the + * Memory Region. + * + * OUTPUTS: + * NewMrHandle - The handle to the modified Memory Region. This handle must be + * used on future references to the Memory Region. On error this may be + * null, indicating no Memory Region was successfully returned and the + * previous Memory Region is no longer registered. + * + * RETURNS: + * + */ + +typedef FSTATUS (VPI_MODIFYPHYSMEMREGION)( + IN IB_HANDLE MrHandle, + IN IB_MR_MODIFY_REQ ModifyReqType, + IN void *ReqIoVirtualAddress OPTIONAL, + IN void *PhysBufferList OPTIONAL, + IN uint64 NumPhysBuffers OPTIONAL, + IN uint32 IoVaOffset OPTIONAL, + IN IB_HANDLE PdHandle OPTIONAL, + IN IB_ACCESS_CONTROL AccessControl OPTIONAL, + OUT IB_HANDLE *NewMrHandle, + OUT void **IoVirtualAddress, + OUT IB_L_KEY *Lkey, + OUT IB_R_KEY *Rkey + ); +VPI_MODIFYPHYSMEMREGION ModifyPhysMemRegion; /* internal use only, depricated */ + +/* Version2 of API, supports 64 bit IO virtual addresses */ +typedef FSTATUS (VPI_MODIFYPHYSMEMREGION2)( + IN IB_HANDLE MrHandle, + IN IB_MR_MODIFY_REQ ModifyReqType, + IN IB_VIRT_ADDR ReqIoVirtualAddress OPTIONAL, + IN void *PhysBufferList OPTIONAL, + IN uint64 NumPhysBuffers OPTIONAL, + IN uint32 IoVaOffset OPTIONAL, + IN IB_HANDLE PdHandle OPTIONAL, + IN IB_ACCESS_CONTROL AccessControl OPTIONAL, + OUT IB_HANDLE *NewMrHandle, + OUT IB_VIRT_ADDR *IoVirtualAddress, + OUT IB_L_KEY *Lkey, + OUT IB_R_KEY *Rkey + ); +IBA_API VPI_MODIFYPHYSMEMREGION2 iba_modify_pmr; + +/* + * ModifyContigPhysMemRegion/iba_modify_contig_pmr + * + * Modifies the attributes of an existing Memory Region previously created + * by RegisterPhysMemRegionr RegisterContigPhysMemRegion. + * Any combination attributes may be modified by + * the call. The attributes are the physical buffer list, Protection Domain, + * and Access Control selectors. + * + * If the Protection Domain handle is null for a modify Protection Domain + * request, the effect is to make the Memory Region inaccessible for all + * work request operations until a Protection Domain handle is provided on + * a subsequent ModifyPhysMemRegion call. + * + * INPUTS: + * MrHandle - Handle to an Memory Region. Upon completion of this call this + * handle is no longer valid, regardless of the return status of the call. + * ModifyReqType - Indicates an attribute or a combination of attributes to + * modify. + * ReqIoVirtualAddress - Virtual address of the first byte of the memory + * area to register. + * NumPhysBuffers - With the Virtual Address, defines the memory area to register. + * IoVaOffset - Offset into the first buffer of the region's IoVirtualAddress. + * ProtectionDomain - Handle of the Protection Domain to be used to register + * the memory. + * AccessControl - Selectors indicating the access control attributes for the + * Memory Region. + * + * OUTPUTS: + * NewMrHandle - The handle to the modified Memory Region. This handle must be + * used on future references to the Memory Region. On error this may be + * null, indicating no Memory Region was successfully returned and the + * previous Memory Region is no longer registered. + * + * RETURNS: + * + */ + +typedef FSTATUS (VPI_MODIFYCONTIGPHYSMEMREGION2)( + IN IB_HANDLE MrHandle, + IN IB_MR_MODIFY_REQ ModifyReqType, + IN IB_VIRT_ADDR ReqIoVirtualAddress OPTIONAL, + IN IB_MR_PHYS_BUFFER *PhysBufferList OPTIONAL, + IN uint64 NumPhysBuffers OPTIONAL, + IN uint32 IoVaOffset OPTIONAL, + IN IB_HANDLE PdHandle OPTIONAL, + IN IB_ACCESS_CONTROL AccessControl OPTIONAL, + OUT IB_HANDLE *NewMrHandle, + OUT IB_VIRT_ADDR *IoVirtualAddress, + OUT IB_L_KEY *Lkey, + OUT IB_R_KEY *Rkey + ); +IBA_API VPI_MODIFYCONTIGPHYSMEMREGION2 iba_modify_contig_pmr; + +/*RegisterSharedMemRegion/iba_register_smr + * + *create a new IBA memory region mapping to physical pages representing + *the original memory region (with either same or different access + * rights based on the specified access control word). + * For this one special API, the MrHandle given does not need to be from + * the same process nor protection domain as the PdHandle for which the + * new shared memory region will be created. User space MR handles + * can be interchanged between user processes and Kernel space MR handles + * can be interchanges between drivers/PDs/CA instances. However user space + * handles cannot be interchanged with kernel space MR handles. + * + * INPUTS: + * . MrHandle handle of the original memory region + * VirtualAddress virtual address of the shared memory region. + * PdHandle PD handle + * AccessControl Access Control word + * + * OUTPUTS: + * SharedMrHandle handle associated with the shared memory region. + * Lkey pointer to the local key returned by the + * function + * Rkey pointer to the remote key returned by the + * function. + * + * RETURNS: + * Status 'FSUCCESS' if the shared memory region was created + * successfully else a relevant error status. + */ +typedef FSTATUS (VPI_REGISTERSHAREDMEMREGION)( + IN IB_HANDLE MrHandle, + IN void *VirtualAddress, + IN IB_HANDLE PdHandle, + IN IB_ACCESS_CONTROL AccessControl, + OUT IB_HANDLE *SharedMrHandle, + OUT void **SharedVirtualAddress, + OUT IB_L_KEY *Lkey, + OUT IB_R_KEY *Rkey + ); +VPI_REGISTERSHAREDMEMREGION RegisterSharedMemRegion; /* internal use only, depricated */ + +/* Version2 of API, supports 64 bit IO virtual addresses */ +typedef FSTATUS (VPI_REGISTERSHAREDMEMREGION2)( + IN IB_HANDLE MrHandle, + IN IB_VIRT_ADDR VirtualAddress, + IN IB_HANDLE PdHandle, + IN IB_ACCESS_CONTROL AccessControl, + OUT IB_HANDLE *SharedMrHandle, + OUT IB_VIRT_ADDR *SharedVirtualAddress, + OUT IB_L_KEY *Lkey, + OUT IB_R_KEY *Rkey + ); +IBA_API VPI_REGISTERSHAREDMEMREGION2 iba_register_smr; + +/*CreateMemWindow/iba_create_mw + * + *create a memory window, that can be bound to a 'registered' memory region. + * + * INPUTS: + * . CaHandle handle of the channel adapter + * PdHandle PD handle + * + * OUTPUTS: + * MwHandle pointer to the handle of the memory window + * Rkey pointer to the remote key returned by the + * function. + * + * RETURNS: + * Status 'FSUCCESS' if the memory window was created successfully + * else a relevant error status. + * + */ +typedef FSTATUS (VPI_CREATEMEMWINDOW)( + IN IB_HANDLE CaHandle, + IN IB_HANDLE PdHandle, + OUT IB_HANDLE *MwHandle, + OUT IB_R_KEY *Rkey + ); +IBA_API VPI_CREATEMEMWINDOW iba_create_mw; + +/*QueryMemWindow/iba_query_mw + * + *query the attributes of a previously created memory window. + * + * INPUTS: + * MwHandle memory window handle. + * + * OUTPUTS: + * PdHandle pointer to the PD handle + * Rkey pointer to the remote key + * RETURNS: + * Status 'FSUCCESS' if the memory window attributes were retrieved + * successfuly else a relevant error status. + * + */ +typedef FSTATUS (VPI_QUERYMEMWINDOW)( + IN IB_HANDLE MwHandle, + OUT IB_HANDLE *PdHandle, + OUT IB_R_KEY *Rkey + ); +IBA_API VPI_QUERYMEMWINDOW iba_query_mw; + + + +/* + * PostMemWindowBind/iba_post_bind_mw + * + * Posts a Memory Window Bind work request to the specified QP. This operation + * will consume a Work Queue Element (WQE) from the Send Q and thus is + * equivalent to a PostSend request in consuming a WQE. The work + * completion for the work request is returned through PollCQ. + * + * INPUTS: + * QpHandle - The handle of the QP. The bind work request is posted to the + * Send Q of the QP. + * WorkReqId - Identifier supplied by the consumer for the consumer's use in + * associating a subsequent work completion with this work request. Not + * used by the Verbs Provider. + * MwHandle - The handle of the Memory Window. + * CurrentRKey - The current Rkey for the Memory Window. This Rkey was + * returned from the previous bind request if this is a subsequent bind + * request for the Memory Window, or from the Create Memory Window + * operation if this is the first bind on this Memory Window. + * MrHandle - The handle of the Memory Region the Memory Window is to be + * bound to. (passed through but generally ignored) + * MrLkey - Lkey of the Memory Region. + * VirtualAddress - Virtual Address of base of memory window region. + * Length - Length (in bytes) of the window. + * AccessControl - Selects RdmaWrite and/or RdmaRead enable bits. + * Options - Allows selection of SignaledCompletion and Fence bits. Fence bit + * only applies on an Unreliable Connected QP. + * + * OUTPUTS: + * NewRKey - The new Rkey for the bound Memory Window to be used in a + * subsequent send or memory window bind work request referencing this + * memory window. + * + * RETURNS: + * + */ + +typedef FSTATUS (VPI_POSTMEMWINDOWBIND)( + IN IB_HANDLE QpHandle, + IN uint64 WorkReqId, + IN IB_HANDLE MwHandle, + IN IB_R_KEY CurrentRkey, + IN IB_HANDLE MrHandle, + IN IB_L_KEY MrLkey, + IN void *VirtualAddress, + IN uintn Length, + IN IB_ACCESS_CONTROL AccessControl, + IN IB_MW_BIND_OPTIONS Options, + OUT IB_R_KEY *NewRkey + ); +VPI_POSTMEMWINDOWBIND PostMemWindowBind; /* internal use only, depricated */ + + +/* Version2 of API, supports 64 bit IO virtual addresses */ +typedef FSTATUS (VPI_POSTMEMWINDOWBIND2)( + IN IB_HANDLE QpHandle, + IN uint64 WorkReqId, + IN IB_HANDLE MwHandle, + IN IB_R_KEY CurrentRkey, + IN IB_HANDLE MrHandle, + IN IB_L_KEY MrLkey, + IN IB_VIRT_ADDR VirtualAddress, + IN uint64 Length, + IN IB_ACCESS_CONTROL AccessControl, + IN IB_MW_BIND_OPTIONS Options, + OUT IB_R_KEY *NewRkey + ); +IBA_API VPI_POSTMEMWINDOWBIND2 iba_post_bind_mw; + + +/*DestroyMemWindow/iba_destroy_mw + * + *destroy the previously registered memory window. + * + * INPUTS: + * MwHandle handle of the memory window + * + * OUTPUTS: + * . None + * + * RETURNS: + * Status 'FSUCCESS' if the memory window was destroyed + * successfully else a relevant error status. + */ +typedef FSTATUS (VPI_DESTROYMEMWINDOW)( + IN IB_HANDLE MwHandle + ); +IBA_API VPI_DESTROYMEMWINDOW iba_destroy_mw; + +/*PostSend/iba_post_send + *post a work request to the 'send' queue of a specific queue pair. + * this is depricated, use iba_post_send2 + * + * INPUTS: + * QpHandle Handle of the queue pair + * WorkRequest Pointer to the work request structure + * data pointed to only used during duration of call + * + * OUTPUTS: + * None + * + * RETURNS: + * Status 'FSUCCESS' if the request was posted successfully else + * a relevant error status. + */ +typedef FSTATUS (VPI_POSTSEND)( + IN IB_HANDLE QpHandle, + IN IB_WORK_REQ *WorkRequest + ); +IBA_API VPI_POSTSEND iba_post_send; + +/*iba_post_send2 + *post a list of work requests to the 'send' queue of a specific queue pair. + * + * + * INPUTS: + * QpHandle Handle of the queue pair + * WorkRequestList Pointer to the linked list of work request structures + * data pointed to only used during duration of call + * + * OUTPUTS: + * FailedWorkRequest Pointer to 1st WorkRequest which failed + * + * RETURNS: + * Status 'FSUCCESS' if the request was posted successfully else + * a relevant error status. On failure FailedWorkRequest is set to point + * to the WorkRequest which failed. On success FailedWorkRequest is not + * altered + */ +typedef FSTATUS (VPI_POSTSEND2)( + IN IB_HANDLE QpHandle, + IN IB_WORK_REQ2 *WorkRequestList, + OUT IB_WORK_REQ2 **FailedWorkRequest OPTIONAL + ); +IBA_API VPI_POSTSEND2 iba_post_send2; + +/*PostRecv/iba_post_recv + * + *post a work request to the 'receive' queue of a specific queue pair. + * this is depricated, use iba_post_recv2 + * + * INPUTS: + * QpHandle Handle of the queue pair + * WorkRequest Pointer to the work request structure + * data pointed to only used during duration of call + * + * OUTPUTS: + * None + * + * RETURNS: + * Status 'FSUCCESS' if the request was posted successfully else + * a relevant error status. + */ +typedef FSTATUS (VPI_POSTRECV)( + IN IB_HANDLE QpHandle, + IN IB_WORK_REQ *WorkRequest + ); +IBA_API VPI_POSTRECV iba_post_recv; + + +/*iba_post_recv2 + *post a list of work requests to the 'recv' queue of a specific queue pair. + * + * + * INPUTS: + * QpHandle Handle of the queue pair + * WorkRequestList Pointer to the linked list of work request structures + * data pointed to only used during duration of call + * + * OUTPUTS: + * FailedWorkRequest Pointer to 1st WorkRequest which failed + * + * RETURNS: + * Status 'FSUCCESS' if the request was posted successfully else + * a relevant error status. On failure FailedWorkRequest is set to point + * to the WorkRequest which failed. On success FailedWorkRequest is not + * altered + */ +typedef FSTATUS (VPI_POSTRECV2)( + IN IB_HANDLE QpHandle, + IN IB_WORK_REQ2 *WorkRequestList, + OUT IB_WORK_REQ2 **FailedWorkRequest OPTIONAL + ); +IBA_API VPI_POSTRECV2 iba_post_recv2; + +/* + * PollCQ/iba_poll_cq + * + * Checks for a work completion on the given Completion Queue. If one is + * present the WorkCompletion structure passed to the call is filled in with + * completion information for the completed request. + * + * INPUTS: + * CqHandle - Handle to a Completion Queue. + * + * OUTPUTS: + * WorkCompletion - The caller passes a pointer to a work completion structure. + * If the function returns FSUCCESS the structure contains information for + * a completed work request. + * + * RETURNS: + * FSUCCESS - A work completion is returned. + * FNOT_DONE - There is no work completion. + * FINVALID_PARAMETER - One of the parameters was invalid. + * + * Does not prempt + */ + +typedef FSTATUS (VPI_POLLCQ)( + IN IB_HANDLE CqHandle, + OUT IB_WORK_COMPLETION *WorkCompletion + ); +IBA_API VPI_POLLCQ iba_poll_cq; + + +/* + * PeekCQ/iba_peek_cq + * + * Determines if the given Completion Queue has at least NumWC completions + * queued to it. + * + * INPUTS: + * CqHandle - Handle to a Completion Queue. + * NumWC - number of CQEs to check for + * + * OUTPUTS: + * + * RETURNS: + * FSUCCESS - >= NumWC on completion Queue + * FNOT_DONE - < NumWC on completion Queue + * FINSUFFICIENT_RESOURCES - NumWC > Size of Completion Queue + * FINVALID_PARAMETER - One of the parameters was invalid. + * + * Does not prempt + */ + +typedef FSTATUS (VPI_PEEKCQ)( + IN IB_HANDLE CqHandle, + IN uint32 NumWC + ); +IBA_API VPI_PEEKCQ iba_peek_cq; + +/* + * PollCQAndRearmCQ/iba_poll_and_rearm_cq + * + * Optimized combination of PollCQ and RearmCQ for use in completion callbacks. + * Checks for a work completion on the given Completion Queue. If one is + * present the WorkCompletion structure passed to the call is filled in with + * completion information for the completed request. Also Rearms the CQ + * after processing last entry on CQ + * + * INPUTS: + * CqHandle - Handle to a Completion Queue. + * EventSelect - Events to rearm CQ for + * + * OUTPUTS: + * WorkCompletion - The caller passes a pointer to a work completion structure. + * If the function returns FSUCCESS, FCOMPLETED or FPOLL_NEEDED + * the structure contains information for + * a completed work request. + * + * RETURNS: + * FSUCCESS - A work completion is returned. Caller should call + * PollAndRearmCQ again. CQ has not been rearmed. + * FCOMPLETED - A work completion is returned. All CQEs have been + * processed, caller need not call PollCQ nor PollAndRearmCQ + * CQ has been rearmed. + * FPOLL_NEEDED - A work completion is returned. The CQ has been Rearmed, + * caller must loop on PollCQ to drain rest of CQ. + * FNOT_DONE - There is no work completion. CQ has been rearmed. + * FINVALID_PARAMETER - One of the parameters was invalid. + * + * Does not prempt + */ + +typedef FSTATUS (VPI_POLLANDREARMCQ2)( + IN IB_HANDLE CqHandle, + IN IB_CQ_EVENT_SELECT EventSelect, + OUT IB_WORK_COMPLETION *WorkCompletion + ); +IBA_API VPI_POLLANDREARMCQ2 iba_poll_and_rearm_cq; + + +/*RearmCQ/iba_rearm_cq + * + *arm a specific CQ so that a callback will occur the next time + *the hardware adds a work completion to the CQ + * + * INPUTS: + * CqHandle Handle of the CQ + * EventSelect specifies a filter for the types of events + * that would be allowed to generate callbacks + * + * OUTPUTS: + * + * + * RETURNS: + * status 'FSUCCESS' if the CQ was armed successfully + * else a relevant error status. + * + * Does not prempt + */ +typedef FSTATUS (VPI_REARMCQ)( + IN IB_HANDLE CqHandle, + IN IB_CQ_EVENT_SELECT EventSelect + ); +IBA_API VPI_REARMCQ iba_rearm_cq; + +/*RearmNCQ/iba_rearm_n_cq + * + *arm a specific CQ so that a callback will occur once the hardware has + *added NumWC work completions to the CQ. + *If the CQ already has NumWC completions, a callback may be generated + *however this behaviour can be hardware specific + * + * INPUTS: + * CqHandle Handle of the CQ + * NumWC How many Work completions to wait for before + * generating a callback. + * + * OUTPUTS: + * + * RETURNS: + * status 'FSUCCESS' if the CQ was armed successfully + * else a relevant error status. + * + * Does not prempt + */ +typedef FSTATUS (VPI_REARMNCQ)( + IN IB_HANDLE CqHandle, + IN uint16 NumWC + ); +IBA_API VPI_REARMNCQ iba_rearm_n_cq; + +#if defined(VXWORKS) +/* + * Private interfaces for use by the SMA and CM + */ + +/* Process a MAD Packet for the SMA or PMA. + * The SMA and PMA in IbAccess use this function to process all the + * MAD packets they receive. + * + * Arguments: + * qp_handle - QP packet arrived on (QP0/QP1), implies HFI + * port_number - Port number packet arrived on (1 to N) + * SLID - LID who sent us packet, special value of 0 indicates our own firmware + * sent it to us for us to send out on QP0 + * MadInOut - Mad packet, the response should be composed here + * data pointed to only used during duration of call + * + * Returns: + * FSUCCESS - MadArg contains an appropriate response packet + * other - packet could not be processed and no response should be sent + */ +typedef FSTATUS (VPI_GETSETMAD)( + IN IB_HANDLE QpHandle, + IN uint8 PortNumber, + IN STL_LID_32 SLID, + IN STL_SMP *SmpInOut, + IN uint32 *SmpLength + ); +VPI_GETSETMAD iba_get_set_mad; + + +/* + * RegisterConnMgr + * + * Registers the Connection Manager for the given CA. + * Async Events appropriate to CM will be sent to this + * open CA instance even for QPs not part of the CA instance itself + * + * INPUTS: + * CaHandle - Handle to an open instance of a CA. + * + * OUTPUTS: + * None. + * + * RETURNS: + * + */ + +typedef FSTATUS (VPI_REGISTERCONNMGR)( + IN IB_HANDLE CaHandle + ); +VPI_REGISTERCONNMGR iba_register_cm; +#endif /* defined(VXWORKS) */ + +/* + * Private interface to support the user-mode Verbs Provider component + * Each HFI's UVP and its corresponding kernel VPD can define the + * private info they need to handshake such that kernel bypass operations + * can be performed without calling the kernel VPD + * The private info can be input and/or output data. It is up to the + * HFI specific UVP as to how and when these calls are made + * + * These calls are not for end user applications + */ + +/*QueryCAPrivateInfo/iba_query_ca_private_info + *This function is exported by the UVCA to let the caller + *(specifically UVP components) extract the hardware specific information + *of the specified channel adapter.This functions provides a means for + *the UVP module to privately communicate with its kernel mode + *counter part the VPD. The intermediate components including the UVCA act + *the carriers of data communicated between these two modules + * + * INPUTS: + * CaHandle UVCA specific handle of the channel adapter. + * OutBufSize pointer to the size of the buffer allocated by + * the caller (UVP). + * + * OUTPUTS: + * OutBufSize . pointer to the number of bytes returned by the VPD. + * OutBuf pointer the data buffer.On successful return from + * this function, the buffer will be filled with + * hardware specific information of the specified + * channel adapter. + * + * RETURNS: + * status 'FSUCCESS' if the channel adapter specific information was + * successfully retrieved else a relevant error status. + * + * + */ +typedef FSTATUS +(VPI_QUERYCA_PRIVATE_INFO)( + IN IB_HANDLE CaHandle, + IN OUT uint32 *BufferSize, + OUT void *Buffer + ); +IBA_API VPI_QUERYCA_PRIVATE_INFO iba_query_ca_private_info; + +/*QueryPDPrivateInfo/iba_query_pd_private_info + *This function is exported by the UVCA to let the caller + *(specifically UVP components) extract the hardware specific information + *of the specified PD. This functions provides a means for + *the UVP module to privately communicate with its kernel mode + *counter part the VPD. The intermediate components including the UVCA act + *the carriers of data communicated between these two modules + * + * INPUTS: + * PdHandle UVCA specific handle of the PD. + * OutBufSize pointer to the size of the buffer allocated by + * the caller (UVP). + * + * OUTPUTS: + * OutBufSize . pointer to the number of bytes returned by the VPD. + * OutBuf pointer the data buffer.On successful return from + * this function, the buffer will be filled with + * hardware specific information of the specified + * PD. + * + * RETURNS: + * status 'FSUCCESS' if the PD specific information was + */ +typedef FSTATUS +(VPI_QUERYPD_PRIVATE_INFO)( + IN IB_HANDLE PdHandle, + IN OUT uint32 *BufferSize, + OUT void *Buffer + ); +IBA_API VPI_QUERYPD_PRIVATE_INFO iba_query_pd_private_info; + +/*QueryQPPrivateInfo/iba_query_qp_private_info + *This function is exported by the UVCA to let the caller + *(specifically UVP components) extract the hardware specific information + *of the specified queue pair. This functions provides a means for + *the UVP module to privately communicate with its kernel mode + *counter part the VPD. The intermediate components including the UVCA act + *the carriers of data communicated between these two modules + * + * INPUTS: + * QpHandle UVCA specific handle of the queue pair. + * OutBufSize pointer to the size of the buffer allocated by + * the caller (UVP). + * + * OUTPUTS: + * OutBufSize . pointer to the number of bytes returned by the VPD. + * OutBuf pointer the data buffer.On successful return from + * this function, the buffer will be filled with + * hardware specific information of the specified + * queue pair. + * + * RETURNS: + * status 'FSUCCESS' if the queue pair specific information was + */ +typedef FSTATUS +(VPI_QUERYQP_PRIVATE_INFO)( + IN IB_HANDLE QpHandle, + IN OUT uint32 *BufferSize, + OUT void *Buffer + ); +IBA_API VPI_QUERYQP_PRIVATE_INFO iba_query_qp_private_info; + +/*QueryCQPrivateInfo/iba_query_cq_private_info + *This function is exported by the UVCA to let the caller + *(specifically UVP components) extract the hardware specific information + *of the specified completion queue. This functions provides a means for + *the UVP module to privately communicate with its kernel mode + *counter part the VPD. The intermediate components including the UVCA act + *the carriers of data communicated between these two modules + * + * INPUTS: + * CqHandle UVCA specific handle of the completion queue. + * OutBufSize pointer to the size of the buffer allocated by + * the caller (UVP). + * + * OUTPUTS: + * OutBufSize . pointer to the number of bytes returned by the VPD. + * OutBuf pointer the data buffer.On successful return from + * this function, the buffer will be filled with + * hardware specific information of the specified + * completion queue. + * + * RETURNS: + * status 'FSUCCESS' if the completion queue specific information was + * successfully retrieved else a relevant error status. + * + */ +typedef FSTATUS +(VPI_QUERYCQ_PRIVATE_INFO)( + IN IB_HANDLE CqHandle, + IN OUT uint32 *BufferSize, + OUT void *Buffer + ); +IBA_API VPI_QUERYCQ_PRIVATE_INFO iba_query_cq_private_info; + +/*QueryAVPrivateInfo/iba_query_av_private_info + *This function is exported by the UVCA to let the caller + *(specifically UVP components) extract the hardware specific information + *of the specified Address Vector. This functions provides a means for + *the UVP module to privately communicate with its kernel mode + *counter part the VPD. The intermediate components including the UVCA act + *the carriers of data communicated between these two modules + * + * INPUTS: + * AvHandle UVCA specific handle of the adress vector. + * OutBufSize pointer to the size of the buffer allocated by + * the caller (UVP). + * + * OUTPUTS: + * OutBufSize . pointer to the number of bytes returned by the VPD. + * OutBuf pointer the data buffer.On successful return from + * this function, the buffer will be filled with + * hardware specific information of the specified + * address vector. + * + * RETURNS: + * status 'FSUCCESS' if the address vector specific information was + * successfully retrieved else a relevant error status. + * + * + */ +typedef FSTATUS +(VPI_QUERYAV_PRIVATE_INFO)( + IN IB_HANDLE AvHandle, + IN OUT uint32 *BufferSize, + OUT void *Buffer + ); +IBA_API VPI_QUERYAV_PRIVATE_INFO iba_query_av_private_info; + +#ifdef __cplusplus +}; +#endif + + +#endif /* _IBA_VPI_EXPORT_H_ */ diff --git a/IbAccess/Common/Public/README b/IbAccess/Common/Public/README new file mode 100644 index 0000000..793d8c9 --- /dev/null +++ b/IbAccess/Common/Public/README @@ -0,0 +1 @@ +OS Abstraction layer diff --git a/IbAccess/Common/Public/datatypes.h b/IbAccess/Common/Public/datatypes.h new file mode 100644 index 0000000..4c35391 --- /dev/null +++ b/IbAccess/Common/Public/datatypes.h @@ -0,0 +1,146 @@ +/* BEGIN_ICS_COPYRIGHT3 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT3 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +#ifndef _IBA_PUBLIC_DATA_TYPES_H_ +#define _IBA_PUBLIC_DATA_TYPES_H_ + + +#include "iba/public/datatypes_osd.h" + +/* TBD - use /usr/include/stdint.h??? */ + +#ifdef __cplusplus +extern "C" { +#endif + +/* Minimum of signed integral types. */ +# define IB_INT8_MIN (-128) +# define IB_INT16_MIN (-32767-1) +# define IB_INT32_MIN (-2147483647-1) +# define IB_INT64_MIN (-9223372036854775807ll -1) +/* Maximum of signed integral types. */ +# define IB_INT8_MAX (127) +# define IB_INT16_MAX (32767) +# define IB_INT32_MAX (2147483647) +# define IB_INT64_MAX (9223372036854775807ll) +/* Maximum of unsigned integral types. */ +# define IB_UINT8_MAX (255) +# define IB_UINT16_MAX (65535) +# define IB_UINT32_MAX (4294967295U) +# define IB_UINT64_MAX (18446744073709551615ULL) + +#ifndef offsetof +#define offsetof(TYPE, MEMBER) ((uintn) &((TYPE *)0)->MEMBER) +#endif + +#ifdef __cplusplus +/* Currently the DTA fails to compile because of a bug + * in 3.4.2-6.fc3 that ships with fc3 and el4 beta. + * A workaround is possible, but I'm waiting to see what + * redhats response is to bug 146385. + */ +#define PARENT_STRUCT(ADDRESS, TYPE, MEMBER) \ + ((TYPE *)((char *)(ADDRESS) - (uintn)(&(((TYPE*)0)->* (&TYPE::MEMBER))))) +#else +#define PARENT_STRUCT(ADDRESS, TYPE, MEMBER) \ + ((TYPE *)((char *)(ADDRESS) - offsetof(TYPE, MEMBER))) +#endif + +#ifndef IN +#define IN /* Function input parameter */ +#endif +#ifndef OUT +#define OUT /* Function output parameter */ +#endif +#ifndef OPTIONAL +#define OPTIONAL /* Optional function parameter - NULL if not used */ +#endif + + +/**************************************************************************** + * Function Returns And Completion Codes * + * * + * The text for any addition to this enumerated type must be added to the * + * string array defined in . * + * * + ****************************************************************************/ + +/* + * The generic error codes are listed here. The lower 8 bits of FSTATUS + * define the generic error codes. Modules using this can use the top + * 24 bits to encode module specific error codes. + */ +typedef uint32 FSTATUS; + +#define FSUCCESS 0x00 +#define FERROR 0x01 +#define FINVALID_STATE 0x02 +#define FINVALID_OPERATION 0x03 +#define FINVALID_SETTING 0x04 +#define FINVALID_PARAMETER 0x05 +#define FINSUFFICIENT_RESOURCES 0x06 +#define FINSUFFICIENT_MEMORY 0x07 +#define FCOMPLETED 0x08 +#define FNOT_DONE 0x09 +#define FPENDING 0x0A +#define FTIMEOUT 0x0B +#define FCANCELED 0x0C +#define FREJECT 0x0D +#define FOVERRUN 0x0E +#define FPROTECTION 0x0F +#define FNOT_FOUND 0x10 +#define FUNAVAILABLE 0x11 +#define FBUSY 0x12 +#define FDISCONNECT 0x13 +#define FDUPLICATE 0x14 +#define FPOLL_NEEDED 0x15 + +#define FSTATUS_COUNT 0x16 /* should be the last value */ + +/**************************************************************************** + * Debug Output Level * + ****************************************************************************/ +typedef enum _FDEBUG_LEVEL +{ + FDEBUG_OFF, + FDEBUG_ERROR, + FDEBUG_TERSE, + FDEBUG_NORMAL, + FDEBUG_VERBOSE + +} FDEBUG_LEVEL; + +#ifdef __cplusplus +}; +#endif + + +#endif /* _IBA_PUBLIC_DATA_TYPES_H_ */ diff --git a/IbAccess/Common/Public/iarray.c b/IbAccess/Common/Public/iarray.c new file mode 100644 index 0000000..0a4cf5f --- /dev/null +++ b/IbAccess/Common/Public/iarray.c @@ -0,0 +1,848 @@ +/* BEGIN_ICS_COPYRIGHT6 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT6 ****************************************/ + + +#include "iarray.h" +#include "imemory.h" +#include "imath.h" + +// Make a memory tag of 'iarr' for iarray. +#define ARR_MEM_TAG MAKE_MEM_TAG( i, a, r, r ) + + +/////////////////////////////////////////////////////////////////////////////// +// array access methods +// These methods are an attempt to follow the functionality of the C++ STL. +// The names and behavior are obviously not exact matches, but hopefully, +// close enough to make those familiar with the ANSI standard comfortable. +/////////////////////////////////////////////////////////////////////////////// + + +/////////////////////////////////////////////////////////////////////////////// +// ArrayInitState +// +// Description: +// This function performs basic array initialization. This function cannot +// fail. +// +// Inputs: +// pArray - Pointer to array +// +// Outputs: +// None. +// +// Returns: +// None. +// +/////////////////////////////////////////////////////////////////////////////// +void +ArrayInitState( + IN ARRAY* const pArray ) +{ + DEBUG_ASSERT( pArray ); + MemoryClear( pArray, sizeof( ARRAY ) ); +} + + + +/////////////////////////////////////////////////////////////////////////////// +// ArrayInit +// +// Description: +// This function initializes the array. New elements in the array are +// initialized to NULL. +// +// Inputs: +// pArray - Pointer to array +// InitialSize - initial number of elements +// GrowSize - number of elements to allocate when incrementally growing +// the array +// ElementSize - size of each element in the array +// MemFlags - memory allocate flags (IBA_MEM_FLAG_*) +// +// Outputs: +// None. +// +// Returns: +// FSUCCESS +// FINSUFFICIENT_MEMORY - array is initialized to zero size +// +/////////////////////////////////////////////////////////////////////////////// +FSTATUS +ArrayInit( + IN ARRAY* const pArray, + IN const uint32 InitialSize, + IN const uint32 GrowSize, + IN const uint32 ElementSize, + IN const uint32 MemFlags) +{ + FSTATUS Status; + + DEBUG_ASSERT( pArray ); + DEBUG_ASSERT( GrowSize ); + DEBUG_ASSERT( ElementSize ); + + ArrayInitState( pArray ); + + pArray->m_GrowSize = GrowSize; + pArray->m_ElementSize = ElementSize; + + // get the storage needed by the user + Status = ArraySetSize( pArray, InitialSize, MemFlags, NULL ); + + return( Status ); +} + + +/////////////////////////////////////////////////////////////////////////////// +// ArrayDestroy +// +// Description: +// This function deallocates all allocated memory associated with the array. +// The array is left initialized to zero size. This function does not fail. +// If any Array operations did premptable memory allocate (via MemFlags), this +// may prempt. +// +// Inputs: +// pArray - Pointer to array +// +// Outputs: +// None. +// +// Returns: +// None. +// +/////////////////////////////////////////////////////////////////////////////// +void +ArrayDestroy( + IN ARRAY* const pArray ) +{ + DEBUG_ASSERT( pArray ); + + // Destroy the page array. + if( pArray->m_pElements ) + MemoryDeallocate( pArray->m_pElements ); + + // reset internal state + AtomicWrite(&pArray->m_Capacity, 0); + pArray->m_GrowSize = 0; + pArray->m_Size = 0; + pArray->m_pElements = NULL; + + return; +} + + + +/////////////////////////////////////////////////////////////////////////////// +// ArraySet +// +// Description: +// This function sets the element at the specified index. The array grows as +// necessary. +// +// Inputs: +// pArray - Pointer to array. +// Index - Index of element to get. +// pElement - Pointer to the element to set at the specified index. +// MemFlags - memory allocate flags (IBA_MEM_FLAG_*) +// ppNewElements - *ppNewElements is potential new storage for array resize +// must have been returned by ArrayPrepareSet(Index) +// +// Outputs: +// ppNewElements - *ppNewElements is set to NULL if ppNewElements was used +// +// Returns: +// FSUCCESS +// FINSUFFICIENT_MEMORY The array could not be resized to accomodate the +// specified element. +// +/////////////////////////////////////////////////////////////////////////////// +FSTATUS +ArraySet( + IN ARRAY* const pArray, + IN const uint32 Index, + IN void* const pElement, + IN const uint32 MemFlags, + IN OUT void** ppNewElements OPTIONAL) +{ + FSTATUS Status; + + DEBUG_ASSERT( pArray ); + DEBUG_ASSERT( pElement ); + + // Determine if the array has room for this element. + if( IB_EXPECT_FALSE(Index >= pArray->m_Size )) + { + // Resize to accomodate the given index. + Status = ArraySetSize( pArray, Index + 1, MemFlags, ppNewElements ); + if (Status != FSUCCESS) + return( Status ); + } + + // At this point, the array is guaranteed to be big enough + // Copy the data into the array + MemoryCopy(ArrayGetPtr( pArray, Index ), pElement, pArray->m_ElementSize); + + return( FSUCCESS ); +} + + +/////////////////////////////////////////////////////////////////////////////// +// ArraySet32 +// +// Description: +// This function sets the element at the specified index. The array grows as +// necessary. +// Optimized for ElementSize of 32 bits +// +// Inputs: +// pArray - Pointer to array. +// Index - Index of element to get. +// Element - the element to set at the specified index. +// MemFlags - memory allocate flags (IBA_MEM_FLAG_*) +// ppNewElements - *ppNewElements is potential new storage for array resize +// must have been returned by ArrayPrepareSet(Index) +// +// Outputs: +// ppNewElements - *ppNewElements is set to NULL if ppNewElements was used +// +// Returns: +// FSUCCESS +// FINSUFFICIENT_MEMORY The array could not be resized to accomodate the +// specified element. +// +/////////////////////////////////////////////////////////////////////////////// +FSTATUS +ArraySet32( + IN ARRAY* const pArray, + IN const uint32 Index, + IN uint32 Element, + IN const uint32 MemFlags, + IN OUT void** ppNewElements OPTIONAL) +{ + FSTATUS Status; + + DEBUG_ASSERT( pArray ); + + // Determine if the array has room for this element. + if( IB_EXPECT_FALSE(Index >= pArray->m_Size )) + { + // Resize to accomodate the given index. + Status = ArraySetSize( pArray, Index + 1, MemFlags, ppNewElements ); + if (Status != FSUCCESS) + return( Status ); + } + + // At this point, the array is guaranteed to be big enough + *(ArrayGetPtr32( pArray, Index )) = Element; + + return( FSUCCESS ); +} + + +/////////////////////////////////////////////////////////////////////////////// +// ArraySet64 +// +// Description: +// This function sets the element at the specified index. The array grows as +// necessary. +// Optimized for ElementSize of 64 bits +// +// Inputs: +// pArray - Pointer to array. +// Index - Index of element to get. +// Element - the element to set at the specified index. +// MemFlags - memory allocate flags (IBA_MEM_FLAG_*) +// ppNewElements - *ppNewElements is potential new storage for array resize +// must have been returned by ArrayPrepareSet(Index) +// +// Outputs: +// ppNewElements - *ppNewElements is set to NULL if ppNewElements was used +// +// Returns: +// FSUCCESS +// FINSUFFICIENT_MEMORY The array could not be resized to accomodate the +// specified element. +// +/////////////////////////////////////////////////////////////////////////////// +FSTATUS +ArraySet64( + IN ARRAY* const pArray, + IN const uint32 Index, + IN uint64 Element, + IN const uint32 MemFlags, + IN OUT void** ppNewElements OPTIONAL) +{ + FSTATUS Status; + + DEBUG_ASSERT( pArray ); + + // Determine if the array has room for this element. + if( IB_EXPECT_FALSE(Index >= pArray->m_Size )) + { + // Resize to accomodate the given index. + Status = ArraySetSize( pArray, Index + 1, MemFlags, ppNewElements ); + if (Status != FSUCCESS) + return( Status ); + } + + // At this point, the array is guaranteed to be big enough + *(ArrayGetPtr64( pArray, Index )) = Element; + + return( FSUCCESS ); +} + + + +/////////////////////////////////////////////////////////////////////////////// +// ArraySetPointer +// +// Description: +// This function sets the element at the specified index. The array grows as +// necessary. +// Optimized for ElementSize of sizeof(void*) +// +// Inputs: +// pArray - Pointer to array. +// Index - Index of element to get. +// Element - the element to set at the specified index. +// MemFlags - memory allocate flags (IBA_MEM_FLAG_*) +// ppNewElements - *ppNewElements is potential new storage for array resize +// must have been returned by ArrayPrepareSet(Index) +// +// Outputs: +// ppNewElements - *ppNewElements is set to NULL if ppNewElements was used +// +// Returns: +// FSUCCESS +// FINSUFFICIENT_MEMORY The array could not be resized to accomodate the +// specified element. +// +/////////////////////////////////////////////////////////////////////////////// +FSTATUS +ArraySetPointer( + IN ARRAY* const pArray, + IN const uint32 Index, + IN void* Element, + IN const uint32 MemFlags, + IN OUT void** ppNewElements OPTIONAL) +{ + FSTATUS Status; + + DEBUG_ASSERT( pArray ); + + // Determine if the array has room for this element. + if( IB_EXPECT_FALSE(Index >= pArray->m_Size) ) + { + // Resize to accomodate the given index. + Status = ArraySetSize( pArray, Index + 1, MemFlags, ppNewElements ); + if (Status != FSUCCESS) + return( Status ); + } + + // At this point, the array is guaranteed to be big enough + *(ArrayGetPtrPointer( pArray, Index )) = Element; + + return( FSUCCESS ); +} + + +/////////////////////////////////////////////////////////////////////////////// +// ArraySetCapacity +// +// Description: +// This function reserves capacity in the array to the specified number of +// elements. This function can only fail if the new capacity is larger than +// the old capacity. If the new capacity is less than the old, no action +// is taken. +// +// Inputs: +// pArray - Pointer to array +// NewCapacity - Number of elements reserved in the array +// MemFlags - memory allocate flags (IBA_MEM_FLAG_*) +// ppNewElements - *ppNewElements is potential new storage for array resize +// must have been returned by ArrayPrepareSize(Size) +// +// Outputs: +// ppNewElements - *ppNewElements is set to NULL if ppNewElements was used +// +// Returns: +// FSUCCESS +// FINSUFFICIENT_MEMORY - array is left unaltered +// +/////////////////////////////////////////////////////////////////////////////// +FSTATUS +ArraySetCapacity( + IN ARRAY* const pArray, + IN const uint32 NewCapacity, + IN const uint32 MemFlags, + IN OUT void** ppNewElements OPTIONAL) +{ + uint32 NewBytes = NewCapacity * pArray->m_ElementSize; + uint32 OldBytes = AtomicRead(&pArray->m_Capacity) * pArray->m_ElementSize; + uint8 *pNewElements; + + DEBUG_ASSERT( pArray ); + + // Do we have to do anything here? + if( NewCapacity <= AtomicRead(&pArray->m_Capacity) ) + { + // Nope + return( FSUCCESS ); + } + + // Allocate our array. + if (ppNewElements && *ppNewElements) + { + pNewElements = (uint8*)*ppNewElements; + if( pArray->m_pElements ) + { + // Copy the old array into the new. + MemoryCopy( pNewElements, pArray->m_pElements, OldBytes); + } + // caller will deallocate *ppNewElements, may need to be in a premptable + // context, so don't deallocate here + *ppNewElements = pArray->m_pElements; + } else { + pNewElements = (uint8*)MemoryAllocate2AndClear(NewBytes, MemFlags, ARR_MEM_TAG); + if( !pNewElements ) + return( FINSUFFICIENT_MEMORY ); + if( pArray->m_pElements ) + { + // Copy the old array into the new. + MemoryCopy( pNewElements, pArray->m_pElements, OldBytes); + MemoryDeallocate( pArray->m_pElements ); + } + } + + // Set the new array. + pArray->m_pElements = pNewElements; + + // clear the new elements + MemoryClear(pArray->m_pElements+OldBytes, NewBytes-OldBytes); + + // Update the array with the new capactity. + AtomicWrite(&pArray->m_Capacity, NewCapacity); + + return( FSUCCESS ); +} + +// compute capacity to grow to as part of enlarging array to given size +static __inline +uint32 ArrayComputeCapacity( + IN ARRAY* const pArray, + IN const uint32 Size) +{ + return ROUNDUP(Size, pArray->m_GrowSize); +} + + +/////////////////////////////////////////////////////////////////////////////// +// ArrayPrepareSize +// +// Description: +// This function allocates the storage that would be needed to resize the +// the array to the specified number of elements. +// This function can only fail if the new size is larger than +// the old capacity. +// +// This allows for premptable array allocation for arrays which must be +// guarded by spin locks. For example: +// if (FSUCCESS != ArrayPrepareSize(&myArray, Size, +// IBA_MEM_FLAG_PREMPTABLE, &pNewElements)) +// failure return +// SpinLockAcquire +// status = ArraySetSize(&myArray, Size, IBA_MEM_FLAG_NONE, &pNewElements); +// SpinLockRelease +// if (pNewElements) +// MemoryDeallocate(pNewElements); +// +// Inputs: +// pArray - Pointer to array +// Size - new number of elements in the the array +// MemFlags - memory allocate flags (IBA_MEM_FLAG_*) +// +// Outputs: +// ppNewElements - *ppNewElements memory allocated for use in ArraySet or +// ArraySetSize or ArraySetCapacity +// +// Returns: +// FSUCCESS - successfully allocated (or no allocation needed) +// FINSUFFICIENT_MEMORY - unable to allocate +// +/////////////////////////////////////////////////////////////////////////////// +FSTATUS +ArrayPrepareSize( + IN ARRAY* const pArray, + IN const uint32 Size, + IN const uint32 MemFlags, + OUT void** ppNewElements) +{ + DEBUG_ASSERT( pArray ); + DEBUG_ASSERT( ppNewElements ); + + *ppNewElements = NULL; + // Check to see if the requested size requires growth + if( Size <= AtomicRead(&pArray->m_Capacity) ) + return( FSUCCESS ); + + *ppNewElements = MemoryAllocate2AndClear( + pArray->m_ElementSize* + ArrayComputeCapacity(pArray, Size), + MemFlags, ARR_MEM_TAG); + if( !*ppNewElements ) + return( FINSUFFICIENT_MEMORY ); + return( FSUCCESS ); +} + + +/////////////////////////////////////////////////////////////////////////////// +// ArraySetSize +// +// Description: +// This function resizes the array to the specified number of +// elements. This function can only fail if the new size is larger than +// the old capacity. +// +// Inputs: +// pArray - Pointer to array +// Size - new number of elements in the the array +// MemFlags - memory allocate flags (IBA_MEM_FLAG_*) +// ppNewElements - *ppNewElements is potential new storage for array resize +// must have been returned by ArrayPrepareSize(Size) +// +// Outputs: +// ppNewElements - *ppNewElements is set to NULL if ppNewElements was used +// +// Returns: +// FSUCCESS +// FINSUFFICIENT_MEMORY - array will have at least as many elements +// as prior to the call. Use ArrayGetSize() +// to determine the number of elements +// +/////////////////////////////////////////////////////////////////////////////// +FSTATUS +ArraySetSize( + IN ARRAY* const pArray, + IN const uint32 Size, + IN const uint32 MemFlags, + IN OUT void** ppNewElements OPTIONAL) +{ + FSTATUS Status; + + DEBUG_ASSERT( pArray ); + + // Check to see if the requested size is the same as the existing size. + if( Size == pArray->m_Size ) + return( FSUCCESS ); + + // Determine if the array has room for this element. + if( Size > AtomicRead(&pArray->m_Capacity) ) + { + Status = ArraySetCapacity( pArray, ArrayComputeCapacity(pArray, Size), + MemFlags, ppNewElements ); + if( Status != FSUCCESS ) + return( Status ); + } + + // Are we shrinking the array? + if( Size < pArray->m_Size ) + { + uint32 NewBytes = Size * pArray->m_ElementSize; + uint32 OldBytes = pArray->m_Size * pArray->m_ElementSize; + + // zero the removed elements + MemoryClear(pArray->m_pElements+NewBytes, OldBytes - NewBytes); + } + + pArray->m_Size = Size; + return( FSUCCESS ); +} + + +/////////////////////////////////////////////////////////////////////////////// +// ArraySetMinSize +// +// Description: +// This function resizes the array to the specified number of +// elements only if the current number of elements in the array is fewer +// than the specified size. +// +// Inputs: +// pArray - Pointer to array +// MinSize - at least the number of elements needed in the array +// MemFlags - memory allocate flags (IBA_MEM_FLAG_*) +// ppNewElements - *ppNewElements is potential new storage for array resize +// must have been returned by ArrayPrepareSize(Size) +// +// Outputs: +// ppNewElements - *ppNewElements is set to NULL if ppNewElements was used +// +// Returns: +// FSUCCESS +// FINSUFFICIENT_MEMORY - array is left unaltered +// +/////////////////////////////////////////////////////////////////////////////// +FSTATUS ArraySetMinSize( + IN ARRAY* const pArray, + IN const uint32 MinSize, + IN const uint32 MemFlags, + IN OUT void** ppNewElements OPTIONAL) +{ + DEBUG_ASSERT( pArray ); + + if( MinSize > pArray->m_Size ) + { + // We have to resize the array + return( ArraySetSize( pArray, MinSize, MemFlags, ppNewElements ) ); + } + + // We didn't have to do anything + return( FSUCCESS ); +} + + +/////////////////////////////////////////////////////////////////////////////// +// ArrayApplyFunc +// +// Description: +// This function calls the user supplied function for each item in the array. +// +// The called function has the form: +// void ApplyFunc( uint32 Index, void *pElement, void *Context ); +// where: +// Index = index of this element +// pElement = void* at this location in the array +// Context = user supplied context +// +// Inputs: +// pArray - pointer to array to iterate through +// pfnCallback - callback called for each non-NULL element +// Context - context to pass to callback function +// +// Outputs: +// None. +// +// Returns: +// None. +// +/////////////////////////////////////////////////////////////////////////////// +void +ArrayApplyFunc( + IN const ARRAY* const pArray, + IN ARR_APPLY_FUNC pfnCallback, + IN void* const Context ) +{ + uint32 i; + void *pElement; + + DEBUG_ASSERT( pArray ); + DEBUG_ASSERT( pfnCallback ); + + for( i = 0; i < pArray->m_Size; i++ ) + { + pElement = ArrayGetPtr( pArray, i ); + pfnCallback( i, pElement, Context ); + } +} + + +/////////////////////////////////////////////////////////////////////////////// +// ArrayFindFromStart +// +// Description: +// This function calls the specified function for each item in the array, +// starting from the beginning of the array, until the callback function +// returns TRUE or every item was processed. +// +// The called function has the form: +// boolean FindFunc( uint32 Index, void *pElement, void *Context ); +// where: +// Index = index of this element +// pElement = pointer to the element at this location in the array +// Context = user supplied context +// +// Inputs: +// pArray - pointer to array to iterate through +// pfnCallback - callback called for each non-NULL element +// Context - context to pass to callback function +// +// Outputs: +// None. +// +// Returns: +// Index value where execution stopped. If the callback function never +// returned TRUE, then the return value = the size of the array. +// +/////////////////////////////////////////////////////////////////////////////// +uint32 +ArrayFindFromStart( + IN const ARRAY* const pArray, + IN ARR_FIND_FUNC pfnCallback, + IN void* const Context ) +{ + uint32 i; + void *pElement; + + DEBUG_ASSERT( pArray ); + DEBUG_ASSERT( pfnCallback ); + + for( i = 0; i < pArray->m_Size; i++ ) + { + pElement = ArrayGetPtr( pArray, i ); + // Invoke the callback + if( pfnCallback( i, pElement, Context ) ) + break; + } + return( i ); +} + + +/////////////////////////////////////////////////////////////////////////////// +// ArrayFindFromEnd +// +// Description: +// This function calls the specified function for each item in the array, +// starting from the end of the array, until the callback function returns +// TRUE or every item was processed. +// +// The called function has the form: +// boolean FindFunc( uint32 Index, void *pElement, void *Context ); +// where: +// Index = index of this element +// pElement = pointer to the element at this location in the array +// Context = user supplied context +// +// Inputs: +// pArray - pointer to array to iterate through +// pfnCallback - callback called for each non-NULL element +// Context - context to pass to callback function +// +// Outputs: +// None. +// +// Returns: +// Index value where execution stopped. If the callback function never +// returned TRUE, then the return value = the size of the array. +// +/////////////////////////////////////////////////////////////////////////////// +uint32 +ArrayFindFromEnd( + IN const ARRAY* const pArray, + IN ARR_FIND_FUNC pfnCallback, + IN void* const Context ) +{ + uint32 i; + void *pElement; + + DEBUG_ASSERT( pArray ); + DEBUG_ASSERT( pfnCallback ); + + i = pArray->m_Size; + + while( i ) + { + // Get a pointer to the element in the array. + pElement = ArrayGetPtr( pArray, --i ); + DEBUG_ASSERT( pElement ); + + // Invoke the callback for the current element. + if( pfnCallback( i, pElement, Context ) ) + return i; + } + + return( pArray->m_Size ); +} + +/////////////////////////////////////////////////////////////////////////////// +// ArrayFindFromIndex +// +// Description: +// This function calls the specified function for each item in the array, +// starting from the given index of the array, until the callback function +// returns TRUE or every item was processed. +// +// The called function has the form: +// boolean FindFunc( uint32 Index, void *pElement, void *Context ); +// where: +// Index = index of this element +// pElement = pointer to the element at this location in the array +// Context = user supplied context +// +// Inputs: +// pArray - pointer to array to iterate through +// pfnCallback - callback called for each non-NULL element +// Context - context to pass to callback function +// Index - index to start from +// +// Outputs: +// None. +// +// Returns: +// Index value where execution stopped. If the callback function never +// returned TRUE, then the return value = the size of the array. +// +/////////////////////////////////////////////////////////////////////////////// +uint32 +ArrayFindFromIndex( + IN const ARRAY* const pArray, + IN ARR_FIND_FUNC pfnCallback, + IN void* const Context, + IN const uint32 Index + ) +{ + uint32 i; + void *pElement; + + DEBUG_ASSERT( pArray ); + DEBUG_ASSERT( pfnCallback ); + + // if Index is beyond Size, we will exit this loop immediately + for( i = Index; i < pArray->m_Size; i++ ) + { + pElement = ArrayGetPtr( pArray, i ); + // Invoke the callback + if( pfnCallback( i, pElement, Context ) ) + return( i ); + } + + for( i = 0; i < Index; i++ ) + { + // Get a pointer to the element in the array. + pElement = ArrayGetPtr( pArray, i ); + DEBUG_ASSERT( pElement ); + + // Invoke the callback for the current element. + if( pfnCallback( i, pElement, Context ) ) + return i; + } + + return( pArray->m_Size ); +} diff --git a/IbAccess/Common/Public/iarray.h b/IbAccess/Common/Public/iarray.h new file mode 100644 index 0000000..c986683 --- /dev/null +++ b/IbAccess/Common/Public/iarray.h @@ -0,0 +1,1098 @@ +/* BEGIN_ICS_COPYRIGHT3 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT3 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + + +#ifndef _IBA_PUBLIC_IARRAY_H_ +#define _IBA_PUBLIC_IARRAY_H_ + +#include "iba/public/datatypes.h" +#include "iba/public/imemory.h" +#include "iba/public/ispinlock.h" + + +#ifdef __cplusplus +extern "C" +{ +#endif + +/* Callback function declarations. */ +typedef void (*ARR_APPLY_FUNC)( + IN const uint32 Index, + IN void* const Elem, + IN void* const Context ); + +typedef boolean (*ARR_FIND_FUNC)( + IN const uint32 Index, + IN void* const Elem, + IN void* const Context ); + +/**************************************************************************** + * + * Array definition. + * + * Array statically stores items in an array, providing constant access + * times. The array can be resized dynamically. When the array is resized, + * objects in the array are relocated in memory. + * + * The array is an efficient dynamic storage for simple elements. If persistent + * pointers to the elements in the array are required, a VECTOR should be + * used instead. + */ + + +/* The array structure is allocated by the user and is opaque to them */ +typedef struct _ARRAY +{ + /* fields are PRIVATE and should NOT be used directly by callers */ + uint32 m_Size; /* # of elements logically in the array. */ + uint32 m_GrowSize; /* # of elements to grab when growing. */ + uint32 m_ElementSize; /* Size of each element. */ + ATOMIC_UINT m_Capacity; /* total # of elements allocated. */ + /* This is atomic only so ArrayPrepareSize */ + /* can be called without holding locks */ + uint8 *m_pElements; /* Internal array of elements. */ + +} ARRAY; + + + +/**************************************************************************** + * array access methods + * These methods are an attempt to follow the functionality of the C++ STL. + * The names and behavior are obviously not exact matches, but hopefully, + * close enough to make those familiar with the ANSI standard comfortable. + ****************************************************************************/ + + +/**************************************************************************** + * ArrayInitState + * + * Description: + * This function performs basic array initialization. This function cannot + * fail. + * + * Inputs: + * pArray - Pointer to array + * + * Outputs: + * None. + * + * Returns: + * None. + * + ****************************************************************************/ +void +ArrayInitState( + IN ARRAY* const pArray ); + + +/**************************************************************************** + * ArrayInit + * + * Description: + * This function initializes the array. New elements in the array are + * initialized to 0. + * + * Inputs: + * pArray - Pointer to array + * InitialSize - initial number of elements + * GrowSize - number of elements to allocate when incrementally growing + * the array + * ElementSize - size of each element in the array + * MemFlags - memory allocate flags (IBA_MEM_FLAG_*) + * + * Outputs: + * None. + * + * Returns: + * FSUCCESS + * FINSUFFICIENT_MEMORY - array is initialized to zero size + * + ****************************************************************************/ +FSTATUS +ArrayInit( + IN ARRAY* const pArray, + IN const uint32 InitialSize, + IN const uint32 GrowSize, + IN const uint32 ElementSize, + IN const uint32 MemFlags ); + + +/**************************************************************************** + * ArrayDestroy + * + * Description: + * This function deallocates all allocated memory associated with the array. + * The array is left initialized to zero size. This function does not fail. + * If any Array operations did premptable memory allocate (via MemFlags), this + * may prempt. + * + * Inputs: + * pArray - Pointer to array + * + * Outputs: + * None. + * + * Returns: + * None. + * + ****************************************************************************/ +void +ArrayDestroy( + IN ARRAY* const pArray ); + + +/**************************************************************************** + * ArrayGetCapacity + * + * Description: + * This function returns the current capacity of the array. + * This function cannot fail. + * + * Inputs: + * pArray - Pointer to array + * + * Outputs: + * None. + * + * Returns: + * Capacity, in objects, of the array. + * + ****************************************************************************/ +static __inline uint32 +ArrayGetCapacity( + IN const ARRAY* const pArray ) +{ + DEBUG_ASSERT( pArray ); + return( AtomicRead(&pArray->m_Capacity) ); +} + + +/**************************************************************************** + * ArrayGetSize + * + * Description: + * This function returns the size of the array. This function cannot fail. + * + * Inputs: + * pArray - Pointer to array + * + * Outputs: + * None. + * + * Returns: + * Size, in objects, of the array. + * + ****************************************************************************/ +static __inline uint32 +ArrayGetSize( + IN const ARRAY* const pArray ) +{ + DEBUG_ASSERT( pArray ); + return( pArray->m_Size ); +} + + +/**************************************************************************** + * ArrayGetPtr + * + * Description: + * This function returns a pointer to the element at the specified index. + * Range checking is NOT performed. Provides constant time access. + * + * Inputs: + * pArray - Pointer to array. + * Index - Index of element to get. + * + * Outputs: + * Pointer to the element. + * + * Returns: + * None. + * + * Notes: + * Pointers retrieved are not valid if the array is resized. + * + ****************************************************************************/ +static __inline void* +ArrayGetPtr( + IN const ARRAY* const pArray, + IN const uint32 Index ) +{ + return( pArray->m_pElements + (Index*pArray->m_ElementSize) ); +} + + +/**************************************************************************** + * ArrayGet + * + * Description: + * This function returns the element at the specified index. The returned + * element is a copy of the element in the array. Range checking is NOT + * performed. Provides constant time access. + * + * Inputs: + * pArray - Pointer to array. + * Index - Index of element to get. + * pElement - Pointer to storage for the element to be returned. + * + * Outputs: + * pElement - Copy of the desired element. + * + * Returns: + * None. + * + ****************************************************************************/ +static __inline void +ArrayGet( + IN const ARRAY* const pArray, + IN const uint32 Index, + OUT void * const pElement ) +{ + DEBUG_ASSERT( pArray ); + DEBUG_ASSERT( pElement ); + + /* Get a pointer to the element. */ + MemoryCopy(pElement, ArrayGetPtr( pArray, Index ), pArray->m_ElementSize ); +} + +/**************************************************************************** + * ArrayAt + * + * Description: + * This function returns the element at the specified index. The returned + * element is a copy of the element in the array. Range checking is + * performed. Provides constant time access. + * + * Inputs: + * pArray - Pointer to array. + * Index - Index of element to get. + * pElement - Pointer to storage for the element to be returned. + * + * Outputs: + * pElement - Copy of the desired element. + * + * Returns: + * FSUCCESS + * FINVALID_PARAMETER Index out of range. + * + ****************************************************************************/ +static __inline +FSTATUS +ArrayAt( + IN const ARRAY* const pArray, + IN const uint32 Index, + OUT void* const pElement ) +{ + DEBUG_ASSERT( pArray ); /* Other asserts are in ArrayGet */ + + /* Range check */ + if( IB_EXPECT_FALSE(Index >= pArray->m_Size )) + return( FINVALID_PARAMETER ); + + ArrayGet( pArray, Index, pElement ); + return( FSUCCESS ); +} + + + +/**************************************************************************** + * ArraySet + * + * Description: + * This function sets the element at the specified index. The array grows as + * necessary. + * + * Inputs: + * pArray - Pointer to array. + * Index - Index of element to get. + * pElement - Pointer to the element to set at the specified index. + * MemFlags - memory allocate flags (IBA_MEM_FLAG_*) + * ppNewElements - *ppNewElements is potential new storage for array resize + * must have been returned by ArrayPrepareSet(Index) + * + * Outputs: + * ppNewElements - *ppNewElements is set to NULL if ppNewElements was used + * + * Returns: + * FSUCCESS + * FINSUFFICIENT_MEMORY The array could not be resized to accomodate the + * specified element. + * + ****************************************************************************/ +FSTATUS +ArraySet( + IN ARRAY* const pArray, + IN const uint32 Index, + IN void* const pElement, + IN const uint32 MemFlags, + IN OUT void** ppNewElements OPTIONAL); + + +/**************************************************************************** + * ArrayGetPtr32 + * + * Description: + * This function returns a pointer to the element at the specified index. + * Range checking is NOT performed. Provides constant time access. + * Optimized for ElementSize of 32 bits + * + * Inputs: + * pArray - Pointer to array. + * Index - Index of element to get. + * + * Outputs: + * Pointer to the element. + * + * Returns: + * None. + * + * Notes: + * Pointers retrieved are not valid if the array is resized. + * + ****************************************************************************/ +static __inline uint32* +ArrayGetPtr32( + IN const ARRAY* const pArray, + IN const uint32 Index ) +{ + DEBUG_ASSERT(pArray->m_ElementSize == sizeof(uint32)); + return( (uint32*)pArray->m_pElements + Index ); +} + + +/**************************************************************************** + * ArrayGet32 + * + * Description: + * This function returns the element at the specified index. The returned + * element is a copy of the element in the array. Range checking is NOT + * performed. Provides constant time access. + * Optimized for ElementSize of 32 bits + * + * Inputs: + * pArray - Pointer to array. + * Index - Index of element to get. + * + * Outputs: + * + * Returns: + * copy of desired element + * + ****************************************************************************/ +static __inline uint32 +ArrayGet32( + IN const ARRAY* const pArray, + IN const uint32 Index ) +{ + DEBUG_ASSERT( pArray ); + + return *(ArrayGetPtr32( pArray, Index )); +} + + +/**************************************************************************** + * ArrayAt32 + * + * Description: + * This function returns the element at the specified index. The returned + * element is a copy of the element in the array. Range checking is + * performed. Provides constant time access. + * Optimized for ElementSize of 32 bits + * + * Inputs: + * pArray - Pointer to array. + * Index - Index of element to get. + * pElement - Pointer to storage for the element to be returned. + * + * Outputs: + * pElement - Copy of the desired element. + * + * Returns: + * FSUCCESS + * FINVALID_PARAMETER Index out of range. + * + ****************************************************************************/ +static __inline +FSTATUS +ArrayAt32( + IN const ARRAY* const pArray, + IN const uint32 Index, + OUT uint32* const pElement ) +{ + DEBUG_ASSERT( pArray ); /* Other asserts are in ArrayGet */ + + /* Range check */ + if( IB_EXPECT_FALSE(Index >= pArray->m_Size )) + return( FINVALID_PARAMETER ); + + *pElement = ArrayGet32( pArray, Index); + return( FSUCCESS ); +} + + + +/**************************************************************************** + * ArraySet32 + * + * Description: + * This function sets the element at the specified index. The array grows as + * necessary. + * Optimized for ElementSize of 32 bits + * + * Inputs: + * pArray - Pointer to array. + * Index - Index of element to get. + * Element - the element to set at the specified index. + * MemFlags - memory allocate flags (IBA_MEM_FLAG_*) + * ppNewElements - *ppNewElements is potential new storage for array resize + * must have been returned by ArrayPrepareSet(Index) + * + * Outputs: + * ppNewElements - *ppNewElements is set to NULL if ppNewElements was used + * + * Returns: + * FSUCCESS + * FINSUFFICIENT_MEMORY The array could not be resized to accomodate the + * specified element. + * + ****************************************************************************/ +FSTATUS +ArraySet32( + IN ARRAY* const pArray, + IN const uint32 Index, + IN uint32 Element, + IN const uint32 MemFlags, + IN OUT void** ppNewElements OPTIONAL); + + +/**************************************************************************** + * ArrayGetPtr64 + * + * Description: + * This function returns a pointer to the element at the specified index. + * Range checking is NOT performed. Provides constant time access. + * Optimized for ElementSize of 64 bits + * + * Inputs: + * pArray - Pointer to array. + * Index - Index of element to get. + * + * Outputs: + * Pointer to the element. + * + * Returns: + * None. + * + * Notes: + * Pointers retrieved are not valid if the array is resized. + * + ****************************************************************************/ +static __inline uint64* +ArrayGetPtr64( + IN const ARRAY* const pArray, + IN const uint32 Index ) +{ + DEBUG_ASSERT(pArray->m_ElementSize == sizeof(uint64)); + return( (uint64*)pArray->m_pElements + Index ); +} + + +/**************************************************************************** + * ArrayGet64 + * + * Description: + * This function returns the element at the specified index. The returned + * element is a copy of the element in the array. Range checking is NOT + * performed. Provides constant time access. + * Optimized for ElementSize of 64 bits + * + * Inputs: + * pArray - Pointer to array. + * Index - Index of element to get. + * + * Outputs: + * + * Returns: + * copy of desired element + * + ****************************************************************************/ +static __inline uint64 +ArrayGet64( + IN const ARRAY* const pArray, + IN const uint32 Index ) +{ + DEBUG_ASSERT( pArray ); + + return *(ArrayGetPtr64( pArray, Index )); +} + + +/**************************************************************************** + * ArrayAt64 + * + * Description: + * This function returns the element at the specified index. The returned + * element is a copy of the element in the array. Range checking is + * performed. Provides constant time access. + * Optimized for ElementSize of 64 bits + * + * Inputs: + * pArray - Pointer to array. + * Index - Index of element to get. + * pElement - Pointer to storage for the element to be returned. + * + * Outputs: + * pElement - Copy of the desired element. + * + * Returns: + * FSUCCESS + * FINVALID_PARAMETER Index out of range. + * + ****************************************************************************/ +static __inline +FSTATUS +ArrayAt64( + IN const ARRAY* const pArray, + IN const uint32 Index, + OUT uint64* const pElement ) +{ + DEBUG_ASSERT( pArray ); /* Other asserts are in ArrayGet */ + + /* Range check */ + if( IB_EXPECT_FALSE(Index >= pArray->m_Size )) + return( FINVALID_PARAMETER ); + + *pElement = ArrayGet64( pArray, Index); + return( FSUCCESS ); +} + + + + +/**************************************************************************** + * ArraySet64 + * + * Description: + * This function sets the element at the specified index. The array grows as + * necessary. + * Optimized for ElementSize of 64 bits + * + * Inputs: + * pArray - Pointer to array. + * Index - Index of element to get. + * Element - the element to set at the specified index. + * MemFlags - memory allocate flags (IBA_MEM_FLAG_*) + * ppNewElements - *ppNewElements is potential new storage for array resize + * must have been returned by ArrayPrepareSet(Index) + * + * Outputs: + * ppNewElements - *ppNewElements is set to NULL if ppNewElements was used + * + * Returns: + * FSUCCESS + * FINSUFFICIENT_MEMORY The array could not be resized to accomodate the + * specified element. + * + ****************************************************************************/ +FSTATUS +ArraySet64( + IN ARRAY* const pArray, + IN const uint32 Index, + IN uint64 Element, + IN const uint32 MemFlags, + IN OUT void** ppNewElements OPTIONAL); + + +/**************************************************************************** + * ArrayGetPtrPointer + * + * Description: + * This function returns a pointer to the element at the specified index. + * Range checking is NOT performed. Provides constant time access. + * Optimized for ElementSize of sizeof(void*) + * + * Inputs: + * pArray - Pointer to array. + * Index - Index of element to get. + * + * Outputs: + * Pointer to the element. + * + * Returns: + * None. + * + * Notes: + * Pointers retrieved are not valid if the array is resized. + * + ****************************************************************************/ +static __inline void** +ArrayGetPtrPointer( + IN const ARRAY* const pArray, + IN const uint32 Index ) +{ + DEBUG_ASSERT(pArray->m_ElementSize == sizeof(void*)); + return( (void**)pArray->m_pElements + Index ); +} + + +/**************************************************************************** + * ArrayGetPointer + * + * Description: + * This function returns the element at the specified index. The returned + * element is a copy of the element in the array. Range checking is NOT + * performed. Provides constant time access. + * Optimized for ElementSize of sizeof(void*) + * + * Inputs: + * pArray - Pointer to array. + * Index - Index of element to get. + * + * Outputs: + * + * Returns: + * copy of desired element + * + ****************************************************************************/ +static __inline void* +ArrayGetPointer( + IN const ARRAY* const pArray, + IN const uint32 Index ) +{ + DEBUG_ASSERT( pArray ); + + return *(ArrayGetPtrPointer( pArray, Index )); +} + + +/**************************************************************************** + * ArrayAtPointer + * + * Description: + * This function returns the element at the specified index. The returned + * element is a copy of the element in the array. Range checking is + * performed. Provides constant time access. + * Optimized for ElementSize of sizeof(void*) + * + * Inputs: + * pArray - Pointer to array. + * Index - Index of element to get. + * pElement - Pointer to storage for the element to be returned. + * + * Outputs: + * pElement - Copy of the desired element. + * + * Returns: + * FSUCCESS + * FINVALID_PARAMETER Index out of range. + * + ****************************************************************************/ +static __inline +FSTATUS +ArrayAtPointer( + IN const ARRAY* const pArray, + IN const uint32 Index, + OUT void** const pElement ) +{ + DEBUG_ASSERT( pArray ); /* Other asserts are in ArrayGet */ + + /* Range check */ + if( IB_EXPECT_FALSE(Index >= pArray->m_Size )) + return( FINVALID_PARAMETER ); + + *pElement = ArrayGetPointer( pArray, Index ); + return( FSUCCESS ); +} + + + + +/**************************************************************************** + * ArraySetPointer + * + * Description: + * This function sets the element at the specified index. The array grows as + * necessary. + * Optimized for ElementSize of sizeof(void*) + * + * Inputs: + * pArray - Pointer to array. + * Index - Index of element to get. + * Element - the element to set at the specified index. + * MemFlags - memory allocate flags (IBA_MEM_FLAG_*) + * ppNewElements - *ppNewElements is potential new storage for array resize + * must have been returned by ArrayPrepareSet(Index) + * + * Outputs: + * ppNewElements - *ppNewElements is set to NULL if ppNewElements was used + * + * Returns: + * FSUCCESS + * FINSUFFICIENT_MEMORY The array could not be resized to accomodate the + * specified element. + * + ****************************************************************************/ +FSTATUS +ArraySetPointer( + IN ARRAY* const pArray, + IN const uint32 Index, + IN void* Element, + IN const uint32 MemFlags, + IN OUT void** ppNewElements OPTIONAL); + +/**************************************************************************** + * ArraySetCapacity + * + * Description: + * This function reserves capacity in the array to the specified number of + * elements. This function can only fail if the new capacity is larger than + * the old capacity. If the new capacity is less than the old, no action + * is taken. + * + * Inputs: + * pArray - Pointer to array + * NewCapacity - Number of elements reserved in the array + * MemFlags - memory allocate flags (IBA_MEM_FLAG_*) + * ppNewElements - *ppNewElements is potential new storage for array resize + * must have been returned by ArrayPrepareSize(Size) + * + * Outputs: + * ppNewElements - *ppNewElements is set to NULL if ppNewElements was used + * + * Returns: + * FSUCCESS + * FINSUFFICIENT_MEMORY - array is left unaltered + * + ****************************************************************************/ +FSTATUS +ArraySetCapacity( + IN ARRAY* const pArray, + IN const uint32 NewCapacity, + IN const uint32 MemFlags, + IN OUT void** ppNewElements OPTIONAL); + + +/**************************************************************************** + * ArrayPrepareSize + * + * Description: + * This function allocates the storage that would be needed to resize the + * the array to the specified number of elements. + * This function can only fail if the new size is larger than + * the old capacity. + * + * This allows for premptable array allocation for arrays which must be + * guarded by spin locks. For example: + * if (FSUCCESS != ArrayPrepareSize(&myArray, Size, + * IBA_MEM_FLAG_PREMPTABLE, &pNewElements)) + * failure return + * SpinLockAcquire + * status = ArraySetSize(&myArray, Size, &pNewElements); + * SpinLockRelease + * if (pNewElements) + * MemoryDeallocate(pNewElements); + * + * Inputs: + * pArray - Pointer to array + * Size - new number of elements in the the array + * MemFlags - memory allocate flags (IBA_MEM_FLAG_*) + * + * Outputs: + * ppNewElements - *ppNewElements memory allocated for use in ArraySet or + * ArraySetSize or ArraySetCapacity + * + * Returns: + * FSUCCESS - successfully allocated (or no allocation needed) + * FINSUFFICIENT_MEMORY - unable to allocate + * + ****************************************************************************/ +FSTATUS +ArrayPrepareSize( + IN ARRAY* const pArray, + IN const uint32 Size, + IN const uint32 MemFlags, + OUT void** ppNewElements); + + +/**************************************************************************** + * ArrayPrepareSet + * + * Description: + * This function allocates the storage that would be needed to resize the + * the array to ArraySet the specified element. + * This function can only fail if the Index would require a new size larger + * than the old capacity. + * + * This allows for premptable array allocation for arrays which must be + * guarded by spin locks. For example: + * if (FSUCCESS != ArrayPrepareSet(&myArray, Index, + * IBA_MEM_FLAG_PREMPTABLE, &pNewElements)) + * failure return + * SpinLockAcquire + * status = ArraySet32(&myArray, Index, value, &pNewElements); + * SpinLockRelease + * if (pNewElements) + * MemoryDeallocate(pNewElements); + * + * Inputs: + * pArray - Pointer to array + * Index - element Index which is about to be Set + * MemFlags - memory allocate flags (IBA_MEM_FLAG_*) + * + * Outputs: + * ppNewElements - *ppNewElements memory allocated for use in ArraySet or + * ArraySetSize + * + * Returns: + * FSUCCESS - successfully allocated (or no allocation needed) + * FINSUFFICIENT_MEMORY - unable to allocate + * + ****************************************************************************/ +static __inline FSTATUS +ArrayPrepareSet( + IN ARRAY* const pArray, + IN const uint32 Index, + IN const uint32 MemFlags, + OUT void** ppNewElements) +{ + return ArrayPrepareSize(pArray, Index+1, MemFlags, ppNewElements); +} + +/**************************************************************************** + * ArraySetSize + * + * Description: + * This function resizes the array to the specified number of + * elements. This function can only fail if the new size is larger than + * the old capacity. + * + * Inputs: + * pArray - Pointer to array + * Size - new number of elements in the the array + * MemFlags - memory allocate flags (IBA_MEM_FLAG_*) + * ppNewElements - *ppNewElements is potential new storage for array resize + * must have been returned by ArrayPrepareSize(Size) + * + * Outputs: + * ppNewElements - *ppNewElements is set to NULL if ppNewElements was used + * + * Returns: + * FSUCCESS + * FINSUFFICIENT_MEMORY - array will have at least as many elements + * as prior to the call. Use ArrayGetSize() + * to determine the number of elements + * + ****************************************************************************/ +FSTATUS +ArraySetSize( + IN ARRAY* const pArray, + IN const uint32 Size, + IN const uint32 MemFlags, + IN OUT void** ppNewElements OPTIONAL); + + +/**************************************************************************** + * ArraySetMinSize + * + * Description: + * This function resizes the array to the specified number of + * elements only if the current number of elements in the array is fewer + * than the specified size. + * + * Inputs: + * pArray - Pointer to array + * MinSize - at least the number of elements needed in the array + * MemFlags - memory allocate flags (IBA_MEM_FLAG_*) + * ppNewElements - *ppNewElements is potential new storage for array resize + * must have been returned by ArrayPrepareSize(Size) + * + * Outputs: + * ppNewElements - *ppNewElements is set to NULL if ppNewElements was used + * + * Returns: + * FSUCCESS + * FINSUFFICIENT_MEMORY - array is left unaltered + * + ****************************************************************************/ +FSTATUS ArraySetMinSize( + IN ARRAY* const pArray, + IN const uint32 MinSize, + IN const uint32 MemFlags, + IN OUT void** ppNewElements OPTIONAL); + + +/**************************************************************************** + * ArrayApplyFunc + * + * Description: + * This function calls the user supplied function for each item in the array, + * starting from the beginning of the array. + * + * The called function has the form: + * void ApplyFunc( uint32 Index, void *pElement, void *Context ); + * where: + * Index = index of this element + * pElement = void* at this location in the array + * Context = user supplied context + * + * Inputs: + * pArray - pointer to array to iterate through + * pfnCallback - callback called for each non-NULL element + * Context - context to pass to callback function + * + * Outputs: + * None. + * + * Returns: + * None. + * + ****************************************************************************/ +void +ArrayApplyFunc( + IN const ARRAY* const pArray, + IN ARR_APPLY_FUNC pfnCallback, + IN void* const Context ); + + +/**************************************************************************** + * ArrayFindFromStart + * + * Description: + * This function calls the specified function for each item in the array, + * starting from the beginning of the array, until the callback function + * returns TRUE or every item was processed. + * + * The called function has the form: + * boolean FindFunc( uint32 Index, void *pElement, void *Context ); + * where: + * Index = index of this element + * pElement = pointer to the element at this location in the array + * Context = user supplied context + * + * Inputs: + * pArray - pointer to array to iterate through + * pfnCallback - callback called for each non-NULL element + * Context - context to pass to callback function + * + * Outputs: + * None. + * + * Returns: + * Index value where execution stopped. If the callback function never + * returned TRUE, then the return value = the size of the array. + * + ****************************************************************************/ +uint32 +ArrayFindFromStart( + IN const ARRAY* const pArray, + IN ARR_FIND_FUNC pfnCallback, + IN void* const Context ); + + +/**************************************************************************** + * ArrayFindFromEnd + * + * Description: + * This function calls the specified function for each item in the array, + * starting from the end of the array, until the callback function returns + * TRUE or every item was processed. + * + * The called function has the form: + * boolean FindFunc( uint32 Index, void *pElement, void *Context ); + * where: + * Index = index of this element + * pElement = pointer to the element at this location in the array + * Context = user supplied context + * + * Inputs: + * pArray - pointer to array to iterate through + * pfnCallback - callback called for each non-NULL element + * Context - context to pass to callback function + * + * Outputs: + * None. + * + * Returns: + * Index value where execution stopped. If the callback function never + * returned TRUE, then the return value = the size of the array. + * + ****************************************************************************/ +uint32 +ArrayFindFromEnd( + IN const ARRAY* const pArray, + IN ARR_FIND_FUNC pfnCallback, + IN void* const Context ); + + +/////////////////////////////////////////////////////////////////////////////// +// ArrayFindFromIndex +// +// Description: +// This function calls the specified function for each item in the array, +// starting from the given index of the array, until the callback function +// returns TRUE or every item was processed. +// +// The called function has the form: +// boolean FindFunc( uint32 Index, void *pElement, void *Context ); +// where: +// Index = index of this element +// pElement = pointer to the element at this location in the array +// Context = user supplied context +// +// Inputs: +// pArray - pointer to array to iterate through +// pfnCallback - callback called for each non-NULL element +// Context - context to pass to callback function +// Index - index to start from +// +// Outputs: +// None. +// +// Returns: +// Index value where execution stopped. If the callback function never +// returned TRUE, then the return value = the size of the array. +// +/////////////////////////////////////////////////////////////////////////////// +uint32 +ArrayFindFromIndex( + IN const ARRAY* const pArray, + IN ARR_FIND_FUNC pfnCallback, + IN void* const Context, + IN const uint32 Index + ); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + + +#endif /* _IBA_PUBLIC_IARRAY_H_ */ diff --git a/IbAccess/Common/Public/ibitvector.c b/IbAccess/Common/Public/ibitvector.c new file mode 100644 index 0000000..e0802de --- /dev/null +++ b/IbAccess/Common/Public/ibitvector.c @@ -0,0 +1,829 @@ +/* BEGIN_ICS_COPYRIGHT6 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT6 ****************************************/ + + +#include "ibitvector.h" +#include "imemory.h" +#include "imath.h" + +// Make a memory tag of 'ivec' for ivector. +#define VEC_MEM_TAG MAKE_MEM_TAG( i, v, e, c ) + + +/////////////////////////////////////////////////////////////////////////////// +// bit vector access methods +// These methods are an attempt to follow the functionality of the C++ STL. +// The names and behavior are obviously not exact matches, but hopefully, +// close enough to make those familiar with the ANSI standard comfortable. +/////////////////////////////////////////////////////////////////////////////// + + +/////////////////////////////////////////////////////////////////////////////// +// BitVectorInitState +// +// Description: +// This function performs basic bit vector initialization. This function cannot +// fail. +// +// Inputs: +// pBitVector - Pointer to bit vector +// +// Outputs: +// None. +// +// Returns: +// None. +// +/////////////////////////////////////////////////////////////////////////////// +void +BitVectorInitState( + IN BIT_VECTOR* const pBitVector ) +{ + ASSERT( pBitVector ); + + MemoryClear( pBitVector, sizeof( BIT_VECTOR ) ); +} + + + +/////////////////////////////////////////////////////////////////////////////// +// BitVectorInit +// +// Description: +// This function initializes the bit vector. New bits in the bit vector are +// initialized to 0. +// +// Inputs: +// pBitVector - Pointer to bit vector +// InitialSize - prefered initial number of bits +// GrowSize - number of bits to allocate when incrementally growing +// the bit vector (will round up to multiple of processor +// word size) +// MaxSize - maximum number of bits in bit vector, 0 -> no limit +// Context - Context value passed to the callbacks. +// IsPageable - TRUE indicates the bit vector should use pageable memory +// FALSE indicates the bit vector should used non-paged memory +// +// Outputs: +// None. +// +// Returns: +// FSUCCESS +// FINSUFFICIENT_MEMORY - bit vector is initialized to zero size +// +/////////////////////////////////////////////////////////////////////////////// +FSTATUS +BitVectorInit( + IN BIT_VECTOR* const pBitVector, + IN const uint32 InitialSize, + IN const uint32 GrowSize, + IN const uint32 MaxSize, + IN boolean IsPageable ) +{ + FSTATUS Status; + + ASSERT( pBitVector ); + ASSERT( GrowSize ); + + BitVectorInitState( pBitVector ); + + pBitVector->m_GrowSize = ROUNDUPP2(GrowSize, _BIT_VECTOR_ENTRY_SIZE); + pBitVector->m_MaxSize = (MaxSize == 0)? IB_UINT32_MAX : MaxSize; + pBitVector->m_Pageable = IsPageable; + + // get the storage needed by the user + Status = BitVectorSetSize( pBitVector, MIN(InitialSize, pBitVector->m_MaxSize) ); + + return( Status ); +} + + +/////////////////////////////////////////////////////////////////////////////// +// BitVectorDestroy +// +// Description: +// This function deallocates all allocated memory associated with the bit vector. +// The bit vector is left initialized to zero size. This function does not fail. +// +// Inputs: +// pBitVector - Pointer to bit vector +// +// Outputs: +// None. +// +// Returns: +// None. +// +/////////////////////////////////////////////////////////////////////////////// +void +BitVectorDestroy( + IN BIT_VECTOR* const pBitVector ) +{ + ASSERT( pBitVector ); + + // Destroy the page bit vector. + if( pBitVector->m_pBitArray ) + { + MemoryDeallocate( pBitVector->m_pBitArray ); + } + + // reset internal state + pBitVector->m_Capacity = 0; + pBitVector->m_GrowSize = 0; + pBitVector->m_Size = 0; + pBitVector->m_pBitArray = NULL; + + return; +} + + +/////////////////////////////////////////////////////////////////////////////// +// BitVectorAt +// +// Description: +// This function returns the bit at the specified index. +// Range checking is performed. Provides constant time access. +// +// Inputs: +// pBitVector - Pointer to bit vector. +// Index - Index of bit to get. +// pValue - Pointer to storage for the bit to be returned. +// +// Outputs: +// pValue - Copy of the desired bit. +// +// Returns: +// FSUCCESS +// FINVALID_SETTING Index out of range. +// +/////////////////////////////////////////////////////////////////////////////// +FSTATUS +BitVectorAt( + IN const BIT_VECTOR* const pBitVector, + IN const uint32 Index, + OUT uint8* pValue ) +{ + ASSERT( pBitVector ); // Other asserts are in BitVectorGet + + // Range check + if( Index >= pBitVector->m_Size ) + return( FINVALID_PARAMETER ); + + *pValue = BitVectorGet( pBitVector, Index ); + return( FSUCCESS ); +} + + +/////////////////////////////////////////////////////////////////////////////// +// BitVectorSet +// +// Description: +// This function sets the bit at the specified index. The array grows as +// necessary. +// +// Inputs: +// pBitVector - Pointer to bit vector. +// Index - Index of bit to get. +// Value - value to set the bit to +// +// Outputs: +// None. +// +// Returns: +// FSUCCESS +// FINSUFFICIENT_MEMORY The array could not be resized to accomodate the +// specified bit. +// FINSUFFICIENT_RESOURCES - would grow vector beyond max size +// +/////////////////////////////////////////////////////////////////////////////// +FSTATUS +BitVectorSet( + IN BIT_VECTOR* const pBitVector, + IN const uint32 Index, + IN const uint8 Value ) +{ + FSTATUS Status; + + ASSERT( pBitVector ); + + // Determine if the bit vector has room for this bit. + if( Index >= pBitVector->m_Size ) + { + // Resize to accomodate the given index. + Status = BitVectorSetSize( pBitVector, Index + 1 ); + + // Check for failure on or before the given index. + if( (Status != FSUCCESS) && (pBitVector->m_Size <= Index) ) + return( Status ); + if (pBitVector->m_Size <= Index) { + return( FINSUFFICIENT_MEMORY ); + } + } + + // At this point, the array is guaranteed to be big enough + if (Value) + { + pBitVector->m_pBitArray[_BitVectorSubscript(Index)] |= _BitVectorMask(Index); + } else { + pBitVector->m_pBitArray[_BitVectorSubscript(Index)] &= ~_BitVectorMask(Index); + } + + return( FSUCCESS ); +} + + +/////////////////////////////////////////////////////////////////////////////// +// BitVectorSetCapacity +// +// Description: +// This function reserves capacity in the bit vector to the specified number of +// bits. This function can only fail if the new capacity is larger than +// the old capacity. If the new capacity is less than the old, no action +// is taken. When growing the capacity, new bits will have value 0. +// +// Inputs: +// pBitVector - Pointer to bit vector +// NewCapacity - Number of bits reserved in the array +// +// Outputs: +// None. +// +// Returns: +// FSUCCESS +// FINSUFFICIENT_MEMORY - bit vector is left unaltered +// +/////////////////////////////////////////////////////////////////////////////// +FSTATUS +BitVectorSetCapacity( + IN BIT_VECTOR* const pBitVector, + IN uint32 NewCapacity ) +{ + unsigned *pNewBitArray; + + ASSERT( pBitVector ); + + if (NewCapacity > pBitVector->m_MaxSize) + { + NewCapacity = pBitVector->m_MaxSize; + } + + // Do we have to do anything here? + if( NewCapacity <= pBitVector->m_Capacity ) + { + // Nope + return( FSUCCESS ); + } + + // Allocate our bit array. + pNewBitArray = (unsigned*)MemoryAllocateAndClear( ((NewCapacity+_BIT_VECTOR_ENTRY_SIZE)/_BIT_VECTOR_ENTRY_SIZE) * sizeof( unsigned ), + pBitVector->m_Pageable, VEC_MEM_TAG ); + if( !pNewBitArray ) + return( FINSUFFICIENT_MEMORY ); + + if( pBitVector->m_pBitArray ) + { + // Copy the old bit array into the new. + MemoryCopy( pNewBitArray, pBitVector->m_pBitArray, + ((pBitVector->m_Capacity+_BIT_VECTOR_ENTRY_SIZE)/_BIT_VECTOR_ENTRY_SIZE) * sizeof( unsigned ) ); + + // Free the old bit array. + MemoryDeallocate( pBitVector->m_pBitArray ); + } + + // Set the new array. + pBitVector->m_pBitArray = pNewBitArray; + + // Update the bit vector with the new capacity. + pBitVector->m_Capacity = NewCapacity; + + return( FSUCCESS ); +} + + +/////////////////////////////////////////////////////////////////////////////// +// BitVectorSetSize +// +// Description: +// This function resizes the bit vector to the specified number of +// bits. This function can only fail if the new size is larger than +// the old capacity. +// +// Inputs: +// pBitVector - Pointer to bit vector +// Size - new number of bits in the the array +// +// Outputs: +// None. +// +// Returns: +// FSUCCESS +// FINSUFFICIENT_MEMORY - bit vector will have at least as many bits +// as prior to the call. Use BitVectorGetSize() +// to determine the number of bits +// FINSUFFICIENT_RESOURCES - would grow vector beyond max size +// +/////////////////////////////////////////////////////////////////////////////// +FSTATUS +BitVectorSetSize( + IN BIT_VECTOR* const pBitVector, + IN const uint32 Size ) +{ + FSTATUS Status; + uint32 NewCapacity; + + ASSERT( pBitVector ); + + if( Size == pBitVector->m_Size ) + return( FSUCCESS ); // no change + if (Size > pBitVector->m_MaxSize) + return( FINSUFFICIENT_RESOURCES ); + + // Determine if the bit vector has room. + if( Size >= pBitVector->m_Capacity ) + { + // keep capacity as a multiple of GrowSize + NewCapacity = ROUNDUP(Size, pBitVector->m_GrowSize); + Status = BitVectorSetCapacity( pBitVector, NewCapacity ); + if( Status != FSUCCESS ) + return( Status ); + } + + pBitVector->m_Size = Size; + return( FSUCCESS ); +} + + +/////////////////////////////////////////////////////////////////////////////// +// BitVectorSetMinSize +// +// Description: +// This function resizes the bit vector to the specified number of +// bits only if the current number of bits in the array is fewer +// than the specified size. +// +// Inputs: +// pBitVector - Pointer to bit vector +// MinSize - at least the number of bitbits needed in the array +// +// Outputs: +// None. +// +// Returns: +// FSUCCESS +// FINSUFFICIENT_MEMORY - bit vector is left unaltered +// +/////////////////////////////////////////////////////////////////////////////// +FSTATUS BitVectorSetMinSize( + IN BIT_VECTOR* const pBitVector, + IN const uint32 MinSize ) +{ + ASSERT( pBitVector ); + + if( MinSize > pBitVector->m_Size ) + { + // We have to resize the array + return( BitVectorSetSize( pBitVector, MinSize ) ); + } + + // We didn't have to do anything + return( FSUCCESS ); +} + + +/////////////////////////////////////////////////////////////////////////////// +// BitVectorApplyFunc +// +// Description: +// This function calls the user supplied function for each item in the bit vector. +// +// The called function has the form: +// void ApplyFunc( uint32 Index, uint8 Value, void *Context ); +// where: +// Index = index of this bit +// Value = value of bit at this Index in the array +// Context = user supplied context +// +// Inputs: +// pBitVector - pointer to bit vector to iterate through +// pfnCallback - callback called for each non-NULL bit +// Context - context to pass to callback function +// +// Outputs: +// None. +// +// Returns: +// None. +// +/////////////////////////////////////////////////////////////////////////////// +void +BitVectorApplyFunc( + IN const BIT_VECTOR* const pBitVector, + IN BITVEC_APPLY_FUNC pfnCallback, + IN void* const Context ) +{ + return BitVectorApplyFuncRange(pBitVector, pfnCallback, Context, + 0, pBitVector->m_Size); +} + + +/////////////////////////////////////////////////////////////////////////////// +// BitVectorApplyFuncRange +// +// Description: +// This function calls the user supplied function for each item in the bit vector +// across the given range of indexes of the bit vector. +// +// The called function has the form: +// void ApplyFunc( uint32 Index, uint8 Value, void *Context ); +// where: +// Index = index of this bit +// Value = value of bit at this Index in the array +// Context = user supplied context +// +// Inputs: +// pBitVector - pointer to bit vector to iterate through +// pfnCallback - callback called for each non-NULL bit +// Context - context to pass to callback function +// StartIndex - Index to start at +// EndIndexP1 - Index to stop at (exclusive) +// +// Outputs: +// None. +// +// Returns: +// None. +// +/////////////////////////////////////////////////////////////////////////////// +void +BitVectorApplyFuncRange( + IN const BIT_VECTOR* const pBitVector, + IN BITVEC_APPLY_FUNC pfnCallback, + IN void* const Context, + IN uint32 StartIndex, + IN uint32 EndIndexP1 ) +{ + uint32 i; + uint8 Value; + + ASSERT( pBitVector ); + ASSERT( pfnCallback ); + + i = StartIndex; + if (EndIndexP1 > pBitVector->m_Size) + EndIndexP1 = pBitVector->m_Size; + for( ; i < EndIndexP1; ++i ) + { + Value = BitVectorGet( pBitVector, i ); + pfnCallback( i, Value, Context ); + } +} + + +/////////////////////////////////////////////////////////////////////////////// +// BitVectorApplyFuncSelected +// +// Description: +// This function calls the user supplied function for each bit in the bit vector, +// which matches Value, starting from the beginning of the array. +// +// The called function has the form: +// void ApplyFunc( uint32 Index, uint8 Value, void *Context ); +// where: +// Index = index of this bit +// Value = value of bit at this Index in the array +// Context = user supplied context +// +// Inputs: +// pBitVector - pointer to bit vector to iterate through +// pfnCallback - callback called for each non-NULL bit +// Context - context to pass to callback function +// Value - Bit values to execute pfnCallback for +// +// Outputs: +// None. +// +// Returns: +// None. +// +/////////////////////////////////////////////////////////////////////////////// +void +BitVectorApplyFuncSelected( + IN const BIT_VECTOR* const pBitVector, + IN BITVEC_APPLY_FUNC pfnCallback, + IN void* const Context, + IN uint8 Value ) +{ + return BitVectorApplyFuncSelectedRange(pBitVector, pfnCallback, Context, + Value, 0, pBitVector->m_Size); +} + +/////////////////////////////////////////////////////////////////////////////// +// BitVectorApplyFuncSelectedRange +// +// Description: +// This function calls the user supplied function for each bit in the bit vector, +// across the given range of indexes of the bit vector, +// which matches Value, starting from the beginning of the array. +// +// The called function has the form: +// void ApplyFunc( uint32 Index, uint8 Value, void *Context ); +// where: +// Index = index of this bit +// Value = value of bit at this Index in the array +// Context = user supplied context +// +// Inputs: +// pBitVector - pointer to bit vector to iterate through +// pfnCallback - callback called for each non-NULL bit +// Context - context to pass to callback function +// Value - Bit values to execute pfnCallback for +// StartIndex - Index to start at +// EndIndexP1 - Index to stop at (exclusive) +// +// Outputs: +// None. +// +// Returns: +// None. +// +/////////////////////////////////////////////////////////////////////////////// +void +BitVectorApplyFuncSelectedRange( + IN const BIT_VECTOR* const pBitVector, + IN BITVEC_APPLY_FUNC pfnCallback, + IN void* const Context, + IN uint8 Value, + IN uint32 StartIndex, + IN uint32 EndIndexP1 ) +{ + uint32 i; + uint8 Val; + + ASSERT( pBitVector ); + ASSERT( pfnCallback ); + + i = StartIndex; + if (EndIndexP1 > pBitVector->m_Size) + EndIndexP1 = pBitVector->m_Size; + for( ; i < EndIndexP1; ++i ) + { + Val = BitVectorGet( pBitVector, i ); + if (Value == Val) + pfnCallback( i, Value, Context ); + } +} + +/////////////////////////////////////////////////////////////////////////////// +// BitVectorFindFromStart +// +// Description: +// This function searches the Bit Vector for the given value +// starting from the beginning of the bit vector, until a bit matching +// Value is found +// +// Inputs: +// pBitVector - pointer to bit vector to iterate through +// Value - bit value to find +// +// Outputs: +// None. +// +// Returns: +// Index value where the first bit with the given value was found. +// If the callback given value was never found, +// then the return value = the size of the bit vector. +// +/////////////////////////////////////////////////////////////////////////////// +uint32 +BitVectorFindFromStart( + IN const BIT_VECTOR* const pBitVector, + IN uint8 Value ) +{ + return BitVectorFindRange(pBitVector, Value, 0, pBitVector->m_Size); +} + +/////////////////////////////////////////////////////////////////////////////// +// BitVectorFindFromIndex +// +// Description: +// This function searches the Bit Vector for the given value +// starting from the given index of the bit vector, until a bit matching +// Value is found. Search proceeds forward (increasing indexes). +// +// Inputs: +// pBitVector - pointer to bit vector to iterate through +// Value - bit value to find +// Index - Index to start at +// +// Outputs: +// None. +// +// Returns: +// Index value where the first bit with the given value was found. +// If the given value was never found, +// then the return value = the size of the bit vector. +// +/////////////////////////////////////////////////////////////////////////////// +uint32 +BitVectorFindFromIndex( + IN const BIT_VECTOR* const pBitVector, + IN uint8 Value, + IN uint32 Index ) +{ + return BitVectorFindRange(pBitVector, Value, Index, pBitVector->m_Size); +} + +/////////////////////////////////////////////////////////////////////////////// +// BitVectorFindRange +// +// Description: +// This function searches the Bit Vector for the given value +// across the given range of indexes of the bit vector, until a bit matching +// Value is found. Search proceeds forward (increasing indexes). +// +// Inputs: +// pBitVector - pointer to bit vector to iterate through +// Value - bit value to find +// StartIndex - Index to start at +// EndIndexP1 - Index to stop at (exclusive) +// +// Outputs: +// None. +// +// Returns: +// Index value where the first bit with the given value was found. +// If the given value was never found, +// then the return value = EndIndexP1 +// +/////////////////////////////////////////////////////////////////////////////// +uint32 +BitVectorFindRange( + IN const BIT_VECTOR* const pBitVector, + IN uint8 Value, + IN uint32 StartIndex, + IN uint32 EndIndexP1 ) +{ + uint32 i; + uint32 *pEntry; + uint32 mask; + uint32 inc; + + ASSERT( pBitVector ); + + // for speed we unroll the Value test and do 32 bits at a time + i = StartIndex; + if (EndIndexP1 > pBitVector->m_Size) + EndIndexP1 = pBitVector->m_Size; + pEntry = &pBitVector->m_pBitArray[_BitVectorSubscript(i)]; + // First word is special case with smaller mask and increment + inc = _BIT_VECTOR_ENTRY_SIZE-_BitVectorMaskShift(i); + mask = ~0<<_BitVectorMaskShift(i); + if (Value) + { + while(i < EndIndexP1) + { + // expect optimizes the looping case + if (IB_EXPECT_FALSE((*pEntry & mask) != 0)) + { + // this is the entry with our bit + while(i < EndIndexP1) + { + if (*pEntry & _BitVectorMask(i)) + goto done; + i++; + } + goto done; + } + ++pEntry; + i+=inc; + inc = _BIT_VECTOR_ENTRY_SIZE; + mask = ~0; + } + } else { + while(i < EndIndexP1) + { + // expect optimizes the looping case + if (IB_EXPECT_FALSE((*pEntry & mask) != mask)) + { + // this is the entry with our bit + while(i < EndIndexP1) + { + if (0 == (*pEntry & _BitVectorMask(i))) + goto done; + i++; + } + goto done; + } + ++pEntry; + i+=inc; + inc = _BIT_VECTOR_ENTRY_SIZE; + mask = ~0; + } + } +done: + // In case EndIndexP1 is not a multiple of 32, and we over incremented in the outer loop + if (i > EndIndexP1) i = EndIndexP1; + + DEBUG_ASSERT((EndIndexP1 == i) || (Value && BitVectorGet(pBitVector, i)) || (!Value && !BitVectorGet(pBitVector, i))); + return( i ); +} + + +/////////////////////////////////////////////////////////////////////////////// +// BitVectorFindFromEnd +// +// Description: +// This function searches the Bit Vector for the given value +// starting from the end of the bit vector, until a bit matching +// Value is found +// +// Inputs: +// pBitVector - pointer to bit vector to iterate through +// Value - bit value to find +// +// Outputs: +// None. +// +// Returns: +// Index value where the first bit with the given value was found. +// If the callback given value was never found, +// then the return value = the size of the bit vector. +// +/////////////////////////////////////////////////////////////////////////////// +uint32 +BitVectorFindFromEnd( + IN const BIT_VECTOR* const pBitVector, + IN uint8 Value ) +{ + uint32 i; + uint32 *pEntry; + + ASSERT( pBitVector ); + + // for speed we unroll the Value test and do 32 bits at a time + i = pBitVector->m_Size; + pEntry = &pBitVector->m_pBitArray[_BitVectorSubscript(i)]; + if (Value) + { + for( ; i; i-=32, --pEntry) + { + // expect optimizes the looping case + if (IB_EXPECT_FALSE(*pEntry)) + { + // this is the entry with our bit + for (; i; --i) + { + if (*pEntry & _BitVectorMask(i)) + goto found; + } + goto notfound; + } + } + } else { + for( ; i; i-=32, --pEntry) + { + // expect optimizes the looping case + if (IB_EXPECT_FALSE(*pEntry != 0xffffffff)) + { + // this is the entry with our bit + for (; i; --i) + { + if (0 == (*pEntry & _BitVectorMask(i))) + goto found; + } + goto notfound; + } + } + } +notfound: + return (pBitVector->m_Size); + +found: + return( i ); +} diff --git a/IbAccess/Common/Public/ibitvector.h b/IbAccess/Common/Public/ibitvector.h new file mode 100644 index 0000000..043ad7a --- /dev/null +++ b/IbAccess/Common/Public/ibitvector.h @@ -0,0 +1,689 @@ +/* BEGIN_ICS_COPYRIGHT3 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT3 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + + +#ifndef _IBA_PUBLIC_IBITVECTOR_H_ +#define _IBA_PUBLIC_IBITVECTOR_H_ + +#include "iba/public/datatypes.h" + + +#ifdef __cplusplus +extern "C" +{ +#endif + +/* Callback function declarations. */ +typedef void (*BITVEC_APPLY_FUNC)( + IN const uint32 Index, + IN uint8 const Value, /* 0 or 1 */ + IN void* const Context ); + +/**************************************************************************** + * + * BitVector definition. + * + * BitVector statically stores items as bits in an array, providing constant + * access times. The array can be resized dynamically. + */ + + +/* The bit vector structure is allocated by the user and is opaque to them */ +typedef struct _BIT_VECTOR +{ + /* all fields below are private, use accessor functions to */ + /* manipulate this structure */ + uint32 m_Size; /* # of bits logically in the bit vector. */ + uint32 m_GrowSize; /* # of bits to grab when growing. */ + uint32 m_MaxSize; /* Max # bits to grow to, 0-> no limit */ + uint32 m_Capacity; /* total # of bits allocated. */ + boolean m_Pageable; /* User supplied pageable memory flag. */ + unsigned *m_pBitArray; /* Internal vector of bits */ +} BIT_VECTOR; + +#define _BIT_VECTOR_ENTRY_SIZE (sizeof(unsigned)*8) /* bits per Array entry */ + +/* some private inline functions */ +static __inline uint32 +_BitVectorSubscript(uint32 bit) +{ + return (bit / _BIT_VECTOR_ENTRY_SIZE); +} + +static __inline uint32 +_BitVectorMaskShift(uint32 bit) +{ + return (bit& (_BIT_VECTOR_ENTRY_SIZE-1)); +} + +static __inline uint32 +_BitVectorMask(uint32 bit) +{ + return (1<< _BitVectorMaskShift(bit)); +} + +static __inline uint32 +_BitVectorBit(uint32 subscript, uint32 mask_shift) +{ + return ((subscript*_BIT_VECTOR_ENTRY_SIZE)+mask_shift); +} + + +/**************************************************************************** + * bit vector access methods + * These methods are an attempt to follow the functionality of the C++ STL. + * The names and behavior are obviously not exact matches, but hopefully, + * close enough to make those familiar with the ANSI standard comfortable. + ****************************************************************************/ + + +/**************************************************************************** + * BitVectorInitState + * + * Description: + * This function performs basic bit vector initialization. + * This function cannot fail. + * + * Inputs: + * pBitVector - Pointer to bit vector + * + * Outputs: + * None. + * + * Returns: + * None. + * + ****************************************************************************/ +void +BitVectorInitState( + IN BIT_VECTOR* const pBitVector ); + + +/**************************************************************************** + * BitVectorInit + * + * Description: + * This function initializes the bit vector. New bits in the bit vector are + * initialized to 0. + * + * Inputs: + * pBitVector - Pointer to bit bit vector + * InitialSize - prefered initial number of bits + * GrowSize - number of bits to allocate when incrementally growing + * the bit vector + * MaxSize - maximum number of bits in bit vector, 0 -> no limit + * IsPageable - TRUE indicates the bit vector should use pageable memory + * FALSE indicates the bit vector should used non-paged memory + * + * Outputs: + * None. + * + * Returns: + * FSUCCESS + * FINSUFFICIENT_MEMORY - bit vector is initialized to zero size + * + ****************************************************************************/ +FSTATUS +BitVectorInit( + IN BIT_VECTOR* const pBitVector, + IN const uint32 InitialSize, + IN const uint32 GrowSize, + IN const uint32 MaxSize, + IN boolean IsPageable ); + + +/**************************************************************************** + * BitVectorDestroy + * + * Description: + * This function deallocates all allocated memory associated with the bit + * vector. + * The bit vector is left initialized to zero size. + * This function does not fail. + * + * Inputs: + * pBitVector - Pointer to bit vector + * + * Outputs: + * None. + * + * Returns: + * None. + * + ****************************************************************************/ +void +BitVectorDestroy( + IN BIT_VECTOR* const pBitVector ); + + +/**************************************************************************** + * BitVectorGetCapacity + * + * Description: + * This function returns the current capacity of the bit vector. + * This function cannot fail. + * + * Inputs: + * pBitVector - Pointer to bit vector + * + * Outputs: + * None. + * + * Returns: + * Capacity, in bits, of the bit vector. + * + ****************************************************************************/ +static __inline uint32 +BitVectorGetCapacity( + IN const BIT_VECTOR* const pBitVector ) +{ + DEBUG_ASSERT( pBitVector ); + return( pBitVector->m_Capacity ); +} + + +/**************************************************************************** + * BitVectorGetSize + * + * Description: + * This function returns the size of the bit vector. This function cannot fail. + * + * Inputs: + * pBitVector - Pointer to bit vector + * + * Outputs: + * None. + * + * Returns: + * Size, in bits, of the bit vector. + * + ****************************************************************************/ +static __inline uint32 +BitVectorGetSize( + IN const BIT_VECTOR* const pBitVector ) +{ + DEBUG_ASSERT( pBitVector ); + return( pBitVector->m_Size ); +} + + +/**************************************************************************** + * BitVectorGetMaxSize + * + * Description: + * This function returns the max size of the bit vector. + * This function cannot fail. + * + * Inputs: + * pBitVector - Pointer to bit vector + * + * Outputs: + * None. + * + * Returns: + * MaxSize, in bits, of the bit vector. (0-> no limit) + * + ****************************************************************************/ +static __inline uint32 +BitVectorGetMaxSize( + IN const BIT_VECTOR* const pBitVector ) +{ + DEBUG_ASSERT( pBitVector ); + return( pBitVector->m_MaxSize ); +} + +/**************************************************************************** + * BitVectorGet + * + * Description: + * This function returns the value of the bit at the specified index. + * Range checking is NOT performed. Provides constant time access. + * + * Inputs: + * pBitVector - Pointer to bit vector. + * Index - Index of bit to get. + * + * Outputs: + * value of bit + * + * Returns: + * None. + * + * Notes: + * + ****************************************************************************/ +static __inline uint8 +BitVectorGet( + IN const BIT_VECTOR* const pBitVector, + IN const uint32 Index ) +{ + DEBUG_ASSERT(pBitVector); + return( (pBitVector->m_pBitArray[_BitVectorSubscript(Index)]&_BitVectorMask(Index)) >> _BitVectorMaskShift(Index) ); +} + + +/**************************************************************************** + * BitVectorAt + * + * Description: + * This function returns the bit at the specified index. + * Range checking is performed. Provides constant time access. + * + * Inputs: + * pBitVector - Pointer to bit vector. + * Index - Index of element to get. + * pValue - Pointer to storage for the bit to be returned. + * + * Outputs: + * pValue - value of given bit + * + * Returns: + * FSUCCESS + * FINVALID_SETTING Index out of range. + * + ****************************************************************************/ +FSTATUS +BitVectorAt( + IN const BIT_VECTOR* const pBitVector, + IN const uint32 Index, + OUT uint8* pValue ); + +/**************************************************************************** + * BitVectorSet + * + * Description: + * This function sets the bit at the specified index to the given value. + * The array grows as necessary. + * + * Inputs: + * pBitVector - Pointer to bit vector. + * Index - Index of bit to set to value. + * Value - value to set the bit to + * + * Outputs: + * None. + * + * Returns: + * FSUCCESS + * FINSUFFICIENT_MEMORY The array could not be resized to accomodate the + * specified bit. + * FINSUFFICIENT_RESOURCES - would grow vector beyond max size + * + ****************************************************************************/ +FSTATUS +BitVectorSet( + IN BIT_VECTOR* const pBitVector, + IN const uint32 Index, + IN const uint8 Value ); + + +/**************************************************************************** + * BitVectorSetCapacity + * + * Description: + * This function reserves capacity in the bit vector to the specified number of + * bit. This function can only fail if the new capacity is larger than + * the old capacity. If the new capacity is less than the old, no action + * is taken. When growing the capacity, new bits will have value 0. + * + * Inputs: + * pBitVector - Pointer to bit vector + * NewCapacity - Number of bit reserved in the array + * + * Outputs: + * None. + * + * Returns: + * FSUCCESS + * FINSUFFICIENT_MEMORY - bit vector is left unaltered + * + ****************************************************************************/ +FSTATUS +BitVectorSetCapacity( + IN BIT_VECTOR* const pBitVector, + IN uint32 NewCapacity ); + + +/**************************************************************************** + * BitVectorSetSize + * + * Description: + * This function resizes the bit vector to the specified number of + * bit. This function can only fail if the new size is larger than + * the old capacity. + * + * Inputs: + * pBitVector - Pointer to bit vector + * Size - new number of bit in the the array + * + * Outputs: + * None. + * + * Returns: + * FSUCCESS + * FINSUFFICIENT_MEMORY - bit vector will have at least as many bit + * as prior to the call. Use BitVectorGetSize() + * to determine the number of bit + * FINSUFFICIENT_RESOURCES - would grow vector beyond max size + * + ****************************************************************************/ +FSTATUS +BitVectorSetSize( + IN BIT_VECTOR* const pBitVector, + IN const uint32 Size ); + + +/**************************************************************************** + * BitVectorSetMinSize + * + * Description: + * This function resizes the bit vector to the specified number of + * bit only if the current number of bit in the array is fewer + * than the specified size. + * + * Inputs: + * pBitVector - Pointer to bit vector + * MinSize - at least the number of bit needed in the array + * + * Outputs: + * None. + * + * Returns: + * FSUCCESS + * FINSUFFICIENT_MEMORY - bit vector is left unaltered + * + ****************************************************************************/ +FSTATUS BitVectorSetMinSize( + IN BIT_VECTOR* const pBitVector, + IN const uint32 MinSize ); + + +/**************************************************************************** + * BitVectorApplyFunc + * + * Description: + * This function calls the user supplied function for each bit in the bit vector, + * starting from the beginning of the array. + * + * The called function has the form: + * void ApplyFunc( uint32 Index, uint8 Value, void *Context ); + * where: + * Index = index of this bit + * Value = value of bit at this Index in the array + * Context = user supplied context + * + * Inputs: + * pBitVector - pointer to bit vector to iterate through + * pfnCallback - callback called for each non-NULL bit + * Context - context to pass to callback function + * + * Outputs: + * None. + * + * Returns: + * None. + * + ****************************************************************************/ +void +BitVectorApplyFunc( + IN const BIT_VECTOR* const pBitVector, + IN BITVEC_APPLY_FUNC pfnCallback, + IN void* const Context ); + + +/**************************************************************************** + * BitVectorApplyFuncRange + * + * Description: + * This function calls the user supplied function for each item in the bit + * vector across the given range of indexes of the bit vector. + * + * The called function has the form: + * void ApplyFunc( uint32 Index, uint8 Value, void *Context ); + * where: + * Index = index of this bit + * Value = value of bit at this Index in the array + * Context = user supplied context + * + * Inputs: + * pBitVector - pointer to bit vector to iterate through + * pfnCallback - callback called for each non-NULL bit + * Context - context to pass to callback function + * StartIndex - Index to start at + * EndIndexP1 - Index to stop at (exclusive) + * + * Outputs: + * None. + * + * Returns: + * None. + * + ****************************************************************************/ +void +BitVectorApplyFuncRange( + IN const BIT_VECTOR* const pBitVector, + IN BITVEC_APPLY_FUNC pfnCallback, + IN void* const Context, + IN uint32 StartIndex, + IN uint32 EndIndexP1 ); + +/**************************************************************************** + * BitVectorApplyFuncSelected + * + * Description: + * This function calls the user supplied function for each bit in the bit + * vector, which matches Value, starting from the beginning of the array. + * + * The called function has the form: + * void ApplyFunc( uint32 Index, uint8 Value, void *Context ); + * where: + * Index = index of this bit + * Value = value of bit at this Index in the array + * Context = user supplied context + * + * Inputs: + * pBitVector - pointer to bit vector to iterate through + * pfnCallback - callback called for each non-NULL bit + * Context - context to pass to callback function + * Value - Bit values to execute pfnCallback for + * + * Outputs: + * None. + * + * Returns: + * None. + * + ****************************************************************************/ +void +BitVectorApplyFuncSelected( + IN const BIT_VECTOR* const pBitVector, + IN BITVEC_APPLY_FUNC pfnCallback, + IN void* const Context, + IN uint8 Value ); + + +/**************************************************************************** + * BitVectorApplyFuncSelectedRange + * + * Description: + * This function calls the user supplied function for each bit in the bit + * vector, across the given range of indexes of the bit vector, + * which matches Value, starting from the beginning of the array. + * + * The called function has the form: + * void ApplyFunc( uint32 Index, uint8 Value, void *Context ); + * where: + * Index = index of this bit + * Value = value of bit at this Index in the array + * Context = user supplied context + * + * Inputs: + * pBitVector - pointer to bit vector to iterate through + * pfnCallback - callback called for each non-NULL bit + * Context - context to pass to callback function + * Value - Bit values to execute pfnCallback for + * StartIndex - Index to start at + * EndIndexP1 - Index to stop at (exclusive) + * + * Outputs: + * None. + * + * Returns: + * None. + * + ****************************************************************************/ +void +BitVectorApplyFuncSelectedRange( + IN const BIT_VECTOR* const pBitVector, + IN BITVEC_APPLY_FUNC pfnCallback, + IN void* const Context, + IN uint8 Value, + IN uint32 StartIndex, + IN uint32 EndIndexP1 ); + +/**************************************************************************** + * BitVectorFindFromStart + * + * Description: + * This function searches the Bit Vector for the given value + * starting from the beginning of the bit vector, until a bit matching + * Value is found + * + * Inputs: + * pBitVector - pointer to bit vector to iterate through + * Value - bit value to find + * + * Outputs: + * None. + * + * Returns: + * Index value where the first bit with the given value was found. + * If the callback given value was never found, + * then the return value = the size of the bit vector. + * + ****************************************************************************/ +uint32 +BitVectorFindFromStart( + IN const BIT_VECTOR* const pBitVector, + IN uint8 Value ); + +/**************************************************************************** + * BitVectorFindFromIndex + * + * Description: + * This function searches the Bit Vector for the given value + * starting from the given index of the bit vector, until a bit matching + * Value is found. Search proceeds forward (increasing indexes). + * + * Inputs: + * pBitVector - pointer to bit vector to iterate through + * Value - bit value to find + * Index - Index to start at + * + * Outputs: + * None. + * + * Returns: + * Index value where the first bit with the given value was found. + * If the callback given value was never found, + * then the return value = the size of the bit vector. + * + ****************************************************************************/ +uint32 +BitVectorFindFromIndex( + IN const BIT_VECTOR* const pBitVector, + IN uint8 Value, + IN uint32 Index ); + +/**************************************************************************** + * BitVectorFindRange + * + * Description: + * This function searches the Bit Vector for the given value + * across the given range of indexes of the bit vector, until a bit matching + * Value is found. Search proceeds forward (increasing indexes). + * + * Inputs: + * pBitVector - pointer to bit vector to iterate through + * Value - bit value to find + * StartIndex - Index to start at + * EndIndexP1 - Index to stop at (exclusive) + * + * Outputs: + * None. + * + * Returns: + * Index value where the first bit with the given value was found. + * If the given value was never found, + * then the return value = EndIndexP1 + * + ****************************************************************************/ +uint32 +BitVectorFindRange( + IN const BIT_VECTOR* const pBitVector, + IN uint8 Value, + IN uint32 StartIndex, + IN uint32 EndIndexP1); + + +/**************************************************************************** + * BitVectorFindFromEnd + * + * Description: + * This function searches the Bit Vector for the given value + * starting from the end of the bit vector, until a bit matching + * Value is found + * + * Inputs: + * pBitVector - pointer to bit vector to iterate through + * Value - bit value to find + * + * Outputs: + * None. + * + * Returns: + * Index value where the first bit with the given value was found. + * If the callback given value was never found, + * then the return value = the size of the bit vector. + * + ****************************************************************************/ +uint32 +BitVectorFindFromEnd( + IN const BIT_VECTOR* const pBitVector, + IN uint8 Value ); + + +#ifdef __cplusplus +} /* extern "C" */ +#endif + + +#endif /* _IBA_PUBLIC_IBITVECTOR_H_ */ diff --git a/IbAccess/Common/Public/ibyteswap.h b/IbAccess/Common/Public/ibyteswap.h new file mode 100644 index 0000000..f9bebbb --- /dev/null +++ b/IbAccess/Common/Public/ibyteswap.h @@ -0,0 +1,2103 @@ +/* BEGIN_ICS_COPYRIGHT3 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT3 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +#ifndef _IBA_PUBLIC_IBYTESWAP_H_ +#define _IBA_PUBLIC_IBYTESWAP_H_ + +/* + * The ibyteswap_osd.h provides the following macros. + * __LITTLE_ENDIAN + * __BIG_ENDIAN + * __BYTE_ORDER + * + * If the platform does not provide byte swapping functions, ibyteswap_osd.h + * will also provide the following macros. + * ntoh16, hton16 + * ntoh32, hton32 + * ntoh64, hton64 + */ +#include "iba/public/datatypes.h" +#include "iba/public/ibyteswap_osd.h" + +#if defined(__LINUX__) && defined(_BSD_SOURCE) +#include +#elif defined(VXWORKS) +#include <../src/hwif/h/vxbus/vxbAccess.h> +#endif + + +#ifdef __cplusplus +extern "C" +{ +#endif + +#undef CPU_LE +#undef CPU_BE +#if defined(__LITTLE_ENDIAN) && (__BYTE_ORDER == __LITTLE_ENDIAN) +#define CPU_LE 1 +#define CPU_BE 0 +#elif defined(__BIG_ENDIAN) && (__BYTE_ORDER == __BIG_ENDIAN) +#define CPU_LE 0 +#define CPU_BE 1 +#else +#error "Unknown BYTE_ORDER" +#endif + + +/* Default implementation of 16 bit swap function. */ +#ifndef ntoh16 + #if CPU_LE + #define ntoh16( x ) ( (((x) & 0x00FF) << 8) | (((x) & 0xFF00) >> 8) ) + #else + #define ntoh16 + #endif + #define hton16 ntoh16 +#endif +#ifndef le16toh + #if CPU_BE + #define le16toh( x ) ( (((x) & 0x00FF) << 8) | (((x) & 0xFF00) >> 8) ) + #else + #define le16toh + #endif +#endif + +/* Default implementation of 32 bit swap function. */ +#ifndef ntoh32 + #if CPU_LE + #define ntoh32( x ) ( (((x) & 0x000000FF) << 24) | \ + (((x) & 0x0000FF00) << 8) | \ + (((x) & 0x00FF0000) >> 8) | \ + (((x) & 0xFF000000) >> 24) ) + #else + #define ntoh32 + #endif +#define hton32 ntoh32 +#endif +#ifndef le32toh + #if CPU_BE + #define le32toh( x ) ( (((x) & 0x000000FF) << 24) | \ + (((x) & 0x0000FF00) << 8) | \ + (((x) & 0x00FF0000) >> 8) | \ + (((x) & 0xFF000000) >> 24) ) + #else + #define le32toh + #endif +#endif + +/* Default implementation of 64 bit swap function. */ +#ifndef ntoh64 + #if CPU_LE + #define ntoh64( x ) ( (((x) & 0x00000000000000FF) << 56) | \ + (((x) & 0x000000000000FF00) << 40) | \ + (((x) & 0x0000000000FF0000) << 24) | \ + (((x) & 0x00000000FF000000) << 8 ) | \ + (((x) & 0x000000FF00000000) >> 8 ) | \ + (((x) & 0x0000FF0000000000) >> 24) | \ + (((x) & 0x00FF000000000000) >> 40) | \ + (((x) & 0xFF00000000000000) >> 56) ) + #else + #define ntoh64 + #endif +#define hton64 ntoh64 +#endif +#ifndef le64toh + #if CPU_BE + #define le64toh( x ) ( (((x) & 0x00000000000000FF) << 56) | \ + (((x) & 0x000000000000FF00) << 40) | \ + (((x) & 0x0000000000FF0000) << 24) | \ + (((x) & 0x00000000FF000000) << 8 ) | \ + (((x) & 0x000000FF00000000) >> 8 ) | \ + (((x) & 0x0000FF0000000000) >> 24) | \ + (((x) & 0x00FF000000000000) >> 40) | \ + (((x) & 0xFF00000000000000) >> 56) ) + #else + #define le64toh + #endif +#endif + + +/* + * Generic function to swap the byte order of byte arrays of any given size. + */ +#if CPU_LE +static __inline void +ntoh( + IN void* pSrc, + IN void* pDest, + IN uint8 Size ) +{ + uint8 i; + uint8 *s = (uint8*)pSrc; + uint8 *d = (uint8*)pDest; + char temp; + if( s == d ) + { + /* Swap in place if source and destination are the same. */ + for( i = 0; i < Size / 2; i++ ) + { + temp = d[i]; + d[i] = s[Size - 1 - i]; + s[Size - 1 - i] = temp; + } + } + else + { + for( i = 0; i < Size; i++ ) + d[i] = s[Size - 1 - i]; + } +} +#else +#define ntoh(pSrc, pDest, Size) (void)0 +#endif + + +/* + * The following is suggested use only. Primarily when there are different + * types of fields, its easy to generate this description, rather than + * manually perform the operation. If the specific case is very simple, the + * simplest thing is to do direct swap, using the CPU_LE, CPU_BE for + * conditional compilation for different bit fields, and htonXX macros. + * ntohXX are provided for consistency, in reality they both do the same thing. + */ +typedef struct _swap_desc { + uint8 size; /* Size of the field. */ + uint16 offset; /* Offset from the start of struct. */ +} SWAP_DESC; + + +/* + * Usage example: + * typedef struct __MyStruct { + * uint8 myint8_1; + * uint8 myint8_2; + * uint16 myint16_1; + * uint32 myint32_1; + * } MYSTRUCT; + * + * SWAP_DESC_START (MYSTRUCT) + * SWAP_DESC_FIELD(MYSTRUCT, myint16_1) + * SWAP_DESC_FIELD(MYSTRUCT, myint32_1) + * SWAP_DESC_END + * + * send_buf() + * { + * ..... + * + * databuf is the buffer that points to a structure of type MYSTRUCT. + * SwapStruct(SWAP_DESC_NAME(MYSTRUCT, destbuf, srcbuf); + * ..... + */ +#define SWAP_DESC_START(name) SWAP_DESC DEF_##name[] = { +#define SWAP_DESC_FIELD(name, field) \ + { \ + sizeof(((name *) 0)->field), \ + offsetof(name, field) \ + }, +#define SWAP_DESC_END {0,0}}; + +#define SWAP_DESC_NAME(name) DEF_##name + +static __inline void +SwapStruct( + IN SWAP_DESC *desc, + OUT void *pDest, + IN void *pSrc) +{ + int i = 0; + void *src, *dest; + + for( i=0; desc[i].size > 0; i++ ) + { + src = (uchar*)pSrc + desc[i].offset; + dest = (uchar*)pDest + desc[i].offset; + switch( desc[i].size ) + { + case 2: + *(uint16*)dest = hton16( *(uint16*)src ); + break; + case 4: + *(uint32*)dest = hton32( *(uint32*)src ); + break; + case 8: + *(uint64*)dest = hton64( *(uint64*)src ); + break; + } + } +} + +/*! +fetch a byte from a 32 bit value + +@param value - 32 bit value +@param byte - byte position (for BE U32 0=MSB, 3=LSB, for LE U32 0=LSB, 3=MSB) + +@return - host byte order 8 bit value +*/ +static __inline uint8 GetU8FromU32(uint32 value, int byte) +{ + return ((uint8*)&value)[byte]; +} + +/*! +fetch a byte from a 32 bit BigEndian Byte Order value + +@param value - 32 bit big endian value +@param byte - BE byte position (0=MSB, 3=LSB) + +@return - host byte order 8 bit value +*/ +static __inline uint8 GetU8FromBeU32(uint32 value, int byte) +{ + return ((uint8*)&value)[byte]; +} + +/*! +fetch a byte from a 32 bit LittleEndian Byte Order value + +@param value - 32 bit little endian value +@param byte - LE byte position (0=MSB, 3=LSB) + +@return - host byte order 8 bit value +*/ +static __inline uint8 GetU8FromLeU32(uint32 value, int byte) +{ + return ((uint8*)&value)[3-byte]; +} + +/*! +fetch a 16 bit BigEndian Byte Order field + +@param addr - address of Big Endian item to fetch + may be poorly aligned + +@return - host byte order 16 bit value +*/ +static __inline uint16 GetBeU16(const uint8* addr) +{ + return ((uint16)(addr[0])<<8) | addr[1]; +} + +/*! +fetch a 16 bit BigEndian Byte Order array + +@param dest - address to store host order array in (must be u16 aligned) +@param src - address of Big Endian array to fetch (must be u16 aligned) +@param byte - byte count for array (note bytes not u16 count) +*/ +static __inline void FetchBeU16Array(uint16* dest, const uint16 *src, uint32 bytes) +{ + do { + *dest++ = ntoh16(*src); + src++; + } while (bytes -= 2); +} + + +/*! +store a 16 bit BigEndian Byte Order field + +@param addr - address to store Big Endian value at + may be poorly aligned +@param value - host byte order 16 bit value to store +*/ +static __inline void StoreBeU16(uint8* addr, uint16 value) +{ + addr[0] = value >> 8; + addr[1] = value & 0xffu; +} + +/*! +store a 16 bit BigEndian Byte Order array + +@param dest - address to store Big Endian array in (must be u16 aligned) +@param src - address of host order array to fetch (must be u16 aligned) +@param byte - byte count for array (note bytes not u16 count) +*/ +static __inline void StoreBeU16Array(uint16* dest, const uint16 *src, uint32 bytes) +{ + do { + *dest++ = hton16(*src); + src++; + } while (bytes -= 2); +} + +/*! +fetch a 24 bit BigEndian Byte Order field + +@param addr - address of Big Endian item to fetch + may be poorly aligned + +@return - host byte order 24 bit value +*/ +static __inline uint32 GetBeU24(const uint8* addr) +{ + return ((uint32)(addr[0]) << 16) | GetBeU16(&addr[1]); +} + +/*! +store a 24 bit BigEndian Byte Order field + +@param addr - address to Big Endian store value at + may be poorly aligned +@param value - host byte order 24 bit value to store +*/ +static __inline void StoreBeU24(uint8* addr, uint32 value) +{ + addr[0] = value >> 16; + StoreBeU16(&addr[1], value & 0xffffu); +} + +/*! +fetch a 32 bit BigEndian Byte Order field + +@param addr - address of Big Endian item to fetch + may be poorly aligned + +@return - host byte order 32 bit value +*/ +static __inline uint32 GetBeU32(const uint8* addr) +{ + return ((uint32)GetBeU16(addr) << 16) | GetBeU16(&addr[2]); +} + +/*! +fetch a 32 bit BigEndian Byte Order array + +@param dest - address to store host order array in (must be u32 aligned) +@param src - address of Big Endian array to fetch (must be u32 aligned) +@param byte - byte count for array (note bytes not u32 count) +*/ +static __inline void FetchBeU32Array(uint32* dest, const uint32 *src, uint32 bytes) +{ + do { + *dest++ = ntoh32(*src); + src++; + } while (bytes -= 4); +} + +/*! +store a 32 bit BigEndian Byte Order field + +@param addr - address to store Big Endian value at + may be poorly aligned +@param value - host byte order 32 bit value to store +*/ +static __inline void StoreBeU32(uint8* addr, uint32 value) +{ + StoreBeU16(addr, value >> 16); + StoreBeU16(&addr[2], value & 0xffffu); +} + +/*! +store a 32 bit BigEndian Byte Order array + +@param dest - address to store Big Endian array in (must be u32 aligned) +@param src - address of host order array to fetch (must be u32 aligned) +@param byte - byte count for array (note bytes not u32 count) +*/ +static __inline void StoreBeU32Array(uint32* dest, const uint32 *src, uint32 bytes) +{ + do { + *dest++ = hton32(*src); + src++; + } while (bytes -= 4); +} + +/*! +fetch a 48 bit BigEndian Byte Order field + +@param addr - address of Big Endian item to fetch + may be poorly aligned + +@return - host byte order 48 bit value +*/ +static __inline uint64 GetBeU48(const uint8* addr) +{ + return ((uint64)GetBeU16(addr) << 32) | GetBeU32(&addr[2]); +} + +/*! +store a 48 bit BigEndian Byte Order field + +@param addr - address to store Big Endian value at + may be poorly aligned +@param value - host byte order 48 bit value to store +*/ +static __inline void StoreBeU48(uint8* addr, uint64 value) +{ + StoreBeU16(addr, value >> 32); + StoreBeU32(&addr[2], value & 0xffffffffu); +} + +/*! +fetch a 64 bit BigEndian Byte Order field + +@param addr - address of item to fetch + may be poorly aligned + +@return - host byte order 64 bit value +*/ +static __inline uint64 GetBeU64(const uint8* addr) +{ + return ((uint64)GetBeU32(addr) << 32) | GetBeU32(&addr[4]); +} + +/*! +fetch a 64 bit BigEndian Byte Order array + +@param dest - address to store host order array in (must be u64 aligned) +@param src - address of Big Endian array to fetch (must be u64 aligned) +@param byte - byte count for array (note bytes not u64 count) +*/ +static __inline void FetchBeU64Array(uint64* dest, const uint64 *src, uint32 bytes) +{ + do { + *dest++ = ntoh64(*src); + src++; + } while (bytes -= 8); +} + +/*! +store a 64 bit BigEndian Byte Order field + +@param addr - address to store Big Endian value at + may be poorly aligned +@param value - host byte order 64 bit value to store +*/ +static __inline void StoreBeU64(uint8* addr, uint64 value) +{ + StoreBeU32(addr, value >> 32); + StoreBeU32(&addr[4], value & 0xffffffffu); +} + +/*! +store a 64 bit BigEndian Byte Order array + +@param dest - address to store Big Endian array in (must be u64 aligned) +@param src - address of host order array to fetch (must be u64 aligned) +@param byte - byte count for array (note bytes not u64 count) +*/ +static __inline void StoreBeU64Array(uint64* dest, const uint64 *src, uint32 bytes) +{ + do { + *dest++ = hton64(*src); + src++; + } while (bytes -= 8); +} + +/*! +fetch a 16 bit LittleEndian Byte Order field + +@param addr - address of Little Endian item to fetch + may be poorly aligned + +@return - host byte order 16 bit value +*/ +static __inline uint16 GetLeU16(const uint8* addr) +{ + return addr[0] | ((uint16)(addr[1])<<8); +} + +/*! +fetch a 16 bit LittleEndian Byte Order array + +@param dest - address to store host order array in (must be u16 aligned) +@param src - address of Little Endian array to fetch (must be u16 aligned) +@param byte - byte count for array (note bytes not u16 count) +*/ +static __inline void FetchLeU16Array(uint16* dest, const uint16 *src, uint32 bytes) +{ + do { + *dest++ = GetLeU16((const uint8*)src); /* TBD - optimize with ltoh */ + src++; + } while (bytes -= 2); +} + +/*! +store a 16 bit LittleEndian Byte Order field + +@param addr - address to store Little Endian value at + may be poorly aligned +@param value - host byte order 16 bit value to store +*/ +static __inline void StoreLeU16(uint8* addr, uint16 value) +{ + addr[0] = value & 0xffu; + addr[1] = value >> 8; +} + +/*! +store a 16 bit LittleEndian Byte Order array + +@param dest - address to store Little Endian array in (must be u16 aligned) +@param src - address of host order array to fetch (must be u16 aligned) +@param byte - byte count for array (note bytes not u16 count) +*/ +static __inline void StoreLeU16Array(uint16* dest, const uint16 *src, uint32 bytes) +{ + do { + StoreLeU16((uint8*)dest++, *src); /* TBD optimize with htol */ + src++; + } while (bytes -= 2); +} + +/*! +fetch a 24 bit LittleEndian Byte Order field + +@param addr - address of Little Endian item to fetch + may be poorly aligned + +@return - host byte order 24 bit value +*/ +static __inline uint32 GetLeU24(const uint8* addr) +{ + return GetLeU16(addr) | ((uint32)(addr[2]) << 16); +} + +/*! +store a 24 bit LittleEndian Byte Order field + +@param addr - address to store Little Endian value at + may be poorly aligned +@param value - host byte order 24 bit value to store +*/ +static __inline void StoreLeU24(uint8* addr, uint32 value) +{ + StoreLeU16(addr, value & 0xffffu); + addr[2] = value >> 16; +} + +/*! +fetch a 32 bit LittleEndian Byte Order field + +@param addr - address of Little Endian item to fetch + may be poorly aligned + +@return - host byte order 32 bit value +*/ +static __inline uint32 GetLeU32(const uint8* addr) +{ + return GetLeU16(addr) | ((uint32)GetLeU16(&addr[2]) << 16); +} + +/*! +fetch a 32 bit LittleEndian Byte Order array + +@param dest - address to store host order array in (must be u32 aligned) +@param src - address of Little Endian array to fetch (must be u32 aligned) +@param byte - byte count for array (note bytes not u32 count) +*/ +static __inline void FetchLeU32Array(uint32* dest, const uint32 *src, uint32 bytes) +{ + do { + *dest++ = GetLeU32((const uint8*)src); /* TBD - optimize with ltoh */ + src++; + } while (bytes -= 4); +} + +/*! +store a 32 bit LittleEndian Byte Order field + +@param addr - address to store Little Endian value at + may be poorly aligned +@param value - host byte order 32 bit value to store +*/ +static __inline void StoreLeU32(uint8* addr, uint32 value) +{ + StoreLeU16(addr, value & 0xffffu); + StoreLeU16(&addr[2], value >> 16); +} + +/*! +store a 32 bit LittleEndian Byte Order array + +@param dest - address to store Little Endian array in (must be u32 aligned) +@param src - address of host order array to fetch (must be u32 aligned) +@param byte - byte count for array (note bytes not u32 count) +*/ +static __inline void StoreLeU32Array(uint32* dest, const uint32 *src, uint32 bytes) +{ + do { + StoreLeU32((uint8*)dest++, *src); /* TBD optimize with htol */ + src++; + } while (bytes -= 4); +} + +/*! +fetch a 48 bit LittleEndian Byte Order field + +@param addr - address of Little Endian item to fetch + may be poorly aligned + +@return - host byte order 48 bit value +*/ +static __inline uint64 GetLeU48(const uint8* addr) +{ + return GetLeU32(addr) | ((uint64)GetLeU16(&addr[4]) << 32); +} + +/*! +store a 48 bit LittleEndian Byte Order field + +@param addr - address to store Little Endian value at + may be poorly aligned +@param value - host byte order 48 bit value to store +*/ +static __inline void StoreLeU48(uint8* addr, uint64 value) +{ + StoreLeU32(addr, value & 0xffffffffu); + StoreLeU16(&addr[4], value >> 32); +} + +/*! +fetch a 64 bit LittleEndian Byte Order field + +@param addr - address of Little Endian item to fetch + may be poorly aligned + +@return - host byte order 64 bit value +*/ +static __inline uint64 GetLeU64(const uint8* addr) +{ + return GetLeU32(addr) | ((uint64)GetLeU32(&addr[4]) << 32); +} + +/*! +fetch a 64 bit LittleEndian Byte Order array + +@param dest - address to store host order array in (must be u64 aligned) +@param src - address of Little Endian array to fetch (must be u64 aligned) +@param byte - byte count for array (note bytes not u64 count) +*/ +static __inline void FetchLeU64Array(uint64* dest, const uint64 *src, uint32 bytes) +{ + do { + *dest++ = GetLeU64((const uint8*)src); /* TBD - optimize with ltoh */ + src++; + } while (bytes -= 8); +} + +/*! +store a 64 bit LittleEndian Byte Order field + +@param addr - address to store Little Endian value at + may be poorly aligned +@param value - host byte order 64 bit value to store +*/ +static __inline void StoreLeU64(uint8* addr, uint64 value) +{ + StoreLeU32(addr, value & 0xffffffffu); + StoreLeU32(&addr[4], value >> 32); +} + +/*! +store a 64 bit LittleEndian Byte Order array + +@param dest - address to store Little Endian array in (must be u64 aligned) +@param src - address of host order array to fetch (must be u64 aligned) +@param byte - byte count for array (note bytes not u64 count) +*/ +static __inline void StoreLeU64Array(uint64* dest, const uint64 *src, uint32 bytes) +{ + do { + StoreLeU64((uint8*)dest++, *src); /* TBD optimize with htol */ + src++; + } while (bytes -= 8); +} + +/*! +fetch a 16 bit Host Byte Order field + +@param addr - address of Little Endian item to fetch + may be poorly aligned + +@return - host byte order 16 bit value +*/ +static __inline uint16 GetU16(const uint8* addr) +{ +#if CPU_BE + return GetBeU16(addr); +#else + return GetLeU16(addr); +#endif +} + +/*! +store a 16 bit Host Byte Order field + +@param addr - address to store host byte order value at + may be poorly aligned +@param value - host byte order 16 bit value to store +*/ +static __inline void StoreU16(uint8* addr, uint16 value) +{ +#if CPU_BE + StoreBeU16(addr, value); +#else + StoreLeU16(addr, value); +#endif +} + +/*! +fetch a 24 bit Host Byte Order field + +@param addr - address of host byte order item to fetch + may be poorly aligned + +@return - host byte order 24 bit value +*/ +static __inline uint32 GetU24(const uint8* addr) +{ +#if CPU_BE + return GetBeU24(addr); +#else + return GetLeU24(addr); +#endif +} + +/*! +store a 24 bit Host Byte Order field + +@param addr - address to store host byte order value at + may be poorly aligned +@param value - host byte order 24 bit value to store +*/ +static __inline void StoreU24(uint8* addr, uint32 value) +{ +#if CPU_BE + StoreBeU24(addr, value); +#else + StoreLeU24(addr, value); +#endif +} + +/*! +fetch a 32 bit Host Byte Order field + +@param addr - address of host byte order item to fetch + may be poorly aligned + +@return - host byte order 32 bit value +*/ +static __inline uint32 GetU32(const uint8* addr) +{ +#if CPU_BE + return GetBeU32(addr); +#else + return GetLeU32(addr); +#endif +} + +/*! +store a 32 bit Host Byte Order field + +@param addr - address to store host byte order value at + may be poorly aligned +@param value - host byte order 32 bit value to store +*/ +static __inline void StoreU32(uint8* addr, uint32 value) +{ +#if CPU_BE + StoreBeU32(addr, value); +#else + StoreLeU32(addr, value); +#endif +} + +/*! +fetch a 48 bit Host Byte Order field + +@param addr - address of host byte order item to fetch + may be poorly aligned + +@return - host byte order 48 bit value +*/ +static __inline uint64 GetU48(const uint8* addr) +{ +#if CPU_BE + return GetBeU48(addr); +#else + return GetLeU48(addr); +#endif +} + +/*! +store a 48 bit Host Byte Order field + +@param addr - address to store host byte order value at + may be poorly aligned +@param value - host byte order 48 bit value to store +*/ +static __inline void StoreU48(uint8* addr, uint64 value) +{ +#if CPU_BE + StoreBeU48(addr, value); +#else + StoreLeU48(addr, value); +#endif +} + +/*! +fetch a 64 bit Host Byte Order field + +@param addr - address of host byte order item to fetch + may be poorly aligned + +@return - host byte order 64 bit value +*/ +static __inline uint64 GetU64(const uint8* addr) +{ +#if CPU_BE + return GetBeU64(addr); +#else + return GetLeU64(addr); +#endif +} + +/*! +store a 64 bit Host Byte Order field + +@param addr - address to store host byte order value at + may be poorly aligned +@param value - host byte order 64 bit value to store +*/ +static __inline void StoreU64(uint8* addr, uint64 value) +{ +#if CPU_BE + StoreBeU64(addr, value); +#else + StoreLeU64(addr, value); +#endif +} + +/* These macros make it very easy and clean to declare bit fields in byte order + * sensitive structures. field arguments are provided in big endian order. + * This matches the order in which most networking specs (including + * the IBTA Infiniband specs) are presented. + * The first argument will use the most significant bits. The last entry + * will use the least significant bits. The implementation is dependent on + * little endian compilers placing the 1st bit field encountered in the + * least significant bits while big endian compilers put the 1st bit field + * encountered in the most significant bits. + * All bits in the vartype should be consumed by the sizes of the fields. + * Any unused bits could result in undefined or compiler specific behaviour. + */ +#if CPU_BE +#if CPU_LE +#error "Unknown byte order, CPU_LE and CPU_BE both set" +#endif + #define IB_BITFIELD2(vartype,field1,field2) \ + vartype field1; \ + vartype field2; + + #define IB_BITFIELD3(vartype,field1,field2,field3) \ + vartype field1; \ + vartype field2; \ + vartype field3; + + #define IB_BITFIELD4(vartype,field1,field2,field3,field4) \ + vartype field1; \ + vartype field2; \ + vartype field3; \ + vartype field4; + + #define IB_BITFIELD5(vartype,field1,field2,field3,field4,field5) \ + vartype field1; \ + vartype field2; \ + vartype field3; \ + vartype field4; \ + vartype field5; + + #define IB_BITFIELD6(vartype,field1,field2,field3,field4,field5,field6) \ + vartype field1; \ + vartype field2; \ + vartype field3; \ + vartype field4; \ + vartype field5; \ + vartype field6; + + #define IB_BITFIELD7(vartype,field1,field2,field3,field4,field5,field6,field7) \ + vartype field1; \ + vartype field2; \ + vartype field3; \ + vartype field4; \ + vartype field5; \ + vartype field6; \ + vartype field7; + + #define IB_BITFIELD8(vartype,field1,field2,field3,field4,field5,field6,field7,field8) \ + vartype field1; \ + vartype field2; \ + vartype field3; \ + vartype field4; \ + vartype field5; \ + vartype field6; \ + vartype field7; \ + vartype field8; + + #define IB_BITFIELD9(vartype,field1,field2,field3,field4,field5,field6,field7,field8,field9) \ + vartype field1; \ + vartype field2; \ + vartype field3; \ + vartype field4; \ + vartype field5; \ + vartype field6; \ + vartype field7; \ + vartype field8; \ + vartype field9; + + #define IB_BITFIELD10(vartype,field1,field2,field3,field4,field5,field6,field7,field8,field9,field10) \ + vartype field1; \ + vartype field2; \ + vartype field3; \ + vartype field4; \ + vartype field5; \ + vartype field6; \ + vartype field7; \ + vartype field8; \ + vartype field9; \ + vartype field10; + + #define IB_BITFIELD11(vartype,field1,field2,field3,field4,field5,field6,field7,field8,field9,field10,field11) \ + vartype field1; \ + vartype field2; \ + vartype field3; \ + vartype field4; \ + vartype field5; \ + vartype field6; \ + vartype field7; \ + vartype field8; \ + vartype field9; \ + vartype field10;\ + vartype field11; + + #define IB_BITFIELD12(vartype,field1,field2,field3,field4,field5,field6,field7,field8,field9,field10,field11,field12) \ + vartype field1; \ + vartype field2; \ + vartype field3; \ + vartype field4; \ + vartype field5; \ + vartype field6; \ + vartype field7; \ + vartype field8; \ + vartype field9; \ + vartype field10;\ + vartype field11;\ + vartype field12; + + #define IB_BITFIELD13(vartype,field1,field2,field3,field4,field5,field6,field7,field8,field9,field10,field11,field12,field13) \ + vartype field1; \ + vartype field2; \ + vartype field3; \ + vartype field4; \ + vartype field5; \ + vartype field6; \ + vartype field7; \ + vartype field8; \ + vartype field9; \ + vartype field10;\ + vartype field11;\ + vartype field12;\ + vartype field13; + + #define IB_BITFIELD14(vartype,field1,field2,field3,field4,field5,field6,field7,field8,field9,field10,field11,field12,field13,field14) \ + vartype field1; \ + vartype field2; \ + vartype field3; \ + vartype field4; \ + vartype field5; \ + vartype field6; \ + vartype field7; \ + vartype field8; \ + vartype field9; \ + vartype field10;\ + vartype field11;\ + vartype field12;\ + vartype field13;\ + vartype field14; + + #define IB_BITFIELD15(vartype,field1,field2,field3,field4,field5,field6,field7,field8,field9,field10,field11,field12,field13,field14,field15) \ + vartype field1; \ + vartype field2; \ + vartype field3; \ + vartype field4; \ + vartype field5; \ + vartype field6; \ + vartype field7; \ + vartype field8; \ + vartype field9; \ + vartype field10;\ + vartype field11;\ + vartype field12;\ + vartype field13;\ + vartype field14;\ + vartype field15; + + #define IB_BITFIELD16(vartype,field1,field2,field3,field4,field5,field6,field7,field8,field9,field10,field11,field12,field13,field14,field15,field16) \ + vartype field1; \ + vartype field2; \ + vartype field3; \ + vartype field4; \ + vartype field5; \ + vartype field6; \ + vartype field7; \ + vartype field8; \ + vartype field9; \ + vartype field10;\ + vartype field11;\ + vartype field12;\ + vartype field13;\ + vartype field14;\ + vartype field15;\ + vartype field16; + + #define IB_BITFIELD17(vartype,field1,field2,field3,field4,field5,field6,field7,field8,field9,field10,field11,field12,field13,field14,field15,field16,field17) \ + vartype field1; \ + vartype field2; \ + vartype field3; \ + vartype field4; \ + vartype field5; \ + vartype field6; \ + vartype field7; \ + vartype field8; \ + vartype field9; \ + vartype field10;\ + vartype field11;\ + vartype field12;\ + vartype field13;\ + vartype field14;\ + vartype field15;\ + vartype field16;\ + vartype field17; + + #define IB_BITFIELD18(vartype,field1,field2,field3,field4,field5,field6,field7,field8,field9,field10,field11,field12,field13,field14,field15,field16,field17,field18) \ + vartype field1; \ + vartype field2; \ + vartype field3; \ + vartype field4; \ + vartype field5; \ + vartype field6; \ + vartype field7; \ + vartype field8; \ + vartype field9; \ + vartype field10;\ + vartype field11;\ + vartype field12;\ + vartype field13;\ + vartype field14;\ + vartype field15;\ + vartype field16;\ + vartype field17;\ + vartype field18; + + #define IB_BITFIELD19(vartype,field1,field2,field3,field4,field5,field6,field7,field8,field9,field10,field11,field12,field13,field14,field15,field16,field17,field18,field19) \ + vartype field1; \ + vartype field2; \ + vartype field3; \ + vartype field4; \ + vartype field5; \ + vartype field6; \ + vartype field7; \ + vartype field8; \ + vartype field9; \ + vartype field10;\ + vartype field11;\ + vartype field12;\ + vartype field13;\ + vartype field14;\ + vartype field15;\ + vartype field16;\ + vartype field17;\ + vartype field18;\ + vartype field19; + + #define IB_BITFIELD20(vartype,field1,field2,field3,field4,field5,field6,field7,field8,field9,field10,field11,field12,field13,field14,field15,field16,field17,field18,field19,field20) \ + vartype field1; \ + vartype field2; \ + vartype field3; \ + vartype field4; \ + vartype field5; \ + vartype field6; \ + vartype field7; \ + vartype field8; \ + vartype field9; \ + vartype field10;\ + vartype field11;\ + vartype field12;\ + vartype field13;\ + vartype field14;\ + vartype field15;\ + vartype field16;\ + vartype field17;\ + vartype field18;\ + vartype field19;\ + vartype field20; + + #define IB_BITFIELD21(vartype,field1,field2,field3,field4,field5,field6,field7,field8,field9,field10,field11,field12,field13,field14,field15,field16,field17,field18,field19,field20,field21) \ + vartype field1; \ + vartype field2; \ + vartype field3; \ + vartype field4; \ + vartype field5; \ + vartype field6; \ + vartype field7; \ + vartype field8; \ + vartype field9; \ + vartype field10;\ + vartype field11;\ + vartype field12;\ + vartype field13;\ + vartype field14;\ + vartype field15;\ + vartype field16;\ + vartype field17;\ + vartype field18;\ + vartype field19;\ + vartype field20;\ + vartype field21; + + #define IB_BITFIELD22(vartype,field1,field2,field3,field4,field5,field6,field7,field8,field9,field10,field11,field12,field13,field14,field15,field16,field17,field18,field19,field20,field21,field22) \ + vartype field1; \ + vartype field2; \ + vartype field3; \ + vartype field4; \ + vartype field5; \ + vartype field6; \ + vartype field7; \ + vartype field8; \ + vartype field9; \ + vartype field10;\ + vartype field11;\ + vartype field12;\ + vartype field13;\ + vartype field14;\ + vartype field15;\ + vartype field16;\ + vartype field17;\ + vartype field18;\ + vartype field19;\ + vartype field20;\ + vartype field21;\ + vartype field22; + + #define IB_BITFIELD23(vartype,field1,field2,field3,field4,field5,field6,field7,field8,field9,field10,field11,field12,field13,field14,field15,field16,field17,field18,field19,field20,field21,field22,field23) \ + vartype field1; \ + vartype field2; \ + vartype field3; \ + vartype field4; \ + vartype field5; \ + vartype field6; \ + vartype field7; \ + vartype field8; \ + vartype field9; \ + vartype field10;\ + vartype field11;\ + vartype field12;\ + vartype field13;\ + vartype field14;\ + vartype field15;\ + vartype field16;\ + vartype field17;\ + vartype field18;\ + vartype field19;\ + vartype field20;\ + vartype field21;\ + vartype field22;\ + vartype field23; + + #define IB_BITFIELD24(vartype,field1,field2,field3,field4,field5,field6,field7,field8,field9,field10,field11,field12,field13,field14,field15,field16,field17,field18,field19,field20,field21,field22,field23,field24) \ + vartype field1; \ + vartype field2; \ + vartype field3; \ + vartype field4; \ + vartype field5; \ + vartype field6; \ + vartype field7; \ + vartype field8; \ + vartype field9; \ + vartype field10;\ + vartype field11;\ + vartype field12;\ + vartype field13;\ + vartype field14;\ + vartype field15;\ + vartype field16;\ + vartype field17;\ + vartype field18;\ + vartype field19;\ + vartype field20;\ + vartype field21;\ + vartype field22;\ + vartype field23;\ + vartype field24; + + #define IB_BITFIELD25(vartype,field1,field2,field3,field4,field5,field6,field7,field8,field9,field10,field11,field12,field13,field14,field15,field16,field17,field18,field19,field20,field21,field22,field23,field24,field25) \ + vartype field1; \ + vartype field2; \ + vartype field3; \ + vartype field4; \ + vartype field5; \ + vartype field6; \ + vartype field7; \ + vartype field8; \ + vartype field9; \ + vartype field10;\ + vartype field11;\ + vartype field12;\ + vartype field13;\ + vartype field14;\ + vartype field15;\ + vartype field16;\ + vartype field17;\ + vartype field18;\ + vartype field19;\ + vartype field20;\ + vartype field21;\ + vartype field22;\ + vartype field23;\ + vartype field24;\ + vartype field25; + + #define IB_BITFIELD26(vartype,field1,field2,field3,field4,field5,field6,field7,field8,field9,field10,field11,field12,field13,field14,field15,field16,field17,field18,field19,field20,field21,field22,field23,field24,field25,field26) \ + vartype field1; \ + vartype field2; \ + vartype field3; \ + vartype field4; \ + vartype field5; \ + vartype field6; \ + vartype field7; \ + vartype field8; \ + vartype field9; \ + vartype field10;\ + vartype field11;\ + vartype field12;\ + vartype field13;\ + vartype field14;\ + vartype field15;\ + vartype field16;\ + vartype field17;\ + vartype field18;\ + vartype field19;\ + vartype field20;\ + vartype field21;\ + vartype field22;\ + vartype field23;\ + vartype field24;\ + vartype field25;\ + vartype field26; + + #define IB_BITFIELD27(vartype,field1,field2,field3,field4,field5,field6,field7,field8,field9,field10,field11,field12,field13,field14,field15,field16,field17,field18,field19,field20,field21,field22,field23,field24,field25,field26,field27) \ + vartype field1; \ + vartype field2; \ + vartype field3; \ + vartype field4; \ + vartype field5; \ + vartype field6; \ + vartype field7; \ + vartype field8; \ + vartype field9; \ + vartype field10;\ + vartype field11;\ + vartype field12;\ + vartype field13;\ + vartype field14;\ + vartype field15;\ + vartype field16;\ + vartype field17;\ + vartype field18;\ + vartype field19;\ + vartype field20;\ + vartype field21;\ + vartype field22;\ + vartype field23;\ + vartype field24;\ + vartype field25;\ + vartype field26;\ + vartype field27; + + #define IB_BITFIELD28(vartype,field1,field2,field3,field4,field5,field6,field7,field8,field9,field10,field11,field12,field13,field14,field15,field16,field17,field18,field19,field20,field21,field22,field23,field24,field25,field26,field27,field28) \ + vartype field1; \ + vartype field2; \ + vartype field3; \ + vartype field4; \ + vartype field5; \ + vartype field6; \ + vartype field7; \ + vartype field8; \ + vartype field9; \ + vartype field10;\ + vartype field11;\ + vartype field12;\ + vartype field13;\ + vartype field14;\ + vartype field15;\ + vartype field16;\ + vartype field17;\ + vartype field18;\ + vartype field19;\ + vartype field20;\ + vartype field21;\ + vartype field22;\ + vartype field23;\ + vartype field24;\ + vartype field25;\ + vartype field26;\ + vartype field27;\ + vartype field28; + + #define IB_BITFIELD29(vartype,field1,field2,field3,field4,field5,field6,field7,field8,field9,field10,field11,field12,field13,field14,field15,field16,field17,field18,field19,field20,field21,field22,field23,field24,field25,field26,field27,field28,field29) \ + vartype field1; \ + vartype field2; \ + vartype field3; \ + vartype field4; \ + vartype field5; \ + vartype field6; \ + vartype field7; \ + vartype field8; \ + vartype field9; \ + vartype field10;\ + vartype field11;\ + vartype field12;\ + vartype field13;\ + vartype field14;\ + vartype field15;\ + vartype field16;\ + vartype field17;\ + vartype field18;\ + vartype field19;\ + vartype field20;\ + vartype field21;\ + vartype field22;\ + vartype field23;\ + vartype field24;\ + vartype field25;\ + vartype field26;\ + vartype field27;\ + vartype field28;\ + vartype field29; + + #define IB_BITFIELD30(vartype,field1,field2,field3,field4,field5,field6,field7,field8,field9,field10,field11,field12,field13,field14,field15,field16,field17,field18,field19,field20,field21,field22,field23,field24,field25,field26,field27,field28,field29,field30) \ + vartype field1; \ + vartype field2; \ + vartype field3; \ + vartype field4; \ + vartype field5; \ + vartype field6; \ + vartype field7; \ + vartype field8; \ + vartype field9; \ + vartype field10;\ + vartype field11;\ + vartype field12;\ + vartype field13;\ + vartype field14;\ + vartype field15;\ + vartype field16;\ + vartype field17;\ + vartype field18;\ + vartype field19;\ + vartype field20;\ + vartype field21;\ + vartype field22;\ + vartype field23;\ + vartype field24;\ + vartype field25;\ + vartype field26;\ + vartype field27;\ + vartype field28;\ + vartype field29;\ + vartype field30; + + #define IB_BITFIELD31(vartype,field1,field2,field3,field4,field5,field6,field7,field8,field9,field10,field11,field12,field13,field14,field15,field16,field17,field18,field19,field20,field21,field22,field23,field24,field25,field26,field27,field28,field29,field30,field31) \ + vartype field1; \ + vartype field2; \ + vartype field3; \ + vartype field4; \ + vartype field5; \ + vartype field6; \ + vartype field7; \ + vartype field8; \ + vartype field9; \ + vartype field10;\ + vartype field11;\ + vartype field12;\ + vartype field13;\ + vartype field14;\ + vartype field15;\ + vartype field16;\ + vartype field17;\ + vartype field18;\ + vartype field19;\ + vartype field20;\ + vartype field21;\ + vartype field22;\ + vartype field23;\ + vartype field24;\ + vartype field25;\ + vartype field26;\ + vartype field27;\ + vartype field28;\ + vartype field29;\ + vartype field30;\ + vartype field31; + + #define IB_BITFIELD32(vartype,field1,field2,field3,field4,field5,field6,field7,field8,field9,field10,field11,field12,field13,field14,field15,field16,field17,field18,field19,field20,field21,field22,field23,field24,field25,field26,field27,field28,field29,field30,field31,field32) \ + vartype field1; \ + vartype field2; \ + vartype field3; \ + vartype field4; \ + vartype field5; \ + vartype field6; \ + vartype field7; \ + vartype field8; \ + vartype field9; \ + vartype field10;\ + vartype field11;\ + vartype field12;\ + vartype field13;\ + vartype field14;\ + vartype field15;\ + vartype field16;\ + vartype field17;\ + vartype field18;\ + vartype field19;\ + vartype field20;\ + vartype field21;\ + vartype field22;\ + vartype field23;\ + vartype field24;\ + vartype field25;\ + vartype field26;\ + vartype field27;\ + vartype field28;\ + vartype field29;\ + vartype field30;\ + vartype field31;\ + vartype field32; + +#elif CPU_LE + #define IB_BITFIELD2(vartype,field1,field2) \ + vartype field2; \ + vartype field1; + + #define IB_BITFIELD3(vartype,field1,field2,field3) \ + vartype field3; \ + vartype field2; \ + vartype field1; + + #define IB_BITFIELD4(vartype,field1,field2,field3,field4) \ + vartype field4; \ + vartype field3; \ + vartype field2; \ + vartype field1; + + #define IB_BITFIELD5(vartype,field1,field2,field3,field4,field5) \ + vartype field5; \ + vartype field4; \ + vartype field3; \ + vartype field2; \ + vartype field1; + + #define IB_BITFIELD6(vartype,field1,field2,field3,field4,field5,field6) \ + vartype field6; \ + vartype field5; \ + vartype field4; \ + vartype field3; \ + vartype field2; \ + vartype field1; + + #define IB_BITFIELD7(vartype,field1,field2,field3,field4,field5,field6,field7) \ + vartype field7; \ + vartype field6; \ + vartype field5; \ + vartype field4; \ + vartype field3; \ + vartype field2; \ + vartype field1; + + #define IB_BITFIELD8(vartype,field1,field2,field3,field4,field5,field6,field7,field8) \ + vartype field8; \ + vartype field7; \ + vartype field6; \ + vartype field5; \ + vartype field4; \ + vartype field3; \ + vartype field2; \ + vartype field1; + + #define IB_BITFIELD9(vartype,field1,field2,field3,field4,field5,field6,field7,field8,field9) \ + vartype field9; \ + vartype field8; \ + vartype field7; \ + vartype field6; \ + vartype field5; \ + vartype field4; \ + vartype field3; \ + vartype field2; \ + vartype field1; + + #define IB_BITFIELD10(vartype,field1,field2,field3,field4,field5,field6,field7,field8,field9,field10) \ + vartype field10;\ + vartype field9; \ + vartype field8; \ + vartype field7; \ + vartype field6; \ + vartype field5; \ + vartype field4; \ + vartype field3; \ + vartype field2; \ + vartype field1; + + #define IB_BITFIELD11(vartype,field1,field2,field3,field4,field5,field6,field7,field8,field9,field10,field11) \ + vartype field11;\ + vartype field10;\ + vartype field9; \ + vartype field8; \ + vartype field7; \ + vartype field6; \ + vartype field5; \ + vartype field4; \ + vartype field3; \ + vartype field2; \ + vartype field1; + + #define IB_BITFIELD12(vartype,field1,field2,field3,field4,field5,field6,field7,field8,field9,field10,field11,field12) \ + vartype field12;\ + vartype field11;\ + vartype field10;\ + vartype field9; \ + vartype field8; \ + vartype field7; \ + vartype field6; \ + vartype field5; \ + vartype field4; \ + vartype field3; \ + vartype field2; \ + vartype field1; + + #define IB_BITFIELD13(vartype,field1,field2,field3,field4,field5,field6,field7,field8,field9,field10,field11,field12,field13) \ + vartype field13;\ + vartype field12;\ + vartype field11;\ + vartype field10;\ + vartype field9; \ + vartype field8; \ + vartype field7; \ + vartype field6; \ + vartype field5; \ + vartype field4; \ + vartype field3; \ + vartype field2; \ + vartype field1; + + #define IB_BITFIELD14(vartype,field1,field2,field3,field4,field5,field6,field7,field8,field9,field10,field11,field12,field13,field14) \ + vartype field14;\ + vartype field13;\ + vartype field12;\ + vartype field11;\ + vartype field10;\ + vartype field9; \ + vartype field8; \ + vartype field7; \ + vartype field6; \ + vartype field5; \ + vartype field4; \ + vartype field3; \ + vartype field2; \ + vartype field1; + + #define IB_BITFIELD15(vartype,field1,field2,field3,field4,field5,field6,field7,field8,field9,field10,field11,field12,field13,field14,field15) \ + vartype field15;\ + vartype field14;\ + vartype field13;\ + vartype field12;\ + vartype field11;\ + vartype field10;\ + vartype field9; \ + vartype field8; \ + vartype field7; \ + vartype field6; \ + vartype field5; \ + vartype field4; \ + vartype field3; \ + vartype field2; \ + vartype field1; + + #define IB_BITFIELD16(vartype,field1,field2,field3,field4,field5,field6,field7,field8,field9,field10,field11,field12,field13,field14,field15,field16) \ + vartype field16;\ + vartype field15;\ + vartype field14;\ + vartype field13;\ + vartype field12;\ + vartype field11;\ + vartype field10;\ + vartype field9; \ + vartype field8; \ + vartype field7; \ + vartype field6; \ + vartype field5; \ + vartype field4; \ + vartype field3; \ + vartype field2; \ + vartype field1; + + #define IB_BITFIELD17(vartype,field1,field2,field3,field4,field5,field6,field7,field8,field9,field10,field11,field12,field13,field14,field15,field16,field17) \ + vartype field17;\ + vartype field16;\ + vartype field15;\ + vartype field14;\ + vartype field13;\ + vartype field12;\ + vartype field11;\ + vartype field10;\ + vartype field9; \ + vartype field8; \ + vartype field7; \ + vartype field6; \ + vartype field5; \ + vartype field4; \ + vartype field3; \ + vartype field2; \ + vartype field1; + + #define IB_BITFIELD18(vartype,field1,field2,field3,field4,field5,field6,field7,field8,field9,field10,field11,field12,field13,field14,field15,field16,field17,field18) \ + vartype field18;\ + vartype field17;\ + vartype field16;\ + vartype field15;\ + vartype field14;\ + vartype field13;\ + vartype field12;\ + vartype field11;\ + vartype field10;\ + vartype field9; \ + vartype field8; \ + vartype field7; \ + vartype field6; \ + vartype field5; \ + vartype field4; \ + vartype field3; \ + vartype field2; \ + vartype field1; + + #define IB_BITFIELD19(vartype,field1,field2,field3,field4,field5,field6,field7,field8,field9,field10,field11,field12,field13,field14,field15,field16,field17,field18,field19) \ + vartype field19;\ + vartype field18;\ + vartype field17;\ + vartype field16;\ + vartype field15;\ + vartype field14;\ + vartype field13;\ + vartype field12;\ + vartype field11;\ + vartype field10;\ + vartype field9; \ + vartype field8; \ + vartype field7; \ + vartype field6; \ + vartype field5; \ + vartype field4; \ + vartype field3; \ + vartype field2; \ + vartype field1; + + #define IB_BITFIELD20(vartype,field1,field2,field3,field4,field5,field6,field7,field8,field9,field10,field11,field12,field13,field14,field15,field16,field17,field18,field19,field20) \ + vartype field20;\ + vartype field19;\ + vartype field18;\ + vartype field17;\ + vartype field16;\ + vartype field15;\ + vartype field14;\ + vartype field13;\ + vartype field12;\ + vartype field11;\ + vartype field10;\ + vartype field9; \ + vartype field8; \ + vartype field7; \ + vartype field6; \ + vartype field5; \ + vartype field4; \ + vartype field3; \ + vartype field2; \ + vartype field1; + + #define IB_BITFIELD21(vartype,field1,field2,field3,field4,field5,field6,field7,field8,field9,field10,field11,field12,field13,field14,field15,field16,field17,field18,field19,field20,field21) \ + vartype field21;\ + vartype field20;\ + vartype field19;\ + vartype field18;\ + vartype field17;\ + vartype field16;\ + vartype field15;\ + vartype field14;\ + vartype field13;\ + vartype field12;\ + vartype field11;\ + vartype field10;\ + vartype field9; \ + vartype field8; \ + vartype field7; \ + vartype field6; \ + vartype field5; \ + vartype field4; \ + vartype field3; \ + vartype field2; \ + vartype field1; + + #define IB_BITFIELD22(vartype,field1,field2,field3,field4,field5,field6,field7,field8,field9,field10,field11,field12,field13,field14,field15,field16,field17,field18,field19,field20,field21,field22) \ + vartype field22;\ + vartype field21;\ + vartype field20;\ + vartype field19;\ + vartype field18;\ + vartype field17;\ + vartype field16;\ + vartype field15;\ + vartype field14;\ + vartype field13;\ + vartype field12;\ + vartype field11;\ + vartype field10;\ + vartype field9; \ + vartype field8; \ + vartype field7; \ + vartype field6; \ + vartype field5; \ + vartype field4; \ + vartype field3; \ + vartype field2; \ + vartype field1; + + #define IB_BITFIELD23(vartype,field1,field2,field3,field4,field5,field6,field7,field8,field9,field10,field11,field12,field13,field14,field15,field16,field17,field18,field19,field20,field21,field22,field23) \ + vartype field23;\ + vartype field22;\ + vartype field21;\ + vartype field20;\ + vartype field19;\ + vartype field18;\ + vartype field17;\ + vartype field16;\ + vartype field15;\ + vartype field14;\ + vartype field13;\ + vartype field12;\ + vartype field11;\ + vartype field10;\ + vartype field9; \ + vartype field8; \ + vartype field7; \ + vartype field6; \ + vartype field5; \ + vartype field4; \ + vartype field3; \ + vartype field2; \ + vartype field1; + + #define IB_BITFIELD24(vartype,field1,field2,field3,field4,field5,field6,field7,field8,field9,field10,field11,field12,field13,field14,field15,field16,field17,field18,field19,field20,field21,field22,field23,field24) \ + vartype field24;\ + vartype field23;\ + vartype field22;\ + vartype field21;\ + vartype field20;\ + vartype field19;\ + vartype field18;\ + vartype field17;\ + vartype field16;\ + vartype field15;\ + vartype field14;\ + vartype field13;\ + vartype field12;\ + vartype field11;\ + vartype field10;\ + vartype field9; \ + vartype field8; \ + vartype field7; \ + vartype field6; \ + vartype field5; \ + vartype field4; \ + vartype field3; \ + vartype field2; \ + vartype field1; + + #define IB_BITFIELD25(vartype,field1,field2,field3,field4,field5,field6,field7,field8,field9,field10,field11,field12,field13,field14,field15,field16,field17,field18,field19,field20,field21,field22,field23,field24,field25) \ + vartype field25;\ + vartype field24;\ + vartype field23;\ + vartype field22;\ + vartype field21;\ + vartype field20;\ + vartype field19;\ + vartype field18;\ + vartype field17;\ + vartype field16;\ + vartype field15;\ + vartype field14;\ + vartype field13;\ + vartype field12;\ + vartype field11;\ + vartype field10;\ + vartype field9; \ + vartype field8; \ + vartype field7; \ + vartype field6; \ + vartype field5; \ + vartype field4; \ + vartype field3; \ + vartype field2; \ + vartype field1; + + #define IB_BITFIELD26(vartype,field1,field2,field3,field4,field5,field6,field7,field8,field9,field10,field11,field12,field13,field14,field15,field16,field17,field18,field19,field20,field21,field22,field23,field24,field25,field26) \ + vartype field26;\ + vartype field25;\ + vartype field24;\ + vartype field23;\ + vartype field22;\ + vartype field21;\ + vartype field20;\ + vartype field19;\ + vartype field18;\ + vartype field17;\ + vartype field16;\ + vartype field15;\ + vartype field14;\ + vartype field13;\ + vartype field12;\ + vartype field11;\ + vartype field10;\ + vartype field9; \ + vartype field8; \ + vartype field7; \ + vartype field6; \ + vartype field5; \ + vartype field4; \ + vartype field3; \ + vartype field2; \ + vartype field1; + + #define IB_BITFIELD27(vartype,field1,field2,field3,field4,field5,field6,field7,field8,field9,field10,field11,field12,field13,field14,field15,field16,field17,field18,field19,field20,field21,field22,field23,field24,field25,field26,field27) \ + vartype field27;\ + vartype field26;\ + vartype field25;\ + vartype field24;\ + vartype field23;\ + vartype field22;\ + vartype field21;\ + vartype field20;\ + vartype field19;\ + vartype field18;\ + vartype field17;\ + vartype field16;\ + vartype field15;\ + vartype field14;\ + vartype field13;\ + vartype field12;\ + vartype field11;\ + vartype field10;\ + vartype field9; \ + vartype field8; \ + vartype field7; \ + vartype field6; \ + vartype field5; \ + vartype field4; \ + vartype field3; \ + vartype field2; \ + vartype field1; + + #define IB_BITFIELD28(vartype,field1,field2,field3,field4,field5,field6,field7,field8,field9,field10,field11,field12,field13,field14,field15,field16,field17,field18,field19,field20,field21,field22,field23,field24,field25,field26,field27,field28) \ + vartype field28;\ + vartype field27;\ + vartype field26;\ + vartype field25;\ + vartype field24;\ + vartype field23;\ + vartype field22;\ + vartype field21;\ + vartype field20;\ + vartype field19;\ + vartype field18;\ + vartype field17;\ + vartype field16;\ + vartype field15;\ + vartype field14;\ + vartype field13;\ + vartype field12;\ + vartype field11;\ + vartype field10;\ + vartype field9; \ + vartype field8; \ + vartype field7; \ + vartype field6; \ + vartype field5; \ + vartype field4; \ + vartype field3; \ + vartype field2; \ + vartype field1; + + #define IB_BITFIELD29(vartype,field1,field2,field3,field4,field5,field6,field7,field8,field9,field10,field11,field12,field13,field14,field15,field16,field17,field18,field19,field20,field21,field22,field23,field24,field25,field26,field27,field28,field29) \ + vartype field29;\ + vartype field28;\ + vartype field27;\ + vartype field26;\ + vartype field25;\ + vartype field24;\ + vartype field23;\ + vartype field22;\ + vartype field21;\ + vartype field20;\ + vartype field19;\ + vartype field18;\ + vartype field17;\ + vartype field16;\ + vartype field15;\ + vartype field14;\ + vartype field13;\ + vartype field12;\ + vartype field11;\ + vartype field10;\ + vartype field9; \ + vartype field8; \ + vartype field7; \ + vartype field6; \ + vartype field5; \ + vartype field4; \ + vartype field3; \ + vartype field2; \ + vartype field1; + + #define IB_BITFIELD30(vartype,field1,field2,field3,field4,field5,field6,field7,field8,field9,field10,field11,field12,field13,field14,field15,field16,field17,field18,field19,field20,field21,field22,field23,field24,field25,field26,field27,field28,field29,field30) \ + vartype field30;\ + vartype field29;\ + vartype field28;\ + vartype field27;\ + vartype field26;\ + vartype field25;\ + vartype field24;\ + vartype field23;\ + vartype field22;\ + vartype field21;\ + vartype field20;\ + vartype field19;\ + vartype field18;\ + vartype field17;\ + vartype field16;\ + vartype field15;\ + vartype field14;\ + vartype field13;\ + vartype field12;\ + vartype field11;\ + vartype field10;\ + vartype field9; \ + vartype field8; \ + vartype field7; \ + vartype field6; \ + vartype field5; \ + vartype field4; \ + vartype field3; \ + vartype field2; \ + vartype field1; + + #define IB_BITFIELD31(vartype,field1,field2,field3,field4,field5,field6,field7,field8,field9,field10,field11,field12,field13,field14,field15,field16,field17,field18,field19,field20,field21,field22,field23,field24,field25,field26,field27,field28,field29,field30,field31) \ + vartype field31;\ + vartype field30;\ + vartype field29;\ + vartype field28;\ + vartype field27;\ + vartype field26;\ + vartype field25;\ + vartype field24;\ + vartype field23;\ + vartype field22;\ + vartype field21;\ + vartype field20;\ + vartype field19;\ + vartype field18;\ + vartype field17;\ + vartype field16;\ + vartype field15;\ + vartype field14;\ + vartype field13;\ + vartype field12;\ + vartype field11;\ + vartype field10;\ + vartype field9; \ + vartype field8; \ + vartype field7; \ + vartype field6; \ + vartype field5; \ + vartype field4; \ + vartype field3; \ + vartype field2; \ + vartype field1; + + #define IB_BITFIELD32(vartype,field1,field2,field3,field4,field5,field6,field7,field8,field9,field10,field11,field12,field13,field14,field15,field16,field17,field18,field19,field20,field21,field22,field23,field24,field25,field26,field27,field28,field29,field30,field31,field32) \ + vartype field32;\ + vartype field31;\ + vartype field30;\ + vartype field29;\ + vartype field28;\ + vartype field27;\ + vartype field26;\ + vartype field25;\ + vartype field24;\ + vartype field23;\ + vartype field22;\ + vartype field21;\ + vartype field20;\ + vartype field19;\ + vartype field18;\ + vartype field17;\ + vartype field16;\ + vartype field15;\ + vartype field14;\ + vartype field13;\ + vartype field12;\ + vartype field11;\ + vartype field10;\ + vartype field9; \ + vartype field8; \ + vartype field7; \ + vartype field6; \ + vartype field5; \ + vartype field4; \ + vartype field3; \ + vartype field2; \ + vartype field1; +#else +#error "Uknown Byte order, neither CPU_LE nor CPU_BE set" +#endif /* CPU_LE */ + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* _IBA_PUBLIC_IBYTE_SWAP_H_ */ diff --git a/IbAccess/Common/Public/icmdthread.c b/IbAccess/Common/Public/icmdthread.c new file mode 100644 index 0000000..aa74051 --- /dev/null +++ b/IbAccess/Common/Public/icmdthread.c @@ -0,0 +1,210 @@ +/* BEGIN_ICS_COPYRIGHT6 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT6 ****************************************/ + +#include "icmdthread.h" +#include "imemory.h" + +#define CMD_THREAD_TAG MAKE_MEM_TAG( i, c, t, h ) + +// +// CmdThread Implementation +// + +static boolean CmdThreadDeQueue(CMD_THREAD* pCmdThread, void **pCmd) +{ + LIST_ITEM *pItem; + + SpinLockAcquire(&pCmdThread->m_QueueLock); + pItem = QListRemoveHead(&pCmdThread->m_Queue); + SpinLockRelease(&pCmdThread->m_QueueLock); + if (pItem == NULL) + return FALSE; + *pCmd = (void*)QListObj(pItem); + MemoryDeallocate(pItem); + return TRUE; +} + +// add a command to the end of the queue +boolean CmdThreadQueue(CMD_THREAD* pCmdThread, void *Cmd) +{ + LIST_ITEM *pItem; + + ASSERT( pCmdThread->m_Initialized ); + pItem = (LIST_ITEM*)MemoryAllocate2(sizeof(LIST_ITEM), IBA_MEM_FLAG_SHORT_DURATION, CMD_THREAD_TAG); + if (pItem == NULL) + return FALSE; + QListSetObj(pItem, Cmd); + SpinLockAcquire(&pCmdThread->m_QueueLock); + QListInsertTail(&pCmdThread->m_Queue, pItem); + SpinLockRelease(&pCmdThread->m_QueueLock); + EventTrigger(&pCmdThread->m_Event); + return TRUE; +} + +// internal Thread for cmd queue processing +static void +CmdThreadRoutine( + IN void *Context ) +{ + CMD_THREAD *pCmdThread = (CMD_THREAD*)Context; + + ThreadSetPriority(pCmdThread->m_Pri); + + // Continue looping until signalled to end. + while( TRUE ) + { + void* cmd; + + // Wait for the specified event to occur. + // IbAccess created kernel threads have signals blocked + // use interruptible wait so we don't contribute to loadavg + EventWaitOnInterruptible( &pCmdThread->m_Event, EVENT_NO_TIMEOUT ); + + // See if we've been signalled to end execution. + if( pCmdThread->m_Exit ) + { + break; + } + + while (CmdThreadDeQueue(pCmdThread, &cmd)) { + // A command is on the queue. Invoke the callback. + (*pCmdThread->m_Callback)( pCmdThread->m_Context, cmd ); + } + } +} + + +void +CmdThreadInitState( + IN CMD_THREAD *pCmdThread ) +{ + MemoryClear( pCmdThread, sizeof( CMD_THREAD ) ); + EventInitState( &pCmdThread->m_Event ); + QListInitState( &pCmdThread->m_Queue ); + SpinLockInitState( &pCmdThread->m_QueueLock ); + ThreadInitState( &pCmdThread->m_Thread ); +} + + +// +// Starts the thread +// +// Callback is called for each command processed, it should free the command +// as needed +// FreeCmd is only called on cleanup to free any commands remaining on the queue +// if cmd's do not need to be freed (eg. are not pointers), this can be NULL +boolean +CmdThreadCreate( + IN CMD_THREAD *pCmdThread, + IN THREAD_PRI Pri, + IN char* Name, + IN CMD_THREAD_CALLBACK Callback, + IN CMD_THREAD_CALLBACK FreeCmd, + IN void *Context ) +{ + ASSERT( Callback ); + ASSERT( ! pCmdThread->m_Initialized ); + + CmdThreadInitState( pCmdThread ); + + if( !SpinLockInit( &pCmdThread->m_QueueLock ) ) + goto fail_lock; + if( !QListInit( &pCmdThread->m_Queue ) ) + goto fail_list; + + // Initialize the event that the threads wait on. + if( !EventInit( &pCmdThread->m_Event ) ) + goto fail_event; + + pCmdThread->m_Callback = Callback; + pCmdThread->m_FreeCmd = FreeCmd; + pCmdThread->m_Context = Context; + pCmdThread->m_Pri = Pri; + + // Start the thread. + if( !ThreadCreate( &pCmdThread->m_Thread, Name, CmdThreadRoutine, pCmdThread ) ) + goto fail_thread; + + pCmdThread->m_Initialized = TRUE; + return TRUE; + +fail_thread: + EventDestroy(&pCmdThread->m_Event); +fail_event: + SpinLockDestroy(&pCmdThread->m_QueueLock); +fail_list: + QListDestroy(&pCmdThread->m_Queue); +fail_lock: + return FALSE; +} + + +// Destroys the thread, hence stopping it +void +CmdThreadStop( + IN CMD_THREAD *pCmdThread ) +{ + if( !pCmdThread->m_Initialized ) + return; + + // Indicate to thread that it needs to exit. + pCmdThread->m_Exit = TRUE; + + EventTrigger( &pCmdThread->m_Event ); + + // Stop the thread. Note: it is safe to call ThreadDestroy multiple times + ThreadDestroy( &pCmdThread->m_Thread ); +} + +// +// Destroys the threads and calls FreeCmd for each item on queue +// +void +CmdThreadDestroy( + IN CMD_THREAD *pCmdThread ) +{ + void *cmd; + + if( !pCmdThread->m_Initialized ) + return; + + CmdThreadStop(pCmdThread); + + // Free any remaining cmds on the Queue + while (CmdThreadDeQueue(pCmdThread, &cmd)) { + if (pCmdThread->m_FreeCmd != NULL) { + (*pCmdThread->m_FreeCmd)( pCmdThread->m_Context, cmd ); + } + } + + EventDestroy( &pCmdThread->m_Event ); + QListDestroy( &pCmdThread->m_Queue ); + SpinLockDestroy( &pCmdThread->m_QueueLock ); + pCmdThread->m_Initialized = FALSE; +} diff --git a/IbAccess/Common/Public/icmdthread.h b/IbAccess/Common/Public/icmdthread.h new file mode 100644 index 0000000..13e3b11 --- /dev/null +++ b/IbAccess/Common/Public/icmdthread.h @@ -0,0 +1,109 @@ +/* BEGIN_ICS_COPYRIGHT3 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT3 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + + +#ifndef _IBA_PUBLIC_ICMD_THREAD_H_ +#define _IBA_PUBLIC_ICMD_THREAD_H_ + +#include "iba/public/ilist.h" +#include "iba/public/ithread.h" +#include "iba/public/ievent.h" +#include "iba/public/ispinlock.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef void (*CMD_THREAD_CALLBACK)( IN void *Context, IN void* Cmd ); + +/* + * Cmd Thread object. + * Thread will wait until a command is placed on the queue, then invoke a + * command processing callback + * useful to perform command or packet processing in a thread context instead + * of a callback/ISR context + */ +typedef struct _CMD_THREAD +{ + /* Routine called by thread when cmd found on queue */ + CMD_THREAD_CALLBACK m_Callback; + CMD_THREAD_CALLBACK m_FreeCmd; /* called on cleanup to free commands */ + void *m_Context; + THREAD_PRI m_Pri; + + QUICK_LIST m_Queue; + SPIN_LOCK m_QueueLock; + EVENT m_Event; + THREAD m_Thread; + + boolean m_Initialized; + boolean m_Exit; +} CMD_THREAD; + +void +CmdThreadInitState( + IN CMD_THREAD *pCmdThread ); + +boolean +CmdThreadCreate( + IN CMD_THREAD *pCmdThread, + IN THREAD_PRI Pri, + IN char* Name, + IN CMD_THREAD_CALLBACK Callback, + IN CMD_THREAD_CALLBACK FreeCmd, + IN void *Context ); + +/* Stop must be called in a premptable context. + * Stops thread and waits for it. After this no more Callbacks will + * occur, calls to CmdThreadQueue will add to queue and + * wait for CmdThreadDestroy to clean the queue. + * intended for use during shutdown/destroy sequencing, + * thread cannot be restarted without CmdThreadDestroy being called first + */ +void +CmdThreadStop( + IN CMD_THREAD *pCmdThread ); + +/* Destroy must be called at passive level. */ +void +CmdThreadDestroy( + IN CMD_THREAD *pCmdThread ); + +boolean +CmdThreadQueue( + IN CMD_THREAD *pCmdThread, + IN void* cmd); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* _IBA_PUBLIC_ICMD_THREAD_H_ */ diff --git a/IbAccess/Common/Public/idebug.h b/IbAccess/Common/Public/idebug.h new file mode 100644 index 0000000..1538f7c --- /dev/null +++ b/IbAccess/Common/Public/idebug.h @@ -0,0 +1,82 @@ +/* BEGIN_ICS_COPYRIGHT3 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT3 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +#ifndef _IBA_PUBLIC_IDEBUG_H_ +#define _IBA_PUBLIC_IDEBUG_H_ + +#include "iba/public/datatypes.h" +#include "iba/public/idebug_osd.h" + + +#ifdef __cplusplus +extern "C" +{ +#endif + +typedef enum { + _DBG_DUMP_FORMAT_BYTES, /* dump bytes */ + _DBG_DUMP_FORMAT_U64, /* dump 64 bit words, Host Byte Order */ + _DBG_DUMP_FORMAT_U32, /* dump 32 bit words, Host Byte Order */ + _DBG_DUMP_FORMAT_U16, /* dump 16 bit words, Host Byte Order */ + _DBG_DUMP_FORMAT_LE_U64,/* dump 64 bit words, Little Endian */ + _DBG_DUMP_FORMAT_LE_U32,/* dump 32 bit words, Little Endian */ + _DBG_DUMP_FORMAT_LE_U16,/* dump 16 bit words, Little Endian */ + _DBG_DUMP_FORMAT_BE_U64,/* dump 64 bit words, Big Endian */ + _DBG_DUMP_FORMAT_BE_U32,/* dump 32 bit words, Big Endian */ + _DBG_DUMP_FORMAT_BE_U16 /* dump 16 bit words, Big Endian */ +} dbgDumpFormat_t; + +#if defined( IB_DEBUG ) +#ifndef DbgOut +#define DbgOut DbgOutRoutine +#endif +#else +#undef DbgOut +#define DbgOut(ARGLIST...) (void)(0) +#endif /* defined( IB_DEBUG ) */ + +#ifndef MsgOut +extern void +MsgOut( + IN char *Message, + IN ... ); +#endif + +void PrintDump( void* addr, uint32 len, dbgDumpFormat_t dumpFormat); +void PrintDump2( uint32 level, void* addr, uint32 len, dbgDumpFormat_t dumpFormat); + +void DumpStack(void); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* _IBA_PUBLIC_DEBUG_H_ */ diff --git a/IbAccess/Common/Public/idebugdump.c b/IbAccess/Common/Public/idebugdump.c new file mode 100644 index 0000000..d8d0aac --- /dev/null +++ b/IbAccess/Common/Public/idebugdump.c @@ -0,0 +1,174 @@ +/* BEGIN_ICS_COPYRIGHT6 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT6 ****************************************/ + +#include "datatypes.h" +#include "idebug.h" +#include "ibyteswap.h" + +struct buffer { + char data[80]; + int len; +}; + +#define BUF_PRINT(buf, format, args...) \ + (buf)->len += sprintf((buf)->data+(buf)->len, format, ## args) + +// output character representation of len bytes +static void FormatChars(struct buffer* buf, const uint8* addr, uint32 len) +{ + uint32 j; + + BUF_PRINT(buf, " "); + for (j = 0; j= ' ' && addr[j] <= '~') + { + BUF_PRINT(buf, "%c", addr[j]); + } else { + BUF_PRINT(buf, "."); + } + } +} + +void PrintDump( void* addr, uint32 len, dbgDumpFormat_t dumpFormat) +{ + PrintDump2( 0, addr, len, dumpFormat); +} + +void PrintDump2( uint32 level, void* addr, uint32 len, dbgDumpFormat_t dumpFormat) +{ + // not very efficient due to numerous IbLogPrintf calls + // and retesting format each loop but adequate for now + uint32 i; + struct buffer buf; + + IbLogPrintf(level, " Dump:\n"); + buf.len=0; + for (i=0; im_Priority); + + // Continue looping until signalled to end. + while( TRUE ) + { + // Wait for the specified event to occur. + // IbAccess created kernel threads have signals blocked + // use interruptible wait so we don't contribute to loadavg + EventWaitOnInterruptible( &pEventThread->m_Event, EVENT_NO_TIMEOUT ); + + // See if we've been signalled to end execution. + if( pEventThread->m_Exit ) + { + break; + } + + // The event has been signalled. Invoke the callback. + (*pEventThread->m_Callback)( pEventThread->m_Context ); + } +} + + +void +EventThreadInitState( + IN EVENT_THREAD *pEventThread ) +{ + MemoryClear( pEventThread, sizeof( EVENT_THREAD ) ); + EventInitState( &pEventThread->m_Event ); + ThreadInitState( &pEventThread->m_Thread ); +} + + +// +// Starts the event thread +// +boolean +EventThreadCreate( + IN EVENT_THREAD *pEventThread, + IN char* Name, + IN THREAD_PRI Priority, + IN THREAD_CALLBACK Callback, + IN void *Context ) +{ + ASSERT( Callback ); + + EventThreadInitState( pEventThread ); + + // Initialize the event that the thread waits on. + if( !EventInit( &pEventThread->m_Event ) ) + { + return FALSE; + } + + pEventThread->m_Priority = Priority; + pEventThread->m_Callback = Callback; + pEventThread->m_Context = Context; + + // Start the thread. + if( !ThreadCreate( &pEventThread->m_Thread, Name, EventThreadRoutine, pEventThread ) ) + { + EventDestroy(&pEventThread->m_Event); + return FALSE; + } + + pEventThread->m_Initialized = TRUE; + return TRUE; +} + +// Destroys the thread, hence stopping it +void +EventThreadStop( + IN EVENT_THREAD *pEventThread ) +{ + if( !pEventThread->m_Initialized ) + return; + + // Indicate to thread that it needs to exit. + pEventThread->m_Exit = TRUE; + + EventTrigger( &pEventThread->m_Event ); + + // Stop the thread. Note: it is safe to call ThreadDestroy multiple times + ThreadDestroy( &pEventThread->m_Thread ); +} + +// +// Destroys the thread and event +// +void +EventThreadDestroy( + IN EVENT_THREAD *pEventThread ) +{ + if( !pEventThread->m_Initialized ) + return; + + EventThreadStop(pEventThread); + + EventDestroy( &pEventThread->m_Event ); + pEventThread->m_Initialized = FALSE; +} diff --git a/IbAccess/Common/Public/ieventthread.h b/IbAccess/Common/Public/ieventthread.h new file mode 100644 index 0000000..81d646b --- /dev/null +++ b/IbAccess/Common/Public/ieventthread.h @@ -0,0 +1,102 @@ +/* BEGIN_ICS_COPYRIGHT3 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT3 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + + +#ifndef _IEVENT_THREAD_H_ +#define _IEVENT_THREAD_H_ + +#include "iba/public/ithread.h" +#include "iba/public/ievent.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Event Thread object. Thread will wait on an event, then invoke a callback. + */ +typedef struct _EVENT_THREAD +{ + /* Routine called by thread when the specified event occurs. */ + THREAD_CALLBACK m_Callback; + void *m_Context; + + THREAD m_Thread; + EVENT m_Event; + boolean m_Exit; + boolean m_Initialized; + THREAD_PRI m_Priority; + +} EVENT_THREAD; + +void +EventThreadInitState( + IN EVENT_THREAD *pEventThread ); + +boolean +EventThreadCreate( + IN EVENT_THREAD *pEventThread, + IN char* Name, + IN THREAD_PRI Priority, + IN THREAD_CALLBACK Callback, + IN void *Context ); + +/* Stop must be called at passive level. + * stops thread and waits for it. After this no more Callbacks will + * occur, calls to EventThreadSignal will do nothing + * intended for use during shutdown/destroy sequencing, + * thread cannot be restarted without EventThreadDestroy being called first + */ +void +EventThreadStop( + IN EVENT_THREAD *pEventThread ); + +/* Destroy must be called at passive level. */ +void +EventThreadDestroy( + IN EVENT_THREAD *pEventThread ); + +/* releases the thread for execution */ +static _inline void +EventThreadSignal( + IN EVENT_THREAD *pEventThread ) +{ +#ifdef IB_DEBUG + ASSERT(pEventThread->m_Initialized); +#endif + EventTrigger( &pEventThread->m_Event ); +} + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* _IEVENT_THREAD_H_ */ diff --git a/IbAccess/Common/Public/igrowpool.c b/IbAccess/Common/Public/igrowpool.c new file mode 100644 index 0000000..a5f83cf --- /dev/null +++ b/IbAccess/Common/Public/igrowpool.c @@ -0,0 +1,732 @@ +/* BEGIN_ICS_COPYRIGHT6 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT6 ****************************************/ + + +#include "igrowpool.h" +#include "imemory.h" +#include "imath.h" + + +//////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +////////////// //////////// +////////////// IMPLEMENTATION OF QUICK COMPOSITE POOL //////////// +////////////// //////////// +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// + +#define QPOOL_MEM_TAG MAKE_MEM_TAG( i, q, p, l ) + + +// +// Initialize the state of a quick composite pool. +// +void +QCompPoolInitState( + IN QCOMP_POOL* const pPool ) +{ + ASSERT( pPool ); + + MemoryClear( pPool, sizeof(QCOMP_POOL) ); + + QListInitState(&pPool->m_FreeList); + ObjMgrInitState(&pPool->m_ObjMgr); + + pPool->m_State = PoolReset; +} + + +// +// Initialize a quick composite pool. +// +FSTATUS +QCompPoolInit( + IN QCOMP_POOL* const pPool, + IN const uint32 MinCount, + IN const uint32* const ComponentSizes, + IN const uint32 NumComponents, + IN const uint32 GrowSize, + IN QCPOOL_CTOR_FUNC pfnConstructor, + IN QCPOOL_INIT_FUNC pfnInitializer OPTIONAL, + IN QCPOOL_DTOR_FUNC pfnDestructor OPTIONAL, + IN void* const Context ) +{ + FSTATUS Status; + uint32 i; + ASSERT( pPool ); + ASSERT( NumComponents ); + ASSERT( NumComponents == 1 || pfnConstructor ); + + QCompPoolInitState( pPool ); + + if( NumComponents != 1 && !pfnConstructor ) + return( FINVALID_SETTING ); + + // Allocate the array of component sizes and component pointers all + // in one allocation. + + pPool->m_pComponents = (void**)MemoryAllocateAndClear( + (sizeof(uint32) + sizeof(void*)) * NumComponents, + FALSE, QPOOL_MEM_TAG ); + + if( !pPool->m_pComponents ) + return( FINSUFFICIENT_MEMORY ); + + // Calculate the pointer to the array of pointers, used for callbacks. + pPool->m_ComponentSizes = (uint32*)(pPool->m_pComponents + NumComponents); + + // Copy the user's sizes into our array for future use. + MemoryCopy( pPool->m_ComponentSizes, ComponentSizes, + sizeof(uint32) * NumComponents ); + + // Store the number of sub-objects per object. + pPool->m_NumComponents = NumComponents; + + // Round up and store the size of the components. + for( i = 0; i < NumComponents; i++ ) + { + // We roundup each component size so that all components + // are aligned on a natural boundary. + pPool->m_ComponentSizes[i] = + ROUNDUPP2( pPool->m_ComponentSizes[i], sizeof(uintn) ); + } + + pPool->m_GrowSize = GrowSize; + + // Store callback function pointers. + pPool->m_pfnCtor = pfnConstructor; // may be NULL + pPool->m_pfnInit = pfnInitializer; // may be NULL + pPool->m_pfnDtor = pfnDestructor; // may be NULL + pPool->m_Context = Context; + + if( !ObjMgrInit( &pPool->m_ObjMgr, FALSE ) ) + { + // some error occurred + // user should call CompPoolDestroy() + return( FINSUFFICIENT_MEMORY ); + } + + if( !QListInit( &pPool->m_FreeList ) ) + { + // some error occurred + // user should call CompPoolDestroy() + return( FINSUFFICIENT_MEMORY ); + } + + // We are now initialized. We change the initialized flag before + // growing since the grow function asserts that we are initialized. + pPool->m_State = PoolReady; + + // so far so good. Do the allocations. + if( !MinCount ) + return( FSUCCESS ); + + Status = QCompPoolGrow( pPool, MinCount ); + // Trap for error. + if( Status != FSUCCESS ) + pPool->m_State = PoolInitError; + + return( Status ); +} + + +// +// Destroy a quick composite pool. +// +void +QCompPoolDestroy( + IN QCOMP_POOL* const pPool ) +{ + ASSERT( pPool ); + + if( pPool->m_State != PoolReset ) + { + // assert if the user hasn't put everything back in the pool + // before destroying it + // if they haven't, then most likely they are still using memory + // that will be freed, and the destructor will not be called! + ASSERT( QCompPoolCount(pPool) == pPool->m_NumObjects ); + + // call the user's destructor for each object in the pool + if( pPool->m_pfnDtor ) + { + while( QListCount( &pPool->m_FreeList ) ) + { + pPool->m_pfnDtor( QListRemoveHead( &pPool->m_FreeList ), + pPool->m_Context ); + } + } + } + + QListDestroy( &pPool->m_FreeList ); + ObjMgrDestroy( &pPool->m_ObjMgr ); + MemoryDeallocate(pPool->m_pComponents); +} + + +// +// Grow the number of objects in a quick composite pool. +// +FSTATUS +QCompPoolGrow( + IN QCOMP_POOL* const pPool, + IN uint32 ObjCount ) +{ + FSTATUS Status = FSUCCESS; + uint8 *pObject; + LIST_ITEM *pListItem; + uint32 i, ObjSize; + + ASSERT( pPool ); + ASSERT( pPool->m_State == PoolReady ); + ASSERT( ObjCount ); + + // Calculate the size of an object. + ObjSize = 0; + for( i = 0; i < pPool->m_NumComponents; i++ ) + ObjSize += pPool->m_ComponentSizes[i]; + + // Allocate the buffer for the new objects. + pObject = (uint8*)ObjMgrAllocate( &pPool->m_ObjMgr, ObjSize * ObjCount ); + + // Make sure the allocation succeeded. + if( !pObject ) + return( FINSUFFICIENT_MEMORY ); + + // initialize the new elements and add them to the free list + while( ObjCount-- ) + { + // Setup the array of components for the current object. + pPool->m_pComponents[0] = pObject; + for( i = 1; i < pPool->m_NumComponents; i++ ) + { + // Calculate the pointer to the next component. + pPool->m_pComponents[i] = (uint8*)pPool->m_pComponents[i-1] + + pPool->m_ComponentSizes[i-1]; + } + + // call the user's constructor + // this can NOT fail + if( pPool->m_pfnCtor ) + { + pListItem = pPool->m_pfnCtor( pPool->m_pComponents, + pPool->m_NumComponents, pPool->m_Context ); + ASSERT( pListItem ); + } + else + { + // If no constructor is provided, assume that the LIST_ITEM + // is stored at the beginning of the first component. + pListItem = (LIST_ITEM*)pPool->m_pComponents[0]; + // Set the list item to point to itself. + QListSetObj( pListItem, pListItem ); + } + + // call the user's initializer + // this can fail! + if( pPool->m_pfnInit ) + { + Status = pPool->m_pfnInit( pListItem, pPool->m_Context ); + if( Status != FSUCCESS ) + { + // user initialization failed + // we may have only grown the pool by some partial amount + // Invoke the destructor for the object that failed initialization. + if( pPool->m_pfnDtor ) + pPool->m_pfnDtor( pListItem, pPool->m_Context ); + + // Return the user's status. + return( Status ); + } + } + + // Insert the new item in the free list, traping for failure. + QListInsertHead( &pPool->m_FreeList, pListItem ); + + pPool->m_NumObjects++; + + // move the pointer to the next item + pObject = (uint8*)pObject + ObjSize; + } + + return( Status ); +} + + +// +// Get an object from a quick composite pool. +// +LIST_ITEM* +QCompPoolGet( + IN QCOMP_POOL* const pPool ) +{ + LIST_ITEM *pListItem; + + ASSERT( pPool ); + ASSERT( pPool->m_State == PoolReady ); + + if( !QCompPoolCount( pPool ) ) + { + // No object is available. + // Return NULL if the user does not want automatic growth. + if( !pPool->m_GrowSize ) + return( NULL ); + + // we ran out of elements + // get more + QCompPoolGrow( pPool, pPool->m_GrowSize ); + // we may not have gotten everything we wanted but we might have + // gotten something. + if( !QCompPoolCount( pPool ) ) + return( NULL ); + } + + pListItem = QListRemoveHead( &pPool->m_FreeList ); + // OK, at this point we have an object + ASSERT( pListItem ); + return( pListItem ); +} + + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +////////////// //////////// +////////////// IMPLEMENTATION OF QUICK GROW POOL //////////// +////////////// //////////// +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// + +// +// Callback to translate quick composite to quick grow pool +// constructor callback. +// +static LIST_ITEM* +QGrowPoolCtorCb( + IN void** const pCompArray, + IN uint32 NumComponents, + IN void* const Context ) +{ + QGROW_POOL *pPool = (QGROW_POOL*)Context; + + ASSERT( pPool ); + ASSERT( pPool->m_pfnCtor ); + ASSERT( NumComponents == 1 ); + + return( pPool->m_pfnCtor( pCompArray[0], pPool->m_Context ) ); +} + +// +// Callback to translate quick composite to quick grow pool +// constructor callback. +// +static FSTATUS +QGrowPoolInitCb( + IN LIST_ITEM* const pListItem, + IN void* const Context ) +{ + QGROW_POOL *pPool = (QGROW_POOL*)Context; + + ASSERT( pPool ); + ASSERT( pPool->m_pfnInit ); + + return( pPool->m_pfnInit( pListItem, pPool->m_Context ) ); +} + +// +// Callback to translate quick composite to quick grow pool +// constructor callback. +// +static void +QGrowPoolDtorCb( + IN LIST_ITEM* const pListItem, + IN void* const Context ) +{ + QGROW_POOL *pPool = (QGROW_POOL*)Context; + + ASSERT( pPool ); + ASSERT( pPool->m_pfnDtor ); + + pPool->m_pfnDtor( pListItem, pPool->m_Context ); +} + + +// +// Initializes the state of a quick grow pool. +// +void +QGrowPoolInitState( + IN QGROW_POOL* const pPool ) +{ + MemoryClear( pPool, sizeof(QGROW_POOL) ); + + QCompPoolInitState( &pPool->m_QCPool ); +} + + +// +// Initializes a quick grow pool. +// +FSTATUS +QGrowPoolInit( + IN QGROW_POOL* const pPool, + IN const uint32 MinCount, + IN const uint32 ObjectSize, + IN const uint32 GrowSize, + IN QGPOOL_CTOR_FUNC pfnConstructor OPTIONAL, + IN QGPOOL_INIT_FUNC pfnInitializer OPTIONAL, + IN QGPOOL_DTOR_FUNC pfnDestructor OPTIONAL, + IN void* const Context ) +{ + FSTATUS Status; + ASSERT( pPool ); + + QGrowPoolInitState( pPool ); + + pPool->m_pfnCtor = pfnConstructor; // may be NULL + pPool->m_pfnInit = pfnInitializer; // may be NULL + pPool->m_pfnDtor = pfnDestructor; // may be NULL + + Status = QCompPoolInit( &pPool->m_QCPool, MinCount, &ObjectSize, + 1, GrowSize, + pfnConstructor ? QGrowPoolCtorCb : NULL, + pfnInitializer ? QGrowPoolInitCb : NULL, + pfnDestructor ? QGrowPoolDtorCb : NULL, + pPool ); + + return( Status ); +} + + +// +// Destroy a quick grow pool. +// +void +QGrowPoolDestroy( + IN QGROW_POOL* const pPool ) +{ + ASSERT( pPool ); + QCompPoolDestroy( &pPool->m_QCPool ); +} + + +//////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +////////////// //////////// +////////////// IMPLEMENTATION OF COMPOSITE POOL //////////// +////////////// //////////// +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// + +#define CPOOL_MEM_TAG MAKE_MEM_TAG( i, c, p, l ) + + +static LIST_ITEM* +CompPoolCtorCb( + IN void** const pCompArray, + IN uint32 NumComponents, + IN void* const Context ) +{ + COMP_POOL *pPool = (COMP_POOL*)Context; + LIST_ITEM *pListItem; + ASSERT( pPool ); + + // Set our pointer to the list item, which is stored at the beginning of + // the first component. + pListItem = (LIST_ITEM*)pCompArray[0]; + // Calculate the pointer to the user's first component. + pCompArray[0] = ((uchar*)pCompArray[0]) + sizeof(LIST_ITEM); + + // Set the object pointer in the list item to point to the first of the + // user's components. + QListSetObj( pListItem, pCompArray[0] ); + + // Invoke the user's constructor callback. + if( pPool->m_pfnCtor ) + pPool->m_pfnCtor( pCompArray, NumComponents, pPool->m_Context ); + + return( pListItem ); +} + + +static FSTATUS +CompPoolInitCb( + IN LIST_ITEM* const pListItem, + IN void* const Context ) +{ + COMP_POOL *pPool = (COMP_POOL*)Context; + ASSERT( pPool ); + ASSERT( pPool->m_pfnInit ); + ASSERT( QListObj( pListItem ) ); + + // Invoke the user's initializer callback. + return( pPool->m_pfnInit( QListObj( pListItem ), pPool->m_Context ) ); +} + + +static void +CompPoolDtorCb( + IN LIST_ITEM* const pListItem, + IN void* const Context ) +{ + COMP_POOL *pPool = (COMP_POOL*)Context; + ASSERT( pPool ); + ASSERT( pPool->m_pfnDtor ); + ASSERT( QListObj( pListItem ) ); + + // Invoke the user's destructor callback. + pPool->m_pfnDtor( QListObj( pListItem ), pPool->m_Context ); +} + + +// +// Initializes the state of a composite pool. +// +void +CompPoolInitState( + IN COMP_POOL* const pCPool ) +{ + ASSERT( pCPool ); + + MemoryClear( pCPool, sizeof(COMP_POOL) ); + + QCompPoolInitState( &pCPool->m_QCPool ); +} + + +// +// Initialize a composite pool. +// +FSTATUS +CompPoolInit( + IN COMP_POOL* const pCPool, + IN const uint32 MinCount, + IN const uint32* const ComponentSizes, + IN const uint32 NumComponents, + IN const uint32 GrowSize, + IN CPOOL_CTOR_FUNC pfnConstructor, + IN CPOOL_INIT_FUNC pfnInitializer OPTIONAL, + IN CPOOL_DTOR_FUNC pfnDestructor OPTIONAL, + IN void* const Context ) +{ + FSTATUS Status; + uint32 *pCompSizes; + + ASSERT( pCPool ); + ASSERT( NumComponents ); + ASSERT( NumComponents == 1 || pfnConstructor ); + + CompPoolInitState( pCPool ); + + if( NumComponents != 1 && !pfnConstructor ) + return( FINVALID_SETTING ); + + // Allocate the array of component sizes, allocation sizes, and + // component pointers all in one allocation. + pCompSizes = (uint32*)MemoryAllocateAndClear( sizeof(uint32) * NumComponents, + FALSE, CPOOL_MEM_TAG ); + + if( !pCompSizes ) + return( FINSUFFICIENT_MEMORY ); + + // Copy the user's component sizes into our local component size array. + MemoryCopy( pCompSizes, ComponentSizes, sizeof(uint32) * NumComponents ); + + // Add the size of the list item to the first component. + pCompSizes[0] += sizeof(LIST_ITEM); + + // Store callback function pointers. + pCPool->m_pfnCtor = pfnConstructor; // may be NULL + pCPool->m_pfnInit = pfnInitializer; // may be NULL + pCPool->m_pfnDtor = pfnDestructor; // may be NULL + pCPool->m_Context = Context; + + Status = QCompPoolInit( &pCPool->m_QCPool, MinCount, pCompSizes, NumComponents, + GrowSize, + CompPoolCtorCb, + pfnInitializer ? CompPoolInitCb : NULL, + pfnDestructor ? CompPoolDtorCb : NULL, + pCPool ); + + return( Status ); +} + + +// +// Destroys a composite pool. +// +void +CompPoolDestroy( + IN COMP_POOL* const pCPool ) +{ + ASSERT( pCPool ); + + QCompPoolDestroy( &pCPool->m_QCPool ); +} + + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +////////////// //////////// +////////////// IMPLEMENTATION OF GROW POOL //////////// +////////////// //////////// +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// + + +static LIST_ITEM* +GrowPoolCtorCb( + IN void** const ppObj, + IN uint32 Count, + IN void* const Context ) +{ + GROW_POOL *pPool = (GROW_POOL*)Context; + LIST_ITEM *pListItem; + ASSERT( pPool ); + ASSERT( ppObj ); + ASSERT( Count == 1 ); + + // Set our pointer to the list item, which is stored at the beginning of + // the first component. + pListItem = (LIST_ITEM*)*ppObj; + // Calculate the pointer to the user's first component. + *ppObj = ((uchar*)*ppObj) + sizeof(LIST_ITEM); + + // Set the object pointer in the list item to point to the first of the + // user's components. + QListSetObj( pListItem, *ppObj ); + + // Invoke the user's constructor callback. + if( pPool->m_pfnCtor ) + pPool->m_pfnCtor( *ppObj, pPool->m_Context ); + + return( pListItem ); +} + + +static FSTATUS +GrowPoolInitCb( + IN LIST_ITEM* const pListItem, + IN void* const Context ) +{ + GROW_POOL *pPool = (GROW_POOL*)Context; + ASSERT( pPool ); + ASSERT( pPool->m_pfnInit ); + ASSERT( QListObj( pListItem ) ); + + // Invoke the user's initializer callback. + return( pPool->m_pfnInit( QListObj( pListItem ), pPool->m_Context ) ); +} + + +static void +GrowPoolDtorCb( + IN LIST_ITEM* const pListItem, + IN void* const Context ) +{ + GROW_POOL *pPool = (GROW_POOL*)Context; + ASSERT( pPool ); + ASSERT( pPool->m_pfnDtor ); + ASSERT( QListObj( pListItem ) ); + + // Invoke the user's destructor callback. + pPool->m_pfnDtor( QListObj( pListItem ), pPool->m_Context ); +} + + +// +// Initialize the state of a grow pool. +// +void +GrowPoolInitState( + IN GROW_POOL* const pGPool ) +{ + ASSERT( pGPool ); + + MemoryClear( pGPool, sizeof(GROW_POOL) ); + + QCompPoolInitState( &pGPool->m_QCPool ); +} + + +// +// Initialize a grow pool. +// +FSTATUS +GrowPoolInit( + IN GROW_POOL* const pGPool, + IN const uint32 MinCount, + IN uint32 ObjectSize, + IN const uint32 GrowSize, + IN GPOOL_CTOR_FUNC pfnConstructor OPTIONAL, + IN GPOOL_INIT_FUNC pfnInitializer OPTIONAL, + IN GPOOL_DTOR_FUNC pfnDestructor OPTIONAL, + IN void* const Context ) +{ + FSTATUS Status; + + ASSERT( pGPool ); + + GrowPoolInitState( pGPool ); + + // Add the size of the list item to the first component. + ObjectSize += sizeof(LIST_ITEM); + + // Store callback function pointers. + pGPool->m_pfnCtor = pfnConstructor; // may be NULL + pGPool->m_pfnInit = pfnInitializer; // may be NULL + pGPool->m_pfnDtor = pfnDestructor; // may be NULL + pGPool->m_Context = Context; + + // + // We need a constructor in all cases for GrowPool, since + // the user pointer must be manipulated to hide the prefixed LIST_ITEM + // + Status = QCompPoolInit( &pGPool->m_QCPool, MinCount, &ObjectSize, 1, + GrowSize, + GrowPoolCtorCb, + pfnInitializer ? GrowPoolInitCb : NULL, + pfnDestructor ? GrowPoolDtorCb : NULL, + pGPool ); + + return( Status ); +} + + +// +// Destroy a grow pool. +// +void +GrowPoolDestroy( + IN GROW_POOL* const pGPool ) +{ + ASSERT( pGPool ); + QCompPoolDestroy( &pGPool->m_QCPool ); +} + + diff --git a/IbAccess/Common/Public/igrowpool.h b/IbAccess/Common/Public/igrowpool.h new file mode 100644 index 0000000..25b24c9 --- /dev/null +++ b/IbAccess/Common/Public/igrowpool.h @@ -0,0 +1,620 @@ +/* BEGIN_ICS_COPYRIGHT3 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT3 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + + +#ifndef _IBA_PUBLIC_IGROWPOOL_H_ +#define _IBA_PUBLIC_IGROWPOOL_H_ + +#include "iba/public/datatypes.h" +#include "iba/public/iobjmgr.h" +#include "iba/public/ilist.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/**************************************************************************** + **************************************************************************** + *********** ********** + *********** DECLARATION OF QUICK COMPOSITE POOL ********** + *********** ********** + **************************************************************************** + ****************************************************************************/ + +typedef enum _POOL_STATE +{ + PoolReset, + PoolInitError, + PoolReady + +} POOL_STATE; + +/**************************************************************************** + * Quick composite pool callback + * function types. + */ +typedef LIST_ITEM* (*QCPOOL_CTOR_FUNC)( + IN void** const pCompArray, + IN uint32 NumComponents, + IN void* const Context ); + +typedef FSTATUS (*QCPOOL_INIT_FUNC)( + IN LIST_ITEM* const pListItem, + IN void* const Context ); + +typedef void (*QCPOOL_DTOR_FUNC)( + IN LIST_ITEM* const pListItem, + IN void* const Context ); + + +/**************************************************************************** + * Quick composite pool structure. + */ +typedef struct _QCOMP_POOL +{ + /* These fields are private and should NOt be directly accessed */ + /* Number of components that make up a composite object. */ + uint32 m_NumComponents; + + /* Array of sizes for components that make up a user object. */ + uint32 *m_ComponentSizes; + + /* Array of pointers to components, used for constructor callback. */ + void **m_pComponents; + + /* Number of objects in the pool */ + uint32 m_NumObjects; + + /* Number of objects to auto-grow */ + uint32 m_GrowSize; + + /* Pointer to object constructor */ + QCPOOL_CTOR_FUNC m_pfnCtor; + + /* Pointer to object initializer */ + QCPOOL_INIT_FUNC m_pfnInit; + + /* Pointer to object destructor */ + QCPOOL_DTOR_FUNC m_pfnDtor; + + /* Context to pass to callback functions. */ + void *m_Context; + + /* Stack of available objects */ + QUICK_LIST m_FreeList; + + /* Object manager holds allocations */ + OBJECT_MGR m_ObjMgr; + + POOL_STATE m_State; + +} QCOMP_POOL; + + + +/**************************************************************************** + * Quick composite pool access methods. + */ + +/* + * Initialize the state of a quick composite pool. + */ +void +QCompPoolInitState( + IN QCOMP_POOL* const pPool ); + + +/* + * Initialize a quick composite pool. + */ +FSTATUS +QCompPoolInit( + IN QCOMP_POOL* const pPool, + IN const uint32 MinCount, + IN const uint32* const ComponentSizes, + IN const uint32 NumComponents, + IN const uint32 GrowSize, + IN QCPOOL_CTOR_FUNC pfnConstructor, + IN QCPOOL_INIT_FUNC pfnInitializer OPTIONAL, + IN QCPOOL_DTOR_FUNC pfnDestructor OPTIONAL, + IN void* const Context ); + + +/* + * Destroy a quick composite pool. + */ +void +QCompPoolDestroy( + IN QCOMP_POOL* const pPool ); + +/* + * Returns the number of objects available in a quick composite pool. + */ +static __inline uint32 +QCompPoolCount( + IN QCOMP_POOL* const pPool ) +{ + ASSERT( pPool ); + return( QListCount( &pPool->m_FreeList ) ); +} + + +/* + * Get an object from a quick composite pool. + */ +LIST_ITEM* +QCompPoolGet( + IN QCOMP_POOL* const pPool ); + + +/* + * Puts an object back in a quick composite pool. + */ +static __inline void +QCompPoolPut( + IN QCOMP_POOL* const pPool, + IN LIST_ITEM* const pListItem ) +{ + /* return this lil' doggy to the pool */ + QListInsertHead( &pPool->m_FreeList, pListItem ); + /* check for funny-business */ + ASSERT( QCompPoolCount(pPool) <= pPool->m_NumObjects ); +} + + +/* + * Grows a quick composite pool by the specified number of objects. + */ +FSTATUS +QCompPoolGrow( + IN QCOMP_POOL* const pPool, + IN uint32 ObjCount ); + + +/**************************************************************************** + **************************************************************************** + *********** ********** + *********** DECLARATION OF QUICK GROW POOL ********** + *********** ********** + **************************************************************************** + ****************************************************************************/ + +/**************************************************************************** + * Quick grow pool callback function types. + */ +typedef LIST_ITEM* (*QGPOOL_CTOR_FUNC)( + IN void* const pObject, + IN void* const Context ); + +typedef FSTATUS (*QGPOOL_INIT_FUNC)( + IN LIST_ITEM* const pListItem, + IN void* const Context ); + +typedef void (*QGPOOL_DTOR_FUNC)( + IN LIST_ITEM* const pListItem, + IN void* const Context ); + + +/**************************************************************************** + * Grow pool structure. + */ +typedef struct _QGROW_POOL +{ + /* These fields are private and should NOT be directly accessed */ + QCOMP_POOL m_QCPool; + + QGPOOL_CTOR_FUNC m_pfnCtor; + QGPOOL_INIT_FUNC m_pfnInit; + QGPOOL_DTOR_FUNC m_pfnDtor; + void *m_Context; + +} QGROW_POOL; + + +/**************************************************************************** + * Quick grow pool access methods. + */ + +/* + * Initializes the state of a quick grow pool. + */ +void +QGrowPoolInitState( + IN QGROW_POOL* const pPool ); + + +/* + * Initializes a quick grow pool. + */ +FSTATUS +QGrowPoolInit( + IN QGROW_POOL* const pPool, + IN const uint32 MinCount, + IN const uint32 ObjectSize, + IN const uint32 GrowSize, + IN QGPOOL_CTOR_FUNC pfnConstructor OPTIONAL, + IN QGPOOL_INIT_FUNC pfnInitializer OPTIONAL, + IN QGPOOL_DTOR_FUNC pnfDestructor OPTIONAL, + IN void* const Context ); + + +/* + * Destroy a quick grow pool. + */ +void +QGrowPoolDestroy( + IN QGROW_POOL* const pPool ); + + +/* + * Gets an object from a quick grow pool. + */ +static __inline LIST_ITEM* +QGrowPoolGet( + IN QGROW_POOL* const pPool ) +{ + ASSERT( pPool ); + return( QCompPoolGet( &pPool->m_QCPool ) ); +} + + +/* + * Puts an object back in the pool. + */ +static __inline void +QGrowPoolPut( + IN QGROW_POOL* const pPool, + LIST_ITEM* const pListItem ) +{ + ASSERT( pPool ); + QCompPoolPut( &pPool->m_QCPool, pListItem ); +} + + +/* + * Grows a quick grow pool by the specified number of objects. + */ +static __inline FSTATUS +QGrowPoolGrow( + IN QGROW_POOL* const pPool, + IN const uint32 ObjCount ) +{ + ASSERT( pPool ); + return( QCompPoolGrow( &pPool->m_QCPool, ObjCount ) ); +} + + +/* + * Returns the number of objects available in a quick grow pool. + */ +static __inline uint32 +QGrowPoolCount( + IN QGROW_POOL* const pPool ) +{ + ASSERT( pPool ); + return( QCompPoolCount( &pPool->m_QCPool ) ); +} + + +/**************************************************************************** + **************************************************************************** + *********** ********** + *********** DECLARATION OF COMPOSITE POOL ********** + *********** ********** + **************************************************************************** + ****************************************************************************/ + +/**************************************************************************** + * Composite pool callback function types. + */ +typedef void (*CPOOL_CTOR_FUNC)( + IN void** const pCompArray, + IN uint32 NumComponents, + IN void* const Context ); + +typedef FSTATUS (*CPOOL_INIT_FUNC)( + IN void* const pObject, + IN void* const Context ); + +typedef void (*CPOOL_DTOR_FUNC)( + IN void* const pObject, + IN void* const Context ); + + +/**************************************************************************** + * Composite pool structure. + */ +typedef struct _COMP_POOL +{ + /* These fields are private and should NOT be directly accessed */ + QCOMP_POOL m_QCPool; + + /* Callback pointers. */ + CPOOL_CTOR_FUNC m_pfnCtor; + CPOOL_INIT_FUNC m_pfnInit; + CPOOL_DTOR_FUNC m_pfnDtor; + /* Context to pass to callback functions. */ + void *m_Context; + +} COMP_POOL; + + +/**************************************************************************** + * Composite pool access methods. + */ + +/* + * Initializes the state of a composite pool. + */ +void +CompPoolInitState( + IN COMP_POOL* const pCPool ); + + +/* + * Initializes a composite pool. + */ +FSTATUS +CompPoolInit( + IN COMP_POOL* const pCPool, + IN const uint32 MinCount, + IN const uint32* const ComponentSizes, + IN const uint32 NumComponents, + IN const uint32 GrowSize, + IN CPOOL_CTOR_FUNC pfnConstructor, + IN CPOOL_INIT_FUNC pfnInitializer OPTIONAL, + IN CPOOL_DTOR_FUNC pfnDestructor OPTIONAL, + IN void* const Context ); + + +/* + * Destroys a composite pool. + */ +void +CompPoolDestroy( + IN COMP_POOL* const pCPool ); + + +/* + * Gets an object from a composite pool. + */ +static __inline void* +CompPoolGet( + IN COMP_POOL* const pCPool ) +{ + LIST_ITEM *pListItem; + + ASSERT( pCPool ); + + pListItem = QCompPoolGet( &pCPool->m_QCPool ); + if( !pListItem ) + return( NULL ); + + return( QListObj( pListItem ) ); +} + + +/* + * Puts an object back in a composite pool. + */ +static __inline void +CompPoolPut( + IN COMP_POOL* const pCPool, + IN void* const pObject ) +{ + LIST_ITEM *pListItem; + + ASSERT( pCPool ); + ASSERT( pObject ); + + pListItem = (LIST_ITEM*)((uchar*)pObject - sizeof(LIST_ITEM)); + + /* good sanity check */ + ASSERT( pListItem->pObject == pObject ); + + QCompPoolPut( &pCPool->m_QCPool, pListItem ); +} + + +/* + * Grows a composite pool by the specified number of objects. + */ +static __inline FSTATUS +CompPoolGrow( + IN COMP_POOL* const pCPool, + IN uint32 ObjCount ) +{ + ASSERT( pCPool ); + return( QCompPoolGrow( &pCPool->m_QCPool, ObjCount ) ); +} + + +/* + * Returns the number of objects available in a composite pool. + */ +static __inline uint32 +CompPoolCount( + IN COMP_POOL* const pCPool ) +{ + ASSERT( pCPool ); + return( QCompPoolCount( &pCPool->m_QCPool ) ); +} + + +/**************************************************************************** + **************************************************************************** + *********** ********** + *********** DECLARATION OF GROW POOL ********** + *********** ********** + **************************************************************************** + ****************************************************************************/ + +/**************************************************************************** + * Grow pool callback function types. + */ +typedef void (*GPOOL_CTOR_FUNC)( + IN void* const pObject, + IN void* const Context ); + +typedef FSTATUS (*GPOOL_INIT_FUNC)( + IN void* const pObject, + IN void* const Context ); + +typedef void (*GPOOL_DTOR_FUNC)( + IN void* const pObject, + IN void* const Context ); + + +/**************************************************************************** + * Grow pool structure. + */ +typedef struct _GROW_POOL +{ + /* These fields are private and should NOT be directly accessed */ + QCOMP_POOL m_QCPool; + + GPOOL_CTOR_FUNC m_pfnCtor; + GPOOL_INIT_FUNC m_pfnInit; + GPOOL_DTOR_FUNC m_pfnDtor; + void *m_Context; + +} GROW_POOL; + + +/**************************************************************************** + * Grow pool access methods. + */ + +/* + * Initializes the state of a grow pool. + */ +void +GrowPoolInitState( + IN GROW_POOL* const pGPool ); + + +/* + * Initialize a grow pool. + */ +FSTATUS +GrowPoolInit( + IN GROW_POOL* const pGPool, + IN const uint32 MinCount, + IN uint32 ObjectSize, + IN const uint32 GrowSize, + IN GPOOL_CTOR_FUNC pfnConstructor OPTIONAL, + IN GPOOL_INIT_FUNC pfnInitializer OPTIONAL, + IN GPOOL_DTOR_FUNC pnfDestructor OPTIONAL, + IN void* const Context ); + + +/* + * Destroy a grow pool. + */ +void +GrowPoolDestroy( + IN GROW_POOL* const pGPool ); + + +/* + * Get an object from a grow pool. + */ +static __inline void* +GrowPoolGet( + IN GROW_POOL* const pGPool ) +{ + LIST_ITEM *pListItem; + + ASSERT( pGPool ); + + pListItem = QCompPoolGet( &pGPool->m_QCPool ); + if( !pListItem ) + return( NULL ); + + ASSERT( QListObj( pListItem ) != NULL ); + return( QListObj( pListItem ) ); +} + + +/* + * Put an object back in a grow pool. + */ +static __inline void +GrowPoolPut( + IN GROW_POOL* const pGPool, + void* const pObject ) +{ + LIST_ITEM *pListItem; + + ASSERT( pGPool ); + ASSERT( pObject ); + + pListItem = (LIST_ITEM*)((uchar*)pObject - sizeof(LIST_ITEM)); + + /* good sanity check */ + ASSERT( pListItem->pObject == pObject ); + + QCompPoolPut( &pGPool->m_QCPool, pListItem ); +} + + +/* + * Grows the resource pool by the specified number of objects. + */ +static __inline FSTATUS +GrowPoolGrow( + IN GROW_POOL* const pGPool, + IN const uint32 ObjCount ) +{ + ASSERT( pGPool ); + return( QCompPoolGrow( &pGPool->m_QCPool, ObjCount ) ); +} + + +/* + * Returns the number of objects available in the free pool. + */ +static __inline uint32 +GrowPoolCount( + IN GROW_POOL* const pGPool ) +{ + ASSERT( pGPool ); + return( QCompPoolCount( &pGPool->m_QCPool ) ); +} + + +#ifdef __cplusplus +} /* extern "C" */ +#endif + + +#endif /* _IBA_PUBLIC_IGROWPOOL_H_ */ diff --git a/IbAccess/Common/Public/ihandletrans.c b/IbAccess/Common/Public/ihandletrans.c new file mode 100644 index 0000000..4cac989 --- /dev/null +++ b/IbAccess/Common/Public/ihandletrans.c @@ -0,0 +1,294 @@ +/* BEGIN_ICS_COPYRIGHT6 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT6 ****************************************/ + + +#include "ihandletrans.h" + +/////////////////////////////////////////////////////////////////////////////// +// LHandleTransInitState +// +// Description: +// This function performs basic initialization. This function cannot +// fail. +// +// Inputs: +// pLHandleTrans - Pointer to handle translator +// +// Outputs: +// None. +// +// Returns: +// None. +// +/////////////////////////////////////////////////////////////////////////////// +void +LHandleTransInitState( + IN LOCKED_HANDLE_TRANS* const pLHandleTrans ) +{ + SpinLockInitState(&pLHandleTrans->m_Lock); + ArrayInitState(&pLHandleTrans->m_List); + ResMapInitState(&pLHandleTrans->m_Map); +} + + +/////////////////////////////////////////////////////////////////////////////// +// LHandleTransInit +// +// Description: +// This function initializes the handle translator. +// New entries in the translator are +// initialized to NULL. +// +// Inputs: +// pLHandleTrans - Pointer to handle translator +// InitialSize - initial number of elements +// GrowSize - number of elements to allocate when incrementally growing +// the handle translator +// MaxHandles - maximum handles allowed, 0 if no limit +// MemFlags - memory allocate flags (IBA_MEM_FLAG_*) +// +// Outputs: +// None. +// +// Returns: +// FSUCCESS +// FINSUFFICIENT_MEMORY - failed to initialize translator +// +/////////////////////////////////////////////////////////////////////////////// +FSTATUS +LHandleTransInit( + IN LOCKED_HANDLE_TRANS* const pLHandleTrans, + IN const uint32 InitialSize, + IN const uint32 GrowSize, + IN const uint32 MaxHandles, + IN const uint32 MemFlags ) +{ + if (! SpinLockInit(&pLHandleTrans->m_Lock)) + goto faillock; + if (FSUCCESS != ArrayInit(&pLHandleTrans->m_List, InitialSize, GrowSize, sizeof(void*), MemFlags)) + goto faillist; + if (FSUCCESS != ResMapInit(&pLHandleTrans->m_Map, InitialSize, GrowSize, MaxHandles, (MemFlags&IBA_MEM_FLAG_PAGEABLE)?TRUE:FALSE)) + goto failmap; + // reserve entry 0 so no handles end up being 0 + if (FSUCCESS != ResMapReserve(&pLHandleTrans->m_Map, 0)) + goto failres; + return FSUCCESS; + +failres: + ResMapDestroy(&pLHandleTrans->m_Map); +failmap: + ArrayDestroy(&pLHandleTrans->m_List); +faillist: + SpinLockDestroy(&pLHandleTrans->m_Lock); +faillock: + return FINSUFFICIENT_MEMORY; +} + + +/////////////////////////////////////////////////////////////////////////////// +// LHandleTransDestroy +// +// Description: +// This function deallocates all allocated memory associated with the +// handle translator. +// If any operations did premptable memory allocate (via MemFlags), this +// may prempt. +// +// Inputs: +// pLHandleTrans - Pointer to handle translator +// +// Outputs: +// None. +// +// Returns: +// None. +// +/////////////////////////////////////////////////////////////////////////////// +void +LHandleTransDestroy( + IN LOCKED_HANDLE_TRANS* const pLHandleTrans ) +{ + ResMapDestroy(&pLHandleTrans->m_Map); + ArrayDestroy(&pLHandleTrans->m_List); + SpinLockDestroy(&pLHandleTrans->m_Lock); +} + +/////////////////////////////////////////////////////////////////////////////// +// LHandleTransCreateHandle +// +// Description: +// This function creates a new 32 bit handle to the given pointer +// As necessary the internal vector may grow. +// +// Inputs: +// pLHandleTrans- Pointer to handle translator. +// Ptr - Pointer of object handle is for +// MemFlags - memory allocate flags (IBA_MEM_FLAG_*) +// +// Outputs: +// pHandle - Handle created +// +// Returns: +// FSUCCESS +// FINSUFFICIENT_MEMORY The array could not be resized to accomodate the +// specified element. +// +/////////////////////////////////////////////////////////////////////////////// +FSTATUS +LHandleTransCreateHandle( + IN LOCKED_HANDLE_TRANS* pLHandleTrans, + IN const void* Ptr, + IN const uint32 MemFlags, + OUT uint32* pHandle ) +{ + FSTATUS status; + void *pNewElements = NULL; + + SpinLockAcquire(&pLHandleTrans->m_Lock); + status = ResMapAllocate(&pLHandleTrans->m_Map, pHandle); + if (status != FSUCCESS) + goto done; + if (MemFlags & IBA_MEM_FLAG_PREMPTABLE) + { + SpinLockRelease(&pLHandleTrans->m_Lock); + status = ArrayPrepareSet(&pLHandleTrans->m_List, *pHandle, MemFlags, &pNewElements); + SpinLockAcquire(&pLHandleTrans->m_Lock); + if (status != FSUCCESS) + goto failarray; + } + status = ArraySetPointer(&pLHandleTrans->m_List, *pHandle, (void*)Ptr, MemFlags, &pNewElements); + if (status != FSUCCESS) + goto failarray; +done: + SpinLockRelease(&pLHandleTrans->m_Lock); + if (pNewElements) + MemoryDeallocate(pNewElements); + return status; +failarray: + (void)ResMapFree(&pLHandleTrans->m_Map, *pHandle); + goto done; +} + +/////////////////////////////////////////////////////////////////////////////// +// LHandleTransReplaceHandle +// +// Description: +// This function replaces the pointer which an existing handle points to +// +// Inputs: +// pLHandleTrans- Pointer to handle translator. +// Handle - previously created handle +// Ptr - Pointer of object handle is for +// +// Outputs: +// +// Returns: +// FSUCCESS +// FINSUFFICIENT_MEMORY The array could not be resized to accomodate the +// specified element. +// +/////////////////////////////////////////////////////////////////////////////// +FSTATUS +LHandleTransReplaceHandle( + IN LOCKED_HANDLE_TRANS* pLHandleTrans, + IN uint32 Handle, + IN const void* Ptr) +{ + FSTATUS status; + + SpinLockAcquire(&pLHandleTrans->m_Lock); + status = ArraySetPointer(&pLHandleTrans->m_List, Handle, (void*)Ptr, IBA_MEM_FLAG_NONE, NULL); + SpinLockRelease(&pLHandleTrans->m_Lock); + return status; +} + +/////////////////////////////////////////////////////////////////////////////// +// LHandleTransDestroyHandle +// +// Description: +// This function destroys a handle, by replacing its pointer with NULL +// +// Inputs: +// pLHandleTrans- Pointer to handle translator. +// Handle - previously created handle +// +// Outputs: +// +// Returns: +// FSUCCESS - successfully destroyed handle +// FINVALID_STATE - handle was not valid +// +/////////////////////////////////////////////////////////////////////////////// +FSTATUS +LHandleTransDestroyHandle( + IN LOCKED_HANDLE_TRANS* pLHandleTrans, + IN uint32 Handle ) +{ + FSTATUS status; + + SpinLockAcquire(&pLHandleTrans->m_Lock); + status = ResMapFree(&pLHandleTrans->m_Map, Handle); + if (FSUCCESS == status) + { + (void)ArraySetPointer(&pLHandleTrans->m_List, Handle, NULL, IBA_MEM_FLAG_NONE, NULL); + } + SpinLockRelease(&pLHandleTrans->m_Lock); + return status; +} + + +/////////////////////////////////////////////////////////////////////////////// +// LHandleTransGetPtr +// +// Description: +// This function translates from a handle to its corresponding pointer +// +// Inputs: +// pLHandleTrans- Pointer to handle translator. +// Handle - previously created handle +// +// Outputs: +// +// Returns: +// pointer assigned to handle (will be NULL if invalid handle) +// +/////////////////////////////////////////////////////////////////////////////// +void* +LHandleTransGetPtr( + IN LOCKED_HANDLE_TRANS* pLHandleTrans, + IN uint32 Handle) +{ + void* Ptr; + + SpinLockAcquire(&pLHandleTrans->m_Lock); + if (FSUCCESS != ArrayAtPointer(&pLHandleTrans->m_List, Handle, (void**)&Ptr)) + Ptr = NULL; + SpinLockRelease(&pLHandleTrans->m_Lock); + return Ptr; +} diff --git a/IbAccess/Common/Public/ihandletrans.h b/IbAccess/Common/Public/ihandletrans.h new file mode 100644 index 0000000..5b2278f --- /dev/null +++ b/IbAccess/Common/Public/ihandletrans.h @@ -0,0 +1,257 @@ +/* BEGIN_ICS_COPYRIGHT3 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT3 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + + +#ifndef _IBA_PUBLIC_IHANDLETRANS_H_ +#define _IBA_PUBLIC_IHANDLETRANS_H_ + +#include "iba/public/datatypes.h" +#include "iba/public/iarray.h" +#include "iba/public/iresmap.h" +#include "iba/public/ispinlock.h" + + +#ifdef __cplusplus +extern "C" +{ +#endif + +/**************************************************************************** + * + * Handle Translator definition. + * + * A Handle Translator facilitates translation from 32 bit handles to + * pointers to the corresponding resource. This can provide 2 + * benefits: + * - a handle validation function + * - support for APIs (such as VAPI) with 32 bit handles + * + * Internally a Handle Translator uses a vector and a resource map which + * can be dynamically resized as more handles are created. + * + * The handle 0 is reserved such that 0 can be treated as a invalid handle + * Similarly, an unitialized/freed/deleted handle returns NULL for its pointer + * + * The Locked Handle Translator has its own spinlock and is thread safe + */ + + +/* handle translator structure is allocated by the user and is opaque to them */ +typedef struct _LOCKED_HANDLE_TRANS +{ + SPIN_LOCK m_Lock; /* protects structure */ + ARRAY m_List; /* index is handle, contained object is ptr */ + RESOURCE_MAP m_Map; /* efficiently track available entries in Array */ +} LOCKED_HANDLE_TRANS; + + +/**************************************************************************** + * LHandleTransInitState + * + * Description: + * This function performs basic initialization. This function cannot + * fail. + * + * Inputs: + * pLHandleTrans - Pointer to handle translator + * + * Outputs: + * None. + * + * Returns: + * None. + * + ****************************************************************************/ +void +LHandleTransInitState( + IN LOCKED_HANDLE_TRANS* const pLHandleTrans ); + + +/**************************************************************************** + * LHandleTransInit + * + * Description: + * This function initializes the handle translator. + * New entries in the translator are + * initialized to NULL. + * + * Inputs: + * pLHandleTrans - Pointer to handle translator + * InitialSize - initial number of elements + * GrowSize - number of elements to allocate when incrementally growing + * the handle translator + * MaxHandles - maximum handles allowed, 0 if no limit + * MemFlags - memory allocate flags (IBA_MEM_FLAG_*) + * + * Outputs: + * None. + * + * Returns: + * FSUCCESS + * FINSUFFICIENT_MEMORY - failed to initialize translator + * + ****************************************************************************/ +FSTATUS +LHandleTransInit( + IN LOCKED_HANDLE_TRANS* const pLHandleTrans, + IN const uint32 InitialSize, + IN const uint32 GrowSize, + IN const uint32 MaxHandles, + IN const uint32 MemFlags ); + + +/**************************************************************************** + * LHandleTransDestroy + * + * Description: + * This function deallocates all allocated memory associated with the + * handle translator. + * If any operations did premptable memory allocate (via MemFlags), this + * may prempt. + * + * Inputs: + * pLHandleTrans - Pointer to handle translator + * + * Outputs: + * None. + * + * Returns: + * None. + * + ****************************************************************************/ +void +LHandleTransDestroy( + IN LOCKED_HANDLE_TRANS* const pLHandleTrans ); + +/**************************************************************************** + * LHandleTransCreateHandle + * + * Description: + * This function creates a new 32 bit handle to the given pointer + * As necessary the internal vector may grow. + * + * Inputs: + * pLHandleTrans- Pointer to handle translator. + * Ptr - Pointer of object handle is for + * MemFlags - memory allocate flags (IBA_MEM_FLAG_*) + * + * Outputs: + * pHandle - Handle created + * + * Returns: + * FSUCCESS + * FINSUFFICIENT_MEMORY unable to grows translator + * FINSUFFICIENT_RESOURCES would exceed MaxHandles specified in Init + * + ****************************************************************************/ +FSTATUS +LHandleTransCreateHandle( + IN LOCKED_HANDLE_TRANS* pLHandleTrans, + IN const void* Ptr, + IN const uint32 MemFlags, + OUT uint32* pHandle ); + +/**************************************************************************** + * LHandleTransReplaceHandle + * + * Description: + * This function replaces the pointer which an existing handle points to + * + * Inputs: + * pLHandleTrans- Pointer to handle translator. + * Handle - previously created handle + * Ptr - Pointer of object handle is for + * + * Outputs: + * + * Returns: + * FSUCCESS + * FINSUFFICIENT_MEMORY The array could not be resized to accomodate the + * specified element. + * + ****************************************************************************/ +FSTATUS +LHandleTransReplaceHandle( + IN LOCKED_HANDLE_TRANS* pLHandleTrans, + IN uint32 Handle, + IN const void* Ptr); + +/**************************************************************************** + * LHandleTransDestroyHandle + * + * Description: + * This function destroys a handle, by replacing its pointer with NULL + * + * Inputs: + * pLHandleTrans- Pointer to handle translator. + * Handle - previously created handle + * + * Outputs: + * + * Returns: + * FSUCCESS - successfully destroyed handle + * FINVALID_STATE - handle was not valid + * + ****************************************************************************/ +FSTATUS +LHandleTransDestroyHandle( + IN LOCKED_HANDLE_TRANS* pLHandleTrans, + IN uint32 Handle ); + + +/**************************************************************************** + * LHandleTransGetPtr + * + * Description: + * This function translates from a handle to its corresponding pointer + * + * Inputs: + * pLHandleTrans- Pointer to handle translator. + * Handle - previously created handle + * + * Outputs: + * + * Returns: + * pointer assigned to handle (will be NULL if invalid handle) + * + ****************************************************************************/ +void* +LHandleTransGetPtr( + IN LOCKED_HANDLE_TRANS* pLHandleTrans, + IN uint32 Handle); + + +#ifdef __cplusplus +} /* extern "C" */ +#endif + + +#endif /* _IBA_PUBLIC_IHANDLETRANS_H_ */ diff --git a/IbAccess/Common/Public/iheapmanager.c b/IbAccess/Common/Public/iheapmanager.c new file mode 100644 index 0000000..418b39f --- /dev/null +++ b/IbAccess/Common/Public/iheapmanager.c @@ -0,0 +1,497 @@ +/* BEGIN_ICS_COPYRIGHT4 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT4 ****************************************/ + +#include "iba/public/iheapmanager.h" +#include "iba/public/imemory.h" +#include "iba/public/idebug.h" +#include "iba/public/imath.h" +#include "iba/public/itimer.h" + +/* Take size*count from available space at end of heap and put + * on the given free list. + */ +static FSTATUS get_buffer_by_growing(HEAP_MANAGER *heap_mng, + uint32 size, + QUICK_LIST *list, + uint32 count, + uint8 flag) +{ + uint32 i = count; + +#if HEAP_MANAGER_DEBUG + MsgOut("get_buffer_by_growing (%p, %u, %p, %u, %u)[\n", + heap_mng, size, list, count, flag); + MsgOut("available memory: %d Try to grow by: %d\n", + heap_mng->available_memory, size *count); +#endif + + while(i > 0) + { + HEAP_OBJECT *heap_obj; + + if(heap_mng->available_memory < size) + { + DbgOut("ERROR: %s Heap is out of memory\n", heap_mng->name); + return FINSUFFICIENT_RESOURCES; + } + heap_obj = (HEAP_OBJECT *)MemoryAllocateAndClear(sizeof(HEAP_OBJECT), + heap_mng->tag,FALSE); + if(heap_obj == NULL) + { + MsgOut("ERROR: Heap Object allocation error\n"); + return FINSUFFICIENT_MEMORY; + } +#if HEAP_DEBUG + heap_mng->malloc_count++; +#endif + heap_obj->size = size; + heap_obj->offset = heap_mng->cur_offset; + heap_obj->flag = flag; + heap_mng->cur_offset += size; + heap_mng->available_memory -=size; + if(!heap_mng->last_obj) + { + heap_mng->last_obj = heap_obj; + } else { + heap_mng->last_obj->next = heap_obj; + heap_obj->prev = heap_mng->last_obj; + heap_mng->last_obj = heap_obj; + } + QListInsertTail(list, &heap_obj->u.list_item); + QListSetObj(&heap_obj->u.list_item, heap_obj); + i--; + } +#if HEAP_MANAGER_DEBUG + MsgOut("] get_buffer_by_growing\n"); +#endif + return FSUCCESS; +} + +void HeapManagerPrintSummary(HEAP_MANAGER *heap_mng) +{ + uint32 i; + QUICK_LIST *list; + + SpinLockAcquire(&heap_mng->heap_lock); + + MsgOut("Heap Manager: %s\n",heap_mng->name); + MsgOut("Max memory: %u\n",heap_mng->max_memory); + MsgOut("Available memory: %u\n",heap_mng->available_memory); + MsgOut("Current Offset: %u\n",heap_mng->cur_offset); + + for(i = 0;i < 32;i++) + { + list = &heap_mng->bucket_lists[i]; + MsgOut("Free List size: %u count: %u\n",1<heap_lock); +} + +uint32 HeapManagerGetAvailable(HEAP_MANAGER *heap_mng) +{ + uint32 ret; + + SpinLockAcquire(&heap_mng->heap_lock); + ret = heap_mng->available_memory; + SpinLockRelease(&heap_mng->heap_lock); + return ret; +} + +uint32 HeapManagerGetUsed(HEAP_MANAGER *heap_mng) +{ + return heap_mng->max_memory - HeapManagerGetAvailable(heap_mng); +} + +uint32 HeapManagerGetMaxMemory(HEAP_MANAGER *heap_mng) +{ + return heap_mng->max_memory; +} + +void HeapManagerInitState(HEAP_MANAGER *heap_mng) +{ + MemoryClear(heap_mng, sizeof(*heap_mng)); + SpinLockInitState( &heap_mng->heap_lock ); +} + +FSTATUS HeapManagerInit(HEAP_MANAGER *heap_mng, const HEAP_INIT *heap_init, + const char* name, uint32 tag) +{ + unsigned i; + int size = 0,count = 0; + QUICK_LIST *list; + uint32 log2_block_size; + +#if HEAP_MANAGER_DEBUG + MsgOut("HeapManagerInit(%p, %s, %u)[\n", heap_init, name, tag); +#endif + + heap_mng->available_memory = heap_init->max_memory; + heap_mng->max_memory = heap_init->max_memory; + heap_mng->tag = tag; + + strcpy((char*)heap_mng->name,name?name:"Unknown Heap Manager"); + + SpinLockInit(&heap_mng->heap_lock ); + + for(i = 0;i < 32 ;i++) + { + QListInitState( &heap_mng->bucket_lists[i] ); + if( !QListInit( &heap_mng->bucket_lists[i]) ) + { +#if HEAP_MANAGER_DEBUG + MsgOut("ERROR: heap bucket lists init failed : %s: %u\n", name, i); +#endif + return FINVALID_PARAMETER; + } + } + heap_mng->block_size = heap_init->block_size; + heap_mng->water_mark = heap_init->water_mark; + heap_mng->start_addr = heap_init->start_addr; + + log2_block_size = CeilLog2(heap_mng->block_size ); +#if HEAP_DEBUG + heap_mng->malloc_count = 0; +#endif + /* buffer assignment to bucket */ + for(i = 31; i >= log2_block_size; i--) + { + size = 1<buck_init_count[i]; + list = &heap_mng->bucket_lists[i]; + + if(FSUCCESS != get_buffer_by_growing(heap_mng,size,list,count,HEAP_OBJECT_PREALLOCATED)) + { + MsgOut("ERROR: Initial buffer allocation error for heap_manager: %s size: 0x%x\n", + name, size); + } + } + +#if HEAP_MANAGER_DEBUG + MsgOut("] init_heap_manager\n"); +#endif + return FSUCCESS; +} + +void HeapManagerDestroy(HEAP_MANAGER *heap_mng) +{ + int i; + QUICK_LIST *list; + + for (i = 0;i < 32 ;i++) + { + list = &heap_mng->bucket_lists[i] ; + while (QListCount(list)) + { + LIST_ITEM *item = QListRemoveHead(list); + HEAP_OBJECT *heap_obj = (HEAP_OBJECT*)QListObj(item); + ASSERT(item); + ASSERT(heap_obj); + heap_mng->available_memory += heap_obj->size; + MemoryDeallocate(heap_obj); +#if HEAP_DEBUG + heap_mng->malloc_count--; +#endif + } + QListDestroy(list); + } + SpinLockDestroy(&heap_mng->heap_lock); +#if HEAP_DEBUG + MsgOut("heap(%s) malloc_count: %d\n",heap_mng->name,heap_mng->malloc_count); +#endif + if (heap_mng->available_memory != heap_mng->max_memory) + MsgOut("heap(%s) leaked: %u\n", heap_mng->name, + heap_mng->max_memory - heap_mng->available_memory); +} + +/* Get buffer from bigger size queue and split and queue to requested one */ +static FSTATUS HeapManagerSplitBucket(HEAP_MANAGER *heap_mng,uint32 log2_size) +{ + uint32 i,count=0,max_count = 0,max_index = 0; + QUICK_LIST *list,*max_list = NULL; + HEAP_OBJECT *heap_obj = NULL; + HEAP_OBJECT *new_heap_obj = NULL; + LIST_ITEM *item; + +#if HEAP_MANAGER_DEBUG + MsgOut("Out of Free memory for heap(%s), need to rearange\n", + heap_mng->name); +#endif + // split the bucket with the most free + for(i = log2_size;i < 32;i++) + { + QUICK_LIST *list = &heap_mng->bucket_lists[i]; + count = QListCount(list); + if(count > max_count) + { + max_count = count; + max_index = i; + max_list = list; +#if HEAP_MANAGER_DEBUG + MsgOut("Found %u blocks of %u bytes\n", count, 1< 1); + if ( log2_size >= 32 ) { + ASSERT( FALSE ); + return FOVERRUN; + } + list = &heap_mng->bucket_lists[log2_size]; + /* so we can split into count blocks and add to log2_size queue */ + for(i = 0;i< count;i++) + { + new_heap_obj = (HEAP_OBJECT *)MemoryAllocateAndClear( + sizeof(HEAP_OBJECT), heap_mng->tag,FALSE); + if (! new_heap_obj) + { + // unwind + while (i--) + { + new_heap_obj = heap_obj->prev; + ASSERT(new_heap_obj); + heap_obj->prev = new_heap_obj->prev; + QListRemoveItem(list, &new_heap_obj->u.list_item); + MemoryDeallocate(new_heap_obj); +#if HEAP_DEBUG + heap_mng->malloc_count--; +#endif + } + if (heap_obj->prev) + heap_obj->prev->next = heap_obj; + QListInsertTail(max_list, &heap_obj->u.list_item); + QListSetObj(&heap_obj->u.list_item, heap_obj); + MsgOut("ERROR: Heap Object allocation error\n"); + return FINSUFFICIENT_MEMORY; + } +#if HEAP_DEBUG + heap_mng->malloc_count++; +#endif + new_heap_obj->size = 1<offset = heap_obj->offset + (i * new_heap_obj->size); + new_heap_obj->flag = heap_obj->flag; + new_heap_obj->prev = heap_obj->prev; + if (new_heap_obj->prev) + new_heap_obj->prev->next = new_heap_obj; + heap_obj->prev = new_heap_obj; // scratch area while we build list + + QListInsertTail(list, &new_heap_obj->u.list_item); + QListSetObj(&new_heap_obj->u.list_item, new_heap_obj); + } + new_heap_obj->next = heap_obj->next; + if (new_heap_obj->next) + new_heap_obj->next->prev = new_heap_obj; + else + heap_mng->last_obj = new_heap_obj; + + MemoryDeallocate(heap_obj); +#if HEAP_DEBUG + heap_mng->malloc_count--; +#endif + return FSUCCESS; +} + + + +/* allocate buffer from Free List first. + * If failed, then try to grow from free memory pool. + * last option is split from larger buffer on different free list. + */ +HEAP_OBJECT * HeapManagerAllocate(HEAP_MANAGER *heap_mng,uint32 size) +{ + uint32 log2_size = 0; + QUICK_LIST *list = NULL; + HEAP_OBJECT *heap_obj; + LIST_ITEM *item; + +#if HEAP_MANAGER_DEBUG + MsgOut("HeapManagerAllocate(%p, %u) %s [\n",heap_mng,size,heap_mng->name); +#endif + + // round size up to next power of 2 >= block_size for heap + if(size < heap_mng->block_size) + size = heap_mng->block_size; + log2_size = CeilLog2(size); + if ( log2_size >= 32 ) { + ASSERT( FALSE ); + return NULL; + } + size = 1<< log2_size; + list = &heap_mng->bucket_lists[log2_size]; + + SpinLockAcquire(&heap_mng->heap_lock); + if( QListCount(list) ) + { + item = QListRemoveHead(list); + } else if(FSUCCESS == get_buffer_by_growing(heap_mng,size,list,1,0)) { + item = QListRemoveHead(list); + } else if(FSUCCESS == HeapManagerSplitBucket(heap_mng,log2_size)) { + item = QListRemoveHead(list); + } else { + uint32 timestamp = GetTimeStampSec(); + if (heap_mng->last_error_time == 0 + || (timestamp - heap_mng->last_error_time) > HEAP_ERROR_RATE_LIMIT) + { + heap_mng->last_error_time = timestamp; + SpinLockRelease(&heap_mng->heap_lock); + MsgOut("ERROR: Heap(%s) malloc failed\n", heap_mng->name); + } else { + SpinLockRelease(&heap_mng->heap_lock); + } + return NULL; + } + ASSERT(item); + heap_obj = (HEAP_OBJECT *)QListObj(item); + ASSERT(heap_obj); +#if HEAP_MANAGER_DEBUG + MsgOut("Heap_Obj(%p): %u from Free List, remaining count: %u\n", + heap_obj, heap_obj->size, QListCount(list) ); +#endif + heap_obj->flag |= (uint8)HEAP_OBJECT_IN_USE; + SpinLockRelease(&heap_mng->heap_lock); +#if HEAP_DEBUG + MsgOut("HeapManagerAllocate: head(%s) size(%d) done\n", + heap_mng->name,(int)size); +#endif + heap_obj->u.info.addr = heap_mng->start_addr + heap_obj->offset; + AtomicWrite(&heap_obj->u.info.refcount, 1); +#if HEAP_MANAGER_DEBUG + MsgOut("] HeapManagerAllocate\n"); +#endif + return heap_obj; +} + +void HeapManagerIncRefCount(HEAP_MANAGER *heap_mng,HEAP_OBJECT *heap_obj) +{ + ASSERT(heap_obj); + AtomicIncrementVoid(&heap_obj->u.info.refcount); +} + +void HeapManagerDecRefCount(HEAP_MANAGER *heap_mng,HEAP_OBJECT *heap_obj) +{ + ASSERT(heap_obj); + AtomicDecrementVoid(&heap_obj->u.info.refcount); +} + +FSTATUS HeapManagerDeallocate(HEAP_MANAGER *heap_mng,HEAP_OBJECT *heap_obj) +{ + uint32 log2_size = 0; + QUICK_LIST *list = NULL; + +#if HEAP_MANAGER_DEBUG + MsgOut("HeapManagerDeallocate (%p, %p) [\n", heap_mng, heap_obj); +#endif + + SpinLockAcquire(&heap_mng->heap_lock); + if (AtomicRead(&heap_obj->u.info.refcount) != 1) + { + MsgOut("ERROR: heap_obj(%p) refcount count(%u) is not zero\n",heap_obj, + AtomicRead(&heap_obj->u.info.refcount) - 1); + SpinLockRelease(&heap_mng->heap_lock); +#if HEAP_MANAGER_DEBUG + MsgOut("] HeapManagerDeallocate\n"); +#endif + return FBUSY; + } + ASSERT(heap_obj->flag & HEAP_OBJECT_IN_USE); + heap_obj->flag &= ~HEAP_OBJECT_IN_USE; + + /* add back to free list */ + log2_size = CeilLog2(heap_obj->size); + if ( log2_size >= 32 ) { + ASSERT( FALSE ); + return FOVERRUN; + } + list = &heap_mng->bucket_lists[log2_size]; + QListInsertTail(list, &heap_obj->u.list_item); + QListSetObj(&heap_obj->u.list_item, heap_obj); +#if HEAP_DEBUG + MsgOut("Put Heap_Obj(%p): %d back to queue\n",heap_obj, heap_obj->size); +#endif + + /* see if we can shink the pool */ + if(heap_obj->next == NULL && ! (heap_obj->flag & HEAP_OBJECT_PREALLOCATED)) + { + ASSERT(heap_mng->last_obj == heap_obj); + while (NULL != (heap_obj = heap_mng->last_obj) + && ! (heap_obj->flag & (HEAP_OBJECT_PREALLOCATED|HEAP_OBJECT_IN_USE))) + { + heap_mng->cur_offset -= heap_obj->size; + heap_mng->available_memory += heap_obj->size; + log2_size = CeilLog2(heap_obj->size); + if ( log2_size >= 32 ) { + ASSERT( FALSE ); + return FOVERRUN; + } + list = &heap_mng->bucket_lists[log2_size]; + QListRemoveItem(list, &heap_obj->u.list_item); + heap_mng->last_obj = heap_obj->prev; + if(heap_obj->prev) + heap_obj->prev->next = NULL; +#if HEAP_DEBUG + heap_mng->malloc_count--; + MsgOut("Heap_OBJ: %p freed cur_offset: %d available memory: %d\n",heap_obj,heap_mng->cur_offset, + heap_mng->available_memory); +#endif + MemoryDeallocate(heap_obj); + } + } + + SpinLockRelease(&heap_mng->heap_lock); + +#if HEAP_MANAGER_DEBUG + MsgOut("] HeapManagerDeallocate\n"); +#endif + return FSUCCESS; +} + +void HeapManagerRelease(HEAP_MANAGER *heap_mng,HEAP_OBJECT *heap_obj) +{ +#if HEAP_MANAGER_DEBUG + MsgOut("HeapManagerRelease (%p, %p) [\n", heap_mng, heap_obj); +#endif + + if (AtomicRead(&heap_obj->u.info.refcount) == 1) + { + HeapManagerDeallocate(heap_mng,heap_obj); + } else { + AtomicDecrementVoid(&heap_obj->u.info.refcount); + } +#if HEAP_MANAGER_DEBUG + MsgOut("] HeapManagerRelease\n"); +#endif +} diff --git a/IbAccess/Common/Public/iheapmanager.h b/IbAccess/Common/Public/iheapmanager.h new file mode 100644 index 0000000..603e593 --- /dev/null +++ b/IbAccess/Common/Public/iheapmanager.h @@ -0,0 +1,148 @@ +/* BEGIN_ICS_COPYRIGHT3 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT3 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +#ifndef _IBA_PUBLIC_IHEAP_MANAGER_H +#define _IBA_PUBLIC_IHEAP_MANAGER_H + +#include "iba/public/datatypes.h" +#include "iba/public/ispinlock.h" +#include "iba/public/ilist.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +/* A simple heap is implemented + * This can be given a range of addresses to manage, such as HFI local memory + * and will provide allocate and free functions against that memory + * No pointers are maintained in the memory managed by the heap itself + * This means the memory can be in a slower access location, such as across + * PCI without impacting the performance of these functions + */ + +#define HEAP_DEBUG 0 /* set to 1 to enable heap debugging */ +#define HEAP_MANAGER_DEBUG 0 /* set to 1 to enable heap manager logging */ + +/* HEAP_OBJECT flags */ +#define HEAP_OBJECT_PREALLOCATED 1 /* part of initial sizing, don't release */ +#define HEAP_OBJECT_IN_USE 2 + +#define HEAP_ERROR_RATE_LIMIT (10*60)/* report malloc errors no faster than this */ + +typedef struct _HEAP_OBJECT +{ + union { + LIST_ITEM list_item; /* for internal use, bucket_lists */ + struct { /* valid only when allocated */ + uint64 addr; /* heap start + offset */ + ATOMIC_UINT refcount; /* refcount for shared memory */ + } info; + } u; + uint8 flag; /* HEAP_OBJECT flags above */ + uint32 size; /* actual size in bytes */ + uint32 offset; /* offset from heap start address */ + /* these lists track all blocks */ + struct _HEAP_OBJECT *prev; /* for internal use, links for buddies */ + struct _HEAP_OBJECT *next; /* for internal use, links for buddies */ +} HEAP_OBJECT; + +typedef struct _HEAP_MANAGER +{ + uint32 available_memory; /* unassigned memory at end of heap */ + uint32 max_memory; /* total size of heap */ + uint64 start_addr; /* physical start address of memory */ + uint32 cur_offset; /* offset of 1st unassigned memory */ + SPIN_LOCK heap_lock; + QUICK_LIST bucket_lists[32]; /* free memory chunck in power of 2 order*/ + uint32 block_size; /* smallest block size in bytes */ + uint32 water_mark; /* not used yet */ + uint32 tag; + HEAP_OBJECT *heap_object; + const char name[100]; + HEAP_OBJECT *last_obj; /* all blocks */ + uint32 last_error_time; /* timestamp when last error reported */ +#if HEAP_DEBUG + uint32 malloc_count; +#endif +} HEAP_MANAGER; + +typedef struct _HEAP_INIT +{ + uint64 start_addr; /* initial address of heap */ + uint32 block_size; /* size of blocks */ + uint32 buck_init_count[32]; /* count of initial assignment of + * buffers to each bucket + */ + uint32 max_memory; /* should be power of 2 */ + uint32 water_mark; /* Minimal amount memory before + * rearange from bucket + */ +} HEAP_INIT; + +static __inline void HeapManagerIncBucketInit(HEAP_INIT *heap_init, + uint32 log2_size) +{ + heap_init->buck_init_count[log2_size]++; +} + +void HeapManagerInitState(HEAP_MANAGER *heap_mng); +FSTATUS HeapManagerInit(HEAP_MANAGER* heap_mng, const HEAP_INIT *heap_init, + const char* name, uint32 tag); +void HeapManagerDestroy(HEAP_MANAGER *heap_mng); +HEAP_OBJECT * HeapManagerAllocate(HEAP_MANAGER *heap_mng, uint32 size); +FSTATUS HeapManagerDeallocate(HEAP_MANAGER *heap_mng, HEAP_OBJECT *heap_obj); +void HeapManagerRelease(HEAP_MANAGER *heap_mng, HEAP_OBJECT *heap_obj); + +void HeapManagerPrintSummary(HEAP_MANAGER *heap_mng); +uint32 HeapManagerGetAvailable(HEAP_MANAGER *heap_mng); +uint32 HeapManagerGetUsed(HEAP_MANAGER *heap_mng); +uint32 HeapManagerGetMaxMemory(HEAP_MANAGER *heap_mng); + +void HeapManagerIncRefCount(HEAP_MANAGER *heap_mng, HEAP_OBJECT *heap_obj); +void HeapManagerDecRefCount(HEAP_MANAGER *heap_mng, HEAP_OBJECT *heap_obj); +static __inline uint32 HeapManagerGetRefCount(HEAP_OBJECT *heap_obj) +{ + return AtomicRead(&heap_obj->u.info.refcount); +} +static __inline uint64 HeapManagerGetAddr(HEAP_OBJECT *heap_obj) +{ + return heap_obj->u.info.addr; +} +static __inline uint32 HeapManagerGetSize(HEAP_OBJECT *heap_obj) +{ + return heap_obj->size; +} + +#if defined(__cplusplus) +} +#endif + +#endif /* _IBA_PUBLIC_IHEAP_MANAGER_H */ diff --git a/IbAccess/Common/Public/iintrservicethread.h b/IbAccess/Common/Public/iintrservicethread.h new file mode 100644 index 0000000..25ed66d --- /dev/null +++ b/IbAccess/Common/Public/iintrservicethread.h @@ -0,0 +1,89 @@ +/* BEGIN_ICS_COPYRIGHT3 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT3 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + + +#ifndef _IINTR_SERVICE_THREAD_H_ +#define _IINTR_SERVICE_THREAD_H_ + +#include "iba/public/ithread.h" +#include "iba/public/ipci.h" +#include "iba/public/iintrservicethread_osd.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Interrupt Service Thread. + * This allows the "slower" part of servicing of an interrupt to be + * done in a higher level task. On most OS's this is still a restricted + * task which cannot sleep/wait or otherwise preempt itself + * + * Each instance could potentially be a separate thread, hence allowing + * concurrent processing of different types of Interrupts without having + * serious interrupts need to queue behind less severe interrupts. + * + * The interrupt handler should manage the low level hardware registers + * to identify the cause of the interrupt then Signal the appropriate + * IntrServiceThread. The interrupt can then return (releasing the interrupt + * lockout) and the IntrServiceThread callback will be run in a higher level + * context to complete the processing of the interrupt. + */ + +void +IntrServiceThreadInitState( + IN INTR_SERVICE_THREAD *pIntrServiceThread ); + +boolean +IntrServiceThreadCreate( + IN INTR_SERVICE_THREAD *pIntrServiceThread, + IN PCI_DEVICE *pDev, + IN char* Name, + IN THREAD_CALLBACK Callback, + IN void *Context ); + +/* Destroy must be called at passive level. */ +void +IntrServiceThreadDestroy( + IN INTR_SERVICE_THREAD *pIntrServiceThread ); + +/* This is Interrupt callable, it will run the callback on the + * Interrupt Service Thread + */ +static _inline void +IntrServiceThreadSignal( + IN INTR_SERVICE_THREAD *pIntrServiceThread ); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* _IINTR_SERVICE_THREAD_H_ */ diff --git a/IbAccess/Common/Public/ilist.c b/IbAccess/Common/Public/ilist.c new file mode 100644 index 0000000..8236759 --- /dev/null +++ b/IbAccess/Common/Public/ilist.c @@ -0,0 +1,1880 @@ +/* BEGIN_ICS_COPYRIGHT6 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT6 ****************************************/ + +/* NOTE: In order to support conditional inlining of ilist functions, + * the DEFINE_ILIST_FUNCS macro is defined *prior* to including the + * ilist.h header file. This file is the *only* source file that should + * be including ilist.h with the DEFINE_ILIST_FUNCS macro enabled. + */ +#define DEFINE_ILIST_FUNCS 1 + +#include "ilist.h" +#include "iobjmgr.h" +#include "imemory.h" + +#define FREE_ITEM_GROW_SIZE 10 + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +////////////// //////////// +////////////// IMPLEMENTATION OF QUICK_LIST //////////// +////////////// //////////// +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// + + +/////////////////////////////////////////////////////////////////////////////// +// QListInitState +// +// Description: +// This function initializes the state of the quicklist. +// This function cannot fail. +// +// Inputs: +// pQuickList - Pointer to quicklist object +// +// Outputs: +// None. +// +// Returns: +// None. +// +/////////////////////////////////////////////////////////////////////////////// +void +QListInitState( + IN QUICK_LIST* const pQuickList ) +{ + ASSERT( pQuickList ); + // a no-op - destroy can always be called +} + + +/////////////////////////////////////////////////////////////////////////////// +// QListInit +// +// Description: +// This function initializes the quicklist. +// +// Inputs: +// pQuickList - Pointer to quicklist object +// +// Outputs: +// None. +// +// Returns: +// TRUE on success +// FALSE otherwise +// +/////////////////////////////////////////////////////////////////////////////// +boolean +QListInit( + IN QUICK_LIST* const pQuickList ) +{ + ASSERT( pQuickList ); + + // Initialize the quick list data structure. + QListRemoveAll( pQuickList ); + return TRUE; +} + + +/////////////////////////////////////////////////////////////////////////////// +// QListDestroy +// +// Description: +// Destroys a list, discards any items on the list but does not free them +// +// Inputs: +// pQuickList - Pointer to quicklist object +// +// Outputs: +// None +// +// Returns: +// None +// +/////////////////////////////////////////////////////////////////////////////// +void +QListDestroy( + IN QUICK_LIST* const pQuickList ) +{ + ASSERT( pQuickList ); + // Remove all elements from the list. + QListRemoveAll( pQuickList ); +} + + +/////////////////////////////////////////////////////////////////////////////// +// QListIsItemInList +// +// Description: +// Return true if the specified item is in the list +// +// Inputs: +// pQuickList - Pointer to quicklist object +// pListItem - Pointer to the LIST_ITEM to find +// +// Outputs: +// None +// +// Returns: +// None +// +/////////////////////////////////////////////////////////////////////////////// +boolean +QListIsItemInList( + IN const QUICK_LIST* const pQuickList, + IN const LIST_ITEM* const pListItem ) +{ + const LIST_ITEM* pTemp; + + ASSERT( pQuickList && pListItem ); + + // Traverse looking for a match + pTemp = QListHead( pQuickList ); + while( pTemp ) + { + if( pTemp == pListItem ) + return( TRUE ); + + pTemp = QListNext( pQuickList, pTemp ); + } + + return( FALSE ); +} + + +/////////////////////////////////////////////////////////////////////////////// +// QListAllocateAndInit +// +// Description: +// This function allocates memory for and initializes the state of the +// quicklist. +// +// Inputs: +// IsPageable - +// Tag - +// +// Outputs: +// None. +// +// Returns: +// NULL on error, otherwise pointer to a ready to use List +// +/////////////////////////////////////////////////////////////////////////////// +QUICK_LIST* +QListAllocateAndInit( + IN boolean IsPageable, + IN uint32 Tag ) +{ + QUICK_LIST *pQuickList; + + pQuickList = (QUICK_LIST*)MemoryAllocateAndClear(sizeof(QUICK_LIST), + IsPageable, Tag); + if (pQuickList != NULL) + { + QListInitState(pQuickList); + if (! QListInit(pQuickList)) + { + MemoryDeallocate(pQuickList); + pQuickList = NULL; + } + } + return pQuickList; +} + +/////////////////////////////////////////////////////////////////////////////// +// QListDeallocate +// +// Description: +// This function destroys the list and deallocates memory for the +// quicklist. +// It does not free items which were on the list +// +// Inputs: +// pQuickList - Pointer to quicklist object allocated by QListAllocateAndInit +// if NULL, this function does nothing +// +// Outputs: +// None. +// +// Returns: +// +/////////////////////////////////////////////////////////////////////////////// +void +QListDeallocate( + IN QUICK_LIST* const pQuickList ) +{ + if (pQuickList) + { + QListDestroy(pQuickList); + MemoryDeallocate(pQuickList); + } +} + +/////////////////////////////////////////////////////////////////////////////// +// QListRemoveAll +// +// Description: +// Removes all items in the specified list. +// +// Inputs: +// pQuickList - Pointer to quicklist object +// +// Outputs: +// None +// +// Returns: +// None +// +/////////////////////////////////////////////////////////////////////////////// +void +QListRemoveAll( + IN QUICK_LIST* const pQuickList ) +{ + ASSERT( pQuickList ); + + // Clean up the pointers to indicate that the list is empty. + pQuickList->m_Head.pNextItem = &pQuickList->m_Head; + pQuickList->m_Head.pPrevItem = &pQuickList->m_Head; + pQuickList->m_Count = 0; +} + + +/////////////////////////////////////////////////////////////////////////////// +// QListInsertArrayHead +// +// Description: +// Insert an array of items to the head of a list. The array pointer passed +// into the function points to the LIST_ITEM in the first element of the +// caller's element array. There is no restriction on where the element is +// stored in the parent structure. +// +// Inputs: +// pQuickList - Pointer to quicklist object. +// pArray - Pointer to LIST_ITEM of first element in array to add. +// ItemCount - number of items to add from the array. +// ItemSize - size of each item in the array. This is the offset from +// LIST_ITEM to LIST_ITEM. +// +// Outputs: +// None +// +// Returns: +// None +// +/////////////////////////////////////////////////////////////////////////////// +void +QListInsertArrayHead( + IN QUICK_LIST* const pQuickList, + IN LIST_ITEM* const pArray, + IN uint32 ItemCount, + IN const uint32 ItemSize ) +{ + LIST_ITEM *pItem; + + ASSERT( pArray ); + ASSERT( ItemSize ); + ASSERT( ItemCount ); + + // To add items from the array to the list in the same order as + // the elements appear in the array, we add them starting with + // the last one first. Locate the last item. + pItem = (LIST_ITEM*)((uint8 *)pArray + (ItemSize * (ItemCount - 1))); + + // Continue to add all items to the list. + while( ItemCount-- ) + { + QListInsertHead( pQuickList, pItem ); + + // Get the next object to add to the list. + pItem = (LIST_ITEM*)((uint8 *)pItem - ItemSize); + } +} + + +/////////////////////////////////////////////////////////////////////////////// +// QListInsertArrayTail +// +// Description: +// Insert an array of items to the tail of a list. The array pointer passed +// into the function points to the LIST_ITEM in the first element of the +// caller's element array. There is no restriction on where the element is +// stored in the parent structure. +// +// Inputs: +// pQuickList - Pointer to quicklist object. +// pArray - Pointer to LIST_ITEM of first element in array to add. +// ItemCount - number of items to add from the array. +// ItemSize - size of each item in the array. This is the offset from +// LIST_ITEM to LIST_ITEM. +// +// Outputs: +// None +// +// Returns: +// None +// +/////////////////////////////////////////////////////////////////////////////// +void +QListInsertArrayTail( + IN QUICK_LIST* const pQuickList, + IN LIST_ITEM* const pArray, + IN uint32 ItemCount, + IN const uint32 ItemSize ) +{ + LIST_ITEM *pItem; + + ASSERT( pArray && ItemSize && ItemCount ); + + // Set the first item to add to the list. + pItem = pArray; + + // Continue to add all items to the list. + while ( ItemCount-- ) + { + QListInsertTail( pQuickList, pItem ); + + // Get the next object to add to the list. + pItem = (LIST_ITEM*)((uint8*)pItem + ItemSize); + } +} + + +/////////////////////////////////////////////////////////////////////////////// +// QListInsertListHead +// +// Description: +// Add the items in a list to the head of another list. +// +// Inputs: +// pDestList - Pointer to destination quicklist object. +// pSrcList - Pointer to quicklist to add. +// +// Outputs: +// None +// +// Returns: +// None +// +/////////////////////////////////////////////////////////////////////////////// +void +QListInsertListHead( + IN QUICK_LIST* const pDestList, + IN QUICK_LIST* const pSrcList ) +{ + ASSERT( pDestList ); + ASSERT( pSrcList ); + + // Is the src list empty? + // We must have this check here for code below to work. + if( QListIsEmpty( pSrcList ) ) + return; + + // Chain the destination list to the tail of the source list. + pSrcList->m_Head.pPrevItem->pNextItem = pDestList->m_Head.pNextItem; + pDestList->m_Head.pNextItem->pPrevItem = pSrcList->m_Head.pPrevItem; + + // Update the head of the destination list to the head of the source list. + pDestList->m_Head.pNextItem = pSrcList->m_Head.pNextItem; + pDestList->m_Head.pNextItem->pPrevItem = &pDestList->m_Head; + + // Adjust the count. + pDestList->m_Count += pSrcList->m_Count; + + // Update source list to reflect being empty. + QListRemoveAll( pSrcList ); +} + + +/////////////////////////////////////////////////////////////////////////////// +// QListInsertListTail +// +// Description: +// Add the items in a list to the tail of another list. +// +// Inputs: +// pDestList - Pointer to destination quicklist object +// pSrcList - Pointer to quicklist to add +// +// Outputs: +// None +// +// Returns: +// None +// +/////////////////////////////////////////////////////////////////////////////// +void +QListInsertListTail( + IN QUICK_LIST* const pDestList, + IN QUICK_LIST* const pSrcList ) +{ + ASSERT( pDestList ); + ASSERT( pSrcList ); + + // Is the src list empty? + // We must have this check here for code below to work. + if( QListIsEmpty( pSrcList ) ) + return; + + // Chain the source list to the tail of the destination list. + pDestList->m_Head.pPrevItem->pNextItem = pSrcList->m_Head.pNextItem; + pSrcList->m_Head.pNextItem->pPrevItem = pDestList->m_Head.pPrevItem; + + // Update the tail of the destination list to the tail of the source list. + pDestList->m_Head.pPrevItem = pSrcList->m_Head.pPrevItem; + pDestList->m_Head.pPrevItem->pNextItem = &pDestList->m_Head; + + // Bump the count. + pDestList->m_Count += pSrcList->m_Count; + + // Update source list to reflect being empty. + QListRemoveAll( pSrcList ); +} + + +/////////////////////////////////////////////////////////////////////////////// +// QListGetItemAt (OBSOLETE - DO NOT USE) +// +// Description: +// Return the item at the specified offset into the list. 0 is the first item. +// +// Inputs: +// pQuickList - Pointer to quicklist object +// Index - offset into list of item to return +// +// Outputs: +// None +// +// Returns: +// LIST_ITEM at specified index +// NULL if item doesn't exist in the list +// +/////////////////////////////////////////////////////////////////////////////// +LIST_ITEM* +QListGetItemAt( + IN const QUICK_LIST* const pQuickList, + IN uint32 Index ) +{ + LIST_ITEM *pTemp; + + ASSERT( pQuickList ); + + if( pQuickList->m_Count <= Index ) + return( NULL ); + + // start at the front + pTemp = QListHead( pQuickList ); + + // if index is 0, we never enter the loop + while( Index-- && pTemp ) + pTemp = QListNext( pQuickList, pTemp ); + + return( pTemp ); +} + + +/////////////////////////////////////////////////////////////////////////////// +// QListFindFromHead +// +// Description: +// Use the specified function to search for an item starting at the head of +// a list. Returns the item if found, otherwise NULL. If the user does not +// provide a compare function, then the pObject pointer in each LIST_ITEM is +// compared with the specified Context. +// +// Inputs: +// pQuickList - Pointer to quicklist object +// pfnFunc - User supplied compare function +// Context - Context for compare function, or compare value if pfnFunc +// is NULL. +// +// Outputs: +// None +// +// Returns: +// Pointer to LIST_ITEM if found. +// NULL otherwise +// +/////////////////////////////////////////////////////////////////////////////// +LIST_ITEM* +QListFindFromHead( + IN const QUICK_LIST* const pQuickList, + IN QLIST_FIND_FUNC pfnFunc OPTIONAL, + IN void* const Context ) +{ + LIST_ITEM *pListItem; + + ASSERT( pQuickList ); + + pListItem = QListHead( pQuickList ); + + if( pfnFunc ) + { + // The user provided a compare function + while( pListItem ) + { + if( pfnFunc( pListItem, Context ) ) + return( pListItem ); + pListItem = QListNext( pQuickList, pListItem ); + } + } + else + { + // The user didn't give us a compare function + // Just compare context with the object pointer + while( pListItem ) + { + if( pListItem->pObject == Context ) + return( pListItem ); + pListItem = QListNext( pQuickList, pListItem ); + } + } + + // No match + return( NULL ); +} + + +/////////////////////////////////////////////////////////////////////////////// +// QListFindFromTail +// +// Description: +// Use the specified function to search for an item starting at the tail of +// a list. Returns the item if found, otherwise NULL. If the user does not +// provide a compare function, then the pObject pointer in each LIST_ITEM is +// compared with the specified Context. +// +// Inputs: +// pQuickList - Pointer to quicklist object +// pfnFunc - User supplied compare function +// Context - Context for compare function, or compare value if pfnFunc +// is NULL. +// +// Outputs: +// None +// +// Returns: +// Pointer to LIST_ITEM if found. +// NULL otherwise +// +/////////////////////////////////////////////////////////////////////////////// +LIST_ITEM* +QListFindFromTail( + IN const QUICK_LIST* const pQuickList, + IN QLIST_FIND_FUNC pfnFunc OPTIONAL, + IN void* const Context ) +{ + LIST_ITEM *pListItem; + + ASSERT( pQuickList ); + + pListItem = QListTail( pQuickList ); + + if( pfnFunc ) + { + // The user provided a compare function + while( pListItem ) + { + if( pfnFunc( pListItem, Context ) ) + return( pListItem ); + pListItem = QListPrev( pQuickList, pListItem ); + } + } + else + { + // The user didn't give us a compare function + // Just compare context with the object pointer + while( pListItem ) + { + if( pListItem->pObject == Context ) + return( pListItem ); + pListItem = QListPrev( pQuickList, pListItem ); + } + } + + // No match + return( NULL ); +} + + +/////////////////////////////////////////////////////////////////////////////// +// QListApplyFunc +// +// Description: +// Call the specified function for each item in the list. +// +// Inputs: +// pQuickList - Pointer to quicklist object +// pfnFunc - User supplied function +// Context - Context for function +// +// Outputs: +// None +// +// Returns: +// None +// +/////////////////////////////////////////////////////////////////////////////// +void +QListApplyFunc( + IN const QUICK_LIST* const pQuickList, + IN QLIST_APPLY_FUNC pfnFunc, + IN void* const Context ) +{ + LIST_ITEM* pListItem; + + // Note that context can have any arbitrary value. + ASSERT( pQuickList ); + ASSERT( pfnFunc ); + + pListItem = QListHead( pQuickList ); + while( pListItem ) + { + pfnFunc( pListItem, Context ); + pListItem = QListNext( pQuickList, pListItem ); + } +} + + +/////////////////////////////////////////////////////////////////////////////// +// QListMoveItems +// +// Description: +// Move items from one list to another based on a user supplied function. +// Items are moved if Func() returns true. +// Items are moved to the tail of the destination list. +// +// Inputs: +// pSrcList - Pointer to source quicklist object +// pDestList - Pointer to destination quicklist object +// pfnFunc - User supplied function, returns true to move an item +// Context - Context for function +// +// Outputs: +// None +// +// Returns: +// None +// +/////////////////////////////////////////////////////////////////////////////// +void +QListMoveItems( + IN QUICK_LIST* const pSrcList, + IN QUICK_LIST* const pDestList, + IN QLIST_FIND_FUNC pfnFunc, + IN void* const Context ) +{ + LIST_ITEM *pCurrentItem, *pNextItem; + + ASSERT( pSrcList ); + ASSERT( pDestList ); + ASSERT( pfnFunc ); + + pCurrentItem = QListHead( pSrcList ); + + while( pCurrentItem ) + { + // Before we do anything, get a pointer to the next item. + pNextItem = QListNext( pSrcList, pCurrentItem ); + + if( pfnFunc( pCurrentItem, Context ) ) + { + // Move the item from one list to the other. + QListRemoveItem( pSrcList, pCurrentItem ); + QListInsertTail( pDestList, pCurrentItem ); + } + pCurrentItem = pNextItem; + } +} + + + + + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +////////////// //////////// +////////////// IMPLEMENTATION OF LOCKED_QUICK_LIST //////////// +////////////// //////////// +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// + + +/////////////////////////////////////////////////////////////////////////////// +// LQListInitState +// +// Description: +// This function initializes the state of the locked quicklist. +// This function cannot fail. +// +// Inputs: +// pLQuickList - Pointer to locked quicklist object +// +// Outputs: +// None. +// +// Returns: +// None. +// +/////////////////////////////////////////////////////////////////////////////// +void +LQListInitState( + IN LOCKED_QUICK_LIST* const pLQuickList ) +{ + ASSERT( pLQuickList ); + SpinLockInitState(&pLQuickList->m_Lock); + QListInitState(&pLQuickList->m_List); +} + + +/////////////////////////////////////////////////////////////////////////////// +// LQListInit +// +// Description: +// This function initializes the locked quicklist. +// +// Inputs: +// pLQuickList - Pointer to locked quicklist object +// +// Outputs: +// None. +// +// Returns: +// TRUE on success +// FALSE otherwise +// +/////////////////////////////////////////////////////////////////////////////// +boolean +LQListInit( + IN LOCKED_QUICK_LIST* const pLQuickList ) +{ + boolean result; + ASSERT( pLQuickList ); + + if (! SpinLockInit(&pLQuickList->m_Lock)) + { + return FALSE; + } + result = QListInit(&pLQuickList->m_List); + if (! result) + { + SpinLockDestroy(&pLQuickList->m_Lock); + } + return result; +} + + +/////////////////////////////////////////////////////////////////////////////// +// LQListDestroy +// +// Description: +// Destroys a locked list, discards any items on it (but does not free them) +// The lock associated with the list is also destroyed. +// +// Inputs: +// pLQuickList - Pointer to locked quicklist object +// +// Outputs: +// None +// +// Returns: +// None +// +/////////////////////////////////////////////////////////////////////////////// +void +LQListDestroy( + IN LOCKED_QUICK_LIST* const pLQuickList ) +{ + ASSERT( pLQuickList ); + QListDestroy(&pLQuickList->m_List); + SpinLockDestroy(&pLQuickList->m_Lock); +} + + +/////////////////////////////////////////////////////////////////////////////// +// LQListIsItemInList +// +// Description: +// Return true if the specified item is in the list +// +// Inputs: +// pLQuickList - Pointer to locked quicklist object +// pListItem - Pointer to the LIST_ITEM to find +// +// Outputs: +// None +// +// Returns: +// None +// +/////////////////////////////////////////////////////////////////////////////// +boolean +LQListIsItemInList( + IN LOCKED_QUICK_LIST* const pLQuickList, + IN const LIST_ITEM* const pListItem ) +{ + boolean result; + + ASSERT( pLQuickList && pListItem ); + SpinLockAcquire(&pLQuickList->m_Lock); + result = QListIsItemInList(&pLQuickList->m_List, pListItem); + SpinLockRelease(&pLQuickList->m_Lock); + return result; +} + + +/////////////////////////////////////////////////////////////////////////////// +// LQListAllocateAndInit +// +// Description: +// This function allocates memory for and initializes the state of the +// quicklist. +// +// Inputs: +// IsPageable - +// Tag - +// +// Outputs: +// None. +// +// Returns: +// NULL on error, otherwise pointer to a ready to use List +// +/////////////////////////////////////////////////////////////////////////////// +LOCKED_QUICK_LIST* +LQListAllocateAndInit( + IN boolean IsPageable, + IN uint32 Tag ) +{ + LOCKED_QUICK_LIST *pLQuickList; + + pLQuickList = (LOCKED_QUICK_LIST*)MemoryAllocateAndClear( + sizeof(LOCKED_QUICK_LIST), IsPageable, Tag); + if (pLQuickList != NULL) + { + LQListInitState(pLQuickList); + if (! LQListInit(pLQuickList)) + { + MemoryDeallocate(pLQuickList); + pLQuickList = NULL; + } + } + return pLQuickList; +} + +/////////////////////////////////////////////////////////////////////////////// +// LQListDeallocate +// +// Description: +// This function destroys the list and deallocates memory for the +// quicklist. +// It does not free items which were on the list +// +// Inputs: +// pLQuickList - Pointer to quicklist object allocated by LQListAllocateAndInit +// if NULL, this function does nothing +// +// Outputs: +// None. +// +// Returns: +// +/////////////////////////////////////////////////////////////////////////////// +void +LQListDeallocate( + IN LOCKED_QUICK_LIST* const pLQuickList ) +{ + if (pLQuickList) + { + LQListDestroy(pLQuickList); + MemoryDeallocate(pLQuickList); + } +} + +/////////////////////////////////////////////////////////////////////////////// +// LQListRemoveAll +// +// Description: +// Removes all items in the specified list. +// +// Inputs: +// pLQuickList - Pointer to locked quicklist object +// +// Outputs: +// None +// +// Returns: +// None +// +/////////////////////////////////////////////////////////////////////////////// +void +LQListRemoveAll( + IN LOCKED_QUICK_LIST* const pLQuickList ) +{ + ASSERT( pLQuickList ); + SpinLockAcquire(&pLQuickList->m_Lock); + QListRemoveAll(&pLQuickList->m_List); + SpinLockRelease(&pLQuickList->m_Lock); +} + + +/////////////////////////////////////////////////////////////////////////////// +// LQListInsertArrayHead +// +// Description: +// Insert an array of items to the head of a list. The array pointer passed +// into the function points to the LIST_ITEM in the first element of the +// caller's element array. There is no restriction on where the element is +// stored in the parent structure. +// +// Inputs: +// pLQuickList - Pointer to locked quicklist object. +// pArray - Pointer to LIST_ITEM of first element in array to add. +// ItemCount - number of items to add from the array. +// ItemSize - size of each item in the array. This is the offset from +// LIST_ITEM to LIST_ITEM. +// +// Outputs: +// None +// +// Returns: +// None +// +/////////////////////////////////////////////////////////////////////////////// +void +LQListInsertArrayHead( + IN LOCKED_QUICK_LIST* const pLQuickList, + IN LIST_ITEM* const pArray, + IN uint32 ItemCount, + IN const uint32 ItemSize ) +{ + ASSERT( pLQuickList ); + SpinLockAcquire(&pLQuickList->m_Lock); + QListInsertArrayHead(&pLQuickList->m_List, pArray, ItemCount, ItemSize); + SpinLockRelease(&pLQuickList->m_Lock); +} + + +/////////////////////////////////////////////////////////////////////////////// +// LQListInsertArrayTail +// +// Description: +// Insert an array of items to the tail of a list. The array pointer passed +// into the function points to the LIST_ITEM in the first element of the +// caller's element array. There is no restriction on where the element is +// stored in the parent structure. +// +// Inputs: +// pLQuickList - Pointer to locked quicklist object. +// pArray - Pointer to LIST_ITEM of first element in array to add. +// ItemCount - number of items to add from the array. +// ItemSize - size of each item in the array. This is the offset from +// LIST_ITEM to LIST_ITEM. +// +// Outputs: +// None +// +// Returns: +// None +// +/////////////////////////////////////////////////////////////////////////////// +void +LQListInsertArrayTail( + IN LOCKED_QUICK_LIST* const pLQuickList, + IN LIST_ITEM* const pArray, + IN uint32 ItemCount, + IN const uint32 ItemSize ) +{ + ASSERT( pLQuickList); + SpinLockAcquire(&pLQuickList->m_Lock); + QListInsertArrayTail(&pLQuickList->m_List, pArray, ItemCount, ItemSize); + SpinLockRelease(&pLQuickList->m_Lock); +} + + +/////////////////////////////////////////////////////////////////////////////// +// LQListInsertListHead +// +// Description: +// Add the items in a list to the head of another list. +// +// Inputs: +// pDestList - Pointer to destination locked quicklist object. +// pSrcList - Pointer to locked quicklist to add. +// +// Outputs: +// None +// +// Returns: +// None +// +/////////////////////////////////////////////////////////////////////////////// +void +LQListInsertListHead( + IN LOCKED_QUICK_LIST* const pDestList, + IN LOCKED_QUICK_LIST* const pSrcList ) +{ + LIST_ITEM *pSrcHead; + LIST_ITEM *pSrcTail; + uint32 SrcCount; + + ASSERT( pDestList ); + ASSERT( pSrcList ); + + // to avoid lock heirarchy issues, we never hold both locks at once + // as such this is a specialized implementation rather than simple calls + // to QListInsertListHead + // This means there will be a brief instance where items in SrcList are in + // neither list + + SpinLockAcquire(&pSrcList->m_Lock); + // Is the src list empty? + // We must have this check here for code below to work. + if( QListIsEmpty( &pSrcList->m_List ) ) + { + SpinLockRelease(&pSrcList->m_Lock); + return; + } + pSrcHead = pSrcList->m_List.m_Head.pNextItem; + pSrcTail = pSrcList->m_List.m_Head.pPrevItem; + SrcCount = pSrcList->m_List.m_Count; + // Update source list to reflect being empty. + QListRemoveAll( &pSrcList->m_List ); + SpinLockRelease(&pSrcList->m_Lock); + + SpinLockAcquire(&pDestList->m_Lock); + // Chain the destination list to the tail of the source list. + pSrcTail->pNextItem = pDestList->m_List.m_Head.pNextItem; + pDestList->m_List.m_Head.pNextItem->pPrevItem = pSrcTail; + + // Update the head of the destination list to the head of the source list. + pDestList->m_List.m_Head.pNextItem = pSrcHead; + pDestList->m_List.m_Head.pNextItem->pPrevItem = &pDestList->m_List.m_Head; + + // Adjust the count. + pDestList->m_List.m_Count += SrcCount; + SpinLockRelease(&pDestList->m_Lock); +} + + +/////////////////////////////////////////////////////////////////////////////// +// LQListInsertListTail +// +// Description: +// Add the items in a list to the tail of another list. +// +// Inputs: +// pDestList - Pointer to destination locked quicklist object +// pSrcList - Pointer to locked quicklist to add +// +// Outputs: +// None +// +// Returns: +// None +// +/////////////////////////////////////////////////////////////////////////////// +void +LQListInsertListTail( + IN LOCKED_QUICK_LIST* const pDestList, + IN LOCKED_QUICK_LIST* const pSrcList ) +{ + LIST_ITEM *pSrcHead; + LIST_ITEM *pSrcTail; + uint32 SrcCount; + + ASSERT( pDestList ); + ASSERT( pSrcList ); + + // to avoid lock heirarchy issues, we never hold both locks at once + // as such this is a specialized implementation rather than simple calls + // to QListInsertListHead + // This means there will be a brief instance where items in SrcList are in + // neither list + + SpinLockAcquire(&pSrcList->m_Lock); + // Is the src list empty? + // We must have this check here for code below to work. + if( QListIsEmpty( &pSrcList->m_List ) ) + { + SpinLockRelease(&pSrcList->m_Lock); + return; + } + + pSrcHead = pSrcList->m_List.m_Head.pNextItem; + pSrcTail = pSrcList->m_List.m_Head.pPrevItem; + SrcCount = pSrcList->m_List.m_Count; + + // Update source list to reflect being empty. + QListRemoveAll( &pSrcList->m_List ); + SpinLockRelease(&pSrcList->m_Lock); + + SpinLockAcquire(&pDestList->m_Lock); + // Chain the source list to the tail of the destination list. + pDestList->m_List.m_Head.pPrevItem->pNextItem = pSrcHead; + pSrcHead->pPrevItem = pDestList->m_List.m_Head.pPrevItem; + + // Update the tail of the destination list to the tail of the source list. + pDestList->m_List.m_Head.pPrevItem = pSrcTail; + pDestList->m_List.m_Head.pPrevItem->pNextItem = &pDestList->m_List.m_Head; + + // Bump the count. + pDestList->m_List.m_Count += SrcCount; + SpinLockRelease(&pDestList->m_Lock); +} + + +/////////////////////////////////////////////////////////////////////////////// +// LQListGetItemAt (OBSOLETE - DO NOT USE) +// +// Description: +// Return the item at the specified offset into the list. 0 is the first item. +// Must be used with care, as due to possible races, there is no guarantee +// that in item is still on list after call completes +// +// Inputs: +// pLQuickList - Pointer to locked quicklist object +// Index - offset into list of item to return +// +// Outputs: +// None +// +// Returns: +// LIST_ITEM at specified index +// NULL if item doesn't exist in the list +// +/////////////////////////////////////////////////////////////////////////////// +LIST_ITEM* +LQListGetItemAt( + IN LOCKED_QUICK_LIST* const pLQuickList, + IN uint32 Index ) +{ + LIST_ITEM *pTemp; + + ASSERT( pLQuickList ); + SpinLockAcquire(&pLQuickList->m_Lock); + pTemp = QListGetItemAt(&pLQuickList->m_List, Index); + SpinLockRelease(&pLQuickList->m_Lock); + return pTemp; +} + + +/////////////////////////////////////////////////////////////////////////////// +// LQListFindFromHead +// +// Description: +// Use the specified function to search for an item starting at the head of +// a list. Returns the item if found, otherwise NULL. If the user does not +// provide a compare function, then the pObject pointer in each LIST_ITEM is +// compared with the specified Context. +// List Lock will be held while function is called +// Must be used with care, as due to possible races, there is no guarantee +// that in item is still on list after call completes +// +// Inputs: +// pLQuickList - Pointer to locked quicklist object +// pfnFunc - User supplied compare function +// Context - Context for compare function, or compare value if pfnFunc +// is NULL. +// +// Outputs: +// None +// +// Returns: +// Pointer to LIST_ITEM if found. +// NULL otherwise +// +/////////////////////////////////////////////////////////////////////////////// +LIST_ITEM* +LQListFindFromHead( + IN LOCKED_QUICK_LIST* const pLQuickList, + IN QLIST_FIND_FUNC pfnFunc OPTIONAL, + IN void* const Context ) +{ + LIST_ITEM *pListItem; + + ASSERT( pLQuickList ); + SpinLockAcquire(&pLQuickList->m_Lock); + pListItem = QListFindFromHead(&pLQuickList->m_List, pfnFunc, Context); + SpinLockRelease(&pLQuickList->m_Lock); + + return pListItem; +} + + +/////////////////////////////////////////////////////////////////////////////// +// LQListFindFromTail +// +// Description: +// Use the specified function to search for an item starting at the tail of +// a list. Returns the item if found, otherwise NULL. If the user does not +// provide a compare function, then the pObject pointer in each LIST_ITEM is +// compared with the specified Context. +// List Lock will be held while function is called +// Must be used with care, as due to possible races, there is no guarantee +// that in item is still on list after call completes +// +// Inputs: +// pLQuickList - Pointer to locked quicklist object +// pfnFunc - User supplied compare function +// Context - Context for compare function, or compare value if pfnFunc +// is NULL. +// +// Outputs: +// None +// +// Returns: +// Pointer to LIST_ITEM if found. +// NULL otherwise +// +/////////////////////////////////////////////////////////////////////////////// +LIST_ITEM* +LQListFindFromTail( + IN LOCKED_QUICK_LIST* const pLQuickList, + IN QLIST_FIND_FUNC pfnFunc OPTIONAL, + IN void* const Context ) +{ + LIST_ITEM *pListItem; + + ASSERT( pLQuickList ); + + SpinLockAcquire(&pLQuickList->m_Lock); + pListItem = QListFindFromTail(&pLQuickList->m_List, pfnFunc, Context); + SpinLockRelease(&pLQuickList->m_Lock); + + return pListItem; +} + + +/////////////////////////////////////////////////////////////////////////////// +// LQListFindFromHeadAndRemove +// +// Description: +// Use the specified function to search for an item starting at the head of +// a list. Returns the item if found, otherwise NULL. If the user does not +// provide a compare function, then the pObject pointer in each LIST_ITEM is +// compared with the specified Context. +// If item is found in list it will be removed +// List Lock will be held while function is called +// +// Inputs: +// pLQuickList - Pointer to locked quicklist object +// pfnFunc - User supplied compare function +// Context - Context for compare function, or compare value if pfnFunc +// is NULL. +// +// Outputs: +// None +// +// Returns: +// Pointer to LIST_ITEM if found. +// NULL otherwise +// +/////////////////////////////////////////////////////////////////////////////// +LIST_ITEM* +LQListFindFromHeadAndRemove( + IN LOCKED_QUICK_LIST* const pLQuickList, + IN QLIST_FIND_FUNC pfnFunc OPTIONAL, + IN void* const Context ) +{ + LIST_ITEM *pListItem; + + ASSERT( pLQuickList ); + SpinLockAcquire(&pLQuickList->m_Lock); + pListItem = QListFindFromHead(&pLQuickList->m_List, pfnFunc, Context); + if (pListItem) + { + QListRemoveItem(&pLQuickList->m_List, pListItem); + } + SpinLockRelease(&pLQuickList->m_Lock); + + return pListItem; +} + + +/////////////////////////////////////////////////////////////////////////////// +// LQListFindFromTailAndRemove +// +// Description: +// Use the specified function to search for an item starting at the tail of +// a list. Returns the item if found, otherwise NULL. If the user does not +// provide a compare function, then the pObject pointer in each LIST_ITEM is +// compared with the specified Context. +// If item is found in list it will be removed +// List Lock will be held while function is called +// +// Inputs: +// pLQuickList - Pointer to locked quicklist object +// pfnFunc - User supplied compare function +// Context - Context for compare function, or compare value if pfnFunc +// is NULL. +// +// Outputs: +// None +// +// Returns: +// Pointer to LIST_ITEM if found. +// NULL otherwise +// +/////////////////////////////////////////////////////////////////////////////// +LIST_ITEM* +LQListFindFromTailAndRemove( + IN LOCKED_QUICK_LIST* const pLQuickList, + IN QLIST_FIND_FUNC pfnFunc OPTIONAL, + IN void* const Context ) +{ + LIST_ITEM *pListItem; + + ASSERT( pLQuickList ); + + SpinLockAcquire(&pLQuickList->m_Lock); + pListItem = QListFindFromTail(&pLQuickList->m_List, pfnFunc, Context); + if (pListItem) + { + QListRemoveItem(&pLQuickList->m_List, pListItem); + } + SpinLockRelease(&pLQuickList->m_Lock); + + return pListItem; +} + + +/////////////////////////////////////////////////////////////////////////////// +// LQListApplyFunc +// +// Description: +// Call the specified function for each item in the list. +// List Lock will be held while function is called +// +// Inputs: +// pLQuickList - Pointer to locked quicklist object +// pfnFunc - User supplied function +// Context - Context for function +// +// Outputs: +// None +// +// Returns: +// None +// +/////////////////////////////////////////////////////////////////////////////// +void +LQListApplyFunc( + IN LOCKED_QUICK_LIST* const pLQuickList, + IN QLIST_APPLY_FUNC pfnFunc, + IN void* const Context ) +{ + ASSERT( pLQuickList ); + SpinLockAcquire(&pLQuickList->m_Lock); + QListApplyFunc(&pLQuickList->m_List, pfnFunc, Context); + SpinLockRelease(&pLQuickList->m_Lock); +} + + + + + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +////////////// //////////// +////////////// IMPLEMENTATION OF DLIST //////////// +////////////// //////////// +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// + + + +// +// Items placed on the list require the use of a LIST_ITEM. A free pool +// of LIST_ITEMs is maintained to avoid allocating them with each insertion. +// To optimize performance when caching, the free list operates as a stack. +// + +// +// Attempt to grow the pool of available free LIST_ITEMs. +// +void +FreeItemPoolGrow( + IN DLIST* const pList ) +{ + LIST_ITEM *ListItemArray; + + // Allocate a new array of LIST_ITEMs. + ListItemArray = (LIST_ITEM*)ObjMgrAllocate( pList->m_pObjMgr, + sizeof( LIST_ITEM ) * pList->GrowItems ); + + if( !ListItemArray ) + return; + + // Add the LIST_ITEMs to the free list. + QListInsertArrayHead( &pList->m_FreeItemList, ListItemArray, + pList->GrowItems, sizeof( LIST_ITEM ) ); +} + + + + +/////////////////////////////////////////////////////////////////////////////// +// ListInitState +// +// Description: +// Initialize the state of the list. This function does not fail. +// This should be the first function called for a list. +// +// Inputs: +// pList - Pointer to DLIST object +// +// Outputs: +// None +// +// Returns: +// None +// +/////////////////////////////////////////////////////////////////////////////// +void +ListInitState( + IN DLIST* const pList ) +{ + QListInitState( &pList->m_List ); + QListInitState( &pList->m_FreeItemList ); + pList->m_pObjMgr = NULL; +} + + +/////////////////////////////////////////////////////////////////////////////// +// ListInit +// +// Description: +// Initialize the the list. The list will always be able to store MinItems +// items. +// +// Inputs: +// pList - Pointer to DLIST object +// MinItems - The minimum number of items to support in the list. If the +// number of items in the list exceeds this number, +// the list allocates more items automatically. +// +// Outputs: +// None +// +// Returns: +// TRUE on success +// FALSE otherwise +// +/////////////////////////////////////////////////////////////////////////////// +boolean +ListInit( + IN DLIST* const pList, + IN const uint32 MinItems ) +{ + ASSERT( pList && MinItems ); + + ListInitState( pList ); + if( !QListInit( &pList->m_FreeItemList ) ) + return FALSE; + + if( !QListInit( &pList->m_List ) ) + { + ListDestroy( pList ); + return FALSE; + } + + // Create and initialize the object manager. + pList->m_pObjMgr = + (OBJECT_MGR*)MemoryAllocate( sizeof( OBJECT_MGR ), FALSE, 0 ); + if( !pList->m_pObjMgr || + !ObjMgrInit( pList->m_pObjMgr, FALSE ) ) + { + ListDestroy( pList ); + return FALSE; + } + + // Set the minimum number of items and grow the initial pool. + pList->MinItems = MinItems; + pList->GrowItems = MinItems; + FreeItemPoolGrow( pList ); + if( !QListCount( &pList->m_FreeItemList ) ) + { + // Could not create minimum number of LIST_ITEMs - abort. + ListDestroy( pList ); + return FALSE; + } + + // We will grow by MinItems/8 items at a time, with a minimum of + // FREE_ITEM_GROW_SIZE. + pList->GrowItems >>= 3; + if( pList->GrowItems < FREE_ITEM_GROW_SIZE ) + pList->GrowItems = FREE_ITEM_GROW_SIZE; + + return TRUE; +} + + +/////////////////////////////////////////////////////////////////////////////// +// ListDestroy +// +// Description: +// Deallocate all internal memory used by the list. +// This function does not fail. +// +// Inputs: +// pList - Pointer to DLIST object +// +// Outputs: +// None +// +// Returns: +// None +// +/////////////////////////////////////////////////////////////////////////////// +void +ListDestroy( + IN DLIST* const pList ) +{ + ASSERT( pList ); + + QListDestroy( &pList->m_FreeItemList ); + QListDestroy( &pList->m_List ); + + if( pList->m_pObjMgr ) + { + ObjMgrDestroy( pList->m_pObjMgr ); + MemoryDeallocate( pList->m_pObjMgr ); + pList->m_pObjMgr = NULL; + } +} + + +/////////////////////////////////////////////////////////////////////////////// +// ListRemoveObject +// +// Description: +// Remove the item containing the specified user object from the list. +// +// Inputs: +// pList - Pointer to DLIST object +// pObject - User object pointer (may be NULL) +// +// Outputs: +// None +// +// Returns: +// TRUE if the object was found and removed from the list +// FALSE otherwise +// +/////////////////////////////////////////////////////////////////////////////// +boolean +ListRemoveObject( + IN DLIST* const pList, + IN void* const pObject ) +{ + LIST_ITEM *pListItem; + + ASSERT( pList ); + + // find the item in question + pListItem = QListFindFromHead( &pList->m_List, NULL, pObject ); + if( pListItem ) + { + // remove this item + QListRemoveItem( &pList->m_List, pListItem ); + QListInsertHead( &pList->m_FreeItemList, pListItem ); + return TRUE; + } + return FALSE; +} + + +/////////////////////////////////////////////////////////////////////////////// +// ListInsertArrayHead +// +// Description: +// Insert an array of new items at the head of the list. +// +// Inputs: +// pList - Pointer to DLIST object +// pArray - Pointer to array +// ItemCount - Number of items in the array to insert +// ItemSize - Size (in bytes) of each item in the array +// +// Outputs: +// None +// +// Returns: +// TRUE on success +// FALSE otherwise +// +/////////////////////////////////////////////////////////////////////////////// +boolean +ListInsertArrayHead( + IN DLIST* const pList, + IN void* const pArray, + IN const uint32 ItemCount, + IN const uint32 ItemSize ) +{ + void *pObject; + uint32 Count = ItemCount; + + ASSERT( pArray && ItemSize && ItemCount ); + + // To add items from the array to the list in the same order as + // the elements appear in the array, we add them starting with + // the last one first. Locate the last item. + pObject = ((uchar*)pArray + (ItemSize * (ItemCount - 1))); + + // Continue to add all items to the list. + while( Count-- ) + { + if( !ListInsertHead( pList, pObject ) ) + { + // Remove all items that have been inserted. + while( Count++ < ItemCount ) + ListRemoveHead( pList ); + return FALSE; + } + + // Get the next object to add to the list. + pObject = ((uchar*)pObject - ItemSize); + } + + return TRUE; +} + + +/////////////////////////////////////////////////////////////////////////////// +// ListInsertArrayTail +// +// Description: +// Insert an array of new items at the tail of the list. +// +// Inputs: +// pList - Pointer to DLIST object +// pArray - Pointer to array +// ItemCount - number of items in the array to insert +// ItemSize - Size (in bytes) of each item in the array +// +// Outputs: +// None +// +// Returns: +// TRUE on success +// FALSE otherwise +// +/////////////////////////////////////////////////////////////////////////////// +boolean +ListInsertArrayTail( + IN DLIST* const pList, + IN void* const pArray, + IN const uint32 ItemCount, + IN const uint32 ItemSize ) +{ + void *pObject; + uint32 Count = ItemCount; + + ASSERT( pArray && ItemSize && ItemCount ); + + // Set the first item to add to the list. + pObject = pArray; + + // Continue to add all items to the list. + while ( Count-- ) + { + if( !ListInsertTail( pList, pObject ) ) + { + // Remove all items that have been inserted. + while( Count++ < ItemCount ) + ListRemoveTail( pList ); + return FALSE; + } + + // Get the next object to add to the list. + pObject = ((uchar*)pObject + ItemSize); + } + + return TRUE; +} + + +// +// Returns the specified numbered item in a list. If no item is found +// at that location, returns NULL. +// OBSOLETE!!! DO NOT USE!!! +// +void* +ListGetObjectAt( + IN const DLIST* const pList, + IN const uint32 Index ) +{ + LIST_ITEM *pListItem; + + ASSERT( pList ); + if( (pListItem = QListGetItemAt( &pList->m_List, Index )) ) + return pListItem->pObject; + else + return( NULL ); +} + + +/////////////////////////////////////////////////////////////////////////////// +// ListFindFromHead +// +// Description: +// Use the specified function to search for an object starting at the head of +// a list. Returns the item if found, otherwise NULL. The list is not +// modified. +// +// Inputs: +// pList - Pointer to DLIST object +// pfnFunc - Pointer to user's compare function +// Context - User context for compare function (may be NULL) +// +// Outputs: +// None +// +// Returns: +// Pointer to user object for which Func returned TRUE +// NULL otherwise +// +/////////////////////////////////////////////////////////////////////////////// +void* +ListFindFromHead( + IN const DLIST* const pList, + IN LIST_FIND_FUNC pfnFunc, + IN void* const Context ) +{ + LIST_ITEM*pListItem; + + // Note that context can have any arbitrary value. + ASSERT( pList ); + ASSERT( pfnFunc ); + + pListItem = QListHead( &pList->m_List ); + + while( pListItem ) + { + if( pfnFunc( pListItem->pObject, Context ) ) + return( pListItem->pObject ); + + pListItem = QListNext( &pList->m_List, pListItem ); + } + + // no match + return( NULL ); +} + + +/////////////////////////////////////////////////////////////////////////////// +// ListFindFromTail +// +// Description: +// Use the specified function to search for an object starting at the tail of +// a list. Returns the item if found, otherwise NULL. The list is not +// modified. +// +// Inputs: +// pList - Pointer to DLIST object +// pfnFunc - Pointer to user's compare function +// Context - User context for compare function (may be NULL) +// +// Outputs: +// None +// +// Returns: +// Pointer to user object for which Func returned TRUE +// NULL otherwise +// +/////////////////////////////////////////////////////////////////////////////// +void* +ListFindFromTail( + IN const DLIST* const pList, + IN LIST_FIND_FUNC pfnFunc, + IN void* const Context ) +{ + LIST_ITEM* pListItem; + + // Note that context can have any arbitrary value. + ASSERT( pList ); + ASSERT( pfnFunc ); + + pListItem = QListTail( &pList->m_List ); + + while( pListItem ) + { + if( pfnFunc( pListItem->pObject, Context ) ) + return( pListItem->pObject ); + + pListItem = QListPrev( &pList->m_List, pListItem ); + } + + // no match + return( NULL ); +} + + +/////////////////////////////////////////////////////////////////////////////// +// ListApplyFunc +// +// Description: +// Calls the given function for all tiems in the list. The list is not +// modified. +// +// Inputs: +// pList - Pointer to DLIST object +// pfnFunc - Pointer to user's compare function +// Context - User context for compare function (may be NULL) +// +// Outputs: +// None +// +// Returns: +// None +// +/////////////////////////////////////////////////////////////////////////////// +void +ListApplyFunc( + IN const DLIST* const pList, + IN LIST_APPLY_FUNC pfnFunc, + IN void* const Context ) +{ + LIST_ITEM* pListItem; + + // Note that context can have any arbitrary value. + ASSERT( pList ); + ASSERT( pfnFunc ); + + pListItem = QListHead( &pList->m_List ); + + while( pListItem ) + { + pfnFunc( pListItem->pObject, Context ); + + pListItem = QListNext( &pList->m_List, pListItem ); + } +} diff --git a/IbAccess/Common/Public/ilist.h b/IbAccess/Common/Public/ilist.h new file mode 100644 index 0000000..857095d --- /dev/null +++ b/IbAccess/Common/Public/ilist.h @@ -0,0 +1,3126 @@ +/* BEGIN_ICS_COPYRIGHT3 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT3 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +#ifndef _IBA_PUBLIC_ILIST_H_ +#define _IBA_PUBLIC_ILIST_H_ + + +#include "iba/public/datatypes.h" +#include "iba/public/ispinlock.h" + +/* Many of the simpler, more commonly used list functions are inlined + * to improve performance. That inlining confuses the gdb stack trace + * however. To disable inlining while debugging, do the following: + * + * 1) Change the INLINE_LIST macro (below) from 1 to 0 + * + * 2) Uncomment the lines in the IbAccess/Darwin/exports file which + * correspond to the list functions which are no longer inlined. + */ +#define INLINE_ILIST 1 + +#if INLINE_ILIST +#define CONDITIONALLY_INLINE static __inline +#else +#define CONDITIONALLY_INLINE +#endif + +/* NOTE: In order to conditionally inline the list functions (as + * described above), this header file is also used to *define* + * (not just declare) the non-inlined functions in ilist.c when + * inlining is disabled. The *only* source file that should be + * enabling the DEFINE_ILIST_FUNCS macro is ilist.c. + */ + +#ifdef __cplusplus +extern "C" { +#endif + + +/* + * Generic list item structure. Used by all lists to store objects. + * The previous and next pointers are used internally, and should not + * be accessed by users. + */ +typedef struct _LIST_ITEM +{ + struct _LIST_ITEM *pNextItem; /* DO NOT USE!! */ + struct _LIST_ITEM *pPrevItem; /* DO NOT USE!! */ + void *pObject; /* User's context */ + +} LIST_ITEM; + +/* define an opaque iterator for the LIST functions */ +typedef void *LIST_ITERATOR; + +typedef void +(*QLIST_APPLY_FUNC)( + IN LIST_ITEM *pListItem, + IN void *Context ); + +typedef boolean +(*QLIST_FIND_FUNC)( + IN LIST_ITEM *pListItem, + IN void *Context ); + +typedef void +(*LIST_APPLY_FUNC)( + IN void *pObject, + IN void *Context ); + +typedef boolean +(*LIST_FIND_FUNC)( + IN void *pObject, + IN void *Context ); + + + +/**************************************************************************** + * Quick list object definition. The quick list stores user supplied "list + * items" in a doubly linked list. Operations on a quick list always succeed + * since it does not allocate memory on the fly. The user of the + * quick list is responsible for locking and unlocking it to prevent + * corruption. + * + ****************************************************************************/ +typedef struct _QUICK_LIST +{ + /* Private data structure used by the quick list object. */ + /* Users should not access these variables directly. */ + LIST_ITEM m_Head; /* DO NOT USE!! */ + /* Number of items in the list. */ + uint32 m_Count; /* DO NOT USE!! */ + +} QUICK_LIST; + +/**************************************************************************** + * Locked Quick list object definition. This is a Quick List with an + * associated lock. + ****************************************************************************/ +typedef struct _LOCKED_QUICK_LIST +{ + /* Users may access these directly for functions which must walk the list */ + /* beware, the LQList functions provided below will acquire the lock */ + /* and should not be used while the list is locked by the user */ + /* this is not ideal, but iterators which work in conjunction with locks */ + /* can be quite complex so this more simplistic approach is taken */ + QUICK_LIST m_List; + SPIN_LOCK m_Lock; +} LOCKED_QUICK_LIST; + +/**************************************************************************** + * List object definition. The list stores user supplied objects in a doubly + * linked list. Operations on a list may require the allocation of memory, + * and may therefore fail. The user of the list is responsible for + * locking and unlocking it to prevent corruption. + * + ****************************************************************************/ +typedef struct _DLIST +{ + /* Private data structure used by the list object. */ + /* Users should not access these variables directly. */ + /* List of free "list items" used to add objects to the list. */ + QUICK_LIST m_List; /* DO NOT USE!! */ + QUICK_LIST m_FreeItemList; /* DO NOT USE!! */ + + /* The list dynamically adds list items as needed. The object */ + /* manager is used to track their allocation. This is a pointer */ + /* to the object manager to avoid circular include dependencies. */ + struct _OBJECT_MGR *m_pObjMgr; /* DO NOT USE!! */ + uint32 MinItems; /* DO NOT USE!! */ + uint32 GrowItems; /* DO NOT USE!! */ + +} DLIST; + + +/**************************************************************************** + * Queue object definition. The queue stores user supplied objects in a doubly + * linked list. A queue stores and returns objects in FIFO order. + * Operations on a queue may require the allocation of memory, + * and may therefore fail. The user of the queue is responsible for + * locking and unlocking it to prevent corruption. + * + ****************************************************************************/ +typedef DLIST QUEUE; + + +/**************************************************************************** + * Stack object definition. The stack stores user supplied objects in a doubly + * linked list. A stack stores and returns objects in LIFO order. + * Operations on a stack may require the allocation of memory, and may + * therefore fail. The user of the stack is responsible for locking and + * unlocking it to prevent corruption. + * + ****************************************************************************/ +typedef DLIST STACK; + + +/**************************************************************************** + * PrimitiveInsert + * + * Description: + * Add a new item in front of the specified item. This is a low level + * function for use internally by the queuing routines. + * + * Inputs: + * pListItem - Pointer to LIST_ITEM to insert in front of + * pNewItem - Pointer to LIST_ITEM to add + * + * Outputs: + * None + * + * Returns: + * None + * + ****************************************************************************/ +CONDITIONALLY_INLINE void +PrimitiveInsert( + IN LIST_ITEM* const pListItem, + IN LIST_ITEM* const pNewItem ) +#if INLINE_ILIST || DEFINE_ILIST_FUNCS +{ + pNewItem->pNextItem = pListItem; + pNewItem->pPrevItem = pListItem->pPrevItem; + pListItem->pPrevItem = pNewItem; + pNewItem->pPrevItem->pNextItem = pNewItem; +} +#else +; +#endif + +/**************************************************************************** + * PrimitiveRemove + * + * Description: + * Remove an item from a list. This is a low level routine + * for use internally by the queuing routines. + * + * Inputs: + * pListItem - Pointer to LIST_ITEM to remove + * + * Outputs: + * None + * + * Returns: + * None + * + ****************************************************************************/ +CONDITIONALLY_INLINE void +PrimitiveRemove( + IN LIST_ITEM* const pListItem ) +#if INLINE_ILIST || DEFINE_ILIST_FUNCS +{ + /* set the back pointer */ + pListItem->pNextItem->pPrevItem = pListItem->pPrevItem; + /* set the next pointer */ + pListItem->pPrevItem->pNextItem = pListItem->pNextItem; + + /* NULL the link pointers to indicate that item is not on any list */ + pListItem->pNextItem = NULL; + pListItem->pPrevItem = NULL; +} +#else +; +#endif + +/**************************************************************************** + * ListItemIsInAList + * + * Description: + * Examines a list item's link pointers to determine whether it is currently + * on a list. This test relies upon those pointers being initialized to NULL + * and on the Remove() function NULLing those pointers. + * + * Inputs: + * pListItem - Pointer to LIST_ITEM to be tested + * + * Outputs: + * None + * + * Returns: + * TRUE if item is on a list + * FALSE if list item is not on a list + * + ****************************************************************************/ +static __inline boolean +ListItemIsInAList( + IN LIST_ITEM* const pListItem ) +{ + ASSERT( pListItem ); + return (pListItem->pNextItem != NULL); +} + +/**************************************************************************** + * ListItemInitState + * + * Description: + * NULLs a list item's link pointers to indicate that it is currently not + * on any list. + * + * Inputs: + * pListItem - Pointer to LIST_ITEM to be initialized + * + * Outputs: + * None + * + * Returns: + * None + * + ****************************************************************************/ +static __inline void +ListItemInitState( + IN LIST_ITEM* const pListItem ) +{ + ASSERT( pListItem ); + + /* NULL the link pointers to indicate item is not on any list */ + pListItem->pNextItem = NULL; + pListItem->pPrevItem = NULL; +} + + +/**************************************************************************** + **************************************************************************** + *********** ********** + *********** DECLARATION OF QUICK_LIST ********** + *********** ********** + **************************************************************************** + ****************************************************************************/ + + +/* + * Set the object pointer in a list item. + */ +static __inline void +QListSetObj( + IN LIST_ITEM* const pListItem, + IN void* const pObject ) +{ + ASSERT( pListItem ); + pListItem->pObject = pObject; +} + + +/* + * Get the object pointed to by a list item. + */ +static __inline void* +QListObj( + IN const LIST_ITEM* const pListItem ) +{ + ASSERT( pListItem ); + + return pListItem->pObject; +} + + +/**************************************************************************** + * QListInitState + * + * Description: + * This function initializes the state of the quicklist. + * This function cannot fail. + * + * Inputs: + * pQuickList - Pointer to quicklist object + * + * Outputs: + * None. + * + * Returns: + * None. + * + ****************************************************************************/ +void +QListInitState( + IN QUICK_LIST* const pQuickList ); + + +/**************************************************************************** + * QListInit + * + * Description: + * This function initializes the quicklist. + * + * Inputs: + * pQuickList - Pointer to quicklist object + * + * Outputs: + * None. + * + * Returns: + * TRUE on success + * FALSE otherwise + * + ****************************************************************************/ +boolean +QListInit( + IN QUICK_LIST* const pQuickList ); + + +/**************************************************************************** + * QListDestroy + * + * Description: + * Destroys a list and discards any items on the list without freeing them + * + * Inputs: + * pQuickList - Pointer to quicklist object + * + * Outputs: + * None + * + * Returns: + * None + * + ****************************************************************************/ +void +QListDestroy( + IN QUICK_LIST* const pQuickList ); + + +/**************************************************************************** + * QListAllocateAndInit + * + * Description: + * This function allocates memory for and initializes the state of the + * quicklist. + * + * Inputs: + * IsPageable - + * Tag - + * + * Outputs: + * None. + * + * Returns: + * NULL on error, otherwise pointer to a ready to use List + * + ****************************************************************************/ +QUICK_LIST* +QListAllocateAndInit( + IN boolean IsPageable, + IN uint32 Tag ); + + +/**************************************************************************** + * QListDeallocate + * + * Description: + * This function destroys the list and deallocates memory for the + * quicklist. + * It does not free items which were on the list + * + * Inputs: + * pQuickList - Pointer to quicklist object allocated by QListAllocateAndInit + * if NULL, this function does nothing + * + * Outputs: + * None. + * + * Returns: + * + ****************************************************************************/ +void +QListDeallocate( + IN QUICK_LIST* const pQuickList ); + + +/**************************************************************************** + * QListIsEmpty + * + * Description: + * return true if the list is empty + * + * Inputs: + * pQuickList - Pointer to quicklist object + * + * Outputs: + * None + * + * Returns: + * True if the list is empty + * False otherwise + * + ****************************************************************************/ +static __inline boolean +QListIsEmpty( + IN const QUICK_LIST* const pQuickList ) +{ + return( (boolean)(pQuickList->m_Count == 0) ); +} + + +/**************************************************************************** + * QListCount + * + * Description: + * Returns the number of items in the list. This call is not expensive, + * since the QList routines always maintain the count value. + * + * Inputs: + * pSrcList - Pointer to source quicklist object + * + * Outputs: + * None + * + * Returns: + * Number of items in the list + * + ****************************************************************************/ +static __inline uint32 +QListCount( + IN const QUICK_LIST* const pQuickList ) +{ + ASSERT( pQuickList ); + return pQuickList->m_Count; +} + + +/**************************************************************************** + * QListIsItemInList + * + * Description: + * Return true if the specified item is in the list + * + * Inputs: + * pQuickList - Pointer to quicklist object + * pListItem - Pointer to the LIST_ITEM to find + * + * Outputs: + * None + * + * Returns: + * None + * + ****************************************************************************/ +boolean +QListIsItemInList( + IN const QUICK_LIST* const pQuickList, + IN const LIST_ITEM* const pListItem ); + + +/**************************************************************************** + * QListInsertHead + * + * Description: + * Add a new item to the head of the list. The caller does not need to + * initialize the LIST_ITEM to be added. + * + * Inputs: + * pQuickList - Pointer to quicklist object + * pListItem - Pointer to LIST_ITEM to add + * + * Outputs: + * None + * + * Returns: + * None + * + ****************************************************************************/ +CONDITIONALLY_INLINE void +QListInsertHead( + IN QUICK_LIST* const pQuickList, + IN LIST_ITEM* const pListItem ) +#if INLINE_ILIST || DEFINE_ILIST_FUNCS +{ + ASSERT( pQuickList ); + ASSERT( pListItem ); + +#ifdef QLIST_PARANOID + ASSERT( !QListIsItemInList( pQuickList, pListItem ) ); +#endif + + /* put this guy at the front */ + PrimitiveInsert( pQuickList->m_Head.pNextItem, pListItem ); + + /* bump the count */ + pQuickList->m_Count++; +} +#else +; +#endif + + +/**************************************************************************** + * QListInsertTail + * + * Description: + * Add a new item to the tail of the list. The caller does not need to + * initialize the LIST_ITEM to be added. + * + * Inputs: + * pQuickList - Pointer to quicklist object + * pListItem - Pointer to LIST_ITEM to add + * + * Outputs: + * None + * + * Returns: + * None + * + ****************************************************************************/ +CONDITIONALLY_INLINE void +QListInsertTail( + IN QUICK_LIST* const pQuickList, + IN LIST_ITEM* const pListItem ) +#if INLINE_ILIST || DEFINE_ILIST_FUNCS +{ + ASSERT( pQuickList ); + ASSERT( pListItem ); + +#ifdef QLIST_PARANOID + ASSERT( !QListIsItemInList( pQuickList, pListItem ) ); +#endif + + /* put this guy at the back */ + /* In other words, put the new element in front of the head */ + /* which is the same as being at the tail */ + PrimitiveInsert( &pQuickList->m_Head, pListItem ); + + /* bump the count */ + pQuickList->m_Count++; +} +#else +; +#endif + + +/**************************************************************************** + * QListInsertPrev + * + * Description: + * Insert an item before the specified item for the given list. + * + * Inputs: + * pQuickList - Pointer to quicklist object + * pListItem - Pointer to item in the list + * pNewItem - Pointer to item to insert before pListItem + * + * Outputs: + * None + * + * Returns: + * None + * + ****************************************************************************/ +CONDITIONALLY_INLINE void +QListInsertPrev( + IN QUICK_LIST* const pQuickList, + IN LIST_ITEM* const pListItem, + IN LIST_ITEM* const pNewItem ) +#if INLINE_ILIST || DEFINE_ILIST_FUNCS +{ + /* sanity checks */ + ASSERT( pQuickList ); + ASSERT( pListItem ); + ASSERT( pNewItem ); + +#ifdef QLIST_PARANOID + ASSERT( QListIsItemInList( pQuickList, pListItem ) ); + ASSERT( !QListIsItemInList( pQuickList, pNewItem ) ); +#endif + + PrimitiveInsert( pListItem, pNewItem ); + + pQuickList->m_Count++; +} +#else +; +#endif + + +/**************************************************************************** + * QListInsertNext + * + * Description: + * Insert an item after the specified item for the given list. + * + * Inputs: + * pQuickList - Pointer to quicklist object + * pListItem - Pointer to item in the list + * pNewItem - Pointer to item to insert before pListItem + * + * Outputs: + * None + * + * Returns: + * None + * + ****************************************************************************/ +CONDITIONALLY_INLINE void +QListInsertNext( + IN QUICK_LIST* const pQuickList, + IN LIST_ITEM* const pListItem, + IN LIST_ITEM* const pNewItem ) +#if INLINE_ILIST || DEFINE_ILIST_FUNCS +{ + /* sanity checks */ + ASSERT( pQuickList ); + ASSERT( pListItem ); + ASSERT( pNewItem ); + +#ifdef QLIST_PARANOID + ASSERT( QListIsItemInList( pQuickList, pListItem ) ); + ASSERT( !QListIsItemInList( pQuickList, pNewItem ) ); +#endif + + PrimitiveInsert( pListItem->pNextItem, pNewItem ); + + pQuickList->m_Count++; +} +#else +; +#endif + + +/**************************************************************************** + * QListHead + * + * Description: + * Retruns a pointer to the head of a list. Does not alter the list. + * Returns NULL if the list is empty. + * + * Inputs: + * pQuickList - Pointer to quicklist object + * + * Outputs: + * None + * + * Returns: + * Pointer to head of list + * + ****************************************************************************/ +static __inline LIST_ITEM* +QListHead( + IN const QUICK_LIST* const pQuickList ) +{ + ASSERT( pQuickList ); + + /* make sure the list isn't empty */ + if( QListIsEmpty( pQuickList ) ) + return( NULL ); + + return( pQuickList->m_Head.pNextItem ); +} + + +/**************************************************************************** + * QListTail + * + * Description: + * Retruns a pointer to the last element of a list. Does not alter the list. + * Returns NULL if the list is empty. + * + * Inputs: + * pQuickList - Pointer to quicklist object + * + * Outputs: + * None + * + * Returns: + * Pointer to tail of list + * + ****************************************************************************/ +static __inline LIST_ITEM* +QListTail( + IN const QUICK_LIST* const pQuickList ) +{ + ASSERT( pQuickList ); + + /* make sure the list isn't empty */ + if( QListIsEmpty( pQuickList ) ) + return( NULL ); + + return( pQuickList->m_Head.pPrevItem ); +} + + +/**************************************************************************** + * QListPrev + * + * Description: + * Return a pointer to the element in front of the specified element. + * Returns NULL if there is no element in front of the specified element. + * + * + * Inputs: + * pQuickList - Pointer to quicklist object + * pListItem - Pointer to item in the list + * pNewItem - Pointer to item to insert before pListItem + * + * Outputs: + * None + * + * Returns: + * None + * + ****************************************************************************/ +static __inline LIST_ITEM* +QListPrev( + IN const QUICK_LIST* const pQuickList, + IN const LIST_ITEM* const pListItem ) +{ + /* Sanity checks */ + ASSERT( pQuickList ); + ASSERT( pListItem ); + +#ifdef QLIST_PARANOID + ASSERT( QListIsItemInList( pQuickList, pListItem ) ); +#endif + + /* Return the previous item, if any. */ + if( pListItem->pPrevItem != &pQuickList->m_Head ) + return( pListItem->pPrevItem ); + else + return( NULL ); +} + + +/**************************************************************************** + * QListNext + * + * Description: + * Return a pointer to the element in back of the specified element. + * Returns NULL if there is no element in back of the specified element. + * + * Inputs: + * pQuickList - Pointer to quicklist object + * pListItem - Pointer to item in the list + * + * Outputs: + * None + * + * Returns: + * None + * + ****************************************************************************/ +static __inline LIST_ITEM* +QListNext( + IN const QUICK_LIST* const pQuickList, + IN const LIST_ITEM* const pListItem ) +{ + /* sanity checks */ + ASSERT( pQuickList ); + ASSERT( pListItem ); + +#ifdef QLIST_PARANOID + ASSERT( QListIsItemInList( pQuickList, pListItem ) ); +#endif + + /* Return the next item, if any. */ + if( pListItem->pNextItem == &pQuickList->m_Head ) + return( NULL ); + else + return( pListItem->pNextItem ); +} + + +/**************************************************************************** + * QListRemoveHead + * + * Description: + * Remove an item from the head of a list. + * + * Inputs: + * pQuickList - Pointer to quicklist object + * + * Outputs: + * None + * + * Returns: + * Pointer to LIST_ITEM removed from the list + * + ****************************************************************************/ +CONDITIONALLY_INLINE LIST_ITEM* +QListRemoveHead( + IN QUICK_LIST* const pQuickList ) +#if INLINE_ILIST || DEFINE_ILIST_FUNCS +{ + LIST_ITEM *pItem; + + ASSERT( pQuickList ); + + /* make sure the list isn't empty */ + if( !pQuickList->m_Count ) + return( NULL ); + + pItem = pQuickList->m_Head.pNextItem; + PrimitiveRemove( pItem ); + + pQuickList->m_Count--; + + return pItem; +} +#else +; +#endif + + +/**************************************************************************** + * QListRemoveTail + * + * Description: + * Remove an item from the tail of a list. + * + * Inputs: + * pQuickList - Pointer to quicklist object + * + * Outputs: + * None + * + * Returns: + * Pointer to LIST_ITEM removed from the list + * + ****************************************************************************/ +CONDITIONALLY_INLINE LIST_ITEM* +QListRemoveTail( + IN QUICK_LIST* const pQuickList ) +#if INLINE_ILIST || DEFINE_ILIST_FUNCS +{ + LIST_ITEM *pItem; + + ASSERT( pQuickList ); + + /* make sure the list isn't empty */ + if( QListIsEmpty( pQuickList ) ) + return( NULL ); + + pItem = pQuickList->m_Head.pPrevItem; + PrimitiveRemove( pItem ); + + pQuickList->m_Count--; + + return pItem; +} +#else +; +#endif + + +/**************************************************************************** + * QListRemoveItem + * + * Description: + * Removes an item from the specified list. + * + * Inputs: + * pQuickList - Pointer to quicklist object + * pListItem - Pointer to the list item to remove + * + * Outputs: + * None + * + * Returns: + * None + * + ****************************************************************************/ +CONDITIONALLY_INLINE void +QListRemoveItem( + IN QUICK_LIST* const pQuickList, + IN LIST_ITEM* const pListItem ) +#if INLINE_ILIST || DEFINE_ILIST_FUNCS +{ + ASSERT( pQuickList ); + ASSERT( pListItem ); + +#ifdef QLIST_PARANOID + ASSERT( QListIsItemInList( pQuickList, pListItem ) ); +#endif + + PrimitiveRemove( pListItem ); + + pQuickList->m_Count--; +} +#else +; +#endif + + +/**************************************************************************** + * QListSafeRemoveItem + * + * Description: + * Removes an item from the specified list only if its in the list + * + * Inputs: + * pQuickList - Pointer to quicklist object + * pListItem - Pointer to the list item to remove + * + * Outputs: + * None + * + * Returns: + * TRUE - was on list + * FALSE - was not on list + * + ****************************************************************************/ +CONDITIONALLY_INLINE boolean +QListSafeRemoveItem( + IN QUICK_LIST* const pQuickList, + IN LIST_ITEM* const pListItem ) +#if INLINE_ILIST || DEFINE_ILIST_FUNCS +{ + ASSERT( pQuickList ); + ASSERT( pListItem ); + + if( QListIsItemInList( pQuickList, pListItem ) ) + { + PrimitiveRemove( pListItem ); + pQuickList->m_Count--; + return TRUE; + } + return FALSE; +} +#else +; +#endif + + +/**************************************************************************** + * QListRemoveAll + * + * Description: + * Removes all items in the specified list. + * + * Inputs: + * pQuickList - Pointer to quicklist object + * + * Outputs: + * None + * + * Returns: + * None + * + ****************************************************************************/ +void +QListRemoveAll( + IN QUICK_LIST* const pQuickList ); + + + +/**************************************************************************** + * QListInsertArrayHead + * + * Description: + * Insert an array of items to the head of a list. The array pointer passed + * into the function points to the LIST_ITEM in the first element of the + * caller's element array. There is no restriction on where the element is + * stored in the parent structure. + * + * Inputs: + * pQuickList - Pointer to quicklist object. + * pArray - Pointer to LIST_ITEM of first element in array to add. + * ItemCount - Number of items to add from the array. + * ItemSize - Size of each item in the array. This is the offset from + * LIST_ITEM to LIST_ITEM. + * + * Outputs: + * None + * + * Returns: + * None + * + ****************************************************************************/ +void +QListInsertArrayHead( + IN QUICK_LIST* const pQuickList, + IN LIST_ITEM* const pArray, + IN uint32 ItemCount, + IN const uint32 ItemSize ); + + +/**************************************************************************** + * QListInsertArrayTail + * + * Description: + * Insert an array of items to the tail of a list. The array pointer passed + * into the function points to the LIST_ITEM in the first element of the + * caller's element array. There is no restriction on where the element is + * stored in the parent structure. + * + * Inputs: + * pQuickList - Pointer to quicklist object. + * pArray - Pointer to LIST_ITEM of first element in array to add. + * ItemCount - Number of items to add from the array. + * ItemSize - Size of each item in the array. This is the offset from + * LIST_ITEM to LIST_ITEM. + * + * Outputs: + * None + * + * Returns: + * None + * + ****************************************************************************/ +void +QListInsertArrayTail( + IN QUICK_LIST* const pQuickList, + IN LIST_ITEM* const pArray, + IN uint32 ItemCount, + IN const uint32 ItemSize); + + +/**************************************************************************** + * QListInsertListHead + * + * Description: + * Add the items in a list to the head of another list. + * + * Inputs: + * pDestList - Pointer to destination quicklist object. + * pSrcList - Pointer to quicklist to add. + * + * Outputs: + * None + * + * Returns: + * None + * + ****************************************************************************/ +void +QListInsertListHead( + IN QUICK_LIST* const pDestList, + IN QUICK_LIST* const pSrcList ); + + +/**************************************************************************** + * QListInsertListTail + * + * Description: + * Add the items in a list to the tail of another list. + * + * Inputs: + * pDestList - Pointer to destination quicklist object + * pSrcList - Pointer to quicklist to add + * + * Outputs: + * None + * + * Returns: + * None + * + ****************************************************************************/ +void +QListInsertListTail( + IN QUICK_LIST * const pDestList, + IN QUICK_LIST * const pSrcList ); + + +/**************************************************************************** + * QListGetItemAt (OBSOLETE - DO NOT USE) + * + * Description: + * Return the item at the specified offset into the list. 0 is the first item. + * + * Inputs: + * pQuickList - Pointer to quicklist object + * Index - Offset into list of item to return + * + * Outputs: + * None + * + * Returns: + * LIST_ITEM at specified index + * NULL if item doesn't exist in the list + * + ****************************************************************************/ +/**** OBSOLETE - DO NOT USE FOR NEW CODE!!! */ +LIST_ITEM* +QListGetItemAt( + IN const QUICK_LIST* const pQuickList, + IN uint32 Index ); + +/**** Define for backward compatibility. */ +/**** OBSOLETE - DO NOT USE FOR NEW CODE!!! */ +#define QListFindItem QListFindFromHead + + +/**************************************************************************** + * QListFindFromHead + * + * Description: + * Use the specified function to search for an item starting at the head of + * a list. Returns the item if found, otherwise NULL. If the user does not + * provide a compare function, then the pObject pointer in each LIST_ITEM is + * compared with the specified Context. + * + * Inputs: + * pQuickList - Pointer to quicklist object + * pfnFunc - User supplied compare function + * Context - Context for compare function, or compare value if pfnFunc + * is NULL. + * + * Outputs: + * None + * + * Returns: + * Pointer to LIST_ITEM if found. + * NULL otherwise + * + ****************************************************************************/ +LIST_ITEM* +QListFindFromHead( + IN const QUICK_LIST* const pQuickList, + IN QLIST_FIND_FUNC pfnFunc OPTIONAL, + IN void* const Context ); + + +/**************************************************************************** + * QListFindFromTail + * + * Description: + * Use the specified function to search for an item starting at the tail of + * a list. Returns the item if found, otherwise NULL. If the user does not + * provide a compare function, then the pObject pointer in each LIST_ITEM is + * compared with the specified Context. + * + * Inputs: + * pQuickList - Pointer to quicklist object + * pfnFunc - User supplied compare function + * Context - Context for compare function, or compare value if pfnFunc + * is NULL. + * + * Outputs: + * None + * + * Returns: + * Pointer to LIST_ITEM if found. + * NULL otherwise + * + ****************************************************************************/ +LIST_ITEM* +QListFindFromTail( + IN const QUICK_LIST* const pQuickList, + IN QLIST_FIND_FUNC pfnFunc OPTIONAL, + IN void* const Context ); + + +/**************************************************************************** + * QListApplyFunc + * + * Description: + * Call the specified function for each item in the list. + * + * Inputs: + * pQuickList - Pointer to quicklist object + * pfnFunc - User supplied function + * Context - Context for function + * + * Outputs: + * None + * + * Returns: + * None + * + ****************************************************************************/ +void +QListApplyFunc( + IN const QUICK_LIST* const pQuickList, + IN QLIST_APPLY_FUNC pfnFunc, + IN void* const Context ); + + +/**************************************************************************** + * QListMoveItems + * + * Description: + * Move items from one list to another based on a user supplied function. + * Items are moved if Func() returns true. + * Items are moved to the tail of the destination list. + * + * Inputs: + * pSrcList - Pointer to source quicklist object + * pDestList - Pointer to destination quicklist object + * pfnFunc - User supplied function, returns true to move an item + * Context - Context for function + * + * Outputs: + * None + * + * Returns: + * None + * + ****************************************************************************/ +void +QListMoveItems( + IN QUICK_LIST* const pSrcList, + IN QUICK_LIST* const pDestList, + IN QLIST_FIND_FUNC pfnFunc, + IN void* const Context ); + + +/**************************************************************************** + **************************************************************************** + *********** ********** + *********** DECLARATION OF LOCKED_QUICK_LIST ********** + *********** ********** + **************************************************************************** + ****************************************************************************/ + + +/**************************************************************************** + * LQListInitState + * + * Description: + * This function initializes the state of the quicklist. + * This function cannot fail. + * + * Inputs: + * pLQuickList - Pointer to quicklist object + * + * Outputs: + * None. + * + * Returns: + * None. + * + ****************************************************************************/ +void +LQListInitState( + IN LOCKED_QUICK_LIST* const pLQuickList ); + + +/**************************************************************************** + * LQListInit + * + * Description: + * This function initializes the quicklist. + * + * Inputs: + * pQuickList - Pointer to quicklist object + * + * Outputs: + * None. + * + * Returns: + * TRUE on success + * FALSE otherwise + * + ****************************************************************************/ +boolean +LQListInit( + IN LOCKED_QUICK_LIST* const pLQuickList ); + + +/**************************************************************************** + * LQListDestroy + * + * Description: + * Destroys a list and discards any items on the list without freeing them + * + * Inputs: + * pLQuickList - Pointer to quicklist object + * + * Outputs: + * None + * + * Returns: + * None + * + ****************************************************************************/ +void +LQListDestroy( + IN LOCKED_QUICK_LIST* const pLQuickList ); + +/**************************************************************************** + * LQListAllocateAndInit + * + * Description: + * This function allocates memory for and initializes the state of the + * quicklist. + * + * Inputs: + * IsPageable - + * Tag - + * + * Outputs: + * None. + * + * Returns: + * NULL on error, otherwise pointer to a ready to use List + * + ****************************************************************************/ +LOCKED_QUICK_LIST* +LQListAllocateAndInit( + IN boolean IsPageable, + IN uint32 Tag ); + +/**************************************************************************** + * LQListDeallocate + * + * Description: + * This function destroys the list and deallocates memory for the + * quicklist. + * It does not free items which were on the list + * + * Inputs: + * pLQuickList - Pointer to quicklist object allocated by LQListAllocateAndInit + * if NULL, this function does nothing + * + * Outputs: + * None. + * + * Returns: + * + ****************************************************************************/ +void +LQListDeallocate( + IN LOCKED_QUICK_LIST* const pLQuickList ); + +/**************************************************************************** + * LQListIsEmpty + * + * Description: + * return true if the list is empty + * + * Inputs: + * pLQuickList - Pointer to quicklist object + * + * Outputs: + * None + * + * Returns: + * True if the list is empty + * False otherwise + * + ****************************************************************************/ +static __inline boolean +LQListIsEmpty( + IN LOCKED_QUICK_LIST* const pLQuickList ) +{ + boolean result; + ASSERT(pLQuickList); + SpinLockAcquire(&pLQuickList->m_Lock); + result = QListIsEmpty(&pLQuickList->m_List); + SpinLockRelease(&pLQuickList->m_Lock); + return result; +} + + +/**************************************************************************** + * LQListCount + * + * Description: + * Returns the number of items in the list. This call is not expensive, + * since the QList routines always maintain the count value. + * + * Inputs: + * pSrcList - Pointer to source quicklist object + * + * Outputs: + * None + * + * Returns: + * Number of items in the list + * + ****************************************************************************/ +static __inline uint32 +LQListCount( + IN LOCKED_QUICK_LIST* const pLQuickList ) +{ + uint32 result; + + ASSERT( pLQuickList ); + SpinLockAcquire(&pLQuickList->m_Lock); + result = QListCount(&pLQuickList->m_List); + SpinLockRelease(&pLQuickList->m_Lock); + return result; +} + + +/**************************************************************************** + * LQListIsItemInList + * + * Description: + * Return true if the specified item is in the list + * + * Inputs: + * pLQuickList - Pointer to quicklist object + * pListItem - Pointer to the LIST_ITEM to find + * + * Outputs: + * None + * + * Returns: + * None + * + ****************************************************************************/ +boolean +LQListIsItemInList( + IN LOCKED_QUICK_LIST* const pLQuickList, + IN const LIST_ITEM* const pListItem ); + + +/**************************************************************************** + * LQListInsertHead + * + * Description: + * Add a new item to the head of the list. The caller does not need to + * initialize the LIST_ITEM to be added. + * + * Inputs: + * pLQuickList - Pointer to quicklist object + * pListItem - Pointer to LIST_ITEM to add + * + * Outputs: + * None + * + * Returns: + * None + * + ****************************************************************************/ +static __inline void +LQListInsertHead( + IN LOCKED_QUICK_LIST* const pLQuickList, + IN LIST_ITEM* const pListItem ) +{ + ASSERT( pLQuickList ); + SpinLockAcquire(&pLQuickList->m_Lock); + QListInsertHead(&pLQuickList->m_List, pListItem); + SpinLockRelease(&pLQuickList->m_Lock); +} + + +/**************************************************************************** + * LQListInsertTail + * + * Description: + * Add a new item to the tail of the list. The caller does not need to + * initialize the LIST_ITEM to be added. + * + * Inputs: + * pLQuickList - Pointer to quicklist object + * pListItem - Pointer to LIST_ITEM to add + * + * Outputs: + * None + * + * Returns: + * None + * + ****************************************************************************/ +static __inline void +LQListInsertTail( + IN LOCKED_QUICK_LIST* const pLQuickList, + IN LIST_ITEM* const pListItem ) +{ + ASSERT( pLQuickList ); + SpinLockAcquire(&pLQuickList->m_Lock); + QListInsertTail(&pLQuickList->m_List, pListItem); + SpinLockRelease(&pLQuickList->m_Lock); +} + + +/**************************************************************************** + * LQListInsertPrev + * + * Description: + * Insert an item before the specified item for the given list. + * + * Inputs: + * pLQuickList - Pointer to quicklist object + * pListItem - Pointer to item in the list + * pNewItem - Pointer to item to insert before pListItem + * + * Outputs: + * None + * + * Returns: + * None + * + ****************************************************************************/ +static __inline void +LQListInsertPrev( + IN LOCKED_QUICK_LIST* const pLQuickList, + IN LIST_ITEM* const pListItem, + IN LIST_ITEM* const pNewItem ) +{ + ASSERT( pLQuickList ); + SpinLockAcquire(&pLQuickList->m_Lock); + QListInsertPrev(&pLQuickList->m_List, pListItem, pNewItem); + SpinLockRelease(&pLQuickList->m_Lock); +} + + +/**************************************************************************** + * LQListInsertNext + * + * Description: + * Insert an item after the specified item for the given list. + * + * Inputs: + * pLQuickList - Pointer to quicklist object + * pListItem - Pointer to item in the list + * pNewItem - Pointer to item to insert before pListItem + * + * Outputs: + * None + * + * Returns: + * None + * + ****************************************************************************/ +static __inline void +LQListInsertNext( + IN LOCKED_QUICK_LIST* const pLQuickList, + IN LIST_ITEM* const pListItem, + IN LIST_ITEM* const pNewItem ) +{ + ASSERT( pLQuickList ); + SpinLockAcquire(&pLQuickList->m_Lock); + QListInsertNext(&pLQuickList->m_List, pListItem, pNewItem); + SpinLockRelease(&pLQuickList->m_Lock); +} + + +/* The following functions are not provided for LOCKED_QUICK_LIST since they + * are typically used to iterate the list. + * caller must SpinLockAcquire pLQuickList->m_Lock during iteration of list + * then use QList functions against pLQuickList->m_List + * QListHead, QListTail, QListPrev, QListNext + * + * In some cases (such as emptying a list), functions like LQListRemoveHead + * and LQListRemoveTail may be a better choice + * + * For QListMoveItems, user should instead implement a higher level lock which + * covers the 2 lists involved in which case neither list could be a + * LOCKED_QUICK_LIST. At present there is only 1 use of this function in TSL + */ + +/**************************************************************************** + * LQListRemoveHead + * + * Description: + * Remove an item from the head of a locked list. + * + * Inputs: + * pLQuickList - Pointer to quicklist object + * + * Outputs: + * None + * + * Returns: + * Pointer to LIST_ITEM removed from the list + * + ****************************************************************************/ +static __inline LIST_ITEM* +LQListRemoveHead( + IN LOCKED_QUICK_LIST* const pLQuickList ) +{ + LIST_ITEM *pItem; + + ASSERT( pLQuickList ); + SpinLockAcquire(&pLQuickList->m_Lock); + pItem = QListRemoveHead(&pLQuickList->m_List); + SpinLockRelease(&pLQuickList->m_Lock); + return pItem; +} + + +/**************************************************************************** + * LQListRemoveTail + * + * Description: + * Remove an item from the tail of a list. + * + * Inputs: + * pLQuickList - Pointer to quicklist object + * + * Outputs: + * None + * + * Returns: + * Pointer to LIST_ITEM removed from the list + * + ****************************************************************************/ +static __inline LIST_ITEM* +LQListRemoveTail( + IN LOCKED_QUICK_LIST* const pLQuickList ) +{ + LIST_ITEM *pItem; + + ASSERT( pLQuickList ); + SpinLockAcquire(&pLQuickList->m_Lock); + pItem = QListRemoveTail(&pLQuickList->m_List); + SpinLockRelease(&pLQuickList->m_Lock); + + return pItem; +} + + +/**************************************************************************** + * LQListRemoveItem + * + * Description: + * Removes an item from the specified list. + * + * Inputs: + * pLQuickList - Pointer to quicklist object + * pListItem - Pointer to the list item to remove + * + * Outputs: + * None + * + * Returns: + * None + * + ****************************************************************************/ +static __inline void +LQListRemoveItem( + IN LOCKED_QUICK_LIST* const pLQuickList, + IN LIST_ITEM* const pListItem ) +{ + ASSERT( pLQuickList ); + SpinLockAcquire(&pLQuickList->m_Lock); + QListRemoveItem(&pLQuickList->m_List, pListItem); + SpinLockRelease(&pLQuickList->m_Lock); +} + +/**************************************************************************** + * LQListSafeRemoveItem + * + * Description: + * Removes an item from the specified list only if its in the list + * + * Inputs: + * pLQuickList - Pointer to quicklist object + * pListItem - Pointer to the list item to remove + * + * Outputs: + * None + * + * Returns: + * TRUE - was on list + * FALSE - was not on list + * + ****************************************************************************/ +static __inline boolean +LQListSafeRemoveItem( + IN LOCKED_QUICK_LIST* const pLQuickList, + IN LIST_ITEM* const pListItem ) +{ + boolean result; + ASSERT( pLQuickList ); + SpinLockAcquire(&pLQuickList->m_Lock); + result =QListSafeRemoveItem(&pLQuickList->m_List, pListItem); + SpinLockRelease(&pLQuickList->m_Lock); + return result; +} + + +/**************************************************************************** + * QListRemoveAll + * + * Description: + * Removes all items in the specified list. + * + * Inputs: + * pLQuickList - Pointer to quicklist object + * + * Outputs: + * None + * + * Returns: + * None + * + ****************************************************************************/ +void +LQListRemoveAll( + IN LOCKED_QUICK_LIST* const pLQuickList ); + + +/**************************************************************************** + * LQListInsertArrayHead + * + * Description: + * Insert an array of items to the head of a list. The array pointer passed + * into the function points to the LIST_ITEM in the first element of the + * caller's element array. There is no restriction on where the element is + * stored in the parent structure. + * + * Inputs: + * pLQuickList - Pointer to quicklist object. + * pArray - Pointer to LIST_ITEM of first element in array to add. + * ItemCount - Number of items to add from the array. + * ItemSize - Size of each item in the array. This is the offset from + * LIST_ITEM to LIST_ITEM. + * + * Outputs: + * None + * + * Returns: + * None + * + ****************************************************************************/ +void +LQListInsertArrayHead( + IN LOCKED_QUICK_LIST* const pLQuickList, + IN LIST_ITEM* const pArray, + IN uint32 ItemCount, + IN const uint32 ItemSize ); + + +/**************************************************************************** + * LQListInsertArrayTail + * + * Description: + * Insert an array of items to the tail of a list. The array pointer passed + * into the function points to the LIST_ITEM in the first element of the + * caller's element array. There is no restriction on where the element is + * stored in the parent structure. + * + * Inputs: + * pLQuickList - Pointer to quicklist object. + * pArray - Pointer to LIST_ITEM of first element in array to add. + * ItemCount - Number of items to add from the array. + * ItemSize - Size of each item in the array. This is the offset from + * LIST_ITEM to LIST_ITEM. + * + * Outputs: + * None + * + * Returns: + * None + * + ****************************************************************************/ +void +LQListInsertArrayTail( + IN LOCKED_QUICK_LIST* const pLQuickList, + IN LIST_ITEM* const pArray, + IN uint32 ItemCount, + IN const uint32 ItemSize); + + +/**************************************************************************** + * LQListInsertListHead + * + * Description: + * Add the items in a list to the head of another list. + * + * Inputs: + * pDestList - Pointer to destination quicklist object. + * pSrcList - Pointer to quicklist to add. + * + * Outputs: + * None + * + * Returns: + * None + * + ****************************************************************************/ +void +LQListInsertListHead( + IN LOCKED_QUICK_LIST* const pDestList, + IN LOCKED_QUICK_LIST* const pSrcList ); + + +/**************************************************************************** + * LQListInsertListTail + * + * Description: + * Add the items in a list to the tail of another list. + * + * Inputs: + * pDestList - Pointer to destination quicklist object + * pSrcList - Pointer to quicklist to add + * + * Outputs: + * None + * + * Returns: + * None + * + ****************************************************************************/ +void +LQListInsertListTail( + IN LOCKED_QUICK_LIST * const pDestList, + IN LOCKED_QUICK_LIST * const pSrcList ); + + +/**************************************************************************** + * LQListGetItemAt (OBSOLETE - DO NOT USE) + * + * Description: + * Return the item at the specified offset into the list. 0 is the first item. + * Must be used with care, as due to possible races, there is no guarantee + * that in item is still on list after call completes + * + * Inputs: + * pLQuickList - Pointer to quicklist object + * Index - Offset into list of item to return + * + * Outputs: + * None + * + * Returns: + * LIST_ITEM at specified index + * NULL if item doesn't exist in the list + * + ****************************************************************************/ +/**** OBSOLETE - DO NOT USE FOR NEW CODE!!! */ +LIST_ITEM* +LQListGetItemAt( + IN LOCKED_QUICK_LIST* const pLQuickList, + IN uint32 Index ); + +/**** Define for backward compatibility. */ +/**** OBSOLETE - DO NOT USE FOR NEW CODE!!! */ +#define LQListFindItem LQListFindFromHead + + +/**************************************************************************** + * LQListFindFromHead + * + * Description: + * Use the specified function to search for an item starting at the head of + * a list. Returns the item if found, otherwise NULL. If the user does not + * provide a compare function, then the pObject pointer in each LIST_ITEM is + * compared with the specified Context. + * List Lock will be held while function is called + * Must be used with care, as due to possible races, there is no guarantee + * that in item is still on list after call completes + * + * Inputs: + * pLQuickList - Pointer to quicklist object + * pfnFunc - User supplied compare function + * Context - Context for compare function, or compare value if pfnFunc + * is NULL. + * + * Outputs: + * None + * + * Returns: + * Pointer to LIST_ITEM if found. + * NULL otherwise + * + ****************************************************************************/ +LIST_ITEM* +LQListFindFromHead( + IN LOCKED_QUICK_LIST* const pLQuickList, + IN QLIST_FIND_FUNC pfnFunc OPTIONAL, + IN void* const Context ); + + +/**************************************************************************** + * LQListFindFromTail + * + * Description: + * Use the specified function to search for an item starting at the tail of + * a list. Returns the item if found, otherwise NULL. If the user does not + * provide a compare function, then the pObject pointer in each LIST_ITEM is + * compared with the specified Context. + * List Lock will be held while function is called + * Must be used with care, as due to possible races, there is no guarantee + * that in item is still on list after call completes + * + * Inputs: + * pLQuickList - Pointer to quicklist object + * pfnFunc - User supplied compare function + * Context - Context for compare function, or compare value if pfnFunc + * is NULL. + * + * Outputs: + * None + * + * Returns: + * Pointer to LIST_ITEM if found. + * NULL otherwise + * + ****************************************************************************/ +LIST_ITEM* +LQListFindFromTail( + IN LOCKED_QUICK_LIST* const pLQuickList, + IN QLIST_FIND_FUNC pfnFunc OPTIONAL, + IN void* const Context ); + + +/**************************************************************************** + * LQListFindFromHeadAndRemove + * + * Description: + * Use the specified function to search for an item starting at the head of + * a list. Returns the item if found, otherwise NULL. If the user does not + * provide a compare function, then the pObject pointer in each LIST_ITEM is + * compared with the specified Context. + * If item is found on list, it will be removed from the list + * List Lock will be held while function is called + * + * Inputs: + * pLQuickList - Pointer to quicklist object + * pfnFunc - User supplied compare function + * Context - Context for compare function, or compare value if pfnFunc + * is NULL. + * + * Outputs: + * None + * + * Returns: + * Pointer to LIST_ITEM if found. + * NULL otherwise + * + ****************************************************************************/ +LIST_ITEM* +LQListFindFromHeadAndRemove( + IN LOCKED_QUICK_LIST* const pLQuickList, + IN QLIST_FIND_FUNC pfnFunc OPTIONAL, + IN void* const Context ); + + +/**************************************************************************** + * LQListFindFromTailAndRemove + * + * Description: + * Use the specified function to search for an item starting at the tail of + * a list. Returns the item if found, otherwise NULL. If the user does not + * provide a compare function, then the pObject pointer in each LIST_ITEM is + * compared with the specified Context. + * If item is found on list, it will be removed from the list + * List Lock will be held while function is called + * + * Inputs: + * pLQuickList - Pointer to quicklist object + * pfnFunc - User supplied compare function + * Context - Context for compare function, or compare value if pfnFunc + * is NULL. + * + * Outputs: + * None + * + * Returns: + * Pointer to LIST_ITEM if found. + * NULL otherwise + * + ****************************************************************************/ +LIST_ITEM* +LQListFindFromTailAndRemove( + IN LOCKED_QUICK_LIST* const pLQuickList, + IN QLIST_FIND_FUNC pfnFunc OPTIONAL, + IN void* const Context ); + +/**************************************************************************** + * LQListApplyFunc + * + * Description: + * Call the specified function for each item in the list. + * List Lock will be held while function is called + * + * Inputs: + * pLQuickList - Pointer to quicklist object + * pfnFunc - User supplied function + * Context - Context for function + * + * Outputs: + * None + * + * Returns: + * None + * + ****************************************************************************/ +void +LQListApplyFunc( + IN LOCKED_QUICK_LIST* const pLQuickList, + IN QLIST_APPLY_FUNC pfnFunc, + IN void* const Context ); + + +/**************************************************************************** + **************************************************************************** + *********** ********** + *********** DECLARATION OF DLIST ********** + *********** ********** + **************************************************************************** + ****************************************************************************/ + + +/* Private function to grow the pool if internal LIST_ITEMs. + * Users should not call this function. + */ +void +FreeItemPoolGrow( + IN DLIST* const pList ); + + + +/* + * Private functions to retrieves or create a LIST_ITEMs for use with + * the list. + */ +static __inline LIST_ITEM* +FreeItemGet( + IN DLIST* const pList ) +{ + /* Check for the availability of "LIST_ITEMs" in the free list. */ + if( !QListCount( &pList->m_FreeItemList ) ) + { + /* We're out. Create new items. */ + FreeItemPoolGrow( pList ); + } + + return QListRemoveHead( &pList->m_FreeItemList ); +} + + +/**************************************************************************** + * ListInitState + * + * Description: + * Initialize the state of the DLIST. This function does not fail. + * This should be the first function called for a DLIST. + * + * Inputs: + * pList - Pointer to DLIST object + * + * Outputs: + * None + * + * Returns: + * None + * + ****************************************************************************/ +void +ListInitState( + IN DLIST* const pList ); + + +/**************************************************************************** + * ListInit + * + * Description: + * Initialize the the DLIST. The list will always be able to store MinItems + * items. + * + * Inputs: + * pList - Pointer to DLIST object + * MinItems - The minimum number of items to support in the DLIST. If the + * number of items in the DLIST exceeds this number, + * the DLIST allocates more items automatically. + * + * Outputs: + * None + * + * Returns: + * TRUE on success + * FALSE otherwise + * + ****************************************************************************/ +boolean +ListInit( + IN DLIST* const pList, + IN const uint32 MinItems ); + + +/**************************************************************************** + * ListDestroy + * + * Description: + * Deallocate all internal memory used by the DLIST. + * This function does not fail. + * + * Inputs: + * pList - Pointer to DLIST object + * + * Outputs: + * None + * + * Returns: + * None + * + ****************************************************************************/ +void +ListDestroy( + IN DLIST* const pList ); + + +/**************************************************************************** + * ListIsEmpty + * + * Description: + * Return true if the DLIST is empty. + * + * Inputs: + * pList - Pointer to DLIST object + * + * Outputs: + * None + * + * Returns: + * TRUE if the DLIST is empty + * FALSE otherwise + * + ****************************************************************************/ +static __inline boolean +ListIsEmpty( + IN const DLIST* const pList ) +{ + ASSERT( pList ); + return( QListIsEmpty( &pList->m_List ) ); +} + + +/**************************************************************************** + * ListCount + * + * Description: + * Returns the number of items in the DLIST. + * + * Inputs: + * pList - Pointer to DLIST object + * + * Outputs: + * None + * + * Returns: + * Number of items in the list. + * + ****************************************************************************/ +static __inline uint32 +ListCount( + IN const DLIST* const pList ) +{ + ASSERT( pList ); + return QListCount( &pList->m_List ); +} + + + + +/**************************************************************************** + * ListInsertHead + * + * Description: + * Insert a new item at the head of the list. + * + * Inputs: + * pList - Pointer to DLIST object + * pObject - Pointer to user's object to insert into the list + * + * Outputs: + * None + * + * Returns: + * TRUE on success + * FALSE otherwise + * + ****************************************************************************/ +static __inline boolean +ListInsertHead( + IN DLIST* const pList, + IN void* const pObject ) +{ + LIST_ITEM *pListItem; + + ASSERT( pList); + /* Get a LIST_ITEM to add to the list. */ + if( (pListItem = FreeItemGet( pList )) == NULL ) + return FALSE; + + pListItem->pObject = pObject; + QListInsertHead( &pList->m_List, pListItem ); + return TRUE; +} + + +/**************************************************************************** + * ListInsertTail + * + * Description: + * Insert a new item at the tail of the list. + * + * Inputs: + * pList - Pointer to DLIST object + * pObject - Pointer to user's object to insert into the list + * + * Outputs: + * None + * + * Returns: + * TRUE on success + * FALSE otherwise + * + ****************************************************************************/ +static __inline boolean +ListInsertTail( + IN DLIST* const pList, + IN void* const pObject ) +{ + LIST_ITEM *pListItem; + + ASSERT( pList ); + /* Get a LIST_ITEM to add to the list. */ + if( (pListItem = FreeItemGet( pList )) == NULL ) + return FALSE; + + pListItem->pObject = pObject; + QListInsertTail( &pList->m_List, pListItem ); + return TRUE; +} + + +/**************************************************************************** + * ListInsertPrev + * + * Description: + * Insert a new item before the specified item for the given list. + * + * Inputs: + * pList - Pointer to list object + * Iterator - LIST_ITERATOR to item in the list + * pObject - Pointer to user's object to insert into the list + * + * Outputs: + * None + * + * Returns: + * TRUE on success + * FALSE otherwise + * + ****************************************************************************/ +static __inline boolean +ListInsertPrev( + IN DLIST* const pList, + IN LIST_ITERATOR const Iterator, + IN void* const pObject ) +{ + LIST_ITEM *pNewItem; + + ASSERT( pList); + /* Get a LIST_ITEM to add to the list. */ + if( (pNewItem = FreeItemGet( pList )) == NULL ) + return FALSE; + + pNewItem->pObject = pObject; + QListInsertPrev( &pList->m_List, + (LIST_ITEM*)Iterator , pNewItem ); + return TRUE; +} + + +/**************************************************************************** + * ListInsertNext + * + * Description: + * Insert a new item after the specified item for the given list. + * + * Inputs: + * pList - Pointer to DLIST object + * Iterator - LIST_ITERATOR to item in the list. + * pObject - Pointer to user's object to insert into the list + * + * Outputs: + * None + * + * Returns: + * TRUE on success + * FALSE otherwise + * + ****************************************************************************/ +static __inline boolean +ListInsertNext( + IN DLIST* const pList, + IN LIST_ITERATOR const Iterator, + IN void* const pObject ) +{ + LIST_ITEM *pNewItem; + + ASSERT( pList); + /* Get a LIST_ITEM to add to the list. */ + if( (pNewItem = FreeItemGet( pList )) == NULL ) + return FALSE; + + pNewItem->pObject = pObject; + /* we have to cast away const here, since we are modifying */ + /* the LIST_ITEM */ + QListInsertNext( &pList->m_List, + (LIST_ITEM*)Iterator , pNewItem ); + return TRUE; +} + + +/**************************************************************************** + * ListObj + * + * Description: + * Return a pointer to the list_elements associated object + * + * Inputs: + * pListItem - pointer to LIST_ITEM + * + * Outputs: + * None + * + * Returns: + * pointer to user object associated with this list_item + * + ****************************************************************************/ +static __inline void* +ListObj( + IN LIST_ITERATOR const Iterator ) +{ + return( ((LIST_ITEM*)Iterator)->pObject ); +} + + +/**************************************************************************** + * ListHead + * + * Description: + * Return a LIST_ITERATOR to the first item in the DLIST. + * + * The LIST_ITERATOR is opaque to the user. To get the user object + * at this element, use ListObj(). + * + * Inputs: + * pList - Pointer to DLIST object + * ListItem - LIST_ITERATOR to item in the list + * + * Outputs: + * None + * + * Returns: + * LIST_ITERATOR to the head of the DLIST + * NULL if the DLIST is empty + * + ****************************************************************************/ +static __inline LIST_ITERATOR +ListHead( + IN const DLIST* const pList ) +{ + ASSERT( pList ); + return( QListHead( &pList->m_List ) ); +} + + +/**************************************************************************** + * ListTail + * + * Description: + * Return a LIST_ITERATOR to the last item in the DLIST. + * + * The LIST_ITERATOR is opaque to the user. To get the user object + * at this element, use ListObj(). + * + * Inputs: + * pList - Pointer to DLIST object + * ListItem - LIST_ITERATOR to item in the list + * + * Outputs: + * None + * + * Returns: + * LIST_ITERATOR to the last item of the DLIST + * NULL if the DLIST is empty + * + ****************************************************************************/ +static __inline LIST_ITERATOR +ListTail( + IN const DLIST* const pList ) +{ + ASSERT( pList ); + return( QListTail( &pList->m_List ) ); +} + + +/**************************************************************************** + * ListPrev + * + * Description: + * Return a LIST_ITERATOR to the item before of the specified element. + * Returns NULL if there is no element before of the specified element. + * + * The LIST_ITERATOR is opaque to the user. To get the user object + * at this element, use ListObj(). + * + * Inputs: + * pList - Pointer to list object + * ListItem - LIST_ITERATOR to item in the list + * + * Outputs: + * None + * + * Returns: + * LIST_ITERATOR to item before the specified item + * + ****************************************************************************/ +static __inline LIST_ITERATOR +ListPrev( + IN const DLIST* const pList, + IN LIST_ITERATOR const Iterator ) +{ + /* sanity checks */ + ASSERT( pList ); + ASSERT( Iterator ); + return( QListPrev( &pList->m_List, (LIST_ITEM*)Iterator ) ); +} + + +/**************************************************************************** + * ListNext + * + * Description: + * Return a LIST_ITERATOR to the item after the specified element. + * Returns NULL if there is no element after of the specified element. + * + * The LIST_ITERATOR is opaque to the user. To get the user object + * at this element, use ListObj(). + * + * Inputs: + * pList - Pointer to DLIST object + * ListItem - LIST_ITERATOR to item in the list + * + * Outputs: + * None + * + * Returns: + * LIST_ITERATOR to item before the specified item + * + ****************************************************************************/ +static __inline LIST_ITERATOR +ListNext( + IN const DLIST* const pList, + IN LIST_ITERATOR const Iterator ) +{ + /* sanity checks */ + ASSERT( pList ); + ASSERT( Iterator ); + return( QListNext( &pList->m_List, (LIST_ITEM*)Iterator ) ); +} + + +/**************************************************************************** + * ListRemoveHead + * + * Description: + * Remove the item at the head of the list and return the pointer to + * its user object. + * + * Inputs: + * pList - Pointer to DLIST object + * + * Outputs: + * None + * + * Returns: + * Pointer to the user object at the head of the list + * NULL if the list is empty + * + ****************************************************************************/ +static __inline void* +ListRemoveHead( + IN DLIST* const pList ) +{ + LIST_ITEM *pListItem; + + ASSERT( pList ); + /* See if the list is empty. */ + /* Get the item at the head of the list. */ + if( (pListItem = QListRemoveHead( &pList->m_List )) == NULL ) + return( NULL ); + + /* Place the LIST_ITEM back into the free list. */ + QListInsertHead( &pList->m_FreeItemList, pListItem ); + + return pListItem->pObject; +} + + +/**************************************************************************** + * ListRemoveTail + * + * Description: + * Remove the item at the tail of the list and return the pointer to + * its user object. + * + * Inputs: + * pList - Pointer to DLIST object + * + * Outputs: + * None + * + * Returns: + * Pointer to the user object at the tail of the list + * NULL if the list is empty + * + ****************************************************************************/ +static __inline void* +ListRemoveTail( + IN DLIST* const pList ) +{ + LIST_ITEM *pListItem; + + ASSERT( pList ); + /* See if the list is empty. */ + /* Get the item at the tail of the list. */ + if( (pListItem = QListRemoveTail( &pList->m_List )) == NULL ) + return( NULL ); + + /* Place the LIST_ITEM back into the free list. */ + QListInsertHead( &pList->m_FreeItemList, pListItem ); + + return pListItem->pObject; +} + + +/**************************************************************************** + * ListRemoveItem + * + * Description: + * Removes the item indicated by the LIST_ITERATOR. + * + * Inputs: + * pList - Pointer to list object + * Iterator - LIST_ITERATOR to the list item to remove. + * + * Outputs: + * None + * + * Returns: + * None + * + ****************************************************************************/ +static __inline void +ListRemoveItem( + IN DLIST* const pList, + IN LIST_ITERATOR const Iterator ) +{ + ASSERT( pList ); + + QListRemoveItem( &pList->m_List, (LIST_ITEM*)Iterator ); + + /* Place the LIST_ITEM back into the free list. */ + QListInsertHead( &pList->m_FreeItemList, (LIST_ITEM*)Iterator ); +} + + + +/**************************************************************************** + * ListRemoveObject + * + * Description: + * Remove the item containing the specified user object from the DLIST. + * + * Inputs: + * pList - Pointer to DLIST object + * pObject - User object pointer (may be NULL) + * + * Outputs: + * None + * + * Returns: + * TRUE if the object was found and removed from the list + * FALSE otherwise + * + ****************************************************************************/ +boolean +ListRemoveObject( + IN DLIST* const pList, + IN void* const pObject ); + + +/**************************************************************************** + * ListRemoveAll + * + * Description: + * Remove all the items in a list. + * + * Inputs: + * pList - Pointer to DLIST object + * + * Outputs: + * None + * + * Returns: + * None + * + ****************************************************************************/ +static __inline void +ListRemoveAll( + IN DLIST* const pList ) +{ + ASSERT( pList ); + + /* Move the whole list of items to the front of the free item list. */ + QListInsertListHead( &pList->m_FreeItemList, &pList->m_List ); +} + + +/**************************************************************************** + * ListInsertArrayHead + * + * Description: + * Insert an array of new items at the head of the DLIST. + * + * Inputs: + * pList - Pointer to DLIST object + * pArray - Pointer to array + * ItemCount - Number of items in the array to insert + * ItemSize - Size (in bytes) of each item in the array + * + * Outputs: + * None + * + * Returns: + * TRUE on success + * FALSE otherwise + * + ****************************************************************************/ +boolean +ListInsertArrayHead( + IN DLIST* const pList, + IN void* const pArray, + IN const uint32 ItemCount, + IN const uint32 ItemSize ); + + +/**************************************************************************** + * ListInsertArrayTail + * + * Description: + * Insert an array of new items at the tail of the DLIST. + * + * Inputs: + * pList - Pointer to DLIST object + * pArray - Pointer to array + * ItemCount - number of items in the array to insert + * ItemSize - Size (in bytes) of each item in the array + * + * Outputs: + * None + * + * Returns: + * TRUE on success + * FALSE otherwise + * + ****************************************************************************/ +boolean +ListInsertArrayTail( + IN DLIST* const pList, + IN void* const pArray, + IN const uint32 ItemCount, + IN const uint32 ItemSize); + + +/**************************************************************************** + * ListIsObjectInList + * + * Description: + * Returns true if the specified user object is in the DLIST. + * + * Inputs: + * pList - Pointer to DLIST object + * pObject - User object pointer + * + * Outputs: + * None + * + * Returns: + * TRUE if the object was found + * FALSE otherwise + * + ****************************************************************************/ +static __inline boolean +ListIsObjectInList( + IN const DLIST* const pList, + IN void* const pObject ) +{ + ASSERT( pList ); + return ((boolean) + (QListFindFromHead( &pList->m_List, NULL, pObject ) != NULL)); +} + +/* Get an item at a specific location in a list. */ +/**** OBSOLETE - DO NOT USE FOR NEW CODE!!! */ +void* +ListGetObjectAt( + IN const DLIST* const pList, + IN const uint32 Index ); + +/**** Define for backward compatibility. */ +/**** OBSOLETE - DO NOT USE FOR NEW CODE!!! */ +#define ListFindObject ListFindFromHead + +/**************************************************************************** + * ListFindFromHead + * + * Description: + * Use the specified function to search for an object, returns the object if + * found, otherwise NULL. The DLIST is not modified. Execution stops if Func + * returns TRUE. + * + * Inputs: + * pList - Pointer to DLIST object + * pfnFunc - Pointer to user's compare function + * Context - User context for compare function (may be NULL) + * + * Outputs: + * None + * + * Returns: + * Pointer to user object for which Func returned TRUE + * NULL otherwise + * + ****************************************************************************/ +void* +ListFindFromHead( + IN const DLIST* const pList, + IN LIST_FIND_FUNC pfnFunc, + IN void* const Context ); + + +/**************************************************************************** + * ListFindFromTail + * + * Description: + * Use the specified function to search for an object starting at the tail of + * a list. Returns the item if found, otherwise NULL. The list is not + * modified. + * + * Inputs: + * pList - Pointer to DLIST object + * pfnFunc - Pointer to user's compare function + * Context - User context for compare function (may be NULL) + * + * Outputs: + * None + * + * Returns: + * Pointer to user object for which Func returned TRUE + * NULL otherwise + * + ****************************************************************************/ +void* +ListFindFromTail( + IN const DLIST* const pList, + IN LIST_FIND_FUNC pfnFunc, + IN void* const Context ); + + +/**************************************************************************** + * ListApplyFunc + * + * Description: + * Calls the given function for all tiems in the list. The list is not + * modified. + * + * Inputs: + * pList - Pointer to DLIST object + * pfnFunc - Pointer to user's compare function + * Context - User context for compare function (may be NULL) + * + * Outputs: + * None + * + * Returns: + * None + * + ****************************************************************************/ +void +ListApplyFunc( + IN const DLIST* const pList, + IN LIST_APPLY_FUNC pfnFunc, + IN void* const Context ); + + +/**************************************************************************** + **************************************************************************** + *********** ********** + *********** DECLARATION OF QUEUE ********** + *********** ********** + **************************************************************************** + ****************************************************************************/ + + + +/* + * Initialize a queue protected by spinlocks. + */ +static __inline void +QueueInitState( + IN QUEUE* const pQueue ) +{ + ListInitState( pQueue ); +} + + +static __inline boolean +QueueInit( + IN QUEUE* const pQueue, + IN const uint32 MinSize ) +{ + ASSERT( pQueue ); + return ListInit( pQueue, MinSize ); +} + + +/* + * Destroy a queue and all memory associated with it. + */ +static __inline void +QueueDestroy( IN QUEUE* const pQueue ) +{ + ASSERT( pQueue ); + ListDestroy( pQueue ); +} + + +/* + * Add a new item to a queue. + */ +static __inline boolean +QueueInsert( IN QUEUE* const pQueue, IN void* pObject ) +{ + ASSERT( pQueue ); + return ListInsertTail( pQueue, pObject ); +} + + +/* + * Inserts an array of items to a queue. + */ +static __inline boolean +QueueInsertArray( + IN QUEUE* const pQueue, + IN void* const pArray, + IN const uint32 ItemCount, + IN const uint32 ItemSize ) +{ + ASSERT( pQueue ); + return ListInsertArrayTail( pQueue, pArray, ItemCount, ItemSize ); +} + + +/* + * Remove an item from a queue. + */ +static __inline void* +QueueRemove( + IN QUEUE* const pQueue ) +{ + ASSERT( pQueue ); + return ListRemoveHead( pQueue ); +} + + +/* + * Remove the specified object from a queue. + */ +static __inline boolean +QueueRemoveObject( + IN QUEUE* const pQueue, + IN void* const pObject ) +{ + ASSERT( pQueue ); + return ListRemoveObject( pQueue, pObject ); +} + + +/* + * Removes all items in the specified queue. + */ +static __inline void +QueueRemoveAll( + IN QUEUE* const pQueue ) +{ + ASSERT( pQueue ); + ListRemoveAll( pQueue ); +} + + +/* + * Returns whether the queue is empty. + */ +static __inline uint32 +QueueCount( + IN const QUEUE* const pQueue ) +{ + ASSERT( pQueue ); + return ListCount( pQueue ); +} + + +/* + * Returns the head object without removing it. + */ +static __inline void* +QueueGetHead( + IN const QUEUE* const pQueue ) +{ + void *Itor; + + ASSERT( pQueue ); + Itor = ListHead( pQueue ); + if( Itor ) + return ListObj( Itor ); + else + return NULL; +} + + +/* + * Calls the given function for all items in the queue. The items are not + * removed from the queue. + */ +static __inline void +QueueApplyFunc( + IN const QUEUE* const pQueue, + IN LIST_APPLY_FUNC Func, + IN void* const Context ) +{ + ASSERT( pQueue ); + ListApplyFunc( pQueue, Func, Context ); +} + + +/**************************************************************************** + **************************************************************************** + *********** ********** + *********** DECLARATION OF STACK ********** + *********** ********** + **************************************************************************** + ****************************************************************************/ + + +/* + * Initialize a stack protected by spinlocks. + */ +static __inline void +StackInitState( + IN STACK* const pStack ) +{ + ListInitState( pStack ); +} + +static __inline boolean +StackInit( + IN STACK* const pStack, + IN const uint32 MinSize ) +{ + ASSERT( pStack ); + return ListInit( pStack, MinSize ); +} + + +/* + * Destroy a stack and all memory associated with it. + */ +static __inline void +StackDestroy( + IN STACK* const pStack ) +{ + ASSERT( pStack ); + ListDestroy( pStack ); +} + + +/* + * Push an object onto the stack. + */ +static __inline boolean +StackPush( + IN STACK* const pStack, + IN void* const pObject ) +{ + ASSERT( pStack ); + return ListInsertHead( pStack, pObject ); +} + + +/* + * Push an array of objects onto a stack. + */ +static __inline boolean +StackPushArray( + IN STACK* const pStack, + IN void* const pArray, + IN const uint32 ItemCount, + IN const uint32 ItemSize ) +{ + ASSERT( pStack ); + return ListInsertArrayHead( pStack, pArray, ItemCount, ItemSize ); +} + + +/* + * Pop an object from a stack. + */ +static __inline void* +StackPop( + IN STACK* const pStack ) +{ + ASSERT( pStack ); + return ListRemoveHead( pStack ); +} + + +/* + * Pops all objects from the specified stack. + */ +static __inline void +StackPopAll( + IN STACK* const pStack ) +{ + ASSERT( pStack ); + ListRemoveAll( pStack ); +} + + +/* + * Returns the number of items on a stack. + */ +static __inline uint32 +StackCount( + IN const STACK* const pStack ) +{ + ASSERT( pStack ); + return ListCount( pStack ); +} + + +/* + * Calls the given function for all items in the stack. The items are not + * removed from the stack. + */ +static __inline void +StackApplyFunc( + IN const STACK* const pStack, + IN LIST_APPLY_FUNC Func, + IN void* const Context ) +{ + ASSERT( pStack ); + ListApplyFunc( pStack, Func, Context ); +} + + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* _IBA_PUBLIC_ILIST_H_ */ diff --git a/IbAccess/Common/Public/imap.c b/IbAccess/Common/Public/imap.c new file mode 100644 index 0000000..e62d464 --- /dev/null +++ b/IbAccess/Common/Public/imap.c @@ -0,0 +1,2065 @@ +/* BEGIN_ICS_COPYRIGHT6 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT6 ****************************************/ +////////////////////////////////////////////////////////////////////////////// +// +// Map +// +// Map is an associative array. By providing a key, the caller can retrieve +// an object from the map. All objects in the map have an associated key, +// as specified by the caller when the object was inserted into the map. +// In addition to random access, the caller can traverse the map much like +// a linked list, either forwards from the first object or backwards from +// the last object. The objects in the map are always traversed in +// order since the nodes are stored sorted. +// +// This implementation of Map uses a balanced binary tree. +// +// There are several states of interest in a balanced binary tree. +// +// There are four cases where a subtree is considered balanced. +// Above each diagram is the balance represented by an integer. +// +// 0 -1 +1 0 +// +// B B A Trivial case: A +// / \ / | +// A C A B +// +// +// +// There are four cases after an insertion where a subtree is considered +// unbalanced: +// +// -2 -2 +2 +2 +// (LL) (LR) (RR) (RL) +// +// C C A A +// / / \ | +// B A B C +// / \ \ / +// A B C B +// +// +// Because the tree is balanced as necessary after every insertion, the four +// cases above are the ONLY four cases of imbalance in the tree. +// +// Each of the above cases must be reblanced to look like: +// +// +// B +// / | +// A C +// +// +// +// +////////////////////////////////////////////////////////////////////////////// + +#include "string.h" +#include "imap.h" +#include "idebug.h" + + +////////////////////////////////////////////////////////////////////////////// +// +// Local function prototypes +// These functions should not be called by users of MAP_RES +// +////////////////////////////////////////////////////////////////////////////// +void MapDoubleRight( IN MAP_ITEM* const ppRoot ); +void MapDoubleLeft( IN MAP_ITEM* const ppRoot ); +MAP_ITEM* MapItorProbeLeft( IN MAP_ITERATOR* const pItor ); +MAP_ITEM* MapItorProbeRight( IN MAP_ITERATOR* const pItor ); +uint32 MapConsoleDumpDepth( IN const MAP_ITEM* const pItem, + IN const uint8 ShowDepth, + IN const uint8 CurrentDepth, + IN uint32 Total ); +void MapConsoleDumpSubtree( IN const MAP_ITEM* const pItem ); + +void MapConsolePad( IN const uint8 ShowDepth, + IN const boolean Leading, + IN const uint32 FudgeFactor, + IN const boolean Dashless ); +boolean MapItorShouldPropogateForDelete( IN MAP_ITERATOR * const pItor ); +MAP_ROTDIR MapItemCheckRot( IN const MAP_ITEM * const pItem ); +boolean MapUpdateDepths( IN MAP_ITEM* const pItem ); +void MapItorWalkBackAndBalance( IN MAP_ITERATOR* const pItor ); +void MapItemExchange( + IN MAP_ITEM* const pOldItem, + IN MAP_ITEM* const pNewItem ); +void MapItorRecursiveBalance( IN MAP_ITERATOR * const pItor ); +void MapItorDeleteLeaf( IN MAP_ITERATOR * const pItor ); +void MapItorDeleteLeftHalfLeaf( IN MAP_ITERATOR * const pItor ); +void MapItorDeleteRightHalfLeaf( IN MAP_ITERATOR * const pItor ); +void MapItemInsertLeft( + IN MAP_ITEM* const pInsertItem, + IN MAP_ITEM* const pAtItem ); +void MapItemInsertRight( + IN MAP_ITEM* const pInsertItem, + IN MAP_ITEM* const pAtItem ); +void +MapItemInit( + IN MAP_ITEM* const pItem, + IN const uint64 Key, + IN const void* const pObj ); +void +MapItorWalkBackAndBalanceToItem( + IN MAP_ITERATOR* const pItor, + IN MAP_ITEM* const pItem ); + +////////////////////////////////////////////////////////////////////////////// +// +// MapInitState +// +// Description: +// Initializes the state of a MAP_RES object. +// +// Inputs: +// pMap - pointer to a MAP_RES +// +// Outputs: +// None +// +// Returns: +// None +// +////////////////////////////////////////////////////////////////////////////// +void +MapInitState( + IN MAP_RES* const pMap ) +{ + ASSERT( pMap ); + + GrowPoolInitState( &pMap->m_Pool ); + MapItemInit( &pMap->m_End, 0, NULL ); + // special setup for the root node + pMap->m_End.m_pUp = &pMap->m_End; + pMap->m_Count = 0; +} + +////////////////////////////////////////////////////////////////////////////// +// +// MapInit +// +// Description: +// Initializes a MAP_RES object. +// This function must be called before using a new MAP_RES. +// +// Inputs: +// pMap - pointer to a MAP_RES +// +// Outputs: +// None +// +// Returns: +// None +// +////////////////////////////////////////////////////////////////////////////// +FSTATUS +MapInit( + IN MAP_RES* const pMap ) +{ + FSTATUS Status; + + MapInitState( pMap ); + pMap->m_DelToggle = FALSE; + Status = GrowPoolInit( &pMap->m_Pool, + MAP_START_SIZE, // minimum number of objects to allocate + sizeof( MAP_ITEM), // size of object + MAP_GROW_SIZE, // minimum number of objects to grow + NULL, // no state initialization needed + NULL, // no initializer needed + NULL, // no destructor needed + NULL ); // no context needed + return Status; +} + +////////////////////////////////////////////////////////////////////////////// +// +// MapDestroy +// +// Description: +// Destroys a MAP_RES object. +// This function must be called when finished with a MAP_RES. +// +// Inputs: +// pMap - pointer to a MAP_RES +// +// Outputs: +// None +// +// Returns: +// None +// +////////////////////////////////////////////////////////////////////////////// +void +MapDestroy( + IN MAP_RES* const pMap ) +{ + MAP_ITERATOR Itor; + MAP_ITEM *pItem; + + // all objects must be returned to the resource pool + // delete leaves until there is nothing left in the map + + if( MapRoot( pMap ) ) + { + pItem = MapItorInit( MapRoot( pMap ), &Itor ); + + while( !MapIsLeaf( pItem ) ) + { + pItem = MapItorProbeLeft( &Itor ); + + do + { + // Because we're deleting from right to left, + // every node we encounter will either be a leaf + // or a left half-leaf. + // Obviously we don't bother with rebalancing. + if( MapItorIsLeaf( &Itor ) ) + { + MapItorDeleteLeaf( &Itor ); + + // return this item to the pool + GrowPoolPut( &pMap->m_Pool, pItem ); + } + + } while( (pItem = MapItorNext( &Itor )) != NULL ); + + pItem = MapItorInit( MapRoot( pMap ), &Itor ); + } + + // now, put the root node itself in the resource pool + // if it hasn't been deleted already + if( MapRoot( pMap ) ) + GrowPoolPut( &pMap->m_Pool, MapRoot( pMap ) ); + } + + GrowPoolDestroy( &pMap->m_Pool ); + pMap->m_Count = 0; + MapSetRoot( pMap, NULL ); +} + + +////////////////////////////////////////////////////////////////////////////// +// +// MapItemInit +// +// Description: +// Initializes a MAP_ITEM object. +// This function must be called before using a new MAP_ITEM. +// This internal function should not be called by users of MAP_RES. +// +// Inputs: +// pItem - pointer to a MAP_ITEM. +// Key - key value associated with this MAP_ITEM. +// pObj - user object associated with theis MAP_ITEM. +// +// Outputs: +// None +// +// Returns: +// None +// +////////////////////////////////////////////////////////////////////////////// +void +MapItemInit( + IN MAP_ITEM * const pItem, + IN const uint64 Key, + IN const void* const pObj ) +{ + pItem->m_Key = Key; + pItem->m_pObj = (void *)pObj; + pItem->m_pLeft = NULL; + pItem->m_pRight = NULL; + pItem->m_pUp = NULL; + MapItemResetBalances( pItem ); +} + + +////////////////////////////////////////////////////////////////////////////// +// +// MapItemGetPtrAbove +// +// Description: +// Returns a pointer to a the pointer that points to the node at +// the Iterator. +// +// Inputs: +// pItor - pointer to a map iterator +// +// Outputs: +// None +// +// Returns: +// pointer to a pointer to the node at the iterator +// +////////////////////////////////////////////////////////////////////////////// +MAP_ITEM** +MapItemGetPtrAbove( + IN MAP_ITEM* const pItem ) +{ + MAP_ITEM *pAbove; + ASSERT(pItem); + pAbove = pItem->m_pUp; + if( pAbove->m_pLeft == pItem ) + return( &pAbove->m_pLeft ); + else + { + ASSERT( pAbove->m_pRight == pItem ); + return( &pAbove->m_pRight ); + } +} + + +////////////////////////////////////////////////////////////////////////////// +// +// MapItemCheckRot +// +// Description: +// Returns the type of rotation, if any, necessary at the given item. +// This internal function should not be called by users of MAP_RES. +// +// Inputs: +// pItem - pointer to a MAP_ITEM +// +// Outputs: +// None +// +// Returns: +// MAP_ROTR - rotate right required +// MAP_ROTDR - rotate double right required +// MAP_ROTL - rotate left required +// MAP_ROTDL - rotate double left required +// MAP_ROTNONE - no rotation required +// MAP_RECURSIVE - recursive rebalance required +// +////////////////////////////////////////////////////////////////////////////// +MAP_ROTDIR +MapItemCheckRot( + IN const MAP_ITEM* const pItem ) +{ +#if MAP_DEBUG + if( pItem->m_DLMax - pItem->m_DRMin > MAP_MAX_MIN_DELTA ) + { + DbgOut("\n\aERROR - DLMax - DRMin > %u for key = 0x%"PRIx64, + MAP_MAX_MIN_DELTA, pItem->m_Key ); + MapConsoleDumpSubtree( pItem ); + ASSERT( FALSE ); + return( MAP_ROTNONE ); + } + if( pItem->m_DRMax - pItem->m_DLMin > MAP_MAX_MIN_DELTA ) + { + DbgOut("\n\aERROR - DRMax - DLMin > %u for key = 0x%"PRIx64, + MAP_MAX_MIN_DELTA, pItem->m_Key ); + MapConsoleDumpSubtree( pItem ); + ASSERT( FALSE ); + return( MAP_ROTNONE ); + } + if( pItem->m_DLMax - pItem->m_DLMin > MAP_MAX_MIN_DELTA - 1 ) + { + DbgOut("\n\aERROR - DLMax - DLMin > %u for key = 0x%"PRIx64, + MAP_MAX_MIN_DELTA - 1, pItem->m_Key ); + MapConsoleDumpSubtree( pItem ); + ASSERT( FALSE ); + return( MAP_ROTNONE ); + } + if( pItem->m_DRMax - pItem->m_DRMin > MAP_MAX_MIN_DELTA - 1 ) + { + DbgOut("\n\aERROR - DRMax - DRMin > %u for key = 0x%"PRIx64, + MAP_MAX_MIN_DELTA - 1, pItem->m_Key ); + MapConsoleDumpSubtree( pItem ); + ASSERT( FALSE ); + return( MAP_ROTNONE ); + } + + // We can never be out of balance on the same side + // since that means a node below is out of balance. + ASSERT( pItem->m_DLMax - pItem->m_DRMin <= MAP_MAX_MIN_DELTA ); + ASSERT( pItem->m_DRMax - pItem->m_DLMin <= MAP_MAX_MIN_DELTA ); + + ASSERT( pItem->m_DLMax - pItem->m_DLMin < MAP_MAX_MIN_DELTA ); + ASSERT( pItem->m_DRMax - pItem->m_DRMin < MAP_MAX_MIN_DELTA ); + +#else + // We can never be out of balance on the same side + // since that means a node below is out of balance. + ASSERT( pItem->m_DLMax - pItem->m_DRMin <= MAP_MAX_MIN_DELTA ); + ASSERT( pItem->m_DRMax - pItem->m_DLMin <= MAP_MAX_MIN_DELTA ); + + ASSERT( pItem->m_DLMax - pItem->m_DLMin < MAP_MAX_MIN_DELTA ); + ASSERT( pItem->m_DRMax - pItem->m_DRMin < MAP_MAX_MIN_DELTA ); +#endif + + if( pItem->m_DLMax - pItem->m_DRMin == MAP_MAX_MIN_DELTA ) + { + // We are heavy left. + // Determine if we need ROTR, ROTDR or RECURSIVE + if(pItem->m_DRMax > MAP_RECURSION_THRESHOLD ) + return MAP_RECURSIVE; + + if( pItem->m_pLeft->m_DLMax > pItem->m_pLeft->m_DRMax ) + return MAP_ROTR; + + return MAP_ROTDR; + } + + if( pItem->m_DRMax - pItem->m_DLMin == MAP_MAX_MIN_DELTA ) + { + // We are heavy right. + // Determine if we need ROTL, ROTDL or RECURSIVE + if(pItem->m_DLMax > MAP_RECURSION_THRESHOLD ) + return MAP_RECURSIVE; + + if( pItem->m_pRight->m_DRMax > pItem->m_pRight->m_DLMax ) + return MAP_ROTL; + + return MAP_ROTDL; + } + + return MAP_ROTNONE; +} + +////////////////////////////////////////////////////////////////////////////// +// +// MapGet +// +// Description: +// Retrieves the user object for the specified key. +// +// Inputs: +// pMap - pointer to a MAP_RES +// Key - 64-bit user key value to search for +// +// Outputs: +// None +// +// Returns: +// Pointer to the user item +// NULL if not found +// +////////////////////////////////////////////////////////////////////////////// +void* +MapGet( + IN const MAP_RES* const pMap, + IN const uint64 Key ) +{ + MAP_ITEM *pItem; + + ASSERT( pMap ); + + pItem = MapRoot( pMap ); + + while( pItem != NULL ) + { + if( Key < pItem->m_Key ) + pItem = pItem->m_pLeft; // too small + else + if( Key > pItem->m_Key ) + pItem = pItem->m_pRight; // too big + else + return pItem->m_pObj; // just right + } + + // could not find a match + return NULL; +} + +////////////////////////////////////////////////////////////////////////////// +// +// MapItorInit +// +// Description: +// Sets an iterator to the specified node of a tree. +// This is an internal function and should not be called by user's of map. +// +// Inputs: +// pItem - pointer to MAP_ITEM (may be NULL) +// pItor - pointer to a MAP_ITERATOR +// +// Outputs: +// None +// +// Returns: +// Pointer to the input MAP_ITEM +// +////////////////////////////////////////////////////////////////////////////// +MAP_ITEM* +MapItorInit( + IN MAP_ITEM* const pItem, + IN MAP_ITERATOR * const pItor ) +{ + ASSERT( pItor ); + pItor->pItem = pItem; + return( pItem ); +} + + +////////////////////////////////////////////////////////////////////////////// +// +// MapItorGet +// +// Description: +// Set the specified iterator to the item with the specified key. +// This internal function should not be called by users of MAP_RES. +// +// Inputs: +// pMap - pointer to a MAP_RES object +// pItor - pointer to a MAP_ITERATOR object +// Key - Key of new object to seek +// +// Outputs: +// None +// +// Returns: +// pItem of the object if found +// NULL otherwise +// +////////////////////////////////////////////////////////////////////////////// +MAP_ITEM* +MapItorGet( + IN const MAP_RES * const pMap, + IN MAP_ITERATOR * const pItor, + IN const uint64 Key ) +{ + MAP_ITEM *pItem; + + ASSERT( pMap ); + ASSERT( pItor ); + + pItem = MapRoot( pMap ); + + while( pItem != NULL ) + { + if( Key < pItem->m_Key ) + pItem = pItem->m_pLeft; // too small + else + if( Key > pItem->m_Key ) + pItem = pItem->m_pRight; // too big + else + { + MapItorInit( pItem, pItor ); + return( pItem ); // just right + } + } + + // couldn't find an item with the specified key + pItor->pItem = NULL; + return NULL; +} + + +////////////////////////////////////////////////////////////////////////////// +// +// MapItorBalance +// +// Description: +// Balances the tree at the node pointed to by the iterator. +// +// Inputs: +// pItor - pointer to a MAP_ITERATOR object +// +// Outputs: +// None +// +// Returns: +// TRUE if a rebalance occurred. +// FALSE otherwise +// +////////////////////////////////////////////////////////////////////////////// +boolean +MapItorBalance( + IN MAP_ITERATOR* const pItor ) +{ + switch( MapItemCheckRot( pItor->pItem ) ) + { + case MAP_ROTL: + MapRotLeft( pItor->pItem ); // Fix +2 RR + break; + + case MAP_ROTDL: + MapDoubleLeft( pItor->pItem ); // Fix +2 RL or +2 R0 + break; + + case MAP_ROTDR: + MapDoubleRight( pItor->pItem ); // Fix -2 LR or -2 L0 + break; + + case MAP_ROTR: + MapRotRight( pItor->pItem ); // Fix -2 LL + break; + + case MAP_RECURSIVE: + // no rotation available capable for fixing this mess + MapItorRecursiveBalance( pItor ); + break; + + default: + // no rebalance necessary + return( FALSE ); + } + + return( TRUE ); +} + +////////////////////////////////////////////////////////////////////////////// +// +// MapItorRecursiveBalance +// +// Description: +// Balances the tree at the node pointed to by the iterator. +// This algorithm recursively calls MapItorWalkBackAndBalance. +// This function should be used for unbalanced nodes with +// more children than can be accomodated with the simple rotation +// primitives. +// This internal function should not be called by users of MAP_RES. +// +// Inputs: +// pItor - pointer to a MAP_ITERATOR object +// ppRoot - pointer to a pointer to the node at the iterator +// +// Outputs: +// None +// +// Returns: +// None +// +////////////////////////////////////////////////////////////////////////////// +void +MapItorRecursiveBalance( + IN MAP_ITERATOR* const pItor ) +{ + MAP_ITEM *pOldRoot; + MAP_ITEM *pNewRoot; + MAP_ITEM *pInsertPoint; + MAP_ITERATOR HeavyItor; + MAP_ITERATOR LightItor; + + pOldRoot = pItor->pItem; +#if MAP_DEBUG > 1 + DbgOut("\nRecursively balancing at key = 0x%X", pOldRoot->m_Key ); + DbgOut("\nBefore:"); + MapConsoleDumpSubtree( pOldRoot ); +#endif + + // Prepare some iterators for balancing the heavy and light subtrees. + MapItorInit( pOldRoot, &HeavyItor ); + MapItorInit( pOldRoot, &LightItor ); + + if( pOldRoot->m_DLMax - pOldRoot->m_DRMin == MAP_MAX_MIN_DELTA ) + { + // We are heavy left. + // The new root will be the rightmost node in the left subtree. + // Traverse to the this new root and remove it from the subtree. + MapItorLeft( &HeavyItor ); + pNewRoot = MapItorProbeRight( &HeavyItor ); + MapItorDeleteRightHalfLeaf( &HeavyItor ); + + // install the new root + MapItemExchange( pOldRoot, pNewRoot ); + + // Now, insert the old root at the leftmost point in + // the right subtree. + MapItorRight( &LightItor ); + pInsertPoint = MapItorProbeLeft( &LightItor ); + MapItemInsertLeft( pOldRoot, pInsertPoint ); + } + else + { + ASSERT( pOldRoot->m_DRMax - pOldRoot->m_DLMin == MAP_MAX_MIN_DELTA ); + // We are heavy right. + // The new root will be the rightmost node in the left subtree. + // Traverse to the this new root and remove it from the subtree. + MapItorRight( &HeavyItor ); + pNewRoot = MapItorProbeLeft( &HeavyItor ); + MapItorDeleteLeftHalfLeaf( &HeavyItor ); + + // install the new root + MapItemExchange( pOldRoot, pNewRoot ); + + // Now, insert the old root at the leftmost point in + // the right subtree. + MapItorLeft( &LightItor ); + pInsertPoint = MapItorProbeRight( &LightItor ); + MapItemInsertRight( pOldRoot, pInsertPoint ); + } + + // Now, the new tree is complete, but still unbalanced +#if MAP_DEBUG > 2 + DbgOut("\nAfter reposition, before heavy rebalance at key = 0x%X", + pNewRoot->m_Key ); + DbgOut("\nAfter:"); + MapConsoleDumpSubtree( pNewRoot ); +#endif + + MapItorWalkBackAndBalanceToItem( &HeavyItor, pNewRoot ); +#if MAP_DEBUG > 2 + DbgOut("\nBefore light rebalance, after heavy rebalance at key = 0x%X", + pNewRoot->m_Key ); + DbgOut("\nAfter:"); + MapConsoleDumpSubtree( pNewRoot ); +#endif + MapItorWalkBackAndBalanceToItem( &LightItor, pNewRoot ); + // don't balance above the new root! + // the new root is the last node we need to leave in a + // balanced state + // The function above leave LightItor at the new root + MapUpdateDepthsNoCheck( pNewRoot ); + + ASSERT( LightItor.pItem == pNewRoot ); + + MapItorBalance( &LightItor ); +#if MAP_DEBUG > 1 + DbgOut("\nDone recursively balancing at key = 0x%X", pNewRoot->m_Key ); + DbgOut("\nAfter:"); + MapConsoleDumpSubtree( pNewRoot ); +#endif +} + +////////////////////////////////////////////////////////////////////////////// +// +// MapItemExchange +// +// Description: +// Replaces a MAP_ITEM with another MAP_ITEM +// +// Inputs: +// pItor - pointer to an initialized MAP_ITERATOR +// pItem - pointer to a new MAP_ITEM to insert +// +// Outputs: +// None +// +// Returns: +// None +// +////////////////////////////////////////////////////////////////////////////// +void +MapItemExchange( + IN MAP_ITEM* const pOldItem, + IN MAP_ITEM* const pNewItem ) +{ + if ( NULL == pOldItem ) { + ASSERT( FALSE ); + return; + } + + if ( NULL == pNewItem ) { + ASSERT( FALSE ); + return; + } + + *MapItemGetPtrAbove( pOldItem ) = pNewItem; + + pNewItem->m_pLeft = pOldItem->m_pLeft; + pNewItem->m_pRight = pOldItem->m_pRight; + pNewItem->m_pUp = pOldItem->m_pUp; + + if( pNewItem->m_pLeft ) + pNewItem->m_pLeft->m_pUp = pNewItem; + if( pNewItem->m_pRight ) + pNewItem->m_pRight->m_pUp = pNewItem; +} + +////////////////////////////////////////////////////////////////////////////// +// +// MapItemInsertLeft +// +// Description: +// Replaces a MAP_ITEM with another MAP_ITEM +// +// Inputs: +// +// Outputs: +// None +// +// Returns: +// +////////////////////////////////////////////////////////////////////////////// +void +MapItemInsertLeft( + IN MAP_ITEM* const pInsertItem, + IN MAP_ITEM* const pAtItem ) +{ + if ( NULL == pAtItem ) { + ASSERT( FALSE ); + return; + } + ASSERT( pAtItem->m_pLeft == NULL ); + + pInsertItem->m_pRight = NULL; + pInsertItem->m_pLeft = NULL; + pInsertItem->m_pUp = pAtItem; + pAtItem->m_pLeft = pInsertItem; + MapItemResetBalances( pInsertItem ); +} + + +////////////////////////////////////////////////////////////////////////////// +// +// MapItemInsertRight +// +// Description: +// Replaces a MAP_ITEM with another MAP_ITEM +// +// Inputs: +// +// Outputs: +// None +// +// Returns: +// +////////////////////////////////////////////////////////////////////////////// +void +MapItemInsertRight( + IN MAP_ITEM* const pInsertItem, + IN MAP_ITEM* const pAtItem ) +{ + if ( NULL == pAtItem ) { + ASSERT( FALSE ); + return; + } + ASSERT( pAtItem->m_pRight == NULL ); + pInsertItem->m_pRight = NULL; + pInsertItem->m_pLeft = NULL; + pInsertItem->m_pUp = pAtItem; + pAtItem->m_pRight = pInsertItem; + MapItemResetBalances( pInsertItem ); +} + +////////////////////////////////////////////////////////////////////////////// +// +// MapItorInsert +// +// Description: +// Insert an object into a MAP_RES. An error is returned if the specified +// key already exists in the map. +// +// Inputs: +// pItor - pointer to an initialized MAP_ITERATOR +// pItem - pointer to a new MAP_ITEM to insert +// +// Outputs: +// None +// +// Returns: +// FSUCCESS +// FDUPLICATE - object with the specified key already exists in the map +// +////////////////////////////////////////////////////////////////////////////// +FSTATUS +MapItorInsert( + IN MAP_ITERATOR* const pItor, + IN MAP_ITEM* const pItem ) +{ + uint64 Key; + + ASSERT( pItor ); + ASSERT( pItem ); + + Key = pItem->m_Key; + + while( TRUE ) + { + if( Key < pItor->pItem->m_Key ) + { + // The new key is too small. + // Traverse left if possible, otherwise, insert the new item + // and leave the loop + if( pItor->pItem->m_pLeft != NULL ) + MapItorLeft( pItor ); + else + { + MapItemInsertLeft( pItem, pItor->pItem ); + return FSUCCESS; + } + } + else + { + if( Key > pItor->pItem->m_Key ) + { + // The new key is too large - mirror image of process above + if( pItor->pItem->m_pRight != NULL ) + MapItorRight( pItor ); + else + { + MapItemInsertRight( pItem, pItor->pItem ); + return FSUCCESS; + } + } + else + return( FDUPLICATE ); // Key already in the map! + } + } +} + +////////////////////////////////////////////////////////////////////////////// +// +// MapItorWalkBackAndBalance +// +// Description: +// Walks the current iterator back to the root of the MAP_RES. +// Along the way, recompute depth information and rebalance as necessary. +// +// Inputs: +// pItor - pointer to an initialized MAP_ITERATOR +// +// Outputs: +// None +// +// Returns: +// FSUCCESS +// FDUPLICATE - object with the specified key already exists in the map +// +////////////////////////////////////////////////////////////////////////////// +void +MapItorWalkBackAndBalance( + IN MAP_ITERATOR* const pItor ) +{ + ASSERT( pItor ); + + // special case if we're on a leaf + // this prevents early short circuit in loop below + if( MapIsLeaf( pItor->pItem ) ) + { + MapItemResetBalances( pItor->pItem ); + MapItorUp( pItor ); + } + + do + { + // If the depth of a given node does not change + // then none of the nodes above will change. + // Thus, we can take a short-circuit exit here. + + MapUpdateDepthsNoCheck( pItor->pItem ); + +/* + if( !MapUpdateDepths( pItor->pItem ) ) + return; +*/ + + + // balance as necessary + // if a balance occurs, the new root is guaranteed to be balanced + // so move the iterator up to prevent false negative on the + // updatedepths call above + if( MapItorBalance( pItor ) ) + MapItorUp( pItor ); + + // go up one level and check if we're done + } while( !MapItorAtRoot( MapItorUp( pItor ) ) ); +} + +////////////////////////////////////////////////////////////////////////////// +// +// MapItorWalkBackAndBalance +// +// Description: +// Walks the current iterator back to the root of the MAP_RES. +// Along the way, recompute depth information and rebalance as necessary. +// +// Inputs: +// pItor - pointer to an initialized MAP_ITERATOR +// +// Outputs: +// None +// +// Returns: +// FSUCCESS +// FDUPLICATE - object with the specified key already exists in the map +// +////////////////////////////////////////////////////////////////////////////// +void +MapItorWalkBackAndBalanceToItem( + IN MAP_ITERATOR* const pItor, + IN MAP_ITEM* const pItem ) +{ + ASSERT( pItor ); + ASSERT( pItor->pItem != pItem ); + + // special case if we're on a leaf + // this prevents early short circuit in loop below + if( MapIsLeaf( pItor->pItem ) ) + { + MapItemResetBalances( pItor->pItem ); + MapItorUp( pItor ); + } + + do + { + // If the depth of a given node does not change + // then none of the nodes above will change. + // Thus, we can take a short-circuit exit here. + +/* + if( !MapUpdateDepths( pItor->pItem ) ) + return; +*/ + + MapUpdateDepthsNoCheck( pItor->pItem ); + + // balance as necessary + // if a balance occurs, the new root is guaranteed to be balanced + // so move the iterator up to prevent false negative on the + // updatedepths call above + if( MapItorBalance( pItor ) ) + MapItorUp( pItor ); + + // go up one level and check if we're done + } while( MapItorUp( pItor )->pItem != pItem ); +} + + +////////////////////////////////////////////////////////////////////////////// +// +// MapInsert +// +// Description: +// Insert an object into the map. An error is returned if the specified +// key already exists in the map. +// +// Inputs: +// pMap - pointer to a MAP_RES object +// Key - Key of new object to insert +// pObj - pointer to user object to insert into the map +// +// Outputs: +// None +// +// Returns: +// FSUCCESS +// FDUPLICATE - object with the specified key already exists in the map +// FINSUFFICIENT_MEMORY +// +////////////////////////////////////////////////////////////////////////////// +FSTATUS +MapInsert( + IN MAP_RES* const pMap, + IN const uint64 Key, + IN const void* const pObj ) +{ + MAP_ITEM *pNew; + MAP_ITERATOR Itor; + FSTATUS Status; + + ASSERT( pMap ); + + // acquire an empty map item for this new element + // then, initialize its key and object + pNew = (MAP_ITEM *)GrowPoolGet( &pMap->m_Pool ); + if( pNew == NULL ) + return FINSUFFICIENT_MEMORY; + + MapItemInit( pNew, Key, pObj ); + + if( MapRoot( pMap ) == NULL ) + { + // this is the first element in the tree + MapSetRoot( pMap, pNew ); + pMap->m_Count++; + return FSUCCESS; + } + + MapItorInit( MapRoot( pMap ), &Itor ); + + // After the insert, the iterator points to the parent + // of the new node. + Status = MapItorInsert( &Itor, pNew ); + if( Status != FSUCCESS ) + { + // don't leak + GrowPoolPut( &pMap->m_Pool, pNew ); + return Status; + } + + // we successfully added an item to the tree + pMap->m_Count++; + + // + // We have added depth to this section of the tree. + // Rebalance as necessary as we + // retrace our path through the tree and update balances. + // + MapItorWalkBackAndBalance( &Itor ); + + return FSUCCESS; +} + +////////////////////////////////////////////////////////////////////////////// +// +// MapRemove +// +// Description: +// Remove the node with the specified key. +// +// Inputs: +// pMap - pointer to a MAP_RES object +// Key - Key of new object to insert +// pObj - pointer to user object to insert into the map +// +// Outputs: +// None +// +// Returns: +// FSUCCESS +// FNOT_FOUND - the specified key does not exist in the map +// +////////////////////////////////////////////////////////////////////////////// +FSTATUS +MapRemove( + IN MAP_RES* const pMap, + IN const uint64 Key ) +{ + MAP_ITEM *pItem; + MAP_ITEM *pSubsItem; + MAP_ITERATOR RootItor; + + ASSERT( pMap ); + + // + // Phase One: + // Seek the node with the specified key + // + pItem = MapItorGet( pMap, &RootItor, Key ); + + if( pItem == NULL ) + return FNOT_FOUND; + + // + // maybe we're lucky and the deleted node is a leaf + // + if( MapIsLeaf( pItem ) ) + { + // yes, the node is a leaf + MapItorDeleteLeaf( &RootItor ); + + // return the deleted node to the pool + GrowPoolPut( &pMap->m_Pool, pItem ); + } + else + { + // + // This item is not a leaf. + // Use the DeleteToggle to decide from which side + // we'll take the substitude node to replace the deleted node. + // I'm speculating that toggling is more effecient that an + // exhaustive analysis to determine which side is the best + // choice from which to take the substitute leaf. By choosing + // arbitrarily, we have a better than 50% chance of being right, + // since ties go in our favor. + // + if( pItem->m_pRight != NULL ) + { + if( pItem->m_pLeft != NULL ) + { + if( pMap->m_DelToggle ) + { + // we're going to take node from the right subtree + pMap->m_DelToggle = (boolean)(!pMap->m_DelToggle); + MapItorRight( &RootItor ); // step right + pSubsItem = MapItorProbeLeft( &RootItor ); // probe left + MapItorDeleteLeftHalfLeaf( &RootItor ); + } + else + { + // we're going to take node from the left subtree + pMap->m_DelToggle = (boolean)(!pMap->m_DelToggle); + MapItorLeft( &RootItor ); // step left + pSubsItem = MapItorProbeRight( &RootItor ); // probe right + MapItorDeleteRightHalfLeaf( &RootItor ); + } + } + else + { + // left subtree is NULL + // we must take node from the right subtree + pSubsItem = MapItorRight( &RootItor ); +#if MAP_MAX_MIN_DELTA < 3 + MapItorDeleteLeaf( &RootItor ); +#else + pSubsItem = MapItorProbeLeft( &RootItor ); // probe left + MapItorDeleteLeftHalfLeaf( &RootItor ); +#endif + } + } + else + { + // Right subtree is NULL + // we must take node from the left subtree + pSubsItem = MapItorLeft( &RootItor ); +#if MAP_MAX_MIN_DELTA < 3 + MapItorDeleteLeaf( &RootItor ); +#else + pSubsItem = MapItorProbeRight( &RootItor ); // probe right + MapItorDeleteRightHalfLeaf( &RootItor ); +#endif + } + + // + // Phase Three: + // We have identified the node to be deleted and the + // node that will replace it. Now, substitute the replacement + // for the deleted item. + // Note that the balance of the node may change from + // the original node, but that gets taken care of later. + // + MapItemExchange( pItem, pSubsItem ); + + if( RootItor.pItem == pItem ) + MapItorInit( pSubsItem, &RootItor ); + + // return the deleted node to the pool + GrowPoolPut( &pMap->m_Pool, pItem ); + } + + // we have successfully deleted the node + if( --pMap->m_Count == 0 ) + { + // there is nothing left in the tree! + MapSetRoot( pMap, NULL ); + return FSUCCESS; + } + + // + // Phase Four: + // The new tree is intact but possibly unbalanced. + // We have removed depth from this section of the tree + // Retrace our path through the tree and update balances. + // + MapItorWalkBackAndBalance( &RootItor ); + return FSUCCESS; +} + +////////////////////////////////////////////////////////////////////////////// +// +// MapDoubleRight +// +// Description: +// Double-rotate the subtree pointed to by *ppRoot to the right. +// This transform can rebalance a -2 LR. +// This internal function should not be called by users of MAP_RES. +// +// Inputs: +// ppRoot - pointer to a pointer to a MAP_ITEM +// +// Outputs: +// None +// +// Returns: +// None +// +////////////////////////////////////////////////////////////////////////////// +void +MapDoubleRight( + IN MAP_ITEM* const pItem ) +{ + MAP_ITEM **ppRoot = MapItemGetPtrAbove( pItem ); + + ASSERT( ppRoot ); + ASSERT( *ppRoot ); + ASSERT( (*ppRoot)->m_pLeft ); + ASSERT( (*ppRoot)->m_pLeft->m_pRight ); + + // point the root to the new root + *ppRoot = pItem->m_pLeft->m_pRight; + (*ppRoot)->m_pUp = pItem->m_pUp; + + // setup old root's left item's right pointer with + // the proper right subtree + pItem->m_pLeft->m_pRight = (*ppRoot)->m_pLeft; + if( (*ppRoot)->m_pLeft ) + (*ppRoot)->m_pLeft->m_pUp = pItem->m_pLeft; + + // setup the left pointer in the new root + (*ppRoot)->m_pLeft = pItem->m_pLeft; + if( pItem->m_pLeft->m_pUp ) + pItem->m_pLeft->m_pUp = *ppRoot; + + // setup old root's left pointer with the proper left subtree + pItem->m_pLeft = (*ppRoot)->m_pRight; + if( (*ppRoot)->m_pRight ) + (*ppRoot)->m_pRight->m_pUp = pItem; + + // setup the right pointer on the new root + (*ppRoot)->m_pRight = pItem; + pItem->m_pUp = *ppRoot; + + + // + // Now set the balances of the altered nodes + // This must be done from the most distant nodes first, + // then back towards the root. + // + MapUpdateDepthsNoCheck( (*ppRoot)->m_pLeft ); + MapUpdateDepthsNoCheck( (*ppRoot)->m_pRight ); + MapUpdateDepthsNoCheck( *ppRoot ); +} + +////////////////////////////////////////////////////////////////////////////// +// +// MapDoubleLeft +// +// Description: +// Double rotate the subtree pointed to by *ppRoot to the Left. +// This transform can rebalance a +2 RL. +// +// Inputs: +// ppRoot - pointer to a pointer to a MAP_ITEM +// +// Outputs: +// None +// +// Returns: +// None +// +////////////////////////////////////////////////////////////////////////////// +void +MapDoubleLeft( + IN MAP_ITEM* const pItem ) +{ + MAP_ITEM **ppRoot = MapItemGetPtrAbove( pItem ); + + ASSERT( ppRoot ); + ASSERT( *ppRoot ); + ASSERT( (*ppRoot)->m_pRight ); + ASSERT( (*ppRoot)->m_pRight->m_pLeft ); + + // point the root to the new root + // and record the old balance of the new root + if ( NULL == pItem->m_pRight ) { + ASSERT( FALSE ); + return; + } + *ppRoot = pItem->m_pRight->m_pLeft; + (*ppRoot)->m_pUp = pItem->m_pUp; + + // setup old root's right item's left pointer with + // the proper left subtree + pItem->m_pRight->m_pLeft = (*ppRoot)->m_pRight; + if( (*ppRoot)->m_pRight ) + (*ppRoot)->m_pRight->m_pUp = pItem->m_pRight; + + // setup the right pointer in the new root + (*ppRoot)->m_pRight = pItem->m_pRight; + if( pItem->m_pRight ) + pItem->m_pRight->m_pUp = *ppRoot; + + // setup old root's right pointer with the proper left subtree + pItem->m_pRight = (*ppRoot)->m_pLeft; + if( (*ppRoot)->m_pLeft ) + (*ppRoot)->m_pLeft->m_pUp = pItem; + + // setup the left pointer on the new root + (*ppRoot)->m_pLeft = pItem; + pItem->m_pUp = *ppRoot; + + // + // Now set the balances of the altered nodes + // This must be done from the most distant nodes first, + // then back towards the root. + // + MapUpdateDepthsNoCheck( (*ppRoot)->m_pLeft ); + MapUpdateDepthsNoCheck( (*ppRoot)->m_pRight ); + MapUpdateDepthsNoCheck( *ppRoot ); +} + +////////////////////////////////////////////////////////////////////////////// +// +// MapUpdateDepthsNoCheck +// +// Description: +// Updates the depth values of the specified item. This algorithm assumes +// the depths of all children of this item are already correct. +// This internal function should not be called by users of MAP_RES. +// +// Inputs: +// pItem - pointer to a MAP_ITEM +// +// Outputs: +// None +// +// Returns: +// None +// +////////////////////////////////////////////////////////////////////////////// +void +MapUpdateDepthsNoCheck( + IN MAP_ITEM* const pItem ) +{ + ASSERT( pItem ); + + if( pItem->m_pLeft ) + { + pItem->m_DLMin = (int8)(MIN( pItem->m_pLeft->m_DLMin, pItem->m_pLeft->m_DRMin ) + 1); + pItem->m_DLMax = (int8)(MAX( pItem->m_pLeft->m_DLMax, pItem->m_pLeft->m_DRMax ) + 1); + } + else + { + pItem->m_DLMin = -1; + pItem->m_DLMax = -1; + } + + if( pItem->m_pRight ) + { + pItem->m_DRMin = (int8)(MIN( pItem->m_pRight->m_DLMin, pItem->m_pRight->m_DRMin ) + 1); + pItem->m_DRMax = (int8)(MAX( pItem->m_pRight->m_DLMax, pItem->m_pRight->m_DRMax ) + 1); + } + else + { + pItem->m_DRMin = -1; + pItem->m_DRMax = -1; + } +} + +////////////////////////////////////////////////////////////////////////////// +// +// MapUpdateDepths +// +// Description: +// Updates the depth values of the specified item. This algorithm assumes +// the depths of all children of this item are already correct. +// This internal function should not be called by users of MAP_RES. +// +// Inputs: +// pItem - pointer to a MAP_ITEM +// +// Outputs: +// None +// +// Returns: +// TRUE if any of the depth values changed +// FALSE otherwise +// +////////////////////////////////////////////////////////////////////////////// +boolean +MapUpdateDepths( + IN MAP_ITEM* const pItem ) +{ + int8 OldDLMin; + int8 OldDLMax; + int8 OldDRMin; + int8 OldDRMax; + + ASSERT( pItem ); + ASSERT( !MapIsLeaf( pItem ) ); + + // retain the old values for comparison + OldDLMin = pItem->m_DLMin; + OldDLMax = pItem->m_DLMax; + OldDRMin = pItem->m_DRMin; + OldDRMax = pItem->m_DRMax; + + MapUpdateDepthsNoCheck( pItem ); + + // check for any change + if( (pItem->m_DLMin != OldDLMin) || (pItem->m_DLMax != OldDLMax) || + (pItem->m_DRMin != OldDRMin) || (pItem->m_DRMax != OldDRMax) ) + return TRUE; + + // no change to the depth of this node + return FALSE; +} + + +////////////////////////////////////////////////////////////////////////////// +// +// MapItorProbeLeft +// +// Description: +// This function returns the leftmost child, given a starting iterator. +// This is a helper function for traversing the tree. +// Users of MAP_RES should not call this function. +// +// Input: +// pItor - pointer to an iterator, possibly already in use +// +// Output +// None +// +// Returns: +// Pointer to the left-most item found in the subtree +// +////////////////////////////////////////////////////////////////////////////// +MAP_ITEM* +MapItorProbeLeft( + IN MAP_ITERATOR* const pItor ) +{ + MAP_ITEM *pItem = pItor->pItem; + + if( pItem == NULL ) + return NULL; + + // + // Traverse as far to the left in the tree as we can go. + // Record our path along the way. + // + while( pItem->m_pLeft != NULL ) + pItem = pItem->m_pLeft; + + pItor->pItem = pItem; + return( pItem ); +} + +////////////////////////////////////////////////////////////////////////////// +// +// MapItorProbeRight +// +// Description: +// This function returns the rightmost child, given a starting iterator. +// This is a helper function for traversing the tree. +// Users of MAP_RES should not call this function. +// +// Input: +// pItor - pointer to an iterator, possibly already in use +// +// Output +// None +// +// Returns: +// Pointer to the right-most item found in the subtree +// +////////////////////////////////////////////////////////////////////////////// +MAP_ITEM* MapItorProbeRight( IN MAP_ITERATOR* const pItor ) +{ + MAP_ITEM *pItem = pItor->pItem; + + if( pItem == NULL ) + return NULL; + + // + // Traverse as far to the right in the tree as we can go. + // Record our path along the way. + // + while( pItem->m_pRight != NULL ) + pItem = pItem->m_pRight; + + pItor->pItem = pItem; + return( pItem ); +} + +////////////////////////////////////////////////////////////////////////////// +// +// MapHead +// +// Description: +// Sets a map iterator to the first item in the map. The first item in the +// map is the item with the smallest key value. +// +// Inputs: +// pMap - pointer to the map +// pItor - pointer to a map iterator +// +// Outputs: +// None +// +// Returns: +// Pointer to the user item at the head of the map +// +////////////////////////////////////////////////////////////////////////////// +void* +MapHead( + IN const MAP_RES* const pMap, + IN MAP_ITERATOR* const pItor ) +{ + MAP_ITEM *pItem; + ASSERT( pMap ); + ASSERT( pItor ); + + pItem = MapItorInit( MapRoot( pMap ), pItor ); + + if( pItem ) + { + pItem = MapItorProbeLeft( pItor ); + if( pItem ) + return pItem->m_pObj; + } + + return NULL; +} + +////////////////////////////////////////////////////////////////////////////// +// +// MapRemoveHead +// +// Description: +// Removes the logical first element in the map. +// +// Inputs: +// pMap - pointer to the map +// +// Outputs: +// None +// +// Returns: +// Pointer to the user item at the head of the map +// +////////////////////////////////////////////////////////////////////////////// +void* +MapRemoveHead( + IN MAP_RES* const pMap ) +{ + void *pObj; + MAP_ITERATOR Itor; + + ASSERT( pMap ); + + pObj = MapHead( pMap, &Itor ); + + if( MapIsItorValid( &Itor ) ) + MapRemove( pMap, MapKey( &Itor ) ); + + return pObj; +} + +////////////////////////////////////////////////////////////////////////////// +// +// MapTail +// +// Description: +// Sets a map iterator to the last item in the map. The last item in the +// map is the item with the largest key value. +// +// Inputs: +// pMap - pointer to the map +// pItor - pointer to a map iterator +// +// Outputs: +// None +// +// Returns: +// Pointer to the user item at the head of the map +// +////////////////////////////////////////////////////////////////////////////// +void* +MapTail( + IN const MAP_RES* const pMap, + IN MAP_ITERATOR* const pItor ) +{ + MAP_ITEM *pItem; + ASSERT( pMap ); + ASSERT( pItor ); + + pItem = MapItorInit( MapRoot( pMap ), pItor ); + + if( pItem ) + { + pItem = MapItorProbeRight( pItor ); + if( pItem ) + return pItem->m_pObj; + } + + return NULL; +} + +////////////////////////////////////////////////////////////////////////////// +// +// MapRemoveTail +// +// Description: +// Removes the last first element in the map. +// +// Inputs: +// pMap - pointer to the map +// +// Outputs: +// None +// +// Returns: +// Pointer to the user item at the tail of the map +// +////////////////////////////////////////////////////////////////////////////// +void* +MapRemoveTail( + IN MAP_RES* const pMap ) +{ + void *pObj; + MAP_ITERATOR Itor; + + ASSERT( pMap ); + + pObj = MapTail( pMap, &Itor ); + + if( MapIsItorValid( &Itor ) ) + MapRemove( pMap, MapKey( &Itor ) ); + + return pObj; +} + +////////////////////////////////////////////////////////////////////////////// +// +// MapItorNext +// +// Description: +// Sets a map iterator to the next item in the map. This is an internal +// function that should not be called by users of map. +// +// Inputs: +// pItor - pointer to a map iterator +// +// Outputs: +// None +// +// Returns: +// Pointer to the MAP_ITEM to which the iterator has moved +// +////////////////////////////////////////////////////////////////////////////// +MAP_ITEM* +MapItorNext( + IN MAP_ITERATOR* const pItor ) +{ + MAP_ITEM *pOldItem; + // + // Traverse the tree until we find the next logical node + // Or we run out of nodes + // + if( pItor->pItem->m_pRight != NULL ) + { + // + // We must traverse the right subtree of this node + // + MapItorRight( pItor ); + return( MapItorProbeLeft( pItor ) ); + } + else + { + // right pointer is null, so ascend + do + { + pOldItem = pItor->pItem; + MapItorUp( pItor ); + + } while( pItor->pItem->m_pRight == pOldItem ); + + } + + if( MapItorAtRoot( pItor ) ) + return( NULL ); + + return( pItor->pItem ); + +} + +////////////////////////////////////////////////////////////////////////////// +// +// MapItorPrev +// +// Description: +// Sets a map iterator to the previous item in the map. This is an internal +// function that should not be called by users of map. +// +// Inputs: +// pItor - pointer to a map iterator +// +// Outputs: +// None +// +// Returns: +// Pointer to the MAP_ITEM to which the iterator has moved +// +////////////////////////////////////////////////////////////////////////////// +MAP_ITEM* MapItorPrev( IN MAP_ITERATOR* const pItor ) +{ + MAP_ITEM *pOldItem; + // + // Traverse the tree until we find the next logical node + // Or we run out of nodes + // + if( pItor->pItem->m_pLeft != NULL ) + { + // + // We must traverse the left subtree of this node + // + MapItorLeft( pItor ); + return( MapItorProbeRight( pItor ) ); + } + else + { + // left pointer is null, so ascend + do + { + pOldItem = pItor->pItem; + MapItorUp( pItor ); + + } while( pItor->pItem->m_pLeft == pOldItem ); + + } + + if( MapItorAtRoot( pItor ) ) + return( NULL ); + + return( pItor->pItem ); +} + +////////////////////////////////////////////////////////////////////////////// +// +// MapDebugCheckDepth +// +// Description: +// Returns FSUCCESS if the maximum and minimum depth of the tree vary by +// no more than 1 +// This function should not be called by users of map. +// +// Inputs: +// pMap - pointer to a MAP_RES +// +// Outputs: +// None +// +// Returns: +// FSUCCESS - depths do not vary by more than 1 +// FERROR otherwise +// +////////////////////////////////////////////////////////////////////////////// +/* +FSTATUS MapDebugCheckDepth( IN const MAP_RES * const pMap ) +{ + MAP_ITERATOR Itor; + MAP_ITEM *pItem; + uint32 Min = 0xFFFFFFFF; + uint32 Max = 0; + uint32 Depth; + + MapItorInit( MapRoot( pMap ), &Itor ); + pItem = MapItorProbeLeft( &Itor ); + while( pItem != NULL ) + { + if( (pItem->m_pLeft == NULL) || (pItem->m_pRight == NULL) ) + { + // this is a leaf so mark the depth + Depth = MapItorGetDepth( &Itor ); + if( Depth > Max ) + Max = Depth; + if( Depth < Min ) + Min = Depth; + } + + // verify the balance is legit + if( MapItemCheckRot( pItem ) != MAP_ROTNONE ) + { + DbgOut("\nBad tree! Bad bal = %d for key 0x%X", MapItemCheckRot( pItem ), + pItem->m_Key ); + return FERROR; + } + + + // try the next element + pItem = MapItorNext( &Itor ); + } + + if( Max - Min < MAP_MAX_MIN_DELTA ) + return FSUCCESS; + + DbgOut("\nBad tree! Min = %u, Max = %u", Min, Max ); + return FERROR; + +} +*/ + +////////////////////////////////////////////////////////////////////////////// +// +// MapConsoleDump +// +// Description: +// Prints a simple map the the current tree +// +// Inputs: +// pMap - pointer to a MAP_RES object +// Key - Key of new object to insert +// pObj - pointer to user object to insert into the map +// +// Outputs: +// None +// +// Returns: +// FSUCCESS +// FNOT_FOUND - the specified key does not exist in the map +// +////////////////////////////////////////////////////////////////////////////// +void MapConsoleDump( IN const MAP_RES* const pMap ) +{ + MapConsoleDumpSubtree( MapRoot( pMap ) ); +} + +////////////////////////////////////////////////////////////////////////////// +// +// MapConsoleDumpSubtree +// +// Description: +// Prints a simple map the the current tree +// +// Inputs: +// pMap - pointer to a MAP_RES object +// Key - Key of new object to insert +// pObj - pointer to user object to insert into the map +// +// Outputs: +// None +// +// Returns: +// FSUCCESS +// FNOT_FOUND - the specified key does not exist in the map +// +////////////////////////////////////////////////////////////////////////////// +void MapConsoleDumpSubtree( IN const MAP_ITEM* const pItem ) +{ + uint8 Depth; + + Depth = 1; + + DbgOut("\n%u: ", Depth ); + while( MapConsoleDumpDepth( pItem, Depth, 1, 0 ) != 0 ) + { + Depth++; + DbgOut("\n%u: ", Depth); + + if( Depth > MAP_CONSOLE_DISPLAY_DEPTH_MAX ) + { + DbgOut("More nodes beyond displayable depth..."); + break; + } + } + + DbgOut("\n\n"); +} + +uint32 MapConsoleDumpDepth( IN const MAP_ITEM* const pItem, + IN const uint8 ShowDepth, + IN const uint8 CurrentDepth, + IN uint32 Total ) + +{ + uint32 Width; + uint32 FrontHalf; + uint32 BackHalf; + + if( CurrentDepth == ShowDepth ) + { + char Num[16]; + + // display this node + if( pItem != NULL ) + { + if( CurrentDepth < 4 ) + // show balance in addition to key + snprintf( Num, sizeof(Num) - 1, "%"PRIx64"[%d,%d,%d,%d]", pItem->m_Key, + pItem->m_DLMin, pItem->m_DLMax, + pItem->m_DRMin, pItem->m_DRMax ); + else + snprintf( Num, sizeof(Num) - 1, "%"PRIx64, pItem->m_Key ); + + Width = strlen( Num ); + // compensate if width is not an even number + if( (Width % 2) == 0 ) + FrontHalf = BackHalf = Width / 2; + else + { + if( Width == 1 ) + { + FrontHalf = 0; + BackHalf = 1; + } + else + { + FrontHalf = Width/2; + BackHalf = Width/2 +1; + } + } + + MapConsolePad( ShowDepth, TRUE, FrontHalf, FALSE ); + DbgOut( "%s", Num ); + Total++; + MapConsolePad( ShowDepth, FALSE, BackHalf, FALSE ); + } + else + { + MapConsolePad( ShowDepth, TRUE, 0, TRUE ); + DbgOut("#"); + MapConsolePad( ShowDepth, FALSE, 1, TRUE ); + } + + } + else + { + if( pItem != NULL ) + { + // we're not deep enough, recurse left, then right + Total += MapConsoleDumpDepth( pItem->m_pLeft, ShowDepth, + (uint8)(CurrentDepth + 1), Total ); + + Total += MapConsoleDumpDepth( pItem->m_pRight, ShowDepth, + (uint8)(CurrentDepth + 1), Total ); + } + else + MapConsolePad( (uint8)(CurrentDepth - 1), FALSE, 0, TRUE ); + } + + return Total; +} + +void MapConsolePad( IN const uint8 ShowDepth, + IN const boolean Leading, + IN const uint32 FudgeFactor, + IN const boolean Dashless ) +{ + uint32 i; + uint32 NumChars = 1<<(7 - ShowDepth); + char DashChar; + + if( Dashless ) + DashChar = ' '; + else + DashChar = '-'; + + // determine if we need to print leading or trailing '-' + if( Leading ) + { + // print leading '-' + for( i = 0; i < NumChars - FudgeFactor; i++) + { + if( i < NumChars/2 ) + DbgOut(" "); + else + DbgOut("%c", DashChar); + } + } + else + { + // print trailing '-' + for( i = FudgeFactor; i < NumChars; i++) + { + if( i < NumChars/2 +1 ) + DbgOut("%c", DashChar); + else + DbgOut(" "); + } + } +} + + diff --git a/IbAccess/Common/Public/imap.h b/IbAccess/Common/Public/imap.h new file mode 100644 index 0000000..82341cd --- /dev/null +++ b/IbAccess/Common/Public/imap.h @@ -0,0 +1,882 @@ +/* BEGIN_ICS_COPYRIGHT3 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT3 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +/**************************************************************************** + * + * Map + * + ****************************************************************************/ + +#ifndef _IBA_PUBLIC_IMAP_H_INCLUDED_ +#define _IBA_PUBLIC_IMAP_H_INCLUDED_ + +#include "iba/public/datatypes.h" +#include "iba/public/imath.h" +#include "iba/public/igrowpool.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/* enable this #define for more debug information */ +#ifdef IB_DEBUG +#define MAP_DEBUG 1 +#else +#define MAP_DEBUG 0 +#endif + +#define MAP_RECURSION_THRESHOLD 0 +#define MAP_CONSOLE_DISPLAY_DEPTH_MAX 7 +#define MAP_START_SIZE 256 +#define MAP_GROW_SIZE 256 +#define MAP_MAX_MIN_DELTA 2 + +/* define the various rotations */ +typedef enum _MAP_ROTDIR +{ + MAP_ROTNONE, /* no rotation */ + MAP_ROTL, /* rotate left */ + MAP_ROTR, /* rotate right */ + MAP_ROTDL, /* double rotate left */ + MAP_ROTDR, /* double rotate right */ + MAP_RECURSIVE /* too complex for simple rotations */ + +} MAP_ROTDIR; + +/* define the map linkage structure */ +typedef struct _MAP_ITEM +{ + struct _MAP_ITEM *m_pLeft; /* DO NOT USE!! */ + struct _MAP_ITEM *m_pRight; /* DO NOT USE!! */ + struct _MAP_ITEM *m_pUp; /* DO NOT USE!! */ + int8 m_DLMin; /* DO NOT USE!! */ + int8 m_DLMax; /* DO NOT USE!! */ + int8 m_DRMin; /* DO NOT USE!! */ + int8 m_DRMax; /* DO NOT USE!! */ + uint64 m_Key; /* DO NOT USE!! */ + void *m_pObj; /* DO NOT USE!! */ + +} MAP_ITEM, *PMAP_ITEM; + +/* define the map structure for global map resources */ +typedef struct _MAP_RES +{ + MAP_ITEM m_End; /* DO NOT USE!! */ + uint32 m_Count; /* DO NOT USE!! */ + boolean m_DelToggle; /* DO NOT USE!! */ + GROW_POOL m_Pool; /* DO NOT USE!! */ + +} MAP_RES, *PMAP_RES; + +/* Define the iterator used to traverse the tree */ +typedef struct _MAP_ITERATOR +{ + MAP_ITEM *pItem; +} MAP_ITERATOR; + + +/* internal function prototypes not for use by user's of map */ +MAP_ITEM* MapItorNext( IN MAP_ITERATOR* const pItor ); +MAP_ITEM* MapItorPrev( IN MAP_ITERATOR* const pItor ); +void MapUpdateDepthsNoCheck( IN MAP_ITEM* const pItem ); +MAP_ITEM* MapItorInit( IN MAP_ITEM* const pItem, + IN MAP_ITERATOR * const pItor ); +MAP_ITEM** MapItemGetPtrAbove( IN MAP_ITEM* const pItem ); + +/**************************************************************************** + * + * MapItorItem + * + * Description: + * Returns a pointer to the MAP_ITEM pointed to by the iterator. + * This function should not be called by user's of map. + * + * Inputs: + * pItor - pointer to a map iterator + * + * Outputs: + * None + * + * Returns: + * Pointer to the MAP_ITEM to which the iterator points + * + ****************************************************************************/ +static __inline MAP_ITEM* +MapItorItem( + IN const MAP_ITERATOR* const pItor ) +{ + return( pItor->pItem ); +} + +/**************************************************************************** + * + * MapDebugGetRootKey + * + * Description: + * Returns the key value of the current root of the map. + * This function is for debugging only and should not be called by + * general users of MAP_RES. + * + * + * Inputs: + * pMap - pointer to a MAP_RES + * + * Outputs: + * None + * + * Returns: + * TRUE if the item is a leaf + * FALSE otherwise + * + ****************************************************************************/ +static __inline uint64 +MapDebugGetRootKey( + IN const MAP_RES* const pMap ) +{ + ASSERT( pMap ); + ASSERT( pMap->m_End.m_pLeft ); + return( pMap->m_End.m_pLeft->m_Key ); +} + +/**************************************************************************** + * + * MapRoot + * + * Description: + * Returns the current root of the map. + * This function should not be called by user's of map. + * + * Inputs: + * pMap - pointer to a MAP_RES + * + * Outputs: + * None + * + * Returns: + * TRUE if the item is a leaf + * FALSE otherwise + * + ****************************************************************************/ +static __inline MAP_ITEM* +MapRoot( + IN const MAP_RES* const pMap ) +{ + ASSERT( pMap ); + return( pMap->m_End.m_pLeft ); +} + +/**************************************************************************** + * + * MapItorGetPtrAbove + * + * Description: + * Returns a pointer to a the pointer that points to the node at + * the Iterator. + * + * Inputs: + * pItor - pointer to a map iterator + * + * Outputs: + * None + * + * Returns: + * pointer to a pointer to the node at the iterator + * + ****************************************************************************/ +static __inline MAP_ITEM** +MapItorGetPtrAbove( + IN const MAP_ITERATOR* const pItor ) +{ + return( MapItemGetPtrAbove( pItor->pItem ) ); +} + +/**************************************************************************** + * + * MapItorUp + * + * Description: + * Moves the iterator one step toward the root. + * Returns a pointer to the new MAP_ITEM pointed to by the iterator. + * This function should not be called by user's of map. + * + * Inputs: + * pItor - pointer to a map iterator + * + * Outputs: + * None + * + * Returns: + * Pointer to the MAP_ITEM to which the iterator points + * + ****************************************************************************/ +static __inline MAP_ITERATOR* +MapItorUp( + IN MAP_ITERATOR* const pItor ) +{ + pItor->pItem = pItor->pItem->m_pUp; + return( pItor ); +} + +/**************************************************************************** + * + * MapSetRoot + * + * Description: + * Sets the root of the map. + * This function should not be called by user's of map. + * + * Inputs: + * pMap - pointer to a MAP_RES + * pItem - pointer to the MAP_RES item. This pointer may be NULL. + * + * Outputs: + * None + * + * Returns: + * TRUE if the item is a leaf + * FALSE otherwise + * + ****************************************************************************/ +static __inline void +MapSetRoot( + IN MAP_RES* const pMap, + IN MAP_ITEM* const pItem ) +{ + ASSERT( pMap ); + pMap->m_End.m_pLeft = pItem; + if( pItem ) + pItem->m_pUp = &pMap->m_End; +} + +/**************************************************************************** + * + * MapCount + * + * Description: + * Returns the number of items in the map. + * + * Inputs: + * pMap - pointer to a MAP_RES + * + * Outputs: + * None + * + * Returns: + * TRUE if the item is a leaf + * FALSE otherwise + * + ****************************************************************************/ +static __inline uint32 +MapCount( + IN const MAP_RES* const pMap ) +{ + ASSERT( pMap ); + return( pMap->m_Count ); +} + +/**************************************************************************** + * + * MapObj + * + * Description: + * Returns the user object pointed to by an iterator. + * + * Inputs: + * pItor - MAP_ITERATOR + * + * Outputs: + * None + * + * Returns: + * pointer to the user object + * + ****************************************************************************/ +static __inline void* +MapObj( + IN const MAP_ITERATOR* const pItor ) +{ + ASSERT( pItor ); + return( pItor->pItem->m_pObj ); +} + +/**************************************************************************** + * + * MapKey + * + * Description: + * Returns the key pointed to by an iterator. + * + * Inputs: + * Itor - MAP_ITERATOR + * + * Outputs: + * None + * + * Returns: + * key value of the object pointed to by the iterator + * + ****************************************************************************/ +static __inline uint64 +MapKey( + IN const MAP_ITERATOR* const pItor ) +{ + ASSERT( pItor ); + return( pItor->pItem->m_Key ); +} + + +/**************************************************************************** + * + * MapIsLeaf + * + * Description: + * Returns true if the specified MAP_ITEM is a leaf. + * This function should not be called by user's of map. + * + * Inputs: + * pItem - pointer to a MAP_ITEM + * + * Outputs: + * None + * + * Returns: + * TRUE if the item is a leaf + * FALSE otherwise + * + ****************************************************************************/ +static __inline boolean +MapIsLeaf( + IN const MAP_ITEM* const pItem ) +{ + ASSERT( pItem ); + return( (boolean)((pItem->m_pLeft == NULL) && (pItem->m_pRight == NULL)) ); +} + +/**************************************************************************** + * + * MapIsRoot + * + * Description: + * Returns true if the specified MAP_ITEM is the root of the given MAP_RES + * This function should not be called by user's of map. + * + * Inputs: + * pMap - pointer ot a MAP_ITEM + * pItem - pointer to a MAP_ITEM + * + * Outputs: + * None + * + * Returns: + * TRUE if the item is the root + * FALSE otherwise + * + ****************************************************************************/ +static __inline boolean +MapIsRoot( + IN const MAP_RES* const pMap, + IN const MAP_ITEM* const pItem) +{ + ASSERT( pMap ); + return( (boolean)(pMap->m_End.m_pLeft == pItem) ); +} + +/**************************************************************************** + * + * MapItorIsLeaf + * + * Description: + * Returns true if the item pointed to by the iterator is a leaf. + * This function should not be called by user's of map. + * + * Inputs: + * pItor - pointer to a MAP_ITERATOR + * + * Outputs: + * None + * + * Returns: + * TRUE if the iterator's item is a leaf + * FALSE otherwise + * + ****************************************************************************/ +static __inline boolean +MapItorIsLeaf( + IN const MAP_ITERATOR* const pItor ) +{ + ASSERT( pItor ); + return( (boolean)((pItor->pItem->m_pLeft == NULL) && + (pItor->pItem->m_pRight == NULL) )); +} + +/**************************************************************************** + * + * MapItorDeleteLeaf + * + * Description: + * Performs a simple delete of the item pointed to by the given iterator. + * The iterator must point to a leaf item. + * The iterator may point to the root node of this iterator. + * The balances in the tree nodes are not adjusted! + * This internal function should not be called by users of MAP_RES. + * + * Inputs: + * pItor - pointer to a MAP_ITERATOR object + * + * Outputs: + * None + * + * Returns: + * None + * + ****************************************************************************/ +static __inline void +MapItorDeleteLeaf( + IN MAP_ITERATOR* const pItor ) +{ + /* The pointer that points to the leaf item must be set to NULL */ + /* or the node above the node to be deleted, determine when the */ + /* node to delete hangs to the left or right. */ + ASSERT( pItor ); + ASSERT( MapIsLeaf( pItor->pItem ) ); + *(MapItorGetPtrAbove( pItor )) = NULL; + /* put the iterator back into the map now that the node */ + /* it points to has been deleted. */ + MapItorUp( pItor ); +} + +/**************************************************************************** + * + * MapItorDeleteRightHalfLeaf + * + * Description: + * Performs a simple delete of the item pointed to by the given iterator. + * The iterator must point to an item that has a NULL child on the right. + * The iterator can NOT point to the root node of this iterator. + * The iterator may point to a true leaf. + * The balances in the tree nodes is not adjusted! + * This internal function should not be called by users of MAP_RES. + * + * Inputs: + * pItor - pointer to a MAP_ITERATOR object + * + * Outputs: + * None + * + * Returns: + * None + * + ****************************************************************************/ +static __inline void +MapItorDeleteRightHalfLeaf( + IN MAP_ITERATOR* const pItor ) +{ + ASSERT( pItor ); + ASSERT( pItor->pItem->m_pRight == NULL ); + *(MapItorGetPtrAbove( pItor )) = pItor->pItem->m_pLeft; + if( pItor->pItem->m_pLeft != NULL ) + pItor->pItem->m_pLeft->m_pUp = pItor->pItem->m_pUp; + /* put the iterator back into the map now that the node */ + /* it points to has been deleted. */ + MapItorUp( pItor ); +} + +/**************************************************************************** + * + * MapItorDeleteLeftHalfLeaf + * + * Description: + * Performs a simple delete of the item pointed to by the given iterator. + * The iterator must point to an item that has a NULL child on the left. + * The iterator can NOT point to the root node of this iterator. + * The iterator may point to a true leaf. + * The balances in the tree nodes is not adjusted! + * This internal function should not be called by users of MAP_RES. + * + * Inputs: + * pItor - pointer to a MAP_ITERATOR object + * + * Outputs: + * None + * + * Returns: + * None + * + ****************************************************************************/ +static __inline void +MapItorDeleteLeftHalfLeaf( + IN MAP_ITERATOR * const pItor ) +{ + ASSERT( pItor ); + ASSERT( pItor->pItem->m_pLeft == NULL ); + *(MapItorGetPtrAbove( pItor )) = pItor->pItem->m_pRight; + if( pItor->pItem->m_pRight != NULL ) + pItor->pItem->m_pRight->m_pUp = pItor->pItem->m_pUp; + /* put the iterator back into the map now that the node */ + /* it points to has been deleted. */ + MapItorUp( pItor ); +} + + +/**************************************************************************** + * + * MapItorLeft + * + * Description: + * Step the iterator one node down to the left. + * This function should not be called by user's of map. + * + * Inputs: + * pItor - pointer to a map iterator + * + * Outputs: + * None + * + * Returns: + * Pointer to the MAP_ITEM to which the iterator moved + * + ****************************************************************************/ +static __inline MAP_ITEM* +MapItorLeft( + IN MAP_ITERATOR* const pItor ) +{ + pItor->pItem = pItor->pItem->m_pLeft; + return( pItor->pItem ); +} + +/**************************************************************************** + * + * MapItemInit + * + * Description: + * Initializes a MAP_ITEM object. + * This function must be called before using a new MAP_ITEM. + * This internal function should not be called by users of MAP_RES. + * + * Inputs: + * pItem - pointer to a MAP_ITEM. + * Key - key value associated with this MAP_ITEM. + * pObj - user object associated with theis MAP_ITEM. + * + * Outputs: + * None + * + * Returns: + * None + * + ****************************************************************************/ +static __inline void +MapItemResetBalances( + IN MAP_ITEM* const pItem ) +{ + pItem->m_DLMin = -1; + pItem->m_DLMax = -1; + pItem->m_DRMin = -1; + pItem->m_DRMax = -1; +} + +/**************************************************************************** + * + * MapItorRight + * + * Description: + * Step the iterator one node down to the right. + * This function should not be called by user's of map. + * + * Inputs: + * pItor - pointer to a map iterator + * + * Outputs: + * None + * + * Returns: + * Pointer to the MAP_ITEM to which the iterator moved + * + ****************************************************************************/ +static __inline MAP_ITEM* +MapItorRight( + IN MAP_ITERATOR* const pItor ) +{ + pItor->pItem = pItor->pItem->m_pRight; + return( pItor->pItem ); +} + +/**************************************************************************** + * + * MapItorAtRoot + * + * Description: + * Returns true if this iterator points to the root node + * + * Inputs: + * pItor - pointer to a map iterator + * + * Outputs: + * None + * + * Returns: + * TRUE - The iterator points to the root node + * FALSE otherwise + * + ****************************************************************************/ +static __inline boolean +MapItorAtRoot( + IN const MAP_ITERATOR* const pItor ) +{ + return( (boolean)(pItor->pItem->m_pUp == pItor->pItem) ); +} + +/**************************************************************************** + * + * MapIsItorValid + * + * Description: + * Returns TRUE if the MAP_ITERATOR points to an object in the map. + * Returns FALSE if the iterator points outside the map or to the logical + * end of the map (which is of course outstide the map too) + * + * Inputs: + * Itor - MAP_ITERATOR + * + * Outputs: + * None + * + * Returns: + * key value of the object pointed to by the iterator + * + ****************************************************************************/ +static __inline boolean +MapIsItorValid( + IN const MAP_ITERATOR* const pItor ) +{ + if( pItor->pItem != NULL ) + return( !MapItorAtRoot( pItor ) ); + else + return( FALSE ); +} + +/**************************************************************************** + * + * MapRotRight + * + * Description: + * Rotate the subtree pointed to by *ppRoot to the right. This transform + * can rebalance a -2 LL + * + * Inputs: + * ppRoot - pointer to a pointer to a MAP_ITEM + * + * Outputs: + * None + * + * Returns: + * None + * + ****************************************************************************/ +static __inline void +MapRotRight( + IN MAP_ITEM *pItem ) +{ + MAP_ITEM **ppRoot = MapItemGetPtrAbove( pItem ); + + ASSERT( pItem ); + ASSERT( ppRoot ); + ASSERT( *ppRoot ); + + /* point to the new root */ + /* which is the left leaf of the old root */ + *ppRoot = pItem->m_pLeft; + pItem->m_pLeft->m_pUp = pItem->m_pUp; + + /* Set old root's left tree to the new root's old right tree */ + pItem->m_pLeft = (*ppRoot)->m_pRight; + if( pItem->m_pLeft ) + pItem->m_pLeft->m_pUp = pItem; + + /* the right subtree of the new root becomes the old root */ + /* the unblanaced node */ + (*ppRoot)->m_pRight = pItem; + if( (*ppRoot)->m_pRight ) + (*ppRoot)->m_pRight->m_pUp = *ppRoot; + + MapUpdateDepthsNoCheck( pItem ); + MapUpdateDepthsNoCheck( *ppRoot ); + +} + +/**************************************************************************** + * + * MapRotLeft + * + * Description: + * Rotate the subtree pointed to by *ppRoot to the left. This transform + * can rebalance a +2 RR + * + * Inputs: + * ppRoot - pointer to a pointer to a MAP_ITEM + * + * Outputs: + * None + * + * Returns: + * None + * + ****************************************************************************/ +static __inline void +MapRotLeft( + IN MAP_ITEM *pItem ) +{ + MAP_ITEM **ppRoot = MapItemGetPtrAbove( pItem ); + + ASSERT( pItem ); + ASSERT( ppRoot ); + ASSERT( *ppRoot ); + + /* point the new root */ + /* which is the right leaf of the old root */ + *ppRoot = pItem->m_pRight; + pItem->m_pRight->m_pUp = pItem->m_pUp; + + /* setup the left subtree of the old root */ + /* to be the right subtree of the new root */ + pItem->m_pRight = (*ppRoot)->m_pLeft; + if( pItem->m_pRight ) + pItem->m_pRight->m_pUp = pItem; + + /* the right subtree of the new root becomes the old root */ + /* the unblanaced node */ + (*ppRoot)->m_pLeft = pItem; + if( (*ppRoot)->m_pLeft ) + (*ppRoot)->m_pLeft->m_pUp = *ppRoot; + + MapUpdateDepthsNoCheck( pItem ); + MapUpdateDepthsNoCheck( *ppRoot ); +} + +/**************************************************************************** + * + * MapNext + * + * Description: + * Sets a map iterator to the logical next item in the map. + * + * Inputs: + * pItor - pointer to a map iterator + * + * Outputs: + * None + * + * Returns: + * Pointer to the user object at the next map location + * + ****************************************************************************/ +static __inline void* +MapNext( + IN MAP_ITERATOR* const pItor ) +{ + MAP_ITEM *pItem; + ASSERT( pItor ); + pItem = MapItorNext( pItor ); + if( pItem != NULL ) + return( pItem->m_pObj ); + else + return NULL; +} + +/**************************************************************************** + * + * MapPrev + * + * Description: + * Sets a map iterator to the previous item in the map. + * + * Inputs: + * pItor - pointer to a map iterator + * + * Outputs: + * None + * + * Returns: + * Pointer to the user object at the next map location + * + ****************************************************************************/ +static __inline void* +MapPrev( + IN MAP_ITERATOR* const pItor ) +{ + MAP_ITEM *pItem; + ASSERT( pItor ); + pItem = MapItorPrev( pItor ); + if( pItem != NULL ) + return( pItem->m_pObj ); + else + return NULL; +} + + + +void MapInitState( IN MAP_RES * const pMap ); + +FSTATUS MapInit( IN MAP_RES * const pMap ); + +void MapDestroy( IN MAP_RES * const pMap ); + +FSTATUS MapInsert( IN MAP_RES* const pMap, + IN const uint64 Key, + IN const void* const pObj ); + +void* MapHead( IN const MAP_RES* const pMap, + IN MAP_ITERATOR* const pItor ); + +void* MapRemoveHead( IN MAP_RES* const pMap ); + +void* MapTail( IN const MAP_RES* const pMap, + IN MAP_ITERATOR* const pItor ); + +void* MapRemoveTail( IN MAP_RES* const pMap ); + +FSTATUS MapRemove( IN MAP_RES* const pMap, + IN const uint64 Key ); + +void MapConsoleDump( IN const MAP_RES* const pMap ); + +void* MapGet( IN const MAP_RES* const pMap, + IN const uint64 Key ); + + +/*FSTATUS MapDebugCheckDepth( IN const MAP_RES * const pMap ); */ + +#ifdef __cplusplus +} +#endif + +#endif /* _IBA_PUBLIC_IMAP_H_INCLUDED */ diff --git a/IbAccess/Common/Public/imath.c b/IbAccess/Common/Public/imath.c new file mode 100644 index 0000000..c0d668e --- /dev/null +++ b/IbAccess/Common/Public/imath.c @@ -0,0 +1,65 @@ +/* BEGIN_ICS_COPYRIGHT6 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT6 ****************************************/ + +#include "datatypes.h" +#include "imath.h" + +static uint32 +ones64(uint64 x) +{ + x -= ((x >> 1) & 0x5555555555555555ULL); + x = (((x >> 2) & 0x3333333333333333ULL) + (x & 0x3333333333333333ULL)); + x = (((x >> 4) + x) & 0x0f0f0f0f0f0f0f0fULL); + x += (x >> 8); + x += (x >> 16); + x += (x >> 32); + return(x & 0x0000003f); +} + +uint32 +FloorLog2(uint64 x) +{ + x |= (x >> 1); + x |= (x >> 2); + x |= (x >> 4); + x |= (x >> 8); + x |= (x >> 16); + x |= (x >> 32); + return(ones64(x >> 1)); +} + +uint32 CeilLog2(uint64 val) +{ + uint32 floor2 = FloorLog2(val); + if ((1ULL << floor2) == val) + return (floor2); + else + return (floor2+1); +} + diff --git a/IbAccess/Common/Public/imath.h b/IbAccess/Common/Public/imath.h new file mode 100644 index 0000000..3560d51 --- /dev/null +++ b/IbAccess/Common/Public/imath.h @@ -0,0 +1,96 @@ +/* BEGIN_ICS_COPYRIGHT3 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT3 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +#ifndef _IBA_PUBLIC_IMATH_H_ +#define _IBA_PUBLIC_IMATH_H_ + +#include "iba/public/datatypes.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +#ifndef MAX +#define MAX(x,y) ((x) > (y) ? (x) : (y)) +#endif + +#ifndef MIN +#define MIN(x,y) ((x) < (y) ? (x) : (y)) +#endif + +/* round up value to align, align must be a power of 2 */ +#ifndef ROUNDUPP2 +#define ROUNDUPP2(val, align) \ + (((uintn)(val) + (uintn)(align) - 1) & (~((uintn)(align)-1))) +#endif +/* force to use 64 bits in 32bit box */ +#ifndef ROUNDUP64P2 +#define ROUNDUP64P2(val, align) \ + (((uint64)(val) + (uint64)(align) - 1) & (~((uint64)(align)-1))) +#endif + +/* round up value to align, align can be any value, less efficient than ROUNDUPP2 */ +#ifndef ROUNDUP +#define ROUNDUP(val, align) \ + ((( ((uintn)(val)) + (uintn)(align) -1) / (align) ) * (align)) +#endif + +/* round down value to align, align must be a power of 2 */ +#ifndef ROUNDDOWNP2 +#define ROUNDDOWNP2(val, align) \ + (((uintn)(val)) & (~((uintn)(align)-1))) +#endif +/* round down value to align, align can be any value, less efficient than ROUNDDOWNP2 */ +#ifndef ROUNDDOWN +#define ROUNDDOWN(val, align) \ + ((( ((uintn)(val))) / (align) ) * (align)) +#endif + +/* convert bytes to Megabytes, rounding up */ +#define BYTES_TO_MB(val) (((val) + ((1024*1024)-1))>> 20) + + +/* log2(x) truncated */ +uint32 FloorLog2(uint64 x); + +/* log2(x) rounded up if x is not a power of 2 */ +uint32 CeilLog2(uint64 x); + +static _inline uint32 NextPower2(uint64 x) +{ + return (1 << CeilLog2(x)); +} + +#if defined(__cplusplus) +} +#endif + +#endif /* _IBA_PUBLIC_IMATH_H_ */ diff --git a/IbAccess/Common/Public/imemory.c b/IbAccess/Common/Public/imemory.c new file mode 100644 index 0000000..b5951cb --- /dev/null +++ b/IbAccess/Common/Public/imemory.c @@ -0,0 +1,1673 @@ +/* BEGIN_ICS_COPYRIGHT6 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT6 ****************************************/ + +#if !defined(VXWORKS) +#define _GNU_SOURCE +#endif + +#include "imemory.h" +#include "idebug.h" +#include "itimer.h" +#include +#include +#include +#include +#include + +#define MAX_VFABRIC_NAME 64 // from fm_xml.h + +// from stl_pa.h +#define STL_PA_SELECT_UTIL_HIGH 0x00020001 +#define STL_PA_SELECT_UTIL_MC_HIGH 0x00020081 +#define STL_PA_SELECT_UTIL_PKTS_HIGH 0x00020082 +#define STL_PA_SELECT_CATEGORY_INTEG 0x00030001 +#define STL_PA_SELECT_CATEGORY_CONG 0x00030002 +#define STL_PA_SELECT_CATEGORY_SMA_CONG 0x00030003 +#define STL_PA_SELECT_CATEGORY_BUBBLE 0x00030004 +#define STL_PA_SELECT_CATEGORY_SEC 0x00030005 +#define STL_PA_SELECT_CATEGORY_ROUT 0x00030006 +#define FOCUS_PORTS_COMPARATOR_INVALID 0 +#define FOCUS_PORTS_COMPARATOR_GREATER_THAN 1 +#define FOCUS_PORTS_COMPARATOR_LESS_THAN 2 +#define FOCUS_PORTS_COMPARATOR_GREATER_THAN_OR_EQUAL 3 +#define FOCUS_PORTS_COMPARATOR_LESS_THAN_OR_EQUAL 4 + +#if defined(MEM_TRACK_ON) +#if defined(VXWORKS) +#include "tickLib.h" +#define TICK tickGet() +#else +#define TICK 0 // TBD need to specify value for Linux and MAC +#endif +#define MEM_TRACK_FTR +#include "imemtrack.h" + +// Default number of headers to allocate at a time. +#define MEM_HDR_ALLOC_SIZE 50 + +#if defined(MEM_TRACK_ON) +#define UNTRACKED_COUNT 12000 +void *unTAddr[UNTRACKED_COUNT]; +int unTindex=0; +int unTmissed=0; +#endif + +MEM_TRACKER *pMemTracker = NULL; +static uint32 last_reported_allocations; +static uint32 total_allocations; +static uint32 last_reported_secs; +static uint32 current_allocations; +static uint32 current_allocated; +static uint32 max_allocations; +static uint32 max_allocated; + +static void MemoryTrackerDereference(MemoryTrackerFileName_t *trk); +static MemoryTrackerFileName_t *MemoryTrackerBuckets[MEMORY_TRACKER_BUCKETS]; +#endif // MEM_TRACK_ON + +#ifdef VXWORKS +extern unsigned long long strtoull (const char *__s, char **__endptr, int __base); +extern long long strtoll (const char *__s, char **__endptr, int __base); +#endif + +char* +StringConcat(const char* str1, ...) +{ +#ifdef VXWORKS +#define stpcpy(s1, s2) (strcpy(s1, s2) + strlen(s2)) +#endif + + if (!str1) + return NULL; + + /* calculate length first */ + size_t strings_length = 1 + strlen(str1); + + va_list args; + va_start(args, str1); + char* str = va_arg(args, char*); + while (str) { + strings_length += strlen(str); + str = va_arg(args, char*); + } + va_end(args); + + /* next, allocate a memory */ + char* string = (char*)malloc(strings_length); + if (!string) + return NULL; + + /* finally, create the string */ + char* string_tmp = stpcpy(string, str1); + va_start(args, str1); + str = va_arg(args, char*); + while (str) { + string_tmp = stpcpy(string_tmp, str); + str = va_arg(args, char*); + } + va_end(args); + + return string; +} + +// convert a string to a uint64. Very similar to strtoull except that +// base=0 implies base 10 or 16, but excludes base 8 +// hence allowing leading 0's for base 10. +// +// Also provides easier to use status returns and error checking. +// +// Can also optionally skip trailing whitespace, when skip_trail_whietspace is +// FALSE, trailing whitespace is treated as a FERROR +// +// When endptr is NULL, trailing characters (after optional whitespace) are +// considered an FERROR. When endptr is non-NULL, for a FSUCCESS conversion, +// it points to the characters after the optional trailing whitespace. +// Errors: +// FSUCCESS - successful conversion, *endptr points to 1st char after value +// FERROR - invalid contents, non-numeric +// FINVALID_SETTING - value out of range +// FINVALID_PARAMETER - invalid function arguments (NULL value or str) +FSTATUS StringToUint64(uint64 *value, const char* str, char **endptr, int base, boolean skip_trail_whitespace) +{ + char *end = NULL; + uint64 temp; + + if (! str || ! value) + return FINVALID_PARAMETER; + errno = 0; + temp = strtoull(str, &end, base?base:10); + if ( ! base && ! (temp == IB_UINT64_MAX && errno) + && (end && temp == 0 && *end == 'x' && end != str)) { + // try again as base 16 + temp = strtoull(str, &end, 16); + } + if ((temp == IB_UINT64_MAX && errno) + || (end && end == str)) { + if (errno == ERANGE) + return FINVALID_SETTING; + else + return FERROR; + } + + // skip whitespace + if (end && skip_trail_whitespace) { + while (isspace(*end)) { + end++; + } + } + if (endptr) + *endptr = end; + else if (end && *end != '\0') + return FERROR; + *value = temp; + return FSUCCESS; +} + +FSTATUS StringToUint32(uint32 *value, const char* str, char **endptr, int base, boolean skip_trail_whitespace) +{ + uint64 temp; + FSTATUS status; + + status = StringToUint64(&temp, str, endptr, base, skip_trail_whitespace); + if (status != FSUCCESS) + return status; + if (temp > IB_UINT32_MAX) + return FINVALID_SETTING; + *value = (uint32)temp; + return FSUCCESS; +} + +FSTATUS StringToUint16(uint16 *value, const char* str, char **endptr, int base, boolean skip_trail_whitespace) +{ + uint64 temp; + FSTATUS status; + + status = StringToUint64(&temp, str, endptr, base, skip_trail_whitespace); + if (status != FSUCCESS) + return status; + if (temp > IB_UINT16_MAX) + return FINVALID_SETTING; + *value = (uint16)temp; + return FSUCCESS; +} + +FSTATUS StringToUint8(uint8 *value, const char* str, char **endptr, int base, boolean skip_trail_whitespace) +{ + uint64 temp; + FSTATUS status; + + status = StringToUint64(&temp, str, endptr, base, skip_trail_whitespace); + if (status != FSUCCESS) + return status; + if (temp > IB_UINT8_MAX) + return FINVALID_SETTING; + *value = (uint8)temp; + return FSUCCESS; +} + +// convert a string to a int64. Very similar to strtoull except that +// base=0 implies base 10 or 16, but excludes base 8 +// hence allowing leading 0's for base 10. +// +// Also provides easier to use status returns and error checking. +// +// Can also optionally skip trailing whitespace, when skip_trail_whitespace is +// FALSE, trailing whitespace is treated as a FERROR +// +// When endptr is NULL, trailing characters (after optional whitespace) are +// considered an FERROR. When endptr is non-NULL, for a FSUCCESS conversion, +// it points to the characters after the optional trailing whitespace. +// Errors: +// FSUCCESS - successful conversion, *endptr points to 1st char after value +// FERROR - invalid contents, non-numeric +// FINVALID_SETTING - value out of range +// FINVALID_PARAMETER - invalid function arguments (NULL value or str) +FSTATUS StringToInt64(int64 *value, const char* str, char **endptr, int base, boolean skip_trail_whitespace) +{ + char *end = NULL; + int64 temp; + + if (! str || ! value) + return FINVALID_PARAMETER; + errno = 0; + temp = strtoll(str, &end, base?base:10); + if ( ! base && ! ((temp == IB_INT64_MAX || temp == IB_INT64_MIN) && errno) + && (end && temp == 0 && *end == 'x' && end != str)) { + // try again as base 16 + temp = strtoll(str, &end, 16); + } + if (((temp == IB_INT64_MAX || temp == IB_INT64_MIN) && errno) + || (end && end == str)) { + if (errno == ERANGE) + return FINVALID_SETTING; + else + return FERROR; + } + + // skip whitespace + if (end && skip_trail_whitespace) { + while (isspace(*end)) { + end++; + } + } + if (endptr) + *endptr = end; + else if (end && *end != '\0') + return FERROR; + *value = temp; + return FSUCCESS; +} + +FSTATUS StringToInt32(int32 *value, const char* str, char **endptr, int base, boolean skip_trail_whitespace) +{ + int64 temp; + FSTATUS status; + + status = StringToInt64(&temp, str, endptr, base, skip_trail_whitespace); + if (status != FSUCCESS) + return status; + if (temp < IB_INT32_MIN || temp > IB_INT32_MAX) + return FINVALID_SETTING; + *value = (int32)temp; + return FSUCCESS; +} + +FSTATUS StringToInt16(int16 *value, const char* str, char **endptr, int base, boolean skip_trail_whitespace) +{ + int64 temp; + FSTATUS status; + + status = StringToInt64(&temp, str, endptr, base, skip_trail_whitespace); + if (status != FSUCCESS) + return status; + if (temp < IB_INT16_MIN || temp > IB_INT16_MAX) + return FINVALID_SETTING; + *value = (int16)temp; + return FSUCCESS; +} + +FSTATUS StringToInt8(int8 *value, const char* str, char **endptr, int base, boolean skip_trail_whitespace) +{ + int64 temp; + FSTATUS status; + + status = StringToInt64(&temp, str, endptr, base, skip_trail_whitespace); + if (status != FSUCCESS) + return status; + if (temp < IB_INT8_MIN || temp > IB_INT8_MAX) + return FINVALID_SETTING; + *value = (int8)temp; + return FSUCCESS; +} + +// GID of form hValue:lValue +// values must be base 16, as such 0x prefix is optional for both hValue and +// lValue +// whitespace is permitted before and after : +FSTATUS StringToGid(uint64 *hValue, uint64 *lValue, const char* str, char **endptr, boolean skip_trail_whitespace) +{ + FSTATUS status; + char *end; + + status = StringToUint64(hValue, str, &end, 16, TRUE); + if (status != FSUCCESS) + return status; + if (end == NULL || *end != ':') + return FERROR; + end++; + return StringToUint64(lValue, end, endptr, 16, skip_trail_whitespace); +} + +// VESWPort of form guid:port:index or desc:port:index +// guid must be base 16, as such 0x prefix is optional. +// desc max size is MAX_VFABRIC_NAME (64) +// port and index are decimal +// whitespace is permitted before and after : +// byname = 0: the format is guid:port:index +// byname = 1: the format is desc:port:index +FSTATUS StringToVeswPort(uint64 *guid, char *desc, uint32 *port, uint32 *index, + const char* str, char **endptr, boolean skip_trail_whitespace, + boolean byname) +{ + FSTATUS status = FSUCCESS; + char *end, *string = NULL; + char *name; + + if (byname) { + string = strdup(str); + + name = strtok_r((char *)string, ":", &end); + if (name != NULL && strlen(name) <= MAX_VFABRIC_NAME && end != NULL) { + strcpy(desc, name); + } else { + status = FERROR; + goto out; + } + } else { + status = StringToUint64(guid, str, &end, 16, TRUE); + if (status != FSUCCESS || end == NULL || *end != ':') { + status = FERROR; + goto out; + } + end++; + } + + status = StringToUint32(port, end, &end, 10, TRUE); + if (status != FSUCCESS || end == NULL || *end != ':') { + status = FERROR; + goto out; + } + end++; + status = StringToUint32(index, end, endptr, 10, skip_trail_whitespace); +out: + if (string != NULL) { + free(string); + } + return status; +} + + +// MAC Address of form %02x:%02x:%02x:%02x:%02x:%02x +// values must be base16, 0x prefix is optional +FSTATUS StringToMAC(uint8_t *MAC,const char *str, char **endptr, + boolean skip_trail_whitespace) +{ + FSTATUS status; + char *end = NULL; + + status = StringToUint8(&MAC[0], str, &end, 16, FALSE); + if (status != FSUCCESS) + return status; + if ((end == NULL) || (*end != ':')) + return FERROR; + end++; + + status = StringToUint8(&MAC[1], end, &end, 16, FALSE); + if (status != FSUCCESS) + return status; + if ((end == NULL) || (*end != ':')) + return FERROR; + end++; + + status = StringToUint8(&MAC[2], end, &end, 16, FALSE); + if (status != FSUCCESS) + return status; + if ((end == NULL) || (*end != ':')) + return FERROR; + end++; + + status = StringToUint8(&MAC[3], end, &end, 16, FALSE); + if (status != FSUCCESS) + return status; + if ((end == NULL) || (*end != ':')) + return FERROR; + end++; + + status = StringToUint8(&MAC[4], end, &end, 16, FALSE); + if (status != FSUCCESS) + return status; + if ((end == NULL) || (*end != ':')) + return FERROR; + end++; + + status = StringToUint8(&MAC[5], end, endptr, 16, FALSE); + + return status; +} + + +// Byte Count as an integer followed by an optional suffix of: +// K, KB, M, MB, G or GB +// (K==KB, etc) +// converted to an absolute number of bytes +FSTATUS StringToUint64Bytes(uint64 *value, const char* str, char **endptr, int base, boolean skip_trail_whitespace) +{ + char *end; + FSTATUS status; + uint64 temp; + + status = StringToUint64(&temp, str, &end, base, skip_trail_whitespace); + if (status != FSUCCESS) + return status; + if (end) { + char *units = end; + // skip whitespace + while (isspace(*units)) { + units++; + } + // parse optional units + if (strncmp(units, "KB",2) == 0) { + temp *= 1024; + end = units+2; + } else if (strncmp(units, "K",1) == 0) { + temp *= 1024; + end = units+1; + } else if (strncmp(units, "MB",2) == 0) { + temp *= 1024*1024; + end = units+2; + } else if (strncmp(units, "M",1) == 0) { + temp *= 1024*1024; + end = units+1; + } else if (strncmp(units, "GB",2) == 0) { + temp *= (1024*1024*1024ULL); + end = units+2; + } else if (strncmp(units, "G",1) == 0) { + temp *= (1024*1024*1024ULL); + end = units+1; + } + } + + // skip whitespace + if (end && skip_trail_whitespace) { + while (isspace(*end)) { + end++; + } + } + if (endptr) + *endptr = end; + else if (end && *end != '\0') + return FERROR; + *value = temp; + return FSUCCESS; +} + +#if !defined(VXWORKS) +#define RELATIVE_TIME_STR_LEN 3 + // June 6th, 2015 11:59:59 PM + // as represented by the format +static const char * date_formats[] = {"%Y-%m-%d %T", // 2015-06-30 23:59:59 + "%Y-%m-%d %R", // 2015-06-30 23:59 + "%Y-%m-%d", // 2015-06-30 + "%m/%d/%Y %T", // 06/30/2015 23:59:59 + "%m/%d/%Y %R", // 06/30/2015 23:59 + "%m/%d/%Y", // 06/30/2015 + "%d.%m.%Y %T", // 30.06.2015 23:59:59 + "%d.%m.%Y %R", // 30.06.2015 23:59 + "%d.%m.%Y", // 30.06.2015 + // %x, %X are locale specific + "%x %X", // e.g. 30/06/15 23:59:59 or 30.06.2015 23.59.59, etc. + "%x", // e.g. 30/06/15, 06/30/15, etc. + "%X", // e.g. 23:59:59, 23.59.59, etc. + "%R"}; // 23:59 +static const char * time_units[] = {"seconds", "minutes", "hours", "days"}; + +/** + * StringToDateTime - parse a string to return a date/time + * + * @param value - will contain date as # of seconds since epoch if parsing successful + * @param str - the string representation of the date to be parsed + * + * @return - FSTATUS indicating success or failure of parsing: + * FSUCCESS - successful parsing + * FINVALID_PARAMETER - str not valid date/time or not in valid format + * FINVALID_SETTING - relative value out of range + * FINSUFFICIENT_MEMORY - memory could not be allocated to parse string + * FERROR - other error parsing string + */ +FSTATUS StringToDateTime(uint32 *value, const char* str){ + int i, len; + char * return_str; + struct tm tm = {0}; + uint32 seconds; + FSTATUS status; + + //try to match input to one of known formats from above + len = sizeof(date_formats) / sizeof(const char *); + for (i = 0; i < len; ++i){ + memset(&tm, 0, sizeof(struct tm)); + return_str = strptime(str, date_formats[i], &tm); + // want to match an exact format, meaning strptime returns null byte + if (return_str != NULL && *return_str == '\0'){ + break; + } + } + + if (return_str != NULL && *return_str== '\0'){ // possible valid date entered + struct tm tm2; + time_t timer; + if (i >= len - 2){ + // strptime matched against %X or %R, meaning we have a time + // but no information on the date. Fill in tm with today's date + time(&timer); //get current time + struct tm * tmp; + tmp = localtime(&timer); + if (!tmp){ + return FERROR; + } + tm.tm_year = tmp->tm_year; + tm.tm_mon = tmp->tm_mon; + tm.tm_mday = tmp->tm_mday; + tm.tm_wday = tmp->tm_wday; + tm.tm_yday = tmp->tm_yday; + } + // mktime will normalize fields of tm if they are outside their valid range, + // so make a copy before the mktime call and compare before and after. If the + // days of the month are not equal then the date enetered was not valid + memcpy(&tm2, &tm, sizeof(struct tm)); + tm.tm_isdst = -1; //signal mktime to determine if daylight saving in effect + timer = mktime(&tm); + if (timer != -1){ + //check if input time was a valid date, e.g. not 02/30/YYYY + if (tm.tm_mday != tm2.tm_mday){ + return FINVALID_PARAMETER; + }else{ + *value = (uint32) timer; + return FSUCCESS; + } + } + }else{ + // determine if time entered in the form + // " ago" where units is a member of time_units from above + char *string, *saveptr, *token, *tokens[RELATIVE_TIME_STR_LEN]; + + string = strdup(str); + if (!string){ + return FINSUFFICIENT_MEMORY; + } + + //split string by space (" ") + token = strtok_r(string, " ", &saveptr); + i = 0; + while (token != NULL){ + if (i >= RELATIVE_TIME_STR_LEN){ + //too many tokens + free(string); + return FERROR; + } + tokens[i] = token; + ++i; + token = strtok_r(NULL, " ", &saveptr); + } + + //check if proper number of tokens + if (i != RELATIVE_TIME_STR_LEN){ + free(string); + return FINVALID_PARAMETER; + } + + //check if first token is a valid base 10 number + status = StringToUint32(&seconds, tokens[0], NULL, 10, TRUE); + if (FSUCCESS != status){ + free(string); + return status; + } + + //check if second token in accepted units of time + len = sizeof(time_units) / sizeof (const char *); + for (i = 0; i < len; ++i){ + if (strcasecmp(time_units[i], tokens[1]) == 0 || strncasecmp(time_units[i], tokens[1], strlen(time_units[i]) - 1) == 0){ + break; + } + } + + //convert first token to seconds if necessary + if (i >= len){ + // could not determine units + free(string); + return FERROR; + } + + switch (i){ + case 0: + break; + case 1: //convert from minutes to seconds + seconds = seconds * 60; + break; + case 2: //convert from hours to seconds + seconds = seconds * 60 * 60; + break; + case 3: //convert from days to seconds + seconds = seconds * 24 * 60 * 60; + } + + //calculate absolute time to query for + time_t timer; + time(&timer); + *value = (uint32)timer - seconds; + + free(string); + return FSUCCESS; + } + + return FERROR; +} + +// Tuple of form select:comparator:argument +// select must be one of "utilization", "pktrate", "integrity", "congestion", "smacongestion", "bubbles", "security", or "routing". +// comparator must be one of "GT", "LT", "GE", "LE". +// argument may be any 64-bit value +// string inputs are case insensitive. +FSTATUS StringToTuple(uint32 *select, uint8 *comparator, uint64 *argument, char* str, char **endptr) +{ + FSTATUS status = FSUCCESS; + char *end; + char *selectstr; + char *comparatorstr; + char *argumentstr; + + if ((select == NULL) || (comparator == NULL) || (argument == NULL) || (str == NULL)) + return FERROR; + + selectstr = strtok_r(str, ":", &end); + + if (selectstr == NULL) + return FERROR; + + if (strcasecmp(selectstr, "utilization") == 0) + *select = STL_PA_SELECT_UTIL_HIGH; + else if (strcasecmp(selectstr, "pktrate") == 0) + *select = STL_PA_SELECT_UTIL_PKTS_HIGH; + else if (strcasecmp(selectstr, "integrity") == 0) + *select = STL_PA_SELECT_CATEGORY_INTEG; + else if (strcasecmp(selectstr, "congestion") == 0) + *select = STL_PA_SELECT_CATEGORY_CONG; + else if (strcasecmp(selectstr, "smacongestion") == 0) + *select = STL_PA_SELECT_CATEGORY_SMA_CONG; + else if (strcasecmp(selectstr, "bubbles") == 0) + *select = STL_PA_SELECT_CATEGORY_BUBBLE; + else if (strcasecmp(selectstr, "security") == 0) + *select = STL_PA_SELECT_CATEGORY_SEC; + else if (strcasecmp(selectstr, "routing") == 0) + *select = STL_PA_SELECT_CATEGORY_ROUT; + else + return FERROR; + + comparatorstr = strtok_r((char *)NULL, ":", &end); + + if (comparatorstr == NULL) + return FERROR; + + if (strcasecmp(comparatorstr, "GT") == 0) + *comparator = FOCUS_PORTS_COMPARATOR_GREATER_THAN; + else if (strcasecmp(comparatorstr, "LT") == 0) + *comparator = FOCUS_PORTS_COMPARATOR_LESS_THAN; + else if (strcasecmp(comparatorstr, "GE") == 0) + *comparator = FOCUS_PORTS_COMPARATOR_GREATER_THAN_OR_EQUAL; + else if (strcasecmp(comparatorstr, "LE") == 0) + *comparator = FOCUS_PORTS_COMPARATOR_LESS_THAN_OR_EQUAL; + else + return FERROR; + + argumentstr = strtok_r((char *)NULL, ":", &end); + + if (argumentstr) { + status = StringToUint64(argument, argumentstr, NULL, 0, TRUE); + return status; + } + + return FERROR; +} + +#endif + +#if !defined(VXWORKS) +#define MEMORY_ALLOCATE_PRIV(size, flags, tag) MemoryAllocatePriv(size, flags, tag) +#define MEMORY_ALLOCATE_PHYS_CONT_PRIV(size) MemoryAllocatePhysContPriv(size) +#define MEMORY_DEALLOCATE_PHYS_CONT_PRIV(size) MemoryDeallocatePhysContPriv(size) +#define MEMORY_DEALLOCATE_PRIV(ptr) MemoryDeallocatePriv(ptr) +#else +#define MEMORY_ALLOCATE_PRIV(size, flags, tag) MemoryAllocatePriv(size, __builtin_return_address(0)) +#define MEMORY_ALLOCATE_PHYS_CONT_PRIV(size) MemoryAllocatePhysContPriv(size, __builtin_return_address(0)) +#define MEMORY_DEALLOCATE_PHYS_CONT_PRIV(size) MemoryDeallocatePhysContPriv(size, __builtin_return_address(0)) +#define MEMORY_DEALLOCATE_PRIV(ptr) MemoryDeallocatePriv(ptr, __builtin_return_address(0)) +#endif + +#if defined(MEM_TRACK_ON) +// +// Destroy the memory tracker object. +// +static __inline void +DestroyMemTracker( void ) +{ + MEM_TRACKER *tmp; + if( !pMemTracker ) + return; + + tmp = pMemTracker; + pMemTracker = NULL; /* so no one uses it while we're destroying it */ + + // Destory all objects in the memory tracker object. + QListDestroy( &tmp->FreeHrdList ); + SpinLockDestroy( &tmp->Lock ); + QListDestroy( &tmp->AllocList ); + + // Free the memory allocated for the memory tracker object. + MEMORY_DEALLOCATE_PRIV( tmp ); +} + +// +// Allocate and initialize the memory tracker object. +// +static __inline boolean +CreateMemTracker( void ) +{ + MEM_TRACKER *tmp; + + if( pMemTracker ) + return TRUE; + + // Allocate the memory tracker object. Don't update global until we're done + tmp = (MEM_TRACKER*)MEMORY_ALLOCATE_PRIV( sizeof(MEM_TRACKER), IBA_MEM_FLAG_LEGACY, TRK_TAG ); + + if( !tmp ) + return FALSE; + + // Pre-initialize all objects in the memory tracker object. + QListInitState( &tmp->AllocList ); + SpinLockInitState( &tmp->Lock ); + QListInitState( &tmp->FreeHrdList ); + + // Initialize the list. + if( !QListInit( &tmp->AllocList ) ) + { + /* global isn't initialize, don't call Destroy func; do the clean up */ + MEMORY_DEALLOCATE_PRIV( tmp ); + return FALSE; + } + + // Initialize the spin lock to protect list operations. + if( !SpinLockInit( &tmp->Lock ) ) + { + /* global isn't initialize, don't call Destroy func; do the clean up */ + QListDestroy( &tmp->AllocList ); + SpinLockDestroy( &tmp->Lock ); + MEMORY_DEALLOCATE_PRIV( tmp ); + return FALSE; + } + + // Initialize the free list. + if( !QListInit( &tmp->FreeHrdList ) ) + { + /* global isn't initialize, don't call Destroy func; do the clean up */ + QListDestroy( &tmp->AllocList ); + SpinLockDestroy( &tmp->Lock ); + MEMORY_DEALLOCATE_PRIV( tmp ); + return FALSE; + } + +// MsgOut( "\n\n\n*** Memory tracker object address = %p ***\n\n\n", tmp ); + MsgOut( "\n*** Memory tracker enabled ***\n" ); + + /* NOW update the global */ + pMemTracker = tmp; + + return TRUE; +} +#endif + +// +// Enables memory allocation tracking. +// +static __inline void +MemoryTrackStart( void ) +{ +#if defined(MEM_TRACK_ON) + if( pMemTracker ) + return; + + CreateMemTracker(); +#endif // MEM_TRACK_ON +} + + +// +// Clean up memory tracking. +// +static __inline void +MemoryTrackStop( void ) +{ +#if defined(MEM_TRACK_ON) + LIST_ITEM *pListItem; + + if( !pMemTracker ) + return; + + if( QListCount( &pMemTracker->AllocList ) ) + { + // There are still items in the list. Print them out. + MemoryDisplayUsage(1, 0, 0); + } else { + MsgOut( "\n*** Memory tracker stopped, no leaks detected ***\n" ); + MsgOut("IbAccess max allocations=%u bytes=%u\n", + max_allocations, max_allocated); + } + + // Free all allocated headers. + SpinLockAcquire( &pMemTracker->Lock ); + while( (pListItem = QListRemoveHead( &pMemTracker->AllocList )) != NULL ) + { + SpinLockRelease( &pMemTracker->Lock ); + MEMORY_DEALLOCATE_PRIV( PARENT_STRUCT( pListItem, MEM_ALLOC_HDR, ListItem ) ); + SpinLockAcquire( &pMemTracker->Lock ); + } + while( (pListItem = QListRemoveHead( &pMemTracker->FreeHrdList )) != NULL ) + { + SpinLockRelease( &pMemTracker->Lock ); + MEMORY_DEALLOCATE_PRIV( PARENT_STRUCT( pListItem, MEM_ALLOC_HDR, ListItem ) ); + SpinLockAcquire( &pMemTracker->Lock ); + } + SpinLockRelease( &pMemTracker->Lock ); + + DestroyMemTracker(); +#endif // MEM_TRACK_ON +} + + +// +// Enables memory allocation tracking. +// +void +MemoryTrackUsage( + IN boolean Start ) +{ + if( Start ) + MemoryTrackStart(); + else + MemoryTrackStop(); +} + +#if defined(MEM_TRACK_ON) +static void +MemoryTrackerShow( + IN char *prefix, + IN MEM_ALLOC_HDR *pHdr, + IN char *suffix) +{ +#if defined(VXWORKS) + if ((int)pHdr->LineNum >= 0x00408000) { + MsgOut( "%s%p(%u) %s ra=%p tick=%u%s\n", prefix, + pHdr->ListItem.pObject, pHdr->Bytes, pHdr->trk->filename, + (void *)pHdr->LineNum, pHdr->tick, suffix ); + } else + MsgOut( "%s%p(%u) in file %s line %d tick=%u%s\n", prefix, + pHdr->ListItem.pObject, pHdr->Bytes, pHdr->trk->filename, + pHdr->LineNum, pHdr->tick, suffix ); +#else + MsgOut( "%s%p(%u) in file %s line %d%s\n", prefix, + pHdr->ListItem.pObject, pHdr->Bytes, pHdr->trk->filename, + pHdr->LineNum, suffix ); +#endif +} + +static void +MemoryTrackerCheckOverrun( + IN MEM_ALLOC_HDR *pHdr ) +{ +#ifdef MEM_TRACK_FTR + // Check that the user did not overrun his memory allocation. + if( (pHdr->pFtr != NULL) && (pHdr->pFtr->OutOfBound != TRK_TAG) ) + { + MemoryTrackerShow("*** User overrun detected ", pHdr, ""); + } +#endif +} + +/* unlink a header from the allocated list */ +/* must be called with pMemTracker->Lock held */ +static void +MemoryTrackerUnlink( + IN MEM_ALLOC_HDR *pHdr ) +{ + // Remove the item from the list. + QListRemoveItem( &pMemTracker->AllocList, &pHdr->ListItem ); + + --current_allocations; + current_allocated -= pHdr->Bytes; + if (pHdr->reported) + MemoryTrackerShow("", pHdr, " FREED"); + MemoryTrackerDereference(pHdr->trk); + // Return the header to the free header list. + QListInsertHead( &pMemTracker->FreeHrdList, &pHdr->ListItem ); +} +#endif // MEM_TRACK_ON + +// +// Display memory usage. +// +void +MemoryDisplayUsage( int method, uint32 minSize, uint32 minTick ) +{ +#if defined(MEM_TRACK_ON) + uint32 allocated = 0; + uint32 allocations = 0; + MEM_ALLOC_HDR *pHdr; + LIST_ITEM *item, *next, *tail, *head; + unsigned int allocations_per_sec = 0; + uint32 currentTime; + boolean all = (method == 1); + + if( !pMemTracker ) { + MsgOut( "*** IbAccess Memory Tracking is disabled ***\n" ); + return; + } + + /* "lock" present allocations by setting + * displaying flag, so other allocates/frees will not affect them + * This gives us a snapshot while permitting the system to run + * while we perform the output (the output itself may use memory allocate) + * However, our report loop below must stay within head/tail + */ + SpinLockAcquire( &pMemTracker->Lock ); + tail = QListTail(&pMemTracker->AllocList); + head = QListHead(&pMemTracker->AllocList); + for(item = head; item != NULL; item = QListNext(&pMemTracker->AllocList, item)) { + pHdr = PARENT_STRUCT( item, MEM_ALLOC_HDR, ListItem ); + pHdr->displaying = TRUE; + } + SpinLockRelease (&pMemTracker->Lock); + + MsgOut( "*** IbAccess Memory Usage %s minSize=%d minTick=%d ***\n", all?"All":"Unreported", minSize, minTick ); + + if (head && tail) { + item = head; + do { + next = QListNext(&pMemTracker->AllocList, item); + pHdr = PARENT_STRUCT( item, MEM_ALLOC_HDR, ListItem ); + + #ifdef MEM_TRACK_FTR + // Check that the user did not overrun his memory allocation. + if (pHdr->deallocate == FALSE) { + MemoryTrackerCheckOverrun(pHdr); + } + #endif // MEM_TRACK_FTR + if ((pHdr->Bytes >= minSize) && (pHdr->tick >= minTick) && (all || (pHdr->reported == 0))) { + // method 2 just marks all current allocations as reported, without actually reporting them + // method 3 displays the items without changing their reported state (allows us to avoid the FREED messages) + if (method != 2) + MemoryTrackerShow("", pHdr, ""); + if (method != 3) + pHdr->reported = 1; + } + allocated += pHdr->Bytes; + ++allocations; + SpinLockAcquire( &pMemTracker->Lock ); + pHdr->displaying = FALSE; + if (pHdr->deallocate) { + MemoryTrackerUnlink(pHdr); + } + SpinLockRelease (&pMemTracker->Lock); + item = next; + } while (&pHdr->ListItem != tail && item != NULL); + } + currentTime = GetTimeStampSec(); + if (last_reported_secs && currentTime != last_reported_secs) { + allocations_per_sec = (total_allocations - last_reported_allocations) / (currentTime - last_reported_secs); + } + last_reported_secs = currentTime; + last_reported_allocations = total_allocations; + MsgOut("IbAccess current allocations=%u bytes=%u max allocations=%u bytes=%u p/s=%d\n", + allocations, allocated, max_allocations, max_allocated, allocations_per_sec); +#endif // MEM_TRACK_ON +} + + +#if defined(MEM_TRACK_ON) +unsigned int hashValue(const char *key) { + unsigned int nHash = 0; + while (*key) + nHash = (nHash<<5) + nHash + *key++; + return nHash; +} + +static MemoryTrackerFileName_t *MemoryTrackerFileNameLookup(const char *filename, unsigned int *hash) { + unsigned int hashVal; + MemoryTrackerFileName_t *trk; + int len = strlen(filename); + + hashVal = hashValue(filename) % MEMORY_TRACKER_BUCKETS; + *hash = hashVal; + + for(trk = MemoryTrackerBuckets[hashVal]; trk != NULL; trk = trk->next) { + if (trk->filenameLen == len) { + if (memcmp(&trk->filename[0], filename, len) == 0) { + return trk; + } + } + } + return NULL; +} + +static MemoryTrackerFileName_t *MemoryTrackerFileNameAlloc(const char *filename, int filenameLen, unsigned int hash) { + MemoryTrackerFileName_t *trk; + + trk = (MemoryTrackerFileName_t*)MEMORY_ALLOCATE_PRIV( + sizeof( MemoryTrackerFileName_t ) + filenameLen + 1, + IBA_MEM_FLAG_LEGACY, TRK_TAG ); + if (trk != NULL) { + trk->referenceCount = 1; + trk->filenameLen = filenameLen; + memcpy(&trk->filename, filename, filenameLen + 1); + trk->next = MemoryTrackerBuckets[hash]; + MemoryTrackerBuckets[hash] = trk; + // MsgOut("Added len=%d name=(%p)%s\n", filenameLen, trk->filename, trk->filename); + } + return trk; +} + +static MemoryTrackerFileName_t *MemoryTrackerReference(const char *filename) { + MemoryTrackerFileName_t *trk; + int len = strlen(filename); + unsigned int hash; + + trk = MemoryTrackerFileNameLookup(filename, &hash); + if (trk == NULL) { + trk = MemoryTrackerFileNameAlloc(filename, len, hash); + if (trk == NULL) + return NULL; + } else { + ++trk->referenceCount; + } + return trk; +} + +static void MemoryTrackerDereference(MemoryTrackerFileName_t *trk) { + if (trk == NULL) { + MsgOut("Could not find reference to trk=%p\n", trk); + } else { + --trk->referenceCount; + } +} + +static void +MemoryTrackerTrackAllocation( + IN const char *pFileName, + IN int32 nLine, + IN uint32 Bytes, + IN uint32 flags, + IN void *pMem, + IN MEM_ALLOC_FTR *pFtr) +{ + MEM_ALLOC_HDR *pHdr; + LIST_ITEM *pListItem; + +#ifdef MEM_TRACK_FTR + if (pFtr) + pFtr->OutOfBound = TRK_TAG; +#endif // MEM_TRACK_FTR + + if( !pMemTracker ) { + if (unTindex < UNTRACKED_COUNT) + unTAddr[unTindex++] = pMem; + else { + static int firsttime=1; + if (firsttime) { + MsgOut("***** Untracked memory allocation array LIMIT:%d REACHED; check unTmissed value to calculate new size\n", UNTRACKED_COUNT); + firsttime = 0; + } + unTmissed++; /* so we know how much more to expand the array */ + } + return; + } + + // Get a header from the free header list. + SpinLockAcquire( &pMemTracker->Lock ); + pListItem = QListRemoveHead( &pMemTracker->FreeHrdList ); + SpinLockRelease( &pMemTracker->Lock ); + + if( pListItem ) + { + // Set the header pointer to the header retrieved from the list. + pHdr = PARENT_STRUCT( pListItem, MEM_ALLOC_HDR, ListItem ); + } + else + { + // We failed to get a free header. Allocate one. + // we can prempt if caller allows it, however we do not want + // pageable, nor short duration memory + pHdr = (MEM_ALLOC_HDR*)MEMORY_ALLOCATE_PRIV( sizeof( MEM_ALLOC_HDR ), + flags & IBA_MEM_FLAG_PREMPTABLE, TRK_TAG ); + if( !pHdr ) + { + // We failed to allocate the header, don't track this allocate + return; + } + } + pHdr->LineNum = nLine; + pHdr->tick = TICK; + pHdr->Bytes = Bytes; + pHdr->reported = 0; + pHdr->displaying = FALSE; + pHdr->deallocate = FALSE; + // We store the pointer to the memory returned to the user. This allows + // searching the list of allocated memory even if the buffer allocated is + // not in the list without dereferencing memory we do not own. + pHdr->ListItem.pObject = pMem; + +#ifdef MEM_TRACK_FTR + pHdr->pFtr = pFtr; +#else + pHdr->pFtr = NULL; +#endif // MEM_TRACK_FTR + + SpinLockAcquire( &pMemTracker->Lock ); + pHdr->trk = MemoryTrackerReference(pFileName); + ++total_allocations; + if (++current_allocations > max_allocations) + max_allocations = current_allocations; + if ((current_allocated += pHdr->Bytes) > max_allocated) + max_allocated = current_allocated; + + // Insert the header structure into our allocation list. + QListInsertTail( &pMemTracker->AllocList, &pHdr->ListItem ); + SpinLockRelease( &pMemTracker->Lock ); + + return; +} + +int +MemoryTrackerTrackDeallocate( + IN void *pMemory ) +{ + MEM_ALLOC_HDR *pHdr; + LIST_ITEM *pListItem; + int result = 0; + + if( pMemTracker ) + { + SpinLockAcquire( &pMemTracker->Lock ); + + // Removes an item from the allocation tracking list given a pointer + // To the user's data and returns the pointer to header referencing the + // allocated memory block. + pListItem = + QListFindFromTail( &pMemTracker->AllocList, NULL, pMemory ); + + if( pListItem ) + { + // Get the pointer to the header. + pHdr = PARENT_STRUCT( pListItem, MEM_ALLOC_HDR, ListItem ); +#ifdef MEM_TRACK_FTR + MemoryTrackerCheckOverrun(pHdr); +#endif // MEM_TRACK_FTR + + if (pHdr->displaying) { + pHdr->deallocate = TRUE; + } else { + // Remove the item from the list. + MemoryTrackerUnlink(pHdr); + } + } else { + int ii, found; + for (ii=0, found=0; iiLock ); + } + return result; +} + +// +// Allocates memory and stores information about the allocation in a list. +// The contents of the list can be printed out by calling the function +// "MemoryReportUsage". Memory allocation will succeed even if the list +// cannot be created. +// +void* +MemoryAllocateDbg( + IN const char *pFileName, + IN int32 nLine, + IN uint32 Bytes, + IN boolean IsPageable, + IN uint32 Tag ) +{ + return MemoryAllocate2Dbg(pFileName, nLine, Bytes, + (IsPageable?IBA_MEM_FLAG_PAGEABLE:IBA_MEM_FLAG_NONE) + |IBA_MEM_FLAG_LEGACY, Tag); +} + +#if defined(VXWORKS) +void +MemoryAllocateVxWorksTrack( + IN void *result, + IN uint32 Bytes, + IN char *reason, + IN void *caller) +{ + MemoryTrackerTrackAllocation(reason, (int)caller, Bytes, IBA_MEM_FLAG_NONE, result, NULL); +} +#endif + +void* +MemoryAllocate2Dbg( + IN const char *pFileName, + IN int32 nLine, + IN uint32 Bytes, + IN uint32 flags, + IN uint32 Tag ) +{ + void *pMem; + +#ifdef MEM_TRACK_FTR + // Increase the size of our allocation to account for the footer. + Bytes += sizeof( MEM_ALLOC_FTR ); + Bytes = (Bytes + 3) >> 2 << 2; +#endif // MEM_TRACK_FTR + + // Allocate the memory first, so that we give the user's allocation + // priority over the the header allocation. + pMem = MEMORY_ALLOCATE_PRIV( Bytes, flags, Tag ); + + if( !pMem ) + return NULL; + + MemoryTrackerTrackAllocation(pFileName, nLine, Bytes, flags, pMem, +#ifdef MEM_TRACK_FTR + (MEM_ALLOC_FTR*)((uchar*)pMem + Bytes - sizeof( MEM_ALLOC_FTR )) +#else + NULL +#endif + ); + + return pMem; +} + +void* +MemoryAllocateRel( + IN uint32 Bytes, + IN boolean IsPageable, + IN uint32 Tag ) +{ + return MemoryAllocateDbg( "Unknown", 0, Bytes, IsPageable, Tag ); +} +void* +MemoryAllocate2Rel( + IN uint32 Bytes, + IN uint32 flags, + IN uint32 Tag ) +{ + return MemoryAllocate2Dbg( "Unknown", 0, Bytes, flags, Tag ); +} + +#if defined(VXWORKS) +void* +MemoryAllocatePhysContDbg( + IN const char *pFileName, + IN int32 nLine, + IN uint32 Bytes ) +{ + void *pMem; + + /* no footer on PhysCont allocates, they tend to be a full page + * and a footer would waste another page, TBD we could round up + * provided resulting Bytes was still same number of pages + */ + + // Allocate the memory first, so that we give the user's allocation + // priority over the the header allocation. + pMem = MEMORY_ALLOCATE_PHYS_CONT_PRIV( Bytes ); + + if( !pMem ) + return NULL; + + MemoryTrackerTrackAllocation(pFileName, nLine, Bytes, IBA_MEM_FLAG_PREMPTABLE, pMem, NULL); + + return pMem; +} + +void* +MemoryAllocatePhysContRel( + IN uint32 Bytes ) +{ + return MemoryAllocatePhysContDbg( "Unknown", 0, Bytes ); +} +#endif /* defined(VXWORKS) */ +#else // !MEM_TRACK_ON +void* +MemoryAllocateDbg( + IN const char *pFileName, + IN int32 nLine, + IN uint32 Bytes, + IN boolean IsPageable, + IN uint32 Tag ) +{ + return MEMORY_ALLOCATE_PRIV( Bytes, + (IsPageable?IBA_MEM_FLAG_PAGEABLE:IBA_MEM_FLAG_NONE) + |IBA_MEM_FLAG_LEGACY, Tag ); +} + +void* +MemoryAllocate2Dbg( + IN const char *pFileName, + IN int32 nLine, + IN uint32 Bytes, + IN uint32 flags, + IN uint32 Tag ) +{ + return MEMORY_ALLOCATE_PRIV( Bytes, flags, Tag); +} +void* +MemoryAllocateRel( + IN uint32 Bytes, + IN boolean IsPageable, + IN uint32 Tag ) +{ + return MEMORY_ALLOCATE_PRIV( Bytes, + (IsPageable?IBA_MEM_FLAG_PAGEABLE:IBA_MEM_FLAG_NONE) + |IBA_MEM_FLAG_LEGACY, Tag ); +} + +void* +MemoryAllocate2Rel( + IN uint32 Bytes, + IN uint32 flags, + IN uint32 Tag ) +{ + return MEMORY_ALLOCATE_PRIV( Bytes, flags, Tag); +} + +#if defined(VXWORKS) +void* +MemoryAllocatePhysContDbg( + IN const char *pFileName, + IN int32 nLine, + IN uint32 Bytes ) +{ + return MEMORY_ALLOCATE_PHYS_CONT_PRIV( Bytes ); +} + +void* +MemoryAllocatePhysContRel( + IN uint32 Bytes ) +{ + return MEMORY_ALLOCATE_PHYS_CONT_PRIV( Bytes ); +} +#endif /* defined(VXWORKS) */ +#endif // MEM_TRACK_ON + + +#if defined(MEM_TRACK_ON) +void* +MemoryAllocateAndClearDbg( + IN const char *pFileName, + IN int32 nLine, + IN uint32 Bytes, + IN boolean IsPageable, + IN uint32 Tag ) +{ + return MemoryAllocate2AndClearDbg(pFileName, nLine, Bytes, + (IsPageable?IBA_MEM_FLAG_PAGEABLE:IBA_MEM_FLAG_NONE) + |IBA_MEM_FLAG_LEGACY, Tag ); +} +void* +MemoryAllocate2AndClearDbg( + IN const char *pFileName, + IN int32 nLine, + IN uint32 Bytes, + IN uint32 flags, + IN uint32 Tag ) +{ + void *pBuffer; + + if( (pBuffer = MemoryAllocate2Dbg( pFileName, nLine, Bytes, flags, Tag )) != NULL ) + { + MemoryClear( pBuffer, Bytes ); + } + + return pBuffer; +} + +void* +MemoryAllocateAndClearRel( + IN uint32 Bytes, + IN boolean IsPageable, + IN uint32 Tag ) +{ + return MemoryAllocateAndClearDbg("Unknown", 0, Bytes, IsPageable, Tag); +} + +void* +MemoryAllocate2AndClearRel( + IN uint32 Bytes, + IN uint32 flags, + IN uint32 Tag ) +{ + return MemoryAllocate2AndClearDbg("Unknown", 0, Bytes, flags, Tag); +} + +#else // !MEM_TRACK_ON +void* +MemoryAllocateAndClearDbg( + IN const char *pFileName, + IN int32 nLine, + IN uint32 Bytes, + IN boolean IsPageable, + IN uint32 Tag ) +{ + return MemoryAllocate2AndClear(Bytes, + (IsPageable?IBA_MEM_FLAG_PAGEABLE:IBA_MEM_FLAG_NONE) + |IBA_MEM_FLAG_LEGACY, Tag ); +} + +void* +MemoryAllocate2AndClearDbg( + IN const char *pFileName, + IN int32 nLine, + IN uint32 Bytes, + IN uint32 flags, + IN uint32 Tag ) +{ + return MemoryAllocate2AndClear(Bytes, flags, Tag); +} + +void* +MemoryAllocateAndClearRel( + IN uint32 Bytes, + IN boolean IsPageable, + IN uint32 Tag ) +{ + return MemoryAllocate2AndClear(Bytes, + (IsPageable?IBA_MEM_FLAG_PAGEABLE:IBA_MEM_FLAG_NONE) + |IBA_MEM_FLAG_LEGACY, Tag ); +} + +void* +MemoryAllocate2AndClearRel( + IN uint32 Bytes, + IN uint32 flags, + IN uint32 Tag ) +{ + void *pBuffer; + + if( (pBuffer = MEMORY_ALLOCATE_PRIV( Bytes, flags, Tag )) != NULL ) + { + MemoryClear( pBuffer, Bytes ); + } + + return pBuffer; +} +#endif // !MEM_TRACK_ON + + +int +MemoryDeallocate( + IN void *pMemory ) +{ +#if defined(MEM_TRACK_ON) + int result; + + if (pMemory == NULL) + return 0; + + result = MemoryTrackerTrackDeallocate(pMemory ); + MEMORY_DEALLOCATE_PRIV( pMemory ); + return result; +#else + MEMORY_DEALLOCATE_PRIV( pMemory ); + return 0; +#endif // MEM_TRACK_ON + +} + +#if defined(VXWORKS) +void +MemoryDeallocatePhysCont( + IN void *pMemory ) +{ +#if defined(MEM_TRACK_ON) + (void)MemoryTrackerTrackDeallocate(pMemory ); +#endif // MEM_TRACK_ON + MEMORY_DEALLOCATE_PHYS_CONT_PRIV( pMemory ); +} +#endif /* defined(VXWORKS) */ + +void +MemoryClear( + IN void *pMemory, + IN uint32 Bytes ) +{ + MemoryFill( pMemory, 0, Bytes ); +} + + +#if defined(MEM_TRACK_ON) +void* +MemoryAllocateObjectArrayRel( + IN uint32 ObjectCount, + IN OUT uint32 *pObjectSize, + IN uint32 ByteAlignment, + IN uint32 AlignmentOffset, + IN boolean IsPageable, + IN uint32 Tag, + OUT void **ppFirstObject, + OUT uint32 *pArraySize ) +{ + return MemoryAllocateObjectArrayDbg("Unknown", 0, ObjectCount, pObjectSize, + ByteAlignment, AlignmentOffset, IsPageable, Tag, + ppFirstObject, pArraySize); +} + +void* +MemoryAllocateObjectArrayDbg( + IN const char *pFileName, + int32 nLine, + IN uint32 ObjectCount, + IN OUT uint32 *pObjectSize, + IN uint32 ByteAlignment, + IN uint32 AlignmentOffset, + IN boolean IsPageable, + IN uint32 Tag, + OUT void **ppFirstObject, + OUT uint32 *pArraySize ) +#else // !MEM_TRACK_ON +void* +MemoryAllocateObjectArrayDbg( + IN const char *pFileName, + int32 nLine, + IN uint32 ObjectCount, + IN OUT uint32 *pObjectSize, + IN uint32 ByteAlignment, + IN uint32 AlignmentOffset, + IN boolean IsPageable, + IN uint32 Tag, + OUT void **ppFirstObject, + OUT uint32 *pArraySize ) +{ + return MemoryAllocateObjectArrayRel(ObjectCount, pObjectSize, ByteAlignment, + AlignmentOffset, IsPageable, Tag, + ppFirstObject, pArraySize); +} + +void* +MemoryAllocateObjectArrayRel( + IN uint32 ObjectCount, + IN OUT uint32 *pObjectSize, + IN uint32 ByteAlignment, + IN uint32 AlignmentOffset, + IN boolean IsPageable, + IN uint32 Tag, + OUT void **ppFirstObject, + OUT uint32 *pArraySize ) +#endif // MEM_TRACK_ON +{ + void *pArray; + + ASSERT( ObjectCount && *pObjectSize && AlignmentOffset < *pObjectSize ); + + if( ByteAlignment > 1) + { + // Fixup the object size based on the alignment specified. + *pObjectSize = ((*pObjectSize) + ByteAlignment - 1) - + (((*pObjectSize) + ByteAlignment - 1) % ByteAlignment); + } + + // Determine the size of the buffer to allocate. + *pArraySize = (ObjectCount * (*pObjectSize)) + ByteAlignment; + + // Allocate the array of objects. +#if defined(MEM_TRACK_ON) + if( !(pArray = MemoryAllocateAndClearDbg( pFileName, nLine, *pArraySize, + IsPageable, Tag )) ) +#else // !MEM_TRACK_ON + if( !(pArray = MemoryAllocateAndClear( *pArraySize, IsPageable, Tag )) ) + +#endif // MEM_TRACK_ON + { + *pArraySize = 0; + return NULL; + } + + if( ByteAlignment > 1 ) + { + // Calculate the pointer to the first object that is properly aligned. + *ppFirstObject = (void*)( + ((uchar*)pArray + AlignmentOffset + ByteAlignment - 1) - + (((uintn)pArray + AlignmentOffset + ByteAlignment - 1) % + ByteAlignment )); + } + else + { + *ppFirstObject = pArray; + } + return pArray; +} + diff --git a/IbAccess/Common/Public/imemory.h b/IbAccess/Common/Public/imemory.h new file mode 100644 index 0000000..5bdd18c --- /dev/null +++ b/IbAccess/Common/Public/imemory.h @@ -0,0 +1,629 @@ +/* BEGIN_ICS_COPYRIGHT3 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT3 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +#ifndef _IBA_PUBLIC_IMEMORY_H_ +#define _IBA_PUBLIC_IMEMORY_H_ + + +#include "iba/public/datatypes.h" +#include "iba/public/imath.h" +#ifdef _NATIVE_MEMORY +#include "iba/public/imemory_osd.h" +#endif + +#ifndef MAKE_MEM_TAG_DEFINED +#define MAKE_MEM_TAG( a, b, c, d ) 0 +#define MAKE_MEM_TAG_DEFINED +#endif /* MAKE_MEM_TAG */ + +#ifdef __cplusplus +extern "C" +{ +#endif +/* Enable and disables memory lock debug */ +#ifndef MLOCK_DBG /* allow to be set from CFLAGS */ +#define MLOCK_DBG 0 /* 0=no, 1=validate, 2=validate+log */ +#endif + +/* flags for memory allocation controls */ +#define IBA_MEM_FLAG_NONE 0x0000 +#define IBA_MEM_FLAG_LEGACY 0x0001 /* old style mode */ +#define IBA_MEM_FLAG_PREMPTABLE 0x0002 /* may sleep during alloc/free */ +#define IBA_MEM_FLAG_PAGEABLE 0x0004 /* memory allocated may be pageable */ +#define IBA_MEM_FLAG_SHORT_DURATION 0x0008 /* memory will be freed soon */ +#define IBA_MEM_FLAG_PREFER_CONTIG 0x0010 /* prefer phys contig pages */ +#define IBA_MEM_FLAG_INTR_SVC_THREAD 0x0020 /* in an IntrServiceThread, no locks */ + +/* Enables and disables tracking of memory allocation. */ +void +MemoryTrackUsage( + IN boolean Start ); + +/* Prints all memory allocation information. */ +void +MemoryDisplayUsage( int method, uint32 minSize, uint32 minTick ); + +/* Turn on memory allocation tracking in debug builds if not already turned on. */ +#if !defined(MALLOC_TRACK_ON) + #define MALLOC_TRACK_ON +#endif + +#ifdef MEM_TRACK_ON +/* Debug versions of memory allocation calls store the file name + * and line number where invoked in a header for use in tracking memory + * leaks. + */ +#define MemoryAllocate( a, b, c ) \ + MemoryAllocate2Dbg( __FILE__, __LINE__, a, (b?IBA_MEM_FLAG_PAGEABLE:IBA_MEM_FLAG_NONE)|IBA_MEM_FLAG_LEGACY, c ) + +#define MemoryAllocateAndClear( a, b, c ) \ + MemoryAllocate2AndClearDbg( __FILE__, __LINE__, a, (b?IBA_MEM_FLAG_PAGEABLE:IBA_MEM_FLAG_NONE)|IBA_MEM_FLAG_LEGACY, c ) + +#define MemoryAllocateObjectArray( a, b, c, d, e, f, g, h ) \ + MemoryAllocateObjectArrayDbg( __FILE__, __LINE__, a, b, c, d, e, f, g, h ) + +#define MemoryAllocate2( a, b, c ) \ + MemoryAllocate2Dbg( __FILE__, __LINE__, a, b, c ) + +#define MemoryAllocate2AndClear( a, b, c ) \ + MemoryAllocate2AndClearDbg( __FILE__, __LINE__, a, b, c ) + +#else + +#define MemoryAllocate( a, b, c ) \ + MemoryAllocate2Rel( a, (b?IBA_MEM_FLAG_PAGEABLE:IBA_MEM_FLAG_NONE)|IBA_MEM_FLAG_LEGACY, c ) + +#define MemoryAllocateAndClear( a, b, c ) \ + MemoryAllocate2AndClearRel( a, (b?IBA_MEM_FLAG_PAGEABLE:IBA_MEM_FLAG_NONE)|IBA_MEM_FLAG_LEGACY, c ) + +#define MemoryAllocateObjectArray( a, b, c, d, e, f, g, h ) \ + MemoryAllocateObjectArrayRel(a, b, c, d, e, f, g, h ) + +#define MemoryAllocate2( a, b, c ) \ + MemoryAllocate2Rel(a, b, c ) + +#define MemoryAllocate2AndClear( a, b, c ) \ + MemoryAllocate2AndClearRel( a, b, c ) + +#endif + + + +/* Allocate memory region. */ +void* +MemoryAllocateDbg( + IN const char *pFileName, + IN int32 nLine, + IN uint32 Bytes, + IN boolean IsPageable, + IN uint32 Tag ); +void* +MemoryAllocateRel( + IN uint32 Bytes, + IN boolean IsPageable, + IN uint32 Tag ); + +void* +MemoryAllocate2Dbg( + IN const char *pFileName, + IN int32 nLine, + IN uint32 Bytes, + IN uint32 flags, + IN uint32 Tag ); +void* +MemoryAllocate2Rel( + IN uint32 Bytes, + IN uint32 flags, + IN uint32 Tag ); + +/* Allocate memory region and set the memory to 0. */ +void* +MemoryAllocateAndClearDbg( + IN const char *pFileName, + IN int32 nLine, + IN uint32 Bytes, + IN boolean IsPageable, + IN uint32 Tag ); +void* +MemoryAllocateAndClearRel( + IN uint32 Bytes, + IN boolean IsPageable, + IN uint32 Tag ); + +void* +MemoryAllocate2AndClearDbg( + IN const char *pFileName, + IN int32 nLine, + IN uint32 Bytes, + IN uint32 flags, + IN uint32 Tag ); +void* +MemoryAllocate2AndClearRel( + IN uint32 Bytes, + IN uint32 flags, + IN uint32 Tag ); + +/* Allocate an array of objects alligned on arbitrary byte boundary. */ +void* +MemoryAllocateObjectArrayDbg( + IN const char *pFileName, + IN int32 nLine, + IN uint32 ObjectCount, + IN OUT uint32 *pObjectSize, + IN uint32 ByteAlignment, + IN uint32 AlignmentOffset, + IN boolean IsPageable, + IN uint32 Tag, + OUT void **ppFirstObject, + OUT uint32 *pArraySize ); +void* +MemoryAllocateObjectArrayRel( + IN uint32 ObjectCount, + IN OUT uint32 *pObjectSize, + IN uint32 ByteAlignment, + IN uint32 AlignmentOffset, + IN boolean IsPageable, + IN uint32 Tag, + OUT void **ppFirstObject, + OUT uint32 *pArraySize ); + +/* Release allocated memory. */ +int +MemoryDeallocate( + IN void *pMemory ); + +/* Fill allocated memory with a specified value. */ +void +MemoryFill( + IN void *pMemory, + IN uchar Fill, + IN uint32 Bytes ); + +/* Clear allocated memory. */ +void +MemoryClear( + IN void *pMemory, + IN uint32 Bytes ); + +/* Copy one buffer into another. */ +void* +MemoryCopy( + IN void *pDest, + IN const void *pSrc, + IN uint32 Bytes ); + +/* Compare two buffers. Functions similarly to the standard C memcmp call. */ +int32 +MemoryCompare( + IN const void *pMemory1, + IN const void *pMemory2, + IN uint32 Bytes ); + +/* round address down to a page boundary and adjust Length to + * end of a page boundary + * page_size must be a power of 2 + */ +static _inline void MemoryFixAddrLength(IN uint32 page_size, + IN OUT void** VirtualAddress, + IN OUT uintn* Length) +{ + /* bytes between page boundary and VirtualAddress */ + uintn start_offset = ((uintn)*VirtualAddress) & (page_size-1); + + /* round down virtual address to a page boundary */ + *VirtualAddress = (void*)((uintn)*VirtualAddress - start_offset); + *Length += start_offset; + + /* round up Length to a page boundary */ + *Length = ROUNDUPP2(*Length, page_size); +} +/** + * Safe version of strncpy that will always null terminate. Copies up to + * dstsize-1 characters from source to dest plus a null terminator. + * + * @param dest A pointer to destination buffer + * @param source A pointer to source buffer + * @param dstsize Size of dest buffer + * + * @return dest on Success or NULL on failure + */ +static _inline char * StringCopy(char * dest, const char * source, size_t dstsize) +{ + if(!dest || !dstsize || !source) + return NULL; + +#if defined(VXWORKS) + size_t l = MIN(dstsize-1,strlen(source)); +#else + size_t l = strnlen(source, dstsize-1); +#endif + memcpy(dest,source,l); + dest[l] = '\0'; + return dest; +} + +/** + * Concatenates all of the given strings into one long string. The returned + * string should be freed by #free. Variable arguments must end with NULL. + * Otherwise the function will be appending random memory junks. + * @param str1 first string to be concatenated + * @param ... a NULL-terminated list of strings + * @return newly allocated string containing all provided strings + */ +char* StringConcat(const char* str1, ...); + + +// convert a string to a uint or int +// Very similar to strtoull/strtoll except that +// base=0 implies base 10 or 16, but excludes base 8 +// hence allowing leading 0's for base 10. +// +// Also provides easier to use status returns and error checking. +// +// Can also optionally skip trailing whitespace, when skip_trail_whitespace is +// FALSE, trailing whitespace is treated as a FERROR +// +// When endptr is NULL, trailing characters (after optional whitespace) are +// considered an FERROR. When endptr is non-NULL, for a FSUCCESS conversion, +// it points to the characters after the optional trailing whitespace. +// Errors: +// FSUCCESS - successful conversion, *endptr points to 1st char after value +// FERROR - invalid contents, non-numeric, *endptr and *value undefined +// FINVALID_SETTING - value out of range, *endptr and *value undefined +// FINVALID_PARAMETER - invalid function arguments (NULL value or str) +FSTATUS StringToUint64(uint64 *value, const char* str, char **endptr, int base, boolean skip_trail_whitespace); +FSTATUS StringToUint32(uint32 *value, const char* str, char **endptr, int base, boolean skip_trail_whitespace); +FSTATUS StringToUint16(uint16 *value, const char* str, char **endptr, int base, boolean skip_trail_whitespace); +FSTATUS StringToUint8(uint8 *value, const char* str, char **endptr, int base, boolean skip_trail_whitespace); +FSTATUS StringToInt64(int64 *value, const char* str, char **endptr, int base, boolean skip_trail_whitespace); +FSTATUS StringToInt32(int32 *value, const char* str, char **endptr, int base, boolean skip_trail_whitespace); +FSTATUS StringToInt16(int16 *value, const char* str, char **endptr, int base, boolean skip_trail_whitespace); +FSTATUS StringToInt8(int8 *value, const char* str, char **endptr, int base, boolean skip_trail_whitespace); +// GID of form hValue:lValue +// values must be base 16, as such 0x prefix is optional for both hValue and +// lValue +// whitespace is permitted before and after : +FSTATUS StringToGid(uint64 *hValue, uint64 *lValue, const char* str, char **endptr, boolean skip_trail_whitespace); +// VESWPort of form guid:port:index or desc:port:index +// guid must be base 16, as such 0x prefix is optional. +// desc max size is MAX_VFABRIC_NAME (64) +// port and index are decimal +// whitespace is permitted before and after : +// byname = 0: the format is guid:port:index +// byname = 1: the format is desc:port:index +FSTATUS StringToVeswPort(uint64 *guid, char *desc, uint32 *port, uint32 *index, + const char* str, char **endptr, boolean skip_trail_whitespace, + boolean byname); + +// MAC Address of form %02x:%02x:%02x:%02x:%02x:%02x +// values must be base16, 0x prefix is optional +FSTATUS StringToMAC(uint8_t *MAC,const char *str, char **endptr, + boolean skip_trail_whitespace); + +// Byte Count as an integer followed by an optional suffix of: +// K, KB, M, MB, G or GB +// (K==KB, etc) +// converted to an absolute number of bytes +FSTATUS StringToUint64Bytes(uint64 *value, const char* str, char **endptr, int base, boolean skip_trail_whitespace); +/** + * StringToDateTime - parse a string to return a date/time + * + * @param value - will contain date as # of seconds since epoch if parsing successful + * @param str - the string representation of the date to be parsed + * + * @return - FSTATUS indicating success or failure of parsing: + * FSUCCESS - successful parsing + * FINVALID_PARAMETER - str not valid date/time or not in valid format + * FINVALID_SETTING - relative value out of range + * FINSUFFICIENT_MEMORY - memory could not be allocated to parse string + * FERROR - other error parsing string + */ +FSTATUS StringToDateTime(uint32 *value, const char * str); + +// Tuple of form select:comparator:argument +// select must be one of "utilization", "pktrate", "integrity", "congestion", "smacongestion", "bubbles", "security", or "routing". +// comparator must be one of "gt", "ge", "lt", "le". +// argument may be any 64-bit value +FSTATUS StringToTuple(uint32 *select, uint8 *comparator, uint64 *argument, char* str, char **endptr); + +#if defined(VXWORKS) +/* internal private functions not for general use, these are supplied + * by the OS specific imemory_osd module + */ +void* +MemoryAllocatePhysContPriv( IN uint32 Bytes, void *caller ); + +void +MemoryDeallocatePhysContPriv( IN void *pMemory, void *caller ); + +/* macros for general use */ +#ifdef MEM_TRACK_ON +#define MemoryAllocatePhysCont( a ) \ + MemoryAllocatePhysContDbg( __FILE__, __LINE__, a ) +#else +#define MemoryAllocatePhysCont( a ) \ + MemoryAllocatePhysContRel( a ) +#endif + +/* internal routines, not for general use */ +void* +MemoryAllocatePhysContDbg( + IN const char *pFileName, + IN int32 nLine, + IN uint32 Bytes ); + +void* +MemoryAllocatePhysContRel( + IN uint32 Bytes ); + +void +MemoryDeallocatePhysCont( + IN void *pMemory ); + +/* allocate physically contiguous memory aligned to a "align" boundary + * + * INPUT: + * size - size of memory in bytes + * align - power of 2 to align to + * OUTPUT: + * aligned_addr - aligned address + * RETURNS: + * actual start of memory allocated, use this for MemoryDeallocate + * NULL on error + */ +#ifdef MEM_TRACK_ON +#define MemoryAllocatePhysContAligned( a, b, c ) \ + MemoryAllocatePhysContAlignedDbg( __FILE__, __LINE__, a, b, c ) +static _inline void* MemoryAllocatePhysContAlignedDbg( + IN const char *pFileName, + IN int32 nLine, +#else +static _inline void* MemoryAllocatePhysContAligned( +#endif + IN uint32 size, + IN uint32 align, + OUT void **aligned_addr + ) +{ + void *buf; + +#ifdef MEM_TRACK_ON + buf = MemoryAllocatePhysContDbg(pFileName, nLine, size+align-1); +#else + buf = MemoryAllocatePhysCont(size+align-1); +#endif + *aligned_addr = (void*)ROUNDUPP2((uintn)buf,align); + return buf; +} +#ifdef MEM_TRACK_ON +#define MemoryAllocatePhysContAlignedAndClear( a, b, c ) \ + MemoryAllocatePhysContAlignedAndClearDbg( __FILE__, __LINE__, a, b, c ) +static _inline void* MemoryAllocatePhysContAlignedAndClearDbg( + IN const char *pFileName, + IN int32 nLine, +#else +static _inline void* MemoryAllocatePhysContAlignedAndClear( +#endif + IN uint32 size, + IN uint32 align, + OUT void **aligned_addr + ) +{ +#ifdef MEM_TRACK_ON + void *buf = MemoryAllocatePhysContAlignedDbg(pFileName, nLine, size, align, aligned_addr); +#else + void *buf = MemoryAllocatePhysContAligned(size, align, aligned_addr); +#endif + if (buf) + MemoryClear(*aligned_addr, size); + return buf; +} +#endif /* defined(VXWORKS) */ + +/* allocate memory aligned to a "align" boundary + * + * INPUT: + * size - size of memory in bytes + * align - power of 2 to align to + * tag - tag for memory tracker + * OUTPUT: + * aligned_addr - aligned address + * RETURNS: + * actual start of memory allocated, use this for MemoryDeallocate + * NULL on error + */ +#ifdef MEM_TRACK_ON +#define MemoryAllocateAligned( a, b, c, d, e ) \ + MemoryAllocateAlignedDbg( __FILE__, __LINE__, a, b, c, d, e ) +static _inline void* MemoryAllocateAlignedDbg( + IN const char *pFileName, + IN int32 nLine, +#else +static _inline void* MemoryAllocateAligned( +#endif + IN uint32 size, + IN uint32 align, + IN boolean IsPageable, + IN uint32 tag, + OUT void **aligned_addr + ) +{ + void *buf; + +#ifdef MEM_TRACK_ON + buf = MemoryAllocateDbg(pFileName, nLine, size+align-1, IsPageable, tag); +#else + buf = MemoryAllocate(size+align-1, IsPageable, tag); +#endif + *aligned_addr = (void*)ROUNDUPP2((uintn)buf,align); + return buf; +} + +#ifdef MEM_TRACK_ON +#define MemoryAllocateAlignedAndClear( a, b, c, d, e ) \ + MemoryAllocateAlignedAndClearDbg( __FILE__, __LINE__, a, b, c, d, e ) +static _inline void* MemoryAllocateAlignedAndClearDbg( + IN const char *pFileName, + IN int32 nLine, +#else +static _inline void* MemoryAllocateAlignedAndClear( +#endif + IN uint32 size, + IN uint32 align, + IN boolean IsPageable, + IN uint32 tag, + OUT void **aligned_addr + ) +{ + void *buf; + +#ifdef MEM_TRACK_ON + buf = MemoryAllocateAlignedDbg(pFileName, nLine, size, align, IsPageable, tag, aligned_addr); +#else + buf = MemoryAllocateAligned(size, align, IsPageable, tag, aligned_addr); +#endif + if (buf) + MemoryClear(*aligned_addr, size); + return buf; +} + +#if defined(MALLOC_TRACK_ON) && defined(VXWORKS) +void +MemoryAllocateVxWorksTrack( + IN void *result, + IN uint32 Bytes, + IN char *reason, + IN void *caller); + +int +MemoryTrackerTrackDeallocate( + IN void *pMemory); +#endif + +#ifdef MEM_TRACK_ON +#define MemoryAllocate2Aligned( a, b, c, d, e ) \ + MemoryAllocate2AlignedDbg( __FILE__, __LINE__, a, b, c, d, e ) +static _inline void* MemoryAllocate2AlignedDbg( + IN const char *pFileName, + IN int32 nLine, +#else +static _inline void* MemoryAllocate2Aligned( +#endif + IN uint32 size, + IN uint32 align, + IN uint32 flags, + IN uint32 tag, + OUT void **aligned_addr + ) +{ + void *buf; + +#ifdef MEM_TRACK_ON + buf = MemoryAllocate2Dbg(pFileName, nLine, size+align-1, flags, tag); +#else + buf = MemoryAllocate2(size+align-1, flags, tag); +#endif + *aligned_addr = (void*)ROUNDUPP2((uintn)buf,align); + return buf; +} + +#ifdef MEM_TRACK_ON +#define MemoryAllocate2AlignedAndClear( a, b, c, d, e ) \ + MemoryAllocate2AlignedAndClearDbg( __FILE__, __LINE__, a, b, c, d, e ) +static _inline void* MemoryAllocate2AlignedAndClearDbg( + IN const char *pFileName, + IN int32 nLine, +#else +static _inline void* MemoryAllocate2AlignedAndClear( +#endif + IN uint32 size, + IN uint32 align, + IN uint32 flags, + IN uint32 tag, + OUT void **aligned_addr + ) +{ + void *buf; + +#ifdef MEM_TRACK_ON + buf = MemoryAllocate2AlignedDbg(pFileName, nLine, size, align, flags, tag, aligned_addr); +#else + buf = MemoryAllocate2Aligned(size, align, flags, tag, aligned_addr); +#endif + if (buf) + MemoryClear(*aligned_addr, size); + return buf; +} + +/* internal private functions not for general use, these are supplied + * by the OS specific imemory_osd module + */ +#if !defined(VXWORKS) +void* +MemoryAllocatePriv( IN uint32 Bytes, IN uint32 flags, IN uint32 Tag ); + + +void +MemoryDeallocatePriv( IN void *pMemory ); + +#else // VXWORKS routines + +void* +MemoryAllocatePriv( IN uint32 Bytes, void *caller ); + +void +MemoryDeallocatePriv( IN void *pMemory, void *caller ); +#endif + +#ifdef LINUX +/* + * Memory Locking Strategies implemented. These are obtained via + * Kernel Memory module, passed via Vka to Uvca and into user Memory module + * At this time only Linux has a few choices available. The strategy to use + * is selected based on kernel version (hence the need for the Kernel Memory + * module to report). This is done such that a single object for the user + * space libraries can work against multiple kernel versions. + * MADVISE - user space does an madvise(SEQ) then calls VKA to MemoryLock + * unadvise is not needed. + * MLOCK - user space does an mlock and madvise(DONTFORK) then calls VKA to + * MemoryLock. After MemoryUnlock, user space does munlock and + * madvise(DOFORK). User space must track and handle overlapping + * locks because mlock and madvise are not "stackable" + */ +#define MEMORY_LOCK_STRAT_MADVISE 0 +#define MEMORY_LOCK_STRAT_MLOCK 1 +#endif + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* _IBA_PUBLIC_IMEMORY_H_ */ diff --git a/IbAccess/Common/Public/imemtrack.h b/IbAccess/Common/Public/imemtrack.h new file mode 100644 index 0000000..a107e1c --- /dev/null +++ b/IbAccess/Common/Public/imemtrack.h @@ -0,0 +1,91 @@ +/* BEGIN_ICS_COPYRIGHT3 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT3 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +#ifndef _IBA_PUBLIC_IMEMTRACK_H_ +#define _IBA_PUBLIC_IMEMTRACK_H_ + +#include "iba/public/ilist.h" +#include "iba/public/ispinlock.h" +#include "iba/public/imemory.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define TRK_TAG MAKE_MEM_TAG( m, t, r, k ) + + +typedef struct MemoryTrackerFileName { + struct MemoryTrackerFileName *next; + int referenceCount; + int filenameLen; + char filename[1]; +} MemoryTrackerFileName_t; + +#define MEMORY_TRACKER_BUCKETS 53 + +/* Structure to track memory allocations. */ +typedef struct _MEM_TRACKER +{ + /* List for tracking memory allocations. */ + QUICK_LIST AllocList; + /* Lock for synchronization. */ + SPIN_LOCK Lock; + /* List to manage free headers. */ + QUICK_LIST FreeHrdList; + +} MEM_TRACKER; + +/* Footer for all memory allocations. */ +typedef struct _MEM_ALLOC_FTR +{ + uint32 OutOfBound; +} MEM_ALLOC_FTR; + +/* Header for all memory allocations. */ +typedef struct _MEM_ALLOC_HDR +{ + LIST_ITEM ListItem; + MemoryTrackerFileName_t *trk; + uint32 LineNum; + uint32 Bytes; + int32 reported; + uint32 tick; + volatile boolean displaying; + volatile boolean deallocate; + MEM_ALLOC_FTR *pFtr; +} MEM_ALLOC_HDR; + +#ifdef __cplusplus +}; +#endif + +#endif /* _IBA_PUBLIC_IMEMTRACK_H_ */ diff --git a/IbAccess/Common/Public/imutex.h b/IbAccess/Common/Public/imutex.h new file mode 100644 index 0000000..d0a05b2 --- /dev/null +++ b/IbAccess/Common/Public/imutex.h @@ -0,0 +1,172 @@ +/* BEGIN_ICS_COPYRIGHT1 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT1 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +#ifndef _IBA_PUBLIC_IMUTEX_H_ +#define _IBA_PUBLIC_IMUTEX_H_ + +#include "iba/public/imutex_osd.h" + + +#ifdef __cplusplus +extern "C" +{ +#endif + +/**************************************************************************** + * MutexInitState + * + * Description: + * Initializes the state of a mutex. + * + * Inputs: + * pMutex - Pointer to a mutex object. + * + * Outputs: + * None + * + * Returns: + * None + * + ****************************************************************************/ +void +MutexInitState( + IN MUTEX* const pMutex ); + + +/**************************************************************************** + * MutexInit + * + * Description: + * Initializes the mutex. This function performs all initialization. + * + * Inputs: + * pMutex - Pointer to a mutex object + * + * Outputs: + * None + * + * Returns: + * FSUCCESS + * FERROR - Initialization failed. + * + ****************************************************************************/ +FSTATUS +MutexInit( + IN MUTEX* const pMutex); + + +/**************************************************************************** + * MutexDestroy + * + * Description: + * Destroys the mutex. + * + * Inputs: + * pMutex - Pointer to a mutex object + * + * Outputs: + * None + * + * Returns: + * None + * + ****************************************************************************/ +void +MutexDestroy( + IN MUTEX* const pMutex ); + + +/**************************************************************************** + * MutexAcquire + * + * Description: + * Acquires a mutex. This call blocks if the mutex cannot be + * acquired immediately. + * + * Inputs: + * pMutex - Pointer to a mutex object + * + * Outputs: + * None + * + * Returns: + * None + * + ****************************************************************************/ +void +MutexAcquire( + IN MUTEX* const pMutex); + + +/**************************************************************************** + * MutexRelease + * + * Description: + * Releases a mutex. This will free one blocking waiter, if any. + * + * Inputs: + * pMutex - Pointer to a mutex object + * + * Outputs: + * None + * + * Returns: + * None + * + ****************************************************************************/ +void +MutexRelease( + IN MUTEX* const pMutex ); + +#ifdef __cplusplus +} /* extern "C" */ + +/* RAI object to help create and release mutexes */ +class AutoMutex +{ +public: + AutoMutex( MUTEX *pMutex) + { + m_mutex = pMutex; + MutexAcquire(m_mutex); + } + + ~AutoMutex() + { + MutexRelease(m_mutex); + } + +private: + MUTEX *m_mutex; +}; +#endif /* __cplusplus */ + +#endif /* _IBA_PUBLIC_IMUTEX_H_ */ diff --git a/IbAccess/Common/Public/iobjmgr.c b/IbAccess/Common/Public/iobjmgr.c new file mode 100644 index 0000000..43cdbda --- /dev/null +++ b/IbAccess/Common/Public/iobjmgr.c @@ -0,0 +1,118 @@ +/* BEGIN_ICS_COPYRIGHT6 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT6 ****************************************/ + +#include "iobjmgr.h" +#include "imemory.h" + + +#define OBJ_MGR_TAG MAKE_MEM_TAG( i, o, b, j ) + +void +ObjMgrInitState( + IN OBJECT_MGR* const pObjMgr ) +{ + QListInitState( &pObjMgr->m_ObjList ); + pObjMgr->m_Initialized = FALSE; +} + + +boolean +ObjMgrInit( + IN OBJECT_MGR* const pObjMgr, + IN const boolean ObjectsPageable ) +{ + ASSERT( pObjMgr ); + + pObjMgr->m_Initialized = FALSE; + pObjMgr->ObjectsPageable = ObjectsPageable; + pObjMgr->m_Initialized = + QListInit( &pObjMgr->m_ObjList ); + return pObjMgr->m_Initialized; +} + + +void +ObjMgrDestroy( + IN OBJECT_MGR* const pObjMgr ) +{ + LIST_ITEM *pListItem; + ASSERT( pObjMgr ); + + if( !pObjMgr->m_Initialized ) + return; + + // Deallocate all objects. + while( NULL != (pListItem = QListRemoveHead( &pObjMgr->m_ObjList )) ) + MemoryDeallocate( pListItem ); + + QListDestroy( &pObjMgr->m_ObjList ); + pObjMgr->m_Initialized = FALSE; +} + + +// Allocate an object and add it to the object manager's list. +void* +ObjMgrAllocate( + IN OBJECT_MGR* const pObjMgr, + IN const uint32 Bytes ) +{ + LIST_ITEM *pListItem; + ASSERT( pObjMgr && Bytes && pObjMgr->m_Initialized ); + + // Allocate the object, with a list item at the head. + pListItem = (LIST_ITEM*)MemoryAllocateAndClear( Bytes + sizeof( LIST_ITEM ), + pObjMgr->ObjectsPageable, OBJ_MGR_TAG ); + + if( !pListItem ) + return NULL; + + // Insert the item into the object manager's list. + pListItem->pObject = (char*)pListItem + sizeof( LIST_ITEM ); + QListInsertHead( &pObjMgr->m_ObjList, pListItem ); + return pListItem->pObject; +} + + +// Destroy an object maintained by the object manager. +void +ObjMgrDeallocate( + IN OBJECT_MGR* const pObjMgr, + IN void* const pObject ) +{ + LIST_ITEM *pListItem; + ASSERT( pObjMgr && pObject && pObjMgr->m_Initialized ); + + // Remove the object from the list. + pListItem = (LIST_ITEM*)((char*)pObject - sizeof( LIST_ITEM )); + ASSERT( pListItem->pObject == pObject ); + QListRemoveItem( &pObjMgr->m_ObjList, pListItem ); + + // Deallocate the object. + MemoryDeallocate( pListItem ); +} diff --git a/IbAccess/Common/Public/iobjmgr.h b/IbAccess/Common/Public/iobjmgr.h new file mode 100644 index 0000000..ffff0e4 --- /dev/null +++ b/IbAccess/Common/Public/iobjmgr.h @@ -0,0 +1,87 @@ +/* BEGIN_ICS_COPYRIGHT3 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT3 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +#ifndef _IBA_PUBLIC_IOBJMGR_H_ +#define _IBA_PUBLIC_IOBJMGR_H_ + +#include "iba/public/ilist.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * An object manager allocates objects, then deallocates them when destroyed. + */ +typedef struct _OBJECT_MGR +{ + /* Private data structure for the object manager. */ + /* Users should not access these variables directly. */ + QUICK_LIST m_ObjList; /* DO NOT USE!! */ + boolean ObjectsPageable; /* DO NOT USE!! */ + boolean m_Initialized; /* DO NOT USE!! */ + +} OBJECT_MGR; + + +/* Create an object manager. */ +void +ObjMgrInitState( + IN OBJECT_MGR* const pObjMgr ); + +boolean +ObjMgrInit( + IN OBJECT_MGR* const pObjMgr, + IN const boolean ObjectsPageable ); + +/* Destroy an object manager and all allocated resources. */ +void +ObjMgrDestroy( + IN OBJECT_MGR* const pObjMgr ); + +/* Allocate an object and add it to the object manager's list. */ +void* +ObjMgrAllocate( + IN OBJECT_MGR* const pObjMgr, + IN const uint32 Bytes ); + +/* Destroy a specific object maintained by the object manager. */ +void +ObjMgrDeallocate( + IN OBJECT_MGR* const pObjMgr, + IN void* const pObject ); + + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* _IBA_PUBLIC_IOBJMGR_H_ */ diff --git a/IbAccess/Common/Public/ipci.c b/IbAccess/Common/Public/ipci.c new file mode 100644 index 0000000..919b37b --- /dev/null +++ b/IbAccess/Common/Public/ipci.c @@ -0,0 +1,54 @@ +/* BEGIN_ICS_COPYRIGHT6 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT6 ****************************************/ + +#include "ipci.h" + +uint64 PciGetMemoryPciPhysAddr(IN PCI_DEVICE *pDev, IN uint8 barNumber) +{ + uint32 addr_l; + uint32 addr_h = 0; + + if (! PciReadConfig(pDev, + offsetof(IBA_PCI_COMMON_CONFIG,u.type0.BaseAddresses[barNumber]), + 4, &addr_l)) + { + return 0; + } + if ((addr_l & IBA_PCI_BAR_CNTL_TYPE_MASK) == IBA_PCI_BAR_CNTL_TYPE_64BIT) + { + // 64 bit BAR, get high bits + if (! PciReadConfig(pDev, + offsetof(IBA_PCI_COMMON_CONFIG,u.type0.BaseAddresses[barNumber+1]), + 4, &addr_h)) + { + return 0; + } + } + return (addr_l & ~IBA_PCI_BAR_CNTL_MASK) | ((uint64)addr_h << 32); +} diff --git a/IbAccess/Common/Public/ipci.h b/IbAccess/Common/Public/ipci.h new file mode 100644 index 0000000..b0fd660 --- /dev/null +++ b/IbAccess/Common/Public/ipci.h @@ -0,0 +1,568 @@ +/* BEGIN_ICS_COPYRIGHT3 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT3 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +#ifndef _IBA_PUBLIC_IPCI_H_ +#define _IBA_PUBLIC_IPCI_H_ + +#include "iba/public/datatypes.h" + +#if defined(VXWORKS) + +#ifdef __cplusplus +extern "C" { +#endif + +/* Enable and disables PciDmaMap debug */ +#ifndef PCIDMAMAP_DBG /* allow to be set from CFLAGS */ +#define PCIDMAMAP_DBG 0 /* 0=no, 1=validate, 2=validate+log */ +#endif + +struct _PCI_DEVICE; +struct _PCI_DMA_FUNCS; + + /* return TRUE if interrupt has been handled */ +typedef boolean (*INTR_HANDLER)(IN struct _PCI_DEVICE *pDev, IN void *Context); + +#define IBA_PCI_TYPE0_ADDRESSES 6 +#define IBA_PCI_BRIDGE_ADDRESSES 2 + +/* control fields in BaseAddress Registers */ +#define IBA_PCI_BAR_CNTL_MASK 0xF +#define IBA_PCI_BAR_CNTL_TYPE_MASK 0x6 +#define IBA_PCI_BAR_CNTL_IO_SPACE 0x1 +#define IBA_PCI_BAR_CNTL_TYPE_32BIT 0x0 /* PCI */ +#define IBA_PCI_BAR_CNTL_TYPE_20BIT 0x2 /* obsolete */ +#define IBA_PCI_BAR_CNTL_TYPE_64BIT 0x4 /* PCI-X requires */ +#define IBA_PCI_BAR_CNTL_PREFETCHABLE 0x8 + +typedef struct _IBA_PCI_COMMON_CONFIG { + uint16 VendorID; + uint16 DeviceID; + uint16 Command; + uint16 Status; + uint8 RevisionID; + uint8 ProgIf; + uint8 SubClass; + uint8 BaseClass; + uint8 CacheLineSize; + uint8 LatencyTimer; + uint8 HeaderType; + uint8 BIST; + union { + struct _pci_header_type0 { + uint32 BaseAddresses[IBA_PCI_TYPE0_ADDRESSES]; + uint32 CIS; + uint16 SubVendorId; + uint16 SubSystemId; + uint32 RomBaseAddress; + uint8 CapabilitiesPtr; + uint8 Reserved1[3]; + uint32 Reserved2; + uint8 InterruptLine; + uint8 InterruptPin; + uint8 MinimumGrant; + uint8 MaximumLatency; + } type0; + struct _pci_header_bridge { + uint32 BaseAddresses[IBA_PCI_BRIDGE_ADDRESSES]; + uint8 PrimaryBusNumber; + uint8 SecondaryBusNumber; + uint8 SubordinateBusNumber; + uint8 SecondaryLatencyTimer; + uint8 IOBase; + uint8 IOLimit; + uint16 SecondaryStatus; + uint16 MemoryBase; + uint16 MemoryLimit; + uint16 PrefetchableMemoryBase_l; + uint16 PrefetchableMemoryLimit_l; + uint32 PrefetchableMemoryBase_h; + uint32 PrefetchableMemoryLimit_h; + uint16 IOBase_h; + uint16 IOLimit_h; + uint8 CapabilitiesPtr; + uint8 Reserved1[3]; + uint32 RomBaseAddress; + uint8 InterruptLine; + uint8 InterruptPin; + uint16 BridgeControl; + } bridge; + } u; + uint8 DeviceSpecific[192]; /* 48 uint32's */ +} IBA_PCI_COMMON_CONFIG; + +#define IBA_PCI_COMMON_HDR_LENGTH \ + (offsetof(IBA_PCI_COMMON_CONFIG, DeviceSpecific)) + +#ifdef __cplusplus +} +#endif + +#endif /* defined(VXWORKS) */ + +#ifdef VXWORKS +#include "iba/public/ipci_osd.h" +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/* Helper macros for reading and writing PCI memory + * Note these macros are for convenience, the memory may also be directly + * accessed + */ + +#define SUPPORT_ATOMIC_64BITS + +/* use mmx for 64bit write for ia32 user space */ +#if defined(SUPPORT_ATOMIC_64BITS_MMX) +#define DEV_WRITE64(Address, Value) \ + mmx_write_64bits(Value,Address) +#elif defined(SUPPORT_ATOMIC_64BITS_PPC) +#define DEV_WRITE64(Address, Value) \ + ppc_write_64bits(Value,Address) +#else +#define DEV_WRITE64(Address, Value) \ + *(volatile uint64 *)(Address) = (Value) +#endif + +#define DEV_WRITE32(Address, Value) \ + *(volatile uint32 *)(Address) = (Value) +#define DEV_WRITE16(Address, Value) \ + *(volatile uint16 *)(Address) = (Value) +#define DEV_WRITE8(Address, Value) \ + *(volatile uint8 *)(Address) = (Value) + +/* read 64bit using mmx for ia32 user space*/ +#if defined(SUPPORT_ATOMIC_64BITS_MMX) +#define DEV_READ64(Address, pValue) \ + *((uint64 *)pValue) = mmx_read_64bits((volatile uint64 *)Address) +#elif defined(SUPPORT_ATOMIC_64BITS_PPC) +#define DEV_READ64(Address, pValue) \ + *((uint64 *)pValue) = ppc_read_64bits((volatile uint64 *)Address) +#else +#define DEV_READ64(Address, pValue) \ + *((uint64 *)pValue) = *(volatile uint64 *)(Address) +#endif + +#define DEV_READ32(Address, pValue) \ + *((uint32 *)pValue) = *(volatile uint32 *)(Address) +#define DEV_READ16(Address, pValue) \ + *((uint16 *)pValue) = *(volatile uint16 *)(Address) +#define DEV_READ8(Address, pValue) \ + *((uint8 *)pValue) = *(volatile uint8 *)(Address) + +#define DEV_WRITE64_TO_BE(Address, Value) \ + *(volatile uint64 *)(Address) = hton64(Value) +#define DEV_WRITE32_TO_BE(Address, Value) \ + *(volatile uint32 *)(Address) = hton32(Value) +#define DEV_WRITE16_TO_BE(Address, Value) \ + *(volatile uint16 *)(Address) = hton16(Value) + +#define DEV_READ64_FROM_BE(Address, pValue) \ + do { \ + *((uint64 *)pValue) = *(volatile uint64 *)(Address) ;\ + *pValue = ntoh64(*pValue); \ + } while (0) +#define DEV_READ32_FROM_BE(Address, pValue) \ + do { \ + *((uint32 *)pValue) = *(volatile uint32 *)(Address) ;\ + *pValue = ntoh32(*pValue); \ + } while (0) +#define DEV_READ16_FROM_BE(Address, pValue) \ + do { \ + *((uint16 *)pValue) = *(volatile uint16 *)(Address) ;\ + *pValue = ntoh16(*pValue); \ + } while (0) + + +#if defined(VXWORKS) +/* These functions implement create/destroy of PCI_DEVICE */ +extern void PciInitState(PCI_DEVICE *pDev); + +/*PciInit is supplied for Operating systems which provide a plug and play + * callback based PCI enumeration, in which case the OS specific arguments + * will be similar to the plag and play callback arguments for the OS + *extern FSTATUS PciInit( PCI_DEVICE *pDev, + * OS specific arguments to describe device + * ) + */ + +/*PciFindDevice is supplied for Operating systems which do a driver initiated + *PCI enumeration (such as VxWorks) + * pDev - where to save information about device found + * vendorId - PCI vendor ID to search for + * deviceId - PCI device ID to search for + * pLastDev - previous device returned during this enumeration loop + * (pass NULL for 1st interation of loop) + * + * returns: + * FSUCCESS - a device was found, *pDev is initialized to refer to the device + * others - no device found (or no more devices), *pDev undefined + * FNOT_FOUND - no more devices of given vendor/device + * FINSUFFICIENT_MEMORY - unable to allocate internal memory + * others - error reading/accessing device + */ +extern FSTATUS PciFindDevice(IN uint16 vendorId, IN uint16 deviceId, + IN PCI_DEVICE *pLastDev, OUT PCI_DEVICE *pDev); + +/*PciGetBus locates the parent Bus of a given PCI Device + * pDev - Device whose parent we want to know + * pBusDev - where to save information about parent bus + * + * returns: + * FSUCCESS - found parent + * FNOT_FOUND - no parent + */ +extern FSTATUS PciGetBus(IN PCI_DEVICE *pDev, OUT PCI_DEVICE *pBusDev); + +extern void PciDestroy(IN PCI_DEVICE *pDev); +/*static _inline void PciSetContext(IN PCI_DEVICE *pDev, IN void *context); */ +/*static _inline void *PciGetContext(IN PCI_DEVICE *pDev); */ + +/* Get Basic PCI Device Information (location in system) */ +static _inline uint32 PciGetBusNumber(IN PCI_DEVICE *pDev); +static _inline uint32 PciGetDeviceNumber(IN PCI_DEVICE *pDev); +static _inline uint32 PciGetFuncNumber(IN PCI_DEVICE *pDev); + +/* Get Basic PCI Device Information (comes from PCI Config registers) */ +static _inline uint16 PciGetVendorId(IN PCI_DEVICE *pDev); +static _inline uint16 PciGetDeviceId(IN PCI_DEVICE *pDev); +static _inline uint8 PciGetRevisionId(IN PCI_DEVICE *pDev); +static _inline uint16 PciGetSubsystemVendorId(IN PCI_DEVICE *pDev); +static _inline uint16 PciGetSubsystemId(IN PCI_DEVICE *pDev); +static _inline uint8 PciGetInterruptLine(IN PCI_DEVICE *pDev); +static _inline uint8 PciGetInterruptPin(IN PCI_DEVICE *pDev); + +/* PCI Device Memory and BARs + * depending on device, there could be 6 32 bit BARs or 3 64 bit BARs + * however in either case we still use values of 0-5 for barNumber below + * Beware on VxWorks, PciGetMemoryLength always returns 0 + */ +extern uint64 PciGetMemoryLength(IN PCI_DEVICE *pDev, IN uint8 barNumber); +extern uint64 PciGetMemoryPciPhysAddr(IN PCI_DEVICE *pDev, IN uint8 barNumber); +extern uint64 PciGetMemoryCpuPhysAddr(IN PCI_DEVICE *pDev, IN uint8 barNumber); + +/* Mapping PCI memory to CPU Kernel Virtual + * These functions work with an opaque handle to a memory map object + */ +extern FSTATUS PciMapUncachedMemory(IN PCI_DEVICE *pDev, + IN uint8 barNumber, + OUT PCI_MAP_HANDLE *pMap, + OUT void** virt OPTIONAL); +extern FSTATUS PciMapUncachedMemoryPartial(IN PCI_DEVICE *pDev, + IN uint8 barNumber, + IN uint64 offset, + IN uint64 length, + OUT PCI_MAP_HANDLE *pMap, + OUT void** virt OPTIONAL); +extern void* PciMapGetVirtual(IN PCI_MAP_HANDLE pMap); +extern void PciUnmapMemory(IN PCI_MAP_HANDLE pMap); + +/* enable bus master operation by device */ +extern FSTATUS PciSetBusMaster(IN PCI_DEVICE *pDev, int bus_width); +/* enable memory mapped access to device */ +extern FSTATUS PciSetMemoryEnable(IN PCI_DEVICE *pDev); + +/* PCI MSI (Message Signalled Interrupts) support + * At present only 1 MSI interrupt is supported per device + * The use of MSI by the driver is optional + * In the future MSI-X may be implemented and allow >1 MSI interrupt per device + */ +/* Enable use of MSI, must call before PciSetIntrHandler */ +extern FSTATUS PciEnableMsi(IN PCI_DEVICE *pDev); +/* Disable use of MSI, must call after PciClearIntrHandler + * Noop if not enabled + */ +extern void PciDisableMsi(IN PCI_DEVICE *pDev); + +/* PCI Device Interrupts */ +/* Set Interrupt handler and enable interrupts */ +extern FSTATUS PciSetIntrHandler(IN PCI_DEVICE *pDev, IN const char* Name, + IN INTR_HANDLER Handler, IN void* Context); +/* Clear Interrupt Handler and disable interrupts */ +extern void PciClearIntrHandler(IN PCI_DEVICE *pDev); + +/* + * The following functions implement read/write to PCI config space + * to perform device specific configuration. + * + * PCI_DEVICE - is an opaque structure that makes sense only for that OS + * or platform that implements that abstraction. + * + * Offset - the offset into the space where the operation should be performed. + * + * Width - The width of the IO to perform. It could be one of 1,2,4 bytes + * in size. The memory provided to these function should be aligned + * to the byte width to which the operation is being performed. + * + * pVal - Pointer to the location where the data should be read into, or + * the value that should be written to the pci device. + */ +extern boolean +PciReadConfig( + IN PCI_DEVICE *pDev, + IN uint32 Offset, + IN uint32 Width, + OUT void *pVal + ); +extern boolean +PciWriteConfig( + IN PCI_DEVICE *pDev, + IN uint32 Offset, + IN uint32 Width, + IN void *pVal + ); + +/* + * The following function finds a device based on the Bus_Number/Slot_Number + * pair and returns a pointer to the PCI_DEVICE structure. This structure + * will be used by the ReadConfig and WriteConfig functions listed above. + * + * PCI_DEVICE - is an opaque structure that makes sense only for that OS or + * platform that implements the abstraction. + * + * BusNumber: number of PCI bus on which desired PCI device resides + * Slot: PCI slot in which the desired PCI device residesdevice resides + * + * Return Value: + * FSUCCESS - If a device at BusNumber and SlotNumber if found. + * FNOT_FOUND - If a device cannot be found. + */ + +extern FSTATUS +PciGetDevice( + IN OUT PCI_DEVICE *pDev, + IN uint16 BusNumber, + IN uint8 SlotNumber + ); + +#if defined(HAVEIOMMU) +/* + * The following functions create, manage and release pools of memory + * that are guaranteed to be accessible to PCI devices. + */ +extern void* PciPoolCreate( + IN const char *name, + IN PCI_DEVICE *pDev, + IN size_t size, + IN size_t align); + +extern void PciPoolDestroy(IN void* pool); + +/* + * Returns the virtual address of the dma-able memory or NULL. + * The dma address of the dma-able memory is returned in dmaaddr. + */ +extern void* PciPoolAlloc( + IN void* pool, + OUT uint64 *dmaaddr); + +/* Free the dma-able memory. NOTE THAT YOU PASS BOTH THE VIRTUAL + * AND PHYSICAL (DMA) ADDRESSES OF THE MEMORY. + */ +extern void PciPoolFree( + IN void* pool, + IN void* vaddr, + IN uint64 dmaddr); +#endif + +// defined in OS specific header +//#define PCI_DMA_BIDIR DMA_BIDIRECTIONAL +//#define PCI_DMA_TODEV DMA_TODEVICE +//#define PCI_DMA_FROMDEV DMA_FROMDEVICE +//... + +/* + * The following functions manage mapping memory for access by PCI devices. + * For each function, a function type is declared which can be used by + * PciSetDmaFuncs to specify device specific overrides which will be called + * by these functions. + */ + +/* map a kernel virtual address, returns Bus Physical address to be + * used by device for IO + * Virtual memory specified must be kernel virtual and physically contiguous + */ +typedef FSTATUS (PCI_DMA_MAP_VIRT_FUNC)( + IN struct _PCI_DEVICE *pDev, + IN void *addr, + IN uint64 size, + IN int dir, + OUT uint64 *dma_address, + OUT uint64 *map_handle /* opaque handle for use in Unmap below */ + ); +extern PCI_DMA_MAP_VIRT_FUNC PciDmaMapVirt; + +/* undoes a previous PciDmaMapVirt, must be called with map_handle = handle + * previously returned by PciDmaMapVirt + */ +typedef void (PCI_DMA_UNMAP_VIRT_FUNC)( + IN struct _PCI_DEVICE *pDev, + IN uint64 size, + IN int dir, + IN uint64 map_handle + ); +extern PCI_DMA_UNMAP_VIRT_FUNC PciDmaUnmapVirt; + +/* map a set of physically contiguous pages. + * physadd need not be page aligned, however some OS's may require this not + * span multiple pages + */ +typedef FSTATUS (PCI_DMA_MAP_PHYS_FUNC)( + IN struct _PCI_DEVICE *pDev, + IN uint64 physaddr, + IN uint64 size, + IN int dir, + OUT uint64 *dma_address, + OUT uint64 *map_handle + ); +extern PCI_DMA_MAP_PHYS_FUNC PciDmaMapPhys; + +/* undoes a previous PciDmaMapPhys, must be called with map_handle = handle + * previously returned by PciDmaMapPhys + */ +typedef void (PCI_DMA_UNMAP_PHYS_FUNC)( + IN struct _PCI_DEVICE *pDev, + IN uint64 size, + IN int dir, + IN uint64 map_handle + ); +extern PCI_DMA_UNMAP_PHYS_FUNC PciDmaUnmapPhys; + +/* map a scatter gather list of segments + * scatter gather list format is OS specific as is typically supplied to + * typical drivers on the given OS. On some OSs an offset is also supplied by + * the OS for typical drivers. + * an OS specific ITERATOR is returned for use in walking the resulting + * list of DMA addresses/lengths. + * Note that on some OSs, the number of entries in the resulting iterator + * may be different than sg_len + */ +typedef FSTATUS (PCI_DMA_MAP_SG_FUNC)( + IN struct _PCI_DEVICE *pDev, + IN PCI_DMA_SG_LIST *sg_list, + IN uint32 sg_len, + IN uint32 offset, + IN int dir, + OUT PCI_DMA_SG_ITERATOR *iterator, + OUT uint64 *map_handle + ); +extern PCI_DMA_MAP_SG_FUNC PciDmaMapSg; + +/* return the next mapped SG entry's address and length and advance + * returns: + * FCOMPLETED - end of list, no address/length available + * FSUCCESS - address/length provided and advanced + */ +typedef FSTATUS (PCI_DMA_SG_NEXT_FUNC)( + IN struct _PCI_DEVICE *pDev, + IN PCI_DMA_SG_LIST *sg_list, + IN PCI_DMA_SG_ITERATOR *iterator, + OUT uint64 *dma_address, + OUT uint64 *dma_length + ); +extern PCI_DMA_SG_NEXT_FUNC PciDmaSgNext; + +/* return the number of unprocessed SG entries + * If called immediately after PciDmaMapSg, this is total mapped areas + * If called after one or more PciDmaSgNext calls, this is remaining areas + */ +extern uint32 PciDmaSgCountLeft( + IN PCI_DMA_SG_LIST *sg_list, + IN PCI_DMA_SG_ITERATOR *iterator + ); + +/* undoes a previous PciDmaMapSg, must be called with map_handle = handle + * previously returned by PciDmaMapSg + */ +typedef void (PCI_DMA_UNMAP_SG_FUNC)( + IN struct _PCI_DEVICE *pDev, + IN PCI_DMA_SG_LIST *sg_list, + IN uint32 sg_len, + IN uint32 offset, + IN int dir, + IN uint64 map_handle + ); +extern PCI_DMA_UNMAP_SG_FUNC PciDmaUnmapSg; + +/* usage model for scatter/gather DMA: + * To start IO: + * status = PciDmaMapSg(.....) + * check status, fail if not FSUCCESS + * while (PciDmaSgNext(...) != FCOMPLETED) + * setup transfer to dma_address,length (typically added to WQE) + * + * when IO completes: + * PciDmaUnmapSg(...) + */ + +/* device specific functions which can be called as part of Pci DMA functions + * above + */ +typedef struct _PCI_DMA_FUNCS { + PCI_DMA_MAP_VIRT_FUNC *pMapVirt; + PCI_DMA_UNMAP_VIRT_FUNC *pUnmapVirt; + PCI_DMA_MAP_PHYS_FUNC *pMapPhys; + PCI_DMA_UNMAP_PHYS_FUNC *pUnmapPhys; + PCI_DMA_MAP_SG_FUNC *pMapSg; + PCI_DMA_UNMAP_SG_FUNC *pUnmapSg; + PCI_DMA_SG_NEXT_FUNC *pSgNext; +} PCI_DMA_FUNCS; + +/* specify DMA function overrides which should be called by the Pci DMA + * functions above. The context supplied may be fetched via PciGetDmaContext + * it is distinct from the Interrupt context used in interrupt callbacks + */ +extern void PciSetDmaFuncs( + IN PCI_DEVICE *pDev, + IN PCI_DMA_FUNCS *funcs, + IN void *context); +/*static _inline void *PciGetDmaContext(IN PCI_DEVICE *pDev); */ + +/* This function indicates if the given Device and/or OS requires + * calls to PciDmaMap functions above. + * If this returns TRUE, PciDmaMap functions are required. + * If this returns FALSE the calls above are benign but not necessary. + * In which case PciDmaMap functions will simply return CPU physical addresses. + * When FALSE is returned its up to the caller, who may be able to optimize + * by avoiding the PciDmaMap functions. + */ +//static _inline boolean PciNeedDmaMap(IN PCI_DEVICE *pDev); + +#endif /* defined(VXWORKS) */ + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* _IBA_PUBLIC_IPCI_H_ */ diff --git a/IbAccess/Common/Public/iproc_fs.c b/IbAccess/Common/Public/iproc_fs.c new file mode 100644 index 0000000..f0383ab --- /dev/null +++ b/IbAccess/Common/Public/iproc_fs.c @@ -0,0 +1,182 @@ +/* BEGIN_ICS_COPYRIGHT4 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT4 ****************************************/ + +#include "imemory.h" +#include "idebug.h" +#include "iproc_fs.h" + +// General purpose function to support proc file reads +// +// config_data, config_alloc, total_size - static variables in proc function +// will be managed here to maintain context across multiple read calls to +// this file. +// func - function to allocate space to text contents and format it +// func_data - will be passed as argument to provide context of what to format +// buf, start, offset, maxlen, eof - standard proc read arguments + +IBA_PROC_RET +iba_proc_read_wrapper(char **config_data, char **config_alloc, int *total_size, + IBA_PROC_FORMAT_FUNC func, void* func_data, + char *buf, char **start, IBA_PROC_OFFSET offset, int maxlen, + int *eof) +{ + int cur_size; + + if (! *config_data) { + *total_size = 0; // in case format fails to allocate space + *config_data = *config_alloc = (*func)(func_data, total_size); + } + + /* + * How much data is available for read: OS spits reads into 512b blocks + * and asks each individualy via a separate call to you each time. + */ + cur_size = (*total_size <= maxlen ? *total_size : maxlen); + + /* + * Is this the last read.. do something to generate + * an EOF + */ + if (cur_size <= 0) { + *config_data = NULL; + if (*config_alloc != NULL) + MemoryDeallocate(*config_alloc); + *config_alloc = NULL; + *eof = 1; + return 0; + } + MemoryCopy((void *)buf, (void *)*config_data, cur_size); + + /* + * setup for next call + */ + *total_size -= cur_size; // Compute #bytes left to deliver. + *config_data += cur_size; + + if (*total_size <= 0) + *eof = 1; + else + *eof = 0; + + *start = (char *)(uintn)cur_size; + return cur_size; +} + +void +SimpleProcInitState(SIMPLE_PROC *pProc) +{ + MemoryClear(pProc, sizeof(*pProc)); +} + +// internal format function if callback occurs for +// /proc object which is uninitialize (eg. being destroyed) +static +char * SimpleProcFormatUninit(void *data, int* total_size) +{ + return NULL; +} + +static +IBA_PROC_RET SimpleProcRead(char *buf, char **start, IBA_PROC_OFFSET offset, int maxlen, int *eof, void *data) +{ + SIMPLE_PROC *pProc = (SIMPLE_PROC*)data; + + return iba_proc_read_wrapper(&pProc->config_data, &pProc->config_alloc, + &pProc->total_size, + pProc->Initialized ? pProc->FormatFunc + : SimpleProcFormatUninit, + pProc->Context, + buf, start, offset, maxlen, eof); +} + +static +IBA_PROC_RET SimpleProcWrite(IBA_PROC_FILE *file, const char *buffer, unsigned long length, void *data) +{ + SIMPLE_PROC *pProc = (SIMPLE_PROC*)data; + + if (pProc->Initialized); + (*pProc->ClearFunc)(pProc->Context); + return length; +} + +// create and initialize /proc file +// Inputs: +// pProc - object to initialize +// Name - relative filename in ProcDir +// ProcDir - parent directory +// Context - context to pass to FormatFunc and ClearFunc +// FormatFunc - function to allocate and format /proc read data +// ClearFunc - function to clear data in response to /proc write +// Outputs: +// None +// Returns: +// true - initialized and callbacks will begin on user access to /proc +// false - unable to create +// +// must be called in a preemptable context +// +boolean +SimpleProcInit(SIMPLE_PROC *pProc, const char* Name, IBA_PROC_NODE *ProcDir, + void *Context, IBA_PROC_FORMAT_FUNC FormatFunc, + OPTIONAL SIMPLE_PROC_CLEAR_FUNC ClearFunc) +{ + IBA_PROC_NODE *entry; + + ASSERT(! pProc->Initialized); + ASSERT(FormatFunc); + ASSERT(Name); + pProc->Context = Context; + strncpy(pProc->Name, Name, SIMPLE_PROC_NAME_LEN-1); + pProc->Name[SIMPLE_PROC_NAME_LEN-1] = '\0'; + pProc->ProcDir = ProcDir; + pProc->FormatFunc = FormatFunc; + pProc->ClearFunc = ClearFunc; + + entry = iba_create_proc_entry(pProc->Name, + IBA_PROC_MODE_IFREG | IBA_PROC_MODE_IRUGOWUG, + pProc->ProcDir); + if (! entry) + { + MsgOut("Cannot create proc entry: %s\n", pProc->Name); + return FALSE; + } + iba_set_proc_data(entry, pProc); + iba_set_proc_read_func(entry, SimpleProcRead); + iba_set_proc_write_func(entry, ClearFunc?SimpleProcWrite:NULL); + pProc->Initialized = TRUE; + return TRUE; +} + +void +SimpleProcDestroy(SIMPLE_PROC *pProc) +{ + if (pProc->Initialized) + iba_remove_proc_entry(pProc->Name, pProc->ProcDir); + MemoryClear(pProc, sizeof(*pProc)); +} diff --git a/IbAccess/Common/Public/iproc_fs.h b/IbAccess/Common/Public/iproc_fs.h new file mode 100644 index 0000000..80319ed --- /dev/null +++ b/IbAccess/Common/Public/iproc_fs.h @@ -0,0 +1,304 @@ +/* BEGIN_ICS_COPYRIGHT4 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT4 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +#ifndef _IPROC_FS_H_ +#define _IPROC_FS_H_ + +#include "iba/public/iproc_fs_osd.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +#define NULL_NODE NULL + +/* Below are descriptions of the functions which are provided by iproc_fs_osd.h + * On some platforms these may be defines, on others they may be actual + * functions. + */ + +/********************************************************** + * IBA_PROC_READ_FUNC - "/proc node" read handler + * + * A driver implements a function of this type to handle reads + * from its registered "/proc node". It should fill in the + * user data buffer with the data to be returned. + * + * The 'off' argument indicates the byte position within + * the buffer where the current segment begins. This will + * always be zero on Darwin, since the entire user buffer + * is read in a single pass. + * + * The 'eof' argument points to an End Of File flag that the + * driver should set to 1. + * + * This function should return the number of bytes written into + * the user data buffer, to be displayed as read data. + * + * Equivalent to Linux read_func_t: + * + * "The read function should write its information into the page. + * For proper use, the function should start writing at an offset of off in + * page and write at most count bytes, but because most read functions are + * quite simple and only return a small amount of information, these two + * parameters are usually ignored (it breaks pagers like more + * and less, but cat still works). + * If the off and count parameters are properly used, eof should be used to + * signal that the end of the file has been reached by writing 1 to the memory + * location eof points to. + * + * The read_func function must return the number of bytes written into the page. + * or a IBA_PROC_RET value to reflect an error code" + * typedef IBA_PROC_RET (IBA_PROC_READ_FUNC) ( + * char *buffer, // User data buffer + * char **start, // Not used + * IBA_PROC_OFFSET off, // Byte offset into buffer + * int count, // max bytes to write + * int *eof, // Returned EOF flag + * void *priv ///Kernel private data + * ); + ***********************************************************/ + +/********************************************************** + * IBA_PROC_WRITE_FUNC - "/proc node" write handler + * + * A driver implements a function of this type to handle + * writes to its registered "/proc node". It should copy the + * data in the user buffer for its own internal use. + * + * Equivalent to Linux write_func_t: + * + * "The write function should read count bytes at maximum from the buffer." + * + * This function returns the number of bytes written + * or a IBA_PROC_RET value to reflect an error code + * typedef IBA_PROC_RET (IBA_PROC_WRITE_FUNC) ( + * IBA_PROC_FILE * file, // File pointer + * const char *buffer, // User data buffer + * unsigned long count, // Max bytes to read + * void *priv // Kernel private data + * ); + ***********************************************************/ + +/********************************************************** + * iba_proc_mkdir() - Create a "/proc directory node". + * + * A driver calls this function to create a directory node + * within the emulated "/proc file system" in IbAccess. The + * directory node will be created with the specified file name, + * under the directory node specified by 'parent'. + * A NULL value for 'parent' implies the root node ("/proc"). + * + * IbAccess returns an opaque handle to that node. + * + * IBA_PROC_NODE * + * iba_proc_mkdir( + * const char *name, // File name + * IBA_PROC_NODE *parent // Parent directory + * ); + ***********************************************************/ + +/********************************************************** + * iba_create_proc_entry() - Create a "/proc file node". + * + * A driver calls this function to create a file node + * within the emulated "/proc file system" in IbAccess. The + * file node will be created with the specified file name, + * under the directory node specified by 'parent'. + * A NULL value for 'parent' implies the root node ("/proc"). + * + * IbAccess returns an opaque handle to that node, which can + * be used later to remove it. + * + * After the node has been created, IbAccess will accept + * PROC_READ and PROC_WRITE User Client commands directed to + * this node, calling the driver's registered read and write + * handlers, respectively. If a NULL handler was registered, + * then IbAccess will return an Access Error to the user + * instead. The 'priv' argument is a driver private data + * structure that IbAccess will associate with the node and + * return to the driver when calling its read or write + * handler. + * + * IBA_PROC_NODE * + * iba_create_proc_entry( + * const char *name, // File name + * IBA_PROC_MODE mode, // File mode (N/U on Darwin) + * IBA_PROC_NODE *parent // Parent directory + * ); + ***********************************************************/ + +/********************************************************** + * iba_get_proc_*(), iba_set_proc_*() + * + * These are accessor functions for the opaque IBA_PROC_NODE + * structure. + * + * void + * iba_set_proc_read_func( + * IBA_PROC_NODE *node, // File proc node + * IBA_PROC_READ_FUNC *rd_func // Read handler function + * ); + * + * void + * iba_set_proc_write_func( + * IBA_PROC_NODE *node, // File proc node + * IBA_PROC_WRITE_FUNC *wr_func // Write handler function + * ); + * + * // return >=0 for byte count on success, <0 is a PROC_IBA_RET_* value + * static _inline IBA_PROC_RET + * iba_proc_copy_user_data( + * char *dest, // kernel destination buffer + * const char* userBuffer, // user buffer from IBA_PROC_WRITE_FUNC + * unsigned bytes // number of bytes to copy + * ); + * + * void + * iba_set_proc_data( + * IBA_PROC_NODE *node, // File proc node + * void *data // Private data struct + * ); + * + * void * + * iba_get_proc_data( + * IBA_PROC_NODE *node // File proc node + * ); + * + * const char * + * iba_get_proc_name( + * IBA_PROC_NODE *node // File proc node + * ); + ***********************************************************/ + +/********************************************************** + * iba_remove_proc_entry() - Remove a "/proc node". + * + * A driver calls this function to remove a previously created + * "/proc node", of either file or directory type, specified + * by the node name and parent directory node. + * A NULL value for 'parent' implies the root node ("/proc"). + * + * void + * iba_remove_proc_entry( + * const char *name, // Node name + * IBA_PROC_NODE *parent // Parent directory + * ); + ***********************************************************/ + +/* support function type for iba_proc_read_wrapper + * called in a premptable context + * + * Inputs: + * data - context information + * Outputs: + * total_size - returns size of proc text returned (not including any \0) + * Returns: + * a pointer to text array of data to output for /proc read + * can be NULL if unable to allocate or no data available + * if NULL is returned, *total_size should be unchanged or 0 + * caller will MemoryDeallocate when done + */ +typedef char * (*IBA_PROC_FORMAT_FUNC)(void *data, int* total_size); + +/* General purpose function to support proc file reads + * for simple /proc files, this can be provided as the read_func + * + * config_data, config_alloc, total_size - static variables in proc function + * will be managed here to maintain context across multiple read calls to + * this file. + * func - function to allocate space to text contents and format it + * func_data - will be passed as argument to provide context of what to format + * buf, start, offset, maxlen, eof - standard proc read arguments + */ + +extern IBA_PROC_RET +iba_proc_read_wrapper(char **config_data, char **config_alloc, int *total_size, + IBA_PROC_FORMAT_FUNC func, void* func_data, + char *buf, char **start, IBA_PROC_OFFSET offset, int maxlen, + int *eof); + +/* for simpler /proc interfaces, this provides a simplified + * interface. Caller need only supply a format function and an optional + * clear function (to be called by write) + * The function provides all the necessary initialization and handler functions + * for the /proc interface itself + */ + +/* function type for optional clear function, used on write to /proc file */ +typedef void (*SIMPLE_PROC_CLEAR_FUNC)(void *context); + +#define SIMPLE_PROC_NAME_LEN 80 +typedef struct _SIMPLE_PROC { + boolean Initialized; + void *Context; /* callback's context */ + char Name[SIMPLE_PROC_NAME_LEN];/* relative file name */ + IBA_PROC_NODE *ProcDir; /* parent directory */ + IBA_PROC_FORMAT_FUNC FormatFunc; /* callback function */ + SIMPLE_PROC_CLEAR_FUNC ClearFunc; /* callback function */ + char *config_data; /* for use in read */ + char *config_alloc; /* for use in read */ + int total_size; /* for use in read */ +} SIMPLE_PROC; + +extern void +SimpleProcInitState(SIMPLE_PROC *pProc); + +/* create and initialize /proc file + * Inputs: + * pProc - object to initialize + * Name - relative filename in ProcDir + * ProcDir - parent directory + * Context - context to pass to FormatFunc and ClearFunc + * FormatFunc - function to allocate and format /proc read data + * ClearFunc - function to clear data in response to /proc write + * Outputs: + * None + * Returns: + * true - initialized and callbacks will begin on user access to /proc + * false - unable to create + * + * must be called in a preemptable context + */ +extern boolean +SimpleProcInit(SIMPLE_PROC *pProc, const char* Name, IBA_PROC_NODE *ProcDir, + void *Context, IBA_PROC_FORMAT_FUNC FormatFunc, + OPTIONAL SIMPLE_PROC_CLEAR_FUNC ClearFunc); + +extern void +SimpleProcDestroy(SIMPLE_PROC *pProc); + +#ifdef __cplusplus +} +#endif + +#endif /* _IPROC_FS_H_ */ diff --git a/IbAccess/Common/Public/iquickmap.c b/IbAccess/Common/Public/iquickmap.c new file mode 100644 index 0000000..80c81ec --- /dev/null +++ b/IbAccess/Common/Public/iquickmap.c @@ -0,0 +1,1994 @@ +/* BEGIN_ICS_COPYRIGHT6 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT6 ****************************************/ + +/* This file incorporates work covered by the following copyright and permission notice */ + +/* +* Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. +* Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved. +* Copyright (c) 1996-2003 Intel Corporation. All rights reserved. +* +* This software is available to you under a choice of one of two +* licenses. You may choose to be licensed under the terms of the GNU +* General Public License (GPL) Version 2, available from the file +* COPYING in the main directory of this source tree, or the +* OpenIB.org BSD license below: +* +* Redistribution and use in source and binary forms, with or +* without modification, are permitted provided that the following +* conditions are met: +* +* - Redistributions of source code must retain the above +* copyright notice, this list of conditions and the following +* disclaimer. +* +* - Redistributions in binary form must reproduce the above +* copyright notice, this list of conditions and the following +* disclaimer in the documentation and/or other materials +* provided with the distribution. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +* +*/ + +/* + * Abstract: + * Implementation of quick map, a binary tree where the caller always provides + * all necessary storage. + * + * Environment: + * All + * + * $Revision$ + */ + + +/***************************************************************************** +* +* Map +* +* Map is an associative array. By providing a key, the caller can retrieve +* an object from the map. All objects in the map have an associated key, +* as specified by the caller when the object was inserted into the map. +* In addition to random access, the caller can traverse the map much like +* a linked list, either forwards from the first object or backwards from +* the last object. The objects in the map are always traversed in +* order since the nodes are stored sorted. +* +* This implementation of Map uses a red black tree verified against +* Cormen-Leiserson-Rivest text, McGraw-Hill Edition, fourteenth +* printing, 1994. +* +*****************************************************************************/ + + +#include +#include + + +/****************************************************************************** +******************************************************************************* +************** ************ +************** IMPLEMENTATION OF QUICK MAP ************ +************** ************ +******************************************************************************* +******************************************************************************/ + +/* + * Get the root. + */ +static inline cl_map_item_t* +__cl_map_root( + IN const cl_qmap_t* const p_map ) +{ + ASSERT( p_map ); + return( p_map->root.p_left ); +} + + +/* + * Returns whether a given item is on the left of its parent. + */ +static boolean +__cl_map_is_left_child( + IN const cl_map_item_t* const p_item ) +{ + ASSERT( p_item ); + ASSERT( p_item->p_up ); + ASSERT( p_item->p_up != p_item ); + + return( p_item->p_up->p_left == p_item ); +} + + +/* + * Retrieve the pointer to the parent's pointer to an item. + */ +static cl_map_item_t** +__cl_map_get_parent_ptr_to_item( + IN cl_map_item_t* const p_item ) +{ + ASSERT( p_item ); + ASSERT( p_item->p_up ); + ASSERT( p_item->p_up != p_item ); + + if( __cl_map_is_left_child( p_item ) ) + return( &p_item->p_up->p_left ); + + ASSERT( p_item->p_up->p_right == p_item ); + return( &p_item->p_up->p_right ); +} + + +/* + * Rotate a node to the left. This rotation affects the least number of links + * between nodes and brings the level of C up by one while increasing the depth + * of A one. Note that the links to/from W, X, Y, and Z are not affected. + * + * R R + * | | + * A C + * / \ / \ + * W C A Z + * / \ / \ + * B Z W B + * / \ / \ + * X Y X Y + */ +static void +__cl_map_rot_left( + IN cl_qmap_t* const p_map, + IN cl_map_item_t* const p_item ) +{ + cl_map_item_t **pp_root; + + ASSERT( p_map ); + ASSERT( p_item ); + ASSERT( p_item->p_right != &p_map->nil_item ); + + pp_root = __cl_map_get_parent_ptr_to_item( p_item ); + + /* Point R to C instead of A. */ + *pp_root = p_item->p_right; + /* Set C's parent to R. */ + (*pp_root)->p_up = p_item->p_up; + + /* Set A's right to B */ + p_item->p_right = (*pp_root)->p_left; + /* + * Set B's parent to A. We trap for B being NIL since the + * caller may depend on NIL not changing. + */ + if( (*pp_root)->p_left != &p_map->nil_item ) + (*pp_root)->p_left->p_up = p_item; + + /* Set C's left to A. */ + (*pp_root)->p_left = p_item; + /* Set A's parent to C. */ + p_item->p_up = *pp_root; +} + + +/* + * Rotate a node to the right. This rotation affects the least number of links + * between nodes and brings the level of A up by one while increasing the depth + * of C one. Note that the links to/from W, X, Y, and Z are not affected. + * + * R R + * | | + * C A + * / \ / \ + * A Z W C + * / \ / \ + * W B B Z + * / \ / \ + * X Y X Y + */ +static void +__cl_map_rot_right( + IN cl_qmap_t* const p_map, + IN cl_map_item_t* const p_item ) +{ + cl_map_item_t **pp_root; + + ASSERT( p_map ); + ASSERT( p_item ); + ASSERT( p_item->p_left != &p_map->nil_item ); + + /* Point R to A instead of C. */ + pp_root = __cl_map_get_parent_ptr_to_item( p_item ); + (*pp_root) = p_item->p_left; + /* Set A's parent to R. */ + (*pp_root)->p_up = p_item->p_up; + + /* Set C's left to B */ + p_item->p_left = (*pp_root)->p_right; + /* + * Set B's parent to C. We trap for B being NIL since the + * caller may depend on NIL not changing. + */ + if( (*pp_root)->p_right != &p_map->nil_item ) + (*pp_root)->p_right->p_up = p_item; + + /* Set A's right to C. */ + (*pp_root)->p_right = p_item; + /* Set C's parent to A. */ + p_item->p_up = *pp_root; +} + + +void +cl_qmap_init( + IN cl_qmap_t* const p_map, + IN cl_pfn_qmap_compare_key_t key_compare) +{ + ASSERT( p_map ); + + MemoryClear( p_map, sizeof(cl_qmap_t) ); + + /* special setup for the root node */ + p_map->root.p_up = &p_map->root; + p_map->root.p_left = &p_map->nil_item; + p_map->root.p_right = &p_map->nil_item; + p_map->root.color = CL_MAP_BLACK; +#if QMAP_DEBUG + p_map->root.p_map = p_map; +#endif + + /* Setup the node used as terminator for all leaves. */ + p_map->nil_item.p_up = &p_map->nil_item; + p_map->nil_item.p_left = &p_map->nil_item; + p_map->nil_item.p_right = &p_map->nil_item; + p_map->nil_item.color = CL_MAP_BLACK; +#if QMAP_DEBUG + p_map->nil_item.p_map = p_map; +#endif + + p_map->state = CL_INITIALIZED; + p_map->key_compare = key_compare; + + cl_qmap_remove_all( p_map ); +} + + +cl_map_item_t* +cl_qmap_get( + IN const cl_qmap_t* const p_map, + IN const uint64 key ) +{ + cl_map_item_t *p_item; + + ASSERT( p_map ); + ASSERT( p_map->state == CL_INITIALIZED ); + + p_item = __cl_map_root( p_map ); + + if (p_map->key_compare == NULL) + { + while( p_item != &p_map->nil_item ) + { + if( key == p_item->key ) + break; /* just right */ + + if( key < p_item->key ) + p_item = p_item->p_left; /* too small */ + else + p_item = p_item->p_right; /* too big */ + } + } else { + while( p_item != &p_map->nil_item ) + { + int compare_res = (*p_map->key_compare)(p_item->key, key); + if( compare_res == 0 ) /* key == p_item->key */ + break; /* just right */ + + if( compare_res > 0 ) /* p_item->key > key */ + p_item = p_item->p_left; /* too small */ + else + p_item = p_item->p_right; /* too big */ + } + } + + return( p_item ); +} + +cl_map_item_t* +cl_qmap_get_next( + IN const cl_qmap_t* const p_map, + IN const uint64 key ) +{ + cl_map_item_t *p_item; + cl_map_item_t *p_item_found; + + ASSERT( p_map ); + ASSERT( p_map->state == CL_INITIALIZED ); + + p_item = __cl_map_root( p_map ); + p_item_found = (cl_map_item_t*)&p_map->nil_item; + + if (p_map->key_compare == NULL) + { + while( p_item != &p_map->nil_item ) + { + if( key < p_item->key ){ + p_item_found = p_item; + p_item = p_item->p_left; + }else{ + p_item = p_item->p_right; + } + } + } else { + while( p_item != &p_map->nil_item ) + { + int compare_res = (*p_map->key_compare)(p_item->key, key); + + if( compare_res < 0 ){ + p_item_found = p_item; + p_item = p_item->p_left; + }else{ + p_item = p_item->p_right; + } + } + } + + return( p_item_found ); +} + + +cl_map_item_t* +cl_qmap_get_compare( + IN const cl_qmap_t* const p_map, + IN const uint64 key, + IN cl_pfn_qmap_compare_key_t key_compare) +{ + cl_map_item_t *p_item; + + ASSERT( p_map ); + ASSERT( p_map->state == CL_INITIALIZED ); + ASSERT( key_compare != NULL); + + p_item = __cl_map_root( p_map ); + + while( p_item != &p_map->nil_item ) + { + int compare_res = (*key_compare)(p_item->key, key); + if( compare_res == 0 ) /* key == p_item->key */ + break; /* just right */ + + if( compare_res > 0 ) /* p_item->key > key */ + p_item = p_item->p_left; /* too small */ + else + p_item = p_item->p_right; /* too big */ + } + + return( p_item ); +} + +cl_map_item_t* +cl_qmap_get_item_compare( + IN const cl_qmap_t* const p_map, + IN const uint64 key, + IN cl_pfn_qmap_item_compare_t compare) +{ + cl_map_item_t *p_item; + + ASSERT( p_map ); + ASSERT( p_map->state == CL_INITIALIZED ); + ASSERT( compare != NULL); + + p_item = __cl_map_root( p_map ); + + while( p_item != &p_map->nil_item ) + { + int compare_res = (*compare)(p_item, key); + if( compare_res == 0 ) /* key == p_item->key */ + break; /* just right */ + + if( compare_res > 0 ) /* p_item->key > key */ + p_item = p_item->p_left; /* too small */ + else + p_item = p_item->p_right; /* too big */ + } + + return( p_item ); +} + +void +cl_qmap_apply_func( + IN const cl_qmap_t* const p_map, + IN cl_pfn_qmap_apply_t pfn_func, + IN const void* const context ) +{ + cl_map_item_t* p_map_item; + + /* Note that context can have any arbitrary value. */ + ASSERT( p_map ); + ASSERT( p_map->state == CL_INITIALIZED ); + ASSERT( pfn_func ); + + p_map_item = cl_qmap_head( p_map ); + while( p_map_item != cl_qmap_end( p_map ) ) + { + pfn_func( p_map_item, (void*)context ); + p_map_item = cl_qmap_next( p_map_item ); + } +} + + +/* + * Balance a tree starting at a given item back to the root. + */ +static void +__cl_map_ins_bal( + IN cl_qmap_t* const p_map, + IN cl_map_item_t* p_item ) +{ + cl_map_item_t* p_grand_uncle; + + ASSERT( p_map ); + ASSERT( p_item ); + ASSERT( p_item != &p_map->root ); + + while( p_item->p_up->color == CL_MAP_RED ) + { + if( __cl_map_is_left_child( p_item->p_up ) ) + { + p_grand_uncle = p_item->p_up->p_up->p_right; + ASSERT( p_grand_uncle ); + if( p_grand_uncle->color == CL_MAP_RED ) + { + p_grand_uncle->color = CL_MAP_BLACK; + p_item->p_up->color = CL_MAP_BLACK; + p_item->p_up->p_up->color = CL_MAP_RED; + p_item = p_item->p_up->p_up; + continue; + } + + if( !__cl_map_is_left_child( p_item ) ) + { + p_item = p_item->p_up; + __cl_map_rot_left( p_map, p_item ); + } + p_item->p_up->color = CL_MAP_BLACK; + p_item->p_up->p_up->color = CL_MAP_RED; + __cl_map_rot_right( p_map, p_item->p_up->p_up ); + } + else + { + p_grand_uncle = p_item->p_up->p_up->p_left; + ASSERT( p_grand_uncle ); + if( p_grand_uncle->color == CL_MAP_RED ) + { + p_grand_uncle->color = CL_MAP_BLACK; + p_item->p_up->color = CL_MAP_BLACK; + p_item->p_up->p_up->color = CL_MAP_RED; + p_item = p_item->p_up->p_up; + continue; + } + + if( __cl_map_is_left_child( p_item ) ) + { + p_item = p_item->p_up; + __cl_map_rot_right( p_map, p_item ); + } + p_item->p_up->color = CL_MAP_BLACK; + p_item->p_up->p_up->color = CL_MAP_RED; + __cl_map_rot_left( p_map, p_item->p_up->p_up ); + } + } +} + + +cl_map_item_t* +cl_qmap_insert( + IN cl_qmap_t* const p_map, + IN const uint64 key, + IN cl_map_item_t* const p_item ) +{ + cl_map_item_t *p_insert_at, *p_comp_item; + int compare_res = 0; + + ASSERT( p_map ); + ASSERT( p_map->state == CL_INITIALIZED ); + ASSERT( p_item ); + ASSERT( p_map->root.p_up == &p_map->root ); + ASSERT( p_map->root.color != CL_MAP_RED ); + ASSERT( p_map->nil_item.color != CL_MAP_RED ); + + /* Find the insertion location. */ + p_insert_at = &p_map->root; + p_comp_item = __cl_map_root( p_map ); + + if (p_map->key_compare == NULL) + { + while( p_comp_item != &p_map->nil_item ) + { + p_insert_at = p_comp_item; + + if( key == p_insert_at->key ) + return( p_insert_at ); + + /* Traverse the tree until the correct insertion point is found. */ + if( key < p_insert_at->key ) + { + p_comp_item = p_insert_at->p_left; + compare_res = 1; + } else { + p_comp_item = p_insert_at->p_right; + compare_res = -1; + } + } + } else { + while( p_comp_item != &p_map->nil_item ) + { + p_insert_at = p_comp_item; + compare_res = (*p_map->key_compare)(p_insert_at->key, key); + + if( compare_res == 0 ) /* key == p_insert_at->key */ + return( p_insert_at ); + + /* Traverse the tree until the correct insertion point is found. */ + if( compare_res > 0 ) /* p_insert_at->key > key */ + p_comp_item = p_insert_at->p_left; + else + p_comp_item = p_insert_at->p_right; + } + } + + ASSERT( p_insert_at != &p_map->nil_item ); + ASSERT( p_comp_item == &p_map->nil_item ); + + /* Insert the item. */ + p_item->p_left = &p_map->nil_item; + p_item->p_right = &p_map->nil_item; + p_item->key = key; + p_item->color = CL_MAP_RED; + if( p_insert_at == &p_map->root ) + { + p_insert_at->p_left = p_item; + /* + * Primitive insert places the new item in front of + * the existing item. + */ + __cl_primitive_insert( &p_map->nil_item.pool_item.list_item, + &p_item->pool_item.list_item ); + } + else if( compare_res > 0 ) /* key < p_insert_at->key */ + { + p_insert_at->p_left = p_item; + /* + * Primitive insert places the new item in front of + * the existing item. + */ + __cl_primitive_insert( &p_insert_at->pool_item.list_item, + &p_item->pool_item.list_item ); + } + else + { + p_insert_at->p_right = p_item; + /* + * Primitive insert places the new item in front of + * the existing item. + */ + __cl_primitive_insert( p_insert_at->pool_item.list_item.p_next, + &p_item->pool_item.list_item ); + } + /* Increase the count. */ + p_map->count++; + + p_item->p_up = p_insert_at; + + /* + * We have added depth to this section of the tree. + * Rebalance as necessary as we retrace our path through the tree + * and update colors. + */ + __cl_map_ins_bal( p_map, p_item ); + + __cl_map_root( p_map )->color = CL_MAP_BLACK; + + /* + * Note that it is not necessary to re-color the nil node black because all + * red color assignments are made via the p_up pointer, and nil is never + * set as the value of a p_up pointer. + */ + +#if QMAP_DEBUG + /* Set the pointer to the map in the map item for consistency checking. */ + p_item->p_map = p_map; +#endif + + return( p_item ); +} + + +static void +__cl_map_del_bal( + IN cl_qmap_t* const p_map, + IN cl_map_item_t* p_item ) +{ + cl_map_item_t *p_uncle; + + while( (p_item->color != CL_MAP_RED) && (p_item->p_up != &p_map->root) ) + { + if( __cl_map_is_left_child( p_item ) ) + { + p_uncle = p_item->p_up->p_right; + + if( p_uncle->color == CL_MAP_RED ) + { + p_uncle->color = CL_MAP_BLACK; + p_item->p_up->color = CL_MAP_RED; + __cl_map_rot_left( p_map, p_item->p_up ); + p_uncle = p_item->p_up->p_right; + } + + if( p_uncle->p_right->color != CL_MAP_RED ) + { + if( p_uncle->p_left->color != CL_MAP_RED ) + { + p_uncle->color = CL_MAP_RED; + p_item = p_item->p_up; + continue; + } + + p_uncle->p_left->color = CL_MAP_BLACK; + p_uncle->color = CL_MAP_RED; + __cl_map_rot_right( p_map, p_uncle ); + p_uncle = p_item->p_up->p_right; + } + p_uncle->color = p_item->p_up->color; + p_item->p_up->color = CL_MAP_BLACK; + p_uncle->p_right->color = CL_MAP_BLACK; + __cl_map_rot_left( p_map, p_item->p_up ); + break; + } + else + { + p_uncle = p_item->p_up->p_left; + + if( p_uncle->color == CL_MAP_RED ) + { + p_uncle->color = CL_MAP_BLACK; + p_item->p_up->color = CL_MAP_RED; + __cl_map_rot_right( p_map, p_item->p_up ); + p_uncle = p_item->p_up->p_left; + } + + if( p_uncle->p_left->color != CL_MAP_RED ) + { + if( p_uncle->p_right->color != CL_MAP_RED ) + { + p_uncle->color = CL_MAP_RED; + p_item = p_item->p_up; + continue; + } + + p_uncle->p_right->color = CL_MAP_BLACK; + p_uncle->color = CL_MAP_RED; + __cl_map_rot_left( p_map, p_uncle ); + p_uncle = p_item->p_up->p_left; + } + p_uncle->color = p_item->p_up->color; + p_item->p_up->color = CL_MAP_BLACK; + p_uncle->p_left->color = CL_MAP_BLACK; + __cl_map_rot_right( p_map, p_item->p_up ); + break; + } + } + p_item->color = CL_MAP_BLACK; +} + +void +cl_qmap_remove_item( + IN cl_qmap_t* const p_map, + IN cl_map_item_t* const p_item ) +{ + cl_map_item_t *p_child, *p_del_item; + + ASSERT( p_map ); + ASSERT( p_map->state == CL_INITIALIZED ); + ASSERT( p_item ); +#if QMAP_DEBUG + ASSERT( p_item->p_map == p_map ); +#endif + + if( p_item == cl_qmap_end( p_map ) ) + return; + + if( (p_item->p_right == &p_map->nil_item) || (p_item->p_left == &p_map->nil_item ) ) + { + /* The item being removed has children on at most on side. */ + p_del_item = p_item; + } + else + { + /* + * The item being removed has children on both side. + * We select the item that will replace it. After removing + * the substitute item and rebalancing, the tree will have the + * correct topology. Exchanging the substitute for the item + * will finalize the removal. + */ + p_del_item = cl_qmap_next( p_item ); + ASSERT( p_del_item != &p_map->nil_item ); + } + + /* Remove the item from the list. */ + __cl_primitive_remove( &p_item->pool_item.list_item ); + /* Decrement the item count. */ + p_map->count--; + + /* Get the pointer to the new root's child, if any. */ + if( p_del_item->p_left != &p_map->nil_item ) + p_child = p_del_item->p_left; + else + p_child = p_del_item->p_right; + + /* + * This assignment may modify the parent pointer of the nil node. + * This is inconsequential. + */ + p_child->p_up = p_del_item->p_up; + (*__cl_map_get_parent_ptr_to_item( p_del_item )) = p_child; + + if( p_del_item->color != CL_MAP_RED ) + __cl_map_del_bal( p_map, p_child ); + + /* + * Note that the splicing done below does not need to occur before + * the tree is balanced, since the actual topology changes are made by the + * preceding code. The topology is preserved by the color assignment made + * below (reader should be reminded that p_del_item == p_item in some cases). + */ + if( p_del_item != p_item ) + { + /* + * Finalize the removal of the specified item by exchanging it with + * the substitute which we removed above. + */ + p_del_item->p_up = p_item->p_up; + p_del_item->p_left = p_item->p_left; + p_del_item->p_right = p_item->p_right; + (*__cl_map_get_parent_ptr_to_item( p_item )) = p_del_item; + p_item->p_right->p_up = p_del_item; + p_item->p_left->p_up = p_del_item; + p_del_item->color = p_item->color; + } + + ASSERT( p_map->nil_item.color != CL_MAP_RED ); + +#if QMAP_DEBUG + /* Clear the pointer to the map since the item has been removed. */ + p_item->p_map = NULL; +#endif +} + + +cl_map_item_t* +cl_qmap_remove( + IN cl_qmap_t* const p_map, + IN const uint64 key ) +{ + cl_map_item_t *p_item; + + ASSERT( p_map ); + ASSERT( p_map->state == CL_INITIALIZED ); + + /* Seek the node with the specified key */ + p_item = cl_qmap_get( p_map, key ); + + cl_qmap_remove_item( p_map, p_item ); + + return( p_item ); +} + +cl_map_item_t* +cl_qmap_remove_compare( + IN cl_qmap_t* const p_map, + IN const uint64 key, + IN cl_pfn_qmap_compare_key_t key_compare) +{ + cl_map_item_t *p_item; + + ASSERT( p_map ); + ASSERT( p_map->state == CL_INITIALIZED ); + + /* Seek the node with the specified key */ + p_item = cl_qmap_get_compare( p_map, key, key_compare ); + + cl_qmap_remove_item( p_map, p_item ); + + return( p_item ); +} + +void +cl_qmap_merge( + OUT cl_qmap_t* const p_dest_map, + IN OUT cl_qmap_t* const p_src_map ) +{ + cl_map_item_t *p_item, *p_item2, *p_next; + + ASSERT( p_dest_map ); + ASSERT( p_src_map ); + ASSERT( p_src_map->key_compare == p_dest_map->key_compare ); + + p_item = cl_qmap_head( p_src_map ); + + while( p_item != cl_qmap_end( p_src_map ) ) + { + p_next = cl_qmap_next( p_item ); + + /* Remove the item from its current map. */ + cl_qmap_remove_item( p_src_map, p_item ); + /* Insert the item into the destination map. */ + p_item2 = cl_qmap_insert( p_dest_map, cl_qmap_key( p_item ), p_item ); + /* Check that the item was successfully inserted. */ + if( p_item2 != p_item ) + { + /* Put the item in back in the source map. */ + p_item2 = + cl_qmap_insert( p_src_map, cl_qmap_key( p_item ), p_item ); + ASSERT( p_item2 == p_item ); + } + p_item = p_next; + } +} + + +static void +__cl_qmap_delta_move( + IN OUT cl_qmap_t* const p_dest, + IN OUT cl_qmap_t* const p_src, + IN OUT cl_map_item_t** const pp_item ) +{ + cl_map_item_t *p_temp, *p_next; + + /* + * Get the next item so that we can ensure that pp_item points to + * a valid item upon return from the function. + */ + p_next = cl_qmap_next( *pp_item ); + /* Move the old item from its current map the the old map. */ + cl_qmap_remove_item( p_src, *pp_item ); + p_temp = cl_qmap_insert( p_dest, cl_qmap_key( *pp_item ), *pp_item ); + /* We should never have duplicates. */ + ASSERT( p_temp == *pp_item ); + /* Point pp_item to a valid item in the source map. */ + (*pp_item) = p_next; +} + + +void +cl_qmap_delta( + IN OUT cl_qmap_t* const p_map1, + IN OUT cl_qmap_t* const p_map2, + OUT cl_qmap_t* const p_new, + OUT cl_qmap_t* const p_old ) +{ + cl_map_item_t *p_item1, *p_item2; + uint64 key1, key2; + + ASSERT( p_map1 ); + ASSERT( p_map2 ); + ASSERT( p_new ); + ASSERT( p_old ); + ASSERT( cl_is_qmap_empty( p_new ) ); + ASSERT( cl_is_qmap_empty( p_old ) ); + ASSERT( p_map1->key_compare == p_map1->key_compare ); + + p_item1 = cl_qmap_head( p_map1 ); + p_item2 = cl_qmap_head( p_map2 ); + + while( p_item1 != cl_qmap_end( p_map1 ) && + p_item2 != cl_qmap_end( p_map2 ) ) + { + key1 = cl_qmap_key( p_item1 ); + key2 = cl_qmap_key( p_item2 ); + if( key1 < key2 ) + { + /* We found an old item. */ + __cl_qmap_delta_move( p_old, p_map1, &p_item1 ); + } + else if( key1 > key2 ) + { + /* We found a new item. */ + __cl_qmap_delta_move( p_new, p_map2, &p_item2 ); + } + else + { + /* Move both forward since they have the same key. */ + p_item1 = cl_qmap_next( p_item1 ); + p_item2 = cl_qmap_next( p_item2 ); + } + } + + /* Process the remainder if the end of either source map was reached. */ + while( p_item2 != cl_qmap_end( p_map2 ) ) + __cl_qmap_delta_move( p_new, p_map2, &p_item2 ); + + while( p_item1 != cl_qmap_end( p_map1 ) ) + __cl_qmap_delta_move( p_old, p_map1, &p_item1 ); +} + + +/****************************************************************************** +******************************************************************************* +************** ************ +************** IMPLEMENTATION OF MAP ************ +************** ************ +******************************************************************************* +******************************************************************************/ + + +#if 0 +#define MAP_GROW_SIZE 32 + + +void +cl_map_construct( + IN cl_map_t* const p_map ) +{ + ASSERT( p_map ); + + cl_qpool_construct( &p_map->pool ); +} + + +cl_status_t +cl_map_init( + IN cl_map_t* const p_map, + IN const size_t min_items ) +{ + size_t grow_size; + + ASSERT( p_map ); + + cl_qmap_init( &p_map->qmap ); + + /* + * We will grow by min_items/8 items at a time, with a minimum of + * MAP_GROW_SIZE. + */ + grow_size = min_items >> 3; + if( grow_size < MAP_GROW_SIZE ) + grow_size = MAP_GROW_SIZE; + + return( cl_qpool_init( &p_map->pool, min_items, 0, grow_size, + sizeof(cl_map_obj_t), NULL, NULL, NULL ) ); +} + + +void +cl_map_destroy( + IN cl_map_t* const p_map ) +{ + ASSERT( p_map ); + + cl_qpool_destroy( &p_map->pool ); +} + + +void* +cl_map_insert( + IN cl_map_t* const p_map, + IN const uint64 key, + IN const void* const p_object ) +{ + cl_map_obj_t *p_map_obj, *p_obj_at_key; + + ASSERT( p_map ); + + p_map_obj = (cl_map_obj_t*)cl_qpool_get( &p_map->pool ); + + if( !p_map_obj ) + return( NULL ); + + cl_qmap_set_obj( p_map_obj, p_object ); + + p_obj_at_key = + (cl_map_obj_t*)cl_qmap_insert( &p_map->qmap, key, &p_map_obj->item ); + + /* Return the item to the pool if insertion failed. */ + if( p_obj_at_key != p_map_obj ) + cl_qpool_put( &p_map->pool, &p_map_obj->item.pool_item ); + + return( cl_qmap_obj( p_obj_at_key ) ); +} + + +void* +cl_map_get( + IN const cl_map_t* const p_map, + IN const uint64 key ) +{ + cl_map_item_t *p_item; + + ASSERT( p_map ); + + p_item = cl_qmap_get( &p_map->qmap, key ); + + if( p_item == cl_qmap_end( &p_map->qmap ) ) + return( NULL ); + + return( cl_qmap_obj( PARENT_STRUCT( p_item, cl_map_obj_t, item ) ) ); +} + + +void +cl_map_remove_item( + IN cl_map_t* const p_map, + IN const cl_map_iterator_t itor ) +{ + ASSERT( itor->p_map == &p_map->qmap ); + + if( itor == cl_map_end( p_map ) ) + return; + + cl_qmap_remove_item( &p_map->qmap, (cl_map_item_t*)itor ); + cl_qpool_put( &p_map->pool, &((cl_map_item_t*)itor)->pool_item ); +} + + +void* +cl_map_remove( + IN cl_map_t* const p_map, + IN const uint64 key ) +{ + cl_map_item_t *p_item; + + ASSERT( p_map ); + + p_item = cl_qmap_remove( &p_map->qmap, key ); + + if( p_item == cl_qmap_end( &p_map->qmap ) ) + return( NULL ); + + cl_qpool_put( &p_map->pool, &p_item->pool_item ); + + return( cl_qmap_obj( (cl_map_obj_t*)p_item ) ); +} + + +void +cl_map_remove_all( + IN cl_map_t* const p_map ) +{ + cl_map_item_t *p_item; + + ASSERT( p_map ); + + /* Return all map items to the pool. */ + while( !cl_is_qmap_empty( &p_map->qmap ) ) + { + p_item = cl_qmap_head( &p_map->qmap ); + cl_qmap_remove_item( &p_map->qmap, p_item ); + cl_qpool_put( &p_map->pool, &p_item->pool_item ); + + if( !cl_is_qmap_empty( &p_map->qmap ) ) + { + p_item = cl_qmap_tail( &p_map->qmap ); + cl_qmap_remove_item( &p_map->qmap, p_item ); + cl_qpool_put( &p_map->pool, &p_item->pool_item ); + } + } +} + + +cl_status_t +cl_map_merge( + OUT cl_map_t* const p_dest_map, + IN OUT cl_map_t* const p_src_map ) +{ + cl_status_t status = CL_SUCCESS; + cl_map_iterator_t itor, next; + uint64 key; + void *p_obj, *p_obj2; + + ASSERT( p_dest_map ); + ASSERT( p_src_map ); + + itor = cl_map_head( p_src_map ); + while( itor != cl_map_end( p_src_map ) ) + { + next = cl_map_next( itor ); + + p_obj = cl_map_obj( itor ); + key = cl_map_key( itor ); + + cl_map_remove_item( p_src_map, itor ); + + /* Insert the object into the destination map. */ + p_obj2 = cl_map_insert( p_dest_map, key, p_obj ); + /* Trap for failure. */ + if( p_obj != p_obj2 ) + { + if( !p_obj2 ) + status = CL_INSUFFICIENT_MEMORY; + /* Put the object back in the source map. This must succeed. */ + p_obj2 = cl_map_insert( p_src_map, key, p_obj ); + ASSERT( p_obj == p_obj2 ); + /* If the failure was due to insufficient memory, return. */ + if( status != CL_SUCCESS ) + return( status ); + } + itor = next; + } + + return( CL_SUCCESS ); +} + + +static void +__cl_map_revert( + IN OUT cl_map_t* const p_map1, + IN OUT cl_map_t* const p_map2, + IN OUT cl_map_t* const p_new, + IN OUT cl_map_t* const p_old ) +{ + cl_status_t status; + + /* Restore the initial state. */ + status = cl_map_merge( p_map1, p_old ); + ASSERT( status == CL_SUCCESS ); + status = cl_map_merge( p_map2, p_new ); + ASSERT( status == CL_SUCCESS ); +} + + +static cl_status_t +__cl_map_delta_move( + OUT cl_map_t* const p_dest, + IN OUT cl_map_t* const p_src, + IN OUT cl_map_iterator_t* const p_itor ) +{ + cl_map_iterator_t next; + void *p_obj, *p_obj2; + uint64 key; + + /* Get a valid iterator so we can continue the loop. */ + next = cl_map_next( *p_itor ); + /* Get the pointer to the object for insertion. */ + p_obj = cl_map_obj( *p_itor ); + /* Get the key for the object. */ + key = cl_map_key( *p_itor ); + /* Move the object. */ + cl_map_remove_item( p_src, *p_itor ); + p_obj2 = cl_map_insert( p_dest, key, p_obj ); + /* Check for failure. We should never get a duplicate. */ + if( !p_obj2 ) + { + p_obj2 = cl_map_insert( p_src, key, p_obj ); + ASSERT( p_obj2 == p_obj ); + return( CL_INSUFFICIENT_MEMORY ); + } + + /* We should never get a duplicate */ + ASSERT( p_obj == p_obj2 ); + /* Update the iterator so that it is valid. */ + (*p_itor) = next; + + return( CL_SUCCESS ); +} + + +cl_status_t +cl_map_delta( + IN OUT cl_map_t* const p_map1, + IN OUT cl_map_t* const p_map2, + OUT cl_map_t* const p_new, + OUT cl_map_t* const p_old ) +{ + cl_map_iterator_t itor1, itor2; + uint64 key1, key2; + cl_status_t status; + + ASSERT( p_map1 ); + ASSERT( p_map2 ); + ASSERT( p_new ); + ASSERT( p_old ); + ASSERT( cl_is_map_empty( p_new ) ); + ASSERT( cl_is_map_empty( p_old ) ); + + itor1 = cl_map_head( p_map1 ); + itor2 = cl_map_head( p_map2 ); + + /* + * Note that the check is for the end, since duplicate items will remain + * in their respective maps. + */ + while( itor1 != cl_map_end( p_map1 ) && + itor2 != cl_map_end( p_map2 ) ) + { + key1 = cl_map_key( itor1 ); + key2 = cl_map_key( itor2 ); + if( key1 < key2 ) + { + status = __cl_map_delta_move( p_old, p_map1, &itor1 ); + /* Check for failure. */ + if( status != CL_SUCCESS ) + { + /* Restore the initial state. */ + __cl_map_revert( p_map1, p_map2, p_new, p_old ); + /* Return the failure status. */ + return( status ); + } + } + else if( key1 > key2 ) + { + status = __cl_map_delta_move( p_new, p_map2, &itor2 ); + if( status != CL_SUCCESS ) + { + /* Restore the initial state. */ + __cl_map_revert( p_map1, p_map2, p_new, p_old ); + /* Return the failure status. */ + return( status ); + } + } + else + { + /* Move both forward since they have the same key. */ + itor1 = cl_map_next( itor1 ); + itor2 = cl_map_next( itor2 ); + } + } + + /* Process the remainder if either source map is empty. */ + while( itor2 != cl_map_end( p_map2 ) ) + { + status = __cl_map_delta_move( p_new, p_map2, &itor2 ); + if( status != CL_SUCCESS ) + { + /* Restore the initial state. */ + __cl_map_revert( p_map1, p_map2, p_new, p_old ); + /* Return the failure status. */ + return( status ); + } + } + + while( itor1 != cl_map_end( p_map1 ) ) + { + status = __cl_map_delta_move( p_old, p_map1, &itor1 ); + if( status != CL_SUCCESS ) + { + /* Restore the initial state. */ + __cl_map_revert( p_map1, p_map2, p_new, p_old ); + /* Return the failure status. */ + return( status ); + } + } + + return( CL_SUCCESS ); +} + + +/****************************************************************************** +******************************************************************************* +************** ************ +************** IMPLEMENTATION OF FLEXI MAP ************ +************** ************ +******************************************************************************* +******************************************************************************/ + +/* + * Get the root. + */ +static inline cl_fmap_item_t* +__cl_fmap_root( + IN const cl_fmap_t* const p_map ) +{ + ASSERT( p_map ); + return( p_map->root.p_left ); +} + + +/* + * Returns whether a given item is on the left of its parent. + */ +static boolean +__cl_fmap_is_left_child( + IN const cl_fmap_item_t* const p_item ) +{ + ASSERT( p_item ); + ASSERT( p_item->p_up ); + ASSERT( p_item->p_up != p_item ); + + return( p_item->p_up->p_left == p_item ); +} + + +/* + * Retrieve the pointer to the parent's pointer to an item. + */ +static cl_fmap_item_t** +__cl_fmap_get_parent_ptr_to_item( + IN cl_fmap_item_t* const p_item ) +{ + ASSERT( p_item ); + ASSERT( p_item->p_up ); + ASSERT( p_item->p_up != p_item ); + + if( __cl_fmap_is_left_child( p_item ) ) + return( &p_item->p_up->p_left ); + + ASSERT( p_item->p_up->p_right == p_item ); + return( &p_item->p_up->p_right ); +} + + +/* + * Rotate a node to the left. This rotation affects the least number of links + * between nodes and brings the level of C up by one while increasing the depth + * of A one. Note that the links to/from W, X, Y, and Z are not affected. + * + * R R + * | | + * A C + * / \ / \ + * W C A Z + * / \ / \ + * B Z W B + * / \ / \ + * X Y X Y + */ +static void +__cl_fmap_rot_left( + IN cl_fmap_t* const p_map, + IN cl_fmap_item_t* const p_item ) +{ + cl_fmap_item_t **pp_root; + + ASSERT( p_map ); + ASSERT( p_item ); + ASSERT( p_item->p_right != &p_map->nil_item ); + + pp_root = __cl_fmap_get_parent_ptr_to_item( p_item ); + + /* Point R to C instead of A. */ + *pp_root = p_item->p_right; + /* Set C's parent to R. */ + (*pp_root)->p_up = p_item->p_up; + + /* Set A's right to B */ + p_item->p_right = (*pp_root)->p_left; + /* + * Set B's parent to A. We trap for B being NIL since the + * caller may depend on NIL not changing. + */ + if( (*pp_root)->p_left != &p_map->nil_item ) + (*pp_root)->p_left->p_up = p_item; + + /* Set C's left to A. */ + (*pp_root)->p_left = p_item; + /* Set A's parent to C. */ + p_item->p_up = *pp_root; +} + + +/* + * Rotate a node to the right. This rotation affects the least number of links + * between nodes and brings the level of A up by one while increasing the depth + * of C one. Note that the links to/from W, X, Y, and Z are not affected. + * + * R R + * | | + * C A + * / \ / \ + * A Z W C + * / \ / \ + * W B B Z + * / \ / \ + * X Y X Y + */ +static void +__cl_fmap_rot_right( + IN cl_fmap_t* const p_map, + IN cl_fmap_item_t* const p_item ) +{ + cl_fmap_item_t **pp_root; + + ASSERT( p_map ); + ASSERT( p_item ); + ASSERT( p_item->p_left != &p_map->nil_item ); + + /* Point R to A instead of C. */ + pp_root = __cl_fmap_get_parent_ptr_to_item( p_item ); + (*pp_root) = p_item->p_left; + /* Set A's parent to R. */ + (*pp_root)->p_up = p_item->p_up; + + /* Set C's left to B */ + p_item->p_left = (*pp_root)->p_right; + /* + * Set B's parent to C. We trap for B being NIL since the + * caller may depend on NIL not changing. + */ + if( (*pp_root)->p_right != &p_map->nil_item ) + (*pp_root)->p_right->p_up = p_item; + + /* Set A's right to C. */ + (*pp_root)->p_right = p_item; + /* Set C's parent to A. */ + p_item->p_up = *pp_root; +} + + +void +cl_fmap_init( + IN cl_fmap_t* const p_map, + IN cl_pfn_fmap_cmp_t pfn_compare ) +{ + ASSERT( p_map ); + ASSERT( pfn_compare ); + + MemoryClear( p_map, sizeof(cl_fmap_t) ); + + /* special setup for the root node */ + p_map->root.p_up = &p_map->root; + p_map->root.p_left = &p_map->nil_item; + p_map->root.p_right = &p_map->nil_item; + p_map->root.color = CL_MAP_BLACK; +#if QMAP_DEBUG + p_map->root.p_map = p_map; +#endif + + /* Setup the node used as terminator for all leaves. */ + p_map->nil_item.p_up = &p_map->nil_item; + p_map->nil_item.p_left = &p_map->nil_item; + p_map->nil_item.p_right = &p_map->nil_item; + p_map->nil_item.color = CL_MAP_BLACK; +#if QMAP_DEBUG + p_map->nil_item.p_map = p_map; +#endif + + /* Store the compare function pointer. */ + p_map->pfn_compare = pfn_compare; + + p_map->state = CL_INITIALIZED; + + cl_fmap_remove_all( p_map ); +} + + +cl_fmap_item_t* +cl_fmap_get( + IN const cl_fmap_t* const p_map, + IN const void* const p_key ) +{ + cl_fmap_item_t *p_item; + intn_t cmp; + + ASSERT( p_map ); + ASSERT( p_map->state == CL_INITIALIZED ); + + p_item = __cl_fmap_root( p_map ); + + while( p_item != &p_map->nil_item ) + { + cmp = p_map->pfn_compare( p_key, p_item->p_key ); + + if( !cmp ) + break; /* just right */ + + if( cmp < 0 ) + p_item = p_item->p_left; /* too small */ + else + p_item = p_item->p_right; /* too big */ + } + + return( p_item ); +} + + +void +cl_fmap_apply_func( + IN const cl_fmap_t* const p_map, + IN cl_pfn_fmap_apply_t pfn_func, + IN const void* const context ) +{ + cl_fmap_item_t* p_fmap_item; + + /* Note that context can have any arbitrary value. */ + ASSERT( p_map ); + ASSERT( p_map->state == CL_INITIALIZED ); + ASSERT( pfn_func ); + + p_fmap_item = cl_fmap_head( p_map ); + while( p_fmap_item != cl_fmap_end( p_map ) ) + { + pfn_func( p_fmap_item, (void*)context ); + p_fmap_item = cl_fmap_next( p_fmap_item ); + } +} + + +/* + * Balance a tree starting at a given item back to the root. + */ +static void +__cl_fmap_ins_bal( + IN cl_fmap_t* const p_map, + IN cl_fmap_item_t* p_item ) +{ + cl_fmap_item_t* p_grand_uncle; + + ASSERT( p_map ); + ASSERT( p_item ); + ASSERT( p_item != &p_map->root ); + + while( p_item->p_up->color == CL_MAP_RED ) + { + if( __cl_fmap_is_left_child( p_item->p_up ) ) + { + p_grand_uncle = p_item->p_up->p_up->p_right; + ASSERT( p_grand_uncle ); + if( p_grand_uncle->color == CL_MAP_RED ) + { + p_grand_uncle->color = CL_MAP_BLACK; + p_item->p_up->color = CL_MAP_BLACK; + p_item->p_up->p_up->color = CL_MAP_RED; + p_item = p_item->p_up->p_up; + continue; + } + + if( !__cl_fmap_is_left_child( p_item ) ) + { + p_item = p_item->p_up; + __cl_fmap_rot_left( p_map, p_item ); + } + p_item->p_up->color = CL_MAP_BLACK; + p_item->p_up->p_up->color = CL_MAP_RED; + __cl_fmap_rot_right( p_map, p_item->p_up->p_up ); + } + else + { + p_grand_uncle = p_item->p_up->p_up->p_left; + ASSERT( p_grand_uncle ); + if( p_grand_uncle->color == CL_MAP_RED ) + { + p_grand_uncle->color = CL_MAP_BLACK; + p_item->p_up->color = CL_MAP_BLACK; + p_item->p_up->p_up->color = CL_MAP_RED; + p_item = p_item->p_up->p_up; + continue; + } + + if( __cl_fmap_is_left_child( p_item ) ) + { + p_item = p_item->p_up; + __cl_fmap_rot_right( p_map, p_item ); + } + p_item->p_up->color = CL_MAP_BLACK; + p_item->p_up->p_up->color = CL_MAP_RED; + __cl_fmap_rot_left( p_map, p_item->p_up->p_up ); + } + } +} + + +cl_fmap_item_t* +cl_fmap_insert( + IN cl_fmap_t* const p_map, + IN const void* const p_key, + IN cl_fmap_item_t* const p_item ) +{ + cl_fmap_item_t *p_insert_at, *p_comp_item; + intn_t cmp = 0; + + ASSERT( p_map ); + ASSERT( p_map->state == CL_INITIALIZED ); + ASSERT( p_item ); + ASSERT( p_map->root.p_up == &p_map->root ); + ASSERT( p_map->root.color != CL_MAP_RED ); + ASSERT( p_map->nil_item.color != CL_MAP_RED ); + + p_item->p_left = &p_map->nil_item; + p_item->p_right = &p_map->nil_item; + p_item->p_key = p_key; + p_item->color = CL_MAP_RED; + + /* Find the insertion location. */ + p_insert_at = &p_map->root; + p_comp_item = __cl_fmap_root( p_map ); + + while( p_comp_item != &p_map->nil_item ) + { + p_insert_at = p_comp_item; + + cmp = p_map->pfn_compare( p_key, p_insert_at->p_key ); + + if( !cmp ) + return( p_insert_at ); + + /* Traverse the tree until the correct insertion point is found. */ + if( cmp < 0 ) + p_comp_item = p_insert_at->p_left; + else + p_comp_item = p_insert_at->p_right; + } + + ASSERT( p_insert_at != &p_map->nil_item ); + ASSERT( p_comp_item == &p_map->nil_item ); + /* Insert the item. */ + if( p_insert_at == &p_map->root ) + { + p_insert_at->p_left = p_item; + /* + * Primitive insert places the new item in front of + * the existing item. + */ + __cl_primitive_insert( &p_map->nil_item.pool_item.list_item, + &p_item->pool_item.list_item ); + } + else if( cmp < 0 ) + { + p_insert_at->p_left = p_item; + /* + * Primitive insert places the new item in front of + * the existing item. + */ + __cl_primitive_insert( &p_insert_at->pool_item.list_item, + &p_item->pool_item.list_item ); + } + else + { + p_insert_at->p_right = p_item; + /* + * Primitive insert places the new item in front of + * the existing item. + */ + __cl_primitive_insert( p_insert_at->pool_item.list_item.p_next, + &p_item->pool_item.list_item ); + } + /* Increase the count. */ + p_map->count++; + + p_item->p_up = p_insert_at; + + /* + * We have added depth to this section of the tree. + * Rebalance as necessary as we retrace our path through the tree + * and update colors. + */ + __cl_fmap_ins_bal( p_map, p_item ); + + __cl_fmap_root( p_map )->color = CL_MAP_BLACK; + + /* + * Note that it is not necessary to re-color the nil node black because all + * red color assignments are made via the p_up pointer, and nil is never + * set as the value of a p_up pointer. + */ + +#if QMAP_DEBUG + /* Set the pointer to the map in the map item for consistency checking. */ + p_item->p_map = p_map; +#endif + + return( p_item ); +} + + +static void +__cl_fmap_del_bal( + IN cl_fmap_t* const p_map, + IN cl_fmap_item_t* p_item ) +{ + cl_fmap_item_t *p_uncle; + + while( (p_item->color != CL_MAP_RED) && (p_item->p_up != &p_map->root) ) + { + if( __cl_fmap_is_left_child( p_item ) ) + { + p_uncle = p_item->p_up->p_right; + + if( p_uncle->color == CL_MAP_RED ) + { + p_uncle->color = CL_MAP_BLACK; + p_item->p_up->color = CL_MAP_RED; + __cl_fmap_rot_left( p_map, p_item->p_up ); + p_uncle = p_item->p_up->p_right; + } + + if( p_uncle->p_right->color != CL_MAP_RED ) + { + if( p_uncle->p_left->color != CL_MAP_RED ) + { + p_uncle->color = CL_MAP_RED; + p_item = p_item->p_up; + continue; + } + + p_uncle->p_left->color = CL_MAP_BLACK; + p_uncle->color = CL_MAP_RED; + __cl_fmap_rot_right( p_map, p_uncle ); + p_uncle = p_item->p_up->p_right; + } + p_uncle->color = p_item->p_up->color; + p_item->p_up->color = CL_MAP_BLACK; + p_uncle->p_right->color = CL_MAP_BLACK; + __cl_fmap_rot_left( p_map, p_item->p_up ); + break; + } + else + { + p_uncle = p_item->p_up->p_left; + + if( p_uncle->color == CL_MAP_RED ) + { + p_uncle->color = CL_MAP_BLACK; + p_item->p_up->color = CL_MAP_RED; + __cl_fmap_rot_right( p_map, p_item->p_up ); + p_uncle = p_item->p_up->p_left; + } + + if( p_uncle->p_left->color != CL_MAP_RED ) + { + if( p_uncle->p_right->color != CL_MAP_RED ) + { + p_uncle->color = CL_MAP_RED; + p_item = p_item->p_up; + continue; + } + + p_uncle->p_right->color = CL_MAP_BLACK; + p_uncle->color = CL_MAP_RED; + __cl_fmap_rot_left( p_map, p_uncle ); + p_uncle = p_item->p_up->p_left; + } + p_uncle->color = p_item->p_up->color; + p_item->p_up->color = CL_MAP_BLACK; + p_uncle->p_left->color = CL_MAP_BLACK; + __cl_fmap_rot_right( p_map, p_item->p_up ); + break; + } + } + p_item->color = CL_MAP_BLACK; +} + + +void +cl_fmap_remove_item( + IN cl_fmap_t* const p_map, + IN cl_fmap_item_t* const p_item ) +{ + cl_fmap_item_t *p_child, *p_del_item; + + ASSERT( p_map ); + ASSERT( p_map->state == CL_INITIALIZED ); + ASSERT( p_item ); +#if QMAP_DEBUG + ASSERT( p_item->p_map == p_map ); +#endif + + if( p_item == cl_fmap_end( p_map ) ) + return; + + if( (p_item->p_right == &p_map->nil_item) || (p_item->p_left == &p_map->nil_item ) ) + { + /* The item being removed has children on at most on side. */ + p_del_item = p_item; + } + else + { + /* + * The item being removed has children on both side. + * We select the item that will replace it. After removing + * the substitute item and rebalancing, the tree will have the + * correct topology. Exchanging the substitute for the item + * will finalize the removal. + */ + p_del_item = cl_fmap_next( p_item ); + ASSERT( p_del_item != &p_map->nil_item ); + } + + /* Remove the item from the list. */ + __cl_primitive_remove( &p_item->pool_item.list_item ); + /* Decrement the item count. */ + p_map->count--; + + /* Get the pointer to the new root's child, if any. */ + if( p_del_item->p_left != &p_map->nil_item ) + p_child = p_del_item->p_left; + else + p_child = p_del_item->p_right; + + /* + * This assignment may modify the parent pointer of the nil node. + * This is inconsequential. + */ + p_child->p_up = p_del_item->p_up; + (*__cl_fmap_get_parent_ptr_to_item( p_del_item )) = p_child; + + if( p_del_item->color != CL_MAP_RED ) + __cl_fmap_del_bal( p_map, p_child ); + + /* + * Note that the splicing done below does not need to occur before + * the tree is balanced, since the actual topology changes are made by the + * preceding code. The topology is preserved by the color assignment made + * below (reader should be reminded that p_del_item == p_item in some cases). + */ + if( p_del_item != p_item ) + { + /* + * Finalize the removal of the specified item by exchanging it with + * the substitute which we removed above. + */ + p_del_item->p_up = p_item->p_up; + p_del_item->p_left = p_item->p_left; + p_del_item->p_right = p_item->p_right; + (*__cl_fmap_get_parent_ptr_to_item( p_item )) = p_del_item; + p_item->p_right->p_up = p_del_item; + p_item->p_left->p_up = p_del_item; + p_del_item->color = p_item->color; + } + + ASSERT( p_map->nil_item.color != CL_MAP_RED ); + +#if QMAP_DEBUG + /* Clear the pointer to the map since the item has been removed. */ + p_item->p_map = NULL; +#endif +} + + +cl_fmap_item_t* +cl_fmap_remove( + IN cl_fmap_t* const p_map, + IN const void* const p_key ) +{ + cl_fmap_item_t *p_item; + + ASSERT( p_map ); + ASSERT( p_map->state == CL_INITIALIZED ); + + /* Seek the node with the specified key */ + p_item = cl_fmap_get( p_map, p_key ); + + cl_fmap_remove_item( p_map, p_item ); + + return( p_item ); +} + + +void +cl_fmap_merge( + OUT cl_fmap_t* const p_dest_map, + IN OUT cl_fmap_t* const p_src_map ) +{ + cl_fmap_item_t *p_item, *p_item2, *p_next; + + ASSERT( p_dest_map ); + ASSERT( p_src_map ); + + p_item = cl_fmap_head( p_src_map ); + + while( p_item != cl_fmap_end( p_src_map ) ) + { + p_next = cl_fmap_next( p_item ); + + /* Remove the item from its current map. */ + cl_fmap_remove_item( p_src_map, p_item ); + /* Insert the item into the destination map. */ + p_item2 = cl_fmap_insert( p_dest_map, cl_fmap_key( p_item ), p_item ); + /* Check that the item was successfully inserted. */ + if( p_item2 != p_item ) + { + /* Put the item in back in the source map. */ + p_item2 = + cl_fmap_insert( p_src_map, cl_fmap_key( p_item ), p_item ); + ASSERT( p_item2 == p_item ); + } + p_item = p_next; + } +} + + +static void +__cl_fmap_delta_move( + IN OUT cl_fmap_t* const p_dest, + IN OUT cl_fmap_t* const p_src, + IN OUT cl_fmap_item_t** const pp_item ) +{ + cl_fmap_item_t *p_temp, *p_next; + + /* + * Get the next item so that we can ensure that pp_item points to + * a valid item upon return from the function. + */ + p_next = cl_fmap_next( *pp_item ); + /* Move the old item from its current map the the old map. */ + cl_fmap_remove_item( p_src, *pp_item ); + p_temp = cl_fmap_insert( p_dest, cl_fmap_key( *pp_item ), *pp_item ); + /* We should never have duplicates. */ + ASSERT( p_temp == *pp_item ); + /* Point pp_item to a valid item in the source map. */ + (*pp_item) = p_next; +} + + +void +cl_fmap_delta( + IN OUT cl_fmap_t* const p_map1, + IN OUT cl_fmap_t* const p_map2, + OUT cl_fmap_t* const p_new, + OUT cl_fmap_t* const p_old ) +{ + cl_fmap_item_t *p_item1, *p_item2; + intn_t cmp; + + ASSERT( p_map1 ); + ASSERT( p_map2 ); + ASSERT( p_new ); + ASSERT( p_old ); + ASSERT( cl_is_fmap_empty( p_new ) ); + ASSERT( cl_is_fmap_empty( p_old ) ); + + p_item1 = cl_fmap_head( p_map1 ); + p_item2 = cl_fmap_head( p_map2 ); + + while( p_item1 != cl_fmap_end( p_map1 ) && + p_item2 != cl_fmap_end( p_map2 ) ) + { + cmp = p_map1->pfn_compare( cl_fmap_key( p_item1 ), + cl_fmap_key( p_item2 ) ); + if( cmp < 0 ) + { + /* We found an old item. */ + __cl_fmap_delta_move( p_old, p_map1, &p_item1 ); + } + else if( cmp > 0 ) + { + /* We found a new item. */ + __cl_fmap_delta_move( p_new, p_map2, &p_item2 ); + } + else + { + /* Move both forward since they have the same key. */ + p_item1 = cl_fmap_next( p_item1 ); + p_item2 = cl_fmap_next( p_item2 ); + } + } + + /* Process the remainder if the end of either source map was reached. */ + while( p_item2 != cl_fmap_end( p_map2 ) ) + __cl_fmap_delta_move( p_new, p_map2, &p_item2 ); + + while( p_item1 != cl_fmap_end( p_map1 ) ) + __cl_fmap_delta_move( p_old, p_map1, &p_item1 ); +} +#endif diff --git a/IbAccess/Common/Public/iquickmap.h b/IbAccess/Common/Public/iquickmap.h new file mode 100644 index 0000000..29bff98 --- /dev/null +++ b/IbAccess/Common/Public/iquickmap.h @@ -0,0 +1,1344 @@ +/* BEGIN_ICS_COPYRIGHT3 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT3 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +/* + * Abstract: + * Declaration of quick map, a binary tree where the caller always provides + * all necessary storage. + * + * Environment: + * All + * + * $Revision$ + */ + + +#ifndef _IBA_PUBLIC_IQUICKMAP_H_ +#define _IBA_PUBLIC_IQUICKMAP_H_ + + +#include "iba/public/datatypes.h" + +#define QMAP_DEBUG 0 /* beware setting this changes ABI so must rebuild all */ + +typedef struct _cl_list_item +{ + struct _cl_list_item *p_next; + struct _cl_list_item *p_prev; +#if QMAP_DEBUG + struct _cl_qlist *p_list; +#endif + +} cl_list_item_t; + + +typedef struct _cl_pool_item +{ + cl_list_item_t list_item; +#if QMAP_DEBUG + /* Pointer to the owner pool used for sanity checks. */ + struct _cl_qcpool *p_pool; +#endif + +} cl_pool_item_t; + + +typedef enum _cl_state +{ + CL_UNINITIALIZED = 1, + CL_INITIALIZED, + CL_DESTROYING, + CL_DESTROYED + +} cl_state_t; + +#define CL_INLINE static __inline +#define CL_EXPORT + +/****h* Component Library/Quick Map +* NAME +* Quick Map +* +* DESCRIPTION +* Quick map implements a binary tree that stores user provided cl_map_item_t +* structures. Each item stored in a quick map has a unique 64-bit key +* (duplicates are not allowed). Quick map provides the ability to +* efficiently search for an item given a key. +* +* Quick map does not allocate any memory, and can therefore not fail +* any operations due to insufficient memory. Quick map can thus be useful +* in minimizing the error paths in code. +* +* Quick map is not thread safe, and users must provide serialization when +* adding and removing items from the map. +* +* The quick map functions operate on a cl_qmap_t structure which should be +* treated as opaque and should be manipulated only through the provided +* functions. +* +* SEE ALSO +* Structures: +* cl_qmap_t, cl_map_item_t, cl_map_obj_t +* +* Callbacks: +* cl_pfn_qmap_apply_t +* +* Item Manipulation: +* cl_qmap_set_obj, cl_qmap_obj, cl_qmap_key +* +* Initialization: +* cl_qmap_init +* +* Iteration: +* cl_qmap_end, cl_qmap_head, cl_qmap_tail, cl_qmap_next, cl_qmap_prev +* +* Manipulation: +* cl_qmap_insert, cl_qmap_get, cl_qmap_remove_item, cl_qmap_remove, +* cl_qmap_remove_all, cl_qmap_merge, cl_qmap_delta +* +* Search: +* cl_qmap_apply_func +* +* Attributes: +* cl_qmap_count, cl_is_qmap_empty, +*********/ + + +/****i* Component Library: Quick Map/cl_map_color_t +* NAME +* cl_map_color_t +* +* DESCRIPTION +* The cl_map_color_t enumerated type is used to note the color of +* nodes in a map. +* +* SYNOPSIS +*/ +typedef enum _cl_map_color +{ + CL_MAP_RED, + CL_MAP_BLACK + +} cl_map_color_t; +/* +* VALUES +* CL_MAP_RED +* The node in the map is red. +* +* CL_MAP_BLACK +* The node in the map is black. +* +* SEE ALSO +* Quick Map, cl_map_item_t +*********/ + + +/****s* Component Library: Quick Map/cl_map_item_t +* NAME +* cl_map_item_t +* +* DESCRIPTION +* The cl_map_item_t structure is used by maps to store objects. +* +* The cl_map_item_t structure should be treated as opaque and should +* be manipulated only through the provided functions. +* +* SYNOPSIS +*/ +typedef struct _cl_map_item +{ + /* Must be first to allow casting. */ + cl_pool_item_t pool_item; + struct _cl_map_item *p_left; + struct _cl_map_item *p_right; + struct _cl_map_item *p_up; + cl_map_color_t color; + uint64 key; +#if QMAP_DEBUG + struct _cl_qmap *p_map; +#endif + +} cl_map_item_t; +/* +* FIELDS +* pool_item +* Used to store the item in a doubly linked list, allowing more +* efficient map traversal. +* +* p_left +* Pointer to the map item that is a child to the left of the node. +* +* p_right +* Pointer to the map item that is a child to the right of the node. +* +* p_up +* Pointer to the map item that is the parent of the node. +* +* p_nil +* Pointer to the map's NIL item, used as a terminator for leaves. +* The NIL sentinel is in the cl_qmap_t structure. +* +* color +* Indicates whether a node is red or black in the map. +* +* key +* Value that uniquely represents a node in a map. This value is set by +* calling cl_qmap_insert and can be retrieved by calling cl_qmap_key. +* +* NOTES +* None of the fields of this structure should be manipulated by users, as +* they are crititcal to the proper operation of the map in which they +* are stored. +* +* To allow storing items in either a quick list, a quick pool, or a quick +* map, the map implementation guarantees that the map item can be safely +* cast to a pool item used for storing an object in a quick pool, or cast to +* a list item used for storing an object in a quick list. This removes the +* need to embed a map item, a list item, and a pool item in objects that need +* to be stored in a quick list, a quick pool, and a quick map. +* +* SEE ALSO +* Quick Map, cl_qmap_insert, cl_qmap_key, cl_pool_item_t, cl_list_item_t +*********/ + + +/****s* Component Library: Quick Map/cl_map_obj_t +* NAME +* cl_map_obj_t +* +* DESCRIPTION +* The cl_map_obj_t structure is used to store objects in maps. +* +* The cl_map_obj_t structure should be treated as opaque and should +* be manipulated only through the provided functions. +* +* SYNOPSIS +*/ +typedef struct _cl_map_obj +{ + cl_map_item_t item; + const void *p_object; + +} cl_map_obj_t; +/* +* FIELDS +* item +* Map item used by internally by the map to store an object. +* +* p_object +* User defined context. Users should not access this field directly. +* Use cl_qmap_set_obj and cl_qmap_obj to set and retrieve the value +* of this field. +* +* NOTES +* None of the fields of this structure should be manipulated by users, as +* they are crititcal to the proper operation of the map in which they +* are stored. +* +* Use cl_qmap_set_obj and cl_qmap_obj to set and retrieve the object +* stored in a map item, respectively. +* +* SEE ALSO +* Quick Map, cl_qmap_set_obj, cl_qmap_obj, cl_map_item_t +*********/ + +/****d* Component Library: Quick Map/cl_pfn_qmap_key_compare_t +* NAME +* cl_pfn_qmap_key_compare_t +* +* DESCRIPTION +* The cl_pfn_qmap_akey_comparet function type defines the prototype for functions +* used to compare keys for items in a quick map. +* +* SYNOPSIS +*/ +typedef int +(*cl_pfn_qmap_compare_key_t)( + IN const uint64 key1, + IN const uint64 key2 ); +/* +* PARAMETERS +* key1 +* [in] first key to compare +* +* key2 +* [in] second key to compare +* +* RETURN VALUE +* -1 key1 < key2 +* 0 key1 == key2 +* 1 key1 > key2 +* +* NOTES +* This function type is provided as function prototype reference for the +* function provided by users as a parameter to the cl_qmap_init and +* some other functions. +* +* Comparision must be consistent. Eg. +* if key1 < key2 +* then key2 > key1 +* +* often key1 and key2 are cast by the function to a pointer to a key object or +* subfield within the map object. However they could also do +* odd-collating sequences (or ignore bits) in uint64 keys +* +* SEE ALSO +* Quick Map, cl_qmap_init +*********/ + +/****d* Component Library: Quick Map/cl_pfn_qmap_item_compare_t +* NAME +* cl_pfn_qmap_item_compare_t +* +* DESCRIPTION +* The cl_pfn_qmap_item_compare_t function type defines the prototype for functions +* used to compare an item to a key for items in a quick map. +* +* SYNOPSIS +*/ +typedef int +(*cl_pfn_qmap_item_compare_t)( + IN const cl_map_item_t* item, + IN const uint64 key ); +/* +* PARAMETERS +* item +* [in] item to compare +* +* key +* [in] key to compare +* +* RETURN VALUE +* -1 item < key +* 0 item == key +* 1 item > key +* +* NOTES +* This function type is provided as function prototype reference for the +* function provided by users as a parameter to cl_qmap_get_item_compare +* and some other functions. +* +* Comparision must be consistent. Eg. +* if item < key +* then key > item +* +* SEE ALSO +* Quick Map, cl_qmap_get_item_compare +*********/ + +/****s* Component Library: Quick Map/cl_qmap_t +* NAME +* cl_qmap_t +* +* DESCRIPTION +* Quick map structure. +* +* The cl_qmap_t structure should be treated as opaque and should +* be manipulated only through the provided functions. +* +* SYNOPSIS +*/ +typedef struct _cl_qmap +{ + cl_map_item_t root; + cl_map_item_t nil_item; + cl_state_t state; + size_t count; + cl_pfn_qmap_compare_key_t key_compare; /* optional compare function */ + +} cl_qmap_t; +/* +* PARAMETERS +* root +* Map item that serves as root of the map. The root is set up to +* always have itself as parent. The left pointer is set to point to +* the item at the root. +* +* nil_item +* Map item that serves as terminator for all leaves, as well as providing +* the list item used as quick list for storing map items in a list for +* faster traversal. +* +* state +* State of the map, used to verify that operations are permitted. +* +* count +* Number of items in the map. +* +* SEE ALSO +* Quick Map +*********/ + + +/****d* Component Library: Quick Map/cl_pfn_qmap_apply_t +* NAME +* cl_pfn_qmap_apply_t +* +* DESCRIPTION +* The cl_pfn_qmap_apply_t function type defines the prototype for functions +* used to iterate items in a quick map. +* +* SYNOPSIS +*/ +typedef void +(*cl_pfn_qmap_apply_t)( + IN cl_map_item_t* const p_map_item, + IN void* context ); +/* +* PARAMETERS +* p_map_item +* [in] Pointer to a cl_map_item_t structure. +* +* context +* [in] Value passed to the callback function. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* This function type is provided as function prototype reference for the +* function provided by users as a parameter to the cl_qmap_apply_func +* function. +* +* SEE ALSO +* Quick Map, cl_qmap_apply_func +*********/ + + +#ifdef __cplusplus +extern "C" { +#endif + + +/****f* Component Library: Quick Map/cl_qmap_count +* NAME +* cl_qmap_count +* +* DESCRIPTION +* The cl_qmap_count function returns the number of items stored +* in a quick map. +* +* SYNOPSIS +*/ +CL_INLINE size_t +cl_qmap_count( + IN const cl_qmap_t* const p_map ) +{ + ASSERT( p_map ); + ASSERT( p_map->state == CL_INITIALIZED ); + return( p_map->count ); +} +/* +* PARAMETERS +* p_map +* [in] Pointer to a cl_qmap_t structure whose item count to return. +* +* RETURN VALUE +* Returns the number of items stored in the map. +* +* SEE ALSO +* Quick Map, cl_is_qmap_empty +*********/ + + +/****f* Component Library: Quick Map/cl_is_qmap_empty +* NAME +* cl_is_qmap_empty +* +* DESCRIPTION +* The cl_is_qmap_empty function returns whether a quick map is empty. +* +* SYNOPSIS +*/ +CL_INLINE boolean +cl_is_qmap_empty( + IN const cl_qmap_t* const p_map ) +{ + ASSERT( p_map ); + ASSERT( p_map->state == CL_INITIALIZED ); + + return( p_map->count == 0 ); +} +/* +* PARAMETERS +* p_map +* [in] Pointer to a cl_qmap_t structure to test for emptiness. +* +* RETURN VALUES +* TRUE if the quick map is empty. +* +* FALSE otherwise. +* +* SEE ALSO +* Quick Map, cl_qmap_count, cl_qmap_remove_all +*********/ + + +/****f* Component Library: Quick Map/cl_qmap_set_obj +* NAME +* cl_qmap_set_obj +* +* DESCRIPTION +* The cl_qmap_set_obj function sets the object stored in a map object. +* +* SYNOPSIS +*/ +CL_INLINE void +cl_qmap_set_obj( + IN cl_map_obj_t* const p_map_obj, + IN const void* const p_object ) +{ + ASSERT( p_map_obj ); + p_map_obj->p_object = p_object; +} +/* +* PARAMETERS +* p_map_obj +* [in] Pointer to a map object stucture whose object pointer +* is to be set. +* +* p_object +* [in] User defined context. +* +* RETURN VALUE +* This function does not return a value. +* +* SEE ALSO +* Quick Map, cl_qmap_obj +*********/ + + +/****f* Component Library: Quick Map/cl_qmap_obj +* NAME +* cl_qmap_obj +* +* DESCRIPTION +* The cl_qmap_obj function returns the object stored in a map object. +* +* SYNOPSIS +*/ +CL_INLINE void* +cl_qmap_obj( + IN const cl_map_obj_t* const p_map_obj ) +{ + ASSERT( p_map_obj ); + return( (void*)p_map_obj->p_object ); +} +/* +* PARAMETERS +* p_map_obj +* [in] Pointer to a map object stucture whose object pointer to return. +* +* RETURN VALUE +* Returns the value of the object pointer stored in the map object. +* +* SEE ALSO +* Quick Map, cl_qmap_set_obj +*********/ + + +/****f* Component Library: Quick Map/cl_qmap_key +* NAME +* cl_qmap_key +* +* DESCRIPTION +* The cl_qmap_key function retrieves the key value of a map item. +* +* SYNOPSIS +*/ +CL_INLINE uint64 +cl_qmap_key( + IN const cl_map_item_t* const p_item ) +{ + ASSERT( p_item ); + return( p_item->key ); +} +/* +* PARAMETERS +* p_item +* [in] Pointer to a map item whose key value to return. +* +* RETURN VALUE +* Returns the 64-bit key value for the specified map item. +* +* NOTES +* The key value is set in a call to cl_qmap_insert. +* +* SEE ALSO +* Quick Map, cl_qmap_insert +*********/ + + +/****f* Component Library: Quick Map/cl_qmap_init +* NAME +* cl_qmap_init +* +* DESCRIPTION +* The cl_qmap_init function initialized a quick map for use. +* +* SYNOPSIS +*/ +CL_EXPORT void +cl_qmap_init( + IN cl_qmap_t* const p_map, + IN cl_pfn_qmap_compare_key_t key_compare ); +/* +* PARAMETERS +* p_map +* [in] Pointer to a cl_qmap_t structure to initialize. +* +* key_compare +* [in] Optional key_compare function (NULL if uint64 keys used) +* +* RETURN VALUES +* This function does not return a value. +* +* NOTES +* Allows calling quick map manipulation functions. +* +* SEE ALSO +* Quick Map, cl_qmap_insert, cl_qmap_remove +*********/ + + +/****f* Component Library: Quick Map/cl_qmap_end +* NAME +* cl_qmap_end +* +* DESCRIPTION +* The cl_qmap_end function returns the end of a quick map. +* +* SYNOPSIS +*/ +CL_INLINE const cl_map_item_t * +cl_qmap_end( + IN const cl_qmap_t* const p_map ) +{ + ASSERT( p_map ); + ASSERT( p_map->state == CL_INITIALIZED ); + /* Nil is the end of the map. */ + return( &p_map->nil_item ); +} +/* +* PARAMETERS +* p_map +* [in] Pointer to a cl_qmap_t structure whose end to return. +* +* RETURN VALUE +* Pointer to the end of the map. +* +* NOTES +* cl_qmap_end is useful for determining the validity of map items returned +* by cl_qmap_head, cl_qmap_tail, cl_qmap_next, or cl_qmap_prev. If the map +* item pointer returned by any of these functions compares to the end, the +* end of the map was encoutered. +* When using cl_qmap_head or cl_qmap_tail, this condition indicates that +* the map is empty. +* +* SEE ALSO +* Quick Map, cl_qmap_head, cl_qmap_tail, cl_qmap_next, cl_qmap_prev +*********/ + + +/****f* Component Library: Quick Map/cl_qmap_head +* NAME +* cl_qmap_head +* +* DESCRIPTION +* The cl_qmap_head function returns the map item with the lowest key +* value stored in a quick map. +* +* SYNOPSIS +*/ +CL_INLINE cl_map_item_t* +cl_qmap_head( + IN const cl_qmap_t* const p_map ) +{ + ASSERT( p_map ); + ASSERT( p_map->state == CL_INITIALIZED ); + return( (cl_map_item_t*)p_map->nil_item.pool_item.list_item.p_next ); +} +/* +* PARAMETERS +* p_map +* [in] Pointer to a cl_qmap_t structure whose item with the lowest key +* is returned. +* +* RETURN VALUES +* Pointer to the map item with the lowest key in the quick map. +* +* Pointer to the map end if the quick map was empty. +* +* NOTES +* cl_qmap_head does not remove the item from the map. +* +* SEE ALSO +* Quick Map, cl_qmap_tail, cl_qmap_next, cl_qmap_prev, cl_qmap_end, +* cl_qmap_item_t +*********/ + + +/****f* Component Library: Quick Map/cl_qmap_tail +* NAME +* cl_qmap_tail +* +* DESCRIPTION +* The cl_qmap_tail function returns the map item with the highest key +* value stored in a quick map. +* +* SYNOPSIS +*/ +CL_INLINE cl_map_item_t* +cl_qmap_tail( + IN const cl_qmap_t* const p_map ) +{ + ASSERT( p_map ); + ASSERT( p_map->state == CL_INITIALIZED ); + return( (cl_map_item_t*)p_map->nil_item.pool_item.list_item.p_prev ); +} +/* +* PARAMETERS +* p_map +* [in] Pointer to a cl_qmap_t structure whose item with the highest key +* is returned. +* +* RETURN VALUES +* Pointer to the map item with the highest key in the quick map. +* +* Pointer to the map end if the quick map was empty. +* +* NOTES +* cl_qmap_end does not remove the item from the map. +* +* SEE ALSO +* Quick Map, cl_qmap_head, cl_qmap_next, cl_qmap_prev, cl_qmap_end, +* cl_qmap_item_t +*********/ + + +/****f* Component Library: Quick Map/cl_qmap_next +* NAME +* cl_qmap_next +* +* DESCRIPTION +* The cl_qmap_next function returns the map item with the next higher +* key value than a specified map item. +* +* SYNOPSIS +*/ +CL_INLINE cl_map_item_t* +cl_qmap_next( + IN const cl_map_item_t* const p_item ) +{ + ASSERT( p_item ); + return( (cl_map_item_t*)p_item->pool_item.list_item.p_next ); +} +/* +* PARAMETERS +* p_item +* [in] Pointer to a map item whose successor to return. +* +* RETURN VALUES +* Pointer to the map item with the next higher key value in a quick map. +* +* Pointer to the map end if the specified item was the last item in +* the quick map. +* +* SEE ALSO +* Quick Map, cl_qmap_head, cl_qmap_tail, cl_qmap_prev, cl_qmap_end, +* cl_map_item_t +*********/ + + +/****f* Component Library: Quick Map/cl_qmap_prev +* NAME +* cl_qmap_prev +* +* DESCRIPTION +* The cl_qmap_prev function returns the map item with the next lower +* key value than a precified map item. +* +* SYNOPSIS +*/ +CL_INLINE cl_map_item_t* +cl_qmap_prev( + IN const cl_map_item_t* const p_item ) +{ + ASSERT( p_item ); + return( (cl_map_item_t*)p_item->pool_item.list_item.p_prev ); +} +/* +* PARAMETERS +* p_item +* [in] Pointer to a map item whose predecessor to return. +* +* RETURN VALUES +* Pointer to the map item with the next lower key value in a quick map. +* +* Pointer to the map end if the specifid item was the first item in +* the quick map. +* +* SEE ALSO +* Quick Map, cl_qmap_head, cl_qmap_tail, cl_qmap_next, cl_qmap_end, +* cl_map_item_t +*********/ + + +/****f* Component Library: Quick Map/cl_qmap_insert +* NAME +* cl_qmap_insert +* +* DESCRIPTION +* The cl_qmap_insert function inserts a map item into a quick map. +* +* SYNOPSIS +*/ +CL_EXPORT cl_map_item_t* +cl_qmap_insert( + IN cl_qmap_t* const p_map, + IN const uint64 key, + IN cl_map_item_t* const p_item ); +/* +* PARAMETERS +* p_map +* [in] Pointer to a cl_qmap_t structure into which to add the item. +* +* key +* [in] Value to assign to the item. If Quickmap uses a key +* compare function, this must be pointer to key structure for +* object added to list +* +* p_item +* [in] Pointer to a cl_map_item_t stucture to insert into the quick map. +* +* RETURN VALUE +* Pointer to the item in the map with the specified key. If insertion +* was successful, this is the pointer to the item. If an item with the +* specified key already exists in the map, the pointer to that item is +* returned. +* +* NOTES +* Insertion operations may cause the quick map to rebalance. +* +* SEE ALSO +* Quick Map, cl_qmap_remove, cl_map_item_t +*********/ + + +/****f* Component Library: Quick Map/cl_qmap_get/cl_qmap_get_next +* NAME +* cl_qmap_get +* +* DESCRIPTION +* The cl_qmap_get function returns the map item associated with a key. +* +* SYNOPSIS +*/ +CL_EXPORT cl_map_item_t* +cl_qmap_get( + IN const cl_qmap_t* const p_map, + IN const uint64 key ); + +CL_EXPORT cl_map_item_t* +cl_qmap_get_next( + IN const cl_qmap_t* const p_map, + IN const uint64 key ); + +/* +* PARAMETERS +* p_map +* [in] Pointer to a cl_qmap_t structure from which to retrieve the +* item with the specified key. +* +* key +* [in] Key value used to search for the desired map item. +* If Quickmap uses a key compare function, this must be pointer to +* key structure to compare against keys of object in map +* RETURN VALUES +* Pointer to the map item with the desired key value. +* +* Pointer to the map end if there was no item with the desired key value +* stored in the quick map. +* +* NOTES +* cl_qmap_get does not remove the item from the quick map. +* +* SEE ALSO +* Quick Map, cl_qmap_remove +*********/ + +/****f* Component Library: Quick Map/cl_qmap_get_compare +* NAME +* cl_qmap_get_compare +* +* DESCRIPTION +* The cl_qmap_get_compare function returns the map item associated with a key. +* +* SYNOPSIS +*/ +CL_EXPORT cl_map_item_t* +cl_qmap_get_compare( + IN const cl_qmap_t* const p_map, + IN const uint64 key, + IN cl_pfn_qmap_compare_key_t key_compare); +/* +* PARAMETERS +* p_map +* [in] Pointer to a cl_qmap_t structure from which to retrieve the +* item with the specified key. +* +* key +* [in] Key value used to search for the desired map item. +* If Quickmap uses a key compare function, this must be pointer to +* key structure to compare against keys of object in map +* +* key_compare +* [in] function to compare keys. Keys of objects in map will +* be key1 argument. key provided as argument to cl_qmap_get_compare +* will be used as key2 argument. Function must be semantically +* same comparision as key_compare function of map. +* RETURN VALUES +* Pointer to the map item with the desired key value. +* +* Pointer to the map end if there was no item with the desired key value +* stored in the quick map. +* +* NOTES +* cl_qmap_get_compare does not remove the item from the quick map. +* +* This is provided to allow alternate structures for comparison +* +* SEE ALSO +* Quick Map, cl_qmap_remove +*********/ + +/****f* Component Library: Quick Map/cl_qmap_get_item_compare +* NAME +* cl_qmap_get_item_compare +* +* DESCRIPTION +* The cl_qmap_get_item_compare function returns the map item associated with a key. +* +* SYNOPSIS +*/ +CL_EXPORT cl_map_item_t* +cl_qmap_get_item_compare( + IN const cl_qmap_t* const p_map, + IN const uint64 key, + IN cl_pfn_qmap_item_compare_t compare); +/* +* PARAMETERS +* p_map +* [in] Pointer to a cl_qmap_t structure from which to retrieve the +* item with the specified key. +* +* key +* [in] Key value used to search for the desired map item. +* If Quickmap uses a key compare function, this must be pointer to +* key structure to compare against keys of object in map +* +* compare +* [in] function to compare items to key. objects in map will +* be item argument. key provided as argument to cl_qmap_get_item_compare +* will be used as key argument. Function must be semantically +* same comparision as key_compare function of map. +* RETURN VALUES +* Pointer to the map item with the desired key value. +* +* Pointer to the map end if there was no item with the desired key value +* stored in the quick map. +* +* NOTES +* cl_qmap_get_item_compare does not remove the item from the quick map. +* +* This is provided to allow alternate structures for comparison +* +* SEE ALSO +* Quick Map, cl_qmap_remove +*********/ + +/****f* Component Library: Quick Map/cl_qmap_remove_item +* NAME +* cl_qmap_remove_item +* +* DESCRIPTION +* The cl_qmap_remove_item function removes the specified map item +* from a quick map. +* +* SYNOPSIS +*/ +CL_EXPORT void +cl_qmap_remove_item( + IN cl_qmap_t* const p_map, + IN cl_map_item_t* const p_item ); +/* +* PARAMETERS +* p_item +* [in] Pointer to a map item to remove from its quick map. +* +* RETURN VALUES +* This function does not return a value. +* +* In a debug build, cl_qmap_remove_item asserts that the item being removed +* is in the specified map. +* +* NOTES +* Removes the map item pointed to by p_item from its quick map. +* +* SEE ALSO +* Quick Map, cl_qmap_remove, cl_qmap_remove_all, cl_qmap_insert +*********/ + + +/****f* Component Library: Quick Map/cl_qmap_remove +* NAME +* cl_qmap_remove +* +* DESCRIPTION +* The cl_qmap_remove function removes the map item with the specified key +* from a quick map. +* +* SYNOPSIS +*/ +CL_EXPORT cl_map_item_t* +cl_qmap_remove( + IN cl_qmap_t* const p_map, + IN const uint64 key ); +/* +* PARAMETERS +* p_map +* [in] Pointer to a cl_qmap_t structure from which to remove the item +* with the specified key. +* +* key +* [in] Key value used to search for the map item to remove. +* If Quickmap uses a key compare function, this must be pointer to +* key structure to compare against keys of object in map +* +* RETURN VALUES +* Pointer to the removed map item if it was found. +* +* Pointer to the map end if no item with the specified key exists in the +* quick map. +* +* SEE ALSO +* Quick Map, cl_qmap_remove_item, cl_qmap_remove_all, cl_qmap_insert +*********/ + +/****f* Component Library: Quick Map/cl_qmap_remove_compare +* NAME +* cl_qmap_remove_compare +* +* DESCRIPTION +* The cl_qmap_remove_compare function removes the map item with the specified key +* from a quick map. +* +* SYNOPSIS +*/ +CL_EXPORT cl_map_item_t* +cl_qmap_remove_compare( + IN cl_qmap_t* const p_map, + IN const uint64 key, + IN cl_pfn_qmap_compare_key_t key_compare); +/* +* PARAMETERS +* p_map +* [in] Pointer to a cl_qmap_t structure from which to remove the item +* with the specified key. +* +* key +* [in] Key value used to search for the map item to remove. +* If Quickmap uses a key compare function, this must be pointer to +* key structure to compare against keys of object in map +* +* key_compare +* [in] function to compare keys. Keys of objects in map will +* be key1 argument. key provided as argument to cl_qmap_remove_compare +* will be used as key2 argument. Function must be semantically +* same comparision as key_compare function of map. +* RETURN VALUES +* Pointer to the removed map item if it was found. +* +* Pointer to the map end if no item with the specified key exists in the +* quick map. +* +* This is provided to allow alternate structures for comparison +* +* SEE ALSO +* Quick Map, cl_qmap_remove_item, cl_qmap_remove_all, cl_qmap_insert +*********/ + +/****f* Component Library: Quick Map/cl_qmap_remove_all +* NAME +* cl_qmap_remove_all +* +* DESCRIPTION +* The cl_qmap_remove_all function removes all items in a quick map, +* leaving it empty. +* +* SYNOPSIS +*/ +CL_INLINE void +cl_qmap_remove_all( + IN cl_qmap_t* const p_map ) +{ + ASSERT( p_map ); + ASSERT( p_map->state == CL_INITIALIZED ); + + p_map->root.p_left = &p_map->nil_item; + p_map->nil_item.pool_item.list_item.p_next = &p_map->nil_item.pool_item.list_item; + p_map->nil_item.pool_item.list_item.p_prev = &p_map->nil_item.pool_item.list_item; + p_map->count = 0; +} +/* +* PARAMETERS +* p_map +* [in] Pointer to a cl_qmap_t structure to empty. +* +* RETURN VALUES +* This function does not return a value. +* +* SEE ALSO +* Quick Map, cl_qmap_remove, cl_qmap_remove_item +*********/ + + +/****f* Component Library: Quick Map/cl_qmap_merge +* NAME +* cl_qmap_merge +* +* DESCRIPTION +* The cl_qmap_merge function moves all items from one map to another, +* excluding duplicates. +* +* SYNOPSIS +*/ +CL_EXPORT void +cl_qmap_merge( + OUT cl_qmap_t* const p_dest_map, + IN OUT cl_qmap_t* const p_src_map ); +/* +* PARAMETERS +* p_dest_map +* [out] Pointer to a cl_qmap_t structure to which items should be added. +* +* p_src_map +* [in/out] Pointer to a cl_qmap_t structure whose items to add +* to p_dest_map. +* +* RETURN VALUES +* This function does not return a value. +* +* NOTES +* Items are evaluated based on their keys only. +* +* Upon return from cl_qmap_merge, the quick map referenced by p_src_map +* contains all duplicate items. +* +* Only valid if p_dest_map and p_src_map have same key compare function +* (or lack thereof). Undefined results otherwise. +* +* SEE ALSO +* Quick Map, cl_qmap_delta +*********/ + + +/****f* Component Library: Quick Map/cl_qmap_delta +* NAME +* cl_qmap_delta +* +* DESCRIPTION +* The cl_qmap_delta function computes the differences between two maps. +* +* SYNOPSIS +*/ +CL_EXPORT void +cl_qmap_delta( + IN OUT cl_qmap_t* const p_map1, + IN OUT cl_qmap_t* const p_map2, + OUT cl_qmap_t* const p_new, + OUT cl_qmap_t* const p_old ); +/* +* PARAMETERS +* p_map1 +* [in/out] Pointer to the first of two cl_qmap_t structures whose +* differences to compute. +* +* p_map2 +* [in/out] Pointer to the second of two cl_qmap_t structures whose +* differences to compute. +* +* p_new +* [out] Pointer to an empty cl_qmap_t structure that contains the items +* unique to p_map2 upon return from the function. +* +* p_old +* [out] Pointer to an empty cl_qmap_t structure that contains the items +* unique to p_map1 upon return from the function. +* +* RETURN VALUES +* This function does not return a value. +* +* NOTES +* Items are evaluated based on their keys. Items that exist in both +* p_map1 and p_map2 remain in their respective maps. Items that +* exist only p_map1 are moved to p_old. Likewise, items that exist only +* in p_map2 are moved to p_new. This function can be usefull in evaluating +* changes between two maps. +* +* Both maps pointed to by p_new and p_old must be empty on input. This +* requirement removes the possibility of failures. +* +* Only valid if p_dest_map and p_src_map have same key compare function +* (or lack thereof). Undefined results otherwise. +* +* SEE ALSO +* Quick Map, cl_qmap_merge +*********/ + + +/****f* Component Library: Quick Map/cl_qmap_apply_func +* NAME +* cl_qmap_apply_func +* +* DESCRIPTION +* The cl_qmap_apply_func function executes a specified function +* for every item stored in a quick map. +* +* SYNOPSIS +*/ +CL_EXPORT void +cl_qmap_apply_func( + IN const cl_qmap_t* const p_map, + IN cl_pfn_qmap_apply_t pfn_func, + IN const void* const context ); +/* +* PARAMETERS +* p_map +* [in] Pointer to a cl_qmap_t structure. +* +* pfn_func +* [in] Function invoked for every item in the quick map. +* See the cl_pfn_qmap_apply_t function type declaration for details +* about the callback function. +* +* context +* [in] Value to pass to the callback functions to provide context. +* +* RETURN VALUE +* This function does not return a value. +* +* NOTES +* The function provided must not perform any map operations, as these +* would corrupt the quick map. +* +* SEE ALSO +* Quick Map, cl_pfn_qmap_apply_t +*********/ + + +/****i* Component Library: Quick List/__cl_primitive_insert +* NAME +* __cl_primitive_insert +* +* DESCRIPTION +* Add a new item in front of the specified item. This is a low level +* function for use internally by the queuing routines. +* +* SYNOPSIS +*/ +CL_INLINE void +__cl_primitive_insert( + IN cl_list_item_t* const p_list_item, + IN cl_list_item_t* const p_new_item ) +{ + /* ASSERT that a non-null pointer is provided. */ + ASSERT( p_list_item ); + /* ASSERT that a non-null pointer is provided. */ + ASSERT( p_new_item ); + + p_new_item->p_next = p_list_item; + p_new_item->p_prev = p_list_item->p_prev; + p_list_item->p_prev = p_new_item; + p_new_item->p_prev->p_next = p_new_item; +} + +/* +* PARAMETERS +* p_list_item +* [in] Pointer to cl_list_item_t to insert in front of +* +* p_new_item +* [in] Pointer to cl_list_item_t to add +* +* RETURN VALUE +* This function does not return a value. +*********/ + + +/****i* Component Library: Quick List/__cl_primitive_remove +* NAME +* __cl_primitive_remove +* +* DESCRIPTION +* Remove an item from a list. This is a low level routine +* for use internally by the queuing routines. +* +* SYNOPSIS +*/ +CL_INLINE void +__cl_primitive_remove( + IN cl_list_item_t* const p_list_item ) +{ + /* ASSERT that a non-null pointer is provided. */ + ASSERT( p_list_item ); + + /* set the back pointer */ + p_list_item->p_next->p_prev= p_list_item->p_prev; + /* set the next pointer */ + p_list_item->p_prev->p_next= p_list_item->p_next; + + /* if we're debugging, spruce up the pointers to help find bugs */ +#if QMAP_DEBUG + if( p_list_item != p_list_item->p_next ) + { + p_list_item->p_next = NULL; + p_list_item->p_prev = NULL; + } +#endif /* QMAP_DEBUG */ +} + +#ifdef __cplusplus +} +#endif + + +#endif /* _IBA_PUBLIC_IQUICKMAP_H_ */ diff --git a/IbAccess/Common/Public/ireaper.c b/IbAccess/Common/Public/ireaper.c new file mode 100644 index 0000000..5115020 --- /dev/null +++ b/IbAccess/Common/Public/ireaper.c @@ -0,0 +1,173 @@ +/* BEGIN_ICS_COPYRIGHT6 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT6 ****************************************/ + + +#include "ireaper.h" +#include "ilist.h" +#include "ievent.h" +#include "ispinlock.h" +#include "isyscallback.h" +#include "imemory.h" +#include "idebug.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +#define REAPER_TAG MAKE_MEM_TAG(p,e,r,I) +#define REAPER_THRESHOLD 20 // how many to queue before worth reaping + +#define REAPER_DEBUG 0 + +typedef struct _REAPER_OBJ +{ + SPIN_LOCK Lock; + QUICK_LIST Queue; + SYS_CALLBACK_ITEM *SysCallItemp; + ATOMIC_UINT Scheduled; + boolean Initialized; +} REAPER_OBJ; + +// Global sytem reaper object. +static REAPER_OBJ Me; + +void ReaperDrain (void); +void ReaperCallback(IN void *Key, IN void *Context); + +#if defined(__cplusplus) +} +#endif + +// Initialize the reaper +// Called once from the framework that initializes and loads +// the Public library +boolean +ReaperInit (void) +{ +#if REAPER_DEBUG + DbgOut("ReaperInit\n"); +#endif + MemoryClear( &Me, sizeof(REAPER_OBJ) ); + + QListInitState (&Me.Queue); + SpinLockInitState (&Me.Lock); + + if (!QListInit (&Me.Queue)) + { + DbgOut ("Failed to initialize Reaper Queue\n"); + goto failqueue; + } + + if (!SpinLockInit (&Me.Lock)) + { + DbgOut ("Failed to initialize Reaper Lock\n"); + goto faillock; + } + Me.SysCallItemp = SysCallbackGet( &Me ); + if (! Me.SysCallItemp) + { + DbgOut ("Failed to get Reaper Syscallback item\n"); + goto failsyscall; + } + + Me.Initialized = TRUE; + return TRUE; + +failsyscall: + SpinLockDestroy(&Me.Lock); +faillock: + QListDestroy(&Me.Queue); +failqueue: + return FALSE; +} + +void +ReaperDestroy (void) +{ +#if REAPER_DEBUG + DbgOut("ReaperDestroy\n"); +#endif + if (! Me.Initialized) + return; + + ReaperDrain(); + Me.Initialized = FALSE; + + SysCallbackPut(Me.SysCallItemp); + SpinLockDestroy(&Me.Lock); + QListDestroy(&Me.Queue); +} + +void +ReaperDrain (void) +{ + LIST_ITEM *pListItem = NULL; +#if REAPER_DEBUG + DbgOut("ReaperDrain\n"); +#endif + + SpinLockAcquire(&Me.Lock); + while ((pListItem = QListRemoveHead (&Me.Queue)) != NULL) + { + SpinLockRelease(&Me.Lock); + ((REAPER_CALLBACK)(QListObj(pListItem)))(pListItem); + SpinLockAcquire(&Me.Lock); + } + AtomicWrite(&Me.Scheduled, 0); + SpinLockRelease(&Me.Lock); +} + +void +ReaperQueue( + IN LIST_ITEM *pItem, + IN REAPER_CALLBACK Callback + ) +{ + uint32 count; + + QListSetObj(pItem, (void*)Callback); + SpinLockAcquire(&Me.Lock); + QListInsertTail(&Me.Queue, pItem); + count = QListCount(&Me.Queue); +#if REAPER_DEBUG + DbgOut("ReaperQueue: count=%u\n", count); +#endif + SpinLockRelease(&Me.Lock); + if (count >= REAPER_THRESHOLD && AtomicExchange(&Me.Scheduled, 1) == 0) + SysCallbackQueue(Me.SysCallItemp, ReaperCallback, &Me, FALSE); +} + + +void ReaperCallback(IN void *Key, IN void *Context) +{ + ASSERT(Key == (void*)&Me); + ASSERT(Context == (void*)&Me); + + ReaperDrain(); +} diff --git a/IbAccess/Common/Public/ireaper.h b/IbAccess/Common/Public/ireaper.h new file mode 100644 index 0000000..8a80748 --- /dev/null +++ b/IbAccess/Common/Public/ireaper.h @@ -0,0 +1,81 @@ +/* BEGIN_ICS_COPYRIGHT3 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT3 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +#ifndef _IBA_PUBLIC_IREAPER_H_ +#define _IBA_PUBLIC_IREAPER_H_ + +#include "iba/public/datatypes.h" +#include "iba/public/ilist.h" + +/* + * The Reaper helps to Destroy objects. It allows a object to + * schedule itself for later destruction. As such it helps to avoid + * the complex issue of an object needing to destroy itself within its + * own callback, Such as when a timer callback needs to destroy the object + * containing the timer. + * + * In general objects should mostly delete themselves before queueing to the + * Reaper, this will avoid odd races or object existance issues. + * The Reaper callback for the object should focus on destroying simpler + * datatypes (such as timers) and deleting the object. + * The object queued to the reaper should not be queued to any other lists + * + * While on the reaper queue, the LIST_ITEM->m_Object will be changed. + * The callback must use PARENT_STRUCT to get from the pItem supplied + * to the full object. + * + * Internally, the reaper uses the Syscallback mechanism to schedule its + * callbacks. + */ + +#ifdef __cplusplus +extern "C" { +#endif + +typedef void (*REAPER_CALLBACK)( IN LIST_ITEM *pItem ); + +boolean +ReaperInit(void); + +void +ReaperDestroy(void); + +void +ReaperQueue( + IN LIST_ITEM *pItem, + IN REAPER_CALLBACK Callback + ); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* _IBA_PUBLIC_IREAPER_H_ */ diff --git a/IbAccess/Common/Public/ireqmgr.c b/IbAccess/Common/Public/ireqmgr.c new file mode 100644 index 0000000..2a71e77 --- /dev/null +++ b/IbAccess/Common/Public/ireqmgr.c @@ -0,0 +1,349 @@ +/* BEGIN_ICS_COPYRIGHT6 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT6 ****************************************/ + + +#include "ireqmgr.h" +#include "imemory.h" + +// minimum number of objects to allocate +#define REQ_MGR_START_SIZE 10 +// minimum number of objects to grow +#define REQ_MGR_GROW_SIZE 10 + + +/////////////////////////////////////////////////////////////////////////////// +// ReqMgrInitState +// +// Description: +// This function performs basic request manager initialization. This +// function cannot fail. +// +// Inputs: +// pReqMgr - Pointer to a request manager structure. +// +// Outputs: +// None. +// +// Returns: +// None. +// +/////////////////////////////////////////////////////////////////////////////// +void +ReqMgrInitState( + IN REQ_MGR* const pReqMgr ) +{ + ASSERT( pReqMgr ); + + // Clear the structure. + MemoryClear( pReqMgr, sizeof(REQ_MGR) ); + + // Initialize the state of the request queue. + QueueInitState( &pReqMgr->m_RequestQueue ); + + // Initialize the state of the free request stack. + GrowPoolInitState( &pReqMgr->m_RequestPool ); +} + + +/////////////////////////////////////////////////////////////////////////////// +// ReqMgrInit +// +// Description: +// Initializes the request manager for use. +// +// Inputs: +// pReqMgr - Pointer to a request manager. +// pfnGetCount - Pointer to a callback function invoked to +// get the number of available objects. +// GetContext - Context to pass into the pfnGetCount function. +// +// Outputs: +// None. +// +// Returns: +// FSUCCESS - the request manager was successfully initialized. +// FINSUFFICIENT_MEMORY - there was not enough memory to initialize the +// request manager. +// +/////////////////////////////////////////////////////////////////////////////// +FSTATUS +ReqMgrInit( + IN REQ_MGR* const pReqMgr, + IN REQMGR_GET_COUNT_FUNC pfnGetCount, + IN void* const GetContext ) +{ + FSTATUS Status; + + ASSERT( pReqMgr ); + ASSERT( pfnGetCount ); + + // Initialize the state of the request manager, in case it hasn't yet + // been done. + ReqMgrInitState( pReqMgr ); + + if( !QueueInit( &pReqMgr->m_RequestQueue, 1 ) ) + return( FINSUFFICIENT_MEMORY ); + + Status = GrowPoolInit( &pReqMgr->m_RequestPool, REQ_MGR_START_SIZE, + sizeof(REQUEST_OBJECT), REQ_MGR_GROW_SIZE, NULL, NULL, NULL, NULL ); + + if( Status != FSUCCESS ) + return( Status ); + + // Store callback information for the count function. + pReqMgr->m_pfnGetCount = pfnGetCount; + pReqMgr->m_GetContext = GetContext; + + pReqMgr->m_Initialized = TRUE; + + return( FSUCCESS ); +} + + +/////////////////////////////////////////////////////////////////////////////// +// ReqMgrDestroy +// +// Description: +// Destroys a request manager. +// +// Inputs: +// pReqMgr - Pointer to a request manager. +// +// Outputs: +// None. +// +// Returns: +// None. +// +/////////////////////////////////////////////////////////////////////////////// +void +ReqMgrDestroy( + IN REQ_MGR* const pReqMgr ) +{ + REQUEST_OBJECT *pReq; + + ASSERT( pReqMgr ); + + // Return all requests to the grow pool. + if( pReqMgr->m_Initialized ) + { + while( NULL != (pReq = (REQUEST_OBJECT*)QueueRemove( &pReqMgr->m_RequestQueue )) ) + GrowPoolPut( &pReqMgr->m_RequestPool, pReq ); + } + + QueueDestroy( &pReqMgr->m_RequestQueue ); + GrowPoolDestroy( &pReqMgr->m_RequestPool ); + + pReqMgr->m_Initialized = FALSE; +} + + +/////////////////////////////////////////////////////////////////////////////// +// ReqMgrGet +// +// Description: +// Retrieves a number of objects, either synchronously or asynchronously. +// +// Inputs: +// pReqMgr - Pointer to a request manager. +// pCount - Contains the number of objects to retrieve. +// ReqType - Type of get operation. Can be ReqGetSync, ReqGetAsync, or +// ReqGetAsyncPartialOk. +// pfnCallback - Pointer to a callback function to store for the request. +// Context1 - First of two contexts passed to the request callback. +// Context2 - Second of two contexts passed to the request callback. +// +// Outputs: +// pCount - Contains the number of objects available. +// +// Returns: +// FSUCCESS - The request callback has been invoked with elements to +// satisfy the request. If the request allowed partial +// completions, all elements are guaranteed to have been returned. +// FPENDING - The request could not complete in it's entirety. If the +// request allowed partial completion, some elements may have been +// already returned. +// FINSUFFICIENT_RESOURCES - There were not enough objects for the request to +// succeed. +// FINSUFFICIENT_MEMORY - There was not enough memory to process the +// request (including queuing the request). +// +/////////////////////////////////////////////////////////////////////////////// +FSTATUS +ReqMgrGet( + IN REQ_MGR* const pReqMgr, + IN OUT uint32* const pCount, + IN const REQ_MGR_TYPE ReqType, + IN REQ_CALLBACK pfnCallback, + IN void* const Context1, + IN void* const Context2 ) +{ + uint32 AvailableCount; + uint32 Count; + REQUEST_OBJECT *pRequest; + + ASSERT( pReqMgr ); + ASSERT( pReqMgr->m_Initialized ); + ASSERT( pCount ); + ASSERT( *pCount ); + + // Get the number of available objects in the grow pool. + AvailableCount = pReqMgr->m_pfnGetCount( pReqMgr->m_GetContext ); + + // Check to see if there is nothing on the queue, and there are + // enough items to satisfy the whole request. + if( !QueueCount( &pReqMgr->m_RequestQueue ) && *pCount <= AvailableCount ) + return( FSUCCESS ); + + if( ReqType == ReqGetSync ) + return( FINSUFFICIENT_RESOURCES ); + + // We need a request object to place on the request queue. + pRequest = (REQUEST_OBJECT*)GrowPoolGet( &pReqMgr->m_RequestPool ); + + if( !pRequest ) + return( FINSUFFICIENT_MEMORY ); + + // We can return the available number of objects but we still need + // to queue a request for the remainder. + if( ReqType == ReqGetAsyncPartialOk && + !QueueCount( &pReqMgr->m_RequestQueue ) ) + { + Count = *pCount - AvailableCount; + *pCount = AvailableCount; + pRequest->PartialOk = TRUE; + } + else + { + // We cannot return any objects. We queue a request for all of them. + Count = *pCount; + *pCount = 0; + pRequest->PartialOk = FALSE; + } + + // Set the request fields and enqueue it. + pRequest->pfnCallback = pfnCallback; + pRequest->Context1 = Context1; + pRequest->Context2 = Context2; + pRequest->Count = Count; + + if( !QueueInsert( &pReqMgr->m_RequestQueue, pRequest ) ) + { + // We could not queue the request. Return the request to the pool. + GrowPoolPut( &pReqMgr->m_RequestPool, pRequest ); + return( FINSUFFICIENT_MEMORY ); + } + + return( FPENDING ); +} + + +/////////////////////////////////////////////////////////////////////////////// +// ReqMgrResume +// +// Description: +// Continues (and completes if possible) a pending request for objects, +// if any. +// +// Inputs: +// pReqMgr - Pointer to a request manager. +// +// Outputs: +// pCount - Number of objects available for a resuming request. +// ppfnCallback - Contains the callback function pointer as provided +// in the ReqMgrGet function. +// pContext1 - Contains the Context1 value for the resuming request, +// as provided in the ReqMgrGet function. +// pContext2 - Contains the Context2 value for the resuming request, +// as provided in the ReqMgrGet function. +// +// Returns: +// FSUCCESS - A request was completed. +// FNOT_DONE - There were no pending requests. +// FINSUFFICIENT_RESOURCES - There were not enough resources to complete a +// pending request. +// FPENDING - A request was continued, but not completed. +// +// Remarks: +// At most one requset is resumed. +// +/////////////////////////////////////////////////////////////////////////////// +FSTATUS +ReqMgrResume( + IN REQ_MGR* const pReqMgr, + OUT uint32* const pCount, + OUT REQ_CALLBACK* const ppfnCallback, + OUT void** const pContext1, + OUT void** const pContext2 ) +{ + uint32 AvailableCount; + REQUEST_OBJECT *pQueuedRequest; + + ASSERT( pReqMgr ); + ASSERT( pReqMgr->m_Initialized ); + + // If no requests are pending, there's nothing to return. + if( !QueueCount( &pReqMgr->m_RequestQueue ) ) + return FNOT_DONE; + + // Get the item at the head of the request queue, but do not remove it yet. + pQueuedRequest = (REQUEST_OBJECT*) + QueueGetHead( &pReqMgr->m_RequestQueue ); + // If no requests are pending, there's nothing to return. + if (pQueuedRequest == NULL) + return FNOT_DONE; + + *ppfnCallback = pQueuedRequest->pfnCallback; + *pContext1 = pQueuedRequest->Context1; + *pContext2 = pQueuedRequest->Context2; + + AvailableCount = pReqMgr->m_pfnGetCount( pReqMgr->m_GetContext ); + + // See if the request can be fulfilled. + if( pQueuedRequest->Count > AvailableCount ) + { + if( !pQueuedRequest->PartialOk ) + return( FINSUFFICIENT_RESOURCES ); + + pQueuedRequest->Count -= AvailableCount; + + *pCount = AvailableCount; + return( FPENDING ); + } + + *pCount = pQueuedRequest->Count; + + // The entire request can be met. Remove it from the request queue + // and return. + QueueRemove( &pReqMgr->m_RequestQueue ); + + // Return the internal request object to the free stack. + GrowPoolPut( &pReqMgr->m_RequestPool, pQueuedRequest ); + return( FSUCCESS ); +} diff --git a/IbAccess/Common/Public/ireqmgr.h b/IbAccess/Common/Public/ireqmgr.h new file mode 100644 index 0000000..3469704 --- /dev/null +++ b/IbAccess/Common/Public/ireqmgr.h @@ -0,0 +1,282 @@ +/* BEGIN_ICS_COPYRIGHT3 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT3 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + + +#ifndef _IBA_PUBLIC_IREQ_MGR_H_ +#define _IBA_PUBLIC_IREQ_MGR_H_ + +#include "iba/public/datatypes.h" +#include "iba/public/igrowpool.h" +#include "iba/public/ilist.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/**************************************************************************** + * Generic request callback type, used to queue requests. + * + ****************************************************************************/ +typedef void +(*REQ_CALLBACK)( void ); + + +/**************************************************************************** + * This structure is used to manage queuing requests for objects. + * + ****************************************************************************/ +typedef struct _REQUEST_OBJECT +{ + uint32 Count; /* Number of items requested. */ + boolean PartialOk; /* Is it okay to return some of the items. */ + REQ_CALLBACK pfnCallback; /* Notification routine when completed. */ + void *Context1; /* Callback context information. */ + void *Context2; /* Callback context information. */ + +} REQUEST_OBJECT; + + +/**************************************************************************** + * The REQ_MGR_GET_TYPE enumarated type is used to specify the type of + * request being performed when calling ReqMgrGet(). + * + ****************************************************************************/ +typedef enum _REQ_MGR_TYPE +{ + ReqGetSync, + ReqGetAsync, + ReqGetAsyncPartialOk + +} REQ_MGR_TYPE; + + +/**************************************************************************** + * GET_AVAILABLE_COUNT + * + * Description: + * Function type declaration for the object count callback function invoked by + * the request manager to retrieve the number of objects available. + * + * Inputs: + * Context - User specified context. + * + * Outputs: + * None. + * + * Returns: + * Number of available objects. + * + ****************************************************************************/ +typedef uint32 (*REQMGR_GET_COUNT_FUNC)( + IN void *Context ); + + +/**************************************************************************** + * REQ_MGR object. + * + ****************************************************************************/ +typedef struct _REQ_MGR +{ + /* Pointer to the count callback function. */ + REQMGR_GET_COUNT_FUNC m_pfnGetCount; /* DO NOT USE!! */ + /* Context to pass as single parameter to count callback. */ + void *m_GetContext; /* DO NOT USE!! */ + + /* Offset into each object where the chain pointers are located. */ + uint32 m_NextPtrOffset; /* DO NOT USE!! */ + uint32 m_PrevPtrOffset; /* DO NOT USE!! */ + + /* Pending requests for elements. */ + QUEUE m_RequestQueue; /* DO NOT USE!! */ + + /* Requests are dynamically allocated and added to the stack. */ + GROW_POOL m_RequestPool; /* DO NOT USE!! */ + + boolean m_Initialized; /* DO NOT USE!! */ + +} REQ_MGR; + + +/**************************************************************************** + * ReqMgrInitState + * + * Description: + * This function performs basic request manager initialization. This + * function cannot fail. + * + * Inputs: + * pReqMgr - Pointer to a request manager structure. + * + * Outputs: + * None. + * + * Returns: + * None. + * + ****************************************************************************/ +void +ReqMgrInitState( + IN REQ_MGR* const pReqMgr ); + + +/**************************************************************************** + * ReqMgrInit + * + * Description: + * Initializes the request manager for use. + * + * Inputs: + * pReqMgr - Pointer to a request manager. + * pfnGetCount - Pointer to a callback function invoked to + * get the number of available objects. + * GetContext - Context to pass into the pfnGetCount function. + * + * Outputs: + * None. + * + * Returns: + * FSUCCESS - the request manager was successfully initialized. + * FINSUFFICIENT_MEMORY - there was not enough memory to initialize the + * request manager. + * + ****************************************************************************/ +FSTATUS +ReqMgrInit( + IN REQ_MGR* const pReqMgr, + IN REQMGR_GET_COUNT_FUNC pfnGetCount, + IN void* const GetContext ); + + +/**************************************************************************** + * ReqMgrDestroy + * + * Description: + * Destroys a request manager. + * + * Inputs: + * pReqMgr - Pointer to a request manager. + * + * Outputs: + * None. + * + * Returns: + * None. + * + ****************************************************************************/ +void +ReqMgrDestroy( + IN REQ_MGR* const pReqMgr ); + + +/**************************************************************************** + * ReqMgrGet + * + * Description: + * Retrieves a number of objects, either synchronously or asynchronously. + * + * Inputs: + * pReqMgr - Pointer to a request manager. + * pCount - Contains the number of objects to retrieve. + * ReqType - Type of get operation. Can be ReqGetSync, ReqGetAsync, or + * ReqGetAsyncPartialOk. + * pfnCallback - Pointer to a callback function to store for the request. + * Context1 - First of two contexts. + * Context2 - Second of two contexts. + * + * Outputs: + * pCount - Contains the number of objects available. + * + * Returns: + * FSUCCESS - The request callback has been invoked with elements to + * satisfy the request. If the request allowed partial + * completions, all elements are guaranteed to have been returned. + * FPENDING - The request could not complete in it's entirety. If the + * request allowed partial completion, some elements may have been + * already returned. + * FINSUFFICIENT_RESOURCES - There were not enough objects for the request to + * succeed. + * FINSUFFICIENT_MEMORY - There was not enough memory to process the + * request (including queuing the request). + * + ****************************************************************************/ +FSTATUS +ReqMgrGet( + IN REQ_MGR* const pReqMgr, + IN OUT uint32* const pCount, + IN const REQ_MGR_TYPE ReqType, + IN REQ_CALLBACK pfnCallback, + IN void* const Context1, + IN void* const Context2 ); + + +/**************************************************************************** + * ReqMgrResume + * + * Description: + * Continues (and completes if possible) a pending request for objects, + * if any. + * + * Inputs: + * pReqMgr - Pointer to a request manager. + * + * Outputs: + * pCount - Number of objects available for a resuming request. + * pContext1 - Contains the Context1 value for the resuming request, + * as provided in the ReqMgrGet function. + * pContext2 - Contains the Context2 value for the resuming request, + * as provided in the ReqMgrGet function. + * + * Returns: + * FSUCCESS - A request was completed. + * FNOT_DONE - There were no pending requests. + * FINSUFFICIENT_RESOURCES - There were not enough resources to complete a + * pending request. + * FPENDING - A request was continued, but not completed. + * + * Remarks: + * At most one requset is resumed. + * + ****************************************************************************/ +FSTATUS +ReqMgrResume( + IN REQ_MGR* const pReqMgr, + OUT uint32* const pCount, + OUT REQ_CALLBACK* const ppfnCallback, + OUT void** const pContext1, + OUT void** const pContext2 ); + + +#ifdef __cplusplus +} +#endif + +#endif /* _IBA_PUBLIC_IREQ_MGR_H_ */ diff --git a/IbAccess/Common/Public/iresmap.c b/IbAccess/Common/Public/iresmap.c new file mode 100644 index 0000000..866fd4b --- /dev/null +++ b/IbAccess/Common/Public/iresmap.c @@ -0,0 +1,398 @@ +/* BEGIN_ICS_COPYRIGHT6 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT6 ****************************************/ + + +#include "iresmap.h" + +/////////////////////////////////////////////////////////////////////////////// +// resource map access methods +// These methods are an attempt to follow the functionality of the C++ STL. +// The names and behavior are obviously not exact matches, but hopefully, +// close enough to make those familiar with the ANSI standard comfortable. +/////////////////////////////////////////////////////////////////////////////// + + +/////////////////////////////////////////////////////////////////////////////// +// ResMapInitState +// +// Description: +// This function performs basic resource map initialization. This function cannot +// fail. +// +// Inputs: +// pResMap - Pointer to resource map +// +// Outputs: +// None. +// +// Returns: +// None. +// +/////////////////////////////////////////////////////////////////////////////// +void +ResMapInitState( + IN RESOURCE_MAP* const pResMap ) +{ + ASSERT( pResMap ); + + BitVectorInitState(&pResMap->m_ResList); + pResMap->m_FirstFree = 0; + pResMap->m_NextFree = 0; + pResMap->m_NumReserved = 0; + pResMap->m_NumAllocated = 0; +} + + + +/////////////////////////////////////////////////////////////////////////////// +// ResMapInit +// +// Description: +// This function initializes the resource map. New bits in the resource map are +// initialized to 0. +// +// Inputs: +// pResMap - Pointer to resource map +// InitialSize - prefered initial number of bits +// GrowSize - number of bits to allocate when incrementally growing +// the resource map (will round up to multiple of processor +// word size) +// MaxSize - maximum number of bits in resource map, 0 -> no limit +// IsPageable - TRUE indicates the resource map should use pageable memory +// FALSE indicates the resource map should used non-paged memory +// +// Outputs: +// None. +// +// Returns: +// FSUCCESS +// FINSUFFICIENT_MEMORY - resource map is initialized to zero size +// +/////////////////////////////////////////////////////////////////////////////// +FSTATUS +ResMapInit( + IN RESOURCE_MAP* const pResMap, + IN const uint32 InitialSize, + IN const uint32 GrowSize, + IN const uint32 MaxSize, + IN boolean IsPageable ) +{ + ASSERT( pResMap ); + + ResMapInitState( pResMap ); + return (BitVectorInit(&pResMap->m_ResList, InitialSize, GrowSize, MaxSize, + IsPageable)); +} + + +/////////////////////////////////////////////////////////////////////////////// +// ResMapDestroy +// +// Description: +// This function deallocates all allocated memory associated with the resource map. +// The resource map is left initialized to zero size. This function does not fail. +// +// Inputs: +// pResMap - Pointer to resource map +// +// Outputs: +// None. +// +// Returns: +// None. +// +/////////////////////////////////////////////////////////////////////////////// +void +ResMapDestroy( + IN RESOURCE_MAP* const pResMap ) +{ + ASSERT( pResMap ); + + BitVectorDestroy(&pResMap->m_ResList); + pResMap->m_FirstFree = 0; + pResMap->m_NextFree = 0; + pResMap->m_NumReserved = 0; + pResMap->m_NumAllocated = 0; + + return; +} + + +/**************************************************************************** + * ResMapAvailable + * + * Description: + * This function indicates if the resource map has any available resources + * + * Inputs: + * pResMap - Pointer to resource map + * + * Outputs: + * None. + * + * Returns: + * TRUE - resources are available + * FALSE - no resources are available + * + ****************************************************************************/ +boolean +ResMapAvailable( + IN const RESOURCE_MAP* const pResMap ) +{ + uint32 max_size; + + DEBUG_ASSERT( pResMap ); + max_size = BitVectorGetMaxSize(&pResMap->m_ResList); + /* max_size ==0 -> no limit */ + return (! max_size + || pResMap->m_NumReserved + pResMap->m_NumAllocated < max_size); +} + +/////////////////////////////////////////////////////////////////////////////// +// ResMapIsAllocated +// +// Description: +// This function returns the status of the specified resource +// Range checking is performed. Provides constant time access. +// +// Inputs: +// pResMap - Pointer to resource map. +// Number - Number of resource to check +// +// Outputs: +// +// Returns: +// TRUE - allocated, FALSE - free or Number out of range +// +/////////////////////////////////////////////////////////////////////////////// +boolean +ResMapIsAllocated( + IN const RESOURCE_MAP* const pResMap, + IN const uint32 Number ) +{ + ASSERT( pResMap ); // Other asserts are in ResMapGet + + // Range check + if( Number >= BitVectorGetSize(&pResMap->m_ResList)) + { + return FALSE; // beyond what we have allocated/tracked + } + + return _ResMapGetIsAllocated( pResMap, Number ); +} + + +/////////////////////////////////////////////////////////////////////////////// +// ResMapReserve +// +// Description: +// Reserves a specific resource number +// +// Inputs: +// pResMap - pointer to resource map to iterate through +// Number - resource number to reserve +// +// Outputs: +// +// Returns: +// FSUCCESS - Number now marked as allocated +// FINSUFFICIENT_RESOURCES - Number already allocated +// FINSUFFICIENT_MEMORY - unable to grow map +// +/////////////////////////////////////////////////////////////////////////////// +FSTATUS +ResMapReserve( + IN RESOURCE_MAP* const pResMap, + IN uint32 Number ) +{ + FSTATUS Status; + + // check Number is not already allocated or reserved + if (BitVectorGetSize(&pResMap->m_ResList) > Number) + { + if (BitVectorGet(&pResMap->m_ResList, Number)) + { + return FINSUFFICIENT_RESOURCES; + } + } + Status = BitVectorSet(&pResMap->m_ResList, Number, 1); + if (Status == FSUCCESS) + { + // Leave FirstFree and NextFree alone, won't hurt much + ++(pResMap->m_NumReserved); + } + return Status; +} + + +/////////////////////////////////////////////////////////////////////////////// +// ResMapAllocate +// +// Description: +// Locates a free resource Number +// +// Inputs: +// pResMap - pointer to resource map to iterate through +// pNumber - where to store allocated resource number +// +// Outputs: +// *pNumber - resource allocated +// +// Returns: +// FSUCCESS - *pNumber is Resource number (now marked as allocated) +// FINSUFFICIENT_RESOURCES - no free resources +// FINSUFFICIENT_MEMORY - unable to grow map +// +/////////////////////////////////////////////////////////////////////////////// +FSTATUS +ResMapAllocate( + IN RESOURCE_MAP* const pResMap, + OUT uint32 *pNumber ) +{ + uint32 Size; + uint32 Number; + FSTATUS Status; + + ASSERT(pResMap); + + // no use doing all this searching if no resources available + if (! ResMapAvailable(pResMap)) + return FINSUFFICIENT_RESOURCES; + + Size = BitVectorGetSize(&pResMap->m_ResList); + // search from m_NextFree to end of present size + Number = BitVectorFindFromIndex(&pResMap->m_ResList, FALSE, pResMap->m_NextFree); + if (Number < Size) + { + Status = BitVectorSet(&pResMap->m_ResList, Number, 1); + if (Status != FSUCCESS) + { + return Status; + } + goto found; + } + // search from start of list + if (pResMap->m_FirstFree < pResMap->m_NextFree) + { + // search from m_FirstFree to m_NextFree + Number = BitVectorFindRange(&pResMap->m_ResList, FALSE, pResMap->m_FirstFree, pResMap->m_NextFree); + if (Number == pResMap->m_NextFree) Number = Size; + } else { + // expand to grow list + Number = Size; + } + Status = BitVectorSet(&pResMap->m_ResList, Number, 1); + if (Status != FSUCCESS) + { + return Status; + } + pResMap->m_FirstFree = Number+1; +found: + pResMap->m_NextFree = Number+1; + ++(pResMap->m_NumAllocated); + *pNumber = Number; + return FSUCCESS; +} + +/////////////////////////////////////////////////////////////////////////////// +// ResMapFree +// +// Description: +// This function sets the given resource number to be free. +// should not be used to free reserved entries +// +// Inputs: +// pResMap - Pointer to resource map. +// Number - Number of resource to free +// +// Outputs: +// None. +// +// Returns: +// FSUCCESS +// FINVALID_STATE - resource was already free +// +/////////////////////////////////////////////////////////////////////////////// +FSTATUS +ResMapFree( + IN RESOURCE_MAP* const pResMap, + IN const uint32 Number) +{ + FSTATUS Status; + + if (Number >= BitVectorGetSize(&pResMap->m_ResList) + || BitVectorGet(&pResMap->m_ResList, Number) == 0) + { + return FINVALID_STATE; + } + DEBUG_ASSERT(pResMap->m_NumAllocated); + + Status = BitVectorSet(&pResMap->m_ResList, Number, 0); + ASSERT(Status == FSUCCESS); + if (Number < pResMap->m_FirstFree) + pResMap->m_FirstFree = Number; + --(pResMap->m_NumAllocated); + return Status; +} + + +/////////////////////////////////////////////////////////////////////////////// +// ResMapApplyFuncAllocated +// +// Description: +// This function calls the user supplied function for each allocated resource +// in the resource map, starting from the beginning of the array. +// +// The called function has the form: +// void ApplyFunc( uint32 Number, uint8 IsAllocated, void *Context ); +// where: +// Number = resourcse number +// IsAllocated = 1/TRUE->allocated, 0/FALSE->free +// Context = user supplied context +// +// Inputs: +// pResMap - pointer to resource map to iterate through +// pfnCallback - callback called for each non-NULL bit +// Context - context to pass to callback function +// +// Outputs: +// None. +// +// Returns: +// None. +// +/////////////////////////////////////////////////////////////////////////////// +void +ResMapApplyFuncAllocated( + IN const RESOURCE_MAP* const pResMap, + IN RESMAP_APPLY_FUNC pfnCallback, + IN void* const Context) +{ + BitVectorApplyFunc(&pResMap->m_ResList, pfnCallback, Context); +} diff --git a/IbAccess/Common/Public/iresmap.h b/IbAccess/Common/Public/iresmap.h new file mode 100644 index 0000000..d1e5110 --- /dev/null +++ b/IbAccess/Common/Public/iresmap.h @@ -0,0 +1,434 @@ +/* BEGIN_ICS_COPYRIGHT3 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT3 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + + +#ifndef _IBA_PUBLIC_IRESMAP_H_ +#define _IBA_PUBLIC_IRESMAP_H_ + +#include "iba/public/datatypes.h" +#include "iba/public/ibitvector.h" + + +#ifdef __cplusplus +extern "C" +{ +#endif + +/**************************************************************************** + * + * Resource Map definition + * + * A Resourcse Map tracks the available resources in a BitVector and + * assists in allocating, freeing and manipulating the resources + * allocation attempts to use an expanding blocks approach + * The BitVector is not grown until all resources in its scope are + * allocated. When allocation is performed it moves increasing through + * the BitVector until the end is reached, then it re-uses entries from + * the start. This will tend to recycle the resources and avoid re-use + * of recently used resources (which can be good for security but bad + * for cache hit rates). + * + * Resource numbers start at 0. + */ + +typedef BITVEC_APPLY_FUNC RESMAP_APPLY_FUNC; + + +/* The resource map structure is allocated by the user and is opaque to them */ +typedef struct _RESOURCE_MAP +{ + /* all fields below are private, use accessor functions to */ + /* manipulate this structure */ + BIT_VECTOR m_ResList; + uint32 m_FirstFree; /* lowest which may be free */ + uint32 m_NextFree; /* where to start search */ + uint32 m_NumReserved; /* number of reserved entries */ + uint32 m_NumAllocated; /* number of allocated entries */ +} RESOURCE_MAP; + + +/**************************************************************************** + * resource map access methods + * These methods are an attempt to follow the functionality of the C++ STL. + * The names and behavior are obviously not exact matches, but hopefully, + * close enough to make those familiar with the ANSI standard comfortable. + ****************************************************************************/ + + +/**************************************************************************** + * ResMapInitState + * + * Description: + * This function performs basic resource map initialization. + * This function cannot fail. + * + * Inputs: + * pResMap - Pointer to resource map + * + * Outputs: + * None. + * + * Returns: + * None. + * + ****************************************************************************/ +void +ResMapInitState( + IN RESOURCE_MAP* const pResMap ); + + +/**************************************************************************** + * ResMapInit + * + * Description: + * This function initializes the resource map. + * all entries are initialized as free. + * + * Inputs: + * pResMap - Pointer to resource map + * InitialSize - prefered initial number of resources + * GrowSize - number of resources to increasing scope + * allocate when incrementally growing the resource map + * (will round up to multiple of 32 or 64) + * MaxSize - maximum number of resources to track, 0 -> no limit + * IsPageable - TRUE indicates the resource map should use pageable memory + * FALSE indicates the resource map should used non-paged memory + * + * Outputs: + * None. + * + * Returns: + * FSUCCESS + * FINSUFFICIENT_MEMORY - resource map is initialized to zero size + * + ****************************************************************************/ +FSTATUS +ResMapInit( + IN RESOURCE_MAP* const pResMap, + IN const uint32 InitialSize, + IN const uint32 GrowSize, + IN const uint32 MaxSize, + IN boolean IsPageable ); + + +/**************************************************************************** + * ResMapDestroy + * + * Description: + * This function deallocates all allocated memory associated with the resource map. + * The resource map is left initialized to zero size. + * This function does not fail. + * + * Inputs: + * pResMap - Pointer to resource map + * + * Outputs: + * None. + * + * Returns: + * None. + * + ****************************************************************************/ +void +ResMapDestroy( + IN RESOURCE_MAP* const pResMap ); + + +/**************************************************************************** + * ResMapGetSize + * + * Description: + * This function returns the current size of the resource map. + * This function cannot fail. + * This indicates the range of resources being tracked presently + * + * Inputs: + * pResMap - Pointer to resource map + * + * Outputs: + * None. + * + * Returns: + * present Size, in resources, of the resource map. + * + ****************************************************************************/ +static __inline uint32 +ResMapGetSize( + IN const RESOURCE_MAP* const pResMap ) +{ + DEBUG_ASSERT( pResMap ); + return BitVectorGetSize(&pResMap->m_ResList); +} + +/**************************************************************************** + * ResMapGetNumReserved + * + * Description: + * This function returns the number of reserved entries in the resource map. + * This function cannot fail. + * + * Inputs: + * pResMap - Pointer to resource map + * + * Outputs: + * None. + * + * Returns: + * present number of reserved resources in the resource map. + * + ****************************************************************************/ +static __inline uint32 +ResMapGetNumReserved( + IN const RESOURCE_MAP* const pResMap ) +{ + DEBUG_ASSERT( pResMap ); + return pResMap->m_NumReserved; +} + + +/**************************************************************************** + * ResMapGetNumAllocated + * + * Description: + * This function returns the number of allocated entries in the resource map. + * This function cannot fail. + * returned count does not include reserved resources. + * + * Inputs: + * pResMap - Pointer to resource map + * + * Outputs: + * None. + * + * Returns: + * present number of allocated resources in the resource map. + * + ****************************************************************************/ +static __inline uint32 +ResMapGetNumAllocated( + IN const RESOURCE_MAP* const pResMap ) +{ + DEBUG_ASSERT( pResMap ); + return pResMap->m_NumAllocated; +} + + +/**************************************************************************** + * ResMapAvailable + * + * Description: + * This function indicates if the resource map has any available resources + * + * Inputs: + * pResMap - Pointer to resource map + * + * Outputs: + * None. + * + * Returns: + * TRUE - resources are available + * FALSE - no resources are available + * + ****************************************************************************/ +boolean +ResMapAvailable( + IN const RESOURCE_MAP* const pResMap ); + +/**************************************************************************** + * ResMapGetIsAllocated + * + * Description: + * This function returns the status of the specified resource + * Range checking is NOT performed. Provides constant time access. + * Internal function, not for general use. + * + * Inputs: + * pResMap - Pointer to resource map. + * Number - Number of resource to check + * + * Outputs: + * FALSE->free, TRUE-> allocated + * + * Returns: + * None. + * + * Notes: + * prefered interface is ResMapIsAllocated + * + ****************************************************************************/ +static __inline boolean +_ResMapGetIsAllocated( + IN const RESOURCE_MAP* const pResMap, + IN const uint32 Number ) +{ + DEBUG_ASSERT(pResMap); + return ( BitVectorGet(&pResMap->m_ResList, Number) != 0); +} + + +/**************************************************************************** + * ResMapIsAllocated + * + * Description: + * This function returns the status of the specified resource + * Range checking is performed. Provides constant time access. + * + * Inputs: + * pResMap - Pointer to resource map. + * Number - Number of resource to check + * + * Outputs: + * + * Returns: + * TRUE - allocated, FALSE - free or Number out of range + * + ****************************************************************************/ +boolean +ResMapIsAllocated( + IN const RESOURCE_MAP* const pResMap, + IN const uint32 Number ); + + + +/**************************************************************************** + * ResMapReserve + * + * Description: + * Reserves a specific resource number + * + * Inputs: + * pResMap - pointer to resource map to iterate through + * Number - resource number to reserve + * + * Outputs: + * + * Returns: + * FSUCCESS - Number now marked as allocated + * FINSUFFICIENT_RESOURCES - Number already allocated + * FINSUFFICIENT_MEMORY - unable to grow map + * + ****************************************************************************/ +FSTATUS +ResMapReserve( + IN RESOURCE_MAP* const pResMap, + IN uint32 Number ); + + + +/**************************************************************************** + * ResMapAllocate + * + * Description: + * Locates a free resource Number + * + * Inputs: + * pResMap - pointer to resource map to iterate through + * pNumber - where to store allocated resource number + * + * Outputs: + * *pNumber - resource allocated + * + * Returns: + * FSUCCESS - *pNumber is Resource number (now marked as allocated) + * FINSUFFICIENT_RESOURCES - no free resources + * FINSUFFICIENT_MEMORY - unable to grow map + * + ****************************************************************************/ +FSTATUS +ResMapAllocate( + IN RESOURCE_MAP* const pResMap, + OUT uint32 *pNumber ); + + + +/**************************************************************************** + * ResMapFree + * + * Description: + * This function sets the given resource number to be free. + * should not be used to free reserved entries + * + * Inputs: + * pResMap - Pointer to resource map. + * Number - Number of resource to free + * + * Outputs: + * None. + * + * Returns: + * FSUCCESS + * FINVALID_STATE - resource was already free + * + ****************************************************************************/ +FSTATUS +ResMapFree( + IN RESOURCE_MAP* const pResMap, + IN const uint32 Number); + + + +/**************************************************************************** + * ResMapApplyFuncAllocated + * + * Description: + * This function calls the user supplied function for each allocated resource + * in the resource map, starting from the beginning of the array. + * + * The called function has the form: + * void ApplyFunc( uint32 Number, uint8 IsAllocated, void *Context ); + * where: + * Number = resourcse number + * IsAllocated = 1/TRUE->allocated, 0/FALSE->free + * Context = user supplied context + * + * Inputs: + * pResMap - pointer to resource map to iterate through + * pfnCallback - callback called for each non-NULL bit + * Context - context to pass to callback function + * + * Outputs: + * None. + * + * Returns: + * None. + * + ****************************************************************************/ +void +ResMapApplyFuncAllocated( + IN const RESOURCE_MAP* const pResMap, + IN RESMAP_APPLY_FUNC pfnCallback, + IN void* const Context); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* _IBA_PUBLIC_IRESMAP_H_ */ diff --git a/IbAccess/Common/Public/iresmgr.c b/IbAccess/Common/Public/iresmgr.c new file mode 100644 index 0000000..f520698 --- /dev/null +++ b/IbAccess/Common/Public/iresmgr.c @@ -0,0 +1,521 @@ +/* BEGIN_ICS_COPYRIGHT6 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT6 ****************************************/ + +#include "iresmgr.h" +#include "imemory.h" + + +#define RES_MGR_TAG MAKE_MEM_TAG( i, r, e, s ) + + +// Private function declaration used only internally to the free pool. +uint32 +FreePoolGetAvailableCount( + IN const FREE_POOL* const pFreePool, + IN const uint32 Count, + IN const boolean PartialOk ); + + +void +FreePoolInitState( + IN FREE_POOL* const pFreePool ) +{ + StackInitState( &pFreePool->m_Stack ); + StackInitState( &pFreePool->m_FreeRequestStack ); + QueueInitState( &pFreePool->m_RequestQueue ); + pFreePool->m_Initialized = FALSE; +} + + +boolean +FreePoolInit( + IN FREE_POOL* const pFreePool, + IN const uint32 MinItems ) +{ + uint32 RequestCount; + + ASSERT( pFreePool ); + + FreePoolInitState( pFreePool ); + if( !StackInit( &pFreePool->m_Stack, MinItems ) ) + return FALSE; + + // Assume that we may have requests for 25% more resources than the + // minimum number of objects that we support. + if( !(RequestCount = (MinItems >> 2)) ) + RequestCount = 1; + + if( !QueueInit( &pFreePool->m_RequestQueue, RequestCount ) ) + { + FreePoolDestroy( pFreePool ); + return FALSE; + } + + if( !StackInit( &pFreePool->m_FreeRequestStack, RequestCount ) ) + { + FreePoolDestroy( pFreePool ); + return FALSE; + } + + pFreePool->m_Initialized = TRUE; + return TRUE; +} + + +void +FreePoolDestroy( + IN FREE_POOL* const pFreePool ) +{ + REQUEST_OBJECT *pRequest; + + ASSERT( pFreePool ); + + if( pFreePool->m_Initialized ) + { + // Deallocate any request objects on the request queue. + while( NULL != (pRequest = (REQUEST_OBJECT*) QueueRemove( &pFreePool->m_RequestQueue )) ) + { + MemoryDeallocate( pRequest ); + } + + // Deallocate any request objects on the free request stack. + while( NULL != (pRequest = (REQUEST_OBJECT*) StackPop( &pFreePool->m_FreeRequestStack )) ) + { + MemoryDeallocate( pRequest ); + } + } + + StackDestroy( &pFreePool->m_FreeRequestStack ); + QueueDestroy( &pFreePool->m_RequestQueue ); + StackDestroy( &pFreePool->m_Stack ); + pFreePool->m_Initialized = FALSE; +} + + +// +// Return the number of items that can be given by the free pool to +// complete the specified request. Users of the free pool must cooperate +// to ensure concurrency. +// +uint32 +FreePoolCheck( + IN const FREE_POOL* const pFreePool, + IN const uint32 Count, + IN const boolean PartialOk ) +{ + ASSERT( pFreePool && Count && pFreePool->m_Initialized ); + + // If anything is on the request queue, we cannot fulfill this request + // ahead of it. + if( QueueCount( &pFreePool->m_RequestQueue ) ) + return 0; + + return FreePoolGetAvailableCount( pFreePool, Count, PartialOk ); +} + + +// +// Return the number of elements that may be removed from the free pool. +// This assumes that other checking has been done to verify that elements +// may be successfully removed (e.g. no queued requests) +// +uint32 +FreePoolGetAvailableCount( + IN const FREE_POOL* const pFreePool, + IN const uint32 Count, + IN const boolean PartialOk ) +{ + // See if we have enough items to complete the entire request. + if ( StackCount( &pFreePool->m_Stack ) >= Count ) + return Count; + + // We can't complete the entire request, but we may be able to complete + // part of the request if the user will accept a partial completion. + // Return the number of items on the free pool. + if ( PartialOk ) + return StackCount( &pFreePool->m_Stack ); + else + return 0; +} + + +// +// Adds an object to the free pool. +// +boolean +FreePoolPut( + IN FREE_POOL* const pFreePool, + IN void* const pObject ) +{ + ASSERT( pFreePool && pFreePool->m_Initialized ); + return StackPush( &pFreePool->m_Stack, pObject ); +} + + +// +// Adds an array of objects to the free pool. +// +boolean +FreePoolPutArray( + IN FREE_POOL* const pFreePool, + IN void* const pArray, + IN const uint32 ItemCount, + IN const uint32 ItemSize ) +{ + ASSERT( pFreePool && pFreePool->m_Initialized ); + return StackPushArray( &pFreePool->m_Stack, pArray, + ItemCount, ItemSize ); +} + + +// +// Removes an item from the free list. +// +void* +FreePoolGet( + IN FREE_POOL* const pFreePool ) +{ + ASSERT( pFreePool && pFreePool->m_Initialized ); + return StackPop( &pFreePool->m_Stack ); +} + + +// +// Queue a request for items from the free pool when they become available. +// The request is queued without checking for available objects. +// +boolean +FreePoolQueueRequest( + IN FREE_POOL* const pFreePool, + IN const uint32 Count, + IN const boolean PartialOk, + IN REQ_CALLBACK Callback, + IN void* const Context1, + IN void* const Context2 ) +{ + REQUEST_OBJECT *pRequest; + + ASSERT( pFreePool && pFreePool->m_Initialized ); + + // We need a request object to place on the request list. Try first to + // get one from the free request list. If none are available, then we + // need to allocate a new one. + if( !(pRequest = (REQUEST_OBJECT*) + StackPop( &pFreePool->m_FreeRequestStack )) ) + { + // We need to allocate a new request object. + pRequest = (REQUEST_OBJECT*)MemoryAllocate( sizeof(REQUEST_OBJECT), + FALSE, RES_MGR_TAG ); + if( !pRequest ) + return FALSE; + } + + // Copy the request and enqueue it. + pRequest->Count = Count; + pRequest->PartialOk = PartialOk; + pRequest->pfnCallback = Callback; + pRequest->Context1 = Context1; + pRequest->Context2 = Context2; + if( QueueInsert( &pFreePool->m_RequestQueue, pRequest ) ) + { + return TRUE; + } + else + { + // We could not queue the request. Delete the request object and + // return. + if( !StackPush( &pFreePool->m_FreeRequestStack, pRequest ) ) + MemoryDeallocate( pRequest ); + return FALSE; + } +} + + +// +// Checks the request list to see if the first request can be completed. +// If it can, information about the request is returned. If the request +// can only be partially completed, the portion that can be completed is +// returned, and a requests is left queued for the remainder. +// +boolean +FreePoolDequeueRequest( + IN FREE_POOL* const pFreePool, + OUT REQUEST_OBJECT* const pRequest ) +{ + REQUEST_OBJECT *pQueuedRequest; + uint32 ItemCount; + + ASSERT( pFreePool && pRequest && pFreePool->m_Initialized ); + + // If no requests are pending, there's nothing to return. + if( !QueueCount( &pFreePool->m_RequestQueue ) ) + return FALSE; + + // Get the item at the head of the request queue, but do not remove it yet. + pQueuedRequest = (REQUEST_OBJECT*) + QueueGetHead( &pFreePool->m_RequestQueue ); + // If no requests are pending, there's nothing to return. + if (pQueuedRequest == NULL) + return FALSE; + + ItemCount = FreePoolGetAvailableCount( pFreePool, + pQueuedRequest->Count, pQueuedRequest->PartialOk ); + // See if the request can be fulfilled. + if( !ItemCount ) + return FALSE; + + // Return the part of the request than can be fulfilled immediately. + MemoryCopy( pRequest, pQueuedRequest, sizeof( REQUEST_OBJECT ) ); + if ( pQueuedRequest->Count <= ItemCount ) + { + // The entire request can be met. Remove it from the request queue + // and return. + QueueRemove( &pFreePool->m_RequestQueue ); + // Return the internal request object to the free stack. + if( !StackPush( &pFreePool->m_FreeRequestStack, + pQueuedRequest ) ) + { + MemoryDeallocate( pQueuedRequest ); + } + } + else + { + // We are fulfilling part of the request. Return the number of items that + // may be removed from the free pool for the partial completion. + pRequest->Count = ItemCount; + + // Leave the queued request but update it to reflect the partial completion. + pQueuedRequest->Count -= ItemCount; + } + return TRUE; +} + + +// +// Return the number of items currently in the free pool. +// +uint32 +FreePoolFreeCount( + IN const FREE_POOL* const pFreePool ) +{ + return StackCount( &pFreePool->m_Stack ); +} + + +// +// Initialize every object in the resource manager with the specified +// function. +// +void +FreePoolApplyFunc( + IN const FREE_POOL* const pFreePool, + IN LIST_APPLY_FUNC Func, + IN void* const Context ) +{ + ASSERT( pFreePool && pFreePool->m_Initialized ); + + // Make sure a function was provided. + if( !Func ) + return; + + // Invoke the function for each element in the free pool. + StackApplyFunc( &pFreePool->m_Stack, Func, Context ); +} + + +// +// Asynchronous Resource Manager +// + +// +// Allocate the requested resources and add them to the free pool. +// If a byte alignment is specified, the alignment offset into each object +// allocated is aligned on the specified byte boundary. +// +void +ResMgrInitState( + IN RES_MGR* const pResMgr ) +{ + FreePoolInitState( &pResMgr->m_FreePool ); + pResMgr->m_pArray = NULL; +} + +boolean +ResMgrInit( + IN RES_MGR* const pResMgr, + IN const uint32 ObjectCount, + IN uint32 ObjectSize, + IN const uint32 ByteAlignment, + IN const uint32 AlignmentOffset ) +{ + void *pObject; + + ASSERT( pResMgr && ObjectCount && ObjectSize && + AlignmentOffset < ObjectSize ); + + ResMgrInitState( pResMgr ); + + // Initialize the free pool. + if( !FreePoolInit( &pResMgr->m_FreePool, ObjectCount ) ) + return FALSE; + + // Allocate the array of objects. This function will change the object + // size to reflect any added padding. + if( !(pResMgr->m_pArray = MemoryAllocateObjectArray( ObjectCount, + &ObjectSize, ByteAlignment, AlignmentOffset, FALSE, RES_MGR_TAG, + &pObject, &pResMgr->m_ArraySize )) ) + { + ResMgrDestroy( pResMgr ); + return FALSE; + } + + // Place all elements of the array in the free pool. + pResMgr->m_ItemCount = ObjectCount; + + // Add the objects to the free pool. + if( !FreePoolPutArray( &pResMgr->m_FreePool, pObject, + ObjectCount, ObjectSize ) ) + { + // We could not add the objects to the free pool. + ResMgrDestroy( pResMgr ); + return FALSE; + } + + return TRUE; +} + + +// +// Destroy a resource manager. +// +void +ResMgrDestroy( + IN RES_MGR* const pResMgr ) +{ + ASSERT( pResMgr ); + + if( pResMgr->m_pArray ) + MemoryDeallocate( pResMgr->m_pArray ); + + FreePoolDestroy( &pResMgr->m_FreePool ); +} + + + +// +// Call the free pool for all other operations. +// +boolean +ResMgrPut( + IN RES_MGR* const pResMgr, + IN void* const pObject ) +{ + ASSERT( pResMgr ); + + return FreePoolPut( &pResMgr->m_FreePool, pObject ); + +} + +boolean +ResMgrPutArray( + IN RES_MGR* const pResMgr, + IN void* const pArray, + IN const uint32 ItemCount, + IN const uint32 ItemSize ) +{ + ASSERT( pResMgr ); + + return FreePoolPutArray( &pResMgr->m_FreePool, pArray, + ItemCount, ItemSize ); +} + +void* +ResMgrGet( + IN RES_MGR* const pResMgr) +{ + ASSERT( pResMgr ); + + return FreePoolGet( &pResMgr->m_FreePool ); +} + +uint32 +ResMgrCheck( + IN const RES_MGR* const pResMgr, + IN const uint32 Count, + IN const boolean PartialOk ) +{ + ASSERT( pResMgr ); + + return FreePoolCheck( &pResMgr->m_FreePool, Count, PartialOk ); +} + +boolean +ResMgrQueueRequest( + IN RES_MGR* const pResMgr, + IN const uint32 Count, + IN const boolean PartialOk, + IN REQ_CALLBACK Callback, + IN void* const Context1, + IN void* const Context2 ) +{ + ASSERT( pResMgr ); + + return FreePoolQueueRequest( &pResMgr->m_FreePool, Count, + PartialOk, Callback, Context1, Context2 ); +} + +boolean +ResMgrDequeueRequest( + IN RES_MGR* const pResMgr, + OUT REQUEST_OBJECT* const pRequest ) +{ + ASSERT( pResMgr ); + + return FreePoolDequeueRequest( &pResMgr->m_FreePool, pRequest ); +} + +uint32 +ResMgrFreeCount( + IN const RES_MGR* const pResMgr ) +{ + ASSERT( pResMgr ); + + return FreePoolFreeCount( &pResMgr->m_FreePool ); +} + +void +ResMgrApplyFunc( + IN const RES_MGR* const pResMgr, + IN LIST_APPLY_FUNC Func, + IN void *Context ) +{ + ASSERT( pResMgr ); + + FreePoolApplyFunc( &pResMgr->m_FreePool, Func, Context ); +} diff --git a/IbAccess/Common/Public/iresmgr.h b/IbAccess/Common/Public/iresmgr.h new file mode 100644 index 0000000..b604b2e --- /dev/null +++ b/IbAccess/Common/Public/iresmgr.h @@ -0,0 +1,253 @@ +/* BEGIN_ICS_COPYRIGHT3 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT3 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +#ifndef _IBA_PUBLIC_IRESMGR_H_ +#define _IBA_PUBLIC_IRESMGR_H_ + +#include "iba/public/ilist.h" +#include "iba/public/ireqmgr.h" +#include "iba/public/iobjmgr.h" + + +#ifdef __cplusplus +extern "C" +{ +#endif + + + +/* + * The free pool object provides an asynchronous free pool of available objects. + * If no objects are available, it queues a request. A free pool manages + * resources but does not create them. + */ + + +/* + * Free pool object definition. + */ +typedef struct _FREE_POOL +{ + /* Available elements in free pool. */ + STACK m_Stack; /* DO NOT USE!! */ + + /* Pending requests for elements. */ + QUEUE m_RequestQueue; /* DO NOT USE!! */ + + /* Requests are dynamically allocated and added to the stack. */ + STACK m_FreeRequestStack; /* DO NOT USE!! */ + + boolean m_Initialized; /* DO NOT USE!! */ + +} FREE_POOL; + + + +/* + * Function declarations. + */ + +/* Create a new free pool. */ +void +FreePoolInitState( + IN FREE_POOL* const pFreePool ); + +boolean +FreePoolInit( + IN FREE_POOL* const pFreePool, + IN const uint32 MinItems ); + +void +FreePoolDestroy( + IN FREE_POOL* const pFreePool ); + +/* Get/free resources. */ +boolean +FreePoolPut( + IN FREE_POOL* const pFreePool, + IN void* const pObject ); + +boolean +FreePoolPutArray( + IN FREE_POOL* const pFreePool, + IN void* const pArray, + IN const uint32 ItemCount, + IN const uint32 ItemSize ); + +void* +FreePoolGet( + IN FREE_POOL* const pFreePool); + +/* Check the free pool to see if a request can be completed, queue + * a request, or get a request that can be completed. + */ +uint32 +FreePoolCheck( + IN const FREE_POOL* const pFreePool, + IN const uint32 Count, + IN const boolean PartialOk ); + +boolean +FreePoolQueueRequest( + IN FREE_POOL* const pFreePool, + IN const uint32 Count, + IN const boolean PartialOk, + IN REQ_CALLBACK pfnCallback, + IN void* const Context1, + IN void* const Context2 ); + +boolean +FreePoolDequeueRequest( + IN FREE_POOL* const pFreePool, + OUT REQUEST_OBJECT* const pRequest ); + +/* Return number of objects in the free pool. */ +uint32 +FreePoolFreeCount( + IN const FREE_POOL* const pFreePool ); + +/* Initialize every object in the resource manager with the specified + * function. + */ +void +FreePoolApplyFunc( + IN const FREE_POOL* const pFreePool, + IN LIST_APPLY_FUNC pfnFunc, + IN void* const Context ); + + + +/* + * The resource manager object manages the allocation, deallocation, and + * distribution of objects. + */ + + +/* + * Resource manager object definition. + */ +typedef struct _RES_MGR +{ + /* Private data structure used by the resource manager object. */ + /* Users should not access these variables directly. */ + FREE_POOL m_FreePool; /* DO NOT USE!! */ + + /* These variables are exposed to the user to allow the memory to be */ + /* pinned, registered, etc. */ + uint32 m_ItemCount; /* DO NOT USE!! */ + void *m_pArray; /* DO NOT USE!! */ + uint32 m_ArraySize; /* DO NOT USE!! */ + +} RES_MGR; + + +/* + * Function declarations. + */ + +/* Create a new resource manager. */ + +/* Initializes, Allocates/frees the resources dynamically. */ +void +ResMgrInitState( + IN RES_MGR* const pResMgr ); + +boolean +ResMgrInit( + IN RES_MGR* const pResMgr, + IN const uint32 ObjectCount, + IN uint32 ObjectSize, + IN const uint32 ByteAlignment, + IN const uint32 AlignmentOffset ); + +void +ResMgrDestroy( + IN RES_MGR* const pResMgr ); + +/* Get/free resources. */ +boolean +ResMgrPut( + IN RES_MGR* const pResMgr, + IN void* const pObject ); + +boolean +ResMgrPutArray( + IN RES_MGR* const pResMgr, + IN void* const pArray, + IN const uint32 ItemCount, + IN const uint32 ItemSize ); + +void* +ResMgrGet( + IN RES_MGR* const pResMgr ); + +/* Check the free pool to see if a request can be completed, queue + * a request, or get a request that can be completed. + */ +uint32 +ResMgrCheck( + IN const RES_MGR* const pResMgr, + IN const uint32 Count, + IN const boolean PartialOk ); + +boolean +ResMgrQueueRequest( + IN RES_MGR* const pResMgr, + IN const uint32 Count, + IN const boolean PartialOk, + IN REQ_CALLBACK Callback, + IN void* const Context1, + IN void* const Context2 ); + +boolean +ResMgrDequeueRequest( + IN RES_MGR* const pResMgr, + OUT REQUEST_OBJECT* const pRequest ); + +/* Return number of objects in the free pool. */ +uint32 +ResMgrFreeCount( + IN const RES_MGR* const pResMgr ); + +/* Initialize every object in the resource manager with the specified + * function. + */ +void +ResMgrApplyFunc( + IN const RES_MGR* const pResMgr, + IN LIST_APPLY_FUNC Func, + IN void* const Context ); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* _IBA_PUBLIC_IRESMGR_H_ */ diff --git a/IbAccess/Common/Public/isemaphore.h b/IbAccess/Common/Public/isemaphore.h new file mode 100644 index 0000000..a59a6ad --- /dev/null +++ b/IbAccess/Common/Public/isemaphore.h @@ -0,0 +1,194 @@ +/* BEGIN_ICS_COPYRIGHT1 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT1 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +#ifndef _IBA_PUBLIC_ISEMAPHORE_H_ +#define _IBA_PUBLIC_ISEMAPHORE_H_ + +/* Indicates that waiting on an event should never timeout */ +#define SEMA_NO_TIMEOUT ((int32)0xFFFFFFFF) + +#include "iba/public/isemaphore_osd.h" + + +#ifdef __cplusplus +extern "C" +{ +#endif + +/**************************************************************************** + * SemaInitState + * + * Description: + * Initializes the state of a semaphore. + * + * Inputs: + * pSema - Pointer to a semaphore object. + * + * Outputs: + * None + * + * Returns: + * None + * + ****************************************************************************/ +void +SemaInitState( + IN SEMAPHORE* const pSema ); + + +/**************************************************************************** + * SemaInit + * + * Description: + * Initializes the semaphore. This function performs all initialization. + * + * Inputs: + * pSema - Pointer to a semaphore object + * MaxCount - Maximum number of wait operations that the semaphore can + * satisfy before blocking callers. + * + * Outputs: + * None + * + * Returns: + * FSUCCESS + * FERROR - Initialization failed. + * + ****************************************************************************/ +FSTATUS +SemaInit( + IN SEMAPHORE* const pSema, + IN const int32 MaxCount ); + + +/**************************************************************************** + * SemaDestroy + * + * Description: + * Destroys the semaphore. + * + * Inputs: + * pSema - Pointer to a semaphore object + * + * Outputs: + * None + * + * Returns: + * None + * + ****************************************************************************/ +void +SemaDestroy( + IN SEMAPHORE* const pSema ); + + +/**************************************************************************** + * SemaAcquire + * + * Description: + * Acquires a semaphore. This call blocks for the specified interval if the + * semaphore cannot be acquired immediately. A wait of SEMA_NO_TIMEOUT + * will never timeout. + * + * Inputs: + * pSema - Pointer to a semaphore object + * wait_us - Time, in microseconds, to wait for the semaphore. + * + * Outputs: + * None + * + * Returns: + * FSUCCESS - The samphore was successfully acquired. + * FTIMEOUT - The operation timed out. + * + ****************************************************************************/ +FSTATUS +SemaAcquire( + IN SEMAPHORE* const pSema, + IN const int32 wait_us ); + + +/**************************************************************************** + * SemaRelease + * + * Description: + * Releases a semaphore. This will free one blocking waiter, if any. + * + * Inputs: + * pSema - Pointer to a semaphore object + * + * Outputs: + * None + * + * Returns: + * None + * + ****************************************************************************/ +void +SemaRelease( + IN SEMAPHORE* const pSema ); + + +/**************************************************************************** + * SemaGetNative + * + * Description: + * Return the platform-native pointer to the semaphore object. This allows + * using the semaphore with platform specific wait operations. + * + * Inputs: + * pSema - Pointer to a semaphore object + * + * Outputs: + * None + * + * Returns: + * Pointer to the platform native semaphore. + * + ****************************************************************************/ +#ifdef _INDIRECT_NATIVE_SEMA /* set in isemaphore_osd.h */ +void* +SemaGetNative( + IN const SEMAPHORE* const pSema ); +#else +static __inline void* +SemaGetNative( + IN const SEMAPHORE* const pSema ) +{ + return (void*)pSema; +} +#endif /* _INDIRECT_NATIVE_EVENT */ + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* _IBA_PUBLIC_ISEMAPHORE_H_ */ diff --git a/IbAccess/Common/Public/ispinlock.h b/IbAccess/Common/Public/ispinlock.h new file mode 100644 index 0000000..fb12002 --- /dev/null +++ b/IbAccess/Common/Public/ispinlock.h @@ -0,0 +1,388 @@ +/* BEGIN_ICS_COPYRIGHT3 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT3 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + + +#ifndef _IBA_PUBLIC_ISPINLOCK_H_ +#define _IBA_PUBLIC_ISPINLOCK_H_ + + +#include "iba/public/ispinlock_osd.h" + + +#ifdef __cplusplus +extern "C" +{ +#endif +/* + * Function declarations. + */ + +/*--------------------------------------------------------------------------- + * Simple spin locks. These are callable in interrupts, callbacks + * and processes. The caller must not sleep/wait while holding the lock + */ +/* Initialize a spinlock before its use. */ +void +SpinLockInitState( + IN SPIN_LOCK *pSpinLock ); + +boolean +SpinLockInit( + IN SPIN_LOCK *pSpinLock ); + +/* Destroy the spinlock when through using it. */ +void +SpinLockDestroy( + IN SPIN_LOCK *pSpinLock ); + +/* Wait on and acquire a spinlock. */ +void +SpinLockAcquire( + IN SPIN_LOCK *pSpinLock ); + +/* Wait on and acquire a spinlock. User must be running at dispatch/interrupt. */ +void +SpinLockFastAcquire( + IN SPIN_LOCK *pSpinLock ); + +/* Release the spinlock. */ +void +SpinLockRelease( + IN SPIN_LOCK *pSpinLock ); + +/* Release a spinlock acquired through the fast acquire. */ +void +SpinLockFastRelease( + IN SPIN_LOCK *pSpinLock ); + +/*--------------------------------------------------------------------------- + * Read/Write spin locks. These are callable in interrupts, callbacks + * and processes. The caller must not sleep/wait while holding the lock + * Initialize a spinlock before its use. + * These can be slightly more efficient than Simple Spin Locks. + * locking for Read will allow multiple readers in at once but no writers. + * locking for Write allows no one else in (readers nor writers). + * A process must be consistent that its Acquire (Read/Write and Fast) matches + * its Release. + */ +void +SpinRwLockInitState( + IN SPIN_RW_LOCK *pSpinRwLock ); + +boolean +SpinRwLockInit( + IN SPIN_RW_LOCK *pSpinRwLock ); + +/* Destroy the spinlock when through using it. */ +void +SpinRwLockDestroy( + IN SPIN_RW_LOCK *pSpinRwLock ); + +/* Wait on and acquire a spinlock. */ +void +SpinRwLockAcquireRead( + IN SPIN_RW_LOCK *pSpinRwLock ); +void +SpinRwLockAcquireWrite( + IN SPIN_RW_LOCK *pSpinRwLock ); + + +/* Wait on and acquire a spinlock. User must be running at dispatch/interrupt. */ +void +SpinRwLockFastAcquireRead( + IN SPIN_RW_LOCK *pSpinRwLock ); +void +SpinRwLockFastAcquireWrite( + IN SPIN_RW_LOCK *pSpinRwLock ); + +/* Release the spinlock. */ +void +SpinRwLockReleaseRead( + IN SPIN_RW_LOCK *pSpinRwLock ); +void +SpinRwLockReleaseWrite( + IN SPIN_RW_LOCK *pSpinRwLock ); + +/* Release a spinlock acquired through the fast acquire. */ +void +SpinRwLockFastReleaseRead( + IN SPIN_RW_LOCK *pSpinRwLock ); +void +SpinRwLockFastReleaseWrite( + IN SPIN_RW_LOCK *pSpinRwLock ); + +/*--------------------------------------------------------------------------- + * Memory Barriers. + * + * Some CPU Architectures permit out of order access to memory. + * For code within a spinlock this is not an issue because on such + * CPUs, the spin lock code will implement a memory barrier. + * However when accessing PCI memory (or CPU memory shared with hardware) + * or when 2 Threads synchronize themselves without using spinlocks + * (such as when ring buffers are used), Memory Barriers are needed to + * force the ordering of memory access. + * + * IoBarriers protect memory shared with IO hardware. + * CpuBarriers protect memory shared between threads/CPUs. + * + * A Read barrier ensures all Reads before the Barrier complete prior to + * performing any Reads after the barrier + * for example: + * if (p->valid) { + * XBarrierRead(); // make sure reads below don't happen before + * // valid is set + * read rest of *p + * } + * + * A Write barrier ensures all Writes before the Barrier complete prior to + * performing any Writes after the barrier + * for example: + * put data at *p + * XBarrierWrite(); // make sure p written before we set valid + * p->valid = 1; + * OR + * put WQE on QP + * XBarrierWrite(); // make sure WQE written before set valid + * wqe->valid = 1; + * XBarrierWrite(); // make sure WQE marked as valid before ring + * *doorbell = RING; + * + * A Read/Write barrier insures all Reads and Writes before the Barrier complete + * prior to performing any Reads or Writes after the barrier. + * + * These are interrupt callable. + */ +static _inline void IoBarrierRead(void); +static _inline void IoBarrierWrite(void); +static _inline void IoBarrierReadWrite(void); + +static _inline void CpuBarrierRead(void); +static _inline void CpuBarrierWrite(void); +static _inline void CpuBarrierReadWrite(void); + +/* This can help optimize cache operation by beginning the memory read before + * the data is actually needed + */ +static _inline void CpuPrefetch(void *addr); + +/*--------------------------------------------------------------------------- + * Atomic operations for reading, writing, incrementing and decrementing + * ATOMIC_UINT is opaque system specific container for an atomically + * accessible value. + * This container will contain at least 24 bits of value, but may be larger than + * 32 bits. + * The API allows 32 bit values to be added, subtracted and exchanged with this + * value. If the value goes negative or exceeds 24 bits behaviour is undefined. + * + * functions declared in ispinlock_osd.h so they can be inline when appropriate + */ + +/*uint32 + *AtomicRead( + * IN ATOMIC_UINT *pValue ); + */ + +/*void + *AtomicWrite( + * IN ATOMIC_UINT *pValue, IN uint32 newValue ); + */ + +/*uint32 + *AtomicExchange( + * IN ATOMIC_UINT *pValue, IN uint32 newValue ); + */ + +/* atomically performs: + * if (*pValue == oldValue) { + * *pValue = newValue; return TRUE; + * } else + * return FALSE; + *boolean + *AtomicCompareStore( + * IN ATOMIC_UINT *pValue, IN uint32 oldValue, IN uint32 newValue ); + */ + +/*uint32 + *AtomicIncrement( + * IN ATOMIC_UINT *pValue ); + */ + +/*void + *AtomicIncrementVoid( + * IN ATOMIC_UINT *pValue ); + */ + +/*uint32 + *AtomicDecrement( + * IN ATOMIC_UINT *pValue ); + */ + +/*void + *AtomicDecrementVoid( + * IN ATOMIC_UINT *pValue ); + */ + +/*uint32 + *AtomicAdd( + * IN ATOMIC_UINT *pValue, uint32 add ); + */ + +/*void + *AtomicAddVoid( + * IN ATOMIC_UINT *pValue, uint32 add ); + */ + +/*uint32 + *AtomicSubtract( + * IN ATOMIC_UINT *pValue, uint32 sub ); + */ + +/*void + *AtomicSubtractVoid( + * IN ATOMIC_UINT *pValue, uint32 sub ); + */ + +#ifdef ATOMIC_TEST + +#include "iba/public/idebug.h" + +/* simple single threaded test to verify Atomics */ +static __inline void +AtomicRunTest(void) +{ + ATOMIC_UINT a; + + MsgOut("Running Atomic Tests\n"); + AtomicWrite(&a, 5); + if (AtomicRead(&a) != 5) + { MsgOut("AtomicRead Failed\n"); goto fail; } + if (AtomicIncrement(&a) != 6) + { MsgOut("AtomicIncrement Failed\n"); goto fail; } + AtomicIncrementVoid(&a); + if (AtomicRead(&a) != 7) + { MsgOut("AtomicIncrementVoid Failed\n"); goto fail; } + if (AtomicCompareStore(&a, 5, 7)) + { MsgOut("AtomicCompareStore Failed\n"); goto fail; } + if (! AtomicCompareStore(&a, 7, 0)) + { MsgOut("AtomicCompareStore Failed\n"); goto fail; } + if (AtomicExchange(&a, 1)) + { MsgOut("AtomicExchange 1 Failed\n"); goto fail; } + if (AtomicRead(&a) != 1) + { MsgOut("AtomicExchange 1 read Failed\n"); goto fail; } + if (! AtomicExchange(&a, 0)) + { MsgOut("AtomicExchange 0 Failed\n"); goto fail; } + if (AtomicRead(&a) != 0) + { MsgOut("AtomicExchange 0 read Failed\n"); goto fail; } + AtomicWrite(&a, 7); + if (AtomicDecrement(&a) != 6) + { MsgOut("AtomicDecrement Failed\n"); goto fail; } + AtomicDecrementVoid(&a); + if (AtomicRead(&a) != 5) + { MsgOut("AtomicDecrementVoid Failed\n"); goto fail; } + if (AtomicAdd(&a, 3) != 8) + { MsgOut("AtomicAdd Failed\n"); goto fail; } + AtomicAddVoid(&a, 4); + if (AtomicRead(&a) != 12) + { MsgOut("AtomicAddVoid Failed\n"); goto fail; } + if (AtomicSubtract(&a, 3) != 9) + { MsgOut("AtomicSubtract Failed\n"); goto fail; } + AtomicSubtractVoid(&a, 4); + if (AtomicRead(&a) != 5) + { MsgOut("AtomicSubtractVoid Failed\n"); goto fail; } + MsgOut("Atomic tests passed\n"); + return; +fail: + MsgOut("Atomic tests failed\n"); + return; +} +#endif + +#ifdef __cplusplus +} /* extern "C" */ + +/* RAI object to help create and release spin locks */ +class AutoSpinLock +{ +public: + AutoSpinLock( SPIN_LOCK *pLock) + { + m_lock = pLock; + SpinLockAcquire(m_lock); + } + + ~AutoSpinLock() + { + SpinLockRelease(m_lock); + } + +private: + SPIN_LOCK *m_lock; +}; + +/* RAI objects to help create and release RW spin locks */ +class AutoRwSpinLockRead +{ +public: + AutoRwSpinLockRead( SPIN_RW_LOCK *pLock) + { + m_lock = pLock; + SpinRwLockAcquireRead(m_lock); + } + + ~AutoRwSpinLockRead() + { + SpinRwLockReleaseRead(m_lock); + } + +private: + SPIN_RW_LOCK *m_lock; +}; + +class AutoRwSpinLockWrite +{ +public: + AutoRwSpinLockWrite( SPIN_RW_LOCK *pLock) + { + m_lock = pLock; + SpinRwLockAcquireWrite(m_lock); + } + + ~AutoRwSpinLockWrite() + { + SpinRwLockReleaseWrite(m_lock); + } + +private: + SPIN_RW_LOCK *m_lock; +}; +#endif /* __cplusplus */ + +#endif /* _IBA_PUBLIC_ISPINLOCK_H_ */ diff --git a/IbAccess/Common/Public/isyscallback.c b/IbAccess/Common/Public/isyscallback.c new file mode 100644 index 0000000..85a2b7b --- /dev/null +++ b/IbAccess/Common/Public/isyscallback.c @@ -0,0 +1,314 @@ +/* BEGIN_ICS_COPYRIGHT6 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT6 ****************************************/ + + +#include "isyscallback.h" +#include "ithread.h" +#include "ithreadpool.h" +#include "ispinlock.h" +#include "imemory.h" +#include "idebug.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +#define SYS_CALLBACK_TAG MAKE_MEM_TAG(b,c,s,I) + +#define SYS_CALLBACK_DEBUG 0 + +#define MIN_SYSCALLBACK_THREADS (15) // Low water mark +//#define MAX_SYSCALLBACK_THREADS (10) // High water mark +// BUGBUG TBD - implement growing thread pool based on demand and queue depths +#define GROW_SYSCALLBACK_COUNT (1) // Grow limit + +typedef struct _SYS_CALLBACK_OBJ +{ + LOCKED_QUICK_LIST LowPriQueue; + LOCKED_QUICK_LIST HighPriQueue; + THREAD_POOL ThreadPool; + boolean Initialized; + uint32 ThreadCount; + +} SYS_CALLBACK_OBJ; + +// Global sytem callback object. +static SYS_CALLBACK_OBJ Me; + +void _SysCallbackWrapper (IN void *Context); + +#if defined(__cplusplus) +} +#endif + +static +void +_SysCallbackCleanup (void) +{ +#if SYS_CALLBACK_DEBUG + DbgOut("SysCallbackCleanup\n"); +#endif + + // Destroy the thread pool. This blocks until all threads have exited. + ThreadPoolDestroy (&Me.ThreadPool); + + // Cleanup any pending callbacks. + if( Me.Initialized ) + { + uint32 Count = 0; + LIST_ITEM *pListItem = NULL; + + // TBD if there is something left on our queue, perhaps we should + // Invoke the user callback: + //SYS_CALLBACK_ITEM *pItem = (SYS_CALLBACK_ITEM*)QListObj(pListItem); + //ASSERT (pItem); + //pItem->Callback (pItem->Key, pItem->Context); + + while ((pListItem = LQListRemoveHead (&Me.HighPriQueue)) != NULL) + { + SysCallbackPut( (SYS_CALLBACK_ITEM*)QListObj(pListItem) ); + Count++; + } + if (Count) + DbgOut (" %d High Priority Items Destroyed \n", Count); + + Count = 0; + while ((pListItem = LQListRemoveHead (&Me.LowPriQueue)) != NULL) + { + SysCallbackPut( (SYS_CALLBACK_ITEM*)QListObj(pListItem) ); + Count++; + } + + if (Count) + DbgOut (" %d Low Priority Items Destroyed \n", Count); + } + + LQListDestroy (&Me.LowPriQueue); + LQListDestroy (&Me.HighPriQueue); + + Me.Initialized = FALSE; +} + +// +// Called once from the framework that initializes and loads +// the Public library +// + +// Initialize the System callback module. +boolean +SysCallbackInit (void) +{ +#if SYS_CALLBACK_DEBUG + DbgOut("SysCallbackInit\n"); +#endif + MemoryClear( &Me, sizeof(SYS_CALLBACK_OBJ) ); + + LQListInitState (&Me.HighPriQueue); + LQListInitState (&Me.LowPriQueue); + ThreadPoolInitState (&Me.ThreadPool); + + Me.ThreadCount = MIN_SYSCALLBACK_THREADS; + + if (!LQListInit (&Me.HighPriQueue)) + { + DbgOut ("Failed to initialize Syscallback High Pri Queue \n"); + goto fail; + } + + if (!LQListInit (&Me.LowPriQueue)) + { + DbgOut ("Failed to initialize Syscallback Low Pri Queue \n"); + goto faillow; + } + + if( !ThreadPoolCreate (&Me.ThreadPool, Me.ThreadCount, "SysCallb", + THREAD_PRI_HIGH, _SysCallbackWrapper, NULL) ) + { + DbgOut ("Failed to initialize Syscallback Thread Pool \n"); + goto failthread; + } + + Me.Initialized = TRUE; + return TRUE; + +failthread: + LQListDestroy (&Me.LowPriQueue); +faillow: + LQListDestroy (&Me.HighPriQueue); +fail: + return FALSE; +} + +void +SysCallbackDestroy (void) +{ +#if SYS_CALLBACK_DEBUG + DbgOut("SysCallbackDestroy\n"); +#endif + if (Me.Initialized) + _SysCallbackCleanup(); +} + + +// Internal Function to manage SYS_CALLBACK_ITEMs +static SYS_CALLBACK_ITEM * +alloc_syscallback (void) +{ + SYS_CALLBACK_ITEM *pItem = NULL; + + pItem = (SYS_CALLBACK_ITEM*)MemoryAllocateAndClear ( + sizeof (SYS_CALLBACK_ITEM), + FALSE, SYS_CALLBACK_TAG); + if( pItem ) + { + QListSetObj(&pItem->ListItem, pItem); + } + return pItem; +} + +static void +free_syscallback (IN SYS_CALLBACK_ITEM *pItem) +{ + ASSERT (pItem); + MemoryDeallocate (pItem); + return; +} + + +SYS_CALLBACK_ITEM* +SysCallbackGet( IN void *Key ) +{ + SYS_CALLBACK_ITEM *pItem = NULL; + +#if SYS_CALLBACK_DEBUG + DbgOut("SysCallbackGet\n"); +#endif + ASSERT( Me.Initialized == TRUE ); + + // Simple, return the next available one from the free pool + pItem = alloc_syscallback (); + + if (!pItem) + return NULL; + + pItem->Key = Key; + +#if SYS_CALLBACK_DEBUG + DbgOut("SysCallbackGet returns: %p Key %p\n", pItem, Key); +#endif + return pItem; +} + +void +SysCallbackPut( IN SYS_CALLBACK_ITEM *pItem ) +{ +#if SYS_CALLBACK_DEBUG + DbgOut("SysCallbackPut: %p\n", pItem); +#endif + ASSERT( pItem ); + ASSERT( Me.Initialized == TRUE ); + + // Return it to the free pool + free_syscallback (pItem); +} + +void SysCallbackQueue (IN SYS_CALLBACK_ITEM *pItem, + IN SYSTEM_CALLBACK Callback, IN void *Context, + IN boolean HighPriority) +{ +#if SYS_CALLBACK_DEBUG + DbgOut("SysCallbackQueue: %p: callback %p Context %p High=%d\n", pItem, Callback, Context, HighPriority); +#endif + ASSERT( Me.Initialized == TRUE ); + + pItem->Callback = Callback; + pItem->Context = Context; + + // Queue the SYS_CALLBACK_ITEM at the tail of a queue (ie HIGH or LOW) + // based on the Priority of this request + if (HighPriority) + { + LQListInsertTail (&Me.HighPriQueue, &pItem->ListItem); + } else { + LQListInsertTail (&Me.LowPriQueue, &pItem->ListItem); + } + + // Signal one of the threads from the THREAD_POOL items + ThreadPoolSignal (&Me.ThreadPool); +} + + +// This is our SysCallback Thread function. +// It looks at the high priority queue first, if there is some work to do +// pick it up and run it. Else move on to the low priority queue +void +_SysCallbackWrapper (IN void *Context) +{ + LIST_ITEM *pListItem = NULL; + +#if SYS_CALLBACK_DEBUG + DbgOut("SysCallbackWrapper: %p\n", Context); +#endif + do + { +#if SYS_CALLBACK_DEBUG + DbgOut("SysCallbackWrapper: Check High Queue\n"); +#endif + // Process items from the High Priority Queue first. + pListItem = LQListRemoveHead (&Me.HighPriQueue); + + // Check to see if there was anything on the high priority queue. + if (!pListItem) + { +#if SYS_CALLBACK_DEBUG + DbgOut("SysCallbackWrapper: Check Low Queue\n"); +#endif + // Nothing on the high priority queue. Check the low priority + // queue. + pListItem = LQListRemoveHead (&Me.LowPriQueue); + } + + if( pListItem ) + { + // Invoke the user callback. + SYS_CALLBACK_ITEM *pItem = (SYS_CALLBACK_ITEM*)QListObj(pListItem); + ASSERT (pItem); + // Invoke the user callback. +#if SYS_CALLBACK_DEBUG + DbgOut("SysCallbackWrapper: process Item %p Key %p\n", pItem, pItem->Key); +#endif + pItem->Callback (pItem->Key, pItem->Context); + } + } while( pListItem ); +#if SYS_CALLBACK_DEBUG + DbgOut("SysCallbackWrapper: Done\n"); +#endif + + return; +} diff --git a/IbAccess/Common/Public/isyscallback.h b/IbAccess/Common/Public/isyscallback.h new file mode 100644 index 0000000..3e35c12 --- /dev/null +++ b/IbAccess/Common/Public/isyscallback.h @@ -0,0 +1,109 @@ +/* BEGIN_ICS_COPYRIGHT3 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT3 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + + +#ifndef _IBA_PUBLIC_ISYSCALLBACK_H_ +#define _IBA_PUBLIC_ISYSCALLBACK_H_ + +#include "iba/public/datatypes.h" + +#ifdef __cplusplus +extern "C" { +#endif +typedef void (*SYSTEM_CALLBACK)( IN void *Key, IN void *Context ); +#ifdef __cplusplus +}; +#endif + + +#ifdef _NATIVE_SYSCALLBACK +/* Include platform specific system callback support. */ +#include "iba/public/isyscallback_osd.h" + +#else /* Use this public version */ +#include "iba/public/ilist.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct _SYS_CALLBACK_ITEM +{ + SYSTEM_CALLBACK Callback; + void *Key; + void *Context; + + /* list maintenance */ + LIST_ITEM ListItem; +} SYS_CALLBACK_ITEM; + + +/* + * Return TRUE if initialization is successful. + * FALSE if initialization failed. + */ +boolean +SysCallbackInit(void); + +void +SysCallbackDestroy(void); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* _NATIVE_SYSCALLBACK */ + +#ifdef __cplusplus +extern "C" +{ +#endif + +SYS_CALLBACK_ITEM * +SysCallbackGet( + IN void *Key ); + +void +SysCallbackPut( + IN SYS_CALLBACK_ITEM *pItem ); + +void +SysCallbackQueue( + IN SYS_CALLBACK_ITEM *pItem, + IN SYSTEM_CALLBACK Callback, + IN void *Context, + IN boolean HighPriority ); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* _IBA_PUBLIC_ISYSCALLBACK_H_ */ diff --git a/IbAccess/Common/Public/isysutil.h b/IbAccess/Common/Public/isysutil.h new file mode 100644 index 0000000..006168f --- /dev/null +++ b/IbAccess/Common/Public/isysutil.h @@ -0,0 +1,63 @@ +/* BEGIN_ICS_COPYRIGHT3 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT3 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +#ifndef _IBA_PUBLIC_ISYSUTIL_H_ +#define _IBA_PUBLIC_ISYSUTIL_H_ + +#include "iba/public/datatypes.h" +#include "iba/public/isysutil_osd.h" + +/* Assorted System Utility Functions */ + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(VXWORKS) +/* obtain the System Node Name. Any domain name suffix is removed + * remainder is copied to dest for up to dest_len characters + * if dest_len is < strlen(node name), dest is not \0 terminated. + * returns dest + */ +extern char *SystemGetNodeName(char *dest, uint32 dest_len); +extern void SystemSeedRandom(unsigned long entropy); +extern unsigned long SystemGetRandom(void); +/* OS specific header will define 2 functions: + * boolean SystemIncModuleRefCount(void) + * void SystemDecModuleRefCount(void) + */ +#endif /* defined(VXWORKS) */ + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* _IBA_PUBLIC_ISYSUTIL_H_ */ diff --git a/IbAccess/Common/Public/itcpip.h b/IbAccess/Common/Public/itcpip.h new file mode 100644 index 0000000..d02d426 --- /dev/null +++ b/IbAccess/Common/Public/itcpip.h @@ -0,0 +1,110 @@ +/* BEGIN_ICS_COPYRIGHT3 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT3 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +#ifndef _IBA_PUBLIC_ITCPIP_H_ +#define _IBA_PUBLIC_ITCPIP_H_ + +#include "iba/public/datatypes.h" +#include "iba/public/ibyteswap.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#include "iba/public/ipackon.h" + +typedef struct _IP_HEADER +{ + IB_BITFIELD2(uint8, + Version:4, + HeaderLength:4 + ) + uint8 TypeOfService; + uint16 TotalLength; + uint16 Id; + uint16 FragmentOffset; + uint8 TimeToLive; + uint8 Protocol; + uint16 CheckSum; + uint32 SrcAddr; + uint32 DestAddr; +} PACK_SUFFIX IP_HEADER; + +typedef struct _IPV6_HEADER +{ + IB_BITFIELD2(uint8, + Version:4, + Priority:4 + ) + uint8 FlowLabel[3]; + uint16 PayloadLength; + uint8 NextHeader; + uint8 HopLimit; + uint8 SrcAddr[16]; + uint8 DestAddr[16]; +} PACK_SUFFIX IPV6_HEADER; + +/* + * IPV6 extension headers + */ +#define IPPROTO_ICMPV6 58 /* ICMPv6 */ + + +#define IP_PROTOCOL_UDP 17 +typedef struct _UDP_HEADER +{ + uint16 SrcPort; + uint16 DestPort; + uint16 UdpLength; + uint16 UdpCheckSum; +} PACK_SUFFIX UDP_HEADER; + +/* ARP */ + +/* opcodes */ +#define ARP_OPCODE_REQUEST 1 +#define ARP_OPCODE_REPLY 2 +#define ARP_OPCODE_RARP_REQUEST 3 +#define ARP_OPCODE_RARP_REPLY 4 +#define ARP_OPCODE_INARP_REQUEST 8 +#define ARP_OPCODE_INARP_REPLY 9 +#define ARP_OPCODE_NAK 10 + +/* protocol Hardware Ids */ +#define ARP_HARDWARE_ETHERNET 1 + +#include "iba/public/ipackoff.h" + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* _IBA_PUBLIC_ITCPIP_H_ */ diff --git a/IbAccess/Common/Public/ithread.h b/IbAccess/Common/Public/ithread.h new file mode 100644 index 0000000..8819014 --- /dev/null +++ b/IbAccess/Common/Public/ithread.h @@ -0,0 +1,123 @@ +/* BEGIN_ICS_COPYRIGHT3 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT3 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + + +#ifndef _IBA_PUBLIC_ITHREAD_H_ +#define _IBA_PUBLIC_ITHREAD_H_ + +#define THREAD_NAME_SIZE 16 /* matches Linux current->comm[] size */ + +#include "iba/public/ithread_osd.h" +#include "iba/public/ilist.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/* Callback function invoked after the thread is created. */ +typedef void (*THREAD_CALLBACK)( IN void *Context ); + +/* Thread object definition. */ +typedef struct _THREAD +{ + /* Private data structure used by the thread object. */ + /* Users should not access these variables directly. */ + struct _ThreadPriv + { + THREAD_OSD m_Osd; + THREAD_CALLBACK m_Callback; + void *m_Context; + + } m_Private; + +} THREAD; + + + +/* Create a new system thread. */ +void +ThreadInitState( + IN THREAD *pThread ); + +boolean +ThreadCreate( + IN THREAD *pThread, + IN char* Name, + IN THREAD_CALLBACK Callback, + IN void *Context ); + +/* Destroy the thread when through using it. + * This should not be called by the thread itself to exiting. + */ +void +ThreadDestroy( + IN THREAD *pThread ); + +/* Suspend the currently executing thread. */ +void +ThreadSuspend( + IN uint32 pause_ms ); + +/* Stall the currently executing thread. */ +void +ThreadStall( + IN uint32 pause_us ); + +/* Return the number of processors in the system. */ +uint32 +ProcCount( void ); + +/* Returns current CPU */ +uint32 +CurrentProc( void ); + +/* Returns TRUE if the calling thread is the specified thread object. */ +boolean +IsCurrentThread( + IN THREAD *pThread ); + +/* Sets priority for current thread */ +void +ThreadSetPriority( + IN THREAD_PRI pri); + +/*Sets Name for the calling thread */ +void ThreadSetName( + IN char *name); +/* gets name of the calling thread set by ThreadSetName*/ +char* ThreadGetName(void); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* _IBA_PUBLIC_ITHREAD_H_ */ diff --git a/IbAccess/Common/Public/ithreadpool.c b/IbAccess/Common/Public/ithreadpool.c new file mode 100644 index 0000000..ed7b5d2 --- /dev/null +++ b/IbAccess/Common/Public/ithreadpool.c @@ -0,0 +1,274 @@ +/* BEGIN_ICS_COPYRIGHT6 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT6 ****************************************/ + + +#include "datatypes.h" +#include "ithreadpool.h" +#include "ispinlock.h" +#include "imemory.h" +#include "idebug.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +#define THREAD_POOL_DEBUG 0 + +void +ThreadPoolCleanup( + IN THREAD_POOL *pThreadPool ); + +#if defined(__cplusplus) +} +#endif + +// +// ThreadPool Implementation +// +static void +ThreadPoolRoutine( + IN void *Context ) +{ + THREAD_POOL *pThreadPool = (THREAD_POOL*)Context; + + ThreadSetPriority(pThreadPool->m_Priority); + + // Continue looping until signalled to end. + while( TRUE ) + { + // Wait for the specified event to occur. + // IbAccess created kernel threads have signals blocked + // use interruptible wait so we don't contribute to loadavg + EventWaitOnInterruptible( &pThreadPool->m_Event, EVENT_NO_TIMEOUT ); + + // See if we've been signalled to end execution. + if( pThreadPool->m_Exit ) + { + // Decrement the running count to notify the destroying thread + // that the event was received and processed. + AtomicDecrementVoid( &pThreadPool->m_RunningCount ); + EventTrigger( &pThreadPool->m_DestroyEvent ); + break; + } + +#if THREAD_POOL_DEBUG + DbgOut("ThreadPool: calling callback: %p(%p)\n", pThreadPool->m_Callback, pThreadPool->m_Context); +#endif + // The event has been signalled. Invoke the callback. + (*pThreadPool->m_Callback)( pThreadPool->m_Context ); + } +} + + +void +ThreadPoolInitState( + IN THREAD_POOL *pThreadPool ) +{ +#if THREAD_POOL_DEBUG + DbgOut("ThreadPoolInitState: %p\n", pThreadPool); +#endif + MemoryClear( pThreadPool, sizeof( THREAD_POOL ) ); + EventInitState( &pThreadPool->m_Event ); + EventInitState( &pThreadPool->m_DestroyEvent ); + ListInitState( &pThreadPool->m_List ); +} + + +// +// Starts the thread pool with the requested number of threads. +// If Count is set to zero, creates one thread per processor in the system. +// +boolean +ThreadPoolCreate( + IN THREAD_POOL *pThreadPool, + IN uint32 Count, + IN char* Name, + IN THREAD_PRI Priority, + IN THREAD_CALLBACK Callback, + IN void *Context ) +{ + THREAD *pThread; + uint32 i; + +#if THREAD_POOL_DEBUG + DbgOut("ThreadPoolCreate: %p Count %d Name %s Callback %p Context %p\n", pThreadPool, Count, Name, Callback, Context); +#endif + ASSERT( Callback ); + + ThreadPoolInitState( pThreadPool ); + + if( !Count ) + Count = ProcCount(); + + if( !ListInit( &pThreadPool->m_List, Count) ) + return FALSE; + + // Initialize the event that the threads wait on. + if( !EventInit( &pThreadPool->m_Event ) ) + { + ListDestroy( &pThreadPool->m_List); + return FALSE; + } + + // Initialize the event used to destroy the threadpool. + if( !EventInit( &pThreadPool->m_DestroyEvent ) ) + { + ListDestroy( &pThreadPool->m_List ); + EventDestroy( &pThreadPool->m_Event ); + return FALSE; + } + + pThreadPool->m_Callback = Callback; + pThreadPool->m_Context = Context; + pThreadPool->m_Priority = Priority; + + for( i = 0; i < Count; i++ ) + { + char tname[THREAD_NAME_SIZE]; + + // -6 allows for '\0', [] and 3 digits of count + snprintf(tname, THREAD_NAME_SIZE, "%.*s[%d]", + THREAD_NAME_SIZE-6, Name, i+1); + + // Create a new thread. + if( !(pThread = (THREAD*)MemoryAllocate( sizeof( THREAD ), FALSE, 0)) ) + { + ThreadPoolCleanup( pThreadPool ); + return FALSE; + } + ThreadInitState(pThread); + + // Add it to the list. This is guaranteed to work. + ListInsertHead( &pThreadPool->m_List, pThread ); + + // Start the thread. + if( !ThreadCreate( pThread, tname, ThreadPoolRoutine, pThreadPool ) ) + { + ThreadPoolCleanup( pThreadPool ); + return FALSE; + } + + // Increment the running count to insure that a destroying thread + // will signal all the threads. + AtomicIncrement(&pThreadPool->m_RunningCount); + } + pThreadPool->m_Initialized = TRUE; + return TRUE; +} + + +// +// Destroys all threads that have been created. +// +void +ThreadPoolDestroy( + IN THREAD_POOL *pThreadPool ) +{ +#if THREAD_POOL_DEBUG + DbgOut("ThreadPoolDestroy: %p\n"); +#endif + if( !pThreadPool->m_Initialized ) + return; + + ThreadPoolCleanup( pThreadPool ); +} + + +void +ThreadPoolCleanup( + IN THREAD_POOL *pThreadPool ) +{ + THREAD *pThread; + +#if THREAD_POOL_DEBUG + DbgOut("ThreadPoolCleanup: %p\n"); +#endif + // Indicate to all threads that they need to exit. + pThreadPool->m_Exit = TRUE; + + // Signal the threads until they have all exited. Signalling + // once for each thread is not guaranteed to work since two events + // could release only a single thread, depending on the rate at which + // the events are set and how the thread scheduler processes notifications. + while( AtomicRead(&pThreadPool->m_RunningCount) ) + { + EventTrigger( &pThreadPool->m_Event ); + // Wait for the destroy event to occur, indicating that the thread + // has exited. + EventWaitOn( &pThreadPool->m_DestroyEvent, EVENT_NO_TIMEOUT ); + } + + // Stop each thread one at a time. Note that this cannot be done in the + // above for loop because signal will wake up an unknown thread. + while( NULL != (pThread = (THREAD*)ListRemoveHead( &pThreadPool->m_List )) ) + { + ThreadDestroy( pThread ); + MemoryDeallocate( pThread ); + } + + EventDestroy( &pThreadPool->m_DestroyEvent ); + EventDestroy( &pThreadPool->m_Event ); + ListDestroy( &pThreadPool->m_List ); + pThreadPool->m_Initialized = FALSE; +} + + +// +// Releases one thread for execution. +// +void +ThreadPoolSignal( + IN THREAD_POOL *pThreadPool ) +{ +#if THREAD_POOL_DEBUG + DbgOut("ThreadPoolSignal: %p\n"); +#endif + + if (pThreadPool->m_Initialized) { + EventTrigger( &pThreadPool->m_Event ); + } +} + +#if !defined(__VXWORKS__) +// +// Releases all threads for execution. +// +void +ThreadPoolBroadcast( + IN THREAD_POOL *pThreadPool ) +{ +#if THREAD_POOL_DEBUG + DbgOut("ThreadPoolBroadcast: %p\n"); +#endif + + if (pThreadPool->m_Initialized) { + EventBroadcast( &pThreadPool->m_Event ); + } +} +#endif diff --git a/IbAccess/Common/Public/ithreadpool.h b/IbAccess/Common/Public/ithreadpool.h new file mode 100644 index 0000000..5b4fa8e --- /dev/null +++ b/IbAccess/Common/Public/ithreadpool.h @@ -0,0 +1,96 @@ +/* BEGIN_ICS_COPYRIGHT3 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT3 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + + +#ifndef _IBA_PUBLIC_ITHREAD_POOL_H_ +#define _IBA_PUBLIC_ITHREAD_POOL_H_ + +#include "iba/public/ilist.h" +#include "iba/public/ithread.h" +#include "iba/public/ievent.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Thread Pool object. Threads will wait on an event, then invoke a callback. + */ +typedef struct _THREAD_POOL +{ + /* Routine called by thread when the specified event occurs. */ + THREAD_CALLBACK m_Callback; + void *m_Context; + + DLIST m_List; + EVENT m_Event; + EVENT m_DestroyEvent; + boolean m_Exit; + + boolean m_Initialized; + + ATOMIC_UINT m_RunningCount; + THREAD_PRI m_Priority; + +} THREAD_POOL; + + +void +ThreadPoolInitState( + IN THREAD_POOL *pThreadPool ); + +boolean +ThreadPoolCreate( + IN THREAD_POOL *pThreadPool, + IN uint32 ThreadCount, + IN char* Name, + IN THREAD_PRI Priority, + IN THREAD_CALLBACK Callback, + IN void *Context ); + +/* Destroy must be called in a premptable context. */ +void +ThreadPoolDestroy( + IN THREAD_POOL *pThreadPool ); + +void +ThreadPoolSignal( + IN THREAD_POOL *pThreadPool ); + +void +ThreadPoolBroadcast( + IN THREAD_POOL *pThreadPool ); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* _IBA_PUBLIC_ITHREAD_POOL_H_ */ diff --git a/IbAccess/Common/Public/itimer.h b/IbAccess/Common/Public/itimer.h new file mode 100644 index 0000000..1343859 --- /dev/null +++ b/IbAccess/Common/Public/itimer.h @@ -0,0 +1,193 @@ +/* BEGIN_ICS_COPYRIGHT3 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT3 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +#ifndef _IBA_PUBLIC_ITIMER_H_ +#define _IBA_PUBLIC_ITIMER_H_ + +#include "iba/public/itimer_osd.h" + +/* Timer Overview + * + * Timers provide a kernel level mechanism for scheduling a callback + * in the future. + * + * TimerInit and TimerDestroy may only be used at base (not interrupt/tasklet) + * level + * + * TimerStart and TimerStop may be used anywhere, including in the timer + * callback itself + * + * TimerCallbackStopped should only be used in the callback itself. + * + * Timer callbacks should be assumed to be at interrupt level, it can vary + * per OS. + * + * TimerStop will schedule the stop of the timer and make a best attempt + * at stopping it. However, it may not be completely successful. + * If the callback is already starting, it may occur after TimerStop. + * In which case the timer code will skip stale callbacks and not call the + * consumer callback. + * However if a callback is in progress and has already started to + * execute the consumer callback function, TimerStop will not stop it nor + * will TimerStop preempt nor wait for the callback to finish. + * See the discussion of TimerCallbackStopped for a dicussion of the + * recommended locking and usage model to prevent races and deadlocks. + * (This behaviour is necessary such that TimerStop will not deadlock with + * a caller who holds a consumer lock and is stopping the timer while the + * callback has already started and is waiting for the consumer lock). + * + * TimerDestroy will wait for any callbacks to complete. After the completion + * of TimerDestroy the caller can safely assume no more callbacks will occur + * nor are any still executing. + * + * If TimerDestroy is called while holding a lock which the callback might + * also attempt to get, a deadlock can occur. In which case the Reaper + * should be used to destroy the object or the TimerDestroy should be done + * outside of the lock if safe. In simple cases, the sequence: + * get lock + * TimerStop + * release lock + * TimerDestroy + * is safe if the callback is following the locking model recommended in + * TimerCallbackStopped + */ + + +#ifdef __cplusplus +extern "C" { +#endif + +/* Return the number of micro secs that have passed since the system was booted. */ +uint64 +GetTimeStamp( void ); + +/* Return the number of seconds that have passed since the system was booted. */ +uint32 +GetTimeStampSec( void ); + +#if defined(VXWORKS) +/* + * Callback function invoked once the timer expires. + */ +typedef void (*TIMER_CALLBACK)( IN void *Context ); + + +/* + * Private data structure used by the spinlock object. + * Users should not access these variables directly. + */ +typedef struct _TIMER_PRIV +{ + TIMER_OSD m_Osd; + TIMER_CALLBACK m_TimerCallback; + void *m_Context; +} TIMER_PRIV; + + + +/* + * Timer object definition. + */ +typedef struct _TIMER +{ + /* No publically accessible members. */ + TIMER_PRIV m_Private; +} TIMER; + + +/* + * Function declarations. + */ +/* Initialize a timer before its use. */ +void +TimerInitState( + IN TIMER *pTimer ); + +boolean +TimerInit( + IN TIMER *pTimer, + IN TIMER_CALLBACK TimerCallback, + IN void *Context ); + +/* Destroy the timer object when done using it. */ +void +TimerDestroy( + IN TIMER *pTimer ); + +/* Start the timer to alert at the specified time. */ +boolean +TimerStart( + IN TIMER *pTimer, + IN uint32 time_ms ); + +/* Stop the timer from alerting. */ +void TimerStop( + IN TIMER *pTimer ); + +/* used in a timer callback to determine if the callback is applicable + * Mainly needed if timer callback gets a lock which is shared with code + * outside the timer. Helps to catch if while callback waited for lock + * the toplevel code has gotten lock, stopped timer, and done other stuff. + * TRUE - callback was stopped and should not do anything + * FALSE - callback is real and should perform callback actions + * + * In general it is recommended that objects shared between timer callbacks + * and other code should have a lock for the object or subsystem. + * In which case the typical callback should be structured as: + * callback(void *context) + * { + * lock + * if (TimerCallbackStopped( timer)) + * unlock + * return + * process callback + * unlock + * } + * + * and other code using object should be structured as: + * lock + * do stuff + * TimerStop + * other stuff, possibly TimerStart + * unlock + * + */ +boolean TimerCallbackStopped(TIMER *pTimer); + +/* Indicates if timer has expired and callback has or will be run */ +boolean TimerExpired(TIMER *pTimer); +#endif /* defined(VXWORKS) */ + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* _IBA_PUBLIC_ITIMER_H_ */ diff --git a/IbAccess/Common/Public/statustext.c b/IbAccess/Common/Public/statustext.c new file mode 100644 index 0000000..8be2497 --- /dev/null +++ b/IbAccess/Common/Public/statustext.c @@ -0,0 +1,140 @@ +/* BEGIN_ICS_COPYRIGHT6 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT6 ****************************************/ + +#include "statustext.h" + +// Status values above converted to text for easier printing. +const char* FStatusText[] = +{ + "FSUCCESS", + "FERROR", + "FINVALID_STATE", + "FINVALID_OPERATION", + "FINVALID_SETTING", + "FINVALID_PARAMETER", + "FINSUFFICIENT_RESOURCES", + "FINSUFFICIENT_MEMORY", + "FCOMPLETED", + "FNOT_DONE", + "FPENDING", + "FTIMEOUT", + "FCANCELED", + "FREJECT", + "FOVERRUN", + "FPROTECTION", + "FNOT_FOUND", + "FUNAVAILABLE", + "FBUSY", + "FDISCONNECT", + "FDUPLICATE", + "FPOLL_NEEDED" +}; + +const char* FCmStatusText[] = +{ + "FCM0", + "FCM_NOT_INITIALIZED", + "FCM_INVALID_HANDLE", + "FCM_ADDR_INUSE", + "FCM_INVALID_EVENT", + "FCM_ALREADY_DISCONNECTING", + "FCM_CONNECT_DESTROY", + "FCM7", + "FCM8", + "FCM9", + "FCM_CONNECT_TIMEOUT", + "FSIDR_REQUEST_TIMEOUT", + "FCM12", + "FCM_CONNECT_REJECT", + "FCM_CONNECT_CANCEL", + "FCM15", + "FCM16", + "FCM17", + "FCM18", + "FCM19", + "FCM_CONNECT_REPLY", + "FCM_DISCONNECT_REQUEST", + "FCM_DISCONNECT_REPLY", + "FCM_CONNECT_REQUEST", + "FCM_CONNECT_ESTABLISHED", + "FCM_DISCONNECTED", + "FSIDR_REQUEST", + "FSIDR_RESPONSE", + "FSIDR_RESPONSE_ERR", + "FCM_CA_REMOVED", + "FCM_ALTPATH_REQUEST", + "FCM_ALTPATH_REPLY", + "FCM_ALTPATH_REJECT", + "FCM_ALTPATH_TIMEOUT", + "FCM34", + "FCM35", + "FCM36", + "FCM37", + "FCM38", + "FCM39", + "FCM40", + "FCM41", + "FCM42", + "FCM43", + "FCM44", + "FCM45", + "FCM46", + "FCM47", + "FCM48", + "FCM49", + "FCM50", + "FCM51", + "FCM52", + "FCM53", + "FCM54", + "FCM55", + "FCM56", + "FCM57", + "FCM58", + "FCM59", + "FCM60", + "FCM61", + "FCM62", + "FCM63", + "FCM_WAIT_OBJECT0", + "FCM_WAIT_OBJECT1", + "FCM_WAIT_OBJECT2", + "FCM_WAIT_OBJECT3", + "FCM_WAIT_OBJECT4", + "FCM_WAIT_OBJECT5", + "FCM_WAIT_OBJECT6", + "FCM_WAIT_OBJECT7", + "FCM_WAIT_OBJECT8", + "FCM_WAIT_OBJECT9" +}; + +const char* iba_fstatus_msg(FSTATUS status) +{ + return FSTATUS_MSG(status); +} diff --git a/IbAccess/Common/Public/statustext.h b/IbAccess/Common/Public/statustext.h new file mode 100644 index 0000000..788d651 --- /dev/null +++ b/IbAccess/Common/Public/statustext.h @@ -0,0 +1,62 @@ +/* BEGIN_ICS_COPYRIGHT3 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT3 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +#ifndef _IBA_PUBLIC_STATUS_TEXT_H_ +#define _IBA_PUBLIC_STATUS_TEXT_H_ + +#include "iba/ib_status.h" /* IB-defined status code */ + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +/* Status values above converted to text for easier printing. */ +extern const char* FStatusText[]; +extern const char* FCmStatusText[]; + +/* prefered way to convert FSTATUS to a string */ +IBA_API const char* iba_fstatus_msg(FSTATUS status); + +/* depricated macro to convert FSTATUS_MSG to a string */ +/* FCM_WAIT_OBJECT0 == 64, < 74 allows for 0-9 */ +#define FSTATUS_MSG(errcode) \ + (((GET_MODULE(errcode) == IB_MOD_CM) && (GET_MODERR(errcode) < 74)) ? \ + FCmStatusText[GET_MODERR(errcode)]: \ + (((errcode & 0xFF) < FSTATUS_COUNT) ? \ + FStatusText[(errcode) & 0xFF] : "invalid status code")) + + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* _IBA_PUBLIC_STATUS_TEXT_H_ */ diff --git a/IbAccess/Common/SubnetDriver/client.c b/IbAccess/Common/SubnetDriver/client.c new file mode 100644 index 0000000..916f744 --- /dev/null +++ b/IbAccess/Common/SubnetDriver/client.c @@ -0,0 +1,332 @@ +/* BEGIN_ICS_COPYRIGHT4 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT4 ****************************************/ + + +#include +#include +#include +#include +#include +#include +#include + + +uint32 LastClientId; +CLIENT_CONTROL_PARAMETERS DefaultClientParameters; + +QUICK_LIST *pClientList = NULL; +SPIN_LOCK *pClientListLock = NULL; + +// Initialize the default parameters that clients get +void +SetDefaultClientParameters( + void + ) +{ + DefaultClientParameters.ControlParameters.RetryCount = g_SdParams.DefaultRetryCount; + DefaultClientParameters.ControlParameters.Timeout = g_SdParams.DefaultRetryInterval; + DefaultClientParameters.ClientDebugFlags = g_SdParams.DefaultDebugFlags; + DefaultClientParameters.OptionFlags = g_SdParams.DefaultOptionFlags; + + SpinLockAcquire(pClientListLock); + LastClientId = 0; + SpinLockRelease(pClientListLock); +} + + + +FSTATUS +iba_sd_register( + IN OUT CLIENT_HANDLE *ClientHandle, + IN PCLIENT_CONTROL_PARAMETERS pClientParameters OPTIONAL + ) +{ + ClientListEntry *pClientEntry; + + // + // Note: If the caller is running at low priority, the input pointers for + // the client ID and the client parameters can be pageable. If the caller + // is running at a high priority, it is the caller's responsibility to + // make sure that the pointers point to non-pageable memory. + // + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, iba_sd_register); + + pClientEntry = (ClientListEntry*)MemoryAllocate2AndClear(sizeof(ClientListEntry), IBA_MEM_FLAG_NONE, + SUBNET_DRIVER_TAG); + if (pClientEntry == NULL) + { + _DBG_ERROR( + ("Cannot allocate memory for new client entry\n")); + return(FINSUFFICIENT_MEMORY); + } + pClientEntry->ListItem.pObject = (void *)pClientEntry; + if (pClientParameters == NULL) + { + _DBG_INFO(("ClientParameters is NULL, Setting Driver Defaults\n")); + MemoryCopy(&pClientEntry->ClientParameters, &DefaultClientParameters, + sizeof(pClientEntry->ClientParameters)); + } else { + MemoryCopy(&pClientEntry->ClientParameters, pClientParameters, + sizeof(pClientEntry->ClientParameters)); + } + + QListInit(&pClientEntry->ClientTraps); + + SpinLockAcquire(pClientListLock); + pClientEntry->ClientId = LastClientId++; + // + // Note: We are running at the priority level of the caller. If the caller + // is running at low priority, the memory containing input client parameters + // could be pageable and may not be touched at high priority with a spin + // lock held. We therefor copy parameters to (non-pageable) stack location + // before raising priority by getting a lock + // + + QListInsertHead(pClientList, &pClientEntry->ListItem); + SpinLockRelease(pClientListLock); + + // + // Now we are back at the caller's priority, which could be low. In that + // case, it is now safe to touch the caller's potentially pageable memory. + // + //*pCid = Cid; + *ClientHandle = (CLIENT_HANDLE)pClientEntry; + + _DBG_LEAVE_LVL( _DBG_LVL_FUNC_TRACE ); + return(FSUCCESS); + +} + +FSTATUS +iba_sd_deregister( + IN CLIENT_HANDLE ClientHandle + ) +{ + return CommonSdDeregister(ClientHandle); +} + +FSTATUS +CommonSdDeregister( + IN CLIENT_HANDLE ClientHandle + ) +{ + ClientListEntry *pClientEntry = (ClientListEntry *)ClientHandle; + FSTATUS Fstatus = FNOT_FOUND; + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, iba_sd_deregister); + + SpinLockAcquire(pClientListLock); + // &pClientEntry->ListItem does not dereference pClientEntry + if(QListIsItemInList(pClientList, &pClientEntry->ListItem) == TRUE) + { + QListRemoveItem(pClientList, &pClientEntry->ListItem); + Fstatus = FSUCCESS; + _DBG_INFO(("Client Entry removal passed\n")); + } else { + Fstatus = FNOT_FOUND; + _DBG_INFO(("Client Entry removal failed\n")); + } + SpinLockRelease(pClientListLock); + + // Clean up CompletionList and QueryList for this clienthandle + if(Fstatus == FSUCCESS) + { + CancelClientQueries(ClientHandle); + UnsubscribeClient(pClientEntry); + MemoryDeallocate(pClientEntry); + } + + _DBG_LEAVE_LVL( _DBG_LVL_FUNC_TRACE ); + return(Fstatus); +} + +static boolean +CompareClientHandle( + IN LIST_ITEM* pListItem, + IN void* Context) +{ + return (((PQueryDetails)QListObj(pListItem))->ClientHandle == (CLIENT_HANDLE)Context); +} + +// cancel all queries in progress for client +// if we remove them from the pQueryList, any subsequent responses will +// be discarded, same as if the query had timed out +// if we cancel just before completions are reported, we could find some +// on the completion list for this client, so we clean them up too +// +// Note that child queries are never associated to a ClientHandle. +// Hence we will not be cancelling any child queries here. +// By cancelling the parent, the child will be discarded when it comes to +// the head of the pChildQueryList or when its response arrives. +void +CancelClientQueries( + IN CLIENT_HANDLE ClientHandle + ) +{ + QueryDetails *pQueryElement; + boolean schedule = FALSE; + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, CancelClientQueries); + + // first process the Query List + SpinLockAcquire(&pQueryList->m_Lock); + while (NULL != (pQueryElement = (QueryDetails*)QListFindFromHead( + &pQueryList->m_List, + CompareClientHandle, ClientHandle))) + { + QListRemoveItem(&pQueryList->m_List, &pQueryElement->QueryListItem); + DEBUG_ASSERT( pQueryElement->QState != QueryDestroy); + DEBUG_ASSERT( pQueryElement->pParentQuery == NULL); // not a child + pQueryElement->ClientHandle = NULL; // disassociate from client + if( pQueryElement->QState == ProcessingResponse + || pQueryElement->ChildProcessingResponseCount) + { + DEBUG_ASSERT(pQueryElement->QState == WaitingForChildToComplete + || ! pQueryElement->ChildProcessingResponseCount); + // RecvHandler is still holding onto pQueryElement + // mark state so RecvHandler will destroy it, leave off list + pQueryElement->QState = QueryDestroy; + SpinLockRelease(&pQueryList->m_Lock); + } else { + // no one else is using this element, we can unlock and change it + SpinLockRelease(&pQueryList->m_Lock); + if( pQueryElement->QState == WaitingForResult + || pQueryElement->QState == BusyRetryDelay) + AtomicDecrementVoid(&Outstanding); + // so we don't prempt here, defer destroy to premptable context + pQueryElement->QState = QueryDestroy; + LQListInsertHead(pCompletionList, &pQueryElement->QueryListItem); + schedule = TRUE; + } + SpinLockAcquire(&pQueryList->m_Lock); + } + SpinLockRelease(&pQueryList->m_Lock); + + // now process the Completion List + SpinLockAcquire(&pCompletionList->m_Lock); + while (NULL != (pQueryElement = (QueryDetails*)QListFindFromHead( + &pCompletionList->m_List, + CompareClientHandle, ClientHandle))) + { + // any items in QueryDestroy state should no longer be associated to + // a client. so we can assert that we are not in QueryDestroy state + DEBUG_ASSERT(pQueryElement->QState == QueryComplete); + DEBUG_ASSERT( pQueryElement->pParentQuery == NULL); // not a child + pQueryElement->ClientHandle = NULL; // disassociate from client + // so we don't prempt here, defer destroy to premptable context + // can leave on list + pQueryElement->QState = QueryDestroy; + SpinLockRelease(&pCompletionList->m_Lock); + schedule = TRUE; + SpinLockAcquire(&pCompletionList->m_Lock); + } + SpinLockRelease(&pCompletionList->m_Lock); + + // completion processing will handle defered destroys + if (schedule) + ScheduleCompletionProcessing(); +} + +FSTATUS +iba_sd_get_client_control_parameters( + IN CLIENT_HANDLE ClientHandle, + IN OUT PCLIENT_CONTROL_PARAMETERS pClientControlParameters + ) +{ + FSTATUS Fstatus = FNOT_FOUND; + CLIENT_CONTROL_PARAMETERS ClientParams; + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, iba_sd_get_client_control_parameters); + + if (pClientControlParameters == NULL) { + _DBG_INFO(("Invalid ClientControlParameters\n")); + _DBG_LEAVE_LVL( _DBG_LVL_FUNC_TRACE ); + return(FINVALID_PARAMETER); + } + + // Note: If the caller is running at low priority, the input memory for + // the client parameters can be pageable. If the caller is running at a + // high priority, it is the caller's responsibility to make sure that the + // memory is non-pageable. + Fstatus = ValidateClientHandle(ClientHandle, &ClientParams); + + // Now we are back to the caller's priority level and can safely touch + // the memory to which the results have to be written. + if (Fstatus == FSUCCESS) + { + MemoryCopy(pClientControlParameters, &ClientParams, + sizeof(ClientParams)); + } + _DBG_LEAVE_LVL( _DBG_LVL_FUNC_TRACE ); + return(Fstatus); +} + +FSTATUS +iba_sd_set_client_control_parameters( + IN CLIENT_HANDLE ClientHandle, + IN PCLIENT_CONTROL_PARAMETERS pClientControlParameters + ) +{ + FSTATUS Fstatus = FNOT_FOUND; + CLIENT_CONTROL_PARAMETERS ClientParams; + LIST_ITEM *pListItem = &((ClientListEntry *)ClientHandle)->ListItem; + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, iba_sd_set_client_control_parameters); + + if (pClientControlParameters == NULL) + { + _DBG_INFO(("Invalid ClientControlParameters\n")); + _DBG_LEAVE_LVL( _DBG_LVL_FUNC_TRACE ); + return(FINVALID_PARAMETER); + } + // Note: If the caller is running at low priority, the input memory for + // the client parameters can be pageable. If the caller is running at a + // high priority, it is the caller's responsibility to make sure that the + // memory is non-pageable. + // + // Note: We are running at caller's priority, which may be low. In that + // case, the caller could have supplied us a pointer to pageable memory that + // cannot be touched at high priority with the spin lock held. We therefore + // copy the parameters first to a local (non-pageable) stack location. + MemoryCopy(&ClientParams, pClientControlParameters, + sizeof(ClientParams)); + + SpinLockAcquire(pClientListLock); + if (QListIsItemInList(pClientList, pListItem)) + { + ClientListEntry *pClientEntry = (ClientListEntry*)ClientHandle; + Fstatus = FSUCCESS; + MemoryCopy(&(pClientEntry->ClientParameters), &ClientParams, + sizeof(pClientEntry->ClientParameters)); + } + SpinLockRelease(pClientListLock); + _DBG_LEAVE_LVL( _DBG_LVL_FUNC_TRACE ); + return(Fstatus); +} diff --git a/IbAccess/Common/SubnetDriver/dbg.h b/IbAccess/Common/SubnetDriver/dbg.h new file mode 100644 index 0000000..09715f1 --- /dev/null +++ b/IbAccess/Common/SubnetDriver/dbg.h @@ -0,0 +1,109 @@ +/* BEGIN_ICS_COPYRIGHT4 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT4 ****************************************/ +/* [ICS VERSION STRING: unknown] */ + +#ifndef _IBA_SD_DBG_H_ +#define _IBA_SD_DBG_H_ + +#include +#include +#include + +// define boolean +#define TRUE 1 +#define FALSE 0 + +#ifndef Ib_SubnDrv_Dbg +#undef _ib_dbg_params +#define _ib_dbg_params Ib_SubnDrv_Dbg +#endif + +// The following debug macros must be defined before including the "ib_debug.h" +#define _DBG_PRINT_EPILOG(LEVEL,STRING) +#define _DBG_PRINT_PROLOG(LEVEL,STRING) +#define _DBG_ERROR_EPILOG(LEVEL,STRING) +#define _DBG_ERROR_PROLOG(LEVEL,STRING) +#define _DBG_FATAL_EPILOG(LEVEL,STRING) +#define _DBG_FATAL_PROLOG(LEVEL,STRING) + + +#define _DBG_CHK_IRQL(IRQL) + +#include "ib_debug.h" + +#if defined(DBG) ||defined( IB_DEBUG) + +// +// We want to be able to control debug output based on global flags as well +// as per client debug flags that over-ride the global debug flags. This is +// why we need to take debug flags as input to this macro +// +#define DebugPrint(_DbgFlags_,_l_,_x_) \ + if (_DbgFlags_ & (_l_)) { \ + DbgOut("IBSd: "); \ + DbgOut _x_; \ + } + +// +// Debugging Output Levels +// + +#define _SD_ERROR(_DbgFlags_,_x_) \ + if ( _DbgFlags_ & SD_DBG_ERROR) \ + { \ + DbgOut("%s%s() !ERROR! ", _DBG_PTR(__MOD_NAME__),_DBG_PTR(__FUNC__)); \ + DbgOut _x_; \ + } + + +#define _SD_INFO(_DbgFlags_,_x_) \ + if ( _DbgFlags_ & SD_DBG_INFO) \ + { \ + DbgOut("%s%s() !INFO! ", _DBG_PTR(__MOD_NAME__),_DBG_PTR(__FUNC__)); \ + DbgOut _x_; \ + } + +#define _SD_TRACE(_DbgFlags_,_x_) \ + if ( _DbgFlags_ & SD_DBG_TRACE) \ + { \ + DbgOut("%s%s() !TRACE! ", _DBG_PTR(__MOD_NAME__),_DBG_PTR(__FUNC__)); \ + DbgOut _x_; \ + } + +#else // !((_DEBUG) || (DBG)) + +#define DebugPrint(_DbgFlags_,_l_,_x_) +#define _SD_ERROR(_DbgFlags_,_x_) +#define _SD_INFO(_DbgFlags_,_x_) +#define _SD_TRACE(_DbgFlags_,_x_) + +#endif // (_DEBUG) || (DBG) + +#endif // _IBA_SD_DBG_H_ + diff --git a/IbAccess/Common/SubnetDriver/ibt.c b/IbAccess/Common/SubnetDriver/ibt.c new file mode 100644 index 0000000..7097ae7 --- /dev/null +++ b/IbAccess/Common/SubnetDriver/ibt.c @@ -0,0 +1,519 @@ +/* BEGIN_ICS_COPYRIGHT4 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT4 ****************************************/ + + + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// +//Define global context for each of MGMT Class that we support +// + +SD_SERVICECONTEXT SdContext_SA = {0}; +SD_SERVICECONTEXT SdContext_Vend = {0}; + + +IB_HANDLE GsiSAHandle = NULL; + +IB_HANDLE sa_poolhandle = NULL; +IB_HANDLE sa_represp_poolhandle = NULL; + +static boolean +map_tranid_queryelement( LIST_ITEM *pItem, void *ptrid ); + +FSTATUS +InitializeIbt( + void + ) +/*++ +Routine Description. + +Arguments: + +--*/ +{ + FSTATUS Fstatus; + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, InitializeIbt); + + if((Fstatus = RegisterWithGSI()) !=FSUCCESS) + { + _DBG_ERROR(("Cannot register with GSI, exiting\n")); + _DBG_LEAVE_EXT(_DBG_LVL_FUNC_TRACE); + return(Fstatus); + } + + _DBG_LEAVE_EXT(_DBG_LVL_FUNC_TRACE); + return(Fstatus); + +} + +FSTATUS +RegisterWithGSI( + void + ) +/*++ +--*/ +{ + FSTATUS Status; + uint32 BufSize; + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, RegisterWithGSI); + + //Initialize the Subnet Data Interface context for SA + SdContext_SA.MgmtClass = MCLASS_SUBN_ADM; + + + Status = iba_gsi_register_class( + MCLASS_SUBN_ADM, // MgmtClass + IB_SUBN_ADM_CLASS_VERSION, // Mgmtclassversion of GSI + GSI_REGISTER_REPORT_PROCESSOR, // Register as a report processor + TRUE, // SAR + (void *)&SdContext_SA, + SdGsaSendCompleteCallback, + SdGsaRecvCallback, + &GsiSAHandle + ); + + + if(Status != FSUCCESS) + { + _DBG_ERROR(("Register with GSI failed for SubnetAdmin Class, exiting\n")); + _DBG_LEAVE_EXT(_DBG_LVL_FUNC_TRACE); + return(Status); + } + + BufSize = sizeof(SA_MAD); + + _DBG_INFO(("The size of SA_MAD is <0x%x>\n", (int)sizeof(SA_MAD))); + + Status = iba_gsi_create_dgrm_pool( + GsiSAHandle, + SD_MAX_SA_NDGRM, //64 elements + 1, // one buffer per element + &BufSize, + sizeof(void *), //Context size. + &sa_poolhandle + ); + + + if(Status != FSUCCESS) + { + _DBG_ERROR(("Create Dgrm Pool failed for SA, exiting\n")); + _DBG_LEAVE_EXT(_DBG_LVL_FUNC_TRACE); + return(Status); + } + + Status = iba_gsi_create_dgrm_pool( + GsiSAHandle, + SD_MAX_RESP_NDGRM, //64 elements + 1, // one buffer per element + &BufSize, + sizeof(void *), //Context size. + &sa_represp_poolhandle + ); + + + if(Status != FSUCCESS) + { + _DBG_ERROR(("Create Dgrm Pool failed for SA Report Resp, exiting\n")); + _DBG_LEAVE_EXT(_DBG_LVL_FUNC_TRACE); + return(Status); + } + + _DBG_LEAVE_EXT(_DBG_LVL_FUNC_TRACE); + return(Status); +} + +void +DeRegisterWithGSI( + void + ) +/*++ +Routine Description. + +Arguments: + +--*/ +{ + if(sa_represp_poolhandle) + { + iba_gsi_destroy_dgrm_pool(sa_represp_poolhandle); + sa_represp_poolhandle = NULL; + } + + if(sa_poolhandle) + { + iba_gsi_destroy_dgrm_pool(sa_poolhandle); + sa_poolhandle = NULL; + } + + + if(GsiSAHandle) + { + iba_gsi_deregister_class(GsiSAHandle); + GsiSAHandle = NULL; + } +} + +/*++ +Routine Description. + +This is invoked when GSA gets a packet sent by this GSI client +(since we are not a manager, we get no unsolicited responses). +The DgrmList will contain a single message. +This could be a single packet message or an RMPP message. +For an RMPP message each RMPP DATA packet is a separate Element in DgrmList. +Each Element has its own GRH header, MAD header, RMPP Header SA_HDR +and the actual SA payload. +this GsiCoalesceDgrm route will help us simply this structure. + +The dgrmlist given to us comes from the GSI receive pool. As such each element +is organized as follows: + Element + Buffer - GRH + Buffer - MAD_BLOCK_SIZE MAD packet + +Arguments: + ServiceContext - handle for our Gsi registration + DgrmList - the message being sent to us + +--*/ +FSTATUS +SdGsaRecvCallback( + void *ServiceContext, + IBT_DGRM_ELEMENT *pDgrmList + ) +{ + PSD_SERVICECONTEXT SdContext = (PSD_SERVICECONTEXT)ServiceContext; + uint32 messageSize = 0; + uint8 * buffer = NULL; + PQueryDetails pQueryElement; + MAD_RMPP *pMadSar; + IB_CLASS_PORT_INFO *pClassPortInfo; + LIST_ITEM *pListItem; + uint32 classHeaderSize = 0; // per packet class specific header + uint8 classVersion = 0; + uint32 madBlockSize; + uint32 rmppGsDataSize; + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, SdGsaRecvCallback); + + ASSERT(pDgrmList); + + // check the service context MgmtClass value + if ( SdContext->MgmtClass == MCLASS_SUBN_ADM) + { + _DBG_INFO(("Receiving a SubnetAdm datagram element\n")); + classHeaderSize = sizeof(SA_HDR); + classVersion = IB_SUBN_ADM_CLASS_VERSION; + } else { + _DBG_INFO(("Receiving datagram for wrong class <%d>! \n", + SdContext->MgmtClass)); + _DBG_BREAK; + goto badmad; + } + + pMadSar = (MAD_RMPP *)GsiDgrmGetRecvMad(pDgrmList); + if (!pMadSar) + { + _DBG_WARNING((" Empty MAD passed in!\n", _DBG_PTR(pDgrmList))); + goto badmad; + } + + // Sanity check base mad header + { + uint8 BaseVer=0; + uint8 MgmtClass=0; + uint8 ClassVer=0; + + MAD_GET_VERSION_INFO((MAD*)pMadSar, &BaseVer, &MgmtClass, &ClassVer); + if ( ((BaseVer != IB_BASE_VERSION) && (BaseVer != STL_BASE_VERSION)) || + (MgmtClass != SdContext->MgmtClass) || + (ClassVer != classVersion)) + { + _DBG_WARNING((" Invalid base version, mgmt class or class version \n", + _DBG_PTR(pMadSar), _DBG_PTR(BaseVer), _DBG_PTR(MgmtClass), ClassVer)); + goto badmad; + } + } + + if (MAD_IS_REQUEST((MAD*)pMadSar)) + { + ProcessRequest(ServiceContext, pDgrmList); + // FCOMPLETED will cause GSI to return the Dgrm to its recv pool + return FCOMPLETED; + } + + // Lookup the Query Element using the transaction ID + SpinLockAcquire(&pQueryList->m_Lock); + { + uint64 TempTranID; + + TempTranID = (uint64)(pMadSar->common.TransactionID >> 8); + _DBG_INFO(("The TransactionID obtained is <%"PRIx64">\n",TempTranID)); + if ((pListItem = QListFindItem( + &pQueryList->m_List,map_tranid_queryelement, &TempTranID)) == NULL) + { + // if it is not in the list assume that we have already + // completed this pQueryElement + _DBG_WARNING(("Received Message with no outstanding query! \n")); + goto done; + } + } + pQueryElement = (PQueryDetails)QListObj(pListItem); + _DBG_INFO(("Response Turnaround Time: %"PRId64" usec\n", + GetTimeStamp() - pQueryElement->CmdSentTime)); + if( pQueryElement->QState != WaitingForResult) + { + _DBG_INFO(("pQueryElement is not in WaitingForResult State\n")); + goto done; + } + + if(pMadSar->common.u.NS.Status.AsReg16 == MAD_STATUS_BUSY + && pQueryElement->RetriesLeft) + { + _DBG_INFO(("pQueryElement going into BusyRetryDelay State\n")); + // leave on queue, timer will fire and trigger retry + // don't decrement OutStanding, hence while busy we won't attempt to + // start any other queries either + pQueryElement->QState = BusyRetryDelay; // causes use of a new timeout + goto done; + } + + pQueryElement->QState = ProcessingResponse; // holds our reference + // unlock so we can prempt during coallese + SpinLockRelease(&pQueryList->m_Lock); + + rmppGsDataSize = (pMadSar->common.BaseVersion == IB_BASE_VERSION) + ? IBA_RMPP_GS_DATASIZE : STL_RMPP_GS_DATASIZE; + madBlockSize = (pMadSar->common.BaseVersion == IB_BASE_VERSION) + ? IB_MAD_BLOCK_SIZE : STL_MAD_BLOCK_SIZE; + + if(pDgrmList->TotalRecvSize > (sizeof(IB_GRH) + madBlockSize)) + { + // RMPP response, coalesce the pieces into a single buffer + messageSize = iba_gsi_coalesce_dgrm2(pDgrmList, &buffer,classHeaderSize, + IBA_MEM_FLAG_PREMPTABLE|IBA_MEM_FLAG_SHORT_DURATION); + if (messageSize == 0) + { + _DBG_ERROR(("Invalid RMPP response received! \n")); + } else if (buffer == NULL) { + _DBG_ERROR(("Can't allocate %d byte RMPP response buffer! \n",messageSize)); + messageSize = 0; // flags failure + } + pMadSar = (MAD_RMPP *)(buffer + sizeof(IB_GRH)); + } else { + messageSize = sizeof(IB_GRH) + + sizeof(MAD_COMMON) + + sizeof(RMPP_HEADER) + + pMadSar->RmppHdr.u2.PayloadLen; // includes SA_HDRs + if (pMadSar->RmppHdr.u2.PayloadLen > rmppGsDataSize) + { + _DBG_ERROR(("Invalid PayloadLen for single packet message: %u! \n", pMadSar->RmppHdr.u2.PayloadLen)); + messageSize = 0; // flags failure + + } + } + SpinLockAcquire(&pQueryList->m_Lock); + if (FreeCancelledQueryElement(pQueryElement)) + goto done; + // restore state so failures will cause retry/timeout + pQueryElement->QState = WaitingForResult; + if (messageSize == 0) + { + // allocate failure or invalid response + goto done; + } + if( pQueryElement->IsSelfCommand) + { + // Internal commands, not requested by an SubnetData user + _DBG_INFO(("This is a self issued command\n")); + if(pMadSar->common.u.NS.Status.AsReg16 != MAD_STATUS_SUCCESS) + { + _DBG_ERROR(("Mad status = <0x%x: %s>, Port 0x%016"PRIx64"\n", + pMadSar->common.u.NS.Status.AsReg16, + _DBG_PTR(iba_mad_status_msg(pMadSar->common.u.NS.Status)), + pQueryElement->PortGuid)); + // leave on queue, timer will timeout and retry + goto done; + } + + //////////////// + switch (pQueryElement->SdSentCmd) + { + case GetClassportInfo: + { + CA_PORT *pCaPort; + + pClassPortInfo = (IB_CLASS_PORT_INFO *)((SA_MAD*)pMadSar)->Data; + _DBG_DUMP_MEMORY(_DBG_LVL_INFO, ("Class Port Info Response"), + pClassPortInfo, sizeof(IB_CLASS_PORT_INFO)); + BSWAP_IB_CLASS_PORT_INFO(pClassPortInfo); + + // Update Ca Port with the details of the redirected info + SpinLockAcquire(pCaPortListLock); + pCaPort = GetCaPort(pDgrmList->PortGuid); + + // spec was not real clear if a non-redirect should supply 0 + // or should provide the default location. + // So if LID is 0, we use the default location + // BUGBUG handle redirectGID/GRH case + if (pClassPortInfo->RedirectLID) + { + pCaPort->RedirectedQP = pClassPortInfo->u3.s.RedirectQP; + pCaPort->RedirectedQKey = pClassPortInfo->Redirect_Q_Key; + pCaPort->RedirectedLid = pClassPortInfo->RedirectLID; + pCaPort->RedirectedSL = (uint8)pClassPortInfo->u2.s.RedirectSL; + // IB does not have Static rate in ClassPortInfo + // so we can't be sure what rate of remote port is + // we use a constant value for GSI QPs + pCaPort->RedirectedStaticRate = IB_STATIC_RATE_GSI; + // BUGBUG - get PKey Index from Port Info + pCaPort->RedirectedPkeyIndex = 0; // TBD lookup in Pkey Table for port + // pClassPortInfo->Redirect_P_Key; + } else { + pCaPort->RedirectedQP = pCaPort->RemoteQp; + pCaPort->RedirectedQKey = pCaPort->RemoteQKey; + pCaPort->RedirectedLid = pCaPort->Lid; + pCaPort->RedirectedSL = pCaPort->ServiceLevel; + pCaPort->RedirectedStaticRate = pCaPort->StaticRate; + pCaPort->RedirectedPkeyIndex = pCaPort->PkeyIndex; + } + + AtomicDecrementVoid(&Outstanding); + _DBG_INFO(("QueryElement %p Completed: %u Outstanding\n", + _DBG_PTR(pQueryElement), + AtomicRead(&Outstanding))); + QListRemoveItem( &pQueryList->m_List, pListItem ); + //For SA after ClassPortInfo is done, we are ready + _DBG_INFO(("InfoProviders for SA is initialized to TRUE\n")); + pCaPort->bInitialized = TRUE; + + SpinLockRelease(pCaPortListLock); + SpinLockRelease(&pQueryList->m_Lock); + FreeQueryElement(pQueryElement); + goto unlocked; + break; + } + default: + DEBUG_ASSERT(0); + _DBG_ERROR(("Unknown self command! \n")); + break; + } //End Switch + } else { + // SubnetData user issued command, callback the receive handler + AtomicDecrementVoid(&Outstanding); + _DBG_INFO(("QueryElement %p Completed: %u Outstanding\n", + _DBG_PTR(pQueryElement), + AtomicRead(&Outstanding))); + + // pQueryList->m_lock held, pQueryElement still on list + // Note RecvHandler may choose to release and reacquire lock for + // example to do premptable allocates or frees. + // lock is held during call so RecvHandler can be certain pQueryElement + // will not be deleted or state changed unless RecvHandler chooses to + // release lock + // QueryElement is in WaitingForResult state + SubnetAdmRecv(pQueryElement, pMadSar, messageSize - sizeof(IB_GRH), pDgrmList); + // RecvHandler could have freed pQueryElement, so can't use it anymore + } + +done: + // in some situations when we get here the pQueryElement has been freed + SpinLockRelease(&pQueryList->m_Lock); +unlocked: + if(buffer != NULL) + { + MemoryDeallocate(buffer); + buffer = NULL; + } + SdSendNextOutstanding(); //pQueryElement may be free, can't deref +badmad: + // FCOMPLETED will cause GSI to return the Dgrm to its recv pool + return FCOMPLETED; +} + +// helper for list search, compare transaction id in list item to one +// provided. Since arg is void*, we must use pointers to uint64 TIDs +static boolean +map_tranid_queryelement( LIST_ITEM *pItem, void *ptrid ) +{ + PQueryDetails piQuery = (PQueryDetails)pItem->pObject; + uint64 *pTempTranId = (uint64*)ptrid; + + uint64 SrcTranId = piQuery->u.pMad->common.TransactionID >> 8; + uint64 DestTranId = (*pTempTranId); + _DBG_INFO(("SrcTranID =<%"PRIx64"> DestTranID=<%"PRIx64">\n",\ + SrcTranId,DestTranId)); + + return (SrcTranId == DestTranId); +} + + +/*++ +Routine Description. + +Arguments: + +--*/ +void +SdGsaSendCompleteCallback( + void *ServiceContext, + IBT_DGRM_ELEMENT *pDgrmList + ) +{ + PSD_SERVICECONTEXT SdContext = (PSD_SERVICECONTEXT)ServiceContext; + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, SdGsaSendCompleteCallback); + + ASSERT(pDgrmList); + ASSERT( SdContext->MgmtClass == MCLASS_SUBN_ADM); + +#ifdef SA_ALLOC_DEBUG + if (iba_gsi_dgrm_pool_count(sa_poolhandle) < 50) MsgOut("Dgrm send callback\n"); +#endif + if(SdContext->MgmtClass == MCLASS_SUBN_ADM) + { + _DBG_INFO(("GsiSendCompleteCallback called for SUBNETADM DGRM Element\n")); + } + + iba_gsi_dgrm_pool_put( pDgrmList); + + _DBG_LEAVE_EXT(_DBG_LVL_FUNC_TRACE); + return; +} diff --git a/IbAccess/Common/SubnetDriver/infop.c b/IbAccess/Common/SubnetDriver/infop.c new file mode 100644 index 0000000..6ef3f09 --- /dev/null +++ b/IbAccess/Common/SubnetDriver/infop.c @@ -0,0 +1,646 @@ +/* BEGIN_ICS_COPYRIGHT4 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT4 ****************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern uint32 SADisable; + +ATOMIC_UINT Outstanding; // number of queries/operations in progress + +uint32 NumLocalCAs = 0; +uint32 NumTotalPorts = 0; +EUI64 *pLocalCaGuidList = NULL; +IB_CA_ATTRIBUTES *pLocalCaInfo = NULL; +SPIN_LOCK *pLocalCaInfoLock = NULL; +IB_HANDLE CaNotifyHandle = NULL; +SPIN_LOCK *pCaPortListLock = NULL; +QUICK_LIST *pCaPortList = NULL; + +LIST_ITEM* +GetCaPortListItem( + EUI64 PortGuid + ) +{ + LIST_ITEM *pCaPortListItem; + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, GetCaPortListItem); + + _DBG_INFO(("Searching for Ca Port (GUID: %"PRIx64").\n", PortGuid)); + + for (pCaPortListItem = QListHead(pCaPortList); + pCaPortListItem != NULL; + pCaPortListItem = QListNext(pCaPortList, pCaPortListItem) + ) + { + CA_PORT *pCaPort = (CA_PORT *) QListObj(pCaPortListItem); + ASSERT(pCaPort != NULL); + + if (pCaPort->PortGuid == PortGuid) + { + _DBG_INFO(("Found Ca Port (GUID: %"PRIx64").\n", PortGuid)); + _DBG_INFO(("SubnetAdm Ca Port (GUID: %"PRIx64").\n", pCaPort->SaPortGuid)); + _DBG_LEAVE_LVL(_DBG_LVL_FUNC_TRACE); + return pCaPortListItem; + } + } + + _DBG_INFO(("Ca Port (GUID: %"PRIx64") not found.\n", PortGuid)); + _DBG_LEAVE_LVL(_DBG_LVL_FUNC_TRACE); + return NULL; +} + +CA_PORT* +GetCaPort( + EUI64 PortGuid + ) +{ + LIST_ITEM *pCaPortListItem = GetCaPortListItem(PortGuid); + CA_PORT *pCaPort = NULL; + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, GetCaPort); + + if (pCaPortListItem != NULL) + { + pCaPort = (CA_PORT *) QListObj(pCaPortListItem); + ASSERT(pCaPort != NULL); + } + + _DBG_LEAVE_LVL(_DBG_LVL_FUNC_TRACE); + return pCaPort; +} + +void +AddCa( + EUI64 CaGuid + ) +{ + IB_CA_ATTRIBUTES *pNewCaInfo = NULL; + uint32 ii; + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, AddCa); + + _DBG_INFO(("Adding Ports for Channel Adapter (GUID: %"PRIx64").\n", + CaGuid)); + + if (pLocalCaInfo != NULL) + { + SpinLockAcquire(pLocalCaInfoLock); + + _DBG_INFO(("NumLocalCAs (%d).\n", NumLocalCAs)); + + for (ii = 0; ii < NumLocalCAs; ii++) + { + if (pLocalCaInfo[ii].GUID == CaGuid) + { + _DBG_INFO( + ("Channel Adapter (GUID: %"PRIx64") Found @ Index (%d).\n", + pLocalCaInfo[ii].GUID, ii)); + pNewCaInfo = &pLocalCaInfo[ii]; + break; + } + } + + if (pNewCaInfo != NULL) + { + IB_PORT_ATTRIBUTES *pPortAttr; + + _DBG_INFO(("Channel Adapter (GUID: %"PRIx64") Port Count (%d).\n", + pNewCaInfo->GUID, pNewCaInfo->Ports)); + + for (ii = 0, pPortAttr = pNewCaInfo->PortAttributesList; + ii < pNewCaInfo->Ports; + ii++, pPortAttr = pPortAttr->Next + ) + { + CA_PORT* pCaPort = (CA_PORT*)MemoryAllocateAndClear(sizeof(CA_PORT), + TRUE, SUBNET_DRIVER_TAG); + ASSERT(pCaPort != NULL); + + pCaPort->CaGuid = CaGuid; + pCaPort->PortGuid = pPortAttr->GUID; + if (! LookupPKey(pPortAttr, DEFAULT_P_KEY, TRUE, &pCaPort->DefaultPkeyIndex)) + pCaPort->DefaultPkeyIndex = 0; + QListSetObj(&pCaPort->CaPortListItem, pCaPort); + + SpinLockAcquire(pCaPortListLock); + + QListInsertTail(pCaPortList, &pCaPort->CaPortListItem); + + _DBG_INFO(("Added Port (Number %d) (GUID: %"PRIx64 + ") (Channel Adapter GUID: %"PRIx64").\n", + ii, + pCaPort->PortGuid, + pCaPort->CaGuid)); + + SpinLockRelease(pCaPortListLock); + + InitializeCaPortInfo(pPortAttr->GUID); + } + } + + SpinLockRelease(pLocalCaInfoLock); + } + + _DBG_LEAVE_LVL(_DBG_LVL_FUNC_TRACE); +} + +void +RemoveCa( + EUI64 CaGuid + ) +{ + LIST_ITEM *pCaPortListItem; + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, RemoveCa); + + SpinLockAcquire(pCaPortListLock); + + pCaPortListItem = QListHead(pCaPortList); + + while (pCaPortListItem != NULL) + { + CA_PORT *pCaPort = (CA_PORT *) QListObj(pCaPortListItem); + ASSERT(pCaPort != NULL); + + pCaPortListItem = QListNext(pCaPortList, pCaPortListItem); + + if (pCaPort->CaGuid == CaGuid) + { + QListRemoveItem(pCaPortList, &pCaPort->CaPortListItem); + MemoryDeallocate(pCaPort); + } + } + + SpinLockRelease(pCaPortListLock); + + _DBG_LEAVE_LVL(_DBG_LVL_FUNC_TRACE); +} + +uint32 +GetNumTotalPorts( + IN void + ) +{ + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, GetNumTotalPorts); + _DBG_LEAVE_LVL(_DBG_LVL_FUNC_TRACE); + return (NumTotalPorts); +} + +FSTATUS +iba_sd_get_local_port_guids_alloc( + IN OUT uint64 **ppLocalPortGuidsList, + IN OUT uint32 *LocalPortGuidsCount + ) +{ + return iba_sd_get_local_port_guids_alloc2(ppLocalPortGuidsList, NULL, + LocalPortGuidsCount); +} + +FSTATUS +iba_sd_get_local_port_guids_alloc2( + IN OUT uint64 **ppLocalPortGuidsList, + IN OUT uint64 **ppLocalPortSubnetPrefixList, + IN OUT uint32 *LocalPortGuidsCount + ) +{ + FSTATUS Fstatus = FNOT_DONE; + LIST_ITEM *pCaPortListItem; + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, iba_sd_get_local_port_guids_alloc2); + + if (ppLocalPortGuidsList) { + *ppLocalPortGuidsList = NULL; + } else { + Fstatus = FINVALID_PARAMETER; + goto done; + } + + if (ppLocalPortSubnetPrefixList) + *ppLocalPortSubnetPrefixList = NULL; + + if (LocalPortGuidsCount) { + *LocalPortGuidsCount = 0; + } else { + Fstatus = FINVALID_PARAMETER; + goto done; + } + + if (NumTotalPorts == 0) + { + _DBG_INFO(("No LocalPortGuids allocated.\n")); + Fstatus = FSUCCESS; + goto done; + } + + *ppLocalPortGuidsList = + (EUI64*)MemoryAllocate2AndClear((sizeof(EUI64)*NumTotalPorts), + IBA_MEM_FLAG_SHORT_DURATION, SUBNET_DRIVER_TAG); + if (*ppLocalPortGuidsList == NULL) + { + _DBG_ERROR(("Cannot allocate memory for LocalPortGuids\n")); + Fstatus = FINSUFFICIENT_MEMORY; + goto done; + } + if (ppLocalPortSubnetPrefixList) + { + *ppLocalPortSubnetPrefixList = + (EUI64*)MemoryAllocate2AndClear((sizeof(EUI64)*NumTotalPorts), + IBA_MEM_FLAG_SHORT_DURATION, SUBNET_DRIVER_TAG); + if (*ppLocalPortSubnetPrefixList == NULL) + { + _DBG_ERROR(("Cannot allocate memory for LocalPortSubnetPrefix\n")); + Fstatus = FINSUFFICIENT_MEMORY; + goto fail; + } + } + + SpinLockAcquire(pCaPortListLock); + + for (pCaPortListItem = QListHead(pCaPortList); + pCaPortListItem != NULL; + pCaPortListItem = QListNext(pCaPortList, pCaPortListItem) + ) + { + IB_PORT_ATTRIBUTES *pPortAttr; + FSTATUS status; + + CA_PORT *pCaPort = (CA_PORT *) QListObj(pCaPortListItem); + ASSERT(pCaPort != NULL); + + status = iba_query_port_by_guid_alloc(pCaPort->PortGuid, &pPortAttr); + if (FSUCCESS != status) + { + Fstatus = status; + break; + } + + _DBG_INFO(("The port state is %d\n",pPortAttr->PortState)); + _DBG_INFO(("BaseLid <%d>\n",pPortAttr->Address.BaseLID)); + if ((pPortAttr->Address.BaseLID != /*IB_INVALID_LID*/ 0) && + (pPortAttr->PortState == PortStateActive)) + { + //NOTENOTE: Return only active ports + (*ppLocalPortGuidsList)[*LocalPortGuidsCount] = pPortAttr->GUID; + if (ppLocalPortSubnetPrefixList) + (*ppLocalPortSubnetPrefixList)[*LocalPortGuidsCount] = pPortAttr->GIDTable[0].Type.Global.SubnetPrefix; + (*LocalPortGuidsCount)++; + Fstatus = FSUCCESS; + } + + MemoryDeallocate(pPortAttr); + } + + SpinLockRelease(pCaPortListLock); + +fail: + if (Fstatus != FSUCCESS) { + if (*ppLocalPortGuidsList != NULL) { + MemoryDeallocate(*ppLocalPortGuidsList); + *ppLocalPortGuidsList = 0; + } + *LocalPortGuidsCount = 0; + if (ppLocalPortSubnetPrefixList && *ppLocalPortSubnetPrefixList) + { + MemoryDeallocate(*ppLocalPortSubnetPrefixList); + *ppLocalPortSubnetPrefixList = 0; + } + // enable this code in the future, + // for now for backward compatibility + // return an error code for no ports found (FNOT_DONE above) + //if (Fstatus == FNOT_DONE) + // Fstatus = FSUCCESS; + } + +done: + _DBG_LEAVE_EXT(_DBG_LVL_FUNC_TRACE); + return Fstatus; +} + + +FSTATUS +GetLocalCaInfo( + void + ) +{ + FSTATUS Fstatus; + uint32 ii; + uint32 OldNumLocalCAs = NumLocalCAs; + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, GetLocalCaInfo); + + // This function has been called by holding a pLocalCaInfoLock spinlock + + if (pLocalCaGuidList) + { + MemoryDeallocate(pLocalCaGuidList); + pLocalCaGuidList = NULL; + } + + NumLocalCAs = 0; + Fstatus = iba_get_caguids_alloc(&NumLocalCAs, &pLocalCaGuidList); + if (Fstatus != FSUCCESS) + { + _DBG_ERROR(("Fstatus <0x%x> getting local CA GUIDs\n", Fstatus)); + pLocalCaGuidList = NULL; + NumLocalCAs = 0; + _DBG_LEAVE_EXT(_DBG_LVL_FUNC_TRACE); + return(Fstatus); + } + + _DBG_INFO(("Number of Channel Adapters present <%d>\n", NumLocalCAs)); + if (NumLocalCAs <= 0) { + _DBG_INFO(("No CA reported by GetCaGuids\n")); + return FSUCCESS; + } + + if (pLocalCaInfo) + { + uint32 count; + for(count=0; count\n", + Status)); + _DBG_LEAVE_LVL(_DBG_LVL_FUNC_TRACE); + return; + } + + switch (NotifyRecord.EventType) + { + case IB_NOTIFY_CA_ADD: + _DBG_INFO(("IB_NOTIFY_CA_ADD (GUID: %"PRIx64").\n", + NotifyRecord.Guid)); + AddCa(NotifyRecord.Guid); + break; + + case IB_NOTIFY_CA_REMOVE: + _DBG_INFO(("IB_NOTIFY_CA_REMOVE (GUID: %"PRIx64").\n", + NotifyRecord.Guid)); + RemoveCa(NotifyRecord.Guid); + break; + + case IB_NOTIFY_LID_EVENT: + _DBG_INFO(("IB_NOTIFY_LID_EVENT (GUID: %"PRIx64").\n", + NotifyRecord.Guid)); + InitializeCaPortInfo(NotifyRecord.Guid); + ReRegisterTrapSubscriptions(NotifyRecord.Guid); + break; + + case IB_NOTIFY_SM_EVENT: + _DBG_INFO(("IB_NOTIFY_SM_EVENT (GUID: %"PRIx64").\n", + NotifyRecord.Guid)); + InitializeCaPortInfo(NotifyRecord.Guid); + ReRegisterTrapSubscriptions(NotifyRecord.Guid); + break; + + case IB_NOTIFY_PORT_DOWN: + _DBG_INFO(("IB_NOTIFY_PORT_DOWN (GUID: %"PRIx64").\n", + NotifyRecord.Guid)); + InitializeCaPortInfo(NotifyRecord.Guid); + InvalidatePortTrapSubscriptions(NotifyRecord.Guid); + break; + + case IB_NOTIFY_PKEY_EVENT: + _DBG_INFO(("IB_NOTIFY_PKEY_EVENT (GUID: %"PRIx64").\n", + NotifyRecord.Guid)); + InitializeCaPortInfo(NotifyRecord.Guid); + ReRegisterTrapSubscriptions(NotifyRecord.Guid); + break; + + default: + _DBG_INFO(("Someother Event (%lu) (GUID: %"PRIx64").\n", + NotifyRecord.EventType, + NotifyRecord.Guid)); + break; + } +#ifdef USE_SD_MULTICAST + McPortNotifyCallback(&NotifyRecord); +#endif + _DBG_LEAVE_LVL(_DBG_LVL_FUNC_TRACE); + + return; +} + +FSTATUS +InitializeCaPortInfo( + EUI64 PortGuid + ) +{ + FSTATUS Fstatus = FERROR; + CA_PORT *pCaPort; + IB_PORT_ATTRIBUTES *pPortAttr = NULL; + boolean bInitialized; + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, InitializeCaPortInfo); + + if (SdUnloading) + { + _DBG_LEAVE_LVL( _DBG_LVL_FUNC_TRACE ); + return(FINVALID_STATE); + } + _DBG_INFO(("Number of Local CA are %d\n",NumLocalCAs)); + + SpinLockAcquire(pCaPortListLock); + + pCaPort = GetCaPort(PortGuid); + if (pCaPort == NULL) + { + SpinLockRelease(pCaPortListLock); + /* there is a rare possibility during shutdown that the port could go + * up/down after the Subnet Driver Remove Device has been called but + * before SMARemoveDevice is called. In which case IbtNotifyGroup is + * still enabled for the given CA and the SubnetDriver could get a port + * state change which will put is here. In this rare case we + * could fail to find the CaGuid and should ignore the callback + */ + _DBG_INFO(("GetCaPort returned NULL for Port (GUID: %"PRIx64").\n", PortGuid)); + _DBG_LEAVE_LVL( _DBG_LVL_FUNC_TRACE ); + return (Fstatus); + } + + // + // Note: The calling function should not fail driver load if this + // function returns error. It is possible that this function is called + // before the local CA has been initialized by a remote subnet manager + // In that case, this function will fail but will register for a local + // CA change callback. When the local CA does get initialized, this + // registered callback will be invoked and the callback will call this + // function again. + // + + // + // LID for the information provider is initially set to the LID of the + // subnet manager. This can be subsequently redirected. Get the SM LID + // using local IBT calls + // + + Fstatus = iba_query_port_by_guid_alloc(PortGuid, &pPortAttr); + ASSERT(Fstatus == FSUCCESS); + + _DBG_INFO(("The port state is %d\n",pPortAttr->PortState)); + _DBG_INFO(("BaseLid <%d>\n",pPortAttr->Address.BaseLID)); + + if (! LookupPKey(pPortAttr, DEFAULT_P_KEY, TRUE, &pCaPort->DefaultPkeyIndex)) + pCaPort->DefaultPkeyIndex = 0; + + pCaPort->Lid = pPortAttr->SMAddress.LID; + pCaPort->ServiceLevel = pPortAttr->SMAddress.ServiceLevel; + pCaPort->RemoteQp = GSI_QP; + pCaPort->RemoteQKey = GSI_QKEY; + // IB does not have Static rate in UD LRH + // so we can't be sure what rate of remote port is + // we use a constant value for GSI QPs + pCaPort->StaticRate = IB_STATIC_RATE_GSI; + pCaPort->PkeyIndex = pCaPort->DefaultPkeyIndex; + pCaPort->SaPortGuid = pPortAttr->GUID; + if(pPortAttr->NumGIDs > 0) + pCaPort->SubnetPrefix = pPortAttr->GIDTable[0].Type.Global.SubnetPrefix; + // default redirect to default location + pCaPort->RedirectedQP = pCaPort->RemoteQp; + pCaPort->RedirectedQKey = pCaPort->RemoteQKey; + pCaPort->RedirectedLid = pCaPort->Lid; + pCaPort->RedirectedSL = pCaPort->ServiceLevel; + pCaPort->RedirectedStaticRate = pCaPort->StaticRate; + pCaPort->RedirectedPkeyIndex = pCaPort->PkeyIndex; + + if ((pPortAttr->Address.BaseLID != /*IB_INVALID_LID*/ 0) && + (pPortAttr->PortState == PortStateActive)) + //NOTENOTE: Check for pPortAttr->SMAddress.LID != 0 + { + pCaPort->SdSMAddressValid = TRUE; + Fstatus = FSUCCESS; + } + + // Free the port attributes buffer. + MemoryDeallocate( pPortAttr ); + + if (Fstatus != FSUCCESS) + { + // + // It is possible that local ports have not yet been initialized by + // a remote subnet manager. This is OK - we have registered for a + // callback when that happens and we will initialize the service + // provider at that time + // + + pCaPort->bInitialized = FALSE; + + _DBG_INFO(("No local port currently available\n")); + pCaPort->SdSMAddressValid = FALSE; + + SpinLockRelease(pCaPortListLock); + + // + // We haven't collected enough information to send any message to the + // information provider, so simply return for now. + // + _DBG_LEAVE_LVL(_DBG_LVL_FUNC_TRACE); + return(Fstatus); + } + + bInitialized = pCaPort->bInitialized; + + SpinLockRelease(pCaPortListLock); + + if (! SADisable) + { + if(bInitialized == FALSE) + SubnetAdmInit(); + } + + _DBG_LEAVE_LVL(_DBG_LVL_FUNC_TRACE); + return(FSUCCESS); +} diff --git a/IbAccess/Common/SubnetDriver/multicast.c b/IbAccess/Common/SubnetDriver/multicast.c new file mode 100644 index 0000000..b1ec21f --- /dev/null +++ b/IbAccess/Common/SubnetDriver/multicast.c @@ -0,0 +1,1462 @@ +/* BEGIN_ICS_COPYRIGHT5 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + * ** END_ICS_COPYRIGHT5 ****************************************/ +/* [ICS VERSION STRING: unknown] */ + +#include "multicast.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ipackon.h" + +typedef struct _MC_RID +{ + IB_GID MGID; + IB_GID PortGID; +} PACK_SUFFIX MC_RID; + +typedef struct _MC_GROUP_ID +{ + int JoinVersion; + MC_RID McRID; + EUI64 EgressPortGUID; +} MC_GROUP_ID; + +typedef struct _MC_GROUP +{ + LIST_ITEM ListItem; + MC_GROUP_STATE McGroupState; + TIMER Timer; + boolean TimerActive; + uint64 ComponentMask; + MC_GROUP_ID McGroupId; + IB_MCMEMBER_RECORD McMemberRecord; + FABRIC_OPERATION_DATA FabOp; + QUERY FabInfoQuery; + QUICK_LIST McClientList; + uint32 McGroupInUse; + boolean McGroupDelete; +} MC_GROUP; + +typedef struct _MC_CLIENT +{ + LIST_ITEM ListItem; + LIST_ITEM McGroupListItem; + CLIENT_HANDLE SdClientHandle; + uint16 McFlags; + MC_GROUP *pMcGroup; + void *pContext; + SD_MULTICAST_CALLBACK *pMulticastCallback; + uint32 McClientInUse; + boolean McClientDelete; +} MC_CLIENT; + +static CLIENT_HANDLE McSdHandle; + +static QUICK_LIST MasterMcGroupList; +static QUICK_LIST MasterMcClientList; + +static SPIN_LOCK MulticastLock; + +static TIMER MaintenanceTimer; +static boolean MaintenanceTimerActivated; + +extern uint32 NumTotalPorts; + +/* Assumes MulticastLock is Held */ +static +void +McLockAllGroups(void) +{ + LIST_ITEM *pListItem; + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, McLockAllGroups); + + for (pListItem = QListHead(&MasterMcGroupList); + pListItem != NULL; + pListItem = QListNext(&MasterMcGroupList, pListItem)) + { + MC_GROUP *pMcGroup = (MC_GROUP *)QListObj(pListItem); + + ASSERT(pMcGroup != NULL); + + pMcGroup->McGroupInUse++; + } + + _DBG_LEAVE_LVL( _DBG_LVL_FUNC_TRACE ); +} + + +/* Assumes MulticastLock is Held */ +static +void +McUnlockAllGroups(void) +{ + LIST_ITEM *pListItem; + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, McUnlockAllGroups); + + for (pListItem = QListHead(&MasterMcGroupList); + pListItem != NULL; + pListItem = QListNext(&MasterMcGroupList, pListItem)) + { + MC_GROUP *pMcGroup = (MC_GROUP *)QListObj(pListItem); + + ASSERT(pMcGroup != NULL); + + pMcGroup->McGroupInUse--; + } + + _DBG_LEAVE_LVL( _DBG_LVL_FUNC_TRACE ); +} + +/* Assumes MulticastLock is Held */ +static +void +McLockAllGroupClients(MC_GROUP *pMcGroup) +{ + LIST_ITEM *pListItem; + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, McLockAllGroupClients); + + for (pListItem = QListHead(&pMcGroup->McClientList); + pListItem != NULL; + pListItem = QListNext(&pMcGroup->McClientList, pListItem)) + { + MC_CLIENT *pMcClient = (MC_CLIENT *)QListObj(pListItem); + + ASSERT(pMcClient != NULL); + + pMcClient->McClientInUse++; + } + + _DBG_LEAVE_LVL( _DBG_LVL_FUNC_TRACE ); +} + +/* Assumes MulticastLock is Held */ +static +void +McUnlockAllGroupClients(MC_GROUP *pMcGroup) +{ + LIST_ITEM *pListItem; + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, McUnlockAllGroupClients); + + for (pListItem = QListHead(&pMcGroup->McClientList); + pListItem != NULL; + pListItem = QListNext(&pMcGroup->McClientList, pListItem)) + { + MC_CLIENT *pMcClient = (MC_CLIENT *)QListObj(pListItem); + + ASSERT(pMcClient != NULL); + + pMcClient->McClientInUse--; + } + + _DBG_LEAVE_LVL( _DBG_LVL_FUNC_TRACE ); +} + +/* Assumes MulticastLock is Held */ +static +void +QueueSubnetDriverCall(MC_GROUP *pMcGroup, MC_GROUP_STATE State) +{ + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, QueueSubnetDriverCall); + + if (pMcGroup->TimerActive == TRUE) + { + TimerStop(&pMcGroup->Timer); + } + else + { + pMcGroup->McGroupInUse++; + pMcGroup->TimerActive = TRUE; + } + + ASSERT((State == MC_GROUP_STATE_REQUEST_JOIN) || (State == MC_GROUP_STATE_REQUEST_LEAVE)); + pMcGroup->McGroupState = State; + TimerStart(&pMcGroup->Timer, 1000); + _DBG_LEAVE_LVL( _DBG_LVL_FUNC_TRACE ); +} + +/* Assumes MulticastLock is Held */ +static +void +CallMcClients(MC_GROUP *pMcGroup, FSTATUS Status, MC_GROUP_STATE State) +{ + LIST_ITEM *pMcClientListItem; + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, CallMcClient); + + if (pMcGroup->McGroupDelete == TRUE && pMcGroup->McGroupInUse == 0 ) + { + goto exit; + } + + McLockAllGroupClients(pMcGroup); + + //pMcGroup->McGroupInUse++; + pMcGroup->McGroupState = State; + + for (pMcClientListItem = QListHead(&pMcGroup->McClientList); + pMcClientListItem != NULL; + pMcClientListItem = QListNext(&pMcGroup->McClientList, pMcClientListItem)) + { + SD_MULTICAST_CALLBACK *pMulticastCallback; + void *pContext; + MC_CLIENT *pMcClient = (MC_CLIENT *)QListObj(pMcClientListItem); + + ASSERT(pMcClient != NULL); + + if (pMcClient->McClientDelete == TRUE) + { + continue; + } + + if (State == MC_GROUP_STATE_UNAVAILABLE) + { + if (!(pMcClient->McFlags & MC_FLAG_WANT_UNAVAILABLE)) + { + continue; + } + } + + pMulticastCallback = pMcClient->pMulticastCallback; + pContext = pMcClient->pContext; + SpinLockRelease(&MulticastLock); + (*pMulticastCallback)(pContext, Status, State, &pMcGroup->McMemberRecord); + SpinLockAcquire(&MulticastLock); + } + + McUnlockAllGroupClients(pMcGroup); + +exit: + _DBG_LEAVE_LVL( _DBG_LVL_FUNC_TRACE ); +} + +static +void +McGroupFabOpCallback(void *pContext, + FABRIC_OPERATION_DATA *pFabOp, + FSTATUS Status, + uint32 MadStatus) +{ + MC_GROUP *pMcGroup = (MC_GROUP*)pContext; + LIST_ITEM *pListItem; + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, McGroupFabOpCallback); + + if (McSdHandle != NULL) + { + ASSERT(pMcGroup != NULL); + + SpinLockAcquire(&MulticastLock); + + //pMcGroup->McGroupInUse--; + + if ((Status == FTIMEOUT) || (MadStatus == MAD_STATUS_BUSY)) + { + /* Has Timed Out. Try Again */ + pMcGroup->McGroupInUse--; + QueueSubnetDriverCall(pMcGroup, pMcGroup->McGroupState); + goto exit; + } + + switch (pMcGroup->McGroupState) + { + case MC_GROUP_STATE_REQUEST_JOIN: + { + MC_GROUP_STATE State = MC_GROUP_STATE_AVAILABLE; + + if ((Status != FSUCCESS) || (MadStatus != MAD_STATUS_SUCCESS)) + { + _DBG_ERROR(("McGroupFabOpCallback Group Join Failure. Status = %d, Mad Status = %d\n", + Status, MadStatus)); + State = MC_GROUP_STATE_JOIN_FAILED; + } else { + /* update record with full details from SM */ + // why is this necessary??? could it be causing any harm??? + pMcGroup->McMemberRecord = pFabOp->Value.McMemberRecordValue.McMemberRecord; + } + + CallMcClients(pMcGroup, Status, State); + if (State == MC_GROUP_STATE_JOIN_FAILED) + { + // set up the group for delete + pMcGroup->McGroupDelete = TRUE; + // set all clients using this group for delete + for (pListItem = QListHead(&pMcGroup->McClientList); + pListItem != NULL; + pListItem = QListNext(&pMcGroup->McClientList, pListItem)) + { + MC_CLIENT *pMcClient = (MC_CLIENT *)QListObj(pListItem); + pMcClient->McClientDelete = TRUE; + } + } + break; + } + + case MC_GROUP_STATE_REQUEST_LEAVE: + { + // Removed group from the SM + // pMcGroup will be deallocated by McMaintenance + + CallMcClients(pMcGroup, Status, MC_GROUP_STATE_UNAVAILABLE ); + break; + } + default: + _DBG_ERROR(("McGroupFabOpCallback: Unknown MC Group Request %d, FabOp Type %d, Status %d, MadStatus %d\n", + pMcGroup->McGroupState, pFabOp->Type, Status, MadStatus)); + } +exit: + pMcGroup->McGroupInUse--; + SpinLockRelease(&MulticastLock); + } + + _DBG_LEAVE_LVL( _DBG_LVL_FUNC_TRACE ); +} + +/* Assumes MulticastLock is Held */ +static +void +IssueMcGroupFabOp(MC_GROUP *pMcGroup, FABRIC_OPERATION_TYPE FabOpType) +{ + FSTATUS Status; + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, IssueMcGroupFabOp); + + if (pMcGroup->McGroupDelete == TRUE && pMcGroup->McGroupInUse == 0 ) + { + goto exit; + } + + //pMcGroup->McGroupInUse++; + + pMcGroup->FabOp.Type = FabOpType; + + pMcGroup->FabOp.Value.McMemberRecordValue.ComponentMask = pMcGroup->ComponentMask; + pMcGroup->FabOp.Value.McMemberRecordValue.McMemberRecord = pMcGroup->McMemberRecord; + + SpinLockRelease(&MulticastLock); + + Status = iba_sd_port_fabric_operation(McSdHandle, + pMcGroup->McGroupId.EgressPortGUID, + &pMcGroup->FabOp, + McGroupFabOpCallback, + NULL, + pMcGroup); + + SpinLockAcquire(&MulticastLock); + + if ((Status != FPENDING) && (Status != FSUCCESS)) + { + pMcGroup->McGroupInUse--; + /* Port may not yet be active. We'll get it later when it does go active */ + /* _DBG_ERROR(("PortFabricOperation Status = %d\n", Status)); */ + } + +exit: + _DBG_LEAVE_LVL( _DBG_LVL_FUNC_TRACE ); +} + +/* Assumes MulticastLock is Held */ +static +MC_GROUP* +FindMcGroupNext(IB_GID *pMGID, + MC_GROUP *pMcGroup) +{ + LIST_ITEM *pListItem; + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, FindMcGroupNext); + + _DBG_INFO(("looking for MGID:%"PRIx64" : %"PRIx64"\n", pMGID->AsReg64s.H, pMGID->AsReg64s.L)); + + pListItem = (pMcGroup == NULL) ? QListHead(&MasterMcGroupList) : QListNext(&MasterMcGroupList, &pMcGroup->ListItem); + + while (pListItem != NULL) + { + pMcGroup = (MC_GROUP *)QListObj(pListItem); + + ASSERT(pMcGroup != NULL); + + _DBG_INFO(("MGID:%"PRIx64" : %"PRIx64" PortGuid:%"PRIx64" inuse:%d\n", + pMcGroup->McMemberRecord.RID.MGID.AsReg64s.H, + pMcGroup->McMemberRecord.RID.MGID.AsReg64s.L, + pMcGroup->McMemberRecord.RID.PortGID.Type.Global.InterfaceID, + pMcGroup->McGroupInUse)); + + if (MemoryCompare(&pMcGroup->McGroupId.McRID.MGID, pMGID, sizeof(IB_GID)) == 0) + { + if (pMcGroup->McGroupDelete == FALSE) + { + _DBG_LEAVE_LVL( _DBG_LVL_FUNC_TRACE ); + return pMcGroup; + } + } + + pListItem = QListNext(&MasterMcGroupList, pListItem); + } + + _DBG_LEAVE_LVL( _DBG_LVL_FUNC_TRACE ); + return NULL; +} + +/* Assumes MulticastLock is Held */ +static +MC_GROUP* +FindMcGroup(MC_GROUP_ID *pMcGroupId) +{ + LIST_ITEM *pListItem; + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, FindMcGroup); + + _DBG_INFO(("looking for MGID:%"PRIx64" : %"PRIx64" PortGuid:%"PRIx64"\n", + pMcGroupId->McRID.MGID.AsReg64s.H, + pMcGroupId->McRID.MGID.AsReg64s.L, + pMcGroupId->McRID.PortGID.Type.Global.InterfaceID)); + for (pListItem = QListHead(&MasterMcGroupList); + pListItem != NULL; + pListItem = QListNext(&MasterMcGroupList, pListItem)) + { + MC_GROUP *pMcGroup = (MC_GROUP *)QListObj(pListItem); + + ASSERT(pMcGroup != NULL); + + _DBG_INFO(("MGID:%"PRIx64" : %"PRIx64" PortGuid:%"PRIx64" inuse:%d\n", + pMcGroup->McMemberRecord.RID.MGID.AsReg64s.H, + pMcGroup->McMemberRecord.RID.MGID.AsReg64s.L, + pMcGroup->McMemberRecord.RID.PortGID.Type.Global.InterfaceID, + pMcGroup->McGroupInUse)); + + if (MemoryCompare(&pMcGroup->McMemberRecord.RID, &pMcGroupId->McRID, sizeof(MC_RID)) == 0) + { + if (pMcGroup->McGroupDelete == FALSE) + { + _DBG_LEAVE_LVL( _DBG_LVL_FUNC_TRACE ); + return pMcGroup; + } + + break; + } + } + + _DBG_LEAVE_LVL( _DBG_LVL_FUNC_TRACE ); + return NULL; +} + +/* Assumes MulticastLock is Held */ +static +void +McMakeGroupsAvailable(EUI64 PortGuid) +{ + LIST_ITEM *pListItem; + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, McMakeGroupsAvailable); + + for (pListItem = QListHead(&MasterMcGroupList); + pListItem != NULL; + pListItem = QListNext(&MasterMcGroupList, pListItem)) + { + MC_GROUP *pMcGroup = (MC_GROUP*)QListObj(pListItem); + + ASSERT(pMcGroup != NULL); + + if (pMcGroup->McGroupDelete == FALSE) + { + if (PortGuid == pMcGroup->McGroupId.EgressPortGUID) + { + QueueSubnetDriverCall(pMcGroup, MC_GROUP_STATE_REQUEST_JOIN); + } + } + } + + _DBG_LEAVE_LVL( _DBG_LVL_FUNC_TRACE ); +} + +/* Assumes MulticastLock is Held */ +static +void +McMakeGroupsUnavailable(EUI64 PortGuid) +{ + LIST_ITEM *pListItem; + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, McMakeGroupsUnavailable); + + McLockAllGroups(); + + for (pListItem = QListHead(&MasterMcGroupList); + pListItem != NULL; + pListItem = QListNext(&MasterMcGroupList, pListItem)) + { + MC_GROUP *pMcGroup = (MC_GROUP*)QListObj(pListItem); + + ASSERT(pMcGroup != NULL); + + if (pMcGroup->McGroupDelete == FALSE) + { + if (PortGuid == pMcGroup->McGroupId.EgressPortGUID) + { + CallMcClients(pMcGroup, FUNAVAILABLE, MC_GROUP_STATE_UNAVAILABLE); + } + } + } + + McUnlockAllGroups(); + + _DBG_LEAVE_LVL( _DBG_LVL_FUNC_TRACE ); +} + +void +McPortNotifyCallback(IB_NOTIFY_RECORD *pNotifyRecord) +{ + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, PortNotifyCallback); + + if (McSdHandle != NULL) + { + SpinLockAcquire(&MulticastLock); + + switch(pNotifyRecord->EventType) + { + case IB_NOTIFY_LID_EVENT: + case IB_NOTIFY_SM_EVENT: + case IB_NOTIFY_PKEY_EVENT: + _DBG_INFO(("McPortNotifyCallback EventType:%d\n", + (int)pNotifyRecord->EventType)); + McMakeGroupsAvailable(pNotifyRecord->Guid); + break; + + case IB_NOTIFY_PORT_DOWN: + _DBG_INFO(("McPortNotifyCallback EventType PortDown\n")); + McMakeGroupsUnavailable(pNotifyRecord->Guid); + break; + + default: + break; + } + + SpinLockRelease(&MulticastLock); + } + + _DBG_LEAVE_LVL( _DBG_LVL_FUNC_TRACE ); +} + +static +void +McNoticeReportCallback( + void *pContext, + IB_NOTICE *pNotice, + EUI64 PortGuid + ) +{ + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, McNoticeReportCallback); + + if (McSdHandle != NULL) + { + SpinLockAcquire(&MulticastLock); + + switch(pNotice->u.Generic.TrapNumber) + { + case SMA_TRAP_ADD_MULTICAST_GROUP: + { + TRAP_66_DETAILS *pTrap66Details = (TRAP_66_DETAILS *)pNotice->Data; + MC_GROUP *pMcGroup = NULL; + while ((pMcGroup = FindMcGroupNext(&pTrap66Details->GIDAddress, pMcGroup)) != NULL) + { + QueueSubnetDriverCall(pMcGroup, MC_GROUP_STATE_REQUEST_JOIN); + } + break; + } + + case SMA_TRAP_DEL_MULTICAST_GROUP: + { + TRAP_67_DETAILS *pTrap67Details = (TRAP_67_DETAILS *)pNotice->Data; + MC_GROUP *pMcGroup = NULL; + while ((pMcGroup = FindMcGroupNext(&pTrap67Details->GIDAddress, pMcGroup)) != NULL) + { + _DBG_ERROR(("McNoticeReportCallback Mc Group (0x%016"PRIx64"%016"PRIx64") " + "Deleted By SM But We Still Have Connections.\n", + pTrap67Details->GIDAddress.AsReg64s.H, + pTrap67Details->GIDAddress.AsReg64s.L)); + } + break; + } + + default: + /* shouldn't ever happend */ + _DBG_ERROR(("McNoticeReportCallback: Unknown Notification Trap Number %d", + pNotice->u.Generic.TrapNumber)); + } + + SpinLockRelease(&MulticastLock); + } + + _DBG_LEAVE_LVL( _DBG_LVL_FUNC_TRACE ); +} + +static +void +IssueSubnetDriverCall( + void *pContext + ) +{ + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, IssueSubnetDriverCall); + + if (McSdHandle != NULL) + { + MC_GROUP *pMcGroup = (MC_GROUP*)pContext; + FABRIC_OPERATION_TYPE FabOpType; + + ASSERT(pMcGroup != NULL); + + SpinLockAcquire(&MulticastLock); + if (TimerCallbackStopped(&pMcGroup->Timer)) + goto unlock; // stale timer callback + + pMcGroup->TimerActive = FALSE; + + //pMcGroup->McGroupInUse--; + + switch(pMcGroup->McGroupState) + { + case MC_GROUP_STATE_REQUEST_JOIN: + _DBG_INFO(("issuing FabOpSetmember MGID:%"PRIx64" : %"PRIx64" PortGuid:%"PRIx64" inuse:%d\n", + pMcGroup->McMemberRecord.RID.MGID.AsReg64s.H, + pMcGroup->McMemberRecord.RID.MGID.AsReg64s.L, + pMcGroup->McMemberRecord.RID.PortGID.Type.Global.InterfaceID, + pMcGroup->McGroupInUse)); + FabOpType = FabOpSetMcMemberRecord; + break; + + case MC_GROUP_STATE_REQUEST_LEAVE: + _DBG_INFO(("issuing FabOpDeleteMcMember MGID:%"PRIx64" : %"PRIx64" PortGuid:%"PRIx64" inuse:%d\n", + pMcGroup->McMemberRecord.RID.MGID.AsReg64s.H, + pMcGroup->McMemberRecord.RID.MGID.AsReg64s.L, + pMcGroup->McMemberRecord.RID.PortGID.Type.Global.InterfaceID, + pMcGroup->McGroupInUse)); + FabOpType = FabOpDeleteMcMemberRecord; + break; + + case MC_GROUP_STATE_JOIN_FAILED: + case MC_GROUP_STATE_AVAILABLE: + case MC_GROUP_STATE_UNAVAILABLE: + default: + // Gets rid of compiler warning + _DBG_INFO(("issuing FabOpDeleteMcMember(2) MGID:%"PRIx64" : %"PRIx64" PortGuid:%"PRIx64" inuse:%d\n", + pMcGroup->McMemberRecord.RID.MGID.AsReg64s.H, + pMcGroup->McMemberRecord.RID.MGID.AsReg64s.L, + pMcGroup->McMemberRecord.RID.PortGID.Type.Global.InterfaceID, + pMcGroup->McGroupInUse)); + FabOpType = FabOpDeleteMcMemberRecord; + break; + } + + IssueMcGroupFabOp(pMcGroup, FabOpType); + +unlock: + SpinLockRelease(&MulticastLock); + } + _DBG_LEAVE_LVL( _DBG_LVL_FUNC_TRACE ); +} + +/* Assumes MulticastLock is Held */ +static +MC_CLIENT* +FindMcClient( + CLIENT_HANDLE SdClientHandle, + MC_GROUP_ID *pMcGroupId + ) +{ + LIST_ITEM *pListItem; + size_t compareSize; + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, FindMcClient); + + compareSize = (pMcGroupId->JoinVersion == 1) ? sizeof(int) + sizeof(IB_GID) : sizeof(MC_GROUP_ID); + + for (pListItem = QListHead(&MasterMcClientList); + pListItem != NULL; + pListItem = QListNext(&MasterMcClientList, pListItem)) + { + MC_CLIENT *pMcClient = (MC_CLIENT *)QListObj(pListItem); + + if ((pMcClient->SdClientHandle == SdClientHandle) && + (pMcClient->pMcGroup != NULL) && + (MemoryCompare(&pMcGroupId, &pMcClient->pMcGroup->McGroupId, compareSize) == 0)) + { + return pMcClient; + } + } + + _DBG_LEAVE_LVL( _DBG_LVL_FUNC_TRACE ); + + return NULL; +} + +/* Assumes MulticastLock is Held */ +static __inline +boolean +McJoinFlagsAdjusted( + MC_GROUP *pMcGroup, + IB_MCMEMBER_RECORD *pMcMemberRecord + ) +{ + boolean FlagsAdjusted = FALSE; + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, McJoinFlagsAdjusted); + + //Adjust the join/leave flags + if (!pMcGroup->McMemberRecord.JoinFullMember) + { + if (pMcMemberRecord->JoinFullMember) + { + pMcGroup->McMemberRecord.JoinFullMember = 1; + FlagsAdjusted = TRUE; + } + } + + if (!pMcGroup->McMemberRecord.JoinNonMember) + { + if (pMcMemberRecord->JoinNonMember) + { + pMcGroup->McMemberRecord.JoinNonMember = 1; + FlagsAdjusted = TRUE; + } + } + + if (!pMcGroup->McMemberRecord.JoinSendOnlyMember) + { + if (pMcMemberRecord->JoinSendOnlyMember) + { + pMcGroup->McMemberRecord.JoinSendOnlyMember = 1; + FlagsAdjusted = TRUE; + } + } + + _DBG_LEAVE_LVL( _DBG_LVL_FUNC_TRACE ); + + return FlagsAdjusted; +} + + +static +void +McSubscribeForTraps(void) +{ + uint32 PortIndex; + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, McSubscribeForTraps); + + for (PortIndex = 0; PortIndex < NumTotalPorts; PortIndex++) + { + FSTATUS Status; + + Status = iba_sd_trap_notice_subscribe(McSdHandle, + SMA_TRAP_ADD_MULTICAST_GROUP, + pLocalCaGuidList[PortIndex], + NULL, + McNoticeReportCallback); + if (Status != FSUCCESS) + { + _DBG_ERROR(("Cannot Subscribe For Trap " + "SMA_TRAP_ADD_MULTICAST_GROUP.\n")); + break; + } + + Status = iba_sd_trap_notice_subscribe(McSdHandle, + SMA_TRAP_DEL_MULTICAST_GROUP, + pLocalCaGuidList[PortIndex], + NULL, + McNoticeReportCallback); + if (Status != FSUCCESS) + { + _DBG_ERROR(("Cannot Subscribe For Trap " + "SMA_TRAP_DEL_MULTICAST_GROUP.\n")); + break; + } + } + + _DBG_LEAVE_LVL( _DBG_LVL_FUNC_TRACE ); +} + +static +void +McUnsubscribeForTraps(void) +{ + uint32 PortIndex; + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, McUnSubscribeForTraps); + + for (PortIndex = 0; PortIndex < NumTotalPorts; PortIndex++) + { + FSTATUS Status; + + Status = iba_sd_trap_notice_unsubscribe(McSdHandle, + SMA_TRAP_ADD_MULTICAST_GROUP, + pLocalCaGuidList[PortIndex]); + if (Status != FSUCCESS) + { + _DBG_ERROR(("Cannot Unsubscribe For Trap " + "SMA_TRAP_ADD_MULTICAST_GROUP.\n")); + } + + Status = iba_sd_trap_notice_unsubscribe(McSdHandle, + SMA_TRAP_DEL_MULTICAST_GROUP, + pLocalCaGuidList[PortIndex]); + if (Status != FSUCCESS) + { + _DBG_ERROR(("Cannot Unsubscribe For Trap " + "SMA_TRAP_DEL_MULTICAST_GROUP.\n")); + } + } + + _DBG_LEAVE_LVL( _DBG_LVL_FUNC_TRACE ); +} + +static +FSTATUS +IncrementMcGroupUsageCount(CLIENT_HANDLE SdClientHandle, + void *pContext, + SD_MULTICAST_CALLBACK *pMulticastCallback, + uint16 McFlags, + uint64 ComponentMask, + IB_MCMEMBER_RECORD *pMcMemberRecord, + MC_GROUP_ID *pMcGroupId) +{ + MC_CLIENT *pMcClientTemp; + MC_CLIENT *pMcClient = NULL; + MC_GROUP *pMcGroupTemp; + MC_GROUP *pMcGroup = NULL; + boolean StartTrapNotification; + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, IncrementMcGroupUsageCount); + + /* Allocate Everything up front to avoid locking issues */ + pMcClientTemp = (MC_CLIENT *)MemoryAllocate2AndClear(sizeof(MC_CLIENT), IBA_MEM_FLAG_NONE, SUBNET_DRIVER_TAG); + if (pMcClientTemp == NULL) + { + _DBG_LEAVE_LVL( _DBG_LVL_FUNC_TRACE ); + return FINSUFFICIENT_MEMORY; + } + + pMcClientTemp->SdClientHandle = SdClientHandle; + pMcClientTemp->pContext = pContext; + pMcClientTemp->McFlags = McFlags; + pMcClientTemp->pMulticastCallback = pMulticastCallback; + + pMcGroupTemp = (MC_GROUP*)MemoryAllocate2AndClear(sizeof(MC_GROUP), IBA_MEM_FLAG_SHORT_DURATION, SUBNET_DRIVER_TAG); + if (pMcGroupTemp == NULL) + { + _DBG_ERROR(("IncrementMcGroupUsageCount MemoryAllocateError\n")); + MemoryDeallocate(pMcClientTemp); + _DBG_LEAVE_LVL( _DBG_LVL_FUNC_TRACE ); + return FINSUFFICIENT_MEMORY; + } + + SpinLockAcquire(&MulticastLock); + + pMcClient = FindMcClient(SdClientHandle, pMcGroupId); + if (pMcClient == NULL) + { + pMcClient= pMcClientTemp; + pMcClientTemp = NULL; + } + else + { + _DBG_ERROR(("IncrementMcGroupUsageCount Client already exists.\n")); + /*SpinLockRelease(&MulticastLock); + MemoryDeallocate(pMcGroupTemp); + MemoryDeallocate(pMcClient); + _DBG_LEAVE_LVL( _DBG_LVL_FUNC_TRACE ); + return FDUPLICATE;*/ + // continue anyway + } + + StartTrapNotification = QListIsEmpty(&MasterMcGroupList); + + pMcGroup = FindMcGroup(pMcGroupId); + if (pMcGroup == NULL) + { + // didn't find Mcgroup in list, let us add one + pMcGroupTemp->McGroupState = MC_GROUP_STATE_REQUEST_JOIN; + pMcGroupTemp->ComponentMask = ComponentMask; + pMcGroupTemp->McMemberRecord = *pMcMemberRecord; + pMcGroupTemp->McGroupId = *pMcGroupId; + QListInit(&pMcGroupTemp->McClientList); + QListSetObj(&pMcGroupTemp->ListItem, pMcGroupTemp); + + pMcGroup = pMcGroupTemp; + pMcGroupTemp = NULL; + + QListInsertTail(&MasterMcGroupList, &pMcGroup->ListItem); + + TimerInitState(&pMcGroup->Timer); + TimerInit(&pMcGroup->Timer, IssueSubnetDriverCall, pMcGroup ); + } + else + { + // group already exists - check state + if ( (pMcGroup->McGroupState != MC_GROUP_STATE_REQUEST_JOIN) && + (pMcGroup->McGroupState != MC_GROUP_STATE_AVAILABLE) ) + { + if (pMcGroup->McGroupState == MC_GROUP_STATE_JOIN_FAILED) + { + _DBG_ERROR(("Prior attempt to join Multicast Group failed\n")); + } + else + { + _DBG_ERROR(("IncrementMcGroupUsageCount McGroup invalid state:%d.\n", + pMcGroup->McGroupState)); + } + SpinLockRelease(&MulticastLock); + MemoryDeallocate(pMcGroupTemp); + if(pMcClientTemp) + MemoryDeallocate(pMcClientTemp); + _DBG_LEAVE_LVL( _DBG_LVL_FUNC_TRACE ); + return FDUPLICATE; + } + } + + pMcClient->pMcGroup = pMcGroup; + + QListSetObj(&pMcClient->ListItem, pMcClient); + QListInsertTail(&MasterMcClientList, &pMcClient->ListItem); + + QListSetObj(&pMcClient->McGroupListItem, pMcClient); + QListInsertTail(&pMcGroup->McClientList, &pMcClient->McGroupListItem); + + if (pMcGroupTemp == NULL) + { + /* First client joining the group - Get The Process Started */ + _DBG_INFO(("new mcgroup - queuing join\n")); + QueueSubnetDriverCall(pMcGroup, MC_GROUP_STATE_REQUEST_JOIN); + } + else + { + _DBG_INFO(("existing mcgroup - checking flags %d\n", + pMcGroup->McGroupState)); + if ((McJoinFlagsAdjusted(pMcGroup, pMcMemberRecord) == TRUE) && + (pMcGroup->McGroupState == MC_GROUP_STATE_AVAILABLE)) // TODO: Check Concurrency Here + /* we had already joined and the flags changes - so rejoin */ + { + _DBG_INFO(("flags changed after we joined - rejoining \n")); + QueueSubnetDriverCall(pMcGroup, MC_GROUP_STATE_REQUEST_JOIN); + } + else if (pMcGroup->McGroupState == MC_GROUP_STATE_AVAILABLE) + { + // we already had joined but we got a new client - issue callbacks + _DBG_INFO(("someone joined when state is available - issuing callbacks \n")); + CallMcClients(pMcGroup, FSUCCESS, MC_GROUP_STATE_AVAILABLE); + } + // NOTE if state is JOIN, then when that completes all clients + // including new one will be notified via callback + } + + if (MaintenanceTimerActivated == FALSE) + { + MaintenanceTimerActivated = TRUE; + TimerStart(&MaintenanceTimer, 5000); + } + + SpinLockRelease(&MulticastLock); + + if (StartTrapNotification) + { + McSubscribeForTraps(); + } + + if (pMcGroupTemp) + { + TimerDestroy(&pMcGroupTemp->Timer); + QListDestroy(&pMcGroupTemp->McClientList); + MemoryDeallocate(pMcGroupTemp); + } + + if (pMcClientTemp) + { + MemoryDeallocate(pMcClientTemp); + } + + _DBG_LEAVE_LVL( _DBG_LVL_FUNC_TRACE ); + + return FSUCCESS; +} + +static +FSTATUS +DecrementMcGroupUsageCount(CLIENT_HANDLE SdClientHandle, MC_GROUP_ID *pMcGroupId) +{ + FSTATUS Status = FSUCCESS; + MC_CLIENT *pMcClient; + MC_GROUP *pMcGroup; + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, DecrementMcGroupUsageCount); + + SpinLockAcquire(&MulticastLock); + + pMcClient = FindMcClient(SdClientHandle, pMcGroupId); + if (pMcClient == NULL) + { + Status = FNOT_FOUND; + SpinLockRelease(&MulticastLock); + _DBG_ERROR(("DecrementMcGroupUsageCount Client Not Found.\n")); + goto exit; + } + + pMcGroup = pMcClient->pMcGroup; + pMcClient->pMcGroup = NULL; + pMcClient->McClientDelete = TRUE; + + QListRemoveItem(&pMcGroup->McClientList, &pMcClient->McGroupListItem); + if (QListIsEmpty(&pMcGroup->McClientList)) + { + /* schedule the group removal in Maintenance thread */ + pMcGroup->McGroupDelete = TRUE; + + if (pMcGroup->McGroupState == MC_GROUP_STATE_AVAILABLE) + { + QueueSubnetDriverCall(pMcGroup, MC_GROUP_STATE_REQUEST_LEAVE); + } + } + + SpinLockRelease(&MulticastLock); + +exit: + _DBG_LEAVE_LVL( _DBG_LVL_FUNC_TRACE ); + + return Status; +} + +static +void +McMaintenance(void *pContext) +{ + LIST_ITEM *pListItem; + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, McMaintenance); + + if (McSdHandle != NULL) + { + SpinLockAcquire(&MulticastLock); + + if (TimerCallbackStopped(&MaintenanceTimer)) + { + // stale timer callback + SpinLockRelease(&MulticastLock); + goto done; + } + + // Loop Through MasterMcClientList + + pListItem = QListHead(&MasterMcClientList); + + while(pListItem != NULL) + { + MC_CLIENT *pMcClient = (MC_CLIENT *)QListObj(pListItem); + + ASSERT(pMcClient != NULL); + + pListItem = QListNext(&MasterMcClientList, pListItem); + + if ((pMcClient->McClientDelete == TRUE) && + (pMcClient->McClientInUse == 0)) + { + QListRemoveItem(&MasterMcClientList, &pMcClient->ListItem); + SpinLockRelease(&MulticastLock); + MemoryDeallocate(pMcClient); + if (McSdHandle == NULL) + { + break; + } + SpinLockAcquire(&MulticastLock); + } + } + } + + if (McSdHandle != NULL) + { + // Loop Through MasterMcGroupList + + pListItem = QListHead(&MasterMcGroupList); + + while(pListItem != NULL) + { + MC_GROUP *pMcGroup = (MC_GROUP *)QListObj(pListItem); + + ASSERT(pMcGroup != NULL); + + pListItem = QListNext(&MasterMcGroupList, pListItem); + + if ((pMcGroup->McGroupDelete == TRUE) && + (pMcGroup->McGroupInUse == 0)) + { + TimerDestroy(&pMcGroup->Timer); + QListDestroy(&pMcGroup->McClientList); + QListRemoveItem(&MasterMcGroupList, &pMcGroup->ListItem); + SpinLockRelease(&MulticastLock); + MemoryDeallocate(pMcGroup); + if (McSdHandle == NULL) + { + break; + } + SpinLockAcquire(&MulticastLock); + } + } + } + + if (McSdHandle != NULL) + { + if (!QListIsEmpty(&MasterMcGroupList) || + !QListIsEmpty(&MasterMcClientList)) + { + /* Only Start It If There Is A Possibility Of Something To Do */ + TimerStart(&MaintenanceTimer, 5000); + SpinLockRelease(&MulticastLock); + } + else + { + McUnsubscribeForTraps(); + MaintenanceTimerActivated = FALSE; + SpinLockRelease(&MulticastLock); + } + } + +done: + _DBG_LEAVE_LVL( _DBG_LVL_FUNC_TRACE ); +} + +FSTATUS +MulticastInitialize(void) +{ + FSTATUS Status; + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, InitializeMulticast); + + McSdHandle = NULL; + + QListInit(&MasterMcGroupList); + QListInit(&MasterMcClientList); + SpinLockInitState(&MulticastLock); + SpinLockInit(&MulticastLock); + + TimerInitState(&MaintenanceTimer); + TimerInit(&MaintenanceTimer, McMaintenance, NULL); + + MaintenanceTimerActivated = FALSE; + + Status = iba_sd_register(&McSdHandle, NULL); + if (Status != FSUCCESS) + { + McSdHandle = NULL; + _DBG_ERROR(("Multicast Module Not Able To Register With Subnet Driver " + "Status = %d.\n", Status)); + } + + _DBG_LEAVE_LVL( _DBG_LVL_FUNC_TRACE ); + + return Status; +} + +FSTATUS +MulticastTerminate(void) +{ + FSTATUS Status; + CLIENT_HANDLE McSdHandleTemp; + LIST_ITEM *pListItem; + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, MulticastTerminate); + + /* Just in case maintenance routine is running */ + SpinLockAcquire(&MulticastLock); + McSdHandleTemp = McSdHandle; + McSdHandle = NULL; + SpinLockRelease(&MulticastLock); + + if (McSdHandleTemp == NULL) + { + _DBG_ERROR(("Multicast Module Not A Registered Subnet Driver " + "Client Process.\n")); + Status = FINVALID_STATE; + goto exit; + } + + if (MaintenanceTimerActivated == TRUE) + { + TimerStop(&MaintenanceTimer); + MaintenanceTimerActivated = FALSE; + } + + Status = iba_sd_deregister(McSdHandleTemp); + if (Status != FSUCCESS) { + _DBG_ERROR(("Cannot Deregister With " + "Subnet Data Interface.\n")); + } + + for (pListItem = QListRemoveHead(&MasterMcGroupList); + pListItem != NULL; + pListItem = QListRemoveHead(&MasterMcGroupList)) + { + MC_GROUP *pMcGroup = (MC_GROUP *)QListObj(pListItem); + + ASSERT(pMcGroup != NULL); + + TimerStop(&pMcGroup->Timer); + TimerDestroy(&pMcGroup->Timer); + QListDestroy(&pMcGroup->McClientList); + MemoryDeallocate(pMcGroup); + } + + for (pListItem = QListRemoveHead(&MasterMcClientList); + pListItem != NULL; + pListItem = QListRemoveHead(&MasterMcClientList)) + { + MC_CLIENT *pMcClient = (MC_CLIENT *)QListObj(pListItem); + + ASSERT(pMcClient != NULL); + + MemoryDeallocate(pMcClient); + } + + QListDestroy(&MasterMcGroupList); + QListDestroy(&MasterMcClientList); + TimerDestroy(&MaintenanceTimer); + SpinLockDestroy(&MulticastLock); + +exit: + _DBG_LEAVE_LVL( _DBG_LVL_FUNC_TRACE ); + + return Status; +} + +static +FSTATUS +McJoinGroup( + CLIENT_HANDLE SdClientHandle, + uint16 McFlags, + uint64 ComponentMask, + IB_MCMEMBER_RECORD *pMcMemberRecord, + MC_GROUP_ID *pMcGroupId, + void *pContext, + SD_MULTICAST_CALLBACK *pMulticastCallback + ) +{ + FSTATUS Status; + CLIENT_CONTROL_PARAMETERS ClientParams; + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, McJoinGroup); + + if (McSdHandle == NULL) + { + _DBG_ERROR(("Multicast Module Not A Registered Subnet Driver " + "Client Process.\n")); + Status = FINVALID_STATE; + goto exit; + } + + Status = ValidateClientHandle(SdClientHandle, &ClientParams); + if (Status != FSUCCESS) + { + _DBG_ERROR(("Invalid Client Handle Specified\n")); + goto exit; + } + + Status = IncrementMcGroupUsageCount(SdClientHandle, + pContext, + pMulticastCallback, + McFlags, + ComponentMask, + pMcMemberRecord, + pMcGroupId); + +exit: + _DBG_LEAVE_LVL( _DBG_LVL_FUNC_TRACE ); + + return Status; +} + +FSTATUS +iba_sd_join_mcgroup2( + CLIENT_HANDLE SdClientHandle, + uint16 McFlags, + uint64 ComponentMask, + IB_MCMEMBER_RECORD *pMcMemberRecord, + EUI64 EgressPortGUID, + void *pContext, + SD_MULTICAST_CALLBACK *pMulticastCallback + ) +{ + FSTATUS Status; + MC_GROUP_ID McGroupId; + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, iba_sd_join_mcgroup2); + + McGroupId.JoinVersion = 2; + McGroupId.McRID.MGID = pMcMemberRecord->RID.MGID; + McGroupId.McRID.PortGID = pMcMemberRecord->RID.PortGID; + McGroupId.EgressPortGUID = EgressPortGUID; + + Status = McJoinGroup(SdClientHandle, + McFlags, + ComponentMask, + pMcMemberRecord, + &McGroupId, + pContext, + pMulticastCallback); + + _DBG_LEAVE_LVL( _DBG_LVL_FUNC_TRACE ); + + return Status; +} + +FSTATUS +iba_sd_join_mcgroup( + CLIENT_HANDLE SdClientHandle, + uint16 McFlags, + uint64 ComponentMask, + IB_MCMEMBER_RECORD *pMcMemberRecord, + void *pContext, + SD_MULTICAST_CALLBACK *pMulticastCallback + ) +{ + FSTATUS Status; + MC_GROUP_ID McGroupId; + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, iba_sd_join_mcgroup); + + McGroupId.JoinVersion = 1; + McGroupId.McRID.MGID = pMcMemberRecord->RID.MGID; + McGroupId.McRID.PortGID = pMcMemberRecord->RID.PortGID; + McGroupId.EgressPortGUID = pMcMemberRecord->RID.PortGID.Type.Global.InterfaceID; + + Status = McJoinGroup(SdClientHandle, + McFlags, + ComponentMask, + pMcMemberRecord, + &McGroupId, + pContext, + pMulticastCallback); + + _DBG_LEAVE_LVL( _DBG_LVL_FUNC_TRACE ); + + return Status; +} + +static +FSTATUS +McLeaveGroup( + CLIENT_HANDLE SdClientHandle, + MC_GROUP_ID *pMcGroupId + ) +{ + FSTATUS Status; + CLIENT_CONTROL_PARAMETERS ClientParams; + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, McLeaveGroup); + + if (McSdHandle == NULL) + { + _DBG_ERROR(("Multicast Module Not A Registered Subnet Driver " + "Client Process.\n")); + Status = FINVALID_STATE; + goto exit; + } + + Status = ValidateClientHandle(SdClientHandle, &ClientParams); + if (Status != FSUCCESS) + { + _DBG_ERROR(("Invalid Client Handle Specified\n")); + goto exit; + } + + Status = DecrementMcGroupUsageCount(SdClientHandle, pMcGroupId); + if (Status == FPENDING) + { + Status = FSUCCESS; + } + +exit: + _DBG_LEAVE_LVL( _DBG_LVL_FUNC_TRACE ); + + return Status; +} + +FSTATUS +iba_sd_leave_mcgroup2( + CLIENT_HANDLE SdClientHandle, + IB_GID *pMGID, + IB_GID *pPortGID, + EUI64 EgressPortGUID + ) +{ + FSTATUS Status; + MC_GROUP_ID McGroupId; + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, iba_sd_leave_mcgroup2); + + McGroupId.JoinVersion = 2; + McGroupId.McRID.MGID = *pMGID; + McGroupId.McRID.PortGID = *pPortGID; + McGroupId.EgressPortGUID = EgressPortGUID; + + Status = McLeaveGroup(SdClientHandle, &McGroupId); + + _DBG_LEAVE_LVL( _DBG_LVL_FUNC_TRACE ); + + return Status; +} + +FSTATUS +iba_sd_leave_mcgroup( + CLIENT_HANDLE SdClientHandle, + IB_GID *pMGID + ) +{ + FSTATUS Status; + MC_GROUP_ID McGroupId; + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, iba_sd_leave_mcgroup); + + MemoryClear(&McGroupId, sizeof(McGroupId)); + McGroupId.JoinVersion = 1; + McGroupId.McRID.MGID = *pMGID; + + Status = McLeaveGroup(SdClientHandle, &McGroupId); + + _DBG_LEAVE_LVL( _DBG_LVL_FUNC_TRACE ); + + return Status; +} diff --git a/IbAccess/Common/SubnetDriver/multicast.h b/IbAccess/Common/SubnetDriver/multicast.h new file mode 100644 index 0000000..f303d74 --- /dev/null +++ b/IbAccess/Common/SubnetDriver/multicast.h @@ -0,0 +1,53 @@ +/* BEGIN_ICS_COPYRIGHT5 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + * ** END_ICS_COPYRIGHT5 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +#ifndef _MULTICAST_H +#define _MULTICAST_H + +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +FSTATUS MulticastInitialize(void); +FSTATUS MulticastTerminate(void); + +void McPortNotifyCallback(IB_NOTIFY_RECORD *pNotifyRecord); + +#ifdef __cplusplus +} +#endif + +#endif /* _MULTICAST_H */ diff --git a/IbAccess/Common/SubnetDriver/query.c b/IbAccess/Common/SubnetDriver/query.c new file mode 100644 index 0000000..ae577ac --- /dev/null +++ b/IbAccess/Common/SubnetDriver/query.c @@ -0,0 +1,2057 @@ +/* BEGIN_ICS_COPYRIGHT4 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT4 ****************************************/ + + +#include +#include +#include +#include +#include +#include +#include + +LOCKED_QUICK_LIST *pQueryList = NULL; +LOCKED_QUICK_LIST *pCompletionList = NULL; +LOCKED_QUICK_LIST *pChildQueryList = NULL; +ATOMIC_UINT ChildQueryActive; + +MUTEX *pChildGrowParentMutex; + +ATOMIC_UINT TranId; + +#define PATHRECORD_NUMBPATH 32 // max to request given 2 guids + +void +FillBaseGmpValues( + IN PQueryDetails piQuery + ); + +FSTATUS +FillSADetailsForNodeRecord( + IN PQueryDetails pQueryElement, + IN uint32 MemAllocFlags + ); + +FSTATUS +FillSADetailsForPortInfoRecord( + IN PQueryDetails pQueryElement, + IN uint32 MemAllocFlags + ); + +FSTATUS +FillSADetailsForSMInfoRecord( + IN PQueryDetails pQueryElement, + IN uint32 MemAllocFlags + ); + +FSTATUS +FillSADetailsForLinkRecord( + IN PQueryDetails pQueryElement, + IN uint32 MemAllocFlags + ); + +FSTATUS +FillSADetailsForPathRecord( + IN PQueryDetails pQueryElement, + IN uint32 MemAllocFlags + ); + +FSTATUS +FillSADetailsForServiceRecord( + IN PQueryDetails pQueryElement, + IN uint32 MemAllocFlags + ); + +FSTATUS +FillSADetailsForMcMemberRecord( + IN PQueryDetails pQueryElement, + IN uint32 MemAllocFlags + ); + +FSTATUS +FillSADetailsForInformInfoRecord( + IN PQueryDetails pQueryElement, + IN uint32 MemAllocFlags + ); + +FSTATUS +FillSADetailsForInformInfo( + IN PQueryDetails pQueryElement, + IN uint32 MemAllocFlags + ); + +FSTATUS +FillSADetailsForMultiPathRecord( + IN PQueryDetails pQueryElement, + IN uint32 MemAllocFlags + ); + +FSTATUS +FillSADetailsForTraceRecord( + PQueryDetails pQueryElement, + uint32 MemAllocFlags + ); + +FSTATUS +FillSADetailsForSwitchInfoRecord( + PQueryDetails pQueryElement, + uint32 MemAllocFlags + ); + +FSTATUS +FillSADetailsForLinearFDBRecord( + PQueryDetails pQueryElement, + uint32 MemAllocFlags + ); + +FSTATUS +FillSADetailsForRandomFDBRecord( + PQueryDetails pQueryElement, + uint32 MemAllocFlags + ); + +FSTATUS +FillSADetailsForMCastFDBRecord( + PQueryDetails pQueryElement, + uint32 MemAllocFlags + ); + +FSTATUS +FillSADetailsForVLArbTableRecord( + PQueryDetails pQueryElement, + uint32 MemAllocFlags + ); + +FSTATUS +FillSADetailsForPKeyTableRecord( + PQueryDetails pQueryElement, + uint32 MemAllocFlags + ); + +void +FillCommonSADetails( + IN PQueryDetails pQueryElement, + IN uint16 AttribId, + IN uint32 RecordSize + ); + +FSTATUS +BuildCommonSAMad( + IN PQueryDetails pQueryElement, + IN uint16 AttribId, + IN uint32 RecordSize, + IN uint32 MemAllocFlags + ); + +#if 0 // keep this around in case we need it for debugging again +void QueryShowPacket(char *msg, unsigned char *packet, int length) +{ + _DBG_DUMP_MEMORY(_DBG_LVL_?, ("%s", msg), (void*)packet, length); +} +#endif + +FSTATUS +InitializeList( + QUICK_LIST **ppList, + SPIN_LOCK **ppListLock +) +{ + FSTATUS Fstatus = FSUCCESS; + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, InitializeList); + + *ppList = (QUICK_LIST*)MemoryAllocateAndClear(sizeof(QUICK_LIST), FALSE, + SUBNET_DRIVER_TAG); + *ppListLock = (SPIN_LOCK*)MemoryAllocateAndClear(sizeof(SPIN_LOCK), FALSE, + SUBNET_DRIVER_TAG); + + if ((*ppList == NULL) || (*ppListLock == NULL)) + { + _DBG_ERROR(("Cannot allocate global query list\n")); + Fstatus = FINSUFFICIENT_MEMORY; + goto failalloc; + } + + QListInitState(*ppList); + if (!QListInit(*ppList)) + { + _DBG_ERROR(("Cannot intialize query list, exiting\n")); + Fstatus = FERROR; + goto faillist; + } + + // Initialize the the control lock for the query list + SpinLockInitState(*ppListLock); + if (!SpinLockInit(*ppListLock)) + { + _DBG_ERROR(("Cannot initialize query list lock\n")); + Fstatus = FERROR; + goto faillock; + } + + _DBG_LEAVE_LVL( _DBG_LVL_FUNC_TRACE ); + return(FSUCCESS); + +faillock: + QListDestroy(*ppList); +faillist: +failalloc: + if (*ppListLock != NULL) + { + MemoryDeallocate(*ppListLock); + *ppListLock = NULL; + } + if (*ppList != NULL) + { + MemoryDeallocate(*ppList); + *ppList = NULL; + } + _DBG_LEAVE_LVL( _DBG_LVL_FUNC_TRACE ); + return(Fstatus); +} + + +void +DestroyList( + QUICK_LIST *pList, + SPIN_LOCK *pListLock + ) +{ + void * pListEntry; + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, DestroyList); + + if (pListLock != NULL) + { + //Destroy the List + SpinLockAcquire(pListLock); + while(NULL != (pListEntry = (void *)QListRemoveHead(pList))) + { + MemoryDeallocate(pListEntry); + } + QListDestroy(pList); + SpinLockRelease(pListLock); + + MemoryDeallocate(pList); + + //Destroy the Lock + SpinLockDestroy(pListLock); + MemoryDeallocate(pListLock); + } + + _DBG_LEAVE_LVL( _DBG_LVL_FUNC_TRACE ); +} + + +void +FillBaseGmpValues( + IN PQueryDetails piQuery + ) +{ + uint64 TempTranId; + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, FillBaseGmpValues); + + piQuery->u.pGmp->common.BaseVersion = IB_BASE_VERSION; + piQuery->u.pGmp->common.MgmtClass = MCLASS_SUBN_ADM; + piQuery->u.pGmp->common.ClassVersion = IB_SUBN_ADM_CLASS_VERSION; + TempTranId = (uint64)AtomicIncrement(&TranId); + piQuery->u.pGmp->common.TransactionID = TempTranId << 8; + _DBG_INFO(("The TransactionID stored is <%"PRIx64">\n", TempTranId)); + _DBG_LEAVE_LVL( _DBG_LVL_FUNC_TRACE ); +} + +// verify the ClientHandle is valid and return the corresponding +// ClientControlParams +FSTATUS ValidateClientHandle( + IN CLIENT_HANDLE ClientHandle, + OUT CLIENT_CONTROL_PARAMETERS *pClientParams + ) +{ + FSTATUS Fstatus = FNOT_FOUND; + LIST_ITEM *pListItem; + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, ValidateClientHandle); + if(ClientHandle == NULL) + { + //Handle the case for invalid parameters + _DBG_ERROR(("Client handle is a null value\n")); + Fstatus = FINVALID_PARAMETER; + goto done; + } + pListItem = &((ClientListEntry*)ClientHandle)->ListItem; + + SpinLockAcquire(pClientListLock); + if (QListIsItemInList(pClientList, pListItem)) + { + ClientListEntry *pClientEntry = (ClientListEntry*)ClientHandle; + + Fstatus = FSUCCESS; + // Get the client control parameters + *pClientParams = pClientEntry->ClientParameters; + } + SpinLockRelease(pClientListLock); +done: + _DBG_LEAVE_LVL( _DBG_LVL_FUNC_TRACE ); + return Fstatus; +} + +// check if port is valid and active +// if *pPortGuid == (EUI64)-1, 1st active port is returned in *pPortGuid +FSTATUS CheckPortActive( + IN OUT EUI64 *pPortGuid + ) +{ + uint64 *pLocalPortGuidsList = NULL; + uint32 LocalPortGuidsCount; + uint32 ii; + FSTATUS Fstatus; + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, CheckPortActive); + /* Get List Of Active Port Guids */ + Fstatus = iba_sd_get_local_port_guids_alloc(&pLocalPortGuidsList, &LocalPortGuidsCount); + if (Fstatus != FSUCCESS || LocalPortGuidsCount == 0) + { + _DBG_INFO(("No Active LocalPortGuids found\n")); + if (Fstatus == FSUCCESS) + Fstatus = FNOT_FOUND; + goto done; + } + + /* Look to see if we are to use the first active port */ + if (*pPortGuid == (EUI64)-1) + { + *pPortGuid = pLocalPortGuidsList[0]; + } else { + /* Check to see if it's active */ + for (ii = 0; (ii < LocalPortGuidsCount); ++ii) + { + if (*pPortGuid == pLocalPortGuidsList[ii]) + break; + } + + if (ii == LocalPortGuidsCount) + { + /* It's not active now */ + Fstatus = FNOT_FOUND; + _DBG_INFO(("LocalPortGuid <0x%"PRIx64"> Not Currently Active.\n", *pPortGuid)); + goto done; + } + } + +done: + if (pLocalPortGuidsList != NULL) + { + MemoryDeallocate(pLocalPortGuidsList); + } + _DBG_LEAVE_LVL( _DBG_LVL_FUNC_TRACE ); + return Fstatus; +} + + +// lookup an appropriate subnet prefix for a port +// if the PortGuid is local we use its SubnetPrefix +// otherwise we use the SubnetPrefix of the port the query is going to +// be issued from +uint64 GetSubnetPrefixForPortGuid( + EUI64 QueryPortGuid, // local port query will be issued from + EUI64 PortGuid // port we want a subnet prefix for + ) +{ + CA_PORT *pCaPort; + uint64 subnetPrefix; + + SpinLockAcquire(pCaPortListLock); + pCaPort = GetCaPort(PortGuid); + if (pCaPort != NULL) + { + // a local port + subnetPrefix = pCaPort->SubnetPrefix; + } else { + // non-local port + // use the Subnet Prefix of the port we are issuing query from + pCaPort = GetCaPort(QueryPortGuid); + ASSERT(pCaPort != NULL); + subnetPrefix = pCaPort->SubnetPrefix; + } + SpinLockRelease(pCaPortListLock); + return subnetPrefix; +} + +// Query against 1st active port +FSTATUS +iba_sd_query_fabric_info( + IN CLIENT_HANDLE ClientHandle, + IN PQUERY pQuery, + IN SDK_QUERY_CALLBACK *Callback, + IN COMMAND_CONTROL_PARAMETERS *pQueryControlParameters OPTIONAL, + IN void *Context OPTIONAL + ) +{ + FSTATUS Fstatus; + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, iba_sd_query_fabric_info); + + Fstatus = CommonQueryPortFabricInformation(ClientHandle, (EUI64)-1, pQuery, Callback, pQueryControlParameters, Context); + + _DBG_LEAVE_LVL( _DBG_LVL_FUNC_TRACE ); + return(Fstatus); +} + +// Query against a specific port +// if Portuid == (EUI64)-1 -> against 1st active port +FSTATUS +iba_sd_query_port_fabric_info( + IN CLIENT_HANDLE ClientHandle, + IN EUI64 PortGuid, + IN PQUERY pQuery, + IN SDK_QUERY_CALLBACK *Callback, + IN COMMAND_CONTROL_PARAMETERS *pQueryControlParameters OPTIONAL, + IN void *Context OPTIONAL + ) +{ + FSTATUS Fstatus; + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, iba_sd_query_port_fabric_info); + Fstatus = CommonQueryPortFabricInformation(ClientHandle, PortGuid, pQuery, Callback, pQueryControlParameters, Context); + + _DBG_LEAVE_LVL( _DBG_LVL_FUNC_TRACE ); + return(Fstatus); +} + +// Common routine for Kernel calls +// Query against a specific port +// if Portuid == (EUI64)-1 -> against 1st active port +FSTATUS +CommonQueryPortFabricInformation( + IN CLIENT_HANDLE ClientHandle, + IN EUI64 PortGuid, + IN PQUERY pQuery, + IN SDK_QUERY_CALLBACK *Callback, + IN COMMAND_CONTROL_PARAMETERS *pQueryControlParameters OPTIONAL, + IN void *Context OPTIONAL + ) +{ + FSTATUS Fstatus; + CLIENT_CONTROL_PARAMETERS ClientParams; + PQueryDetails pQueryElement; + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, CommonQueryPortFabricInformation); + + if (SdUnloading) + { + _DBG_LEAVE_LVL( _DBG_LVL_FUNC_TRACE ); + return(FINVALID_STATE); + } + Fstatus = ValidateClientHandle(ClientHandle, &ClientParams); + + if (Fstatus != FSUCCESS) + { + _SD_ERROR(ClientParams.ClientDebugFlags, + ("Client Handle 0x%p not registered\n", _DBG_PTR(ClientHandle))); + _DBG_LEAVE_LVL( _DBG_LVL_FUNC_TRACE ); + return(Fstatus); + } + + Fstatus = CheckPortActive(&PortGuid); + if (Fstatus != FSUCCESS) + { + _DBG_LEAVE_LVL( _DBG_LVL_FUNC_TRACE ); + return(Fstatus); + } + + pQueryElement = (QueryDetails*)MemoryAllocate2AndClear(sizeof(QueryDetails), + IBA_MEM_FLAG_SHORT_DURATION, SUBNET_DRIVER_TAG); + if (pQueryElement == NULL) + { + _SD_ERROR(ClientParams.ClientDebugFlags, + ("Cannot allocate memory for QueryElement\n")); + _DBG_LEAVE_LVL( _DBG_LVL_FUNC_TRACE ); + return(FINSUFFICIENT_MEMORY); + } + QListSetObj(&pQueryElement->QueryListItem, (void *)pQueryElement); + + if (pQueryControlParameters != NULL) + { + pQueryElement->ControlParameters = *pQueryControlParameters; + } else { + pQueryElement->ControlParameters = ClientParams.ControlParameters; + } + + pQueryElement->ClientHandle = ClientHandle; + pQueryElement->SdSentCmd = UserQueryFabricInformation; + pQueryElement->cmd.query.UserQuery = *pQuery; + pQueryElement->cmd.query.UserCallback = Callback; + pQueryElement->cmd.query.pClientResult = NULL; + pQueryElement->UserContext = Context; + pQueryElement->PortGuid = PortGuid; + + // Convert the user query into one or more detailed queries + Fstatus = ValidateAndFillSDQuery(pQueryElement, IBA_MEM_FLAG_SHORT_DURATION); + if (Fstatus != FSUCCESS) + { + FreeQueryElement(pQueryElement); + _DBG_LEAVE_LVL( _DBG_LVL_FUNC_TRACE ); + return(Fstatus); + } + +#if defined(DBG) ||defined( IB_DEBUG) + { + CA_PORT *pCaPort; + + SpinLockAcquire(pCaPortListLock); + pCaPort = GetCaPort(PortGuid); + ASSERT(pCaPort != NULL); + ASSERT(pQueryElement->PortGuid == pCaPort->PortGuid); + SpinLockRelease(pCaPortListLock); + } +#endif + + SendQueryElement(pQueryElement, TRUE /*FirstAttempt*/); + + StartTimerHandler(pTimerObject, g_SdParams.TimeInterval); + + _DBG_LEAVE_LVL( _DBG_LVL_FUNC_TRACE ); + return(FPENDING); +} + +// Fabric Operation against 1st active port +FSTATUS +iba_sd_fabric_operation( + IN CLIENT_HANDLE ClientHandle, + IN FABRIC_OPERATION_DATA* pFabOp, + IN SDK_FABRIC_OPERATION_CALLBACK *Callback, + IN COMMAND_CONTROL_PARAMETERS *pCmdControlParameters OPTIONAL, + IN void* Context OPTIONAL + ) +{ + FSTATUS Fstatus; + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, iba_sd_fabric_operation); + + Fstatus = CommonPortFabricOperation(ClientHandle, (EUI64)-1, pFabOp, Callback, pCmdControlParameters, Context); + + _DBG_LEAVE_LVL( _DBG_LVL_FUNC_TRACE ); + return(Fstatus); +} + +// Fabric Operation against a specific port +// if Portuid == -1 -> against 1st active port +FSTATUS +iba_sd_port_fabric_operation( + IN CLIENT_HANDLE ClientHandle, + IN EUI64 PortGuid, + IN FABRIC_OPERATION_DATA* pFabOp, + IN SDK_FABRIC_OPERATION_CALLBACK *Callback, + IN COMMAND_CONTROL_PARAMETERS *pCmdControlParameters OPTIONAL, + IN void* Context OPTIONAL + ) +{ + FSTATUS Fstatus; + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, iba_sd_port_fabric_operation); + + Fstatus = CommonPortFabricOperation(ClientHandle, PortGuid, pFabOp, Callback, pCmdControlParameters, Context); + + _DBG_LEAVE_LVL( _DBG_LVL_FUNC_TRACE ); + return Fstatus; +} + +// Common routine for Kernel calls +// Fabric Operation against a specific port +// if Portuid == -1 -> against 1st active port +FSTATUS +CommonPortFabricOperation( + IN CLIENT_HANDLE ClientHandle, + IN EUI64 PortGuid, + IN FABRIC_OPERATION_DATA* pFabOp, + IN SDK_FABRIC_OPERATION_CALLBACK *Callback, + IN COMMAND_CONTROL_PARAMETERS *pCmdControlParameters OPTIONAL, + IN void* Context OPTIONAL + ) +{ + FSTATUS Fstatus = FNOT_FOUND; + CLIENT_CONTROL_PARAMETERS ClientParams; + PQueryDetails pQueryElement; + boolean saOp; + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, CommonPortFabricOperation); + + if (SdUnloading) + { + _DBG_LEAVE_LVL( _DBG_LVL_FUNC_TRACE ); + return(FINVALID_STATE); + } + Fstatus = ValidateClientHandle(ClientHandle, &ClientParams); + if (Fstatus != FSUCCESS) + { + _SD_ERROR(ClientParams.ClientDebugFlags, + ("Client Handle 0x%p not registered\n", _DBG_PTR(ClientHandle))); + _DBG_LEAVE_LVL( _DBG_LVL_FUNC_TRACE ); + return(Fstatus); + } + + Fstatus = CheckPortActive(&PortGuid); + if (Fstatus != FSUCCESS) + { + _DBG_LEAVE_LVL( _DBG_LVL_FUNC_TRACE ); + return(Fstatus); + } + + pQueryElement = (QueryDetails*)MemoryAllocate2AndClear(sizeof(QueryDetails), + IBA_MEM_FLAG_SHORT_DURATION, SUBNET_DRIVER_TAG); + if (pQueryElement == NULL) + { + _SD_ERROR(ClientParams.ClientDebugFlags, + ("Cannot allocate memory for QueryElement\n")); + _DBG_LEAVE_LVL( _DBG_LVL_FUNC_TRACE ); + return(FINSUFFICIENT_MEMORY); + } + QListSetObj(&pQueryElement->QueryListItem, (void *)pQueryElement); + + if (pCmdControlParameters != NULL) + { + pQueryElement->ControlParameters = *pCmdControlParameters; + } else { + pQueryElement->ControlParameters = ClientParams.ControlParameters; + } + + pQueryElement->ClientHandle = ClientHandle; + pQueryElement->SdSentCmd= UserFabricOperation; + pQueryElement->cmd.op.FabOp= *pFabOp; + pQueryElement->cmd.op.FabOpCallback = Callback; + pQueryElement->UserContext = Context; + pQueryElement->PortGuid = PortGuid; + + switch (pFabOp->Type) + { + case FabOpSetServiceRecord: + case FabOpDeleteServiceRecord: + case FabOpSetMcMemberRecord: + case FabOpJoinMcGroup: + case FabOpLeaveMcGroup: + case FabOpDeleteMcMemberRecord: + case FabOpSetInformInfo: + Fstatus = ValidateAndFillSDFabOp(pQueryElement, IBA_MEM_FLAG_SHORT_DURATION); + saOp = TRUE; + break; + default: + Fstatus = FINVALID_PARAMETER; + saOp = TRUE; + break; + } + + if (Fstatus != FSUCCESS) + { + FreeQueryElement(pQueryElement); + _DBG_LEAVE_LVL( _DBG_LVL_FUNC_TRACE ); + return(Fstatus); + } + +#if defined( DBG) ||defined( IB_DEBUG) + { + CA_PORT *pCaPort; + + SpinLockAcquire(pCaPortListLock); + pCaPort = GetCaPort(PortGuid); + ASSERT(pCaPort != NULL); + ASSERT(pQueryElement->PortGuid = pCaPort->PortGuid); + SpinLockRelease(pCaPortListLock); + } +#endif + + SendQueryElement(pQueryElement, TRUE); + + StartTimerHandler(pTimerObject, g_SdParams.TimeInterval); + + _DBG_LEAVE_LVL( _DBG_LVL_FUNC_TRACE ); + return(FPENDING); +} + +FSTATUS +ValidateAndFillSDQuery( + PQueryDetails pQueryElement, + uint32 MemAllocFlags + ) +{ + FSTATUS status = FINVALID_PARAMETER; + PQUERY pQuery; + IB_NODE_RECORD* pSaNodeRecordData; + IB_PATH_RECORD* pSaPathRecordData; + + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, ValidateAndFillSDQuery); + + pQuery = &pQueryElement->cmd.query.UserQuery; + + + _DBG_INFO(("pQuery->InputType = 0x%x, pQuery->OutputType = 0x%x\n", + pQuery->InputType, + pQuery->OutputType)); + switch(pQuery->InputType) + { + case InputTypeNoInput: //NO INPUT + { + // output types which are based on a NodeRecord query + if (pQuery->OutputType == OutputTypeLid + || pQuery->OutputType == OutputTypeSystemImageGuid + || pQuery->OutputType == OutputTypeNodeGuid + || pQuery->OutputType == OutputTypePortGuid + || pQuery->OutputType == OutputTypeNodeDesc + || pQuery->OutputType == OutputTypeNodeRecord + || pQuery->OutputType == OutputTypePathRecord + ) + { + status = FillSADetailsForNodeRecord(pQueryElement, MemAllocFlags); + } + else if (pQuery->OutputType == OutputTypePortInfoRecord) + { + status = FillSADetailsForPortInfoRecord(pQueryElement, MemAllocFlags); + } + else if (pQuery->OutputType == OutputTypeSMInfoRecord) + { + status = FillSADetailsForSMInfoRecord(pQueryElement, MemAllocFlags); + } + else if (pQuery->OutputType == OutputTypeLinkRecord) + { + status = FillSADetailsForLinkRecord(pQueryElement, MemAllocFlags); + } + else if (pQuery->OutputType == OutputTypeServiceRecord) + { + status = FillSADetailsForServiceRecord(pQueryElement, MemAllocFlags); + } + else if (pQuery->OutputType == OutputTypeMcMemberRecord) + { + status = FillSADetailsForMcMemberRecord(pQueryElement, MemAllocFlags); + } + else if (pQuery->OutputType == OutputTypeInformInfoRecord) + { + status = FillSADetailsForInformInfoRecord(pQueryElement, MemAllocFlags); + } + else if (pQuery->OutputType == OutputTypeSwitchInfoRecord) + { + status = FillSADetailsForSwitchInfoRecord(pQueryElement, MemAllocFlags); + } + else if (pQuery->OutputType == OutputTypeLinearFDBRecord) + { + status = FillSADetailsForLinearFDBRecord(pQueryElement, MemAllocFlags); + } + else if (pQuery->OutputType == OutputTypeRandomFDBRecord) + { + status = FillSADetailsForRandomFDBRecord(pQueryElement, MemAllocFlags); + } + else if (pQuery->OutputType == OutputTypeMCastFDBRecord) + { + status = FillSADetailsForMCastFDBRecord(pQueryElement, MemAllocFlags); + } + else if (pQuery->OutputType == OutputTypeVLArbTableRecord) + { + status = FillSADetailsForVLArbTableRecord(pQueryElement, MemAllocFlags); + } + else if (pQuery->OutputType == OutputTypePKeyTableRecord) + { + status = FillSADetailsForPKeyTableRecord(pQueryElement, MemAllocFlags); + } else { + status = FINVALID_PARAMETER; + } + break; + } + case InputTypeNodeType: //Input is a NodeType + { + // limited list of valid output types + // all are based on a NodeRecord query + if (! (pQuery->OutputType == OutputTypeLid + || pQuery->OutputType == OutputTypeSystemImageGuid + || pQuery->OutputType == OutputTypeNodeGuid + || pQuery->OutputType == OutputTypePortGuid + || pQuery->OutputType == OutputTypeNodeDesc + || pQuery->OutputType == OutputTypeNodeRecord + || pQuery->OutputType == OutputTypePathRecord + )) + { + status = FINVALID_PARAMETER; + break; + } + status = FillSADetailsForNodeRecord(pQueryElement, MemAllocFlags); + if ( status != FSUCCESS) + { + break; + } + + pQueryElement->u.pSaMad->SaHdr.ComponentMask = + IB_NODE_RECORD_COMP_NODETYPE; + pSaNodeRecordData = (IB_NODE_RECORD*)&(pQueryElement->u.pSaMad->Data); + pSaNodeRecordData->NodeInfoData.NodeType = (uint8)pQuery->InputValue.TypeOfNode; + BSWAP_IB_NODE_RECORD(pSaNodeRecordData); + status = FSUCCESS; + break; + } + + case InputTypeSystemImageGuid: + { + // limited list of valid output types + // all are based on a NodeRecord query + if (! (pQuery->OutputType == OutputTypeLid + || pQuery->OutputType == OutputTypeSystemImageGuid + || pQuery->OutputType == OutputTypeNodeGuid + || pQuery->OutputType == OutputTypePortGuid + || pQuery->OutputType == OutputTypeNodeDesc + || pQuery->OutputType == OutputTypeNodeRecord + || pQuery->OutputType == OutputTypePathRecord + )) + { + status = FINVALID_PARAMETER; + break; + } + status = FillSADetailsForNodeRecord(pQueryElement, MemAllocFlags); + if ( status != FSUCCESS) + { + break; + } + pQueryElement->u.pSaMad->SaHdr.ComponentMask = + IB_NODE_RECORD_COMP_SYSIMAGEGUID; + pSaNodeRecordData = (IB_NODE_RECORD*)&(pQueryElement->u.pSaMad->Data); + pSaNodeRecordData->NodeInfoData.SystemImageGUID = pQuery->InputValue.Guid; + BSWAP_IB_NODE_RECORD(pSaNodeRecordData); + status = FSUCCESS; + break; + } + + case InputTypeNodeGuid: + { + // limited list of valid output types + // all are based on a NodeRecord query + if (! (pQuery->OutputType == OutputTypeLid + || pQuery->OutputType == OutputTypeSystemImageGuid + || pQuery->OutputType == OutputTypeNodeGuid + || pQuery->OutputType == OutputTypePortGuid + || pQuery->OutputType == OutputTypeNodeDesc + || pQuery->OutputType == OutputTypeNodeRecord + || pQuery->OutputType == OutputTypePathRecord + )) + { + status = FINVALID_PARAMETER; + break; + } + + status = FillSADetailsForNodeRecord(pQueryElement, MemAllocFlags); + if ( status != FSUCCESS) + { + break; + } + pQueryElement->u.pSaMad->SaHdr.ComponentMask = + IB_NODE_RECORD_COMP_NODEGUID; + pSaNodeRecordData = (IB_NODE_RECORD*)&(pQueryElement->u.pSaMad->Data); + pSaNodeRecordData->NodeInfoData.NodeGUID = pQuery->InputValue.Guid; + BSWAP_IB_NODE_RECORD(pSaNodeRecordData); + status = FSUCCESS; + break; + } + + case InputTypePortGuid: + { + if ( pQuery->OutputType == OutputTypePathRecord || pQuery->OutputType == OutputTypeTraceRecord) + { + if (pQuery->OutputType == OutputTypeTraceRecord) + status = FillSADetailsForTraceRecord(pQueryElement, MemAllocFlags); + else + status = FillSADetailsForPathRecord(pQueryElement, MemAllocFlags); + if ( status != FSUCCESS) + { + break; + } + pQueryElement->u.pSaMad->SaHdr.ComponentMask = + IB_PATH_RECORD_COMP_DGID + | IB_PATH_RECORD_COMP_SGID + | IB_PATH_RECORD_COMP_REVERSIBLE + | IB_PATH_RECORD_COMP_NUMBPATH; + pSaPathRecordData = (IB_PATH_RECORD*)&(pQueryElement->u.pSaMad->Data); + + // use local port's SubnetPrefix + pSaPathRecordData->SGID.Type.Global.SubnetPrefix = + pSaPathRecordData->DGID.Type.Global.SubnetPrefix = + GetSubnetPrefixForPortGuid(pQueryElement->PortGuid, + pQueryElement->PortGuid); + + pSaPathRecordData->SGID.Type.Global.InterfaceID = + pQueryElement->PortGuid; + pSaPathRecordData->DGID.Type.Global.InterfaceID = + pQuery->InputValue.Guid; + pSaPathRecordData->Reversible = 1; + pSaPathRecordData->NumbPath = PATHRECORD_NUMBPATH; + + BSWAP_IB_PATH_RECORD(pSaPathRecordData); + status = FSUCCESS; + break; + } + else if ( pQuery->OutputType == OutputTypeMcMemberRecord) + { + IB_MCMEMBER_RECORD* pSaMcMemberRecord; + + status = FillSADetailsForMcMemberRecord(pQueryElement, MemAllocFlags); + if ( status != FSUCCESS) + { + break; + } + pQueryElement->u.pSaMad->SaHdr.ComponentMask = + IB_MCMEMBER_RECORD_COMP_PORTGID; + pSaMcMemberRecord = (IB_MCMEMBER_RECORD*)&(pQueryElement->u.pSaMad->Data); + pSaMcMemberRecord->RID.PortGID.Type.Global.SubnetPrefix = + GetSubnetPrefixForPortGuid(pQueryElement->PortGuid, + pQuery->InputValue.Guid); + pSaMcMemberRecord->RID.PortGID.Type.Global.InterfaceID = + pQuery->InputValue.Guid; + BSWAP_IB_MCMEMBER_RECORD(pSaMcMemberRecord); + status = FSUCCESS; + break; + } + else if ( pQuery->OutputType == OutputTypeServiceRecord) + { + IB_SERVICE_RECORD* pSaServiceRecord; + + status = FillSADetailsForServiceRecord(pQueryElement, MemAllocFlags); + if ( status != FSUCCESS) + { + break; + } + pQueryElement->u.pSaMad->SaHdr.ComponentMask = + IB_SERVICE_RECORD_COMP_SERVICEGID; + pSaServiceRecord = (IB_SERVICE_RECORD*)&(pQueryElement->u.pSaMad->Data); + pSaServiceRecord->RID.ServiceGID.Type.Global.SubnetPrefix = + GetSubnetPrefixForPortGuid(pQueryElement->PortGuid, + pQuery->InputValue.Guid); + pSaServiceRecord->RID.ServiceGID.Type.Global.InterfaceID = + pQuery->InputValue.Guid; + BSWAP_IB_SERVICE_RECORD(pSaServiceRecord); + status = FSUCCESS; + break; + } + else if ( pQuery->OutputType == OutputTypeInformInfoRecord) + { + IB_INFORM_INFO_RECORD* pSaInformInfoRecord; + + status = FillSADetailsForInformInfoRecord(pQueryElement, MemAllocFlags); + if ( status != FSUCCESS) + { + break; + } + pQueryElement->u.pSaMad->SaHdr.ComponentMask = + IB_INFORMINFO_RECORD_COMP_SUBSCRIBERGID; + pSaInformInfoRecord = (IB_INFORM_INFO_RECORD*)&(pQueryElement->u.pSaMad->Data); + pSaInformInfoRecord->RID.SubscriberGID.Type.Global.SubnetPrefix= + GetSubnetPrefixForPortGuid(pQueryElement->PortGuid, + pQuery->InputValue.Guid); + pSaInformInfoRecord->RID.SubscriberGID.Type.Global.InterfaceID = + pQuery->InputValue.Guid; + BSWAP_IB_INFORM_INFO_RECORD(pSaInformInfoRecord); + status = FSUCCESS; + break; + } + + // limited list of valid output types + // all are based on a NodeRecord query + if (! (pQuery->OutputType == OutputTypeLid + || pQuery->OutputType == OutputTypeSystemImageGuid + || pQuery->OutputType == OutputTypeNodeGuid + || pQuery->OutputType == OutputTypePortGuid + || pQuery->OutputType == OutputTypeNodeDesc + || pQuery->OutputType == OutputTypeNodeRecord + )) + { + status = FINVALID_PARAMETER; + break; + } + status = FillSADetailsForNodeRecord(pQueryElement, MemAllocFlags); + if ( status != FSUCCESS) + { + break; + } + pQueryElement->u.pSaMad->SaHdr.ComponentMask = + IB_NODE_RECORD_COMP_PORTGUID; + pSaNodeRecordData = (IB_NODE_RECORD*)&(pQueryElement->u.pSaMad->Data); + pSaNodeRecordData->NodeInfoData.PortGUID = pQuery->InputValue.Guid; + BSWAP_IB_NODE_RECORD(pSaNodeRecordData); + status = FSUCCESS; + break; + } + + case InputTypePortGid: + { + if ( pQuery->OutputType == OutputTypePathRecord || pQuery->OutputType == OutputTypeTraceRecord) + { + if (pQuery->OutputType == OutputTypeTraceRecord) + status = FillSADetailsForTraceRecord(pQueryElement, MemAllocFlags); + else + status = FillSADetailsForPathRecord(pQueryElement, MemAllocFlags); + if ( status != FSUCCESS) + { + break; + } + pQueryElement->u.pSaMad->SaHdr.ComponentMask = + IB_PATH_RECORD_COMP_DGID + | IB_PATH_RECORD_COMP_SGID + | IB_PATH_RECORD_COMP_REVERSIBLE + | IB_PATH_RECORD_COMP_NUMBPATH; + pSaPathRecordData = (IB_PATH_RECORD*)&(pQueryElement->u.pSaMad->Data); + pSaPathRecordData->DGID = pQuery->InputValue.Gid; + // use local port's SubnetPrefix + pSaPathRecordData->SGID.Type.Global.SubnetPrefix = + GetSubnetPrefixForPortGuid(pQueryElement->PortGuid, + pQueryElement->PortGuid); + pSaPathRecordData->SGID.Type.Global.InterfaceID = + pQueryElement->PortGuid; + pSaPathRecordData->Reversible = 1; + pSaPathRecordData->NumbPath = PATHRECORD_NUMBPATH; + + BSWAP_IB_PATH_RECORD(pSaPathRecordData); + status = FSUCCESS; + break; + } + else if ( pQuery->OutputType == OutputTypeMcMemberRecord) + { + IB_MCMEMBER_RECORD* pSaMcMemberRecord; + + status = FillSADetailsForMcMemberRecord(pQueryElement, MemAllocFlags); + if ( status != FSUCCESS) + { + break; + } + pQueryElement->u.pSaMad->SaHdr.ComponentMask = + IB_MCMEMBER_RECORD_COMP_PORTGID; + pSaMcMemberRecord = (IB_MCMEMBER_RECORD*)&(pQueryElement->u.pSaMad->Data); + pSaMcMemberRecord->RID.PortGID = pQuery->InputValue.Gid; + BSWAP_IB_MCMEMBER_RECORD(pSaMcMemberRecord); + status = FSUCCESS; + break; + } + else if ( pQuery->OutputType == OutputTypeServiceRecord) + { + IB_SERVICE_RECORD* pSaServiceRecord; + + status = FillSADetailsForServiceRecord(pQueryElement, MemAllocFlags); + if ( status != FSUCCESS) + { + break; + } + pQueryElement->u.pSaMad->SaHdr.ComponentMask = + IB_SERVICE_RECORD_COMP_SERVICEGID; + pSaServiceRecord = (IB_SERVICE_RECORD*)&(pQueryElement->u.pSaMad->Data); + pSaServiceRecord->RID.ServiceGID = pQuery->InputValue.Gid; + BSWAP_IB_SERVICE_RECORD(pSaServiceRecord); + status = FSUCCESS; + break; + } + else if ( pQuery->OutputType == OutputTypeInformInfoRecord) + { + IB_INFORM_INFO_RECORD* pSaInformInfoRecord; + + status = FillSADetailsForInformInfoRecord(pQueryElement, MemAllocFlags); + if ( status != FSUCCESS) + { + break; + } + pQueryElement->u.pSaMad->SaHdr.ComponentMask = + IB_INFORMINFO_RECORD_COMP_SUBSCRIBERGID; + pSaInformInfoRecord = (IB_INFORM_INFO_RECORD*)&(pQueryElement->u.pSaMad->Data); + pSaInformInfoRecord->RID.SubscriberGID = pQuery->InputValue.Gid; + BSWAP_IB_INFORM_INFO_RECORD(pSaInformInfoRecord); + status = FSUCCESS; + break; + } + + status = FINVALID_PARAMETER; + break; + } + case InputTypeMcGid: + { + if ( pQuery->OutputType == OutputTypeMcMemberRecord) + { + IB_MCMEMBER_RECORD* pSaMcMemberRecord; + + status = FillSADetailsForMcMemberRecord(pQueryElement, MemAllocFlags); + if ( status != FSUCCESS) + { + break; + } + pQueryElement->u.pSaMad->SaHdr.ComponentMask = + IB_MCMEMBER_RECORD_COMP_MGID; + pSaMcMemberRecord = (IB_MCMEMBER_RECORD*)&(pQueryElement->u.pSaMad->Data); + pSaMcMemberRecord->RID.MGID = pQuery->InputValue.Gid; + BSWAP_IB_MCMEMBER_RECORD(pSaMcMemberRecord); + status = FSUCCESS; + break; + } + status = FINVALID_PARAMETER; + break; + } + + case InputTypeLid: + { + if (pQuery->OutputType == OutputTypePortInfoRecord) + { + IB_PORTINFO_RECORD* pPortInfoRecord; + status = FillSADetailsForPortInfoRecord(pQueryElement, MemAllocFlags); + if ( status != FSUCCESS) + { + break; + } + pQueryElement->u.pSaMad->SaHdr.ComponentMask = IB_PORTINFO_RECORD_COMP_ENDPORTLID; + pPortInfoRecord = (IB_PORTINFO_RECORD*)&(pQueryElement->u.pSaMad->Data); + pPortInfoRecord->RID.s.EndPortLID = pQuery->InputValue.Lid; + BSWAP_IB_PORTINFO_RECORD(pPortInfoRecord, TRUE); + status = FSUCCESS; + break; + } else if ( pQuery->OutputType == OutputTypeMcMemberRecord) + { + IB_MCMEMBER_RECORD* pSaMcMemberRecord; + + status = FillSADetailsForMcMemberRecord(pQueryElement, MemAllocFlags); + if ( status != FSUCCESS) + { + break; + } + pQueryElement->u.pSaMad->SaHdr.ComponentMask = + IB_MCMEMBER_RECORD_COMP_MLID; + pSaMcMemberRecord = (IB_MCMEMBER_RECORD*)&(pQueryElement->u.pSaMad->Data); + pSaMcMemberRecord->MLID = pQuery->InputValue.Lid; + BSWAP_IB_MCMEMBER_RECORD(pSaMcMemberRecord); + status = FSUCCESS; + break; + } else if (pQuery->OutputType == OutputTypeSwitchInfoRecord) + { + IB_SWITCHINFO_RECORD* pSwitchInfoRecord; + status = FillSADetailsForSwitchInfoRecord(pQueryElement, MemAllocFlags); + if ( status != FSUCCESS) + { + break; + } + pQueryElement->u.pSaMad->SaHdr.ComponentMask = IB_SWITCHINFO_RECORD_COMP_LID; + pSwitchInfoRecord = (IB_SWITCHINFO_RECORD*)&(pQueryElement->u.pSaMad->Data); + pSwitchInfoRecord->RID.s.LID = pQuery->InputValue.Lid; + BSWAP_IB_SWITCHINFO_RECORD(pSwitchInfoRecord); + status = FSUCCESS; + break; + } else if (pQuery->OutputType == OutputTypeLinearFDBRecord) + { + IB_LINEAR_FDB_RECORD* pLinearFDBRecord; + status = FillSADetailsForLinearFDBRecord(pQueryElement, MemAllocFlags); + if ( status != FSUCCESS) + { + break; + } + pQueryElement->u.pSaMad->SaHdr.ComponentMask = IB_LINEARFDB_RECORD_COMP_LID; + pLinearFDBRecord = (IB_LINEAR_FDB_RECORD*)&(pQueryElement->u.pSaMad->Data); + pLinearFDBRecord->RID.s.LID = pQuery->InputValue.Lid; + BSWAP_IB_LINEAR_FDB_RECORD(pLinearFDBRecord); + status = FSUCCESS; + break; + } else if (pQuery->OutputType == OutputTypeRandomFDBRecord) + { + IB_RANDOM_FDB_RECORD* pRandomFDBRecord; + status = FillSADetailsForRandomFDBRecord(pQueryElement, MemAllocFlags); + if ( status != FSUCCESS) + { + break; + } + pQueryElement->u.pSaMad->SaHdr.ComponentMask = IB_RANDOMFDB_RECORD_COMP_LID; + pRandomFDBRecord = (IB_RANDOM_FDB_RECORD*)&(pQueryElement->u.pSaMad->Data); + pRandomFDBRecord->RID.s.LID = pQuery->InputValue.Lid; + BSWAP_IB_RANDOM_FDB_RECORD(pRandomFDBRecord); + status = FSUCCESS; + break; + } else if (pQuery->OutputType == OutputTypeMCastFDBRecord) + { + IB_MCAST_FDB_RECORD* pMCastFDBRecord; + status = FillSADetailsForMCastFDBRecord(pQueryElement, MemAllocFlags); + if ( status != FSUCCESS) + { + break; + } + pQueryElement->u.pSaMad->SaHdr.ComponentMask = IB_MCASTFDB_RECORD_COMP_LID; + pMCastFDBRecord = (IB_MCAST_FDB_RECORD*)&(pQueryElement->u.pSaMad->Data); + pMCastFDBRecord->RID.s.LID = pQuery->InputValue.Lid; + BSWAP_IB_MCAST_FDB_RECORD(pMCastFDBRecord); + status = FSUCCESS; + break; + } else if (pQuery->OutputType == OutputTypeVLArbTableRecord) + { + IB_VLARBTABLE_RECORD* pVLArbTableRecord; + status = FillSADetailsForVLArbTableRecord(pQueryElement, MemAllocFlags); + if ( status != FSUCCESS) + { + break; + } + pQueryElement->u.pSaMad->SaHdr.ComponentMask = IB_VLARBTABLE_RECORD_COMP_LID; + pVLArbTableRecord = (IB_VLARBTABLE_RECORD*)&(pQueryElement->u.pSaMad->Data); + pVLArbTableRecord->RID.s.LID = pQuery->InputValue.Lid; + BSWAP_IB_VLARBTABLE_RECORD(pVLArbTableRecord); + status = FSUCCESS; + break; + } else if (pQuery->OutputType == OutputTypePKeyTableRecord) + { + IB_P_KEY_TABLE_RECORD* pPKeyTableRecord; + status = FillSADetailsForPKeyTableRecord(pQueryElement, MemAllocFlags); + if ( status != FSUCCESS) + { + break; + } + pQueryElement->u.pSaMad->SaHdr.ComponentMask = IB_PKEYTABLE_RECORD_COMP_LID; + pPKeyTableRecord = (IB_P_KEY_TABLE_RECORD*)&(pQueryElement->u.pSaMad->Data); + pPKeyTableRecord->RID.s.LID = pQuery->InputValue.Lid; + BSWAP_IB_P_KEY_TABLE_RECORD(pPKeyTableRecord); + status = FSUCCESS; + break; + } + // limited list of valid output types + // all are based on a NodeRecord query + if (! (pQuery->OutputType == OutputTypeLid + || pQuery->OutputType == OutputTypeSystemImageGuid + || pQuery->OutputType == OutputTypeNodeGuid + || pQuery->OutputType == OutputTypePortGuid + || pQuery->OutputType == OutputTypeNodeDesc + || pQuery->OutputType == OutputTypeNodeRecord + || pQuery->OutputType == OutputTypePathRecord + )) + { + status = FINVALID_PARAMETER; + break; + } + status = FillSADetailsForNodeRecord(pQueryElement, MemAllocFlags); + if ( status != FSUCCESS) + { + break; + } + pSaNodeRecordData = (IB_NODE_RECORD*)&(pQueryElement->u.pSaMad->Data); + pQueryElement->u.pSaMad->SaHdr.ComponentMask = + IB_NODE_RECORD_COMP_LID; + pSaNodeRecordData->RID.s.LID = pQuery->InputValue.Lid; + BSWAP_IB_NODE_RECORD(pSaNodeRecordData); + status = FSUCCESS; + break; + } + + case InputTypeNodeDesc: + { + // limited list of valid output types + // all are based on a NodeRecord query + if (! (pQuery->OutputType == OutputTypeLid + || pQuery->OutputType == OutputTypeSystemImageGuid + || pQuery->OutputType == OutputTypeNodeGuid + || pQuery->OutputType == OutputTypePortGuid + || pQuery->OutputType == OutputTypeNodeDesc + || pQuery->OutputType == OutputTypeNodeRecord + || pQuery->OutputType == OutputTypePathRecord + )) + { + status = FINVALID_PARAMETER; + break; + } + status = FillSADetailsForNodeRecord(pQueryElement, MemAllocFlags); + if ( status != FSUCCESS) + { + break; + } + pQueryElement->u.pSaMad->SaHdr.ComponentMask = + IB_NODE_RECORD_COMP_NODEDESC; + pSaNodeRecordData = (IB_NODE_RECORD*)&(pQueryElement->u.pSaMad->Data); + + if (pQuery->InputValue.NodeDesc.NameLength > NODE_DESCRIPTION_ARRAY_SIZE) + { + status = FINVALID_PARAMETER; + break; + } + + MemoryClear(pSaNodeRecordData->NodeDescData.NodeString, + sizeof(NODE_DESCRIPTION)); + + MemoryCopy(pSaNodeRecordData->NodeDescData.NodeString, + &(pQuery->InputValue.NodeDesc.Name), + pQuery->InputValue.NodeDesc.NameLength); + + // don't need to byte swap the Node Description! + status = FSUCCESS; + break; + } + + case InputTypePortGuidPair: + { + if ( pQuery->OutputType != OutputTypePathRecord && pQuery->OutputType != OutputTypeTraceRecord) + { + status = FINVALID_PARAMETER; + break; + } + + if (pQuery->OutputType == OutputTypeTraceRecord) + status = FillSADetailsForTraceRecord(pQueryElement, MemAllocFlags); + else + status = FillSADetailsForPathRecord(pQueryElement, MemAllocFlags); + if ( status != FSUCCESS) + { + break; + } + + pQueryElement->u.pSaMad->SaHdr.ComponentMask = + IB_PATH_RECORD_COMP_DGID + | IB_PATH_RECORD_COMP_SGID + | IB_PATH_RECORD_COMP_REVERSIBLE + | IB_PATH_RECORD_COMP_NUMBPATH; + pSaPathRecordData = (IB_PATH_RECORD*)&(pQueryElement->u.pSaMad->Data); + // use subnet prefix of SourcePort, if not local use our's + pSaPathRecordData->DGID.Type.Global.SubnetPrefix = + pSaPathRecordData->SGID.Type.Global.SubnetPrefix = + GetSubnetPrefixForPortGuid(pQueryElement->PortGuid, + pQuery->InputValue.PortGuidPair.SourcePortGuid); + + pSaPathRecordData->DGID.Type.Global.InterfaceID = + pQuery->InputValue.PortGuidPair.DestPortGuid; + pSaPathRecordData->SGID.Type.Global.InterfaceID = + pQuery->InputValue.PortGuidPair.SourcePortGuid; + pSaPathRecordData->Reversible = 1; + pSaPathRecordData->NumbPath = PATHRECORD_NUMBPATH; // required + + BSWAP_IB_PATH_RECORD(pSaPathRecordData); + status = FSUCCESS; + break; + } + + case InputTypeGidPair: + { + if ( pQuery->OutputType != OutputTypePathRecord && pQuery->OutputType != OutputTypeTraceRecord) + { + status = FINVALID_PARAMETER; + break; + } + + if (pQuery->OutputType == OutputTypeTraceRecord) + status = FillSADetailsForTraceRecord(pQueryElement, MemAllocFlags); + else + status = FillSADetailsForPathRecord(pQueryElement, MemAllocFlags); + if ( status != FSUCCESS) + { + break; + } + + pQueryElement->u.pSaMad->SaHdr.ComponentMask = + IB_PATH_RECORD_COMP_DGID + | IB_PATH_RECORD_COMP_SGID + | IB_PATH_RECORD_COMP_REVERSIBLE + | IB_PATH_RECORD_COMP_NUMBPATH; + pSaPathRecordData = (IB_PATH_RECORD*)&(pQueryElement->u.pSaMad->Data); + pSaPathRecordData->DGID= pQuery->InputValue.GidPair.DestGid; + pSaPathRecordData->SGID= pQuery->InputValue.GidPair.SourceGid; + pSaPathRecordData->Reversible = 1; + pSaPathRecordData->NumbPath = PATHRECORD_NUMBPATH; // required + + BSWAP_IB_PATH_RECORD(pSaPathRecordData); + status = FSUCCESS; + break; + } + case InputTypePathRecord: + { + if (pQuery->OutputType != OutputTypePathRecord && pQuery->OutputType != OutputTypeTraceRecord) + { + status = FINVALID_PARAMETER; + break; + } + + if (pQuery->OutputType == OutputTypeTraceRecord) + status = FillSADetailsForTraceRecord(pQueryElement, MemAllocFlags); + else + status = FillSADetailsForPathRecord(pQueryElement, MemAllocFlags); + if ( status != FSUCCESS) + { + break; + } + pSaPathRecordData = (IB_PATH_RECORD*)&(pQueryElement->u.pSaMad->Data); + pQueryElement->u.pSaMad->SaHdr.ComponentMask = + pQuery->InputValue.PathRecordValue.ComponentMask; + *pSaPathRecordData = pQuery->InputValue.PathRecordValue.PathRecord; + BSWAP_IB_PATH_RECORD(pSaPathRecordData); + status = FSUCCESS; + break; + } + + case InputTypeServiceRecord: + { + IB_SERVICE_RECORD* pSaServiceRecord; + + // make sure the output type is sane + if ( pQuery->OutputType != OutputTypeServiceRecord) + { + status = FINVALID_PARAMETER; + break; + } + + // fill out the basic details of the packet request + status = FillSADetailsForServiceRecord(pQueryElement, MemAllocFlags); + if ( status != FSUCCESS) + { + break; + } + + pQueryElement->u.pSaMad->SaHdr.ComponentMask = + pQuery->InputValue.ServiceRecordValue.ComponentMask; + pSaServiceRecord = (IB_SERVICE_RECORD*)&(pQueryElement->u.pSaMad->Data); + *pSaServiceRecord = pQuery->InputValue.ServiceRecordValue.ServiceRecord; + BSWAP_IB_SERVICE_RECORD(pSaServiceRecord); + status = FSUCCESS; + break; + } + case InputTypeMcMemberRecord: + { + IB_MCMEMBER_RECORD* pSaMcMemberRecord; + + // make sure the output type is sane + if ( pQuery->OutputType != OutputTypeMcMemberRecord) + { + status = FINVALID_PARAMETER; + break; + } + + // fill out the basic details of the packet request + status = FillSADetailsForMcMemberRecord(pQueryElement, MemAllocFlags); + if ( status != FSUCCESS) + { + break; + } + + pQueryElement->u.pSaMad->SaHdr.ComponentMask = + pQuery->InputValue.McMemberRecordValue.ComponentMask; + pSaMcMemberRecord = (IB_MCMEMBER_RECORD*)&(pQueryElement->u.pSaMad->Data); + *pSaMcMemberRecord = pQuery->InputValue.McMemberRecordValue.McMemberRecord; + BSWAP_IB_MCMEMBER_RECORD(pSaMcMemberRecord); + status = FSUCCESS; + break; + } + case InputTypePortGuidList: + { + IB_MULTIPATH_RECORD *pSaMultiPathRecordData; + uint8 i; + + if ( pQuery->OutputType != OutputTypePathRecord) + { + status = FINVALID_PARAMETER; + break; + } + if ( 0 == pQuery->InputValue.PortGuidList.SourceGuidCount + || 0 == pQuery->InputValue.PortGuidList.DestGuidCount) + { + status = FINVALID_PARAMETER; + break; + } + if ( pQuery->InputValue.PortGuidList.SourceGuidCount + + pQuery->InputValue.PortGuidList.DestGuidCount + > MULTIPATH_GID_LIMIT) + { + status = FINVALID_PARAMETER; + break; + } + status = FillSADetailsForMultiPathRecord(pQueryElement, MemAllocFlags); + if ( status != FSUCCESS) + { + break; + } + + pQueryElement->u.pSaMad->SaHdr.ComponentMask = + IB_MULTIPATH_RECORD_COMP_DGIDCOUNT + | IB_MULTIPATH_RECORD_COMP_SGIDCOUNT + | IB_MULTIPATH_RECORD_COMP_REVERSIBLE + | IB_MULTIPATH_RECORD_COMP_NUMBPATH + | IB_MULTIPATH_RECORD_COMP_INDEPENDENCESELECTOR; + pSaMultiPathRecordData = (IB_MULTIPATH_RECORD*)&(pQueryElement->u.pSaMad->Data); + for (i =0; i< pQuery->InputValue.PortGuidList.SourceGuidCount + + pQuery->InputValue.PortGuidList.DestGuidCount; ++i) + { + // use subnet prefix of PortGuid, if not local use our's + pSaMultiPathRecordData->GIDList[i].Type.Global.SubnetPrefix = + GetSubnetPrefixForPortGuid(pQueryElement->PortGuid, + pQuery->InputValue.PortGuidList.GuidList[i]); + + pSaMultiPathRecordData->GIDList[i].Type.Global.InterfaceID = + pQuery->InputValue.PortGuidList.GuidList[i]; + } + pSaMultiPathRecordData->Reversible = 1; + pSaMultiPathRecordData->NumbPath = PATHRECORD_NUMBPATH; // required + pSaMultiPathRecordData->IndependenceSelector = 1; + pSaMultiPathRecordData->SGIDCount = pQuery->InputValue.PortGuidList.SourceGuidCount; + pSaMultiPathRecordData->DGIDCount = pQuery->InputValue.PortGuidList.DestGuidCount; + + BSWAP_IB_MULTIPATH_RECORD(pSaMultiPathRecordData); + status = FSUCCESS; + break; + } + + case InputTypeGidList: + { + IB_MULTIPATH_RECORD *pSaMultiPathRecordData; + uint8 i; + + if ( pQuery->OutputType != OutputTypePathRecord) + { + status = FINVALID_PARAMETER; + break; + } + if ( 0 == pQuery->InputValue.GidList.SourceGidCount + || 0 == pQuery->InputValue.GidList.DestGidCount) + { + status = FINVALID_PARAMETER; + break; + } + if ( pQuery->InputValue.GidList.SourceGidCount + +pQuery->InputValue.GidList.DestGidCount + > MULTIPATH_GID_LIMIT) + { + status = FINVALID_PARAMETER; + break; + } + status = FillSADetailsForMultiPathRecord(pQueryElement, MemAllocFlags); + if ( status != FSUCCESS) + { + break; + } + + pQueryElement->u.pSaMad->SaHdr.ComponentMask = + IB_MULTIPATH_RECORD_COMP_DGIDCOUNT + | IB_MULTIPATH_RECORD_COMP_SGIDCOUNT + | IB_MULTIPATH_RECORD_COMP_REVERSIBLE + | IB_MULTIPATH_RECORD_COMP_NUMBPATH + | IB_MULTIPATH_RECORD_COMP_INDEPENDENCESELECTOR; + pSaMultiPathRecordData = (IB_MULTIPATH_RECORD*)&(pQueryElement->u.pSaMad->Data); + for (i =0; i< pQuery->InputValue.GidList.SourceGidCount + + pQuery->InputValue.GidList.DestGidCount; ++i) + { + pSaMultiPathRecordData->GIDList[i]= pQuery->InputValue.GidList.GidList[i]; + } + pSaMultiPathRecordData->Reversible = 1; + pSaMultiPathRecordData->NumbPath = PATHRECORD_NUMBPATH; // required + pSaMultiPathRecordData->IndependenceSelector = 1; + pSaMultiPathRecordData->SGIDCount = pQuery->InputValue.GidList.SourceGidCount; + pSaMultiPathRecordData->DGIDCount = pQuery->InputValue.GidList.DestGidCount; + + BSWAP_IB_MULTIPATH_RECORD(pSaMultiPathRecordData); + status = FSUCCESS; + break; + } + case InputTypeMultiPathRecord: + { + IB_MULTIPATH_RECORD *pSaMultiPathRecordData; + + if ( pQuery->OutputType != OutputTypePathRecord) + { + status = FINVALID_PARAMETER; + break; + } + status = FillSADetailsForMultiPathRecord(pQueryElement, MemAllocFlags); + if ( status != FSUCCESS) + { + break; + } + pSaMultiPathRecordData = (IB_MULTIPATH_RECORD*)&(pQueryElement->u.pSaMad->Data); + pQueryElement->u.pSaMad->SaHdr.ComponentMask = + pQuery->InputValue.MultiPathRecordValue.ComponentMask; + *pSaMultiPathRecordData = pQuery->InputValue.MultiPathRecordValue.MultiPathRecord; + BSWAP_IB_MULTIPATH_RECORD(pSaMultiPathRecordData); + status = FSUCCESS; + break; + } + + default: + status = FINVALID_PARAMETER; + break; + + } + if (FSUCCESS == status) + { + BSWAP_SA_HDR(&pQueryElement->u.pSaMad->SaHdr); + } + _DBG_LEAVE_LVL( _DBG_LVL_FUNC_TRACE ); + return status; +} + +FSTATUS +ValidateAndFillSDFabOp( + PQueryDetails pQueryElement, + uint32 MemAllocFlags + ) +{ + FSTATUS status = FINVALID_PARAMETER; + FABRIC_OPERATION_DATA *pFabOp; + MAD* pMad; + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, ValidateAndFillSDFabOp); + + pFabOp = &pQueryElement->cmd.op.FabOp; + + _DBG_INFO(("pFabOp->Type = 0x%x\n", pFabOp->Type)); + switch(pFabOp->Type) + { + case FabOpSetServiceRecord: + case FabOpDeleteServiceRecord: + { + IB_SERVICE_RECORD* pSaServiceRecord; + + status = FillSADetailsForServiceRecord(pQueryElement, MemAllocFlags); + if ( status != FSUCCESS) + { + break; + } + + pMad = pQueryElement->u.pMad; + if (pFabOp->Type == FabOpSetServiceRecord) + { + pMad->common.mr.s.Method = SUBN_ADM_SET; + pQueryElement->u.pSaMad->SaHdr.ComponentMask = 0; // unused + } else { + pMad->common.mr.s.Method = SUBN_ADM_DELETE; + pQueryElement->u.pSaMad->SaHdr.ComponentMask = + pFabOp->Value.ServiceRecordValue.ComponentMask; + } + pSaServiceRecord = (IB_SERVICE_RECORD*)&(pQueryElement->u.pSaMad->Data); + *pSaServiceRecord = pFabOp->Value.ServiceRecordValue.ServiceRecord; + BSWAP_IB_SERVICE_RECORD(pSaServiceRecord); + status = FSUCCESS; + break; + } + case FabOpSetMcMemberRecord: + case FabOpDeleteMcMemberRecord: + { + IB_MCMEMBER_RECORD* pSaMcMemberRecord; + + status = FillSADetailsForMcMemberRecord(pQueryElement, MemAllocFlags); + if ( status != FSUCCESS) + { + break; + } + + pMad = pQueryElement->u.pMad; + pMad->common.mr.s.Method = (pFabOp->Type == FabOpSetMcMemberRecord) + ? SUBN_ADM_SET : SUBN_ADM_DELETE; + pQueryElement->u.pSaMad->SaHdr.ComponentMask = + pFabOp->Value.McMemberRecordValue.ComponentMask; + pSaMcMemberRecord = (IB_MCMEMBER_RECORD*)&(pQueryElement->u.pSaMad->Data); + *pSaMcMemberRecord = pFabOp->Value.McMemberRecordValue.McMemberRecord; + BSWAP_IB_MCMEMBER_RECORD(pSaMcMemberRecord); + status = FSUCCESS; + break; + } + case FabOpJoinMcGroup: + case FabOpLeaveMcGroup: + { + IB_MCMEMBER_RECORD* pSaMcMemberRecord; + + status = FillSADetailsForMcMemberRecord(pQueryElement, MemAllocFlags); + if ( status != FSUCCESS) + { + break; + } + + pMad = pQueryElement->u.pMad; + pMad->common.mr.s.Method = SUBN_ADM_SET; + pMad->common.mr.s.Method = (pFabOp->Type == FabOpJoinMcGroup) + ?SUBN_ADM_SET:SUBN_ADM_DELETE; + pQueryElement->u.pSaMad->SaHdr.ComponentMask = + IB_MCMEMBER_RECORD_COMP_MGID + | IB_MCMEMBER_RECORD_COMP_PORTGID + | IB_MCMEMBER_RECORD_COMP_JOINSTATE; + pSaMcMemberRecord = (IB_MCMEMBER_RECORD*)&(pQueryElement->u.pSaMad->Data); + pSaMcMemberRecord->RID.MGID = pFabOp->Value.McJoinLeave.MGID; + pSaMcMemberRecord->RID.PortGID.Type.Global.SubnetPrefix = + GetSubnetPrefixForPortGuid(pQueryElement->PortGuid, + pQueryElement->PortGuid); + pSaMcMemberRecord->RID.PortGID.Type.Global.InterfaceID = + pQueryElement->PortGuid; + pSaMcMemberRecord->JoinFullMember = pFabOp->Value.McJoinLeave.JoinFullMember; + pSaMcMemberRecord->JoinNonMember = pFabOp->Value.McJoinLeave.JoinNonMember; + pSaMcMemberRecord->JoinSendOnlyMember = pFabOp->Value.McJoinLeave.JoinSendOnlyMember; + BSWAP_IB_MCMEMBER_RECORD(pSaMcMemberRecord); + status = FSUCCESS; + break; + } + case FabOpSetInformInfo: + { + IB_INFORM_INFO* pSaInformInfo; + + status = FillSADetailsForInformInfo(pQueryElement, MemAllocFlags); + if ( status != FSUCCESS) + { + break; + } + + pMad = pQueryElement->u.pMad; + pMad->common.mr.s.Method = SUBN_ADM_SET; + // ComponentMask not used + pSaInformInfo = (IB_INFORM_INFO*)&(pQueryElement->u.pSaMad->Data); + *pSaInformInfo = pFabOp->Value.InformInfo; + BSWAP_INFORM_INFO(pSaInformInfo); + status = FSUCCESS; + break; + } + default: + status = FINVALID_PARAMETER; + break; + } + if (FSUCCESS == status) + { + BSWAP_SA_HDR(&pQueryElement->u.pSaMad->SaHdr); + } + _DBG_LEAVE_LVL( _DBG_LVL_FUNC_TRACE ); + return status; +} + +FSTATUS +FillSADetailsForNodeRecord( + PQueryDetails pQueryElement, + uint32 MemAllocFlags + ) +{ + FSTATUS Fstatus; + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, FillSADetailsForNodeRecord); + + Fstatus = BuildCommonSAMad(pQueryElement, SA_ATTRIB_NODE_RECORD, + sizeof(IB_NODE_RECORD), MemAllocFlags); + _DBG_LEAVE_LVL( _DBG_LVL_FUNC_TRACE ); + return Fstatus; +} + +FSTATUS +FillSADetailsForPortInfoRecord( + PQueryDetails pQueryElement, + uint32 MemAllocFlags + ) +{ + FSTATUS Fstatus; + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, FillSADetailsForPortInfoRecord); + + Fstatus = BuildCommonSAMad(pQueryElement, SA_ATTRIB_PORTINFO_RECORD, + sizeof(IB_PORTINFO_RECORD), MemAllocFlags); + _DBG_LEAVE_LVL( _DBG_LVL_FUNC_TRACE ); + return Fstatus; +} + +FSTATUS +FillSADetailsForSMInfoRecord( + PQueryDetails pQueryElement, + uint32 MemAllocFlags + ) +{ + FSTATUS Fstatus; + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, FillSADetailsForSMInfoRecord); + + Fstatus = BuildCommonSAMad(pQueryElement, SA_ATTRIB_SMINFO_RECORD, + sizeof(IB_SMINFO_RECORD), MemAllocFlags); + _DBG_LEAVE_LVL( _DBG_LVL_FUNC_TRACE ); + return Fstatus; +} + +FSTATUS +FillSADetailsForLinkRecord( + PQueryDetails pQueryElement, + uint32 MemAllocFlags + ) +{ + FSTATUS Fstatus; + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, FillSADetailsForLinkRecord); + + Fstatus = BuildCommonSAMad(pQueryElement, SA_ATTRIB_LINK_RECORD, + sizeof(IB_LINK_RECORD), MemAllocFlags); + _DBG_LEAVE_LVL( _DBG_LVL_FUNC_TRACE ); + return Fstatus; +} + +FSTATUS +FillSADetailsForPathRecord( + PQueryDetails pQueryElement, + uint32 MemAllocFlags + ) +{ + FSTATUS Fstatus; + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, FillSADetailsForPathRecord); + + Fstatus = BuildCommonSAMad(pQueryElement, SA_ATTRIB_PATH_RECORD, + sizeof(IB_PATH_RECORD), MemAllocFlags); + _DBG_LEAVE_LVL( _DBG_LVL_FUNC_TRACE ); + return Fstatus; +} + +FSTATUS +FillSADetailsForServiceRecord( + PQueryDetails pQueryElement, + uint32 MemAllocFlags + ) +{ + FSTATUS Fstatus; + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, FillSADetailsForServiceRecord); + + Fstatus = BuildCommonSAMad(pQueryElement, SA_ATTRIB_SERVICE_RECORD, + sizeof(IB_SERVICE_RECORD), MemAllocFlags); + _DBG_LEAVE_LVL( _DBG_LVL_FUNC_TRACE ); + return Fstatus; +} + +FSTATUS +FillSADetailsForMcMemberRecord( + PQueryDetails pQueryElement, + uint32 MemAllocFlags + ) +{ + FSTATUS Fstatus; + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, FillSADetailsForMcMemberRecord); + + Fstatus = BuildCommonSAMad(pQueryElement, SA_ATTRIB_MCMEMBER_RECORD, + sizeof(IB_MCMEMBER_RECORD), MemAllocFlags); + _DBG_LEAVE_LVL( _DBG_LVL_FUNC_TRACE ); + return Fstatus; +} + +FSTATUS +FillSADetailsForInformInfoRecord( + PQueryDetails pQueryElement, + uint32 MemAllocFlags + ) +{ + FSTATUS Fstatus; + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, FillSADetailsForInformInfoRecord); + + Fstatus = BuildCommonSAMad(pQueryElement, SA_ATTRIB_INFORM_INFO_RECORD, + sizeof(IB_INFORM_INFO_RECORD), MemAllocFlags); + _DBG_LEAVE_LVL( _DBG_LVL_FUNC_TRACE ); + return Fstatus; +} + +FSTATUS +FillSADetailsForInformInfo( + PQueryDetails pQueryElement, + uint32 MemAllocFlags + ) +{ + FSTATUS Fstatus; + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, FillSADetailsForInformInfo); + + Fstatus = BuildCommonSAMad(pQueryElement, SA_ATTRIB_INFORM_INFO, + sizeof(IB_INFORM_INFO), MemAllocFlags); + _DBG_LEAVE_LVL( _DBG_LVL_FUNC_TRACE ); + return Fstatus; +} + +FSTATUS +FillSADetailsForMultiPathRecord( + PQueryDetails pQueryElement, + uint32 MemAllocFlags + ) +{ + FSTATUS Fstatus; + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, FillSADetailsForMultiPathRecord); + + Fstatus = BuildCommonSAMad(pQueryElement, SA_ATTRIB_MULTIPATH_RECORD, + sizeof(IB_MULTIPATH_RECORD), MemAllocFlags); + pQueryElement->u.pMad->common.mr.s.Method = SUBN_ADM_GETMULTI; + _DBG_LEAVE_LVL( _DBG_LVL_FUNC_TRACE ); + return Fstatus; +} + +FSTATUS +FillSADetailsForTraceRecord( + PQueryDetails pQueryElement, + uint32 MemAllocFlags + ) +{ + FSTATUS Fstatus; + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, FillSADetailsForTraceRecord); + + Fstatus = BuildCommonSAMad(pQueryElement, SA_ATTRIB_TRACE_RECORD, + sizeof(IB_PATH_RECORD), MemAllocFlags); + pQueryElement->u.pMad->common.mr.s.Method = SUBN_ADM_GETTRACETABLE; + _DBG_LEAVE_LVL( _DBG_LVL_FUNC_TRACE ); + return Fstatus; +} + +FSTATUS +FillSADetailsForSwitchInfoRecord( + PQueryDetails pQueryElement, + uint32 MemAllocFlags + ) +{ + FSTATUS Fstatus; + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, FillSADetailsForSwitchInfoRecord); + + Fstatus = BuildCommonSAMad(pQueryElement, SA_ATTRIB_SWITCHINFO_RECORD, + sizeof(IB_SWITCHINFO_RECORD), MemAllocFlags); + _DBG_LEAVE_LVL( _DBG_LVL_FUNC_TRACE ); + return Fstatus; +} + +FSTATUS +FillSADetailsForLinearFDBRecord( + PQueryDetails pQueryElement, + uint32 MemAllocFlags + ) +{ + FSTATUS Fstatus; + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, FillSADetailsForLinearFDBRecord); + + Fstatus = BuildCommonSAMad(pQueryElement, SA_ATTRIB_LINEAR_FWDTBL_RECORD, + sizeof(IB_LINEAR_FDB_RECORD), MemAllocFlags); + _DBG_LEAVE_LVL( _DBG_LVL_FUNC_TRACE ); + return Fstatus; +} + +FSTATUS +FillSADetailsForRandomFDBRecord( + PQueryDetails pQueryElement, + uint32 MemAllocFlags + ) +{ + FSTATUS Fstatus; + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, FillSADetailsForRandomFDBRecord); + + Fstatus = BuildCommonSAMad(pQueryElement, SA_ATTRIB_RANDOM_FWDTBL_RECORD, + sizeof(IB_RANDOM_FDB_RECORD), MemAllocFlags); + _DBG_LEAVE_LVL( _DBG_LVL_FUNC_TRACE ); + return Fstatus; +} + +FSTATUS +FillSADetailsForMCastFDBRecord( + PQueryDetails pQueryElement, + uint32 MemAllocFlags + ) +{ + FSTATUS Fstatus; + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, FillSADetailsForMCastFDBRecord); + + Fstatus = BuildCommonSAMad(pQueryElement, SA_ATTRIB_MCAST_FWDTBL_RECORD, + sizeof(IB_MCAST_FDB_RECORD), MemAllocFlags); + _DBG_LEAVE_LVL( _DBG_LVL_FUNC_TRACE ); + return Fstatus; +} + +FSTATUS +FillSADetailsForVLArbTableRecord( + PQueryDetails pQueryElement, + uint32 MemAllocFlags + ) +{ + FSTATUS Fstatus; + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, FillSADetailsForVLArbTableRecord); + + Fstatus = BuildCommonSAMad(pQueryElement, SA_ATTRIB_VLARBTABLE_RECORD, + sizeof(IB_VLARBTABLE_RECORD), MemAllocFlags); + _DBG_LEAVE_LVL( _DBG_LVL_FUNC_TRACE ); + return Fstatus; +} + +FSTATUS +FillSADetailsForPKeyTableRecord( + PQueryDetails pQueryElement, + uint32 MemAllocFlags + ) +{ + FSTATUS Fstatus; + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, FillSADetailsForPKeyTableRecord); + + Fstatus = BuildCommonSAMad(pQueryElement, SA_ATTRIB_P_KEY_TABLE_RECORD, + sizeof(IB_P_KEY_TABLE_RECORD), MemAllocFlags); + _DBG_LEAVE_LVL( _DBG_LVL_FUNC_TRACE ); + return Fstatus; +} + +// common Mad, RMPP and SAHdr for a SUBN_ADM GETTABLE +void +FillCommonSADetails( + PQueryDetails pQueryElement, + IN uint16 AttribId, + IN uint32 RecordSize + ) +{ + MAD *mad; + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, FillCommonSADetails); + + pQueryElement->IsSelfCommand = FALSE; + // caller has filed in pQueryElement->SdSentCmd + DEBUG_ASSERT(pQueryElement->SdSentCmd != UnknownCommand); + + FillBaseGmpValues(pQueryElement); + + mad = pQueryElement->u.pMad; + mad->common.mr.s.R = 0; //since this is not a response, set it to 0; + mad->common.mr.s.Method = SUBN_ADM_GETTABLE; + MAD_SET_ATTRIB_ID(pQueryElement->u.pMad, AttribId); + MAD_SET_ATTRIB_MOD(mad, 0); // unused in IBA1.1 + + // 1 segment RMPP + // if ComponentMask is needed caller can set after this call + MemoryClear(&(pQueryElement->u.pSaMad->RmppHdr), sizeof(RMPP_HEADER)); + MemoryClear(&(pQueryElement->u.pSaMad->SaHdr), sizeof(SA_HDR)); + + _DBG_LEAVE_LVL( _DBG_LVL_FUNC_TRACE ); + return; +} + +// Allocate and Build +// common Mad, RMPP and SAHdr for a SUBN_ADM GETTABLE +FSTATUS +BuildCommonSAMad( + IN PQueryDetails pQueryElement, + IN uint16 AttribId, + IN uint32 RecordSize, + IN uint32 MemAllocFlags + ) +{ + // Allocate memory for the GMP with NodeRecord as payload + pQueryElement->u.pSaMad = (SA_MAD*)MemoryAllocate2AndClear(sizeof(SA_MAD), + MemAllocFlags, SUBNET_DRIVER_TAG); + if (pQueryElement->u.pSaMad == NULL) + { + return FINSUFFICIENT_MEMORY; + + } + FillCommonSADetails(pQueryElement, AttribId, RecordSize); + + pQueryElement->TotalBytesInGmp = (pQueryElement->u.pSaMad->common.BaseVersion == IB_BASE_VERSION) + ? IB_MAD_BLOCK_SIZE + : (sizeof(SA_MAD) - STL_SUBN_ADM_DATASIZE) + RecordSize; + + return FSUCCESS; +} diff --git a/IbAccess/Common/SubnetDriver/query.h b/IbAccess/Common/SubnetDriver/query.h new file mode 100644 index 0000000..a2c9129 --- /dev/null +++ b/IbAccess/Common/SubnetDriver/query.h @@ -0,0 +1,180 @@ +/* BEGIN_ICS_COPYRIGHT4 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT4 ****************************************/ +/* [ICS VERSION STRING: unknown] */ + + +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef _IBA_SD_QUERY_ +#define _IBA_SD_QUERY_ + +#ifdef __cplusplus +extern "C" { +#endif + +#define GSI_QP 1 +#define GSI_QKEY 1 + +typedef enum _SD_SENT_CMD { + UnknownCommand = 0, + GetClassportInfo, + UserQueryFabricInformation, + UserFabricOperation +} SD_SENT_CMD; + +typedef enum _QUERY_STATE { + ReadyToSend = 0, // on queue, not yet sent + NotAbleToSend, // try again later, port down, no buffers, etc + WaitingForResult, // sent, awaiting reply + BusyRetryDelay, // SA reported Busy, delay and retry + WaitingForChildToComplete, // primary request done, child queries queued + ProcessingResponse, // premptable memory allocation while process response + // this means another thread holds a reference to + // this pQueryElement, so we can change state to + // QueryDestroy, but cannot free it nor otherwise + // time it out. + QueryComplete, // query is done (or failed), ready to deliver to client + QueryDestroy // query cancelled while ProcessingResponse, destroy + // when come back from preemption in processing response +} QUERY_STATE; + + +typedef struct _QueryDetails { + LIST_ITEM QueryListItem; + boolean IsSelfCommand; + SD_SENT_CMD SdSentCmd; + QUERY_STATE QState; + CLIENT_HANDLE ClientHandle; + void *UserContext; + COMMAND_CONTROL_PARAMETERS ControlParameters; + uint64 CmdSentTime; // when last sent or tried to send + // only valid for WaitingForResult, NotAbleToSend + // Note that ReadyToSend state is not timed out + uint32 RetriesLeft; + + FSTATUS Status; + uint32 MadStatus; + + union { + struct { // QueryFabricInformation + SDK_QUERY_CALLBACK *UserCallback; + QUERY UserQuery; + QUERY_RESULT_VALUES * pClientResult; + } query; + struct { // FabricOperation + FABRIC_OPERATION_DATA FabOp; + SDK_FABRIC_OPERATION_CALLBACK *FabOpCallback; + } op; + } cmd; + + // The client query cannot be satisfied until all related serialized and + // parallel queries have completed or timed out. Serialized queries can + // only be issued after it's referring query has completed. Parallel + // queries can be issued in parallel + struct _QueryDetails *pParentQuery; + uint32 NoOfChildQuery; + char *ChildResults; + uint32 TotalBytes; + // count of Child queries which are in ProcessingResponse state and are + // holding a reference to parent but are not holding the + // pQueryList->m_Lock. hence parent query cannot be freed. + uint32 ChildProcessingResponseCount; + + uint32 TotalBytesInGmp; + union { + MAD *pMad; + MAD_RMPP *pGmp; + SA_MAD *pSaMad; + } u; + EUI64 PortGuid; // port to send query via +} QueryDetails, *PQueryDetails; + + + +typedef +FSTATUS (*PInitHandler) ( + void + ); + +typedef +FSTATUS (*PDeinitHandler) ( + void + ); + +typedef +FSTATUS (*PSendHandler) ( + PQueryDetails + ); + +typedef +FSTATUS (*PRecvHandler) ( + PQueryDetails, + void *buffer, + uint32 bufsize + ,IBT_DGRM_ELEMENT *pDgrmList + ); + +typedef struct _CA_PORT { + EUI64 CaGuid; + EUI64 PortGuid; + uint16 DefaultPkeyIndex; // index of default Pkey for this port + boolean SdSMAddressValid; + boolean bInitialized; + IB_LID Lid; + IB_SL ServiceLevel; + uint32 RemoteQp; + uint32 RemoteQKey; + EUI64 SaPortGuid; + uint8 StaticRate; // enum IB_STATIC_RATE + uint16 PkeyIndex; + uint64 SubnetPrefix; + uint32 RedirectedQP; + uint32 RedirectedQKey; + uint16 RedirectedLid; + uint8 RedirectedSL; + uint8 RedirectedStaticRate; // enum IB_STATIC_RATE + uint16 RedirectedPkeyIndex; + LIST_ITEM CaPortListItem; +} CA_PORT; + + +extern SYS_CALLBACK_ITEM * pCallbackItemObject; + +#ifdef __cplusplus +}; +#endif + +#endif // _IBA_SD_QUERY_ diff --git a/IbAccess/Common/SubnetDriver/report.c b/IbAccess/Common/SubnetDriver/report.c new file mode 100644 index 0000000..53e612e --- /dev/null +++ b/IbAccess/Common/SubnetDriver/report.c @@ -0,0 +1,262 @@ +/* BEGIN_ICS_COPYRIGHT4 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT4 ****************************************/ +/*! + + \file report.h + + $Revision$ + $Date$ + + \brief Routines to handle reports for trap events +*/ + +#include +#include +#include +#include "iba/stl_mad_priv.h" +#include +#include +#include +#include + +/*! + \brief Sends a ReportResponse message to the SM acknowledging we have received + the report message. This should stop the SM from send us the report again. +*/ +static __inline +FSTATUS +SendReportResponse(void *pContext, IBT_DGRM_ELEMENT *pReportDgrmList) +{ + FSTATUS Status; + uint32 ElementCount; + IBT_DGRM_ELEMENT *pResponseDgrmElement; + MAD *pReportMad; + MAD *pResponseMad; + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, SendReportResponse); + + // + // Get a datagram element from the SA datagram pool + // + ElementCount = 1; + Status = iba_gsi_dgrm_pool_get( sa_represp_poolhandle, &ElementCount, &pResponseDgrmElement ); +#ifdef SA_ALLOC_DEBUG + if (iba_gsi_dgrm_pool_count(sa_poolhandle) < 50) MsgOut("get sa for report: Status %d\n", Status); +#endif + if ( Status != FSUCCESS ) + { + _DBG_ERROR( ( "Failed to get DGRM Element. Status 0x%x\n", Status ) ); + goto exit; + } + + pResponseDgrmElement->Element.pContext = pContext; + pResponseDgrmElement->RemoteQP = pReportDgrmList->RemoteQP; + pResponseDgrmElement->RemoteQKey = pReportDgrmList->RemoteQKey; + pResponseDgrmElement->RemoteLID = pReportDgrmList->RemoteLID; + pResponseDgrmElement->ServiceLevel = pReportDgrmList->ServiceLevel; + pResponseDgrmElement->PortGuid = pReportDgrmList->PortGuid; + pResponseDgrmElement->PathBits = pReportDgrmList->PathBits; + pResponseDgrmElement->StaticRate = pReportDgrmList->StaticRate; + pResponseDgrmElement->PkeyIndex = pReportDgrmList->PkeyIndex; + + pReportMad = GsiDgrmGetRecvMad(pReportDgrmList); + + pResponseMad = GsiDgrmGetSendMad(pResponseDgrmElement); + + // + // Set various fields within MAD itself now + // + MemoryClear( pResponseMad, sizeof(MAD) ); + + pResponseMad->common.BaseVersion = IB_BASE_VERSION; + pResponseMad->common.MgmtClass = MCLASS_SUBN_ADM; + pResponseMad->common.ClassVersion = IB_SUBN_ADM_CLASS_VERSION; + pResponseMad->common.mr.AsReg8 = MMTHD_REPORT_RESP; + pResponseMad->common.u.NS.Status.AsReg16 = MAD_STATUS_SUCCESS; + pResponseMad->common.TransactionID = pReportMad->common.TransactionID; + pResponseMad->common.AttributeID = MCLASS_ATTRIB_ID_NOTICE; + pResponseMad->common.AttributeModifier = 0; + + pResponseDgrmElement->Element.pBufferList->ByteCount = sizeof(MAD_COMMON); + + Status = iba_gsi_post_send( GsiSAHandle, pResponseDgrmElement ); +#ifdef SA_ALLOC_DEBUG + if (iba_gsi_dgrm_pool_count(sa_poolhandle) < 50) MsgOut("send sa for report: Status %d\n", Status); +#endif + if ( Status != FSUCCESS ) + { + // + // This should not happen and if this happens it + //can be due to port status changinging to inactive + // Free the TSL DGRM Element + // + + iba_gsi_dgrm_pool_put( pResponseDgrmElement ); + _DBG_ERROR( ( "iba_gsi_post_send failed, Status = %d\n", Status ) ); + } + +exit: + _DBG_LEAVE_LVL( _DBG_LVL_FUNC_TRACE ); + return Status; +} + +/*! + \brief Validates that the fields in the report make sense +*/ +static __inline +FSTATUS +ValidateReport(IBT_DGRM_ELEMENT *pReportDgrmList) +{ + FSTATUS Status = FSUCCESS; + SA_MAD *pReportMad = (SA_MAD *)GsiDgrmGetRecvMad(pReportDgrmList); + uint32 ByteCount = pReportDgrmList->Element.pBufferList->pNextBuffer->ByteCount; + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, ValidateReport); + + if ( ByteCount < sizeof(SA_MAD) ) + { + _DBG_ERROR( ("Invalid ByteCount. Expected %d, Received %d\n", + (int)(sizeof(SA_MAD) + sizeof(IB_NOTICE)), + ByteCount) ); + Status = FERROR; + goto exit; + } + + if ( pReportDgrmList->Element.pNextElement != NULL ) + { + // Should be single element + _DBG_ERROR( ("Error Multi Element Request Received\n") ); + Status = FERROR; + goto exit; + } + + if ( pReportMad->common.AttributeID != MCLASS_ATTRIB_ID_NOTICE ) + { + // Should be a Notice Attribute ID + _DBG_ERROR( ("Invalid AttributeID. Expected %d, Received %d\n", + MCLASS_ATTRIB_ID_NOTICE, + pReportMad->common.AttributeID) ); + Status = FERROR; + goto exit; + } + + if ( !( pReportMad->common.AttributeModifier == 0 ) ) + { + // Attribute Modifier must be zero + _DBG_ERROR( ("Invalid AttributeModifier. Expected %d, Received %d\n", + 0, + pReportMad->common.AttributeModifier) ); + Status = FERROR; + } + +exit: + _DBG_LEAVE_LVL( _DBG_LVL_FUNC_TRACE ); + return Status; +} + +/*! + \brief Swaps the Notice and the Notice Details data (based on trap) fields +*/ +static __inline +void +BSwapNoticeRecord(IB_NOTICE *pNotice, boolean toHostOrder) +{ + void *pNoticeDataDetails; + uint16 trapNumber = 0; + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, BSwapNoticeRecord); + + if (! toHostOrder) + trapNumber = pNotice->u.Generic.TrapNumber; + BSWAP_IB_NOTICE(pNotice); + if (toHostOrder) + trapNumber = pNotice->u.Generic.TrapNumber; + + pNoticeDataDetails = pNotice->Data; + switch (trapNumber) + { + case SMA_TRAP_GID_NOW_IN_SERVICE: + BSWAP_TRAP_64_DETAILS((TRAP_64_DETAILS *)pNoticeDataDetails); + break; + + case SMA_TRAP_GID_OUT_OF_SERVICE: + BSWAP_TRAP_65_DETAILS((TRAP_65_DETAILS *)pNoticeDataDetails); + break; + + case SMA_TRAP_ADD_MULTICAST_GROUP: + BSWAP_TRAP_66_DETAILS((TRAP_66_DETAILS *)pNoticeDataDetails); + break; + + case SMA_TRAP_DEL_MULTICAST_GROUP: + BSWAP_TRAP_67_DETAILS((TRAP_67_DETAILS *)pNoticeDataDetails); + break; + + default: + break; + } + + _DBG_LEAVE_LVL( _DBG_LVL_FUNC_TRACE ); +} + +/*! + \brief Performs the processing required to acknowledge, validate, adjust and inform clients + when a report message has been received from the Subnet Manager +*/ +FSTATUS +ProcessReport( void *pContext, IBT_DGRM_ELEMENT *pReportDgrmList ) +{ + FSTATUS Status; + IB_NOTICE *pNotice = (IB_NOTICE *)(((SA_MAD *)GsiDgrmGetRecvMad(pReportDgrmList))->Data); + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, ProcessReport); + + Status = SendReportResponse( pContext, pReportDgrmList ); + if (Status != FSUCCESS) + { + _DBG_ERROR( ( "SendReportResponse failed, Status = %d\n", Status ) ); + /* Continue on as report still could be valid */ + Status = FSUCCESS; + } + + Status = ValidateReport( pReportDgrmList ); + if (Status != FSUCCESS) + { + _DBG_ERROR( ( "ValidateReport failed, Status = %d\n", Status ) ); + goto exit; + } + + BSwapNoticeRecord(pNotice, TRUE); + + ProcessClientTraps( pContext, pNotice, pReportDgrmList->PortGuid ); + + BSwapNoticeRecord(pNotice, FALSE); +exit: + _DBG_LEAVE_LVL( _DBG_LVL_FUNC_TRACE ); + return Status; +} diff --git a/IbAccess/Common/SubnetDriver/report.h b/IbAccess/Common/SubnetDriver/report.h new file mode 100644 index 0000000..c2283de --- /dev/null +++ b/IbAccess/Common/SubnetDriver/report.h @@ -0,0 +1,60 @@ +/* BEGIN_ICS_COPYRIGHT4 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT4 ****************************************/ +/*! + + \file report.h + + $Revision$ + $Date$ + + \brief Routines to handle reports for trap events +*/ + +#ifndef _REPORT_H_ +#define _REPORT_H_ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/*! + \brief Processes a received Report Method message + +*/ +FSTATUS ProcessReport(void *pContext, IBT_DGRM_ELEMENT *pReportDgrmList); + +#ifdef __cplusplus +}; +#endif + +#endif // _REPORT_H_ + diff --git a/IbAccess/Common/SubnetDriver/sa.c b/IbAccess/Common/SubnetDriver/sa.c new file mode 100644 index 0000000..3652214 --- /dev/null +++ b/IbAccess/Common/SubnetDriver/sa.c @@ -0,0 +1,1651 @@ +/* BEGIN_ICS_COPYRIGHT4 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT4 ****************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include + + +#if 0 // keep this around in case we need it for debugging again +void SaShowPacket(char *msg, unsigned char *packet, int length) { + _DBG_DUMP_MEMORY(_DBG_LVL_? ("%s", msg), (void*)packet, length); +} +#endif + +FSTATUS +SubnetAdmInit( + void + ) +{ + uint64 *pLocalPortGuidsList = NULL; + uint32 LocalPortGuidsCount; + FSTATUS Fstatus; + unsigned ii; + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, SubnetAdmInit); + + Fstatus = iba_sd_get_local_port_guids_alloc(&pLocalPortGuidsList, &LocalPortGuidsCount); + if (Fstatus != FSUCCESS || LocalPortGuidsCount == 0) + { + if (Fstatus == FSUCCESS) + Fstatus = FNOT_DONE; + if (pLocalPortGuidsList != NULL) + { + MemoryDeallocate(pLocalPortGuidsList); + pLocalPortGuidsList = NULL; + } + _DBG_INFO(("No Active LocalPortGuids found\n")); + _DBG_LEAVE_LVL( _DBG_LVL_FUNC_TRACE ); + return(Fstatus); + } + + for (ii = 0; ii < LocalPortGuidsCount; ii++) + { + MAD *mad; + PQueryDetails pQueryElement; + + pQueryElement = (QueryDetails*)MemoryAllocateAndClear(sizeof(QueryDetails), + FALSE, SUBNET_DRIVER_TAG); + + if (pQueryElement == NULL) + { + _DBG_ERROR(("Cannot allocate memory for QueryElement in SubnetAdmInit\n")); + _DBG_LEAVE_LVL( _DBG_LVL_FUNC_TRACE ); + return(FINSUFFICIENT_MEMORY); + } + + QListSetObj(&pQueryElement->QueryListItem, (void *)pQueryElement); + pQueryElement->IsSelfCommand = TRUE; + pQueryElement->SdSentCmd = GetClassportInfo; + pQueryElement->ControlParameters.RetryCount = g_SdParams.DefaultRetryCount; + pQueryElement->ControlParameters.Timeout = g_SdParams.DefaultRetryInterval; + + pQueryElement->u.pSaMad = (SA_MAD*)MemoryAllocateAndClear(sizeof(SA_MAD), + FALSE, + SUBNET_DRIVER_TAG); + if (pQueryElement->u.pSaMad == NULL) + { + MemoryDeallocate(pQueryElement); + _DBG_ERROR(("Cannot allocate memory for QueryElement->u.pSaMad in SubnetAdmInit\n")); + _DBG_LEAVE_LVL( _DBG_LVL_FUNC_TRACE ); + return(FINSUFFICIENT_MEMORY); + } + + mad = (MAD *)pQueryElement->u.pSaMad; + + FillBaseGmpValues(pQueryElement); + + mad->common.mr.s.R = 0; //since this is not a response, set it to 0; + mad->common.mr.s.Method = MMTHD_GET; + + MAD_SET_ATTRIB_ID(mad, MCLASS_ATTRIB_ID_CLASS_PORT_INFO); + MAD_SET_ATTRIB_MOD(mad, 0); + + // fields were initialized to 0 above + // which is what we want for a single packet RMPP request in 1.0a or 1.1 + pQueryElement->TotalBytesInGmp = (mad->common.BaseVersion == IB_BASE_VERSION) + ? IB_MAD_BLOCK_SIZE + : (sizeof(SA_MAD) - STL_SUBN_ADM_DATASIZE) + sizeof(STL_CLASS_PORT_INFO); + + pQueryElement->PortGuid = pLocalPortGuidsList[ii]; + +#if defined( DBG) || defined(IB_DEBUG) + { + CA_PORT *pCaPort; + + SpinLockAcquire(pCaPortListLock); + pCaPort = GetCaPort(pLocalPortGuidsList[ii]); + ASSERT(pCaPort != NULL); + ASSERT(pQueryElement->PortGuid == pCaPort->PortGuid); + SpinLockRelease(pCaPortListLock); + } +#endif + + SendQueryElement(pQueryElement, TRUE /*FirstAttempt*/); + } + + MemoryDeallocate(pLocalPortGuidsList); + + // Trigger the timer handler + StartTimerHandler(pTimerObject, g_SdParams.TimeInterval); + + _DBG_LEAVE_LVL( _DBG_LVL_FUNC_TRACE ); + return(FSUCCESS); +} + +// for a given SA attribute, indicate the size of the actual +// unpadded record returned +uint32 +SubnetAdmAttrToRecordSize(uint8 attribute) +{ + switch (attribute) + { + case SA_ATTRIB_INFORM_INFO: + return(sizeof(IB_INFORM_INFO)); + case SA_ATTRIB_NODE_RECORD: + return(sizeof(IB_NODE_RECORD)); + case SA_ATTRIB_PORTINFO_RECORD: + return(sizeof(IB_PORTINFO_RECORD)); + case SA_ATTRIB_SWITCHINFO_RECORD: + return(sizeof(IB_SWITCHINFO_RECORD)); + case SA_ATTRIB_LINEAR_FWDTBL_RECORD: + return(sizeof(IB_LINEAR_FDB_RECORD)); + case SA_ATTRIB_RANDOM_FWDTBL_RECORD: + return(sizeof(IB_RANDOM_FDB_RECORD)); + case SA_ATTRIB_MCAST_FWDTBL_RECORD: + return(sizeof(IB_MCAST_FDB_RECORD)); + case SA_ATTRIB_SMINFO_RECORD: + return(sizeof(IB_SMINFO_RECORD)); + case SA_ATTRIB_INFORM_INFO_RECORD: + return(sizeof(IB_INFORM_INFO_RECORD)); + case SA_ATTRIB_LINK_RECORD: + return(sizeof(IB_LINK_RECORD)); + case SA_ATTRIB_SERVICE_RECORD: + return(sizeof(IB_SERVICE_RECORD)); + case SA_ATTRIB_P_KEY_TABLE_RECORD: + return(sizeof(IB_P_KEY_TABLE_RECORD)); + case SA_ATTRIB_PATH_RECORD: + return(sizeof(IB_PATH_RECORD)); + case SA_ATTRIB_VLARBTABLE_RECORD: + return(sizeof(IB_VLARBTABLE_RECORD)); + case SA_ATTRIB_MCMEMBER_RECORD: + return(sizeof(IB_MCMEMBER_RECORD)); + case SA_ATTRIB_TRACE_RECORD: + return(sizeof(IB_TRACE_RECORD)); + case SA_ATTRIB_MULTIPATH_RECORD: + return(sizeof(IB_MULTIPATH_RECORD)); + case SA_ATTRIB_SERVICEASSOCIATION_RECORD: + return(sizeof(IB_SERVICEASSOCIATION_RECORD)); + default: + return 0; + } +} + +// look at payload len in SA reponse and compute the size of +// each record and the number of records +// also validates payload does not indicate truncation of last record +// if last was truncated, it reduces NumRecords with a warning +FSTATUS +SdComputeResponseSizes( + SA_MAD *pSaMad, + uint32 messageSize, // Size of Coalesced message + uint32 *pNumRecords, + uint32 *pPaddedRecordSize, + uint32 *pRecordSize + ) +{ + uint32 saPayload; + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, SdComputeResponseSizes); + + *pRecordSize = SubnetAdmAttrToRecordSize(pSaMad->common.AttributeID); + if (pSaMad->common.mr.AsReg8 == SUBN_ADM_GET_RESP) + { + // single record response + *pPaddedRecordSize = *pRecordSize; + *pNumRecords = 1; + return FSUCCESS; + } + // round up just in case SA omits pad bytes at end of last record + *pPaddedRecordSize = pSaMad->SaHdr.AttributeOffset*sizeof(uint64) ; + if (*pPaddedRecordSize == 0) { + _DBG_WARN(("Invalid AttributeOffset!\n" + "\tAttributeOffset........%d\n" + "\tPayloadLen.............%d\n" + "\tRecordSize.............%d\n", + pSaMad->SaHdr.AttributeOffset, + pSaMad->RmppHdr.u2.PayloadLen, + *pRecordSize)); + *pNumRecords = 0; // TBD ignore or fail request???? + _DBG_LEAVE_LVL( _DBG_LVL_FUNC_TRACE ); + return FSUCCESS; + } + // GsiCoalesceDgrm already removed extra SA_HDRs and adjusted + // messageSize to account for their removal + saPayload = messageSize - (sizeof(MAD_COMMON) + sizeof(RMPP_HEADER) + sizeof(SA_HDR)); + *pNumRecords = (saPayload + (*pPaddedRecordSize)-1) / (*pPaddedRecordSize); + + // see if last Record in list is complete + if (*pNumRecords + && (*pNumRecords-1)*(*pPaddedRecordSize)+(*pRecordSize) > saPayload) + { + // last record was truncated + _DBG_WARN(("Final Record of SA Response is truncated!\n" + "\tAttributeOffset........%d\n" + "\tPayloadLen.............%d\n" + "\tRecordSize.............%d\n", + pSaMad->SaHdr.AttributeOffset, + pSaMad->RmppHdr.u2.PayloadLen, + *pRecordSize)); + --(*pNumRecords); // TBD ignore or fail request???? + } + _DBG_INFO(("SA Response:\n" + "\tAttributeOffset........%d (%d)\n" + "\tPayloadLen.............%d\n" + "\tRecordSize.............%d\n" + "\tNumRecords.............%d\n", + pSaMad->SaHdr.AttributeOffset, + *pPaddedRecordSize, + pSaMad->RmppHdr.u2.PayloadLen, + *pRecordSize, *pNumRecords)); + + _DBG_LEAVE_LVL( _DBG_LVL_FUNC_TRACE ); + return FSUCCESS; +} + +// called with pQueryList->m_Lock held +// called with buffer==NULL and messageSize == 0 if query has timed out +// pQueryElement is in WaitingForResult, still on list +FSTATUS +SubnetAdmRecv( + PQueryDetails pQueryElement, + void *buffer, // caller removed GRH already + uint32 messageSize // caller removed GRH already + ,IBT_DGRM_ELEMENT *pDgrmList + ) +{ + QUERY_RESULT_VALUES * pClientResult = NULL; + SA_MAD *pSaMad = (SA_MAD*)buffer; + uint16 MadAttributeID; + QUERY_RESULT_TYPE QueryOutputType; + uint32 NumRecords; + uint32 RecordSize; // before padding + uint32 PaddedRecordSize; // after padding + uint8 *p; // start of next record + + uint32 i; + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, SubnetAdmRecv); + + if(pQueryElement->pParentQuery != NULL) + { + return SdHandleChildQuery(pQueryElement, buffer, messageSize); + } + // Handle the case if buffer == NULL; + + if (buffer == NULL) //Timeout + { + _DBG_ERROR(("SA Query Timed Out <%d ms, %d retries>\n", + pQueryElement->ControlParameters.Timeout, + pQueryElement->ControlParameters.RetryCount)); + + DEBUG_ASSERT(pQueryElement->SdSentCmd != UserQueryFabricInformation + || pQueryElement->cmd.query.pClientResult == NULL); + pQueryElement->Status = FTIMEOUT; + pQueryElement->MadStatus = 0; // unknown, no response + goto done; + } + + // Include MAD Status and reserved field + pQueryElement->MadStatus = (pSaMad->common.u.NS.Reserved1 << 16| + pSaMad->common.u.NS.Status.AsReg16); + + if (pSaMad->common.u.NS.Status.AsReg16 == MAD_STATUS_SUCCESS) + { + _DBG_INFO(("Successful MAD completion received\n")); + pQueryElement->Status = FSUCCESS; + } else if (pQueryElement->SdSentCmd == UserQueryFabricInformation + && pSaMad->common.u.NS.Status.AsReg16 == MAD_STATUS_SA_NO_RECORDS) + { + _DBG_INFO(("No Records MAD completion received\n")); + pQueryElement->Status = FSUCCESS; + } else { + _DBG_ERROR(("Failed MAD completion received, Status <0x%x: %s>, Port 0x%016"PRIx64"\n", + pSaMad->common.u.NS.Status.AsReg16, + _DBG_PTR(iba_sd_mad_status_msg(pQueryElement->MadStatus)), + pQueryElement->PortGuid)); + pQueryElement->Status = FERROR; + DEBUG_ASSERT(pQueryElement->SdSentCmd != UserQueryFabricInformation + || pQueryElement->cmd.query.pClientResult == NULL); + goto done; + } + + // + // Based on the attribute ID figure out how to process the response + // + MadAttributeID = pSaMad->common.AttributeID; + BSWAP_SA_HDR(&pSaMad->SaHdr); + if (pQueryElement->SdSentCmd == UserFabricOperation) + { + // Fabric Operation Response + switch (MadAttributeID) + { + case SA_ATTRIB_SERVICE_RECORD: + { + IB_SERVICE_RECORD *pServiceRecord; + + pServiceRecord = (IB_SERVICE_RECORD*)pSaMad->Data; + BSWAP_IB_SERVICE_RECORD(pServiceRecord); + _DBG_INFO(("Processing SERVICE_RECORD..... NumRecords[1]\n")); + pQueryElement->cmd.op.FabOp.Value.ServiceRecordValue.ServiceRecord = + *pServiceRecord; + } + break; + case SA_ATTRIB_MCMEMBER_RECORD: + { + IB_MCMEMBER_RECORD *pMcMemberRecord; + + pMcMemberRecord = (IB_MCMEMBER_RECORD*)pSaMad->Data; + BSWAP_IB_MCMEMBER_RECORD(pMcMemberRecord); + if (g_SdParams.MinPktLifeTime) { + uint32 PktLifeTime = TimeoutTimeMsToMult(g_SdParams.MinPktLifeTime); + if (PktLifeTime > pMcMemberRecord->PktLifeTime) + pMcMemberRecord->PktLifeTime = PktLifeTime; + } + _DBG_INFO(("Processing MCMEMBER_RECORD..... NumRecords[1]\n")); + pQueryElement->cmd.op.FabOp.Value.McMemberRecordValue.McMemberRecord = + *pMcMemberRecord; + } + break; + case SA_ATTRIB_INFORM_INFO: + { + IB_INFORM_INFO *pInformInfo; + + pInformInfo = (IB_INFORM_INFO*)pSaMad->Data; + BSWAP_INFORM_INFO(pInformInfo); + _DBG_INFO(("Processing IB_INFORM_INFO..... NumRecords[1]\n")); + pQueryElement->cmd.op.FabOp.Value.InformInfo = + *pInformInfo; + } + default: + break; + } + goto done; + } + + if (pQueryElement->SdSentCmd != UserQueryFabricInformation) + { + DEBUG_ASSERT(0); + goto done; + } + + // Fabric Query + QueryOutputType = pQueryElement->cmd.query.UserQuery.OutputType; + pQueryElement->QState = ProcessingResponse; // holds our reference + // unlock so we can prempt during memory allocates below + SpinLockRelease(&pQueryList->m_Lock); + + if (pSaMad->common.u.NS.Status.AsReg16 == MAD_STATUS_SA_NO_RECORDS) { + NumRecords = 0; + } else { + (void)SdComputeResponseSizes( pSaMad, messageSize, &NumRecords, + &PaddedRecordSize, &RecordSize); + } + + switch (MadAttributeID) + { + case SA_ATTRIB_NODE_RECORD: + { + if (! g_SdParams.ValidateNodeRecord) + { + for (i = 0, p = pSaMad->Data; + i < NumRecords; i++, p+=PaddedRecordSize) + { + BSWAP_IB_NODE_RECORD((IB_NODE_RECORD*)p); + } + } else { + int dodump = 0; + + /* while we byte swap, also validate + * we are checking for 0 Node or Port GUIDs. This generally + * indicates an RMPP or SA problem where records get skewed + */ + for (i = 0, p = pSaMad->Data; + i < NumRecords; i++, p+=PaddedRecordSize) + { +//#define VALID_GUID(guid) ((((guid) >> 40) == 0x66a) || (((guid) >> 40) == 0x2c9)) +#define VALID_GUID(guid) ((guid) != 0) + BSWAP_IB_NODE_RECORD((IB_NODE_RECORD*)p); + if ( ! VALID_GUID(((IB_NODE_RECORD*)p)->NodeInfoData.NodeGUID) + || ! VALID_GUID(((IB_NODE_RECORD*)p)->NodeInfoData.PortGUID)) +#undef VALID_GUID + { + dodump=1; +#ifdef ICS_LOGGING + _DBG_ERROR(("Corrupted Node Record %d of %d offset 0x%x", i+1, NumRecords, (unsigned)(p - pSaMad->Data))); + _DBG_DUMP_MEMORY(_DBG_LVL_ERROR, ("Corrupted Node Record"), (void*)p, sizeof(IB_NODE_RECORD)); +#else + _DBG_DUMP_MEMORY(_DBG_LVL_ERROR, + ("Corrupted Node Record %d of %d offset 0x%x", i+1, NumRecords, (unsigned)(p - pSaMad->Data)), + (void*)p, sizeof(IB_NODE_RECORD)); +#endif + } + } + if (dodump && g_SdParams.DumpInvalidNodeRecord) + { + IBT_ELEMENT *pElement; + + _DBG_DUMP_MEMORY(_DBG_LVL_ERROR, ("Coalesed"), (void*)buffer, messageSize); + + for (i=0,pElement = &pDgrmList->Element; pElement; i++,pElement=pElement->pNextElement) + { + IBT_BUFFER *pBufferHdr = pElement->pBufferList->pNextBuffer; +#ifdef ICS_LOGGING + _DBG_ERROR(("Dgrm %d", i)); + _DBG_DUMP_MEMORY(_DBG_LVL_ERROR, ("Dgrm"), (void*)pBufferHdr->pData, pBufferHdr->ByteCount); +#else + _DBG_DUMP_MEMORY(_DBG_LVL_ERROR, ("Dgrm %d", i), (void*)pBufferHdr->pData, pBufferHdr->ByteCount); +#endif + } + } + } + _DBG_INFO(("Processing IB_NODE_RECORD..... NumRecords[%d]\n", + NumRecords)); + switch(QueryOutputType) + { + case (OutputTypeLid): + { + PLID_RESULTS pLidResults; + + _DBG_INFO(("Extracting LIDs from NodeRecord....\n")); + + pClientResult = (QUERY_RESULT_VALUES*)MemoryAllocate2AndClear(sizeof(QUERY_RESULT_VALUES) + + (NumRecords * sizeof(LID_RESULTS)), + IBA_MEM_FLAG_PREMPTABLE|IBA_MEM_FLAG_SHORT_DURATION, SUBNET_DRIVER_TAG); + if (pClientResult == NULL) + goto failalloc; + pClientResult->ResultDataSize = NumRecords * sizeof(LID_RESULTS); + + if (NumRecords > 0 ) + { + pLidResults = (PLID_RESULTS)pClientResult->QueryResult; + pLidResults->NumLids = NumRecords; + for (i = 0, p = pSaMad->Data; + i < NumRecords; i++, p+=PaddedRecordSize) + { + pLidResults->Lids[i] = + ((IB_NODE_RECORD*)p)->RID.s.LID; + } + } + break; + } + + case (OutputTypeSystemImageGuid): + case (OutputTypeNodeGuid): + case (OutputTypePortGuid): + { + PGUID_RESULTS pGuidResults; + + pClientResult = (QUERY_RESULT_VALUES*)MemoryAllocate2AndClear(sizeof(QUERY_RESULT_VALUES) + + (NumRecords * sizeof(GUID_RESULTS)), + IBA_MEM_FLAG_PREMPTABLE|IBA_MEM_FLAG_SHORT_DURATION, SUBNET_DRIVER_TAG); + if (pClientResult == NULL) + goto failalloc; + pClientResult->ResultDataSize = NumRecords * sizeof(GUID_RESULTS); + switch (QueryOutputType) + { + case (OutputTypeSystemImageGuid): + + _DBG_INFO(("Extracting SystemImageGUIDs from NodeRecord - NumRecords[%d]\n", + NumRecords)); + if (NumRecords > 0 ) + { + pGuidResults = (PGUID_RESULTS)pClientResult->QueryResult; + pGuidResults->NumGuids = NumRecords; + for (i = 0, p = pSaMad->Data; + i < NumRecords; i++, p+=PaddedRecordSize) + { + pGuidResults->Guids[i] = + ((IB_NODE_RECORD*)p)->NodeInfoData.SystemImageGUID; + } + } + break; + case (OutputTypeNodeGuid): + + _DBG_INFO(("Extracting NodeGUIDs from NodeRecord - NumRecords[%d]\n", + NumRecords)); + if (NumRecords > 0 ) + { + pGuidResults = (PGUID_RESULTS)pClientResult->QueryResult; + pGuidResults->NumGuids = NumRecords; + for (i = 0, p = pSaMad->Data; + i < NumRecords; i++, p+=PaddedRecordSize) + { + + pGuidResults->Guids[i] = + ((IB_NODE_RECORD*)p)->NodeInfoData.NodeGUID; + } + } + break; + case (OutputTypePortGuid): + + _DBG_INFO(("Extracting PortGUIDS from NodeRecord - NumRecords[%d]\n", + NumRecords)); + if (NumRecords > 0 ) + { + pGuidResults = (PGUID_RESULTS)pClientResult->QueryResult; + pGuidResults->NumGuids = NumRecords; + for (i = 0, p = pSaMad->Data; + i < NumRecords; i++, p+=PaddedRecordSize) + { + pGuidResults->Guids[i] = + ((IB_NODE_RECORD*)p)->NodeInfoData.PortGUID; + + } + } + break; + default: + break; + } + break; + } + case (OutputTypeNodeDesc): + { + PNODEDESC_RESULTS pNodeDescResults; + + + pClientResult = (QUERY_RESULT_VALUES*)MemoryAllocate2AndClear(sizeof(QUERY_RESULT_VALUES) + + (NumRecords * sizeof(NODEDESC_RESULTS)), + IBA_MEM_FLAG_PREMPTABLE|IBA_MEM_FLAG_SHORT_DURATION, SUBNET_DRIVER_TAG); + if (pClientResult == NULL) + goto failalloc; + pClientResult->ResultDataSize = NumRecords * sizeof(NODEDESC_RESULTS); + + _DBG_INFO(("Extracting NodeDescription from NodeRecord - NumRecords[%d]\n", + NumRecords)); + if ( NumRecords > 0 ) + { + pNodeDescResults = (PNODEDESC_RESULTS)pClientResult->QueryResult; + pNodeDescResults->NumDescs = NumRecords; + for (i = 0, p = pSaMad->Data; + i < NumRecords; i++, p+=PaddedRecordSize) + { + pNodeDescResults->NodeDescs[i] = + ((IB_NODE_RECORD*)p)->NodeDescData; + } + } + break; + } + + case (OutputTypeNodeRecord): + { + PNODE_RECORD_RESULTS pNodeInfoResults; + + + pClientResult = (QUERY_RESULT_VALUES*)MemoryAllocate2AndClear(sizeof(QUERY_RESULT_VALUES) + + (NumRecords * sizeof(NODE_RECORD_RESULTS)), + IBA_MEM_FLAG_PREMPTABLE|IBA_MEM_FLAG_SHORT_DURATION, SUBNET_DRIVER_TAG); + if (pClientResult == NULL) + goto failalloc; + pClientResult->ResultDataSize = NumRecords * sizeof(NODE_RECORD_RESULTS); + + _DBG_INFO(("Extracting complete NodeRecord - NumRecords[%d]\n", + NumRecords)); + if ( NumRecords > 0 ) + { + pNodeInfoResults = (PNODE_RECORD_RESULTS)pClientResult->QueryResult; + pNodeInfoResults->NumNodeRecords = NumRecords; + + for (i = 0, p = pSaMad->Data; + i < NumRecords; i++, p+=PaddedRecordSize) + { + pNodeInfoResults->NodeRecords[i] = + *((IB_NODE_RECORD*)p); + } + } + break; + } + case (OutputTypePathRecord): + { + uint64 *pDestPortGuidsList; + uint32 DestPortGuidsCount; + QueryDetails **pChildQueryElements; + + extern uint32 NumTotalPorts; + + if(NumTotalPorts == 0) + { + _DBG_INFO(("Total Number of Ports turns out to be zero\n")); + break; + } + + if ( NumRecords == 0) + { + pClientResult = (QUERY_RESULT_VALUES*)MemoryAllocate2AndClear(sizeof(QUERY_RESULT_VALUES), + IBA_MEM_FLAG_PREMPTABLE|IBA_MEM_FLAG_SHORT_DURATION, SUBNET_DRIVER_TAG); + if (pClientResult == NULL) + goto failalloc; + pClientResult->ResultDataSize = 0; + break; + } + + pDestPortGuidsList = (EUI64*)MemoryAllocate2AndClear((sizeof(EUI64)*NumRecords), + IBA_MEM_FLAG_PREMPTABLE|IBA_MEM_FLAG_SHORT_DURATION, + SUBNET_DRIVER_TAG); + + DestPortGuidsCount = NumRecords; + if (pDestPortGuidsList == NULL) + { + _DBG_ERROR(("Cannot allocate memory for DestPortGuids\n")); + goto failalloc2; + } + + for (i = 0, p = pSaMad->Data; + i < NumRecords; i++, p+=PaddedRecordSize) + { + pDestPortGuidsList[i] = + ((IB_NODE_RECORD*)p)->NodeInfoData.PortGUID; + } + + // Multistaged query + pChildQueryElements = BuildSAChildQueriesForPathRecord( + pQueryElement, + pDestPortGuidsList, + DestPortGuidsCount); + MemoryDeallocate(pDestPortGuidsList); + if(! pChildQueryElements) + { + goto failalloc2; + } + SpinLockAcquire(&pQueryList->m_Lock); + if (FreeCancelledQueryElement(pQueryElement)) + { + SpinLockRelease(&pQueryList->m_Lock); + for(i = 0; im_Lock); + goto ret; + } + pQueryElement->QState = WaitingForChildToComplete; + //Leave pQueryElement on pQueryList + DEBUG_ASSERT(pQueryElement->SdSentCmd == UserQueryFabricInformation); + DEBUG_ASSERT(pQueryElement->cmd.query.pClientResult == NULL); + // start the child queries + pQueryElement->NoOfChildQuery = DestPortGuidsCount; + for(i = 0; iQueryListItem); + } + SpinLockRelease(&pQueryList->m_Lock); + MemoryDeallocate(pChildQueryElements); + SpinLockAcquire(&pQueryList->m_Lock); + // completion processing will processes pChildQueryList + ScheduleCompletionProcessing(); + goto ret; + } + default: + break; + } + break; + } + + case SA_ATTRIB_PORTINFO_RECORD: + { + for (i = 0, p = pSaMad->Data; + i < NumRecords; i++, p+=PaddedRecordSize) + { + BSWAP_IB_PORTINFO_RECORD((IB_PORTINFO_RECORD*)p, TRUE); + } + _DBG_INFO(("Processing IB_PORTINFO_RECORD..... NumRecords[%d]\n", + NumRecords)); + + switch(QueryOutputType) + { + + case (OutputTypePortInfoRecord): + { + PPORTINFO_RECORD_RESULTS pPortInfoResults; + + pClientResult = (QUERY_RESULT_VALUES*)MemoryAllocate2AndClear(sizeof(QUERY_RESULT_VALUES) + + (NumRecords * sizeof(PORTINFO_RECORD_RESULTS)), + IBA_MEM_FLAG_PREMPTABLE|IBA_MEM_FLAG_SHORT_DURATION, SUBNET_DRIVER_TAG); + if (pClientResult == NULL) + goto failalloc; + pClientResult->ResultDataSize = NumRecords * sizeof(PORTINFO_RECORD_RESULTS); + + _DBG_INFO(("Extracting complete PortInfoRecords - NumRecords[%d]\n", + NumRecords)); + + if ( NumRecords > 0) + { + pPortInfoResults = (PPORTINFO_RECORD_RESULTS)pClientResult->QueryResult; + pPortInfoResults->NumPortInfoRecords = NumRecords; + + for (i = 0, p = pSaMad->Data; + i < NumRecords; i++, p+=PaddedRecordSize) + { + pPortInfoResults->PortInfoRecords[i] = + *((IB_PORTINFO_RECORD*)p); + } + } + break; + } + default: + break; + } + break; + } + case SA_ATTRIB_SMINFO_RECORD: + { + for (i = 0, p = pSaMad->Data; + i < NumRecords; i++, p+=PaddedRecordSize) + { + BSWAP_IB_SMINFO_RECORD((IB_SMINFO_RECORD*)p); + } + + _DBG_INFO(("Processing IB_SMINFO_RECORD..... NumRecords[%d]\n", + NumRecords)); + switch(QueryOutputType) + { + + case (OutputTypeSMInfoRecord): + { + PSMINFO_RECORD_RESULTS pSMInfoResults; + + pClientResult = (QUERY_RESULT_VALUES*)MemoryAllocate2AndClear(sizeof(QUERY_RESULT_VALUES) + + (NumRecords * sizeof(SMINFO_RECORD_RESULTS)), + IBA_MEM_FLAG_PREMPTABLE|IBA_MEM_FLAG_SHORT_DURATION, SUBNET_DRIVER_TAG); + if (pClientResult == NULL) + goto failalloc; + pClientResult->ResultDataSize = NumRecords * sizeof(SMINFO_RECORD_RESULTS); + + _DBG_INFO(("Extracting complete SMInfoRecords - NumRecords[%d]\n", + NumRecords)); + if ( NumRecords > 0) + { + pSMInfoResults = (PSMINFO_RECORD_RESULTS)pClientResult->QueryResult; + pSMInfoResults->NumSMInfoRecords = NumRecords; + + for (i = 0, p = pSaMad->Data; + i < NumRecords; i++, p+=PaddedRecordSize) + { + pSMInfoResults->SMInfoRecords[i] = + *((IB_SMINFO_RECORD*)p); + } + } + break; + } + default: + break; + } + break; + } + case SA_ATTRIB_LINK_RECORD: + { + for (i = 0, p = pSaMad->Data; + i < NumRecords; i++, p+=PaddedRecordSize) + { + BSWAP_IB_LINK_RECORD((IB_LINK_RECORD*)p); + } + _DBG_INFO(("Processing IB_LINK_RECORD..... NumRecords[%d]\n", + NumRecords)); + switch(QueryOutputType) + { + case (OutputTypeLinkRecord): + { + PLINK_RECORD_RESULTS pLinkResults; + + pClientResult = (QUERY_RESULT_VALUES*)MemoryAllocate2AndClear(sizeof(QUERY_RESULT_VALUES) + + (NumRecords * sizeof(LINK_RECORD_RESULTS)), + IBA_MEM_FLAG_PREMPTABLE|IBA_MEM_FLAG_SHORT_DURATION, SUBNET_DRIVER_TAG); + if (pClientResult == NULL) + goto failalloc; + pClientResult->ResultDataSize = NumRecords * sizeof(LINK_RECORD_RESULTS); + + _DBG_INFO(("Extracting complete LinkRecords - NumRecords[%d]\n", + NumRecords)); + if ( NumRecords > 0) + { + pLinkResults = (PLINK_RECORD_RESULTS)pClientResult->QueryResult; + pLinkResults->NumLinkRecords = NumRecords; + + for (i = 0, p = pSaMad->Data; + i < NumRecords; i++, p+=PaddedRecordSize) + { + pLinkResults->LinkRecords[i] = *((IB_LINK_RECORD*)p); + } + } + break; + } + default: + break; + } + break; + } + case SA_ATTRIB_PATH_RECORD: + { + uint32 PktLifeTime = 0; + if (g_SdParams.MinPktLifeTime) + PktLifeTime = TimeoutTimeMsToMult(g_SdParams.MinPktLifeTime); + for (i = 0, p = pSaMad->Data; + i < NumRecords; i++, p+=PaddedRecordSize) + { + BSWAP_IB_PATH_RECORD((IB_PATH_RECORD*)p); + if (PktLifeTime > ((IB_PATH_RECORD*)p)->PktLifeTime) + ((IB_PATH_RECORD*)p)->PktLifeTime = PktLifeTime; + } + _DBG_INFO(("Processing IB_PATH_RECORD..... NumRecords[%d]\n", + NumRecords)); + switch(QueryOutputType) + { + + case (OutputTypePathRecord): + { + PPATH_RESULTS pPathRecordResults; + + pClientResult = (QUERY_RESULT_VALUES*)MemoryAllocate2AndClear(sizeof(QUERY_RESULT_VALUES) + + (NumRecords * sizeof(PATH_RESULTS)), + IBA_MEM_FLAG_PREMPTABLE|IBA_MEM_FLAG_SHORT_DURATION, SUBNET_DRIVER_TAG); + if (pClientResult == NULL) + goto failalloc; + pClientResult->ResultDataSize = NumRecords * sizeof(PATH_RESULTS); + + _DBG_INFO(("Extracting complete PathRecord - NumRecords[%d]\n", + NumRecords)); + if ( NumRecords > 0) + { + pPathRecordResults = (PPATH_RESULTS)pClientResult->QueryResult; + pPathRecordResults->NumPathRecords = NumRecords; + + for (i = 0, p = pSaMad->Data; + i < NumRecords; i++, p+=PaddedRecordSize) + { + pPathRecordResults->PathRecords[i] = + *((IB_PATH_RECORD*)p); + } + } + break; + } + default: + break; + } + break; + } + case SA_ATTRIB_SERVICE_RECORD: + { + for (i = 0, p = pSaMad->Data; + i < NumRecords; i++, p+=PaddedRecordSize) + { + BSWAP_IB_SERVICE_RECORD((IB_SERVICE_RECORD*)p); + } + _DBG_INFO(("Processing IB_SERVICE_RECORD..... NumRecords[%d]\n", + NumRecords)); + + switch(QueryOutputType) + { + + case (OutputTypeServiceRecord): + { + PSERVICE_RECORD_RESULTS pServiceResults; + + pClientResult = (QUERY_RESULT_VALUES*)MemoryAllocate2AndClear(sizeof(QUERY_RESULT_VALUES) + + (NumRecords * sizeof(SERVICE_RECORD_RESULTS)), + IBA_MEM_FLAG_PREMPTABLE|IBA_MEM_FLAG_SHORT_DURATION, SUBNET_DRIVER_TAG); + if (pClientResult == NULL) + goto failalloc; + pClientResult->ResultDataSize = NumRecords * sizeof(SERVICE_RECORD_RESULTS); + + _DBG_INFO(("Extracting complete ServiceRecords - NumRecords[%d]\n", + NumRecords)); + if ( NumRecords > 0) + { + pServiceResults = (PSERVICE_RECORD_RESULTS)pClientResult->QueryResult; + pServiceResults->NumServiceRecords = NumRecords; + for (i = 0, p = pSaMad->Data; + i < NumRecords; i++, p+=PaddedRecordSize) + { + pServiceResults->ServiceRecords[i] = *((IB_SERVICE_RECORD*)p); + } + } + break; + } + default: + break; + } + break; + } + case SA_ATTRIB_MCMEMBER_RECORD: + { + uint32 PktLifeTime = 0; + if (g_SdParams.MinPktLifeTime) + PktLifeTime = TimeoutTimeMsToMult(g_SdParams.MinPktLifeTime); + for (i = 0, p = pSaMad->Data; + i < NumRecords; i++, p+=PaddedRecordSize) + { + BSWAP_IB_MCMEMBER_RECORD((IB_MCMEMBER_RECORD*)p); + if (PktLifeTime > ((IB_MCMEMBER_RECORD*)p)->PktLifeTime) + ((IB_MCMEMBER_RECORD*)p)->PktLifeTime = PktLifeTime; + } + _DBG_INFO(("Processing IB_MCMEMBER_RECORD..... NumRecords[%d]\n", + NumRecords)); + + switch(QueryOutputType) + { + + case (OutputTypeMcMemberRecord): + { + PMCMEMBER_RECORD_RESULTS pMcMemberResults; + + pClientResult = (QUERY_RESULT_VALUES*)MemoryAllocate2AndClear(sizeof(QUERY_RESULT_VALUES) + + (NumRecords * sizeof(MCMEMBER_RECORD_RESULTS)), + IBA_MEM_FLAG_PREMPTABLE|IBA_MEM_FLAG_SHORT_DURATION, SUBNET_DRIVER_TAG); + if (pClientResult == NULL) + goto failalloc; + pClientResult->ResultDataSize = NumRecords * sizeof(MCMEMBER_RECORD_RESULTS); + + _DBG_INFO(("Extracting complete McMemberRecords - NumRecords[%d]\n", + NumRecords)); + if ( NumRecords > 0) + { + pMcMemberResults = (PMCMEMBER_RECORD_RESULTS)pClientResult->QueryResult; + pMcMemberResults->NumMcMemberRecords = NumRecords; + for (i = 0, p = pSaMad->Data; + i < NumRecords; i++, p+=PaddedRecordSize) + { + pMcMemberResults->McMemberRecords[i] = *((IB_MCMEMBER_RECORD*)p); + } + } + break; + } + default: + break; + } + break; + } + case SA_ATTRIB_INFORM_INFO_RECORD: + { + for (i = 0, p = pSaMad->Data; + i < NumRecords; i++, p+=PaddedRecordSize) + { + BSWAP_IB_INFORM_INFO_RECORD((IB_INFORM_INFO_RECORD*)p); + } + _DBG_INFO(("Processing IB_INFORM_INFO_RECORD..... NumRecords[%d]\n", + NumRecords)); + + switch(QueryOutputType) + { + + case (OutputTypeInformInfoRecord): + { + PINFORM_INFO_RECORD_RESULTS pInformInfoResults; + + pClientResult = (QUERY_RESULT_VALUES*)MemoryAllocate2AndClear(sizeof(QUERY_RESULT_VALUES) + + (NumRecords * sizeof(INFORM_INFO_RECORD_RESULTS)), + IBA_MEM_FLAG_PREMPTABLE|IBA_MEM_FLAG_SHORT_DURATION, SUBNET_DRIVER_TAG); + if (pClientResult == NULL) + goto failalloc; + pClientResult->ResultDataSize = NumRecords * sizeof(INFORM_INFO_RECORD_RESULTS); + + _DBG_INFO(("Extracting complete InformInfoRecords - NumRecords[%d]\n", + NumRecords)); + if ( NumRecords > 0) + { + pInformInfoResults = (PINFORM_INFO_RECORD_RESULTS)pClientResult->QueryResult; + pInformInfoResults->NumInformInfoRecords = NumRecords; + for (i = 0, p = pSaMad->Data; + i < NumRecords; i++, p+=PaddedRecordSize) + { + pInformInfoResults->InformInfoRecords[i] = *((IB_INFORM_INFO_RECORD*)p); + } + } + break; + } + default: + break; + } + break; + } + case SA_ATTRIB_TRACE_RECORD: + { + for (i = 0, p = pSaMad->Data; + i < NumRecords; i++, p+=PaddedRecordSize) + { + BSWAP_IB_TRACE_RECORD((IB_TRACE_RECORD*)p); + } + _DBG_INFO(("Processing IB_TRACE_RECORD..... NumRecords[%d]\n", + NumRecords)); + + switch(QueryOutputType) + { + + case (OutputTypeTraceRecord): + { + PTRACE_RECORD_RESULTS pTraceRecordResults; + + pClientResult = (QUERY_RESULT_VALUES*)MemoryAllocate2AndClear(sizeof(QUERY_RESULT_VALUES) + + (NumRecords * sizeof(TRACE_RECORD_RESULTS)), + IBA_MEM_FLAG_PREMPTABLE|IBA_MEM_FLAG_SHORT_DURATION, SUBNET_DRIVER_TAG); + if (pClientResult == NULL) + goto failalloc; + pClientResult->ResultDataSize = NumRecords * sizeof(TRACE_RECORD_RESULTS); + + _DBG_INFO(("Extracting complete TraceRecord - NumRecords[%d]\n", + NumRecords)); + if ( NumRecords > 0) + { + pTraceRecordResults = (PTRACE_RECORD_RESULTS)pClientResult->QueryResult; + pTraceRecordResults->NumTraceRecords = NumRecords; + + for (i = 0, p = pSaMad->Data; + i < NumRecords; i++, p+=PaddedRecordSize) + { + pTraceRecordResults->TraceRecords[i] = + *((IB_TRACE_RECORD*)p); + // convert encrypted fields + pTraceRecordResults->TraceRecords[i].GIDPrefix ^= IB_TRACE_RECORD_COMP_ENCRYPT_MASK; + pTraceRecordResults->TraceRecords[i].NodeID ^= IB_TRACE_RECORD_COMP_ENCRYPT_MASK; + pTraceRecordResults->TraceRecords[i].ChassisID ^= IB_TRACE_RECORD_COMP_ENCRYPT_MASK; + pTraceRecordResults->TraceRecords[i].EntryPortID ^= IB_TRACE_RECORD_COMP_ENCRYPT_MASK; + pTraceRecordResults->TraceRecords[i].ExitPortID ^= IB_TRACE_RECORD_COMP_ENCRYPT_MASK; + } + } + break; + } + default: + break; + } + break; + } + case SA_ATTRIB_SWITCHINFO_RECORD: + { + for (i = 0, p = pSaMad->Data; + i < NumRecords; i++, p+=PaddedRecordSize) + { + BSWAP_IB_SWITCHINFO_RECORD((IB_SWITCHINFO_RECORD*)p); + } + _DBG_INFO(("Processing IB_SWITCHINFO_RECORD..... NumRecords[%d]\n", + NumRecords)); + + switch(QueryOutputType) + { + + case (OutputTypeSwitchInfoRecord): + { + PSWITCHINFO_RECORD_RESULTS pSwitchInfoResults; + + pClientResult = (QUERY_RESULT_VALUES*)MemoryAllocate2AndClear(sizeof(QUERY_RESULT_VALUES) + + (NumRecords * sizeof(SWITCHINFO_RECORD_RESULTS)), + IBA_MEM_FLAG_PREMPTABLE|IBA_MEM_FLAG_SHORT_DURATION, SUBNET_DRIVER_TAG); + if (pClientResult == NULL) + goto failalloc; + pClientResult->ResultDataSize = NumRecords * sizeof(SWITCHINFO_RECORD_RESULTS); + + _DBG_INFO(("Extracting complete SwitchInfoRecords - NumRecords[%d]\n", + NumRecords)); + if ( NumRecords > 0) + { + pSwitchInfoResults = (PSWITCHINFO_RECORD_RESULTS)pClientResult->QueryResult; + pSwitchInfoResults->NumSwitchInfoRecords = NumRecords; + for (i = 0, p = pSaMad->Data; + i < NumRecords; i++, p+=PaddedRecordSize) + { + pSwitchInfoResults->SwitchInfoRecords[i] = *((IB_SWITCHINFO_RECORD*)p); + } + } + break; + } + default: + break; + } + break; + } + case SA_ATTRIB_LINEAR_FWDTBL_RECORD: + { + for (i = 0, p = pSaMad->Data; + i < NumRecords; i++, p+=PaddedRecordSize) + { + BSWAP_IB_LINEAR_FDB_RECORD((IB_LINEAR_FDB_RECORD*)p); + } + _DBG_INFO(("Processing IB_LINEAR_FDB_RECORD..... NumRecords[%d]\n", + NumRecords)); + + switch(QueryOutputType) + { + + case (OutputTypeLinearFDBRecord): + { + PLINEAR_FDB_RECORD_RESULTS pLinearFDBResults; + + pClientResult = (QUERY_RESULT_VALUES*)MemoryAllocate2AndClear(sizeof(QUERY_RESULT_VALUES) + + (NumRecords * sizeof(LINEAR_FDB_RECORD_RESULTS)), + IBA_MEM_FLAG_PREMPTABLE|IBA_MEM_FLAG_SHORT_DURATION, SUBNET_DRIVER_TAG); + if (pClientResult == NULL) + goto failalloc; + pClientResult->ResultDataSize = NumRecords * sizeof(LINEAR_FDB_RECORD_RESULTS); + + _DBG_INFO(("Extracting complete LinearFDBRecords - NumRecords[%d]\n", + NumRecords)); + if ( NumRecords > 0) + { + pLinearFDBResults = (PLINEAR_FDB_RECORD_RESULTS)pClientResult->QueryResult; + pLinearFDBResults->NumLinearFDBRecords = NumRecords; + for (i = 0, p = pSaMad->Data; + i < NumRecords; i++, p+=PaddedRecordSize) + { + pLinearFDBResults->LinearFDBRecords[i] = *((IB_LINEAR_FDB_RECORD*)p); + } + } + break; + } + default: + break; + } + break; + } + case SA_ATTRIB_RANDOM_FWDTBL_RECORD: + { + for (i = 0, p = pSaMad->Data; + i < NumRecords; i++, p+=PaddedRecordSize) + { + BSWAP_IB_RANDOM_FDB_RECORD((IB_RANDOM_FDB_RECORD*)p); + } + _DBG_INFO(("Processing IB_RANDOM_FDB_RECORD..... NumRecords[%d]\n", + NumRecords)); + + switch(QueryOutputType) + { + + case (OutputTypeRandomFDBRecord): + { + PRANDOM_FDB_RECORD_RESULTS pRandomFDBResults; + + pClientResult = (QUERY_RESULT_VALUES*)MemoryAllocate2AndClear(sizeof(QUERY_RESULT_VALUES) + + (NumRecords * sizeof(RANDOM_FDB_RECORD_RESULTS)), + IBA_MEM_FLAG_PREMPTABLE|IBA_MEM_FLAG_SHORT_DURATION, SUBNET_DRIVER_TAG); + if (pClientResult == NULL) + goto failalloc; + pClientResult->ResultDataSize = NumRecords * sizeof(RANDOM_FDB_RECORD_RESULTS); + + _DBG_INFO(("Extracting complete RandomFDBRecords - NumRecords[%d]\n", + NumRecords)); + if ( NumRecords > 0) + { + pRandomFDBResults = (PRANDOM_FDB_RECORD_RESULTS)pClientResult->QueryResult; + pRandomFDBResults->NumRandomFDBRecords = NumRecords; + for (i = 0, p = pSaMad->Data; + i < NumRecords; i++, p+=PaddedRecordSize) + { + pRandomFDBResults->RandomFDBRecords[i] = *((IB_RANDOM_FDB_RECORD*)p); + } + } + break; + } + default: + break; + } + break; + } + case SA_ATTRIB_MCAST_FWDTBL_RECORD: + { + for (i = 0, p = pSaMad->Data; + i < NumRecords; i++, p+=PaddedRecordSize) + { + BSWAP_IB_MCAST_FDB_RECORD((IB_MCAST_FDB_RECORD*)p); + } + _DBG_INFO(("Processing IB_MCAST_FDB_RECORD..... NumRecords[%d]\n", + NumRecords)); + + switch(QueryOutputType) + { + + case (OutputTypeMCastFDBRecord): + { + PMCAST_FDB_RECORD_RESULTS pMCastFDBResults; + + pClientResult = (QUERY_RESULT_VALUES*)MemoryAllocate2AndClear(sizeof(QUERY_RESULT_VALUES) + + (NumRecords * sizeof(MCAST_FDB_RECORD_RESULTS)), + IBA_MEM_FLAG_PREMPTABLE|IBA_MEM_FLAG_SHORT_DURATION, SUBNET_DRIVER_TAG); + if (pClientResult == NULL) + goto failalloc; + pClientResult->ResultDataSize = NumRecords * sizeof(MCAST_FDB_RECORD_RESULTS); + + _DBG_INFO(("Extracting complete MCastFDBRecords - NumRecords[%d]\n", + NumRecords)); + if ( NumRecords > 0) + { + pMCastFDBResults = (PMCAST_FDB_RECORD_RESULTS)pClientResult->QueryResult; + pMCastFDBResults->NumMCastFDBRecords = NumRecords; + for (i = 0, p = pSaMad->Data; + i < NumRecords; i++, p+=PaddedRecordSize) + { + pMCastFDBResults->MCastFDBRecords[i] = *((IB_MCAST_FDB_RECORD*)p); + } + } + break; + } + default: + break; + } + break; + } + case SA_ATTRIB_VLARBTABLE_RECORD: + { + for (i = 0, p = pSaMad->Data; + i < NumRecords; i++, p+=PaddedRecordSize) + { + BSWAP_IB_VLARBTABLE_RECORD((IB_VLARBTABLE_RECORD*)p); + } + _DBG_INFO(("Processing IB_VLARBTABLE_RECORD..... NumRecords[%d]\n", + NumRecords)); + + switch(QueryOutputType) + { + + case (OutputTypeVLArbTableRecord): + { + PVLARBTABLE_RECORD_RESULTS pVLArbTableResults; + + pClientResult = (QUERY_RESULT_VALUES*)MemoryAllocate2AndClear(sizeof(QUERY_RESULT_VALUES) + + (NumRecords * sizeof(VLARBTABLE_RECORD_RESULTS)), + IBA_MEM_FLAG_PREMPTABLE|IBA_MEM_FLAG_SHORT_DURATION, SUBNET_DRIVER_TAG); + if (pClientResult == NULL) + goto failalloc; + pClientResult->ResultDataSize = NumRecords * sizeof(VLARBTABLE_RECORD_RESULTS); + + _DBG_INFO(("Extracting complete VLArbTableRecords - NumRecords[%d]\n", + NumRecords)); + if ( NumRecords > 0) + { + pVLArbTableResults = (PVLARBTABLE_RECORD_RESULTS)pClientResult->QueryResult; + pVLArbTableResults->NumVLArbTableRecords = NumRecords; + for (i = 0, p = pSaMad->Data; + i < NumRecords; i++, p+=PaddedRecordSize) + { + pVLArbTableResults->VLArbTableRecords[i] = *((IB_VLARBTABLE_RECORD*)p); + } + } + break; + } + default: + break; + } + break; + } + case SA_ATTRIB_P_KEY_TABLE_RECORD: + { + for (i = 0, p = pSaMad->Data; + i < NumRecords; i++, p+=PaddedRecordSize) + { + BSWAP_IB_P_KEY_TABLE_RECORD((IB_P_KEY_TABLE_RECORD*)p); + } + _DBG_INFO(("Processing IB_P_KEY_TABLE_RECORD..... NumRecords[%d]\n", + NumRecords)); + + switch(QueryOutputType) + { + + case (OutputTypePKeyTableRecord): + { + PPKEYTABLE_RECORD_RESULTS pPKeyTableResults; + + pClientResult = (QUERY_RESULT_VALUES*)MemoryAllocate2AndClear(sizeof(QUERY_RESULT_VALUES) + + (NumRecords * sizeof(PKEYTABLE_RECORD_RESULTS)), + IBA_MEM_FLAG_PREMPTABLE|IBA_MEM_FLAG_SHORT_DURATION, SUBNET_DRIVER_TAG); + if (pClientResult == NULL) + goto failalloc; + pClientResult->ResultDataSize = NumRecords * sizeof(PKEYTABLE_RECORD_RESULTS); + + _DBG_INFO(("Extracting complete PKeyTableRecords - NumRecords[%d]\n", + NumRecords)); + if ( NumRecords > 0) + { + pPKeyTableResults = (PPKEYTABLE_RECORD_RESULTS)pClientResult->QueryResult; + pPKeyTableResults->NumPKeyTableRecords = NumRecords; + for (i = 0, p = pSaMad->Data; + i < NumRecords; i++, p+=PaddedRecordSize) + { + pPKeyTableResults->PKeyTableRecords[i] = *((IB_P_KEY_TABLE_RECORD*)p); + } + } + break; + } + default: + break; + } + break; + } + default: + break; + } + SpinLockAcquire(&pQueryList->m_Lock); + if (FreeCancelledQueryElement(pQueryElement)) + goto ret; + DEBUG_ASSERT(pQueryElement->SdSentCmd == UserQueryFabricInformation); + DEBUG_ASSERT(pQueryElement->cmd.query.pClientResult == NULL); + pQueryElement->cmd.query.pClientResult = pClientResult; + if (NULL != pClientResult) + { + pClientResult->Status = pQueryElement->Status; + pClientResult->MadStatus = pQueryElement->MadStatus; + } + +done: + // Insert the Queryelement into the CompletionList + QListRemoveItem( &pQueryList->m_List, &pQueryElement->QueryListItem); + pQueryElement->QState = QueryComplete; + LQListInsertHead(pCompletionList, &pQueryElement->QueryListItem); + ScheduleCompletionProcessing(); +ret: + _DBG_LEAVE_EXT(_DBG_LVL_FUNC_TRACE); + return (FSUCCESS); + +failalloc: + _DBG_ERROR(("Cannot allocate memory for SA Response\n")); +failalloc2: + SpinLockAcquire(&pQueryList->m_Lock); + if (FreeCancelledQueryElement(pQueryElement)) + goto ret; + DEBUG_ASSERT(pQueryElement->SdSentCmd == UserQueryFabricInformation); + DEBUG_ASSERT(pQueryElement->cmd.query.pClientResult == NULL); + pQueryElement->Status = FINSUFFICIENT_MEMORY; + pQueryElement->MadStatus = 0; + goto done; +} + + +// called with pQueryList->m_Lock already held +// This handles the 2nd tier of a 2 tiered query +// currently only 2nd tier is a GetTable for PathRecord +// called with buffer==NULL and messageSize == 0 if query has timed out +// pQueryElement is in WaitingForResult, still on list +FSTATUS +SdHandleChildQuery( + PQueryDetails pQueryElement, + void *buffer, // caller removed GRH already + uint32 messageSize // caller removed GRH already + ) +{ + //FSTATUS Fstatus = FERROR; + QUERY_RESULT_VALUES * pClientResult = NULL; + uint32 NumRecords; + uint32 RecordSize; + uint32 PaddedRecordSize; + uint32 PreviousNumPathRecords = 0; + uint32 PrevDataSize = 0; + SA_MAD *pSaMad = (SA_MAD*)buffer; + char *temp; + PPATH_RESULTS pPathResults = NULL; + PQueryDetails pRootQueryElement = pQueryElement->pParentQuery; + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, SdHandleChildQuery); + //Check for the Parent Query + // pQueryList->m_Lock already held + // this does not dereference pParentQuery + if (! QListIsItemInList(&pQueryList->m_List,&pRootQueryElement->QueryListItem)) + { + _DBG_INFO(("Could not find the root queryelement\n")); + goto childdone; + } + + if (buffer == NULL) //Timeout + { + _DBG_ERROR(("SA Query Timed Out <%d ms, %d retries>\n", + pQueryElement->ControlParameters.Timeout, + pQueryElement->ControlParameters.RetryCount)); + pQueryElement->Status = FTIMEOUT; + pQueryElement->MadStatus = 0; // unknown, no response + goto done; + } + // Include MAD Status and reserved field + pQueryElement->MadStatus = (pSaMad->common.u.NS.Reserved1 << 16| + pSaMad->common.u.NS.Status.AsReg16); + if (pSaMad->common.u.NS.Status.AsReg16 == MAD_STATUS_SA_NO_RECORDS) + { + _DBG_INFO(("No Records MAD completion received\n")); + } else if (pSaMad->common.u.NS.Status.AsReg16 != MAD_STATUS_SUCCESS) { + _DBG_ERROR(("Failed MAD completion received, Status <0x%x: %s>, Port 0x%016"PRIx64"\n", + pSaMad->common.u.NS.Status.AsReg16, + _DBG_PTR(iba_sd_mad_status_msg(pQueryElement->MadStatus)), + pQueryElement->PortGuid)); + pQueryElement->Status = FERROR; + goto done; + } + + pQueryElement->Status = FSUCCESS; + _DBG_INFO(("Successful MAD completion received\n")); + BSWAP_SA_HDR(&pSaMad->SaHdr); + + DEBUG_ASSERT(pRootQueryElement->SdSentCmd == UserQueryFabricInformation); + pRootQueryElement->ChildProcessingResponseCount++; // holds ref to parent + pQueryElement->QState = ProcessingResponse; // prevent timeout of child + SpinLockRelease(&pQueryList->m_Lock); + + // This mutex prevents races between multiple child processes updating + // their parents pClientResult at the same time. In reality, since there + // is one thread for SD GSA callbacks, there will be no contention for + // this mutex, hence there is no advantage to putting it into the + // parent query element. Also note that for parent queries, the + // pClientResult of the parent is not modified until all children are done + MutexAcquire(pChildGrowParentMutex); + if(pRootQueryElement->cmd.query.pClientResult) + { + PrevDataSize = pRootQueryElement->cmd.query.pClientResult->ResultDataSize; + pPathResults =(PPATH_RESULTS)pRootQueryElement->cmd.query.pClientResult->QueryResult; + PreviousNumPathRecords = pPathResults->NumPathRecords; + }else + { + PrevDataSize = sizeof(PATH_RESULTS) - sizeof(IB_PATH_RECORD); + PreviousNumPathRecords = 0; + } + + if (pSaMad->common.u.NS.Status.AsReg16 == MAD_STATUS_SA_NO_RECORDS) + { + NumRecords = 0; + } else { + (void)SdComputeResponseSizes(pSaMad, messageSize, &NumRecords, + &PaddedRecordSize, &RecordSize); + } + if(NumRecords) + { + uint32 ResBuffSize = 0; + uint32 PathRecSize = NumRecords*RecordSize; + + ResBuffSize = sizeof(QUERY_RESULT_VALUES) + + PathRecSize + PrevDataSize; + + pClientResult = (QUERY_RESULT_VALUES*)MemoryAllocate2AndClear(ResBuffSize, + IBA_MEM_FLAG_PREMPTABLE|IBA_MEM_FLAG_SHORT_DURATION, + SUBNET_DRIVER_TAG); + if (pClientResult != NULL) + { + uint8* p; + uint32 i; + IB_PATH_RECORD *pIbPathRecDest; + uint32 PktLifeTime = 0; + + pClientResult->Status = FSUCCESS; + pClientResult->MadStatus = pQueryElement->MadStatus; + pClientResult->ResultDataSize = PathRecSize + PrevDataSize; + pPathResults = (PPATH_RESULTS)pClientResult->QueryResult; + if (g_SdParams.MinPktLifeTime) { + PktLifeTime = TimeoutTimeMsToMult(g_SdParams.MinPktLifeTime); + } + + pIbPathRecDest = pPathResults->PathRecords; + for (i = 0, p = pSaMad->Data; + i < NumRecords; + i++, p+=PaddedRecordSize, pIbPathRecDest++) + { + BSWAP_IB_PATH_RECORD((IB_PATH_RECORD*)p); + MemoryCopy(pIbPathRecDest, p, sizeof(IB_PATH_RECORD)); + if (PktLifeTime > pIbPathRecDest->PktLifeTime) + pIbPathRecDest->PktLifeTime = PktLifeTime; + } + if(PreviousNumPathRecords>0) + { + //Append the Previous Data + temp = (char *)pPathResults->PathRecords; + temp = temp + PathRecSize; + pPathResults = + (PPATH_RESULTS)pRootQueryElement->cmd.query.pClientResult->QueryResult; + MemoryCopy(temp, + pPathResults->PathRecords, + PreviousNumPathRecords * RecordSize); + MemoryDeallocate(pRootQueryElement->cmd.query.pClientResult); + + } + pPathResults = (PPATH_RESULTS)pClientResult->QueryResult; + pPathResults->NumPathRecords = PreviousNumPathRecords + NumRecords; + pRootQueryElement->cmd.query.pClientResult = pClientResult; + }else { + _DBG_ERROR( ("Cannot allocate memory for QueryElement\n")); + } + } + MutexRelease(pChildGrowParentMutex); + SpinLockAcquire(&pQueryList->m_Lock); + pRootQueryElement->ChildProcessingResponseCount--; + // children can't be cancelled directly + DEBUG_ASSERT(pQueryElement->QState != QueryDestroy); + if (FreeCancelledQueryElement(pRootQueryElement)) + { + // parent has been cancelled, child is done but no parent + goto childdone; + } + +done: + // Associate this child to the parent + (pRootQueryElement->NoOfChildQuery)--; + if(pRootQueryElement->NoOfChildQuery == 0) + { + ASSERT(pRootQueryElement->QState == WaitingForChildToComplete); + //Remove Parent from Qlist and insert it into CompletionList //NOTENOTE + // pQueryList->m_Lock already held + QListRemoveItem( &pQueryList->m_List, (LIST_ITEM *)pRootQueryElement ); + + //Update the status from WaitingForChild to QueryComplete + + pRootQueryElement->QState = QueryComplete; + + // Insert the parent QueryElement into the CompletionList + LQListInsertHead(pCompletionList, &pRootQueryElement->QueryListItem); + } +childdone: + AtomicDecrementVoid(&ChildQueryActive); + QListRemoveItem( &pQueryList->m_List, &pQueryElement->QueryListItem); + if (buffer == NULL) + { + // called within TimerHandler, defer destroy to premptable context + pQueryElement->QState = QueryDestroy; + LQListInsertHead(pCompletionList, &pQueryElement->QueryListItem); + } else { + // call free in a premptable context + SpinLockRelease(&pQueryList->m_Lock); + FreeQueryElement(pQueryElement); + SpinLockAcquire(&pQueryList->m_Lock); + } + // run CompletionQueue to queue next child queries or complete + // parent as appropriate + ScheduleCompletionProcessing(); + _DBG_LEAVE_EXT(_DBG_LVL_FUNC_TRACE); + return(FSUCCESS); +} + +////////////////////////////////////////////////////// +// called without pQueryList->m_Lock held +// pRootQueryElement is in ProcessingResponse state, so we can access it +// returns a list of Child queries which have been built and initialized +// but have not yet been places on ChildQueryList, so they have not yet +// been started +QueryDetails ** +BuildSAChildQueriesForPathRecord( + PQueryDetails pRootQueryElement, + uint64 *pDestPortGuidsList, + uint32 DestPortGuidsCount + ) +{ + uint32 i; + QueryDetails *pQueryElement; + QueryDetails **pChildQueryElements; + FSTATUS status; + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, BuildSAChildQueriesForPathRecord); + + pChildQueryElements = (QueryDetails**)MemoryAllocate2AndClear( + sizeof(QueryDetails*)*DestPortGuidsCount, + IBA_MEM_FLAG_PREMPTABLE|IBA_MEM_FLAG_SHORT_DURATION, + SUBNET_DRIVER_TAG); + if (NULL == pChildQueryElements) + { + _DBG_ERROR(("Cannot allocate memory for list of Child SA Queries\n")); + goto done; + } + + for(i = 0; iQueryListItem, (void *)pQueryElement); + + pQueryElement->ControlParameters = pRootQueryElement->ControlParameters; + + pQueryElement->SdSentCmd = UserQueryFabricInformation; + pQueryElement->cmd.query.UserQuery.InputType = InputTypePortGuidPair; + pQueryElement->cmd.query.UserQuery.OutputType = OutputTypePathRecord; + pQueryElement->cmd.query.UserQuery.InputValue.PortGuidPair.DestPortGuid= + pDestPortGuidsList[i]; + pQueryElement->cmd.query.UserQuery.InputValue.PortGuidPair.SourcePortGuid = + pRootQueryElement->PortGuid; + pQueryElement->cmd.query.pClientResult = NULL; + pQueryElement->PortGuid = pRootQueryElement->PortGuid; + // do not associate directly to client, we let destruction of our parent + // be our control. + pQueryElement->ClientHandle = NULL; + + status = ValidateAndFillSDQuery(pQueryElement, + IBA_MEM_FLAG_PREMPTABLE|IBA_MEM_FLAG_SHORT_DURATION); + if (FSUCCESS != status) + { + _DBG_ERROR(("Unable to allocate Mad for Child SA Query\n")); + MemoryDeallocate(pQueryElement); + goto failalloc; + } + + //Update the parent pointer + pQueryElement->pParentQuery = pRootQueryElement; + pQueryElement->QState = ReadyToSend; + + pChildQueryElements[i] = pQueryElement; + } + +done: + _DBG_LEAVE_EXT(_DBG_LVL_FUNC_TRACE); + return pChildQueryElements; + +failalloc: + // we failed at i, free i-1 to 0 + while (i > 0) + FreeQueryElement(pChildQueryElements[--i]); + MemoryDeallocate(pChildQueryElements); + pChildQueryElements = NULL; + goto done; +} diff --git a/IbAccess/Common/SubnetDriver/sd_common.c b/IbAccess/Common/SubnetDriver/sd_common.c new file mode 100644 index 0000000..11d4a8f --- /dev/null +++ b/IbAccess/Common/SubnetDriver/sd_common.c @@ -0,0 +1,151 @@ +/* BEGIN_ICS_COPYRIGHT6 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT6 ****************************************/ + +#include "stl_sd.h" + +static const char* const SdQueryInputTypeText[] = { + "InputTypeNoInput", + "InputTypeNodeType", + "InputTypeSystemImageGuid", + "InputTypeNodeGuid", + "InputTypePortGuid", + "InputTypePortGid", + "InputTypeMcGid", + "InputTypePortGuidPair", + "InputTypeGidPair", + "InputTypePathRecord", +#ifdef IB_STACK_OPENIB + "InputTypePathRecordNetworkOrder", +#endif + "InputTypeLid", + "InputTypePKey", + "InputTypeSL", + "InputTypeIndex", + "InputTypeServiceId", + "InputTypeNodeDesc", + "InputTypeServiceRecord", + "InputTypeMcMemberRecord", + "InputTypePortGuidList", + "InputTypeGidList", + "InputTypeMultiPathRecord", +}; + +const char* iba_sd_query_input_type_msg(QUERY_INPUT_TYPE code) +{ + if (code < 0 || code >= (int)(sizeof(SdQueryInputTypeText)/sizeof(char*))) + return "Unknown SD Query Input Type"; + else + return SdQueryInputTypeText[code]; +} + +static const char* const SdQueryResultTypeText[] = { + "OutputTypeSystemImageGuid", + "OutputTypeNodeGuid", + "OutputTypePortGuid", + "OutputTypeLid", + "OutputTypeGid", + "OutputTypeNodeDesc", + "OutputTypePathRecord", +#ifdef IB_STACK_OPENIB + "OutputTypePathRecordNetworkOrder", +#endif + "OutputTypeNodeRecord", + "OutputTypePortInfoRecord", + "OutputTypeSMInfoRecord", + "OutputTypeLinkRecord", + "OutputTypeServiceRecord", + "OutputTypeMcMemberRecord", + "OutputTypeInformInfoRecord", + "OutputTypeTraceRecord", + "OutputTypeSwitchInfoRecord", + "OutputTypeLinearFDBRecord", + "OutputTypeRandomFDBRecord", + "OutputTypeMCastFDBRecord", + "OutputTypeVLArbTableRecord", + "OutputTypePKeyTableRecord", + "OutputTypeVfInfoRecord", /* VF_RECORD_RESULTS is set of VF info records */ + // PM query results + "OutputTypePaRecord", /* PA_PACKET_RESULTS complete PA SinglePacketRespRecords */ + "OutputTypePaTableRecord", /* PA_TABLE_PACKET_RESULTS complete PA MultiPacketRespRecords */ +}; + +const char* iba_sd_query_result_type_msg(QUERY_RESULT_TYPE code) +{ + if (code < 0 || code >= (int)(sizeof(SdQueryResultTypeText)/sizeof(char*))) + return "Unknown SD Query Result Type"; + else + return SdQueryResultTypeText[code]; +} + +static const char* const SdFabricOpTypeText[] = { + "FabOpSetServiceRecord", + "FabOpDeleteServiceRecord", + "FabOpSetMcMemberRecord", + "FabOpJoinMcGroup", + "FabOpLeaveMcGroup", + "FabOpDeleteMcMemberRecord", + "FabOpSetInformInfo", +}; + +const char* iba_sd_fabric_op_type_msg(FABRIC_OPERATION_TYPE code) +{ + if (code < 0 || code >= (int)(sizeof(SdFabricOpTypeText)/sizeof(char*))) + return "Unknown SD Fabric Op Type"; + else + return SdFabricOpTypeText[code]; +} + +// upper 8 bits of MAD_STATUS_SA_* fields from ib_sa_records.h +static const char* const SdSAStatusText[] = { + "Success", // not used by code below + "Insufficient SA Resources", + "Invalid SA Request", + "No SA Records", + "Too Many SA Records", + "Invalid GID in SA Request", + "Insufficient Components in SA Request" +}; + +const char* iba_sd_mad_status_msg(uint32 code) +{ + // this is a little more complex than most due to bitfields and reserved + // values + MAD_STATUS madStatus; + + madStatus.AsReg16 = code; // ignore reserved bits in Sd MadStatus + if (code == MAD_STATUS_SUCCESS || (code & 0xff)) + return iba_mad_status_msg(madStatus); // standard mad status fields + else { + code = madStatus.S.ClassSpecific; // SA specific status code field + if (code >= (unsigned)(sizeof(SdSAStatusText)/sizeof(char*))) + return "Unknown SA Mad Status"; + else + return SdSAStatusText[code]; + } +} diff --git a/IbAccess/Common/SubnetDriver/sdc.c b/IbAccess/Common/SubnetDriver/sdc.c new file mode 100644 index 0000000..03e3e0f --- /dev/null +++ b/IbAccess/Common/SubnetDriver/sdc.c @@ -0,0 +1,705 @@ +/* BEGIN_ICS_COPYRIGHT4 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT4 ****************************************/ + + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//Refer this macro only in one c file +#ifdef ICS_LOGGING +_IB_DBG_PARAM_BLOCK(_DBG_LVL_ALL,_DBG_BREAK_ENABLE,SUBNET_DRIVER_TAG,"SubnetDrv",MOD_SDI,Sdi); +#else +_IB_DBG_PARAM_BLOCK(_DBG_LVL_ALL,_DBG_BREAK_ENABLE,SUBNET_DRIVER_TAG,"SubnetDrv"); +#endif +SYS_CALLBACK_ITEM * pCallbackItemObject = NULL; +TIMER * pTimerObject = NULL; +ATOMIC_UINT IsTimerStarted; +ATOMIC_UINT SdWorkItemQueued; +ATOMIC_UINT SdWorkItemsInProcess; +boolean SdUnloading = FALSE; + +SD_CONFIG_PARAMS g_SdParams = SD_DEFAULT_CONFIG_PARAMS; + +FSTATUS +SdCommonCreate( + void + ) +{ + // + // This is where we would put common code that needs to execute when we + // get a device open request. Currently we have nothing to do here. + // + return(FSUCCESS); +} + +FSTATUS +SdCommonClose( + void + ) +{ + // + // This is where we would put common code that needs to execute when we + // get a device close request. Currently we have nothing to do here. + // + return(FSUCCESS); +} + +FSTATUS +InitializeDriver( + void + ) +{ + FSTATUS Fstatus; + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, InitializeDriver); + + // Read the global programmable driver parameters + (void)ReadDriverTunables(); + + _TRC_REGISTER(); + + // Initialize the work item queue required to + // be called in the timer handler function + pCallbackItemObject = InitializeWorkItemqueue(); + if(pCallbackItemObject == NULL) + { + _DBG_ERROR(("Could not initialize WorkItemqueue\n")); + _DBG_BREAK; + + _DBG_LEAVE_EXT(_DBG_LVL_FUNC_TRACE); + return(FINSUFFICIENT_RESOURCES); + } + + // Initialize the timer handlers + pTimerObject = (TIMER*)MemoryAllocateAndClear(sizeof(TIMER),FALSE,SUBNET_DRIVER_TAG); + if(pTimerObject == NULL) + { + _DBG_ERROR(("Memory Allocation for Timer Object Failed\n")); + _DBG_BREAK; + UnloadDriver(); + + _DBG_LEAVE_EXT(_DBG_LVL_FUNC_TRACE); + return(FINSUFFICIENT_RESOURCES); + } + + TimerInitState(pTimerObject); + + if (TimerInit(pTimerObject, TimerHandler, NULL) != TRUE) + { + _DBG_ERROR(("TimerInit failed \n")); + _DBG_BREAK; + UnloadDriver(); + + _DBG_LEAVE_EXT(_DBG_LVL_FUNC_TRACE); + return(FINSUFFICIENT_RESOURCES); + } + + + // Initialize the IB Transport components that we need + Fstatus = InitializeIbt(); + + if (Fstatus != FSUCCESS) + { + _DBG_ERROR(("FStatus <0x%x> initializing IB Transport\n", Fstatus)); + _DBG_BREAK; + UnloadDriver(); + + _DBG_LEAVE_EXT(_DBG_LVL_FUNC_TRACE); + return(Fstatus); + } + + // Initialize some data structures + // pQueryList, pCompletionList, pClientList, pCaPortList + pQueryList = LQListAllocateAndInit(FALSE, SUBNET_DRIVER_TAG); + if (! pQueryList) + { + _DBG_ERROR(("Unable to initialize client list\n")); + _DBG_BREAK; + UnloadDriver(); + + _DBG_LEAVE_EXT(_DBG_LVL_FUNC_TRACE); + return(FINSUFFICIENT_MEMORY); + } + + pCompletionList = LQListAllocateAndInit(FALSE, SUBNET_DRIVER_TAG); + + if (! pCompletionList) + { + _DBG_ERROR(("Unable to initialize Completion list\n")); + _DBG_BREAK; + UnloadDriver(); + + _DBG_LEAVE_EXT(_DBG_LVL_FUNC_TRACE); + return(FINSUFFICIENT_MEMORY); + } + + Fstatus = InitializeList(&pClientList, + &pClientListLock); + + if (Fstatus != FSUCCESS) + { + _DBG_ERROR(("Status 0x%x initializing client list\n", Fstatus)); + _DBG_BREAK; + UnloadDriver(); + + _DBG_LEAVE_EXT(_DBG_LVL_FUNC_TRACE); + return(Fstatus); + } + + pChildQueryList = LQListAllocateAndInit(FALSE, SUBNET_DRIVER_TAG); + + if (! pChildQueryList) + { + _DBG_ERROR(("Unable to initialize ChildQueryList\n")); + _DBG_BREAK; + UnloadDriver(); + + _DBG_LEAVE_EXT(_DBG_LVL_FUNC_TRACE); + return(FINSUFFICIENT_MEMORY); + } + + pChildGrowParentMutex = (MUTEX*)MemoryAllocateAndClear(sizeof(MUTEX),FALSE,SUBNET_DRIVER_TAG); + if(pChildGrowParentMutex == NULL) + { + _DBG_ERROR(("Memory Allocation for Mutex Failed\n")); + _DBG_BREAK; + UnloadDriver(); + + _DBG_LEAVE_EXT(_DBG_LVL_FUNC_TRACE); + return(FINSUFFICIENT_RESOURCES); + } + + MutexInitState(pChildGrowParentMutex); + + if (MutexInit(pChildGrowParentMutex) != FSUCCESS) + { + _DBG_ERROR(("MutexInit failed \n")); + _DBG_BREAK; + UnloadDriver(); + + _DBG_LEAVE_EXT(_DBG_LVL_FUNC_TRACE); + return(FINSUFFICIENT_RESOURCES); + } + + Fstatus = InitializeList(&pCaPortList, &pCaPortListLock); + + if (Fstatus != FSUCCESS) + { + _DBG_ERROR(("Status 0x%x initializing CaPortList\n", Fstatus)); + _DBG_BREAK; + UnloadDriver(); + + _DBG_LEAVE_EXT(_DBG_LVL_FUNC_TRACE); + return(Fstatus); + } + + SetDefaultClientParameters(); + + // Allocate and Initialize pLocalCaInfoLock SPIN_LOCK Structure + // and also register for a port change event callback + pLocalCaInfoLock = (SPIN_LOCK*)MemoryAllocateAndClear(sizeof(SPIN_LOCK), + FALSE, SUBNET_DRIVER_TAG); + + if(pLocalCaInfoLock == NULL) + { + _DBG_ERROR(("Memory Allocation failed for pLocalCaInfoLock\n")); + _DBG_BREAK; + UnloadDriver(); + + _DBG_LEAVE_EXT(_DBG_LVL_FUNC_TRACE); + return (FINSUFFICIENT_MEMORY); + } + + SpinLockInitState(pLocalCaInfoLock); + + if (SpinLockInit(pLocalCaInfoLock)!= TRUE) + { + _DBG_ERROR(("Cannot initialize local CA info lock\n")); + _DBG_BREAK; + UnloadDriver(); + + _DBG_LEAVE_EXT(_DBG_LVL_FUNC_TRACE); + return (FINSUFFICIENT_MEMORY); + } + + AtomicWrite(&Outstanding, 0); + + SubscribeInitialize(); +#ifdef USE_SD_MULTICAST + Fstatus = MulticastInitialize(); + if (Fstatus != FSUCCESS) + { + _DBG_ERROR(("Fstatus <0x%x> MulticastInitialize\n", Fstatus)); + _DBG_BREAK; + UnloadDriver(); + + _DBG_LEAVE_EXT(_DBG_LVL_FUNC_TRACE); + return(Fstatus); + } +#endif + // + // Register with the IB transport to get notifications when there is + // a local CA event (e.g. new link inserted, new CA inserted etc.). + // NOTENOTE1:Chech which typecase is required + // + + Fstatus = iba_register_notify(LocalCaChangeCallback, + NULL, IB_NOTIFY_ANY|IB_NOTIFY_ON_REGISTER, IB_NOTIFY_SYNC, &CaNotifyHandle); + + if (Fstatus != FSUCCESS) + { + _DBG_ERROR(("Fstatus <0x%x> RegisterNotify\n", Fstatus)); + _DBG_BREAK; + UnloadDriver(); + + _DBG_LEAVE_EXT(_DBG_LVL_FUNC_TRACE); + return(Fstatus); + + } + + _DBG_LEAVE_EXT(_DBG_LVL_FUNC_TRACE); + return(FSUCCESS); +} + + +FSTATUS +UnloadDriver( + void + ) +{ + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, UnloadDriver); + + _TRC_UNREGISTER(); + +#ifdef USE_SD_MULTICAST + MulticastTerminate(); +#endif + SubscribeTerminate(); + + // DeregisterNotify Handle + if (CaNotifyHandle) + { + iba_deregister_notify(CaNotifyHandle); + CaNotifyHandle = NULL; + } + + SdUnloading = TRUE; // prevent new queries + + // wait for any sys callbacks or outstanding queries to complete/timeout + while (! LQListIsEmpty(pQueryList) || ! LQListIsEmpty(pCompletionList) + || ! LQListIsEmpty(pChildQueryList) || AtomicRead(&SdWorkItemQueued) + || AtomicRead(&SdWorkItemsInProcess)) + ThreadSuspend(10); + + // Destroy Timer Object + if(pTimerObject) + { + TimerDestroy(pTimerObject); + MemoryDeallocate(pTimerObject); + pTimerObject = NULL; + } + + if(pCallbackItemObject ) + { + SysCallbackPut(pCallbackItemObject ); + pCallbackItemObject = NULL; + } + + // Destroy the Datagram pool and deregister with GSI + DeRegisterWithGSI(); + + // DeInit Lists and destroy + LQListDeallocate(pQueryList); + pQueryList = NULL; + + LQListDeallocate(pCompletionList); + pCompletionList = NULL; + + DestroyList(pClientList,pClientListLock); + pClientList = NULL; + pClientListLock = NULL; + + LQListDeallocate(pChildQueryList); + pChildQueryList = NULL; + + DestroyList(pCaPortList,pCaPortListLock); + pCaPortList = NULL; + pCaPortListLock = NULL; + + if(pChildGrowParentMutex) + { + MutexDestroy(pChildGrowParentMutex); + MemoryDeallocate(pChildGrowParentMutex); + pChildGrowParentMutex = NULL; + } + + // Deallocate global memory and destroy spinlocks + if(pLocalCaInfo) + { + uint32 count; + for(count=0; countm_Lock); + if (TimerCallbackStopped(pTimerObject)) + goto unlock; // stale timer callback + + if (AtomicExchange(&IsTimerStarted,0) == 0) { + _DBG_PRINT(_DBG_LVL_WARN,("TimerHandler was 0\n")); + } + + while(NULL != (pListItem = QListGetItemAt(&pQueryList->m_List, index))) + { + pQueryElement = (PQueryDetails)pListItem->pObject; + + DEBUG_ASSERT(pQueryElement->QState != QueryComplete); + DEBUG_ASSERT(pQueryElement->QState != QueryDestroy); + if (pQueryElement->QState == ReadyToSend) + { + // was unable to send due to MaxOutstanding or GSI buffers, + // see if it can be sent now + SendQueryElement(pQueryElement, FALSE /*! FirstAttempt*/); + StartTimer = TRUE; + index++; + } else if (((pQueryElement->QState == WaitingForResult) + || (pQueryElement->QState == NotAbleToSend)) + && ((CurrMicroTime - pQueryElement->CmdSentTime) > + (pQueryElement->ControlParameters.Timeout * 1000))) + { + // Command has not complected with in the predefined expected time + // Check for Retrycount and resend the command + if (pQueryElement->QState == WaitingForResult) { + // it was sent and timed out + AtomicDecrementVoid(&Outstanding); + } + if(pQueryElement->RetriesLeft > 0) + { //Retry it + _DBG_WARN (("Timeout has occured on a Query! \n")); + _DBG_INFO(("Retrying a QueryElement Retries Left = %d\n", + pQueryElement->RetriesLeft)); + --(pQueryElement->RetriesLeft); + SendQueryElement(pQueryElement, FALSE /*! FirstAttempt*/); + StartTimer = TRUE; + index++; + } else { + _DBG_WARN (("Timeout has occured on a Query, Retries Exhausted! \n")); + if(pQueryElement->IsSelfCommand != TRUE) + { + // RecvHandler calls ScheduleCompletionProcessing as needed + SubnetAdmRecv(pQueryElement,NULL,0, NULL); + } else { + // defer destroy to premptable context + QListRemoveItem( &pQueryList->m_List, (LIST_ITEM *)pQueryElement ); + pQueryElement->QState = QueryDestroy; + LQListInsertHead(pCompletionList, &pQueryElement->QueryListItem); + ScheduleCompletionProcessing(); + } + // Do not increment the index++ + } + } else if ((pQueryElement->QState == BusyRetryDelay) + && ((CurrMicroTime - pQueryElement->CmdSentTime) > + (g_SdParams.SaBusyBackoff * 1000))) + { + // got a SA Busy response and we have some Retries left + // it was sent and got a busy response, but was not processed + AtomicDecrementVoid(&Outstanding); + ASSERT(pQueryElement->RetriesLeft > 0); + //Retry it + _DBG_WARN (("SA Busy has occured on a Query! \n")); + _DBG_INFO(("Retrying a QueryElement Retries Left = %d\n", + pQueryElement->RetriesLeft)); + --(pQueryElement->RetriesLeft); + SendQueryElement(pQueryElement, FALSE /*! FirstAttempt*/); + StartTimer = TRUE; + index++; + } else { + // Command has not timed out, it is still in the QueryList + // Need to start Timer again + // this applies also to commands in WaitingForChildToComplete + // and ProcessingResponse states + StartTimer = TRUE; + index++; + } + } + + if (StartTimer == TRUE) + StartTimerHandler(pTimerObject, g_SdParams.TimeInterval); + +unlock: + SpinLockRelease(&pQueryList->m_Lock); + + _DBG_LEAVE_EXT(_DBG_LVL_FUNC_TRACE); + return; +} + +// if we are not at MaxOutstanding +// send the next QueryElements from given provider Id which is are the QueryList +// in ReadyToSend state +void +SdSendNextOutstanding(void) +{ + PQueryDetails pQueryElement; + uint32 index = 0; + LIST_ITEM* pListItem; + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, SdSendNextOutstanding); + + SpinLockAcquire(&pQueryList->m_Lock); + if (AtomicRead(&Outstanding) >= g_SdParams.MaxOutstanding) + goto unlock; + while(NULL != (pListItem = QListGetItemAt(&pQueryList->m_List, index))) + { + pQueryElement = (PQueryDetails)pListItem->pObject; + if (pQueryElement->QState == ReadyToSend) + { + SendQueryElement(pQueryElement, FALSE /*! FirstAttempt*/); + if (AtomicRead(&Outstanding) >= g_SdParams.MaxOutstanding) + break; + } + index++; + } +unlock: + SpinLockRelease(&pQueryList->m_Lock); + _DBG_LEAVE_EXT(_DBG_LVL_FUNC_TRACE); + return; +} + +void +ProcessChildQueryQueue( + void + ) +{ + LIST_ITEM* pListItem; + + if (AtomicRead(&ChildQueryActive) > g_SdParams.MaxChildQuery) + return; + + while(NULL != (pListItem = LQListRemoveTail(pChildQueryList))) + { + PQueryDetails pQueryElement = (PQueryDetails)pListItem->pObject; + DEBUG_ASSERT(pQueryElement->pParentQuery); + // this does not dereference pParentQuery + if (! LQListIsItemInList(pQueryList,&pQueryElement->pParentQuery->QueryListItem)) + { + // discard this one, parent has been canceled + FreeQueryElement(pQueryElement); + } else { + SendQueryElement(pQueryElement, TRUE /*FirstAttempt*/); + + if (AtomicIncrement(&ChildQueryActive) > g_SdParams.MaxChildQuery) + break; + } + } +} + +void +ScheduleCompletionProcessing(void) +{ + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, ScheduleCompletionProcessing); + if (AtomicExchange(&SdWorkItemQueued, 1) == 0) { + SysCallbackQueue(pCallbackItemObject, ProcessCompletionQueue, + NULL, FALSE); + } else { + _DBG_INFO(("ProcessCompletionQueue already queued\n")); + } + _DBG_LEAVE_EXT(_DBG_LVL_FUNC_TRACE); +} + +// This is called in a thread context. +// The FreeQueryElement (and possibly client callbacks) can prempt +void +ProcessCompletionQueue( + void* Key, //Functional Device OBJECT + void *Context) + +{ + QUERY_RESULT_VALUES QueryResError; + PQUERY_RESULT_VALUES pQueryRes; + PQueryDetails pQueryElement; + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, ProcessCompletionQueue); + + AtomicIncrementVoid(&SdWorkItemsInProcess); + if (AtomicExchange(&SdWorkItemQueued,0) == 0) { + _DBG_ERROR(("ProcessCompletionQueue was 0\n")); + } + + ProcessChildQueryQueue(); + + QueryResError.ResultDataSize = 0; + + while (NULL != (pQueryElement = (PQueryDetails)LQListRemoveHead(pCompletionList))) + { + DEBUG_ASSERT(pQueryElement->QState == QueryComplete + || pQueryElement->QState == QueryDestroy); + if (pQueryElement->QState == QueryComplete) + { + if (pQueryElement->SdSentCmd == UserFabricOperation) + { + // This is a FabOp response + pQueryElement->cmd.op.FabOpCallback(pQueryElement->UserContext, + &(pQueryElement->cmd.op.FabOp), + pQueryElement->Status, + pQueryElement->MadStatus); + } else { + ASSERT(pQueryElement->SdSentCmd == UserQueryFabricInformation); + if(pQueryElement->cmd.query.pClientResult == NULL) + { + _DBG_INFO(("ClientResult is null\n")); + pQueryRes = &QueryResError; + QueryResError.Status = pQueryElement->Status; + QueryResError.MadStatus = pQueryElement->MadStatus; + } else { + pQueryRes = pQueryElement->cmd.query.pClientResult; + } + + ASSERT(pQueryElement->cmd.query.UserCallback); + (*pQueryElement->cmd.query.UserCallback)(pQueryElement->UserContext, + &(pQueryElement->cmd.query.UserQuery), pQueryRes); + } + } + FreeQueryElement(pQueryElement); + } + AtomicDecrementVoid(&SdWorkItemsInProcess); + + _DBG_LEAVE_EXT(_DBG_LVL_FUNC_TRACE); + return; +} + +// used after a premptable operation on a QueryElement to see if the query +// element is still active to continue processing of it. +// must be called with pQueryList->m_Lock held for a query which was on +// the pQueryList when caller prempted. +// returns TRUE - query has been cancelled, +// if this is last reference, the query element is freed +// (releases and reacquires lock so free can preempt) +// returns FALSE - query is still active, lock is not released +// +boolean +FreeCancelledQueryElement( + PQueryDetails pQueryElement + ) +{ + if (pQueryElement->QState == QueryDestroy) + { + // query was cancelled, it is no longer on the list + // if there are children still holding reference, we can't + // free until last has released its reference (each will + // call this function as they release, last child's call will cause + // us to FreeQueryElement for the given parent) + if (! pQueryElement->ChildProcessingResponseCount) + { + // all referenences are gone, free in a preemptable context + SpinLockRelease(&pQueryList->m_Lock); + FreeQueryElement(pQueryElement); + SpinLockAcquire(&pQueryList->m_Lock); + } + return TRUE; + } else { + return FALSE; + } +} + +// Free the given query element +// should be called without holding any locks +// caller must remove query from any lists prior to call +void +FreeQueryElement( + PQueryDetails pQueryElement + ) +{ + DEBUG_ASSERT(pQueryElement->SdSentCmd != UnknownCommand); + DEBUG_ASSERT(! pQueryElement->ChildProcessingResponseCount); + if (pQueryElement->SdSentCmd == UserQueryFabricInformation + && pQueryElement->cmd.query.pClientResult) + { + MemoryDeallocate(pQueryElement->cmd.query.pClientResult); + } + if (pQueryElement->u.pGmp) + { + MemoryDeallocate(pQueryElement->u.pGmp); + } + MemoryDeallocate(pQueryElement); +} diff --git a/IbAccess/Common/SubnetDriver/sdi.h b/IbAccess/Common/SubnetDriver/sdi.h new file mode 100644 index 0000000..534f78a --- /dev/null +++ b/IbAccess/Common/SubnetDriver/sdi.h @@ -0,0 +1,375 @@ +/* BEGIN_ICS_COPYRIGHT4 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT4 ****************************************/ +/* [ICS VERSION STRING: unknown] */ + +#ifndef _IBA_SD_INTERNAL_ +#define _IBA_SD_INTERNAL_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define SUBNET_DRIVER_TAG ((uint32) 0x44627553) //'DbuS' + +extern ATOMIC_UINT IsTimerStarted; + +#define StartTimerHandler(pTimerObject, TimeInMS) {\ + if (AtomicExchange(&IsTimerStarted, 1) == 0) {\ + TimerStart(pTimerObject, /* ms*/ TimeInMS);\ + }\ + } + +#define SD_MAX_SA_NDGRM 64 // SA query/requests - default MaxSaOutstanding +#define SD_MAX_RESP_NDGRM 64 // Notify Responses + +typedef uint32 ClientId; + +extern ATOMIC_UINT Outstanding; // number of queries/operations in progress + +extern SPIN_LOCK *pCaPortListLock; +extern QUICK_LIST *pCaPortList; + +extern IB_HANDLE CaNotifyHandle; +extern uint32 NumLocalCAs; +extern EUI64 *pLocalCaGuidList; +extern SPIN_LOCK *pLocalCaInfoLock; +extern IB_CA_ATTRIBUTES *pLocalCaInfo; + +// This list contains all the registered SD clients +extern SPIN_LOCK *pClientListLock; +extern QUICK_LIST *pClientList; + +// This list contains all the active queries +// The lock for this list protects the list itself and the +// QueryElements on the list. It also protects changes to QState for +// all the elements on the list. +extern LOCKED_QUICK_LIST *pQueryList; + +// This list contains all the completed queries or queries scheduled for +// a defered destroy (so destroy could occur in a preemptable context) +extern LOCKED_QUICK_LIST *pCompletionList; + +// This list contains all the scheduled but inactive child queries +// when a child query becomes active, it is placed on the pQueryList +extern LOCKED_QUICK_LIST *pChildQueryList; +extern ATOMIC_UINT ChildQueryActive; + +// This mutex prevents races between multiple child processes updating +// their parents pClientResult at the same time. In reality, since there +// is one thread for SD GSA callbacks, there will be no contention for +// this mutex, hence there is no advantage to putting it into the +// parent query element. Also note that for parent queries, the +// pClientResult of the parent is not modified until all children are done +extern MUTEX *pChildGrowParentMutex; + +extern TIMER *pTimerObject; + +extern ATOMIC_UINT SdWorkItemQueued; +extern ATOMIC_UINT SdWorkItemsInProcess; +extern boolean SdUnloading; + +//GSI related handles +extern IB_HANDLE GsiSAHandle; + +extern IB_HANDLE sa_poolhandle; +extern IB_HANDLE sa_represp_poolhandle; + +typedef struct _SD_SERVICECONTEXT { + uint8 MgmtClass; //To distingusish when we receive a packet +}SD_SERVICECONTEXT, *PSD_SERVICECONTEXT; + + +typedef struct _ClientListEntry { + LIST_ITEM ListItem; //Linked list pointers, Do not move this element + uint32 ClientId; + CLIENT_CONTROL_PARAMETERS ClientParameters; + QUICK_LIST ClientTraps; +} ClientListEntry, *PClientListEntry; + +typedef struct _QueryListEntry { + PClientListEntry pClient; +} QueryListEntry, *PQueryListEntry; + + +FSTATUS +SdCommonCreate( + void + ); + +FSTATUS +SdCommonClose( + void + ); + +void +SetDefaultSDDriverTunables( + void + ); + +FSTATUS +ReadDriverTunables( + void + ); + + +FSTATUS +InitializeDriver( + void + ); + +FSTATUS +UnloadDriver( + void + ); + +FSTATUS +InitializeList( + IN QUICK_LIST **ppList, + IN SPIN_LOCK **ppListLock +); + + +void +DestroyList( + IN QUICK_LIST *pList, + IN SPIN_LOCK *pListLock + ); + +FSTATUS +CommonQueryPortFabricInformation( + IN CLIENT_HANDLE ClientHandle, + IN EUI64 PortGuid, + IN PQUERY Query, + IN SDK_QUERY_CALLBACK *Callback, + IN COMMAND_CONTROL_PARAMETERS *pQueryControlParameters OPTIONAL, + IN void *Context OPTIONAL + ); + +FSTATUS +CommonPortFabricOperation( + IN CLIENT_HANDLE ClientHandle, + IN EUI64 PortGuid, + IN FABRIC_OPERATION_DATA* pFabOp, + IN SDK_FABRIC_OPERATION_CALLBACK *Callback, + IN COMMAND_CONTROL_PARAMETERS *pCmdControlParameters OPTIONAL, + IN void* Context OPTIONAL + ); + +FSTATUS +CommonSdDeregister( + IN CLIENT_HANDLE ClientHandle + ); + +FSTATUS +ValidateAndFillSDQuery( + PQueryDetails pQueryElement, + uint32 MemAllocFlags + ); + +FSTATUS +ValidateAndFillSDFabOp( + PQueryDetails pQueryElement, + uint32 MemAllocFlags + ); + +FSTATUS ValidateClientHandle( + IN CLIENT_HANDLE ClientHandle, + OUT CLIENT_CONTROL_PARAMETERS *pClientParams + ); + +FSTATUS CheckPortActive( + IN OUT EUI64 *pPortGuid + ); + +FSTATUS +SdHandleChildQuery( + PQueryDetails pQueryElement, + void *buffer, + uint32 bufsize + ); + + +FSTATUS +InitializeIbt( void); + +SYS_CALLBACK_ITEM * +InitializeWorkItemqueue( void); + +void +TimerHandler( IN void *Context); + +void +SdSendNextOutstanding(void); + +void +ProcessChildQueryQueue( void); + +//void +//ProcessDelayedWorkQueue( + //void* Key, //Functional Device OBJECT + //void *Context); + +void +ScheduleCompletionProcessing(void); + +void +ProcessCompletionQueue( + void* Key, //Functional Device OBJECT + void *Context + ); + +boolean +FreeCancelledQueryElement( + PQueryDetails pQueryElement + ); + +void +FreeQueryElement( + PQueryDetails pQueryElement + ); + +FSTATUS +RegisterWithGSI( + void + ); + +void +DeRegisterWithGSI( + void + ); + +FSTATUS +SdGsaRecvCallback( + IN void *ServiceContext, + IN IBT_DGRM_ELEMENT *pDgrmList + ); + +void +SdGsaSendCompleteCallback( + IN void *ServiceContext, + IN IBT_DGRM_ELEMENT *pDgrmList + + ); + +CA_PORT* +GetCaPort( + EUI64 PortGuid + ); + +void +AddCa( + IN EUI64 CaGuid + ); + +void +RemoveCa( + IN EUI64 CaGuid + ); + +FSTATUS +InitializeCaPortInfo( + IN EUI64 PortGuid + ); + +uint32 +GetNumTotalPorts( + IN void + ); + +FSTATUS +GetLocalCaInfo( + void + ); + +void +LocalCaChangeCallback( + IN IB_NOTIFY_RECORD + ); + +QueryDetails** +BuildSAChildQueriesForPathRecord( + PQueryDetails pRootQueryElement, + uint64 *pDestPortGuidsList, + uint32 DestPortGuidsCount +); + +FSTATUS +SubnetAdmInit( + void + ); + +FSTATUS +SubnetAdmRecv( + PQueryDetails pQueryElement, + void *buffer, + uint32 messageSize + ,IBT_DGRM_ELEMENT *pDgrmList + ); + +FSTATUS +SendQueryElement( + PQueryDetails pQueryElement, + boolean FirstAttempt + ); + + +void +FillBaseGmpValues( + IN PQueryDetails piQuery + ); + +void +SetDefaultClientParameters( + void + ); + +void +CancelClientQueries( + IN CLIENT_HANDLE ClientHandle + ); + +#ifdef __cplusplus +}; +#endif + +#endif // _IBA_SD_INTERNAL_ diff --git a/IbAccess/Common/SubnetDriver/sdrequest.c b/IbAccess/Common/SubnetDriver/sdrequest.c new file mode 100644 index 0000000..5d7b3a1 --- /dev/null +++ b/IbAccess/Common/SubnetDriver/sdrequest.c @@ -0,0 +1,92 @@ +/* BEGIN_ICS_COPYRIGHT4 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT4 ****************************************/ +/*! + + \file sdrequest.h + + $Revision$ + $Date$ + + \brief Routines for handling requests forwarded by the subnet manager +*/ + +#include +#include +#include +#include +#include + +/*! + \brief Attempts to process a Request received by the GSA +*/ +FSTATUS +ProcessRequest( void *ServiceContext, IBT_DGRM_ELEMENT *pDgrmList ) +{ + FSTATUS Status = FSUCCESS; + SA_MAD *pMad = (SA_MAD *)GsiDgrmGetRecvMad(pDgrmList); + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, ProcessRequest); + + switch ( pMad->common.MgmtClass ) + { + case MCLASS_SUBN_ADM: + switch ( pMad->common.mr.AsReg8 ) + { + case MMTHD_REPORT: + Status = ProcessReport( ServiceContext, pDgrmList ); + break; + + default: + case MMTHD_GET: + case MMTHD_SET: + case MMTHD_SEND: + case MMTHD_TRAP: + case MMTHD_TRAP_REPRESS: + case MMTHD_GET_RESP: + case MMTHD_REPORT_RESP: + break; + } + break; + + default: + case MCLASS_SM_LID_ROUTED: + case MCLASS_SM_DIRECTED_ROUTE: + case MCLASS_PERF: + case MCLASS_BM: + case MCLASS_DEV_MGT: + case MCLASS_COMM_MGT: + case MCLASS_SNMP: + case MCLASS_DEV_CONF_MGT: + case MCLASS_DTA: + break; + } + + _DBG_LEAVE_LVL( _DBG_LVL_FUNC_TRACE ); + return Status; +} diff --git a/IbAccess/Common/SubnetDriver/sdrequest.h b/IbAccess/Common/SubnetDriver/sdrequest.h new file mode 100644 index 0000000..a1a765e --- /dev/null +++ b/IbAccess/Common/SubnetDriver/sdrequest.h @@ -0,0 +1,58 @@ +/* BEGIN_ICS_COPYRIGHT4 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT4 ****************************************/ +/*! + + \file sdrequest.h + + $Revision$ + $Date$ + + \brief Routines for handling requests forwarded by the subnet manager +*/ + +#ifndef _SD_REQUEST_H_ +#define _SD_REQUEST_H_ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/*! + \brief Attempts to process a Request received by the GSA +*/ +FSTATUS ProcessRequest(void *ServiceContext, IBT_DGRM_ELEMENT *pDgrmList); + +#ifdef __cplusplus +}; +#endif + +#endif // _SD_REQUEST_H_ diff --git a/IbAccess/Common/SubnetDriver/sdsend.c b/IbAccess/Common/SubnetDriver/sdsend.c new file mode 100644 index 0000000..4225c21 --- /dev/null +++ b/IbAccess/Common/SubnetDriver/sdsend.c @@ -0,0 +1,210 @@ +/* BEGIN_ICS_COPYRIGHT4 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT4 ****************************************/ + + +#include +#include +#include +#include +#include +#include +#include + +// only add to list if FirstAttempt +// only get lock while adding to list if NeedLock +static void +QueueQuery( + PQueryDetails pQueryElement, + boolean FirstAttempt, + boolean NeedLock + ) +{ + if (FirstAttempt) + { + pQueryElement->RetriesLeft = pQueryElement->ControlParameters.RetryCount; + if (NeedLock) + { + LQListInsertTail(pQueryList, &pQueryElement->QueryListItem); + } else { + QListInsertTail(&pQueryList->m_List, &pQueryElement->QueryListItem); + } + } +} + + +// when called with FirstAttempt == FALSE, pQueryList->m_lock is held +// when called with FirstAttempt == TRUE, pQueryList->m_lock is not held +FSTATUS +SendQueryElement( + PQueryDetails pQueryElement, + boolean FirstAttempt + ) +{ + uint32 ElementCount; + IBT_DGRM_ELEMENT *pIbtDgrmElement; + FSTATUS Status; + CA_PORT *pCaPort; + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, SendQueryElement); + + ASSERT(pQueryElement); + + if (AtomicIncrement(&Outstanding) > g_SdParams.MaxOutstanding) + { + AtomicDecrementVoid(&Outstanding); + _DBG_INFO(("Max outstanding of %u reached, queuing query element %p\n", + g_SdParams.MaxOutstanding, _DBG_PTR(pQueryElement))); + // we will try again later + pQueryElement->QState = ReadyToSend; + QueueQuery(pQueryElement, FirstAttempt, FirstAttempt); + goto done; + } + + ElementCount = 1; + + Status = iba_gsi_dgrm_pool_get(sa_poolhandle, &ElementCount, &pIbtDgrmElement); +#ifdef SA_ALLOC_DEBUG + if (iba_gsi_dgrm_pool_count(sa_poolhandle) < 50) + { + MsgOut("Dgrm Alloc Status %d\n", Status); + MsgOut("SA Dgrm Pool=%u\n", iba_gsi_dgrm_pool_count(sa_poolhandle)); + } +#endif + if (Status != FSUCCESS) + { + _DBG_WARN(("Failed to allocate SA DGRM, Status = <%d>, exitting\n", Status)); + // we will try again later + AtomicDecrementVoid(&Outstanding); + pQueryElement->QState = ReadyToSend; + QueueQuery(pQueryElement, FirstAttempt, FirstAttempt); + goto done; + } + + pQueryElement->CmdSentTime = GetTimeStamp(); + pIbtDgrmElement->Element.pContext = (void *)&pQueryElement->QueryListItem; + + SpinLockAcquire(pCaPortListLock); + pCaPort = GetCaPort(pQueryElement->PortGuid); + if (pCaPort == NULL) + { + SpinLockRelease(pCaPortListLock); + _DBG_ERROR(("GetCaPort returned NULL for Port (GUID: %"PRIx64").\n", pQueryElement->PortGuid)); + // TBD we should return an error, however callers are not + // prepared, so we queue for retries and timeout + pQueryElement->QState = NotAbleToSend; + QueueQuery(pQueryElement, FirstAttempt, FirstAttempt); + goto cantsend; + } + + // TBD - enable this code when ClassPortInfo works in SM +#if 0 + // this is necessary to handle a redirected SA + if((pQueryElement->IsSelfCommand) && + (pQueryElement->SdSentCmd == GetClassportInfo) ) + { + pIbtDgrmElement->RemoteLID = pCaPort->Lid; + pIbtDgrmElement->ServiceLevel= pCaPort->ServiceLevel; + pIbtDgrmElement->StaticRate = pCaPort->StaticRate; + pIbtDgrmElement->RemoteQP = pCaPort->RemoteQp; + pIbtDgrmElement->RemoteQKey = pCaPort->RemoteQKey; + pIbtDgrmElement->PkeyIndex = pCaPort->PkeyIndex; + } else { + pIbtDgrmElement->RemoteLID = pCaPort->RedirectedLid; + pIbtDgrmElement->ServiceLevel= pCaPort->RedirectedSL; + pIbtDgrmElement->StaticRate = pCaPort->RedirectedStaticRate; + pIbtDgrmElement->RemoteQP = pCaPort->RedirectedQP; + pIbtDgrmElement->RemoteQKey= pCaPort->RedirectedQKey; + pIbtDgrmElement->PkeyIndex = pCaPort->RedirectedPkeyIndex; + } +#else + pIbtDgrmElement->RemoteLID = pCaPort->Lid; + pIbtDgrmElement->ServiceLevel = pCaPort->ServiceLevel; + pIbtDgrmElement->StaticRate = pCaPort->StaticRate; + pIbtDgrmElement->RemoteQP = pCaPort->RemoteQp; + pIbtDgrmElement->RemoteQKey = pCaPort->RemoteQKey; +// pIbtDgrmElement->PkeyIndex = pCaPort->PkeyIndex; + pIbtDgrmElement->PkeyIndex = pCaPort->DefaultPkeyIndex; +#endif + pIbtDgrmElement->PathBits = 0; + pIbtDgrmElement->PortGuid = pQueryElement->PortGuid; + + MemoryCopy( GsiDgrmGetSendMad(pIbtDgrmElement), + pQueryElement->u.pGmp, pQueryElement->TotalBytesInGmp ); + + pIbtDgrmElement->Element.pBufferList->ByteCount = pQueryElement->TotalBytesInGmp; + + if(pCaPort->SdSMAddressValid == TRUE) //Send only if the we have atleast one port active + { + SpinLockRelease(pCaPortListLock); + pQueryElement->QState = WaitingForResult; + // probably not needed, but to be safe, + // hold lock during post_send in case it fails + // once we add to list, others (such as iba_sd_deregister) could + // remove from list or change its state + if (FirstAttempt) + SpinLockAcquire(&pQueryList->m_Lock); + QueueQuery(pQueryElement, FirstAttempt, FALSE); + Status =iba_gsi_post_send( GsiSAHandle, pIbtDgrmElement); +#ifdef SA_ALLOC_DEBUG + if (iba_gsi_dgrm_pool_count(sa_poolhandle) < 50) MsgOut("Dgrm send Status %d\n", Status); +#endif + if (Status != FSUCCESS) + { + pQueryElement->QState = NotAbleToSend; + _DBG_ERROR(("iba_gsi_post_send failed, Status = %d\n", Status)); + if (FirstAttempt) + SpinLockRelease(&pQueryList->m_Lock); + goto cantsend; + } + if (FirstAttempt) + SpinLockRelease(&pQueryList->m_Lock); + } else { + SpinLockRelease(pCaPortListLock); + pQueryElement->QState = NotAbleToSend; + QueueQuery(pQueryElement, FirstAttempt, FirstAttempt); + _DBG_INFO(("Unable to Send, Sd SM Address not valid: Port 0x%016"PRIx64"\n", pQueryElement->PortGuid)); + goto cantsend; + } + + _DBG_INFO(("Sent Query Element %p: %u Outstanding\n", + _DBG_PTR(pQueryElement), + AtomicRead(&Outstanding))); +done: + _DBG_LEAVE_LVL( _DBG_LVL_FUNC_TRACE ); + return FSUCCESS; + +cantsend: +#ifdef SA_ALLOC_DEBUG + if (iba_gsi_dgrm_pool_count(sa_poolhandle) < 50) MsgOut("Dgrm cant send\n"); +#endif + // unable to send for now, cleanup, timer will retry later + AtomicDecrementVoid(&Outstanding); + iba_gsi_dgrm_pool_put( pIbtDgrmElement); + goto done; +} diff --git a/IbAccess/Common/SubnetDriver/subscribe.c b/IbAccess/Common/SubnetDriver/subscribe.c new file mode 100644 index 0000000..9f9bc86 --- /dev/null +++ b/IbAccess/Common/SubnetDriver/subscribe.c @@ -0,0 +1,808 @@ +/* BEGIN_ICS_COPYRIGHT4 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT4 ****************************************/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// This maintains subscriptions with the SA for traps/notices +// As part of this it handles SM restarts, port down/up and local resource +// exhaustion and retries the subscription as needed to maintain it +// To properly maintain subscriptions, it keeps no more than 1 +// subscribe/unsubsribe operation outstanding at the SM at a time. +// This way we can be assured of the order they are processed (if there +// were more than 1 queued to SD, SD retries could result in them being +// processed by the SM in an unpredicatable order). +// +// A TRAP_REFERENCE is retained for each trap on a given port which has a +// request outstanding or has local clients registered. Only once there is no +// one registered and no outstanding ops is it destroyed. +// This ensures there is no more than one op outstanding for a trap and hence +// ensures the order they are processed by the SM. +// +// Unsubscribes are not heavily retried, as the consequence is minimal. +// However the code is persistent about Subscribes so it can ensure it will +// get the desired traps/notices + +typedef enum _TRAP_REFERENCE_FLAGS +{ + TRAP_REF_FLAGS_NONE = 0x0000, + TRAP_REF_FLAGS_SUBSCRIBED = 0x0001, // are we subscribed for this trap + TRAP_REF_FLAGS_OPQUEUED = 0x0002 // is a FabricOperation started +} TRAP_REFERENCE_FLAGS; + +typedef struct _CLIENT_TRAP_INFO +{ + LIST_ITEM ListItem; + uint16 TrapNumber; + EUI64 PortGuid; + void *pContext; // client context for callback + SD_REPORT_NOTICE_CALLBACK *pReportNoticeCallback; // client callback +} CLIENT_TRAP_INFO; + +typedef struct _TRAP_REFERENCE +{ + LIST_ITEM ListItem; + TIMER Timer; + uint16 TrapNumber; + EUI64 PortGuid; + uint32 RefCount; + TRAP_REFERENCE_FLAGS Flags; +} TRAP_REFERENCE; + +static CLIENT_HANDLE SdClientHandle; +static QUICK_LIST SubscribedTrapsList; +static SPIN_LOCK SubscribedTrapsListLock; + +// Delays used when queuing a timer to issue subscribe/unsubscribe later +#define RETRY_DELAY 1000 // 1 second in ms, retry a failure +#define PORT_DOWN_DELAY 60000 // 1 minute in ms, retry a send/down failure +#define DEFER_DELAY 1000 // 1 second in ms, defer to releave SA + +static int SubscribeInitialized = 0; + +static void +ProcessTrapSubscribeResponse(void* Context, FABRIC_OPERATION_DATA* pFabOp, FSTATUS Status, uint32 MadStatus); + +// reaper callback +static void +ReapTrapReference(LIST_ITEM *pItem) +{ + // Reaper uses QListObj, so we must use PARENT_STRUCT + TRAP_REFERENCE *pTrapReference = PARENT_STRUCT(pItem, TRAP_REFERENCE, ListItem); + TimerDestroy(&pTrapReference->Timer); + MemoryDeallocate(pTrapReference); +} + +// Queue a Trap timer callback to issue a subscribe or unsubscribe +// must be called with SubscribedTrapsListLock held +static void +QueueTrapTimer(TRAP_REFERENCE *pTrapReference, uint32 timeout_ms) +{ + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, QueueTrapTimer); + + if (SubscribeInitialized != 0) + { + // restart timer if running + TimerStop(&pTrapReference->Timer); + TimerStart(&pTrapReference->Timer, timeout_ms); + } + + _DBG_LEAVE_LVL( _DBG_LVL_FUNC_TRACE ); +} + +// must be called with SubscribedTrapsListLock held +static void +IssueTrapSubscribe(TRAP_REFERENCE *pTrapReference) +{ + FSTATUS Status; + FABRIC_OPERATION_DATA *pFabOp; + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, IssueTrapSubscribe); + + ASSERT (pTrapReference != NULL); + + pFabOp = (FABRIC_OPERATION_DATA*)MemoryAllocate2AndClear( sizeof(FABRIC_OPERATION_DATA), IBA_MEM_FLAG_SHORT_DURATION, SUBNET_DRIVER_TAG ); + if ( pFabOp == NULL ) + { + _DBG_ERROR(("SubscribeForTrap MemoryAllocateError\n")); + QueueTrapTimer(pTrapReference, RETRY_DELAY); // try again later + } else { + pFabOp->Type = FabOpSetInformInfo; + memset(&pFabOp->Value.InformInfo.GID, 0, sizeof(pFabOp->Value.InformInfo.GID)); + pFabOp->Value.InformInfo.LIDRangeBegin = LID_PERMISSIVE; + pFabOp->Value.InformInfo.LIDRangeEnd = 0; + pFabOp->Value.InformInfo.Reserved = 0; + pFabOp->Value.InformInfo.IsGeneric = 1; + pFabOp->Value.InformInfo.Subscribe = 1; + pFabOp->Value.InformInfo.Type = IB_NOTICE_ALL; + + pFabOp->Value.InformInfo.u.Generic.TrapNumber = pTrapReference->TrapNumber; + pFabOp->Value.InformInfo.u.Generic.u2.s.QPNumber = GSI_QP; + pFabOp->Value.InformInfo.u.Generic.u2.s.RespTimeValue = 18; + pFabOp->Value.InformInfo.u.Generic.u.s.ProducerType = STL_NODE_FI; + + Status = iba_sd_port_fabric_operation( SdClientHandle, pTrapReference->PortGuid, pFabOp, ProcessTrapSubscribeResponse, NULL, pTrapReference ); + if ((Status != FPENDING) && (Status != FSUCCESS)) + { + /* Port may not yet be active. + * ReRegisterTrapSubscriptions will be called when it goes active + * but we queue a slow timer just in case operation failed for + * another reason (such as low memory, etc) + */ + /* _DBG_ERROR(("PortFabricOperation Status = %d\n", Status)); */ + QueueTrapTimer(pTrapReference, (SystemGetRandom() % PORT_DOWN_DELAY));// try again later + } else { + pTrapReference->Flags = (TRAP_REFERENCE_FLAGS)(pTrapReference->Flags | TRAP_REF_FLAGS_OPQUEUED); + } + + MemoryDeallocate( pFabOp ); + } + + _DBG_LEAVE_LVL( _DBG_LVL_FUNC_TRACE ); +} + +// must be called with SubscribedTrapsListLock held +static +void IssueTrapUnSubscribe(TRAP_REFERENCE *pTrapReference) +{ + FSTATUS Status; + FABRIC_OPERATION_DATA *pFabOp; + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, IssueTrapUnSubscribe); + + pFabOp = (FABRIC_OPERATION_DATA*)MemoryAllocate2AndClear( sizeof(FABRIC_OPERATION_DATA), IBA_MEM_FLAG_SHORT_DURATION, SUBNET_DRIVER_TAG ); + if ( pFabOp == NULL ) + { + _DBG_ERROR(("SubscribeForTrap MemoryAllocateError\n")); + QueueTrapTimer(pTrapReference, RETRY_DELAY); // try again later + } else { + pFabOp->Type = FabOpSetInformInfo; + memset(&pFabOp->Value.InformInfo.GID, 0, sizeof(pFabOp->Value.InformInfo.GID)); + pFabOp->Value.InformInfo.LIDRangeBegin = LID_PERMISSIVE; + pFabOp->Value.InformInfo.LIDRangeEnd = 0; + pFabOp->Value.InformInfo.Reserved = 0; + pFabOp->Value.InformInfo.IsGeneric = 1; + pFabOp->Value.InformInfo.Subscribe = 0; + pFabOp->Value.InformInfo.Type = IB_NOTICE_ALL; + + pFabOp->Value.InformInfo.u.Generic.TrapNumber = pTrapReference->TrapNumber; + pFabOp->Value.InformInfo.u.Generic.u2.s.QPNumber = GSI_QP; + pFabOp->Value.InformInfo.u.Generic.u2.s.RespTimeValue = 18; + pFabOp->Value.InformInfo.u.Generic.u.s.ProducerType = STL_NODE_FI; + + Status = iba_sd_port_fabric_operation( SdClientHandle, pTrapReference->PortGuid, pFabOp, ProcessTrapSubscribeResponse, NULL, pTrapReference ); + if ((Status != FPENDING) && (Status != FSUCCESS)) + { + /* Port may not yet be active. + * ReRegisterTrapSubscriptions will be called when it goes active + * but we queue a slow timer just in case operation failed for + * another reason (such as low memory, etc) + */ + /* _DBG_ERROR(("PortFabricOperation Status = %d\n", Status)); */ + QueueTrapTimer(pTrapReference, PORT_DOWN_DELAY);// try again later + } else { + // to be conservative, assume we are unsubscribed, just in case + // SA processes request, but delivers response late + // also avoids us retrying unsubscribe in event SM is down + pTrapReference->Flags = (TRAP_REFERENCE_FLAGS)(pTrapReference->Flags & ~TRAP_REF_FLAGS_SUBSCRIBED); + pTrapReference->Flags = (TRAP_REFERENCE_FLAGS)(pTrapReference->Flags | TRAP_REF_FLAGS_OPQUEUED); + } + + MemoryDeallocate( pFabOp ); + } + + _DBG_LEAVE_LVL( _DBG_LVL_FUNC_TRACE ); +} + +// check trap state and issue subscriptions or destroy object as needed +// must be called with SubscribedTrapsListLock held +static void +ProcessTrapStateChange(TRAP_REFERENCE *pTrapReference, uint32 delay_ms) +{ + // we only queue 1 op at a time, this way be can ensure they are + // not processed out of order + if (! (pTrapReference->Flags & TRAP_REF_FLAGS_OPQUEUED)) + { + if (pTrapReference->RefCount && ! (pTrapReference->Flags & TRAP_REF_FLAGS_SUBSCRIBED)) + { + // we need to subscribe + if (delay_ms) + QueueTrapTimer(pTrapReference, delay_ms); + else + IssueTrapSubscribe(pTrapReference); + } else if (! pTrapReference->RefCount && (pTrapReference->Flags & TRAP_REF_FLAGS_SUBSCRIBED)) { + // we need to unsubscribe + if (delay_ms) + QueueTrapTimer(pTrapReference, delay_ms); + else + IssueTrapUnSubscribe(pTrapReference); + } else if (pTrapReference->RefCount == 0) { + // unsubscribed and no one needs to subscribe, cleanup + QListRemoveItem(&SubscribedTrapsList, &pTrapReference->ListItem); + TimerStop(&pTrapReference->Timer); // make sure no future callbacks + ReaperQueue(&pTrapReference->ListItem, ReapTrapReference); + } else { + // we are subscribed as we want to be + ASSERT(pTrapReference->RefCount && (pTrapReference->Flags & TRAP_REF_FLAGS_SUBSCRIBED)); + } + } else { + // let sd callback call us when op finishes or fails + } +} + +static void +TrapTimerCallback(void *Context) +{ + TRAP_REFERENCE *pTrapReference = (TRAP_REFERENCE *)Context; + + SpinLockAcquire(&SubscribedTrapsListLock); + if (TimerCallbackStopped(&pTrapReference->Timer)) + { + SpinLockRelease(&SubscribedTrapsListLock); + return; + } + ProcessTrapStateChange(pTrapReference, 0); + SpinLockRelease(&SubscribedTrapsListLock); +} + +// callback when SA query completes or fails +static void +ProcessTrapSubscribeResponse(void* Context, FABRIC_OPERATION_DATA* pFabOp, FSTATUS Status, uint32 MadStatus) +{ + TRAP_REFERENCE *pTrapReference = (TRAP_REFERENCE *)Context; + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, ProcessTrapSubscribeResponse); + + SpinLockAcquire(&SubscribedTrapsListLock); + if (SubscribeInitialized == 0) + goto unlock; // we are shutting down, don't start anything new + + pTrapReference->Flags = (TRAP_REFERENCE_FLAGS)(pTrapReference->Flags & ~TRAP_REF_FLAGS_OPQUEUED); + if (Status != FSUCCESS) + { + // our attempt failed + if (pFabOp->Value.InformInfo.Subscribe == 0) + { + _DBG_WARN( ("Trap Unsubscribe Failure. Status = %s, MadStatus = 0x%x: %s.\n", + _DBG_PTR(iba_fstatus_msg(Status)), MadStatus, _DBG_PTR(iba_sd_mad_status_msg(MadStatus))) ); + } else { + _DBG_WARN( ("Trap Subscribe Failure. Status = %s, MadStatus = 0x%x: %s.\n", + _DBG_PTR(iba_fstatus_msg(Status)), MadStatus, _DBG_PTR(iba_sd_mad_status_msg(MadStatus))) ); + } + // delay any retry or adjustment so we don't beat on SA too hard + if (MadStatus == MAD_STATUS_BUSY) + { + ProcessTrapStateChange(pTrapReference, (SystemGetRandom() % PORT_DOWN_DELAY)); + _DBG_PRINT(_DBG_LVL_INFO, ("SM Returned Busy. Delaying Subscription By %ld MS.\n", (SystemGetRandom() % PORT_DOWN_DELAY))); + } else { + ProcessTrapStateChange(pTrapReference, RETRY_DELAY); + } + } else { + if (pFabOp->Value.InformInfo.Subscribe == 1) + { + /* We are now subscribed with the SA */ + pTrapReference->Flags = (TRAP_REFERENCE_FLAGS)(pTrapReference->Flags | TRAP_REF_FLAGS_SUBSCRIBED); + } else { + /* We are now completely unsubscribed from the SA */ + // flag was cleared when we issued unsubscribe request + } + ProcessTrapStateChange(pTrapReference, 0); + } +unlock: + SpinLockRelease(&SubscribedTrapsListLock); + + _DBG_LEAVE_LVL( _DBG_LVL_FUNC_TRACE ); +} + +void +SubscribeInitialize() +{ + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, SubscribeInitialize); + + iba_sd_register( &SdClientHandle, NULL ); /* TODO: Error Handling*/ + QListInit(&SubscribedTrapsList); + SpinLockInitState(&SubscribedTrapsListLock); + SpinLockInit(&SubscribedTrapsListLock); + + SubscribeInitialized = 1; + + _DBG_LEAVE_LVL( _DBG_LVL_FUNC_TRACE ); +} + +void +SubscribeTerminate() +{ + LIST_ITEM *pTrapReferenceListItem; + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, SubscribeTerminate); + + SpinLockAcquire(&SubscribedTrapsListLock); + SubscribeInitialized = 0; + SpinLockRelease(&SubscribedTrapsListLock); + + iba_sd_deregister(SdClientHandle); + + /* no more SD callbacks will occur now, so OPQUEUED is not important */ + SpinLockAcquire(&SubscribedTrapsListLock); + while ( NULL != (pTrapReferenceListItem = QListRemoveHead(&SubscribedTrapsList))) + { + TRAP_REFERENCE *pTrapReference = (TRAP_REFERENCE *)QListObj(pTrapReferenceListItem); + + ASSERT(pTrapReference != NULL); + TimerStop(&pTrapReference->Timer); + // release lock so TimerDestroy can wait for callback + SpinLockRelease(&SubscribedTrapsListLock); + TimerDestroy(&pTrapReference->Timer); + + MemoryDeallocate(pTrapReference); + + SpinLockAcquire(&SubscribedTrapsListLock); + } + SpinLockRelease(&SubscribedTrapsListLock); + + QListDestroy(&SubscribedTrapsList); + SpinLockDestroy(&SubscribedTrapsListLock); + + _DBG_LEAVE_LVL( _DBG_LVL_FUNC_TRACE ); +} + +static __inline +FSTATUS +IncrementTrapUsageCount(uint16 TrapNumber, EUI64 PortGuid) +{ + static int Seeded = 0; + + FSTATUS Status = FSUCCESS; + LIST_ITEM *pTrapReferenceListItem; + TRAP_REFERENCE *pTrapReference; + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, IncrementTrapUsageCount); + + SpinLockAcquire(&SubscribedTrapsListLock); + if (SubscribeInitialized == 0) + { + SpinLockRelease(&SubscribedTrapsListLock); + Status = FINVALID_STATE; + goto exit; + } + + pTrapReferenceListItem = QListHead(&SubscribedTrapsList); + + while (pTrapReferenceListItem != NULL) + { + pTrapReference = (TRAP_REFERENCE *)QListObj(pTrapReferenceListItem); + + ASSERT(pTrapReference != NULL); + + if ((pTrapReference->TrapNumber == TrapNumber) && + (pTrapReference->PortGuid == PortGuid)) + { + pTrapReference->RefCount++; + goto process; + } + + pTrapReferenceListItem = QListNext(&SubscribedTrapsList, pTrapReferenceListItem); + } + + SpinLockRelease(&SubscribedTrapsListLock); + + pTrapReference = (TRAP_REFERENCE*)MemoryAllocate2AndClear(sizeof(TRAP_REFERENCE), IBA_MEM_FLAG_NONE, SUBNET_DRIVER_TAG); + if (pTrapReference == NULL) + { + _DBG_ERROR(("IncrementTrapUsageCount MemoryAllocateError\n")); + Status = FINSUFFICIENT_MEMORY; + goto exit; + } + + TimerInitState(&pTrapReference->Timer); + TimerInit(&pTrapReference->Timer, TrapTimerCallback, pTrapReference); + pTrapReference->TrapNumber = TrapNumber; + pTrapReference->PortGuid = PortGuid; + pTrapReference->RefCount = 1; + pTrapReference->Flags = TRAP_REF_FLAGS_NONE; + + QListSetObj(&pTrapReference->ListItem, pTrapReference); + + SpinLockAcquire(&SubscribedTrapsListLock); + QListInsertTail(&SubscribedTrapsList, &pTrapReference->ListItem); + + if (!Seeded) + { + SystemSeedRandom((unsigned long)pTrapReference->PortGuid); + Seeded = 1; + } + +process: + // Subscribe as needed, defer since its likely we are just starting + // the drivers and SA may not yet be ready for operations + ProcessTrapStateChange(pTrapReference, DEFER_DELAY); + SpinLockRelease(&SubscribedTrapsListLock); + +exit: + _DBG_LEAVE_LVL( _DBG_LVL_FUNC_TRACE ); + return Status; +} + +static __inline +void +DecrementTrapUsageCount(uint16 TrapNumber, EUI64 PortGuid) +{ + LIST_ITEM *pTrapReferenceListItem; + TRAP_REFERENCE *pTrapReference; + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, DecrementTrapUsageCount); + + SpinLockAcquire(&SubscribedTrapsListLock); + + pTrapReferenceListItem = QListHead(&SubscribedTrapsList); + + while (pTrapReferenceListItem != NULL) + { + pTrapReference = (TRAP_REFERENCE *)QListObj(pTrapReferenceListItem); + + ASSERT(pTrapReference != NULL); + + if ((pTrapReference->TrapNumber == TrapNumber) && + (pTrapReference->PortGuid == PortGuid)) + { + pTrapReference->RefCount--; + // unsubscribe as needed + ProcessTrapStateChange(pTrapReference, 0); + break; + } + + pTrapReferenceListItem = QListNext(&SubscribedTrapsList, pTrapReferenceListItem); + } + + SpinLockRelease(&SubscribedTrapsListLock); + + _DBG_LEAVE_LVL( _DBG_LVL_FUNC_TRACE ); +} + +// client is deregistering from SD, remove all their trap registrations +void +UnsubscribeClient(ClientListEntry *pClientEntry) +{ + LIST_ITEM *pClientTrapItem = QListRemoveHead(&pClientEntry->ClientTraps); + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, UnsubscribeClient); + + while (pClientTrapItem != NULL) + { + CLIENT_TRAP_INFO *pClientTrapInfo = (CLIENT_TRAP_INFO *)QListObj(pClientTrapItem); + + ASSERT(pClientTrapInfo != NULL); + + DecrementTrapUsageCount(pClientTrapInfo->TrapNumber, pClientTrapInfo->PortGuid); + + MemoryDeallocate(pClientTrapInfo); + + pClientTrapItem = QListRemoveHead(&pClientEntry->ClientTraps); + } + + QListDestroy(&pClientEntry->ClientTraps); + + _DBG_LEAVE_LVL( _DBG_LVL_FUNC_TRACE ); +} + +// due to a port down event or as part of reregistration, clear all our +// subscription state +// if port down, no use retrying subscriptions now, for reregistration +// caller will process state change +void +InvalidatePortTrapSubscriptions(EUI64 PortGuid) +{ + LIST_ITEM *pTrapReferenceListItem; + TRAP_REFERENCE *pTrapReference; + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, InvalidatePortTrapSubscriptions); + + SpinLockAcquire(&SubscribedTrapsListLock); + + for (pTrapReferenceListItem = QListHead(&SubscribedTrapsList); + pTrapReferenceListItem != NULL; + pTrapReferenceListItem = QListNext(&SubscribedTrapsList, pTrapReferenceListItem)) + { + pTrapReference = (TRAP_REFERENCE *)QListObj(pTrapReferenceListItem); + + ASSERT(pTrapReference != NULL); + + if (pTrapReference->PortGuid == PortGuid) + { + pTrapReference->Flags = (TRAP_REFERENCE_FLAGS)(pTrapReference->Flags & ~TRAP_REF_FLAGS_SUBSCRIBED); + } + } + + SpinLockRelease(&SubscribedTrapsListLock); + + _DBG_LEAVE_LVL( _DBG_LVL_FUNC_TRACE ); + +} + +// called for port SM, LID or PKey change. Note LID change can imply +// an SM reregistration request as well +void +ReRegisterTrapSubscriptions(EUI64 PortGuid) +{ + LIST_ITEM *pTrapReferenceListItem; + TRAP_REFERENCE *pTrapReference; + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, ReRegisterTrapSubscriptions); + + InvalidatePortTrapSubscriptions(PortGuid); + + SpinLockAcquire(&SubscribedTrapsListLock); + + pTrapReferenceListItem = QListHead(&SubscribedTrapsList); + + while (pTrapReferenceListItem != NULL) + { + pTrapReference = (TRAP_REFERENCE *)QListObj(pTrapReferenceListItem); + + pTrapReferenceListItem = QListNext(&SubscribedTrapsList, pTrapReferenceListItem); + ASSERT(pTrapReference != NULL); + + if (pTrapReference->PortGuid == PortGuid) + { + // we delay so SA can settle a little and get ready for requests + ProcessTrapStateChange(pTrapReference, DEFER_DELAY); + } + } + + SpinLockRelease(&SubscribedTrapsListLock); + + _DBG_LEAVE_LVL( _DBG_LVL_FUNC_TRACE ); +} + +static __inline +CLIENT_TRAP_INFO * +FindClientTrapInfo(QUICK_LIST* pClientTraps, uint16 TrapNumber, EUI64 PortGuid) +{ + LIST_ITEM *pClientTrapInfoItem = QListHead(pClientTraps); + CLIENT_TRAP_INFO *pClientTrapInfo = NULL; + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, FindClientTrapInfo); + + while (pClientTrapInfoItem != NULL) + { + pClientTrapInfo = (CLIENT_TRAP_INFO *)QListObj(pClientTrapInfoItem); + + ASSERT(pClientTrapInfo != NULL); + + if ((pClientTrapInfo->TrapNumber == TrapNumber) && + (pClientTrapInfo->PortGuid == PortGuid)) + { + break; + } + + pClientTrapInfo = NULL; + pClientTrapInfoItem = QListNext(pClientTraps, pClientTrapInfoItem); + } + + _DBG_LEAVE_LVL( _DBG_LVL_FUNC_TRACE ); + + return pClientTrapInfo; +} + +/*! + \brief Looks through the list of Subnet Driver clients for those which have + subscribed for callback when a specific trap report has been received +*/ +void +ProcessClientTraps(void *pContext, IB_NOTICE *pNotice, EUI64 PortGuid) +{ + LIST_ITEM *pClientEntryListItem; + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, ProcessClientTraps); + + SpinLockAcquire(pClientListLock); + + pClientEntryListItem = QListHead(pClientList); + while (pClientEntryListItem != NULL) + { + CLIENT_TRAP_INFO *pClientTrapInfo; + ClientListEntry *pClientListEntry = (ClientListEntry *)QListObj(pClientEntryListItem); + + ASSERT(pClientListEntry != NULL); + + /* Call Subscribed Clients */ + + pClientTrapInfo = FindClientTrapInfo(&pClientListEntry->ClientTraps, pNotice->u.Generic.TrapNumber, PortGuid); + if ((pClientTrapInfo != NULL) && + (pClientTrapInfo->pReportNoticeCallback != NULL)) + { + SpinLockRelease(pClientListLock); /* TODO: This needs more thought for other than discovery */ + (*pClientTrapInfo->pReportNoticeCallback)(pClientTrapInfo->pContext, pNotice, PortGuid); + SpinLockAcquire(pClientListLock); + } + + pClientEntryListItem = QListNext(pClientList, pClientEntryListItem); + } + + SpinLockRelease(pClientListLock); + + _DBG_LEAVE_LVL( _DBG_LVL_FUNC_TRACE ); +} + +FSTATUS +iba_sd_trap_notice_subscribe(CLIENT_HANDLE ClientHandle, + uint16 TrapNumber, + EUI64 PortGuid, + void *pContext, + SD_REPORT_NOTICE_CALLBACK *pReportNoticeCallback) +{ + FSTATUS Status; + CLIENT_CONTROL_PARAMETERS ClientParams; + ClientListEntry *pClientEntry = (ClientListEntry *)ClientHandle; + CLIENT_TRAP_INFO *pClientTrapInfo; + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, iba_sd_trap_notice_subscribe); + + Status = ValidateClientHandle(ClientHandle, &ClientParams); + if (Status != FSUCCESS) + { + _DBG_ERROR(("Invalid Client Handle Specified\n")); + goto exit; + } + + SpinLockAcquire(pClientListLock); + + pClientTrapInfo = FindClientTrapInfo(&pClientEntry->ClientTraps, TrapNumber, PortGuid); + if (pClientTrapInfo != NULL) + { + // Already Subscribed + Status = FDUPLICATE; + SpinLockRelease(pClientListLock); + goto exit; + } + + SpinLockRelease(pClientListLock); + + pClientTrapInfo = (CLIENT_TRAP_INFO*)MemoryAllocate2AndClear(sizeof(CLIENT_TRAP_INFO), IBA_MEM_FLAG_NONE, SUBNET_DRIVER_TAG); + if (pClientTrapInfo == NULL) + { + Status = FINSUFFICIENT_MEMORY; + goto exit; + } + + pClientTrapInfo->TrapNumber = TrapNumber; + pClientTrapInfo->PortGuid = PortGuid; + pClientTrapInfo->pContext = pContext; + pClientTrapInfo->pReportNoticeCallback = pReportNoticeCallback; + + QListSetObj(&pClientTrapInfo->ListItem, pClientTrapInfo); + + SpinLockAcquire(pClientListLock); + QListInsertTail(&pClientEntry->ClientTraps, &pClientTrapInfo->ListItem); + SpinLockRelease(pClientListLock); + + Status = IncrementTrapUsageCount(TrapNumber, PortGuid); + if (Status != FSUCCESS) + { + SpinLockAcquire(pClientListLock); + QListRemoveItem(&pClientEntry->ClientTraps, &pClientTrapInfo->ListItem); + SpinLockRelease(pClientListLock); + MemoryDeallocate(pClientTrapInfo); + } + +exit: + _DBG_LEAVE_LVL( _DBG_LVL_FUNC_TRACE ); + return Status; +} + +FSTATUS +iba_sd_trap_notice_unsubscribe(CLIENT_HANDLE ClientHandle, uint16 TrapNumber, EUI64 PortGuid) +{ + FSTATUS Status; + CLIENT_CONTROL_PARAMETERS ClientParams; + ClientListEntry *pClientEntry = (ClientListEntry *)ClientHandle; + CLIENT_TRAP_INFO *pClientTrapInfo; + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, iba_sd_trap_notice_unsubscribe); + + Status = ValidateClientHandle(ClientHandle, &ClientParams); + if (Status != FSUCCESS) + { + _DBG_ERROR(("Invalid Client Handle Specified\n")); + goto exit; + } + + SpinLockAcquire(pClientListLock); + + pClientTrapInfo = FindClientTrapInfo(&pClientEntry->ClientTraps, TrapNumber, PortGuid); + if (pClientTrapInfo == NULL) + { + // Not Found + Status = FERROR; + SpinLockRelease(pClientListLock); + goto exit; + } + + QListRemoveItem(&pClientEntry->ClientTraps, &pClientTrapInfo->ListItem); + + SpinLockRelease(pClientListLock); + + MemoryDeallocate(pClientTrapInfo); + + DecrementTrapUsageCount(TrapNumber, PortGuid); + +exit: + _DBG_LEAVE_LVL( _DBG_LVL_FUNC_TRACE ); + return Status; +} + +// reports FALSE if we have failed to subscribe to any traps for given port +// returns TRUE if we succeeded to subscribe to all desired traps for +// given port or if we have requested no subscriptions for given port +boolean +iba_sd_port_traps_subscribed(EUI64 PortGuid) +{ + boolean Subscribed = TRUE; + LIST_ITEM *pTrapReferenceListItem; + TRAP_REFERENCE *pTrapReference; + + _DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, iba_sd_port_traps_subscribed); + + SpinLockAcquire(&SubscribedTrapsListLock); + + for (pTrapReferenceListItem = QListHead(&SubscribedTrapsList); + pTrapReferenceListItem != NULL; + pTrapReferenceListItem = QListNext(&SubscribedTrapsList, pTrapReferenceListItem)) + { + pTrapReference = (TRAP_REFERENCE *)QListObj(pTrapReferenceListItem); + + ASSERT(pTrapReference != NULL); + + if (pTrapReference->PortGuid == PortGuid) + { + if (pTrapReference->RefCount && !(pTrapReference->Flags & TRAP_REF_FLAGS_SUBSCRIBED)) + { + Subscribed = FALSE; + break; + } + } + } + + SpinLockRelease(&SubscribedTrapsListLock); + + _DBG_LEAVE_LVL( _DBG_LVL_FUNC_TRACE ); + + return Subscribed; +} diff --git a/IbAccess/Common/SubnetDriver/subscribe.h b/IbAccess/Common/SubnetDriver/subscribe.h new file mode 100644 index 0000000..6ba0a4e --- /dev/null +++ b/IbAccess/Common/SubnetDriver/subscribe.h @@ -0,0 +1,67 @@ +/* BEGIN_ICS_COPYRIGHT4 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT4 ****************************************/ +/*! + + \file subscribe.h + + $Revision$ + $Date$ + + \brief Routines to handle subscribing/unsubscribing to trap events +*/ + +#ifndef _SUBSCRIBE_H_ +#define _SUBSCRIBE_H_ + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +void SubscribeInitialize(void); + +void SubscribeTerminate(void); + +void +UnsubscribeClient(ClientListEntry *pClientEntry); + +void InvalidatePortTrapSubscriptions(EUI64 PortGuid); + +void ReRegisterTrapSubscriptions(EUI64 PortGuid); + +void ProcessClientTraps(void *pContext, IB_NOTICE *pNotice, EUI64 PortGuid); + +#ifdef __cplusplus +}; +#endif + +#endif // _SUBSCRIBE_H diff --git a/IbAccess/Makefile b/IbAccess/Makefile new file mode 100644 index 0000000..ef8b767 --- /dev/null +++ b/IbAccess/Makefile @@ -0,0 +1,187 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** +# Makefile for IbAccess Module + +# Include Make Control Settings +include $(TL_DIR)/$(PROJ_FILE_DIR)/Makesettings.project + +#=============================================================================# +# Definitions: +#-----------------------------------------------------------------------------# + +# Name of SubProjects +DS_SUBPROJECTS = +# name of executable or downloadable image +EXECUTABLE = # IbAccess$(EXE_SUFFIX) +ifeq "$(IB_STACK)" "IBACCESS" +# list of sub directories to build +ifeq "$(BUILD_TARGET_OS)" "VXWORKS" +DIRS = Vxworks +else +DIRS= +endif +endif +ifeq "$(IB_STACK)" "OPENIB" +ifeq "$(BUILD_TARGET_OS)" "LINUX" +DIRS = UserLinux +endif +endif +# C files (.c) +CFILES = \ + # Add more c files here +# C++ files (.cpp) +CCFILES = \ + # Add more cpp files here +# lex files (.lex) +LFILES = \ + # Add more lex files here +# archive library files (basename, $ARFILES will add MOD_LIB_DIR/prefix and suffix) +ifeq "$(BUILD_TARGET_OS)" "VXWORKS" +LIBFILES = Gsa Sma Vca Public TtsInit Umadt Sdi Tools +ifeq "$(INCLUDE_STLEEP)" "yes" +LIBFILES += Stleep +endif +ifeq "$(BUILD_CM)" "yes" +LIBFILES += Cm +endif +ifeq "$(BUILD_BMA)" "yes" +LIBFILES += Bma +endif +ifeq "$(BUILD_DMC)" "yes" +LIBFILES += Dmc +endif +else +LIBFILES= +endif +# Windows Resource Files (.rc) +RSCFILES = +# Windows IDL File (.idl) +IDLFILE = +# Windows Linker Module Definitions (.def) file for dll's +DEFFILE = +# targets to build during INCLUDES phase (add public includes here) +INCLUDE_TARGETS = \ + # Add more h hpp files here +# Non-compiled files +MISC_FILES = +# all source files +SOURCES = $(CFILES) $(CCFILES) $(LFILES) $(RSCFILES) $(IDLFILE) +# Source files to include in DSP File +DSP_SOURCES = $(INCLUDE_TARGETS) $(SOURCES) $(MISC_FILES) \ + $(RSCFILES) $(DEFFILE) $(MAKEFILE) Makerules.module +# all object files +OBJECTS = $(CFILES:.c=$(OBJ_SUFFIX)) $(CCFILES:.cpp=$(OBJ_SUFFIX)) \ + $(LFILES:.lex=$(OBJ_SUFFIX)) +RSCOBJECTS = $(RSCFILES:.rc=$(RES_SUFFIX)) +# targets to build during LIBS phase +LIB_TARGETS_IMPLIB = +ifeq "$(BUILD_TARGET_OS)" "VXWORKS" +LIB_TARGETS_ARLIB = $(LIB_PREFIX)IbAccess$(ARLIB_SUFFIX) +else +LIB_TARGETS_ARLIB = +endif +LIB_TARGETS_EXP = $(LIB_TARGETS_IMPLIB:$(ARLIB_SUFFIX)=$(EXP_SUFFIX)) +LIB_TARGETS_MISC = +# targets to build during CMDS phase +CMD_TARGETS_SHLIB = +CMD_TARGETS_EXE = $(EXECUTABLE) +CMD_TARGETS_MISC = +# files to remove during clean phase +CLEAN_TARGETS_MISC = +CLEAN_TARGETS = $(OBJECTS) $(RSCOBJECTS) $(IDL_TARGETS) $(CLEAN_TARGETS_MISC) +# other files to remove during clobber phase +CLOBBER_TARGETS_MISC= +# sub-directory to install to within bin +BIN_SUBDIR = +# sub-directory to install to within include +INCLUDE_SUBDIR = + +# Additional Settings +#CLOCALDEBUG = User defined C debugging compilation flags [Empty] +#CCLOCALDEBUG = User defined C++ debugging compilation flags [Empty] +#CLOCAL = User defined C flags for compiling [Empty] +#CCLOCAL = User defined C++ flags for compiling [Empty] +#BSCLOCAL = User flags for Browse File Builder [Empty] +#DEPENDLOCAL = user defined makedepend flags [Empty] +#LINTLOCAL = User defined lint flags [Empty] +#LOCAL_INCLUDE_DIRS = User include directories to search for C/C++ headers [Empty] +#LDLOCAL = User defined C flags for linking [Empty] +#IMPLIBLOCAL = User flags for Object Lirary Manager [Empty] +#MIDLLOCAL = User flags for IDL compiler [Empty] +#RSCLOCAL = User flags for resource compiler [Empty] +#LOCALDEPLIBS = User libraries to include in dependencies [Empty] +#LOCALLIBS = User libraries to use when linking [Empty] +# (in addition to LOCALDEPLIBS) +#LOCAL_LIB_DIRS = User library directories for libpaths [Empty] + +LOCALDEPLIBS = + +# Include Make Rules definitions and rules +include $(TL_DIR)/IbAccess/Makerules.module + +#=============================================================================# +# Overrides: +#-----------------------------------------------------------------------------# +#CCOPT = # C++ optimization flags, default lets build config decide +#COPT = # C optimization flags, default lets build config decide +#SUBSYSTEM = Subsystem to build for (none, console or windows) [none] +# (Windows Only) +#USEMFC = How Windows MFC should be used (none, static, shared, no_mfc) [none] +# (Windows Only) +#=============================================================================# + +#=============================================================================# +# Rules: +#-----------------------------------------------------------------------------# +# process Sub-directories +include $(TL_DIR)/Makerules/Maketargets.toplevel + +# build cmds and libs +include $(TL_DIR)/Makerules/Maketargets.build + +# install for includes, libs and cmds phases +include $(TL_DIR)/Makerules/Maketargets.moduleinstall + +# install for stage phase +ifeq "$(BUILD_TARGET_OS)" "VXWORKS" +STAGE:: +else +include $(TL_DIR)/Makerules/Maketargets.modulestage +endif + +# Unit test execution +#include $(TL_DIR)/Makerules/Maketargets.runtest + +clobber:: clobber_module + +#=============================================================================# + +#=============================================================================# +# DO NOT DELETE THIS LINE -- make depend depends on it. +#=============================================================================# diff --git a/IbAccess/Makerules.module b/IbAccess/Makerules.module new file mode 100644 index 0000000..1107ea1 --- /dev/null +++ b/IbAccess/Makerules.module @@ -0,0 +1,149 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** +## Rules for IbAccess module +#=============================================================================# +## Module Make Rules File +## ----------------------- +## +#=============================================================================# +## +#=============================================================================# +# The following list is the standard list of definitions which will be defined +# for all platforms. It consists of general and machine specific sections that +# contain many system parameters which may be used in a makefile. Please keep +# the list(s) in strictly aphabetical order to facilitate simple searches. +# +# See Makerules.global for the meaning of these flags +#-----------------------------------------------------------------------------# +# Common platform definitions: +#-----------------------------------------------------------------------------# +ifeq "$(CARD_TYPE)" "" +BUILT_SUFFIX= +else +BUILT_SUFFIX=.$(CARD_TYPE).$(TARGET_BSP).$(BUILD_CONFIG) +endif + +MOD_DIR=$(TL_DIR)/IbAccess +MOD_INCLUDE_DIR=$(PROJ_INCLUDE_DIR) +MOD_LIB_DIR=$(MOD_DIR)/builtlibs$(BUILT_SUFFIX) +MOD_BIN_DIR=$(PROJ_BIN_DIR) +MOD_SHLIB_DIR=$(PROJ_SHLIB_DIR) +MOD_SBR_DIR=$(PROJ_SBR_DIR) + +MOD_STAGE_DIR=$(PROJ_STAGE_DIR) +MOD_STAGE_INCLUDE_DIR=$(PROJ_STAGE_INCLUDE_DIR) +MOD_STAGE_LIB_DIR=$(MOD_DIR)/builtlibs$(BUILT_SUFFIX) +MOD_STAGE_BIN_DIR=$(PROJ_STAGE_BIN_DIR) +MOD_STAGE_SHLIB_DIR=$(PROJ_STAGE_SHLIB_DIR) +MOD_STAGE_SBR_DIR=$(PROJ_STAGE_SBR_DIR) +MOD_STAGE_DRIVER_BIN_DIR=$(PROJ_STAGE_DRIVER_BIN_DIR) + +MOD_BIN_SUBDIR = +MOD_DRIVER_BIN_SUBDIR = + +MOD_INCLUDE_DIRS = . $(GLOBAL_INCLUDE_DIR)/$(MOD_INCLUDE_SUBDIR) +MOD_LIB_DIRS = $(MOD_LIB_DIR) +MODDEPLIBS = +MODLIBS = + +BSCMOD = + +CCMOD = $(CMOD) +DEPENDMOD = +LDMOD = +LINTMOD = +MIDLMOD = +RSCMOD = + +# this allows Makefiles in OS specific directories to build and include +# files from corresponding Common directory +VPATH = $(COMMON_SRCDIR) +MOD_INCLUDE_DIRS += $(COMMON_SRCDIR) + +#-----------------------------------------------------------------------------# +# Platform specific definitions: +#-----------------------------------------------------------------------------# +ifeq "$(BUILD_TARGET_OS)" "VXWORKS" +CMOD = -DICS_LOGGING -D_NATIVE_MEMORY -DUSE_SD_MULTICAST +ifeq "$(BUILD_CONFIG)" "debug" +CMOD += -DDBG -D_DEBUG +endif +MOD_INCLUDE_SUBDIR = iba +MOD_INCLUDE_DIRS += $(GLOBAL_INCLUDE_DIR)/iba//public +endif +ifeq "$(BUILD_TARGET_OS)" "LINUX" +endif # LINUX +ifeq "$(BUILD_TARGET_OS)" "WIN32" +endif # WIN32 +#=============================================================================# +# Include Global makerules definitions and rules +include $(TL_DIR)/$(PROJ_FILE_DIR)/Makerules.project +#=============================================================================# + +#=============================================================================# +## The project makerules file also contains the following basic make target +## rules for simplifying application build processes: +## +#=============================================================================# +# The following section contains a list of standard targets which will be used +# by all of the makefiles. The targets are listed in alphabetical order and +# depend on the above definitions section as well as externally defined items +# from the user specific makefile. +#=============================================================================# +# General Rules: +#-----------------------------------------------------------------------------# +#=============================================================================# +ifeq "$(BUILD_TARGET_OS)" "VXWORKS" +#ifneq "$(TTS_WARN)" "high" +#ALL:: +# @echo "!!!Warnings have been disable for the tts_source module!!!" +# @echo "To enable warnings simply use TTS_WARN=high as follows" +# @echo "e.g. make TTS_WARN=high or runbuild TTS_WARN=high" +#endif +endif +#=============================================================================# +# This section contains a set of targets which override the standard ones +# provided for by GNU make. +#=============================================================================# +# Standard Makefile Rules Overrides: +#-----------------------------------------------------------------------------# +#=============================================================================# + +#=============================================================================# +# Targets to make sure the initial environment is properly configured +#=============================================================================# +#ifndef ENVIRONMENT +#check_env: +# @echo "The ENVIRONMENT environment variable must be set to be valid" +# @exit 1 +#else #ENVIRONMENT +#check_env: +#endif #ENVIRONMENT +#.PHONY: check_env +#=============================================================================# diff --git a/IbAccess/README b/IbAccess/README new file mode 100644 index 0000000..db2aff4 --- /dev/null +++ b/IbAccess/README @@ -0,0 +1,82 @@ +IbAccess Infiniband transport stack and agents + +Makefile design: +IbAccess can be built for multiple OS types. A large percentage of the code +is designed to be portable. However there are OS specific portions. + +Primary directory layout is as follows: + +Common - portable code for kernel mode and where the same user mode functions +UserCommon - portable code for user mode only +X - kernel code for OS X (Linux, Win2K, etc) +UserX - user mode code for OS X (Linux, Win2K, etc) when applicable + +READMEs in the X and UserX trees document the major functionality in each + directory + +The makefiles are implemented strictly in the X and UserX directory trees. +In those directories each Makefile follows the standard +"module level" makefile style as generated by buildMakefile -c Common/... +For example in Linux/Ibt/Cm use: + buildMakefile -c Common/Ibt/Cm + +The -c option causes the following additions to a basic Makefile + +COMMON_SRCDIR - is defined as the path to a peer Common directory (-c option) + for example: $(MOD_DIR)/Common/Ibt/Sma + This is used in Makerules.module to guide VPATH and MOD_INCLUDE_DIRS + to allow the given X/UserX Makefile to compile code in COMMON_SRCDIR +CFILES - files which are to be compiled from the local directory (directory + Makefile appears in) as well as files to be compiled from COMMON_SRCDIR + due to VPATH in Makerules.module, simple filenames must be listed for each. +INCLUDE_TARGETS - files which are to be public includes from the local + directory and the COMMON_SRCDIR. Here the files in the COMMON_SRCDIR + must be listed as full paths (eg. $(COMMON_SRCDIR)/header.h). + +The Makefiles for Each OS can decide which common files need to be compiled +and exported. +In some cases a given OS may only need a subset of the common capabilities +(especially from the OsAbstraction/Public component). +Those which are disabled are moved below the "Add more x files here" line +and are commented out (note that due to \ missing on "Add more ..." line +there is no problem with leaving a backslash at the end of these commented +out lines.) + +To Add a VPD Interface: +edit vpd_export.h, and update VPD_INTERFACE_VERSION_LATEST in enum (add a new +enum value). +update vca to use the interface +update Verbs Drivers to: + - report new interface version in VcaRegisterVpd3 (always use explicit not LATEST) + - implement new interface + - update va_verbs value returned +No need to rename VcaRegisterVpd nor VPD_KM_INTERFACE + +To add a UVP Interface: +edit uvp_export.h and update UVP_INTERFACE_VERSION_LATEST in enum (add a new enum value) +update uvca to use the interface +update UVP Verbs drivers to: + - return new interface version in GetVersion (always use explicit not LATEST) + - implement new interface + - update Interface function table value returned +No need to rename UVP_INTERFACE + +To add a Verbs interface: +- implement function in vca (iba_*) and export it (use an existing + function such as iba_post_send as an example of what is needed +- update vpi_export.h to export the function (no need to add to deprecated + VPI_KM_INTERFACE) +- implement function in uvca (iba_*) (see an existing function) +- update uvca_export.h to export the function (no need to add to deprecated + VPI_UM_INTERFACE) +- update IBT_VERSION to next number +- as needed add to UVP and/or VPD interface (see above) + +For windows declare IBA_API in UserWindows/../datatypes_osd.h as follows: +#ifdef _IBA_API_EXPORTS_ +#undef IBA_API +#define IBA_API __declspec(dllexport) +#else +#undef IBA_API +#define IBA_API __declspec(dllimport) +#endif // _IBA_API_EXPORTS_ diff --git a/IbAccess/TODO b/IbAccess/TODO new file mode 100644 index 0000000..4e7ae7e --- /dev/null +++ b/IbAccess/TODO @@ -0,0 +1,162 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +#[ICS VERSION STRING: unknown] +- if DestroyCQ fails, the Global handle should not be cleared. See how + deregister_mr handles the FBUSY (or any error) return. +- review other failure paths. +- modify_mr failure paths inconcistent. Some destroy the original MR, some + leave it untouched. Need a consistent way for caller to know. + Should NewMr returned be the original if it still exists or NULL if + original was destroyed? +- single/multi threaded flags allow locks in driver to be skipped + - on 3.0 GHz Pentium allows 40-50ns MPI improvement + - add UVCA, UVP API; + iba_set_flags(flags) - IBA_MULTI_THREADED, IBA_SINGLE_THREADED (0), later others + - entire appl/driver context is single/multi-threaded + - N/A for kernel since CONFIG_SMP tells kernel + - ? how to drive into UVP? + - via iba_ca_set_flags calls with special flags? + - call for presently open CAs as well as all future opens + - single threaded implies ca is single threaded + - multi-threaded does not imply ca behaviour + - add VPD, UVCA?, VCA API, UVP API?: + iba_ca_set_flags (flags) - IBA_MULTI_THREADED, IBA_SINGLE_THREADED (0), later others + - glue into TavorVpd spin lock optimization + - given ca instance is single/multi threaded +- review data structures between user and kernel. +- could allow non-owner user space iba_query_mr, issue query to + VKA using GetFirstDevice() for device context. This could be used to + create a tool to query all MR handles (1-10,000 or so) and report sizes, + total size. +- OsWait Object handle validation in VKA (Cq->WaitObjPtr) and CM (CEP->EventObj) +. Also review how these objects get created + is it via VKA calls? +- Ibt Open failures call close for subcomponents never opened +- make sure all output parameters can be NULL/optional in APIs, including + verbs drivers +- add const to API definitions +- VKA and VCA (possibly VPD) need to verify that same HCA applies when 2 + handles given such as CA and PD given for create QP, register MR, modify MR, + etc. +- some outputs from VPD/UVP not needed: QueryMR PdHandle, QueryAV PdHandle, etc + These are always replaced by VCA/UVCA +- iba_gsi_coallse, make it multiple APIs so don't have to copy into 1 + buffer. Such as iba_gsi_copy_dgrm(....,offset, len) to copy part of it + and let gsi deal with fragmentation of packets in RMPP response. + and iba_gsi_get_len(....) +- CM ProcessRej not right when in established or LAP states, see TBD comment + in ProcessRejReq +- could internally have a struct QP_CONTEXT in Vca which forms + base structure for IB_HANDLE returned by Vpd. + As such eliminate need for 2 small structures. + ditto for other resources (CQ, CA, etc). +- maintain reference counts in CA/QP/CQ during callbacks (async and completion) + avoid or defer destroy while in callback. May be able to have a simple + flag, much as CM does instead of an actual count. + applies to UVCA and possibly VCA. +- review error checks in UVCA, where possible just depend on checks in VKA + or VPD. Hence removing checks and code from UVCA. +- add API to query a single PKey/Gid by Index +- move common error checks, caching, etc from VPD to VCA +- move SMA caching from VPD to SMI +- utility function - GetAVFromCompletion(WORK_COMPLETION) + - build a IB_ADDRESS_VECTOR from a UD completion +- use IB_ADDRESS_VECTOR in Ibt_Dgrm for GSI +- Drop Element in Ibt_Dgrm for GSI +- growable dgrm pool in GSI +- ? use physical memory regions in GSI and kmalloc MAD buffers on fly? +- RD QpAttr lists for various state changes not correct +- declare ATOMIC_UINT as atomic_t in linux kernel +- look at removing thundering heard in Public/ithreadpool.c, could use + a counting semaphore instead and each release could add 1 free to + the semaphore. Would need to review counting semaphores truely work + on all platforms as this would be the 1st true use of them. +- RMPP and SA query timeouts should be based on: + ClassPortInfo.RespTimeValue + 2*PortInfo.SubnetTimeout + - if user provides a timeout, use larger of user timeout and this value. + - requery ClassPortInfo at a slow (hourly?) period rate + - see page 642, 650 IBTA 1.1 +- should RMPP context expect 1st data packet from sender (SA) within RespTimeout + for ClassPortInfo of SA rather than wait on TotalTransationTimeout? +- response time miscomputed for self querye of ClassPortInfo in SA CmdSentTime +- debug SA redirect code (requires fixes from SA). + Expected response to ClassPortInfo: + If no redirect, or a redirect to a known local subnet path + (This is what our SA should do at present): + Redirect SL, LID, P_Key,QP,Q_Key - set + RedirectGID, TC, FL=0 + + if no redirect, or a redirect to a known global subnet path: + Redirect SL, LID, P_Key,QP,Q_Key,RedirectGID, TC, FL - set + + If redirect and consumer needs to resolve path: + Redirect GID, QP, P_Key, Q_key -set + Redirect SL, LID, TC, FL = 0 + + Note some versions of our SM return 0 in all fields except QP + if not redirect. + Also our agents need to be fixed to return proper ClassPortInfo, most + zero the fields. + +- subnet driver, bInitialized flag seems unnecessary/incomplete + - should reset on port down and insure re-issue ClassPortInfo + when port comes up, see infop.c and calls to InitializeProviders + - class port info not really used yet, sdsend.c has use of redirect + ifdef'ed out +- Vka: + - pOpenContext and DeviceClose interaction with fork + - UVCA and VKA should not add handle to map's until object fully built? + - after validate handle, no locks nor reference counts held, so it could + get destroyed while in use by call which validated it. + - need a refcount and destroy must wait, make sure no deadlock + if callback calls destroy +- new test case in user_cm_test + - check handling of race between DREP w/o a callback: + RTU -> + callback sleep + DREQ -> + CmDisconnect(NULL, Drep, -) +- /proc/iba - have a file in release build showing overall memory locking stats + debug build can have the list. Ditto for memory allocation stats? +- merge umadt and sqpt into Common Umadt +- should CM grab QP error events and disconnect? +- VCA could keep lists of all CAs and their attributes, update in SMA + GetLocalCaInfo in Subnet/infop, sqpt_misc.c, umadt could be + a iba_query_all_cas_alloc function instead +- In HCA hot swap environment, SystemImageGuid can go stale if CA it was + chosen from is removed. Should have VcaSystemImageGuid(0) called by all SMA + and query CA operations (perhaps in IbAccess itself). Then if CA which + is SystemImageGuid is removed, change system image guid in Vca global to + that of another CA (or 0 if last CA) and issue the SystemImageGuid Change + notice to the SM on all active ports. + Also have a SystemImageGuid change callback in IBT notify + interface. Should somehow separate the system shutdown case since the + remaining CAs will quickly be removed and the notice and traps are of little + value. diff --git a/IbAccess/UserCommon/Inc/ibt.h b/IbAccess/UserCommon/Inc/ibt.h new file mode 100644 index 0000000..3c3b0b7 --- /dev/null +++ b/IbAccess/UserCommon/Inc/ibt.h @@ -0,0 +1,66 @@ +/* BEGIN_ICS_COPYRIGHT2 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT2 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +#ifndef _IBA_IBT_H_ +#define _IBA_IBT_H_ + +/* This is the primary include file for user mode access to + * the IbAccess APIs. It in turn includes all the files required to + * define the datatypes and interface functions which are exported. + */ + +#include "iba/public/datatypes.h" +#include "iba/public/statustext.h" +#include "iba/ib_ibt.h" +#include "iba/stl_types.h" +#include "iba/stl_sd.h" +#include "iba/stl_pa_priv.h" +#if defined(VXWORKS) +#ifdef BUILD_CM +#include "iba/ib_cm.h" +#endif +#else +#include "iba/ib_cm.h" +#endif +#include "iba/ib_avtracker.h" +#include "iba/umadt.h" + +#ifdef __cplusplus +extern "C" { +#endif + +IBA_API FSTATUS iba_init(void); + +#ifdef __cplusplus +}; +#endif + +#endif /* _IBA_IBT_H_ */ diff --git a/IbAccess/UserLinux/Inc/Makefile b/IbAccess/UserLinux/Inc/Makefile new file mode 100644 index 0000000..103bd50 --- /dev/null +++ b/IbAccess/UserLinux/Inc/Makefile @@ -0,0 +1,227 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** +# Makefile for Inc + +# Include Make Control Settings +include $(TL_DIR)/$(PROJ_FILE_DIR)/Makesettings.project + +#=============================================================================# +# Definitions: +#-----------------------------------------------------------------------------# + +# Name of SubProjects +DS_SUBPROJECTS = +# name of executable or downloadable image +EXECUTABLE = # Inc$(EXE_SUFFIX) +# list of sub directories to build +DIRS = +# C files (.c) +CFILES = \ + # Add more c files here +# C++ files (.cpp) +CCFILES = \ + # Add more cpp files here +# lex files (.lex) +LFILES = \ + # Add more lex files here +# archive library files (basename, $ARFILES will add MOD_LIB_DIR/prefix and suffix) +LIBFILES = +# Windows Resource Files (.rc) +RSCFILES = +# Windows IDL File (.idl) +IDLFILE = +# Windows Linker Module Definitions (.def) file for dll's +DEFFILE = +# targets to build during INCLUDES phase (add public includes here) +INCLUDE_TARGETS = \ + $(COMMON_SRCDIR)/ib_debug.h \ + $(COMMON_SRCDIR)/ib_dm.h \ + $(COMMON_SRCDIR)/ib_generalServices.h \ + $(COMMON_SRCDIR)/ib_helper.h \ + $(COMMON_SRCDIR)/ib_mad.h \ + $(COMMON_SRCDIR)/ib_pkt.h \ + $(COMMON_SRCDIR)/ib_rmpp.h \ + $(COMMON_SRCDIR)/ib_sa_records.h \ + $(COMMON_SRCDIR)/ib_sa_records_priv.h \ + $(COMMON_SRCDIR)/ib_sd.h \ + $(COMMON_SRCDIR)/ib_sd_priv.h \ + $(COMMON_SRCDIR)/ib_cm.h \ + $(COMMON_SRCDIR)/ib_sm_priv.h \ + $(COMMON_SRCDIR)/ib_sm_types.h \ + $(COMMON_SRCDIR)/ib_status.h \ + $(COMMON_SRCDIR)/ib_types.h \ + $(COMMON_SRCDIR)/ipublic.h \ + $(COMMON_SRCDIR)/stl_helper.h \ + $(COMMON_SRCDIR)/stl_mad_priv.h \ + $(COMMON_SRCDIR)/stl_mad_types.h \ + $(COMMON_SRCDIR)/stl_pa_priv.h \ + $(COMMON_SRCDIR)/stl_pa_types.h \ + $(COMMON_SRCDIR)/stl_pkt.h \ + $(COMMON_SRCDIR)/stl_pm.h \ + $(COMMON_SRCDIR)/stl_sm_priv.h \ + $(COMMON_SRCDIR)/stl_sm_types.h \ + $(COMMON_SRCDIR)/stl_sa_priv.h \ + $(COMMON_SRCDIR)/stl_sa_types.h \ + $(COMMON_SRCDIR)/stl_sd.h \ + $(COMMON_SRCDIR)/stl_t.h \ + $(COMMON_SRCDIR)/stl_types.h \ + $(COMMON_SRCDIR)/stl_em_eostl.h \ + $(COMMON_SRCDIR)/stl_ea_eostl.h \ + $(COMMON_SRCDIR)/stl_eepha_eostl.h \ + $(COMMON_SRCDIR)/stl_rmpp.h \ + ib_debug_osd.h \ + # Add more h hpp files here + # bldver_osd.h \ + # $(COMMON_SRCDIR)/bldver.h \ + # $(COMMON_SRCDIR)/cm_params.h \ + # $(COMMON_SRCDIR)/gsi_params.h \ + # $(COMMON_SRCDIR)/ib_gsi.h \ + # $(COMMON_SRCDIR)/ibt.h \ + # $(COMMON_SRCDIR)/ib_smi.h \ + # $(COMMON_SRCDIR)/sd_params.h \ + # $(COMMON_SRCDIR)/vpi_export.h \ + +ifeq "$(IB_STACK)" "OPENIB" +INCLUDE_TARGETS += \ + $(MOD_DIR)/../UserCommon/Inc/ibt.h \ + $(COMMON_SRCDIR)/ib_avtracker.h \ + $(COMMON_SRCDIR)/ib_ibt.h \ + $(COMMON_SRCDIR)/umadt.h \ + $(COMMON_SRCDIR)/vpi.h \ + $(COMMON_SRCDIR)/vpi_export.h \ + # Add more h hpp files here +endif + +ifeq "$(IB_STACK)" "IBACCESS" +INCLUDE_TARGETS += \ + $(COMMON_SRCDIR)/ib_avtracker.h \ + $(COMMON_SRCDIR)/ib_cm.h \ + $(COMMON_SRCDIR)/ib_ibt.h \ + $(COMMON_SRCDIR)/umadt.h \ + $(COMMON_SRCDIR)/vpi.h \ + $(COMMON_SRCDIR)/vpi_export.h \ + # Add more h hpp files here +endif +# Non-compiled files +MISC_FILES = +# all source files +SOURCES = $(CFILES) $(CCFILES) $(LFILES) $(RSCFILES) $(IDLFILE) +# Source files to include in DSP File +DSP_SOURCES = $(INCLUDE_TARGETS) $(SOURCES) $(MISC_FILES) \ + $(RSCFILES) $(DEFFILE) $(MAKEFILE) +# all object files +OBJECTS = $(CFILES:.c=$(OBJ_SUFFIX)) $(CCFILES:.cpp=$(OBJ_SUFFIX)) \ + $(LFILES:.lex=$(OBJ_SUFFIX)) +RSCOBJECTS = $(RSCFILES:.rc=$(RES_SUFFIX)) +# targets to build during LIBS phase +LIB_TARGETS_IMPLIB = +LIB_TARGETS_ARLIB = +LIB_TARGETS_EXP = $(LIB_TARGETS_IMPLIB:$(ARLIB_SUFFIX)=$(EXP_SUFFIX)) +LIB_TARGETS_MISC = +# targets to build during CMDS phase +CMD_TARGETS_SHLIB = +CMD_TARGETS_EXE = $(EXECUTABLE) +CMD_TARGETS_MISC = +CMD_TARGETS_DRIVER = +# files to remove during clean phase +CLEAN_TARGETS_MISC = +CLEAN_TARGETS = $(OBJECTS) $(RSCOBJECTS) $(IDL_TARGETS) $(CLEAN_TARGETS_MISC) +# other files to remove during clobber phase +CLOBBER_TARGETS_MISC= +# sub-directory to install to within bin +BIN_SUBDIR = +# sub-directory to install to within include +INCLUDE_SUBDIR = + +# Additional Settings +#CLOCALDEBUG = User defined C debugging compilation flags [Empty] +#CCLOCALDEBUG = User defined C++ debugging compilation flags [Empty] +#CLOCAL = User defined C flags for compiling [Empty] +#CCLOCAL = User defined C++ flags for compiling [Empty] +#BSCLOCAL = User flags for Browse File Builder [Empty] +#DEPENDLOCAL = user defined makedepend flags [Empty] +#LINTLOCAL = User defined lint flags [Empty] +#LOCAL_INCLUDE_DIRS = User include directories to search for C/C++ headers [Empty] +#LDLOCAL = User defined C flags for linking [Empty] +#IMPLIBLOCAL = User flags for Object Lirary Manager [Empty] +#MIDLLOCAL = User flags for IDL compiler [Empty] +#RSCLOCAL = User flags for resource compiler [Empty] +#LOCALDEPLIBS = User libraries to include in dependencies [Empty] +#LOCALLIBS = User libraries to use when linking [Empty] +# (in addition to LOCALDEPLIBS) +#LOCAL_LIB_DIRS = User library directories for libpaths [Empty] + +LOCALDEPLIBS = + +# Include Make Rules definitions and rules +include $(TL_DIR)/IbAccess/UserLinux/Makerules.module + +COMMON_SRCDIR = $(MOD_DIR)/../Common/Inc + +#=============================================================================# +# Overrides: +#-----------------------------------------------------------------------------# +#CCOPT = # C++ optimization flags, default lets build config decide +#COPT = # C optimization flags, default lets build config decide +#SUBSYSTEM = Subsystem to build for (none, console or windows) [none] +# (Windows Only) +#USEMFC = How Windows MFC should be used (none, static, shared, no_mfc) [none] +# (Windows Only) +#=============================================================================# + +#=============================================================================# +# Rules: +#-----------------------------------------------------------------------------# +# process Sub-directories +include $(TL_DIR)/Makerules/Maketargets.toplevel + +# build cmds and libs +include $(TL_DIR)/Makerules/Maketargets.build + +# install for includes, libs and cmds phases +include $(TL_DIR)/Makerules/Maketargets.install + +# install for stage phase +ifeq "$(IB_STACK)" "OPENIB" +STAGE:: +ifeq "$(PRODUCT)" "OPENIB_FF" + $(VS)$(STAGE_INSTALL) $(STAGE_INSTALL_DIR_OPT) $(PROJ_STAGE_OPAMGT_DIR) $(INCLUDE_TARGETS) +endif +else +include $(TL_DIR)/Makerules/Maketargets.stage +endif + +# Unit test execution +#include $(TL_DIR)/Makerules/Maketargets.runtest + +#=============================================================================# + +#=============================================================================# +# DO NOT DELETE THIS LINE -- make depend depends on it. +#=============================================================================# diff --git a/IbAccess/UserLinux/Inc/README b/IbAccess/UserLinux/Inc/README new file mode 100644 index 0000000..41bc966 --- /dev/null +++ b/IbAccess/UserLinux/Inc/README @@ -0,0 +1 @@ +Linux specific user include files diff --git a/IbAccess/UserLinux/Inc/bldver_osd.h b/IbAccess/UserLinux/Inc/bldver_osd.h new file mode 100644 index 0000000..69911db --- /dev/null +++ b/IbAccess/UserLinux/Inc/bldver_osd.h @@ -0,0 +1,35 @@ +/* BEGIN_ICS_COPYRIGHT2 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT2 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ +#ifndef _IBA_BLD_VER_OSD_H_ +#define _IBA_BLD_VER_OSD_H_ + + +#endif /* _IBA_BLD_VER_OSD_H_ */ diff --git a/IbAccess/UserLinux/Inc/ib_debug_osd.h b/IbAccess/UserLinux/Inc/ib_debug_osd.h new file mode 100644 index 0000000..ed36906 --- /dev/null +++ b/IbAccess/UserLinux/Inc/ib_debug_osd.h @@ -0,0 +1,50 @@ +/* BEGIN_ICS_COPYRIGHT3 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT3 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +/* Suppress duplicate loading of this file */ +#ifndef _IBA_IB_DEBUG_OSD_H_ +#define _IBA_IB_DEBUG_OSD_H_ + +#include "iba/public/idebug.h" + +#define _DBG_CHK_IRQL(IRQL) + +#define _DBG_PRINT_EPILOG(LEVEL,STRING) +#define _DBG_PRINT_PROLOG(LEVEL,STRING) +#define _DBG_ERROR_EPILOG(LEVEL,STRING) +#define _DBG_ERROR_PROLOG(LEVEL,STRING) +#define _DBG_FATAL_EPILOG(LEVEL,STRING) +#define _DBG_FATAL_PROLOG(LEVEL,STRING) + +#include "iba/ib_debug.h" + +#endif /* _IBA_IB_DEBUG_OSD_H_ */ + diff --git a/IbAccess/UserLinux/Makefile b/IbAccess/UserLinux/Makefile new file mode 100644 index 0000000..dec94cf --- /dev/null +++ b/IbAccess/UserLinux/Makefile @@ -0,0 +1,49 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** +# Makefile for UserLinux + +# Include Make Control Settings +include $(TL_DIR)/$(PROJ_FILE_DIR)/Makesettings.project + +DS_SUBPROJECTS = +DSP_SOURCES = Makefile + +ifeq "$(IB_STACK)" "OPENIB" +DIRS = Public Inc +endif + +include $(TL_DIR)/IbAccess/UserLinux/Makerules.module + +include $(TL_DIR)/Makerules/Maketargets.toplevel + +# install for includes, libs and cmds phases +include $(TL_DIR)/Makerules/Maketargets.install + +# install for stage phase +include $(TL_DIR)/Makerules/Maketargets.stage diff --git a/IbAccess/UserLinux/Makerules.module b/IbAccess/UserLinux/Makerules.module new file mode 100644 index 0000000..8882e28 --- /dev/null +++ b/IbAccess/UserLinux/Makerules.module @@ -0,0 +1,141 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** +## Rules for IbAccess/Linux module +#=============================================================================# +## Module Make Rules File +## ----------------------- +## +#=============================================================================# +## +#=============================================================================# +# The following list is the standard list of definitions which will be defined +# for all platforms. It consists of general and machine specific sections that +# contain many system parameters which may be used in a makefile. Please keep +# the list(s) in strictly aphabetical order to facilitate simple searches. +# +# See Makerules.global for the meaning of these flags +#-----------------------------------------------------------------------------# +# Common platform definitions: +#-----------------------------------------------------------------------------# +MOD_DIR=$(TL_DIR)/IbAccess/UserLinux +MOD_INCLUDE_DIR=$(PROJ_INCLUDE_DIR) +ifeq "$(IB_STACK)" "OPENIB" +MOD_LIB_DIR=$(PROJ_LIB_DIR) +else +MOD_LIB_DIR=$(MOD_DIR)/builtlibs$(BUILT_SUFFIX) +endif +MOD_BIN_DIR=$(MOD_DIR)/builtbin$(BUILT_SUFFIX) +MOD_SHLIB_DIR=$(PROJ_SHLIB_DIR) +MOD_SBR_DIR=$(PROJ_SBR_DIR) +MOD_DRIVER_BIN_DIR=$(MOD_DIR)/builtbin$(BUILT_SUFFIX) + +MOD_STAGE_DIR=$(PROJ_STAGE_DIR) +MOD_STAGE_INCLUDE_DIR=$(PROJ_STAGE_INCLUDE_DIR) +ifeq "$(IB_STACK)" "OPENIB" +MOD_STAGE_LIB_DIR=$(PROJ_STAGE_LIB_DIR) +else +MOD_STAGE_LIB_DIR=$(MOD_DIR)/builtlibs$(BUILT_SUFFIX) +endif +MOD_STAGE_BIN_DIR=$(PROJ_STAGE_BIN_DIR) +MOD_STAGE_SHLIB_DIR=$(PROJ_STAGE_SHLIB_DIR) +MOD_STAGE_SBR_DIR=$(PROJ_STAGE_SBR_DIR) +MOD_STAGE_DRIVER_BIN_DIR=$(PROJ_STAGE_DRIVER_BIN_DIR) + +MOD_BIN_SUBDIR = +MOD_DRIVER_BIN_SUBDIR = +MOD_INCLUDE_SUBDIR = iba + +MOD_INCLUDE_DIRS = . $(GLOBAL_INCLUDE_DIR)/$(MOD_INCLUDE_SUBDIR) $(GLOBAL_INCLUDE_DIR)/iba/public +MOD_LIB_DIRS = $(MOD_LIB_DIR) +MODDEPLIBS = +MODLIBS = + +BSCMOD = +CMOD = $(CPIC) +CCMOD = $(CMOD) +DEPENDMOD = +LDMOD = +LINTMOD = +MIDLMOD = +RSCMOD = + +# this allows Makefiles in OS specific directories to build and include +# files from corresponding Common directory +VPATH = $(COMMON_SRCDIR) +MOD_INCLUDE_DIRS += $(COMMON_SRCDIR) $(MOD_DIR)/Ibt/IbtMain $(MOD_DIR)/../Linux/Public $(MOD_DIR)/../Linux/Inc $(MOD_DIR)/../Common/Inc + +#-----------------------------------------------------------------------------# +# Platform specific definitions: +#-----------------------------------------------------------------------------# +ifeq "$(BUILD_TARGET_OS)" "VXWORKS" +endif +ifeq "$(BUILD_TARGET_OS)" "LINUX" +endif # LINUX +ifeq "$(BUILD_TARGET_OS)" "WIN32" +endif # WIN32 +ifeq "$(BUILD_TARGET_OS)" "DARWIN" +endif # DARWIN +#=============================================================================# +# Include Global makerules definitions and rules +include $(TL_DIR)/$(PROJ_FILE_DIR)/Makerules.project +#=============================================================================# + +#=============================================================================# +## The project makerules file also contains the following basic make target +## rules for simplifying application build processes: +## +#=============================================================================# +# The following section contains a list of standard targets which will be used +# by all of the makefiles. The targets are listed in alphabetical order and +# depend on the above definitions section as well as externally defined items +# from the user specific makefile. +#=============================================================================# +# General Rules: +#-----------------------------------------------------------------------------# +#=============================================================================# +#=============================================================================# +# This section contains a set of targets which override the standard ones +# provided for by GNU make. +#=============================================================================# +# Standard Makefile Rules Overrides: +#-----------------------------------------------------------------------------# +#=============================================================================# + +#=============================================================================# +# Targets to make sure the initial environment is properly configured +#=============================================================================# +#ifndef ENVIRONMENT +#check_env: +# @echo "The ENVIRONMENT environment variable must be set to be valid" +# @exit 1 +#else #ENVIRONMENT +#check_env: +#endif #ENVIRONMENT +#.PHONY: check_env +#=============================================================================# diff --git a/IbAccess/UserLinux/Public/Makefile b/IbAccess/UserLinux/Public/Makefile new file mode 100644 index 0000000..9687b59 --- /dev/null +++ b/IbAccess/UserLinux/Public/Makefile @@ -0,0 +1,233 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** +# Makefile for public + +# Include Make Control Settings +include $(TL_DIR)/$(PROJ_FILE_DIR)/Makesettings.project + +#=============================================================================# +# Definitions: +#-----------------------------------------------------------------------------# + +# Name of SubProjects +DS_SUBPROJECTS = +# name of executable or downloadable image +EXECUTABLE = # public$(EXE_SUFFIX) +# list of sub directories to build +DIRS = +# C files (.c) +CFILES = \ + iarray.c \ + ibitvector.c \ + icmdthread.c \ + idebugdump.c \ + idebug_linux.c \ + ievent.c \ + ieventthread.c \ + ilist.c \ + imath.c \ + imemory.c \ + imemory_osd.c \ + iobjmgr.c \ + iquickmap.c \ + isemaphore.c \ + ispinlock.c \ + ithread.c \ + ithreadpool.c \ + itimer.c \ + statustext.c \ + # Add more c files here + # ireaper.c \ + +CFILES += \ +# C++ files (.cpp) +CCFILES = \ + # Add more cpp files here +# lex files (.lex) +LFILES = \ + # Add more lex files here +# archive library files (basename, $ARFILES will add MOD_LIB_DIR/prefix and suffix) +LIBFILES = +# Windows Resource Files (.rc) +RSCFILES = +# Windows IDL File (.idl) +IDLFILE = +# Windows Linker Module Definitions (.def) file for dll's +DEFFILE = +# targets to build during INCLUDES phase (add public includes here) +INCLUDE_TARGETS = \ + $(COMMON_SRCDIR)/datatypes.h \ + $(COMMON_SRCDIR)/iarray.h \ + $(COMMON_SRCDIR)/ibitvector.h \ + $(COMMON_SRCDIR)/ibyteswap.h \ + $(COMMON_SRCDIR)/icmdthread.h \ + $(COMMON_SRCDIR)/idebug.h \ + $(COMMON_SRCDIR)/iethernet.h \ + $(COMMON_SRCDIR)/ievent.h \ + $(COMMON_SRCDIR)/ieventthread.h \ + $(COMMON_SRCDIR)/iheapmanager.h \ + $(COMMON_SRCDIR)/ilist.h \ + $(COMMON_SRCDIR)/imath.h \ + $(COMMON_SRCDIR)/imemory.h \ + $(COMMON_SRCDIR)/imemtrack.h \ + $(COMMON_SRCDIR)/imutex.h \ + $(COMMON_SRCDIR)/iobjmgr.h \ + $(COMMON_SRCDIR)/iquickmap.h \ + $(COMMON_SRCDIR)/isemaphore.h \ + $(COMMON_SRCDIR)/ispinlock.h \ + $(COMMON_SRCDIR)/itcpip.h \ + $(COMMON_SRCDIR)/ithread.h \ + $(COMMON_SRCDIR)/ithreadpool.h \ + $(COMMON_SRCDIR)/itimer.h \ + $(COMMON_SRCDIR)/statustext.h \ + datatypes_osd.h \ + idebug_osd.h \ + ievent_osd.h \ + imemory_osd.h \ + imutex_osd.h \ + ipackoff.h \ + ipackon.h \ + isemaphore_osd.h \ + ispinlock_osd.h \ + ithread_osd.h \ + itimer_osd.h \ + ibyteswap_osd.h + # Add more h hpp files here + # $(COMMON_SRCDIR)/ipassivelock.h \ + # $(COMMON_SRCDIR)/ireaper.h \ + +# Non-compiled files +MISC_FILES = +# all source files +SOURCES = $(CFILES) $(CCFILES) $(LFILES) $(RSCFILES) $(IDLFILE) +# Source files to include in DSP File +DSP_SOURCES = $(INCLUDE_TARGETS) $(SOURCES) $(MISC_FILES) \ + $(RSCFILES) $(DEFFILE) $(MAKEFILE) +# all object files +OBJECTS = $(CFILES:.c=$(OBJ_SUFFIX)) $(CCFILES:.cpp=$(OBJ_SUFFIX)) \ + $(LFILES:.lex=$(OBJ_SUFFIX)) +RSCOBJECTS = $(RSCFILES:.rc=$(RES_SUFFIX)) +# targets to build during LIBS phase +LIB_TARGETS_IMPLIB = +ifeq "$(IB_STACK)" "OPENIB" +LIB_TARGETS_ARLIB = $(LIB_PREFIX)public$(ARLIB_SUFFIX) +else +LIB_TARGETS_ARLIB = +endif +LIB_TARGETS_EXP = $(LIB_TARGETS_IMPLIB:$(ARLIB_SUFFIX)=$(EXP_SUFFIX)) +LIB_TARGETS_MISC = +# targets to build during CMDS phase +SHLIB_VERSION = 0.0 +ifeq "$(IB_STACK)" "OPENIB" +CMD_TARGETS_SHLIB = +else +CMD_TARGETS_SHLIB = $(LIB_PREFIX)public$(SHLIB_VERSION_SUFFIX) +endif +CMD_TARGETS_EXE = $(EXECUTABLE) +CMD_TARGETS_MISC = +CMD_TARGETS_DRIVER = +# files to remove during clean phase +CLEAN_TARGETS_MISC = +CLEAN_TARGETS = $(OBJECTS) $(RSCOBJECTS) $(IDL_TARGETS) $(CLEAN_TARGETS_MISC) +# other files to remove during clobber phase +CLOBBER_TARGETS_MISC= +# sub-directory to install to within bin +BIN_SUBDIR = +# sub-directory to install to within include +INCLUDE_SUBDIR = + +# Additional Settings +#CLOCALDEBUG = User defined C debugging compilation flags [Empty] +#CCLOCALDEBUG = User defined C++ debugging compilation flags [Empty] +#CLOCAL = User defined C flags for compiling [Empty] +#CCLOCAL = User defined C++ flags for compiling [Empty] +#BSCLOCAL = User flags for Browse File Builder [Empty] +#DEPENDLOCAL = user defined makedepend flags [Empty] +#LINTLOCAL = User defined lint flags [Empty] +#LOCAL_INCLUDE_DIRS = User include directories to search for C/C++ headers [Empty] +#LDLOCAL = User defined C flags for linking [Empty] +#IMPLIBLOCAL = User flags for Object Lirary Manager [Empty] +#MIDLLOCAL = User flags for IDL compiler [Empty] +#RSCLOCAL = User flags for resource compiler [Empty] +#LOCALDEPLIBS = User libraries to include in dependencies [Empty] +#LOCALLIBS = User libraries to use when linking [Empty] +# (in addition to LOCALDEPLIBS) +#LOCAL_LIB_DIRS = User library directories for libpaths [Empty] + +LOCALDEPLIBS = +# need -nostartfiles since we have our own _init +LDLOCAL=-nostartfiles + +# Include Make Rules definitions and rules +include $(TL_DIR)/IbAccess/UserLinux/Makerules.module + +COMMON_SRCDIR = $(MOD_DIR)/../Common/Public +MOD_INCLUDE_SUBDIR = iba/public + +#=============================================================================# +# Overrides: +#-----------------------------------------------------------------------------# +#CCOPT = # C++ optimization flags, default lets build config decide +#COPT = # C optimization flags, default lets build config decide +#SUBSYSTEM = Subsystem to build for (none, console or windows) [none] +# (Windows Only) +#USEMFC = How Windows MFC should be used (none, static, shared, no_mfc) [none] +# (Windows Only) +#=============================================================================# + +#=============================================================================# +# Rules: +#-----------------------------------------------------------------------------# +# process Sub-directories +include $(TL_DIR)/Makerules/Maketargets.toplevel + +# build cmds and libs +include $(TL_DIR)/Makerules/Maketargets.build + +# install for includes, libs and cmds phases +include $(TL_DIR)/Makerules/Maketargets.install + +# install for stage phase +ifeq "$(IB_STACK)" "OPENIB" +STAGE:: +ifeq "$(PRODUCT)" "OPENIB_FF" + $(VS)$(STAGE_INSTALL) $(STAGE_INSTALL_DIR_OPT) $(PROJ_STAGE_OPAMGT_DIR) $(INCLUDE_TARGETS) +endif +else +include $(TL_DIR)/Makerules/Maketargets.stage +endif + +# Unit test execution +#include $(TL_DIR)/Makerules/Maketargets.runtest + +#=============================================================================# + +#=============================================================================# +# DO NOT DELETE THIS LINE -- make depend depends on it. +#=============================================================================# diff --git a/IbAccess/UserLinux/Public/README b/IbAccess/UserLinux/Public/README new file mode 100644 index 0000000..d0757b3 --- /dev/null +++ b/IbAccess/UserLinux/Public/README @@ -0,0 +1 @@ +An OS Abstraction layer diff --git a/IbAccess/UserLinux/Public/datatypes_osd.h b/IbAccess/UserLinux/Public/datatypes_osd.h new file mode 100644 index 0000000..42a0531 --- /dev/null +++ b/IbAccess/UserLinux/Public/datatypes_osd.h @@ -0,0 +1,174 @@ +/* BEGIN_ICS_COPYRIGHT2 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT2 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + + +#ifndef _IBA_PUBLIC_DATA_TYPES_OSD_H_ +#define _IBA_PUBLIC_DATA_TYPES_OSD_H_ + +#include +#include +#include +#include + + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * This file defines the data types specific to the Linux Operating System. + * Most of the basic type definitions are picked up from + */ + +#ifndef TRUE +#define TRUE 1 +#endif + +#ifndef FALSE +#define FALSE 0 +#endif + +#define IBA_API +#define _NATIVE_MEMORY + +#if defined(__PGI) && defined(__X86_64__) +/* PGI C compiler's linux86-64/6.1/include/sys/types.h header does not define + * this, oddly their linux86/6.1/include/sys/types.h header does + */ +typedef unsigned long u_int64_t; +#endif + +#ifndef IB_STACK_OPENIB +typedef unsigned char boolean_t, boolean; +#else +typedef unsigned char boolean; +#endif +typedef uint8_t uint8; +typedef int8_t int8; +typedef uint16_t uint16; +typedef int16_t int16; +typedef uint32_t uint32; +typedef int32_t int32; +typedef int64_t int64; +typedef uint64_t uint64; +typedef long intn; /* __WORDSIZE/pointer sized integer */ +typedef unsigned long uintn; /* __WORDSIZE/pointer sized integer */ +typedef unsigned char uchar; + +/* Global state for all the objects that are created using the public + * layer (Events, Timers, Threads etc.) + */ + +typedef enum _ObjectState { + Constructed = 0, + Started, + Destroyed +} ObjectState; + +/* Copied from SLES9 compiler.h */ +#if (__GNUC__ > 3) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1) + +#ifndef inline +#define inline __inline__ +#endif /* inline */ + +#ifndef __inline__ +#define __inline__ __inline__ +#endif /* __inline__ */ + +#ifndef __inline +#define __inline __inline__ +#endif /* __inline */ + +#endif /* (__GNUC__ > 3) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1) */ + +/* Copied from SLES10 compiler.h */ +#ifndef __always_inline +#define __always_inline inline +#endif + +#ifndef __inline + +#if ! defined(__PATHSCALE__) && ! defined(__PGI) && (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1)) +#define inline __attribute__((always_inline)) inline +#define __inline __attribute__((always_inline)) inline +#else +#define __inline inline +#endif /* GNUC */ + +#endif /* __inline */ + +#define _inline inline + +#define CONTAINING_RECORD(address, type, field) \ + ((type *)((char *)(address) - (uintn)(&((type *)0)->field))) + +extern void PanicOnAssert (char *exp, char *filename, int linenum, char *message); + +#if defined(__PATHSCALE__) || (__GNUC__) +/* These are a few macros to aid compiler in branch prediction */ + /* tell compiler typical value for an expression */ +#define IB_EXPECT(expr, expected) __builtin_expect((expr), (expected)) + /* tell compiler typical expectation for conditional expression */ +#define IB_EXPECT_TRUE(cond) __builtin_expect(!!(cond), 1) +#define IB_EXPECT_FALSE(cond) __builtin_expect(!!(cond), 0) +#else +#define IB_EXPECT(expr, expected) (expr) +#define IB_EXPECT_TRUE(expr) (expr) +#define IB_EXPECT_FALSE(expr) (expr) +#endif + +/* macro to tell compiler a variable may be unused and to suppress any related + * warnings. Useful to reduce clutter when code has ifdef's or debug code + * this macro can be used as follows: + * int var IB_UNUSED; + * it can be used for parameters and variables + */ +#define IB_UNUSED __attribute__((unused)) + +#undef DEBUG_ASSERT +#ifndef ASSERT +extern void BackTrace(FILE *file); +#define ASSERT(__exp__) do { if (IB_EXPECT_FALSE(! (__exp__))) { BackTrace(stderr); assert(__exp__); } } while(0); +#endif /* ASSERT */ +#if defined(IB_DEBUG) || defined(DBG) +#define DEBUG_ASSERT(__exp__) ASSERT(__exp__) +#else +#define DEBUG_ASSERT(__exp__) (void)0 +#endif + +#define __cdecl + +#ifdef __cplusplus +}; +#endif + +#endif /* _IBA_PUBLIC_DATA_TYPES_OSD_H_ */ diff --git a/IbAccess/UserLinux/Public/ibyteswap_osd.h b/IbAccess/UserLinux/Public/ibyteswap_osd.h new file mode 100644 index 0000000..18de40e --- /dev/null +++ b/IbAccess/UserLinux/Public/ibyteswap_osd.h @@ -0,0 +1,90 @@ +/* BEGIN_ICS_COPYRIGHT3 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT3 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + + +/* + * This provides defines __LITTLE_ENDIAN, __BIG_ENDIAN and __BYTE_ORDER + */ + +#ifndef _IBA_PUBLIC_IBYTESWAP_OSD_H_ +#define _IBA_PUBLIC_IBYTESWAP_OSD_H_ + +#include "iba/public/datatypes.h" +#include +#include + +#if !defined(bswap_64) || (__PGIC__) +/* unfortunately when compiling with PGI C, the macro is not defined by + * /usr/include/bits/byteswap.h and, in fact, newer versions declare a + * prototype for bswap_64() but then never provide the function... + */ +#if __BYTE_ORDER == __LITTLE_ENDIAN +static uint64 bswap_64(uint64 x) +{ + union { + uint64 __u64; + uint32 __u32[2]; + } __in, __out; + __in.__u64 = x; + __out.__u32[0] = bswap_32(__in.__u32[1]); + __out.__u32[1] = bswap_32(__in.__u32[0]); + return __out.__u64; +} +#else +#define bswap_64(x) (x) +#endif /* endian */ +#endif /* bswap_64 */ + +/* + * Convert multi-byte words for the local machine architecture. + * This is a byte swap on small-endian machines, but not on big-endian. + */ +#if defined(__LITTLE_ENDIAN) && (__BYTE_ORDER == __LITTLE_ENDIAN) +#define ntoh16(x) bswap_16(x) +#define hton16(x) bswap_16(x) + +#define ntoh32(x) bswap_32(x) +#define hton32(x) bswap_32(x) + +#define ntoh64(x) bswap_64(x) +#define hton64(x) bswap_64(x) +#else +#define ntoh16(x) (x) +#define hton16(x) (x) + +#define ntoh32(x) (x) +#define hton32(x) (x) + +#define ntoh64(x) (x) +#define hton64(x) (x) +#endif + +#endif /* _IBA_PUBLIC_IBYTESWAP_H_ */ diff --git a/IbAccess/UserLinux/Public/idebug_linux.c b/IbAccess/UserLinux/Public/idebug_linux.c new file mode 100644 index 0000000..36f13e5 --- /dev/null +++ b/IbAccess/UserLinux/Public/idebug_linux.c @@ -0,0 +1,170 @@ +/* BEGIN_ICS_COPYRIGHT5 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT5 ****************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include "datatypes.h" +#include "ib_debug.h" + +static int use_syslog = 0; +/*! +Very linux specific way to get the pathname when we +don't have access to the arglist. +*/ +void +pgmname(char *name, size_t max) +{ + char procname[64]; + char buf[PATH_MAX]; + int len; + char *p; + + use_syslog = 1; + sprintf(procname,"/proc/%d/exe", getpid()); + len = readlink(procname, buf, sizeof(buf)); + if (len > 0) + { + buf[len] = '\0'; + p = strrchr(buf, '/'); + strncpy(name, p == NULL?buf:p+1, max); + name[max-1] = 0; + } + else + { + /* reasonable default? */ + strncpy(name, "ibt", max); + name[max-1]=0; + } +} + +//static char *default_log_name = "ibt"; + +void IbLogPrintf(uint32 level, const char* format, ...) +{ + va_list args; + + va_start(args, format); + if (use_syslog) + { + int priority; + + if (level & _DBG_LVL_FATAL) + priority = LOG_CRIT; + if (level & _DBG_LVL_ERROR) + priority = LOG_ERR; + else if (level & (_DBG_LVL_WARN)) + priority = LOG_WARNING; + else if (! level || level & (_DBG_LVL_INFO)) + priority = LOG_INFO; + else + priority = LOG_DEBUG; + + vsyslog(priority, format, args); + } else + { + vprintf(format, args); + } + va_end(args); +} + +// Only used for direct calls to DbgOut +void +PrintUDbg(char *Message, ...) +{ + va_list args; + + va_start(args, Message); + if (use_syslog) + { + vsyslog(LOG_DEBUG, Message, args); + } else + { + vprintf(Message, args); + } + va_end(args); +} + +// only used for direct calls to MsgOut +void +PrintUMsg(char *Message, ...) +{ + va_list args; + + va_start(args, Message); + if (use_syslog) + { + vsyslog(LOG_INFO, Message, args); + } else + { + vprintf(Message, args); + } + va_end(args); +} + +#include +void BackTrace(FILE *file) +{ + void *buffer[100]; + int size; + + if (file && ! use_syslog) + { + fprintf(file, "Stack Backtrace:\n"); + fflush(file); + } else { + syslog(LOG_INFO, "Stack Backtrace:\n"); + } + size = backtrace(buffer, 100); + if (size <= 0 || size > 100) { + fprintf(stderr, "unable to get backtrace\n"); + return; + } + if (file && ! use_syslog) + { + backtrace_symbols_fd(buffer, size, fileno(file)); + fprintf(file, "\n"); + } else { + char **symbols = backtrace_symbols(buffer, size); + int i; + + for (i=0; i +#include +#include +#include + +#ifdef ___cplusplus +extern "C" { +#endif + +extern void IbLogPrintf(uint32 level, const char* format, ...) +#if defined(__GNUC__) + __attribute__((format(printf, 2, 3))) +#endif + ; +extern void PrintUDbg( char *Message, ... ) +#if defined(__GNUC__) + __attribute__((format(printf, 1, 2))) +#endif + ; +extern void PrintUMsg( char *Message, ... ) +#if defined(__GNUC__) + __attribute__((format(printf, 1, 2))) +#endif + ; + +#if defined(IB_DEBUG) || defined(DBG) +#ifndef DbgOutRoutine +#define DbgOutRoutine PrintUDbg +extern void PrintUDbg(IN char *DebugMessage, IN ... ); +#endif +#ifdef __ia64 +#define DbgBreakPoint() asm(" break 0") +#elif defined(ppc) +#define DbgBreakPoint() asm(" trap") +#else +#define DbgBreakPoint() asm(" int $3") +#endif +#else +#define DbgOut +#endif + +#define MsgOut PrintUMsg +#undef __PRI64_PREFIX +#if __WORDSIZE == 64 +#define __PRI64_PREFIX "l" +#define PRISZT "lu" +#elif __WORDSIZE == 32 +#define __PRI64_PREFIX "L" +#define PRISZT "u" +#else +#error "__WORDSIZE not 64 nor 32" +#endif + +#undef __PRIN_PREFIX +#undef PRId64 +#undef PRIo64 +#undef PRIu64 +#undef PRIx64 +#undef PRIX64 +#undef PRIdN +#undef PRIoN +#undef PRIuN +#undef PRIxN +#define __PRIN_PREFIX "l" + +#define PRId64 __PRI64_PREFIX"d" +#define PRIo64 __PRI64_PREFIX"o" +#define PRIu64 __PRI64_PREFIX"u" +#define PRIx64 __PRI64_PREFIX"x" +#define PRIX64 __PRI64_PREFIX"X" +#define PRIdN __PRIN_PREFIX"d" +#define PRIoN __PRIN_PREFIX"o" +#define PRIuN __PRIN_PREFIX"u" +#define PRIxN __PRIN_PREFIX"x" + +#ifdef ___cplusplus +} +#endif + +#endif /* _IBA_PUBLIC_IDEBUG_OSD_H_ */ diff --git a/IbAccess/UserLinux/Public/idebuggrabber_osd.h b/IbAccess/UserLinux/Public/idebuggrabber_osd.h new file mode 100644 index 0000000..d9d5533 --- /dev/null +++ b/IbAccess/UserLinux/Public/idebuggrabber_osd.h @@ -0,0 +1,63 @@ +/* BEGIN_ICS_COPYRIGHT3 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT3 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + + +#ifndef _IBA_PUBLIC_IDEBUG_GRABBER_OSD_H_ +#define _IBA_PUBLIC_IDEBUG_GRABBER_OSD_H_ + +#include +#include +#include "iba/public/datatypes.h" +#include "iba/public/idebug.h" + +#ifdef __cplusplus +extern "C" { +#endif + +static _inline void +DebugGrabberRunScript(char * GrabberScript) +{ + int ret; + + ret = system(GrabberScript); + if (ret < 0) + MsgOut("DebugGrab via %s failed: ret=%d, errno=%d\n", GrabberScript, ret, errno); + else if (! WIFEXITED(ret)) + MsgOut("DebugGrab via %s failed: wait ret=0x%x\n", GrabberScript, ret); + else if (WEXITSTATUS(ret)) + MsgOut("DebugGrab via %s failed: ret=%d\n", GrabberScript, WEXITSTATUS(ret)); +} + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* _IBA_PUBLIC_IDEBUG_GRABBER_OSD_H_ */ diff --git a/IbAccess/UserLinux/Public/ievent.c b/IbAccess/UserLinux/Public/ievent.c new file mode 100644 index 0000000..cda11f5 --- /dev/null +++ b/IbAccess/UserLinux/Public/ievent.c @@ -0,0 +1,204 @@ +/* BEGIN_ICS_COPYRIGHT5 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT5 ****************************************/ + + +#include "datatypes.h" +#include "ievent.h" +#include "idebug.h" +//----------------------------------------------------------- +// Internal functions needed for events +//----------------------------------------------------------- + + +//----------------------------------------------------------- +// Declare that we intended to create an event +//----------------------------------------------------------- +void +EventInitState (IN EVENT *pEvent) +{ + pEvent->ev_state = Constructed; +} + +//----------------------------------------------------------- +// Initialize an event +//----------------------------------------------------------- +boolean +EventInit( IN EVENT *pEvent ) +{ + pthread_cond_init(&pEvent->ev_condvar,NULL); + pthread_mutex_init( &pEvent->ev_mutex, NULL ); + pEvent->ev_signaled = FALSE; + pEvent->ev_state = Started; + return TRUE; +} + +//----------------------------------------------------------- +// Destroy an event +//----------------------------------------------------------- +void +EventDestroy( IN EVENT *pEvent ) +{ + // Destroy only if the event was constructed + if (pEvent->ev_state == Started) + { + pthread_cond_destroy( &pEvent->ev_condvar ); + pthread_mutex_destroy( &pEvent->ev_mutex ); + pEvent->ev_signaled = FALSE; + pEvent->ev_state = Destroyed; + } +} + +//----------------------------------------------------------- +// Trigger or Signal an event +//----------------------------------------------------------- +void +EventTrigger( IN EVENT *pEvent ) +{ + + // Make sure that the event was Started + ASSERT (pEvent->ev_state == Started); + + pthread_mutex_lock( &pEvent->ev_mutex ); + + pEvent->ev_signaled = TRUE; + pthread_cond_signal(&pEvent->ev_condvar ); + + pthread_mutex_unlock( &pEvent->ev_mutex ); +} + +//----------------------------------------------------------- +// Wakes all waiters intest of just one. +//----------------------------------------------------------- +void +EventBroadcast( IN EVENT *pEvent ) +{ + + // Make sure that the event was Started + ASSERT (pEvent->ev_state == Started); + + pthread_mutex_lock( &pEvent->ev_mutex ); + + pEvent->ev_signaled = TRUE; + pthread_cond_broadcast(&pEvent->ev_condvar ); + + pthread_mutex_unlock( &pEvent->ev_mutex ); +} + +//----------------------------------------------------------- +// Clear an event, as though it was never triggered +//----------------------------------------------------------- +void +EventClear( IN EVENT *pEvent ) +{ + + // Make sure that the event was Started + ASSERT (pEvent->ev_state == Started); + + pthread_mutex_lock( &pEvent->ev_mutex ); + + pEvent->ev_signaled = FALSE; + + pthread_mutex_unlock( &pEvent->ev_mutex ); +} + + +//----------------------------------------------------------- +// Wait for an event - this event is NOT interruptible +//----------------------------------------------------------- +FSTATUS +EventWaitOn( IN EVENT *pEvent, IN int32 wait_micro) +{ + // Make sure that the event was started + ASSERT (pEvent->ev_state == Started); + + // + // Don't wait if the it has been signaled already! + // + pthread_mutex_lock( &pEvent->ev_mutex ); + if (pEvent->ev_signaled == TRUE) + { + // autoclear + pEvent->ev_signaled = FALSE; + + pthread_mutex_unlock( &pEvent->ev_mutex); + return FSUCCESS; + } + + if (wait_micro == EVENT_NO_TIMEOUT) + { + wait_micro = 0; + // Wait for condition variable ev_condvar to be signaled or broadcast. + // Also need to implement interruptible/Non interruptible waits!! + pthread_cond_wait(&pEvent->ev_condvar,&pEvent->ev_mutex); + + pEvent->ev_signaled = FALSE; + pthread_mutex_unlock( &pEvent->ev_mutex ); + return FSUCCESS; + } + else + { + FSTATUS status = FERROR; + int retval; + + // Get the current time + if (gettimeofday(&pEvent->ev_curtime, NULL) == 0) + { + (pEvent->ev_timeout).tv_sec = (pEvent->ev_curtime).tv_sec + (wait_micro/1000000); + (pEvent->ev_timeout).tv_nsec = ((pEvent->ev_curtime).tv_usec + (wait_micro % 1000000)) * 1000; + // handle carry from nsec to sec + if ((pEvent->ev_timeout).tv_nsec > 1000000000) { + (pEvent->ev_timeout).tv_sec++; + (pEvent->ev_timeout).tv_nsec -= 1000000000; + } + + retval = pthread_cond_timedwait(&pEvent->ev_condvar, &pEvent->ev_mutex, &pEvent->ev_timeout); + if (retval == ETIMEDOUT) + { + status = FTIMEOUT; + } + else + { + // We got signalled + status = FSUCCESS; + } + } + pEvent->ev_signaled = FALSE; + pthread_mutex_unlock( &pEvent->ev_mutex ); + return status; + } +} + +//----------------------------------------------------------- +// Wait for an event - this event is interruptible +//----------------------------------------------------------- +FSTATUS +EventWaitOnInterruptible( IN EVENT *pEvent, IN int32 wait_micro) +{ + return EventWaitOn(pEvent, wait_micro); +} diff --git a/IbAccess/UserLinux/Public/ievent_osd.h b/IbAccess/UserLinux/Public/ievent_osd.h new file mode 100644 index 0000000..3c2e8b1 --- /dev/null +++ b/IbAccess/UserLinux/Public/ievent_osd.h @@ -0,0 +1,65 @@ +/* BEGIN_ICS_COPYRIGHT2 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT2 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + + +#ifndef _IBA_PUBLIC_IEVENT_OSD_H_ +#define _IBA_PUBLIC_IEVENT_OSD_H_ + +#include "iba/public/datatypes.h" +#include "iba/public/ispinlock.h" +#include /* usr/include */ +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/*-------------------------------------------------------- + * OS Specific data structure used by the event object. + * Users should not access these variables directly. + *-------------------------------------------------------- */ + +typedef struct _EVENT +{ + boolean ev_signaled; + pthread_mutex_t ev_mutex; + pthread_cond_t ev_condvar; + ObjectState ev_state; + struct timeval ev_curtime; + struct timespec ev_timeout; +} EVENT; + +#ifdef __cplusplus +}; +#endif + +#endif /* _IBA_PUBLIC_IEVENT_OSD_H_ */ diff --git a/IbAccess/UserLinux/Public/imemory_osd.c b/IbAccess/UserLinux/Public/imemory_osd.c new file mode 100644 index 0000000..c62eff5 --- /dev/null +++ b/IbAccess/UserLinux/Public/imemory_osd.c @@ -0,0 +1,746 @@ +/* BEGIN_ICS_COPYRIGHT5 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT5 ****************************************/ + +#include "datatypes.h" +#include "imemory.h" +#include "imath.h" +#include "idebug.h" +#include "iquickmap.h" +#include "ispinlock.h" +#include "errno.h" +#include "string.h" +#include + +#ifdef IB_STACK_IBACCESS +static uint32 s_lock_strategy = 0xffffffff; + +/* + * Certain redhat kernels use these defines without providing them. + * This allows us to support these features with such kernels. + * + * Note that this has no impact on kernels that really don't support + * this feature. + */ +#if !defined(MADV_DONTFORK) +#define MADV_DONTFORK 10 +#endif +#if !defined(MADV_DOFORK) +#define MADV_DOFORK 11 +#endif + +static FSTATUS +MemoryLockPrepareMlock(uintn start, uintn length); +static FSTATUS +MemoryLockUnprepareMlock(uintn start, uintn length); + +#endif /* IB_STACK_IBACCESS */ + +void* +MemoryAllocatePriv( IN uint32 Bytes, IN uint32 flags, IN uint32 Tag ) +{ + return malloc( Bytes ); +} + +void +MemoryDeallocatePriv( IN void *pMemory ) +{ + free( pMemory ); +} + +void +MemoryFill( IN void *pMemory, IN uchar Fill, IN uint32 Bytes ) +{ + memset( pMemory, Fill, Bytes ); +} + +void* +MemoryCopy( IN void *pDest, IN const void *pSrc, IN uint32 Bytes ) +{ + return memcpy( pDest, pSrc, Bytes ); +} + +int32 +MemoryCompare( IN const void *pMemory1, IN const void *pMemory2, IN uint32 Bytes ) +{ + return memcmp( pMemory1, pMemory2, Bytes ); +} + +#ifdef IB_STACK_IBACCESS +FSTATUS MemoryLockPrepare(uintn buf_org, uintn Length) +{ + uintn buf_aligned = 0; + uintn size = Length; + uint32 page_size = getpagesize(); + uintn tos_aligned; + + buf_aligned = ROUNDDOWNP2(buf_org, page_size); + size = size + buf_org - buf_aligned; + size = ROUNDUPP2(size, page_size); + // This is an odd case, if buf_aligned is on the stack, we need to make sure + // the stack itself is at least 1 page beyond the buf itself + // we use &tos_aligned as an rough indication of top of stack + // if we didn't do this, the VMA created by madvise could actually grow + // after we locked the memory, which would confuse the memory locking code + + // for stacks which grow down: + tos_aligned = ROUNDDOWNP2(&tos_aligned, page_size); + if (tos_aligned == buf_aligned) + { + // force stack to grow by 1 page so TOS is on a different page than buf + volatile uint8 *temp = (uint8*)alloca(page_size); + if (temp == NULL) + return FINSUFFICIENT_MEMORY; + *temp = 1; // touch new page so stack grows + } +#if 0 + // for stacks which grow up: + tos_aligned = ROUNDUPP2(&tos_aligned, page_size); + if ( buf_aligned + size == tos_aligned) + { + // force stack to grow by 1 page so TOS is on a different page than buf + volatile uint8 *temp = (uint8*)alloca(page_size); + if (temp == NULL) + return FINSUFFICIENT_MEMORY;; + *(temp+page_size) = 1; // touch new page so stack grows + } +#endif + + switch (s_lock_strategy) { + case MEMORY_LOCK_STRAT_MADVISE: +#if MLOCK_DBG > 1 + MsgOut("%s: madvise addr:0x%"PRIxN" size:0x%"PRIxN"\n",__func__,buf_aligned,size); +#endif + if(madvise((void *)buf_aligned, (size_t)size, MADV_SEQUENTIAL )) + { + MsgOut("%s: madvise failed with buf:0x%"PRIxN" size:%"PRIdN"\n",__func__,buf_aligned,size); + return FINSUFFICIENT_RESOURCES;; + } + break; + + case MEMORY_LOCK_STRAT_MLOCK: + return MemoryLockPrepareMlock(buf_aligned, size); + break; + + default: + /* strategy not supported or MemoryLockSetStrategy not called first */ + return FINVALID_OPERATION; + } + return FSUCCESS; +} + +FSTATUS MemoryLockUnprepare(uintn buf_org, uintn Length) +{ + switch (s_lock_strategy) { + case MEMORY_LOCK_STRAT_MADVISE: + /* no action needed */ + return FSUCCESS; + break; + + case MEMORY_LOCK_STRAT_MLOCK: + { + uint32 page_size = getpagesize(); + uintn buf_aligned = ROUNDDOWNP2(buf_org,page_size); + uintn size = Length + buf_org - buf_aligned; + size = ROUNDUPP2(size, page_size); + return MemoryLockUnprepareMlock(buf_aligned, size); + break; + } + + default: + /* strategy not supported or MemoryLockSetStrategy not called first */ + return FINVALID_OPERATION; + } +} + +/* This provides to the User Memory module the memory lock strategy which Uvca + * obtained via Vka from the kernel Memory module + */ +FSTATUS MemorySetLockStrategy(uint32 strategy) +{ + switch (strategy) { + case MEMORY_LOCK_STRAT_MADVISE: + s_lock_strategy = strategy; + return FSUCCESS; + break; + + case MEMORY_LOCK_STRAT_MLOCK: + s_lock_strategy = strategy; + return FSUCCESS; + break; + + default: + return FINVALID_PARAMETER; + break; + } +} + +/* Tell UVca if MemoryLockUnprepare is necessary for the configured locking + * strategy. If not, UVCA has the option of optimizing its operation to + * avoid the MemoryLockUnprepare. + * However, if unnecessary, MemoryLockUnprepare should be a noop and should + * not fail (hence allowing UVCA to choose not to optimize it out). + */ +boolean MemoryNeedLockUnprepare(void) +{ + switch (s_lock_strategy) { + case MEMORY_LOCK_STRAT_MADVISE: + return FALSE; + break; + case MEMORY_LOCK_STRAT_MLOCK: + return TRUE; + break; + default: /* unexpected case, play it safe */ + return TRUE; + break; + } +} + + +/* ********************************************************************** */ +/* This implements the MEMORY_LOCK_STRAT_MLOCK core functionality + * in this strategy the user space uses mlock and madvise prior to + * the kernel MemoryLock being called. Since mlock and madvise do not "stack" + * we must track the presently locked regions and only call mlock/madvise for + * the "delta" caused by the given lock/unlock of memory. + * note that MemoryLockPrepare is called before MemoryLock + * and MemoryLockUnprepare is called after MemoryUnlock + * + * This implementation of MemoryLockPrepare/MemoryLockUnprepare "stacks" + * This assumes every MemoryLockUnprepare exactly matches a previous + * call to MemoryLockPrepare. It will assert otherwise. + * UVCA follows this requirement. + */ + +#define MLOCK_TAG MAKE_MEM_TAG(k,c,l,m) + +/* initial testing indicates most applications have relatively few + * locked areas at a time, hence the cost of compressing then uncompressing + * them (on unlock) is more expensive that having more areas to track and store + * especially since the locked_area structure is relatively small and a + * cl_qmap is used to search them + */ +#define COMPRESS_AREAS 0 /* conserve memory by merging areas when possible */ + +typedef struct _locked_area { + cl_map_item_t MapItem; + uintn start; // virtual address + uintn end; // last address included in area + uint32 lock_cnt;// number of times locked +} LOCKED_AREA; + +typedef struct _addr_range { + uintn start; // virtual address + uintn end; // last address included in range +} ADDR_RANGE; + +static cl_qmap_t LockedArea_Map; +static SPIN_LOCK LockedAreaMap_Lock; +#if MLOCK_DBG +static unsigned s_num_locks = 0; /* count of MemoryLockPrepare calls */ +static unsigned s_num_split = 0; /* count of LOCKED_AREAs split */ +static unsigned s_num_merge = 0; /* count of LOCKED_AREAs merged */ +static unsigned s_max_areas = 0; /* maximum number of areas */ +#endif + +#if MLOCK_DBG +/* dump all the locked areas, must be called with LockedAreaMap_Lock held */ +static void LockedAreaDump(void) +{ + cl_map_item_t *pMapItem; + + MsgOut(" start end cnt\n"); + for (pMapItem = cl_qmap_head(&LockedArea_Map); + pMapItem != cl_qmap_end(&LockedArea_Map); + pMapItem = cl_qmap_next(pMapItem)) + { + LOCKED_AREA *pArea = PARENT_STRUCT(pMapItem, LOCKED_AREA, MapItem); + + MsgOut("0x%16.16"PRIxN" 0x%16.16"PRIxN" %10u\n", pArea->start, pArea->end, pArea->lock_cnt); + } +} +#endif + +/* compare start addresses of 2 entries in map + * used as primary sort for LockedArea_Map. The map should not have any + * overlapping areas, hence sort by start address is sufficient + * Return: + * -1: key1 < key 2 + * 0: key1 = key 2 + * 1: key1 > key 2 + */ +static int LockedAreaCompare(uint64 key1, uint64 key2) +{ + LOCKED_AREA *pArea1 = (LOCKED_AREA*)(uintn)key1; + LOCKED_AREA *pArea2 = (LOCKED_AREA*)(uintn)key2; + + if (pArea1->start < pArea2->start) + return -1; + else if (pArea1->start == pArea2->start) + return 0; + else + return 1; +} + +/* compare address range in key2 against address range in key1 + * key1 is a LOCKED_AREA*, key2 is a ADDR_RANGE* + * Return: + * -1: key1 < key 2 (eg. key 2 is above range of key 1) + * 0: key1 = key 2 (eg. key 2 overlaps with range of key 1) + * 1: key1 > key 2 (eg. key 2 is below range of key 1) + * Note that more than 1 range in the LockedArea_Map could overlap + * a given value for key2 + */ +static int LockedAreaRangeCompare(uint64 key1, uint64 key2) +{ + LOCKED_AREA *pArea1 = (LOCKED_AREA*)(uintn)key1; + ADDR_RANGE *pRange2 = (ADDR_RANGE*)(uintn)key2; + + if (pArea1->start > pRange2->end) + return 1; + else if (pArea1->end < pRange2->start) + return -1; + else + return 0; +} + +/* convert a pMapItem into a pArea, returns NULL if "end marker" */ +static LOCKED_AREA *LockedAreaFromMapItem(cl_map_item_t *pMapItem) +{ + if (pMapItem != cl_qmap_end(&LockedArea_Map)) { + return PARENT_STRUCT(pMapItem, LOCKED_AREA, MapItem); + } else { + return NULL; + } +} + +/* next area after pArea, returns NULL if no areas after pArea */ +static _inline LOCKED_AREA *LockedAreaNext(LOCKED_AREA *pArea) +{ + return (LockedAreaFromMapItem(cl_qmap_next(&pArea->MapItem))); +} + +/* prev area before pArea, returns NULL if no areas before pArea */ +static _inline LOCKED_AREA *LockedAreaPrev(LOCKED_AREA *pArea) +{ + return (LockedAreaFromMapItem(cl_qmap_prev(&pArea->MapItem))); +} + +/* must call with Map locked + * merges pArea1 and pArea2 (which must be adjacent areas) + * returns resulting merged area (Area2 is freed) + * cannot fail + */ +static LOCKED_AREA *LockedAreaMerge(LOCKED_AREA *pArea1, LOCKED_AREA *pArea2) +{ + ASSERT(pArea1->end+1 == pArea2->start); + ASSERT(pArea1->lock_cnt == pArea2->lock_cnt); + pArea1->end = pArea2->end; + cl_qmap_remove_item(&LockedArea_Map, &pArea2->MapItem); +#if MLOCK_DBG + s_num_merge++; +#endif + return pArea1; +} + +/* create a new LOCKED_AREA and insert it into LockedArea_Map + * returns NULL on memory allocation errors, otherwise pointer to new area + */ +static LOCKED_AREA *LockedAreaAlloc(uintn start, uintn end, uint32 lock_cnt) +{ + LOCKED_AREA *pNewArea; + cl_map_item_t *pMapItem; + + pNewArea = (LOCKED_AREA*)MemoryAllocate2( + sizeof(LOCKED_AREA), IBA_MEM_FLAG_NONE, MLOCK_TAG); + if (! pNewArea) + return NULL; + pNewArea->start = start; + pNewArea->end = end; + pNewArea->lock_cnt = lock_cnt; + pMapItem = cl_qmap_insert(&LockedArea_Map, (uintn)pNewArea, &pNewArea->MapItem); + // assert new area is unique + ASSERT(pMapItem == &pNewArea->MapItem); +#if MLOCK_DBG + if (cl_qmap_count(&LockedArea_Map) > s_max_areas) + s_max_areas = cl_qmap_count(&LockedArea_Map); +#endif + return pNewArea; +} + +/* must call with Map locked + * splits pArea into 2 areas at addr + * 1st area will be pArea->start to addr-1 + * 2nd area will be addr to pArea->end + * returns 2nd area (pArea becomes 1st area) + * returns NULL on failure to allocate memory + */ +static LOCKED_AREA *LockedAreaSplit(LOCKED_AREA *pArea, uintn addr) +{ + LOCKED_AREA *pNewArea; + cl_map_item_t *pMapItem; + + ASSERT(pArea->start < addr); + ASSERT(pArea->end >= addr); + pNewArea = (LOCKED_AREA*)MemoryAllocate2( + sizeof(LOCKED_AREA), IBA_MEM_FLAG_NONE, MLOCK_TAG); + if (! pNewArea) + return NULL; + pNewArea->start = addr; + pNewArea->end = pArea->end; + pNewArea->lock_cnt = pArea->lock_cnt; + pArea->end = addr-1; // must fixup before insert pNewArea + pMapItem = cl_qmap_insert(&LockedArea_Map, (uintn)pNewArea, &pNewArea->MapItem); + ASSERT(pMapItem == &pNewArea->MapItem); /* assert new area is unique */ +#if MLOCK_DBG + s_num_split++; + if (cl_qmap_count(&LockedArea_Map) > s_max_areas) + s_max_areas = cl_qmap_count(&LockedArea_Map); +#endif + return pNewArea; +} + +/* must call with Map locked + * find the 1st area in LockedArea_Map which overlaps start-end + * returns NULL if no overlapping area(s) + */ +static LOCKED_AREA *FindFirstOverlap(uintn start, uintn end) +{ + ADDR_RANGE Range; + cl_map_item_t *pMapItem; + LOCKED_AREA *pArea; + + Range.start = start; + Range.end = end; + + /* first find if any locked areas overlap the Range */ + pMapItem = cl_qmap_get_compare(&LockedArea_Map, (uint64)(uintn)&Range, LockedAreaRangeCompare); + if (pMapItem == cl_qmap_end(&LockedArea_Map)) { + /* no overlap with existing locks */ + return NULL; + } + pArea = PARENT_STRUCT(pMapItem, LOCKED_AREA, MapItem); + /* because RangeCompare is not unique, we could get any area which + * overlaps, so we must back up to find first area which overlaps + */ + while ((pMapItem = cl_qmap_prev(&pArea->MapItem)) != cl_qmap_end(&LockedArea_Map)) { + if (LockedAreaRangeCompare(cl_qmap_key(pMapItem), (uint64)(uintn)&Range) != 0) { + // no overlap, pArea is 1st to overlap Range + break; + } + pArea = PARENT_STRUCT(pMapItem, LOCKED_AREA, MapItem); + } + /* now pArea is 1st area to overlap Range */ + return pArea; +} + +/* account for the locking/unlocking of start-end in pArea + * as needed we could split pArea into up to 2 pieces + * the returned value is the area which overlaps desired start/end + * returns NULL on error + */ +static LOCKED_AREA *LockedAreaAddLock(LOCKED_AREA *pArea, uintn start, uintn end, uint32 add) +{ + LOCKED_AREA *p = NULL; + + if (pArea->start < start) { + ASSERT(pArea->end >= start); + p = pArea; // save for recovery + pArea = LockedAreaSplit(pArea, start); // 2nd half + if (! pArea) + return NULL; // failed + } + if (pArea->end > end) { + ASSERT(pArea->start <= end); + if (! LockedAreaSplit(pArea, end+1)) { + // error, undo split above + if (p) + (void)LockedAreaMerge(p, pArea); + return NULL; // failed + } + // pArea is still 1st half + } + pArea->lock_cnt += add; + return pArea; +} + +static _inline LOCKED_AREA *LockedAreaIncLock(LOCKED_AREA *pArea, uintn start, uintn end) +{ + return LockedAreaAddLock(pArea, start, end, 1); +} + +static _inline LOCKED_AREA *LockedAreaDecLock(LOCKED_AREA *pArea, uintn start, uintn end) +{ + return LockedAreaAddLock(pArea, start, end, (uint32)-1); +} + +/* create a new locked area covering start-end */ +static LOCKED_AREA *LockedAreaCreate(uintn start, uintn end) +{ + LOCKED_AREA *pArea; + uintn length = (end-start)+1; + +#if MLOCK_DBG > 1 + MsgOut("%s: mlock addr:0x%"PRIxN" size:0x%"PRIxN"\n",__func__,start,length); +#endif + if (mlock((void*)start, (size_t)length) < 0) { + MsgOut("mlock failed: start=0x%p, len=%u, errno=%s (%d)\n", + (void*)start, (unsigned)length, strerror(errno), errno); + return NULL; + } +#if MLOCK_DBG > 1 + MsgOut("%s: madvise DONTFORK addr:0x%"PRIxN" size:0x%"PRIxN"\n",__func__,start,length); +#endif + if (madvise((void*)start, (size_t)length, MADV_DONTFORK) < 0) { + MsgOut("madvise DONTFORK failed: start=0x%p, len=%u, errno=%s (%d)\n", + (void*)start, (unsigned)length, strerror(errno), errno); + (void)munlock((void*)start, (size_t)length); + return NULL; + } + pArea = LockedAreaAlloc(start, end, 1); + if (! pArea) { + (void)madvise((void*)start, (size_t)length, MADV_DOFORK); + (void)munlock((void*)start, (size_t)length); + } + return pArea; +} + +/* destroy a locked area */ +static void LockedAreaDestroy(LOCKED_AREA *pArea) +{ + uintn length = (pArea->end - pArea->start)+1; +#if MLOCK_DBG > 1 + MsgOut("%s: madvise DOFORK addr:0x%"PRIxN" size:0x%"PRIxN"\n",__func__,pArea->start,length); +#endif + (void)madvise((void*)pArea->start, (size_t)length, MADV_DOFORK); +#if MLOCK_DBG > 1 + MsgOut("%s: munlock addr:0x%"PRIxN" size:0x%"PRIxN"\n",__func__,pArea->start,length); +#endif + (void)munlock((void*)pArea->start, (size_t)length); + cl_qmap_remove_item(&LockedArea_Map, &pArea->MapItem); + MemoryDeallocate(pArea); +} + +#if COMPRESS_AREAS +/* merge Areas with same lock count. This saves space but + * may make for more work in unlock + */ +static void CompressAreas(LOCKED_AREA *pFirstArea, uintn end) +{ + LOCKED_AREA *pArea; + + ASSERT(pFirstArea); + /* start merge process with 1st area before this lock (if any) */ + pArea = LockedAreaPrev(pFirstArea); + if (pArea) + pFirstArea = pArea; + while (pFirstArea->start <= end) { + pArea = LockedAreaNext(pFirstArea); + if (! pArea) + break; + if (pArea->lock_cnt == pFirstArea->lock_cnt + && pFirstArea->end+1 == pArea->start) + pFirstArea = LockedAreaMerge(pFirstArea, pArea); + else + pFirstArea = pArea; + } +} +#endif /* COMPRESS_AREAS */ + + +/* heart of managing mlock/madvise locked areas. + * start and length must be pagesize aligned + */ +static FSTATUS +MemoryLockPrepareMlock(uintn start, uintn length) +{ + LOCKED_AREA *pArea; +#if COMPRESS_AREAS + LOCKED_AREA *pFirstArea; +#endif + uintn end = start + length-1; + uintn addr; + +#if MLOCK_DBG > 1 + MsgOut("%s: addr:0x%"PRIxN" size:0x%"PRIxN"\n",__func__,start,length); +#endif + if (! length) + return FSUCCESS; +// TBD - should we just mlock and madvise whole area 1st outside spin lock? +// however error unwind would be impossible if madvise failed? +// does kernel properly count mlock if done twice to same page? + SpinLockAcquire(&LockedAreaMap_Lock); +#if MLOCK_DBG + s_num_locks++; +#endif + pArea = FindFirstOverlap(start, end); +#if COMPRESS_AREAS + pFirstArea = NULL; +#endif + for (addr=start; addr<=end; ) { + if (! pArea) { + pArea = LockedAreaCreate(addr, end); + } else if (pArea->start > addr) { + // fill gap + pArea = LockedAreaCreate(addr, MIN(end, pArea->start-1)); + } else { + pArea = LockedAreaIncLock(pArea, addr, end); + } + if (! pArea) { + // error, unwind what we did so far + SpinLockRelease(&LockedAreaMap_Lock); +#if MLOCK_DBG + MsgOut("failure for MemoryLockPrepare(0x%"PRIxN", 0x%"PRIxN") for 0x%"PRIxN"-0x%"PRIxN"\n", start, length, addr, end); + LockedAreaDump(); + MsgOut("MemoryLockUnprepare(0x%"PRIxN", 0x%"PRIxN") for 0x%"PRIxN"-0x%"PRIxN"\n", start, length, addr, end); +#endif + if (addr != start) + (void)MemoryLockUnprepareMlock(start, addr-start); + return FINSUFFICIENT_RESOURCES; + } + // adjust to reflect what is left to do + addr = pArea->end+1; +#if COMPRESS_AREAS + if (! pFirstArea) + pFirstArea = pArea; +#endif + pArea = LockedAreaNext(pArea); + } +#if COMPRESS_AREAS + /* merge Areas with same lock count. This saves space but + * may make for more work in unlock + */ + ASSERT(pFirstArea); + CompressAreas(pFirstArea, end); +#endif +#if MLOCK_DBG > 1 + LockedAreaDump(); +#endif + SpinLockRelease(&LockedAreaMap_Lock); + return FSUCCESS; +} + +/* start and length must be pagesize aligned + */ +static FSTATUS +MemoryLockUnprepareMlock(uintn start, uintn length) +{ + LOCKED_AREA *pArea; + LOCKED_AREA *p; +#if COMPRESS_AREAS + LOCKED_AREA *pFirstArea; +#endif + uintn end = start + length-1; + uintn addr; + +#if MLOCK_DBG > 1 + MsgOut("%s: addr:0x%"PRIxN" size:0x%"PRIxN"\n",__func__,start,length); +#endif + if (! length) + return FSUCCESS; + SpinLockAcquire(&LockedAreaMap_Lock); + pArea = FindFirstOverlap(start, end); +#if COMPRESS_AREAS + pFirstArea = NULL; +#endif + for (addr=start; addr<=end; ) { + ASSERT(pArea); + ASSERT(pArea->start <= addr); + pArea = LockedAreaDecLock(pArea, addr, end); +#if COMPRESS_AREAS + if (! pArea) { + // stuck, can't really re-lock it, so leave it + // partially unlocked and give up + DbgOut("Unable to unlock: addr=0x%p, end=0x%p\n", + (void*)addr, (void*)end); + break; + } +#else + // since never merge, should be no need to split, so should not fail + ASSERT(pArea); +#endif + // adjust to reflect what is left to do + addr = pArea->end+1; + p = LockedAreaNext(pArea); + if (! pArea->lock_cnt) { + LockedAreaDestroy(pArea); +#if COMPRESS_AREAS + } else { + if (! pFirstArea) + pFirstArea = pArea; +#endif + } + pArea = p; + } +#if COMPRESS_AREAS + /* merge Areas with same lock count */ + if (pFirstArea) + CompressAreas(pFirstArea, end); +#endif +#if MLOCK_DBG > 1 + LockedAreaDump(); +#endif + SpinLockRelease(&LockedAreaMap_Lock); + return FSUCCESS; +} +/* end of MEMORY_LOCK_STRAT_MLOCK specific code */ +/* ********************************************************************** */ + + +FSTATUS +MemoryLockPrepareInit(void) +{ + + cl_qmap_init(&LockedArea_Map, LockedAreaCompare); + SpinLockInitState( &LockedAreaMap_Lock ); + + if ( !SpinLockInit ( &LockedAreaMap_Lock ) ) + { + MsgOut ("MemoryLockPrepareInit: Locked Area SpinLock init failed\n"); + return FERROR; + } + + + return FSUCCESS; +} + +void +MemoryLockPrepareCleanup(void) +{ + +#if MLOCK_DBG + MsgOut("MLock Stats: numLocks: %u, maxAreas: %u, numSplit: %u, numMerge: %u\n", + s_num_locks, s_max_areas, s_num_split, s_num_merge); +#endif + if (! cl_is_qmap_empty(&LockedArea_Map)) { + DbgOut("MemoryLockPrepareCleanup: Locked Area Map not empty\n"); + } + SpinLockDestroy( &LockedAreaMap_Lock ); + +} +#endif /* IB_STACK_IBACCESS */ diff --git a/IbAccess/UserLinux/Public/imemory_osd.h b/IbAccess/UserLinux/Public/imemory_osd.h new file mode 100644 index 0000000..973133d --- /dev/null +++ b/IbAccess/UserLinux/Public/imemory_osd.h @@ -0,0 +1,79 @@ +/* BEGIN_ICS_COPYRIGHT2 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT2 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +#ifndef _IBA_PUBLIC_IMEMORY_OSD_H_ +#define _IBA_PUBLIC_IMEMORY_OSD_H_ + +#include "iba/public/datatypes.h" +#include +#include +#include + +#define MEM_TRACK_NO_FTR + +/* + * OS Defined PAGE_SIZE. + */ +#define MemoryGetOsPageSize() getpagesize() + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef IB_STACK_IBACCESS +FSTATUS MemoryLockPrepare(uintn buf_org, uintn Length); +FSTATUS MemoryLockUnprepare(uintn buf_org, uintn Length); + +/* This provides to the User Memory module the memory lock strategy which Uvca + * obtained via Vka from the kernel Memory module + */ +FSTATUS MemorySetLockStrategy(uint32 strategy); + +/* Tell UVca is MemoryLockUnprepare is necessary for the configured locking + * strategy. If not, UVCA has the option of optimizing its operation to + * avoid the MemoryLockUnprepare. + * However, if unnecessary, MemoryLockUnprepare should be a noop and should + * not fail (hence allowing UVCA to choose not to optimize it out). + */ +boolean MemoryNeedLockUnprepare(void); + +/* Initialization routines which libibt will call to initialize user space + * memory locking component + */ +FSTATUS MemoryLockPrepareInit(void); +void MemoryLockPrepareCleanup(void); +#endif /* IB_STACK_IBACCESS */ + +#ifdef __cplusplus +}; +#endif + +#endif /* _IBA_PUBLIC_IMEMORY_OSD_H_ */ diff --git a/IbAccess/UserLinux/Public/imutex_osd.h b/IbAccess/UserLinux/Public/imutex_osd.h new file mode 100644 index 0000000..0e83f3b --- /dev/null +++ b/IbAccess/UserLinux/Public/imutex_osd.h @@ -0,0 +1,178 @@ +/* BEGIN_ICS_COPYRIGHT3 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT3 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +#ifndef _IBA_PUBLIC_IMUTEX_OSD_H_ +#define _IBA_PUBLIC_IMUTEX_OSD_H_ + +#include "iba/public/datatypes.h" +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef pthread_mutex_t MUTEX; + +/**************************************************************************** + * MutexInitState + * + * Description: + * Initializes the state of a mutex. + * + * Inputs: + * pMutex - Pointer to a mutex object. + * + * Outputs: + * None + * + * Returns: + * None + * + ****************************************************************************/ +static _inline void +MutexInitState( + IN MUTEX* const pMutex ) +{ + /* **************************************************** */ + /* ************ DO NOTHING FOR NOW !!! *************** */ + /* **************************************************** */ +} + + +/**************************************************************************** + * MutexInit + * + * Description: + * Initializes the mutex. This function performs all initialization. + * + * Inputs: + * pMutex - Pointer to a mutex object + * + * Outputs: + * None + * + * Returns: + * FSUCCESS + * FERROR - Initialization failed. + * + ****************************************************************************/ +static _inline FSTATUS +MutexInit( + IN MUTEX* const pMutex) +{ + DEBUG_ASSERT(pMutex); + + /* Initialize with pthread_mutexattr_t = NULL */ + pthread_mutex_init(pMutex,NULL); + return FSUCCESS; +} + + +/**************************************************************************** + * MutexDestroy + * + * Description: + * Destroys the mutex. + * + * Inputs: + * pMutex - Pointer to a mutex object + * + * Outputs: + * None + * + * Returns: + * None + * + ****************************************************************************/ +static _inline void +MutexDestroy( + IN MUTEX* const pMutex ) +{ + DEBUG_ASSERT(pMutex); + pthread_mutex_destroy(pMutex); +} + + +/**************************************************************************** + * MutexAcquire + * + * Description: + * Acquires a mutex. This call blocks if the mutex cannot be + * acquired immediately. + * + * Inputs: + * pMutex - Pointer to a mutex object + * + * Outputs: + * None + * + * Returns: + * None + * + ****************************************************************************/ +static _inline void +MutexAcquire( + IN MUTEX* const pMutex) +{ + ASSERT(pMutex); + pthread_mutex_lock(pMutex); +} + + +/**************************************************************************** + * MutexRelease + * + * Description: + * Releases a mutex. This will free one blocking waiter, if any. + * + * Inputs: + * pMutex - Pointer to a mutex object + * + * Outputs: + * None + * + * Returns: + * None + * + ****************************************************************************/ +static _inline void +MutexRelease( + IN MUTEX* const pMutex ) +{ + ASSERT(pMutex); + pthread_mutex_unlock(pMutex); +} + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* _IBA_PUBLIC_IMUTEX_OSD_H_ */ diff --git a/IbAccess/UserLinux/Public/ipackoff.h b/IbAccess/UserLinux/Public/ipackoff.h new file mode 100644 index 0000000..57b3503 --- /dev/null +++ b/IbAccess/UserLinux/Public/ipackoff.h @@ -0,0 +1,34 @@ +/* BEGIN_ICS_COPYRIGHT2 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT2 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +#ifdef PACK_SUFFIX +#undef PACK_SUFFIX +#endif diff --git a/IbAccess/UserLinux/Public/ipackon.h b/IbAccess/UserLinux/Public/ipackon.h new file mode 100644 index 0000000..866cda9 --- /dev/null +++ b/IbAccess/UserLinux/Public/ipackon.h @@ -0,0 +1,34 @@ +/* BEGIN_ICS_COPYRIGHT2 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT2 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +#ifndef PACK_SUFFIX +#define PACK_SUFFIX __attribute__((packed)) +#endif diff --git a/IbAccess/UserLinux/Public/isemaphore.c b/IbAccess/UserLinux/Public/isemaphore.c new file mode 100644 index 0000000..51dc1bd --- /dev/null +++ b/IbAccess/UserLinux/Public/isemaphore.c @@ -0,0 +1,97 @@ +/* BEGIN_ICS_COPYRIGHT4 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT4 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +#include "iba/public/isemaphore.h" +#include "iba/public/ithread.h" +#include "semaphore.h" +#include "errno.h" + +/////////////////////////////////////////////////////////////////////////////// +// SemaAcquire +// +// Description: +// Acquires a semaphore. This call blocks for the specified interval if the +// semaphore cannot be acquired immediately. A wait of SEMA_NO_TIMEOUT +// will never timeout. +// +// Inputs: +// pSema - Pointer to a semaphore object +// wait_us - Time, in microseconds, to wait for the semaphore. +// +// Outputs: +// None +// +// Returns: +// FSUCCESS - The samphore was successfully acquired. +// FTIMEOUT - The operation timed out. +// +/////////////////////////////////////////////////////////////////////////////// +FSTATUS +SemaAcquire( + IN SEMAPHORE* const pSema, + IN const int32 wait_us ) +{ + FSTATUS Status; + + ASSERT( pSema ); + + if( wait_us == SEMA_NO_TIMEOUT ) + { + if ( 0 == sem_wait ( pSema )) + Status = FSUCCESS; + else + Status = FERROR; + } else if (wait_us == 0) { + if (0 == sem_trywait(pSema)) + Status = FSUCCESS; + else if (errno == EAGAIN) + Status = FTIMEOUT; + else + Status = FERROR; + } else { + // user space semaphores don't have a timeout on wait + uint32 ms = (wait_us+999)/1000; + Status = FTIMEOUT; + do + { + if (0 == sem_trywait( pSema )) + { + Status = FSUCCESS; + break; + } else if (errno != EAGAIN) { + Status = FERROR; + break; + } + ThreadSuspend(1); + } while (ms--); + } + return Status; +} diff --git a/IbAccess/UserLinux/Public/isemaphore_osd.h b/IbAccess/UserLinux/Public/isemaphore_osd.h new file mode 100644 index 0000000..daed0ca --- /dev/null +++ b/IbAccess/UserLinux/Public/isemaphore_osd.h @@ -0,0 +1,181 @@ +/* BEGIN_ICS_COPYRIGHT3 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT3 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +#ifndef _IBA_PUBLIC_ISEMAPHORE_OSD_H_ +#define _IBA_PUBLIC_ISEMAPHORE_OSD_H_ + +#include "iba/public/datatypes.h" +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef sem_t SEMAPHORE; + + +/**************************************************************************** + * SemaInitState + * + * Description: + * Initializes the state of a semaphore. + * + * Inputs: + * pSema - Pointer to a semaphore object. + * + * Outputs: + * None + * + * Returns: + * None + * + ****************************************************************************/ +static __inline void +SemaInitState( + IN SEMAPHORE* const pSema ) +{ + /* No-op. */ +} + + +/**************************************************************************** + * SemaInit + * + * Description: + * Initializes the semaphore. This function performs all initialization. + * + * Inputs: + * pSema - Pointer to a semaphore object + * MaxCount - Maximum number of wait operations that the semaphore can + * satisfy before blocking callers. + * + * Outputs: + * None + * + * Returns: + * FSUCCESS + * FERROR - Initialization failed. + * + ****************************************************************************/ +static __inline FSTATUS +SemaInit( + IN SEMAPHORE* const pSema, + IN const int32 MaxCount ) +{ + ASSERT( pSema ); + ASSERT( MaxCount ); + + if (-1 == sem_init( pSema, 0, MaxCount )) + return FERROR; + else + return FSUCCESS; +} + + +/**************************************************************************** + * SemaDestroy + * + * Description: + * Destroys the semaphore. + * + * Inputs: + * pSema - Pointer to a semaphore object + * + * Outputs: + * None + * + * Returns: + * None + * + ****************************************************************************/ +static __inline void +SemaDestroy( + IN SEMAPHORE* const pSema ) +{ + ASSERT( pSema ); + sem_destroy(pSema); +} + + +/**************************************************************************** + * SemaAcquire + * + * Description: + * Acquires a semaphore. This call blocks for the specified interval if the + * semaphore cannot be acquired immediately. A wait of SEMA_NO_TIMEOUT + * will never timeout. + * + * Inputs: + * pSema - Pointer to a semaphore object + * wait_us - Time, in microseconds, to wait for the semaphore. + * + * Outputs: + * None + * + * Returns: + * FSUCCESS - The samphore was successfully acquired. + * FTIMEOUT - The operation timed out. + * + ****************************************************************************/ +FSTATUS +SemaAcquire( + IN SEMAPHORE* const pSema, + IN const int32 wait_us ); + +/**************************************************************************** + * SemaRelease + * + * Description: + * Releases a semaphore. This will free one blocking waiter, if any. + * + * Inputs: + * pSema - Pointer to a semaphore object + * + * Outputs: + * None + * + * Returns: + * None + * + ****************************************************************************/ +static __inline void +SemaRelease( + IN SEMAPHORE* const pSema ) +{ + sem_post(pSema); +} + + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* _IBA_PUBLIC_ISEMAPHORE_OSD_H_ */ diff --git a/IbAccess/UserLinux/Public/ispinlock.c b/IbAccess/UserLinux/Public/ispinlock.c new file mode 100644 index 0000000..6fa7a2c --- /dev/null +++ b/IbAccess/UserLinux/Public/ispinlock.c @@ -0,0 +1,229 @@ +/* BEGIN_ICS_COPYRIGHT5 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT5 ****************************************/ + +#include "datatypes.h" +#include "ispinlock.h" // Common/Public/ + +//------------------------------------------------------------- +// Initialize a spinlock before its use. +//------------------------------------------------------------- +void +SpinLockInitState( IN SPIN_LOCK *pSpinLock ) +{ + // **************************************************** + // ************ DO NOTHING FOR NOW !!! *************** + // **************************************************** +} + +//------------------------------------------------------------- +// Initialize a spin lock +//------------------------------------------------------------- +boolean +SpinLockInit( SPIN_LOCK *pSpinLock ) +{ + ASSERT(pSpinLock); + + // Initialize with pthread_mutexattr_t = NULL + + pthread_mutex_init(&pSpinLock->sp_lock,NULL); + return TRUE; +} + +//------------------------------------------------------------- +// Destroy a spin lock +//------------------------------------------------------------- +void +SpinLockDestroy( SPIN_LOCK *pSpinLock ) +{ + ASSERT(pSpinLock); + pthread_mutex_destroy(&pSpinLock->sp_lock); +} + +//------------------------------------------------------------- +// Acquire a spin lock +//------------------------------------------------------------- +void +SpinLockAcquire( SPIN_LOCK *pSpinLock ) +{ + ASSERT(pSpinLock); + pthread_mutex_lock(&pSpinLock->sp_lock); +} + + +//------------------------------------------------------------- +// Acquire a spin lock with less overhead +//------------------------------------------------------------- +void +SpinLockFastAcquire( SPIN_LOCK *pSpinLock ) +{ + SpinLockAcquire( pSpinLock ); // For Now +} + + +//------------------------------------------------------------- +// Release a spin lock +//------------------------------------------------------------- +void +SpinLockRelease( SPIN_LOCK *pSpinLock ) +{ + ASSERT(pSpinLock); + pthread_mutex_unlock(&pSpinLock->sp_lock); +} + + +//------------------------------------------------------------- +// Release a spin lock with less overhead +//------------------------------------------------------------- +void +SpinLockFastRelease( SPIN_LOCK *pSpinLock ) +{ + SpinLockRelease( pSpinLock ); // For Now +} + +//------------------------------------------------------------- +// Initialize a spinrwlock before its use. +//------------------------------------------------------------- +void +SpinRwLockInitState( IN SPIN_RW_LOCK *pSpinRwLock ) +{ + // **************************************************** + // ************ DO NOTHING FOR NOW !!! *************** + // **************************************************** +} + +//------------------------------------------------------------- +// Initialize a spin rw lock +//------------------------------------------------------------- +boolean +SpinRwLockInit( SPIN_RW_LOCK *pSpinRwLock ) +{ + ASSERT(pSpinRwLock); + + // Initialize with pthread_mutexattr_t = NULL + +#if 0 + pthread_rwlock_init(&pSpinRwLock->rw_lock,NULL); +#else + pthread_mutex_init(&pSpinRwLock->rw_lock,NULL); +#endif + return TRUE; +} + +//------------------------------------------------------------- +// Destroy a spin rw lock +//------------------------------------------------------------- +void +SpinRwLockDestroy( SPIN_RW_LOCK *pSpinRwLock ) +{ + ASSERT(pSpinRwLock); +#if 0 + pthread_rwlock_destroy(&pSpinRwLock->rw_lock); +#else + pthread_mutex_destroy(&pSpinRwLock->rw_lock); +#endif +} + +//------------------------------------------------------------- +// Acquire a spin rw lock +//------------------------------------------------------------- +void +SpinRwLockAcquireRead( SPIN_RW_LOCK *pSpinRwLock ) +{ + ASSERT(pSpinRwLock); +#if 0 + pthread_rwlock_rdlock(&pSpinRwLock->rw_lock); +#else + pthread_mutex_lock(&pSpinRwLock->rw_lock); +#endif +} +void +SpinRwLockAcquireWrite( SPIN_RW_LOCK *pSpinRwLock ) +{ + ASSERT(pSpinRwLock); +#if 0 + pthread_rwlock_wrlock(&pSpinRwLock->rw_lock); +#else + pthread_mutex_lock(&pSpinRwLock->rw_lock); +#endif +} + + +//------------------------------------------------------------- +// Acquire a spin rw lock with less overhead +//------------------------------------------------------------- +void +SpinRwLockFastAcquireRead( SPIN_RW_LOCK *pSpinRwLock ) +{ + SpinRwLockAcquireRead( pSpinRwLock ); // For Now +} +void +SpinRwLockFastAcquireWrite( SPIN_RW_LOCK *pSpinRwLock ) +{ + SpinRwLockAcquireWrite( pSpinRwLock ); // For Now +} + + +//------------------------------------------------------------- +// Release a spin rw lock +//------------------------------------------------------------- +void +SpinRwLockReleaseRead( SPIN_RW_LOCK *pSpinRwLock ) +{ + ASSERT(pSpinRwLock); +#if 0 + pthread_rwlock_unlock(&pSpinRwLock->rw_lock); +#else + pthread_mutex_unlock(&pSpinRwLock->rw_lock); +#endif +} +void +SpinRwLockReleaseWrite( SPIN_RW_LOCK *pSpinRwLock ) +{ + ASSERT(pSpinRwLock); +#if 0 + pthread_rwlock_unlock(&pSpinRwLock->rw_lock); +#else + pthread_mutex_unlock(&pSpinRwLock->rw_lock); +#endif +} + + +//------------------------------------------------------------- +// Release a spin rw lock with less overhead +//------------------------------------------------------------- +void +SpinRwLockFastReleaseRead( SPIN_RW_LOCK *pSpinRwLock ) +{ + SpinRwLockReleaseRead( pSpinRwLock ); // For Now +} +void +SpinRwLockFastReleaseWrite( SPIN_RW_LOCK *pSpinRwLock ) +{ + SpinRwLockReleaseWrite( pSpinRwLock ); // For Now +} diff --git a/IbAccess/UserLinux/Public/ispinlock_osd.h b/IbAccess/UserLinux/Public/ispinlock_osd.h new file mode 100644 index 0000000..86400f9 --- /dev/null +++ b/IbAccess/UserLinux/Public/ispinlock_osd.h @@ -0,0 +1,197 @@ +/* BEGIN_ICS_COPYRIGHT2 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT2 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +#ifndef _IBA_PUBLIC_ISPINLOCK_OSD_H +#define _IBA_PUBLIC_ISPINLOCK_OSD_H + +#include "iba/public/datatypes.h" +#include + + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct _SPIN_LOCK +{ + /* No publically accessible members. */ + pthread_mutex_t sp_lock; +} SPIN_LOCK; + +typedef struct _SPIN_RW_LOCK +{ + /* No publically accessible members. */ + pthread_mutex_t rw_lock; +} SPIN_RW_LOCK; + +typedef uint32 ATOMIC_UINT; + +static inline uint32 AtomicRead(const volatile ATOMIC_UINT *pValue) +{ + return *pValue; +} + +static inline void AtomicWrite(volatile ATOMIC_UINT *pValue, + uint32 newValue) +{ + *pValue = newValue; +} + +static inline ATOMIC_UINT AtomicExchange(volatile ATOMIC_UINT *pValue, + uint32 newValue) +{ + return __sync_lock_test_and_set(pValue,newValue); +} + +static inline boolean AtomicCompareStore(volatile ATOMIC_UINT *pValue, + ATOMIC_UINT oldValue, + ATOMIC_UINT newValue) +{ + return __sync_bool_compare_and_swap(pValue, oldValue, newValue); +} + +static inline ATOMIC_UINT AtomicAdd(ATOMIC_UINT *pValue, + ATOMIC_UINT add) +{ + return __sync_add_and_fetch(pValue, add); +} + +static inline void AtomicAddVoid(ATOMIC_UINT *pValue, ATOMIC_UINT add) +{ + (void)AtomicAdd(pValue, add); +} + +static inline ATOMIC_UINT AtomicSubtract(ATOMIC_UINT *pValue, + ATOMIC_UINT sub) +{ + return __sync_sub_and_fetch(pValue, sub); +} + +static inline void AtomicSubtractVoid(ATOMIC_UINT *pValue, uint32 sub) +{ + (void)AtomicSubtract(pValue, sub); +} + +static inline ATOMIC_UINT AtomicIncrement(ATOMIC_UINT *pValue) +{ + return AtomicAdd(pValue, 1); +} + +static inline void AtomicIncrementVoid(ATOMIC_UINT *pValue) +{ + AtomicAddVoid(pValue, 1); +} + +static inline ATOMIC_UINT AtomicDecrement(ATOMIC_UINT *pValue) +{ + return AtomicSubtract(pValue, 1); +} + +static inline void AtomicDecrementVoid(ATOMIC_UINT *pValue) +{ + AtomicSubtractVoid(pValue, 1); +} + +/* for user mode barriers we always use the SMP safe versions */ +#if defined(__i386__) || defined(__i686__) || defined(__IA32__) +/* Some non intel clones support out of order store. be conservative */ +static _inline void IoBarrierRead(void) + { __asm__ __volatile__ ("lock; addl $0,0(%%esp)": : :"memory"); } +static _inline void IoBarrierReadWrite(void) + { __asm__ __volatile__ ("lock; addl $0,0(%%esp)": : :"memory"); } +static _inline void IoBarrierWrite(void) + { __asm__ __volatile__ ("lock; addl $0,0(%%esp)": : :"memory"); } + +static _inline void CpuBarrierRead(void) {IoBarrierRead(); } +static _inline void CpuBarrierWrite(void) {IoBarrierWrite(); } +static _inline void CpuBarrierReadWrite(void) {IoBarrierReadWrite(); } + +static _inline void CpuPrefetch(void *addr) +{ + asm volatile("prefetchnta (%0)" :: "r" (addr)); +} +#elif defined(__x86_64__) || defined(__X64_64__) +static _inline void IoBarrierRead(void) { asm volatile("lfence":::"memory"); } +static _inline void IoBarrierWrite(void) { asm volatile("sfence":::"memory"); } +static _inline void IoBarrierReadWrite(void){asm volatile("mfence":::"memory");} + +static _inline void CpuBarrierRead(void) {IoBarrierRead(); } +static _inline void CpuBarrierWrite(void) {IoBarrierWrite(); } +static _inline void CpuBarrierReadWrite(void) {IoBarrierReadWrite(); } + +static _inline void CpuPrefetch(void *addr) +{ + asm volatile("prefetcht0 %0" :: "m" (*(unsigned long *)addr)); +} +#elif defined(__ia64__) || defined(__IA64__) +static _inline void IoBarrierRead(void) + { __asm__ __volatile__ ("mf" ::: "memory"); } +static _inline void IoBarrierWrite(void) + { __asm__ __volatile__ ("mf" ::: "memory"); } +static _inline void IoBarrierReadWrite(void) + { __asm__ __volatile__ ("mf" ::: "memory"); } + +static _inline void CpuBarrierRead(void) {IoBarrierRead(); } +static _inline void CpuBarrierWrite(void) {IoBarrierWrite(); } +static _inline void CpuBarrierReadWrite(void) {IoBarrierReadWrite(); } + +static _inline void CpuPrefetch(void *addr) +{ + asm volatile("lfetch [%0]" :: "r" (addr)); +} +#elif defined(__ppc__) || defined(__PPC__) +static _inline void IoBarrierRead(void) + { __asm__ __volatile__ ("eieio" : : : "memory"); } +static _inline void IoBarrierWrite(void) + { __asm__ __volatile__ ("eieio" : : : "memory"); } +static _inline void IoBarrierReadWrite(void) + { __asm__ __volatile__ ("eieio" : : : "memory"); } + +static _inline void CpuBarrierRead(void) + { __asm__ __volatile__ ("isync" : : : "memory"); } +static _inline void CpuBarrierWrite(void) + { __asm__ __volatile__ ("eieio" : : : "memory"); } +static _inline void CpuBarrierReadWrite(void) + { __asm__ __volatile__ ("isync" : : : "memory"); } + +static _inline void CpuPrefetch(void *addr) +{ + asm volatile("dcbt 0,%0" :: "r" (addr)); +} +#else +#error "Unsupported CPU type" +#endif + +#ifdef __cplusplus +}; +#endif + +#endif /* _IBA_PUBLIC_ISPINLOCK_OSD_H */ diff --git a/IbAccess/UserLinux/Public/ithread.c b/IbAccess/UserLinux/Public/ithread.c new file mode 100644 index 0000000..b30299d --- /dev/null +++ b/IbAccess/UserLinux/Public/ithread.c @@ -0,0 +1,295 @@ +/* BEGIN_ICS_COPYRIGHT5 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT5 ****************************************/ + + +#include +#include +#include +#include "datatypes.h" +#include "ithread.h" +#include "idebug.h" + +//---------------------------------------------------------------- +//Globals +//---------------------------------------------------------------- +// threadNameKey is global to all threads which is used to access +// the thread's name from its thread local storage. +static pthread_key_t threadNameKey; +static pthread_once_t key_once = PTHREAD_ONCE_INIT; // ensures key is only set once +static int isNameKeySet = 0; // to ensure key has been created before it is used. +//---------------------------------------------------------------- +//Init function to set the threadNameKey once. +//Invoked via the pthread_once interface in __UserThreadStartup. +//---------------------------------------------------------------- +static void +__ThreadMakeKey() +{ + int rc; + + if ((rc = pthread_key_create(&threadNameKey, NULL)) == 0) + isNameKeySet = 1; + else + MsgOut("Failed to create thread name key, rc: %d.\n",rc); +} +//---------------------------------------------------------------- +// Internal function to initialize the thread data structure. This +// function is typically called before a call to kernel_thread(). +//---------------------------------------------------------------- +static void +__InitializeThreadData(IN THREAD *pThread, IN THREAD_CALLBACK Callback, + IN void *Context, IN char *Name) +{ + pThread->m_Private.m_Osd.tr_flags = 0; + pThread->m_Private.m_Callback = Callback; + pThread->m_Private.m_Context = Context; + memcpy(pThread->m_Private.m_Osd.tr_name, Name, THREAD_NAME_SIZE); + EventInit( &pThread->m_Private.m_Osd.tr_RunningEvent ); +} + +// +//---------------------------------------------------------------- +// Internal function to run a new user mode thread. +// This function is always run as a result of creation a new user mode thread. +// Its main job is to synchronize the creation and running of the new thread. +//---------------------------------------------------------------- +// + + +static int +__UserThreadStartup(void * arg) +{ + THREAD *pThread = (THREAD *) arg; + // + // Trigger the thread running event. + // The creating thread waits on this event. + // +#if DEBUG_THREAD + DbgOut ("__UserThreadStartup( %p )[\n",pThread ); +#endif + // create thread name_key + (void)pthread_once(&key_once, __ThreadMakeKey); + // set thread name + if (isNameKeySet) + ThreadSetName(pThread->m_Private.m_Osd.tr_name); + + EventTrigger(&pThread->m_Private.m_Osd.tr_RunningEvent); + if (pThread->m_Private.m_Callback) + { + pThread->m_Private.m_Callback(pThread->m_Private.m_Context); + } + +#if DEBUG_THREAD + DbgOut("__UserThreadStartup( %p )]\n",pThread ); +#endif + + return (0) ; + +} +//---------------------------------------------------------------- +// +// Indicate that there was an intent to use a thread +//---------------------------------------------------------------- +// +void +ThreadInitState ( IN THREAD *pThread ) +{ + pThread->m_Private.m_Osd.tr_state = Constructed; + EventInitState( &pThread->m_Private.m_Osd.tr_RunningEvent); +} + +// +//---------------------------------------------------------------- +// Create a new thread. This thread will execute supplied "Callback" +// with the user supplied "Context" +//---------------------------------------------------------------- +// +boolean +ThreadCreate( IN THREAD *pThread, IN char* Name, IN THREAD_CALLBACK Callback, IN void *Context ) +{ + int ret; + + if (pThread == NULL) + { + return FALSE; + } + + // + // Initialize the thread structure + // + __InitializeThreadData(pThread, Callback, Context, Name); + +#if DEBUG_THREAD + DbgOut("__ThreadCreate( %p )[\n",pThread ); +#endif + + ret = pthread_create(&pThread->m_Private.m_Osd.tr_id, + NULL, + (void *)__UserThreadStartup, + (void *)pThread); + + if (ret != 0) // pthread_create returns a "0" for success + { + return FALSE; + } + + // TBD - any way to set name of thread? + + // + // Wait for the "child" thread to indicate that it is up and running + // It assumes that the spawned thread will signal Running Event when it starts up + // + EventWaitOn( &pThread->m_Private.m_Osd.tr_RunningEvent, EVENT_NO_TIMEOUT); + + pThread->m_Private.m_Osd.tr_state = Started; + +#if DEBUG_THREAD + DbgOut("__ThreadCreate( %p )]\n",pThread ); +#endif + + return TRUE; +} + +// +//---------------------------------------------------------------- +// Destroy the thread. +// If this function is called after the callback function terminated causing +// the thread to terminate, this function returns immediately. +// If this function is called before the callback function returns, the +// caller will wait for the kill event forever. +//---------------------------------------------------------------- +// +void +ThreadDestroy( IN THREAD *pThread ) +{ + if ( pThread->m_Private.m_Osd.tr_state != Started ) + { + // thread was never Started + return; + } + // If more than one threads are wating on a thread + // the outcome may not be deterministic + // Might want to try waiting on the thread kill event + +#if DEBUG_THREAD + DbgOut ("__ThreadDestroy( %p )[\n",pThread ); +#endif + pthread_join( pThread->m_Private.m_Osd.tr_id, NULL ); + EventDestroy( &pThread->m_Private.m_Osd.tr_RunningEvent ); + + // clear all the thread state data + pThread->m_Private.m_Osd.tr_state = Destroyed; + pThread->m_Private.m_Osd.tr_id = 0; + pThread->m_Private.m_Callback = NULL; + pThread->m_Private.m_Context = NULL; +#if DEBUG_THREAD + DbgOut ("__ThreadDestroy( %p )]\n",pThread ); +#endif +} + +// +//---------------------------------------------------------------- +// Suspend a thread execution for "pause_ms" milliseconds +//---------------------------------------------------------------- +// +void +ThreadSuspend( IN uint32 pause_ms ) +{ + // Convert to micro seconds + usleep(pause_ms * 1000); + +} + +// +//---------------------------------------------------------------- +// Delay execution of thread for some number of microseconds. +// This uses Linuxs' udelay() function. Remember, suggested maximum +// value of microseconds is 1000, ie, 1 milliseconds. +//---------------------------------------------------------------- +// +void +ThreadStall( IN uint32 pause_us ) +{ + usleep(pause_us); +} + + +//---------------------------------------------------------------- +// Number of processors on this system +//---------------------------------------------------------------- +uint32 +ProcCount(void) +{ + //******************************** + //*********** FOR NOW!! ********** + //******************************** + return 0; +} + +uint32 +CurrentProc(void) +{ + return 0; // for now +} + +//---------------------------------------------------------------- +// set priority for current thread +//---------------------------------------------------------------- +void ThreadSetPriority(IN THREAD_PRI pri) +{ + if (nice(pri) < 0) { + MsgOut("Failed to set thread priority.\n"); + } +} + +//---------------------------------------------------------------- +//set thread name. using a thread specific key +//---------------------------------------------------------------- +void ThreadSetName(IN char *name) +{ + + if( pthread_setspecific(threadNameKey, name)!= 0) + { + MsgOut("Failed to Set Thread Name.\n"); + } + +} + +//------------------------------------------------------------------ +// get thread name. returns the name which was set by +// ThreadSetName(). +// ----------------------------------------------------------------- +char* ThreadGetName(void) +{ + char* name; + + name = (char*)pthread_getspecific(threadNameKey); + + return (name != NULL)?name:"null"; +} + diff --git a/IbAccess/UserLinux/Public/ithread_osd.h b/IbAccess/UserLinux/Public/ithread_osd.h new file mode 100644 index 0000000..c7618e2 --- /dev/null +++ b/IbAccess/UserLinux/Public/ithread_osd.h @@ -0,0 +1,79 @@ +/* BEGIN_ICS_COPYRIGHT2 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT2 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + + +#ifndef _IBA_PUBLIC_ITHREAD_OSD_H_ +#define _IBA_PUBLIC_ITHREAD_OSD_H_ + +#include "iba/public/datatypes.h" +#include "iba/public/ievent.h" +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define DEBUG_THREAD 0 /* set to 1 to enable DbgOut for thread */ + +/*--------------------------------------------------------- + * OS dependent data structure used by the thread object. + * Users should not access these variables directly. + *--------------------------------------------------------- */ + +typedef struct _THREAD_OSD +{ + uint32 tr_flags; + char tr_name[THREAD_NAME_SIZE]; + pthread_t tr_id; + pthread_attr_t tr_attr; + EVENT tr_RunningEvent; + ObjectState tr_state; +} THREAD_OSD; + +/* for LINUX these are nice values */ +typedef enum { + THREAD_PRI_VERY_HIGH = -15, + THREAD_PRI_HIGH = -10, + THREAD_PRI_NORMAL = 0, + THREAD_PRI_LOW = 10, + THREAD_PRI_VERY_LOW = 15 +} THREAD_PRI; + +typedef struct _WORK_REQUEST_OSD +{ + uint32 Foo; +} WORK_REQUEST_OSD; + +#ifdef __cplusplus +}; +#endif + +#endif /* _IBA_PUBLIC_ITHREAD_OSD_H_ */ diff --git a/IbAccess/UserLinux/Public/itimer.c b/IbAccess/UserLinux/Public/itimer.c new file mode 100644 index 0000000..d2b7c7e --- /dev/null +++ b/IbAccess/UserLinux/Public/itimer.c @@ -0,0 +1,57 @@ +/* BEGIN_ICS_COPYRIGHT5 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT5 ****************************************/ + +#include "datatypes.h" +#include "itimer.h" + +uint64 +GetTimeStamp(void) +{ + uint64 Tstamp; + struct timeval tv; + + timerclear(&tv); + (void) gettimeofday(&tv, NULL); + + Tstamp = ((uint64)tv.tv_sec * TIME_INC_CONVERSION) + (uint64)tv.tv_usec; + + return ( Tstamp ); +} + +uint32 +GetTimeStampSec(void) +{ + struct timeval tv; + + timerclear(&tv); + (void) gettimeofday(&tv, NULL); + + return ( tv.tv_sec ); +} + diff --git a/IbAccess/UserLinux/Public/itimer_osd.h b/IbAccess/UserLinux/Public/itimer_osd.h new file mode 100644 index 0000000..41859c7 --- /dev/null +++ b/IbAccess/UserLinux/Public/itimer_osd.h @@ -0,0 +1,54 @@ +/* BEGIN_ICS_COPYRIGHT2 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT2 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + + +#ifndef _IBA_PUBLIC_ITIMER_OSD_H_ +#define _IBA_PUBLIC_ITIMER_OSD_H_ + +#include "iba/public/datatypes.h" +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define TIME_INC_CONVERSION ((unsigned long)1000000)/* usecs per second */ + +typedef struct _TIMER_OSD +{ + int ti_timer; +} TIMER_OSD; + +#ifdef __cplusplus +}; +#endif + +#endif /*_IBA_PUBLIC_ITIMER_OSD_H_ */ diff --git a/IbAccess/UserLinux/README b/IbAccess/UserLinux/README new file mode 100644 index 0000000..4400905 --- /dev/null +++ b/IbAccess/UserLinux/README @@ -0,0 +1 @@ +Linux User libraries diff --git a/IbPrint/Makefile b/IbPrint/Makefile new file mode 100644 index 0000000..957299f --- /dev/null +++ b/IbPrint/Makefile @@ -0,0 +1,179 @@ +# Makefile for IbPrint + +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# Include Make Control Settings +include $(TL_DIR)/$(PROJ_FILE_DIR)/Makesettings.project + +#=============================================================================# +# Definitions: +#-----------------------------------------------------------------------------# + +# Name of SubProjects +DS_SUBPROJECTS = +# name of executable or downloadable image +EXECUTABLE = # IbPrint$(EXE_SUFFIX) +# list of sub directories to build +DIRS = +# C files (.c) +CFILES = \ + ibprint.c \ + stl_mad.c \ + stl_sma.c \ + stl_sa.c \ + stl_pm.c \ + stl_pa.c \ + types.c \ + sma.c \ + sa.c \ + sd.c \ + mad.c \ + stl_ea.c \ + stl_ema.c \ + # Add more c files here + +# C++ files (.cpp) +CCFILES = \ + # Add more cpp files here +# lex files (.lex) +LFILES = \ + # Add more lex files here +# archive library files (basename, $ARFILES will add MOD_LIB_DIR/prefix and suffix) +LIBFILES = +# Windows Resource Files (.rc) +RSCFILES = +# Windows IDL File (.idl) +IDLFILE = +# Windows Linker Module Definitions (.def) file for dll's +DEFFILE = +# targets to build during INCLUDES phase (add public includes here) +INCLUDE_TARGETS = \ + ibprint.h \ + stl_print.h \ + # Add more h hpp files here +# Non-compiled files +MISC_FILES = +# all source files +SOURCES = $(CFILES) $(CCFILES) $(LFILES) $(RSCFILES) $(IDLFILE) +# Source files to include in DSP File +DSP_SOURCES = $(INCLUDE_TARGETS) $(SOURCES) $(MISC_FILES) \ + $(RSCFILES) $(DEFFILE) $(MAKEFILE) +# all object files +OBJECTS = $(CFILES:.c=$(OBJ_SUFFIX)) $(CCFILES:.cpp=$(OBJ_SUFFIX)) \ + $(LFILES:.lex=$(OBJ_SUFFIX)) +RSCOBJECTS = $(RSCFILES:.rc=$(RES_SUFFIX)) +# targets to build during LIBS phase +LIB_TARGETS_IMPLIB = +LIB_TARGETS_ARLIB = $(LIB_PREFIX)IbPrint$(ARLIB_SUFFIX) +LIB_TARGETS_EXP = $(LIB_TARGETS_IMPLIB:$(ARLIB_SUFFIX)=$(EXP_SUFFIX)) +LIB_TARGETS_MISC = +# targets to build during CMDS phase +SHLIB_VERSION = +CMD_TARGETS_SHLIB = +CMD_TARGETS_EXE = $(EXECUTABLE) +CMD_TARGETS_MISC = +CMD_TARGETS_DRIVER = +CMD_TARGETS_KEXT = +# files to remove during clean phase +CLEAN_TARGETS_MISC = +CLEAN_TARGETS = $(OBJECTS) $(RSCOBJECTS) $(IDL_TARGETS) $(CLEAN_TARGETS_MISC) +# other files to remove during clobber phase +CLOBBER_TARGETS_MISC= +# sub-directory to install to within bin +BIN_SUBDIR = +# sub-directory to install to within include +INCLUDE_SUBDIR = + +# Additional Settings +#CLOCALDEBUG = User defined C debugging compilation flags [Empty] +#CCLOCALDEBUG = User defined C++ debugging compilation flags [Empty] +CLOCAL = $(CPIE) +#CCLOCAL = User defined C++ flags for compiling [Empty] +#BSCLOCAL = User flags for Browse File Builder [Empty] +#DEPENDLOCAL = user defined makedepend flags [Empty] +#LINTLOCAL = User defined lint flags [Empty] +#LOCAL_INCLUDE_DIRS = User include directories to search for C/C++ headers [Empty] +#LDLOCAL = User defined C flags for linking [Empty] +#IMPLIBLOCAL = User flags for Object Lirary Manager [Empty] +#MIDLLOCAL = User flags for IDL compiler [Empty] +#RSCLOCAL = User flags for resource compiler [Empty] +#LOCALDEPLIBS = User libraries to include in dependencies [Empty] +#LOCALLIBS = User libraries to use when linking [Empty] +# (in addition to LOCALDEPLIBS) +#LOCAL_LIB_DIRS = User library directories for libpaths [Empty] +CLOCAL += -I$(TL_DIR)/IbAccess/Common/Inc -I$(TL_DIR)/IbAccess/Vxworks/Public/ + +LOCAL_INCLUDE_DIRS = $(TL_DIR)/IbAccess/Common/Inc \ + $(TL_DIR)/IbAccess/Common/Public +ifeq "$(BUILD_TARGET)" "ATOM" +LOCAL_INCLUDE_DIRS += \ + $(TL_DIR)/target/include +endif + +LOCALDEPLIBS = + +# Include Make Rules definitions and rules +include $(TL_DIR)/$(PROJ_FILE_DIR)/Makerules.project + +#=============================================================================# +# Overrides: +#-----------------------------------------------------------------------------# +#CCOPT = # C++ optimization flags, default lets build config decide +#COPT = # C optimization flags, default lets build config decide +#SUBSYSTEM = Subsystem to build for (none, console or windows) [none] +# (Windows Only) +#USEMFC = How Windows MFC should be used (none, static, shared, no_mfc) [none] +# (Windows Only) +#=============================================================================# + +#=============================================================================# +# Rules: +#-----------------------------------------------------------------------------# +# process Sub-directories +include $(TL_DIR)/Makerules/Maketargets.toplevel + +# build cmds and libs +include $(TL_DIR)/Makerules/Maketargets.build + +# install for includes, libs and cmds phases +include $(TL_DIR)/Makerules/Maketargets.install + +# install for stage phase +#include $(TL_DIR)/Makerules/Maketargets.stage +STAGE:: + +# Unit test execution +#include $(TL_DIR)/Makerules/Maketargets.runtest + +#=============================================================================# + +#=============================================================================# +# DO NOT DELETE THIS LINE -- make depend depends on it. +#=============================================================================# diff --git a/IbPrint/README b/IbPrint/README new file mode 100644 index 0000000..dffa137 --- /dev/null +++ b/IbPrint/README @@ -0,0 +1,2 @@ +Library to provide utility functions to print various IB data structures +to various logs, files, etc diff --git a/IbPrint/ibprint.c b/IbPrint/ibprint.c new file mode 100644 index 0000000..f77af3a --- /dev/null +++ b/IbPrint/ibprint.c @@ -0,0 +1,131 @@ +/* BEGIN_ICS_COPYRIGHT7 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT7 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +#include +#include +#include +#include +#include +#include +#include "ibprint.h" +#ifdef LINUX +#include +#endif + +// TBD: now universally using 0x---:---- for GIDs +// saquery and used to use 0x---:0x--- in a few places but +// mostly used 0x----:----- + +void PrintDestInitNone(PrintDest_t *dest) +{ + dest->type = PL_NONE; +} + +void PrintDestInitFile(PrintDest_t *dest, FILE *file) +{ + dest->type = PL_FILE; + dest->u.file = file; +} + +void PrintDestInitBuffer(PrintDest_t *dest, char *buffer, uint16 length) +{ + dest->type = PL_BUFFER; + dest->u.buf.length = length; + dest->u.buf.offset = 0; + dest->u.buf.buffer = buffer; +} + +void PrintDestInitCallback(PrintDest_t *dest, PrintCallbackFunc_t func, void *context) +{ + dest->type = PL_CALLBACK; + dest->u.callback.func = func; + dest->u.callback.context = context; +} + +#ifdef LINUX +void PrintDestInitSyslog(PrintDest_t *dest, int priority) +{ + dest->type = PL_SYSLOG; + dest->u.priority = priority; +} +#endif + +#ifdef VXWORKS +void PrintDestInitLog(PrintDest_t *dest) +{ + dest->type = PL_LOG; + // TBD +} +#endif + +// TBD - for logging should \n be output? +// all calls output an entire line, including the \n +// TBD - add the \n here, that way callbacks for syslog will not include \n +// Note - syslog will only add if needed, so might be ok, what about vxworks? +void PrintFunc(PrintDest_t *dest, const char *format, ...) +{ + va_list args; + + va_start(args, format); + switch (dest->type) { + case PL_NONE: + break; + case PL_FILE: + (void)vfprintf(dest->u.file, format, args); + break; + case PL_BUFFER: + { + uint16 avail = dest->u.buf.length - dest->u.buf.offset; + if (avail) + dest->u.buf.offset += vsnprintf(&dest->u.buf.buffer[dest->u.buf.offset], + avail, format, args); + } + break; + case PL_CALLBACK: + { + char buf[140]; + vsnprintf(buf, sizeof(buf), format, args); + (dest->u.callback.func)(dest->u.callback.context, buf); + } + break; +#ifdef LINUX + case PL_SYSLOG: + (void)vsyslog(dest->u.priority, format, args); + break; +#endif +#ifdef VXWORKS + case PL_LOG: + // TBD + break; +#endif + } + va_end(args); +} diff --git a/IbPrint/ibprint.h b/IbPrint/ibprint.h new file mode 100644 index 0000000..5c4baf3 --- /dev/null +++ b/IbPrint/ibprint.h @@ -0,0 +1,239 @@ +/* BEGIN_ICS_COPYRIGHT7 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT7 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +#ifndef IBPRINT_H +#define IBPRINT_H + +#include +#include +#include +#include +#include + +typedef enum { + PL_NONE = 0, // no output + PL_FILE, // output to a FILE + PL_BUFFER, // output to a buffer + PL_CALLBACK, // output via callback +#ifdef LINUX + PL_SYSLOG, // output to syslog +#endif +#ifdef VXWORKS + PL_LOG, // output to embedded log + // TBD add VxWorks sysprint or simply print? +#endif +} PrintType_t; + +typedef struct PrintBuf_s { + uint16 length; // size of buffer + uint16 offset; // next place to write in buffer + char *buffer; +} PrintBuf_t; + +typedef void (*PrintCallbackFunc_t)(void *context, const char *buf); + +typedef struct PrintCallback_s { + PrintCallbackFunc_t func; + void *context; +} PrintCallback_t; + +typedef struct PrintDest_s { + PrintType_t type; + union { + FILE *file; + PrintBuf_t buf; + PrintCallback_t callback; +#ifdef LINUX + int priority; // for syslog +#endif +#ifdef VXWORKS + // TBD +#endif + } u; +} PrintDest_t; + + +extern void PrintDestInitNone(PrintDest_t *dest); // no output +extern void PrintDestInitFile(PrintDest_t *dest, FILE *file); +extern void PrintDestInitBuffer(PrintDest_t *dest, char *buffer, uint16 length); +extern void PrintDestInitCallback(PrintDest_t *dest, PrintCallbackFunc_t func, + void *context); +#ifdef LINUX +extern void PrintDestInitSyslog(PrintDest_t *dest, int priority); +#endif + +#ifdef VXWORKS +extern void PrintDestInitLog(PrintDest_t *dest); +#endif +extern void PrintFunc(PrintDest_t *dest, const char *format, ...) __attribute__((format(printf,2,3))); + +/////////////////////////////////////////////////////////////////////////////// +// some basic IB types +extern void PrintGuid(PrintDest_t *dest, int indent, EUI64 Guid); +extern void PrintLid(PrintDest_t *dest, int indent, IB_LID Lid); +extern void PrintGid(PrintDest_t *dest, int indent, const IB_GID *pGid); +extern void PrintLongMaskBits(PrintDest_t *dest, int indent, const char* prefix, const uint8 *bits, unsigned size); +extern void PrintSeparator(PrintDest_t *dest); + +/////////////////////////////////////////////////////////////////////////////// +// common MAD headers and MADs +//extern const char* IbMgmtClassToText(uint8 class); +//extern const char* IbMadMethodToText(uint8 method); +//extern const char* IbMadStatusToText(uint16 status); +extern void PrintMad(PrintDest_t *dest, int indent, const MAD *pMad); +extern void PrintMadHeader(PrintDest_t *dest, int indent, const MAD_COMMON *hdr); +extern void PrintSmpHeader(PrintDest_t *dest, int indent, const SMP *smp); +typedef void (*formatcapmask_func_t)(char buf[80], uint16 cmask); +typedef void (*formatcapmask2_func_t)(char buf[80], uint32 cmask); +extern void FormatClassPortInfoCapMask(char buf[80], uint16 cmask); +extern void FormatClassPortInfoCapMask2(char buf[80], uint32 cmask); +extern void PrintClassPortInfo2(PrintDest_t *dest, int indent, + const IB_CLASS_PORT_INFO *pClassPortInfo, formatcapmask_func_t func, + formatcapmask2_func_t func2); +extern void PrintClassPortInfo(PrintDest_t *dest, int indent, + const IB_CLASS_PORT_INFO *pClassPortInfo); +// TBD extern void PrintNotice(PrintDest_t *dest, int indent, const NOTICE *pNotice); +// TBD also trap 64-67 details + +/////////////////////////////////////////////////////////////////////////////// +// SMA +extern void PrintSmp(PrintDest_t *dest, int indent, const SMP *smp); +extern void PrintNodeDesc(PrintDest_t *dest, int indent, + const NODE_DESCRIPTION *pNodeDesc); +extern void PrintNodeInfo(PrintDest_t *dest, int indent, + const NODE_INFO *pNodeInfo); +// style=0 or 1 +// TBD - key off portGuid!=0 to decide style instead? +extern void PrintPortInfo(PrintDest_t *dest, int indent, + const PORT_INFO *pPortInfo, EUI64 portGuid, int style); +extern void PrintPortInfoSmp(PrintDest_t *dest, int indent, + const SMP *smp, EUI64 portGuid); +extern void PrintSMInfo(PrintDest_t *dest, int indent, + const SM_INFO *pSMInfo, IB_LID lid); +extern void PrintSwitchInfo(PrintDest_t *dest, int indent, + const SWITCH_INFO *pSwitchInfo, IB_LID lid); +extern void PrintLinearFDB(PrintDest_t *dest, int indent, + const FORWARDING_TABLE *pLinearFDB, uint16 blockNum); +extern void PrintRandomFDB(PrintDest_t *dest, int indent, + const FORWARDING_TABLE *pRandomFDB, uint16 blockNum); +extern boolean isMCastFDBEmpty(const FORWARDING_TABLE *pMCastFDB); +extern void PrintMCastFDB(PrintDest_t *dest, int indent, + const FORWARDING_TABLE *pMCastFDB, uint16 blockNum); +extern void PrintMCastFDBSmp(PrintDest_t *dest, int indent, + const SMP *smp); +extern boolean isMCastFDBEmptyRows(const FORWARDING_TABLE *pMCastFDB, + uint8 numPositions); +extern void PrintPortGroupTable(PrintDest_t *dest, int indent, + const PORT_GROUP_TABLE *pPortGroup, uint16 tier, uint16 blockNum); +extern void PrintAdaptiveRoutingLidmask(PrintDest_t *dest, int indent, + const ADAPTIVE_ROUTING_LIDMASK *pLidmask, uint16 blockNum); + + +// prints full rows in table +// pMcastFDB expected to be FORWARDING_TABLE[1+endPosition-startPosition] entry +extern void PrintMCastFDBRows(PrintDest_t *dest, int indent, + const FORWARDING_TABLE *pMCastFDB, uint16 blockNum, + uint8 startPosition, uint8 endPosition, boolean showHeading); +extern void PrintVLArbTable(PrintDest_t *dest, int indent, + const VLARBTABLE *pVLArbTable, uint8 blockNum); +extern void PrintVLArbTableSmp(PrintDest_t *dest, int indent, + const SMP *smp, NODE_TYPE nodetype); +extern void PrintPKeyTable(PrintDest_t *dest, int indent, + const PARTITION_TABLE *pPKeyTable, uint16 blockNum); +extern void PrintPKeyTableSmp(PrintDest_t *dest, int indent, + const SMP *smp, NODE_TYPE nodetype, + boolean showHeading, boolean showBlock); +extern void PrintGuidInfo(PrintDest_t *dest, int indent, + const GUID_INFO *pGuidInfo, uint8 blockNum); + +/////////////////////////////////////////////////////////////////////////////// +// SA one print function for each SA query OutputType +extern void PrintPathRecord(PrintDest_t *dest, int indent, + const IB_PATH_RECORD *pPathRecord); +extern void PrintNodeRecord(PrintDest_t *dest, int indent, + const IB_NODE_RECORD *pNodeRecord); + +extern void PrintPortInfoRecord(PrintDest_t *dest, int indent, + const IB_PORTINFO_RECORD *pPortInfoRecord); +extern void PrintSMInfoRecord(PrintDest_t *dest, int indent, + const IB_SMINFO_RECORD *pSMInfoRecord); +extern void PrintLinkRecord(PrintDest_t *dest, int indent, + const IB_LINK_RECORD *pLinkRecord); +extern void PrintTraceRecord(PrintDest_t *dest, int indent, + const IB_TRACE_RECORD *pTraceRecord); +extern void PrintSwitchInfoRecord(PrintDest_t *dest, int indent, + const IB_SWITCHINFO_RECORD *pSwitchInfoRecord); +extern void PrintLinearFDBRecord(PrintDest_t *dest, int indent, + const IB_LINEAR_FDB_RECORD *pLinearFDBRecord); +extern void PrintRandomFDBRecord(PrintDest_t *dest, int indent, + const IB_RANDOM_FDB_RECORD *pRandomFDBRecord); +extern void PrintMCastFDBRecord(PrintDest_t *dest, int indent, + const IB_MCAST_FDB_RECORD *pMCastFDBRecord); +extern void PrintVLArbTableRecord(PrintDest_t *dest, int indent, + const IB_VLARBTABLE_RECORD *pVLArbTableRecord); +extern void PrintPKeyTableRecord(PrintDest_t *dest, int indent, + const IB_P_KEY_TABLE_RECORD *pPKeyTableRecord); +//extern char HexToChar(uint8 c); +//extern void FormatChars(char *buf, const uint8* data, uint32 len); +extern void PrintServiceRecord(PrintDest_t *dest, int indent, + const IB_SERVICE_RECORD *pServiceRecord); +extern void PrintMcMemberRecord(PrintDest_t *dest, int indent, + const IB_MCMEMBER_RECORD *pMcMemberRecord); +extern void PrintInformInfo(PrintDest_t *dest, int indent, + const IB_INFORM_INFO *pInformInfo); +extern void PrintInformInfoRecord(PrintDest_t *dest, int indent, + const IB_INFORM_INFO_RECORD *pInformInfoRecord); + +/////////////////////////////////////////////////////////////////////////////// +// IbAccess SubnetDriver interface + +// display the results from a query +// Note: csv is ignored for all but OutputTypeVfInfoRecord +extern void PrintQueryResultValue(PrintDest_t *dest, int indent, + PrintDest_t *dbgDest, + QUERY_RESULT_TYPE OutputType, int csv, + const QUERY_RESULT_VALUES *pResult); +// display the results from a query +// returns potential exit status: +// 0 - success +// 1 - query failed +// 2 - query failed due to invalid query +// Note: csv is ignored for all but OutputTypeVfInfoRecord +extern int PrintQueryResult(PrintDest_t *dest, int indent, + PrintDest_t *dbgDest, + QUERY_RESULT_TYPE OutputType, int csv, FSTATUS status, + QUERY_RESULT_VALUES *pResult); + +/////////////////////////////////////////////////////////////////////////////// +// Print with additional information. +extern void PrintExtendedPathRecord(PrintDest_t *dest, int indent, + const IB_PATH_RECORD *pPathRecord); +#endif /* IBPRINT_H */ diff --git a/IbPrint/mad.c b/IbPrint/mad.c new file mode 100644 index 0000000..ab4fb6e --- /dev/null +++ b/IbPrint/mad.c @@ -0,0 +1,234 @@ +/* BEGIN_ICS_COPYRIGHT7 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT7 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +#include +#include +#include +#include +#include +#include +#include "ibprint.h" + +static const char* IbMgmtClassToText(uint8 class) +{ + switch (class) { + case MCLASS_SM_LID_ROUTED: return "SMA"; + case MCLASS_SM_DIRECTED_ROUTE: return "SMA_DR"; + case MCLASS_SUBN_ADM: return "SA"; + case MCLASS_PERF: return "PMA"; + case MCLASS_BM: return "BMA"; + case MCLASS_DEV_MGT: return "DMA"; + case MCLASS_COMM_MGT: return "CM"; + case MCLASS_SNMP: return "SNMP"; + case MCLASS_CC: return "CCA"; + case MCLASS_VFI_PM: return "PM"; + default: return "Unknown"; + } +} + +static const char* IbMadMethodToText(uint8 method) +{ + switch (method) { + case MMTHD_GET: return "Get"; + case MMTHD_SET: return "Set"; + case MMTHD_SEND: return "Send"; + case MMTHD_TRAP: return "Trap"; + case MMTHD_REPORT: return "Report"; + case MMTHD_TRAP_REPRESS: return "TrapRepress"; + case MMTHD_GET_RESP: return "GetResp"; + case MMTHD_REPORT_RESP: return "ReportResp"; + default: return "Unknown"; + } +} + +void PrintMadHeader(PrintDest_t *dest, int indent, const MAD_COMMON *hdr) +{ + MAD_STATUS mad_status; + + if (hdr->MgmtClass == MCLASS_SM_DIRECTED_ROUTE) + mad_status.AsReg16 = hdr->u.DR.s.Status; + else + mad_status = hdr->u.NS.Status; + PrintFunc(dest, "%*sBaseVersion: %d MgmtClass: 0x%02x (%6s) ClassVersion: %d\n", + indent, "", hdr->BaseVersion, hdr->MgmtClass, + IbMgmtClassToText(hdr->MgmtClass), hdr->ClassVersion); + PrintFunc(dest, "%*sMethod: 0x%02x R: %u (%11s) AttribID: 0x%04x AttribMod: 0x%08x\n", + indent, "", hdr->mr.s.Method, hdr->mr.s.R, + IbMadMethodToText(hdr->mr.AsReg8), + hdr->AttributeID, hdr->AttributeModifier); + PrintFunc(dest, "%*sTID: 0x%016"PRIx64" Status: 0x%04x (%s)\n", + indent, "", hdr->TransactionID, mad_status.AsReg16, + iba_mad_status_msg(mad_status)); +} + +void PrintSmpHeader(PrintDest_t *dest, int indent, const SMP *smp) +{ + PrintMadHeader(dest, indent, &smp->common); + PrintFunc(dest, "%*sM_KEY: 0x%016"PRIx64"\n", indent, "", smp->M_Key); + if (smp->common.MgmtClass == MCLASS_SM_DIRECTED_ROUTE) { + uint16 offset; + uint32 i; + char buf[81]; + PrintFunc(dest, "%*sDR: D: %u Ptr: %3u Cnt: %3u DrSLID: 0x%04x DrDLID: 0x%04x\n", + indent, "", smp->common.u.DR.s.D, + smp->common.u.DR.HopPointer, smp->common.u.DR.HopCount, + smp->SmpExt.DirectedRoute.DrSLID, + smp->SmpExt.DirectedRoute.DrDLID); + + offset = sprintf(buf, "InitPath:"); + // entry 0 is not used + for (i=1; i<= smp->common.u.DR.HopCount; i++) { + if ((i-1)%16 == 0 && i>1) { + PrintFunc(dest, "%*s%s\n", indent, "", buf); + offset=sprintf(buf, " "); + } + offset += sprintf(&buf[offset], " %3u", smp->SmpExt.DirectedRoute.InitPath[i]); + } + PrintFunc(dest, "%*s%s\n", indent, "", buf); + + if (smp->common.u.DR.s.D) { + offset = sprintf(buf, "RetPath: "); + // entry 0 is not used + for (i=1; i<= smp->common.u.DR.HopCount; i++) { + if ((i-1)%16 == 0 && i>1) { + PrintFunc(dest, "%*s%s\n", indent, "", buf); + offset=sprintf(buf, " "); + } + offset += sprintf(&buf[offset], " %3u", smp->SmpExt.DirectedRoute.RetPath[i]); + } + PrintFunc(dest, "%*s%s\n", indent, "", buf); + } + } +} + +void FormatClassPortInfoCapMask(char buf[80], uint16 cmask) +{ + snprintf(buf, 80, "%s%s", + (cmask & CLASS_PORT_CAPMASK_TRAP)?"Trap ":"", + (cmask & CLASS_PORT_CAPMASK_NOTICE)?"Notice ":""); +} + +void FormatClassPortInfoCapMask2(char buf[80], uint32 cmask) +{ + // no generic bits yet, only class specific + buf[0] = '\0'; + //sprintf(buf, "%s%s", + // (cmask & CLASS_PORT_CAPMASK_TRAP)?"Trap ":"", + // (cmask & CLASS_PORT_CAPMASK_NOTICE)?"Notice ":""); +} + +void PrintClassPortInfo2(PrintDest_t *dest, int indent, const IB_CLASS_PORT_INFO *pClassPortInfo, formatcapmask_func_t func, formatcapmask2_func_t func2) +{ + char tbuf[8]; + char cbuf[80]; + PrintFunc(dest, "%*sBaseVersion: %d ClassVersion: %d\n", + indent, "", pClassPortInfo->BaseVersion, + pClassPortInfo->ClassVersion); + FormatTimeoutMult(tbuf, pClassPortInfo->u1.s.RespTimeValue); + (*func)(cbuf, pClassPortInfo->CapMask); + PrintFunc(dest, "%*sRespTime: %s Capability: 0x%04x: %s\n", + indent, "", tbuf, + pClassPortInfo->CapMask, cbuf); + (*func2)(cbuf, pClassPortInfo->u1.s.CapMask2); + PrintFunc(dest, "%*sCapability2: 0x%07x: %s\n", + indent, "", + pClassPortInfo->u1.s.CapMask2, cbuf); + + PrintFunc(dest, "%*sRedirect: LID: 0x%04x GID: 0x%016"PRIx64":0x%016"PRIx64"\n", + indent, "", + pClassPortInfo->RedirectLID, + pClassPortInfo->RedirectGID.AsReg64s.H, + pClassPortInfo->RedirectGID.AsReg64s.L); + PrintFunc(dest, "%*s QP: 0x%06x QKey: 0x%08x PKey: 0x%04x SL: %2u\n", + indent, "", + pClassPortInfo->u3.s.RedirectQP, + pClassPortInfo->Redirect_Q_Key, + pClassPortInfo->Redirect_P_Key, + pClassPortInfo->u2.s.RedirectSL); + PrintFunc(dest, "%*s FlowLabel: 0x%05x TClass: 0x%02x\n", + indent, "", + pClassPortInfo->u2.s.RedirectFlowLabel, + pClassPortInfo->u2.s.RedirectTClass); + + PrintFunc(dest, "%*sTrap: LID: 0x%04x GID: 0x%016"PRIx64":0x%016"PRIx64"\n", + indent, "", + pClassPortInfo->TrapLID, + pClassPortInfo->TrapGID.AsReg64s.H, + pClassPortInfo->TrapGID.AsReg64s.L); + PrintFunc(dest, "%*s QP: 0x%06x QKey: 0x%08x PKey: 0x%04x SL: %2u\n", + indent, "", + pClassPortInfo->u5.s.TrapQP, + pClassPortInfo->Trap_Q_Key, + pClassPortInfo->Trap_P_Key, + pClassPortInfo->u4.s.TrapSL); + PrintFunc(dest, "%*s FlowLabel: 0x%05x HopLimit: 0x%02x TClass: 0x%02x\n", + indent, "", + pClassPortInfo->u4.s.TrapFlowLabel, + pClassPortInfo->u5.s.TrapHopLimit, + pClassPortInfo->u4.s.TrapTClass); +} + +void PrintClassPortInfo(PrintDest_t *dest, int indent, const IB_CLASS_PORT_INFO *pClassPortInfo) +{ + PrintClassPortInfo2(dest, indent, pClassPortInfo, FormatClassPortInfoCapMask, FormatClassPortInfoCapMask2); +} + +void PrintMad(PrintDest_t *dest, int indent, const MAD *pMad) +{ + switch (pMad->common.MgmtClass) { + case MCLASS_SM_LID_ROUTED: + case MCLASS_SM_DIRECTED_ROUTE: + PrintSmp(dest, indent, (const SMP*)pMad); + break; + case MCLASS_SUBN_ADM: + case MCLASS_PERF: + case MCLASS_BM: + case MCLASS_DEV_MGT: + case MCLASS_COMM_MGT: + case MCLASS_SNMP: + case MCLASS_DEV_CONF_MGT: + case MCLASS_DTA: + case MCLASS_CC: + case MCLASS_VFI_PM: + default: + PrintMadHeader(dest, indent, &pMad->common); + // TBD hex dump of Data + break; + } +} + +// TBD void PrintNotice(PrintDest_t *dest, int indent, const NOTICE *pNotice) +// TBD also trap 64-67 details +// +// TBD fix opamgt to dump mads using IbPrint +// add a raw hex dump to IbPrint +// add a MAD dump to IbPrint, decode mad header and output in correct format +// for all but SA and PA RMPP mads. diff --git a/IbPrint/sa.c b/IbPrint/sa.c new file mode 100644 index 0000000..d3d7c59 --- /dev/null +++ b/IbPrint/sa.c @@ -0,0 +1,347 @@ +/* BEGIN_ICS_COPYRIGHT7 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT7 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +#include +#include +#include +#include +#include +#include +#include "ibprint.h" + +// Prints a path record with extended information. (Currently, just the SID.) +void PrintExtendedPathRecord(PrintDest_t *dest, int indent, const IB_PATH_RECORD *pPathRecord) +{ + PrintFunc(dest, "%*sSID: 0x%016"PRIx64"\n", + indent, "", + pPathRecord->ServiceID); + + PrintPathRecord(dest,indent,pPathRecord); +} + + char buf[8]; +// one print function for each SA query OutputType +void PrintPathRecord(PrintDest_t *dest, int indent, const IB_PATH_RECORD *pPathRecord) +{ + char buf[8]; + PrintFunc(dest, "%*sSGID: 0x%016"PRIx64":0x%016"PRIx64"\n", + indent, "", + pPathRecord->SGID.Type.Global.SubnetPrefix, + pPathRecord->SGID.Type.Global.InterfaceID); + PrintFunc(dest, "%*sDGID: 0x%016"PRIx64":0x%016"PRIx64"\n", + indent, "", + pPathRecord->DGID.Type.Global.SubnetPrefix, + pPathRecord->DGID.Type.Global.InterfaceID); + PrintFunc(dest, "%*sSLID: 0x%04x DLID: 0x%04x Reversible: %s PKey: 0x%04x\n", + indent, "", pPathRecord->SLID, pPathRecord->DLID, + pPathRecord->Reversible?"Y":"N", pPathRecord->P_Key); + if (IsGlobalRoute(pPathRecord)) { + // Technically Raw is not part of GRH, but it too is not used + PrintFunc(dest, "%*sRaw: %s FlowLabel: 0x%05x HopLimit: 0x%02x TClass: 0x%02x\n", + indent, "", pPathRecord->u1.s.RawTraffic?"Y":"N", + pPathRecord->u1.s.FlowLabel, pPathRecord->u1.s.HopLimit, + pPathRecord->TClass); + } + FormatTimeoutMult(buf, pPathRecord->PktLifeTime); + PrintFunc(dest, "%*sSL: %2u Mtu: %5s Rate: %4s PktLifeTime: %s Pref: %d\n", + indent, "", pPathRecord->u2.s.SL, IbMTUToText(pPathRecord->Mtu), + StlStaticRateToText(pPathRecord->Rate), buf, + pPathRecord->Preference); +} + +void PrintNodeRecord(PrintDest_t *dest, int indent, const IB_NODE_RECORD *pNodeRecord) +{ + PrintFunc(dest, "%*sLID: 0x%04x Type: %s Name: %.*s\n", + indent, "", pNodeRecord->RID.s.LID, + StlNodeTypeToText(pNodeRecord->NodeInfoData.NodeType), + NODE_DESCRIPTION_ARRAY_SIZE, + pNodeRecord->NodeDescData.NodeString); + PrintFunc(dest, "%*sPorts: %d PortNum: %d PartitionCap: %d\n", + indent, "", pNodeRecord->NodeInfoData.NumPorts, + pNodeRecord->NodeInfoData.u1.s.LocalPortNum, + pNodeRecord->NodeInfoData.PartitionCap + ); + PrintFunc(dest, "%*sNodeGuid: 0x%016"PRIx64" PortGuid: 0x%016"PRIx64"\n", + indent, "", + pNodeRecord->NodeInfoData.NodeGUID, + pNodeRecord->NodeInfoData.PortGUID); + PrintFunc(dest, "%*sSystemImageGuid: 0x%016"PRIx64"\n", + indent, "", pNodeRecord->NodeInfoData.SystemImageGUID); + PrintFunc(dest, "%*sBaseVersion: %d SmaVersion: %d VendorID: 0x%x DeviceId: 0x%x Revision: 0x%x\n", + indent, "", pNodeRecord->NodeInfoData.BaseVersion, + pNodeRecord->NodeInfoData.ClassVersion, + pNodeRecord->NodeInfoData.u1.s.VendorID, + pNodeRecord->NodeInfoData.DeviceID, + pNodeRecord->NodeInfoData.Revision); +} + +void PrintPortInfoRecord(PrintDest_t *dest, int indent, const IB_PORTINFO_RECORD *pPortInfoRecord) +{ + const PORT_INFO *pPortInfo = &pPortInfoRecord->PortInfoData; + + PrintFunc(dest, "%*sLID: 0x%04x PortNum: %d LocalPortNum: %d\n", + indent, "", pPortInfoRecord->RID.s.EndPortLID, + pPortInfoRecord->RID.s.PortNum, pPortInfo->LocalPortNum); + PrintPortInfo(dest, indent, pPortInfo, 0, 0); +} + +void PrintSMInfoRecord(PrintDest_t *dest, int indent, const IB_SMINFO_RECORD *pSMInfoRecord) +{ + PrintSMInfo(dest, indent, &pSMInfoRecord->SMInfoData, + pSMInfoRecord->RID.s.LID); +} + +void PrintLinkRecord(PrintDest_t *dest, int indent, const IB_LINK_RECORD *pLinkRecord) +{ + PrintFunc(dest, "%*sLID: 0x%04x -> 0x%04x Port: %3u -> %3u\n", + indent, "", + pLinkRecord->RID.FromLID, pLinkRecord->ToLID, + pLinkRecord->RID.FromPort, pLinkRecord->ToPort); +} + +void PrintTraceRecord(PrintDest_t *dest, int indent, const IB_TRACE_RECORD *pTraceRecord) +{ + PrintFunc(dest, "%*sGIDPrefix: 0x%016"PRIx64"\n", + indent, "", pTraceRecord->GIDPrefix); + PrintFunc(dest, "%*sIDGeneration: 0x%04x\n", + indent, "", pTraceRecord->IDGeneration); + PrintFunc(dest, "%*sNodeType: %s\n", + indent, "", StlNodeTypeToText(pTraceRecord->NodeType)); + PrintFunc(dest, "%*sNodeID: 0x%016"PRIx64" ChassisID: %016"PRIx64"\n", + indent, "", pTraceRecord->NodeID, pTraceRecord->ChassisID); + PrintFunc(dest, "%*sEntryPortID: 0x%016"PRIx64" ExitPortID: %016"PRIx64"\n", + indent, "", pTraceRecord->EntryPortID, pTraceRecord->ExitPortID); + PrintFunc(dest, "%*sEntryPort: 0x%02x ExitPort: 0x%02x\n", + indent, "", pTraceRecord->EntryPort, pTraceRecord->ExitPort); +} + +void PrintSwitchInfoRecord(PrintDest_t *dest, int indent, const IB_SWITCHINFO_RECORD *pSwitchInfoRecord) +{ + PrintSwitchInfo(dest, indent, &pSwitchInfoRecord->SwitchInfoData, + pSwitchInfoRecord->RID.s.LID); +} + +void PrintLinearFDBRecord(PrintDest_t *dest, int indent, const IB_LINEAR_FDB_RECORD *pLinearFDBRecord) +{ + PrintFunc(dest, "%*sLID: 0x%04x BlockNum: %5u\n", + indent, "", pLinearFDBRecord->RID.s.LID, + pLinearFDBRecord->RID.s.BlockNum); + PrintLinearFDB(dest, indent, &pLinearFDBRecord->LinearFdbData, + pLinearFDBRecord->RID.s.BlockNum); +} + +void PrintRandomFDBRecord(PrintDest_t *dest, int indent, const IB_RANDOM_FDB_RECORD *pRandomFDBRecord) +{ + PrintFunc(dest, "%*sLID: 0x%04x BlockNum: %5u\n", + indent, "", pRandomFDBRecord->RID.s.LID, + pRandomFDBRecord->RID.s.BlockNum); + PrintRandomFDB(dest, indent, &pRandomFDBRecord->RandomFdbData, + pRandomFDBRecord->RID.s.BlockNum); +} + +void PrintMCastFDBRecord(PrintDest_t *dest, int indent, const IB_MCAST_FDB_RECORD *pMCastFDBRecord) +{ + PrintFunc(dest, "%*sLID: 0x%04x Position: %2u BlockNum: %5u\n", + indent, "", pMCastFDBRecord->RID.s.LID, + pMCastFDBRecord->RID.s.Position, + pMCastFDBRecord->RID.s.BlockNum); + PrintMCastFDB(dest, indent, &pMCastFDBRecord->MCastFdbData, + pMCastFDBRecord->RID.s.BlockNum); +} + +void PrintVLArbTableRecord(PrintDest_t *dest, int indent, const IB_VLARBTABLE_RECORD *pVLArbTableRecord) +{ + PrintFunc(dest, "%*sLID: 0x%04x OutputPortNum: %2u BlockNum: %2u (%s)\n", + indent, "", + pVLArbTableRecord->RID.s.LID, + pVLArbTableRecord->RID.s.OutputPortNum, + pVLArbTableRecord->RID.s.BlockNum, + pVLArbTableRecord->RID.s.BlockNum == 1?"Low Pri lower": + pVLArbTableRecord->RID.s.BlockNum == 2?"Low Pri upper": + pVLArbTableRecord->RID.s.BlockNum == 3?"High Pri lower": + pVLArbTableRecord->RID.s.BlockNum == 4?"High Pri upper": + "Unknown" + ); + PrintVLArbTable(dest, indent, &pVLArbTableRecord->VLArbData, + pVLArbTableRecord->RID.s.BlockNum); +} + +void PrintPKeyTableRecord(PrintDest_t *dest, int indent, const IB_P_KEY_TABLE_RECORD *pPKeyTableRecord) +{ + PrintFunc(dest, "%*sLID: 0x%04x PortNum: %2u BlockNum: %2u\n", + indent, "", pPKeyTableRecord->RID.s.LID, + pPKeyTableRecord->RID.s.PortNum, + pPKeyTableRecord->RID.s.BlockNum); + PrintPKeyTable(dest, indent, &pPKeyTableRecord->PKeyTblData, + pPKeyTableRecord->RID.s.BlockNum); +} + +static char HexToChar(uint8 c) +{ + if (c >= ' ' && c <= '~') + return (char)c; + else + return '.'; +} + +static void FormatChars(char *buf, const uint8* data, uint32 len) +{ + uint32 j; + int offset = 0; + + for (j=0; jRID.ServiceID, + pServiceRecord->RID.ServiceGID.Type.Global.SubnetPrefix, + pServiceRecord->RID.ServiceGID.Type.Global.InterfaceID, + pServiceRecord->RID.ServiceP_Key); + if (pServiceRecord->ServiceLease == SERVICE_LEASE_INFINITE) + strcpy(buf, "Infinite"); + else + // %6d not quite big enough for uint32, but will cover most non-infinite + // practical values + sprintf(buf, "%6d s", pServiceRecord->ServiceLease); + PrintFunc(dest, "%*sLease: %s Name: %s\n", + indent, "", buf, pServiceRecord->ServiceName); + // dump service data + offset=sprintf(buf, "Data8: "); + for (j=0; j<16; ++j) + offset+=sprintf(&buf[offset], " %02x", pServiceRecord->ServiceData8[j]); + offset+=sprintf(&buf[offset], " "); + FormatChars(&buf[offset], pServiceRecord->ServiceData8, 16); + PrintFunc(dest, "%*s%s\n", indent, "", buf); + + offset=sprintf(buf, "Data16:"); + for (j=0; j<8; ++j) + offset+=sprintf(&buf[offset], " %04x", pServiceRecord->ServiceData16[j]); + offset+=sprintf(&buf[offset], " "); + FormatChars(&buf[offset], (uint8*)pServiceRecord->ServiceData16, 16); + PrintFunc(dest, "%*s%s\n", indent, "", buf); + + offset=sprintf(buf, "Data32:"); + for (j=0; j<4; ++j) + offset+=sprintf(&buf[offset], " %08x", pServiceRecord->ServiceData32[j]); + offset+=sprintf(&buf[offset], " "); + FormatChars(&buf[offset], (uint8*)pServiceRecord->ServiceData32, 16); + PrintFunc(dest, "%*s%s\n", indent, "", buf); + + offset=sprintf(buf, "Data64:"); + for (j=0; j<2; ++j) + offset+=sprintf(&buf[offset], " %016"PRIx64, pServiceRecord->ServiceData64[j]); + offset+=sprintf(&buf[offset], " "); + FormatChars(&buf[offset], (uint8*)pServiceRecord->ServiceData64, 16); + PrintFunc(dest, "%*s%s\n", indent, "", buf); +} + +void PrintMcMemberRecord(PrintDest_t *dest, int indent, const IB_MCMEMBER_RECORD *pMcMemberRecord) +{ + char buf[8]; + PrintFunc(dest, "%*sGID: 0x%016"PRIx64":0x%016"PRIx64"\n", + indent, "", + pMcMemberRecord->RID.MGID.AsReg64s.H, + pMcMemberRecord->RID.MGID.AsReg64s.L); + PrintFunc(dest, "%*sPortGid: 0x%016"PRIx64":0x%016"PRIx64" Membership: %s%s%s\n", + indent, "", + pMcMemberRecord->RID.PortGID.Type.Global.SubnetPrefix, + pMcMemberRecord->RID.PortGID.Type.Global.InterfaceID, + pMcMemberRecord->JoinFullMember?"Full ":"", + pMcMemberRecord->JoinNonMember?"Non ":"", + pMcMemberRecord->JoinSendOnlyMember?"Sendonly ":""); + FormatTimeoutMult(buf, pMcMemberRecord->PktLifeTime); + PrintFunc(dest, "%*sMLID: 0x%08x PKey: 0x%04x Mtu: %5s Rate: %4s PktLifeTime: %s\n", + indent, "", + MCAST16_TO_MCAST32(pMcMemberRecord->MLID), pMcMemberRecord->P_Key, + IbMTUToText(pMcMemberRecord->Mtu), + IbStaticRateToText(pMcMemberRecord->Rate), + buf); + PrintFunc(dest, "%*sQKey: 0x%08x SL: %2u FlowLabel: 0x%05x HopLimit: 0x%02x TClass: 0x%02x\n", + indent, "", + pMcMemberRecord->Q_Key, pMcMemberRecord->u1.s.SL, + pMcMemberRecord->u1.s.FlowLabel, pMcMemberRecord->u1.s.HopLimit, + pMcMemberRecord->TClass); + +} + +void PrintInformInfo(PrintDest_t *dest, int indent, const IB_INFORM_INFO *pInformInfo) +{ + if (pInformInfo->IsGeneric) + { + char buf[8]; + PrintFunc(dest, "%*s%sSubcribe: Type: %8s Generic: Trap: %5d QPN: 0x%06x\n", + indent, "", + pInformInfo->Subscribe?"":"Un", + IbNoticeTypeToText(pInformInfo->Type), + pInformInfo->u.Generic.TrapNumber, + pInformInfo->u.Generic.u2.s.QPNumber); + FormatTimeoutMult(buf, pInformInfo->u.Generic.u2.s.RespTimeValue); + PrintFunc(dest, "%*sRespTime: %s Producer: %s\n", + indent, "", buf, + StlNodeTypeToText(pInformInfo->u.Generic.u.s.ProducerType)); + } else { + char buf[8]; + FormatTimeoutMult(buf, pInformInfo->u.Generic.u2.s.RespTimeValue); + PrintFunc(dest, "%*s%sSubcribe: Type: %8s VendorId: 0x%04x DeviceId: 0x%04x QPN: 0x%06x\n", + indent, "", + pInformInfo->Subscribe?"":"Un", + IbNoticeTypeToText(pInformInfo->Type), + pInformInfo->u.Vendor.u.s.VendorID, + pInformInfo->u.Vendor.DeviceID, + pInformInfo->u.Vendor.u2.s.QPNumber); + PrintFunc(dest, "%*sRespTime: %s\n", + indent, "", + buf); + } + PrintFunc(dest, "%*sGID: 0x%016"PRIx64":0x%016"PRIx64" LIDs: 0x%04x - 0x%04x\n", + indent, "", + pInformInfo->GID.AsReg64s.H, + pInformInfo->GID.AsReg64s.L, + pInformInfo->LIDRangeBegin, + pInformInfo->LIDRangeEnd); +} + +void PrintInformInfoRecord(PrintDest_t *dest, int indent, const IB_INFORM_INFO_RECORD *pInformInfoRecord) +{ + PrintFunc(dest, "%*sSubGID: 0x%016"PRIx64":0x%016"PRIx64" Enum: 0x%04x\n", + indent, "", + pInformInfoRecord->RID.SubscriberGID.Type.Global.SubnetPrefix, + pInformInfoRecord->RID.SubscriberGID.Type.Global.InterfaceID, + pInformInfoRecord->RID.Enum); + PrintInformInfo(dest, indent, &pInformInfoRecord->InformInfoData); +} diff --git a/IbPrint/sd.c b/IbPrint/sd.c new file mode 100644 index 0000000..ddbd8ad --- /dev/null +++ b/IbPrint/sd.c @@ -0,0 +1,709 @@ +/* BEGIN_ICS_COPYRIGHT7 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT7 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +#include +#include +#include +#include +#include +#include +#include "ibprint.h" +#include "ib_sd_priv.h" +#include "stl_sd.h" +#include "stl_print.h" + +// display the results from a query +// Note: csv is ignored for all but OutputTypeVfInfoRecord +void PrintQueryResultValue(PrintDest_t *dest, int indent, PrintDest_t *dbgDest, + QUERY_RESULT_TYPE OutputType, int csv, + const QUERY_RESULT_VALUES *pResult) +{ + uint32 i; + + if (dbgDest) { + PrintFunc(dbgDest, "OutputType (0x%x): %s\n", OutputType, + iba_sd_query_result_type_msg(OutputType)); + PrintFunc(dbgDest, "MadStatus 0x%x: %s\n", pResult->MadStatus, + iba_sd_mad_status_msg(pResult->MadStatus)); + PrintFunc(dbgDest, "%d Bytes Returned\n", pResult->ResultDataSize); + } + switch ((int)OutputType) + { + case OutputTypeSystemImageGuid: + case OutputTypeNodeGuid: + case OutputTypePortGuid: + case OutputTypeStlSystemImageGuid: + case OutputTypeStlNodeGuid: + case OutputTypeStlPortGuid: + { + GUID_RESULTS *p = (GUID_RESULTS*)pResult->QueryResult; + for (i=0; iNumGuids; ++i) + { + PrintGuid(dest, indent, p->Guids[i]); + } + break; + } + case OutputTypeClassPortInfo: + { + IB_CLASS_PORT_INFO_RESULTS *p = (IB_CLASS_PORT_INFO_RESULTS*)pResult->QueryResult; + + /* There should never be more than 1 ClassPortInfo in the results. */ + if (p->NumClassPortInfo) + PrintClassPortInfo2(dest, indent, p->ClassPortInfo, + StlSaClassPortInfoCapMask, StlSaClassPortInfoCapMask2); + break; + } + case OutputTypeStlClassPortInfo: + { + STL_CLASS_PORT_INFO_RESULT *p = (STL_CLASS_PORT_INFO_RESULT*)pResult->QueryResult; + + /* There should never be more than 1 ClassPortInfo in the results. */ + if (p->NumClassPortInfo) + PrintStlClassPortInfo(dest, indent, &p->ClassPortInfo, MCLASS_SUBN_ADM); + break; + } + case OutputTypeStlFabricInfoRecord: + { + STL_FABRICINFO_RECORD_RESULT *p = (STL_FABRICINFO_RECORD_RESULT*)pResult->QueryResult; + + /* There should never be more than 1 FaricInfoRecord in the results. */ + if (p->NumFabricInfoRecords) + PrintStlFabricInfoRecord(dest, indent, &p->FabricInfoRecord); + break; + } + case OutputTypeStlLid: + { + STL_LID_RESULTS *p = (STL_LID_RESULTS*)pResult->QueryResult; + for (i=0; iNumLids; ++i) + { + PrintStlLid(dest, indent, p->Lids[i], 0); + } + break; + } + case OutputTypeGid: + { + GID_RESULTS *p = (GID_RESULTS*)pResult->QueryResult; + for (i=0; iNumGids; ++i) + { + PrintGid(dest, indent, &p->Gids[i]); + } + break; + } + case OutputTypeNodeDesc: + { + NODEDESC_RESULTS *p = (NODEDESC_RESULTS*)pResult->QueryResult; + for (i=0; iNumDescs; ++i) + { + PrintNodeDesc(dest, indent, &p->NodeDescs[i]); + } + break; + } + case OutputTypeStlNodeDesc: + { + STL_NODEDESC_RESULTS *p = (STL_NODEDESC_RESULTS*)pResult->QueryResult; + for (i=0; iNumDescs; ++i) + { + PrintStlNodeDesc(dest, indent, &p->NodeDescs[i], 0); + } + break; + } + case OutputTypePathRecord: + { + PATH_RESULTS *p = (PATH_RESULTS*)pResult->QueryResult; + for (i=0; iNumPathRecords; ++i) + { + if (i) PrintSeparator(dest); + PrintPathRecord(dest, indent, &p->PathRecords[i]); + } + break; + } + case OutputTypeNodeRecord: + { + NODE_RECORD_RESULTS *p = (NODE_RECORD_RESULTS*)pResult->QueryResult; + for (i=0; iNumNodeRecords; ++i) + { + if (i) PrintSeparator(dest); + PrintNodeRecord(dest, indent, &p->NodeRecords[i]); + } + break; + } + case OutputTypeStlNodeRecord: + { + STL_NODE_RECORD_RESULTS *p = (STL_NODE_RECORD_RESULTS*)pResult->QueryResult; + for (i=0; iNumNodeRecords; ++i) + { + if (i) PrintSeparator(dest); + PrintStlNodeRecord(dest, indent, &p->NodeRecords[i]); + } + break; + } + case OutputTypePortInfoRecord: + { + PORTINFO_RECORD_RESULTS *p = (PORTINFO_RECORD_RESULTS*)pResult->QueryResult; + for (i=0; iNumPortInfoRecords; ++i) + { + if (i) PrintSeparator(dest); + PrintPortInfoRecord(dest, indent, &p->PortInfoRecords[i]); + } + break; + } + case OutputTypeStlPortInfoRecord: + { + STL_PORTINFO_RECORD_RESULTS *p = (STL_PORTINFO_RECORD_RESULTS*)pResult->QueryResult; + for (i=0; iNumPortInfoRecords; ++i) + { + if (i) PrintSeparator(dest); + PrintStlPortInfoRecord(dest, indent, &p->PortInfoRecords[i]); + } + break; + } + case OutputTypeSMInfoRecord: + { + SMINFO_RECORD_RESULTS *p = (SMINFO_RECORD_RESULTS*)pResult->QueryResult; + for (i=0; iNumSMInfoRecords; ++i) + { + if (i) PrintSeparator(dest); + PrintSMInfoRecord(dest, indent, &p->SMInfoRecords[i]); + } + break; + } + case OutputTypeStlSMInfoRecord: + { + STL_SMINFO_RECORD_RESULTS *p = (STL_SMINFO_RECORD_RESULTS*)pResult->QueryResult; + for (i=0; iNumSMInfoRecords; ++i) + { + if (i) PrintSeparator(dest); + PrintStlSMInfo(dest, indent, &(p->SMInfoRecords[i].SMInfo), + p->SMInfoRecords[i].RID.LID, 0); + } + break; + } + case OutputTypeLinkRecord: + { + LINK_RECORD_RESULTS *p = (LINK_RECORD_RESULTS*)pResult->QueryResult; + for (i=0; iNumLinkRecords; ++i) + { + PrintLinkRecord(dest, indent, &p->LinkRecords[i]); + } + break; + } + case OutputTypeStlLinkRecord: + { + STL_LINK_RECORD_RESULTS *p = (STL_LINK_RECORD_RESULTS*)pResult->QueryResult; + for (i=0; iNumLinkRecords; ++i) + { + PrintStlLinkRecord(dest, indent, &p->LinkRecords[i]); + } + break; + } + case OutputTypeServiceRecord: + { + SERVICE_RECORD_RESULTS *p = (SERVICE_RECORD_RESULTS*)pResult->QueryResult; + for (i=0; iNumServiceRecords; ++i) + { + if (i) PrintSeparator(dest); + PrintServiceRecord(dest, indent, &p->ServiceRecords[i]); + } + break; + } + case OutputTypeMcMemberRecord: + { + MCMEMBER_RECORD_RESULTS *p = (MCMEMBER_RECORD_RESULTS*)pResult->QueryResult; + for (i=0; iNumMcMemberRecords; ++i) + { + if (i) PrintSeparator(dest); + PrintMcMemberRecord(dest, indent, &p->McMemberRecords[i]); + } + break; + } + case OutputTypeInformInfoRecord: + { + INFORM_INFO_RECORD_RESULTS *p = (INFORM_INFO_RECORD_RESULTS*)pResult->QueryResult; + for (i=0; iNumInformInfoRecords; ++i) + { + if (i) PrintSeparator(dest); + PrintInformInfoRecord(dest, indent, &p->InformInfoRecords[i]); + } + break; + } + case OutputTypeStlInformInfoRecord: + { + STL_INFORM_INFO_RECORD_RESULTS *p = (STL_INFORM_INFO_RECORD_RESULTS*)pResult->QueryResult; + for (i=0; iNumInformInfoRecords; ++i) + { + if (i) PrintSeparator(dest); + PrintStlInformInfoRecord(dest, indent, &p->InformInfoRecords[i]); + } + break; + } + case OutputTypeStlTraceRecord: + { + STL_TRACE_RECORD_RESULTS *p = (STL_TRACE_RECORD_RESULTS*)pResult->QueryResult; + for (i=0; iNumTraceRecords; ++i) + { + if (i) PrintSeparator(dest); + PrintStlTraceRecord(dest, indent, &p->TraceRecords[i]); + } + break; + } + case OutputTypeStlSCSCTableRecord: + { + STL_SC_MAPPING_TABLE_RECORD_RESULTS *p = (STL_SC_MAPPING_TABLE_RECORD_RESULTS*)pResult->QueryResult; + uint32_t lid = p->SCSCRecords[0].RID.LID; + for (i=0; iNumSCSCTableRecords; ++i) + { + if (lid!=p->SCSCRecords[i].RID.LID) { + PrintSeparator(dest); + lid=p->SCSCRecords[i].RID.LID; + } + PrintStlSCSCTableRecord(dest, indent, p->SCSCRecords[i].RID_Secondary, &p->SCSCRecords[i]); + } + break; + } + case OutputTypeStlSLSCTableRecord: + { + STL_SL2SC_MAPPING_TABLE_RECORD_RESULTS *p = (STL_SL2SC_MAPPING_TABLE_RECORD_RESULTS*)pResult->QueryResult; + uint32_t lid = p->SLSCRecords[0].RID.LID; + for (i=0; iNumSLSCTableRecords; ++i) + { + if (lid!=p->SLSCRecords[i].RID.LID) { + PrintSeparator(dest); + lid=p->SLSCRecords[i].RID.LID; + } + PrintStlSLSCTableRecord(dest, indent, &p->SLSCRecords[i]); + } + break; + } + case OutputTypeStlSCSLTableRecord: + { + STL_SC2SL_MAPPING_TABLE_RECORD_RESULTS *p = (STL_SC2SL_MAPPING_TABLE_RECORD_RESULTS*)pResult->QueryResult; + uint32_t lid = p->SCSLRecords[0].RID.LID; + for (i=0; iNumSCSLTableRecords; i++) { + if (lid!=p->SCSLRecords[i].RID.LID) { + PrintSeparator(dest); + lid=p->SCSLRecords[i].RID.LID; + } + PrintStlSCSLTableRecord(dest, indent, &p->SCSLRecords[i]); + } + break; + } + case OutputTypeStlSCVLtTableRecord: + { + STL_SC2PVL_T_MAPPING_TABLE_RECORD_RESULTS *p = (STL_SC2PVL_T_MAPPING_TABLE_RECORD_RESULTS*)pResult->QueryResult; + uint32_t lid = p->SCVLtRecords[0].RID.LID; + for (i=0; iNumSCVLtTableRecords; i++) { + if (lid!=p->SCVLtRecords[i].RID.LID) { + PrintSeparator(dest); + lid=p->SCVLtRecords[i].RID.LID; + } + PrintStlSCVLxTableRecord(dest, indent, &p->SCVLtRecords[i], STL_MCLASS_ATTRIB_ID_SC_VLT_MAPPING_TABLE); + } + break; + } + case OutputTypeStlSCVLntTableRecord: + { + STL_SC2PVL_NT_MAPPING_TABLE_RECORD_RESULTS *p = (STL_SC2PVL_NT_MAPPING_TABLE_RECORD_RESULTS*)pResult->QueryResult; + uint32_t lid=p->SCVLntRecords[0].RID.LID; + for (i=0; iNumSCVLntTableRecords; i++) { + if (lid!=p->SCVLntRecords[i].RID.LID) { + PrintSeparator(dest); + lid=p->SCVLntRecords[i].RID.LID; + } + PrintStlSCVLxTableRecord(dest, indent, &p->SCVLntRecords[i], STL_MCLASS_ATTRIB_ID_SC_VLNT_MAPPING_TABLE); + } + break; + } + case OutputTypeStlSCVLrTableRecord: + { + STL_SC2PVL_R_MAPPING_TABLE_RECORD_RESULTS *p = (STL_SC2PVL_R_MAPPING_TABLE_RECORD_RESULTS*)pResult->QueryResult; + uint32_t lid=p->SCVLrRecords[0].RID.LID; + for (i=0; iNumSCVLrTableRecords; i++) { + if (lid!=p->SCVLrRecords[i].RID.LID) { + PrintSeparator(dest); + lid=p->SCVLrRecords[i].RID.LID; + } + PrintStlSCVLxTableRecord(dest, indent, &p->SCVLrRecords[i], STL_MCLASS_ATTRIB_ID_SC_VLR_MAPPING_TABLE); + } + break; + } + case OutputTypeSwitchInfoRecord: + { + SWITCHINFO_RECORD_RESULTS *p = (SWITCHINFO_RECORD_RESULTS*)pResult->QueryResult; + for (i=0; iNumSwitchInfoRecords; ++i) + { + if (i) PrintSeparator(dest); + PrintSwitchInfoRecord(dest, indent, &p->SwitchInfoRecords[i]); + } + break; + } + case OutputTypeStlSwitchInfoRecord: + { + STL_SWITCHINFO_RECORD_RESULTS *p = (STL_SWITCHINFO_RECORD_RESULTS*)pResult->QueryResult; + for (i=0; iNumSwitchInfoRecords; ++i) + { + if (i) PrintSeparator(dest); + PrintStlSwitchInfoRecord(dest, indent, &p->SwitchInfoRecords[i]); + } + break; + } + case OutputTypeStlLinearFDBRecord: + { + STL_LINEAR_FDB_RECORD_RESULTS *p = (STL_LINEAR_FDB_RECORD_RESULTS*)pResult->QueryResult; + + for (i=0; iNumLinearFDBRecords; ++i) + { + if (i) PrintSeparator(dest); + PrintStlLinearFDBRecord(dest, indent, &p->LinearFDBRecords[i]); + } + break; + } + case OutputTypeRandomFDBRecord: + { + RANDOM_FDB_RECORD_RESULTS *p = (RANDOM_FDB_RECORD_RESULTS*)pResult->QueryResult; + for (i=0; iNumRandomFDBRecords; ++i) + { + if (i) PrintSeparator(dest); + PrintRandomFDBRecord(dest, indent, &p->RandomFDBRecords[i]); + } + break; + } + case OutputTypeStlMCastFDBRecord: + { + STL_MCAST_FDB_RECORD_RESULTS *p = (STL_MCAST_FDB_RECORD_RESULTS*)pResult->QueryResult; + for (i=0; iNumMCastFDBRecords; ++i) + { + if (i) PrintSeparator(dest); + PrintStlMCastFDBRecord(dest, indent, &p->MCastFDBRecords[i]); + } + break; + } + case OutputTypeStlVLArbTableRecord: + { + STL_VLARBTABLE_RECORD_RESULTS *p = (STL_VLARBTABLE_RECORD_RESULTS*)pResult->QueryResult; + for (i=0; iNumVLArbTableRecords; ++i) + { + if (i) PrintSeparator(dest); + PrintStlVLArbTableRecord(dest, indent, &p->VLArbTableRecords[i]); + } + break; + } + case OutputTypeStlPKeyTableRecord: + { + STL_PKEYTABLE_RECORD_RESULTS *p = (STL_PKEYTABLE_RECORD_RESULTS*)pResult->QueryResult; + for (i=0; iNumPKeyTableRecords; ++i) + { + if (i) PrintSeparator(dest); + PrintStlPKeyTableRecord(dest, indent, &p->PKeyTableRecords[i]); + } + break; + } + case OutputTypeStlVfInfoRecord: + { + STL_VFINFO_RECORD_RESULTS *p = (STL_VFINFO_RECORD_RESULTS*)pResult->QueryResult; + + for (i=0; iNumVfInfoRecords; ++i) { + if (csv == 1) { + PrintStlVfInfoRecordCSV(dest, indent, &p->VfInfoRecords[i]); + } else if (csv == 2) { + PrintStlVfInfoRecordCSV2(dest, indent, &p->VfInfoRecords[i]); + } else { + if (i) PrintSeparator(dest); + PrintStlVfInfoRecord(dest, indent, &p->VfInfoRecords[i]); + } + } + break; + } + case OutputTypeStlQuarantinedNodeRecord: + { + STL_QUARANTINED_NODE_RECORD_RESULTS *p = (STL_QUARANTINED_NODE_RECORD_RESULTS*)pResult->QueryResult; + int hasPrinted = 0; + // Loop through and print out spoofing violations first + PrintSeparator(dest); + PrintFunc(dest, "%*sNodes Quarantined Due To Spoofing:\n", indent, ""); + PrintSeparator(dest); + for(i = 0; i < p->NumQuarantinedNodeRecords; ++i) + { + if (i && hasPrinted) PrintSeparator(dest); + + if(p->QuarantinedNodeRecords[i].quarantineReasons & STL_QUARANTINE_REASON_SPOOF_GENERIC) { + PrintQuarantinedNodeRecord(dest, indent, &p->QuarantinedNodeRecords[i]); + hasPrinted = 1; + } + } + + if(!hasPrinted) { + PrintFunc(dest, "%*s None.\n\n", indent, ""); + } else { + hasPrinted = 0; + } + + // Then loop through and print out all other violations + PrintSeparator(dest); + PrintFunc(dest, "%*sNodes Quarantined Due To Other Violations:\n", indent, ""); + PrintSeparator(dest); + for(i = 0; i < p->NumQuarantinedNodeRecords; ++i) + { + if (i && hasPrinted) PrintSeparator(dest); + if(!(p->QuarantinedNodeRecords[i].quarantineReasons & STL_QUARANTINE_REASON_SPOOF_GENERIC)) { + PrintQuarantinedNodeRecord(dest, indent, &p->QuarantinedNodeRecords[i]); + hasPrinted = 1; + } + } + + if(!hasPrinted) { + PrintFunc(dest, "%*s None.\n\n", indent, ""); + } + + break; + } + case OutputTypeStlCongInfoRecord: + { + STL_CONGESTION_INFO_RECORD_RESULTS *p = (STL_CONGESTION_INFO_RECORD_RESULTS*)pResult->QueryResult; + for(i = 0; i < p->NumRecords; ++i) + { + if (i) PrintSeparator(dest); + PrintStlCongestionInfoRecord(dest, indent, &p->Records[i]); + } + break; + } + case OutputTypeStlSwitchCongRecord: + { + STL_SWITCH_CONGESTION_SETTING_RECORD_RESULTS *p = (STL_SWITCH_CONGESTION_SETTING_RECORD_RESULTS*)pResult->QueryResult; + for(i = 0; i < p->NumRecords; ++i) + { + if (i) PrintSeparator(dest); + PrintStlSwitchCongestionSettingRecord(dest, indent, &p->Records[i]); + } + break; + } + case OutputTypeStlSwitchPortCongRecord: + { + STL_SWITCH_PORT_CONGESTION_SETTING_RECORD_RESULTS *p = (STL_SWITCH_PORT_CONGESTION_SETTING_RECORD_RESULTS*)pResult->QueryResult; + for(i = 0; i < p->NumRecords; ++i) + { + if (i) PrintSeparator(dest); + PrintStlSwitchPortCongestionSettingRecord(dest, indent, &p->Records[i]); + } + break; + } + case OutputTypeStlHFICongRecord: + { + STL_HFI_CONGESTION_SETTING_RECORD_RESULTS *p = (STL_HFI_CONGESTION_SETTING_RECORD_RESULTS*)pResult->QueryResult; + for(i = 0; i < p->NumRecords; ++i) + { + if (i) PrintSeparator(dest); + PrintStlHfiCongestionSettingRecord(dest, indent, &p->Records[i]); + } + break; + } + case OutputTypeStlHFICongCtrlRecord: + { + STL_HFI_CONGESTION_CONTROL_TABLE_RECORD_RESULTS *p = (STL_HFI_CONGESTION_CONTROL_TABLE_RECORD_RESULTS*)pResult->QueryResult; + for(i = 0; i < p->NumRecords; ++i) + { + if (i) PrintSeparator(dest); + PrintStlHfiCongestionControlTabRecord(dest, indent, &p->Records[i]); + } + break; + } + case OutputTypeStlBufCtrlTabRecord: + { + STL_BUFFER_CONTROL_TABLE_RECORD_RESULTS *p = (STL_BUFFER_CONTROL_TABLE_RECORD_RESULTS*)pResult->QueryResult; + for(i = 0; i < p->NumBufferControlRecords; ++i) + { + if (i) PrintSeparator(dest); + PrintBfrCtlTableRecord(dest, indent, &p->BufferControlRecords[i]); + } + break; + } + case OutputTypeStlCableInfoRecord: + { + const uint32 max_records = 2; // Max number of grouped records + // NOTE that CIR.Length is 7 bits (<= 127) + STL_CABLE_INFO_RECORD_RESULTS *p = (STL_CABLE_INFO_RECORD_RESULTS*)pResult->QueryResult; + STL_CABLE_INFO_RECORD *p_rec; + uint32 ct_records = 0; // Count of grouped records + uint8 first_addr = 0; // First CableInfo addr in bf_cable_info + uint8 last_addr = 0; // Last CableInfo addr in bf_cable_info + uint32 prev_lid; + uint8 prev_port; + uint8 prev_addr; + uint8 bf_cable_info[sizeof(STL_CABLE_INFO_RECORD) * max_records]; + for(i = 0; i < p->NumCableInfoRecords; ++i) + { + p_rec = &p->CableInfoRecords[i]; + // Skip unaligned or partial records + if ( ( (p_rec->u1.s.Address != STL_CIB_STD_HIGH_PAGE_ADDR) && + (p_rec->u1.s.Address != STL_CIB_STD_HIGH_PAGE_ADDR + STL_CABLE_INFO_MAXLEN + 1) ) || + (p_rec->Length != STL_CABLE_INFO_MAXLEN) ) + continue; + // Group multiple records for same LID and port into one + if (! ct_records) { + // First record for LID/Port + memset(bf_cable_info, 0, sizeof(bf_cable_info)); + memcpy(bf_cable_info, p_rec, sizeof(STL_CABLE_INFO_RECORD)); + last_addr = 0; + } + else { + if ((p_rec->LID == prev_lid) && (p_rec->Port == prev_port) && + (p_rec->u1.s.Address != prev_addr) && (ct_records < max_records)) { + // Subsequent record for same LID/Port + if (p_rec->u1.s.Address < first_addr) { + memmove( ((STL_CABLE_INFO_RECORD *)bf_cable_info)->Data + first_addr - p_rec->u1.s.Address, + ((STL_CABLE_INFO_RECORD *)bf_cable_info)->Data, + STL_CIR_DATA_SIZE * max_records - (first_addr - p_rec->u1.s.Address) ); + memcpy(bf_cable_info, p_rec, sizeof(STL_CABLE_INFO_RECORD)); + } + else { + memcpy( ((STL_CABLE_INFO_RECORD *)bf_cable_info)->Data + p_rec->u1.s.Address - first_addr, + p_rec->Data, STL_CIR_DATA_SIZE ); + } + } + else { + // Print grouped record + if (i - ct_records) PrintSeparator(dest); + PrintStlCableInfoRecord(dest, indent, (STL_CABLE_INFO_RECORD *)bf_cable_info); + memset(bf_cable_info, 0, sizeof(bf_cable_info)); + memcpy(bf_cable_info, p_rec, sizeof(STL_CABLE_INFO_RECORD)); + last_addr = 0; + ct_records = 0; + } + } + prev_lid = p_rec->LID; + prev_port = p_rec->Port; + prev_addr = p_rec->u1.s.Address; + if (prev_addr > last_addr) + last_addr = prev_addr; + ct_records += 1; + first_addr = ((STL_CABLE_INFO_RECORD *)bf_cable_info)->u1.s.Address; + ((STL_CABLE_INFO_RECORD *)bf_cable_info)->Length = last_addr - first_addr + STL_CIR_DATA_SIZE - 1; + } + if (ct_records) { + if (i - ct_records) PrintSeparator(dest); + PrintStlCableInfoRecord(dest, indent, (STL_CABLE_INFO_RECORD *)bf_cable_info); + } + break; + } + case OutputTypeStlPortGroupRecord: + { + STL_PORT_GROUP_TABLE_RECORD_RESULTS *p = (STL_PORT_GROUP_TABLE_RECORD_RESULTS*)pResult->QueryResult; + for(i = 0; i < p->NumRecords; ++i) + { + if (i) PrintSeparator(dest); + PrintStlPortGroupTabRecord(dest, indent, &p->Records[i]); + } + break; + } + case OutputTypeStlPortGroupFwdRecord: + { + STL_PORT_GROUP_FORWARDING_TABLE_RECORD_RESULTS *p = (STL_PORT_GROUP_FORWARDING_TABLE_RECORD_RESULTS*)pResult->QueryResult; + for(i = 0; i < p->NumRecords; ++i) + { + if (i) PrintSeparator(dest); + PrintStlPortGroupFwdTabRecord(dest, indent, &p->Records[i]); + } + break; + } + + case OutputTypeStlDeviceGroupMemberRecord: + { + STL_DEVICE_GROUP_MEMBER_RECORD_RESULTS *p = (STL_DEVICE_GROUP_MEMBER_RECORD_RESULTS*)pResult->QueryResult; + for (i=0; i < p->NumRecords; ++i) + { + PrintStlDeviceGroupMemberRecord(dest, indent, &p->Records[i]); + } + break; + } + + case OutputTypeStlDeviceGroupNameRecord: + { + STL_DEVICE_GROUP_NAME_RECORD_RESULTS *p = (STL_DEVICE_GROUP_NAME_RECORD_RESULTS*)pResult->QueryResult; + for (i=0; i < p->NumRecords; ++i) + { + PrintStlDeviceGroupNameRecord(dest, indent, &p->Records[i], i+1); + } + break; + } + + case OutputTypeStlDeviceTreeMemberRecord: + { + STL_DEVICE_TREE_MEMBER_RECORD_RESULTS *p = (STL_DEVICE_TREE_MEMBER_RECORD_RESULTS*)pResult->QueryResult; + for (i=0; i < p->NumRecords; ++i) + { + PrintStlDeviceTreeMemberRecord(dest, indent, &p->Records[i]); + } + break; + } + case OutputTypeStlSwitchCostRecord: + { + STL_SWITCH_COST_RECORD_RESULTS *p = (STL_SWITCH_COST_RECORD_RESULTS*)pResult->QueryResult; + for(i = 0; i < p ->NumRecords; ++i) + { + if (i) PrintSeparator(dest); + PrintStlSwitchCostRecord(dest, indent, &p->Records[i]); + } + } + break; + default: + PrintFunc(dest, "Unsupported OutputType\n"); + } +} + +// display the results from a query +// returns potential exit status: +// 0 - success +// 1 - query failed +// 2 - query failed due to invalid query +// Note: csv is ignored for all but OutputTypeVfInfoRecord +int PrintQueryResult(PrintDest_t *dest, int indent, PrintDest_t *dbgDest, + QUERY_RESULT_TYPE OutputType, int csv, FSTATUS status, + QUERY_RESULT_VALUES *pResult) +{ + int ret = 0; + + if (! pResult || status == FINVALID_PARAMETER) + { + PrintFunc(dest, "%*sFailed: %s\n", indent, "", iba_fstatus_msg(status)); + // for FINVALID_PARAMETER, use special exit status + // will trigger usage output by main + ret = (status == FINVALID_PARAMETER)?2:1; + } else if (pResult->Status != FSUCCESS || pResult->MadStatus!= MAD_STATUS_SUCCESS) { + PrintFunc(dest, "%*sFailed: %s MadStatus 0x%x: %s\n", indent, "", + iba_fstatus_msg(pResult->Status), + pResult->MadStatus, iba_sd_mad_status_msg(pResult->MadStatus)); + ret = 1; + } else if (pResult->ResultDataSize == 0) { + PrintFunc(dest, "%*sNo Records Returned\n", indent, ""); + } else { + PrintQueryResultValue(dest, indent, dbgDest, OutputType, csv, pResult); + } + return (ret); +} diff --git a/IbPrint/sma.c b/IbPrint/sma.c new file mode 100644 index 0000000..d2fb881 --- /dev/null +++ b/IbPrint/sma.c @@ -0,0 +1,624 @@ +/* BEGIN_ICS_COPYRIGHT7 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT7 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +#include +#include +#include +#include +#include +#include +#include "ibprint.h" + +void PrintNodeDesc(PrintDest_t *dest, int indent, const NODE_DESCRIPTION *pNodeDesc) +{ + PrintFunc(dest, "%*s%.*s\n", + indent, "", + NODE_DESCRIPTION_ARRAY_SIZE, pNodeDesc->NodeString); +} + +void PrintNodeInfo(PrintDest_t *dest, int indent, const NODE_INFO *pNodeInfo) +{ + PrintFunc(dest, "%*sType: %s Ports: %d PortNum: %d PartitionCap: %d\n", + indent, "", + StlNodeTypeToText(pNodeInfo->NodeType), pNodeInfo->NumPorts, + pNodeInfo->u1.s.LocalPortNum, pNodeInfo->PartitionCap); + PrintFunc(dest, "%*sNodeGuid: 0x%016"PRIx64" PortGuid: 0x%016"PRIx64"\n", + indent, "", pNodeInfo->NodeGUID, pNodeInfo->PortGUID); + PrintFunc(dest, "%*sSystemImageGuid: 0x%016"PRIx64"\n", + indent, "", pNodeInfo->SystemImageGUID); + PrintFunc(dest, "%*sBaseVersion: %d SmaVersion: %d VendorID: 0x%x DeviceId: 0x%x Revision: 0x%x\n", + indent, "", pNodeInfo->BaseVersion, + pNodeInfo->ClassVersion, pNodeInfo->u1.s.VendorID, + pNodeInfo->DeviceID, pNodeInfo->Revision); +} + +// style=0 or 1 +// TBD - key off portGuid!=0 to decide style instead? +void PrintPortInfo(PrintDest_t *dest, int indent, const PORT_INFO *pPortInfo, EUI64 portGuid, int style) +{ + char tempBuf[9]; + char tempBuf2[9]; + char cbuf[80]; + + PrintFunc(dest, "%*sPortState: %-6s PhysState: %-8s DownDefault: %-5s\n", + indent, "", + IbPortStateToText(pPortInfo->Link.PortState), + IbPortPhysStateToText(pPortInfo->Link.PortPhysicalState), + IbPortDownDefaultToText(pPortInfo->Link.DownDefaultState)); + if (style == 0) { + PrintFunc(dest, "%*sLID: 0x%04x LMC: %u Subnet: 0x%016"PRIx64"\n", + indent, "", + pPortInfo->LID, pPortInfo->s1.LMC, pPortInfo->SubnetPrefix); + } else { + PrintFunc(dest, "%*sLID: 0x%04x LMC: %u\n", + indent, "", pPortInfo->LID, pPortInfo->s1.LMC); + if (portGuid) { + PrintFunc(dest, "%*sSubnet: 0x%016"PRIx64" GUID: 0x%016"PRIx64" GUID Cap: %4u\n", + indent, "", pPortInfo->SubnetPrefix, portGuid, pPortInfo->GUIDCap); + } else { + PrintFunc(dest, "%*sSubnet: 0x%016"PRIx64" GUID Cap: %4u\n", + indent, "", pPortInfo->SubnetPrefix, pPortInfo->GUIDCap); + } + } + FormatTimeoutMult(tempBuf, pPortInfo->Resp.TimeValue); + FormatTimeoutMult(tempBuf2, pPortInfo->Subnet.Timeout); + PrintFunc(dest, "%*sSMLID: 0x%04x SMSL: %2u RespTimeout: %s SubnetTimeout: %s\n", + indent, "", + pPortInfo->MasterSMLID, pPortInfo->s2.MasterSMSL, tempBuf, tempBuf2); + PrintFunc(dest, "%*sM_KEY: 0x%016"PRIx64" Lease: %5u s Protect: %s\n", + indent, "", pPortInfo->M_Key, pPortInfo->M_KeyLeasePeriod, + IbMKeyProtectToText(pPortInfo->s1.M_KeyProtectBits)); + PrintFunc(dest, "%*sMTU: Active: %5s Supported: %5s VL Stall: %u\n", + indent, "", IbMTUToText(pPortInfo->s2.NeighborMTU), + IbMTUToText(pPortInfo->MTU.Cap), pPortInfo->XmitQ.VLStallCount); + PrintFunc(dest, "%*sLinkWidth: Active: %4s Supported: %7s Enabled: %7s\n", + indent, "", + IbLinkWidthToText(pPortInfo->LinkWidth.Active), + IbLinkWidthToText(pPortInfo->LinkWidth.Supported), + IbLinkWidthToText(pPortInfo->LinkWidth.Enabled)); + PrintFunc( dest, "%*sLinkSpeed: Active: %7s Supported: %10s Enabled: %10s\n", + indent, "", + IbLinkSpeedToText(PortDataGetLinkSpeedActiveCombined((PORT_INFO *)pPortInfo)), + IbLinkSpeedToText(PortDataGetLinkSpeedSupportedCombined((PORT_INFO *)pPortInfo)), + IbLinkSpeedToText(PortDataGetLinkSpeedEnabledCombined((PORT_INFO *)pPortInfo)) ); + if (pPortInfo->XmitQ.HOQLife > IB_LIFETIME_MAX) + { + memcpy(tempBuf, "Infinite", 9); + } else { + FormatTimeoutMult(tempBuf, pPortInfo->XmitQ.HOQLife); + } + PrintFunc(dest, "%*sVLs: Active: %-2d Supported: %-2d HOQLife: %s\n", + indent, "", + pPortInfo->s3.OperationalVL, + pPortInfo->VL.s.Cap, tempBuf); + PrintFunc(dest, "%*sVL Arb Cap: High: %4u Low: %4u HiLimit: %4u\n", + indent, "", pPortInfo->VL.ArbitrationHighCap, + pPortInfo->VL.ArbitrationLowCap, pPortInfo->VL.HighLimit); +#if ! GUID_CAP_ALWAYS_ALONE + if (style == 0) +#endif + PrintFunc(dest, "%*sGUID Cap: %4u\n", indent, "", pPortInfo->GUIDCap); + + FormatCapabilityMask(cbuf, pPortInfo->CapabilityMask); + PrintFunc(dest, "%*sCapability 0x%08x: %s\n", + indent, "", + pPortInfo->CapabilityMask.AsReg32, cbuf); + PrintFunc(dest, "%*sViolations: M_Key: %5u P_Key: %5u Q_Key: %5u\n", + indent, "", + pPortInfo->Violations.M_Key, pPortInfo->Violations.P_Key, + pPortInfo->Violations.Q_Key); + PrintFunc(dest, "%*sErrorLimits: Overrun: %2u LocalPhys: %2u DiagCode: 0x%04x\n", + indent, "", + pPortInfo->Errors.Overrun, pPortInfo->Errors.LocalPhys, + pPortInfo->DiagCode); + PrintFunc(dest, "%*sP_Key Enforcement: In: %3s Out: %3s FilterRaw: In: %3s Out: %3s\n", + indent, "", + pPortInfo->s3.PartitionEnforcementInbound?"On":"Off", + pPortInfo->s3.PartitionEnforcementOutbound?"On":"Off", + pPortInfo->s3.FilterRawInbound?"On":"Off", + pPortInfo->s3.FilterRawOutbound?"On":"Off"); +} + +void PrintPortInfoSmp(PrintDest_t *dest, int indent, const SMP *smp, EUI64 portGuid) +{ + const PORT_INFO* pPortInfo = (PORT_INFO *)&(smp->SmpExt.DirectedRoute.SMPData); + + PrintFunc(dest, "%*sPort %u Info\n", indent, "", + smp->common.AttributeModifier & 0xff); + PrintPortInfo(dest, indent+4, pPortInfo, portGuid, 1); +} + +void PrintSMInfo(PrintDest_t *dest, int indent, const SM_INFO *pSMInfo, IB_LID lid) +{ + if (lid) + PrintFunc(dest, "%*sLID: 0x%04x PortGuid: 0x%016"PRIx64" State: %11s\n", + indent, "", lid, pSMInfo->GUID, + IbSMStateToText(pSMInfo->s.SMState)); + else + PrintFunc(dest, "%*sPortGuid: 0x%016"PRIx64" State: %11s\n", + indent, "", pSMInfo->GUID, + IbSMStateToText(pSMInfo->s.SMState)); + PrintFunc(dest, "%*sSM_Key: 0x%016"PRIx64" Priority: %3d ActCount: 0x%08x\n", + indent, "", pSMInfo->SM_Key, + pSMInfo->s.Priority, pSMInfo->ActCount); +} + +void PrintSwitchInfo(PrintDest_t *dest, int indent, const SWITCH_INFO *pSwitchInfo, IB_LID lid) +{ + char buf[8]; + + if (lid) + PrintFunc(dest, "%*sLID: 0x%04x\n", indent, "", lid); + + PrintFunc(dest, "%*sLinearFDBCap: %5u LinearFDBTop: 0x%04x MCFDBCap: %5u MCFDBTop: 0x%04x\n", + indent, "", + pSwitchInfo->LinearFDBCap, pSwitchInfo->LinearFDBTop, + pSwitchInfo->MulticastFDBCap, pSwitchInfo->MulticastFDBTop); + FormatTimeoutMult(buf, pSwitchInfo->u1.s.LifeTimeValue); + PrintFunc(dest, "%*sRandomFDBCap: %5u LIDsPerPort: %5u LifeTime: %s\n", + indent, "", + pSwitchInfo->RandomFDBCap, pSwitchInfo->LIDsPerPort, buf); + PrintFunc(dest, "%*sDefaultPort: %3u DefaultMCPrimaryPort: %3u DefaultMCNotPrimaryPort: %3u\n", + indent, "", + pSwitchInfo->DefaultPort, + pSwitchInfo->DefaultMulticastPrimaryPort, + pSwitchInfo->DefaultMulticastNotPrimaryPort); + PrintFunc(dest, "%*sCapability: 0x%02x: %s%s%s%s%s%s PartEnfCap: %5u PortStateChange: %d\n", + indent, "", + pSwitchInfo->u2.AsReg8, + pSwitchInfo->u2.s.InboundEnforcementCapable?"IE ": "", + pSwitchInfo->u2.s.OutboundEnforcementCapable?"OE ": "", + pSwitchInfo->u2.s.FilterRawPacketInboundCapable?"FI ": "", + pSwitchInfo->u2.s.FilterRawPacketOutboundCapable?"FO ": "", + pSwitchInfo->u2.s.EnhancedPort0?"E0 ": "", + pSwitchInfo->u1.s.OptimizedSLVL?"SLVL ": "", + pSwitchInfo->PartitionEnforcementCap, + pSwitchInfo->u1.s.PortStateChange); +} + +void PrintLinearFDB(PrintDest_t *dest, int indent, const FORWARDING_TABLE *pLinearFDB, uint16 blockNum) +{ + int i; + IB_LID baselid = blockNum*LFT_BLOCK_SIZE; + + for (i=0; iu.Linear.LftBlock[i] != 255) + PrintFunc(dest, "%*s LID 0x%04x -> Port %5u\n", + indent, "", baselid + i, + pLinearFDB->u.Linear.LftBlock[i]); + } +} + +void PrintRandomFDB(PrintDest_t *dest, int indent, const FORWARDING_TABLE *pRandomFDB, uint16 blockNum) +{ + int i; + + for (i=0; iu.Random.RftBlock[i].s.Valid) + { + IB_LID lid = pRandomFDB->u.Random.RftBlock[i].LID; + uint8 lmc = pRandomFDB->u.Random.RftBlock[i].s.LMC; + if (lmc) { + PrintFunc(dest, "%*s LID 0x%04x-0x%04x -> Port %5u\n", + indent, "", lid, lid + (1<u.Random.RftBlock[i].Port); + } else { + PrintFunc(dest, "%*s LID 0x%04x -> Port %5u\n", + indent, "", lid, + pRandomFDB->u.Random.RftBlock[i].Port); + } + } + } +} + +boolean isMCastFDBEmpty(const FORWARDING_TABLE *pMCastFDB) +{ + int i; + + for (i=0; iu.Multicast.MftBlock[i]) + return FALSE; + } + return TRUE; +} + +void PrintMCastFDB(PrintDest_t *dest, int indent, const FORWARDING_TABLE *pMCastFDB, uint16 blockNum) +{ + int i; + IB_LID baselid = blockNum*MFT_BLOCK_SIZE+LID_MCAST_START; + + for (i=0; iu.Multicast.MftBlock[i]) + { + PrintFunc(dest, "%*s LID 0x%04x -> PortMask 0x%04x\n", + indent, "", baselid+i, + pMCastFDB->u.Multicast.MftBlock[i]); + } + } +} + +void PrintMCastFDBSmp(PrintDest_t *dest, int indent, const SMP *smp) +{ + const FORWARDING_TABLE *pMCastFDB = (FORWARDING_TABLE *)&(smp->SmpExt.DirectedRoute.SMPData); + + PrintFunc(dest, "%*sPosition: %2u\n", indent, "", + smp->common.AttributeModifier >> 28); + + PrintMCastFDB(dest, indent, pMCastFDB, smp->common.AttributeModifier & 0x1ff); +} + +boolean isMCastFDBEmptyRows(const FORWARDING_TABLE *pMCastFDB, uint8 numPositions) +{ + int i; + unsigned p; + + for (i=0; i PortMask 0x", baselid+i); + // show the combined mask, MSb to LSb + p=endPosition; + do { + offset += sprintf(&buf[offset], "%04x", pMCastFDB[p-startPosition].u.Multicast.MftBlock[i]); + } while (p-- != startPosition); + PrintFunc(dest, "%*s%s\n", indent, "", buf); + + // show the list of ports that Mask corresponds to + offset = sprintf(buf, " Ports:"); + for (p=startPosition; p<=endPosition; ++p) { + PORTMASK mask = pMCastFDB[p-startPosition].u.Multicast.MftBlock[i]; + if (mask) { + uint8 bit; + for (bit=0; bit 70) { + PrintFunc(dest, "%*s%s\n", indent, "", buf); + offset = sprintf(buf, " "); + } + offset += sprintf(&buf[offset], " %3u", p*MFT_BLOCK_WIDTH+bit); + } + } + } + } + PrintFunc(dest, "%*s%s\n", indent, "", buf); + } + } +} + +void PrintVLArbTable(PrintDest_t *dest, int indent, const VLARBTABLE *pVLArbTable, uint8 blockNum) +{ + uint8 base_index = 0; + int i; + + if (blockNum == 2 || blockNum == 4) + base_index = IB_VLARBTABLE_SIZE; + PrintFunc(dest, "%*s Indx VL Weight\n", indent, ""); + for (i=0; iArbTable[i].Weight) + { + PrintFunc(dest, "%*s %2d %2u %3u\n", + indent, "", base_index+i, + pVLArbTable->ArbTable[i].s.VL, + pVLArbTable->ArbTable[i].Weight); + } + } +} + +void PrintVLArbTableSmp(PrintDest_t *dest, int indent, const SMP *smp, NODE_TYPE nodetype) +{ + VLARBTABLE *pVLArbTable = (VLARBTABLE *)&(smp->SmpExt.DirectedRoute.SMPData); + char buf[40] = ""; + uint32 block = smp->common.AttributeModifier >> 16; + + if (nodetype == STL_NODE_SW) { + + sprintf(buf, "OutputPort: %3u ", smp->common.AttributeModifier & 0xffff); + } + PrintFunc(dest, "%*s%sBlockNum: %2u (%s)\n", indent, "", + buf, block, + block == 1?"Low Pri lower": + block == 2?"Low Pri upper": + block == 3?"High Pri lower": + block == 4?"High Pri upper": + "Unknown" + ); + PrintVLArbTable(dest, indent, pVLArbTable, block); +} + +void PrintPKeyTable(PrintDest_t *dest, int indent, const PARTITION_TABLE *pPKeyTable, uint16 blockNum) +{ + uint16 i; + char buf[81]; + int offset=0; + uint16 index = blockNum*PARTITION_TABLE_BLOCK_SIZE; + + // 8 entries per line + for (i=0; iPartitionTableBlock[i].AsInt16); + } + PrintFunc(dest, "%*s%s\n", indent, "", buf); +} + +void PrintPKeyTableSmp(PrintDest_t *dest, int indent, const SMP *smp, NODE_TYPE nodetype, boolean showHeading, boolean showBlock) +{ + PARTITION_TABLE *pPKeyTable = (PARTITION_TABLE *)&(smp->SmpExt.DirectedRoute.SMPData); + char buf[40] = ""; + uint32 block = smp->common.AttributeModifier & 0xffff; + + if (showHeading) { + if (nodetype == STL_NODE_SW) + sprintf(buf, "OutputPort: %3u ", smp->common.AttributeModifier >> 16); + if (showBlock) + PrintFunc(dest, "%*s%sBlockNum: %2u\n", indent, "", buf, block); + else if (buf[0]) + PrintFunc(dest, "%*s%s\n", indent, "", buf); + } + PrintPKeyTable(dest, indent, pPKeyTable, block); +} + +void PrintGuidInfo(PrintDest_t *dest, int indent, const GUID_INFO *pGuidInfo, uint8 blockNum) +{ + int i; + char buf[81]; + int offset=0; + uint16 index = blockNum*GUID_INFO_BLOCK_SIZE; + + // 2 entries per line + for (i=0; iGid[i]); + } + PrintFunc(dest, "%*s%s\n", indent, "", buf); +} + +void PrintPortGroupTable(PrintDest_t *dest, int indent, const PORT_GROUP_TABLE *pPortGroup, uint16 tier, uint16 blockNum) +{ + int i; + uint baseport = (blockNum & 0xff)*PGTABLE_LIST_COUNT; + + PrintFunc(dest, "%*s Adaptive Routing Port Group (Tier= %d):\n", indent, "", tier); + for (i=0; iPortGroup[i] != 0) { + PrintFunc(dest, "%*s Port %5u -> PortGroup %5u\n", + indent, "", baseport + i, + pPortGroup->PortGroup[i]); + } + } +} + +void PrintAdaptiveRoutingLidmask(PrintDest_t *dest, int indent, const ADAPTIVE_ROUTING_LIDMASK *pLidmask, uint16 blockNum) +{ + char string[256]; + char str[32]; + int i,j; + uint8_t lidmask; + IB_LID curlid; + IB_LID baselid = blockNum*(LIDMASK_LEN*8); + int firstdone = 0; + int first = 0; + int next = 0; + + string[0] = '\0'; + for (i=LIDMASK_LEN-1; i>=0; i--) + { + if (pLidmask->lidmask[i]) { + lidmask = pLidmask->lidmask[i]; + for (j=0; j<8; j++) { + if (lidmask & (1< 80) { + strcat(string, ","); + PrintFunc(dest, "%*s %s\n", indent, "", string); + string[0] = '\0'; + firstdone = 0; + } + curlid = baselid+j; + if (!first) { + first = curlid; + } else if (!next) { + if (curlid - first > 1) { + if (!firstdone) { + sprintf(str, "0x%x", first); + firstdone = 1; + } else { + sprintf(str, ",0x%x", first); + } + strcat(string, str); + first = curlid; + } else { + next = curlid; + } + } else { + if (curlid - next > 1) { + if (!firstdone) { + sprintf(str, "0x%x-0x%x", first, next); + firstdone = 1; + } else { + sprintf(str, ",0x%x-0x%x", first, next); + } + strcat(string, str); + first = curlid; + next = 0; + } else { + next = curlid; + } + } + } + } + } + baselid+=8; + } + + if (first) { + if (!firstdone) { + sprintf(str, "0x%x", first); + strcat(string, str); + } else { + sprintf(str, ",0x%x", first); + strcat(string, str); + } + if (next) { + sprintf(str, "-0x%x", next); + strcat(string, str); + } + } + if (strlen(string) > 0) { + PrintFunc(dest, "%*s %s\n", indent, "", string); + } +} + +void PrintSmp(PrintDest_t *dest, int indent, const SMP *smp) +{ + PrintSmpHeader(dest, indent, smp); + switch (smp->common.AttributeID) { + case MCLASS_ATTRIB_ID_NODE_DESCRIPTION: + PrintNodeDesc(dest, indent, (const NODE_DESCRIPTION *)&smp->SmpExt.DirectedRoute.SMPData); + break; + case MCLASS_ATTRIB_ID_NODE_INFO: + PrintNodeInfo(dest, indent, (const NODE_INFO *)&smp->SmpExt.DirectedRoute.SMPData); + break; + case MCLASS_ATTRIB_ID_SWITCH_INFO: + PrintSwitchInfo(dest, indent, (const SWITCH_INFO *)&smp->SmpExt.DirectedRoute.SMPData, 0); + break; + case MCLASS_ATTRIB_ID_GUID_INFO: + PrintGuidInfo(dest, indent, (const GUID_INFO *)&smp->SmpExt.DirectedRoute.SMPData, smp->common.AttributeModifier); + break; + case MCLASS_ATTRIB_ID_PORT_INFO: + PrintPortInfoSmp(dest, indent, smp, 0); + break; + case MCLASS_ATTRIB_ID_PART_TABLE: + PrintPKeyTableSmp(dest, indent, smp, + (smp->common.AttributeModifier >> 16)?STL_NODE_SW:0, TRUE, TRUE); + break; + case MCLASS_ATTRIB_ID_VL_ARBITRATION: + PrintVLArbTableSmp(dest, indent, smp, + (smp->common.AttributeModifier &0xffff)?STL_NODE_SW:0); + break; + case MCLASS_ATTRIB_ID_LINEAR_FWD_TABLE: + PrintLinearFDB(dest, indent, + (const FORWARDING_TABLE *)&smp->SmpExt.DirectedRoute.SMPData, + smp->common.AttributeModifier & 0xffff); + break; + case MCLASS_ATTRIB_ID_RANDOM_FWD_TABLE: + PrintRandomFDB(dest, indent, + (const FORWARDING_TABLE *)&smp->SmpExt.DirectedRoute.SMPData, + smp->common.AttributeModifier); + break; + case MCLASS_ATTRIB_ID_MCAST_FWD_TABLE: + PrintMCastFDBSmp(dest, indent, smp); + break; + case MCLASS_ATTRIB_ID_SM_INFO: + PrintSMInfo(dest, indent, (const SM_INFO *)&smp->SmpExt.DirectedRoute.SMPData, 0); + break; + case MCLASS_ATTRIB_ID_VENDOR_DIAG: + // TBD Hex Dump + break; + case MCLASS_ATTRIB_ID_LED_INFO: + // TBD Hex Dump + break; + case MCLASS_ATTRIB_ID_PORT_LFT: + PrintLinearFDB(dest, indent, + (const FORWARDING_TABLE *)&smp->SmpExt.DirectedRoute.SMPData, + smp->common.AttributeModifier & 0xffff); + break; + case MCLASS_ATTRIB_ID_PORT_GROUP: + PrintPortGroupTable(dest, indent, + (const PORT_GROUP_TABLE *)&smp->SmpExt.DirectedRoute.SMPData, + smp->common.AttributeModifier >>16, + smp->common.AttributeModifier & 0xffff); + break; + case MCLASS_ATTRIB_ID_AR_LIDMASK: + PrintAdaptiveRoutingLidmask(dest, indent, + (const ADAPTIVE_ROUTING_LIDMASK *)&smp->SmpExt.DirectedRoute.SMPData, + //smp->common.AttributeModifier >>17, + smp->common.AttributeModifier & 0xffff); + break; + default: + // TBD Hex Dump + break; + } +} diff --git a/IbPrint/stl_ea.c b/IbPrint/stl_ea.c new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/IbPrint/stl_ea.c diff --git a/IbPrint/stl_ema.c b/IbPrint/stl_ema.c new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/IbPrint/stl_ema.c diff --git a/IbPrint/stl_mad.c b/IbPrint/stl_mad.c new file mode 100644 index 0000000..cd1dfde --- /dev/null +++ b/IbPrint/stl_mad.c @@ -0,0 +1,148 @@ +/* BEGIN_ICS_COPYRIGHT7 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT7 ****************************************/ + +#include "ibprint.h" +#include "stl_print.h" + +void PrintStlSmpHeader(PrintDest_t *dest, int indent, const STL_SMP *smp) +{ + PrintMadHeader(dest, indent, &smp->common); + PrintFunc(dest, "%*sM_KEY: 0x%016"PRIx64"\n", indent, "", smp->M_Key); + if (smp->common.MgmtClass == MCLASS_SM_DIRECTED_ROUTE) { + uint16 offset; + uint32 i; + char buf[128]; + PrintFunc(dest, "%*sDR: D: %u Ptr: %3u Cnt: %3u DrSLID: 0x%08x DrDLID: 0x%08x\n", + indent, "", smp->common.u.DR.s.D, + smp->common.u.DR.HopPointer, smp->common.u.DR.HopCount, + smp->SmpExt.DirectedRoute.DrSLID, + smp->SmpExt.DirectedRoute.DrDLID); + + offset = sprintf(buf, "InitPath:"); + // entry 0 is not used + for (i=1; i<= smp->common.u.DR.HopCount; i++) { + if ((i-1)%16 == 0 && i>1) { + PrintFunc(dest, "%*s%s\n", indent, "", buf); + offset=sprintf(buf, " "); + } + offset += sprintf(&buf[offset], " %3u", smp->SmpExt.DirectedRoute.InitPath[i]); + } + PrintFunc(dest, "%*s%s\n", indent, "", buf); + + if (smp->common.u.DR.s.D) { + offset = sprintf(buf, "RetPath: "); + // entry 0 is not used + for (i=1; i<= smp->common.u.DR.HopCount; i++) { + if ((i-1)%16 == 0 && i>1) { + PrintFunc(dest, "%*s%s\n", indent, "", buf); + offset=sprintf(buf, " "); + } + offset += sprintf(&buf[offset], " %3u", smp->SmpExt.DirectedRoute.RetPath[i]); + } + PrintFunc(dest, "%*s%s\n", indent, "", buf); + } + } +} + +void PrintStlAggregateMember(PrintDest_t *dest, int indent, const STL_AGGREGATE *aggr) +{ + PrintFunc(dest, "%*sAttrID: 0x%04x\n", indent, "", aggr->AttributeID); + PrintFunc(dest, "%*sError: 0x%02x, RequestLength: 0x%02x\n", indent+2, "", + aggr->Result.s.Error, aggr->Result.s.RequestLength); + PrintFunc(dest, "%*sModifier: 0x%02x\n", indent+2, "", aggr->AttributeModifier); +} + +void PrintStlClassPortInfo(PrintDest_t *dest, int indent, const STL_CLASS_PORT_INFO *pClassPortInfo, uint8 MgmtClass) +{ + char tbuf[8]; + char cbuf[80]; + char c2buf[80]; + PrintFunc(dest, "%*sBaseVersion: %d ClassVersion: %d\n", + indent, "", pClassPortInfo->BaseVersion, + pClassPortInfo->ClassVersion); + FormatTimeoutMult(tbuf, pClassPortInfo->u1.s.RespTimeValue); + switch (MgmtClass) { + case MCLASS_SUBN_ADM: /* SA */ + StlSaClassPortInfoCapMask(cbuf, pClassPortInfo->CapMask); + StlSaClassPortInfoCapMask2(c2buf, pClassPortInfo->u1.s.CapMask2); + break; + case MCLASS_PERF: /* PM */ + StlPmClassPortInfoCapMask(cbuf, pClassPortInfo->CapMask); + StlPmClassPortInfoCapMask2(c2buf, pClassPortInfo->u1.s.CapMask2); + break; + case MCLASS_VFI_PM: /* PA */ + StlPaClassPortInfoCapMask(cbuf, pClassPortInfo->CapMask); + StlPaClassPortInfoCapMask2(c2buf, pClassPortInfo->u1.s.CapMask2); + break; + default: + StlCommonClassPortInfoCapMask(cbuf, pClassPortInfo->CapMask); + StlCommonClassPortInfoCapMask2(c2buf, pClassPortInfo->u1.s.CapMask2); + break; + } + PrintFunc(dest, "%*sRespTime: %s Capability: 0x%04x: %s\n", + indent, "", tbuf, + pClassPortInfo->CapMask, cbuf); + PrintFunc(dest, "%*sCapability2: 0x%07x: %s\n", + indent, "", + pClassPortInfo->u1.s.CapMask2, c2buf); + + PrintFunc(dest, "%*sRedirect: LID: 0x%.*x GID: 0x%016"PRIx64":0x%016"PRIx64"\n", + indent, "",(pClassPortInfo->RedirectLID <= IB_MAX_UCAST_LID ? 4 : 8), + pClassPortInfo->RedirectLID, + pClassPortInfo->RedirectGID.AsReg64s.H, + pClassPortInfo->RedirectGID.AsReg64s.L); + PrintFunc(dest, "%*s QP: 0x%06x QKey: 0x%08x PKey: 0x%04x SL: %2u\n", + indent, "", + pClassPortInfo->u3.s.RedirectQP, + pClassPortInfo->Redirect_Q_Key, + pClassPortInfo->Redirect_P_Key, + pClassPortInfo->u3.s.RedirectSL); + PrintFunc(dest, "%*s FlowLabel: 0x%05x TClass: 0x%02x\n", + indent, "", + pClassPortInfo->u2.s.RedirectFlowLabel, + pClassPortInfo->u2.s.RedirectTClass); + + PrintFunc(dest, "%*sTrap: LID: 0x%.*x GID: 0x%016"PRIx64":0x%016"PRIx64"\n", + indent, "",(pClassPortInfo->TrapLID <= IB_MAX_UCAST_LID ? 4:8), + pClassPortInfo->TrapLID, + pClassPortInfo->TrapGID.AsReg64s.H, + pClassPortInfo->TrapGID.AsReg64s.L); + PrintFunc(dest, "%*s QP: 0x%06x QKey: 0x%08x PKey: 0x%04x SL: %2u\n", + indent, "", + pClassPortInfo->u5.s.TrapQP, + pClassPortInfo->Trap_Q_Key, + pClassPortInfo->Trap_P_Key, + pClassPortInfo->u6.s.TrapSL); + PrintFunc(dest, "%*s FlowLabel: 0x%05x HopLimit: 0x%02x TClass: 0x%02x\n", + indent, "", + pClassPortInfo->u4.s.TrapFlowLabel, + pClassPortInfo->u5.s.TrapHopLimit, + pClassPortInfo->u4.s.TrapTClass); +} + diff --git a/IbPrint/stl_pa.c b/IbPrint/stl_pa.c new file mode 100644 index 0000000..e2bc5e5 --- /dev/null +++ b/IbPrint/stl_pa.c @@ -0,0 +1,795 @@ +/* BEGIN_ICS_COPYRIGHT7 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT7 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "ibprint.h" + +void PrintStlPAImageId(PrintDest_t *dest, int indent, const STL_PA_IMAGE_ID_DATA *pImageId) +{ + time_t absTime = (time_t)pImageId->imageTime.absoluteTime; + + PrintFunc(dest, "%*sImageNumber: 0x%"PRIx64" Offset: %d\n", + indent, "", pImageId->imageNumber, pImageId->imageOffset); + if (absTime) { + char buf[80]; + snprintf(buf, sizeof(buf), "%s", ctime((const time_t *)&absTime)); + if ((strlen(buf)>0) && (buf[strlen(buf)-1] == '\n')) + buf[strlen(buf)-1] = '\0'; + + PrintFunc(dest, "%*sImageTime: %s\n", indent, "", buf); + } + return; +} + +void PrintStlPAGroupList(PrintDest_t *dest, int indent, const int numRecords, const STL_PA_GROUP_LIST *pGroupList) +{ + int i; + + PrintFunc(dest, "%*sNumber of Groups: %u\n", indent, "", numRecords); + for (i = 0; i < numRecords; i++) + PrintFunc(dest, "%*sGroup %u: %s\n", indent, "", i+1, pGroupList[i].groupName); + return; +} + +void PrintStlPAGroupList2(PrintDest_t *dest, int indent, const int numRecords, const STL_PA_GROUP_LIST2 *pGroupList) +{ + int i; + + PrintFunc(dest, "%*sNumber of Groups: %u\n", indent, "", numRecords); + for (i = 0; i < numRecords; i++) + PrintFunc(dest, "%*sGroup %u: %s\n", indent, "", i+1, pGroupList[i].groupName); + + PrintStlPAImageId(dest, indent+2, &pGroupList[0].imageId); + return; +} + +void PrintStlPAGroupUtilStats(PrintDest_t *dest, int indent, const STL_PA_PM_UTIL_STATS *pUtilStat) +{ + int i; + + PrintFunc(dest, "%*sUtil: Tot %6"PRIu64" Max %6u Min %6u Avg %6u MiB/s\n", + indent, "", pUtilStat->totalMBps, pUtilStat->maxMBps, pUtilStat->minMBps, pUtilStat->avgMBps); + PrintFunc(dest, "%*sUtil: ", indent, ""); + for (i = 0; i < STL_PM_UTIL_BUCKETS; i++) + PrintFunc(dest, " %4d", pUtilStat->BWBuckets[i]); + PrintFunc(dest, "%*s\n", indent, ""); + PrintFunc(dest, "%*sPkts: Tot %6"PRIu64" Max %6u Min %6u Avg %6u KiPps/s\n", + indent, "", pUtilStat->totalKPps, pUtilStat->maxKPps, pUtilStat->minKPps, pUtilStat->avgKPps); + PrintFunc(dest, "%*s NoResp Ports: PMA: %u Topo: %u\n", + indent, "", pUtilStat->pmaNoRespPorts, pUtilStat->topoIncompPorts); + + return; +} + +void PrintStlPAGroupErrorStats(PrintDest_t *dest, int indent, const STL_PM_CATEGORY_STATS *pErrStat) +{ + int i; + + PrintFunc(dest, "%*sIntegrity Max %6u Buckets: ", + indent, "", pErrStat->categoryMaximums.integrityErrors); + for (i = 0; i < STL_PM_CATEGORY_BUCKETS; i++) + PrintFunc(dest, " %4u ", pErrStat->ports[i].integrityErrors); + PrintFunc(dest, "\n"); + + PrintFunc(dest, "%*sCongestion Max %6u Buckets: ", + indent, "", pErrStat->categoryMaximums.congestion); + for (i = 0; i < STL_PM_CATEGORY_BUCKETS; i++) + PrintFunc(dest, " %4u ", pErrStat->ports[i].congestion); + PrintFunc(dest, "\n"); + + PrintFunc(dest, "%*sSmaCongestion Max %6u Buckets: ", + indent, "", pErrStat->categoryMaximums.smaCongestion); + for (i = 0; i < STL_PM_CATEGORY_BUCKETS; i++) + PrintFunc(dest, " %4u ", pErrStat->ports[i].smaCongestion); + PrintFunc(dest, "\n"); + + PrintFunc(dest, "%*sBubble Max %6u Buckets: ", + indent, "", pErrStat->categoryMaximums.bubble); + for (i = 0; i < STL_PM_CATEGORY_BUCKETS; i++) + PrintFunc(dest, " %4u ", pErrStat->ports[i].bubble); + PrintFunc(dest, "\n"); + + PrintFunc(dest, "%*sSecurity Max %6u Buckets: ", + indent, "", pErrStat->categoryMaximums.securityErrors); + for (i = 0; i < STL_PM_CATEGORY_BUCKETS; i++) + PrintFunc(dest, " %4u ", pErrStat->ports[i].securityErrors); + PrintFunc(dest, "\n"); + + PrintFunc(dest, "%*sRouting Max %6u Buckets: ", + indent, "", pErrStat->categoryMaximums.routingErrors); + for (i = 0; i < STL_PM_CATEGORY_BUCKETS; i++) + PrintFunc(dest, " %4u ", pErrStat->ports[i].routingErrors); + PrintFunc(dest, "\n"); + + + PrintFunc(dest, "%*sUtilization: %3u.%1u%%\n", indent, "", + pErrStat->categoryMaximums.utilizationPct10 / 10, + pErrStat->categoryMaximums.utilizationPct10 % 10); + PrintFunc(dest, "%*sDiscards: %3u.%1u%%\n", indent, "", + pErrStat->categoryMaximums.discardsPct10 / 10, + pErrStat->categoryMaximums.discardsPct10 % 10); + + return; +} + +void PrintStlPAGroupInfo(PrintDest_t *dest, int indent, const STL_PA_PM_GROUP_INFO_DATA *pGroupInfo) +{ + + PrintFunc(dest, "%*sGroup name: %s\n", + indent, "", pGroupInfo->groupName); + if (pGroupInfo->minInternalRate != IB_STATIC_RATE_DONTCARE + || pGroupInfo->maxInternalRate != IB_STATIC_RATE_DONTCARE) + PrintFunc(dest, "%*sNum internal ports: %u MinRate: %4s MaxRate: %4s MaxMiBps: %u\n", + indent, "", pGroupInfo->numInternalPorts, + StlStaticRateToText(pGroupInfo->minInternalRate), + StlStaticRateToText(pGroupInfo->maxInternalRate), + pGroupInfo->maxInternalMBps); + else + PrintFunc(dest, "%*sNum internal ports: %u\n", + indent, "", pGroupInfo->numInternalPorts); + + if (pGroupInfo->minExternalRate != IB_STATIC_RATE_DONTCARE + || pGroupInfo->maxExternalRate != IB_STATIC_RATE_DONTCARE) + PrintFunc(dest, "%*sNum external ports: %u MinRate: %4s MaxRate: %4s MaxMiBps: %u\n", + indent, "", pGroupInfo->numExternalPorts, + StlStaticRateToText(pGroupInfo->minExternalRate), + StlStaticRateToText(pGroupInfo->maxExternalRate), + pGroupInfo->maxExternalMBps); + else + PrintFunc(dest, "%*sNum external ports: %u\n", + indent, "", pGroupInfo->numExternalPorts); + + PrintFunc(dest, "%*sInternal utilization statistics:\n", + indent, ""); + PrintStlPAGroupUtilStats(dest, indent+2, &pGroupInfo->internalUtilStats); + PrintFunc(dest, "%*sSend utilization statistics:\n", + indent, ""); + PrintStlPAGroupUtilStats(dest, indent+2, &pGroupInfo->sendUtilStats); + PrintFunc(dest, "%*sReceive utilization statistics:\n", + indent, ""); + PrintStlPAGroupUtilStats(dest, indent+2, &pGroupInfo->recvUtilStats); + PrintFunc(dest, "%*sInternal Error Summary:\n", + indent, ""); + PrintStlPAGroupErrorStats(dest, indent+2, &pGroupInfo->internalCategoryStats); + PrintFunc(dest, "%*sExternal Error Summary:\n", + indent, ""); + PrintStlPAGroupErrorStats(dest, indent+2, &pGroupInfo->externalCategoryStats); + PrintFunc(dest, "%*sImageID:\n", + indent, ""); + PrintStlPAImageId(dest, indent+2, &pGroupInfo->imageId); + return; +} + +void PrintStlPAPortCounters(PrintDest_t *dest, int indent, const STL_PORT_COUNTERS_DATA *pPortCounters, const STL_LID nodeLid, const uint32 portNumber, const uint32 flags) +{ + PrintFunc(dest, "%*s%s controlled Port Counters (%s) for LID 0x%.*x, port number %u%s:\n", + indent, "", (flags & STL_PA_PC_FLAG_USER_COUNTERS) ? "User" : "PM", + (flags & STL_PA_PC_FLAG_DELTA) ? "delta" : "total", + (nodeLid <= IB_MAX_UCAST_LID ? 4:8), + nodeLid, portNumber, + (flags&STL_PA_PC_FLAG_UNEXPECTED_CLEAR)?" (Unexpected Clear)":""); + PrintFunc(dest, "%*sPerformance: Transmit\n", indent, ""); + PrintFunc(dest, "%*s Xmit Data %20"PRIu64" MB (%"PRIu64" Flits)\n", + indent, "", + pPortCounters->portXmitData/FLITS_PER_MB, + pPortCounters->portXmitData); + PrintFunc(dest, "%*s Xmit Pkts %20"PRIu64"\n", + indent, "", + pPortCounters->portXmitPkts); + PrintFunc(dest, "%*s MC Xmit Pkts %20"PRIu64"\n", + indent, "", + pPortCounters->portMulticastXmitPkts); + PrintFunc(dest, "%*sPerformance: Receive\n", + indent, ""); + PrintFunc(dest, "%*s Rcv Data %20"PRIu64" MB (%"PRIu64" Flits)\n", + indent, "", + pPortCounters->portRcvData/FLITS_PER_MB, + pPortCounters->portRcvData); + PrintFunc(dest, "%*s Rcv Pkts %20"PRIu64"\n", + indent, "", + pPortCounters->portRcvPkts); + PrintFunc(dest, "%*s MC Rcv Pkts %20"PRIu64"\n", + indent, "", + pPortCounters->portMulticastRcvPkts); + PrintFunc(dest, "%*sSignal Integrity Errors: \n", + indent, ""); + PrintFunc(dest, "%*s Link Quality Ind %10u\n", + indent, "", + pPortCounters->lq.s.linkQualityIndicator); + PrintFunc(dest, "%*s Uncorrectable Err %10u\n", // 8-bit + indent, "", + pPortCounters->uncorrectableErrors); + PrintFunc(dest, "%*s Link Downed %10u\n", // 32-bit + indent, "", + pPortCounters->linkDowned); + PrintFunc(dest, "%*s Num Lanes Down %10u\n", + indent, "", + pPortCounters->lq.s.numLanesDown); + PrintFunc(dest, "%*s Rcv Errors %10"PRIu64"\n", + indent, "", + pPortCounters->portRcvErrors); + PrintFunc(dest, "%*s Exc. Buffer Overrun %10"PRIu64"\n", + indent, "", + pPortCounters->excessiveBufferOverruns); + PrintFunc(dest, "%*s FM Config %10"PRIu64"\n", + indent, "", + pPortCounters->fmConfigErrors); + PrintFunc(dest, "%*s Link Error Recovery %10u\n", // 32-bit + indent, "", + pPortCounters->linkErrorRecovery); + PrintFunc(dest, "%*s Local Link Integrity %10"PRIu64"\n", + indent, "", + pPortCounters->localLinkIntegrityErrors); + PrintFunc(dest, "%*s Rcv Rmt Phys Err %10"PRIu64"\n", + indent, "", + pPortCounters->portRcvRemotePhysicalErrors); + PrintFunc(dest, "%*sSecurity Errors: \n", + indent, ""); + PrintFunc(dest, "%*s Xmit Constraint %10"PRIu64"\n", + indent, "", + pPortCounters->portXmitConstraintErrors); + PrintFunc(dest, "%*s Rcv Constraint %10"PRIu64"\n", + indent, "", + pPortCounters->portRcvConstraintErrors); + PrintFunc(dest, "%*sRouting and Other Errors: \n", + indent, ""); + PrintFunc(dest, "%*s Rcv Sw Relay Err %10"PRIu64"\n", + indent, "", + pPortCounters->portRcvSwitchRelayErrors); + PrintFunc(dest, "%*s Xmit Discards %10"PRIu64"\n", + indent, "", + pPortCounters->portXmitDiscards); + PrintFunc(dest, "%*sCongestion: \n", + indent, ""); + PrintFunc(dest, "%*s Cong Discards %10"PRIu64"\n", + indent, "", + pPortCounters->swPortCongestion); + PrintFunc(dest, "%*s Rcv FECN %10"PRIu64"\n", + indent, "", + pPortCounters->portRcvFECN); + PrintFunc(dest, "%*s Rcv BECN %10"PRIu64"\n", + indent, "", + pPortCounters->portRcvBECN); + PrintFunc(dest, "%*s Mark FECN %10"PRIu64"\n", + indent, "", + pPortCounters->portMarkFECN); + PrintFunc(dest, "%*s Xmit Time Cong %10"PRIu64"\n", + indent, "", + pPortCounters->portXmitTimeCong); + PrintFunc(dest, "%*s Xmit Wait %10"PRIu64"\n", + indent, "", + pPortCounters->portXmitWait); + PrintFunc(dest, "%*sBubbles: \n", + indent, ""); + PrintFunc(dest, "%*s Xmit Wasted BW %10"PRIu64"\n", + indent, "", + pPortCounters->portXmitWastedBW); + PrintFunc(dest, "%*s Xmit Wait Data %10"PRIu64"\n", + indent, "", + pPortCounters->portXmitWaitData); + PrintFunc(dest, "%*s Rcv Bubble %10"PRIu64"\n", + indent, "", + pPortCounters->portRcvBubble); + if (flags & STL_PA_PC_FLAG_CLEAR_FAIL) { + PrintFunc(dest, "\nPort Counter Clear was Unsuccessful\n\n"); + } + PrintStlPAImageId(dest, indent+2, &pPortCounters->imageId); +} + +void PrintStlPAGroupConfig(PrintDest_t *dest, int indent, const char *groupName, const int numRecords, const STL_PA_PM_GROUP_CFG_RSP *pGroupConfig) +{ + int i; + + PrintFunc(dest, "%*sGroup name: %s\n", + indent, "", groupName); + PrintFunc(dest, "%*sNumber ports: %u\n", + indent, "", numRecords); + for (i = 0; i < numRecords; i++) { + PrintFunc(dest, "%*s%u:LID:0x%.*x Port:%u GUID:0x%016"PRIx64" NodeDesc: %.*s\n", + indent, "", i+1,(pGroupConfig[i].nodeLid <= IB_MAX_UCAST_LID ? 4:8), + pGroupConfig[i].nodeLid, + pGroupConfig[i].portNumber, + pGroupConfig[i].nodeGUID, + (int)sizeof(pGroupConfig[i].nodeDesc), + pGroupConfig[i].nodeDesc); + } + PrintStlPAImageId(dest, indent, &pGroupConfig->imageId); + + return; +} + +void PrintStlPAGroupNodeInfo(PrintDest_t *dest, int indent, const char *groupName, const int numRecords, const STL_PA_GROUP_NODEINFO_RSP *pGroupNodeInfo) +{ + char buf[80]; + int i; + + PrintFunc(dest, "%*sGroup name: %s\n", + indent, "", groupName); + PrintFunc(dest, "%*sNumber nodes: %u\n", + indent, "", numRecords); + for (i = 0; i < numRecords; i++) { + PrintFunc(dest, "%*s%u:LID: 0x%08x Type: %s Name: %.*s\n", + indent, "", i+1, pGroupNodeInfo[i].nodeLID, + StlNodeTypeToText(pGroupNodeInfo[i].nodeType), + (int)sizeof(pGroupNodeInfo[i].nodeDesc), + pGroupNodeInfo[i].nodeDesc); + PrintFunc(dest, "%*s NodeGuid: 0x%016" PRIx64 "\n", + indent, " ",pGroupNodeInfo[i].nodeGUID); + FormatStlPortMask(buf, pGroupNodeInfo[i].portSelectMask, MAX_STL_PORTS, 80); + PrintFunc(dest, "%*s PortSelectMask: %s\n", indent, " ", buf); + PrintSeparator(dest); + } + PrintStlPAImageId(dest, indent, &pGroupNodeInfo->imageId); + + return; +} + +void PrintStlPAGroupLinkInfo(PrintDest_t *dest, int indent, const char *groupName, const int numRecords, const STL_PA_GROUP_LINKINFO_RSP *pGroupLinkInfo) +{ + int i; + + PrintFunc(dest, "%*sGroup name: %s\n", + indent, "", groupName); + PrintFunc(dest, "%*sNumber links: %u\n", + indent, "", numRecords); + for (i = 0; i < numRecords; i++) { + PrintFunc(dest, "%*s%u:LID: 0x%08x -> 0x%08x Port: %3u -> %3u\n", + indent, "", i+1, pGroupLinkInfo[i].fromLID, pGroupLinkInfo[i].toLID, + pGroupLinkInfo[i].fromPort, pGroupLinkInfo[i].toPort); + PrintFunc(dest, "%*s MTU: %5s txRate: %4s rxRate: %4s\n", + indent, " ", IbMTUToText(pGroupLinkInfo[i].mtu), + StlStaticRateToText(StlLinkSpeedWidthToStaticRate(pGroupLinkInfo[i].activeSpeed, pGroupLinkInfo[i].txLinkWidthDowngradeActive)), + StlStaticRateToText(StlLinkSpeedWidthToStaticRate(pGroupLinkInfo[i].activeSpeed, pGroupLinkInfo[i].rxLinkWidthDowngradeActive))); + PrintFunc(dest, "%*s Local Status: %s\n", indent, "", + StlFocusStatusToText(pGroupLinkInfo[i].localStatus)); + PrintFunc(dest, "%*s Neighbor Status: %s\n", indent, "", + StlFocusStatusToText(pGroupLinkInfo[i].neighborStatus)); + PrintSeparator(dest); + } + PrintStlPAImageId(dest, indent, &pGroupLinkInfo->imageId); + + return; +} + + +void PrintStlPMConfig(PrintDest_t *dest, int indent, const STL_PA_PM_CFG_DATA *pPMConfig) +{ + char buf[80]; + + PrintFunc(dest, "%*sSweep Interval: %u sec PM Flags (0x%X):\n", + indent, "", pPMConfig->sweepInterval, pPMConfig->pmFlags); + StlFormatPmFlags(buf, pPMConfig->pmFlags); + PrintFunc(dest, "%*s %s\n", indent, "", buf); + StlFormatPmFlags2(buf, pPMConfig->pmFlags); + PrintFunc(dest, "%*s %s\n", indent, "", buf); + PrintFunc(dest, "%*sMax Clients: %u\n", + indent, "", pPMConfig->maxClients); + PrintFunc(dest, "%*sTotal Images: %-7u Freeze Images: %-7u Freeze Lease: %-7u sec\n", + indent, "", pPMConfig->sizeHistory, pPMConfig->sizeFreeze, + pPMConfig->lease); + PrintFunc(dest, "%*sErr Thresholds: Integrity: %-7u Congestion: %-7u\n", + indent, "", pPMConfig->categoryThresholds.integrityErrors, + pPMConfig->categoryThresholds.congestion ); + PrintFunc(dest, "%*s SMA Congest: %-7u Bubble: %-7u\n", + indent, "",pPMConfig->categoryThresholds.smaCongestion, + pPMConfig->categoryThresholds.bubble); + PrintFunc(dest, "%*s Security: %-7u Routing: %-7u\n", + indent, "", pPMConfig->categoryThresholds.securityErrors, + pPMConfig->categoryThresholds.routingErrors ); + PrintFunc(dest, "%*s Integrity Wts: Lnk Wdth Dngd: %-7u Link Qual: %-7u\n", + indent, "", pPMConfig->integrityWeights.LinkWidthDowngrade, + pPMConfig->integrityWeights.LinkQualityIndicator ); + PrintFunc(dest, "%*s Uncorrectable: %-7u Link Downed: %-7u\n", + indent, "", pPMConfig->integrityWeights.UncorrectableErrors, + pPMConfig->integrityWeights.LinkDowned); + PrintFunc(dest, "%*s Rcv Errors: %-7u Excs Bfr Ovrn: %-7u\n", + indent, "", pPMConfig->integrityWeights.PortRcvErrors, + pPMConfig->integrityWeights.ExcessiveBufferOverruns); + PrintFunc(dest, "%*s FM Config Err: %-7u Link Err Recov: %-7u\n", + indent, "", pPMConfig->integrityWeights.FMConfigErrors, + pPMConfig->integrityWeights.LinkErrorRecovery); + PrintFunc(dest, "%*s Loc Link Integ: %-7u \n", + indent, "", pPMConfig->integrityWeights.LocalLinkIntegrityErrors ); + PrintFunc(dest, "%*s Congest Wts: Cong Discards: %-7u Rcv FECN: %-7u\n", + indent, "", pPMConfig->congestionWeights.SwPortCongestion, + pPMConfig->congestionWeights.PortRcvFECN); + PrintFunc(dest, "%*s Rcv BECN: %-7u Mark FECN: %-7u\n", + indent, "", pPMConfig->congestionWeights.PortRcvBECN, + pPMConfig->congestionWeights.PortMarkFECN); + PrintFunc(dest, "%*s Tx Time Cong: %-7u Tx Wait: %-7u\n", + indent, "", pPMConfig->congestionWeights.PortXmitTimeCong, + pPMConfig->congestionWeights.PortXmitWait); + PrintFunc(dest, "%*sPM Memory Size: %"PRIu64" MiB (%" PRIu64 " bytes)\n", + indent, "", pPMConfig->memoryFootprint/(1024*1024), + pPMConfig->memoryFootprint ); + PrintFunc(dest, "%*sPMA MADs: MaxAttempts: %-6u MinRespTimeout: %-6u RespTimeout: %-6u\n", + indent, "", pPMConfig->maxAttempts, pPMConfig->minRespTimeout, + pPMConfig->respTimeout ); + PrintFunc(dest, "%*sSweep: MaxParallelNodes: %-6u PmaBatchSize: %-6u ErrorClear: %1u\n", + indent, "", pPMConfig->maxParallelNodes, + pPMConfig->pmaBatchSize, pPMConfig->errorClear); + + return; +} + + +void PrintStlPAFocusPorts(PrintDest_t *dest, int indent, const char *groupName, const int numRecords, const uint32 select, const uint32 start, const uint32 range, + const STL_FOCUS_PORTS_RSP *pFocusPorts) +{ + int i; + + PrintFunc(dest, "%*sGroup name: %s\n", indent, "", groupName); + PrintFunc(dest, "%*sNumber links: %u\n", indent, "", numRecords); + PrintFunc(dest, "%*sFocus select: %s\n", indent, "", StlFocusAttributeToText(select)); + PrintFunc(dest, "%*sFocus start: %u\n", indent, "", start); + PrintFunc(dest, "%*sFocus range: %u\n", indent, "", range); + for (i = 0; i < numRecords; i++) { + PrintFunc(dest, "%*s%u:LID:0x%04x Port:%u Rate: %4s MTU: %5s nbrLID:0x%04x nbrPort:%u\n", + indent, "", i+start, pFocusPorts[i].nodeLid, pFocusPorts[i].portNumber, + StlStaticRateToText(pFocusPorts[i].rate), IbMTUToText(pFocusPorts[i].maxVlMtu), + pFocusPorts[i].neighborLid, pFocusPorts[i].neighborPortNumber); + if (IS_FOCUS_SELECT_UTIL(select)) { + PrintFunc(dest, "%*s Value: %16.1f nbrValue: %16.1f\n", + indent, "", (float)pFocusPorts[i].value/10.0, (float)pFocusPorts[i].neighborValue/10.0); + } else if (IS_FOCUS_SELECT_NO_VAL(select)) { + // Skip print of Values + } else { + PrintFunc(dest, "%*s Value: %16"PRIu64" nbrValue: %16"PRIu64"\n", + indent, "", pFocusPorts[i].value, pFocusPorts[i].neighborValue); + } + PrintFunc(dest, "%*s GUID: 0x%016"PRIx64" nbrGuid: 0x%016"PRIx64"\n", + indent, "", pFocusPorts[i].nodeGUID, pFocusPorts[i].neighborGuid); + PrintFunc(dest, "%*s Status: %s Name: %.*s\n", indent, "", + StlFocusStatusToText(pFocusPorts[i].localStatus), + (int)sizeof(pFocusPorts[i].nodeDesc), pFocusPorts[i].nodeDesc); + PrintFunc(dest, "%*s Status: %s Neighbor Name: %.*s\n", indent, "", + StlFocusStatusToText(pFocusPorts[i].neighborStatus), + (int)sizeof(pFocusPorts[i].neighborNodeDesc), pFocusPorts[i].neighborNodeDesc); + } + PrintStlPAImageId(dest, indent, &pFocusPorts[0].imageId); + + return; +} + +void PrintStlPAFocusPortsMultiSelect(PrintDest_t *dest, int indent, const char *groupName, const int numRecords, const uint32 start, const uint32 range, const STL_FOCUS_PORTS_MULTISELECT_RSP *pFocusPorts, uint8 logical_operator, + STL_FOCUS_PORT_TUPLE *tuple) +{ + int i, j; + + PrintFunc(dest, "%*sGroup name: %s\n", indent, "", groupName); + PrintFunc(dest, "%*sNumber links: %u\n", indent, "", numRecords); + PrintFunc(dest, "%*sFocus start: %u\n", indent, "", start); + PrintFunc(dest, "%*sFocus range: %u\n", indent, "", range); + + for (j = 0; j < MAX_NUM_FOCUS_PORT_TUPLES; j++) { + if (tuple[j].comparator != FOCUS_PORTS_COMPARATOR_INVALID) { + PrintFunc(dest, "%*sFocus select: %-22s %-25s %16"PRIu64"\n", indent, "", + StlFocusAttributeToText(tuple[j].select), + StlComparatorToText(tuple[j].comparator), + tuple[j].argument); + } + } + + if (logical_operator != FOCUS_PORTS_LOGICAL_OPERATOR_INVALID) { + PrintFunc(dest, "%*sTuples joined by logical operator: %s\n", indent, "", StlOperatorToText(logical_operator)); + } + + for (i = 0; i < numRecords; i++) { + PrintFunc(dest, "%*s%3u:LID:0x%.*x Port:%u Rate: %4s MTU: %5s nbrLID:0x%.*x nbrPort:%u\n", + indent, "", i+start, (pFocusPorts[i].nodeLid <= IB_MAX_UCAST_LID ? 4:8), pFocusPorts[i].nodeLid, + pFocusPorts[i].portNumber, + StlStaticRateToText(pFocusPorts[i].rate), IbMTUToText(pFocusPorts[i].maxVlMtu), + (pFocusPorts[i].neighborLid <= IB_MAX_UCAST_LID ? 4:8), pFocusPorts[i].neighborLid, + pFocusPorts[i].neighborPortNumber); + for (j = 0; j < MAX_NUM_FOCUS_PORT_TUPLES; j++) { + if (tuple[j].comparator != FOCUS_PORTS_COMPARATOR_INVALID) { + if (IS_FOCUS_SELECT_UTIL(tuple[j].select)) { + PrintFunc(dest, "%*s %-22s Value: %16.1f" " nbrValue: %16.1f\n", + indent, "", StlFocusAttributeToText(tuple[j].select), (float)pFocusPorts[i].value[j]/10.0, (float)pFocusPorts[i].neighborValue[j]/10.0); + } else { + PrintFunc(dest, "%*s %-22s Value: %16"PRIu64" nbrValue: %16"PRIu64"\n", + indent, "", StlFocusAttributeToText(tuple[j].select), pFocusPorts[i].value[j], pFocusPorts[i].neighborValue[j]); + } + } + } + PrintFunc(dest, "%*s GUID: 0x%016"PRIx64" nbrGuid: 0x%016"PRIx64"\n", + indent, "", pFocusPorts[i].nodeGUID, pFocusPorts[i].neighborGuid); + PrintFunc(dest, "%*s Status: %s Name: %.*s\n", indent, "", + StlFocusStatusToText(pFocusPorts[i].localStatus), + (int)sizeof(pFocusPorts[i].nodeDesc), pFocusPorts[i].nodeDesc); + PrintFunc(dest, "%*s Status: %s Neighbor Name: %.*s\n", indent, "", + StlFocusStatusToText(pFocusPorts[i].neighborStatus), + (int)sizeof(pFocusPorts[i].neighborNodeDesc), pFocusPorts[i].neighborNodeDesc); + } + PrintStlPAImageId(dest, indent, &pFocusPorts[0].imageId); + + return; +} + +void PrintStlPAImageInfo(PrintDest_t *dest, int indent, const STL_PA_IMAGE_INFO_DATA *pImageInfo) +{ + int i; + time_t sweepStart = (time_t)pImageInfo->sweepStart; + char buf[80]; + + ctime_r((const time_t *)&sweepStart, buf); + if ((strlen(buf)>0) && (buf[strlen(buf)-1] == '\n')) + buf[strlen(buf)-1] = '\0'; + PrintStlPAImageId(dest, indent, &pImageInfo->imageId); + PrintFunc(dest, "%*sImageSweepStart: %s Duration: %u.%03u Seconds\n", + indent, "", buf, + pImageInfo->sweepDuration/1000000, + (pImageInfo->sweepDuration%1000000)/1000); + if (pImageInfo->imageInterval) { + PrintFunc(dest, "%*sImage Interval: %u Seconds\n", + indent, "", pImageInfo->imageInterval); + } + PrintFunc(dest, "%*sNum SW Ports: %u HFI Ports: %u\n", + indent, "", pImageInfo->numSwitchPorts, + pImageInfo->numHFIPorts); + PrintFunc(dest, "%*sNum SWs: %u Links: %u SMs: %u\n", + indent, "", pImageInfo->numSwitchNodes, + pImageInfo->numLinks, pImageInfo->numSMs); + PrintFunc(dest, "%*sNum NoResp Nodes: %u NoResp Ports: %u Unexpected Clear Ports: %u\n", + indent, "", pImageInfo->numNoRespNodes, + pImageInfo->numNoRespPorts, + pImageInfo->numUnexpectedClearPorts); + PrintFunc(dest, "%*sNum Skipped Nodes: %u Skipped Ports: %u\n", + indent, "", pImageInfo->numSkippedNodes, + pImageInfo->numSkippedPorts); + for (i = 0; i < 2; i++) { + if (i != 0 && ! pImageInfo->SMInfo[i].lid) + continue; + PrintFunc(dest, "%*s%s: LID: 0x%.*x Port: %3u Priority: %2u State: %s\n", + indent, "", (i==0)?" Master SM":"Secondary SM", + (pImageInfo->SMInfo[i].lid <= IB_MAX_UCAST_LID ? 4:8), + pImageInfo->SMInfo[i].lid, + pImageInfo->SMInfo[i].portNumber, + pImageInfo->SMInfo[i].priority, + IbSMStateToText(pImageInfo->SMInfo[i].state)); + PrintFunc(dest, "%*s PortGuid: %016"PRIx64"\n", + indent, "", pImageInfo->SMInfo[i].smPortGuid); + PrintFunc(dest, "%*s Name: %.*s\n", + indent, "", (int)sizeof(pImageInfo->SMInfo[i].smNodeDesc), + pImageInfo->SMInfo[i].smNodeDesc); + } + + return; +} + +void PrintStlPAMoveFreeze(PrintDest_t *dest, int indent, const STL_MOVE_FREEZE_DATA *pMoveFreeze) +{ + PrintFunc(dest, "%*sOld Freeze Image\n", indent, ""); + PrintStlPAImageId(dest, indent, &pMoveFreeze->oldFreezeImage); + PrintFunc(dest, "%*sNew Freeze Image\n", indent, ""); + PrintStlPAImageId(dest, indent, &pMoveFreeze->newFreezeImage); + + return; +} + +void PrintStlPAVFList(PrintDest_t *dest, int indent, const int numRecords, const STL_PA_VF_LIST *pVFList) +{ + int i; + + PrintFunc(dest, "%*sNumber of VFs: %u\n", indent, "", numRecords); + for (i = 0; i < numRecords; i++) { + PrintFunc(dest, "%*sVF %u: %s\n", indent, "", i+1, pVFList[i].vfName); + } + return; +} + +void PrintStlPAVFList2(PrintDest_t *dest, int indent, const int numRecords, const STL_PA_VF_LIST2 *pVFList) +{ + int i; + + PrintFunc(dest, "%*sNumber of VFs: %u\n", indent, "", numRecords); + for (i = 0; i < numRecords; i++) { + PrintFunc(dest, "%*sVF %u: %s\n", indent, "", i+1, pVFList[i].vfName); + } + PrintStlPAImageId(dest, indent+2, &pVFList[0].imageId); + return; +} + +void PrintStlPAVFInfo(PrintDest_t *dest, int indent, const STL_PA_VF_INFO_DATA *pVFInfo) +{ + + PrintFunc(dest, "%*sVF name: %s\n", + indent, "", pVFInfo->vfName); + if (pVFInfo->minInternalRate != IB_STATIC_RATE_DONTCARE + || pVFInfo->maxInternalRate != IB_STATIC_RATE_DONTCARE) + PrintFunc(dest, "%*sNumPorts: %u MinRate: %4s MaxRate: %4s MaxMiBps: %u\n", + indent, "", pVFInfo->numPorts, + StlStaticRateToText(pVFInfo->minInternalRate), + StlStaticRateToText(pVFInfo->maxInternalRate), + pVFInfo->maxInternalMBps); + else + PrintFunc(dest, "%*sNum ports: %u\n", + indent, "", pVFInfo->numPorts); + + PrintFunc(dest, "%*sInternal utilization statistics:\n", + indent, ""); + PrintStlPAGroupUtilStats(dest, indent+2, &pVFInfo->internalUtilStats); + PrintFunc(dest, "%*sInternal Error Summary:\n", + indent, ""); + PrintStlPAGroupErrorStats(dest, indent+2, &pVFInfo->internalCategoryStats); + PrintFunc(dest, "%*sImage Id:\n", + indent, ""); + PrintStlPAImageId(dest, indent+2, &pVFInfo->imageId); + + return; +} + +void PrintStlPAVFConfig(PrintDest_t *dest, int indent, const char *vfName, const int numRecords, const STL_PA_VF_CFG_RSP *pVFConfig) +{ + int i; + + PrintFunc(dest, "%*sVF name: %s\n", + indent, "", vfName); + PrintFunc(dest, "%*sNumber ports: %u\n", + indent, "", numRecords); + for (i = 0; i < numRecords; i++) { + PrintFunc(dest, "%*s%u:LID:0x%.*x Port:%u GUID:0x%016"PRIx64" NodeDesc: %.*s\n", + indent, "", i+1, (pVFConfig[i].nodeLid <= IB_MAX_UCAST_LID ? 4:8), + pVFConfig[i].nodeLid, + pVFConfig[i].portNumber, + pVFConfig[i].nodeGUID, + (int)sizeof(pVFConfig[i].nodeDesc), + pVFConfig[i].nodeDesc); + } + PrintStlPAImageId(dest, indent, &pVFConfig->imageId); + + return; +} + +void PrintStlPAVFPortCounters(PrintDest_t *dest, int indent, const STL_PA_VF_PORT_COUNTERS_DATA *pVFPortCounters, const STL_LID nodeLid, const uint32 portNumber, const uint32 flags) +{ + PrintFunc(dest, "%*s%s Controlled VF Port Counters (%s) for node LID 0x%.*x, port number %u%s:\n", indent, "", + (flags & STL_PA_PC_FLAG_USER_COUNTERS) ? "User" : "PM", + (flags & STL_PA_PC_FLAG_DELTA) ? "delta" : "total", + (nodeLid <= IB_MAX_UCAST_LID ? 4:8), + nodeLid, portNumber, + (flags & STL_PA_PC_FLAG_UNEXPECTED_CLEAR) ? " (Unexpected Clear)" : ""); + PrintFunc(dest, "%*sVF name: %s\n", + indent, "", pVFPortCounters->vfName); + PrintFunc(dest, "%*sPerformance: Transmit\n", indent, ""); + PrintFunc(dest, "%*s Xmit Data %20"PRIu64" MB (%"PRIu64" Flits)\n", + indent, "", + pVFPortCounters->portVFXmitData/FLITS_PER_MB, + pVFPortCounters->portVFXmitData); + PrintFunc(dest, "%*s Xmit Pkts %20"PRIu64"\n", + indent, "", + pVFPortCounters->portVFXmitPkts); + PrintFunc(dest, "%*sPerformance: Receive\n", + indent, ""); + PrintFunc(dest, "%*s Rcv Data %20"PRIu64" MB (%"PRIu64" Flits)\n", + indent, "", + pVFPortCounters->portVFRcvData/FLITS_PER_MB, + pVFPortCounters->portVFRcvData); + PrintFunc(dest, "%*s Rcv Pkts %20"PRIu64"\n", + indent, "", + pVFPortCounters->portVFRcvPkts); + PrintFunc(dest, "%*sRouting and Other Errors: \n", + indent, ""); + PrintFunc(dest, "%*s Xmit Discards %20"PRIu64"\n", + indent, "", + pVFPortCounters->portVFXmitDiscards); + PrintFunc(dest, "%*sCongestion: \n", + indent, ""); + PrintFunc(dest, "%*s Congestion Discards %20"PRIu64"\n", + indent, "", + pVFPortCounters->swPortVFCongestion); + PrintFunc(dest, "%*s Rcv FECN %20"PRIu64"\n", + indent, "", + pVFPortCounters->portVFRcvFECN); + PrintFunc(dest, "%*s Rcv BECN %20"PRIu64"\n", + indent, "", + pVFPortCounters->portVFRcvBECN); + PrintFunc(dest, "%*s Mark FECN %20"PRIu64"\n", + indent, "", + pVFPortCounters->portVFMarkFECN); + PrintFunc(dest, "%*s Xmit Time Cong %20"PRIu64"\n", + indent, "", + pVFPortCounters->portVFXmitTimeCong); + PrintFunc(dest, "%*s Xmit Wait %20"PRIu64"\n", + indent, "", + pVFPortCounters->portVFXmitWait); + PrintFunc(dest, "%*sBubbles: \n", + indent, ""); + PrintFunc(dest, "%*s Xmit Wasted BW %20"PRIu64"\n", + indent, "", + pVFPortCounters->portVFXmitWastedBW); + PrintFunc(dest, "%*s Xmit Wait Data %20"PRIu64"\n", + indent, "", + pVFPortCounters->portVFXmitWaitData); + PrintFunc(dest, "%*s Rcv Bubble %20"PRIu64"\n", + indent, "", + pVFPortCounters->portVFRcvBubble); + if (flags & STL_PA_PC_FLAG_SHARED_VL) { + PrintFunc(dest, "\nCounters may be shared between Virtual Fabrics\n\n"); + } + if (flags & STL_PA_PC_FLAG_CLEAR_FAIL) { + PrintFunc(dest, "\nPort Counter Clear was Unsuccessful\n\n"); + } + PrintStlPAImageId(dest, indent, &pVFPortCounters->imageId); + + return; +} + +void PrintStlPAVFFocusPorts(PrintDest_t *dest, int indent, const char *vfName, const int numRecords, const uint32 select, const uint32 start, const uint32 range, + const STL_PA_VF_FOCUS_PORTS_RSP *pVFFocusPorts) +{ + int i; + + PrintFunc(dest, "%*sVF name: %s\n", indent, "", vfName); + PrintFunc(dest, "%*sNumber links: %u\n", indent, "", numRecords); + PrintFunc(dest, "%*sFocus select: %s\n", indent, "", StlFocusAttributeToText(select)); + PrintFunc(dest, "%*sFocus start: %u\n", indent, "", start); + PrintFunc(dest, "%*sFocus range: %u\n", indent, "", range); + for (i = 0; i < numRecords; i++) { + PrintFunc(dest, "%*s%u:LID:0x%04x Port:%u Rate: %4s MTU: %5s nbrLID:0x%04x nbrPort:%u\n", + indent, "", i+start, pVFFocusPorts[i].nodeLid, pVFFocusPorts[i].portNumber, + StlStaticRateToText(pVFFocusPorts[i].rate), IbMTUToText(pVFFocusPorts[i].maxVlMtu), + pVFFocusPorts[i].neighborLid, pVFFocusPorts[i].neighborPortNumber); + + if (IS_FOCUS_SELECT_UTIL(select)) { + PrintFunc(dest, "%*s Value: %16.1f nbrValue: %16.1f\n", + indent, "", (float)pVFFocusPorts[i].value/10.0, (float)pVFFocusPorts[i].neighborValue/10.0); + } else if (IS_FOCUS_SELECT_NO_VAL(select)) { + // Skip print of Values + } else { + PrintFunc(dest, "%*s Value: %16"PRIu64" nbrValue: %16"PRIu64"\n", + indent, "", pVFFocusPorts[i].value, pVFFocusPorts[i].neighborValue); + } + PrintFunc(dest, "%*s GUID: 0x%016"PRIx64" nbrGuid: 0x%016"PRIx64"\n", + indent, "", pVFFocusPorts[i].nodeGUID, pVFFocusPorts[i].neighborGuid); + PrintFunc(dest, "%*s Status: %s Name: %.*s\n", + indent, "", + StlFocusStatusToText(pVFFocusPorts[i].localStatus), + (int)sizeof(pVFFocusPorts[i].nodeDesc), + pVFFocusPorts[i].nodeDesc); + PrintFunc(dest, "%*s Status: %s Neighbor Name: %.*s\n", + indent, "", + StlFocusStatusToText(pVFFocusPorts[i].neighborStatus), + (int)sizeof(pVFFocusPorts[i].neighborNodeDesc), + pVFFocusPorts[i].neighborNodeDesc); + } + PrintStlPAImageId(dest, indent, &pVFFocusPorts[0].imageId); + + return; +} diff --git a/IbPrint/stl_pm.c b/IbPrint/stl_pm.c new file mode 100644 index 0000000..e6e4839 --- /dev/null +++ b/IbPrint/stl_pm.c @@ -0,0 +1,829 @@ +/* BEGIN_ICS_COPYRIGHT7 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT7 ****************************************/ + + +#include "stl_print.h" +#include + +void PrintStlPortStatusRsp(PrintDest_t *dest, int indent, const STL_PORT_STATUS_RSP *pStlPortStatusRsp) +{ + int i, j; + + PrintFunc(dest, "%*sPort Number %u\n", + indent, "", + pStlPortStatusRsp->PortNumber); + PrintFunc(dest, "%*sVL Select Mask 0x%08x\n", + indent+4, "", + pStlPortStatusRsp->VLSelectMask); + + PrintFunc(dest, "%*sPerformance: Transmit\n", + indent+4, ""); + PrintFunc(dest, "%*s Xmit Data %20"PRIu64" MB (%"PRIu64" Flits)\n", + indent+4, "", + pStlPortStatusRsp->PortXmitData/FLITS_PER_MB, + pStlPortStatusRsp->PortXmitData); + PrintFunc(dest, "%*s Xmit Pkts %20"PRIu64"\n", + indent+4, "", + pStlPortStatusRsp->PortXmitPkts); + PrintFunc(dest, "%*s MC Xmt Pkts %20"PRIu64"\n", + indent+4, "", + pStlPortStatusRsp->PortMulticastXmitPkts); + + PrintFunc(dest, "%*sPerformance: Receive\n", + indent+4, ""); + PrintFunc(dest, "%*s Rcv Data %20"PRIu64" MB (%"PRIu64" Flits)\n", + indent+4, "", + pStlPortStatusRsp->PortRcvData/FLITS_PER_MB, + pStlPortStatusRsp->PortRcvData); + PrintFunc(dest, "%*s Rcv Pkts %20"PRIu64"\n", + indent+4, "", + pStlPortStatusRsp->PortRcvPkts); + PrintFunc(dest, "%*s MC Rcv Pkts %20"PRIu64"\n", + indent+4, "", + pStlPortStatusRsp->PortMulticastRcvPkts); + + PrintFunc(dest, "%*sErrors: Signal Integrity\n", + indent+4, ""); + PrintFunc(dest, "%*s Link Qual Indicator %20u (%s)\n", + indent+4, "", + pStlPortStatusRsp->lq.s.LinkQualityIndicator, + StlLinkQualToText(pStlPortStatusRsp->lq.s.LinkQualityIndicator)); + PrintFunc(dest, "%*s Uncorrectable Errors %20u\n", //8 bit + indent+4, "", + pStlPortStatusRsp->UncorrectableErrors); + PrintFunc(dest, "%*s Link Downed %20u\n", // 32 bit + indent+4, "", + pStlPortStatusRsp->LinkDowned); + PrintFunc(dest, "%*s Rcv Errors %20"PRIu64"\n", + indent+4, "", + pStlPortStatusRsp->PortRcvErrors); + PrintFunc(dest, "%*s Exc. Buffer Overrun %20"PRIu64"\n", + indent+4, "", + pStlPortStatusRsp->ExcessiveBufferOverruns); + PrintFunc(dest, "%*s FM Config Errors %20"PRIu64"\n", + indent+4, "", + pStlPortStatusRsp->FMConfigErrors); + PrintFunc(dest, "%*s Local Link Integ Err %20"PRIu64"\n", + indent+4, "", + pStlPortStatusRsp->LocalLinkIntegrityErrors); + PrintFunc(dest, "%*s Link Error Recovery %20u\n", // 32 bit + indent+4, "", + pStlPortStatusRsp->LinkErrorRecovery); + PrintFunc(dest, "%*s Rcv Rmt Phys Err %20"PRIu64"\n", + indent+4, "", + pStlPortStatusRsp->PortRcvRemotePhysicalErrors); + + PrintFunc(dest, "%*sErrors: Security\n", + indent+4, ""); + PrintFunc(dest, "%*s Xmit Constraint %20"PRIu64"\n", + indent+4, "", + pStlPortStatusRsp->PortXmitConstraintErrors); + PrintFunc(dest, "%*s Rcv Constraint %20"PRIu64"\n", + indent+4, "", + pStlPortStatusRsp->PortRcvConstraintErrors); + + PrintFunc(dest, "%*sErrors: Routing and Other Errors\n", + indent+4, ""); + PrintFunc(dest, "%*s Rcv Sw Relay Err %20"PRIu64"\n", + indent+4, "", + pStlPortStatusRsp->PortRcvSwitchRelayErrors); + PrintFunc(dest, "%*s Xmit Discards %20"PRIu64"\n", + indent+4, "", + pStlPortStatusRsp->PortXmitDiscards); + + PrintFunc(dest, "%*sPerformance: Congestion\n", + indent+4, ""); + PrintFunc(dest, "%*s Congestion Discards %20"PRIu64"\n", + indent+4, "", + pStlPortStatusRsp->SwPortCongestion); + PrintFunc(dest, "%*s Rcv FECN %20"PRIu64"\n", + indent+4, "", + pStlPortStatusRsp->PortRcvFECN); + PrintFunc(dest, "%*s Rcv BECN %20"PRIu64"\n", + indent+4, "", + pStlPortStatusRsp->PortRcvBECN); + PrintFunc(dest, "%*s Mark FECN %20"PRIu64"\n", + indent+4, "", + pStlPortStatusRsp->PortMarkFECN); + PrintFunc(dest, "%*s Xmit Time Congestion %20"PRIu64"\n", + indent+4, "", + pStlPortStatusRsp->PortXmitTimeCong); + PrintFunc(dest, "%*s Xmit Wait %20"PRIu64"\n", + indent+4, "", + pStlPortStatusRsp->PortXmitWait); + + PrintFunc(dest, "%*sPerformance: Bubbles\n", + indent+4, ""); + PrintFunc(dest, "%*s Xmit Wasted BW %20"PRIu64"\n", + indent+4, "", + pStlPortStatusRsp->PortXmitWastedBW); + PrintFunc(dest, "%*s Xmit Wait Data %20"PRIu64"\n", + indent+4, "", + pStlPortStatusRsp->PortXmitWaitData); + PrintFunc(dest, "%*s Rcv Bubble %20"PRIu64"\n", + indent+4, "", + pStlPortStatusRsp->PortRcvBubble); + + + + + /* per_VL counters */ + for (i = 0, j = 0; i < STL_MAX_VLS; i++) { + if ((pStlPortStatusRsp->VLSelectMask >> i) & (uint64)1) { + PrintFunc(dest, "\n"); + PrintFunc(dest, "%*s VL Number %d\n", + indent+4, "", + i); + PrintFunc(dest, "%*s Performance: Transmit\n", + indent+8, ""); + PrintFunc(dest, "%*s Xmit Data %20"PRIu64" MB (%"PRIu64" Flits)\n", + indent+8, "", + pStlPortStatusRsp->VLs[j].PortVLXmitData/FLITS_PER_MB, + pStlPortStatusRsp->VLs[j].PortVLXmitData); + PrintFunc(dest, "%*s Xmit Pkts %20"PRIu64"\n", + indent+8, "", + pStlPortStatusRsp->VLs[j].PortVLXmitPkts); + + PrintFunc(dest, "%*s Performance: Receive\n", + indent+8, ""); + PrintFunc(dest, "%*s Rcv Data %20"PRIu64" MB (%"PRIu64" Flits)\n", + indent+8, "", + pStlPortStatusRsp->VLs[j].PortVLRcvData/FLITS_PER_MB, + pStlPortStatusRsp->VLs[j].PortVLRcvData); + PrintFunc(dest, "%*s Rcv Pkts %20"PRIu64"\n", + indent+8, "", + pStlPortStatusRsp->VLs[j].PortVLRcvPkts); + + PrintFunc(dest, "%*s Performance: Congestion\n", + indent+8, ""); + PrintFunc(dest, "%*s Congestion Discards %20"PRIu64"\n", + indent+8, "", + pStlPortStatusRsp->VLs[j].SwPortVLCongestion); + PrintFunc(dest, "%*s Rcv FECN %20"PRIu64"\n", + indent+8, "", + pStlPortStatusRsp->VLs[j].PortVLRcvFECN); + PrintFunc(dest, "%*s Rcv BECN %20"PRIu64"\n", + indent+8, "", + pStlPortStatusRsp->VLs[j].PortVLRcvBECN); + PrintFunc(dest, "%*s Mark FECN %20"PRIu64"\n", + indent+8, "", + pStlPortStatusRsp->VLs[j].PortVLMarkFECN); + PrintFunc(dest, "%*s Xmit Time Congestion %20"PRIu64"\n", + indent+8, "", + pStlPortStatusRsp->VLs[j].PortVLXmitTimeCong); + PrintFunc(dest, "%*s Xmit Wait %20"PRIu64"\n", + indent+8, "", + pStlPortStatusRsp->VLs[j].PortVLXmitWait); + + PrintFunc(dest, "%*s Performance: Bubbles\n", + indent+8, ""); + PrintFunc(dest, "%*s Xmit Wasted BW %20"PRIu64"\n", + indent+8, "", + pStlPortStatusRsp->VLs[j].PortVLXmitWastedBW); + PrintFunc(dest, "%*s Xmit Wait Data %20"PRIu64"\n", + indent+8, "", + pStlPortStatusRsp->VLs[j].PortVLXmitWaitData); + PrintFunc(dest, "%*s Rcv Bubble %20"PRIu64"\n", + indent+8, "", + pStlPortStatusRsp->VLs[j].PortVLRcvBubble); + + PrintFunc(dest, "%*s Errors: Other\n", + indent+8, ""); + PrintFunc(dest, "%*s Xmit Discards %20"PRIu64"\n", + indent+8, "", + pStlPortStatusRsp->VLs[j].PortVLXmitDiscards); + + j++; + } + } + return; +} + +void PrintStlPortStatusRspSummary(PrintDest_t *dest, int indent, const STL_PORT_STATUS_RSP *pStlPortStatusRsp, int printLineByLine) +{ + if (printLineByLine) { + PrintIntWithDotsDec(dest, indent, "XmitDataMB", pStlPortStatusRsp->PortXmitData/FLITS_PER_MB); + PrintIntWithDotsDec(dest, indent, "XmitPkts", pStlPortStatusRsp->PortXmitPkts); + PrintIntWithDotsDec(dest, indent, "RcvDataMB", pStlPortStatusRsp->PortRcvData/FLITS_PER_MB); + PrintIntWithDotsDec(dest, indent, "RcvPkts", pStlPortStatusRsp->PortRcvPkts); + PrintIntWithDotsDec(dest, indent, "LinkQualityIndicator", pStlPortStatusRsp->lq.s.LinkQualityIndicator); + } else { + PrintFunc(dest, "%*sXmit Data: %18"PRIu64" MB Pkts: %20"PRIu64"\n", + indent, "", + pStlPortStatusRsp->PortXmitData/FLITS_PER_MB, + pStlPortStatusRsp->PortXmitPkts); + PrintFunc(dest, "%*sRecv Data: %18"PRIu64" MB Pkts: %20"PRIu64"\n", + indent, "", + pStlPortStatusRsp->PortRcvData/FLITS_PER_MB, + pStlPortStatusRsp->PortRcvPkts); + PrintFunc(dest, "%*sLink Quality: %u (%s)\n", + indent, "", + pStlPortStatusRsp->lq.s.LinkQualityIndicator, + StlLinkQualToText(pStlPortStatusRsp->lq.s.LinkQualityIndicator)); + + } +} + +void PrintStlClearPortStatus(PrintDest_t *dest, int indent, const STL_CLEAR_PORT_STATUS *pStlClearPortStatus) +{ + char buf[128] = {0}; + + if (pStlClearPortStatus->PortSelectMask[0]) { + PrintFunc(dest, "%*s Port Select Mask 0x%016"PRIx64" %016"PRIx64" %016"PRIx64" %016"PRIx64"\n", + indent, "", + pStlClearPortStatus->PortSelectMask[0], + pStlClearPortStatus->PortSelectMask[1], + pStlClearPortStatus->PortSelectMask[2], + pStlClearPortStatus->PortSelectMask[3]); + } else if (pStlClearPortStatus->PortSelectMask[1]) { + PrintFunc(dest, "%*s Port Select Mask 0x%016"PRIx64" %016"PRIx64" %016"PRIx64"\n", + indent, "", + pStlClearPortStatus->PortSelectMask[1], + pStlClearPortStatus->PortSelectMask[2], + pStlClearPortStatus->PortSelectMask[3]); + } else if (pStlClearPortStatus->PortSelectMask[2]) { + PrintFunc(dest, "%*s Port Select Mask 0x%016"PRIx64" %016"PRIx64"\n", + indent, "", + pStlClearPortStatus->PortSelectMask[2], + pStlClearPortStatus->PortSelectMask[3]); + } else { + PrintFunc(dest, "%*s Port Select Mask 0x%016"PRIx64"\n", + indent, "", + pStlClearPortStatus->PortSelectMask[3]); + } + FormatStlCounterSelectMask(buf, pStlClearPortStatus->CounterSelectMask); + PrintFunc(dest, "%*s Counter Sel Mask 0x%08x: %s\n", + indent, "", + pStlClearPortStatus->CounterSelectMask.AsReg32, + buf); +} + +void PrintStlDataPortCountersRsp(PrintDest_t *dest, int indent, const STL_DATA_PORT_COUNTERS_RSP *pStlDataPortCountersRsp) +{ + int i, j, ii, jj; + uint64 portSelectMask; + uint32 vlSelectMask; + struct _port_dpctrs *port; + + if (pStlDataPortCountersRsp->PortSelectMask[0]) { + PrintFunc(dest, "%*s Port Select Mask 0x%016"PRIx64" %016"PRIx64" %016"PRIx64" %016"PRIx64"\n", + indent, "", + pStlDataPortCountersRsp->PortSelectMask[0], + pStlDataPortCountersRsp->PortSelectMask[1], + pStlDataPortCountersRsp->PortSelectMask[2], + pStlDataPortCountersRsp->PortSelectMask[3]); + } else if (pStlDataPortCountersRsp->PortSelectMask[1]) { + PrintFunc(dest, "%*s Port Select Mask 0x%016"PRIx64" %016"PRIx64" %016"PRIx64"\n", + indent, "", + pStlDataPortCountersRsp->PortSelectMask[1], + pStlDataPortCountersRsp->PortSelectMask[2], + pStlDataPortCountersRsp->PortSelectMask[3]); + } else if (pStlDataPortCountersRsp->PortSelectMask[2]) { + PrintFunc(dest, "%*s Port Select Mask 0x%016"PRIx64" %016"PRIx64"\n", + indent, "", + pStlDataPortCountersRsp->PortSelectMask[2], + pStlDataPortCountersRsp->PortSelectMask[3]); + } else { + PrintFunc(dest, "%*s Port Select Mask 0x%016"PRIx64"\n", + indent, "", + pStlDataPortCountersRsp->PortSelectMask[3]); + } + PrintFunc(dest, "%*s VL Select Mask 0x%08x\n", + indent, "", + pStlDataPortCountersRsp->VLSelectMask); + PrintFunc(dest, "%*s LocalLinkIntegrity Resolution %20u\n", + indent, "", + StlShiftToResolution(pStlDataPortCountersRsp->res.s.LocalLinkIntegrityResolution, RES_ADDER_LLI)); + PrintFunc(dest, "%*s LinkErrorRecovery Resolution %20u\n", + indent, "", + StlShiftToResolution(pStlDataPortCountersRsp->res.s.LinkErrorRecoveryResolution, RES_ADDER_LER)); + + + /* Count the bits in the mask and process the ports in succession */ + /* Assume that even though port numbers may not be contiguous, that entries */ + /* in the array are */ + port = (struct _port_dpctrs *)&(pStlDataPortCountersRsp->Port[0]); + for (i = 3; i >= 0; i--) { + portSelectMask = pStlDataPortCountersRsp->PortSelectMask[i]; + for (j = 0; portSelectMask && j < 64; j++, portSelectMask>>= (uint64)1) { + if (portSelectMask & (uint64)1) { + PrintFunc(dest, "%*s Port Number %u\n", + indent, "", + port->PortNumber); + PrintFunc(dest, "%*s Xmit Data %20"PRIu64" MB (%"PRIu64" Flits)\n", + indent+4, "", + port->PortXmitData/FLITS_PER_MB, + port->PortXmitData); + PrintFunc(dest, "%*s Rcv Data %20"PRIu64" MB (%"PRIu64" Flits)\n", + indent+4, "", + port->PortRcvData/FLITS_PER_MB, + port->PortRcvData); + PrintFunc(dest, "%*s Xmit Pkts %20"PRIu64"\n", + indent+4, "", + port->PortXmitPkts); + PrintFunc(dest, "%*s Rcv Pkts %20"PRIu64"\n", + indent+4, "", + port->PortRcvPkts); + PrintFunc(dest, "%*s MC Xmit Pkts %20"PRIu64"\n", + indent+4, "", + port->PortMulticastXmitPkts); + PrintFunc(dest, "%*s MC Rcv Pkts %20"PRIu64"\n", + indent+4, "", + port->PortMulticastRcvPkts); + PrintFunc(dest, "%*s Signal Integrity Errors: \n", + indent, ""); + PrintFunc(dest, "%*s Link Qual. Indicator %20u (%s)\n", + indent+4, "", + port->lq.s.LinkQualityIndicator, + StlLinkQualToText(port->lq.s.LinkQualityIndicator)); + PrintFunc(dest, "%*s Congestion: \n", + indent, ""); + PrintFunc(dest, "%*s Congestion Discards %20"PRIu64"\n", + indent+4, "", + port->SwPortCongestion); + PrintFunc(dest, "%*s Rcv FECN %20"PRIu64"\n", + indent+4, "", + port->PortRcvFECN); + PrintFunc(dest, "%*s Rcv BECN %20"PRIu64"\n", + indent+4, "", + port->PortRcvBECN); + PrintFunc(dest, "%*s Mark FECN %20"PRIu64"\n", + indent+4, "", + port->PortMarkFECN); + PrintFunc(dest, "%*s Xmit Time Cong %20"PRIu64"\n", + indent+4, "", + port->PortXmitTimeCong); + PrintFunc(dest, "%*s Xmit Wait %20"PRIu64"\n", + indent+4, "", + port->PortXmitWait); + PrintFunc(dest, "%*s Bubbles: \n", + indent, ""); + PrintFunc(dest, "%*s Xmit Wasted BW %20"PRIu64"\n", + indent+4, "", + port->PortXmitWastedBW); + PrintFunc(dest, "%*s Xmit Wait Data %20"PRIu64"\n", + indent+4, "", + port->PortXmitWaitData); + PrintFunc(dest, "%*s Rcv Bubble %20"PRIu64"\n", + indent+4, "", + port->PortRcvBubble); + PrintFunc(dest, "%*s Error Counter Summary %20"PRIu64"\n", + indent+4, "", + port->PortErrorCounterSummary); + /* Count the bits in the mask and process the VLs in succession */ + /* Assume that even though VL numbers may not be contiguous, that entries */ + /* in the array are */ + vlSelectMask = pStlDataPortCountersRsp->VLSelectMask; + for (ii = 0, jj = 0; vlSelectMask && ii < STL_MAX_VLS; ii++, vlSelectMask >>= (uint32)1) { + if (vlSelectMask & (uint32)1) { + PrintFunc(dest, "%*s VL Number %d\n", + indent+4, "", + ii); + PrintFunc(dest, "%*s Xmit Data %20"PRIu64" MB (%"PRIu64" Flits)\n", + indent+4, "", + port->VLs[jj].PortVLXmitData/FLITS_PER_MB, + port->VLs[jj].PortVLXmitData); + PrintFunc(dest, "%*s Rcv Data %20"PRIu64" MB (%"PRIu64" Flits)\n", + indent+4, "", + port->VLs[jj].PortVLRcvData/FLITS_PER_MB, + port->VLs[jj].PortVLRcvData); + PrintFunc(dest, "%*s Xmit Pkts %20"PRIu64"\n", + indent+4, "", + port->VLs[jj].PortVLXmitPkts); + PrintFunc(dest, "%*s Rcv Pkts %20"PRIu64"\n", + indent+4, "", + port->VLs[jj].PortVLRcvPkts); + PrintFunc(dest, "%*s Congestion Discards %20"PRIu64"\n", + indent+4, "", + port->VLs[jj].SwPortVLCongestion); + PrintFunc(dest, "%*s Rcv FECN %20"PRIu64"\n", + indent+4, "", + port->VLs[jj].PortVLRcvFECN); + PrintFunc(dest, "%*s Rcv BECN %20"PRIu64"\n", + indent+4, "", + port->VLs[jj].PortVLRcvBECN); + PrintFunc(dest, "%*s Mark FECN %20"PRIu64"\n", + indent+4, "", + port->VLs[jj].PortVLMarkFECN); + PrintFunc(dest, "%*s Xmit Time Cong %20"PRIu64"\n", + indent+4, "", + port->VLs[jj].PortVLXmitTimeCong); + PrintFunc(dest, "%*s Xmit Wait %20"PRIu64"\n", + indent+4, "", + port->VLs[jj].PortVLXmitWait); + PrintFunc(dest, "%*s Xmit Wasted BW %20"PRIu64"\n", + indent+4, "", + port->VLs[jj].PortVLXmitWastedBW); + PrintFunc(dest, "%*s Xmit Wait Data %20"PRIu64"\n", + indent+4, "", + port->VLs[jj].PortVLXmitWaitData); + PrintFunc(dest, "%*s Rcv Bubble %20"PRIu64"\n", + indent+4, "", + port->VLs[jj].PortVLRcvBubble); + jj++; + } + } + port = (struct _port_dpctrs *)&(port->VLs[jj]); + } + } + } +} + +void PrintStlErrorPortCountersRsp(PrintDest_t *dest, int indent, const STL_ERROR_PORT_COUNTERS_RSP *pStlErrorPortCountersRsp) +{ + int i, j, ii, p; + uint64 portSelectMask; + uint32 vlSelectMask; + uint8 vlCount; + struct _port_epctrs *ePort; + + if (pStlErrorPortCountersRsp->PortSelectMask[0]) { + PrintFunc(dest, "%*s Port Select Mask 0x%016"PRIx64" %016"PRIx64" %016"PRIx64" %016"PRIx64"\n", + indent, "", + pStlErrorPortCountersRsp->PortSelectMask[0], + pStlErrorPortCountersRsp->PortSelectMask[1], + pStlErrorPortCountersRsp->PortSelectMask[2], + pStlErrorPortCountersRsp->PortSelectMask[3]); p = 0; + } else if (pStlErrorPortCountersRsp->PortSelectMask[1]) { + PrintFunc(dest, "%*s Port Select Mask 0x%016"PRIx64" %016"PRIx64" %016"PRIx64"\n", + indent, "", + pStlErrorPortCountersRsp->PortSelectMask[1], + pStlErrorPortCountersRsp->PortSelectMask[2], + pStlErrorPortCountersRsp->PortSelectMask[3]); p = 1; + } else if (pStlErrorPortCountersRsp->PortSelectMask[2]) { + PrintFunc(dest, "%*s Port Select Mask 0x%016"PRIx64" %016"PRIx64"\n", + indent, "", + pStlErrorPortCountersRsp->PortSelectMask[2], + pStlErrorPortCountersRsp->PortSelectMask[3]); p = 2; + } else { + PrintFunc(dest, "%*s Port Select Mask 0x%016"PRIx64"\n", + indent, "", + pStlErrorPortCountersRsp->PortSelectMask[3]); p = 3; + } + PrintFunc(dest, "%*s VL Select Mask 0x%08x\n", + indent, "", + pStlErrorPortCountersRsp->VLSelectMask); + + /* Count the bits in the mask and process the ports in succession */ + /* Assume that even though port numbers may not be contiguous, that entries */ + /* in the array are */ + + ePort = (struct _port_epctrs *)&pStlErrorPortCountersRsp->Port[0]; + for (i = 3; i >= p; i--) { + portSelectMask = pStlErrorPortCountersRsp->PortSelectMask[i]; + for (j = 0; portSelectMask && j < 64; j++, portSelectMask >>= (uint64)1) { + if (portSelectMask & (uint64)1) { + PrintFunc(dest, "%*s Port Number %u\n", + indent+1, "", ePort->PortNumber ); + PrintFunc(dest, "%*s Signal Integrity Errors: \n", + indent, ""); + PrintFunc(dest, "%*s Uncorrectable Errors %10u\n", + indent+4, "", ePort->UncorrectableErrors); + PrintFunc(dest, "%*s Link Downed %10u\n", + indent+4, "", ePort->LinkDowned); + PrintFunc(dest, "%*s Rcv Errors %10"PRIu64"\n", + indent+4, "", ePort->PortRcvErrors); + PrintFunc(dest, "%*s Exc. Buffer Overrun %10"PRIu64"\n", + indent+4, "", ePort->ExcessiveBufferOverruns); + PrintFunc(dest, "%*s FM Config Errors %10"PRIu64"\n", + indent+4, "", ePort->FMConfigErrors); + PrintFunc(dest, "%*s Link Error Recovery %10u\n", + indent+4, "", ePort->LinkErrorRecovery); + PrintFunc(dest, "%*s Local Link Integrity %10"PRIu64"\n", + indent+4, "", ePort->LocalLinkIntegrityErrors); + PrintFunc(dest, "%*s Rcv Rmt Phys. Errors %10"PRIu64"\n", + indent+4, "", ePort->PortRcvRemotePhysicalErrors); + PrintFunc(dest, "%*s Security Errors: \n", + indent, ""); + PrintFunc(dest, "%*s Xmit Constraint Errors %10"PRIu64"\n", + indent+4, "", ePort->PortXmitConstraintErrors); + PrintFunc(dest, "%*s Rcv Constraint Errors %10"PRIu64"\n", + indent+4, "", ePort->PortRcvConstraintErrors); + PrintFunc(dest, "%*s Routing and Other Errors: \n", + indent, ""); + PrintFunc(dest, "%*s Rcv Switch Relay %10"PRIu64"\n", + indent+4, "", ePort->PortRcvSwitchRelayErrors); + PrintFunc(dest, "%*s Xmit Discards %10"PRIu64"\n", + indent+4, "", ePort->PortXmitDiscards); + /* Count the bits in the mask and process the VLs in succession */ + /* Assume that even though VL numbers may not be contiguous, that entries */ + /* in the array are */ + for (vlCount = 0, ii = 0, vlSelectMask = pStlErrorPortCountersRsp->VLSelectMask; + vlSelectMask && ii < 32; ii++, vlSelectMask >>= (uint32)1) { + if (vlSelectMask & (uint32)1) { + PrintFunc(dest, "%*s VL Number %d\n", + indent+4, "", ii); + PrintFunc(dest, "%*s Xmit Discards %10"PRIu64"\n", + indent+8, "", ePort->VLs[vlCount++].PortVLXmitDiscards); + } + } + ePort = (struct _port_epctrs *)&ePort->VLs[vlCount]; + } + } + } + return; +} + +/** + * @param headerOnly when true, do not print per-port info + */ +void PrintStlErrorInfoRsp(PrintDest_t *dest, int indent, const STL_ERROR_INFO_RSP *pStlErrorInfoRsp, + int headerOnly) +{ + int i, j, k; + int ii; + uint8 bits; + uint8 *pChar; + char *pBuf; + char displayBuf[256]; + + if (pStlErrorInfoRsp->PortSelectMask[0]) { + PrintFunc(dest, "%*s Port Select Mask 0x%016"PRIx64" %016"PRIx64" %016"PRIx64" %016"PRIx64"\n", + indent, "", + pStlErrorInfoRsp->PortSelectMask[0], + pStlErrorInfoRsp->PortSelectMask[1], + pStlErrorInfoRsp->PortSelectMask[2], + pStlErrorInfoRsp->PortSelectMask[3]); + } else if (pStlErrorInfoRsp->PortSelectMask[1]) { + PrintFunc(dest, "%*s Port Select Mask 0x%016"PRIx64" %016"PRIx64" %016"PRIx64"\n", + indent, "", + pStlErrorInfoRsp->PortSelectMask[1], + pStlErrorInfoRsp->PortSelectMask[2], + pStlErrorInfoRsp->PortSelectMask[3]); + } else if (pStlErrorInfoRsp->PortSelectMask[2]) { + PrintFunc(dest, "%*s Port Select Mask 0x%016"PRIx64" %016"PRIx64"\n", + indent, "", + pStlErrorInfoRsp->PortSelectMask[2], + pStlErrorInfoRsp->PortSelectMask[3]); + } else { + PrintFunc(dest, "%*s Port Select Mask 0x%016"PRIx64"\n", + indent, "", + pStlErrorInfoRsp->PortSelectMask[3]); + } + PrintFunc(dest, "%*s Error Select Mask 0x%08x\n", + indent, "", + pStlErrorInfoRsp->ErrorInfoSelectMask.AsReg32); + + if (headerOnly) + return; + + for (i = 3; i >= 0; i--) { + for (j = 0, k = 0; j < 64; j++) { + if ((pStlErrorInfoRsp->PortSelectMask[i] >> j) & (uint64)1) { + PrintFunc(dest, "%*s Port Number %u\n", + indent, "", + pStlErrorInfoRsp->Port[k].PortNumber); + if (pStlErrorInfoRsp->Port[k].UncorrectableErrorInfo.s.Status) { + PrintFunc(dest, "%*s Uncorr Error Info %s\n", + indent+4, "", + ":"); + PrintFunc(dest, "%*s Error Code %s (%u)\n", + indent+4, "", + UncorrectableErrorInfoToText(pStlErrorInfoRsp->Port[k].UncorrectableErrorInfo.s.ErrorCode), + pStlErrorInfoRsp->Port[k].UncorrectableErrorInfo.s.ErrorCode); + } else { + PrintFunc(dest, "%*s Uncorr Error Info %s\n", + indent+4, "", + "N/A"); + } + if (pStlErrorInfoRsp->Port[k].PortRcvErrorInfo.s.Status) { + PrintFunc(dest, "%*s Rcv Error Info %s\n", + indent+4, "", + ":"); + PrintFunc(dest, "%*s Error Code %s (%u)\n", + indent+4, "", + PortRcvErrorInfoToText(pStlErrorInfoRsp->Port[k].PortRcvErrorInfo.s.ErrorCode), + pStlErrorInfoRsp->Port[k].PortRcvErrorInfo.s.ErrorCode); + + if ((pStlErrorInfoRsp->Port[k].PortRcvErrorInfo.s.ErrorCode == RCVERRORINFO1) || + ((pStlErrorInfoRsp->Port[k].PortRcvErrorInfo.s.ErrorCode >= RCVERRORINFO4) && + (pStlErrorInfoRsp->Port[k].PortRcvErrorInfo.s.ErrorCode <= RCVERRORINFO12))) { + pBuf = displayBuf; + for (ii = 0, pChar = (uint8 *)pStlErrorInfoRsp->Port[k].PortRcvErrorInfo.ErrorInfo.EI1to12.PacketFlit1; ii < 8; ii++) { + sprintf(pBuf, "0x%02x ", *pChar++); + pBuf += 5; + } + bits = (uint8)pStlErrorInfoRsp->Port[k].PortRcvErrorInfo.ErrorInfo.EI1to12.s.Flit1Bits; + pChar = &bits; + sprintf(pBuf, "%01x ", *pChar++); + pBuf += 2; + *pBuf = '\0'; + PrintFunc(dest, "%*s Flit 1: %s\n", + indent+4, "", + displayBuf); + pBuf = displayBuf; + for (ii = 0, pChar = (uint8 *)pStlErrorInfoRsp->Port[k].PortRcvErrorInfo.ErrorInfo.EI1to12.PacketFlit2; ii < 8; ii++) { + sprintf(pBuf, "0x%02x ", *pChar++); + pBuf += 5; + } + bits = (uint8)pStlErrorInfoRsp->Port[k].PortRcvErrorInfo.ErrorInfo.EI1to12.s.Flit2Bits; + pChar = &bits; + sprintf(pBuf, "%01x ", *pChar++); + pBuf += 2; + *pBuf = '\0'; + PrintFunc(dest, "%*s Flit 2: %s\n", + indent+4, "", + displayBuf); + } else if (pStlErrorInfoRsp->Port[k].PortRcvErrorInfo.s.ErrorCode == RCVERRORINFO13) { + pBuf = displayBuf; + for (ii = 0, pChar = (uint8 *)pStlErrorInfoRsp->Port[k].PortRcvErrorInfo.ErrorInfo.EI13.PacketBytes; ii < 8; ii++) { + sprintf(pBuf, "0x%02x ", *pChar++); + pBuf += 5; + } + bits = (uint8)pStlErrorInfoRsp->Port[k].PortRcvErrorInfo.ErrorInfo.EI13.s.FlitBits; + pChar = &bits; + sprintf(pBuf, "%01x ", *pChar++); + pBuf += 2; + *pBuf = '\0'; + PrintFunc(dest, "%*s VL Marker Flit: %s\n", + indent+4, "", + displayBuf); + } else { + /* bad error code */ + } + } else { + PrintFunc(dest, "%*s Rcv Error Info %s\n", + indent+4, "", + "N/A"); + } + if (pStlErrorInfoRsp->Port[k].ExcessiveBufferOverrunInfo.s.Status) { + PrintFunc(dest, "%*s Exc Buf Overrun Info %s\n", + indent+4, "", + ":"); + PrintFunc(dest, "%*s SC %u\n", + indent+4, "", + pStlErrorInfoRsp->Port[k].ExcessiveBufferOverrunInfo.s.SC); + } else { + PrintFunc(dest, "%*s Exc Buf Overrun Info %s\n", + indent+4, "", + "N/A"); + } + if (pStlErrorInfoRsp->Port[k].FMConfigErrorInfo.s.Status) { + PrintFunc(dest, "%*s FM Config Error Info %s\n", + indent+4, "", + ":"); + PrintFunc(dest, "%*s Error Code %s (%u)\n", + indent+4, "", + FMConfigErrorInfoToText(pStlErrorInfoRsp->Port[k].FMConfigErrorInfo.s.ErrorCode), + pStlErrorInfoRsp->Port[k].FMConfigErrorInfo.s.ErrorCode); + switch(pStlErrorInfoRsp->Port[k].FMConfigErrorInfo.s.ErrorCode) { + case 0: + case 1: + case 2: + case 8: + PrintFunc(dest, "%*s Distance: %u\n", + indent+4, "", + pStlErrorInfoRsp->Port[k].FMConfigErrorInfo.ErrorInfo.EI0to2_8.Distance); + break; + case 3: + case 4: + case 5: + PrintFunc(dest, "%*s VL: %u\n", + indent+4, "", + pStlErrorInfoRsp->Port[k].FMConfigErrorInfo.ErrorInfo.EI3to5.VL); + break; + case 6: + PrintFunc(dest, "%*s Bad Flit Bits: 0x%010x\n", + indent+4, "", + pStlErrorInfoRsp->Port[k].FMConfigErrorInfo.ErrorInfo.EI6.BadFlitBits); + break; + case 7: + PrintFunc(dest, "%*s SC: %u\n", + indent+4, "", + pStlErrorInfoRsp->Port[k].FMConfigErrorInfo.ErrorInfo.EI7.SC); + break; + default: + /* bad error code */ + break; + } + } else { + PrintFunc(dest, "%*s FM Config Error Info %s\n", + indent+4, "", + "N/A"); + } + if (pStlErrorInfoRsp->Port[k].PortRcvSwitchRelayErrorInfo.s.Status) { + PrintFunc(dest, "%*s Rcv Sw Rel Info %s\n", + indent+4, "", + ":"); + PrintFunc(dest, "%*s Error Code %s (%u)\n", + indent+4, "", + PortRcvSwitchRelayErrorInfoToText(pStlErrorInfoRsp->Port[k].PortRcvSwitchRelayErrorInfo.s.ErrorCode), + pStlErrorInfoRsp->Port[k].PortRcvSwitchRelayErrorInfo.s.ErrorCode); + switch (pStlErrorInfoRsp->Port[k].PortRcvSwitchRelayErrorInfo.s.ErrorCode) { + case 0: + PrintFunc(dest, "%*s DLID: 0x%010x\n", + indent+4, "", + pStlErrorInfoRsp->Port[k].PortRcvSwitchRelayErrorInfo.ErrorInfo.EI0.DLID); + PrintFunc(dest, "%*s SLID: 0x%010x\n", + indent+4, "", + (pStlErrorInfoRsp->Port[k].PortRcvSwitchRelayErrorInfo.SLID_23_16 << 16) | + (pStlErrorInfoRsp->Port[k].PortRcvSwitchRelayErrorInfo.SLID_15_0)); + PrintFunc(dest, "%*s SC: %u\n", + indent+4, "", + pStlErrorInfoRsp->Port[k].PortRcvSwitchRelayErrorInfo.ErrorInfo.EI0.SC); + PrintFunc(dest, "%*s RC: %u\n", + indent+4, "", + pStlErrorInfoRsp->Port[k].PortRcvSwitchRelayErrorInfo.s.RC); + break; + case 2: + PrintFunc(dest, "%*s DLID: 0x%010x\n", + indent+4, "", + (pStlErrorInfoRsp->Port[k].PortRcvSwitchRelayErrorInfo.ErrorInfo.EI2.DLID_23_16 << 16) | + (pStlErrorInfoRsp->Port[k].PortRcvSwitchRelayErrorInfo.ErrorInfo.EI2.DLID_15_0)); + PrintFunc(dest, "%*s SLID: 0x%010x\n", + indent+4, "", + (pStlErrorInfoRsp->Port[k].PortRcvSwitchRelayErrorInfo.SLID_23_16 << 16) | + (pStlErrorInfoRsp->Port[k].PortRcvSwitchRelayErrorInfo.SLID_15_0)); + PrintFunc(dest, "%*s Egress Port Num: %u\n", + indent+4, "", + pStlErrorInfoRsp->Port[k].PortRcvSwitchRelayErrorInfo.ErrorInfo.EI2.EgressPortNum); + PrintFunc(dest, "%*s RC: %u\n", + indent+4, "", + pStlErrorInfoRsp->Port[k].PortRcvSwitchRelayErrorInfo.s.RC); + break; + case 3: + PrintFunc(dest, "%*s Egress Port Num: %u\n", + indent+4, "", + pStlErrorInfoRsp->Port[k].PortRcvSwitchRelayErrorInfo.ErrorInfo.EI3.EgressPortNum); + PrintFunc(dest, "%*s SC: %u\n", + indent+4, "", + pStlErrorInfoRsp->Port[k].PortRcvSwitchRelayErrorInfo.ErrorInfo.EI3.SC); + break; + default: + /* bad error code */ + break; + } + } else { + PrintFunc(dest, "%*s Rcv Sw Rel Info %s\n", + indent+4, "", + "N/A"); + } + if (pStlErrorInfoRsp->Port[k].PortXmitConstraintErrorInfo.s.Status) { + PrintFunc(dest, "%*s Xmit Constraint Info %s\n", + indent+4, "", + ":"); + PrintFunc(dest, "%*s P_Key 0x%010x\n", + indent+4, "", + pStlErrorInfoRsp->Port[k].PortXmitConstraintErrorInfo.P_Key); + PrintFunc(dest, "%*s SLID 0x%010x\n", + indent+4, "", + pStlErrorInfoRsp->Port[k].PortXmitConstraintErrorInfo.SLID); + } else { + PrintFunc(dest, "%*s Xmit Constraint Info %s\n", + indent+4, "", + "N/A"); + } + if (pStlErrorInfoRsp->Port[k].PortRcvConstraintErrorInfo.s.Status) { + PrintFunc(dest, "%*s Rcv Constraint Info %s\n", + indent+4, "", + ":"); + if(pStlErrorInfoRsp->Port[k].PortRcvConstraintErrorInfo.s.ErrorCode) + PrintFunc(dest, "%*s Error Code %s (%u)\n", + indent+4, "", + PortRcvConstraintErrorInfoToText( + pStlErrorInfoRsp->Port[k].PortRcvConstraintErrorInfo.s.ErrorCode), + pStlErrorInfoRsp->Port[k].PortRcvConstraintErrorInfo.s.ErrorCode); + PrintFunc(dest, "%*s P_Key 0x%010x\n", + indent+4, "", + pStlErrorInfoRsp->Port[k].PortRcvConstraintErrorInfo.P_Key); + PrintFunc(dest, "%*s SLID 0x%010x\n", + indent+4, "", + pStlErrorInfoRsp->Port[k].PortRcvConstraintErrorInfo.SLID); + } else { + PrintFunc(dest, "%*s Rcv Constraint Info %s\n", + indent+4, "", + "N/A"); + } + k++; + } + } + } + return; +} + diff --git a/IbPrint/stl_print.h b/IbPrint/stl_print.h new file mode 100644 index 0000000..6c0cdee --- /dev/null +++ b/IbPrint/stl_print.h @@ -0,0 +1,329 @@ +/* BEGIN_ICS_COPYRIGHT7 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT7 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +#ifndef __STL_PRINT_H__ +#define __STL_PRINT_H__ + +#include "iba/stl_mad_priv.h" +#include "iba/stl_sm_priv.h" +#include "iba/stl_sa_priv.h" +#include "iba/stl_sd.h" +#include "iba/stl_pm.h" +#include "ibprint.h" + +#if defined (__cplusplus) +extern "C" { +#endif + +// Note: The functions in ibprint.h should be used, unless there is a STL-specific diffference, +// in which case add a print here. There are two groupings for these prints: +// First grouping are those used for debug/output primarily of SM/SMA interactions. +// Second grouping is for RECORD prints in support of customer-visible iba_* prints of SA info. + +// Usage defines +#define CABLEINFO_DETAIL_ONELINE 0 // One-line output +#define CABLEINFO_DETAIL_SUMMARY 1 // Multi-line but abbreviated output +#define CABLEINFO_DETAIL_BRIEF 2 // Brief output +#define CABLEINFO_DETAIL_VERBOSE 3 // Verbose output +#define CABLEINFO_DETAIL_ALL 4 // All fields output +#define RCVERRORINFO1 1 +#define RCVERRORINFO4 4 +#define RCVERRORINFO12 12 +#define RCVERRORINFO13 13 + + +// verbose level of print content +int PrintStlVerboseSet(int level); + +// Basic STL prints +void PrintStlLid(PrintDest_t *dest, int indent, STL_LID lid, int printLineByLine); + +// General classPortInfo +void PrintStlClassPortInfo(PrintDest_t *dest, int indent, const STL_CLASS_PORT_INFO *pClassPortInfo, uint8 MgmtClass); + +// SM/SMA +void PrintStlLedInfo(PrintDest_t *dest, int indent, const STL_LED_INFO *pLedInfo, EUI64 portGuid, int printLineByLine); +void PrintStlSmpHeader(PrintDest_t *dest, int indent, const STL_SMP *smp); +void PrintStlAggregateMember(PrintDest_t *dest, int indent, + const STL_AGGREGATE *aggr); +void PrintStlNodeInfo(PrintDest_t *dest, int indent, const STL_NODE_INFO *pNodeInfo, int printLineByLine); +void PrintStlNodeDesc(PrintDest_t *dest, int indent, const STL_NODE_DESCRIPTION *pStlNodeDesc, int printLineByLine); +void PrintStlPortInfo(PrintDest_t *dest, int indent, const STL_PORT_INFO *pPortInfo, EUI64 portGuid, int PrintLineByLine); + +void PrintStlSwitchInfo(PrintDest_t *dest, int indent, const STL_SWITCH_INFO *pSwitchInfo, STL_LID lid, int PrintLineByLine); +void PrintStlPKeyTable(PrintDest_t *dest, int indent, const STL_PARTITION_TABLE *pPKeyTable, uint16 blockNum, int printLineByLine); +void PrintStlPortInfoSmp(PrintDest_t *dest, int indent, const STL_SMP *smp, EUI64 portGuid, int printLineByLine); + + +void PrintStlPKeyTableSmp(PrintDest_t *dest, int indent, const STL_SMP *smp, + NODE_TYPE nodetype, boolean showHeading, boolean showBlock, int printLineByLine); +void PrintStlSLSCMap(PrintDest_t *dest, int indent, const char* prefix, + const STL_SLSCMAP *pSLSCMap, boolean heading); +void PrintStlSLSCMapSmp(PrintDest_t *dest, int indent, const STL_SMP *smp, + int printLineByLine); +void PrintStlSCSCMap(PrintDest_t *dest, int indent, const char* prefix, + const STL_SCSCMAP *pSCSCMap, boolean heading); +void PrintStlSCSCMapSmp(PrintDest_t *dest, int indent, const STL_SMP *smp, + boolean heading, int printLineByLine); +void PrintStlSCSLMap(PrintDest_t *dest, int indent, const char *prefix, + const STL_SCSLMAP *pSCSLMap, boolean heading); +void PrintStlSCSLMapSmp(PrintDest_t *dest, int indent, const STL_SMP *smp, + int printLineByLine); +void PrintStlSCVLxMap(PrintDest_t *dest, int indent, const char* prefix, + const STL_SCVLMAP *pSCVLMap, boolean heading, + uint16_t attribute, int printLineByLine); +void PrintStlSCVLxMapSmp(PrintDest_t *dest, int indent, const STL_SMP *smp, + NODE_TYPE nodetype, boolean heading, int printLineByLine); + /* NOTE: smp defines Attribute printed via AttributeID */ +void PrintStlLinearFDB(PrintDest_t *dest, int indent, const STL_LINEAR_FORWARDING_TABLE *pLinearFDB, uint32 blockNum, int printLineByLine); + + +void PrintStlVLArbTable(PrintDest_t *dest, int indent, const STL_VLARB_TABLE *pVLArbTable, uint32 blockNum, int printLineByLine); +void PrintStlVLArbTableSmp(PrintDest_t *dest, int indent, const STL_SMP *smp, uint8_t nodeType, int printLineByLine); +void PrintStlMCastSmp(PrintDest_t *dest, int indent, const STL_SMP *smp, uint8_t pos, uint32_t startBlk, uint8_t count, int printLineByLine); +void PrintStlMCastFDB(PrintDest_t *dest, int indent, const STL_MULTICAST_FORWARDING_TABLE *pMCastFDB, uint32 blockNum, int printLineByLine); +void PrintStlInformInfo(PrintDest_t *dest, int indent, const STL_INFORM_INFO *pInformInfo); +void PrintStlCongestionInfo(PrintDest_t *dest, int indent, const STL_CONGESTION_INFO *pCongestionInfo, int printLineByLine); +void PrintStlSwitchCongestionSetting(PrintDest_t *dest, int indent, const STL_SWITCH_CONGESTION_SETTING *pSwCongestionSetting, int printLineByLine); +void PrintStlHfiCongestionSetting(PrintDest_t *dest, int indent, const STL_HFI_CONGESTION_SETTING *pHfiCongestionSetting, int printLineByLine); +void PrintStlSwitchPortCongestionSettingElement(PrintDest_t *dest, int indent, const STL_SWITCH_PORT_CONGESTION_SETTING_ELEMENT *pElement, uint8_t index, int printLineByLine); +void PrintStlSwitchPortCongestionSettingSmp(PrintDest_t *dest, int indent, const STL_SMP *smp, int printLineByLine); +void PrintStlSwitchCongestionLog(PrintDest_t *dest, int indent, const STL_SWITCH_CONGESTION_LOG *pSwCongestionLog, int printLineByLine); +void PrintStlHfiCongestionLog(PrintDest_t *dest, int indent, const STL_HFI_CONGESTION_LOG *pHfiCongestionLog, int printLineByLine); +void PrintStlHfiCongestionControlTab(PrintDest_t *dest, int indent, const STL_HFI_CONGESTION_CONTROL_TABLE *pHfiCongestionControl, uint8_t cnt, uint8_t start, int printLineByLine); +void PrintStlBfrCtlTable(PrintDest_t *dest, int indent, const STL_BUFFER_CONTROL_TABLE *pBfrCtlTable, int printLineByLine); +void PrintStlBfrCtlTableSmp(PrintDest_t *dest, int indent, const STL_SMP *smp, uint8_t nodeType, int printLineByLine); +void PrintStlCableInfoLowPage(PrintDest_t *dest, int indent, const uint8_t *cableInfoData, uint8_t detail, int printLineByLine); +void PrintStlCableInfoHighPage(PrintDest_t *dest, int indent, const uint8_t *cableInfoData, uint8_t portType, uint8_t detail, int printLineByLine); +void PrintStlCableInfoHighPage0DD(PrintDest_t *dest, int indent, const uint8_t *cableInfoData, uint8_t portType, uint8_t detail, int printLineByLine); +void PrintStlCableInfoDump(PrintDest_t *dest, int indent, const uint8_t *cableInfoData, uint16_t addr, uint8_t len, int printLineByLine); +// len is real length of cable data +void PrintStlCableInfo(PrintDest_t *dest, int indent, const uint8_t *cableInfoData, uint16_t addr, uint8_t len, uint8_t portType, uint8_t detail, int printLineByLine, boolean hexOnly); +void PrintStlCableInfoSmp(PrintDest_t *dest, int indent, const STL_SMP *smp, uint8_t portType, int printLineByLine); +void PrintStlPortGroupFDB(PrintDest_t *dest, int indent, const STL_PORT_GROUP_FORWARDING_TABLE *pPortGroupFDB, uint32 blockNum, int printLineByLine); +void PrintStlPortGroupTable(PrintDest_t *dest, int indent, const uint64_t *pPortGroup, uint32 blockNum, int position, int printLineByLine); +// SA/ iba_* customer-visible user commands +// SA one print function for each SA query OutputType +void PrintStlNodeRecord(PrintDest_t *dest, int indent, const STL_NODE_RECORD *pNodeRecord); +void PrintStlPortInfoRecord(PrintDest_t *dest, int indent, const STL_PORTINFO_RECORD *pPortInfoRecord); +void PrintStlPortStateInfo(PrintDest_t *dest, int indent, const STL_PORT_STATE_INFO *psip, uint16 portCount, uint16 startPort, int printLineByLine); +void PrintStlSwitchInfoRecord(PrintDest_t *dest, int indent, const STL_SWITCHINFO_RECORD *pSwitchInfoRecord); +void PrintStlPKeyTableRecord(PrintDest_t *dest, int indent, const STL_P_KEY_TABLE_RECORD *pPKeyTableRecord); +void PrintStlSCSCTableRecord(PrintDest_t *dest, int indent, int extended, const STL_SC_MAPPING_TABLE_RECORD *pSCSCMapRecord); +void PrintStlSLSCTableRecord(PrintDest_t *dest, int indent, const STL_SL2SC_MAPPING_TABLE_RECORD *pSCSLMapRecord); +void PrintStlSCSLTableRecord(PrintDest_t *dest, int indent, const STL_SC2SL_MAPPING_TABLE_RECORD *pSCSLMapRecord); +void PrintStlSCVLxTableRecord(PrintDest_t *dest, int indent, const STL_SC2VL_R_MAPPING_TABLE_RECORD *pSCVLxMapRecord, uint16_t attribute); +void PrintStlSMInfo(PrintDest_t *dest, int indent, const STL_SM_INFO *pSMInfo, STL_LID lid, int printLineByLine); +void PrintStlLinearFDBRecord(PrintDest_t *dest, int indent, const STL_LINEAR_FORWARDING_TABLE_RECORD *pLinearFDBRecord); +void PrintStlVLArbTableRecord(PrintDest_t *dest, int indent, const STL_VLARBTABLE_RECORD *pVLArbTableRecord); +void PrintStlMcMemberRecord(PrintDest_t *dest, int indent, const STL_MCMEMBER_RECORD *pMcMemberRecord); +void PrintStlMCastFDBRecord(PrintDest_t *dest, int indent, const STL_MULTICAST_FORWARDING_TABLE_RECORD *pMCastFDBRecord); +void PrintStlLinkRecord(PrintDest_t *dest, int indent, const STL_LINK_RECORD *pLinkRecord); +void PrintStlServiceRecord(PrintDest_t *dest, int indent, const STL_SERVICE_RECORD *pServiceRecord); +void PrintStlInformInfoRecord(PrintDest_t * dest, int indent, const STL_INFORM_INFO_RECORD * pInformInfoRecord); +void PrintStlVfInfoRecord_detail(PrintDest_t *dest, int indent, int detail, const STL_VFINFO_RECORD *pVfInfo, int showQueryParams); +void PrintStlVfInfoRecord(PrintDest_t *dest, int indent, const STL_VFINFO_RECORD *pVfInfo); +void PrintStlVfInfoRecordCSV(PrintDest_t *dest, int indent, const STL_VFINFO_RECORD *pVfInfo); +void PrintStlVfInfoRecordCSV2(PrintDest_t *dest, int indent, const STL_VFINFO_RECORD *pVfInfo); +void PrintStlTraceRecord(PrintDest_t *dest, int indent, const STL_TRACE_RECORD *pTraceRecord); +void PrintStlFabricInfoRecord(PrintDest_t *dest, int indent, const STL_FABRICINFO_RECORD *pFabricInfoRecord); +void PrintQuarantinedNodeRecord(PrintDest_t *dest, int indent, const STL_QUARANTINED_NODE_RECORD *pQuarantinedNodeRecord); +void PrintStlCongestionInfoRecord(PrintDest_t *dest, int indent, const STL_CONGESTION_INFO_RECORD *pCongestionInfo); +void PrintStlSwitchCongestionSettingRecord(PrintDest_t *dest, int indent, const STL_SWITCH_CONGESTION_SETTING_RECORD *pSwCongestionSetting); +void PrintStlSwitchPortCongestionSettingRecord(PrintDest_t *dest, int indent, const STL_SWITCH_PORT_CONGESTION_SETTING_RECORD *pSwPortCS); +void PrintStlHfiCongestionSettingRecord(PrintDest_t *dest, int indent, const STL_HFI_CONGESTION_SETTING_RECORD *pHfiCongestionSetting); +void PrintStlHfiCongestionControlTabRecord(PrintDest_t *dest, int indent, const STL_HFI_CONGESTION_CONTROL_TABLE_RECORD *pHfiCongestionControl); +void PrintBfrCtlTableRecord(PrintDest_t *dest, int indent, const STL_BUFFER_CONTROL_TABLE_RECORD *pBfrCtlTable); +void PrintStlCableInfoRecord(PrintDest_t *dest, int indent, const STL_CABLE_INFO_RECORD *pCableInfoRecord); +void PrintStlPortGroupTabRecord(PrintDest_t *dest, int indent, const STL_PORT_GROUP_TABLE_RECORD *pRecord); +void PrintStlPortGroupFwdTabRecord(PrintDest_t *dest, int indent, const STL_PORT_GROUP_FORWARDING_TABLE_RECORD *pRecord); +void PrintStlDeviceGroupMemberRecord(PrintDest_t *dest, int indent, const STL_DEVICE_GROUP_MEMBER_RECORD *pRecord); +void PrintStlDeviceGroupNameRecord(PrintDest_t *dest, int indent, const STL_DEVICE_GROUP_NAME_RECORD *pRecord, int record_no); +void PrintStlDeviceTreeMemberRecord(PrintDest_t *dest, int indent, const STL_DEVICE_TREE_MEMBER_RECORD *pRecord); +void PrintStlSwitchCostRecord(PrintDest_t *dest, int indent, const STL_SWITCH_COST_RECORD *pRecord); +// len is real length of cable data +void PrintStlPortSummary(PrintDest_t *dest, int indent, const char* portName, const STL_PORT_INFO *pPortInfo, EUI64 portGuid, uint16_t g_pkey, const uint8_t *cableInfoData, uint16_t addr, uint8_t len, const STL_PORT_STATUS_RSP *pPortStatusRsp, uint8_t detail, int printLineByLine); + +// PM +void PrintStlPortStatusRsp(PrintDest_t *dest, int indent, const STL_PORT_STATUS_RSP *pStlPortStatusRsp); +void PrintStlPortStatusRspSummary(PrintDest_t *dest, int indent, const STL_PORT_STATUS_RSP *pStlPortStatusRsp, int printLineByLine); +void PrintStlClearPortStatus(PrintDest_t *dest, int indent, const STL_CLEAR_PORT_STATUS *pStlClearPortStatus); +void PrintStlDataPortCountersRsp(PrintDest_t *dest, int indent, const STL_DATA_PORT_COUNTERS_RSP *pStlDataPortCountersRsp); +void PrintStlErrorPortCountersRsp(PrintDest_t *dest, int indent, const STL_ERROR_PORT_COUNTERS_RSP *pStlErrorPortCountersRsp); +void PrintStlErrorInfoRsp(PrintDest_t *dest, int indent, const STL_ERROR_INFO_RSP *pStlErrorInfoRsp, int headerOnly); + + +// PA +void PrintStlPAGroupList(PrintDest_t *dest, int indent, const int numRecords, const STL_PA_GROUP_LIST *pGroupList); +void PrintStlPAGroupList2(PrintDest_t *dest, int indent, const int numRecords, const STL_PA_GROUP_LIST2 *pGroupList); +void PrintStlPAGroupInfo(PrintDest_t *dest, int indent, const STL_PA_PM_GROUP_INFO_DATA *pGroupInfo); +void PrintStlPAGroupConfig(PrintDest_t *dest, int indent, const char *groupName, const int numRecords, const STL_PA_PM_GROUP_CFG_RSP *pGroupConfig); +void PrintStlPAGroupNodeInfo(PrintDest_t *dest, int indent, const char *groupName, const int numRecords, const STL_PA_GROUP_NODEINFO_RSP *pGroupNodeInfo); +void PrintStlPAGroupLinkInfo(PrintDest_t *dest, int indent, const char *groupName, const int numRecords, const STL_PA_GROUP_LINKINFO_RSP *pGroupLinkInfo); +void PrintStlPAPortCounters(PrintDest_t *dest, int indent, const STL_PORT_COUNTERS_DATA *pPortCounters, const STL_LID nodeLid, const uint32 portNumber, const uint32 flags); +void PrintStlPMConfig(PrintDest_t *dest, int indent, const STL_PA_PM_CFG_DATA *pPMConfig); +void PrintStlPAImageId(PrintDest_t *dest, int indent, const STL_PA_IMAGE_ID_DATA *pPAImageID); +void PrintStlPAFocusPorts(PrintDest_t *dest, int indent, const char *groupName, const int numRecords, const uint32 select, const uint32 start, const uint32 range, + const STL_FOCUS_PORTS_RSP *pFocusPorts); +void PrintStlPAFocusPortsMultiSelect(PrintDest_t *dest, int indent, const char *groupName, const int numRecords, const uint32 start, const uint32 range, + const STL_FOCUS_PORTS_MULTISELECT_RSP *pFocusPorts, uint8 logical_operator, STL_FOCUS_PORT_TUPLE *tuple); +void PrintStlPAImageInfo(PrintDest_t *dest, int indent, const STL_PA_IMAGE_INFO_DATA *pImageInfo); +void PrintStlPAMoveFreeze(PrintDest_t *dest, int indent, const STL_MOVE_FREEZE_DATA *pMoveFreeze); +void PrintStlPAVFList(PrintDest_t *dest, int indent, const int numRecords, const STL_PA_VF_LIST *pVFList); +void PrintStlPAVFList2(PrintDest_t *dest, int indent, const int numRecords, const STL_PA_VF_LIST2 *pVFList); +void PrintStlPAVFInfo(PrintDest_t *dest, int indent, const STL_PA_VF_INFO_DATA *pVFInfo); +void PrintStlPAVFConfig(PrintDest_t *dest, int indent, const char *vfName, const int numRecords, const STL_PA_VF_CFG_RSP *pVFConfig); +void PrintStlPAVFPortCounters(PrintDest_t *dest, int indent, const STL_PA_VF_PORT_COUNTERS_DATA *pVFPortCounters, const STL_LID nodeLid, const uint32 portNumber, const uint32 flags); +void PrintStlPAVFFocusPorts(PrintDest_t *dest, int indent, const char *vfName, const int numRecords, const uint32 select, const uint32 start, const uint32 range, + const STL_PA_VF_FOCUS_PORTS_RSP *pVFFocusPorts); + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// + +// Print___WithDots for -g option printing fo iba_[sp]maquery +void PrintIntWithDots(PrintDest_t *dest, int indent, const char * name, uint64_t value); +void PrintIntWithDotsFull(PrintDest_t *dest, int indent, const char * name, uint64_t value); +void PrintIntWithDotsDec(PrintDest_t *dest, int indent, const char * name, uint64_t value); +void PrintStrWithDots(PrintDest_t *dest, int indent, const char * name, const char * value); + +#if defined (__cplusplus) +} +#endif + + +static __inline const char* +FMConfigErrorInfoToText(uint8 errorInfo) +{ + switch (errorInfo) { + case 0: return "BadHeadDist"; + case 1: return "BadTailDist"; + case 2: return "BadCtrlDist"; + case 3: return "BadCrdtAck"; + case 4: return "UnsupportedVLMarker"; + case 5: return "BadPreempt"; + case 6: return "BadControlFlit"; + case 7: return "ExceedMulticastLimit"; + case 8: return "BadMarkerDist"; + default: + return "Unknown"; + } +} + +static __inline const char* +PortRcvErrorInfoToText(uint8 errorInfo) +{ + switch (errorInfo) + { + case 0: + return "reserved"; + case 1: + return "BadPktLen"; + case 2: + return "PktLenTooLong"; + case 3: + return "PktLenTooShort"; + case 4: + return "BadSLID"; + case 5: + return "BadDLID"; + case 6: + return "BadL2"; + case 7: + return "BadSC"; + case 8: + return "reserved"; + case 9: + return "Headless"; + case 10: + return "reserved"; + case 11: + return "PreemptError"; + case 12: + return "PreemptVL15"; + case 13: + return "BadVLMarker"; + default: + return "Unknown"; + } +} + +static __inline const char* +PortRcvSwitchRelayErrorInfoToText(uint8 errorInfo) +{ + switch (errorInfo) { + case 0: return "BadDLIDRange"; + case 1: return "reserved"; + case 2: return "BadEgress"; + case 3: return "BadSC2SC"; + default: + return "Unknown"; + } +} + +static __inline const char* +PortRcvConstraintErrorInfoToText(uint8 errorInfo) +{ + switch (errorInfo) + { + case 0: + return "reserved"; + case 1: + return "pkeyViolation"; + case 2: + return "BadSLIDRange"; + case 3: + return "SWP0pkeyCheck"; + default: + return "Unknown"; + } +} +static __inline const char* +UncorrectableErrorInfoToText(uint8 errorInfo) +{ + switch (errorInfo) + { + case 0: + return "BadHead"; + case 1: + return "BadBody"; + case 2: + return "BadTail"; + case 3: + return "BadLFCmd"; + case 4: + return "InternalError"; + default: + return "Unknown"; + } +} + + +#endif /* __STL_PRINT_H__ */ diff --git a/IbPrint/stl_sa.c b/IbPrint/stl_sa.c new file mode 100644 index 0000000..7c81695 --- /dev/null +++ b/IbPrint/stl_sa.c @@ -0,0 +1,705 @@ +/* BEGIN_ICS_COPYRIGHT7 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT7 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "stl_print.h" +#include +#include + +#define SIZE_TIME 256 // used in buffer to generate time string for output + +void +PrintStlNodeRecord(PrintDest_t * dest, int indent, + const STL_NODE_RECORD * pNodeRecord) +{ + PrintFunc(dest, "%*sLID: 0x%08x Type: %s Name: %.*s\n", + indent, "", pNodeRecord->RID.LID, + StlNodeTypeToText(pNodeRecord->NodeInfo.NodeType), + NODE_DESCRIPTION_ARRAY_SIZE, + pNodeRecord->NodeDesc.NodeString); + PrintFunc(dest, "%*sPorts: %d PortNum: %d PartitionCap: %d\n", + indent, "", pNodeRecord->NodeInfo.NumPorts, + pNodeRecord->NodeInfo.u1.s.LocalPortNum, + pNodeRecord->NodeInfo.PartitionCap); + PrintFunc(dest, + "%*sNodeGuid: 0x%016" PRIx64 " PortGuid: 0x%016" PRIx64 "\n", + indent, "", pNodeRecord->NodeInfo.NodeGUID, + pNodeRecord->NodeInfo.PortGUID); + PrintFunc(dest, "%*sSystemImageGuid: 0x%016" PRIx64 "\n", indent, "", + pNodeRecord->NodeInfo.SystemImageGUID); + PrintFunc(dest, + "%*sBaseVersion: %d SmaVersion: %d VendorID: 0x%x DeviceId: 0x%x Revision: 0x%x\n", + indent, "", pNodeRecord->NodeInfo.BaseVersion, + pNodeRecord->NodeInfo.ClassVersion, + pNodeRecord->NodeInfo.u1.s.VendorID, + pNodeRecord->NodeInfo.DeviceID, + pNodeRecord->NodeInfo.Revision); +} + +void +PrintStlPortInfoRecord(PrintDest_t * dest, int indent, + const STL_PORTINFO_RECORD * pPortInfoRecord) +{ + const STL_PORT_INFO *pPortInfo = &pPortInfoRecord->PortInfo; + char buffer[SIZE_TIME]; // Buffer for formatting time output + struct tm *loctime; // Time structure to convert into human readable time + + PrintFunc(dest, + "%*sPortLID: 0x%08x PortNum: 0x%02x (%2u)\n", + indent, "", pPortInfoRecord->RID.EndPortLID, + (uint32) pPortInfoRecord->RID.PortNum, + (uint32) pPortInfoRecord->RID.PortNum); + PrintStlPortInfo(dest, indent, pPortInfo, 0, 0); + + // Print out the linkdown reasons (in time order) + int startIdx = STL_LINKDOWN_REASON_NEXT_INDEX((STL_LINKDOWN_REASON*)&pPortInfoRecord->LinkDownReasons[0]); + if (pPortInfoRecord->LinkDownReasons[startIdx].Timestamp==0) { + // Empty entries exist, reset the startIdx to 0. + startIdx = 0; + } else { + if (++startIdx >= STL_NUM_LINKDOWN_REASONS) { + startIdx = 0; + } + } + // If no Linkdown reasons exist, print notice. + if (pPortInfoRecord->LinkDownReasons[startIdx].Timestamp==0) { + PrintFunc(dest, "%*sLinkDownErrorLog: None\n", indent,""); + } else { + int i = 0; + for (; i < STL_NUM_LINKDOWN_REASONS; i++) { + if (pPortInfoRecord->LinkDownReasons[startIdx].Timestamp==0) { + break; // We are done. + } + uint8 ldr = pPortInfoRecord->LinkDownReasons[startIdx].LinkDownReason; + uint8 nldr = pPortInfoRecord->LinkDownReasons[startIdx].NeighborLinkDownReason; + time_t ts = (time_t) pPortInfoRecord->LinkDownReasons[startIdx].Timestamp; + + loctime=localtime(&ts); // convert timestamp into time structure + if (loctime == NULL) { // ensure we have a valid time back + strncpy(buffer, "N/A", SIZE_TIME); + } + else { + strftime(buffer, SIZE_TIME, "%B %d, %I:%M:%S %p",loctime); // generate time string + } + PrintFunc(dest, "%*sLinkDownErrorLog: %2d (%20s) Time: %s \n", + indent, "", ldr, StlLinkDownReasonToText(ldr), buffer); + PrintFunc(dest, "%*sNeighborLinkDownErrorLog: %2d (%20s) Time: %s\n", + indent, "", nldr, StlLinkDownReasonToText(nldr), buffer); + if (++startIdx >= STL_NUM_LINKDOWN_REASONS) { + startIdx = 0; + } + } + } + +} + +void +PrintStlSwitchInfoRecord(PrintDest_t * dest, int indent, + const STL_SWITCHINFO_RECORD * pSwitchInfoRecord) +{ + PrintStlSwitchInfo(dest, indent, &pSwitchInfoRecord->SwitchInfoData, + pSwitchInfoRecord->RID.LID, 0); +} + +void +PrintStlPKeyTableRecord(PrintDest_t * dest, int indent, + const STL_P_KEY_TABLE_RECORD * pPKeyTableRecord) +{ + PrintFunc(dest, "%*sLID: 0x%08x PortNum: %2u BlockNum: %2u\n", + indent, "", pPKeyTableRecord->RID.LID, + pPKeyTableRecord->RID.PortNum, + pPKeyTableRecord->RID.Blocknum); + PrintStlPKeyTable(dest, indent, &pPKeyTableRecord->PKeyTblData, + pPKeyTableRecord->RID.Blocknum, 0); +} + +void +PrintStlSCSCTableRecord(PrintDest_t * dest, int indent, int extended, + const STL_SC_MAPPING_TABLE_RECORD * pSCSCMapRecord) +{ + PrintFunc(dest, "%*sLID: 0x%08x InputPort: %3u OutputPort: %3u %s\n", + indent, "", + pSCSCMapRecord->RID.LID, pSCSCMapRecord->RID.InputPort, + pSCSCMapRecord->RID.OutputPort, + !extended ? "" : "(secondary)"); + + PrintStlSCSCMap(dest, indent, "", + (STL_SCSCMAP *) & pSCSCMapRecord->Map, TRUE); +} + +void +PrintStlSLSCTableRecord(PrintDest_t * dest, int indent, + const STL_SL2SC_MAPPING_TABLE_RECORD * pSLSCMapRecord) +{ + PrintFunc(dest, "%*sLID: 0x%08x\n", + indent, "", pSLSCMapRecord->RID.LID); + PrintStlSLSCMap(dest, indent, "", + (STL_SLSCMAP *) & pSLSCMapRecord->SLSCMap, TRUE); +} + +void +PrintStlSCSLTableRecord(PrintDest_t * dest, int indent, + const STL_SC2SL_MAPPING_TABLE_RECORD * pSCSLMapRecord) +{ + PrintFunc(dest, "%*sLID: 0x%08x\n", + indent, "", pSCSLMapRecord->RID.LID); + PrintStlSCSLMap(dest, indent, "", + (STL_SCSLMAP *) & pSCSLMapRecord->SCSLMap, TRUE); +} + +void +PrintStlSCVLxTableRecord(PrintDest_t * dest, int indent, + const STL_SC2VL_R_MAPPING_TABLE_RECORD * pSCVLxMapRecord, + uint16_t attribute) +{ + PrintFunc(dest, "%*sLID: 0x%08x Port: %3u\n", + indent, "", pSCVLxMapRecord->RID.LID, + pSCVLxMapRecord->RID.Port); + PrintStlSCVLxMap(dest, indent, "", + (STL_SCVLMAP *) & pSCVLxMapRecord->SCVLMap, TRUE, + attribute, FALSE); +} + +void +PrintStlLinearFDBRecord(PrintDest_t * dest, int indent, + const STL_LINEAR_FORWARDING_TABLE_RECORD * + pLinearFDBRecord) +{ + PrintFunc(dest, "%*sLID: 0x%08x BlockNum: %6u\n", + indent, "", pLinearFDBRecord->RID.LID, + pLinearFDBRecord->RID.BlockNum); + PrintStlLinearFDB(dest, indent, + (STL_LINEAR_FORWARDING_TABLE *) pLinearFDBRecord-> + LinearFdbData, pLinearFDBRecord->RID.BlockNum, 0); +} + + +void +PrintStlVLArbTableRecord(PrintDest_t * dest, int indent, + const STL_VLARBTABLE_RECORD * pVLArbTableRecord) +{ + PrintFunc(dest, "%*sLID: 0x%08x Port: %02u\n", indent, "", + pVLArbTableRecord->RID.LID, + pVLArbTableRecord->RID.OutputPortNum); + PrintStlVLArbTable(dest, indent, &pVLArbTableRecord->VLArbTable, + pVLArbTableRecord->RID.BlockNum, 0); +} + + +void +PrintStlMcMemberRecord(PrintDest_t * dest, int indent, + const STL_MCMEMBER_RECORD * pMcMemberRecord) +{ + char buf[8]; + PrintFunc(dest, "%*sGID: 0x%016" PRIx64 ":0x%016" PRIx64 "\n", + indent, "", + pMcMemberRecord->RID.MGID.AsReg64s.H, + pMcMemberRecord->RID.MGID.AsReg64s.L); + PrintFunc(dest, + "%*sPortGid: 0x%016" PRIx64 ":0x%016" PRIx64 + " Membership: %s%s%s\n", indent, "", + pMcMemberRecord->RID.PortGID.Type.Global.SubnetPrefix, + pMcMemberRecord->RID.PortGID.Type.Global.InterfaceID, + pMcMemberRecord->JoinFullMember ? "Full " : "", + pMcMemberRecord->JoinNonMember ? "Non " : "", + pMcMemberRecord->JoinSendOnlyMember ? "Sendonly " : ""); + FormatTimeoutMult(buf, pMcMemberRecord->PktLifeTime); + PrintFunc(dest, + "%*sMLID: 0x%08x PKey: 0x%04x Mtu: %5s Rate: %4s PktLifeTime: %s\n", + indent, "", pMcMemberRecord->MLID, pMcMemberRecord->P_Key, + IbMTUToText(pMcMemberRecord->Mtu), + StlStaticRateToText(pMcMemberRecord->Rate), buf); + PrintFunc(dest, + "%*sQKey: 0x%08x SL: %2u HopLimit: 0x%02x TClass: 0x%02x\n", + indent, "", pMcMemberRecord->Q_Key, pMcMemberRecord->SL, + pMcMemberRecord->HopLimit, pMcMemberRecord->TClass); +} + +void +PrintStlMCastFDBRecord(PrintDest_t * dest, int indent, + const STL_MULTICAST_FORWARDING_TABLE_RECORD * + pMCastFDBRecord) +{ + PrintFunc(dest, "%*sLID: 0x%08x Position: %1u BlockNum: %7u\n", + indent, "", pMCastFDBRecord->RID.LID, + pMCastFDBRecord->RID.u1.s.Position, + pMCastFDBRecord->RID.u1.s.BlockNum); + PrintStlMCastFDB(dest, indent, &pMCastFDBRecord->MftTable, + pMCastFDBRecord->RID.u1.s.BlockNum, 0); +} + +void +PrintStlLinkRecord(PrintDest_t * dest, int indent, + const STL_LINK_RECORD * pLinkRecord) +{ + { + + PrintFunc(dest, "%*sLID: 0x%08x -> 0x%08x Port: %3u -> %3u\n", + indent, "", + pLinkRecord->RID.FromLID, pLinkRecord->ToLID, + pLinkRecord->RID.FromPort, pLinkRecord->ToPort); + } + +} + + +void +PrintStlInformInfoRecord(PrintDest_t * dest, int indent, + const STL_INFORM_INFO_RECORD * pInformInfoRecord) +{ + PrintFunc(dest, + "%*sSubLID: 0x%08x Enum: 0x%04x\n", indent, "", + pInformInfoRecord->RID.SubscriberLID, + pInformInfoRecord->RID.Enum); + PrintStlInformInfo(dest, indent, &pInformInfoRecord->InformInfoData); +} + +void PrintStlVfInfoRecord_detail(PrintDest_t *dest, int indent, int detail, + const STL_VFINFO_RECORD *pVfInfo, int showQueryParams) +{ + char buf[8]; + char slStr[40]; + + PrintFunc(dest,"%*svFabric Index: %d Name: %s \n", + indent, "", + pVfInfo->vfIndex, + pVfInfo->vfName); + + int remChars = sizeof(slStr); + char *slStrPtr = slStr; + int ret; + + ret = snprintf(slStrPtr, remChars, "%d", pVfInfo->s1.slBase); + if (ret > 0 && ret <= remChars) { + remChars -= ret; + slStrPtr += ret; + } + + + if (pVfInfo->slMulticastSpecified) { + ret = snprintf(slStrPtr, remChars, " McastSL: %d", pVfInfo->slMulticast); + if (ret > 0 && ret <= remChars) { + remChars -= ret; + slStrPtr += ret; + } + } + + if (detail > 1) { + if (showQueryParams != 0) { + PrintFunc(dest,"%*sServiceId: 0x%016"PRIx64" MGID: 0x%016"PRIx64":0x%016"PRIx64"\n", + indent, "", pVfInfo->ServiceID, + pVfInfo->MGID.AsReg64s.H, + pVfInfo->MGID.AsReg64s.L); + } + + // FormatTimeoutMult(buf, pVfInfo->s1.pktLifeTimeInc); + snprintf(buf, 8, "%d", 1<s1.pktLifeTimeInc); + + PrintFunc(dest,"%*sPKey: 0x%x SL: %s Select: 0x%x%s %s%s PktLifeTimeMult: %s \n", + indent, "", + pVfInfo->pKey, + slStr, + pVfInfo->s1.selectFlags, + pVfInfo->s1.selectFlags? ":" : "", + (pVfInfo->s1.selectFlags&STL_VFINFO_REC_SEL_PKEY_QUERY) ? "PKEY " : "", + (pVfInfo->s1.selectFlags&STL_VFINFO_REC_SEL_SL_QUERY) ? "SL ": "", + pVfInfo->s1.pktLifeSpecified? buf: "unspecified"); + + if (pVfInfo->s1.mtuSpecified) { + PrintFunc(dest,"%*sMaxMtu: %5s ", + indent, "", + IbMTUToText(pVfInfo->s1.mtu)); + } else + PrintFunc(dest,"%*sMaxMtu: unlimited ", indent, ""); + + + PrintFunc(dest,"%*sMaxRate: %s ", indent, "", + pVfInfo->s1.rateSpecified ? IbStaticRateToText(pVfInfo->s1.rate) : "unlimited"); + + PrintFunc(dest, "%*sOptions: 0x%02x%s %s%s%s\n", indent, "", + pVfInfo->optionFlags, + pVfInfo->optionFlags? ":" : "", + (pVfInfo->optionFlags&STL_VFINFO_REC_OPT_SECURITY) ? "Security " : "", + (pVfInfo->optionFlags&STL_VFINFO_REC_OPT_QOS) ? "QoS " : "", + (pVfInfo->optionFlags&STL_VFINFO_REC_OPT_FLOW_DISABLE) ? "FlowCtrlDisable" : ""); + + FormatTimeoutMult(buf, pVfInfo->hoqLife); + + if (pVfInfo->optionFlags&STL_VFINFO_REC_OPT_QOS) { + if (pVfInfo->priority) { + if (pVfInfo->bandwidthPercent) { + PrintFunc(dest,"%*sQOS: Bandwidth: %3d%% Priority: %s PreemptionRank: %u HoQLife: %s\n", + indent, "", pVfInfo->bandwidthPercent, "high", pVfInfo->preemptionRank, buf); + } else { + PrintFunc(dest,"%*sQOS: HighPriority PreemptionRank: %u HoQLife: %s\n", indent, "", pVfInfo->preemptionRank, buf); + } + } else { + PrintFunc(dest,"%*sQOS: Bandwidth: %3d%% PreemptionRank: %u HoQLife: %s\n", + indent, "", pVfInfo->bandwidthPercent, pVfInfo->preemptionRank, buf); + } + } else { + PrintFunc(dest,"%*sQOS: Disabled PreemptionRank: %u HoQLife: %s\n", + indent, "", pVfInfo->preemptionRank, buf); + } + } else { + PrintFunc(dest, "%*sPKey: 0x%x SL: %s\n", indent, "", pVfInfo->pKey, slStr); + } +} + +void PrintStlVfInfoRecord(PrintDest_t *dest, int indent, const STL_VFINFO_RECORD *pVfInfo) +{ + PrintStlVfInfoRecord_detail(dest, indent, 255, pVfInfo, 1); +} + +// implementation of single-line VFInfo output +// @param enumsAsText - when true, convert enumerated values to human-readable text, when false print enums as integer values +static void PrintStlVfInfoRecordCSV_impl(PrintDest_t *dest, int indent, const STL_VFINFO_RECORD *pVfInfo, boolean enumsAsText) +{ + char mcastSl[4] = ""; + + if (pVfInfo->slMulticastSpecified) + snprintf(mcastSl, sizeof(mcastSl), "%u", pVfInfo->slMulticast); + + if (enumsAsText) { + PrintFunc(dest,"%*s%s:%d:0x%x:%d:%s:%s:0x%x:%s\n", + + indent, "", + pVfInfo->vfName, + pVfInfo->vfIndex, + pVfInfo->pKey, + pVfInfo->s1.slBase, + (pVfInfo->s1.mtuSpecified)? IbMTUToText(pVfInfo->s1.mtu):"unlimited", + pVfInfo->s1.rateSpecified ? IbStaticRateToText(pVfInfo->s1.rate) : "unlimited", + pVfInfo->optionFlags, + mcastSl); + } else { + PrintFunc(dest,"%*s%s:%d:0x%x:%d:%d:%d:0x%x:%s\n", + indent, "", + pVfInfo->vfName, + pVfInfo->vfIndex, + pVfInfo->pKey, + pVfInfo->s1.slBase, + (pVfInfo->s1.mtuSpecified)? pVfInfo->s1.mtu:0, + pVfInfo->s1.rateSpecified ? pVfInfo->s1.rate:0, + pVfInfo->optionFlags, + mcastSl); + } +} + +// output VFINFO in a delimited format for easy parsing in shell scripts +void PrintStlVfInfoRecordCSV2(PrintDest_t *dest, int indent, const STL_VFINFO_RECORD *pVfInfo) +{ + PrintStlVfInfoRecordCSV_impl(dest, indent, pVfInfo, 0); +} + +// output VFINFO in a delimited format for easy parsing in shell scripts +void PrintStlVfInfoRecordCSV(PrintDest_t *dest, int indent, const STL_VFINFO_RECORD *pVfInfo) +{ + PrintStlVfInfoRecordCSV_impl(dest, indent, pVfInfo, 1); +} + + +void PrintStlTraceRecord(PrintDest_t *dest, int indent, const STL_TRACE_RECORD *pTraceRecord) +{ + PrintFunc(dest, "%*sIDGeneration: 0x%04x\n", + indent, "", pTraceRecord->IDGeneration); + PrintFunc(dest, "%*sNodeType: %s\n", + indent, "", StlNodeTypeToText(pTraceRecord->NodeType)); + PrintFunc(dest, "%*sNodeID: 0x%016"PRIx64" ChassisID: %016"PRIx64"\n", + indent, "", pTraceRecord->NodeID, pTraceRecord->ChassisID); + PrintFunc(dest, "%*sEntryPortID: 0x%016"PRIx64" ExitPortID: %016"PRIx64"\n", + indent, "", pTraceRecord->EntryPortID, pTraceRecord->ExitPortID); + PrintFunc(dest, "%*sEntryPort: 0x%02x ExitPort: 0x%02x\n", + indent, "", pTraceRecord->EntryPort, pTraceRecord->ExitPort); +} + +void PrintStlFabricInfoRecord(PrintDest_t *dest, int indent, const STL_FABRICINFO_RECORD *pFabricInfoRecord) +{ + PrintFunc(dest, "%*sNumber of HFIs: %u\n", + indent, "", pFabricInfoRecord->NumHFIs); + PrintFunc(dest, "%*sNumber of Switches: %u\n", + indent, "", pFabricInfoRecord->NumSwitches); + PrintFunc(dest, "%*sNumber of Links: %u\n", + indent, "", pFabricInfoRecord->NumInternalHFILinks + + pFabricInfoRecord->NumExternalHFILinks + + pFabricInfoRecord->NumInternalISLs + + pFabricInfoRecord->NumExternalISLs); + PrintFunc(dest, "%*sNumber of HFI Links: %-7u (Internal: %u External: %u)\n", + indent, "", pFabricInfoRecord->NumInternalHFILinks + + pFabricInfoRecord->NumExternalHFILinks, + pFabricInfoRecord->NumInternalHFILinks, + pFabricInfoRecord->NumExternalHFILinks); + PrintFunc(dest, "%*sNumber of ISLs: %-7u (Internal: %u External: %u)\n", + indent, "", pFabricInfoRecord->NumInternalISLs + + pFabricInfoRecord->NumExternalISLs, + pFabricInfoRecord->NumInternalISLs, + pFabricInfoRecord->NumExternalISLs); + PrintFunc(dest, "%*sNumber of Degraded Links: %-7u (HFI Links: %u ISLs: %u)\n", + indent, "", pFabricInfoRecord->NumDegradedHFILinks + + pFabricInfoRecord->NumDegradedISLs, + pFabricInfoRecord->NumDegradedHFILinks, + pFabricInfoRecord->NumDegradedISLs); + PrintFunc(dest, "%*sNumber of Omitted Links: %-7u (HFI Links: %u ISLs: %u)\n", + indent, "", pFabricInfoRecord->NumOmittedHFILinks + + pFabricInfoRecord->NumOmittedISLs, + pFabricInfoRecord->NumOmittedHFILinks, + pFabricInfoRecord->NumOmittedISLs); +} + +void PrintQuarantinedNodeRecord(PrintDest_t *dest, int indent, const STL_QUARANTINED_NODE_RECORD *pQuarantinedNodeRecord) +{ + int violStrLen = 256; + char violationString[violStrLen]; + int previousViolation = 0; + memset(violationString, 0, sizeof(violationString)); + + if(pQuarantinedNodeRecord->quarantineReasons & STL_QUARANTINE_REASON_SPOOF_GENERIC) { + strncat(violationString, "NodeGUID/NodeType Spoofing", violStrLen - strlen(violationString)); + previousViolation = 1; + } + if(pQuarantinedNodeRecord->quarantineReasons & STL_QUARANTINE_REASON_TOPO_NODE_DESC) { + strncat(violationString, previousViolation ? ", NodeDesc Mismatch" : "NodeDesc Mismatch", + violStrLen - strlen(violationString)); + previousViolation = 1; + } + if(pQuarantinedNodeRecord->quarantineReasons & STL_QUARANTINE_REASON_TOPO_NODE_GUID) { + strncat(violationString, previousViolation ? ", NodeGUID Mismatch" : "NodeGUID Mismatch", + violStrLen - strlen(violationString)); + previousViolation = 1; + } + if(pQuarantinedNodeRecord->quarantineReasons & STL_QUARANTINE_REASON_TOPO_PORT_GUID) { + strncat(violationString, previousViolation ? ", PortGUID Mismatch" : "PortGUID Mismatch", + violStrLen - strlen(violationString)); + previousViolation = 1; + } + if(pQuarantinedNodeRecord->quarantineReasons & STL_QUARANTINE_REASON_TOPO_UNDEFINED_LINK) { + strncat(violationString, previousViolation ? ", Undefined Link" : "Undefined Link", + violStrLen - strlen(violationString)); + previousViolation = 1; + } + if(pQuarantinedNodeRecord->quarantineReasons & STL_QUARANTINE_REASON_SMALL_MTU_SIZE) { + strncat(violationString, previousViolation ? ", Small MTU Size" : "Small MTU Size", + violStrLen - strlen(violationString)); + previousViolation = 1; + } + if(pQuarantinedNodeRecord->quarantineReasons & STL_QUARANTINE_REASON_VL_COUNT) { + strncat(violationString, previousViolation ? ", Incorrect VL Count" : "Incorrect VL Count", + violStrLen - strlen(violationString)); + previousViolation = 1; + } + if(pQuarantinedNodeRecord->quarantineReasons & STL_QUARANTINE_REASON_MAXLID) { + strncat(violationString, previousViolation ? ", MaximumLID unsupportable" : "MaximumLID unsupportable", + violStrLen - strlen(violationString)); + previousViolation = 1; + } + + PrintFunc(dest, "%*sConnected to Port %d of (LID: 0x%x, NodeGUID: 0x%016" PRIx64 ")\n", indent, "", pQuarantinedNodeRecord->trustedPortNum, pQuarantinedNodeRecord->trustedLid, pQuarantinedNodeRecord->trustedNodeGUID); + PrintFunc(dest, "%*s Offending Node Actual NodeGUID: 0x%016" PRIx64 "\n", indent, "", pQuarantinedNodeRecord->trustedNeighborNodeGUID); + PrintFunc(dest, "%*s Violation(s): %s\n", indent, "", violationString); + + if(pQuarantinedNodeRecord->quarantineReasons & STL_QUARANTINE_REASON_TOPO_NODE_DESC) { + PrintFunc(dest, "%*s Expected Node Description: %.*s\n", indent, "", STL_NODE_DESCRIPTION_ARRAY_SIZE, pQuarantinedNodeRecord->expectedNodeInfo.nodeDesc.NodeString); + } + if(pQuarantinedNodeRecord->quarantineReasons & STL_QUARANTINE_REASON_TOPO_NODE_GUID) { + PrintFunc(dest, "%*s Expected NodeGUID: 0x%016" PRIx64 "\n", indent, "", pQuarantinedNodeRecord->expectedNodeInfo.nodeGUID); + } + if(pQuarantinedNodeRecord->quarantineReasons & STL_QUARANTINE_REASON_TOPO_PORT_GUID) { + PrintFunc(dest, "%*s Expected PortGUID: 0x%016" PRIx64 "\n", indent, "", pQuarantinedNodeRecord->expectedNodeInfo.portGUID); + } + + if(pQuarantinedNodeRecord->quarantineReasons & STL_QUARANTINE_REASON_SPOOF_GENERIC) { + PrintFunc(dest, "%*s \n", indent, ""); + } else { + PrintFunc(dest, "%*s Received node Information:\n", indent, ""); + } + + PrintFunc(dest, "%*s Node Description: %.*s\n", indent, "", NODE_DESCRIPTION_ARRAY_SIZE, pQuarantinedNodeRecord->NodeDesc.NodeString); + PrintFunc(dest, "%*s Type: %s Ports: %d PortNum: %d PartitionCap: %d\n", indent, "", StlNodeTypeToText(pQuarantinedNodeRecord->NodeInfo.NodeType), pQuarantinedNodeRecord->NodeInfo.NumPorts, pQuarantinedNodeRecord->NodeInfo.u1.s.LocalPortNum, pQuarantinedNodeRecord->NodeInfo.PartitionCap); + PrintFunc(dest, "%*s NodeGUID: 0x%016" PRIx64 " PortGUID: 0x%016" PRIx64 "\n", indent, "", pQuarantinedNodeRecord->NodeInfo.NodeGUID, pQuarantinedNodeRecord->NodeInfo.PortGUID); + PrintFunc(dest, "%*s SystemImageGuid: 0x%016" PRIx64 " BaseVersion: %d SmaVersion: %d\n", indent, "", pQuarantinedNodeRecord->NodeInfo.SystemImageGUID, pQuarantinedNodeRecord->NodeInfo.BaseVersion, pQuarantinedNodeRecord->NodeInfo.ClassVersion); + PrintFunc(dest, "%*s VendorID: 0x%x DeviceId: 0x%x Revision: 0x%x\n", indent, "", pQuarantinedNodeRecord->NodeInfo.u1.s.VendorID, pQuarantinedNodeRecord->NodeInfo.DeviceID, pQuarantinedNodeRecord->NodeInfo.Revision); +} + +void PrintStlCongestionInfoRecord(PrintDest_t *dest, int indent, const STL_CONGESTION_INFO_RECORD *pCongestionInfo) { + PrintFunc(dest, "%*sLID %d\n", indent, "", pCongestionInfo->LID); + PrintStlCongestionInfo(dest, indent, &pCongestionInfo->CongestionInfo, 0); +} + +void PrintStlSwitchCongestionSettingRecord(PrintDest_t *dest, int indent, const STL_SWITCH_CONGESTION_SETTING_RECORD *pSwCongestionSetting) { + PrintFunc(dest, "%*sLID %d\n", indent, "", pSwCongestionSetting->LID); + PrintStlSwitchCongestionSetting(dest, indent, &pSwCongestionSetting->SwitchCongestionSetting, 0); +} + +void PrintStlSwitchPortCongestionSettingRecord(PrintDest_t *dest, int indent, const STL_SWITCH_PORT_CONGESTION_SETTING_RECORD *pSwPortCS) { + PrintFunc(dest, "%*sLID %d Port %d:\n", indent, "", pSwPortCS->RID.LID, pSwPortCS->RID.Port); + PrintStlSwitchPortCongestionSettingElement(dest, indent, pSwPortCS->SwitchPortCongestionSetting.Elements, 0, 0); +} + +void PrintStlHfiCongestionSettingRecord(PrintDest_t *dest, int indent, const STL_HFI_CONGESTION_SETTING_RECORD *pHfiCongestionSetting) { + PrintFunc(dest, "%*sLID %d\n", indent, "", pHfiCongestionSetting->LID); + PrintStlHfiCongestionSetting(dest, indent, &pHfiCongestionSetting->HFICongestionSetting, 0); +} + +void PrintStlHfiCongestionControlTabRecord(PrintDest_t *dest, int indent, const STL_HFI_CONGESTION_CONTROL_TABLE_RECORD *pHfiCongestionControl) { + PrintFunc(dest, "%*sLID %d BlockNum %d:\n", indent, "", pHfiCongestionControl->RID.LID, pHfiCongestionControl->RID.BlockNum); + PrintStlHfiCongestionControlTab(dest, indent, &pHfiCongestionControl->HFICongestionControlTable, 1, 0, 0); +} + +void PrintBfrCtlTableRecord(PrintDest_t *dest, int indent, const STL_BUFFER_CONTROL_TABLE_RECORD *pBfrCtlTable) +{ + PrintFunc(dest, "%*sLID %d Port %d:\n", indent, "", pBfrCtlTable->RID.LID, pBfrCtlTable->RID.Port); + PrintStlBfrCtlTable(dest, indent, &pBfrCtlTable->BufferControlTable, 0); +} + +void PrintStlCableInfoRecord(PrintDest_t *dest, int indent, const STL_CABLE_INFO_RECORD *pCableInfoRecord) +{ + PrintFunc(dest, "%*sLID %d Port %d:\nPortType: %s\n", indent, "", + pCableInfoRecord->LID, pCableInfoRecord->Port, StlPortTypeToText(pCableInfoRecord->u1.s.PortType)); + PrintStlCableInfo(dest, indent, pCableInfoRecord->Data, + pCableInfoRecord->u1.s.Address, pCableInfoRecord->Length+1, pCableInfoRecord->u1.s.PortType, CABLEINFO_DETAIL_ALL, 0, FALSE); +} + +void PrintStlPortGroupTabRecord(PrintDest_t *dest, int indent, const STL_PORT_GROUP_TABLE_RECORD *pRecord) +{ + PrintFunc(dest, "%*sLID %d Block %d:\n", indent, "", pRecord->RID.LID, pRecord->RID.BlockNum); + PrintStlPortGroupTable(dest, indent, pRecord->GroupBlock, pRecord->RID.BlockNum, 0, 0); +} + +void PrintStlPortGroupFwdTabRecord(PrintDest_t *dest, int indent, const STL_PORT_GROUP_FORWARDING_TABLE_RECORD *pRecord) +{ + + PrintFunc(dest, "%*sSwitch LID: 0x%08x BlockNum: %6u\n", indent, "", pRecord->RID.LID, pRecord->RID.u1.s.BlockNum); + PrintStlPortGroupFDB(dest, indent+4, (STL_PORT_GROUP_FORWARDING_TABLE *) pRecord->PGFdbData, pRecord->RID.u1.s.BlockNum, 0); +} +void PrintStlDeviceGroupMemberRecord(PrintDest_t *dest, int indent, const STL_DEVICE_GROUP_MEMBER_RECORD *pRecord) +{ + PrintFunc(dest,"%*sDevice Group: %s LID: 0x%08x Port: %d PortGUID: 0x%016" PRIx64 " Node Description: %s\n", indent, "", + pRecord->DeviceGroupName, pRecord->LID, pRecord->Port, pRecord->GUID, pRecord->NodeDescription.NodeString); +} + +void PrintStlDeviceGroupNameRecord(PrintDest_t *dest, int indent, const STL_DEVICE_GROUP_NAME_RECORD *pRecord, int record_no) +{ + PrintFunc(dest,"%*sGroup %d: %s\n", indent, "", + record_no, pRecord->DeviceGroupName); +} + + +void PrintStlDeviceTreeMemberRecord(PrintDest_t *dest, int indent, const STL_DEVICE_TREE_MEMBER_RECORD *pRecord) +{ + char buf_act[256]; + char buf_mode[256]; + int length = strlen("Ports :"); // The string from FormatStlPortMask() + + FormatStlPortMask(buf_act, pRecord->portMaskAct, MAX_STL_PORTS, sizeof(buf_act)); + FormatStlPortMask(buf_mode, pRecord->portMaskPortLinkMode, MAX_STL_PORTS, sizeof(buf_mode)); + + PrintFunc(dest,"%*sNodeLID: 0x%08x NodeGUID: 0x%016" PRIx64 " NodeSystemImageGUID: 0x%016" PRIx64 " Type: [%s] Node Description: [%s] NumPorts: %d Active %s\n", + indent, "", pRecord->LID, pRecord->GUID, pRecord->SystemImageGUID, StlNodeTypeToText(pRecord->NodeType), pRecord->NodeDescription.NodeString, pRecord->NumPorts, + strlen(buf_act) > length ? buf_act : "ports: none"); + +} + +void PrintStlSwitchCostRecord(PrintDest_t *dest, int indent, const STL_SWITCH_COST_RECORD *pRecord) +{ + int i; + PrintFunc(dest, "%*sSource LID: 0x%08x\n", indent, "", pRecord->SLID); + for(i = 0; (i < STL_SWITCH_COST_NUM_ENTRIES) && (pRecord->Cost[i].DLID != 0); ++i){ + PrintFunc(dest, "%*sLID: 0x%08x -> Cost: %u\n", indent+4, "", pRecord->Cost[i].DLID, pRecord->Cost[i].value); + } +} + +#define HEXTOCHAR(c) ((isgraph(c)||(c)==' ')?(c):'.') + +static void FormatChars(char *buf, const uint8* data, uint32 len) +{ + uint32 j; + int offset = 0; + + for (j=0; jRID.ServiceID, + pServiceRecord->RID.ServiceGID.Type.Global.SubnetPrefix, + pServiceRecord->RID.ServiceGID.Type.Global.InterfaceID, + pServiceRecord->RID.ServiceP_Key); + if (pServiceRecord->ServiceLease == SERVICE_LEASE_INFINITE) + strcpy(buf, "Infinite"); + else + // %6d not quite big enough for uint32, but will cover most non-infinite + // practical values + sprintf(buf, "%6d s", pServiceRecord->ServiceLease); + PrintFunc(dest, "%*sLease: %s Name: %s\n", + indent, "", buf, pServiceRecord->ServiceName); + // dump service data + offset=sprintf(buf, "Data8: "); + for (j=0; j<16; ++j) + offset+=sprintf(&buf[offset], " %02x", pServiceRecord->ServiceData8[j]); + offset+=sprintf(&buf[offset], " "); + FormatChars(&buf[offset], pServiceRecord->ServiceData8, 16); + PrintFunc(dest, "%*s%s\n", indent, "", buf); + + offset=sprintf(buf, "Data16:"); + for (j=0; j<8; ++j) + offset+=sprintf(&buf[offset], " %04x", pServiceRecord->ServiceData16[j]); + offset+=sprintf(&buf[offset], " "); + FormatChars(&buf[offset], (uint8*)pServiceRecord->ServiceData16, 16); + PrintFunc(dest, "%*s%s\n", indent, "", buf); + + offset=sprintf(buf, "Data32:"); + for (j=0; j<4; ++j) + offset+=sprintf(&buf[offset], " %08x", pServiceRecord->ServiceData32[j]); + offset+=sprintf(&buf[offset], " "); + FormatChars(&buf[offset], (uint8*)pServiceRecord->ServiceData32, 16); + PrintFunc(dest, "%*s%s\n", indent, "", buf); + + offset=sprintf(buf, "Data64:"); + for (j=0; j<2; ++j) + offset+=sprintf(&buf[offset], " %016"PRIx64, pServiceRecord->ServiceData64[j]); + offset+=sprintf(&buf[offset], " "); + FormatChars(&buf[offset], (uint8*)pServiceRecord->ServiceData64, 16); + PrintFunc(dest, "%*s%s\n", indent, "", buf); +} diff --git a/IbPrint/stl_sma.c b/IbPrint/stl_sma.c new file mode 100644 index 0000000..cac8cae --- /dev/null +++ b/IbPrint/stl_sma.c @@ -0,0 +1,2626 @@ +/* BEGIN_ICS_COPYRIGHT7 **************************************** + +Copyright (c) 2015-2018, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT7 ****************************************/ + +#include + +#include "stl_print.h" +#include + +void PrintStlLid(PrintDest_t *dest, int indent, STL_LID lid, int printLineByLine) +{ + if (printLineByLine) + PrintIntWithDots(dest, indent, "Lid", lid); + else + PrintFunc(dest, "%*s0x%08x\n", indent, "", lid); +} + +// PrintIntWithDots is a local function used when outputing structures in line-by-line format +void PrintIntWithDots(PrintDest_t *dest, int indent, const char * name, uint64_t value) +{ + // 0123456789012345678901234567890123456789012345678901234567890 + char pad[] = "............................................................."; + char dataFormat[] = "%*s%s%.*s : 0x%"PRIx64"\n"; + size_t maxDotColumn = 60; +#ifndef __VXWORKS__ + int padLen = maxDotColumn-strnlen((const char *)name, maxDotColumn); +#else + size_t strlength = min(strlen((const char *)name), maxDotColumn); + int padLen = maxDotColumn-strlength; +#endif + PrintFunc(dest, (const char *)dataFormat, indent, "", name, padLen, pad, value); +} + +// PrintIntWithDotsFull is a local function used when outputing structures in line-by-line format +void PrintIntWithDotsFull(PrintDest_t *dest, int indent, const char * name, uint64_t value) +{ + // 0123456789012345678901234567890123456789012345678901234567890 + char pad[] = "............................................................."; + char dataFormat[] = "%*s%s%.*s : 0x%016"PRIx64"\n"; //add padding for full width + size_t maxDotColumn = 60; +#ifndef __VXWORKS__ + int padLen = maxDotColumn-strnlen((const char *)name, maxDotColumn); +#else + size_t strlength = min(strlen((const char *)name), maxDotColumn); + int padLen = maxDotColumn-strlength; +#endif + PrintFunc(dest, (const char *)dataFormat, indent, "", name, padLen, pad, value); +} + + +// PrintIntWithDotsDec is a local function used when outputing structures in line-by-line format +void PrintIntWithDotsDec(PrintDest_t *dest, int indent, const char * name, uint64_t value) +{ + // 0123456789012345678901234567890123456789012345678901234567890 + char pad[] = "............................................................."; + char dataFormat[] = "%*s%s%.*s : %"PRIu64"\n"; + size_t maxDotColumn = 60; +#ifndef __VXWORKS__ + int padLen = maxDotColumn-strnlen((const char *)name, maxDotColumn); +#else + size_t strlength = min(strlen((const char *)name), maxDotColumn); + int padLen = maxDotColumn-strlength; +#endif + PrintFunc(dest, (const char *)dataFormat, indent, "", name, padLen, pad, value); +} + +// PrintStrWithDots is a local function used when outputing structures in line-by-line format +void PrintStrWithDots(PrintDest_t *dest, int indent, const char * name, const char * value) +{ + // 0123456789012345678901234567890123456789012345678901234567890 + char pad[] = "............................................................."; + char dataFormat[] = "%*s%s%.*s : %s\n"; + size_t maxDotColumn = 60; +#ifndef __VXWORKS__ + int padLen = maxDotColumn-strnlen((const char *)name, maxDotColumn); +#else + size_t strlength = min(strlen((const char *)name), maxDotColumn); + int padLen = maxDotColumn-strlength; +#endif + PrintFunc(dest, (const char *)dataFormat, indent, "", name, padLen, pad, value); +} + +void PrintStlNodeDesc(PrintDest_t *dest, int indent, const STL_NODE_DESCRIPTION *pStlNodeDesc, int printLineByLine) +{ + if (printLineByLine) { + PrintStrWithDots(dest, indent, "NodeString", (const char *)pStlNodeDesc->NodeString); + } + else { +#ifndef __VXWORKS__ + size_t strlength = strnlen((const char *)pStlNodeDesc->NodeString, STL_NODE_DESCRIPTION_ARRAY_SIZE); +#else + size_t strlength = min(strlen((const char *)pStlNodeDesc->NodeString), STL_NODE_DESCRIPTION_ARRAY_SIZE); +#endif + PrintFunc(dest, "%*s%.*s\n", + indent, "", + (int)strlength, + pStlNodeDesc->NodeString); + } +} + +void PrintStlNodeInfo(PrintDest_t *dest, int indent, const STL_NODE_INFO *pNodeInfo, int printLineByLine) +{ + if (printLineByLine) { + PrintIntWithDots(dest, indent, "BaseVersion", pNodeInfo->BaseVersion); + PrintIntWithDots(dest, indent, "ClassVersion", pNodeInfo->ClassVersion); + PrintStrWithDots(dest, indent, "NodeType", StlNodeTypeToText(pNodeInfo->NodeType)); + PrintIntWithDots(dest, indent, "NumPorts", pNodeInfo->NumPorts); + PrintIntWithDotsFull(dest, indent, "SystemImageGUID", pNodeInfo->SystemImageGUID); + PrintIntWithDotsFull(dest, indent, "NodeGUID", pNodeInfo->NodeGUID); + PrintIntWithDotsFull(dest, indent, "PortGUID", pNodeInfo->PortGUID); + PrintIntWithDots(dest, indent, "PartitionCap", pNodeInfo->PartitionCap); + PrintIntWithDots(dest, indent, "DeviceID", pNodeInfo->DeviceID); + PrintIntWithDots(dest, indent, "Revision", pNodeInfo->Revision); + PrintIntWithDots(dest, indent, "u1.AsReg32", pNodeInfo->u1.AsReg32); + PrintIntWithDots(dest, indent, "u1.s.LocalPortNum", pNodeInfo->u1.s.LocalPortNum); + PrintIntWithDots(dest, indent, "u1.s.VendorID", pNodeInfo->u1.s.VendorID); + } + else { + PrintFunc(dest, "%*sType: %s Ports: %d PortNum: %d PartitionCap: %d\n", + indent, "", + StlNodeTypeToText(pNodeInfo->NodeType), pNodeInfo->NumPorts, + pNodeInfo->u1.s.LocalPortNum, pNodeInfo->PartitionCap); + PrintFunc(dest, "%*sNodeGuid: 0x%016"PRIx64" PortGuid: 0x%016"PRIx64"\n", + indent, "", pNodeInfo->NodeGUID, pNodeInfo->PortGUID); + PrintFunc(dest, "%*sSystemImageGuid: 0x%016"PRIx64"\n", + indent, "", pNodeInfo->SystemImageGUID); + PrintFunc(dest, "%*sBaseVersion: %d SmaVersion: %d VendorID: 0x%x DeviceId: 0x%x Revision: 0x%x\n", + indent, "", pNodeInfo->BaseVersion, + pNodeInfo->ClassVersion, pNodeInfo->u1.s.VendorID, + pNodeInfo->DeviceID, pNodeInfo->Revision); + } +} + +void PrintStlPortInfo(PrintDest_t *dest, int indent, const STL_PORT_INFO *pPortInfo, EUI64 portGuid, int printLineByLine) +{ + // Note: This output is used by a number of commands, including opaportinfo. + // By design, there are two formats. The default format (printLineByLine = 0) puts the + // most useful information first, similar to what the IB command did. + // In general, format 0 is patterned after the legacy PrintPortInfo used for IB. + // The second format (printLineByLine = 1) dumps the record in a line-by-line format + // more suitable for record content analysis. + if (printLineByLine) { + PrintIntWithDots(dest, indent, "LID", (uint32)pPortInfo->LID); + PrintIntWithDots(dest, indent, "FlowControlMask", (uint32)pPortInfo->FlowControlMask); + + if (pPortInfo->CapabilityMask3.s.VLSchedulingConfig == VL_SCHED_MODE_VLARB) + PrintIntWithDots(dest, indent, "VL.PreemptCap", (uint32)pPortInfo->VL.PreemptCap); + PrintIntWithDots(dest, indent, "VL.s2.Cap", (uint32)pPortInfo->VL.s2.Cap); + if (pPortInfo->CapabilityMask3.s.VLSchedulingConfig == VL_SCHED_MODE_VLARB) { + PrintIntWithDots(dest, indent, "VL.HighLimit", (uint32)pPortInfo->VL.HighLimit); + PrintIntWithDots(dest, indent, "VL.PreemptingLimit", (uint32)pPortInfo->VL.PreemptingLimit); + PrintIntWithDots(dest, indent, "VL.ArbitrationHighCap", (uint32)pPortInfo->VL.ArbitrationHighCap); + PrintIntWithDots(dest, indent, "VL.ArbitrationLowCap", (uint32)pPortInfo->VL.ArbitrationLowCap); + } + // STL_PORT_STATES + PrintIntWithDots(dest, indent, "PortStates.AsReg32", (uint32)pPortInfo->PortStates.AsReg32); + PrintIntWithDots(dest, indent, "PortStates.s.IsSMConfigurationStarted", (uint32)pPortInfo->PortStates.s.IsSMConfigurationStarted); + PrintIntWithDots(dest, indent, "PortStates.s.NeighborNormal", (uint32)pPortInfo->PortStates.s.NeighborNormal); + PrintIntWithDots(dest, indent, "PortStates.s.OfflineDisabledReason", (uint32)pPortInfo->PortStates.s.OfflineDisabledReason); + PrintIntWithDots(dest, indent, "PortStates.s.PortPhysicalState", (uint32)pPortInfo->PortStates.s.PortPhysicalState); + PrintIntWithDots(dest, indent, "PortStates.s.PortState", (uint32)pPortInfo->PortStates.s.PortState); + PrintIntWithDots(dest, indent, "PortStates.s.LEDEnabled", (uint32)pPortInfo->PortStates.s.LEDEnabled); + PrintIntWithDots(dest, indent, "PortPhysConfig.AsReg8", pPortInfo->PortPhysConfig.AsReg8); + PrintIntWithDots(dest, indent, "PortPhysConfig.s.PortType", pPortInfo->PortPhysConfig.s.PortType); + PrintIntWithDots(dest, indent, "BundleNextPort", (uint32)pPortInfo->BundleNextPort); + PrintIntWithDots(dest, indent, "BundleLane", (uint32)pPortInfo->BundleLane); + PrintIntWithDots(dest, indent, "MultiCollectMask.CollectiveMask", (uint32)pPortInfo->MultiCollectMask.CollectiveMask); + PrintIntWithDots(dest, indent, "MultiCollectMask.MulticastMask", (uint32)pPortInfo->MultiCollectMask.MulticastMask); + PrintIntWithDots(dest, indent, "s1.M_KeyProtectBits", (uint32)pPortInfo->s1.M_KeyProtectBits); + PrintIntWithDots(dest, indent, "s1.LMC", (uint32)pPortInfo->s1.LMC); + PrintIntWithDots(dest, indent, "s2.MasterSMSL", (uint32)pPortInfo->s2.MasterSMSL); + PrintIntWithDots(dest, indent, "s3.PartitionEnforcementInbound", (uint32)pPortInfo->s3.PartitionEnforcementInbound); + PrintIntWithDots(dest, indent, "s3.PartitionEnforcementOutbound", (uint32)pPortInfo->s3.PartitionEnforcementOutbound); + PrintIntWithDots(dest, indent, "s4.OperationalVL", (uint32)pPortInfo->s4.OperationalVL); + PrintIntWithDots(dest, indent, "P_Keys.P_Key_8B", (uint32)pPortInfo->P_Keys.P_Key_8B); + PrintIntWithDots(dest, indent, "P_Keys.P_Key_10B", (uint32)pPortInfo->P_Keys.P_Key_10B); + PrintIntWithDots(dest, indent, "Violations.M_Key", (uint32)pPortInfo->Violations.M_Key); + PrintIntWithDots(dest, indent, "Violations.P_Key", (uint32)pPortInfo->Violations.P_Key); + PrintIntWithDots(dest, indent, "Violations.Q_Key", (uint32)pPortInfo->Violations.Q_Key); + PrintIntWithDots(dest, indent, "SM_TrapQP.QueuePair", (uint32)pPortInfo->SM_TrapQP.s.QueuePair); + PrintIntWithDots(dest, indent, "SA_QP.QueuePair", (uint32)pPortInfo->SA_QP.s.QueuePair); + PrintIntWithDots(dest, indent, "NeighborPortNum", (uint32)pPortInfo->NeighborPortNum); + PrintIntWithDots(dest, indent, "LinkDownReason", (uint32)pPortInfo->LinkDownReason); + PrintIntWithDots(dest, indent, "NeighborLinkDownReason", (uint32)pPortInfo->NeighborLinkDownReason); + PrintIntWithDots(dest, indent, "LinkInitReason", (uint32)pPortInfo->s3.LinkInitReason); + PrintIntWithDots(dest, indent, "Subnet.ClientReregister", (uint32)pPortInfo->Subnet.ClientReregister); + PrintIntWithDots(dest, indent, "Subnet.MulticastPKeyTrapSuppressionEnabled", (uint32)pPortInfo->Subnet.MulticastPKeyTrapSuppressionEnabled); + PrintIntWithDots(dest, indent, "Subnet.Timeout", (uint32)pPortInfo->Subnet.Timeout); + // STL_LINK_SPEED + PrintIntWithDots(dest, indent, "LinkSpeed.Supported", (uint32)pPortInfo->LinkSpeed.Supported); + PrintIntWithDots(dest, indent, "LinkSpeed.Enabled", (uint32)pPortInfo->LinkSpeed.Enabled); + PrintIntWithDots(dest, indent, "LinkSpeed.Active", (uint32)pPortInfo->LinkSpeed.Active); + // STL_LINK_WIDTH + PrintIntWithDots(dest, indent, "LinkWidth.Supported", (uint32)pPortInfo->LinkWidth.Supported); + PrintIntWithDots(dest, indent, "LinkWidth.Enabled", (uint32)pPortInfo->LinkWidth.Enabled); + PrintIntWithDots(dest, indent, "LinkWidth.Active", (uint32)pPortInfo->LinkWidth.Active); + // STL_LINK_DOWNGRADE + PrintIntWithDots(dest, indent, "LinkWidthDowngrade.Supported", (uint32)pPortInfo->LinkWidthDowngrade.Supported); + PrintIntWithDots(dest, indent, "LinkWidthDowngrade.Enabled", (uint32)pPortInfo->LinkWidthDowngrade.Enabled); + PrintIntWithDots(dest, indent, "LinkWidthDowngrade.TxActive", (uint32)pPortInfo->LinkWidthDowngrade.TxActive); + PrintIntWithDots(dest, indent, "LinkWidthDowngrade.RxActive", (uint32)pPortInfo->LinkWidthDowngrade.RxActive); + // STL_PORT_LINK_MODE + PrintIntWithDots(dest, indent, "PortLinkMode.AsReg16", (uint32)pPortInfo->PortLinkMode.AsReg16); + PrintIntWithDots(dest, indent, "PortLinkMode.s.Supported", (uint32)pPortInfo->PortLinkMode.s.Supported); + PrintIntWithDots(dest, indent, "PortLinkMode.s.Enabled", (uint32)pPortInfo->PortLinkMode.s.Enabled); + PrintIntWithDots(dest, indent, "PortLinkMode.s.Active", (uint32)pPortInfo->PortLinkMode.s.Active); + // STL_PORT_LTP_CRC_MODE + PrintIntWithDots(dest, indent, "PortLTPCRCMode.AsReg16", (uint32)pPortInfo->PortLTPCRCMode.AsReg16); + PrintIntWithDots(dest, indent, "PortLTPCRCMode.s.Supported", (uint32)pPortInfo->PortLTPCRCMode.s.Supported); + PrintIntWithDots(dest, indent, "PortLTPCRCMode.s.Enabled", (uint32)pPortInfo->PortLTPCRCMode.s.Enabled); + PrintIntWithDots(dest, indent, "PortLTPCRCMode.s.Active", (uint32)pPortInfo->PortLTPCRCMode.s.Active); + + PrintIntWithDots(dest, indent, "PortMode.AsReg16", (uint32)pPortInfo->PortMode.AsReg16); + PrintIntWithDots(dest, indent, "PortMode.s.IsActiveOptimizeEnabled", (uint32)pPortInfo->PortMode.s.IsActiveOptimizeEnabled); + PrintIntWithDots(dest, indent, "PortMode.s.IsPassThroughEnabled", (uint32)pPortInfo->PortMode.s.IsPassThroughEnabled); + PrintIntWithDots(dest, indent, "PortMode.s.IsVLMarkerEnabled", (uint32)pPortInfo->PortMode.s.IsVLMarkerEnabled); + PrintIntWithDots(dest, indent, "PortMode.s.Is16BTrapQueryEnabled", (uint32)pPortInfo->PortMode.s.Is16BTrapQueryEnabled); + // STL_PORT_PACKET_FORMAT + PrintIntWithDots(dest, indent, "PortPacketFormats.Supported", (uint32)pPortInfo->PortPacketFormats.Supported); + PrintIntWithDots(dest, indent, "PortPacketFormats.Enabled", (uint32)pPortInfo->PortPacketFormats.Enabled); + PrintIntWithDots(dest, indent, "FlitControl.Interleave.AsReg16", (uint32)pPortInfo->FlitControl.Interleave.AsReg16); + PrintIntWithDots(dest, indent, "FlitControl.Interleave.s.DistanceSupported", (uint32)pPortInfo->FlitControl.Interleave.s.DistanceSupported); + PrintIntWithDots(dest, indent, "FlitControl.Interleave.s.DistanceEnabled", (uint32)pPortInfo->FlitControl.Interleave.s.DistanceEnabled); + PrintIntWithDots(dest, indent, "FlitControl.Interleave.s.MaxNestLevelTxEnabled", (uint32)pPortInfo->FlitControl.Interleave.s.MaxNestLevelTxEnabled); + PrintIntWithDots(dest, indent, "FlitControl.Interleave.s.MaxNestLevelRxSupported", (uint32)pPortInfo->FlitControl.Interleave.s.MaxNestLevelRxSupported); + // Convert Flits to bytes and display in decimal + PrintIntWithDotsDec(dest, indent, "FlitControl.Preemption.MinInitial", (uint32)(pPortInfo->FlitControl.Preemption.MinInitial * BYTES_PER_FLIT)); + // Convert Flits to bytes and display in decimal + PrintIntWithDotsDec(dest, indent, "FlitControl.Preemption.MinTail", (uint32)(pPortInfo->FlitControl.Preemption.MinTail * BYTES_PER_FLIT)); + PrintIntWithDots(dest, indent, "FlitControl.Preemption.LargePktLimit", (uint32)pPortInfo->FlitControl.Preemption.LargePktLimit); + PrintIntWithDots(dest, indent, "FlitControl.Preemption.SmallPktLimit", (uint32)pPortInfo->FlitControl.Preemption.SmallPktLimit); + PrintIntWithDots(dest, indent, "FlitControl.Preemption.MaxSmallPktLimit", (uint32)pPortInfo->FlitControl.Preemption.MaxSmallPktLimit); + PrintIntWithDots(dest, indent, "FlitControl.Preemption.PreemptionLimit", (uint32)pPortInfo->FlitControl.Preemption.PreemptionLimit); + + if (pPortInfo->CapabilityMask3.s.IsMAXLIDSupported) { + PrintIntWithDots(dest, indent, "MaxLID", (uint32)pPortInfo->MaxLID); + } + + PrintIntWithDots(dest, indent, "PortErrorAction.AsReg32", (uint32)pPortInfo->PortErrorAction.AsReg32); + PrintIntWithDots(dest, indent, "PortErrorAction.s.ExcessiveBufferOverrun", (uint32)pPortInfo->PortErrorAction.s.ExcessiveBufferOverrun); + PrintIntWithDots(dest, indent, "PortErrorAction.s.FmConfigErrorExceedMulticastLimit", (uint32)pPortInfo->PortErrorAction.s.FmConfigErrorExceedMulticastLimit); + PrintIntWithDots(dest, indent, "PortErrorAction.s.FmConfigErrorBadControlFlit", (uint32)pPortInfo->PortErrorAction.s.FmConfigErrorBadControlFlit); + PrintIntWithDots(dest, indent, "PortErrorAction.s.FmConfigErrorBadPreempt", (uint32)pPortInfo->PortErrorAction.s.FmConfigErrorBadPreempt); + PrintIntWithDots(dest, indent, "PortErrorAction.s.FmConfigErrorUnsupportedVLMarker", (uint32)pPortInfo->PortErrorAction.s.FmConfigErrorUnsupportedVLMarker); + PrintIntWithDots(dest, indent, "PortErrorAction.s.FmConfigErrorBadCrdtAck", (uint32)pPortInfo->PortErrorAction.s.FmConfigErrorBadCrdtAck); + PrintIntWithDots(dest, indent, "PortErrorAction.s.FmConfigErrorBadCtrlDist", (uint32)pPortInfo->PortErrorAction.s.FmConfigErrorBadCtrlDist); + PrintIntWithDots(dest, indent, "PortErrorAction.s.FmConfigErrorBadTailDist", (uint32)pPortInfo->PortErrorAction.s.FmConfigErrorBadTailDist); + PrintIntWithDots(dest, indent, "PortErrorAction.s.FmConfigErrorBadHeadDist", (uint32)pPortInfo->PortErrorAction.s.FmConfigErrorBadHeadDist); + PrintIntWithDots(dest, indent, "PortErrorAction.s.RcvErrorBadVLMarker", (uint32)pPortInfo->PortErrorAction.s.PortRcvErrorBadVLMarker); + PrintIntWithDots(dest, indent, "PortErrorAction.s.RcvErrorPreemptVL15", (uint32)pPortInfo->PortErrorAction.s.PortRcvErrorPreemptVL15); + PrintIntWithDots(dest, indent, "PortErrorAction.s.RcvErrorPreemptError", (uint32)pPortInfo->PortErrorAction.s.PortRcvErrorPreemptError); + PrintIntWithDots(dest, indent, "PortErrorAction.s.RcvErrorBadMidTail", (uint32)pPortInfo->PortErrorAction.s.PortRcvErrorBadMidTail); + PrintIntWithDots(dest, indent, "PortErrorAction.s.RcvErrorReserved", (uint32)pPortInfo->PortErrorAction.s.PortRcvErrorReserved); + PrintIntWithDots(dest, indent, "PortErrorAction.s.RcvErrorBadSC", (uint32)pPortInfo->PortErrorAction.s.PortRcvErrorBadSC); + PrintIntWithDots(dest, indent, "PortErrorAction.s.RcvErrorBadL2", (uint32)pPortInfo->PortErrorAction.s.PortRcvErrorBadL2); + PrintIntWithDots(dest, indent, "PortErrorAction.s.RcvErrorBadDLID", (uint32)pPortInfo->PortErrorAction.s.PortRcvErrorBadDLID); + PrintIntWithDots(dest, indent, "PortErrorAction.s.RcvErrorBadSLID", (uint32)pPortInfo->PortErrorAction.s.PortRcvErrorBadSLID); + PrintIntWithDots(dest, indent, "PortErrorAction.s.RcvErrorPktLenTooShort", (uint32)pPortInfo->PortErrorAction.s.PortRcvErrorPktLenTooShort); + PrintIntWithDots(dest, indent, "PortErrorAction.s.RcvErrorPktLenTooLong", (uint32)pPortInfo->PortErrorAction.s.PortRcvErrorPktLenTooLong); + PrintIntWithDots(dest, indent, "PortErrorAction.s.RcvErrorBadPktLen", (uint32)pPortInfo->PortErrorAction.s.PortRcvErrorBadPktLen); + PrintIntWithDots(dest, indent, "PassThroughControl.EgressPort", (uint32)pPortInfo->PassThroughControl.EgressPort); + PrintIntWithDots(dest, indent, "PassThroughControl.DRControl", (uint32)pPortInfo->PassThroughControl.DRControl); + PrintIntWithDots(dest, indent, "M_KeyLeasePeriod", (uint32)pPortInfo->M_KeyLeasePeriod); + PrintIntWithDots(dest, indent, "BufferUnits.AsReg32", (uint32)pPortInfo->BufferUnits.AsReg32); + PrintIntWithDots(dest, indent, "BufferUnits.s.VL15Init", (uint32)pPortInfo->BufferUnits.s.VL15Init); + PrintIntWithDots(dest, indent, "BufferUnits.s.VL15CreditRate", (uint32)pPortInfo->BufferUnits.s.VL15CreditRate); + PrintIntWithDots(dest, indent, "BufferUnits.s.CreditAck", (uint32)pPortInfo->BufferUnits.s.CreditAck); + PrintIntWithDots(dest, indent, "BufferUnits.s.BufferAlloc", (uint32)pPortInfo->BufferUnits.s.BufferAlloc); + PrintIntWithDots(dest, indent, "MasterSMLID", (uint32)pPortInfo->MasterSMLID); + PrintIntWithDots(dest, indent, "M_Key", pPortInfo->M_Key); + PrintIntWithDots(dest, indent, "SubnetPrefix", pPortInfo->SubnetPrefix); + int i; + char NeighBorMTUbuf[64]; + for (i = 0; i < STL_MAX_VLS/2; i++) { + snprintf(NeighBorMTUbuf, sizeof(NeighBorMTUbuf), "MTUActive[%02d].STL_VL_TO_MTU.AsReg8", i); + PrintIntWithDots(dest, indent, NeighBorMTUbuf, (uint32)pPortInfo->NeighborMTU[i].AsReg8); + snprintf(NeighBorMTUbuf, sizeof(NeighBorMTUbuf), "MTUActive[%02d].STL_VL_TO_MTU.s.VL0_to_MTU", i); + PrintIntWithDots(dest, indent, NeighBorMTUbuf, (uint32)pPortInfo->NeighborMTU[i].s.VL0_to_MTU); + snprintf(NeighBorMTUbuf, sizeof(NeighBorMTUbuf), "MTUActive[%02d].STL_VL_TO_MTU.s.VL1_to_MTU", i); + PrintIntWithDots(dest, indent, NeighBorMTUbuf, (uint32)pPortInfo->NeighborMTU[i].s.VL1_to_MTU); + } + char XmitQbuf[64]; + for (i = 0; i < STL_MAX_VLS; i++) { + snprintf(XmitQbuf, sizeof(XmitQbuf), "XmitQ[%02d].VLStallCount", i); + PrintIntWithDots(dest, indent, XmitQbuf, (uint32)pPortInfo->XmitQ[i].VLStallCount); + snprintf(XmitQbuf, sizeof(XmitQbuf), "XmitQ[%02d].HOQLife", i); + PrintIntWithDots(dest, indent, XmitQbuf, (uint32)pPortInfo->XmitQ[i].HOQLife); + } + char tempBuf[64]; + PrintStrWithDots(dest, indent, "IPAddrIPV6.addr", + inet_ntop(AF_INET6, pPortInfo->IPAddrIPV6.addr, tempBuf, sizeof(tempBuf))); + PrintStrWithDots(dest, indent, "IPAddrIPV4.addr", + inet_ntop(AF_INET, pPortInfo->IPAddrIPV4.addr, tempBuf, sizeof(tempBuf))); + PrintIntWithDots(dest, indent, "NeighborNodeGUID", pPortInfo->NeighborNodeGUID); + + PrintIntWithDots(dest, indent, "CapabilityMask.AsReg32", (uint32)pPortInfo->CapabilityMask.AsReg32); + PrintIntWithDots(dest, indent, "CapabilityMask.s.IsCapabilityMaskNoticeSupported", (uint32)pPortInfo->CapabilityMask.s.IsCapabilityMaskNoticeSupported); + PrintIntWithDots(dest, indent, "CapabilityMask.s.IsVendorClassSupported", (uint32)pPortInfo->CapabilityMask.s.IsVendorClassSupported); + PrintIntWithDots(dest, indent, "CapabilityMask.s.IsDeviceManagementSupported", (uint32)pPortInfo->CapabilityMask.s.IsDeviceManagementSupported); + PrintIntWithDots(dest, indent, "CapabilityMask.s.IsConnectionManagementSupported", (uint32)pPortInfo->CapabilityMask.s.IsConnectionManagementSupported); + PrintIntWithDots(dest, indent, "CapabilityMask.s.IsAutomaticMigrationSupported", (uint32)pPortInfo->CapabilityMask.s.IsAutomaticMigrationSupported); + PrintIntWithDots(dest, indent, "CapabilityMask.s.IsSM", (uint32)pPortInfo->CapabilityMask.s.IsSM); + + PrintIntWithDots(dest, indent, "CapabilityMask3.AsReg16", (uint32)pPortInfo->CapabilityMask3.AsReg16); + PrintIntWithDots(dest, indent, "CapabilityMask3.s.IsMAXLIDSupported", (uint32)pPortInfo->CapabilityMask3.s.IsMAXLIDSupported); + PrintIntWithDots(dest, indent, "CapabilityMask3.s.IsSnoopSupported", (uint32)pPortInfo->CapabilityMask3.s.IsSnoopSupported); + PrintIntWithDots(dest, indent, "CapabilityMask3.s.IsAsyncSC2VLSupported", (uint32)pPortInfo->CapabilityMask3.s.IsAsyncSC2VLSupported); + PrintIntWithDots(dest, indent, "CapabilityMask3.s.IsAddrRangeConfigSupported", (uint32)pPortInfo->CapabilityMask3.s.IsAddrRangeConfigSupported); + PrintIntWithDots(dest, indent, "CapabilityMask3.s.IsPassThroughSupported", (uint32)pPortInfo->CapabilityMask3.s.IsPassThroughSupported); + PrintIntWithDots(dest, indent, "CapabilityMask3.s.IsSharedSpaceSupported", (uint32)pPortInfo->CapabilityMask3.s.IsSharedSpaceSupported); + PrintIntWithDots(dest, indent, "CapabilityMask3.s.IsSharedGroupSpaceSupported", (uint32)pPortInfo->CapabilityMask3.s.IsSharedGroupSpaceSupported); + PrintIntWithDots(dest, indent, "CapabilityMask3.s.IsVLMarkerSupported", (uint32)pPortInfo->CapabilityMask3.s.IsVLMarkerSupported); + PrintIntWithDots(dest, indent, "CapabilityMask3.s.IsVLrSupported", (uint32)pPortInfo->CapabilityMask3.s.IsVLrSupported); + PrintStrWithDots(dest, indent, "CapabilityMask3.s.VLSchedulingConfig", StlVLSchedulingConfigToText(pPortInfo->CapabilityMask3)); + + + PrintIntWithDots(dest, indent, "OverallBufferSpace", (uint32)pPortInfo->OverallBufferSpace); + PrintIntWithDots(dest, indent, "DiagCode.AsReg16", (uint32)pPortInfo->DiagCode.AsReg16); + PrintIntWithDots(dest, indent, "DiagCode.s.UniversalDiagCode", (uint32)pPortInfo->DiagCode.s.UniversalDiagCode); + PrintIntWithDots(dest, indent, "DiagCode.s.VendorDiagCode", (uint32)pPortInfo->DiagCode.s.VendorDiagCode); + PrintIntWithDots(dest, indent, "DiagCode.s.Chain", (uint32)pPortInfo->DiagCode.s.Chain); + + PrintIntWithDots(dest, indent, "ReplayDepth.BufferDepth", + (uint32)((pPortInfo->ReplayDepthH.BufferDepthH << 8) | pPortInfo->ReplayDepth.BufferDepth)); + PrintIntWithDots(dest, indent, "ReplayDepth.WireDepth", + (uint32)((pPortInfo->ReplayDepthH.WireDepthH << 8) | pPortInfo->ReplayDepth.WireDepth)); + PrintIntWithDots(dest, indent, "PortNeighborMode.MgmtAllowed", (uint32)pPortInfo->PortNeighborMode.MgmtAllowed); + PrintIntWithDots(dest, indent, "PortNeighborMode.NeighborFWAuthenBypass", (uint32)pPortInfo->PortNeighborMode.NeighborFWAuthenBypass); + PrintIntWithDots(dest, indent, "PortNeighborMode.NeighborNodeType (0=FI,1=SW,>1=Unknown)", (uint32)pPortInfo->PortNeighborMode.NeighborNodeType); + PrintIntWithDots(dest, indent, "MTU.Cap", (uint32)pPortInfo->MTU.Cap); + PrintIntWithDots(dest, indent, "Resp.TimeValue", (uint32)pPortInfo->Resp.TimeValue); + PrintIntWithDots(dest, indent, "LocalPortNum", (uint32)pPortInfo->LocalPortNum); + } else { + // Patterned after the existing IB output + char tempBuf[64]; + char tempBuf2[64]; + char tempBuf3[64]; + char tempBuf4[64]; + char cbuf[80]; + //int i; + uint8_t ldr=0; + + if (portGuid) { + PrintFunc(dest, "%*sSubnet: %#018"PRIx64" GUID: %#018"PRIx64"\n", + indent, "", pPortInfo->SubnetPrefix, portGuid); + } else { + PrintFunc(dest, "%*sSubnet: %#018"PRIx64"\n", + indent, "", pPortInfo->SubnetPrefix); + } + + if(pPortInfo->LinkDownReason != 0) + ldr = pPortInfo->LinkDownReason; + else if(pPortInfo->NeighborLinkDownReason != 0) + ldr = pPortInfo->NeighborLinkDownReason; + + if(pPortInfo->PortStates.s.PortState == IB_PORT_INIT + && pPortInfo->s3.LinkInitReason) { + PrintFunc(dest, "%*sLocalPort: %-3d PortState: %s (%s)\n", + indent, "", + pPortInfo->LocalPortNum, + StlPortStateToText(pPortInfo->PortStates.s.PortState), + StlLinkInitReasonToText(pPortInfo->s3.LinkInitReason)); + } + else if(pPortInfo->PortStates.s.PortState == IB_PORT_DOWN && ldr) { + PrintFunc(dest, "%*sLocalPort: %-3d PortState: %s (%s)\n", + indent, "", + pPortInfo->LocalPortNum, + StlPortStateToText(pPortInfo->PortStates.s.PortState), + StlLinkDownReasonToText(ldr)); + } + else { + PrintFunc(dest, "%*sLocalPort: %-3d PortState: %s\n", + indent, "", + pPortInfo->LocalPortNum, + StlPortStateToText(pPortInfo->PortStates.s.PortState)); + } + PrintFunc(dest, "%*sPhysicalState: %-14s\n", + indent, "", + StlPortPhysStateToText(pPortInfo->PortStates.s.PortPhysicalState)); + PrintFunc(dest, "%*sOfflineDisabledReason: %-14s\n", + indent, "", + StlPortOfflineDisabledReasonToText(pPortInfo->PortStates.s.OfflineDisabledReason)); + PrintFunc(dest, "%*sIsSMConfigurationStarted: %-5s NeighborNormal: %s\n", + indent, "", + pPortInfo->PortStates.s.IsSMConfigurationStarted?"True":"False", + pPortInfo->PortStates.s.NeighborNormal?"True":"False"); + if (pPortInfo->LID == 0xffffffff) + PrintFunc(dest, "%*sBaseLID: DontCare SMLID: 0x%08x\n", + indent, "", pPortInfo->MasterSMLID); + else + PrintFunc(dest, "%*sBaseLID: 0x%08x SMLID: 0x%08x\n", + indent, "", pPortInfo->LID, pPortInfo->MasterSMLID); + PrintFunc(dest, "%*sLMC: %-2u SMSL: %-2u\n", + indent, "", + pPortInfo->s1.LMC, pPortInfo->s2.MasterSMSL); + FormatTimeoutMult(tempBuf, pPortInfo->Resp.TimeValue); + FormatTimeoutMult(tempBuf2, pPortInfo->Subnet.Timeout); + PrintFunc(dest,"%*sPortType: %-22s LimtRsp/Subnet: %s,%s\n", + indent, "", StlPortTypeToText(pPortInfo->PortPhysConfig.s.PortType), tempBuf, tempBuf2); + PrintFunc(dest, "%*sBundleNextPort:%-3u BundleLane: %-3u\n", + indent, "", + pPortInfo->BundleNextPort, + pPortInfo->BundleLane); + PrintFunc(dest, "%*sM_KEY: 0x%016"PRIx64" Lease: %5u s Protect: %s\n", + indent, "", pPortInfo->M_Key, pPortInfo->M_KeyLeasePeriod, + IbMKeyProtectToText(pPortInfo->s1.M_KeyProtectBits)); +#if 0 + PrintFunc(dest, "%*sMTU: Active: %4u Supported: %4u VL Stall: %u\n", + indent, "", GetBytesFromMtu(pPortInfo->s2.NeighborMTU), + GetBytesFromMtu(pPortInfo->MTU.Cap), pPortInfo->XmitQ.VLStallCount); +#endif + PrintFunc(dest, "%*sLinkWidth Act: %-8s En: %-13s Sup: %-13s\n", + indent,"", + StlLinkWidthToText(pPortInfo->LinkWidth.Active, tempBuf, sizeof(tempBuf)), + StlLinkWidthToText(pPortInfo->LinkWidth.Enabled, tempBuf3, sizeof(tempBuf3)), + StlLinkWidthToText(pPortInfo->LinkWidth.Supported, tempBuf2, sizeof(tempBuf2))); + PrintFunc(dest, "%*sLinkWidthDnGrd ActTx: %-2.2s Rx: %-2.2s En: %-13s Sup: %-13s\n", + indent,"", + StlLinkWidthToText(pPortInfo->LinkWidthDowngrade.TxActive, tempBuf, sizeof(tempBuf)), + StlLinkWidthToText(pPortInfo->LinkWidthDowngrade.RxActive, tempBuf4, sizeof(tempBuf4)), + StlLinkWidthToText(pPortInfo->LinkWidthDowngrade.Enabled, tempBuf3, sizeof(tempBuf3)), + StlLinkWidthToText(pPortInfo->LinkWidthDowngrade.Supported, tempBuf2, sizeof(tempBuf2))); + PrintFunc(dest, "%*sLinkSpeed Act: %-8s En: %-13s Sup: %-13s\n", + indent,"", + StlLinkSpeedToText(pPortInfo->LinkSpeed.Active, tempBuf, sizeof(tempBuf)), + StlLinkSpeedToText(pPortInfo->LinkSpeed.Enabled, tempBuf3, sizeof(tempBuf3)), + StlLinkSpeedToText(pPortInfo->LinkSpeed.Supported, tempBuf2, sizeof(tempBuf2))); + + PrintFunc(dest, "%*sPortLinkMode Act: %-8s En: %-13s Sup: %-13s\n", + indent, "", + StlPortLinkModeToText(pPortInfo->PortLinkMode.s.Active, tempBuf, sizeof(tempBuf)), + StlPortLinkModeToText(pPortInfo->PortLinkMode.s.Enabled, tempBuf3, sizeof(tempBuf3)), + StlPortLinkModeToText(pPortInfo->PortLinkMode.s.Supported, tempBuf2, sizeof(tempBuf2))); + + PrintFunc(dest, "%*sPortLTPCRCMode Act: %-8s En: %-13s Sup: %-13s\n", + indent, "", + StlPortLtpCrcModeToText(pPortInfo->PortLTPCRCMode.s.Active, tempBuf, sizeof(tempBuf)), + StlPortLtpCrcModeToText(pPortInfo->PortLTPCRCMode.s.Enabled, tempBuf3, sizeof(tempBuf3)), + StlPortLtpCrcModeToText(pPortInfo->PortLTPCRCMode.s.Supported, tempBuf2, sizeof(tempBuf2))); + + PrintFunc(dest, "%*sNeighborMode MgmtAllowed: %3s FWAuthBypass: %3s NeighborNodeType: %s\n", + indent, "", + pPortInfo->PortNeighborMode.MgmtAllowed?"Yes":"No", + pPortInfo->PortNeighborMode.NeighborFWAuthenBypass?"On":"Off", + OpaNeighborNodeTypeToText(pPortInfo->PortNeighborMode.NeighborNodeType)); + PrintFunc(dest, "%*sNeighborNodeGuid: 0x%016"PRIx64" NeighborPortNum: %-3d\n", + indent, "", pPortInfo->NeighborNodeGUID, pPortInfo->NeighborPortNum); + + FormatStlPortPacketFormat(cbuf, pPortInfo->PortPacketFormats.Supported, sizeof(cbuf)); + PrintFunc(dest, "%*sPortPacketFormats Sup: %s", + indent, "", cbuf); + FormatStlPortPacketFormat(cbuf, pPortInfo->PortPacketFormats.Enabled, sizeof(cbuf)); + PrintFunc(dest, " En: %s\n", cbuf); + + FormatStlCapabilityMask(cbuf, pPortInfo->CapabilityMask); // same as IB + PrintFunc(dest, "%*sCapability: 0x%08x: %s\n", + indent, "", + pPortInfo->CapabilityMask.AsReg32, cbuf); + FormatStlCapabilityMask3(cbuf, pPortInfo->CapabilityMask3, sizeof(cbuf)); + PrintFunc(dest, "%*sCapability3: 0x%04x: %s\n", + indent, "", pPortInfo->CapabilityMask3.AsReg16, cbuf); + + + PrintFunc(dest, "%*sSM_TrapQP: 0x%x SA_QP: 0x%x\n", + indent, "", + pPortInfo->SM_TrapQP.s.QueuePair, pPortInfo->SA_QP.s.QueuePair); + PrintFunc(dest, "%*sIPAddr IPV6/IPAddr IPv4: %s/%s\n", + indent, "", + inet_ntop(AF_INET6, pPortInfo->IPAddrIPV6.addr, tempBuf, sizeof(tempBuf)), + inet_ntop(AF_INET, pPortInfo->IPAddrIPV4.addr, tempBuf2, sizeof(tempBuf2))); + + PrintFunc(dest, "%*sVLs Active: %d+1\n", + indent, "", pPortInfo->s4.OperationalVL); + if (pPortInfo->CapabilityMask3.s.VLSchedulingConfig == VL_SCHED_MODE_VLARB) { + PrintFunc(dest, "%*sVL: PreemptCap %d Cap %d+1 HighLimit 0x%04x PreemptLimit 0x%04x\n", + indent, "", pPortInfo->VL.PreemptCap, pPortInfo->VL.s2.Cap, + pPortInfo->VL.HighLimit, pPortInfo->VL.PreemptingLimit); + } else + PrintFunc(dest, "%*sVL: Cap %d+1\n", indent, "", pPortInfo->VL.s2.Cap); + + PrintFunc(dest, "%*sVLFlowControlDisabledMask: 0x%08x", indent, "", + pPortInfo->FlowControlMask); + if (pPortInfo->CapabilityMask3.s.VLSchedulingConfig == VL_SCHED_MODE_VLARB) { + PrintFunc(dest, " ArbHighCap: %d ArbLowCap: %d", + pPortInfo->VL.ArbitrationHighCap, + pPortInfo->VL.ArbitrationLowCap); + } + PrintFunc(dest, "\n"); + + PrintFunc(dest, "%*sMulticastMask: 0x%x CollectiveMask: 0x%x\n", + indent, "", pPortInfo->MultiCollectMask.MulticastMask, + pPortInfo->MultiCollectMask.CollectiveMask); + + PrintFunc(dest, "%*sP_Key Enforcement: In: %3s Out: %3s\n", + indent, "", + pPortInfo->s3.PartitionEnforcementInbound?"On":"Off", + pPortInfo->s3.PartitionEnforcementOutbound?"On":"Off"); + + PrintFunc(dest, "%*sP_Keys P_Key_8B: 0x%04x P_Key_10B: 0x%04x\n", + indent, "", pPortInfo->P_Keys.P_Key_8B, pPortInfo->P_Keys.P_Key_10B); + + PrintFunc(dest, "%*sMulticastPKeyTrapSuppressionEnabled: %2u ClientReregister %2u\n", + indent, "", + pPortInfo->Subnet.MulticastPKeyTrapSuppressionEnabled, + pPortInfo->Subnet.ClientReregister); + + PrintFunc(dest, "%*sPortMode ActiveOptimize: %3s PassThru: %3s VLMarker: %3s 16BTrapQuery: %3s\n", + indent, "", + pPortInfo->PortMode.s.IsActiveOptimizeEnabled?"On":"Off", + pPortInfo->PortMode.s.IsPassThroughEnabled?"On":"Off", + pPortInfo->PortMode.s.IsVLMarkerEnabled?"On":"Off", + pPortInfo->PortMode.s.Is16BTrapQueryEnabled?"On":"Off"); + + // Not have to print, passthrough not implemented in gen1 + //PrintFunc(dest, "%*sPassThroughDRControl: %3s\n", + // indent, "", pPortInfo->PassThroughControl.DRControl?"On":"Off"); + PrintFunc(dest, "%*sFlitCtrlInterleave Distance Max: %2u Enabled: %2u\n", + indent, "", + pPortInfo->FlitControl.Interleave.s.DistanceSupported, + pPortInfo->FlitControl.Interleave.s.DistanceEnabled); + PrintFunc(dest, "%*s MaxNestLevelTxEnabled: %u MaxNestLevelRxSupported: %u\n", + indent, "", + pPortInfo->FlitControl.Interleave.s.MaxNestLevelTxEnabled, + pPortInfo->FlitControl.Interleave.s.MaxNestLevelRxSupported); + // Convert Flits to bytes and display in decimal + PrintFunc(dest, "%*sFlitCtrlPreemption MinInitial: %"PRIu64" MinTail: %"PRIu64" LargePktLim: 0x%02x\n", + indent, "", + (uint64_t)(pPortInfo->FlitControl.Preemption.MinInitial * BYTES_PER_FLIT), + (uint64_t)(pPortInfo->FlitControl.Preemption.MinTail * BYTES_PER_FLIT), + pPortInfo->FlitControl.Preemption.LargePktLimit); + PrintFunc(dest, "%*s SmallPktLimit: 0x%02x MaxSmallPktLimit 0x%02x PreemptionLimit: 0x%02x\n", + indent, "", + pPortInfo->FlitControl.Preemption.SmallPktLimit, + pPortInfo->FlitControl.Preemption.MaxSmallPktLimit, + pPortInfo->FlitControl.Preemption.PreemptionLimit); + + if (pPortInfo->CapabilityMask3.s.IsMAXLIDSupported) + PrintFunc(dest, "%*sMaxLID: %u\n", + indent, "", pPortInfo->MaxLID); + + FormatStlPortErrorAction(cbuf, pPortInfo, sizeof(cbuf)); + PrintFunc(dest, "%*sPortErrorActions: 0x%x: %s\n", indent, "", pPortInfo->PortErrorAction.AsReg32, cbuf); + + PrintFunc(dest, "%*sBufferUnits:VL15Init 0x%04x VL15CreditRate 0x%02x CreditAck 0x%x BufferAlloc 0x%x\n", + indent, "", + pPortInfo->BufferUnits.s.VL15Init, + pPortInfo->BufferUnits.s.VL15CreditRate, + pPortInfo->BufferUnits.s.CreditAck, + pPortInfo->BufferUnits.s.BufferAlloc); + PrintFunc(dest, "%*sMTU Supported: (0x%x) %s bytes\n", + indent, "", pPortInfo->MTU.Cap, IbMTUToText(pPortInfo->MTU.Cap)); + PrintFunc(dest, "%*sMTU Active By VL:\n",indent,""); + PrintFunc(dest, "%*s00:%5s 01:%5s 02:%5s 03:%5s 04:%5s 05:%5s 06:%5s 07:%5s\n", + indent, "", + IbMTUToText(GET_STL_PORT_INFO_NeighborMTU(pPortInfo, 0)), + IbMTUToText(GET_STL_PORT_INFO_NeighborMTU(pPortInfo, 1)), + IbMTUToText(GET_STL_PORT_INFO_NeighborMTU(pPortInfo, 2)), + IbMTUToText(GET_STL_PORT_INFO_NeighborMTU(pPortInfo, 3)), + IbMTUToText(GET_STL_PORT_INFO_NeighborMTU(pPortInfo, 4)), + IbMTUToText(GET_STL_PORT_INFO_NeighborMTU(pPortInfo, 5)), + IbMTUToText(GET_STL_PORT_INFO_NeighborMTU(pPortInfo, 6)), + IbMTUToText(GET_STL_PORT_INFO_NeighborMTU(pPortInfo, 7))); + PrintFunc(dest, "%*s08:%5s 09:%5s 10:%5s 11:%5s 12:%5s 13:%5s 14:%5s 15:%5s\n", + indent, "", + IbMTUToText(GET_STL_PORT_INFO_NeighborMTU(pPortInfo, 8)), + IbMTUToText(GET_STL_PORT_INFO_NeighborMTU(pPortInfo, 9)), + IbMTUToText(GET_STL_PORT_INFO_NeighborMTU(pPortInfo, 10)), + IbMTUToText(GET_STL_PORT_INFO_NeighborMTU(pPortInfo, 11)), + IbMTUToText(GET_STL_PORT_INFO_NeighborMTU(pPortInfo, 12)), + IbMTUToText(GET_STL_PORT_INFO_NeighborMTU(pPortInfo, 13)), + IbMTUToText(GET_STL_PORT_INFO_NeighborMTU(pPortInfo, 14)), + IbMTUToText(GET_STL_PORT_INFO_NeighborMTU(pPortInfo, 15))); + PrintFunc(dest, "%*s16:%5s 17:%5s 18:%5s 19:%5s 20:%5s 21:%5s 22:%5s 23:%5s\n", + indent, "", + IbMTUToText(GET_STL_PORT_INFO_NeighborMTU(pPortInfo, 16)), + IbMTUToText(GET_STL_PORT_INFO_NeighborMTU(pPortInfo, 17)), + IbMTUToText(GET_STL_PORT_INFO_NeighborMTU(pPortInfo, 18)), + IbMTUToText(GET_STL_PORT_INFO_NeighborMTU(pPortInfo, 19)), + IbMTUToText(GET_STL_PORT_INFO_NeighborMTU(pPortInfo, 20)), + IbMTUToText(GET_STL_PORT_INFO_NeighborMTU(pPortInfo, 21)), + IbMTUToText(GET_STL_PORT_INFO_NeighborMTU(pPortInfo, 22)), + IbMTUToText(GET_STL_PORT_INFO_NeighborMTU(pPortInfo, 23))); + PrintFunc(dest, "%*s24:%5s 25:%5s 26:%5s 27:%5s 28:%5s 29:%5s 30:%5s 31:%5s\n", + indent, "", + IbMTUToText(GET_STL_PORT_INFO_NeighborMTU(pPortInfo, 24)), + IbMTUToText(GET_STL_PORT_INFO_NeighborMTU(pPortInfo, 25)), + IbMTUToText(GET_STL_PORT_INFO_NeighborMTU(pPortInfo, 26)), + IbMTUToText(GET_STL_PORT_INFO_NeighborMTU(pPortInfo, 27)), + IbMTUToText(GET_STL_PORT_INFO_NeighborMTU(pPortInfo, 28)), + IbMTUToText(GET_STL_PORT_INFO_NeighborMTU(pPortInfo, 29)), + IbMTUToText(GET_STL_PORT_INFO_NeighborMTU(pPortInfo, 30)), + IbMTUToText(GET_STL_PORT_INFO_NeighborMTU(pPortInfo, 31))); + + FormatStlVLStalls(cbuf, pPortInfo, sizeof(cbuf)); + PrintFunc(dest, "%*sStallCnt/VL: %s\n", indent, "", cbuf); + + FormatStlVLHOQLife(cbuf, pPortInfo, 0, 8, sizeof(cbuf)); + PrintFunc(dest, "%*sHOQLife VL[00,07]: %s\n", indent, "", cbuf); + FormatStlVLHOQLife(cbuf, pPortInfo, 8, 16, sizeof(cbuf)); + PrintFunc(dest, "%*sHOQLife VL[08,15]: %s\n", indent, "", cbuf); + FormatStlVLHOQLife(cbuf, pPortInfo, 16, 24, sizeof(cbuf)); + PrintFunc(dest, "%*sHOQLife VL[16,23]: %s\n", indent, "", cbuf); + FormatStlVLHOQLife(cbuf, pPortInfo, 24, 32, sizeof(cbuf)); + PrintFunc(dest, "%*sHOQLife VL[24,31]: %s\n", indent, "", cbuf); + + // Other odds and ends? + PrintFunc(dest, "%*sReplayDepth Buffer 0x%02x; Wire 0x%02x\n", + indent, "", + (pPortInfo->ReplayDepthH.BufferDepthH << 8) | pPortInfo->ReplayDepth.BufferDepth, + (pPortInfo->ReplayDepthH.WireDepthH << 8) | pPortInfo->ReplayDepth.WireDepth); + PrintFunc(dest, "%*sDiagCode: 0x%04x LedEnabled: %-3s\n", indent, "", \ + pPortInfo->DiagCode.AsReg16, + pPortInfo->PortStates.s.LEDEnabled? "On" : "Off"); + PrintFunc(dest, "%*sLinkDownReason: %s NeighborLinkDownReason: %s\n", + indent, "", StlLinkDownReasonToText(pPortInfo->LinkDownReason), + StlLinkDownReasonToText(pPortInfo->NeighborLinkDownReason)); + + PrintFunc(dest, "%*sOverallBufferSpace: 0x%04x\n", + indent, "", pPortInfo->OverallBufferSpace); + + // Not sure counters belong in this port structure + PrintFunc(dest, "%*sViolations M_Key: %-5u P_Key: %-5u Q_Key: %-5u\n", + indent, "", + pPortInfo->Violations.M_Key, pPortInfo->Violations.P_Key, + pPortInfo->Violations.Q_Key); + } + +} + +void PrintStlLedInfo(PrintDest_t *dest, int indent, const STL_LED_INFO *pLedInfo, EUI64 portGuid, int printLineByLine) +{ + + PrintFunc(dest, "%*sLedInfo: %d \n", indent, "", pLedInfo->u.s.LedMask); +} + +void PrintStlPortInfoSmp(PrintDest_t *dest, int indent, const STL_SMP *smp, EUI64 portGuid, int printLineByLine) +{ + STL_PORT_INFO *pPortInfo = (STL_PORT_INFO *)stl_get_smp_data((STL_SMP *)smp); + + PrintFunc(dest, "%*sPort %u Info\n", indent, "", + smp->common.AttributeModifier & 0xff); + PrintStlPortInfo(dest, indent+3, pPortInfo, portGuid, printLineByLine); +} + +void PrintStlPortStateInfo(PrintDest_t *dest, int indent, const STL_PORT_STATE_INFO *psip, uint16 portCount, uint16 startPort, int printLineByLine) +{ + uint16 i; + char tempBuf[64]; + if (printLineByLine) { + for (i = 0; i < portCount; i++) { + snprintf(tempBuf, sizeof(tempBuf), "Port[%d].PortStates.AsReg32", i+startPort); + PrintIntWithDots(dest, indent, tempBuf, psip[i].PortStates.AsReg32); + snprintf(tempBuf, sizeof(tempBuf), "Port[%d].PortStates.s.LEDEnabled", i+startPort); + PrintIntWithDots(dest, indent, tempBuf, psip[i].PortStates.s.LEDEnabled); + snprintf(tempBuf, sizeof(tempBuf), "Port[%d].PortStates.s.IsSMConfigurationStarted", i+startPort); + PrintIntWithDots(dest, indent, tempBuf, psip[i].PortStates.s.IsSMConfigurationStarted); + snprintf(tempBuf, sizeof(tempBuf), "Port[%d].PortStates.s.NeighborNormal", i+startPort); + PrintIntWithDots(dest, indent, tempBuf, psip[i].PortStates.s.NeighborNormal); + snprintf(tempBuf, sizeof(tempBuf), "Port[%d].PortStates.s.OfflineDisabledReason", i+startPort); + PrintIntWithDots(dest, indent, tempBuf, psip[i].PortStates.s.OfflineDisabledReason); + snprintf(tempBuf, sizeof(tempBuf), "Port[%d].PortStates.s.PortPhysicalState", i+startPort); + PrintIntWithDots(dest, indent, tempBuf, psip[i].PortStates.s.PortPhysicalState); + snprintf(tempBuf, sizeof(tempBuf), "Port[%d].PortStates.s.PortState", i+startPort); + PrintIntWithDots(dest, indent, tempBuf, psip[i].PortStates.s.PortState); + snprintf(tempBuf, sizeof(tempBuf), "Port[%d].LinkWidthDowngradeTxActive", i+startPort); + PrintIntWithDots(dest, indent, tempBuf, psip[i].LinkWidthDowngradeTxActive); + snprintf(tempBuf, sizeof(tempBuf), "Port[%d].LinkWidthDowngradeRxActive", i+startPort); + PrintIntWithDots(dest, indent, tempBuf, psip[i].LinkWidthDowngradeRxActive); + + } + } + else { + char tempBuf2[64]; + for (i=0; iPartitionTableBlock[i].AsReg16); + snprintf(buf, sizeof(buf), "PartitionTableBlock[%d].s.MembershipType", i); + PrintIntWithDots(dest, indent, buf, pPKeyTable->PartitionTableBlock[i].s.MembershipType); + snprintf(buf, sizeof(buf), "PartitionTableBlock[%d].s.P_KeyBase", i); + PrintIntWithDots(dest, indent, buf, pPKeyTable->PartitionTableBlock[i].s.P_KeyBase); + } + } + else { + + // 8 entries per line + for (i=0; iPartitionTableBlock[i].AsReg16); + } + PrintFunc(dest, "%*s%s\n", indent, "", buf); + } +} + +void PrintStlPKeyTableSmp(PrintDest_t *dest, int indent, const STL_SMP *smp, NODE_TYPE nodetype, boolean showHeading, boolean showBlock, int printLineByLine) +{ + char buf[40] = ""; + uint32 sub; + uint32 block = smp->common.AttributeModifier & PKEY_BLOCK_NUM_MASK; + uint32 numBlocks = (smp->common.AttributeModifier >> 24) & 0xff; + uint32 portNum = (smp->common.AttributeModifier >> 16) & 0xff; + STL_PARTITION_TABLE *pPKeyTable; + if (printLineByLine) { + if (showHeading) { + if (nodetype == STL_NODE_SW) + PrintIntWithDots(dest, indent, "OutputPort", portNum); + if (showBlock) + PrintIntWithDots(dest, indent, "BlockNum", block); + } + pPKeyTable = (STL_PARTITION_TABLE *)stl_get_smp_data((STL_SMP *)smp); + for (sub = 0; sub < numBlocks; sub++) { + PrintStlPKeyTable(dest, indent, pPKeyTable + sub, sub+block, printLineByLine); + } + + } + else { + if (showHeading) { + if (nodetype == STL_NODE_SW) + sprintf(buf, "OutputPort: %3u ", portNum); + if (showBlock) + PrintFunc(dest, "%*s%sBlockNum: %2u\n", indent, "", buf, block); + else if (buf[0]) + PrintFunc(dest, "%*s%s\n", indent, "", buf); + } + + pPKeyTable = (STL_PARTITION_TABLE *)stl_get_smp_data((STL_SMP *)smp); + for (sub = 0; sub < numBlocks; sub++) { + PrintStlPKeyTable(dest, indent, pPKeyTable + sub, sub+block, printLineByLine); + } + } +} + +void PrintStlSwitchInfo(PrintDest_t *dest, int indent, const STL_SWITCH_INFO *pSwitchInfo, STL_LID lid, int printLineByLine) +{ + char buf[64]; + if (printLineByLine) { + if (lid) + PrintIntWithDots(dest, indent, "lid", lid); + + if (pSwitchInfo->RoutingMode.Enabled & STL_ROUTE_LINEAR) + PrintIntWithDots(dest, indent, "LinearFDBCap", pSwitchInfo->LinearFDBCap); + + PrintIntWithDots(dest, indent, "MulticastFDBCap", pSwitchInfo->MulticastFDBCap); + PrintIntWithDots(dest, indent, "LinearFDBTop", pSwitchInfo->LinearFDBTop); + PrintIntWithDots(dest, indent, "MulticastFDBTop", pSwitchInfo->MulticastFDBTop); + #if 0 + //Not Support in Gen 1. + PrintIntWithDots(dest, indent, "CollectiveCap", pSwitchInfo->CollectiveCap); + PrintIntWithDots(dest, indent, "CollectiveTop", pSwitchInfo->CollectiveTop); + #endif + PrintStrWithDots(dest, indent, "IPAddrIPV6", + inet_ntop(AF_INET6, pSwitchInfo->IPAddrIPV6.addr, buf, sizeof(buf))); + PrintStrWithDots(dest, indent, "IPAddrIPV4", + inet_ntop(AF_INET, pSwitchInfo->IPAddrIPV4.addr, buf, sizeof(buf))); + + PrintIntWithDots(dest, indent, "u1.AsReg8", pSwitchInfo->u1.AsReg8); + PrintIntWithDots(dest, indent, "u1.s.PortStateChange", pSwitchInfo->u1.s.PortStateChange); + PrintIntWithDots(dest, indent, "u1.s.LifeTimeValue", pSwitchInfo->u1.s.LifeTimeValue); + PrintIntWithDots(dest, indent, "PartitionEnforcementCap", pSwitchInfo->PartitionEnforcementCap); + PrintIntWithDots(dest, indent, "PortGroupFDBCap", pSwitchInfo->PortGroupFDBCap); + PrintIntWithDots(dest, indent, "PortGroupCap", pSwitchInfo->PortGroupCap); + PrintIntWithDots(dest, indent, "PortGroupTop", pSwitchInfo->PortGroupTop); + PrintIntWithDots(dest, indent, "RoutingMode.Supported", pSwitchInfo->RoutingMode.Supported); + PrintIntWithDots(dest, indent, "RoutingMode.Enabled", pSwitchInfo->RoutingMode.Enabled); + PrintIntWithDots(dest, indent, "u2.AsReg8", pSwitchInfo->u2.AsReg8); + PrintIntWithDots(dest, indent, "u2.s.EnhancedPort0", pSwitchInfo->u2.s.EnhancedPort0); + PrintIntWithDots(dest, indent, "MultiCollectMask.CollectiveMask", pSwitchInfo->MultiCollectMask.CollectiveMask); + PrintIntWithDots(dest, indent, "MultiCollectMask.MulticastMask", pSwitchInfo->MultiCollectMask.MulticastMask); + PrintIntWithDots(dest, indent, "AdaptiveRouting.AsReg16", pSwitchInfo->AdaptiveRouting.AsReg16); + PrintIntWithDots(dest, indent, "AdaptiveRouting.s.Enable", pSwitchInfo->AdaptiveRouting.s.Enable); + PrintIntWithDots(dest, indent, "AdaptiveRouting.s.Pause", pSwitchInfo->AdaptiveRouting.s.Pause); + PrintIntWithDots(dest, indent, "AdaptiveRouting.s.Algorithm", pSwitchInfo->AdaptiveRouting.s.Algorithm); + PrintIntWithDots(dest, indent, "AdaptiveRouting.s.Frequency", pSwitchInfo->AdaptiveRouting.s.Frequency); + PrintIntWithDots(dest, indent, "AdaptiveRouting.s.LostRoutesOnly", pSwitchInfo->AdaptiveRouting.s.LostRoutesOnly); + PrintIntWithDots(dest, indent, "AdaptiveRouting.s.Threshold", pSwitchInfo->AdaptiveRouting.s.Threshold); + PrintIntWithDots(dest, indent, "CapabilityMask.AsReg16", pSwitchInfo->CapabilityMask.AsReg16); + PrintIntWithDots(dest, indent, "CapabilityMask.s.IsAddrRangeConfigSupported", pSwitchInfo->CapabilityMask.s.IsAddrRangeConfigSupported); + PrintIntWithDots(dest, indent, "CapabilityMask.s.IsExtendedSCSCSupported", pSwitchInfo->CapabilityMask.s.IsExtendedSCSCSupported); + PrintIntWithDots(dest, indent, "CapabilityMask.s.IsAdaptiveRoutingSupported", pSwitchInfo->CapabilityMask.s.IsAdaptiveRoutingSupported); + +#if 0 + //Not Support in Gen 1. + PrintIntWithDots(dest, indent, "CapabilityMaskCollectives.AsReg16", pSwitchInfo->CapabilityMaskCollectives.AsReg16); +#endif + } + else { + + if (lid) + PrintFunc(dest, "%*sLID: 0x%08x\n", indent, "", lid); + + if (pSwitchInfo->RoutingMode.Enabled & STL_ROUTE_LINEAR) + PrintFunc(dest, "%*sLinearFDBCap: %5u LinearFDBTop: 0x%08x MCFDBCap: %5u MCFDBTop: 0x%08x\n", + indent, "", + pSwitchInfo->LinearFDBCap, pSwitchInfo->LinearFDBTop, + pSwitchInfo->MulticastFDBCap, pSwitchInfo->MulticastFDBTop); + else + PrintFunc(dest, "%*sLinearFDBTop: 0x%08x MCFDBCap: %5u MCFDBTop: 0x%08x\n", + indent, "", + pSwitchInfo->LinearFDBTop, pSwitchInfo->MulticastFDBCap, pSwitchInfo->MulticastFDBTop); + PrintFunc(dest, "%*sCapability: 0x%02x: %s PartEnfCap: %5u PortStateChange: %d SwitchLifeTime: %d\n", + indent, "", + pSwitchInfo->u2.AsReg8, + pSwitchInfo->u2.s.EnhancedPort0?"E0 ": "", + pSwitchInfo->PartitionEnforcementCap, + pSwitchInfo->u1.s.PortStateChange, + pSwitchInfo->u1.s.LifeTimeValue); + PrintFunc(dest, "%*sPortGroupFDBCap: %5u PortGroupCap: %3u PortGroupTop: %3u\n", + indent, "", + pSwitchInfo->PortGroupFDBCap, + pSwitchInfo->PortGroupCap, pSwitchInfo->PortGroupTop); + PrintFunc(dest, "%*sIPAddrIPV6: %s\n", + indent, "", + inet_ntop(AF_INET6, + pSwitchInfo->IPAddrIPV6.addr, + buf, sizeof(buf))); + PrintFunc(dest, "%*sIPAddrIPV4: %s\n", + indent, "", + inet_ntop(AF_INET, + pSwitchInfo->IPAddrIPV4.addr, + buf, sizeof(buf))); + PrintFunc(dest, "%*sCollectiveCap: %5u CollectiveTop: %5u CollectiveMask: %1u MulticastMask: %1u\n", + indent, "", + pSwitchInfo->CollectiveCap, pSwitchInfo->CollectiveTop, + pSwitchInfo->MultiCollectMask.CollectiveMask, + pSwitchInfo->MultiCollectMask.MulticastMask); + + PrintFunc(dest, "%*sRoutingMode: Supported: %s Enabled: %s\n", + indent, "", + StlRoutingModeToText(pSwitchInfo->RoutingMode.Supported), + StlRoutingModeToText(pSwitchInfo->RoutingMode.Enabled)); + + PrintFunc(dest, "%*sAdaptiveRouting: Enable: %u Pause: %u Alg: %u Freq: %u LostRoutesOnly: %u Thresh: %u\n", + indent, "", + pSwitchInfo->AdaptiveRouting.s.Enable, + pSwitchInfo->AdaptiveRouting.s.Pause, + pSwitchInfo->AdaptiveRouting.s.Algorithm, + pSwitchInfo->AdaptiveRouting.s.Frequency, + pSwitchInfo->AdaptiveRouting.s.LostRoutesOnly, + pSwitchInfo->AdaptiveRouting.s.Threshold); + + PrintFunc(dest, "%*sCapabilityMask: IsAddrRangeConfigSupported: %u IsAdaptiveRoutingSupported: %u\n", + indent, "", + pSwitchInfo->CapabilityMask.s.IsAddrRangeConfigSupported, + pSwitchInfo->CapabilityMask.s.IsAdaptiveRoutingSupported); + + PrintFunc(dest, "%*sCapabilityMask: IsExtendedSCSCSupported: %u\n", + indent, "", + pSwitchInfo->CapabilityMask.s.IsExtendedSCSCSupported); + +#if 0 + //Not Support in Gen 1. + PrintFunc(dest, "*sCapabilityMaskCollectives: Reserved: %u\n", indent, "", pSwitchInfo->CapabilityMaskCollectives.s.Reserved); +#endif + + PrintFunc(dest, "%*sMulticastMask: 0x%x CollectiveMask: 0x%x\n", + indent, "", pSwitchInfo->MultiCollectMask.MulticastMask, + pSwitchInfo->MultiCollectMask.CollectiveMask); + } +} + +void PrintStlCongestionInfo(PrintDest_t *dest, int indent, const STL_CONGESTION_INFO *pCongestionInfo, int printLineByLine) +{ + if (printLineByLine) { + PrintIntWithDots(dest, indent, "CongestionInfo", pCongestionInfo->CongestionInfo); + PrintIntWithDots(dest, indent, "ControlTableCap", pCongestionInfo->ControlTableCap); + PrintIntWithDots(dest, indent, "CongestionLogLength", pCongestionInfo->CongestionLogLength); + } + else { + PrintFunc(dest, "%*sCongestion Info: %s\n", indent, "", + pCongestionInfo->CongestionInfo == CC_CONGESTION_INFO_CREDIT_STARVATION ? "CS" : "No CS"); + PrintFunc(dest, "%*sControl Table Capacity: %u\n", indent, "", pCongestionInfo->ControlTableCap); + PrintFunc(dest, "%*sCongestion Log Size: %u\n", indent, "", pCongestionInfo->CongestionLogLength); + } +} + +void PrintStlSwitchCongestionSetting(PrintDest_t *dest, int indent, const STL_SWITCH_CONGESTION_SETTING *pSwCongestionSetting, int printLineByLine) +{ + unsigned int i; + char tempVal[128] = { '\0' }; + + if (printLineByLine) { + char *cursor; + + PrintIntWithDots(dest, indent, "ControlMap", pSwCongestionSetting->Control_Map); + + cursor = tempVal; + i = 0; + while (i < 32) { + cursor += sprintf(cursor, "%02x", pSwCongestionSetting->Victim_Mask[i]); + if ((++i % 8) == 0) *(cursor++) = ' '; + } + PrintStrWithDots(dest, indent, "Victim_Mask", tempVal); + + cursor = tempVal; + i = 0; + while (i < 32) { + cursor += sprintf(cursor, "%02x", pSwCongestionSetting->Credit_Mask[i]); + if ((++i % 8) == 0) *(cursor++) = ' '; + } + PrintStrWithDots(dest, indent, "Credit_Mask", tempVal); + + PrintIntWithDots(dest, indent, "Threshold", pSwCongestionSetting->Threshold); + PrintIntWithDots(dest, indent, "Packet_Size", pSwCongestionSetting->Packet_Size); + PrintIntWithDots(dest, indent, "CS_Threshold", pSwCongestionSetting->CS_Threshold); + PrintIntWithDots(dest, indent, "CS_ReturnDelay", pSwCongestionSetting->CS_ReturnDelay); + PrintIntWithDots(dest, indent, "Marking_Rate", pSwCongestionSetting->Marking_Rate); + + } + else { + PrintFunc(dest, "%*sControl Map: 0x%x ( ", indent, "", pSwCongestionSetting->Control_Map); + if (pSwCongestionSetting->Control_Map & CC_SWITCH_CONTROL_MAP_VICTIM_VALID) + PrintFunc(dest, "Victim_Mask "); + if (pSwCongestionSetting->Control_Map & CC_SWITCH_CONTROL_MAP_CREDIT_VALID) + PrintFunc(dest, "Credit_Mask "); + if (pSwCongestionSetting->Control_Map & CC_SWITCH_CONTROL_MAP_CC_VALID) + PrintFunc(dest, "Threshold/Packet_Size "); + if (pSwCongestionSetting->Control_Map & CC_SWITCH_CONTROL_MAP_CS_VALID) + PrintFunc(dest, "CS_Threshold/CS_ReturnDelay "); + if (pSwCongestionSetting->Control_Map & CC_SWITCH_CONTROL_MAP_MARKING_VALID) + PrintFunc(dest, "Marking_Rate "); + PrintFunc(dest, ")\n"); + + PrintFunc(dest, "%*sPer Port Mask Values:\n", indent, ""); + PrintFunc(dest, "%*sMask Type | Flagged Ports\n", indent+4, ""); + + PrintFunc(dest, "%*sVictim Mask | ", indent+4, ""); + for (i = 0; i < 256; ++i) + if ((pSwCongestionSetting->Victim_Mask[31-(i/8)]>>(i % 8)) & 1) PrintFunc(dest, "%u ", i); + PrintFunc(dest, "\n"); + + PrintFunc(dest, "%*sCredit Mask | ", indent+4, ""); + for (i = 0; i < 256; ++i) + if ((pSwCongestionSetting->Credit_Mask[31-(i/8)]>>(i % 8)) & 1) PrintFunc(dest, "%u ", i); + PrintFunc(dest, "\n"); + + PrintFunc(dest, "%*sThreshold: %u\n", indent, "", pSwCongestionSetting->Threshold); + PrintFunc(dest, "%*sPacket Size: %u\n", indent, "", pSwCongestionSetting->Packet_Size); + PrintFunc(dest, "%*sCS Threshold: %u\n", indent, "", pSwCongestionSetting->CS_Threshold); + PrintFunc(dest, "%*sCS ReturnDelay: %u\n", indent, "", pSwCongestionSetting->CS_ReturnDelay); + PrintFunc(dest, "%*sMarking Rate: %u\n", indent, "", pSwCongestionSetting->Marking_Rate); + } +} + +void PrintStlHfiCongestionSetting(PrintDest_t *dest, int indent, const STL_HFI_CONGESTION_SETTING *pHfiCongestionSetting, int printLineByLine) +{ + unsigned int i; + char tempBuf[64]; + if (printLineByLine) { + PrintIntWithDots(dest, indent, "Control_Map", pHfiCongestionSetting->Control_Map); + PrintIntWithDots(dest, indent, "Port_Control", pHfiCongestionSetting->Port_Control); + for (i = 0; i < STL_MAX_SLS; i++) { + snprintf(tempBuf, sizeof(tempBuf), "HFICongestionEntryList[%d].CCTI_Increase", i); + PrintIntWithDots(dest, indent, tempBuf, pHfiCongestionSetting->HFICongestionEntryList[i].CCTI_Increase); + snprintf(tempBuf, sizeof(tempBuf), "HFICongestionEntryList[%d].CCTI_Timer", i); + PrintIntWithDots(dest, indent, tempBuf, pHfiCongestionSetting->HFICongestionEntryList[i].CCTI_Timer); + snprintf(tempBuf, sizeof(tempBuf), "HFICongestionEntryList[%d].TriggerThreshold", i); + PrintIntWithDots(dest, indent, tempBuf, pHfiCongestionSetting->HFICongestionEntryList[i].TriggerThreshold); + snprintf(tempBuf, sizeof(tempBuf), "HFICongestionEntryList[%d].CCTI_Min", i); + PrintIntWithDots(dest, indent, tempBuf, pHfiCongestionSetting->HFICongestionEntryList[i].CCTI_Min); + } + } + else { + PrintFunc(dest, "%*sCongestion Control Type: %s\n", indent, "", + pHfiCongestionSetting->Port_Control == CC_HFI_CONGESTION_SETTING_SL_PORT ? "SL Based" : "QP Based"); + + PrintFunc(dest, "%*sEntries:\n", indent, ""); + for (i=0; i < STL_MAX_SLS; ++i) { + if (pHfiCongestionSetting->Control_Map & (1<HFICongestionEntryList[i].CCTI_Increase); + PrintFunc(dest, "%*sCCT Timer: %u\n", indent+8, "", pHfiCongestionSetting->HFICongestionEntryList[i].CCTI_Timer); + PrintFunc(dest, "%*sCCT Trigger Threshold: %u\n", indent+8, "", + pHfiCongestionSetting->HFICongestionEntryList[i].TriggerThreshold); + PrintFunc(dest, "%*sCCT Min: %u\n", indent+8, "", pHfiCongestionSetting->HFICongestionEntryList[i].CCTI_Min); + } + } + } +} + +void PrintStlSwitchPortCongestionSettingSmp(PrintDest_t *dest, int indent, const STL_SMP *smp, int printLineByLine) +{ + const uint8_t start = smp->common.AttributeModifier & 0xff; + const uint8_t count = (smp->common.AttributeModifier>>24) & 0xff; + const STL_SWITCH_PORT_CONGESTION_SETTING_ELEMENT *element; + uint8_t i; + for (i = 0; i < count; ++i) { + element = &((STL_SWITCH_PORT_CONGESTION_SETTING*)stl_get_smp_data((STL_SMP*)smp))->Elements[i]; + if (!printLineByLine) + PrintFunc(dest, "%*sPort %u:\n", indent, "", i + start); + PrintStlSwitchPortCongestionSettingElement(dest, indent + (printLineByLine ? 0 : 4), element, + i + start, printLineByLine); + } +} + +void PrintStlSwitchPortCongestionSettingElement(PrintDest_t *dest, int indent, const STL_SWITCH_PORT_CONGESTION_SETTING_ELEMENT *pElement, uint8_t index, int printLineByLine) +{ + char tempBuf[64] = { '\0' }; + + if (printLineByLine) { + snprintf(tempBuf, sizeof(tempBuf), "Elements[%d].Valid", index); + PrintIntWithDots(dest, indent, tempBuf, pElement->Valid); + snprintf(tempBuf, sizeof(tempBuf), "Elements[%d].Control_Type", index); + PrintIntWithDots(dest, indent, tempBuf, pElement->Control_Type); + snprintf(tempBuf, sizeof(tempBuf), "Elements[%d].Threshold", index); + PrintIntWithDots(dest, indent, tempBuf, pElement->Threshold); + snprintf(tempBuf, sizeof(tempBuf), "Elements[%d].Packet_Size", index); + PrintIntWithDots(dest, indent, tempBuf, pElement->Packet_Size); + snprintf(tempBuf, sizeof(tempBuf), "Elements[%d].Marking_Rate", index); + PrintIntWithDots(dest, indent, tempBuf, pElement->Marking_Rate); + } else { + PrintFunc(dest, "%*sValid: %s, Control Type: %s, Threshold: %u, Packet Size: %d, Marking Rate: %u\n", + indent, "", + pElement->Valid ? "Yes" : "No", + pElement->Control_Type ? "Credit Starvation" : "Congestion Control", + pElement->Threshold, + pElement->Packet_Size, pElement->Marking_Rate); + } +} + + +void PrintStlSwitchCongestionLog(PrintDest_t *dest, int indent, const STL_SWITCH_CONGESTION_LOG *pSwCongestionLog, int printLineByLine) +{ + unsigned int i; + char tempBuf[64]; + char tempVal[300]; + if (printLineByLine) { + PrintIntWithDots(dest, indent, "LogType", pSwCongestionLog->LogType); + PrintIntWithDots(dest, indent, "CongestionFlags", pSwCongestionLog->CongestionFlags); + PrintIntWithDots(dest, indent, "LogEventsCounter", pSwCongestionLog->LogEventsCounter); + PrintIntWithDots(dest, indent, "CurrentTimeStamp", pSwCongestionLog->CurrentTimeStamp); + snprintf(tempVal, sizeof(tempVal), "%02x%02x%02x%02x%02x%02x%02x%02x %02x%02x%02x%02x%02x%02x%02x%02x %02x%02x%02x%02x%02x%02x%02x%02x %02x%02x%02x%02x%02x%02x%02x%02x", + pSwCongestionLog->PortMap[31], pSwCongestionLog->PortMap[30], pSwCongestionLog->PortMap[29], pSwCongestionLog->PortMap[28], + pSwCongestionLog->PortMap[27], pSwCongestionLog->PortMap[26], pSwCongestionLog->PortMap[25], pSwCongestionLog->PortMap[24], + pSwCongestionLog->PortMap[23], pSwCongestionLog->PortMap[22], pSwCongestionLog->PortMap[21], pSwCongestionLog->PortMap[20], + pSwCongestionLog->PortMap[19], pSwCongestionLog->PortMap[18], pSwCongestionLog->PortMap[17], pSwCongestionLog->PortMap[16], + pSwCongestionLog->PortMap[15], pSwCongestionLog->PortMap[14], pSwCongestionLog->PortMap[13], pSwCongestionLog->PortMap[12], + pSwCongestionLog->PortMap[11], pSwCongestionLog->PortMap[10], pSwCongestionLog->PortMap[9], pSwCongestionLog->PortMap[8], + pSwCongestionLog->PortMap[7], pSwCongestionLog->PortMap[6], pSwCongestionLog->PortMap[5], pSwCongestionLog->PortMap[4], + pSwCongestionLog->PortMap[3], pSwCongestionLog->PortMap[2], pSwCongestionLog->PortMap[1], pSwCongestionLog->PortMap[0]); + PrintStrWithDots(dest, indent, "PortMap", tempVal); + for (i = 0; i < MIN(STL_NUM_CONGESTION_LOG_ELEMENTS, pSwCongestionLog->LogEventsCounter); ++i) { + snprintf(tempBuf, sizeof(tempBuf), "CongestionEntryList[%d].SLID", i); + PrintIntWithDots(dest, indent, tempBuf, pSwCongestionLog->CongestionEntryList[i].SLID); + snprintf(tempBuf, sizeof(tempBuf), "CongestionEntryList[%d].DLID", i); + PrintIntWithDots(dest, indent, tempBuf, pSwCongestionLog->CongestionEntryList[i].DLID); + snprintf(tempBuf, sizeof(tempBuf), "CongestionEntryList[%d].SC", i); + PrintIntWithDots(dest, indent, tempBuf, pSwCongestionLog->CongestionEntryList[i].SC); + snprintf(tempBuf, sizeof(tempBuf), "CongestionEntryList[%d].TimeStamp", i); + PrintIntWithDots(dest, indent, tempBuf, pSwCongestionLog->CongestionEntryList[i].TimeStamp); + } + } + else { + PrintFunc(dest, "%*sLogType: %s\nCongestion Flags: 0x%hhx\nLog Events: %hu\nCurrent Timestamp: %.3f uSec (0x%x)\n", + indent, "", + pSwCongestionLog->LogType == 1 ? "Switch" : "Invalid - Should always be Switch", + pSwCongestionLog->CongestionFlags, + pSwCongestionLog->LogEventsCounter, + (float)pSwCongestionLog->CurrentTimeStamp * 1.024f, pSwCongestionLog->CurrentTimeStamp); + PrintFunc(dest, "%*sMarked Ports:\n", indent, ""); + PrintFunc(dest, "%*s", indent+4, ""); + for (i = 0; i < 256; ++i) + if ((pSwCongestionLog->PortMap[31-(i/8)]>>(i % 8)) & 1) PrintFunc(dest, "%u, ", i); + PrintFunc(dest, "\n"); + + PrintFunc(dest, "%*sCongestion Event Log:\n", indent, ""); + // CongestionLog will contain at most the 20 most recent log events. + for (i = 0; i < MIN(STL_NUM_CONGESTION_LOG_ELEMENTS, pSwCongestionLog->LogEventsCounter); ++i) { + const STL_SWITCH_CONGESTION_LOG_EVENT *cursor = &pSwCongestionLog->CongestionEntryList[i]; + PrintFunc(dest, "%*sEvent #%u:\n", indent+4, "", i + 1); + PrintFunc(dest, "%*sSLID: %u\n", indent+8, "", cursor->SLID); + PrintFunc(dest, "%*sDLID: %u\n", indent+8, "", cursor->DLID); + PrintFunc(dest, "%*sSC: %u\n", indent+8, "", cursor->SC); + PrintFunc(dest, "%*sTimeStamp: %.3f uSec (0x%x)\n", indent+8, "", (float)cursor->TimeStamp * 1.024f, cursor->TimeStamp); + } + } +} + + +void PrintStlHfiCongestionLog(PrintDest_t *dest, int indent, const STL_HFI_CONGESTION_LOG *pHfiCongestionLog, int printLineByLine) +{ + unsigned int i; + char tempBuf[64]; + char tempVal[16]; + if (printLineByLine) { + PrintIntWithDots(dest, indent, "LogType", pHfiCongestionLog->LogType); + PrintIntWithDots(dest, indent, "CongestionFlags", pHfiCongestionLog->CongestionFlags); + PrintIntWithDots(dest, indent, "ThresholdEventCounter", pHfiCongestionLog->ThresholdEventCounter); + PrintIntWithDots(dest, indent, "CurrentTimeStamp", pHfiCongestionLog->CurrentTimeStamp); + snprintf(tempVal, sizeof(tempVal), "%02x%02x%02x%02x", + pHfiCongestionLog->ThresholdCongestionEventMap[3], pHfiCongestionLog->ThresholdCongestionEventMap[2], + pHfiCongestionLog->ThresholdCongestionEventMap[1], pHfiCongestionLog->ThresholdCongestionEventMap[0]); + PrintStrWithDots(dest, indent, "ThresholdCongestionEventMap", tempVal); + for (i = 0; i < MIN(STL_NUM_CONGESTION_LOG_ELEMENTS, pHfiCongestionLog->ThresholdEventCounter); ++i) { + snprintf(tempBuf, sizeof(tempBuf), "CongestionEntryList[%d].Local_QP_CN_Entry", i); + snprintf(tempVal, sizeof(tempVal), "%02x%02x%02x", + pHfiCongestionLog->CongestionEntryList[i].Local_QP_CN_Entry.AsReg8s[2], + pHfiCongestionLog->CongestionEntryList[i].Local_QP_CN_Entry.AsReg8s[1], + pHfiCongestionLog->CongestionEntryList[i].Local_QP_CN_Entry.AsReg8s[0]); + PrintStrWithDots(dest, indent, tempBuf, tempVal); + + snprintf(tempBuf, sizeof(tempBuf), "CongestionEntryList[%d].Remote_QP_Number_CN_Entry", i); + snprintf(tempVal, sizeof(tempVal), "%02x%02x%02x", + pHfiCongestionLog->CongestionEntryList[i].Remote_QP_Number_CN_Entry.AsReg8s[2], + pHfiCongestionLog->CongestionEntryList[i].Remote_QP_Number_CN_Entry.AsReg8s[1], + pHfiCongestionLog->CongestionEntryList[i].Remote_QP_Number_CN_Entry.AsReg8s[0]); + PrintStrWithDots(dest, indent, tempBuf, tempVal); + + snprintf(tempBuf, sizeof(tempBuf), "CongestionEntryList[%d].SL_CN_Entry", i); + PrintIntWithDots(dest, indent, tempBuf, pHfiCongestionLog->CongestionEntryList[i].SL_CN_Entry); + + snprintf(tempBuf, sizeof(tempBuf), "CongestionEntryList[%d].Service_Type_CN_Entry", i); + PrintIntWithDots(dest, indent, tempBuf, pHfiCongestionLog->CongestionEntryList[i].Service_Type_CN_Entry); + + snprintf(tempBuf, sizeof(tempBuf), "CongestionEntryList[%d].Remote_LID_CN_Entry", i); + PrintIntWithDots(dest, indent, tempBuf, pHfiCongestionLog->CongestionEntryList[i].Remote_LID_CN_Entry); + + snprintf(tempBuf, sizeof(tempBuf), "CongestionEntryList[%d].TimeStamp_CN_Entry", i); + PrintIntWithDots(dest, indent, tempBuf, pHfiCongestionLog->CongestionEntryList[i].TimeStamp_CN_Entry); + } + } + else { + PrintFunc(dest, "%*sLogType: %s\nCongestion Flags: 0x%hhx\nLog Events: %hu\nCurrent Timestamp: %.3f uSec (0x%x)\n", + indent, "", + pHfiCongestionLog->LogType == 2 ? "HFI" : "Invalid - Should always be HFI", + pHfiCongestionLog->CongestionFlags, + pHfiCongestionLog->ThresholdEventCounter, + (float)pHfiCongestionLog->CurrentTimeStamp * 1.024f, pHfiCongestionLog->CurrentTimeStamp); + PrintFunc(dest, "%*sMarked SLs:\n", indent, ""); + PrintFunc(dest, "%*s", indent+4, ""); + for (i = 0; i < 32; ++i) + if ((pHfiCongestionLog->ThresholdCongestionEventMap[i/8]>>(i % 8)) & 1) PrintFunc(dest, "%u, ", i); + PrintFunc(dest, "\n"); + + PrintFunc(dest, "%*sCongestion Event Log:\n", indent, ""); + for (i = 0; i < MIN(STL_NUM_CONGESTION_LOG_ELEMENTS, pHfiCongestionLog->ThresholdEventCounter); ++i) { + const STL_HFI_CONGESTION_LOG_EVENT *cursor = &pHfiCongestionLog->CongestionEntryList[i]; + const uint32_t localQP = cursor->Local_QP_CN_Entry.AsReg8s[2]<<16 | + cursor->Local_QP_CN_Entry.AsReg8s[1]<<8 | + cursor->Local_QP_CN_Entry.AsReg8s[0]; + const uint32_t remoteQP = cursor->Remote_QP_Number_CN_Entry.AsReg8s[2]<<16 | + cursor->Remote_QP_Number_CN_Entry.AsReg8s[1]<<8 | + cursor->Remote_QP_Number_CN_Entry.AsReg8s[0]; + + PrintFunc(dest, "%*sEvent #%u:\n", indent+4, "", i + 1); + PrintFunc(dest, "%*sLocal QP CN: %u\n", indent+8, "", localQP); + PrintFunc(dest, "%*sRemote QP CN %u\n", indent+8, "", remoteQP); + PrintFunc(dest, "%*sLocal QP SL: %u\n", indent+8, "", cursor->SL_CN_Entry); + PrintFunc(dest, "%*sLocal QP Service Type: %s\n", indent+8, "", StlQPServiceTypeToText(cursor->Service_Type_CN_Entry)); + PrintFunc(dest, "%*sRemote LID: %u\n", indent+8, "", cursor->Remote_LID_CN_Entry); + PrintFunc(dest, "%*sTimeStamp: %.3f uSec (0x%x)\n", indent+8, "", (float)cursor->TimeStamp_CN_Entry * 1.024f, + cursor->TimeStamp_CN_Entry); + } + } +} + +void PrintStlHfiCongestionControlTab(PrintDest_t *dest, int indent, const STL_HFI_CONGESTION_CONTROL_TABLE *pHfiCongestionControl, uint8_t cnt, uint8_t start, int printLineByLine) +{ + unsigned int block, i; + char tempBuf[64]; + if (printLineByLine) { + PrintIntWithDots(dest, indent, "CCTI_Limit", pHfiCongestionControl->CCTI_Limit); + if (!pHfiCongestionControl->CCTI_Limit) { + return; + } + for (block = 0; block < cnt; ++block) { + for(i = 0; i < STL_NUM_CONGESTION_CONTROL_ELEMENTS_BLOCK_ENTRIES; ++i){ + if (printLineByLine >= 2) { + snprintf(tempBuf, sizeof(tempBuf), "CCT_Block_List[%d].CCT_Entry_List[%d].AsReg16", block + start, i); + PrintIntWithDots(dest, indent, tempBuf, pHfiCongestionControl->CCT_Block_List[block].CCT_Entry_List[i].AsReg16); + } + snprintf(tempBuf, sizeof(tempBuf), "CCT_Block_List[%d].CCT_Entry_List[%d].s.CCT_Shift", block + start, i); + PrintIntWithDots(dest, indent, tempBuf, pHfiCongestionControl->CCT_Block_List[block].CCT_Entry_List[i].s.CCT_Shift); + snprintf(tempBuf, sizeof(tempBuf), "CCT_Block_List[%d].CCT_Entry_List[%d].s.CCT_Multiplier", block + start, i); + PrintIntWithDots(dest, indent, tempBuf, pHfiCongestionControl->CCT_Block_List[block].CCT_Entry_List[i].s.CCT_Multiplier); + } + } + } else { + PrintFunc(dest, "%*sMax CCTI: %u\n", indent, "", pHfiCongestionControl->CCTI_Limit); + if (!pHfiCongestionControl->CCTI_Limit) { + return; + } + PrintFunc(dest, "%*sCCT Entries:\n", indent, ""); + for (block = 0; block < cnt; ++block) { + PrintFunc(dest, "%*sBlock %u:\n", indent+3, "", block + start); + for (i = 0; i < STL_NUM_CONGESTION_CONTROL_ELEMENTS_BLOCK_ENTRIES; ++i) { + const STL_HFI_CONGESTION_CONTROL_TABLE_ENTRY *cursor = &pHfiCongestionControl->CCT_Block_List[block].CCT_Entry_List[i]; + PrintFunc(dest, "%*sEntry %u: Shift %u, Multiplier: %u\n", indent+4, "", ((block + start) * STL_NUM_CONGESTION_CONTROL_ELEMENTS_BLOCK_ENTRIES) + i, + cursor->s.CCT_Shift, cursor->s.CCT_Multiplier); + } + } + } +} + +static void PrintStlSxSCMapHeading(PrintDest_t *dest, int indent, const char* prefix, const char* type) +{ + PrintFunc(dest, "%*s%s%s: 00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31\n", + indent, "", prefix, type); +} + +void PrintStlSLSCMap(PrintDest_t *dest, int indent, const char* prefix, const STL_SLSCMAP *pSLSCMap, boolean heading) +{ + int i; + if (heading) + PrintStlSxSCMapHeading(dest, indent, prefix, "SL"); + PrintFunc(dest, "%*s%sSC: ", indent, "", prefix); + + for (i = 0; i < STL_MAX_SLS; i++) + PrintFunc(dest, "%02u ", pSLSCMap->SLSCMap[i].SC); + PrintFunc(dest, "\n"); +} + +void PrintStlSLSCMapSmp(PrintDest_t *dest, int indent, const STL_SMP *smp, int printLineByLine) +{ + STL_SLSCMAP *pSLSCMap; + int i; + pSLSCMap = (STL_SLSCMAP *)stl_get_smp_data((STL_SMP *)smp); + char tempBuf[64]; + + if (printLineByLine) { + for (i = 0; i < STL_MAX_SLS; i++) { + snprintf(tempBuf, sizeof(tempBuf), "SLSCMap[%d].SC", i); + PrintIntWithDots(dest, indent, tempBuf, pSLSCMap->SLSCMap[i].SC); + } + } + else { + PrintStlSxSCMapHeading(dest, indent, "", "SL"); + + PrintFunc(dest, "%*sSC: ", indent, ""); + + for (i = 0; i < STL_MAX_SLS; i++) + PrintFunc(dest, "%02u ", pSLSCMap->SLSCMap[i].SC); + PrintFunc(dest, "\n"); + } +} + +void PrintStlSCSCMap(PrintDest_t *dest, int indent, const char* prefix, const STL_SCSCMAP *pSCSCMap, boolean heading) +{ + int i; + if (heading) + PrintStlSxSCMapHeading(dest, indent, prefix, "SC"); + PrintFunc(dest, "%*s%sSC':", indent, "", prefix); + + for (i = 0; i < STL_MAX_SCS; i++) + PrintFunc(dest, "%02u ", pSCSCMap->SCSCMap[i].SC); + + PrintFunc(dest, "\n"); +} + +void PrintStlSCSCMapSmp(PrintDest_t *dest, int indent, const STL_SMP *smp, boolean heading, int printLineByLine) +{ + int i; + STL_SCSCMAP *pSCSCMap; + const char *headingprefix = ""; + char tempBuf[64]; + uint32_t sub; + uint32_t numBlocks = (smp->common.AttributeModifier >> 24) & 0xff; + if (numBlocks==0) + numBlocks=1; + + pSCSCMap = (STL_SCSCMAP *)stl_get_smp_data((STL_SMP *)smp); + + if (printLineByLine) { + for (sub = 0; sub < numBlocks; sub++) { + PrintIntWithDots(dest, indent, "blockNum", sub); + if (smp->common.AttributeModifier & 0x20000) { + PrintStrWithDots(dest, indent, "Ingress Ports", "ALL"); + } else { + PrintIntWithDots(dest, indent, "Ingress Port", (smp->common.AttributeModifier >> 8) & 0xff ); + } + if (smp->common.AttributeModifier & 0x10000) { + PrintStrWithDots(dest, indent, "Egress Ports", "ALL"); + } else { + PrintIntWithDots(dest, indent, "Egress Port", (smp->common.AttributeModifier & 0xff) + sub); + } + for(i = 0; i < STL_MAX_SCS; i++) { + snprintf(tempBuf, sizeof(tempBuf), "SCSCMap[%d].SC", i); + PrintIntWithDots(dest, indent, tempBuf, pSCSCMap[sub].SCSCMap[i].SC); + } + } + } + else { + headingprefix = "InPort,OutPort|"; + if (heading) + PrintStlSxSCMapHeading(dest, indent, headingprefix, "SC"); + + for (sub = 0; sub < numBlocks; sub++) { + char prefix[40] = ""; + int offset; + if (smp->common.AttributeModifier & 0x20000) { + offset = sprintf(prefix, " ALL ,"); + } else { + offset = sprintf(prefix, " %3u ,", + (smp->common.AttributeModifier >> 8) & 0xff); + } + if (smp->common.AttributeModifier & 0x10000) { + sprintf(&prefix[offset], " ALL |"); + } else { + sprintf(&prefix[offset], " %3u |", + (smp->common.AttributeModifier & 0xff) + + sub); + } + PrintStlSCSCMap(dest, indent, prefix, pSCSCMap + sub, FALSE); + } + } +} + +void PrintStlSCSLMap(PrintDest_t *dest, int indent, const char* prefix, const STL_SCSLMAP *pSCSLMap, boolean heading) +{ + int i; + if (heading) { + PrintStlSxSCMapHeading(dest, indent, "", "SC"); + + PrintFunc(dest, "%*sSL: ", indent, ""); + for (i = 0; i< STL_MAX_SCS; i++) { + PrintFunc(dest, "%02u ", pSCSLMap->SCSLMap[i].SL); + } + PrintFunc(dest, "\n"); + } +} + +void PrintStlSCSLMapSmp(PrintDest_t *dest, int indent, const STL_SMP *smp, int printLineByLine) +{ + STL_SCSLMAP *pSCSLMap; + int i; + pSCSLMap = (STL_SCSLMAP *)stl_get_smp_data((STL_SMP *)smp); + char tempBuf[64]; + + if (printLineByLine) { + for (i = 0; i < STL_MAX_SCS; i++) { + snprintf(tempBuf, sizeof(tempBuf), "SCSLMap[%d].SL", i); + PrintIntWithDots(dest, indent, tempBuf, pSCSLMap->SCSLMap[i].SL); + } + } + else { + PrintStlSxSCMapHeading(dest, indent, "", "SC"); + + PrintFunc(dest, "%*sSL: ", indent, ""); + + for (i = 0; i < STL_MAX_SCS; i++) + PrintFunc(dest, "%02u ", pSCSLMap->SCSLMap[i].SL); + PrintFunc(dest, "\n"); + } +} + +void PrintStlSCVLxMap(PrintDest_t *dest, int indent, const char* prefix, + const STL_SCVLMAP *pSCVLMap, boolean heading, + uint16_t attribute, int printLineByLine) +{ + int i; + char tempBuf[64]; + const char* vlstr; + switch (attribute) { + case STL_MCLASS_ATTRIB_ID_SC_VLR_MAPPING_TABLE: + vlstr = " VLR"; + break; + case STL_MCLASS_ATTRIB_ID_SC_VLT_MAPPING_TABLE: + vlstr = " VLT"; + break; + case STL_MCLASS_ATTRIB_ID_SC_VLNT_MAPPING_TABLE: + vlstr = "VLNT"; + break; + default: + vlstr = "UNKN"; + } + if (printLineByLine) { + PrintStrWithDots(dest, indent, "Type", vlstr); + for (i = 0; i < STL_MAX_SCS; i++) { + snprintf(tempBuf, sizeof(tempBuf), "SCVLMap[%d].VL", i); + PrintIntWithDots(dest, indent, tempBuf, pSCVLMap->SCVLMap[i].VL); + } + } + else { + if (heading) + PrintStlSxSCMapHeading(dest, indent, "", " SC"); + PrintFunc(dest, "%*s%s%s: ", indent, "", prefix, vlstr); + + for (i = 0; i < STL_MAX_SCS; i++) + PrintFunc(dest, "%02u ", pSCVLMap->SCVLMap[i].VL); + PrintFunc(dest, "\n"); + } +} + +void PrintStlSCVLxMapSmp(PrintDest_t *dest, int indent, const STL_SMP *smp, NODE_TYPE nodetype, boolean heading, int printLineByLine) +{ + STL_SCVLMAP *pSCVLMap; + char prefix[40] = ""; + const char *headingprefix = ""; + uint32_t sub; + uint32_t numBlocks = (smp->common.AttributeModifier >> 24) & 0xff; + pSCVLMap = (STL_SCVLMAP *)stl_get_smp_data((STL_SMP *)smp); + + + if (printLineByLine) { + if (nodetype == STL_NODE_SW) { + if (smp->common.AttributeModifier & 0x100) { + PrintStrWithDots(dest, indent, "Ports", "All"); + } + else { + PrintIntWithDots(dest, indent, "Port", smp->common.AttributeModifier & 0xff); + } + } + for (sub = 0; sub < numBlocks; sub++) { + PrintStlSCVLxMap(dest, indent, "", pSCVLMap + sub, FALSE, + smp->common.AttributeID, printLineByLine); + } + } + else { +#if 0 + if (nodetype == STL_NODE_SW) { + int offset; + + headingprefix = "StartPort,EndPort|"; + if (smp->common.AttributeModifier & 0x100) { + offset = sprintf(prefix, " ALL ,"); + } else { + offset = sprintf(prefix, " %3u ,", smp->common.AttributeModifier & 0xff); + } + sprintf(&prefix[offset], " %3u |", + (smp->common.AttributeModifier & 0xff) + numBlocks - 1); + } +#endif + if (nodetype == STL_NODE_SW) { + // "Port ## |" + headingprefix=" "; + } + if (heading) + PrintStlSxSCMapHeading(dest, indent, headingprefix, " SC"); + for (sub = 0; sub < numBlocks; sub++) { + if (nodetype == STL_NODE_SW) { + sprintf(prefix, "Port %2u |", + (smp->common.AttributeModifier & 0xff) + sub); + } + PrintStlSCVLxMap(dest, indent, prefix, pSCVLMap + sub, FALSE, + smp->common.AttributeID, printLineByLine); + } + } +} + +void PrintStlSMInfo(PrintDest_t *dest, int indent, const STL_SM_INFO *pSMInfo, STL_LID lid, int printLineByLine) +{ + if (printLineByLine) { + if (lid) { + PrintIntWithDots(dest, indent, "LID", lid); + } + PrintIntWithDotsFull(dest, indent, "PortGUID", pSMInfo->PortGUID); + PrintIntWithDots(dest, indent, "SM_Key", pSMInfo->SM_Key); + PrintIntWithDots(dest, indent, "ActCount", pSMInfo->ActCount); + PrintIntWithDots(dest, indent, "ElapsedTime", pSMInfo->ElapsedTime); + PrintIntWithDots(dest, indent, "u.AsReg16", pSMInfo->u.AsReg16); + PrintIntWithDots(dest, indent, "u.s.Priority", pSMInfo->u.s.Priority); + PrintIntWithDots(dest, indent, "u.s.ElevatedPriority", pSMInfo->u.s.ElevatedPriority); + PrintIntWithDots(dest, indent, "u.s.InitialPriority", pSMInfo->u.s.InitialPriority); + PrintIntWithDots(dest, indent, "u.s.SMStateCurrent", pSMInfo->u.s.SMStateCurrent); + } + else { + if (lid) + PrintFunc(dest, "%*sLID: 0x%08x PortGuid: 0x%016"PRIx64" State: %s\n", + indent, "", lid, pSMInfo->PortGUID, + StlSMStateToText(pSMInfo->u.s.SMStateCurrent)); + else + PrintFunc(dest, "%*sPortGuid: 0x%016"PRIx64" State: %s\n", + indent, "", pSMInfo->PortGUID, + StlSMStateToText(pSMInfo->u.s.SMStateCurrent)); + PrintFunc(dest, "%*sPriority: %2d Initial Priority: %2d Elevated Priority: %2d\n", + indent, "", pSMInfo->u.s.Priority, pSMInfo->u.s.InitialPriority, pSMInfo->u.s.ElevatedPriority); + PrintFunc(dest, "%*sSM_Key: 0x%016"PRIx64" ActCount: 0x%08x\n", + indent, "", pSMInfo->SM_Key, pSMInfo->ActCount); + PrintFunc(dest, "%*sElapsed Time: %d seconds\n", + indent, "", pSMInfo->ElapsedTime); + } +} + +void PrintStlLinearFDB(PrintDest_t *dest, int indent, const STL_LINEAR_FORWARDING_TABLE *pLinearFDB, uint32 blockNum, int printLineByLine) +{ + int i; + uint32 baselid = blockNum*MAX_LFT_ELEMENTS_BLOCK; + char tempBuf[64]; + if (printLineByLine) { + for (i=0; i< MAX_LFT_ELEMENTS_BLOCK; ++i) { + if (pLinearFDB->LftBlock[i] != 0xFF) { + PrintIntWithDots(dest, indent, "LID", baselid+i); + snprintf(tempBuf, sizeof(tempBuf), "LftBlock[%d].Port", i); + PrintIntWithDots(dest, indent, tempBuf, pLinearFDB->LftBlock[i]); + } + } + } + else { + for (i=0; iLftBlock[i] != 255) + PrintFunc(dest, "%*s LID 0x%08x -> Port %5u\n", + indent, "", baselid + i, + pLinearFDB->LftBlock[i]); + } + } +} + +void PrintStlVLArbTable(PrintDest_t *dest, int indent, const STL_VLARB_TABLE *pVLArbTable, uint32 section, int printLineByLine) +{ + int i, j; + char buf[64]; + + if (printLineByLine) { + if (section == 0) PrintStrWithDots(dest, indent, "Table Type", "Low Priority"); + else if (section == 1) PrintStrWithDots(dest, indent, "Table Type", "High Priority"); + else if (section == 2) PrintStrWithDots(dest, indent, "Table Type", "Preemption Table"); + else PrintStrWithDots(dest, indent, "Table Type", "Preemption Matrix"); + + if (section < 3) { + for (i = 0; i < VLARB_TABLE_LENGTH; i++) { + snprintf(buf, sizeof(buf), "Elements[%d].s.VL", i); + PrintIntWithDots(dest, indent, buf, pVLArbTable->Elements[i].s.VL); + snprintf(buf, sizeof(buf), "Elements[%d].Weight", i); + PrintIntWithDots(dest, indent, buf, pVLArbTable->Elements[i].Weight); + } + } + else { + for (i = 0; i < STL_MAX_VLS; i++) { + snprintf(buf, sizeof(buf), "Matrix[%d]", i); + PrintIntWithDots(dest, indent, buf, pVLArbTable->Matrix[i]); + } + + } + + } + else { + if (section == 0) PrintFunc(dest, "%*sTable Type: Low Priority\n", indent, ""); + else if (section == 1) PrintFunc(dest, "%*sTable Type: High Priority\n", indent, ""); + else if (section == 2) PrintFunc(dest, "%*sTable Type: Preemption Table\n", indent, ""); + else PrintFunc(dest, "%*sTable Type: Preemption Matrix\n", indent, ""); + + if (section < 3) + { + PrintFunc(dest, "%*sIndx VL Weight\n", indent, ""); + for (i = 0; i < VLARB_TABLE_LENGTH; ++i) + { + if (pVLArbTable->Elements[i].Weight == 0) continue; + PrintFunc(dest, "%*s%3d %2u %3u\n", + indent, "", i, pVLArbTable->Elements[i].s.VL, + pVLArbTable->Elements[i].Weight); + } + } + else + { + PrintFunc(dest, "%*sVL | Preemptable VL's\n", indent, ""); + for (i = 0; i < STL_MAX_VLS; ++i) + { + if ( pVLArbTable->Matrix[i] == 0) + continue; + + PrintFunc(dest, "%*sVL%2u : ", indent, "", i); + for (j = 0; j < STL_MAX_VLS; ++j) + if ( pVLArbTable->Matrix[i] & 1<common.AttributeModifier >> 24) & 0xff; + int section = (smp->common.AttributeModifier >> 16) & 0xff; + int port = smp->common.AttributeModifier & 0xff; + int i; + if (printLineByLine) { + for (i = 0; i < numPorts; i++) { + BSWAP_STL_VLARB_TABLE(pVlArbTab, section); + if (nodeType == STL_NODE_SW) { + PrintIntWithDots(dest, indent, "Port", port+i); + PrintStlVLArbTable(dest, indent+4, pVlArbTab, section, printLineByLine); + } else { + PrintStlVLArbTable(dest, indent, pVlArbTab, section, printLineByLine); + } + pVlArbTab++; + } + } + else { + for (i = 0; i < numPorts; i++) { + BSWAP_STL_VLARB_TABLE(pVlArbTab, section); + if (nodeType == STL_NODE_SW) { + PrintFunc(dest, "%*sPort: %d\n", indent, "", (int)port + i); + PrintStlVLArbTable(dest, indent+4, pVlArbTab, section, printLineByLine); + } else { + PrintStlVLArbTable(dest, indent, pVlArbTab, section, printLineByLine); + } + pVlArbTab++; + } + } +} + + + +void PrintStlMCastSmp(PrintDest_t *dest, int indent, const STL_SMP *smp, uint8_t pos, uint32_t startBlk, uint8_t count, int printLineByLine) +{ + uint8_t block; + STL_MULTICAST_FORWARDING_TABLE *pMCastBlock; + + if (printLineByLine) + PrintIntWithDots(dest, indent, "pos", pos); + else { + const uint8_t startPort = pos * STL_PORT_MASK_WIDTH; + PrintFunc(dest, "Position %u (ports %u-%u)\n", pos, startPort, startPort + STL_PORT_MASK_WIDTH - 1); + } + + for (block = 0, pMCastBlock = (STL_MULTICAST_FORWARDING_TABLE*)stl_get_smp_data((STL_SMP*)smp); + block < count; ++block, ++pMCastBlock) { + + BSWAP_STL_MULTICAST_FORWARDING_TABLE(pMCastBlock); + + PrintStlMCastFDB(dest, indent + (printLineByLine ? 0 : 4), pMCastBlock, startBlk + block, printLineByLine); + } +} + +void PrintStlMCastFDB(PrintDest_t *dest, int indent, const STL_MULTICAST_FORWARDING_TABLE *pMCastFDB, uint32 blockNum, int printLineByLine) +{ + int i; + STL_LID baselid = blockNum * STL_NUM_MFT_ELEMENTS_BLOCK + STL_LID_MULTICAST_BEGIN; + char tempBuf[64]; + if (printLineByLine) { + for (i=0; i< STL_NUM_MFT_ELEMENTS_BLOCK; ++i) { + if (pMCastFDB->MftBlock[i]) { + PrintIntWithDots(dest, indent, "LID", baselid+i); + snprintf(tempBuf, sizeof(tempBuf), "MftBlock[%d].PortMask", i); + PrintIntWithDots(dest, indent, tempBuf, pMCastFDB->MftBlock[i]); + } + } + } + else { + for (i=0; i MftBlock[i]) + { + PrintFunc(dest, "%*s LID 0x%08x -> PortMask 0x%016"PRIx64"\n", + indent, "", baselid+i, pMCastFDB->MftBlock[i]); + } + } + } +} + +void PrintStlInformInfo(PrintDest_t *dest, int indent, + const STL_INFORM_INFO *pInformInfo) +{ + if (pInformInfo->IsGeneric) + { + char buf[8]; + PrintFunc(dest, "%*s%sSubcribe: Type: %8s Generic: Trap: %5d " + "QPN: 0x%06x\n", + indent, "", + pInformInfo->Subscribe?"":"Un", + IbNoticeTypeToText(pInformInfo->Type), + pInformInfo->u.Generic.TrapNumber, + pInformInfo->u.Generic.u1.s.QPNumber); + FormatTimeoutMult(buf, pInformInfo->u.Generic.u1.s.RespTimeValue); + PrintFunc(dest, "%*sRespTime: %s Producer: %s\n", + indent, "", buf, + StlNodeTypeToText(pInformInfo->u.Generic.u2.s.ProducerType)); + } else { + char buf[8]; + FormatTimeoutMult(buf, pInformInfo->u.Generic.u1.s.RespTimeValue); + PrintFunc(dest, "%*s%sSubcribe: Type: %8s VendorId: 0x%04x DeviceId: 0x%04x QPN: 0x%06x\n", + indent, "", + pInformInfo->Subscribe?"":"Un", + IbNoticeTypeToText(pInformInfo->Type), + pInformInfo->u.Vendor.u2.s.VendorID, + pInformInfo->u.Vendor.DeviceID, + pInformInfo->u.Vendor.u1.s.QPNumber); + PrintFunc(dest, "%*sRespTime: %s\n", + indent, "", + buf); + } + PrintFunc(dest, "%*sGID: 0x%016"PRIx64":0x%016"PRIx64 + " LIDs: 0x%08x - 0x%08x\n", + indent, "", + pInformInfo->GID.AsReg64s.H, + pInformInfo->GID.AsReg64s.L, + pInformInfo->LIDRangeBegin, + pInformInfo->LIDRangeEnd); +} + +void PrintStlBfrCtlTable(PrintDest_t *dest, int indent, const STL_BUFFER_CONTROL_TABLE *pBfrCtlTable, int printLineByLine) +{ + int i = 0; + char tempBuf[64]; + if (printLineByLine) { + PrintIntWithDots(dest, indent, "TxOverallSharedLimit", pBfrCtlTable->TxOverallSharedLimit); + for (i = 0; i < STL_MAX_VLS; i++) { + snprintf(tempBuf, sizeof(tempBuf), "VL[%d].TxDedicatedLimit", i); + PrintIntWithDots(dest, indent, tempBuf, pBfrCtlTable->VL[i].TxDedicatedLimit); + snprintf(tempBuf, sizeof(tempBuf), "VL[%d].TxSharedLimit", i); + PrintIntWithDots(dest, indent, tempBuf, pBfrCtlTable->VL[i].TxSharedLimit); + } + } + else { + PrintFunc(dest, "%*sGlobal Shared(AU): %d\n", indent, "", pBfrCtlTable->TxOverallSharedLimit); + for (i = 0; i < STL_MAX_VLS; i++) + PrintFunc(dest, "%*sVL%2u : D: %8d, S: %8d\n", indent, "", i, pBfrCtlTable->VL[i].TxDedicatedLimit, pBfrCtlTable->VL[i].TxSharedLimit); + } +} + +void PrintStlBfrCtlTableSmp(PrintDest_t *dest, int indent, const STL_SMP *smp, uint8_t nodeType, int printLineByLine) +{ + uint8_t * data = stl_get_smp_data((STL_SMP *)smp); + STL_BUFFER_CONTROL_TABLE *table = (STL_BUFFER_CONTROL_TABLE *)(data); + int numPorts = (smp->common.AttributeModifier >> 24) & 0xff; + int port = smp->common.AttributeModifier & 0xff; + int i = 0; + if (printLineByLine) { + for (i = 0; i < numPorts; i++) { + BSWAP_STL_BUFFER_CONTROL_TABLE(table); + PrintIntWithDots(dest, indent, "Port", (int)(port+i)); + PrintStlBfrCtlTable(dest, indent, table, printLineByLine); + PrintSeparator(dest); + // Handle the dissimilar sizes of Buffer Table and 8-byte pad alignment + data += STL_BFRCTRLTAB_PAD_SIZE; + table = (STL_BUFFER_CONTROL_TABLE *)(data); + } + } + else { + for (i = 0; i < numPorts; i++) { + BSWAP_STL_BUFFER_CONTROL_TABLE(table); + PrintFunc(dest, "%*sPort: %2d: ", indent, "", (int)(port+i)); + PrintStlBfrCtlTable(dest, indent, table, printLineByLine); + PrintSeparator(dest); + // Handle the dissimilar sizes of Buffer Table and 8-byte pad alignment + data += STL_BFRCTRLTAB_PAD_SIZE; + table = (STL_BUFFER_CONTROL_TABLE *)(data); + } + } +} + +void PrintStlCableInfoLowPage(PrintDest_t *dest, int indent, const uint8_t *cableInfoData, uint8_t detail, int printLineByLine) +{ + float temp; + char tempBuf[129]; + char tempBuf2[129]; + char temperature[15]={0}; + char vcc[15]={0}; + boolean qsfp_dd = (cableInfoData[0] == STL_CIB_STD_QSFP_DD); + + if (qsfp_dd) + temp = ((cableInfoData[14] << 8) + (cableInfoData[15]))/256.0; + else + temp = ((cableInfoData[22] << 8) + (cableInfoData[23]))/256.0; + if (temp) { + snprintf(temperature, sizeof(temperature), "%.2f C", temp); + } + else { + snprintf(temperature, sizeof(temperature), "not indicated"); + } + if (qsfp_dd) + temp = ((cableInfoData[16] << 8) + (cableInfoData[17]))/10000.0; + else + temp = ((cableInfoData[26] << 8) + (cableInfoData[27]))/10000.0; + if (temp) { + snprintf(vcc, sizeof(vcc), "%.2f V", temp); + } + else { + snprintf(vcc, sizeof(vcc), "not indicated"); + } + + // get connection type + StlCableInfoDecodeConnType(cableInfoData[0], tempBuf2); + + // For lower page, print temperature and vcc + switch (detail) { + case CABLEINFO_DETAIL_ONELINE: + case CABLEINFO_DETAIL_SUMMARY: + case CABLEINFO_DETAIL_BRIEF: + case CABLEINFO_DETAIL_VERBOSE: + if (printLineByLine) { + StringCopy(tempBuf, tempBuf2, strlen(tempBuf2)); + strncat(tempBuf2, ": Direct CableInfo", strlen(": Direct CableInfo") + 1); + PrintStrWithDots(dest, indent, tempBuf2, ""); + PrintStrWithDots(dest, indent, "Temperature", temperature); + PrintStrWithDots(dest, indent, "Supply Voltage", vcc); + break; + } + else { + memset(tempBuf, ' ', sizeof(tempBuf)); + snprintf(tempBuf, sizeof(tempBuf), "%s: %s %s", tempBuf2, temperature, vcc); + PrintFunc(dest, "%*s%s\n", indent, "", tempBuf); + break; + } + case CABLEINFO_DETAIL_ALL: + default: + if (printLineByLine) { + StringCopy(tempBuf, tempBuf2, strlen(tempBuf2)); + strncat(tempBuf2, ": Direct CableInfo", strlen(": Direct CableInfo") + 1); + PrintStrWithDots(dest, indent, tempBuf2, ""); + PrintStrWithDots(dest, indent, "Temperature", temperature); + PrintStrWithDots(dest, indent, "Supply Voltage", vcc); + break; + } + else { + PrintFunc(dest, "%*s%s Interpreted CableInfo:\n", indent, "", tempBuf2); + PrintFunc(dest, "%*sTemperature: %s\n", indent+4, "", temperature); + PrintFunc(dest, "%*sSupply Voltage: %s\n", indent+4, "", vcc); + break; + } + } +} + +#define MAX_CABLE_LENGTH_STR_LEN 8 // ~2-3 digits (poss. decimal pt) plus 'm' + +void PrintStlCableInfoHighPage(PrintDest_t *dest, int indent, const uint8_t *cableInfoData, uint8_t portType, uint8_t detail, int printLineByLine) +{ + unsigned int i; + boolean cableLenValid; // Copper cable length valid + char tempBuf[129]; + char tempStr[STL_CIB_STD_MAX_STRING + 1] = {'\0'}; + STL_CABLE_INFO_STD* cableInfo; + CableTypeInfoType cableTypeInfo; + cableInfo = (STL_CABLE_INFO_STD*)cableInfoData; + + StlCableInfoDecodeCableType(cableInfo->dev_tech.s.xmit_tech, cableInfo->connector, cableInfo->ident, &cableTypeInfo); + cableLenValid = cableTypeInfo.cableLengthValid; + + // Output CableInfo fields per detail level + switch (detail) { + case CABLEINFO_DETAIL_ONELINE: + case CABLEINFO_DETAIL_SUMMARY: + case CABLEINFO_DETAIL_BRIEF: + case CABLEINFO_DETAIL_VERBOSE: + if (printLineByLine) { + // Build ONELINE output line-by-line + strncpy(tempBuf, cableTypeInfo.cableTypeShortDesc, strlen(cableTypeInfo.cableTypeShortDesc)); + PrintStrWithDots(dest, indent, "CableType", tempBuf); + StlCableInfoOM4LengthToText(cableInfo->len_om4, cableLenValid, sizeof(tempBuf), tempBuf); + PrintStrWithDots(dest, indent, "CableLength", tempBuf); + memcpy(tempBuf, cableInfo->vendor_name, sizeof(cableInfo->vendor_name)); + StlCableInfoTrimTrailingWS(tempBuf, sizeof(cableInfo->vendor_name)); + PrintStrWithDots(dest, indent, "CableVendorName", tempBuf); + memcpy(tempBuf, cableInfo->vendor_pn, sizeof(cableInfo->vendor_pn)); + StlCableInfoTrimTrailingWS(tempBuf, sizeof(cableInfo->vendor_pn)); + PrintStrWithDots(dest, indent, "CableVendorPN", tempBuf); + memcpy(tempBuf, cableInfo->vendor_rev, sizeof(cableInfo->vendor_rev)); + StlCableInfoTrimTrailingWS(tempBuf, sizeof(cableInfo->vendor_rev)); + PrintStrWithDots(dest, indent, "CableVendorRev", tempBuf); + if (detail == CABLEINFO_DETAIL_ONELINE) + break; + + // Build line 2 of SUMMARY output line-by-line + PrintStrWithDots( dest, indent, "CablePowerClass", + StlCableInfoPowerClassToText(cableInfo->ext_ident.s.pwr_class_low, cableInfo->ext_ident.s.pwr_class_high) ); + memcpy(tempBuf, cableInfo->vendor_sn, sizeof(cableInfo->vendor_sn)); + StlCableInfoTrimTrailingWS(tempBuf, sizeof(cableInfo->vendor_sn)); + PrintStrWithDots(dest, indent, "CableVendorSN", tempBuf); + StlCableInfoDateCodeToText(cableInfo->date_code, tempBuf); + PrintStrWithDots(dest, indent, "CableDateCode", tempBuf); + + // Build line 3 of SUMMARY output line-by-line + sprintf(tempBuf, "0x%02X%02X%02X", cableInfo->vendor_oui[0], cableInfo->vendor_oui[1], cableInfo->vendor_oui[2]); + PrintStrWithDots(dest, indent, "CableOUI", tempBuf); + break; + } + else { + // Build ONELINE output on one line (68 chars) + memset(tempBuf, ' ', sizeof(tempBuf)); + i = 0; + strcpy(&tempBuf[i], " "); + i = STL_CIB_LINE1_FIELD1; + strncpy(&tempBuf[i], cableTypeInfo.cableTypeShortDesc, strlen(cableTypeInfo.cableTypeShortDesc)); + tempBuf[i + strlen(cableTypeInfo.cableTypeShortDesc)] = ','; + tempBuf[i + 1 + strlen(cableTypeInfo.cableTypeShortDesc)] = ' '; + i = STL_CIB_LINE1_FIELD2; + StlCableInfoOM4LengthToText(cableInfo->len_om4, cableLenValid, MAX_CABLE_LENGTH_STR_LEN, &tempBuf[i]); + tempBuf[i + strlen(&tempBuf[i])] = ' '; + i = STL_CIB_LINE1_FIELD3; + memcpy(tempStr, cableInfo->vendor_name, sizeof(cableInfo->vendor_name)); + StlCableInfoTrimTrailingWS(tempStr, sizeof(cableInfo->vendor_name)); + memcpy(&tempBuf[i], tempStr, strlen(tempStr)); + i = STL_CIB_LINE1_FIELD4; + strcpy(&tempBuf[i], "P/N "); + i = STL_CIB_LINE1_FIELD5; + memcpy(tempStr, cableInfo->vendor_pn, sizeof(cableInfo->vendor_pn)); + StlCableInfoTrimTrailingWS(tempStr, sizeof(cableInfo->vendor_pn)); + memcpy(&tempBuf[i], tempStr, strlen(tempStr)); + i = STL_CIB_LINE1_FIELD6; + strcpy(&tempBuf[i], "Rev "); + i = STL_CIB_LINE1_FIELD7; + memcpy(tempStr, cableInfo->vendor_rev, sizeof(cableInfo->vendor_rev)); + StlCableInfoTrimTrailingWS(tempStr, sizeof(cableInfo->vendor_rev)); + memcpy(&tempBuf[i], tempStr, strlen(tempStr)); + i = STL_CIB_LINE1_FIELD8; + tempBuf[i] = '\0'; + PrintFunc(dest, "%*s%s\n", indent, "", tempBuf); + if (detail == CABLEINFO_DETAIL_ONELINE) + break; + + // Build line 2 of SUMMARY output on one line (68 chars) + memset(tempBuf, ' ', sizeof(tempBuf)); + i = STL_CIB_LINE2_FIELD1; + strcpy(&tempBuf[i], StlCableInfoPowerClassToText(cableInfo->ext_ident.s.pwr_class_low, cableInfo->ext_ident.s.pwr_class_high)); + tempBuf[i + strlen(&tempBuf[i])] = ' '; + i = STL_CIB_LINE2_FIELD2; + strcpy(&tempBuf[i], "S/N "); + i = STL_CIB_LINE2_FIELD3; + memcpy(tempStr, cableInfo->vendor_sn, sizeof(cableInfo->vendor_sn)); + StlCableInfoTrimTrailingWS(tempStr, sizeof(cableInfo->vendor_sn)); + memcpy(&tempBuf[i], tempStr, strlen(tempStr)); + i = STL_CIB_LINE2_FIELD4; + strcpy(&tempBuf[i], "Mfg "); + i = STL_CIB_LINE2_FIELD5; + StlCableInfoDateCodeToText(cableInfo->date_code, &tempBuf[i]); + PrintFunc(dest, "%*s%s\n", indent, "", tempBuf); + + // Build line 3 of SUMMARY output on one line (68 chars) + memset(tempBuf, ' ', sizeof(tempBuf)); + i = STL_CIB_LINE3_FIELD1; + sprintf(&tempBuf[i], "OUI 0x%02X%02X%02X", cableInfo->vendor_oui[0], cableInfo->vendor_oui[1], cableInfo->vendor_oui[2]); + PrintFunc(dest, "%*s%s\n", indent, "", tempBuf); + break; + } + + case CABLEINFO_DETAIL_ALL: + default: + if (printLineByLine) { + if (portType != STL_PORT_TYPE_STANDARD) return; + PrintStrWithDots(dest, indent, "QSFP Direct CableInfo", ""); + PrintIntWithDots(dest, indent, "Identifier", cableInfo->ident); + PrintStrWithDots(dest, indent, "PowerClass", + StlCableInfoPowerClassToText(cableInfo->ext_ident.s.pwr_class_low, cableInfo->ext_ident.s.pwr_class_high)); + PrintStrWithDots(dest, indent, "Connector", cableTypeInfo.connectorType); + StlCableInfoBitRateToText(cableInfo->bit_rate_low, cableInfo->bit_rate_high, tempBuf); + PrintStrWithDots(dest, indent, "NominalBR", tempBuf); + StlCableInfoCableTypeToTextLong(cableInfo->dev_tech.s.xmit_tech, cableInfo->connector, tempBuf); + PrintStrWithDots(dest, indent, "DeviceTech", tempBuf); + memcpy(tempStr, cableInfo->vendor_name, sizeof(cableInfo->vendor_name)); + StlCableInfoTrimTrailingWS(tempStr, sizeof(cableInfo->vendor_name)); + PrintStrWithDots(dest, indent, "VendorName", tempStr); + snprintf(tempStr, sizeof(tempStr), "0x%02x%02x%02x", cableInfo->vendor_oui[0], + cableInfo->vendor_oui[1], cableInfo->vendor_oui[2]); + PrintStrWithDots(dest, indent, "VendorOUI", tempStr); + memcpy(tempStr, cableInfo->vendor_pn, sizeof(cableInfo->vendor_pn)); + StlCableInfoTrimTrailingWS(tempStr, sizeof(cableInfo->vendor_pn)); + PrintStrWithDots(dest, indent, "VendorPN", tempStr); + memcpy(tempStr, cableInfo->vendor_rev, sizeof(cableInfo->vendor_rev)); + StlCableInfoTrimTrailingWS(tempStr, sizeof(cableInfo->vendor_rev)); + PrintStrWithDots(dest, indent, "VendorRev", tempStr); + PrintIntWithDots(dest, indent, "CC_BASE", cableInfo->cc_base); + memcpy(tempStr, cableInfo->vendor_sn, sizeof(cableInfo->vendor_sn)); + StlCableInfoTrimTrailingWS(tempStr, sizeof(cableInfo->vendor_sn)); + PrintStrWithDots(dest, indent, "VendorSN", tempStr); + StlCableInfoDateCodeToText(cableInfo->date_code, tempBuf); + PrintStrWithDots(dest, indent, "DateCode", tempBuf); + PrintIntWithDots(dest, indent, "CC_EXT", cableInfo->cc_ext); + break; + } + else { + if (portType != STL_PORT_TYPE_STANDARD) return; + PrintFunc(dest, "%*sQSFP Interpreted CableInfo:\n", indent, ""); + PrintFunc(dest, "%*sIdentifier: 0x%x\n", indent+4, "", cableInfo->ident); + PrintFunc(dest, "%*sPowerClass: %s\n", indent+4, "", + StlCableInfoPowerClassToText(cableInfo->ext_ident.s.pwr_class_low, cableInfo->ext_ident.s.pwr_class_high)); + memcpy(tempBuf, cableTypeInfo.connectorType, sizeof(cableTypeInfo.connectorType)); + PrintFunc(dest, "%*sConnector: %s\n", indent+4, "", tempBuf); + StlCableInfoBitRateToText(cableInfo->bit_rate_low, cableInfo->bit_rate_high, tempBuf); + PrintFunc(dest, "%*sNominalBR: %s\n", indent+4, "", tempBuf); + StlCableInfoCableTypeToTextLong(cableInfo->dev_tech.s.xmit_tech, cableInfo->connector, tempBuf); + PrintFunc(dest, "%*sDeviceTech: %s\n", indent+4, "", tempBuf); + memcpy(tempStr, cableInfo->vendor_name, sizeof(cableInfo->vendor_name)); + StlCableInfoTrimTrailingWS(tempStr, sizeof(cableInfo->vendor_name)); + PrintFunc(dest, "%*sVendorName: %s\n", indent+4, "", tempStr); + PrintFunc(dest, "%*sVendorOUI: 0x%02x%02x%02x\n", indent+4, "", cableInfo->vendor_oui[0], + cableInfo->vendor_oui[1], cableInfo->vendor_oui[2]); + memcpy(tempStr, cableInfo->vendor_pn, sizeof(cableInfo->vendor_pn)); + StlCableInfoTrimTrailingWS(tempStr, sizeof(cableInfo->vendor_pn)); + PrintFunc(dest, "%*sVendorPN: %s\n", indent+4, "", tempStr); + memcpy(tempStr, cableInfo->vendor_rev, sizeof(cableInfo->vendor_rev)); + StlCableInfoTrimTrailingWS(tempStr, sizeof(cableInfo->vendor_rev)); + PrintFunc(dest, "%*sVendorRev: %s\n", indent+4, "", tempStr); + PrintFunc(dest, "%*sCC_BASE: 0x%x\n", indent+4, "", cableInfo->cc_base); + memcpy(tempStr, cableInfo->vendor_sn, sizeof(cableInfo->vendor_sn)); + StlCableInfoTrimTrailingWS(tempStr, sizeof(cableInfo->vendor_sn)); + PrintFunc(dest, "%*sVendorSN: %s\n", indent+4, "", tempStr); + StlCableInfoDateCodeToText(cableInfo->date_code, tempBuf); + PrintFunc(dest, "%*sDateCode: %s\n", indent+4, "", tempBuf); + PrintFunc(dest, "%*sCC_EXT: 0x%x\n", indent+4, "", cableInfo->cc_ext); + break; + } + + } // End of switch (detail) + + +} + +// Print for upper page 0 for QSFP-DD +void PrintStlCableInfoHighPage0DD(PrintDest_t *dest, int indent, const uint8_t *cableInfoData, uint8_t portType, uint8_t detail, int printLineByLine) +{ + unsigned int i; + boolean cableLenValid; // Copper cable length valid + char tempBuf[129]; + char tempStr[STL_CIB_STD_MAX_STRING + 1] = {'\0'}; + STL_CABLE_INFO_UP0_DD* cableInfo; + CableTypeInfoType cableTypeInfo; + cableInfo = (STL_CABLE_INFO_UP0_DD*)cableInfoData; + + StlCableInfoDecodeCableType(cableInfo->cable_type, cableInfo->connector, cableInfo->ident, &cableTypeInfo); + cableLenValid = cableTypeInfo.cableLengthValid; + + // Output CableInfo fields per detail level + switch (detail) { + case CABLEINFO_DETAIL_ONELINE: + case CABLEINFO_DETAIL_SUMMARY: + case CABLEINFO_DETAIL_BRIEF: + case CABLEINFO_DETAIL_VERBOSE: + if (printLineByLine) { + // Build ONELINE output line-by-line + strncpy(tempBuf, cableTypeInfo.cableTypeShortDesc, strlen(cableTypeInfo.cableTypeShortDesc)); + PrintStrWithDots(dest, indent, "CableType", tempBuf); + StlCableInfoDDCableLengthToText(cableInfo->cableLengthEnc, cableLenValid, sizeof(tempBuf), tempBuf); + PrintStrWithDots(dest, indent, "CableLength", tempBuf); + memcpy(tempBuf, cableInfo->vendor_name, sizeof(cableInfo->vendor_name)); + StlCableInfoTrimTrailingWS(tempBuf, sizeof(cableInfo->vendor_name)); + PrintStrWithDots(dest, indent, "CableVendorName", tempBuf); + memcpy(tempBuf, cableInfo->vendor_pn, sizeof(cableInfo->vendor_pn)); + StlCableInfoTrimTrailingWS(tempBuf, sizeof(cableInfo->vendor_pn)); + PrintStrWithDots(dest, indent, "CableVendorPN", tempBuf); + memcpy(tempBuf, cableInfo->vendor_rev, sizeof(cableInfo->vendor_rev)); + StlCableInfoTrimTrailingWS(tempBuf, sizeof(cableInfo->vendor_rev)); + PrintStrWithDots(dest, indent, "CableVendorRev", tempBuf); + if (detail == CABLEINFO_DETAIL_ONELINE) + break; + + // Build line 2 of SUMMARY output line-by-line + snprintf(tempBuf, 20, "%.2f W max", (float)cableInfo->powerMax / 4.0); + PrintStrWithDots( dest, indent, "CableMaxPower", tempBuf); + memcpy(tempBuf, cableInfo->vendor_sn, sizeof(cableInfo->vendor_sn)); + StlCableInfoTrimTrailingWS(tempBuf, sizeof(cableInfo->vendor_sn)); + PrintStrWithDots(dest, indent, "CableVendorSN", tempBuf); + StlCableInfoDateCodeToText(cableInfo->date_code, tempBuf); + PrintStrWithDots(dest, indent, "CableDateCode", tempBuf); + + // Build line 3 of SUMMARY output line-by-line + sprintf(tempBuf, "0x%02X%02X%02X", cableInfo->vendor_oui[0], cableInfo->vendor_oui[1], cableInfo->vendor_oui[2]); + PrintStrWithDots(dest, indent, "CableOUI", tempBuf); + break; + } + else { + // Build ONELINE output on one line (68 chars) + memset(tempBuf, ' ', sizeof(tempBuf)); + i = 0; + strcpy(&tempBuf[i], " "); + i = STL_CIB_LINE1_FIELD1; + strncpy(&tempBuf[i], cableTypeInfo.cableTypeShortDesc, strlen(cableTypeInfo.cableTypeShortDesc)); + tempBuf[i + strlen(cableTypeInfo.cableTypeShortDesc)] = ','; + tempBuf[i + 1 + strlen(cableTypeInfo.cableTypeShortDesc)] = ' '; + i = STL_CIB_LINE1_FIELD2; + StlCableInfoDDCableLengthToText(cableInfo->cableLengthEnc, cableLenValid, sizeof(tempBuf), tempBuf); + tempBuf[i + strlen(&tempBuf[i])] = ' '; + i = STL_CIB_LINE1_FIELD3; + memcpy(tempStr, cableInfo->vendor_name, sizeof(cableInfo->vendor_name)); + StlCableInfoTrimTrailingWS(tempStr, sizeof(cableInfo->vendor_name)); + memcpy(&tempBuf[i], tempStr, strlen(tempStr)); + i = STL_CIB_LINE1_FIELD4; + strcpy(&tempBuf[i], "P/N "); + i = STL_CIB_LINE1_FIELD5; + memcpy(tempStr, cableInfo->vendor_pn, sizeof(cableInfo->vendor_pn)); + StlCableInfoTrimTrailingWS(tempStr, sizeof(cableInfo->vendor_pn)); + memcpy(&tempBuf[i], tempStr, strlen(tempStr)); + i = STL_CIB_LINE1_FIELD6; + strcpy(&tempBuf[i], "Rev "); + i = STL_CIB_LINE1_FIELD7; + memcpy(tempStr, cableInfo->vendor_rev, sizeof(cableInfo->vendor_rev)); + StlCableInfoTrimTrailingWS(tempStr, sizeof(cableInfo->vendor_rev)); + memcpy(&tempBuf[i], tempStr, strlen(tempStr)); + i = STL_CIB_LINE1_FIELD8; + tempBuf[i] = '\0'; + PrintFunc(dest, "%*s%s\n", indent, "", tempBuf); + if (detail == CABLEINFO_DETAIL_ONELINE) + break; + + // Build line 2 of SUMMARY output on one line (68 chars) + memset(tempBuf, ' ', sizeof(tempBuf)); + i = STL_CIB_LINE2_FIELD1; + snprintf(&tempBuf[i], 20, "%.2f W max", (float)cableInfo->powerMax / 4.0); + tempBuf[i + strlen(&tempBuf[i])] = ' '; + i = STL_CIB_LINE2_FIELD2; + strcpy(&tempBuf[i], "S/N "); + i = STL_CIB_LINE2_FIELD3; + memcpy(tempStr, cableInfo->vendor_sn, sizeof(cableInfo->vendor_sn)); + StlCableInfoTrimTrailingWS(tempStr, sizeof(cableInfo->vendor_sn)); + memcpy(&tempBuf[i], tempStr, strlen(tempStr)); + i = STL_CIB_LINE2_FIELD4; + strcpy(&tempBuf[i], "Mfg "); + i = STL_CIB_LINE2_FIELD5; + StlCableInfoDateCodeToText(cableInfo->date_code, &tempBuf[i]); + PrintFunc(dest, "%*s%s\n", indent, "", tempBuf); + + // Build line 3 of SUMMARY output on one line (68 chars) + memset(tempBuf, ' ', sizeof(tempBuf)); + i = STL_CIB_LINE3_FIELD1; + sprintf(&tempBuf[i], "OUI 0x%02X%02X%02X", cableInfo->vendor_oui[0], cableInfo->vendor_oui[1], cableInfo->vendor_oui[2]); + PrintFunc(dest, "%*s%s\n", indent, "", tempBuf); + break; + } + + case CABLEINFO_DETAIL_ALL: + default: + if (printLineByLine) { + if (portType != STL_PORT_TYPE_STANDARD) return; + PrintStrWithDots(dest, indent, "QSFP Direct CableInfo", ""); + PrintIntWithDots(dest, indent, "Identifier", cableInfo->ident); + snprintf(tempBuf, 20, "%.2f W max", (float)cableInfo->powerMax / 4.0); + PrintStrWithDots(dest, indent, "CableMaxPower", tempBuf); + memcpy(tempBuf, cableTypeInfo.connectorType, sizeof(cableTypeInfo.connectorType)); + PrintStrWithDots(dest, indent, "Connector", tempBuf); + snprintf(tempBuf, 4, "n/a"); + PrintStrWithDots(dest, indent, "NominalBR", tempBuf); + StlCableInfoCableTypeToTextLong(cableInfo->cable_type, cableInfo->connector, tempBuf); + PrintStrWithDots(dest, indent, "DeviceTech", tempBuf); + memcpy(tempStr, cableInfo->vendor_name, sizeof(cableInfo->vendor_name)); + StlCableInfoTrimTrailingWS(tempStr, sizeof(cableInfo->vendor_name)); + PrintStrWithDots(dest, indent, "VendorName", tempStr); + snprintf(tempStr, sizeof(tempStr), "0x%02x%02x%02x", cableInfo->vendor_oui[0], + cableInfo->vendor_oui[1], cableInfo->vendor_oui[2]); + PrintStrWithDots(dest, indent, "VendorOUI", tempStr); + memcpy(tempStr, cableInfo->vendor_pn, sizeof(cableInfo->vendor_pn)); + StlCableInfoTrimTrailingWS(tempStr, sizeof(cableInfo->vendor_pn)); + PrintStrWithDots(dest, indent, "VendorPN", tempStr); + memcpy(tempStr, cableInfo->vendor_rev, sizeof(cableInfo->vendor_rev)); + StlCableInfoTrimTrailingWS(tempStr, sizeof(cableInfo->vendor_rev)); + PrintStrWithDots(dest, indent, "VendorRev", tempStr); + memcpy(tempStr, cableInfo->vendor_sn, sizeof(cableInfo->vendor_sn)); + StlCableInfoTrimTrailingWS(tempStr, sizeof(cableInfo->vendor_sn)); + PrintStrWithDots(dest, indent, "VendorSN", tempStr); + StlCableInfoDateCodeToText(cableInfo->date_code, tempBuf); + PrintStrWithDots(dest, indent, "DateCode", tempBuf); + break; + } + else { + if (portType != STL_PORT_TYPE_STANDARD) return; + PrintFunc(dest, "%*sQSFP Interpreted CableInfo:\n", indent, ""); + PrintFunc(dest, "%*sIdentifier: 0x%x\n", indent+4, "", cableInfo->ident); + snprintf(tempBuf, 20, "%.2f W max", (float)cableInfo->powerMax / 4.0); + PrintFunc(dest, "%*sCableMaxPower: %s\n", indent+4, "", tempBuf); + memcpy(tempBuf, cableTypeInfo.connectorType, sizeof(cableTypeInfo.connectorType)); + PrintFunc(dest, "%*sConnector: %s\n", indent+4, "", tempBuf); + StlCableInfoCableTypeToTextLong(cableInfo->cable_type, cableInfo->connector, tempBuf); + PrintFunc(dest, "%*sDeviceTech: %s\n", indent+4, "", tempBuf); + memcpy(tempStr, cableInfo->vendor_name, sizeof(cableInfo->vendor_name)); + StlCableInfoTrimTrailingWS(tempStr, sizeof(cableInfo->vendor_name)); + PrintFunc(dest, "%*sVendorName: %s\n", indent+4, "", tempStr); + PrintFunc(dest, "%*sVendorOUI: 0x%02x%02x%02x\n", indent+4, "", cableInfo->vendor_oui[0], + cableInfo->vendor_oui[1], cableInfo->vendor_oui[2]); + memcpy(tempStr, cableInfo->vendor_pn, sizeof(cableInfo->vendor_pn)); + StlCableInfoTrimTrailingWS(tempStr, sizeof(cableInfo->vendor_pn)); + PrintFunc(dest, "%*sVendorPN: %s\n", indent+4, "", tempStr); + memcpy(tempStr, cableInfo->vendor_rev, sizeof(cableInfo->vendor_rev)); + StlCableInfoTrimTrailingWS(tempStr, sizeof(cableInfo->vendor_rev)); + PrintFunc(dest, "%*sVendorRev: %s\n", indent+4, "", tempStr); + memcpy(tempStr, cableInfo->vendor_sn, sizeof(cableInfo->vendor_sn)); + StlCableInfoTrimTrailingWS(tempStr, sizeof(cableInfo->vendor_sn)); + PrintFunc(dest, "%*sVendorSN: %s\n", indent+4, "", tempStr); + StlCableInfoDateCodeToText(cableInfo->date_code, tempBuf); + PrintFunc(dest, "%*sDateCode: %s\n", indent+4, "", tempBuf); + break; + } + + } // End of switch (detail) + + return; +} + +void PrintStlCableInfoDump(PrintDest_t *dest, int indent, const uint8_t *cableInfoData, uint16_t addr, uint8_t len, int printLineByLine) +{ + unsigned int i, j; + char tempBuf[129]; + char tempVal[64]; + if (printLineByLine) { + PrintStrWithDots(dest, indent, "CableInfo Dump of Received Address and Data", ""); + for (i = 0; i * 16 < len; ++i) { + int strOffset = 0; + // Print 16 bytes per line + snprintf(tempBuf, sizeof(tempBuf), "addr[%04X]", addr + i * 16); + for (j = 0; j < MIN(16, len - i * 16); ++j) + strOffset += snprintf( &tempVal[strOffset], 64-strOffset, "%s%02x", + (j?",":""), cableInfoData[i * 16 + j] ); + PrintStrWithDots(dest, indent, tempBuf, tempVal); + } + } + else { + PrintFunc(dest, "%*sCableInfo Dump of Received Address and Data:\n", indent, ""); + for (i = 0; i * 16 < len; ++i) { + // Print 16 bytes per line + PrintFunc(dest, "%*s%8u:", indent, "", addr + i * 16); + for (j = 0; j < MIN(16, len - i * 16); ++j) + PrintFunc(dest, " %.2x", cableInfoData[i * 16 + j]); + PrintFunc(dest, "\n"); + } + } +} + +// Print CableInfo data at specified detail level and in specified format +// +// len - Real length of cable data (must be <= 255) +// detail - Output detail level as CABLEINFO_DETAIL_xxx +// printLineByLine = 1 - Print line-by-line format +void PrintStlCableInfo(PrintDest_t *dest, int indent, const uint8_t *cableInfoData, uint16_t addr, uint8_t len, uint8_t portType, uint8_t detail, int printLineByLine, boolean hexOnly) +{ + boolean qsfp_dd; + + if (cableInfoData) + qsfp_dd = (cableInfoData[0] == STL_CIB_STD_QSFP_DD); + else { + fprintf(stderr, "PrintStlCableInfo: cableInfoData pointer is invalid\n"); + return; + } + + if (hexOnly) { + PrintStlCableInfoDump(dest, indent, cableInfoData, addr, len, printLineByLine); + } + else if (addr==STL_CIB_STD_LOW_PAGE_ADDR && len==STL_CIB_STD_LEN) { + if (detail >= CABLEINFO_DETAIL_ALL) { + PrintStlCableInfoDump(dest, indent, cableInfoData, addr, len, printLineByLine); + } + PrintStlCableInfoLowPage(dest, indent, cableInfoData, detail, printLineByLine); + } + else if (addr==STL_CIB_STD_HIGH_PAGE_ADDR && len==STL_CIB_STD_LEN){ + if (detail >= CABLEINFO_DETAIL_ALL) { + PrintStlCableInfoDump(dest, indent, cableInfoData, addr, len, printLineByLine); + } + if (qsfp_dd) + PrintStlCableInfoHighPage0DD(dest, indent, cableInfoData, portType, detail, printLineByLine); + else + PrintStlCableInfoHighPage(dest, indent, cableInfoData, portType, detail, printLineByLine); + } + else { + PrintFunc(dest, "%*sOnly raw hex cable data available - Addr:%u Len:%u\n", indent, "", addr, len); + PrintStlCableInfoDump(dest, indent, cableInfoData, addr, len, printLineByLine); + } + +} // End of PrintStlCableInfo() + +void PrintStlCableInfoSmp(PrintDest_t *dest, int indent, const STL_SMP *smp, uint8_t portType, int printLineByLine) +{ + STL_CABLE_INFO *pCableInfo = (STL_CABLE_INFO*)stl_get_smp_data((STL_SMP*)smp); + const uint16_t addr = (smp->common.AttributeModifier>>19) & 0x0fff; + const uint8_t len = (smp->common.AttributeModifier>>13) & 0x3f; + + if (printLineByLine) { + PrintIntWithDots(dest, indent, "Starting Address", addr); + PrintIntWithDots(dest, indent, "Length", len+1); + PrintStrWithDots(dest, indent, "Port Type", StlPortTypeToText(portType)); + } + else { + PrintFunc(dest, "%*sStarting Address: 0x%x (%u)\nLength: %u\nPort Type: %s\n", + indent, "", + addr, addr, len+1, StlPortTypeToText(portType)); + } + BSWAP_STL_CABLE_INFO(pCableInfo); + PrintStlCableInfo(dest, indent, pCableInfo->Data, addr, len+1, portType, CABLEINFO_DETAIL_ALL, printLineByLine,FALSE); +} + +void PrintStlPortGroupFDB(PrintDest_t *dest, int indent, const STL_PORT_GROUP_FORWARDING_TABLE *pPortGroupFDB, uint32 blockNum, int printLineByLine) +{ + int i; + STL_LID baselid = blockNum*NUM_PGFT_ELEMENTS_BLOCK; + char tempBuf[64]; + if (printLineByLine) { + for (i=0; iPgftBlock[i] != 255) { + PrintIntWithDots(dest, indent, "LID", baselid +i); + snprintf(tempBuf, sizeof(tempBuf), "PgftBlock[%i].Port", i); + PrintIntWithDots(dest, indent, tempBuf, pPortGroupFDB->PgftBlock[i]); + } + } + } + else { + for (i=0; iPgftBlock[i] != 255) + PrintFunc(dest, "%*s LID 0x%08x -> PortGroup %3u\n", + indent, "", baselid + i, + pPortGroupFDB->PgftBlock[i]); + } + } +} + + +void PrintStlPortGroupTable(PrintDest_t *dest, int indent, const uint64_t *pPortGroup, uint32 blockNum, int position, int printLineByLine) +{ + int i, j; + position *= 64; // Move to the right positional port number + uint64 msk = 0; + + if (printLineByLine) { + for (i=0; iPortStates.s.PortState) { + default: + case IB_PORT_DOWN: + show_rate = SHOW_RATE_EN; + show_mgmt = 0; + show_address = 0; + show_perf = 0; + + if (pPortInfo->PortPhysConfig.s.PortType == STL_PORT_TYPE_STANDARD + && pPortInfo->PortStates.s.OfflineDisabledReason != STL_OFFDIS_REASON_LOCAL_MEDIA_NOT_INSTALLED + && pPortInfo->PortStates.s.OfflineDisabledReason != STL_OFFDIS_REASON_SWITCH_MGMT + && pPortInfo->PortStates.s.OfflineDisabledReason != STL_OFFDIS_REASON_SMA_DISABLED) { + show_cable = 1; + } + break; + case IB_PORT_INIT: + show_rate = SHOW_RATE_ACT; + if (pPortInfo->PortNeighborMode.NeighborNodeType == STL_NEIGH_NODE_TYPE_SW + // my neighbor is PRR + && pPortInfo->NeighborPortNum) // only switch port 0 has no neighbor + show_mgmt = 1; // pkey in Init reflects MgmtAllowed for links w/sw + else + show_mgmt = 0; // omit for HFI to HFI link, and switch port 0 + // Mgmt is uncertain til armed + show_address = 0; + if (pPortInfo->PortPhysConfig.s.PortType == STL_PORT_TYPE_STANDARD) + show_cable = 1; + show_perf = 1; + break; + case IB_PORT_ARMED: + case IB_PORT_ACTIVE: + show_rate = SHOW_RATE_ACT; + show_mgmt = 1; // once Armed, pkey reflects MgmtAllowed or in Admin VF + show_address = 1; + if (pPortInfo->PortPhysConfig.s.PortType == STL_PORT_TYPE_STANDARD) + show_cable = 1; + show_perf = 1; + break; + } + + if(pPortInfo->LinkDownReason != 0) + ldr = pPortInfo->LinkDownReason; + else if(pPortInfo->NeighborLinkDownReason != 0) + ldr = pPortInfo->NeighborLinkDownReason; + + if (printLineByLine) { + // this is for scripting, so its easier for calling scripts if we + // always return all related fields from the summary + PrintStrWithDots(dest, indent, "PortName", portName); + if (portGuid) + PrintIntWithDotsFull(dest, indent, "PortGUID", portGuid); + if (show_address) + PrintIntWithDots(dest, indent, "SubnetPrefix", pPortInfo->SubnetPrefix); + if (pPortInfo->PortStates.s.PortState == IB_PORT_DOWN) { + PrintIntWithDots(dest, indent, "PortStates.s.PortPhysicalState", (uint32)pPortInfo->PortStates.s.PortPhysicalState); + if (ldr) { + PrintIntWithDots(dest, indent, "LinkDownReason", (uint32)pPortInfo->LinkDownReason); + PrintIntWithDots(dest, indent, "NeighborLinkDownReason", (uint32)pPortInfo->NeighborLinkDownReason); + } + + if (pPortInfo->PortStates.s.PortPhysicalState == STL_PORT_PHYS_OFFLINE + || pPortInfo->PortStates.s.PortPhysicalState == IB_PORT_PHYS_DISABLED) + PrintIntWithDots(dest, indent, "PortStates.s.OfflineDisabledReason", (uint32)pPortInfo->PortStates.s.OfflineDisabledReason); + } else { + PrintIntWithDots(dest, indent, "PortStates.s.PortState", (uint32)pPortInfo->PortStates.s.PortState); + if (pPortInfo->PortStates.s.PortState == IB_PORT_INIT) + PrintIntWithDots(dest, indent, "LinkInitReason", (uint32)pPortInfo->s3.LinkInitReason); + if (pPortInfo->PortStates.s.PortState == IB_PORT_ARMED) + PrintIntWithDots(dest, indent, "PortStates.s.NeighborNormal", (uint32)pPortInfo->PortStates.s.NeighborNormal); + } + + switch (show_rate) { + case SHOW_RATE_NONE: + break; + case SHOW_RATE_EN: + PrintIntWithDots(dest, indent, "LinkSpeed.Enabled", (uint32)pPortInfo->LinkSpeed.Enabled); + PrintIntWithDots(dest, indent, "LinkSpeed.Supported", (uint32)pPortInfo->LinkSpeed.Supported); + PrintIntWithDots(dest, indent, "LinkWidth.Enabled", (uint32)pPortInfo->LinkWidth.Enabled); + PrintIntWithDots(dest, indent, "LinkWidth.Supported", (uint32)pPortInfo->LinkWidth.Supported); + PrintIntWithDots(dest, indent, "LinkWidthDowngrade.Enabled", (uint32)pPortInfo->LinkWidthDowngrade.Enabled); + PrintIntWithDots(dest, indent, "LinkWidthDowngrade.Supported", (uint32)pPortInfo->LinkWidthDowngrade.Supported); + PrintIntWithDots(dest, indent, "PortLTPCRCMode.s.Enabled", (uint32)pPortInfo->PortLTPCRCMode.s.Enabled); + PrintIntWithDots(dest, indent, "PortLTPCRCMode.s.Supported", (uint32)pPortInfo->PortLTPCRCMode.s.Supported); + break; + case SHOW_RATE_ACT: + PrintIntWithDots(dest, indent, "LinkSpeed.Active", (uint32)pPortInfo->LinkSpeed.Active); + PrintIntWithDots(dest, indent, "LinkSpeed.Enabled", (uint32)pPortInfo->LinkSpeed.Enabled); + PrintIntWithDots(dest, indent, "LinkWidth.Active", (uint32)pPortInfo->LinkWidth.Active); + PrintIntWithDots(dest, indent, "LinkWidth.Enabled", (uint32)pPortInfo->LinkWidth.Enabled); + PrintIntWithDots(dest, indent, "LinkWidthDowngrade.Enabled", (uint32)pPortInfo->LinkWidthDowngrade.Enabled); + PrintIntWithDots(dest, indent, "LinkWidthDowngrade.TxActive", (uint32)pPortInfo->LinkWidthDowngrade.TxActive); + PrintIntWithDots(dest, indent, "LinkWidthDowngrade.RxActive", (uint32)pPortInfo->LinkWidthDowngrade.RxActive); + PrintIntWithDots(dest, indent, "PortLTPCRCMode.s.Enabled", (uint32)pPortInfo->PortLTPCRCMode.s.Enabled); + PrintIntWithDots(dest, indent, "PortLTPCRCMode.s.Active", (uint32)pPortInfo->PortLTPCRCMode.s.Active); + if (show_mgmt) + PrintStrWithDots(dest, indent, "Mgmt", (pkey == 0xffff)?"True":"False"); + break; + } + if (show_address) { + PrintIntWithDots(dest, indent, "LID", (uint32)pPortInfo->LID); + PrintIntWithDots(dest, indent, "LMC", (uint32)pPortInfo->s1.LMC); + PrintIntWithDots(dest, indent, "MasterSMLID", (uint32)pPortInfo->MasterSMLID); + PrintIntWithDots(dest, indent, "MasterSMSL", (uint32)pPortInfo->s2.MasterSMSL); + } + } else { + char tempBuf[64]; + char tempBuf2[64]; + char tempBuf3[64]; + char tempBuf4[64]; + + // portName can be up to 68 characters, but typically much smaller + if (portGuid && show_address) + PrintFunc(dest, "%*s%-34s PortGID:0x%016"PRIx64":%016"PRIx64"\n", + indent, "", portName, pPortInfo->SubnetPrefix, portGuid); + else if (portGuid) + PrintFunc(dest, "%*s%-34s PortGUID:0x%016"PRIx64"\n", + indent, "", portName, portGuid); + else + PrintFunc(dest, "%*s%-34s\n", + indent, "", portName); + + indent += 3; + + switch (pPortInfo->PortStates.s.PortState) { + default: + case IB_PORT_DOWN: + if (pPortInfo->PortStates.s.PortPhysicalState == STL_PORT_PHYS_OFFLINE + || pPortInfo->PortStates.s.PortPhysicalState == IB_PORT_PHYS_DISABLED) { + if (ldr) + PrintFunc(dest, "%*sPhysicalState: %-14s (%s) OfflineDisabledReason: %-14s\n", + indent, "", + StlPortPhysStateToText(pPortInfo->PortStates.s.PortPhysicalState), + StlLinkDownReasonToText(ldr), + StlPortOfflineDisabledReasonToText(pPortInfo->PortStates.s.OfflineDisabledReason)); + else + PrintFunc(dest, "%*sPhysicalState: %-14s OfflineDisabledReason: %-14s\n", + indent, "", + StlPortPhysStateToText(pPortInfo->PortStates.s.PortPhysicalState), + StlPortOfflineDisabledReasonToText(pPortInfo->PortStates.s.OfflineDisabledReason)); + } else { + if (ldr) + PrintFunc(dest, "%*sPhysicalState: %-14s (%s)\n", + indent, "", + StlPortPhysStateToText(pPortInfo->PortStates.s.PortPhysicalState), + StlLinkDownReasonToText(ldr)); + else + PrintFunc(dest, "%*sPhysicalState: %-14s\n", + indent, "", + StlPortPhysStateToText(pPortInfo->PortStates.s.PortPhysicalState)); + } + break; + case IB_PORT_INIT: + if (pPortInfo->s3.LinkInitReason) + PrintFunc(dest, "%*sPortState: %s (%s)\n", + indent, "", + StlPortStateToText(pPortInfo->PortStates.s.PortState), + StlLinkInitReasonToText(pPortInfo->s3.LinkInitReason)); + else + PrintFunc(dest, "%*sPortState: %s\n", + indent, "", + StlPortStateToText(pPortInfo->PortStates.s.PortState)); + break; + case IB_PORT_ARMED: + PrintFunc(dest, "%*sPortState: %s NeighborNormal: %s\n", + indent, "", + StlPortStateToText(pPortInfo->PortStates.s.PortState), + pPortInfo->PortStates.s.NeighborNormal?"True":"False"); + break; + case IB_PORT_ACTIVE: + PrintFunc(dest, "%*sPortState: %s\n", + indent, "", + StlPortStateToText(pPortInfo->PortStates.s.PortState)); + break; + } + switch (show_rate) { + case SHOW_RATE_NONE: + break; + case SHOW_RATE_EN: + // TBD - combine width and speed into one line + // 16 char too long + // remove "Link" = 8, Gb->g = 2, 12s->11s = 2 + PrintFunc(dest, "%*sLinkSpeed En: %-12s Sup: %-12s\n", + indent,"", + StlLinkSpeedToText(pPortInfo->LinkSpeed.Enabled, tempBuf, sizeof(tempBuf2)), + StlLinkSpeedToText(pPortInfo->LinkSpeed.Supported, tempBuf2, sizeof(tempBuf))); + PrintFunc(dest, "%*sLinkWidth En: %-12s Sup: %-12s\n", + indent,"", + StlLinkWidthToText(pPortInfo->LinkWidth.Enabled, tempBuf3, sizeof(tempBuf4)), + StlLinkWidthToText(pPortInfo->LinkWidth.Supported, tempBuf4, sizeof(tempBuf3))); + PrintFunc(dest, "%*sLCRC En: %-8s Sup: %-8s\n", + indent, "", + StlPortLtpCrcModeToText(pPortInfo->PortLTPCRCMode.s.Enabled, tempBuf, sizeof(tempBuf)), + StlPortLtpCrcModeToText(pPortInfo->PortLTPCRCMode.s.Supported, tempBuf3, sizeof(tempBuf3))); + break; + case SHOW_RATE_ACT: + // TBD - combine width and speed into one line + PrintFunc(dest, "%*sLinkSpeed Act: %-12s En: %-12s\n", + indent,"", + StlLinkSpeedToText(pPortInfo->LinkSpeed.Active, tempBuf, sizeof(tempBuf)), + StlLinkSpeedToText(pPortInfo->LinkSpeed.Enabled, tempBuf2, sizeof(tempBuf3))); + PrintFunc(dest, "%*sLinkWidth Act: %-12s En: %-12s\n", + indent,"", + StlLinkWidthToText(pPortInfo->LinkWidth.Active, tempBuf3, sizeof(tempBuf)), + StlLinkWidthToText(pPortInfo->LinkWidth.Enabled, tempBuf4, sizeof(tempBuf3))); + PrintFunc(dest, "%*sLinkWidthDnGrd ActTx: %-2.2s Rx: %-2.2s En: %-12s\n", + indent,"", + StlLinkWidthToText(pPortInfo->LinkWidthDowngrade.TxActive, tempBuf, sizeof(tempBuf)), + StlLinkWidthToText(pPortInfo->LinkWidthDowngrade.RxActive, tempBuf4, sizeof(tempBuf4)), + StlLinkWidthToText(pPortInfo->LinkWidthDowngrade.Enabled, tempBuf3, sizeof(tempBuf3))); + if (show_mgmt) { + PrintFunc(dest, "%*sLCRC Act: %-8s En: %-8s Mgmt: %-5s\n", + indent, "", + StlPortLtpCrcModeToText(pPortInfo->PortLTPCRCMode.s.Active, tempBuf, sizeof(tempBuf)), + StlPortLtpCrcModeToText(pPortInfo->PortLTPCRCMode.s.Enabled, tempBuf3, sizeof(tempBuf3)), + (pkey == 0xffff)?"True":"False"); + } else { + PrintFunc(dest, "%*sLCRC Act: %-8s En: %-8s\n", + indent, "", + StlPortLtpCrcModeToText(pPortInfo->PortLTPCRCMode.s.Active, tempBuf, sizeof(tempBuf)), + StlPortLtpCrcModeToText(pPortInfo->PortLTPCRCMode.s.Enabled, tempBuf3, sizeof(tempBuf3))); + } + break; + } + + if (show_address) { + PrintFunc(dest, "%*sLID: 0x%08x-0x%08x SM LID: 0x%08x SL: %-2u\n", + indent, "", pPortInfo->LID, + pPortInfo->LID + (1<s1.LMC)-1, + pPortInfo->MasterSMLID, pPortInfo->s2.MasterSMSL); + } + } + if (show_cable && cableInfoData) { + PrintStlCableInfo(dest, indent, cableInfoData, addr, len, pPortInfo->PortPhysConfig.s.PortType, detail, printLineByLine, FALSE); + } + if (show_perf && pPortStatusRsp) { + PrintStlPortStatusRspSummary(dest, indent, pPortStatusRsp, printLineByLine); + } +} + diff --git a/IbPrint/types.c b/IbPrint/types.c new file mode 100644 index 0000000..a6e1841 --- /dev/null +++ b/IbPrint/types.c @@ -0,0 +1,100 @@ +/* BEGIN_ICS_COPYRIGHT7 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT7 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +#include +#include +#include +#include +#include +#include +#include "ibprint.h" + +// TBD: now universally using 0x---:---- for GIDs +// saquery used to use 0x---:0x--- in a few places but +// mostly used 0x----:----- + +void PrintGuid(PrintDest_t *dest, int indent, EUI64 Guid) +{ + PrintFunc(dest, "%*s0x%016"PRIx64"\n", indent, "", Guid); +} + +void PrintLid(PrintDest_t *dest, int indent, IB_LID Lid) +{ + PrintFunc(dest, "%*s0x%04x\n", indent, "", Lid); +} + +void PrintGid(PrintDest_t *dest, int indent, const IB_GID *pGid) +{ + PrintFunc(dest, "%*s0x%016"PRIx64":0x%016"PRIx64"\n", + indent, "", + pGid->AsReg64s.H, + pGid->AsReg64s.L); +} + +void PrintLongMaskBits(PrintDest_t *dest, int indent, const char* prefix, const uint8 *bits, unsigned size) +{ + char buf[80]; + int buflen; + unsigned i; + +#if 0 + // hex dump of field to aid debug + buflen = sprintf(buf, "%s ", prefix); + for (i=0; i 60) { + PrintFunc(dest, "%*s%s\n", indent, "", buf); + buflen=sprintf(buf, " "); // indent list continuation + } + buflen +=sprintf(buf+buflen, "%02x", bits[i]); + } + PrintFunc(dest, "%*s%s\n", indent, "", buf); +#endif + buflen = snprintf(buf, sizeof(buf), "%s", prefix); + for (i=0; i 60) { + PrintFunc(dest, "%*s%s\n", indent, "", buf); + buflen=sprintf(buf, " "); // indent list continuation + } + buflen +=sprintf(buf+buflen, " %3u", i); + } + } + PrintFunc(dest, "%*s%s\n", indent, "", buf); +} + +void PrintSeparator(PrintDest_t *dest) +{ + PrintFunc(dest, "-------------------------------------------------------------------------------\n"); +} + +// TBD - add a hex dump of a buffer, see idebugdump.c for example +// FormatChars in sa.c +// can just do the BYTES format diff --git a/IbaTools/FastFabric/Makefile b/IbaTools/FastFabric/Makefile new file mode 100644 index 0000000..8ff38fc --- /dev/null +++ b/IbaTools/FastFabric/Makefile @@ -0,0 +1,217 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# Makefile for cluster_tools + +# Include Make Control Settings +include $(TL_DIR)/$(PROJ_FILE_DIR)/Makesettings.project + +#=============================================================================# +# Definitions: +#-----------------------------------------------------------------------------# + +# Name of SubProjects +DS_SUBPROJECTS = +# name of executable or downloadable image +EXECUTABLE = #$(BUILDDIR)/FastFabric$(EXE_SUFFIX) +# list of sub directories to build +DIRS = +# C files (.c) +CFILES = \ + # Add more c files here +# C++ files (.cpp) +CCFILES = \ + # Add more cpp files here +# lex files (.lex) +LFILES = \ + # Add more lex files here +# archive library files (basename, $ARFILES will add MOD_LIB_DIR/prefix and suffix) +LIBFILES= +# Windows Resource Files (.rc) +RSCFILES = +# Windows IDL File (.idl) +IDLFILE = +# Windows Linker Module Definitions (.def) file for dll's +DEFFILE = +# targets to build during INCLUDES phase (add public includes here) +INCLUDE_TARGETS = \ + # Add more h hpp files here +# Non-compiled files +MISC_FILES = switches allhosts-sample chassis-sample esm_chassis-sample \ + hosts-sample switches-sample ports-sample osid_wrapper \ + mac_to_dhcp opa_ca_openssl.cnf opa_comp_openssl.cnf \ + opa_ca_openssl.cnf-sample opa_comp_openssl.cnf-sample +# expect files +TCL_SOURCES = chassis_reboot.exp reboot.exp sacache.exp load.exp \ + chassis_upgrade.exp chassis_fmconfig.exp chassis_fmcontrol.exp \ + chassis_fmgetconfig.exp chassis_fmgetsecurityfiles.exp \ + chassis_fmsecurityfiles.exp upgrade.exp configipoib.exp \ + mpiperf.exp mpiperfdeviation.exp ipoibping.exp ff_function.exp \ + switch_upgrade.exp switch_dump.exp switch_reboot.exp \ + switch_info.exp switch_hwvpd.exp switch_ping.exp \ + switch_fwverify.exp switch_capture.exp chassis_configure.exp \ + switch_configure.exp switch_getconfig.exp chassis_getconfig.exp +# all source files +SOURCES = $(CFILES) $(CCFILES) $(LFILES) $(RSCFILES) $(IDLFILE) +# Source files to include in DSP File +DSP_SOURCES = $(INCLUDE_TARGETS) $(SOURCES) $(MISC_FILES) \ + $(RSCFILES) $(DEFFILE) $(MAKEFILE) $(TCL_SOURCES) +# all object files +OBJECTS = $(CFILES:.c=$(OBJ_SUFFIX)) $(CCFILES:.cpp=$(OBJ_SUFFIX)) \ + $(LFILES:.lex=$(OBJ_SUFFIX)) +RSCOBJECTS = $(RSCFILES:.rc=$(RES_SUFFIX)) +# targets to build during LIBS phase +LIB_TARGETS_IMPLIB = +LIB_TARGETS_ARLIB = # $(LIB_PREFIX)ResourceTest$(ARLIB_SUFFIX) +LIB_TARGETS_EXP = $(LIB_TARGETS_IMPLIB:$(ARLIB_SUFFIX)=$(EXP_SUFFIX)) +LIB_TARGETS_MISC = +# targets to build during CMDS phase +CMD_TARGETS_SHLIB = +CMD_TARGETS_EXE = $(EXECUTABLE) +CMD_TARGETS_MISC = opasetupssh opascpall opauploadall opadownloadall opapingall opacmdall opashowallports opacaptureall opahostadmin opachassisadmin opaswitchadmin tcl_proc ff_funcs opafastfabric.conf.def opafastfabric.conf-sample opafabricanalysis opahostsmanalysis opaesmanalysis opachassisanalysis opaallanalysis opafastfabric opaswenableall opaswdisableall opaexpandfile show_counts opacablehealthcron opa-cablehealth +# files to remove during clean phase +CLEAN_TARGETS_MISC = opatest +CLEAN_TARGETS = $(OBJECTS) $(RSCOBJECTS) $(IDL_TARGETS) $(CLEAN_TARGETS_MISC) +# other files to remove during clobber phase +CLOBBER_TARGETS_MISC= +# sub-directory to install to within bin +BIN_SUBDIR = +# sub-directory to install to within include +INCLUDE_SUBDIR = + +# Additional Settings +#CLOCALDEBUG = User defined C debugging compilation flags [Empty] +#CCLOCALDEBUG = User defined C++ debugging compilation flags [Empty] +#CLOCAL = User defined C flags for compiling [Empty] +#CCLOCAL = User defined C++ flags for compiling [Empty] +#BSCLOCAL = User flags for Browse File Builder [Empty] +#DEPENDLOCAL = user defined makedepend flags [Empty] +#LINTLOCAL = User defined lint flags [Empty] +#LOCAL_INCLUDE_DIRS = User include directories to search for C/C++ headers [Empty] +#LDLOCAL = User defined C flags for linking [Empty] +#IMPLIBLOCAL = User flags for Object Lirary Manager [Empty] +#MIDLLOCAL = User flags for IDL compiler [Empty] +#RSCLOCAL = User flags for resource compiler [Empty] +#LOCALDEPLIBS = User libraries to include in dependencies [Empty] +#LOCALLIBS = User libraries to use when linking [Empty] +# (in addition to LOCALDEPLIBS) +#LOCAL_LIB_DIRS = User library directories for libpaths [Empty] + +CLOCAL = $(CPIE) + +# Include Make Rules definitions and rules +include $(TL_DIR)/IbaTools/Makerules.module + +#=============================================================================# +# Overrides: +#-----------------------------------------------------------------------------# +#CCOPT = # C++ optimization flags, default lets build config decide +#COPT = # C optimization flags, default lets build config decide +#SUBSYSTEM = Subsystem to build for (none, console or windows) [none] +# (Windows Only) +#USEMFC = How Windows MFC should be used (none, static, shared, no_mfc) [none] +# (Windows Only) +#=============================================================================# + +#=============================================================================# +# Rules: +#-----------------------------------------------------------------------------# +#$(BUILDDIR)/opafastfabric.conf: opafastfabric.conf.$(BUILD_TARGET_OS).$(IB_STACK) $(BUILDDIR) +opafastfabric.conf.def: opafastfabric.conf.$(BUILD_TARGET_OS).$(IB_STACK) + if [ "$(BUILD_TARGET_OS_VENDOR_VERSION)" = "ES123" ]; then \ + sed -i '/FF_IPOIB_CONNECTED=/s/no/yes/' $<; \ + fi; + $(CP) $< $@ + chmod a+x $@ + +opafastfabric.conf-sample: opafastfabric.conf.$(BUILD_TARGET_OS).$(IB_STACK) + $(CP) $< $@ + chmod a+x $@ + +.SUFFIXES: .pl -sample +%:%.pl + $(RM) $(RMFORCE) $@ + $(CP) $< $@ + +%-sample:% + $(CP) $< $@ + +opaswenableall: opaswdisableall.sh + $(CP) $< $@ + +opafastfabric: opafastfabric.pl + $(SED) -e 's/THIS_IS_THE_IB_STACK_TYPE/$(IB_STACK)/' < $< > $@ + $(CHMOD) a+x $@ + +opahostadmin: opatest + $(CP) $< $@ + +opachassisadmin: opatest + $(CP) $< $@ + +opaswitchadmin: opatest + $(CP) $< $@ + +opacablehealthcron: opacablehealthcron.sh + $(CP) $< $@ + +opa-cablehealth: opacablehealth.cron + $(CP) $< $@ + +switches: ibnodes + $(CP) $< $@ + +osid_wrapper: + echo $(BUILD_TARGET_OS_ID) > osid_wrapper + +# process Sub-directories +include $(TL_DIR)/Makerules/Maketargets.toplevel + +# build cmds and libs +include $(TL_DIR)/Makerules/Maketargets.build + +# install for includes, libs and cmds phases +include $(TL_DIR)/Makerules/Maketargets.install + +# install for stage phase +#include $(TL_DIR)/Makerules/Maketargets.stage +STAGE:: + $(VS)$(STAGE_INSTALL) $(STAGE_INSTALL_DIR_OPT) $(PROJ_STAGE_FASTFABRIC_DIR) opasetupssh opascpall opauploadall opadownloadall opapingall opacmdall opashowallports opacaptureall opahostadmin opachassisadmin opaswitchadmin opafabricanalysis opahostsmanalysis opaesmanalysis opachassisanalysis opaallanalysis opafastfabric opaswenableall opaswdisableall opaexpandfile ff_funcs opafastfabric.conf.def show_counts opacablehealthcron + $(VS)$(STAGE_INSTALL) $(STAGE_INSTALL_DIR_OPT) $(PROJ_STAGE_IBTOOLS_DIR) tcl_proc $(TCL_SOURCES) opafastfabric.conf.def ff_funcs ports hosts allhosts switches chassis esm_chassis osid_wrapper + $(VS)$(STAGE_INSTALL) $(STAGE_INSTALL_DIR_OPT) $(PROJ_STAGE_FASTFABRIC_DIR)/samples allhosts-sample chassis-sample hosts-sample switches-sample ports-sample mac_to_dhcp opafastfabric.conf-sample opa_ca_openssl.cnf-sample opa_comp_openssl.cnf-sample esm_chassis-sample + $(VS)$(STAGE_INSTALL) $(STAGE_INSTALL_DIR_OPT) $(PROJ_STAGE_ETC_DIR)/cron.d opa-cablehealth + +# Unit test execution +#include $(TL_DIR)/Makerules/Maketargets.runtest + +#=============================================================================# + +#=============================================================================# +# DO NOT DELETE THIS LINE -- make depend depends on it. +#=============================================================================# diff --git a/IbaTools/FastFabric/OPTION_MAP b/IbaTools/FastFabric/OPTION_MAP new file mode 100644 index 0000000..0d60348 --- /dev/null +++ b/IbaTools/FastFabric/OPTION_MAP @@ -0,0 +1,291 @@ +List of command line options used in various Fast Fabric tools +--help provide full help text, otherwise brief help of common options +-a show all hosts (opacheckload) +-a clear all performance stats for all ports +-a ip address of node running FE +-a action Action for specified chassis firmware upgrade (push, select, run) +-a 'sguid ..;dguid..' query by a list of port guids +-b Take a baseline without a health check +-b date_time begin time for performance stats interval query +-b {b | b,c | ,c} output a block of data with range of count +-c clobber previous result files before run +-c copy files before run (opaverifyhosts) +-c focus select value +-c crc new CRC enabled (opaportconfig) +-c char concatentation character +-c file config file for error analysis or thresholds +-d display configuration checksum information (opafmconfigcheck) +-d delta flag for port counters query (0 or 1) +-d dir upload or download directory (or UPLOADS_DIR or DOWNLOADS_DIR) + or analysis directory tree (FF_ANALYSIS_DIR) +-d detail detail level for report +-d name query by node name/description or vf name +-d delimiter delimiter output between names and values +-e evaluate health only, default is compare/check mode +-e output mtu & rate as eunm values (opagenvf) +-e flag 32 bit selection flag for clearing port counters +-e element name of XML element to extract, name of header XML element to end +-e date_time end time for performance stats interval query +-f delta flag for portCounters query (0 or 1) +-f value focus select value for getting focus ports +-f hostfile hosts to act on (or HOSTS_FILE) +-g group name for groupInfo query +-g display in line by line format (default is summary) (opainfo) +-g guid query by port guid +-g element name of XML element to generate +-h host name of node running FE +-h element name of XML element in which to enclose generated XML elements +-h hosts hosts to act on (or HOSTS) +-h hfi HFI to use +-i ipoib_suffix suffix to convert ethernet to IPoIB +-i seconds Obtain performance stats over interval seconds +-i vfindex query a specific vfindex +-i level output indent level (0-15) +-j time begin time in opa[pa|fe]query pa queries +-k kill any previous jobs (opaverifyhosts) +-k in XML tags with newlines, keep newlines as is +-k pkey query a specific pkey +-l list files but dont create archive (oparchive) +-l add comments with line numbers after each XML end tag +-l lid query a specific lid +-m access fabric information directly from SMA +-m netmask netmask for configuring IPoIB +-m marker marker for end of cmd output in opacmdall +-m gid query by multicast gid +-m port port in destination device to query +-n numprocs number of processes per node for cabletests, number of hosts + for opacheckload +-n guid query by node guid +-n image_number 64 bit image number +-n mask port mask in hex (ports 31-0) +-o output_file write data to output file +-o directory output directory +-p run command in parallel +-p port port to use +-p ports list of HFI ports to use (or PORTS) +-p guid query by port guid +-q quiet mode +-q time end time in opa[pa|fe]query pa queries +-r size of window for focus ports list +-r recursive download/upload of directories +-r reverse output (least busy hosts) (opachassisanalysis) +-r seconds repeat to keep port down for seconds (opaportconfig) +-r release release to load on servers +-s save history of analysis failures +-s get performance stats for all ports +-s strict check mode (opafmconfigcheck) +-s update/resolved switches switch names using topology xml +-s specify a service level (default 0) +-s guid query by system image guid +-s element name of XML element to suppress extraction +-s file secondary topology CSV input file +-s flag 32 bit select flag for clearing port counters +-s speed new link speeds enabled (opaportconfig) +-t optimized recursive copy of directories using TAR +-t trim leading and trailing whitespace in XML tag contents +-t portsfile list of local hfi ports used (or PORTS_FILE) +-t type query by node type +-t file primary topology CSV input file +-u user user code for host operation (default is root) +-u upload_file destination filename to upload to (opaverifyhosts) +-u gid query by port gid +-v verbose mode +-v show version +-v level verbose level (0-8) +-v debugging mode display debugging and status information (opafmconfigcheck) +-w start window for focus ports +-w mask 32 bit virtual lane select mask +-w width new link widths enabled (opaportconfig) +-x output in xml +-x exclude libs, kernel, module samples (oparchive) +-x snapshot_suffix suffix for snapshot file created (opalinkanalysis) +-x gid specify a source gid for query +-y time image time in opa[pa|fe]query pa queries +-z do not get port info first, clear port attributes (opaportconfig) + +-A skip "active" test (opafindgood) +-A force clear of hw error counters (opacabletest) +-A get PortInfo for down switch ports direct from SMA +-A 'sgid ...;dgid ...' query by list of gids +-B 'sguid ...;dguid ...' query by list of port guids +-C perform operation on chassis (default is hosts) +-C clear error counters, clear performance counters +-D point Destination for trace route +-D detail detail level for opacapture +-E ESM FE +-E esmchassis eSM chassis to act on (or ESM_CHASSIS) +-F chassisfile chassis to act on (or CHASSIS_FILE) +-F focus focus option for report +-G esmchassisfile eSM chassis to act on (or ESM_CHASSIS_FILE) +-G 'gid gid' query by a pair of gids +-H only include permanent hardware data +-H do not output element name header record +-H chassis chassis to act on (or CHASSIS) +-I issue query in legacy Inifiband format +-I install_opts install options for server install +-I fm_bootstate fmconfig and fmcontrol install options +-K do not clean temporary files +-L limit operation to specified focus +-L opaswitches node list file for inband operations on switches (or OPASWITCHES_FILE) +-L lid set PortInfo.LID = lid (opaportconfig) +-L SL query by service level +-L nodefile File with switches in cluster (default /etc/opa/switches) +-M access performance stats directly from PMA +-M inage offset (pa query) +-M host Connected mgmt host from which queries can be initiated +-N omit node and IOC names +-N port number for portCounters query +-N opaswitches node list for inband operations on switches (or OPASWITCHES) +-N nodes list of nodes to execute against +-O image offset (groupInfo, groupConfig, portCounters) +-O override, bypass version checks and force upgrade +-P skip ping of host +-P output hostname/chassis name as line prefix for opacmdall +-P include data persistent across reboots +-P 'guid guid' query by a pair of port guids +-P port_number port number for portCounters query +-P state new port physical state (opaportconfig) +-P file Read command parameters from command file (opaxml) +-P packages packages to load for server or chassis upgrade +-R configure remote hosts only (skips localhost in opasetupssh) +-R skip "running/ssh" test +-R do not attempt to get routes (opadisablehosts, opagenswitches) +-R path filesystem path to search (oparchive) +-Q skip "quarantine" test (opafindgood) +-Q do not include focus description in report +-S securely prompt for chassis admin password +-S start of window for focus ports (should be 0) +-S point source for trace route +-S serviceid query a specific service id +-S state new port state (opaportconfig) +-T product IntelOPA product type to install +-T timelimit timelimit for opacmdall operations and tools using opacmdall +-T file name of topology file input/output file or SSL/TLS parameters XML file +-U only perform connect (for opasetupssh) +-U omit unexpected devices (opalinkanalysis) +-U user controlled counters flag for portCounters query +-U upgrade_opts upgrade options for server upgrade +-V VF name for vfInfo query +-V verbose output +-X file input file to use + +Output Type Descriptions used by Fast Fabric tools - note that individual tools +may not support all output types. + all - comp, nodes, ious, links, extlinks, slowconnlinks, errors reports + bfrctrl - list of buffer control tables + brcomps - Brief summary of all systems and SMs in fabric + brnodes - brief summary of all nodes and SMs in fabric + cableinfo - list of Cable Info records + classportinfo - list of port info records + clearerrorinfo - clears the error info + clearportstatus - clears the port status + clrAllPortCounters - clear all port counters in a fabric + clrPortCounters - clear port counters of a fabric port + clrVfPortCounters - clear VF port counters of a fabric port + conginfo - list of Congestion Info Records + comps - Summary of all systems & SMs in fabric + desc - list of node descriptions/names + errors - summary of links whose errors exceed counts in config file + extislinks - summary of all inter-switch links external to system + extlinks - summary of all links external to system + fabricinfo - summary of fabric devices + focusPorts - get sorted list of ports + freezeImage - creates a freeze frame for image ID + groupConfig - configuration of a PA group + groupInfo - summary of statistics of a PA group + groupList - List of PA groups + getdatacounters - list of data counters + geterrorcounters - list of error counters + geterrorinfo - list of error info + getportstatus - list of port status records + hficongcon - list of HFI Congesting Control Settings + hficongset - list of HFI Congestion Settings + filinks - summary of all FI links + ibnodeinfo - list of IB generic node data records (opasmaquery) + imageInfo - get information about a PA image + inform - list of inform info records + ious - summary of all IO units in fabric + islinks - summary of all inter-switch links + lid - list of lids + lids - summary of all LIDs in fabric + linear - summary of linear fowarding database (FDB) for each switch + linfdb - list of switch linear FDB records + link - list of link records + links - summary of all links + mcast - summary of multicast FDB for each switch + mcfdb - list of switch multicast FDB records + mcmember - list of multicast member records + misconfiglinks - summary of links configured to run slower than supported + misoconnlinks - summary of links connected with mismatched speed potential + moveFreeze - move freeze frame from image ID to new image ID + node - list of node records + nodes - summary of all nodes types and SMs in fabric + nodeaggr - aggregate query returning list of node info and description records + nodedesc - list of node description records + nodeguid - list of node guids + nodeinfo - list of node info records + none - no report (useful if just want to clear stats) + otherports - summary of ports not connected to this fabric + paclassPortInfo - class port info + path - list of path records + pathusage - summary of number of FI to FI paths routed through each switch port + pkey - list of P-Key table records + pmConfig - retrieve PM configuration information + portCounters - port counters for a fabric port + portgroup - list of AR Port Group records + portgroups - summary of adaptive routing port groups for each switch + portgroupfdb - list of AR Port Group FWD records + portguid - list of port guids + portinfo - list of port info records + portusage - summary of ports referenced in linear FDB for each switch + pstateinfo - list of switch port state info records + quarantine - list of quarantined nodes + quarantinednodes - summary of quarantined nodes + ranfdb - list of switch random FDB records + releaseImage - release freeze frame for image ID + renewImage - renew lease for freeze frame for image ID + route - trace route between -S and -D points + saclassPortInfo - class port info + scsc - list of SC to SC mapping table records + scsl - list of SC to SL mapping table records + scvlnt - list of SC to VLnt table records + scvlt - list of SC to VLt table records + service - list of service records + slsc - list of SL to SC mapping table records + slowconfiglinks - summary of links configured to run slower than supported + slowconnlinks - summary of links connected with mismatched speed potential + slowlinks - summary of links running slower than expected + sminfo - list of SM info records + snapshot - output fabric state for later use as snapshot input + swaggr - aggregate query returning list of node info and switch info records + swconglog - list of switch congestion log records + swcongset - list of Switch Congestion Settings + swinfo - list of switch info records + swportcong - list of switch congestion settings + systemguid - list of system image guids + topology - output topology of fabric for later use as topology input + trace - list of trace records + treepathusage - analysis of number of FI to FI paths routed through each switch port for fat tree + validatecreditloops - validate topology configuration of fabric to identify credit loops + validatepgs - validate all port groups in fabric + validateroute - validate all routes in fabric + validateroutes - validate all routes in fabric + verifyall - verifyfis, verifysws, verifysms, verifylinks reports + verifyextislinks - compare fabric external inter-switch links to supplied topology + verifyextlinks - compare fabric links to supplied topology (external links only) + verifyfis - compare fabric FIs to supplied topology + verifyfilinks - compare fabric FI links to supplied topology + verifyislinks - compare fabric inter-switch links to supplied topology + verifylinks - compare fabric links to supplied topology + verifynodes - verifyfis and verifysws reports + verifysms - compare fabric SMs to supplied topology + verifysws - compare fabric switches to supplied topology + vfConfig - configuration for a virtual fabric + vfFocusPorts - get sorted list of virtual fabric ports + vfinfo - summary of vFabric information + vlList - list of virtual fabrics + vfmember - summary of vFabric membership information + vfPortCounters - port counters for a fabric port + vfinfocsv - list of vFabrics in CSV format + vfinfocsv2 - list of vFabrics in CSV format with enums + vlarb - list of VL arbitration table records diff --git a/IbaTools/FastFabric/README b/IbaTools/FastFabric/README new file mode 100644 index 0000000..2f14dd5 --- /dev/null +++ b/IbaTools/FastFabric/README @@ -0,0 +1 @@ +Fast fabric tools - help administer larger fabrics diff --git a/IbaTools/FastFabric/allhosts b/IbaTools/FastFabric/allhosts new file mode 100644 index 0000000..6ea65af --- /dev/null +++ b/IbaTools/FastFabric/allhosts @@ -0,0 +1,11 @@ +# [ICS VERSION STRING: unknown] +# This file lists the TCP/IP names of ALL the hosts in the cluster. +# THIS SHOULD INCLUDE THE NODE RUNNING FASTFABRIC +# +# If Ethernet is being used for the management network, specify +# the hostname corresponding to the ethernet IP address. +# This file will be used by FastFabric to indicate which hosts should be +# operated on by various fastfabric menus and CLI commands. + +include /etc/opa/hosts +# add line below with TCP/IP name of FastFabric host (eg. this host) diff --git a/IbaTools/FastFabric/chassis b/IbaTools/FastFabric/chassis new file mode 100644 index 0000000..55c3392 --- /dev/null +++ b/IbaTools/FastFabric/chassis @@ -0,0 +1,11 @@ +# [ICS VERSION STRING: unknown] +# This file lists the TCP/IP names of the Intel Internally Managed +# Switches in the cluster. +# +# If Ethernet is being used for the management network, specify +# the name corresponding to the ethernet IP address of the chassis. +# This file will be used by FastFabric to indicate which chassis should be +# operated on by various fastfabric menus and CLI commands. +# +# The opagenchassis tool can be used to query the SM and generate a list of +# Internally Managed switches. diff --git a/IbaTools/FastFabric/chassis_configure.exp b/IbaTools/FastFabric/chassis_configure.exp new file mode 100644 index 0000000..f18397f --- /dev/null +++ b/IbaTools/FastFabric/chassis_configure.exp @@ -0,0 +1,234 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] + +#=============================================================================# +# Test Suite Description: +#-----------------------------------------------------------------------------# +## configure +## ------- +## configure all chassis +#=============================================================================# + +# manditory setup +log_user 0; # disable detailed logging to stdout + +# uncomment the following to debug the test +#strace 20 +#log_user 1 +#exp_internal 1 +#cmd_trace on +#strace 4 + +set install_exit_code 0 + +proc suite_setup {} { + # example of conditional setup + #test_execute {load populate} { + #do some installation or configuration stuff + #} +} + +proc case_setup {} { +# setup to do at start of each test case +# Usage: +# pass as argument to start_suite +# Arguments: +# None +# This procedure will be run at the start of every test case +# It provides an opportunity for uniform cleanup/setup for each test case + +} + +proc case_cleanup { failed } { +# cleanup to do after each test case +# Usage: +# pass as argument to start_suite +# Arguments: +# failed - set to 1 if test case failed in which case additional +# information/files may be desired in test_tmp +# set to 0 if test case passed +# This procedure will be run at the end of every test case +# It provides an opportunity for uniform cleanup after each test case + global env + + test_execute {} { + if { $failed } { + global chassis + # could put cleanup here + target_chassis_admin_sh_exit + } + } +} + +array set ch_config_link_crc { +0 "16b" +1 "14b_or_16b" +2 "48b_or_16b" +3 "48b_or_14b_or_16b" +4 "per_lane_or_16b" +5 "per_lane_or_14b_or_16b" +6 "per_lane_or_48b_or_16b" +7 "per_lane_or_48b_or_14b_or_16b" +-1 "no change" +} + +array set ch_config_linkwidths { +1 1X +2 2X +3 1X/2X +4 3X +5 1X/3X +6 2X/3X +7 1X/2X/3X +8 4X +9 1X/4X +10 2X/4X +11 1X/2X/4X +12 3X/4X +13 1X/3X/4X +14 2X/3X/4X +15 1X/2X/3X/4X +0 "no change" +} + +proc ch_get_array_entry { arrayname key } { + +variable $arrayname + +upvar #0 $arrayname myarray + +if {![info exists myarray($key)]} { + return "Invalid Input: $key" +} else { + return $myarray($key) +} + +} + +proc ch_get_ip { ip } { + +if { [string equal "$ip" "0.0.0.0"] == 0 } { + return $ip +} else { + return "not being set" +} + +} + +proc ch_get_syslog_facility { facility } { + +if { [string equal "$facility" "-1"] == 0 } { + return $facility +} else { + return "not being set" +} + +} + +proc ch_get_syslog_port { port } { + +if { [string equal "$port" "-1"] == 0 } { + return $port +} else { + return "not being set" +} + +} + +proc ch_get_tzoffset { offset } { + +if { [string equal "$offset" "100"] == 0 } { + return $offset +} else { + return "not being set" +} + +} + +proc ch_get_dst { start end } { + +if { [string equal "$start" "0 0 0"] == 0 } { + return "<$start>/<$end>" +} else { + return "not being set" +} + +} + +proc ch_get_setname { setname } { + +if { [string equal "$setname" "y"] == 0 } { + return "not being set" +} else { + return "being set to match chassis Ethernet name" +} + +} + +test_suite "configure" "configure" "configure all chassis: +SYSLOG_SERVER: [ch_get_ip $env(SYSLOG_SERVER)] +SYSLOG_PORT: [ch_get_syslog_port $env(SYSLOG_PORT)] +SYSLOG_FACILITY: [ch_get_syslog_facility $env(SYSLOG_FACILITY)] +NTP_SERVER: [ch_get_ip $env(NTP_SERVER)] +TZ_OFFSET: [ch_get_tzoffset $env(TZ_OFFSET)] +DST START/END: [ch_get_dst $env(DST_START) $env(DST_END)] +LINKWIDTH: [ch_get_array_entry ch_config_linkwidths $env(LINKWIDTH_SETTING)] +NODEDESC: [ch_get_setname $env(SET_NAME)] +LINKCRCMODE: [ch_get_array_entry ch_config_link_crc $env(LINKCRCMODE)] +File: /usr/lib/opa/tools/chassis_configure.exp" suite_setup noop { + global chassis + + # Global Initializations for Test Suite: + # -------------------------------------- + + # ADD ANY GLOBAL INITIALIZATION HERE, SUCH AS: + # set env(MY_ENV_VAR) value + # also validate the environment + # if the environment is bad call fail_suite "information" abort_now + # abort_now should be 0 if it is safe to proceed and simply ignore all + # test_case calls. it should be 1 if that is not possible. + + # Procedures used to support Test Suite: + # -------------------------------------- + + # The actual test cases: + # ---------------------- + + parallel chassis $env(CFG_CHASSIS) { + set chassis [chassis_strip_slots "$chassis"] + local_sh + send_unix_cmd "grep $chassis $env(CFG_CFGTEMPDIR)/.chassisSetup.out | grep IP_Addr" + set out [expect_list 60 { ": [0-9.]+" } ] + regexp {([0-9.]+)} $out c chassisIP + local_sh_exit + test_case_chassis_configure $chassis $chassisIP + } +} diff --git a/IbaTools/FastFabric/chassis_fmconfig.exp b/IbaTools/FastFabric/chassis_fmconfig.exp new file mode 100644 index 0000000..9ec04cc --- /dev/null +++ b/IbaTools/FastFabric/chassis_fmconfig.exp @@ -0,0 +1,128 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] + +#=============================================================================# +# Test Suite Description: +#-----------------------------------------------------------------------------# +## reboot +## ------- +## reboot all chassis +#=============================================================================# + +# manditory setup +log_user 0; # disable detailed logging to stdout + +# uncomment the following to debug the test +#strace 20 +#log_user 1 +#exp_internal 1 +#cmd_trace on +#strace 4 + +set install_exit_code 0 + +proc suite_setup {} { + # example of conditional setup + #test_execute {load populate} { + #do some installation or configuration stuff + #} +} + +proc case_setup {} { +# setup to do at start of each test case +# Usage: +# pass as argument to start_suite +# Arguments: +# None +# This procedure will be run at the start of every test case +# It provides an opportunity for uniform cleanup/setup for each test case + +} + +proc case_cleanup { failed } { +# cleanup to do after each test case +# Usage: +# pass as argument to start_suite +# Arguments: +# failed - set to 1 if test case failed in which case additional +# information/files may be desired in test_tmp +# set to 0 if test case passed +# This procedure will be run at the end of every test case +# It provides an opportunity for uniform cleanup after each test case + global env + + test_execute {} { + if { $failed } { + # could put cleanup here + } + } +} + +test_suite "fmconfig" "update FM config" "update all chassis FM config +FM config File: $env(CFG_FMFILE) +Action: $env(CFG_FWACTION) +Bootstate: $env(CFG_INSTALL_OPTIONS) +File: /usr/lib/opa/tools/chassis_fmconfig.exp" suite_setup noop { + global env + + # Global Initializations for Test Suite: + # -------------------------------------- + + # ADD ANY GLOBAL INITIALIZATION HERE, SUCH AS: + # set env(MY_ENV_VAR) value + # also validate the environment + # if the environment is bad call fail_suite "information" abort_now + # abort_now should be 0 if it is safe to proceed and simply ignore all + # test_case calls. it should be 1 if that is not possible. + + # Procedures used to support Test Suite: + # -------------------------------------- + + # The actual test cases: + # ---------------------- + + if { [ test_case "check" "check config file" "check config to be pushed to all chassis +Config File: $env(CFG_FMFILE) +File: /usr/lib/opa/tools/chassis_fmconfig.exp" case_setup case_cleanup { + puts "" + set config_file $env(CFG_FMFILE) + check_esm_config "$config_file" + } ] } { + fail_suite "Invalid Config File" + } + + # We only get here if the config file supplied is valid + parallel chassis $env(CFG_CHASSIS) { + set chassis [chassis_strip_slots "$chassis"] + + test_case_push_esm_config "$chassis" "$env(CFG_FMFILE)" "$env(CFG_FWACTION)" "$env(CFG_INSTALL_OPTIONS)" + } +} diff --git a/IbaTools/FastFabric/chassis_fmcontrol.exp b/IbaTools/FastFabric/chassis_fmcontrol.exp new file mode 100644 index 0000000..477953a --- /dev/null +++ b/IbaTools/FastFabric/chassis_fmcontrol.exp @@ -0,0 +1,124 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] + +#=============================================================================# +# Test Suite Description: +#-----------------------------------------------------------------------------# +## reboot +## ------- +## reboot all chassis +#=============================================================================# + +# manditory setup +log_user 0; # disable detailed logging to stdout + +# uncomment the following to debug the test +#strace 20 +#log_user 1 +#exp_internal 1 +#cmd_trace on +#strace 4 + +set install_exit_code 0 + +proc suite_setup {} { + # example of conditional setup + #test_execute {load populate} { + #do some installation or configuration stuff + #} +} + +proc case_setup {} { +# setup to do at start of each test case +# Usage: +# pass as argument to start_suite +# Arguments: +# None +# This procedure will be run at the start of every test case +# It provides an opportunity for uniform cleanup/setup for each test case + +} + +proc case_cleanup { failed } { +# cleanup to do after each test case +# Usage: +# pass as argument to start_suite +# Arguments: +# failed - set to 1 if test case failed in which case additional +# information/files may be desired in test_tmp +# set to 0 if test case passed +# This procedure will be run at the end of every test case +# It provides an opportunity for uniform cleanup after each test case + global env + + test_execute {} { + if { $failed } { + # could put cleanup here + } + } +} + +test_suite "fmcontrol" "FM control" "control FM on all chassis +Action: $env(CFG_FWACTION) +Bootstate: $env(CFG_INSTALL_OPTIONS) +File: /usr/lib/opa/tools/chassis_fmcontrol.exp" suite_setup noop { + global env + + # Global Initializations for Test Suite: + # -------------------------------------- + + # ADD ANY GLOBAL INITIALIZATION HERE, SUCH AS: + # set env(MY_ENV_VAR) value + # also validate the environment + # if the environment is bad call fail_suite "information" abort_now + # abort_now should be 0 if it is safe to proceed and simply ignore all + # test_case calls. it should be 1 if that is not possible. + + # Procedures used to support Test Suite: + # -------------------------------------- + + # The actual test cases: + # ---------------------- + + # We only get here if the config file supplied is valid + parallel chassis $env(CFG_CHASSIS) { + set chassis [chassis_strip_slots "$chassis"] + + test_case "$chassis.fmcontrol" "control $chassis FM" "control FM on $chassis +Action: $env(CFG_FWACTION) +Bootstate: $env(CFG_INSTALL_OPTIONS) +File: tools/chassis_fmcontrol.exp" noop noop { + upvar chassis chassis + + push_esm_config "$chassis" "" "$env(CFG_FWACTION)" "$env(CFG_INSTALL_OPTIONS)" + } + } +} diff --git a/IbaTools/FastFabric/chassis_fmgetconfig.exp b/IbaTools/FastFabric/chassis_fmgetconfig.exp new file mode 100644 index 0000000..2e61cde --- /dev/null +++ b/IbaTools/FastFabric/chassis_fmgetconfig.exp @@ -0,0 +1,115 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] + +#=============================================================================# +# Test Suite Description: +#-----------------------------------------------------------------------------# +## reboot +## ------- +## reboot all chassis +#=============================================================================# + +# manditory setup +log_user 0; # disable detailed logging to stdout + +# uncomment the following to debug the test +#strace 20 +#log_user 1 +#exp_internal 1 +#cmd_trace on +#strace 4 + +set install_exit_code 0 + +proc suite_setup {} { + # example of conditional setup + #test_execute {load populate} { + #do some installation or configuration stuff + #} +} + +proc case_setup {} { +# setup to do at start of each test case +# Usage: +# pass as argument to start_suite +# Arguments: +# None +# This procedure will be run at the start of every test case +# It provides an opportunity for uniform cleanup/setup for each test case + +} + +proc case_cleanup { failed } { +# cleanup to do after each test case +# Usage: +# pass as argument to start_suite +# Arguments: +# failed - set to 1 if test case failed in which case additional +# information/files may be desired in test_tmp +# set to 0 if test case passed +# This procedure will be run at the end of every test case +# It provides an opportunity for uniform cleanup after each test case + global env + + test_execute {} { + if { $failed } { + # could put cleanup here + } + } +} + +test_suite "fmgetconfig" "get FM config" "get all chassis FM config file +Destination Filename: $env(CFG_FMFILE) +File: /usr/lib/opa/tools/chassis_fmgetconfig.exp" suite_setup noop { + global env + + # Global Initializations for Test Suite: + # -------------------------------------- + + # ADD ANY GLOBAL INITIALIZATION HERE, SUCH AS: + # set env(MY_ENV_VAR) value + # also validate the environment + # if the environment is bad call fail_suite "information" abort_now + # abort_now should be 0 if it is safe to proceed and simply ignore all + # test_case calls. it should be 1 if that is not possible. + + # Procedures used to support Test Suite: + # -------------------------------------- + + # The actual test cases: + # ---------------------- + + parallel chassis $env(CFG_CHASSIS) { + set chassis [chassis_strip_slots "$chassis"] + + test_case_get_esm_config "$chassis" "$env(UPLOADS_DIR)/$chassis/$env(CFG_FMFILE)" + } +} diff --git a/IbaTools/FastFabric/chassis_fmgetsecurityfiles.exp b/IbaTools/FastFabric/chassis_fmgetsecurityfiles.exp new file mode 100644 index 0000000..d31e055 --- /dev/null +++ b/IbaTools/FastFabric/chassis_fmgetsecurityfiles.exp @@ -0,0 +1,117 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] + +#=============================================================================# +# Test Suite Description: +#-----------------------------------------------------------------------------# +## reboot +## ------- +## reboot all chassis +#=============================================================================# + +# manditory setup +log_user 0; # disable detailed logging to stdout + +# uncomment the following to debug the test +#strace 20 +#log_user 1 +#exp_internal 1 +#cmd_trace on +#strace 4 + +set install_exit_code 0 + +proc suite_setup {} { + # example of conditional setup + #test_execute {load populate} { + #do some installation or configuration stuff + #} +} + +proc case_setup {} { +# setup to do at start of each test case +# Usage: +# pass as argument to start_suite +# Arguments: +# None +# This procedure will be run at the start of every test case +# It provides an opportunity for uniform cleanup/setup for each test case + +} + +proc case_cleanup { failed } { +# cleanup to do after each test case +# Usage: +# pass as argument to start_suite +# Arguments: +# failed - set to 1 if test case failed in which case additional +# information/files may be desired in test_tmp +# set to 0 if test case passed +# This procedure will be run at the end of every test case +# It provides an opportunity for uniform cleanup after each test case + global env + + test_execute {} { + if { $failed } { + # could put cleanup here + } + } +} + + +test_suite "fmgetsecurityfiles" "get FM security files" "get chassis FM security files +Security Files: $env(CFG_SECFILE) +File: /usr/lib/opa/tools/chassis_fmgetsecurityfiles.exp" suite_setup noop { + global env + + # Global Initializations for Test Suite: + # -------------------------------------- + + # ADD ANY GLOBAL INITIALIZATION HERE, SUCH AS: + # set env(MY_ENV_VAR) value + # also validate the environment + # if the environment is bad call fail_suite "information" abort_now + # abort_now should be 0 if it is safe to proceed and simply ignore all + # test_case calls. it should be 1 if that is not possible. + + # Procedures used to support Test Suite: + # -------------------------------------- + + # The actual test cases: + # ---------------------- + + parallel chassis $env(CFG_CHASSIS) { + set chassis [chassis_strip_slots "$chassis"] + + test_case_get_esm_security_files "$chassis" "$env(CFG_SECFILE)" "$env(UPLOADS_DIR)/$chassis/" + } +} + diff --git a/IbaTools/FastFabric/chassis_fmsecurityfiles.exp b/IbaTools/FastFabric/chassis_fmsecurityfiles.exp new file mode 100644 index 0000000..5c2a45d --- /dev/null +++ b/IbaTools/FastFabric/chassis_fmsecurityfiles.exp @@ -0,0 +1,148 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] + +#=============================================================================# +# Test Suite Description: +#-----------------------------------------------------------------------------# +## reboot +## ------- +## reboot all chassis +#=============================================================================# + +# manditory setup +log_user 0; # disable detailed logging to stdout + +# uncomment the following to debug the test +#strace 20 +#log_user 1 +#exp_internal 1 +#cmd_trace on +#strace 4 + +set install_exit_code 0 + +proc suite_setup {} { + # example of conditional setup + #test_execute {load populate} { + #do some installation or configuration stuff + #} +} + +proc case_setup {} { +# setup to do at start of each test case +# Usage: +# pass as argument to start_suite +# Arguments: +# None +# This procedure will be run at the start of every test case +# It provides an opportunity for uniform cleanup/setup for each test case + +} + +proc case_cleanup { failed } { +# cleanup to do after each test case +# Usage: +# pass as argument to start_suite +# Arguments: +# failed - set to 1 if test case failed in which case additional +# information/files may be desired in test_tmp +# set to 0 if test case passed +# This procedure will be run at the end of every test case +# It provides an opportunity for uniform cleanup after each test case + global env + + test_execute {} { + if { $failed } { + # could put cleanup here + } + } +} + +test_suite "upgrade" "upgrade FM security files" "upgrade all chassis +Security Files: $env(CFG_SECFILES) +Action: $env(CFG_SECACTION) +File: /usr/lib/opa/tools/chassis_fmsecurityfiles.exp" suite_setup noop { + global env + + # Global Initializations for Test Suite: + # -------------------------------------- + + # ADD ANY GLOBAL INITIALIZATION HERE, SUCH AS: + # set env(MY_ENV_VAR) value + # also validate the environment + # if the environment is bad call fail_suite "information" abort_now + # abort_now should be 0 if it is safe to proceed and simply ignore all + # test_case calls. it should be 1 if that is not possible. + + # Procedures used to support Test Suite: + # -------------------------------------- + + # The actual test cases: + # ---------------------- + + if { [ test_case "check" "check FM security files" "check FM security files to be pushed to all chassis +Firmware Files: $env(CFG_SECFILES) +File: /usr/lib/opa/tools/chassis_fmsecurityfiles.exp" case_setup case_cleanup { + upvar num_secfiles num_secfiles + upvar sec_files sec_files + + set sec_files "" + + set num_secfiles [llength $env(CFG_SECFILES)] + + puts "" + foreach sec_file $env(CFG_SECFILES) { + puts "$sec_file" + # No verification of .pem files available for now, so just + # print file name + + lappend sec_files "$sec_file" + } + } ] } { + fail_suite "Invalid FM Security Files" + } + + # We only get here if all the security files supplied are valid + parallel chassis $env(CFG_CHASSIS) { + set slots [chassis_get_slots "$chassis"] + set chassis [chassis_strip_slots "$chassis"] + + for { set i 0 } { $i < $num_secfiles } { incr i } { + set sec_file [lindex $sec_files $i] + + test_case_push_chassis_security_file "$chassis" "$sec_file" "push" "$slots" + } + + if { ! [ string equal "$env(CFG_SECACTION)" "push"] } { + test_case_push_chassis_security_file "$chassis" "" "$env(CFG_SECACTION)" "$slots" + } + } +} diff --git a/IbaTools/FastFabric/chassis_getconfig.exp b/IbaTools/FastFabric/chassis_getconfig.exp new file mode 100644 index 0000000..7454afc --- /dev/null +++ b/IbaTools/FastFabric/chassis_getconfig.exp @@ -0,0 +1,130 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: @(#) ./fastfabric/tools/chassis_getconfig.exp 6_1_0_0_39 [02/01/11 09:25] + +#=============================================================================# +# Test Suite Description: +#-----------------------------------------------------------------------------# +## getconfig +## ------- +## getconfig all chassis +#=============================================================================# + +# manditory setup +log_user 0; # disable detailed logging to stdout + +# uncomment the following to debug the test +#strace 20 +#log_user 1 +#exp_internal 1 +#cmd_trace on +#strace 4 + +set install_exit_code 0 + +proc suite_setup {} { + # example of conditional setup + #test_execute {load populate} { + #do some installation or configuration stuff + #} +} + +proc case_setup {} { +# setup to do at start of each test case +# Usage: +# pass as argument to start_suite +# Arguments: +# None +# This procedure will be run at the start of every test case +# It provides an opportunity for uniform cleanup/setup for each test case + +} + +proc case_cleanup { failed } { +# cleanup to do after each test case +# Usage: +# pass as argument to start_suite +# Arguments: +# failed - set to 1 if test case failed in which case additional +# information/files may be desired in test_tmp +# set to 0 if test case passed +# This procedure will be run at the end of every test case +# It provides an opportunity for uniform cleanup after each test case + global env + + test_execute {} { + if { $failed } { + global chassis + # could put cleanup here + target_chassis_admin_sh_exit + } + } +} + +test_suite "getconfig" "getconfig" "getconfig all chassis +File: /usr/lib/opa/tools/chassis_getconfig.exp" suite_setup noop { + global chassis + + # Global Initializations for Test Suite: + # -------------------------------------- + + # ADD ANY GLOBAL INITIALIZATION HERE, SUCH AS: + # set env(MY_ENV_VAR) value + # also validate the environment + # if the environment is bad call fail_suite "information" abort_now + # abort_now should be 0 if it is safe to proceed and simply ignore all + # test_case calls. it should be 1 if that is not possible. + + # Procedures used to support Test Suite: + # -------------------------------------- + + # The actual test cases: + # ---------------------- + + # we will get config information to this temp file + set mypid [pid] + set fname [ exec mktemp --tmpdir "ch_getconfig_XXXX" ] + set fd [ open "$fname" {CREAT WRONLY APPEND TRUNC} ] + + parallel chassis $env(CFG_CHASSIS) { + fconfigure $fd -buffering line + set chassis [chassis_strip_slots "$chassis"] + test_case_chassis_getconfig $chassis "$fd" + } + + # omit some lines, and provide a summary of how many switches have each + # type of config + catch { close $fd } + catch { + set summary [exec cat $fname | egrep -v {^[[:space:]]*$|Node Description} | /usr/lib/opa/tools/show_counts 2>@1 ] + show_message "Summary:\ncount - configuration\n$summary" + } + catch { exec rm -f $fname } +} diff --git a/IbaTools/FastFabric/chassis_reboot.exp b/IbaTools/FastFabric/chassis_reboot.exp new file mode 100644 index 0000000..b5f1f39 --- /dev/null +++ b/IbaTools/FastFabric/chassis_reboot.exp @@ -0,0 +1,114 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] + +#=============================================================================# +# Test Suite Description: +#-----------------------------------------------------------------------------# +## reboot +## ------- +## reboot all chassis +#=============================================================================# + +# manditory setup +log_user 0; # disable detailed logging to stdout + +# uncomment the following to debug the test +#strace 20 +#log_user 1 +#exp_internal 1 +#cmd_trace on +#strace 4 + +set install_exit_code 0 + +proc suite_setup {} { + # example of conditional setup + #test_execute {load populate} { + #do some installation or configuration stuff + #} +} + +proc case_setup {} { +# setup to do at start of each test case +# Usage: +# pass as argument to start_suite +# Arguments: +# None +# This procedure will be run at the start of every test case +# It provides an opportunity for uniform cleanup/setup for each test case + +} + +proc case_cleanup { failed } { +# cleanup to do after each test case +# Usage: +# pass as argument to start_suite +# Arguments: +# failed - set to 1 if test case failed in which case additional +# information/files may be desired in test_tmp +# set to 0 if test case passed +# This procedure will be run at the end of every test case +# It provides an opportunity for uniform cleanup after each test case + global env + + test_execute {} { + if { $failed } { + global chassis + # could put cleanup here + } + } +} + +test_suite "reboot" "reboot" "reboot all chassis +File: /usr/lib/opa/tools/chassis_reboot.exp" suite_setup noop { + global chassis + + # Global Initializations for Test Suite: + # -------------------------------------- + + # ADD ANY GLOBAL INITIALIZATION HERE, SUCH AS: + # set env(MY_ENV_VAR) value + # also validate the environment + # if the environment is bad call fail_suite "information" abort_now + # abort_now should be 0 if it is safe to proceed and simply ignore all + # test_case calls. it should be 1 if that is not possible. + + # Procedures used to support Test Suite: + # -------------------------------------- + + # The actual test cases: + # ---------------------- + + parallel chassis $env(CFG_CHASSIS) { + set chassis [chassis_strip_slots "$chassis"] + test_case_chassis_reboot $chassis + } +} diff --git a/IbaTools/FastFabric/chassis_upgrade.exp b/IbaTools/FastFabric/chassis_upgrade.exp new file mode 100644 index 0000000..b2aa797 --- /dev/null +++ b/IbaTools/FastFabric/chassis_upgrade.exp @@ -0,0 +1,153 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] + +#=============================================================================# +# Test Suite Description: +#-----------------------------------------------------------------------------# +## reboot +## ------- +## reboot all chassis +#=============================================================================# + +# manditory setup +log_user 0; # disable detailed logging to stdout + +# uncomment the following to debug the test +#strace 20 +#log_user 1 +#exp_internal 1 +#cmd_trace on +#strace 4 + +set install_exit_code 0 + +proc suite_setup {} { + # example of conditional setup + #test_execute {load populate} { + #do some installation or configuration stuff + #} +} + +proc case_setup {} { +# setup to do at start of each test case +# Usage: +# pass as argument to start_suite +# Arguments: +# None +# This procedure will be run at the start of every test case +# It provides an opportunity for uniform cleanup/setup for each test case + +} + +proc case_cleanup { failed } { +# cleanup to do after each test case +# Usage: +# pass as argument to start_suite +# Arguments: +# failed - set to 1 if test case failed in which case additional +# information/files may be desired in test_tmp +# set to 0 if test case passed +# This procedure will be run at the end of every test case +# It provides an opportunity for uniform cleanup after each test case + global env + + test_execute {} { + if { $failed } { + # could put cleanup here + } + } +} + +test_suite "upgrade" "upgrade firmware" "upgrade all chassis +Firmware Files: $env(CFG_FWFILES) +Action: $env(CFG_FWACTION) +File: /usr/lib/opa/tools/chassis_upgrade.exp" suite_setup noop { + global env + + # Global Initializations for Test Suite: + # -------------------------------------- + + # ADD ANY GLOBAL INITIALIZATION HERE, SUCH AS: + # set env(MY_ENV_VAR) value + # also validate the environment + # if the environment is bad call fail_suite "information" abort_now + # abort_now should be 0 if it is safe to proceed and simply ignore all + # test_case calls. it should be 1 if that is not possible. + + # Procedures used to support Test Suite: + # -------------------------------------- + + # The actual test cases: + # ---------------------- + + if { [ test_case "check" "check firmware files" "check firmware to be pushed to all chassis +Firmware Files: $env(CFG_FWFILES) +File: /usr/lib/opa/tools/chassis_upgrade.exp" case_setup case_cleanup { + upvar num_fw num_fw + upvar fw_files fw_files + upvar fw_versions fw_versions + upvar fw_card_types fw_card_types + + set fw_files "" + set fw_versions "" + set fw_card_types "" + + set num_fw [llength $env(CFG_FWFILES)] + + puts "" + foreach fw_file $env(CFG_FWFILES) { + puts "$fw_file" + set fw_version [get_file_firmware_version $fw_file] + set card_type [get_file_firmware_type $fw_file] + puts "\tVersion: $fw_version\tType: $card_type" + + lappend fw_files "$fw_file" + lappend fw_versions "$fw_version" + lappend fw_card_types "$card_type" + } + } ] } { + fail_suite "Invalid Firmware Files" + } + + # We only get here if all the firmware files supplied are valid + parallel chassis $env(CFG_CHASSIS) { + set slots [chassis_get_slots "$chassis"] + set chassis [chassis_strip_slots "$chassis"] + + for { set i 0 } { $i < $num_fw } { incr i } { + set fw_file [lindex $fw_files $i] + set fw_version [lindex $fw_versions $i] + set card_type [lindex $fw_card_types $i] + + test_case_push_chassis_firmware "$chassis" "$fw_file" "$fw_version" "$card_type" "$env(CFG_FWACTION)" "$slots" + } + } +} diff --git a/IbaTools/FastFabric/configipoib.exp b/IbaTools/FastFabric/configipoib.exp new file mode 100644 index 0000000..1067311 --- /dev/null +++ b/IbaTools/FastFabric/configipoib.exp @@ -0,0 +1,228 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: @(#) ./fastfabric/tools/configipoib.exp 0mwhe.20150409 [04/09/15 10:26] + +source "/usr/lib/opa/tools/ff_function.exp" + +#=============================================================================# +# Test Suite Description: +#-----------------------------------------------------------------------------# +## configipoib +## ------- +## configure IPoIB ifcfg file based on /etc/hosts +#=============================================================================# + +# manditory setup +log_user 0; # disable detailed logging to stdout + +# uncomment the following to debug the test +#strace 20 +#log_user 1 +#exp_internal 1 +#cmd_trace on +#strace 4 + +set install_exit_code 0 + +proc suite_setup {} { + # example of conditional setup + #test_execute {load populate} { + #do some installation or configuration stuff + #} +} + +proc case_setup {} { +# setup to do at start of each test case +# Usage: +# pass as argument to start_suite +# Arguments: +# None +# This procedure will be run at the start of every test case +# It provides an opportunity for uniform cleanup/setup for each test case + +} + +proc case_cleanup { failed } { +# cleanup to do after each test case +# Usage: +# pass as argument to start_suite +# Arguments: +# failed - set to 1 if test case failed in which case additional +# information/files may be desired in test_tmp +# set to 0 if test case passed +# This procedure will be run at the end of every test case +# It provides an opportunity for uniform cleanup after each test case + global env + + test_execute {} { + if { $failed } { + global host + # could put cleanup here + } + } +} + +test_suite "configipoib" "configure IPoIB" "Configure IPoIB based on /etc/hosts +creates ifcfg-ib file +File: /usr/lib/opa/tools/configipoib.exp" suite_setup noop { + global host + + # Global Initializations for Test Suite: + # -------------------------------------- + + # ADD ANY GLOBAL INITIALIZATION HERE, SUCH AS: + # set env(MY_ENV_VAR) value + # also validate the environment + # if the environment is bad call fail_suite "information" abort_now + # abort_now should be 0 if it is safe to proceed and simply ignore all + # test_case calls. it should be 1 if that is not possible. + + # Procedures used to support Test Suite: + # -------------------------------------- + + # The actual test cases: + # ---------------------- + + if { [ info exists env(FF_IPOIB_CONFIG) ] && "$env(FF_IPOIB_CONFIG)" != "" } { + set mode $env(FF_IPOIB_CONFIG) + } else { + set mode "static" + log_message "FF_IPOIB_CONFIG not found /etc/opa/opafastfabric.conf Defaulting to static" + } + + + if { ![ string equal "$mode" "auto"] && ![ string equal "$mode" "static"] && ![string equal "$mode" "dhcp"] } { + fail_test "Bad value FF_IPOIB_CONFIG=$mode in /etc/opa/opafastfabric.conf it should be one of auto/static/dhcp " + } + + # Suites are structured so that if all tests are run, at completion + # host is left running the set of drivers specified in the config file + parallel host $env(CFG_HOSTS) { + set ipoib_name "[ ff_host_to_ipoib $host]" + set ipoib_base_dev_num "[ ff_ipoib_base_dev_num $host]" + + test_case "$host.config" "config ipoib on $host" "Configure $host IPoIB +File: /usr/lib/opa/tools/configipoib.exp" case_setup case_cleanup { + global env + upvar host host + upvar number number + upvar disk disk + upvar mode mode + upvar ipoib_name ipoib_name + upvar ipoib_base_dev_num ipoib_base_dev_num + upvar inic_name inic_name + + # These two variables have the same purpose but different enumerated + # values. ipoib_mode is used for SLES ipoib_cm is used for RHEL. + set ipoib_mode "datagram" + set ipoib_cm "no" + set ipoib_mtu "" + + target_root_sh $host + + if { [ string equal "$mode" "auto"] || [ string equal "$mode" "static"] } { + # try resolver 1st, then revert to lookup in /etc/hosts + unix_cmd 60 "" "tmp=`host $ipoib_name 2>/dev/null|sed -e 's/^.*has address //'|grep '^\[0-9\]'` +if \[ \"\$tmp\" = '' \] +then + tmp=`egrep '\[\[:space:\]\]$ipoib_name\[\[:space:\]\]|\[\[:space:\]\]$ipoib_name\$' /etc/hosts|grep -v localhost|tr ' ' '\\t'|cut -f1` +fi" + if { [ string equal "$mode" "auto"] } { + unix_cmd 60 "" {[ "$tmp" = '' ]} + if { 0 == [ get_exit_status 60 ] } { + set mode "dhcp" + } else { + set mode "static" + } + } + } + + if { [ info exists env(CFG_IPOIB_CONNECTED) ] && [ string equal -nocase "$env(CFG_IPOIB_CONNECTED)" "yes" ]} { + set ipoib_mode "connected" + set ipoib_cm "yes" + set ipoib_mtu "\nMTU=65520" + } + + if { [ string equal "$mode" "static"] } { + # verify we have found an IP address for $host's $ipoib_name + unix_cmd 60 0 {if [ -x /usr/lib/opa/tools/opaipcalc ]; then opaipcalc=/usr/lib/opa/tools/opaipcalc; else opaipcalc=/sbin/opaipcalc; fi } + unix_cmd 60 0 "echo \"IPADDR=\$tmp\"; \[ \"\$tmp\" != '' \]" + if { [ info exists env(CFG_IPOIB_NETMASK) ] && "$env(CFG_IPOIB_NETMASK)" != "" } { + unix_cmd 60 0 "mask='$env(CFG_IPOIB_NETMASK)'" + } else { + unix_cmd 60 0 "mask=`\$opaipcalc --netmask \$tmp`" + unix_cmd 60 0 "mask=`echo \"\$mask\"|sed -e 's/NETMASK=//'`" + } + unix_cmd 60 0 "echo \"NETMASK=\$mask\"; \[ \"\$mask\" != '' \]" + unix_cmd 60 0 "network=`\$opaipcalc --network \$tmp \$mask`" + unix_cmd 60 0 "echo \"\$network\"; \[ \"\$network\" != '' \]" + unix_cmd 60 0 "broadcast=`\$opaipcalc --broadcast \$tmp \$mask`" + unix_cmd 60 0 "echo \"\$broadcast\"; \[ \"\$broadcast\" != '' \]" + unix_cmd 60 0 "echo \"IPOIB_MODE=\$ipoib_mode\"" + unix_cmd 60 0 "bproto_ip_mask_info=\"BOOTPROTO=static +IPADDR=\$tmp +NETMASK=\$mask +\$network +\$broadcast\"" + + } elseif { [ string equal "$mode" "dhcp"] } { + unix_cmd 60 0 "bproto_ip_mask_info=\"BOOTPROTO=dhcp\"" + } else { + + fail_test "Bad value FF_IPOIB_CONFIG=$mode in /etc/opa/opafastfabric.conf it should be one of auto/static/dhcp " + } + + set os_type [ exec uname -s ] + + send_unix_cmd "if \[ -d /etc/sysconfig/network-scripts \]; then +cat > /etc/sysconfig/network-scripts/ifcfg-ib$ipoib_base_dev_num < /etc/sysconfig/network/ifcfg-ib$ipoib_base_dev_num <&2 + fi +} + +# filter out blank and comment lines +ff_filter_comments() +{ + egrep -v '^[[:space:]]*#'|egrep -v '^[[:space:]]*$' +} + +expand_file() +{ + # $1 is command name + # $2 is file name + # outputs list of all non-comment lines in file + # expands any included files + local file + + # tabs and spaces are permitted as field splitters for include lines + # however spaces are permitted in other lines (to handle node descriptions) + # and tabs must be used for any comments on non-include lines + # any line whose 1st non-whitespace character is # is a comment + cat "$2"|ff_filter_comments|while read line + do + f1=$(expr "$line" : '\([^ ]*\).*') + if [ x"$f1" = x"include" ] + then + f2=$(expr "$line" : "[^ ]*[ ][ ]*\([^ ]*\).*") + file=`resolve_file "$1" "$f2"` + if [ "$file" != "" ] + then + expand_file "$1" "$file" + fi + else + echo "$line"|cut -f1 + fi + done +} + +check_host_args() +{ + # $1 is command name + # uses $HOSTS and $HOSTS_FILE + # sets $HOSTS or calls Usage which should exit + local l_hosts_file + + if [ "$HOSTS_FILE" = "" ] + then + HOSTS_FILE=$CONFIG_DIR/opa/hosts + fi + if [ "$HOSTS" = "" ] + then + l_hosts_file=$HOSTS_FILE + HOSTS_FILE=`resolve_file "$1" "$HOSTS_FILE"` + if [ "$HOSTS_FILE" = "" ] + then + echo "$1: HOSTS env variable is empty and the file $l_hosts_file does not exist" >&2 + echo "$1: Must export HOSTS or HOSTS_FILE or use -f or -h option" >&2 + Usage + fi + HOSTS=`expand_file "$1" "$HOSTS_FILE"` + if [ "$HOSTS" = "" ] + then + echo "$1: HOSTS env variable and the file $HOSTS_FILE are both empty" >&2 + echo "$1: Must export HOSTS or HOSTS_FILE or use -f or -h option" >&2 + Usage + fi + + fi +} + +check_chassis_args() +{ + # $1 is command name + # uses $CHASSIS and $CHASSIS_FILE + # sets $CHASSIS or calls Usage which should exit + local l_chassis_file + + if [ "$CHASSIS_FILE" = "" ] + then + CHASSIS_FILE=$CONFIG_DIR/opa/chassis + fi + if [ "$CHASSIS" = "" ] + then + l_chassis_file=$CHASSIS_FILE + CHASSIS_FILE=`resolve_file "$1" "$CHASSIS_FILE"` + if [ "$CHASSIS_FILE" = "" ] + then + echo "$1: CHASSIS env variable is empty and the file $l_chassis_file does not exist" >&2 + echo "$1: Must export CHASSIS or CHASSIS_FILE or use -F or -H option" >&2 + Usage + fi + CHASSIS=`expand_file "$1" "$CHASSIS_FILE"` + if [ "$CHASSIS" = "" ] + then + echo "$1: CHASSIS env variable and the file $CHASSIS_FILE are both empty" >&2 + echo "$1: Must export CHASSIS or CHASSIS_FILE or use -F or -H option" >&2 + Usage + fi + fi + + export CFG_CHASSIS_LOGIN_METHOD=$FF_CHASSIS_LOGIN_METHOD + export CFG_CHASSIS_ADMIN_PASSWORD=$FF_CHASSIS_ADMIN_PASSWORD +} + +check_ib_transport_args() +{ + # $1 is command name + # uses $OPASWITCHES and $OPASWITCHES_FILE + # sets $OPASWITCHES or calls Usage which should exit + local l_opaswitches_file + + if [ "$OPASWITCHES_FILE" = "" ] + then + OPASWITCHES_FILE=$CONFIG_DIR/opa/switches + fi + if [ "$OPASWITCHES" = "" ] + then + l_opaswitches_file=$OPASWITCHES_FILE + OPASWITCHES_FILE=`resolve_file "$1" "$OPASWITCHES_FILE"` + if [ "$OPASWITCHES_FILE" = "" ] + then + echo "$1: OPASWITCHES env variable is empty and the file $l_opaswitches_file does not exist" >&2 + echo "$1: Must export OPASWITCHES or OPASWITCHES_FILE or use -L or -N option" >&2 + Usage + fi + OPASWITCHES=`expand_file "$1" "$OPASWITCHES_FILE"` + if [ "$OPASWITCHES" = "" ] + then + echo "$1: OPASWITCHES env variable and the file $OPASWITCHES_FILE are both empty" >&2 + echo "$1: Must export OPASWITCHES or OPASWITCHES_FILE or use -L or -N option" >&2 + Usage + fi + fi + +} + +check_ports_args() +{ + # $1 is command name + # uses $PORTS and $PORTS_FILE + # sets $PORTS or calls Usage which should exit + local have_file_name + + if [ "$PORTS_FILE" = "" ] + then + PORTS_FILE=$CONFIG_DIR/opa/ports + fi + if [ "$PORTS" = "" ] + then + # allow case where PORTS_FILE is not found (ignore stderr) + if [ "$PORTS_FILE" != "$CONFIG_DIR/opa/ports" ] + then + PORTS_FILE=`resolve_file "$1" "$PORTS_FILE"` + have_file_name=1 + else + # quietly hide a missing ports file + PORTS_FILE=`resolve_file "$1" "$PORTS_FILE" 2>/dev/null` + have_file_name=0 + fi + if [ "$PORTS_FILE" = "" ] + then + if [ "$have_file_name" = 1 ] + then + Usage + fi + else + PORTS=`expand_file "$1" "$PORTS_FILE"` + fi + fi + if [ "$PORTS" = "" ] + then + PORTS="0:0" # default to 1st active port + #echo "$1: Must export PORTS or PORTS_FILE or use -l or -p option" >&2 + #Usage + fi + +} + +resolve_topology_file() +{ + # $1 is command name, $2 is hfi_port fabric selector (0:0, 1:2, etc) + # uses $FF_TOPOLOGY_FILE + # sets $TOPOLOGY_FILE or calls Usage which should exit + # if topology check is disabled, sets TOPOLOGY_FILE to "" + + if [ "$FF_TOPOLOGY_FILE" = "" -o "$FF_TOPOLOGY_FILE" = "NONE" ] + then + TOPOLOGY_FILE="" + # topology check disabled + return + fi + # expand marker + file=$(echo "$FF_TOPOLOGY_FILE"|sed -e "s/%P/$2/g") + # allow case where FF_TOPOLOGY_FILE is not found (ignore stderr) + TOPOLOGY_FILE=`resolve_file "$1" "$file" 2>/dev/null` +} + +check_esm_chassis_args() +{ + # $1 is command name + # uses $ESM_CHASSIS and $ESM_CHASSIS_FILE + # sets $ESM_CHASSIS or calls Usage which should exit + local l_esm_chassis_file + + if [ "$ESM_CHASSIS_FILE" = "" ] + then + ESM_CHASSIS_FILE=$CONFIG_DIR/opa/esm_chassis + fi + if [ "$ESM_CHASSIS" = "" ] + then + l_esm_chassis_file=$ESM_CHASSIS_FILE + ESM_CHASSIS_FILE=`resolve_file "$1" "$ESM_CHASSIS_FILE"` + if [ "$ESM_CHASSIS_FILE" = "" ] + then + echo "$1: ESM_CHASSIS env variable is empty and the file $l_esm_chassis_file does not exist" >&2 + echo "$1: Must export ESM_CHASSIS or ESM_CHASSIS_FILE or use -G or -E option" >&2 + Usage + fi + ESM_CHASSIS=`expand_file "$1" "$ESM_CHASSIS_FILE"` + if [ "$ESM_CHASSIS" = "" ] + then + echo "$1: ESM_CHASSIS env variable and the file $ESM_CHASSIS_FILE are both empty" >&2 + echo "$1: Must export ESM_CHASSIS or ESM_CHASSIS_FILE or use -G or -E option" >&2 + Usage + fi + fi + +} + + +strip_chassis_slots() +{ + # removes any slot numbers and returns chassis network name + case "$1" in + *\[*\]*:*) # [chassis]:slot format + #echo "$1"|awk -F \[ '{print $2}'|awk -F \] '{print $1}' + echo "$1"|sed -e 's/.*\[//' -e 's/\].*//' + ;; + *\[*\]) # [chassis] format + #echo "$1"|awk -F \[ '{print $2}'|awk -F \] '{print $1}' + echo "$1"|sed -e 's/.*\[//' -e 's/\].*//' + ;; + *:*:*) # ipv6 without [] nor slot + echo "$1" + ;; + *:*) # chassis:slot format + echo "$1"|cut -f1 -d: + ;; + *) # chassis without [] nor slot + echo "$1" + ;; + esac +} + +strip_switch_name() +{ + # $1 is a switches entry + # removes any node name and returns node GUID + echo "$1"|cut -f1 -d, +} + +ping_host() +{ + #$1 is the destination to ping + #return 1 if dest doesn't respond: unknown host or unreachable + + if type /usr/lib/opa/tools/opagetipaddrtype >/dev/null 2>&1 + then + iptype=`/usr/lib/opa/tools/opagetipaddrtype $1 2>/dev/null` + if [ x"$iptype" = x ] + then + iptype='ipv4' + fi + else + iptype="ipv4" + fi + if [ "$iptype" == "ipv4" ] + then + ping -c 2 -w 4 $1 >/dev/null 2>&1 + else + ping6 -c 2 -w 4 $1 >/dev/null 2>&1 + fi + return $? +} + + +# convert the supplied $1 list into a one line per entry style output +# this is useful to take a parsed input like "$HOSTS" and convert it +# to a pipeline for use in some of the functions below or other +# basic shell commands which use stdin +ff_var_to_stdout() +{ + # translate spaces to newlines and get rid of any blank lines caused by + # extra spaces + echo "$1"|tr -s ' ' '\n'|sed -e '/^$/d' +} + +# take the list on stdin and convert to lower case +ff_to_lc() +{ + tr A-Z a-z +} + +# take the list on stdin and convert to lowercase, +# sort alphabetically filtering any dups +# assumed the list is a set of TCP/IP names which are hence case insensitive +ff_filter_dups() +{ + ff_to_lc|sort -u +} + +# convert the supplied $1 list into a one line per entry style output +# and convert to lowercase, filter dups and alphabetically sort +ff_var_filter_dups_to_stdout() +{ + ff_var_to_stdout "$1"|ff_filter_dups +} diff --git a/IbaTools/FastFabric/ff_function.exp b/IbaTools/FastFabric/ff_function.exp new file mode 100644 index 0000000..ab64a00 --- /dev/null +++ b/IbaTools/FastFabric/ff_function.exp @@ -0,0 +1,74 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] + +# Invoke a fast fabric config file function/utility +# to do so we need to start a bash shell + +proc ff_function { func_name arg } { + if { [ catch { + set result [ exec bash -c " + if \[ -f /etc/opa/opafastfabric.conf \] + then + . /etc/opa/opafastfabric.conf + fi + . /usr/lib/opa/tools/opafastfabric.conf.def + if \[ x\"\$FF_IPOIB_SUFFIX\" = xNONE \] + then + export FF_IPOIB_SUFFIX=\"\" + fi + $func_name $arg + " 2>@ stderr ] + } res ] != 0 } { + set error "$func_name $arg: FAILED" + puts stderr "$error" + error $error $error + } + return $result +} + +# convert a name from $HOSTS/$HOSTS_FILE to its basic (hostname -s) format +# name given could be ethernet or IPoIB +proc ff_host_basename { host } { + return "[ ff_function ff_host_basename $host ]" +} + +# convert a name from $HOSTS/$HOSTS_FILE to its IPoIB equivalent +# name given could be ethernet or IPoIB +proc ff_host_to_ipoib { host } { + return "[ ff_function ff_host_basename_to_ipoib [ff_host_basename $host] ]" +} + +# return the base IPoIB device number for this stack +# Should return 1 on Silverstorm stacks (IBACCESS) and +# 0 on OFED stacks (OPENIB). +proc ff_ipoib_base_dev_num { host } { + return "[ ff_function ff_ipoib_base_dev_num $host]" +} diff --git a/IbaTools/FastFabric/hosts b/IbaTools/FastFabric/hosts new file mode 100644 index 0000000..0131fb2 --- /dev/null +++ b/IbaTools/FastFabric/hosts @@ -0,0 +1,8 @@ +# [ICS VERSION STRING: unknown] +# This file lists the TCP/IP names of the hosts in the cluster. +# EXCEPT FOR THE NODE RUNNING FASTFABRIC +# +# If Ethernet is being used for the management network, specify +# the hostname corresponding to the ethernet IP address. +# This file will be used by FastFabric to indicate which hosts should be +# operated on by various fastfabric menus and CLI commands. diff --git a/IbaTools/FastFabric/ibnodes b/IbaTools/FastFabric/ibnodes new file mode 100644 index 0000000..2829c28 --- /dev/null +++ b/IbaTools/FastFabric/ibnodes @@ -0,0 +1,21 @@ +# [ICS VERSION STRING: unknown] +# This file lists all the Intel Externally Managed Switches +# +# specify one line per switch of the form guid,nodeDesc,distance +# guid - node guid of the switch +# nodeDesc - optional node description which should be programmed into +# the switch by FastFabric. It is recommended to supply a unique +# nodeDesc for each switch to simplify management of the cluster. +# distance - optional relative distance of the switch from the FastFabric node +# this is used by reboot operations to first operate on switches furthest +# from the FastFabric node. +# Nodes without a distance specified will be treated as furthest. +# For fabrics with multiple IB subnets, the local hfi and port to use may be +# specified as: guid:hfi:port,nodeDesc,distance. +# See the FastFabric Manual for more info +# +# The opagenswitches tool can be used to query the SM and generate a list of +# Externally Managed switches in the proper form for this file. +# +# for example: +# 0x00066a00e300299f,SwitchA1,2 diff --git a/IbaTools/FastFabric/ipoibping.exp b/IbaTools/FastFabric/ipoibping.exp new file mode 100644 index 0000000..5739e60 --- /dev/null +++ b/IbaTools/FastFabric/ipoibping.exp @@ -0,0 +1,126 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] + +source /usr/lib/opa/tools/ibtools.exp +source "/usr/lib/opa/tools/ff_function.exp" + +#=============================================================================# +# Test Suite Description: +#-----------------------------------------------------------------------------# +## ipoibping +## ------- +## IPoIB ping test to each host +#=============================================================================# + +# manditory setup +log_user 0; # disable detailed logging to stdout + +# uncomment the following to debug the test +#strace 20 +#log_user 1 +#exp_internal 1 +#cmd_trace on +#strace 4 + +proc suite_setup {} { + # example of conditional setup + #test_execute {load populate} { + #do some installation or configuration stuff + #} +} + +proc case_setup {} { +# setup to do at start of each test case +# Usage: +# pass as argument to start_suite +# Arguments: +# None +# This procedure will be run at the start of every test case +# It provides an opportunity for uniform cleanup/setup for each test case + + #upvar 2 host host + + #host_save_log $host +} + +proc case_cleanup { failed } { +# cleanup to do after each test case +# Usage: +# pass as argument to start_suite +# Arguments: +# failed - set to 1 if test case failed in which case additional +# information/files may be desired in test_tmp +# set to 0 if test case passed +# This procedure will be run at the end of every test case +# It provides an opportunity for uniform cleanup after each test case + global env + + test_execute {} { + if { $failed || [ test_save_temp ] } { + # save any logs/results from system(s) under test + #upvar host host + #host_check_log $host "qipoib" + } + } +} + +test_suite "ipoibping" "ipoib ping" "Ping test to each host via IPoIB +File: /usr/lib/opa/tools/ipoibping.exp" suite_setup noop { + + # Global Initializations for Test Suite: + # -------------------------------------- + + # ADD ANY GLOBAL INITIALIZATION HERE, SUCH AS: + # set env(MY_ENV_VAR) value + # also validate the environment + # if the environment is bad call fail_suite "information" abort_now + # abort_now should be 0 if it is safe to proceed and simply ignore all + # test_case calls. it should be 1 if that is not possible. + + # Procedures used to support Test Suite: + # -------------------------------------- + + # The actual test cases: + # ---------------------- + + # use fast fabric conversion function to get IPoIB addresses of hosts + set ipoib_hosts {} + foreach host $env(CFG_HOSTS) { + lappend ipoib_hosts "[ff_host_to_ipoib $host]" + } + + # prevent test_case_ping1 from modifying host name + set env(CFG_IPOIB_SUFFIX) "" + + # ping from localhost to each remote host, "" ipoib_suffix since + # we already translated host names + test_case_ping1 localhost $ipoib_hosts "IPoIB" "" "$env(CFG_IPOIB_MTU)" 1 +} diff --git a/IbaTools/FastFabric/load.exp b/IbaTools/FastFabric/load.exp new file mode 100644 index 0000000..b9d0751 --- /dev/null +++ b/IbaTools/FastFabric/load.exp @@ -0,0 +1,132 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] + +#=============================================================================# +# Test Suite Description: +#-----------------------------------------------------------------------------# +## load +## ------- +## simple installation on all hosts +#=============================================================================# + +# manditory setup +log_user 0; # disable detailed logging to stdout + +# uncomment the following to debug the test +#strace 20 +#log_user 1 +#exp_internal 1 +#cmd_trace on +#strace 4 + +set install_exit_code 0 + +proc suite_setup {} { + # example of conditional setup + #test_execute {load populate} { + #do some installation or configuration stuff + #} +} + +proc case_setup {} { +# setup to do at start of each test case +# Usage: +# pass as argument to start_suite +# Arguments: +# None +# This procedure will be run at the start of every test case +# It provides an opportunity for uniform cleanup/setup for each test case + +} + +proc case_cleanup { failed } { +# cleanup to do after each test case +# Usage: +# pass as argument to start_suite +# Arguments: +# failed - set to 1 if test case failed in which case additional +# information/files may be desired in test_tmp +# set to 0 if test case passed +# This procedure will be run at the end of every test case +# It provides an opportunity for uniform cleanup after each test case + global env + + test_execute {} { + if { $failed || [ test_save_temp ] } { + # save any logs/results from system(s) under test + global host + + install_get_logs $host + } + + if { $failed } { + # could put cleanup here + } + } +} + +test_suite "load" "load" "Simple installation of all hosts +File: /usr/lib/opa/tools/load.exp" suite_setup noop { + global host + + # Global Initializations for Test Suite: + # -------------------------------------- + + # ADD ANY GLOBAL INITIALIZATION HERE, SUCH AS: + # set env(MY_ENV_VAR) value + # also validate the environment + # if the environment is bad call fail_suite "information" abort_now + # abort_now should be 0 if it is safe to proceed and simply ignore all + # test_case calls. it should be 1 if that is not possible. + + # Procedures used to support Test Suite: + # -------------------------------------- + + # The actual test cases: + # ---------------------- + + parallel host $env(CFG_HOSTS) { + test_case "$host" "load $env(CFG_RELEASE) on $host" "Installation of $env(CFG_RELEASE) $env(CFG_PRODUCT) on $host +with options $env(CFG_INSTALL_OPTIONS) +Removing any previous configuration +File: /usr/lib/opa/tools/load.exp" case_setup case_cleanup { + upvar host host + + # build list of drivers. If config says not to test a + # given driver, its possible that its not on the media + # so we can't expect it to be installed + # for now assume Stack or Enablement tools are always on media + set drivers {{((OFED OPA Stack)|(OFA OPA Stack)|(OFED IBACM)|(OFA IBACM)|(Intel HFI Components)|(OPA Tools)|(OFED IP over IB)|(OFA IP over IB)|(IFS FM))}} + + install_all $host "$drivers" 1 1 0 "" "$env(CFG_RELEASE)" "$env(CFG_INSTALL_OPTIONS)" "$env(CFG_SCPFROMDIR)" "$env(CFG_PRODUCT)" + } + } +} diff --git a/IbaTools/FastFabric/mac_to_dhcp.sh b/IbaTools/FastFabric/mac_to_dhcp.sh new file mode 100644 index 0000000..84d930e --- /dev/null +++ b/IbaTools/FastFabric/mac_to_dhcp.sh @@ -0,0 +1,51 @@ +#!/bin/bash +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +#[ICS VERSION STRING: unknown] + +# given a file of host and mac addresses, generate dhcp stanzas to +# append to dhcpd.conf +# this works for an inpurt file format such as: +# myserver252 00:26:6C:F0:BB:94 +# myserver253 00:26:6C:F0:A7:A4 +# Usage: +# mac_to_dhcp < in_file > dhcp_file + + +while read host mac +do +cat << EOF +host $host { + option host-name "$host"; + hardware ethernet $mac; + fixed-address $host; +} +EOF +done diff --git a/IbaTools/FastFabric/mpiperf.exp b/IbaTools/FastFabric/mpiperf.exp new file mode 100644 index 0000000..3b69e3a --- /dev/null +++ b/IbaTools/FastFabric/mpiperf.exp @@ -0,0 +1,146 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] + +source "/usr/lib/opa/tools/ff_function.exp" + +#=============================================================================# +# Test Suite Description: +#-----------------------------------------------------------------------------# +## mpiperf +## ------- +## quick MPI performance verification between each pair of hosts +#=============================================================================# + +# manditory setup +log_user 0; # disable detailed logging to stdout + +# uncomment the following to debug the test +#strace 20 +#log_user 1 +#exp_internal 1 +#cmd_trace on +#strace 4 + +proc suite_setup {} { + # example of conditional setup + #test_execute {load populate} { + #do some installation or configuration stuff + #} +} + +proc case_setup {} { +# setup to do at start of each test case +# Usage: +# pass as argument to start_suite +# Arguments: +# None +# This procedure will be run at the start of every test case +# It provides an opportunity for uniform cleanup/setup for each test case + + #upvar 2 host host + + #host_save_log $host +} + +proc case_cleanup { failed } { +# cleanup to do after each test case +# Usage: +# pass as argument to start_suite +# Arguments: +# failed - set to 1 if test case failed in which case additional +# information/files may be desired in test_tmp +# set to 0 if test case passed +# This procedure will be run at the end of every test case +# It provides an opportunity for uniform cleanup after each test case + global env + + test_execute {} { + if { $failed || [ test_save_temp ] } { + # save any logs/results from system(s) under test + #upvar host host + #host_check_log $host "qmpi" + } + } +} + +test_suite "mpiperf" "mpi lat/bw" "Quick tests of mpi lat/bw between each pair +of hosts +File: /usr/lib/opa/tools/mpiperf.exp" suite_setup noop { + global env + + # Global Initializations for Test Suite: + # -------------------------------------- + + # ADD ANY GLOBAL INITIALIZATION HERE, SUCH AS: + # set env(MY_ENV_VAR) value + # also validate the environment + # if the environment is bad call fail_suite "information" abort_now + # abort_now should be 0 if it is safe to proceed and simply ignore all + # test_case calls. it should be 1 if that is not possible. + + # Procedures used to support Test Suite: + # -------------------------------------- + + # The actual test cases: + # ---------------------- + + set full 0 + # compute host_pairs by taking each pair of hosts from CFG_HOSTS + # 1 to 2, 3 to 4, etc. Thus each hosts bus speed and Ib connect is + # verified once + set host_pairs {} + set num_hosts [llength $env(CFG_HOSTS)] + if { $num_hosts < 2 } { + fail_suite "Need at least 2 hosts for MPI" + } + + for { set i 0 } { $i < [ expr $num_hosts -1] } { incr i 2 } { + set host1 [lindex $env(CFG_HOSTS) $i] + set host2 [lindex $env(CFG_HOSTS) [ expr $i + 1]] + lappend host_pairs "[ff_host_to_ipoib $host1] [ff_host_to_ipoib $host2]" + } + if { $num_hosts > 1 && $num_hosts % 2 == 1 } { + # odd number, for last pair check last 2 hosts + set host1 [lindex $env(CFG_HOSTS) [expr $num_hosts -2] ] + set host2 [lindex $env(CFG_HOSTS) [expr $num_hosts -1] ] + lappend host_pairs "[ff_host_to_ipoib $host1] [ff_host_to_ipoib $host2]" + } + + # prevent build_mpi_hosts/test_case_run_mpi_app from modifying host name + set env(CFG_IPOIB_SUFFIX) "" + + set mpitype [determine_mpitype "$env(FF_MPI_APPS_DIR)"] + + foreach pair $host_pairs { + test_case_run_mpi_app $mpitype default localhost $pair 60 "$env(FF_MPI_APPS_DIR)/latency" "latency" "100000 0" 1 + test_case_run_mpi_app $mpitype default localhost $pair 60 "$env(FF_MPI_APPS_DIR)/bandwidth" "bw" "100 1000000" 1 + } +} diff --git a/IbaTools/FastFabric/mpiperfdeviation.exp b/IbaTools/FastFabric/mpiperfdeviation.exp new file mode 100644 index 0000000..bcd9839 --- /dev/null +++ b/IbaTools/FastFabric/mpiperfdeviation.exp @@ -0,0 +1,136 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] + +source "/usr/lib/opa/tools/ff_function.exp" + +#=============================================================================# +# Test Suite Description: +#-----------------------------------------------------------------------------# +## mpiperfdeviation +## ------- +## quick MPI performance verification between each pair of hosts +#=============================================================================# + +# manditory setup +log_user 0; # disable detailed logging to stdout + +# uncomment the following to debug the test +#strace 20 +#log_user 1 +#exp_internal 1 +#cmd_trace on +#strace 4 + +proc suite_setup {} { + # example of conditional setup + #test_execute {load populate} { + #do some installation or configuration stuff + #} +} + +proc case_setup {} { +# setup to do at start of each test case +# Usage: +# pass as argument to start_suite +# Arguments: +# None +# This procedure will be run at the start of every test case +# It provides an opportunity for uniform cleanup/setup for each test case + + #upvar 2 host host + + #host_save_log $host +} + +proc case_cleanup { failed } { +# cleanup to do after each test case +# Usage: +# pass as argument to start_suite +# Arguments: +# failed - set to 1 if test case failed in which case additional +# information/files may be desired in test_tmp +# set to 0 if test case passed +# This procedure will be run at the end of every test case +# It provides an opportunity for uniform cleanup after each test case + global env + + test_execute {} { + if { $failed || [ test_save_temp ] } { + # save any logs/results from system(s) under test + #upvar host host + #host_check_log $host "qmpi" + } + } +} + +test_suite "mpiperfdeviation" "mpi lat/bw deviation" "Quick tests of mpi lat/bw deviation pairs +of hosts +File: /usr/lib/opa/tools/mpiperfdeviation.exp" suite_setup noop { + global env + + # Global Initializations for Test Suite: + # -------------------------------------- + + # ADD ANY GLOBAL INITIALIZATION HERE, SUCH AS: + # set env(MY_ENV_VAR) value + # also validate the environment + # if the environment is bad call fail_suite "information" abort_now + # abort_now should be 0 if it is safe to proceed and simply ignore all + # test_case calls. it should be 1 if that is not possible. + + # Procedures used to support Test Suite: + # -------------------------------------- + + # The actual test cases: + # ---------------------- + + set full 0 + # compute host_pairs by taking each pair of hosts from CFG_HOSTS + # 1 to 2, 3 to 4, etc. Thus each hosts bus speed and Ib connect is + # verified once + set host_pairs {} + set num_hosts [llength $env(CFG_HOSTS)] + if { $num_hosts < 2 } { + fail_suite "Need at least 2 hosts for MPI" + } + + for { set i 0 } { $i < [ expr $num_hosts] } { incr i 1 } { + set host1 [lindex $env(CFG_HOSTS) $i] + lappend host_pairs "[ff_host_to_ipoib $host1]" + } + + # prevent build_mpi_hosts/test_case_run_mpi_app from modifying host name + set env(CFG_IPOIB_SUFFIX) "" + + set mpitype [determine_mpitype "$env(FF_MPI_APPS_DIR)"] + + test_case_run_mpi_app $mpitype default localhost $host_pairs 60 "$env(FF_MPI_APPS_DIR)/deviation" "deviation" "$env(FF_DEVIATION_ARGS)" 1 +} diff --git a/IbaTools/FastFabric/opa_ca_openssl.cnf b/IbaTools/FastFabric/opa_ca_openssl.cnf new file mode 100644 index 0000000..26a1556 --- /dev/null +++ b/IbaTools/FastFabric/opa_ca_openssl.cnf @@ -0,0 +1,244 @@ +# +# Intel OPA Self-Signed CA OpenSSL example configuration file. +# This is mostly being used for generation of certificate requests. +# + +# This definition stops the following lines choking if HOME isn't +# defined. +HOME = . +RANDFILE = $ENV::HOME/.rnd + +# Extra OBJECT IDENTIFIER info: +#oid_file = $ENV::HOME/.oid +oid_section = new_oids + +# To use this configuration file with the "-extfile" option of the +# "openssl x509" utility, name here the section containing the +# X.509v3 extensions to use: +# extensions = +# (Alternatively, use a configuration file that has only +# X.509v3 extensions in its main [= default] section.) + +[ new_oids ] + +# We can add new OIDs in here for use by 'ca', 'req' and 'ts'. +# Add a simple OID like this: +# testoid1=1.2.3.4 +# Or use config file substitution like this: +# testoid2=${testoid1}.5.6 + +# Policies used by the TSA examples. +tsa_policy1 = 1.2.3.4.1 +tsa_policy2 = 1.2.3.4.5.6 +tsa_policy3 = 1.2.3.4.5.7 +#################################################################### +[ ca ] +default_ca = opa_ca # The default ca section + +#################################################################### +[ opa_ca ] + +dir = /root/opaCA # Where everything is kept +certs = $dir/certs # Where the issued certs are kept +crl_dir = $dir/crl # Where the issued crl are kept +database = $dir/index.txt # database index file. +#unique_subject = no # Set to 'no' to allow creation of + # several ctificates with same subject. +new_certs_dir = $dir/newcerts # default place for new certs. + +certificate = $dir/cacert.pem # The CA certificate +serial = $dir/serial # The current serial number +crlnumber = $dir/crlnumber # the current crl number + # must be commented out to leave a V1 CRL +crl = $dir/crl.pem # The current CRL +private_key = $dir/private/cakey.pem# The private key +RANDFILE = $dir/private/.rand # private random number file + +x509_extensions = opa_ca_cert_extensions # The extentions to add to the cert + +# Comment out the following two lines for the "traditional" +# (and highly broken) format. +#name_opt = opa_ca # Subject Name options +#cert_opt = opa_ca # Certificate field options + +# Extension copying option: use with caution. +# copy_extensions = copy + +# Extensions to add to a CRL. Note: Netscape communicator chokes on V2 CRLs +# so this is commented out by default to leave a V1 CRL. +# crlnumber must also be commented out to leave a V1 CRL. +# crl_extensions = crl_ext + +default_days = 365 # how long to certify for +default_crl_days= 30 # how long before next CRL +default_md = Recommend referencing https://www.ssl.com/guide/ssl-best-practices +preserve = no # keep passed DN ordering + +# A few difference way of specifying how similar the request should look +# For type CA, the listed attributes must be the same, and the optional +# and supplied fields are just that :-) +policy = opa_ca_policy_match + +# For the CA policy +[ opa_ca_policy_match ] +commonName = supplied +countryName = supplied +stateOrProvinceName = supplied +organizationName = supplied +emailAddress = supplied +organizationalUnitName = optional + +#################################################################### +[ req ] +default_bits = Recommend referencing https://www.ssl.com/guide/ssl-best-practices +default_md = Recommend referencing https://www.ssl.com/guide/ssl-best-practices +default_keyfile = /root/opaCA/private/cakey.pem +distinguished_name = opa_ca_distinguished_name +attributes = req_attributes +x509_extensions = opa_ca_extensions # The extentions to add to the self signed cert +prompt = no + +# Passwords for private keys if not present they will be prompted for +# input_password = secret +# output_password = secret + +# This sets a mask for permitted string types. There are several options. +# default: PrintableString, T61String, BMPString. +# pkix : PrintableString, BMPString (PKIX recommendation before 2004) +# utf8only: only UTF8Strings (PKIX recommendation after 2004). +# nombstr : PrintableString, T61String (no BMPStrings or UTF8Strings). +# MASK:XXXX a literal mask value. +# WARNING: ancient versions of Netscape crash on BMPStrings or UTF8Strings. +string_mask = utf8only + +[ opa_ca_distinguished_name ] +countryName = US +#countryName_default = XX +#countryName_min = 2 +#countryName_max = 2 + +stateOrProvinceName = Pennsylvania +#stateOrProvinceName_default = Default Province + +localityName = King of Prussia +#localityName_default = Default City + +organizationName = OPA A0 Sample Corporation +#organizationName_default = Default Company Ltd + +organizationalUnitName = OPA A0 Sample Division +#organizationalUnitName_default = + +commonName = phkpstl023.ph.intel.com +#commonName_max = 64 + +emailAddress = root@phkpstl023.ph.intel.com +#emailAddress_max = 64 + +# SET-ex3 = SET extension number 3 + +[ req_attributes ] +challengePassword = A challenge password +challengePassword_min = 4 +challengePassword_max = 20 + +unstructuredName = An optional company name + +[ opa_ca_cert_extensions ] + +# These extensions are added when 'ca' signs a request. + +# This goes against PKIX guidelines but some CAs do it and some software +# requires this to avoid interpreting an end user certificate as a CA. + +basicConstraints=CA:FALSE + +# Here are some examples of the usage of nsCertType. If it is omitted +# the certificate can be used for anything *except* object signing. + +# This is OK for an SSL server. +# nsCertType = server + +# For an object signing certificate this would be used. +# nsCertType = objsign + +# For normal client use this is typical +# nsCertType = client, email + +# and for everything including object signing: +# nsCertType = client, email, objsign + +# This is typical in keyUsage for a client certificate. +# keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +# This will be displayed in Netscape's comment listbox. +nsComment = "OpenSSL Generated Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer + +# This stuff is for subjectAltName and issuerAltname. +# Import the email address. +# subjectAltName=email:copy +# An alternative to produce certificates that aren't +# deprecated according to PKIX. +# subjectAltName=email:move + +# Copy subject details +# issuerAltName=issuer:copy + +#nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem +#nsBaseUrl +#nsRevocationUrl +#nsRenewalUrl +#nsCaPolicyUrl +#nsSslServerName + +# This is required for TSA certificates. +# extendedKeyUsage = critical,timeStamping + +[ opa_ca_extensions ] + +# Extensions for a typical CA + +# PKIX recommendation. + +subjectKeyIdentifier=hash + +authorityKeyIdentifier=keyid:always,issuer + +# This is what PKIX recommends but some broken software chokes on critical +# extensions. +#basicConstraints = critical,CA:true +# So we do this instead. +basicConstraints = CA:true + +# Key usage: this is typical for a CA certificate. However since it will +# prevent it being used as an test self-signed certificate it is best +# left out by default. +# keyUsage = cRLSign, keyCertSign + +# Some might want this also +# nsCertType = sslCA, emailCA + +# Include email address in subject alt name: another PKIX recommendation +# subjectAltName=email:copy +# Copy issuer details +# issuerAltName=issuer:copy + +# DER hex encoding of an extension: beware experts only! +# obj=DER:02:03 +# Where 'obj' is a standard or added object +# You can even override a supported extension: +# basicConstraints= critical, DER:30:03:01:01:FF + +[ crl_ext ] + +# CRL extensions. +# Only issuerAltName and authorityKeyIdentifier make any sense in a CRL. + +# issuerAltName=issuer:copy +authorityKeyIdentifier=keyid:always + +#################################################################### diff --git a/IbaTools/FastFabric/opa_comp_openssl.cnf b/IbaTools/FastFabric/opa_comp_openssl.cnf new file mode 100644 index 0000000..1308b05 --- /dev/null +++ b/IbaTools/FastFabric/opa_comp_openssl.cnf @@ -0,0 +1,83 @@ +# +# Intel OPA FM/FF Component OpenSSL example configuration file. +# This is mostly being used for generation of certificate requests. +# + +# This definition stops the following lines choking if HOME isn't +# defined. +HOME = . +RANDFILE = $ENV::HOME/.rnd + +# Extra OBJECT IDENTIFIER info: +#oid_file = $ENV::HOME/.oid +##oid_section = new_oids + +# To use this configuration file with the "-extfile" option of the +# "openssl x509" utility, name here the section containing the +# X.509v3 extensions to use: +# extensions = +# (Alternatively, use a configuration file that has only +# X.509v3 extensions in its main [= default] section.) + +[ req ] +default_bits = Recommend referencing https://www.ssl.com/guide/ssl-best-practices +default_md = Recommend referencing https://www.ssl.com/guide/ssl-best-practices +distinguished_name = opa_comp_distinguished_name +attributes = req_attributes +prompt = no + +# Passwords for private keys if not present they will be prompted for +# input_password = secret +# output_password = secret + +# This sets a mask for permitted string types. There are several options. +# default: PrintableString, T61String, BMPString. +# pkix : PrintableString, BMPString (PKIX recommendation before 2004) +# utf8only: only UTF8Strings (PKIX recommendation after 2004). +# nombstr : PrintableString, T61String (no BMPStrings or UTF8Strings). +# MASK:XXXX a literal mask value. +# WARNING: ancient versions of Netscape crash on BMPStrings or UTF8Strings. +string_mask = utf8only + +req_extensions = v3_req # The extensions to add to a certificate request + +[ opa_comp_distinguished_name ] +countryName = US +#countryName_default = US +#countryName_min = 2 +#countryName_max = 2 + +stateOrProvinceName = Pennsylvania +#stateOrProvinceName_default = Default Province + +localityName = King of Prussia +#localityName_default = Default City + +organizationName = OPA A0 Sample Corporation +#organizationName_default = Default Company Ltd + +organizationalUnitName = OPA A0 Sample Division +#organizationalUnitName_default = + +commonName = phkpstl023.ph.intel.com +#commonName_max = 64 + +emailAddress = root@phkpstl023.ph.intel.com +#emailAddress_max = 64 + +# SET-ex3 = SET extension number 3 + +[ req_attributes ] +#challengePassword = A challenge password +#challengePassword_min = 4 +#challengePassword_max = 20 + +unstructuredName = An optional company name + +[ v3_req ] + +# Extensions to add to a certificate request + +basicConstraints = CA:FALSE +keyUsage = nonRepudiation, digitalSignature, keyEncipherment +#################################################################### diff --git a/IbaTools/FastFabric/opaallanalysis.sh b/IbaTools/FastFabric/opaallanalysis.sh new file mode 100644 index 0000000..7ed70c0 --- /dev/null +++ b/IbaTools/FastFabric/opaallanalysis.sh @@ -0,0 +1,235 @@ +#!/bin/bash +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] +# Analyze fabric, chassis and SMs for errors and/or changes relative to baseline + +# optional override of defaults +if [ -f /etc/opa/opafastfabric.conf ] +then + . /etc/opa/opafastfabric.conf +fi + +. /usr/lib/opa/tools/opafastfabric.conf.def + +. /usr/lib/opa/tools/ff_funcs + +trap "exit 1" SIGHUP SIGTERM SIGINT + +Usage_full() +{ + echo "Usage: opaallanalysis [-b|-e] [-s] [-d dir] [-c file] [-t portsfile] [-p ports]" >&2 + echo " [-F chassisfile] [-H 'chassis']">&2 + echo " [-G esmchassisfile] [-E 'esmchassis']" >&2 + echo " [-T topology_input]" >&2 + echo " or" >&2 + echo " opaallanalysis --help" >&2 + echo " --help - produce full help text" >&2 + echo " -b - baseline mode, default is compare/check mode" >&2 + echo " -e - evaluate health only, default is compare/check mode" >&2 + echo " -s - save history of failures (errors/differences)" >&2 + echo " -d dir - top level directory for saving baseline and history of failed checks" >&2 + echo " default is /var/usr/lib/opa/analysis" >&2 + echo " -c file - error thresholds config file" >&2 + echo " default is $CONFIG_DIR/opa/opamon.conf" >&2 + echo " -t portsfile - file with list of local HFI ports used to access" >&2 + echo " fabric(s) for analysis, default is $CONFIG_DIR/opa/ports" >&2 + echo " -p ports - list of local HFI ports used to access fabric(s) for analysis" >&2 + echo " default is 1st active port" >&2 + echo " This is specified as hfi:port" >&2 + echo " 0:0 = 1st active port in system" >&2 + echo " 0:y = port y within system" >&2 + echo " x:0 = 1st active port on HFI x" >&2 + echo " x:y = HFI x, port y" >&2 + echo " The first HFI in the system is 1. The first port on an HFI is 1." >&2 + echo " -T topology_input - name of a topology input file to use." >&2 + echo " Any %P markers in this filename will be replaced with the" >&2 + echo " hfi:port being operated on (such as 0:0 or 1:2)" >&2 + echo " default is $CONFIG_DIR/opa/topology.%P.xml" >&2 + echo " if NONE is specified, will not use any topology_input files" >&2 + echo " See opareport for more information on topology_input files" >&2 + echo " -F chassisfile - file with chassis in cluster" >&2 + echo " default is $CONFIG_DIR/opa/chassis" >&2 + echo " -H chassis - list of chassis to analyze" >&2 + echo " -G esmchassisfile - file with SM chassis in cluster" >&2 + echo " default is $CONFIG_DIR/opa/esm_chassis" >&2 + echo " -E esmchassis - list of SM chassis to analyze" >&2 + echo " Environment:" >&2 + echo " PORTS - list of ports, used in absence of -t and -p" >&2 + echo " PORTS_FILE - file containing list of ports, used in absence of -t and -p" >&2 + echo " FF_TOPOLOGY_FILE - file containing topology_input, used in absence of -T" >&2 + echo " CHASSIS - list of chassis, used if -F and -H options not supplied" >&2 + echo " CHASSIS_FILE - file containing list of chassis, used if -F and -H options not" >&2 + echo " supplied" >&2 + echo " ESM_CHASSIS - list of SM chassis, used if -G and -E not supplied" >&2 + echo " ESM_CHASSIS_FILE - file containing list of SM chassis, used if -G and -E not" >&2 + echo " supplied" >&2 + echo " FF_ANALYSIS_DIR - top level directory for baselines and failed health checks" >&2 + echo " FF_CHASSIS_CMDS - list of commands to issue during analysis," >&2 + echo " unused if -e option supplied" >&2 + echo " FF_CHASSIS_HEALTH - single command to issue to check overall health during analysis," >&2 + echo " unused if -b option supplied" >&2 + echo "for example:" >&2 + echo " opaallanalysis" >&2 + echo " opaallanalysis -p '1:1 1:2 2:1 2:2'" >&2 + exit 0 +} + +Usage() +{ + echo "Usage: opaallanalysis [-b|-e] [-s] [-F chassisfile] [-G esmchassisfile]" >&2 + echo " or" >&2 + echo " opaallanalysis --help" >&2 + echo " --help - produce full help text" >&2 + echo " -b - baseline mode, default is compare/check mode" >&2 + echo " -e - evaluate health only, default is compare/check mode" >&2 + echo " -s - save history of failures (errors/differences)" >&2 + echo " -F chassisfile - file with chassis in cluster" >&2 + echo " default is $CONFIG_DIR/opa/chassis" >&2 + echo " -G esmchassisfile - file with SM chassis in cluster" >&2 + echo " default is $CONFIG_DIR/opa/esm_chassis" >&2 + echo "for example:" >&2 + echo " opaallanalysis" >&2 + exit 2 +} + +if [ x"$1" = "x--help" ] +then + Usage_full +fi + +getbaseline=n +healthonly=n +savehistory=n +opts="" +configfile=$CONFIG_DIR/opa/opamon.conf +status=ok +while getopts besd:c:p:t:T:H:F:E:G: param +do + case $param in + b) opts="$opts -b"; getbaseline=y;; + e) opts="$opts -e"; healthonly=y;; + s) opts="$opts -s"; savehistory=y;; + d) export FF_ANALYSIS_DIR="$OPTARG";; + c) configfile="$OPTARG";; + p) export PORTS="$OPTARG";; + t) export PORTS_FILE="$OPTARG";; + T) export FF_TOPOLOGY_FILE="$OPTARG";; + H) export CHASSIS="$OPTARG";; + F) export CHASSIS_FILE="$OPTARG";; + E) export ESM_CHASSIS="$OPTARG";; + G) export ESM_CHASSIS_FILE="$OPTARG";; + ?) Usage;; + esac +done +shift $((OPTIND -1)) +if [ $# -ge 1 ] +then + Usage +fi +if [ "$getbaseline" = y -a "$healthonly" = y ] +then + Usage +fi + + +# first verify all arguments +for i in $FF_ALL_ANALYSIS +do + case $i in + fabric) + check_ports_args opaallanalysis;; + chassis) + check_chassis_args opaallanalysis;; + hostsm) + ;; + esm) + check_esm_chassis_args opaallanalysis;; + *) + echo "opaallanalysis: Invalid setting in FF_ALL_ANALYSIS: $i" >&2 + exit 1;; + esac +done + +export FF_CURTIME="${FF_CURTIME:-`date +%Y-%m-%d-%H:%M:%S`}" + +#----------------------------------------------------------------- +for i in $FF_ALL_ANALYSIS +do + case $i in + fabric) + /usr/sbin/opafabricanalysis $opts -c "$configfile" + if [ $? != 0 ] + then + status=bad + fi + ;; + chassis) + /usr/sbin/opachassisanalysis $opts + if [ $? != 0 ] + then + status=bad + fi + ;; + hostsm) + /usr/sbin/opahostsmanalysis $opts + if [ $? != 0 ] + then + status=bad + fi + ;; + esm) + /usr/sbin/opaesmanalysis $opts + if [ $? != 0 ] + then + status=bad + fi + ;; + esac +done + +if [ "$status" != "ok" ] +then + if [[ $healthonly == n ]] + then + echo "opaallanalysis: Possible errors or changes found" >&2 + else + echo "opaallanalysis: Possible errors found" >&2 + fi + exit 1 +else + if [[ $getbaseline == n ]] + then + echo "opaallanalysis: All OK" + else + echo "opaallanalysis: Baselined" + fi + exit 0 +fi diff --git a/IbaTools/FastFabric/opacablehealth.cron b/IbaTools/FastFabric/opacablehealth.cron new file mode 100644 index 0000000..0273b61 --- /dev/null +++ b/IbaTools/FastFabric/opacablehealth.cron @@ -0,0 +1,2 @@ +# [ICS VERSION STRING: unknown] +0 2 * * sun root /usr/lib/opa/tools/opacablehealthcron > /dev/null 2>&1 diff --git a/IbaTools/FastFabric/opacablehealthcron.sh b/IbaTools/FastFabric/opacablehealthcron.sh new file mode 100755 index 0000000..f8b3297 --- /dev/null +++ b/IbaTools/FastFabric/opacablehealthcron.sh @@ -0,0 +1,133 @@ +#!/bin/bash +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2018, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] + +# Usage: opacablehealthcron +# At regular intervals executes cablehealth and saves the data in a file + +Usage_full() +{ + echo "Usage: opacablehealthcron" >&2 + echo " opacablehealthcron --help" >&2 + echo " --help - produce full help text" >&2 + echo "This script will at regular intervals execute opareport -o cablehealth" >&2 + echo "The output of the program is stored in an already specified location" >&2 + echo "It is defined in FF_CABLE_HEALTH_REPORT_DIR of opafastfabric.conf" >&2 +} + +Usage() +{ + Usage_full + exit 2 +} + +if [ x"$1" = "x--help" ] +then + Usage_full + exit 0 +fi + + +if [ -f /usr/lib/opa/tools/ff_funcs ] +then + . /usr/lib/opa/tools/ff_funcs + ff_available=y +else + ff_available=n +fi + +if [ $ff_available = "y" ] +then + if [ -f $CONFIG_DIR/opa/opafastfabric.conf ] + then + . $CONFIG_DIR/opa/opafastfabric.conf + fi + . /usr/lib/opa/tools/opafastfabric.conf.def +fi + +# Check if is the master FM +# For nodes with FM running as master, BaseLID and SMLId will be same +# In Multi-rail the SM could be linked to any one of the HFI, PORT combinations +# In Multi-plane master SM for each fabric could be linked to any of the HFI, PORT combinations +if [ "$ff_available" = y ] +then + check_ports_args opacablehealthcron +else + PORTS='0:0' +fi + +for hfi_port in $PORTS +do + hfi=$(expr $hfi_port : '\([0-9]*\):[0-9]*') + port=$(expr $hfi_port : '[0-9]*:\([0-9]*\)') + if [ "$hfi" = "" -o "$port" = "" ] + then + echo "opacablehealthcron: Error: Invalid port specification: $hfi_port" >&2 + continue + fi + + ## fixup name so winzip won't complain + hfi_port_dir=${hfi}_${port} + + # For nodes with FM running as master, LID and MasterSMLID will be same + baseLid=`/usr/sbin/opasmaquery -h $hfi -p $port -o portinfo -g 2>/dev/null| sed -ne '/\bLID\b/ s/.*: *//p'` + smLid=`/usr/sbin/opasmaquery -h $hfi -p $port -o portinfo -g 2>/dev/null| sed -ne '/\bMasterSMLID\b/ s/.*: *//p'` + #Store HFI of device connected to SM + if [ "$baseLid" != "$smLid" ] + then + continue; + fi + + echo "Periodic generation of Cable Health Report" + # create cable health report directory and generate report + if [ $ff_available = "y" ] && [ -n "${FF_CABLE_HEALTH_REPORT_DIR}" ] + then + echo "Gathering Cable Health Report ..." + # Directory name with HFI and PORT + FF_CABLE_HEALTH_REPORT_DIR_WITH_HFI_PORT="${FF_CABLE_HEALTH_REPORT_DIR}/${hfi_port_dir}/" + mkdir -p ${FF_CABLE_HEALTH_REPORT_DIR_WITH_HFI_PORT} + # Maintain the number of cable health report files at FF_CABLE_HEALTH_MAX_FILES + if [ -n "${FF_CABLE_HEALTH_MAX_FILES}" ] + then + files_in_dir=`ls ${FF_CABLE_HEALTH_REPORT_DIR_WITH_HFI_PORT} | wc -l ` + files_to_delete=`expr $files_in_dir - ${FF_CABLE_HEALTH_MAX_FILES}` + if [ $files_to_delete -gt 0 ] + then + find ${FF_CABLE_HEALTH_REPORT_DIR_WITH_HFI_PORT} -name "cablehealth*" -maxdepth 1 -type f 2>/dev/null | xargs -r ls -1tr | head -n $files_to_delete | xargs -r rm + fi + fi + /usr/sbin/opareport -h $hfi -p $port -o cablehealth 2>/dev/null >${FF_CABLE_HEALTH_REPORT_DIR_WITH_HFI_PORT}/cablehealth$(date "+%Y%m%d%H%M%S").csv + fi +done + +echo "Done." + +exit 0 diff --git a/IbaTools/FastFabric/opacaptureall.sh b/IbaTools/FastFabric/opacaptureall.sh new file mode 100755 index 0000000..92680ac --- /dev/null +++ b/IbaTools/FastFabric/opacaptureall.sh @@ -0,0 +1,339 @@ +#!/bin/bash +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] +# perform an opacapture on all hosts/chassis and upload to this host + +# optional override of defaults +if [ -f /etc/opa/opafastfabric.conf ] +then + . /etc/opa/opafastfabric.conf +fi + +. /usr/lib/opa/tools/opafastfabric.conf.def + +. /usr/lib/opa/tools/ff_funcs + +trap "exit 1" SIGHUP SIGTERM SIGINT + +Usage_full() +{ + echo "Usage: opacaptureall [-Cp] [-f hostfile] [-F chassisfile]" >&2 + echo " [ -h 'hosts'] [-H 'chassis'] [-t portsfile]" >&2 + echo " [-d upload_dir] [-S] [-D detail_level] [file]" >&2 + echo " or" >&2 + echo " opacaptureall --help" >&2 + echo " --help - produce full help text" >&2 + echo " -C - perform capture against chassis, default is hosts" >&2 + echo " -p - perform capture upload in parallel on all hosts/chassis" >&2 + echo " -f hostfile - file with hosts in cluster, default is $CONFIG_DIR/opa/hosts" >&2 + echo " -F chassisfile - file with chassis in cluster" >&2 + echo " default is $CONFIG_DIR/opa/chassis" >&2 + echo " -h hosts - list of hosts to perform capture of" >&2 + echo " -H chassis - list of chassis to perform capture of" >&2 + echo " -t portsfile - file with list of local HFI ports used to access" >&2 + echo " fabric(s) for switch access, default is /etc/opa/ports" >&2 + echo " -d upload_dir - directory to upload to, default is uploads" >&2 + echo " -S - securely prompt for password for admin on chassis" >&2 + echo " -D detail_level - level of detail passed to host opacapture" >&2 + echo " 1-Local 2-Fabric 3-Fabric+FDB 4-Analysis" >&2 + echo " file - name for capture file [.tgz will be appended]" >&2 + echo " Environment:" >&2 + echo " HOSTS - list of hosts, used if -h option not supplied" >&2 + echo " CHASSIS - list of chassis, used if -C used and -h option not supplied" >&2 + echo " HOSTS_FILE - file containing list of hosts, used in absence of -f and -h" >&2 + echo " CHASSIS_FILE - file containing list of chassis, used in absence of -F and -H" >&2 + echo " UPLOADS_DIR - directory to upload to, used in absence of -d" >&2 + echo " FF_MAX_PARALLEL - when -p option is used, maximum concurrent operations" >&2 + echo " FF_CHASSIS_LOGIN_METHOD - how to login to chassis: telnet or ssh" >&2 + echo " FF_CHASSIS_ADMIN_PASSWORD - admin password for chassis, used in absence of -S" >&2 + echo "example:">&2 + echo " Operations on hosts" >&2 + echo " opacaptureall" >&2 + echo " opacaptureall mycapture" >&2 + echo " opacaptureall -h 'arwen elrond' 030127capture" >&2 + echo " Operations on chassis" >&2 + echo " opacaptureall -C" >&2 + echo " opacaptureall -C mycapture" >&2 + echo " opacaptureall -C -H 'chassis1 chassis2' 030127capture" >&2 + echo "For hosts:" >&2 + echo " opacapture will be run to create the specified capture file within ~root" >&2 + echo " on each host (with the .tgz suffix added). The files will be" >&2 + echo " uploaded and unpacked into a matching directory name within" >&2 + echo " upload_dir/hostname/ on the local system" >&2 + echo " default file name is hostcapture" >&2 + echo "For Chassis:" >&2 + echo " The capture CLI command will be run on each chassis and its output will be" >&2 + echo " saved to upload_dir/chassisname/file on the local system" >&2 + echo " default file name is chassiscapture" >&2 + echo "The uploaded captures will be combined into a tgz file with the file name" >&2 + echo "specified and the suffix .all.tgz added" >&2 + exit 0 +} + +Usage() +{ + echo "Usage: opacaptureall [-Cp] [-f hostfile] [-F chassisfile] [-S]" >&2 + echo " [-D detail_level] [file]" >&2 + echo " or" >&2 + echo " opacaptureall --help" >&2 + echo " --help - produce full help text" >&2 + echo " -C - perform capture against chassis, default is hosts" >&2 + echo " -p - perform capture upload in parallel on all hosts/chassis" >&2 + echo " -f hostfile - file with hosts in cluster, default is $CONFIG_DIR/opa/hosts" >&2 + echo " -F chassisfile - file with chassis in cluster" >&2 + echo " default is $CONFIG_DIR/opa/chassis" >&2 + echo " -S - securely prompt for password for admin on chassis or switch" >&2 + echo " -D detail_level - level of detail passed to host opacapture" >&2 + echo " file - name for capture file [.tgz will be appended]" >&2 + echo "example:">&2 + echo " Operations on hosts" >&2 + echo " opacaptureall" >&2 + echo " opacaptureall mycapture" >&2 + echo " Operations on chassis" >&2 + echo " opacaptureall -C" >&2 + echo " opacaptureall -C mycapture" >&2 + echo "For hosts:" >&2 + echo " opacapture will be run to create the specified capture file within ~root" >&2 + echo " on each host (with the .tgz suffix added). The files will be" >&2 + echo " uploaded and unpacked into a matching directory name within" >&2 + echo " uploads/hostname/ on the local system" >&2 + echo " default file name is hostcapture" >&2 + echo "For Chassis:" >&2 + echo " The capture CLI command will be run on each chassis and its output will be" >&2 + echo " saved to uploads/chassisname/file on the local system" >&2 + echo " default file name is chassiscapture" >&2 + echo "The uploaded captures will be combined into a tgz file with the file name" >&2 + echo "specified and the suffix .all.tgz added" >&2 + exit 2 +} + +if [ x"$1" = "x--help" ] +then + Usage_full +fi + +popt=n +chassis=0 +host=0 +Sopt=n +Dopt= +while getopts Cf:F:h:H:t:d:pD:S param +do + case $param in + C) + chassis=1;; + f) + host=1 + export HOSTS_FILE="$OPTARG";; + F) + chassis=1 + export CHASSIS_FILE="$OPTARG";; + h) + host=1 + export HOSTS="$OPTARG";; + H) + chassis=1 + CHASSIS="$OPTARG";; + t) + export PORTS_FILE="$OPTARG";; + d) + export UPLOADS_DIR="$OPTARG";; + p) + popt=y;; + D) + Dopt="-d $OPTARG";; + S) + Sopt=y;; + ?) + Usage;; + esac +done +shift $((OPTIND -1)) +if [[ $# -gt 1 ]] +then + Usage +fi +if [[ $(($chassis+$host)) -gt 1 ]] +then + echo "opacaptureall: conflicting arguments, more than one of host, and chassis specified" >&2 + Usage +fi +if [[ $(($chassis+$host)) -eq 0 ]] +then + host=1 +fi + +if [[ $# -gt 0 ]] +then + file="$1" +else + if [ $chassis -eq 0 ] + then + file=hostcapture + else + file=chassiscapture + fi +fi +if [ `dirname $file` != . ] +then + echo "filename for capture must not specify a directory" >&2 + Usage +fi +file=`basename $file .tgz` # remove .tgz suffix if given +host_local="" + +expand_host_capture() +{ +# $1 = hostname + if [ ! -f $UPLOADS_DIR/$1/${file}.tgz ] + then + echo "ERROR: capture and/or upload from $1 failed" + else + # chmod so we can remove + chmod -R u+w $UPLOADS_DIR/$1/$file >/dev/null 2>/dev/null + rm -rf $UPLOADS_DIR/$1/$file + mkdir -p $UPLOADS_DIR/$1/$file + ( cd $UPLOADS_DIR/$1/$file; tar xfz ../${file}.tgz; chmod -R u+w . ) + fi +} + +if [ $chassis -eq 0 ] +then + check_host_args opacaptureall + + # remove local host from $HOSTS so that opacmdall will not run opacapture locally + hosts_no_local="" + lc_myhostname=$(hostname -s|tr A-Z a-z) + for hostname in $HOSTS + do + lc_hostname=$(echo $hostname|tr A-Z a-z) + if [ "$lc_hostname" != "$lc_myhostname" -a "$lc_hostname" != "localhost" ] + then + hosts_no_local="$hosts_no_local $hostname" + else + host_local="$hostname" + fi + done + + # run capture in parallel since its time consuming + echo "Running capture on all non-local hosts ..." + /usr/sbin/opacmdall -p -h "$hosts_no_local" -u "root" "rm -f ~root/${file}.tgz; opacapture ~root/${file}.tgz" + + echo "Uploading capture from each host ..." + running=0 + captures= + for hostname in $hosts_no_local + do + captures="$captures $hostname/$file" + if [ "$popt" = "y" ] + then + if [ $running -ge $FF_MAX_PARALLEL ] + then + wait + running=0 + fi + ( + /usr/sbin/opauploadall -d $UPLOADS_DIR -u root -h "$hostname" ${file}.tgz . + expand_host_capture "$hostname" + ) & + running=$(( $running + 1)) + else + /usr/sbin/opauploadall -d $UPLOADS_DIR -u root -h "$hostname" ${file}.tgz . + expand_host_capture "$hostname" + fi + done +else + check_chassis_args opacaptureall + if [ "$Sopt" = y ] + then + echo -n "Password for admin on all chassis: " > /dev/tty + stty -echo < /dev/tty > /dev/tty + password= + read password < /dev/tty + stty echo < /dev/tty > /dev/tty + echo > /dev/tty + export FF_CHASSIS_ADMIN_PASSWORD="$password" + fi + + echo "Running capture on all chassis ..." + running=0 + captures= + for chassis in $CHASSIS + do + chassis=`strip_chassis_slots "$chassis"` + captures="$captures $chassis/$file" + if [ "$popt" = "y" ] + then + if [ $running -ge $FF_MAX_PARALLEL ] + then + wait + running=0 + fi + ( + mkdir -p $UPLOADS_DIR/$chassis + # filter out carriage returns + /usr/sbin/opacmdall -C -H "$chassis" -m 'End of Capture' "capture" |tr -d '\015' > $UPLOADS_DIR/$chassis/$file + if [ $? != 0 ] + then + echo "ERROR: capture from $chassis failed" + fi + ) & + running=$(( $running + 1)) + else + mkdir -p $UPLOADS_DIR/$chassis + # filter out carriage returns + /usr/sbin/opacmdall -C -H "$chassis" -m 'End of Capture' "capture" |tr -d '\015' > $UPLOADS_DIR/$chassis/$file + if [ $? != 0 ] + then + echo "ERROR: capture from $chassis failed" + fi + fi + done +fi + +if [ "$host_local" == "" -a "x$Dopt" != "x" ] +then + host_local=$(hostname -s) +fi +if [ "$host_local" != "" ] +then + echo "Running capture on local host ..." + rm -f $UPLOADS_DIR/$host_local/$file.tgz + mkdir -p $UPLOADS_DIR/$host_local + /usr/sbin/opacapture $Dopt $UPLOADS_DIR/$host_local/$file.tgz + expand_host_capture "$host_local" + captures="$captures $host_local/$file" +fi + +wait +echo "Combining captured files into $UPLOADS_DIR/$file.all.tgz ..." +(cd $UPLOADS_DIR; rm -rf $file.all.tgz; tar --format=gnu -czf $file.all.tgz $captures --warning=no-file-changed) +echo "Done." diff --git a/IbaTools/FastFabric/opachassisanalysis.sh b/IbaTools/FastFabric/opachassisanalysis.sh new file mode 100755 index 0000000..3aef303 --- /dev/null +++ b/IbaTools/FastFabric/opachassisanalysis.sh @@ -0,0 +1,258 @@ +#!/bin/bash +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] +# Analyze chassis for errors and/or changes relative to baseline + +# optional override of defaults +if [ -f /etc/opa/opafastfabric.conf ] +then + . /etc/opa/opafastfabric.conf +fi + +. /usr/lib/opa/tools/opafastfabric.conf.def + +. /usr/lib/opa/tools/ff_funcs + +trap "exit 1" SIGHUP SIGTERM SIGINT + +Usage_full() +{ + echo "Usage: opachassisanalysis [-b|-e] [-s] [-d dir] [-F chassisfile] [-H 'chassis']" >&2 + echo " or" >&2 + echo " opachassisanalysis --help" >&2 + echo "Check configuration and health for the Intel Omni-Path Fabric Chassis" >&2 + echo " --help - produce full help text" >&2 + echo " -b - baseline mode, default is compare/check mode" >&2 + echo " -e - evaluate health only, default is compare/check mode" >&2 + echo " -s - save history of failures (errors/differences)" >&2 + echo " -d dir - top level directory for saving baseline and history of failed checks" >&2 + echo " default is /var/usr/lib/opa/analysis" >&2 + echo " -F chassisfile - file with chassis in cluster" >&2 + echo " default is $CONFIG_DIR/opa/chassis" >&2 + echo " -H chassis - list of chassis to analyze" >&2 + echo " Environment:" >&2 + echo " CHASSIS - list of chassis, used if -F and -H options not supplied" >&2 + echo " CHASSIS_FILE - file containing list of chassis, used if -F and -H options">&2 + echo " not supplied" >&2 + echo " FF_ANALYSIS_DIR - top level directory for baselines and failed health checks" >&2 + echo " FF_CHASSIS_CMDS - list of commands to issue during analysis," >&2 + echo " unused if -e option supplied" >&2 + echo " FF_CHASSIS_HEALTH - single command to issue to check overall health during">&2 + echo " analysis, unused if -b option supplied" >&2 + echo "for example:" >&2 + echo " opachassisanalysis" >&2 + exit 0 +} + +Usage() +{ + echo "Usage: opachassisanalysis [-b|-e] [-s] [-F chassisfile]" >&2 + echo " or" >&2 + echo " opachassisanalysis --help" >&2 + echo " --help - produce full help text" >&2 + echo " -b - baseline mode, default is compare/check mode" >&2 + echo " -e - evaluate health only, default is compare/check mode" >&2 + echo " -s - save history of failures (errors/differences)" >&2 + echo " -F chassisfile - file with chassis in cluster" >&2 + echo " default is $CONFIG_DIR/opa/chassis" >&2 + echo "for example:" >&2 + echo " opachassisanalysis" >&2 + exit 2 +} + +if [ x"$1" = "x--help" ] +then + Usage_full +fi + +getbaseline=n +healthonly=n +savehistory=n +status=ok +while getopts besd:H:F: param +do + case $param in + b) getbaseline=y;; + e) healthonly=y;; + s) savehistory=y;; + d) export FF_ANALYSIS_DIR="$OPTARG";; + H) export CHASSIS="$OPTARG";; + F) export CHASSIS_FILE="$OPTARG";; + ?) Usage;; + esac +done +shift $((OPTIND -1)) +if [ $# -ge 1 ] +then + Usage +fi +if [ "$getbaseline" = y -a "$healthonly" = y ] +then + Usage +fi + +check_chassis_args opachassisanalysis + +#----------------------------------------------------------------- +# Set up file paths +#----------------------------------------------------------------- +baseline_dir="$FF_ANALYSIS_DIR/baseline" +latest_dir="$FF_ANALYSIS_DIR/latest" +export FF_CURTIME="${FF_CURTIME:-`date +%Y-%m-%d-%H:%M:%S`}" +failures_dir="$FF_ANALYSIS_DIR/$FF_CURTIME" + +#----------------------------------------------------------------- +save_failures() +{ + if [ "$savehistory" = y ] + then + mkdir -p $failures_dir + cp $* $failures_dir + echo "opachassisanalysis: Failure information saved to: $failures_dir/" >&2 + fi +} + +baseline=$baseline_dir/chassis +latest=$latest_dir/chassis + +# fake loop so we can use break/continue to skip to end of script +for loop in 1 +do + if [[ $getbaseline == n && $healthonly == n ]] + then + for cmd in $FF_CHASSIS_CMDS + do + if [ ! -f $baseline.$cmd ] + then + echo "opachassisanalysis: Error: Previous baseline run required" >&2 + status=bad + break + fi + done + if [ "$status" != "ok" ] + then + continue + fi + fi + + if [[ $healthonly == n ]] + then + # get a new snapshot + mkdir -p $latest_dir + + rm -rf $latest.* + + for cmd in $FF_CHASSIS_CMDS + do + /usr/sbin/opacmdall -C $cmd > $latest.$cmd 2>&1 + if [ $? != 0 ] + then + echo "opachassisanalysis: Error: Unable to issue chassis command. See $latest.$cmd" >&2 + status=bad + break + elif grep FAILED < $latest.$cmd > /dev/null + then + echo "opachassisanalysis: Warning: $cmd command failed for 1 or more chassis. See $latest.$cmd" >&2 + continue + fi + done + if [ "$status" != "ok" ] + then + continue + fi + + if [[ $getbaseline == y ]] + then + mkdir -p $baseline_dir + rm -rf $baseline.* + + for cmd in $FF_CHASSIS_CMDS + do + cp $latest.$cmd $baseline_dir + done + fi + fi + + if [[ $getbaseline == n ]] + then + # check chassis health/running + mkdir -p $latest_dir + + /usr/sbin/opacmdall -C "$FF_CHASSIS_HEALTH" > $latest.$FF_CHASSIS_HEALTH 2>&1 + if [ $? != 0 ] + then + echo "opachassisanalysis: Error: Unable to issue chassis command: $FF_CHASSIS_HEALTH. See $latest.$FF_CHASSIS_HEALTH" >&2 + status=bad + save_failures $latest.$FF_CHASSIS_HEALTH + elif grep FAILED < $latest.$FF_CHASSIS_HEALTH > /dev/null + then + echo "opachassisanalysis: Error: Chassis error. See $latest.$FF_CHASSIS_HEALTH" >&2 + status=bad + save_failures $latest.$FF_CHASSIS_HEALTH + fi + fi + + if [[ $getbaseline == n && $healthonly == n ]] + then + # compare to baseline + for cmd in $FF_CHASSIS_CMDS + do + $FF_DIFF_CMD $baseline.$cmd $latest.$cmd > $latest.$cmd.diff 2>&1 + if [ -s $latest.$cmd.diff ] + then + echo "opachassisanalysis: Chassis configuration changed. See $latest.$cmd.diff" >&2 + status=bad + save_failures $latest.$cmd $latest.$cmd.diff + else + rm -f $latest.$cmd.diff + fi + done + fi +done + +if [ "$status" != "ok" ] +then + if [[ $healthonly == n ]] + then + echo "opachassisanalysis: Possible Chassis errors or changes found" >&2 + else + echo "opachassisanalysis: Possible Chassis errors found" >&2 + fi + exit 1 +else + if [[ $getbaseline == n ]] + then + echo "opachassisanalysis: Chassis OK" + else + echo "opachassisanalysis: Baselined" + fi + exit 0 +fi diff --git a/IbaTools/FastFabric/opacmdall.sh b/IbaTools/FastFabric/opacmdall.sh new file mode 100755 index 0000000..fbeadaf --- /dev/null +++ b/IbaTools/FastFabric/opacmdall.sh @@ -0,0 +1,246 @@ +#!/bin/bash +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] +# run a command on all hosts or chassis + +# optional override of defaults +if [ -f /etc/opa/opafastfabric.conf ] +then + . /etc/opa/opafastfabric.conf +fi + +. /usr/lib/opa/tools/opafastfabric.conf.def + +TOOLSDIR=${TOOLSDIR:-/usr/lib/opa/tools} +BINDIR=${BINDIR:-/usr/sbin} + +. $TOOLSDIR/ff_funcs + +trap "exit 1" SIGHUP SIGTERM SIGINT + +Usage_full() +{ + echo "Usage: opacmdall [-CpqPS] [-f hostfile] [-F chassisfile] [-h 'hosts']" >&2 + echo " [-H 'chassis'] [-u user] [-m 'marker'] [-T timelimit]" >&2 + echo " 'cmd'" >&2 + echo " or" >&2 + echo " opacmdall --help" >&2 + echo " --help - produce full help text" >&2 + echo " -C - perform command against chassis, default is hosts" >&2 + echo " -p - run command in parallel on all hosts/chassis" >&2 + echo " -q - quiet mode, don't show command to execute" >&2 + echo " -f hostfile - file with hosts in cluster, default is $CONFIG_DIR/opa/hosts" >&2 + echo " -F chassisfile - file with chassis in cluster" >&2 + echo " default is $CONFIG_DIR/opa/chassis" >&2 + echo " -h hosts - list of hosts to execute command on" >&2 + echo " -H chassis - list of chassis to execute command on" >&2 + echo " -u user - user to perform cmd as" >&2 + echo " for hosts default is current user code" >&2 + echo " for chassis default is admin" >&2 + echo " -S - securely prompt for password for user on chassis" >&2 + echo " -m 'marker' - marker for end of chassis command output" >&2 + echo " if omitted defaults to chassis command prompt" >&2 + echo " this may be a regular expression" >&2 + echo " -T timelimit - timelimit in seconds when running host commands" >&2 + echo " default is -1 (infinite)" >&2 + echo " -P output hostname/chassis name as prefix to each output line" >&2 + echo " this can make script processing of output easier" >&2 + echo " Environment:" >&2 + echo " HOSTS - list of hosts, used if -h option not supplied" >&2 + echo " CHASSIS - list of chassis, used if -C used and -H and -F options not supplied" >&2 + echo " HOSTS_FILE - file containing list of hosts, used in absence of -f and -h" >&2 + echo " CHASSIS_FILE - file containing list of chassis, used in absence of -F and -H" >&2 + echo " FF_MAX_PARALLEL - when -p option is used, maximum concurrent operations" >&2 + echo " FF_SERIALIZE_OUTPUT - serialize output of parallel operations (yes or no)" >&2 + echo " FF_CHASSIS_LOGIN_METHOD - how to login to chassis: telnet or ssh" >&2 + echo " FF_CHASSIS_ADMIN_PASSWORD - password for chassis, used in absence of -S" >&2 + echo "for example:" >&2 + echo " Operations on hosts" >&2 + echo " opacmdall date" >&2 + echo " opacmdall 'uname -a'" >&2 + echo " opacmdall -h 'elrond arwen' date" >&2 + echo " HOSTS='elrond arwen' opacmdall date" >&2 + echo " Operations on chassis" >&2 + echo " opacmdall -C 'ismPortStats -noprompt'" >&2 + echo " opacmdall -C -H 'chassis1 chassis2' 'ismPortStats -noprompt'" >&2 + echo " CHASSIS='chassis1 chassis2' opacmdall -C 'ismPortStats -noprompt'" >&2 + exit 0 +} + +Usage() +{ + echo "Usage: opacmdall [-Cpq] [-f hostfile] [-F chassisfile] [-u user] [-S]" >&2 + echo " [-T timelimit] [-P] 'cmd'" >&2 + echo " or" >&2 + echo " opacmdall --help" >&2 + echo " --help - produce full help text" >&2 + echo " -C - perform command against chassis, default is hosts" >&2 + echo " -p - run command in parallel on all hosts/chassis" >&2 + echo " -q - quiet mode, don't show command to execute" >&2 + echo " -f hostfile - file with hosts in cluster, default is $CONFIG_DIR/opa/hosts" >&2 + echo " -F chassisfile - file with chassis in cluster" >&2 + echo " default is $CONFIG_DIR/opa/chassis" >&2 + echo " -u user - user to perform cmd as" >&2 + echo " for hosts default is current user code" >&2 + echo " for chassis default is admin, this is ignored" >&2 + echo " -S - securely prompt for password for user on chassis" >&2 + echo " -T timelimit - timelimit in seconds when running host commands" >&2 + echo " default is -1 (infinite)" >&2 + echo " -P - output hostname/chassis name as prefix to each output line" >&2 + echo " this can make script processing of output easier" >&2 + echo "for example:" >&2 + echo " Operations on hosts" >&2 + echo " opacmdall date" >&2 + echo " opacmdall 'uname -a'" >&2 + echo " Operations on chassis" >&2 + echo " opacmdall -C 'ismPortStats -noprompt'" >&2 + exit 2 +} + +if [ x"$1" = "x--help" ] +then + Usage_full +fi + +user=`id -u -n` +uopt=n +quiet=0 +host=0 +chassis=0 +parallel=0 +Sopt=n +marker="" +timelimit="-1" +output_prefix=0 +while getopts Cqph:H:f:F:u:Sm:T:P param +do + case $param in + C) + chassis=1;; + q) + quiet=1;; + p) + parallel=1;; + h) + host=1 + HOSTS="$OPTARG";; + H) + chassis=1 + CHASSIS="$OPTARG";; + f) + host=1 + HOSTS_FILE="$OPTARG";; + F) + chassis=1 + CHASSIS_FILE="$OPTARG";; + u) + uopt=y + user="$OPTARG";; + S) + Sopt=y;; + m) + marker="$OPTARG";; + T) + timelimit="$OPTARG";; + P) + output_prefix=1;; + ?) + Usage;; + esac +done +shift $((OPTIND -1)) + +if [ $# -ne 1 ] +then + Usage +fi +if [[ $(($chassis+$host)) -gt 1 ]] +then + echo "opacmdall: conflicting arguments, host and chassis both specified" >&2 + Usage +fi +if [[ $(($chassis+$host)) -eq 0 ]] +then + host=1 +fi +if [ x"$marker" != "x" -a $chassis -eq 0 ] +then + echo "opacmdall: -m option only applicable to chassis, ignored" >&2 +fi +if [ "$timelimit" -le 0 ] +then + timelimit=0 # some old versions of expect mistakenly treat -1 as a option +fi + +export TEST_MAX_PARALLEL="$FF_MAX_PARALLEL" +export TEST_TIMEOUT_MULT="$FF_TIMEOUT_MULT" +export CFG_LOGIN_METHOD="$FF_LOGIN_METHOD" +export CFG_PASSWORD="$FF_PASSWORD" +export CFG_ROOTPASS="$FF_ROOTPASS" +export CFG_CHASSIS_LOGIN_METHOD="$FF_CHASSIS_LOGIN_METHOD" +export CFG_CHASSIS_ADMIN_PASSWORD="$FF_CHASSIS_ADMIN_PASSWORD" +export TEST_SERIALIZE_OUTPUT="$FF_SERIALIZE_OUTPUT" + +if [ $chassis -eq 0 ] +then + check_host_args opacmdall + if [ $parallel -eq 0 ] + then + tclproc=hosts_run_cmd + else + tclproc=hosts_parallel_run_cmd + fi + $TOOLSDIR/tcl_proc $tclproc "$HOSTS" "$user" "$1" $quiet $timelimit $output_prefix +else + if [ "$uopt" = n ] + then + user=admin + fi + check_chassis_args opacmdall + if [ "$Sopt" = y ] + then + echo -n "Password for $user on all chassis: " > /dev/tty + stty -echo < /dev/tty > /dev/tty + password= + read password < /dev/tty + stty echo < /dev/tty > /dev/tty + echo > /dev/tty + export CFG_CHASSIS_ADMIN_PASSWORD="$password" + fi + # pardon my spelling need plural chassis that is distinct from singular + if [ $parallel -eq 0 ] + then + tclproc=chassises_run_cmd + else + tclproc=chassises_parallel_run_cmd + fi + $TOOLSDIR/tcl_proc $tclproc "$CHASSIS" "$user" "$1" $quiet "$marker" "$output_prefix" +fi diff --git a/IbaTools/FastFabric/opadownloadall.sh b/IbaTools/FastFabric/opadownloadall.sh new file mode 100755 index 0000000..4937e84 --- /dev/null +++ b/IbaTools/FastFabric/opadownloadall.sh @@ -0,0 +1,191 @@ +#!/bin/bash +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] + +# optional override of defaults +if [ -f /etc/opa/opafastfabric.conf ] +then + . /etc/opa/opafastfabric.conf +fi + +. /usr/lib/opa/tools/opafastfabric.conf.def + +. /usr/lib/opa/tools/ff_funcs + +trap "exit 1" SIGHUP SIGTERM SIGINT + +Usage_full() +{ + echo "Usage: opadownloadall [-rp] [-f hostfile] [-d download_dir] [-h 'hosts']" >&2 + echo " [-u user] source_file ... dest_file" >&2 + echo " or" >&2 + echo " opadownloadall --help" >&2 + echo " --help - produce full help text" >&2 + echo " -p - perform copy in parallel on all hosts" >&2 + echo " -r - recursive download of directories" >&2 + echo " -f hostfile - file with hosts in cluster, default is $CONFIG_DIR/opa/hosts" >&2 + echo " -h hosts - list of hosts to download to" >&2 + echo " -u user - user to perform copy to, default is current user code" >&2 + echo " -d download_dir - directory to download from, default is downloads" >&2 + echo " source_file - list of source files to copy" >&2 + echo " dest_file - destination for copy" >&2 + echo " If more than 1 source file, this must be a directory" >&2 + echo " Environment:" >&2 + echo " HOSTS - list of hosts, used if -h option not supplied" >&2 + echo " HOSTS_FILE - file containing list of hosts, used in absence of -f and -h" >&2 + echo " DOWNLOADS_DIR - directory to download from, used in absence of -d" >&2 + echo " FF_MAX_PARALLEL - when -p option is used, maximum concurrent operations" >&2 + echo "example:">&2 + echo " opadownloadall -h 'arwen elrond' irqbalance vncservers $CONFIG_DIR" >&2 + echo " opadownloadall -p irqbalance vncservers $CONFIG_DIR" >&2 + echo "user@ syntax cannot be used in filenames specified" >&2 + echo "A local directory within download_dir/ must exist for each hostname." >&2 + echo "Source file will be download_dir/hostname/source_file within the local system." >&2 + echo "To copy files from hosts in the cluster to this host use opauploadall." >&2 + exit 0 +} + +Usage() +{ + echo "Usage: opadownloadall [-rp] [-f hostfile] [-d download_dir]" >&2 + echo " source_file ... dest_file" >&2 + echo " or" >&2 + echo " opadownloadall --help" >&2 + echo " --help - produce full help text" >&2 + echo " -p - perform copy in parallel on all hosts" >&2 + echo " -r - recursive download of directories" >&2 + echo " -f hostfile - file with hosts in cluster, default is $CONFIG_DIR/opa/hosts" >&2 + echo " -d download_dir - directory to download from, default is downloads" >&2 + echo " source_file - list of source files to copy" >&2 + echo " dest_file - destination for copy" >&2 + echo " If more than 1 source file, this must be a directory" >&2 + echo "example:">&2 + echo " opadownloadall -p irqbalance vncservers $CONFIG_DIR" >&2 + echo "user@ syntax cannot be used in filenames specified" >&2 + echo "A local directory within downloads/ must exist for each hostname." >&2 + echo "Source file will be downloads/hostname/source_file within the local system." >&2 + echo "To copy files from hosts in the cluster to this host use opauploadall." >&2 + exit 2 +} + +if [ x"$1" = "x--help" ] +then + Usage_full +fi + +user=`id -u -n` +opts= +popt=n +while getopts f:d:h:u:rp param +do + case $param in + f) + HOSTS_FILE="$OPTARG";; + d) + DOWNLOADS_DIR="$OPTARG";; + h) + HOSTS="$OPTARG";; + u) + user="$OPTARG";; + r) + opts="$opts -r";; + p) + opts="$opts -q" + popt=y;; + ?) + Usage;; + esac +done +shift $((OPTIND -1)) +if [ $# -lt 2 ] +then + Usage +fi + +check_host_args opadownloadall + +# remove last name from the list +files= +dest= +for file in "$@" +do + if [ ! -z "$dest" ] + then + files="$files $dest" + fi + dest="$file" +done + +running=0 +pids="" +stat=0 +for hostname in $HOSTS +do + src_files= + for file in $files + do + src_files="$src_files $DOWNLOADS_DIR/$hostname/$file" + done + + if [ "$popt" = "y" ] + then + if [ $running -ge $FF_MAX_PARALLEL ] + then + for pid in $pids; do + wait $pid + if [ "$?" -ne 0 ]; then + stat=1 + fi + done + pids="" + running=0 + fi + echo "scp $opts $src_files $user@[$hostname]:$dest" + scp $opts $src_files $user@\[$hostname\]:$dest & + pid=$! + pids="$pids $pid" + running=$(( $running + 1)) + else + echo "scp $opts $src_files $user@[$hostname]:$dest" + scp $opts $src_files $user@\[$hostname\]:$dest + if [ "$?" -ne 0 ]; then + stat=1 + fi + fi +done + +for pid in $pids; do + wait $pid + if [ "$?" -ne 0 ]; then + stat=1 + fi +done +exit $stat diff --git a/IbaTools/FastFabric/opaesmanalysis.sh b/IbaTools/FastFabric/opaesmanalysis.sh new file mode 100755 index 0000000..c7ad7ca --- /dev/null +++ b/IbaTools/FastFabric/opaesmanalysis.sh @@ -0,0 +1,322 @@ +#!/bin/bash +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] +# Analyze Embedded SMs for errors and/or changes relative to baseline + +# optional override of defaults +if [ -f /etc/opa/opafastfabric.conf ] +then + . /etc/opa/opafastfabric.conf +fi + +. /usr/lib/opa/tools/opafastfabric.conf.def + +. /usr/lib/opa/tools/ff_funcs + +trap "exit 1" SIGHUP SIGTERM SIGINT + +Usage_full() +{ + echo "Usage: opaesmanalysis [-b|-e] [-s] [-d dir] [-G esmchassisfile]" >&2 + echo " [-E 'esmchassis']" >&2 + echo " or" >&2 + echo " opaesmanalysis --help" >&2 + echo " --help - produce full help text" >&2 + echo " -b - baseline mode, default is compare/check mode" >&2 + echo " -e - evaluate health only, default is compare/check mode" >&2 + echo " -s - save history of failures (errors/differences)" >&2 + echo " -d dir - top level directory for saving baseline and history of failed checks" >&2 + echo " default is /var/usr/lib/opa/analysis" >&2 + echo " -G esmchassisfile - file with SM chassis in cluster" >&2 + echo " default is $CONFIG_DIR/opa/esm_chassis" >&2 + echo " -E esmchassis - list of SM chassis to analyze" >&2 + echo " Environment:" >&2 + echo " ESM_CHASSIS - list of SM chassis, used if -G and -E not supplied" >&2 + echo " ESM_CHASSIS_FILE - file containing list of SM chassis, used if -G and -E not" >&2 + echo " supplied" >&2 + echo " FF_ANALYSIS_DIR - top level directory for baselines and failed health checks" >&2 + echo "for example:" >&2 + echo " opaesmanalysis" >&2 + exit 0 +} + +Usage() +{ + echo "Usage: opaesmanalysis [-b|-e] [-s] [-G esmchassisfile]" >&2 + echo " or" >&2 + echo " opaesmanalysis --help" >&2 + echo " --help - produce full help text" >&2 + echo " -b - baseline mode, default is compare/check mode" >&2 + echo " -e - evaluate health only, default is compare/check mode" >&2 + echo " -s - save history of failures (errors/differences)" >&2 + echo " -G esmchassisfile - file with SM chassis in cluster" >&2 + echo " default is $CONFIG_DIR/opa/esm_chassis" >&2 + echo "for example:" >&2 + echo " opaesmanalysis" >&2 + exit 2 +} + +if [ x"$1" = "x--help" ] +then + Usage_full +fi + +getbaseline=n +healthonly=n +savehistory=n +status=ok +while getopts besd:E:G: param +do + case $param in + b) getbaseline=y;; + e) healthonly=y;; + s) savehistory=y;; + d) export FF_ANALYSIS_DIR="$OPTARG";; + E) export ESM_CHASSIS="$OPTARG";; + G) export ESM_CHASSIS_FILE="$OPTARG";; + ?) Usage;; + esac +done +shift $((OPTIND -1)) +if [ $# -ge 1 ] +then + Usage +fi +if [ "$getbaseline" = y -a "$healthonly" = y ] +then + Usage +fi + +check_esm_chassis_args opaesmanalysis + +#----------------------------------------------------------------- +# Set up file paths +#----------------------------------------------------------------- +baseline_dir="$FF_ANALYSIS_DIR/baseline" +latest_dir="$FF_ANALYSIS_DIR/latest" +export FF_CURTIME="${FF_CURTIME:-`date +%Y-%m-%d-%H:%M:%S`}" +failures_dir="$FF_ANALYSIS_DIR/$FF_CURTIME" + +#----------------------------------------------------------------- +save_failures() +{ + if [ "$savehistory" = y ] + then + mkdir -p $failures_dir + cp $* $failures_dir + echo "opaesmanalysis: Failure information saved to: $failures_dir/" >&2 + fi +} + +baseline=$baseline_dir/esm +latest=$latest_dir/esm + +# fake loop so we can use break/continue to skip to end of script +for loop in 1 +do + if [[ $getbaseline == n && $healthonly == n ]] + then + for cmd in $FF_ESM_CMDS + do + if [ ! -f $baseline.$cmd ] + then + echo "opaesmanalysis: Error: Previous baseline run required" >&2 + status=bad + break + fi + done + for chassis in $ESM_CHASSIS + do + chassis=`strip_chassis_slots "$chassis"` + if [ ! -f $baseline.$chassis.smConfig ] + then + echo "opaesmanalysis: Error: Previous baseline run required" >&2 + status=bad + break + fi + done + if [ "$status" != "ok" ] + then + continue + fi + fi + + if [[ $healthonly == n ]] + then + # get a new snapshot + mkdir -p $latest_dir + + # cleanup old snapshot + rm -rf $latest.* test.log test.res test_tmp* save_tmp temp + + for cmd in $FF_ESM_CMDS + do + if [ "$cmd" == "smConfig" ] + then + /usr/sbin/opacmdall -C -H "$ESM_CHASSIS" "smConfig query" > $latest.$cmd 2>&1 + else + /usr/sbin/opacmdall -C -H "$ESM_CHASSIS" $cmd > $latest.$cmd 2>&1 + fi + + if [ $? != 0 ] + then + echo "opaesmanalysis: Error: Unable to issue chassis command. See $latest.$cmd" >&2 + status=bad + break + elif grep FAILED < $latest.$cmd > /dev/null + then + echo "opaesmanalysis: Warning: $cmd command failed for 1 or more chassis. See $latest.$cmd" >&2 + continue + fi + done + for chassis in $ESM_CHASSIS + do + chassis=`strip_chassis_slots "$chassis"` + /usr/sbin/opacmdall -C -H "$chassis" "showCapability -key smConfig" > $latest.$chassis.smConfig 2>&1 + if [ $? != 0 ] + then + echo "opaesmanalysis: Error: Unable to issue chassis command. See $latest.$chassis.smConfig" >&2 + status=bad + elif ! egrep 'FAILED|unavailable' < $latest.$chassis.smConfig >/dev/null + then + # supports XML config for esm + ( + cd $latest_dir + mkdir temp + rm -rf test.log test.res test_tmp* save_tmp + export FF_RESULT_DIR=. + /usr/sbin/opachassisadmin -H "$chassis" -d $latest_dir/temp fmgetconfig > $latest.$chassis.fmgetconfig 2>&1 + if [ $? != 0 ] || grep FAILED < test.res >/dev/null + then + cat test.log >> $latest.$chassis.fmgetconfig 2>/dev/null + echo "opaesmanalysis: Error: Unable to get FM config file. See $latest.$chassis.fmgetconfig" + status=bad + else + mv $latest_dir/temp/$chassis/opafm.xml $latest.$chassis.opafm.xml + fi + rm -rf test.log test.res test_tmp* save_tmp temp + ) + fi + done + if [ "$status" != "ok" ] + then + continue + fi + + if [[ $getbaseline == y ]] + then + mkdir -p $baseline_dir + rm -rf $baseline.* + for cmd in $FF_ESM_CMDS + do + cp $latest.$cmd $baseline_dir + done + for chassis in $ESM_CHASSIS + do + chassis=`strip_chassis_slots "$chassis"` + cp $latest.$chassis.smConfig $baseline_dir + [ -e $latest.$chassis.fmgetconfig ] && cp $latest.$chassis.fmgetconfig $baseline_dir + [ -e $latest.$chassis.opafm.xml ] && cp $latest.$chassis.opafm.xml $baseline_dir + done + fi + fi + + if [[ $getbaseline == n ]] + then + # check SM health/running + mkdir -p $latest_dir + + /usr/sbin/opacmdall -C -H "$ESM_CHASSIS" 'smControl status' > $latest.smstatus 2>&1 + if [ $? != 0 ] + then + echo "opaesmanalysis: Error: Unable to issue chassis command. See $latest.smstatus" >&2 + status=bad + save_failures $latest.smstatus + elif grep stopped < $latest.smstatus > /dev/null + then + echo "opaesmanalysis: Error: SM(s) not running. See $latest.smstatus" >&2 + status=bad + save_failures $latest.smstatus + fi + fi + + if [[ $getbaseline == n && $healthonly == n ]] + then + # compare to baseline + for cmd in $FF_ESM_CMDS + do + $FF_DIFF_CMD $baseline.$cmd $latest.$cmd > $latest.$cmd.diff 2>&1 + if [ -s $latest.$cmd.diff ] + then + echo "opaesmanalysis: SM configuration changed. See $latest.$cmd.diff" >&2 + status=bad + save_failures $latest.$cmd $latest.$cmd.diff + else + rm -f $latest.$cmd.diff + fi + done + for chassis in $ESM_CHASSIS + do + chassis=`strip_chassis_slots "$chassis"` + if [ -f $latest.$chassis.opafm.xml -o -f $baseline.$chassis.opafm.xml ] + then + $FF_DIFF_CMD $baseline.$chassis.opafm.xml $latest.$chassis.opafm.xml > $latest.$chassis.opafm.xml.diff 2>&1 + if [ -s $latest.$chassis.opafm.xml.diff ] + then + echo "opaesmanalysis: SM configuration changed. See $latest.$chassis.opafm.xml.diff" >&2 + status=bad + save_failures $latest.$chassis.opafm.xml $latest.$chassis.opafm.xml.diff + else + rm -f $latest.$chassis.opafm.xml.diff + fi + fi + done + fi +done + +if [ "$status" != "ok" ] +then + if [[ $healthonly == n ]] + then + echo "opaesmanalysis: Possible SM errors or changes found" >&2 + else + echo "opaesmanalysis: Possible SM errors found" >&2 + fi + exit 1 +else + if [[ $getbaseline == n ]] + then + echo "opaesmanalysis: SM(s) OK" + else + echo "opaesmanalysis: Baselined" + fi + exit 0 +fi diff --git a/IbaTools/FastFabric/opaexpandfile.sh b/IbaTools/FastFabric/opaexpandfile.sh new file mode 100755 index 0000000..0701353 --- /dev/null +++ b/IbaTools/FastFabric/opaexpandfile.sh @@ -0,0 +1,77 @@ +#!/bin/bash +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] + +# expand a hosts, chassis or switches file by following includes and +# removing comments + +# optional override of defaults +if [ -f /etc/opa/opafastfabric.conf ] +then + . /etc/opa/opafastfabric.conf +fi + +. /usr/lib/opa/tools/opafastfabric.conf.def + +. /usr/lib/opa/tools/ff_funcs + +trap "exit 1" SIGHUP SIGTERM SIGINT + +Usage() +{ + echo "Usage: opaexpandfile file" >&2 + echo " or" >&2 + echo " opaexpandfile --help" >&2 + echo " --help - produce full help text" >&2 + echo " file - FastFabric hosts, chassis or opaswitches file to expand by following" >&2 + echo " includes and removing comments" >&2 + echo "example:">&2 + echo " opaexpandfile allhosts" >&2 + exit 0 +} + +if [ x"$1" = "x--help" ] +then + Usage +fi + +if [ $# -ne 1 ] +then + Usage +fi +file="$1" + +file=`resolve_file "opaexpandfile" "$file"` +if [ "$file" = "" ] +then + Usage +fi +expand_file "opaexpandfile" "$file" diff --git a/IbaTools/FastFabric/opafabricanalysis.sh b/IbaTools/FastFabric/opafabricanalysis.sh new file mode 100755 index 0000000..c01b0e5 --- /dev/null +++ b/IbaTools/FastFabric/opafabricanalysis.sh @@ -0,0 +1,355 @@ +#!/bin/bash +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] +# Analyze fabric for errors and/or changes relative to baseline + +# optional override of defaults +if [ -f /etc/opa/opafastfabric.conf ] +then + . /etc/opa/opafastfabric.conf +fi + +. /usr/lib/opa/tools/opafastfabric.conf.def + +. /usr/lib/opa/tools/ff_funcs + +trap "exit 1" SIGHUP SIGTERM SIGINT + +Usage_full() +{ + echo "Usage: opafabricanalysis [-b|-e] [-s] [-d dir] [-c file] [-t portsfile]" >&2 + echo " [-p ports] [-T topology_input]" >&2 + echo " or" >&2 + echo " opafabricanalysis --help" >&2 + echo " --help - produce full help text" >&2 + echo " -b - baseline mode, default is compare/check mode" >&2 + echo " -e - evaluate health only, default is compare/check mode" >&2 + echo " -s - save history of failures (errors/differences)" >&2 + echo " -d dir - top level directory for saving baseline and history of failed checks" >&2 + echo " default is /var/usr/lib/opa/analysis" >&2 + echo " -c file - error thresholds config file" >&2 + echo " default is $CONFIG_DIR/opa/opamon.conf" >&2 + echo " -t portsfile - file with list of local HFI ports used to access" >&2 + echo " fabric(s) for analysis, default is $CONFIG_DIR/opa/ports" >&2 + echo " -p ports - list of local HFI ports used to access fabric(s) for analysis" >&2 + echo " default is 1st active port" >&2 + echo " This is specified as hfi:port" >&2 + echo " 0:0 = 1st active port in system" >&2 + echo " 0:y = port y within system" >&2 + echo " x:0 = 1st active port on HFI x" >&2 + echo " x:y = HFI x, port y" >&2 + echo " The first HFI in the system is 1. The first port on an HFI is 1." >&2 + echo " -T topology_input - name of a topology input file to use." >&2 + echo " Any %P markers in this filename will be replaced with the" >&2 + echo " hfi:port being operated on (such as 0:0 or 1:2)" >&2 + echo " default is $CONFIG_DIR/opa/topology.%P.xml" >&2 + echo " if NONE is specified, will not use any topology_input files" >&2 + echo " See opareport for more information on topology_input files" >&2 + echo " Environment:" >&2 + echo " PORTS - list of ports, used in absence of -t and -p" >&2 + echo " PORTS_FILE - file containing list of ports, used in absence of -t and -p" >&2 + echo " FF_ANALYSIS_DIR - top level directory for baselines and failed health checks" >&2 + echo " FF_TOPOLOGY_FILE - file containing topology_input, used in absence of -T" >&2 + echo "for example:" >&2 + echo " opafabricanalysis" >&2 + echo " opafabricanalysis -p '1:1 1:2 2:1 2:2'" >&2 + exit 0 +} + +Usage() +{ + echo "Usage: opafabricanalysis [-b|-e] [-s]" >&2 + echo " or" >&2 + echo " opafabricanalysis --help" >&2 + echo " --help - produce full help text" >&2 + echo " -b - baseline mode, default is compare/check mode" >&2 + echo " -e - evaluate health only, default is compare/check mode" >&2 + echo " -s - save history of failures (errors/differences)" >&2 + echo "for example:" >&2 + echo " opafabricanalysis" >&2 + exit 2 +} + +if [ x"$1" = "x--help" ] +then + Usage_full +fi + +getbaseline=n +healthonly=n +savehistory=n +configfile=$CONFIG_DIR/opa/opamon.conf +status=ok +while getopts besd:c:p:t:T: param +do + case $param in + b) getbaseline=y;; + e) healthonly=y;; + s) savehistory=y;; + d) export FF_ANALYSIS_DIR="$OPTARG";; + c) configfile="$OPTARG";; + p) export PORTS="$OPTARG";; + t) export PORTS_FILE="$OPTARG";; + T) export FF_TOPOLOGY_FILE="$OPTARG";; + ?) Usage;; + esac +done +shift $((OPTIND -1)) +if [ $# -ge 1 ] +then + Usage +fi +if [ "$getbaseline" = y -a "$healthonly" = y ] +then + Usage +fi + +check_ports_args opafabricanalysis + +#----------------------------------------------------------------- +# Set up file paths +#----------------------------------------------------------------- +baseline_dir="$FF_ANALYSIS_DIR/baseline" +latest_dir="$FF_ANALYSIS_DIR/latest" +export FF_CURTIME="${FF_CURTIME:-`date +%Y-%m-%d-%H:%M:%S`}" +failures_dir="$FF_ANALYSIS_DIR/$FF_CURTIME" + +#----------------------------------------------------------------- +save_failures() +{ + if [ "$savehistory" = y ] + then + mkdir -p $failures_dir + cp $* $failures_dir + echo "opafabricanalysis: Failure information saved to: $failures_dir/" >&2 + fi +} + +for hfi_port in $PORTS +do + hfi=$(expr $hfi_port : '\([0-9]*\):[0-9]*') + port=$(expr $hfi_port : '[0-9]*:\([0-9]*\)') + if [ "$hfi" = "" -o "$port" = "" ] + then + echo "opafabricanalysis: Error: Invalid port specification: $hfi_port" >&2 + status=bad + continue + fi + resolve_topology_file opafabricanalysis "$hfi:$port" + topt="" + if [ "$TOPOLOGY_FILE" != "" ] + then + topt="-T $TOPOLOGY_FILE" + fi + + + baseline=$baseline_dir/fabric.$hfi_port + latest=$latest_dir/fabric.$hfi_port + + if [ "$port" -eq 0 ] + then + port_opts="-h $hfi" # default port to 1st active + else + port_opts="-h $hfi -p $port" + fi + + if [[ $getbaseline == n && $healthonly == n ]] + then + if [ ! -f $baseline.links -o ! -f $baseline.comps ] + then + echo "opafabricanalysis: Port $hfi_port Error: Previous baseline run required" >&2 + status=bad + continue + fi + fi + + if [[ $healthonly == n ]] + then + # get a new snapshot + mkdir -p $latest_dir + rm -rf $latest.* + + /usr/sbin/opareport $port_opts -o snapshot -q > $latest.snapshot.xml 2> $latest.snapshot.stderr + if [ $? != 0 ] + then + echo "opafabricanalysis: Port $hfi_port Error: Unable to access fabric. See $latest.snapshot.stderr" >&2 + status=bad + save_failures $latest.snapshot.xml $latest.snapshot.stderr + continue + fi + + /usr/sbin/opareport -X $latest.snapshot.xml -q -o links -P > $latest.links 2> $latest.links.stderr + if [ $? != 0 ] + then + echo "opafabricanalysis: Port $hfi_port Error: Unable to analyze fabric snapshot. See $latest.links.stderr" >&2 + status=bad + save_failures $latest.snapshot.xml $latest.links $latest.links.stderr + continue + fi + + /usr/sbin/opareport -X $latest.snapshot.xml -q -o comps -P -d 4 > $latest.comps 2> $latest.comps.stderr + if [ $? != 0 ] + then + echo "opafabricanalysis: Port $hfi_port Error: Unable to analyze fabric snapshot. See $latest.comps.stderr" >&2 + status=bad + save_failures $latest.snapshot.xml $latest.comps $latest.comps.stderr + continue + fi + + if [[ $getbaseline == y ]] + then + mkdir -p $baseline_dir + rm -rf $baseline.* + cp $latest.snapshot.xml $latest.links $latest.comps $baseline_dir + fi + fi + + if [[ $getbaseline == n ]] + then + # check fabric health + mkdir -p $latest_dir + + /usr/sbin/opareport $port_opts $topt -c "$configfile" -q $FF_FABRIC_HEALTH > $latest.errors 2>$latest.errors.stderr + if [ $? != 0 ] + then + echo "opafabricanalysis: Port $hfi_port Error: Unable to access fabric. See $latest.errors.stderr" >&2 + status=bad + save_failures $latest.errors $latest.errors.stderr + elif grep 'Errors found' < $latest.errors | grep -v ' 0 Errors found' > /dev/null + then + echo "opafabricanalysis: Port $hfi_port: Fabric possible errors found. See $latest.errors" >&2 + status=bad + save_failures $latest.errors $latest.errors.stderr + fi + fi + + if [[ $getbaseline == n && $healthonly == n ]] + then + # compare to baseline + + # cleanup old files + rm -f $latest.links.changes $latest.links.changes.stderr + rm -f $latest.links.rebase $latest.links.rebase.stderr + rm -f $latest.comps.changes $latest.comps.changes.stderr + rm -f $latest.comps.rebase $latest.comps.rebase.stderr + + base_comps=$baseline.comps + $FF_DIFF_CMD $baseline.links $latest.links > $latest.links.diff 2>&1 + if [ -s $latest.links.diff ] + then + if [ ! -e $baseline.snapshot.xml ] + then + echo "opafabricanalysis: Port $hfi_port: New baseline required" >&2 + else + # see if change is only due to new FF version + /usr/sbin/opareport -X $baseline.snapshot.xml -q -o links -P > $latest.links.rebase 2> $latest.links.rebase.stderr + if [ $? != 0 ] + then + # there are other issues + rm -f $latest.links.rebase $latest.links.rebase.stderr + else + cmp -s $latest.links $latest.links.rebase >/dev/null 2>&1 + if [ $? == 0 ] + then + # change is due to FF version + # use new output format + echo "opafabricanalysis: Port $hfi_port: New baseline recommended" >&2 + $FF_DIFF_CMD $latest.links.rebase $latest.links > $latest.links.diff 2>&1 + /usr/sbin/opareport -X $baseline.snapshot.xml -q -o comps -P -d 4 > $latest.comps.rebase 2> $latest.comps.rebase.stderr + if [ $? != 0 ] + then + # there are other issues + rm -f $latest.comps.rebase $latest.comps.rebase.stderr + else + base_comps=$latest.comps.rebase + fi + fi + fi + fi + fi + if [ -s $latest.links.diff -a -e $baseline.snapshot.xml ] + then + # use the baseline snapshot to generate an XML links report + # we then use that as the expect topology and compare the + # latest snapshot to the expected topology to generate a more + # precise and understandable summary of the differences + ( /usr/sbin/opareport -X $baseline.snapshot.xml $topt -q -o links -P -x| + /usr/sbin/opareport -T - -X $latest.snapshot.xml -q -o verifylinks -P > $latest.links.changes ) 2> $latest.links.changes.stderr + fi + + $FF_DIFF_CMD $base_comps $latest.comps > $latest.comps.diff 2>&1 + if [ -s $latest.comps.diff -a -e $baseline.snapshot.xml ] + then + # use the baseline snapshot to generate an XML nodes and SMs report + # we then use that as the expect topology and compare the + # latest snapshot to the expected topology to generate a more + # precise and understandable summary of the differences + ( /usr/sbin/opareport -X $baseline.snapshot.xml $topt -q -o brnodes -d 1 -P -x| + /usr/sbin/opareport -T - -X $latest.snapshot.xml -q -o verifynodes -o verifysms -P > $latest.comps.changes ) 2> $latest.comps.changes.stderr + fi + + if [ -s $latest.links.changes -o -s $latest.comps.changes ] + then + echo "opafabricanalysis: Port $hfi_port: Fabric configuration changed. See $latest.links.changes, $latest.comps.changes and/or $latest.comps.diff" >&2 + status=bad + files="$latest.links $latest.links.diff $latest.comps $latest.comps.diff" + [ -e $latest.links.changes ] && files="$files $latest.links.changes $latest.links.changes.stderr" + [ -e $latest.comps.changes ] && files="$files $latest.comps.changes $latest.comps.changes.stderr" + save_failures $files + elif [ -s $latest.links.diff -o -s $latest.comps.diff ] + then + echo "opafabricanalysis: Port $hfi_port: Fabric configuration changed. See $latest.links.diff and/or $latest.comps.diff" >&2 + status=bad + save_failures $latest.links $latest.links.diff $latest.comps $latest.comps.diff + else + rm -f $latest.links.diff $latest.links.changes $latest.links.changes.stderr $latest.comps.diff $latest.comps.changes $latest.comps.changes.stderr + fi + fi +done + +if [ "$status" != "ok" ] +then + if [[ $healthonly == n ]] + then + echo "opafabricanalysis: Possible fabric errors or changes found" >&2 + else + echo "opafabricanalysis: Possible fabric errors found" >&2 + fi + exit 1 +else + if [[ $getbaseline == n ]] + then + echo "opafabricanalysis: Fabric(s) OK" + else + echo "opafabricanalysis: Baselined" + fi + exit 0 +fi diff --git a/IbaTools/FastFabric/opafastfabric.conf.LINUX.OPENIB b/IbaTools/FastFabric/opafastfabric.conf.LINUX.OPENIB new file mode 100755 index 0000000..96f7627 --- /dev/null +++ b/IbaTools/FastFabric/opafastfabric.conf.LINUX.OPENIB @@ -0,0 +1,264 @@ +#!/bin/bash +# [ICS VERSION STRING: unknown] +# This is a bash sourced config file which defines variables used in +# fast fabric tools. Command line arguments will override these settings. +# Assignments should be scripted such that this file does not override +# exported environment settings, as shown in the defaults below + +if [ "$CONFIG_DIR" = "" ] +then + CONFIG_DIR=/etc + export CONFIG_DIR +fi + +# Override default location for HOSTS_FILE +export HOSTS_FILE=${HOSTS_FILE:-$CONFIG_DIR/opa/hosts} + +# Override default location for CHASSIS_FILE +export CHASSIS_FILE=${CHASSIS_FILE:-$CONFIG_DIR/opa/chassis} + +# Override default location for ESM_CHASSIS_FILE +export ESM_CHASSIS_FILE=${ESM_CHASSIS_FILE:-$CONFIG_DIR/opa/esm_chassis} + +# Override default location for OPASWITCHES_FILE +export OPASWITCHES_FILE=${OPASWITCHES_FILE:-$CONFIG_DIR/opa/switches} + +# Override default location for PORTS_FILE +export PORTS_FILE=${PORTS_FILE:-$CONFIG_DIR/opa/ports} + +# Default suffix for IPoIB host names +# the special value "NONE" is used to indicate a value of "" +# this value can be used in ff_host_basename_to_ipoib and ff_host_basename +# below to convert between IPoIB and Ethernet hostnames +export FF_IPOIB_SUFFIX=${FF_IPOIB_SUFFIX:--opa} +# Alternatively a IPoIB prefix can be provided, commented out +# examples in ff_host_basename and ff_host_basename can be enabled if desired +export FF_IPOIB_PREFIX=${FF_IPOIB_PREFIX:-opa-} + +# Default management host +export MGMT_HOST=${MGMT_HOST:-localhost} + + +# The shell functions below are only defined if no existing function/command +# with given name, hence allowing use of shell functions or creation of a +# command for this operation + +# shell Function to convert a basic hostname into an IPoIB hostname +# if FF_IPOIB_SUFFIX is "", this should return $1 unmodified +# such that commands can be used with -i "" to skip IPoIB operations +# (special value of NONE will be converted to "" before this is called) +if ! type ff_host_basename_to_ipoib >/dev/null 2>/dev/null +then + function ff_host_basename_to_ipoib() + { + # $1 = hostname provided + echo "$1$FF_IPOIB_SUFFIX" + # comment out line above and uncomment line below if using prefixes + #echo "$FF_IPOIB_PREFIX$1" + } +fi + +# shell Function to convert a hostname into a basic hostname +# (eg. remove IPoIB suffix, etc) should match result of "hostname -s" on host +# if FF_IPOIB_SUFFIX is "", this should return $1 unmodified +# such that commands can be used with -i "" to skip IPoIB operations +# (special value of NONE will be converted to "" before this is called) +if ! type ff_host_basename >/dev/null 2>/dev/null +then + function ff_host_basename() + { + # $1 = hostname provided (could be ethernet or IPoIB name) + echo "$1"|sed -e "s/$FF_IPOIB_SUFFIX\$//" + # comment out line above and uncomment line below if using prefixes + #echo "$1"|sed -e "s/^$FF_IPOIB_PREFIX//" + } +fi + +# input to opahostadmin configipoib indicating which mode to +# use for IP configuration of ipoib interface, valid values are one of +# static, dhcp, auto +# for auto, if not found in resolver, will configure static, otherwise uses dhcp +export FF_IPOIB_CONFIG=${FF_IPOIB_CONFIG:-static} + +# IP netmask for IPoIB subnet [-m option], only used for static +# if "" default will be determined based on class of IP address [A, B, C] +export FF_IPOIB_NETMASK=${FF_IPOIB_NETMASK:-} + +# IPOIB Connected Mode. Legal values are "yes" (connected) and "no" (datagram). +export FF_IPOIB_CONNECTED=${FF_IPOIB_CONNECTED:-no} + +# Maximum parallel processes for opahostadmin, opachassisadmin, opaswitchadmin +# and -p option on other commands +# set to 1 to avoid parallel execution +# 1000 is a reasonable default. If a larger number is needed, it is recommended +# consideration is given to ulimit -u, memory consumption by many scp/ssh sessions, +# and the total number of TCP connections the system can handle. +export FF_MAX_PARALLEL=${FF_MAX_PARALLEL:-1000} + +# If the systems are slow for some reason, this can be used to provide a +# multiplier for all timeouts in opahostadmin, opachassisadmin, opaswitchadmin +export FF_TIMEOUT_MULT=${FF_TIMEOUT_MULT:-2} + +# where to put result files from FastFabric runs of +# opahostadmin, opachassisadmin, opaswitchadmin +#export FF_RESULT_DIR=${FF_RESULT_DIR:-.} +export FF_RESULT_DIR=${FF_RESULT_DIR:-$HOME} + +# IntelOPA product to install during opahostadmin load and upgrade +export FF_PRODUCT=${FF_PRODUCT:-IntelOPA-Basic.`cat /usr/lib/opa/tools/osid_wrapper`} + +# IntelOPA product version to install during opahostadmin load and upgrade +export FF_PRODUCT_VERSION=${FF_PRODUCT_VERSION:-`cat /etc/opa/version_wrapper 2>/dev/null`} + +# IntelOPA packages to install during opahostadmin load [-P option] +#export FF_PACKAGES=${FF_PACKAGES:-oftools ipoib mpi pgas} +#export FF_PACKAGES=${FF_PACKAGES:-oftools ipoib psm_mpi pgas} +export FF_PACKAGES=${FF_PACKAGES:-oftools ipoib psm_mpi} + +# Additional INSTALL options during opahostadmin load [-I option] +#export FF_INSTALL_OPTIONS=${FF_INSTALL_OPTIONS:- -E ibacm} +export FF_INSTALL_OPTIONS=${FF_INSTALL_OPTIONS:- } + +# Additional INSTALL options during opahostadmin upgrade [-U option] +#export FF_UPGRADE_OPTIONS=${FF_UPGRADE_OPTIONS:- -E ibacm} +export FF_UPGRADE_OPTIONS=${FF_UPGRADE_OPTIONS:- } + +# where to upload server specific files to during opauploadall, opacaptureall +# [-d option] +export UPLOADS_DIR=${UPLOADS_DIR:-./uploads} + +# where to download server specific files from during opadownloadall +# [-d option] +export DOWNLOADS_DIR=${DOWNLOADS_DIR:-./downloads} + +# where to save history and baselines for cluster analysis and health checks +# [-d option] +export FF_ANALYSIS_DIR=${FF_ANALYSIS_DIR:-/var/usr/lib/opa/analysis} + +# topology input file(s) to use for opafabricanalysis, opaallanalysis and +# opareports operations. The %P marker will be replaced with the +# local HFI port/fabric selection string (for example 0:0 or 1:2) for +# the fabric being selected (see PORTS_FILE for more information) +# if this file is not found, or the value of this parameter is "NONE" +# no topology input file will be used +export FF_TOPOLOGY_FILE=${FF_TOPOLOGY_FILE:-$CONFIG_DIR/opa/topology.%P.xml} + +# How to login to host systems during opahostadmin +# At this time only ssh is supported. +# Note: at present opacmdall and opascpall always assume password-less ssh/scp +export FF_LOGIN_METHOD=${FF_LOGIN_METHOD:-ssh} + +# initial user name (cannot be root if CFG_LOGIN_METHOD=telnet) +export FF_USERNAME=${FF_USERNAME:-root} + +# password for FF_USERNAME (not needed if password-less ssh configured) +export FF_PASSWORD=${FF_PASSWORD:-} + +# if FF_USERNAME is not root, what is the root password needed when +# suing to root +export FF_ROOTPASS=${FF_ROOTPASS:=} + +# How to login to chassis +# can be ssh or telnet +export FF_CHASSIS_LOGIN_METHOD=${FF_CHASSIS_LOGIN_METHOD:-ssh} + +# password for admin (not needed if password-less ssh configured) +export FF_CHASSIS_ADMIN_PASSWORD=${FF_CHASSIS_ADMIN_PASSWORD:-adminpass} + +#base device number for IPoIB devices - IPoIB devices in the systems will +# be named "ib($FF_IPOIB_BASE_DEV_NUM) ib($FF_IPOIB_BASE_DEV_NUM+1) ..." +# On Silvertstorm stack it will be "ib1 ib2 ...." +# On OFED stack it will be "ib0 ib1 ..." +export FF_IPOIB_BASE_DEV_NUM=${FF_IPOIB_BASE_DEV_NUM:-0} + +# shell Function to return the base IPoIB device number for this stack type. +# For Silverstorm stack installations this function should return 1, for +# OFED stack installations this should return 0. +if ! type ff_ipoib_base_dev_num >/dev/null 2>/dev/null +then + function ff_ipoib_base_dev_num() + { + # No arguments to this function + # $host is supplied as an arguemnt when this function is called + # but it is ignored here. This is a hack to limit the number of + # changes required. + echo "$FF_IPOIB_BASE_DEV_NUM" + } +fi + +# options for opareport during opafabricanalysis health check +# alternative would be to use "-i seconds" instead of -C +# depending on fabric design, more strict link speed checks, such as +# -o slowconfiglinks or -o slowconnlinks may be appropriate +export FF_FABRIC_HEALTH=${FF_FABRIC_HEALTH:- -s -C -o errors -o slowlinks} + +# list of CLI commands to issue during opachassisanalysis +export FF_CHASSIS_CMDS=${FF_CHASSIS_CMDS:-showAllConfig} + +# single CLI command to issue to check overall health during opachassisanalysis +# hwCheck is prefered, but is not supported on older chassis FW +export FF_CHASSIS_HEALTH=${FF_CHASSIS_HEALTH:-hwCheck} + +# list of CLI commands to issue during opaesmanalysis +export FF_ESM_CMDS=${FF_ESM_CMDS:-smConfig} + +# list of analysis to perform during opaallanalysis +# pick appropriate type of SM to analyze +#export FF_ALL_ANALYSIS=${FF_ALL_ANALYSIS:-fabric chassis hostsm esm} +export FF_ALL_ANALYSIS=${FF_ALL_ANALYSIS:-fabric chassis} + +# command to perform text files for baseline vs latest snapshot during +# fabric health analysis commands +#export FF_DIFF_CMD=${FF_DIFF_CMD:-diff} +export FF_DIFF_CMD=${FF_DIFF_CMD:-diff -C 1} + +# location to find fastfabric mpi_apps for use by assorted fastfabric tools +# As needed they can be copied to a global filesystem and adjust this variable +# This MUST be a absolute path which exists on all nodes +export FF_MPI_APPS_DIR=${FF_MPI_APPS_DIR:-$HOME/mpi_apps} + +#location of Cable Health Report files +export FF_CABLE_HEALTH_REPORT_DIR=${FF_CABLE_HEALTH_REPORT_DIR:-/var/opt/opafm/cablehealth} + +# Maximum number of cable health report files to maintain +export FF_CABLE_HEALTH_MAX_FILES=${FF_CABLE_HEALTH_MAX_FILES:- 255} + +# env variables to set within each rank of MPI runs done by fastfabric directly +# alternatively the $FF_MPI_APPS_DIR/ofed.*.param files can be edited +# with appropriate values. +# example of PSM selection of vFabric by PKEY/SL +#export FF_MPI_ENV=${FF_MPI_ENV:-PSM2_PKEY=0xffff HFI_SL=0 PSM2_MTU=2048} +# example of PSM selection of path and vFabric by query to dist_sa +#export FF_MPI_ENV=${FF_MPI_ENV:-PSM2_PATH_REC=opp PSM2_IB_SERVICE_ID=0x1000117500000000} +# example of PSM selection of path and vFabric by default query to dist_sa +#export FF_MPI_ENV=${FF_MPI_ENV:-PSM2_PATH_REC=opp} +export FF_MPI_ENV=${FF_MPI_ENV:-} + +# configuration of arguments for MPI performance deviation testing +# via $FF_MPI_APPS_DIR/deviation/deviation +# The defaults should work for most fabrics. This can be made stricter +# and/or specific to the fabric by using arguments such as -h hostname +# -bwthres and -latthres. Samples are provided for various topologies. +# See run_deviation or the user's guide for more +# information. +#export FF_DEVIATION_ARGS=${FF_DEVIATION_ARGS:--bwtol 20 -lattol 50 -c -v} +#export FF_DEVIATION_ARGS=${FF_DEVIATION_ARGS:--bwtol 20 -lattol 50 -c -h hostname} +export FF_DEVIATION_ARGS=${FF_DEVIATION_ARGS:--bwtol 20 -lattol 50 -c} +# 1 hop fabric, 100g links, x16 Hosts +#export FF_DEVIATION_ARGS==${FF_DEVIATION_ARGS:--bwthres 12000 -latthres 1.07 -c} +# 3 hop fabric, 100g links, x16 Hosts +#export FF_DEVIATION_ARGS==${FF_DEVIATION_ARGS:--bwthres 12000 -latthres 1.35 -c} +# 5 hop fabric, 100g links, x16 Hosts +#export FF_DEVIATION_ARGS==${FF_DEVIATION_ARGS:--bwthres 12000 -latthres 1.63 -c} + +# location to find fastfabric shmem_apps for use by assorted fastfabric tools +# As needed they can be copied to a global filesystem and adjust this variable +# This MUST be a absolute path which exists on all nodes +export FF_SHMEM_APPS_DIR=${FF_SHMEM_APPS_DIR:-$HOME/shmem_apps} + +#Serialize output of operations running in parallel +export FF_SERIALIZE_OUTPUT=${FF_SERIALIZE_OUTPUT:-yes} + +# Directory name for location of hostverify.sh script and output target directory +# on each host used by opaverifyhosts +export FF_HOSTVERIFY_DIR=${FF_HOSTVERIFY_DIR:-/root} diff --git a/IbaTools/FastFabric/opafastfabric.pl b/IbaTools/FastFabric/opafastfabric.pl new file mode 100755 index 0000000..65819f7 --- /dev/null +++ b/IbaTools/FastFabric/opafastfabric.pl @@ -0,0 +1,3247 @@ +#!/usr/bin/perl +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] + +# + +use strict; +use Term::ANSIColor; +use Term::ANSIColor qw(:constants); +use File::Basename; +use Math::BigInt; + +#Setup some defaults +my $KEY_ESC=27; +my $KEY_CNTL_C=3; +my $KEY_ENTER=13; + +# version string is filled in by prep, special marker format for it to use +my $VERSION = "THIS_IS_THE_ICS_VERSION_NUMBER:@(#)000.000.000.000B000"; +$VERSION =~ s/THIS_IS_THE_ICS_VERSION_NUMBER:@\(#\)//; +$VERSION =~ s/%.*//; +my $INT_VERSION = "THIS_IS_THE_ICS_INTERNAL_VERSION_NUMBER:@(#)000.000.000.000B000"; +$INT_VERSION =~ s/THIS_IS_THE_ICS_INTERNAL_VERSION_NUMBER:@\(#\)//; +$INT_VERSION =~ s/%.*//; +my $BRAND = "THIS_IS_THE_ICS_BRAND:Intel% "; +# backslash before : is so patch_brand doesn't replace string +$BRAND =~ s/THIS_IS_THE_ICS_BRAND\://; +$BRAND =~ s/%.*//; + +# TARGET_STACK +# this is patched by Makefile to be IBACCESS or OPENIB, only OPENIB is supported +my $IB_STACK_TYPE="THIS_IS_THE_IB_STACK_TYPE"; + +if ( "$IB_STACK_TYPE" ne "OPENIB" ) { + die "Fatal Error: STACK_TYPE not properly set. opafastfabric script corrupted\n"; +} + +my $FF_CONF_FILE; +my $OPA_CONFIG_DIR; # opa editable config scripts +my $SYS_CONFIG_DIR; # system editable config scripts +my $BIN_DIR; +my $TOOLS_DIR; +# where to install libraries +my $LIB_DIR; +my $USRLOCALLIB_DIR; +my $OPTIBALIB_DIR; +my $OWNER; +my $GROUP; + +$SYS_CONFIG_DIR="/etc"; +$OPA_CONFIG_DIR = "$SYS_CONFIG_DIR/opa"; +$LIB_DIR = "/lib"; +$USRLOCALLIB_DIR = "/usr/local/lib"; +$OPTIBALIB_DIR = "/usr/lib/opa/lib"; +if ( "$BIN_DIR" eq "" ) { + $BIN_DIR = "/usr/sbin"; +} +if ( "$TOOLS_DIR" eq "" ) { + $TOOLS_DIR = "/usr/lib/opa/tools"; +} +$FF_CONF_FILE = "$OPA_CONFIG_DIR/opafastfabric.conf"; +$OWNER = "root"; +$GROUP = "root"; + +my $ROOT = "/"; + +my $MENU_CHOICE=0; + +my $Default_Prompt=0; # use default values at prompts, non-interactive + + # full name of component for error messages +my %ComponentName = ( + "oftools" => "OPA Tools", + "fastfabric" => "FastFabric", + "mpiapps" => "opa-mpi-apps", # a package name + "mpisrc" => "MPI Source", + ); + +my @FabricSetupSteps; + # Names of fabric setup steps +@FabricSetupSteps = ( "config", "findgood", "setupssh", + "copyhosts", "showuname", "install", + "configipoib", "buildapps", "reboot", "refreshssh", + "rebuildmpi", "opacmdall", "copyall", "viewres" + ); + + # full name of steps for prompts +my %FabricSetupStepsName = ( + "config" => "Edit Config and Select/Edit Host File", + "findgood" => "Verify Hosts Pingable", + "setupssh" => "Set Up Password-Less SSH/SCP", + "copyhosts" => "Copy /etc/hosts to All Hosts", + "showuname" => "Show uname -a for All Hosts", + "install" => "Install/Upgrade OPA Software", + "configipoib" => "Configure IPoIB IP Address", + "buildapps" => "Build Test Apps and Copy to Hosts", + "reboot" => "Reboot Hosts", + "refreshssh" => "Refresh SSH Known Hosts", + "rebuildmpi" => "Rebuild MPI Library and Tools", + "opacmdall" => "Run a Command on All Hosts", + "copyall" => "Copy a File to All Hosts", + "viewres" => "View opahostadmin Result Files" + ); +# what to output before each menu item as a delimiter/marker +my %FabricSetupStepsMenuDelimiter = ( + "config" => "setup", + "findgood" => "", + "setupssh" => "", + "copyhosts" => "", + "showuname" => "", + "install" => "", + "configipoib" => "", + "buildapps" => "", + "reboot" => "", + "refreshssh" => "admin", + "rebuildmpi" => "", + "opacmdall" => "", + "copyall" => "", + "viewres" => "review", + ); + # Names of fabric admin steps +my @FabricAdminSteps; +# opapingall replaced with findgood +@FabricAdminSteps = ( "config", "fabric_info", "findgood", "singlehost", + "showallports", "sacache", "ipoibping", + "refreshssh", "mpiperf", "health", "cabletest", "opacaptureall", + "opacmdall", "viewres" + ); + # full name of steps for prompts +my %FabricAdminStepsName = ( + "config" => "Edit Config and Select/Edit Host File", + "fabric_info" => "Summary of Fabric Components", + #"opapingall" => "Verify Hosts via Ethernet Ping", + "findgood" => "Verify Hosts Are Pingable, SSHable, and Active", + "singlehost" => "Perform Single Host Verification", + "showallports" => "Verify OPA Fabric Status and Topology", + "sacache" => "Verify Hosts See Each Other", + "ipoibping" => "Verify Hosts Ping via IPoIB", + "refreshssh" => "Refresh SSH Known Hosts", + "mpiperf" => "Check MPI Performance", + "health" => "Check Overall Fabric Health", + "cabletest" => "Start or Stop Bit Error Rate Cable Test", + "opacaptureall" => "Generate All Hosts Problem Report Info", + "opacmdall" => "Run a Command on All Hosts", + "viewres" => "View opahostadmin Result Files" + ); +# what to output before each menu item as a delimiter/marker +my %FabricAdminStepsMenuDelimiter = ( + "config" => "validation", + "fabric_info" => "", + #"opapingall" => "", + "findgood" => "", + "singlehost" => "", + "showallports" => "", + "sacache" => "", + "ipoibping" => "", + "refreshssh" => "", + "mpiperf" => "", + "health" => "", + "cabletest" => "", + "opacaptureall" => "admin", + "opacmdall" => "", + "viewres" => "review", + ); +my @FabricMonitorSteps; +@FabricMonitorSteps = ( "opatop" + ); + # full name of steps for prompts +my %FabricMonitorStepsName = ( + "opatop" => "Fabric Performance Monitoring" + ); +# what to output before each menu item as a delimiter/marker +my %FabricMonitorStepsMenuDelimiter = ( + "opatop" => "" + ); +my @FabricChassisSteps = ( "config", "opapingall", "fwpush", "setup", "setupssh", + "reboot", "getconfig" , "fmconfig", "fmsecurityfiles", "fmgetsecurityfiles", "showallports", "fmcontrol", "opacaptureall", "opacmdall", "viewres" + ); +# what to output before each menu item as a delimiter/marker +my %FabricChassisStepsMenuDelimiter = ( + "config" => "setup", + "opapingall" => "", + "fwpush" => "", + "setup" => "", + "setupssh" => "", + "reboot" => "", + "getconfig" => "", + "fmconfig" => "", + "fmsecurityfiles" => "", + "fmgetsecurityfiles" => "", + "showallports" => "admin", + "fmcontrol" => "", + "opacaptureall" => "", + "opacmdall" => "", + "viewres" => "review", + ); +my %FabricChassisStepsName = ( + "config" => "Edit Config and Select/Edit Chassis File", + "opapingall" => "Verify Chassis via Ethernet Ping", + "fwpush" => "Update Chassis Firmware", + "setup" => "Set Up Chassis Basic Configuration", + "setupssh" => "Set Up Password-Less SSH/SCP", + "reboot" => "Reboot Chassis", + "fmconfig" => "Configure Chassis Fabric Manager (FM)", + "getconfig" => "Get Basic Chassis Configuration", + "fmsecurityfiles" => "Update Chassis FM Security Files", + "fmgetsecurityfiles" => "Get Chassis FM Security Files", + "showallports" => "Check OPA Fabric Status", + "fmcontrol" => "Control Chassis Fabric Manager (FM)", + "opacaptureall" => "Generate All Chassis Problem Report Info", + "opacmdall" => "Run a Command on All Chassis", + "viewres" => "View opachassisadmin Result Files" + ); +my @FabricExtMgmtSwSteps = ( "config", "genopaswitches", "ibping", "fwverify", + "fwpush", "setup", "reboot", "switchinfo", "getconfig", + "hwvpd","viewres" + ); +my %FabricExtMgmtSwStepsName = ( + "config" => "Edit Config and Select/Edit Switch File", + "genopaswitches" => "Generate or Update Switch File", + "ibping" => "Test for Switch Presence", + "fwverify" => "Verify Switch Firmware", + "fwpush" => "Update Switch Firmware", + "setup" => "Set Up Switch Basic Configuration", + "reboot" => "Reboot Switch", + "switchinfo" => "Report Switch Firmware & Hardware Info", + "getconfig" => "Get Basic Switch Configuration", + "hwvpd" => "Report Switch VPD Information", + "viewres" => "View opaswitchadmin Result Files" + ); +# what to output before each menu item as a delimiter/marker +my %FabricExtMgmtSwStepsMenuDelimiter = ( + "config" => "setup", + "genopaswitches" => "", + "ibping" => "", + "fwverify" => "", + "fwpush" => "", + "setup" => "", + "reboot" => "", + "switchinfo" => "", + "getconfig" => "", + "hwvpd" => "admin", + "viewres" => "review", + ); +my $FabricSetupHostsFile="$OPA_CONFIG_DIR/hosts"; +# HOSTS_FILE overrides default +if ( "$ENV{HOSTS_FILE}" ne "" ) { + $FabricSetupHostsFile="$ENV{HOSTS_FILE}"; +} +my $PrevFabricSetupHostsFile=$FabricSetupHostsFile; +my $FabricSetupScpFromDir="."; +my $FabricAdminHostsFile="$OPA_CONFIG_DIR/allhosts"; +my $PrevFabricAdminHostsFile="$OPA_CONFIG_DIR/allhosts"; +# HOSTS_FILE overrides default +if ( "$ENV{HOSTS_FILE}" ne "" ) { + $FabricAdminHostsFile="$ENV{HOSTS_FILE}"; +} +my $FabricChassisFile="$OPA_CONFIG_DIR/chassis"; +# CHASSIS_FILE overrides default +if ( "$ENV{CHASSIS_FILE}" ne "" ) { + $FabricChassisFile="$ENV{CHASSIS_FILE}"; +} +my $FabricChassisPackages="none"; +my $FabricChassisFMConfig="none"; +my $FabricChassisFMSecurityFiles="none"; +my $FabricExtMgmtSwFile="$OPA_CONFIG_DIR/switches"; +# OPASWITCHES_FILE overrides default +if ( "$ENV{OPASWITCHES_FILE}" ne "" ) { + $FabricExtMgmtSwFile="$ENV{OPASWITCHES_FILE}"; +} +my $FabricExtMgmtSwPackages="none"; +my $Editor="$ENV{EDITOR}"; +if ( "$Editor" eq "" ) { + $Editor="vi"; +} + +sub HitKeyCont; +sub remove_whitespace($); + +sub set_libdir +{ + if ( -d "$ROOT/lib64" ) + { + $LIB_DIR = "/lib64"; + $USRLOCALLIB_DIR = "/usr/local/lib64"; + $OPTIBALIB_DIR = "/usr/lib/opa/lib64"; + } +} + +sub getch +{ + my $c; + system("stty -echo raw"); + $c=getc(STDIN); + system("stty echo -raw"); + print "\n"; + return $c; +} + +sub open_log +{ + open(LOG_FD, ">>$ROOT/var/log/opa.log"); + print LOG_FD "-------------------------------------------------------------------------------\n"; + print LOG_FD basename($0) . " $INT_VERSION Run " . `/bin/date`; + print LOG_FD "$0 @ARGV\n" +} + +sub close_log +{ + close LOG_FD; +} + +# show Skip/Perform status for a step in a menu +sub printStepSelected +{ + my $selected = $_[0]; + my $message = $_[1]; + + if (! $selected ) + { + print "[ Skip ] "; + } else { + print GREEN, "[Perform] ", RESET; + } + print BOLD, RED "$message", RESET, "\n"; + return; +} + +sub print_separator +{ + print "-------------------------------------------------------------------------------\n"; +} + +sub print_delimiter +{ + my $delimiter = "$_[0]"; + if ("$delimiter" eq "line" ) { + print_separator; + } elsif ("$delimiter" eq "blank" ) { + print("\n"); + } elsif ("$delimiter" eq "admin" ) { + print("Admin:\n"); + } elsif ("$delimiter" eq "setup" ) { + print("Setup:\n"); + } elsif ("$delimiter" eq "validation" ) { + print("Validation:\n"); + } elsif ("$delimiter" eq "review" ) { + print("Review:\n"); + } elsif ("$delimiter" eq "other" ) { + print("Other:\n"); + } +} + +# remove any directory prefixes from path +sub basename +{ + my($path) = "$_[0]"; + + $path =~ s/.*\/(.*)$/$1/; + return $path +} + +sub make_dir +{ + my($dir) = "$ROOT$_[0]"; + my($owner) = "$_[1]"; + my($group) = "$_[2]"; + my($mode) = "$_[3]"; + + system "mkdir -p -m $mode $dir"; + system "chown $owner $dir"; + system "chgrp $group $dir"; +} + +sub check_dir +{ + my($dir) = "$_[0]"; + if (! -d "$ROOT$dir" ) + { + #Creating directory + + make_dir("$dir", "$OWNER", "$GROUP", "ugo=rx,u=rwx"); + } +} + +sub copy_file +{ + my($src) = "$_[0]"; + my($dest) = "$ROOT$_[1]"; + my($owner) = "$_[2]"; + my($group) = "$_[3]"; + my($mode) = "$_[4]"; + # only copy file if source exists, this keep all those cp errors for litering + # install for development. + + if ( -e $src) + { + system "cp -rf $src $dest"; + system "chown $owner $dest"; + system "chgrp $group $dest"; + system "chmod $mode $dest"; + } +} + +sub copy_data_file +{ + copy_file("$_[0]", "$_[1]", "$OWNER", "$GROUP", "ugo=r,u=rw"); +} + +sub GetChoice($$@) +{ + my($Question) = shift(); + my($default) = shift(); + + my %choices; + @choices{@_}=(); # Convert our choices to a hash table. + + my $c; + + if ( $Default_Prompt ) { + print LOG_FD "$Question -> $default\n"; + $c=lc($default); + if (exists $choices{$c}) { + return $c; + } + # If the default is invalid, fall through. + } + + while (1) + { + print "$Question [$default]: "; + chomp($_ = ); + $_=remove_whitespace($_); + if ("$_" eq "") { + $_=$default; + } + $c = lc($_); + + if (exists $choices{$c}) + { + print LOG_FD "$Question -> $c\n"; + return $c; + } + } +} + +sub GetNumericValue +{ + my($retval) = 0; + + my($Question) = $_[0]; + my($default) = $_[1]; + my($minvalue) = $_[2]; + my($maxvalue) = $_[3]; + + if ( $Default_Prompt ) { + print "$Question -> $default\n"; + print LOG_FD "$Question -> $default\n"; + if (($default ge $minvalue) && ($default le $maxvalue)) { + return $default; + } + # for invalid default, fall through and prompt + } + + while (1) + { + print "$Question [$default]: "; + chomp($retval = ); + $retval=remove_whitespace($retval); + + if (length($retval) == 0) { + $retval=$default; + } + if (($retval >= $minvalue) && ($retval <= $maxvalue)) { + print LOG_FD "$Question -> $retval\n"; + return $retval; + } + else { + print "Value Out-of-Range ($minvalue to $maxvalue)\n"; + } + } +} + +sub GetYesNo +{ + my($retval) = 1; + my($answer) = 0; + + my($Question) = $_[0]; + my($default) = $_[1]; + + if ( $Default_Prompt ) { + print "$Question -> $default\n"; + print LOG_FD "$Question -> $default\n"; + if ( "$default" eq "y") { + return 1; + } elsif ("$default" eq "n") { + return 0; + } + # for invalid default, fall through and prompt + } + + while ($answer == 0) + { + print "$Question [$default]: "; + chomp($_ = ); + $_=remove_whitespace($_); + #$_ = getch(); + if ("$_" eq "") { + $_=$default; + } + if (/^[Nn]/) + { + print LOG_FD "$Question -> n\n"; + $retval = 0; + $answer = 1; + } elsif (/^[Yy]/ ) { + print LOG_FD "$Question -> y\n"; + $retval = 1; + $answer = 1; + } + } + return $retval; +} + + +sub HitKeyCont +{ + if ( $Default_Prompt ) + { + return; + } + + print "Hit any key to continue..."; + #$_=; + getch(); + return; +} + +sub HitKeyContAbortable +{ + my $c; + + if ( $Default_Prompt ) + { + return; + } + + print "Hit any key to continue (or ESC to abort)..."; + #$_=; + $c = getch(); + # cntl-C is Abort character + if ( ord($c) == $KEY_ESC || ord($c) == $KEY_CNTL_C ) + { + return (GetYesNo("Abort?", "y") == 1); + } else { + return 0; + } +} + +# return 1 if the given config file has only comment and whitespace lines +sub empty_config_file($) +{ + my $file = $_[0]; + my $lines = `$BIN_DIR/opaexpandfile $file|wc -l`; # let errors go to stderr + return ( $lines == 0); +} + +# check if the given config files exists and is non-empty +# return 1 if its good, 0 if not +sub valid_config_file($$) +{ + my $desc = $_[0]; + my $file = $_[1]; + + if ( ! -e "$file" ) { + print "$file: not found\n"; + print "You must create/select a $desc to proceed\n"; + HitKeyCont; + return 0; # failure + } + if (empty_config_file($file)) { + print "$file: is empty\n"; + print "You must create/select a $desc to proceed\n"; + HitKeyCont; + return 0; # failure + } + return 1; # success +} + +# provide a simple menu to select a single item from a list +# # returns one of selections or "" (to indicate user escaped menu) +sub selection_menu($$$@) +{ + my $title = shift(); + my $title2 = shift(); + my $prompt = shift(); + my @selections = @_; + + my $firstline = 0; + my $maxlines=15; + my $i; + my $inp; + +DO_MENU: + system "clear"; + printf ("$title\n"); + printf ("$title2\n\n"); + my $screens = int((scalar(@selections) + $maxlines-1)/$maxlines); + if ($screens > 1 ) { + printf ("Please Select $prompt (screen %d of $screens):\n", + $firstline/$maxlines+1); + } else { + printf ("Please Select $prompt:\n"); + } + my $index=0; + for($i=0; $i < scalar(@selections); $i++) { + if ($index >= $firstline && $index < $firstline+$maxlines) { + printf ("%x) %s\n", $index-$firstline, $selections[$i]); + } + $index++; + } + printf ("\n"); + if ($screens > 1 ) { + printf ("N) Next Screen\n"); + } + printf ( "X) Return to Previous Menu (or ESC or Q)\n"); + $inp = getch(); + + if ($inp =~ /[qQ]/ || $inp =~ /[xX]/ || ord($inp) == $KEY_ESC) { + return ""; + } + + if ($inp =~ /[nN]/ ) { + if (scalar(@selections) > $maxlines) { + $firstline += $maxlines; + if ($firstline >= scalar(@selections)) { + $firstline=0; + } + } + } elsif ($inp =~ /[0123456789abcdefABCDEF]/) { + my $value = hex($inp); + my $index = ($firstline + $value); + if ( $value < $maxlines && $index < scalar(@selections)) { + return $selections[$index]; + } + } + goto DO_MENU; +} + +# This function supports reading parameters from config file which are +# actually shell scripts. openib.conf, fastfabric.conf and the Linux network +# config files are examples of such. +# If the file or parameter does not exist, returns "" +sub read_simple_config_param($$) +{ + my $config_file=shift(); + my $parameter=shift(); + + if ( ! -e "$config_file" ) { + return ""; + } + my $value=`. $config_file >/dev/null 2>/dev/null; echo \$$parameter`; + chomp($value); + return "$value"; +} + +sub remove_whitespace($) +{ + my $string=shift(); + chomp($string); + $string =~ s/^[[:space:]]*//; # remove leading + $string =~ s/[[:space:]]*$//; # remove trailing + return $string; +} + +sub installed_mpiapps +{ + return (system("rpm -q opa-mpi-apps > /dev/null") == 0); +} + + +sub installed_mpisrc +{ + return (-e "$ROOT/usr/src/opa/MPI/do_build"); +} + +sub check_user +{ + my $user; + $user=`/usr/bin/id -u`; + if ($user != 0) + { + die "\n\nYou must be \"root\" to run this install program\n\n"; + } +} + +sub Usage +{ + # don't document -r option, its only used for MPI do_build and + # may not be appropriate anyway + printf STDERR "Usage: $0 [--fromdir dir]\n"; + printf STDERR " --fromdir dir - default directory to get install image from\n"; + exit (2); +} + +sub process_args +{ + my $arg; + my $last_arg; + my $setroot = 0; + my $setdir = 0; + + if (scalar @ARGV >= 1) { + foreach $arg (@ARGV) { + if ( $setdir ) { + $FabricSetupScpFromDir="$arg"; + $setdir=0; + } elsif ( $setroot ) { + $ROOT="$arg"; + $setroot=0; + } elsif ( "$arg" eq "--fromdir" ) { + $setdir=1; + } elsif ( "$arg" eq "-r" ) { + $setroot=1; + } + else { + printf STDERR "Invalid option: $arg\n"; + Usage; + } + $last_arg=$arg; + } + } + if ( $setdir || $setroot) { + printf STDERR "Missing argument for option: $last_arg\n"; + Usage; + } + +} + +sub read_ffconfig_param +{ + my $param = "$_[0]"; # ffconfig parameter + + my $result=`if [ -f $FF_CONF_FILE ]; then . $FF_CONF_FILE >/dev/null 2>&1; fi; . $TOOLS_DIR/opafastfabric.conf.def >/dev/null 2>&1; . $TOOLS_DIR/ff_funcs >/dev/null 2>&1; echo \$$param`; + chomp($result); + return "$result"; +} + +sub setup_ffconfig +{ + do { + if ( ! -e "$FF_CONF_FILE" ) { + # replace missing file + copy_data_file("$TOOLS_DIR/opafastfabric.conf.def", "$FF_CONF_FILE"); + } + print "You will now have a chance to edit/review the FastFabric Config File:\n"; + print "$FF_CONF_FILE\n"; + print "The values in this file will control the default operation of the\n"; + print "FastFabric Tools. With the exception of the host file to use,\n"; + print "the values you specify for defaults will be used for all FastFabric\n"; + print "Operations performed via this menu system\n"; + print "Beware existing environment variables will override the values in this file.\n\n"; + + print "About to: $Editor $FF_CONF_FILE\n"; + if ( HitKeyContAbortable() == 1) { + return 1; + } + system("$Editor $FF_CONF_FILE"); + if ( ! -e "$FF_CONF_FILE" ) { + print "You must have a $FF_CONF_FILE file to proceed\n\n"; + } + } until ( -e "$FF_CONF_FILE"); + return 0; +} + +sub setup_ffports +{ + my $file = read_ffconfig_param("PORTS_FILE"); + do { + if ( ! -e "$file" ) { + # replace missing file + copy_data_file("/usr/lib/opa/tools/ports", "$file"); + } + print "You will now have a chance to edit/review the FastFabric PORTS_FILE:\n"; + print "$file\n"; + print "Some of the FastFabric operations which follow will use this file to\n"; + print "specify the local HFI ports to use to access the fabric(s) to operate on\n"; + print "Beware existing environment variables will override the values in this file.\n\n"; + + print "About to: $Editor $file\n"; + if ( HitKeyContAbortable() == 1) { + return 1; + } + system("$Editor $file"); + if ( ! -e "$file" ) { + print "You must have a $file file to proceed\n\n"; + } + } until ( -e "$file"); + return 0; +} + +sub run_fabric_cmd +{ + my $cmd = "$_[0]"; + my $skip_prompt = "$_[1]"; + print "Executing: $cmd\n"; + print LOG_FD "Executing: $cmd\n"; + system("$cmd"); + if ( "$skip_prompt" ne "skip_prompt" && HitKeyContAbortable() == 1) { + return 1; + } + return 0; +} + +sub run_fabric_opacmdall +{ + my $DestFile = "$_[0]"; + my $chassis = "$_[1]"; + my $Sopt = "$_[2]"; + my $other_opts = "$_[3]"; + my $cmd; + my $fabric_cmd; + + # valid_config_file has already been called by caller + do { + if ($chassis == 0) { + print "Enter Command to run on all hosts (or none):"; + } else { + print "Enter Command to run on all chassis (or none):"; + } + chomp($cmd = ); + $cmd=remove_whitespace($cmd); + } until ( length($cmd) != 0 ); + if ( "$cmd" ne "none" ) { + if ($chassis == 0) { + my $timelimit=GetNumericValue("Timelimit in minutes (0=unlimited):", 1, 0, 24*60) * 60; + if ( $timelimit ) { + $other_opts="$other_opts -T $timelimit"; + } + if (GetYesNo("Run in parallel on all hosts?", "y") ) { + $fabric_cmd="$BIN_DIR/opacmdall -p $other_opts -f $DestFile '$cmd'"; + } else { + $fabric_cmd="$BIN_DIR/opacmdall $other_opts -f $DestFile '$cmd'"; + } + } else { + if (GetYesNo("Run in parallel on all chassis?", "y") ) { + $fabric_cmd="$BIN_DIR/opacmdall -C $Sopt -p $other_opts -F $DestFile '$cmd'"; + } else { + $fabric_cmd="$BIN_DIR/opacmdall -C $Sopt $other_opts -F $DestFile '$cmd'"; + } + } + if (GetYesNo("About to run: $fabric_cmd\nAre you sure you want to proceed?", "n") ) { + return run_fabric_cmd("$fabric_cmd"); + } + } + return 0; +} + +sub check_load($$$) +{ + my $hostfile = "$_[0]"; + my $ropt = "$_[1]"; # -r shows least busy hosts, default is busiest + my $prompt = "$_[2]"; + + # valid_config_file has already been called by caller + if (GetYesNo("View Load on hosts $prompt?", "y") ) { + return run_fabric_cmd("$BIN_DIR/opacheckload $ropt -f $hostfile"); + } + return 0; +} + +sub ff_viewres +{ + my $view_punchlist = "$_[0]"; + my $view_verifyhosts = "$_[1]"; + + my $result_dir = read_ffconfig_param("FF_RESULT_DIR"); + my $files = "$result_dir/test.res $result_dir/test.log"; + my $rm_files = "test.res test.log"; + my $extra_rm_files = "test.res~ test.log~"; + if ( $view_verifyhosts) { + $files= "$result_dir/verifyhosts.res $files"; + $rm_files= "verifyhosts.res $rm_files"; + $extra_rm_files = "verifyhosts.res~ $extra_rm_files"; + } + if ( $view_punchlist) { + $files= "$result_dir/punchlist.csv $files"; + } + if ( ! -e "$result_dir/test.res" && ! -e "$result_dir/test.log" + && ! ($view_punchlist && -e "$result_dir/punchlist.csv") + && ! ($view_verifyhosts && -e "$result_dir/verifyhosts.res") ) { + print "No result files in $result_dir\n"; + if ( HitKeyContAbortable() ) { + return 1; + } + } else { + print "Using $Editor (to select a different editor, export EDITOR).\n"; + print "About to: $Editor $files\n"; + if ( HitKeyContAbortable() ) { + return 1; + } + system("$Editor $files"); + if (GetYesNo("Would you like to remove $rm_files test_tmp* and save_tmp\nin $result_dir ?", "n") ) { + print("Executing: cd $result_dir && rm -rf $rm_files save_tmp test_tmp* $extra_rm_files\n"); + system("cd $result_dir && rm -rf $rm_files save_tmp test_tmp* $extra_rm_files"); + if ( HitKeyContAbortable() ) { + return 1; + } + } + } + return 0; +} + +sub fabricsetup_config +{ + my $inp; + my $file; + + print "Using $Editor (to select a different editor, export EDITOR).\n"; + do { + if (setup_ffconfig() ) { + return 1; + } + do + { + print "The FastFabric operations which follow will require a file\n"; + print "listing the hosts to operate on\n"; + print "You should select a file which OMITS this host\n"; + print "Select Host File to Use/Edit [$PrevFabricSetupHostsFile]: "; + chomp($inp = ); + $inp=remove_whitespace($inp); + + if ( length($inp) == 0 ) + { + $file = $PrevFabricSetupHostsFile; + } else { + $file = $inp; + } + print "About to: $Editor $file\n"; + if ( HitKeyContAbortable() ) { + return 1; + } + system("$Editor '$file'"); + if ( ! -e "$file" ) { + print "You must create a Host File to proceed\n\n"; + } else { + $FabricSetupHostsFile=$file; + $PrevFabricSetupHostsFile=$file; + } + } until ( -e "$file"); + print "Selected Host File: $FabricSetupHostsFile\n"; + } until (! GetYesNo("Do you want to edit/review/change the files?", "y") ); + print LOG_FD "Selected Host File -> $FabricSetupHostsFile\n"; + return 0; +} + +sub fabricsetup_opapingall +{ + if (! valid_config_file("Host File", $FabricSetupHostsFile) ) { + return 1; + } + return run_fabric_cmd("$BIN_DIR/opapingall -p -f $FabricSetupHostsFile"); +} +sub fabricsetup_findgood +{ + my $findgood_opts="-A -Q"; + + if ( -e "$PrevFabricSetupHostsFile" + && "$PrevFabricSetupHostsFile" ne "$FabricSetupHostsFile" ) { + if (GetYesNo("Would you like to go back to using $PrevFabricSetupHostsFile?", "y") ) { + $FabricSetupHostsFile = $PrevFabricSetupHostsFile; + } + } + if (! valid_config_file("Host File", $FabricSetupHostsFile) ) { + return 1; + } + if (! GetYesNo("Would you like to verify hosts are ssh-able?", "n") ) { + # skip ssh test + $findgood_opts="$findgood_opts -R"; + } + if ( run_fabric_cmd("$BIN_DIR/opafindgood $findgood_opts -f $FabricSetupHostsFile")) { + # serious failure + return 1; + } + # ask even if non-bad since good file will be better sorted for cabletest + #if (-s $OPA_CONFIG_DIR/bad) { + if ( "$FabricSetupHostsFile" ne "$OPA_CONFIG_DIR/good") { + if (GetYesNo("Would you like to now use $OPA_CONFIG_DIR/good as Host File?", "y") ) { + $PrevFabricSetupHostsFile = "$FabricSetupHostsFile"; + $FabricSetupHostsFile = "$OPA_CONFIG_DIR/good"; + } + } + return 0; +} + +sub fabricsetup_setupssh +{ + if (! valid_config_file("Host File", $FabricSetupHostsFile) ) { + return 1; + } + return run_fabric_cmd("$BIN_DIR/opasetupssh -S -p -i '' -f $FabricSetupHostsFile"); +} +sub fabricsetup_copyhosts +{ + if (! valid_config_file("Host File", $FabricSetupHostsFile) ) { + return 1; + } + return run_fabric_cmd("$BIN_DIR/opascpall -p -f $FabricSetupHostsFile /etc/hosts /etc/hosts"); +} +sub fabricsetup_showuname +{ + if (! valid_config_file("Host File", $FabricSetupHostsFile) ) { + return 1; + } + return run_fabric_cmd("$BIN_DIR/opacmdall -T 60 -f $FabricSetupHostsFile 'uname -a'"); +} +sub fabricsetup_install +{ + my $install_mode; + my $dir="$FabricSetupScpFromDir"; + my $query=0; + my $install_file; + my $product = read_ffconfig_param("FF_PRODUCT"); + my $version = read_ffconfig_param("FF_PRODUCT_VERSION"); + my $packages = ""; + my $options; + + $install_file="$product.$version.tgz"; + + if (! valid_config_file("Host File", $FabricSetupHostsFile) ) { + return 1; + } + do { + do { + if ( "$dir" ne "none" && ! -e "$dir/$install_file" ) { + print "$dir/$install_file: not found\n"; + $query=1; + } else { + $query = ! GetYesNo("Do you want to use $dir/$install_file?", "y"); + } + if ( $query ) { + do { + print "Enter Directory to get $install_file from (or none):"; + chomp($dir = ); + $dir=remove_whitespace($dir); + } until ( length($dir) != 0 ); + } + } until ( "$dir" eq "none" || -e "$dir/$install_file" ); + if ("$dir" eq "none" ) { + print "You have selected to skip the installation/upgrade step\n"; + $install_mode="skip"; + } else { + print "You have selected to use $dir/$install_file\n"; + $FabricSetupScpFromDir="$dir"; + print "\nAn upgrade/reinstall or an initial installation may be performed.\n\n"; + print "An upgrade/reinstall requires an existing installation of OPA software\non the selected nodes and will upgrade or reinstall the existing packages.\n\n"; + print "An initial installation will first uninstall any existing OPA software.\n"; + + my $choice = GetChoice("Would you like to do a fresh [i]nstall, an [u]pgrade or [s]kip this step?", + "u", ("i", "u", "s")); + + if ("$choice" eq "u") { + $install_mode="upgrade"; + print "You have selected to perform an upgrade installation\n"; + $options = read_ffconfig_param("FF_UPGRADE_OPTIONS"); + if ("$options" ne "") { + if (! GetYesNo("Do you want to use the following upgrade options: '$options'?", "y")) { + do { + print "Enter upgrade options (or none):"; + chomp($options = ); + $options=remove_whitespace($options); + } until ( length($options) != 0); + } + if ("$options" eq "none") { + $options=""; + } + else { + $options = "-U \'$options\'"; + } + } + } elsif ("$choice" eq "i") { + $install_mode="load"; + print "You have selected to perform an initial installation\n"; + print "This will uninstall any existing OPA software on the selected nodes\n"; + $options = read_ffconfig_param("FF_INSTALL_OPTIONS"); + if ("$options" ne "") { + if (! GetYesNo("Do you want to use the following install options: '$options'?", "y")) { + do { + print "Enter install options (or none):"; + chomp($options = ); + $options=remove_whitespace($options); + } until ( length($options) != 0); + } + if ("$options" eq "none") { + $options=""; + } + else { + $options = "-I \'$options\'"; + $packages = read_ffconfig_param("FF_PACKAGES"); + if ("$packages" ne "") { + if (! GetYesNo("Do you want to install the following packages?\n $packages\n", "y")) { + do { + print "Enter packages (or none):"; + chomp($packages = ); + $packages=remove_whitespace($packages); + } until ( length($packages) != 0); + } + if ("$packages" eq "none") { + $packages=""; + } + else { + $packages = "-P \'$packages\'"; + } + } + } + } + } + } + } until (GetYesNo("Are you sure you want to proceed?", "n") ); + if ( "$install_mode" ne "skip" ) { + return run_fabric_cmd("$BIN_DIR/opahostadmin -f $FabricSetupHostsFile -d $FabricSetupScpFromDir $options $packages $install_mode"); + } + return 0; +} + +sub fabricsetup_configipoib +{ + # netmask is via $FF_CONF_FILE + if (! valid_config_file("Host File", $FabricSetupHostsFile) ) { + return 1; + } + return run_fabric_cmd("$BIN_DIR/opahostadmin -f $FabricSetupHostsFile configipoib"); +} +sub fabricsetup_buildmpi +{ + my $mpi_apps_dir = "/usr/src/opa/mpi_apps"; + my $build_dir = read_ffconfig_param("FF_MPI_APPS_DIR"); + if (! -e "$mpi_apps_dir/Makefile") { + # the makefile and some of apps are part of opa-fastfabric package + print "$mpi_apps_dir/Makefile: not found\n"; + print "Make sure opa-fastfabric is properly installed\n"; + HitKeyCont; + return 1; + } + # for now do not build NASA, etc, just basic stuff + my $mode; + my $mpich_prefix; + my $inp; + do { + # get default MPI to use + $mpich_prefix= `cd $mpi_apps_dir 2>/dev/null; . ./select_mpi 2>/dev/null; echo \$MPICH_PREFIX`; + chomp $mpich_prefix; + + # identify other alternatives + my $prefix="/usr"; + my $dirs=`find $prefix/mpi -maxdepth 2 -mindepth 2 -type d 2>/dev/null|sort`; + $dirs=$dirs . `find /opt/intel/impi/*/intel64 -maxdepth 0 -type d 2>/dev/null|sort`; + my @dirs = split /[[:space:]]+/, $dirs; + + #print "The following MPIs have been found on this system:\n"; + if ( $dirs !~ m|$mpich_prefix|) { + # odd case, default is not in a normal location + #print " $mpich_prefix\n"; + @dirs = ($mpich_prefix, @dirs); + } + my @mpi_dirs = (); + foreach my $d ( @dirs ) { + next if ( ! -e "$d/bin/mpicc" ); # skip incomplete MPI dirs + #print " $d\n"; + @mpi_dirs = (@mpi_dirs, $d); + } + + do { + $inp = selection_menu( + "Host Setup: $FabricSetupStepsName{'buildapps'}", + "MPI Directory Selection", "MPI Directory", + (@mpi_dirs, "Enter Other Directory")); + if ( "$inp" eq "" ) { + $inp = "none"; + } elsif ( "$inp" eq "Enter Other Directory" ) { + do { + print "Enter MPI directory location (or none):"; + chomp($inp = ); + $inp=remove_whitespace($inp); + } until ( "$inp" ne ""); + } + if ("$inp" ne "none" && ! -e "$inp" ) { + print "$inp: not found\n"; + HitKeyCont; + } + } until ( "$inp" eq "none" || -e "$inp" ); + $mpich_prefix=$inp; + if ("$mpich_prefix" eq "none" ) { + print "You have selected to skip the building of the MPI Apps step\n"; + $mode="skip"; + } else { + print "You have selected to use MPI: $mpich_prefix\n"; + $mode="build"; + } + } until (GetYesNo("Are you sure you want to proceed?", "n") ); + + if ( "$mode" ne "build" ) { + return 0; + } + if ( -e "$build_dir/.filelist" ) { + run_fabric_cmd("cd $build_dir; rm -rf `cat .filelist`", "skip_prompt"); + } + run_fabric_cmd("mkdir -p $build_dir; cp -r -p $mpi_apps_dir/. $build_dir", "skip_prompt"); + run_fabric_cmd("cd $mpi_apps_dir; find . -mindepth 1 > $build_dir/.filelist", "skip_prompt"); + if (!installed_mpiapps()){ + print "Package $ComponentName{mpiapps} not installed. Only building subset of MPI Apps\n"; + HitKeyCont; + if (run_fabric_cmd("cd $build_dir; MPICH_PREFIX=$mpich_prefix make clobber opa-base")) { + return 1; + } + } else{ + if (run_fabric_cmd("cd $build_dir; MPICH_PREFIX=$mpich_prefix make clobber quick")) { + return 1; + } + } + if (! valid_config_file("Host File", $FabricSetupHostsFile) ) { + return 1; + } + my $fabric_cmd="$BIN_DIR/opascpall -t -p -f $FabricSetupHostsFile $build_dir $build_dir"; + if (GetYesNo("About to run: $fabric_cmd\nAre you sure you want to proceed?","n") ) { + return run_fabric_cmd("$fabric_cmd"); + } + return 0; +} +sub fabricsetup_buildapps +{ + my $res = 0; + if (GetYesNo("Do you want to build MPI Test Apps?", "y") ) { + $res = fabricsetup_buildmpi(); + } + return $res; +} + +sub fabricsetup_reboot +{ + if (! valid_config_file("Host File", $FabricSetupHostsFile) ) { + return 1; + } + return run_fabric_cmd("$BIN_DIR/opahostadmin -f $FabricSetupHostsFile reboot"); +} +sub fabricsetup_refreshssh +{ + if (! valid_config_file("Host File", $FabricSetupHostsFile) ) { + return 1; + } + return run_fabric_cmd("$BIN_DIR/opasetupssh -p -U -f $FabricSetupHostsFile"); +} +sub fabricsetup_rebuildmpi +{ + if ( ! installed_mpisrc() ) { + printf("$ComponentName{mpisrc} not installed on this system\n"); + printf("Unable to Rebuild MPI\n"); + HitKeyCont; + return; + } + if (run_fabric_cmd("cd $ROOT/usr/src/opa/MPI; ./do_build")) { + return 1; + } + if (! valid_config_file("Host File", $FabricSetupHostsFile) ) { + return 1; + } + # do in two steps so user can see results of build before scp starts + # determine where MPI was built and copy needed files to all nodes + my $mpich_prefix= read_simple_config_param("$ROOT/usr/src/opa/MPI/.mpiinfo", "MPICH_PREFIX"); + # instead of copy, copy the actual rpms and install them + #return run_fabric_cmd("$BIN_DIR/opascpall -t -p -f $FabricSetupHostsFile $mpich_prefix $mpich_prefix"); + my $mpi_rpms= read_simple_config_param("$ROOT/usr/src/opa/MPI/.mpiinfo", "MPI_RPMS"); + if (run_fabric_cmd("cd /usr/src/opa/MPI && $BIN_DIR/opascpall -p -f $FabricSetupHostsFile $mpi_rpms /var/tmp")) { + return 1; + } + # need force for reinstall case + return run_fabric_cmd("$BIN_DIR/opacmdall -p -f $FabricSetupHostsFile 'cd /var/tmp; rpm -U --force $mpi_rpms; rm -f $mpi_rpms'"); +} +sub fabricsetup_opacmdall +{ + if (! valid_config_file("Host File", $FabricSetupHostsFile) ) { + return 1; + } + return run_fabric_opacmdall("$FabricSetupHostsFile", 0, "", ""); +} +sub fabricsetup_copyall +{ + my $file; + my $dir; + my $fabric_cmd; + + if (! valid_config_file("Host File", $FabricSetupHostsFile) ) { + return 1; + } + do { + print "Enter File to copy to all hosts (or none):"; + chomp($file = ); + $file=remove_whitespace($file); + } until ( length($file) != 0 ); + if ( "$file" ne "none" ) { + if ( substr($file,0,1) ne "/" ) { + chomp($dir=`pwd`); + $file="$dir/$file"; + } + $fabric_cmd="$BIN_DIR/opascpall -p -f $FabricSetupHostsFile $file $file"; + if (GetYesNo("About to run: $fabric_cmd\nAre you sure you want to proceed?", "n") ) { + return run_fabric_cmd("$fabric_cmd"); + } + } + return 0; +} +sub fabricsetup_viewres +{ + return ff_viewres(0,0); +} + +# Host Setup +sub fabric_setup +{ + my $result; + my $inp; + my %selected = (); + my %statusMessage = (); # TBD - not used + my $step; + my $i; + + foreach $step ( @FabricSetupSteps ) + { + $selected{$step}= 0; + } +DO_SETUP: + system "clear"; + print color("bold"); + printf ("FastFabric OPA Host Setup Menu\n"); + printf ("Host File: $FabricSetupHostsFile\n"); + print color("reset"); + for($i=0; $i < scalar(@FabricSetupSteps); $i++) + { + $step = $FabricSetupSteps[$i]; + print_delimiter("$FabricSetupStepsMenuDelimiter{$step}"); + printf ("%x) %-41s ", $i, $FabricSetupStepsName{$step}); + printStepSelected($selected{$step}, $statusMessage{$step}); + } + + printf ("\nP) Perform the Selected Actions N) Select None\n"); + printf ( "X) Return to Previous Menu (or ESC or Q)\n"); + + %statusMessage = (); + + $inp = getch(); + + if ($inp =~ /[qQ]/ || $inp =~ /[xX]/ || ord($inp) == $KEY_ESC) + { + return; + } + + if ($inp =~ /[nN]/ ) + { + foreach $step ( @FabricSetupSteps ) + { + $selected{$step}= 0; + } + } + elsif ($inp =~ /[0123456789abcdefABCDEF]/) + { + $step = $FabricSetupSteps[hex($inp)]; + $selected{$step}= ! $selected{$step}; + } + elsif ($inp =~ /[pP]/) + { + # perform the fabric setup + foreach $step ( @FabricSetupSteps ) + { + if ($selected{$step} ) + { + print LOG_FD "Performing Host Setup: $FabricSetupStepsName{$step}\n"; + print "\nPerforming Host Setup: $FabricSetupStepsName{$step}\n"; + $result = eval "fabricsetup_$step"; + $selected{$step} = 0; + if ( $result ) { + goto DO_SETUP + } + } + } + } + + goto DO_SETUP; +} + +sub fabricadmin_config +{ + my $inp; + my $file; + + print "Using $Editor (to select a different editor, export EDITOR).\n"; + do { + if (setup_ffconfig() ) { + return 1; + } + if (setup_ffports() ) { + return 1; + } + do + { + print "The FastFabric operations which follow will require a file\n"; + print "listing the hosts to operate on\n"; + print "You should select a file which INCLUDES this host\n"; + print "Select Host File to Use/Edit [$PrevFabricAdminHostsFile]: "; + chomp($inp = ); + $inp=remove_whitespace($inp); + + if ( length($inp) == 0 ) + { + $file = $PrevFabricAdminHostsFile; + } else { + $file = $inp; + } + print "About to: $Editor $file\n"; + if ( HitKeyContAbortable() ) { + return 1; + } + system("$Editor '$file'"); + if ( ! -e "$file" ) { + print "You must create a Host File to proceed\n\n"; + } else { + $FabricAdminHostsFile=$file; + $PrevFabricAdminHostsFile=$file; + } + } until ( -e "$file"); + print "Selected Host File: $FabricAdminHostsFile\n"; + } until (! GetYesNo("Do you want to edit/review/change the files?", "y") ); + print LOG_FD "Selected Host File -> $FabricAdminHostsFile\n"; + return 0; +} + +sub fabricadmin_fabric_info +{ + if ( ! -e "$BIN_DIR/opafabricinfo" ) { + print "opafabricinfo requires $ComponentName{oftools} be installed\n"; + HitKeyCont; + return 1; + } + return run_fabric_cmd("$BIN_DIR/opafabricinfo"); +} +#sub fabricadmin_opapingall +#{ +# if ( ! -e "$FabricAdminHostsFile" ) { +# print "$FabricAdminHostsFile: not found\n"; +# print "You must create/select a Host File to proceed\n"; +# HitKeyCont; +# return 1; +# } +# return run_fabric_cmd("/sbin/opapingall -p -f $FabricAdminHostsFile"); +#} +sub fabricadmin_findgood +{ + my $findgood_opts=""; + + if ( -e "$PrevFabricAdminHostsFile" + && "$PrevFabricAdminHostsFile" ne "$FabricAdminHostsFile" ) { + if (GetYesNo("Would you like to go back to using $PrevFabricAdminHostsFile?", "y") ) { + $FabricAdminHostsFile = $PrevFabricAdminHostsFile; + } + } + if (! valid_config_file("Host File", $FabricAdminHostsFile) ) { + return 1; + } + if (! GetYesNo("Would you like to verify hosts are ssh-able?", "y") ) { + # skip ssh test + $findgood_opts="$findgood_opts -R"; + } + if (! GetYesNo("Would you like to verify host OPA ports are active?", "y") ) { + # skip active test + $findgood_opts="$findgood_opts -A"; + } + if (! GetYesNo("Would you like to verify host OPA ports are not quarantined?", "y") ) { + # skip quarantine test + $findgood_opts="$findgood_opts -Q"; + } + if ( run_fabric_cmd("$BIN_DIR/opafindgood $findgood_opts -f $FabricAdminHostsFile")) { + return 1; + } + # ask even if non-bad since good file will be better sorted for cabletest + #if (-s $OPA_CONFIG_DIR/bad) { + if ( "$FabricAdminHostsFile" ne "$OPA_CONFIG_DIR/good") { + if (GetYesNo("Would you like to now use $OPA_CONFIG_DIR/good as Host File?", "y") ) { + $PrevFabricAdminHostsFile = "$FabricAdminHostsFile"; + $FabricAdminHostsFile = "$OPA_CONFIG_DIR/good"; + } + } + return 0; +} + +sub fabricadmin_singlehost +{ + my $verifyhosts_opts=""; + my $verifyhosts_tests=""; + my $result_dir = read_ffconfig_param("FF_RESULT_DIR"); + my $hostverify_sample = "/usr/share/opa/samples/hostverify.sh"; + my $hostverify_default = read_ffconfig_param("FF_HOSTVERIFY_DIR") . "/hostverify_default.sh"; + my $hostverify = ""; + my $hostverify_res = "hostverify.res"; + my $inp; + my $timelimit = 1; + my $hostverify_specific = read_ffconfig_param("FF_HOSTVERIFY_DIR") . "/hostverify_" . basename($FabricAdminHostsFile) . ".sh"; + my $use_specific = 0; + + if (! valid_config_file("Host File", $FabricAdminHostsFile) ) { + return 1; + } + if (GetYesNo("Would you like to use $hostverify_specific?", "y") ) { + $use_specific = 1; + $hostverify = $hostverify_specific; + } else { + $hostverify = $hostverify_default; + } + + if ( ! -e "$hostverify" ) { + copy_data_file("$hostverify_sample", "$hostverify"); + } + + if (GetYesNo("Would you like to copy $hostverify_sample to $hostverify?", "n") ) { + copy_data_file("$hostverify_sample", "$hostverify"); + } + + if (GetYesNo("Would you like to edit $hostverify?", "y") ) { + + print "About to: $Editor $hostverify\n"; + if ( HitKeyContAbortable() == 1) { + return 1; + } + system("$Editor $hostverify"); + if (! $use_specific) { + if (GetYesNo("Would you like to save $hostverify locally as $hostverify_specific?", "n") ) { + copy_data_file("$hostverify", "$hostverify_specific"); + } + } else { + if (GetYesNo("Would you like to save $hostverify locally as $hostverify_default?", "n") ) { + copy_data_file("$hostverify", "$hostverify_default"); + } + } + } + + print "Choose n below only if $hostverify on hosts has not changed \n"; + if (GetYesNo("Would you like to copy $hostverify to hosts?", "y") ) { + $verifyhosts_opts="-c"; # copy the hostverify.sh file + } + + if (GetYesNo("Would you like to specify tests to run?", "n") ) { + print "Enter space separated list of hostverify tests [default hpl]: "; + chomp($inp = ); + $inp=remove_whitespace($inp); + if ( length($inp) != 0 ) + { + $verifyhosts_tests="$inp"; + } else { + $verifyhosts_tests="default hpl"; + } + } + + #If HPL test is to be run, make sure mpi-tests package is installed + if (index($verifyhosts_tests,"hpl") != -1) { + if (!installed_mpiapps()) { + print "Package $ComponentName{mpiapps} not installed. Cannot hun HPL test.\n"; + HitKeyCont; + return 1; + } + } + + print "Enter filename for upload destination file [$hostverify_res]: "; + chomp($inp = ); + $inp=remove_whitespace($inp); + + if ( length($inp) != 0 ) + { + $hostverify_res = $inp; + } + + #Get timelimit, and suggest a higher default if HPL test is being run. + if (index($verifyhosts_tests,"hpl") != -1) { + $timelimit=GetNumericValue("Timelimit in minutes:", 5, 1, 100) * 60; + } else { + $timelimit=GetNumericValue("Timelimit in minutes:", 1, 1, 100) * 60; + } + + + if (check_load($FabricAdminHostsFile, "", "prior to verification") ) { + return 1; + } + run_fabric_cmd("$BIN_DIR/opaverifyhosts -k $verifyhosts_opts -u $hostverify_res -T $timelimit -f $FabricAdminHostsFile -F $hostverify $verifyhosts_tests", "skip_prompt"); + print "About to: $Editor $result_dir/verifyhosts.res\n"; + if ( HitKeyContAbortable() ) { + return 1; + } + system("$Editor '$result_dir/verifyhosts.res'"); + return 0; +} + +sub fabricadmin_showallports +{ + my $linkanalysis=0; + my $linkanalysis_opts=""; + my $linkanalysis_reports=""; + my $topology=0; + my $result_dir = read_ffconfig_param("FF_RESULT_DIR"); + my $linkanalysis_file = "$result_dir/linkanalysis.res"; + my $inp; + + if (GetYesNo("Would you like to perform fabric error analysis?", "y") ) { + $linkanalysis=1; + $linkanalysis_reports="$linkanalysis_reports errors"; + if (GetYesNo("Clear error counters after generating report?", "n") ) { + $linkanalysis_reports="$linkanalysis_reports clearerrors"; + if (GetYesNo("Force Clear of hardware error counters after generating report?", "n") ) { + $linkanalysis_reports="$linkanalysis_reports clearhwerrors"; + } + } + } + if (GetYesNo("Would you like to perform fabric link speed error analysis?", "y") ) { + $linkanalysis=1; + $linkanalysis_reports="$linkanalysis_reports slowlinks"; + if (GetYesNo("Check for links configured to run slower than supported?", "n") ) { + $linkanalysis_reports="$linkanalysis_reports misconfiglinks"; + } + if (GetYesNo("Check for links connected with mismatched speed potential?", "n") ) { + $linkanalysis_reports="$linkanalysis_reports misconnlinks"; + } + } + print "\nThe fabric deployment can be verified against the planned topology.\n"; + print "Typically the planned topology will have been converted to an XML topology\n"; + print "file using opaxlattopology or a customized variation.\n"; + print "If this step has been done and a topology file has been placed in the\n"; + print "location specified by the FF_TOPOLOGY_FILE in opafastfabric.conf then\n"; + print "a topology verification can be performed.\n"; + print "Refer to the FastFabric CLI reference guide for more info.\n\n"; + if (GetYesNo("Would you like to verify fabric topology?", "y") ) { + # TBD - check for presence of topology files + if (GetYesNo("Verify all aspects of topology (links, nodes, SMs)?", "y") ) { + $linkanalysis=1; + $topology=1; + $linkanalysis_reports="$linkanalysis_reports verifyall"; + } else { + # given venn diagram of types of links checked in verify*links + # reasonable choices are: + # verifylinks + # or + # verifyextlinks + # or + # verfyfilinks and/or ( verifyislinks or verifyextislinks) + # Note we do not have a verifyextfilinks since most fi links are ext + if (GetYesNo("Verify all link topology (backplanes and cables)?", "y") ) { + $linkanalysis=1; + $topology=1; + $linkanalysis_reports="$linkanalysis_reports verifylinks"; + } elsif (GetYesNo("Verify cable link topology (HFIs and switches)?", "y") ) { + $linkanalysis=1; + $topology=1; + $linkanalysis_reports="$linkanalysis_reports verifyextlinks"; + } else { + if (GetYesNo("Verify inter-switch link topology (backplanes and cables)?", "y") ) { + $linkanalysis=1; + $topology=1; + $linkanalysis_reports="$linkanalysis_reports verifyislinks"; + } elsif (GetYesNo("Verify cable inter-switch link topology?", "y") ) { + $linkanalysis=1; + $topology=1; + $linkanalysis_reports="$linkanalysis_reports verifyextislinks"; + } + if (GetYesNo("Verify FI link topology?", "y") ) { + $linkanalysis=1; + $topology=1; + $linkanalysis_reports="$linkanalysis_reports verifyfilinks"; + } + } + if (GetYesNo("Verify all nodes?", "y") ) { + $linkanalysis=1; + $topology=1; + $linkanalysis_reports="$linkanalysis_reports verifynodes"; + } + if (GetYesNo("Verify all SMs?", "y") ) { + $linkanalysis=1; + $topology=1; + $linkanalysis_reports="$linkanalysis_reports verifysms"; + } + } + if ($topology) { + if (! GetYesNo("Include unexpected devices in punchlist?", "y") ) { + $linkanalysis_opts="$linkanalysis_opts -U"; + } + } + } + print "Enter filename for results [$linkanalysis_file]: "; + chomp($inp = ); + $inp=remove_whitespace($inp); + + if ( length($inp) != 0 ) + { + $linkanalysis_file = $inp; + } + if ($linkanalysis) { + my $snapshot_suffix=`date +%Y%m%d-%H%M%S`; + chop $snapshot_suffix; + if ( run_fabric_cmd("$BIN_DIR/opalinkanalysis $linkanalysis_opts -x '$snapshot_suffix' $linkanalysis_reports > $linkanalysis_file 2>&1", "skip_prompt") ) { + return 1; + } + } else { + if (! valid_config_file("Host File", $FabricAdminHostsFile) ) { + return 1; + } + if ( run_fabric_cmd("$BIN_DIR/opashowallports -f $FabricAdminHostsFile > $linkanalysis_file 2>&1", "skip_prompt") ) { + return 1; + } + } + print "About to: $Editor $linkanalysis_file\n"; + if ( HitKeyContAbortable() ) { + return 1; + } + system("$Editor '$linkanalysis_file'"); + return 0; +} +sub fabricadmin_sacache +{ + if (! valid_config_file("Host File", $FabricAdminHostsFile) ) { + return 1; + } + return run_fabric_cmd("$BIN_DIR/opahostadmin -f $FabricAdminHostsFile sacache"); +} +sub fabricadmin_ipoibping +{ + if (! valid_config_file("Host File", $FabricAdminHostsFile) ) { + return 1; + } + return run_fabric_cmd("$BIN_DIR/opahostadmin -f $FabricAdminHostsFile ipoibping"); +} +sub fabricadmin_refreshssh +{ + if (! valid_config_file("Host File", $FabricAdminHostsFile) ) { + return 1; + } + return run_fabric_cmd("$BIN_DIR/opasetupssh -p -U -f $FabricAdminHostsFile"); +} +sub fabricadmin_mpiperf +{ + if (! valid_config_file("Host File", $FabricAdminHostsFile) ) { + return 1; + } + if (GetYesNo("Test Latency and Bandwidth deviation between all hosts?", "y") ) { + if (check_load($FabricAdminHostsFile, "", "prior to test")) { + return 1; + } + return run_fabric_cmd("$BIN_DIR/opahostadmin -f $FabricAdminHostsFile mpiperfdeviation"); + } else { + + if (!installed_mpiapps()) { + print "Package $ComponentName{mpiapps} not installed.\n"; + print "Cannot run the mpiperf tests. Deviation tests can still be used. Please try again. \n"; + HitKeyCont; + return 1; + } + + if (check_load($FabricAdminHostsFile, "", "prior to test")) { + return 1; + } + return run_fabric_cmd("$BIN_DIR/opahostadmin -f $FabricAdminHostsFile mpiperf"); + } +} +sub fabricadmin_health +{ + # TBD - esm_chassis and chassis file + if (GetYesNo("Baseline present configuration?", "n") ) { + return run_fabric_cmd("$BIN_DIR/opaallanalysis -b"); + } else { + return run_fabric_cmd("$BIN_DIR/opaallanalysis"); + } +} +sub fabricadmin_cabletest +{ + my $IFS_FM_BASE="/usr/lib/opa-fm"; + my $rundir="$IFS_FM_BASE/bin"; + my $cabletest_opts = ""; + my $cabletest_file = ""; + my $cabletest_cmds = ""; + my $check_load_before = 0; + + do { + if (GetYesNo("Stop or cleanup any already running Cable Test?", "y") ) { + if (GetYesNo("Stop HFI-Switch Cable Test?", "y") ) { + if ( ! -e "$FabricAdminHostsFile" ) { + print "$FabricAdminHostsFile: not found\n"; + print "You must create/select a Host File to proceed\n"; + HitKeyCont; + return 1; + } + $cabletest_file="-f '$FabricAdminHostsFile'"; + $cabletest_cmds="$cabletest_cmds stop_fi"; + } + if ( -e "$rundir/fm_cmdall" ) { + if (GetYesNo("Stop ISL Cable Test?", "y") ) { + $cabletest_cmds="$cabletest_cmds stop_isl"; + } + } + } + + if (GetYesNo("Start Cable Test?", "y") ) { + if (GetYesNo("Clear error counters?", "y") ) { + if (GetYesNo("Force Clear of hardware error counters too?", "y") ) { + $cabletest_opts="$cabletest_opts -A"; + } else { + $cabletest_opts="$cabletest_opts -C"; + } + } + if (GetYesNo("Start HFI-Switch Cable Test?", "y") ) { + if ( ! -e "$FabricAdminHostsFile" ) { + print "$FabricAdminHostsFile: not found\n"; + print "You must create/select a Host File to proceed\n"; + HitKeyCont; + return 1; + } + my $numprocs=GetNumericValue("Number of Processes per host:", 3, 1, 64); + $cabletest_opts="$cabletest_opts -n $numprocs"; + $cabletest_cmds="$cabletest_cmds start_fi"; + $cabletest_file="-f '$FabricAdminHostsFile'"; + $check_load_before = 1; + } + + if ( -e "$rundir/fm_cmdall" ) { + if (GetYesNo("Start ISL Cable Test?", "y") ) { + $cabletest_cmds="$cabletest_cmds start_isl"; + } + } + } + if ( $check_load_before) { + if (check_load($FabricAdminHostsFile, "", "prior to test")) { + return 1; + } + } + if ( "$cabletest_opts" ne "" || "$cabletest_cmds" ne "" ) { + print "About to run: $BIN_DIR/opacabletest $cabletest_opts $cabletest_file $cabletest_cmds\n"; + if ( HitKeyContAbortable() ) { + return 1; + } + return run_fabric_cmd("$BIN_DIR/opacabletest $cabletest_opts $cabletest_file $cabletest_cmds"); + } + } until (GetYesNo("No selection made. Are you sure you want to proceed?", "n") ); +} +sub fabricadmin_opacaptureall +{ + my $detail; + + if (! valid_config_file("Host File", $FabricAdminHostsFile) ) { + return 1; + } + $detail=GetNumericValue("Capture detail level (1-Normal 2-Fabric 3-Fabric+FDB 4-Analysis):", 4, 1, 4); + return run_fabric_cmd("$BIN_DIR/opacaptureall -p -D $detail -f $FabricAdminHostsFile"); +} +sub fabricadmin_opacmdall +{ + if (! valid_config_file("Host File", $FabricAdminHostsFile) ) { + return 1; + } + return run_fabric_opacmdall("$FabricAdminHostsFile", 0, "", ""); +} +sub fabricadmin_viewres +{ + return ff_viewres(1,1); +} + +# Host Admin +sub fabric_admin +{ + my $result; + my $inp; + my %selected = (); + my %statusMessage = (); # TBD - not used + my $step; + my $i; + + foreach $step ( @FabricAdminSteps ) + { + $selected{$step}= 0; + } +DO_SETUP: + system "clear"; + print color("bold"); + printf ("FastFabric OPA Host Verification/Admin Menu\n"); + printf ("Host File: $FabricAdminHostsFile\n"); + print color("reset"); + for($i=0; $i < scalar(@FabricAdminSteps); $i++) + { + $step = $FabricAdminSteps[$i]; + print_delimiter("$FabricAdminStepsMenuDelimiter{$step}"); + printf ("%x) %-48s ", $i, $FabricAdminStepsName{$step}); + printStepSelected($selected{$step}, $statusMessage{$step}); + } + + printf ("\nP) Perform the Selected Actions N) Select None\n"); + printf ( "X) Return to Previous Menu (or ESC or Q)\n"); + + %statusMessage = (); + + $inp = getch(); + + if ($inp =~ /[qQ]/ || $inp =~ /[xX]/ || ord($inp) == $KEY_ESC) + { + return; + } + + if ($inp =~ /[nN]/ ) + { + foreach $step ( @FabricAdminSteps ) + { + $selected{$step}= 0; + } + } + elsif ($inp =~ /[0123456789abcdefABCDEF]/) + { + $step = $FabricAdminSteps[hex($inp)]; + $selected{$step}= ! $selected{$step}; + } + elsif ($inp =~ /[pP]/) + { + # perform the fabric admin + foreach $step ( @FabricAdminSteps ) + { + if ($selected{$step} ) + { + print LOG_FD "Performing Host Admin: $FabricAdminStepsName{$step}\n"; + print "\nPerforming Host Admin: $FabricAdminStepsName{$step}\n"; + $result = eval "fabricadmin_$step"; + $selected{$step} = 0; + if ( $result ) + { + goto DO_SETUP + } + } + } + } + + goto DO_SETUP; +} + +# Fabric Monitor +sub fabricmonitor_opatop +{ + return run_fabric_cmd("$BIN_DIR/opatop"); +} +sub fabric_monitor +{ + my $result; + my $inp; + my %selected = (); + my %statusMessage = (); # TBD - not used + my $step; + my $i; + + foreach $step ( @FabricMonitorSteps ) + { + $selected{$step}= 0; + } +DO_SETUP: + system "clear"; + print color("bold"); + printf ("FastFabric OPA Fabric Monitoring Menu\n\n"); + print color("reset"); + for($i=0; $i < scalar(@FabricMonitorSteps); $i++) + { + $step = $FabricMonitorSteps[$i]; + print_delimiter("$FabricMonitorStepsMenuDelimiter{$step}"); + printf ("%x) %-41s ", $i, $FabricMonitorStepsName{$step}); + printStepSelected($selected{$step}, $statusMessage{$step}); + } + + printf ("\nP) Perform the Selected Actions N) Select None\n"); + printf ( "X) Return to Previous Menu (or ESC or Q)\n"); + + %statusMessage = (); + + $inp = getch(); + + if ($inp =~ /[qQ]/ || $inp =~ /[xX]/ || ord($inp) == $KEY_ESC) + { + return; + } + + if ($inp =~ /[nN]/ ) + { + foreach $step ( @FabricMonitorSteps ) + { + $selected{$step}= 0; + } + } + elsif ($inp =~ /[0123456789abcdefABCDEF]/) + { + $step = $FabricMonitorSteps[hex($inp)]; + $selected{$step}= ! $selected{$step}; + } + elsif ($inp =~ /[pP]/) + { + # perform the fabric monitor + foreach $step ( @FabricMonitorSteps ) + { + if ($selected{$step} ) + { + print LOG_FD "Performing Fabric Monitoring: $FabricMonitorStepsName{$step}\n"; + print "\nPerforming Fabric Monitoring: $FabricMonitorStepsName{$step}\n"; + $result = eval "fabricmonitor_$step"; + $selected{$step} = 0; + if ( $result ) + { + goto DO_SETUP + } + } + } + } + + goto DO_SETUP; +} + +sub chassis_config +{ + my $inp; + my $file; + + print "Using $Editor (to select a different editor, export EDITOR).\n"; + do { + if (setup_ffconfig() ) { + return 1; + } + if (setup_ffports() ) { + return 1; + } + do + { + print "The FastFabric operations which follow will require a file\n"; + print "listing the chassis to operate on\n"; + print "Select Chassis File to Use/Edit [$FabricChassisFile]: "; + chomp($inp = ); + $inp=remove_whitespace($inp); + + if ( length($inp) == 0 ) + { + $file = $FabricChassisFile; + } else { + $file = $inp; + } + print "About to: $Editor $file\n"; + if ( HitKeyContAbortable() ) { + return 1; + } + system("$Editor '$file'"); + if ( ! -e "$file" ) { + print "You must create a Chassis File to proceed\n\n"; + } else { + $FabricChassisFile=$file; + } + } until ( -e "$file"); + print "Selected Chassis File: $FabricChassisFile\n"; + } until (! GetYesNo("Do you want to edit/review/change the files?", "y") ); + print LOG_FD "Selected Chassis File -> $FabricChassisFile\n"; + return 0; +} + +sub chassis_getconfig +{ + if (! valid_config_file("Chassis File", $FabricChassisFile) ) { + return 1; + } + return run_fabric_cmd("$BIN_DIR/opachassisadmin -F $FabricChassisFile getconfig"); +} + +sub chassis_fmgetsecurityfiles +{ + return run_fabric_cmd("$BIN_DIR/opachassisadmin -F $FabricChassisFile fmgetsecurityfiles"); +} + + +# expand security files list, returns "" if "none" or has invalid entries +sub chassis_expand_fmsecurityfiles +{ + my $packages = $_[0]; + my $all_packages=""; + if ( "$packages" eq "none" ) { + return ""; + } + foreach my $package (split(/[[:space:]]+/, "$packages")) { + # file or directory (can be wildcards) + # expand directory, also filters files without .pem suffix + my $expanded = `find $package -type f -name '*.pem' 2>/dev/null`; + if ( $expanded eq "" ) { + print "$package: No .pem files found\n"; + return ""; + } + $all_packages="$all_packages$expanded"; + } + return "$all_packages"; +} + +sub chassis_fmsecurityfiles +{ + my $packages="$FabricChassisPackages"; + my $parallel=1; + my $query=0; + my $action; + my $all_packages=""; + my $Sopt=""; + + if (! valid_config_file("Chassis File", $FabricChassisFile) ) { + return 1; + } + do { +QUERY: + $Sopt=""; + do { + if ( $query ) { + # we must query again, don't check validity + } elsif ( "$packages" eq "none" ) { + $query=1; + } else { + $all_packages=chassis_expand_fmsecurityfiles("$packages"); + if ("$all_packages" eq "") { + $query=1; + } + } + if ( ! $query ) { + $query = ! GetYesNo("Do you want to use $packages?", "y"); + } + if ( $query ) { + do { + print "Multiple FM Security files and/or Directories may be space separated\n"; + print "Shell wildcards may be used\n"; + print "For Directories all .pem files in the directory tree will be used\n"; + print "Enter Files/Directories to use (or none):"; + chomp($packages = ); + $packages=remove_whitespace($packages); + } until ( length($packages) != 0 ); + $all_packages=chassis_expand_fmsecurityfiles("$packages"); + if ("$packages" eq "none" || "$all_packages" ne "") { + $query=0; + } + } + } until ( ! $query); + if ("$packages" eq "none" ) { + print "You have selected to skip the security files upgrade step\n"; + $action="skip"; + } else { + print "You have selected to use: $packages\n"; + print "The following security files will be used:\n"; + #$all_packages =~ s/^/ /mg; + #print "$all_packages"; + my $file; + my $ver; + my $type; + foreach $file (split(/[[:space:]]+/, "$all_packages")) + { + print "$file\n"; + } + if ( $query ) { + goto QUERY; + } + $FabricChassisPackages="$all_packages"; + $parallel=1; + print "\nAfter push of the security files, the FM may be started/restarted\n"; + if (GetYesNo("Would you like to restart the FM?", "n") ) { + if (GetYesNo("Would you like to run the FM on slave MMs?", "n") ) { + $action="restartall"; + print "You have selected to push, and restart the FM on all MMs\n\n"; + } else { + $action="restart"; + print "You have selected to push, and restart the FM on master MMs (stop on slaves)\n\n"; + } + + print "There will be a disruption as FMs are restarted\n"; + print "Doing the operation in parallel (on multiple chassis) will finish the fastest\n"; + print "Doing it serially may reduce disruption\n"; + if (GetYesNo("Would you like to do the operation in parallel?", "y") ) { + print "You have selected to perform the push, and FM restart in parallel\n\n"; + $parallel=1; + } else { + print "You have selected to perform the push, and FM restart serially\n\n"; + $parallel=0; + } + } elsif (GetYesNo("Would you like to push the security files?", "n") ) { + $action="push"; + print "You have selected to push FM security files\n"; + } else { + print "You have selected to skip the security files upgrade step\n"; + $action="skip"; + } + } + if ( "$action" ne "skip" ) { + if (GetYesNo("Would you like to be prompted for chassis' password?", "n") ) { + $Sopt="-S"; + } + } + } until (GetYesNo("Are you sure you want to proceed?", "n") ); + if ( "$action" ne "skip" ) { + my $pathnames=expand_pathnames($FabricChassisPackages); + if ( $parallel ) { + return run_fabric_cmd("$BIN_DIR/opachassisadmin $Sopt -F $FabricChassisFile -s '$pathnames' -a $action fmsecurityfiles"); + } else { + return run_fabric_cmd("FF_MAX_PARALLEL=0 $BIN_DIR/opachassisadmin $Sopt -F $FabricChassisFile -s '$pathnames' -a $action fmsecurityfiles"); + } + } +} + +sub chassis_opapingall +{ + if (! valid_config_file("Chassis File", $FabricChassisFile) ) { + return 1; + } + return run_fabric_cmd("$BIN_DIR/opapingall -C -p -F $FabricChassisFile"); +} + +sub chassis_setup +{ + my $Sopt = ""; + + if (! valid_config_file("Chassis File", $FabricChassisFile) ) { + return 1; + } + if (GetYesNo("Would you like to be prompted for chassis' password?", "n") ) { + $Sopt="-S"; + } + return run_fabric_cmd("$BIN_DIR/opachassisadmin $Sopt -F $FabricChassisFile configure"); +} + +sub chassis_setupssh +{ + my $opt; + + if (! valid_config_file("Chassis File", $FabricChassisFile) ) { + return 1; + } + if (GetYesNo("Would you like to override the default Chassis password?", "n") ) { + $opt="-S"; + } else { + $opt=""; + print "Default Chassis password will be used to perform the setup\n"; + } + return run_fabric_cmd("$BIN_DIR/opasetupssh -p $opt -C -F $FabricChassisFile"); +} + +# expand directory list, expands any ~ characters +sub expand_pathnames +{ + my $pathnames = $_[0]; + my $all_pathnames=""; + my $first=1; + foreach my $pathname (split(/[[:space:]]+/, "$pathnames")) { + # file or directory (can be wildcards) + # expand directory, also filters files without .dpkg or .spkg suffix + my $expanded = `echo -n $pathname`; + if ( $expanded ne "" ) { + if ( $first ) { + $all_pathnames="$expanded"; + $first=0; + } else { + $all_pathnames="$all_pathnames $expanded"; + } + } + } + return "$all_pathnames"; +} + +# expand package list, returns "" if "none" or has invalid entries +sub chassis_expand_fwpackages +{ + my $packages = $_[0]; + my $all_packages=""; + if ( "$packages" eq "none" ) { + return ""; + } + foreach my $package (split(/[[:space:]]+/, "$packages")) { + # file or directory (can be wildcards) + # expand directory, also filters files without .dpkg or .spkg suffix + my $expanded = `find $package -type f -name '*.[ds]pkg' 2>/dev/null`; + if ( $expanded eq "" ) { + print "$package: No .dpkg nor .spkg files found\n"; + return ""; + } + $all_packages="$all_packages$expanded"; + } + return "$all_packages"; +} +sub chassis_fwpush +{ + my $packages="$FabricChassisPackages"; + my $parallel=1; + my $query=0; + my $action; + my $all_packages=""; + my $Sopt=""; + + if (! valid_config_file("Chassis File", $FabricChassisFile) ) { + return 1; + } + do { +QUERY: + $Sopt=""; + do { + if ( $query ) { + # we must query again, don't check validity + } elsif ( "$packages" eq "none" ) { + $query=1; + } else { + $all_packages=chassis_expand_fwpackages("$packages"); + if ("$all_packages" eq "") { + $query=1; + } + } + if ( ! $query ) { + $query = ! GetYesNo("Do you want to use $packages?", "y"); + } + if ( $query ) { + do { + print "Multiple Firmware files and/or Directories may be space separated\n"; + print "Shell wildcards may be used\n"; + print "For Directories all .dpkg or .spkg files in the directory tree will be used\n"; + print "Enter Files/Directories to use (or none):"; + chomp($packages = ); + $packages=remove_whitespace($packages); + } until ( length($packages) != 0 ); + $all_packages=chassis_expand_fwpackages("$packages"); + if ("$packages" eq "none" || "$all_packages" ne "") { + $query=0; + } + } + } until ( ! $query); + if ("$packages" eq "none" ) { + print "You have selected to skip the firmware upgrade step\n"; + $action="skip"; + } else { + print "You have selected to use: $packages\n"; + print "The following firmware files will be used:\n"; + #$all_packages =~ s/^/ /mg; + #print "$all_packages"; + my $file; + my $ver; + my $type; + foreach $file (split(/[[:space:]]+/, "$all_packages")) + { + $ver=`$BIN_DIR/opafirmware --showVersion $file 2>/dev/null`; + chomp($ver); + $type=`$BIN_DIR/opafirmware --showType $file 2>/dev/null`; + chomp($type); + if ( "$ver" eq "" || "$type" eq "" ) { + $query=1; + print "$file\n\tInvalid Firmware File\n"; + } else { + print "$file\n\tVersion: $ver\tType: $type\n"; + } + } + if ( $query ) { + goto QUERY; + } + $FabricChassisPackages="$packages"; + $parallel=1; + print "After push, the firmware may be optionally selected or booted\n"; + if (GetYesNo("Would you like to run the firmware now?", "n") ) { + $action="run"; + print "You have selected to push, select and reboot to the firmware\n"; + print "There will be a disruption as chassis or slots are rebooted\n"; + print "Doing the operation in parallel (on multiple chassis) will finish the fastest\n"; + print "Doing it serially may reduce disruption\n"; + if (GetYesNo("Would you like to do the operation in parallel?", "y") ) { + print "You have selected to perform the push, select and reboot in parallel\n"; + $parallel=1; + } else { + print "You have selected to perform the push, select and reboot serially\n"; + $parallel=0; + } + } elsif (GetYesNo("Would you like to select the firmware?", "n") ) { + $action="select"; + print "You have selected to push and select the firmware, but not run it\n"; + } elsif (GetYesNo("Would you like to push the firmware?", "n") ) { + $action="push"; + print "You have selected to push firmware but not select nor run it\n"; + } else { + print "You have selected to skip the firmware upgrade step\n"; + $action="skip"; + } + } + if ( "$action" ne "skip" ) { + if (GetYesNo("Would you like to be prompted for chassis' password?", "n") ) { + $Sopt="-S"; + } + } + } until (GetYesNo("Are you sure you want to proceed?", "n") ); + if ( "$action" ne "skip" ) { + my $pathnames=expand_pathnames($all_packages); + if ( $parallel ) { + return run_fabric_cmd("$BIN_DIR/opachassisadmin $Sopt -F $FabricChassisFile -P '$pathnames' -a $action upgrade"); + } else { + return run_fabric_cmd("FF_MAX_PARALLEL=0 $BIN_DIR/opachassisadmin $Sopt -F $FabricChassisFile -P '$pathnames' -a $action upgrade"); + } + } +} + +sub chassis_prompt_fm_bootstate() +{ + my $bootstate=""; + + if (GetYesNo("Would you like to change FM boot state to enable FM start at boot?", "n") ) { + if (GetYesNo("Would you like to enable FM start on slave MMs at boot?", "n") ) { + $bootstate=" -I enableall"; + print "You have selected to enable FM start at boot on all MMs\n\n"; + } else { + $bootstate=" -I enable"; + print "You have selected to enable FM start at boot on master MMs (disable on slaves)\n\n"; + } + }elsif (GetYesNo("Would you like to change FM boot state to disable FM start at boot?", "n") ) { + $bootstate=" -I disable"; + print "You have selected to disable FM start at boot\n\n"; + } else { + print "You have selected not to change FM start at boot options\n\n"; + } + return "$bootstate"; +} + +sub chassis_fmconfig +{ + my $fmconfig="$FabricChassisFMConfig"; + my $parallel=1; + my $query=0; + my $action; + my $bootstate=""; + my $Sopt=""; + my $tooldir; + + if (! valid_config_file("Chassis File", $FabricChassisFile) ) { + return 1; + } + if ( -e "/usr/lib/opa/fm_tools" ) { + $tooldir="/usr/lib/opa/fm_tools"; + } else { + my $IFS_FM_BASE="/usr/lib/opa-fm"; + $tooldir="$IFS_FM_BASE/bin"; + } + my $can_generate=( -e "$tooldir/config_generate"); + do { +QUERY: + $Sopt=""; + $bootstate=""; + do { + if ( $query ) { + # we must query again, don't check validity + } elsif ( "$fmconfig" eq "none" || "$fmconfig" eq "") { + $query=1; + } + if ( ! $query ) { + $query = ! GetYesNo("Do you want to use $fmconfig?", "y"); + } + if ( $query ) { + do { + if ($can_generate) { + print "Enter FM Config file to use (or none or generate):"; + } else { + print "Enter FM Config file to use (or none):"; + } + chomp($fmconfig = ); + $fmconfig=remove_whitespace($fmconfig); + } until ( length($fmconfig) != 0 ); + if ("$fmconfig" eq "none" || ($can_generate && "$fmconfig" eq "generate") || -e "$fmconfig") { + $query=0; + } + } + } until ( ! $query); + if ("$fmconfig" eq "none" ) { + print "You have selected to skip the configure FM step\n"; + $action="skip"; + } else { + if ($can_generate && "$fmconfig" eq "generate") { + print "You have selected to generate: ./opafm.xml\n"; + if (run_fabric_cmd("$tooldir/config_generate -e ./opafm.xml", "skip_prompt") != 0) { + $query=1; + goto QUERY; + } + $fmconfig="./opafm.xml"; + } + print "You have selected to use: $fmconfig\n"; + if ( -e "$tooldir/config_check" ) { + print "Syntax Checking $fmconfig...\n"; + print "Executing: $tooldir/config_check -s -c $fmconfig\n"; + if (system("$tooldir/config_check -s -c $fmconfig") != 0) { + print "Invalid FM Config File\n"; + $query=1; + goto QUERY; + } + print "Valid FM Config file: $fmconfig\n"; + } + $FabricChassisFMConfig="$fmconfig"; + $parallel=1; + + print "\nAfter push, the FM may be started/restarted\n"; + if (GetYesNo("Would you like to restart the FM?", "n") ) { + if (GetYesNo("Would you like to run the FM on slave MMs?", "n") ) { + $action="runall"; + print "You have selected to push, and restart the FM on all MMs\n\n"; + } else { + $action="run"; + print "You have selected to push, and restart the FM on master MMs (stop on slaves)\n\n"; + } + + print "There will be a disruption as FMs are restarted\n"; + print "Doing the operation in parallel (on multiple chassis) will finish the fastest\n"; + print "Doing it serially may reduce disruption\n"; + if (GetYesNo("Would you like to do the operation in parallel?", "y") ) { + print "You have selected to perform the push, and FM restart in parallel\n\n"; + $parallel=1; + } else { + print "You have selected to perform the push, and FM restart serially\n\n"; + $parallel=0; + } + } elsif (GetYesNo("Would you like to push the FM config file?", "n") ) { + $action="push"; + print "You have selected to push FM config but not restart the FMs\n\n"; + } else { + print "You have selected to skip the configure FM step\n\n"; + $action="skip"; + } + } + if ( "$action" ne "skip" ) { + $bootstate=chassis_prompt_fm_bootstate(); + + if (GetYesNo("Would you like to be prompted for chassis' password?", "n") ) { + $Sopt="-S"; + } + } + } until (GetYesNo("Are you sure you want to proceed?", "n") ); + + if ( "$action" ne "skip" ) { + my $pathnames=expand_pathnames($FabricChassisFMConfig); + if ( $parallel ) { + return run_fabric_cmd("$BIN_DIR/opachassisadmin $Sopt -F $FabricChassisFile -P '$pathnames' -a $action$bootstate fmconfig"); + } else { + return run_fabric_cmd("FF_MAX_PARALLEL=0 $BIN_DIR/opachassisadmin $Sopt -F $FabricChassisFile -P '$pathnames' -a $action$bootstate fmconfig"); + } + } +} + +sub chassis_showallports +{ + my $linkanalysis=0; + my $linkanalysis_opts=""; + my $linkanalysis_reports=""; + my $Sopt=""; + my $result_dir = read_ffconfig_param("FF_RESULT_DIR"); + my $linkanalysis_file = "$result_dir/linkanalysis.res"; + my $inp; + + if (GetYesNo("Would you like to perform fabric error analysis?", "y") ) { + $linkanalysis=1; + $linkanalysis_reports="$linkanalysis_reports errors"; + if (GetYesNo("Clear error counters after generating report?", "n") ) { + $linkanalysis_reports="$linkanalysis_reports clearerrors"; + if (GetYesNo("Force Clear of hardware error counters after generating report?", "n") ) { + $linkanalysis_reports="$linkanalysis_reports clearhwerrors"; + } + } + } + if (GetYesNo("Would you like to perform fabric link speed error analysis?", "y") ) { + $linkanalysis=1; + $linkanalysis_reports="$linkanalysis_reports slowlinks"; + if (GetYesNo("Check for links configured to run slower than supported?", "n") ) { + $linkanalysis_reports="$linkanalysis_reports misconfiglinks"; + } + if (GetYesNo("Check for links connected with mismatched speed potential?", "n") ) { + $linkanalysis_reports="$linkanalysis_reports misconnlinks"; + } + } + + print "Enter filename for results [$linkanalysis_file]: "; + chomp($inp = ); + $inp=remove_whitespace($inp); + + if ( length($inp) != 0 ) + { + $linkanalysis_file = $inp; + } + if ($linkanalysis) { + #my $snapshot_suffix=`date +%Y%m%d-%H%M%S`; + #chop $snapshot_suffix; + if ( run_fabric_cmd("$BIN_DIR/opalinkanalysis $linkanalysis_opts $linkanalysis_reports > $linkanalysis_file 2>&1", "skip_prompt") ) { + return 1; + } + } else { + if (! valid_config_file("Chassis File", $FabricChassisFile) ) { + return 1; + } + if (GetYesNo("Would you like to be prompted for chassis' password?", "n") ) { + $Sopt="-S"; + } + if ( run_fabric_cmd("$BIN_DIR/opashowallports -C $Sopt -F $FabricChassisFile > $linkanalysis_file 2>&1", "skip_prompt") ) { + return 1; + } + } + print "About to: $Editor $linkanalysis_file\n"; + if ( HitKeyContAbortable() ) { + return 1; + } + system("$Editor '$linkanalysis_file'"); + return 0; +} + +sub chassis_fmcontrol +{ + my $Sopt = ""; + my $bootstate = ""; + my $action; + my $parallel; + + if (! valid_config_file("Chassis File", $FabricChassisFile) ) { + return 1; + } + do { + $Sopt=""; + $bootstate=""; + if (GetYesNo("Would you like to restart the FM?", "n") ) { + if (GetYesNo("Would you like to run the FM on slave MMs?", "n") ) { + $action="restartall"; + print "You have selected to restart the FM on all MMs\n\n"; + } else { + $action="restart"; + print "You have selected to restart the FM on master MMs (stop on slaves)\n\n"; + } + print "There will be a disruption as FMs are restarted\n"; + print "Doing it serially may reduce disruption\n"; + } elsif (GetYesNo("Would you like to make sure the FM is not running?", "n") ) { + $action="stop"; + print "You have selected to make sure the FM is not running on any MMs\n\n"; + } elsif (GetYesNo("Would you like to make sure the FM is running?", "n") ) { + if (GetYesNo("Would you like to run FM on slave MMs?", "n") ) { + $action="runall"; + print "You have selected to run the FM on all MMs\n\n"; + } else { + $action="run"; + print "You have selected to run the FM on master MMs (stop on slaves)\n\n"; + } + } else { + print "You have selected to skip the control FM step\n"; + $action="skip"; + } + + if ( "$action" ne "skip" ) { + print "Doing the operation in parallel (on multiple chassis) will finish the fastest\n"; + if (GetYesNo("Would you like to do the operation in parallel?", "y") ) { + print "You have selected to perform the operation in parallel\n\n"; + $parallel=1; + } else { + print "You have selected to perform the operation serially\n\n"; + $parallel=0; + } + + $bootstate=chassis_prompt_fm_bootstate(); + + if (GetYesNo("Would you like to be prompted for chassis' password?", "n") ) { + $Sopt="-S"; + } + } + } until (GetYesNo("Are you sure you want to proceed?", "n") ); + if ( "$action" ne "skip" ) { + if ( $parallel ) { + return run_fabric_cmd("$BIN_DIR/opachassisadmin $Sopt -F $FabricChassisFile -a $action$bootstate fmcontrol"); + } else { + return run_fabric_cmd("FF_MAX_PARALLEL=0 $BIN_DIR/opachassisadmin $Sopt -F $FabricChassisFile -a $action$bootstate fmcontrol"); + } + } +} + +sub chassis_reboot +{ + my $Sopt = ""; + + if (! valid_config_file("Chassis File", $FabricChassisFile) ) { + return 1; + } + if (GetYesNo("Would you like to be prompted for chassis' password?", "n") ) { + $Sopt="-S"; + } + return run_fabric_cmd("$BIN_DIR/opachassisadmin $Sopt -F $FabricChassisFile reboot"); +} +sub chassis_opacaptureall +{ + my $Sopt = ""; + + if (! valid_config_file("Chassis File", $FabricChassisFile) ) { + return 1; + } + if (GetYesNo("Would you like to be prompted for chassis' password?", "n") ) { + $Sopt="-S"; + } + return run_fabric_cmd("$BIN_DIR/opacaptureall -C $Sopt -p -F $FabricChassisFile"); +} +sub chassis_opacmdall +{ + my $Sopt = ""; + + if (! valid_config_file("Chassis File", $FabricChassisFile) ) { + return 1; + } + if (GetYesNo("Would you like to be prompted for chassis' password?", "n") ) { + $Sopt="-S"; + } + return run_fabric_opacmdall("$FabricChassisFile", 1, "$Sopt", ""); +} +sub chassis_viewres +{ + return ff_viewres(1,0); +} + +# Chassis Admin +sub chassis_admin +{ + my $result; + my $inp; + my %selected = (); + my %statusMessage = (); # TBD - not used + my $step; + my $i; + + foreach $step ( @FabricChassisSteps ) + { + $selected{$step}= 0; + } +DO_SETUP: + system "clear"; + print color("bold"); + printf ("FastFabric OPA Chassis Setup/Admin Menu\n"); + printf ("Chassis File: $FabricChassisFile\n"); + print color("reset"); + for($i=0; $i < scalar(@FabricChassisSteps); $i++) + { + $step = $FabricChassisSteps[$i]; + print_delimiter("$FabricChassisStepsMenuDelimiter{$step}"); + printf ("%x) %-41s ", $i, $FabricChassisStepsName{$step}); + printStepSelected($selected{$step}, $statusMessage{$step}); + } + + printf ("\nP) Perform the Selected Actions N) Select None\n"); + printf ( "X) Return to Previous Menu (or ESC or Q)\n"); + + %statusMessage = (); + + $inp = getch(); + + if ($inp =~ /[qQ]/ || $inp =~ /[xX]/ || ord($inp) == $KEY_ESC) + { + return; + } + + if ($inp =~ /[nN]/ ) + { + foreach $step ( @FabricChassisSteps ) + { + $selected{$step}= 0; + } + } + elsif ($inp =~ /[0123456789abcdefABCDEF]/) + { + $step = $FabricChassisSteps[hex($inp)]; + $selected{$step}= ! $selected{$step}; + } + elsif ($inp =~ /[pP]/) + { + # perform the fabric admin + foreach $step ( @FabricChassisSteps ) + { + if ($selected{$step} ) + { + print LOG_FD "Performing Chassis Admin: $FabricChassisStepsName{$step}\n"; + print "\nPerforming Chassis Admin: $FabricChassisStepsName{$step}\n"; + $result = eval "chassis_$step"; + $selected{$step} = 0; + if ( $result ) + { + goto DO_SETUP + } + } + } + } + + goto DO_SETUP; +} + +sub ext_mgmt_sw_config +{ + my $inp; + my $file; + + print "Using $Editor (to select a different editor, export EDITOR).\n"; + do { + if (setup_ffconfig() ) { + return 1; + } + if (setup_ffports() ) { + return 1; + } + do + { + print "The FastFabric operations which follow will require a file\n"; + print "listing the externally managed switches to operate on\n"; + print "Select Switch File to Use/Edit [$FabricExtMgmtSwFile]: "; + chomp($inp = ); + $inp=remove_whitespace($inp); + + if ( length($inp) == 0 ) + { + $file = $FabricExtMgmtSwFile; + } else { + $file = $inp; + } + print "About to: $Editor $file\n"; + if ( HitKeyContAbortable() ) { + return 1; + } + system("$Editor '$file'"); + if ( ! -e "$file" ) { + print "You must create a Externally Managed Switch File to proceed\n\n"; + } else { + $FabricExtMgmtSwFile=$file; + } + } until ( -e "$file"); + print "Selected Externally Managed Switch File: $FabricExtMgmtSwFile\n"; + } until (! GetYesNo("Do you want to edit/review/change the files?", "y") ); + print LOG_FD "Selected Ports File -> " . read_ffconfig_param("PORTS_FILE") . "\n"; + print LOG_FD "Selected Externally Managed Switch File -> $FabricExtMgmtSwFile\n"; + return 0; +} + +sub ext_mgmt_sw_genopaswitches +{ + my $topology_file = read_ffconfig_param("FF_TOPOLOGY_FILE"); + do { + my $opts=""; + my $run = 0; + + if ( ! -e "$FabricExtMgmtSwFile" ) { + # we will generate the file + print "$FabricExtMgmtSwFile not found\n"; + print "This file will be generated based on present fabric contents\n"; + # omit -L option, will cause file generation + $run=1; + } elsif (empty_config_file($FabricExtMgmtSwFile) ) { + print "$FabricExtMgmtSwFile empty\n"; + print "This file will be regenerated based on present fabric contents\n"; + # omit -L option, will cause file generation + $run=1; + } else { + print "$FabricExtMgmtSwFile exists\n"; + if (GetYesNo("Do you want to regenerate $FabricExtMgmtSwFile?", "n")) { + $run=1; + } else { + # -L option causes no file generation + $opts="-L $FabricExtMgmtSwFile"; + } + } + if (GetYesNo("Do you want to update switch names based on\n$topology_file file(s)?", "y")) { + $opts="$opts -s"; + $run=1; + } + + if ( $run) { + my $fabric_cmd="$BIN_DIR/opagenswitches $opts -o $FabricExtMgmtSwFile"; + if (GetYesNo("About to run: $fabric_cmd\nAre you sure you want to proceed?", "n") ) { + return run_fabric_cmd("$fabric_cmd"); + } + } + } until (GetYesNo("No selection made. Are you sure you want to proceed?", "n") ); +} + +sub ext_mgmt_sw_ibping +{ + if (! valid_config_file("Externally Managed Switch File", $FabricExtMgmtSwFile) ) { + return 1; + } + return run_fabric_cmd("$BIN_DIR/opaswitchadmin -L $FabricExtMgmtSwFile ping"); +} + +sub ext_mgmt_sw_setup +{ + + if (! valid_config_file("Externally Managed Switch File", $FabricExtMgmtSwFile) ) { + return 1; + } + return run_fabric_cmd("$BIN_DIR/opaswitchadmin -F $FabricExtMgmtSwFile configure"); +} + +sub ext_mgmt_sw_switchinfo +{ + + if (! valid_config_file("Externally Managed Switch File", $FabricExtMgmtSwFile) ) { + return 1; + } + return run_fabric_cmd("$BIN_DIR/opaswitchadmin -L $FabricExtMgmtSwFile info"); +} +sub ext_mgmt_sw_getconfig +{ + + if (! valid_config_file("Externally Managed Switch File", $FabricExtMgmtSwFile) ) { + return 1; + } + return run_fabric_cmd("$BIN_DIR/opaswitchadmin -L $FabricExtMgmtSwFile getconfig"); +} + +sub ext_mgmt_sw_fwverify +{ + + if (! valid_config_file("Externally Managed Switch File", $FabricExtMgmtSwFile) ) { + return 1; + } + return run_fabric_cmd("$BIN_DIR/opaswitchadmin -L $FabricExtMgmtSwFile fwverify"); +} + +sub ext_mgmt_sw_hwvpd +{ + + if (! valid_config_file("Externally Managed Switch File", $FabricExtMgmtSwFile) ) { + return 1; + } + return run_fabric_cmd("$BIN_DIR/opaswitchadmin -L $FabricExtMgmtSwFile hwvpd"); +} + +sub ext_mgmt_sw_setup +{ + + if (! valid_config_file("Externally Managed Switch File", $FabricExtMgmtSwFile) ) { + return 1; + } + return run_fabric_cmd("$BIN_DIR/opaswitchadmin -L $FabricExtMgmtSwFile configure"); +} + +# expand package list, returns "" if "none" or has invalid entries +sub ext_mgmt_sw_expand_fwpackages +{ + my $packages = $_[0]; + my $all_packages=""; + if ( "$packages" eq "none" ) { + return ""; + } + foreach my $package (split(/[[:space:]]+/, "$packages")) { + # file or directory (can be wildcards) + # expand directory, also filters files without .emfw suffix + my $expanded = `find $package -type f -name '*.emfw' 2>/dev/null`; + if ( $expanded eq "" ) { + print "$package: No .emfw files found\n"; + return ""; + } + $all_packages="$all_packages$expanded"; + } + return "$all_packages"; +} + +sub ext_mgmt_sw_fwpush +{ + my $packages="$FabricExtMgmtSwPackages"; + my $parallel=1; + my $query=0; + my $action; + my $all_packages=""; + my $Oopt=""; + + if (! valid_config_file("Externally Managed Switch File", $FabricExtMgmtSwFile) ) { + return 1; + } + do { + do { + if ( $query ) { + # we must query again, don't check validity + } elsif ( "$packages" eq "none" ) { + $query=1; + } else { + $all_packages=ext_mgmt_sw_expand_fwpackages("$packages"); + if ("$all_packages" eq "") { + $query=1; + } + } + if ( ! $query ) { + $query = ! GetYesNo("Do you want to use $packages?", "y"); + } + if ( $query ) { + do { + print "Multiple Firmware files and/or Directories may be space separated\n"; + print "Shell wildcards may be used\n"; + print "For Directories all .emfw files in the directory tree will be used\n"; + print "Enter Files/Directories to use (or none):"; + chomp($packages = ); + $packages=remove_whitespace($packages); + } until ( length($packages) != 0 ); + $all_packages=ext_mgmt_sw_expand_fwpackages("$packages"); + if ("$packages" eq "none" || "$all_packages" ne "") { + $query=0; + } + } + } until ( ! $query); + if ("$packages" eq "none" ) { + print "You have selected to skip the firmware upgrade step\n"; + $action="skip"; + } else { + print "You have selected to use: $packages\n"; + print "The following firmware files will be used:\n"; + $all_packages =~ s/^/ /mg; + print "$all_packages"; + $FabricExtMgmtSwPackages="$packages"; + $parallel=1; + print "After upgrade, the switch may be optionally rebooted\n"; + if (GetYesNo("Would you like to reboot the switch after the update?", "n") ) { + $action="run"; + print "You have selected to update the switch firmware and reboot.\n"; + print "There will be a disruption as switch or switches are rebooted\n"; + print "Doing the operation in parallel (on multiple switches) will finish the fastest\n"; + print "Doing it serially may reduce disruption\n"; + if (GetYesNo("Would you like to do the operation in parallel?", "y") ) { + print "You have selected to perform the update and reboot in parallel\n"; + $parallel=1; + } else { + print "You have selected to perform the update and reboot serially\n"; + $parallel=0; + } + } else { + $action="select"; + print "You have selected to update the switch firmware but not reboot the switch.\n"; + print "Doing the operation in parallel (on multiple switches) will finish the fastest\n"; + print "Doing it serially may reduce disruption\n"; + if (GetYesNo("Would you like to do the operation in parallel?", "y") ) { + print "You have selected to perform the update in parallel\n"; + $parallel=1; + } else { + print "You have selected to perform the update serially\n"; + $parallel=0; + } + } + $Oopt = ""; + print "The firmware on the switch will be checked. If the running version is the same\n"; + print "as the version being used for the update, the update operation will be skipped\n"; + if (GetYesNo("Would you like to override this check, and force the update to occur?", "n") ) { + print "You have selected to override the version checks and force the update\n"; + $Oopt = "-O" + } + } + } until (GetYesNo("Are you sure you want to proceed?", "n") ); + if ( "$action" ne "skip" ) { + my $pathnames=expand_pathnames($all_packages); + if ( $parallel ) { + return run_fabric_cmd("$BIN_DIR/opaswitchadmin $Oopt -L $FabricExtMgmtSwFile -P '$pathnames' -a $action upgrade"); + } else { + return run_fabric_cmd("FF_MAX_PARALLEL=0 $BIN_DIR/opaswitchadmin $Oopt -L $FabricExtMgmtSwFile -P '$pathnames' -a $action upgrade"); + } + } +} + +sub ext_mgmt_sw_reboot +{ + + if (! valid_config_file("Externally Managed Switch File", $FabricExtMgmtSwFile) ) { + return 1; + } + return run_fabric_cmd("$BIN_DIR/opaswitchadmin -L $FabricExtMgmtSwFile reboot"); +} + +sub ext_mgmt_sw_viewres +{ + return ff_viewres(1,0); +} + +# Externally Managed Switch Admin +sub ext_mgmt_sw_admin +{ + my $result; + my $inp; + my %selected = (); + my %statusMessage = (); # TBD - not used + my $step; + my $i; + + foreach $step ( @FabricExtMgmtSwSteps ) + { + $selected{$step}= 0; + } +DO_SETUP: + system "clear"; + print color("bold"); + printf ("FastFabric OPA Switch Setup/Admin Menu\n"); + printf ("Externally Managed Switch File: $FabricExtMgmtSwFile\n"); + print color("reset"); + for($i=0; $i < scalar(@FabricExtMgmtSwSteps); $i++) + { + $step = $FabricExtMgmtSwSteps[$i]; + print_delimiter("$FabricExtMgmtSwStepsMenuDelimiter{$step}"); + printf ("%x) %-41s ", $i, $FabricExtMgmtSwStepsName{$step}); + printStepSelected($selected{$step}, $statusMessage{$step}); + } + + printf ("\nP) Perform the Selected Actions N) Select None\n"); + printf ( "X) Return to Previous Menu (or ESC or Q)\n"); + + %statusMessage = (); + + $inp = getch(); + + if ($inp =~ /[qQ]/ || $inp =~ /[xX]/ || ord($inp) == $KEY_ESC) + { + return; + } + + if ($inp =~ /[nN]/ ) + { + foreach $step ( @FabricExtMgmtSwSteps ) + { + $selected{$step}= 0; + } + } + elsif ($inp =~ /[0123456789abcdefABCDEF]/) + { + $step = $FabricExtMgmtSwSteps[hex($inp)]; + $selected{$step}= ! $selected{$step}; + } + elsif ($inp =~ /[pP]/) + { + # perform the fabric admin + foreach $step ( @FabricExtMgmtSwSteps ) + { + if ($selected{$step} ) + { + print LOG_FD "Performing Switch Admin: $FabricExtMgmtSwStepsName{$step}\n"; + print "\nPerforming Switch Admin: $FabricExtMgmtSwStepsName{$step}\n"; + $result = eval "ext_mgmt_sw_$step"; + $selected{$step} = 0; + if ( $result ) + { + goto DO_SETUP + } + } + } + } + + goto DO_SETUP; +} + + +sub show_menu +{ + my $inp; + my $max_inp = 5; + +START: + system "clear"; + print color("bold"); + printf ("$BRAND FastFabric OPA Tools\n"); + printf ("Version: $VERSION\n\n"); + print color("reset"); + printf (" 1) Chassis Setup/Admin\n"); + printf (" 2) Externally Managed Switch Setup/Admin\n"); + printf (" 3) Host Setup\n"); + printf (" 4) Host Verification/Admin\n"); + printf (" 5) Fabric Monitoring\n"); + printf ("\n X) Exit (or Q)\n"); + + $inp = getch(); + + if ($inp =~ /[qQ]/ || $inp =~ /[Xx]/ ) { + die "Exiting\n"; + } + if (ord($inp) == $KEY_ENTER) { + goto START; + } + + if ($inp =~ /[0123456789abcdefABCDEF]/) + { + $inp = hex($inp); + } + + if ($inp < 1 || $inp > $max_inp) + { +# printf ("Invalid choice...Try again\n"); + goto START; + } + $MENU_CHOICE = $inp; +} + +process_args; +check_user; +open_log; +set_libdir; + +RESTART: +show_menu; + +if ($MENU_CHOICE == 1) +{ + # Chassis Setup/Admin + chassis_admin; + goto RESTART; +} +elsif ($MENU_CHOICE == 2) +{ + # Externally Managed Switch Setup/Admin + ext_mgmt_sw_admin; + goto RESTART; +} +elsif ($MENU_CHOICE == 3) +{ + # Host Setup + fabric_setup; + goto RESTART; +} +elsif ($MENU_CHOICE == 4) +{ + # Host Verification/Admin + fabric_admin; + goto RESTART; +} +elsif ($MENU_CHOICE == 5) +{ + # Fabric Monitoring + fabric_monitor; + goto RESTART; +} +close_log; diff --git a/IbaTools/FastFabric/opahostsmanalysis.sh b/IbaTools/FastFabric/opahostsmanalysis.sh new file mode 100755 index 0000000..a268c85 --- /dev/null +++ b/IbaTools/FastFabric/opahostsmanalysis.sh @@ -0,0 +1,225 @@ +#!/bin/bash +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] +# Analyze host SM for errors and/or changes relative to baseline + +# optional override of defaults +if [ -f /etc/opa/opafastfabric.conf ] +then + . /etc/opa/opafastfabric.conf +fi + +. /usr/lib/opa/tools/opafastfabric.conf.def + +. /usr/lib/opa/tools/ff_funcs + +trap "exit 1" SIGHUP SIGTERM SIGINT + +Usage_full() +{ + echo "Usage: opahostsmanalysis [-b|-e] [-s] [-d dir]" >&2 + echo " or" >&2 + echo " opahostsmanalysis --help" >&2 + echo " --help - produce full help text" >&2 + echo " -b - baseline mode, default is compare/check mode" >&2 + echo " -e - evaluate health only, default is compare/check mode" >&2 + echo " -s - save history of failures (errors/differences)" >&2 + echo " -d dir - top level directory for saving baseline and history of failed checks" >&2 + echo " default is /var/usr/lib/opa/analysis" >&2 + echo " Environment:" >&2 + echo " FF_ANALYSIS_DIR - top level directory for baselines and failed health checks" >&2 + echo "for example:" >&2 + echo " opahostsmanalysis" >&2 + exit 0 +} + +Usage() +{ + echo "Usage: opahostsmanalysis [-b|-e] [-s]" >&2 + echo " or" >&2 + echo " opahostsmanalysis --help" >&2 + echo " --help - produce full help text" >&2 + echo " -b - baseline mode, default is compare/check mode" >&2 + echo " -e - evaluate health only, default is compare/check mode" >&2 + echo " -s - save history of failures (errors/differences)" >&2 + echo "for example:" >&2 + echo " opahostsmanalysis" >&2 + exit 2 +} + +if [ x"$1" = "x--help" ] +then + Usage_full +fi + +getbaseline=n +healthonly=n +savehistory=n +status=ok +while getopts besd: param +do + case $param in + b) getbaseline=y;; + e) healthonly=y;; + s) savehistory=y;; + d) export FF_ANALYSIS_DIR="$OPTARG";; + ?) Usage;; + esac +done +shift $((OPTIND -1)) +if [ $# -ge 1 ] +then + Usage +fi +if [ "$getbaseline" = y -a "$healthonly" = y ] +then + Usage +fi + +#----------------------------------------------------------------- +# Set up file paths +#----------------------------------------------------------------- +# newer versions of the SM (which support XML config) +# +SM_CONFIG_FILE=/etc/opa-fm/opafm.xml + +baseline_dir="$FF_ANALYSIS_DIR/baseline" +latest_dir="$FF_ANALYSIS_DIR/latest" +export FF_CURTIME="${FF_CURTIME:-`date +%Y-%m-%d-%H:%M:%S`}" +failures_dir="$FF_ANALYSIS_DIR/$FF_CURTIME" + +#----------------------------------------------------------------- +save_failures() +{ + if [ "$savehistory" = y ] + then + mkdir -p $failures_dir + cp $* $failures_dir + echo "opahostsmanalysis: Failure information saved to: $failures_dir/" >&2 + fi +} + +baseline=$baseline_dir/hostsm +latest=$latest_dir/hostsm + +# fake loop so we can use continue to skip to end of script +for loop in 1 +do + if [[ $getbaseline == n && $healthonly == n ]] + then + if [ ! -f $baseline.smver -o ! -f $baseline.smconfig ] + then + echo "opahostsmanalysis: Error: Previous baseline run required" >&2 + status=bad + continue + fi + fi + + if [[ $healthonly == n ]] + then + # get a new snapshot + mkdir -p $latest_dir + rm -rf $latest.* + + rpm -q opa-fm > $latest.smver 2>&1 + if [ $? != 0 ] + then + echo "opahostsmanalysis: Error: Host SM not installed" >&2 + status=bad + continue + fi + + cp $SM_CONFIG_FILE $latest.smconfig + if [ $? != 0 ] + then + echo "opahostsmanalysis: Error: Unable to copy Host SM Config" >&2 + status=bad + continue + fi + + if [[ $getbaseline == y ]] + then + mkdir -p $baseline_dir + rm -rf $baseline.* + cp $latest.smver $latest.smconfig $baseline_dir + fi + fi + + if [[ $getbaseline == n ]] + then + # check SM health/running + mkdir -p $latest_dir + + /usr/lib/opa-fm/bin/fm_cmd smShowCounters > $latest.smstatus 2>&1 + r=$? + + if [ $r != 0 ] + then + echo "opahostsmanalysis: Error: Host SM not running. See $latest.smstatus" >&2 + status=bad + save_failures $latest.smstatus + fi + fi + + if [[ $getbaseline == n && $healthonly == n ]] + then + # compare to baseline + $FF_DIFF_CMD $baseline.smver $latest.smver > $latest.smver.diff 2>&1 + $FF_DIFF_CMD $baseline.smconfig $latest.smconfig > $latest.smconfig.diff 2>&1 + if [ -s $latest.smver.diff -o -s $latest.smconfig.diff ] + then + echo "opahostsmanalysis: SM configuration changed. See $latest.smconfig.diff and $latest.smver.diff" >&2 + status=bad + save_failures $latest.smver $latest.smver.diff $latest.smconfig $latest.smconfig.diff + else + rm -f $latest.smver.diff $latest.smconfig.diff + fi + fi +done + +if [ "$status" != "ok" ] +then + if [[ $healthonly == n ]] + then + echo "opahostsmanalysis: Possible Host SM errors or changes found" >&2 + else + echo "opahostsmanalysis: Possible Host SM errors found" >&2 + fi + exit 1 +else + if [[ $getbaseline == n ]] + then + echo "opahostsmanalysis: Host SM(s) OK" + else + echo "opahostsmanalysis: Baselined" + fi + exit 0 +fi diff --git a/IbaTools/FastFabric/opapingall.sh b/IbaTools/FastFabric/opapingall.sh new file mode 100755 index 0000000..e4619c1 --- /dev/null +++ b/IbaTools/FastFabric/opapingall.sh @@ -0,0 +1,180 @@ +#!/bin/bash +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] + +# optional override of defaults +if [ -f /etc/opa/opafastfabric.conf ] +then + . /etc/opa/opafastfabric.conf +fi + +. /usr/lib/opa/tools/opafastfabric.conf.def + +. /usr/lib/opa/tools/ff_funcs + +trap "exit 1" SIGHUP SIGTERM SIGINT + +Usage_full() +{ + echo "Usage: opapingall [-Cp] [-f hostfile] [-F chassisfile] [-h 'hosts']" >&2 + echo " [-H 'chassis']" >&2 + echo " or" >&2 + echo " opapingall --help" >&2 + echo " --help - produce full help text" >&2 + echo " -C - perform ping against chassis, default is hosts" >&2 + echo " Merely selects applicable list, can ping both hosts and chassis" >&2 + echo " -p - ping all hosts/chassis in parallel" >&2 + echo " -f hostfile - file with hosts in cluster, default is $CONFIG_DIR/opa/hosts" >&2 + echo " -F chassisfile - file with chassis in cluster" >&2 + echo " default is $CONFIG_DIR/opa/chassis" >&2 + echo " -h hosts - list of hosts to ping" >&2 + echo " -H chassis - list of chassis to ping" >&2 + echo " Environment:" >&2 + echo " HOSTS - list of hosts, used if -h option not supplied" >&2 + echo " CHASSIS - list of chassis, used if -H option not supplied" >&2 + echo " HOSTS_FILE - file containing list of hosts, used in absence of -f and -h" >&2 + echo " CHASSIS_FILE - file containing list of chassis, used in absence of -F and -H" >&2 + echo " FF_MAX_PARALLEL - when -p option is used, maximum concurrent operations" >&2 + echo "example:">&2 + echo " opapingall" >&2 + echo " opapingall -h 'arwen elrond'" >&2 + echo " HOSTS='arwen elrond' opapingall" >&2 + echo " opapingall -C" >&2 + echo " opapingall -C -H 'chassis1 chassis2'" >&2 + echo " CHASSIS='chassis1 chassis2' opapingall -C" >&2 + exit 0 +} + +Usage() +{ + echo "Usage: opapingall [-Cp] [-f hostfile] [-F chassisfile]" >&2 + echo " or" >&2 + echo " opapingall --help" >&2 + echo " --help - produce full help text" >&2 + echo " -C - perform ping against chassis, default is hosts" >&2 + echo " Merely selects applicable list, can ping both hosts and chassis" >&2 + echo " -p - ping all hosts/chassis in parallel" >&2 + echo " -f hostfile - file with hosts in cluster, default is $CONFIG_DIR/opa/hosts" >&2 + echo " -F chassisfile - file with chassis in cluster" >&2 + echo " default is $CONFIG_DIR/opa/chassis" >&2 + echo "example:">&2 + echo " opapingall" >&2 + echo " opapingall -C" >&2 + exit 2 +} + +if [ x"$1" = "x--help" ] +then + Usage_full +fi + +ping_dest() +{ + # $1 is the destination to ping + ping_host $1 + if [ $? != 0 ] + then + echo "$1: doesn't ping" + else + echo "$1: is alive" + fi +} + +popt=n +host=0 +chassis=0 +while getopts Cf:F:h:H:p param +do + case $param in + C) + chassis=1;; + h) + host=1 + HOSTS="$OPTARG";; + H) + chassis=1 + CHASSIS="$OPTARG";; + f) + host=1 + HOSTS_FILE="$OPTARG";; + F) + chassis=1 + CHASSIS_FILE="$OPTARG";; + p) + popt=y;; + ?) + Usage;; + esac +done +shift $((OPTIND -1)) +if [ $# -gt 0 ] +then + Usage +fi +if [[ $(($chassis+$host)) -gt 1 ]] +then + echo "opapingall: conflicting arguments, host and chassis both specified" >&2 + Usage +fi +if [[ $(($chassis+$host)) -eq 0 ]] +then + host=1 +fi +if [ $chassis -eq 0 ] +then + check_host_args opapingall + DESTS="$HOSTS" +else + check_chassis_args opapingall + DESTS="$CHASSIS" +fi + +running=0 +for dest in $DESTS +do + if [ $chassis -ne 0 ] + then + dest=`strip_chassis_slots "$dest"` + fi + if [ "$popt" = "y" ] + then + if [ $running -ge $FF_MAX_PARALLEL ] + then + wait + running=0 + fi + ping_dest $dest & + running=$(($running + 1)) + else + ping_dest $dest + fi +done +wait diff --git a/IbaTools/FastFabric/opascpall.sh b/IbaTools/FastFabric/opascpall.sh new file mode 100755 index 0000000..cea2d5a --- /dev/null +++ b/IbaTools/FastFabric/opascpall.sh @@ -0,0 +1,277 @@ +#!/bin/bash +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] +# copy a file to all hosts + +# optional override of defaults +if [ -f /etc/opa/opafastfabric.conf ] +then + . /etc/opa/opafastfabric.conf +fi + +. /usr/lib/opa/tools/opafastfabric.conf.def + +. /usr/lib/opa/tools/ff_funcs + +temp="$(mktemp --tmpdir "opascpall.XXXXXX")" +trap "rm -f $temp; exit 1" SIGHUP SIGTERM SIGINT +trap "rm -f $temp" EXIT + +Usage_full() +{ + echo "Usage: opascpall [-p] [-r] [-f hostfile] [-h 'hosts'] [-u user]" >&2 + echo " source_file ... dest_file" >&2 + echo " opascpall -t [-p] [-f hostfile] [-h 'hosts'] [-u user] " >&2 + echo " [source_dir [dest_dir]]" >&2 + echo " or" >&2 + echo " opascpall --help" >&2 + echo " --help - produce full help text" >&2 + echo " -p - perform copy in parallel on all hosts" >&2 + echo " -r - recursive copy of directories" >&2 + echo " -t - optimized recursive copy of directories using tar" >&2 + echo " if dest_dir omitted, defaults to current directory name" >&2 + echo " if source_dir and dest_dir omitted, both default to current directory" >&2 + echo " -h hosts - list of hosts to copy to" >&2 + echo " -f hostfile - file with hosts in cluster, default is $CONFIG_DIR/opa/hosts" >&2 + echo " -u user - user to perform copy to, default is current user code" >&2 + echo " source_file - list of source files to copy" >&2 + echo " source_dir - source directory to copy, if omitted . is used" >&2 + echo " dest_file - destination for copy." >&2 + echo " If more than 1 source file, this must be a directory" >&2 + echo " dest_dir - destination for copy. If omitted current directory name is used" >&2 + echo " Environment:" >&2 + echo " HOSTS - list of hosts, used if -h option not supplied" >&2 + echo " HOSTS_FILE - file containing list of hosts, used in absence of -f and -h" >&2 + echo " FF_MAX_PARALLEL - when -p option is used, maximum concurrent operations" >&2 + echo "example:">&2 + echo " opascpall MPI-PMB /root/MPI-PMB" >&2 + echo " opascpall -t -p /usr/src/opa/mpi_apps /usr/src/opa/mpi_apps" >&2 + echo " opascpall a b c /root/tools/" >&2 + echo " opascpall -h 'arwen elrond' a b c /root/tools" >&2 + echo " HOSTS='arwen elrond' opascpall a b c /root/tools" >&2 + echo "user@ syntax cannot be used in filenames specified" >&2 + echo "To copy from hosts in the cluster to this host, use opauploadall" >&2 + exit 0 +} + +Usage() +{ + echo "Usage: opascpall [-p] [-r] [-f hostfile] source_file ... dest_file" >&2 + echo " opascpall -t [-p] [-f hostfile] [source_dir [dest_dir]]" >&2 + echo " or" >&2 + echo " opascpall --help" >&2 + echo " --help - produce full help text" >&2 + echo " -p - perform copy in parallel on all hosts" >&2 + echo " -r - recursive copy of directories" >&2 + echo " -t - optimized recursive copy of directories using tar" >&2 + echo " if dest_dir omitted, defaults to current directory name" >&2 + echo " if source_dir and dest_dir omitted, both default to current directory" >&2 + echo " -f hostfile - file with hosts in cluster, default is $CONFIG_DIR/opa/hosts" >&2 + echo " source_file - list of source files to copy" >&2 + echo " source_dir - source directory to copy, if omitted . is used" >&2 + echo " dest_file - destination for copy." >&2 + echo " If more than 1 source file, this must be a directory" >&2 + echo " dest_dir - destination for copy. If omitted current directory name is used" >&2 + echo "example:">&2 + echo " opascpall MPI-PMB /root/MPI-PMB" >&2 + echo " opascpall -t -p /usr/src/opa/mpi_apps /usr/src/opa/mpi_apps" >&2 + echo " opascpall a b c /root/tools/" >&2 + echo "user@ syntax cannot be used in filenames specified" >&2 + echo "To copy from hosts in the cluster to this host, use opauploadall" >&2 + exit 2 +} + +if [ x"$1" = "x--help" ] +then + Usage_full +fi + +user=`id -u -n` +opts= +topt=n +popt=n +status=0 + +pids='' + +while getopts f:h:u:prt param +do + case $param in + h) + HOSTS="$OPTARG";; + f) + HOSTS_FILE="$OPTARG";; + u) + user="$OPTARG";; + p) + opts="$opts -q" + popt=y;; + r) + opts="$opts -r";; + t) + topt=y;; + ?) + Usage;; + esac +done +shift $((OPTIND -1)) +if [ "$topt" = "n" -a $# -lt 2 ] +then + Usage +fi +if [ "$topt" = "y" -a $# -gt 2 ] +then + Usage +fi +check_host_args opascpall + +if [ "$topt" = "n" ] +then + # remove last name from the list + files= + dest= + for file in "$@" + do + if [ ! -z "$dest" ] + then + files="$files $dest" + fi + dest="$file" + done + + running=0 + + for hostname in $HOSTS + do + if [ "$popt" = "y" ] + then + if [ $running -ge $FF_MAX_PARALLEL ] + then + wait + running=0 + fi + echo "scp $opts $files $user@[$hostname]:$dest" + scp $opts $files $user@\[$hostname\]:$dest & + pid=$! + pids="$pids $pid" + running=$(( $running + 1)) + else + echo "scp $opts $files $user@[$hostname]:$dest" + scp $opts $files $user@\[$hostname\]:$dest + if [ "$?" -ne 0 ] + then + status=1 + fi + fi + done + +#checking exit status for background jobs + for pid in $pids + do + wait $pid + if [ "$?" -ne 0 ] + then + status=1 + fi + done + +else + if [ $# -lt 2 ] + then + destdir=$PWD + else + destdir=$2 + fi + if [ $# -lt 1 ] + then + srcdir=$PWD + else + srcdir=$1 + fi + if [ ! -d $srcdir ] + then + echo "opascpall: $srcdir: No such directory" >&2 + Usage + fi + cd $srcdir + tar cvfz $temp . + + running=0 + for hostname in $HOSTS + do + if [ "$popt" = "y" ] + then + if [ $running -ge $FF_MAX_PARALLEL ] + then + wait + running=0 + fi + ( + echo "scp $opts $temp $user@[$hostname]:$temp" + scp $opts $temp $user@\[$hostname\]:$temp + echo "$user@$hostname: mkdir -p $destdir; cd $destdir; tar xfz $temp; rm -f $temp" + ssh $user@$hostname "mkdir -p $destdir; cd $destdir; tar xfz $temp; rm -f $temp" + ) & + pid=$! + pids="$pids $pid" + running=$(( $running + 1)) + else + echo "scp $opts $temp $user@[$hostname]:$temp" + scp $opts $temp $user@\[$hostname\]:$temp + if [ "$?" -ne 0 ] + then + status=1 + fi + echo "$user@$hostname: mkdir -p $destdir; cd $destdir; tar xfz $temp; rm -f $temp" + ssh $user@$hostname "mkdir -p $destdir; cd $destdir; tar xfz $temp; rm -f $temp" + if [ "$?" -ne 0 ] + then + status=1 + fi + fi + done + +#checking exit status for background jobs + for pid in $pids + do + wait $pid + if [ "$?" -ne 0 ] + then + status=1 + fi + done + rm -f $temp +fi + +if [ $status -ne 0 ] + then + exit 1 +fi diff --git a/IbaTools/FastFabric/opasetupssh.sh b/IbaTools/FastFabric/opasetupssh.sh new file mode 100755 index 0000000..35c93a4 --- /dev/null +++ b/IbaTools/FastFabric/opasetupssh.sh @@ -0,0 +1,711 @@ +#!/bin/bash +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] +# setup password-less ssh on a group of hosts + +# optional override of defaults +if [ -f /etc/opa/opafastfabric.conf ] +then + . /etc/opa/opafastfabric.conf +fi + +. /usr/lib/opa/tools/opafastfabric.conf.def + +. /usr/lib/opa/tools/ff_funcs + +trap "exit 1" SIGHUP SIGTERM SIGINT + +if [ x"$FF_IPOIB_SUFFIX" = xNONE ] +then + export FF_IPOIB_SUFFIX="" +fi + +Usage_full() +{ + echo "Usage: opasetupssh [-CpU] [-f hostfile] [-F chassisfile] [-h 'hosts']" >&2 + echo " [-H 'chassis'] [-i ipoib_suffix] [-u user] [-S]" >&2 + echo " [-RP]" >&2 + echo " or" >&2 + echo " opasetupssh --help" >&2 + echo >&2 + echo " --help - produce full help text" >&2 + echo " -C - perform operation against chassis, default is hosts" >&2 + echo " -p - perform operation against all chassis/hosts in parallel" >&2 + echo " -U - only perform connect (to enter in local hosts knownhosts)" >&2 + echo " (when run in this mode the -S option is ignored)" >&2 + echo >&2 + echo " -f hostfile - file with hosts in cluster, default is " >&2 + echo " $CONFIG_DIR/opa/hosts" >&2 + echo " -F chassisfile - file with chassis in cluster, default is" >&2 + echo " $CONFIG_DIR/opa/chassis" >&2 + echo " -h hosts - list of hosts to setup" >&2 + echo " -H chassis - list of chassis to setup" >&2 + echo >&2 + echo " -i ipoib_suffix - suffix to apply to host names to create ipoib" >&2 + echo " host names default is '$FF_IPOIB_SUFFIX'" >&2 + echo " -u user - user on remote system to allow this user to ssh to," >&2 + echo " default is current user code for host(s) and admin" >&2 + echo " for chassis" >&2 + echo " -S - securely prompt for password for user on remote system" >&2 + echo " -R - skip setup of ssh to localhost" >&2 + echo " -P - skip ping of host (for ssh to devices on internet with ping firewalled)" >&2 + echo >&2 + echo " Environment:" >&2 + echo " HOSTS_FILE - file containing list of hosts, used in absence of -f and -h" >&2 + echo " CHASSIS_FILE - file containing list of chassis, used in absence of -F and -H" >&2 + echo " HOSTS - list of hosts, used if -h option not supplied" >&2 + echo " CHASSIS - list of chassis, used if -C used and -H and -F options not supplied" >&2 + echo " FF_MAX__PARALLEL - when -p option is used, maximum concurrent operations" >&2 + echo " FF_IPOIB_SUFFIX - suffix to apply to hostnames to create ipoib hostnames," >&2 + echo " used in absence of -i" >&2 + echo " FF_CHASSIS_LOGIN_METHOD - how to login to chassis: telnet or ssh" >&2 + echo " FF_CHASSIS_ADMIN_PASSWORD - password for chassis, used in absence of -S" >&2 + echo >&2 + echo "example:">&2 + echo " Operations on hosts" >&2 + echo " opasetupssh -S -i''" >&2 + echo " opasetupssh -U" >&2 + echo " opasetupssh -h 'arwen elrond' -U" >&2 + echo " HOSTS='arwen elrond' opasetupssh -U" >&2 + echo " Operations on chassis" >&2 + echo " opasetupssh -C" >&2 + echo " opasetupssh -C -H 'chassis1 chassis2'" >&2 + echo " CHASSIS='chassis1 chassis2' opasetupssh -C" >&2 + exit 0 +} + +Usage() +{ + echo "Usage: opasetupssh [-CpU] [-f hostfile] [-F chassisfile]" >&2 + echo " [-i ipoib_suffix] [-S]" >&2 + echo " or" >&2 + echo " opasetupssh --help" >&2 + echo " --help - produce full help text" >&2 + echo " -C - perform operation against chassis, default is hosts" >&2 + echo " -p - perform operation against all chassis/hosts in parallel" >&2 + echo " -U - only perform connect (to enter in local hosts knownhosts)" >&2 + echo " (when run in this mode, the -S options is ignored)" >&2 + echo " -f hostfile - file with hosts in cluster, default is $CONFIG_DIR/opa/hosts" >&2 + echo " -F chassisfile - file with chassis in cluster, default is" >&2 + echo " $CONFIG_DIR/opa/chassis" >&2 + echo " -i ipoib_suffix - suffix to apply to host names to create ipoib host names" >&2 + echo " default is '$FF_IPOIB_SUFFIX'" >&2 + echo " -S - securely prompt for password for user on remote system" >&2 + echo >&2 + echo "example:">&2 + echo " Operations on hosts" >&2 + echo " opasetupssh -S -i''" >&2 + echo " opasetupssh -U" >&2 + echo " Operations on chassis" >&2 + echo " opasetupssh -C" >&2 + exit 2 +} + +if [ x"$1" = "x--help" ] +then + Usage_full +fi + +myuser=`id -u -n` +user=$myuser +Uopt=n +popt=n +Ropt=n +Sopt=n +uopt=n +password= +chassis=0 +host=0 +ipoib=0 +skip_ping=n +bracket='' +close_bracket='' + +shellcmd="ssh -o StrictHostKeyChecking=no" +copycmd=scp +bracket='[' +close_bracket=']' + +while getopts CpUi:f:h:u:H:F:SRP param +do + case $param in + C) + chassis=1;; + p) + popt=y;; + U) + Uopt=y;; + i) + ipoib=1 + FF_IPOIB_SUFFIX="$OPTARG";; + h) + host=1 + HOSTS="$OPTARG";; + H) + chassis=1 + CHASSIS="$OPTARG";; + f) + host=1 + HOSTS_FILE="$OPTARG";; + F) + chassis=1 + CHASSIS_FILE="$OPTARG";; + u) + uopt=y + user="$OPTARG";; + S) + Sopt=y;; + R) + Ropt=y;; + P) + skip_ping=y;; + ?) + Usage;; + esac +done +shift $((OPTIND -1)) +if [ $# -gt 0 ] +then + Usage +fi +if [[ $(($chassis+$host)) -gt 1 ]] +then + echo "opasetupssh: conflicting arguments, host and chassis both specified" >&2 + Usage +fi +if [[ $(($chassis+$host)) -eq 0 ]] +then + host=1 +fi +if [[ $(($chassis+$ipoib)) -gt 1 ]] +then + echo "opasetupssh: conflicting arguments, IPOIB and chassis both specified" >&2 + Usage +fi +if [ "$Uopt" = y -a "$Sopt" = y ] +then + echo "opasetupssh: Warning: -S option ignored in conjunction with -U" >&2 + Sopt=n +fi +if [ "$Uopt" = y ] +then + # need commands setup so can run setup_self_ssh on remote host + shellcmd="ssh -o StrictHostKeyChecking=no" + copycmd=scp + bracket='[' + close_bracket=']' +fi +if [ "$Sopt" = y ] +then + bracket='\[' + close_bracket='\]' +fi +if [ "$chassis" = 1 -a "$Ropt" = y ] +then + echo "opasetupssh: Warning: -R option ignored for chassis" >&2 + Ropt=n +fi +# for chassis, make the default user to be admin (unless specified) +if [ $chassis = 1 -a "$uopt" = n ] +then + user="admin" +fi + +if [ $chassis -eq 1 ] +then + shellcmd=ssh + copycmd=scp + export CFG_CHASSIS_LOGIN_METHOD="$FF_CHASSIS_LOGIN_METHOD" + export CFG_CHASSIS_ADMIN_PASSWORD="$FF_CHASSIS_ADMIN_PASSWORD" + if [ "$Sopt" = y ] + then + given_pwd='entered' + else + given_pwd='default' + fi +fi +# if user requested to enter a password securely, prompt user and save password +if [ $host -eq 1 ] +then + check_host_args opasetupssh + if [ "$Sopt" = y ] + then + echo -n "Password for $user on all hosts: " > /dev/tty + stty -echo < /dev/tty > /dev/tty + password= + read password < /dev/tty + stty echo < /dev/tty > /dev/tty + echo > /dev/tty + export password + fi +else + check_chassis_args opasetupssh + if [ "$Sopt" = y ] + then + echo -n "Password for $user on all chassis: " > /dev/tty + stty -echo < /dev/tty > /dev/tty + password= + read password < /dev/tty + stty echo < /dev/tty > /dev/tty + echo > /dev/tty + export CFG_CHASSIS_ADMIN_PASSWORD="$password" + fi +fi + +# connect to host via ssh +connect_to_host() +{ + # $1 = user + # $2 = host + + # We use an alternate file to build up the new keys + # this way parallel calls can let ssh itself handle file locking + # then update_known_hosts can replace data in real known_hosts file + ssh -o 'UserKnownHostsFile=~/.ssh/.known_hosts-ffnew' -o 'StrictHostKeyChecking=no' $1@$2 echo "$2: Connected" +} + +# update known_hosts file with information from connect_to_host calls +update_known_hosts() +{ + if [ -e ~/.ssh/.known_hosts-ffnew ] + then + if [ -e ~/.ssh/known_hosts ] + then + ( + IFS=" , " + while read name trash + do + # remove old entry from known hosts in case key changed + if grep "^$name[, ]" < ~/.ssh/known_hosts > /dev/null 2>&1 + then + grep -v "^$name[, ]" < ~/.ssh/known_hosts > ~/.ssh/.known_hosts-fftmp + mv ~/.ssh/.known_hosts-fftmp ~/.ssh/known_hosts + fi + done < ~/.ssh/.known_hosts-ffnew + ) + fi + total_processed=$(( $total_processed + $(wc -l < ~/.ssh/.known_hosts-ffnew) )) + cat ~/.ssh/.known_hosts-ffnew >> ~/.ssh/known_hosts + chmod go-w ~/.ssh/known_hosts + + rm -rf ~/.ssh/.known_hosts-ffnew ~/.ssh/.known_hosts-fftmp + fi +} + +# Generate public and private SSH key pairs +cd ~ +mkdir -m 0700 -p ~/.ssh ~/.ssh2 +permission_ssh=$(stat -c %a ~/.ssh) +if [ "$permission_ssh" -ne 700 ]; then + chmod 700 ~/.ssh + echo "Warning: ~/.ssh dir permissions are $permission_ssh. Changed to 700.." +fi + +permission_ssh2=$(stat -c %a ~/.ssh2) +if [ "$permission_ssh2" -ne 700 ]; then + chmod 700 ~/.ssh2 + echo "Warning: ~/.ssh2 dir permissions are $permission_ssh2. Changed to 700." +fi + +if [ ! -f ~/.ssh/id_rsa.pub -o ! -f ~/.ssh/id_rsa ] +then + ssh-keygen -P "" -t rsa -f ~/.ssh/id_rsa +fi +if [ ! -f .ssh/id_dsa.pub -o ! -f .ssh/id_dsa ] +then + ssh-keygen -P "" -t dsa -f ~/.ssh/id_dsa +fi +# recreate public key in Reflection format for ssh2 +if [ ! -f .ssh2/ssh2_id_dsa.pub ] +then + # older distros may not support this, ignore error + ssh-keygen -P "" -O ~/.ssh/id_dsa.pub -o ~/.ssh2/ssh2_id_dsa.pub 2>/dev/null +fi + +# send command to the host and handle any password prompt if user supplied secure password +run_host_cmd() +{ +if [ "$Sopt" = "n" ] +then + $* +else + expect -c " +global env +spawn -noecho $* +expect { +{assword:} { + puts -nonewline stdout \"\" + flush stdout + exp_send \"\$env(password)\\r\" + interact + wait + } +{assphrase for key} { + puts stdout \"\nError: PassPhrase not supported. Remove PassPhrase\" + flush stdout + exit + } +{continue connecting} { exp_send \"yes\\r\" + exp_continue + } +} +" +fi +} + +# send command to the chassis and always expect to be prompted for password +run_chassis_cmd() +{ +expect -c " +global env +spawn -noecho $* +expect { +{assword:} { + puts -nonewline stdout \"\" + flush stdout + exp_send \"$CFG_CHASSIS_ADMIN_PASSWORD\r\" + interact + wait + } +{assphrase for key} { + puts stdout \"\nError: PassPhrase not supported. Remove PassPhrase\" + flush stdout + exit + } +{continue connecting} { exp_send \"yes\\r\" + exp_continue + } +} +" +} + +# connect to chassis via ssh +connect_to_chassis() +{ + # $1 = user + # $2 = chassis + # $3 = 1 if display connected + + # We use an alternate file to build up the new keys + # this way parallel calls can let ssh itself handle file locking + # then update_known_hosts can replace data in real known_hosts file + ssh -o 'UserKnownHostsFile=~/.ssh/.known_hosts-ffnew' -o 'StrictHostKeyChecking=no' $1@$2 "chassisQuery" 2>&1| grep -q 'slots:' + if [ $? -eq 0 ] + then + if [ $3 = 1 ] + then + echo "$2: Connected" + fi + return 0 + else + if [ $3 = 1 ] + then + echo "$2: Can't Connect" + fi + return 1 + fi +} + +# do selected opasetupssh operation for a single host +process_host() +{ + local hostname=$1 + local setup_self_ssh + + thost=`ff_host_basename $hostname` + thost_ib=`ff_host_basename_to_ipoib $thost` + #setup_self_ssh='[ -x /usr/lib/opa/tools/setup_self_ssh ] && /usr/lib/opa/tools/setup_self_ssh' + setup_self_ssh='/tmp/setup_self_ssh' + if [ "$thost" != "$thost_ib" ] + then + setup_self_ssh="$setup_self_ssh -i $thost_ib" + fi + [ "$skip_ping" = "y" ] || ping_host $thost + if [ $? != 0 ] + then + echo "Couldn't ping $thost" + sleep 1 + else + if [ "$Uopt" = n ] + then + echo "Configuring $thost..." + run_host_cmd $shellcmd -l $user $thost mkdir -m 0700 -p '~/.ssh' '~/.ssh2' + run_host_cmd $shellcmd -l $user $thost "stat -c %a ~/.ssh > /tmp/perm_ssh && stat -c %a ~/.ssh2 > /tmp/perm_ssh2" + run_host_cmd $copycmd $user@$bracket$thost$close_bracket:/tmp/perm_ssh /tmp/perm_ssh.$user.$thost + run_host_cmd $copycmd $user@$bracket$thost$close_bracket:/tmp/perm_ssh2 /tmp/perm_ssh2.$user.$thost + run_host_cmd $shellcmd -l $user $thost "rm -f /tmp/perm_ssh /tmp/perm_ssh2" + + if [ -f /tmp/perm_ssh.$user.$thost ] + then + permission_ssh=$(cat /tmp/perm_ssh.$user.$thost) + else + echo "Warning: /tmp/perm_ssh.$user.$thost: No such File." + fi + + if [ -f /tmp/perm_ssh2.$user.$thost ] + then + permission_ssh2=$(cat /tmp/perm_ssh2.$user.$thost) + else + echo "Warning: /tmp/perm_ssh2.$user.$thost: No such File." + fi + + if [ "$permission_ssh" -ne 700 -o "$permission_ssh2" -ne 700 ]; then + run_host_cmd $shellcmd -l $user $thost chmod 700 '~/.ssh' '~/.ssh2' + echo "Warning: $user@$thost:~/.ssh, ~/.ssh2 dir permissions are $permission_ssh/$permission_ssh2. Changed to 700.." + fi + rm -f /tmp/perm_ssh.$user.$thost /tmp/perm_ssh2.$user.$thost + run_host_cmd $copycmd ~/.ssh/id_rsa.pub $user@$bracket$thost$close_bracket:.ssh/$ihost.$myuser.id_rsa.pub + run_host_cmd $copycmd ~/.ssh/id_dsa.pub $user@$bracket$thost$close_bracket:.ssh/$ihost.$myuser.id_dsa.pub + + run_host_cmd $shellcmd -l $user $thost ">> ~/.ssh/authorized_keys" + run_host_cmd $shellcmd -l $user $thost "cat ~/.ssh/authorized_keys ~/.ssh/$ihost.$myuser.id_rsa.pub ~/.ssh/$ihost.$myuser.id_dsa.pub |sort -u > ~/.ssh/.tmp_keys" + run_host_cmd $shellcmd -l $user $thost "mv ~/.ssh/.tmp_keys ~/.ssh/authorized_keys" + + run_host_cmd $shellcmd -l $user $thost ">> ~/.ssh/authorized_keys2" + run_host_cmd $shellcmd -l $user $thost "cat ~/.ssh/authorized_keys2 ~/.ssh/$ihost.$myuser.id_rsa.pub ~/.ssh/$ihost.$myuser.id_dsa.pub |sort -u > ~/.ssh/.tmp_keys2" + run_host_cmd $shellcmd -l $user $thost "mv ~/.ssh/.tmp_keys2 ~/.ssh/authorized_keys2" + + if [ -f ~/.ssh2/ssh2_id_dsa.pub ] + then + run_host_cmd $copycmd ~/.ssh2/ssh2_id_dsa.pub $user@$thost:.ssh2/$ihost.$myuser.ssh2_id_dsa.pub + else + # older distros may not support this, ignore error + run_host_cmd $shellcmd -l $user $thost "ssh-keygen -P "" -O ~/.ssh/$ihost.$myuser.id_dsa.pub -o ~/.ssh2/$ihost.$myuser.ssh2_id_dsa.pub 2>/dev/null" + fi + run_host_cmd $shellcmd -l $user $thost "test -f ~/.ssh2/$ihost.$myuser.ssh2_id_dsa.pub && ! grep '^Key $ihost.$myuser.ssh2_id_dsa.pub\$' ~/.ssh2/authorization >/dev/null 2>&1 && echo 'Key $ihost.$myuser.ssh2_id_dsa.pub' >> .ssh2/authorization" + + run_host_cmd $shellcmd -l $user $thost "chmod go-w ~/.ssh/authorized_keys ~/.ssh/authorized_keys2" + run_host_cmd $shellcmd -l $user $thost "test -f ~/.ssh2/authorization && chmod go-w ~/.ssh2/authorization" + connect_to_host $user $thost + if [ "$thost" != "$thost_ib" ] + then + connect_to_host $user $thost_ib + fi + if [ "$Ropt" = "n" ] + then + run_host_cmd $copycmd /usr/lib/opa/tools/setup_self_ssh $user@$bracket$thost$close_bracket:/tmp/setup_self_ssh + run_host_cmd $shellcmd -l $user $thost "$setup_self_ssh" + run_host_cmd $shellcmd -l $user $thost "rm -f /tmp/setup_self_ssh" + fi + echo "Configured $thost" + else + echo "Connecting to $thost..." + connect_to_host $user $thost + if [ "$thost" != "$thost_ib" ] + then + connect_to_host $user $thost_ib + fi + if [ "$Ropt" = "n" ] + then + run_host_cmd $copycmd /usr/lib/opa/tools/setup_self_ssh $user@$bracket$thost$close_bracket:/tmp/setup_self_ssh + run_host_cmd $shellcmd -l $user $thost "$setup_self_ssh -U" + run_host_cmd $shellcmd -l $user $thost "rm -f /tmp/setup_self_ssh" + fi + fi + fi +} + +wait_chassis_scp() +{ + local tchassis user + tchassis="$1" + user="$2" + + waited=0 + while true + do + # since chassis is returning incorrectly for scp response + # we must use their workaround by checking RetCode + ret=$($chassis_cmd $tchassis $user "showLastScpRetCode -all" 2>&1) + case "$ret" in + *In\ Progress*) + sleep 1 + waited=$(($waited + 1)) + if [ $waited -gt 30 ] # 30 seconds is more than enough + then + echo "$tchassis: Timeout waiting for scp complete" + return 1 + fi;; + *Success*) + return 0;; + *) + echo "$tchassis: $ret" + return 1;; + esac + done +} + +# do selected opasetupssh operation for a single chassis +process_chassis() +{ + local chassisname=$1 + local tempfile=~/.ssh/.tmp_chassis_keys.$running + + tchassis=`strip_chassis_slots $chassisname` + [ "$skip_ping" = "y" ] || ping_host $tchassis + if [ $? != 0 ] + then + echo "Couldn't ping $tchassis" + sleep 1 + else + if [ "$Uopt" = n ] + then + echo "Configuring $tchassis..." + # ensure that we can login successfully by trying any simple command with expected response + $chassis_cmd $tchassis $user "chassisQuery" 2>&1| grep -q 'slots:' + if [ $? -ne 0 ] + then + echo "Login to $tchassis failed for the $given_pwd password, skipping..." + continue + fi + rm -f $tempfile $tempfile.2 2>/dev/null + /usr/lib/opa/tools/tcl_proc chassis_sftp_cmd "sftp $user@\[${tchassis}\]:" "get /firmware/$user/authorized_keys $tempfile" 2>&1| grep -q 'FAILED' + if [ $? -eq 0 ] || [ ! -f $tempfile ] + then + echo "Unable to configure $tchassis for password-less ssh, skipping..." + continue + fi + cat ~/.ssh/id_rsa.pub $tempfile | sort -u > $tempfile.2 + /usr/lib/opa/tools/tcl_proc chassis_sftp_cmd "sftp $user@\[${tchassis}\]:" "put $tempfile.2 /firmware/$user/authorized_keys" 2>&1| grep -q 'FAILED' + if [ $? -eq 0 ] + then + echo "$tchassis password-less ssh config failed, skipping..." + else + connect_to_chassis $user $tchassis 1 + if [ $? -eq 0 ] + then + echo "Configured $tchassis" + fi + fi + rm -f $tempfile $tempfile.2 2>/dev/null + else + echo "Connecting to $tchassis..." + connect_to_chassis $user $tchassis 1 + fi + fi +} + +# configure ssh on the host(s) or chassis +running=0 +total_processed=0 +rm -rf ~/.ssh/.known_hosts-ffnew ~/.ssh/.known_hosts-fftmp + +stty_settings=`stty -g` + +if [ $host -eq 1 ] +then + ihost=`hostname | cut -f1 -d.` + ihost_ib=`ff_host_basename_to_ipoib $ihost` + # setup ssh to ourselves + # This can also help if the .ssh directory is in a shared filesystem + rm -f ~/.ssh/.tmp_keys$$ + + >> ~/.ssh/authorized_keys + cat ~/.ssh/authorized_keys ~/.ssh/id_rsa.pub ~/.ssh/id_dsa.pub|sort -u > ~/.ssh/.tmp_keys$$ + mv ~/.ssh/.tmp_keys$$ ~/.ssh/authorized_keys + + >> ~/.ssh/authorized_keys2 + cat ~/.ssh/authorized_keys2 ~/.ssh/id_rsa.pub ~/.ssh/id_dsa.pub|sort -u > ~/.ssh/.tmp_keys$$ + mv ~/.ssh/.tmp_keys$$ ~/.ssh/authorized_keys2 + + # set up ssh2 DSA authorization + # older distros may not support this + [ -f ~/.ssh2/ssh2_id_dsa.pub ] && ! grep '^Key ssh2_id_dsa.pub$' ~/.ssh2/authorization >/dev/null 2>&1 && echo "Key ssh2_id_dsa.pub" >> ~/.ssh2/authorization + + chmod go-w ~/.ssh/authorized_keys ~/.ssh/authorized_keys2 + test -f ~/.ssh2/authorization && chmod go-w ~/.ssh2/authorization + + if [ "$Ropt" = "n" ] + then + echo "Verifying localhost ssh..." + if [ "$uopt" = n ] + then + # make sure we can ssh ourselves so ipoibping test works + connect_to_host $user localhost + connect_to_host $user $ihost + # make sure we can ssh to ourselves over ipoib, so MPI can be run on master + connect_to_host $user $ihost_ib + else + run_host_cmd $shellcmd -l $user localhost echo localhost connected.. + run_host_cmd $shellcmd -l $user $ihost echo $ihost connected.. + run_host_cmd $shellcmd -l $user $ihost_ib echo $ihost_ib connected.. + fi + + stty $stty_settings + update_known_hosts + fi + + for hostname in $HOSTS + do + if [ "$popt" = y ] + then + if [ $running -ge $FF_MAX_PARALLEL ] + then + wait + stty $stty_settings + update_known_hosts + running=0 + fi + process_host $hostname < /dev/tty & + running=$(($running +1)) + else + process_host $hostname + stty $stty_settings + update_known_hosts + fi + done +else + chassis_cmd='/usr/lib/opa/tools/tcl_proc chassis_run_cmd' + for chassisname in $CHASSIS + do + if [ "$popt" = y ] + then + if [ $running -ge $FF_MAX_PARALLEL ] + then + wait + stty $stty_settings + update_known_hosts + running=0 + fi + process_chassis $chassisname < /dev/tty & + running=$(($running +1)) + else + process_chassis $chassisname + stty $stty_settings + update_known_hosts + fi + done +fi +wait +stty $stty_settings +update_known_hosts + +echo "Successfully processed: $total_processed" diff --git a/IbaTools/FastFabric/opashowallports.sh b/IbaTools/FastFabric/opashowallports.sh new file mode 100755 index 0000000..7c10b2b --- /dev/null +++ b/IbaTools/FastFabric/opashowallports.sh @@ -0,0 +1,172 @@ +#!/bin/bash +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] + +# optional override of defaults +if [ -f /etc/opa/opafastfabric.conf ] +then + . /etc/opa/opafastfabric.conf +fi + +. /usr/lib/opa/tools/opafastfabric.conf.def + +. /usr/lib/opa/tools/ff_funcs + +trap "exit 1" SIGHUP SIGTERM SIGINT + +Usage_full() +{ + echo "Usage: opashowallports [-C] [-f hostfile] [-F chassisfile]" >&2 + echo " [-h 'hosts'] [-H 'chassis'] [-S]" >&2 + echo " or" >&2 + echo " opashowallports --help" >&2 + echo " --help - produce full help text" >&2 + echo " -C - perform operation against chassis, default is hosts" >&2 + echo " -f hostfile - file with hosts in cluster, default is $CONFIG_DIR/opa/hosts" >&2 + echo " -F chassisfile - file with chassis in cluster" >&2 + echo " default is $CONFIG_DIR/opa/chassis" >&2 + echo " -h hosts - list of hosts to show ports for" >&2 + echo " -H chassis - list of chassis to show ports for" >&2 + echo " -S - securely prompt for password for admin on chassis" >&2 + echo " Environment:" >&2 + echo " HOSTS - list of hosts, used if -h option not supplied" >&2 + echo " CHASSIS - list of chassis, used if -H option not supplied" >&2 + echo " HOSTS_FILE - file containing list of hosts, used in absence of -f and -h" >&2 + echo " CHASSIS_FILE - file containing list of chassis, used in absence of -F and -H" >&2 + echo " FF_CHASSIS_LOGIN_METHOD - how to login to chassis: telnet or ssh" >&2 + echo " FF_CHASSIS_ADMIN_PASSWORD - admin password for chassis, used in absence of -S" >&2 + echo "example:">&2 + echo " opashowallports" >&2 + echo " opashowallports -h 'elrond arwen'" >&2 + echo " HOSTS='elrond arwen' opashowallports" >&2 + echo " opashowallports -C" >&2 + echo " opashowallports -H 'chassis1 chassis2'" >&2 + echo " CHASSIS='chassis1 chassis2' opashowallports -C" >&2 + exit 0 +} + + +Usage() +{ + echo "Usage: opashowallports [-C] [-f hostfile] [-F chassisfile] [-S]" >&2 + echo " or" >&2 + echo " opashowallports --help" >&2 + echo " --help - produce full help text" >&2 + echo " -C - perform operation against chassis, default is hosts" >&2 + echo " -f hostfile - file with hosts in cluster, default is $CONFIG_DIR/opa/hosts" >&2 + echo " -F chassisfile - file with chassis in cluster" >&2 + echo " default is $CONFIG_DIR/opa/chassis" >&2 + echo " -S - securely prompt for password for admin on chassis" >&2 + echo "example:">&2 + echo " opashowallports" >&2 + echo " opashowallports -C" >&2 + exit 2 +} + +if [ x"$1" = "x--help" ] +then + Usage_full +fi + +host=0 +chassis=0 +Sopt=n +while getopts Cf:F:h:H:S param +do + case $param in + C) + chassis=1;; + f) + host=1 + HOSTS_FILE="$OPTARG";; + F) + chassis=1 + CHASSIS_FILE="$OPTARG";; + h) + host=1 + HOSTS="$OPTARG";; + H) + chassis=1 + CHASSIS="$OPTARG";; + S) + Sopt=y;; + ?) + Usage;; + esac +done +shift $((OPTIND -1)) +if [[ $# -gt 0 ]] +then + Usage +fi +if [[ $(($chassis+$host)) -gt 1 ]] +then + echo "opashowallports: conflicting arguments, both host and chassis specified" >&2 + Usage +fi +if [[ $(($chassis+$host)) -eq 0 ]] +then + host=1 +fi + +if [ "$chassis" -eq 0 ] +then + + check_host_args opashowallports + for hostname in $HOSTS + do + echo "--------------------------------------------------------------------" + echo "$hostname:" + /usr/lib/opa/tools/tcl_proc hosts_run_cmd "$hostname" "root" '/usr/sbin/opainfo' 1 + done +else + + check_chassis_args opashowallports + export CFG_CHASSIS_LOGIN_METHOD=$FF_CHASSIS_LOGIN_METHOD + export CFG_CHASSIS_ADMIN_PASSWORD=$FF_CHASSIS_ADMIN_PASSWORD + if [ "$Sopt" = y ] + then + echo -n "Password for admin on all chassis: " > /dev/tty + stty -echo < /dev/tty > /dev/tty + password= + read password < /dev/tty + stty echo < /dev/tty > /dev/tty + echo > /dev/tty + export CFG_CHASSIS_ADMIN_PASSWORD="$password" + fi + for chassis in $CHASSIS + do + chassis=`strip_chassis_slots "$chassis"` + echo "--------------------------------------------------------------------" + echo "$chassis:" + /usr/lib/opa/tools/tcl_proc chassises_run_cmd "$chassis" "admin" 'ismPortStats -noprompt' 1 2>&1|egrep 'FAIL|Port State|Link Qual|Link Width|Link Speed|^[[:space:]]|^Name' | egrep -v 'Tx|Rx' + done +fi diff --git a/IbaTools/FastFabric/opaswdisableall.sh b/IbaTools/FastFabric/opaswdisableall.sh new file mode 100755 index 0000000..d7ebad4 --- /dev/null +++ b/IbaTools/FastFabric/opaswdisableall.sh @@ -0,0 +1,197 @@ +#!/bin/bash +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2018, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] +# This script provides a simple way to disable all unused switch ports +# or re-enable all presently unused (or disabled) switch ports +# it uses opareport to gather the information from the SM + +# optional override of defaults +if [ -f /etc/opa/opafastfabric.conf ] +then + . /etc/opa/opafastfabric.conf +fi + +. /usr/lib/opa/tools/opafastfabric.conf.def + +if [ -f /usr/lib/opa/tools/ff_funcs ] +then + . /usr/lib/opa/tools/ff_funcs +fi + +trap "exit 1" SIGHUP SIGTERM SIGINT + +tool="/usr/sbin/opaportconfig" +cmd=`basename $0` +if [ "$cmd" == "opaswdisableall" ] +then + subcmd="disable" + capsubcmd="Disable" + extra="" + operation="Disabling" +elif [ "$cmd" == "opaswenableall" ] +then + subcmd="enable" + capsubcmd="Re-enable" + extra=" (or disabled)" + operation="Enabling" + cmd="opaswenableall" +else + echo "$cmd: Invalid rename of command. Must be opaswenableall or opaswdisableall" >&2 + exit 1 +fi + +Usage_full() +{ + echo "Usage: $cmd [-t portsfile] [-p ports] [-F focus]" >&2 + echo " or" >&2 + echo " $cmd --help" >&2 + echo "$capsubcmd all unused$extra switch ports" >&2 + echo " --help - produce full help text" >&2 + echo " -t portsfile - file with list of local HFI ports used to access" >&2 + echo " fabric(s) for operation, default is $CONFIG_DIR/opa/ports" >&2 + echo " -p ports - list of local HFI ports used to access fabric(s) for operation" >&2 + echo " default is 1st active port" >&2 + echo " This is specified as hfi:port" >&2 + echo " 0:0 = 1st active port in system" >&2 + echo " 0:y = port y within system" >&2 + echo " x:0 = 1st active port on HFI x" >&2 + echo " x:y = HFI x, port y" >&2 + echo " The first HFI in the system is 1. The first port on an HFI is 1." >&2 + echo " -F focus - an opareport style focus argument to limit scope of operation" >&2 + echo " See opareport --help for more information" >&2 + echo " Environment:" >&2 + echo " PORTS - list of ports, used in absence of -t and -p" >&2 + echo " PORTS_FILE - file containing list of ports, used in absence of -t and -p" >&2 + echo "for example:" >&2 + echo " $cmd" >&2 + echo " $cmd -p '1:1 1:2 2:1 2:2'" >&2 + exit 0 +} + +Usage() +{ + echo "Usage: $cmd" >&2 + echo " or" >&2 + echo " $cmd --help" >&2 + echo "$capsubcmd all unused$extra switch ports" >&2 + echo " --help - produce full help text" >&2 + echo "for example:" >&2 + echo " $cmd" >&2 + exit 2 +} + +## Main function: + +focus="" + +if [ x"$1" = "x--help" ] +then + Usage_full +fi + +while getopts p:t:F: param +do + case $param in + p) + export PORTS="$OPTARG";; + + t) + export PORTS_FILE="$OPTARG";; + + F) + focus="-F '$OPTARG'";; + + *) + Usage;; + + esac + +done + +shift $((OPTIND -1)) +if [ $# -ge 1 ] +then + Usage +fi +check_ports_args $cmd + +change_swports() +{ + # $1 = hfi + # $2 = port + if [ "$port" -eq 0 ] + then + port_opts="-h $hfi" # default port to 1st active + else + port_opts="-h $hfi -p $port" + fi + + echo "$operation Ports on Fabric $hfi:$port:" + echo "NodeGUID Port Name" + + IFS=';' + eval /usr/sbin/opareport $port_opts -q -x -o otherports "$focus" | \ + /usr/sbin/opaxmlextract -d \; -e Switches.OtherPort.NodeGUID -e Switches.OtherPort.PortNum -e Switches.OtherPort.NodeDesc | \ + tail -n +2 | while read guid port nodedesc + do + lid=`eval /usr/sbin/opasaquery $port_opts -o lid -n $guid 2>/dev/null` + # silently skip node guids we can't find in SA anymore, may be tranisient + if [ "$?" -eq 0 -a "$lid" != "No Records Returned" ] + then + printf "%18s %3s %s\n" "$guid" "$port" "$nodedesc" + eval "$tool" $port_opts -l "$lid" -m "$port" "$subcmd" > /dev/null + fi + done + echo "-------------------------------------------------------------------------------" +} + +status=ok + +for hfi_port in $PORTS +do + hfi=$(expr $hfi_port : '\([0-9]*\):[0-9]*') + port=$(expr $hfi_port : '[0-9]*:\([0-9]*\)') + if [ "$hfi" = "" -o "$port" = "" ] + then + echo "$cmd: Error: Invalid port specification: $hfi_port" >&2 + status=bad + continue + fi + + change_swports "$hfi" "$port" +done + +if [ "$status" != "ok" ] +then + exit 1 +else + exit 0 +fi diff --git a/IbaTools/FastFabric/opatest.sh b/IbaTools/FastFabric/opatest.sh new file mode 100755 index 0000000..057c117 --- /dev/null +++ b/IbaTools/FastFabric/opatest.sh @@ -0,0 +1,1001 @@ +#!/bin/bash +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] +# perform installation verification on hosts in a cluster + +# optional override of defaults +if [ -f /etc/opa/opafastfabric.conf ] +then + . /etc/opa/opafastfabric.conf +fi + +. /usr/lib/opa/tools/opafastfabric.conf.def + +. /usr/lib/opa/tools/ff_funcs + +if [ x"$FF_IPOIB_SUFFIX" = xNONE ] +then + export FF_IPOIB_SUFFIX="" +fi + +# identify how we are being run, affects valid options and usage +mode=invalid +cmd=`basename $0` +case $cmd in +opahostadmin|opaswitchadmin|opachassisadmin) mode=$cmd;; +esac + +if [ "$mode" = "invalid" ] +then + echo "Invalid executable name for this file: $cmd; expected opahostadmin, opaswitchadmin or opachassisadmin" >&2 + exit 1 +fi + +Usage_opahostadmin_full() +{ + echo "Usage: opahostadmin [-c] [-i ipoib_suffix] [-f hostfile] [-h 'hosts'] " >&2 + echo " [-r release] [-I install_options] [-U upgrade_options] [-d dir]" >&2 + echo " [-T product] [-P packages] [-m netmask] [-S] operation ..." >&2 + echo " or" >&2 + echo " opahostadmin --help" >&2 + echo " --help - produce full help text" >&2 + echo " -c - clobber result files from any previous run before starting this run" >&2 + echo " -i ipoib_suffix - suffix to apply to host names to create ipoib host names" >&2 + echo " default is '$FF_IPOIB_SUFFIX'" >&2 + echo " -f hostfile - file with hosts in cluster, default is $CONFIG_DIR/opa/hosts" >&2 + echo " -h hosts - list of hosts to execute operation against" >&2 + echo " -r release - IntelOPA release to load/upgrade to, default is $FF_PRODUCT_VERSION" >&2 + echo " -d dir - directory to get product.release.tgz from for load/upgrade" >&2 + echo " -I install_options - IntelOPA install options" >&2 + echo " -U upgrade_options - IntelOPA upgrade options" >&2 + echo " -T product - IntelOPA product type to install" >&2 + echo " default is $FF_PRODUCT" >&2 + echo " Other options include: IntelOPA-Basic.," >&2 + echo " IntelOPA-IFS." >&2 + echo " Where is the distro and CPU, such as RHEL7-x86_64" >&2 + echo " -P packages - IntelOPA packages to install, default is '$FF_PACKAGES'" >&2 + echo " See IntelOPA INSTALL -C for a complete list of packages" >&2 + echo " -m netmask - IPoIB netmask to use for configipoib" >&2 + echo " -S - securely prompt for password for user on remote system" >&2 + echo " operation - operation to perform. operation can be one or more of:" >&2 + echo " load - initial install of all hosts" >&2 + echo " upgrade - upgrade install of all hosts" >&2 + echo " configipoib - create ifcfg-ib1 using host IP addr from /etc/hosts" >&2 + echo " reboot - reboot hosts, ensure they go down and come back" >&2 + echo " sacache - confirm sacache has all hosts in it" >&2 + echo " ipoibping - verify this host can ping each host via IPoIB" >&2 + echo " mpiperf - verify latency and bandwidth for each host" >&2 + echo " mpiperfdeviation - check for latency and bandwidth tolerance" >&2 + echo " deviation between hosts" >&2 + echo " Environment:" >&2 + echo " HOSTS - list of hosts, used if -h option not supplied" >&2 + echo " HOSTS_FILE - file containing list of hosts, used in absence of -f and -h" >&2 + echo " FF_MAX_PARALLEL - maximum concurrent operations" >&2 + echo " FF_SERIALIZE_OUTPUT - serialize output of parallel operations (yes or no)" >&2 + echo " FF_TIMEOUT_MULT - Multiplier for all timeouts associated with this command." >&2 + echo " Used if the systems are slow for some reason." >&2 + echo "for example:" >&2 + echo " opahostadmin -c reboot" >&2 + echo " opahostadmin upgrade" >&2 + echo " opahostadmin -h 'elrond arwen' reboot" >&2 + echo " HOSTS='elrond arwen' opahostadmin reboot" >&2 + echo "During run the following files are produced:" >&2 + echo " test.res - appended with summary results of run" >&2 + echo " test.log - appended with detailed results of run" >&2 + echo " save_tmp/ - contains a directory per failed operation with detailed logs" >&2 + echo " test_tmp*/ - intermediate result files while operation is running" >&2 + echo "-c option will remove all of the above" >&2 + exit 0 +} +Usage_opachassisadmin_full() +{ + echo "Usage: opachassisadmin [-c] [-F chassisfile] [-H 'chassis'] " >&2 + echo " [-P packages] [-a action] [-I fm_bootstate]" >&2 + echo " [-S] [-d upload_dir] [-s securityfiles] operation ..." >&2 + echo " or" >&2 + echo " opachassisadmin --help" >&2 + echo " --help - produce full help text" >&2 + echo " -c - clobber result files from any previous run before starting this run" >&2 + echo " -F chassisfile - file with chassis in cluster" >&2 + echo " default is $CONFIG_DIR/opa/chassis" >&2 + echo " -H chassis - list of chassis to execute operation against" >&2 + echo " -P packages - filenames/directories of firmware" >&2 + echo " images to install. For directories specified, all" >&2 + echo " .pkg, .dpkg and .spkg files in directory tree will be used." >&2 + echo " shell wildcards may also be used within quotes." >&2 + echo " or for fmconfig, filename of FM config file to use" >&2 + echo " or for fmgetconfig, filename to upload to (default" >&2 + echo " opafm.xml)" >&2 + echo " -a action - action for supplied file" >&2 + echo " For Chassis upgrade:" >&2 + echo " push - ensure firmware is in primary or alternate" >&2 + echo " select - ensure firmware is in primary" >&2 + echo " run - ensure firmware is in primary and running" >&2 + echo " default is push" >&2 + echo " For Chassis fmconfig:" >&2 + echo " push - ensure config file is in chassis" >&2 + echo " run - after push, restart FM on master, stop on slave" >&2 + echo " runall - after push, restart FM on all MM" >&2 + echo " For Chassis fmcontrol:" >&2 + echo " stop - stop FM on all MM" >&2 + echo " run - make sure FM running on master, stopped on slave" >&2 + echo " runall - make sure FM running on all MM" >&2 + echo " restart- restart FM on master, stop on slave" >&2 + echo " restartall- restart FM on all MM" >&2 + echo " For Chassis fmsecurityfiles:" >&2 + echo " push - ensure FM security files are in chassis" >&2 + echo " restart- after push, restart FM on master, stop on slave" >&2 + echo " restartall - after push, restart FM on all MM" >&2 + echo " -I fm_bootstate fmconfig and fmcontrol install options" >&2 + echo " disable - disable FM start at chassis boot" >&2 + echo " enable - enable FM start on master at chassis boot" >&2 + echo " enableall - enable FM start on all MM at chassis boot" >&2 + echo " -d upload_dir - directory to upload FM config files to, default is uploads" >&2 + echo " -S - securely prompt for password for admin on chassis" >&2 + echo " -s securityFiles - security files to install, default is '*.pem'" >&2 + echo " For Chassis fmsecurityfiles, filenames/directories of" >&2 + echo " security files to install. For directories specified," >&2 + echo " all security files in directory tree will be used." >&2 + echo " shell wildcards may also be used within quotes." >&2 + echo " or for Chassis fmgetsecurityfiles, filename to upload to" >&2 + echo " (default *.pem)" >&2 + echo " operation - operation to perform. operation can be one or more of:" >&2 + echo " reboot - reboot chassis, ensure they go down and come back" >&2 + echo " configure - run wizard to set up chassis configuration" >&2 + echo " upgrade - upgrade install of all chassis" >&2 + echo " getconfig - get basic configuration of chassis" >&2 + echo " fmconfig - FM config operation on all chassis" >&2 + echo " fmgetconfig - Fetch FM config from all chassis" >&2 + echo " fmcontrol - Control FM on all chassis" >&2 + echo " fmsecurityfiles - FM security files operation on all chassis" >&2 + echo " fmgetsecurityfiles - Fetch FM security files from all chassis" >&2 + echo " Environment:" >&2 + echo " CHASSIS - list of chassis, used if -H and -F option not supplied" >&2 + echo " CHASSIS_FILE - file containing list of chassis, used in absence of -F and -H" >&2 + echo " FF_MAX_PARALLEL - maximum concurrent operations" >&2 + echo " FF_SERIALIZE_OUTPUT - serialize output of parallel operations (yes or no)" >&2 + echo " FF_TIMEOUT_MULT - Multiplier for all timeouts associated with this command." >&2 + echo " Used if the systems are slow for some reason." >&2 + echo " UPLOADS_DIR - directory to upload to, used in absence of -d" >&2 + echo "for example:" >&2 + echo " opachassisadmin -c reboot" >&2 + echo " opachassisadmin -P /root/ChassisFw4.2.0.0.1 upgrade" >&2 + echo " opachassisadmin -H 'chassis1 chassis2' reboot" >&2 + echo " CHASSIS='chassis1 chassis2' opachassisadmin reboot" >&2 + echo " opachassisadmin -a run -P '*.pkg' upgrade" >&2 + echo "During run the following files are produced:" >&2 + echo " test.res - appended with summary results of run" >&2 + echo " test.log - appended with detailed results of run" >&2 + echo " save_tmp/ - contains a directory per failed operation with detailed logs" >&2 + echo " test_tmp*/ - intermediate result files while operation is running" >&2 + echo "-c option will remove all of the above" >&2 + exit 0 +} +Usage_opaswitchadmin_full() +{ + echo "Usage: opaswitchadmin [-c] [-N 'nodes'] [-L nodefile] [-O] [-P packages]" >&2 + echo " [-a action] [-t portsfile] [-p ports] operation ..." >&2 + echo " or" >&2 + echo " opaswitchadmin --help" >&2 + echo " --help - produce full help text" >&2 + echo " -c - clobber result files from any previous run before starting this run" >&2 + echo " -N nodes - list of OPA switches to execute operation against" >&2 + echo " -L nodefile - file with OPA switches in cluster" >&2 + echo " default is $CONFIG_DIR/opa/switches" >&2 + echo " -P packages - for upgrade, filename/directory of firmware" >&2 + echo " image to install. For directory specified," >&2 + echo " .emfw file in directory tree will be used." >&2 + echo " shell wildcards may also be used within quotes." >&2 + echo " -t portsfile - file with list of local HFI ports used to access" >&2 + echo " fabric(s) for switch access, default is /etc/opa/ports" >&2 + echo " -p ports - list of local HFI ports used to access fabric(s) for switch access" >&2 + echo " default is 1st active port" >&2 + echo " This is specified as hfi:port" >&2 + echo " 0:0 = 1st active port in system" >&2 + echo " 0:y = port y within system" >&2 + echo " x:0 = 1st active port on HFI x" >&2 + echo " x:y = HFI x, port y" >&2 + echo " The first HFI in the system is 1. The first port on an HFI is 1." >&2 + echo " -a action - action for firmware file for Switch upgrade" >&2 + echo " select - ensure firmware is in primary" >&2 + echo " run - ensure firmware is in primary and running" >&2 + echo " default is select" >&2 + echo " -O - override: for firmware upgrade, bypass version checks and force update" >&2 + echo " unconditionally" >&2 + echo " operation - operation to perform. operation can be one or more of:" >&2 + echo " reboot - reboot switches, ensure they go down and come back" >&2 + echo " configure - run wizard to set up switch configuration" >&2 + echo " NOTE: You must reboot the switch for any new settings to be applied." >&2 + echo " upgrade - upgrade install of all switches" >&2 + echo " info - report f/w & h/w version, part number, and data rate capability of" >&2 + echo " all OPA switches" >&2 + echo " hwvpd - complete hardware VPD report of all OPA switches" >&2 + echo " ping - ping all OPA switches - test for presence" >&2 + echo " fwverify - report integrity of failsafe firmware of all OPA switches" >&2 + echo " getconfig - get port configurations of a externally managed switch" >&2 + echo " Environment:" >&2 + echo " OPASWITCHES - list of nodes, used if -N and -L option not supplied" >&2 + echo " OPASWITCHES_FILE - file containing list of nodes, used in absence of -N and" >&2 + echo " -L" >&2 + echo " FF_MAX_PARALLEL - maximum concurrent operations" >&2 + echo " FF_SERIALIZE_OUTPUT - serialize output of parallel operations (yes or no)" >&2 + echo " FF_TIMEOUT_MULT - Multiplier for all timeouts associated with this command." >&2 + echo " Used if the systems are slow for some reason." >&2 + echo "for example:" >&2 + echo " opaswitchadmin -c reboot" >&2 + echo " opaswitchadmin -P /root/ChassisFw4.2.0.0.1 upgrade" >&2 + echo " opaswitchadmin -a run -P '*.emfw' upgrade" >&2 + echo "During run the following files are produced:" >&2 + echo " test.res - appended with summary results of run" >&2 + echo " test.log - appended with detailed results of run" >&2 + echo " save_tmp/ - contains a directory per failed operation with detailed logs" >&2 + echo " test_tmp*/ - intermediate result files while operation is running" >&2 + echo "-c option will remove all of the above" >&2 + exit 0 +} +Usage_full() +{ + case $mode in + opahostadmin) Usage_opahostadmin_full;; + opachassisadmin) Usage_opachassisadmin_full;; + opaswitchadmin) Usage_opaswitchadmin_full;; + esac +} +Usage_opahostadmin() +{ + echo "Usage: opahostadmin [-c] [-f hostfile] [-r release] [-d dir]" >&2 + echo " [-T product] [-P packages] [-S] operation ..." >&2 + echo " or" >&2 + echo " opahostadmin --help" >&2 + echo " --help - produce full help text" >&2 + echo " -c - clobber result files from any previous run before starting this run" >&2 + echo " -f hostfile - file with hosts in cluster, default is $CONFIG_DIR/opa/hosts" >&2 + echo " -r release - IntelOPA release to load/upgrade to, default is $FF_PRODUCT_VERSION" >&2 + echo " -d dir - directory to get product.release.tgz from for load/upgrade" >&2 + echo " -T product - IntelOPA product type to install" >&2 + echo " default is $FF_PRODUCT" >&2 + echo " Other options include: IntelOPA-Basic., IntelOPA-IFS." >&2 + echo " Where is the distro and CPU, such as RHEL7-x86_64" >&2 + echo " -P packages - IntelOPA packages to install, default is '$FF_PACKAGES'" >&2 + echo " See IntelOPA INSTALL -C for a complete list of packages" >&2 + echo " -S - securely prompt for password for user on remote system" >&2 + echo " operation - operation to perform. operation can be one or more of:" >&2 + echo " load - initial install of all hosts" >&2 + echo " upgrade - upgrade install of all hosts" >&2 + echo " configipoib - create ifcfg-ib1 using host IP addr from /etc/hosts" >&2 + echo " reboot - reboot hosts, ensure they go down and come back" >&2 + echo " sacache - confirm sacache has all hosts in it" >&2 + echo " ipoibping - verify this host can ping each host via IPoIB" >&2 + echo " mpiperf - verify latency and bandwidth for each host" >&2 + echo " mpiperfdeviation - check for latency and bandwidth tolerance" >&2 + echo " deviation between hosts" >&2 + echo "for example:" >&2 + echo " opahostadmin -c reboot" >&2 + echo " opahostadmin upgrade" >&2 + echo "During run the following files are produced:" >&2 + echo " test.res - appended with summary results of run" >&2 + echo " test.log - appended with detailed results of run" >&2 + echo " save_tmp/ - contains a directory per failed test with detailed logs" >&2 + echo " test_tmp*/ - intermediate result files while test is running" >&2 + echo "-c option will remove all of the above" >&2 + exit 2 +} +Usage_opachassisadmin() +{ + echo "Usage: opachassisadmin [-c] [-F chassisfile] " >&2 + echo " [-P packages] [-I fm_bootstate] [-a action]" >&2 + echo " [-S] [-d upload_dir] [-s securityfiles] operation ..." >&2 + echo " or" >&2 + echo " opachassisadmin --help" >&2 + echo " --help - produce full help text" >&2 + echo " -c - clobber result files from any previous run before starting this run" >&2 + echo " -F chassisfile - file with chassis in cluster" >&2 + echo " default is $CONFIG_DIR/opa/chassis" >&2 + echo " -P packages - filenames/directories of firmware" >&2 + echo " images to install. For directories specified, all" >&2 + echo " .pkg, .dpkg and .spkg files in directory tree will be used." >&2 + echo " shell wildcards may also be used within quotes." >&2 + echo " or for fmconfig, filename of FM config file to use" >&2 + echo " or for fmgetconfig, filename to upload to (default" >&2 + echo " opafm.xml)" >&2 + echo " -a action - action for supplied file" >&2 + echo " For Chassis upgrade:" >&2 + echo " push - ensure firmware is in primary or alternate" >&2 + echo " select - ensure firmware is in primary" >&2 + echo " run - ensure firmware is in primary and running" >&2 + echo " default is push" >&2 + echo " For Chassis fmconfig:" >&2 + echo " push - ensure config file is in chassis" >&2 + echo " run - after push, restart FM on master, stop on slave" >&2 + echo " runall - after push, restart FM on all MM" >&2 + echo " For Chassis fmcontrol:" >&2 + echo " stop - stop FM on all MM" >&2 + echo " run - make sure FM running on master, stopped on slave" >&2 + echo " runall - make sure FM running on all MM" >&2 + echo " restart- restart FM on master, stop on slave" >&2 + echo " restartall- restart FM on all MM" >&2 + echo " For Chassis fmsecurityfiles:" >&2 + echo " push - ensure FM security files are in chassis" >&2 + echo " restart- after push, restart FM on master, stop on slave" >&2 + echo " restartall - after push, restart FM on all MM" >&2 + echo " -I fm_bootstate fmconfig and fmcontrol install options" >&2 + echo " disable - disable FM start at chassis boot" >&2 + echo " enable - enable FM start on master at chassis boot" >&2 + echo " enableall - enable FM start on all MM at chassis boot" >&2 + echo " -d upload_dir - directory to upload FM config files to, default is uploads" >&2 + echo " -S - securely prompt for password for admin on chassis" >&2 + echo " -s securityFiles - security files to install, default is '*.pem'" >&2 + echo " For Chassis fmsecurityfiles, filenames/directories of" >&2 + echo " security files to install. For directories specified," >&2 + echo " all security files in directory tree will be used." >&2 + echo " shell wildcards may also be used within quotes." >&2 + echo " or for Chassis fmgetsecurityfiles, filename to upload to" >&2 + echo " (default *.pem)" >&2 + echo " operation - operation to perform. operation can be one or more of:" >&2 + echo " reboot - reboot chassis, ensure they go down and come back" >&2 + echo " configure - run wizard to set up chassis configuration" >&2 + echo " upgrade - upgrade install of all chassis" >&2 + echo " getconfig - get basic configuration of chassis" >&2 + echo " fmconfig - FM config operation on all chassis" >&2 + echo " fmgetconfig - Fetch FM config from all chassis" >&2 + echo " fmcontrol - Control FM on all chassis" >&2 + echo " fmsecurityfiles - FM security files operation on all chassis" >&2 + echo " fmgetsecurityfiles - Fetch FM security files from all chassis" >&2 + echo "for example:" >&2 + echo " opachassisadmin -c reboot" >&2 + echo " opachassisadmin -P /root/ChassisFw4.2.0.0.1 upgrade" >&2 + echo " opachassisadmin -a run -P '*.pkg' upgrade" >&2 + echo "During run the following files are produced:" >&2 + echo " test.res - appended with summary results of run" >&2 + echo " test.log - appended with detailed results of run" >&2 + echo " save_tmp/ - contains a directory per failed operation with detailed logs" >&2 + echo " test_tmp*/ - intermediate result files while operation is running" >&2 + echo "-c option will remove all of the above" >&2 + exit 2 +} +Usage_opaswitchadmin() +{ + echo "Usage: opaswitchadmin [-c] [-L nodefile] [-O] [-P packages]" >&2 + echo " [-a action] operation ..." >&2 + echo " or" >&2 + echo " opaswitchadmin --help" >&2 + echo " --help - produce full help text" >&2 + echo " -c - clobber result files from any previous run before starting this run" >&2 + echo " -L nodefile - file with OPA switches in cluster" >&2 + echo " default is $CONFIG_DIR/opa/switches" >&2 + echo " -P packages - for upgrade, filename/directory of firmware" >&2 + echo " image to install. For directory specified," >&2 + echo " .emfw file in directory tree will be used." >&2 + echo " shell wildcards may also be used within quotes." >&2 + echo " -a action - action for firmware file for Switch upgrade" >&2 + echo " select - ensure firmware is in primary" >&2 + echo " run - ensure firmware is in primary and running" >&2 + echo " default is select" >&2 + echo " -O - override: for firmware upgrade, bypass version checks and force update" >&2 + echo " unconditionally" >&2 + echo " operation - operation to perform. operation can be one or more of:" >&2 + echo " reboot - reboot switches, ensure they go down and come back" >&2 + echo " configure - run wizard to set up switch configuration" >&2 + echo " NOTE: You must reboot the switch for any new settings to be applied." >&2 + echo " upgrade - upgrade install of all switches" >&2 + echo " info - report f/w & h/w version, part number, and data rate capability of" >&2 + echo " all OPA switches" >&2 + echo " hwvpd - complete hardware VPD report of all OPA switches" >&2 + echo " ping - ping all OPA switches - test for presence" >&2 + echo " fwverify - report integrity of failsafe firmware of all OPA switches" >&2 + echo " getconfig - get port configurations of a externally managed switch" >&2 + echo "for example:" >&2 + echo " opaswitchadmin -c reboot" >&2 + echo " opaswitchadmin -P /root/ChassisFw4.2.0.0.1 upgrade" >&2 + echo " opaswitchadmin -a run -P '*.emfw' upgrade" >&2 + echo "During run the following files are produced:" >&2 + echo " test.res - appended with summary results of run" >&2 + echo " test.log - appended with detailed results of run" >&2 + echo " save_tmp/ - contains a directory per failed operation with detailed logs" >&2 + echo " test_tmp*/ - intermediate result files while operation is running" >&2 + echo "-c option will remove all of the above" >&2 + exit 2 +} +Usage() +{ + case $mode in + opahostadmin) Usage_opahostadmin;; + opachassisadmin) Usage_opachassisadmin;; + opaswitchadmin) Usage_opaswitchadmin;; + esac +} + +if [ x"$1" = "x--help" ] +then + Usage_full +fi + +# default to install wrapper version +if [ -e /etc/opa/version_wrapper ] +then + CFG_RELEASE=`cat /etc/opa/version_wrapper 2>/dev/null`; +fi +if [ x"$CFG_RELEASE" = x ] +then +# if no wrapper, use version of FF itself as filled in at build time +# version string is filled in by prep, special marker format for it to use +CFG_RELEASE="THIS_IS_THE_ICS_VERSION_NUMBER:@(#)000.000.000.000B000" +fi +export CFG_RELEASE=`echo $CFG_RELEASE|sed -e 's/THIS_IS_THE_ICS_VERSION_NUMBER:@(#.//' -e 's/%.*//'` +# THIS_IS_THE_ICS_INTERNAL_VERSION_NUMBER:@(#)000.000.000.000B000 +# test automation configuration defaults +export CFG_INIC_SUFFIX= +export CFG_IPOIB_SUFFIX="$FF_IPOIB_SUFFIX" +export CFG_USERNAME="$FF_USERNAME" +export CFG_PASSWORD="$FF_PASSWORD" +export CFG_ROOTPASS="$FF_ROOTPASS" +export CFG_LOGIN_METHOD="$FF_LOGIN_METHOD" +export CFG_CHASSIS_LOGIN_METHOD="$FF_CHASSIS_LOGIN_METHOD" +export CFG_CHASSIS_ADMIN_PASSWORD="$FF_CHASSIS_ADMIN_PASSWORD" +export CFG_FAILOVER="n" +export CFG_FTP_SERVER="" +export CFG_IPOIB="y" +export CFG_IPOIB_MTU="2030" +export CFG_IPOIB_COMBOS=TBD +export CFG_INIC=n +export CFG_SDP=n +export CFG_SRP=n +export CFG_MPI=y +export CFG_UDAPL=n +export TEST_TIMEOUT_MULT="$FF_TIMEOUT_MULT" +export TEST_RESULT_DIR="$FF_RESULT_DIR" +export TEST_MAX_PARALLEL="$FF_MAX_PARALLEL" +export TEST_CONFIG_FILE="/dev/null" +export TL_DIR=/usr/lib/opa/tools +export TEST_IDENTIFY=no +export TEST_SHOW_CONFIG=no +export TEST_SHOW_START=yes +export CFG_PRODUCT="${FF_PRODUCT:-IntelOPA-Basic}" +export CFG_INSTALL_OPTIONS="$FF_INSTALL_OPTIONS" +export CFG_UPGRADE_OPTIONS="$FF_UPGRADE_OPTIONS" +export CFG_IPOIB_NETMASK="$FF_IPOIB_NETMASK" +export CFG_IPOIB_CONNECTED="$FF_IPOIB_CONNECTED" +export CFG_MPI_ENV="$FF_MPI_ENV" +export TEST_SERIALIZE_OUTPUT="$FF_SERIALIZE_OUTPUT" + +clobber=n +host=0 +chassis=0 +opaswitch=0 +dir=. +packages="notsupplied" +action=default +Sopt=n +sopt=n +bypassSwitchCheck=n +fwOverride=n +securityFiles="notsupplied" +case $mode in +opahostadmin) host=1; options='cd:h:f:i:r:I:U:P:T:m:S';; +opachassisadmin) chassis=1; options='a:I:cH:F:P:d:Ss:';; +opaswitchadmin) opaswitch=1; options='a:Bcd:P:p:t:L:N:O';; +esac +while getopts "$options" param +do + case $param in + a) + action="$OPTARG";; + B) + bypassSwitchCheck=y;; + c) + clobber=y;; + d) + dir="$OPTARG" + export UPLOADS_DIR="$dir";; + h) + host=1 + HOSTS="$OPTARG";; + H) + chassis=1 + CHASSIS="$OPTARG";; + N) + opaswitch=1 + OPASWITCHES="$OPTARG";; + f) + host=1 + HOSTS_FILE="$OPTARG";; + F) + chassis=1 + CHASSIS_FILE="$OPTARG";; + L) + opaswitch=1 + OPASWITCHES_FILE="$OPTARG";; + i) + export CFG_IPOIB_SUFFIX="$OPTARG" + export FF_IPOIB_SUFFIX="$OPTARG";; + r) + export FF_PRODUCT_VERSION="$OPTARG";; + I) + export CFG_INSTALL_OPTIONS="$OPTARG";; + U) + export CFG_UPGRADE_OPTIONS="$OPTARG";; + P) + packages="$OPTARG";; + T) + export CFG_PRODUCT="$OPTARG";; + m) + export CFG_IPOIB_NETMASK="$OPTARG";; + p) + export PORTS="$OPTARG";; + t) + export PORTS_FILE="$OPTARG";; + s) + securityFiles="$OPTARG";; + S) + Sopt=y;; + O) + fwOverride=y;; + ?) + Usage;; + esac +done +shift $((OPTIND -1)) + +if [ $# -lt 1 ] +then + Usage +fi + +for tkn in $* +do + if [[ $tkn == -* ]] + then + Usage + fi +done +# given optarg selections, this error should not be able to happen +if [[ $(($chassis+$host+$opaswitch)) -gt 1 ]] +then + echo "$cmd: conflicting arguments, more than one of host, chassis or opaswitches specified" >&2 + Usage +fi +# given mode checks, this error should not be able to happen +if [[ $(($chassis+$host+$opaswitch)) -eq 0 ]] +then + host=1 +fi +if [ ! -d "$FF_RESULT_DIR" ] +then + echo "$cmd: Invalid FF_RESULT_DIR: $FF_RESULT_DIR: No such directory" >&2 + exit 1 +fi +if [ $chassis -eq 1 ] +then + check_chassis_args $cmd + if [ "$action" = "default" ] + then + action=push + fi + if [ "$CFG_INSTALL_OPTIONS" = "$FF_INSTALL_OPTIONS" ] + then + export CFG_INSTALL_OPTIONS= + fi +elif [ $opaswitch -eq 1 ] +then + check_ib_transport_args $cmd + check_ports_args $cmd + if [ "$action" = "default" ] + then + action=select + fi +else + check_host_args $cmd + + if [ "$packages" = "notsupplied" ] + then + packages="$FF_PACKAGES" + fi + if [ "x$packages" != "x" ] + then + for p in $packages + do + CFG_INSTALL_OPTIONS="$CFG_INSTALL_OPTIONS -i $p" + done + fi + if [ "x$CFG_INSTALL_OPTIONS" = "x" ] + then + CFG_INSTALL_OPTIONS='-i iba -i ipoib -i mpi' + fi +fi + +export CFG_HOSTS="$HOSTS" +export CFG_CHASSIS="$CHASSIS" +export CFG_OPASWITCHES="$OPASWITCHES" +export CFG_PORTS="$PORTS" +export CFG_MPI_PROCESSES="$HOSTS" +#export CFG_PERF_PAIRS=TBD +export CFG_SCPFROMDIR="$dir" +if [ x"$FF_PRODUCT_VERSION" != x ] +then + CFG_RELEASE="$FF_PRODUCT_VERSION" +fi + +# use NONE so ff_function's inclusion of defaults works properly +if [ x"$FF_IPOIB_SUFFIX" = x ] +then + export FF_IPOIB_SUFFIX="NONE" + export CFG_IPOIB_SUFFIX="NONE" +fi + +if [ "$clobber" = "y" ] +then + ( cd $TEST_RESULT_DIR; rm -rf test.res save_tmp test.log test_tmp* *.dmp ) +fi + +# create an empty test.log file +( cd $TEST_RESULT_DIR; >> test.log ) + +run_test() +{ + # $1 = test suite name + TCLLIBPATH="$TL_DIR /usr/lib/tcl" expect -f $TL_DIR/$1.exp | tee -a $TEST_RESULT_DIR/test.res +} + +if [ $chassis -eq 1 ] +then + if [ "$Sopt" = y ] + then + read -sp "Password for admin on all chassis: " password + echo + export CFG_CHASSIS_ADMIN_PASSWORD="$password" + fi + for test_suite in $* + do + case $test_suite in + reboot) + run_test chassis_$test_suite;; + configure) + export CFG_CFGTEMPDIR="$(mktemp -d --tmpdir opacfgtmp.XXXXXX)" + # Update traps to delete all temporary directories. + trap "rm -rf $CFG_CFGTEMPDIR; exit 1" 1 2 3 9 15 + trap "rm -rf $CFG_CFGTEMPDIR" EXIT + + /usr/lib/opa/tools/chassis_setup $CFG_CFGTEMPDIR $CFG_CHASSIS + if [ $? = 0 ] + then + export SYSLOG_SERVER=`grep "Syslog Server IP_Address" $CFG_CFGTEMPDIR/.chassisSetup.out | cut -d : -f 2` + export SYSLOG_PORT=`grep "Syslog Port" $CFG_CFGTEMPDIR/.chassisSetup.out | cut -d : -f 2` + export SYSLOG_FACILITY=`grep "Syslog Facility" $CFG_CFGTEMPDIR/.chassisSetup.out | cut -d : -f 2` + export NTP_SERVER=`grep "NTP Server" $CFG_CFGTEMPDIR/.chassisSetup.out | cut -d : -f 2` + export TZ_OFFSET=`grep "Timezone offset" $CFG_CFGTEMPDIR/.chassisSetup.out | cut -d : -f 2` + export DST_START=`grep "Start DST" $CFG_CFGTEMPDIR/.chassisSetup.out | cut -d : -f 2` + export DST_END=`grep "End DST" $CFG_CFGTEMPDIR/.chassisSetup.out | cut -d : -f 2` + export LINKWIDTH_SETTING=`grep "Link Width Selection" $CFG_CFGTEMPDIR/.chassisSetup.out | cut -d : -f 2` + export SET_NAME=`grep "Set OPA Node Desc" $CFG_CFGTEMPDIR/.chassisSetup.out | cut -d : -f 2` + export LINKCRCMODE=`grep "Link CRC Mode" $CFG_CFGTEMPDIR/.chassisSetup.out | cut -d : -f 2` + run_test chassis_$test_suite + else + echo "Chassis setup wizard exited abnormally ... aborting" + fi;; + getconfig) + run_test chassis_$test_suite;; + upgrade) + if [ "$packages" = "notsupplied" -o "$packages" = "" ] + then + echo "$cmd: -P option required for chassis upgrade" >&2 + Usage + fi + if [ "$action" != "push" -a "$action" != "select" -a "$action" != "run" ] + then + echo "$cmd: Invalid firmware upgrade action: $action" >&2 + Usage + fi + # check fw files exist, expand directories + CFG_FWFILES="" + for fwfile in $packages + do + # expand directory, also filters files without .pkg/.dpkg/.spkg suffix + # this also expands wildcards in "$packages" + fwfiles=`find $fwfile -type f -name '*.pkg'` + fwfiles="$fwfiles `find $fwfile -type f -name '*.[ds]pkg'`" + if [ $? != 0 -o x"$fwfiles" == x -o x"$fwfiles" == x" " ] + then + echo "$cmd: $fwfile: No .pkg nor .dpkg nor .spkg files found" >&2 + Usage + fi + CFG_FWFILES="$CFG_FWFILES $fwfiles" + done + export CFG_FWFILES + export CFG_FWACTION="$action" + run_test chassis_$test_suite;; + fmconfig) + if [ "$packages" = "notsupplied" -o "$packages" = "" ] + then + echo "$cmd: -P option required for chassis fmconfig" >&2 + Usage + fi + if [ "$action" != "push" -a "$action" != "run" -a "$action" != "runall" ] + then + echo "$cmd: Invalid FM config action: $action" >&2 + Usage + fi + if [ "$CFG_INSTALL_OPTIONS" != "" -a "$CFG_INSTALL_OPTIONS" != "disable" -a "$CFG_INSTALL_OPTIONS" != "enable" -a "$CFG_INSTALL_OPTIONS" != "enableall" ] + then + echo "$cmd: Invalid FM bootstate: $CFG_INSTALL_OPTIONS" >&2 + Usage + fi + export CFG_FMFILE="$packages" + export CFG_FWACTION="$action" + run_test chassis_$test_suite;; + fmcontrol) + if [ "$action" != "stop" -a "$action" != "run" -a "$action" != "runall" -a "$action" != "restart" -a "$action" != "restartall" ] + then + echo "$cmd: Invalid FM config action: $action" >&2 + Usage + fi + if [ "$CFG_INSTALL_OPTIONS" != "" -a "$CFG_INSTALL_OPTIONS" != "disable" -a "$CFG_INSTALL_OPTIONS" != "enable" -a "$CFG_INSTALL_OPTIONS" != "enableall" ] + then + echo "$cmd: Invalid FM bootstate: $CFG_INSTALL_OPTIONS" >&2 + fi + export CFG_FWACTION="$action" + run_test chassis_$test_suite;; + fmgetconfig) + if [ "$packages" = "notsupplied" -o "$packages" = "" ] + then + packages="opafm.xml" + #echo "$cmd: -P option required for chassis fmgetconfig" >&2 + #Usage + fi + export CFG_FMFILE="$packages" + run_test chassis_$test_suite;; + fmsecurityfiles) + if [ "$securityFiles" = "notsupplied" -o "$securityFiles" = "" ] + then + echo "$cmd: -s option required for chassis fmsecurityfiles" >&2 + Usage + fi + if [ "$action" != "push" -a "$action" != "restart" -a "$action" != "restartall" ] + then + echo "$cmd: Invalid security files upgrade action: $action" >&2 + Usage + fi + # check security files exist, expand directories + CFG_SECFILES="" + for securityfile in $securityFiles + do + # expand directory, also filters files without .pem suffix + # this also expands wildcards in "$securityFiles" + securityfiles=`find $securityfile -type f -name '*.pem'` + if [ $? != 0 -o x"$securityfiles" == x ] + then + echo "$cmd: $securityfile: No .pem files found" >&2 + Usage + fi + CFG_SECFILES="$CFG_SECFILES $securityfiles" + done + export CFG_SECFILES + export CFG_SECACTION="$action" + run_test chassis_$test_suite;; + fmgetsecurityfiles) + if [ "$securityFiles" = "notsupplied" -o "$securityFiles" = "" ] + then + securityFiles="*.pem" + fi + export CFG_SECFILE="$securityFiles" + run_test chassis_$test_suite;; + *) + echo "Invalid Operation name: $test_suite" >&2 + Usage; + ;; + esac + done +elif [ $opaswitch -eq 1 ] +then + if [ "$bypassSwitchCheck" = y ] + then + export CFG_SWITCH_BYPASS_SWITCH_CHECK=y + else + export CFG_SWITCH_BYPASS_SWITCH_CHECK=n + fi + for test_suite in $* + do + + case $test_suite in + reboot) + run_test switch_$test_suite;; + info) + run_test switch_$test_suite;; + hwvpd) + run_test switch_$test_suite;; + ping) + run_test switch_$test_suite;; + fwverify) + run_test switch_$test_suite;; + configure) + CFG_CFGTEMPDIR="$(mktemp -d --tmpdir opacfgtmp.XXXXXX)" + # Update traps to delete all temporary directories. + trap "rm -rf $CFG_CFGTEMPDIR; exit 1" 1 2 3 9 15 + trap "rm -rf $CFG_CFGTEMPDIR" EXIT + /usr/lib/opa/tools/switch_setup $CFG_CFGTEMPDIR + if [ $? = 0 ] + then + export LINKWIDTH_SETTING=`grep "Link Width Selection" $CFG_CFGTEMPDIR/.switchSetup.out | cut -d : -f 2` + export NODEDESC_SETTING=`grep "Node Description Selection" $CFG_CFGTEMPDIR/.switchSetup.out | cut -d : -f 2` + export FMENABLED_SETTING=`grep "FM Enabled Selection" $CFG_CFGTEMPDIR/.switchSetup.out | cut -d : -f 2` + export LINKCRCMODE_SETTING=`grep "Link CRC Mode Selection" $CFG_CFGTEMPDIR/.switchSetup.out | cut -d : -f 2` + run_test switch_$test_suite + else + echo "Ext mgd switch setup wizard exited abnormally ... aborting" + fi;; + upgrade) + if [ "$packages" = "notsupplied" -o "$packages" = "" ] + then + echo "$cmd: -P option required for switch upgrade" >&2 + Usage + fi + if [ "$action" != "select" -a "$action" != "run" ] + then + echo "$cmd: Invalid firmware upgrade action: $action" >&2 + echo "$cmd: 'run' and 'select' are the only supported actions" >&2 + Usage + fi + + # check fw files exist, expand directories + CFG_FWFILES="" + CFG_FWBINFILES="" + + CFG_TMPDIR_LIST="" + for fwfile in $packages + do + + echo "$cmd: processing package file: $fwfile" >&2 + # expand directory, also filters files without .emfw suffix + # this also expands wildcards in "$packages" + fwfiles=`find $fwfile -type f -name '*.emfw'` + if [ $? != 0 -o x"$fwfiles" == x ] + then + echo "$cmd: $fwfile: No .emfw files found" >&2 + Usage + fi + CFG_FWFILES="$fwfiles" + + echo "$cmd: found package file: $fwfiles" >&2 + # copy file to temporary directory + for tarball in $CFG_FWFILES + do + # create temporary work directory + CFG_FWFILE="$tarball" + CFG_FWTEMPDIR="$(mktemp -d --tmpdir opafwtmp.XXXXXX)" + + # Update traps to delete all temporary directories. + CFG_TMPDIR_LIST="$CFG_TMPDIR_LIST $CFG_FWTEMPDIR" + trap "rm -rf $CFG_TMPDIR_LIST; exit 1" 1 2 3 9 15 + trap "rm -rf $CFG_TMPDIR_LIST" EXIT + + CFG_FWRELEASEFILE="$CFG_FWTEMPDIR/release.emfw.txt" + + cp -f $tarball $CFG_FWTEMPDIR + + # remove previous firmware image .bin files, and extract + # .bin files from .emfw file. + rm -rf '$CFG_FWTEMPDIR/*.bin' + tar --directory $CFG_FWTEMPDIR -zxf $tarball + + # search for text file that contains release related information + # about the firmware image .bin files + if [ ! -f "$CFG_FWRELEASEFILE" ] + then + echo "$cmd: No release.emfw.txt file found for package file: $tarball" >&2 + Usage + fi + + fwreleaseinfo=`cat $CFG_FWRELEASEFILE` + CFG_FWRELINFO="$fwreleaseinfo" + fwreleaseversioninfo=`cat $CFG_FWRELEASEFILE | grep _ | sed "s/_/./g"` + CFG_FWRELEASEVERSIONINFO=$fwreleaseversioninfo + CFG_FWSPEED=`cat $CFG_FWRELEASEFILE | grep DR` + if [ "$CFG_FWSPEED" = "" ] + then + CFG_FWSPEED="QDR" + fi + CFG_FWASICVER=`grep "V[0-9]" $CFG_FWRELEASEFILE` + if [ "$CFG_FWASICVER" = "" ] + then + CFG_FWASICVER="V0" + fi + CFG_SWITCH_DEVICE=`head -n 1 $CFG_FWRELEASEFILE` + + # expand directory, also filters files without .bin suffix + fwfiles=`find $CFG_FWTEMPDIR -type f -name '*.bin'` + if [ $? != 0 -o x"$fwfiles" == x ] + then + echo "$cmd: $tarball: No .bin files found" >&2 + Usage + fi + + CFG_FWBINFILES="$fwfiles" + CFG_FWOVERRIDE=$fwOverride + + export CFG_FWFILES + export CFG_FWFILE + export CFG_FWBINFILES + export CFG_FWTEMPDIR + export CFG_FWRELINFO + export CFG_FWSPEED + export CFG_FWASICVER + export CFG_SWITCH_DEVICE + export CFG_FWRELEASEVERSIONINFO + export CFG_FWACTION="$action" + export CFG_FWOVERRIDE + + echo "$cmd: upgrading with switch firmware image: $tarball : version $fwreleaseversioninfo" >&2 + run_test switch_$test_suite + + done + done + ;; + getconfig) + run_test switch_$test_suite;; + *) + echo "Invalid Operation name: $test_suite" >&2 + Usage; + ;; + esac + done +else + if [ "$Sopt" = y ] + then + read -sp "Password for $CFG_USERNAME on all hosts: " password + echo + export CFG_PASSWORD="$password" + if [ "$CFG_USERNAME" != "root" ] + then + read -sp "Password for root on all hosts: " password + echo + export CFG_ROOTPASS="$password" + else + export CFG_ROOTPASS="$CFG_PASSWORD" + fi + fi + for test_suite in $* + do + case $test_suite in + load|upgrade) + if [ ! -f "$dir/$CFG_PRODUCT.$CFG_RELEASE.tgz" ] + then + echo "$cmd: $dir/$CFG_PRODUCT.$CFG_RELEASE.tgz not found" >&2 + exit 1 + fi + run_test $test_suite;; + reboot|sacache|configipoib|ipoibping|mpiperf|mpiperfdeviation) + run_test $test_suite;; + *) + echo "Invalid Operation name: $test_suite" >&2 + Usage; + ;; + esac + done +fi diff --git a/IbaTools/FastFabric/opauploadall.sh b/IbaTools/FastFabric/opauploadall.sh new file mode 100755 index 0000000..ae9bda6 --- /dev/null +++ b/IbaTools/FastFabric/opauploadall.sh @@ -0,0 +1,224 @@ +#!/bin/bash +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2018, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] + +# optional override of defaults +if [ -f /etc/opa/opafastfabric.conf ] +then + . /etc/opa/opafastfabric.conf +fi + +. /usr/lib/opa/tools/opafastfabric.conf.def + +. /usr/lib/opa/tools/ff_funcs + +trap "exit 1" SIGHUP SIGTERM SIGINT + +Usage_full() +{ + echo "Usage: opauploadall [-rp] [-f hostfile] [-d upload_dir] [-h 'hosts'] [-u user]" >&2 + echo " source_file ... dest_file" >&2 + echo " or" >&2 + echo " opauploadall --help" >&2 + echo " --help - produce full help text" >&2 + echo " -p - perform copy in parallel on all hosts" >&2 + echo " -r - recursive upload of directories" >&2 + echo " -f hostfile - file with hosts in cluster, default is $CONFIG_DIR/opa/hosts" >&2 + echo " -h hosts - list of hosts to upload from" >&2 + echo " -u user - user to perform copy to, default is current user code" >&2 + echo " -d upload_dir - directory to upload to, default is uploads" >&2 + echo " source_file - list of source files to copy" >&2 + echo " dest_file - destination for copy" >&2 + echo " If more than 1 source file, this must be a directory" >&2 + echo " Environment:" >&2 + echo " HOSTS - list of hosts, used if -h option not supplied" >&2 + echo " HOSTS_FILE - file containing list of hosts, used in absence of -f and -h" >&2 + echo " UPLOADS_DIR - directory to upload to, used in absence of -d" >&2 + echo " FF_MAX_PARALLEL - when -p option is used, maximum concurrent operations" >&2 + echo "example:">&2 + echo " opauploadall -h 'arwen elrond' capture.tgz /etc/init.d/ipoib.cfg ." >&2 + echo " opauploadall -p capture.tgz /etc/init.d/ipoib.cfg ." >&2 + echo " opauploadall capture.tgz /etc/init.d/ipoib.cfg pre-install" >&2 + echo "user@ syntax cannot be used in filenames specified" >&2 + echo "A local directory within upload_dir/ will be created for each hostname." >&2 + echo "Destination file will be upload_dir/hostname/dest_file within the local system." >&2 + echo "If copying multiple files, or dest_file has a trailing /, dest_file" >&2 + echo " directory will be created." >&2 + echo "To copy files from this host to hosts in the cluster use opascpall or" >&2 + echo " opadownloadall." >&2 + exit 0 +} + +Usage() +{ + echo "Usage: opauploadall [-rp] [-f hostfile] source_file ... dest_file" >&2 + echo " or" >&2 + echo " opauploadall --help" >&2 + echo " --help - produce full help text" >&2 + echo " -p - perform copy in parallel on all hosts" >&2 + echo " -r - recursive upload of directories" >&2 + echo " -f hostfile - file with hosts in cluster, default is $CONFIG_DIR/opa/hosts" >&2 + echo " source_file - list of source files to copy" >&2 + echo " dest_file - destination for copy" >&2 + echo " If more than 1 source file, this must be a directory" >&2 + echo "example:">&2 + echo " opauploadall -p capture.tgz /etc/init.d/ipoib.cfg ." >&2 + echo " opauploadall capture.tgz /etc/init.d/ipoib.cfg pre-install" >&2 + echo "user@ syntax cannot be used in filenames specified" >&2 + echo "A local directory within uploads/ will be created for each hostname." >&2 + echo "Destination file will be uploads/hostname/dest_file within the local system." >&2 + echo "If copying multiple files, or dest_file has a trailing /, dest_file" >&2 + echo " directory will be created." >&2 + echo "To copy files from this host to hosts in the cluster use opascpall or" >&2 + echo " opadownloadall." >&2 + exit 2 +} + +if [ x"$1" = "x--help" ] +then + Usage_full +fi + +user=`id -u -n` +opts= +popt=n +while getopts f:d:h:u:rp param +do + case $param in + f) + HOSTS_FILE="$OPTARG";; + d) + UPLOADS_DIR="$OPTARG";; + h) + HOSTS="$OPTARG";; + u) + user="$OPTARG";; + r) + opts="$opts -r";; + p) + opts="$opts -q" + popt=y;; + ?) + Usage;; + esac +done +shift $((OPTIND -1)) +if [ $# -lt 2 ] +then + Usage +fi + +check_host_args opauploadall + +# remove last name from the list +files= +dest= +file_count=0 +for file in "$@" +do + if [ ! -z "$dest" ] + then + if [ ! -z "$files" ] + then + files="$files $dest" + else + files="$dest" + fi + file_count=`expr $file_count + 1` + fi + dest="$file" +done + +# Determine if we need to create a directory +create_dir=y +if [ $file_count -le 1 ] && [ "${dest: -1}" != "/" ] +then + create_dir=n + echo "$files" | grep -e "*" -e "\[" -e "?" >/dev/null + if [ "$?" -eq 0 ]; then + echo "opauploadall: Warning: possible wildcards in source_file. If multiple" >&2 + echo " files may match, dest_file should be a directory with trailing /" >&2 + fi +fi + +# Convert files to an array to iterate through while +# avoiding wildcard expansion +read -a files <<< $files + +running=0 +pids="" +stat=0 +for hostname in $HOSTS +do + src_files= + for file in "${files[@]}" + do + src_files="$src_files $user@[$hostname]:$file" + done + mkdir -p $UPLOADS_DIR/$hostname + if [ "$create_dir" == "y" ] + then + mkdir -p $UPLOADS_DIR/$hostname/$dest + fi + + if [ "$popt" = "y" ] + then + if [ $running -ge $FF_MAX_PARALLEL ] + then + for pid in $pids; do + wait $pid + if [ "$?" -ne 0 ]; then + stat=1 + fi + done + pids="" + running=0 + fi + echo "scp $opts $src_files $UPLOADS_DIR/$hostname/$dest" + scp $opts $src_files $UPLOADS_DIR/$hostname/$dest & + pid=$! + pids="$pids $pid" + running=$(( $running + 1)) + else + echo "scp $opts $src_files $UPLOADS_DIR/$hostname/$dest" + scp $opts $src_files $UPLOADS_DIR/$hostname/$dest + if [ "$?" -ne 0 ]; then + stat=1 + fi + fi +done +for pid in $pids; do + wait $pid + if [ "$?" -ne 0 ]; then + stat=1 + fi +done +exit $stat diff --git a/IbaTools/FastFabric/ports b/IbaTools/FastFabric/ports new file mode 100644 index 0000000..6d7d43d --- /dev/null +++ b/IbaTools/FastFabric/ports @@ -0,0 +1,10 @@ +# [ICS VERSION STRING: unknown] +# This file defines the local HFI ports to use to access the fabric(s) +# +# specify one line per HFI port of the form hfi:port such as: +# 0:0 = 1st active port in system +# 0:y = port y within system +# x:0 = 1st active port on HFI x +# x:y = HFI x, port y +# The first HFI in the system is 1. The first port on an HFI is 1. +0:0 diff --git a/IbaTools/FastFabric/reboot.exp b/IbaTools/FastFabric/reboot.exp new file mode 100644 index 0000000..53fc4b6 --- /dev/null +++ b/IbaTools/FastFabric/reboot.exp @@ -0,0 +1,115 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] + +source /usr/lib/opa/tools/ibtools.exp + +#=============================================================================# +# Test Suite Description: +#-----------------------------------------------------------------------------# +## reboot +## ------- +## reboot all hosts +#=============================================================================# + +# manditory setup +log_user 0; # disable detailed logging to stdout + +# uncomment the following to debug the test +#strace 20 +#log_user 1 +#exp_internal 1 +#cmd_trace on +#strace 4 + +set install_exit_code 0 + +proc suite_setup {} { + # example of conditional setup + #test_execute {load populate} { + #do some installation or configuration stuff + #} +} + +proc case_setup {} { +# setup to do at start of each test case +# Usage: +# pass as argument to start_suite +# Arguments: +# None +# This procedure will be run at the start of every test case +# It provides an opportunity for uniform cleanup/setup for each test case + +} + +proc case_cleanup { failed } { +# cleanup to do after each test case +# Usage: +# pass as argument to start_suite +# Arguments: +# failed - set to 1 if test case failed in which case additional +# information/files may be desired in test_tmp +# set to 0 if test case passed +# This procedure will be run at the end of every test case +# It provides an opportunity for uniform cleanup after each test case + global env + + test_execute {} { + if { $failed } { + global host + # could put cleanup here + } + } +} + +test_suite "reboot" "reboot" "reboot all hosts +File: /usr/lib/opa/tools/reboot.exp" suite_setup noop { + global host + + # Global Initializations for Test Suite: + # -------------------------------------- + + # ADD ANY GLOBAL INITIALIZATION HERE, SUCH AS: + # set env(MY_ENV_VAR) value + # also validate the environment + # if the environment is bad call fail_suite "information" abort_now + # abort_now should be 0 if it is safe to proceed and simply ignore all + # test_case calls. it should be 1 if that is not possible. + + # Procedures used to support Test Suite: + # -------------------------------------- + + # The actual test cases: + # ---------------------- + + parallel host $env(CFG_HOSTS) { + test_case_reboot $host + } +} diff --git a/IbaTools/FastFabric/restampFirmwares.sh b/IbaTools/FastFabric/restampFirmwares.sh new file mode 100755 index 0000000..8c1ec19 --- /dev/null +++ b/IbaTools/FastFabric/restampFirmwares.sh @@ -0,0 +1,85 @@ +#!/bin/bash +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +#[ICS VERSION STRING: unknown] +# script to restamp embedded firmware with different version numbers to aid +# run_tests scripts for firmware push + +#NEWVERSION=3_1_0_0_29S1 +NEWVERSION=cking2 + +#SOURCEDIR=~ftp/Integration/GA3_1_0_0/ALL_EMB/3_1_0_0_29/Infinicon +SOURCEDIR=cking/ + +# product codes +EIOU_PC=1 +FCIOU_PC=2 +CMU_PC=3 +IBX_PC=4 +I2K_PC=5 +I3K_PC=6 +I5K_PC=7 +I9K_PC=8 + +# bsp codes +SWAUX_BC=3 +PCIX_BC=7 +MC1125_BC=9 +T3_BC=10 + +STRIP=/usr/local/bin/mips64-vxworks-strip +DEFLATE=/usr/local/ics/bin/icsdeflate + + +mkdir $NEWVERSION +cd $NEWVERSION + +for i in CMU/CMU.sw_aux CMU/CMU.mc1125 EIOU/EIOU.pcix FCIOU/FCIOU.pcix IBX/IBX.sw_aux IBX/IBX.mc1125 I2K/I2K.mc1125 I3K/I3K.mc1125 I5K/I5K.t3 I9K/I9K.t3 +do + cp $SOURCEDIR/$i . +done + +for i in CMU.sw_aux CMU.mc1125 EIOU.pcix FCIOU.pcix IBX.sw_aux IBX.mc1125 I2K.mc1125 I3K.mc1125 I5K.t3 I9K.t3 +do + patch_version -n `format_releasetag $NEWVERSION` $NEWVERSION $i +done + +mkpkg CMU.sw_aux InfiniFabric sw_aux $CMU_PC $SWAUX_BC $STRIP $DEFLATE +mkpkg CMU.mc1125 InfiniFabric mc1125 $CMU_PC $MC1125_BC $STRIP $DEFLATE +mkpkg EIOU.pcix VEx pcix $EIOU_PC $PCIX_BC $STRIP $DEFLATE +mkpkg FCIOU.pcix VFx pcix $FCIOU_PC $PCIX_BC $STRIP $DEFLATE +mkpkg IBX.sw_aux IBx sw_aux $IBX_PC $SWAUX_BC $STRIP $DEFLATE +mkpkg IBX.mc1125 IBx mc1125 $IBX_PC $MC1125_BC $STRIP $DEFLATE +mkpkg I2K.mc1125 InfinIO2000 mc1125 $I2K_PC $MC1125_BC $STRIP $DEFLATE +mkpkg I3K.mc1125 InfinIO3000 mc1125 $I3K_PC $MC1125_BC $STRIP $DEFLATE +mkpkg I5K.t3 InfinIO5000 t3 $I5K_PC $T3_BC $STRIP $DEFLATE +mkpkg I9K.t3 InfinIO9000 t3 $I9K_PC $T3_BC $STRIP $DEFLATE + +rm -f CMU.* EIOU.* FCIOU.* IBX.* I[2359]K.* diff --git a/IbaTools/FastFabric/run_tests b/IbaTools/FastFabric/run_tests new file mode 100755 index 0000000..eef6dc7 --- /dev/null +++ b/IbaTools/FastFabric/run_tests @@ -0,0 +1,843 @@ +#!/bin/bash +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +#[ICS VERSION STRING: unknown] + +check_act() +{ + if [ x"$2" = xa ] + then + out=`opacmdall -C -H "$chassis" "fwVersion $slota"` + elif [ x"$2" = xb ] + then + out=`opacmdall -C -H "$chassis" "fwVersion $slotb"` + else + out=`opacmdall -C -H "$chassis" "fwVersion $slot"` + fi + fw=`echo "$out"|grep 'Firmware Version:'|sed -e 's/.*Firmware Version:[ ]*\([a-zA-Z0-9_.-]*\).*/\1/'` + if [ "$fw" != "$1" ] + then + echo "FAILED: unexpected running fw version: $fw, expected: $1, out=$out" >> test.log + else + echo "OK: act fw version: $fw, expected: $1" >> test.log + fi +} + +check_pri() +{ + if [ x"$2" = xa ] + then + out=`opacmdall -C -H "$chassis" "bootQuery $slota"` + elif [ x"$2" = xb ] + then + out=`opacmdall -C -H "$chassis" "bootQuery $slotb"` + else + out=`opacmdall -C -H "$chassis" "bootQuery $slot"` + fi + fw=`echo "$out"|grep 'version:'|sed -e 's/.*version:[ ]*\([a-zA-Z0-9_.-]*\).*/\1/'` + if [ "$fw" != "$1" ] + then + echo "FAILED: unexpected pri fw version: $fw, expected: $1, out=$out" >> test.log + else + echo "OK: pri fw version: $fw, expected: $1" >> test.log + fi +} + +check_alt() +{ + if [ x"$2" = xa ] + then + out=`opacmdall -C -H "$chassis" "bootQuery $slota -alternate"` + elif [ x"$2" = xb ] + then + out=`opacmdall -C -H "$chassis" "bootQuery $slotb -alternate"` + else + out=`opacmdall -C -H "$chassis" "bootQuery $slot -alternate"` + fi + fw=`echo "$out"|grep 'version:'|sed -e 's/.*version:[ ]*\([a-zA-Z0-9_.-]*\).*/\1/'` + if [ "$fw" != "$1" ] + then + echo "FAILED: unexpected alt fw version: $fw, expected: $1, out=$out" >> test.log + else + echo "OK: alt fw version: $fw, expected: $1" >> test.log + fi +} + +set_fw_ver() +{ +#cat > /sbin/opafirmware < /dev/null +} + +set_fw_ver1() +{ + set_fw_ver $fw1_ver "$card_type" + > /dev/null +} +set_fw_ver2() +{ + set_fw_ver $fw2_ver "$card_type" + > /dev/null +} + +set_fw_ver3() +{ + set_fw_ver $fw3_ver "$card_type" + > /dev/null +} +set_fw_verbad() +{ + set_fw_ver 3.1.0.0.29 "VEx" + > /dev/null +} + +set -x +rm -f test.log test.res +rm -rf test_tmp* +rm -rf save_tmp + + +test1() +{ + echo "/////////////////////////////////////////" >> test.log + echo "pre-test setup - run $fw1" >> test.log + set_fw_ver1 + opachassisadmin -H "$chassis" -P $fw1 -a run upgrade + echo "/////////////////////////////////////////" >> test.log + echo "pre-test setup - push $fw2 to alt" >> test.log + set_fw_ver2 + opachassisadmin -H "$chassis" -P $fw2 -a push upgrade + + + echo "/////////////////////////////////////////" >> test.log + echo "firmware already on card and primary/active" >> test.log + + echo "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%" >> test.log + echo "already on chassis, don't select, no push ">> test.log + echo "now running $fw1 pri, $fw2 alt" >> test.log + check_act $fw1_ver + check_pri $fw1_ver + check_alt $fw2_ver + set_fw_ver1 + opachassisadmin -H "$chassis" -P $fw1 upgrade + + echo "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%" >> test.log + echo "already on chassis, don't select, no push ">> test.log + echo "now running $fw1 pri, $fw2 alt" >> test.log + check_act $fw1_ver + check_pri $fw1_ver + check_alt $fw2_ver + set_fw_ver1 + opachassisadmin -H "$chassis" -P $fw1 -a push upgrade + + echo "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%" >> test.log + echo "already on chassis, no need to select" >> test.log + echo "now running $fw1 pri, $fw2 alt" >> test.log + check_act $fw1_ver + check_pri $fw1_ver + check_alt $fw2_ver + set_fw_ver1 + opachassisadmin -H "$chassis" -P $fw1 -a select upgrade + + echo "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%" >> test.log + echo "already on chassis, no need to reboot" >> test.log + echo "now running $fw1 pri, $fw2 alt" >> test.log + set_fw_ver1 + check_act $fw1_ver + check_pri $fw1_ver + check_alt $fw2_ver + opachassisadmin -H "$chassis" -P $fw1 -a run upgrade + check_act $fw1_ver + check_pri $fw1_ver + check_alt $fw2_ver +} + + +test2() +{ + echo "/////////////////////////////////////////" >> test.log + echo "pre-test setup - run $fw2" >> test.log + set_fw_ver2 + opachassisadmin -H "$chassis" -P $fw2 -a run upgrade + echo "/////////////////////////////////////////" >> test.log + echo "pre-test setup - push $fw1 to alt" >> test.log + set_fw_ver1 + opachassisadmin -H "$chassis" -P $fw1 -a push upgrade + + + echo "/////////////////////////////////////////" >> test.log + echo "firmware already on card and alternate/ not active" >> test.log + + echo "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%" >> test.log + echo "already on chassis, no need to push" >> test.log + echo "now running $fw2 pri, $fw1 alt" >> test.log + check_act $fw2_ver + check_pri $fw2_ver + check_alt $fw1_ver + set_fw_ver1 + opachassisadmin -H "$chassis" -P $fw1 upgrade + + echo "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%" >> test.log + echo "already on chassis, no need to push" >> test.log + echo "now running $fw2 pri, $fw1 alt" >> test.log + check_act $fw2_ver + check_pri $fw2_ver + check_alt $fw1_ver + set_fw_ver1 + opachassisadmin -H "$chassis" -P $fw1 -a push upgrade + + echo "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%" >> test.log + echo "already on chassis, but need to select and reboot" >> test.log + echo "now running $fw2 pri, $fw1 alt" >> test.log + check_act $fw2_ver + check_pri $fw2_ver + check_alt $fw1_ver + set_fw_ver1 + opachassisadmin -H "$chassis" -P $fw1 -a run upgrade + + echo "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%" >> test.log + echo "already on chassis, but need to select" >> test.log + echo "now running $fw1 pri, $fw2 alt" >> test.log + check_act $fw1_ver + check_pri $fw1_ver + check_alt $fw2_ver + set_fw_ver2 + opachassisadmin -H "$chassis" -P $fw2 -a select upgrade + check_act $fw1_ver + check_pri $fw2_ver + check_alt $fw1_ver +} + +test3() +{ + echo "/////////////////////////////////////////" >> test.log + echo "pre-test setup - run $fw1" >> test.log + set_fw_ver1 + opachassisadmin -H "$chassis" -P $fw1 -a run upgrade + echo "/////////////////////////////////////////" >> test.log + echo "pre-test setup - push $fw2 and select" >> test.log + set_fw_ver2 + opachassisadmin -H "$chassis" -P $fw2 -a select upgrade + + echo "/////////////////////////////////////////" >> test.log + echo "firmware already on card and alternate but active" >> test.log + echo "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%" >> test.log + echo "already on chassis, no need to push" >> test.log + echo "now running $fw1 alt, $fw2 pri" >> test.log + check_act $fw1_ver + check_pri $fw2_ver + check_alt $fw1_ver + set_fw_ver1 + opachassisadmin -H "$chassis" -P $fw1 -a push upgrade + echo "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%" >> test.log + echo "already on chassis, no need to push" >> test.log + echo "now running $fw1 alt, $fw2 pri" >> test.log + check_act $fw1_ver + check_pri $fw2_ver + check_alt $fw1_ver + set_fw_ver1 + opachassisadmin -H "$chassis" -P $fw1 upgrade + echo "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%" >> test.log + echo "already on chassis, but need to select" >> test.log + echo "now running $fw1 alt, $fw2 pri" >> test.log + check_act $fw1_ver + check_pri $fw2_ver + check_alt $fw1_ver + set_fw_ver1 + opachassisadmin -H "$chassis" -P $fw1 -a select upgrade + echo "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%" >> test.log + echo "already on chassis, but need to select" >> test.log + echo "now running $fw1 pri, $fw2 alt" >> test.log + check_act $fw1_ver + check_pri $fw1_ver + check_alt $fw2_ver + set_fw_ver2 + opachassisadmin -H "$chassis" -P $fw2 -a select upgrade + echo "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%" >> test.log + echo "already on chassis, but need to select and reboot" >> test.log + echo "now running $fw1 alt, $fw2 pri" >> test.log + check_act $fw1_ver + check_pri $fw2_ver + check_alt $fw1_ver + set_fw_ver2 + opachassisadmin -H "$chassis" -P $fw2 -a run upgrade + echo "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%" >> test.log + echo "already on chassis, but need to select and reboot" >> test.log + echo "now running $fw1 alt, $fw2 pri" >> test.log + check_act $fw2_ver + check_pri $fw2_ver + check_alt $fw1_ver + set_fw_ver1 + opachassisadmin -H "$chassis" -P $fw1 -a run upgrade + check_act $fw1_ver + check_pri $fw1_ver + check_alt $fw2_ver +} + +test4() +{ + echo "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%" >> test.log + echo "Wrong card type" >> test.log + echo "now running $fw1 pri, $fw2 alt" >> test.log + check_act $fw1_ver + check_pri $fw1_ver + check_alt $fw2_ver + set_fw_verbad + opachassisadmin -H "$chassis" -P $badfw -a run upgrade + check_act $fw1_ver + check_pri $fw1_ver + check_alt $fw2_ver +} + +test5() +{ + echo "/////////////////////////////////////////" >> test.log + echo "pre-test setup - run $fw1" >> test.log + set_fw_ver1 + opachassisadmin -H "$chassis" -P $fw1 -a run upgrade + echo "/////////////////////////////////////////" >> test.log + echo "pre-test setup - push $fw2" >> test.log + set_fw_ver2 + opachassisadmin -H "$chassis" -P $fw2 -a push upgrade + + echo "/////////////////////////////////////////" >> test.log + echo "firmware not on card" >> test.log + echo "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%" >> test.log + echo "need to push" >> test.log + echo "now running $fw1 pri, $fw2 alt" >> test.log + check_act $fw1_ver + check_pri $fw1_ver + check_alt $fw2_ver + set_fw_ver3 + opachassisadmin -H "$chassis" -P $fw3 -a push upgrade + echo "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%" >> test.log + echo "need to push" >> test.log + echo "now running $fw1 pri, $fw3 alt" >> test.log + check_act $fw1_ver + check_pri $fw1_ver + check_alt $fw3_ver + set_fw_ver2 + opachassisadmin -H "$chassis" -P $fw2 upgrade + echo "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%" >> test.log + echo "need to push and select" >> test.log + echo "now running $fw1 pri, $fw2 alt" >> test.log + check_act $fw1_ver + check_pri $fw1_ver + check_alt $fw2_ver + set_fw_ver3 + opachassisadmin -H "$chassis" -P $fw3 -a select upgrade + echo "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%" >> test.log + echo "need to push and select" >> test.log + echo "now running $fw1 alt, $fw3 pri" >> test.log + check_act $fw1_ver + check_pri $fw3_ver + check_alt $fw1_ver + set_fw_ver2 + opachassisadmin -H "$chassis" -P $fw2 -a select upgrade + echo "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%" >> test.log + echo "need to push" >> test.log + echo "now running $fw1 alt, $fw2 pri" >> test.log + check_act $fw1_ver + check_pri $fw2_ver + check_alt $fw1_ver + set_fw_ver3 + opachassisadmin -H "$chassis" -P $fw3 -a push upgrade + echo "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%" >> test.log + echo "need to push and activate" >> test.log + echo "now running $fw1 pri, $fw3 alt" >> test.log # TBD what to expect + check_act $fw1_ver + check_pri $fw3_ver + check_alt $fw1_ver + set_fw_ver2 + opachassisadmin -H "$chassis" -P $fw2 -a run upgrade + check_act $fw2_ver + check_pri $fw2_ver + check_alt $fw1_ver +} + +test1m() +{ + echo "/////////////////////////////////////////" >> test.log + echo "pre-test setup - run $fw1 in $slota" >> test.log + set_fw_ver1 + opachassisadmin -H "$chassis:$slota" -P $fw1 -a run upgrade + echo "pre-test setup - run $fw2 in $slotb" >> test.log + set_fw_ver2 + opachassisadmin -H "$chassis:$slotb" -P $fw2 -a run upgrade + echo "/////////////////////////////////////////" >> test.log + echo "pre-test setup - push $fw2 to alt in $slota" >> test.log + set_fw_ver2 + opachassisadmin -H "$chassis:$slota" -P $fw2 -a push upgrade + echo "pre-test setup - push $fw1 to alt in $slotb" >> test.log + set_fw_ver1 + opachassisadmin -H "$chassis:$slotb" -P $fw1 -a push upgrade + + + echo "/////////////////////////////////////////" >> test.log + echo "firmware already on card and primary/active" >> test.log + + echo "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%" >> test.log + echo "already on chassis, don't select, no push ">> test.log + echo "now $slota running $fw1 pri, $fw2 alt" >> test.log + check_act $fw1_ver a + check_pri $fw1_ver a + check_alt $fw2_ver a + echo "now $slotb running $fw2 pri, $fw1 alt" >> test.log + check_act $fw2_ver b + check_pri $fw2_ver b + check_alt $fw1_ver b + set_fw_ver1 + opachassisadmin -H "$chassis" -P $fw1 upgrade + + echo "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%" >> test.log + echo "already on chassis, don't select, no push ">> test.log + echo "now $slota running $fw1 pri, $fw2 alt" >> test.log + check_act $fw1_ver a + check_pri $fw1_ver a + check_alt $fw2_ver a + echo "now $slotb running $fw2 pri, $fw1 alt" >> test.log + check_act $fw2_ver b + check_pri $fw2_ver b + check_alt $fw1_ver b + set_fw_ver1 + opachassisadmin -H "$chassis" -P $fw1 -a push upgrade + + echo "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%" >> test.log + echo "already on chassis, no need to select (on $slota, select $slotb)" >> test.log + echo "now $slota running $fw1 pri, $fw2 alt" >> test.log + check_act $fw1_ver a + check_pri $fw1_ver a + check_alt $fw2_ver a + echo "now $slotb running $fw2 pri, $fw1 alt" >> test.log + check_act $fw2_ver b + check_pri $fw2_ver b + check_alt $fw1_ver b + set_fw_ver1 + opachassisadmin -H "$chassis" -P $fw1 -a select upgrade + + echo "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%" >> test.log + echo "already on chassis, no need to reboot $slota, reboot $slotb" >> test.log + echo "now $slota running $fw1 pri, $fw2 alt" >> test.log + check_act $fw1_ver a + check_pri $fw1_ver a + check_alt $fw2_ver a + echo "now $slotb running $fw2 alt, $fw1 pri" >> test.log + check_act $fw2_ver b + check_pri $fw1_ver b + check_alt $fw2_ver b + set_fw_ver1 + opachassisadmin -H "$chassis" -P $fw1 -a run upgrade + check_act $fw1_ver a + check_pri $fw1_ver a + check_alt $fw2_ver a + check_act $fw1_ver b + check_pri $fw1_ver b + check_alt $fw2_ver b +} + + +test2m() +{ + echo "/////////////////////////////////////////" >> test.log + echo "pre-test setup - run $fw2 in $slota" >> test.log + set_fw_ver2 + opachassisadmin -H "$chassis:$slota" -P $fw2 -a run upgrade + echo "pre-test setup - run $fw1 in $slotb" >> test.log + set_fw_ver1 + opachassisadmin -H "$chassis:$slotb" -P $fw1 -a run upgrade + echo "/////////////////////////////////////////" >> test.log + echo "pre-test setup - push $fw1 to alt in $slota" >> test.log + set_fw_ver1 + opachassisadmin -H "$chassis:$slota" -P $fw1 -a push upgrade + echo "pre-test setup - push $fw2 to alt in $slotb" >> test.log + set_fw_ver2 + opachassisadmin -H "$chassis:$slotb" -P $fw2 -a push upgrade + + + echo "/////////////////////////////////////////" >> test.log + echo "firmware already on card and alternate/ not active" >> test.log + + echo "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%" >> test.log + echo "already on chassis, no need to push" >> test.log + echo "now $slota running $fw2 pri, $fw1 alt" >> test.log + check_act $fw2_ver a + check_pri $fw2_ver a + check_alt $fw1_ver a + echo "now $slotb running $fw1 pri, $fw2 alt" >> test.log + check_act $fw1_ver b + check_pri $fw1_ver b + check_alt $fw2_ver b + set_fw_ver1 + opachassisadmin -H "$chassis" -P $fw1 upgrade + + echo "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%" >> test.log + echo "already on chassis, no need to push" >> test.log + echo "now $slota running $fw2 pri, $fw1 alt" >> test.log + check_act $fw2_ver a + check_pri $fw2_ver a + check_alt $fw1_ver a + echo "now $slotb running $fw1 pri, $fw2 alt" >> test.log + check_act $fw1_ver b + check_pri $fw1_ver b + check_alt $fw2_ver b + set_fw_ver1 + opachassisadmin -H "$chassis" -P $fw1 -a push upgrade + + echo "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%" >> test.log + echo "already on chassis, but need to select and reboot ($slota only)" >> test.log + echo "now $slota running $fw2 pri, $fw1 alt" >> test.log + check_act $fw2_ver a + check_pri $fw2_ver a + check_alt $fw1_ver a + echo "now $slotb running $fw1 pri, $fw2 alt" >> test.log + check_act $fw1_ver b + check_pri $fw1_ver b + check_alt $fw2_ver b + set_fw_ver1 + opachassisadmin -H "$chassis" -P $fw1 -a run upgrade + + echo "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%" >> test.log + echo "already on chassis, but need to select" >> test.log + echo "now $slota/$slotb running $fw1 pri, $fw2 alt" >> test.log + check_act $fw1_ver a + check_pri $fw1_ver a + check_alt $fw2_ver a + check_act $fw1_ver b + check_pri $fw1_ver b + check_alt $fw2_ver b + set_fw_ver2 + opachassisadmin -H "$chassis" -P $fw2 -a select upgrade + check_act $fw1_ver a + check_pri $fw2_ver a + check_alt $fw1_ver a + check_act $fw1_ver b + check_pri $fw2_ver b + check_alt $fw1_ver b +} + +test3m() +{ + echo "/////////////////////////////////////////" >> test.log + echo "pre-test setup - run $fw1 in $slota" >> test.log + set_fw_ver1 + opachassisadmin -H "$chassis:$slota" -P $fw1 -a run upgrade + echo "pre-test setup - run $fw2 in $slotb" >> test.log + set_fw_ver2 + opachassisadmin -H "$chassis:$slotb" -P $fw2 -a run upgrade + echo "/////////////////////////////////////////" >> test.log + echo "pre-test setup - push $fw2 in $slota and select" >> test.log + set_fw_ver2 + opachassisadmin -H "$chassis:$slota" -P $fw2 -a select upgrade + echo "pre-test setup - push $fw1 in $slota and select" >> test.log + set_fw_ver1 + opachassisadmin -H "$chassis:$slotb" -P $fw1 -a select upgrade + + echo "/////////////////////////////////////////" >> test.log + echo "firmware already on card and alternate but active" >> test.log + echo "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%" >> test.log + echo "already on chassis, no need to push" >> test.log + echo "now $slota running $fw1 alt, $fw2 pri" >> test.log + check_act $fw1_ver a + check_pri $fw2_ver a + check_alt $fw1_ver a + echo "now $slotb running $fw2 alt, $fw1 pri" >> test.log + check_act $fw2_ver b + check_pri $fw1_ver b + check_alt $fw2_ver b + set_fw_ver1 + opachassisadmin -H "$chassis" -P $fw1 -a push upgrade + echo "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%" >> test.log + echo "already on chassis, no need to push" >> test.log + echo "now $slota running $fw1 alt, $fw2 pri" >> test.log + check_act $fw1_ver a + check_pri $fw2_ver a + check_alt $fw1_ver a + echo "now $slotb running $fw2 alt, $fw1 pri" >> test.log + check_act $fw2_ver b + check_pri $fw1_ver b + check_alt $fw2_ver b + set_fw_ver1 + opachassisadmin -H "$chassis" -P $fw1 upgrade + echo "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%" >> test.log + echo "already on chassis, but need to select" >> test.log + echo "now $slota running $fw1 alt, $fw2 pri" >> test.log + check_act $fw1_ver a + check_pri $fw2_ver a + check_alt $fw1_ver a + echo "now $slotb running $fw2 alt, $fw1 pri" >> test.log + check_act $fw2_ver b + check_pri $fw1_ver b + check_alt $fw2_ver b + set_fw_ver1 + opachassisadmin -H "$chassis" -P $fw1 -a select upgrade + echo "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%" >> test.log + echo "already on chassis, but need to select" >> test.log + echo "now $slota running $fw1 pri, $fw2 alt" >> test.log + check_act $fw1_ver a + check_pri $fw1_ver a + check_alt $fw2_ver a + echo "now $slotb running $fw2 alt, $fw2 pri" >> test.log + check_act $fw2_ver b + check_pri $fw1_ver b + check_alt $fw2_ver b + set_fw_ver2 + opachassisadmin -H "$chassis" -P $fw2 -a select upgrade + echo "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%" >> test.log + echo "already on chassis, but need to select and reboot" >> test.log + echo "now $slota running $fw1 alt, $fw2 pri" >> test.log + check_act $fw1_ver a + check_pri $fw2_ver a + check_alt $fw1_ver a + echo "now $slotb running $fw2 pri, $fw2 alt" >> test.log + check_act $fw2_ver b + check_pri $fw2_ver b + check_alt $fw1_ver b + set_fw_ver2 + opachassisadmin -H "$chassis" -P $fw2 -a run upgrade + echo "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%" >> test.log + echo "already on chassis, but need to select and reboot" >> test.log + echo "now $slota/$slotb running $fw1 alt, $fw2 pri" >> test.log + check_act $fw2_ver a + check_pri $fw2_ver a + check_alt $fw1_ver a + check_act $fw2_ver b + check_pri $fw2_ver b + check_alt $fw1_ver b + set_fw_ver1 + opachassisadmin -H "$chassis" -P $fw1 -a run upgrade + check_act $fw1_ver a + check_pri $fw1_ver a + check_alt $fw2_ver a + check_act $fw1_ver b + check_pri $fw1_ver b + check_alt $fw2_ver b +} + +test4m() +{ + echo "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%" >> test.log + echo "Wrong card type" >> test.log + echo "now running $fw1 pri, $fw2 alt" >> test.log + check_act $fw1_ver a + check_pri $fw1_ver a + check_alt $fw2_ver a + check_act $fw1_ver b + check_pri $fw1_ver b + check_alt $fw2_ver b + set_fw_verbad + opachassisadmin -H "$chassis" -P $badfw -a run upgrade + check_act $fw1_ver a + check_pri $fw1_ver a + check_alt $fw2_ver a + check_act $fw1_ver b + check_pri $fw1_ver b + check_alt $fw2_ver b +} + +test5m() +{ + echo "/////////////////////////////////////////" >> test.log + echo "pre-test setup - run $fw1 on $slota" >> test.log + set_fw_ver1 + opachassisadmin -H "$chassis:$slota" -P $fw1 -a run upgrade + echo "pre-test setup - run $fw2 on $slotb" >> test.log + set_fw_ver2 + opachassisadmin -H "$chassis:$slotb" -P $fw2 -a run upgrade + echo "/////////////////////////////////////////" >> test.log + echo "pre-test setup - push $fw2 on $slota" >> test.log + set_fw_ver2 + opachassisadmin -H "$chassis:$slota" -P $fw2 -a push upgrade + echo "pre-test setup - push $fw1 on $slotb" >> test.log + set_fw_ver1 + opachassisadmin -H "$chassis:$slotb" -P $fw1 -a push upgrade + + echo "/////////////////////////////////////////" >> test.log + echo "firmware not on card" >> test.log + echo "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%" >> test.log + echo "need to push" >> test.log + echo "now $slota running $fw1 pri, $fw2 alt" >> test.log + check_act $fw1_ver a + check_pri $fw1_ver a + check_alt $fw2_ver a + echo "now $slotb running $fw2 pri, $fw1 alt" >> test.log + check_act $fw2_ver b + check_pri $fw2_ver b + check_alt $fw1_ver b + set_fw_ver3 + opachassisadmin -H "$chassis" -P $fw3 -a push upgrade + echo "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%" >> test.log + echo "need to push" >> test.log + echo "now $slota running $fw1 pri, $fw3 alt" >> test.log + check_act $fw1_ver a + check_pri $fw1_ver a + check_alt $fw3_ver a + echo "now $slotb running $fw2 pri, $fw3 alt" >> test.log + check_act $fw2_ver b + check_pri $fw2_ver b + check_alt $fw3_ver b + set_fw_ver2 + opachassisadmin -H "$chassis" -P $fw2 upgrade + echo "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%" >> test.log + echo "need to push and select" >> test.log + echo "now $slota running $fw1 pri, $fw2 alt" >> test.log + check_act $fw1_ver a + check_pri $fw1_ver a + check_alt $fw2_ver a + echo "now $slota running $fw2 pri, $fw1 alt" >> test.log + check_act $fw2_ver b + check_pri $fw2_ver b + check_alt $fw3_ver b + set_fw_ver3 + opachassisadmin -H "$chassis" -P $fw3 -a select upgrade + echo "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%" >> test.log + echo "need to push and select" >> test.log + echo "now $slota running $fw1 alt, $fw3 pri" >> test.log + check_act $fw1_ver a + check_pri $fw3_ver a + check_alt $fw1_ver a + echo "now $slotb running $fw2 alt, $fw3 pri" >> test.log + check_act $fw2_ver b + check_pri $fw3_ver b + check_alt $fw2_ver b + set_fw_ver2 + opachassisadmin -H "$chassis" -P $fw2 -a select upgrade + echo "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%" >> test.log + echo "need to push" >> test.log + echo "now $slota running $fw1 alt, $fw2 pri" >> test.log + check_act $fw1_ver a + check_pri $fw2_ver a + check_alt $fw1_ver a + echo "now $slotb running $fw2 pri, $fw1 alt" >> test.log + check_act $fw2_ver b + check_pri $fw2_ver b + check_alt $fw3_ver b + set_fw_ver3 + opachassisadmin -H "$chassis" -P $fw3 -a push upgrade + echo "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%" >> test.log + echo "need to push and activate" >> test.log + echo "now $slota running $fw1 pri, $fw3 alt" >> test.log # TBD what to expect + check_act $fw1_ver a + check_pri $fw3_ver a + check_alt $fw1_ver a + echo "now $slotb running $fw2 pri, $fw3 alt" >> test.log # TBD what to expect + check_act $fw2_ver b + check_pri $fw2_ver b + check_alt $fw3_ver b + set_fw_ver2 + opachassisadmin -H "$chassis" -P $fw2 -a run upgrade + check_act $fw2_ver a + check_pri $fw2_ver a + check_alt $fw1_ver a + check_act $fw2_ver b + check_pri $fw2_ver b + check_alt $fw3_ver b +} + +# this makes log a little easier to read, we only do 1 chassis per test anyway +export FF_MAX_PARALLEL=0 + +# these tests can be used for single slot chassis (9024, I2K, I3K) +# or to test 1 card type in a multi-slot chassis + +# Single slot chassis tests +#======================================================== +#firmware files to push, 3 similar versions with different numbers +fw1=embfw/3_1_1_0_10S1/InfinIO9000.t3.pkg +fw2=embfw/3_1_1_0_10S2/InfinIO9000.t3.pkg +fw3=embfw/3_1_1_0_10S3/InfinIO9000.t3.pkg +fw1_ver=3.1.1.0.10S1 +fw2_ver=3.1.1.0.10S2 +fw3_ver=3.1.1.0.10S3 +badfw=embfw/3_1_0_0_29/VEx.pcix.pkg + + +# simple switch +chassis=i9k112 +card_type="InfinIO9000.t3" +slot=0 +test1 +test2 +test3 +test4 +test5 + +# simple switch, specific slot +chassis="i9k112:101" +card_type="InfinIO9000.t3" +slot=0 +test1 +test2 +test3 +test4 +test5 + +# simple switch, management slot +chassis="i9k112:0" +card_type="InfinIO9000.t3" +slot=0 +test1 +test2 +test3 +test4 +test5 + +# multi-slot chassis tests +#======================================================== + +#firmware files to push, 3 similar versions with different numbers +fw1=embfw/3_1_1_0_10S1/VEx.pcix.pkg +fw2=embfw/3_1_1_0_10S2/VEx.pcix.pkg +fw3=embfw/3_1_1_0_10S3/VEx.pcix.pkg +fw1_ver=3.1.1.0.10S1 +fw2_ver=3.1.1.0.10S2 +fw3_ver=3.1.1.0.10S3 +badfw=embfw/3_1_0_0_29/InfinIO2000.mc1125.pkg + +# pick 2 slots which have the same card type +# VEx cards in hobbiton +chassis=hobbiton +slota=1 +slotb=3 +card_type="VEx.pcix" + +# these tests are strictly for multi-slot chassis and test mixed +# firmware versions prior to operation +test1m +test2m +test3m +test4m +test5m diff --git a/IbaTools/FastFabric/sacache.exp b/IbaTools/FastFabric/sacache.exp new file mode 100644 index 0000000..b9c188d --- /dev/null +++ b/IbaTools/FastFabric/sacache.exp @@ -0,0 +1,116 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] + +source /usr/lib/opa/tools/ibtools.exp +source "/usr/lib/opa/tools/ff_function.exp" + +#=============================================================================# +# Test Suite Description: +#-----------------------------------------------------------------------------# +## sacache +## ------- +## confirm all hosts have full list of hosts in their sacache +#=============================================================================# + +# manditory setup +log_user 0; # disable detailed logging to stdout + +# uncomment the following to debug the test +#strace 20 +#log_user 1 +#exp_internal 1 +#cmd_trace on +#strace 4 + +proc suite_setup {} { + # example of conditional setup + #test_execute {load populate} { + #do some installation or configuration stuff + #} +} + +proc case_setup {} { +# setup to do at start of each test case +# Usage: +# pass as argument to start_suite +# Arguments: +# None +# This procedure will be run at the start of every test case +# It provides an opportunity for uniform cleanup/setup for each test case + +} + +proc case_cleanup { failed } { +# cleanup to do after each test case +# Usage: +# pass as argument to start_suite +# Arguments: +# failed - set to 1 if test case failed in which case additional +# information/files may be desired in test_tmp +# set to 0 if test case passed +# This procedure will be run at the end of every test case +# It provides an opportunity for uniform cleanup after each test case + global env + + test_execute {} { + if { $failed || [ test_save_temp ] } { + # save any logs/results from system(s) under test + } + } +} + +test_suite "sacache" "sacache" "confirm sacache has paths to all hosts +File: /usr/lib/opa/tools/sacache.exp" suite_setup noop { + + # Global Initializations for Test Suite: + # -------------------------------------- + + # ADD ANY GLOBAL INITIALIZATION HERE, SUCH AS: + # set env(MY_ENV_VAR) value + # also validate the environment + # if the environment is bad call fail_suite "information" abort_now + # abort_now should be 0 if it is safe to proceed and simply ignore all + # test_case calls. it should be 1 if that is not possible. + + # Procedures used to support Test Suite: + # -------------------------------------- + + # The actual test cases: + # ---------------------- + set hosts {} + foreach host $env(CFG_HOSTS) { + lappend hosts [ff_host_basename $host] + } + + parallel host $env(CFG_HOSTS) { + test_case_discovered_hosts $host $hosts + } +} diff --git a/IbaTools/FastFabric/show_counts.sh b/IbaTools/FastFabric/show_counts.sh new file mode 100755 index 0000000..ea4c61c --- /dev/null +++ b/IbaTools/FastFabric/show_counts.sh @@ -0,0 +1,65 @@ +#!/bin/bash + +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] + +# given an input file on stdin, sort it and output a count before each line +# duplicate lines are output only once with a count > 1 +# unique lines are output with a count of 1 + +# useful to summarize output from commands such as getconfig for 12200 switches + +sort|( +last="" +count=0 +while read line +do + if [ $count != 0 ] + then + if [ x"$line" = x"$last" ] + then + count=$(($count + 1)) + else + printf "%5d - %s\\n" "$count" "$last" + last="$line" + count=1 + fi + else + last="$line" + count=1 + fi +done +if [ $count != 0 ] +then + printf "%5d - %s\\n" "$count" "$last" +fi +) +exit 0 diff --git a/IbaTools/FastFabric/switch_capture.exp b/IbaTools/FastFabric/switch_capture.exp new file mode 100644 index 0000000..4e7054d --- /dev/null +++ b/IbaTools/FastFabric/switch_capture.exp @@ -0,0 +1,114 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] + +#=============================================================================# +# Test Suite Description: +#-----------------------------------------------------------------------------# +## switch info +## ------- +## report switch info of all unmanaged switch nodes +#=============================================================================# + +# manditory setup +log_user 0; # disable detailed logging to stdout + +# uncomment the following to debug the test +#strace 20 +#log_user 1 +#exp_internal 1 +#cmd_trace on +#strace 4 + +set install_exit_code 0 + +proc suite_setup {} { + # example of conditional setup + #test_execute {load populate} { + #do some installation or configuration stuff + #} +} + +proc case_setup {} { +# setup to do at start of each test case +# Usage: +# pass as argument to start_suite +# Arguments: +# None +# This procedure will be run at the start of every test case +# It provides an opportunity for uniform cleanup/setup for each test case + +} + +proc case_cleanup { failed } { +# cleanup to do after each test case +# Usage: +# pass as argument to start_suite +# Arguments: +# failed - set to 1 if test case failed in which case additional +# information/files may be desired in test_tmp +# set to 0 if test case passed +# This procedure will be run at the end of every test case +# It provides an opportunity for uniform cleanup after each test case + global env + + test_execute {} { + if { $failed } { + global opaswitch + # could put cleanup here + } + } +} + +test_suite "switchcapture" "capture switch state" "capture switch firmware and hardware state of all externally managed switch nodes +File: /usr/lib/opa/tools/switch_capture.exp" suite_setup noop { + global opaswitch + + # Global Initializations for Test Suite: + # -------------------------------------- + + # ADD ANY GLOBAL INITIALIZATION HERE, SUCH AS: + # set env(MY_ENV_VAR) value + # also validate the environment + # if the environment is bad call fail_suite "information" abort_now + # abort_now should be 0 if it is safe to proceed and simply ignore all + # test_case calls. it should be 1 if that is not possible. + + # Procedures used to support Test Suite: + # -------------------------------------- + + # The actual test cases: + # ---------------------- + + parallel opaswitch $env(CFG_OPASWITCHES) { + set opaswitch [ trim_opaswitch_distance "$opaswitch"] + test_case_i2c_extmgd_switchcapture "$opaswitch" "$env(UPLOADS_DIR)/$opaswitch/$env(CFG_CAPTUREFILE)" + } +} diff --git a/IbaTools/FastFabric/switch_configure.exp b/IbaTools/FastFabric/switch_configure.exp new file mode 100644 index 0000000..3516482 --- /dev/null +++ b/IbaTools/FastFabric/switch_configure.exp @@ -0,0 +1,176 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] + +#=============================================================================# +# Test Suite Description: +#-----------------------------------------------------------------------------# +## configure +## ------- +## configure all switches +#=============================================================================# + +# manditory setup +log_user 0; # disable detailed logging to stdout + +# uncomment the following to debug the test +#strace 20 +#log_user 1 +#exp_internal 1 +#cmd_trace on +#strace 4 + +set install_exit_code 0 + +proc suite_setup {} { + # example of conditional setup + #test_execute {load populate} { + #do some installation or configuration stuff + #} +} + +proc case_setup {} { +# setup to do at start of each test case +# Usage: +# pass as argument to start_suite +# Arguments: +# None +# This procedure will be run at the start of every test case +# It provides an opportunity for uniform cleanup/setup for each test case + +} + +proc case_cleanup { failed } { +# cleanup to do after each test case +# Usage: +# pass as argument to start_suite +# Arguments: +# failed - set to 1 if test case failed in which case additional +# information/files may be desired in test_tmp +# set to 0 if test case passed +# This procedure will be run at the end of every test case +# It provides an opportunity for uniform cleanup after each test case + global env + + test_execute {} { + if { $failed } { + global opaswitch + # could put cleanup here + } + } +} + +array set sw_config_linkwidths { +1 1X +2 2X +3 1X/2X +4 3X +5 1X/3X +6 2X/3X +7 1X/2X/3X +8 4X +9 1X/4X +10 2X/4X +11 1X/2X/4X +12 3X/4X +13 1X/3X/4X +14 2X/3X/4X +15 1x/2X/3X/4X +0 "no change" +} + +array set sw_config_nodedesc { +0 "not being set" +1 "being set as per opaswitches file" +} + +array set sw_config_fmenabled { +0 "disabled" +1 "enabled" +-1 "no change" +} + +array set sw_config_linkcrcmode { +0 "16b" +1 "14b/16b" +2 "48b/16b" +3 "48b/14b/16b" +4 "per lane/16b" +5 "per lane/14b/16b" +6 "per lane/48b/16b" +7 "per lane/48b/14b/16b" +-1 "no change" +} + +proc sw_get_array_entry { arrayname key } { + +variable $arrayname + +upvar #0 $arrayname myarray + +if {![info exists myarray($key)]} { + return "Invalid Input: $key" +} else { + return $myarray($key) +} + +} + +test_suite "configure" "configure" "configure all switches: +LINKWIDTH: [sw_get_array_entry sw_config_linkwidths $env(LINKWIDTH_SETTING)] +NODEDESC: [sw_get_array_entry sw_config_nodedesc $env(NODEDESC_SETTING)] +FMENABLED: [sw_get_array_entry sw_config_fmenabled $env(FMENABLED_SETTING)] +LINKCRCMODE: [sw_get_array_entry sw_config_linkcrcmode $env(LINKCRCMODE_SETTING)] + +File: /usr/lib/opa/tools/switch_configure.exp" suite_setup noop { + global opaswitch + + # Global Initializations for Test Suite: + # -------------------------------------- + + # ADD ANY GLOBAL INITIALIZATION HERE, SUCH AS: + # set env(MY_ENV_VAR) value + # also validate the environment + # if the environment is bad call fail_suite "information" abort_now + # abort_now should be 0 if it is safe to proceed and simply ignore all + # test_case calls. it should be 1 if that is not possible. + + # Procedures used to support Test Suite: + # -------------------------------------- + + # The actual test cases: + # ---------------------- + + parallel opaswitch $env(CFG_OPASWITCHES) { + set opaswitch [ trim_opaswitch_distance "$opaswitch"] + local_sh + test_case_ext_mgmt_sw_config $opaswitch + } +} diff --git a/IbaTools/FastFabric/switch_dump.exp b/IbaTools/FastFabric/switch_dump.exp new file mode 100644 index 0000000..dae0e5b --- /dev/null +++ b/IbaTools/FastFabric/switch_dump.exp @@ -0,0 +1,114 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] + +#=============================================================================# +# Test Suite Description: +#-----------------------------------------------------------------------------# +## dump +## ------- +## dump firmware of all unmanaged switch nodes +#=============================================================================# + +# manditory setup +log_user 0; # disable detailed logging to stdout + +# uncomment the following to debug the test +#strace 20 +#log_user 1 +#exp_internal 1 +#cmd_trace on +#strace 4 + +set install_exit_code 0 + +proc suite_setup {} { + # example of conditional setup + #test_execute {load populate} { + #do some installation or configuration stuff + #} +} + +proc case_setup {} { +# setup to do at start of each test case +# Usage: +# pass as argument to start_suite +# Arguments: +# None +# This procedure will be run at the start of every test case +# It provides an opportunity for uniform cleanup/setup for each test case + +} + +proc case_cleanup { failed } { +# cleanup to do after each test case +# Usage: +# pass as argument to start_suite +# Arguments: +# failed - set to 1 if test case failed in which case additional +# information/files may be desired in test_tmp +# set to 0 if test case passed +# This procedure will be run at the end of every test case +# It provides an opportunity for uniform cleanup after each test case + global env + + test_execute {} { + if { $failed } { + global opaswitch + # could put cleanup here + } + } +} + +test_suite "dump" "dump firmware" "dump firmware of all externally managed switch nodes +File: /usr/lib/opa/tools/switch_dump.exp" suite_setup noop { + global opaswitch + + # Global Initializations for Test Suite: + # -------------------------------------- + + # ADD ANY GLOBAL INITIALIZATION HERE, SUCH AS: + # set env(MY_ENV_VAR) value + # also validate the environment + # if the environment is bad call fail_suite "information" abort_now + # abort_now should be 0 if it is safe to proceed and simply ignore all + # test_case calls. it should be 1 if that is not possible. + + # Procedures used to support Test Suite: + # -------------------------------------- + + # The actual test cases: + # ---------------------- + + parallel opaswitch $env(CFG_OPASWITCHES) { + set opaswitch [ trim_opaswitch_distance "$opaswitch"] + test_case_i2c_extmgd_eeprom "extmgd.eeprom" $opaswitch "NOSPEED" "-R [ trim_opaswitch_hfi_port $opaswitch ]" + } +} diff --git a/IbaTools/FastFabric/switch_fwverify.exp b/IbaTools/FastFabric/switch_fwverify.exp new file mode 100644 index 0000000..7cf1101 --- /dev/null +++ b/IbaTools/FastFabric/switch_fwverify.exp @@ -0,0 +1,115 @@ + +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] + +#=============================================================================# +# Test Suite Description: +#-----------------------------------------------------------------------------# +## switch fwverify +## ------- +## report switch firmware verification of all unmanaged switch nodes +#=============================================================================# + +# manditory setup +log_user 0; # disable detailed logging to stdout + +# uncomment the following to debug the test +#strace 20 +#log_user 1 +#exp_internal 1 +#cmd_trace on +#strace 4 + +set install_exit_code 0 + +proc suite_setup {} { + # example of conditional setup + #test_execute {load populate} { + #do some installation or configuration stuff + #} +} + +proc case_setup {} { +# setup to do at start of each test case +# Usage: +# pass as argument to start_suite +# Arguments: +# None +# This procedure will be run at the start of every test case +# It provides an opportunity for uniform cleanup/setup for each test case + +} + +proc case_cleanup { failed } { +# cleanup to do after each test case +# Usage: +# pass as argument to start_suite +# Arguments: +# failed - set to 1 if test case failed in which case additional +# information/files may be desired in test_tmp +# set to 0 if test case passed +# This procedure will be run at the end of every test case +# It provides an opportunity for uniform cleanup after each test case + global env + + test_execute {} { + if { $failed } { + global opaswitch + # could put cleanup here + } + } +} + +test_suite "switchfwverify" "report switch fwverify" "report firmware version and capability of all externally managed switch nodes +File: /usr/lib/opa/tools/switch_fwverify.exp" suite_setup noop { + global opaswitch + + # Global Initializations for Test Suite: + # -------------------------------------- + + # ADD ANY GLOBAL INITIALIZATION HERE, SUCH AS: + # set env(MY_ENV_VAR) value + # also validate the environment + # if the environment is bad call fail_suite "information" abort_now + # abort_now should be 0 if it is safe to proceed and simply ignore all + # test_case calls. it should be 1 if that is not possible. + + # Procedures used to support Test Suite: + # -------------------------------------- + + # The actual test cases: + # ---------------------- + + parallel opaswitch $env(CFG_OPASWITCHES) { + set opaswitch [ trim_opaswitch_distance "$opaswitch"] + test_case_i2c_extmgd_switchfwverify "$opaswitch" + } +} diff --git a/IbaTools/FastFabric/switch_getconfig.exp b/IbaTools/FastFabric/switch_getconfig.exp new file mode 100644 index 0000000..30d6b3f --- /dev/null +++ b/IbaTools/FastFabric/switch_getconfig.exp @@ -0,0 +1,130 @@ + +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] + +#=============================================================================# +# Test Suite Description: +#-----------------------------------------------------------------------------# +## switch getportconfig +## ------- +## report of port configurations of all unmanaged switch nodes +#=============================================================================# + +# manditory setup +log_user 0; # disable detailed logging to stdout + +# uncomment the following to debug the test +#strace 20 +#log_user 1 +#exp_internal 1 +#cmd_trace on +#strace 4 + +set install_exit_code 0 + +proc suite_setup {} { + # example of conditional setup + #test_execute {load populate} { + #do some installation or configuration stuff + #} +} + +proc case_setup {} { +# setup to do at start of each test case +# Usage: +# pass as argument to start_suite +# Arguments: +# None +# This procedure will be run at the start of every test case +# It provides an opportunity for uniform cleanup/setup for each test case + +} + +proc case_cleanup { failed } { +# cleanup to do after each test case +# Usage: +# pass as argument to start_suite +# Arguments: +# failed - set to 1 if test case failed in which case additional +# information/files may be desired in test_tmp +# set to 0 if test case passed +# This procedure will be run at the end of every test case +# It provides an opportunity for uniform cleanup after each test case + global env + + test_execute {} { + if { $failed } { + global opaswitch + # could put cleanup here + } + } +} + +test_suite "switchgetportconfig" "report switch getconfig" "report port configurations of all externally managed switch nodes +File: /usr/lib/opa/tools/switch_getconfig.exp" suite_setup noop { + global opaswitch + + # Global Initializations for Test Suite: + # -------------------------------------- + + # ADD ANY GLOBAL INITIALIZATION HERE, SUCH AS: + # set env(MY_ENV_VAR) value + # also validate the environment + # if the environment is bad call fail_suite "information" abort_now + # abort_now should be 0 if it is safe to proceed and simply ignore all + # test_case calls. it should be 1 if that is not possible. + + # Procedures used to support Test Suite: + # -------------------------------------- + + # The actual test cases: + # ---------------------- + + # we will get config information to this temp file + set mypid [pid] + set fname [ exec mktemp --tmpdir "sw_getconfig_XXXX" ] + set fd [ open "$fname" {CREAT WRONLY APPEND TRUNC} ] + + parallel opaswitch $env(CFG_OPASWITCHES) { + fconfigure $fd -buffering line + set opaswitch [ trim_opaswitch_distance "$opaswitch"] + test_case_i2c_extmgd_switchgetportconfig "$opaswitch" "$fd" + } + + # omit some lines, and provide a summary of how many switches have each + # type of config + catch { close $fd } + catch { + set summary [exec cat $fname | egrep -v {^[[:space:]]*$|Node Description} | /usr/lib/opa/tools/show_counts 2>@1 ] + show_message "Summary:\ncount - configuration\n$summary" + } + catch { exec rm -f $fname } +} diff --git a/IbaTools/FastFabric/switch_hwvpd.exp b/IbaTools/FastFabric/switch_hwvpd.exp new file mode 100644 index 0000000..266518c --- /dev/null +++ b/IbaTools/FastFabric/switch_hwvpd.exp @@ -0,0 +1,115 @@ + +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] + +#=============================================================================# +# Test Suite Description: +#-----------------------------------------------------------------------------# +## switch hwvpd +## ------- +## report switch hwvpd of all unmanaged switch nodes +#=============================================================================# + +# manditory setup +log_user 0; # disable detailed logging to stdout + +# uncomment the following to debug the test +#strace 20 +#log_user 1 +#exp_internal 1 +#cmd_trace on +#strace 4 + +set install_exit_code 0 + +proc suite_setup {} { + # example of conditional setup + #test_execute {load populate} { + #do some installation or configuration stuff + #} +} + +proc case_setup {} { +# setup to do at start of each test case +# Usage: +# pass as argument to start_suite +# Arguments: +# None +# This procedure will be run at the start of every test case +# It provides an opportunity for uniform cleanup/setup for each test case + +} + +proc case_cleanup { failed } { +# cleanup to do after each test case +# Usage: +# pass as argument to start_suite +# Arguments: +# failed - set to 1 if test case failed in which case additional +# information/files may be desired in test_tmp +# set to 0 if test case passed +# This procedure will be run at the end of every test case +# It provides an opportunity for uniform cleanup after each test case + global env + + test_execute {} { + if { $failed } { + global opaswitch + # could put cleanup here + } + } +} + +test_suite "switchhwvpd" "report switch hwvpd" "report firmware version and capability of all externally managed switch nodes +File: /usr/lib/opa/tools/switch_hwvpd.exp" suite_setup noop { + global opaswitch + + # Global Initializations for Test Suite: + # -------------------------------------- + + # ADD ANY GLOBAL INITIALIZATION HERE, SUCH AS: + # set env(MY_ENV_VAR) value + # also validate the environment + # if the environment is bad call fail_suite "information" abort_now + # abort_now should be 0 if it is safe to proceed and simply ignore all + # test_case calls. it should be 1 if that is not possible. + + # Procedures used to support Test Suite: + # -------------------------------------- + + # The actual test cases: + # ---------------------- + + parallel opaswitch $env(CFG_OPASWITCHES) { + set opaswitch [ trim_opaswitch_distance "$opaswitch"] + test_case_i2c_extmgd_switchhwvpd "$opaswitch" + } +} diff --git a/IbaTools/FastFabric/switch_info.exp b/IbaTools/FastFabric/switch_info.exp new file mode 100644 index 0000000..735a5e5 --- /dev/null +++ b/IbaTools/FastFabric/switch_info.exp @@ -0,0 +1,130 @@ + +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] + +#=============================================================================# +# Test Suite Description: +#-----------------------------------------------------------------------------# +## switch info +## ------- +## report switch info of all unmanaged switch nodes +#=============================================================================# + +# manditory setup +log_user 0; # disable detailed logging to stdout + +# uncomment the following to debug the test +#strace 20 +#log_user 1 +#exp_internal 1 +#cmd_trace on +#strace 4 + +set install_exit_code 0 + +proc suite_setup {} { + # example of conditional setup + #test_execute {load populate} { + #do some installation or configuration stuff + #} +} + +proc case_setup {} { +# setup to do at start of each test case +# Usage: +# pass as argument to start_suite +# Arguments: +# None +# This procedure will be run at the start of every test case +# It provides an opportunity for uniform cleanup/setup for each test case + +} + +proc case_cleanup { failed } { +# cleanup to do after each test case +# Usage: +# pass as argument to start_suite +# Arguments: +# failed - set to 1 if test case failed in which case additional +# information/files may be desired in test_tmp +# set to 0 if test case passed +# This procedure will be run at the end of every test case +# It provides an opportunity for uniform cleanup after each test case + global env + + test_execute {} { + if { $failed } { + global opaswitch + # could put cleanup here + } + } +} + +test_suite "switchinfo" "report switch info" "report firmware version and capability of all externally managed switch nodes +File: /usr/lib/opa/tools/switch_info.exp" suite_setup noop { + global opaswitch + + # Global Initializations for Test Suite: + # -------------------------------------- + + # ADD ANY GLOBAL INITIALIZATION HERE, SUCH AS: + # set env(MY_ENV_VAR) value + # also validate the environment + # if the environment is bad call fail_suite "information" abort_now + # abort_now should be 0 if it is safe to proceed and simply ignore all + # test_case calls. it should be 1 if that is not possible. + + # Procedures used to support Test Suite: + # -------------------------------------- + + # The actual test cases: + # ---------------------- + + # we will get config information to this temp file + set mypid [pid] + set fname [ exec mktemp --tmpdir "sw_info_XXXX" ] + set fd [ open "$fname" {CREAT WRONLY APPEND TRUNC} ] + + parallel opaswitch $env(CFG_OPASWITCHES) { + fconfigure $fd -buffering line + set opaswitch [ trim_opaswitch_distance "$opaswitch"] + test_case_i2c_extmgd_switchinfo "$opaswitch" "$fd" + } + + # omit some lines, and provide a summary of how many switches have each + # type of config + catch { close $fd } + catch { + set summary [exec cat $fname | egrep -v {^[[:space:]]*$} | /usr/lib/opa/tools/show_counts 2>@1 ] + show_message "Summary:\ncount - info\n$summary" + } + catch { exec rm -f $fname } +} diff --git a/IbaTools/FastFabric/switch_ping.exp b/IbaTools/FastFabric/switch_ping.exp new file mode 100644 index 0000000..8773345 --- /dev/null +++ b/IbaTools/FastFabric/switch_ping.exp @@ -0,0 +1,115 @@ + +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] + +#=============================================================================# +# Test Suite Description: +#-----------------------------------------------------------------------------# +## switch ping +## ------- +## report switch ping of all unmanaged switch nodes +#=============================================================================# + +# manditory setup +log_user 0; # disable detailed logging to stdout + +# uncomment the following to debug the test +#strace 20 +#log_user 1 +#exp_internal 1 +#cmd_trace on +#strace 4 + +set install_exit_code 0 + +proc suite_setup {} { + # example of conditional setup + #test_execute {load populate} { + #do some installation or configuration stuff + #} +} + +proc case_setup {} { +# setup to do at start of each test case +# Usage: +# pass as argument to start_suite +# Arguments: +# None +# This procedure will be run at the start of every test case +# It provides an opportunity for uniform cleanup/setup for each test case + +} + +proc case_cleanup { failed } { +# cleanup to do after each test case +# Usage: +# pass as argument to start_suite +# Arguments: +# failed - set to 1 if test case failed in which case additional +# information/files may be desired in test_tmp +# set to 0 if test case passed +# This procedure will be run at the end of every test case +# It provides an opportunity for uniform cleanup after each test case + global env + + test_execute {} { + if { $failed } { + global opaswitch + # could put cleanup here + } + } +} + +test_suite "switchping" "report switch ping" "report firmware version and capability of all externally managed switch nodes +File: /usr/lib/opa/tools/switch_ping.exp" suite_setup noop { + global opaswitch + + # Global Initializations for Test Suite: + # -------------------------------------- + + # ADD ANY GLOBAL INITIALIZATION HERE, SUCH AS: + # set env(MY_ENV_VAR) value + # also validate the environment + # if the environment is bad call fail_suite "information" abort_now + # abort_now should be 0 if it is safe to proceed and simply ignore all + # test_case calls. it should be 1 if that is not possible. + + # Procedures used to support Test Suite: + # -------------------------------------- + + # The actual test cases: + # ---------------------- + + parallel opaswitch $env(CFG_OPASWITCHES) { + set opaswitch [ trim_opaswitch_distance "$opaswitch"] + test_case_i2c_extmgd_switchping "$opaswitch" + } +} diff --git a/IbaTools/FastFabric/switch_reboot.exp b/IbaTools/FastFabric/switch_reboot.exp new file mode 100644 index 0000000..1ee19ea --- /dev/null +++ b/IbaTools/FastFabric/switch_reboot.exp @@ -0,0 +1,136 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] + +#=============================================================================# +# Test Suite Description: +#-----------------------------------------------------------------------------# +## reboot +## ------- +## reboot all externally managed switch nodes +#=============================================================================# + +# manditory setup +log_user 0; # disable detailed logging to stdout + +# uncomment the following to debug the test +#strace 20 +#log_user 1 +#exp_internal 1 +#cmd_trace on +#strace 4 + +set install_exit_code 0 + +proc suite_setup {} { + # example of conditional setup + #test_execute {load populate} { + #do some installation or configuration stuff + #} +} + +proc case_setup {} { +# setup to do at start of each test case +# Usage: +# pass as argument to start_suite +# Arguments: +# None +# This procedure will be run at the start of every test case +# It provides an opportunity for uniform cleanup/setup for each test case + +} + +proc case_cleanup { failed } { +# cleanup to do after each test case +# Usage: +# pass as argument to start_suite +# Arguments: +# failed - set to 1 if test case failed in which case additional +# information/files may be desired in test_tmp +# set to 0 if test case passed +# This procedure will be run at the end of every test case +# It provides an opportunity for uniform cleanup after each test case + global env + + test_execute {} { + if { $failed } { + global opaswitch + # could put cleanup here + } + } +} + +test_suite "reboot" "reboot" "reboot all externally managed switch nodes +File: /usr/lib/opa/tools/switch_reboot.exp" suite_setup noop { + global opaswitch + + # Global Initializations for Test Suite: + # -------------------------------------- + + # ADD ANY GLOBAL INITIALIZATION HERE, SUCH AS: + # set env(MY_ENV_VAR) value + # also validate the environment + # if the environment is bad call fail_suite "information" abort_now + # abort_now should be 0 if it is safe to proceed and simply ignore all + # test_case calls. it should be 1 if that is not possible. + + # Procedures used to support Test Suite: + # -------------------------------------- + + # The actual test cases: + # ---------------------- + + # determine max distance, opaswitches w/o distance are treated as furthest + set max_distance "-1" + set blank_distance 0 + foreach opaswitch $env(CFG_OPASWITCHES) { + set distance [ get_opaswitch_distance "$opaswitch" ] + if { [ string equal "$distance" "" ] } { + set blank_distance 1 + } elseif { $distance > $max_distance } { + set max_distance $distance + } + } + if { $blank_distance } { + incr max_distance + } + + # work from furthest away to closest + for { set i $max_distance } {$i>=0} {incr i -1} { + parallel opaswitch $env(CFG_OPASWITCHES) { + set distance [ get_opaswitch_distance "$opaswitch" ] + if { $distance == $i + || ( $distance == "" && $i == $max_distance ) } { + set opaswitch [ trim_opaswitch_distance "$opaswitch"] + test_case_i2c_extmgd_reset $opaswitch "-t [ trim_opaswitch_hfi_port $opaswitch]" + } + } + } +} diff --git a/IbaTools/FastFabric/switch_upgrade.exp b/IbaTools/FastFabric/switch_upgrade.exp new file mode 100644 index 0000000..6c5c104 --- /dev/null +++ b/IbaTools/FastFabric/switch_upgrade.exp @@ -0,0 +1,198 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] + +#=============================================================================# +# Test Suite Description: +#-----------------------------------------------------------------------------# +## switch_upgrade +## -------------- +## upgrade firmware of all externally managed switch nodes +#=============================================================================# + +# manditory setup +log_user 0; # disable detailed logging to stdout + +# uncomment the following to debug the test +#strace 20 +#log_user 1 +#exp_internal 1 +#cmd_trace on +#strace 4 + +set install_exit_code 0 + +proc suite_setup {} { + # example of conditional setup + #test_execute {load populate} { + #do some installation or configuration stuff + #} +} + +proc case_setup {} { +# setup to do at start of each test case +# Usage: +# pass as argument to start_suite +# Arguments: +# None +# This procedure will be run at the start of every test case +# It provides an opportunity for uniform cleanup/setup for each test case + +} + +proc case_cleanup { failed } { +# cleanup to do after each test case +# Usage: +# pass as argument to start_suite +# Arguments: +# failed - set to 1 if test case failed in which case additional +# information/files may be desired in test_tmp +# set to 0 if test case passed +# This procedure will be run at the end of every test case +# It provides an opportunity for uniform cleanup after each test case + global env + + test_execute {} { + if { $failed } { + global opaswitch + # could put cleanup here + } + } +} + +test_suite "upgrade" "upgrade firmware" "upgrade all externally managed switch nodes +Firmware package File: $env(CFG_FWFILE) +Firmware Files: $env(CFG_FWBINFILES) +Action: $env(CFG_FWACTION) +File: /usr/lib/opa/tools/switch_upgrade.exp" suite_setup noop { + global env + global opaswitch + + # Global Initializations for Test Suite: + # -------------------------------------- + + # ADD ANY GLOBAL INITIALIZATION HERE, SUCH AS: + # set env(MY_ENV_VAR) value + # also validate the environment + # if the environment is bad call fail_suite "information" abort_now + # abort_now should be 0 if it is safe to proceed and simply ignore all + # test_case calls. it should be 1 if that is not possible. + + # Procedures used to support Test Suite: + # -------------------------------------- + + # The actual test cases: + # ---------------------- + + if { [ test_case "check" "check firmware files" "check firmware to be pushed to all externally managed switch nodes +Firmware package File: $env(CFG_FWFILE) +Firmware Files: $env(CFG_FWBINFILES) +Firmware Release Info: $env(CFG_FWRELINFO) +File: /usr/lib/opa/tools/switch_upgrade.exp" case_setup case_cleanup { + set fw_version "" + set fw_type "" + set fw_speed "" + set fw_rel_info "" + set fw_rel_info_param "fwtype" + + # For now simply retrieve the information from the release informatio file, + # in the future may add functionality to utilize this information. + set num_fw [llength $env(CFG_FWFILES)] + + foreach fw_rel_info $env(CFG_FWRELINFO) { + switch -exact -- $fw_rel_info_param { + fwtype { + set fw_rel_info_param "fwversion" + set fw_type $fw_rel_info + log_message "Firmware Type: $fw_type\n" + } + fwversion { + if { [ string equal "$fw_type" "12000"] } { + set fw_speed "QDR" + set fw_version $fw_rel_info + set fw_rel_info_param "" + } else { + set fw_version "V0" + set fw_rel_info_param "fwspeed" + } + set fw_version $fw_rel_info + log_message "Firmware Version: $fw_version\n" + } + fwspeed { + set fw_rel_info_param "" + set fw_speed $fw_rel_info + set speed $fw_speed + log_message "Firmware Speed: $fw_speed\n" + } + } + } + if { $fw_rel_info_param != "" } { + fail_suite "Invalid Firmware Files" + } + } ] } { + fail_suite "Invalid Firmware Files" + } + + # We only get here if all the firmware files supplied are valid + # determine max distance, opaswitches w/o distance are treated as furthest + set max_distance "-1" + set blank_distance 0 + foreach opaswitch $env(CFG_OPASWITCHES) { + set distance [ get_opaswitch_distance "$opaswitch" ] + if { [ string equal "$distance" "" ] } { + set blank_distance 1 + } elseif { $distance > $max_distance } { + set max_distance $distance + } + } + if { $blank_distance } { + incr max_distance + } + + # work from furthest away to closest + for { set i $max_distance } {$i>=0} {incr i -1} { + parallel opaswitch $env(CFG_OPASWITCHES) { + set distance [ get_opaswitch_distance "$opaswitch" ] + if { $distance == $i + || ( $distance == "" && $i == $max_distance ) } { + set opaswitch [ trim_opaswitch_distance "$opaswitch"] + set speed $env(CFG_FWSPEED) + set asicver $env(CFG_FWASICVER) + if { [ string equal "$env(CFG_FWACTION)" "run"] } { + # Push and select the firmware image, and reboot the switch. + test_case_i2c_extmgd_eeprom "upgrade" $opaswitch $speed $asicver "-S -d $env(CFG_FWTEMPDIR) -t [ trim_opaswitch_hfi_port $opaswitch]" + } else { + # Push and select the firmware image. + test_case_i2c_extmgd_eeprom "upgrade" $opaswitch $speed $asicver "-d $env(CFG_FWTEMPDIR) -t [trim_opaswitch_hfi_port $opaswitch]" + } + } + } + } +} diff --git a/IbaTools/FastFabric/tcl_proc.sh b/IbaTools/FastFabric/tcl_proc.sh new file mode 100644 index 0000000..1eeda19 --- /dev/null +++ b/IbaTools/FastFabric/tcl_proc.sh @@ -0,0 +1,53 @@ +#!/bin/bash +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] +# execute a tcl procedure using front +# TEST_CONFIG_FILE is always set to /dev/null +# this allows the environment required for a specific tcl proc (if any) +# to be explicitly provided. For example many commands only need +# CFG_HOSTS defined + +export TL_DIR=/usr/lib/opa/tools + +Usage() +{ + echo "Usage: tcl_proc proc [args ...]" >&2 + exit 2 +} + +if [[ $# -lt 1 ]] +then + Usage +fi + +proc="$1" +shift +TEST_CONFIG_FILE="/dev/null" TCLLIBPATH="/usr/lib/opa/tools /usr/lib/tcl" expect -f /usr/lib/opa/tools/front "$proc" "$@" diff --git a/IbaTools/FastFabric/upgrade.exp b/IbaTools/FastFabric/upgrade.exp new file mode 100644 index 0000000..dd4abe5 --- /dev/null +++ b/IbaTools/FastFabric/upgrade.exp @@ -0,0 +1,132 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] + +#=============================================================================# +# Test Suite Description: +#-----------------------------------------------------------------------------# +## upgrade +## ------- +## simple upgrade installation on all hosts +#=============================================================================# + +# manditory setup +log_user 0; # disable detailed logging to stdout + +# uncomment the following to debug the test +#strace 20 +#log_user 1 +#exp_internal 1 +#cmd_trace on +#strace 4 + +set install_exit_code 0 + +proc suite_setup {} { + # example of conditional setup + #test_execute {load populate} { + #do some installation or configuration stuff + #} +} + +proc case_setup {} { +# setup to do at start of each test case +# Usage: +# pass as argument to start_suite +# Arguments: +# None +# This procedure will be run at the start of every test case +# It provides an opportunity for uniform cleanup/setup for each test case + +} + +proc case_cleanup { failed } { +# cleanup to do after each test case +# Usage: +# pass as argument to start_suite +# Arguments: +# failed - set to 1 if test case failed in which case additional +# information/files may be desired in test_tmp +# set to 0 if test case passed +# This procedure will be run at the end of every test case +# It provides an opportunity for uniform cleanup after each test case + global env + + test_execute {} { + if { $failed || [ test_save_temp ] } { + # save any logs/results from system(s) under test + global host + + install_get_logs $host + } + + if { $failed } { + global host + # could put cleanup here + } + } +} + +test_suite "upgrade" "upgrade" "Simple upgrade of all hosts +File: /usr/lib/opa/tools/upgrade.exp" suite_setup noop { + global host + + # Global Initializations for Test Suite: + # -------------------------------------- + + # ADD ANY GLOBAL INITIALIZATION HERE, SUCH AS: + # set env(MY_ENV_VAR) value + # also validate the environment + # if the environment is bad call fail_suite "information" abort_now + # abort_now should be 0 if it is safe to proceed and simply ignore all + # test_case calls. it should be 1 if that is not possible. + + # Procedures used to support Test Suite: + # -------------------------------------- + + # The actual test cases: + # ---------------------- + + parallel host $env(CFG_HOSTS) { + test_case "$host" "upgrade to $env(CFG_RELEASE) on $host" "Upgrade to $env(CFG_RELEASE) $env(CFG_PRODUCT) on $host +with options $env(CFG_UPGRADE_OPTIONS) +File: /usr/lib/opa/tools/upgrade.exp" case_setup case_cleanup { + upvar host host + + # build list of drivers. If config says not to test a + # given driver, its possible that its not on the media + # so we can't expect it to be installed + # for now assume Stack or Enablement tools are always on media + set drivers {{((OFED OPA Stack)|(OFA OPA Stack)|(OFED IBACM)|(OFA IBACM)|(Intel HFI Components)|(OPA Tools)|(OFED IP over IB)|(OFA IP over IB)|(OPA FM))}} + + install_all $host "$drivers" 0 0 0 "" "$env(CFG_RELEASE)" "-U $env(CFG_UPGRADE_OPTIONS)" "$env(CFG_SCPFROMDIR)" "$env(CFG_PRODUCT)" + } + } +} diff --git a/IbaTools/Makefile b/IbaTools/Makefile new file mode 100644 index 0000000..3289866 --- /dev/null +++ b/IbaTools/Makefile @@ -0,0 +1,95 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2018, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** +# Makefile for IbaTools + +# Include Make Control Settings +include $(TL_DIR)/$(PROJ_FILE_DIR)/Makesettings.project + +DS_SUBPROJECTS = +DSP_SOURCES = Makefile + +DIRS = \ + $(shell ls -d disable_ports 2>/dev/null) \ + $(shell ls -d FastFabric 2>/dev/null) \ + $(shell ls -d fabric_info 2>/dev/null) \ + $(shell ls -d setup_self_ssh 2>/dev/null) \ + $(shell ls -d stream 2>/dev/null) \ + $(shell ls -d opaipcalc 2>/dev/null) \ + $(shell ls -d opagetipaddrtype 2>/dev/null) \ + $(shell ls -d opafirmware 2>/dev/null) \ + $(shell ls -d opamon 2>/dev/null) \ + $(shell ls -d opareport 2>/dev/null) \ + $(shell ls -d opa2rm 2>/dev/null) \ + $(shell ls -d opaxmlextract 2>/dev/null) \ + $(shell ls -d opaxmlfilter 2>/dev/null) \ + $(shell ls -d opaxmlgenerate 2>/dev/null) \ + $(shell ls -d portdown 2>/dev/null) \ + $(shell ls -d opahfirev 2>/dev/null) \ + $(shell ls -d saquery 2>/dev/null) \ + $(shell ls -d opaxlattopology 2>/dev/null) \ + $(shell ls -d opagenswitches 2>/dev/null) \ + $(shell ls -d opagenesmchassis 2>/dev/null) \ + $(shell ls -d opasmaquery 2>/dev/null) \ + $(shell ls -d opapaextract 2>/dev/null) \ + $(shell ls -d opatop 2>/dev/null) \ + $(shell ls -d chassis_setup 2>/dev/null) \ + $(shell ls -d switch_setup 2>/dev/null) \ + $(shell ls -d opafindgood 2>/dev/null) \ + $(shell ls -d opalinkanalysis 2>/dev/null) \ + $(shell ls -d opacabletest 2>/dev/null) \ + $(shell ls -d opacheckload 2>/dev/null) \ + $(shell ls -d nodeverify 2>/dev/null) \ + $(shell ls -d usemem 2>/dev/null) \ + $(shell ls -d opapacketcapture 2>/dev/null) \ + $(shell ls -d man 2>/dev/null) \ + $(shell ls -d opasnapconfig 2>/dev/null) \ + $(shell ls -d opatmmtool 2>/dev/null) +ifeq "$(IB_STACK)" "OPENIB" +DIRS += \ + $(shell ls -d opainfo 2>/dev/null) \ + $(shell ls -d opasw 2>/dev/null) \ + $(shell ls -d opapaquery 2>/dev/null) \ + $(shell ls -d oparesolvehfiport 2>/dev/null) \ + $(shell ls -d opagenchassis 2>/dev/null) +endif # OPENIB + +include $(TL_DIR)/IbaTools/Makerules.module + +include $(TL_DIR)/Makerules/Maketargets.toplevel + +# install for includes, libs and cmds phases +include $(TL_DIR)/Makerules/Maketargets.install + +# install for stage phase - nothing to stage, internal tools +#include $(TL_DIR)/Makerules/Maketargets.stage +STAGE:: + +clobber:: + rm -rf modules builtlibs + diff --git a/IbaTools/Makerules.module b/IbaTools/Makerules.module new file mode 100644 index 0000000..dc72944 --- /dev/null +++ b/IbaTools/Makerules.module @@ -0,0 +1,126 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** +## Rules for IbaTools module +#=============================================================================# +## Module Make Rules File +## ----------------------- +## +#=============================================================================# +## +#=============================================================================# +# The following list is the standard list of definitions which will be defined +# for all platforms. It consists of general and machine specific sections that +# contain many system parameters which may be used in a makefile. Please keep +# the list(s) in strictly aphabetical order to facilitate simple searches. +# +# See Makerules.global for the meaning of these flags +#-----------------------------------------------------------------------------# +# Common platform definitions: +#-----------------------------------------------------------------------------# +MOD_DIR=$(TL_DIR)/IbaTools +MOD_INCLUDE_DIR=$(PROJ_INCLUDE_DIR) +MOD_LIB_DIR=$(PROJ_LIB_DIR) +MOD_BIN_DIR=$(PROJ_BIN_DIR) +MOD_SHLIB_DIR=$(PROJ_SHLIB_DIR) +MOD_SBR_DIR=$(PROJ_SBR_DIR) + +MOD_STAGE_DIR=$(PROJ_STAGE_DIR) +MOD_STAGE_INCLUDE_DIR=$(PROJ_STAGE_INCLUDE_DIR) +MOD_STAGE_LIB_DIR=$(PROJ_STAGE_LIB_DIR) +MOD_STAGE_BIN_DIR=$(PROJ_STAGE_BIN_DIR) +MOD_STAGE_TESTS_BIN_DIR=$(PROJ_STAGE_TESTS_BIN_DIR) +MOD_STAGE_SHLIB_DIR=$(PROJ_STAGE_SHLIB_DIR) +MOD_STAGE_SBR_DIR=$(PROJ_STAGE_SBR_DIR) + +MOD_BIN_SUBDIR = +MOD_INCLUDE_SUBDIR = # or module_name + + +MOD_INCLUDE_DIRS = # or $(MOD_DIR)/include +MOD_LIB_DIRS = # or $(MOD_LIB_DIR) +MODDEPLIBS = +MODLIBS = + +BSCMOD = +CMOD = +CCMOD = $(CMOD) +DEPENDMOD = +LDMOD = +LINTMOD = +MIDLMOD = +RSCMOD = + +#-----------------------------------------------------------------------------# +# Platform specific definitions: +#-----------------------------------------------------------------------------# +ifeq "$(TARGET_OS)" "VXWORKS" +endif # VXWORKS +ifeq "$(TARGET_OS)" "LINUX" +endif # LINUX +ifeq "$(TARGET_OS)" "WIN32" +endif # WIN32 +#=============================================================================# +# Include Global makerules definitions and rules +include $(TL_DIR)/$(PROJ_FILE_DIR)/Makerules.project +#=============================================================================# + +#=============================================================================# +## The project makerules file also contains the following basic make target +## rules for simplifying application build processes: +## +#=============================================================================# +# The following section contains a list of standard targets which will be used +# by all of the makefiles. The targets are listed in alphabetical order and +# depend on the above definitions section as well as externally defined items +# from the user specific makefile. +#=============================================================================# +# General Rules: +#-----------------------------------------------------------------------------# +#=============================================================================# + +#=============================================================================# +# This section contains a set of targets which override the standard ones +# provided for by GNU make. +#=============================================================================# +# Standard Makefile Rules Overrides: +#-----------------------------------------------------------------------------# +#=============================================================================# + +#=============================================================================# +# Targets to make sure the initial environment is properly configured +#=============================================================================# +#ifndef ENVIRONMENT +#check_env: +# @echo "The ENVIRONMENT environment variable must be set to be valid" +# @exit 1 +#else #ENVIRONMENT +#check_env: +#endif #ENVIRONMENT +#.PHONY: check_env +#=============================================================================# diff --git a/IbaTools/README b/IbaTools/README new file mode 100644 index 0000000..379eab7 --- /dev/null +++ b/IbaTools/README @@ -0,0 +1 @@ +Assorted simple utility programs and simple samples of using the iba APIs diff --git a/IbaTools/chassis_setup/Makefile b/IbaTools/chassis_setup/Makefile new file mode 100644 index 0000000..9ab56da --- /dev/null +++ b/IbaTools/chassis_setup/Makefile @@ -0,0 +1,160 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** +# Makefile for chassis_setup + +# Include Make Control Settings +include $(TL_DIR)/$(PROJ_FILE_DIR)/Makesettings.project + +#=============================================================================# +# Definitions: +#-----------------------------------------------------------------------------# + +# Name of SubProjects +DS_SUBPROJECTS = +# name of executable or downloadable image +EXECUTABLE = $(BUILDDIR)/chassis_setup$(EXE_SUFFIX) +# list of sub directories to build +DIRS = +# C files (.c) +CFILES = \ + chassis_setup.c \ + # Add more files here +# C++ files (.cpp) +CCFILES = \ + # Add more files here +# lex files (.lex) +LFILES = \ + # Add more lex files here +# archive library files (basename, $ARFILES will add MOD_LIB_DIR/prefix and suffix) +LIBFILES = +# Windows Resource Files (.rc) +RSCFILES = +# Windows IDL File (.idl) +IDLFILE = +# Windows Linker Module Definitions (.def) file for dll's +DEFFILE = +# targets to build during INCLUDES phase (add public includes here) +INCLUDE_TARGETS = \ + chassis_setup.h \ + # Add more h hpp files here +# Non-compiled files +MISC_FILES = +# all source files +SOURCES = $(CFILES) $(CCFILES) $(LFILES) $(RSCFILES) $(IDLFILE) +# Source files to include in DSP File +DSP_SOURCES = $(INCLUDE_TARGETS) $(SOURCES) $(MISC_FILES) \ + $(RSCFILES) $(DEFFILE) $(MAKEFILE) +# all object files +OBJECTS = $(CFILES:.c=$(OBJ_SUFFIX)) $(CCFILES:.cpp=$(OBJ_SUFFIX)) \ + $(LFILES:.lex=$(OBJ_SUFFIX)) +RSCOBJECTS = $(RSCFILES:.rc=$(RES_SUFFIX)) + +# targets to build during LIBS phase +LIB_TARGETS_IMPLIB = +LIB_TARGETS_ARLIB = +LIB_TARGETS_EXP = $(LIB_TARGETS_IMPLIB:$(ARLIB_SUFFIX)=$(EXP_SUFFIX)) +LIB_TARGETS_MISC = +# targets to build during CMDS phase +CMD_TARGETS_SHLIB = +CMD_TARGETS_EXE = $(EXECUTABLE) +CMD_TARGETS_MISC = +CMD_TARGETS_DRIVER = +# files to remove during clean phase +CLEAN_TARGETS_MISC = +CLEAN_TARGETS = $(OBJECTS) $(RSCOBJECTS) $(IDL_TARGETS) $(CLEAN_TARGETS_MISC) +# other files to remove during clobber phase +CLOBBER_TARGETS_MISC= +# sub-directory to install to within bin +BIN_SUBDIR = +# sub-directory to install to within include +INCLUDE_SUBDIR = + +# Additional Settings +#CLOCALDEBUG = User defined C debugging compilation flags [Empty] +#CCLOCALDEBUG = User defined C++ debugging compilation flags [Empty] +#CLOCAL = User defined C flags for compiling [Empty] +#CCLOCAL = User defined C++ flags for compiling [Empty] +#BSCLOCAL = User flags for Browse File Builder [Empty] +#DEPENDLOCAL = user defined makedepend flags [Empty] +#LINTLOCAL = User defined lint flags [Empty] +#LOCAL_INCLUDE_DIRS = User include directories to search for C/C++ headers [Empty] +#LDLOCAL = User defined C flags for linking [Empty] +#IMPLIBLOCAL = User flags for Object Lirary Manager [Empty] +#MIDLLOCAL = User flags for IDL compiler [Empty] +#RSCLOCAL = User flags for resource compiler [Empty] +#LOCALDEPLIBS = User libraries to include in dependencies [Empty] +#LOCALLIBS = User libraries to use when linking [Empty] +# (in addition to LOCALDEPLIBS) +# = User library directories for libpaths [Empty] + +CLOCAL = $(CPIE) + +LOCAL_LIB_DIRS = +LOCALLIBS= + +# Include Make Rules definitions and rules +include $(TL_DIR)/IbaTools/Makerules.module + +#=============================================================================# +# Overrides: +#-----------------------------------------------------------------------------# +#CCOPT = # C++ optimization flags, default lets build config decide +#COPT = # C optimization flags, default lets build config decide +#SUBSYSTEM = Subsystem to build for (none, console or windows) [none] +# (Windows Only) +#USEMFC = How Windows MFC should be used (none, static, shared, no_mfc) [none] +# (Windows Only) +#=============================================================================# + +#=============================================================================# +# Rules: +#-----------------------------------------------------------------------------# +# process Sub-directories +include $(TL_DIR)/Makerules/Maketargets.toplevel + +# build cmds and libs +include $(TL_DIR)/Makerules/Maketargets.build + +# install for includes, libs and cmds phases +include $(TL_DIR)/Makerules/Maketargets.install + +# install for stage phase +#include $(TL_DIR)/Makerules/Maketargets.stage +STAGE:: + $(VS)$(STAGE_INSTALL) $(STAGE_INSTALL_DIR_OPT) $(PROJ_STAGE_FASTFABRIC_DIR) $(CMD_TARGETS_EXE) $(CMD_TARGETS_MISC) $(MISC_FILES) + + +# Unit test execution +#include $(TL_DIR)/Makerules/Maketargets.runtest + +#=============================================================================# + +#=============================================================================# +# DO NOT DELETE THIS LINE -- make depend depends on it. +#=============================================================================# diff --git a/IbaTools/chassis_setup/chassis_setup.c b/IbaTools/chassis_setup/chassis_setup.c new file mode 100644 index 0000000..9ee5f8a --- /dev/null +++ b/IbaTools/chassis_setup/chassis_setup.c @@ -0,0 +1,848 @@ +/* BEGIN_ICS_COPYRIGHT5 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + * ** END_ICS_COPYRIGHT5 ****************************************/ +/* [ICS VERSION STRING: unknown] */ +#include +#include +#include +#include +#include +#include +#include +#include "chassis_setup.h" +#include "iba/stl_types.h" + +#define NO_TZ_DST_SETUP 100 +#define SYSLOG_PORT_DEFAULT -1 +#define SYSLOG_FACILITY_DEFAULT -1 +/* Info for all chassis */ +int tzOffset; /* Offset in hours (from UTC) */ +dstInfo_t dstInfo; /* DST start and end info */ +char syslogIpAddr[20]; /* IP addr of syslog server */ +int syslogPort = SYSLOG_PORT_DEFAULT; /* Port for syslog */ +int syslogFacility = SYSLOG_FACILITY_DEFAULT; /* Facility level for syslog */ +char ntpIpAddr[20]; /* IP addr of NTP server */ +int linkWidthSelection; /* selection for link width */ +int setname; /* should OPA Node Desc be set to match ethernet name */ +int linkCRCModeSelection; /* selection for Link CRC mode */ + +/* Globals for chassis specifics */ + +int numChassis; +chassisInfo_t *chassisInfoTable; +int chassisInfoTableSize; + +void stripCR(char *buf) +{ + char *p; + + if ((p = strchr(buf, '\n')) != NULL) + *p = '\0'; + if ((p = strchr(buf, '\r')) != NULL) + *p = '\0'; + + return; +} + +int getYesNo(char *question, int def) +{ + int done = 0; + int res = 1; + char answerBuf[8]; + + while (!done) + { + printf("%s: ", question); + if (fgets(answerBuf, 8, stdin)) { + stripCR(answerBuf); + if (strncmp(answerBuf, "none", 4) == 0) + { + res = 0; + done = 1; + } + else if ((answerBuf[0] == 'n') || (answerBuf[0] == 'N')) + { + res = 0; + done = 1; + } + else if ((answerBuf[0] == 'y') || (answerBuf[0] == 'Y')) + { + res = 1; + done = 1; + } + else if (strlen(answerBuf) == 0) + { + res = def; + done = 1; + } + else + { + fprintf(stderr, "<%s> is not a valid entry - please enter y or n ... \n", answerBuf); + } + } + } + return(res); +} + +int getInt(char *question, int low, int high, boolean allowAbort, int abortValue) +{ + int done = 0; + int selection; + int res = 1; + int i; + int goodInt; + char answerBuf[64]; + + while (!done) + { + if (allowAbort) + printf("%s (or none): ", question); + else + printf("%s: ", question); + if (fgets(answerBuf, 64, stdin)) { + stripCR(answerBuf); + + if (allowAbort && (strncmp(answerBuf, "none", 4) == 0)) + return abortValue; + + if (strlen(answerBuf) == 0) + goodInt = 0; + else { + for (i = 0, goodInt = 1; (i < strlen(answerBuf)) && goodInt; i++) { + if (!isdigit(answerBuf[i])) + goodInt = 0; + } + } + + if (goodInt) + selection = atoi(answerBuf); + else + selection = -1; + + if ((selection < low) || (selection > high)) + fprintf(stderr, "<%s> is not a valid entry - please select a choice from %d to %d ...\n", answerBuf, low, high); + else + { + res = selection; + done = 1; + } + } + } + return(res); +} + +void setupTZInfo(tzCode_t timeZone) +{ + switch (timeZone) + { + case TZ_NA_ATLA: + /* NAmer - Atlantic */ + if (daylight) + dstInfo = NA_DSTInfo; + else + dstInfo = None_DSTInfo; + tzOffset = -4; + break; + case TZ_NA_EAST: + /* NAmer - Eastern */ + if (daylight) + dstInfo = NA_DSTInfo; + else + dstInfo = None_DSTInfo; + tzOffset = -5; + break; + case TZ_NA_CENT: + /* NAmer - Central */ + if (daylight) + dstInfo = NA_DSTInfo; + else + dstInfo = None_DSTInfo; + tzOffset = -6; + break; + case TZ_NA_MOUN: + /* NAmer - Mountain */ + if (daylight) + dstInfo = NA_DSTInfo; + else + dstInfo = None_DSTInfo; + tzOffset = -7; + break; + case TZ_NA_PACI: + /* NAmer - Pacific */ + if (daylight) + dstInfo = NA_DSTInfo; + else + dstInfo = None_DSTInfo; + tzOffset = -8; + break; + case TZ_NA_ASKA: + /* NAmer - Alaska */ + if (daylight) + dstInfo = NA_DSTInfo; + else + dstInfo = None_DSTInfo; + tzOffset = -9; + break; + case TZ_NA_HAWI: + /* NAmer - Hawaii */ + dstInfo = None_DSTInfo; + tzOffset = -10; + break; + case TZ_EU_UTC: + /* Europe - UTC */ + if (daylight) + dstInfo = EUR_DSTInfo; + else + dstInfo = None_DSTInfo; + tzOffset = 0; + break; + case TZ_EU_CENT: + /* Europe - Central */ + if (daylight) + dstInfo = EUR_DSTInfo; + else + dstInfo = None_DSTInfo; + tzOffset = 1; + break; + case TZ_EU_EAST: + /* Europe - Eastern */ + if (daylight) + dstInfo = EUR_DSTInfo; + else + dstInfo = None_DSTInfo; + tzOffset = 2; + break; + case TZ_EU_MOSC: + /* Europe - Russia/Moscow */ + if (daylight) + dstInfo = EUR_DSTInfo; + else + dstInfo = None_DSTInfo; + tzOffset = 3; + break; + case TZ_AS_CHIN: + /* China */ + dstInfo = None_DSTInfo; + tzOffset = 8; + break; + case TZ_AS_JAPN: + /* Japan */ + dstInfo = None_DSTInfo; + tzOffset = 9; + break; + case TZ_AU_SYDN: + /* Australia - Sydney */ + if (daylight) + dstInfo = AUS_DSTInfo; + else + dstInfo = None_DSTInfo; + tzOffset = 10; + break; + case TZ_NZ_AUCK: + /* New Zealand - Auckland */ + if (daylight) + dstInfo = NZ_DSTInfo; + else + dstInfo = None_DSTInfo; + tzOffset = 12; + break; + } + return; +} + +void getTimeZoneInfo(int configureTZDST) +{ + int useServerTZInfo = 1; + int tzSelection; + int configureManually = 0; + int done = 0; + tzCode_t timeZone = TZ_NA_EAST; + char questionText[100]; + + if (configureTZDST) + { + useServerTZInfo = getYesNo("Do you want to use the local timezone information from the local server? [y]", 1); + + if (useServerTZInfo) + { + tzset(); + switch (TIMEZONEOFFSET) + { + case 0: + /* UTC */ + timeZone = TZ_EU_UTC; + break; + case 4: + /* NAmer - Atlantic */ + timeZone = TZ_NA_ATLA; + break; + case 5: + /* NAmer - Eastern */ + timeZone = TZ_NA_EAST; + break; + case 6: + /* NAmer - Central */ + timeZone = TZ_NA_CENT; + break; + case 7: + /* NAmer - Mountain */ + timeZone = TZ_NA_MOUN; + break; + case 8: + /* NAmer - Pacific */ + timeZone = TZ_NA_PACI; + break; + case 9: + /* NAmer - Alaska */ + timeZone = TZ_NA_ASKA; + break; + case 10: + /* NAmer - Hawaii */ + timeZone = TZ_NA_HAWI; + break; + case -1: + /* Cent Europe */ + timeZone = TZ_EU_CENT; + break; + case -2: + /* East Europe */ + timeZone = TZ_EU_EAST; + break; + case -3: + /* Russia - Moscow */ + timeZone = TZ_EU_MOSC; + break; + case -8: + /* China */ + timeZone = TZ_AS_CHIN; + break; + case -9: + /* Japan */ + timeZone = TZ_AS_JAPN; + break; + case -10: + /* Australia - Sydney */ + timeZone = TZ_AU_SYDN; + break; + case -12: + /* New Zealand - Auckland */ + timeZone = TZ_NZ_AUCK; + break; + } + setupTZInfo(timeZone); + } /* using server TZ info */ + else + { /* not using server TZ info */ + + printf("Select a locale that matches your location: \n"); + printf("\t1 - North America - Atlantic\n"); + printf("\t2 - North America - Eastern\n"); + printf("\t3 - North America - Central\n"); + printf("\t4 - North America - Mountain\n"); + printf("\t5 - North America - Arizona\n"); + printf("\t6 - North America - Pacific\n"); + printf("\t7 - North America - Alaska\n"); + printf("\t8 - North America - Hawaii\n"); + printf("\t9 - UK\n"); + printf("\t10 - Central Europe\n"); + printf("\t11 - Eastern Europe\n"); + printf("\t12 - Russia - Moscow\n"); + printf("\t13 - China\n"); + printf("\t14 - Japan\n"); + printf("\t15 - Australia - Sydney\n"); + printf("\t16 - New Zealand - Auckland\n"); + printf("\t17 - Configure manually\n"); + tzSelection = getInt("Enter selection", 1, 17, FALSE, 0); + daylight = 1; + switch (tzSelection) + { + case 1: + timeZone = TZ_NA_ATLA; + break; + case 2: + timeZone = TZ_NA_EAST; + break; + case 3: + timeZone = TZ_NA_CENT; + break; + case 4: + timeZone = TZ_NA_MOUN; + break; + case 5: + timeZone = TZ_NA_MOUN; + daylight = 0; + break; + case 6: + timeZone = TZ_NA_PACI; + break; + case 7: + timeZone = TZ_NA_ASKA; + break; + case 8: + timeZone = TZ_NA_HAWI; + daylight = 0; + break; + case 9: + timeZone = TZ_EU_UTC; + break; + case 10: + timeZone = TZ_EU_CENT; + break; + case 11: + timeZone = TZ_EU_EAST; + break; + case 12: + timeZone = TZ_EU_MOSC; + break; + case 13: + timeZone = TZ_AS_CHIN; + daylight = 0; + break; + case 14: + timeZone = TZ_AS_JAPN; + daylight = 0; + break; + case 15: + timeZone = TZ_AU_SYDN; + break; + case 16: + timeZone = TZ_NZ_AUCK; + break; + case 17: + configureManually = 1; + break; + } + if (!configureManually) + setupTZInfo(timeZone); + else + { + tzOffset = getInt("Enter timezone offset in hours - positive is east, negative is west of UTC", -12, 12, FALSE, 0); + daylight = getYesNo("Does your timezone observe Daylight Saving or Summer Time? [y]", 1); + if (daylight) + { + while (!done) + { + printf("You will be prompted for adjustment information - which day of the week in which month (e.g. 2nd Sunday in March),\n"); + printf("for both start and end of the observance.\n\n"); + printf("For month, valid replies are: 3-11: 3-Mar, 4-Apr, 5-May, 6-Jun, 7-Jul, 8-Aug, 9-Sep, 10-Oct, 11-Nov\n"); + printf("For day of week, valid replies are: 1-7: 1-Sun, 2-Mon, 3-Tue, 4-Wed, 5-Thu, 6-Fri, 7-Sat\n"); + printf("For which day, valid replies are: 1-5: 1-1st, 2-2nd, 3-3rd, 4-4th, 5-last\n"); + dstInfo.startMonth = getInt("Enter the month in which your timezone begins observing DST/Summer Time", 3, 11, FALSE, 0); + dstInfo.startDay = getInt("Enter the day of week on which your timezone begins observing DST/Summer Time", 1, 7, FALSE, 0); + snprintf(questionText, sizeof(questionText), "Enter which %s in %s your timezone begins observing DST/Summer Time", DaysOfWeek[dstInfo.startDay], MonthsOfYear[dstInfo.startMonth]); + dstInfo.startWhich = getInt(questionText, 1, 5, FALSE, 0); + dstInfo.endMonth = getInt("Enter the month in which your timezone ends observing DST/Summer Time", 3, 11, FALSE, 0); + dstInfo.endDay = getInt("Enter the day of week on which your timezone ends observing DST/Summer Time", 1, 7, FALSE, 0); + snprintf(questionText, sizeof(questionText), "Enter which %s in %s your timezone ends observing DST/Summer Time", DaysOfWeek[dstInfo.endDay], MonthsOfYear[dstInfo.endMonth]); + dstInfo.endWhich = getInt(questionText, 1, 5, FALSE, 0); + printf("You have selected the following start/end parameters:\n"); + printf(" Start DST/Summer Time on the %s %s in %s\n", Ordinals[dstInfo.startWhich], DaysOfWeek[dstInfo.startDay], MonthsOfYear[dstInfo.startMonth]); + printf(" End DST/Summer Time on the %s %s in %s\n", Ordinals[dstInfo.endWhich], DaysOfWeek[dstInfo.endDay], MonthsOfYear[dstInfo.endMonth]); + done = getYesNo("Does this reflect your timezone's start and end DST/Summer Time adjustments? [y]", 1); + } + } + } + + } /* not using server TZ info */ + } else { + tzOffset = NO_TZ_DST_SETUP; + memset((void *)&dstInfo, 0, sizeof(dstInfo)); + } + + return; +} + +int validateIpAddrSection(char *p) +{ + int res = 0; + int digitCount = 0; + + while(isdigit(*p++)) + { + digitCount++; + } + if (digitCount <= 3) + res = digitCount; + + return(res); +} + +int getIpAddress(char *ipAddress, char *promptText) +{ + char inbuf[64]; + int ipAddrParts[4]; + int res = 1; + int done = 0; + int i = 0; + char *p; + int goodSyntax = 1; + + while (!done) + { + p = inbuf; + printf("Enter IP address for %s (or none): ", promptText); + if (fgets(inbuf, 64, stdin) == NULL) { + goodSyntax = 0; + printf("\n"); + } else { + if (strncmp(inbuf, "none", 4) == 0) + { + return 0; + } + goodSyntax = 1; + for (i = 0; i < 4; i++) + { + if ((res = validateIpAddrSection(p)) > 0) + p += res; + else + goodSyntax = 0; + + if (i < 3) + { + if (*p == '.') + p++; + else + goodSyntax = 0; + } + } + } + + if (goodSyntax) + { + sscanf(inbuf, "%d.%d.%d.%d", &ipAddrParts[0], &ipAddrParts[1], &ipAddrParts[2], &ipAddrParts[3]); + goodSyntax = 1; + i = 0; + while (goodSyntax && (i < 4)) + { + if ((ipAddrParts[i] < 0) || (ipAddrParts[i] > 255)) + goodSyntax = 0; + i++; + } + } + + if (!goodSyntax) + fprintf(stderr, "Bad IP Address syntax: %s", inbuf); + else + done = 1; + } + + if (goodSyntax) + snprintf(ipAddress, 16, "%d.%d.%d.%d", ipAddrParts[0], ipAddrParts[1], ipAddrParts[2], ipAddrParts[3]); + else + res = 0; + + return(res); +} + +int validLicenseKey(char *key) +{ + char *p; + int goodSyntax = 1; + int i; + int j; + + /* valid syntax is 5 groups of six alphanumeric chars, each followed by a hyphen, and lastly + a single alphanumeric */ + p = key; + for (i = 0; (i < 5) && goodSyntax; i++) + { + for (j = 0; (j < 6) && goodSyntax; j++) + { + if (!isalnum(*p++)) + goodSyntax = 0; + if (j == 5) + { + if (*p++ != '-') + goodSyntax = 0; + } + } + } + if (!isalnum(*p)) + goodSyntax = 0; + + return(goodSyntax); +} + +void removeCR(char *buf) +{ + char *p; + + if ((p = strchr(buf, '\n')) != NULL) + *p = '\0'; +} + +int getLicenseKey(char *smKey, char *promptText) +{ + int done = 0; + int res = 1; + char keyBuf[80]; + + while (!done) + { + printf("Enter license key for %s: ", promptText); + if (fgets(keyBuf, 80, stdin)) { + removeCR(keyBuf); + + if (validLicenseKey(keyBuf)) + done = 1; + else + fprintf(stderr, "Bad license key syntax\n"); + } + } + + strcpy(smKey, keyBuf); + + return(res); +} + +int storeChassisInfo(char *ipAddr, char *smKey) +{ + chassisInfo_t *oldTable; + int i; + int res = 1; + + if (numChassis == chassisInfoTableSize) + { + oldTable = chassisInfoTable; + if ((chassisInfoTable = (chassisInfo_t *)malloc(sizeof(chassisInfo_t) * (chassisInfoTableSize + CHASSISINFOBLOCK))) == NULL) + { + fprintf(stderr, "Error allocating table for chassis info\n"); + return(0); + } + if (oldTable != NULL) + { + for (i = 0; i < chassisInfoTableSize; i++) + memcpy(&chassisInfoTable[i], &oldTable[i], sizeof(chassisInfo_t)); + free(oldTable); + } + chassisInfoTableSize += CHASSISINFOBLOCK; + } + + memcpy(&chassisInfoTable[numChassis].chassisIpAddr, ipAddr, strlen(ipAddr)+1); + memcpy(&chassisInfoTable[numChassis].chassisSMKey, smKey, strlen(smKey)+1); + numChassis++; + + return(res); +} + +int getChassisSpecifics(int argc, char *argv[]) +{ + int res = 1; + int i; +#if 0 + int ipAddr; + int licenseKey; + char promptText[20]; +#endif + char chassisIpAddr[20]; + char chassisSMKey[50]; + + for (i = 2; i < argc; i++) + { +#if 0 + sprintf(promptText, "chassis %s", argv[i]); + printf("%s\n", promptText); + ipAddr = getYesNo("Do you wish to set the chassis IP address for this chassis? [n]", 0); + if (ipAddr) + { + if (!(res = getIpAddress(chassisIpAddr, promptText))) + NOIPADDR(chassisIpAddr); + } + else + NOIPADDR(chassisIpAddr); +#else + NOIPADDR(chassisIpAddr); +#endif + +#if 0 + licenseKey = getYesNo("Do you wish to add an SM license key for this chassis? [y]", 1); + if (licenseKey) + { + if (!(res = getLicenseKey(chassisSMKey, promptText))) + strcpy(chassisSMKey, "NO-KEY"); + } + else + strcpy(chassisSMKey, "NO-KEY"); + res = storeChassisInfo(chassisIpAddr, chassisSMKey); +#else + strcpy(chassisSMKey, "NO-KEY"); + res = storeChassisInfo(chassisIpAddr, chassisSMKey); +#endif + } + + return(res); +} + +int getGeneralInfo() +{ + int cfgSyslog = 0; + int useSyslogServer = 0; + int useSyslogPort = 0; + int useSyslogFacility = 0; + int useNTPServer = 0; + int setTzInfo = 0; + int setLinkWidth = 0; + int setLinkCRCMode = 0; + int res = 1; + + cfgSyslog = getYesNo("Do you wish to adjust syslog configuration settings? [y]", 1); + if (cfgSyslog) + { + useSyslogServer = getYesNo("Do you wish to configure a syslog server? [y]", 1); + if (useSyslogServer) + { + if (!(res = getIpAddress(syslogIpAddr, "syslog server"))) + NOIPADDR(syslogIpAddr); + } + else + { + NOIPADDR(syslogIpAddr); + } + useSyslogPort = getYesNo("Do you wish to configure the syslog TCP/UDP port number? [n]", 0); + if (useSyslogPort) + { + syslogPort = getInt("Enter TCP/UDP port number for syslog", 1, 1<<16, TRUE, SYSLOG_PORT_DEFAULT); + } + useSyslogFacility = getYesNo("Do you wish to configure the syslog facility? [n]", 0); + if (useSyslogFacility) + { + syslogFacility = getInt("Enter facility level for syslog (0-23)", 0, 23, TRUE, SYSLOG_FACILITY_DEFAULT); + } + } + else + { + NOIPADDR(syslogIpAddr); + } + + useNTPServer = getYesNo("Do you wish to configure an NTP server? [y]", 1); + if (useNTPServer) + { + if (!(res = getIpAddress(ntpIpAddr, "NTP server"))) + NOIPADDR(ntpIpAddr); + } + else + NOIPADDR(ntpIpAddr); + + setTzInfo = getYesNo("Do you wish to configure timezone and DST information? [y]", 1); + getTimeZoneInfo(setTzInfo); + + setLinkWidth = getYesNo("Do you wish to configure the chassis link width? [n]", 0); + if (setLinkWidth) + { + printf("\t1 : 1X\n\t2 : 2X\n\t3 : 1X/2X\n\t4 : 3X\n\t5 : 1X/3X\n\t6 : 2X/3X\n\t7 : 1X/2X/3X\n\t8 : 4X\n\t9 : 1X/4X\n\t10 : 2X/4X\n\t11 : 1X/2X/4X\n\t12 : 3X/4X\n\t13 : 1X/3X/4X\n\t14 : 2X/3X/4X\n\t15 : 1X/2X/3X/4X\n"); + linkWidthSelection = getInt("Enter selection", 1, 15, TRUE, 0); + if (linkWidthSelection > 0) + { + printf("*******************************************************************************\n"); + printf("*** Note: a reboot of all chassis devices is required in order to activate\n*** changes to the chassis link width\n"); + printf("*******************************************************************************\n"); + } + } else + linkWidthSelection = 0; + + setname = getYesNo("Do you wish to configure OPA Node Desc to match ethernet chassis name? [y]", 1); + if (setname) { + printf("*******************************************************************************\n"); + printf("*** Note: a reboot of all chassis devices is required in order to activate\n*** changes to the chassis OPA Node Desc\n"); + printf("*******************************************************************************\n"); + } + + setLinkCRCMode = getYesNo("Do you wish to configure the Link CRC Mode? [n]", 0); + if (setLinkCRCMode) { + printf("\t0 : 16b,\n\t1 : 14b/16b,\n\t2 : 48b/16b,\n\t3 : 48b/14b/16b,\n\t4 : per-lane/16b,\n\t5 : per-lane/14b/16b,\n\t6 : per-lane/48b/16b,\n\t7 : per-lane/48b/14b/16b\n"); + linkCRCModeSelection = getInt("Enter selection", 0, 7, TRUE, -1); + if (linkCRCModeSelection > -1) + { + printf("*******************************************************************************\n"); + printf("*** Note: a reboot of all chassis devices is required in order to activate\n*** changes to the chassis link CRC mode\n"); + printf("*******************************************************************************\n"); + } + } else + linkCRCModeSelection = -1; + + return(res); +} + +int +main(int argc, char *argv[]) +{ + int i; + FILE *fp_out; + char *dirName; + + chassisInfoTable = NULL; + chassisInfoTableSize = 0; + numChassis = 0; + + dirName = argv[1]; + if (dirName == NULL) + dirName = "."; + + if (chdir(dirName) < 0) { + fprintf(stderr, "Error changing directory to %s: %s\n", dirName, strerror(errno)); + exit(1); + } + + getChassisSpecifics(argc, argv); + getGeneralInfo(); + + if ((fp_out = fopen("./.chassisSetup.out","w")) == NULL) + { + fprintf(stderr, "Error opening .chassisSetup.out for output: %s\n", strerror(errno)); + exit(1); + } + + /* display chassis info */ + fprintf(fp_out, "Number of chassis: %d\n", numChassis); + for (i = 0; i < numChassis; i++) + { + fprintf(fp_out, "%d Chassis %s IP_Addr: %s\n", i+2, argv[i+2], chassisInfoTable[i].chassisIpAddr); + fprintf(fp_out, "%d Chassis %s SM_Key: %s\n", i+2, argv[i+2], (chassisInfoTable[i].chassisSMKey != NULL) ? chassisInfoTable[i].chassisSMKey : "NULL"); + } + + /* display general info */ + fprintf(fp_out, "Syslog Server IP_Address:%s\n", syslogIpAddr); + fprintf(fp_out, "Syslog Port:%d\n", syslogPort); + fprintf(fp_out, "Syslog Facility:%d\n", syslogFacility); + fprintf(fp_out, "NTP Server IP_Address:%s\n", ntpIpAddr); + fprintf(fp_out, "Timezone offset:%d\n", tzOffset); + fprintf(fp_out, "Start DST:%d %d %d\n", + dstInfo.startWhich, + dstInfo.startDay, + dstInfo.startMonth); + fprintf(fp_out, "End DST:%d %d %d\n", + dstInfo.endWhich, + dstInfo.endDay, + dstInfo.endMonth); + fprintf(fp_out, "Link Width Selection:%d\n", linkWidthSelection); + fprintf(fp_out, "Set OPA Node Desc:%s\n", setname?"y":"n"); + fprintf(fp_out, "Link CRC Mode:%d\n", linkCRCModeSelection); + + fclose(fp_out); + exit(0); +} diff --git a/IbaTools/chassis_setup/chassis_setup.h b/IbaTools/chassis_setup/chassis_setup.h new file mode 100644 index 0000000..35a0e6f --- /dev/null +++ b/IbaTools/chassis_setup/chassis_setup.h @@ -0,0 +1,127 @@ +/* BEGIN_ICS_COPYRIGHT3 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT3 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +#ifndef CHASSISSETUP_H_INCLUDED +#define CHASSISSETUP_H_INCLUDED + +/* chassisSetup.h */ + +#define TIMEZONEOFFSET (timezone / (60*60)) + +typedef struct dst_struct +{ + int startWhich; /* 1 = 1st, 2 = 2nd, 3 = 3rd, 4 = 4th, 5 = 5th */ + int startDay; /* 1 = Sun, 2 = Mon, 3 = Tue, 4 = Wed, 5 = Thu, 6 = Fri, 7 = Sat */ + int startMonth; /* 3 = Mar, 4 = Apr, 5 = May, 6 = Jun, 7 = Jul, 8 = Aug, 9 = Sep, 10 = Oct, 11 = Nov */ + int endWhich; /* 1 = 1st, 2 = 2nd, 3 = 3rd, 4 = 4th, 5 = 5th */ + int endDay; /* 1 = Sun, 2 = Mon, 3 = Tue, 4 = Wed, 5 = Thu, 6 = Fri, 7 = Sat */ + int endMonth; /* 3 = Mar, 4 = Apr, 5 = May, 6 = Jun, 7 = Jul, 8 = Aug, 9 = Sep, 10 = Oct, 11 = Nov */ +} dstInfo_t; + +char *DaysOfWeek[] = +{ + "Zero", + "Sunday", + "Monday", + "Tuesday", + "Wednesday", + "Thursday", + "Friday", + "Saturday" +}; + +char *MonthsOfYear[] = +{ + "Zero", + "January", + "February", + "March", + "April", + "May", + "June", + "July", + "August", + "September", + "October", + "November", + "December" +}; + +char *Ordinals[] = +{ + "zero", + "first", + "second", + "third", + "fourth", + "last" +}; + +typedef enum +{ + TZ_NA_ATLA = 1, + TZ_NA_EAST, + TZ_NA_CENT, + TZ_NA_MOUN, + TZ_NA_PACI, + TZ_NA_ASKA, + TZ_NA_HAWI, + TZ_EU_UTC, + TZ_EU_CENT, + TZ_EU_EAST, + TZ_EU_MOSC, + TZ_AS_CHIN, + TZ_AS_JAPN, + TZ_AU_SYDN, + TZ_NZ_AUCK, +} tzCode_t; + +/* canned DST settings */ +dstInfo_t NA_DSTInfo = {2, 1, 3, 1, 1, 11}; /* 2nd Sun in Mar to 1st Sun in Nov */ +dstInfo_t EUR_DSTInfo = {5, 1, 3, 5, 1, 10}; /* last Sun in Mar to last Sun in Oct */ +dstInfo_t AUS_DSTInfo = {1, 1, 10, 1, 1, 4}; /* 1st Sun in Oct to 1st Sun in Apr */ +dstInfo_t NZ_DSTInfo = {5, 1, 9, 1, 1, 4}; /* last Sun in Sep to 1st Sun in Apr */ +dstInfo_t None_DSTInfo = {0, 0, 0, 0, 0, 0}; /* No DST in effect */ + + +#define NO_IP_ADDR "0.0.0.0" + +#define NOIPADDR(IpAddr) (strcpy(IpAddr, NO_IP_ADDR)) + +typedef struct chassisInfo_st +{ + char chassisIpAddr[20]; + char chassisSMKey[50]; +} chassisInfo_t; + +#define CHASSISINFOBLOCK 10 + +#endif /* CHASSISSETUP_H_INCLUDED */ diff --git a/IbaTools/disable_ports/Makefile b/IbaTools/disable_ports/Makefile new file mode 100644 index 0000000..1b7bf73 --- /dev/null +++ b/IbaTools/disable_ports/Makefile @@ -0,0 +1,162 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** +# Makefile for disable_ports + +# Include Make Control Settings +include $(TL_DIR)/$(PROJ_FILE_DIR)/Makesettings.project + +#=============================================================================# +# Definitions: +#-----------------------------------------------------------------------------# + +# Name of SubProjects +DS_SUBPROJECTS = +# name of executable or downloadable image +EXECUTABLE = #$(BUILDDIR)/disable_ports$(EXE_SUFFIX) +# list of sub directories to build +DIRS = +# C files (.c) +CFILES = \ + # Add more c files here +# C++ files (.cpp) +CCFILES = \ + # Add more cpp files here +# lex files (.lex) +LFILES = \ + # Add more lex files here +# archive library files (basename, $ARFILES will add MOD_LIB_DIR/prefix and suffix) +LIBFILES= +# Windows Resource Files (.rc) +RSCFILES = +# Windows IDL File (.idl) +IDLFILE = +# Windows Linker Module Definitions (.def) file for dll's +DEFFILE = +# targets to build during INCLUDES phase (add public includes here) +INCLUDE_TARGETS = \ + # Add more h hpp files here +# Non-compiled files +MISC_FILES = +# all source files +SOURCES = $(CFILES) $(CCFILES) $(LFILES) $(RSCFILES) $(IDLFILE) +# Source files to include in DSP File +DSP_SOURCES = $(INCLUDE_TARGETS) $(SOURCES) $(MISC_FILES) \ + $(RSCFILES) $(DEFFILE) $(MAKEFILE) +# all object files +OBJECTS = $(CFILES:.c=$(OBJ_SUFFIX)) $(CCFILES:.cpp=$(OBJ_SUFFIX)) \ + $(LFILES:.lex=$(OBJ_SUFFIX)) +RSCOBJECTS = $(RSCFILES:.rc=$(RES_SUFFIX)) +# targets to build during LIBS phase +LIB_TARGETS_IMPLIB = +LIB_TARGETS_ARLIB = # $(LIB_PREFIX)ResourceTest$(ARLIB_SUFFIX) +LIB_TARGETS_EXP = $(LIB_TARGETS_IMPLIB:$(ARLIB_SUFFIX)=$(EXP_SUFFIX)) +LIB_TARGETS_MISC = +# targets to build during CMDS phase +CMD_TARGETS_SHLIB = +CMD_TARGETS_EXE = $(EXECUTABLE) +CMD_TARGETS_MISC = opadisableports opaextractbadlinks opaextractsellinks opaextractmissinglinks opaextractlids opaenableports opaledports opadisablehosts +# files to remove during clean phase +CLEAN_TARGETS_MISC = +CLEAN_TARGETS = $(OBJECTS) $(RSCOBJECTS) $(IDL_TARGETS) $(CLEAN_TARGETS_MISC) +# other files to remove during clobber phase +CLOBBER_TARGETS_MISC= +# sub-directory to install to within bin +BIN_SUBDIR = +# sub-directory to install to within include +INCLUDE_SUBDIR = + +# Additional Settings +#CLOCALDEBUG = User defined C debugging compilation flags [Empty] +#CCLOCALDEBUG = User defined C++ debugging compilation flags [Empty] +#CLOCAL = User defined C flags for compiling [Empty] +#CCLOCAL = User defined C++ flags for compiling [Empty] +#BSCLOCAL = User flags for Browse File Builder [Empty] +#DEPENDLOCAL = user defined makedepend flags [Empty] +#LINTLOCAL = User defined lint flags [Empty] +#LOCAL_INCLUDE_DIRS = User include directories to search for C/C++ headers [Empty] +#LDLOCAL = User defined C flags for linking [Empty] +#IMPLIBLOCAL = User flags for Object Lirary Manager [Empty] +#MIDLLOCAL = User flags for IDL compiler [Empty] +#RSCLOCAL = User flags for resource compiler [Empty] +#LOCALDEPLIBS = User libraries to include in dependencies [Empty] +#LOCALLIBS = User libraries to use when linking [Empty] +# (in addition to LOCALDEPLIBS) +#LOCAL_LIB_DIRS = User library directories for libpaths [Empty] + +CLOCAL=$(CIBACCESS) $(CPIE) +LOCAL_INCLUDE_DIRS= +ifeq "$(IB_STACK)" "IBACCESS" +LOCALDEPLIBS=$(IBACCESS_USER_LIBS)IbPrint +LOCALLIBS= +LOCAL_LIB_DIRS=$(IBACCESS_USER_LIB_DIRS) +else +LOCALDEPLIBS=$(IBACCESS_USER_LIBS) IbPrint opamgt-priv +LOCALLIBS=$(OPENIB_USER_LIBS) +LOCAL_LIB_DIRS=$(OPENIB_USER_LIB_DIRS) $(IBACCESS_USER_LIB_DIRS) +endif + +# Include Make Rules definitions and rules +include $(TL_DIR)/IbaTools/Makerules.module + +#=============================================================================# +# Overrides: +#-----------------------------------------------------------------------------# +#CCOPT = # C++ optimization flags, default lets build config decide +#COPT = # C optimization flags, default lets build config decide +#SUBSYSTEM = Subsystem to build for (none, console or windows) [none] +# (Windows Only) +#USEMFC = How Windows MFC should be used (none, static, shared, no_mfc) [none] +# (Windows Only) +#=============================================================================# + +#=============================================================================# +# Rules: +#-----------------------------------------------------------------------------# +# process Sub-directories +include $(TL_DIR)/Makerules/Maketargets.toplevel + +# build cmds and libs +include $(TL_DIR)/Makerules/Maketargets.build + +# install for includes, libs and cmds phases +include $(TL_DIR)/Makerules/Maketargets.install + +# install for stage phase +#include $(TL_DIR)/Makerules/Maketargets.stage +STAGE:: + $(VS)$(STAGE_INSTALL) $(STAGE_INSTALL_DIR_OPT) $(PROJ_STAGE_FASTFABRIC_DIR) $(CMD_TARGETS_MISC) + +# Unit test execution +#include $(TL_DIR)/Makerules/Maketargets.runtest + +#=============================================================================# + +#=============================================================================# +# DO NOT DELETE THIS LINE -- make depend depends on it. +#=============================================================================# diff --git a/IbaTools/disable_ports/opadisablehosts.sh b/IbaTools/disable_ports/opadisablehosts.sh new file mode 100755 index 0000000..d5bf405 --- /dev/null +++ b/IbaTools/disable_ports/opadisablehosts.sh @@ -0,0 +1,158 @@ +#!/bin/bash +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + + +# [ICS VERSION STRING: unknown] + +# disable the specified set of hosts + +if [ -f /etc/opa/opafastfabric.conf ] +then + . /etc/opa/opafastfabric.conf +fi + +. /usr/lib/opa/tools/opafastfabric.conf.def + +. /usr/lib/opa/tools/ff_funcs + +tempfile="$(mktemp)" +trap "rm -f $tempfile; exit 1" SIGHUP SIGTERM SIGINT +trap "rm -f $tempfile" EXIT + +Usage_full() +{ + echo "Usage: opadisablehosts [-h hfi] [-p port] reason host ..." >&2 + echo " or" >&2 + echo " opadisablehosts --help" >&2 + echo " " >&2 + echo " --help - produce full help text" >&2 + echo " -h hfi - hfi, numbered 1..n, 0= -p port will be" >&2 + echo " a system wide port num (default is 0)" >&2 + echo " -p port - port, numbered 1..n, 0=1st active" >&2 + echo " (default is 1st active)" >&2 + echo " reason - text description of reason hosts are being disabled," >&2 + echo " will be saved in reason field of output file" >&2 + echo >&2 + echo "The -h and -p options permit a variety of selections:" >&2 + echo " -h 0 - 1st active port in system (this is the default)" >&2 + echo " -h 0 -p 0 - 1st active port in system " >&2 + echo " -h x - 1st active port on HFI x" >&2 + echo " -h x -p 0 - 1st active port on HFI x" >&2 + echo " -h 0 -p y - port y within system (irrespective of which ports are active)" >&2 + echo " -h x -p y - HFI x, port y" >&2 + echo >&2 + echo "Information about the links disabled will be written to a CSV file. By default">&2 + echo "this file is named $CONFIG_DIR/opa/disabled:hfi:port.csv where the hfi:port">&2 + echo "part of the file name is replaced by the HFI number and the port number being">&2 + echo "operated on (such as 1:1 or 2:1). This CSV file can be used as input to">&2 + echo "opaenableports. It is of the form:" >&2 + echo " NodeGUID;PortNum;NodeType;NodeDesc;NodeGUID;PortNum;NodeType;NodeDesc;Reason" >&2 + echo "For each listed link, the switch port closer to this is the one that has been" >&2 + echo "disabled." >&2 + echo >&2 + echo "for example:" >&2 + echo " opadisablehosts 'bad DRAM' compute001 compute045" >&2 + echo " opadisablehosts -h 1 -p 2 'crashed' compute001 compute045" >&2 + exit 0 +} + +Usage() +{ + echo "Usage: opadisablehosts [-h hfi] [-p port] reason host ..." >&2 + echo " or" >&2 + echo " opadisablehosts --help" >&2 + echo " " >&2 + echo " --help - produce full help text" >&2 + echo " -h hfi - hfi, numbered 1..n, 0= -p port will be" >&2 + echo " a system wide port num (default is 0)" >&2 + echo " -p port - port, numbered 1..n, 0=1st active" >&2 + echo " (default is 1st active)" >&2 + echo " reason - text description of reason hosts are being disabled," >&2 + echo " will be saved in reason field of output file" >&2 + echo >&2 + echo "for example:" >&2 + echo " opadisablehosts 'bad DRAM' compute001 compute045" >&2 + exit 2 +} + +if [ x"$1" = "x--help" ] +then + Usage_full +fi + +reason= +hfi=0 +port=0 +while getopts h:p: param +do + case $param in + h) hfi="$OPTARG";; + p) port="$OPTARG";; + ?) Usage;; + esac +done +shift $((OPTIND -1)) +if [ $# -lt 1 ] +then + Usage +fi +reason="$1" +shift + +if [ $# -lt 1 ] +then + Usage +fi + +if [ "$port" -eq 0 ] +then + port_opts="-h $hfi" # default port to 1st active +else + port_opts="-h $hfi -p $port" +fi + +# loop for each host +# this could be more efficient, but for a small list of hosts its ok +res=0 +for i in "$@" +do + echo "=============================================================================" + echo "Disabling host: $i..." + /usr/sbin/opaextractsellinks $port_opts -F "nodepat:$i hfi*" > $tempfile + if [ ! -s $tempfile ] + then + echo "opadisablehosts: Unable to find host: $i" >&2 + res=1 + else + /usr/sbin/opadisableports -h $hfi -p $port "$reason" < $tempfile + fi + rm -f $tempfile +done +exit $res diff --git a/IbaTools/disable_ports/opadisableports.sh b/IbaTools/disable_ports/opadisableports.sh new file mode 100755 index 0000000..aa6a2cc --- /dev/null +++ b/IbaTools/disable_ports/opadisableports.sh @@ -0,0 +1,371 @@ +#!/bin/bash +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2018, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + + +# [ICS VERSION STRING: unknown] + +# disable the specified set of ports + + +# optional override of defaults +if [ -f /etc/opa/opafastfabric.conf ] +then + . /etc/opa/opafastfabric.conf +fi + +. /usr/lib/opa/tools/opafastfabric.conf.def + +. /usr/lib/opa/tools/ff_funcs + +lidmap="$(mktemp --tmpdir lidmapXXXXXX)" +trap "rm -f $lidmap; exit 1" SIGHUP SIGTERM SIGINT +trap "rm -f $lidmap" EXIT + +Usage_full() +{ + echo "Usage: opadisableports [-R] [-h hfi] [-p port] [reason] < disable.csv" >&2 + echo " or" >&2 + echo " opadisableports --help" >&2 + echo " --help - produce full help text" >&2 + echo " -R - do not attempt to get routes for computation of distance" >&2 + echo " instead just disable switch port with lower LID assuming" >&2 + echo " that will be closer to this node" >&2 + echo " -h hfi - hfi, numbered 1..n, 0= -p port will be a system wide port num" >&2 + echo " (default is 0)" >&2 + echo " -p port - port, numbered 1..n, 0=1st active (default is 1st active)" >&2 + echo " reason - optional text description of reason ports are being disabled," >&2 + echo " will be saved in the reason field of the output file" >&2 + echo >&2 + echo "The -h and -p options permit a variety of selections:" >&2 + echo " -h 0 - 1st active port in system (this is the default)" >&2 + echo " -h 0 -p 0 - 1st active port in system" >&2 + echo " -h x - 1st active port on HFI x" >&2 + echo " -h x -p 0 - 1st active port on HFI x" >&2 + echo " -h 0 -p y - port y within system (irrespective of which ports are active)" >&2 + echo " -h x -p y - HFI x, port y" >&2 + + echo >&2 + echo "The disable.csv is an input file listing the links to disable. It is of the" >&2 + echo "form:" >&2 + echo " NodeGUID;PortNum;NodeType;NodeDesc;NodeGUID;PortNum;NodeType;NodeDesc;Reason" >&2 + echo "For each listed link, the switch port closer to this node will be disabled." >&2 + echo "The Reason field is optional." >&2 + echo "An input file such as this can be generated by opaextractbadlinks or" >&2 + echo "opaextractsellinks." >&2 + echo >&2 + echo "Information about the links disabled (and the reason) will be saved (in same">&2 + echo "format) to an output file named $CONFIG_DIR/opa/disabled:hfi:port.csv where">&2 + echo "the hfi:port part of the file name is replaced by the HFI number and the port">&2 + echo "number being operated on (such as 1:1 or 2:1). This CSV file can be used as">&2 + echo "input to opaenableports." >&2 + echo >&2 + echo "for example:" >&2 + echo " opadisableports 'bad cable' < disable.csv" >&2 + echo " opadisableports -h 1 -p 1 'dead servers' < disable.csv" >&2 + echo " opaextractsellinks -F lid:3 | opadisableports 'bad server'" >&2 + echo " opaextractmissinglinks -T /etc/opa/topology.0:0.xml | opadisableports" >&2 + exit 0 +} + +Usage() +{ + echo "Usage: opadisableports [-R] [-h hfi] [-p port] [reason] < disable.csv" >&2 + echo " or" >&2 + echo " opadisableports --help" >&2 + echo " --help - produce full help text" >&2 + echo " -R - do not attempt to get routes for computation of distance" >&2 + echo " instead just disable switch port with lower LID assuming" >&2 + echo " that will be closer to this node" >&2 + echo " -h hfi - hfi, numbered 1..n, 0= -p port will be a system wide port num" >&2 + echo " (default is 0)" >&2 + echo " -p port - port, numbered 1..n, 0=1st active (default is 1st active)" >&2 + echo " reason - optional text description of reason ports are being disabled," >&2 + echo " will be saved in the reason field of the output file" >&2 + echo >&2 + echo "disable.csv is an input file listing the links to disable." >&2 + echo "It is of the form:" >&2 + echo " NodeGUID;PortNum;NodeType;NodeDesc;NodeGUID;PortNum;NodeType;NodeDesc;Reason" >&2 + echo "For each listed link, the switch port closer to this node will be disabled." >&2 + echo "The Reason field is optional.">&2 + echo "An input file such as this can be generated by opaextractbadlinks or" >&2 + echo "opaextractsellinks." >&2 + echo >&2 + echo "Information about the links disabled (and the reason) will be saved (in same">&2 + echo "format) to an output file named $CONFIG_DIR/opa/disabled:hfi:port.csv where">&2 + echo "the hfi:port part of the file name is replaced by the HFI number and the port">&2 + echo "number being operated on (such as 1:1 or 2:1)." >&2 + echo >&2 + echo "for example:" >&2 + echo " opadisableports 'bad cable' < disable.csv" >&2 + exit 2 +} + +if [ x"$1" = "x--help" ] +then + Usage_full +fi + +res=0 +reason= +reason_csv= +use_distance=y +hfi_input=0 +port_input=0 + +while getopts Rh:p: param +do + case $param in + R) use_distance=n;; + p) port_input="$OPTARG";; + h) hfi_input="$OPTARG";; + ?) Usage;; + esac +done +shift $((OPTIND -1)) +if [ $# -ge 1 ] +then + reason="$1" + reason_csv=";$1" # add field separator + shift +fi +if [ $# -ge 1 ] +then + Usage +fi + +/usr/sbin/oparesolvehfiport $hfi_input $port_input &>/dev/null +if [ $? -ne 0 -o "$hfi_input" = "" -o "$port_input" = "" ] +then + echo "opadisableports: Error: Invalid port specification: $hfi_input:$port_input" >&2 + exit 1 +fi + +hfi=$(/usr/sbin/oparesolvehfiport $hfi_input $port_input -o hfinum) +port=`echo $(/usr/sbin/oparesolvehfiport $hfi_input $port_input | cut -f 2 -d ':')` +port_opts="-h $hfi -p $port" + +lookup_lid_by_guid_port() +{ + local nodeguid="$1" + local portnum="$2" + local guid dport type desc lid + + grep "^$nodeguid;$portnum;" < $lidmap|while read guid dport type desc lid + do + echo -n $lid + done +} +lookup_guid_by_desc_port() +{ + local nodedesc="$1" + local portnum="$2" + + local guid dport type desc lid + + grep "^[^;]*;$portnum;[^;]*;$nodedesc;[^;]*" < $lidmap | while read guid dport type desc lid + do + echo -n $guid + return + done +} + +get_distance() +{ + local lid=$1 + local portguid + + if [ "$use_distance" = n ] + then + echo "0" + else + portguid=$(eval opasaquery $port_opts -o portguid -l $lid) + eval opasaquery $port_opts -o trace -g $portguid|grep -c "NodeType:" + fi +} + +disable_ports() +{ + suffix=":$hfi:$port" + + # generate lidmap + /usr/sbin/opaextractlids $port_opts > $lidmap + if [ ! -s $lidmap ] + then + echo "opadisableports: Unable to determine fabric lids" >&2 + rm -f $lidmap + return 1 + fi + + disabled=0 + skipped=0 + failed=0 + IFS=';' + while read nodeguid1 port1 type1 desc1 nodeguid2 port2 type2 desc2 rest + do + # For non ISLs pick the switch side, so we can reenable later + if [ "$type1" = SW -a "$type2" != SW ] + then + if [ -z "$nodeguid1" ] + then + nodeguid1=$(lookup_guid_by_desc_port "$desc1" 0) + fi + lid=$(lookup_lid_by_guid_port $nodeguid1 0) + distance=$(get_distance $lid) + echo "$distance;$lid;$nodeguid1;$port1;$type1;$desc1;$nodeguid2;$port2;$type2;$desc2;$rest" + elif [ "$type1" != SW -a "$type2" = SW ] + then + if [ -z "$nodeguid2" ] + then + nodeguid2=$(lookup_guid_by_desc_port "$desc2" 0) + fi + lid=$(lookup_lid_by_guid_port $nodeguid2 0) + distance=$(get_distance $lid) + echo "$distance;$lid;$nodeguid2;$port2;$type2;$desc2;$nodeguid1;$port1;$type1;$desc1;$rest" + else + # determine which side of ISL to disable + if [ -z "$nodeguid1" ] + then + nodeguid1=$(lookup_guid_by_desc_port "$desc1" 0) + fi + if [ -z "$nodeguid2" ] + then + nodeguid2=$(lookup_guid_by_desc_port "$desc2" 0) + fi + lid1=$(lookup_lid_by_guid_port $nodeguid1 0) + lid2=$(lookup_lid_by_guid_port $nodeguid2 0) + if [ x"$lid1" != x -a x"$lid2" = x ] + then + # might be a re-disable case, use the LID we can still resolve + distance=$(get_distance $lid1) + echo "$distance;$lid1;$nodeguid1;$port1;$type1;$desc1;$nodeguid2;$port2;$type2;$desc2;$rest" + elif [ x"$lid1" = x -a x"$lid2" != x ] + then + # might be a re-disable case, use the LID we can still resolve + distance=$(get_distance $lid2) + echo "$distance;$lid2;$nodeguid2;$port2;$type2;$desc2;$nodeguid1;$port1;$type1;$desc1;$rest" + elif [ x"$lid1" = x -a x"$lid2" = x ] + then + # can't resolve + lid= + echo "0;;$nodeguid1;$port1;$type1;$desc1;$nodeguid2;$port2;$type2;$desc2;$rest" + else + distance1=$(get_distance $lid1) + distance2=$(get_distance $lid2) + if [ $(( $distance1 )) -lt $(( $distance2 )) ] + then + # pick side closer to FM + echo "$distance1;$lid1;$nodeguid1;$port1;$type1;$desc1;$nodeguid2;$port2;$type2;$desc2;$rest" + elif [ $(( $lid1 )) -eq $(( $lid2 )) ] + then + # this implies a switch is connected to itself + # atypical config, for completeness pick lower port number + if [ $(( $port1 )) -le $(( $port2 )) ] + then + echo "$distance1;$lid1;$nodeguid1;$port1;$type1;$desc1;$nodeguid2;$port2;$type2;$desc2;$rest" + else + echo "$distance2;$lid2;$nodeguid2;$port2;$type2;$desc2;$nodeguid1;$port1;$type1;$desc1;$rest" + fi + elif [ $(( $distance1 )) -eq $(( $distance2 )) ] + then + # two LIDs of an ISL are equal distance? + # not expected, but for completeness, pick lower LID + # as a tie breaker and assume it might be closer to FM + # LID == tested above, but use -le to be paranoid + if [ $(( $lid1 )) -le $(( $lid2 )) ] + then + echo "$distance1;$lid1;$nodeguid1;$port1;$type1;$desc1;$nodeguid2;$port2;$type2;$desc2;$rest" + else + echo "$distance2;$lid2;$nodeguid2;$port2;$type2;$desc2;$nodeguid1;$port1;$type1;$desc1;$rest" + fi + else + # pick side closer to FM + echo "$distance2;$lid2;$nodeguid2;$port2;$type2;$desc2;$nodeguid1;$port1;$type1;$desc1;$rest" + fi + fi + fi + done | if [ "$use_distance" = y ] + then + sort -r -n -t ';' -k 1 # do furthest from this node first + else + cat # do in order of input file + fi | + { + while read distance lid guid dport type desc lguid lport ltype ldesc rest + do + if [ x"$rest" != x ] + then + rest=";$rest" # add field separator + fi + + if [ x"$lid" = x ] + then + echo "Skipping link: $desc:$dport -> $ldesc:$lport" + skipped=$(( $skipped + 1)) + else + echo "Disabling link: $desc:$dport -> $ldesc:$lport" + eval /usr/sbin/opaportconfig $port_opts -l $lid -m $dport disable + + if [ $? = 0 ] + then + logger -p user.err "Disabled link: $desc:$dport -> $ldesc:$lport due to: $reason" + disabled=$(( $disabled + 1)) + if [ ! -e $CONFIG_DIR/opa/disabled$suffix.csv ] || ! grep "^$guid;$dport;" < $CONFIG_DIR/opa/disabled$suffix.csv > /dev/null 2>&1 + then + # keep a disabled file per local hfi:port + # same format as our input but 1st port + # indicates which one was disabled and + # second port is only for info + # if fed back into this tool will select + # same port to disable + echo "$guid;$dport;$type;$desc;$lguid;$lport;$ltype;$ldesc$rest$reason_csv" >> $CONFIG_DIR/opa/disabled$suffix.csv + fi + else + failed=$(( $failed + 1)) + fi + fi + done + if [ $failed -eq 0 ] + then + echo "Disabled: $disabled; Skipped: $skipped" + return 0 + else + echo "Disabled: $disabled; Skipped: $skipped; Failed: $failed" + return 1 + fi + } +} + +disable_ports "$hfi" "$port" +if [ $? -ne 0 ] +then + res=1 +fi + +exit $res diff --git a/IbaTools/disable_ports/opaenableports.sh b/IbaTools/disable_ports/opaenableports.sh new file mode 100755 index 0000000..8c9c695 --- /dev/null +++ b/IbaTools/disable_ports/opaenableports.sh @@ -0,0 +1,214 @@ +#!/bin/bash +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + + +# [ICS VERSION STRING: unknown] + +# reenable the specified set of ports + +# optional override of defaults +if [ -f /etc/opa/opafastfabric.conf ] +then + . /etc/opa/opafastfabric.conf +fi + +. /usr/lib/opa/tools/opafastfabric.conf.def + +. /usr/lib/opa/tools/ff_funcs + +tempfile="$(mktemp)" +lidmap="$(mktemp --tmpdir lidmapXXXXXX)" +trap "rm -f $tempfile; rm -f $lidmap; exit 1" SIGHUP SIGTERM SIGINT +trap "rm -f $tempfile; rm -f $lidmap" EXIT + +Usage_full() +{ + echo "Usage: opaenableports [-h hfi] [-p port] < disabled.csv" >&2 + echo " or" >&2 + echo " opaenableports --help" >&2 + echo " --help - produce full help text" >&2 + echo " -h hfi - hfi, numbered 1..n, 0= -p port will be a system wide port num" >&2 + echo " (default is 0)" >&2 + echo " -p port - port, numbered 1..n, 0=1st active (default is 1st active)" >&2 + echo >&2 + echo "The -h and -p options permit a variety of selections:" >&2 + echo " -h 0 - 1st active port in system (this is the default)" >&2 + echo " -h 0 -p 0 - 1st active port in system" >&2 + echo " -h x - 1st active port on HFI x" >&2 + echo " -h x -p 0 - 1st active port on HFI x" >&2 + echo " -h 0 -p y - port y within system (irrespective of which ports are active)" >&2 + echo " -h x -p y - HFI x, port y" >&2 + echo >&2 + echo "disabled.csv is an input file listing the ports to enable." >&2 + echo "It is of the form:" >&2 + echo " NodeGUID;PortNum;NodeType;NodeDesc;Ignored" >&2 + echo "An input file such as this is generated in $CONFIG_DIR/opa/disabled*.csv" >&2 + echo "by opadisableports." >&2 + echo "for example:" >&2 + echo " opaenableports < disabled.csv" >&2 + echo " opaenableports < $CONFIG_DIR/opa/disabled:1:1.csv" >&2 + echo " opaenableports -h 1 -p 1 < disabled.csv" >&2 + exit 0 +} + +Usage() +{ + echo "Usage: opaenableports [-h hfi] [-p port] < disabled.csv" >&2 + echo " or" >&2 + echo " opaenableports --help" >&2 + echo " --help - produce full help text" >&2 + echo " -h hfi - hfi, numbered 1..n, 0= -p port will be a system wide port num" >&2 + echo " (default is 0)" >&2 + echo " -p port - port, numbered 1..n, 0=1st active (default is 1st active)" >&2 + echo >&2 + echo "disabled.csv is a file listing the ports to enable." >&2 + echo "It is of the form:" >&2 + echo " NodeGUID;PortNum;NodeType;NodeDesc;Ignored" >&2 + echo "An input file such as this is generated in $CONFIG_DIR/opa/disabled*.csv" >&2 + echo "by opadisableports." >&2 + echo "for example:" >&2 + echo " opaenableports < disabled.csv" >&2 + exit 2 +} + +if [ x"$1" = "x--help" ] +then + Usage_full +fi + +res=0 +hfi_input=0 +port_input=0 + +while getopts h:p: param +do + case $param in + p) port_input="$OPTARG";; + h) hfi_input="$OPTARG";; + ?) Usage;; + esac +done +shift $((OPTIND -1)) +if [ $# -ge 1 ] +then + Usage +fi + +/usr/sbin/oparesolvehfiport $hfi_input $port_input &>/dev/null +if [ $? -ne 0 -o "$hfi_input" = "" -o "$port_input" = "" ] +then + echo "opaenableports: Error: Invalid port specification: $hfi_input:$port_input" >&2 + exit 1 +fi + +hfi=$(/usr/sbin/oparesolvehfiport $hfi_input $port_input -o hfinum) +port=`echo $(/usr/sbin/oparesolvehfiport $hfi_input $port_input | cut -f 2 -d ':')` +port_opts="-h $hfi -p $port" + +lookup_lid() +{ + local nodeguid="$1" + local portnum="$2" + local guid dport type desc lid + + grep "^$nodeguid;$portnum;" < $lidmap|while read guid dport type desc lid + do + echo -n $lid + done +} + + +enable_ports() +{ + enabled=0 + failed=0 + skipped=0 + suffix=":$hfi:$port" + + # generate lidmap + /usr/sbin/opaextractlids $port_opts > $lidmap + if [ ! -s $lidmap ] + then + echo "opaenableports: Unable to determine fabric lids" >&2 + rm -f $lidmap + return 1 + fi + + IFS=';' + while read nodeguid dport type desc rest + do + lid=$(lookup_lid $nodeguid 0) + if [ x"$lid" = x ] + then + echo "Skipping port: $desc:$dport: Device not found in fabric" + skipped=$(( $skipped + 1)) + else + echo "Enabling port: $desc:$dport" + eval /usr/sbin/opaportconfig $port_opts -l $lid -m $dport enable + + if [ $? = 0 ] + then + logger -p user.err "Enabled port: $desc:$dport" + if [ -e $CONFIG_DIR/opa/disabled$suffix.csv ] + then + # remove from disabled ports + grep -v "^$nodeguid;$dport;" < $CONFIG_DIR/opa/disabled$suffix.csv > $tempfile + mv $tempfile $CONFIG_DIR/opa/disabled$suffix.csv + fi + enabled=$(( $enabled + 1)) + else + failed=$(( $failed + 1)) + fi + fi + done + if [ $skipped -ne 0 ] + then + echo "For Skipped ports, either the device is now offline or the other end of the" + echo "link was disabled and the device is no longer accessible in-band." + echo "The end of the link previously disabled by opedisableports or opadisablehosts" + echo "can be found in $CONFIG_DIR/opa/disabled$suffix.csv" + fi + if [ $failed -eq 0 ] + then + echo "Enabled: $enabled; Skipped: $skipped" + return 0 + else + echo "Enabled: $enabled; Skipped: $skipped; Failed: $failed" + return 1 + fi +} + +enable_ports "$hfi" "$port" +if [ $? -ne 0 ] +then + res=1 +fi + +exit $res diff --git a/IbaTools/disable_ports/opaextractbadlinks.sh b/IbaTools/disable_ports/opaextractbadlinks.sh new file mode 100755 index 0000000..48072ae --- /dev/null +++ b/IbaTools/disable_ports/opaextractbadlinks.sh @@ -0,0 +1,108 @@ +#!/bin/bash +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] + +# Run opareports and pipe output to opaxmlextract to extract +# links with excessive errors + +tempfile="$(mktemp)" +trap "rm -f $tempfile; exit 1" SIGHUP SIGTERM SIGINT +trap "rm -f $tempfile" EXIT + +cmd=`basename $0` +Usage_full() +{ + echo >&2 + echo "Usage: ${cmd} [--help]|[opareport options]" >&2 + echo " --help - produce full help text" >&2 + echo " [opareport options] - options will be passed to opareport." >&2 + echo >&2 + echo "${cmd} is a front end to the opareport tool that generates" >&2 + echo "a report listing all or some of the links that have exceeded the error threshold." >&2 + echo "The output is in a CSV format suitable for importing into a spreadsheet" >&2 + echo "or parsed by other scripts." >&2 + echo >&2 + echo "for example:" >&2 + echo " List all the bad links in the fabric:" >&2 + echo " ${cmd}" >&2 + echo >&2 + echo " List all the bad links to a switch named \"coresw1\":" >&2 + echo " ${cmd} -F \"node:coresw1\"" >&2 + echo >&2 + echo " List all the bad links to end-nodes:" >&2 + echo " ${cmd} -F \"nodetype:FI\"" >&2 + echo >&2 + echo " List all the bad links on the 2nd HFI's fabric of a multi-plane fabric:" >&2 + echo " ${cmd} -h 2" >&2 + echo >&2 + echo "See the man page for \"opareport\" for the full set of options." >&2 + echo "By design, the tool ignores \"-o/--output\" report option." >&2 + echo >&2 + exit 0 +} + +Usage() +{ + echo >&2 + echo "Usage: ${cmd} [--help]|[opareport options]" >&2 + echo " --help - produce full help text" >&2 + echo " [opareport options] - options will be passed to opareport." >&2 + echo >&2 +} + +if [ x"$1" = "x--help" ] +then + Usage_full +fi + +line1= +# we do this against a single fabric, options can select a local HFI and Port +/usr/sbin/opareport -o errors -x -Q "$@" > $tempfile +if [ -s $tempfile ] +then + cat $tempfile| /usr/sbin/opaxmlextract -H -d \; -e LinkErrors.Link.Port.NodeGUID -e LinkErrors.Link.Port.PortNum -e LinkErrors.Link.Port.NodeType -e LinkErrors.Link.Port.NodeDesc|while read line + do + if [ x"$line1" = x ] + then + line1="$line" + else + echo "$line1;$line" + line1= + fi + done + res=0 +else + echo "${cmd}: Unable to get error report" >&2 + Usage + res=1 +fi +rm -f $tempfile +exit $res diff --git a/IbaTools/disable_ports/opaextractlids.sh b/IbaTools/disable_ports/opaextractlids.sh new file mode 100755 index 0000000..109ca08 --- /dev/null +++ b/IbaTools/disable_ports/opaextractlids.sh @@ -0,0 +1,95 @@ +#!/bin/bash +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] + +# Run opareport pipe output to opaxmlextract to extract lids to a csv file + +tempfile="$(mktemp)" +trap "rm -f $tempfile; exit 1" SIGHUP SIGTERM SIGINT +trap "rm -f $tempfile" EXIT + +cmd=`basename $0` +Usage_full() +{ + echo >&2 + echo "Usage: ${cmd} [--help]|[opareport options]" >&2 + echo " --help - produce full help text" >&2 + echo " [opareport options] - options will be passed to opareport." >&2 + echo >&2 + echo "${cmd} is a front end to the opareport tool that generates" >&2 + echo "a report listing all or some of the lids in the fabric." >&2 + echo "The output is in a CSV format suitable for importing into a spreadsheet" >&2 + echo "or parsed by other scripts." >&2 + echo >&2 + echo "for example:" >&2 + echo " List all the lids in the fabric:" >&2 + echo " ${cmd}" >&2 + echo >&2 + echo " List all the lids of end-nodes:" >&2 + echo " ${cmd} -F \"nodetype:FI\"" >&2 + echo >&2 + echo " List all the lids on the 2nd HFI's fabric of a multi-plane fabric:" >&2 + echo " ${cmd} -h 2" >&2 + echo >&2 + echo "See the man page for \"opareport\" for the full set of options." >&2 + echo "By design, the tool ignores \"-o/--output\" report option." >&2 + echo >&2 + exit 0 +} + +Usage() +{ + echo >&2 + echo "Usage: ${cmd} [--help]|[opareport options]" >&2 + echo " --help - produce full help text" >&2 + echo " [opareport options] - options will be passed to opareport." >&2 + echo >&2 +} + +if [ x"$1" = "x--help" ] +then + Usage_full +fi + +IFS=';' +/usr/sbin/opareport -o lids -x -Q "$@" > $tempfile +if [ -s $tempfile ] +then + cat $tempfile | /usr/sbin/opaxmlextract -H -d \; -e LIDSummary.LIDs.Value.NodeGUID -e LIDSummary.LIDs.Value.PortNum -e LIDSummary.LIDs.Value.NodeType -e LIDSummary.LIDs.Value.NodeDesc -e LIDSummary.LIDs.Value:LID + res=0 +else + echo "${cmd}: Unable to get lids report" >&2 + Usage + res=1 +fi + +rm -f $tempfile +exit $res diff --git a/IbaTools/disable_ports/opaextractmissinglinks.sh b/IbaTools/disable_ports/opaextractmissinglinks.sh new file mode 100755 index 0000000..292d641 --- /dev/null +++ b/IbaTools/disable_ports/opaextractmissinglinks.sh @@ -0,0 +1,206 @@ +#!/bin/bash +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] + +# Run opareports and pipe output to opaxmlextract to extract +# specified missing links + +tempfile="$(mktemp)" +trap "rm -f $tempfile; exit 1" SIGHUP SIGTERM SIGINT +trap "rm -f $tempfile" EXIT + +# Default values +topology_input=/etc/opa/topology.0:0.xml +otype=verifylinks + +topology_args="-T $topology_input" +otype_args="-o $otype" + +cmd=`basename $0` +Usage_full() +{ + echo >&2 + echo "Usage: ${cmd} [-T topology_input] [-o report] [--help]|[opareport options]" >&2 + echo " --help - produce full help text" >&2 + echo " -T - topology file to verify against" >&2 + echo " [Default: \"/etc/opa/topology.0:0.xml\"]" >&2 + echo " -o - output report type [Default: \"verifylinks\"]" >&2 + echo " verifylinks - verify links against topology input" >&2 + echo " verifyextlinks - verify links against topology input" >&2 + echo " limit analysis to links external to systems" >&2 + echo " verifyfilinks - verify links against topology input" >&2 + echo " limit analysis to FI links" >&2 + echo " verifyislinks - verify links against topology input" >&2 + echo " limit analysis to inter-switch links" >&2 + echo " verifyextislinks - verify links against topology input" >&2 + echo " limit analysis to inter-switch links external to systems" >&2 + echo " [opareport options] - options will be passed to opareport." >&2 + echo >&2 + echo "${cmd} is a front end to the opareport tool that generates" >&2 + echo "a report listing all or some of the links that are present in the supplied" >&2 + echo "topology file, but are missing in the fabric. The output is in a CSV format" >&2 + echo "suitable for importing into a spreadsheet or parsed by other scripts." >&2 + echo >&2 + echo "for example:" >&2 + echo " List all the missing links in the fabric:" >&2 + echo " ${cmd}" >&2 + echo >&2 + echo " List all the missing links to a switch named \"coresw1\":" >&2 + echo " ${cmd} -T topology.0:0.xml -F \"node:coresw1\"" >&2 + echo >&2 + echo " List all the missing connections to end-nodes:" >&2 + echo " ${cmd} -o verifyfilinks" >&2 + echo >&2 + echo " List all the missing links on the 2nd HFI's fabric of a multi-plane fabric:" >&2 + echo " ${cmd} -h 2 -T /etc/opa/topology.2:1.xml" >&2 + echo >&2 + echo " List all the missing links between two switches:" >&2 + echo " ${cmd} -o verifyislinks -T topology.0:0.xml" >&2 + echo >&2 + echo "See the man page for \"opareport\" for the full set of options." >&2 + echo >&2 + exit 0 +} + +Usage() +{ + echo >&2 + echo "Usage: ${cmd} [-T topology_input] [-o report] [--help]|[opareport options]" >&2 + echo " --help - produce full help text" >&2 + echo " -T - topology file to verify against" >&2 + echo " [Default: \"/etc/opa/topology.0:0.xml\"]" >&2 + echo " -o - output report type [Default: \"verifylinks\"]" >&2 + echo " verifylinks, verifyextlinks, verifyfilinks, verifyislinks, verifyextislinks" >&2 + echo " [opareport options] - options will be passed to opareport." >&2 + echo >&2 +} + +if [ x"$1" = "x--help" ] +then + Usage_full +fi + +# Check argument list +while getopts ":T:o:" param +do + case "${param}" in + T) topology_input=${OPTARG} + topology_args= + ;; + o) + otype=${OPTARG} + otype_args= + ;; + *) ;; + esac +done + +# Parse and verify otype while setting XML_PREFIX +case $otype in +verifyextislinks)XML_PREFIX=VerifyExtISLinks;; +verifyextlinks)XML_PREFIX=VerifyExtLinks;; +verifyislinks)XML_PREFIX=VerifyISLinks;; +verifyfilinks)XML_PREFIX=VerifyFILinks;; +verifylinks|verifyall)XML_PREFIX=VerifyLinks;; +*) + echo "${cmd}: Please supply a supported output report type: $otype" >&2 + echo " [verifyextislinks, verifyextlinks, verifyislinks, verifyfilinks," >&2 + echo " verifylinks, and verifyall]. Default is \"verifylinks\"" >&2 + Usage + exit 1;; +esac + +# Verify Topology file argument is supplied +if [ -z "$topology_input" ]; then + echo "${cmd}: Topology file must be provided to verify against" >&2 + Usage + exit 1 +fi + +# Verify Topology file exists +if [ ! -f "$topology_input" ]; then + echo "${cmd}: Topology file not found: \"$topology_input\"" >&2 + Usage + exit 1 +fi + +line1= +line2= +# we do this against a single fabric, options can select a local HFI and Port +/usr/sbin/opareport ${otype_args} ${topology_args} -x -Q "$@" > $tempfile +if [ -s $tempfile ] +then + IFS=';' + cat $tempfile | /usr/sbin/opaxmlextract -H -d \; -e ${XML_PREFIX}.Link.Port.NodeGUID \ + -e ${XML_PREFIX}.Link.Port.PortNum -e ${XML_PREFIX}.Link.Port.NodeType \ + -e ${XML_PREFIX}.Link.Port.NodeDesc -e ${XML_PREFIX}.Link.Problem \ + | while read guid port type desc problem + do + if [ -z "$line1" -a -z "$problem" ] + # if current line is 1st half of link and not a problem + then + # Port 1 if LINK: 'NodeGUID;PortNum;NodeType;NodeDesc;' + line1="${guid};${port};${type};${desc};" + + elif [ -z "$line2" -a -z "$problem" ] + # if current line is 2nd half of link and not a problem + then + # Port 2 if LINK: 'NodeGUID;PortNum;NodeType;NodeDesc;' + line2="${guid};${port};${type};${desc};" + + elif [ "$problem" == "Missing Link" -a "$line1" -a "$line2" ] + # if current line is the Missing Link Problem and other data exists + then + # echo LINK and clear temp variables + echo "${line1}${line2}Missing Link" + line1= + line2= + + elif [ "$problem" ] + # if current line is a Link.Problem, but not "Missing Link", then skip over + then + continue + else + # else None of the Link.Problems were "Missing Link", + # Reset temp variables and set current line to 1st port of link + line1="${guid};${port};${type};${desc};" + line2= + fi + done + res=0 +else + echo "${cmd}: Unable to find specified missing links" >&2 + Usage + res=1 +fi +rm -f $tempfile +exit $res + diff --git a/IbaTools/disable_ports/opaextractsellinks.sh b/IbaTools/disable_ports/opaextractsellinks.sh new file mode 100755 index 0000000..322d12e --- /dev/null +++ b/IbaTools/disable_ports/opaextractsellinks.sh @@ -0,0 +1,109 @@ +#!/bin/bash +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] + +# Run opareports and pipe output to opaxmlextract to extract +# specified links + +tempfile="$(mktemp)" +trap "rm -f $tempfile; exit 1" SIGHUP SIGTERM SIGINT +trap "rm -f $tempfile" EXIT + +cmd=`basename $0` +Usage_full() +{ + echo >&2 + echo "Usage: ${cmd} [--help]|[opareport options]" >&2 + echo " --help - produce full help text" >&2 + echo " [opareport options] - options will be passed to opareport." >&2 + echo >&2 + echo "${cmd} is a front end to the opareport tool that generates" >&2 + echo "a report listing all or some of the links in the fabric in a CSV format" >&2 + echo "suitable for importing into a spreadsheet or parsed by other scripts." >&2 + echo >&2 + echo "for example:" >&2 + echo " List all the links in the fabric:" >&2 + echo " ${cmd}" >&2 + echo >&2 + echo " List all the links to a switch named \"coresw1\":" >&2 + echo " ${cmd} -F \"node:coresw1\"" >&2 + echo >&2 + echo " List all the connections to end-nodes:" >&2 + echo " ${cmd} -F \"nodetype:FI\"" >&2 + echo >&2 + echo " List all the links on the 2nd HFI's fabric of a multi-plane fabric:" >&2 + echo " ${cmd} -h 2" >&2 + echo >&2 + echo "See the man page for \"opareport\" for the full set of options." >&2 + echo "By design, the tool ignores \"-o/--output\" report option." >&2 + echo >&2 + exit 0 +} + +Usage() +{ + echo >&2 + echo "Usage: ${cmd} [--help]|[opareport options]" >&2 + echo " --help - produce full help text" >&2 + echo " [opareport options] - options will be passed to opareport." >&2 + echo >&2 +} + +if [ x"$1" = "x--help" ] +then + Usage_full +fi + +line1= +# we do this against a single fabric, options can select a local HFI and Port +/usr/sbin/opareport -o links -x -Q "$@" > $tempfile +if [ -s $tempfile ] +then + cat $tempfile| /usr/sbin/opaxmlextract -H -d \; -e LinkSummary.Link.Port.NodeGUID -e LinkSummary.Link.Port.PortNum -e LinkSummary.Link.Port.NodeType -e LinkSummary.Link.Port.NodeDesc|while read line + do + if [ x"$line1" = x ] + then + # 1st port in given link + line1="$line" + else + # 2nd port in given link, output a single line for given link + echo "$line1;$line" + line1= + fi + done + res=0 +else + echo "${cmd}: Unable to find specified links" >&2 + Usage + res=1 +fi +rm -f $tempfile +exit $res diff --git a/IbaTools/disable_ports/opaledports.sh b/IbaTools/disable_ports/opaledports.sh new file mode 100755 index 0000000..fab7c5d --- /dev/null +++ b/IbaTools/disable_ports/opaledports.sh @@ -0,0 +1,270 @@ +#!/bin/bash +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + + +# [ICS VERSION STRING: unknown] + +# optional override of defaults +if [ -f /etc/opa/opafastfabric.conf ] +then + . /etc/opa/opafastfabric.conf +fi + +. /usr/lib/opa/tools/opafastfabric.conf.def + +. /usr/lib/opa/tools/ff_funcs + +#Temporary lidmap setup +lidmap="$(mktemp --tmpdir lidmapXXXXXX)" +trap "rm -f $lidmap; exit 1" SIGHUP SIGTERM SIGINT +trap "rm -f $lidmap" EXIT + +Usage_full() +{ + echo "Usage: opaledports [-h hfi] [-p port] [-s|-d] [on|off] < portlist.csv" >&2 + echo " or" >&2 + echo " opaledports [-h hfi] [-p port] [-C]" >&2 + echo " or" >&2 + echo " opaledports --help" >&2 + echo >&2 + echo " --help - produce full help text" >&2 + echo " -h hfi - hfi, numbered 1..n, 0= -p port will be a system wide port num" >&2 + echo " (default is 0)" >&2 + echo " -p port - port, numbered 1..n, 0=1st active (default is 1st active)" >&2 + echo " -s - Affect source side (first node) of link only." >&2 + echo " -d - Affect dest side (second node) of link only." >&2 + echo " -C - This option clears beaconing LED on all ports.">&2 + echo " on|off - action to perform" >&2 + echo " on - Turns on beaconing LED" >&2 + echo " off - Turns off beaconing LED" >&2 + echo >&2 + echo "portlist.csv is a file listing the links to process" >&2 + echo "It is of the form:" >&2 + echo " NodeGUID;PortNum;NodeType;NodeDesc;NodeGUID;PortNum;NodeType;NodeDesc;Dontcare" >&2 + echo >&2 + echo "for example:" >&2 + echo " echo \"0x001175010165ac1d;1;FI;phkpstl035 hfi1_0\"|opaledports on" >&2 + echo " opaledports on < portlist.csv" >&2 + echo " opaextractsellinks -F led:on | opaledports off" >&2 + echo " opaledports -C" >&2 + exit 0 +} + +Usage() +{ + echo "Usage: opaledports [-h hfi] [-p port] [-s|-d] [on|off] < portlist.csv" >&2 + echo " or" >&2 + echo " opaledports [-h hfi] [-p port] [-C]" >&2 + echo " or" >&2 + echo " opaledports --help" >&2 + echo >&2 + echo " --help - produce full help text" >&2 + echo " -h hfi - hfi, numbered 1..n, 0= -p port will be a system wide port num" >&2 + echo " (default is 0)" >&2 + echo " -p port - port, numbered 1..n, 0=1st active (default is 1st active)" >&2 + echo " -s - Affect source side (first node) of link only." >&2 + echo " -d - Affect dest side (second node) of link only." >&2 + echo " on|off - action to perform" >&2 + echo " on - enabled beaconing LED" >&2 + echo " off - disables beaconing LED" >&2 + echo >&2 + echo "portlist.csv is a file listing the links to process" >&2 + echo "It is of the form:" >&2 + echo " NodeGUID;PortNum;NodeType;NodeDesc;NodeGUID;PortNum;NodeType;NodeDesc;Dontcare" >&2 + echo >&2 + echo "for example:" >&2 + echo " opaledports on < portlist.csv" >&2 + exit 2 +} + +lookup_lid() +{ + local nodeguid="$1" + local portnum="$2" + local guid port type desc lid + grep "^$nodeguid;$portnum;" < $lidmap|head -n 1| while read guid port type desc lid + do + echo -n $lid + done +} + +generate_lidmap() +{ + + # generate lidmap + /usr/sbin/opaextractlids $port_opts > $lidmap + if [ ! -s $lidmap ] + then + echo "opaledports: Unable to determine fabric lids" >&2 + rm -f $lidmap + return 1 + fi +} + +set_led() +{ + processed=0 + skipped=0 + failed=0 + IFS=';' + while read nodeguid1 port1 type1 desc1 nodeguid2 port2 type2 desc2 rest + do + if [ "$dstonly" -eq 0 ]; then #we are processing first port + if [ $type1 = "SW" ]; then + lid1=$(lookup_lid $nodeguid1 0) + else + lid1=$(lookup_lid $nodeguid1 $port1) + fi + echo "$lid1;$nodeguid1;$port1;$type1;$desc1" + fi + if [ "$srconly" -eq 0 ]; then #we are processing second port + if [ -n "$nodeguid2" ]; then + if [ $type2 = "SW" ]; then + lid2=$(lookup_lid $nodeguid2 0) + else + lid2=$(lookup_lid $nodeguid2 $port2) + fi + echo "$lid2;$nodeguid2;$port2;$type2;$desc2" + fi + fi + done | + { + while read lid guid port type desc + do + if [ x"$lid" = x ] + then + echo "Skipping link: $desc:$port -> $ldesc:$lport" + skipped=$(( $skipped + 1)) + else + if [ "$enable_disable" == "on" ]; then + echo "Turning on LED beaconing: $guid:$desc:$lid:$port" + eval /usr/sbin/opaportconfig $port_opts -l $lid -m $port ledon + if [ $? -ne 0 ]; then failed=$((failed+1)); fi + else + echo "Turning off LED beaconing: $guid:$desc:$lid:$port" + eval /usr/sbin/opaportconfig $port_opts -l $lid -m $port ledoff + if [ $? -ne 0 ]; then failed=$((failed+1)); fi + fi + processed=$(( $processed + 1)) + fi + done + if [ $failed -eq 0 ] + then + echo "Processed: $processed; Skipped: $skipped" + return 0 + else + echo "Processed: $processed; Skipped: $skipped; Failed: $failed" + return 1 + fi + } +} + + +if [ x"$1" = "x--help" ] +then + Usage_full +fi + +res=0 +export srconly=0 +export dstonly=0 +export clearall=0 +export hfi_input=0 +export port_input=0 + +while getopts sdCh:p:t: param +do + case $param in + p) export port_input="$OPTARG";; + h) export hfi_input="$OPTARG";; + C) export clearall=1;; + s) export srconly=1;; + d) export dstonly=1;; + ?) Usage;; + esac +done + +/usr/sbin/oparesolvehfiport $hfi_input $port_input &>/dev/null +if [ $? -ne 0 -o "$hfi_input" = "" -o "$port_input" = "" ] +then + echo "opaledports: Error: Invalid port specification: $hfi_input:$port_input" >&2 + exit 1 +fi + +hfi=$(/usr/sbin/oparesolvehfiport $hfi_input $port_input -o hfinum) +port=`echo $(/usr/sbin/oparesolvehfiport $hfi_input $port_input | cut -f 2 -d ':')` +port_opts="-h $hfi -p $port" + +if [ "$clearall" -eq 1 ]; then + if [ $srconly -eq 1 ] || [ $dstonly -eq 1 ]; then + echo "ERROR: -d/-s incompatible with -C option" >&2 + Usage + exit 1 + fi + export clearall=0 + /usr/sbin/opaextractsellinks $port_opts -F led:on | $0 $port_opts off + exit $? +fi + +if [ $srconly -eq 1 ] && [ $dstonly -eq 1 ]; then + echo "ERROR: -d and -s options mutually exclusive. Choose only one." >&2 + Usage +fi + +shift $((OPTIND -1)) + +if [ $# -ge 1 ] +then + enable_disable="$1" + shift +fi + +if [ $# -ge 1 ] +then + Usage +fi + +if [ "$enable_disable" != "on" ] && [ "$enable_disable" != "off" ]; then + echo "ERROR: No action -C, on or off specified" >&2 + Usage +fi + +suffix=":$hfi:$port" +generate_lidmap + +echo "Processing fabric: ${suffix}..." +echo "--------------------------------------------------------" +set_led "$hfi" "$port" +if [ $? -ne 0 ] +then + res=1 +fi + +exit $res diff --git a/IbaTools/fabric_info/Makefile b/IbaTools/fabric_info/Makefile new file mode 100644 index 0000000..9387d57 --- /dev/null +++ b/IbaTools/fabric_info/Makefile @@ -0,0 +1,156 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** +# Makefile for opafabricinfo + +# Include Make Control Settings +include $(TL_DIR)/$(PROJ_FILE_DIR)/Makesettings.project + +#=============================================================================# +# Definitions: +#-----------------------------------------------------------------------------# + +# Name of SubProjects +DS_SUBPROJECTS = +# name of executable or downloadable image +EXECUTABLE = #$(BUILDDIR)/opafabricinfo$(EXE_SUFFIX) +# list of sub directories to build +DIRS = +# C files (.c) +CFILES = \ + # Add more c files here +# C++ files (.cpp) +CCFILES = \ + # Add more cpp files here +# lex files (.lex) +LFILES = \ + # Add more lex files here +# archive library files (basename, $ARFILES will add MOD_LIB_DIR/prefix and suffix) +LIBFILES= +# Windows Resource Files (.rc) +RSCFILES = +# Windows IDL File (.idl) +IDLFILE = +# Windows Linker Module Definitions (.def) file for dll's +DEFFILE = +# targets to build during INCLUDES phase (add public includes here) +INCLUDE_TARGETS = \ + # Add more h hpp files here + +# Non-compiled files +MISC_FILES = + +# all source files +SOURCES = $(CFILES) $(CCFILES) $(LFILES) $(RSCFILES) $(IDLFILE) +# Source files to include in DSP File +DSP_SOURCES = $(INCLUDE_TARGETS) $(SOURCES) $(MISC_FILES) \ + $(RSCFILES) $(DEFFILE) $(MAKEFILE) +# all object files +OBJECTS = $(CFILES:.c=$(OBJ_SUFFIX)) $(CCFILES:.cpp=$(OBJ_SUFFIX)) \ + $(LFILES:.lex=$(OBJ_SUFFIX)) +RSCOBJECTS = $(RSCFILES:.rc=$(RES_SUFFIX)) +# targets to build during LIBS phase +LIB_TARGETS_IMPLIB = +LIB_TARGETS_ARLIB = # $(LIB_PREFIX)ResourceTest$(ARLIB_SUFFIX) +LIB_TARGETS_EXP = $(LIB_TARGETS_IMPLIB:$(ARLIB_SUFFIX)=$(EXP_SUFFIX)) +LIB_TARGETS_MISC = +# targets to build during CMDS phase +CMD_TARGETS_SHLIB = +CMD_TARGETS_EXE = $(EXECUTABLE) +CMD_TARGETS_MISC = opafabricinfo +# files to remove during clean phase +CLEAN_TARGETS_MISC = +CLEAN_TARGETS = $(OBJECTS) $(RSCOBJECTS) $(IDL_TARGETS) $(CLEAN_TARGETS_MISC) +# other files to remove during clobber phase +CLOBBER_TARGETS_MISC= +# sub-directory to install to within bin +BIN_SUBDIR = +# sub-directory to install to within include +INCLUDE_SUBDIR = + +# Additional Settings +#CLOCALDEBUG = User defined C debugging compilation flags [Empty] +#CCLOCALDEBUG = User defined C++ debugging compilation flags [Empty] +#CLOCAL = User defined C flags for compiling [Empty] +#CCLOCAL = User defined C++ flags for compiling [Empty] +#BSCLOCAL = User flags for Browse File Builder [Empty] +#DEPENDLOCAL = user defined makedepend flags [Empty] +#LINTLOCAL = User defined lint flags [Empty] +#LOCAL_INCLUDE_DIRS = User include directories to search for C/C++ headers [Empty] +#LDLOCAL = User defined C flags for linking [Empty] +#IMPLIBLOCAL = User flags for Object Lirary Manager [Empty] +#MIDLLOCAL = User flags for IDL compiler [Empty] +#RSCLOCAL = User flags for resource compiler [Empty] +#LOCALDEPLIBS = User libraries to include in dependencies [Empty] +#LOCALLIBS = User libraries to use when linking [Empty] +# (in addition to LOCALDEPLIBS) +#LOCAL_LIB_DIRS = User library directories for libpaths [Empty] + +CLOCAL = $(CPIE) + +# Include Make Rules definitions and rules +include $(TL_DIR)/IbaTools/Makerules.module + +#=============================================================================# +# Overrides: +#-----------------------------------------------------------------------------# +#CCOPT = # C++ optimization flags, default lets build config decide +#COPT = # C optimization flags, default lets build config decide +#SUBSYSTEM = Subsystem to build for (none, console or windows) [none] +# (Windows Only) +#USEMFC = How Windows MFC should be used (none, static, shared, no_mfc) [none] +# (Windows Only) +#=============================================================================# + +#=============================================================================# +# Rules: +#-----------------------------------------------------------------------------# +# process Sub-directories +include $(TL_DIR)/Makerules/Maketargets.toplevel + +# build cmds and libs +include $(TL_DIR)/Makerules/Maketargets.build + +opafabricinfo: fabric_info.sh + cat $< > $@ + chmod a+x $@ + +# install for includes, libs and cmds phases +include $(TL_DIR)/Makerules/Maketargets.install + +# install for stage phase +include $(TL_DIR)/Makerules/Maketargets.stage + +# Unit test execution +#include $(TL_DIR)/Makerules/Maketargets.runtest + +#=============================================================================# + +#=============================================================================# +# DO NOT DELETE THIS LINE -- make depend depends on it. +#=============================================================================# diff --git a/IbaTools/fabric_info/README b/IbaTools/fabric_info/README new file mode 100644 index 0000000..b86dbcd --- /dev/null +++ b/IbaTools/fabric_info/README @@ -0,0 +1 @@ +Fast fabric tool to report high level fabric statistics using saquery diff --git a/IbaTools/fabric_info/fabric_info.sh b/IbaTools/fabric_info/fabric_info.sh new file mode 100644 index 0000000..b20fe2b --- /dev/null +++ b/IbaTools/fabric_info/fabric_info.sh @@ -0,0 +1,275 @@ +#!/bin/bash +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] +# This script provides a quick summary of fabric configuration +# it uses saquery to gather the information from the SM + +if [ -f /usr/lib/opa/tools/ff_funcs ] +then + # optional override of defaults + if [ -f /etc/opa/opafastfabric.conf ] + then + . /etc/opa/opafastfabric.conf + fi + + . /usr/lib/opa/tools/opafastfabric.conf.def + + . /usr/lib/opa/tools/ff_funcs + ff_available=y +else + ff_available=n +fi + +trap "exit 1" SIGHUP SIGTERM SIGINT + +# if ff is not available, we can only support a subset of the capability + +show_info() +{ + # $1 = hfi + # $2 = port + if [ "$port" -eq 0 ] + then + port_opts="-h $hfi" # default port to 1st active + else + port_opts="-h $hfi -p $port" + fi + echo "Fabric $hfi:$port Information:" + if /usr/sbin/opasmaquery $port_opts -o pkey 2>/dev/null|grep 0xffff >/dev/null 2>&1 + then + # Mgmt Node + tmp=`/usr/sbin/opasaquery $port_opts -o sminfo` + if [ "$?" -ne 0 ] + then + echo "ERROR: opasaquery failed" + return 1 + fi + echo "$tmp" | grep "Guid:"|while read trash lid trash guid trash state + do + tmp=`/usr/sbin/opasaquery $port_opts -g $guid -o desc` + if [ "$?" -ne 0 ] + then + echo "ERROR: opasaquery failed" + return 1 + fi + tmp=`echo "$tmp"|head -1` + echo "SM: $tmp Guid: $guid State: $state" + done + /usr/sbin/opasaquery $port_opts -o fabricinfo + if [ "$?" -ne 0 ] + then + echo "ERROR: opasaquery failed" + return 1 + fi + else + # Non-Mgmt Node + tmp=`/usr/sbin/opaportinfo $port_opts` + if [ "$?" -ne 0 ] + then + echo "ERROR: opaportinfo failed" + return 1 + fi + echo "$tmp" | grep "SMLID:"|while read trash lid trash smlid + do + tmp=`/usr/sbin/opasaquery $port_opts -l $smlid -o desc` + if [ "$?" -ne 0 ] + then + echo "ERROR: opasaquery failed" + return 1 + fi + tmp=`echo "$tmp" | head -1` + echo "Master SM: $tmp" + done + + tmp=`/usr/sbin/opasaquery $port_opts -t fi -o nodeguid` + if [ "$?" -ne 0 ] + then + echo "ERROR: opasaquery failed" + return 1 + fi + tmp=`echo "$tmp" | sort -u | wc -l` + echo "Number of HFIs: $tmp" + tmp=`/usr/sbin/opasaquery $port_opts -t fi -o desc` + if [ "$?" -ne 0 ] + then + echo "ERROR: opasaquery failed" + return 1 + fi + tmp=`echo "$tmp" | wc -l` + echo "Number of HFI Ports: $tmp" + fi + echo "-------------------------------------------------------------------------------" +} + +Usage_ff_full() +{ + echo "Usage: opafabricinfo [-t portsfile] [-p ports]" >&2 + echo " or" >&2 + echo " opafabricinfo --help" >&2 + echo " --help - produce full help text" >&2 + echo " -t portsfile - file with list of local HFI ports used to access" >&2 + echo " fabric(s) for analysis, default is $CONFIG_DIR/opa/ports" >&2 + echo " -p ports - list of local HFI ports used to access fabric(s) for analysis" >&2 + echo " default is 1st active port" >&2 + echo " This is specified as hfi:port" >&2 + echo " 0:0 = 1st active port in system" >&2 + echo " 0:y = port y within system" >&2 + echo " x:0 = 1st active port on HFI x" >&2 + echo " x:y = HFI x, port y" >&2 + echo " The first HFI in the system is 1. The first port on an HFI is 1." >&2 + echo " Environment:" >&2 + echo " PORTS - list of ports, used in absence of -t and -p" >&2 + echo " PORTS_FILE - file containing list of ports, used in absence of -t and -p" >&2 + echo "for example:" >&2 + echo " opafabricinfo" >&2 + echo " opafabricinfo -p '1:1 1:2 2:1 2:2'" >&2 + exit 0 +} + +Usage_basic_full() +{ + echo "Usage: opafabricinfo [-p ports]" >&2 + echo " or" >&2 + echo " opafabricinfo --help" >&2 + echo " --help - produce full help text" >&2 + echo " -p ports - list of local HFI ports used to access fabric(s) for analysis" >&2 + echo " default is 1st active port" >&2 + echo " This is specified as hfi:port" >&2 + echo " 0:0 = 1st active port in system" >&2 + echo " 0:y = port y within system" >&2 + echo " x:0 = 1st active port on HFI x" >&2 + echo " x:y = HFI x, port y" >&2 + echo " The first HFI in the system is 1. The first port on an HFI is 1." >&2 + echo " Environment:" >&2 + echo " PORTS - list of ports, used in absence of -p" >&2 + echo "for example:" >&2 + echo " opafabricinfo" >&2 + echo " opafabricinfo -p '1:1 1:2 2:1 2:2'" >&2 + exit 0 +} + +Usage_ff() +{ + echo "Usage: opafabricinfo" >&2 + echo " or" >&2 + echo " opafabricinfo --help" >&2 + echo " --help - produce full help text" >&2 + echo "for example:" >&2 + echo " opafabricinfo" >&2 + exit 2 +} + +Usage_basic() +{ + Usage_ff +} + +Usage() +{ + if [ "$ff_available" = y ] + then + Usage_ff + else + Usage_basic + fi +} + +if [ x"$1" = "x--help" ] +then + if [ "$ff_available" = y ] + then + Usage_ff_full + else + Usage_basic_full + fi +fi + +status=ok +if [ "$ff_available" = y ] +then + while getopts p:t: param + do + case $param in + p) export PORTS="$OPTARG";; + t) export PORTS_FILE="$OPTARG";; + ?) Usage;; + esac + done + shift $((OPTIND -1)) +else + while getopts p: param + do + case $param in + p) export PORTS="$OPTARG";; + ?) Usage;; + esac + done + shift $((OPTIND -1)) +fi +if [ $# -ge 1 ] +then + Usage +fi + +if [ "$ff_available" = y ] +then + check_ports_args opafabricinfo +else + if [ "x$PORTS" = "x" ] + then + PORTS='0:0' + fi +fi + +for hfi_port in $PORTS +do + hfi=$(expr $hfi_port : '\([0-9]*\):[0-9]*') + port=$(expr $hfi_port : '[0-9]*:\([0-9]*\)') + if [ "$hfi" = "" -o "$port" = "" ] + then + echo "opafabricinfo: Error: Invalid port specification: $hfi_port" >&2 + status=bad + continue + fi + + show_info "$hfi" "$port" + if [ $? -ne 0 ] + then + status=bad + fi +done + +if [ "$status" != "ok" ] +then + exit 1 +else + exit 0 +fi diff --git a/IbaTools/man/Makefile b/IbaTools/man/Makefile new file mode 100644 index 0000000..9867392 --- /dev/null +++ b/IbaTools/man/Makefile @@ -0,0 +1,242 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** +# Makefile for IbaTools/man + +# Include Make Control Settings +include $(TL_DIR)/$(PROJ_FILE_DIR)/Makesettings.project + +#=============================================================================# +# Definitions: +#-----------------------------------------------------------------------------# + +# Name of SubProjects +DS_SUBPROJECTS = +# name of executable or downloadable image +EXECUTABLE = +# list of sub directories to build +DIRS = +# C files (.c) +CFILES = \ + # Add more c files here +# C++ files (.cpp) +CCFILES = \ + # Add more cpp files here +# lex files (.lex) +LFILES = \ + # Add more lex files here +# archive library files (basename, $ARFILES will add MOD_LIB_DIR/prefix and suffix) +LIBFILES= +# Windows Resource Files (.rc) +RSCFILES = +# Windows IDL File (.idl) +IDLFILE = +# Windows Linker Module Definitions (.def) file for dll's +DEFFILE = +# targets to build during INCLUDES phase (add public includes here) +INCLUDE_TARGETS = \ + # Add more h hpp files here +# Non-compiled files +MAN_PAGE_1_FILES = \ + opacapture.1 \ + opaconfig.1 \ + opafabricinfo.1 \ + opagetvf.1 \ + opagetvf_env.1 \ + opahfirev.1 \ + opainfo.1 \ + opa_osd_dump.1 \ + opa_osd_exercise.1 \ + opa_osd_perf.1 \ + opa_osd_query.1 \ + opapacketcapture.1 \ + opapmaquery.1 \ + opaportconfig.1 \ + opaportinfo.1 \ + oparesolvehfiport.1 \ + opasaquery.1 \ + opashowmc.1 \ + opasmaquery.1 \ + # Add more man pages for chapter 1 +MAN_PAGE_8_FILES = \ + opaallanalysis.8 \ + opacabletest.8 \ + opacaptureall.8 \ + opachassisadmin.8 \ + opachassisanalysis.8 \ + opacheckload.8 \ + opacmdall.8 \ + opadisablehosts.8 \ + opadisableports.8 \ + opadownloadall.8 \ + opaenableports.8 \ + opaledports.8 \ + opaesmanalysis.8 \ + opaexpandfile.8 \ + opaextractbadlinks.8 \ + opaextracterror.8 \ + opaextractlids.8 \ + opaextractlink.8 \ + opaextractperf.8 \ + opaextractperf2.8 \ + opaextractsellinks.8 \ + opaextractstat.8 \ + opaextractstat2.8 \ + opafabricanalysis.8 \ + opafastfabric.8 \ + opafindgood.8 \ + opafirmware.8 \ + opafmconfigcheck.8 \ + opafmconfigdiff.8 \ + opagenchassis.8 \ + opagenesmchassis.8 \ + opagenswitches.8 \ + opagentopology.8 \ + opahostadmin.8 \ + opahostsmanalysis.8 \ + opalinkanalysis.8 \ + opamergeperf2.8 \ + opapaquery.8 \ + opapingall.8 \ + opareport.8 \ + opareports.8 \ + opascpall.8 \ + opasetupssh.8 \ + opashowallports.8 \ + opasorthosts.8 \ + opaswitchadmin.8 \ + opatop.8 \ + opauploadall.8 \ + opaverifyhosts.8 \ + opaxlattopology.8 \ + opashowmc.8 \ + opaxmlextract.8 \ + opaxmlfilter.8 \ + opaxmlgenerate.8 \ + opaxmlindent.8 \ + opaswdisableall.8 \ + opaswenableall.8 \ + opaextractmissinglinks.8 \ + opa2rm.8 \ + # Add more man pages for chapter 8 +MISC_FILES= \ + $(MAN_PAGE_1_FILES) \ + $(MAN_PAGE_8_FILES) \ + # Add more files here +# all source files +SOURCES = $(CFILES) $(CCFILES) $(LFILES) $(RSCFILES) $(IDLFILE) +# Source files to include in DSP File +DSP_SOURCES = $(INCLUDE_TARGETS) $(SOURCES) $(MISC_FILES) \ + $(RSCFILES) $(DEFFILE) $(MAKEFILE) +# all object files +OBJECTS = $(CFILES:.c=$(OBJ_SUFFIX)) $(CCFILES:.cpp=$(OBJ_SUFFIX)) \ + $(LFILES:.lex=$(OBJ_SUFFIX)) +RSCOBJECTS = $(RSCFILES:.rc=$(RES_SUFFIX)) +# targets to build during LIBS phase +LIB_TARGETS_IMPLIB = +LIB_TARGETS_ARLIB = # $(LIB_PREFIX)ResourceTest$(ARLIB_SUFFIX) +LIB_TARGETS_EXP = $(LIB_TARGETS_IMPLIB:$(ARLIB_SUFFIX)=$(EXP_SUFFIX)) +LIB_TARGETS_MISC = +# targets to build during CMDS phase +CMD_TARGETS_SHLIB = +CMD_TARGETS_EXE = $(EXECUTABLE) +CMD_TARGETS_MISC = +# files to remove during clean phase +CLEAN_TARGETS_MISC = +CLEAN_TARGETS = $(OBJECTS) $(RSCOBJECTS) $(IDL_TARGETS) $(CLEAN_TARGETS_MISC) +# other files to remove during clobber phase +CLOBBER_TARGETS_MISC= +# sub-directory to install to within bin +BIN_SUBDIR = +# sub-directory to install to within include +INCLUDE_SUBDIR = + +# Additional Settings +#CLOCALDEBUG = User defined C debugging compilation flags [Empty] +#CCLOCALDEBUG = User defined C++ debugging compilation flags [Empty] +#CLOCAL = User defined C flags for compiling [Empty] +#CCLOCAL = User defined C++ flags for compiling [Empty] +#BSCLOCAL = User flags for Browse File Builder [Empty] +#DEPENDLOCAL = user defined makedepend flags [Empty] +#LINTLOCAL = User defined lint flags [Empty] +#LOCAL_INCLUDE_DIRS = User include directories to search for C/C++ headers [Empty] +#LDLOCAL = User defined C flags for linking [Empty] +#IMPLIBLOCAL = User flags for Object Lirary Manager [Empty] +#MIDLLOCAL = User flags for IDL compiler [Empty] +#RSCLOCAL = User flags for resource compiler [Empty] +#LOCALDEPLIBS = User libraries to include in dependencies [Empty] +#LOCALLIBS = User libraries to use when linking [Empty] +# (in addition to LOCALDEPLIBS) +#LOCAL_LIB_DIRS = User library directories for libpaths [Empty] + +CLOCAL = $(CPIE) +LOCAL_INCLUDE_DIRS= +LOCALDEPLIBS= +LOCALLIBS= +LOCAL_LIB_DIRS= + +# Include Make Rules definitions and rules +include $(TL_DIR)/IbaTools/Makerules.module + +#=============================================================================# +# Overrides: +#-----------------------------------------------------------------------------# +#CCOPT = # C++ optimization flags, default lets build config decide +#COPT = # C optimization flags, default lets build config decide +#SUBSYSTEM = Subsystem to build for (none, console or windows) [none] +# (Windows Only) +#USEMFC = How Windows MFC should be used (none, static, shared, no_mfc) [none] +# (Windows Only) +#=============================================================================# + +#=============================================================================# +# Rules: +#-----------------------------------------------------------------------------# +# process Sub-directories +include $(TL_DIR)/Makerules/Maketargets.toplevel + +# build cmds and libs +include $(TL_DIR)/Makerules/Maketargets.build + +# install for includes, libs and cmds phases +include $(TL_DIR)/Makerules/Maketargets.install + +# install for stage phase +#include $(TL_DIR)/Makerules/Maketargets.stage +STAGE:: + $(VS)$(STAGE_INSTALL) $(STAGE_INSTALL_DIR_OPT) $(PROJ_STAGE_MAN_DIR)/man1 $(MAN_PAGE_1_FILES) + $(VS)$(STAGE_INSTALL) $(STAGE_INSTALL_DIR_OPT) $(PROJ_STAGE_MAN_DIR)/man8 $(MAN_PAGE_8_FILES) + +# Unit test execution +#include $(TL_DIR)/Makerules/Maketargets.runtest + +#=============================================================================# + +#=============================================================================# +# DO NOT DELETE THIS LINE -- make depend depends on it. +#=============================================================================# diff --git a/IbaTools/man/opa2rm.manPage b/IbaTools/man/opa2rm.manPage new file mode 100644 index 0000000..a017a7a --- /dev/null +++ b/IbaTools/man/opa2rm.manPage @@ -0,0 +1,197 @@ +.\" .\" ********************************************************************* +.\" .\" * * +.\" .\" * Copyright 2015-2019, Intel Corporation * +.\" .\" * * +.\" .\" * All Rights Reserved. * +.\" .\" * * +.\" .\" ********************************************************************* + +.TH opa2rm 8 "Intel Corporation" "Copyright(C) 2015\-2019" "IFSFFCLIRG (Man Page)" +.SH NAME +opa2rm + + +.PP +Permits the generation of configuration files for FastFabric or resource managers from a topology xml file. +.PP +When using a topology spreadsheet and opaxlattopology to design and prepare for deployment verification of a fabric, opa2rm may be used to generate resource manager configuration from the planned cluster design. Using this approach will allow the resulting configuration files to be complete, even if some nodes in the fabric have not yet been installed or made operational. Alternatively, opareport -o topology can be used to generate a topology XML file for input to opa2rm. In this case, only the currently present nodes will be included. +.PP +When working with SLURM, the opa2rm -o slurm option should typically be used. This option will generate a SLURM configuration file that lists the hosts directly connected to each switch in a syntax that can be used by SLURM\[aq]s topology/tree plugin. It also generates a single "fake" switch shown as connecting all the other switches together. This approach allows for SLURM job placement to be improved while avoiding undo overhead in SLURM. This option also allows for topologies that are not a pure fat-tree. +.PP +When the configuration is a pure fat tree or oversubscribed fat tree, the opa2rm -o slurmfull option may be used to generate the full description of the fabric, including all intermediate and core switches in the fat tree topology. This option may permit better job placement optimization than the output from the opa2rm -o slurm option. However for larger fabrics, it may also increase the overhead within SLURM. +.SH Syntax +opa2rm [-v] [-q] -o \fIoutput\fR [-g|-u|-t] [-F \fIpoint\fR] [-p \fIprefix\fR] [-s \fIsuffix\fR] topology\(ulinput +.SH Options + +.TP 10 +--help + +Produces full help text. + +.TP 10 +-v/--verbose + +Specifies verbose output. + +.TP 10 +-q/--quiet + +Disables progress reports. + +.TP 10 +-o/--output \fIoutput\fR + +Specifies the output type: + +.RS +.TP 10 + +.sp +slurm +SLURM tree nodes. Supports a variety of topologies. + +.RE + +.RS +.TP 10 + +.sp +slurmful +SLURM fat tree nodes and ISLs. Only supports pure trees. + +.RE + +.RS +.TP 10 + +.sp +hosts +FastFabric hosts file omitting this host + +.RE + +.TP 10 +-g/--guid + +Specifies the output switch GUIDs instead of names. + +.TP 10 +-u/--underscore + +Changes spaces in switch names to underscores. + +.TP 10 +-t/--trunc + +Truncates switch names at first space. + +.IP +This will treat large Director switches as a single, big switch. +.IP +If -g, -u or -t are not specified, the switch name\[aq]s suffix, after the first space, will be placed at the start of the name. For example, \[aq]core5 Leaf 101\[aq] becomes \[aq]Leaf101\(ulcore5\[aq]. +.TP 10 +-F/--focus \fIpoint\fR + +Specifies the focus area for output. Limits the scope of output to links that match any of the given focus points. + +.TP 10 +-p/--prefix \fIprefix\fR + +Specifies the prefix to prepend to all FI hostnames. + +.TP 10 +-s/--suffix \fIsuffix\fR + +Specifies the suffix to append to all FI hostnames. + +.TP 10 +topology\(ulinput + +Specifies the topology\(ulinput file to use. \[aq]-\[aq] may be used to specify stdin. + +.SH Point Syntax + +.TP 10 +node:\fIvalue\fR + +\fIvalue\fR is node description (node name). + +.TP 10 +node:\fIvalue1\fR:port:\fIvalue2\fR + +\fIvalue1\fR is node description (node name); \fIvalue2\fR is port number. + +.TP 10 +nodepat:\fIvalue\fR + +\fIvalue\fR is glob pattern for node description (node name). + +.TP 10 +nodepat:\fIvalue1\fR:port:\fIvalue2\fR + +\fIvalue1\fR is glob pattern for node description (node name); \fIvalue2\fR is port number. + +.TP 10 +nodetype:\fIvalue\fR + +\fIvalue\fR is node type (SW or FI). + +.TP 10 +nodetype:\fIvalue1\fR:port:\fIvalue2\fR + +\fIvalue1\fR is node type (SW or FI); \fIvalue2\fR is port number. + +.TP 10 +rate:\fIvalue\fR + +\fIvalue\fR is string for rate (25g, 50g, 75g, 100g). + +.TP 10 +mtucap:\fIvalue\fR + +\fIvalue\fR is MTU size (2048, 4096, 8192, 10240); omits switch mgmt port 0. + +.TP 10 +labelpat:\fIvalue\fR + +\fIvalue\fR is glob pattern for cable label. + +.TP 10 +lengthpat:\fIvalue\fR + +\fIvalue\fR is glob pattern for cable length. + +.TP 10 +cabledetpat:\fIvalue\fR + +\fIvalue\fR is glob pattern for cable details. + +.TP 10 +linkdetpat:\fIvalue\fR + +\fIvalue\fR is glob pattern for link details. + +.TP 10 +portdetpat:\fIvalue\fR + +\fIvalue\fR is glob pattern for port details to value. + +.SH Examples +opa2rm -o slurm topology.xml +.br + +opa2rm -o slurm -p \[aq]opa-\[aq] topology.xml +.br + +opa2rm -o slurm -s \[aq]-opa\[aq] topology.xml +.br + +opa2rm -o slurm -F \[aq]nodepat:compute*\[aq] -F \[aq]nodepat:opacore1 *\[aq] +.br +topology.xml +.br + +opa2rm -o nodes -F \[aq]nodedetpat:compute*\[aq] topology.xml +.br + +opa2rm -o hosts topology.xml diff --git a/IbaTools/man/opa_osd_dump.manPage b/IbaTools/man/opa_osd_dump.manPage new file mode 100644 index 0000000..d0f99c1 --- /dev/null +++ b/IbaTools/man/opa_osd_dump.manPage @@ -0,0 +1,31 @@ +.\" .\" ********************************************************************* +.\" .\" * * +.\" .\" * Copyright 2015-2019, Intel Corporation * +.\" .\" * * +.\" .\" * All Rights Reserved. * +.\" .\" * * +.\" .\" ********************************************************************* + +.TH opa\(ulosd\(uldump 1 "Intel Corporation" "Copyright(C) 2015\-2019" "IFSFFCLIRG (Man Page)" +.SH NAME +opa\(ulosd\(uldump + + +.PP +Prints the current contents of the distributed SA shared memory database. +.SH Syntax +opa\(ulosd\(uldump [--verbose \fIarg\fR | -v \fIarg\fR] +.SH Options + +.TP 10 +--help + +Produces full help text. + +.TP 10 +--verbose/-v \fIarg\fR + +Specifies the Kernel logging level to perform. Range = 1 - 7. + +.SH Example +opa\(ulosd\(uldump >opasadb\(ulcontents diff --git a/IbaTools/man/opa_osd_exercise.manPage b/IbaTools/man/opa_osd_exercise.manPage new file mode 100644 index 0000000..3d36e95 --- /dev/null +++ b/IbaTools/man/opa_osd_exercise.manPage @@ -0,0 +1,87 @@ +.\" .\" ********************************************************************* +.\" .\" * * +.\" .\" * Copyright 2015-2019, Intel Corporation * +.\" .\" * * +.\" .\" * All Rights Reserved. * +.\" .\" * * +.\" .\" ********************************************************************* + +.TH opa\(ulosd\(ulexercise 1 "Intel Corporation" "Copyright(C) 2015\-2019" "IFSFFCLIRG (Man Page)" +.SH NAME +opa\(ulosd\(ulexercise + + +.PP +Performs stress test on SM and distributed SA query system. +.SH Syntax +opa\(ulosd\(ulexercise [-d | -s | -r | -x | -X | -D | -p | -S | -t | -e] \fIguidlist\fR +.SH Options + +.TP 10 +--help + +Produces full help text. + +.TP 10 +-d \fIdebug level\fR + +Sets debugging level. + +.TP 10 +-s \fIseconds\fR + +Specifies running for at least \fIseconds\fR seconds. +.TP 10 +-r \fIremote\fR + +Specifies the host running the fabric simulator. +.TP 10 +-x \fIcount\fR + +Number of destinations to toggle up or down after each pass. +.br +Maximum = MAX\(ulTOGGLES. +.TP 10 +-X \fIcount\fR + +Specifies how often to toggle a source port up or down +.br +(in seconds). +.TP 10 +-D \fIseconds\fR + +Specifies how long to sleep after each pass. This value gives the Subnet Manager time to process port events. +.TP 10 +-p \fIpkey\fR + +Specifies to include \fIpkey\fR in the searches. Can be specified up to 8 times. +.TP 10 +-S \fIsid\fR + +Specifies to include SID in the searches. +.TP 10 +-t \fIerror threshold\fR + +Cancels the test if the number of path errors to a single destination exceeds \fIerror threshold\fR. The count is reset to zero when a correct result is retrieved. Can be specified up to 8 times. Note that providing both SIDs and pkeys may cause problems. +.TP 10 +-e + +Instructs simulator to enable all ports before starting. +.TP 10 +\fIguidlist\fR + +Text file that lists the source and destination GUIDs and LIDs. \fIguidlist\fR format is: + +.RS + +.IP \(bu +lid\(ul0;guid\(ul0;node\(uldesc\(ul0 +.IP \(bu +lid\(ul1;guid\(ul1;node\(uldesc\(ul1 +.IP \(bu +and so on. + +.RE + +.SH Example +opa\(ulosd\(ulexercise -p 0x9001 guidtable diff --git a/IbaTools/man/opa_osd_perf.manPage b/IbaTools/man/opa_osd_perf.manPage new file mode 100644 index 0000000..3b4082e --- /dev/null +++ b/IbaTools/man/opa_osd_perf.manPage @@ -0,0 +1,44 @@ +.\" .\" ********************************************************************* +.\" .\" * * +.\" .\" * Copyright 2015-2019, Intel Corporation * +.\" .\" * * +.\" .\" * All Rights Reserved. * +.\" .\" * * +.\" .\" ********************************************************************* + +.TH opa\(ulosd\(ulperf 1 "Intel Corporation" "Copyright(C) 2015\-2019" "IFSFFCLIRG (Man Page)" +.SH NAME +opa\(ulosd\(ulperf + + +.PP +Tests the performance of the distributed SA shared memory database. +.SH Syntax +opa\(ulosd\(ulperf [-q | -p | -S] \fIguidtable\fR +.SH Options + +.TP 10 +--help + +Produces full help text. + +.TP 10 +-q \fIqueries\fR + +Runs at least the specified number of queries. + +.TP 10 +-p \fIpkey\fR + +Specifies to include \fIpkey\fR in the searches. Can be specified up to 8 times. +.TP 10 +-S \fIsid\fR + +Specifies to include SID in the searches. Can be specified up to 8 times. Note that providing both SIDs and pkeys may cause problems. +.TP 10 +\fIguidtable\fR + +Text file that lists the destination GUIDs and LIDs. For example, from a build\(ultable.pl file. + +.SH Example +opa\(ulosd\(ulperf -q 100000 -p 0x8001 guidtable diff --git a/IbaTools/man/opa_osd_query.manPage b/IbaTools/man/opa_osd_query.manPage new file mode 100644 index 0000000..a3581f2 --- /dev/null +++ b/IbaTools/man/opa_osd_query.manPage @@ -0,0 +1,82 @@ +.\" .\" ********************************************************************* +.\" .\" * * +.\" .\" * Copyright 2015-2019, Intel Corporation * +.\" .\" * * +.\" .\" * All Rights Reserved. * +.\" .\" * * +.\" .\" ********************************************************************* + +.TH opa\(ulosd\(ulquery 1 "Intel Corporation" "Copyright(C) 2015\-2019" "IFSFFCLIRG (Man Page)" +.SH NAME +opa\(ulosd\(ulquery + + +.PP +Queries the opasadb for path records. This tool allows you to create an arbitrary path query and view the result. +.SH Syntax +opa\(ulosd\(ulquery [-v | -verbose] | [-s | --slid] | [-d | --dlid] | [-S | +.br +--sgid] | +[-D | --dgid]| [-k | --pkey] | [-i | --sid] | [-h | --hfi] | +.br +[-p | --port] +.SH Options + +.PP + +.B NOTE: + +.IP \(bu +All arguments are optional, but ill-formed queries can be expected to fail. You must provide at least a pair of LIDs or a pair of GIDs. +.IP \(bu +The mixing of lids and gids in a query is not permitted. +.IP \(bu +SID or PKey can be provided, but not both. +.IP \(bu +If you have multiple HFIs, the same LID can appear on more than one HFI, therefore you must specify which HFI to use when searching by LIDs. +.IP \(bu +Numbers can be in decimal, hex, or octal. + +.TP 10 +--help + +Produces full help text. +.TP 10 +-v/--verbose \fIarg\fR + +Sets debugging level. Range is 1 - 7. + +.TP 10 +-s/--slid \fIarg\fR + +Specifies source LID. +.TP 10 +-d/--dlid \fIarg\fR + +Specifies destination LID. +.TP 10 +-S/--sgid \fIarg\fR + +Specifies source GID in GID format (0x00000000:0x00000000) or in Inet6 format (x:x:x:x:x:x:x:x). +.TP 10 +-D/--dgid \fIarg\fR + +Specifies destination GID in GID format (0x00000000:0x00000000) or in Inet6 format (x:x:x:x:x:x:x:x). +.TP 10 +-k/--pkey \fIarg\fR + +Specifies partition key. +.TP 10 +-i/--sid \fIarg\fR + +Specifies service ID. +.TP 10 +-h/--hfi \fIarg\fR + +Specifies the HFI to use. Default is first HFI. The HFI can be identified by name, for example, hfi1\(ul0 or by number, for example, 1, 2, 3, ... . +.TP 10 +-p/--port \fIarg\fR + +Specifies the port to use. Default is first port. +.SH Example +opa\(ulosd\(ulquery -s2 -d4 diff --git a/IbaTools/man/opaallanalysis.manPage b/IbaTools/man/opaallanalysis.manPage new file mode 100644 index 0000000..1a17618 --- /dev/null +++ b/IbaTools/man/opaallanalysis.manPage @@ -0,0 +1,170 @@ +.\" .\" ********************************************************************* +.\" .\" * * +.\" .\" * Copyright 2015-2019, Intel Corporation * +.\" .\" * * +.\" .\" * All Rights Reserved. * +.\" .\" * * +.\" .\" ********************************************************************* + +.TH opaallanalysis 8 "Intel Corporation" "Copyright(C) 2015\-2019" "IFSFFCLIRG (Man Page)" +.SH NAME +opaallanalysis + + +.PP + +\fB(All)\fR +opaallanalysis command performs the set of analysis specified in FF\(ulALL\(ulANALYSIS and can be specified for fabric, chassis, esm, or hostsm. +.SH Syntax +opaallanalysis [-b|-e] [-s] [-d \fIdir\fR] [-c \fIfile\fR] [-t \fIportsfile\fR] +.br +[-p \fIports\fR] +[-F \fIchassisfile\fR] [-H \[aq]\fIchassis\fR\[aq]] [-G \fIesmchassisfile\fR] +.br +[-E \fIesmchassis\fR] +[-T \fItopology\(ulinput\fR] +.SH Options + +.TP 10 +--help + +Produces full help text. +.TP 10 +-b + +Sets the baseline mode. Default is compare/check mode. +.TP 10 +-e + +Evaluates health only. Default is compare/check mode. +.TP 10 +-s + +Saves history of failures (errors/differences). +.TP 10 +-d \fIdir\fR + +Identifies the top-level directory for saving baseline and history of failed checks. Default is /var/usr/lib/opa/analysis +.TP 10 +-c \fIfile\fR + +Specifies the error thresholds configuration file. Default is /etc/opa/opamon.conf +.TP 10 +-t \fIportsfile\fR + +Specifies the file with list of local HFI ports used to access fabric(s) for analysis. Default is /etc/opa/ports +.TP 10 +-p \fIports\fR + +Specifies the list of local HFI ports used to access fabric(s) for analysis. Default is the first active port. Specified as HFI:port as follows: +.RS +.TP 10 + +.sp +0:0 +First active port in system. +.RE + +.RS +.TP 10 + +.sp +0:\fIy\fR +Port \fIy\fR within system. +.RE + +.RS +.TP 10 + +.sp +\fIx\fR:0 +First active port on HFI \fIx\fR. +.RE + +.RS +.TP 10 + +.sp +\fIx\fR:\fIy\fR +HFI \fIx\fR, port \fIy\fR. +.RE + +.TP 10 +-F \fIchassisfile\fR + +Specifies the file with a chassis in a cluster. Default is /etc/opa/chassis +.TP 10 +-H \[aq]\fIchassis\fR\[aq] + +Specifies the list of chassis on which to execute the command. +.TP 10 +-G \fIesmchassisfile\fR + +Specifies the file with embedded SM chassis in the cluster. Default is /etc/opa/esm\(ulchassis +.TP 10 +-E \fIesmchassis\fR + +Specifies the list of embedded SM chassis to analyze. +.TP 10 +-T \fItopology\(ulinput\fR + +Specifies the name of topology input file to use. Any %P markers in this filename are replaced with the HFI:port being operated on, such as 0:0 or 1:2. Default is /etc/opa/topology.%P.xml. If -T NONE is specified, no topology input file is used. See +\fIopareport\fR +for more information. +.SH Example +opaallanalysis +.br + +opaallanalysis -p \[aq]1:1 2:1\[aq] +.SH Environment Variables + +.PP +The following environment variables are also used by this command: +.TP 10 +\fBPORTS\fR + +List of ports, used in absence of -t and -p. +.TP 10 +\fBPORTS\(ulFILE\fR + +File containing list of ports, used in absence of -t and -p. +.TP 10 +\fBFF\(ulTOPOLOGY\(ulFILE\fR + +File containing topology\(ulinput (may have %P marker in filename), used in absence of -T. +.TP 10 +\fBCHASSIS\fR + +List of chassis, used if -F and -H options are not supplied. +.TP 10 +\fBCHASSIS\(ulFILE\fR + +File containing list of chassis, used if -F and -H options are not supplied. +.TP 10 +\fBESM\(ulCHASSIS\fR + +List of SM chassis, used if -G and -E options are not supplied. +.TP 10 +\fBESM\(ulCHASSIS\(ulFILE\fR + +File containing list of SM chassis, used if -G and -E options are not supplied. +.TP 10 +\fBFF\(ulANALYSIS\(ulDIR\fR + +Top level directory for baselines and failed health checks. +.TP 10 +\fBFF\(ulCHASSIS\(ulCMDS\fR + +List of commands to issue during analysis, unused if -e option supplied. +.TP 10 +\fBFF\(ulCHASSIS\(ulHEALTH\fR + +Single command to issue to check overall health during analysis, unused if -b option supplied +.SH Details + +.PP +The opaallanalysis command performs the set of analysis specified in \fBFF\(ulALL\(ulANALYSIS\fR, which must be a space-separated list. This can be provided by the environment or using /etc/opa/opafastfabric.conf. The analysis set includes the options: fabric, chassis, esm, or hostsm. For a fabric with only externally managed switches, \fBFF\(ulALL\(ulANALYSIS\fR should be set to -fabric in opafastfabric.conf. +.PP +Note that the opaallanalysis command has options which are a super-set of the options for all other analysis commands. The options are passed along to the respective tools as needed. For example, the -c file option is passed on to opafabricanalysis if it is specified in \fBFF\(ulALL\(ulANALYSIS\fR. +.PP +The output files are all the output files for the \fBFF\(ulALL\(ulANALYSIS\fR selected set of analysis. See the previous sections for the specific output files. diff --git a/IbaTools/man/opacabletest.manPage b/IbaTools/man/opacabletest.manPage new file mode 100644 index 0000000..19eee37 --- /dev/null +++ b/IbaTools/man/opacabletest.manPage @@ -0,0 +1,187 @@ +.\" .\" ********************************************************************* +.\" .\" * * +.\" .\" * Copyright 2015-2019, Intel Corporation * +.\" .\" * * +.\" .\" * All Rights Reserved. * +.\" .\" * * +.\" .\" ********************************************************************* + +.TH opacabletest 8 "Intel Corporation" "Copyright(C) 2015\-2019" "IFSFFCLIRG (Man Page)" +.SH NAME +opacabletest + + +.PP + +\fB(Switch)\fR +Initiates or stops Cable Bit Error Rate stress tests for Intel(R) Omni-Path Host Fabric Interface (HFI)-to-switch links and/or ISLs. +.SH Syntax +opacabletest [-C|-A] [-c \fIfile\fR] [-f \fIhostfile\fR] [-h \fI\[aq]hosts\[aq]\fR] [-n \fInumprocs\fR] +.br + +[-t \fIportsfile\fR] [-p \fIports\fR] [start|start\(ulfi|start\(ulisl|stop|stop\(ulfi| +.br +stop\(ulisl] ... +.SH Options + +.TP 10 +--help + +Produces full help text. + +.TP 10 +-C + +Clears error counters. + +.TP 10 +-A + +Forces the system to clear hardware error counters. Implies -C. + +.TP 10 +-c \fIfile\fR + +Specifies the error thresholds configuration file. Default is /etc/opa/opamon.si.conf file. Only used if -C or -A specified. + +.TP 10 +-f \fIhostfile\fR + +Specifies the file with hosts to include in HFI -to-SW test. Default is /etc/opa/hosts file. + +.TP 10 +-h \fIhosts\fR + +Specifies the list of hosts to include in HFI -SW test. + +.TP 10 +-n \fInumprocs\fR + +Specifies the number of processes per host for HFI -SW test. + +.TP 10 +-t \fIportsfile\fR + +Specifies the file with list of local HFI ports used to access fabrics when clearing counters. Default is /etc/opa/ports file. + +.TP 10 +-p \fIports\fR + +Specifies the list of local HFI ports used to access fabrics for counter clear. + +.IP +Default is first active port. The first HFI in the system is 1. The first port on an HFI is 1. Uses the format hfi:port, +.br +for example: +.RS +.TP 10 + +.sp +0:0 +First active port in system. + +.RE + +.RS +.TP 10 + +.sp +0:y +Port \fIy\fR within system. + +.RE + +.RS +.TP 10 + +.sp +x:0 +First active port on HFI \fIx\fR. + +.RE + +.RS +.TP 10 + +.sp +x:y +HFI \fIx\fR, port \fIy\fR. + +.RE + +.TP 10 +start + +Starts the HFI -SW and ISL tests. + +.TP 10 +start\(ulfi + +Starts the HFI -SW test. + +.TP 10 +start\(ulisl + +Starts the ISL test. + +.TP 10 +stop + +Stops the HFI -SW and ISL tests. + +.TP 10 +stop\(ulfi + +Stops the HFI -SW test. + +.TP 10 +stop\(ulisl + +Stops the ISL test. + +.PP +The HFI -SW cable test requires that the \fBFF\(ulMPI\(ulAPPS\(ulDIR\fR is set, and it contains a pre-built copy of the mpi\(ulapps for an appropriate message passing interface (MPI). +.PP +The ISL cable test started by this tool assumes that the master Host Subnet Manager (HSM) is running on this host. If using the Embedded Subnet Manager (ESM), or if a different host is the master HSM, the ISL cable test must be controlled by the switch CLI, or by Intel(R) Omni-Path Fabric Suite FastFabric on the master HSM respectively. +.SH Examples +opacabletest -A start +.br + +opacabletest -f good -A start +.br + +opacabletest -h \[aq]arwen elrond\[aq] start\(ulfi +.br + +HOSTS=\[aq]arwen elrond\[aq] opacabletest stop +.br + +opacabletest -A +.SH Environment Variables + +.PP +The following environment variables are also used by this command: +.TP 10 +\fBHOSTS\fR + +List of hosts, used if -h option not supplied. + +.TP 10 +\fBHOSTS\(ulFILE\fR + +File containing list of hosts, used in absence of -f and -h. + +.TP 10 +\fBPORTS\fR + +List of ports, used in absence of -t and -p. + +.TP 10 +\fBPORTS\(ulFILE\fR + +File containing list of ports, used in absence of -t and -p. + +.TP 10 +\fBFF\(ulMAX\(ulPARALLEL\fR + +Maximum concurrent operations. diff --git a/IbaTools/man/opacapture.manPage b/IbaTools/man/opacapture.manPage new file mode 100644 index 0000000..3504fd7 --- /dev/null +++ b/IbaTools/man/opacapture.manPage @@ -0,0 +1,94 @@ +.\" .\" ********************************************************************* +.\" .\" * * +.\" .\" * Copyright 2015-2019, Intel Corporation * +.\" .\" * * +.\" .\" * All Rights Reserved. * +.\" .\" * * +.\" .\" ********************************************************************* + +.TH opacapture 1 "Intel Corporation" "Copyright(C) 2015\-2019" "IFSFFCLIRG (Man Page)" +.SH NAME +opacapture + + +.PP + +\fB(Host)\fR +Captures critical system information into a zipped tar file. The resulting tar file should be sent to Customer Support along with any Intel(R) Omni-Path Fabric problem report regarding this system. +.PP + +.B NOTE: +The resulting host capture file can require significant amounts of space on the host. The actual size varies, but sizes can be multiple megabytes. Intel recommends ensuring that adequate disk space is available on the host system. + + +.SH Syntax +opacapture [-d \fIdetail\fR] \fIoutput\(ultgz\(ulfile\fR +.SH Options + +.TP 10 +--help + +Produces full help text. + +.TP 10 +-d \fIdetail\fR + +Captures level of detail: +.RS +.TP 10 + +.sp +1 (Local) +Obtains local information from host. This is the default if no options are entered. + +.RE + +.RS +.TP 10 + +.sp +2 (Fabric) +In addition to \fILocal\fR, also obtains basic fabric information by queries to the SM and fabric error analysis using \fBopareport\fR. + +.RE + +.RS +.TP 10 + +.sp +3 (Fabric+FDB) +In addition to \fIFabric\fR, also obtains the Forwarding Database (FDB), which includes the switch forwarding tables from the SM and the server multicast membership. + +.RE + +.RS +.TP 10 + +.sp +4 (Analysis) +In addition to \fIFabric+FDB\fR, also obtains opaallanalysis results. If opaallanalysis has not yet been run, it is run as part of the capture. + +.RE + + +.TP 10 +.BR + +.PP + +.B NOTE: +Detail levels 2 - 4 can be used when fabric operational problems occur. If the problem is node-specific, detail level 1 should be sufficient. Detail levels 2 - 4 require an operational Fabric Manager. Typically your support representative requests a given detail level. If a given detail level takes excessively long or fails to be gathered, try a lower detail level. + +.PP +For detail levels 2 - 4, the additional information is only available on a node with Intel(R) Omni-Path Fabric Suite FastFabric Toolset installed. The information is gathered for every fabric specified in the /etc/opa/ports file. + +.TP 10 +\fIoutput\(ultgz\(ulfile\fR + +Specifies the name of a file to be created by opacapture. The file name specified is overwritten if it already exists. Intel recommends using the .tgz suffix in the file name supplied. If the filename given does not have a .tgz suffix, the .tgz suffix is added. + +.SH Examples +opacapture mycapture.tgz +.br + +opacapture -d 3 030127capture.tgz diff --git a/IbaTools/man/opacaptureall.manPage b/IbaTools/man/opacaptureall.manPage new file mode 100644 index 0000000..37de8a0 --- /dev/null +++ b/IbaTools/man/opacaptureall.manPage @@ -0,0 +1,262 @@ +.\" .\" ********************************************************************* +.\" .\" * * +.\" .\" * Copyright 2015-2019, Intel Corporation * +.\" .\" * * +.\" .\" * All Rights Reserved. * +.\" .\" * * +.\" .\" ********************************************************************* + +.TH opacaptureall 8 "Intel Corporation" "Copyright(C) 2015\-2019" "IFSFFCLIRG (Man Page)" +.SH NAME +opacaptureall + + +.PP + +\fB(Chassis and Host)\fR +Captures supporting information for a problem report from all hosts or Intel(R) Omni-Path Chassis and uploads to this system. +.PP + +\fBFor Hosts:\fR +When a host opacaptureall is performed, opacapture is run to create the specified capture file within ~root on each host (with the .tgz suffix added as needed). The files are uploaded and unpacked into a matching directory name within upload\(uldir/\fIhostname\fR/ on the local system. The default file name is hostcapture. +.PP + +\fBFor Chassis:\fR +When a chassis opacaptureall is performed, opacapture is run on each chassis and its output is saved to upload\(uldir/\fIchassisname\fR/\fIfile\fR on the local system. The default file name is chassiscapture. +.PP +For both host and chassis capture, the uploaded captures are combined into a .tgz file with the file name specified and the suffix .all.tgz added. +.SH Syntax +opacaptureall [-C] [-p] [-f \fIhostfile\fR] [-F \fIchassisfile\fR] [-h \[aq]\fIhosts\fR\[aq]] +.br + +[-H \[aq]\fIchassis\fR\[aq]] [-t \fIportsfile\fR] [-d \fIupload\(uldir\fR] [-S] [-D \fIdetail\(ullevel\fR] +.br + +[ \fIfile\fR] +.SH Options + +.TP 10 +--help + +Produces full help text. + +.TP 10 +-C + +Performs capture against chassis. Default is hosts. + +.TP 10 +-p + +Performs capture upload in parallel on all host/chassis. For a host capture, this only affects the upload phase. + +.TP 10 +-f \fIhostfile\fR + +Specifies the file with hosts in cluster. Default is /etc/opa/hosts file. + +.TP 10 +-F \fIchassisfile\fR + +Specifies the file containing a list of chassis in the cluster. Default is /etc/opa/chassis file. + +.TP 10 +-h \fIhosts\fR + +Specifies the list of hosts on which to perform a capture. + +.TP 10 +-H \fIchassis\fR + +Specifies the list of chassis on which to perform a capture. + +.TP 10 +-t \fIportsfile\fR + +Specifies the file with list of local HFI ports used to access fabric(s) for switch access. Default is /etc/opa/ports file. + +.TP 10 +-d \fIupload\(uldir\fR + +Specifies the directory to upload to. Default is uploads. If not specified, the environment variable \fBUPLOADS\(ulDIR\fR is used. If that is not exported, the default ./uploads is used. + +.TP 10 +-S + +Securely prompts for password for administrator on a chassis. + +.TP 10 +-D \fIdetail\(ullevel\fR + +Specifies the level of detail of the capture passed to host opacapture. (Only used for host captures; ignored for chassis captures.) +.RS +.TP 10 + +.sp +1 (Local) +Obtains local information from each host. +.RE + +.RS +.TP 10 + +.sp +2 (Fabric) +In addition to \fILocal\fR, also obtains basic fabric information by queries to the SM and fabric error analysis using opareport. + +.RE + +.RS +.TP 10 + +.sp +3 (Fabric+FDB) +In addition to \fIFabric\fR, also obtains the Forwarding Database (FDB), which includes the switch forwarding tables from the SM. + +.RE + +.RS +.TP 10 + +.sp +4 (Analysis) +In addition to \fIFabric+FDB\fR, also obtains opaallanalysis results. If opaallanalysis has not yet been run, it is run as part of the capture. + +.RE + + +.TP 10 +.BR + +.PP + +.B NOTE: +Detail levels 2-4 can be used when fabric operational problems occur. If the problem is node-specific, detail level 1 should be sufficient. Detail levels 2-4 require an operational Intel(R) Omni-Path Fabric Suite Fabric Manager. Typically your support representative requests a given detail level. If a given detail level takes excessively long or fails to be gathered, try a lower detail level. + +.PP +For detail levels 2-4, the additional information is only gathered on the node running the opacaptureall command. The information is gathered for every fabric specified in the /etc/opa/ports file. + +.TP 10 +\fIfile\fR + +Specifies the name for capture file. The suffix .tgz is appended if it is not specified in the name. + +.SH Examples + + +.SH Host Capture Examples +opacaptureall +.br + +# Creates a hostcapture directory in upload\(uldir/hostname/ for each host +.br +in +/etc/opa/hosts file, then creates hostcapture.all.tgz. +.br + + +.br + +opacaptureall mycapture +.br + +# Creates a mycapture directory in upload\(uldir/hostname/ for each host +.br +in +/etc/opa/hosts file, then creates mycapture.all.tgz. +.br + + +.br + +opacaptureall -h \[aq]arwen elrond\[aq] 030127capture +.br + +# Gets the list of hosts from arwen elrond file and creates +.br +030127capture.tgz file. + + +.SH Chassis Capture Examples +opacaptureall -C +.br + +# Creates a chassiscapture file in upload\(uldir/chassisname/ for each +.br +chassis +in /etc/opa/chassis file, then creates chassiscapture.all.tgz. +.br + + +.br + +opacaptureall -C mycapture +.br + +# Creates a mycapture.tgz file in upload\(uldir/chassisname/ for each +.br +chassis +in /etc/opa/chassis file, then creates mycapture.all.tgz. +.br + + +.br + +opacaptureall -C -H \[aq]chassis1 chassis2\[aq] 030127capture +.br + +# Captures from chassis1 and chassis2, and creates 030127capture.tgz file. +.SH Environment Variables + +.PP +The following environment variables are also used by this command: +.TP 10 +\fBHOSTS\fR + +List of hosts, used if -h option not supplied. + +.TP 10 +\fBCHASSIS\fR + +List of chassis, used if -C is used and -h option is not supplied. + +.TP 10 +\fBHOSTS\(ulFILE\fR + +File containing a list of hosts, used in the absence of -f and -h. + +.TP 10 +\fBCHASSIS\(ulFILE\fR + +File containing a list of chassis, used in the absence of -F and -H. + +.TP 10 +\fBUPLOADS\(ulDIR\fR + +Directory to upload to, used in the absence of -d. + +.TP 10 +\fBFF\(ulMAX\(ulPARALLEL\fR + +When -p option is used, maximum concurrent operations are performed. + +.TP 10 +\fBFF\(ulCHASSIS\(ulLOGIN\(ulMETHOD\fR + +How to log into chassis. Can be Telnet or SSH. + +.TP 10 +\fBFF\(ulCHASSIS\(ulADMIN\(ulPASSWORD\fR + +Password for administrator on all chassis. Used in absence of -S option. + +.SH More Information + +.PP +When performing opacaptureall against hosts, internally SSH is used. The command opacaptureall requires that password-less SSH be set up between the host running Intel(R) Omni-Path Fabric Suite FastFabric Toolset and the hosts opacaptureall is operating against. The opasetupssh command can aid in setting up password-less SSH. +.PP +When performing operations against chassis, Intel recommends that you set up SSH keys using opasetupssh. If SSH keys are not set up, Intel recommends that all chassis be configured with the same admin password and that you use of the -S option to avoid keeping the password in configuration files. +.PP + +.B NOTE: +The resulting host capture files can require significant amounts of space on the Intel(R) Omni-Path Fabric Suite FastFabric Toolset host. Actual size varies, but sizes can be multiple megabytes per host. Intel recommends that you ensure adequate space is available on the Intel(R) Omni-Path Fabric Suite FastFabric Toolset system. In many cases, it may not be necessary to run opacaptureall against all hosts or chassis; instead, a representative subset may be sufficient. Consult with your support representative for further information. diff --git a/IbaTools/man/opachassisadmin.manPage b/IbaTools/man/opachassisadmin.manPage new file mode 100644 index 0000000..5e00631 --- /dev/null +++ b/IbaTools/man/opachassisadmin.manPage @@ -0,0 +1,546 @@ +.\" .\" ********************************************************************* +.\" .\" * * +.\" .\" * Copyright 2015-2019, Intel Corporation * +.\" .\" * * +.\" .\" * All Rights Reserved. * +.\" .\" * * +.\" .\" ********************************************************************* + +.TH opachassisadmin 8 "Intel Corporation" "Copyright(C) 2015\-2019" "IFSFFCLIRG (Man Page)" +.SH NAME +opachassisadmin + + +.PP + +\fB(Switch)\fR +Performs a number of multi-step chassis initialization and verification operations, including initial chassis setup, firmware upgrades, chassis reboot, and others. +.SH Syntax +opachassisadmin [-c] [-F \fIchassisfile\fR] [-H \[aq]\fIchassis\fR\[aq]] [-P \fIpackages\fR] +.br + +[-a \fIaction\fR] [-I \fIfm\(ulbootstate\fR] [-S] [-d \fIupload\(uldir\fR] [-s \fIsecurityfiles\fR] +.br + +\fIoperation\fR ... +.SH Options + +.TP 10 +--help + +Produces full help text. + +.TP 10 +-c + +Overwrites the result files from any previous run before starting this run. + +.TP 10 +-F \fIchassisfile\fR + +Specifies the file with chassis in cluster. The default is /etc/opa/chassis. + +.TP 10 +-H \fIchassis\fR + +Specifies the list of chassis to execute the operation against. + +.TP 10 +-P \fIpackages\fR + +Specifies the filenames and directories of firmware images to install. + +.RS + +.IP \(bu +For directories specified, all .pkg, .dpkg, and .spkg files in directory tree are used. shell wild cards may also be used within quotes. +.IP \(bu +For fmconfig, filename of FM config file is used. +.IP \(bu +For fmgetconfig, filename to upload to is used. Default opafm.xml. + +.RE + +.TP 10 +-a \fIaction\fR + +Specifies the action for the supplied file. The default is push. +.RS +.TP 10 + +.sp +For chassis upgrade: + +.RS +.TP 10 + +.sp +push +Ensures firmware is in primary or alternate. + +.RE + +.RS +.TP 10 + +.sp +select +Ensures firmware is in primary. + +.RE + +.RS +.TP 10 + +.sp +run +Ensures firmware is in primary and running. + +.RE + +.RE + + +.RS +.TP 10 + +.sp +For chassis fmconfig : + +.RS +.TP 10 + +.sp +push +Ensures the configuration file is in chassis. + +.RE + +.RS +.TP 10 + +.sp +run +After push, restarts FM on master, stops on secondary. + +.RE + +.RS +.TP 10 + +.sp +runall +After push, restarts FM on all management modules. + +.RE + +.RE + +.RS +.TP 10 + +.sp +For chassis fmcontrol : + +.RS +.TP 10 + +.sp +stop +Stops FM on all management modules. + +.RE + +.RS +.TP 10 + +.sp +run +Ensures FM running on master, stopped on secondary. + +.RE + +.RS +.TP 10 + +.sp +runall +Ensures FM running on all management modules. + +.RE + +.RS +.TP 10 + +.sp +restart +Restarts FM on master, stops on secondary. + +.RE + +.RS +.TP 10 + +.sp +restartall +Restarts FM on all MM. + +.RE + +.RE + +.RS +.TP 10 + +.sp +For chassis fmsecurityfiles : + +.RS +.TP 10 + +.sp +push +Ensures FM security files are in chassis. + +.RE + +.RS +.TP 10 + +.sp +restart +After push, restarts FM on master, stop on slave. + +.RE + +.RS +.TP 10 + +.sp +restartall +After push, restarts FM on all MM + +.RE + +.RE + +.TP 10 +-I \fIfm\(ulbootstate\fR + +Specifies the fmconfig and fmcontrol install options. +.RS +.TP 10 + +.sp +disable +Disables FM start at chassis boot. + +.RE + +.RS +.TP 10 + +.sp +enable +Enables FM start on master at chassis boot. + +.RE + +.RS +.TP 10 + +.sp +enableall +Enables FM start on all MM at chassis boot. + +.RE + + +.TP 10 +-d \fIupload\(uldir\fR + +Specifies the directory to upload FM configuration files to. Default is uploads. + +.TP 10 +-S + +Securely prompts for password for user on chassis. + +.TP 10 +-s \fIsecurityFiles\fR + +Specifies the security files to install. Default is *.pem. For Chassis \fIfmsecurityfiles\fR, filenames/directories of security files to install. For directories specified, all security files in directory tree are used. Shell wildcards may also be used within quotes. + +.IP +For Chassis \fIfmgetsecurityfiles\fR, filename to upload to. Default is *.pem +.TP 10 +\fIoperation\fR + +Specifies the operation to perform. Can be one or more of: +.RS +.TP 10 + +.sp +reboot +Reboots chassis, ensures they go down and come back. + +.RE + +.RS +.TP 10 + +.sp +configure +Runs wizard to perform chassis configuration. + +.RE + +.RS +.TP 10 + +.sp +upgrade +Upgrades install of all chassis. + +.RE + +.RS +.TP 10 + +.sp +getconfig +Gets basic configuration of chassis. + +.RE + +.RS +.TP 10 + +.sp +fmconfig +FM configuration operation on all chassis. + +.RE + +.RS +.TP 10 + +.sp +fmgetconfig +Fetches FM configuration from all chassis. + +.RE + +.RS +.TP 10 + +.sp +fmcontrol +Controls FM on all chassis. + +.RE + +.RS +.TP 10 + +.sp +fmsecurityfiles +FM security files operation on all chassis. + +.RE + +.RS +.TP 10 + +.sp +fmgetsecurityfiles +Fetches FM security files from all chassis. + +.RE + +For more information on the operations that can be performed, see +\fIOperation Details\fR +. + +.SH Example +opachassisadmin -c reboot +.br + +opachassisadmin -P /root/ChassisFw4.2.0.0.1 upgrade +.br + +opachassisadmin -H \[aq]chassis1 chassis2\[aq] reboot +.br + +CHASSIS=\[aq]chassis1 chassis2\[aq] opachassis\(uladmin reboot +.br + +opachassisadmin -a run -P \[aq]*.pkg\[aq] upgrade +.SH Environment Variables + +.PP +The following environment variables are also used by this command: +.TP 10 +\fBCHASSIS\fR + +List of chassis, used if -H and -F option not supplied. + +.TP 10 +\fBCHASSIS\(ulFILE\fR + +File containing list of chassis, used in absence of -F and -H. + +.TP 10 +\fBFF\(ulMAX\(ulPARALLEL\fR + +Maximum concurrent operations. + +.TP 10 +\fBFF\(ulSERIALIZE\(ulOUTPUT\fR + +Serializes output of parallel operations (yes or no). + +.TP 10 +\fBFF\(ulTIMEOUT\(ulMULT\fR + +Multiplier for all timeouts associated with this command. Used if the systems are slow for some reason. + +.TP 10 +\fBUPLOADS\(ulDIR\fR + +Directory to upload to, used in absence of -d. + + +.SH Operation Details + +.PP + +\fB(Switch)\fR +All chassis operations log into the chassis as chassis user admin. Intel recommends using the -S option to securely prompt for a password, in which case the same password is used for all chassis. Alternately, the password may be put in the environment or the opafastfabric.conf file using \fBFF\(ulCHASSIS\(ulADMIN\(ulPASSWORD\fR. +.PP +All versions of Intel(R) Omni-Path Switch 100 Series firmware permit SSH keys to be configured within the chassis for secure password-less login. In this case, there is no need to configure a \fBFF\(ulCHASSIS\(ulADMIN\(ulPASSWORD\fR ; and, \fBFF\(ulCHASSIS\(ulLOGIN\(ulMETHOD\fR can be SSH. Refer to the +\fIIntel(R) Omni-Path Fabric Suite FastFabric User Guide\fR + + for more information. +.TP 10 +upgrade + +Upgrades the firmware on each chassis or slot specified. The -P option selects a directory containing .pkg files or provides an explicit list of .pkg files for the chassis and/or slots. The -a option selects the desired minimal state for the new firmware. For each chassis and/or slot selected for upgrade, the .pkg file applicable to that slot is selected and used. If more than one .pkg file is specified of a given card type, the operation is undefined. + +.IP +The upgrade is intelligent and does not upgrade chassis that already have the desired firmware in the desired state (as specified by -a). +.IP +When the -a option specifies run, chassis that are not already running the desired firmware are rebooted. By selecting the proper \fBFF\(ulMAX\(ulPARALLEL\fR value, a rolling upgrade or a parallel upgrade may be accomplished. In most cases, a parallel upgrade is recommended for expediency. +.IP +For more information about chassis firmware, refer to the +\fIIntel(R) Omni-Path Fabric Switches GUI User Guide\fR + +and +\fIIntel(R) Omni-Path Fabric Switches Release Notes\fR + +. +.TP 10 +configure + +Runs the chassis setup wizard, which asks a series of questions. Once the wizard has finished prompting for configuration information, all the selected chassis are configured through the CLI interface according to the responses. The following options may be configured for all chassis: + +.RS + +.IP \(bu +Syslog server IP address, TCP/UDP port number, syslog facility code, and the chassis LogMode. + +.IP \(bu +NTP server + +.IP \(bu +Local time zone + +.IP \(bu +Link CRC Mode + +.IP \(bu +Link width supported + +.IP \(bu +Node description + + +.RE + +.TP 10 +reboot + +Reboots the given chassis and ensures they go down and come back up by pinging them during the reboot process. + +.IP +By selecting the proper \fBFF\(ulMAX\(ulPARALLEL\fR value, a rolling reboot or a parallel reboot may be accomplished. In most cases, a parallel upgrade is recommended for expediency. +.TP 10 +getconfig + +Retrieves basic information from a chassis such as syslog, NTP configuration, timezone info, Link CRC Mode, Link Width, and node description. + +.TP 10 +fmconfig + +Updates the Fabric Manager configuration file on each chassis specified. The -P option selects a file to transfer to the chassis. The -a option selects the desired minimal state for the new configuration and controls whether the FM is started/restarted after the file is updated. The -I option can be used to configure the FM start at boot for the selected chassis. + +.TP 10 +fmgetconfig + +Uploads the FM configuration file from all selected chassis. The file is uploaded to the selected uploads directory. The -P option specifies the desired destination filename within the uploads directory. + +.TP 10 +fmcontrol + +Allows the FM to be controlled on each chassis specified. The -a option selects the desired state for the FM. + +.IP +The -I option configures the FM start at boot for the selected chassis. +.TP 10 +fmsecurityfiles + +Updates the FM security files on each chassis specified. The -s option selects file(s) to transfer to the chassis. The -a option selects the desired minimal state for the new security files. In this release, push is the only supported action. + +.TP 10 +fmgetsecurityfiles + +Uploads the FM security files from all selected chassis. The files are uploaded to the selected uploads directory. The -s option specifies the desired destination filename within the uploads directory. + +.SH Logging + +.PP +opachassisadmin provides detailed logging of its results. During each run, the following files are produced: +.TP 10 +test.res + +This file is appended with summary results of run. + +.TP 10 +test.log + +This file is appended with detailed results of run. + +.TP 10 +save\(ultmp/ + +This file is contains a directory per failed test with detailed logs. + +.TP 10 +test\(ultmp*/ + +This file contains the intermediate results while the test is running. + +.PP +The -c option removes all log files. +.SH ssh Keys + +.PP +When performing operations against chassis, Intel recommends setting up SSH keys. If SSH keys are not set up, all chassis must be configured with the same admin password. In this case, Intel recommends using the -S option. The -S option avoids the need to keep the password in configuration files. +.SH Results + +.PP +Results from opachassisadmin are grouped into test suites, test cases, and test items. A given run of opachassisadmin represents a single test suite. Within a test suite, multiple test cases occur; typically one test case per chassis being operated on. Some of the more complex operations may have multiple test items per test case. Each test item represents a major step in the overall test case. +.PP +Each opachassisadmin run appends to test.res and test.log, and creates temporary files in test\(ultmp$PID in the current directory. The test.res file provides an overall summary of operations performed and their results. The same information is also displayed while opachassisadmin is executing. test.log contains detailed information about what was performed, including the specific commands executed and the resulting output. The test\(ultmp directories contain temporary files that reflect tests in progress (or killed). The logs for any failures are logged in the save\(ultemp directory with a directory per failed test case. If the same test case fails more than once, save\(ultemp retains the information from the first failure. Subsequent runs of opachassisadmin are appended to test.log. Intel recommends reviewing failures and using the -c option to remove old logs before subsequent runs of opachassisadmin. +.PP +opachassisadmin implicitly performs its operations in parallel. However, as for the other tools, \fBFF\(ulMAX\(ulPARALLEL\fR can be exported to change the degree of parallelism. 1000 parallel operations is the default. diff --git a/IbaTools/man/opachassisanalysis.manPage b/IbaTools/man/opachassisanalysis.manPage new file mode 100644 index 0000000..c711822 --- /dev/null +++ b/IbaTools/man/opachassisanalysis.manPage @@ -0,0 +1,261 @@ +.\" .\" ********************************************************************* +.\" .\" * * +.\" .\" * Copyright 2015-2019, Intel Corporation * +.\" .\" * * +.\" .\" * All Rights Reserved. * +.\" .\" * * +.\" .\" ********************************************************************* + +.TH opachassisanalysis 8 "Intel Corporation" "Copyright(C) 2015\-2019" "IFSFFCLIRG (Man Page)" +.SH NAME +opachassisanalysis + + +.PP + +\fB(Switch)\fR +Performs analysis of the chassis. +.PP +The opachassisanalysis tool checks the following for the Intel(R) Omni-Path Fabric Chassis: +.IP \(bu +Chassis configuration (as reported by the chassis commands specified in \fBFF\(ulCHASSIS\(ulCMDS\fR in opafastfabric.conf). +.IP \(bu +Chassis health (as reported by the chassis command specified in \fBFF\(ulCHASSIS\(ulHEALTH\fR in opafastfabric.conf). +.SH Syntax +opachassisanalysis [-b|-e] [-s] [-d \fIdir\fR] [-F \fIchassisfile\fR] +.br +[-H \[aq]\fIchassis\fR\[aq]] +.SH Options + +.TP 10 +--help + +Produces full help text. +.TP 10 +-b + +Specifies the baseline mode. Default is the compare/check mode. +.TP 10 +-e + +Evaluates health only. Default is the compare/check mode. +.TP 10 +-s + +Saves history of failures (errors/differences). +.TP 10 +-d \fIdir\fR + +Specifies the top-level directory for saving baseline and history of failed checks. Default is /var/usr/lib/opa/analysis +.TP 10 +-F \fIchassisfile\fR + +Specifies the file with the chassis in the cluster. Default is /etc/opa/chassis +.TP 10 +-H \[aq]\fIchassis\fR\[aq] + +Specifies the list of chassis on which to execute the command. +.SH Example +opachassisanalysis +.SH Environment Variables + +.PP +The following environment variables are also used by this command: +.TP 10 +\fBCHASSIS\fR + +List of chassis, used if -F and -H options are not supplied. +.TP 10 +\fBCHASSIS\(ulFILE\fR + +File containing list of chassis, used if -F and -H options are not supplied. +.TP 10 +\fBFF\(ulANALYSIS\(ulDIR\fR + +Top-level directory for baselines and failed health checks. +.TP 10 +\fBFF\(ulCHASSIS\(ulCMDS\fR + +List of commands to issue during analysis, unused if -e option supplied. + +.TP 10 +\fBFF\(ulCHASSIS\(ulHEALTH\fR + +Single command to issue to check overall health during analysis, unused if -b option supplied. + +.SH Details + +.PP +Intel recommends that you set up SSH keys for chassis (see +\fIopasetupssh\fR +). If SSH keys are not set up, all chassis must be configured with the same admin password and the password must be kept in the /etc/opa/opafastfabric.conf configuration file. +.PP +The default set of \fBFF\(ulCHASSIS\(ulCMDS\fR is: +.PP + +.br +showInventory fwVersion showNodeDesc timeZoneConf timeDSTConf +.br + +snmpCommunityConf snmpTargetAddr showChassisIpAddr showDefaultRoute + +.br + +.PP +The commands specified in \fBFF\(ulCHASSIS\(ulCMDS\fR must be simple commands with no arguments. The output of these commands are compared to the baseline using \fBFF\(ulDIFF\(ulCMD\fR. Therefore, commands that include dynamically changing values, such as port packet counters, should not be included in this list. +.PP +\fBFF\(ulCHASSIS\(ulHEALTH\fR can specify one command (with arguments) to be used to check the chassis health. For chassis with newer firmware, the hwCheck command is recommended. For chassis with older firmware, a benign command, such as fruInfo, should be used. The default is hwCheck. Note that only the exit status of the FF\(ulCHASSIS\(ulHEALTH command is checked. The output is not captured and compared in a snapshot. However, on failure its output is saved to aid diagnosis. +.PP +The opachassisanalysis tool performs its analysis against one or more chassis in the fabric. As such, it permits the chassis to be specified using the -H, -F, CHASSIS, chassis\(ulfile or opafastfabric.conf. The handling of these options and settings is comparable to opacmdall -C and similar FastFabric Toolset commands against a chassis. +.PP +All files generated by opafabricanalysis start with chassis. in the file name. +.PP +The opachassisanalysis tool generates files such as the following within FF\(ulANALYSIS\(ulDIR. The actual file names reflect the individual chassis commands that have been configured through the FF\(ulCHASSIS\(ulHEALTH and FF\(ulCHASSIS\(ulCMDS parameters: +.PP + +\fBHealth Check\fR + +.IP \(bu +latest/chassis.hwCheck Output of hwCheck command for all selected chassis + +.PP + +\fBBaseline:\fR +During a baseline run, the following files are also created in \fIFF\(ulANALYSIS\(ulDIR\fR /latest. +.IP \(bu +baseline/chassis.fwVersion Output of fwVersion command for all selected chassis. + +.IP \(bu +baseline/chassis.showChassisIpAddr Output of the showChassisIpAddr. command for all selected chassis. + +.IP \(bu +baseline/chassis.showDefaultRoute Output of the showDefaultRoute command for all selected chassis. + +.IP \(bu +baseline/chassis.showNodeDesc Output of the showNodeDesc command for all selected chassis. + +.IP \(bu +baseline/chassis.showInventory Output of the showInventory command for all selected chassis. + +.IP \(bu +baseline/chassis.snmpCommunityConf Output of the snmpCommunityConf command for all selected chassis. + +.IP \(bu +baseline/chassis.snmpTargetAddr Output of the snmpTargetAddr command for all selected chassis. + +.IP \(bu +baseline/chassis.timeDSTConf Output of the timeDSTConf command for all selected chassis. + +.IP \(bu +baseline/chassis.timeZoneConf Output of the timeZoneConf command for all selected chassis. + +.PP + +\fBFull Analysis:\fR +The following .diff files are only created if differences are detected. +.IP \(bu +latest/chassis.hwCheck Output of the hwCheck command for all selected chassis. + +.IP \(bu +latest/chassis.fwVersion Output of the fwVersion command for all selected chassis. + +.IP \(bu +latest/chassis.fwVersion.diff diff of the baseline and latest fwVersion. + +.IP \(bu +latest/chassis.showChassisIpAddr Output of the showChassisIpAddr command for all selected chassis. + +.IP \(bu +latest/chassis.showChassisIpAddr.diff diff of baseline and latest showChassisIpAddr. + +.IP \(bu +latest/chassis.showDefaultRoute Output of the showDefaultRoute command for all selected chassis. + +.IP \(bu +latest/chassis.showDefaultRoute.diff diff of the baseline and the latest showDefaultRoute. + +.IP \(bu +latest/chassis.showNodeDesc Output of the showNodeDesc command for all selected chassis. + +.IP \(bu +latest/chassis.showNodeDesc.diff diff of the baseline and latest showNodeDesc. + +.IP \(bu +latest/chassis.showInventory Output of the showInventory command for all selected chassis. + +.IP \(bu +latest/chassis.showInventory.diff diff of the baseline and latest showInventory. + +.IP \(bu +latest/chassis.snmpCommunityConf Output of the snmpCommunityConf command for all selected chassis. + +.IP \(bu +latest/chassis.snmpCommunityConf.diff diff of the baseline and latest snmpCommunityConf. + +.IP \(bu +latest/chassis.snmpTargetAddr Output of the snmpTargetAddr command for all selected chassis. + +.IP \(bu +latest/chassis.snmpTargetAddr.diff diff of the baseline and latest snmpTargetAddr. + +.IP \(bu +latest/chassis.timeDSTConf Output of the timeDSTConf command for all selected chassis. + +.IP \(bu +latest/chassis.timeDSTConf.diff diff of the baseline and latest timeDSTConf. + +.IP \(bu +latest/chassis.timeZoneConf Output of the timeZoneConf command for all selected chassis. + +.IP \(bu +latest/chassis.timeZoneConf.diff diff of the baseline and latest timeZonfConf. + +.PP +If the -s option is used and failures are detected, files related to the checks that failed are also copied to a time-stamped directory name under FF\(ulANALYSIS\(ulDIR. +.SH Chassis Items Checked Against the Baseline + +.PP +Based upon showInventory : +.IP \(bu +Addition/removal of Chassis FRUsReplacement is only checked for FRUs that showInventory displays the serial number. + +.IP \(bu +Removal of redundant FRUs (spines, power supply, fan) +.PP +Based upon fwVersion: +.IP \(bu +Changes to primary or alternate FW versions installed in cards in chassis. +.PP +Based upon showNodeDesc: +.IP \(bu +Changes to configured node description for chassis. Note changes detected here would also be detected in fabric level analysis. +.PP +Based upon timeZoneConf and timeDSTConf: +.IP \(bu +Changes to the chassis time zone and daylight savings time configuration. +.PP +Based upon snmpCommunityConf and snmpTargetAddr: +.IP \(bu +Changes to SNMP persistent configuration within the chassis. +.PP +The following Chassis items are not checked against baseline: +.IP \(bu +Changes to the chassis configuration on the management LAN (for example, showChassisIpAddr, showDefaultRoute). Such changes typically result in the chassis not responding on the LAN at the expected address that is detected by failures that perform other chassis checks. +.SH Chassis Items Also Checked During Health Check + +.PP +Based upon hwCheck: +.IP \(bu +Overall health of FRUs in chassis: +.IP \(bu +Status of Fans in chassis +.IP \(bu +Status of Power Supplies in chassis +.IP \(bu +Temp/Voltage for each card +.IP \(bu +Presence of adequate power/cooling of FRUs +.IP \(bu +Presence of N+1 power/cooling of FRUs +.IP \(bu +Presence of Redundant AC input diff --git a/IbaTools/man/opacheckload.manPage b/IbaTools/man/opacheckload.manPage new file mode 100644 index 0000000..a6943bb --- /dev/null +++ b/IbaTools/man/opacheckload.manPage @@ -0,0 +1,85 @@ +.\" .\" ********************************************************************* +.\" .\" * * +.\" .\" * Copyright 2015-2019, Intel Corporation * +.\" .\" * * +.\" .\" * All Rights Reserved. * +.\" .\" * * +.\" .\" ********************************************************************* + +.TH opacheckload 8 "Intel Corporation" "Copyright(C) 2015\-2019" "IFSFFCLIRG (Man Page)" +.SH NAME +opacheckload + + +.PP +Returns load information on hosts in the fabric. +.SH Syntax +opacheckload [-f \fIhostfile\fR] [-h \[aq]\fIhosts\fR\[aq]] [-r] [-a|-n numprocs] +.br +[-d uploaddir] +.SH Options + +.TP 10 +--help + +Produces full help text. + +.TP 10 +-f \fIhostfile\fR + +Specifies the file with hosts to check. Default is /etc/opa/hosts + +.TP 10 +-h \fIhosts\fR + +Specifies the list of hosts to check. + +.TP 10 +-r + +Reverses output to show the least busy hosts. Default is busiest hosts. +.TP 10 +-n \fInumprocs\fR + +Shows the specified number of top \fInumprocs\fR hosts. Default is 10. +.TP 10 +-a + +Shows all hosts. Default is 10. + +.TP 10 +-d \fIupload\(uldir\fR + +Specifies the target directory to upload loadavg. Default is uploads. + +.SH Examples +opacheckload +.br + +opacheckload -h \[aq]arwen elrond\[aq] +.br + +HOSTS=\[aq]arwen elrond\[aq] opacheckload +.SH Environment Variables + +.PP +The following environment variables are also used by this command: +.TP 10 +\fBHOSTS\fR + +List of hosts, used if -h option not supplied. + +.TP 10 +\fBHOSTS\(ulFILE\fR + +File containing list of hosts, used in absence of -f and -h. + +.TP 10 +\fBUPLOADS\(ulDIR\fR + +Directory to upload loadavg, used in absence of -d. + +.TP 10 +\fBFF\(ulMAX\(ulPARALLEL\fR + +Maximum concurrent operations. diff --git a/IbaTools/man/opacmdall.manPage b/IbaTools/man/opacmdall.manPage new file mode 100644 index 0000000..5c1a7fa --- /dev/null +++ b/IbaTools/man/opacmdall.manPage @@ -0,0 +1,183 @@ +.\" .\" ********************************************************************* +.\" .\" * * +.\" .\" * Copyright 2015-2019, Intel Corporation * +.\" .\" * * +.\" .\" * All Rights Reserved. * +.\" .\" * * +.\" .\" ********************************************************************* + +.TH opacmdall 8 "Intel Corporation" "Copyright(C) 2015\-2019" "IFSFFCLIRG (Man Page)" +.SH NAME +opacmdall + + +.PP + +\fB(Linux and Switch)\fR +Executes a command on all hosts or Intel(R) Omni-Path Chassis. This powerful command can be used for configuring servers or chassis, verifying that they are running, starting and stopping host processes, and other tasks. +.PP + +.B NOTE: +opacmdall depends on the Linux* convention that utilities return 0 for success and >0 for failure. If opacmdall is used to execute a non-standard utility like diff or a program that uses custom exit codes, then opacmdall may erroneously report "Command execution FAILED" when it encounters a non-zero exit code. However, command output is still returned normally and the error may be safely ignored. + +.SH Syntax +opacmdall [-CpqPS] [-f \fIhostfile\fR] [-F \fIchassisfile\fR] [-h \fIhosts\fR] +.br +[-H \fIchassis\fR] +[-u \fIuser\fR] [-m \fImarker\fR] [-T \fItimelimit\fR] \fIcmd\fR +.SH Options + +.TP 10 +--help + +Produces full help text. + +.TP 10 +-C + +Performs command against chassis. Default is hosts. + +.TP 10 +-p + +Runs command in parallel on all hosts/chassis. + +.TP 10 +-q + +Quiet mode, do not show command to execute. + +.TP 10 +-P + +Outputs the hostname/chassis name as prefix to each output line. This can make script processing of output easier. + +.TP 10 +-S + +Securely prompts for password for user on chassis. + +.TP 10 +-f \fIhostfile\fR + +Specifies the file with hosts in cluster. Default is /etc/opa/hosts file. + +.TP 10 +-F \fIchassisfile\fR + +Specifies the file with chassis in cluster. Default is /etc/opa/chassis file. + +.TP 10 +-h \fIhost\fR + +Specifies the list of hosts to execute command on. + +.TP 10 +-H \fIchassis\fR + +Specifies the list of chassis to execute command on. + +.TP 10 +-u \fIuser\fR + +Specifies the user to perform the command as: +.RS + +.IP \(bu +For hosts, the default is current user code. +.IP \(bu +For chassis, the default is admin. + +.RE + + +.TP 10 +-m \fImarker\fR + +Specifies the marker for end of chassis command output. If omitted, defaults to chassis command prompt. This may be a regular expression. + +.TP 10 +-T \fItimelimit\fR + +Specifies the time limit in seconds when running host commands. Default is -1 (infinite). + +.SH Examples + + +.SH Operations on Host +opacmdall date +.br + +opacmdall \[aq]uname -a\[aq] +.br + +opacmdall -h \[aq]elrond arwen\[aq] date +.br + +HOSTS=\[aq]elrond arwen\[aq] opacmdall date + +.SH Operations on Chassis +opacmdall -C \[aq]ismPortStats -noprompt\[aq] +.br + +opacmdall -C -H \[aq]chassis1 chassis2\[aq] ismPortStats -noprompt\[aq] +.br + +CHASSIS=\[aq]chassis1 chassis2\[aq] opacmdall -C ismPortStats -noprompt\[aq] +.SH Environment Variables + +.PP +The following environment variables are also used by this command: +.TP 10 +\fBHOSTS\fR + +List of hosts, used if -h option not supplied. + +.TP 10 +\fBCHASSIS\fR + +List of chassis, used if -C is used and -H and -F options not supplied. + +.TP 10 +\fBHOSTS\(ulFILE\fR + +File containing list of hosts, used in absence of -f and -h. + +.TP 10 +\fBCHASSIS\(ulFILE\fR + +File containing list of chassis, used in absence of -F and -H. + +.TP 10 +\fBFF\(ulMAX\(ulPARALLEL\fR + +When -p option is used, maximum concurrent operations are performed. + +.TP 10 +\fBFF\(ulSERIALIZE\(ulOUTPUT\fR + +Serialize output of parallel operations (yes or no). + +.TP 10 +\fBFF\(ulCHASSIS\(ulLOGIN\(ulMETHOD\fR + +How to log into chassis. Can be Telnet or SSH. + +.TP 10 +\fBFF\(ulCHASSIS\(ulADMIN\(ulPASSWORD\fR + +Password for admin on all chassis. Used in absence of -S option. + +.SH Notes + +.PP +All commands performed with opacmdall must be non-interactive in nature. opacmdall waits for the command to complete before proceeding. For example, when running host commands such as rm, the -i option (interactively prompt before removal) should not be used. (Note that this option is sometimes part of a standard bash alias list.) Similarly, when running chassis commands such as fwUpdateChassis, the -reboot option should not be used because this option causes an immediate reboot and therefore the command never returns. Also, the chassis command reboot should not be executed using opacmdall. Instead, use the opachassisadmin reboot command to reboot one or more chassis. For further information about individual chassis CLI commands, consult the +\fIIntel(R) Omni-Path Fabric Switches Command Line Interface Reference Guide\fR + +. For further information about Linux* operating system commands, consult the man pages. +.PP +When performing opacmdall against hosts, internally SSH is used. The command opacmdall requires that password-less SSH be set up between the host running the Intel(R) Omni-Path Fabric Suite FastFabric Toolset and the hosts opacmdall is operating against. The opasetupssh FastFabric tool can aid in setting up password-less SSH. +.PP +When performing opacmdall against a set of chassis, all chassis must be configured with the same admin password. Alternatively, the opasetupssh FastFabric tool can be used to set up password-less SSH to the chassis. +.PP +When performing operations against chassis, Intel recommends that you set up SSH keys using opasetupssh. If SSH keys are not set up, Intel recommends that you use the -S option to avoid keeping the password in configuration files. diff --git a/IbaTools/man/opaconfig.manPage b/IbaTools/man/opaconfig.manPage new file mode 100644 index 0000000..56b8a43 --- /dev/null +++ b/IbaTools/man/opaconfig.manPage @@ -0,0 +1,184 @@ +.\" .\" ********************************************************************* +.\" .\" * * +.\" .\" * Copyright 2015-2019, Intel Corporation * +.\" .\" * * +.\" .\" * All Rights Reserved. * +.\" .\" * * +.\" .\" ********************************************************************* + +.TH opaconfig 1 "Intel Corporation" "Copyright(C) 2015\-2019" "IFSFFCLIRG (Man Page)" +.SH NAME +opaconfig + + +.PP + +\fB(Switch and Host)\fR +Configures the Intel(R) Omni-Path Software through command line interface or TUI menus. +.SH Syntax +opaconfig [-G] [-v|-vv] [-u|-s|-e \fIcomp\fR] [-E \fIcomp\fR] [-D \fIcomp\fR] +.br + +[--user\(ulqueries|--no\(uluser\(ulqueries] [--answer \fIkeyword=value\fR] +.PP +or +.br +opaconfig -C +.PP +or +.br +opaconfig -V +.SH Options + +.TP 10 +No option + +Starts the Intel(R) Omni-Path Software TUI. + +.TP 10 +--help + +Produces full help text. + +.TP 10 +-G + +Installs GPU Direct components (must have NVidia drivers installed). + +.TP 10 +-v + +Specifies verbose logging. + +.TP 10 +-vv + +Specifies very verbose debug logging. + +.TP 10 +-u + +Uninstalls all ULPs and drivers with default options. + +.TP 10 +-s + +Enables autostart for all installed drivers. + +.TP 10 +-e \fIcomp\fR + +Uninstalls the given component with default options. This option can appear more than once on the command line. + +.TP 10 +-E \fIcomp\fR + +Enables autostart of a given component. This option can appear with -D or more than once on the command line. + +.TP 10 +-D \fIcomp\fR + +Disables autostart of given component. This option can appear with -E or more than once on the command line. + +.TP 10 +-C + +Outputs list of supported components. + +.IP + +\fBNOTE:\fR +Supported components may vary according to OS. Refer to +\fIIntel(R) Omni-Path Fabric Software Release Notes\fR + +, OS RPMs Installation Prerequisites for the list of components by supported OS. +.IP +Supported components include: opa\(ulstack oftools intel\(ulhfi opa\(ulstack\(uldev delta\(ulipoib opamgt\(ulsdk mvapich2\(ulgcc\(ulhfi openmpi\(ulgcc\(ulhfi openmpi\(ulgcc\(ulcuda\(ulhfi sandiashmem mpisrc delta\(uldebug +.IP +Supported components when using command on a Management Node with Intel(R) Omni-Path Fabric Suite installed, include: fastfabric opafm +.IP +Supported component name aliases include: opa ipoib mpi psm\(ulmpi verbs\(ulmpi pgas opadev +.IP +Additional component names allowed for -E and -D options: ibacm rdma\(ulndd delta\(ulsrp delta\(ulsrpt +.TP 10 +-V + +Outputs version. + +.TP 10 +--user\(ulqueries + +Permits non-root users to query the fabric (Default). + +.TP 10 +--no\(uluser\(ulqueries + +Prohibits non-root users from querying the fabric. + +.TP 10 +--answer \fIkeyword=value\fR + +Provides an answer to a question that may occur during the operation. Answers to questions not asked are ignored. Invalid answers result in prompting for interactive installs, or using default options for non-interactive installs. + +.IP + +\fBPossible Questions\fR +(\fIkeyword=value\fR): +.RS +.TP 10 + +.sp +UserQueries +Allow non-root users to access the UMAD interface? + +.TP 10 +.BR + +.PP + +.B NOTE: +Allowing access to UMAD device files may present a security risk. However, this allows tools such as opasaquery and opaportinfo to be used by non-root users. + +.RE + +.RS +.TP 10 + +.sp +ARPTABLE\(ulTUNING +Adjust kernel ARP table size for large fabrics? + +.RE + +.SH Example +# opaconfig +.br + +Intel OPA \fIx.x.x.x.x\fR Software +.br + + +.br + + 1) Show Installed Software +.br + + 2) Reconfigure OFED IP over IB +.br + + 3) Reconfigure Driver Autostart +.br + + 4) Generate Supporting Information for Problem Report +.br + + 5) FastFabric (Host/Chassis/Switch Setup/Admin) +.br + + 6) Uninstall Software +.br + + +.br + + X) Exit diff --git a/IbaTools/man/opadisablehosts.manPage b/IbaTools/man/opadisablehosts.manPage new file mode 100644 index 0000000..85c1a2a --- /dev/null +++ b/IbaTools/man/opadisablehosts.manPage @@ -0,0 +1,88 @@ +.\" .\" ********************************************************************* +.\" .\" * * +.\" .\" * Copyright 2015-2019, Intel Corporation * +.\" .\" * * +.\" .\" * All Rights Reserved. * +.\" .\" * * +.\" .\" ********************************************************************* + +.TH opadisablehosts 8 "Intel Corporation" "Copyright(C) 2015\-2019" "IFSFFCLIRG (Man Page)" +.SH NAME +opadisablehosts + + +.PP + +\fB(Linux)\fR +Searches for a set of hosts in the fabric and disables their corresponding switch port. +.SH Syntax +opadisablehosts [-h \fIhfi\fR] [-p \fIport\fR] \fIreason\fR \fIhost ...\fR +.SH Options + +.TP 10 +--help + +Produces full help text. + +.TP 10 +-h \fIhfi\fR + +Specifies the HFI, numbered 1..n. Using 0 specifies that the -p \fIport\fR port is a system-wide port number. Default is 0. + +.TP 10 +-p \fIport\fR + +Specifies the port, numbered 1..n. Using 0 specifies the first active port. Default is 0. + +.TP 10 +\fIreason\fR + +Specifies the text describing the reason hosts are being disabled. \fIreason\fR is saved in the reason field of the output file. + +.IP +Information about the links disabled is written to a CSV file. By default, this file is named /etc/opa/disabled:hfi:port.csv where the hfi:port part of the file name is replaced by the HFI number and the port number being operated on (such as 1:1 or 2:1). This CSV file can be used as input to opaenableports. +.IP +The list is of the form: NodeGUID;PortNum;NodeType;NodeDesc;NodeGUID; PortNum;NodeType;NodeDesc;Reason For each listed link, the switch port closer to this is the one that has been disabled. +.TP 10 +\fIhost ...\fR + +Defines one or more hosts that are affected by the \fIreason\fR. + + +.SH -h and -p options permit a variety of selections: + +.TP 10 +-h 0 + +First active port in system (Default). + +.TP 10 +-h 0 -p 0 + +First active port in system. + +.TP 10 +-h \fIx\fR + +First active port on HFI \fIx\fR. + +.TP 10 +-h \fIx\fR \fI\fR-p 0 + +First active port on HFI \fIx\fR. + +.TP 10 +-h 0 -p \fIy\fR + +Port \fIy\fR within system (no matter which ports are active). + +.TP 10 +-h \fIx\fR \fI\fR-p \fIy\fR + +HFI \fIx\fR, port \fIy\fR. + +.SH Examples +opadisablehosts \[aq]bad DRAM\[aq] compute001 compute045 +.br + +opadisablehosts -h 1 -p 2 \[aq]crashed\[aq] compute001 compute045 diff --git a/IbaTools/man/opadisableports.manPage b/IbaTools/man/opadisableports.manPage new file mode 100644 index 0000000..ace2192 --- /dev/null +++ b/IbaTools/man/opadisableports.manPage @@ -0,0 +1,99 @@ +.\" .\" ********************************************************************* +.\" .\" * * +.\" .\" * Copyright 2015-2019, Intel Corporation * +.\" .\" * * +.\" .\" * All Rights Reserved. * +.\" .\" * * +.\" .\" ********************************************************************* + +.TH opadisableports 8 "Intel Corporation" "Copyright(C) 2015\-2019" "IFSFFCLIRG (Man Page)" +.SH NAME +opadisableports + + +.PP + +\fB(Linux)\fR +Accepts a CSV file listing links to disable. For each HFI-SW link, the switch side of the link is disabled. For each SW-SW link, the switch port closer to this node is disabled. This approach generally permits a future opaenableports operation to re-enable the port once the issue is corrected or ready to be retested. The list of disabled ports is tracked in /etc/opa/disabled*.csv. +.SH Syntax +opadisableports [-R] [-h \fIhfi\fR] [-p \fIport\fR] [ \fIreason\fR] < disable.csv +.SH Options + +.TP 10 +--help + +Produces full help text. + +.TP 10 +-R + +Does not attempt to get routes for computation of distance. Instead, it disables the port of the switch with the lower LID (which is often the side closest to the SM) assuming that it is closer to this node. + +.TP 10 +-h \fIhfi\fR + +Specifies the HFI, numbered 1..n. Using 0 specifies that the -p \fIport\fR port is a system-wide port number. Default is 0. + +.TP 10 +-p \fIport\fR + +Specifies the port, numbered 1..n. Using 0 specifies the first active port. Default is 0. + +.TP 10 +\fIreason\fR + +Specifies optional text describing why ports are being disabled. If used, text is saved in the reason field of the output file. + +.TP 10 +disable.csv + +Specifies the input file listing the links to disable. The list is of the form: NodeGUID;PortNum;NodeType;NodeDesc;NodeGUID;PortNum; NodeType;NodeDesc;Reason + +.IP +The \fIreason\fR field is optional. An input file such as this can be generated by using opaextractbadlinks, opaextractmissinglinks, or opaextractsellinks. +.PP +Information about the links disabled and the reason is saved (in the same format) to an output file named /etc/opa/disabled:hfi:port.csv where the hfi:port part of the file name is replaced by the HFI number and the port number being operated on (such as 1:1 or 2:1). This CSV file can be used as input to opaenableports. + +.SH -h and -p options permit a variety of selections: + +.TP 10 +-h 0 + +First active port in system (Default). + +.TP 10 +-h 0 -p 0 + +First active port in system. + +.TP 10 +-h \fIx\fR + +First active port on HFI \fIx\fR. + +.TP 10 +-h \fIx\fR \fI\fR-p 0 + +First active port on HFI \fIx\fR. + +.TP 10 +-h 0 -p \fIy\fR + +Port \fIy\fR within system (no matter which ports are active). + +.TP 10 +-h \fIx\fR \fI\fR-p \fIy\fR + +HFI \fIx\fR, port \fIy\fR. + +.SH Examples +opadisableports \[aq]bad cable\[aq] < disable.csv +.br + +opadisableports -h 1 -p 1 \[aq]dead servers\[aq] < disable.csv +.br + +opaextractsellinks -F lid:3 | opadisableports \[aq]bad server\[aq] +.br + +opaextractmissinglinks -T /etc/opa/topology.0:0.xml | opadisableports diff --git a/IbaTools/man/opadownloadall.manPage b/IbaTools/man/opadownloadall.manPage new file mode 100644 index 0000000..55047dc --- /dev/null +++ b/IbaTools/man/opadownloadall.manPage @@ -0,0 +1,125 @@ +.\" .\" ********************************************************************* +.\" .\" * * +.\" .\" * Copyright 2015-2019, Intel Corporation * +.\" .\" * * +.\" .\" * All Rights Reserved. * +.\" .\" * * +.\" .\" ********************************************************************* + +.TH opadownloadall 8 "Intel Corporation" "Copyright(C) 2015\-2019" "IFSFFCLIRG (Man Page)" +.SH NAME +opadownloadall + + +.PP + +\fB(Linux)\fR +Copies one or more files to a group of hosts from a system. Since the file contents to copy may be different for each host, a separate directory on this system is used for the source files for each host. This can also be used in conjunction with opauploadall to upload a host-specific configuration file, edit it for each host, and download the new version to all the hosts. +.PP + +.B NOTE: +The tool opadownloadall can only copy from this system to a group of hosts in the cluster. To copy files from hosts in the cluster to this host, use opauploadall. + + +.SH Syntax +opadownloadall [-rp] [-f \fIhostfile\fR] [-d \fIdownload\(uldir\fR] [-h \[aq]\fIHOSTS\fR\[aq]] +.br +[-u \fIuser\fR] +source\(ulfile ... \fIdest\(ulfile\fR +.SH Options + +.TP 10 +--help + +Produces full help text. + +.TP 10 +-r + +Performs recursive download of directories. + +.TP 10 +-p + +Performs copy in parallel on all hosts. + +.TP 10 +-f \fIhostfile\fR + +Specifies the file with hosts in cluster. Default is /etc/opa/hosts. + +.TP 10 +-d \fIdownload\(uldir\fR + +Specifies the directory to download files from. Default is downloads. If not specified, the environment variable \fBDOWNLOADS\(ulDIR\fR is used. If that is not exported, the default is used. + +.TP 10 +-h \fIHOSTS\fR + +Specifies the list of hosts to download files to. + +.TP 10 +-u \fIuser\fR + +Specifies the user to perform the copy. Default is the current user code. + +.TP 10 +.BR + +.PP + +.B NOTE: +The user@ style syntax cannot be used in the arguments to opadownloadall. + + +.TP 10 +\fIsource\(ulfile\fR + +Specifies the list of source files to copy from the system. + +.IP +The option \fIsource\(ulfile\fR is relative to \fIdownload\(uldir\fR/\fIhostname\fR. A local directory within \fIdownload\(uldir\fR/ must exist for each host being downloaded to. Each downloaded file is copied from \fIdownload\(uldir\fR/\fIhostname\fR/\fIsource\(ulfile\fR. +.TP 10 +\fIdest\(ulfile\fR + +Specifies the name of the file or directory on the destination hosts to copy to. + +.IP +If more than one source file is specified, \fIdest\(ulfile\fR is treated as a directory name. The given directory must already exist on the destination host. The copy fails for hosts where the directory does not exist. +.SH Example +opadownloadall -h \[aq]arwen elrond\[aq] irqbalance vncservers /etc +.br + +# Copies two files to 2 hosts +.br + + +.br + +opadownloadall -p irqbalance vncservers /etc +.br + +# Copies two files to all hosts +.SH Environment Variables + +.PP +The following environment variables are also used by this command: +.TP 10 +\fBHOSTS\fR + +List of hosts; used if -h option not supplied. + +.TP 10 +\fBHOSTS\(ulFILE\fR + +File containing list of hosts; used in absence of -f and -h. + +.TP 10 +\fBFF\(ulMAX\(ulPARALLEL\fR + +When the -p option is used, the maximum concurrent operations are performed. + +.TP 10 +\fBDOWNLOADS\(ulDIR\fR + +Directory to download from, used in absence of -d. diff --git a/IbaTools/man/opaenableports.manPage b/IbaTools/man/opaenableports.manPage new file mode 100644 index 0000000..7082b24 --- /dev/null +++ b/IbaTools/man/opaenableports.manPage @@ -0,0 +1,88 @@ +.\" .\" ********************************************************************* +.\" .\" * * +.\" .\" * Copyright 2015-2019, Intel Corporation * +.\" .\" * * +.\" .\" * All Rights Reserved. * +.\" .\" * * +.\" .\" ********************************************************************* + +.TH opaenableports 8 "Intel Corporation" "Copyright(C) 2015\-2019" "IFSFFCLIRG (Man Page)" +.SH NAME +opaenableports + + +.PP + +\fB(Linux)\fR +Accepts a disabled ports input file and re-enables the specified ports. The input file can be /etc/opa/disabled*.csv or a user-created subset of such a file. After enabling the port, it is removed from /etc/opa/disabled*.csv. +.SH Syntax +opaenableports [-h \fIhfi\fR] [-p \fIport\fR] < disabled.csv +.SH Options + +.TP 10 +--help + +Produces full help text. + +.TP 10 +-h \fIhfi\fR + +Specifies the HFI, numbered 1..n. Using 0 specifies that the -p \fIport\fR port is a system-wide port number. Default is 0. + +.TP 10 +-p \fIport\fR + +Specifies the port, numbered 1..n. Using 0 specifies the first active port. Default is 0. + +.TP 10 +disabled.csv + +Specifies the input file listing the ports to enable. The list is of the form: NodeGUID;PortNum;NodeType;NodeDesc;Ignored. + +.IP +An input file like this is generated in /etc/opa/disabled* by opadisableports. + +.SH -h and -p options permit a variety of selections: + +.TP 10 +-h 0 + +First active port in system (Default). + +.TP 10 +-h 0 -p 0 + +First active port in system. + +.TP 10 +-h \fIx\fR + +First active port on HFI \fIx\fR. + +.TP 10 +-h \fIx\fR \fI\fR-p 0 + +First active port on HFI \fIx\fR. + +.TP 10 +-h 0 -p \fIy\fR + +Port \fIy\fR within system (no matter which ports are active). + +.TP 10 +-h \fIx\fR \fI\fR-p \fIy\fR + +HFI \fIx\fR, port \fIy\fR. + +.SH Examples +opaenableports < disabled.csv +.br + +opaenableports < /etc/opa/disabled:1:1.csv +.br + +opaenableports -h 1 -p 1 < disabled.csv +.SH Other Information + +.PP +For messages containing skipping ports, either the device is offline or the other end of the link has been disabled and the device is no longer accessible in-band. The end of the link previously disabled by opedisableports or opadisablehosts can be found in /etc/opa/disabled:1:1.csv. diff --git a/IbaTools/man/opaesmanalysis.manPage b/IbaTools/man/opaesmanalysis.manPage new file mode 100644 index 0000000..c9df5ee --- /dev/null +++ b/IbaTools/man/opaesmanalysis.manPage @@ -0,0 +1,79 @@ +.\" .\" ********************************************************************* +.\" .\" * * +.\" .\" * Copyright 2015-2019, Intel Corporation * +.\" .\" * * +.\" .\" * All Rights Reserved. * +.\" .\" * * +.\" .\" ********************************************************************* + +.TH opaesmanalysis 8 "Intel Corporation" "Copyright(C) 2015\-2019" "IFSFFCLIRG (Man Page)" +.SH NAME +opaesmanalysis + + +.PP + +\fB(Switch)\fR +Performs analysis of the embedded Subnet Manager (SM) for configuration and health. The opaesmanalysis tool checks the opafm.xml file for the chassis. +.PP +All files generated by opaesmanalysis start with esm in the file name. +.PP +Intel recommends that you set up SSH keys for chassis (see +.br + +\fIopasetupssh\fR +). If SSH keys are not set up, all chassis must be configured with the same admin password and the password must be kept in the opafastfabric.conf configuration file. +.SH Syntax +opaesmanalysis [-b|-e] [-s] [-d \fIdir\fR] [-G \fIesmchassisfile\fR] +.br +[-E \[aq]\fIesmchassis\fR\[aq]] +.SH Options + +.TP 10 +--help + +Produces full help text. +.TP 10 +-b + +Specifies the baseline mode. Default is the compare/check mode. +.TP 10 +-e + +Evaluates health only. Default is the compare/check mode. +.TP 10 +-s + +Saves history of failures (errors/differences). +.TP 10 +-d \fIdir\fR + +Specifies the top-level directory for saving baseline and history of failed checks. Default is /var/usr/lib/opa/analysis +.TP 10 +-G \fIesmchassisfile\fR + +Specifies the file with SM chassis in the cluster. Default is /etc/opa/esm\(ulchassis +.TP 10 +-E \[aq]\fIesmchassis\fR\[aq] + +Specifies the list of SM chassis on which to execute the command. +.SH Example +opaesmanalysis +.SH Environment Variables + +.PP +The following environment variables are also used by this command: +.TP 10 +\fBESM\(ulCHASSIS\fR + +List of SM chassis, used if -G and -E options are not supplied. + +.TP 10 +\fBESM\(ulCHASSIS\(ulFILE\fR + +File containing list of SM chassis, used if -G and -E options are not supplied. + +.TP 10 +\fBFF\(ulANALYSIS\(ulDIR\fR + +Top-level directory for baselines and failed health checks. diff --git a/IbaTools/man/opaexpandfile.manPage b/IbaTools/man/opaexpandfile.manPage new file mode 100644 index 0000000..fe1bd87 --- /dev/null +++ b/IbaTools/man/opaexpandfile.manPage @@ -0,0 +1,33 @@ +.\" .\" ********************************************************************* +.\" .\" * * +.\" .\" * Copyright 2015-2019, Intel Corporation * +.\" .\" * * +.\" .\" * All Rights Reserved. * +.\" .\" * * +.\" .\" ********************************************************************* + +.TH opaexpandfile 8 "Intel Corporation" "Copyright(C) 2015\-2019" "IFSFFCLIRG (Man Page)" +.SH NAME +opaexpandfile + + +.PP + +\fB(Linux)\fR +Expands a Intel(R) Omni-Path Fabric Suite FastFabric hosts, chassis, or switches file. This tool expands and filter outs blank and commented lines. This can be useful when building other scripts that may use these files as input. +.SH Syntax +opaexpandfile \fIfile\fR +.SH Options + +.TP 10 +--help + +Produces full help text. + +.TP 10 +\fIfile\fR + +Specifies the FastFabric file to be processed. + +.SH Example +opaexpandfile allhosts diff --git a/IbaTools/man/opaextractbadlinks.manPage b/IbaTools/man/opaextractbadlinks.manPage new file mode 100644 index 0000000..6a41f23 --- /dev/null +++ b/IbaTools/man/opaextractbadlinks.manPage @@ -0,0 +1,485 @@ +.\" .\" ********************************************************************* +.\" .\" * * +.\" .\" * Copyright 2015-2019, Intel Corporation * +.\" .\" * * +.\" .\" * All Rights Reserved. * +.\" .\" * * +.\" .\" ********************************************************************* + +.TH opaextractbadlinks 8 "Intel Corporation" "Copyright(C) 2015\-2019" "IFSFFCLIRG (Man Page)" +.SH NAME +opaextractbadlinks + + +.PP +Produces a CSV file listing all or some of the links that exceed opareport -o error thresholds. opaextractbadlinks is a front end to the opareport tool. The output from this tool can be imported into a spreadsheet or parsed by other scripts. +.SH Syntax +opaextractbadlinks [opareport \fIoptions\fR] +.SH Options + +.TP 10 +--help + +Produces full help text. + +.TP 10 +opareport \fIoptions\fR + +The following options are passed to opareport. This subset is considered typical and useful for this command. By design, the tool ignores -o/--output report option. + +.RS +.TP 10 + +.sp +-h/--hfi \fIhfi\fR +Specifies the HFI, numbered 1..n. Using 0 specifies that the -p \fIport\fR port is a system-wide port number. Default is 0. + +.RE + +.RS +.TP 10 + +.sp +-p/--port \fIport\fR +Specifies the port, numbered 1..n. Using 0 specifies the first active port. Default is 0. + +.RE + +.RS +.TP 10 + +.sp +-X/--infile \fIsnapshot\(ulinput\fR +Generates a report using the data in the snapshot\(ulinput file. snapshot\(ulinput must have been generated during a previous -o \fIsnapshot\fR run. When used, the -s, -i, -C, and -a options are ignored. \[aq]-\[aq] may be used as the snapshot\(ulinput to specify stdin. + +.RE + +.RS +.TP 10 + +.sp +-T/--topology \fItopology\(ulinput\fR +Uses topology\(ulinput file to augment and verify fabric information. When used, various reports can be augmented with information not available electronically (such as cable labels). \[aq]-\[aq] may be used to specify stdin. + +.RE + +.RS +.TP 10 + +.sp +-i/--interval \fIseconds\fR +Obtains performance statistics over interval \fIseconds\fR. Clears all statistics, waits interval \fIseconds\fR, then generates report. Implies -s option. + +.RE + +.RS +.TP 10 + +.sp +-b / --begin \fIdate\(ultime\fR +Obtains past performance stats over an interval beginning at \fIdate\(ultime\fR. Implies -s option. \fIdate\(ultime\fR may be a time entered as HH:MM[:SS] or date as mm/dd/YYYY, dd.mm.YYYY, YYYY-mm-dd or date followed by time; for example, "2016-07-04 14:40". Relative times are taken as "x [second|minute|hour|day](s) ago. + +.RE + +.RS +.TP 10 + +.sp +-e / --end \fIdate\(ultime\fR +Obtains past performance stats over an interval ending at \fIdate\(ultime\fR. Implies -s option. + +.IP +\fIdate\(ultime\fR may be a time entered as HH:MM[:SS] or date as mm/dd/YYYY, dd.mm.YYYY, YYYY-mm-dd or date followed by time; for example, "2016-07-04 14:40". Relative times are taken as "x [second|minute|hour|day](s) ago. +.RE + +.RS +.TP 10 + +.sp +-C/--clear +Clears performance statistics for all ports. Only statistics with error thresholds are cleared. A clear occurs after generating the report. + +.RE + +.RS +.TP 10 + +.sp +-a/--clearall +Clears all performance statistics for all ports. + +.RE + +.RS +.TP 10 + +.sp +-M/--pmadirect +Accesses performance statistics using direct PMA. + +.RE + +.RS +.TP 10 + +.sp +-A/--allports +Gets PortInfo for down switch ports. Uses direct SMA to get this data. If used with -M, also gets PMA stats for down switch ports. + +.RE + +.RS +.TP 10 + +.sp +-c/--config \fIfile\fR +Specifies the error thresholds configuration file. Default is /etc/opa/opamon.conf file. + +.RE + +.RS +.TP 10 + +.sp +-L/--limit +Limits operation to exact specified focus with -F for port error counters check (-o \fIerrors\fR) and port counters clear (-C or -i). Normally, the neighbor of each selected port is also checked/cleared. Does not affect other reports. + +.RE + +.RS +.TP 10 + +.sp +-F/--focus \fIpoint\fR +Specifies the focus area for report. Used for all reports except route to limit scope of report. Refer to +\fIPoint Syntax\fR +for details. + +.RE + + +.SH -h and -p options permit a variety of selections: + +.TP 10 +-h 0 + +First active port in system (Default). + +.TP 10 +-h 0 -p 0 + +First active port in system. + +.TP 10 +-h \fIx\fR + +First active port on HFI \fIx\fR. + +.TP 10 +-h \fIx\fR \fI\fR-p 0 + +First active port on HFI \fIx\fR. + +.TP 10 +-h 0 -p \fIy\fR + +Port \fIy\fR within system (no matter which ports are active). + +.TP 10 +-h \fIx\fR \fI\fR-p \fIy\fR + +HFI \fIx\fR, port \fIy\fR. + + +.SH Point Syntax + +.TP 10 +gid:\fIvalue\fR + +\fIvalue\fR is numeric port GID of form: subnet:guid. + +.TP 10 +lid:\fIvalue\fR + +\fIvalue\fR is numeric LID. + +.TP 10 +lid:value:node + +\fIvalue\fR is numeric LID, selects entire node with given LID. + +.TP 10 +lid:\fIvalue\fR:port:\fIvalue2\fR + +\fIvalue\fR is numeric LID of node, \fIvalue2\fR is port number. + +.TP 10 +portguid:\fIvalue\fR + +\fIvalue\fR is numeric port GUID. + +.TP 10 +nodeguid:\fIvalue\fR + +\fIvalue\fR is numeric node GUID. + +.TP 10 +nodeguid:\fIvalue1\fR:port:\fIvalue2\fR + +\fIvalue1\fR is numeric node GUID, \fIvalue2\fR is port number. + +.TP 10 +iocguid:\fIvalue\fR + +\fIvalue\fR is numeric IOC GUID. + +.TP 10 +iocguid:\fIvalue1\fR:port:\fIvalue2\fR + +\fIvalue1\fR is numeric IOC GUID, \fIvalue2\fR is port number. + +.TP 10 +systemguid:\fIvalue\fR + +\fIvalue\fR is numeric system image GUID. + +.TP 10 +systemguid:\fIvalue1\fR:port:\fIvalue2\fR + +\fIvalue1\fR is the numeric system image GUID, \fIvalue2\fR is port number. + +.TP 10 +ioc:\fIvalue\fR + +\fIvalue\fR is IOC Profile ID String (IOC Name). + +.TP 10 +ioc:\fIvalue1\fR:port:\fIvalue2\fR + +\fIvalue1\fR is IOC Profile ID String (IOC Name), \fIvalue2\fR is port number. + +.TP 10 +iocpat:\fIvalue\fR + +\fIvalue\fR is glob pattern for IOC Profile ID String (IOC Name). + +.TP 10 +iocpat:\fIvalue1\fR:port:\fIvalue2\fR + +\fIvalue1\fR is glob pattern for IOC Profile ID String (IOC Name), \fIvalue2\fR is port number. + +.TP 10 +ioctype:\fIvalue\fR + +\fIvalue\fR is IOC type (SRP or OTHER). + +.TP 10 +ioctype:\fIvalue1\fR:port:\fIvalue2\fR + +\fIvalue1\fR is IOC type (SRP or OTHER); \fIvalue2\fR is port number. + +.TP 10 +node:\fIvalue\fR + +\fIvalue\fR is node description (node name). + +.TP 10 +node:\fIvalue1\fR:port:\fIvalue2\fR + +\fIvalue1\fR is node description (node name), \fIvalue2\fR is port number. + +.TP 10 +nodepat:\fIvalue\fR + +\fIvalue\fR is glob pattern for node description (node name). + +.TP 10 +nodepat:\fIvalue1\fR:port:\fIvalue2\fR + +\fIvalue1\fR is the glob pattern for the node description (node name), \fIvalue2\fR is port number. + +.TP 10 +nodedetpat:\fIvalue\fR + +\fIvalue\fR is glob pattern for node details. + +.TP 10 +nodedetpat:\fIvalue1\fR:port:\fIvalue2\fR + +\fIvalue1\fR is the glob pattern for the node details, \fIvalue2\fR is port number. + +.TP 10 +nodetype:\fIvalue\fR + +\fIvalue\fR is node type (SW or FI). + +.TP 10 +nodetype:\fIvalue1\fR:port:\fIvalue2\fR + +\fIvalue1\fR is node type (SW or FI), \fIvalue2\fR is port number. + +.TP 10 +rate:\fIvalue\fR + +\fIvalue\fR is string for rate (25g, 50g, 75g, 100g), omits switch mgmt port 0. + +.TP 10 +portstate:\fIvalue\fR + +\fIvalue\fR is a string for state (down, init, armed, active, notactive, initarmed). + +.TP 10 +portphysstate:\fIvalue\fR + +\fIvalue\fR is a string for PHYs state (polling, disabled, training, linkup, recovery, offline, test) + +.TP 10 +mtucap:\fIvalue\fR + +\fIvalue\fR is MTU size (2048, 4096, 8192, 10240), omits switch mgmt port 0. + +.TP 10 +labelpat:\fIvalue\fR + +\fIvalue\fR is glob pattern for cable label. + +.TP 10 +lengthpat:\fIvalue\fR + +\fIvalue\fR is glob pattern for cable length. + +.TP 10 +cabledetpat:\fIvalue\fR + +\fIvalue\fR is glob pattern for cable details. + +.TP 10 +cabinflenpat:\fIvalue\fR + +\fIvalue\fR is glob pattern for cable info length. + +.TP 10 +cabinfvendnamepat:\fIvalue\fR + +\fIvalue\fR is glob pattern for cable info vendor name. + +.TP 10 +cabinfvendpnpat:\fIvalue\fR + +\fIvalue\fR is glob pattern for cable info vendor part number. + +.TP 10 +cabinfvendrevpat:\fIvalue\fR + +\fIvalue\fR is glob pattern for cable info vendor revision. + +.TP 10 +cabinfvendsnpat:\fIvalue\fR + +\fIvalue\fR is glob pattern for cable info vendor serial number. + +.TP 10 +cabinftype:\fIvalue\fR + +\fIvalue\fR is either optical, passive\(ulcopper, active\(ulcopper, or unknown. + +.TP 10 +linkdetpat:\fIvalue\fR + +\fIvalue\fR is glob pattern for link details. + +.TP 10 +portdetpat:\fIvalue\fR + +\fIvalue\fR is glob pattern for port details. + +.TP 10 +sm + +Specifies the master subnet manager (SM). + +.TP 10 +smdetpat:\fIvalue\fR + +\fIvalue\fR is glob pattern for SM details. + +.TP 10 +route:\fIpoint1\fR:\fIpoint2\fR + +Specifies all ports along the routes between the two given points. + +.TP 10 +led:\fIvalue\fR + +\fIvalue\fR is either on or off for LED port beacon. + +.TP 10 +linkqual:\fIvalue\fR + +Specifies the ports with a link quality equal to \fIvalue\fR. + +.TP 10 +linkqualLE:\fIvalue\fR + +Specifies the ports with a link quality less than or equal to \fIvalue\fR. + +.TP 10 +linkqualGE:\fIvalue\fR + +Specifies the ports with a link quality greater than or equal to \fIvalue\fR. + +.TP 10 +nodepatfile:\fIFILENAME\fR + +Specifies the name of file with the list of nodepats or node descriptions. + +.TP 10 +nodepairpatfile:\fIFILENAME\fR + +Specifies the name of file with the list of node pairs, separated by a colon. + +.TP 10 +ldr + +Specifies the ports with a non-zero link down reason or neighbor link down reason. + +.TP 10 +ldr:\fIvalue\fR + +Specifies the ports with a link down reason or neighbor link down reason equal to \fIvalue\fR. + +.SH Examples +# List all the bad links in the fabric: +.br + +opaextractbadlinks +.br + + +.br + +# List all the bad links to a switch named "coresw1": +.br + +opaextractbadlinks -F "node:coresw1" +.br + + +.br + +# List all the bad links to end-nodes: +.br + +opaextractbadlinks -F "nodetype:FI" +.br + + +.br + +# List all the bad links on the 2nd HFI\[aq]s fabric of a multi-plane fabric: +.br + +opaextractbadlinks -h 2 +.br + +.br diff --git a/IbaTools/man/opaextracterror.manPage b/IbaTools/man/opaextracterror.manPage new file mode 100644 index 0000000..f5fb8c4 --- /dev/null +++ b/IbaTools/man/opaextracterror.manPage @@ -0,0 +1,464 @@ +.\" .\" ********************************************************************* +.\" .\" * * +.\" .\" * Copyright 2015-2019, Intel Corporation * +.\" .\" * * +.\" .\" * All Rights Reserved. * +.\" .\" * * +.\" .\" ********************************************************************* + +.TH opaextracterror 8 "Intel Corporation" "Copyright(C) 2015\-2019" "IFSFFCLIRG (Man Page)" +.SH NAME +opaextracterror + + +.PP +Produces a CSV file listing all or some of the errors in the current fabric. opaextracterror is a front end to the opareport tool. The output from this tool can be imported into a spreadsheet or parsed by other scripts. +.SH Syntax +opaextracterror [opareport \fIoptions\fR] +.SH Options + +.TP 10 +--help + +Produces full help text. + +.TP 10 +opareport \fIoptions\fR + +The following options are passed to opareport. This subset is considered typical and useful for this command. By design, the tool ignores -o/--output report option. + +.RS +.TP 10 + +.sp +-h/--hfi \fIhfi\fR +Specifies the HFI, numbered 1..n. Using 0 specifies that the -p \fIport\fR port is a system-wide port number. Default is 0. + +.RE + +.RS +.TP 10 + +.sp +-p/--port \fIport\fR +Specifies the port, numbered 1..n. Using 0 specifies the first active port. Default is 0. + +.RE + +.RS +.TP 10 + +.sp +-X/--infile \fIsnapshot\(ulinput\fR +Generates a report using the data in the snapshot\(ulinput file. snapshot\(ulinput must have been generated during a previous -o \fIsnapshot\fR run. When used, the -s, -i, -C, and -a options are ignored. \[aq]-\[aq] may be used as the snapshot\(ulinput to specify stdin. + +.RE + +.RS +.TP 10 + +.sp +-T/--topology \fItopology\(ulinput\fR +Uses topology\(ulinput file to augment and verify fabric information. When used, various reports can be augmented with information not available electronically (such as cable labels). \[aq]-\[aq] may be used to specify stdin. + +.RE + +.RS +.TP 10 + +.sp +-i/--interval \fIseconds\fR +Obtains performance statistics over interval \fIseconds\fR. Clears all statistics, waits interval \fIseconds\fR, then generates report. Implies -s option. + +.RE + +.RS +.TP 10 + +.sp +-b / --begin \fIdate\(ultime\fR +Obtains past performance stats over an interval beginning at \fIdate\(ultime\fR. Implies -s option. \fIdate\(ultime\fR may be a time entered as HH:MM[:SS] or date as mm/dd/YYYY, dd.mm.YYYY, YYYY-mm-dd or date followed by time; for example, "2016-07-04 14:40". Relative times are taken as "x [second|minute|hour|day](s) ago. + +.RE + +.RS +.TP 10 + +.sp +-e / --end \fIdate\(ultime\fR +Obtains past performance stats over an interval ending at \fIdate\(ultime\fR. Implies -s option. + +.IP +\fIdate\(ultime\fR may be a time entered as HH:MM[:SS] or date as mm/dd/YYYY, dd.mm.YYYY, YYYY-mm-dd or date followed by time; for example, "2016-07-04 14:40". Relative times are taken as "x [second|minute|hour|day](s) ago. +.RE + +.RS +.TP 10 + +.sp +-C/--clear +Clears performance statistics for all ports. Only statistics with error thresholds are cleared. A clear occurs after generating the report. + +.RE + +.RS +.TP 10 + +.sp +-a/--clearall +Clears all performance statistics for all ports. + +.RE + +.RS +.TP 10 + +.sp +-M/--pmadirect +Accesses performance statistics using direct PMA. + +.RE + +.RS +.TP 10 + +.sp +-A/--allports +Gets PortInfo for down switch ports. Uses direct SMA to get this data. If used with -M, also gets PMA stats for down switch ports. + +.RE + +.RS +.TP 10 + +.sp +-F/--focus \fIpoint\fR +Specifies the focus area for report. Used for all reports except route to limit scope of report. Refer to +\fIPoint Syntax\fR +for details. + +.RE + + +.SH -h and -p options permit a variety of selections: + +.TP 10 +-h 0 + +First active port in system (Default). + +.TP 10 +-h 0 -p 0 + +First active port in system. + +.TP 10 +-h \fIx\fR + +First active port on HFI \fIx\fR. + +.TP 10 +-h \fIx\fR \fI\fR-p 0 + +First active port on HFI \fIx\fR. + +.TP 10 +-h 0 -p \fIy\fR + +Port \fIy\fR within system (no matter which ports are active). + +.TP 10 +-h \fIx\fR \fI\fR-p \fIy\fR + +HFI \fIx\fR, port \fIy\fR. + + +.SH Point Syntax + +.TP 10 +gid:\fIvalue\fR + +\fIvalue\fR is numeric port GID of form: subnet:guid. + +.TP 10 +lid:\fIvalue\fR + +\fIvalue\fR is numeric LID. + +.TP 10 +lid:value:node + +\fIvalue\fR is numeric LID, selects entire node with given LID. + +.TP 10 +lid:\fIvalue\fR:port:\fIvalue2\fR + +\fIvalue\fR is numeric LID of node, \fIvalue2\fR is port number. + +.TP 10 +portguid:\fIvalue\fR + +\fIvalue\fR is numeric port GUID. + +.TP 10 +nodeguid:\fIvalue\fR + +\fIvalue\fR is numeric node GUID. + +.TP 10 +nodeguid:\fIvalue1\fR:port:\fIvalue2\fR + +\fIvalue1\fR is numeric node GUID, \fIvalue2\fR is port number. + +.TP 10 +iocguid:\fIvalue\fR + +\fIvalue\fR is numeric IOC GUID. + +.TP 10 +iocguid:\fIvalue1\fR:port:\fIvalue2\fR + +\fIvalue1\fR is numeric IOC GUID, \fIvalue2\fR is port number. + +.TP 10 +systemguid:\fIvalue\fR + +\fIvalue\fR is numeric system image GUID. + +.TP 10 +systemguid:\fIvalue1\fR:port:\fIvalue2\fR + +\fIvalue1\fR is the numeric system image GUID, \fIvalue2\fR is port number. + +.TP 10 +ioc:\fIvalue\fR + +\fIvalue\fR is IOC Profile ID String (IOC Name). + +.TP 10 +ioc:\fIvalue1\fR:port:\fIvalue2\fR + +\fIvalue1\fR is IOC Profile ID String (IOC Name), \fIvalue2\fR is port number. + +.TP 10 +iocpat:\fIvalue\fR + +\fIvalue\fR is glob pattern for IOC Profile ID String (IOC Name). + +.TP 10 +iocpat:\fIvalue1\fR:port:\fIvalue2\fR + +\fIvalue1\fR is glob pattern for IOC Profile ID String (IOC Name), \fIvalue2\fR is port number. + +.TP 10 +ioctype:\fIvalue\fR + +\fIvalue\fR is IOC type (SRP or OTHER). + +.TP 10 +ioctype:\fIvalue1\fR:port:\fIvalue2\fR + +\fIvalue1\fR is IOC type (SRP or OTHER); \fIvalue2\fR is port number. + +.TP 10 +node:\fIvalue\fR + +\fIvalue\fR is node description (node name). + +.TP 10 +node:\fIvalue1\fR:port:\fIvalue2\fR + +\fIvalue1\fR is node description (node name), \fIvalue2\fR is port number. + +.TP 10 +nodepat:\fIvalue\fR + +\fIvalue\fR is glob pattern for node description (node name). + +.TP 10 +nodepat:\fIvalue1\fR:port:\fIvalue2\fR + +\fIvalue1\fR is the glob pattern for the node description (node name), \fIvalue2\fR is port number. + +.TP 10 +nodedetpat:\fIvalue\fR + +\fIvalue\fR is glob pattern for node details. + +.TP 10 +nodedetpat:\fIvalue1\fR:port:\fIvalue2\fR + +\fIvalue1\fR is the glob pattern for the node details, \fIvalue2\fR is port number. + +.TP 10 +nodetype:\fIvalue\fR + +\fIvalue\fR is node type (SW or FI). + +.TP 10 +nodetype:\fIvalue1\fR:port:\fIvalue2\fR + +\fIvalue1\fR is node type (SW or FI), \fIvalue2\fR is port number. + +.TP 10 +rate:\fIvalue\fR + +\fIvalue\fR is string for rate (25g, 50g, 75g, 100g), omits switch mgmt port 0. + +.TP 10 +portstate:\fIvalue\fR + +\fIvalue\fR is a string for state (down, init, armed, active, notactive, initarmed). + +.TP 10 +portphysstate:\fIvalue\fR + +\fIvalue\fR is a string for PHYs state (polling, disabled, training, linkup, recovery, offline, test) + +.TP 10 +mtucap:\fIvalue\fR + +\fIvalue\fR is MTU size (2048, 4096, 8192, 10240), omits switch mgmt port 0. + +.TP 10 +labelpat:\fIvalue\fR + +\fIvalue\fR is glob pattern for cable label. + +.TP 10 +lengthpat:\fIvalue\fR + +\fIvalue\fR is glob pattern for cable length. + +.TP 10 +cabledetpat:\fIvalue\fR + +\fIvalue\fR is glob pattern for cable details. + +.TP 10 +cabinflenpat:\fIvalue\fR + +\fIvalue\fR is glob pattern for cable info length. + +.TP 10 +cabinfvendnamepat:\fIvalue\fR + +\fIvalue\fR is glob pattern for cable info vendor name. + +.TP 10 +cabinfvendpnpat:\fIvalue\fR + +\fIvalue\fR is glob pattern for cable info vendor part number. + +.TP 10 +cabinfvendrevpat:\fIvalue\fR + +\fIvalue\fR is glob pattern for cable info vendor revision. + +.TP 10 +cabinfvendsnpat:\fIvalue\fR + +\fIvalue\fR is glob pattern for cable info vendor serial number. + +.TP 10 +cabinftype:\fIvalue\fR + +\fIvalue\fR is either optical, passive\(ulcopper, active\(ulcopper, or unknown. + +.TP 10 +linkdetpat:\fIvalue\fR + +\fIvalue\fR is glob pattern for link details. + +.TP 10 +portdetpat:\fIvalue\fR + +\fIvalue\fR is glob pattern for port details. + +.TP 10 +sm + +Specifies the master subnet manager (SM). + +.TP 10 +smdetpat:\fIvalue\fR + +\fIvalue\fR is glob pattern for SM details. + +.TP 10 +route:\fIpoint1\fR:\fIpoint2\fR + +Specifies all ports along the routes between the two given points. + +.TP 10 +led:\fIvalue\fR + +\fIvalue\fR is either on or off for LED port beacon. + +.TP 10 +linkqual:\fIvalue\fR + +Specifies the ports with a link quality equal to \fIvalue\fR. + +.TP 10 +linkqualLE:\fIvalue\fR + +Specifies the ports with a link quality less than or equal to \fIvalue\fR. + +.TP 10 +linkqualGE:\fIvalue\fR + +Specifies the ports with a link quality greater than or equal to \fIvalue\fR. + +.TP 10 +nodepatfile:\fIFILENAME\fR + +Specifies the name of file with the list of nodepats or node descriptions. + +.TP 10 +nodepairpatfile:\fIFILENAME\fR + +Specifies the name of file with the list of node pairs, separated by a colon. + +.TP 10 +ldr + +Specifies the ports with a non-zero link down reason or neighbor link down reason. + +.TP 10 +ldr:\fIvalue\fR + +Specifies the ports with a link down reason or neighbor link down reason equal to \fIvalue\fR. + +.SH Examples +# List all the link errors in the fabric: +.br + +opaextracterror +.br + + +.br + +# List all the link errors related to a switch named "coresw1": +.br + +opaextracterror -F "node:coresw1" +.br + + +.br + +# List all the link errors for end-nodes: +.br + +opaextracterror -F "nodetype:FI" +.br + + +.br + +# List all the link errors on the 2nd HFI\[aq]s fabric of a multi-plane fabric: +.br + +opaextracterror -h 2 diff --git a/IbaTools/man/opaextractlids.manPage b/IbaTools/man/opaextractlids.manPage new file mode 100644 index 0000000..96d6a62 --- /dev/null +++ b/IbaTools/man/opaextractlids.manPage @@ -0,0 +1,381 @@ +.\" .\" ********************************************************************* +.\" .\" * * +.\" .\" * Copyright 2015-2019, Intel Corporation * +.\" .\" * * +.\" .\" * All Rights Reserved. * +.\" .\" * * +.\" .\" ********************************************************************* + +.TH opaextractlids 8 "Intel Corporation" "Copyright(C) 2015\-2019" "IFSFFCLIRG (Man Page)" +.SH NAME +opaextractlids + + +.PP +Produces a CSV file listing all or some of the LIDs in the fabric. opaextractlids is a front end to the opareport tool. The output from this tool can be imported into a spreadsheet or parsed by other scripts. +.SH Syntax +opaextractlids [opareport \fIoptions\fR] +.SH Options + +.TP 10 +--help + +Produces full help text. + +.TP 10 +opareport \fIoptions\fR + +The following options are passed to opareport. This subset is considered typical and useful for this command. By design, the tool ignores -o/--output report option. + +.RS +.TP 10 + +.sp +-h/--hfi \fIhfi\fR +Specifies the HFI, numbered 1..n. Using 0 specifies that the -p \fIport\fR port is a system-wide port number. Default is 0. + +.RE + +.RS +.TP 10 + +.sp +-p/--port \fIport\fR +Specifies the port, numbered 1..n. Using 0 specifies the first active port. Default is 0. + +.RE + +.RS +.TP 10 + +.sp +-X/--infile \fIsnapshot\(ulinput\fR +Generates a report using the data in the snapshot\(ulinput file. snapshot\(ulinput must have been generated during a previous -o \fIsnapshot\fR run. When used, the -s, -i, -C, and -a options are ignored. \[aq]-\[aq] may be used as the snapshot\(ulinput to specify stdin. + +.RE + +.RS +.TP 10 + +.sp +-F/--focus \fIpoint\fR +Specifies the focus area for report. Used for all reports except route to limit scope of report. Refer to +\fIPoint Syntax\fR +for details. + +.RE + + +.SH -h and -p options permit a variety of selections: + +.TP 10 +-h 0 + +First active port in system (Default). + +.TP 10 +-h 0 -p 0 + +First active port in system. + +.TP 10 +-h \fIx\fR + +First active port on HFI \fIx\fR. + +.TP 10 +-h \fIx\fR \fI\fR-p 0 + +First active port on HFI \fIx\fR. + +.TP 10 +-h 0 -p \fIy\fR + +Port \fIy\fR within system (no matter which ports are active). + +.TP 10 +-h \fIx\fR \fI\fR-p \fIy\fR + +HFI \fIx\fR, port \fIy\fR. + + +.SH Point Syntax + +.TP 10 +gid:\fIvalue\fR + +\fIvalue\fR is numeric port GID of form: subnet:guid. + +.TP 10 +lid:\fIvalue\fR + +\fIvalue\fR is numeric LID. + +.TP 10 +lid:value:node + +\fIvalue\fR is numeric LID, selects entire node with given LID. + +.TP 10 +lid:\fIvalue\fR:port:\fIvalue2\fR + +\fIvalue\fR is numeric LID of node, \fIvalue2\fR is port number. + +.TP 10 +portguid:\fIvalue\fR + +\fIvalue\fR is numeric port GUID. + +.TP 10 +nodeguid:\fIvalue\fR + +\fIvalue\fR is numeric node GUID. + +.TP 10 +nodeguid:\fIvalue1\fR:port:\fIvalue2\fR + +\fIvalue1\fR is numeric node GUID, \fIvalue2\fR is port number. + +.TP 10 +iocguid:\fIvalue\fR + +\fIvalue\fR is numeric IOC GUID. + +.TP 10 +iocguid:\fIvalue1\fR:port:\fIvalue2\fR + +\fIvalue1\fR is numeric IOC GUID, \fIvalue2\fR is port number. + +.TP 10 +systemguid:\fIvalue\fR + +\fIvalue\fR is numeric system image GUID. + +.TP 10 +systemguid:\fIvalue1\fR:port:\fIvalue2\fR + +\fIvalue1\fR is the numeric system image GUID, \fIvalue2\fR is port number. + +.TP 10 +ioc:\fIvalue\fR + +\fIvalue\fR is IOC Profile ID String (IOC Name). + +.TP 10 +ioc:\fIvalue1\fR:port:\fIvalue2\fR + +\fIvalue1\fR is IOC Profile ID String (IOC Name), \fIvalue2\fR is port number. + +.TP 10 +iocpat:\fIvalue\fR + +\fIvalue\fR is glob pattern for IOC Profile ID String (IOC Name). + +.TP 10 +iocpat:\fIvalue1\fR:port:\fIvalue2\fR + +\fIvalue1\fR is glob pattern for IOC Profile ID String (IOC Name), \fIvalue2\fR is port number. + +.TP 10 +ioctype:\fIvalue\fR + +\fIvalue\fR is IOC type (SRP or OTHER). + +.TP 10 +ioctype:\fIvalue1\fR:port:\fIvalue2\fR + +\fIvalue1\fR is IOC type (SRP or OTHER); \fIvalue2\fR is port number. + +.TP 10 +node:\fIvalue\fR + +\fIvalue\fR is node description (node name). + +.TP 10 +node:\fIvalue1\fR:port:\fIvalue2\fR + +\fIvalue1\fR is node description (node name), \fIvalue2\fR is port number. + +.TP 10 +nodepat:\fIvalue\fR + +\fIvalue\fR is glob pattern for node description (node name). + +.TP 10 +nodepat:\fIvalue1\fR:port:\fIvalue2\fR + +\fIvalue1\fR is the glob pattern for the node description (node name), \fIvalue2\fR is port number. + +.TP 10 +nodedetpat:\fIvalue\fR + +\fIvalue\fR is glob pattern for node details. + +.TP 10 +nodedetpat:\fIvalue1\fR:port:\fIvalue2\fR + +\fIvalue1\fR is the glob pattern for the node details, \fIvalue2\fR is port number. + +.TP 10 +nodetype:\fIvalue\fR + +\fIvalue\fR is node type (SW or FI). + +.TP 10 +nodetype:\fIvalue1\fR:port:\fIvalue2\fR + +\fIvalue1\fR is node type (SW or FI), \fIvalue2\fR is port number. + +.TP 10 +rate:\fIvalue\fR + +\fIvalue\fR is string for rate (25g, 50g, 75g, 100g), omits switch mgmt port 0. + +.TP 10 +portstate:\fIvalue\fR + +\fIvalue\fR is a string for state (down, init, armed, active, notactive, initarmed). + +.TP 10 +portphysstate:\fIvalue\fR + +\fIvalue\fR is a string for PHYs state (polling, disabled, training, linkup, recovery, offline, test) + +.TP 10 +mtucap:\fIvalue\fR + +\fIvalue\fR is MTU size (2048, 4096, 8192, 10240), omits switch mgmt port 0. + +.TP 10 +labelpat:\fIvalue\fR + +\fIvalue\fR is glob pattern for cable label. + +.TP 10 +lengthpat:\fIvalue\fR + +\fIvalue\fR is glob pattern for cable length. + +.TP 10 +cabledetpat:\fIvalue\fR + +\fIvalue\fR is glob pattern for cable details. + +.TP 10 +cabinflenpat:\fIvalue\fR + +\fIvalue\fR is glob pattern for cable info length. + +.TP 10 +cabinfvendnamepat:\fIvalue\fR + +\fIvalue\fR is glob pattern for cable info vendor name. + +.TP 10 +cabinfvendpnpat:\fIvalue\fR + +\fIvalue\fR is glob pattern for cable info vendor part number. + +.TP 10 +cabinfvendrevpat:\fIvalue\fR + +\fIvalue\fR is glob pattern for cable info vendor revision. + +.TP 10 +cabinfvendsnpat:\fIvalue\fR + +\fIvalue\fR is glob pattern for cable info vendor serial number. + +.TP 10 +cabinftype:\fIvalue\fR + +\fIvalue\fR is either optical, passive\(ulcopper, active\(ulcopper, or unknown. + +.TP 10 +linkdetpat:\fIvalue\fR + +\fIvalue\fR is glob pattern for link details. + +.TP 10 +portdetpat:\fIvalue\fR + +\fIvalue\fR is glob pattern for port details. + +.TP 10 +sm + +Specifies the master subnet manager (SM). + +.TP 10 +smdetpat:\fIvalue\fR + +\fIvalue\fR is glob pattern for SM details. + +.TP 10 +route:\fIpoint1\fR:\fIpoint2\fR + +Specifies all ports along the routes between the two given points. + +.TP 10 +led:\fIvalue\fR + +\fIvalue\fR is either on or off for LED port beacon. + +.TP 10 +linkqual:\fIvalue\fR + +Specifies the ports with a link quality equal to \fIvalue\fR. + +.TP 10 +linkqualLE:\fIvalue\fR + +Specifies the ports with a link quality less than or equal to \fIvalue\fR. + +.TP 10 +linkqualGE:\fIvalue\fR + +Specifies the ports with a link quality greater than or equal to \fIvalue\fR. + +.TP 10 +nodepatfile:\fIFILENAME\fR + +Specifies the name of file with the list of nodepats or node descriptions. + +.TP 10 +nodepairpatfile:\fIFILENAME\fR + +Specifies the name of file with the list of node pairs, separated by a colon. + +.TP 10 +ldr + +Specifies the ports with a non-zero link down reason or neighbor link down reason. + +.TP 10 +ldr:\fIvalue\fR + +Specifies the ports with a link down reason or neighbor link down reason equal to \fIvalue\fR. + +.SH Examples +# List all the lids in the fabric: +.br + +opaextractlids +.br + + +.br + +# List all the lids of end-nodes: +.br + +opaextractlids -F "nodetype:FI" +.br + + +.br + +# List all the lids on the 2nd HFI\[aq]s fabric of a multi-plane fabric: +.br + +opaextractlids -h 2 diff --git a/IbaTools/man/opaextractlink.manPage b/IbaTools/man/opaextractlink.manPage new file mode 100644 index 0000000..c68b4e8 --- /dev/null +++ b/IbaTools/man/opaextractlink.manPage @@ -0,0 +1,130 @@ +.\" .\" ********************************************************************* +.\" .\" * * +.\" .\" * Copyright 2015-2019, Intel Corporation * +.\" .\" * * +.\" .\" * All Rights Reserved. * +.\" .\" * * +.\" .\" ********************************************************************* + +.TH opaextractlink 8 "Intel Corporation" "Copyright(C) 2015\-2019" "IFSFFCLIRG (Man Page)" +.SH NAME +opaextractlink + + +.PP +Produces a CSV file listing all or some of the links in the fabric. opaextractlink is a front end to the opareport tool. The output from this tool can be imported into a spreadsheet or parsed by other scripts. +.SH Syntax +opaextractlink [opareport \fIoptions\fR] +.SH Options + +.TP 10 +--help + +Produces full help text. + +.TP 10 +opareport \fIoptions\fR + +The following options are passed to opareport. This subset is considered typical and useful for this command. By design, the tool ignores -o/--output report option. + +.RS +.TP 10 + +.sp +-h/--hfi \fIhfi\fR +Specifies the HFI, numbered 1..n. Using 0 specifies that the -p \fIport\fR port is a system-wide port number. Default is 0. + +.RE + +.RS +.TP 10 + +.sp +-p/--port \fIport\fR +Specifies the port, numbered 1..n. Using 0 specifies the first active port. Default is 0. + +.RE + +.RS +.TP 10 + +.sp +-X/--infile \fIsnapshot\(ulinput\fR +Generates a report using the data in the snapshot\(ulinput file. snapshot\(ulinput must have been generated during a previous -o \fIsnapshot\fR run. When used, the -s, -i, -C, and -a options are ignored. \[aq]-\[aq] may be used as the snapshot\(ulinput to specify stdin. + +.RE + +.RS +.TP 10 + +.sp +-T/--topology \fItopology\(ulinput\fR +Uses topology\(ulinput file to augment and verify fabric information. When used, various reports can be augmented with information not available electronically (such as cable labels). \[aq]-\[aq] may be used to specify stdin. + +.RE + + +.SH -h and -p options permit a variety of selections: + +.TP 10 +-h 0 + +First active port in system (Default). + +.TP 10 +-h 0 -p 0 + +First active port in system. + +.TP 10 +-h \fIx\fR + +First active port on HFI \fIx\fR. + +.TP 10 +-h \fIx\fR \fI\fR-p 0 + +First active port on HFI \fIx\fR. + +.TP 10 +-h 0 -p \fIy\fR + +Port \fIy\fR within system (no matter which ports are active). + +.TP 10 +-h \fIx\fR \fI\fR-p \fIy\fR + +HFI \fIx\fR, port \fIy\fR. + +.SH Examples +# List all the links in the fabric: +.br + +opaextractlink +.br + + +.br + +# List all the links to a switch named "coresw1": +.br + +opaextractlink -F "node:coresw1" +.br + + +.br + +# List all the links to end-nodes: +.br + +opaextractlink -F "nodetype:FI" +.br + + +.br + +# List all the links on the 2nd HFI\[aq]s fabric of a multi-plane fabric: +.br + +opaextractlink -h 2 diff --git a/IbaTools/man/opaextractmissinglinks.manPage b/IbaTools/man/opaextractmissinglinks.manPage new file mode 100644 index 0000000..be4e848 --- /dev/null +++ b/IbaTools/man/opaextractmissinglinks.manPage @@ -0,0 +1,446 @@ +.\" .\" ********************************************************************* +.\" .\" * * +.\" .\" * Copyright 2015-2019, Intel Corporation * +.\" .\" * * +.\" .\" * All Rights Reserved. * +.\" .\" * * +.\" .\" ********************************************************************* + +.TH opaextractmissinglinks 8 "Intel Corporation" "Copyright(C) 2015\-2019" "IFSFFCLIRG (Man Page)" +.SH NAME +opaextractmissinglinks + + +.PP +Produces a CSV file listing all or some of the links in the fabric. opaextractmissinglinks is a front end to the opareport tool that generates a report listing all or some of the links that are present in the supplied topology file, but are missing in the fabric. The output from this tool can be imported into a spreadsheet or parsed by other scripts. +.SH Syntax +opaextractmissinglinks [-T topology\(ulinput] [-o report] +.br +[opareport \fIoptions\fR] +.SH Options + +.TP 10 +--help + +Produces full help text. + +.TP 10 +-T/--topology \fItopology\(ulinput\fR + +Specifies the topology file to verify against. Default is /etc/opa/topology.0:0.xml + +.TP 10 +-o/--output \fIreport\fR + +Specifies the report type for output. Refer to +\fIReport Types\fR +for details. + +.TP 10 +opareport \fIoptions\fR + +The following options are passed to opareport. This subset is considered typical and useful for this command. + +.RS +.TP 10 + +.sp +-h/--hfi \fIhfi\fR +Specifies the HFI, numbered 1..n. Using 0 specifies that the -p \fIport\fR port is a system-wide port number. Default is 0. + +.RE + +.RS +.TP 10 + +.sp +-p/--port \fIport\fR +Specifies the port, numbered 1..n. Using 0 specifies the first active port. Default is 0. + +.RE + +.RS +.TP 10 + +.sp +-X/--infile \fIsnapshot\(ulinput\fR +Generates a report using the data in the snapshot\(ulinput file. snapshot\(ulinput must have been generated during a previous -o \fIsnapshot\fR run. When used, the -s, -i, -C, and -a options are ignored. \[aq]-\[aq] may be used as the snapshot\(ulinput to specify stdin. + +.RE + +.RS +.TP 10 + +.sp +-F/--focus \fIpoint\fR +Specifies the focus area for report. Used for all reports except route to limit scope of report. Refer to +\fIPoint Syntax\fR +for details. + +.RE + + +.SH -h and -p options permit a variety of selections: + +.TP 10 +-h 0 + +First active port in system (Default). + +.TP 10 +-h 0 -p 0 + +First active port in system. + +.TP 10 +-h \fIx\fR + +First active port on HFI \fIx\fR. + +.TP 10 +-h \fIx\fR \fI\fR-p 0 + +First active port on HFI \fIx\fR. + +.TP 10 +-h 0 -p \fIy\fR + +Port \fIy\fR within system (no matter which ports are active). + +.TP 10 +-h \fIx\fR \fI\fR-p \fIy\fR + +HFI \fIx\fR, port \fIy\fR. + + +.SH Report Types + +.TP 10 +verifylinks + +Compares fabric (or snapshot) links to supplied topology and identifies differences and omissions. + +.TP 10 +verifyextlinks + +Compares fabric (or snapshot) links to supplied topology and identifies differences and omissions. Limits analysis to links external to systems. + +.TP 10 +verifyfilinks + +Compares fabric (or snapshot) links to supplied topology and identify differences and omissions. Limits analysis to links to FIs. + +.TP 10 +verifyislinks + +Compares fabric (or snapshot) links to supplied topology and identify differences and omissions. Limits analysis to inter-switch links. + +.TP 10 +verifyextislinks + +Compares fabric (or snapshot) links to supplied topology and identify differences and omissions. Limits analysis to inter-switch links external to systems. + +.TP 10 +verifyall + +Returns verifyfis, verifysws, verifysms, and verifylinks reports. + + +.SH Point Syntax + +.TP 10 +gid:\fIvalue\fR + +\fIvalue\fR is numeric port GID of form: subnet:guid. + +.TP 10 +lid:\fIvalue\fR + +\fIvalue\fR is numeric LID. + +.TP 10 +lid:value:node + +\fIvalue\fR is numeric LID, selects entire node with given LID. + +.TP 10 +lid:\fIvalue\fR:port:\fIvalue2\fR + +\fIvalue\fR is numeric LID of node, \fIvalue2\fR is port number. + +.TP 10 +portguid:\fIvalue\fR + +\fIvalue\fR is numeric port GUID. + +.TP 10 +nodeguid:\fIvalue\fR + +\fIvalue\fR is numeric node GUID. + +.TP 10 +nodeguid:\fIvalue1\fR:port:\fIvalue2\fR + +\fIvalue1\fR is numeric node GUID, \fIvalue2\fR is port number. + +.TP 10 +iocguid:\fIvalue\fR + +\fIvalue\fR is numeric IOC GUID. + +.TP 10 +iocguid:\fIvalue1\fR:port:\fIvalue2\fR + +\fIvalue1\fR is numeric IOC GUID, \fIvalue2\fR is port number. + +.TP 10 +systemguid:\fIvalue\fR + +\fIvalue\fR is numeric system image GUID. + +.TP 10 +systemguid:\fIvalue1\fR:port:\fIvalue2\fR + +\fIvalue1\fR is the numeric system image GUID, \fIvalue2\fR is port number. + +.TP 10 +ioc:\fIvalue\fR + +\fIvalue\fR is IOC Profile ID String (IOC Name). + +.TP 10 +ioc:\fIvalue1\fR:port:\fIvalue2\fR + +\fIvalue1\fR is IOC Profile ID String (IOC Name), \fIvalue2\fR is port number. + +.TP 10 +iocpat:\fIvalue\fR + +\fIvalue\fR is glob pattern for IOC Profile ID String (IOC Name). + +.TP 10 +iocpat:\fIvalue1\fR:port:\fIvalue2\fR + +\fIvalue1\fR is glob pattern for IOC Profile ID String (IOC Name), \fIvalue2\fR is port number. + +.TP 10 +ioctype:\fIvalue\fR + +\fIvalue\fR is IOC type (SRP or OTHER). + +.TP 10 +ioctype:\fIvalue1\fR:port:\fIvalue2\fR + +\fIvalue1\fR is IOC type (SRP or OTHER); \fIvalue2\fR is port number. + +.TP 10 +node:\fIvalue\fR + +\fIvalue\fR is node description (node name). + +.TP 10 +node:\fIvalue1\fR:port:\fIvalue2\fR + +\fIvalue1\fR is node description (node name), \fIvalue2\fR is port number. + +.TP 10 +nodepat:\fIvalue\fR + +\fIvalue\fR is glob pattern for node description (node name). + +.TP 10 +nodepat:\fIvalue1\fR:port:\fIvalue2\fR + +\fIvalue1\fR is the glob pattern for the node description (node name), \fIvalue2\fR is port number. + +.TP 10 +nodedetpat:\fIvalue\fR + +\fIvalue\fR is glob pattern for node details. + +.TP 10 +nodedetpat:\fIvalue1\fR:port:\fIvalue2\fR + +\fIvalue1\fR is the glob pattern for the node details, \fIvalue2\fR is port number. + +.TP 10 +nodetype:\fIvalue\fR + +\fIvalue\fR is node type (SW or FI). + +.TP 10 +nodetype:\fIvalue1\fR:port:\fIvalue2\fR + +\fIvalue1\fR is node type (SW or FI), \fIvalue2\fR is port number. + +.TP 10 +rate:\fIvalue\fR + +\fIvalue\fR is string for rate (25g, 50g, 75g, 100g), omits switch mgmt port 0. + +.TP 10 +portstate:\fIvalue\fR + +\fIvalue\fR is a string for state (down, init, armed, active, notactive, initarmed). + +.TP 10 +portphysstate:\fIvalue\fR + +\fIvalue\fR is a string for PHYs state (polling, disabled, training, linkup, recovery, offline, test) + +.TP 10 +mtucap:\fIvalue\fR + +\fIvalue\fR is MTU size (2048, 4096, 8192, 10240), omits switch mgmt port 0. + +.TP 10 +labelpat:\fIvalue\fR + +\fIvalue\fR is glob pattern for cable label. + +.TP 10 +lengthpat:\fIvalue\fR + +\fIvalue\fR is glob pattern for cable length. + +.TP 10 +cabledetpat:\fIvalue\fR + +\fIvalue\fR is glob pattern for cable details. + +.TP 10 +cabinflenpat:\fIvalue\fR + +\fIvalue\fR is glob pattern for cable info length. + +.TP 10 +cabinfvendnamepat:\fIvalue\fR + +\fIvalue\fR is glob pattern for cable info vendor name. + +.TP 10 +cabinfvendpnpat:\fIvalue\fR + +\fIvalue\fR is glob pattern for cable info vendor part number. + +.TP 10 +cabinfvendrevpat:\fIvalue\fR + +\fIvalue\fR is glob pattern for cable info vendor revision. + +.TP 10 +cabinfvendsnpat:\fIvalue\fR + +\fIvalue\fR is glob pattern for cable info vendor serial number. + +.TP 10 +cabinftype:\fIvalue\fR + +\fIvalue\fR is either optical, passive\(ulcopper, active\(ulcopper, or unknown. + +.TP 10 +linkdetpat:\fIvalue\fR + +\fIvalue\fR is glob pattern for link details. + +.TP 10 +portdetpat:\fIvalue\fR + +\fIvalue\fR is glob pattern for port details. + +.TP 10 +sm + +Specifies the master subnet manager (SM). + +.TP 10 +smdetpat:\fIvalue\fR + +\fIvalue\fR is glob pattern for SM details. + +.TP 10 +route:\fIpoint1\fR:\fIpoint2\fR + +Specifies all ports along the routes between the two given points. + +.TP 10 +led:\fIvalue\fR + +\fIvalue\fR is either on or off for LED port beacon. + +.TP 10 +linkqual:\fIvalue\fR + +Specifies the ports with a link quality equal to \fIvalue\fR. + +.TP 10 +linkqualLE:\fIvalue\fR + +Specifies the ports with a link quality less than or equal to \fIvalue\fR. + +.TP 10 +linkqualGE:\fIvalue\fR + +Specifies the ports with a link quality greater than or equal to \fIvalue\fR. + +.TP 10 +nodepatfile:\fIFILENAME\fR + +Specifies the name of file with the list of nodepats or node descriptions. + +.TP 10 +nodepairpatfile:\fIFILENAME\fR + +Specifies the name of file with the list of node pairs, separated by a colon. + +.TP 10 +ldr + +Specifies the ports with a non-zero link down reason or neighbor link down reason. + +.TP 10 +ldr:\fIvalue\fR + +Specifies the ports with a link down reason or neighbor link down reason equal to \fIvalue\fR. + +.SH Examples +List all the missing links in the fabric: +.br + + opaextractmissinglinks +.br + + +.br + +List all the missing links to a switch named "coresw1": +.br + + opaextractmissinglinks -T topology.0:0.xml -F "node:coresw1" +.br + + +.br + +List all the missing connections to end-nodes: +.br + + opaextractmissinglinks -o verifyfilinks +.br + + +.br + +List all the missing links on the 2nd HFI\[aq]s fabric of a multi-plane fabric: +.br + + opaextractmissinglinks -h 2 -T /etc/opa/topology.2:1.xml +.br + + +.br + +List all the missing links between two switches: +.br + + opaextractmissinglinks -o verifyislinks -T topology.0:0.xml diff --git a/IbaTools/man/opaextractperf.manPage b/IbaTools/man/opaextractperf.manPage new file mode 100644 index 0000000..7422a57 --- /dev/null +++ b/IbaTools/man/opaextractperf.manPage @@ -0,0 +1,468 @@ +.\" .\" ********************************************************************* +.\" .\" * * +.\" .\" * Copyright 2015-2019, Intel Corporation * +.\" .\" * * +.\" .\" * All Rights Reserved. * +.\" .\" * * +.\" .\" ********************************************************************* + +.TH opaextractperf 8 "Intel Corporation" "Copyright(C) 2015\-2019" "IFSFFCLIRG (Man Page)" +.SH NAME +opaextractperf + + +.PP +Provides a report of all performance counters in a CVS format suitable for importing into a spreadsheet or parsed by other scripts for further analysis. It generates a detailed opareport component summary report and pipes the result to opaxmlextract, extracting element values for NodeDesc, SystemImageGUID, PortNum, and all the performance counters. Extraction is performed only from the Systems portion of the report, which does not contain Neighbor information (the Neighbor and SMs portions are suppressed). +.SH Syntax +opaextractperf [opareport \fIoptions\fR] +.SH Options + +.TP 10 +--help + +Produces full help text. + +.TP 10 +opareport \fIoptions\fR + +The following options are passed to opareport. This subset is considered typical and useful for this command. By design, the tool ignores -o/--output report option. + +.RS +.TP 10 + +.sp +-h/--hfi \fIhfi\fR +Specifies the HFI, numbered 1..n. Using 0 specifies that the -p \fIport\fR port is a system-wide port number. Default is 0. + +.RE + +.RS +.TP 10 + +.sp +-p/--port \fIport\fR +Specifies the port, numbered 1..n. Using 0 specifies the first active port. Default is 0. + +.RE + +.RS +.TP 10 + +.sp +-X/--infile \fIsnapshot\(ulinput\fR +Generates a report using the data in the snapshot\(ulinput file. snapshot\(ulinput must have been generated during a previous -o \fIsnapshot\fR run. When used, the -s, -i, -C, and -a options are ignored. \[aq]-\[aq] may be used as the snapshot\(ulinput to specify stdin. + +.RE + +.RS +.TP 10 + +.sp +-T/--topology \fItopology\(ulinput\fR +Uses topology\(ulinput file to augment and verify fabric information. When used, various reports can be augmented with information not available electronically (such as cable labels). \[aq]-\[aq] may be used to specify stdin. + +.RE + +.RS +.TP 10 + +.sp +-i/--interval \fIseconds\fR +Obtains performance statistics over interval \fIseconds\fR. Clears all statistics, waits interval \fIseconds\fR, then generates report. Implies -s option. + +.RE + +.RS +.TP 10 + +.sp +-b / --begin \fIdate\(ultime\fR +Obtains past performance stats over an interval beginning at \fIdate\(ultime\fR. Implies -s option. \fIdate\(ultime\fR may be a time entered as HH:MM[:SS] or date as mm/dd/YYYY, dd.mm.YYYY, YYYY-mm-dd or date followed by time; for example, "2016-07-04 14:40". Relative times are taken as "x [second|minute|hour|day](s) ago. + +.RE + +.RS +.TP 10 + +.sp +-e / --end \fIdate\(ultime\fR +Obtains past performance stats over an interval ending at \fIdate\(ultime\fR. Implies -s option. + +.IP +\fIdate\(ultime\fR may be a time entered as HH:MM[:SS] or date as mm/dd/YYYY, dd.mm.YYYY, YYYY-mm-dd or date followed by time; for example, "2016-07-04 14:40". Relative times are taken as "x [second|minute|hour|day](s) ago. +.RE + +.RS +.TP 10 + +.sp +-C/--clear +Clears performance statistics for all ports. Only statistics with error thresholds are cleared. A clear occurs after generating the report. + +.RE + +.RS +.TP 10 + +.sp +-a/--clearall +Clears all performance statistics for all ports. + +.RE + +.RS +.TP 10 + +.sp +-M/--pmadirect +Accesses performance statistics using direct PMA. + +.RE + +.RS +.TP 10 + +.sp +-A/--allports +Gets PortInfo for down switch ports. Uses direct SMA to get this data. If used with -M, also gets PMA stats for down switch ports. + +.RE + +.RS +.TP 10 + +.sp +-F/--focus \fIpoint\fR +Specifies the focus area for report. Used for all reports except route to limit scope of report. Refer to +\fIPoint Syntax\fR +for details. + +.RE + + +.SH -h and -p options permit a variety of selections: + +.TP 10 +-h 0 + +First active port in system (Default). + +.TP 10 +-h 0 -p 0 + +First active port in system. + +.TP 10 +-h \fIx\fR + +First active port on HFI \fIx\fR. + +.TP 10 +-h \fIx\fR \fI\fR-p 0 + +First active port on HFI \fIx\fR. + +.TP 10 +-h 0 -p \fIy\fR + +Port \fIy\fR within system (no matter which ports are active). + +.TP 10 +-h \fIx\fR \fI\fR-p \fIy\fR + +HFI \fIx\fR, port \fIy\fR. + + +.SH Point Syntax + +.TP 10 +gid:\fIvalue\fR + +\fIvalue\fR is numeric port GID of form: subnet:guid. + +.TP 10 +lid:\fIvalue\fR + +\fIvalue\fR is numeric LID. + +.TP 10 +lid:value:node + +\fIvalue\fR is numeric LID, selects entire node with given LID. + +.TP 10 +lid:\fIvalue\fR:port:\fIvalue2\fR + +\fIvalue\fR is numeric LID of node, \fIvalue2\fR is port number. + +.TP 10 +portguid:\fIvalue\fR + +\fIvalue\fR is numeric port GUID. + +.TP 10 +nodeguid:\fIvalue\fR + +\fIvalue\fR is numeric node GUID. + +.TP 10 +nodeguid:\fIvalue1\fR:port:\fIvalue2\fR + +\fIvalue1\fR is numeric node GUID, \fIvalue2\fR is port number. + +.TP 10 +iocguid:\fIvalue\fR + +\fIvalue\fR is numeric IOC GUID. + +.TP 10 +iocguid:\fIvalue1\fR:port:\fIvalue2\fR + +\fIvalue1\fR is numeric IOC GUID, \fIvalue2\fR is port number. + +.TP 10 +systemguid:\fIvalue\fR + +\fIvalue\fR is numeric system image GUID. + +.TP 10 +systemguid:\fIvalue1\fR:port:\fIvalue2\fR + +\fIvalue1\fR is the numeric system image GUID, \fIvalue2\fR is port number. + +.TP 10 +ioc:\fIvalue\fR + +\fIvalue\fR is IOC Profile ID String (IOC Name). + +.TP 10 +ioc:\fIvalue1\fR:port:\fIvalue2\fR + +\fIvalue1\fR is IOC Profile ID String (IOC Name), \fIvalue2\fR is port number. + +.TP 10 +iocpat:\fIvalue\fR + +\fIvalue\fR is glob pattern for IOC Profile ID String (IOC Name). + +.TP 10 +iocpat:\fIvalue1\fR:port:\fIvalue2\fR + +\fIvalue1\fR is glob pattern for IOC Profile ID String (IOC Name), \fIvalue2\fR is port number. + +.TP 10 +ioctype:\fIvalue\fR + +\fIvalue\fR is IOC type (SRP or OTHER). + +.TP 10 +ioctype:\fIvalue1\fR:port:\fIvalue2\fR + +\fIvalue1\fR is IOC type (SRP or OTHER); \fIvalue2\fR is port number. + +.TP 10 +node:\fIvalue\fR + +\fIvalue\fR is node description (node name). + +.TP 10 +node:\fIvalue1\fR:port:\fIvalue2\fR + +\fIvalue1\fR is node description (node name), \fIvalue2\fR is port number. + +.TP 10 +nodepat:\fIvalue\fR + +\fIvalue\fR is glob pattern for node description (node name). + +.TP 10 +nodepat:\fIvalue1\fR:port:\fIvalue2\fR + +\fIvalue1\fR is the glob pattern for the node description (node name), \fIvalue2\fR is port number. + +.TP 10 +nodedetpat:\fIvalue\fR + +\fIvalue\fR is glob pattern for node details. + +.TP 10 +nodedetpat:\fIvalue1\fR:port:\fIvalue2\fR + +\fIvalue1\fR is the glob pattern for the node details, \fIvalue2\fR is port number. + +.TP 10 +nodetype:\fIvalue\fR + +\fIvalue\fR is node type (SW or FI). + +.TP 10 +nodetype:\fIvalue1\fR:port:\fIvalue2\fR + +\fIvalue1\fR is node type (SW or FI), \fIvalue2\fR is port number. + +.TP 10 +rate:\fIvalue\fR + +\fIvalue\fR is string for rate (25g, 50g, 75g, 100g), omits switch mgmt port 0. + +.TP 10 +portstate:\fIvalue\fR + +\fIvalue\fR is a string for state (down, init, armed, active, notactive, initarmed). + +.TP 10 +portphysstate:\fIvalue\fR + +\fIvalue\fR is a string for PHYs state (polling, disabled, training, linkup, recovery, offline, test) + +.TP 10 +mtucap:\fIvalue\fR + +\fIvalue\fR is MTU size (2048, 4096, 8192, 10240), omits switch mgmt port 0. + +.TP 10 +labelpat:\fIvalue\fR + +\fIvalue\fR is glob pattern for cable label. + +.TP 10 +lengthpat:\fIvalue\fR + +\fIvalue\fR is glob pattern for cable length. + +.TP 10 +cabledetpat:\fIvalue\fR + +\fIvalue\fR is glob pattern for cable details. + +.TP 10 +cabinflenpat:\fIvalue\fR + +\fIvalue\fR is glob pattern for cable info length. + +.TP 10 +cabinfvendnamepat:\fIvalue\fR + +\fIvalue\fR is glob pattern for cable info vendor name. + +.TP 10 +cabinfvendpnpat:\fIvalue\fR + +\fIvalue\fR is glob pattern for cable info vendor part number. + +.TP 10 +cabinfvendrevpat:\fIvalue\fR + +\fIvalue\fR is glob pattern for cable info vendor revision. + +.TP 10 +cabinfvendsnpat:\fIvalue\fR + +\fIvalue\fR is glob pattern for cable info vendor serial number. + +.TP 10 +cabinftype:\fIvalue\fR + +\fIvalue\fR is either optical, passive\(ulcopper, active\(ulcopper, or unknown. + +.TP 10 +linkdetpat:\fIvalue\fR + +\fIvalue\fR is glob pattern for link details. + +.TP 10 +portdetpat:\fIvalue\fR + +\fIvalue\fR is glob pattern for port details. + +.TP 10 +sm + +Specifies the master subnet manager (SM). + +.TP 10 +smdetpat:\fIvalue\fR + +\fIvalue\fR is glob pattern for SM details. + +.TP 10 +route:\fIpoint1\fR:\fIpoint2\fR + +Specifies all ports along the routes between the two given points. + +.TP 10 +led:\fIvalue\fR + +\fIvalue\fR is either on or off for LED port beacon. + +.TP 10 +linkqual:\fIvalue\fR + +Specifies the ports with a link quality equal to \fIvalue\fR. + +.TP 10 +linkqualLE:\fIvalue\fR + +Specifies the ports with a link quality less than or equal to \fIvalue\fR. + +.TP 10 +linkqualGE:\fIvalue\fR + +Specifies the ports with a link quality greater than or equal to \fIvalue\fR. + +.TP 10 +nodepatfile:\fIFILENAME\fR + +Specifies the name of file with the list of nodepats or node descriptions. + +.TP 10 +nodepairpatfile:\fIFILENAME\fR + +Specifies the name of file with the list of node pairs, separated by a colon. + +.TP 10 +ldr + +Specifies the ports with a non-zero link down reason or neighbor link down reason. + +.TP 10 +ldr:\fIvalue\fR + +Specifies the ports with a link down reason or neighbor link down reason equal to \fIvalue\fR. + + +.PP +The portion of the script that calls opareport and opaxmlextract follows: +.PP + +.br +opareport -o comps -s -x -d 10 $@ | opaxmlextract -d \; +.br + +-e NodeDesc -e SystemImageGUID -e PortNum -e XmitDataMB +.br + +-e XmitData -e XmitPkts -e RcvDataMB -e RcvData -e RcvPkts +.br + +-e SymbolErrors -e LinkErrorRecovery -e LinkDowned -e PortRcvErrors +.br + +-e PortRcvRemotePhysicalErrors -e PortRcvSwitchRelayErrors +.br + +-e PortXmitDiscards -e PortXmitConstraintErrors +.br + +-e PortRcvConstraintErrors -e LocalLinkIntegrityErrors +.br + +-e ExcessiveBufferOverrunErrors -e VL15Dropped -s Neighbor -s SMs + +.br + +.SH Example +opaextractperf +.br + +opaextractperf -h 1 -p 2 diff --git a/IbaTools/man/opaextractperf2.manPage b/IbaTools/man/opaextractperf2.manPage new file mode 100644 index 0000000..25b538c --- /dev/null +++ b/IbaTools/man/opaextractperf2.manPage @@ -0,0 +1,445 @@ +.\" .\" ********************************************************************* +.\" .\" * * +.\" .\" * Copyright 2015-2019, Intel Corporation * +.\" .\" * * +.\" .\" * All Rights Reserved. * +.\" .\" * * +.\" .\" ********************************************************************* + +.TH opaextractperf2 8 "Intel Corporation" "Copyright(C) 2015\-2019" "IFSFFCLIRG (Man Page)" +.SH NAME +opaextractperf2 + + +.PP +Provides a report of all performance counters in a CSV format suitable for importing into a spreadsheet or parsed by other scripts for further analysis. It generates a detailed opareport component summary report and pipes the result to opaxmlextract, extracting element values for NodeDesc, NodeGUID, PortNum, neighbor NodeDesc, neighbor NodeGUID, neighbor PortNum and all the performance counters. +.SH Syntax +opaextractperf2 [opareport \fIoptions\fR] +.SH Options + +.TP 10 +--help + +Produces full help text. + +.TP 10 +opareport \fIoptions\fR + +The following options are passed to opareport. This subset is considered typical and useful for this command. Do not use the -o/--output report option. + +.RS +.TP 10 + +.sp +-h/--hfi \fIhfi\fR +Specifies the HFI, numbered 1..n. Using 0 specifies that the -p \fIport\fR port is a system-wide port number. Default is 0. + +.RE + +.RS +.TP 10 + +.sp +-p/--port \fIport\fR +Specifies the port, numbered 1..n. Using 0 specifies the first active port. Default is 0. + +.RE + +.RS +.TP 10 + +.sp +-X/--infile \fIsnapshot\(ulinput\fR +Generates a report using the data in the snapshot\(ulinput file. snapshot\(ulinput must have been generated during a previous -o \fIsnapshot\fR run. When used, the -s, -i, -C, and -a options are ignored. \[aq]-\[aq] may be used as the snapshot\(ulinput to specify stdin. + +.RE + +.RS +.TP 10 + +.sp +-T/--topology \fItopology\(ulinput\fR +Uses topology\(ulinput file to augment and verify fabric information. When used, various reports can be augmented with information not available electronically (such as cable labels). \[aq]-\[aq] may be used to specify stdin. + +.RE + +.RS +.TP 10 + +.sp +-i/--interval \fIseconds\fR +Obtains performance statistics over interval \fIseconds\fR. Clears all statistics, waits interval \fIseconds\fR, then generates report. Implies -s option. + +.RE + +.RS +.TP 10 + +.sp +-b / --begin \fIdate\(ultime\fR +Obtains past performance stats over an interval beginning at \fIdate\(ultime\fR. Implies -s option. \fIdate\(ultime\fR may be a time entered as HH:MM[:SS] or date as mm/dd/YYYY, dd.mm.YYYY, YYYY-mm-dd or date followed by time; for example, "2016-07-04 14:40". Relative times are taken as "x [second|minute|hour|day](s) ago. + +.RE + +.RS +.TP 10 + +.sp +-e / --end \fIdate\(ultime\fR +Obtains past performance stats over an interval ending at \fIdate\(ultime\fR. Implies -s option. + +.IP +\fIdate\(ultime\fR may be a time entered as HH:MM[:SS] or date as mm/dd/YYYY, dd.mm.YYYY, YYYY-mm-dd or date followed by time; for example, "2016-07-04 14:40". Relative times are taken as "x [second|minute|hour|day](s) ago. +.RE + +.RS +.TP 10 + +.sp +-C/--clear +Clears performance statistics for all ports. Only statistics with error thresholds are cleared. A clear occurs after generating the report. + +.RE + +.RS +.TP 10 + +.sp +-a/--clearall +Clears all performance statistics for all ports. + +.RE + +.RS +.TP 10 + +.sp +-M/--pmadirect +Accesses performance statistics using direct PMA. + +.RE + +.RS +.TP 10 + +.sp +-A/--allports +Gets PortInfo for down switch ports. Uses direct SMA to get this data. If used with -M, also gets PMA stats for down switch ports. + +.RE + +.RS +.TP 10 + +.sp +-F/--focus \fIpoint\fR +Specifies the focus area for report. Used for all reports except route to limit scope of report. Refer to +\fIPoint Syntax\fR +for details. + +.RE + + +.SH -h and -p options permit a variety of selections: + +.TP 10 +-h 0 + +First active port in system (Default). + +.TP 10 +-h 0 -p 0 + +First active port in system. + +.TP 10 +-h \fIx\fR + +First active port on HFI \fIx\fR. + +.TP 10 +-h \fIx\fR \fI\fR-p 0 + +First active port on HFI \fIx\fR. + +.TP 10 +-h 0 -p \fIy\fR + +Port \fIy\fR within system (no matter which ports are active). + +.TP 10 +-h \fIx\fR \fI\fR-p \fIy\fR + +HFI \fIx\fR, port \fIy\fR. + + +.SH Point Syntax + +.TP 10 +gid:\fIvalue\fR + +\fIvalue\fR is numeric port GID of form: subnet:guid. + +.TP 10 +lid:\fIvalue\fR + +\fIvalue\fR is numeric LID. + +.TP 10 +lid:value:node + +\fIvalue\fR is numeric LID, selects entire node with given LID. + +.TP 10 +lid:\fIvalue\fR:port:\fIvalue2\fR + +\fIvalue\fR is numeric LID of node, \fIvalue2\fR is port number. + +.TP 10 +portguid:\fIvalue\fR + +\fIvalue\fR is numeric port GUID. + +.TP 10 +nodeguid:\fIvalue\fR + +\fIvalue\fR is numeric node GUID. + +.TP 10 +nodeguid:\fIvalue1\fR:port:\fIvalue2\fR + +\fIvalue1\fR is numeric node GUID, \fIvalue2\fR is port number. + +.TP 10 +iocguid:\fIvalue\fR + +\fIvalue\fR is numeric IOC GUID. + +.TP 10 +iocguid:\fIvalue1\fR:port:\fIvalue2\fR + +\fIvalue1\fR is numeric IOC GUID, \fIvalue2\fR is port number. + +.TP 10 +systemguid:\fIvalue\fR + +\fIvalue\fR is numeric system image GUID. + +.TP 10 +systemguid:\fIvalue1\fR:port:\fIvalue2\fR + +\fIvalue1\fR is the numeric system image GUID, \fIvalue2\fR is port number. + +.TP 10 +ioc:\fIvalue\fR + +\fIvalue\fR is IOC Profile ID String (IOC Name). + +.TP 10 +ioc:\fIvalue1\fR:port:\fIvalue2\fR + +\fIvalue1\fR is IOC Profile ID String (IOC Name), \fIvalue2\fR is port number. + +.TP 10 +iocpat:\fIvalue\fR + +\fIvalue\fR is glob pattern for IOC Profile ID String (IOC Name). + +.TP 10 +iocpat:\fIvalue1\fR:port:\fIvalue2\fR + +\fIvalue1\fR is glob pattern for IOC Profile ID String (IOC Name), \fIvalue2\fR is port number. + +.TP 10 +ioctype:\fIvalue\fR + +\fIvalue\fR is IOC type (SRP or OTHER). + +.TP 10 +ioctype:\fIvalue1\fR:port:\fIvalue2\fR + +\fIvalue1\fR is IOC type (SRP or OTHER); \fIvalue2\fR is port number. + +.TP 10 +node:\fIvalue\fR + +\fIvalue\fR is node description (node name). + +.TP 10 +node:\fIvalue1\fR:port:\fIvalue2\fR + +\fIvalue1\fR is node description (node name), \fIvalue2\fR is port number. + +.TP 10 +nodepat:\fIvalue\fR + +\fIvalue\fR is glob pattern for node description (node name). + +.TP 10 +nodepat:\fIvalue1\fR:port:\fIvalue2\fR + +\fIvalue1\fR is the glob pattern for the node description (node name), \fIvalue2\fR is port number. + +.TP 10 +nodedetpat:\fIvalue\fR + +\fIvalue\fR is glob pattern for node details. + +.TP 10 +nodedetpat:\fIvalue1\fR:port:\fIvalue2\fR + +\fIvalue1\fR is the glob pattern for the node details, \fIvalue2\fR is port number. + +.TP 10 +nodetype:\fIvalue\fR + +\fIvalue\fR is node type (SW or FI). + +.TP 10 +nodetype:\fIvalue1\fR:port:\fIvalue2\fR + +\fIvalue1\fR is node type (SW or FI), \fIvalue2\fR is port number. + +.TP 10 +rate:\fIvalue\fR + +\fIvalue\fR is string for rate (25g, 50g, 75g, 100g), omits switch mgmt port 0. + +.TP 10 +portstate:\fIvalue\fR + +\fIvalue\fR is a string for state (down, init, armed, active, notactive, initarmed). + +.TP 10 +portphysstate:\fIvalue\fR + +\fIvalue\fR is a string for PHYs state (polling, disabled, training, linkup, recovery, offline, test) + +.TP 10 +mtucap:\fIvalue\fR + +\fIvalue\fR is MTU size (2048, 4096, 8192, 10240), omits switch mgmt port 0. + +.TP 10 +labelpat:\fIvalue\fR + +\fIvalue\fR is glob pattern for cable label. + +.TP 10 +lengthpat:\fIvalue\fR + +\fIvalue\fR is glob pattern for cable length. + +.TP 10 +cabledetpat:\fIvalue\fR + +\fIvalue\fR is glob pattern for cable details. + +.TP 10 +cabinflenpat:\fIvalue\fR + +\fIvalue\fR is glob pattern for cable info length. + +.TP 10 +cabinfvendnamepat:\fIvalue\fR + +\fIvalue\fR is glob pattern for cable info vendor name. + +.TP 10 +cabinfvendpnpat:\fIvalue\fR + +\fIvalue\fR is glob pattern for cable info vendor part number. + +.TP 10 +cabinfvendrevpat:\fIvalue\fR + +\fIvalue\fR is glob pattern for cable info vendor revision. + +.TP 10 +cabinfvendsnpat:\fIvalue\fR + +\fIvalue\fR is glob pattern for cable info vendor serial number. + +.TP 10 +cabinftype:\fIvalue\fR + +\fIvalue\fR is either optical, passive\(ulcopper, active\(ulcopper, or unknown. + +.TP 10 +linkdetpat:\fIvalue\fR + +\fIvalue\fR is glob pattern for link details. + +.TP 10 +portdetpat:\fIvalue\fR + +\fIvalue\fR is glob pattern for port details. + +.TP 10 +sm + +Specifies the master subnet manager (SM). + +.TP 10 +smdetpat:\fIvalue\fR + +\fIvalue\fR is glob pattern for SM details. + +.TP 10 +route:\fIpoint1\fR:\fIpoint2\fR + +Specifies all ports along the routes between the two given points. + +.TP 10 +led:\fIvalue\fR + +\fIvalue\fR is either on or off for LED port beacon. + +.TP 10 +linkqual:\fIvalue\fR + +Specifies the ports with a link quality equal to \fIvalue\fR. + +.TP 10 +linkqualLE:\fIvalue\fR + +Specifies the ports with a link quality less than or equal to \fIvalue\fR. + +.TP 10 +linkqualGE:\fIvalue\fR + +Specifies the ports with a link quality greater than or equal to \fIvalue\fR. + +.TP 10 +nodepatfile:\fIFILENAME\fR + +Specifies the name of file with the list of nodepats or node descriptions. + +.TP 10 +nodepairpatfile:\fIFILENAME\fR + +Specifies the name of file with the list of node pairs, separated by a colon. + +.TP 10 +ldr + +Specifies the ports with a non-zero link down reason or neighbor link down reason. + +.TP 10 +ldr:\fIvalue\fR + +Specifies the ports with a link down reason or neighbor link down reason equal to \fIvalue\fR. + +.SH Example +opaextractperf +.br +2 +opaextractperf2 -h 1 -p 2 + + +.SH See Also + +.PP + +\fIopamergeperf2\fR + diff --git a/IbaTools/man/opaextractsellinks.manPage b/IbaTools/man/opaextractsellinks.manPage new file mode 100644 index 0000000..dfc0eb3 --- /dev/null +++ b/IbaTools/man/opaextractsellinks.manPage @@ -0,0 +1,399 @@ +.\" .\" ********************************************************************* +.\" .\" * * +.\" .\" * Copyright 2015-2019, Intel Corporation * +.\" .\" * * +.\" .\" * All Rights Reserved. * +.\" .\" * * +.\" .\" ********************************************************************* + +.TH opaextractsellinks 8 "Intel Corporation" "Copyright(C) 2015\-2019" "IFSFFCLIRG (Man Page)" +.SH NAME +opaextractsellinks + + +.PP +Produces a CSV file listing all or some of the links in the fabric. opaextractsellinks is a front end to the opareport tool. The output from this tool can be imported into a spreadsheet or parsed by other scripts. +.SH Syntax +opaextractsellinks [opareport \fIoptions\fR] +.SH Options + +.TP 10 +--help + +Produces full help text. + +.TP 10 +opareport \fIoptions\fR + +The following options are passed to opareport. This subset is considered typical and useful for this command. By design, the tool ignores -o/--output report option. + +.RS +.TP 10 + +.sp +-h/--hfi \fIhfi\fR +Specifies the HFI, numbered 1..n. Using 0 specifies that the -p \fIport\fR port is a system-wide port number. Default is 0. + +.RE + +.RS +.TP 10 + +.sp +-p/--port \fIport\fR +Specifies the port, numbered 1..n. Using 0 specifies the first active port. Default is 0. + +.RE + +.RS +.TP 10 + +.sp +-X/--infile \fIsnapshot\(ulinput\fR +Generates a report using the data in the snapshot\(ulinput file. snapshot\(ulinput must have been generated during a previous -o \fIsnapshot\fR run. When used, the -s, -i, -C, and -a options are ignored. \[aq]-\[aq] may be used as the snapshot\(ulinput to specify stdin. + +.RE + +.RS +.TP 10 + +.sp +-T/--topology \fItopology\(ulinput\fR +Uses topology\(ulinput file to augment and verify fabric information. When used, various reports can be augmented with information not available electronically (such as cable labels). \[aq]-\[aq] may be used to specify stdin. + +.RE + +.RS +.TP 10 + +.sp +-F/--focus \fIpoint\fR +Specifies the focus area for report. Used for all reports except route to limit scope of report. Refer to +\fIPoint Syntax\fR +for details. + +.RE + + +.SH -h and -p options permit a variety of selections: + +.TP 10 +-h 0 + +First active port in system (Default). + +.TP 10 +-h 0 -p 0 + +First active port in system. + +.TP 10 +-h \fIx\fR + +First active port on HFI \fIx\fR. + +.TP 10 +-h \fIx\fR \fI\fR-p 0 + +First active port on HFI \fIx\fR. + +.TP 10 +-h 0 -p \fIy\fR + +Port \fIy\fR within system (no matter which ports are active). + +.TP 10 +-h \fIx\fR \fI\fR-p \fIy\fR + +HFI \fIx\fR, port \fIy\fR. + + +.SH Point Syntax + +.TP 10 +gid:\fIvalue\fR + +\fIvalue\fR is numeric port GID of form: subnet:guid. + +.TP 10 +lid:\fIvalue\fR + +\fIvalue\fR is numeric LID. + +.TP 10 +lid:value:node + +\fIvalue\fR is numeric LID, selects entire node with given LID. + +.TP 10 +lid:\fIvalue\fR:port:\fIvalue2\fR + +\fIvalue\fR is numeric LID of node, \fIvalue2\fR is port number. + +.TP 10 +portguid:\fIvalue\fR + +\fIvalue\fR is numeric port GUID. + +.TP 10 +nodeguid:\fIvalue\fR + +\fIvalue\fR is numeric node GUID. + +.TP 10 +nodeguid:\fIvalue1\fR:port:\fIvalue2\fR + +\fIvalue1\fR is numeric node GUID, \fIvalue2\fR is port number. + +.TP 10 +iocguid:\fIvalue\fR + +\fIvalue\fR is numeric IOC GUID. + +.TP 10 +iocguid:\fIvalue1\fR:port:\fIvalue2\fR + +\fIvalue1\fR is numeric IOC GUID, \fIvalue2\fR is port number. + +.TP 10 +systemguid:\fIvalue\fR + +\fIvalue\fR is numeric system image GUID. + +.TP 10 +systemguid:\fIvalue1\fR:port:\fIvalue2\fR + +\fIvalue1\fR is the numeric system image GUID, \fIvalue2\fR is port number. + +.TP 10 +ioc:\fIvalue\fR + +\fIvalue\fR is IOC Profile ID String (IOC Name). + +.TP 10 +ioc:\fIvalue1\fR:port:\fIvalue2\fR + +\fIvalue1\fR is IOC Profile ID String (IOC Name), \fIvalue2\fR is port number. + +.TP 10 +iocpat:\fIvalue\fR + +\fIvalue\fR is glob pattern for IOC Profile ID String (IOC Name). + +.TP 10 +iocpat:\fIvalue1\fR:port:\fIvalue2\fR + +\fIvalue1\fR is glob pattern for IOC Profile ID String (IOC Name), \fIvalue2\fR is port number. + +.TP 10 +ioctype:\fIvalue\fR + +\fIvalue\fR is IOC type (SRP or OTHER). + +.TP 10 +ioctype:\fIvalue1\fR:port:\fIvalue2\fR + +\fIvalue1\fR is IOC type (SRP or OTHER); \fIvalue2\fR is port number. + +.TP 10 +node:\fIvalue\fR + +\fIvalue\fR is node description (node name). + +.TP 10 +node:\fIvalue1\fR:port:\fIvalue2\fR + +\fIvalue1\fR is node description (node name), \fIvalue2\fR is port number. + +.TP 10 +nodepat:\fIvalue\fR + +\fIvalue\fR is glob pattern for node description (node name). + +.TP 10 +nodepat:\fIvalue1\fR:port:\fIvalue2\fR + +\fIvalue1\fR is the glob pattern for the node description (node name), \fIvalue2\fR is port number. + +.TP 10 +nodedetpat:\fIvalue\fR + +\fIvalue\fR is glob pattern for node details. + +.TP 10 +nodedetpat:\fIvalue1\fR:port:\fIvalue2\fR + +\fIvalue1\fR is the glob pattern for the node details, \fIvalue2\fR is port number. + +.TP 10 +nodetype:\fIvalue\fR + +\fIvalue\fR is node type (SW or FI). + +.TP 10 +nodetype:\fIvalue1\fR:port:\fIvalue2\fR + +\fIvalue1\fR is node type (SW or FI), \fIvalue2\fR is port number. + +.TP 10 +rate:\fIvalue\fR + +\fIvalue\fR is string for rate (25g, 50g, 75g, 100g), omits switch mgmt port 0. + +.TP 10 +portstate:\fIvalue\fR + +\fIvalue\fR is a string for state (down, init, armed, active, notactive, initarmed). + +.TP 10 +portphysstate:\fIvalue\fR + +\fIvalue\fR is a string for PHYs state (polling, disabled, training, linkup, recovery, offline, test) + +.TP 10 +mtucap:\fIvalue\fR + +\fIvalue\fR is MTU size (2048, 4096, 8192, 10240), omits switch mgmt port 0. + +.TP 10 +labelpat:\fIvalue\fR + +\fIvalue\fR is glob pattern for cable label. + +.TP 10 +lengthpat:\fIvalue\fR + +\fIvalue\fR is glob pattern for cable length. + +.TP 10 +cabledetpat:\fIvalue\fR + +\fIvalue\fR is glob pattern for cable details. + +.TP 10 +cabinflenpat:\fIvalue\fR + +\fIvalue\fR is glob pattern for cable info length. + +.TP 10 +cabinfvendnamepat:\fIvalue\fR + +\fIvalue\fR is glob pattern for cable info vendor name. + +.TP 10 +cabinfvendpnpat:\fIvalue\fR + +\fIvalue\fR is glob pattern for cable info vendor part number. + +.TP 10 +cabinfvendrevpat:\fIvalue\fR + +\fIvalue\fR is glob pattern for cable info vendor revision. + +.TP 10 +cabinfvendsnpat:\fIvalue\fR + +\fIvalue\fR is glob pattern for cable info vendor serial number. + +.TP 10 +cabinftype:\fIvalue\fR + +\fIvalue\fR is either optical, passive\(ulcopper, active\(ulcopper, or unknown. + +.TP 10 +linkdetpat:\fIvalue\fR + +\fIvalue\fR is glob pattern for link details. + +.TP 10 +portdetpat:\fIvalue\fR + +\fIvalue\fR is glob pattern for port details. + +.TP 10 +sm + +Specifies the master subnet manager (SM). + +.TP 10 +smdetpat:\fIvalue\fR + +\fIvalue\fR is glob pattern for SM details. + +.TP 10 +route:\fIpoint1\fR:\fIpoint2\fR + +Specifies all ports along the routes between the two given points. + +.TP 10 +led:\fIvalue\fR + +\fIvalue\fR is either on or off for LED port beacon. + +.TP 10 +linkqual:\fIvalue\fR + +Specifies the ports with a link quality equal to \fIvalue\fR. + +.TP 10 +linkqualLE:\fIvalue\fR + +Specifies the ports with a link quality less than or equal to \fIvalue\fR. + +.TP 10 +linkqualGE:\fIvalue\fR + +Specifies the ports with a link quality greater than or equal to \fIvalue\fR. + +.TP 10 +nodepatfile:\fIFILENAME\fR + +Specifies the name of file with the list of nodepats or node descriptions. + +.TP 10 +nodepairpatfile:\fIFILENAME\fR + +Specifies the name of file with the list of node pairs, separated by a colon. + +.TP 10 +ldr + +Specifies the ports with a non-zero link down reason or neighbor link down reason. + +.TP 10 +ldr:\fIvalue\fR + +Specifies the ports with a link down reason or neighbor link down reason equal to \fIvalue\fR. + +.SH Examples +# List all the links in the fabric: +.br + +opaextractsellinks +.br + + +.br + +# List all the links to a switch named "coresw1": +.br + +opaextractsellinks -F "node:coresw1" +.br + + +.br + +# List all the connections to end-nodes: +.br + +opaextractsellinks -F "nodetype:FI" +.br + + +.br + +# List all the links on the 2nd HFI\[aq]s fabric of a multi-plane fabric: +.br + +opaextractsellinks -h 2 diff --git a/IbaTools/man/opaextractstat.manPage b/IbaTools/man/opaextractstat.manPage new file mode 100644 index 0000000..4a09a64 --- /dev/null +++ b/IbaTools/man/opaextractstat.manPage @@ -0,0 +1,473 @@ +.\" .\" ********************************************************************* +.\" .\" * * +.\" .\" * Copyright 2015-2019, Intel Corporation * +.\" .\" * * +.\" .\" * All Rights Reserved. * +.\" .\" * * +.\" .\" ********************************************************************* + +.TH opaextractstat 8 "Intel Corporation" "Copyright(C) 2015\-2019" "IFSFFCLIRG (Man Page)" +.SH NAME +opaextractstat + + +.PP +Performs an error analysis of a fabric and provides augmented information from a topology\(ulfile. The report provides cable information as well as symbol error counts. +.PP +opaextractstat generates a detailed opareport errors report that also has a topology file (see +\fIopareport\fR +for more information about topology files). The report is piped to opaxmlextract which extracts values for Link, Cable and Port. (The port element names are context-sensitive.) Note that opaxmlextract generates two extraction records for each link (one for each port on the link); therefore, opaextractstat merges the two records into a single record and removes redundant link and cable information. +.PP +opaextractstat contains a while read loop that reads the CSV line-by-line, uses cut to remove redundant information, and outputs the data on a common line. +.SH Syntax +opaextractstat topology\(ulfile [opareport \fIoptions\fR] +.SH Options + +.TP 10 +--help + +Produces full help text. + +.TP 10 +topology\(ulfile + +Specifies topology\(ulfile to use. + +.TP 10 +opareport \fIoptions\fR + +The following options are passed to opareport. This subset is considered typical and useful for this command. By design, the tool ignores -o/--output report option. + +.RS +.TP 10 + +.sp +-h/--hfi \fIhfi\fR +Specifies the HFI, numbered 1..n. Using 0 specifies that the -p \fIport\fR port is a system-wide port number. Default is 0. + +.RE + +.RS +.TP 10 + +.sp +-p/--port \fIport\fR +Specifies the port, numbered 1..n. Using 0 specifies the first active port. Default is 0. + +.RE + +.RS +.TP 10 + +.sp +-X/--infile \fIsnapshot\(ulinput\fR +Generates a report using the data in the snapshot\(ulinput file. snapshot\(ulinput must have been generated during a previous -o \fIsnapshot\fR run. When used, the -s, -i, -C, and -a options are ignored. \[aq]-\[aq] may be used as the snapshot\(ulinput to specify stdin. + +.RE + +.RS +.TP 10 + +.sp +-i/--interval \fIseconds\fR +Obtains performance statistics over interval \fIseconds\fR. Clears all statistics, waits interval \fIseconds\fR, then generates report. Implies -s option. + +.RE + +.RS +.TP 10 + +.sp +-b / --begin \fIdate\(ultime\fR +Obtains past performance stats over an interval beginning at \fIdate\(ultime\fR. Implies -s option. \fIdate\(ultime\fR may be a time entered as HH:MM[:SS] or date as mm/dd/YYYY, dd.mm.YYYY, YYYY-mm-dd or date followed by time; for example, "2016-07-04 14:40". Relative times are taken as "x [second|minute|hour|day](s) ago. + +.RE + +.RS +.TP 10 + +.sp +-e / --end \fIdate\(ultime\fR +Obtains past performance stats over an interval ending at \fIdate\(ultime\fR. Implies -s option. + +.IP +\fIdate\(ultime\fR may be a time entered as HH:MM[:SS] or date as mm/dd/YYYY, dd.mm.YYYY, YYYY-mm-dd or date followed by time; for example, "2016-07-04 14:40". Relative times are taken as "x [second|minute|hour|day](s) ago. +.RE + +.RS +.TP 10 + +.sp +-C/--clear +Clears performance statistics for all ports. Only statistics with error thresholds are cleared. A clear occurs after generating the report. + +.RE + +.RS +.TP 10 + +.sp +-a/--clearall +Clears all performance statistics for all ports. + +.RE + +.RS +.TP 10 + +.sp +-M/--pmadirect +Accesses performance statistics using direct PMA. + +.RE + +.RS +.TP 10 + +.sp +-A/--allports +Gets PortInfo for down switch ports. Uses direct SMA to get this data. If used with -M, also gets PMA stats for down switch ports. + +.RE + +.RS +.TP 10 + +.sp +-c/--config \fIfile\fR +Specifies the error thresholds configuration file. Default is /etc/opa/opamon.conf file. + +.RE + +.RS +.TP 10 + +.sp +-L/--limit +Limits operation to exact specified focus with -F for port error counters check (-o \fIerrors\fR) and port counters clear (-C or -i). Normally, the neighbor of each selected port is also checked/cleared. Does not affect other reports. + +.RE + +.RS +.TP 10 + +.sp +-F/--focus \fIpoint\fR +Specifies the focus area for report. Used for all reports except route to limit scope of report. Refer to +\fIPoint Syntax\fR +for details. + +.RE + + +.SH -h and -p options permit a variety of selections: + +.TP 10 +-h 0 + +First active port in system (Default). + +.TP 10 +-h 0 -p 0 + +First active port in system. + +.TP 10 +-h \fIx\fR + +First active port on HFI \fIx\fR. + +.TP 10 +-h \fIx\fR \fI\fR-p 0 + +First active port on HFI \fIx\fR. + +.TP 10 +-h 0 -p \fIy\fR + +Port \fIy\fR within system (no matter which ports are active). + +.TP 10 +-h \fIx\fR \fI\fR-p \fIy\fR + +HFI \fIx\fR, port \fIy\fR. + + +.SH Point Syntax + +.TP 10 +gid:\fIvalue\fR + +\fIvalue\fR is numeric port GID of form: subnet:guid. + +.TP 10 +lid:\fIvalue\fR + +\fIvalue\fR is numeric LID. + +.TP 10 +lid:value:node + +\fIvalue\fR is numeric LID, selects entire node with given LID. + +.TP 10 +lid:\fIvalue\fR:port:\fIvalue2\fR + +\fIvalue\fR is numeric LID of node, \fIvalue2\fR is port number. + +.TP 10 +portguid:\fIvalue\fR + +\fIvalue\fR is numeric port GUID. + +.TP 10 +nodeguid:\fIvalue\fR + +\fIvalue\fR is numeric node GUID. + +.TP 10 +nodeguid:\fIvalue1\fR:port:\fIvalue2\fR + +\fIvalue1\fR is numeric node GUID, \fIvalue2\fR is port number. + +.TP 10 +iocguid:\fIvalue\fR + +\fIvalue\fR is numeric IOC GUID. + +.TP 10 +iocguid:\fIvalue1\fR:port:\fIvalue2\fR + +\fIvalue1\fR is numeric IOC GUID, \fIvalue2\fR is port number. + +.TP 10 +systemguid:\fIvalue\fR + +\fIvalue\fR is numeric system image GUID. + +.TP 10 +systemguid:\fIvalue1\fR:port:\fIvalue2\fR + +\fIvalue1\fR is the numeric system image GUID, \fIvalue2\fR is port number. + +.TP 10 +ioc:\fIvalue\fR + +\fIvalue\fR is IOC Profile ID String (IOC Name). + +.TP 10 +ioc:\fIvalue1\fR:port:\fIvalue2\fR + +\fIvalue1\fR is IOC Profile ID String (IOC Name), \fIvalue2\fR is port number. + +.TP 10 +iocpat:\fIvalue\fR + +\fIvalue\fR is glob pattern for IOC Profile ID String (IOC Name). + +.TP 10 +iocpat:\fIvalue1\fR:port:\fIvalue2\fR + +\fIvalue1\fR is glob pattern for IOC Profile ID String (IOC Name), \fIvalue2\fR is port number. + +.TP 10 +ioctype:\fIvalue\fR + +\fIvalue\fR is IOC type (SRP or OTHER). + +.TP 10 +ioctype:\fIvalue1\fR:port:\fIvalue2\fR + +\fIvalue1\fR is IOC type (SRP or OTHER); \fIvalue2\fR is port number. + +.TP 10 +node:\fIvalue\fR + +\fIvalue\fR is node description (node name). + +.TP 10 +node:\fIvalue1\fR:port:\fIvalue2\fR + +\fIvalue1\fR is node description (node name), \fIvalue2\fR is port number. + +.TP 10 +nodepat:\fIvalue\fR + +\fIvalue\fR is glob pattern for node description (node name). + +.TP 10 +nodepat:\fIvalue1\fR:port:\fIvalue2\fR + +\fIvalue1\fR is the glob pattern for the node description (node name), \fIvalue2\fR is port number. + +.TP 10 +nodedetpat:\fIvalue\fR + +\fIvalue\fR is glob pattern for node details. + +.TP 10 +nodedetpat:\fIvalue1\fR:port:\fIvalue2\fR + +\fIvalue1\fR is the glob pattern for the node details, \fIvalue2\fR is port number. + +.TP 10 +nodetype:\fIvalue\fR + +\fIvalue\fR is node type (SW or FI). + +.TP 10 +nodetype:\fIvalue1\fR:port:\fIvalue2\fR + +\fIvalue1\fR is node type (SW or FI), \fIvalue2\fR is port number. + +.TP 10 +rate:\fIvalue\fR + +\fIvalue\fR is string for rate (25g, 50g, 75g, 100g), omits switch mgmt port 0. + +.TP 10 +portstate:\fIvalue\fR + +\fIvalue\fR is a string for state (down, init, armed, active, notactive, initarmed). + +.TP 10 +portphysstate:\fIvalue\fR + +\fIvalue\fR is a string for PHYs state (polling, disabled, training, linkup, recovery, offline, test) + +.TP 10 +mtucap:\fIvalue\fR + +\fIvalue\fR is MTU size (2048, 4096, 8192, 10240), omits switch mgmt port 0. + +.TP 10 +labelpat:\fIvalue\fR + +\fIvalue\fR is glob pattern for cable label. + +.TP 10 +lengthpat:\fIvalue\fR + +\fIvalue\fR is glob pattern for cable length. + +.TP 10 +cabledetpat:\fIvalue\fR + +\fIvalue\fR is glob pattern for cable details. + +.TP 10 +cabinflenpat:\fIvalue\fR + +\fIvalue\fR is glob pattern for cable info length. + +.TP 10 +cabinfvendnamepat:\fIvalue\fR + +\fIvalue\fR is glob pattern for cable info vendor name. + +.TP 10 +cabinfvendpnpat:\fIvalue\fR + +\fIvalue\fR is glob pattern for cable info vendor part number. + +.TP 10 +cabinfvendrevpat:\fIvalue\fR + +\fIvalue\fR is glob pattern for cable info vendor revision. + +.TP 10 +cabinfvendsnpat:\fIvalue\fR + +\fIvalue\fR is glob pattern for cable info vendor serial number. + +.TP 10 +cabinftype:\fIvalue\fR + +\fIvalue\fR is either optical, passive\(ulcopper, active\(ulcopper, or unknown. + +.TP 10 +linkdetpat:\fIvalue\fR + +\fIvalue\fR is glob pattern for link details. + +.TP 10 +portdetpat:\fIvalue\fR + +\fIvalue\fR is glob pattern for port details. + +.TP 10 +sm + +Specifies the master subnet manager (SM). + +.TP 10 +smdetpat:\fIvalue\fR + +\fIvalue\fR is glob pattern for SM details. + +.TP 10 +route:\fIpoint1\fR:\fIpoint2\fR + +Specifies all ports along the routes between the two given points. + +.TP 10 +led:\fIvalue\fR + +\fIvalue\fR is either on or off for LED port beacon. + +.TP 10 +linkqual:\fIvalue\fR + +Specifies the ports with a link quality equal to \fIvalue\fR. + +.TP 10 +linkqualLE:\fIvalue\fR + +Specifies the ports with a link quality less than or equal to \fIvalue\fR. + +.TP 10 +linkqualGE:\fIvalue\fR + +Specifies the ports with a link quality greater than or equal to \fIvalue\fR. + +.TP 10 +nodepatfile:\fIFILENAME\fR + +Specifies the name of file with the list of nodepats or node descriptions. + +.TP 10 +nodepairpatfile:\fIFILENAME\fR + +Specifies the name of file with the list of node pairs, separated by a colon. + +.TP 10 +ldr + +Specifies the ports with a non-zero link down reason or neighbor link down reason. + +.TP 10 +ldr:\fIvalue\fR + +Specifies the ports with a link down reason or neighbor link down reason equal to \fIvalue\fR. + + +.PP +The portion of the script that calls opareport and opaxmlextract follows: +.PP + +.br +opareport -x -d 10 -s -o errors -T $@ | opaxmlextract -d \; +.br + +-e Rate -e MTU -e LinkDetails -e CableLength -e CableLabel +.br + +-e CableDetails -e Port.NodeDesc -e Port.PortNum -e SymbolErrors.Value + +.br + +.SH Examples +opaextractstat topology\(ulfile +.br + +opaextractstat topology\(ulfile -c my\(ulopamon.conf diff --git a/IbaTools/man/opaextractstat2.manPage b/IbaTools/man/opaextractstat2.manPage new file mode 100644 index 0000000..bbae570 --- /dev/null +++ b/IbaTools/man/opaextractstat2.manPage @@ -0,0 +1,481 @@ +.\" .\" ********************************************************************* +.\" .\" * * +.\" .\" * Copyright 2015-2019, Intel Corporation * +.\" .\" * * +.\" .\" * All Rights Reserved. * +.\" .\" * * +.\" .\" ********************************************************************* + +.TH opaextractstat2 8 "Intel Corporation" "Copyright(C) 2015\-2019" "IFSFFCLIRG (Man Page)" +.SH NAME +opaextractstat2 + + +.PP +Performs an error analysis of a fabric and provides augmented information from a topology\(ulfile including all error counters. The output is in a CSV format suitable for importing into a spreadsheet or parsed by other scripts. opaextractstat2 is a front end to the opareport and opaxmlextract tools. +.SH Syntax +opaextractstat2 topology\(ulfile [opareport \fIoptions\fR] +.SH Options + +.TP 10 +--help + +Produces full help text. + +.TP 10 +topology\(ulfile + +Specifies topology\(ulfile to use. + +.TP 10 +opareport \fIoptions\fR + +The following options are passed to opareport. This subset is considered typical and useful for this command. By design, the tool ignores -o/--output report option. + +.RS +.TP 10 + +.sp +-h/--hfi \fIhfi\fR +Specifies the HFI, numbered 1..n. Using 0 specifies that the -p \fIport\fR port is a system-wide port number. Default is 0. + +.RE + +.RS +.TP 10 + +.sp +-p/--port \fIport\fR +Specifies the port, numbered 1..n. Using 0 specifies the first active port. Default is 0. + +.RE + +.RS +.TP 10 + +.sp +-X/--infile \fIsnapshot\(ulinput\fR +Generates a report using the data in the snapshot\(ulinput file. snapshot\(ulinput must have been generated during a previous -o \fIsnapshot\fR run. When used, the -s, -i, -C, and -a options are ignored. \[aq]-\[aq] may be used as the snapshot\(ulinput to specify stdin. + +.RE + +.RS +.TP 10 + +.sp +-i/--interval \fIseconds\fR +Obtains performance statistics over interval \fIseconds\fR. Clears all statistics, waits interval \fIseconds\fR, then generates report. Implies -s option. + +.RE + +.RS +.TP 10 + +.sp +-b / --begin \fIdate\(ultime\fR +Obtains past performance stats over an interval beginning at \fIdate\(ultime\fR. Implies -s option. \fIdate\(ultime\fR may be a time entered as HH:MM[:SS] or date as mm/dd/YYYY, dd.mm.YYYY, YYYY-mm-dd or date followed by time; for example, "2016-07-04 14:40". Relative times are taken as "x [second|minute|hour|day](s) ago. + +.RE + +.RS +.TP 10 + +.sp +-e / --end \fIdate\(ultime\fR +Obtains past performance stats over an interval ending at \fIdate\(ultime\fR. Implies -s option. + +.IP +\fIdate\(ultime\fR may be a time entered as HH:MM[:SS] or date as mm/dd/YYYY, dd.mm.YYYY, YYYY-mm-dd or date followed by time; for example, "2016-07-04 14:40". Relative times are taken as "x [second|minute|hour|day](s) ago. +.RE + +.RS +.TP 10 + +.sp +-C/--clear +Clears performance statistics for all ports. Only statistics with error thresholds are cleared. A clear occurs after generating the report. + +.RE + +.RS +.TP 10 + +.sp +-a/--clearall +Clears all performance statistics for all ports. + +.RE + +.RS +.TP 10 + +.sp +-M/--pmadirect +Accesses performance statistics using direct PMA. + +.RE + +.RS +.TP 10 + +.sp +-A/--allports +Gets PortInfo for down switch ports. Uses direct SMA to get this data. If used with -M, also gets PMA stats for down switch ports. + +.RE + +.RS +.TP 10 + +.sp +-c/--config \fIfile\fR +Specifies the error thresholds configuration file. Default is /etc/opa/opamon.conf file. + +.RE + +.RS +.TP 10 + +.sp +-L/--limit +Limits operation to exact specified focus with -F for port error counters check (-o \fIerrors\fR) and port counters clear (-C or -i). Normally, the neighbor of each selected port is also checked/cleared. Does not affect other reports. + +.RE + +.RS +.TP 10 + +.sp +-F/--focus \fIpoint\fR +Specifies the focus area for report. Used for all reports except route to limit scope of report. Refer to +\fIPoint Syntax\fR +for details. + +.RE + + +.SH -h and -p options permit a variety of selections: + +.TP 10 +-h 0 + +First active port in system (Default). + +.TP 10 +-h 0 -p 0 + +First active port in system. + +.TP 10 +-h \fIx\fR + +First active port on HFI \fIx\fR. + +.TP 10 +-h \fIx\fR \fI\fR-p 0 + +First active port on HFI \fIx\fR. + +.TP 10 +-h 0 -p \fIy\fR + +Port \fIy\fR within system (no matter which ports are active). + +.TP 10 +-h \fIx\fR \fI\fR-p \fIy\fR + +HFI \fIx\fR, port \fIy\fR. + + +.SH Point Syntax + +.TP 10 +gid:\fIvalue\fR + +\fIvalue\fR is numeric port GID of form: subnet:guid. + +.TP 10 +lid:\fIvalue\fR + +\fIvalue\fR is numeric LID. + +.TP 10 +lid:value:node + +\fIvalue\fR is numeric LID, selects entire node with given LID. + +.TP 10 +lid:\fIvalue\fR:port:\fIvalue2\fR + +\fIvalue\fR is numeric LID of node, \fIvalue2\fR is port number. + +.TP 10 +portguid:\fIvalue\fR + +\fIvalue\fR is numeric port GUID. + +.TP 10 +nodeguid:\fIvalue\fR + +\fIvalue\fR is numeric node GUID. + +.TP 10 +nodeguid:\fIvalue1\fR:port:\fIvalue2\fR + +\fIvalue1\fR is numeric node GUID, \fIvalue2\fR is port number. + +.TP 10 +iocguid:\fIvalue\fR + +\fIvalue\fR is numeric IOC GUID. + +.TP 10 +iocguid:\fIvalue1\fR:port:\fIvalue2\fR + +\fIvalue1\fR is numeric IOC GUID, \fIvalue2\fR is port number. + +.TP 10 +systemguid:\fIvalue\fR + +\fIvalue\fR is numeric system image GUID. + +.TP 10 +systemguid:\fIvalue1\fR:port:\fIvalue2\fR + +\fIvalue1\fR is the numeric system image GUID, \fIvalue2\fR is port number. + +.TP 10 +ioc:\fIvalue\fR + +\fIvalue\fR is IOC Profile ID String (IOC Name). + +.TP 10 +ioc:\fIvalue1\fR:port:\fIvalue2\fR + +\fIvalue1\fR is IOC Profile ID String (IOC Name), \fIvalue2\fR is port number. + +.TP 10 +iocpat:\fIvalue\fR + +\fIvalue\fR is glob pattern for IOC Profile ID String (IOC Name). + +.TP 10 +iocpat:\fIvalue1\fR:port:\fIvalue2\fR + +\fIvalue1\fR is glob pattern for IOC Profile ID String (IOC Name), \fIvalue2\fR is port number. + +.TP 10 +ioctype:\fIvalue\fR + +\fIvalue\fR is IOC type (SRP or OTHER). + +.TP 10 +ioctype:\fIvalue1\fR:port:\fIvalue2\fR + +\fIvalue1\fR is IOC type (SRP or OTHER); \fIvalue2\fR is port number. + +.TP 10 +node:\fIvalue\fR + +\fIvalue\fR is node description (node name). + +.TP 10 +node:\fIvalue1\fR:port:\fIvalue2\fR + +\fIvalue1\fR is node description (node name), \fIvalue2\fR is port number. + +.TP 10 +nodepat:\fIvalue\fR + +\fIvalue\fR is glob pattern for node description (node name). + +.TP 10 +nodepat:\fIvalue1\fR:port:\fIvalue2\fR + +\fIvalue1\fR is the glob pattern for the node description (node name), \fIvalue2\fR is port number. + +.TP 10 +nodedetpat:\fIvalue\fR + +\fIvalue\fR is glob pattern for node details. + +.TP 10 +nodedetpat:\fIvalue1\fR:port:\fIvalue2\fR + +\fIvalue1\fR is the glob pattern for the node details, \fIvalue2\fR is port number. + +.TP 10 +nodetype:\fIvalue\fR + +\fIvalue\fR is node type (SW or FI). + +.TP 10 +nodetype:\fIvalue1\fR:port:\fIvalue2\fR + +\fIvalue1\fR is node type (SW or FI), \fIvalue2\fR is port number. + +.TP 10 +rate:\fIvalue\fR + +\fIvalue\fR is string for rate (25g, 50g, 75g, 100g), omits switch mgmt port 0. + +.TP 10 +portstate:\fIvalue\fR + +\fIvalue\fR is a string for state (down, init, armed, active, notactive, initarmed). + +.TP 10 +portphysstate:\fIvalue\fR + +\fIvalue\fR is a string for PHYs state (polling, disabled, training, linkup, recovery, offline, test) + +.TP 10 +mtucap:\fIvalue\fR + +\fIvalue\fR is MTU size (2048, 4096, 8192, 10240), omits switch mgmt port 0. + +.TP 10 +labelpat:\fIvalue\fR + +\fIvalue\fR is glob pattern for cable label. + +.TP 10 +lengthpat:\fIvalue\fR + +\fIvalue\fR is glob pattern for cable length. + +.TP 10 +cabledetpat:\fIvalue\fR + +\fIvalue\fR is glob pattern for cable details. + +.TP 10 +cabinflenpat:\fIvalue\fR + +\fIvalue\fR is glob pattern for cable info length. + +.TP 10 +cabinfvendnamepat:\fIvalue\fR + +\fIvalue\fR is glob pattern for cable info vendor name. + +.TP 10 +cabinfvendpnpat:\fIvalue\fR + +\fIvalue\fR is glob pattern for cable info vendor part number. + +.TP 10 +cabinfvendrevpat:\fIvalue\fR + +\fIvalue\fR is glob pattern for cable info vendor revision. + +.TP 10 +cabinfvendsnpat:\fIvalue\fR + +\fIvalue\fR is glob pattern for cable info vendor serial number. + +.TP 10 +cabinftype:\fIvalue\fR + +\fIvalue\fR is either optical, passive\(ulcopper, active\(ulcopper, or unknown. + +.TP 10 +linkdetpat:\fIvalue\fR + +\fIvalue\fR is glob pattern for link details. + +.TP 10 +portdetpat:\fIvalue\fR + +\fIvalue\fR is glob pattern for port details. + +.TP 10 +sm + +Specifies the master subnet manager (SM). + +.TP 10 +smdetpat:\fIvalue\fR + +\fIvalue\fR is glob pattern for SM details. + +.TP 10 +route:\fIpoint1\fR:\fIpoint2\fR + +Specifies all ports along the routes between the two given points. + +.TP 10 +led:\fIvalue\fR + +\fIvalue\fR is either on or off for LED port beacon. + +.TP 10 +linkqual:\fIvalue\fR + +Specifies the ports with a link quality equal to \fIvalue\fR. + +.TP 10 +linkqualLE:\fIvalue\fR + +Specifies the ports with a link quality less than or equal to \fIvalue\fR. + +.TP 10 +linkqualGE:\fIvalue\fR + +Specifies the ports with a link quality greater than or equal to \fIvalue\fR. + +.TP 10 +nodepatfile:\fIFILENAME\fR + +Specifies the name of file with the list of nodepats or node descriptions. + +.TP 10 +nodepairpatfile:\fIFILENAME\fR + +Specifies the name of file with the list of node pairs, separated by a colon. + +.TP 10 +ldr + +Specifies the ports with a non-zero link down reason or neighbor link down reason. + +.TP 10 +ldr:\fIvalue\fR + +Specifies the ports with a link down reason or neighbor link down reason equal to \fIvalue\fR. + + +.PP +The portion of the script that calls opareport and opaxmlextract follows:opareport -x -d 10 -s -o errors -T $@ | opaxmlextract -d \; +.br + +-e Rate -e MTU -e Internal -e LinkDetails -e CableLength -e CableLabel +.br + +-e CableDetails -e Port.NodeGUID -e Port.PortGUID -e Port.PortNum +.br + +-e Port.PortType -e Port.NodeDesc -e Port.PortDetails +.br + +-e PortXmitData.Value -e PortXmitPkts.Value -e PortRcvData.Value +.br + +-e PortRcvPkts.Value -e SymbolErrors.Value -e LinkErrorRecovery.Value +.br + +-e LinkDowned.Value -e PortRcvErrors.Value +.br + +-e PortRcvRemotePhysicalErrors.Value -e PortRcvSwitchRelayErrors.Value +.br + +-e PortXmitConstraintErrors.Value -e PortRcvConstraintErrors.Value +.br + +-e LocalLinkIntegrityErrors.Value -e ExcessiveBufferOverrunErrors.Value +.SH Examples +opaextractstat2 topology\(ulfile +.br + +opaextractstat2 topology\(ulfile -c my\(ulopamon.conf diff --git a/IbaTools/man/opafabricanalysis.manPage b/IbaTools/man/opafabricanalysis.manPage new file mode 100644 index 0000000..629e245 --- /dev/null +++ b/IbaTools/man/opafabricanalysis.manPage @@ -0,0 +1,316 @@ +.\" .\" ********************************************************************* +.\" .\" * * +.\" .\" * Copyright 2015-2019, Intel Corporation * +.\" .\" * * +.\" .\" * All Rights Reserved. * +.\" .\" * * +.\" .\" ********************************************************************* + +.TH opafabricanalysis 8 "Intel Corporation" "Copyright(C) 2015\-2019" "IFSFFCLIRG (Man Page)" +.SH NAME +opafabricanalysis + + +.PP + +\fB(All)\fR +Performs analysis of the fabric. +.SH Syntax +opafabricanalysis [-b|-e] [-s] [-d \fIdir\fR] [-c \fIfile\fR] [-t \fIportsfile\fR] +.br +[-p \fIports\fR] +[-T \fItopology\(ulinput\fR] +.SH Options + +.TP 10 +--help + +Produces full help text. +.TP 10 +-b + +Specifies the baseline mode. Default is compare/check mode. +.TP 10 +-e + +Evaluates health only. Default is compare/check mode. +.TP 10 +-s + +Saves history of failures (errors/differences). +.TP 10 +-d dir + +Specifies the top-level directory for saving baseline and history of failed checks. Default is /var/usr/lib/opa/analysis +.TP 10 +-c file + +Specifies the error thresholds config file.Default is /etc/opa/opamon.conf +.TP 10 +-t portsfile + +Specifies the file with list of local HFI ports used to access fabric(s) for analysis. Default is /etc/opa/ports +.TP 10 +-p ports + +Specifies the list of local HFI ports used to access fabrics for analysis. + +.IP +Default is first active port. The first HFI in the system is 1. The first port on an HFI is 1. Uses the format hfi:port, +.br +for example: +.RS +.TP 10 + +.sp +0:0 +First active port in system. + +.RE + +.RS +.TP 10 + +.sp +0:y +Port \fIy\fR within system. + +.RE + +.RS +.TP 10 + +.sp +x:0 +First active port on HFI \fIx\fR. + +.RE + +.RS +.TP 10 + +.sp +x:y +HFI \fIx\fR, port \fIy\fR. + +.RE + +.TP 10 +-T \fItopology\(ulinput\fR + +Specifies the name of topology input file to use. Any %P markers in this filename are replaced with the HFI:port being operated on (such as 0:0 or 1:2). Default is /etc/opa/topology.%P.xml. If -T NONE is specified, no topology input file is used. See +\fIDetails\fR +and +\fIopareport\fR +for more information. +.SH Example +opafabricanalysis +.br + +opafabricanalysis -p \[aq]1:1 1:2 2:1 2:2\[aq] +.PP +The fabric analysis tool checks the following: +.IP \(bu +Fabric links (both internal to switch chassis and external cables) +.IP \(bu +Fabric components (nodes, links, SMs, systems, and their SMA configuration) +.IP \(bu +Fabric PMA error counters and link speed mismatches +.PP + +.B NOTE: +The comparison includes components on the fabric. Therefore, operations such as shutting down a server cause the server to no longer appear on the fabric and are flagged as a fabric change or failure by opafabricanalysis. + +.SH Environment Variables + +.PP +The following environment variables are also used by this command: +.TP 10 +\fBPORTS\fR + +List of ports, used in absence of -t and -p. +.TP 10 +\fBPORTS\(ulFILE\fR + +File containing list of ports, used in absence of -t and -p. +.TP 10 +\fBFF\(ulTOPOLOGY\(ulFILE\fR + +File containing topology\(ulinput (may have %P marker in filename), used in absence of -T. +.TP 10 +\fBFF\(ulANALYSIS\(ulDIR\fR + +Top-level directory for baselines and failed health checks. +.SH Details + +.PP +For simple fabrics, the Intel(R) Omni-Path Fabric Suite FastFabric Toolset host is connected to a single fabric. By default, the first active port on the FastFabric Toolset host is used to analyze the fabric. However, in more complex fabrics, the FastFabric Toolset host may be connected to more than one fabric or subnet. In this case, you can specify the ports or HFIs to use with one of the following methods: +.IP \(bu +On the command line using the -p option. +.IP \(bu +In a file specified using the -t option. +.IP \(bu +Through the environment variables \fBPORTS\fR or \fBPORTS\(ulFILE\fR. +.IP \(bu +Using the \fBPORTS\(ulFILE\fR configuration option in opafastfabric.conf. +.PP +If the specified port does not exist or is empty, the first active port on the local system is used. In more complex configurations, you must specify the exact ports to use for all fabrics to be analyzed. +.PP +You can specify the topology\(ulinput file to be used with one of the following methods: +.IP \(bu +On the command line using the -T option. +.IP \(bu +In a file specified through the environment variable \fBFF\(ulTOPOLOGY\(ulFILE\fR. +.IP \(bu +Using the ff\(ultopology\(ulfile configuration option in opafastfabric.conf. +.PP +If the specified file does not exist, no topology\(ulinput file is used. Alternately the filename can be specified as NONE to prevent use of an input file. +.PP +For more information on topology\(ulinput, refer to +\fIopareport\fR +. +.PP +By default, the error analysis includes PMA counters and slow links (that is, links running below enabled speeds). You can change this using the \fBFF\(ulFABRIC\(ulHEALTH\fR configuration parameter in opafastfabric.conf. This parameter specifies the opareport options and reports to be used for the health analysis. It also can specify the PMA counter clearing behavior (-I \fIseconds\fR, -C, or none at all). +.PP +When a topology\(ulinput file is used, it can also be useful to extend \fBFF\(ulFABRIC\(ulHEALTH\fR to include fabric topology verification options such as -o verifylinks. +.PP +The thresholds for PMA counter analysis default to /etc/opa/opamon.conf. However, you can specify an alternate configuration file for thresholds using the -c option. The opamon.si.conf file can also be used to check for any non-zero values for signal integrity (SI) counters. +.PP +All files generated by opafabricanalysis start with fabric in their file name. This is followed by the port selection option identifying the port used for the analysis. Default is 0:0. +.PP +The opafabricanalysis tool generates files such as the following within FF\(ulANALYSIS\(ulDIR : +.PP + +\fBHealth Check\fR + +.IP \(bu +latest/fabric.0:0.errors stdout of opareport for errors encountered during fabric error analysis. + +.IP \(bu +latest/fabric.0.0.errors.stderr stderr of opareport during fabric error analysis. + +.PP + +\fBBaseline\fR + +.PP +During a baseline run, the following files are also created in FF\(ulANALYSIS\(ulDIR/latest. +.IP \(bu +baseline/fabric.0:0.snapshot.xml opareport snapshot of complete fabric components and SMA configuration. + +.IP \(bu +baseline/fabric.0:0.comps opareport summary of fabric components and basic SMA configuration. + +.IP \(bu +baseline/fabric.0.0.links opareport summary of internal and external links. + +.PP + +\fBFull Analysis\fR + +.IP \(bu +latest/fabric.0:0.snapshot.xml opareport snapshot of complete fabric components and SMA configuration. + +.IP \(bu +latest/fabric.0:0.snapshot.stderr stderr of opareport during snapshot. + +.IP \(bu +latest/fabric.0:0.errors stdout of opareport for errors encountered during fabric error analysis. + +.IP \(bu +latest/fabric.0.0.errors.stderr stderr of opareport during fabric error analysis. + +.IP \(bu +latest/fabric.0:0.comps stdout of opareport for fabric components and SMA configuration. + +.IP \(bu +latest/fabric.0:0.comps.stderr stderr of opareport for fabric components. + +.IP \(bu +latest/fabric.0:0.comps.diff diff of baseline and latest fabric components. + +.IP \(bu +latest/fabric.0:0.links stdout of opareport summary of internal and external links. + +.IP \(bu +latest/fabric.0:0.links.stderr stderr of opareport summary of internal and external links. + +.IP \(bu +latest/fabric.0:0.links.diff diff of baseline and latest fabric internal and external links. + +.IP \(bu +latest/fabric.0:0.links.changes.stderr stderr of opareport comparison of links. + +.IP \(bu +latest/fabric.0:0.links.changes opareport comparison of links against baseline. This is typically easier to read than the links.diff file and contains the same information. + +.IP \(bu +latest/fabric.0:0.comps.changes.stderr stderr of opareport comparison of components. + +.IP \(bu +latest/fabric.0:0.comps.changes opareport comparison of components against baseline. This is typically easier to read than the comps.diff file and contains the same information. + +.PP +The .diff and .changes files are only created if differences are detected. +.PP +If the -s option is used and failures are detected, files related to the checks that failed are also copied to the time-stamped directory name under FF\(ulANALYSIS\(ulDIR. +.SH Fabric Items Checked Against the Baseline + +.PP +Based on opareport -o links: +.IP \(bu +Unconnected/down/missing cables +.IP \(bu +Added/moved cables +.IP \(bu +Changes in link width and speed +.IP \(bu +Changes to Node GUIDs in fabric (replacement of HFI or Switch hardware) +.IP \(bu +Adding/Removing Nodes [FI, Virtual FIs, Virtual Switches, Physical Switches, Physical Switch internal switching cards (leaf/spine)] +.IP \(bu +Changes to server or switch names +.PP +Based on opareport -o comps: +.IP \(bu +Overlap with items from links report +.IP \(bu +Changes in port MTU, LMC, number of VLs +.IP \(bu +Changes in port speed/width enabled or supported +.IP \(bu +Changes in HFI or switch device IDs/revisions/VendorID (for example, ASIC hardware changes) +.IP \(bu +Changes in port Capability mask (which features/agents run on port/server) +.IP \(bu +Changes to ErrorLimits and PKey enforcement per port +.IP \(bu +Changes to IOUs/IOCs/IOC Services provided + + +.PP +Location (port, node) and number of SMs in fabric. Includes: +.IP \(bu +Primary and backups +.IP \(bu +Configured priority for SM +.SH Fabric Items Also Checked During Health Check + +.PP +Based on opareport -s -C -o errors -o slowlinks: +.IP \(bu +PMA error counters on all Intel(R) Omni-Path Fabric ports (HFI, switch external and switch internal) checked against configurable thresholds. +.IP \(bu +Counters are cleared each time a health check is run. Each health check reflects a counter delta since last health check. +.IP \(bu +Typically identifies potential fabric errors, such as symbol errors. +.IP \(bu +May also identify transient congestion, depending on the counters that are monitored. +.IP \(bu +Link active speed/width as compared to Enabled speed. +.IP \(bu +Identifies links whose active speed/width is < min (enabled speed/width on each side of link). +.IP \(bu +This typically reflects bad cables or bad ports or poor connections. +.IP \(bu +Side effect is the verification of SA health. diff --git a/IbaTools/man/opafabricinfo.manPage b/IbaTools/man/opafabricinfo.manPage new file mode 100644 index 0000000..bb4f12f --- /dev/null +++ b/IbaTools/man/opafabricinfo.manPage @@ -0,0 +1,198 @@ +.\" .\" ********************************************************************* +.\" .\" * * +.\" .\" * Copyright 2015-2019, Intel Corporation * +.\" .\" * * +.\" .\" * All Rights Reserved. * +.\" .\" * * +.\" .\" ********************************************************************* + +.TH opafabricinfo 1 "Intel Corporation" "Copyright(C) 2015\-2019" "IFSFFCLIRG (Man Page)" +.SH NAME +opafabricinfo + + +.PP +Provides a brief summary of the components in the fabric, using the first active port on the given local host to perform its analysis. opafabricinfo is supplied in both: +.IP \(bu +Intel(R) Omni-Path Fabric Suite FastFabric Toolset +In this situation, the command can manage more than one fabric (subnet). + +.IP \(bu +FastFabric Tools +In this situation, the command performs analysis against the first active port on the system only. It takes no options and uses no environment variables. + +.PP +opafabricinfo can be very useful as a quick assessment of the fabric state. It can be run against a known good fabric to identify its components and then later run to see if anything has changed about the fabric configuration or state. +.PP +For more extensive fabric analysis, use opareport, opareports, and opatop. These tools can be found in the +\fIIntel(R) Omni-Path Fabric Suite FastFabric User Guide\fR + +. +.SH Syntax +opafabricinfo [-t \fIportsfile\fR] [-p \fIports\fR] +.SH Options + +.TP 10 +--help + +Produces full help text. +.TP 10 +-t \fIportsfile\fR + +Specifies the file with list of local HFI ports used to access fabric(s) for analysis. Default is /etc/opa/ports file. +.TP 10 +-p \fIports\fR + +Specifies the list of local HFI ports used to access fabrics for analysis. + +.IP +Default is first active port. The first HFI in the system is 1. The first port on an HFI is 1. Uses the format hfi:port, +.br +for example: +.RS +.TP 10 + +.sp +0:0 +First active port in system. + +.RE + +.RS +.TP 10 + +.sp +0:y +Port \fIy\fR within system. + +.RE + +.RS +.TP 10 + +.sp +x:0 +First active port on HFI \fIx\fR. + +.RE + +.RS +.TP 10 + +.sp +x:y +HFI \fIx\fR, port \fIy\fR. + +.RE + +.SH Environment Variables + +.PP +The following environment variables are also used by this command: +.TP 10 +\fBPORTS\fR + +List of ports, used in absence of -t and -p. +.TP 10 +\fBPORTS\(ulFILE\fR + +File containing list of ports, used in absence of -t and -p. + +.IP +For simple fabrics, the Intel(R) Omni-Path Fabric Suite FastFabric Toolset host is connected to a single fabric. By default, the first active port on the FastFabric Toolset host is used to analyze the fabric. However, in more complex fabrics, the FastFabric Toolset host may be connected to more than one fabric or subnet. In this case, you can specify the ports or HFIs to use with one of the following methods: +.RS + +.IP \(bu +On the command line using the -p option. +.IP \(bu +In a file specified using the -t option. +.IP \(bu +Through the environment variables \fBPORTS\fR or \fBPORTS\(ulFILE\fR. +.IP \(bu +Using the ports\(ulfile configuration option in opafastfabric.conf. + +.RE + +.IP +If the specified port does not exist or is empty, the first active port on the local system is used. In more complex configurations, you must specify the exact ports to use for all fabrics to be analyzed. +.SH Example +opafabricinfo +.br + +opafabricinfo -p \[aq]1:1 1:2 2:1 2:2\[aq] +.PP + +\fBOutput example\fR + +.br +# opafabricinfo +.br + +Fabric 0:0 Information: +.br + +SM: hds1fnb6241 hfi1\(ul0 Guid: 0x0011750101575ffe State: Master +.br + +Number of HFIs: 8 +.br + +Number of Switches: 1 +.br + +Number of Links: 8 +.br + +Number of HFI Links: 8 (Internal: 0 External: 8) +.br + +Number of ISLs: 0 (Internal: 0 External: 0) +.br + +Number of Degraded Links: 0 (HFI Links: 0 ISLs: 0) +.br + +Number of Omitted Links: 0 (HFI Links: 0 ISLs: 0) +.SH Output Definitions + +.TP 10 +SM + +Each subnet manger (SM) running in the fabric is listed along with its node name, port GUID, and present SM state (Master, Standby, etc.). +.TP 10 +Number of HFIs + +Number of unique host fabric interfaces (HFIs) in the fabric. An FI with two connected ports is counted as a single FI. +.TP 10 +.BR + +.PP + +.B NOTE: +Fabric Interfaces include HFIs in servers as well as HFIs within I/O Modules, Native Storage, etc. + + +.TP 10 +Number of Switches + +Number of connected switches in the fabric. +.TP 10 +Number of Links + +Number of links in the fabric. Note that a large switch may have internal links. +.TP 10 +Number of HFI Links + +Number of HFI links (Internal and External) in the fabric. +.TP 10 +Number of ISLs + +Number of Interswitch Links (Internal and External) in the fabric. +.TP 10 +Number of Degraded Links + +Number of degraded links (HSI and ISL) in the fabric. +.TP 10 +Number of Omitted Links + +Number of omitted links (HSI and ISL) in the fabric. diff --git a/IbaTools/man/opafastfabric.manPage b/IbaTools/man/opafastfabric.manPage new file mode 100644 index 0000000..2b185fa --- /dev/null +++ b/IbaTools/man/opafastfabric.manPage @@ -0,0 +1,60 @@ +.\" .\" ********************************************************************* +.\" .\" * * +.\" .\" * Copyright 2015-2019, Intel Corporation * +.\" .\" * * +.\" .\" * All Rights Reserved. * +.\" .\" * * +.\" .\" ********************************************************************* + +.TH opafastfabric 8 "Intel Corporation" "Copyright(C) 2015\-2019" "IFSFFCLIRG (Man Page)" +.SH NAME +opafastfabric + + +.PP + +\fB(Switch and Host)\fR +Starts the top-level Intel(R) Omni-Path Fabric Suite FastFabric Text-based User Interface (TUI) menu to enable setup and configuration. +.PP +Refer to the +\fIIntel(R) Omni-Path Fabric Suite FastFabric User Guide\fR + +for details on this tool. +.SH Syntax +opafastfabric +.SH Options + +.PP +None. +.SH Example +#opafastfabric +.br + + Intel FastFabric OPA Tools +.br + + Version: \fIX.X.X.X.X\fR +.br + + +.br + + 1) Chassis Setup/Admin +.br + + 2) Externally Managed Switch Setup/Admin +.br + + 3) Host Setup +.br + + 4) Host Verification/Admin +.br + + 5) Fabric Monitoring +.br + + +.br + + X) Exit (or Q) diff --git a/IbaTools/man/opafindgood.manPage b/IbaTools/man/opafindgood.manPage new file mode 100644 index 0000000..fc36398 --- /dev/null +++ b/IbaTools/man/opafindgood.manPage @@ -0,0 +1,212 @@ +.\" .\" ********************************************************************* +.\" .\" * * +.\" .\" * Copyright 2015-2019, Intel Corporation * +.\" .\" * * +.\" .\" * All Rights Reserved. * +.\" .\" * * +.\" .\" ********************************************************************* + +.TH opafindgood 8 "Intel Corporation" "Copyright(C) 2015\-2019" "IFSFFCLIRG (Man Page)" +.SH NAME +opafindgood + + +.PP +Checks for hosts that are able to be pinged, accessed via SSH, and active on the Intel(R) Omni-Path Fabric. Produces a list of good hosts meeting all criteria. Typically used to identify good hosts to undergo further testing and benchmarking during initial cluster staging and startup. +.PP +The resulting good file lists each good host exactly once and can be used as input to create \fImpi\(ulhosts\fR files for running mpi\(ulapps and the HFI-SW cable test. The files alive, running, active, good, and bad are created in the selected directory listing hosts passing each criteria. +.PP +This command assumes the Node Description for each host is based on the \fIhostname\fR-s output in conjunction with an optional hfi1\(ul# suffix. When using a /etc/opa/hosts file that lists the hostnames, this assumption may not be correct. +.PP +This command automatically generates the file FF\(ulRESULT\(ulDIR/punchlist.csv. This file provides a concise summary of the bad hosts found. This can be imported into Excel directly as a *.csv file. Alternatively, it can be cut/pasted into Excel, and the +\fBData/Text to Columns\fR +toolbar can be used to separate the information into multiple columns at the semicolons. +.PP +A sample generated output is: +.PP + +.br +# opafindgood +.br + +3 hosts will be checked +.br + +2 hosts are pingable (alive) +.br + +2 hosts are ssh\[aq]able (running) +.br + +2 total hosts have FIs active on one or more fabrics (active) +.br + +No Quarantine Node Records Returned +.br + +1 hosts are alive, running, active (good) +.br + +2 hosts are bad (bad) +.br + +Bad hosts have been added to /root/punchlist.csv +.br + +# cat /root/punchlist.csv +.br + +2015/10/04 11:33:22;phs1fnivd13u07n1 hfi1\(ul0 p1 phs1swivd13u06 p16;Link errors +.br + +2015/10/07 10:21:05;phs1swivd13u06;Switch not found in SA DB +.br + +2015/10/09 14:36:48;phs1fnivd13u07n4;Doesn\[aq]t ping +.br + +2015/10/09 14:36:48;phs1fnivd13u07n3;No active port + +.br + +.PP +For a given run, a line is generated for each failing host. Hosts are reported exactly once for a given run. Therefore, a host that does not ping is NOT listed as can\[aq]t ssh nor No active port. There may be cases where ports could be active for hosts that do not ping, especially if Ethernet host names are used for the ping test. However, the lack of ping often implies there are other fundamental issues, such as PXE boot or inability to access DNS or DHCP to get proper host name and IP address. Therefore, reporting hosts that do not ping is typically of limited value. +.PP +Note that opafindgood queries the SA for NodeDescriptions to determine hosts with active ports. As such, ports may be active for hosts that cannot be accessed via SSH or pinged. +.PP +By default, opafindgood checks for and reports nodes that are quarantined for security reasons. To skip this, use the -Q option. +.SH Syntax +opafindgood [-R|-A|-Q] [-d \fIdir\fR] [-f \fIhostfile\fR] [-h \[aq]\fIhosts\fR\[aq]] +.br +[-t \fIportsfile\fR] +[-p \fIports\fR] [-T \fItimelimit\fR] +.SH Options + +.TP 10 +--help + +Produces full help text. +.TP 10 +-R + +Skips the running test (SSH). Recommended if password-less SSH is not set up. +.TP 10 +-A + +Skips the active test. Recommended if Intel(R) Omni-Path Fabric software or fabric is not up. +.TP 10 +-Q + +Skips the quarantine test. Recommended if Intel(R) Omni-Path Fabric software or fabric is not up. +.TP 10 +-d \fIdir\fR + +Specifies the directory in which to create alive, active, running, good, and bad files. Default is /etc/opa directory. +.TP 10 +-f \fIhostfile\fR + +Specifies the file with hosts in cluster. Default is /etc/opa/hosts directory. +.TP 10 +-h \fIhosts\fR + +Specifies the list of hosts to ping. +.TP 10 +-t \fIportsfile\fR + +Specifies the file with list of local HFI ports used to access fabric(s) for analysis. Default is /etc/opa/ports file. +.TP 10 +-p \fIports\fR + +Specifies the list of local HFI ports used to access fabric(s) for analysis. + +.IP +Default is first active port. The first HFI in the system is 1. The first port on an HFI is 1. Uses the format hfi:port, +.br +for example: +.RS +.TP 10 + +.sp +0:0 +First active port in system. + +.RE + +.RS +.TP 10 + +.sp +0:y +Port \fIy\fR within system. + +.RE + +.RS +.TP 10 + +.sp +x:0 +First active port on HFI \fIx\fR. + +.RE + +.RS +.TP 10 + +.sp +x:y +HFI \fIx\fR, port \fIy\fR. + +.RE + +.TP 10 +-T \fItimelimit\fR + +Specifies the time limit in seconds for host to respond to SSH. Default is 20 seconds. + +.SH Environment Variables + +.PP +The following environment variables are also used by this command: +.TP 10 +\fBHOSTS\fR + +List of hosts, used if -h option not supplied. + +.TP 10 +\fBHOSTS\(ulFILE\fR + +File containing list of hosts, used in absence of -f and -h. + +.TP 10 +\fBPORTS\fR + +List of ports, used in absence of -t and -p. + +.TP 10 +\fBPORTS\(ulFILE\fR + +File containing list of ports, used in absence of -t and -p. + +.TP 10 +\fBFF\(ulMAX\(ulPARALLEL\fR + +Maximum concurrent operations. + +.SH Examples +opafindgood +.br + +opafindgood -f allhosts +.br + +opafindgood -h \[aq]arwen elrond\[aq] +.br + +HOSTS=\[aq]arwen elrond\[aq] opafindgood +.br + +HOSTS\(ulFILE=allhosts opafindgood +.br + +opafindgood -p \[aq]1:1 1:2 2:1 2:2\[aq] diff --git a/IbaTools/man/opafirmware.manPage b/IbaTools/man/opafirmware.manPage new file mode 100644 index 0000000..02a7461 --- /dev/null +++ b/IbaTools/man/opafirmware.manPage @@ -0,0 +1,50 @@ +.\" .\" ********************************************************************* +.\" .\" * * +.\" .\" * Copyright 2015-2019, Intel Corporation * +.\" .\" * * +.\" .\" * All Rights Reserved. * +.\" .\" * * +.\" .\" ********************************************************************* + +.TH opafirmware 8 "Intel Corporation" "Copyright(C) 2015\-2019" "IFSFFCLIRG (Man Page)" +.SH NAME +opafirmware + + +.PP +Returns firmware information. +.SH Syntax +opafirmware [--showVersion | --showType] [ \fIfirmwareFile\fR] +.SH Options + +.TP 10 +--help + +Produces full help text. + +.TP 10 +--showVersion + +Specifies the version of the firmware file. + +.TP 10 +--showType + +Specifies the type of the firmware file. + +.TP 10 +\fIfirmwareFile\fR + +Specifies the firmware filename. + +.SH Examples +# opafirmware --showVersion STL1.q7.10.0.0.0.spkg +.br + +10.0.0.0 +.br + +# opafirmware --showType STL1.q7.10.0.0.0.spkg +.br + +Omni\(ulPath\(ulSwitch\(ulProducts.q7 diff --git a/IbaTools/man/opafmconfigcheck.manPage b/IbaTools/man/opafmconfigcheck.manPage new file mode 100644 index 0000000..dcf3a4c --- /dev/null +++ b/IbaTools/man/opafmconfigcheck.manPage @@ -0,0 +1,59 @@ +.\" .\" ********************************************************************* +.\" .\" * * +.\" .\" * Copyright 2015-2019, Intel Corporation * +.\" .\" * * +.\" .\" * All Rights Reserved. * +.\" .\" * * +.\" .\" ********************************************************************* + +.TH opafmconfigcheck 8 "Intel Corporation" "Copyright(C) 2015\-2019" "IFSFFCLIRG (Man Page)" +.SH NAME +opafmconfigcheck + + +.PP +Parses and verifies the configuration file of a Fabric Manager (FM). Displays debugging and status information. +.SH Syntax +opafmconfigcheck [-s] [-c \fIconfig\(ulfile\fR] [-v] [-d] [-r \fIreconfig\(ulfile\fR] +.SH Options + +.TP 10 +--help + +Produces full help text. + +.TP 10 +-s + +Enables strict check mode; validates multicast and VF settings. This option points out inconsistencies or invalid settings in VF and multicast configurations. + +.TP 10 +-c \fIconfig\(ulfile\fR + +Specifies configuration file. +.br +Default is /etc/opa-fm/opafm.xml. + +.TP 10 +-v + +Displays debugging and status information. + +.TP 10 +-d + +Displays configuration checksum information. + +.TP 10 +-r \fIreconfig\(ulfile\fR + +Verifies that the \fIreconfig\(ulfile\fR is valid for dynamical reconfiguration. + +.SH Example +opafmconfigcheck +.br + +opafmconfigcheck -v +.br + +opafmconfigcheck -sv diff --git a/IbaTools/man/opafmconfigdiff.manPage b/IbaTools/man/opafmconfigdiff.manPage new file mode 100644 index 0000000..2504a13 --- /dev/null +++ b/IbaTools/man/opafmconfigdiff.manPage @@ -0,0 +1,54 @@ +.\" .\" ********************************************************************* +.\" .\" * * +.\" .\" * Copyright 2015-2019, Intel Corporation * +.\" .\" * * +.\" .\" * All Rights Reserved. * +.\" .\" * * +.\" .\" ********************************************************************* + +.TH opafmconfigdiff 8 "Intel Corporation" "Copyright(C) 2015\-2019" "IFSFFCLIRG (Man Page)" +.SH NAME +opafmconfigdiff + + +.PP +Performs a file difference between two configuration files corresponding to two FM instances described by \fIfile1\fR and \fIfile2\fR. +.SH Syntax +opafmconfigdiff [-f] [-l] [-d \[aq]\fIdiff\(ulargs\fR\[aq]] \fIfile1 file2\fR +.SH Options + +.TP 10 +--help + +Produces full help text. + +.TP 10 +-f + +Filters out FM parameters that are not part of the consistency check. Removes configuration tags that do not cause consistency checks on the FM to fail from diff. + +.TP 10 +-l + +Includes comments in XML to indicate original line numbers. + +.TP 10 +-d \[aq]\fIdiff\(ulargs\fR\[aq] + +Specifies additional arguments to add to diff command. For example, enter uw for unified format ignoring whitespace. + +.TP 10 +\fIfile1 file2\fR + +Specifies the names of the configuration files to be compared. + +.SH Example +opafmconfigdiff /etc/opa-fm/opafm.xml /usr/share/opa-fm/opafm.xml +.br + +opafmconfigdiff -f /etc/opa-fm/opafm.xml /usr/share/opa-fm/opafm.xml +.br + +opafmconfigdiff -d -uw /etc/opa-fm/opafm.xml /usr/share/opa-fm/ +.br +opafm.xml diff --git a/IbaTools/man/opafmconfigpp.manPage b/IbaTools/man/opafmconfigpp.manPage new file mode 100644 index 0000000..68ab5cf --- /dev/null +++ b/IbaTools/man/opafmconfigpp.manPage @@ -0,0 +1,90 @@ +.\" .\" ********************************************************************* +.\" .\" * * +.\" .\" * Copyright 2015-2019, Intel Corporation * +.\" .\" * * +.\" .\" * All Rights Reserved. * +.\" .\" * * +.\" .\" ********************************************************************* + +.TH opafmconfigpp 8 "Intel Corporation" "Copyright(C) 2015\-2019" "IFSFFCLIRG (Man Page)" +.SH NAME +opafmconfigpp + + +.PP +Merges opafm.xml pre-process file with set of VirtualFabric and DeviceGroup XML files. +.SH Syntax +opafmconfigpp [-p \fIppfile\fR] [-o \fIoutput\fR] [-b] [-s] [-f] [-h] +.SH Options + +.TP 10 +-h + +Produces full help text. + +.TP 10 +-p \fIppfile\fR + +Specifies the file to preprocess. Default is /etc/opa-fm/opafm\(ulpp.xml. + +.TP 10 +-o \fIoutput\fR + +Specifies the output XML file. Default is /etc/opa-fm/opafm.xml. + +.TP 10 +-b + +Backs up the old output file if one exists. Default is 0. + +.TP 10 +-s + +Skips running Config Check on output. Default is 0. + +.TP 10 +-f + +Forces overwrite of old output file. Default is 0. + +.SH Notes + +.PP +The output file will contain two comments at the top, along with the local time it was generated. +.PP +The special INCLUDE comments follow this style: +.PP + +.br + +.br + + + +.br + +.PP +Examples: +.PP + +.br + +.br + + +.br + + +.br + + + +.br + +.PP +INCLUDE comments will be replaced with contents of the given directories. +.SH Example +opafmconfigpp +.br + +opafmconfigpp -b -s diff --git a/IbaTools/man/opagenchassis.manPage b/IbaTools/man/opagenchassis.manPage new file mode 100644 index 0000000..2880783 --- /dev/null +++ b/IbaTools/man/opagenchassis.manPage @@ -0,0 +1,91 @@ +.\" .\" ********************************************************************* +.\" .\" * * +.\" .\" * Copyright 2015-2019, Intel Corporation * +.\" .\" * * +.\" .\" * All Rights Reserved. * +.\" .\" * * +.\" .\" ********************************************************************* + +.TH opagenchassis 8 "Intel Corporation" "Copyright(C) 2015\-2019" "IFSFFCLIRG (Man Page)" +.SH NAME +opagenchassis + + +.PP +Generates a list of IPv4, IPv6, and/or TCP names in a format acceptable for inclusion in the /etc/opa/chassis file. +.SH Syntax +opagenchassis [-t \fIportsfile\fR] [-p \fIports\fR] +.SH Options + +.TP 10 +--help + +Produces full help text. +.TP 10 +-t \fIportsfile\fR + +Specifies the file with list of local HFI ports used to access fabric for analysis. +.br +Default is /etc/opa/ports file. +.TP 10 +-p \fIports\fR + +Specifies the list of local HFI ports used to access fabrics for counter clear. + +.IP +Default is first active port. The first HFI in the system is 1. The first port on an HFI is 1. Uses the format hfi:port, +.br +for example: +.RS +.TP 10 + +.sp +0:0 +First active port in system. + +.RE + +.RS +.TP 10 + +.sp +0:y +Port \fIy\fR within system. + +.RE + +.RS +.TP 10 + +.sp +x:0 +First active port on HFI \fIx\fR. + +.RE + +.RS +.TP 10 + +.sp +x:y +HFI \fIx\fR, port \fIy\fR. + +.RE + +.SH Environment Variables + +.PP +The following environment variables are also used by this command: +.TP 10 +PORTS + +List of ports, used in absence of -t and -p. +.TP 10 +PORTS\(ulFILE + +File containing list of ports, used in absence of -t and -p. +.SH Examples +opagenchassis +.br + +opagenchassis -p \[aq]1:1 1:2 2:1 2:2\[aq] diff --git a/IbaTools/man/opagenesmchassis.manPage b/IbaTools/man/opagenesmchassis.manPage new file mode 100644 index 0000000..a9850d0 --- /dev/null +++ b/IbaTools/man/opagenesmchassis.manPage @@ -0,0 +1,107 @@ +.\" .\" ********************************************************************* +.\" .\" * * +.\" .\" * Copyright 2015-2019, Intel Corporation * +.\" .\" * * +.\" .\" * All Rights Reserved. * +.\" .\" * * +.\" .\" ********************************************************************* + +.TH opagenesmchassis 8 "Intel Corporation" "Copyright(C) 2015\-2019" "IFSFFCLIRG (Man Page)" +.SH NAME +opagenesmchassis + + +.PP +Generates a list of chassis IPv4 and IPv6 addresses and/or TCP names where the Embedded Subnet Manager (ESM) is running, in a format acceptable for inclusion in the /etc/opa/esm\(ulchassis file. This tool uses opagenchassis output to iterate through all the chassis. +.SH Syntax +opagenesmchassis [-u user] [-S] [-t \fIportsfile\fR] [-p \fIports\fR] +.SH Options + +.TP 10 +--help + +Produces full help text. +.TP 10 +-u \fIuser\fR + +Performs command as user. For chassis, the default is admin. +.TP 10 +-S + +Securely prompts for password for user on chassis. +.TP 10 +-t \fIportsfile\fR + +Specifies the file with a list of local HFI ports used to access fabric(s) for analysis. +.br +Default is /etc/opa/ports +.TP 10 +-p \fIports\fR + +Specifies the list of local HFI ports used to access fabrics. + +.IP +Default is first active port. The first HFI in the system is 1. The first port on an HFI is 1. Uses the format hfi:port, +.br +for example: +.RS +.TP 10 + +.sp +0:0 +First active port in system. + +.RE + +.RS +.TP 10 + +.sp +0:y +Port \fIy\fR within system. + +.RE + +.RS +.TP 10 + +.sp +x:0 +First active port on HFI \fIx\fR. + +.RE + +.RS +.TP 10 + +.sp +x:y +HFI \fIx\fR, port \fIy\fR. + +.RE + +.SH Environment Variables + +.PP +The following environment variables are also used by this command: +.TP 10 +\fBFF\(ulCHASSIS\(ulADMIN\(ulPASSWORD\fR + +Password for chassis, used in absence of -S. +.TP 10 +\fBPORTS\fR + +List of ports, used in absence of -t and -p. +.TP 10 +\fBPORTS\(ulFILE\fR + +File containing list of ports, used in absence of -t and -p. +.SH Examples +opagenesmchassis +.br + +opagenesmchassis -S -p \[aq]1:1 1:2 2:1 2:2\[aq] +.PP +Alternatively, while editing the file, use a vi command to include the output such as: +.br +:r! opagenesmchassis diff --git a/IbaTools/man/opagenswitches.manPage b/IbaTools/man/opagenswitches.manPage new file mode 100644 index 0000000..85a3a04 --- /dev/null +++ b/IbaTools/man/opagenswitches.manPage @@ -0,0 +1,192 @@ +.\" .\" ********************************************************************* +.\" .\" * * +.\" .\" * Copyright 2015-2019, Intel Corporation * +.\" .\" * * +.\" .\" * All Rights Reserved. * +.\" .\" * * +.\" .\" ********************************************************************* + +.TH opagenswitches 8 "Intel Corporation" "Copyright(C) 2015\-2019" "IFSFFCLIRG (Man Page)" +.SH NAME +opagenswitches + + +.PP +Analyzes the present fabric and produces a list of Externally Managed switches in the required format for the /etc/opa/switches file. +.SH Syntax +opagenswitches [-t portsfile] [-p ports] [-R] [-L switches\(ulfile] +.br +[-o output\(ulfile] +[-T topology\(ulfile] [-X snapshot\(ulfile] [-s] [-v level] [-K] +.SH Options + +.TP 10 +--help + +Produces full help text. +.TP 10 +-t \fIportsfile\fR + +Specifies the file with list of local HFI ports used to access fabric(s) for analysis. +.br +Default is /etc/opa/ports file. +.TP 10 +-p \fIports\fR + +Specifies the list of local HFI ports used to access fabrics for counter clear. + +.IP +Default is first active port. The first HFI in the system is 1. The first port on an HFI is 1. Uses the format hfi:port, +.br +for example: +.RS +.TP 10 + +.sp +0:0 +First active port in system. + +.RE + +.RS +.TP 10 + +.sp +0:y +Port \fIy\fR within system. + +.RE + +.RS +.TP 10 + +.sp +x:0 +First active port on HFI \fIx\fR. + +.RE + +.RS +.TP 10 + +.sp +x:y +HFI \fIx\fR, port \fIy\fR. + +.RE + +.TP 10 +-R + +Does not attempt to get routes for computation of distance. +.TP 10 +-s + +Updates/resolves switch names using topology XML data. +.TP 10 +-L \fIswitches\(ulfile\fR + +Specifies the name of a pre-existing \fIswitches\(ulfile\fR to be used as input in conjunction with a topology file. When specified, the file is used instead of switches data obtained from the actual fabric. The updated switches data is output to stdout (common to all opagenswitches operations). Does not generate switches data. Must also use -s option. + +.TP 10 +-o \fIoutput\(ulfile\fR + +Writes switches data to \fIoutput\(ulfile\fR. Default is stdout. +.TP 10 +-T \fItopology\(ulfile\fR + +Specifies \fItopology\(ulfile\fR to use. May contain \[aq]%P\[aq] . Must also use -s. + +.IP +Link data in the topology file is compared to actual fabric link data (obtained by opareport -o links or opareport -X snapshot -o links). The data is also matched to a list of switch node GUIDs and the switch NodeDesc values are generated. This list is then applied to the switches data to update NodeDesc values. The comparison of topology link data to actual fabric link data starts with the host names. The host names in the actual fabric must match those in the topology file for the comparison to succeed. However, the comparison logic allows for some mismatches, which could be due to swapped or missing cables. Switch NodeDesc values are matched to GUIDs based on which switch has the greater number of matching links. +.TP 10 +-X \fIsnapshot\(ulfile\fR + +Uses \fIsnapshot\(ulfile\fR XML for fabric link information. +.br +May contain \[aq]%P\[aq] . Must also use -s. +.TP 10 +-v \fIlevel\fR + +Specifies the verbose level. Default is 0. Values include: +.RS +.TP 10 + +.sp +0 +No output. +.RE + +.RS +.TP 10 + +.sp +1 +Progress output. +.RE + +.RS +.TP 10 + +.sp +2 +Reserved. +.RE + +.RS +.TP 10 + +.sp +4 +Time stamps. +.RE + +.RS +.TP 10 + +.sp +8 +Reserved. +.RE + +.TP 10 +-K + +Does not clean temporary files. Temporary files are CSV format and contain lists of links used during script operation. The files are not normally needed after execution, but they can be retained for subsequent inspection or processing. + +.SH Environment Variables + +.PP +The following environment variables are also used by this command: +.TP 10 +\fBPORTS\fR + +List of ports, used in absence of -t and -p. +.TP 10 +\fBPORTS\(ulFILE\fR + +File containing list of ports, used in absence of -t and -p. +.TP 10 +\fBFF\(ulTOPOLOGY\(ulFILE\fR + +File containing topology XML data, used in absence of -T. +.SH Examples +opagenswitches +.br + +opagenswitches -p \[aq]1:1 2:1\[aq] +.br + +opagenswitches -o switches +.br + +opagenswitches -s -o switches +.br + +opagenswitches -L switches -s -o switches +.br + +opagenswitches -s -T topology.%P.xml +.br + +opagenswitches -L switches -s -T topology.%P.xml -X snapshot.%P.xml diff --git a/IbaTools/man/opagentopology.manPage b/IbaTools/man/opagentopology.manPage new file mode 100644 index 0000000..b607e25 --- /dev/null +++ b/IbaTools/man/opagentopology.manPage @@ -0,0 +1,400 @@ +.\" .\" ********************************************************************* +.\" .\" * * +.\" .\" * Copyright 2015-2019, Intel Corporation * +.\" .\" * * +.\" .\" * All Rights Reserved. * +.\" .\" * * +.\" .\" ********************************************************************* + +.TH opagentopology 8 "Intel Corporation" "Copyright(C) 2015\-2019" "IFSFFCLIRG (Man Page)" +.SH NAME +opagentopology + + +.PP +Provides a simple sample of how to generate the topology XML file used for topology verification. Customers who wish to integrate topology XML file generation into their cluster design process can create their own script to take information available in other formats and tools and produce the topology XML file directly. The alternative is to use opaxlattopology and have tools generate the input files it expects. +.PP +This tool uses CSV input files opatopology\(ullinks.txt, opatopology\(ulFIs.txt, and opatopology\(ulSWs.txt to generate LinkSummary, Node FIs, and Node SWs information, respectively. These files are samples of what might be produced as part of translating a user custom file format into temporary intermediate CSV files. +.PP +LinkSummary information includes Link, Cable, and Port information. Note that opagentopology (not opaxmlgenerate) generates the XML version string as well as the and lines. Also note that the indent level is at the default value of zero (0). The portions of the script that call opaxmlgenerate follow: +.PP + +.br +opaxmlgenerate -X /usr/share/opa/samples/opatopology\(ul1.txt -d \; +.br +-h Link +-g Rate -g Rate\(ulInt -g MTU -g LinkDetails -h Cable +.br +-g CableLength -g CableLabel +-g CableDetails -e Cable -h Port +.br +-g NodeGUID -g PortNum -g NodeDesc -g PortGUID + +.br +-g NodeType -g NodeType\(ulInt -g PortDetails -e Port -h Port -g NodeGUID -g PortNum + +.br +-g NodeDesc -g PortGUID -g NodeType -g NodeType\(ulInt -g PortDetails -e Port +.br +-e Link + + +.br + +.br +opaxmlgenerate -X /usr/share/opa/samples/opatopology\(ul2.txt -d \; +.br + +-h Node -g NodeGUID -g NodeDesc -g NodeDetails -g HostName -g NodeType +.br + +-g NodeType\(ulInt -g NumPorts -e Node + +.SH Syntax +/usr/share/opa/samples/opagentopology [--help] +.PP + +.B NOTE: +You must use the full path to access this command. + + +.SH Options + +.TP 10 +No option + +Produces sample output. See +\fIExample\fR +. +.TP 10 +--help + +Produces full help text. + +.SH opatopology\(ullinks.txt + +.PP +This file can be found in /usr/share/opa/samples/. For brevity, this sample shows only two links. The second link shows an example of omitting some information. In the second line, the MTU, LinkDetails, and other fields are not present, which is indicated by an empty value for the field (no entry between the semicolon delimiters). +.PP + +.B NOTE: +The following example exceeds the available width of the page. For readability, a blank line is shown between lines to make it clear where the line ends. In an actual link file, no blank lines are used. + +.PP + +.br +25g;2048;0;IO Server Link;11m;S4567;cable +.br +model 456;0x0002c9020020e004;1;bender HFI-1;0x0002c9020020e004;FI; +.br +Some info about port;0x0011750007000df6;7;Switch 1234 Leaf 4;;SW; +.br + + + +.br + +.br +25g;;0;;;;;0x0002c9020025a678;1;mindy2 HFI-1;;FI;; +.br +0x0011750007000e6d;4;Switch 2345 Leaf 5;;SW; + +.SH opatopology\(ulFIs.txt + +.PP +This file can be found in /usr/share/opa/samples/. For brevity, this sample shows only two nodes. +.PP + +.br +0x0002c9020020e004;bender HFI-1;More details about node +.br + +0x0002c9020025a678;mindy2 HFI-1;Node details + +.br + + +.SH opatopology\(ulSWs.txt + +.PP +This file can be found in /usr/share/opa/samples/. For brevity, this sample shows only two nodes. +.PP + +.br +0x0011750007000df6;Switch 1234 Leaf 4; +0x0011750007000e6d;Switch +.br +2345 Leaf 5; + +.br + + +.SH opatopology\(ulSMs.txt + +.PP +This file can be found in /usr/share/opa/samples/. For brevity, this sample shows only one node. +.PP + +.br +0x0002c9020025a678;1;mindy2 HFI-1;0x0011750007000e6d;FI;details +.br +about SM + +.br + + +.SH Example + +.PP +When run against the supplied topology input files, /usr/share/opa/samples/opagentopology +.br +produces: +.PP + +.br + +.br + + +.br + + +.br + + +.br + +25g +.br + +2048 +.br + +0 +.br + +IO Server Link +.br + + +.br + +11m +.br + +S4567 +.br + +cable model 456 +.br + + +.br + + +.br + +0x0002c9020020e004 +.br + +1 +.br + +bender HFI-1 +.br + +0x0002c9020020e004 +.br + +FI +.br + +Some info about port +.br + + +.br + + +.br + +0x0011750007000df6 +.br + +7 +.br + +Switch 1234 Leaf 4 +.br + +SW +.br + + +.br + + +.br + + +.br + +25g +.br + +0 +.br + + +.br + + +.br + + +.br + +0x0002c9020025a678 +.br + +1 +.br + +mindy2 HFI-1 +.br + +FI +.br + + +.br + + +.br + +0x0011750007000e6d +.br + +4 +.br + +Switch 2345 Leaf 5 +.br + +SW +.br + + +.br + + +.br + + +.br + + +.br + + +.br + + +.br + +0x0002c9020020e004 +.br + +bender HFI-1 +.br + +More details about node +.br + + +.br + + +.br + +0x0002c9020025a678 +.br + +mindy2 HFI-1 +.br + +Node details +.br + + +.br + + +.br + + +.br + + +.br + +0x0011750007000df6 +.br + +Switch 1234 Leaf 4 +.br + + +.br + + +.br + +0x0011750007000e6d +.br + +Switch 2345 Leaf 5 +.br + + +.br + + +.br + + +.br + + +.br + +0x0002c9020025a678 +.br + +1 +.br + +mindy2 HFI-1 +.br + +0x0011750007000e6d +.br + +FI +.br + +details about SM +.br + + +.br + + +.br + + +.br + + + +.br diff --git a/IbaTools/man/opagetvf.manPage b/IbaTools/man/opagetvf.manPage new file mode 100644 index 0000000..baafa26 --- /dev/null +++ b/IbaTools/man/opagetvf.manPage @@ -0,0 +1,94 @@ +.\" .\" ********************************************************************* +.\" .\" * * +.\" .\" * Copyright 2015-2019, Intel Corporation * +.\" .\" * * +.\" .\" * All Rights Reserved. * +.\" .\" * * +.\" .\" ********************************************************************* + +.TH opagetvf 1 "Intel Corporation" "Copyright(C) 2015\-2019" "IFSFFCLIRG (Man Page)" +.SH NAME +opagetvf + + +.PP +Used for scripting application use of vFabrics, such as for mpirun parameters. You can query by VF Name, VF Index, Service ID, MGID, PKey, or SL. Fetches the Virtual Fabric info in a delimited format. Returns exactly one matching VF. When multiple VFs match the query, it prefers non-default VFs in which the calling server is a full member. If multiple choices remain, it returns the one with the lowest VF Index. Uses the same algorithm as the Distributed SA Plug-in (DSAP). +.PP +The tool can be used with additional scripts to help set PKey, SL, MTU, and Rate when running MPI jobs. Internally, this tool is based on the opasaquery -o vfinfocsv command. For more information, see +\fIopasaquery\fR +. +.SH Syntax +opagetvf [-h \fIhfi\fR] [-p \fIport\fR] [-e] [-d \fIvfname\fR | -S \fIserviceId\fR | -m \fImcgid\fR | +.br + +-i \fIvfIndex\fR | -k \fIpkey\fR | -L \fIsl\fR] +.SH Options + +.TP 10 +--help + +Produces full help text. +.TP 10 +-h \fIhfi\fR + +Specifies the HFI to send by. Default is first HFI. +.TP 10 +-p \fIport\fR + +Specifies the port to send by. Default is first active port. +.TP 10 +-e + +Outputs MTU and rate as enum values. +.TP 10 +-d \fIvfname\fR + +Queries by VirtualFabric Name. +.TP 10 +-S \fIserviceId\fR + +Queries by Application ServiceId. +.TP 10 +-m \fIgid\fR + +Queries by Application Multicast GID. +.TP 10 +-i \fIvfindex\fR + +Queries by VirtualFabric Index. +.TP 10 +-k \fIpkey\fR + +Queries by VirtualFabric PKey. +.TP 10 +-L \fISL\fR + +Queries by VirtualFabric SL. +.SH Examples +opagetvf -d \[aq]Compute\[aq] +.br + +opagetvf -h 2 -p 2 -d \[aq]Compute\[aq] +.SH Sample Outputs + +.PP +The output is of the form: name:index:pkey:sl:mtu:rate:optionflag::mcastSl as shown in the following example. +.PP +Option flag (bitmask) values include: +.IP \(bu +0x00 Indicates no bits are set. Specifically, no QoS, no Security, and no flow control disabled (which means flow control is enabled). +.IP \(bu +0x01 Security +.IP \(bu +0x02 QoS +.IP \(bu +0x04 Flow Control Disable +.PP + +.br +# opagetvf -d Default +.br + +Default:0:0xffff:0:unlimited:unlimited:0x0:: + +.br diff --git a/IbaTools/man/opagetvf_env.manPage b/IbaTools/man/opagetvf_env.manPage new file mode 100644 index 0000000..954d410 --- /dev/null +++ b/IbaTools/man/opagetvf_env.manPage @@ -0,0 +1,121 @@ +.\" .\" ********************************************************************* +.\" .\" * * +.\" .\" * Copyright 2015-2019, Intel Corporation * +.\" .\" * * +.\" .\" * All Rights Reserved. * +.\" .\" * * +.\" .\" ********************************************************************* + +.TH opagetvf\(ulenv 1 "Intel Corporation" "Copyright(C) 2015\-2019" "IFSFFCLIRG (Man Page)" +.SH NAME +opagetvf\(ulenv + + +.PP +Provides opagetvf\(ulfunc and opagetvf2\(ulfunc shell functions that query the parameters of a vFabric. Also exports values that indicate the PKEY, SL, MTU, and RATE associated with the vFabric. The typical usage of this tool is to include it in a shell script as:. /usr/sbin/opagetvf\(ulenv +.PP +A usage example is provided in: +.br +/usr/src/opa/mpi\(ulapps/openmpi.params +.PP + +.B NOTE: +opagetvf\(ulfunc and opagetvf2\(ulfunc have a similar usage. The difference is whether the MTU and RATE are returned as absolute values or enum values, respectively. + +.SH Function Syntax +opagetvf\(ulfunc "arguments to opagetvf" \fIpkey\(ulenv\(ulvar\(ulname\fR \fIsl\(ulenv\(ulvar\(ulname\fR +.br + +[ \fImtu\(ulenv\(ulvar\(ulname\fR [ \fIrate\(ulenv\(ulvar\(ulname\fR]] +.PP +or +.PP + +.br +opagetvf2\(ulfunc "arguments to opagetvf" \fIpkey\(ulenv\(ulvar\(ulname\fR +.br +\fIsl\(ulenv\(ulvar\(ulname\fR +[ \fImtu\(ulenv\(ulvar\(ulname\fR [ \fIrate\(ulenv\(ulvar\(ulname\fR]] + +.br + + +.SH Function Options + +.TP 10 +"arguments to opagetvf" + +Specifies a set of arguments to pass to opagetvf to select a virtual fabric.See +\fIopagetvf\fR +for more information. + +.TP 10 +pkey\(ulenv\(ulvar\(ulname + +Specifies the environment variable to fill in with pkey for the selected virtual fabric. The variable given will be exported with the hex numeric value for the pkey.If a variable name of "" is provided, pkey is not saved. + +.TP 10 +sl\(ulenv\(ulvar\(ulname + +Specifies the environment variable to fill in with service level (sl) for the selected virtual fabric. The variable given will be exported with the numeric value for the sl.If a variable name of "" is provided, sl is not saved. + +.TP 10 +mtu\(ulenv\(ulvar\(ulname + +Specifies the environment variable to fill in with maximum MTU for the selected virtual fabric. The variable given will be exported with the value for the MTU.If a variable name of "" is provided, MTU is not saved. + +.IP +For opagetvf\(ulfunc, MTU is returned as an absolute value of 2048, 4096, 8192, or 10240. +.IP +For opagetvf2\(ulfunc, MTU is returned as an enumerated value of 4, 5, 6, or 7 corresponding to the absolute values above, respectively. +.IP +If the selected virtual fabric does not have a limitation specified for MTU, the variable will be unaltered. +.TP 10 +rate\(ulenv\(ulvar\(ulname + +Specifies the environment variable to fill in with maximum static rate for the selected virtual fabric. The variable given will be exported with the value for the rate.If a variable name of "" is provided, rate is not saved. + +.IP +For opagetvf\(ulfunc, rate is returned as an absolute value of 25g, 50g, 75g or 100g. +.IP +For opagetvf2\(ulfunc, rate is returned as an enumerated value of 15, 12, 9, or 16 corresponding to the absolute values above, respectively. +.IP +If the selected virtual fabric does not have a limitation specified for rate, the variable will be unaltered. + +.SH Function Example + +.PP + +.br +. /usr/sbin/opagetvf\(ulenv +.br + + +.br + +# ensure values are empty in case they are not specified for the +.br +virtual fabric +.br + +MTU= +.br + +RATE= +.br + +opagetvf\(ulfunc "-d \[aq]Compute\[aq]" PKEY SERVICE\(ulLEVEL MTU RATE +.br + +echo "The Compute Virtual Fabric has pkey: $PKEY SL:$SERVICE\(ulLEVEL MTU: +.br +$MTU +rate:$RATE" + + +.br + +.PP + +.B NOTE: +Additional examples may be found in /usr/src/opa/mpi\(ulapps/openmpi.params and /usr/src/opa/mpi\(ulapps/mvapich2.params. Those scripts use opagetvf\(ulfunc and opagetvf2\(ulfunc to get virtual fabric parameters and then pass them into openmpi and mvapich2, respectively. diff --git a/IbaTools/man/opahfirev.manPage b/IbaTools/man/opahfirev.manPage new file mode 100644 index 0000000..95fe53a --- /dev/null +++ b/IbaTools/man/opahfirev.manPage @@ -0,0 +1,66 @@ +.\" .\" ********************************************************************* +.\" .\" * * +.\" .\" * Copyright 2015-2019, Intel Corporation * +.\" .\" * * +.\" .\" * All Rights Reserved. * +.\" .\" * * +.\" .\" ********************************************************************* + +.TH opahfirev 1 "Intel Corporation" "Copyright(C) 2015\-2019" "IFSFFCLIRG (Man Page)" +.SH NAME +opahfirev + + +.PP + +\fB(Linux)\fR +Scans the system and reports hardware and firmware information about all the HFIs in the system. +.SH Syntax +opahfirev +.SH Options + +.TP 10 +no option + +Returns information about all of the HFIs in the system. + +.TP 10 +--help + +Produces full help text. + +.SH Example +# opahfirev +.br + +###################### +.br + +phsmpriv07.ph.intel.com - HFI 0000:81:00.0 +.br + +HFI: hfi1\(ul0 +.br + +Board: ChipABI 3.0, ChipRev 7.17, SW Compat 3 +.br + +SN: 0x0063be82 +.br + +Location:Discrete Socket:1 PCISlot:00 NUMANode:1 HFI0 +.br + +Bus: Speed 8GT/s, Width x16 +.br + +GUID: 0011:7501:0163:be82 +.br + +SiRev: B1 (11) +.br + +TMM: 10.4.0.0.146 +.br + +###################### diff --git a/IbaTools/man/opahostadmin.manPage b/IbaTools/man/opahostadmin.manPage new file mode 100644 index 0000000..fc3b73f --- /dev/null +++ b/IbaTools/man/opahostadmin.manPage @@ -0,0 +1,528 @@ +.\" .\" ********************************************************************* +.\" .\" * * +.\" .\" * Copyright 2015-2019, Intel Corporation * +.\" .\" * * +.\" .\" * All Rights Reserved. * +.\" .\" * * +.\" .\" ********************************************************************* + +.TH opahostadmin 8 "Intel Corporation" "Copyright(C) 2015\-2019" "IFSFFCLIRG (Man Page)" +.SH NAME +opahostadmin + + +.PP + +\fB(Host)\fR +Performs a number of multi-step host initialization and verification operations, including upgrading software or firmware, rebooting hosts, and other operations. In general, operations performed by opahostadmin involve a login to one or more host systems. +.SH Syntax +opahostadmin [-c] [-i \fIipoib\(ulsuffix\fR] [-f \fIhostfile\fR] [-h \[aq]\fIhosts\fR\[aq]] +.br +[-r \fIrelease\fR] +[-I \fIinstall\(uloptions\fR] [-U \fIupgrade\(uloptions\fR] [-d \fIdir\fR] +.br +[-T \fIproduct\fR] +[-P \fIpackages\fR] [-m \fInetmask\fR] [-S] \fIoperation\fR ... +.SH Options + +.TP 10 +--help + +Produces full help text. + +.TP 10 +-c + +Overwrites the result files from any previous run before starting this run. + +.TP 10 +-i \fIipoib\(ulsuffix\fR + +Specifies the suffix to apply to host names to create IPoIB host names. Default is -opa. + +.TP 10 +-f \fIhostfile\fR + +Specifies the file with the names of hosts in a cluster. Default is /etc/opa/hosts file. + +.TP 10 +-h \fIhosts\fR + +Specifies the list of hosts to execute the operation against. + +.TP 10 +-r \fIrelease\fR + +Specifies the software version to load/upgrade to. Default is the version of Intel(R) Omni-Path Software presently being run on the server. + +.TP 10 +-d \fIdir\fR + +Specifies the directory to retrieve \fIproduct\fR. \fIrelease\fR.tgz for load or upgrade. + +.TP 10 +-I \fIinstall\(uloptions\fR + +Specifies the software install options. + +.TP 10 +-U \fIupgrade\(uloptions\fR + +Specifies the software upgrade options. + +.TP 10 +-T \fIproduct\fR + +Specifies the product type to install. Default is IntelOPA-Basic. \fI\fR or IntelOPA-IFS. \fI\fR where \fI\fR is the distribution and CPU. + +.TP 10 +-P \fIpackages\fR + +Specifies the packages to install. Default is oftools ipoib psm\(ulmpi + +.TP 10 +-m \fInetmask\fR + +Specifies the IPoIB netmask to use for configipoib operation. + +.TP 10 +-S + +Securely prompts for user password on remote system. + +.TP 10 +\fIoperation\fR + +Performs the specified \fIoperation\fR, which can be one or more of the following: + +.RS +.TP 10 + +.sp +load +Starts initial installation of all hosts. + +.RE + +.RS +.TP 10 + +.sp +upgrade +Upgrades installation of all hosts. + +.RE + +.RS +.TP 10 + +.sp +configipoib +Creates ifcfg-ib1 using host IP address from /etc/hosts file. + +.RE + +.RS +.TP 10 + +.sp +reboot +Reboots hosts, ensures they go down and come back. + +.RE + +.RS +.TP 10 + +.sp +sacache +Confirms sacache has all hosts in it. + +.RE + +.RS +.TP 10 + +.sp +ipoibping +Verifies this host can ping each host through IPoIB. + +.RE + +.RS +.TP 10 + +.sp +mpiperf +Verifies latency and bandwidth for each host. + +.RE + +.RS +.TP 10 + +.sp +mpiperfdeviation +Verifies latency and bandwidth for each host against a defined threshold (or relative to average host performance). + +.RE + +.SH Example +opahostadmin -c reboot +.br + +opahostadmin upgrade +.br + +opahostadmin -h \[aq]elrond arwen\[aq] reboot +.br + +HOSTS=\[aq]elrond arwen\[aq] opahostadmin reboot +.SH Details + +.PP +opahostadmin provides detailed logging of its results. During each run, the following files are produced: +.IP \(bu +test.res : Appended with summary results of run. +.IP \(bu +test.log : Appended with detailed results of run. +.IP \(bu +save\(ultmp/ : Contains a directory per failed test with detailed logs. +.IP \(bu +test\(ultmp*/ : Intermediate result files while test is running. +.PP +The -c option removes all log files. +.PP +Results from opahostadmin are grouped into test suites, test cases, and test items. A given run of opahostadmin represents a single test suite. Within a test suite, multiple test cases occur; typically one test case per host being operated on. Some of the more complex operations may have multiple test items per test case. Each test item represents a major step in the overall test case. +.PP +Each opahostadmin run appends to test.res and test.log, and creates temporary files in test\(ultmp$PID in the current directory. test.res provides an overall summary of operations performed and their results. The same information is also displayed while opahostadmin is executing. test.log contains detailed information about what was performed, including the specific commands executed and the resulting output. The test\(ultmp directories contain temporary files which reflect tests in progress (or killed). The logs for any failures are logged in the save\(ultemp directory with a directory per failed test case. If the same test case fails more than once, save\(ultemp retains the information from the first failure. Subsequent runs of opahostadmin are appended to test.log. Intel recommends reviewing failures and using the -c option to remove old logs before subsequent runs of opahostadmin. +.PP +opahostadmin implicitly performs its operations in parallel. However, as for the other tools, \fBFF\(ulMAX\(ulPARALLEL\fR can be exported to change the degree of parallelism. 1000 parallel operations is the default. +.SH Environment Variables + +.PP +The following environment variables are also used by this command: +.TP 10 +\fBHOSTS\fR + +List of hosts, used if -h option not supplied. + +.TP 10 +\fBHOSTS\(ulFILE\fR + +File containing list of hosts, used in absence of -f and -h. + +.TP 10 +\fBFF\(ulMAX\(ulPARALLEL\fR + +Maximum concurrent operations are performed. + +.TP 10 +\fBFF\(ulSERIALIZE\(ulOUTPUT\fR + +Serialize output of parallel operations (yes or no). + +.TP 10 +\fBFF\(ulTIMEOUT\(ulMULT\fR + +Multiplier for all timeouts associated with this command. Used if the systems are slow for some reason. + + +.SH opahostadmin Operation Details + +.PP + +\fB(Host)\fR +Intel recommends that you set up password SSH or SCP for use during this operation. Alternatively, the -S option can be used to securely prompt for a password, in which case the same password is used for all hosts. Alternately, the password may be put in the environment or the opafastfabric.conf file using \fBFF\(ulPASSWORD\fR and \fBFF\(ulROOTPASS\fR. +.TP 10 +load + +Performs an initial installation of Intel(R) Omni-Path Software on a group of hosts. Any existing installation is uninstalled and existing configuration files are removed. Subsequently, the hosts are installed with a default Intel(R) Omni-Path Software configuration. The -I option can be used to select different install packages. Default is oftools ipoib mpi The -r option can be used to specify a release to install other than the one that this host is presently running. The \fIFF\(ulPRODUCT\fR. \fIFF\(ulPRODUCT\(ulVERSION\fR.tgz file (for example, IntelOPA-Basic. \fIversion\fR.tgz) is expected to exist in the directory specified by -d. Default is the current working directory. The specified software is copied to all the selected hosts and installed. + +.TP 10 +upgrade + +Upgrades all selected hosts without modifying existing configurations. This operation is comparable to the -U option when running ./INSTALL manually. The -r option can be used to upgrade to a release different from this host. The default is to upgrade to the same release as this host. The \fIFF\(ulPRODUCT\fR. \fIFF\(ulPRODUCT\(ulVERSION\fR.tgz file (for example, IntelOPA-Basic. \fIversion\fR.tgz) is expected to exist in the directory specified by -d. The default is the current working directory. The specified software is copied to all the end nodes and installed. +.TP 10 +.BR + +.PP + +.B NOTE: +Only components that are currently installed are upgraded. This operation fails for hosts that do not have Intel(R) Omni-Path Software installed. + + +.TP 10 +configipoib + +Creates a ifcfg-ib1 configuration file for each node using the IP address found using the resolver on the node. The standard Linux* resolver is used through the host command. (If running OFA Delta, this option configures ifcfg-ib0 .) + +.IP +If the host is not found, /etc/hosts on the node is checked. The -i option specifies an IPoIB suffix to apply to the host name to create the IPoIB host name for the node. The default suffix is -ib. The -m option specifies a netmask other than the default for the given class of IP address, such as when dividing a class A or B address into smaller IP subnets. IPoIB is configured for a static IP address and is autostarted at boot. For the Intel(R) OP Software Stack, the default /etc/ipoib.cfg file is used, which provides a redundant IPoIB configuration using both ports of the first HFI in the system. +.TP 10 +.BR + +.PP + +.B NOTE: +opahostadmin configipoib now supports DHCP (auto or static options) for configuring the IPoIB interface. You must specify these options in /etc/opa/opafastfabric.conf against the \fBFF\(ulIPOIB\(ulCONFIG\fR variable. If no options are found, the static IP configuration is used by default. If auto is specified, then one IP address from either static or dhcp is chosen. Static is used if the IP address can be obtained out of /etc/hosts or the resolver, otherwise DHCP is used. + + +.TP 10 +reboot + +Reboots the given hosts and ensures they go down and come back up by pinging them during the reboot process. The ping rate is slow (5 seconds), so if the servers boot faster than this, false failures may be seen. + +.TP 10 +sacache + +Verifies the given hosts can properly communicate with the SA and any cached SA data that is up to date. To run this command, Intel(R) Omni-Path Fabric software must be installed and running on the given hosts. The subnet manager and switches must be up. If this test fails: opacmdall \[aq]opasaquery -o desc\[aq] can be run against any problem hosts. + +.TP 10 +.BR + +.PP + +.B NOTE: +This operation requires that the hosts being queried are specified by a resolvable TCP/IP host name. This operation FAILS if the selected hosts are specified by IP address. + + +.TP 10 +ipoibping + +Verifies IPoIB basic operation by ensuring that the host can ping all other nodes through IPoIB. To run this command, Intel(R) Omni-Path Fabric software must be installed, IPoIB must be configured and running on the host, and the given hosts, the SM, and switches must be up. The -i option can specify an alternate IPoIB hostname suffix. + +.TP 10 +mpiperf + +Verifies that MPI is operational and checks MPI end-to-end latency and bandwidth between pairs of nodes (for example, 1-2, 3-4, 5-6). Use this to verify switch latency/hops, PCI bandwidth, and overall MPI performance. The test.res file contains the results of each pair of nodes tested. + +.TP 10 +.BR + +.PP + +.B NOTE: +This option is available for the Intel(R) Omni-Path Fabric Host Software OFA Delta packaging, but is not presently available for other packagings of OFED. + + +.IP +To obtain accurate results, this test should be run at a time when no other stressful applications (for example, MPI jobs or high stress file system operations) are running on the given hosts. +.IP +Bandwidth issues typically indicate server configuration issues (for example, incorrect slot used, incorrect BIOS settings, or incorrect HFI model), or fabric issues (for example, symbol errors, incorrect link width, or speed). Assuming opareport has previously been used to check for link errors and link speed issues, the server configuration should be verified. +.IP +Note that BIOS settings and differences between server models can account for 10-20% differences in bandwidth. For more details about BIOS settings, consult the documentation from the server supplier and/or the server PCI chipset manufacturer. +.TP 10 +mpiperfdeviation + +Specifies the enhanced version of mpiperf that verifies MPI performance. Can be used to verify switch latency/hops, PCI bandwidth, and overall MPI performance. It performs assorted pair-wise bandwidth and latency tests, and reports pairs outside an acceptable tolerance range. The tool identifies specific nodes that have problems and provides a concise summary of results. The test.res file contains the results of each pair of nodes tested. + +.IP +By default, concurrent mode is used to quickly analyze the fabric and host performance. Pairs that have 20% less bandwidth or 50% more latency than the average pair are reported as failures. +.IP +The tool can be run in a sequential or a concurrent mode. Sequential mode runs each host against a reference host. By default, the reference host is selected based on the best performance from a quick test of the first 40 hosts. In concurrent mode, hosts are paired up and all pairs are run concurrently. Since there may be fabric contention during such a run, any poor performing pairs are then rerun sequentially against the reference host. +.IP +Concurrent mode runs the tests in the shortest amount of time, however, the results could be slightly less accurate due to switch contention. In heavily oversubscribed fabric designs, if concurrent mode is producing unexpectedly low performance, try sequential mode. +.TP 10 +.BR + +.PP + +.B NOTE: +This option is available for the Intel(R) Omni-Path Fabric Host Software OFA Delta packaging, but is not presently available for other packagings of OFED. + + +.IP +To obtain accurate results, this test should be run at a time when no other stressful applications (for example, MPI jobs, high stress file system operations) are running on the given hosts. +.IP +Bandwidth issues typically indicate server configuration issues (for example, incorrect slot used, incorrect BIOS settings, or incorrect HFI model), or fabric issues (for example, symbol errors, incorrect link width, or speed). Assuming opareport has previously been used to check for link errors and link speed issues, the server configuration should be verified. +.IP +Note that BIOS settings and differences between server models can account for 10-20% differences in bandwidth. A result 5-10% below the average is typically not cause for serious alarm, but may reflect limitations in the server design or the chosen BIOS settings. +.IP +For more details about BIOS settings, consult the documentation from the server supplier and/or the server PCI chipset manufacturer. +.IP +The deviation application supports a number of parameters which allow for more precise control over the mode, benchmark and pass/fail criteria. The parameters to use can be selected using the \fBFF\(ulDEVIATION\(ulARGS\fR configuration parameter in opafastfabric.conf +.IP +Available parameters for deviation application: +.IP + +.br +[-bwtol bwtol] [-bwdelta MBs] [-bwthres MBs] +.br + +[-bwloop count] [-bwsize size] [-lattol latol] +.br + +[-latdelta usec] [-latthres usec] [-latloop count] +.br + +[-latsize size][-c] [-b] [-v] [-vv] +.br + +[-h reference\(ulhost] + +.br + +.RS +.TP 10 + +.sp +-bwtol +Specifies the percent of bandwidth degradation allowed below average value. + +.RE + +.RS +.TP 10 + +.sp +-bwbidir +Performs a bidirectional bandwidth test. + +.RE + +.RS +.TP 10 + +.sp +-bwunidir +Performs a unidirectional bandwidth test (Default). + +.RE + +.RS +.TP 10 + +.sp +-bwdelta +Specifies the limit in MB/s of bandwidth degradation allowed below average value. + +.RE + +.RS +.TP 10 + +.sp +-bwthres +Specifies the lower limit in MB/s of bandwidth allowed. + +.RE + +.RS +.TP 10 + +.sp +-bwloop +Specifies the number of loops to execute each bandwidth test. + +.RE + +.RS +.TP 10 + +.sp +-bwsize +Specifies the size of message to use for bandwidth test. + +.RE + +.RS +.TP 10 + +.sp +-lattol +Specifies the percent of latency degradation allowed above average value. + +.RE + +.RS +.TP 10 + +.sp +-latdelta +Specifies the imit in µsec of latency degradation allowed above average value. + +.RE + +.RS +.TP 10 + +.sp +-latthres +Specifies the lower limit in µsec of latency allowed. + +.RE + +.RS +.TP 10 + +.sp +-latloop +Specifies the number of loops to execute each latency test. + +.RE + +.RS +.TP 10 + +.sp +-latsize +Specifies the size of message to use for latency test. + +.RE + +.RS +.TP 10 + +.sp +-c +Runs test pairs concurrently instead of the default of sequential. + +.RE + +.RS +.TP 10 + +.sp +-b +When comparing results against tolerance and delta, uses best instead of average. + +.RE + +.RS +.TP 10 + +.sp +-v +Specifies the verbose output. + +.RE + +.RS +.TP 10 + +.sp +-vv +Specifies the very verbose output. + +.RE + +.RS +.TP 10 + +.sp +-h +Specifies the reference host to use for sequential pairing. + +.RE + +.IP +Both bwtol and bwdelta must be exceeded to fail bandwidth test. +.IP +When bwthres is supplied, bwtol and bwdelta are ignored. +.IP +Both lattol and latdelta must be exceeded to fail latency test. +.IP +When latthres is supplied, lattol and latdelta are ignored. +.IP +For consistency with OSU benchmarks, MB/s is defined as 1000000 bytes/s. diff --git a/IbaTools/man/opahostsmanalysis.manPage b/IbaTools/man/opahostsmanalysis.manPage new file mode 100644 index 0000000..956b598 --- /dev/null +++ b/IbaTools/man/opahostsmanalysis.manPage @@ -0,0 +1,116 @@ +.\" .\" ********************************************************************* +.\" .\" * * +.\" .\" * Copyright 2015-2019, Intel Corporation * +.\" .\" * * +.\" .\" * All Rights Reserved. * +.\" .\" * * +.\" .\" ********************************************************************* + +.TH opahostsmanalysis 8 "Intel Corporation" "Copyright(C) 2015\-2019" "IFSFFCLIRG (Man Page)" +.SH NAME +opahostsmanalysis + + +.PP + +\fB(All)\fR +Performs analysis against the local server only. It is assumed that both the host SM and the FastFabric are installed on the same system. +.PP +The host SM analysis tool checks the following: +.IP \(bu +Host SM software version +.IP \(bu +Host SM configuration file (simple text compare using FF\(ulDIFF\(ulCMD) +.IP \(bu +Host SM health (for example, is it running?) +.SH Syntax +opahostsmanalysis [-b|-e] [-s] [-d \fIdir\fR] +.SH Options + +.TP 10 +--help + +Produces full help text. +.TP 10 +-b + +Specifies the baseline mode. Default is the compare/check mode. +.TP 10 +-e + +Evaluates health only. Default is the compare/check mode. +.TP 10 +-s + +Saves history of failures (errors/differences). +.TP 10 +-d \fIdir\fR + +Specifies the top-level directory for saving baseline and history of failed checks. Default is /var/usr/lib/opa/analysis +.SH Example +opahostsmanalysis +.SH Environment Variables + +.PP +The following environment variables are also used by this command: +.TP 10 +\fBFF\(ulANALYSIS\(ulDIR\fR + +Top-level directory for baselines and failed health checks. +.TP 10 +\fBFF\(ulCURTIME\fR + +Timestamp to use on the directory created in FF\(ulDIFF\(ulCMD. +.TP 10 +\fBFF\(ulDIFF\(ulCMD\fR + +Linux* command to use to compare baseline to latest snapshot. +.SH Details + +.PP +All files generated by opahostsmanalysis start with hostsm in the file name. +.PP +The opahostsmanalysis tool generates files such as the following within FF\(ulANALYSIS\(ulDIR. The actual file names reflect the individual chassis commands that have been configured using the \fBFF\(ulCHASSIS\(ulHEALTH\fR and \fBFF\(ulCHASSIS\(ulCMDS\fR parameters: +.PP + +\fBHealth Check\fR + +.IP \(bu +latest/hostsm.smstatus - Output of the sm\(ulquery smShowStatus command. +.PP + +\fBBaseline\fR + +.IP \(bu +baseline/hostsm.smver - Host SM version. +.IP \(bu +baseline/hostsm.smconfig - Copy of opafm.xml. +.PP +During a baseline run, the files are also created in FF\(ulANALYSIS\(ulDIR/latest. +.PP + +\fBFull Analysis\fR + +.IP \(bu +latest/hostsm.smstatus - Output of the sm\(ulquery smShowStatus command. +.IP \(bu +latest/hostsm.smver - Host SM version. latest/hostsm.smver.diff - diff of the baseline and latest host SM version. + +.IP \(bu +latest/hostsm.smconfig - Copy of opafm.xml. +.IP \(bu +latest/hostsm.smconfig.diff - diff of the baseline and the latest opafm.xml. +.PP +The .diff files are only created if differences are detected. +.PP +If the -s option is used and failures are detected, files related to the checks that failed are also copied to a time-stamped directory name under FF\(ulANALYSIS\(ulDIR. +.SH Host SM Items Checked Against the Baseline + +.IP \(bu +SM configuration file. +.IP \(bu +Version of the SM rpm installed on the system. +.SH Host SM Items Also Checked During Health Check + +.IP \(bu +The SM is in the running state. diff --git a/IbaTools/man/opainfo.manPage b/IbaTools/man/opainfo.manPage new file mode 100644 index 0000000..247eed1 --- /dev/null +++ b/IbaTools/man/opainfo.manPage @@ -0,0 +1,193 @@ +.\" .\" ********************************************************************* +.\" .\" * * +.\" .\" * Copyright 2015-2019, Intel Corporation * +.\" .\" * * +.\" .\" * All Rights Reserved. * +.\" .\" * * +.\" .\" ********************************************************************* + +.TH opainfo 1 "Intel Corporation" "Copyright(C) 2015\-2019" "IFSFFCLIRG (Man Page)" +.SH NAME +opainfo + + +.PP +Provides summary information for local HFI port(s). +.SH Syntax +opainfo [-h \fIhfi\fR] [-p \fIport\fR] [-o \fItype\fR] [-g] [-d \fIdetail\fR] +[-s pm\(ulsl] +.br +[-v [-v]...] + +.SH Options + +.TP 10 +--help + +Produces full help text. + +.TP 10 +-h \fIhfi\fR + +Specifies the HFI, numbered 1..n. Using 0 specifies that the -p \fIport\fR port is a system-wide port number. Default is 0. + +.TP 10 +-p \fIport\fR + +Specifies the port, numbered 1 to n. Using 0 specifies the first active port across all HFIs/ports. Default is 1 which indicates all ports. If selected, the tool returns information on all available ports if p is not defined. + +.TP 10 +-o \fItype\fR + +Specifies the output type and can appear more than once. + +.TP 10 +.BR + +.PP + +.B NOTE: +Behavior without -o gives a brief summary of portinfo, counters and cableinfo. + +.RS +.TP 10 + +.sp +info +Outputs detailed portinfo. +.RE + +.RS +.TP 10 + +.sp +stats +Outputs detailed port counters. +.RE + +.TP 10 +-g + +Output is displayed in line-by-line format. Default is summary format. + +.TP 10 +-d \fIdetail\fR + +Output detail level. Range is 0 - 2. CableInfo only. Default is 0. + +.TP 10 +.BR + +.PP + +.B NOTE: +-d option is ignored when used with -o type. + +.RS +.TP 10 + +.sp +0 +Minimal crucial information (for example, cable length, vendor) + +.RE + +.RS +.TP 10 + +.sp +1 +Brief summary + +.RE + +.RS +.TP 10 + +.sp +2 +Extended brief summary + +.RE + +.TP 10 +-s \fIpm\(ulsl\fR + +Specifies different Service Level for PMA traffic. + + +.SH -h and -p options permit a variety of selections: + +.TP 10 +-h 0 + +First active port in system (Default). + +.TP 10 +-h 0 -p 0 + +First active port in system. + +.TP 10 +-h \fIx\fR + +First active port on HFI \fIx\fR. + +.TP 10 +-h \fIx\fR \fI\fR-p 0 + +First active port on HFI \fIx\fR. + +.TP 10 +-h 0 -p \fIy\fR + +Port \fIy\fR within system (no matter which ports are active). + +.TP 10 +-h \fIx\fR \fI\fR-p \fIy\fR + +HFI \fIx\fR, port \fIy\fR. + + +.SH Debug Options + +.TP 10 +-v + +Specifies the verbose output. Additional invocations (-v -v ...) turn on debugging, openib debugging, and libibumad debugging. + +.SH Examples +opainfo +.br + + hfi1\(ul0:1 PortGID:0xfe80000000000000:001175010165b19c +.br + + PortState: Active +.br + + LinkSpeed Act: 25Gb En: 25Gb +.br + + LinkWidth Act: 4 En: 4 +.br + + LinkWidthDnGrd ActTx: 4 Rx: 4 En: 3,4 +.br + + LCRC Act: 14-bit En: 14-bit,16-bit,48-bit Mgmt: True +.br + + LID: 0x00000001-0x00000001 SM LID: 0x00000002 SL: 0 +.br + + QSFP: PassiveCu, 1m FCI Electronics P/N 10131941-2010LF Rev 5 +.br + + Xmit Data: 22581581 MB Pkts: 5100825193 +.br + + Recv Data: 18725619 MB Pkts: 4024569756 +.br + + Link Quality: 5 (Excellent) diff --git a/IbaTools/man/opaledports.manPage b/IbaTools/man/opaledports.manPage new file mode 100644 index 0000000..9b85a5d --- /dev/null +++ b/IbaTools/man/opaledports.manPage @@ -0,0 +1,96 @@ +.\" .\" ********************************************************************* +.\" .\" * * +.\" .\" * Copyright 2015-2019, Intel Corporation * +.\" .\" * * +.\" .\" * All Rights Reserved. * +.\" .\" * * +.\" .\" ********************************************************************* + +.TH opaledports 8 "Intel Corporation" "Copyright(C) 2015\-2019" "IFSFFCLIRG (Man Page)" +.SH NAME +opaledports + + +.PP +Toggles the beaconing LED state of HFIs, switches, and switch ports. opaledports is a useful aid for finding specific physical nodes in a crowded data center. It supports the CSV link format provided by opaextractsellinks. +.SH Syntax +opaledports [-h hfi] [-p port] [-C] [-s|-d] [on|off] < portlist.csv +.SH Options + +.TP 10 +--help + +Produces full help text. + +.TP 10 +-h \fIhfi\fR + +Specifies the HFI, numbered 1..n. Using 0 specifies that the -p \fIport\fR port is a system-wide port number. Default is 0. + +.TP 10 +-p \fIport\fR + +Specifies the port, numbered 1..n. Using 0 specifies the first active port. Default is 0. + +.TP 10 +-C + +Clears beaconing LED on all ports. + +.IP + +\fBNOTE:\fR +If -C is entered, no other options are valid. +.TP 10 +-s + +Affects source side (first node) of link only. + +.TP 10 +-d + +Affects destination side (second node) of link only. + +.TP 10 +on|off + +Turns on or off the beaconing LED. Options include: + +.RS +.TP 10 + +.sp +on +Turns on beaconing LED. + +.RE + +.RS +.TP 10 + +.sp +off +Turns off beaconing LED. + +.RE + +.TP 10 +portlist.csv + +Specifies the file listing the links to process. The list is of the form: + +.IP +NodeGUID;PortNum;NodeType;NodeDesc;NodeGUID;PortNum; +.br +NodeType;NodeDesc;Dontcare +.SH Examples +echo "0x001175010165ac1d;1;FI;phkpstl035 hfi1\(ul0"|opaledports on +.br + +opaledports on < portlist.csv +.br + +opaextractsellinks -F led:on | opaledports off +.br + +opaledports -C diff --git a/IbaTools/man/opalinkanalysis.manPage b/IbaTools/man/opalinkanalysis.manPage new file mode 100644 index 0000000..8cc2aef --- /dev/null +++ b/IbaTools/man/opalinkanalysis.manPage @@ -0,0 +1,303 @@ +.\" .\" ********************************************************************* +.\" .\" * * +.\" .\" * Copyright 2015-2019, Intel Corporation * +.\" .\" * * +.\" .\" * All Rights Reserved. * +.\" .\" * * +.\" .\" ********************************************************************* + +.TH opalinkanalysis 8 "Intel Corporation" "Copyright(C) 2015\-2019" "IFSFFCLIRG (Man Page)" +.SH NAME +opalinkanalysis + + +.PP + +\fB(Switch)\fR +Encapsulates the capabilities for link analysis. Additionally, this tool includes cable and fabric topology verification capabilities. This tool is built on top of opareport (and its analysis capabilities), and accepts the same syntax for input topology and snapshot files. +.PP +In addition to being able to run assorted opareport link analysis reports, and generate human-readable output, this tool additionally analyzes the results and appends a concise summary of issues found to the FF\(ulRESULT\(ulDIR/punchlist.csv file. +.SH Syntax +opalinkanalysis [-U] [-t \fIportsfile\fR] [-p \fIports\fR] [-T \fItopology\(ulinput\fR] +.br + +[-X \fIsnapshot\(ulinput\fR] [-x \fIsnapshot\(ulsuffix\fR] [-c \fIfile\fR] reports ... +.SH Options + +.TP 10 +--help + +Produces full help text. + +.TP 10 +-U + +Omits unexpected devices and links in punchlist file from verify reports. + +.TP 10 +-t \fIportsfile\fR + +Specifies the file with list of local HFI ports used to access fabric(s) for analysis. Default is /etc/opa/ports. + +.TP 10 +-p \fIports\fR + +Specifies the list of local HFI ports used to access fabrics for analysis. + +.IP +Default is first active port. The first HFI in the system is 1. The first port on an HFI is 1. Uses the format hfi:port, +.br +for example: +.RS +.TP 10 + +.sp +0:0 +First active port in system. + +.RE + +.RS +.TP 10 + +.sp +0:y +Port \fIy\fR within system. + +.RE + +.RS +.TP 10 + +.sp +x:0 +First active port on HFI \fIx\fR. + +.RE + +.RS +.TP 10 + +.sp +x:y +HFI \fIx\fR, port \fIy\fR. + +.RE + +.TP 10 +-T \fItopology\(ulinput\fR + +Specifies the name of a topology input file to use. Any %P markers in this filename are replaced with the hfi:port being operated on (such as 0:0 or 1:2). Default is /etc/opa/topology.%P.xml. If NONE is specified, does not use any topology\(ulinput files. See +\fIopareport\fR +for more information on topology\(ulinput files. + +.TP 10 +-X \fIsnapshot\(ulinput\fR + +Performs analysis using data in \fIsnapshot\(ulinput\fR. \fIsnapshot\(ulinput\fR must have been generated via a previous opareport -o snapshot run. If an errors report is specified, snapshot must have been generated with the opareport -s option. When this option is used, only one port may be specified to select a topology\(ulinput file (unless -T specified). When this option is used, clearerrors and clearhwerrors reports are not permitted. + +.TP 10 +-x \fIsnapshot\(ulsuffix\fR + +Creates a snapshot file per selected port. The files are created in FF\(ulRESULT\(ulDIR with names of the form: snapshotSUFFIX. \fIHFI:PORT\fR.xml. + +.TP 10 +-c \fIfile\fR + +Specifies the error thresholds configuration file. The default is /etc/opa/opamon.si.conf. + +.TP 10 +\fIreports\fR + +Supports the following reports: +.RS +.TP 10 + +.sp +errors +Specifies link error analysis. + +.RE + +.RS +.TP 10 + +.sp +slowlinks +Specifies links running slower than expected. + +.RE + +.RS +.TP 10 + +.sp +misconfiglinks +Specifies links configured to run slower than supported. + +.RE + +.RS +.TP 10 + +.sp +misconnlinks +Specifies links connected with mismatched speed potential. + +.RE + +.RS +.TP 10 + +.sp +all +Includes all reports above. (errors, slowlinks, misconfiglinks, and misconnlinks) + +.RE + +.RS +.TP 10 + +.sp +verifylinks +Verifies links against topology input. + +.RE + +.RS +.TP 10 + +.sp +verifyextlinks +Verifies links against topology input. Limits analysis to links external to systems. + +.RE + +.RS +.TP 10 + +.sp +verifyfilinks +Verifies links against topology input. Limits analysis to FI links. + +.RE + +.RS +.TP 10 + +.sp +verifyislinks +Verifies links against topology input. Limits analysis to inter-switch links. + +.RE + +.RS +.TP 10 + +.sp +verifyextislinks +Verifies links against topology input. Limits analysis to inter-switch links external to systems. + +.RE + +.RS +.TP 10 + +.sp +verifyfis +Verifies FIs against topology input. + +.RE + +.RS +.TP 10 + +.sp +verifysws +Verifies switches against topology input. + +.RE + +.RS +.TP 10 + +.sp +verifynodes +Verifies FIs and switches against topology input. + +.RE + +.RS +.TP 10 + +.sp +verifysms +Verifies SMs against topology input. + +.RE + +.RS +.TP 10 + +.sp +verifyall +Verifies links, FIs, switches, and SMs against topology input. + +.RE + +.RS +.TP 10 + +.sp +clearerrors +Clears error counters, uses PM if available. + +.RE + +.RS +.TP 10 + +.sp +clearhwerrors +Clears hardware error counters, bypasses PM. + +.RE + +.RS +.TP 10 + +.sp +clear +Includes clearerrors and clearhwerrors. + +.RE + + +.PP +A punchlist of bad links is also appended to the file: FF\(ulRESULT\(ulDIR/punchlist.csv +.SH Examples +opalinkanalysis errors +.br + +opalinkanalysis errors clearerrors +.br + +opalinkanalysis -p \[aq]1:1 1:2 2:1 2:2\[aq] +.SH Environment Variables + +.PP +The following environment variables are also used by this command: +.TP 10 +\fBPORTS\fR + +List of ports, used in absence of -t and -p. + +.TP 10 +\fBPORTS\(ulFILE\fR + +File containing list of ports, used in absence of -t and -p. + +.TP 10 +\fBFF\(ulTOPOLOGY\(ulFILE\fR + +File containing \fItopology\(ulinput\fR, used in absence of -T. diff --git a/IbaTools/man/opamergeperf2.manPage b/IbaTools/man/opamergeperf2.manPage new file mode 100644 index 0000000..d3259ef --- /dev/null +++ b/IbaTools/man/opamergeperf2.manPage @@ -0,0 +1,52 @@ +.\" .\" ********************************************************************* +.\" .\" * * +.\" .\" * Copyright 2015-2019, Intel Corporation * +.\" .\" * * +.\" .\" * All Rights Reserved. * +.\" .\" * * +.\" .\" ********************************************************************* + +.TH opamergeperf2 8 "Intel Corporation" "Copyright(C) 2015\-2019" "IFSFFCLIRG (Man Page)" +.SH NAME +opamergeperf2 + + +.PP +Merges the output from two opaextactperf2 runs from the same fabric. Delta counters for matching links will be computed (before subtracted from after) and a CSV file equivalent to opaextractperf2 \[aq]s output format will be generated suitable for importing into a spreadsheet or parsing by other scripts. +.PP + +.B NOTE: +The before.csv and after.csv input files must be generated from the same fabric, with before.csv containing counters prior to after.csv. Both files must have been generated to contain the +\fIrunning counters\fR + +without any counter clears between before.csv and after.csv, and without using any interval options to opareport that might report delta counters, such as opareport -i or opareport with both --begin and --end options. + +.SH Syntax +opamergeperf2 before.csv after.csv +.SH Options + +.TP 10 +--help + +Produces full help text. + +.TP 10 +before.csv + +A CSV file previously generated by opaextractperf2. + +.TP 10 +after.csv + +A CSV file previously generated by opaextractperf2. + +.SH Examples +opamergeperf2 before.csv after.csv > delta.csv + + +.SH See Also + +.PP + +\fIopaextractperf2\fR + diff --git a/IbaTools/man/opapacketcapture.manPage b/IbaTools/man/opapacketcapture.manPage new file mode 100644 index 0000000..4c3505d --- /dev/null +++ b/IbaTools/man/opapacketcapture.manPage @@ -0,0 +1,103 @@ +.\" .\" ********************************************************************* +.\" .\" * * +.\" .\" * Copyright 2015-2019, Intel Corporation * +.\" .\" * * +.\" .\" * All Rights Reserved. * +.\" .\" * * +.\" .\" ********************************************************************* + +.TH opapacketcapture 1 "Intel Corporation" "Copyright(C) 2015\-2019" "IFSFFCLIRG (Man Page)" +.SH NAME +opapacketcapture + + +.PP +Starts capturing packet data. +.PP +To stop capture and trigger dump, use SIGINT or SIGUSR1. Program dumps packets to file and exits. +.PP + +.B NOTE: +Using opapacketcapture with large amounts of traffic can cause performance issues on the given host. Intel recommends you use opapacketcapture on hosts with lower packet rates and bandwidth. + +.SH Syntax +opapacketcapture [-o \fIoutfile\fR] [-d \fIdevfile\fR] [-f \fIfilterfile\fR] +.br +[-t \fItriggerfile\fR] +[-l \fItriggerlag\fR][-a \fIalarm\fR] [-p \fIpackets\fR] [-s \fImaxblocks\fR] +.br +[-v [-v]] +.SH Options + +.TP 10 +--help + +Produces full help text. + +.TP 10 +-o \fIoutfile\fR + +Specifies the output file for captured packets. +.br +Default is packetDump.pcap + +.TP 10 +-d \fIdevfile\fR + +Specifies the device file for capturing packets. +.br + + +.TP 10 +-f \fIfilterfile\fR + +Specifies the file used for filtering. If absent, no filtering is done. + +.TP 10 +-t \fItriggerfile\fR + +Specifies the file used for triggering a stop capture. If absent, normal triggering is performed. + +.TP 10 +-l \fItriggerlag\fR + +Specifies the number of packets to collect after trigger condition is met, before dumping data and exiting. Default is 10. + +.TP 10 +-a \fIalarm\fR + +Specifies the number of seconds for alarm trigger to dump capture and exit. + +.TP 10 +-p \fIpackets\fR + +Specifies the number of packets for alarm trigger to dump capture and exit. + +.TP 10 +-s \fImaxblocks\fR + +Specifies the number of blocks to allocate for ring buffer. Value is in Millions. Default is 2 which corresponds to 128 MiB because 1 block = 64 Bytes. + +.TP 10 +-v + +Produces verbose output. (Use verbose Level 1+ to show levels.) + +.SH Example +# opapacketcapture +.br + +opapacketcapture: Capturing packets using 128 MiB buffer +.br + +^C +.br + +opapacketcapture: Triggered +.br + +Number of packets stored is 100 +.PP +In the example above, opapacketcapture operates until +\fBCTRL+C\fR +is entered. diff --git a/IbaTools/man/opapaquery.manPage b/IbaTools/man/opapaquery.manPage new file mode 100644 index 0000000..678f4dd --- /dev/null +++ b/IbaTools/man/opapaquery.manPage @@ -0,0 +1,750 @@ +.\" .\" ********************************************************************* +.\" .\" * * +.\" .\" * Copyright 2015-2019, Intel Corporation * +.\" .\" * * +.\" .\" * All Rights Reserved. * +.\" .\" * * +.\" .\" ********************************************************************* + +.TH opapaquery 8 "Intel Corporation" "Copyright(C) 2015\-2019" "IFSFFCLIRG (Man Page)" +.SH NAME +opapaquery + + +.PP + +\fB(All)\fR +Performs various queries of the performance management (PM)/performance administration (PA) agent and provides details about fabric performance. Refer to the +\fIIntel(R) Omni-Path Fabric Suite Fabric Manager User Guide\fR + +for a description of the operation and client services of the PM/PA. +.PP +By default, opapaquery queries the most recent data. However, if an image number (\fIimgNum\fR) and/or image offset (\fIimgOff\fR) is provided, the query returns previous sweep data. Queries that access previous sweep data return with the absolute image number representing that data, and therefore have an image offset of zero. +.PP +opapaquery\[aq]s operation is dependent on an Intel(R) Omni-Path Fabric Suite Fabric Manager version 6.0 or greater running as master SM/PM in the fabric. +.PP +By default, opapaquery uses the first active port on the local system. However, if the Fabric Management Node is connected to more than one fabric (for example, a subnet), the HFI and port may be specified to select the fabric whose PA is to be queried. +.SH Syntax +opapaquery [-v] [-h hfi|-b addr] [-p port] [-x gid] [-E] +.br +[-T ssl\(ulparams] [-o type] +[-g groupName] [-l nodeLid] [-P portNumber] +.br +[--timeout] [-G nodeGuid] +[-D nodeDesc] [-d delta] [-j date\(ultime] +.br +[-q date\(ultime] [-U] [-s select] [-f focus] +[-S start] [-r range] +.br +[-n imgNum] [-O imgOff] [-y imgTime] [-m moveImgNum] +[-M moveImgOff] [-V vfName] +.SH Options + +.TP 10 +-v/--verbose + +Specifies the verbose output. + +.TP 10 +-h/--hfi \fIhfi\fR + +Specifies the HFI, numbered 1..n. Using 0 specifies that the -p \fIport\fR port is a system-wide port number. Default is 0. + +.TP 10 +-b/--oob \fIaddress\fR + +Specifies Out-of-Band address of node running the FE. Can be either hostname, IPv4, or IPv6 address. Default is "127.0.0.1". + +.TP 10 +-p/--port \fIport\fR + +Specifies the port. +.RS + +.IP \(bu +In-band: Numbered 1...n. Using 0 specifies the first active port. Default is 0. +.IP \(bu +Out-of-band: Port FE is listening on. Default is 3245. + +.RE + + +.TP 10 +-x/--source-gid \fIsrc\(ulgid\fR + +Specifies the source GID of the local GID. (This is required for most Path and Trace Record Queries when Out-of-Band.) + +.TP 10 +-E/--feEsm + +Specifies the ESM FE. + +.TP 10 +-T/--ssl-params \fIfile\fR + +Specifies the SSL/TLS parameters XML file. Default is /etc/opa/opamgt\(ultls.xml. + +.TP 10 +-o/--output \fItype\fR + +Specifies the output type. Default is groupList. See +\fIOutput Types\fR +. + +.TP 10 +-g/--groupName \fIgroupName\fR + +Specifies the group name for groupInfo query. + +.TP 10 +-l/--lid \fIlid\fR + +Specifies the LID of the node. + +.TP 10 +-P/--portNumber \fIportNumber\fR + +Specifies the port number within the node. + +.TP 10 +--timeout + +Specifies the timeout (response wait time) in ms. Default is 1000 ms. + +.TP 10 +-G/--nodeGuid + +Specifies the GUID of the node. + +.TP 10 +-D/--nodeDesc + +Specifies the description of the node. + +.TP 10 +-d/--delta \fIdelta\fR + +Specifies the delta flag for portCounters query - 0 or 1. + +.TP 10 +-j/--begin \fIdate\(ultime\fR + +Obtains portCounters over an interval beginning at \fIdate\(ultime\fR. \fIdate\(ultime\fR may be a time entered as HH:MM[:SS] or date as mm/dd/YYYY, dd.mm.YYYY, YYYY-mm-dd or date followed by time; for example, "2016-07-04 14:40". Relative times are taken as "x [second|minute|hour|day](s) ago. + +.TP 10 +-q/--end \fIdate\(ultime\fR + +Obtains portCounters over an interval ending at \fIdate\(ultime\fR. \fIdate\(ultime\fR may be a time entered as HH:MM[:SS] or date as mm/dd/YYYY, dd.mm.YYYY, YYYY-mm-dd or date followed by time; for example, "2016-07-04 14:40". Relative times are taken as "x [second|minute|hour|day](s) ago. + +.TP 10 +-U/--userCntrs + +Queries by user-controlled counters flag for portCounters. + +.TP 10 +-s/--select \fIselect\fR + +Specifies the 32-bit select flag for clearing port counters. + +.IP +Select bits for clrPortCounters. 0 is the least significant bit (rightmost). The clrPortCounters bit descriptions are listed in the order "mask - bit - location" below: +.RS + +.IP \(bu +0x80000000 - 31 - Transmit Data (XmitData) + +.IP \(bu +0x40000000 - 30 - Receive Data (RcvData) + +.IP \(bu +0x20000000 - 29 - Transmit Packets (XmitPkts) + +.IP \(bu +0x10000000 - 28 - Receive Packets (RcvPkts) + +.IP \(bu +0x08000000 - 27 - Multicast Transmit Packets (MulticastXmitPkts) + +.IP \(bu +0x04000000 - 26 - Multicast Receive Packets (MulticastRcvPkts) + +.IP \(bu +0x02000000 - 25 - Transmit Wait (XmitWait) + +.IP \(bu +0x01000000 - 24 - Congestion Discards (CongDiscards) + +.IP \(bu +0x00800000 - 23 - Receive FECN (RcvFECN) + +.IP \(bu +0x00400000 - 22 - Receive BECN (RcvBECN) + +.IP \(bu +0x00200000 - 21 - Transmit Time Congestion (XmitTimeCong) + +.IP \(bu +0x00100000 - 20 - Transmit Time Wasted BW (XmitWastedBW) + +.IP \(bu +0x00080000 - 19 - Transmit Time Wait Data (XmitWaitData) + +.IP \(bu +0x00040000 - 18 - Receive Bubble (RcvBubble) + +.IP \(bu +0x00020000 - 17 - Mark FECN (MarkFECN) + +.IP \(bu +0x00010000 - 16 - Receive Constraint Errors (RcvConstraintErrors) + +.IP \(bu +0x00008000 - 15 - Receive Switch Relay (RcvSwitchRelayErrors) + +.IP \(bu +0x00004000 - 14 - Transmit Discards (XmitDiscards) + +.IP \(bu +0x00002000 - 13 - Transmit Constraint Errors (XmitConstraintErrors) + +.IP \(bu +0x00001000 - 12 - Receive Remote Physical Errors (RcvRemotePhysicalErrors) + +.IP \(bu +0x00000800 - 11 - Local Link Integrity (LocalLinkIntegrityErrors) + +.IP \(bu +0x00000400 - 10 - Receive Errors (RcvErrors) + +.IP \(bu +0x00000200 - 9 - Excessive Buffer Overrun (ExcessiveBufferOverruns) + +.IP \(bu +0x00000100 - 8 - FM Configuration Errors (FMConfigErrors) + +.IP \(bu +0x00000080 - 7 - Link Error Recovery (LinkErrorRecovery) + +.IP \(bu +0x00000040 - 6 - Link Error Downed (LinkDowned) + +.IP \(bu +0x00000020 - 5 - Uncorrectable Errors (UncorrectableErrors) + + +.RE + +.IP +Select bits for clrVfPortCounters. 0 is the least significant bit (rightmost). The clrVfPortCounters bit descriptions are listed in the order "mask - bit - location" below: +.RS + +.IP \(bu +0x80000000 - 31 - VL Transmit Data (VLXmitData) + +.IP \(bu +0x40000000 - 30 - VL Receive Data (VLRcvData) + +.IP \(bu +0x20000000 - 29 - VL Transmit Packets (VLXmitPkts) + +.IP \(bu +0x10000000 - 28 - VL Receive Packets (VLRcvPkts) + +.IP \(bu +0x08000000 - 27 - VL Transmit Discards (VLXmitDiscards) + +.IP \(bu +0x04000000 - 26 - VL Congestion Discards (VLCongDiscards) + +.IP \(bu +0x02000000 - 25 - VL Transmit Wait (VLXmitWait) + +.IP \(bu +0x01000000 - 24 - VL Receive FECN (VLRcvFECN) + +.IP \(bu +0x00800000 - 23 - VL Receive BECN (VLRcvBECN) + +.IP \(bu +0x00400000 - 22 - VL Transmit Time Congestion (VLXmitTimeCong) + +.IP \(bu +0x00200000 - 21 - VL Transmit Wasted BW (VLXmitWastedBW) + +.IP \(bu +0x00100000 - 20 - VL Transmit Wait Data (VLXmitWaitData) + +.IP \(bu +0x00080000 - 19 - VL Receive Bubble (VLRcvBubble) + +.IP \(bu +0x00040000 - 18 - VL Mark FECN (VLMarkFECN) + +.IP \(bu +Bits 17-0 reserved + + +.RE + +.TP 10 +-f/--focus \fIfocus\fR + +Specifies the focus select value for getting \fIfocus\fR ports. \fIfocus\fR select values are: +.RS +.TP 10 + +.sp +unexpclrport +Lists unexpectedly cleared ports - LID ordered. + +.RE + +.RS +.TP 10 + +.sp +norespport +Lists no response ports - LID ordered. + +.RE + +.RS +.TP 10 + +.sp +skippedport +Lists skipped ports - LID ordered. + +.RE + +.RS +.TP 10 + +.sp +utilhigh +Sorted by utilization - highest first. + +.RE + +.RS +.TP 10 + +.sp +pktrate +Sorted by packet rate - highest first. + +.RE + +.RS +.TP 10 + +.sp +utillow +Sorted by utilization - lowest first. + +.RE + +.RS +.TP 10 + +.sp +integrity +Sorted by integrity category - highest first. + +.RE + +.RS +.TP 10 + +.sp +congestion +Sorted by congestion category - highest first. + +.RE + +.RS +.TP 10 + +.sp +smacongestion +Sorted by SMA congestion category - highest first. + +.RE + +.RS +.TP 10 + +.sp +bubbles +Sorted by bubble category - highest first. +.RE + +.RS +.TP 10 + +.sp +security +Sorted by security category - highest first. + +.RE + +.RS +.TP 10 + +.sp +routing +Sorted by routing category - highest first. + +.RE + +.RS +.TP 10 + +.sp +vfutilhigh +Sorted by utilization - highest first. +.RE + +.RS +.TP 10 + +.sp +vfpktrate +Sorted by packet rate - highest first. +.RE + +.RS +.TP 10 + +.sp +vfutillow +Sorted by utilization - lowest first. +.RE + +.RS +.TP 10 + +.sp +vfcongestion +Sorted by congestion category - highest first. +.RE + +.RS +.TP 10 + +.sp +vfbubbles +Sorted by bubble category - highest first. +.RE + +.TP 10 +-S/--start \fIstart\fR + +Specifies the start of window for focus ports, should always be 0. + +.TP 10 +-r/--range \fIrange\fR + +Specifies the size of window for focus ports list. + +.TP 10 +-Q/--tuple + +Specifies a tuple that identifies a focus select value, comparator and argument in the form select: comparator:argument. Up to 8 tuples may be specified as: -Q s1:c1:a1 -Q s2:c2:a2 ... -Q s8:c8:a8 + +.IP +Valid focus select values are: utilization, pktrate, integrity, congestion, smacongestion, bubbles, security and routing. +.IP +Valid comparator values are: GT, GE, LT, LE +.IP +Valid arguments are: Any 64-bit value in hexadecimal or decimal. +.IP +When specifying more than one tuple, a logical operator -Z/--operator must also be specified. +.TP 10 +-Z/--operator + +Specifies a logical operator used to join the results of the specified tuples. + +.IP +and - Specifies a port is returned if it meets all of the tuple filter criteria. +.IP +or - Specifies a port is returned if it meets one or more of the tuple filter criteria. +.TP 10 +-n/--imgNum \fIimgNum\fR + +Specifies the 64-bit image number. + +.TP 10 +-O/--imgOff \fIimgOff\fR + +Specifies the image offset. + +.TP 10 +-y/--imgTime + +Specifies the image time. May be used with imageinfo, groupInfo, groupInfo, groupConfig, freezeImage, focusPorts, vfInfo, vfConfig, and vfFocusPorts. Will return closest image within image interval if possible. See --begin/--end above for format. + +.TP 10 +-m/--moveImgNum \fImoveImgNum\fR + +Specifies the 64-bit image number. Used with moveFreeze to move a freeze image. + +.TP 10 +-M/--moveImgOff \fImoveImgOff\fR + +Specifies the image offset. Can be used with moveFreeze to move a freeze image. + +.TP 10 +-V/--vfName \fIvfName\fR + +Specifies the VF name for vfInfo query. + + +.SH -h and -p options permit a variety of selections: + +.TP 10 +-h 0 + +First active port in system (Default). + +.TP 10 +-h 0 -p 0 + +First active port in system. + +.TP 10 +-h \fIx\fR + +First active port on HFI \fIx\fR. + +.TP 10 +-h \fIx\fR \fI\fR-p 0 + +First active port on HFI \fIx\fR. + +.TP 10 +-h 0 -p \fIy\fR + +Port \fIy\fR within system (no matter which ports are active). + +.TP 10 +-h \fIx\fR \fI\fR-p \fIy\fR + +HFI \fIx\fR, port \fIy\fR. + +.SH Output Types + +.TP 10 +classPortInfo + +Specifies the class port info. + +.TP 10 +groupList + +Specifies the list of PA groups. + +.TP 10 +groupInfo + +Specifies the summary statistics of a PA group. Requires -g option for \fIgroupName\fR. + +.TP 10 +groupConfig + +Specifies the configuration of a PA group. Requires -g option for \fIgroupName\fR. + +.TP 10 +groupNodeInfo + +Specifies the node information of a PA group. Requires -g option for \fIgroupName\fR. Options -l \fIlid\fR, -G \fInodeGuid\fR and -D \fInodeDesc\fR are optional. + +.TP 10 +groupLinkInfo + +Specifies the link Information of a PA group. Requires -g option for \fIgroupName\fR. Options -l \fIlid\fR and -P \fIport\fR are optional. Note that -P 255 specifies all ports. Option -P \fIport\fR without -l \fIlid\fR is ignored. + +.TP 10 +portCounters + +Specifies the port counters of fabric port. Requires -l \fIlid\fR and -P \fIport\fR options. -d \fIdelta\fR is optional. + +.TP 10 +clrPortCounters + +Clears port counters of fabric port. Requires -l \fIlid\fR and -P \fIport\fR, and -s \fIselect\fR options. + +.TP 10 +clrAllPortCounters + +Clears all port counters in fabric. + +.TP 10 +pmConfig + +Retrieves PM configuration information. + +.TP 10 +freezeImage + +Creates freeze frame for image ID. Requires -n \fIimgNum\fR. + +.TP 10 +releaseImage + +Releases freeze frame for image ID. Requires -n \fIimgNum\fR. + +.TP 10 +renewImage + +Renews lease for freeze frame for image ID. Requires -n \fIimgNum\fR. + +.TP 10 +moveFreeze + +Moves freeze frame from image ID to new image ID. Requires -n \fIimgNum\fR and -m \fImoveImgNum\fR. + +.TP 10 +focusPorts + +Gets sorted list of ports using utilization or error values (from group buckets). Requires -g \fIgroupname\fR, -f \fIfocus\fR, -S \fIstart\fR, -r \fIrange\fR. + +.TP 10 +imageInfo + +Gets configuration of a PA image (timestamps, etc.). Requires -n \fIimgNum\fR. + +.TP 10 +vfList + +Specifies the list of virtual fabrics. + +.TP 10 +vfInfo + +Specifies the summary statistics of a virtual fabric. Requires -V option for \fIvfName\fR. + +.TP 10 +vfConfig + +Specifies the configuration of a virtual fabric. Requires -V option for \fIvfName\fR. + +.TP 10 +vfPortCounters + +Specifies the port counters of fabric port. Requires -V \fIvfName\fR, -l \fIlid\fR and -P \fIport\fR options, -d \fIdelta\fR is optional. + +.TP 10 +vfFocusPorts + +Gets sorted list of virtual fabric ports using utilization or error values (from VF buckets). Requires -V \fIvfname\fR, -f \fIfocus\fR, -S \fIstart\fR, -r \fIrange\fR. + +.TP 10 +clrVfPortCounters + +Clears VF port counters of fabric port. Requires -l \fIlid\fR, -P \fIport\fR, -s \fIselect\fR, and -V \fIvfname\fR options. + +.SH Examples +opapaquery -o classPortInfo +.br + +opapaquery -o groupList +.br + +opapaquery -o groupInfo -g All +.br + +opapaquery -o groupConfig -g All +.br + +opapaquery -o groupNodeInfo -g All -G +.br + +opapaquery -o groupNodeInfo -g All -D +.br + +opapaquery -o groupNodeInfo -g All -l 1 +.br + +opapaquery -o groupNodeInfo -g All -l 1 -G +.br + +opapaquery -o groupLinkInfo -g All +.br + +opapaquery -o groupLinkInfo -g All -l 1 -P 1 +.br + +opapaquery -o groupLinkInfo -g All -l 1 -P 255 +.br + +opapaquery -o portCounters -l 1 -P 1 -d 1 +.br + +opapaquery -o portCounters -l 1 -P 1 -d 1 -n 0x20000000d02 -O 1 +.br + +opapaquery -o portCounters -l 1 -P 1 -d 1 -j 13:30 -q 14:20 +.br + +opapaquery -o clrPortCounters -l 1 -P 1 -s 0xC0000000 +.br + + (clears XmitData & RcvData) +.br + +opapaquery -o clrAllPortCounters -s 0xC0000000 +.br + + (clears XmitData & RcvData on all ports) +.br + +opapaquery -o pmConfig +.br + +opapaquery -o freezeImage -n 0x20000000d02 +.br + +opapaquery -o releaseImage -n 0xd01 +.br + +opapaquery -o renewImage -n 0xd01 +.br + +opapaquery -o moveFreeze -n 0xd01 -m 0x20000000d02 -M -2 +.br + +opapaquery -o focusPorts -g All -f integrity -S 0 -r 20 +.br + +opapaquery -o focusPorts -g All -S 0 -r 20 -Z AND -Q integrity:ge:20 -Q bubbles:lt:10 +.br + +opapaquery -o focusPorts -g All -f skippedport -S 0 -r 20 +.br + +opapaquery -o imageInfo -n 0x20000000d02 +.br + +opapaquery -o imageInfo -y "1 hour ago" +.br + +opapaquery -o vfList +.br + +opapaquery -o vfInfo -V Default +.br + +opapaquery -o vfConfig -V Default +.br + +opapaquery -o vfPortCounters -l 1 -P 1 -d 1 -V Default +.br + +opapaquery -o clrVfPortCounters -l 1 -P 1 -s 0xC0000000 -V Default +.br + + (clears VLXmitData & VLRcvData) +.br + +opapaquery -o vfFocusPorts -V Default -f integrity -S 0 -r 20 diff --git a/IbaTools/man/opapingall.manPage b/IbaTools/man/opapingall.manPage new file mode 100644 index 0000000..9b1133d --- /dev/null +++ b/IbaTools/man/opapingall.manPage @@ -0,0 +1,109 @@ +.\" .\" ********************************************************************* +.\" .\" * * +.\" .\" * Copyright 2015-2019, Intel Corporation * +.\" .\" * * +.\" .\" * All Rights Reserved. * +.\" .\" * * +.\" .\" ********************************************************************* + +.TH opapingall 8 "Intel Corporation" "Copyright(C) 2015\-2019" "IFSFFCLIRG (Man Page)" +.SH NAME +opapingall + + +.PP + +\fB(All)\fR +Pings a group of hosts or chassis to verify that they are powered on and accessible through TCP/IP ping. +.SH Syntax +opapingall [-C] [-p] [-f \fIhostfile\fR] [-F \fIchassisfile\fR] [-h \[aq]hosts\[aq]] +.br +[-H \[aq]chassis\[aq]] +.SH Options + +.TP 10 +--help + +Produces full help text. + +.TP 10 +-C + +Performs a ping against a chassis. Default is hosts. + +.TP 10 +-p + +Pings all hosts/chassis in parallel. + +.TP 10 +-f \fIhostfile\fR + +Specifies the file with hosts in cluster. +.br +Default is /etc/opa/hosts. + +.TP 10 +-F \fIchassisfile\fR + +Specifies the file with chassis in cluster. +.br +Default is /etc/opa/chassis. + +.TP 10 +-h hosts + +Specifies the list of hosts to ping. + +.TP 10 +-H chassis + +Specifies the list of chassis to ping. + +.SH Example +opapingall +.br + +opapingall -h \[aq]arwen elrond\[aq] +.br + +HOSTS=\[aq]arwen elrond\[aq] opapingall +.br + +opapingall -C +.PP + +.B NOTE: +This command pings all hosts/chassis found in the specified host/chassis file. The use of -C option merely selects the default file and/or environment variable to use. For this command, it is valid to use a file that lists both hosts and chassis. + +.br +opapingall -C -H \[aq]chassis1 chassis2\[aq] +.br + +CHASSIS=\[aq]chassis1 chassis2\[aq] opapingall -C +.SH Environment Variables + +.TP 10 +\fBHOSTS\fR + +List of hosts, used if -h option not supplied. + +.TP 10 +\fBCHASSIS\fR + +List of chassis, used if -H option not supplied. + +.TP 10 +\fBHOSTS\(ulFILE\fR + +File containing list of hosts, used in absence of -f and -h. + +.TP 10 +\fBCHASSIS\(ulFILE\fR + +File containing list of chassis, used in absence of -F and -H. + +.TP 10 +\fBFF\(ulMAX\(ulPARALLEL\fR + +When -p option is used, maximum concurrent operations are performed. diff --git a/IbaTools/man/opapmaquery.manPage b/IbaTools/man/opapmaquery.manPage new file mode 100644 index 0000000..77b334c --- /dev/null +++ b/IbaTools/man/opapmaquery.manPage @@ -0,0 +1,398 @@ +.\" .\" ********************************************************************* +.\" .\" * * +.\" .\" * Copyright 2015-2019, Intel Corporation * +.\" .\" * * +.\" .\" * All Rights Reserved. * +.\" .\" * * +.\" .\" ********************************************************************* + +.TH opapmaquery 1 "Intel Corporation" "Copyright(C) 2015\-2019" "IFSFFCLIRG (Man Page)" +.SH NAME +opapmaquery + + +.PP + +\fB(All)\fR +Performs individual PMA queries against a specific LID. It is very useful in displaying port runtime information. +.SH Syntax +opapmaquery [-v] [-s \fIsl\fR] [-l \fIlid\fR] [-h \fIhfi\fR] [-p \fIport\fR] [-o \fIotype\fR] +.br +[-m \fIport\fR] +[-n \fImask\fR] [-e \fImask\fR] [-w \fImask\fR] + +.SH Options + +.TP 10 +--help + +Produces full help text. + +.TP 10 +-v + +Specifies the verbose output. Can be specified more than once for additional openib debugging and libibumad debugging. + +.TP 10 +-s \fIsl\fR + +Specifies different service level. Default is SM SL. + +.TP 10 +-l \fIlid\fR + +Specifies the destination LID. Default is local port. + +.TP 10 +-h/--hfi \fIhfi\fR + +Specifies the HFI, numbered 1..n. Using 0 specifies that the -p \fIport\fR port is a system-wide port number. Default is 0. + +.TP 10 +-p/--port \fIport\fR + +Specifies the port, numbered 1..n. Using 0 specifies the first active port. Default is 0. + +.TP 10 +-o \fIotype\fR + +Specifies the output type. Default is getportstatus. Refer to +\fIotype options vary by report\fR +for supported options. + +.IP +Valid output types are: +.RS +.TP 10 + +.sp +classportinfo +Specifies the class of port info. + +.RE + +.RS +.TP 10 + +.sp +getportstatus +Specifies the list of port counters. Supported options: + +.IP + +.br +[-m port] [-w vl mask] + +.br + +.RE + +.RS +.TP 10 + +.sp +clearportstatus +Clears the port counters. Supported options: + +.IP + +.br +[-n port mask] [-e counter mask] [-w vl mask] + +.br + +.RE + +.RS +.TP 10 + +.sp +getdatacounters +Specifies the list of data counters. Supported options: + +.IP + +.br +[-n port mask] [-w vl mask] + +.br + +.RE + +.RS +.TP 10 + +.sp +geterrorcounters +Specifies the list of error counters. Supported options: + +.IP + +.br +[-n port mask] [-w vl mask] + +.br + +.RE + +.RS +.TP 10 + +.sp +geterrorinfo +Specifies the list of error info. Supported options: + +.IP + +.br +[-n port mask] + +.br + +.RE + +.RS +.TP 10 + +.sp +clearerrorinfo +Clears the error info. Supported options: + +.IP + +.br +[-n port mask] [-e counter mask] + +.br + +.RE + + +.SH -h and -p options permit a variety of selections: + +.TP 10 +-h 0 + +First active port in system (Default). + +.TP 10 +-h 0 -p 0 + +First active port in system. + +.TP 10 +-h \fIx\fR + +First active port on HFI \fIx\fR. + +.TP 10 +-h \fIx\fR \fI\fR-p 0 + +First active port on HFI \fIx\fR. + +.TP 10 +-h 0 -p \fIy\fR + +Port \fIy\fR within system (no matter which ports are active). + +.TP 10 +-h \fIx\fR \fI\fR-p \fIy\fR + +HFI \fIx\fR, port \fIy\fR. + + +.SH \fIotype\fR options vary by report + +.TP 10 +-m \fIport\fR + +Specifies the port in destination device to query/clear. Required when using -l option for all but -o classportinfo. + +.TP 10 +-n \fImask\fR + +Specifies the port mask, in hexadecimal. Bits represent ports 63-0. For example: 0x2 for port 1, 0x6 for ports 1, 2. + +.TP 10 +-e \fImask\fR + +Specifies the counter/error select mask, in hexadecimal. The following lists "Mask - Bit - Location for Counters". Where applicable, location "for Error Info" is presented. Default is all bits set (0xffffffe0). + +.RS + +.IP \(bu +0x80000000 - 31 - Transmit Data (XmitData) +For Error Info: Receive Error Info + +.IP \(bu +0x40000000 - 30 - Receive Data (RcvData) +For Error Info: Excessive Buffer Overrun + +.IP \(bu +0x20000000 - 29 - Transmit Packets (XmitPkts) +For Error Info: Transmit Const Error Info + +.IP \(bu +0x10000000 - 28 - Receive Packets (RcvPkts) +For Error Info: Receive Const Error Info + +.IP \(bu +0x08000000 - 27 - Multicast Transmit Packets (MulticastXmitPkts) +For Error Info: Receive Switch Relay Error Info + +.IP \(bu +0x04000000 - 26 - Multicast Receive Packets (MulticastRcvPkts) +For Error Info: Uncorrectable Error Info + +.IP \(bu +0x02000000 - 25 - Transmit Wait (XmitWait) +For Error Info: FM Configuration Error Info + +.IP \(bu +0x01000000 - 24 - Congestion Discards (CongDiscards) + +.IP \(bu +0x00800000 - 23 - Receive FECN (RcvFECN) + +.IP \(bu +0x00400000 - 22 - Receive BECN (RcvBECN) + +.IP \(bu +0x00200000 - 21 - Transmit Time Congestion (XmitTimeCong) + +.IP \(bu +0x00100000 - 20 - Transmit Time Wasted BW (XmitWastedBW) + +.IP \(bu +0x00080000 - 19 - Transmit Time Wait Data (XmitWaitData) + +.IP \(bu +0x00040000 - 18 - Receive Bubble (RcvBubble) + +.IP \(bu +0x00020000 - 17 - Mark FECN (MarkFECN) + +.IP \(bu +0x00010000 - 16 - Receive Constraint Errors (RcvConstraintErrors) + +.IP \(bu +0x00008000 - 15 - Receive Switch Relay (RcvSwitchRelayErrors) + +.IP \(bu +0x00004000 - 14 - Transmit Discards (XmitDiscards) + +.IP \(bu +0x00002000 - 13 - Transmit Constraint Errors (XmitConstraintErrors) + +.IP \(bu +0x00001000 - 12 - Receive Remote Physical Errors (RcvRemotePhysicalErrors) + +.IP \(bu +0x00000800 - 11 - Local Link Integrity (LocalLinkIntegrityErrors) + +.IP \(bu +0x00000400 - 10 - Receive Errors (RcvErrors) + +.IP \(bu +0x00000200 - 9 - Excessive Buffer Overrun (ExcessiveBufferOverruns) + +.IP \(bu +0x00000100 - 8 - FM Configuration Errors (FMConfigErrors) + +.IP \(bu +0x00000080 - 7 - Link Error Recovery (LinkErrorRecovery) + +.IP \(bu +0x00000040 - 6 - Link Error Downed (LinkDowned) + +.IP \(bu +0x00000020 - 5 - Uncorrectable Errors (UncorrectableErrors) + + +.RE + +.TP 10 +-w \fImask\fR + +Specifies the Virtual Lane Select Mask, in hexadecimal. Bits represent VL number 31-0. For example, 0x1 for VL 0, 0x3 for VL 0,1. Default is none. + +.SH Examples +opapmaquery -o classportinfo +.br + + +.br + +opapmaquery -o getportstatus +.br + +# get data and error counts, local port +.br + + +.br + +opapmaquery -o getdatacounters -n 0x2 +.br + +# get data counts, local port 1 +.br + + +.br + +opapmaquery -o geterrorcounters -n 0x2 +.br + +# get error counts, local port 1 +.br + + +.br + +opapmaquery -o clearportstatus -n 0x2 +.br + +# clear all counters local port 1 +.br + + +.br + +opapmaquery -o geterrorinfo -n 0x2 +.br + +# get error info for local port 1 +.br + + +.br + +opapmaquery -o clearerrorinfo -n 0x2 +.br + +# clear all error info, local port 1 + +.br +opapmaquery -o getdatacounters -l 6 -n 0x7e -w 0x1 +.br + +# for device at LID 6, get data counters on ports 1-6, inclusive of VL 0 data +.br + + +.br + +opapmaquery -o clearportstatus -l 6 -n 0x2 -e 0x1ffff +.br + +# for device at LID 6, on port 1, clear only error counters +.br + + +.br + +opapmaquery -o clearerrorinfo -l 6 -n 0x2 -e 0x04000000 +.br + +# for device at LID 6, on ports 1, clear uncorrectable error info diff --git a/IbaTools/man/opaportconfig.manPage b/IbaTools/man/opaportconfig.manPage new file mode 100644 index 0000000..a26cb1f --- /dev/null +++ b/IbaTools/man/opaportconfig.manPage @@ -0,0 +1,417 @@ +.\" .\" ********************************************************************* +.\" .\" * * +.\" .\" * Copyright 2015-2019, Intel Corporation * +.\" .\" * * +.\" .\" * All Rights Reserved. * +.\" .\" * * +.\" .\" ********************************************************************* + +.TH opaportconfig 1 "Intel Corporation" "Copyright(C) 2015\-2019" "IFSFFCLIRG (Man Page)" +.SH NAME +opaportconfig + + +.PP + +\fB(Host or Switch)\fR +Controls the configuration and state of a specified Intel(R) Omni-Path Host Fabric Interface (HFI) port on the local host or a remote switch. +.PP + +.B NOTE: +This tool is designed for expert users only. Non-expert users should use other tools such as opaenableports, opadisableports and opaportinfo for basic functionality. + +.SH Syntax +opaportconfig [-l \fIlid\fR [-m \fIdest\(ulport\fR]] [-h \fIhfi\fR] [-p \fIport\fR] [-r \fIsecs\fR] [-z] +.br + +[-S \fIstate\fR] [-P \fIphysstate\fR] [-s \fIspeed\fR] [-w \fIwidth\fR] [-c \fILTPCRC\fR] +[-v] [-x] +.br +[-L \fIlid\fR] [< \fIsub command\fR>] +.SH Options + +.TP 10 +--help + +Produces full help text. + +.TP 10 +-l \fIlid\fR + +Specifies the destination LID. Default is local port. + +.TP 10 +-m \fIdest\(ulport\fR + +Specifies the destination port. Default is port with given LID. Used to access switch ports. + +.TP 10 +-h \fIhfi\fR + +Specifies the HFI to send through/to. Default is first HFI. + +.TP 10 +-p \fIport\fR + +Specifies the port to send through/to. Default is first port. + +.TP 10 +\fIsub command\fR + +Specifies the one of the following choices: + +.RS +.TP 10 + +.sp +enable +Enables port. + +.RE + +.RS +.TP 10 + +.sp +disable +Disables port. + +.RE + +.RS +.TP 10 + +.sp +bounce +Bounces port. + +.TP 10 +.BR + +.PP + +.B NOTE: +Bouncing remote ports may cause timeouts. + +.RE + +.RS +.TP 10 + +.sp +ledon +Turns port LED on. + +.RE + +.RS +.TP 10 + +.sp +ledoff +Turns port LED off. + +.RE + + +.SH Configuration Options + +.TP 10 +-r \fIsecs\fR + +Repeats to keep the port down for the specified amount of seconds. + +.TP 10 +-S \fIstate\fR + +Specifies the new state. Default is 0. + +.RS +.TP 10 + +.sp +0 +No-op. + +.RE + +.RS +.TP 10 + +.sp +1 +Down. + +.RE + +.RS +.TP 10 + +.sp +2 +Initiate. + +.RE + +.RS +.TP 10 + +.sp +3 +Armed. + +.RE + +.RS +.TP 10 + +.sp +4 +Active. + +.RE + +.TP 10 +-P \fIphysstate\fR + +Specifies the new physical state. Default is 0. + +.TP 10 +.BR + +.PP + +.B NOTE: +All transitions are valid. + +.RS +.TP 10 + +.sp +0 +No-op. + +.RE + +.RS +.TP 10 + +.sp +2 +Polling. + +.RE + +.RS +.TP 10 + +.sp +3 +Disabled. + +.RE + +.RS +.TP 10 + +.sp +11 +Phy-Test. Current physstate must be disabled. + +.RE + +.TP 10 +-s \fIspeed\fR + +Specifies the new link speeds enabled. Default is 0. To enable multiple speeds, use the sum of the desired speeds. + +.RS +.TP 10 + +.sp +0 +No-op. + +.RE + +.RS +.TP 10 + +.sp +2 +0x0002 - 25 Gb/s. + +.RE + +.TP 10 +-w \fIwidth\fR + +Specifies the new link widths enabled. Default is 0. To enable multiple widths, use sum of desired widths. + +.RS +.TP 10 + +.sp +0 +No-op. + +.RE + +.RS +.TP 10 + +.sp +1 +0x01 - 1x. + +.RE + +.RS +.TP 10 + +.sp +2 +0x02 - 2x. + +.RE + +.RS +.TP 10 + +.sp +4 +0x04 - 3x. + +.RE + +.RS +.TP 10 + +.sp +8 +0x08 - 4x. + +.RE + +.TP 10 +-c \fILTPCRC\fR + +Specifies the new LTP CRCs enabled. Default is 0. +.br +To enable multiple LTP CRCs, use sum of desired LTP CRCs. + +.RS +.TP 10 + +.sp +0 +No-op. + +.RE + +.RS +.TP 10 + +.sp +1 +0x1 - 14-bit LTP CRC mode. + +.RE + +.RS +.TP 10 + +.sp +2 +0x2 - 16-bit LTP CRC mode. + +.RE + +.RS +.TP 10 + +.sp +4 +0x4 - 48-bit LTP CRC mode. +.RE + +.RS +.TP 10 + +.sp +8 +0x8 - 12/16 bits per lane LTP CRC mode. + +.RE + + +.SH -h and -p options permit a variety of selections: + +.TP 10 +-h 0 + +First active port in system (Default). + +.TP 10 +-h 0 -p 0 + +First active port in system. + +.TP 10 +-h \fIx\fR + +First active port on HFI \fIx\fR. + +.TP 10 +-h \fIx\fR \fI\fR-p 0 + +First active port on HFI \fIx\fR. + +.TP 10 +-h 0 -p \fIy\fR + +Port \fIy\fR within system (no matter which ports are active). + +.TP 10 +-h \fIx\fR \fI\fR-p \fIy\fR + +HFI \fIx\fR, port \fIy\fR. + + +.SH Debug Options + +.TP 10 +-v + +Verbose output. Additional invocations turn on debugging, openib debugging, and libibumad debugging. + +.TP 10 +-z + +Does not get port information first; clears most port attributes. + +.TP 10 +-L \fIlid\fR + +Sets PortInfo.LID = lid. + +.SH Examples +opaportconfig -w 1 +.br + +opaportconfig -p 1 -h 2 -w 3 +.SH Description + +.PP +Port configuration is transient in nature. If the given host is rebooted or its Intel(R) Omni-Path Fabric Stack is restarted, the port reverts to its default configuration and state. Typically, the default state is to have the port enabled with all speeds and widths supported by the given HFI port. +.PP +To access switch ports using this command, the -l and -m options must be given. The -l option specifies the lid of switch port 0 (the logical management port for the switch) and -m specifies the actual switch port to access. +.PP + +.B NOTE: +The /etc/init.d/opaportconfig script is provided as an example of changing port speed every time the server boots. This script can be edited, then scheduled, using chkconfig to control link settings on any set of HFI ports. + +.PP + +.B CAUTION: +When using this command to disable or reconfigure switch ports, if the final port in the path between the Fabric Management Node and the switch is disabled or fails to come online, then opaenableports is not able to reenable it. In this case, the switch CLI and/or a switch reboot may be needed to correct the situation. diff --git a/IbaTools/man/opaportinfo.manPage b/IbaTools/man/opaportinfo.manPage new file mode 100644 index 0000000..b38f927 --- /dev/null +++ b/IbaTools/man/opaportinfo.manPage @@ -0,0 +1,91 @@ +.\" .\" ********************************************************************* +.\" .\" * * +.\" .\" * Copyright 2015-2019, Intel Corporation * +.\" .\" * * +.\" .\" * All Rights Reserved. * +.\" .\" * * +.\" .\" ********************************************************************* + +.TH opaportinfo 1 "Intel Corporation" "Copyright(C) 2015\-2019" "IFSFFCLIRG (Man Page)" +.SH NAME +opaportinfo + + +.PP + +\fB(Host or Switch)\fR +Displays configuration and state of a specified Intel(R) Omni-Path Host Fabric Interface (HFI) port on the local host or a remote switch. +.SH Syntax +opaportinfo [-l \fIlid\fR [-m \fIdest\(ulport\fR]] [-h \fIhfi\fR] [-p \fIport\fR] [-v] +.SH Options + +.TP 10 +-l \fIlid\fR + +Specifies the destination LID. Default is local port. + +.TP 10 +-m \fIdest\(ulport\fR + +Specifies the destination port. Default is port with given LID. Useful to access switch ports. + +.TP 10 +-h \fIhfi\fR + +Specifies the HFI to send through/to. Default is first HFI. + +.TP 10 +-p \fIport\fR + +Specifies the port to send through/to. Default is first port. + + +.SH -h and -p options permit a variety of selections: + +.TP 10 +-h 0 + +First active port in system (Default). + +.TP 10 +-h 0 -p 0 + +First active port in system. + +.TP 10 +-h \fIx\fR + +First active port on HFI \fIx\fR. + +.TP 10 +-h \fIx\fR \fI\fR-p 0 + +First active port on HFI \fIx\fR. + +.TP 10 +-h 0 -p \fIy\fR + +Port \fIy\fR within system (no matter which ports are active). + +.TP 10 +-h \fIx\fR \fI\fR-p \fIy\fR + +HFI \fIx\fR, port \fIy\fR. + + +.SH Debug Options + +.TP 10 +-v + +Specifies the verbose output. Additional invocations (-v -v ...) turn on debugging, openib debugging, and libibumad debugging. + +.SH Examples +opaportinfo -p 1 +.br + +opaportinfo -p 2 -h 2 -l 5 -m 18 +.SH Description + +.PP +To access switch ports using this command, the -l and -m options must be given. The -l option specifies the LID of switch port 0 (the logical management port for the switch) and -m specifies the actual switch port to access. diff --git a/IbaTools/man/opareport.manPage b/IbaTools/man/opareport.manPage new file mode 100644 index 0000000..6e4d490 --- /dev/null +++ b/IbaTools/man/opareport.manPage @@ -0,0 +1,948 @@ +.\" .\" ********************************************************************* +.\" .\" * * +.\" .\" * Copyright 2015-2019, Intel Corporation * +.\" .\" * * +.\" .\" * All Rights Reserved. * +.\" .\" * * +.\" .\" ********************************************************************* + +.TH opareport 8 "Intel Corporation" "Copyright(C) 2015\-2019" "IFSFFCLIRG (Man Page)" +.SH NAME +opareport + + +.PP + +\fB(All)\fR +Provides powerful fabric analysis and reporting capabilities. Must be run on a host connected to the Intel(R) Omni-Path Fabric with the Intel(R) Omni-Path Fabric Suite FastFabric Toolset installed. +.SH Syntax +opareport [-v][-q] [-h \fIhfi\fR] [-p \fIport\fR] [--timeout] [-o \fIreport\fR] +.br +[-d \fIdetail\fR] [-P|-H] +[-N] [-x] [-X \fIsnapshot\(ulinput\fR] [-T \fItopology\(ulinput\fR] +.br +[-s] [-r] [-V] [-i \fIseconds\fR] +[-b \fIdate\(ultime\fR] [-e \fIdate\(ultime\fR] [-C] [-a] +.br +[-m] [-M] [-A] [-c \fIfile\fR] [-L] [-F \fIpoint\fR] +[-S \fIpoint\fR] [-D \fIpoint\fR] [-Q] +.SH Options + +.TP 10 +--help + +Produces full help text. + +.TP 10 +-v/--verbose + +Returns verbose output. + +.TP 10 +-q/--quiet + +Disables progress reports. + +.TP 10 +-h/--hfi \fIhfi\fR + +Specifies the HFI, numbered 1..n. Using 0 specifies that the -p \fIport\fR port is a system-wide port number. Default is 0. + +.TP 10 +-p/--port \fIport\fR + +Specifies the port, numbered 1..n. Using 0 specifies the first active port. Default is 0. + +.TP 10 +--timeout + +Specifies the timeout (wait time for response) in ms. Default is 1000 ms. + +.TP 10 +-o/--output \fIreport\fR + +Specifies the report type for output. Refer to +\fIReport Types\fR +for details. + +.TP 10 +-d/--detail \fIlevel\fR + +Specifies the level of detail 0-n for output. Default is 2. + +.TP 10 +-P/--persist + +Only includes data persistent across reboots. + +.TP 10 +-H/--hard + +Only includes permanent hardware data. + +.TP 10 +-N/--noname + +Omits node and IOC names. + +.TP 10 +-x/--xml + +Produces output in XML. + +.TP 10 +-X/--infile \fIsnapshot\(ulinput\fR + +Generates a report using the data in the snapshot\(ulinput file. snapshot\(ulinput must have been generated during a previous -o \fIsnapshot\fR run. When used, the -s, -i, -C, and -a options are ignored. \[aq]-\[aq] may be used as the snapshot\(ulinput to specify stdin. + +.TP 10 +-T/--topology \fItopology\(ulinput\fR + +Uses topology\(ulinput file to augment and verify fabric information. When used, various reports can be augmented with information not available electronically (such as cable labels). \[aq]-\[aq] may be used to specify stdin. + +.TP 10 +-s/--stats + +Gets performance statistics for all ports. + +.TP 10 +-i/--interval \fIseconds\fR + +Obtains performance statistics over interval \fIseconds\fR. Clears all statistics, waits interval \fIseconds\fR, then generates report. Implies -s option. + +.TP 10 +-b/--begin \fIdate\(ultime\fR + +Obtains performance stats beginning at \fIdate\(ultime\fR. Implies -s option. +.RS + +.IP \(bu +If -b/--begin and -e/--end are specified, the performance stats are provided over the specified interval. +.IP \(bu +If only -b/--begin is specified, the absolute value of the performance stats at the specified time is provided. + +.RE +\fIdate\(ultime\fR may be a time entered as HH:MM[:SS] or date as mm/dd/YYYY, dd.mm.YYYY, YYYY-mm-dd or date followed by time; for example, "2016-07-04 14:40". Relative times are taken as "x [second|minute|hour|day](s) ago. + +.TP 10 +-e/--end \fIdate\(ultime\fR + +Obtains performance stats ending at \fIdate\(ultime\fR. Implies -s option. + +.RS + +.IP \(bu +If -b/--begin and -e/--end are specified, the performance stats are provided over the specified interval. +.IP \(bu +If only -e/--end is specified, the absolute value of the performance stats at the specified time is provided. + +.RE + +.IP +\fIdate\(ultime\fR may be a time entered as HH:MM[:SS] or date as mm/dd/YYYY, dd.mm.YYYY, YYYY-mm-dd or date followed by time; for example, "2016-07-04 14:40". Relative times are taken as "x [second|minute|hour|day](s) ago. +.TP 10 +-C/--clear + +Clears performance statistics for all ports. Only statistics with error thresholds are cleared. A clear occurs after generating the report. + +.TP 10 +-a/--clearall + +Clears all performance statistics for all ports. + +.TP 10 +-m/--smadirect + +Accesses fabric information directly from SMA. + +.TP 10 +-M/--pmadirect + +Accesses performance statistics using direct PMA. + +.TP 10 +-A/--allports + +Gets PortInfo for down switch ports. Uses direct SMA to get this data. If used with -M, also gets PMA stats for down switch ports. + +.TP 10 +-c/--config \fIfile\fR + +Specifies the error thresholds configuration file. Default is /etc/opa/opamon.conf file. + +.TP 10 +-L/--limit + +Limits operation to exact specified focus with -F for port error counters check (-o \fIerrors\fR) and port counters clear (-C or -i). Normally, the neighbor of each selected port is also checked/cleared. Does not affect other reports. + +.TP 10 +-F/--focus \fIpoint\fR + +Specifies the focus area for report. + +.IP +Limits output to reflect a subsection of the fabric. May not work with all reports. (For example, route, mcgroups, and the verify* reports may ignore the option or not generate useful results.) +.TP 10 +-S/--src \fIpoint\fR + +Specifies the source for trace route. Default is local port. + +.TP 10 +-D/--dest \fIpoint\fR + +Specifies the destination for trace route. + +.TP 10 +-Q/--quietfocus + +Excludes focus description from report. + + +.SH -h and -p options permit a variety of selections: + +.TP 10 +-h 0 + +First active port in system (Default). + +.TP 10 +-h 0 -p 0 + +First active port in system. + +.TP 10 +-h \fIx\fR + +First active port on HFI \fIx\fR. + +.TP 10 +-h \fIx\fR \fI\fR-p 0 + +First active port on HFI \fIx\fR. + +.TP 10 +-h 0 -p \fIy\fR + +Port \fIy\fR within system (no matter which ports are active). + +.TP 10 +-h \fIx\fR \fI\fR-p \fIy\fR + +HFI \fIx\fR, port \fIy\fR. + + +.SH Snapshot-Specific Options + +.TP 10 +-r/--routes + +Gets routing tables for all switches. + +.TP 10 +-V/--vltables + +Gets the P-Key tables for all nodes and the QoS VL-related tables for all ports. + + +.SH Report Types + +.TP 10 +comps + +Summary of all systems and SMs in fabric. + +.TP 10 +brcomps + +Brief summary of all systems and SMs in fabric. + +.TP 10 +nodes + +Summary of all node types and SMs in fabric. + +.TP 10 +brnodes + +Brief summary of all node types and SMs in fabric. + +.TP 10 +ious + +Summary of all IO units in the fabric. + +.TP 10 +lids + +Summary of all LIDs in the fabric. + +.TP 10 +linkinfo + +Summary of all links with LIDs in the fabric. + +.TP 10 +links + +Summary of all links. + +.TP 10 +extlinks + +Summary of links external to systems. + +.TP 10 +filinks + +Summary of links to FIs. + +.TP 10 +islinks + +Summary of inter-switch links. + +.TP 10 +extislinks + +Summary of inter-switch links external to systems. + +.TP 10 +slowlinks + +Summary of links running slower than expected. + +.TP 10 +slowconfiglinks + +Summary of links configured to run slower than supported, includes slowlinks. + +.TP 10 +slowconnlinks + +Summary of links connected with mismatched speed potential, includes slowconfiglinks. + +.TP 10 +misconfiglinks + +Summary of links configured to run slower than supported. + +.TP 10 +misconnlinks + +Summary of links connected with mismatched speed potential. + +.TP 10 +errors + +Summary of links whose errors exceed counts in the configuration file. + +.TP 10 +otherports + +Summary of ports not connected to the fabric. + +.TP 10 +linear + +Summary of linear forwarding data base (FDB) for each switch. + +.TP 10 +mcast + +Summary of multicast FDB for each switch in the fabric. + +.TP 10 +mcgroups + +Summary of multicast groups. + +.IP +When used in conjunction with -d, the following report details are possible: +.RS + +.IP \(bu +-d0 : Shows the number of multicast groups +.IP \(bu +-d1 : Shows a list of multicast groups +.IP \(bu +-d2 : Shows a list of members per multicast group + +.RE + +.IP +This report can be used with option -X. +.TP 10 +portusage + +Summary of ports referenced in linear FDB for each switch, broken down by NodeType of DLID. + +.TP 10 +pathusage + +Summary of number of FI to FI paths routed through each switch port. + +.TP 10 +treepathusage + +Analysis of number of FI to FI paths routed through each switch port for a FAT tree. + +.TP 10 +portgroups + +Summary of adaptive routing port groups for each switch. + +.TP 10 +quarantinednodes + +Summary of quarantined nodes. + +.TP 10 +validateroutes + +Validates all routes in the fabric. + +.TP 10 +validatevlroutes + +Validates all routes in the fabric using SLSC, SCSC, and SCVL tables. + +.TP 10 +validatepgs + +Validates all port groups in the fabric. + +.TP 10 +validatecreditloops + +Validates topology configuration of the fabric to identify any existing credit loops. + +.TP 10 +validatevlcreditloops + +Validates topology configuration of the fabric including SLSC, SCSC, and SCVL tables to identify any existing credit loops. + +.TP 10 +validatemcroutes + +Validates multicast routes of the fabric to identify loops in multicast forwarding tables and detect MFT-multicast membership inconsistencies. + +.TP 10 +vfinfo + +Summary of virtual fabric (vFabric) information. + +.TP 10 +vfmember + +Summary of vFabric membership information. + +.TP 10 +dgmember + +Summary of DeviceGroup membership information. + +.TP 10 +verifyfis + +Compares fabric (or snapshot) FIs to supplied topology and identifies differences and omissions. + +.TP 10 +verifysws + +Compares fabric (or snapshot) switches to supplied topology and identifies differences and omissions. + +.TP 10 +verifynodes + +Returns verifyfis and verifysws reports. + +.TP 10 +verifysms + +Compares fabric (or snapshot) SMs to supplied topology and identifies differences and omissions. + +.TP 10 +verifylinks + +Compares fabric (or snapshot) links to supplied topology and identifies differences and omissions. + +.TP 10 +verifyextlinks + +Compares fabric (or snapshot) links to supplied topology and identifies differences and omissions. Limits analysis to links external to systems. + +.TP 10 +verifyfilinks + +Compares fabric (or snapshot) links to supplied topology and identify differences and omissions. Limits analysis to links to FIs. + +.TP 10 +verifyislinks + +Compares fabric (or snapshot) links to supplied topology and identify differences and omissions. Limits analysis to inter-switch links. + +.TP 10 +verifyextislinks + +Compares fabric (or snapshot) links to supplied topology and identify differences and omissions. Limits analysis to inter-switch links external to systems. + +.TP 10 +verifyall + +Returns verifyfis, verifysws, verifysms, and verifylinks reports. + +.TP 10 +all + +Returns comps, nodes, ious, links, extlinks, slowconnlinks, and errors reports. + +.TP 10 +route + +Traces route between -S and -D points. + +.TP 10 +bfrctrl + +Reports Buffer Control Tables for all ports. + +.TP 10 +snapshot + +Outputs snapshot of the fabric state for later use as \fIsnapshot\(ulinput\fR. This implies -x. May not be combined with other reports. When selected, -F, -P, -H, and -N options are ignored. + +.TP 10 +topology + +Outputs the topology of the fabric for later use as \fItopology\(ulinput\fR. This implies -x. May not be combined with other reports. Use with detail level 3 or more to get Port element under Node in output xml. + +.TP 10 +none + +No report, useful to clear statistics. + + +.SH Point Syntax + +.TP 10 +gid:\fIvalue\fR + +\fIvalue\fR is numeric port GID of form: subnet:guid. + +.TP 10 +lid:\fIvalue\fR + +\fIvalue\fR is numeric LID. + +.TP 10 +lid:value:node + +\fIvalue\fR is numeric LID, selects entire node with given LID. + +.TP 10 +lid:\fIvalue\fR:port:\fIvalue2\fR + +\fIvalue\fR is numeric LID of node, \fIvalue2\fR is port number. + +.TP 10 +portguid:\fIvalue\fR + +\fIvalue\fR is numeric port GUID. + +.TP 10 +nodeguid:\fIvalue\fR + +\fIvalue\fR is numeric node GUID. + +.TP 10 +nodeguid:\fIvalue1\fR:port:\fIvalue2\fR + +\fIvalue1\fR is numeric node GUID, \fIvalue2\fR is port number. + +.TP 10 +iocguid:\fIvalue\fR + +\fIvalue\fR is numeric IOC GUID. + +.TP 10 +iocguid:\fIvalue1\fR:port:\fIvalue2\fR + +\fIvalue1\fR is numeric IOC GUID, \fIvalue2\fR is port number. + +.TP 10 +systemguid:\fIvalue\fR + +\fIvalue\fR is numeric system image GUID. + +.TP 10 +systemguid:\fIvalue1\fR:port:\fIvalue2\fR + +\fIvalue1\fR is the numeric system image GUID, \fIvalue2\fR is port number. + +.TP 10 +ioc:\fIvalue\fR + +\fIvalue\fR is IOC Profile ID String (IOC Name). + +.TP 10 +ioc:\fIvalue1\fR:port:\fIvalue2\fR + +\fIvalue1\fR is IOC Profile ID String (IOC Name), \fIvalue2\fR is port number. + +.TP 10 +iocpat:\fIvalue\fR + +\fIvalue\fR is glob pattern for IOC Profile ID String (IOC Name). + +.TP 10 +iocpat:\fIvalue1\fR:port:\fIvalue2\fR + +\fIvalue1\fR is glob pattern for IOC Profile ID String (IOC Name), \fIvalue2\fR is port number. + +.TP 10 +ioctype:\fIvalue\fR + +\fIvalue\fR is IOC type (SRP or OTHER). + +.TP 10 +ioctype:\fIvalue1\fR:port:\fIvalue2\fR + +\fIvalue1\fR is IOC type (SRP or OTHER); \fIvalue2\fR is port number. + +.TP 10 +node:\fIvalue\fR + +\fIvalue\fR is node description (node name). + +.TP 10 +node:\fIvalue1\fR:port:\fIvalue2\fR + +\fIvalue1\fR is node description (node name), \fIvalue2\fR is port number. + +.TP 10 +nodepat:\fIvalue\fR + +\fIvalue\fR is glob pattern for node description (node name). + +.TP 10 +nodepat:\fIvalue1\fR:port:\fIvalue2\fR + +\fIvalue1\fR is the glob pattern for the node description (node name), \fIvalue2\fR is port number. + +.TP 10 +nodedetpat:\fIvalue\fR + +\fIvalue\fR is glob pattern for node details. + +.TP 10 +nodedetpat:\fIvalue1\fR:port:\fIvalue2\fR + +\fIvalue1\fR is the glob pattern for the node details, \fIvalue2\fR is port number. + +.TP 10 +nodetype:\fIvalue\fR + +\fIvalue\fR is node type (SW or FI). + +.TP 10 +nodetype:\fIvalue1\fR:port:\fIvalue2\fR + +\fIvalue1\fR is node type (SW or FI), \fIvalue2\fR is port number. + +.TP 10 +rate:\fIvalue\fR + +\fIvalue\fR is string for rate (25g, 50g, 75g, 100g), omits switch mgmt port 0. + +.TP 10 +portstate:\fIvalue\fR + +\fIvalue\fR is a string for state (down, init, armed, active, notactive, initarmed). + +.TP 10 +portphysstate:\fIvalue\fR + +\fIvalue\fR is a string for PHYs state (polling, disabled, training, linkup, recovery, offline, test) + +.TP 10 +mtucap:\fIvalue\fR + +\fIvalue\fR is MTU size (2048, 4096, 8192, 10240), omits switch mgmt port 0. + +.TP 10 +labelpat:\fIvalue\fR + +\fIvalue\fR is glob pattern for cable label. + +.TP 10 +lengthpat:\fIvalue\fR + +\fIvalue\fR is glob pattern for cable length. + +.TP 10 +cabledetpat:\fIvalue\fR + +\fIvalue\fR is glob pattern for cable details. + +.TP 10 +cabinflenpat:\fIvalue\fR + +\fIvalue\fR is glob pattern for cable info length. + +.TP 10 +cabinfvendnamepat:\fIvalue\fR + +\fIvalue\fR is glob pattern for cable info vendor name. + +.TP 10 +cabinfvendpnpat:\fIvalue\fR + +\fIvalue\fR is glob pattern for cable info vendor part number. + +.TP 10 +cabinfvendrevpat:\fIvalue\fR + +\fIvalue\fR is glob pattern for cable info vendor revision. + +.TP 10 +cabinfvendsnpat:\fIvalue\fR + +\fIvalue\fR is glob pattern for cable info vendor serial number. + +.TP 10 +cabinftype:\fIvalue\fR + +\fIvalue\fR is either optical, passive\(ulcopper, active\(ulcopper, or unknown. + +.TP 10 +linkdetpat:\fIvalue\fR + +\fIvalue\fR is glob pattern for link details. + +.TP 10 +portdetpat:\fIvalue\fR + +\fIvalue\fR is glob pattern for port details. + +.TP 10 +sm + +Specifies the master subnet manager (SM). + +.TP 10 +smdetpat:\fIvalue\fR + +\fIvalue\fR is glob pattern for SM details. + +.TP 10 +route:\fIpoint1\fR:\fIpoint2\fR + +Specifies all ports along the routes between the two given points. + +.TP 10 +led:\fIvalue\fR + +\fIvalue\fR is either on or off for LED port beacon. + +.TP 10 +linkqual:\fIvalue\fR + +Specifies the ports with a link quality equal to \fIvalue\fR. + +.TP 10 +linkqualLE:\fIvalue\fR + +Specifies the ports with a link quality less than or equal to \fIvalue\fR. + +.TP 10 +linkqualGE:\fIvalue\fR + +Specifies the ports with a link quality greater than or equal to \fIvalue\fR. + +.TP 10 +nodepatfile:\fIFILENAME\fR + +Specifies the name of file with the list of nodepats or node descriptions. + +.TP 10 +nodepairpatfile:\fIFILENAME\fR + +Specifies the name of file with the list of node pairs, separated by a colon. + +.TP 10 +ldr + +Specifies the ports with a non-zero link down reason or neighbor link down reason. + +.TP 10 +ldr:\fIvalue\fR + +Specifies the ports with a link down reason or neighbor link down reason equal to \fIvalue\fR. + +.SH Examples + +.PP +opareport can generate hundreds of different reports. Commonly generated reports include the following: +.PP + +.br + opareport -o comps -d 3 +.br + + opareport -o errors -o slowlinks +.br + + opareport -o nodes -F portguid:0x00117500a000447b +.br + + opareport -o nodes -F nodeguid:0x001175009800447b:port:1 +.br + + opareport -o nodes -F nodeguid:0x001175009800447b +.br + + opareport -o nodes -F \[aq]node:duster hfi1\(ul0\[aq] +.br + + opareport -o nodes -F \[aq]node:duster hfi1\(ul0:port:1\[aq] +.br + + opareport -o nodes -F \[aq]nodepat:d*\[aq] +.br + + opareport -o nodes -F \[aq]nodepat:d*:port:1\[aq] +.br + + opareport -o nodes -F \[aq]nodedetpat:compute*\[aq] +.br + + opareport -o nodes -F \[aq]nodedetpat:compute*:port:1\[aq] +.br + + opareport -o nodes -F nodetype:FI +.br + + opareport -o nodes -F nodetype:FI:port:1 +.br + + opareport -o nodes -F lid:1 +.br + + opareport -o nodes -F led:on + opareport -o nodes -F led:off + opareport -o nodes -F lid:1:node +.br + + opareport -o nodes -F lid:1:port:2 +.br + + opareport -o nodes -F gid:0xfe80000000000000:0x00117500a000447b +.br + + opareport -o nodes -F systemguid:0x001175009800447b +.br + + opareport -o nodes -F systemguid:0x001175009800447b:port:1 +.br + + opareport -o nodes -F iocguid:0x00117501300001e0 +.br + + opareport -o nodes -F iocguid:0x00117501300001e0:port:2 +.br + + opareport -o nodes -F \[aq]ioc:Chassis 0x001175005000010C, Slot 2, IOC 1\[aq] +.br + + opareport -o nodes -F \[aq]ioc:Chassis 0x001175005000010C, Slot 2, IOC 1:port:2\[aq] +.br + + opareport -o nodes -F \[aq]iocpat:*Slot 2*\[aq] +.br + + opareport -o nodes -F \[aq]iocpat:*Slot 2*:port:2\[aq] +.br + + opareport -o nodes -F ioctype:SRP + opareport -o nodes -F ioctype:SRP:port:2 +.br + + opareport -o extlinks -F rate:100g +.br + + opareport -o extlinks -F portstate:armed +.br + + opareport -o extlinks -F portphysstate:linkup +.br + + opareport -o extlinks -F \[aq]labelpat:S1345*\[aq] +.br + + opareport -o extlinks -F \[aq]lengthpat:11m\[aq] +.br + + opareport -o extlinks -F \[aq]cabledetpat:*hitachi*\[aq] +.br + + opareport -o extlinks -F \[aq]linkdetpat:*core ISL*\[aq] +.br + + opareport -o extlinks -F \[aq]portdetpat:*mgmt*\[aq] +.br + + opareport -o links -F mtucap:2048 +.br + + opareport -o nodes -F sm +.br + + opareport -o nodes -F \[aq]smdetpat:primary*\[aq] +.br + + opareport -o nodes -F \[aq]route:node:duster hfi1\(ul0:node:cuda hfi1\(ul0\[aq] +.br + + opareport -o nodes -F \[aq]route:node:duster hfi1\(ul0:port:1:node:cuda hfi1\(ul0:port:2\[aq] +.br + + opareport -o treepathusage -F nodepairpatfile:FILENAME +.br + + opareport -o pathusage -F nodepatfile:FILENAME +.br + + opareport -s -o snapshot > file +.br + + opareport -o topology > topology.xml +.br + + opareport -o errors -X file +.br + + opareport -s --begin "2 days ago" +.br + + opareport -s --begin "12:30" --end "14:00" +.br + + opareport -o linkinfo -x > file + +.br + + +.SH Other Information + +.PP +opareport also supports operation with the Fabric Manager Performance Manager (PM)/Performance Manager Agent (PMA). When opareport detects the presence of a PM, it automatically issues any required PortCounter queries and clears to the PM to access the PMs running totals. If a PM is not detected, then opareport directly accesses the PMAs on all the nodes. The -M option can force access to the PMA even if a PM is present. +.PP +opareport takes advantage of these interfaces to obtain extensive information about the fabric from the subnet manager and the end nodes. Using this information, opareport is able to cross-reference it and produce analysis greatly beyond what any single subnet manager request could provide. As such, it exceeds the capabilities previously available in tools such as opasaquery and opafabricinfo. +.PP +opareport obtains and displays counters from the Fabric Manager PM/PA or directly from the fabric PMAs using the -M option. +.PP +opareport internally cross-references all this information so its output can be in user-friendly form. Reports include GUIDs, LIDs, and names for components. Obviously, these reports are easiest to read if the end user has taken the time to provide unique names for all the components in the fabric (node names and IOC names). All Intel components support this capability. For hosts, the node names are automatically assigned based on the network host name of the server. For switches and line cards, the names can be assigned using the element managers for each component. +.PP +Each run of opareport obtains up-to-date information from the fabric. At the start of the run opareport takes a few seconds to obtain all the fabric data, then it is output to stdout. The reports are sorted by GUIDs and other permanent information so they can be rerun in the future and produce output in the same order even if components have been rebooted. This is useful for comparison using simple tools like diff. opareport permits multiple reports to be requested for a single run (for example, one of each report type). +.PP +By default, opareport uses the first active port on the local system. However, if the Management Node is connected to more than one fabric (for example, a subnet), the Intel(R) Omni-Path Host Fabric Interface (HFI) and port may be specified to select the fabric to analyze. diff --git a/IbaTools/man/opareports.manPage b/IbaTools/man/opareports.manPage new file mode 100644 index 0000000..e32fc75 --- /dev/null +++ b/IbaTools/man/opareports.manPage @@ -0,0 +1,1047 @@ +.\" .\" ********************************************************************* +.\" .\" * * +.\" .\" * Copyright 2015-2019, Intel Corporation * +.\" .\" * * +.\" .\" * All Rights Reserved. * +.\" .\" * * +.\" .\" ********************************************************************* + +.TH opareports 8 "Intel Corporation" "Copyright(C) 2015\-2019" "IFSFFCLIRG (Man Page)" +.SH NAME +opareports + + +.PP + +\fB(All)\fR +opareports is a front end to opareport that provides many of the same options and capabilities. It can also run a report against multiple fabrics or subnets (for example, local host HFI ports). opareports can use an input file to augment the reports using additional details from the topology\(ulinput file. +.SH Syntax +opareports [-t \fIportsfile\fR] [-p \fIports\fR] [-T \fItopology\(ulinput\fR] [opareport \fIarguments\fR] +.SH Options + +.TP 10 +--help + +Produces full help text. +.TP 10 +-t \fIportsfile\fR + +Specifies the file with list of local HFI ports used to access fabric for analysis. Default is /etc/opa/ports file. +.TP 10 +-p \fIports\fR + +Specifies the list of local HFI ports used to access fabric for counter clear. + +.IP +Default is first active port. The first HFI in the system is 1. The first port on an HFI is 1. Uses the format hfi:port, +.br +for example: +.RS +.TP 10 + +.sp +0:0 +First active port in system. + +.RE + +.RS +.TP 10 + +.sp +0:y +Port \fIy\fR within system. + +.RE + +.RS +.TP 10 + +.sp +x:0 +First active port on HFI \fIx\fR. + +.RE + +.RS +.TP 10 + +.sp +x:y +HFI \fIx\fR, port \fIy\fR. + +.RE + +.TP 10 +-T \fItopology\(ulinput\fR + +Specifies the name of a topology input file to use. The filename may have %P as a marker which is replaced with the hfi:port being operated on, such as 0:0 or 1:2. The default filename is specified by \fBFF\(ulTOPOLOGY\(ulFILE\fR as /etc/opa/topology.%P.xml. If -T NONE is specified, no topology input file is used. +.TP 10 +opareport \fIarguments\fR + +Options are passed to opareport. + +.IP +Specifies any of the other opareport arguments listed below (see +\fIopareport Options\fR +):opareport [-v][-q] [-h \fIhfi\fR] [-p \fIport\fR] [--timeout] +.br + +[-o \fIreport\fR][-d \fIdetail\fR] [-P|-H] [-N] [-x] +.br + +[-X \fIsnapshot\(ulinput\fR][-T \fItopology\(ulinput\fR] [-s] [-r] [-V] +.br + +[-i \fIseconds\fR][-b \fIdate\(ultime\fR] [-e \fIdate\(ultime\fR] [-C] [-a] +.br + +[-m] [-M] [-A][-c \fIfile\fR] [-L] [-F \fIpoint\fR] [-S \fIpoint\fR] +.br + +[-D \fIpoint\fR] [-Q] +.TP 10 +.BR + +.PP + +.B NOTE: +When using opareport arguments, regard the following: +.RS + +.IP \(bu +The -h and -X options are not available. +.IP \(bu +The meaning of -p is different for opareports than opareport. +.IP \(bu +When run against multiple fabrics, the -x and -o snapshot options are not available. +.IP \(bu +When run against multiple fabrics, the -F option is applied to all fabrics. + +.RE + + +.SH Examples +opareports +.br + +opareports -p \[aq]1:1 2:1\[aq] +.SH Environment Variables + +.PP +The following environment variables are also used by this command: +.TP 10 +\fBPORTS\fR + +List of ports, used in absence of -t and -p. +.TP 10 +\fBPORTS\(ulFILE\fR + +File containing list of ports, used in absence of -t and -p. +.TP 10 +\fBFF\(ulTOPOLOGY\(ulFILE\fR + +File containing topology\(ulinput (may have %P marker in filename), used in absence of -T. + +.SH opareport Options + +.PP +For reference: +.TP 10 +--help + +Produces full help text. + +.TP 10 +-v/--verbose + +Returns verbose output. + +.TP 10 +-q/--quiet + +Disables progress reports. + +.TP 10 +-h/--hfi \fIhfi\fR + +Specifies the HFI, numbered 1..n. Using 0 specifies that the -p \fIport\fR port is a system-wide port number. Default is 0. + +.TP 10 +-p/--port \fIport\fR + +Specifies the port, numbered 1..n. Using 0 specifies the first active port. Default is 0. + +.TP 10 +--timeout + +Specifies the timeout (wait time for response) in ms. Default is 1000 ms. + +.TP 10 +-o/--output \fIreport\fR + +Specifies the report type for output. Refer to +\fIopareport Report Types\fR +for details. + +.TP 10 +-d/--detail \fIlevel\fR + +Specifies the level of detail 0-n for output. Default is 2. + +.TP 10 +-P/--persist + +Only includes data persistent across reboots. + +.TP 10 +-H/--hard + +Only includes permanent hardware data. + +.TP 10 +-N/--noname + +Omits node and IOC names. + +.TP 10 +-x/--xml + +Produces output in XML. + +.TP 10 +-X/--infile \fIsnapshot\(ulinput\fR + +Generates a report using the data in the snapshot\(ulinput file. snapshot\(ulinput must have been generated during a previous -o \fIsnapshot\fR run. When used, the -s, -i, -C, and -a options are ignored. \[aq]-\[aq] may be used as the snapshot\(ulinput to specify stdin. + +.TP 10 +-T/--topology \fItopology\(ulinput\fR + +Uses topology\(ulinput file to augment and verify fabric information. When used, various reports can be augmented with information not available electronically (such as cable labels). \[aq]-\[aq] may be used to specify stdin. + +.TP 10 +-s/--stats + +Gets performance statistics for all ports. + +.TP 10 +-i/--interval \fIseconds\fR + +Obtains performance statistics over interval \fIseconds\fR. Clears all statistics, waits interval \fIseconds\fR, then generates report. Implies -s option. + +.TP 10 +-b/--begin \fIdate\(ultime\fR + +Obtains performance stats beginning at \fIdate\(ultime\fR. Implies -s option. +.RS + +.IP \(bu +If -b/--begin and -e/--end are specified, the performance stats are provided over the specified interval. +.IP \(bu +If only -b/--begin is specified, the absolute value of the performance stats at the specified time is provided. + +.RE +\fIdate\(ultime\fR may be a time entered as HH:MM[:SS] or date as mm/dd/YYYY, dd.mm.YYYY, YYYY-mm-dd or date followed by time; for example, "2016-07-04 14:40". Relative times are taken as "x [second|minute|hour|day](s) ago. + +.TP 10 +-e/--end \fIdate\(ultime\fR + +Obtains performance stats ending at \fIdate\(ultime\fR. Implies -s option. + +.RS + +.IP \(bu +If -b/--begin and -e/--end are specified, the performance stats are provided over the specified interval. +.IP \(bu +If only -e/--end is specified, the absolute value of the performance stats at the specified time is provided. + +.RE + +.IP +\fIdate\(ultime\fR may be a time entered as HH:MM[:SS] or date as mm/dd/YYYY, dd.mm.YYYY, YYYY-mm-dd or date followed by time; for example, "2016-07-04 14:40". Relative times are taken as "x [second|minute|hour|day](s) ago. +.TP 10 +-C/--clear + +Clears performance statistics for all ports. Only statistics with error thresholds are cleared. A clear occurs after generating the report. + +.TP 10 +-a/--clearall + +Clears all performance statistics for all ports. + +.TP 10 +-m/--smadirect + +Accesses fabric information directly from SMA. + +.TP 10 +-M/--pmadirect + +Accesses performance statistics using direct PMA. + +.TP 10 +-A/--allports + +Gets PortInfo for down switch ports. Uses direct SMA to get this data. If used with -M, also gets PMA stats for down switch ports. + +.TP 10 +-c/--config \fIfile\fR + +Specifies the error thresholds configuration file. Default is /etc/opa/opamon.conf file. + +.TP 10 +-L/--limit + +Limits operation to exact specified focus with -F for port error counters check (-o \fIerrors\fR) and port counters clear (-C or -i). Normally, the neighbor of each selected port is also checked/cleared. Does not affect other reports. + +.TP 10 +-F/--focus \fIpoint\fR + +Specifies the focus area for report. + +.IP +Limits output to reflect a subsection of the fabric. May not work with all reports. (For example, route, mcgroups, and the verify* reports may ignore the option or not generate useful results.) +.TP 10 +-S/--src \fIpoint\fR + +Specifies the source for trace route. Default is local port. + +.TP 10 +-D/--dest \fIpoint\fR + +Specifies the destination for trace route. + +.TP 10 +-Q/--quietfocus + +Excludes focus description from report. + + +.SH opareport Snapshot-Specific Options + +.PP +For reference: +.TP 10 +-r/--routes + +Gets routing tables for all switches. + +.TP 10 +-V/--vltables + +Gets the P-Key tables for all nodes and the QoS VL-related tables for all ports. + + +.SH opareport Report Types + +.PP +For reference: +.TP 10 +comps + +Summary of all systems and SMs in fabric. + +.TP 10 +brcomps + +Brief summary of all systems and SMs in fabric. + +.TP 10 +nodes + +Summary of all node types and SMs in fabric. + +.TP 10 +brnodes + +Brief summary of all node types and SMs in fabric. + +.TP 10 +ious + +Summary of all IO units in the fabric. + +.TP 10 +lids + +Summary of all LIDs in the fabric. + +.TP 10 +linkinfo + +Summary of all links with LIDs in the fabric. + +.TP 10 +links + +Summary of all links. + +.TP 10 +extlinks + +Summary of links external to systems. + +.TP 10 +filinks + +Summary of links to FIs. + +.TP 10 +islinks + +Summary of inter-switch links. + +.TP 10 +extislinks + +Summary of inter-switch links external to systems. + +.TP 10 +slowlinks + +Summary of links running slower than expected. + +.TP 10 +slowconfiglinks + +Summary of links configured to run slower than supported, includes slowlinks. + +.TP 10 +slowconnlinks + +Summary of links connected with mismatched speed potential, includes slowconfiglinks. + +.TP 10 +misconfiglinks + +Summary of links configured to run slower than supported. + +.TP 10 +misconnlinks + +Summary of links connected with mismatched speed potential. + +.TP 10 +errors + +Summary of links whose errors exceed counts in the configuration file. + +.TP 10 +otherports + +Summary of ports not connected to the fabric. + +.TP 10 +linear + +Summary of linear forwarding data base (FDB) for each switch. + +.TP 10 +mcast + +Summary of multicast FDB for each switch in the fabric. + +.TP 10 +mcgroups + +Summary of multicast groups. + +.IP +When used in conjunction with -d, the following report details are possible: +.RS + +.IP \(bu +-d0 : Shows the number of multicast groups +.IP \(bu +-d1 : Shows a list of multicast groups +.IP \(bu +-d2 : Shows a list of members per multicast group + +.RE + +.IP +This report can be used with option -X. +.TP 10 +portusage + +Summary of ports referenced in linear FDB for each switch, broken down by NodeType of DLID. + +.TP 10 +pathusage + +Summary of number of FI to FI paths routed through each switch port. + +.TP 10 +treepathusage + +Analysis of number of FI to FI paths routed through each switch port for a FAT tree. + +.TP 10 +portgroups + +Summary of adaptive routing port groups for each switch. + +.TP 10 +quarantinednodes + +Summary of quarantined nodes. + +.TP 10 +validateroutes + +Validates all routes in the fabric. + +.TP 10 +validatevlroutes + +Validates all routes in the fabric using SLSC, SCSC, and SCVL tables. + +.TP 10 +validatepgs + +Validates all port groups in the fabric. + +.TP 10 +validatecreditloops + +Validates topology configuration of the fabric to identify any existing credit loops. + +.TP 10 +validatevlcreditloops + +Validates topology configuration of the fabric including SLSC, SCSC, and SCVL tables to identify any existing credit loops. + +.TP 10 +validatemcroutes + +Validates multicast routes of the fabric to identify loops in multicast forwarding tables and detect MFT-multicast membership inconsistencies. + +.TP 10 +vfinfo + +Summary of virtual fabric (vFabric) information. + +.TP 10 +vfmember + +Summary of vFabric membership information. + +.TP 10 +dgmember + +Summary of DeviceGroup membership information. + +.TP 10 +verifyfis + +Compares fabric (or snapshot) FIs to supplied topology and identifies differences and omissions. + +.TP 10 +verifysws + +Compares fabric (or snapshot) switches to supplied topology and identifies differences and omissions. + +.TP 10 +verifynodes + +Returns verifyfis and verifysws reports. + +.TP 10 +verifysms + +Compares fabric (or snapshot) SMs to supplied topology and identifies differences and omissions. + +.TP 10 +verifylinks + +Compares fabric (or snapshot) links to supplied topology and identifies differences and omissions. + +.TP 10 +verifyextlinks + +Compares fabric (or snapshot) links to supplied topology and identifies differences and omissions. Limits analysis to links external to systems. + +.TP 10 +verifyfilinks + +Compares fabric (or snapshot) links to supplied topology and identify differences and omissions. Limits analysis to links to FIs. + +.TP 10 +verifyislinks + +Compares fabric (or snapshot) links to supplied topology and identify differences and omissions. Limits analysis to inter-switch links. + +.TP 10 +verifyextislinks + +Compares fabric (or snapshot) links to supplied topology and identify differences and omissions. Limits analysis to inter-switch links external to systems. + +.TP 10 +verifyall + +Returns verifyfis, verifysws, verifysms, and verifylinks reports. + +.TP 10 +all + +Returns comps, nodes, ious, links, extlinks, slowconnlinks, and errors reports. + +.TP 10 +route + +Traces route between -S and -D points. + +.TP 10 +bfrctrl + +Reports Buffer Control Tables for all ports. + +.TP 10 +snapshot + +Outputs snapshot of the fabric state for later use as \fIsnapshot\(ulinput\fR. This implies -x. May not be combined with other reports. When selected, -F, -P, -H, and -N options are ignored. + +.TP 10 +topology + +Outputs the topology of the fabric for later use as \fItopology\(ulinput\fR. This implies -x. May not be combined with other reports. Use with detail level 3 or more to get Port element under Node in output xml. + +.TP 10 +none + +No report, useful to clear statistics. + + +.SH opareport Point Syntax + +.PP +For reference: +.TP 10 +gid:value + +\fIvalue\fR is numeric port GID of form: subnet:guid. + +.TP 10 +lid:value + +\fIvalue\fR is numeric LID. + +.TP 10 +lid:value:node + +\fIvalue\fR is numeric LID, selects entire node with given LID. + +.TP 10 +lid:value:port:value2 + +\fIvalue\fR is numeric LID of node, \fIvalue2\fR is port number. + +.TP 10 +portguid:value + +\fIvalue\fR is numeric port GUID. + +.TP 10 +nodeguid:value + +\fIvalue\fR is numeric node GUID. + +.TP 10 +nodeguid:value1:port:value2 + +\fIvalue1\fR is numeric node GUID, \fIvalue2\fR is port number. + +.TP 10 +iocguid:value + +\fIvalue\fR is numeric IOC GUID. + +.TP 10 +iocguid:value1:port:value2 + +\fIvalue1\fR is numeric IOC GUID, \fIvalue2\fR is port number. + +.TP 10 +systemguid:value + +\fIvalue\fR is numeric system image GUID. + +.TP 10 +systemguid:value1:port:value2 + +\fIvalue1\fR is the numeric system image GUID, \fIvalue2\fR is port number. + +.TP 10 +ioc:value + +\fIvalue\fR is IOC Profile ID String (IOC Name). + +.TP 10 +ioc:value1:port:value2 + +\fIvalue1\fR is IOC Profile ID String (IOC Name), \fIvalue2\fR is port number. + +.TP 10 +iocpat:value + +\fIvalue\fR is glob pattern for IOC Profile ID String (IOC Name). + +.TP 10 +iocpat:value1:port:value2 + +\fIvalue1\fR is glob pattern for IOC Profile ID String (IOC Name), \fIvalue2\fR is port number. + +.TP 10 +ioctype:value + +\fIvalue\fR is IOC type (SRP or OTHER). + +.TP 10 +ioctype:value1:port:value2 + +\fIvalue1\fR is IOC type (SRP or OTHER); \fIvalue2\fR is port number. + +.TP 10 +node:value + +\fIvalue\fR is node description (node name). + +.TP 10 +node:value1:port:value2 + +\fIvalue1\fR is node description (node name), \fIvalue2\fR is port number. + +.TP 10 +nodepat:value + +\fIvalue\fR is glob pattern for node description (node name). + +.TP 10 +nodepat:value1:port:value2 + +\fIvalue1\fR is the glob pattern for the node description (node name), \fIvalue2\fR is port number. + +.TP 10 +nodedetpat:value + +\fIvalue\fR is glob pattern for node details. + +.TP 10 +nodedetpat:value1:port:value2 + +\fIvalue1\fR is the glob pattern for the node details, \fIvalue2\fR is port number. + +.TP 10 +nodetype:value + +\fIvalue\fR is node type (SW or FI). + +.TP 10 +nodetype:value1:port:value2 + +\fIvalue1\fR is node type (SW or FI), \fIvalue2\fR is port number. + +.TP 10 +rate:value + +\fIvalue\fR is string for rate (25g, 50g, 75g, 100g), omits switch mgmt port 0. + +.TP 10 +portstate:value + +\fIvalue\fR is a string for state (down, init, armed, active, notactive, initarmed). + +.TP 10 +portphysstate:value + +\fIvalue\fR is a string for PHYs state (polling, disabled, training, linkup, recovery, offline, test) + +.TP 10 +mtucap:value + +\fIvalue\fR is MTU size (2048, 4096, 8192, 10240), omits switch mgmt port 0. + +.TP 10 +labelpat:value + +\fIvalue\fR is glob pattern for cable label. + +.TP 10 +lengthpat:value + +\fIvalue\fR is glob pattern for cable length. + +.TP 10 +cabledetpat:value + +\fIvalue\fR is glob pattern for cable details. + +.TP 10 +cabinflenpat:value + +\fIvalue\fR is glob pattern for cable info length. + +.TP 10 +cabinfvendnamepat:value + +\fIvalue\fR is glob pattern for cable info vendor name. + +.TP 10 +cabinfvendpnpat:value + +\fIvalue\fR is glob pattern for cable info vendor part number. + +.TP 10 +cabinfvendrevpat:value + +\fIvalue\fR is glob pattern for cable info vendor revision. + +.TP 10 +cabinfvendsnpat:value + +\fIvalue\fR is glob pattern for cable info vendor serial number. + +.TP 10 +cabinftype:value + +\fIvalue\fR is either optical, passive\(ulcopper, active\(ulcopper, or unknown. + +.TP 10 +linkdetpat:value + +\fIvalue\fR is glob pattern for link details. + +.TP 10 +portdetpat:value + +\fIvalue\fR is glob pattern for port details. + +.TP 10 +sm + +Specifies the master subnet manager (SM). + +.TP 10 +smdetpat:value + +\fIvalue\fR is glob pattern for SM details. + +.TP 10 +route:point1:point2 + +Specifies all ports along the routes between the two given points. + +.TP 10 +led:value + +\fIvalue\fR is either on or off for LED port beacon. + +.TP 10 +linkqual:value + +Specifies the ports with a link quality equal to \fIvalue\fR. + +.TP 10 +linkqualLE:value + +Specifies the ports with a link quality less than or equal to \fIvalue\fR. + +.TP 10 +linkqualGE:value + +Specifies the ports with a link quality greater than or equal to \fIvalue\fR. + +.TP 10 +nodepatfile:\fIFILENAME\fR + +Specifies the name of file with the list of nodepats or node descriptions. + +.TP 10 +nodepairpatfile:\fIFILENAME\fR + +Specifies the name of file with the list of node pairs, separated by a colon. + +.TP 10 +ldr + +Specifies the ports with a non-zero link down reason or neighbor link down reason. + +.TP 10 +ldr:\fIvalue\fR + +Specifies the ports with a link down reason or neighbor link down reason equal to \fIvalue\fR. + + +.SH opareport Examples + +.PP +For reference: +.PP +opareport can generate hundreds of different reports. Commonly generated reports include the following: opareport -o comps -d 3 +.br + + opareport -o errors -o slowlinks +.br + + opareport -o nodes -F portguid:0x00117500a000447b +.br + + opareport -o nodes -F nodeguid:0x001175009800447b:port:1 +.br + + opareport -o nodes -F nodeguid:0x001175009800447b +.br + + opareport -o nodes -F \[aq]node:duster hfi1\(ul0\[aq] +.br + + opareport -o nodes -F \[aq]node:duster hfi1\(ul0:port:1\[aq] +.br + + opareport -o nodes -F \[aq]nodepat:d*\[aq] +.br + + opareport -o nodes -F \[aq]nodepat:d*:port:1\[aq] +.br + + opareport -o nodes -F \[aq]nodedetpat:compute*\[aq] +.br + + opareport -o nodes -F \[aq]nodedetpat:compute*:port:1\[aq] +.br + + opareport -o nodes -F nodetype:FI +.br + + opareport -o nodes -F nodetype:FI:port:1 +.br + + opareport -o nodes -F lid:1 +.br + + opareport -o nodes -F led:on + opareport -o nodes -F led:off + opareport -o nodes -F lid:1:node +.br + + opareport -o nodes -F lid:1:port:2 +.br + + opareport -o nodes -F gid:0xfe80000000000000:0x00117500a000447b +.br + + opareport -o nodes -F systemguid:0x001175009800447b +.br + + opareport -o nodes -F systemguid:0x001175009800447b:port:1 +.br + + opareport -o nodes -F iocguid:0x00117501300001e0 +.br + + opareport -o nodes -F iocguid:0x00117501300001e0:port:2 +.br + + opareport -o nodes -F \[aq]ioc:Chassis 0x001175005000010C, Slot 2, IOC 1\[aq] +.br + + opareport -o nodes -F \[aq]ioc:Chassis 0x001175005000010C, Slot 2, IOC 1:port:2\[aq] +.br + + opareport -o nodes -F \[aq]iocpat:*Slot 2*\[aq] +.br + + opareport -o nodes -F \[aq]iocpat:*Slot 2*:port:2\[aq] +.br + + opareport -o nodes -F ioctype:SRP + opareport -o nodes -F ioctype:SRP:port:2 +.br + + opareport -o extlinks -F rate:100g +.br + + opareport -o extlinks -F portstate:armed +.br + + opareport -o extlinks -F portphysstate:linkup +.br + + opareport -o extlinks -F \[aq]labelpat:S1345*\[aq] +.br + + opareport -o extlinks -F \[aq]lengthpat:11m\[aq] +.br + + opareport -o extlinks -F \[aq]cabledetpat:*hitachi*\[aq] +.br + + opareport -o extlinks -F \[aq]linkdetpat:*core ISL*\[aq] +.br + + opareport -o extlinks -F \[aq]portdetpat:*mgmt*\[aq] +.br + + opareport -o links -F mtucap:2048 +.br + + opareport -o nodes -F sm +.br + + opareport -o nodes -F \[aq]smdetpat:primary*\[aq] +.br + + opareport -o nodes -F \[aq]route:node:duster hfi1\(ul0:node:cuda hfi1\(ul0\[aq] +.br + + opareport -o nodes -F \[aq]route:node:duster hfi1\(ul0:port:1:node:cuda hfi1\(ul0:port:2\[aq] +.br + + opareport -o treepathusage -F nodepairpatfile:FILENAME +.br + + opareport -o pathusage -F nodepatfile:FILENAME +.br + + opareport -s -o snapshot > file +.br + + opareport -o topology > topology.xml +.br + + opareport -o errors -X file +.br + + opareport -s --begin "2 days ago" +.br + + opareport -s --begin "12:30" --end "14:00" +.br + + opareport -o linkinfo -x > file +.SH Details + +.PP +For simple fabrics, the Intel(R) Omni-Path Fabric Suite FastFabric Toolset host is connected to a single fabric. By default, the first active port on the FastFabric Toolset host is used to analyze the fabric. +.PP +However, in more complex fabrics, the FastFabric Toolset host may be connected to more than one fabric or subnet. In this case, you can specify the ports or HFIs to use with one of the following methods: +.IP \(bu +On the command line using the -p option. +.IP \(bu +In a file specified using the -t option. +.IP \(bu +Through the environment variables \fBPORTS\fR or \fBPORTS\(ulFILE\fR. +.IP \(bu +Using the ports\(ulfile configuration option in /etc/opa/opafastfabric.conf. +.PP +If the specified port does not exist or is empty, the first active port on the local system is used. In more complex configurations, you must specify the exact ports to use for all fabrics to be analyzed. +.PP +You can specify the topology\(ulinput file to be used with one of the following methods: +.IP \(bu +On the command line using the -T option. +.IP \(bu +In a file specified through the environment variable \fBFF\(ulTOPOLOGY\(ulFILE\fR. +.IP \(bu +Using the ff\(ultopology\(ulfile configuration option in opafastfabric.conf. +.PP +If the specified file does not exist, no topology\(ulinput file is used. Alternately the filename can be specified as NONE to prevent use of an input file. diff --git a/IbaTools/man/oparesolvehfiport.manPage b/IbaTools/man/oparesolvehfiport.manPage new file mode 100644 index 0000000..bd9d53d --- /dev/null +++ b/IbaTools/man/oparesolvehfiport.manPage @@ -0,0 +1,105 @@ +.\" .\" ********************************************************************* +.\" .\" * * +.\" .\" * Copyright 2015-2019, Intel Corporation * +.\" .\" * * +.\" .\" * All Rights Reserved. * +.\" .\" * * +.\" .\" ********************************************************************* + +.TH oparesolvehfiport 1 "Intel Corporation" "Copyright(C) 2015\-2019" "IFSFFCLIRG (Man Page)" +.SH NAME +oparesolvehfiport + + +.PP + +\fB(Host)\fR +Permits the Intel(R) Omni-Path Fabric Host Software style Intel(R) Omni-Path Host Fabric Interface (HFI) number and port number arguments to be converted to a Host Software style HFI name and physical port number. +.SH Syntax +oparesolvehfiport [-o \fIoutput\fR] [ \fIhfi\fR] [ \fIport\fR] +.SH Options + +.TP 10 +--help + +Produces full help text. + +.TP 10 +-o \fIoutput\fR + +Specifies the output type. + +.RS +.TP 10 + +.sp +devname +Prints the device name, in the format hfiname:portnum (Default). + +.RE + +.RS +.TP 10 + +.sp +hfinum +Prints the hfi number. + +.RE + +.TP 10 +\fIhfi\fR + +Specifies the HFI, numbered 1..n. Using 0 specifies that the -p port port is a system-wide port number. Default is 0. + +.TP 10 +\fIport\fR + +Specifies the port, numbered 1..n. Using 0 specifies the first active port. Default is 0. + +.IP +The HFI and port permit a variety of selections: +.RS +.TP 10 + +.sp +0 0 +First active port in system. + +.RE + +.RS +.TP 10 + +.sp +\fIx\fR 0 +First active port on HFI \fIx\fR. + +.RE + +.RS +.TP 10 + +.sp +0 \fIy\fR +Port \fIy\fR within system (no matter which ports are active). + +.RE + +.RS +.TP 10 + +.sp +\fIx y\fR +HFI \fIx\fR, port \fIy\fR + +.RE + +.SH Examples +oparesolvehfiport 0 1 #Output: hfi1\(ul0:1 +.br + +oparesolvehfiport -o devname 0 1 #Output: hfi1\(ul0:1 +.br + +oparesolvehfiport -o hfinum 0 1 #Output: 1 diff --git a/IbaTools/man/opasaquery.manPage b/IbaTools/man/opasaquery.manPage new file mode 100644 index 0000000..e4ef4b8 --- /dev/null +++ b/IbaTools/man/opasaquery.manPage @@ -0,0 +1,911 @@ +.\" .\" ********************************************************************* +.\" .\" * * +.\" .\" * Copyright 2015-2019, Intel Corporation * +.\" .\" * * +.\" .\" * All Rights Reserved. * +.\" .\" * * +.\" .\" ********************************************************************* + +.TH opasaquery 1 "Intel Corporation" "Copyright(C) 2015\-2019" "IFSFFCLIRG (Man Page)" +.SH NAME +opasaquery + + +.PP + +\fB(All)\fR +Performs various queries of the subnet manager/subnet agent and provides detailed fabric information. +.PP +opareport and opareports from the Intel(R) Omni-Path Fabric Suite can provide a more powerful tool. In some cases, opasaquery is preferred, especially when dealing with virtual fabrics, service records, and multicast. +.PP +By default, opasaquery uses the first active port on the local system. However, if the node is connected to more than one fabric (for example, a subnet), the Intel(R) Omni-Path Host Fabric Interface (HFI) and port may be specified to select the fabric whose SA is to be queried. +.SH Syntax +opasaquery [-v [-v] [-v]] [-I] [-h \fIhfi\fR|-b \fIaddr\fR] [-p \fIport\fR] [--timeout] +.br +[-x \fIgid\fR] [-E] +[-T \fIssl\(ulparams\fR] [-o \fItype\fR] [-l \fIlid\fR] [-t \fItype\fR] [-s \fIguid\fR] +.br +[-n \fIguid\fR] +[-g \fIguid\fR] [-k \fIpkey\fR] [-i \fIvfIndex\fR] [-S \fIserviceId\fR] [-L \fIsl\fR] +.br +[-u \fIgid\fR] +[-m \fIgid\fR] [-d \fInodeDescription\fR] [-D \fIdg\(ulname\fR] [-P \[aq]\fIguid guid\fR\[aq]] +.br +[-G \[aq]\fIgid gid\fR\[aq]] +[-H \fImask\fR] +.SH Options + +.TP 10 +--help + +Produces full help text. + +.TP 10 +-v/--verbose + +Returns verbose output. A second invocation activates openib debugging, a third invocation activates libibumad debugging. + +.TP 10 +-I/--IB + +Issues query in legacy InfiniBand* format. + +.TP 10 +-h/--hfi \fIhfi\fR + +Specifies the HFI, numbered 1..n. Using 0 specifies that the -p \fIport\fR port is a system-wide port number. Default is 0. + +.TP 10 +-b/--oob \fIaddress\fR + +Specifies Out-of-Band address of node running the FE. Can be either hostname, IPv4, or IPv6 address. Default is "127.0.0.1". + +.TP 10 +-p/--port \fIport\fR + +Specifies the port. +.RS + +.IP \(bu +In-band: numbered 1..n. Using 0 specifies first active port. Default is 0. +.IP \(bu +Out-of-band: Port FE is listening on. Default is 3245. + +.RE + + +.TP 10 +--timeout + +Specifies the timeout (wait time for response) in ms. Default is 1000 ms. + +.TP 10 +-x/--source-gid \fIsrc\(ulgid\fR + +Specifies the source GID of the local GID (This is required for most Path and Trace Record Queries when Out-of-Band.) + +.TP 10 +-E/--feEsm + +Specifies the ESM FE. + +.TP 10 +-T/--ssl-params \fIfile\fR + +Specifies the SSL/TLS parameters XML file. Default is /etc/opa/opamgt\(ultls.xml. + +.TP 10 +-o \fItype\fR + +Output type for query. Default is node. See +\fIOutput Types\fR +for details. + +.TP 10 +-l/--lid \fIlid\fR + +Query a specific LID. + +.TP 10 +-t/--type \fInode\(ultype\fR + +Queries by node type. See +\fINode Types\fR +for details. + +.TP 10 +-s/--sysguid \fIsystem\(ulimage\(ulguid\fR + +Queries by system image GUID. + +.TP 10 +-n/--nodeguid \fInode\(ulguid\fR + +Queries by node GUID. + +.TP 10 +-g/--portguid \fIport\(ulguid\fR + +Queries by port GUID. + +.TP 10 +-k/--pkey \fIpkey\fR + +Queries a specific PKey. + +.TP 10 +-i/--vfindex \fIvfIndex\fR + +Queries a specific vfindex. + +.TP 10 +-S/--serviceId \fIserviceId\fR + +Queries a specific service ID. + +.TP 10 +-L/--SL \fISL\fR + +Queries by service level. + +.TP 10 +-u/--portgid \fIport\(ulgid\fR + +Queries by port GID. See +\fIGIDs\fR +for details. + +.TP 10 +-m/--mcgid \fImulticast\(ulgid\fR + +Queries by multicast GID. See +\fIGIDs\fR +for details. + +.TP 10 +-d/--desc \fInode\(uldescription\fR + +Queries by node name/description. + +.TP 10 +-D/--dgname \fIdg\(ulname\fR + +Queries by device group name/description + +.TP 10 +-P/--guidpair \fIguid guid\fR + +Queries by a pair of port GUIDs. + +.TP 10 +-G/--gidpair \fIgid gid\fR + +Queries by a pair of GIDs. See +\fIGIDs\fR +for details. + + +.SH -h and -p options permit a variety of selections: + +.TP 10 +-h 0 + +First active port in system (Default). + +.TP 10 +-h 0 -p 0 + +First active port in system. + +.TP 10 +-h \fIx\fR + +First active port on HFI \fIx\fR. + +.TP 10 +-h \fIx\fR \fI\fR-p 0 + +First active port on HFI \fIx\fR. + +.TP 10 +-h 0 -p \fIy\fR + +Port \fIy\fR within system (no matter which ports are active). + +.TP 10 +-h \fIx\fR \fI\fR-p \fIy\fR + +HFI \fIx\fR, port \fIy\fR. + +.SH Node Types + +.TP 10 +fi + +Fabric Interface + +.TP 10 +sw + +Switch + +.SH GIDs + +.PP +Specifies a 64-bit subnet and 64-bit interface ID in the form: +.PP +subnet:interface +.PP + +.B NOTE: +In the following example, the GID corresponds to a PortGID. In this case, the interface ID coincides with the lower 64-bits of the GUID of the card. The interface ID will be different if the GID is a MGID (that is, multicast GID). See opafm.xml for MGID examples. + +.PP + +.br +0xfe80000000000000:0x00117500a0000380 + +.br + +.SH Output Types + +.PP +Default is node. +.TP 10 +classportinfo + +Specifies the classportinfo of the SA. + +.TP 10 +systemguid + +Lists the system image GUIDs. + +.TP 10 +nodeguid + +Lists the node GUIDs. + +.TP 10 +portguid + +Lists the port GUIDs. + +.TP 10 +lid + +Lists the LIDs. + +.TP 10 +desc + +Lists the node descriptions/names. + +.TP 10 +path + +Lists the path records. + +.TP 10 +node + +Lists the node records. + +.TP 10 +portinfo + +Lists the port info records. + +.TP 10 +sminfo + +Lists the SM info records. + +.TP 10 +swinfo + +Lists the switch info records. + +.TP 10 +link + +Lists the link records. + +.TP 10 +scsc + +Lists the SC to SC mapping table records. + +.TP 10 +slsc + +Lists the SL to SC mapping table records. + +.TP 10 +scsl + +Lists the SC to SL mapping table records. + +.TP 10 +scvlt + +Lists the SC to VLt table records. + +.TP 10 +scvlr + +Lists the SC to VLr table records. + +.TP 10 +scvlnt + +Lists the SC to VLnt table records. + +.TP 10 +vlarb + +Lists the VL arbitration table records. + +.TP 10 +pkey + +Lists the PKey table records. + +.TP 10 +service + +Lists the service records. + +.TP 10 +mcmember + +Lists the multicast member records. + +.TP 10 +inform + +Lists the inform info records. + +.TP 10 +linfdb + +Lists the switch linear forwarding database (FDB) records. + +.TP 10 +mcfdb + +Lists the switch multicast FDB records. + +.TP 10 +trace + +Lists the trace records. + +.TP 10 +vfinfo + +Lists the vFabrics. + +.TP 10 +vfinfocsv + +Lists the vFabrics in CSV format. + +.TP 10 +vfinfocsv2 + +Lists the vFabrics in CSV format with enums. + +.TP 10 +fabricinfo + +Specifies the summary of fabric devices. + +.TP 10 +quarantine + +Lists the quarantined nodes. + +.TP 10 +conginfo + +Lists the Congestion Info Records. + +.TP 10 +swcongset + +Lists the Switch Congestion Settings. + +.TP 10 +swportcong + +Lists the Switch Port Congestion Settings. + +.TP 10 +hficongset + +Lists the HFI Congestion Settings. + +.TP 10 +hficongcon + +Lists the HFI Congestion Control Settings. + +.TP 10 +bfrctrl + +Lists the buffer control tables. + +.TP 10 +cableinfo + +Lists the Cable Info records. + +.TP 10 +portgroup + +Lists the AR Port Group records. + +.TP 10 +portgroupfdb + +Lists the AR Port Group FWD records. + +.TP 10 +dglist + +Lists the Device Group Names. + +.TP 10 +dgmember + +Lists the Device Group records. + +.TP 10 +dtree + +Lists the Device Tree records. + +.TP 10 +swcost + +Lists the switch cost records. + +.PP +The vfinfocsv and vfinfocsv2 output formats are designed to make it easier to script vfinfo queries. One line is output per vFabric of the form: +.PP + +.br + +.br +name:index:pkey:sl:mtu:rate:optionflag::mcastSl + +.br + +.PP +The only difference between these two formats is how the MTU and rate are output. vfinfocsv outputs MTU and rate in human/text readable format. vfinfocsv2 outputs MTU and rate as enumerations defined for the SMA protocol. The opagetvf command is based on this capability of opasaquery. For more information, see +\fIopagetvf\fR +. +.SH Example +opasaquery -o desc -t fi + +.SH Input Options vs. Output Permitted + +.PP +The following list shows the input (assorted query by options) and outputs (-o) that are permitted. +.TP 10 +None + + +.RS +.TP 10 + +.sp +-o output permitted +systemguid, nodeguid, portguid, lid, desc, path, node, portinfo, sminfo, swinfo, link, vlarb, pkey, service, mcmember, inform, linfdb, mcfdb, vfinfo, vfinfocsv, vfinfocsv2, scsc, slsc, scvlt, scnlmt, linfdb, classportinfo, fabricinfo, quarantine, conginfo, swcongset, swportcong, hficongset, hficongcon, bfrctl, cableinfo, portgroup, portgroupfdb, dglist, dgmember, dtree + +.RE + +.RS +.TP 10 + +.sp +-o output not permitted +trace + +.RE + + +.TP 10 +-t \fInode\(ultype\fR + + +.RS +.TP 10 + +.sp +-o output permitted +systemguid, nodeguid, portguid, lid, desc, node, dglist, dgmember, dtree + +.RE + +.RS +.TP 10 + +.sp +-o output not permitted +portinfo, sminfo, swinfo, vlarb, pkey, service, mcmember, inform, linfdb, mcfdb, trace, vfinfo, vfinfocsv, vfinfocsv2 + +.RE + + +.TP 10 +-l \fIlid\fR + + +.RS +.TP 10 + +.sp +-o output permitted +systemguid, nodeguid, portguid, lid, desc, path, node, portinfo, swinfo, slvl, vlarb, pkey, mcmember, linfdb, mcfdb, dgmember, dtree + +.RE + +.RS +.TP 10 + +.sp +-o output not permitted +sminfo, link, inform, service, trace, vfinfo, vfinfocsv, vfinfocsv2, dglist + +.RE + + +.TP 10 +-k \fIpkey\fR + + +.RS +.TP 10 + +.sp +-o output permitted +mcmember, path, vfinfo, vfinfocsv, vfinfocsv2 + +.RE + +.RS +.TP 10 + +.sp +-o output not permitted +systemimageguid, nodeguid, portguid, lid, desc, node, portinfo, sminfo, swinfo, link, vlarb, pkey, service, mcmember, inform, linfdb, mcfdb, dglist, dgmember, dtree + +.RE + + +.TP 10 +-i +\fIvfindex\fR + + + + +.RS +.TP 10 + +.sp +-o output permitted +vfinfo, vfinfocsv, vfinfocsv2 + +.RE + +.RS +.TP 10 + +.sp +-o output not permitted +systemimageguid, nodeguid, portguid, lid, desc, node, portinfo, sminfo, swinfo, link, vlarb, pkey, service, mcmember, inform, linfdb, mcfdb, dglist, dgmember, dtree + +.RE + + +.TP 10 +-s \fIsystem\(ulimage\(ulguid\fR + + +.RS +.TP 10 + +.sp +-o output permitted +systemguid, nodeguid, portguid, lid, desc, node + +.RE + +.RS +.TP 10 + +.sp +-o output not permitted +portinfo, sminfo, swinfo, link, vlarb, pkey, service, mcmember, inform, linfdb, mcfdb, trace, vfinfo, vfinfocsv, vfinfocsv2, dglist, dgmember, dtree + +.RE + + +.TP 10 +-n \fInode\(ulguid\fR + + +.RS +.TP 10 + +.sp +-o output permitted +systemguid, nodeguid, portguid, lid, desc, node + +.RE + +.RS +.TP 10 + +.sp +-o output not permitted +portinfo, sminfo, swinfo, link, vlarb, pkey, service, mcmember, inform, linfdb, mcfdb, trace, vfinfo, vfinfocsv, vfinfocsv2, dglist, dgmember, dtree + +.RE + + +.TP 10 +-g \fIport\(ulguid\fR + + +.RS +.TP 10 + +.sp +-o output permitted +systemguid, nodeguid, portguid, lid, desc, path, node, trace, dgmember + +.RE + +.RS +.TP 10 + +.sp +-o output not permitted +portinfo, sminfo, swinfo, link, vlarb, pkey, linfdb, mcfdb, vfinfo, vfinfocsv, vfinfocsv2, dglist, dtree, service, mcmember, inform + +.RE + + +.TP 10 +-u \fIport\(ulgid\fR + + +.RS +.TP 10 + +.sp +-o output permitted +path, service, mcmember, inform, trace + +.RE + +.RS +.TP 10 + +.sp +-o output not permitted +systemguid, nodeguid, portguid, lid, desc, node, portinfo, sminfo, swinfo, link, vlarb, pkey, linfdb, mcfdb, vfinfo, vfinfocsv, vfinfocsv2, dglist, dgmember, dtree + +.RE + + +.TP 10 +-m \fImulticast\(ulgid\fR + + +.RS +.TP 10 + +.sp +-o output permitted +mcmember, vfinfo, vfinfocsv, vfinfocsv2 + +.RE + +.RS +.TP 10 + +.sp +-o output not permitted +systemguid, nodeguid, portguid, lid, desc, path, node, portinfo, sminfo, swinfo, link, vlarb, pkey, service, inform, linfdb, mcfdb, trace, dglist, dgmember, dtree + +.RE + + +.TP 10 +-d \fInode\(uldescription\fR + + +.RS +.TP 10 + +.sp +-o output permitted +systemguid, nodeguid, portguid, lid, desc, node, dgmember + +.RE + +.RS +.TP 10 + +.sp +-o output not permitted +trace, dglist, dtree + +.RE + + +.TP 10 +-D \fIdg\(ulname\fR + + +.RS +.TP 10 + +.sp +-o output permitted +dgmember + +.RE + +.RS +.TP 10 + +.sp +-o output not permitted +systemguid, nodeguid, portguid, lid, desc, path, node, portinfo, sminfo, swinfo, link, vlarb, pkey, service, inform, linfdb, mcfdb, trace, dglist, dtree + +.RE + + +.TP 10 +-P \fIport\(ulguid\(ulpair\fR + + +.RS +.TP 10 + +.sp +-o output permitted +path, trace + +.RE + +.RS +.TP 10 + +.sp +-o output not permitted +systemguid, nodeguid, portguid, lid, desc, node, portinfo, sminfo, swinfo, link, vlarb, pkey, service, mcmember, inform, linfdb, mcfdb, dglist, dgmember, dtree + +.RE + + +.TP 10 +-S \fIserviceId\fR + + +.RS +.TP 10 + +.sp +-o output permitted +path, vfinfo, vfinfocsv, vfinfocsv2, service + +.RE + +.RS +.TP 10 + +.sp +-o output not permitted +systemimageguid, nodeguid, portguid, lid, desc, node, portinfo, sminfo, swinfo, link, vlarb, pkey, mcmember, inform, linfdb, mcfdb, dglist, dgmember, dtree + +.RE + + +.TP 10 +-L \fISL\fR + + +.RS +.TP 10 + +.sp +-o output permitted +path, vfinfo, vfinfocsv, vfinfocsv2 + +.RE + +.RS +.TP 10 + +.sp +-o output not permitted +systemimageguid, nodeguid, portguid, lid, desc, node, portinfo, sminfo, swinfo, link, vlarb, pkey, service, mcmember, inform, linfdb, mcfdb, dglist, dgmember, dtree + +.RE + + +.TP 10 +-G \fIgid\(ulpair\fR + + +.RS +.TP 10 + +.sp +-o output permitted +path, trace + +.RE + +.RS +.TP 10 + +.sp +-o output not permitted +systemguid, nodeguid, portguid, lid, desc, node, portinfo, sminfo, swinfo, link, vlarb, pkey, service, mcmember, inform, linfdb, mcfdb, dglist, dgmember, dtree + +.RE + + +.TP 10 +-a \fIport\(ulguid\(ullist\fR + + +.RS +.TP 10 + +.sp +-o output permitted +path + +.RE + +.RS +.TP 10 + +.sp +-o output not permitted +systemguid, nodeguid, portguid, lid, desc, node, portinfo, sminfo, swinfo, link, vlarb, pkey, service, mcmember, inform, linfdb, mcfdb, trace, dglist, dgmember, dtree + +.RE + + +.TP 10 +-A \fIgid\(ullist\fR + + +.RS +.TP 10 + +.sp +-o output permitted +path + +.RE + +.RS +.TP 10 + +.sp +-o output not permitted +systemguid, nodeguid, portguid, lid, desc, node, portinfo, sminfo, swinfo, link, vlarb, pkey, service, mcmember, inform, linfdb, mcfdb, trace, dglist, dgmember, dtree + +.RE + diff --git a/IbaTools/man/opascpall.manPage b/IbaTools/man/opascpall.manPage new file mode 100644 index 0000000..c412f96 --- /dev/null +++ b/IbaTools/man/opascpall.manPage @@ -0,0 +1,138 @@ +.\" .\" ********************************************************************* +.\" .\" * * +.\" .\" * Copyright 2015-2019, Intel Corporation * +.\" .\" * * +.\" .\" * All Rights Reserved. * +.\" .\" * * +.\" .\" ********************************************************************* + +.TH opascpall 8 "Intel Corporation" "Copyright(C) 2015\-2019" "IFSFFCLIRG (Man Page)" +.SH NAME +opascpall + + +.PP + +\fB(Linux)\fR +Copies files or directories from the current system to multiple hosts in the fabric. When copying large directory trees, use the -t option to improve performance. This option tars and compresses the tree, transfers the resulting compressed tarball to each node, and untars it on each node. +.PP +Use this tool for copying data files, operating system files, or applications to all the hosts (or a subset of hosts) within the fabric. +.PP + +.B NOTE: + +.IP \(bu +This tool can only copy from this system to a group of systems in the cluster. To copy from hosts in the cluster to this host, use opauploadall. +.IP \(bu +user@ style syntax cannot be used when specifying filenames. + +.SH Syntax + +.PP + +.br +opascpall [-p] [-r] [-f \fIhostfile\fR] [-h \[aq]\fIhosts\fR\[aq]] [-u \fIuser\fR] +.br +source\(ulfile ... dest\(ulfile + +.br + +.PP + +.br +opascpall [-t] [-p] [-f \fIhostfile\fR] [-h \[aq]\fIhosts\fR\[aq]] [-u \fIuser\fR] +.br +[ \fIsource\(uldir\fR [ \fIdest\(uldir\fR]] + +.br + +.SH Options + +.TP 10 +--help + +Produces full help text. +.TP 10 +-p + +Performs copy in parallel on all hosts. +.TP 10 +-r + +Performs recursive copy of directories. +.TP 10 +-t + +Performs optimized recursive copy of directories using tar. \fIdest\(uldir\fR is optional. If \fIdest\(uldir\fR is not specified, it defaults to the current directory name. If both \fIsource\(uldir\fR and \fIdest\(uldir\fR are omitted, they both default to the current directory name. + +.TP 10 +-h \fIhosts\fR + +Specifies the list of hosts to copy to. +.TP 10 +-f \fIhostfile\fR + +Specifies the file with hosts in cluster. Default is /etc/opa/hosts file. +.TP 10 +-u \fIuser\fR + +Specifies the user to perform copy to. Default is current user code. +.TP 10 +\fIsource\(ulfile\fR + +Specifies the a file or list of source files to copy. + +.TP 10 +\fIsource\(uldir\fR + +Specifies the name of the source directory to copy. If omitted. is used. + +.TP 10 +\fIdest\(ulfile\fR or \fIdest\(uldir\fR + +Specifies the name of the destination file or directory to copy to. If more than one source file, this must be a directory. If omitted current directory name is used. + +.SH Example +# efficiently copy an entire directory tree +.br + +opascpall -t -p /usr/src/opa/mpi\(ulapps /usr/src/opa/mpi\(ulapps +.br + + +.br + +# copy a group of files +.br + +opascpall a b c /root/tools/ +.br + + +.br + +# copy to an explitly specified set of hosts +.br + +opascpall -h \[aq]arwen elrond\[aq] a b c /root/tools +.br + +HOSTS=\[aq]arwen elrond\[aq] opascpall a b c /root/tools +.SH Environment Variables + +.PP +The following environment variables are also used by this command: +.TP 10 +\fBHOSTS\fR + +List of hosts; used if -h option not supplied. + +.TP 10 +\fBHOSTS\(ulFILE\fR + +File containing list of hosts; used in absence of -f and -h. + +.TP 10 +\fBFF\(ulMAX\(ulPARALLEL\fR + +When the -p option is used, maximum concurrent operations are performed. diff --git a/IbaTools/man/opasetupssh.manPage b/IbaTools/man/opasetupssh.manPage new file mode 100644 index 0000000..efb6edb --- /dev/null +++ b/IbaTools/man/opasetupssh.manPage @@ -0,0 +1,207 @@ +.\" .\" ********************************************************************* +.\" .\" * * +.\" .\" * Copyright 2015-2019, Intel Corporation * +.\" .\" * * +.\" .\" * All Rights Reserved. * +.\" .\" * * +.\" .\" ********************************************************************* + +.TH opasetupssh 8 "Intel Corporation" "Copyright(C) 2015\-2019" "IFSFFCLIRG (Man Page)" +.SH NAME +opasetupssh + + +.PP + +\fB(Linux or Switch)\fR +Creates SSH keys and configures them on all hosts or chassis so the system can use SSH and SCP into all other hosts or chassis without a password prompt. Typically, during cluster setup this tool enables the root user on the Management Node to log into the other hosts (as root) or chassis (as admin) using password-less SSH. +.SH Syntax +opasetupssh [-C|p|U] [-f \fIhostfile\fR] [-F \fIchassisfile\fR] [-h \[aq]\fIhosts\fR\[aq]] +.br + +[-H \[aq]\fIchassis\fR\[aq]] [-i \fIipoib\(ulsuffix\fR] [-u \fIuser\fR] [-S] [-R|P] +.SH Options + +.TP 10 +--help + +Produces full help text. + +.TP 10 +-C + +Performs operation against chassis. Default is hosts. + +.TP 10 +-p + +Performs operation against all chassis or hosts in parallel. + +.TP 10 +-U + +Performs connect only (to enter in local hosts, known hosts). When run in this mode, the -S option is ignored. + +.TP 10 +-f \fIhostfile\fR + +Specifies the file with hosts in cluster. +.br +Default is /etc/opa/hosts file. + +.TP 10 +-F \fIchassisfile\fR + +Specifies the file with chassis in cluster. +.br +Default is /etc/opa/chassis file. + +.TP 10 +-h \fIhosts\fR + +Specifies the list of hosts to set up. + +.TP 10 +-H \fIchassis\fR + +Specifies the list of chassis to set up. + +.TP 10 +-i \fIipoib\(ulsuffix\fR + +Specifies the suffix to apply to host names to create IPoIB host names. Default is -opa. + +.TP 10 +-u \fIuser\fR + +Specifies the user on remote system to allow this user to SSH to. Default is current user code for host(s) and admin for chassis. + +.TP 10 +-S + +Securely prompts for password for user on remote system. + +.TP 10 +-R + +Skips setup of SSH to local host. + +.TP 10 +-P + +Skips ping of host (for SSH to devices on Internet with ping +.br +firewalled). + +.SH Examples + + +.SH Operations on Hosts +opasetupssh -S -i \[aq]\[aq] +.br + +opasetupssh -U +.br + +opasetupssh -h \[aq]arwen elrond\[aq] -U +.br + +HOSTS=\[aq]arwen elrond\[aq] opasetupssh -U + +.SH Operations on Chassis +opasetupssh -C +.br + +opasetupssh -C -H \[aq]chassis1 chassis2\[aq] +.br + +CHASSIS=\[aq]chassis1 chassis2\[aq] opasetupssh -C +.SH Environment Variables + +.PP +The following environment variables are also used by this command: +.TP 10 +\fBHOSTS\(ulFILE\fR + +File containing list of hosts, used in absence of -f and -h. + +.TP 10 +\fBCHASSIS\(ulFILE\fR + +File containing list of chassis, used in absence of -F and -H. + +.TP 10 +\fBHOSTS\fR + +List of hosts, used if -h option not supplied. + +.TP 10 +\fBCHASSIS\fR + +List of chassis, used if -C is used and -H and -F options not supplied. + +.TP 10 +\fBFF\(ulMAX\(ulPARALLEL\fR + +When -p option is used, maximum concurrent operations. + +.TP 10 +\fBFF\(ulIPOIB\(ulSUFFIX\fR + +Suffix to append to hostname to create IPoIB hostname. Used in absence of -i. + +.TP 10 +\fBFF\(ulCHASSIS\(ulLOGIN\(ulMETHOD\fR + +How to log into chassis. Can be Telnet or SSH. + +.TP 10 +\fBFF\(ulCHASSIS\(ulADMIN\(ulPASSWORD\fR + +Password for admin on all chassis. Used in absence of -S option. + +.SH Description + +.PP +The Intel(R) Omni-Path Fabric Suite FastFabric Toolset provides additional flexibility in the translation between IPoIB and management network hostnames. +.PP +opasetupssh provides an easy way to create SSH keys and distribute them to the hosts or chassis in the cluster. Many of the FastFabric tools (as well as many versions of MPI) require that SSH is set up for password-less operation. Therefore, opasetupssh is an important setup step. +.PP +This tool also sets up SSH to the local host and the local host\[aq]s IPoIB name. This capability is required by selected FastFabric Toolset commands and may be used by some applications (such as MPI). +.PP +opasetupssh has two modes of operation. The mode is selected by the presence or absence of the -U option. Typically, opasetupssh is first run without the -U option, then it may later be run with the -U option. +.SH Host Initial Key Exchange + +.PP +When run without the -U option, opasetupssh performs the initial key exchange and enables password-less SSH and SCP. The preferred way to use opasetupssh for initial key exchange is with the -S option. This requires that all hosts are configured with the same password for the specified "user" (typically root). In this mode, the password is prompted for once and then SSH and SCP are used in conjunction with that password to complete the setup for the hosts. This mode also avoids the need to set up rsh/rcp/rlogin (which can be a security risk). +.PP +opasetupssh configures password-less SSH/SCP for both the management network and IPoIB. Typically, the management network is used for FastFabric Toolset operations while IPoIB is used for MPI and other applications. +.PP +During initial cluster installation, where the Intel(R) Omni-Path Fabric software is not yet installed on all the hosts, IPoIB is not yet running. In this situation, use the -i option with an empty string as follows: +.PP + +.br +opasetupssh -i \[aq]\[aq] + +.br + +.PP +This causes the last part of the setup of SSH for IPoIB to be skipped. +.SH Refreshing Local Systems Known Hosts + +.PP +If aspects of the host have changed, such as IP addresses, MAC addresses, software installation, or server OS reinstallation, you can refresh the local host\[aq]s SSH known\(ulhosts file by running opasetupssh with the -U option. This option does not transfer the keys, but instead connects to each host (management network and IPoIB) to refresh the SSH keys. Existing entries for the specified hosts are replaced within the local known\(ulhosts file. When run in this mode, the -S option is ignored. This mode assumes SSH has previously been set up for the hosts, as such no files are transferred to the specified hosts and no passwords should be required. +.PP +Typically after completing the installation and booting of Intel(R) Omni-Path Fabric software, opasetupssh must be rerun with the -U option to update the known\(ulhosts file. +.SH Chassis Initial Key Exchange + +.PP +When run without the -U option, opasetupssh performs the initial key exchange and enables password-less SSH and SCP. For chassis, the key exchange uses SCP and the chassis CLI. During this command you log into the chassis using the configured mechanism for chassis login. +.PP +The preferred way to use opasetupssh for initial key exchange is with the -S option. This requires that all chassis are configured with the same password for admin. In this mode, you are prompted for the password once and then the \fBFF\(ulCHASSIS\(ulLOGIN\(ulMETHOD\fR and SCP are used in conjunction with that password to complete the setup for the chassis. This method also avoids the need to setup the chassis password in /etc/opa/opafastfabric.conf (which can be a security risk). +.PP +For chassis, the -i option is ignored. +.SH Chassis Refreshing Local Systems Known Hosts + +.PP +If aspects of the chassis have changed, such as IP addresses or MAC addresses, you can refresh the local host\[aq]s SSH known\(ulhosts file by running opasetupssh with the -U option. This option does not transfer the keys, but instead connects to each chassis to refresh the SSH keys. Existing entries for the specified chassis are replaced within the local known\(ulhosts file. When run in this mode, the -S option is ignored. This mode assumes SSH has previously been set up for the chassis, because no files are transferred to the specified hosts and no passwords are required. diff --git a/IbaTools/man/opashowallports.manPage b/IbaTools/man/opashowallports.manPage new file mode 100644 index 0000000..f765e76 --- /dev/null +++ b/IbaTools/man/opashowallports.manPage @@ -0,0 +1,119 @@ +.\" .\" ********************************************************************* +.\" .\" * * +.\" .\" * Copyright 2015-2019, Intel Corporation * +.\" .\" * * +.\" .\" * All Rights Reserved. * +.\" .\" * * +.\" .\" ********************************************************************* + +.TH opashowallports 8 "Intel Corporation" "Copyright(C) 2015\-2019" "IFSFFCLIRG (Man Page)" +.SH NAME +opashowallports + + +.PP + +\fB(Switch and Host)\fR +Displays basic port state and statistics for all host nodes, chassis, or externally-managed switches. +.PP + +.B NOTE: +opareport and opareports are more powerful Intel(R) Omni-Path Fabric Suite FastFabric commands. For general fabric analysis, use opareport or opareports with options such as -o errors and -o slowlinks to perform an efficient analysis of link speeds and errors. + + +.SH Syntax +opashowallports [-C] [-f \fIhostfile\fR] [-F \fIchassisfile\fR] [-h \[aq]\fIhosts\fR\[aq]] +.br + +[-H \[aq]\fIchassis\fR\[aq]] [-S] +.SH Options + +.TP 10 +--help + +Produces full help text. +.TP 10 +-C + +Performs operation against chassis. Default is host. +.TP 10 +-f \fIhostfile\fR + +Specifies the file containing the list of hosts in cluster. Default is /etc/opa/hosts file. +.TP 10 +-F \fIchassisfile\fR + +Specifies the file containing the list of chassis in cluster. Default is /etc/opa/chassis file. +.TP 10 +-h \fIhosts\fR + +Specifies the list of hosts for which to show ports. +.TP 10 +-H \fIchassis\fR + +Specifies the list of chassis for which to show ports. +.TP 10 +-S + +Securely prompts for password for admin on chassis. +.SH Environment Variables + +.PP +The following environment variables are also used by this command: +.TP 10 +\fBHOSTS\fR + +List of hosts, used if -h option not supplied. + +.TP 10 +\fBCHASSIS\fR + +List of chassis, used if -C is used and -H and -F options not supplied. + +.TP 10 +\fBHOSTS\(ulFILE\fR + +File containing list of hosts, used in absence of -f and -h. + +.TP 10 +\fBCHASSIS\(ulFILE\fR + +File containing list of chassis, used in absence of -F and -H. + +.TP 10 +\fBFF\(ulCHASSIS\(ulLOGIN\(ulMETHOD\fR + +How to log into chassis. Can be Telnet or SSH. + +.TP 10 +\fBFF\(ulCHASSIS\(ulADMIN\(ulPASSWORD\fR + +Password for admin on all chassis. Used in absence of -S option. + +.SH Example +opashowallports +.br + +opashowallports -h \[aq]elrond arwen\[aq] +.br + +HOSTS=\[aq]elrond arwen\[aq] opashowallports +.br + +opashowallports -C +.br + +opashowallports -H \[aq]chassis1 chassis2\[aq] +.br + +CHASSIS=\[aq]chassis1 chassis2\[aq] opashowallports -C +.SH Notes + +.PP +When performing opashowallports against hosts, internally SSH is used. The command opashowallports requires that password-less SSH be set up between the host running the Intel(R) Omni-Path Fabric Suite FastFabric Toolset and the hosts opashowallports is operating against. The opasetupssh FastFabric tool can aid in setting up password-less SSH. +.PP +When performing operations against chassis, Intel recommends that you set up SSH keys (see +\fIopasetupssh\fR +). If SSH keys are not set up, Intel recommends that you use the -S option, to avoid keeping the password in configuration files. +.PP +When performing opashowallports against externally-managed switches, a node with Intel(R) Omni-Path Fabric Suite FastFabric Toolset installed is required. Typically, this is the node from which opashowallports is being run. diff --git a/IbaTools/man/opashowmc.manPage b/IbaTools/man/opashowmc.manPage new file mode 100644 index 0000000..de7f226 --- /dev/null +++ b/IbaTools/man/opashowmc.manPage @@ -0,0 +1,105 @@ +.\" .\" ********************************************************************* +.\" .\" * * +.\" .\" * Copyright 2015-2019, Intel Corporation * +.\" .\" * * +.\" .\" * All Rights Reserved. * +.\" .\" * * +.\" .\" ********************************************************************* + +.TH opashowmc 8 "Intel Corporation" "Copyright(C) 2015\-2019" "IFSFFCLIRG (Man Page)" +.SH NAME +opashowmc + + +.PP + +\fB(Linux)\fR +Displays the Intel(R) Omni-Path Multicast groups created for the fabric along with the Intel(R) Omni-Path Host Fabric Interface (HFI) ports which are a member of each multicast group. This command can be helpful when attempting to analyze or debug Intel(R) Omni-Path multicast usage by applications or ULPs such as IPoIB. +.SH Syntax +opashowmc [-v] [-m \fImgid\fR] [-t \fIportsfile\fR] [-p \fIports\fR] +.SH Options + +.TP 10 +--help + +Produces full help text. + +.TP 10 +-v + +Returns verbose output and shows name of each member. + +.TP 10 +-m \fImgid\fR + +Shows the membership of the group only. + +.TP 10 +-t \fIportsfile\fR + +Specifies the file with list of local HFI ports used to access fabric(s) for analysis. Default is /etc/opa/ports file. + +.TP 10 +-p \fIports\fR + +Specifies the list of local HFI ports used to access fabric(s) for analysis. + +.IP +Default is first active port. The first HFI in the system is 1. The first port on an HFI is 1. Uses the format hfi:port, +.br +for example: +.RS +.TP 10 + +.sp +0:0 +First active port in system. + +.RE + +.RS +.TP 10 + +.sp +0:y +Port \fIy\fR within system. + +.RE + +.RS +.TP 10 + +.sp +x:0 +First active port on HFI \fIx\fR. + +.RE + +.RS +.TP 10 + +.sp +x:y +HFI \fIx\fR, port \fIy\fR. + +.RE + +.SH Examples +opashowmc +.br + +opashowmc -p \[aq]1:1 1:2 2:1 2:2\[aq] +opashowmc -m 0xff12401b80010000:0x00000000ffffffff +.SH Environment Variables + +.PP +The following environment variables are also used by this command: +.TP 10 +\fBPORTS\fR + +List of ports, used in absence of -t and -p. + +.TP 10 +\fBPORTS\(ulFILE\fR + +File containing list of ports, used in absence of -t and -p. diff --git a/IbaTools/man/opasmaquery.manPage b/IbaTools/man/opasmaquery.manPage new file mode 100644 index 0000000..68ed7df --- /dev/null +++ b/IbaTools/man/opasmaquery.manPage @@ -0,0 +1,575 @@ +.\" .\" ********************************************************************* +.\" .\" * * +.\" .\" * Copyright 2015-2019, Intel Corporation * +.\" .\" * * +.\" .\" * All Rights Reserved. * +.\" .\" * * +.\" .\" ********************************************************************* + +.TH opasmaquery 1 "Intel Corporation" "Copyright(C) 2015\-2019" "IFSFFCLIRG (Man Page)" +.SH NAME +opasmaquery + + +.PP + +\fB(All)\fR +Performs Intel(R) Omni-Path Architecture-defined SMA queries and displays the resulting response. Each query is issued directly to the SMA and does not involve SM interaction. +.SH Syntax +opasmaquery [-v] [-d \fIdetail\fR][-g] [-l \fIlid\fR] [-h \fIhfi\fR] [-p \fIport\fR] +[-o \fIotype\fR] +.br +[-m \fIport\fR| \fIport1,port2\fR] [-f \fIflid\fR] [-b \fIblock[,count]\fR] [hop hop ...] +.SH Options + +.TP 10 +--help + +Produces full help text. + +.TP 10 +-v + +Returns verbose output. Can be specified more than once for additional openib and libibumad debugging. + +.TP 10 +-d \fIdetail\fR + +Specifies the output detail level for cableinfo only. Range is 0 - n. Default is 2. An upper limit for detail level is not enforced. After a maximum amount of output is reached, a larger detail value has no effect. + +.TP 10 +-g + +Displays line-by-line format. Default is summary format. + +.TP 10 +-l \fIlid\fR + +Specifies the destination LID. Default is local port. + +.TP 10 +-h/--hfi \fIhfi\fR + +Specifies the HFI, numbered 1..n. Using 0 specifies that the -p \fIport\fR port is a system-wide port number. Default is 0. + +.TP 10 +-p/--port \fIport\fR + +Specifies the port, numbered 1..n. Using 0 specifies the first active port. Default is 0. + +.TP 10 +-o \fIotype\fR + +Specifies the output type. Default is nodeinfo. Refer to +\fIotype Options Vary by Report\fR +for supported options. + +.IP +Valid output types are: +.RS +.TP 10 + +.sp +bfrctrl +Specifies buffer control tables. + +.IP +[-m dest\(ulport] [-m port1,port2] +.RE + +.RS +.TP 10 + +.sp +cableinfo +Specifies cable information. + +.IP +[-d detail] [-m dest\(ulport] [-b block[,count]] +.RE + +.RS +.TP 10 + +.sp +conginfo +Specifies congestion information. + +.RE + +.RS +.TP 10 + +.sp +desc or nodedesc +Specifies node descriptions/names. + +.RE + +.RS +.TP 10 + +.sp +hficongcon +Specifies HFI congestion control settings. + +.IP +[-b block[,count]] [-f flid] +.RE + +.RS +.TP 10 + +.sp +hficonglog +Specifies HFI congestion logs. + +.IP +[-b block[,count]] +.RE + +.RS +.TP 10 + +.sp +hficongset +Specifies HFI congestion settings. + +.RE + +.RS +.TP 10 + +.sp +linfdb +Specifies switch linear forwarding database (FDB) tables. + +.IP +[-b block[,count]] [-f flid] +.RE + +.RS +.TP 10 + +.sp +mcfdb +Specifies switch multicast FDB tables. + +.IP +[-m dest\(ulport] [-b block[,count]] [-f flid] +.RE + +.RS +.TP 10 + +.sp +portgroup +Specifies Adaptive Routing port groups. + +.IP +[-b block[,count]] +.RE + +.RS +.TP 10 + +.sp +portgroupfdb +Specifies Adaptive Routing port group FWD tables. + +.IP +[-b block[,count]] [-f flid] +.RE + +.RS +.TP 10 + +.sp +nodeaggr +Specifies node information and node descriptions. + +.RE + +.RS +.TP 10 + +.sp +node or nodeinfo +Specifies node information. + +.IP +[-m dest\(ulport] +.RE + +.RS +.TP 10 + +.sp +portinfo +Specifies port information. + +.IP +[-m dest\(ulport] +.RE + +.RS +.TP 10 + +.sp +pstateinfo +Specifies switch port state information. + +.IP +[-m dest\(ulport] [-m port1,port2] +.RE + +.RS +.TP 10 + +.sp +pkey +Specifies P-Key tables. + +.IP +[-m dest\(ulport] [-b block[,count]] +.RE + +.RS +.TP 10 + +.sp +slsc +Specifies SL to SC mapping tables. + +.RE + +.RS +.TP 10 + +.sp +scsl +Specifies SC to SL mapping tables. + +.RE + +.RS +.TP 10 + +.sp +scsc +Specifies SC to SC mapping tables. + +.IP +[-m dest\(ulport] [-m port1,port2] +.RE + +.RS +.TP 10 + +.sp +scvlt +Specifies SC to VLt tables. + +.IP +[-m dest\(ulport] [-m port1,port2] +.RE + +.RS +.TP 10 + +.sp +scvlnt +Specifies SC to VLnt tables. + +.IP +[-m dest\(ulport] [-m port1,port2] +.RE + +.RS +.TP 10 + +.sp +scvlr +Specifies SC to VLr tables + +.IP +[-m dest\(ulport] [-m port1,port2] +.RE + +.RS +.TP 10 + +.sp +sminfo +Specifies SM information. + +.RE + +.RS +.TP 10 + +.sp +swaggr +Specifies node information and switch information. + +.RE + +.RS +.TP 10 + +.sp +swconglog +Specifies switch congestion logs. + +.IP +[-b block[,count]] +.RE + +.RS +.TP 10 + +.sp +swcongset +Specifies switch congestion settings. + +.RE + +.RS +.TP 10 + +.sp +swinfo +Specifies switch information. + +.RE + +.RS +.TP 10 + +.sp +swportcong +Specifies switch congestion settings. + +.IP +[-b block[,count]] +.RE + +.RS +.TP 10 + +.sp +vlarb +Specifies VL arbitration tables. + +.IP +[-m dest\(ulport] +.RE + +.RS +.TP 10 + +.sp +ibnodeinfo +Specifies IB node information. + +.RE + +.RS +.TP 10 + +.sp +ledinfo +Specifies LED information. + +.IP +[-m dest\(ulport] +.RE + + +.SH -h and -p options permit a variety of selections: + +.TP 10 +-h 0 + +First active port in system (Default). + +.TP 10 +-h 0 -p 0 + +First active port in system. + +.TP 10 +-h \fIx\fR + +First active port on HFI \fIx\fR. + +.TP 10 +-h \fIx\fR \fI\fR-p 0 + +First active port on HFI \fIx\fR. + +.TP 10 +-h 0 -p \fIy\fR + +Port \fIy\fR within system (no matter which ports are active). + +.TP 10 +-h \fIx\fR \fI\fR-p \fIy\fR + +HFI \fIx\fR, port \fIy\fR. + + +.SH otype Options Vary by Report +[-m port|port1,port2] [-f lid] [-b block[,count]] +.TP 10 +-m \fIport\fR + +Specifies the port in destination device to query. + +.TP 10 +-m \fIport1,port2\fR + +For some reports, specifies a range of ports between \fIport1\fR and \fIport2\fR. For others, this describes an inport/outport pair. + +.TP 10 +-f \fIlid\fR + +Specifies the LID to look up in forwarding table to select which LFT or MFT block to display. Default is to show entire table. + +.TP 10 +-b \fIblock[,count]\fR + +Specifies the block number of either GUIDs or pkey, and the number of blocks to display. Default is to show entire table. + +.IP +For example: +.IP + +.RS +.TP 10 + +.sp +-b \fIblock\fR +Displays all of block \fIblock\fR of a larger table. + +.RE + +.RS +.TP 10 + +.sp +-b \fIblock,count\fR +Displays \fIcount\fR blocks of data starting with block \fIblock\fR. + +.RE + +.RS +.TP 10 + +.sp +-b, \fIcount\fR +Displays \fIcount\fR blocks of data starting with block 0. + +.RE + +.SH Examples + +.PP +opasmaquery -o desc -l 6 +.br + +# get nodedesc via lid routed +.br + + +.br + +opasmaquery -o nodedesc 1 3 +.br + +# get nodedesc via directed route (2 dr hops) +.br + + +.br + +opasmaquery -o nodeinfo -l 2 3 +.br + +# get nodeinfo via a combination of lid routed and +# directed route (1 dr hop) +.br + + +.br + +opasmaquery -o portinfo +.br + +# get local port info +.br + + +.br + +opasmaquery -o portinfo -l 6 -m 1 +.br + +# get port info of port 1 of lid 6 +.br + + +.br + +opasmaquery -o pkey -l 2 3 +.br + +# get pkey table entries starting (lid routed to lid 2, +.br + +# then 1 dr hop to port 3) +.br + + +.br + +opasmaquery -o vlarb -l 6 +.br + +# get vlarb table entries from lid 6 +.br + + +.br + +opasmaquery -o swinfo -l 2 +.br + +# get switch info +.br + + +.br + +opasmaquery -o sminfo -l 1 +.br + +# get SM info +.br + + +.br + +opasmaquery -o slsc -l 3 +.br + +# get sl2sc table entries from lid 3 +.br + + +.br + +opasmaquery -o scsl -l 3 +.br + +# get sc2sl table entries from lid 3 diff --git a/IbaTools/man/opasorthosts.manPage b/IbaTools/man/opasorthosts.manPage new file mode 100644 index 0000000..2f82e68 --- /dev/null +++ b/IbaTools/man/opasorthosts.manPage @@ -0,0 +1,91 @@ +.\" .\" ********************************************************************* +.\" .\" * * +.\" .\" * Copyright 2015-2019, Intel Corporation * +.\" .\" * * +.\" .\" * All Rights Reserved. * +.\" .\" * * +.\" .\" ********************************************************************* + +.TH opasorthosts 8 "Intel Corporation" "Copyright(C) 2015\-2019" "IFSFFCLIRG (Man Page)" +.SH NAME +opasorthosts + + +.PP +Sorts its standard input in a typical host name order and sorts to standard output. Hosts are sorted alphabetically (case-insensitively) by any alpha-numeric prefix, and then sorted numerically by any numeric suffix. Host names may end in a numeric field which may optionally have leading zeros. Unlike a pure alphabetic sort, this command results in intuitive sequencing of host names such as: host1, host2, host10. +.PP +This command does not remove duplicates; any duplicates are listed in adjacent lines. +.PP +Use this command to build mpi\(ulhosts input files for applications or cable tests that place hosts in order by name. +.SH Syntax +opasorthosts < \fIhostlist\fR> \fIoutput\(ulfile\fR +.SH Options + +.TP 10 +--help + +Produces full help text. + +.TP 10 +\fIhostlist\fR + +Specifies the list of host names. + +.TP 10 +\fIoutput\(ulfile\fR + +Specifies the sorted list output. + +.SH Examples +opasorthosts < host.xml > Sorted\(ulhost +.TP 10 +\fBStandard Input\fR + + +.br +opasorthosts +.br + +osd04 +.br + +osd1 +.br + +compute20 +.br + +compute3 +.br + +mgmt1 +.br + +mgmt2 +.br + +login +.TP 10 +\fBStandard Output\fR + + +.br +compute3 +.br + +compute20 +.br + +login +.br + +mgmt1 +.br + +mgmt2 +.br + +osd1 +.br + +osd04 diff --git a/IbaTools/man/opaswdisableall.manPage b/IbaTools/man/opaswdisableall.manPage new file mode 100644 index 0000000..c4c6139 --- /dev/null +++ b/IbaTools/man/opaswdisableall.manPage @@ -0,0 +1,101 @@ +.\" .\" ********************************************************************* +.\" .\" * * +.\" .\" * Copyright 2015-2019, Intel Corporation * +.\" .\" * * +.\" .\" * All Rights Reserved. * +.\" .\" * * +.\" .\" ********************************************************************* + +.TH opaswdisableall 8 "Intel Corporation" "Copyright(C) 2015\-2019" "IFSFFCLIRG (Man Page)" +.SH NAME +opaswdisableall + + +.PP + +\fB(Linux)\fR +Disables all unused switch ports. +.SH Syntax +opaswdisableall [-t \fIportsfile\fR] [-p \fIports\fR] [-F \fIfocus\fR] +.SH Options + +.TP 10 +--help + +Produces full help text. + +.TP 10 +-t \fIportsfile\fR + +Specifies the file with list of local HFI ports used to access fabrics when clearing counters. +.br +Default is /etc/opa/ports file. + +.TP 10 +-p \fIports\fR + +Specifies the list of local HFI ports used to access fabrics for counter clear. + +.IP +Default is first active port. The first HFI in the system is 1. The first port on an HFI is 1. Uses the format hfi:port, +.br +for example: +.RS +.TP 10 + +.sp +0:0 +First active port in system. + +.RE + +.RS +.TP 10 + +.sp +0:y +Port \fIy\fR within system. + +.RE + +.RS +.TP 10 + +.sp +x:0 +First active port on HFI \fIx\fR. + +.RE + +.RS +.TP 10 + +.sp +x:y +HFI \fIx\fR, port \fIy\fR. + +.RE + +.TP 10 +-F \fIfocus\fR + +Specifies the an opareport -style focus argument to limit the scope of operation. + +.SH Examples +opaswdisableall +.br + +opaswdisableall -p \[aq]1:1 1:2 2:1 2:2\[aq] +.SH Environment Variables + +.PP +The following environment variables are also used by this command: +.TP 10 +\fBPORTS\fR + +List of ports, used in absence of -t and -p. + +.TP 10 +\fBPORTS\(ulFILE\fR + +File containing list of ports, used in absence of -t and -p. diff --git a/IbaTools/man/opaswenableall.manPage b/IbaTools/man/opaswenableall.manPage new file mode 100644 index 0000000..0b3e232 --- /dev/null +++ b/IbaTools/man/opaswenableall.manPage @@ -0,0 +1,99 @@ +.\" .\" ********************************************************************* +.\" .\" * * +.\" .\" * Copyright 2015-2019, Intel Corporation * +.\" .\" * * +.\" .\" * All Rights Reserved. * +.\" .\" * * +.\" .\" ********************************************************************* + +.TH opaswenableall 8 "Intel Corporation" "Copyright(C) 2015\-2019" "IFSFFCLIRG (Man Page)" +.SH NAME +opaswenableall + + +.PP + +\fB(Linux)\fR +Re-enables all unused (or disabled) switch ports. +.SH Syntax +opaswenableall [-t \fIportsfile\fR] [-p \fIports\fR] [-F \fIfocus\fR] +.SH Options + +.TP 10 +--help + +Produces full help text. + +.TP 10 +-t \fIportsfile\fR + +Specifies the file with list of local HFI ports used to access fabrics for operation. Default is /etc/opa/ports file. + +.TP 10 +-p \fIports\fR + +Specifies the list of local HFI ports used to access fabrics for operation. + +.IP +Default is first active port. The first HFI in the system is 1. The first port on an HFI is 1. Uses the format hfi:port, +.br +for example: +.RS +.TP 10 + +.sp +0:0 +First active port in system. + +.RE + +.RS +.TP 10 + +.sp +0:y +Port \fIy\fR within system. + +.RE + +.RS +.TP 10 + +.sp +x:0 +First active port on HFI \fIx\fR. + +.RE + +.RS +.TP 10 + +.sp +x:y +HFI \fIx\fR, port \fIy\fR. + +.RE + +.TP 10 +-F \fIfocus\fR + +Specifies an opareport -style focus argument to limit the scope of operation. + +.SH Examples +opaswenableall +.br + +opaswenableall -p \[aq]1:1 1:2 2:1 2:2\[aq] +.SH Environment Variables + +.PP +The following environment variables are also used by this command: +.TP 10 +\fBPORTS\fR + +List of ports, used in absence of -t and -p. + +.TP 10 +\fBPORTS\(ulFILE\fR + +File containing list of ports, used in absence of -t and -p. diff --git a/IbaTools/man/opaswitchadmin.manPage b/IbaTools/man/opaswitchadmin.manPage new file mode 100644 index 0000000..e3bd38f --- /dev/null +++ b/IbaTools/man/opaswitchadmin.manPage @@ -0,0 +1,417 @@ +.\" .\" ********************************************************************* +.\" .\" * * +.\" .\" * Copyright 2015-2019, Intel Corporation * +.\" .\" * * +.\" .\" * All Rights Reserved. * +.\" .\" * * +.\" .\" ********************************************************************* + +.TH opaswitchadmin 8 "Intel Corporation" "Copyright(C) 2015\-2019" "IFSFFCLIRG (Man Page)" +.SH NAME +opaswitchadmin + + +.PP + +\fB(Switch)\fR +Performs a number of multi-step initialization and verification operations against one or more externally managed Intel(R) Omni-Path switches. The operations include initial switch setup, firmware upgrades, chassis reboot, and others. +.SH Syntax +opaswitchadmin [-c] [-N \[aq]\fInodes\fR\[aq]] [-L \fInodefile\fR] [-O] [-P \fIpackages\fR] +.br +[-a \fIaction\fR] +[-t \fIportsfile\fR] [-p \fIports\fR] \fIoperation\fR ... +.SH Options + +.TP 10 +-help + +Produces full help text. + +.TP 10 +-c + +Overwrites result files from any previous run before starting this run. + +.TP 10 +-N \fInodes\fR + +Specifies the list of nodes to execute the operation against. + +.TP 10 +-L \fInodefile\fR + +Specifies the file with nodes in the cluster. Default is /etc/opa/switches file. + +.TP 10 +-P \fIpackages\fR + +For upgrades: Specifies the file name or directory where the firmware image is to install. For the directory specified, .emfw file in the directory tree is used. shell wild cards may also be used within quotes. + +.TP 10 +-t \fIportsfile\fR + +Specifies the file with list of local HFI ports used to access fabrics for switch access. Default is /etc/opa/ports file. + +.TP 10 +-p \fIports\fR + +Specifies the list of local HFI ports used to access fabrics for switch access. + +.IP +Default is first active port. The first HFI in the system is 1. The first port on an HFI is 1. Uses the format hfi:port, +.br +for example: +.RS +.TP 10 + +.sp +0:0 +First active port in system. + +.RE + +.RS +.TP 10 + +.sp +0:y +Port \fIy\fR within system. + +.RE + +.RS +.TP 10 + +.sp +x:0 +First active port on HFI \fIx\fR. + +.RE + +.RS +.TP 10 + +.sp +x:y +HFI \fIx\fR, port \fIy\fR. + +.RE + +.TP 10 +-a \fIaction\fR + +Specifies an action for firmware file for switch upgrade. The action argument can be one or more of the following: + +.RS +.TP 10 + +.sp +select +Ensures firmware is in primary (Default). + +.RE + +.RS +.TP 10 + +.sp +run +Ensures firmware is in primary and running. + +.RE + +.TP 10 +-O + +Specifies the override for firmware upgrades, bypasses the previous firmware version checks, and forces the update unconditionally. + +.TP 10 +\fIoperation\fR + +Performs the specified \fIoperation\fR, which can be one or more of the following: + +.RS +.TP 10 + +.sp +reboot +Reboots switches, ensures they go down and come back. + +.RE + +.RS +.TP 10 + +.sp +configure +Runs wizard to set up switch configuration. + +.TP 10 +.BR + +.PP + +.B NOTE: +You must reboot the switch for any new settings to be applied. + +.RE + +.RS +.TP 10 + +.sp +upgrade +Upgrades installation of all switches. + +.RE + +.RS +.TP 10 + +.sp +info +Reports firmware and hardware version, part number, and data rate capability of all nodes. + +.RE + +.RS +.TP 10 + +.sp +hwvpd +Completes hardware Vital Product Data (VPD) report of all nodes. + +.RE + +.RS +.TP 10 + +.sp +ping +Pings all nodes and tests for presence. + +.RE + +.RS +.TP 10 + +.sp +fwverify +Reports integrity of failsafe firmware of all nodes. + +.RE + +.RS +.TP 10 + +.sp +getconfig +Gets port configurations of an externally managed switch. + +.RE + +.PP +For more information on operations, see +\fIOperation Details\fR +. +.SH Example +opaswitchadmin -c reboot +.br + +opaswitchadmin -P /root/ChassisFw \fIX.X.X.X.X\fR upgrade +.br + +opaswitchadmin -a run -P \[aq]*.emfw\[aq] upgrade +.SH Environment Variables + +.PP +The following environment variables are also used by this command: +.TP 10 +\fBOPASWITCHES\fR + +List of nodes, used in absence of -N and -L options. + +.TP 10 +\fBOPASWITCHES\(ulFILE\fR + +File containing list of nodes, used in absence of -N and -L options. + +.TP 10 +\fBFF\(ulMAX\(ulPARALLEL\fR + +Maximum concurrent operations. + +.TP 10 +\fBFF\(ulSERIALIZE\(ulOUTPUT\fR + +Serialize output of parallel operations (yes or no). + +.TP 10 +\fBFF\(ulTIMEOUT\(ulMULT\fR + +Multiplier for all timeouts associated with this command. Used if the systems are slow for some reason. + +.SH Details + +.PP +opaswitchadmin provides detailed logging of its results. During each run, the following files are produced: +.IP \(bu +test.res : Appended with summary results of run. +.IP \(bu +test.log : Appended with detailed results of run. +.IP \(bu +save\(ultmp/ : Contains a directory per failed test with detailed logs. +.IP \(bu +test\(ultmp*/ : Intermediate result files while test is running. +.PP +The -c option removes all log files. +.PP +Results from opaswitchadmin are grouped into test suites, test cases, and test items. A given run of opaswitchadmin represents a single test suite. Within a test suite, multiple test cases occur; typically one test case per chassis being operated on. Some of the more complex operations may have multiple test items per test case. Each test item represents a major step in the overall test case. +.PP +Each opaswitchadmin run appends to test.res and test.log and creates temporary files in test\(ultmp$PID in the current directory. the test.res file provides an overall summary of operations performed and their results. The same information is also displayed while opaswitchadmin is executing. test.log contains detailed information about what was performed, including the specific commands executed and the resulting output. The test\(ultmp directories contain temporary files that reflect tests in progress (or killed). The logs for any failures are logged in the save\(ultemp directory with a directory per failed test case. If the same test case fails more than once, save\(ultemp retains the information from the first failure. Subsequent runs of opaswitchadmin are appended to test.log. Intel recommends reviewing failures and using the -c option to remove old logs before subsequent runs of opaswitchadmin. opaswitchadmin also appends to punchlist.csv for failing switches. +.PP +opaswitchadmin implicitly performs its operations in parallel. However, as for the other tools, \fBFF\(ulMAX\(ulPARALLEL\fR can be exported to change the degree of parallelism. 1000 parallel operations is the default. + +.SH Operation Details + +.PP + +\fB(Switch)\fR +All operations against Intel(R) Omni-Path Fabric externally-managed switches (except ping) securely access the selected switches. If a password has been set, the -S option must be used to securely prompt for a password. In this case, the same password is used for all switches. +.TP 10 +reboot + +Reboots the given switches. + +.IP +Use the \fBFF\(ulMAX\(ulPARALLEL\fR value to select either a rolling reboot or a parallel reboot. In most cases, a parallel reboot is recommended for expediency. +.TP 10 +upgrade + +Upgrades the firmware on each specified switch. The -P option selects a directory containing a .emfw file or provides an explicit .emfw file for the switches. If more than one .emfw file is specified, the operation is undefined. The -a option selects the desired minimal state for the new firmware. Only the select and run options are valid for this operation. + +.IP +When the -a option specifies run, switches are rebooted. Use the \fBFF\(ulMAX\(ulPARALLEL\fR value to select a rolling upgrade or a parallel upgrade. In most cases, a parallel upgrade is recommended for expediency. +.IP +The upgrade process also sets the switch name. +.IP +The upgrade process is used to set, clear, or change the password of the switches using the -s option. When this option is specified, you are prompted for a new password to be set on the switches. To reset (clear) the password, press Enter when prompted. This option can be used to configure the switches to not require a password for subsequent operations. A change to the password does not take effect until the next reboot of the switch. +.IP +For more information about switch firmware, refer to the +\fIIntel(R) Omni-Path Fabric Switches GUI User Guide\fR + +and +\fIIntel(R) Omni-Path Fabric Switches Release Notes\fR + +. +.TP 10 +configure + +Runs the switch setup wizard, which asks a series of questions. Once the wizard has finished prompting for configuration information, all the selected switches are configured according to the entered responses. The following items are configurable for all Intel(R) Omni-Path Switch 100 Series : + +.RS + +.IP \(bu +FM Enabled +.IP \(bu +Link CRC Mode +.IP \(bu +Link Width Supported +.IP \(bu +OPA Node Description + +.RE + +.TP 10 +.BR + +.PP + +.B NOTE: +Typically, the Node Description is updated automatically during a firmware upgrade, if it is configured properly in the switches file. Updating the node description is also available using the configure option without performing a firmware upgrade. + +.TP 10 +.BR + +.PP + +.B NOTE: +You must reboot the switch for any new settings to be applied. + +.TP 10 +info + +Queries the switches and displays the following information: + +.RS + +.IP \(bu +Firmware version +.IP \(bu +Hardware version +.IP \(bu +Hardware part number, including revision information +.IP \(bu +Speed capability +.IP \(bu +Fan status +.IP \(bu +Power supply status + +.RE + +.IP +This operation also outputs a summary of various configuration settings for each switch within a fabric. +.TP 10 +hwvpd + +Queries the switches and displays the Vital Product Data (VPD) including: + +.RS + +.IP \(bu +Serial number +.IP \(bu +Part number +.IP \(bu +Model name +.IP \(bu +Hardware version +.IP \(bu +Manufacturer +.IP \(bu +Product description +.IP \(bu +Manufacturer ID +.IP \(bu +Manufacture date +.IP \(bu +Manufacture time + +.RE + +.TP 10 +ping + +Issues an inband packet to the switches to test for presence and reports on presence/non-presence of each selected switch. + +.TP 10 +.BR + +.PP + +.B NOTE: +It is not necessary to supply a password (using -S) for this operation. + +.TP 10 +fwverify + +Verifies the integrity of the firmware images in the EEPROMs of the selected switches. + +.TP 10 +getconfig + +Gets port configurations of an externally managed switch. This operation also outputs a summary of various configuration settings for each switch within a fabric. For example, in a fabric with seven switches, a report similar to the following is displayed. + +.IP +This summary helps determine if all switches have the same configuration, and if not, indicates how many have each value. If some of the values are not as expected, view the test.res file to identify which switches have the undesirable values. diff --git a/IbaTools/man/opatop.manPage b/IbaTools/man/opatop.manPage new file mode 100644 index 0000000..7ba2d4f --- /dev/null +++ b/IbaTools/man/opatop.manPage @@ -0,0 +1,108 @@ +.\" .\" ********************************************************************* +.\" .\" * * +.\" .\" * Copyright 2015-2019, Intel Corporation * +.\" .\" * * +.\" .\" * All Rights Reserved. * +.\" .\" * * +.\" .\" ********************************************************************* + +.TH opatop 8 "Intel Corporation" "Copyright(C) 2015\-2019" "IFSFFCLIRG (Man Page)" +.SH NAME +opatop + + +.PP +Starts the Fabric Performance Monitor (opatop) Text-based User Interface (TUI) menu to display performance, congestion, and error information about a fabric. +.SH Syntax +opatop [-v] [-q] [-h \fIhfi\fR] [-p \fIport\fR] [--timeout] [-i \fIseconds\fR] +.SH Options + +.TP 10 +--help + +Produces full help text. + +.TP 10 +-v/--verbose level + +Specifies the verbose output level. Value is additive and includes: +.RS +.TP 10 + +.sp +1 +Screen +.RE + +.RS +.TP 10 + +.sp +4 +STDERR opatop +.RE + +.RS +.TP 10 + +.sp +16 +STDERR PaClient +.RE + +.TP 10 +-q/--quiet + +Disables progress reports. +.TP 10 +-h/--hfi \fIhfi\fR + +Specifies the HFI, numbered 1..n. Using 0 specifies that the -p \fIport\fR port is a system-wide port number. Default is 0. + +.TP 10 +-p/--port \fIport\fR + +Specifies the port, numbered 1..n. Using 0 specifies the first active port. Default is 0. + +.TP 10 +--timeout + +Specifies the timeout (response wait time) in ms. Default is 1000 ms. + +.TP 10 +-i/--interval \fIseconds\fR + +Interval in \fIseconds\fR at which PA queries are performed to refresh to the latest PA image. Default is 10 seconds. + + +.SH -h and -p options permit a variety of selections: + +.TP 10 +-h 0 + +First active port in system (Default). + +.TP 10 +-h 0 -p 0 + +First active port in system. + +.TP 10 +-h \fIx\fR + +First active port on HFI \fIx\fR. + +.TP 10 +-h \fIx\fR \fI\fR-p 0 + +First active port on HFI \fIx\fR. + +.TP 10 +-h 0 -p \fIy\fR + +Port \fIy\fR within system (no matter which ports are active). + +.TP 10 +-h \fIx\fR \fI\fR-p \fIy\fR + +HFI \fIx\fR, port \fIy\fR. diff --git a/IbaTools/man/opauploadall.manPage b/IbaTools/man/opauploadall.manPage new file mode 100644 index 0000000..d731fd0 --- /dev/null +++ b/IbaTools/man/opauploadall.manPage @@ -0,0 +1,116 @@ +.\" .\" ********************************************************************* +.\" .\" * * +.\" .\" * Copyright 2015-2019, Intel Corporation * +.\" .\" * * +.\" .\" * All Rights Reserved. * +.\" .\" * * +.\" .\" ********************************************************************* + +.TH opauploadall 8 "Intel Corporation" "Copyright(C) 2015\-2019" "IFSFFCLIRG (Man Page)" +.SH NAME +opauploadall + + +.PP + +\fB(Linux)\fR +Copies one or more files from a group of hosts to this system. Since the file name is the same on each host, a separate directory on this system is created for each host and the file is copied to it. This is a convenient way to upload log files or configuration files for review. This tool can also be used in conjunction with opadownloadall to upload a host specific configuration file, edit it for each host, and download the new version to all the hosts. +.PP + +.B NOTE: +To copy files from this host to hosts in the cluster, use opascpall or opadownloadall. user@ style syntax cannot be used when specifying filenames. + +.SH Syntax +opauploadall [-rp] [-f \fIhostfile\fR] [-d \fIupload\(uldir\fR] [-h \[aq]\fIhosts\fR\[aq]] [-u \fIuser\fR] +\fIsource\(ulfile\fR ... \fIdest\(ulfile\fR +.SH Options + +.TP 10 +--help + +Produces full help text. +.TP 10 +-p + +Performs copy in parallel on all hosts. +.TP 10 +-r + +Performs recursive upload of directories. +.TP 10 +-f \fIhostfile\fR + +Specifies the file with hosts in cluster. +.br +Default is /etc/opa/hosts file. +.TP 10 +-h \fIhosts\fR + +Specifies the list of hosts to upload from. +.TP 10 +-u \fIuser\fR + +Specifies the user to perform copy to. Default is current user code. +.TP 10 +-d \fIupload\(uldir\fR + +Specifies the directory to upload to. Default is uploads. If not specified, the environment variable \fBUPLOADS\(ulDIR\fR is used. If that is not exported, the default, /uploads, is used. +.TP 10 +\fIsource\(ulfile\fR + +Specifies the name of files to copy to this system, relative to the current directory. Multiple files may be listed. +.TP 10 +\fIdest\(ulfile\fR + +Specifies the name of the file or directory on this system to copy to. It is relative to \fIupload\(uldir\fR/\fIHOSTNAME\fR .A local directory within \fIupload\(uldir\fR/ is created for each hostname. + +.IP +Each uploaded file is copied to upload\(uldir/\fIHOSTNAME\fR/\fIdest\(ulfile\fR within the local system. +.IP +If more than one source file is specified or dest\(ulfile has a trailing / , a dest\(ulfile directory will be created. +.SH Example +# upload two files from 2 hosts +.br + +opauploadall -h \[aq]arwen elrond\[aq] capture.tgz /etc/init.d/ipoib.cfg. +.br + + +.br + +# upload two files from all hosts +.br + +opauploadall -p capture.tgz /etc/init.d/ipoib.cfg. +.br + + +.br + +# upload network config files from all hosts +.br + +opauploadall capture.tgz /etc/init.d/ipoib.cfg pre-install +.SH Environment Variables + +.PP +The following environment variables are also used by this command: +.TP 10 +\fBHOSTS\fR + +List of hosts; used if -h option not supplied. + +.TP 10 +\fBHOSTS\(ulFILE\fR + +File containing list of hosts; used in absence of -f and -h. + +.TP 10 +\fBUPLOADS\(ulDIR\fR + +Directory to upload to, used in absence of -d. + +.TP 10 +\fBFF\(ulMAX\(ulPARALLEL\fR + +When the -p option is used, maximum concurrent operations are performed. diff --git a/IbaTools/man/opaverifyhosts.manPage b/IbaTools/man/opaverifyhosts.manPage new file mode 100644 index 0000000..f92f204 --- /dev/null +++ b/IbaTools/man/opaverifyhosts.manPage @@ -0,0 +1,115 @@ +.\" .\" ********************************************************************* +.\" .\" * * +.\" .\" * Copyright 2015-2019, Intel Corporation * +.\" .\" * * +.\" .\" * All Rights Reserved. * +.\" .\" * * +.\" .\" ********************************************************************* + +.TH opaverifyhosts 8 "Intel Corporation" "Copyright(C) 2015\-2019" "IFSFFCLIRG (Man Page)" +.SH NAME +opaverifyhosts + + +.PP +Verifies basic node configuration and performance by running FF\(ulHOSTVERIFY\(ulDIR/hostverify.sh on all specified hosts. +.PP + +.B NOTE: +Prior to using opaverifyhosts, copy the sample file /usr/share/opa/samples/hostverify.sh to FF\(ulHOSTVERIFY\(ulDIR and edit it to set the appropriate configuration and performance expectations and select which tests to run by default. On the first run for a given node, use the -c option so that hostverify.sh gets copied to each node. + +.PP +FF\(ulHOSTVERIFY\(ulDIR defines both the location of hostverify.sh and the destination of the hostverify.res output file. FF\(ulHOSTVERIFY\(ulDIR is configured in the /etc/opa/opafastfabric.conf file. +.PP +A summary of results is appended to the FF\(ulRESULT\(ulDIR/verifyhosts.res file. A punchlist of failures is also appended to the FF\(ulRESULT\(ulDIR/punchlist.csv file. Only failures are shown on stdout. + +.SH Syntax +opaverifyhosts [-kc] [-f \fIhostfile\fR] [-u \fIupload\(ulfile\fR] [-d \fIupload\(uldir\fR] +.br + +[-h \fIhosts\fR] [-T \fItimelimit\fR] [-F \fIfilename\fR] [ \fItest\fR ...] +.SH Options + +.TP 10 +--help + +Produces full help text. + +.TP 10 +-k + +At start and end of verification, kills any existing hostverify or xhpl jobs on the hosts. + +.TP 10 +-c + +Copies hostverify.sh to hosts first, useful if you have edited it. + +.TP 10 +-f \fIhostfile\fR + +Specifies the file with hosts in cluster. +.br +Default is /etc/opa/hosts. + +.TP 10 +-h \fIhosts\fR + +Specifies the list of hosts to ping. + +.TP 10 +-u \fIupload\(ulfile\fR + +Specifies the filename to upload hostverify.res to after verification to allow backup and review of the detailed results for each node. The default upload destination file is hostverify.res. If -u \[aq]\[aq] is specified, no upload occurs. + +.TP 10 +-d \fIupload\(uldir\fR + +Specifies the directory to upload result from each host to. Default is uploads. + +.TP 10 +-T \fItimelimit\fR + +Specifies the time limit in seconds for host to complete tests. Default is 300 seconds (5 minutes). + +.TP 10 +-F \fIfilename\fR + +Specifies the filename of hostverify script to use. Default is /root/hostverify.sh. + +.TP 10 +\fItest\fR + +Specifies one or more specific tests to run. See +.br +/usr/share/opa/samples/hostverify.sh for a list of available tests. + +.SH Examples +opaverifyhosts -c +.br + +opaverifyhosts -h \[aq]arwen elrond\[aq] +.br + +HOSTS=\[aq]arwen elrond\[aq] opaverifyhosts +.SH Environment Variables + +.TP 10 +\fBHOSTS\fR + +List of hosts, used if -h option not supplied. + +.TP 10 +\fBHOSTS\(ulFILE\fR + +File containing list of hosts, used in absence of -f and -h. + +.TP 10 +\fBUPLOADS\(ulDIR\fR + +Directory to upload to, used in absence of -d. + +.TP 10 +\fBFF\(ulMAX\(ulPARALLEL\fR + +Maximum concurrent operations. diff --git a/IbaTools/man/opaxlattopology.manPage b/IbaTools/man/opaxlattopology.manPage new file mode 100644 index 0000000..e58b6a7 --- /dev/null +++ b/IbaTools/man/opaxlattopology.manPage @@ -0,0 +1,266 @@ +.\" .\" ********************************************************************* +.\" .\" * * +.\" .\" * Copyright 2015-2019, Intel Corporation * +.\" .\" * * +.\" .\" * All Rights Reserved. * +.\" .\" * * +.\" .\" ********************************************************************* + +.TH opaxlattopology 8 "Intel Corporation" "Copyright(C) 2015\-2019" "IFSFFCLIRG (Man Page)" +.SH NAME +opaxlattopology + + +.PP +Generates a topology XML file of a cluster using your customized .csv, linksum\(ulswd06.csv, and linksum\(ulswd24.csv as input. The output topology XML file can be used to bring up and verify the cluster. +.PP + +.B NOTE: +The .csv input file must be present in the same directory from which the script operates, but the linksum CSV files are read from the /usr/share/opa/samples directory. + +.SH Syntax +opaxlattopology [-d \fIlevel\fR] [-v \fIlevel\fR] [-i \fIlevel\fR] [-K] [-s \fIhfi\(ulsuffix\fR] +.br + +[source [dest]] +.SH Options + +.TP 10 +--help + +Produces full help text. + +.TP 10 +-d \fIlevel\fR + +Specifies the output detail level. Default is 0. Levels are additive. + +.IP +By default, the top level is always produced. Switch, rack, and rack group topology files can be added to the output by choosing the appropriate level. If the output at the group or rack level is specified, then group or rack names must be provided in the spreadsheet. Detailed output can be specified in any combination. A directory for each topology XML file is created hierarchically, with group directories (if specified) at the highest level, followed by rack and switch directories (if specified). +.RS +.TP 10 + +.sp +1 +Intel(R) Omni-Path Edge Switch 100 Series topology files. + +.RE + +.RS +.TP 10 + +.sp +2 +Rack topology files. + +.RE + +.RS +.TP 10 + +.sp +4 +Rack group topology files. + +.RE + +.TP 10 +-v \fIlevel\fR + +Specifies the verbose level. Range is 0 - 8. Default is 2. + +.RS +.TP 10 + +.sp +0 +No output. + +.RE + +.RS +.TP 10 + +.sp +1 +Progress output. + +.RE + +.RS +.TP 10 + +.sp +2 +Reserved. + +.RE + +.RS +.TP 10 + +.sp +4 +Time stamps. + +.RE + +.RS +.TP 10 + +.sp +8 +Reserved. + +.RE + +.TP 10 +-i \fIlevel\fR + +Specifies the output indent level. Default is 4. + +.TP 10 +-K + +Specifies DO NOT clean temporary files. + +.IP +Prevents temporary files in each topology directory from being removed. Temporary files contain CSV formatted lists of links, HFIs, and switches used to create a topology XML file. Temporary files are not typically needed after a topology file is created, however they are used for creating linksum\(ulswd06.csv and linksum\(ulswd24.csv files, or can be retained for subsequent inspection or processing. +.TP 10 +-s \fIhfi\(ulsuffix\fR + +Used on Multi-Rail or Multi-Plane fabrics. Can be used to override the default hfi1\(ul0. + +.IP +For Multi-Plane fabric, use the tool multiple times with a different hfi-suffix. +.IP +For Multi-Rail fabric, specify HostName as "HostName HfiName" in the spreadsheet. +.TP 10 +-o report + +Specifies the report type for output. By default, all the sections are generated. + +.IP +Report Types: +.RS +.TP 10 + +.sp +brnodes +Creates the section xml for the csv input. + +.RE + +.RS +.TP 10 + +.sp +links +Creates the section xml for the csv input. + +.RE + +.TP 10 +source + +Specifies the source csv file. Default is topology.csv. + +.TP 10 +dest + +Specifies the output xml file. Default is topology.0:0.xml + +.IP +The default output file name may vary if used with -s option. It can also be used to specify destination folder. +.SH Description + +.PP +The opaxlattopology script reads your customized .csv file from the local directory, and reads the other files from /usr/share/opa/samples/linksum\(ulswd06.csv and /usr/share/opa/samples/linksum\(ulswd24.csv. Two sample topology XLSX files, detailed\(ultopology.xlsx and minimal\(ultopology.xlsx, are located in the /usr/share/opa/samples/ directory. You must create your .csv file by editing one of the sample spreadsheets and saving the Fabric Links tab as a CSV file. Inspect your .csv file to ensure that each row contains the correct and same number of comma separators. Any extraneous entries in the spreadsheet can cause the CSV output to have extra fields. +.PP +The script outputs one or more topology files starting with topology.0:0.xml. Your .csv input file must be present in the same directory from which the script operates, but the linksum CSV files are read from the /usr/share/opa/samples directory. +.SH Example +opaxlattopology +.br + +# reads default input \[aq]topology.csv\[aq] and creates default +.br + +# output \[aq]topology.0:0.xml\[aq] +.br + + +.br + +opaxlattopology fabric\(ul2.csv +.br + +# reads input \[aq]fabric\(ul2.csv\[aq] and creates default output +.PP +Both sample files contain examples of links between HFI and Edge SW (rows 4-7), HFI and Core SW (rows 8-11), and Edge SW and Core SW (rows 12-15). +.SH Environment Variables + +.PP +The following environment variables allow user-specified MTU. +.TP 10 +\fBMTU\(ulSW\(ulSW\fR + +If set, it overrides default MTU on switch-to-switch links. Default is 10240 + +.TP 10 +\fBMTU\(ulSW\(ulHFI\fR + +If set, it overrides default MTU on switch-to-HFI links. Default is 10240 + +.SH Creating linksum Files + +.PP +The linksum\(ulswd06.csv and linksum\(ulswd24.csv files are provided as stand-alone files in the /usr/share/opa/samples directory. However, they can be recreated (or modified) from the spreadsheet, if needed, by performing the following steps: + +.IP 1) 4n +Save each of the following from your custom .xlsx file as individual .csv files: +.IP \(bu +Internal SWD06 Links tab as linksum\(ulswd06.csv +.IP \(bu +Internal SWD24 Links tab as linksum\(ulswd24.csv +.IP \(bu +Fabric Links tab as .csv + +.IP 2) 4n +For each saved .csv file, run the script with the -K option. + +.IP 3) 4n +Upon completion of the script, save the top level linksum.csv file as linksum\(ulswd06.csv or linksum\(ulswd24.csv as appropriate. + +.SH Multi-Rail and Multi-Plane Fabrics + +.PP +By default, the opaxlattopology script considers all of the hosts to have a single HFI (hfi1\(ul0). +.PP +For Multi-Rail/Multi-Plane fabrics, you have the following options: +.IP \(bu +For Multi-Rail fabrics or for a Single Plane fabric with some multi-ported hosts, you can edit the Host Name in your customized .csv file to include the HFI Name (for example: HostName HfiName) and then follow the standard procedure to generate .xml. +.IP \(bu +For a Multi-Plane fabric with identical planes, the tool can be run multiple times on the same .csv with different -s hfi\(ulsuffix options. +For example, if there are two identical fabrics (fabric\(ul1 and fabric\(ul2) connected to a single host with two HFIs (hfi1\(ul0 and hfi1\(ul1), the tool can be run twice like this: + +.IP \(bu +For fabric\(ul1: + +.br +opaxlattopology .csv .xml + +.br + + +.IP \(bu +For fabric\(ul2: + +.br +opaxlattopology -s hfi1\(ul1 .csv .xml + +.br + + + +.IP \(bu +For a fabric with both Multi-Rail and Multi-Plane segments, you can use a combination of the above techniques to generate the desired .xml file. diff --git a/IbaTools/man/opaxmlextract.manPage b/IbaTools/man/opaxmlextract.manPage new file mode 100644 index 0000000..a2bde78 --- /dev/null +++ b/IbaTools/man/opaxmlextract.manPage @@ -0,0 +1,202 @@ +.\" .\" ********************************************************************* +.\" .\" * * +.\" .\" * Copyright 2015-2019, Intel Corporation * +.\" .\" * * +.\" .\" * All Rights Reserved. * +.\" .\" * * +.\" .\" ********************************************************************* + +.TH opaxmlextract 8 "Intel Corporation" "Copyright(C) 2015\-2019" "IFSFFCLIRG (Man Page)" +.SH NAME +opaxmlextract + + +.PP + +\fB(Linux)\fR +Extracts element values from XML input and outputs the data in CSV format. opaxmlextract is intended to be used with opareport, to parse and filter its XML output, and to allow the filtered output to be imported into other tools such as spreadsheets and customer-written scripts. opaxmlextract can also be used with any well-formed XML stream to extract element values into a delimited format. +.PP +Five sample scripts are available as prototypes for customized scripts. They combine various calls to opareport with a call to opaxmlextract with commonly used parameters. +.SH Syntax +opaxmlextract [-v][-H][-d \fIdelimiter\fR][-e \fIextract\(ulelement\fR] +.br + +[-s \fIsuppress\(ulelement\fR][-X \fIinput\(ulfile\fR] [-P \fIparam\(ulfile\fR] +.SH Options + +.TP 10 +--help + +Produces full help text. + +.TP 10 +-v/--verbose + +Produces verbose output. Includes output progress reports during extraction and output prepended wildcard characters on element names in output header record. + +.TP 10 +-H/--noheader + +Does not output element name header record. + +.TP 10 +-d/--delimit \fIdelimiter\fR + +Uses single character or string as the delimiter between element names and element values. Default is semicolon. + +.TP 10 +-e/--extract \fIextract\(ulelement\fR + +Specifies the name of the XML element to extract. Elements can be nested in any order, but are output in the order specified. Elements can be specified multiple times, with a different attribute name or attribute value. An optional attribute (or attribute and value) can also be specified with elements: + +.RS + +.IP \(bu +-e \fIelement\fR +.IP \(bu +-e \fIelement:attrName\fR +.IP \(bu +-e \fIelement:attrName:attrValue\fR + +.RE + +.TP 10 +.BR + +.PP + +.B NOTE: + +.RS + +.IP \(bu +Elements can be compound values separated by a dot. For example, Switches.Node is a Node element contained within a Switches element. +.IP \(bu +To output the attribute value as opposed to the element value, a specification such as -e FIs.Node:id can be used. This will return the value of the id attribute of any Node elements within FIs element. +.IP \(bu +If desired, a specific element can be selected by its attribute value, such as -e MulticastFDB.Value:LID:0xc000 which will return the value of the Value element within Multicast FDB element where the Value element has an attribute of LID with a value of 0xc000. +.IP \(bu +A given element can be specified multiple times each with a different AttrName or attrValue. + +.RE + + +.TP 10 +-s/--suppress \fIsuppress\(ulelement\fR + +Specifies the name of the XML element to suppress extraction. Can be used multiple times (in any order). Supports the same syntax as -e. + +.TP 10 +-X/--infile \fIinput\(ulfile\fR + +Parses XML from \fIinput\(ulfile\fR. + +.TP 10 +-P/--pfile \fIparam\(ulfile\fR + +Reads command parameters from param\(ulfile. + +.SH Example + +.PP +Here is an example of opareport output filtered by opaxmlextract : +.PP + +.br +# opareport -o comps -s -x | opaxmlextract -d \; -e NodeDesc +.br + +-e SystemImageGUID -e NumPorts -s Neighbor +.br + +Getting All Node Records... +.br + +Done Getting All Node Records +.br + +Done Getting All Link Records +.br + +Done Getting All Cable Info Records +.br + +Done Getting All SM Info Records +.br + +Getting All Port Counters... +.br + +Done Getting All Port Counters +.br + +NodeDesc;SystemImageGUID;NumPorts +.br + +phs1fnivd13u07n4 hfi1\(ul0;0x00117501016033c7;1 +.br + +phs1fnivd13u07n2 hfi1\(ul0;0x00117501016033ef;1 +.br + +phs1fnivd13u07n1 hfi1\(ul0;0x001175010160347a;1 +.br + +phs1fnivd13u07n3 hfi1\(ul0;0x0011750101603593;1 +.br + +phs1swivd13u21;0x00117501ff6a5619;48 +.br + +phs1fnivd13u07n1 hfi1\(ul0;; +.br + + +.br + +.SH Details + +.PP +opaxmlextract is a flexible and powerful tool to process an XML stream. The tool: +.IP \(bu +Requires no specific element names to be present in the XML. +.IP \(bu +Assumes no hierarchical relationship between elements. +.IP \(bu +Allows extracted element values to be output in any order. +.IP \(bu +Allows an element\[aq]s value to be extracted only in the context of another specified element. +.IP \(bu +Allows extraction to be suppressed during the scope of specified elements. +.PP +opaxmlextract takes the XML input stream from either stdin or a specified input file. opaxmlextract does not use or require a connection to a fabric. +.PP +opaxmlextract works from two lists of elements supplied as command line or input parameters. The first is a list of elements whose values are to be extracted, called extraction elements. The second is a list of elements for which extraction is to be suppressed, called suppression elements. When an extraction element is encountered and extraction is not suppressed, the value of the element is extracted for later output in an extraction record. An extraction record contains a value for all extraction elements, including those which have a null value. +.PP +When a suppression element is encountered, then no extraction is performed during the extent of that element, from start through end. Suppression is maintained for elements specified inside the suppression element, including elements which may happen to match extraction elements. Suppression can be used to prevent extraction in sections of XML that are present, but not of current interest. For example, NodeDesc or NodeGUID inside a Neighbor specification of opareport. +.PP +opaxmlextract attempts to generate extraction records with data values that are valid at the same time. Specifying extraction elements that are valid in the same scope produces a single record for each group of extraction elements. However, mixing extraction elements from different scopes (including different XML levels) may cause opaxmlextract to produce multiple records. +.PP +opaxmlextract outputs an extraction record under the following conditions: +.IP \(bu +One or more extraction elements containing a non-null value go out of scope (that is, the element containing the extraction elements is ended) and a record containing the element values has not already been output. +.IP \(bu +A new and different value is specified for an extraction element and an extraction record containing the previous value has not already been output. +.PP +Element names (extraction or suppression) can be made context-sensitive with an enclosing element name using the syntax element1.element2. In this case, element2 is extracted (or extraction is suppressed) only when element2 is enclosed by element1. +.PP +The syntax also allows \[aq] * \[aq] to be specified as a wildcard. In this case, *.element3 specifies element3 enclosed by any element or sequence of elements (for example, element1.element3 or element1.element2.element3). Similarly, element1.*.element3 specifies element3 enclosed by element1 with any number of (but at least 1) intermediate elements. +.PP +opaxmlextract prepends any entered element name not containing a \[aq] * \[aq] (anywhere) with \[aq] *. \[aq], matching the element regardless of the enclosing elements. +.PP + +.B NOTE: +Any element names that include a wildcard should be quoted to the shell attempting to wildcard match against filenames. + + +.PP +At the beginning of operation, opaxmlextract, by default, outputs a delimited header record containing the names of the extraction elements. The order of the names is the same as specified on the command line and is the same order as that of the extraction record. Output of the header record can be disabled with the -H option. By default, element names are shown as they were entered on the command line. The -v option causes element names to be output as they are used during extraction, with any prepended wildcard characters. +.PP +Options (parameters) to opaxmlextract can be specified on the command line, with a parameter file, or using both methods. A parameter file is specified with -P \fIparam\(ulfile\fR. When a parameter file specification is encountered on the command line, option processing on the command line is suspended, the parameter file is read and processed entirely, and then command line processing is resumed. +.PP +Option syntax within a parameter file is the same as on the command line. Multiple parameter file specifications can be made, on the command line or within other parameter files. At each point that a parameter file is specified, current option processing is suspended while the parameter file is processed, then resumed. Options are processed in the order they are encountered on the command line or in parameter files. A parameter file can be up to 8192 bytes in size and may contain up to 512 parameters. diff --git a/IbaTools/man/opaxmlfilter.manPage b/IbaTools/man/opaxmlfilter.manPage new file mode 100644 index 0000000..12c8fed --- /dev/null +++ b/IbaTools/man/opaxmlfilter.manPage @@ -0,0 +1,53 @@ +.\" .\" ********************************************************************* +.\" .\" * * +.\" .\" * Copyright 2015-2019, Intel Corporation * +.\" .\" * * +.\" .\" * All Rights Reserved. * +.\" .\" * * +.\" .\" ********************************************************************* + +.TH opaxmlfilter 8 "Intel Corporation" "Copyright(C) 2015\-2019" "IFSFFCLIRG (Man Page)" +.SH NAME +opaxmlfilter + + +.PP +Processes an XML file and removes all specified XML tags. The remaining tags are output and indentation can also be reformatted. opaxmlfilter is the opposite of opaxmlextract. +.SH Syntax +opaxmlfilter [-t|-k] [-l] [-i \fIindent\fR] [-s \fIelement\fR] \fI[input\(ulfile]\fR +.SH Options + +.TP 10 +--help + +Produces full help text. + +.TP 10 +-t + +Trims leading and trailing whitespace in tag contents. + +.TP 10 +-k + +In tags with purely whitespace that contain newlines, keeps newlines as-is. Default is to format as an empty list. + +.TP 10 +-l + +Adds comments with line numbers after each end tag. This can make comparison of resulting files easier since original line numbers are available. + +.TP 10 +-i \fIindent\fR + +Sets indentation to use per level. Default is 4. + +.TP 10 +-s \fIelement\fR + +Specifies the name of the XML element to suppress. Can be used multiple times (maximum of 100) in any order. + +.TP 10 +\fIinput\(ulfile\fR + +Specifies the XML file to read. Default is stdin. diff --git a/IbaTools/man/opaxmlgenerate.manPage b/IbaTools/man/opaxmlgenerate.manPage new file mode 100644 index 0000000..fd0f8ad --- /dev/null +++ b/IbaTools/man/opaxmlgenerate.manPage @@ -0,0 +1,103 @@ +.\" .\" ********************************************************************* +.\" .\" * * +.\" .\" * Copyright 2015-2019, Intel Corporation * +.\" .\" * * +.\" .\" * All Rights Reserved. * +.\" .\" * * +.\" .\" ********************************************************************* + +.TH opaxmlgenerate 8 "Intel Corporation" "Copyright(C) 2015\-2019" "IFSFFCLIRG (Man Page)" +.SH NAME +opaxmlgenerate + + +.PP + +\fB(Linux)\fR +Takes comma-separated-values (CSV) data as input and generates sequences of XML containing user-specified element names and element values within start and end tag specifications. Use this tool to create an XML representation of fabric data from its CSV form. +.SH Syntax +opaxmlgenerate [-v] [-d \fIdelimiter\fR] [-i \fInumber\fR] [-g \fIelement\fR] +.br + +[-h \fIelement\fR] [-e \fIelement\fR] [-X \fIinput\(ulfile\fR] [-P \fIparam\(ulfile\fR] +.SH Options + +.TP 10 +--help + +Produces full help text. + +.TP 10 +-g/--generate \fIelement\fR + +Generates value for \fIelement\fR using value in next field from the input file. Can be used multiple times on the command line. Values are assigned to elements in order. + +.TP 10 +-h/--header \fIelement\fR + +Name of the XML element that is the enclosing header start tag. + +.TP 10 +-e/--end \fIelement\fR + +Name of the XML element that is the enclosing header end tag. + +.TP 10 +-d/--delimit \fIdelimiter\fR + +Specifies the delimiter character that separates values in the input file. Default is semicolon. + +.TP 10 +-i/--indent \fInumber\fR + +Number of spaces to indent each level of XML output. Default is 0. + +.TP 10 +-X/--infile \fIinput\(ulfile\fR + +Generates XML from CSV in input\(ulfile. One record per line with fields in each record separated by the specified delimiter. + +.TP 10 +-P/--pfile \fIparam\(ulfile\fR + +Uses input command line options (parameters) from param\(ulfile. + +.TP 10 +-v/--verbose + +Produces verbose output. Includes output progress reports during extraction. + + +.SH Details + +.PP +opaxmlgenerate takes the CSV data from an input file. It generates fragments of XML, and in combination with a script, can be used to generate complete XML sequences. opaxmlgenerate does not use nor require a connection to an Intel(R) Omni-Path Fabric. +.PP +opaxmlgenerate reads CSV element values and applies element (tag) names to those values. The element names are supplied as command line options to the tool and constitute a template that is applied to the input. +.PP +Element names on the command line are of three (3) types, distinguished by their command line option - Generate, Header, and Header\(ulEnd. The Header and Header\(ulEnd types together constitute enclosing element types. Enclosing elements do not contain a value, but serve to separate and organize Generate elements. +.PP +Generate elements, along with a value from the CSV input file, cause XML in the form of \fIvalue\fR to be generated. Generate elements are normally the majority of the XML output since they specify elements containing the input values. Header elements cause an XML header start tag of the form: to be generated. Header\(ulEnd elements cause an XML header end tag of the form to be generated. Output of enclosing elements is controlled entirely by the placement of those element types on the command line. opaxmlgenerate does +\fBnot\fR +check for matching start and end tags or proper nesting of tags. +.PP +Options (parameters) to opaxmlgenerate can be specified on the command line, with a parameter file, or both. A parameter file is specified with -P \fIparam\(ulfile\fR. When a parameter file specification is encountered on the command line, option processing on the command line is suspended, the parameter file is read and processed entirely, and then command line processing is resumed. Option syntax within a parameter file is the same as on the command line. Multiple parameter file specifications can be made, on the command line or within other parameter files. At each point that a parameter file is specified, current option processing is suspended while the parameter file is processed, then resumed. Options are processed in the order they are encountered on the command line or in parameter files. A parameter file can be up to 8192 bytes in size and may contain up to 512 parameters. + +.SH Using opaxmlgenerate to Create Topology Input Files + +.PP +opaxmlgenerate can be used to create scripts to translate from user-specific format into the opareport topology\(ulinput file format. opaxmlgenerate itself works against a CSV style file with one line per record. Given such a file it can produce hierarchical XML output of arbitrary complexity and depth. +.PP +The typical flow for a script which translates from a user-specific format into opareport topology\(ulinput would be: +.IP \(bu +As needed, reorganize the data into link and node data CSV files, in a sequencing similar to that used by opareport topology\(ulinput. One link record per line in one temporary file, one node record per line in another temporary file and one SM per line in a third temporary file. +.IP \(bu +The script must directly output the boilerplate for XML version, etc. +.IP \(bu +opaxmlgenerate can be used to output the Link section of the topology\(ulinput, using the link record temporary file. +.IP \(bu +opaxmlgenerate can be used to output the Node sections of the topology\(ulinput using the node record temporary file. If desired, there could be separate node record temporary files for HFIs and Switches. +.IP \(bu +opaxmlgenerate can be used to output the SM section of the topology\(ulinput, if desired. +.IP \(bu +The script must directly output the closing XML tags to complete the topology\(ulinput file. diff --git a/IbaTools/man/opaxmlindent.manPage b/IbaTools/man/opaxmlindent.manPage new file mode 100644 index 0000000..a7b5fb8 --- /dev/null +++ b/IbaTools/man/opaxmlindent.manPage @@ -0,0 +1,45 @@ +.\" .\" ********************************************************************* +.\" .\" * * +.\" .\" * Copyright 2015-2019, Intel Corporation * +.\" .\" * * +.\" .\" * All Rights Reserved. * +.\" .\" * * +.\" .\" ********************************************************************* + +.TH opaxmlindent 8 "Intel Corporation" "Copyright(C) 2015\-2019" "IFSFFCLIRG (Man Page)" +.SH NAME +opaxmlindent + + +.PP + +\fB(Linux)\fR +Takes well-formed XML as input, filters out comments, and generates a uniformly-indented equivalent XML file. Use opaxmlindent to reformat files for easier reading and review, also to reformat a file for easy comparison with diff. +.SH Syntax +opaxmlindent [-t|-k] [-i \fIindent\fR] [ \fIinput\(ulfile\fR] +.SH Options + +.TP 10 +--help + +Produces full help text. + +.TP 10 +-t + +Trims leading and trailing whitespace in tag contents. + +.TP 10 +-k + +In tags with purely whitespace that contain newlines, keeps newlines as-is. Default is to format as an empty list. + +.TP 10 +-i \fIindent\fR + +Sets indentation to use per level. Default is 4. + +.TP 10 +\fIinput\(ulfile\fR + +Specifies the XML file to read. Default is stdin. diff --git a/IbaTools/nodeverify/Makefile b/IbaTools/nodeverify/Makefile new file mode 100644 index 0000000..7b5c1e5 --- /dev/null +++ b/IbaTools/nodeverify/Makefile @@ -0,0 +1,162 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** +# Makefile for nodeverify + +# Include Make Control Settings +include $(TL_DIR)/$(PROJ_FILE_DIR)/Makesettings.project + +#=============================================================================# +# Definitions: +#-----------------------------------------------------------------------------# + +# Name of SubProjects +DS_SUBPROJECTS = +# name of executable or downloadable image +EXECUTABLE = #$(BUILDDIR)/nodeverify$(EXE_SUFFIX) +# list of sub directories to build +DIRS = +# C files (.c) +CFILES = \ + # Add more c files here +# C++ files (.cpp) +CCFILES = \ + # Add more cpp files here +# lex files (.lex) +LFILES = \ + # Add more lex files here +# archive library files (basename, $ARFILES will add MOD_LIB_DIR/prefix and suffix) +LIBFILES= +# Windows Resource Files (.rc) +RSCFILES = +# Windows IDL File (.idl) +IDLFILE = +# Windows Linker Module Definitions (.def) file for dll's +DEFFILE = +# targets to build during INCLUDES phase (add public includes here) +INCLUDE_TARGETS = \ + # Add more h hpp files here + +# Non-compiled files +MISC_FILES = + +# all source files +SOURCES = $(CFILES) $(CCFILES) $(LFILES) $(RSCFILES) $(IDLFILE) +# Source files to include in DSP File +DSP_SOURCES = $(INCLUDE_TARGETS) $(SOURCES) $(MISC_FILES) \ + $(RSCFILES) $(DEFFILE) $(MAKEFILE) +# all object files +OBJECTS = $(CFILES:.c=$(OBJ_SUFFIX)) $(CCFILES:.cpp=$(OBJ_SUFFIX)) \ + $(LFILES:.lex=$(OBJ_SUFFIX)) +RSCOBJECTS = $(RSCFILES:.rc=$(RES_SUFFIX)) +# targets to build during LIBS phase +LIB_TARGETS_IMPLIB = +LIB_TARGETS_ARLIB = # $(LIB_PREFIX)ResourceTest$(ARLIB_SUFFIX) +LIB_TARGETS_EXP = $(LIB_TARGETS_IMPLIB:$(ARLIB_SUFFIX)=$(EXP_SUFFIX)) +LIB_TARGETS_MISC = +# targets to build during CMDS phase +CMD_TARGETS_SHLIB = +CMD_TARGETS_EXE = $(EXECUTABLE) +CMD_TARGETS_MISC = opaverifyhosts hostverify.sh +# files to remove during clean phase +CLEAN_TARGETS_MISC = +CLEAN_TARGETS = $(OBJECTS) $(RSCOBJECTS) $(IDL_TARGETS) $(CLEAN_TARGETS_MISC) +# other files to remove during clobber phase +CLOBBER_TARGETS_MISC= nodeverify.sh +# sub-directory to install to within bin +BIN_SUBDIR = +# sub-directory to install to within include +INCLUDE_SUBDIR = + +# Additional Settings +#CLOCALDEBUG = User defined C debugging compilation flags [Empty] +#CCLOCALDEBUG = User defined C++ debugging compilation flags [Empty] +#CLOCAL = User defined C flags for compiling [Empty] +#CCLOCAL = User defined C++ flags for compiling [Empty] +#BSCLOCAL = User flags for Browse File Builder [Empty] +#DEPENDLOCAL = user defined makedepend flags [Empty] +#LINTLOCAL = User defined lint flags [Empty] +#LOCAL_INCLUDE_DIRS = User include directories to search for C/C++ headers [Empty] +#LDLOCAL = User defined C flags for linking [Empty] +#IMPLIBLOCAL = User flags for Object Lirary Manager [Empty] +#MIDLLOCAL = User flags for IDL compiler [Empty] +#RSCLOCAL = User flags for resource compiler [Empty] +#LOCALDEPLIBS = User libraries to include in dependencies [Empty] +#LOCALLIBS = User libraries to use when linking [Empty] +# (in addition to LOCALDEPLIBS) +#LOCAL_LIB_DIRS = User library directories for libpaths [Empty] + +CLOCAL = $(CPIE) +# Include Make Rules definitions and rules +include $(TL_DIR)/IbaTools/Makerules.module + +#=============================================================================# +# Overrides: +#-----------------------------------------------------------------------------# +#CCOPT = # C++ optimization flags, default lets build config decide +#COPT = # C optimization flags, default lets build config decide +#SUBSYSTEM = Subsystem to build for (none, console or windows) [none] +# (Windows Only) +#USEMFC = How Windows MFC should be used (none, static, shared, no_mfc) [none] +# (Windows Only) +#=============================================================================# + +#=============================================================================# +# Rules: +#-----------------------------------------------------------------------------# +# process Sub-directories +include $(TL_DIR)/Makerules/Maketargets.toplevel + +# build cmds and libs +include $(TL_DIR)/Makerules/Maketargets.build + +opaverifyhosts: opaverifynodes.sh + $(CP) opaverifynodes.sh opaverifyhosts + chmod +x opaverifyhosts + +hostverify.sh: nodeverify.sh + $(CP) nodeverify.sh hostverify.sh + chmod +x hostverify.sh + +# install for includes, libs and cmds phases +include $(TL_DIR)/Makerules/Maketargets.install + +# install for stage phase +#include $(TL_DIR)/Makerules/Maketargets.stage +STAGE:: + $(VS)$(STAGE_INSTALL) $(STAGE_INSTALL_DIR_OPT) $(PROJ_STAGE_FASTFABRIC_DIR)/samples hostverify.sh + $(VS)$(STAGE_INSTALL) $(STAGE_INSTALL_DIR_OPT) $(PROJ_STAGE_FASTFABRIC_DIR) opaverifyhosts + +# Unit test execution +#include $(TL_DIR)/Makerules/Maketargets.runtest + +#=============================================================================# + +#=============================================================================# +# DO NOT DELETE THIS LINE -- make depend depends on it. +#=============================================================================# diff --git a/IbaTools/nodeverify/nodeverify.sh b/IbaTools/nodeverify/nodeverify.sh new file mode 100755 index 0000000..0e6556a --- /dev/null +++ b/IbaTools/nodeverify/nodeverify.sh @@ -0,0 +1,975 @@ +#!/bin/bash +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2018, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] + + +# script to verify configuration and performance of an individual node +# this should be run using opaverifyhosts. It can also be run on an individual +# node directly. + +# The following specify expected minimal configuration and performance +MEMSIZE_EXPECTED=30601808 # size of memory (MemTotal) in k as shown in + # /proc/meminfo +HFI_COUNT=1 # expected Number of Intel HFIs +HFI_CPU_CORE[0]=1 # CPU core to use when testing HFI 0 PCI performance +HFI_CPU_CORE[1]=1 # CPU core to use when testing HFI 1 PCI performance +HFI_CPU_CORE[2]=1 # CPU core to use when testing HFI 2 PCI performance +HFI_CPU_CORE[3]=1 # CPU core to use when testing HFI 3 PCI performance + # On some servers, such as Sandy-Bridge, it is + # recommended to set the CPU CORE for each HFI to + # a core within the same CPU socket the HFI's PCI + # bus is connected to +PCI_MAXPAYLOAD=256 # expected value for PCI max payload +PCI_MINREADREQ=512 # expected value for PCI min read req size +PCI_MAXREADREQ=4096 # expected value for PCI max read req size +PCI_SPEED="8GT/s" # expected value for PCI speed on Intel WFR HFI +PCI_WIDTH="x16" # expected value for PCI width on Intel WFR HFI +MPI_APPS=$HOME/mpi_apps/ # where to find mpi_apps for HPL test +MIN_FLOPS="115" # minimum flops expected from HPL test +IPOIB_IF="ib0" # IPoIB interface to check +IPOIB_MODE="connected" # IPoIB required mode "connected" or "datagram" +IPOIB_MTU=65520 # IPoIB required MTU +outputdir=/root # default outputdir is root -d $DIR overrides +CPU_DRIVER="intel_pstate" # power scaling driver for CPU +CPU_GOVERNOR="performance" # scaling governor for CPU +STREAM_MIN_BW=40000 # minimum Triad bandwidth for each run of the + # STREAM memory benchmark (MB/s) + +# If desired, single node HPL can be run, using the parameters defined below. +# +# The goal of the single node HPL test is to check node stability and the +# consistency of performance between hosts, NOT to optimize performance. +# As such a small problem size, such as '16s' is recommended since it will run +# faster and will still be equally good at discovering slow or unstable hosts. +# The given problem size should be run on a known good node and the result +# can be used to select an appropriate MIN_FLOPS value for other hosts. It +# may be necessary to set MIN_FLOPS slightly below the observed result for +# the known good host to account for minor variations in OS background +# overhead, manufacturing variations, etc. + +# When using HPL, the problem size will automatically be adjusted to match +# the number of cores on the host, but this can be overridden by setting +# the HPL_CORES variable. +# +# The size can also be adjusted to consume a percentage of system memory +# by adjusting the HPL_PRESSURE variable up or down between 0.1 and 0.9. +# Note that increasing the value of HPL_PRESSURE will increast the amount +# of time the test will take to execute. + +# In order to run the single node HPL test, each tested host must be able to +# ssh to locahost as root + +# Set this if you don't want the problem size to match the number of cores on +# the target node. +HPL_CORES= + +# By default the problem size will be scaled to consume roughly 30% of RAM on +# the target node. This can be adjusted up or down between 0.0 and 0.9. Note +# that larger values will cause the test to run for a longer time. +HPL_PRESSURE=0.3 + +# can adjust default list of tests below +#TESTS="pcicfg pcispeed initscripts irqbalance hfi_pkt memsize cpu_consist cpu cstates turbo hton htoff ipoib hpl" +TESTS="pcicfg pcispeed initscripts memsize cpu hfi_pkt hton ipoib irqbalance turbo cstates vtd srp stream" + + +Usage() +{ + echo "Usage: ./hostverify.sh [-v] [-d OUTPUTDIR] [test ...]" >&2 + echo " or" >&2 + echo " ./hostverify.sh --help" >&2 + echo " -v - provide verbose output on stdout (by default only PASS/FAIL is output)" >&2 + echo " detailed results are always output to OUTPUTDIR/hostverify.res" >&2 + echo " -d OUTPUTDIR - write detailed results to OUTPUTDIR (defaults to /root)" >&2 + echo " --help - produce full help text" >&2 + echo " test - one or more specific tests to run" >&2 + echo "This verifies basic node configuration and performance" >&2 + echo "Prior to using this, edit it to set proper" >&2 + echo "expectations for node configuration and performance" >&2 + echo >&2 + echo "The following tests are available:" >&2 + echo " pcicfg - verify PCI max payload and max read request size settings" >&2 + echo " pcispeed - verify PCI bus negotiated to PCIe Gen3 x16 speed" >&2 + echo " initscripts - verify powerd and cpuspeed init.d scripts are disabled," >&2 + echo " hfi_pkt - check PCI-HFI bus performance. Requires HFI port is Active" >&2 + echo " memsize - check total size of memory in system" >&2 + echo " vtd - verify that Intel VT-d is disabled" >&2 + echo " hpl - perform a single node HPL test," >&2 + echo " useful to determine if all hosts perform consistently" >&2 + echo " pstates_on - check if Intel P-States are enabled and optimally configured" >&2 + echo " pstates_off - check if Intel P-States are disabled" >&2 + echo " driver_on - check if power scaling driver (default isintel_pstates) enabled" >&2 + echo " generalized version of pstates_on" >&2 + echo " driver_off - check if power scaling driver (default is intel_pstates)" >&2 + echo " generalized version of pstates_off" >&2 + echo " governor - verify proper governor enabled for CPU (default 'performance')" >&2 + echo " cpu_pinned - verify CPU operating at max frequency" >&2 + echo " cpu_unpinned - verify CPU not pinned to max operating frequency" >&2 + echo " pmodules_off - verify other power management modules aren't loaded" >&2 + echo " cpu - check if CPU parameters are configured for optimal performance" >&2 + echo " includes pstates_on and governor tests" >&2 + echo " cpu_consist - check if CPU parameters are configured for most consistent performance" >&2 + echo " includes pstates_off, pmodules_off, governor, and cpu_pinned tests" >&2 + echo " turbo - check if Intel Turbo Boost is enabled" >&2 + echo " cstates - check if Intel C-States are enabled and optimally configured." >&2 + echo " hton - verify that Hyper Threading is enabled" >&2 + echo " htoff - verify that Hyper Threading is disabled" >&2 + echo " ipoib - verify IPoIB is properly configured" >&2 + echo " irqbalance - verify irqbalance is running with proper configuration" >&2 + echo " srp - verify srp daemon is not running" >&2 + echo " stream - verify memory bandwidth" >&2 + echo " default - run all tests selected in TESTS" >&2 + echo >&2 + echo "Detailed output is written to stdout and appended to" >&2 + echo " OUTPUTDIR/hostverify.res" >&2 + echo "egrep 'PASS|FAIL' OUTPUTDIR/hostverify.res for a brief summary" >&2 + echo >&2 + echo "A Intel HFI is required for pcicfg, pcispeed and hfi_pkt tests" >&2 + exit 0 +} + +if [ x"$1" = "x--help" ] +then + Usage +fi + +myfilter() +{ + # filter out the residual report from HPL + egrep 'PASS|FAIL|SKIP'|fgrep -v '||Ax-b||_oo/(eps' +} + +filter=myfilter +while getopts vd: param +do + case $param in + v) filter=cat;; + d) outputdir="$OPTARG";; + ?) Usage;; + esac +done +shift $((OPTIND -1)) + +tests="$TESTS" +if [ $# -ne 0 ] +then + tests= + for i in $* + do + if [ x"$i" == x"default" ] + then + tests="$tests $TESTS" + else + tests="$tests $i" + fi + done +fi + +USEMEM=/usr/lib/opa/tools/usemem # where to find usemem tool +if [ -n "${debug}" ]; then + set -x + set -v +fi + +export LANG=C +unset CDPATH + +TEST=main + +function fail_msg() +{ + set +x + echo "`hostname -s`: FAIL $TEST: $1" +} + +function pass_msg() +{ + set +x + echo "`hostname -s`: PASS $TEST$1" +} + +function fail() +{ + fail_msg "$1" + exit 1 +} + +function pass() +{ + pass_msg "$1" + exit 0 +} + +function skip() +{ + set +x + echo "`hostname -s`: SKIP $TEST$1" + exit 0 +} + +outdir="$(mktemp --tmpdir -d hostverify.XXXXXXXXXX)" || fail "Cannot mktemp --tmpdir -d hostverify.XXXXXXXXXX" + +# verify basic PCIe configuration +test_pcicfg() +{ + TEST=pcicfg + echo "pcicfg ..." + date + + failure=0 + cd "${outdir}" || fail "Can't cd ${outdir}" + + lspci="${lspci:-/sbin/lspci}" + [ ! -x "${lspci}" ] && fail "Can't find lspci" + + # get OmniPath Intel stand-alone WFR HFI + set -x + "${lspci}" -n -d 0x8086:0x24f0 2>pcicfg.stderr | tee -a pcicfg.stdout || fail "Error running lspci" + set +x + [ -s pcicfg.stderr ] && fail "Error during run of lspci: $(cat pcicfg.stderr)" + # also get OmniPath Intel integrated WFR HFI + set -x + "${lspci}" -n -d 0x8086:0x24f1 2>pcicfg.stderr | tee -a pcicfg.stdout || fail "Error running lspci" + set +x + [ -s pcicfg.stderr ] && fail "Error during run of lspci: $(cat pcicfg.stderr)" + + set -x + pci_id=$(egrep -o -m1 "24f[01]" pcicfg.stdout) + if [ -z ${pci_id} ] + then + fail "Error identifying HFI's on the PCI bus" + fi + + + "${lspci}" -vvv -d 0x8086:$pci_id 2>pcicfg.stderr | tee -a pcicfg.stdout || fail "Error running lspci" + set +x + + hfi_count=$(cat pcicfg.stdout|grep 'MaxPayload .* bytes, MaxReadReq .* bytes' | wc -l) + [ $hfi_count -ne $HFI_COUNT ] && { fail_msg "Incorrect number of Intel HFIs: Expect $HFI_COUNT Got: $hfi_count"; failure=1; } + [ $HFI_COUNT -eq 0 ] && pass + + cat pcicfg.stdout|egrep 'MaxPayload .* bytes, MaxReadReq .* bytes|^[0-9]' | + { + failure=0 + device="Unknown" + while read cfgline + do + if echo "$cfgline"|grep '^[0-9]' >/dev/null 2>/dev/null + then + device=$(echo "$cfgline"|cut -f1 -d ' ') + else + result=$(echo "$cfgline"|sed -e 's/.*\(MaxPayload .* bytes, MaxReadReq .* bytes\).*/\1'/) + payload=$(echo "$result"|cut -f2 -d ' ') + readreq=$(echo "$result"|cut -f5 -d ' ') + + [ "$payload" -eq "$PCI_MAXPAYLOAD" ] || { fail_msg "HFI $device: Incorrect MaxPayload of $payload (expected $PCI_MAXPAYLOAD)."; failure=1; } + + [ "$readreq" -le "$PCI_MAXREADREQ" -a "$readreq" -ge "$PCI_MINREADREQ" ] || { fail_msg "HFI $device: MaxReadReq of $readreq out of expected range [$PCI_MINREADREQ,$PCI_MAXREADREQ]."; failure=1; } + + device="Unknown" + fi + done + [ $failure -ne 0 ] && exit 1 + exit 0 + } + [ $failure -ne 0 -o $? != 0 ] && exit 1 # catch any fail calls within while + + pass +} + +# verify PCIe is negotiated at PCIe Gen3 x16 +test_pcispeed() +{ + TEST=pcispeed + echo "pcispeed ..." + date + + failure=0 + cd "${outdir}" || fail "Can't cd ${outdir}" + + lspci="${lspci:-/sbin/lspci}" + [ ! -x "${lspci}" ] && fail "Can't find lspci" + + # get OmniPath Intel stand-alone WFR HFI + set -x + "${lspci}" -n -d 0x8086:0x24f0 2>pcispeed.stderr | tee -a pcispeed.stdout || fail "Error running lspci" + set +x + [ -s pcispeed.stderr ] && fail "Error during run of lspci: $(cat pcispeed.stderr)" + # also get OmniPath Intel integrated WFR HFI + set -x + "${lspci}" -n -d 0x8086:0x24f1 2>pcispeed.stderr | tee -a pcispeed.stdout || fail "Error running lspci" + set +x + [ -s pcispeed.stderr ] && fail "Error during run of lspci: $(cat pcispeed.stderr)" + + set -x + pci_id=$(egrep -o -m1 "24f[01]" pcispeed.stdout) + if [ -z ${pci_id} ] + then + fail "Error identifying HFI's on the PCI bus" + fi + + "${lspci}" -vvv -d 0x8086:$pci_id 2>pcispeed.stderr | tee -a pcispeed.stdout || fail "Error running lspci" + set +x + + hfi_count=$(cat pcispeed.stdout|grep 'Speed .*, Width .*' pcispeed.stdout|egrep -v 'LnkCap|LnkCtl|Supported'| wc -l) + [ $hfi_count -ne $HFI_COUNT ] && { fail_msg "Incorrect number of Intel HFIs: Expect $HFI_COUNT Got: $hfi_count"; failure=1; } + [ $HFI_COUNT -eq 0 ] && pass + + cat pcispeed.stdout|egrep 'Speed .*, Width .*|^[0-9]' pcispeed.stdout|egrep -v 'LnkCap|LnkCtl|Supported'| + { + failure=0 + device="Unknown" + while read cfgline + do + if echo "$cfgline"|grep '^[0-9]' >/dev/null 2>/dev/null + then + device=$(echo "$cfgline"|cut -f1 -d ' ') + else + result=$(echo "$cfgline"|sed -e 's/.*\(Speed .*, Width [^,]*\).*/\1'/) + + expect="Speed $PCI_SPEED, Width $PCI_WIDTH" + [ "$result" = "$expect" ] || { fail_msg "HFI $device: Incorrect Speed or Width: Expect: $expect Got: $result"; failure=1; } + device="Unknown" + fi + done + [ $failure -ne 0 ] && exit 1 + exit 0 + } + [ $failure -ne 0 -o $? != 0 ] && exit 1 # catch any fail calls within while + + pass +} + +# make sure powerd and cpuspeed are disabled +test_initscripts() +{ + TEST="initscripts" + echo "initscripts ..." + date + cd "${outdir}" || fail "Can't cd ${outdir}" + + > chkconfig.out + for i in cpuspeed powerd + do + set -x + if [ -e /etc/init.d/$i ] + then + chkconfig --list $i 2>chkconfig.stderr|tee -a chkconfig.out || fail "Error during chkconfig $i" + [ -s chkconfig.stderr ] && fail "Error during run of chkconfig: $(cat chkconfig.stderr)" + fi + set +x + done + + result=`grep '[2-6]:on' chkconfig.out` + [ -n "${result}" ] && fail "Undesirable service enabled: $result" + + #Now check systemd + for i in cpuspeed powerd + do + set -x + if [ -n "`systemctl list-units | grep $i`" ] + then + [ -n "`systemctl is-enabled $i | grep enabled`" ] && fail "Undesirable systemd service enabled: $i" + fi + set +x + done + + pass +} + +test_irqbalance() +{ + TEST="irqbalance" + echo "irqbalance ..." + date + + set -x + + pid=$(pgrep irqbalance) + [ -z "$pid" ] && fail "irqbalance process not running" + + cmdline=$(ps -o command --no-heading -p $pid) + echo "$cmdline" | grep -q "exact" || fail "irqbalance is NOT running with hint policy 'exact'" + set +x + + pass +} + +#test_nodeperf() +#{ +# TEST="nodeperf" +# echo "nodeperf ..." +# date +# cd "${outdir}" || fail "Can't cd ${outdir}" +# +# if [ -z "${nomemflush}" ]; then +# set -x +# "$USEMEM" 1048576 20737418240 +# set +x +# fi +# +# set -x +# LD_LIBRARY_PATH="${rundir}/lib" "${rundir}/bin/nodeperf" 2>nodeperf.stderr | tee nodeperf.stdout || fail "Failed to run nodeperf" +# set +x +# [ -s nodeperf.stderr ] && cat nodeperf.stdout && fail "Error running nodeperf" +# +# min="${min:-120000}" +# [ -z "${min}" ] && fail "invalid min" +# +# nodeperf=$(cat nodeperf.stdout| grep '0 of 1' | head -1 | cut -d ' ' -f 12) +# [ -z "${nodeperf}" ] && fail "Unable to obtain nodeperf result" +# +# result="$(echo "if ( ${nodeperf} >= ${min} ) { print \"PASS\n\"; } else { print \"FAIL\n\"; }" | bc -lq)" || fail "Unable to analyze nodeperf result" +# [ "${result}" != "PASS" ] && fail "Performance of ${nodeperf} less than min ${min}" +# +# pass +#} + +test_stream() +{ + TEST="stream" + echo "stream ..." + date + + stream="${stream:-/usr/lib/opa/tools/stream}" + [ ! -x "${stream}" ] && fail "Can't find stream" + + for run in 1 2 3; do + if [ -z "${nomemflush}" ]; then + set -x + "$USEMEM" 1048576 20737418240 + set +x + fi + + set -x + "${stream}" 2>stream.stderr |tee stream_${run}.stdout || fail + set +x + [ -s stream.stderr ] && cat stream.stderr && fail "Errors during run" + done + + min="${min:-120000}" + [ -z "${min}" ] && fail "invalid min" + + triadbw1=$(cat stream_1.stdout| grep '^Triad:' | sed -e 's/ */ /g' | cut -d ' ' -f 2) + [ -z "${triadbw1}" ] && fail "Triad result not found" + + triadbw2=$(cat stream_2.stdout| grep '^Triad:' | sed -e 's/ */ /g' | cut -d ' ' -f 2) + [ -z "${triadbw2}" ] && fail "Triad result not found" + + triadbw3=$(cat stream_3.stdout| grep '^Triad:' | sed -e 's/ */ /g' | cut -d ' ' -f 2) + [ -z "${triadbw3}" ] && fail "Triad result not found" + + #result="$(echo "if ( (${triadbw1} + ${triadbw2} + ${triadbw3}) >= ${min} ) { print \"PASS\n\"; } else { print \"FAIL\n\"; }" | bc -lq)" || fail "Unable to analyze BW" + gbw=0 + for x in 1 2 3; do + # The test below requires integers and errors out with floats + [ $(eval echo '$'triadbw$x | cut -d. -f1) -ge $STREAM_MIN_BW ] && (( gbw++ )) + done + [ $gbw -lt 2 ] && result="FAIL" || result="PASS" + [ "${result}" != "PASS" ] && fail "One or more Triad numbers are below 40000" + + pass +} + +# verify PCI-HFI bus performance +test_hfi_pkt() +{ + TEST="hfi_pkt" + echo "hfi_pkt-test ..." + date + cd "${outdir}" || fail "Can't cd ${outdir}" + + lspci="${lspci:-/sbin/lspci}" + setpci="${setpci:-/sbin/setpci}" + + [ ! -x "${lspci}" ] && fail "Can't find lspci" + [ ! -x "${setpci}" ] && fail "Can't find setpci" + + # get OmniPath Intel stand-alone WFR HFI + set -x + "${lspci}" -n -d 0x8086:0x24f0 2>pciinfo.stderr | tee -a pciinfo.stdout || fail "Error running lspci" + set +x + [ -s pciinfo.stderr ] && fail "Error during run of lspci: $(cat pciinfo.stderr)" + # also get OmniPath Intel integrated WFR HFI + set -x + "${lspci}" -n -d 0x8086:0x24f1 2>pciinfo.stderr | tee -a pciinfo.stdout || fail "Error running lspci" + set +x + [ -s pciinfo.stderr ] && fail "Error during run of lspci: $(cat pciinfo.stderr)" + + pci_id=$(egrep -o -m1 "24f[01]" pciinfo.stdout) + if [ $HFI_COUNT -gt 0 ] + then + [ -z "$pci_id" ] && fail "No Intel HFI found" + else + [ ! -z "$pci_id" ] && fail "Unexpected Intel HFI found" + pass + fi + + + hfi_pkt_test="${hfi_pkt_test:-/usr/bin/hfi1_pkt_test}" + [ ! -x "${hfi_pkt_test}" ] && fail "Can't find hfi_pkt_test" + + failure=0 + declare -a pci_addr + pci_addr=($(lspci -nd 0x8086:$pci_id | cut -d' ' -f1)) + + for hfi in $(seq 0 $(($HFI_COUNT-1)) ) + do + if [ -z "${nomemflush}" ]; then + # use 90% of memory to flush caches and convert from K to bytes + set -x + "$USEMEM" 1048576 $(($MEMSIZE_EXPECTED * 90)) + set +x + fi + + if [ x"${HFI_CPU_CORE[$hfi]}" = x ] + then + fail_msg "HFI $hfi: HFI_CPU_CORE[$hfi] not specified" + failure=1 + continue + fi + + pci_bus="$(echo ${pci_addr[$hfi]} | cut -d : -f1):" + + set -x + taskset -c ${HFI_CPU_CORE[$hfi]} "${hfi_pkt_test}" -B -U $hfi 2>hfi_pkt_test.stderr | tee hfi_pkt_test.stdout || { fail_msg "HFI $hfi: Error running hfi_pkt_test"; failure=1; continue; } + set +x + [ -s hfi_pkt_test.stderr ] && { fail_msg "Error during run of hfi_pkt_test: HFI $hfi: $(cat hfi_pkt_test.stderr)"; failure=1; continue; } + + # Check the PCI-Express Device Status register (offset 0xA into PCIe capability structure). + # Lower 4 bits used to indicate if any problems occoured on the bus PCIe bus. + # Error reports range from simple retry to fatal PCIe errors. From our perspective, any of these should indicate + # a problem with the card or the interface, so we declare a problem if this field is non-zero. + # See: PCI-Express Base Spec v 3.1, sec 7.8.5. + + # First check the HFI device itself + set -x + "${setpci}" -s $pci_bus -d 0x8086:$pci_id CAP_EXP+0xa.w 2>pciiset.stderr | tee pciiset.stdout || fail "Error running setpci for HFI device 0x8086:$pci_id" + set +x + [ -s pciiset.stderr ] && fail "Error running setpci for HFI device 0x8086:$pci_id: $(cat pciiset.stderr)" + + result="0x" + result="$result$(cat pciiset.stdout)" + let "result&=0x000f" + [ "${result}" != "0" ] && { fail_msg "HFI $hfi: PCIe bus problems detected during packet test!"; failure=1; continue; } + + # Now let's check the PCIe root port the HFI device is attatched to, as it may report errors on it's side independently + # of the HFI. + set -x + pci_root_port="$(${lspci} -M 2> /dev/null | grep "$pci_bus Entered via" | cut -d' ' -f4)" + set +x + + set -x + "${setpci}" -s $pci_root_port CAP_EXP+0xa.w 2>pciiset.stderr | tee pciiset.stdout || fail "Error running setpci for PCIe root port $pci_root_port" + set +x + [ -s pciiset.stderr ] && fail "Error running setpci for PCIe root port $pci_root_port: $(cat pciiset.stderr)" + + result="0x" + result="$result$(cat pciiset.stdout)" + let "result&=0x000f" + [ "${result}" != "0" ] && { fail_msg "HFI $hfi: PCIe bus problems detected during packet test!"; failure=1; continue; } + + pass_msg ": HFI $hfi: No PCIe bus issues detected during buffer test" + done + [ $failure -ne 0 ] && exit 1 + + exit 0 +} + + +# verify server memory size +test_memsize() +{ + TEST="memsize" + echo "memsize test ..." + date + set -x + mem=$(cat /proc/meminfo | head -1 | cut -f 2 -d : |cut -f 1 -d k) + set +x + echo "memory size: $mem" + if [ $mem -lt $MEMSIZE_EXPECTED ] + then + fail "low memory: $mem expected $MEMSIZE_EXPECTED" + else + pass ": $mem" + fi +} + + +# verify correct VT-d setting +test_vtd() +{ + TEST="vtd" + echo "Checking for correct VT-D setting ..." + date + dmar_interrupts=`grep -i DMAR /proc/interrupts|wc -l` + if [ -e /sys/firmware/acpi/tables/DMAR ] && [ $dmar_interrupts -ne 0 ]; + then + fail ": VT-D should be disabled." + else + pass ": VT-D appears to be disabled." + fi +} + + +# Confirm CPU will not do frequency throttling or boosting. This test is good for running +# benchmarks or jobs that require consistency. Such a configuration does not +# necessarily offer best CPU performance. +test_cpu_consist() +{ + TEST="cpu_consist" + echo "CPU consistency test ..." + date + + (test_pstates_off) + (test_pmodules_off) + (test_governor) + (test_cpu_pinned) +} + +# Confirm CPU has enabled Intel P-States, favoring performance. +test_cpu() +{ + TEST="cpu" + echo "CPU test ..." + + (test_pstates_on) + (test_governor) +} + +# Return whether or not P-States enabled +function pstates_enabled() +{ + echo "pstates test ..." + date + + set -x + driver=`head -n 1 /sys/devices/system/cpu/cpu0/cpufreq/scaling_driver` + set +x + + return $([ "${driver}" = "intel_pstate" ]) +} + + +# Confirm CPU has enabled P-States, favoring performance. +test_pstates_on() +{ + TEST="pstates_on" + (pstates_enabled) || fail "intel_pstate disabled in kernel. Load module or check kernel cmdline." + pass ": CPU is operating with recommended P-State configuration" +} + +# Confirm CPU has disabled P-States +test_pstates_off() +{ + TEST="pstates_off" + (pstates_enabled) && fail "intel_pstate enabled in kernel. Set intel_pstate=disable on kernel cmdline." + pass ": CPU is operating with recommended P-State configuration" +} + + +# Return whether or not default driver loaded +function driver_loaded() +{ + echo "CPU default driver(${CPU_DRIVER}) test ..." + date + + set -x + driver=`head -n 1 /sys/devices/system/cpu/cpu0/cpufreq/scaling_driver` + set +x + + return $([ "${driver}" = ${CPU_DRIVER} ]) +} + +# Confirm desired CPU Driver loaded +test_driver_on() +{ + TEST="driver_on" + driver_loaded || fail "CPU driver not set to ${CPU_DRIVER}." + pass ": CPU is operating with recommend ${CPU_DRIVER} configuration" +} + +# Confirm CPU Driver not loaded +test_driver_off() +{ + TEST="driver_off" + driver_loaded && fail "CPU driver set to ${CPU_DRIVER}." + pass ": CPU is operating with recommended ${CPU_DRIVER} configuration" +} + +# Confirm CPU has no other power management module besides the desired loaded +test_pmodules_off() +{ + TEST="pmodules_off" + echo "power management modules off test ..." + date + + set -x + mod_dir=/lib/modules/$(uname -r)/kernel/drivers/cpufreq/ + if [ -e ${mod_dir} ] + then + modules=$(ls ${mod_dir} | egrep *.ko | while read line; do basename ${line} .ko; done) + fi + + ldmodules= + for mod in ${modules} + do + tmp=$(lsmod | grep ${mod}) + [ -n "${tmp}" ] && [ ${mod} != ${CPU_DRIVER} ] && ldmodules=${mod}' '${ldmodules} + done + + if [ -n "${ldmodules}" ] + then + fail "${ldmodules}loaded in kernel." + fi + + # check if pstates on if it is not the desired driver + [ ${CPU_DRIVER} != "intel_pstate" ] && pstates_enabled && fail "intel_pstates enabled in kernel." + + pass ": No other power management kernel modules loaded." + set +x +} + +# Confirm CPU governor is set properly +test_governor() +{ + TEST="governor" + echo "governor test ..." + date + + set -x + gov=`head -n 1 /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor` + if [ "${gov}" != ${CPU_GOVERNOR} ] + then + fail "cpupower governor is set to ${gov}. Should be ${CPU_GOVERNOR}." + fi + pass ": CPU governor set to ${CPU_GOVERNOR}" + set +x +} + + +# Return whether or not CPU frequency pinned +lo_freq= +hi_freq= +max_freq= +function cpu_pinned() +{ + echo "CPU frequency test" + date + + set -x + result=$(cpupower -c 0 frequency-info -p | tail -1) + lo_freq=$(echo ${result} | cut -f 1 -d ' ') + hi_freq=$(echo ${result} | cut -f 2 -d ' ') + max_freq=$(cpupower -c -0 frequency-info -l | tail -1 | cut -f 2 -d ' ') + + set +x + + if [ "$1" = "max" ] + then + return $([ $hi_freq -eq $lo_freq ] && [ $hi_freq -eq $max_freq ]) + else + return $([ $hi_freq -eq $lo_freq ]) + fi +} + +# Confirm CPU operating at max frequency +test_cpu_pinned() +{ + TEST="cpu_pinned" + cpu_pinned "max" || fail "CPU frequency not pinned to ${max_freq} KHz. Current operating in range of ${lo_freq} - ${hi_freq} KHz." + pass ": CPU is operating at max frequency of ${max_freq} KHz." +} + +# Confirm CPU not pinned to specific frequency +test_cpu_unpinned() +{ + TEST="cpu_unpinned" + cpu_pinned && fail "CPU operating frequency pinned to ${hi_freq} KHz." + pass ": CPU operating frequency not pinned. Current operating in range of ${lo_freq} - ${hi_freq} KHz." +} + +test_cstates() +{ + TEST="cstates" + echo "cstates test ..." + date + set -x + driver=$(cat /sys/devices/system/cpu/cpuidle/current_driver) + [ "${driver}" != "intel_idle" ] && fail "intel_idle not enabled in kernel, C-State config non-optimal." + max_cstate=$(cat /sys/module/intel_idle/parameters/max_cstate) + [ ! $max_cstate -gt 0 ] && fail "C-States are currently disabled." + set +x + + pass ": intel_idle is maintaining recommended C-States." +} + +test_turbo() +{ + TEST="turbo" + echo "Turbo test ..." + date + + set -x + result=$(cpupower frequency-info | sed -n "1,/boost state support/d;1,+1p") + echo $result | grep -q "Supported: yes" || skip "Turbo not supported on platform" + echo $result | grep -q "Active: yes" || fail "Turbo is not enabled" + set +x + + pass ": Supported and enabled" +} + +function check_ht() +{ + echo "Hyperthreading test ..." + date + + lscpu="${lscpu:-/usr/bin/lscpu}" + [ ! -x "${lscpu}" ] && fail "Can't find lscpu" + + set -x + cpus="$(${lscpu} -p=cpu | tail -1)" + cores="$(${lscpu} -p=core | tail -1)" + set +x + + return $([ ! $cpus = $cores ]) +} + +test_hton() +{ + TEST="hton" + check_ht || fail "HyperThreading is disabled" + pass ": Hyperthreading is enabled" +} + +test_htoff() +{ + TEST="htoff" + check_ht && fail "HyperThreading is enabled" + pass ": Hyperthreading is disabled" +} + +test_ipoib() +{ + TEST="ipoib" + echo "IPoIB test ..." + date + + if [ ! -e /sys/class/net/$IPOIB_IF ] + then + fail "Given IPoIB interface $IPOIB_IF couldn't be found." + fi + + set -x + mtu=$(cat /sys/class/net/$IPOIB_IF/mtu) + mode=$(cat /sys/class/net/$IPOIB_IF/mode) + + [ $mode != "$IPOIB_MODE" ] && fail "$IPOIB_IF is in '$mode' mode - should be in '$IPOIB_MODE' mode" + [ $mtu -ne $IPOIB_MTU ] && fail "$IPOIB_IF MTU of $mtu - should be $IPOIB_MTU" + set +x + + pass ": IPoIB properly configured" +} + +# single node HPL +test_hpl() +{ + TEST="hpl" + echo "HPL test ..." + date + cd "${MPI_APPS}" || fail "Can't cd ${MPI_APPS}" + + echo localhost > $outdir/mpi_hosts_hpl + + # configure HPL2's HPL.dat file to control test + if [ -z "$HPL_CORES" ]; then + HPL_CORES=`cat /proc/cpuinfo | grep processor | wc -l` + fi + set -x + ./hpl_dat_gen -d -n 1 -p $HPL_PRESSURE -c $HPL_CORES || fail "Error configuring HPL" + set +x + + set -x + MPI_HOSTS=$outdir/mpi_hosts_hpl MPI_TASKSET="-c 0-$(($HPL_CORES - 1))" ./run_hpl2 $HPL_CORES 2> $outdir/hpl.stderr | tee $outdir/hpl.stdout || fail "Error running HPL" + set +x + + grep -v '^+' < $outdir/hpl.stderr > $outdir/hpl.errors + [ -s $outdir/hpl.errors ] && fail "Error during run of HPL: $(cat $outdir/hpl.errors)" + + [ -z "${MIN_FLOPS}" ] && fail "Invalid MIN_FLOPS" + + flops="$(cat $outdir/hpl.stdout | grep 'WR11R2C4' | head -1 | sed -e 's/ */ /g' | cut -d ' ' -f 7|sed -e 's/e+/ * 10^/')" + [ -z "${flops}" ] && fail "Unable to get result" + + result="$(echo "if ( ${flops} >= ${MIN_FLOPS} ) { print \"PASS\n\"; } else { print \"FAIL\n\"; }" | bc -lq)" || fail "Unable to analyze result: $flops" + [ "${result}" != "PASS" ] && fail "Result of ${flops} less than MIN_FLOPS ${MIN_FLOPS}" + + pass ": $flops Flops" +} + +test_srp() +{ + TEST="srp" + echo "srp daemon..." + date + + set -x + + pid=$(pgrep srp_daemon) + [ -n "$pid" ] && fail "SRP process is running" + + autostart=$(lsmod | grep ib_srp) + [ -n "$autostart" ] && fail "SRP service is configured to start at boot." + + set +x + + pass +} + + + +( + for i in $tests + do + date + if ! type "test_$i"|grep 'is a function' >/dev/null 2>/dev/null + then + TEST="$i" fail_msg "Invalid Test Name" + else + ( test_$i ) + fi + date + echo "======================================================" + done + + rm -rf "${outdir}" + +) 2>&1|tee -a $outputdir/hostverify.res|$filter diff --git a/IbaTools/nodeverify/nodeverify.sh.base b/IbaTools/nodeverify/nodeverify.sh.base new file mode 100755 index 0000000..0e6556a --- /dev/null +++ b/IbaTools/nodeverify/nodeverify.sh.base @@ -0,0 +1,975 @@ +#!/bin/bash +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2018, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] + + +# script to verify configuration and performance of an individual node +# this should be run using opaverifyhosts. It can also be run on an individual +# node directly. + +# The following specify expected minimal configuration and performance +MEMSIZE_EXPECTED=30601808 # size of memory (MemTotal) in k as shown in + # /proc/meminfo +HFI_COUNT=1 # expected Number of Intel HFIs +HFI_CPU_CORE[0]=1 # CPU core to use when testing HFI 0 PCI performance +HFI_CPU_CORE[1]=1 # CPU core to use when testing HFI 1 PCI performance +HFI_CPU_CORE[2]=1 # CPU core to use when testing HFI 2 PCI performance +HFI_CPU_CORE[3]=1 # CPU core to use when testing HFI 3 PCI performance + # On some servers, such as Sandy-Bridge, it is + # recommended to set the CPU CORE for each HFI to + # a core within the same CPU socket the HFI's PCI + # bus is connected to +PCI_MAXPAYLOAD=256 # expected value for PCI max payload +PCI_MINREADREQ=512 # expected value for PCI min read req size +PCI_MAXREADREQ=4096 # expected value for PCI max read req size +PCI_SPEED="8GT/s" # expected value for PCI speed on Intel WFR HFI +PCI_WIDTH="x16" # expected value for PCI width on Intel WFR HFI +MPI_APPS=$HOME/mpi_apps/ # where to find mpi_apps for HPL test +MIN_FLOPS="115" # minimum flops expected from HPL test +IPOIB_IF="ib0" # IPoIB interface to check +IPOIB_MODE="connected" # IPoIB required mode "connected" or "datagram" +IPOIB_MTU=65520 # IPoIB required MTU +outputdir=/root # default outputdir is root -d $DIR overrides +CPU_DRIVER="intel_pstate" # power scaling driver for CPU +CPU_GOVERNOR="performance" # scaling governor for CPU +STREAM_MIN_BW=40000 # minimum Triad bandwidth for each run of the + # STREAM memory benchmark (MB/s) + +# If desired, single node HPL can be run, using the parameters defined below. +# +# The goal of the single node HPL test is to check node stability and the +# consistency of performance between hosts, NOT to optimize performance. +# As such a small problem size, such as '16s' is recommended since it will run +# faster and will still be equally good at discovering slow or unstable hosts. +# The given problem size should be run on a known good node and the result +# can be used to select an appropriate MIN_FLOPS value for other hosts. It +# may be necessary to set MIN_FLOPS slightly below the observed result for +# the known good host to account for minor variations in OS background +# overhead, manufacturing variations, etc. + +# When using HPL, the problem size will automatically be adjusted to match +# the number of cores on the host, but this can be overridden by setting +# the HPL_CORES variable. +# +# The size can also be adjusted to consume a percentage of system memory +# by adjusting the HPL_PRESSURE variable up or down between 0.1 and 0.9. +# Note that increasing the value of HPL_PRESSURE will increast the amount +# of time the test will take to execute. + +# In order to run the single node HPL test, each tested host must be able to +# ssh to locahost as root + +# Set this if you don't want the problem size to match the number of cores on +# the target node. +HPL_CORES= + +# By default the problem size will be scaled to consume roughly 30% of RAM on +# the target node. This can be adjusted up or down between 0.0 and 0.9. Note +# that larger values will cause the test to run for a longer time. +HPL_PRESSURE=0.3 + +# can adjust default list of tests below +#TESTS="pcicfg pcispeed initscripts irqbalance hfi_pkt memsize cpu_consist cpu cstates turbo hton htoff ipoib hpl" +TESTS="pcicfg pcispeed initscripts memsize cpu hfi_pkt hton ipoib irqbalance turbo cstates vtd srp stream" + + +Usage() +{ + echo "Usage: ./hostverify.sh [-v] [-d OUTPUTDIR] [test ...]" >&2 + echo " or" >&2 + echo " ./hostverify.sh --help" >&2 + echo " -v - provide verbose output on stdout (by default only PASS/FAIL is output)" >&2 + echo " detailed results are always output to OUTPUTDIR/hostverify.res" >&2 + echo " -d OUTPUTDIR - write detailed results to OUTPUTDIR (defaults to /root)" >&2 + echo " --help - produce full help text" >&2 + echo " test - one or more specific tests to run" >&2 + echo "This verifies basic node configuration and performance" >&2 + echo "Prior to using this, edit it to set proper" >&2 + echo "expectations for node configuration and performance" >&2 + echo >&2 + echo "The following tests are available:" >&2 + echo " pcicfg - verify PCI max payload and max read request size settings" >&2 + echo " pcispeed - verify PCI bus negotiated to PCIe Gen3 x16 speed" >&2 + echo " initscripts - verify powerd and cpuspeed init.d scripts are disabled," >&2 + echo " hfi_pkt - check PCI-HFI bus performance. Requires HFI port is Active" >&2 + echo " memsize - check total size of memory in system" >&2 + echo " vtd - verify that Intel VT-d is disabled" >&2 + echo " hpl - perform a single node HPL test," >&2 + echo " useful to determine if all hosts perform consistently" >&2 + echo " pstates_on - check if Intel P-States are enabled and optimally configured" >&2 + echo " pstates_off - check if Intel P-States are disabled" >&2 + echo " driver_on - check if power scaling driver (default isintel_pstates) enabled" >&2 + echo " generalized version of pstates_on" >&2 + echo " driver_off - check if power scaling driver (default is intel_pstates)" >&2 + echo " generalized version of pstates_off" >&2 + echo " governor - verify proper governor enabled for CPU (default 'performance')" >&2 + echo " cpu_pinned - verify CPU operating at max frequency" >&2 + echo " cpu_unpinned - verify CPU not pinned to max operating frequency" >&2 + echo " pmodules_off - verify other power management modules aren't loaded" >&2 + echo " cpu - check if CPU parameters are configured for optimal performance" >&2 + echo " includes pstates_on and governor tests" >&2 + echo " cpu_consist - check if CPU parameters are configured for most consistent performance" >&2 + echo " includes pstates_off, pmodules_off, governor, and cpu_pinned tests" >&2 + echo " turbo - check if Intel Turbo Boost is enabled" >&2 + echo " cstates - check if Intel C-States are enabled and optimally configured." >&2 + echo " hton - verify that Hyper Threading is enabled" >&2 + echo " htoff - verify that Hyper Threading is disabled" >&2 + echo " ipoib - verify IPoIB is properly configured" >&2 + echo " irqbalance - verify irqbalance is running with proper configuration" >&2 + echo " srp - verify srp daemon is not running" >&2 + echo " stream - verify memory bandwidth" >&2 + echo " default - run all tests selected in TESTS" >&2 + echo >&2 + echo "Detailed output is written to stdout and appended to" >&2 + echo " OUTPUTDIR/hostverify.res" >&2 + echo "egrep 'PASS|FAIL' OUTPUTDIR/hostverify.res for a brief summary" >&2 + echo >&2 + echo "A Intel HFI is required for pcicfg, pcispeed and hfi_pkt tests" >&2 + exit 0 +} + +if [ x"$1" = "x--help" ] +then + Usage +fi + +myfilter() +{ + # filter out the residual report from HPL + egrep 'PASS|FAIL|SKIP'|fgrep -v '||Ax-b||_oo/(eps' +} + +filter=myfilter +while getopts vd: param +do + case $param in + v) filter=cat;; + d) outputdir="$OPTARG";; + ?) Usage;; + esac +done +shift $((OPTIND -1)) + +tests="$TESTS" +if [ $# -ne 0 ] +then + tests= + for i in $* + do + if [ x"$i" == x"default" ] + then + tests="$tests $TESTS" + else + tests="$tests $i" + fi + done +fi + +USEMEM=/usr/lib/opa/tools/usemem # where to find usemem tool +if [ -n "${debug}" ]; then + set -x + set -v +fi + +export LANG=C +unset CDPATH + +TEST=main + +function fail_msg() +{ + set +x + echo "`hostname -s`: FAIL $TEST: $1" +} + +function pass_msg() +{ + set +x + echo "`hostname -s`: PASS $TEST$1" +} + +function fail() +{ + fail_msg "$1" + exit 1 +} + +function pass() +{ + pass_msg "$1" + exit 0 +} + +function skip() +{ + set +x + echo "`hostname -s`: SKIP $TEST$1" + exit 0 +} + +outdir="$(mktemp --tmpdir -d hostverify.XXXXXXXXXX)" || fail "Cannot mktemp --tmpdir -d hostverify.XXXXXXXXXX" + +# verify basic PCIe configuration +test_pcicfg() +{ + TEST=pcicfg + echo "pcicfg ..." + date + + failure=0 + cd "${outdir}" || fail "Can't cd ${outdir}" + + lspci="${lspci:-/sbin/lspci}" + [ ! -x "${lspci}" ] && fail "Can't find lspci" + + # get OmniPath Intel stand-alone WFR HFI + set -x + "${lspci}" -n -d 0x8086:0x24f0 2>pcicfg.stderr | tee -a pcicfg.stdout || fail "Error running lspci" + set +x + [ -s pcicfg.stderr ] && fail "Error during run of lspci: $(cat pcicfg.stderr)" + # also get OmniPath Intel integrated WFR HFI + set -x + "${lspci}" -n -d 0x8086:0x24f1 2>pcicfg.stderr | tee -a pcicfg.stdout || fail "Error running lspci" + set +x + [ -s pcicfg.stderr ] && fail "Error during run of lspci: $(cat pcicfg.stderr)" + + set -x + pci_id=$(egrep -o -m1 "24f[01]" pcicfg.stdout) + if [ -z ${pci_id} ] + then + fail "Error identifying HFI's on the PCI bus" + fi + + + "${lspci}" -vvv -d 0x8086:$pci_id 2>pcicfg.stderr | tee -a pcicfg.stdout || fail "Error running lspci" + set +x + + hfi_count=$(cat pcicfg.stdout|grep 'MaxPayload .* bytes, MaxReadReq .* bytes' | wc -l) + [ $hfi_count -ne $HFI_COUNT ] && { fail_msg "Incorrect number of Intel HFIs: Expect $HFI_COUNT Got: $hfi_count"; failure=1; } + [ $HFI_COUNT -eq 0 ] && pass + + cat pcicfg.stdout|egrep 'MaxPayload .* bytes, MaxReadReq .* bytes|^[0-9]' | + { + failure=0 + device="Unknown" + while read cfgline + do + if echo "$cfgline"|grep '^[0-9]' >/dev/null 2>/dev/null + then + device=$(echo "$cfgline"|cut -f1 -d ' ') + else + result=$(echo "$cfgline"|sed -e 's/.*\(MaxPayload .* bytes, MaxReadReq .* bytes\).*/\1'/) + payload=$(echo "$result"|cut -f2 -d ' ') + readreq=$(echo "$result"|cut -f5 -d ' ') + + [ "$payload" -eq "$PCI_MAXPAYLOAD" ] || { fail_msg "HFI $device: Incorrect MaxPayload of $payload (expected $PCI_MAXPAYLOAD)."; failure=1; } + + [ "$readreq" -le "$PCI_MAXREADREQ" -a "$readreq" -ge "$PCI_MINREADREQ" ] || { fail_msg "HFI $device: MaxReadReq of $readreq out of expected range [$PCI_MINREADREQ,$PCI_MAXREADREQ]."; failure=1; } + + device="Unknown" + fi + done + [ $failure -ne 0 ] && exit 1 + exit 0 + } + [ $failure -ne 0 -o $? != 0 ] && exit 1 # catch any fail calls within while + + pass +} + +# verify PCIe is negotiated at PCIe Gen3 x16 +test_pcispeed() +{ + TEST=pcispeed + echo "pcispeed ..." + date + + failure=0 + cd "${outdir}" || fail "Can't cd ${outdir}" + + lspci="${lspci:-/sbin/lspci}" + [ ! -x "${lspci}" ] && fail "Can't find lspci" + + # get OmniPath Intel stand-alone WFR HFI + set -x + "${lspci}" -n -d 0x8086:0x24f0 2>pcispeed.stderr | tee -a pcispeed.stdout || fail "Error running lspci" + set +x + [ -s pcispeed.stderr ] && fail "Error during run of lspci: $(cat pcispeed.stderr)" + # also get OmniPath Intel integrated WFR HFI + set -x + "${lspci}" -n -d 0x8086:0x24f1 2>pcispeed.stderr | tee -a pcispeed.stdout || fail "Error running lspci" + set +x + [ -s pcispeed.stderr ] && fail "Error during run of lspci: $(cat pcispeed.stderr)" + + set -x + pci_id=$(egrep -o -m1 "24f[01]" pcispeed.stdout) + if [ -z ${pci_id} ] + then + fail "Error identifying HFI's on the PCI bus" + fi + + "${lspci}" -vvv -d 0x8086:$pci_id 2>pcispeed.stderr | tee -a pcispeed.stdout || fail "Error running lspci" + set +x + + hfi_count=$(cat pcispeed.stdout|grep 'Speed .*, Width .*' pcispeed.stdout|egrep -v 'LnkCap|LnkCtl|Supported'| wc -l) + [ $hfi_count -ne $HFI_COUNT ] && { fail_msg "Incorrect number of Intel HFIs: Expect $HFI_COUNT Got: $hfi_count"; failure=1; } + [ $HFI_COUNT -eq 0 ] && pass + + cat pcispeed.stdout|egrep 'Speed .*, Width .*|^[0-9]' pcispeed.stdout|egrep -v 'LnkCap|LnkCtl|Supported'| + { + failure=0 + device="Unknown" + while read cfgline + do + if echo "$cfgline"|grep '^[0-9]' >/dev/null 2>/dev/null + then + device=$(echo "$cfgline"|cut -f1 -d ' ') + else + result=$(echo "$cfgline"|sed -e 's/.*\(Speed .*, Width [^,]*\).*/\1'/) + + expect="Speed $PCI_SPEED, Width $PCI_WIDTH" + [ "$result" = "$expect" ] || { fail_msg "HFI $device: Incorrect Speed or Width: Expect: $expect Got: $result"; failure=1; } + device="Unknown" + fi + done + [ $failure -ne 0 ] && exit 1 + exit 0 + } + [ $failure -ne 0 -o $? != 0 ] && exit 1 # catch any fail calls within while + + pass +} + +# make sure powerd and cpuspeed are disabled +test_initscripts() +{ + TEST="initscripts" + echo "initscripts ..." + date + cd "${outdir}" || fail "Can't cd ${outdir}" + + > chkconfig.out + for i in cpuspeed powerd + do + set -x + if [ -e /etc/init.d/$i ] + then + chkconfig --list $i 2>chkconfig.stderr|tee -a chkconfig.out || fail "Error during chkconfig $i" + [ -s chkconfig.stderr ] && fail "Error during run of chkconfig: $(cat chkconfig.stderr)" + fi + set +x + done + + result=`grep '[2-6]:on' chkconfig.out` + [ -n "${result}" ] && fail "Undesirable service enabled: $result" + + #Now check systemd + for i in cpuspeed powerd + do + set -x + if [ -n "`systemctl list-units | grep $i`" ] + then + [ -n "`systemctl is-enabled $i | grep enabled`" ] && fail "Undesirable systemd service enabled: $i" + fi + set +x + done + + pass +} + +test_irqbalance() +{ + TEST="irqbalance" + echo "irqbalance ..." + date + + set -x + + pid=$(pgrep irqbalance) + [ -z "$pid" ] && fail "irqbalance process not running" + + cmdline=$(ps -o command --no-heading -p $pid) + echo "$cmdline" | grep -q "exact" || fail "irqbalance is NOT running with hint policy 'exact'" + set +x + + pass +} + +#test_nodeperf() +#{ +# TEST="nodeperf" +# echo "nodeperf ..." +# date +# cd "${outdir}" || fail "Can't cd ${outdir}" +# +# if [ -z "${nomemflush}" ]; then +# set -x +# "$USEMEM" 1048576 20737418240 +# set +x +# fi +# +# set -x +# LD_LIBRARY_PATH="${rundir}/lib" "${rundir}/bin/nodeperf" 2>nodeperf.stderr | tee nodeperf.stdout || fail "Failed to run nodeperf" +# set +x +# [ -s nodeperf.stderr ] && cat nodeperf.stdout && fail "Error running nodeperf" +# +# min="${min:-120000}" +# [ -z "${min}" ] && fail "invalid min" +# +# nodeperf=$(cat nodeperf.stdout| grep '0 of 1' | head -1 | cut -d ' ' -f 12) +# [ -z "${nodeperf}" ] && fail "Unable to obtain nodeperf result" +# +# result="$(echo "if ( ${nodeperf} >= ${min} ) { print \"PASS\n\"; } else { print \"FAIL\n\"; }" | bc -lq)" || fail "Unable to analyze nodeperf result" +# [ "${result}" != "PASS" ] && fail "Performance of ${nodeperf} less than min ${min}" +# +# pass +#} + +test_stream() +{ + TEST="stream" + echo "stream ..." + date + + stream="${stream:-/usr/lib/opa/tools/stream}" + [ ! -x "${stream}" ] && fail "Can't find stream" + + for run in 1 2 3; do + if [ -z "${nomemflush}" ]; then + set -x + "$USEMEM" 1048576 20737418240 + set +x + fi + + set -x + "${stream}" 2>stream.stderr |tee stream_${run}.stdout || fail + set +x + [ -s stream.stderr ] && cat stream.stderr && fail "Errors during run" + done + + min="${min:-120000}" + [ -z "${min}" ] && fail "invalid min" + + triadbw1=$(cat stream_1.stdout| grep '^Triad:' | sed -e 's/ */ /g' | cut -d ' ' -f 2) + [ -z "${triadbw1}" ] && fail "Triad result not found" + + triadbw2=$(cat stream_2.stdout| grep '^Triad:' | sed -e 's/ */ /g' | cut -d ' ' -f 2) + [ -z "${triadbw2}" ] && fail "Triad result not found" + + triadbw3=$(cat stream_3.stdout| grep '^Triad:' | sed -e 's/ */ /g' | cut -d ' ' -f 2) + [ -z "${triadbw3}" ] && fail "Triad result not found" + + #result="$(echo "if ( (${triadbw1} + ${triadbw2} + ${triadbw3}) >= ${min} ) { print \"PASS\n\"; } else { print \"FAIL\n\"; }" | bc -lq)" || fail "Unable to analyze BW" + gbw=0 + for x in 1 2 3; do + # The test below requires integers and errors out with floats + [ $(eval echo '$'triadbw$x | cut -d. -f1) -ge $STREAM_MIN_BW ] && (( gbw++ )) + done + [ $gbw -lt 2 ] && result="FAIL" || result="PASS" + [ "${result}" != "PASS" ] && fail "One or more Triad numbers are below 40000" + + pass +} + +# verify PCI-HFI bus performance +test_hfi_pkt() +{ + TEST="hfi_pkt" + echo "hfi_pkt-test ..." + date + cd "${outdir}" || fail "Can't cd ${outdir}" + + lspci="${lspci:-/sbin/lspci}" + setpci="${setpci:-/sbin/setpci}" + + [ ! -x "${lspci}" ] && fail "Can't find lspci" + [ ! -x "${setpci}" ] && fail "Can't find setpci" + + # get OmniPath Intel stand-alone WFR HFI + set -x + "${lspci}" -n -d 0x8086:0x24f0 2>pciinfo.stderr | tee -a pciinfo.stdout || fail "Error running lspci" + set +x + [ -s pciinfo.stderr ] && fail "Error during run of lspci: $(cat pciinfo.stderr)" + # also get OmniPath Intel integrated WFR HFI + set -x + "${lspci}" -n -d 0x8086:0x24f1 2>pciinfo.stderr | tee -a pciinfo.stdout || fail "Error running lspci" + set +x + [ -s pciinfo.stderr ] && fail "Error during run of lspci: $(cat pciinfo.stderr)" + + pci_id=$(egrep -o -m1 "24f[01]" pciinfo.stdout) + if [ $HFI_COUNT -gt 0 ] + then + [ -z "$pci_id" ] && fail "No Intel HFI found" + else + [ ! -z "$pci_id" ] && fail "Unexpected Intel HFI found" + pass + fi + + + hfi_pkt_test="${hfi_pkt_test:-/usr/bin/hfi1_pkt_test}" + [ ! -x "${hfi_pkt_test}" ] && fail "Can't find hfi_pkt_test" + + failure=0 + declare -a pci_addr + pci_addr=($(lspci -nd 0x8086:$pci_id | cut -d' ' -f1)) + + for hfi in $(seq 0 $(($HFI_COUNT-1)) ) + do + if [ -z "${nomemflush}" ]; then + # use 90% of memory to flush caches and convert from K to bytes + set -x + "$USEMEM" 1048576 $(($MEMSIZE_EXPECTED * 90)) + set +x + fi + + if [ x"${HFI_CPU_CORE[$hfi]}" = x ] + then + fail_msg "HFI $hfi: HFI_CPU_CORE[$hfi] not specified" + failure=1 + continue + fi + + pci_bus="$(echo ${pci_addr[$hfi]} | cut -d : -f1):" + + set -x + taskset -c ${HFI_CPU_CORE[$hfi]} "${hfi_pkt_test}" -B -U $hfi 2>hfi_pkt_test.stderr | tee hfi_pkt_test.stdout || { fail_msg "HFI $hfi: Error running hfi_pkt_test"; failure=1; continue; } + set +x + [ -s hfi_pkt_test.stderr ] && { fail_msg "Error during run of hfi_pkt_test: HFI $hfi: $(cat hfi_pkt_test.stderr)"; failure=1; continue; } + + # Check the PCI-Express Device Status register (offset 0xA into PCIe capability structure). + # Lower 4 bits used to indicate if any problems occoured on the bus PCIe bus. + # Error reports range from simple retry to fatal PCIe errors. From our perspective, any of these should indicate + # a problem with the card or the interface, so we declare a problem if this field is non-zero. + # See: PCI-Express Base Spec v 3.1, sec 7.8.5. + + # First check the HFI device itself + set -x + "${setpci}" -s $pci_bus -d 0x8086:$pci_id CAP_EXP+0xa.w 2>pciiset.stderr | tee pciiset.stdout || fail "Error running setpci for HFI device 0x8086:$pci_id" + set +x + [ -s pciiset.stderr ] && fail "Error running setpci for HFI device 0x8086:$pci_id: $(cat pciiset.stderr)" + + result="0x" + result="$result$(cat pciiset.stdout)" + let "result&=0x000f" + [ "${result}" != "0" ] && { fail_msg "HFI $hfi: PCIe bus problems detected during packet test!"; failure=1; continue; } + + # Now let's check the PCIe root port the HFI device is attatched to, as it may report errors on it's side independently + # of the HFI. + set -x + pci_root_port="$(${lspci} -M 2> /dev/null | grep "$pci_bus Entered via" | cut -d' ' -f4)" + set +x + + set -x + "${setpci}" -s $pci_root_port CAP_EXP+0xa.w 2>pciiset.stderr | tee pciiset.stdout || fail "Error running setpci for PCIe root port $pci_root_port" + set +x + [ -s pciiset.stderr ] && fail "Error running setpci for PCIe root port $pci_root_port: $(cat pciiset.stderr)" + + result="0x" + result="$result$(cat pciiset.stdout)" + let "result&=0x000f" + [ "${result}" != "0" ] && { fail_msg "HFI $hfi: PCIe bus problems detected during packet test!"; failure=1; continue; } + + pass_msg ": HFI $hfi: No PCIe bus issues detected during buffer test" + done + [ $failure -ne 0 ] && exit 1 + + exit 0 +} + + +# verify server memory size +test_memsize() +{ + TEST="memsize" + echo "memsize test ..." + date + set -x + mem=$(cat /proc/meminfo | head -1 | cut -f 2 -d : |cut -f 1 -d k) + set +x + echo "memory size: $mem" + if [ $mem -lt $MEMSIZE_EXPECTED ] + then + fail "low memory: $mem expected $MEMSIZE_EXPECTED" + else + pass ": $mem" + fi +} + + +# verify correct VT-d setting +test_vtd() +{ + TEST="vtd" + echo "Checking for correct VT-D setting ..." + date + dmar_interrupts=`grep -i DMAR /proc/interrupts|wc -l` + if [ -e /sys/firmware/acpi/tables/DMAR ] && [ $dmar_interrupts -ne 0 ]; + then + fail ": VT-D should be disabled." + else + pass ": VT-D appears to be disabled." + fi +} + + +# Confirm CPU will not do frequency throttling or boosting. This test is good for running +# benchmarks or jobs that require consistency. Such a configuration does not +# necessarily offer best CPU performance. +test_cpu_consist() +{ + TEST="cpu_consist" + echo "CPU consistency test ..." + date + + (test_pstates_off) + (test_pmodules_off) + (test_governor) + (test_cpu_pinned) +} + +# Confirm CPU has enabled Intel P-States, favoring performance. +test_cpu() +{ + TEST="cpu" + echo "CPU test ..." + + (test_pstates_on) + (test_governor) +} + +# Return whether or not P-States enabled +function pstates_enabled() +{ + echo "pstates test ..." + date + + set -x + driver=`head -n 1 /sys/devices/system/cpu/cpu0/cpufreq/scaling_driver` + set +x + + return $([ "${driver}" = "intel_pstate" ]) +} + + +# Confirm CPU has enabled P-States, favoring performance. +test_pstates_on() +{ + TEST="pstates_on" + (pstates_enabled) || fail "intel_pstate disabled in kernel. Load module or check kernel cmdline." + pass ": CPU is operating with recommended P-State configuration" +} + +# Confirm CPU has disabled P-States +test_pstates_off() +{ + TEST="pstates_off" + (pstates_enabled) && fail "intel_pstate enabled in kernel. Set intel_pstate=disable on kernel cmdline." + pass ": CPU is operating with recommended P-State configuration" +} + + +# Return whether or not default driver loaded +function driver_loaded() +{ + echo "CPU default driver(${CPU_DRIVER}) test ..." + date + + set -x + driver=`head -n 1 /sys/devices/system/cpu/cpu0/cpufreq/scaling_driver` + set +x + + return $([ "${driver}" = ${CPU_DRIVER} ]) +} + +# Confirm desired CPU Driver loaded +test_driver_on() +{ + TEST="driver_on" + driver_loaded || fail "CPU driver not set to ${CPU_DRIVER}." + pass ": CPU is operating with recommend ${CPU_DRIVER} configuration" +} + +# Confirm CPU Driver not loaded +test_driver_off() +{ + TEST="driver_off" + driver_loaded && fail "CPU driver set to ${CPU_DRIVER}." + pass ": CPU is operating with recommended ${CPU_DRIVER} configuration" +} + +# Confirm CPU has no other power management module besides the desired loaded +test_pmodules_off() +{ + TEST="pmodules_off" + echo "power management modules off test ..." + date + + set -x + mod_dir=/lib/modules/$(uname -r)/kernel/drivers/cpufreq/ + if [ -e ${mod_dir} ] + then + modules=$(ls ${mod_dir} | egrep *.ko | while read line; do basename ${line} .ko; done) + fi + + ldmodules= + for mod in ${modules} + do + tmp=$(lsmod | grep ${mod}) + [ -n "${tmp}" ] && [ ${mod} != ${CPU_DRIVER} ] && ldmodules=${mod}' '${ldmodules} + done + + if [ -n "${ldmodules}" ] + then + fail "${ldmodules}loaded in kernel." + fi + + # check if pstates on if it is not the desired driver + [ ${CPU_DRIVER} != "intel_pstate" ] && pstates_enabled && fail "intel_pstates enabled in kernel." + + pass ": No other power management kernel modules loaded." + set +x +} + +# Confirm CPU governor is set properly +test_governor() +{ + TEST="governor" + echo "governor test ..." + date + + set -x + gov=`head -n 1 /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor` + if [ "${gov}" != ${CPU_GOVERNOR} ] + then + fail "cpupower governor is set to ${gov}. Should be ${CPU_GOVERNOR}." + fi + pass ": CPU governor set to ${CPU_GOVERNOR}" + set +x +} + + +# Return whether or not CPU frequency pinned +lo_freq= +hi_freq= +max_freq= +function cpu_pinned() +{ + echo "CPU frequency test" + date + + set -x + result=$(cpupower -c 0 frequency-info -p | tail -1) + lo_freq=$(echo ${result} | cut -f 1 -d ' ') + hi_freq=$(echo ${result} | cut -f 2 -d ' ') + max_freq=$(cpupower -c -0 frequency-info -l | tail -1 | cut -f 2 -d ' ') + + set +x + + if [ "$1" = "max" ] + then + return $([ $hi_freq -eq $lo_freq ] && [ $hi_freq -eq $max_freq ]) + else + return $([ $hi_freq -eq $lo_freq ]) + fi +} + +# Confirm CPU operating at max frequency +test_cpu_pinned() +{ + TEST="cpu_pinned" + cpu_pinned "max" || fail "CPU frequency not pinned to ${max_freq} KHz. Current operating in range of ${lo_freq} - ${hi_freq} KHz." + pass ": CPU is operating at max frequency of ${max_freq} KHz." +} + +# Confirm CPU not pinned to specific frequency +test_cpu_unpinned() +{ + TEST="cpu_unpinned" + cpu_pinned && fail "CPU operating frequency pinned to ${hi_freq} KHz." + pass ": CPU operating frequency not pinned. Current operating in range of ${lo_freq} - ${hi_freq} KHz." +} + +test_cstates() +{ + TEST="cstates" + echo "cstates test ..." + date + set -x + driver=$(cat /sys/devices/system/cpu/cpuidle/current_driver) + [ "${driver}" != "intel_idle" ] && fail "intel_idle not enabled in kernel, C-State config non-optimal." + max_cstate=$(cat /sys/module/intel_idle/parameters/max_cstate) + [ ! $max_cstate -gt 0 ] && fail "C-States are currently disabled." + set +x + + pass ": intel_idle is maintaining recommended C-States." +} + +test_turbo() +{ + TEST="turbo" + echo "Turbo test ..." + date + + set -x + result=$(cpupower frequency-info | sed -n "1,/boost state support/d;1,+1p") + echo $result | grep -q "Supported: yes" || skip "Turbo not supported on platform" + echo $result | grep -q "Active: yes" || fail "Turbo is not enabled" + set +x + + pass ": Supported and enabled" +} + +function check_ht() +{ + echo "Hyperthreading test ..." + date + + lscpu="${lscpu:-/usr/bin/lscpu}" + [ ! -x "${lscpu}" ] && fail "Can't find lscpu" + + set -x + cpus="$(${lscpu} -p=cpu | tail -1)" + cores="$(${lscpu} -p=core | tail -1)" + set +x + + return $([ ! $cpus = $cores ]) +} + +test_hton() +{ + TEST="hton" + check_ht || fail "HyperThreading is disabled" + pass ": Hyperthreading is enabled" +} + +test_htoff() +{ + TEST="htoff" + check_ht && fail "HyperThreading is enabled" + pass ": Hyperthreading is disabled" +} + +test_ipoib() +{ + TEST="ipoib" + echo "IPoIB test ..." + date + + if [ ! -e /sys/class/net/$IPOIB_IF ] + then + fail "Given IPoIB interface $IPOIB_IF couldn't be found." + fi + + set -x + mtu=$(cat /sys/class/net/$IPOIB_IF/mtu) + mode=$(cat /sys/class/net/$IPOIB_IF/mode) + + [ $mode != "$IPOIB_MODE" ] && fail "$IPOIB_IF is in '$mode' mode - should be in '$IPOIB_MODE' mode" + [ $mtu -ne $IPOIB_MTU ] && fail "$IPOIB_IF MTU of $mtu - should be $IPOIB_MTU" + set +x + + pass ": IPoIB properly configured" +} + +# single node HPL +test_hpl() +{ + TEST="hpl" + echo "HPL test ..." + date + cd "${MPI_APPS}" || fail "Can't cd ${MPI_APPS}" + + echo localhost > $outdir/mpi_hosts_hpl + + # configure HPL2's HPL.dat file to control test + if [ -z "$HPL_CORES" ]; then + HPL_CORES=`cat /proc/cpuinfo | grep processor | wc -l` + fi + set -x + ./hpl_dat_gen -d -n 1 -p $HPL_PRESSURE -c $HPL_CORES || fail "Error configuring HPL" + set +x + + set -x + MPI_HOSTS=$outdir/mpi_hosts_hpl MPI_TASKSET="-c 0-$(($HPL_CORES - 1))" ./run_hpl2 $HPL_CORES 2> $outdir/hpl.stderr | tee $outdir/hpl.stdout || fail "Error running HPL" + set +x + + grep -v '^+' < $outdir/hpl.stderr > $outdir/hpl.errors + [ -s $outdir/hpl.errors ] && fail "Error during run of HPL: $(cat $outdir/hpl.errors)" + + [ -z "${MIN_FLOPS}" ] && fail "Invalid MIN_FLOPS" + + flops="$(cat $outdir/hpl.stdout | grep 'WR11R2C4' | head -1 | sed -e 's/ */ /g' | cut -d ' ' -f 7|sed -e 's/e+/ * 10^/')" + [ -z "${flops}" ] && fail "Unable to get result" + + result="$(echo "if ( ${flops} >= ${MIN_FLOPS} ) { print \"PASS\n\"; } else { print \"FAIL\n\"; }" | bc -lq)" || fail "Unable to analyze result: $flops" + [ "${result}" != "PASS" ] && fail "Result of ${flops} less than MIN_FLOPS ${MIN_FLOPS}" + + pass ": $flops Flops" +} + +test_srp() +{ + TEST="srp" + echo "srp daemon..." + date + + set -x + + pid=$(pgrep srp_daemon) + [ -n "$pid" ] && fail "SRP process is running" + + autostart=$(lsmod | grep ib_srp) + [ -n "$autostart" ] && fail "SRP service is configured to start at boot." + + set +x + + pass +} + + + +( + for i in $tests + do + date + if ! type "test_$i"|grep 'is a function' >/dev/null 2>/dev/null + then + TEST="$i" fail_msg "Invalid Test Name" + else + ( test_$i ) + fi + date + echo "======================================================" + done + + rm -rf "${outdir}" + +) 2>&1|tee -a $outputdir/hostverify.res|$filter diff --git a/IbaTools/nodeverify/opaverifynodes.sh b/IbaTools/nodeverify/opaverifynodes.sh new file mode 100755 index 0000000..acdfa68 --- /dev/null +++ b/IbaTools/nodeverify/opaverifynodes.sh @@ -0,0 +1,229 @@ +#!/bin/bash +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] + +# verify hosts basic single node configuration and performance via hostverify.sh +# prior to using this, copy /usr/share/opa/samples/hostverify.sh to FF_HOSTVERIFY_DIR, +# and edit to set proper expectations for node configuration and performance, + +# optional override of defaults +if [ -f /etc/opa/opafastfabric.conf ] +then + . /etc/opa/opafastfabric.conf +fi + +. /usr/lib/opa/tools/opafastfabric.conf.def + +. /usr/lib/opa/tools/ff_funcs + +trap "exit 1" SIGHUP SIGTERM SIGINT + +punchlist=$FF_RESULT_DIR/punchlist.csv +del=';' # TBD what will work best for import + +Usage_full() +{ + echo "Usage: opaverifyhosts [-kc] [-f hostfile] [-u upload_file] [-d upload_dir]" >&2 + echo " [-h 'hosts'] [-T timelimit] [test ...]" >&2 + echo " or" >&2 + echo " opaverifyhosts --help" >&2 + echo " --help - produce full help text" >&2 + echo " -k - at start and end of verification, kill any existing hostverify" >&2 + echo " or xhpl jobs on the hosts" >&2 + echo " -c - copy hostverify.sh to hosts first, useful if you have edited it" >&2 + echo " -f hostfile - file with hosts in cluster, default is $CONFIG_DIR/opa/hosts" >&2 + echo " -h hosts - list of hosts to ping" >&2 + echo " -u upload_file - filename to upload hostverify.res to after verification" >&2 + echo " to allow backup and review of the detailed results" >&2 + echo " for each node" >&2 + echo " The default upload destination file is hostverify.res" >&2 + echo " If -u '' is specified, no upload will occur" >&2 + echo " -d upload_dir - directory to upload result from each host to" >&2 + echo " default is uploads" >&2 + echo " -T timelimit - timelimit in seconds for host to complete tests" >&2 + echo " default of 300 seconds (5 minutes)" >&2 + echo " -F filename - filename of hostverify script to use. Default is $FF_HOSTVERIFY_DIR/hostverify.sh" >&2 + echo " test - one or more specific tests to run" >&2 + echo " see /usr/share/opa/samples/hostverify.sh for a list of available tests" >&2 + echo "This verifies basic node configuration and performance by running" >&2 + echo "FF_HOSTVERIFY_DIR/hostverify.sh on all specified hosts" >&2 + echo >&2 + echo "Prior to using this, copy /usr/share/opa/samples/hostverify.sh to FF_HOSTVERIFY_DIR" >&2 + echo "and edit to set proper expectations for node configuration and performance" >&2 + echo "Then be sure to use the -c option on first run for a given node" >&2 + echo "so that hostverify.sh gets copied to each node." >&2 + echo "FF_HOSTVERIFY_DIR is configured in /etc/opa/opafastfabric.conf" >&2 + echo >&2 + echo "A summary of results is appended to FF_RESULT_DIR/verifyhosts.res." >&2 + echo "A punchlist of failures is also appended to FF_RESULT_DIR/punchlist.csv" >&2 + echo "Only failures are shown on stdout" >&2 + echo >&2 + echo " Environment:" >&2 + echo " HOSTS - list of hosts, used if -h option not supplied" >&2 + echo " HOSTS_FILE - file containing list of hosts, used in absence of -f and -h" >&2 + echo " UPLOADS_DIR - directory to upload to, used in absence of -d" >&2 + echo " FF_MAX_PARALLEL - maximum concurrent operations" >&2 + echo "example:">&2 + echo " opaverifyhosts -c" >&2 + echo " opaverifyhosts -h 'arwen elrond'" >&2 + echo " HOSTS='arwen elrond' opaverifyhosts" >&2 + exit 0 +} + +Usage() +{ + echo "Usage: opaverifyhosts [-kc] [-f hostfile] [-u upload_file]" >&2 + echo " or" >&2 + echo " opaverifyhosts --help" >&2 + echo " --help - produce full help text" >&2 + echo " -k - at start and end of verification, kill any existing hostverify" >&2 + echo " or xhpl jobs on the hosts" >&2 + echo " -c - copy hostverify.sh to hosts first, useful if you have edited it" >&2 + echo " -f hostfile - file with hosts in cluster, default is $CONFIG_DIR/opa/hosts" >&2 + echo " -u upload_file - filename to upload hostverify.res to after verification" >&2 + echo " to allow backup and review of the detailed results" >&2 + echo " for each node" >&2 + echo " The default upload destination file is hostverify.res" >&2 + echo " If -u '' is specified, no upload will occur" >&2 + echo >&2 + echo "This verifies basic node configuration and performance by running" >&2 + echo "FF_HOSTVERIFY_DIR/hostverify.sh on all specified hosts" >&2 + echo >&2 + echo "Prior to using this, copy /usr/share/opa/samples/hostverify.sh to FF_HOSTVERIFY_DIR" >&2 + echo "and edit to set proper expectations for node configuration and performance" >&2 + echo "Then be sure to use the -c option on first run for a given node" >&2 + echo "so that hostverify.sh gets copied to each node." >&2 + echo "FF_HOSTVERIFY_DIR is configured in /etc/opa/opafastfabric.conf" >&2 + echo >&2 + echo "A summary of results is appended to FF_RESULT_DIR/verifyhosts.res." >&2 + echo "A punchlist of failures is also appended to FF_RESULT_DIR/punchlist.csv" >&2 + echo "Only failures are shown on stdout" >&2 + echo >&2 + echo "example:">&2 + echo " opaverifyhosts" >&2 + echo " opaverifyhosts -c" >&2 + exit 2 +} + +if [ x"$1" = "x--help" ] +then + Usage_full +fi + +append_punchlist() +# stdin has verifyhosts.res failure lines generated in this run +{ + ( + export IFS=':' + opasorthosts | while read host failinfo + do + echo "$timestamp$del$host$del$failinfo" + done >> $punchlist + ) +} + +job_cleanup() +{ + # HOSTS is exported + if [ "$do_kill" = y ] + then + # we don't log this + echo "Killing hostverify and xhpl on hosts..." + # we use patterns so the pkill doesn't kill this script or opacmdall itself + # use an echo at end so exit status is good + opacmdall -p -T 60 "pkill -9 -f -x 'host[v]erify.*.sh'; pkill -9 '[x]hpl'; echo -n" + fi +} + +do_copy=n +upload_file=hostverify.res +timelimit=300 +do_kill=n +filename=$FF_HOSTVERIFY_DIR/hostverify.sh +while getopts kcf:h:d:u:T:F: param +do + case $param in + k) + do_kill=y;; + c) + do_copy=y;; + h) + HOSTS="$OPTARG";; + f) + HOSTS_FILE="$OPTARG";; + d) + export UPLOADS_DIR="$OPTARG";; + u) + upload_file="$OPTARG";; + T) + timelimit="$OPTARG";; + F) + filename="$OPTARG";; + ?) + Usage;; + esac +done +shift $((OPTIND -1)) +check_host_args opaverifyhosts +# HOSTS now lists all the hosts, pass it along to the commands below via env +export HOSTS +unset HOSTS_FILE + +job_cleanup + +echo "=============================================================================" >> $FF_RESULT_DIR/verifyhosts.res +date >> $FF_RESULT_DIR/verifyhosts.res +echo "$(echo "$HOSTS"|tr -s ' ' '\n'|sed -e '/^$/d'|sort -u| wc -l) hosts will be verified" | tee -a $FF_RESULT_DIR/verifyhosts.res + +if [ "$do_copy" = y ] +then + echo "SCPing $filename to $FF_HOSTVERIFY_DIR/hostverify.sh ..."| tee -a $FF_RESULT_DIR/verifyhosts.res + opascpall -p "$filename" "$FF_HOSTVERIFY_DIR/hostverify.sh" 2>&1|tee -a $FF_RESULT_DIR/verifyhosts.res + date >> $FF_RESULT_DIR/verifyhosts.res +fi + +timestamp=$(date +"%Y/%m/%d %T") +echo "Running $FF_HOSTVERIFY_DIR/hostverify.sh -d $FF_HOSTVERIFY_DIR $* ..." +resultlineno=$(cat $FF_RESULT_DIR/verifyhosts.res|wc -l) # for punchlist +opacmdall -p -T $timelimit "bash $FF_HOSTVERIFY_DIR/hostverify.sh -d $FF_HOSTVERIFY_DIR $*" 2>&1|tee -a $FF_RESULT_DIR/verifyhosts.res|egrep 'FAIL' +# update punchlist using new failures +tail -n +$resultlineno $FF_RESULT_DIR/verifyhosts.res| egrep 'FAIL'|append_punchlist +date >> $FF_RESULT_DIR/verifyhosts.res + +job_cleanup + +# upload the result file from each host +if [ z"$upload_file" != z ] +then + echo "Uploading $FF_HOSTVERIFY_DIR/hostverify.res to $UPLOADS_DIR/$upload_file ..."| tee -a $FF_RESULT_DIR/verifyhosts.res + opauploadall -p $FF_HOSTVERIFY_DIR/hostverify.res $upload_file 2>&1|tee -a $FF_RESULT_DIR/verifyhosts.res + date >> $FF_RESULT_DIR/verifyhosts.res +fi diff --git a/IbaTools/opa2rm/Makefile b/IbaTools/opa2rm/Makefile new file mode 100644 index 0000000..f12712e --- /dev/null +++ b/IbaTools/opa2rm/Makefile @@ -0,0 +1,167 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** +# Makefile for opa2rm + +# Include Make Control Settings +include $(TL_DIR)/$(PROJ_FILE_DIR)/Makesettings.project + +#=============================================================================# +# Definitions: +#-----------------------------------------------------------------------------# + +# Name of SubProjects +DS_SUBPROJECTS = +# name of executable or downloadable image +EXECUTABLE = $(BUILDDIR)/opa2rm$(EXE_SUFFIX) +# list of sub directories to build +DIRS = +# C files (.c) +CFILES = \ + opa2rm.c \ + # Add more c files here +# C++ files (.cpp) +CCFILES = \ + # Add more cpp files here +# lex files (.lex) +LFILES = \ + # Add more lex files here +# archive library files (basename, $ARFILES will add MOD_LIB_DIR/prefix and suffix) +LIBFILES= +# Windows Resource Files (.rc) +RSCFILES = +# Windows IDL File (.idl) +IDLFILE = +# Windows Linker Module Definitions (.def) file for dll's +DEFFILE = +# targets to build during INCLUDES phase (add public includes here) +INCLUDE_TARGETS = \ + # Add more h hpp files here +# Non-compiled files +MISC_FILES = +# all source files +SOURCES = $(CFILES) $(CCFILES) $(LFILES) $(RSCFILES) $(IDLFILE) +# Source files to include in DSP File +DSP_SOURCES = $(INCLUDE_TARGETS) $(SOURCES) $(MISC_FILES) \ + $(RSCFILES) $(DEFFILE) $(MAKEFILE) +# all object files +OBJECTS = $(CFILES:.c=$(OBJ_SUFFIX)) $(CCFILES:.cpp=$(OBJ_SUFFIX)) \ + $(LFILES:.lex=$(OBJ_SUFFIX)) +RSCOBJECTS = $(RSCFILES:.rc=$(RES_SUFFIX)) +# targets to build during LIBS phase +LIB_TARGETS_IMPLIB = +LIB_TARGETS_ARLIB = # $(LIB_PREFIX)ResourceTest$(ARLIB_SUFFIX) +LIB_TARGETS_EXP = $(LIB_TARGETS_IMPLIB:$(ARLIB_SUFFIX)=$(EXP_SUFFIX)) +LIB_TARGETS_MISC = +# targets to build during CMDS phase +CMD_TARGETS_SHLIB = +CMD_TARGETS_EXE = $(EXECUTABLE) +CMD_TARGETS_MISC = +# files to remove during clean phase +CLEAN_TARGETS_MISC = +CLEAN_TARGETS = $(OBJECTS) $(RSCOBJECTS) $(IDL_TARGETS) $(CLEAN_TARGETS_MISC) +# other files to remove during clobber phase +CLOBBER_TARGETS_MISC= +# sub-directory to install to within bin +BIN_SUBDIR = +# sub-directory to install to within include +INCLUDE_SUBDIR = + +# Additional Settings +#CLOCALDEBUG = User defined C debugging compilation flags [Empty] +#CCLOCALDEBUG = User defined C++ debugging compilation flags [Empty] +#CLOCAL = User defined C flags for compiling [Empty] +#CCLOCAL = User defined C++ flags for compiling [Empty] +#BSCLOCAL = User flags for Browse File Builder [Empty] +#DEPENDLOCAL = user defined makedepend flags [Empty] +#LINTLOCAL = User defined lint flags [Empty] +#LOCAL_INCLUDE_DIRS = User include directories to search for C/C++ headers [Empty] +#LDLOCAL = User defined C flags for linking [Empty] +#IMPLIBLOCAL = User flags for Object Lirary Manager [Empty] +#MIDLLOCAL = User flags for IDL compiler [Empty] +#RSCLOCAL = User flags for resource compiler [Empty] +#LOCALDEPLIBS = User libraries to include in dependencies [Empty] +#LOCALLIBS = User libraries to use when linking [Empty] +# (in addition to LOCALDEPLIBS) +#LOCAL_LIB_DIRS = User library directories for libpaths [Empty] + +CLOCAL=$(CIBACCESS) $(CPIE) +LOCAL_INCLUDE_DIRS= +ifeq "$(IB_STACK)" "IBACCESS" +LOCALDEPLIBS=$(IBACCESS_USER_LIBS) Xml Topology +LOCALLIBS=m +LOCAL_LIB_DIRS= $(IBACCESS_USER_LIB_DIRS) +else +LOCALDEPLIBS=$(IBACCESS_USER_LIBS) Xml Topology opamgt-priv +LOCALLIBS=$(OPENIB_USER_LIBS) m rt +LOCAL_LIB_DIRS=$(OPENIB_USER_LIB_DIRS) $(IBACCESS_USER_LIB_DIRS) +endif + +ifneq "$(BUILD_TARGET_OS)" "VXWORKS" +LOCALLIBS+= expat +endif + +# Include Make Rules definitions and rules +include $(TL_DIR)/IbaTools/Makerules.module + +#=============================================================================# +# Overrides: +#-----------------------------------------------------------------------------# +#CCOPT = # C++ optimization flags, default lets build config decide +#COPT = # C optimization flags, default lets build config decide +#SUBSYSTEM = Subsystem to build for (none, console or windows) [none] +# (Windows Only) +#USEMFC = How Windows MFC should be used (none, static, shared, no_mfc) [none] +# (Windows Only) +#=============================================================================# + +#=============================================================================# +# Rules: +#-----------------------------------------------------------------------------# +# process Sub-directories +include $(TL_DIR)/Makerules/Maketargets.toplevel + +# build cmds and libs +include $(TL_DIR)/Makerules/Maketargets.build + +# install for includes, libs and cmds phases +include $(TL_DIR)/Makerules/Maketargets.install + +# install for stage phase +#include $(TL_DIR)/Makerules/Maketargets.stage +STAGE:: + $(VS)$(STAGE_INSTALL) $(STAGE_INSTALL_DIR_OPT) $(PROJ_STAGE_FASTFABRIC_DIR) $(EXECUTABLE) $(CMD_TARGETS_MISC) + +# Unit test execution +#include $(TL_DIR)/Makerules/Maketargets.runtest + +#=============================================================================# + +#=============================================================================# +# DO NOT DELETE THIS LINE -- make depend depends on it. +#=============================================================================# diff --git a/IbaTools/opa2rm/README b/IbaTools/opa2rm/README new file mode 100644 index 0000000..c8d8390 --- /dev/null +++ b/IbaTools/opa2rm/README @@ -0,0 +1,3 @@ +[ICS VERSION STRING: unknown] + +translate a topology.xml file to a resource manager config file diff --git a/IbaTools/opa2rm/opa2rm.c b/IbaTools/opa2rm/opa2rm.c new file mode 100644 index 0000000..fd3b01a --- /dev/null +++ b/IbaTools/opa2rm/opa2rm.c @@ -0,0 +1,1557 @@ +/* BEGIN_ICS_COPYRIGHT7 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT7 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +#include +#include +#include +#include +#include +#include +#include +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#define MYTAG MAKE_MEM_TAG('o','2', 'r', 'm') + +#define DBGPRINT(format, args...) \ + do { if (g_verbose) { fflush(stdout); fprintf(stderr, format, ##args); } } while (0) + +#define PROGRESS_PRINT(newline, format, args...) \ + do { if (! g_quiet) { ProgressPrint(newline, format, ##args); } } while (0) + +#define PROGRESS_FREQ 1000 + +#define MIN_LIST_ITEMS 10 // for neighbor sw and fi DLISTs + +// macro to always return a valid pointer for use in %s formats +#define OPTIONAL_STR(s) (s?s:"") + +#define RANGE_IN_MIDDLE 0 // should ranges in middle of name be permitted + +uint8 g_verbose = 0; +uint8 g_quiet = 0; // omit progress output +#define MAX_FOCUS 10 +char *g_focus_arg[MAX_FOCUS]; +Point g_focus[MAX_FOCUS]; +int g_num_focus = 0; +char* g_prefix = NULL; // prefix for all FIs +char* g_suffix = NULL; // suffix for all FIs + +// All the information about the fabric +FabricData_t g_Fabric; + +// In order to allow removal of spaces, sorting and compacting +// names into ranges (eg. compute[1-10]) we keep a NameData per +// name we want to show. The NameData includes the reformated full name +// and the parsed elements of body, numeric range and end +typedef struct NameData_s { + cl_map_item_t NameListEntry; // nameList, key is name + char name[NODE_DESCRIPTION_ARRAY_SIZE]; // full name + + // a name is broken into four parts, body is alphanumeric + // start,end is a numeric part at the end of the body + // prefix is a prefix we will add afterwards such as opa- for IPoIB on OPA + // suffix is a suffix we will add afterwards such as -opa for IPoIB on OPA + const char *prefix; + char body[NODE_DESCRIPTION_ARRAY_SIZE]; + uint32 start, end; // numeric range + boolean leadzero; // did original name have leading zeros for number + int8 numlen; // number of characters in number in original name + const char *suffix; +} NameData_t; + +// This will be attached to each switch node via ExpectedNode.context +typedef struct SwitchLists_s { + cl_qmap_t fiNeighborNames;// filtered list of neighbor FIs NameData_t + cl_qmap_t swNeighborNames;// filtered list of neighbor SWs NameData_t + uint8 tier; // tier in tree of given switch + // (distance from FIs) + DLIST swNeighbors; // list of all neighbor SWs ExpectedNode* +} SwitchLists_t; + +boolean CompareExpectedNodeFocus(ExpectedNode *enodep); +boolean CompareExpectedLinkFocus(ExpectedLink *elinkp); + +// -------------- output of Expected* functions -------------------- +// these next few functions are for error output and debug +// They allow dumping of the input topology file which was parsed +// output goes to stderr + +// show 1 port selector in link data in brief form +void ShowExpectedLinkPortSelBriefSummary(ExpectedLink *elinkp, PortSelector *portselp, + uint8 side, int indent, int detail) +{ + DEBUG_ASSERT(side == 1 || side == 2); + fprintf(stderr, "%*s%4s ", indent, "", + (side == 1)? + elinkp->expected_rate? + StlStaticRateToText(elinkp->expected_rate) + :"" + : "<-> "); + if (side == 1 && elinkp->expected_mtu) + fprintf(stderr, "%5s ", IbMTUToText(elinkp->expected_mtu)); + else + fprintf(stderr, " "); + + if (portselp) { + if (portselp->NodeGUID) + fprintf(stderr, "0x%016"PRIx64, portselp->NodeGUID); + else + fprintf(stderr, " "); + if (portselp->gotPortNum) + fprintf(stderr, " %3u ",portselp->PortNum); + else if (portselp->PortGUID) + fprintf(stderr, " 0x%016"PRIx64, portselp->PortGUID); + else + fprintf(stderr, " "); + if (portselp->NodeType) + fprintf(stderr, " %s", + StlNodeTypeToText(portselp->NodeType)); + else + fprintf(stderr, " "); + if (portselp->NodeDesc) + fprintf(stderr, " %.*s\n", + NODE_DESCRIPTION_ARRAY_SIZE, portselp->NodeDesc); + else + fprintf(stderr, "\n"); + if (detail) { + if (portselp->details) { + fprintf(stderr, "%*sPortDetails: %s\n", indent+4, "", portselp->details); + } + } + } else { + fprintf(stderr, "unspecified\n"); + } +} + + +// show cable information for a link in multi-line format with field headings +void ShowExpectedLinkSummary(ExpectedLink *elinkp, + int indent, int detail) +{ + // From Side (Port 1) + ShowExpectedLinkPortSelBriefSummary(elinkp, elinkp->portselp1, + 1, indent, detail); + // To Side (Port 2) + ShowExpectedLinkPortSelBriefSummary(elinkp, elinkp->portselp2, + 2, indent, detail); + if (elinkp->details) { + fprintf(stderr, "%*sLinkDetails: %s\n", indent, "", elinkp->details); + } + if (elinkp->CableData.length || elinkp->CableData.label + || elinkp->CableData.details) { + fprintf(stderr, "%*sCableLabel: %-*s CableLen: %-*s\n", + indent, "", + CABLE_LABEL_STRLEN, OPTIONAL_STR(elinkp->CableData.label), + CABLE_LENGTH_STRLEN, OPTIONAL_STR(elinkp->CableData.length)); + fprintf(stderr, "%*sCableDetails: %s\n", + indent, "", + OPTIONAL_STR(elinkp->CableData.details)); + } +} + +// Verify links in fabric against specified topology +void ShowExpectedLinksReport(/*Point *focus,*/ int indent, int detail) +{ + LIST_ITEM *p; + uint32 input_checked = 0; + + fprintf(stderr, "%*sLinks Topology Expected\n", indent, ""); + + fprintf(stderr, "%*sRate MTU NodeGUID Port or PortGUID Type Name\n", indent, ""); + if (detail && (g_Fabric.flags & FF_CABLEDATA)) { + //fprintf(stderr, "%*sPortDetails\n", indent+4, ""); + //fprintf(stderr, "%*sLinkDetails\n", indent+4, ""); + fprintf(stderr, "%*sCable: %-*s %-*s\n", indent+4, "", + CABLE_LABEL_STRLEN, "CableLabel", + CABLE_LENGTH_STRLEN, "CableLen"); + fprintf(stderr, "%*s%s\n", indent+4, "", "CableDetails"); + } + for (p=QListHead(&g_Fabric.ExpectedLinks); p != NULL; p = QListNext(&g_Fabric.ExpectedLinks, p)) { + ExpectedLink *elinkp = (ExpectedLink *)QListObj(p); + + if (! elinkp) + continue; + if (! CompareExpectedLinkFocus(elinkp)) + continue; + input_checked++; + ShowExpectedLinkSummary(elinkp, indent, detail); + } + if (detail && input_checked) + fprintf(stderr, "\n"); // blank line between links + fprintf(stderr, "%*s%u of %u Input Links Shown\n", indent, "", + input_checked, QListCount(&g_Fabric.ExpectedLinks)); + + return; +} + +// output brief summary of an expected IB Node +void ShowExpectedNodeBriefSummary(ExpectedNode *enodep, int indent, int detail) +{ + fprintf(stderr, "%*s", indent, ""); + if (enodep->NodeGUID) + fprintf(stderr, "0x%016"PRIx64, enodep->NodeGUID); + else + fprintf(stderr, " "); + if (enodep->NodeType) + fprintf(stderr, " %s", StlNodeTypeToText(enodep->NodeType)); + else + fprintf(stderr, " "); + if (enodep->NodeDesc) + fprintf(stderr, " %s\n", enodep->NodeDesc); + else + fprintf(stderr, "\n"); + if (enodep->details) + fprintf(stderr, "%*sNodeDetails: %s\n", indent+4, "", enodep->details); +} + +// Verify nodes in fabric against specified topology +void ShowExpectedNodesReport(/*Point *focus,*/ uint8 NodeType, int indent, int detail) +{ + LIST_ITEM *p; + uint32 input_checked = 0; + const char *NodeTypeText = StlNodeTypeToText(NodeType); + QUICK_LIST *input_listp; + + switch (NodeType) { + case STL_NODE_FI: + input_listp = &g_Fabric.ExpectedFIs; + break; + case STL_NODE_SW: + input_listp = &g_Fabric.ExpectedSWs; + break; + default: + ASSERT(0); + break; + } + + // intro for report + fprintf(stderr, "%*s%ss Topology Expected\n", indent, "", NodeTypeText); + for (p=QListHead(input_listp); p != NULL; p = QListNext(input_listp, p)) { + ExpectedNode *enodep = (ExpectedNode *)QListObj(p); + + if (! enodep) + continue; + input_checked++; + ShowExpectedNodeBriefSummary(enodep, indent, detail); + } + if (detail && input_checked) + fprintf(stderr, "\n"); // blank line between links + fprintf(stderr, "%*s%u of %u Input %ss Shown\n", indent, "", + input_checked, QListCount(input_listp), NodeTypeText); + return; +} + +// --------------------- NameData functions ---------------------------- + +// when using GUIDs as name, put whole value in body +void SetNameToGuid(NameData_t *namep, EUI64 guid) +{ + sprintf(namep->name, "0x%016"PRIx64, guid); + namep->prefix = NULL; + StringCopy(namep->body, namep->name, NODE_DESCRIPTION_ARRAY_SIZE); + namep->start = 0; + namep->end = 0; + namep->leadzero = FALSE; + namep->numlen = 0; + namep->suffix = NULL; +} + +// Name processing copy Modes: +// underscore - simple conversion of space to underscore +// trunc - take all chars after 1st space and remove +// host405 hfi1_0 -> host405 +// can be useful for single and multi-rail hosts +// can also be useful to produce a more concise slurm file +// by treating large switches as a single black box entity +// flip - take all chars after 1st space and put at start of name +// any additional spaces converted to underscore +// opacore7 Leaf101 -> Leaf101_opacore7 +// can be useful so can sort and combine to get ranges +// such as Leaf101_opacore[1-7] +// guid - use text representation of hex GUID +// TBD - future - could add multi-rail suffix addition or replace modes +// - algortihmic suffix (hf1_0 -> -opa1, hfi1_1 -> -opa2) +typedef enum { + NAME_MODE_UNDERSCORE = 1, + NAME_MODE_FLIP = 2, + NAME_MODE_TRUNC = 3, + NAME_MODE_GUID = 4 +} name_mode_t; + + +// translate and copy name into a NameData, separating out body and number +// and adding prefix and suffix +void CopyName(NameData_t *namep, const char *name, EUI64 guid, name_mode_t mode, + const char *prefix, const char *suffix) +{ + int len = 0; + int i; + + if (! name || mode == NAME_MODE_GUID) { + DEBUG_ASSERT(guid); + SetNameToGuid(namep, guid); + return; + } + if (mode == NAME_MODE_UNDERSCORE) { + // change spaces to underscore + int l; + char *d; + StringCopy(namep->name, name, sizeof(namep->name)); + len = strnlen(namep->name, sizeof(namep->name)); + for (l=len, d=namep->name; l; d++, l--) + if (isspace(*d)) + *d = '_'; + } else if (mode == NAME_MODE_TRUNC) { + // truncate at 1st space + int l; + char *d; + StringCopy(namep->name, name, sizeof(namep->name)); + len = strnlen(namep->name, sizeof(namep->name)); + for (l=len, d=namep->name; l; d++, l--) { + if (isspace(*d)) { + *d = '\0'; + break; + } + } + len = (d - namep->name); + } else if (mode == NAME_MODE_FLIP) { + // put content after 1st space at start of string, + // replacing space w/underscore + int l; + const char *s; + char *d = namep->name; + for (l=sizeof(namep->name), s=name; l && *s && ! isspace(*s); s++, l--) + ; + if (l && *s) { + // we found a space + DEBUG_ASSERT(isspace(*s)); + s++; l--; + // copy remaining characters to start of string + for (; l && *s; s++, l--) + if(!isspace(*s)) + *d++ = *s; + *d++ = '_'; + } + // now copy up to the 1st space into the remainder + for (l=sizeof(namep->name) - (d-namep->name), s=name; l && *s && ! isspace(*s); s++, d++, l--) + *d = *s; + if (l) + *d='\0'; + len = (d - namep->name); + } + + namep->prefix = prefix; + StringCopy(namep->body, namep->name, sizeof(namep->body)); + // assume no number + namep->numlen = 0; + namep->start = 0; + namep->end = 0; + if (len) { + for (i=len; i> 0 && isdigit(namep->body[i-1]); i--) + ; + if (i != len) { + // we have a number, starting at body[i] + if (FSUCCESS == StringToUint32(&namep->start, &namep->body[i], NULL, 10, FALSE)) { + namep->numlen = len - i; + namep->end = namep->start; + namep->leadzero = (namep->numlen > 1 && namep->body[i] == '0'); + namep->body[i] = '\0'; + } + } + } + namep->suffix = suffix; + DBGPRINT("name=%s, prefix=%s body=%s, suffix=%s\n", namep->name, + namep->prefix?namep->prefix:"", namep->body, + namep->suffix?namep->suffix:""); + DBGPRINT("numlen=%u, leadzero=%d, start=%u end=%u\n", namep->numlen, + namep->leadzero, namep->start, namep->end); +} + +void PrintName(const NameData_t *namep) +{ + if (namep->prefix) + printf("%s", namep->prefix); + printf("%.*s", NODE_DESCRIPTION_ARRAY_SIZE, namep->body); + if (namep->numlen) { + if (namep->leadzero) + if (namep->start != namep->end) + printf("[%0*u-%0*u]", namep->numlen, namep->start, namep->numlen, namep->end); + else + printf("%0*u", namep->numlen, namep->start); + else + if (namep->start != namep->end) + printf("[%u-%u]", namep->start, namep->end); + else + printf("%u", namep->start); + } + if (namep->suffix) + printf("%s", namep->suffix); +} + +// is name2 numerically sequential and after name1 +// if so we can consider combining them +boolean SequentialNames(const NameData_t *name1p, const NameData_t *name2p) +{ + // to optimize speed of compare, we do the faster checks 1st + if (! name1p->numlen || ! name2p->numlen) + return FALSE; // only sequential if have numbers + if (name1p->end+1 != name2p->start) + return FALSE; // not in sequence + if (name1p->leadzero && name1p->numlen == name2p->numlen) { + // ok, leading zeros in the lower numbered namep and constant length + } else if (!name2p->leadzero && ! name2p->leadzero) { + // ok, no leading zeros, all good + } else { + return FALSE; // number representation inconsistent + } +#if ! RANGE_IN_MIDDLE + if (name1p->suffix || name2p->suffix) + return FALSE; // can't have range in middle of a name +#endif + if (name1p->prefix) { + if (!name2p->prefix || 0 != strncmp(name1p->prefix, name2p->prefix, NODE_DESCRIPTION_ARRAY_SIZE)) + return FALSE; // different prefix + } else if (name2p->prefix) { + return FALSE; // different prefix + } + if (0 != strncmp(name1p->body, name2p->body, NODE_DESCRIPTION_ARRAY_SIZE)) + return FALSE; // different body + + if (name1p->suffix) { + if (!name2p->suffix || 0 != strncmp(name1p->suffix, name2p->suffix, NODE_DESCRIPTION_ARRAY_SIZE)) + return FALSE; // different suffix + } else if (name2p->suffix) { + return FALSE; // different suffix + } + return TRUE; +} + +// compare two names and return: +// -1 - name1 < name2 +// 0 - name1 == name2 +// 1 - name1 > name2 +int CompareNameData(IN const uint64 name1, IN const uint64 name2) +{ + const NameData_t *name1p = (const NameData_t*)name1; + const NameData_t *name2p = (const NameData_t*)name2; + int ret; + + DBGPRINT("CompareNameData: %s, %s\n", name1p->name, name2p->name); + if (name1p->prefix) { + if (!name2p->prefix) { + return 1; + } else { + ret = strncmp(name1p->prefix, name2p->prefix, NODE_DESCRIPTION_ARRAY_SIZE); + if (ret) + return ret; + } + } else if (name2p->prefix) { + return -1; + } + ret = strncmp(name1p->body, name2p->body, NODE_DESCRIPTION_ARRAY_SIZE); + if (ret) + return ret; + if (! name1p->numlen || ! name2p->numlen) { + // if only 1 has a number, put one without a number 1st + if (name1p->numlen) + return 1; + else if (name2p->numlen) + return -1; + } + // for RANGE_IN_MIDDLE we want items with same suffix together so we can + // find best opportunities to combine, so sort by suffix prior to sorting + // by numeric field + // for ! RANGE_IN_MIDDLE, we want to sort by suffix after sort by numeric + if (name1p->suffix) { + if (!name2p->suffix) { + ret = 1; + } else { + ret = strncmp(name1p->suffix, name2p->suffix, NODE_DESCRIPTION_ARRAY_SIZE); + if (ret) + return ret; + } + } else if (name2p->suffix) { + ret = -1; + } +#if RANGE_IN_MIDDLE + if (ret) + return ret; +#endif + if (! name1p->numlen && ! name2p->numlen) + return ret; + // if we see two styles of format, we want to sort those with shorter + // numeric fields first. c0, c1, c000, c001 so we can find best + // opportunities to combine sequential ranges + if (name1p->leadzero || name2p->leadzero) { + if (name1p->numlen < name2p->numlen) + return -1; + else if (name1p->numlen > name2p->numlen) + return -1; + } + if (name1p->start < name2p->start) + return -1; + else if (name1p->start > name2p->start) + return 1; + else + return ret; +} + +// updates name1p to include name2p +// only valid if name1p and name2p are sequential +// before or after this update, name2p should be remove from list +void CombineNames(NameData_t *name1p, const NameData_t *name2p) +{ + DEBUG_ASSERT(SequentialNames(name1p, name2p)); + DBGPRINT("Combining: %s, %s\n", name1p->name, name2p->name); + name1p->end = name2p->end; +} + +// --------------------- NameData list functions ---------------------------- + +void InitNameList(cl_qmap_t *listp) +{ + cl_qmap_init(listp, CompareNameData); +} + +// add name to list if not already on list +// the algorithm assumes duplicates are relatively infrequent so its simpler +// to just build the final NameData for comparison and throw it away on a +// duplicate. Alternatives would be more complex and have an extra copy +// of the name string for each non-dup +// rationale: +// - hosts on a switch will have no dups +// - ISLs will have dups limited to trunk size of link (1-4 typical) +FSTATUS AddNameList(cl_qmap_t *listp, const char* name, EUI64 guid, name_mode_t mode, + const char *prefix, const char *suffix) +{ + NameData_t *namep; + + if (name) + DBGPRINT("AddNameList: %s 0x%016"PRIx64"\n", name, guid); + else + DBGPRINT("AddNameList: NULL 0x%016"PRIx64"\n", guid); + namep = (NameData_t *)MemoryAllocate2AndClear(sizeof(NameData_t), IBA_MEM_FLAG_PREMPTABLE, MYTAG); + if (! namep) { + fprintf(stderr, "Out of memory\n"); + return FINSUFFICIENT_MEMORY; + } + CopyName(namep, name, guid, mode, prefix, suffix); + if (cl_qmap_insert(listp, (uint64)(uintn)namep, &namep->NameListEntry) != &namep->NameListEntry) { + // name already on list + MemoryDeallocate(namep); + return FSUCCESS; + } + DBGPRINT("AddNameList: created new entry\n"); + return FSUCCESS; +} + +// take the sorted list and convert sequential names to a numeric range +// two styles of numeric ranges: name[0-10] and name[00-10] indicate if +// leading zeros were present in the original names +void CompactNameList(cl_qmap_t *listp) +{ + cl_map_item_t *p; + + DBGPRINT("compacting name list\n"); + for (p=cl_qmap_head(listp); p != cl_qmap_end(listp);) { + NameData_t *name1p = PARENT_STRUCT(p, NameData_t, NameListEntry); + NameData_t *name2p; + cl_map_item_t *next= cl_qmap_next(p); + if (next == cl_qmap_end(listp)) + break; + DBGPRINT("compacting name list: p: %p, next: %p\n", p, next); + name2p = PARENT_STRUCT(next, NameData_t, NameListEntry); + if (SequentialNames(name1p, name2p)) { + cl_qmap_remove_item(listp, next); + CombineNames(name1p, name2p); + MemoryDeallocate(name2p); + } else { + p = cl_qmap_next(p); + } + } +} + +void FreeNameList(cl_qmap_t *listp) +{ + cl_map_item_t *p; + + for (p=cl_qmap_head(listp); p != cl_qmap_end(listp); p = cl_qmap_head(listp)) { + NameData_t *namep = PARENT_STRUCT(p, NameData_t, NameListEntry); + cl_qmap_remove_item(listp, p); + MemoryDeallocate(namep); + } +} + +// --------------------- SwitchLists functions ---------------------------- + +static __inline cl_qmap_t *GetSwitchFiNeighNameList(ExpectedNode *enodep) +{ + return &((SwitchLists_t*)enodep->context)->fiNeighborNames; +} + +static __inline cl_qmap_t *GetSwitchSwNeighNameList(ExpectedNode *enodep) +{ + return &((SwitchLists_t*)enodep->context)->swNeighborNames; +} + +static __inline uint8 GetSwitchTier(ExpectedNode *enodep) +{ + return ((SwitchLists_t*)enodep->context)->tier; +} + +static __inline DLIST *GetSwitchSwNeighList(ExpectedNode *enodep) +{ + return &((SwitchLists_t*)enodep->context)->swNeighbors; +} + +FSTATUS AllocSwitchLists(ExpectedNode *enodep) +{ + enodep->context = MemoryAllocate2AndClear(sizeof(SwitchLists_t), IBA_MEM_FLAG_PREMPTABLE, MYTAG); + if (! enodep->context) + return FINSUFFICIENT_MEMORY; + InitNameList(GetSwitchFiNeighNameList(enodep)); + InitNameList(GetSwitchSwNeighNameList(enodep)); + ListInitState(&((SwitchLists_t*)enodep->context)->swNeighbors); + if (! ListInit(&((SwitchLists_t*)enodep->context)->swNeighbors, MIN_LIST_ITEMS)) + goto fail; + return FSUCCESS; + +fail: + MemoryDeallocate(enodep->context); + return FINSUFFICIENT_MEMORY; +} + +void FreeSwitchLists(ExpectedNode *enodep) +{ + if (enodep->context) { + FreeNameList(GetSwitchFiNeighNameList(enodep)); + FreeNameList(GetSwitchSwNeighNameList(enodep)); + ListDestroy(&((SwitchLists_t*)enodep->context)->swNeighbors); + MemoryDeallocate(enodep->context); + enodep->context = NULL; + } +} + +FSTATUS AddSwitchFiNameList(ExpectedNode *enodep, const char* name, EUI64 guid, name_mode_t mode, + const char *prefix, const char *suffix) +{ + if (! enodep->context) { + FSTATUS status = AllocSwitchLists(enodep); + if (FSUCCESS != status) + return status; + } + return AddNameList(GetSwitchFiNeighNameList(enodep), name, guid, mode, + prefix, suffix); +} + +FSTATUS AddSwitchSwNameList(ExpectedNode *enodep, const char* name, EUI64 guid, name_mode_t mode, + const char *prefix, const char *suffix) +{ + if (! enodep->context) { + FSTATUS status = AllocSwitchLists(enodep); + if (FSUCCESS != status) + return status; + } + return AddNameList(GetSwitchSwNeighNameList(enodep), name, guid, mode, + prefix, suffix); +} + +FSTATUS SetSwitchTier(ExpectedNode *enodep, uint8 tier) +{ + if (! enodep->context) { + FSTATUS status = AllocSwitchLists(enodep); + if (FSUCCESS != status) + return status; + } + ((SwitchLists_t*)enodep->context)->tier = tier; + return FSUCCESS; +} + +FSTATUS AddSwitchSwNeighbor(ExpectedNode *enodep, ExpectedNode *swnodep) +{ + if (! enodep->context) { + FSTATUS status = AllocSwitchLists(enodep); + if (FSUCCESS != status) + return status; + } + if (! ListInsertTail(&((SwitchLists_t*)enodep->context)->swNeighbors, swnodep)) + return FINSUFFICIENT_MEMORY; + return FSUCCESS; +} + +// analyze the expected links to determine the swNeighbors for each switch. +// TBD - Future - would be nice to be able to filter out selected hosts such as +// service nodes connected to core, but would need to figure out how to +// filter out edge switches left with no hosts so they aren't mistaken for +// core switches. For now, SLURM uses with impure trees or other topologies +// should use the -o slurm option which will provide a brief report which does +// not list all the ISLs +void BuildSwitchNeighList(boolean get_isls) +{ + LIST_ITEM *q; + LIST_ITEM *p; + uint8 tier = 0; + boolean found; + + if (! get_isls) + return; + + // now populate swNeighbors for each switch and identify tier 1 switches + for (q=QListHead(&g_Fabric.ExpectedLinks); q != NULL; q = QListNext(&g_Fabric.ExpectedLinks, q)) { + ExpectedLink *elinkp = (ExpectedLink *)QListObj(q); + + if (! elinkp->portselp1 || ! elinkp->portselp1->enodep + || ! elinkp->portselp2 || ! elinkp->portselp2->enodep) { + // Skipping Link, unresolved + continue; + } + // figure out the types on both ends + switch (elinkp->portselp1->enodep->NodeType) { + case STL_NODE_FI: + switch (elinkp->portselp2->enodep->NodeType) { + case STL_NODE_FI: // FI<->FI + // Skipping Link, unexpected FI<->FI link + break; + case STL_NODE_SW: // FI<->SW + (void)SetSwitchTier(elinkp->portselp2->enodep, 1); + break; + default: // should not happen, enodep should always have type + // Skipping Link, unspecified NodeType + break; + } + break; + case STL_NODE_SW: + switch (elinkp->portselp2->NodeType) { + case STL_NODE_FI: // SW<->FI + (void)SetSwitchTier(elinkp->portselp1->enodep, 1); + break; + case STL_NODE_SW: // SW<->SW + (void)AddSwitchSwNeighbor(elinkp->portselp1->enodep, elinkp->portselp2->enodep); + (void)AddSwitchSwNeighbor(elinkp->portselp2->enodep, elinkp->portselp1->enodep); + break; + default: // should not happen, enodep should always have type + // Skipping Link, unspecified NodeType + break; + } + break; + default: // should not happen, enodep should always have type + // Skipping Link, unspecified NodeType + continue; + } + } + + // now we have tier 1 switches identified, need to walk up the tree to + // identify higher tier switches (higher is closer to core and further from + // FIs) + // This algorithm is based on Topology/route.c:DetermineSwitchTiers except + // this works with ExpectedNode while route.c works with NodeData + // + // switches connected to tier 1 switches are tier 2, etc + + // This algorithm works fine for pure trees, however for impure trees + // it can yield unexpected results, for example a core switch with an HFI + // will be considered a tier 1 switch. + tier=2; + do { + found = FALSE; + for (p=QListHead(&g_Fabric.ExpectedSWs); p != NULL; p = QListNext(&g_Fabric.ExpectedSWs, p)) { + ExpectedNode *enodep = (ExpectedNode *)QListObj(p); + LIST_ITERATOR i; + if (GetSwitchTier(enodep) != tier-1) + continue; + for (i=ListHead(GetSwitchSwNeighList(enodep)); i != NULL; + i = ListNext(GetSwitchSwNeighList(enodep),i)) { + ExpectedNode* nswnodep = (ExpectedNode*)ListObj(i); + if (! GetSwitchTier(nswnodep)) { + SetSwitchTier(nswnodep, tier); + found = TRUE; + } + } + } + tier++; + } while (found); + return; +} + +// Analyze ExpectedLinks and build lists of neighbors in ExpectedSW's context +// pointer in preparation for output generation +// The algorithm here assumes: +// - ExpectedSWs and ExpectedLinks are both supplied and consistent +// - NodeDesc and/or NodeGUID is listed for each entry +// - All entries in both have NodeType +// The above will all be true if the topology.xml was autogenerated by +// opaxlattopologory or opareport -o topology +void BuildAllSwitchLists(name_mode_t switch_name_mode, name_mode_t node_name_mode, boolean get_isls, boolean get_hfis) +{ + LIST_ITEM *q; + uint32 input_checked = 0; + uint32 bad_input = 0; + uint32 fi_links = 0; + uint32 isl_links = 0; + uint32 bad_isl_links = 0; + uint32 ix = 0; + + BuildSwitchNeighList(get_isls); + + PROGRESS_PRINT(TRUE, "Processing Links..."); + for (q=QListHead(&g_Fabric.ExpectedLinks); q != NULL; q = QListNext(&g_Fabric.ExpectedLinks, q)) { + ExpectedLink *elinkp = (ExpectedLink *)QListObj(q); + ExpectedNode *swenodep = NULL; + ExpectedNode *nswenodep = NULL; + ExpectedNode *fienodep = NULL; + + if ((ix++ % PROGRESS_FREQ) == 0) { + PROGRESS_PRINT(FALSE, "Processed %6d of %6d Links...", + ix, QListCount(&g_Fabric.ExpectedLinks)); + } + + if (! elinkp->portselp1 || ! elinkp->portselp1->enodep + || ! elinkp->portselp2 || ! elinkp->portselp2->enodep) { + fprintf(stderr, "Skipping Link (topology file line %"PRIu64"), unresolved:\n", elinkp->lineno); + ShowExpectedLinkSummary(elinkp, 4, 0); + bad_input++; + continue; + } + // figure out the types on both ends, want FI-SW and SW-SW links + switch (elinkp->portselp1->enodep->NodeType) { + case STL_NODE_FI: + switch (elinkp->portselp2->enodep->NodeType) { + case STL_NODE_FI: + fprintf(stderr, "Skipping Link (topology file line %"PRIu64"), unexpected FI<->FI link:\n", elinkp->lineno); + ShowExpectedLinkSummary(elinkp, 4, 0); + bad_input++; + continue; + case STL_NODE_SW: + fienodep = elinkp->portselp1->enodep; + swenodep = elinkp->portselp2->enodep; + break; + default: + fprintf(stderr, "Skipping Link (topology file line %"PRIu64"), unspecified NodeType:\n", elinkp->lineno); + ShowExpectedLinkSummary(elinkp, 4, 0); + bad_input++; + continue; + } + break; + case STL_NODE_SW: + switch (elinkp->portselp2->enodep->NodeType) { + case STL_NODE_FI: + swenodep = elinkp->portselp1->enodep; + fienodep = elinkp->portselp2->enodep; + break; + case STL_NODE_SW: + swenodep = elinkp->portselp1->enodep; + nswenodep = elinkp->portselp2->enodep; + break; + default: + fprintf(stderr, "Skipping Link (topology file line %"PRIu64"), unspecified NodeType:\n", elinkp->lineno); + ShowExpectedLinkSummary(elinkp, 4, 0); + bad_input++; + continue; + } + break; + default: + fprintf(stderr, "Skipping Link (topology file line %"PRIu64"), unspecified NodeType:\n", elinkp->lineno); + ShowExpectedLinkSummary(elinkp, 4, 0); + bad_input++; + continue; + } + // now swenodep is a SW + // if neighbor is a FI, fienodep is non-NULL + // if neighbor is a SW, nswenodep is non-NULL + DEBUG_ASSERT(swenodep); + DEBUG_ASSERT(nswenodep || fienodep); + + if ( ! get_hfis && ! nswenodep) + continue; // skip FI-SW link + if ( ! get_isls && ! fienodep) + continue; // skip SW-SW link + if (! CompareExpectedLinkFocus(elinkp)) + continue; + input_checked++; + if (fienodep) { // FI<->SW + (void)AddSwitchFiNameList(swenodep, fienodep->NodeDesc, fienodep->NodeGUID, node_name_mode, g_prefix, g_suffix); + fi_links++; + } else { // SW<->SW + // only add downlink which goes from upper tier switch to lower tier + // SLURM wants just one direction reported for each link, so + // we only report downlinks in pure trees and warn if any links are + // found which are not tier X to tier X-1 or tier X+1 + if (GetSwitchTier(swenodep) == GetSwitchTier(nswenodep)+1) { + (void)AddSwitchSwNameList(swenodep, nswenodep->NodeDesc, nswenodep->NodeGUID, switch_name_mode, NULL, NULL); + isl_links++; + } else if (GetSwitchTier(nswenodep) == GetSwitchTier(swenodep)+1) { + (void)AddSwitchSwNameList(nswenodep, swenodep->NodeDesc, swenodep->NodeGUID, switch_name_mode, NULL, NULL); + isl_links++; + } else { + // This is a best attempt but will not catch all issues + // for example a 3 tier fabric with an HFI on the core will + // treat the core as a tier 1 which is connected to tier 2 + // switches and hence not reported as an issue + fprintf(stderr, "Skipping Link (topology file line %"PRIu64"), not a pure tree:\n", elinkp->lineno); + ShowExpectedLinkSummary(elinkp, 4, 0); + bad_isl_links++; + } + } + } + PROGRESS_PRINT(TRUE, "Done Processing Links"); + fprintf(stderr, "%u of %u Input Links Selected, %u Bad Input Skipped\n", + input_checked, QListCount(&g_Fabric.ExpectedLinks), bad_input); + if (get_hfis) + fprintf(stderr, "%u Input FI Links Shown\n", + fi_links); + if (get_isls) + fprintf(stderr, "%u Input ISLs Shown, %u Bad ISLs Skipped\n", + isl_links, bad_isl_links); + return; +} + +void FreeAllSwitchNamelists(void) +{ + LIST_ITEM *p; + + for (p=QListHead(&g_Fabric.ExpectedSWs); p != NULL; p = QListNext(&g_Fabric.ExpectedSWs, p)) { + ExpectedNode *enodep = (ExpectedNode *)QListObj(p); + + FreeSwitchLists(enodep); + } +} + +// --------------------- Focus functions ---------------------------- + +// compare against all -F options provided +// if matches any one of the -F options, returns TRUE +boolean CompareExpectedNodeFocus(ExpectedNode *enodep) +{ + int i; + + if (! g_num_focus) + return TRUE; // match everything if no focus + for (i=0; i < g_num_focus; i++) + if (CompareExpectedNodePoint(enodep, &g_focus[i])) + return TRUE; + return FALSE; +} + +// compare against all -F options provided +// if matches any one of the -F options, returns TRUE +boolean CompareExpectedLinkFocus(ExpectedLink *elinkp) +{ + int i; + + if (! g_num_focus) + return TRUE; // match everything if no focus + for (i=0; i < g_num_focus; i++) + if (CompareExpectedLinkPoint(elinkp, &g_focus[i])) + return TRUE; + return FALSE; +} + +// --------------------- Output functions ---------------------------- + +// output a comment indicating when and how the output was generated +void PrintComment(const char* commentchar, int argc, char **argv) +{ + char datestr[80] = ""; + int i; + time_t now; + + time(&now); + Top_formattime(datestr, sizeof(datestr), now); + printf("%s generated on %s\n", commentchar, datestr); + printf("%s using:", commentchar); + for (i=0; iNodeDesc) { + fprintf(stderr, "Skipping FI (topology file line %"PRIu64"), no name\n", enodep->lineno); + ShowExpectedNodeBriefSummary(enodep, 4, 0); + bad_input++; + continue; + } + // be paranoid, this is probably not possible since we are checking + // ExpectedFIs list + if (enodep->NodeType != STL_NODE_FI) { + fprintf(stderr, "Skipping FI (topology file line %"PRIu64"), unspecified NodeType\n", enodep->lineno); + ShowExpectedNodeBriefSummary(enodep, 4, 0); + bad_input++; + continue; //unspecified type + } + + if (! CompareExpectedNodeFocus(enodep)) + continue; + input_checked++; + // put hosts in a list, if there are multi-rail hosts + // a given host will only be listed once + if (FSUCCESS != AddNameList(&host_list, enodep->NodeDesc, 0, node_name_mode, g_prefix, g_suffix)) { + // unexpected error + continue; + } + } + // CompactNameList(&host_list); // FastFabric does not support ranges + + for (q=cl_qmap_head(&host_list); q != cl_qmap_end(&host_list); q = cl_qmap_next(q)) { + NameData_t *namep = PARENT_STRUCT(q, NameData_t, NameListEntry); + if (0 == strncmp(myhostname, namep->name, NODE_DESCRIPTION_ARRAY_SIZE)) + printf("#"); // comment out our host + PrintName(namep); + printf("\n"); + } + FreeNameList(&host_list); + fprintf(stderr, "%u of %u Input FIs Shown, %u Bad Input Skipped\n", + input_checked, QListCount(&g_Fabric.ExpectedFIs), bad_input); + + return; +} + +// Output SLURM topology file fake ISL single list of the form: +// SwitchName=fake Switches=abc,def,ghi +// This output form allows for faster SLURM operation by assuming that once +// scheduling gets outside a single edge switch, its roughly equivalent latency +// This also supports impure tree and other topologies +void ShowSlurmFakeISLs(name_mode_t switch_name_mode) +{ + LIST_ITEM *p; + ExpectedNode fake = { + NodeType: STL_NODE_SW, + NodeDesc: "fake", + NodeGUID: 0x00066A0102FFFFFF + }; + + // build list of neighbors for "fake" core switch listing all switches + // which have unfiltered FIs + for (p=QListHead(&g_Fabric.ExpectedSWs); p != NULL; p = QListNext(&g_Fabric.ExpectedSWs, p)) { + ExpectedNode *enodep = (ExpectedNode *)QListObj(p); + cl_qmap_t *neigh_list; + + if (! enodep->context) // switch has no neighbors + continue; + neigh_list = GetSwitchFiNeighNameList(enodep); + if (cl_qmap_head(neigh_list) == cl_qmap_end(neigh_list)) + continue; // switch has no FI neighbors + (void)AddSwitchSwNameList(&fake, enodep->NodeDesc, enodep->NodeGUID, switch_name_mode, NULL, NULL); + } + + if (! fake.context) + return; // there are no switches with FIs + + printf("# Fake Switch to Switch Connectivity\n"); + { + ExpectedNode *enodep = &fake; + int first=1; + cl_qmap_t *neigh_list; + cl_map_item_t *np; + + neigh_list = GetSwitchSwNeighNameList(enodep); + // if using GUIDs for names, simply skip compact and will + // get no ranges in output + if (switch_name_mode != NAME_MODE_GUID) + CompactNameList(neigh_list); + for (np=cl_qmap_head(neigh_list); np != cl_qmap_end(neigh_list); np = cl_qmap_next(np)) { + NameData_t *namep = PARENT_STRUCT(np, NameData_t, NameListEntry); + if (first) { + NameData_t nameData = { }; + printf("SwitchName="); + CopyName(&nameData, enodep->NodeDesc, enodep->NodeGUID, switch_name_mode, NULL, NULL); + PrintName(&nameData); + printf(" Switches="); + first=0; + } else { + printf(","); + } + PrintName(namep); + } + if (! first) + printf("\n"); + } + FreeSwitchLists(&fake); + + return; +} + +// Output SLURM topology file ISL lists for each switch of the form: +// SwitchName=xyz Switches=abc,def,ghi +void ShowSlurmISLs(name_mode_t switch_name_mode) +{ + LIST_ITEM *p; + + printf("# Switch to Switch Connectivity\n"); + for (p=QListHead(&g_Fabric.ExpectedSWs); p != NULL; p = QListNext(&g_Fabric.ExpectedSWs, p)) { + ExpectedNode *enodep = (ExpectedNode *)QListObj(p); + cl_qmap_t *neigh_list; + int first=1; + cl_map_item_t *np; + + if (! enodep->context) // switch has no neighbors + continue; + neigh_list = GetSwitchSwNeighNameList(enodep); + // if using GUIDs for names, simply skip compact and will + // get no ranges in output + if (switch_name_mode != NAME_MODE_GUID) + CompactNameList(neigh_list); + for (np=cl_qmap_head(neigh_list); np != cl_qmap_end(neigh_list); np = cl_qmap_next(np)) { + NameData_t *namep = PARENT_STRUCT(np, NameData_t, NameListEntry); + if (first) { + NameData_t nameData = { }; + printf("SwitchName="); + CopyName(&nameData, enodep->NodeDesc, enodep->NodeGUID, switch_name_mode, NULL, NULL); + PrintName(&nameData); + printf(" Switches="); + first=0; + } else { + printf(","); + } + PrintName(namep); + } + if (! first) + printf("\n"); + } + + return; +} + +// Output SLURM topology file FI lists for each switch of the form: +// SwitchName=xyz Nodes=abc,def,ghi +void ShowSlurmNodes(name_mode_t switch_name_mode, name_mode_t node_name_mode) +{ + LIST_ITEM *p; + + printf("# Switch to FI Connectivity\n"); + for (p=QListHead(&g_Fabric.ExpectedSWs); p != NULL; p = QListNext(&g_Fabric.ExpectedSWs, p)) { + ExpectedNode *enodep = (ExpectedNode *)QListObj(p); + cl_qmap_t *neigh_list; + int first=1; + cl_map_item_t *np; + + if (! enodep->context) // switch has no FI neighbors + continue; + neigh_list = GetSwitchFiNeighNameList(enodep); + // if using GUIDs for names, simply skip compact and will + // get no ranges in output + if (node_name_mode != NAME_MODE_GUID) + CompactNameList(neigh_list); + for (np=cl_qmap_head(neigh_list); np != cl_qmap_end(neigh_list); np = cl_qmap_next(np)) { + NameData_t *namep = PARENT_STRUCT(np, NameData_t, NameListEntry); + if (first) { + NameData_t nameData = { }; + printf("SwitchName="); + CopyName(&nameData, enodep->NodeDesc, enodep->NodeGUID, switch_name_mode, NULL, NULL); + PrintName(&nameData); + printf(" Nodes="); + first=0; + } else { + printf(","); + } + PrintName(namep); + } + if (! first) + printf("\n"); + } + return; +} + +// command line options, each has a short and long flag name +struct option options[] = { + { "verbose", no_argument, NULL, 'v' }, + { "quiet", no_argument, NULL, 'q' }, + { "output", required_argument, NULL, 'o' }, + { "guid", no_argument, NULL, 'g' }, + { "underscore", no_argument, NULL, 'u' }, + { "trunc", no_argument, NULL, 't' }, + { "prefix", required_argument, NULL, 'p' }, + { "suffix", required_argument, NULL, 's' }, + { "strict", required_argument, NULL, 'S' }, + { "check", required_argument, NULL, 'C' }, + { "focus", no_argument, NULL, 'F' }, + { "help", no_argument, NULL, '$' }, // use an invalid option character + + { 0 } +}; + +void Usage_full(void) +{ + fprintf(stderr, "Usage: opa2rm [-v] [-q] -o output [-g|-u|-t] [-F point]\n" + " [-p prefix] [-s suffix] topology_input\n"); + fprintf(stderr, " or\n"); + fprintf(stderr, " opa2rm --help\n"); + fprintf(stderr, " --help - produce full help text\n"); + fprintf(stderr, " -v/--verbose - verbose output\n"); + fprintf(stderr, " -q/--quiet - disable progress reports\n"); + fprintf(stderr, " -o/--output output - output type\n"); + fprintf(stderr, " slurm - SLURM tree nodes\n"); + fprintf(stderr, " Supports variety of topologies\n"); + fprintf(stderr, " slurmfull - SLURM fat tree nodes and ISLs\n"); + fprintf(stderr, " Only supports pure trees\n"); + fprintf(stderr, " hosts - fastfabric hosts file\n"); + fprintf(stderr, " omitting this host\n"); + fprintf(stderr, " -g/--guid - output switch GUIDs instead of names\n"); + fprintf(stderr, " -u/--underscore - change spaces in switch names to underscores\n"); + fprintf(stderr, " -t/--trunc - merely truncate switch names at 1st space\n"); + fprintf(stderr, " This will treat large director switches as a\n"); + fprintf(stderr, " single big switch.\n"); + fprintf(stderr, " If none of -g, -u nor -t are specified\n"); + fprintf(stderr, " switch name suffixes after the first space\n"); + fprintf(stderr, " will be placed at the start of the name.\n"); + fprintf(stderr, " So 'core5 Leaf 101' becomes 'Leaf101_core5'\n"); + fprintf(stderr, " -p/--prefix prefix - prefix to prepend to all FI hostnames\n"); + fprintf(stderr, " -s/--suffix suffix - suffix to append to all FI hostnames\n"); + fprintf(stderr, " -F/--focus point - focus area for output\n"); + fprintf(stderr, " Limits scope of output to links\n"); + fprintf(stderr, " which match any of the given focus points.\n"); + fprintf(stderr, " May be specified up to %d times\n", MAX_FOCUS); + fprintf(stderr, " -C/--check - perform more topology file validation.\n"); + fprintf(stderr, " Requires all links resolve against nodes,\n"); + fprintf(stderr, " all nodes connected to same fabric and\n"); + fprintf(stderr, " treats any resolution errors as fatal.\n"); + fprintf(stderr, " -S/--strict - perform strict topology file validation.\n"); + fprintf(stderr, " Performs all checks in -C, and\n");; + fprintf(stderr, " requires all nodes list PortNum and\n"); + fprintf(stderr, " all nodes list ports used.\n"); + fprintf(stderr, " topology_input - topology_input file to use\n"); + fprintf(stderr, " '-' may be used to specify stdin\n"); +// list only subset of formats applicable to ExpectedLink and useful here +// omit gid, portguid, nodeguid + fprintf(stderr, "Point Syntax:\n"); + fprintf(stderr, " node:value - value is node description (node name)\n"); + fprintf(stderr, " node:value1:port:value2 - value1 is node description (node name)\n"); + fprintf(stderr, " value2 is port #\n"); + fprintf(stderr, " nodepat:value - value is glob pattern for node description (node\n"); + fprintf(stderr, " name)\n"); + fprintf(stderr, " nodepat:value1:port:value2 - value1 is glob pattern for node description\n"); + fprintf(stderr, " (node name), value2 is port #\n"); + fprintf(stderr, " nodetype:value - value is node type (SW or FI)\n"); + fprintf(stderr, " nodetype:value1:port:value2\n"); + fprintf(stderr, " - value1 is node type (SW or FI)\n"); + fprintf(stderr, " value2 is port #\n"); + fprintf(stderr, " rate:value - value is string for rate (25g, 50g, 75g, 100g)\n"); + fprintf(stderr, " omits switch mgmt port 0\n"); + fprintf(stderr, " mtucap:value - value is MTU size (2048, 4096, 8192, 10240)\n"); + fprintf(stderr, " omits switch mgmt port 0\n"); + fprintf(stderr, " labelpat:value - value is glob pattern for cable label\n"); + fprintf(stderr, " lengthpat:value - value is glob pattern for cable length\n"); + fprintf(stderr, " cabledetpat:value - value is glob pattern for cable details\n"); + fprintf(stderr, " linkdetpat:value - value is glob pattern for link details\n"); + fprintf(stderr, " portdetpat:value - value is glob pattern for port details\n"); + fprintf(stderr, " to value\n"); + fprintf(stderr, "Examples:\n"); + fprintf(stderr, " opa2rm -o slurm topology.xml\n"); + fprintf(stderr, " opa2rm -o slurm -p 'opa-' topology.xml\n"); + fprintf(stderr, " opa2rm -o slurm -s '-opa' topology.xml\n"); + fprintf(stderr, " opa2rm -o slurm -F 'nodepat:compute*' -F 'nodepat:opacore1 *' topology.xml\n"); + fprintf(stderr, " opa2rm -o hosts -F 'nodedetpat:compute*' topology.xml\n"); + fprintf(stderr, " opa2rm -o hosts topology.xml\n"); + exit(0); +} + +void Usage(void) +{ + fprintf(stderr, "Usage: opa2rm [-v] [-q] -o output [-g|-u|-t] topology_input\n"); + fprintf(stderr, " or\n"); + fprintf(stderr, " opa2rm --help\n"); + fprintf(stderr, " --help - produce full help text\n"); + fprintf(stderr, " -v/--verbose - verbose output\n"); + fprintf(stderr, " -q/--quiet - disable progress reports\n"); + fprintf(stderr, " -o/--output output - output type\n"); + fprintf(stderr, " slurm - SLURM tree nodes\n"); + fprintf(stderr, " Supports variety of topologies\n"); + fprintf(stderr, " slurmfull - SLURM fat tree nodes and ISLs\n"); + fprintf(stderr, " Only supports pure trees\n"); + fprintf(stderr, " hosts - fastfabric hosts file\n"); + fprintf(stderr, " omitting this host\n"); + fprintf(stderr, " -g/--guid - output switch GUIDs instead of names\n"); + fprintf(stderr, " -u/--underscore - instead of flipping any switch name suffix to\n"); + fprintf(stderr, " start, merely change spaces to underscore\n"); + fprintf(stderr, " -t/--trunc - instead of flipping any switch name suffix to\n"); + fprintf(stderr, " start, merely truncate at 1st space\n"); + fprintf(stderr, " topology_input - topology_input file to use\n"); + fprintf(stderr, " '-' may be used to specify stdin\n"); + exit(2); +} + +typedef enum { // bitmask indicating selected reports + REPORT_NONE =0x0, + REPORT_SLURM =0x1, + REPORT_SLURMFULL =0x2, + REPORT_HOSTS =0x4, +} report_t; + + +// convert a output type argument to the proper constant +report_t checkOutputType(const char* name) +{ + if (0 == strcmp(optarg, "slurm")) { + return REPORT_SLURM; + } else if (0 == strcmp(optarg, "slurmfull")) { + return (REPORT_SLURMFULL); + } else if (0 == strcmp(optarg, "hosts")) { + return (REPORT_HOSTS); + } else { + fprintf(stderr, "opa2rm: Invalid Output Type: %s\n", name); + Usage(); + // NOTREACHED + return REPORT_NONE; + } +} + +int main(int argc, char ** argv) +{ + int c; + report_t report = REPORT_NONE; + int i; + name_mode_t switch_name_mode = NAME_MODE_FLIP; + name_mode_t node_name_mode = NAME_MODE_TRUNC; + char* topology_in_file = NULL; // input file being parsed + int exitstatus = 0; + TopoVal_t validation = TOPOVAL_NONE; + + Top_setcmdname("opa2rm"); + g_quiet = ! isatty(2); // disable progress if stderr is not tty + + // process command line arguments + while (-1 != (c = getopt_long(argc,argv, "vqo:gutp:s:F:SC", + options, &i))) + { + switch (c) + { + case '$': + Usage_full(); + break; + case 'v': + g_verbose++; + break; + case 'q': + g_quiet = 1; + break; + case 'o': + report = (report_t) report | checkOutputType(optarg); + break; + case 'g': + switch_name_mode = NAME_MODE_GUID; + break; + case 'u': + switch_name_mode = NAME_MODE_UNDERSCORE; + break; + case 't': + switch_name_mode = NAME_MODE_TRUNC; + break; + case 'p': + g_prefix = optarg; + break; + case 's': + g_suffix = optarg; + break; + case 'F': // focus for report + if (g_num_focus >= MAX_FOCUS) { + fprintf(stderr, "opa2rm: -F option may only be specified %d times\n", MAX_FOCUS); + Usage(); + } + PointInit(&g_focus[g_num_focus]); + g_focus_arg[g_num_focus++] = optarg; + break; + case 'S': + validation = TOPOVAL_STRICT; + break; + case 'C': + validation = TOPOVAL_SOMEWHAT_STRICT; + break; + default: + fprintf(stderr, "opa2rm: Invalid option -%c\n", c); + Usage(); + break; + } + } /* end while */ + // Name algorithms just check for NULL, so convert empty strings to NULL + if (g_suffix && 0 == strlen(g_suffix)) + g_suffix = NULL; + if (g_prefix && 0 == strlen(g_prefix)) + g_prefix = NULL; + // slurm report generation requires cross referenced elinkp and enodep + if (validation < TOPOVAL_LOOSE + && (report & (REPORT_SLURM|REPORT_SLURMFULL))) + validation = TOPOVAL_LOOSE; + + if (optind < argc) { + topology_in_file = argv[optind++]; + if (!topology_in_file){ + fprintf(stderr, "opa2rm: Error: null input filename\n"); + exitstatus = 1; + goto done; + } + } else { + fprintf(stderr, "opa2rm: Missing topology_input argument\n"); + Usage(); + } + if (optind < argc) + { + fprintf(stderr, "opa2rm: Unexpected extra arguments\n"); + Usage(); + } + if (report == REPORT_NONE) + { + fprintf(stderr, "opa2rm: '-o output' option must be specified\n"); + Usage(); + } + + if (FSUCCESS != InitFabricData(&g_Fabric, FF_NONE)) { + fprintf(stderr, "opa2rm: Unable to initialize fabric storage area\n"); + exitstatus = 1; + goto done; + } + + // parse topology input file + if (FSUCCESS != Xml2ParseTopology(topology_in_file, g_quiet, &g_Fabric, + validation)) { + exitstatus = 1; + goto done; + } + if (g_verbose > 3) + Xml2PrintTopology(stderr, &g_Fabric); // for debug + if (! (g_Fabric.flags & FF_EXPECTED_NODES)) { + printf("opa2rm: Incomplete topology file: no Nodes information provided\n"); + exitstatus = 1; + goto done; + } + if (! (g_Fabric.flags & (FF_EXPECTED_LINKS|FF_EXPECTED_EXTLINKS))) { + printf("opa2rm: Incomplete topology file: no LinkSummary nor ExternalLinkSummary information provided\n"); + exitstatus = 1; + goto done; + } + + for (i=0; i < g_num_focus; i++) { + char *p; + FSTATUS status; + uint8 find_flag = + ((report & (REPORT_SLURM|REPORT_SLURMFULL))?FIND_FLAG_ELINK:0) + | ((report & (REPORT_HOSTS))?FIND_FLAG_ENODE:0); + status = ParseFocusPoint(0, &g_Fabric, g_focus_arg[i], &g_focus[i], + find_flag, &p, TRUE); + if (FINVALID_PARAMETER == status || *p != '\0') { + fprintf(stderr, "opa2rm: Invalid Point Syntax: '%s'\n", g_focus_arg[i]); + fprintf(stderr, "opa2rm: %*s^\n", (int)(p-g_focus_arg[i]), ""); + Usage_full(); + } + if (FSUCCESS != status) { + fprintf(stderr, "opa2rm: Unable to resolve Point: '%s': %s\n", g_focus_arg[i], iba_fstatus_msg(status)); + exitstatus = 1; + goto done; + } + } + + if (g_verbose > 1 ) { + ShowExpectedLinksReport(0, g_verbose); + ShowExpectedNodesReport(STL_NODE_FI, 0, g_verbose); + ShowExpectedNodesReport(STL_NODE_SW, 0, g_verbose); + } + + if (report & REPORT_HOSTS) { + PrintComment("#", argc, argv); + ShowFastFabricHosts(node_name_mode); + } + + if (report & (REPORT_SLURM|REPORT_SLURMFULL)) { + BuildAllSwitchLists(switch_name_mode, node_name_mode, + 0 != (report&REPORT_SLURMFULL), 1); + PrintComment("#", argc, argv); + ShowSlurmNodes(switch_name_mode, node_name_mode); + if (report & REPORT_SLURM) { + printf("\n"); + ShowSlurmFakeISLs(switch_name_mode); + } + if (report & REPORT_SLURMFULL) { + printf("\n"); + ShowSlurmISLs(switch_name_mode); + } + FreeAllSwitchNamelists(); + } + + DestroyFabricData(&g_Fabric); +done: + + for (i=0; i < g_num_focus; i++) + PointDestroy(&g_focus[i]); + + if (exitstatus == 2) + Usage(); + + return exitstatus; +} diff --git a/IbaTools/opacabletest/Makefile b/IbaTools/opacabletest/Makefile new file mode 100644 index 0000000..7f492e3 --- /dev/null +++ b/IbaTools/opacabletest/Makefile @@ -0,0 +1,153 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** +# Makefile for opacabletest + +# Include Make Control Settings +include $(TL_DIR)/$(PROJ_FILE_DIR)/Makesettings.project + +#=============================================================================# +# Definitions: +#-----------------------------------------------------------------------------# + +# Name of SubProjects +DS_SUBPROJECTS = +# name of executable or downloadable image +EXECUTABLE = #$(BUILDDIR)/opacabletest$(EXE_SUFFIX) +# list of sub directories to build +DIRS = +# C files (.c) +CFILES = \ + # Add more c files here +# C++ files (.cpp) +CCFILES = \ + # Add more cpp files here +# lex files (.lex) +LFILES = \ + # Add more lex files here +# archive library files (basename, $ARFILES will add MOD_LIB_DIR/prefix and suffix) +LIBFILES= +# Windows Resource Files (.rc) +RSCFILES = +# Windows IDL File (.idl) +IDLFILE = +# Windows Linker Module Definitions (.def) file for dll's +DEFFILE = +# targets to build during INCLUDES phase (add public includes here) +INCLUDE_TARGETS = \ + # Add more h hpp files here + +# Non-compiled files +MISC_FILES = + +# all source files +SOURCES = $(CFILES) $(CCFILES) $(LFILES) $(RSCFILES) $(IDLFILE) +# Source files to include in DSP File +DSP_SOURCES = $(INCLUDE_TARGETS) $(SOURCES) $(MISC_FILES) \ + $(RSCFILES) $(DEFFILE) $(MAKEFILE) +# all object files +OBJECTS = $(CFILES:.c=$(OBJ_SUFFIX)) $(CCFILES:.cpp=$(OBJ_SUFFIX)) \ + $(LFILES:.lex=$(OBJ_SUFFIX)) +RSCOBJECTS = $(RSCFILES:.rc=$(RES_SUFFIX)) +# targets to build during LIBS phase +LIB_TARGETS_IMPLIB = +LIB_TARGETS_ARLIB = # $(LIB_PREFIX)ResourceTest$(ARLIB_SUFFIX) +LIB_TARGETS_EXP = $(LIB_TARGETS_IMPLIB:$(ARLIB_SUFFIX)=$(EXP_SUFFIX)) +LIB_TARGETS_MISC = +# targets to build during CMDS phase +CMD_TARGETS_SHLIB = +CMD_TARGETS_EXE = $(EXECUTABLE) +CMD_TARGETS_MISC = opacabletest +# files to remove during clean phase +CLEAN_TARGETS_MISC = +CLEAN_TARGETS = $(OBJECTS) $(RSCOBJECTS) $(IDL_TARGETS) $(CLEAN_TARGETS_MISC) +# other files to remove during clobber phase +CLOBBER_TARGETS_MISC= +# sub-directory to install to within bin +BIN_SUBDIR = +# sub-directory to install to within include +INCLUDE_SUBDIR = + +# Additional Settings +#CLOCALDEBUG = User defined C debugging compilation flags [Empty] +#CCLOCALDEBUG = User defined C++ debugging compilation flags [Empty] +#CLOCAL = User defined C flags for compiling [Empty] +#CCLOCAL = User defined C++ flags for compiling [Empty] +#BSCLOCAL = User flags for Browse File Builder [Empty] +#DEPENDLOCAL = user defined makedepend flags [Empty] +#LINTLOCAL = User defined lint flags [Empty] +#LOCAL_INCLUDE_DIRS = User include directories to search for C/C++ headers [Empty] +#LDLOCAL = User defined C flags for linking [Empty] +#IMPLIBLOCAL = User flags for Object Lirary Manager [Empty] +#MIDLLOCAL = User flags for IDL compiler [Empty] +#RSCLOCAL = User flags for resource compiler [Empty] +#LOCALDEPLIBS = User libraries to include in dependencies [Empty] +#LOCALLIBS = User libraries to use when linking [Empty] +# (in addition to LOCALDEPLIBS) +#LOCAL_LIB_DIRS = User library directories for libpaths [Empty] + +CLOCAL = $(CPIE) +# Include Make Rules definitions and rules +include $(TL_DIR)/IbaTools/Makerules.module + +#=============================================================================# +# Overrides: +#-----------------------------------------------------------------------------# +#CCOPT = # C++ optimization flags, default lets build config decide +#COPT = # C optimization flags, default lets build config decide +#SUBSYSTEM = Subsystem to build for (none, console or windows) [none] +# (Windows Only) +#USEMFC = How Windows MFC should be used (none, static, shared, no_mfc) [none] +# (Windows Only) +#=============================================================================# + +#=============================================================================# +# Rules: +#-----------------------------------------------------------------------------# +# process Sub-directories +include $(TL_DIR)/Makerules/Maketargets.toplevel + +# build cmds and libs +include $(TL_DIR)/Makerules/Maketargets.build + +# install for includes, libs and cmds phases +include $(TL_DIR)/Makerules/Maketargets.install + +# install for stage phase +#include $(TL_DIR)/Makerules/Maketargets.stage +STAGE:: + $(VS)$(STAGE_INSTALL) $(STAGE_INSTALL_DIR_OPT) $(PROJ_STAGE_FASTFABRIC_DIR) opacabletest + +# Unit test execution +#include $(TL_DIR)/Makerules/Maketargets.runtest + +#=============================================================================# + +#=============================================================================# +# DO NOT DELETE THIS LINE -- make depend depends on it. +#=============================================================================# diff --git a/IbaTools/opacabletest/opacabletest.sh b/IbaTools/opacabletest/opacabletest.sh new file mode 100755 index 0000000..cce5f04 --- /dev/null +++ b/IbaTools/opacabletest/opacabletest.sh @@ -0,0 +1,293 @@ +#!/bin/bash +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] + +# start and stop HFI-SW and/or ISL cable Bit Error Rate tests + +# optional override of defaults +if [ -f /etc/opa/opafastfabric.conf ] +then + . /etc/opa/opafastfabric.conf +fi + +. /usr/lib/opa/tools/opafastfabric.conf.def + +. /usr/lib/opa/tools/ff_funcs + +tempfile="$(mktemp)" +trap "rm -f $tempfile; exit 1" SIGHUP SIGTERM SIGINT +trap "rm -f $tempfile" EXIT + +Usage_full() +{ + echo "Usage: opacabletest [-C|-A] [-c file] [-f hostfile] [-h 'hosts'] [-n numprocs]" >&2 + echo " [-t portsfile] [-p ports]" >&2 + echo " [start|start_fi|start_isl|stop|stop_fi|stop_isl] ..." >&2 + echo " or" >&2 + echo " opacabletest --help" >&2 + echo " --help - produce full help text" >&2 + echo " -C - clear error counters" >&2 + echo " -A - force clear of hw error counters" >&2 + echo " implies -C" >&2 + echo " -c file - error thresholds config file" >&2 + echo " default is $CONFIG_DIR/opa/opamon.si.conf" >&2 + echo " only used if -C or -A specified" >&2 + echo " -f hostfile - file with hosts to include in HFI-SW test," >&2 + echo " default is $CONFIG_DIR/opa/hosts" >&2 + echo " -h hosts - list of hosts to include in HFI-SW test" >&2 + echo " -n numprocs - number of processes per host for HFI-SW test" >&2 + echo " -t portsfile - file with list of local HFI ports used to access fabric(s)" >&2 + echo " when clearing counters, default is $CONFIG_DIR/opa/ports" >&2 + echo " -p ports - list of local HFI ports used to access fabric(s) for counter clear" >&2 + echo " default is 1st active port" >&2 + echo " This is specified as hfi:port" >&2 + echo " 0:0 = 1st active port in system" >&2 + echo " 0:y = port y within system" >&2 + echo " x:0 = 1st active port on HFI x" >&2 + echo " x:y = HFI x, port y" >&2 + echo " The first HFI in the system is 1. The first port on an HFI is 1." >&2 + echo " start - start the HFI-SW and ISL tests" >&2 + echo " start_fi - start the HFI-SW test" >&2 + echo " start_isl - start the ISL test" >&2 + echo " stop - stop the HFI-SW and ISL tests" >&2 + echo " stop_fi - stop the HFI-SW test" >&2 + echo " stop_isl - stop the ISL test" >&2 + echo >&2 + echo "The HFI-SW cabletest requires that FF_MPI_APPS_DIR be set and contains" >&2 + echo "a prebuilt copy of Intel mpi_apps for an appropriate MPI" >&2 + echo >&2 + echo "The ISL cabletest as started by this tool assumes the master HSM is running" >&2 + echo "on this host. If using ESM or a different host is master FM, ISL cabletest" >&2 + echo "will have to be controlled by the switch CLI or by FastFabric on the master FM" >&2 + echo "respectively" >&2 + echo >&2 + echo " Environment:" >&2 + echo " HOSTS - list of hosts, used if -h option not supplied" >&2 + echo " HOSTS_FILE - file containing list of hosts, used in absence of -f and -h" >&2 + echo " PORTS - list of ports, used in absence of -t and -p" >&2 + echo " PORTS_FILE - file containing list of ports, used in absence of -t and -p" >&2 + echo " FF_MAX_PARALLEL - maximum concurrent operations" >&2 + echo "example:">&2 + echo " opacabletest -A start" >&2 + echo " opacabletest -f good -A start" >&2 + echo " opacabletest -h 'arwen elrond' start_fi" >&2 + echo " HOSTS='arwen elrond' opacabletest stop" >&2 + echo " opacabletest -A" >&2 + rm -f $tempfile + exit 0 +} + +Usage() +{ + echo "Usage: opacabletest [-C|-A] [-n numprocs] [-f hostfile]" >&2 + echo " [start|start_fi|start_isl|stop|stop_fi|stop_isl] ..." >&2 + echo " or" >&2 + echo " opacabletest --help" >&2 + echo " --help - produce full help text" >&2 + echo " -C - clear error counters" >&2 + echo " -A - force clear of hw error counters" >&2 + echo " implies -C" >&2 + echo " -f hostfile - file with hosts to include in HFI-SW test," >&2 + echo " default is $CONFIG_DIR/opa/hosts" >&2 + echo " -n numprocs - number of processes per host for HFI-SW test" >&2 + echo >&2 + echo " start - start the HFI-SW and ISL tests" >&2 + echo " start_fi - start the HFI-SW test" >&2 + echo " start_isl - start the ISL test" >&2 + echo " stop - stop the HFI-SW and ISL tests" >&2 + echo " stop_fi - stop the HFI-SW test" >&2 + echo " stop_isl - stop the ISL test" >&2 + echo >&2 + echo "The HFI-SW cabletest requires that FF_MPI_APPS_DIR be set and contains" >&2 + echo "a prebuilt copy of Intel mpi_apps for an appropriate MPI" >&2 + echo >&2 + echo "The ISL cabletest as started by this tool assumes the master HSM is running" >&2 + echo "on this host. If using ESM or a different host is master FM, ISL cabletest" >&2 + echo "will have to be controlled by the switch CLI or by FastFabric on the master FM" >&2 + echo "respectively" >&2 + echo >&2 + echo " Environment:" >&2 + echo " FF_MAX_PARALLEL - maximum concurrent operations" >&2 + echo "example:">&2 + echo " opacabletest -f good -A start" >&2 + echo " opacabletest stop" >&2 + echo " opacabletest -A" >&2 + rm -f $tempfile + exit 2 +} + +if [ x"$1" = "x--help" ] +then + Usage_full +fi + +clear=n +clearhw=n +numprocs=3 +config_file="$CONFIG_DIR/opa/opamon.si.conf" +while getopts CAf:h:n:t:p:c: param +do + case $param in + C) + clear=y;; + A) + clear=y; clearhw=y;; + h) + HOSTS="$OPTARG";; + f) + HOSTS_FILE="$OPTARG";; + n) + numprocs="$OPTARG";; + t) + PORTS_FILE="$OPTARG";; + p) + PORTS="$OPTARG";; + c) + config_file="$OPTARG";; + ?) + Usage;; + esac +done +shift $((OPTIND -1)) + +check_host_args opacabletest +# HOSTS now lists all the hosts, pass it along to the commands below via env +export HOSTS +unset HOSTS_FILE + +if [ $clear = y ] +then + check_ports_args opacabletest + # PORTS now lists all the ports, pass it along to the commands below via env + export PORTS + unset PORTS_FILE +fi + +if [ $clear = y ] +then + opareports -C -c "$config_file" -o none + if [ $clearhw = y ] + then + opareports -M -C -c "$config_file" -o none + fi +fi + +get_fmconfig() +{ + FM_CONFIG_DIR=/etc + FM_CONFIG_FILE=$CONFIG_DIR/opafm.xml + IFS_FM_BASE=/usr/lib/opa-fm # default +} + +start_fi() +{ + if [ ! -e $FF_MPI_APPS_DIR/run_batch_cabletest ] + then + echo "opacabletest: Invalid FF_MPI_APPS_DIR: $FF_MPI_APPS_DIR" >&2 + exit 1 + fi + if [ ! -x $FF_MPI_APPS_DIR/groupstress/mpi_groupstress ] + then + echo "opacabletest: FF_MPI_APPS_DIR ($FF_MPI_APPS_DIR) not compiled" >&2 + rm -f $tempfile + exit 1 + fi + ff_var_to_stdout "$HOSTS" > $tempfile + cd $FF_MPI_APPS_DIR + MPI_HOSTS=$tempfile ./run_batch_cabletest -n $numprocs infinite +} + +start_isl() +{ + ( + get_fmconfig + if [ ! -x $IFS_FM_BASE/bin/fm_cmdall ] + then + echo "opacabletest: Error: $IFS_FM_BASE/bin/fm_cmdall not found" >&2 + rm -f $tempfile + exit 1 + fi + $IFS_FM_BASE/bin/fm_cmdall smLooptestFastModeStart + ) + res=$? + [ $res -ne 0 ] && exit $res +} + +start() +{ + start_fi + start_isl +} + +stop_fi() +{ + # we use patterns so the pkill doesn't kill this script or opacmdall itself + # use an echo at end so exit status is good + /usr/sbin/opacmdall -p -T 60 "pkill -9 -f '[m]pi_groupstress'; echo -n" +} + +stop_isl() +{ + ( + get_fmconfig + if [ ! -x $IFS_FM_BASE/bin/fm_cmdall ] + then + echo "opacabletest: Error: $IFS_FM_BASE/bin/fm_cmdall not found" >&2 + rm -f $tempfile + exit 1 + fi + $IFS_FM_BASE/bin/fm_cmdall smLooptestStop + ) + res=$? + [ $res -ne 0 ] && exit $res +} + +stop() +{ + stop_fi + stop_isl +} + +while [ $# -ne 0 ] +do + case "$1" in + start) start;; + start_fi) start_fi;; + start_isl) start_isl;; + stop) stop;; + stop_fi) stop_fi;; + stop_isl) stop_isl;; + *) Usage;; + esac + shift +done + +rm -f $tempfile diff --git a/IbaTools/opacheckload/Makefile b/IbaTools/opacheckload/Makefile new file mode 100644 index 0000000..3f9a758 --- /dev/null +++ b/IbaTools/opacheckload/Makefile @@ -0,0 +1,154 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** +# Makefile for opacheckload + +# Include Make Control Settings +include $(TL_DIR)/$(PROJ_FILE_DIR)/Makesettings.project + +#=============================================================================# +# Definitions: +#-----------------------------------------------------------------------------# + +# Name of SubProjects +DS_SUBPROJECTS = +# name of executable or downloadable image +EXECUTABLE = #$(BUILDDIR)/opacheckload$(EXE_SUFFIX) +# list of sub directories to build +DIRS = +# C files (.c) +CFILES = \ + # Add more c files here +# C++ files (.cpp) +CCFILES = \ + # Add more cpp files here +# lex files (.lex) +LFILES = \ + # Add more lex files here +# archive library files (basename, $ARFILES will add MOD_LIB_DIR/prefix and suffix) +LIBFILES= +# Windows Resource Files (.rc) +RSCFILES = +# Windows IDL File (.idl) +IDLFILE = +# Windows Linker Module Definitions (.def) file for dll's +DEFFILE = +# targets to build during INCLUDES phase (add public includes here) +INCLUDE_TARGETS = \ + # Add more h hpp files here + +# Non-compiled files +MISC_FILES = + +# all source files +SOURCES = $(CFILES) $(CCFILES) $(LFILES) $(RSCFILES) $(IDLFILE) +# Source files to include in DSP File +DSP_SOURCES = $(INCLUDE_TARGETS) $(SOURCES) $(MISC_FILES) \ + $(RSCFILES) $(DEFFILE) $(MAKEFILE) +# all object files +OBJECTS = $(CFILES:.c=$(OBJ_SUFFIX)) $(CCFILES:.cpp=$(OBJ_SUFFIX)) \ + $(LFILES:.lex=$(OBJ_SUFFIX)) +RSCOBJECTS = $(RSCFILES:.rc=$(RES_SUFFIX)) +# targets to build during LIBS phase +LIB_TARGETS_IMPLIB = +LIB_TARGETS_ARLIB = # $(LIB_PREFIX)ResourceTest$(ARLIB_SUFFIX) +LIB_TARGETS_EXP = $(LIB_TARGETS_IMPLIB:$(ARLIB_SUFFIX)=$(EXP_SUFFIX)) +LIB_TARGETS_MISC = +# targets to build during CMDS phase +CMD_TARGETS_SHLIB = +CMD_TARGETS_EXE = $(EXECUTABLE) +CMD_TARGETS_MISC = opacheckload +# files to remove during clean phase +CLEAN_TARGETS_MISC = +CLEAN_TARGETS = $(OBJECTS) $(RSCOBJECTS) $(IDL_TARGETS) $(CLEAN_TARGETS_MISC) +# other files to remove during clobber phase +CLOBBER_TARGETS_MISC= +# sub-directory to install to within bin +BIN_SUBDIR = +# sub-directory to install to within include +INCLUDE_SUBDIR = + +# Additional Settings +#CLOCALDEBUG = User defined C debugging compilation flags [Empty] +#CCLOCALDEBUG = User defined C++ debugging compilation flags [Empty] +#CLOCAL = User defined C flags for compiling [Empty] +#CCLOCAL = User defined C++ flags for compiling [Empty] +#BSCLOCAL = User flags for Browse File Builder [Empty] +#DEPENDLOCAL = user defined makedepend flags [Empty] +#LINTLOCAL = User defined lint flags [Empty] +#LOCAL_INCLUDE_DIRS = User include directories to search for C/C++ headers [Empty] +#LDLOCAL = User defined C flags for linking [Empty] +#IMPLIBLOCAL = User flags for Object Lirary Manager [Empty] +#MIDLLOCAL = User flags for IDL compiler [Empty] +#RSCLOCAL = User flags for resource compiler [Empty] +#LOCALDEPLIBS = User libraries to include in dependencies [Empty] +#LOCALLIBS = User libraries to use when linking [Empty] +# (in addition to LOCALDEPLIBS) +#LOCAL_LIB_DIRS = User library directories for libpaths [Empty] + +CLOCAL = $(CPIE) + +# Include Make Rules definitions and rules +include $(TL_DIR)/IbaTools/Makerules.module + +#=============================================================================# +# Overrides: +#-----------------------------------------------------------------------------# +#CCOPT = # C++ optimization flags, default lets build config decide +#COPT = # C optimization flags, default lets build config decide +#SUBSYSTEM = Subsystem to build for (none, console or windows) [none] +# (Windows Only) +#USEMFC = How Windows MFC should be used (none, static, shared, no_mfc) [none] +# (Windows Only) +#=============================================================================# + +#=============================================================================# +# Rules: +#-----------------------------------------------------------------------------# +# process Sub-directories +include $(TL_DIR)/Makerules/Maketargets.toplevel + +# build cmds and libs +include $(TL_DIR)/Makerules/Maketargets.build + +# install for includes, libs and cmds phases +include $(TL_DIR)/Makerules/Maketargets.install + +# install for stage phase +#include $(TL_DIR)/Makerules/Maketargets.stage +STAGE:: + $(VS)$(STAGE_INSTALL) $(STAGE_INSTALL_DIR_OPT) $(PROJ_STAGE_FASTFABRIC_DIR) opacheckload + +# Unit test execution +#include $(TL_DIR)/Makerules/Maketargets.runtest + +#=============================================================================# + +#=============================================================================# +# DO NOT DELETE THIS LINE -- make depend depends on it. +#=============================================================================# diff --git a/IbaTools/opacheckload/opacheckload.sh b/IbaTools/opacheckload/opacheckload.sh new file mode 100755 index 0000000..cb0a706 --- /dev/null +++ b/IbaTools/opacheckload/opacheckload.sh @@ -0,0 +1,160 @@ +#!/bin/bash +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] + +# get loadavg on all hosts and show busiest or least busy hosts +# This can be used to make sure hosts are idle before starting a MPI benchmark +# or to see if a benchmark is running + +# optional override of defaults +if [ -f /etc/opa/opafastfabric.conf ] +then + . /etc/opa/opafastfabric.conf +fi + +. /usr/lib/opa/tools/opafastfabric.conf.def + +. /usr/lib/opa/tools/ff_funcs + +trap "exit 1" SIGHUP SIGTERM SIGINT + +Usage_full() +{ + echo "Usage: opacheckload [-f hostfile] [-h 'hosts'] [-r] [-a|-n numprocs]" >&2 + echo " [-d uploaddir]" >&2 + echo " or" >&2 + echo " opacheckload --help" >&2 + echo " --help - produce full help text" >&2 + echo " -f hostfile - file with hosts to check," >&2 + echo " default is $CONFIG_DIR/opa/hosts" >&2 + echo " -h hosts - list of hosts to check" >&2 + echo " -r - reverse output, show least busy hosts, default is busiest hosts" >&2 + echo " -n numprocs - show top numprocs hosts, default 10" >&2 + echo " -a - show all hosts, default 10" >&2 + echo " -d upload_dir - directory to upload loadavg to, default is uploads" >&2 + echo >&2 + echo " Environment:" >&2 + echo " HOSTS - list of hosts, used if -h option not supplied" >&2 + echo " HOSTS_FILE - file containing list of hosts, used in absence of -f and -h" >&2 + echo " UPLOADS_DIR - directory to upload loadavg to, used in absence of -d" >&2 + echo " FF_MAX_PARALLEL - maximum concurrent operations" >&2 + echo "example:">&2 + echo " opacheckload" >&2 + echo " opacheckload -h 'arwen elrond'" >&2 + echo " HOSTS='arwen elrond' opacheckload" >&2 + exit 0 +} + +Usage() +{ + echo "Usage: opacheckload [-f hostfile] [-r] [-a|-n numprocs]" >&2 + echo " or" >&2 + echo " opacheckload --help" >&2 + echo " --help - produce full help text" >&2 + echo " -f hostfile - file with hosts to check," >&2 + echo " default is $CONFIG_DIR/opa/hosts" >&2 + echo " -r - reverse output, show least busy hosts, default is busiest hosts" >&2 + echo " -n numprocs - show top numprocs hosts, default 10" >&2 + echo " -a - show all hosts, default 10" >&2 + echo " -H - supress headers for script parsing" >&2 + echo >&2 + echo " Environment:" >&2 + echo " FF_MAX_PARALLEL - maximum concurrent operations" >&2 + echo "example:">&2 + echo " opacheckload" >&2 + echo " opacheckload -f good" >&2 + exit 2 +} + +if [ x"$1" = "x--help" ] +then + Usage_full +fi + +numprocs=10 +ropt=-r +while getopts f:h:n:d:aHr param +do + case $param in + h) + HOSTS="$OPTARG";; + H) + skip_headers=1;; + f) + HOSTS_FILE="$OPTARG";; + n) + numprocs="$OPTARG";; + d) + UPLOADS_DIR="$OPTARG";; + a) + numprocs="1000000";; # more than ever expected to be found + r) + ropt="";; # sort from lowest to highest, shows least busy + ?) + Usage;; + esac +done +shift $((OPTIND -1)) + +if [ $# -ne 0 ] +then + echo "opacheckload: extra arguments: $@" >&2 + Usage +fi + +check_host_args opacheckload +# HOSTS now lists all the hosts, pass it along to the commands below via env +export HOSTS +unset HOSTS_FILE + +# remove any stale data so we don't mistakenly report it below +for j in $HOSTS +do + rm -f $UPLOADS_DIR/$j/loadavg +done + +opacmdall -p 'cat /proc/loadavg > /tmp/loadavg' >/dev/null +opauploadall -p /tmp/loadavg loadavg >/dev/null +if [ -z $skip_headers ]; then + echo "loadavg host" +fi + +for j in $HOSTS +do + i=$UPLOADS_DIR/$j/loadavg + if [ ! -e $i ] + then + echo "opacheckload: $j: Unable to get loadavg" >&2 + else + l=`cat $i` + echo "$l $j" + fi +done | sort -n $ropt|head -n $numprocs diff --git a/IbaTools/opaeaquery/opaeaquery.c b/IbaTools/opaeaquery/opaeaquery.c new file mode 100644 index 0000000..d7dcf16 --- /dev/null +++ b/IbaTools/opaeaquery/opaeaquery.c @@ -0,0 +1,42 @@ +/* BEGIN_ICS_COPYRIGHT7 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT7 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + + +#include +#include +#include + +int main(int argc, char ** argv) +{ + printf("Stub\n"); + return 0; +} + diff --git a/IbaTools/opaemaquery/ema.c b/IbaTools/opaemaquery/ema.c new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/IbaTools/opaemaquery/ema.c diff --git a/IbaTools/opaemaquery/epa.c b/IbaTools/opaemaquery/epa.c new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/IbaTools/opaemaquery/epa.c diff --git a/IbaTools/opaemaquery/opaemaquery.c b/IbaTools/opaemaquery/opaemaquery.c new file mode 100644 index 0000000..c10168a --- /dev/null +++ b/IbaTools/opaemaquery/opaemaquery.c @@ -0,0 +1,14 @@ + +#include +#include +#include +#include +#include +#include + +int main(int argc, char ** argv) +{ + printf("Stub\n"); + return 0; +} + diff --git a/IbaTools/opaemaquery/opaemaquery.h b/IbaTools/opaemaquery/opaemaquery.h new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/IbaTools/opaemaquery/opaemaquery.h diff --git a/IbaTools/opafindgood/Makefile b/IbaTools/opafindgood/Makefile new file mode 100644 index 0000000..4aea25f --- /dev/null +++ b/IbaTools/opafindgood/Makefile @@ -0,0 +1,158 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** +# Makefile for opafindgood + +# Include Make Control Settings +include $(TL_DIR)/$(PROJ_FILE_DIR)/Makesettings.project + +#=============================================================================# +# Definitions: +#-----------------------------------------------------------------------------# + +# Name of SubProjects +DS_SUBPROJECTS = +# name of executable or downloadable image +EXECUTABLE = #$(BUILDDIR)/opafindgood$(EXE_SUFFIX) +# list of sub directories to build +DIRS = +# C files (.c) +CFILES = \ + # Add more c files here +# C++ files (.cpp) +CCFILES = \ + # Add more cpp files here +# lex files (.lex) +LFILES = \ + # Add more lex files here +# archive library files (basename, $ARFILES will add MOD_LIB_DIR/prefix and suffix) +LIBFILES= +# Windows Resource Files (.rc) +RSCFILES = +# Windows IDL File (.idl) +IDLFILE = +# Windows Linker Module Definitions (.def) file for dll's +DEFFILE = +# targets to build during INCLUDES phase (add public includes here) +INCLUDE_TARGETS = \ + # Add more h hpp files here + +# Non-compiled files +MISC_FILES = +TCL_SOURCES = comm12.tcl +# all source files +SOURCES = $(CFILES) $(CCFILES) $(LFILES) $(RSCFILES) $(IDLFILE) +# Source files to include in DSP File +DSP_SOURCES = $(INCLUDE_TARGETS) $(SOURCES) $(MISC_FILES) \ + $(RSCFILES) $(DEFFILE) $(MAKEFILE) $(TCL_SOURCES) +# all object files +OBJECTS = $(CFILES:.c=$(OBJ_SUFFIX)) $(CCFILES:.cpp=$(OBJ_SUFFIX)) \ + $(LFILES:.lex=$(OBJ_SUFFIX)) +RSCOBJECTS = $(RSCFILES:.rc=$(RES_SUFFIX)) +# targets to build during LIBS phase +LIB_TARGETS_IMPLIB = +LIB_TARGETS_ARLIB = # $(LIB_PREFIX)ResourceTest$(ARLIB_SUFFIX) +LIB_TARGETS_EXP = $(LIB_TARGETS_IMPLIB:$(ARLIB_SUFFIX)=$(EXP_SUFFIX)) +LIB_TARGETS_MISC = +# targets to build during CMDS phase +CMD_TARGETS_SHLIB = +CMD_TARGETS_EXE = $(EXECUTABLE) +CMD_TARGETS_MISC = opafindgood opasorthosts comm12 +# files to remove during clean phase +CLEAN_TARGETS_MISC = +CLEAN_TARGETS = $(OBJECTS) $(RSCOBJECTS) $(IDL_TARGETS) $(CLEAN_TARGETS_MISC) +# other files to remove during clobber phase +CLOBBER_TARGETS_MISC= +# sub-directory to install to within bin +BIN_SUBDIR = +# sub-directory to install to within include +INCLUDE_SUBDIR = + +# Additional Settings +#CLOCALDEBUG = User defined C debugging compilation flags [Empty] +#CCLOCALDEBUG = User defined C++ debugging compilation flags [Empty] +#CLOCAL = User defined C flags for compiling [Empty] +#CCLOCAL = User defined C++ flags for compiling [Empty] +#BSCLOCAL = User flags for Browse File Builder [Empty] +#DEPENDLOCAL = user defined makedepend flags [Empty] +#LINTLOCAL = User defined lint flags [Empty] +#LOCAL_INCLUDE_DIRS = User include directories to search for C/C++ headers [Empty] +#LDLOCAL = User defined C flags for linking [Empty] +#IMPLIBLOCAL = User flags for Object Lirary Manager [Empty] +#MIDLLOCAL = User flags for IDL compiler [Empty] +#RSCLOCAL = User flags for resource compiler [Empty] +#LOCALDEPLIBS = User libraries to include in dependencies [Empty] +#LOCALLIBS = User libraries to use when linking [Empty] +# (in addition to LOCALDEPLIBS) +#LOCAL_LIB_DIRS = User library directories for libpaths [Empty] + +CLOCAL = $(CPIE) +# Include Make Rules definitions and rules +include $(TL_DIR)/IbaTools/Makerules.module + +#=============================================================================# +# Overrides: +#-----------------------------------------------------------------------------# +#CCOPT = # C++ optimization flags, default lets build config decide +#COPT = # C optimization flags, default lets build config decide +#SUBSYSTEM = Subsystem to build for (none, console or windows) [none] +# (Windows Only) +#USEMFC = How Windows MFC should be used (none, static, shared, no_mfc) [none] +# (Windows Only) +#=============================================================================# + +#=============================================================================# +# Rules: +#-----------------------------------------------------------------------------# +# process Sub-directories +include $(TL_DIR)/Makerules/Maketargets.toplevel + +# build cmds and libs +include $(TL_DIR)/Makerules/Maketargets.build + +# install for includes, libs and cmds phases +include $(TL_DIR)/Makerules/Maketargets.install + +%: %.tcl + $(CP) $< $@ + $(CHMOD) 755 $@ + +# install for stage phase +#include $(TL_DIR)/Makerules/Maketargets.stage +STAGE:: + $(VS)$(STAGE_INSTALL) $(STAGE_INSTALL_DIR_OPT) $(PROJ_STAGE_FASTFABRIC_DIR) opafindgood opasorthosts + $(VS)$(STAGE_INSTALL) $(STAGE_INSTALL_DIR_OPT) $(PROJ_STAGE_IBTOOLS_DIR) comm12 + +# Unit test execution +#include $(TL_DIR)/Makerules/Maketargets.runtest + +#=============================================================================# + +#=============================================================================# +# DO NOT DELETE THIS LINE -- make depend depends on it. +#=============================================================================# diff --git a/IbaTools/opafindgood/comm12.tcl b/IbaTools/opafindgood/comm12.tcl new file mode 100755 index 0000000..8ea0af2 --- /dev/null +++ b/IbaTools/opafindgood/comm12.tcl @@ -0,0 +1,116 @@ +#!/usr/bin/tclsh +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] + +# This implements a variation of comm -12 file1 file2 +# which is used by opafindgood + + +proc compare_files { fd1 fd2 } { +# compare input files fd1 and fd2 +# each file is expected to have 2 fields separated by spaces +# files should be sorted case insensitively by first field +# first field is sorted canonical form of name +# second field is original input from user +# assumes there are no comment lines and no blank lines in input +# assumes there are no duplicate lines in input +# lines whose canonical forms match will have the fd1 second field output + + + set done 0 + set line1 "" + set line2 "" + + while { ! $done } { + if { [ string equal "$line1" "" ] } { + if { ! [ eof $fd1 ] } { + gets $fd1 line1 + } + } + if { [ string equal "$line2" "" ] } { + if { ! [ eof $fd2 ] } { + gets $fd2 line2 + } + } + # cut field 1 at ; and just compare field 1 in each + if { [ string equal "$line1" "" ] } { + set done 1 + #if { [ string equal "$line2" "" ] } { + # set done 1 + #} else { + # puts "$line2" + # set line2 "" + #} + } elseif { [ string equal "$line2" "" ] } { + set done 1 + #puts "$line1" + #set line1 "" + } else { + set list1 [ concat $line1 ] + set list2 [ concat $line2 ] + # we have input from both files + set res [ string compare -nocase [ lindex $list1 0] [ lindex $list2 0] ] + if { $res <= -1 } { + # line1 is less, read fd1 again + #puts [ lindex $list1 1] + set line1 "" + } elseif { $res == 0 } { + # equal, output and read from both + puts [ lindex $list1 1] + set line1 "" + set line2 "" + } else { + # line1 is greater, read fd2 again + #puts [ lindex $list2 1] + set line2 "" + } + } + } +} + + +if { $argc != 2 } { + puts stderr "Usage: comm12 file1 file2" + exit 2 +} + +if { [ catch { + set fname1 [lindex $argv 0] + set fname2 [lindex $argv 1] + set fd1 [open $fname1 "r"] + set fd2 [open $fname2 "r"] + compare_files $fd1 $fd2 + +} res ] != 0 } { + puts stderr "comm12: Error: $res" + exit 1 +} +exit 0 diff --git a/IbaTools/opafindgood/opafindgood.sh b/IbaTools/opafindgood/opafindgood.sh new file mode 100755 index 0000000..33fc4b7 --- /dev/null +++ b/IbaTools/opafindgood/opafindgood.sh @@ -0,0 +1,358 @@ +#!/bin/bash +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] + +# analyzes hosts in fabric and outputs some lists: +# alive - list of pingable hosts +# running - subset of alive which can be sshed to via opacmdall +# active - list of hosts with 1 or more active ports +# good - list of hosts which are running and active +# bad - list of hosts which fail any of the above tests +# The intent is that the good list can be a candidate list of hosts for +# use in running MPI jobs to further use or test the cluster + +# optional override of defaults +if [ -f /etc/opa/opafastfabric.conf ] +then + . /etc/opa/opafastfabric.conf +fi + +. /usr/lib/opa/tools/opafastfabric.conf.def + +. /usr/lib/opa/tools/ff_funcs + +trap "exit 1" SIGHUP SIGTERM SIGINT + +punchlist=$FF_RESULT_DIR/punchlist.csv +del=';' +timestamp=$(date +"%Y/%m/%d %T") + +Usage_full() +{ + echo "Usage: opafindgood [-RAQ] [-d dir] [-f hostfile] [-h 'hosts']" >&2 + echo " [-t portsfile] [-p ports] [-T timelimit]" >&2 + echo " or" >&2 + echo " opafindgood --help" >&2 + echo " --help - produce full help text" >&2 + echo " -R - skip the running test (ssh), recommended if password-less ssh not setup" >&2 + echo " -A - skip the active test, recommended if OPA software or fabric is not up" >&2 + echo " -Q - skip the quarantine test, recommended if OPA software or fabric is not" >&2 + echo " up" >&2 + echo " -d - directory in which to create alive, active, running, good and bad files" >&2 + echo " default is $CONFIG_DIR/opa" >&2 + echo " -f hostfile - file with hosts in cluster, default is $CONFIG_DIR/opa/hosts" >&2 + echo " -h hosts - list of hosts to ping" >&2 + echo " -t portsfile - file with list of local HFI ports used to access" >&2 + echo " fabric(s) for analysis, default is $CONFIG_DIR/opa/ports" >&2 + echo " -p ports - list of local HFI ports used to access fabric(s) for analysis" >&2 + echo " default is 1st active port" >&2 + echo " This is specified as hfi:port" >&2 + echo " 0:0 = 1st active port in system" >&2 + echo " 0:y = port y within system" >&2 + echo " x:0 = 1st active port on HFI x" >&2 + echo " x:y = HFI x, port y" >&2 + echo " The first HFI in the system is 1. The first port on an HFI is 1." >&2 + echo " -T timelimit - timelimit in seconds for host to respond to ssh" >&2 + echo " default of 20 seconds" >&2 + echo >&2 + echo "The files alive, running, active, good and bad are created in the selected" >&2 + echo "directory listing hosts passing each criteria" >&2 + echo "A punchlist of bad hosts is also appended to FF_RESULT_DIR/punchlist.csv" >&2 + echo "The good file can be used as input for an mpi_hosts." >&2 + echo "It will list each good host exactly once" >&2 + echo >&2 + echo " Environment:" >&2 + echo " HOSTS - list of hosts, used if -h option not supplied" >&2 + echo " HOSTS_FILE - file containing list of hosts, used in absence of -f and -h" >&2 + echo " PORTS - list of ports, used in absence of -t and -p" >&2 + echo " PORTS_FILE - file containing list of ports, used in absence of -t and -p" >&2 + echo " FF_MAX_PARALLEL - maximum concurrent operations" >&2 + echo "example:">&2 + echo " opafindgood" >&2 + echo " opafindgood -f allhosts" >&2 + echo " opafindgood -h 'arwen elrond'" >&2 + echo " HOSTS='arwen elrond' opafindgood" >&2 + echo " HOSTS_FILE=allhosts opafindgood" >&2 + echo " opafindgood -p '1:1 1:2 2:1 2:2'" >&2 + exit 0 +} + +Usage() +{ + echo "Usage: opafindgood [-RAQ] [-d dir] [-f hostfile] [-h 'hosts']" >&2 + echo " [-t portsfile] [-p ports] [-T timelimit]" >&2 + echo " opafindgood --help" >&2 + echo " or" >&2 + echo " --help - produce full help text" >&2 + echo " -R - skip the running test (ssh), recommended if password-less ssh not setup" >&2 + echo " -A - skip the active test, recommended if OPA software or fabric is not up" >&2 + echo " -Q - skip the quarantine test, recommended if OPA software or fabric is not" >&2 + echo " up" >&2 + echo " -d - directory in which to create alive, active, running, good and bad files" >&2 + echo " default is $CONFIG_DIR/opa" >&2 + echo " -f hostfile - file with hosts in cluster, default is $CONFIG_DIR/opa/hosts" >&2 + echo "" >&2 + echo " See full help text for explanation of all options." >&2 + echo >&2 + echo "The files alive, running, active, good and bad are created in the selected" >&2 + echo "directory listing hosts passing each criteria" >&2 + echo "A punchlist of bad hosts is also appended to FF_RESULT_DIR/punchlist.csv" >&2 + echo "The good file can be used as input for an mpi_hosts." >&2 + echo "It will list each good host exactly once" >&2 + echo >&2 + echo "example:">&2 + echo " opafindgood" >&2 + echo " opafindgood -f allhosts" >&2 + exit 2 +} + +if [ x"$1" = "x--help" ] +then + Usage_full +fi + +skip_ssh=n +skip_active=n +skip_quarantine=n +dir=$CONFIG_DIR/opa +timelimit=20 +while getopts d:f:h:t:p:QRAT: param +do + case $param in + d) dir="$OPTARG";; + h) HOSTS="$OPTARG";; + f) HOSTS_FILE="$OPTARG";; + p) export PORTS="$OPTARG";; + t) export PORTS_FILE="$OPTARG";; + R) skip_ssh=y;; + A) skip_active=y;; + Q) skip_quarantine=y;; + T) export timelimit="$OPTARG";; + ?) + Usage;; + esac +done +shift $((OPTIND -1)) +if [ $# -gt 0 ] +then + Usage +fi + +check_host_args opafindgood + +# just pass host list via environment for opapingall and opacmdall below +export HOSTS +unset HOSTS_FILE + +check_ports_args opafindgood + + +append_punchlist() +# file with $1 set of tested hosts (in lowercase with no dups, unsorted) +# file with $2 set of passing hosts (in lowercase with no dups, unsorted) +# text for punchlist entry for failing hosts +{ + comm -23 <(sort "$1") <(sort "$2")| opasorthosts | while read host + do + echo "$timestamp$del$host$del$3" + done >> $punchlist +} + +# read stdin and convert hostnames to canonical lower case +# in field 1 of output, field2 is unmodified input +# fields are separated by a space +function to_canon() +{ + while read line + do + canon=$(ff_host_basename $line|ff_to_lc) + echo "$canon $line" + done|sort --ignore-case -t ' ' -k1,1 +} + +function mycomm12() +{ + /usr/lib/opa/tools/comm12 $1 $2 +} + +echo "$(ff_var_filter_dups_to_stdout "$HOSTS"|wc -l) hosts will be checked" + +good_meaning= # indicates which tests a good host has passed +good_file= # file (other than good) holding most recent good list + +# ------------------------------------------------------------------------------ +# ping test +opapingall -p|grep 'is alive'|sed -e 's/:.*//'|ff_filter_dups|opasorthosts > $dir/alive +append_punchlist <(ff_var_filter_dups_to_stdout "$HOSTS") $dir/alive "Doesn't ping" +good_meaning="alive" +good_file=$dir/alive +echo "$(cat $dir/alive|wc -l) hosts are pingable (alive)" + +# ------------------------------------------------------------------------------ +# ssh test +if [ "$skip_ssh" = n ] +then + # -h '' to override HOSTS env var so -f is used (HOSTS would override -f) + # use comm command to filter out hosts with unexpected hostnames + # put in alphabetic order for "comm" command + mycomm12 <(to_canon < $good_file) <(opacmdall -h '' -f $good_file -p -T $timelimit 'hostname -s' |grep -v 'hostname -s'|ff_filter_dups|to_canon) | opasorthosts > $dir/running + append_punchlist $good_file $dir/running "Can't ssh" + good_meaning="$good_meaning, running" + good_file=$dir/running + echo "$(cat $dir/running|wc -l) hosts are ssh'able (running)" +fi + +# ------------------------------------------------------------------------------ +# port active test +if [ "$skip_active" = n ] +then + for hfi_port in $PORTS + do + hfi=$(expr $hfi_port : '\([0-9]*\):[0-9]*') + port=$(expr $hfi_port : '[0-9]*:\([0-9]*\)') + if [ "$hfi" = "" -o "$port" = "" ] + then + echo "opafindgood: Error: Invalid port specification: $hfi_port" >&2 + continue + fi + if [ "$port" -eq 0 ] + then + port_opts="-h $hfi" # default port to 1st active + else + port_opts="-h $hfi -p $port" + fi + + opasaquery $port_opts -t fi -o desc | sed "s/ hfi1_[0-9]*$//" + done | ff_filter_dups|opasorthosts > $dir/active + # don't waste time reporting hosts which don't ping or can't ssh + # they are probably down so no use double reporting them + # If performing quarantine test, wait for its results + if [ "$skip_quarantine" = y ]; then + append_punchlist $good_file $dir/active "No active port" + fi + # put in alphabetic order for "comm" command + mycomm12 <(to_canon < $good_file) <(to_canon < $dir/active) | opasorthosts > $dir/good + good_meaning="$good_meaning, active" + echo "$(cat $dir/active|wc -l) total hosts have FIs active on one or more fabrics (active)" +else + cat $good_file > $dir/good +fi + +# ------------------------------------------------------------------------------ +# quarantined node test +if [ "$skip_quarantine" = n ] +then + OLDIFS=$IFS + IFS=";" + + lastnodeguid="" + punchlist_str="" + + opareport -q -o quarantinednodes -x | opaxmlextract -H -d \; -e QuarantinedNodes.QNode.TrustedNodeGUID -e QuarantinedNodes.QNode.NodeType -e QuarantinedNodes.QNode.NodeDesc -e QuarantinedNodes.QNode.QuarantineReasons.Reason | opasorthosts | + while : ; do + read nodeguid nodetype nodedesc reason + + if [ -z $nodeguid ] + then + # Get trailing writes for last entry, if any + if [ "$punchlist_str" != "" ] + then + echo "$punchlist_str" >> $punchlist + fi + break + fi + if [ "$nodetype" != "FI" ] + then + continue + fi + # trim host name + nodedesc=$(echo "$nodedesc" | cut -d ' ' -f 1) + + # allow for $HOSTS filtering + if [[ "$HOSTS" =~ (^|[[:space:]])"$nodedesc"($|[[:space:]]) ]] + then + : + else + continue + fi + + if [ "$nodeguid" != "$lastnodeguid" ] + then + # New Node, may be the first + if [ "$lastnodeguid" != "" ] + then + # New node, write out last's punchlist item + echo "$punchlist_str" >> $punchlist + fi + punchlist_str="$timestamp;$nodedesc;Quarantined: $reason" + echo "$nodedesc" >> $dir/quarantined + else + # Same Node + punchlist_str+=", $reason" + fi + lastnodeguid="$nodeguid" + done + + IFS=$OLDIFS + + # Apply logic requiring Quarantine report completion + if [ -f "$dir/quarantined" ] + then + cat $dir/quarantined | ff_filter_dups | opasorthosts > $dir/temp + mv -f $dir/temp $dir/quarantined + + # Remove nodes from the "good" file that are quarantined. Have to use a temp file as comm doesn't like rewriting a file it's reading + comm -23 <(sort $dir/good) <(sort $dir/quarantined) | opasorthosts > $dir/temp + mv -f $dir/temp $dir/good + # Active Port Test: Don't output any hosts that have been marked as quarantined. + if [ "$skip_active" = n ] + then + comm -23 <(sort $good_file) <(sort $dir/quarantined) | opasorthosts > $dir/temp + append_punchlist $dir/temp $dir/active "No active port" + rm -f $dir/temp + fi + else + # Quarantine test completed with no results + if [ "$skip_active" = n ] + then + append_punchlist $good_file $dir/active "No active port" + fi + fi +fi + +# ------------------------------------------------------------------------------ +# final output +echo "$(cat $dir/good|wc -l) hosts are $good_meaning (good)" +comm -23 <(ff_var_filter_dups_to_stdout "$HOSTS") <(sort $dir/good)| opasorthosts > $dir/bad +echo "$(cat $dir/bad|wc -l) hosts are bad (bad)" +echo "Bad hosts have been added to $punchlist" + +exit 0 diff --git a/IbaTools/opafindgood/opasorthosts.sh b/IbaTools/opafindgood/opasorthosts.sh new file mode 100755 index 0000000..9eaf202 --- /dev/null +++ b/IbaTools/opafindgood/opasorthosts.sh @@ -0,0 +1,68 @@ +#!/bin/bash +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] + +Usage() +{ + echo "Usage: opasorthosts < hostlist > mpi_hosts" >&2 + echo " or" >&2 + echo " opasorthosts --help" >&2 + echo " --help - produce full help text" >&2 + echo "Sort the hostlist alphabetically (case insensitively) then numerically" >&2 + echo "hostnames may end in a numeric field which may optionally have leading zeros" >&2 + echo "example input:">&2 + echo " osd04" >&2 + echo " osd1" >&2 + echo " compute20" >&2 + echo " compute3" >&2 + echo " mgmt1" >&2 + echo " mgmt2" >&2 + echo " login" >&2 + echo "resulting output:">&2 + echo " compute3" >&2 + echo " compute20" >&2 + echo " login" >&2 + echo " mgmt1" >&2 + echo " mgmt2" >&2 + echo " osd1" >&2 + echo " osd04" >&2 + exit 2 +} + +if [ $# -ne 0 ] +then + Usage +fi + +# use Cntr-C as a temporary delimiter since it should never appear in a name +# sort first by the alphanumeric 1st part of name, +# then by any purely numeric last part +sed -e 's/\([0-9]*\)$/\1/'|sort --ignore-case -k1,1 -k2,2n -t ''|sed -e 's///' diff --git a/IbaTools/opafirmware/Makefile b/IbaTools/opafirmware/Makefile new file mode 100644 index 0000000..3db4f6f --- /dev/null +++ b/IbaTools/opafirmware/Makefile @@ -0,0 +1,157 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** +# Makefile for opafirmware tool + +# Include Make Control Settings +include $(TL_DIR)/$(PROJ_FILE_DIR)/Makesettings.project + +#=============================================================================# +# Definitions: +#-----------------------------------------------------------------------------# + +# Name of SubProjects +DS_SUBPROJECTS = +# name of executable or downloadable image +EXECUTABLE = $(BUILDDIR)/opafirmware$(EXE_SUFFIX) +# list of sub directories to build +DIRS = +# C files (.c) +CFILES = \ + opafirmware.c \ + # Add more files here +# C++ files (.cpp) +CCFILES = \ + # Add more files here +# lex files (.lex) +LFILES = \ + # Add more lex files here +# archive library files (basename, $ARFILES will add MOD_LIB_DIR/prefix and suffix) +LIBFILES = +# Windows Resource Files (.rc) +RSCFILES = +# Windows IDL File (.idl) +IDLFILE = +# Windows Linker Module Definitions (.def) file for dll's +DEFFILE = +# targets to build during INCLUDES phase (add public includes here) +INCLUDE_TARGETS = \ + # Add more h hpp files here +# Non-compiled files +MISC_FILES = +# all source files +SOURCES = $(CFILES) $(CCFILES) $(LFILES) $(RSCFILES) $(IDLFILE) +# Source files to include in DSP File +DSP_SOURCES = $(INCLUDE_TARGETS) $(SOURCES) $(MISC_FILES) \ + $(RSCFILES) $(DEFFILE) $(MAKEFILE) +# all object files +OBJECTS = $(CFILES:.c=$(OBJ_SUFFIX)) $(CCFILES:.cpp=$(OBJ_SUFFIX)) \ + $(LFILES:.lex=$(OBJ_SUFFIX)) +RSCOBJECTS = $(RSCFILES:.rc=$(RES_SUFFIX)) + +# targets to build during LIBS phase +LIB_TARGETS_IMPLIB = +LIB_TARGETS_ARLIB = +LIB_TARGETS_EXP = $(LIB_TARGETS_IMPLIB:$(ARLIB_SUFFIX)=$(EXP_SUFFIX)) +LIB_TARGETS_MISC = +# targets to build during CMDS phase +CMD_TARGETS_SHLIB = +CMD_TARGETS_EXE = $(EXECUTABLE) +CMD_TARGETS_MISC = +CMD_TARGETS_DRIVER = +# files to remove during clean phase +CLEAN_TARGETS_MISC = +CLEAN_TARGETS = $(OBJECTS) $(RSCOBJECTS) $(IDL_TARGETS) $(CLEAN_TARGETS_MISC) +# other files to remove during clobber phase +CLOBBER_TARGETS_MISC= +# sub-directory to install to within bin +BIN_SUBDIR = +# sub-directory to install to within include +INCLUDE_SUBDIR = + +# Additional Settings +#CLOCALDEBUG = User defined C debugging compilation flags [Empty] +#CCLOCALDEBUG = User defined C++ debugging compilation flags [Empty] +#CLOCAL = User defined C flags for compiling [Empty] +#CCLOCAL = User defined C++ flags for compiling [Empty] +#BSCLOCAL = User flags for Browse File Builder [Empty] +#DEPENDLOCAL = user defined makedepend flags [Empty] +#LINTLOCAL = User defined lint flags [Empty] +#LOCAL_INCLUDE_DIRS = User include directories to search for C/C++ headers [Empty] +#LDLOCAL = User defined C flags for linking [Empty] +#IMPLIBLOCAL = User flags for Object Lirary Manager [Empty] +#MIDLLOCAL = User flags for IDL compiler [Empty] +#RSCLOCAL = User flags for resource compiler [Empty] +#LOCALDEPLIBS = User libraries to include in dependencies [Empty] +#LOCALLIBS = User libraries to use when linking [Empty] +# (in addition to LOCALDEPLIBS) +# = User library directories for libpaths [Empty] + +CLOCAL = $(CPIE) +LOCAL_LIB_DIRS = +LOCALLIBS = z + +# Include Make Rules definitions and rules +include $(TL_DIR)/IbaTools/Makerules.module + +#=============================================================================# +# Overrides: +#-----------------------------------------------------------------------------# +#CCOPT = # C++ optimization flags, default lets build config decide +#COPT = # C optimization flags, default lets build config decide +#SUBSYSTEM = Subsystem to build for (none, console or windows) [none] +# (Windows Only) +#USEMFC = How Windows MFC should be used (none, static, shared, no_mfc) [none] +# (Windows Only) +#=============================================================================# + +#=============================================================================# +# Rules: +#-----------------------------------------------------------------------------# +# process Sub-directories +include $(TL_DIR)/Makerules/Maketargets.toplevel + +# build cmds and libs +include $(TL_DIR)/Makerules/Maketargets.build + +# install for includes, libs and cmds phases +include $(TL_DIR)/Makerules/Maketargets.install + +# install for stage phase +#include $(TL_DIR)/Makerules/Maketargets.stage +STAGE:: + $(VS)$(STAGE_INSTALL) $(STAGE_INSTALL_DIR_OPT) $(PROJ_STAGE_FASTFABRIC_DIR) $(EXECUTABLE) + +# Unit test execution +#include $(TL_DIR)/Makerules/Maketargets.runtest + +#=============================================================================# + +#=============================================================================# +# DO NOT DELETE THIS LINE -- make depend depends on it. +#=============================================================================# diff --git a/IbaTools/opafirmware/opafirmware.c b/IbaTools/opafirmware/opafirmware.c new file mode 100644 index 0000000..f3f274d --- /dev/null +++ b/IbaTools/opafirmware/opafirmware.c @@ -0,0 +1,760 @@ +/* BEGIN_ICS_COPYRIGHT7 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT7 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "icsImageHeader.h" +#include "zlib.h" + +#define USCORE '_' +#define DOT '.' +#define COLON ':' +#define SPACE ' ' +#define TEE 'T' +#define NUL '\0' + +/* inquiry types */ +#define SHOWVERSION 1 +#define SHOWTYPE 2 +#define HELP 3 + +/* + * The following set of product codes and bsp codes are to be used + * in case the firmware does not have the embedded strings for product + * and bsp name (pre-3.1.0.1). There is no need to update the list with + * new products and bsps, as all future embedded products will have + * the embedded strings built in. + */ + +/* product codes */ +#define VEX_PRODUCT_CODE 1 +#define VFX_PRODUCT_CODE 2 +#define INFINIFABRIC_PRODUCT_CODE 3 +#define IBX_PRODUCT_CODE 4 +#define INFINIO2000_PRODUCT_CODE 5 +#define INFINIO3000_PRODUCT_CODE 6 +#define INFINIO5000_PRODUCT_CODE 7 +#define INFINIO9000_PRODUCT_CODE 8 +#define X_PRODUCT_CODE 9 +#define STL1_PRODUCT_CODE 10 + +/* bsp codes */ +#define SW_AUX_PRODUCT_CODE 3 +#define PCIX_PRODUCT_CODE 7 +#define MC1125_PRODUCT_CODE 9 +#define T3_PRODUCT_CODE 10 +#define XT3_PRODUCT_CODE 13 +#define N450_PRODUCT_CODE 14 +#define Q7_PRODUCT_CODE 15 + +#define INBUFFERSIZE 64*1024 + +#define PROD_SEARCH_STRING "THIS_IS_THE_ICS_PRODUCT_NAME" +#define BSP_SEARCH_STRING "THIS_IS_THE_ICS_BSP_NAME" + +/* CSS Header definitions */ + +#define CSS_HEADER_SIZE 644 +#define SIGNATURE_LEN 256 +#define EXPONENT_LEN 4 +#define MODULUS_LEN 256 + +typedef struct cssHeader_s { + uint32_t moduleType; + uint32_t headerLen; + uint32_t headerVersion; + uint32_t moduleID; + uint32_t moduleVendor; + uint32_t date; + uint32_t size; + uint32_t keySize; + uint32_t modulusSize; + uint32_t exponentSize; + uint32_t reserved[22]; + uint8_t modulus[MODULUS_LEN]; + uint8_t exponent[EXPONENT_LEN]; + uint8_t signature[SIGNATURE_LEN]; +} cssHeader_t; + +#define CSS_MODULE_TYPE 6 +#define CSS_HEADER_LEN 0xA1 +#define CSS_HEADER_VER 0x10000 +#define CSS_DBG_MODULE_ID 0x80000000 +#define CSS_PRD_MODULE_ID 0 +#define CSS_MODULE_VENDOR 0x8086 +#define CSS_KEY_SIZE 0x40 +#define CSS_MODULUS_SIZE 0x40 +#define CSS_EXPONENT_SIZE 1 + +char *cmpBuffer = NULL; +char *appBuffer = NULL; +int bufSize; + +int cmpBufferSize; +int appBufferSize; + +/* + * the follwing set of functions is borrowed from icsImageUtil + * in devtools (some of have been modifed slightly) + */ + +#define ERR_OK 0 +#define ERR_IO_ERROR -1 +#define ERR_INVALID -2 + +#define gen_cpu_bswap32(what) ((((uint32_t)what) >> 24) | (((uint32_t)what) << 24) | ((((uint32_t)what) >> 8) & 0xff00) | ((((uint32_t)what) << 8) & 0xff0000)) + +struct +{ + int hostBigEndian; + int targetBigEndian; +} g_state; + +char g_ioBuffer[INBUFFERSIZE]; + +int isHostBigEndian (void) +{ + uint32_t probeValue = 0x12345678; + char *probePtr; + + probePtr = (char *)&probeValue; + if (0x12 == *probePtr) + { + return(1); + } else + return(0); +} + +/* + initializeState - initializes the global state for the program. this has to be + called before any other routines are called. +*/ +void initializeState (void) +{ + g_state.hostBigEndian = isHostBigEndian(); + g_state.targetBigEndian = 1; +} + +uint32_t toHostEndian32 (uint32_t value) +{ + if (g_state.hostBigEndian != g_state.targetBigEndian) + return (gen_cpu_bswap32(value)); + else + return (value); +} + +/* + getRecord - retrieves the next record from the given file. it is assumed + the the file pointer is positioned at the start of a valid + record when this routine is called. the record is stored in + the supplied record buffer, and the type and size fields are + converted to the endian of the host. +*/ +int getRecord (FILE *f, IcsImageHeader_Record_t *recordBuffer) +{ + int result; + uint32_t recordType; + uint32_t payloadSize; + + result = fread(&recordType, 4, 1, f); + if (0 == result) + { + fprintf(stderr, "Error reading record type\n"); + return(ERR_IO_ERROR); + } + + result = fread(&payloadSize, 4, 1, f); + if (0 == result) + { + fprintf(stderr, "Error reading record size\n"); + return(ERR_IO_ERROR); + } + + result = fread(&(recordBuffer->payload), toHostEndian32(payloadSize), 1, f); + if (0 == result) + { + fprintf(stderr, "Error reading record payload\n"); + return(ERR_IO_ERROR); + } + + recordBuffer->type = toHostEndian32(recordType); + recordBuffer->size = toHostEndian32(payloadSize); + + return(ERR_OK); +} + +int checkCssHeader (uint8_t *buf) +{ + int isSpkg = 0; + cssHeader_t *cssp; + + cssp = (cssHeader_t *)buf; + if (cssp->moduleType == CSS_MODULE_TYPE && + cssp->headerLen == CSS_HEADER_LEN && + cssp->headerVersion == CSS_HEADER_VER && + cssp->moduleVendor == CSS_MODULE_VENDOR && + (cssp->moduleID == CSS_DBG_MODULE_ID || cssp->moduleID == CSS_PRD_MODULE_ID) && + cssp->keySize == CSS_KEY_SIZE && + cssp->modulusSize == CSS_MODULUS_SIZE ) { + isSpkg = 1; + } + + return(isSpkg); +} + +/* + removeHeader - removes the ICS image header from the given file, if it has one +*/ +int removeHeader (char *inputFileName, char *outputBuffer) +{ + uint32_t imageHeaderSize; + FILE *inputFp; + char *p; + IcsImageHeader_Record_t recordBuffer; + uint32_t bytesRead; + uint32_t firstRecordType; + uint8_t cssBuf[CSS_HEADER_SIZE + 10]; + int isSpkg = 0; + + cmpBufferSize = 0; + + inputFp = fopen(inputFileName, "rb"); + if (NULL == inputFp) + { + return(ERR_IO_ERROR); + } + + if (0 == fread(&cssBuf, CSS_HEADER_SIZE, 1, inputFp)) + { + fclose(inputFp); + return(ERR_IO_ERROR); + } + + isSpkg = checkCssHeader(cssBuf); + + fseek(inputFp, isSpkg ? CSS_HEADER_SIZE : 0, SEEK_SET); + + if (0 == fread(&firstRecordType, 4, 1, inputFp)) + { + fclose(inputFp); + return(ERR_IO_ERROR); + } + + p = outputBuffer; + + fseek(inputFp, isSpkg ? CSS_HEADER_SIZE : 0, SEEK_SET); + + if (ICS_IMAGE_HEADER_RECORD_TYPE_INFO != toHostEndian32(firstRecordType)) + { + fclose(inputFp); + return(ERR_INVALID); + } + + if (ERR_OK != getRecord(inputFp, &recordBuffer)) + { + fclose(inputFp); + return(ERR_INVALID); + } + + imageHeaderSize = toHostEndian32(recordBuffer.payload.info.headerSize); + fseek(inputFp, isSpkg ? CSS_HEADER_SIZE + imageHeaderSize : imageHeaderSize, SEEK_SET); + + while (0 != (bytesRead = fread(g_ioBuffer, 1, INBUFFERSIZE, inputFp))) + { + memcpy(p, g_ioBuffer, bytesRead); + p += bytesRead; + cmpBufferSize += bytesRead; + } + + fclose(inputFp); + return(ERR_OK); +} + +/* end of borrowed stuff from icsImageUtil in devtools */ + + +void copyAndReplace (char *src, char *dest, char from, char to) +{ + char *pSrc; + char *pDest; + + for (pSrc = src, pDest = dest; *pSrc != NUL; pSrc++, pDest++) + { + if (*pSrc == from) + *pDest = to; + else + *pDest = *pSrc; + } + *pDest = NUL; + return; +} + +void displayVersion(char *firmwareVersion) +{ + /* display the version - pass to copyAndReplace to make a dot-separated string */ + + char outputVersion[ICS_IMAGE_HEADER_VERSION_SIZE]; + + copyAndReplace(firmwareVersion, outputVersion, USCORE, DOT); + + printf("%s\n", outputVersion); +} + +void displayType(uint32_t firmwareType, uint32_t bspType) +{ + /* display the type, based on type code */ + + switch(firmwareType) + { + case VEX_PRODUCT_CODE: + printf("VEx."); + break; + case VFX_PRODUCT_CODE: + printf("VFx."); + break; + case INFINIFABRIC_PRODUCT_CODE: + printf("InfiniFabric."); + break; + case IBX_PRODUCT_CODE: + printf("IBx."); + break; + case INFINIO2000_PRODUCT_CODE: + printf("InfinIO2000."); + break; + case INFINIO3000_PRODUCT_CODE: + printf("InfinIO3000."); + break; + case INFINIO5000_PRODUCT_CODE: + printf("InfinIO5000."); + break; + case INFINIO9000_PRODUCT_CODE: + printf("InfinIO9000."); + break; + case X_PRODUCT_CODE: + printf("X."); + break; + case STL1_PRODUCT_CODE: + printf("Intel_Omni_Path_Fabric_Switches_STL1_Series."); + break; + default: + fprintf(stderr, "Unknown product code."); + break; + } + + switch(bspType) + { + case SW_AUX_PRODUCT_CODE: + printf("sw_aux\n"); + break; + case PCIX_PRODUCT_CODE: + printf("pcix\n"); + break; + case MC1125_PRODUCT_CODE: + printf("mc1125\n"); + break; + case T3_PRODUCT_CODE: + printf("t3\n"); + break; + case XT3_PRODUCT_CODE: + printf("xt3\n"); + break; + case N450_PRODUCT_CODE: + printf("n450\n"); + break; + case Q7_PRODUCT_CODE: + printf("q7\n"); + break; + default: + fprintf(stderr, "Unknown bsp code\n"); + break; + } + + return; +} + +#define CHECK_ERR(err, msg) \ +{ \ + if (err != Z_OK) \ + { \ + fprintf(stderr, "%s error: %d\n", msg, err); \ + if (inBuffer) free(inBuffer); \ + if (outBuffer) free(outBuffer); \ + return(ERR_INVALID); \ + } \ +} + +int doInflate(char *smallBuffer, char *bigBuffer) +{ + unsigned char *inBuffer = NULL; + unsigned char *outBuffer = NULL; + char *smallBufferP; + char *bigBufferP; + int inBufferSize; + int outBufferSize; + int bytesToGo = cmpBufferSize; + int bytesCopied = 0; + int bytesToProcess; + int err; + int done = 0; + z_stream decompStream; + + inBufferSize = INBUFFERSIZE; + outBufferSize = INBUFFERSIZE; + + if ((inBuffer = (unsigned char *)malloc(inBufferSize)) == NULL) { + fprintf(stderr, "Error allocating memory for input buffer\n"); + goto memerr; + } + if ((outBuffer = (unsigned char *)malloc(outBufferSize)) == NULL) { + fprintf(stderr, "Error allocating memory for output buffer\n"); + goto memerr; + } + + smallBufferP = smallBuffer + 1; /* move past magic number */ + bigBufferP = bigBuffer; + + decompStream.zalloc = (alloc_func)0; + decompStream.zfree = (free_func)0; + decompStream.opaque = (voidpf)0; + + err = inflateInit(&decompStream); + CHECK_ERR(err, "inflateInit"); + + bytesToProcess = (bytesToGo > inBufferSize) ? inBufferSize : bytesToGo; + memcpy(inBuffer, smallBufferP, bytesToProcess); + bytesToGo -= bytesToProcess; + smallBufferP += bytesToProcess; + + decompStream.next_in = inBuffer; + decompStream.next_out = outBuffer; + + while (!done) + { + decompStream.avail_in = bytesToProcess; + decompStream.avail_out = outBufferSize; + + while(decompStream.avail_in) + { + err = inflate(&decompStream, Z_NO_FLUSH); + if (err == Z_STREAM_END) + break; + CHECK_ERR(err, "inflate"); + + memcpy(bigBufferP, outBuffer, decompStream.next_out - outBuffer); + bigBufferP += decompStream.next_out - outBuffer; + bytesCopied += decompStream.next_out - outBuffer; + + decompStream.next_out = outBuffer; + decompStream.avail_out = outBufferSize; + } + + bytesToProcess = (bytesToGo > inBufferSize) ? inBufferSize : bytesToGo; + if (bytesToProcess == 0) + done = 1; + else + { + memcpy(inBuffer, smallBufferP, bytesToProcess); + bytesToGo -= bytesToProcess; + smallBufferP += bytesToProcess; + + decompStream.next_in = inBuffer; + decompStream.next_out = outBuffer; + } + } + + err = inflateEnd(&decompStream); + CHECK_ERR(err, "inflateEnd"); + + free(inBuffer); + free(outBuffer); + + appBufferSize = bytesCopied; + + return(ERR_OK); + +memerr: + if (inBuffer != NULL) + free(inBuffer); + if (outBuffer != NULL) + free(outBuffer); + return(Z_MEM_ERROR); +} + +int displayEmbeddedProdAndBsp(void) +{ + int result; + int returnVal = 0; + char *p; + char *p1, *p2; + char productName[64]; + char bspName[64]; + int prodStringFound = 0; + int bspStringFound = 0; + +/* + * First, perform the inflate from the compressed buffer to the + * application buffer + */ + + if ((result = doInflate(cmpBuffer, appBuffer)) != ERR_OK) + return(returnVal); + +/* + * In the application buffer, look for both search patterns so + * as to locate the Product and BSP names. Use memchr to find the + * first character ('T'), then compare rest of string. If not found, + * resume search for next occurrence of 'T'. + */ + + p = memchr(appBuffer, TEE, appBufferSize); + if (p == NULL) { + returnVal = 0; + goto fail; + } + while (!prodStringFound && (p != NULL)) + { + if (memcmp(p, PROD_SEARCH_STRING, strlen(PROD_SEARCH_STRING)) == 0) + { + prodStringFound = 1; + returnVal = 1; + p1 = strchr(p, COLON) + 1; + if (p1 == NULL) { + returnVal = 0; + goto fail; + } + for (p2 = productName; (*p1 != SPACE) && (*p1 != NUL); p1++, p2++) + *p2 = *p1; + *p2 = NUL; + } + else + { + p = memchr(p + 1, TEE, appBufferSize - (p - appBuffer)); + } + } + if (returnVal) + { + p = memchr(appBuffer, TEE, appBufferSize); + + while (p && !bspStringFound) + { + if (memcmp(p, BSP_SEARCH_STRING, strlen(BSP_SEARCH_STRING)) == 0) + { + bspStringFound = 1; + p1 = strchr(p, COLON) + 1; + if (p1 == NULL) { + returnVal = 0; + goto fail; + } + for (p2 = bspName; (*p1 != SPACE) && (*p1 != NUL); p1++, p2++) + *p2 = *p1; + *p2 = NUL; + } + else + { + p = memchr(p + 1, TEE, appBufferSize - (p - appBuffer)); + } + } + if (!bspStringFound) + returnVal = 0; + else + printf("%s.%s\n", productName, bspName); + } + +fail: + return(returnVal); +} + +void Usage(void) +{ + fprintf(stderr, "Usage: opafirmware [--help] [--showVersion|--showType firmwareFile]\n"); + fprintf(stderr, " --help - full help text\n"); + + exit(1); +} + +void Usage_full(void) +{ + fprintf(stderr, "Usage: opafirmware [--help] [--showVersion|--showType firmwareFile]\n"); + fprintf(stderr, " --help - full help text\n"); + fprintf(stderr, "\n"); + fprintf(stderr, "Examples:\n"); + fprintf(stderr, " --showVersion STL1.q7.10.0.0.0.spkg\n"); + fprintf(stderr, " 10.0.0.0\n"); + fprintf(stderr, " --showType STL1.q7.10.0.0.0.spkg\n"); + fprintf(stderr, " Omni_Path_Switch_Products.q7\n"); + + exit(0); +} + +int main(int argc, char *argv[]) +{ + char *firmwareFileName; + FILE *fpFirmwareFile; + int inquiryType; + int firstRecordType; + int result; + int fileSize; + int isSpkg = 0; + struct stat statBuf; + IcsImageHeader_Record_t recordBuffer; + uint8_t cssBuf[CSS_HEADER_SIZE + 10]; + + struct option longopts[] = + { + { "showVersion", no_argument, &inquiryType, SHOWVERSION }, + { "showType", no_argument, &inquiryType, SHOWTYPE }, + { "help", no_argument, &inquiryType, HELP }, + { 0, 0, 0 , 0 } + }; + + /* parse options for inquiry type */ + if ((result = getopt_long(argc, argv, "", longopts, NULL))) // assignment, not == + Usage(); + + if (inquiryType == HELP) + Usage_full(); + + if (argc != 3) + Usage(); + + /* set up endian-ness */ + + initializeState(); + + + firmwareFileName = argv[2]; + + if (!firmwareFileName) { + fprintf(stderr, "Error: null input filename\n"); + exit(1); + } + + /* stat file to get size and allocate buffers */ + if (stat(firmwareFileName, &statBuf) < 0) { + fprintf(stderr, "Error taking stat of file {%s}: %s\n", + firmwareFileName, strerror(errno)); + exit(1); + } + + fileSize = (int)statBuf.st_size; + bufSize = fileSize + 1024; /* pad by 1K to be safe */ + if ((cmpBuffer = malloc(bufSize)) == NULL) { + fprintf(stderr, "Error allocating memory for firmware buffer\n"); + goto fail; + } + if ((appBuffer = malloc(bufSize * 3)) == NULL) { + fprintf(stderr, "Error allocating memory for inflated firmware buffer\n"); + goto fail; + } + + memset(cmpBuffer, 0, bufSize); + memset(appBuffer, 0, bufSize * 3); + + /* open file */ + + if ((fpFirmwareFile = fopen(firmwareFileName, "rb")) == NULL) + { + fprintf(stderr, "Error opening file {%s} for input: %s\n", + firmwareFileName, strerror(errno)); + goto fail; + } + + if (0 == fread(&cssBuf, CSS_HEADER_SIZE, 1, fpFirmwareFile)) + { + fprintf(stderr, "Error reading file {%s}: %s\n", + firmwareFileName, strerror(errno)); + goto fail; + } + + isSpkg = checkCssHeader(cssBuf); + + /* get first record, check if ICS image file */ + + fseek(fpFirmwareFile, isSpkg ? CSS_HEADER_SIZE : 0, SEEK_SET); + + if (0 == fread(&firstRecordType, 4, 1, fpFirmwareFile)) + { + fprintf(stderr, "Error reading file {%s}: %s\n", + firmwareFileName, strerror(errno)); + goto fail; + } + + fseek(fpFirmwareFile, isSpkg ? CSS_HEADER_SIZE : 0, SEEK_SET); + + if (ICS_IMAGE_HEADER_RECORD_TYPE_INFO != toHostEndian32(firstRecordType)) + { + fprintf(stderr, "This is not a valid firmware image file\n"); + goto fail; + } + + /* read in header, display what is asked for */ + + if (ERR_OK != getRecord(fpFirmwareFile, &recordBuffer)) + goto fail; + + switch (inquiryType) + { + case SHOWVERSION: + displayVersion(recordBuffer.payload.info.version); + break; + case SHOWTYPE: + /* + * For the type, we really want to look for the embedded strings first. + * Call removeHeader, which will remove the ICS header from the package + * file and place it in the compressed buffer. Then call + * displayEmbeddedProdAndBsp which inflates and then searches. If the search + * fails, it is a pre-3.1.0.1 release, so feed the codes from the ICS header + * to displayType. + */ + result = removeHeader(argv[2], cmpBuffer); + if (!displayEmbeddedProdAndBsp()) /* if this fails, try old way */ + displayType(toHostEndian32(recordBuffer.payload.info.productCode), + toHostEndian32(recordBuffer.payload.info.bspCode)); + break; + default: + fprintf(stderr, "Unknown inquiry type\n"); + goto fail; + } + + fclose(fpFirmwareFile); +fail: + if (cmpBuffer != NULL) + free(cmpBuffer); + if (appBuffer != NULL) + free(appBuffer); + exit(0); +} diff --git a/IbaTools/opagenchassis/Makefile b/IbaTools/opagenchassis/Makefile new file mode 100644 index 0000000..cb49e2a --- /dev/null +++ b/IbaTools/opagenchassis/Makefile @@ -0,0 +1,164 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** +# Makefile for opachassisip + +# Include Make Control Settings +include $(TL_DIR)/$(PROJ_FILE_DIR)/Makesettings.project + +#=============================================================================# +# Definitions: +#-----------------------------------------------------------------------------# + +# Name of SubProjects +DS_SUBPROJECTS = +# name of executable or downloadable image +EXECUTABLE = $(BUILDDIR)/opachassisip$(EXE_SUFFIX) +# list of sub directories to build +DIRS = +# C files (.c) +CFILES = \ + opachassisip.c + # Add more c files here +# C++ files (.cpp) +CCFILES = \ + # Add more cpp files here +# lex files (.lex) +LFILES = \ + # Add more lex files here +# archive library files (basename, $ARFILES will add MOD_LIB_DIR/prefix and suffix) +LIBFILES= +# Windows Resource Files (.rc) +RSCFILES = +# Windows IDL File (.idl) +IDLFILE = +# Windows Linker Module Definitions (.def) file for dll's +DEFFILE = +# targets to build during INCLUDES phase (add public includes here) +INCLUDE_TARGETS = \ + # Add more h hpp files here +# Non-compiled files +MISC_FILES = +# all source files +SOURCES = $(CFILES) $(CCFILES) $(LFILES) $(RSCFILES) $(IDLFILE) +# Source files to include in DSP File +DSP_SOURCES = $(INCLUDE_TARGETS) $(SOURCES) $(MISC_FILES) \ + $(RSCFILES) $(DEFFILE) $(MAKEFILE) +# all object files +OBJECTS = $(CFILES:.c=$(OBJ_SUFFIX)) $(CCFILES:.cpp=$(OBJ_SUFFIX)) \ + $(LFILES:.lex=$(OBJ_SUFFIX)) +RSCOBJECTS = $(RSCFILES:.rc=$(RES_SUFFIX)) +# targets to build during LIBS phase +LIB_TARGETS_IMPLIB = +LIB_TARGETS_ARLIB = # $(LIB_PREFIX)ResourceTest$(ARLIB_SUFFIX) +LIB_TARGETS_EXP = $(LIB_TARGETS_IMPLIB:$(ARLIB_SUFFIX)=$(EXP_SUFFIX)) +LIB_TARGETS_MISC = +# targets to build during CMDS phase +CMD_TARGETS_SHLIB = +CMD_TARGETS_EXE = $(EXECUTABLE) +CMD_TARGETS_MISC = opagenchassis +# files to remove during clean phase +CLEAN_TARGETS_MISC = +CLEAN_TARGETS = $(OBJECTS) $(RSCOBJECTS) $(IDL_TARGETS) $(CLEAN_TARGETS_MISC) +# other files to remove during clobber phase +CLOBBER_TARGETS_MISC= +# sub-directory to install to within bin +BIN_SUBDIR = +# sub-directory to install to within include +INCLUDE_SUBDIR = + +# Additional Settings +#CLOCALDEBUG = User defined C debugging compilation flags [Empty] +#CCLOCALDEBUG = User defined C++ debugging compilation flags [Empty] +#CLOCAL = User defined C flags for compiling [Empty] +#CCLOCAL = User defined C++ flags for compiling [Empty] +#BSCLOCAL = User flags for Browse File Builder [Empty] +#DEPENDLOCAL = user defined makedepend flags [Empty] +#LINTLOCAL = User defined lint flags [Empty] +#LOCAL_INCLUDE_DIRS = User include directories to search for C/C++ headers [Empty] +#LDLOCAL = User defined C flags for linking [Empty] +#IMPLIBLOCAL = User flags for Object Lirary Manager [Empty] +#MIDLLOCAL = User flags for IDL compiler [Empty] +#RSCLOCAL = User flags for resource compiler [Empty] +#LOCALDEPLIBS = User libraries to include in dependencies [Empty] +#LOCALLIBS = User libraries to use when linking [Empty] +# (in addition to LOCALDEPLIBS) +#LOCAL_LIB_DIRS = User library directories for libpaths [Empty] + +CLOCAL=$(CIBACCESS) $(CPIE) +LOCAL_INCLUDE_DIRS= +ifeq "$(IB_STACK)" "IBACCESS" +LOCALDEPLIBS=$(IBACCESS_USER_LIBS) Xml Topology IbPrint +LOCALLIBS=ncurses +LOCAL_LIB_DIRS= $(IBACCESS_USER_LIB_DIRS) Xml +else +LOCALDEPLIBS=$(IBACCESS_USER_LIBS) Xml opamgt-priv Topology IbPrint +LOCALLIBS=$(OPENIB_USER_LIBS) ncurses +LOCAL_LIB_DIRS=$(OPENIB_USER_LIB_DIRS) $(IBACCESS_USER_LIB_DIRS) +endif + +# Include Make Rules definitions and rules +include $(TL_DIR)/IbaTools/Makerules.module + +#=============================================================================# +# Overrides: +#-----------------------------------------------------------------------------# +#CCOPT = # C++ optimization flags, default lets build config decide +#COPT = # C optimization flags, default lets build config decide +#SUBSYSTEM = Subsystem to build for (none, console or windows) [none] +# (Windows Only) +#USEMFC = How Windows MFC should be used (none, static, shared, no_mfc) [none] +# (Windows Only) +#=============================================================================# + +#=============================================================================# +# Rules: +#-----------------------------------------------------------------------------# +# process Sub-directories +include $(TL_DIR)/Makerules/Maketargets.toplevel + +# build cmds and libs +include $(TL_DIR)/Makerules/Maketargets.build + +# install for includes, libs and cmds phases +include $(TL_DIR)/Makerules/Maketargets.install + +# install for stage phase +#include $(TL_DIR)/Makerules/Maketargets.stage +STAGE:: + $(VS)$(STAGE_INSTALL) $(STAGE_INSTALL_DIR_OPT) $(PROJ_STAGE_FASTFABRIC_DIR) $(EXECUTABLE) + $(VS)$(STAGE_INSTALL) $(STAGE_INSTALL_DIR_OPT) $(PROJ_STAGE_FASTFABRIC_DIR) opagenchassis + +# Unit test execution +#include $(TL_DIR)/Makerules/Maketargets.runtest + +#=============================================================================# + +#=============================================================================# +# DO NOT DELETE THIS LINE -- make depend depends on it. +#=============================================================================# diff --git a/IbaTools/opagenchassis/opachassisip.c b/IbaTools/opagenchassis/opachassisip.c new file mode 100644 index 0000000..d05860a --- /dev/null +++ b/IbaTools/opagenchassis/opachassisip.c @@ -0,0 +1,453 @@ +/* BEGIN_ICS_COPYRIGHT5 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + * ** END_ICS_COPYRIGHT5 ****************************************/ +/* [ICS VERSION STRING: unknown] */ +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include +#include +#include +#include +#include +#define _GNU_SOURCE +#include + +#ifdef __cplusplus +} +#endif + +#include +#include +#include "iba/ib_types.h" +#include "iba/ib_sm_priv.h" +#include "iba/ib_helper.h" +#include "iba/ib_ibt.h" +#include "iba/ipublic.h" +#include "ibprint.h" + + +// macro definitions +#ifndef DBGPRINT +#define DBGPRINT(format, args...) \ + do { if (g_verbose) { fflush(stdout); fprintf(stderr, format, ##args); } } while (0) +#endif +#define APP_NAME "opachassisip" +#define MYTAG MAKE_MEM_TAG('i','g', 'i', 'p') + +#define RESP_WAIT_TIME (1000) // 1000 milliseconds for receive response + +// type definitions +typedef struct ipv4AddrEntry_s { + cl_map_item_t AllIpAddrsEntry; // key is SystemImageGUID + STL_IPV4_IP_ADDR ipAddr; +} ipv4AddrEntry_t; + +typedef struct ipv6AddrEntry_s { + cl_map_item_t AllIpAddrsEntry; // key is SystemImageGUID + STL_IPV6_IP_ADDR ipAddr; +} ipv6AddrEntry_t; + +// global variable +uint8_t g_hfi = 0; +uint8_t g_port = 0; +uint64_t g_bkey = 0; +uint8_t g_verbose = 0; +uint8_t g_omgt_debug = 0; +EUI64 g_portGuid = -1; // local port to use to access fabric +IB_PORT_ATTRIBUTES *g_portAttrib; // attributes for our local port +PrintDest_t g_dest; +cl_qmap_t g_allIpv4Addresses; +cl_qmap_t g_allIpv6Addresses; + +// command line options, each has a short and long flag name +struct option options[] = { + { "verbose", no_argument, NULL, 'v'}, + { "hfi", no_argument, NULL, 'h'}, + { "port", no_argument, NULL, 'p'}, + { "help", no_argument, NULL, '?'}, + { 0} +}; + +static void usage() +{ + fprintf(stderr, "Usage: opachassisip [-v][-h][-p]\n"); + fprintf(stderr, " -v/--verbose - verbose output\n"); + fprintf(stderr, " -h/--hfi hfi - hfi to send via, numbered 1..n, 0= -p port will be\n"); + fprintf(stderr, " a system wide port num (default is 0)\n"); + fprintf(stderr, " -p/--port port - port to send via, numbered 1..n, 0=1st active\n"); + fprintf(stderr, " (default is 1st active)\n"); + fprintf(stderr, " ?/--help - produce full help text\n"); + fprintf(stderr, "The -h and -p options permit a variety of selections:\n"); + fprintf(stderr, " -h 0 - 1st active port in system (this is the default)\n"); + fprintf(stderr, " -h 0 -p 0 - 1st active port in system\n"); + fprintf(stderr, " -h x - 1st active port on HFI x\n"); + fprintf(stderr, " -h x -p 0 - 1st active port on HFI x\n"); + fprintf(stderr, " -h 0 -p y - port y within system (irrespective of which ports are active)\n"); + fprintf(stderr, " -h x -p y - HFI x, port y\n"); + + exit(2); +} + +static void signal_handler(int sig) +{ + DBGPRINT("%s: Abort request received, terminating!\n", APP_NAME); + exit(-1); +} + +static int print_v4v6_ip_info(const char *chassisIP) +{ + struct addrinfo hints, *res, *next; + int errcode; + char addrstr[100]; + void *ptr = NULL; + + memset (&hints, 0, sizeof (hints)); + hints.ai_family = PF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + hints.ai_flags |= AI_CANONNAME; + + errcode = getaddrinfo (chassisIP, NULL, &hints, &res); + if (errcode != 0) { + fprintf(stderr, "Unable to get addressing information on IP address %s\n", chassisIP); + return -1; + } + + fprintf(stderr, "Host: %s\n", chassisIP); + while (res) { + inet_ntop (res->ai_family, res->ai_addr->sa_data, addrstr, 100); + + switch (res->ai_family) { + case AF_INET: + ptr = &((struct sockaddr_in *) res->ai_addr)->sin_addr; + break; + case AF_INET6: + ptr = &((struct sockaddr_in6 *) res->ai_addr)->sin6_addr; + break; + } + inet_ntop (res->ai_family, ptr, addrstr, 100); + fprintf(stderr, "IPv%d address: %s (%s)\n", res->ai_family == PF_INET6 ? 6 : 4, + addrstr, res->ai_canonname); + next = res->ai_next; + freeaddrinfo(res); + res = next; + } + freeaddrinfo(res); + + return 0; +} + +static FSTATUS ipv4_ip_list(NodeData *nodep, PortData *portp) +{ + int indent = 0; + cl_map_item_t *mi; + struct hostent *hp = NULL; + struct in_addr sin_addr; + ipv4AddrEntry_t *ipAddrEntryp; + char ipString[100]; + + memset(ipString, 0, sizeof(ipString)); + inet_ntop(AF_INET, &(nodep->pSwitchInfo->SwitchInfoData.IPAddrIPV4), ipString, sizeof(ipString)); + + if (g_verbose) + fprintf(stderr, "Processing IPv4 address: %s\n", ipString); + + memset(&sin_addr, 0, sizeof(sin_addr)); + memcpy(&sin_addr, &(nodep->pSwitchInfo->SwitchInfoData.IPAddrIPV4), sizeof(nodep->pSwitchInfo->SwitchInfoData.IPAddrIPV4)); + + // check whether IP address was already processed + mi = cl_qmap_get(&g_allIpv4Addresses, nodep->NodeInfo.SystemImageGUID); + if (mi != cl_qmap_end(&g_allIpv4Addresses)) { + hp = gethostbyaddr((const char *)&sin_addr, sizeof(sin_addr), AF_INET); + if (g_verbose) { + PrintFunc(&g_dest, "%*s 0x%04x,0x%016"PRIx64",%s,%s:Duplicate\n", + indent, "", + portp->EndPortLID, + nodep->NodeInfo.SystemImageGUID, + (hp) ? hp->h_name : "", + ipString); + } + return FSUCCESS; + } + + // add IP address to the global IPv4 chassis IP list + ipAddrEntryp = (ipv4AddrEntry_t *)MemoryAllocate2AndClear(sizeof(ipv4AddrEntry_t), IBA_MEM_FLAG_PREMPTABLE, MYTAG); + if (ipAddrEntryp == NULL) { + fprintf(stderr, "Error, unable to allocate memory for IP address entry\n"); + return FINSUFFICIENT_MEMORY; + } + + memcpy(&(ipAddrEntryp->ipAddr), &(nodep->pSwitchInfo->SwitchInfoData.IPAddrIPV4), sizeof(ipAddrEntryp->ipAddr)); + + mi = cl_qmap_insert(&g_allIpv4Addresses, nodep->NodeInfo.SystemImageGUID, &ipAddrEntryp->AllIpAddrsEntry); + if (mi != &ipAddrEntryp->AllIpAddrsEntry) { + MemoryDeallocate(ipAddrEntryp); + return FERROR; + } + + // resolve chassis IP address to hostname + hp = gethostbyaddr((const char *)&sin_addr, sizeof(sin_addr), AF_INET); + if (g_verbose) { + PrintFunc(&g_dest, "%*s 0x%04x,0x%016"PRIx64",%s,%s\n", + indent, "", + portp->EndPortLID, + nodep->NodeInfo.SystemImageGUID, + (hp) ? hp->h_name : "", + ipString); + } else { + PrintFunc(&g_dest, "%*s%s\n", + indent, "", (hp) ? hp->h_name : ipString); + } + + return FSUCCESS; +} + +static FSTATUS ipv6_ip_list(NodeData *nodep, PortData *portp) +{ + int indent = 0; + cl_map_item_t *mi; + struct hostent *hp = NULL; + struct in6_addr sin_addr; + ipv6AddrEntry_t *ipAddrEntryp; + char ipString[100]; + + memset(ipString, 0, sizeof(ipString)); + inet_ntop(AF_INET6, &(nodep->pSwitchInfo->SwitchInfoData.IPAddrIPV6), ipString, sizeof(ipString)); + + if (g_verbose) + fprintf(stderr, "Processing IPv6 address: %s\n", ipString); + + memset(&sin_addr, 0, sizeof(sin_addr)); + memcpy(&sin_addr, &(nodep->pSwitchInfo->SwitchInfoData.IPAddrIPV6), sizeof(nodep->pSwitchInfo->SwitchInfoData.IPAddrIPV6)); + + // check whether IPv6 address was already processed + mi = cl_qmap_get(&g_allIpv6Addresses, nodep->NodeInfo.SystemImageGUID); + if (mi != cl_qmap_end(&g_allIpv6Addresses)) { + hp = gethostbyaddr((const char *)&sin_addr, sizeof(sin_addr), AF_INET6); + if (g_verbose) { + PrintFunc(&g_dest, "%*s 0x%04x,0x%016"PRIx64",%s,%s:Duplicate\n", + indent, "", + portp->EndPortLID, + nodep->NodeInfo.SystemImageGUID, + (hp) ? hp->h_name : "", + ipString); + } + return FSUCCESS; + } + + // + // add IPv6 address to the global chassis IP list + ipAddrEntryp = (ipv6AddrEntry_t *)MemoryAllocate2AndClear(sizeof(ipv6AddrEntry_t), IBA_MEM_FLAG_PREMPTABLE, MYTAG); + if (ipAddrEntryp == NULL) { + fprintf(stderr, "Error, unable to allocate memory for IP address entry\n"); + return FINSUFFICIENT_MEMORY; + } + + memcpy(&(ipAddrEntryp->ipAddr), &(nodep->pSwitchInfo->SwitchInfoData.IPAddrIPV6), sizeof(ipAddrEntryp->ipAddr)); + + mi = cl_qmap_insert(&g_allIpv6Addresses, nodep->NodeInfo.SystemImageGUID, &ipAddrEntryp->AllIpAddrsEntry); + if (mi != &ipAddrEntryp->AllIpAddrsEntry) { + MemoryDeallocate(ipAddrEntryp); + return FERROR; + } + + // resolve chassis IPv6 address to hostname + hp = gethostbyaddr((const char *)&sin_addr, sizeof(sin_addr), AF_INET6); + if (g_verbose) { + PrintFunc(&g_dest, "%*s 0x%04x,0x%016"PRIx64",%s,%s\n", + indent, "", + portp->EndPortLID, + nodep->NodeInfo.SystemImageGUID, + (hp) ? hp->h_name : "", + ipString); + } else { + PrintFunc(&g_dest, "%*s%s\n", + indent, "", (hp) ? hp->h_name : ipString); + } + + return FSUCCESS; +} + +static FSTATUS chassis_ip_sweep(struct omgt_port *port, FabricData_t *fabric) +{ + FSTATUS fstatus = FSUCCESS; + cl_map_item_t *p; + int i = 0, pc = 0; + uint8_t zeroArray[16]; + memset(zeroArray, 0, sizeof(zeroArray)); + + // search for switches enabled for enhanced port 0 + for (p=cl_qmap_head(&fabric->AllNodes); p != cl_qmap_end(&fabric->AllNodes); p = cl_qmap_next(p), i++) { + cl_map_item_t *q; + NodeData *nodep = PARENT_STRUCT(p, NodeData, AllNodesEntry); + + if (nodep == NULL) + break; + if (nodep->NodeInfo.NodeType == STL_NODE_SW) { + //if (nodep->pSwitchInfo && nodep->pSwitchInfo->SwitchInfoData.u2.s.EnhancedPort0) { + // get node port related information + for (pc=0, q=cl_qmap_head(&nodep->Ports); q != cl_qmap_end(&nodep->Ports); q = cl_qmap_next(q), pc++) { + PortData *portp = PARENT_STRUCT(q, PortData, NodePortsEntry); + + if (portp == NULL) + break; + if (portp->PortNum == 0) { + if(!nodep->pSwitchInfo->SwitchInfoData.u2.s.EnhancedPort0) + break; + + // If the IPv4 Address is not zero process it + if(memcmp(&(nodep->pSwitchInfo->SwitchInfoData.IPAddrIPV4), zeroArray, sizeof(STL_IPV4_IP_ADDR))) { + if(g_verbose) { + char ipString[100]; + memset(ipString, 0, sizeof(ipString)); + + inet_ntop(AF_INET, &(nodep->pSwitchInfo->SwitchInfoData.IPAddrIPV4), ipString, sizeof(ipString)); + print_v4v6_ip_info(ipString); + } + + ipv4_ip_list(nodep, portp); + break; + // If there was no IPv4 address and the IPv6 address is not zero process it + } else if(memcmp(&(nodep->pSwitchInfo->SwitchInfoData.IPAddrIPV6), zeroArray, sizeof(STL_IPV6_IP_ADDR))) { + if(g_verbose) { + char ipString[100]; + memset(ipString, 0, sizeof(ipString)); + + inet_ntop(AF_INET6, &(nodep->pSwitchInfo->SwitchInfoData.IPAddrIPV6), ipString, sizeof(ipString)); + print_v4v6_ip_info(ipString); + } + + ipv6_ip_list(nodep, portp); + break; + } + } + } + } + } + return fstatus; +} + +int main (int argc, char *argv[]) +{ + int rc = 0, c, index; + unsigned long temp; + char *endptr; + FabricData_t fabric; + struct omgt_port *chas_omgt_session; + + Top_setcmdname(APP_NAME); + + // + // process command line arguments + while (-1 != (c = getopt_long(argc,argv, "voh:p:", options, &index))) { + switch (c) { + case 'v': // enable debug logging + g_verbose = 1; + break; + + case 'o': // enable opamgt level debug reporting + g_omgt_debug = 1; + break; + + case '?': // help + usage(); + break; + + case 'h': // hfi to issue query from + errno = 0; + temp = strtoul(optarg, &endptr, 0); + if (temp > IB_UINT8_MAX || errno || ! endptr || *endptr != '\0') { + fprintf(stderr, "Error, invalid HFI Number: %s!\n", optarg); + usage(); + } + g_hfi = (uint8)temp; + break; + + case 'p': // port to issue query from + errno = 0; + temp = strtoul(optarg, &endptr, 0); + if (temp > IB_UINT8_MAX || errno || ! endptr || *endptr != '\0') { + fprintf(stderr, "Error, invalid Port Number: %s!\n", optarg); + usage(); + } + g_port = (uint8)temp; + break; + + default: + fprintf(stderr, "Error, invalid option -%c!\n", c); + usage(); + break; + } + } // end while + + + if (optind < argc) { + usage(); + } + + // catch signals and do orderly shutdown + signal(SIGTERM, signal_handler); + signal(SIGHUP, signal_handler); + signal(SIGINT, signal_handler); + signal(SIGPIPE, signal_handler); + + struct omgt_params params = {.debug_file = g_omgt_debug ? stderr : NULL}; + rc = omgt_open_port_by_num(&chas_omgt_session, g_hfi, g_port, ¶ms); + if (rc) { + fprintf(stderr, "Error, could not open opamgt session (%d).\n",rc); + exit(rc); + } + + if ((rc = omgt_port_get_port_guid(chas_omgt_session, &g_portGuid)) != 0) { + fprintf(stderr, "Error, could not determine PortGuid: %u\n", rc); + } + + InitSweepVerbose(g_verbose?stderr:NULL); + + // sweep fabric for all nodes + if (FSUCCESS != Sweep(g_portGuid, &fabric, FF_NONE, SWEEP_ALL, !g_verbose, RESP_WAIT_TIME)) + fprintf(stderr, "Error, sweep failed!\n"); + else { + // initialize global structures + cl_qmap_init(&g_allIpv4Addresses, NULL); + cl_qmap_init(&g_allIpv6Addresses, NULL); + PrintDestInitFile(&g_dest, stdout); + + // generate chassis IP list + chassis_ip_sweep(chas_omgt_session,&fabric); + } + + // deallocate connections to IB related entities + DestroyMad(); + omgt_close_port(chas_omgt_session); + + exit(0); +} diff --git a/IbaTools/opagenchassis/opagenchassis.sh b/IbaTools/opagenchassis/opagenchassis.sh new file mode 100644 index 0000000..81b3a47 --- /dev/null +++ b/IbaTools/opagenchassis/opagenchassis.sh @@ -0,0 +1,144 @@ +#!/bin/bash +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] + +# Find all the Internally Managed switch chassis in the fabric +# and output their IP(s)/names. +# When possible, the resolver will be used to reverse lookup the TCP/IP name +# and output it instead of the IP address. +# This is accomplished by querying the BMA(s) via opachassisip. + +# optional override of defaults +if [ -f /etc/opa/opafastfabric.conf ] +then + . /etc/opa/opafastfabric.conf +fi + +. /usr/lib/opa/tools/opafastfabric.conf.def + +. /usr/lib/opa/tools/ff_funcs + +trap "exit 1" SIGHUP SIGTERM SIGINT + +gen_chassis() +{ + local suffix + + # $1 = hfi + # $2 = port + if [ "$port" -eq 0 ] + then + port_opts="-h $hfi" # default port to 1st active + else + port_opts="-h $hfi -p $port" + fi + eval /usr/lib/opa/tools/opachassisip $port_opts +} + +Usage_full() +{ + echo "Usage: opagenchassis [-t portsfile] [-p ports]" >&2 + echo " or" >&2 + echo " opagenchassis --help" >&2 + echo " --help - produce full help text" >&2 + echo " -t portsfile - file with list of local HFI ports used to access" >&2 + echo " fabric(s) for analysis, default is $CONFIG_DIR/opa/ports" >&2 + echo " -p ports - list of local HFI ports used to access fabric(s) for analysis" >&2 + echo " default is 1st active port" >&2 + echo " This is specified as hfi:port" >&2 + echo " 0:0 = 1st active port in system" >&2 + echo " 0:y = port y within system" >&2 + echo " x:0 = 1st active port on HFI x" >&2 + echo " x:y = HFI x, port y" >&2 + echo " The first HFI in the system is 1. The first port on an HFI is 1." >&2 + echo " Environment:" >&2 + echo " PORTS - list of ports, used in absence of -t and -p" >&2 + echo " PORTS_FILE - file containing list of ports, used in absence of -t and -p" >&2 + echo "for example:" >&2 + echo " opagenchassis" >&2 + echo " opagenchassis -p '1:1 1:2 2:1 2:2'" >&2 + exit 0 +} + +Usage() +{ + echo "Usage: opagenchassis" >&2 + echo " or" >&2 + echo " opagenchassis --help" >&2 + echo " --help - produce full help text" >&2 + echo "for example:" >&2 + echo " opagenchassis" >&2 + exit 2 +} + +if [ x"$1" = "x--help" ] +then + Usage_full +fi + +status=ok +while getopts p:t: param +do + case $param in + p) export PORTS="$OPTARG";; + t) export PORTS_FILE="$OPTARG";; + ?) Usage;; + esac +done +shift $((OPTIND -1)) +if [ $# -ge 1 ] +then + Usage +fi + +check_ports_args opagenchassis + +for hfi_port in $PORTS +do + hfi=$(expr $hfi_port : '\([0-9]*\):[0-9]*') + port=$(expr $hfi_port : '[0-9]*:\([0-9]*\)') + /usr/sbin/oparesolvehfiport $hfi $port >/dev/null + if [ $? -ne 0 -o "$hfi" = "" -o "$port" = "" ] + then + echo "opagenchassis: Error: Invalid port specification: $hfi_port" >&2 + status=bad + continue + fi + + gen_chassis "$hfi" "$port" +done + +if [ "$status" != "ok" ] +then + exit 1 +else + exit 0 +fi diff --git a/IbaTools/opagenesmchassis/Makefile b/IbaTools/opagenesmchassis/Makefile new file mode 100644 index 0000000..a0ea133 --- /dev/null +++ b/IbaTools/opagenesmchassis/Makefile @@ -0,0 +1,162 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** +# Makefile for opagenesmchassis + +# Include Make Control Settings +include $(TL_DIR)/$(PROJ_FILE_DIR)/Makesettings.project + +#=============================================================================# +# Definitions: +#-----------------------------------------------------------------------------# + +# Name of SubProjects +DS_SUBPROJECTS = +# name of executable or downloadable image +EXECUTABLE = #$(BUILDDIR)/opagenesmchassis$(EXE_SUFFIX) +# list of sub directories to build +DIRS = +# C files (.c) +CFILES = \ + # Add more c files here +# C++ files (.cpp) +CCFILES = \ + # Add more cpp files here +# lex files (.lex) +LFILES = \ + # Add more lex files here +# archive library files (basename, $ARFILES will add MOD_LIB_DIR/prefix and suffix) +LIBFILES= +# Windows Resource Files (.rc) +RSCFILES = +# Windows IDL File (.idl) +IDLFILE = +# Windows Linker Module Definitions (.def) file for dll's +DEFFILE = +# targets to build during INCLUDES phase (add public includes here) +INCLUDE_TARGETS = \ + # Add more h hpp files here +# Non-compiled files +MISC_FILES = +# all source files +SOURCES = $(CFILES) $(CCFILES) $(LFILES) $(RSCFILES) $(IDLFILE) +# Source files to include in DSP File +DSP_SOURCES = $(INCLUDE_TARGETS) $(SOURCES) $(MISC_FILES) \ + $(RSCFILES) $(DEFFILE) $(MAKEFILE) +# all object files +OBJECTS = $(CFILES:.c=$(OBJ_SUFFIX)) $(CCFILES:.cpp=$(OBJ_SUFFIX)) \ + $(LFILES:.lex=$(OBJ_SUFFIX)) +RSCOBJECTS = $(RSCFILES:.rc=$(RES_SUFFIX)) +# targets to build during LIBS phase +LIB_TARGETS_IMPLIB = +LIB_TARGETS_ARLIB = # $(LIB_PREFIX)ResourceTest$(ARLIB_SUFFIX) +LIB_TARGETS_EXP = $(LIB_TARGETS_IMPLIB:$(ARLIB_SUFFIX)=$(EXP_SUFFIX)) +LIB_TARGETS_MISC = +# targets to build during CMDS phase +CMD_TARGETS_SHLIB = +CMD_TARGETS_EXE = $(EXECUTABLE) +CMD_TARGETS_MISC = opagenesmchassis +# files to remove during clean phase +CLEAN_TARGETS_MISC = +CLEAN_TARGETS = $(OBJECTS) $(RSCOBJECTS) $(IDL_TARGETS) $(CLEAN_TARGETS_MISC) +# other files to remove during clobber phase +CLOBBER_TARGETS_MISC= +# sub-directory to install to within bin +BIN_SUBDIR = +# sub-directory to install to within include +INCLUDE_SUBDIR = + +# Additional Settings +#CLOCALDEBUG = User defined C debugging compilation flags [Empty] +#CCLOCALDEBUG = User defined C++ debugging compilation flags [Empty] +#CLOCAL = User defined C flags for compiling [Empty] +#CCLOCAL = User defined C++ flags for compiling [Empty] +#BSCLOCAL = User flags for Browse File Builder [Empty] +#DEPENDLOCAL = user defined makedepend flags [Empty] +#LINTLOCAL = User defined lint flags [Empty] +#LOCAL_INCLUDE_DIRS = User include directories to search for C/C++ headers [Empty] +#LDLOCAL = User defined C flags for linking [Empty] +#IMPLIBLOCAL = User flags for Object Lirary Manager [Empty] +#MIDLLOCAL = User flags for IDL compiler [Empty] +#RSCLOCAL = User flags for resource compiler [Empty] +#LOCALDEPLIBS = User libraries to include in dependencies [Empty] +#LOCALLIBS = User libraries to use when linking [Empty] +# (in addition to LOCALDEPLIBS) +#LOCAL_LIB_DIRS = User library directories for libpaths [Empty] + +CLOCAL=$(CIBACCESS) $(CPIE) +LOCAL_INCLUDE_DIRS= +ifeq "$(IB_STACK)" "IBACCESS" +LOCALDEPLIBS=$(IBACCESS_USER_LIBS)IbPrint +LOCALLIBS= +LOCAL_LIB_DIRS=$(IBACCESS_USER_LIB_DIRS) +else +LOCALDEPLIBS=$(IBACCESS_USER_LIBS) IbPrint opamgt-priv +LOCALLIBS=$(OPENIB_USER_LIBS) +LOCAL_LIB_DIRS=$(OPENIB_USER_LIB_DIRS) $(IBACCESS_USER_LIB_DIRS) +endif + +# Include Make Rules definitions and rules +include $(TL_DIR)/IbaTools/Makerules.module + +#=============================================================================# +# Overrides: +#-----------------------------------------------------------------------------# +#CCOPT = # C++ optimization flags, default lets build config decide +#COPT = # C optimization flags, default lets build config decide +#SUBSYSTEM = Subsystem to build for (none, console or windows) [none] +# (Windows Only) +#USEMFC = How Windows MFC should be used (none, static, shared, no_mfc) [none] +# (Windows Only) +#=============================================================================# + +#=============================================================================# +# Rules: +#-----------------------------------------------------------------------------# +# process Sub-directories +include $(TL_DIR)/Makerules/Maketargets.toplevel + +# build cmds and libs +include $(TL_DIR)/Makerules/Maketargets.build + +# install for includes, libs and cmds phases +include $(TL_DIR)/Makerules/Maketargets.install + +# install for stage phase +#include $(TL_DIR)/Makerules/Maketargets.stage +STAGE:: + $(VS)$(STAGE_INSTALL) $(STAGE_INSTALL_DIR_OPT) $(PROJ_STAGE_FASTFABRIC_DIR) opagenesmchassis + +# Unit test execution +#include $(TL_DIR)/Makerules/Maketargets.runtest + +#=============================================================================# + +#=============================================================================# +# DO NOT DELETE THIS LINE -- make depend depends on it. +#=============================================================================# diff --git a/IbaTools/opagenesmchassis/opagenesmchassis.sh b/IbaTools/opagenesmchassis/opagenesmchassis.sh new file mode 100755 index 0000000..4127bed --- /dev/null +++ b/IbaTools/opagenesmchassis/opagenesmchassis.sh @@ -0,0 +1,162 @@ +#!/bin/bash +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] + +# Call opagenchassis and iterate through the list of chassis to +# generate esm_chassis file by finding out all chassis where embedded +# subnet manager is running. + +# optional override of defaults +if [ -f /etc/opa/opafastfabric.conf ] +then + . /etc/opa/opafastfabric.conf +fi + +. /usr/lib/opa/tools/opafastfabric.conf.def + +. /usr/lib/opa/tools/ff_funcs + +trap "exit 1" SIGHUP SIGTERM SIGINT + +Usage_full() +{ + echo "Usage: opagenesmchassis [-u user] [-S] [-t portsfile] [-p ports]" >&2 + echo " or" >&2 + echo " opagenesmchassis --help" >&2 + echo " --help - produce full help text" >&2 + echo " -u user - user to perform cmd as" >&2 + echo " for chassis default is admin" >&2 + echo " -S - securely prompt for password for user on chassis" >&2 + echo " -t portsfile - file with list of local HFI ports used to access" >&2 + echo " fabric(s) for analysis, default is $CONFIG_DIR/opa/ports" >&2 + echo " -p ports - list of local HFI ports used to access fabric(s) for analysis" >&2 + echo " default is 1st active port" >&2 + echo " This is specified as hfi:port" >&2 + echo " 0:0 = 1st active port in system" >&2 + echo " 0:y = port y within system" >&2 + echo " x:0 = 1st active port on HFI x" >&2 + echo " x:y = HFI x, port y" >&2 + echo " The first HFI in the system is 1. The first port on an HFI is 1." >&2 + echo " Environment:" >&2 + echo " FF_CHASSIS_ADMIN_PASSWORD - password for chassis, used in absence of -S" >&2 + echo " PORTS - list of ports, used in absence of -t and -p" >&2 + echo " PORTS_FILE - file containing list of ports, used in absence of -t and -p" >&2 + echo "for example:" >&2 + echo " opagenesmchassis" >&2 + echo " opagenesmchassis -S -p '1:1 1:2 2:1 2:2'" >&2 + exit 0 +} + +Usage() +{ + echo "Usage: opagenesmchassis [-u user] [-S]" >&2 + echo " or" >&2 + echo " opagenesmchassis --help" >&2 + echo " --help - produce full help text" >&2 + echo " -u user - user to perform cmd as" >&2 + echo " for chassis default is admin" >&2 + echo " -S - securely prompt for password for user on chassis" >&2 + echo "for example:" >&2 + echo " opagenesmchassis" >&2 + echo " opagenesmchassis -S " >&2 + exit 2 +} + +if [ x"$1" = "x--help" ] +then + Usage_full +fi + + +status=ok +user=`id -u -n` +uopt=n +Sopt=n +while getopts p:t:u:S param +do + case $param in + p) export PORTS="$OPTARG";; + t) export PORTS_FILE="$OPTARG";; + u) uopt=y + user="$OPTARG";; + S) Sopt=y;; + ?) Usage;; + esac +done +shift $((OPTIND -1)) +if [ $# -ge 1 ] +then + Usage +fi + +check_ports_args opagenesmchassis + +if [ "$uopt" = n ] +then + user=admin +fi +for chassis in `/usr/sbin/opagenchassis`; +do + if [ "$Sopt" = y ] + then + chassis_cmd=`/usr/sbin/opacmdall -C -H $chassis -u $user -S 'smControl status' 2>&1` + else + chassis_cmd=`/usr/sbin/opacmdall -C -H $chassis -u $user 'smControl status' 2>&1` + fi + + if [ $? != 0 ] + then + status=bad + elif grep -q "FAILED" <<<$chassis_cmd + then + status=bad + elif grep -q "not started" <<<$chassis_cmd + then + status=bad + elif grep -q "stopped" <<<$chassis_cmd + then + status=bad + elif grep -q "not licensed" <<<$chassis_cmd + then + status=ok + else + echo "$chassis" + status=ok + fi + +done + +if [ "$status" != "ok" ] +then + exit 1 +else + exit 0 +fi diff --git a/IbaTools/opagenswitches/Makefile b/IbaTools/opagenswitches/Makefile new file mode 100644 index 0000000..28c9d00 --- /dev/null +++ b/IbaTools/opagenswitches/Makefile @@ -0,0 +1,163 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** +# Makefile for opagenswitches + +# Include Make Control Settings +include $(TL_DIR)/$(PROJ_FILE_DIR)/Makesettings.project + +#=============================================================================# +# Definitions: +#-----------------------------------------------------------------------------# + +# Name of SubProjects +DS_SUBPROJECTS = +# name of executable or downloadable image +EXECUTABLE = $(BUILDDIR)/opagenswitcheshelper$(EXE_SUFFIX) +# list of sub directories to build +DIRS = +# C files (.c) +CFILES = \ + opagenswitcheshelper.c \ + # Add more c files here +# C++ files (.cpp) +CCFILES = \ + # Add more cpp files here +# lex files (.lex) +LFILES = \ + # Add more lex files here +# archive library files (basename, $ARFILES will add MOD_LIB_DIR/prefix and suffix) +LIBFILES= +# Windows Resource Files (.rc) +RSCFILES = +# Windows IDL File (.idl) +IDLFILE = +# Windows Linker Module Definitions (.def) file for dll's +DEFFILE = +# targets to build during INCLUDES phase (add public includes here) +INCLUDE_TARGETS = \ + # Add more h hpp files here +# Non-compiled files +MISC_FILES = +# all source files +SOURCES = $(CFILES) $(CCFILES) $(LFILES) $(RSCFILES) $(IDLFILE) +# Source files to include in DSP File +DSP_SOURCES = $(INCLUDE_TARGETS) $(SOURCES) $(MISC_FILES) \ + $(RSCFILES) $(DEFFILE) $(MAKEFILE) +# all object files +OBJECTS = $(CFILES:.c=$(OBJ_SUFFIX)) $(CCFILES:.cpp=$(OBJ_SUFFIX)) \ + $(LFILES:.lex=$(OBJ_SUFFIX)) +RSCOBJECTS = $(RSCFILES:.rc=$(RES_SUFFIX)) +# targets to build during LIBS phase +LIB_TARGETS_IMPLIB = +LIB_TARGETS_ARLIB = # $(LIB_PREFIX)ResourceTest$(ARLIB_SUFFIX) +LIB_TARGETS_EXP = $(LIB_TARGETS_IMPLIB:$(ARLIB_SUFFIX)=$(EXP_SUFFIX)) +LIB_TARGETS_MISC = +# targets to build during CMDS phase +CMD_TARGETS_SHLIB = +CMD_TARGETS_EXE = $(EXECUTABLE) +CMD_TARGETS_MISC = opagenswitches +# files to remove during clean phase +CLEAN_TARGETS_MISC = +CLEAN_TARGETS = $(OBJECTS) $(RSCOBJECTS) $(IDL_TARGETS) $(CLEAN_TARGETS_MISC) +# other files to remove during clobber phase +CLOBBER_TARGETS_MISC= +# sub-directory to install to within bin +BIN_SUBDIR = +# sub-directory to install to within include +INCLUDE_SUBDIR = + +# Additional Settings +#CLOCALDEBUG = User defined C debugging compilation flags [Empty] +#CCLOCALDEBUG = User defined C++ debugging compilation flags [Empty] +#CLOCAL = User defined C flags for compiling [Empty] +#CCLOCAL = User defined C++ flags for compiling [Empty] +#BSCLOCAL = User flags for Browse File Builder [Empty] +#DEPENDLOCAL = user defined makedepend flags [Empty] +#LINTLOCAL = User defined lint flags [Empty] +#LOCAL_INCLUDE_DIRS = User include directories to search for C/C++ headers [Empty] +#LDLOCAL = User defined C flags for linking [Empty] +#IMPLIBLOCAL = User flags for Object Lirary Manager [Empty] +#MIDLLOCAL = User flags for IDL compiler [Empty] +#RSCLOCAL = User flags for resource compiler [Empty] +#LOCALDEPLIBS = User libraries to include in dependencies [Empty] +#LOCALLIBS = User libraries to use when linking [Empty] +# (in addition to LOCALDEPLIBS) +#LOCAL_LIB_DIRS = User library directories for libpaths [Empty] + +CLOCAL=$(CIBACCESS) $(CPIE) +LOCAL_INCLUDE_DIRS= +ifeq "$(IB_STACK)" "IBACCESS" +LOCALDEPLIBS=$(IBACCESS_USER_LIBS) IbPrint +LOCALLIBS= +LOCAL_LIB_DIRS=$(IBACCESS_USER_LIB_DIRS) +else +LOCALDEPLIBS=$(IBACCESS_USER_LIBS) IbPrint opamgt-priv +LOCALLIBS=$(OPENIB_USER_LIBS) +LOCAL_LIB_DIRS=$(OPENIB_USER_LIB_DIRS) $(IBACCESS_USER_LIB_DIRS) +endif + +# Include Make Rules definitions and rules +include $(TL_DIR)/IbaTools/Makerules.module + +#=============================================================================# +# Overrides: +#-----------------------------------------------------------------------------# +#CCOPT = # C++ optimization flags, default lets build config decide +#COPT = # C optimization flags, default lets build config decide +#SUBSYSTEM = Subsystem to build for (none, console or windows) [none] +# (Windows Only) +#USEMFC = How Windows MFC should be used (none, static, shared, no_mfc) [none] +# (Windows Only) +#=============================================================================# + +#=============================================================================# +# Rules: +#-----------------------------------------------------------------------------# +# process Sub-directories +include $(TL_DIR)/Makerules/Maketargets.toplevel + +# build cmds and libs +include $(TL_DIR)/Makerules/Maketargets.build + +# install for includes, libs and cmds phases +include $(TL_DIR)/Makerules/Maketargets.install + +# install for stage phase +#include $(TL_DIR)/Makerules/Maketargets.stage +STAGE:: + $(VS)$(STAGE_INSTALL) $(STAGE_INSTALL_DIR_OPT) $(PROJ_STAGE_FASTFABRIC_DIR) $(EXECUTABLE) $(CMD_TARGETS_MISC) + +# Unit test execution +#include $(TL_DIR)/Makerules/Maketargets.runtest + +#=============================================================================# + +#=============================================================================# +# DO NOT DELETE THIS LINE -- make depend depends on it. +#=============================================================================# diff --git a/IbaTools/opagenswitches/opagenswitches.sh b/IbaTools/opagenswitches/opagenswitches.sh new file mode 100644 index 0000000..bbef890 --- /dev/null +++ b/IbaTools/opagenswitches/opagenswitches.sh @@ -0,0 +1,766 @@ +#!/bin/bash +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] + +# query the SM via opareport and generate a switches file listing all the +# Externally Managed SilverStorm switches found in the fabric. + +# Enhancements: optionally, do not generate an switches file, but use an existing +# switches file; optionally, update NodeDesc values in an switches file using +# NodeDesc values found in a specified topology.xml file and fabric link +# information obtained via opareport -o links (live fabric or snapshot). + + +# optional override of defaults +if [ -f /etc/opa/opafastfabric.conf ] +then + . /etc/opa/opafastfabric.conf +fi + +. /usr/lib/opa/tools/opafastfabric.conf.def + +. /usr/lib/opa/tools/ff_funcs + +## Defines: +OPAEXPAND_FILE="/usr/sbin/opaexpandfile" +OPA_REPORT="/usr/sbin/opareport" +OPASAQUERY="/usr/sbin/opasaquery" +XML_EXTRACT="/usr/sbin/opaxmlextract" +GEN_OPASWITCHES_HELPER="/usr/lib/opa/tools/opagenswitcheshelper" +FILE_OPASWITCHES=$(mktemp "opagensw-file_switches-XXXX") +FILE_OPASWITCHES2=$(mktemp "opagensw-file_switches2-XXXX") +FILE_LINKSUM_LEAF_EDGE=$(mktemp "opagensw-linksum_leaf_edge-XXXX.csv") +FILE_LINKSUM_EDGE_HFI=$(mktemp "opagensw-linksum_edge_hfi-XXXX.csv") +FILE_LINKS_LEAF_EDGE=$(mktemp "opagensw-links_leaf_edge-XXXX.csv") +FILE_LINKS_LEAF_EDGE2=$(mktemp "opagensw-links_leaf_edge2-XXXX.csv") +FILE_LINKS_EDGE_HFI=$(mktemp "opagensw-links_edge_hfi-XXXX.csv") +FILE_LINKS_EDGE_HFI2=$(mktemp "opagensw-links_edge_hfi2-XXXX.csv") +FILE_TEMP=$(mktemp "opagensw-1-XXXX") +FILE_TEMP2=$(mktemp "opagensw-2-XXXX") + +## Global variables: + +# Operating variables: +n_verbose=0 +fl_clean=1 +fl_gen_switches=1 +fl_gen_linksum=0 +fl_write_switches=0 +file_switches="$FILE_OPASWITCHES" +file_output="" +file_topology="" +file_snapshot="" +nodeguid1= +portnum1= +nodetype1= +nodedesc1= +nodesuffix1= +nodeguid1b= +portnum1b= +nodetype1b= +nodedesc1b= +nodesuffix1b= +nodeguid2= +portnum2= +nodetype2= +nodedesc2= +nodesuffix2= +nodeguid2b= +portnum2b= +nodetype2b= +nodedesc2b= +nodesuffix2b= +nodedesc_last= +line= +line1= +line2= +n_hfis=0 +hfis= +n_edges=0 +n_edges2=0 +n_edges2b=0 +edges= +n_edges_unique=0 +edges_unique= +n_leaves=0 +n_leaves2=0 +n_leaves2b=0 +leaves= +n_leaves_unique=0 +leaves_unique= + +# Debug variables: +debug_0= +debug_1= +debug_2= +debug_3= +debug_4= +debug_5= +debug_6= +debug_7= +#echo "DEBUG-x.y: 0:$debug_0: 1:$debug_1: 2:$debug_2: 3:$debug_3: 4:$debug_4: 5:$debug_5: 6:$debug_6: 7:$debug_7:" + + +## Local functions: +functout= + +# Clean temporary files +clean_files() +{ + if [ $fl_clean == 1 ] + then + rm -f $FILE_TEMP + rm -f $FILE_TEMP2 + rm -f $FILE_OPASWITCHES + rm -f $FILE_OPASWITCHES2 + rm -f $FILE_LINKSUM_LEAF_EDGE + rm -f $FILE_LINKSUM_EDGE_HFI + rm -f $FILE_LINKS_LEAF_EDGE + rm -f $FILE_LINKS_LEAF_EDGE2 + rm -f $FILE_LINKS_EDGE_HFI + rm -f $FILE_LINKS_EDGE_HFI2 + fi +} # End of clean_files() + +trap 'clean_files; exit 1' SIGINT SIGHUP SIGTERM +trap clean_files EXIT + +Usage_full() +{ + echo "Usage: opagenswitches [-t portsfile] [-p ports] [-R]" >&2 + echo " [-L switches_file] [-o output_file] [-T topology_file] [-X snapshot_file]" >&2 + echo " [-s] [-v level] [-K]" >&2 + echo " or" >&2 + echo " opagenswitches --help" >&2 + echo " --help - produce full help text" >&2 + echo " -t portsfile - file with list of local HFI ports used to access" >&2 + echo " fabric(s) for analysis, default is $CONFIG_DIR/opa/ports" >&2 + echo " -p ports - list of local HFI ports used to access fabric(s) for analysis" >&2 + echo " default is 1st active port" >&2 + echo " This is specified as hfi:port" >&2 + echo " 0:0 = 1st active port in system" >&2 + echo " 0:y = port y within system" >&2 + echo " x:0 = 1st active port on HFI x" >&2 + echo " x:y = HFI x, port y" >&2 + echo " The first HFI in the system is 1. The first port on an HFI is 1." >&2 + echo " -R - do not attempt to get routes for computation of distance" >&2 + echo " -s - update/resolve switches switch names using topology XML data" >&2 + echo " -L switches_file - use switches_file as switches input" >&2 + echo " (do not generate switches data; must also use -s)" >&2 + echo " -o output_file - write switches data to output_file (default is stdout)" >&2 + echo " -T topology_file - use topology_file as topology XML" >&2 + echo " (may contain '%P'; must also use -s)" >&2 + echo " -X snapshot_file - use snapshot_file XML for fabric link information" >&2 + echo " (may contain '%P'; must also use -s)" >&2 + echo " -v level - verbose level (0-8, default 0)" >&2 + echo " 0 - no output" >&2 + echo " 1 - progress output" >&2 + echo " 2 - reserved" >&2 + echo " 4 - time stamps" >&2 + echo " 8 - reserved" >&2 + echo " -K - do not clean temporary files" >&2 + echo " Environment:" >&2 + echo " PORTS - list of ports, used in absence of -t and -p" >&2 + echo " PORTS_FILE - file containing list of ports, used in absence of -t and -p" >&2 + echo " FF_TOPOLOGY_FILE - file containing topology XML data, used in absence of -T" >&2 + echo "for example:" >&2 + echo " opagenswitches" >&2 + echo " opagenswitches -p '1:1 1:2 2:1 2:2'" >&2 + echo " opagenswitches -o switches" >&2 + echo " opagenswitches -s -o switches" >&2 + echo " opagenswitches -L switches -s -o switches" >&2 + echo " opagenswitches -s -T topology.%P.xml" >&2 + echo " opagenswitches -L switches -s -T topology.%P.xml -X snapshot.%P.xml" >&2 + exit 0 +} # End of Usage_full() + +Usage() +{ + echo "Usage: opagenswitches [-R] [-s] [-T topology_file]" >&2 + echo " or" >&2 + echo " opagenswitches --help" >&2 + echo " -R - do not attempt to get routes for computation of distance" >&2 + echo " -s - update/resolve switches switch names using topology XML data" >&2 + echo " -T topology_file - use topology_file as topology XML" >&2 + echo " --help - produce full help text" >&2 + echo "for example:" >&2 + echo " opagenswitches" >&2 + echo " opagenswitches -T topology.0:0.xml" >&2 + exit 2 +} # End of Usage() + +# Display progress information (to STDOUT) +# Inputs: +# $1 - progress string +# +# Outputs: +# none +display_progress() +{ + if [ $n_verbose -ge 1 ] + then + echo "$1" >&2 + if [ $n_verbose -ge 4 ] + then + echo " "`date +"%F %T (%N nSec)"` >&2 + fi + fi +} # End of display_progress() + +gen_switches() +{ + local suffix + + # $1 = hfi + # $2 = port + if [ "$port" -eq 0 ] + then + port_opts="-h $hfi" # default port to 1st active + else + port_opts="-h $hfi -p $port" + fi + + eval $OPASAQUERY $port_opts -o desc >/dev/null 2>&1 + if [ $? -ne 0 ] + then + echo "opagenswitches: Error: Fabric Nodes Not Available at hfi:$hfi port:$port" >&2 + return + fi + suffix=":$hfi:$port" + export IFS=';' + rm -f $FILE_TEMP + eval $OPA_REPORT $port_opts -q -o comps -x -F nodetype:SW:port:0 -d 4| $XML_EXTRACT -H -d \; -e Node.LID -e Node.NodeGUID -e Node.SystemImageGUID -e Node.Capability -e Node.PortInfo.Capability -e Node.NodeDesc -e Node.PortInfo.GUID -s Focus > $FILE_TEMP + if [ $? -eq 0 ] + then + fl_write_switches=1 + cat $FILE_TEMP | while read lid nodeguid systemguid capability portcapability nodedesc portguid + do + if [[ ! $portcapability =~ "VDR" ]]; then + continue + fi + + distance= + comma= + if [ "$get_distance" = y ] + then + # Use lid to handle LMC != 0 case + distance=$(eval opasaquery $port_opts -o trace -l $lid | grep "NodeType: SW" | wc -l) + if [ ! -z "$distance" ] + then + comma="," + fi + fi + + # valid names for switches start with a non-numeric and are alpha numeric + if [[ $nodedesc =~ ^[a-zA-Z_][a-zA-Z_0-9]*$ ]] + then + echo "$nodeguid$suffix,$nodedesc$comma$distance" >> $file_switches + else + echo "# $nodedesc" >> $file_switches + echo "$nodeguid$suffix$comma$comma$distance" >> $file_switches + fi + done # End of while read nodeguid systemguid capability nodedesc portguid + else + echo "opagenswitches: Error: Unable to Query Fabric Nodes at hfi:$hfi port:$port" >&2 + fi + +} # End of gen_switches() + +# Resolve name of switches file +# Inputs: +# $1 - command name +# OPASWITCHES_FILE - switches file name to process +# +# Outputs: +# OPASWITCHES_FILE - resolved switches file name +resolve_switches_file() +{ + if [ "$OPASWITCHES_FILE" = "" ] + then + OPASWITCHES_FILE=$CONFIG_DIR/opa/switches + fi + OPASWITCHES_FILE=`resolve_file "$1" "$OPASWITCHES_FILE"` + if [ "$OPASWITCHES_FILE" = "" ] + then + Usage + fi + +} # End of resolve_switches_file() + +# Resolve name of snapshot file, including %P +# Inputs: +# $1 - command name +# $2 - hfi:port fabric selector (0:0, 1:2, etc) +# FF_SNAPSHOT_FILE - snapshot file name to process +# +# Outputs: +# SNAPSHOT_FILE - resolved snapshot file name +resolve_snapshot_file() +{ + if [ "$FF_SNAPSHOT_FILE" = "" -o "$FF_SNAPSHOT_FILE" = "NONE" ] + then + SNAPSHOT_FILE="" + # snapshot check disabled + return + fi + # Expand %P marker + file=$(echo "$FF_SNAPSHOT_FILE"|sed -e "s/%P/$2/g") + # allow case where FF_SNAPSHOT_FILE is not found (ignore stderr) + SNAPSHOT_FILE=`resolve_file "$1" "$file" 2>/dev/null` + +} # End of resolve_snapshot_file() + + +## Main function: +rm -f $FILE_OPASWITCHES +rm -f $FILE_OPASWITCHES2 +rm -f $FILE_DEBUG +rm -f $FILE_DEBUG2 + +if [ x"$1" = "x--help" ] +then + Usage_full +fi + +get_distance=y +while getopts KL:o:p:Rst:T:v:X: param +do + case $param in + K) fl_clean=0;; + L) fl_gen_switches=0 + fl_write_switches=1 + file_switches="$OPTARG" + if [ ! -f "$file_switches" ] + then + echo "opagenswitches: Error: switches file $file_switches does not exist" >&2 + Usage + fi + ;; + o) file_output="$OPTARG";; + p) export PORTS="$OPTARG";; + R) get_distance=n;; + s) fl_gen_linksum=1;; + t) export PORTS_FILE="$OPTARG";; + T) file_topology="$OPTARG";; + v) n_verbose=$OPTARG;; + X) file_snapshot="$OPTARG";; + ?) Usage;; + esac +done + +shift $((OPTIND -1)) +if [ $# -ge 1 ] +then + Usage +fi + +check_ports_args opagenswitches +if [ $fl_gen_switches == 0 -o "x$file_topology" != "x" -o "x$file_snapshot" != "x" ] + then + if [ $fl_gen_linksum == 0 ] + then + echo "opagenswitches: Error: -L, -T and -X must also use -s" >&2 + Usage + fi +fi + +# Generate file_switches +if [ $fl_gen_switches == 1 ] + then + echo -n "" > $file_switches + + IFS=$' \t\n' + for hfi_port in $PORTS + do + hfi=$(expr $hfi_port : '\([0-9]*\):[0-9]*') + port=$(expr $hfi_port : '[0-9]*:\([0-9]*\)') + /usr/sbin/oparesolvehfiport $hfi $port >/dev/null + if [ $? -ne 0 -o "$hfi" = "" -o "$port" = "" ] + then + echo "opagenswitches: Error: Invalid port specification: $hfi_port" >&2 + continue + fi + + display_progress "Generating switches hfi:$hfi port:$port" + gen_switches "$hfi" "$port" + done +else + OPASWITCHES_FILE=$file_switches + resolve_switches_file "opagenswitches" + cp -p $OPASWITCHES_FILE $FILE_OPASWITCHES + + # Check FILE_OPASWITCHES for include lines + if cat $FILE_OPASWITCHES | grep include >/dev/null 2>&1 + then + echo "opagenswitches: Warning: $OPASWITCHES_FILE contains non-processed include statement(s)" >&2 + fi +fi # End of if [ $fl_gen_switches == 1 ] + +# Process $file_topology +if [ $fl_write_switches == 1 -a $fl_gen_linksum == 1 ] + then + IFS=$' \t\n' + for hfi_port in $PORTS + do + hfi=$(expr $hfi_port : '\([0-9]*\):[0-9]*') + port=$(expr $hfi_port : '[0-9]*:\([0-9]*\)') + /usr/sbin/oparesolvehfiport $hfi $port >/dev/null + if [ $? -ne 0 -o "$hfi" = "" -o "$port" = "" ] + then + echo "opagenswitches: Error: Invalid port specification: $hfi_port" >&2 + continue + fi + + if [ -n "$file_topology" ] + then + FF_TOPOLOGY_FILE=$file_topology + fi + resolve_topology_file "opagenswitches" "$hfi:$port" + if [ -f "$TOPOLOGY_FILE" ] + then + IFS=";" + + # Generate FILE_LINKSUM(s) from TOPOLOGY_FILE + display_progress "Reading $TOPOLOGY_FILE and Generating FILE_LINKSUM Components" + rm -f $FILE_LINKSUM_LEAF_EDGE + rm -f $FILE_LINKSUM_EDGE_HFI + ix=0 + rm -f $FILE_TEMP + cat $TOPOLOGY_FILE | $XML_EXTRACT -H -d \; -e Link.Port.PortNum -e Link.Port.NodeType -e Link.Port.NodeDesc > $FILE_TEMP + $GEN_OPASWITCHES_HELPER proc_linksum $FILE_TEMP $FILE_LINKSUM_EDGE_HFI $FILE_LINKSUM_LEAF_EDGE + + if [ -s $FILE_LINKSUM_LEAF_EDGE ] + then + display_progress "Processing $FILE_LINKSUM_LEAF_EDGE" + rm -f $FILE_TEMP + mv $FILE_LINKSUM_LEAF_EDGE $FILE_TEMP + cat $FILE_TEMP | sort -t \; -k3,3 -k1g,1 -k4g,4 > $FILE_LINKSUM_LEAF_EDGE + fi + + if [ -s $FILE_LINKSUM_EDGE_HFI ] + then + display_progress "Processing $FILE_LINKSUM_EDGE_HFI" + rm -f $FILE_TEMP + mv $FILE_LINKSUM_EDGE_HFI $FILE_TEMP + cat $FILE_TEMP | sort -t \; -k3,3 -k1g,1 -k4g,4 > $FILE_LINKSUM_EDGE_HFI + fi + + # Generate GUID/NodeDesc links files + display_progress "Generating links report and FILE_LINKS Components" + rm -f $FILE_LINKS_LEAF_EDGE + rm -f $FILE_LINKS_EDGE_HFI + ix=0 + + if [ -z "$file_snapshot" ] + then + if [ "$port" -eq 0 ] + then + port_opts="-h $hfi" # default port to 1st active + else + port_opts="-h $hfi -p $port" + fi + eval $OPASAQUERY $port_opts -o desc >/dev/null 2>&1 + if [ $? -ne 0 ] + then + echo "opagenswitches: Error: Fabric Links Not Available at hfi:$hfi port:$port" >&2 + continue + fi + else + FF_SNAPSHOT_FILE=$file_snapshot + resolve_snapshot_file "opagenswitches" "$hfi:$port" + if [ ! -f "$SNAPSHOT_FILE" ] + then + echo "opagenswitches: Error: snapshot file $SNAPSHOT_FILE does not exist" >&2 + continue + fi + port_opts="-X $SNAPSHOT_FILE" + fi + + rm -f $FILE_TEMP + eval $OPA_REPORT $port_opts -q -x -o links | $XML_EXTRACT -H -d \; -e NodeGUID -e PortNum -e NodeType -e NodeDesc > $FILE_TEMP + if [ $? -eq 0 ] + then + $GEN_OPASWITCHES_HELPER proc_links $FILE_TEMP $FILE_LINKS_EDGE_HFI $FILE_LINKS_LEAF_EDGE + + if [ -s $FILE_LINKS_LEAF_EDGE ] + then + display_progress "Processing $FILE_LINKS_LEAF_EDGE" + rm -f $FILE_TEMP + mv $FILE_LINKS_LEAF_EDGE $FILE_TEMP + cat $FILE_TEMP | sort -t \; -k4,4 -k2g,2 -k5g,5 > $FILE_LINKS_LEAF_EDGE + fi # End of if [ -s $FILE_LINKS_LEAF_EDGE ] + + if [ -s $FILE_LINKS_EDGE_HFI ] + then + display_progress "Processing $FILE_LINKS_EDGE_HFI" + rm -f $FILE_TEMP + mv $FILE_LINKS_EDGE_HFI $FILE_TEMP + cat $FILE_TEMP | sort -t \; -k4,4 -k2g,2 -k5g,5 > $FILE_LINKS_EDGE_HFI + fi # End of if [ -s $FILE_LINKS_EDGE_HFI ] + + # Process NodeDesc in links files + rm -f $FILE_LINKS_LEAF_EDGE2 + rm -f $FILE_LINKS_EDGE_HFI2 + + if [ -s $FILE_LINKS_LEAF_EDGE ] + then + cp -p $FILE_LINKS_LEAF_EDGE $FILE_LINKS_LEAF_EDGE2 + fi + if [ -s $FILE_LINKS_EDGE_HFI ] + then + cp -p $FILE_LINKS_EDGE_HFI $FILE_LINKS_EDGE_HFI2 + fi + + # Process edge NodeDesc + if [ -s $FILE_LINKS_EDGE_HFI2 ] + then + display_progress "Processing edge NodeDesc" + + ix_line=1 + nodedesc_last="ZzQQQzZ" + + while read portnum1 nodetype1 nodedesc1 portnum1b nodetype1b nodedesc1b + do + if [ "$nodedesc1" != "$nodedesc_last" ] + then + n_hfis=`cat $FILE_LINKSUM_EDGE_HFI | grep "$nodedesc1;" | wc -l` + hfis=`cat $FILE_LINKSUM_EDGE_HFI | grep "$nodedesc1;" | cut -d \; -f6 | tr '\012' '|' | sed -e 's/|/$|/g' -e 's/|$//'` + n_edges=`cat $FILE_LINKS_EDGE_HFI2 | grep -E "$hfis" | wc -l` + n_edges_unique=`cat $FILE_LINKS_EDGE_HFI2 | grep -E "$hfis" | cut -d \; -f4 | sort -u | wc -l` +# ToDo: may be able to eliminate $edges + edges=`cat $FILE_LINKS_EDGE_HFI2 | grep -E "$hfis" | cut -d \; -f4` + edges_unique=`cat $FILE_LINKS_EDGE_HFI2 | grep -E "$hfis" | cut -d \; -f4 | sort -u` + if [ $n_edges_unique == 1 ] + then + nodedesc2=$(expr "$edges_unique" : '\([0-9a-zA-Z =_-]*\)') + if [ "$nodedesc2" != "$nodedesc1" ] + then + rm -f $FILE_TEMP + mv $FILE_LINKS_EDGE_HFI2 $FILE_TEMP + cat $FILE_TEMP | sed -e "s/$nodedesc2;/$nodedesc1;/" > $FILE_LINKS_EDGE_HFI2 + if [ -s $FILE_LINKS_LEAF_EDGE2 ] + then + rm -f $FILE_TEMP + mv $FILE_LINKS_LEAF_EDGE2 $FILE_TEMP + cat $FILE_TEMP | sed -e "s/$nodedesc2$/$nodedesc1/" > $FILE_LINKS_LEAF_EDGE2 + fi + fi + nodedesc_last=$nodedesc1 + elif [ $n_edges_unique == 2 ] + then + nodedesc2=`echo $edges_unique | head -n1` + nodedesc2b=`echo $edges_unique | tail -n1` + n_edges2=`echo $edges | grep -c "$nodedesc2"` + n_edges2b=`echo $edges | grep -c "$nodedesc2b"` + if [ $n_edges2 -gt $n_edges2b ] + then + if [ "$nodedesc2" != "$nodedesc1" ] + then + rm -f $FILE_TEMP + mv $FILE_LINKS_EDGE_HFI2 $FILE_TEMP + cat $FILE_TEMP | sed -e "s/$nodedesc2;/$nodedesc1;/" > $FILE_LINKS_EDGE_HFI2 + if [ -s $FILE_LINKS_LEAF_EDGE2 ] + then + rm -f $FILE_TEMP + mv $FILE_LINKS_LEAF_EDGE2 $FILE_TEMP + cat $FILE_TEMP | sed -e "s/$nodedesc2$/$nodedesc1/" > $FILE_LINKS_LEAF_EDGE2 + fi + fi + elif [ $n_edges2b -gt $n_edges2 ] + then + if [ "$nodedesc2b" != "$nodedesc1" ] + then + rm -f $FILE_TEMP + mv $FILE_LINKS_EDGE_HFI2 $FILE_TEMP + cat $FILE_TEMP | sed -e "s/$nodedesc2b;/$nodedesc1;/" > $FILE_LINKS_EDGE_HFI2 + if [ -s $FILE_LINKS_LEAF_EDGE2 ] + then + rm -f $FILE_TEMP + mv $FILE_LINKS_LEAF_EDGE2 $FILE_TEMP + cat $FILE_TEMP | sed -e "s/$nodedesc2b$/$nodedesc1/" > $FILE_LINKS_LEAF_EDGE2 + fi + fi + fi + nodedesc_last=$nodedesc1 + elif [ $n_edges_unique -ge 3 ] + then +# ToDo: add processing for 3 edges + filler=1 + elif [ $n_edges_unique == 0 ] + then +# ToDo: consider processing here + filler=1 + fi # End of if [ $n_edges_unique == 1 ] + + fi # End of if [ "$nodedesc1" != "$nodedesc_last" ] + + ix_line=$((ix_line+1)) + + done < <( cat $FILE_LINKSUM_EDGE_HFI ) # End of while read ... do + + fi # End of if [ -s $FILE_LINKS_EDGE_HFI2 ] + + # Process leaf NodeDesc + if [ -s $FILE_LINKS_LEAF_EDGE2 ] + then + display_progress "Processing leaf NodeDesc" + + ix_line=1 + nodedesc_last="ZzQQQzZ" + + while read portnum1 nodetype1 nodedesc1 portnum1b nodetype1b nodedesc1b + do + if [ "$nodedesc1" != "$nodedesc_last" ] + then + if [ -s $FILE_LINKSUM_LEAF_EDGE ] + then + n_edges=`cat $FILE_LINKSUM_LEAF_EDGE | grep "$nodedesc1;" | wc -l` + edges=`cat $FILE_LINKSUM_LEAF_EDGE | grep "$nodedesc1;" | cut -d \; -f4-6 | tr '\012' '|' | sed -e 's/|/$|/g' -e 's/|$//'` + else + n_edges=0 + edges="ZzQQQzZ" + fi + n_leaves=`cat $FILE_LINKS_LEAF_EDGE2 | grep -E "$edges" | wc -l` + n_leaves_unique=`cat $FILE_LINKS_LEAF_EDGE2 | grep -E "$edges" | cut -d \; -f4 | sort -u | wc -l` +# ToDo: may be able to eliminate $leaves + leaves=`cat $FILE_LINKS_LEAF_EDGE2 | grep -E "$edges" | cut -d \; -f4` + leaves_unique=`cat $FILE_LINKS_LEAF_EDGE2 | grep -E "$edges" | cut -d \; -f4 | sort -u` + if [ $n_leaves_unique == 1 ] + then + nodedesc2=$(expr "$leaves_unique" : '\([0-9a-zA-Z =_-]*\)') + if [ "$nodedesc2" != "$nodedesc1" ] + then + rm -f $FILE_TEMP + mv $FILE_LINKS_LEAF_EDGE2 $FILE_TEMP + cat $FILE_TEMP | sed -e "s/$nodedesc2;/$nodedesc1;/" > $FILE_LINKS_LEAF_EDGE2 + fi + nodedesc_last=$nodedesc1 + elif [ $n_leaves_unique == 2 ] + then + nodedesc2=`echo $leaves_unique | head -n1` + nodedesc2b=`echo $leaves_unique | tail -n1` + n_leaves2=`echo $leaves | grep -c "$nodedesc2"` + n_leaves2b=`echo $leaves | grep -c "$nodedesc2b"` + if [ $n_leaves2 -gt $n_leaves2b ] + then + if [ "$nodedesc2" != "$nodedesc1" ] + then + rm -f $FILE_TEMP + mv $FILE_LINKS_LEAF_EDGE2 $FILE_TEMP + cat $FILE_TEMP | sed -e "s/$nodedesc2;/$nodedesc1;/" > $FILE_LINKS_LEAF_EDGE2 + fi + elif [ $n_leaves2b -gt $n_leaves2 ] + then + if [ "$nodedesc2b" != "$nodedesc1" ] + then + rm -f $FILE_TEMP + mv $FILE_LINKS_LEAF_EDGE2 $FILE_TEMP + cat $FILE_TEMP | sed -e "s/$nodedesc2b;/$nodedesc1;/" > $FILE_LINKS_LEAF_EDGE2 + fi + fi + nodedesc_last=$nodedesc1 + elif [ $n_leaves_unique -ge 3 ] + then +# ToDo: add processing for 3 leaves + filler=1 + elif [ $n_leaves_unique == 0 ] + then +# ToDo: consider processing here + filler=1 + fi # End of if [ $n_leaves_unique == 1 ] + + fi # End of if [ "$nodedesc1" != "$nodedesc_last" ] + + ix_line=$((ix_line+1)) + + done < <( cat $FILE_LINKSUM_LEAF_EDGE ) # End of while read ... do + + fi # End of if [ -s $FILE_LINKS_LEAF_EDGE2 ] + + # Process file_switches + display_progress "Processing $file_switches" + + rm -f $FILE_TEMP + rm -f $FILE_TEMP2 + if [ -s $FILE_LINKS_LEAF_EDGE2 ] + then + cat $FILE_LINKS_LEAF_EDGE2 | cut -d \; -f1,4 | sort -u >> $FILE_TEMP + cat $FILE_LINKS_LEAF_EDGE2 | cut -d \; -f5,8 | sort -u >> $FILE_TEMP + fi + if [ -s $FILE_LINKS_EDGE_HFI2 ] + then + cat $FILE_LINKS_EDGE_HFI2 | cut -d \; -f1,4 | sort -u >> $FILE_TEMP + fi + if [ -s $FILE_TEMP ] + then + cat $FILE_TEMP | grep -v -e ';[0-9a-zA-Z_]*[ =-]' | sed -r -e 's/([0-9a-zA-Z_]+);([0-9a-zA-Z_]+)/s\/\(\1:'"$hfi:$port"'\),[0-9a-zA-Z =_-]*\/\\1,\2\//' | sort -u > $FILE_TEMP2 + cat $FILE_OPASWITCHES | sed -r -f $FILE_TEMP2 > $FILE_OPASWITCHES2 + rm -f $FILE_OPASWITCHES + mv $FILE_OPASWITCHES2 $FILE_OPASWITCHES + fi + + fi # End of if [ $? -eq 0 ] + + else + echo "opagenswitches: Error: topology file $TOPOLOGY_FILE does not exist" >&2 + + fi # End of if [ -f "$TOPOLOGY_FILE" ] + + done # End of for hfi_port in $PORTS + +fi # End of if [ $fl_write_switches == 1 -a $fl_gen_linksum == 1 ] + +if [ $fl_write_switches == 1 ] + then + if [ -n "$file_output" ] + then + if [ -f $file_output ] + then + if [ `$OPAEXPAND_FILE $file_output | wc -l` -ne 0 ] + then + rm -f ${file_output}.bak + mv $file_output ${file_output}.bak + fi + fi + rm -f $file_output + cp -p $FILE_OPASWITCHES $file_output + else + cat $FILE_OPASWITCHES + fi + clean_files + display_progress "Done" + exit 0 +else + clean_files + display_progress "Done (error)" + exit 1 +fi + diff --git a/IbaTools/opagenswitches/opagenswitcheshelper.c b/IbaTools/opagenswitches/opagenswitcheshelper.c new file mode 100644 index 0000000..7795f50 --- /dev/null +++ b/IbaTools/opagenswitches/opagenswitcheshelper.c @@ -0,0 +1,347 @@ +/* BEGIN_ICS_COPYRIGHT7 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT7 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +#include +#include +#include +#include +#include +#include + +unsigned int g_debug_level = 0; +unsigned int g_verbose = 0; + +// Local functions + +/* cat_bfr() - concatonate buffer2 onto end of buffer1; replace LF in + * buffer1 with ';' and remove null in buffer1. + * + * Inputs: + * p_bfr1 - pointer to buffer1 + * p_bfr2 - pointer to buffer2 + * + * Outputs: + * none + */ +void cat_bfr(char * p_bfr1, char * p_bfr2) +{ + char * p_bfr; + + if (!p_bfr1 || !p_bfr2 || !strlen(p_bfr1) || !strlen(p_bfr2)) + return; + if ((p_bfr = strchr(p_bfr1, 0x0A))) + { + *p_bfr++ = ';'; + strcat(p_bfr, p_bfr2); + } + return; +} // End of cat_bfr() + + +// Helper functions for opagenswitches.sh + +/* proc_links() - read links input file and parse links according + * to node type. Write link information to appropriate link file. + * + * Inputs: + * p_file_links - name of links input file + * p_file_links_edge_hfi - name of edge-to-hfi links output file + * p_file_links_leaf_edge - name of leaf-to-edge links output file + * + * Outputs: + * status: 0 - OK + * 1 - Error + */ +int proc_links( char * p_file_links, char * p_file_links_edge_hfi, + char * p_file_links_leaf_edge ) +{ + int status = 0; + unsigned int n_size_read = 2048; + unsigned int ct_line = 0; + char * p_bfr; + FILE * h_links = NULL; + FILE * h_links_edge_hfi = NULL; + FILE * h_links_leaf_edge = NULL; + char bf_input[n_size_read * 2 + 1]; + char bf_input2[n_size_read * 2 + 1]; + + // Validate inputs + if (!p_file_links || !p_file_links_edge_hfi || !p_file_links_leaf_edge) + { + fprintf( stderr, "opagenswitches:proc_links NULL Parameter (%s %s %s)\n", + (p_file_links)?p_file_links:"", + (p_file_links_edge_hfi)?p_file_links_edge_hfi:"", + (p_file_links_leaf_edge)?p_file_links_leaf_edge:"" ); + goto error; + } + if ( !(h_links = fopen(p_file_links, "r")) || + !(h_links_edge_hfi = fopen(p_file_links_edge_hfi, "w")) || + !(h_links_leaf_edge = fopen(p_file_links_leaf_edge, "w")) ) + { + fprintf( stderr, "opagenswitches:proc_links Unable to open file (%lu %lu %lu)\n", + (unsigned long)h_links, (unsigned long)h_links_edge_hfi, + (unsigned long)h_links_leaf_edge ); + goto error; + } + + // Read links input file + for (ct_line = 1; ; ct_line++) + { + if (fgets(bf_input, n_size_read, h_links)) + { + ct_line++; + if (fgets(bf_input2, n_size_read, h_links)) + { + // Process bf_input[] and bf_input2[] + if (strstr(bf_input2, "FI")) + { + cat_bfr(bf_input, bf_input2); + fputs(bf_input, h_links_edge_hfi); + } + else if (strstr(bf_input, "FI")) + { + cat_bfr(bf_input2, bf_input); + fputs(bf_input2, h_links_edge_hfi); + } + else if ( ((p_bfr = strchr(bf_input, ';'))) && + ((p_bfr = strchr(++p_bfr, ';'))) && + ((p_bfr = strchr(++p_bfr, ';'))) && + ((p_bfr = strchr(++p_bfr, 'S'))) && + isdigit(*++p_bfr) && isdigit(*++p_bfr) && + isdigit(*++p_bfr) ) + continue; + else if ( ((p_bfr = strchr(bf_input2, ';'))) && + ((p_bfr = strchr(++p_bfr, ';'))) && + ((p_bfr = strchr(++p_bfr, ';'))) && + ((p_bfr = strchr(++p_bfr, 'S'))) && + isdigit(*++p_bfr) && isdigit(*++p_bfr) && + isdigit(*++p_bfr) ) + continue; + else + { + cat_bfr(bf_input2, bf_input); + fputs(bf_input2, h_links_leaf_edge); + } + } + else + { + fprintf(stderr, "opagenswitches:proc_links Missing Record\n"); + goto error; + } + } + else + goto exit; + + } // End of for (ct_line = 1; ; ct_line++) + +exit: + if (h_links) + fclose(h_links); + if (h_links_edge_hfi) + fclose(h_links_edge_hfi); + if (h_links_leaf_edge) + fclose(h_links_leaf_edge); + return (status); + +error: + status = 1; + goto exit; + +} // End of proc_links() + +/* proc_linksum() - read topology input file and parse links according + * to node type. Write link information to appropriate linksum file. + * + * Inputs: + * p_file_topology - name of topology input file + * p_file_linksum_edge_hfi - name of edge-to-hfi linksum output file + * p_file_linksum_leaf_edge - name of leaf-to-edge linksum output file + * + * Outputs: + * status: 0 - OK + * 1 - Error + */ +int proc_linksum( char * p_file_topology, char * p_file_linksum_edge_hfi, + char * p_file_linksum_leaf_edge ) +{ + int status = 0; + unsigned int n_size_read = 2048; + unsigned int ct_line = 0; + char * p_bfr; + FILE * h_topology = NULL; + FILE * h_linksum_edge_hfi = NULL; + FILE * h_linksum_leaf_edge = NULL; + char bf_input[n_size_read * 2 + 1]; + char bf_input2[n_size_read * 2 + 1]; + + // Validate inputs + if (!p_file_topology || !p_file_linksum_edge_hfi || !p_file_linksum_leaf_edge) + { + fprintf( stderr, "opagenswitches:proc_linksum NULL Parameter (%s %s %s)\n", + (p_file_topology)?p_file_topology:"= 1) + { + p_cmdname = argv[1]; + if (argc >= 2) + { + p_arg1 = argv[2]; + if (!p_arg1) { + fprintf(stderr, "opagenswitches: Error: null input filename\n"); + exit(status); + } + if (argc >= 3) + { + p_arg2 = argv[3]; + if (!p_arg2) { + fprintf(stderr, "opagenswitches: Error: null input filename\n"); + exit(status); + } + if (argc >= 4) + { + p_arg3 = argv[4]; + if (!p_arg3) { + fprintf(stderr, "opagenswitches: Error: null input filename\n"); + exit(status); + } + } + } + } + } + + else + exit(status); + + if (!strcmp(p_cmdname, "proc_linksum")) + { + status = proc_linksum(p_arg1, p_arg2, p_arg3); + } + + else if (!strcmp(p_cmdname, "proc_links")) + { + status = proc_links(p_arg1, p_arg2, p_arg3); + } + + else + { + exit(status); + } + + exit(status); + +} // End of main + diff --git a/IbaTools/opagetipaddrtype/Makefile b/IbaTools/opagetipaddrtype/Makefile new file mode 100644 index 0000000..098764b --- /dev/null +++ b/IbaTools/opagetipaddrtype/Makefile @@ -0,0 +1,158 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** +# Makefile for opagetipaddrtype tool + +# Include Make Control Settings +include $(TL_DIR)/$(PROJ_FILE_DIR)/Makesettings.project + +#=============================================================================# +# Definitions: +#-----------------------------------------------------------------------------# + +# Name of SubProjects +DS_SUBPROJECTS = +# name of executable or downloadable image +EXECUTABLE = $(BUILDDIR)/opagetipaddrtype$(EXE_SUFFIX) +# list of sub directories to build +DIRS = +# C files (.c) +CFILES = \ + opagetipaddrtype.c \ + # Add more files here +# C++ files (.cpp) +CCFILES = \ + # Add more files here +# lex files (.lex) +LFILES = \ + # Add more lex files here +# archive library files (basename, $ARFILES will add MOD_LIB_DIR/prefix and suffix) +LIBFILES = +# Windows Resource Files (.rc) +RSCFILES = +# Windows IDL File (.idl) +IDLFILE = +# Windows Linker Module Definitions (.def) file for dll's +DEFFILE = +# targets to build during INCLUDES phase (add public includes here) +INCLUDE_TARGETS = \ + # Add more h hpp files here +# Non-compiled files +MISC_FILES = +# all source files +SOURCES = $(CFILES) $(CCFILES) $(LFILES) $(RSCFILES) $(IDLFILE) +# Source files to include in DSP File +DSP_SOURCES = $(INCLUDE_TARGETS) $(SOURCES) $(MISC_FILES) \ + $(RSCFILES) $(DEFFILE) $(MAKEFILE) +# all object files +OBJECTS = $(CFILES:.c=$(OBJ_SUFFIX)) $(CCFILES:.cpp=$(OBJ_SUFFIX)) \ + $(LFILES:.lex=$(OBJ_SUFFIX)) +RSCOBJECTS = $(RSCFILES:.rc=$(RES_SUFFIX)) + +# targets to build during LIBS phase +LIB_TARGETS_IMPLIB = +LIB_TARGETS_ARLIB = +LIB_TARGETS_EXP = $(LIB_TARGETS_IMPLIB:$(ARLIB_SUFFIX)=$(EXP_SUFFIX)) +LIB_TARGETS_MISC = +# targets to build during CMDS phase +CMD_TARGETS_SHLIB = +CMD_TARGETS_EXE = $(EXECUTABLE) +CMD_TARGETS_MISC = +CMD_TARGETS_DRIVER = +# files to remove during clean phase +CLEAN_TARGETS_MISC = +CLEAN_TARGETS = $(OBJECTS) $(RSCOBJECTS) $(IDL_TARGETS) $(CLEAN_TARGETS_MISC) +# other files to remove during clobber phase +CLOBBER_TARGETS_MISC= +# sub-directory to install to within bin +BIN_SUBDIR = +# sub-directory to install to within include +INCLUDE_SUBDIR = + +# Additional Settings +#CLOCALDEBUG = User defined C debugging compilation flags [Empty] +#CCLOCALDEBUG = User defined C++ debugging compilation flags [Empty] +#CLOCAL = User defined C flags for compiling [Empty] +#CCLOCAL = User defined C++ flags for compiling [Empty] +#BSCLOCAL = User flags for Browse File Builder [Empty] +#DEPENDLOCAL = user defined makedepend flags [Empty] +#LINTLOCAL = User defined lint flags [Empty] +#LOCAL_INCLUDE_DIRS = User include directories to search for C/C++ headers [Empty] +#LDLOCAL = User defined C flags for linking [Empty] +#IMPLIBLOCAL = User flags for Object Lirary Manager [Empty] +#MIDLLOCAL = User flags for IDL compiler [Empty] +#RSCLOCAL = User flags for resource compiler [Empty] +#LOCALDEPLIBS = User libraries to include in dependencies [Empty] +#LOCALLIBS = User libraries to use when linking [Empty] +# (in addition to LOCALDEPLIBS) +# = User library directories for libpaths [Empty] + +CLOCAL = $(CPIE) + +LOCAL_LIB_DIRS = +LOCALLIBS = + +# Include Make Rules definitions and rules +include $(TL_DIR)/IbaTools/Makerules.module + +#=============================================================================# +# Overrides: +#-----------------------------------------------------------------------------# +#CCOPT = # C++ optimization flags, default lets build config decide +#COPT = # C optimization flags, default lets build config decide +#SUBSYSTEM = Subsystem to build for (none, console or windows) [none] +# (Windows Only) +#USEMFC = How Windows MFC should be used (none, static, shared, no_mfc) [none] +# (Windows Only) +#=============================================================================# + +#=============================================================================# +# Rules: +#-----------------------------------------------------------------------------# +# process Sub-directories +include $(TL_DIR)/Makerules/Maketargets.toplevel + +# build cmds and libs +include $(TL_DIR)/Makerules/Maketargets.build + +# install for includes, libs and cmds phases +include $(TL_DIR)/Makerules/Maketargets.install + +# install for stage phase +#include $(TL_DIR)/Makerules/Maketargets.stage +STAGE:: + $(VS)$(STAGE_INSTALL) $(STAGE_INSTALL_DIR_OPT) $(PROJ_STAGE_FASTFABRIC_DIR) $(EXECUTABLE) + +# Unit test execution +#include $(TL_DIR)/Makerules/Maketargets.runtest + +#=============================================================================# + +#=============================================================================# +# DO NOT DELETE THIS LINE -- make depend depends on it. +#=============================================================================# diff --git a/IbaTools/opagetipaddrtype/opagetipaddrtype.c b/IbaTools/opagetipaddrtype/opagetipaddrtype.c new file mode 100644 index 0000000..f54dbde --- /dev/null +++ b/IbaTools/opagetipaddrtype/opagetipaddrtype.c @@ -0,0 +1,70 @@ +/* BEGIN_ICS_COPYRIGHT7 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT7 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +#include +#include +#include +#include +#include +#include + +void Usage() +{ + fprintf(stderr, "Usage: opagetipaddrtype addr\n"); + exit(2); +} + +int main(int argc, char **argv) +{ + struct addrinfo *addrinfo = NULL; + int err; + + if (argc != 2) + Usage(); + + // resolve name to an IP address + if (0 != (err = getaddrinfo(argv[1], NULL, NULL, &addrinfo)) + || ! addrinfo) { + fprintf(stderr,"Error: Unable to resolve name %s, %s\n", + argv[1], gai_strerror(err)); + exit(1); + } + if (addrinfo[0].ai_family == AF_INET) { + fprintf(stdout, "ipv4\n"); + exit(0); + } else if (addrinfo[0].ai_family == AF_INET6) { + fprintf(stdout, "ipv6\n"); + exit(0); + } else { + fprintf(stderr, "Error: Unrecognized address type for hostname %s\n",argv[1]); + exit(1); + } +} diff --git a/IbaTools/opahfirev/Makefile b/IbaTools/opahfirev/Makefile new file mode 100644 index 0000000..a53488b --- /dev/null +++ b/IbaTools/opahfirev/Makefile @@ -0,0 +1,154 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** +# Makefile for iba_ifup + +# Include Make Control Settings +include $(TL_DIR)/$(PROJ_FILE_DIR)/Makesettings.project + +#=============================================================================# +# Definitions: +#-----------------------------------------------------------------------------# + +# Name of SubProjects +DS_SUBPROJECTS = +# name of executable or downloadable image +EXECUTABLE = +# list of sub directories to build +DIRS = +# C files (.c) +CFILES = \ + # Add more c files here +# C++ files (.cpp) +CCFILES = \ + # Add more cpp files here +# lex files (.lex) +LFILES = \ + # Add more lex files here +# archive library files (basename, $ARFILES will add MOD_LIB_DIR/prefix and suffix) +LIBFILES= +# Windows Resource Files (.rc) +RSCFILES = +# Windows IDL File (.idl) +IDLFILE = +# Windows Linker Module Definitions (.def) file for dll's +DEFFILE = +# targets to build during INCLUDES phase (add public includes here) +INCLUDE_TARGETS = \ + # Add more h hpp files here +# Non-compiled files +MISC_FILES = +# all source files +SOURCES = $(CFILES) $(CCFILES) $(LFILES) $(RSCFILES) $(IDLFILE) +# Source files to include in DSP File +DSP_SOURCES = $(INCLUDE_TARGETS) $(SOURCES) $(MISC_FILES) \ + $(RSCFILES) $(DEFFILE) $(MAKEFILE) +# all object files +OBJECTS = $(CFILES:.c=$(OBJ_SUFFIX)) $(CCFILES:.cpp=$(OBJ_SUFFIX)) \ + $(LFILES:.lex=$(OBJ_SUFFIX)) +RSCOBJECTS = $(RSCFILES:.rc=$(RES_SUFFIX)) +# targets to build during LIBS phase +LIB_TARGETS_IMPLIB = +LIB_TARGETS_ARLIB = # $(LIB_PREFIX)startup$(ARLIB_SUFFIX) +LIB_TARGETS_EXP = $(LIB_TARGETS_IMPLIB:$(ARLIB_SUFFIX)=$(EXP_SUFFIX)) +LIB_TARGETS_MISC = +# targets to build during CMDS phase +CMD_TARGETS_SHLIB = +CMD_TARGETS_EXE = $(EXECUTABLE) +CMD_TARGETS_MISC = opahfirev +# files to remove during clean phase +CLEAN_TARGETS_MISC = +CLEAN_TARGETS = $(OBJECTS) $(RSCOBJECTS) $(IDL_TARGETS) $(CLEAN_TARGETS_MISC) +# other files to remove during clobber phase +CLOBBER_TARGETS_MISC= opahfirev.sh +# sub-directory to install to within bin +BIN_SUBDIR = +# sub-directory to install to within include +INCLUDE_SUBDIR = + +# Additional Settings +#CLOCALDEBUG = User defined C debugging compilation flags [Empty] +#CCLOCALDEBUG = User defined C++ debugging compilation flags [Empty] +#CLOCAL = User defined C flags for compiling [Empty] +#CCLOCAL = User defined C++ flags for compiling [Empty] +#BSCLOCAL = User flags for Browse File Builder [Empty] +#DEPENDLOCAL = user defined makedepend flags [Empty] +#LINTLOCAL = User defined lint flags [Empty] +#LOCAL_INCLUDE_DIRS = User include directories to search for C/C++ headers [Empty] +#LDLOCAL = User defined C flags for linking [Empty] +#IMPLIBLOCAL = User flags for Object Lirary Manager [Empty] +#MIDLLOCAL = User flags for IDL compiler [Empty] +#RSCLOCAL = User flags for resource compiler [Empty] +#LOCALDEPLIBS = User libraries to include in dependencies [Empty] +#LOCALLIBS = User libraries to use when linking [Empty] +# (in addition to LOCALDEPLIBS) +#LOCAL_LIB_DIRS = User library directories for libpaths [Empty] + +CLOCAL = $(CPIE) + +# Include Make Rules definitions and rules +include $(TL_DIR)/IbaTools/Makerules.module + +#=============================================================================# +# Overrides: +#-----------------------------------------------------------------------------# +#CCOPT = # C++ optimization flags, default lets build config decide +#COPT = # C optimization flags, default lets build config decide +#SUBSYSTEM = Subsystem to build for (none, console or windows) [none] +# (Windows Only) +#USEMFC = How Windows MFC should be used (none, static, shared, no_mfc) [none] +# (Windows Only) +#=============================================================================# + +#=============================================================================# +# Rules: +#-----------------------------------------------------------------------------# +# process Sub-directories +include $(TL_DIR)/Makerules/Maketargets.toplevel + +# build cmds and libs +include $(TL_DIR)/Makerules/Maketargets.build + +opahfirev: opahfirev.sh + cp opahfirev.sh opahfirev + chmod +x opahfirev + +# install for includes, libs and cmds phases +include $(TL_DIR)/Makerules/Maketargets.install + +# install for stage phase +include $(TL_DIR)/Makerules/Maketargets.stage + +# Unit test execution +#include $(TL_DIR)/Makerules/Maketargets.runtest + +#=============================================================================# + +#=============================================================================# +# DO NOT DELETE THIS LINE -- make depend depends on it. +#=============================================================================# diff --git a/IbaTools/opahfirev/README b/IbaTools/opahfirev/README new file mode 100644 index 0000000..1c859a4 --- /dev/null +++ b/IbaTools/opahfirev/README @@ -0,0 +1,13 @@ +The script has been updated to only report STL devices. +At present, that includes wfr_lite, which utilizes an InfiniPath device. +This will be updated when real hardware comes available. + +###################### +phgppriv04.ph.intel.com - HFI 83:00.0 +Board: ChipABI 2.0, InfiniPath_QLE7342, InfiniPath1 6.2, SW Compat 2 +SN: RIB1024C26610 +Bus: PCIe,5000MHz,x8 +GUID: 0011:7500:0079:159a +###################### + + diff --git a/IbaTools/opahfirev/opahfirev.sh b/IbaTools/opahfirev/opahfirev.sh new file mode 100755 index 0000000..5076d9c --- /dev/null +++ b/IbaTools/opahfirev/opahfirev.sh @@ -0,0 +1,200 @@ +#!/bin/bash +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: @(#) ./bin/opahfirev 0mwhe.20151019 [10/19/15 15:19] +function nn_to_sockets() +{ +#determine socket from the corresponding numa node + + local numa_node="$1" + cmdout="$(lscpu -p=SOCKET,NODE 2>&1)" + + #parse output of lscpu + while read -r line + do + if [ "${line:0:1}" == "#" ] + then continue + fi + sktval="${line%%,*}" + nodeval="${line##*,}" + if [ "${nodeval}" -eq "${numa_node}" ] + then + echo $sktval + return 0 + fi + done <<< "${cmdout}" + return 1 + +} + +Usage() +{ + cat <&2 +This scans the system and reports hardware and firmware information about +all the HFIs in the system. +EOF + exit 2 +} + +if [ $# -ge 1 ] +then + Usage +fi + +BASEDIR=/sys/bus/pci/devices + +hfis=`lspci -nn -D -d '8086:*' | egrep -e "24f[01]|Omni-Path" | grep -vi bridge | cut -d\ -f1` + +if [ -z "$hfis" ] +then + echo "No HFIs found." +else + for hfi in $hfis + do + echo "######################" + echo `hostname` " - HFI $hfi" + + boardver="UNKNOWN" + serial="UNKNOWN" + guid="UNKNOWN" + tmmver="UNKNOWN" + tmm=0 + instance="" + + localbus_info=$(lspci -vv -s "${hfi}" | + grep LnkSta: | + sed -e 's/^[[:space:]]*LnkSta:[[:space:]]*//' | + cut -d, -f1-2) + + driver=${BASEDIR}/${hfi}/infiniband/ + if [ -e ${driver} ] + then + instance=`ls ${driver} 2>/dev/null` + fi + + if [ -z ${instance} ] + then + instance="Driver not Loaded" + elif [ ! -e ${driver} -o ! -e ${driver}/${instance} ] + then + instance="Driver not Loaded" + else + hfinum=${instance#*_} + hfinum=`echo "${hfinum} +1" | bc` + eval 2>/dev/null read boardver < ${driver}/${instance}/boardversion + eval 2>/dev/null read serial < ${driver}/${instance}/serial + eval 2>/dev/null read guid < ${driver}/${instance}/node_guid + eval 2>/dev/null read hw_rev < ${driver}/${instance}/hw_rev + case "$hw_rev" in + "0") + hw_string="A0";; + "1") + hw_string=" A1";; + "10") + hw_string="B0";; + "11") + hw_string="B1";; + #note Add new HW rev codes here. This list was taken from WFR HAS CceRevision + esac + + /usr/sbin/opatmmtool -h ${hfinum} 2>/dev/null 1>/dev/null + tmm=$? + if [ $tmm -eq 0 ] + then + tmmver=`/usr/sbin/opatmmtool -h ${hfinum} fwversion | sed s/"Current Firmware Version="//` + fi + fi + + pci_id=`lspci -n -D -d 0x8086:* | grep ${hfi} | egrep -o 24f[01]` + if [ -z "${pci_id}" ] + then + echo "Error identifying HFI's on the PCI bus">&2 + type="NA" + pci_slot="NA" + else + if [ "$pci_id" = "24f0" ] + then + type="Discrete" + pci_slot="${hfi##*:}" + pci_slot="${pci_slot%%.*}" + else + type="Integrated" + fi + fi + + + nn=`cat /sys/bus/pci/devices/$hfi/numa_node` + res=$? + if [ "${res}" -ne 0 ] + then + nn="NA" + sckt="NA" + else + sckt=$(nn_to_sockets ${nn}) + res=$? + if [ "${res}" -ne 0 ] + then + sckt="NA" + fi + fi + + if [ "${instance}" = "Driver not Loaded" ] + then + hfi_id="_NA" + else + hfi_id=${instance#*_} + fi + + echo "HFI: $instance" + echo "Board: $boardver" + echo "SN: $serial" + if [ "${type}" = "Discrete" ] + then + echo "Location:$type Socket:$sckt PCISlot:$pci_slot NUMANode:$nn HFI$hfi_id" + else + echo "Location:$type Socket:$sckt NUMANode:$nn HFI$hfi_id" + fi + echo "Bus: ${localbus_info}" + echo "GUID: $guid" + + if [ -z $hw_string ] + then + echo "SiRev: $hw_rev" + else + echo "SiRev: $hw_string ($hw_rev)" + fi + + if [ $tmm -eq 0 ] + then + echo "TMM: $tmmver" + fi + echo "######################" + done +fi diff --git a/IbaTools/opahfirev/opahfirev.sh.base b/IbaTools/opahfirev/opahfirev.sh.base new file mode 100755 index 0000000..5076d9c --- /dev/null +++ b/IbaTools/opahfirev/opahfirev.sh.base @@ -0,0 +1,200 @@ +#!/bin/bash +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: @(#) ./bin/opahfirev 0mwhe.20151019 [10/19/15 15:19] +function nn_to_sockets() +{ +#determine socket from the corresponding numa node + + local numa_node="$1" + cmdout="$(lscpu -p=SOCKET,NODE 2>&1)" + + #parse output of lscpu + while read -r line + do + if [ "${line:0:1}" == "#" ] + then continue + fi + sktval="${line%%,*}" + nodeval="${line##*,}" + if [ "${nodeval}" -eq "${numa_node}" ] + then + echo $sktval + return 0 + fi + done <<< "${cmdout}" + return 1 + +} + +Usage() +{ + cat <&2 +This scans the system and reports hardware and firmware information about +all the HFIs in the system. +EOF + exit 2 +} + +if [ $# -ge 1 ] +then + Usage +fi + +BASEDIR=/sys/bus/pci/devices + +hfis=`lspci -nn -D -d '8086:*' | egrep -e "24f[01]|Omni-Path" | grep -vi bridge | cut -d\ -f1` + +if [ -z "$hfis" ] +then + echo "No HFIs found." +else + for hfi in $hfis + do + echo "######################" + echo `hostname` " - HFI $hfi" + + boardver="UNKNOWN" + serial="UNKNOWN" + guid="UNKNOWN" + tmmver="UNKNOWN" + tmm=0 + instance="" + + localbus_info=$(lspci -vv -s "${hfi}" | + grep LnkSta: | + sed -e 's/^[[:space:]]*LnkSta:[[:space:]]*//' | + cut -d, -f1-2) + + driver=${BASEDIR}/${hfi}/infiniband/ + if [ -e ${driver} ] + then + instance=`ls ${driver} 2>/dev/null` + fi + + if [ -z ${instance} ] + then + instance="Driver not Loaded" + elif [ ! -e ${driver} -o ! -e ${driver}/${instance} ] + then + instance="Driver not Loaded" + else + hfinum=${instance#*_} + hfinum=`echo "${hfinum} +1" | bc` + eval 2>/dev/null read boardver < ${driver}/${instance}/boardversion + eval 2>/dev/null read serial < ${driver}/${instance}/serial + eval 2>/dev/null read guid < ${driver}/${instance}/node_guid + eval 2>/dev/null read hw_rev < ${driver}/${instance}/hw_rev + case "$hw_rev" in + "0") + hw_string="A0";; + "1") + hw_string=" A1";; + "10") + hw_string="B0";; + "11") + hw_string="B1";; + #note Add new HW rev codes here. This list was taken from WFR HAS CceRevision + esac + + /usr/sbin/opatmmtool -h ${hfinum} 2>/dev/null 1>/dev/null + tmm=$? + if [ $tmm -eq 0 ] + then + tmmver=`/usr/sbin/opatmmtool -h ${hfinum} fwversion | sed s/"Current Firmware Version="//` + fi + fi + + pci_id=`lspci -n -D -d 0x8086:* | grep ${hfi} | egrep -o 24f[01]` + if [ -z "${pci_id}" ] + then + echo "Error identifying HFI's on the PCI bus">&2 + type="NA" + pci_slot="NA" + else + if [ "$pci_id" = "24f0" ] + then + type="Discrete" + pci_slot="${hfi##*:}" + pci_slot="${pci_slot%%.*}" + else + type="Integrated" + fi + fi + + + nn=`cat /sys/bus/pci/devices/$hfi/numa_node` + res=$? + if [ "${res}" -ne 0 ] + then + nn="NA" + sckt="NA" + else + sckt=$(nn_to_sockets ${nn}) + res=$? + if [ "${res}" -ne 0 ] + then + sckt="NA" + fi + fi + + if [ "${instance}" = "Driver not Loaded" ] + then + hfi_id="_NA" + else + hfi_id=${instance#*_} + fi + + echo "HFI: $instance" + echo "Board: $boardver" + echo "SN: $serial" + if [ "${type}" = "Discrete" ] + then + echo "Location:$type Socket:$sckt PCISlot:$pci_slot NUMANode:$nn HFI$hfi_id" + else + echo "Location:$type Socket:$sckt NUMANode:$nn HFI$hfi_id" + fi + echo "Bus: ${localbus_info}" + echo "GUID: $guid" + + if [ -z $hw_string ] + then + echo "SiRev: $hw_rev" + else + echo "SiRev: $hw_string ($hw_rev)" + fi + + if [ $tmm -eq 0 ] + then + echo "TMM: $tmmver" + fi + echo "######################" + done +fi diff --git a/IbaTools/opainfo/Makefile b/IbaTools/opainfo/Makefile new file mode 100644 index 0000000..567e843 --- /dev/null +++ b/IbaTools/opainfo/Makefile @@ -0,0 +1,157 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** +# Makefile for opamon + +# Include Make Control Settings +include $(TL_DIR)/$(PROJ_FILE_DIR)/Makesettings.project + +#=============================================================================# +# Definitions: +#-----------------------------------------------------------------------------# + +# Name of SubProjects +DS_SUBPROJECTS = +# name of executable or downloadable image +EXECUTABLE = $(BUILDDIR)/opainfo$(EXE_SUFFIX) +# list of sub directories to build +DIRS = +# C files (.c) +CFILES = \ + opainfo.c \ + # Add more c files here +# C++ files (.cpp) +CCFILES = \ + # Add more cpp files here +# lex files (.lex) +LFILES = \ + # Add more lex files here +# archive library files (basename, $ARFILES will add MOD_LIB_DIR/prefix and suffix) +LIBFILES= +# Windows Resource Files (.rc) +RSCFILES = +# Windows IDL File (.idl) +IDLFILE = +# Windows Linker Module Definitions (.def) file for dll's +DEFFILE = +# targets to build during INCLUDES phase (add public includes here) +INCLUDE_TARGETS = \ + # Add more h hpp files here +# Non-compiled files + # Add more files here +MISC_FILES = +# all source files +SOURCES = $(CFILES) $(CCFILES) $(LFILES) $(RSCFILES) $(IDLFILE) +# Source files to include in DSP File +DSP_SOURCES = $(INCLUDE_TARGETS) $(SOURCES) $(MISC_FILES) \ + $(RSCFILES) $(DEFFILE) $(MAKEFILE) +# all object files +OBJECTS = $(CFILES:.c=$(OBJ_SUFFIX)) $(CCFILES:.cpp=$(OBJ_SUFFIX)) \ + $(LFILES:.lex=$(OBJ_SUFFIX)) +RSCOBJECTS = $(RSCFILES:.rc=$(RES_SUFFIX)) +# targets to build during LIBS phase +LIB_TARGETS_IMPLIB = +LIB_TARGETS_ARLIB = # $(LIB_PREFIX)ResourceTest$(ARLIB_SUFFIX) +LIB_TARGETS_EXP = $(LIB_TARGETS_IMPLIB:$(ARLIB_SUFFIX)=$(EXP_SUFFIX)) +LIB_TARGETS_MISC = +# targets to build during CMDS phase +CMD_TARGETS_SHLIB = +CMD_TARGETS_EXE = $(EXECUTABLE) +CMD_TARGETS_MISC = +# files to remove during clean phase +CLEAN_TARGETS_MISC = +CLEAN_TARGETS = $(OBJECTS) $(RSCOBJECTS) $(IDL_TARGETS) $(CLEAN_TARGETS_MISC) +# other files to remove during clobber phase +CLOBBER_TARGETS_MISC= +# sub-directory to install to within bin +BIN_SUBDIR = +# sub-directory to install to within include +INCLUDE_SUBDIR = + +# Additional Settings +#CLOCALDEBUG = User defined C debugging compilation flags [Empty] +#CCLOCALDEBUG = User defined C++ debugging compilation flags [Empty] +#CLOCAL = User defined C flags for compiling [Empty] +#CCLOCAL = User defined C++ flags for compiling [Empty] +#BSCLOCAL = User flags for Browse File Builder [Empty] +#DEPENDLOCAL = user defined makedepend flags [Empty] +#LINTLOCAL = User defined lint flags [Empty] +#LOCAL_INCLUDE_DIRS = User include directories to search for C/C++ headers [Empty] +#LDLOCAL = User defined C flags for linking [Empty] +#IMPLIBLOCAL = User flags for Object Lirary Manager [Empty] +#MIDLLOCAL = User flags for IDL compiler [Empty] +#RSCLOCAL = User flags for resource compiler [Empty] +#LOCALDEPLIBS = User libraries to include in dependencies [Empty] +#LOCALLIBS = User libraries to use when linking [Empty] +# (in addition to LOCALDEPLIBS) +#LOCAL_LIB_DIRS = User library directories for libpaths [Empty] + +CLOCAL = $(CPIE) + +LOCALDEPLIBS = $(IBACCESS_USER_LIBS) IbPrint opamgt-priv +LOCAL_INCLUDE_DIRS= +LOCALLIBS=$(OPENIB_USER_LIBS) +LOCAL_LIB_DIRS=$(OPENIB_USER_LIB_DIRS) $(IBACCESS_USER_LIB_DIRS) + +# Include Make Rules definitions and rules +include $(TL_DIR)/IbaTools/Makerules.module + +#=============================================================================# +# Overrides: +#-----------------------------------------------------------------------------# +#CCOPT = # C++ optimization flags, default lets build config decide +#COPT = # C optimization flags, default lets build config decide +#SUBSYSTEM = Subsystem to build for (none, console or windows) [none] +# (Windows Only) +#USEMFC = How Windows MFC should be used (none, static, shared, no_mfc) [none] +# (Windows Only) +#=============================================================================# + +#=============================================================================# +# Rules: +#-----------------------------------------------------------------------------# +# process Sub-directories +include $(TL_DIR)/Makerules/Maketargets.toplevel + +# build cmds and libs +include $(TL_DIR)/Makerules/Maketargets.build + +# install for includes, libs and cmds phases +include $(TL_DIR)/Makerules/Maketargets.install + +# install for stage phase +include $(TL_DIR)/Makerules/Maketargets.stage + +# Unit test execution +#include $(TL_DIR)/Makerules/Maketargets.runtest + +#=============================================================================# + +#=============================================================================# +# DO NOT DELETE THIS LINE -- make depend depends on it. +#=============================================================================# diff --git a/IbaTools/opainfo/opainfo.c b/IbaTools/opainfo/opainfo.c new file mode 100644 index 0000000..66414b7 --- /dev/null +++ b/IbaTools/opainfo/opainfo.c @@ -0,0 +1,520 @@ +/* BEGIN_ICS_COPYRIGHT7 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT7 ****************************************/ + +#include +#include +#include +#include +#include + +/* work around conflicting names */ +#include "infiniband/umad.h" +#include "infiniband/verbs.h" + +#include "iba/ib_types.h" +#include "iba/ib_sm_priv.h" +#include "iba/ib_helper.h" +#include "opamgt_priv.h" +#include "ibprint.h" +#include "stl_print.h" +#include "iba/stl_pm.h" + +#define RESP_WAIT_TIME 1000 /* in ms */ +#define MAD_ATTEMPTS 1 /* 1 attempt, no retries */ + +// bit mask +#define OTYPE_INFO 1 +#define OTYPE_STATS 2 + +PrintDest_t g_dest; +int g_printLineByLine = 0; +uint8_t g_detail = 0; +unsigned g_verbose = 0; +uint64_t g_transactID = 0xffffffff1234000; // Upper half overwritten by umad +uint16_t g_pkey; // mgmt pkey to use +uint8_t g_cableInfo[STL_CIB_STD_LEN]; +uint8_t g_pm_sl = 0xFF; + +#if defined(DBGPRINT) +#undef DBGPRINT +#endif +#define VRBSE_PRINT(format, args...) do { if (g_verbose) { fflush(stdout); fprintf(stdout, format, ##args); } } while (0) +#define DBGPRINT(format, args...) do { if (g_verbose>1) { fflush(stdout); fprintf(stderr, format, ##args); } } while (0) + +const char *get_port_name(struct omgt_port *portHandle) +{ + static char buf[IBV_SYSFS_NAME_MAX + 6]; + char hfi_name[IBV_SYSFS_NAME_MAX] = {0}; + uint8_t port_num; + (void)omgt_port_get_hfi_port_num(portHandle, &port_num); + (void)omgt_port_get_hfi_name(portHandle, hfi_name); + snprintf(buf, sizeof(buf), "%.*s:%u", IBV_SYSFS_NAME_MAX, hfi_name, port_num); + return buf; +} + +void stl_set_local_route(OUT STL_SMP* smp) +{ + // local directed route + smp->common.MgmtClass = MCLASS_SM_DIRECTED_ROUTE; + smp->common.u.DR.s.D = 0; + smp->common.u.DR.s.Status = 0; + smp->common.u.DR.HopPointer = 0; + smp->common.u.DR.HopCount = 0; + smp->SmpExt.DirectedRoute.DrSLID = STL_LID_PERMISSIVE; + smp->SmpExt.DirectedRoute.DrDLID = STL_LID_PERMISSIVE; + return; +} + + +FSTATUS perform_local_stl_sma_query( IN struct omgt_port *portHandle, + IN uint16 attrid, + IN uint32 attrmod, + OUT STL_SMP* smp ) +{ + FSTATUS status; + + smp->common.BaseVersion = STL_BASE_VERSION; + smp->common.ClassVersion = STL_SM_CLASS_VERSION; + stl_set_local_route(smp); + smp->common.mr.AsReg8 = 0; + smp->common.mr.s.Method = MMTHD_GET; + smp->common.AttributeID = attrid; + smp->common.AttributeModifier = attrmod; + smp->common.TransactionID = (++g_transactID); + + STL_BSWAP_SMP_HEADER(smp); + { + struct omgt_mad_addr addr = { + .lid = 0, + .qpn = 0, + .qkey = 0, + .pkey = g_pkey + }; + size_t recv_size = sizeof(*smp); + size_t send_size = STL_MIN_SMP_DR_MAD; // no payload. + status = omgt_send_recv_mad_no_alloc(portHandle, (uint8_t *)smp, send_size, &addr, + (uint8_t *)smp, &recv_size, RESP_WAIT_TIME, MAD_ATTEMPTS-1); + if (FSUCCESS != status) + fprintf(stderr, "opainfo: MAD failed on hfi:port %s with Status: %s\n", + get_port_name(portHandle), iba_fstatus_msg(status)); + } + + STL_BSWAP_SMP_HEADER(smp); + + if (FSUCCESS == status && smp->common.u.DR.s.Status != MAD_STATUS_SUCCESS) { + fprintf(stderr, "MAD returned with Bad Status: %s\n", + iba_mad_status_msg2(smp->common.u.DR.s.Status)); + return FERROR; + } + return status; +} + +FSTATUS get_local_stl_port_info( IN struct omgt_port *portHandle, + OUT STL_SMP* smp ) +{ + FSTATUS status; + + if (g_verbose) { + VRBSE_PRINT("Sending Get(PortInfo) to hfi:port %s\n", + get_port_name(portHandle)); + } + + MemoryClear(smp, sizeof(*smp)); + + status = perform_local_stl_sma_query(portHandle, + STL_MCLASS_ATTRIB_ID_PORT_INFO, 1<<24, smp); + BSWAP_STL_PORT_INFO((STL_PORT_INFO*)stl_get_smp_data(smp)); + return status; +} + +FSTATUS get_local_stl_cable_info ( IN struct omgt_port *portHandle, + IN unsigned cabaddr, + OUT STL_SMP* smp ) +{ + FSTATUS status; + + if (g_verbose) { + VRBSE_PRINT("Sending Get(CableInfo) to hfi:port %s\n", + get_port_name(portHandle)); + } + MemoryClear(smp, sizeof(*smp)); + + status = perform_local_stl_sma_query(portHandle, + STL_MCLASS_ATTRIB_ID_CABLE_INFO, + (cabaddr & 0x7ff)<<19 | (STL_CABLE_INFO_MAXLEN)<<13, + smp); + BSWAP_STL_CABLE_INFO((STL_CABLE_INFO*)stl_get_smp_data(smp)); + + return status; +} + +FSTATUS perform_local_stl_pma_query( IN struct omgt_port *portHandle, + IN uint16 attrid, + IN uint32 attrmod, + OUT STL_PERF_MAD* mad ) +{ + FSTATUS status; + STL_LID dlid; + uint8_t port_state; + + mad->common.BaseVersion = STL_BASE_VERSION; + mad->common.MgmtClass = MCLASS_PERF; + mad->common.ClassVersion = STL_PM_CLASS_VERSION; + mad->common.u.NS.Status.AsReg16 = 0; + mad->common.mr.AsReg8 = 0; + mad->common.mr.s.Method = MMTHD_GET; + mad->common.AttributeID = attrid; + mad->common.AttributeModifier = attrmod; + mad->common.TransactionID = (++g_transactID); + // rest of fields should be ignored for a Get, zero'ed above + + (void)omgt_port_get_port_state(portHandle, &port_state); + if (port_state != IB_PORT_ACTIVE) { + dlid = STL_LID_PERMISSIVE; // special case for local query + } else { + (void)omgt_port_get_port_lid(portHandle, &dlid); + } + + BSWAP_MAD_HEADER((MAD*)mad); + { + struct omgt_mad_addr addr = { + .lid = dlid, + .qpn = 1, + .qkey = QP1_WELL_KNOWN_Q_KEY, + .pkey = g_pkey, + .sl = g_pm_sl, + }; + size_t recv_size = sizeof(*mad); + size_t send_size = STL_GS_HDRSIZE + sizeof(STL_PORT_STATUS_REQ); + status = omgt_send_recv_mad_no_alloc(portHandle, (uint8_t *)mad, send_size, &addr, + (uint8_t *)mad, &recv_size, RESP_WAIT_TIME, MAD_ATTEMPTS-1); + if (FSUCCESS != status) + fprintf(stderr, "opainfo: MAD failed on hfi:port %s with Status: %s\n", + get_port_name(portHandle), iba_fstatus_msg(status)); + + } + BSWAP_MAD_HEADER((MAD*)mad); + + if (FSUCCESS == status && mad->common.u.NS.Status.AsReg16 != MAD_STATUS_SUCCESS) { + fprintf(stderr, "MAD returned with Bad Status: %s\n", + iba_mad_status_msg2(mad->common.u.NS.Status.AsReg16)); + return FERROR; + } + return status; +} + +FSTATUS get_local_stl_port_status( IN struct omgt_port *portHandle, + OUT STL_PERF_MAD* mad ) +{ + FSTATUS status; + STL_PORT_STATUS_REQ *pPortCounterReq = (STL_PORT_STATUS_REQ *)&(mad->PerfData); + + MemoryClear(mad, sizeof(*mad)); + + if (g_verbose) { + VRBSE_PRINT("Sending Get(PortStatus) to hfi:port %s\n", + get_port_name(portHandle)); + } + (void)omgt_port_get_hfi_port_num(portHandle, &pPortCounterReq->PortNumber); + //pPortCounterReq->VLSelectMask = 0x8001; // Mask for VL15 & VL0 by default (same as pmaquery). + + BSWAP_STL_PORT_STATUS_REQ(pPortCounterReq); + + status = perform_local_stl_pma_query(portHandle, + STL_PM_ATTRIB_ID_PORT_STATUS, 1<<24, mad); + BSWAP_STL_PORT_STATUS_RSP((STL_PORT_STATUS_RSP*)&(mad->PerfData)); + return status; +} + + +void show_info( struct omgt_port *portHandle, + IN int outputType, + IN STL_PORT_INFO* pPortInfo, + IN uint8_t* cableInfo, + IN STL_PORT_STATUS_RSP *pPortStatusRsp) +{ + uint64_t portGUID = 0; + (void)omgt_port_get_port_guid(portHandle, &portGUID); + + if (! outputType) { + uint8_t detail = g_detail; + + if (detail > CABLEINFO_DETAIL_ALL) + detail = CABLEINFO_DETAIL_ALL; + + PrintStlPortSummary(&g_dest, 0, get_port_name(portHandle), + pPortInfo, portGUID, g_pkey, + cableInfo, STL_CIB_STD_HIGH_PAGE_ADDR, STL_CIB_STD_LEN, + pPortStatusRsp, detail, g_printLineByLine); + } + + if (outputType & (OTYPE_INFO|OTYPE_STATS)) + PrintFunc(&g_dest, "%s\n", get_port_name(portHandle)); + if ((outputType & OTYPE_INFO) && pPortInfo) + PrintStlPortInfo(&g_dest, 3, pPortInfo, portGUID, g_printLineByLine); + if ((outputType & OTYPE_STATS) && pPortStatusRsp) + PrintStlPortStatusRsp(&g_dest, 3, pPortStatusRsp); + fflush(stdout); +} + +void Usage(void) +{ + + fprintf(stderr, "Usage: opainfo [-h hfi] [-p port] [-o type] [-g] [-d detail] [-s pm_sl] [-v [-v]...]\n"); + fprintf(stderr, " -h hfi hfi, numbered 1..n, 0=system wide port num\n"); + fprintf(stderr, " (default is 0)\n"); + fprintf(stderr, " -p port port, numbered 1..n, 0=1st active\n"); + fprintf(stderr, " (default is all ports on selected hfi)\n"); + fprintf(stderr, " -o type output type specified (can appear more than once)\n"); + fprintf(stderr, " info - output detailed portinfo\n"); + fprintf(stderr, " stats - output detailed port counters\n"); + fprintf(stderr, " (behavior without -o gives a brief summary of portinfo,\n"); + fprintf(stderr, " counters and cableinfo)\n"); + fprintf(stderr, " -g Display in line-by-line format (default is summary format)\n"); + fprintf(stderr, " -d detail output detail level 0-2 for CableInfo only (default 0):\n"); + fprintf(stderr, " (-d option ignored when used with -o type)\n"); + fprintf(stderr, " 0 - minimal crucial info (e.g. cable length, vendor)\n"); + fprintf(stderr, " 1 - brief summary\n"); + fprintf(stderr, " 2 - extended brief summary\n"); + fprintf(stderr, " -s pm_sl Specify different Service Level for PMA traffic\n"); + fprintf(stderr, " -v verbose output. Additional invocations will turn on debugging,\n"); + fprintf(stderr, " openib debugging and libibumad debugging.\n"); + fprintf(stderr, "\n"); + fprintf(stderr, "The -h and -p options permit a variety of selections:\n"); + fprintf(stderr, " -h 0 all ports on all HFIs (this is the default)\n"); + fprintf(stderr, " -h 0 -p 0 1st active port in system\n"); + fprintf(stderr, " -h x all ports on HFI x\n"); + fprintf(stderr, " -h x -p 0 1st active port on HFI x\n"); + fprintf(stderr, " -h 0 -p y port y within system (irrespective of which ports are active)\n"); + fprintf(stderr, " -h x -p y HFI x, port y\n"); + exit(0); +} + + +/** + * find the output type requested + * + * @param name + * + * @return int + */ +int checkOutputType(const char *name) +{ + if ( 0 == strcmp(name, "info") ) + return OTYPE_INFO; + else if ( 0 == strcmp(name, "stats") ) + return OTYPE_STATS; + else + return -1; +} // int checkOutputType(const char *name) + +// command line options +struct option options[] = { + { "help", no_argument, NULL, '$' }, // use an invalid option character + { 0 } +}; + +int main(int argc, char *argv[]) +{ + uint8 hfi = 0; // all HFIs + uint8 port = 0; + int allPorts = 1; + int outputType = 0; + uint8 pm_sl = 0xFF; + + int c; + int index; + int ret; + FSTATUS fstatus; + uint32_t portCount; + STL_SMP smpPortInfo; + STL_SMP smpCableInfo; + STL_PERF_MAD madPortStatusRsp; + STL_PORT_INFO* pPortInfo; + int have_cableinfo; + STL_PORT_STATUS_RSP *pPortStatusRsp = 0; + struct omgt_port *portHandle = NULL; + + while (-1 != (c = getopt_long(argc,argv, "h:p:o:d:gvs:", options, &index))) + { + switch (c) { + case '$': + Usage(); + break; + case 'h': + if (FSUCCESS != StringToUint8(&hfi, optarg, NULL, 0, TRUE)) { + fprintf(stderr, "opainfo: Invalid HFI Number: %s\n", optarg); + Usage(); + } + break; + case 'p': + if (FSUCCESS != StringToUint8(&port, optarg, NULL, 0, TRUE)) { + fprintf(stderr, "opainfo: Invalid Port Number: %s\n", optarg); + Usage(); + } + allPorts = 0; + break; + case 'o': + outputType |= checkOutputType(optarg); + if (outputType < 0) + Usage(); + break; + case 'g': + g_printLineByLine = 1; + break; + case 'd': + if (FSUCCESS != StringToUint8(&g_detail, optarg, NULL, 0, TRUE)) { + fprintf(stderr, "opainfo: Invalid Detail: %s\n", optarg); + Usage(); + } + break; + case 'v': + g_verbose++; + if (g_verbose > 3) umad_debug(g_verbose - 3); + break; + case 's': + if (FSUCCESS != StringToUint8(&pm_sl, optarg, NULL, 0, TRUE)) { + fprintf(stderr, "opainfo: Invalid PM SL: %s\n", optarg); + Usage(); + } + break; + default: + fprintf(stderr, "opainfo: Invalid option -%c\n", c); + Usage(); + break; + } // switch + } // while + + if (optind < argc) + { + Usage(); + } + + PrintDestInitFile(&g_dest, stdout); + + if (allPorts) { + // determine port count for selected hfi + // if hfi==0, its system wide port count + // if port!=0, we get a specific port (fstatus parsing easier below) + fstatus = omgt_get_portguid( hfi, 1, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, &portCount, + NULL, NULL, NULL ); + + if (hfi && FSUCCESS != fstatus) { + fprintf(stderr, "opainfo: Failed to find hfi %d\n", hfi); + exit(1); + } else if (FSUCCESS != fstatus && FNOT_FOUND != fstatus) { + fprintf(stderr, "opainfo: Failed to determine number of HFIs\n"); + exit(1); + } else if (portCount == 0) { + fprintf(stderr, "opainfo: No HFIs found\n"); + exit(1); + } + port = 1; // start at 1st port + } else { + portCount = 1; + } + + for (; portCount > 0; port++, portCount--) + { + have_cableinfo = FALSE; + struct omgt_params params = {.debug_file = g_verbose > 2 ? stderr : NULL}; + ret = omgt_open_port_by_num(&portHandle, hfi, port, ¶ms); + if (port == 0 && ret == OMGT_STATUS_NOT_DONE) { + // asked for 1st active, but none active, use 1st port + port = 1; + ret = omgt_open_port_by_num(&portHandle, hfi, port, ¶ms); + } + if (ret != 0) { + printf("opainfo: Unable to open hfi:port %u:%u\n", hfi, port); + continue; + } + + // Determine which pkey to use (full or limited) + // Attempt to use full at all times, otherwise, can + // use the limited for queries of the local port. + g_pkey = omgt_get_mgmt_pkey(portHandle, 0, 0); + if (g_pkey==0) { + fprintf(stderr, "opainfo: Unable to find mgmt pkey on hfi:port %s\n", + get_port_name(portHandle)); + goto next; + } + + fstatus = get_local_stl_port_info( portHandle, &smpPortInfo); + if (FSUCCESS != fstatus) + { + fprintf(stderr, "opainfo: Failed to get Portinfo for hfi:port %s\n", + get_port_name(portHandle)); + goto next; // skip to next port, if any + } + pPortInfo = (STL_PORT_INFO *)stl_get_smp_data(&smpPortInfo); + + if (IsCableInfoAvailable(pPortInfo)) { + uint16_t addr; + uint8_t *data; + have_cableinfo = TRUE; // assume success + for (addr = STL_CIB_STD_HIGH_PAGE_ADDR, data=g_cableInfo; + addr + STL_CABLE_INFO_MAXLEN <= STL_CIB_STD_END_ADDR; addr += STL_CABLE_INFO_DATA_SIZE, data += STL_CABLE_INFO_DATA_SIZE) + { + fstatus = get_local_stl_cable_info(portHandle, addr, &smpCableInfo); + if (FSUCCESS != fstatus) { + fprintf(stderr, "opainfo: Failed to get Cableinfo for hfi:port %s\n", + get_port_name(portHandle)); + have_cableinfo = FALSE; + } else { + memcpy(data, ((STL_CABLE_INFO *)stl_get_smp_data(&smpCableInfo))->Data, STL_CABLE_INFO_DATA_SIZE); + } + } + } else { + have_cableinfo = FALSE; + } + + // If PM SL not set, use SM's SL + if (pm_sl == 0xFF) { + (void)omgt_port_get_port_sm_sl(portHandle, &pm_sl); + } + g_pm_sl = pm_sl; + fstatus = get_local_stl_port_status(portHandle, &madPortStatusRsp); + if (FSUCCESS != fstatus) { + fprintf(stderr, "opainfo: Failed to get PMA Port Status for hfi:port %s\n", + get_port_name(portHandle)); + pPortStatusRsp = NULL; + } else { + pPortStatusRsp = (STL_PORT_STATUS_RSP *)&(madPortStatusRsp.PerfData); + } + + show_info(portHandle, outputType, pPortInfo, have_cableinfo?g_cableInfo:NULL, pPortStatusRsp); +next: + omgt_close_port(portHandle); + portHandle = NULL; + } + + return 0 ; + +} // main diff --git a/IbaTools/opaipcalc/Makefile b/IbaTools/opaipcalc/Makefile new file mode 100644 index 0000000..34adfda --- /dev/null +++ b/IbaTools/opaipcalc/Makefile @@ -0,0 +1,150 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** +# Makefile for opaipcalc + +# Include Make Control Settings +include $(TL_DIR)/$(PROJ_FILE_DIR)/Makesettings.project + +#=============================================================================# +# Definitions: +#-----------------------------------------------------------------------------# + +# Name of SubProjects +DS_SUBPROJECTS = +# name of executable or downloadable image +EXECUTABLE = #$(BUILDDIR)/opaipcalc$(EXE_SUFFIX) +# list of sub directories to build +DIRS = +# C files (.c) +CFILES = \ + # Add more c files here +# C++ files (.cpp) +CCFILES = \ + # Add more cpp files here +# lex files (.lex) +LFILES = \ + # Add more lex files here +# archive library files (basename, $ARFILES will add MOD_LIB_DIR/prefix and suffix) +LIBFILES= +# Windows Resource Files (.rc) +RSCFILES = +# Windows IDL File (.idl) +IDLFILE = +# Windows Linker Module Definitions (.def) file for dll's +DEFFILE = +# targets to build during INCLUDES phase (add public includes here) +INCLUDE_TARGETS = \ + # Add more h hpp files here +# Non-compiled files +MISC_FILES = +# all source files +SOURCES = $(CFILES) $(CCFILES) $(LFILES) $(RSCFILES) $(IDLFILE) +# Source files to include in DSP File +DSP_SOURCES = $(INCLUDE_TARGETS) $(SOURCES) $(MISC_FILES) \ + $(RSCFILES) $(DEFFILE) $(MAKEFILE) +# all object files +OBJECTS = $(CFILES:.c=$(OBJ_SUFFIX)) $(CCFILES:.cpp=$(OBJ_SUFFIX)) \ + $(LFILES:.lex=$(OBJ_SUFFIX)) +RSCOBJECTS = $(RSCFILES:.rc=$(RES_SUFFIX)) +# targets to build during LIBS phase +LIB_TARGETS_IMPLIB = +LIB_TARGETS_ARLIB = # $(LIB_PREFIX)ResourceTest$(ARLIB_SUFFIX) +LIB_TARGETS_EXP = $(LIB_TARGETS_IMPLIB:$(ARLIB_SUFFIX)=$(EXP_SUFFIX)) +LIB_TARGETS_MISC = +# targets to build during CMDS phase +CMD_TARGETS_SHLIB = +CMD_TARGETS_EXE = $(EXECUTABLE) +CMD_TARGETS_MISC = opaipcalc +# files to remove during clean phase +CLEAN_TARGETS_MISC = +CLEAN_TARGETS = $(OBJECTS) $(RSCOBJECTS) $(IDL_TARGETS) $(CLEAN_TARGETS_MISC) +# other files to remove during clobber phase +CLOBBER_TARGETS_MISC= +# sub-directory to install to within bin +BIN_SUBDIR = +# sub-directory to install to within include +INCLUDE_SUBDIR = + +# Additional Settings +#CLOCALDEBUG = User defined C debugging compilation flags [Empty] +#CCLOCALDEBUG = User defined C++ debugging compilation flags [Empty] +#CLOCAL = User defined C flags for compiling [Empty] +#CCLOCAL = User defined C++ flags for compiling [Empty] +#BSCLOCAL = User flags for Browse File Builder [Empty] +#DEPENDLOCAL = user defined makedepend flags [Empty] +#LINTLOCAL = User defined lint flags [Empty] +#LOCAL_INCLUDE_DIRS = User include directories to search for C/C++ headers [Empty] +#LDLOCAL = User defined C flags for linking [Empty] +#IMPLIBLOCAL = User flags for Object Lirary Manager [Empty] +#MIDLLOCAL = User flags for IDL compiler [Empty] +#RSCLOCAL = User flags for resource compiler [Empty] +#LOCALDEPLIBS = User libraries to include in dependencies [Empty] +#LOCALLIBS = User libraries to use when linking [Empty] +# (in addition to LOCALDEPLIBS) +#LOCAL_LIB_DIRS = User library directories for libpaths [Empty] + +CLOCAL = $(CPIE) + +# Include Make Rules definitions and rules +include $(TL_DIR)/IbaTools/Makerules.module + +#=============================================================================# +# Overrides: +#-----------------------------------------------------------------------------# +#CCOPT = # C++ optimization flags, default lets build config decide +#COPT = # C optimization flags, default lets build config decide +#SUBSYSTEM = Subsystem to build for (none, console or windows) [none] +# (Windows Only) +#USEMFC = How Windows MFC should be used (none, static, shared, no_mfc) [none] +# (Windows Only) +#=============================================================================# + +#=============================================================================# +# Rules: +#-----------------------------------------------------------------------------# +# process Sub-directories +include $(TL_DIR)/Makerules/Maketargets.toplevel + +# build cmds and libs +include $(TL_DIR)/Makerules/Maketargets.build + +# install for includes, libs and cmds phases +include $(TL_DIR)/Makerules/Maketargets.install + +# install for stage phase +include $(TL_DIR)/Makerules/Maketargets.stage + +# Unit test execution +#include $(TL_DIR)/Makerules/Maketargets.runtest + +#=============================================================================# + +#=============================================================================# +# DO NOT DELETE THIS LINE -- make depend depends on it. +#=============================================================================# diff --git a/IbaTools/opaipcalc/README b/IbaTools/opaipcalc/README new file mode 100644 index 0000000..dc88a07 --- /dev/null +++ b/IbaTools/opaipcalc/README @@ -0,0 +1 @@ +Tool to help compute IP netmask, broadcast and network from an IP address diff --git a/IbaTools/opaipcalc/opaipcalc.sh b/IbaTools/opaipcalc/opaipcalc.sh new file mode 100755 index 0000000..54942d8 --- /dev/null +++ b/IbaTools/opaipcalc/opaipcalc.sh @@ -0,0 +1,178 @@ +#!/usr/bin/perl +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] + +use Socket; +use Getopt::Long; + +sub broadcast_addr() +{ + my($address, $netmask) = @_; + my($tempaddress); + my($tempmask); + my($rval); + + # compute computational address + $tempaddress = inet_aton($address); + if (!defined($tempaddress)) + { + return undef; + } + $tempaddress = unpack("N",$tempaddress); + + # compute computational netmask + $tempmask = inet_aton($netmask); + if (!defined($tempmask)) + { + return undef; + } + $tempmask = unpack("N",$tempmask); + + $rval = $tempmask & $tempaddress; + $rval |= (~$tempmask & 0xfffffff); + $rval = pack("N",$rval); + $rval = inet_ntoa($rval); + return $rval; +} + +sub default_netmask() +{ + my($address) = @_; + my($tempaddress); + my($mask); + my($rval); + + $tempaddress = inet_aton($address); + if (!defined($tempaddress)) + { + return undef; + } + $tempaddress = unpack("N",$tempaddress); + if (($tempaddress & 0x80000000) == 0x00000000) { + $mask = 0xff000000; + } elsif (($tempaddress & 0x40000000) == 0x00000000) { + $mask = 0xffff0000; + } else { + $mask = 0xffffff00; + } + $rval = pack("N",$mask); + $rval = inet_ntoa($rval); + return $rval; +} + +sub network_number() +{ + my($address, $netmask) = @_; + my($tempinetaddr); + my($tempmask); + my($rval); + + $tempinetaddr = inet_aton($address); + if (!defined($tempinetaddr)) + { + return undef; + } + $tempinetaddr = unpack("N",$tempinetaddr); + + # compute computational netmask + $tempmask = inet_aton($netmask); + if (!defined($tempmask)) + { + return undef; + } + $tempmask = unpack("N",$tempmask); + $tempinetaddr &= $tempmask; + $rval = pack("N",$tempinetaddr); + $rval = inet_ntoa($rval); + return $rval; +} + +sub print_usage() { + print STDERR +"Usage: opaipcalc [OPTION...] ip_address [netmask]\n", +" -b, --broadcast Display calculated broadcast address\n", +" -m, --netmask Display default netmask for IP (class A, B, or C)\n", +" -n, --network Display network address\n", +"Help options:\n", +" -?, --help Show this help message\n", +} + +$ret = &GetOptions(\%longopts, 'broadcast|b', 'netmask|m', 'network|n'); +if (!$ret || ($#ARGV < 0 || $#ARGV > 1)) +{ + &print_usage; + exit 1; +} + +if ($#ARGV == 0) { + if ($ARGV[0] =~ /([\d.]+)\/([\d.]+)/) { + $address = $1; + $mask = $2; + } else { + $address = $ARGV[0]; + } +} else { + $address = $ARGV[0]; + $mask = $ARGV[1]; +} + +$mask = &default_netmask($address) unless defined($mask); +$network = &network_number($address,$mask); +if (!defined($network)) +{ + print STDERR "Invalid address or mask\n"; + &print_usage(); + exit 1; +} +$broadcast = &broadcast_addr($address,$mask); +if (!defined($broadcast)) +{ + print STDERR "Invalid address or mask\n"; + &print_usage(); + exit 1; +} + +$usage=1; +foreach $option (sort keys %longopts) { + $usage=0; + SWITCH: { + print ('NETWORK=', &network_number($address,$mask), "\n"), last SWITCH if $option eq 'network'; + print ('BROADCAST=', &broadcast_addr($address,$mask),"\n"), last SWITCH if $option eq 'broadcast'; + print ('NETMASK=', $mask,"\n"), last SWITCH if $option eq 'netmask'; + } +} +if ($usage) { + &print_usage; + exit 1; +} + +exit 0; + diff --git a/IbaTools/opalinkanalysis/Makefile b/IbaTools/opalinkanalysis/Makefile new file mode 100644 index 0000000..7cd327a --- /dev/null +++ b/IbaTools/opalinkanalysis/Makefile @@ -0,0 +1,153 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** +# Makefile for opalinkanalysis + +# Include Make Control Settings +include $(TL_DIR)/$(PROJ_FILE_DIR)/Makesettings.project + +#=============================================================================# +# Definitions: +#-----------------------------------------------------------------------------# + +# Name of SubProjects +DS_SUBPROJECTS = +# name of executable or downloadable image +EXECUTABLE = #$(BUILDDIR)/opalinkanalysis$(EXE_SUFFIX) +# list of sub directories to build +DIRS = +# C files (.c) +CFILES = \ + # Add more c files here +# C++ files (.cpp) +CCFILES = \ + # Add more cpp files here +# lex files (.lex) +LFILES = \ + # Add more lex files here +# archive library files (basename, $ARFILES will add MOD_LIB_DIR/prefix and suffix) +LIBFILES= +# Windows Resource Files (.rc) +RSCFILES = +# Windows IDL File (.idl) +IDLFILE = +# Windows Linker Module Definitions (.def) file for dll's +DEFFILE = +# targets to build during INCLUDES phase (add public includes here) +INCLUDE_TARGETS = \ + # Add more h hpp files here + +# Non-compiled files +MISC_FILES = + +# all source files +SOURCES = $(CFILES) $(CCFILES) $(LFILES) $(RSCFILES) $(IDLFILE) +# Source files to include in DSP File +DSP_SOURCES = $(INCLUDE_TARGETS) $(SOURCES) $(MISC_FILES) \ + $(RSCFILES) $(DEFFILE) $(MAKEFILE) +# all object files +OBJECTS = $(CFILES:.c=$(OBJ_SUFFIX)) $(CCFILES:.cpp=$(OBJ_SUFFIX)) \ + $(LFILES:.lex=$(OBJ_SUFFIX)) +RSCOBJECTS = $(RSCFILES:.rc=$(RES_SUFFIX)) +# targets to build during LIBS phase +LIB_TARGETS_IMPLIB = +LIB_TARGETS_ARLIB = # $(LIB_PREFIX)ResourceTest$(ARLIB_SUFFIX) +LIB_TARGETS_EXP = $(LIB_TARGETS_IMPLIB:$(ARLIB_SUFFIX)=$(EXP_SUFFIX)) +LIB_TARGETS_MISC = +# targets to build during CMDS phase +CMD_TARGETS_SHLIB = +CMD_TARGETS_EXE = $(EXECUTABLE) +CMD_TARGETS_MISC = opalinkanalysis +# files to remove during clean phase +CLEAN_TARGETS_MISC = +CLEAN_TARGETS = $(OBJECTS) $(RSCOBJECTS) $(IDL_TARGETS) $(CLEAN_TARGETS_MISC) +# other files to remove during clobber phase +CLOBBER_TARGETS_MISC= +# sub-directory to install to within bin +BIN_SUBDIR = +# sub-directory to install to within include +INCLUDE_SUBDIR = + +# Additional Settings +#CLOCALDEBUG = User defined C debugging compilation flags [Empty] +#CCLOCALDEBUG = User defined C++ debugging compilation flags [Empty] +#CLOCAL = User defined C flags for compiling [Empty] +#CCLOCAL = User defined C++ flags for compiling [Empty] +#BSCLOCAL = User flags for Browse File Builder [Empty] +#DEPENDLOCAL = user defined makedepend flags [Empty] +#LINTLOCAL = User defined lint flags [Empty] +#LOCAL_INCLUDE_DIRS = User include directories to search for C/C++ headers [Empty] +#LDLOCAL = User defined C flags for linking [Empty] +#IMPLIBLOCAL = User flags for Object Lirary Manager [Empty] +#MIDLLOCAL = User flags for IDL compiler [Empty] +#RSCLOCAL = User flags for resource compiler [Empty] +#LOCALDEPLIBS = User libraries to include in dependencies [Empty] +#LOCALLIBS = User libraries to use when linking [Empty] +# (in addition to LOCALDEPLIBS) +#LOCAL_LIB_DIRS = User library directories for libpaths [Empty] + +CLOCAL = $(CPIE) +# Include Make Rules definitions and rules +include $(TL_DIR)/IbaTools/Makerules.module + +#=============================================================================# +# Overrides: +#-----------------------------------------------------------------------------# +#CCOPT = # C++ optimization flags, default lets build config decide +#COPT = # C optimization flags, default lets build config decide +#SUBSYSTEM = Subsystem to build for (none, console or windows) [none] +# (Windows Only) +#USEMFC = How Windows MFC should be used (none, static, shared, no_mfc) [none] +# (Windows Only) +#=============================================================================# + +#=============================================================================# +# Rules: +#-----------------------------------------------------------------------------# +# process Sub-directories +include $(TL_DIR)/Makerules/Maketargets.toplevel + +# build cmds and libs +include $(TL_DIR)/Makerules/Maketargets.build + +# install for includes, libs and cmds phases +include $(TL_DIR)/Makerules/Maketargets.install + +# install for stage phase +#include $(TL_DIR)/Makerules/Maketargets.stage +STAGE:: + $(VS)$(STAGE_INSTALL) $(STAGE_INSTALL_DIR_OPT) $(PROJ_STAGE_FASTFABRIC_DIR) opalinkanalysis + +# Unit test execution +#include $(TL_DIR)/Makerules/Maketargets.runtest + +#=============================================================================# + +#=============================================================================# +# DO NOT DELETE THIS LINE -- make depend depends on it. +#=============================================================================# diff --git a/IbaTools/opalinkanalysis/opalinkanalysis.sh b/IbaTools/opalinkanalysis/opalinkanalysis.sh new file mode 100755 index 0000000..b4581cb --- /dev/null +++ b/IbaTools/opalinkanalysis/opalinkanalysis.sh @@ -0,0 +1,681 @@ +#!/bin/bash +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] + +# analyzes all the links in the fabric + +# optional override of defaults +if [ -f /etc/opa/opafastfabric.conf ] +then + . /etc/opa/opafastfabric.conf +fi + +. /usr/lib/opa/tools/opafastfabric.conf.def + +. /usr/lib/opa/tools/ff_funcs + +tempfile="$(mktemp)" +trap "rm -f $tempfile; exit 1" SIGHUP SIGTERM SIGINT +trap "rm -f $tempfile" EXIT + +punchlist=$FF_RESULT_DIR/punchlist.csv +del=';' +timestamp=$(date +"%Y/%m/%d %T") + +Usage_full() +{ + echo "Usage: opalinkanalysis [-U] [-t portsfile] [-p ports] [-T topology_input]" >&2 + echo " -X snapshot_input] [-x snapshot_suffix] [-c file] reports ..." >&2 + echo " or" >&2 + echo " opalinkanalysis --help" >&2 + echo " --help - produce full help text" >&2 + echo " -U - omit unexpected devices and links in punchlist from verify reports" >&2 + echo " -t portsfile - file with list of local HFI ports used to access" >&2 + echo " fabric(s) for analysis, default is $CONFIG_DIR/opa/ports" >&2 + echo " -p ports - list of local HFI ports used to access fabric(s) for analysis" >&2 + echo " default is 1st active port" >&2 + echo " This is specified as hfi:port" >&2 + echo " 0:0 = 1st active port in system" >&2 + echo " 0:y = port y within system" >&2 + echo " x:0 = 1st active port on HFI x" >&2 + echo " x:y = HFI x, port y" >&2 + echo " The first HFI in the system is 1. The first port on an HFI is 1." >&2 + echo " -T topology_input - name of a topology input file to use." >&2 + echo " Any %P markers in this filename will be replaced with the" >&2 + echo " hfi:port being operated on (such as 0:0 or 1:2)" >&2 + echo " default is $CONFIG_DIR/opa/topology.%P.xml" >&2 + echo " if NONE is specified, will not use any topology_input files" >&2 + echo " See opareport for more information on topology_input files" >&2 + echo " -X snapshot_input - perform analysis using data in snapshot_input" >&2 + echo " snapshot_input must have been generated via a previous" >&2 + echo " opareport -o snapshot run." >&2 + echo " If errors report is specified, snapshot must have been generated" >&2 + echo " with opareport -s option" >&2 + echo " When this option is used, only one port may be specified" >&2 + echo " to select a topology_input file (unless -T specified)">&2 + echo " When this option is used, clearerrors and clearhwerrors reports" >&2 + echo " are not permitted" >&2 + echo " -x snapshot_suffix - create a snapshot file per selected port" >&2 + echo " The files will be created in FF_RESULT_DIR with names of the form:">&2 + echo " snapshotSUFFIX.HFI:PORT.xml.">&2 + echo " -c file - error thresholds config file" >&2 + echo " default is $CONFIG_DIR/opa/opamon.si.conf" >&2 + echo " reports - The following reports are supported" >&2 + echo " errors - link error analysis" >&2 + echo " slowlinks - links running slower than expected" >&2 + echo " misconfiglinks - links configured to run slower than supported" >&2 + echo " misconnlinks - links connected with mismatched speed potential" >&2 + echo " all - includes all reports above" >&2 + echo " verifylinks - verify links against topology input" >&2 + echo " verifyextlinks - verify links against topology input" >&2 + echo " limit analysis to links external to systems" >&2 + echo " verifyfilinks - verify links against topology input" >&2 + echo " limit analysis to FI links" >&2 + echo " verifyislinks - verify links against topology input" >&2 + echo " limit analysis to inter-switch links" >&2 + echo " verifyextislinks - verify links against topology input" >&2 + echo " limit analysis to inter-switch links external to systems" >&2 + echo " verifyfis - verify FIs against topology input" >&2 + echo " verifysws - verify Switches against topology input" >&2 + echo " verifynodes - verify FIs, Switches and against topology input" >&2 + echo " verifysms - verify SMs against topology input" >&2 + echo " verifyall - verifies links, FIs, Switches, and SMs" >&2 + echo " against topology input" >&2 + echo " clearerrors - clear error counters, uses PM if available" >&2 + echo " clearhwerrors - clear HW error counters, bypasses PM" >&2 + echo " clear - includes clearerrors and clearhwerrors" >&2 + echo >&2 + echo "A punchlist of bad links is also appended to FF_RESULT_DIR/punchlist.csv" >&2 + echo >&2 + echo " Environment:" >&2 + echo " PORTS - list of ports, used in absence of -t and -p" >&2 + echo " PORTS_FILE - file containing list of ports, used in absence of -t and -p" >&2 + echo " FF_TOPOLOGY_FILE - file containing topology_input, used in absence of -T" >&2 + echo "example:">&2 + echo " opalinkanalysis errors" >&2 + echo " opalinkanalysis errors clearerrors" >&2 + echo " opalinkanalysis -p '1:1 1:2 2:1 2:2'" >&2 + exit 0 +} + +Usage() +{ + echo "Usage: opalinkanalysis [-U] reports ..." >&2 + echo " or" >&2 + echo " opalinkanalysis --help" >&2 + echo " --help - produce full help text" >&2 + echo >&2 + echo " -U - omit unexpected devices and links in punchlist from verify reports" >&2 + echo " reports - The following reports are supported" >&2 + echo " errors - link error analysis" >&2 + echo " slowlinks - links running slower than expected" >&2 + echo " misconfiglinks - links configured to run slower than supported" >&2 + echo " misconnlinks - links connected with mismatched speed potential" >&2 + echo " all - includes all reports above" >&2 + echo " verifylinks - verify links against topology input" >&2 + echo " verifyextlinks - verify links against topology input" >&2 + echo " limit analysis to links external to systems" >&2 + echo " verifyfis - verify FIs against topology input" >&2 + echo " verifysws - verify Switches against topology input" >&2 + echo " verifynodes - verify FIs, Switches and against topology input" >&2 + echo " verifysms - verify SMs against topology input" >&2 + echo " verifyall - verifies links, FIs, Switches, and SMs" >&2 + echo " against topology input" >&2 + echo " clearerrors - clear error counters, uses PM if available" >&2 + echo " clearhwerrors - clear HW error counters, bypasses PM" >&2 + echo " clear - includes clearerrors and clearhwerrors" >&2 + echo >&2 + echo "A punchlist of bad links is also appended to FF_RESULT_DIR/punchlist.csv" >&2 + echo >&2 + echo "example:">&2 + echo " opalinkanalysis errors" >&2 + echo " opalinkanalysis errors clearerrors" >&2 + exit 2 +} + +if [ x"$1" = "x--help" ] +then + Usage_full +fi + +append_punchlist() +# $1 = device +# $2 = issue +{ + echo "$timestamp$del$1$del$2" >> $punchlist +} + +set_beaconing_led() +# $1 = nodedesc +# $2 = port num +{ + if [ "$read_snapshot" = n ] + then + #echo "setting led on node:$1 port:$2" + #Map node desc to lid so we can use opaportconfig tool to enable LED + nodelid=$(opasaquery -d "$1" -o lid | head -n 1) + if [ "$nodelid" != "No Records Returned" ] + then + /usr/sbin/opaportconfig -l $nodelid -m $2 ledon + fi + fi +} + +gen_errors_punchlist() +# $@ = snapshot, port and/or topology selection options for opareport +{ + ( + # TBD - is cable information available? + export IFS=';' + port1= + #opareport -q "$@" -o errors -x | /usr/sbin/opaxmlextract -H -d \; -e LinkErrors.Link.Port.NodeGUID -e LinkErrors.Link.Port.PortNum -e LinkErrors.Link.Port.NodeType -e LinkErrors.Link.Port.NodeDesc|while read line + opareport -q "$@" -o errors -x | /usr/sbin/opaxmlextract -H -d \; -e LinkErrors.Link.Port.NodeDesc -e LinkErrors.Link.Port.PortNum|while read desc port + do + if [ x"$port1" = x ] + then + port1="$desc p$port" + else + append_punchlist "$port1 $desc p$port" "Link errors" + port1= + fi + + if [ x"$port" != x ] && [ x"$desc" != x ] + then + set_beaconing_led "$desc" $port + fi + done + ) +} + +gen_slowlinks_punchlist() +# $@ = snapshot, port and/or topology selection options for opareport +{ + ( + # TBD - is cable information available? + export IFS=';' + port1= + #opareport -q "$@" -o slowlinks -x | /usr/sbin/opaxmlextract -H -d \; -e LinksExpected.Link.Port.NodeGUID -e LinksExpected.Link.Port.PortNum -e LinksExpected.Link.Port.NodeType -e LinksExpected.Link.Port.NodeDesc|while read line + opareport -q "$@" -o slowlinks -x | /usr/sbin/opaxmlextract -H -d \; -e LinksExpected.Link.Port.NodeDesc -e LinksExpected.Link.Port.PortNum|while read desc port + do + if [ x"$port1" = x ] + then + port1="$desc p$port" + else + append_punchlist "$port1 $desc p$port" "Link speed/width lower than expected" + port1= + fi + + if [ x"$port" != x ] && [ x"$desc" != x ] + then + set_beaconing_led "$desc" $port + fi + done + ) +} + +gen_misconfiglinks_punchlist() +# $@ = snapshot, port and/or topology selection options for opareport +{ + ( + # TBD - is cable information available? + export IFS=';' + port1= + #opareport -q "$@" -o misconfiglinks -x | /usr/sbin/opaxmlextract -H -d \; -e LinksConfig.Link.Port.NodeGUID -e LinksConfig.Link.Port.PortNum -e LinksConfig.Link.Port.NodeType -e LinksConfig.Link.Port.NodeDesc|while read line + opareport -q "$@" -o misconfiglinks -x | /usr/sbin/opaxmlextract -H -d \; -e LinksConfig.Link.Port.NodeDesc -e LinksConfig.Link.Port.PortNum|while read desc port + do + if [ x"$port1" = x ] + then + port1="$desc p$port" + else + append_punchlist "$port1 $desc p$port" "Link speed/width configured lower than supported" + port1= + fi + + if [ x"$port" != x ] && [ x"$desc" != x ] + then + set_beaconing_led "$desc" $port + fi + done + ) +} + +gen_misconnlinks_punchlist() +# $@ = snapshot, port and/or topology selection options for opareport +{ + ( + # TBD - is cable information available? + export IFS=';' + line1= + #opareport -q "$@" -o misconnlinks -x | /usr/sbin/opaxmlextract -H -d \; -e LinksMismatched.Link.Port.NodeGUID -e LinksMismatched.Link.Port.PortNum -e LinksMismatched.Link.Port.NodeType -e LinksMismatched.Link.Port.NodeDesc|while read line + opareport -q "$@" -o misconnlinks -x | /usr/sbin/opaxmlextract -H -d \; -e LinksMismatched.Link.Port.NodeDesc -e LinksMismatched.Link.Port.PortNum|while read desc port + do + if [ x"$line1" = x ] + then + line1="$desc p$port" + else + append_punchlist "$line1 $desc p$port" "Link speed/width mismatch" + line1= + fi + + if [ x"$port" != x ] && [ x"$desc" != x ] + then + set_beaconing_led "$desc" $port + fi + done + ) +} + +append_verify_punchlist() +# $1 = device +# $2 = issue +{ + if [ $skip_unexpected = y ] + then + case "$2" in + Unexpected*) > /dev/null;; + *) echo "$timestamp$del$1$del$2" >> $punchlist;; + esac + else + echo "$timestamp$del$1$del$2" >> $punchlist + fi + +} + +process_links_csv() +# stdin is a csv with all the bad links from a verify*links report +{ + ( + export IFS=';' + port1= + port2= + foundPort= + prob= + while read desc port portprob linkprob + do + if [ x"$port1" = x ] + then + port1="$desc p$port" + prob="$portprob" + if [ x"$prob" = x ] + then + prob=$linkprob # unlikely to occur here + fi + elif [ x"$port2" = x ] + then + port2="$desc p$port" + if [ x"$prob" = x ] + then + prob=$portprob + fi + if [ x"$prob" = x ] + then + prob=$linkprob # unlikely to occur here + fi + fi + + if [ x"$linkprob" != x ] + then + if [ x"$prob" = x ] + then + prob=$linkprob + fi + + # more port information available + if [ x"$desc" != x ] + then + foundPort="$desc p$port" + fi + + append_verify_punchlist "$port1 $port2" "$prob $foundPort" + port1= + port2= + foundPort= + prob= + fi + + if [ x"$port" != x ] && [ x"$desc" != x ] + then + set_beaconing_led "$desc" $port + fi + done + ) +} + +gen_verifylinks_punchlist() +# $@ = snapshot, port and/or topology selection options for opareport +{ + # TBD - is cable information available? + eval opareport -q "$@" -o verifylinks -x | /usr/sbin/opaxmlextract -H -d \; -e VerifyLinks.Link.Port.NodeDesc -e VerifyLinks.Link.Port.PortNum -e VerifyLinks.Link.Port.Problem -e VerifyLinks.Link.Problem|process_links_csv +} + +gen_verifyextlinks_punchlist() +# $@ = snapshot, port and/or topology selection options for opareport +{ + # TBD - is cable information available? + eval opareport -q "$@" -o verifyextlinks -x | /usr/sbin/opaxmlextract -H -d \; -e VerifyExtLinks.Link.Port.NodeDesc -e VerifyExtLinks.Link.Port.PortNum -e VerifyExtLinks.Link.Port.Problem -e VerifyExtLinks.Link.Problem|process_links_csv +} + +gen_verifyfilinks_punchlist() +# $@ = snapshot, port and/or topology selection options for opareport +{ + # TBD - is cable information available? + eval opareport -q "$@" -o verifyfilinks -x | /usr/sbin/opaxmlextract -H -d \; -e VerifyFILinks.Link.Port.NodeDesc -e VerifyFILinks.Link.Port.PortNum -e VerifyFILinks.Link.Port.Problem -e VerifyFILinks.Link.Problem|process_links_csv +} + +gen_verifyislinks_punchlist() +# $@ = snapshot, port and/or topology selection options for opareport +{ + # TBD - is cable information available? + eval opareport -q "$@" -o verifyislinks -x | /usr/sbin/opaxmlextract -H -d \; -e VerifyISLinks.Link.Port.NodeDesc -e VerifyISLinks.Link.Port.PortNum -e VerifyISLinks.Link.Port.Problem -e VerifyISLinks.Link.Problem|process_links_csv +} + +gen_verifyextislinks_punchlist() +# $@ = snapshot, port and/or topology selection options for opareport +{ + # TBD - is cable information available? + eval opareport -q "$@" -o verifyextislinks -x | /usr/sbin/opaxmlextract -H -d \; -e VerifyExtISLinks.Link.Port.NodeDesc -e VerifyExtISLinks.Link.Port.PortNum -e VerifyExtISLinks.Link.Port.Problem -e VerifyExtISLinks.Link.Problem|process_links_csv +} + +gen_verifyfis_punchlist() +# $@ = snapshot, port and/or topology selection options for opareport +{ + ( + export IFS=';' + #eval opareport -q "$@" -o verifyfis -x | /usr/sbin/opaxmlextract -H -d \; -e VerifyFIs.Node.NodeGUID -e VerifyFIs.Node.Desc -e VerifyFIs.Node.Problem|while read line + eval opareport -q "$@" -o verifyfis -x | /usr/sbin/opaxmlextract -H -d \; -e VerifyFIs.Node.NodeDesc -e VerifyFIs.Node.Problem |while read desc prob + do + append_verify_punchlist "$desc" "$prob" + done + ) +} + +gen_verifysws_punchlist() +# $@ = snapshot, port and/or topology selection options for opareport +{ + ( + export IFS=';' + #eval opareport -q "$@" -o verifysws -x | /usr/sbin/opaxmlextract -H -d \; -e VerifySWs.Node.NodeGUID -e VerifySWs.Node.Desc -e VerifySWs.Node.Problem|while read line + eval opareport -q "$@" -o verifysws -x | /usr/sbin/opaxmlextract -H -d \; -e VerifySWs.Node.NodeDesc -e VerifySWs.Node.Problem |while read desc prob + do + append_verify_punchlist "$desc" "$prob" + done + ) +} + +gen_verifysms_punchlist() +# $@ = snapshot, port and/or topology selection options for opareport +{ + ( + export IFS=';' + #eval opareport -q "$@" -o verifysms -x | /usr/sbin/opaxmlextract -H -d \; -e VerifySMs.SM.NodeGUID -e VerifySMs.SM.Desc -e VerifySMs.SM.Problem|while read line + eval opareport -q "$@" -o verifysms -x | /usr/sbin/opaxmlextract -H -d \; -e VerifySMs.SM.NodeDesc -e VerifySMs.SM.PortNum -e VerifySMs.SM.Problem |while read desc port prob + do + # port number is optional in topology_input, so for missing SMs + # it might not be reported + if [ x"$port" != x ] + then + append_verify_punchlist "$desc p$port" "$prob" + else + append_verify_punchlist "$desc" "$prob" + fi + done + ) +} + +report_opts="" +verify_opts="" +errors=n +clearerrors=n +clearhwerrors=n +slowlinks=n +misconfiglinks=n +misconnlinks=n +verifylinks=n +verifyextlinks=n +verifyfilinks=n +verifyislinks=n +verifyextislinks=n +verifyfis=n +verifysws=n +verifysms=n +reports="" +read_snapshot=n +snapshot_input= +save_snapshot=n +snapshot_suffix= +skip_unexpected=n +config_file="$CONFIG_DIR/opa/opamon.si.conf" +while getopts Ut:p:T:X:x:c: param +do + case $param in + U) skip_unexpected=y;; + p) export PORTS="$OPTARG";; + t) export PORTS_FILE="$OPTARG";; + T) export FF_TOPOLOGY_FILE="$OPTARG";; + X) read_snapshot=y; export snapshot_input="$OPTARG";; + x) save_snapshot=y; export snapshot_suffix="$OPTARG";; + c) config_file="$OPTARG";; + ?) + Usage;; + esac +done +shift $((OPTIND -1)) +if [ $# -le 0 ] +then + echo "opalinkanalysis: Error: must specify at least 1 report" >&2 + Usage +fi +while [ $# -gt 0 ] +do + case "$1" in + errors) errors=y;; + slowlinks) slowlinks=y;; + misconfiglinks) misconfiglinks=y;; + misconnlinks) misconnlinks=y;; + all) errors=y; slowlinks=y; misconfiglinks=y; misconnlinks=y;; + verifylinks) verifylinks=y;; + verifyextlinks) verifyextlinks=y;; + verifyfilinks) verifyfilinks=y;; + verifyislinks) verifyislinks=y;; + verifyextislinks) verifyextislinks=y;; + verifyfis) verifyfis=y;; + verifysws) verifysws=y;; + verifynodes) verifyfis=y; verifysws=y;; + verifysms) verifysms=y;; + verifyall) verifylinks=y; verifyfis=y; verifysws=y; verifysms=y;; + clearerrors) clearerrors=y;; + clearhwerrors) clearhwerrors=y;; + clear) clearerrors=y; clearhwerrors=y;; + *) + echo "opalinkanalysis: Invalid report: $1" >&2 + Usage;; + esac + shift +done + +for report in errors slowlinks misconfiglinks misconnlinks verifylinks verifyextlinks verifyfilinks verifyislinks verifyextislinks verifyfis verifysws verifysms +do + yes=$(eval echo \$$report) + if [ $yes = y ] + then + case $report in + verify*) + verify_opts="$verify_opts -o $report" + reports="$reports $report";; + *) + report_opts="$report_opts -o $report" + reports="$reports $report";; + esac + fi +done + +snapshopt_opts= +if [ $errors = y ] +then + snapshopt_opts="-s" + report_opts="$report_opts -c '$config_file'" +fi + +if [ $read_snapshot = y ] +then + if [ $clearerrors = y -o $clearhwerrors = y ] + then + echo "opalinkanalysis: errors and clearhwerrors reports not available with -X" >&2 + Usage + fi + if [ $save_snapshot = y ] + then + echo "opalinkanalysis: -X and -x options are mutually exclusive" >&2 + fi +fi + +check_ports_args opalinkanalysis + +ports=0 +for hfi_port in $PORTS +do + ports=$(($ports + 1)) +done +if [ $ports -lt 1 ] +then + # should not happen, but be safe + ports=1 + PORTS="0:0" +fi +if [ $read_snapshot = y -a $ports -gt 1 ] +then + echo "opalinkanalysis: -X option cannot be used with more than 1 port" >&2 + Usage +fi + + +status=0 +for hfi_port in $PORTS +do + # TBD - make some ff_funcs to handle these conversions and checks + hfi=$(expr $hfi_port : '\([0-9]*\):[0-9]*') + port=$(expr $hfi_port : '[0-9]*:\([0-9]*\)') + if [ "$hfi" = "" -o "$port" = "" ] + then + echo "opalinkanalysis: Error: Invalid port specification: $hfi_port" >&2 + status=1 + continue + fi + if [ "$port" -eq 0 ] + then + port_opts="-h $hfi" # default port to 1st active + else + port_opts="-h $hfi -p $port" + fi + resolve_topology_file opalinkanalysis "$hfi:$port" + topt="" + if [ "$TOPOLOGY_FILE" != "" ] + then + topt="-T '$TOPOLOGY_FILE'" + fi + + if [ "$read_snapshot" = n ] + then + if [ $ports -gt 1 ] + then + echo "Fabric $hfi:$port Analysis:" + fi + if [ "$save_snapshot" = y ] + then + snapshot_input=$FF_RESULT_DIR/snapshot$snapshot_suffix.$hfi:$port.xml + else + snapshot_input=$tempfile + fi + # generate a snapshot per fabric then analyze + opareport $port_opts $snapshopt_opts -o snapshot > $snapshot_input + fi + + # generate human readable reports + if [ x"$report_opts" != x ] + then + eval opareport -X $snapshot_input $topt $report_opts + fi + + if [ x"$verify_opts" != x ] + then + if [ "$TOPOLOGY_FILE" != "" ] + then + eval opareport -X $snapshot_input $topt $verify_opts + else + echo "Unable to verify topology for $hfi:$port, no topology file found" >&2 + status=1 + fi + fi + + # note: if snapshot=y, these reports are not permitted + if [ "$clearerrors" = y ] + then + opareport $port_opts -C -c "$config_file" -o none + fi + if [ "$clearhwerrors" = y ] + then + opareport $port_opts -M -C -c "$config_file" -o none + fi + + # now generate punchlist + for report in $reports + do + case "$report" in + errors) gen_errors_punchlist -X $snapshot_input -c "$config_file";; + slowlinks) gen_slowlinks_punchlist -X $snapshot_input;; + misconfiglinks) gen_misconfiglinks_punchlist -X $snapshot_input;; + misconnlinks) gen_misconnlinks_punchlist -X $snapshot_input;; + verifylinks) [ "$TOPOLOGY_FILE" != "" ] && gen_verifylinks_punchlist -X $snapshot_input $topt;; + verifyextlinks) [ "$TOPOLOGY_FILE" != "" ] && gen_verifyextlinks_punchlist -X $snapshot_input $topt;; + verifyfilinks) [ "$TOPOLOGY_FILE" != "" ] && gen_verifyfilinks_punchlist -X $snapshot_input $topt;; + verifyislinks) [ "$TOPOLOGY_FILE" != "" ] && gen_verifyislinks_punchlist -X $snapshot_input $topt;; + verifyextislinks) [ "$TOPOLOGY_FILE" != "" ] && gen_verifyextislinks_punchlist -X $snapshot_input $topt;; + verifyfis) [ "$TOPOLOGY_FILE" != "" ] && gen_verifyfis_punchlist -X $snapshot_input $topt;; + verifysws) [ "$TOPOLOGY_FILE" != "" ] && gen_verifysws_punchlist -X $snapshot_input $topt;; + verifysms) [ "$TOPOLOGY_FILE" != "" ] && gen_verifysms_punchlist -X $snapshot_input $topt;; + *) continue;; # should not happen + esac + done + + if [ $read_snapshot = y ] + then + break + fi + + if [ $ports -gt 1 ] + then + echo "-------------------------------------------------------------------------------" + fi + +done + +rm -f $tempfile +exit $status diff --git a/IbaTools/opamon/Makefile b/IbaTools/opamon/Makefile new file mode 100644 index 0000000..d35c62f --- /dev/null +++ b/IbaTools/opamon/Makefile @@ -0,0 +1,164 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** +# Makefile for opamon + +# Include Make Control Settings +include $(TL_DIR)/$(PROJ_FILE_DIR)/Makesettings.project + +#=============================================================================# +# Definitions: +#-----------------------------------------------------------------------------# + +# Name of SubProjects +DS_SUBPROJECTS = +# name of executable or downloadable image +EXECUTABLE = +# list of sub directories to build +DIRS = +# C files (.c) +CFILES = \ + # Add more c files here +# C++ files (.cpp) +CCFILES = \ + # Add more cpp files here +# lex files (.lex) +LFILES = \ + # Add more lex files here +# archive library files (basename, $ARFILES will add MOD_LIB_DIR/prefix and suffix) +LIBFILES= +# Windows Resource Files (.rc) +RSCFILES = +# Windows IDL File (.idl) +IDLFILE = +# Windows Linker Module Definitions (.def) file for dll's +DEFFILE = +# targets to build during INCLUDES phase (add public includes here) +INCLUDE_TARGETS = \ + # Add more h hpp files here +# Non-compiled files +MISC_FILES= opamon.conf opamon.si.conf opamon.conf-sample opamon.si.conf-sample + # Add more files here +# all source files +SOURCES = $(CFILES) $(CCFILES) $(LFILES) $(RSCFILES) $(IDLFILE) +# Source files to include in DSP File +DSP_SOURCES = $(INCLUDE_TARGETS) $(SOURCES) $(MISC_FILES) \ + $(RSCFILES) $(DEFFILE) $(MAKEFILE) +# all object files +OBJECTS = $(CFILES:.c=$(OBJ_SUFFIX)) $(CCFILES:.cpp=$(OBJ_SUFFIX)) \ + $(LFILES:.lex=$(OBJ_SUFFIX)) +RSCOBJECTS = $(RSCFILES:.rc=$(RES_SUFFIX)) +# targets to build during LIBS phase +LIB_TARGETS_IMPLIB = +LIB_TARGETS_ARLIB = # $(LIB_PREFIX)ResourceTest$(ARLIB_SUFFIX) +LIB_TARGETS_EXP = $(LIB_TARGETS_IMPLIB:$(ARLIB_SUFFIX)=$(EXP_SUFFIX)) +LIB_TARGETS_MISC = +# targets to build during CMDS phase +CMD_TARGETS_SHLIB = +CMD_TARGETS_EXE = $(EXECUTABLE) +CMD_TARGETS_MISC = +# files to remove during clean phase +CLEAN_TARGETS_MISC = +CLEAN_TARGETS = $(OBJECTS) $(RSCOBJECTS) $(IDL_TARGETS) $(CLEAN_TARGETS_MISC) +# other files to remove during clobber phase +CLOBBER_TARGETS_MISC= +# sub-directory to install to within bin +BIN_SUBDIR = +# sub-directory to install to within include +INCLUDE_SUBDIR = + +# Additional Settings +#CLOCALDEBUG = User defined C debugging compilation flags [Empty] +#CCLOCALDEBUG = User defined C++ debugging compilation flags [Empty] +#CLOCAL = User defined C flags for compiling [Empty] +#CCLOCAL = User defined C++ flags for compiling [Empty] +#BSCLOCAL = User flags for Browse File Builder [Empty] +#DEPENDLOCAL = user defined makedepend flags [Empty] +#LINTLOCAL = User defined lint flags [Empty] +#LOCAL_INCLUDE_DIRS = User include directories to search for C/C++ headers [Empty] +#LDLOCAL = User defined C flags for linking [Empty] +#IMPLIBLOCAL = User flags for Object Lirary Manager [Empty] +#MIDLLOCAL = User flags for IDL compiler [Empty] +#RSCLOCAL = User flags for resource compiler [Empty] +#LOCALDEPLIBS = User libraries to include in dependencies [Empty] +#LOCALLIBS = User libraries to use when linking [Empty] +# (in addition to LOCALDEPLIBS) +#LOCAL_LIB_DIRS = User library directories for libpaths [Empty] + +CLOCAL = $(CPIE) +LOCAL_INCLUDE_DIRS= +LOCALDEPLIBS= +LOCALLIBS= +LOCAL_LIB_DIRS= + +# Include Make Rules definitions and rules +include $(TL_DIR)/IbaTools/Makerules.module + +#=============================================================================# +# Overrides: +#-----------------------------------------------------------------------------# +#CCOPT = # C++ optimization flags, default lets build config decide +#COPT = # C optimization flags, default lets build config decide +#SUBSYSTEM = Subsystem to build for (none, console or windows) [none] +# (Windows Only) +#USEMFC = How Windows MFC should be used (none, static, shared, no_mfc) [none] +# (Windows Only) +#=============================================================================# + +.SUFFIXES: -sample +%-sample:% + $(CP) $< $@ + + +#=============================================================================# +# Rules: +#-----------------------------------------------------------------------------# +# process Sub-directories +include $(TL_DIR)/Makerules/Maketargets.toplevel + +# build cmds and libs +include $(TL_DIR)/Makerules/Maketargets.build + +# install for includes, libs and cmds phases +include $(TL_DIR)/Makerules/Maketargets.install + +# install for stage phase +#include $(TL_DIR)/Makerules/Maketargets.stage +STAGE:: + $(VS)$(STAGE_INSTALL) $(STAGE_INSTALL_DIR_OPT) $(PROJ_STAGE_DIR)/config opamon.conf opamon.si.conf + + $(VS)$(STAGE_INSTALL) $(STAGE_INSTALL_DIR_OPT) $(PROJ_STAGE_FASTFABRIC_DIR)/samples opamon.conf-sample opamon.si.conf-sample + +# Unit test execution +#include $(TL_DIR)/Makerules/Maketargets.runtest + +#=============================================================================# + +#=============================================================================# +# DO NOT DELETE THIS LINE -- make depend depends on it. +#=============================================================================# diff --git a/IbaTools/opamon/README b/IbaTools/opamon/README new file mode 100644 index 0000000..2a66278 --- /dev/null +++ b/IbaTools/opamon/README @@ -0,0 +1 @@ +config files for error thresholds in iba_report diff --git a/IbaTools/opamon/opamon.conf b/IbaTools/opamon/opamon.conf new file mode 100644 index 0000000..a86e10d --- /dev/null +++ b/IbaTools/opamon/opamon.conf @@ -0,0 +1,69 @@ +# This file controls the opareport Port Counter Thresholds. +# [ICS VERSION STRING: unknown] +# +# Error Counters are specified in absolute number of errors since last cleared. +# All Data Movement thresholds are specified in terms of absolute data +# since last cleared. +# +# Setting a threshold to 0 disables monitoring of the given counter +# +# Output is generated when a threshold is exceeded. +# +# Counters for which a non-zero threshold is specified will be checked +# and potentially cleared by opareport and related tools using opareport. + +Threshold Greater # how to compare counter to threshold + # Greater - reports values > threshold + # Equal - reports values >= threshold + # Does not apply to Link Quality Indicator + +# Normal Data Movement +# -------------------- +XmitData 0 # as MB +RcvData 0 # as MB +XmitPkts 0 # as packets +RcvPkts 0 # as packets +MulticastXmitPkts 0 # as packets +MulticastRcvPkts 0 # as packets + +# Signal Integrity and Node/Link Stability +# ---------------------------------------- +LinkQualityIndicator 4 # (range 0-5) higher number indicates + # better quality. + # Unlike other thresholds, links with a + # value less (worse quality) than this + # threshold are flagged +UncorrectableErrors 1 +LinkDowned 3 +RcvErrors 1 +ExcessiveBufferOverruns 1 +FMConfigErrors 1 +LinkErrorRecovery 0 +LocalLinkIntegrityErrors 0 +RcvRemotePhysicalErrors 0 # side effect of errors elsewhere, ignore +NumLanesDown 0 # LinkWidthDowngrade + +# Security +# -------- +XmitConstraintErrors 10 +RcvConstraintErrors 10 + +# Routing or Down nodes still being sent to +# ----------------------------------------- +RcvSwitchRelayErrors 0 +XmitDiscards 0 # superset of CongDiscards + +# Congestion +# ---------- +CongDiscards 0 +RcvFECN 0 +RcvBECN 0 +MarkFECN 0 +XmitTimeCong 0 +XmitWait 0 + +# Bubbles +# ------- +XmitWastedBW 0 +XmitWaitData 0 +RcvBubble 0 diff --git a/IbaTools/opamon/opamon.si.conf b/IbaTools/opamon/opamon.si.conf new file mode 100644 index 0000000..02cfc87 --- /dev/null +++ b/IbaTools/opamon/opamon.si.conf @@ -0,0 +1,77 @@ +# This file controls the opareport Port Counter Thresholds. +# [ICS VERSION STRING: unknown] + +# This is a variation of the default opamon.conf file. This file only +# checks error counters related to Signal Integrity. Thresholds are set +# such that any and all non-zero counters will be visible. This can be +# useful when using opareport -o errors, opaextracterror, and other +# related tools. For many FastFabric tools this filename can be specified by +# the -c option. + +# +# Error Counters are specified in absolute number of errors since last cleared. +# All Data Movement thresholds are specified in terms of absolute data +# since last cleared. +# +# Setting a threshold to 0 disables monitoring of the given counter +# +# Output is generated when a threshold is exceeded. +# +# Counters for which a non-zero threshold is specified will be checked +# and potentially cleared by opareport and related tools using opareport. + +Threshold Equal # how to compare counter to threshold + # Greater - reports values > threshold + # Equal - reports values >= threshold + # Does not apply to Link Quality Indicator + +# Normal Data Movement +# -------------------- +XmitData 0 # as MB +RcvData 0 # as MB +XmitPkts 0 # as packets +RcvPkts 0 # as packets +MulticastXmitPkts 0 # as packets +MulticastRcvPkts 0 # as packets + +# Signal Integrity and Node/Link Stability +# ---------------------------------------- +LinkQualityIndicator 4 # (range 0-5) higher number indicates + # better quality. + # Unlike other thesholds, links with a + # value less (worse quality) than this + # threshold are flagged +UncorrectableErrors 1 # indicate device internal instability +LinkDowned 1 +RcvErrors 1 +ExcessiveBufferOverruns 1 # can be side effect of SI +FMConfigErrors 1 # can be a side effect of SI +LinkErrorRecovery 0 # not expected to be 0 +LocalLinkIntegrityErrors 0 # not expected to be 0 +RcvRemotePhysicalErrors 0 # side effect of errors elsewhere, ignore +NumLanesDown 1 # LinkWidthDowngrade + +# Security +# -------- +XmitConstraintErrors 0 +RcvConstraintErrors 0 + +# Routing or Down nodes still being sent to +# ----------------------------------------- +RcvSwitchRelayErrors 0 +XmitDiscards 0 # superset of CongDiscards + +# Congestion +# ---------- +CongDiscards 0 +RcvFECN 0 +RcvBECN 0 +MarkFECN 0 +XmitTimeCong 0 +XmitWait 0 + +# Bubbles +# ------- +XmitWastedBW 0 +XmitWaitData 0 +RcvBubble 0 diff --git a/IbaTools/opapacketcapture/Makefile b/IbaTools/opapacketcapture/Makefile new file mode 100644 index 0000000..8f2b22b --- /dev/null +++ b/IbaTools/opapacketcapture/Makefile @@ -0,0 +1,162 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** +# Makefile for opapacketcapture + +# Include Make Control Settings +include $(TL_DIR)/$(PROJ_FILE_DIR)/Makesettings.project + +#=============================================================================# +# Definitions: +#-----------------------------------------------------------------------------# + +# Name of SubProjects +DS_SUBPROJECTS = +# name of executable or downloadable image +EXECUTABLE = $(BUILDDIR)/opapacketcapture$(EXE_SUFFIX) +# list of sub directories to build +DIRS = +# C files (.c) +CFILES = \ + opapacketcapture.c \ + # Add more c files here +# C++ files (.cpp) +CCFILES = \ + # Add more cpp files here +# lex files (.lex) +LFILES = \ + # Add more lex files here +# archive library files (basename, $ARFILES will add MOD_LIB_DIR/prefix and suffix) +LIBFILES= +# Windows Resource Files (.rc) +RSCFILES = +# Windows IDL File (.idl) +IDLFILE = +# Windows Linker Module Definitions (.def) file for dll's +DEFFILE = +# targets to build during INCLUDES phase (add public includes here) +INCLUDE_TARGETS = + \ + # Add more h hpp files here +# Non-compiled files + # Add more files here +MISC_FILES = filterFile.txt triggerFile.txt +# all source files +SOURCES = $(CFILES) $(CCFILES) $(LFILES) $(RSCFILES) $(IDLFILE) +# Source files to include in DSP File +DSP_SOURCES = $(INCLUDE_TARGETS) $(SOURCES) $(MISC_FILES) \ + $(RSCFILES) $(DEFFILE) $(MAKEFILE) +# all object files +OBJECTS = $(CFILES:.c=$(OBJ_SUFFIX)) $(CCFILES:.cpp=$(OBJ_SUFFIX)) \ + $(LFILES:.lex=$(OBJ_SUFFIX)) +RSCOBJECTS = $(RSCFILES:.rc=$(RES_SUFFIX)) +# targets to build during LIBS phase +LIB_TARGETS_IMPLIB = +LIB_TARGETS_ARLIB = # $(LIB_PREFIX)ResourceTest$(ARLIB_SUFFIX) +LIB_TARGETS_EXP = $(LIB_TARGETS_IMPLIB:$(ARLIB_SUFFIX)=$(EXP_SUFFIX)) +LIB_TARGETS_MISC = +# targets to build during CMDS phase +CMD_TARGETS_SHLIB = +CMD_TARGETS_EXE = $(EXECUTABLE) +CMD_TARGETS_MISC = +# files to remove during clean phase +CLEAN_TARGETS_MISC = +CLEAN_TARGETS = $(OBJECTS) $(RSCOBJECTS) $(IDL_TARGETS) $(CLEAN_TARGETS_MISC) +# other files to remove during clobber phase +CLOBBER_TARGETS_MISC= +# sub-directory to install to within bin +BIN_SUBDIR = +# sub-directory to install to within include +INCLUDE_SUBDIR = + +# Additional Settings +#CLOCALDEBUG = User defined C debugging compilation flags [Empty] +#CCLOCALDEBUG = User defined C++ debugging compilation flags [Empty] +#CLOCAL = User defined C flags for compiling [Empty] +#CCLOCAL = User defined C++ flags for compiling [Empty] +#BSCLOCAL = User flags for Browse File Builder [Empty] +#DEPENDLOCAL = user defined makedepend flags [Empty] +#LINTLOCAL = User defined lint flags [Empty] +#LOCAL_INCLUDE_DIRS = User include directories to search for C/C++ headers [Empty] +#LDLOCAL = User defined C flags for linking [Empty] +#IMPLIBLOCAL = User flags for Object Lirary Manager [Empty] +#MIDLLOCAL = User flags for IDL compiler [Empty] +#RSCLOCAL = User flags for resource compiler [Empty] +#LOCALDEPLIBS = User libraries to include in dependencies [Empty] +#LOCALLIBS = User libraries to use when linking [Empty] +# (in addition to LOCALDEPLIBS) +#LOCAL_LIB_DIRS = User library directories for libpaths [Empty] + +CLOCAL = $(CPIE) +LOCALDEPLIBS = $(IBACCESS_USER_LIBS) +LOCAL_INCLUDE_DIRS= +LOCALLIBS= $(IBACCESS_USER_LIBS) rt +#LOCAL_LIB_DIRS=$(OPENIB_USER_LIB_DIRS) $(IBACCESS_USER_LIB_DIRS) +LOCAL_LIB_DIRS=$(IBACCESS_USER_LIB_DIRS) + +# Include Make Rules definitions and rules +include $(TL_DIR)/IbaTools/Makerules.module + +#=============================================================================# +# Overrides: +#-----------------------------------------------------------------------------# +#CCOPT = # C++ optimization flags, default lets build config decide +#COPT = # C optimization flags, default lets build config decide +#SUBSYSTEM = Subsystem to build for (none, console or windows) [none] +# (Windows Only) +#USEMFC = How Windows MFC should be used (none, static, shared, no_mfc) [none] +# (Windows Only) +#=============================================================================# + +#=============================================================================# +# Rules: +#-----------------------------------------------------------------------------# +# process Sub-directories +include $(TL_DIR)/Makerules/Maketargets.toplevel + +# build cmds and libs +include $(TL_DIR)/Makerules/Maketargets.build + +# install for includes, libs and cmds phases +include $(TL_DIR)/Makerules/Maketargets.install + +# install for stage phase +include $(TL_DIR)/Makerules/Maketargets.stage +STAGE:: + $(VS)$(STAGE_INSTALL) $(STAGE_INSTALL_DIR_OPT) $(PROJ_STAGE_FASTFABRIC_DIR)/samples $(MISC_FILES) + $(VS)$(STAGE_INSTALL) $(STAGE_INSTALL_DIR_OPT) $(PROJ_STAGE_FASTFABRIC_DIR) $(MISC_CONFIG_FILES) + $(VS)$(STAGE_INSTALL) $(STAGE_INSTALL_DIR_OPT) $(PROJ_STAGE_FASTFABRIC_DIR) $(EXECUTABLE) + +# Unit test execution +#include $(TL_DIR)/Makerules/Maketargets.runtest + +#=============================================================================# + +#=============================================================================# +# DO NOT DELETE THIS LINE -- make depend depends on it. +#=============================================================================# diff --git a/IbaTools/opapacketcapture/filterFile.txt b/IbaTools/opapacketcapture/filterFile.txt new file mode 100644 index 0000000..dfb38b3 --- /dev/null +++ b/IbaTools/opapacketcapture/filterFile.txt @@ -0,0 +1,43 @@ +# Filter file for opapacketcapture +# [ICS VERSION STRING: unknown] + +# Filter is keyword followed by whitespace then filter value + +# Available filters and values: + +#DLID +#SLID +#MCLASS +#PKEY +#PTYPE +#SVCLEV +#ATTRID +#QP +#TRANSIDH +#TRANSIDL + +# Additionally, condition may be given to handle relationship between multiple +# filters - AND or OR. Default is AND + +# Any filter may be negated with first character '!' or '~' + +#COND + +# Examples: (edit as appropriate) + +SLID 2 # filter on source lid of 2 + +PKEY 0xffff # filter on pkey of 0xffff + +PTYPE UD # filter on packet type of UD + +!DLID 4 # filter on all dest lids except 4 + +~SVCLEV 1 # filter on all service levels except 1 + +#!ATTRID 18 # filter on all MAD attribute IDs except 18 +!ATTRID 0x12 # filter on all MAD attribute IDs except 0x12 + +QP 1 # filter on dest QP of 1 + +COND AND # AND all these conditions together - all must be true diff --git a/IbaTools/opapacketcapture/opapacketcapture.c b/IbaTools/opapacketcapture/opapacketcapture.c new file mode 100644 index 0000000..e537189 --- /dev/null +++ b/IbaTools/opapacketcapture/opapacketcapture.c @@ -0,0 +1,1779 @@ +/* BEGIN_ICS_COPYRIGHT7 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT7 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "iba/public/ibyteswap.h" +#include "iba/stl_types.h" +#include "iba/ib_mad.h" +#include "iba/stl_pkt.h" +#include "opapacketcapture.h" +#include /* for ioctl commands */ +#include + +uint8 *blocks; +packet *packets; + +packet *freePackets; +packet *oldestPacket; +packet *newestPacket; + +uint8 *currentBlock; + +uint64 blocksTableSize; +uint64 numpackets; + +int numPacketsRead = 0; +int numPacketsTaken = 0; +uint64 numPacketsMax = (uint64)-1; +int gotModeArg = 0; +uint8 mode = 0; +int numPacketsStored = 0; +int stopcapture = 0; +int triggerSeen = 0; +int afterTriggerPackets = 0; + +uint32 alarmArg = 0; +char filterFileArg[256]; +char triggerFileArg[256]; +int triggerLag = DEFAULT_TRIGGER_LAG; +int gotFilterFileArg = 0; +int gotTriggerFileArg = 0; +int gotAlarmArg = 0; +int gotTriggerLagArg = 0; +int writethrough = 0; +int retryCount; + +filterFunc_t filters[25]; +filterFunc_t triggers[25]; + +int numFilterFunctions = 0; +int numTriggerFunctions = 0; + +int filterCondition; +int gotCondition = 0; +int triggerCondition; +int gotTriggerCondition = 0; + +int gotdevfile; +int gotoutfile; +char devfile[256]; +char out_file[256]; +int fdIn; + +int ioctlConfigured = 0; +qibPacketFilterCommand_t filterCmd; +uint32 filterValue; + +int verbose = 0; + +static void my_handler(int signal) +{ + stopcapture = 1; + printf("\nopapacketcapture: Triggered\n"); +} + +boolean isWfrPacketBypass(packet *p) { + WFR_SnC_HDR *wfr_hdr = NULL; + boolean res = 0; + + wfr_hdr = (WFR_SnC_HDR *)(&blocks[p->blockNum * BLOCKSIZE]); + + if (wfr_hdr->Direction == STL_WFR_OUTBOUND) { + res = (boolean) wfr_hdr->u.PBC.s.pbcpacketbypass; + } else if (wfr_hdr->Direction == STL_WFR_INBOUND) { + res = (wfr_hdr->u.RHF.s.rcvtype == STL_WFR_RCV_BYPASS); + } + return res; +} + +boolean is9BWfrPacket(packet *p) { + WFR_SnC_HDR *wfr_hdr = NULL; + boolean res = 0; + + wfr_hdr = (WFR_SnC_HDR *)(&blocks[p->blockNum * BLOCKSIZE]); + + if (wfr_hdr->Direction == STL_WFR_OUTBOUND) { + res = !((boolean)wfr_hdr->u.PBC.s.pbcpacketbypass); + } else if (wfr_hdr->Direction == STL_WFR_INBOUND) { + res = (wfr_hdr->u.RHF.s.rcvtype == STL_WFR_RCV_IB); + } + return res; +} + +boolean is16BWfrPacket(packet *p) { + boolean ret = 0; + STL_16B_HDR *lrh = NULL; + if (isWfrPacketBypass(p)) { + lrh = (STL_16B_HDR *)( (uint8 *)(&blocks[p->blockNum * BLOCKSIZE]) + sizeof(WFR_SnC_HDR)); + if (lrh->u1.s.L2 == STL_L2_16B) { + ret = 1; + } + } + return ret; +} + +boolean hasBTH(packet *p) { + boolean ret = 0; + STL_16B_HDR *lrh_16 = NULL; + IB_LRH *lrh_9 = NULL; + if (is9BWfrPacket(p)) { + lrh_9 = (IB_LRH *)( (uint8 *)(&blocks[p->blockNum * BLOCKSIZE]) + sizeof(WFR_SnC_HDR) ); + if (lrh_9->l.LNH == STL_9B_LNH_BTH) { + ret = 1; + } + } else if (is16BWfrPacket(p)) { + lrh_16 = (STL_16B_HDR *)( (uint8 *)(&blocks[p->blockNum * BLOCKSIZE]) + sizeof(WFR_SnC_HDR)); + if (lrh_16->L4 == STL_16B_L4_IB) { + ret = 1; + } + } + return ret; +} + +IB_BTH *get9BTH(packet *p) { + IB_BTH *bth_9 = NULL; + + bth_9 = (IB_BTH *)( (uint8 *)(&blocks[p->blockNum * BLOCKSIZE]) + sizeof(WFR_SnC_HDR) + sizeof(IB_LRH) ); + + return bth_9; +} + +STL_16B_BTH *get16BTH(packet *p) { + STL_16B_BTH *bth_16 = NULL; + + bth_16 = (STL_16B_BTH *)( (uint8 *)(&blocks[p->blockNum * BLOCKSIZE]) + sizeof(WFR_SnC_HDR) + sizeof(STL_16B_HDR) ); + + return bth_16; +} + +uint16 getPkey(packet *p) { + STL_16B_HDR *lrh_16_raw = NULL; + STL_16B_HDR lrh_16; + IB_LRH *lrh_9 = NULL; + IB_BTH *bth_9 = NULL; + uint16 ret = 0; + + if (is9BWfrPacket(p)) { + lrh_9 = (IB_LRH *)( (uint8 *)(&blocks[p->blockNum * BLOCKSIZE]) + sizeof(WFR_SnC_HDR) ); + if (lrh_9->l.LNH == STL_9B_LNH_BTH) { + bth_9 = (IB_BTH *)( (uint8 *)(&blocks[p->blockNum * BLOCKSIZE]) + sizeof(WFR_SnC_HDR) + sizeof(IB_LRH) ); + ret = ntoh16(bth_9->Pkey); + } + } else if (is16BWfrPacket(p)) { + lrh_16_raw = (STL_16B_HDR *)( (uint8 *)(&blocks[p->blockNum * BLOCKSIZE]) + sizeof(WFR_SnC_HDR)); + memcpy((void *)&lrh_16, (void *)lrh_16_raw, sizeof(STL_16B_HDR)); + BSWAP_STL_16B_HDR(&lrh_16); + ret = lrh_16.Pkey; + } + return ret; +} + +uint8 getOpCode(packet *p) { + uint8 ret = 0; + STL_16B_BTH *bth_16 = NULL; + IB_BTH *bth_9 = NULL; + + if (hasBTH(p)) { + if (is9BWfrPacket(p)) { + bth_9 = (IB_BTH *)( (uint8 *)(&blocks[p->blockNum * BLOCKSIZE]) + sizeof(WFR_SnC_HDR) + sizeof(IB_LRH) ); + ret = bth_9->OpCode; + } else if (is16BWfrPacket(p)) { + bth_16 = (STL_16B_BTH *)( (uint8 *)(&blocks[p->blockNum * BLOCKSIZE]) + sizeof(WFR_SnC_HDR) + sizeof(STL_16B_HDR) ); + ret = bth_16->OpCode; + } + } + return ret; +} + +uint32 getDestQp(packet *p) { + uint32 ret = 0; + STL_16B_BTH *bth_16 = NULL; + IB_BTH *bth_9 = NULL; + + if (hasBTH(p)) { + if (is9BWfrPacket(p)) { + bth_9 = (IB_BTH *)( (uint8 *)(&blocks[p->blockNum * BLOCKSIZE]) + sizeof(WFR_SnC_HDR) + sizeof(IB_LRH) ); + ret = ntoh32(bth_9->Qp.AsUINT32); + } else if (is16BWfrPacket(p)) { + bth_16 = (STL_16B_BTH *)( (uint8 *)(&blocks[p->blockNum * BLOCKSIZE]) + sizeof(WFR_SnC_HDR) + sizeof(STL_16B_HDR) ); + ret = ntoh32(bth_16->Qp.AsReg32); + } + } + return ret; +} + +boolean isMAD(packet *p) { + boolean ret = 0; + STL_16B_HDR *lrh_16 = NULL; + STL_16B_BTH *bth_16 = NULL; + IB_BTH *bth_9 = NULL; + + if (hasBTH(p)) { + if (is9BWfrPacket(p)) { + bth_9 = (IB_BTH *)( (uint8 *)(&blocks[p->blockNum * BLOCKSIZE]) + sizeof(WFR_SnC_HDR) + sizeof(IB_LRH) ); + if (bth_9->Qp.s.DestQPNumber == 0 || bth_9->Qp.s.DestQPNumber == 1) { + ret = 1; + } + } else if (is16BWfrPacket(p)) { + bth_16 = (STL_16B_BTH *)( (uint8 *)(&blocks[p->blockNum * BLOCKSIZE]) + sizeof(WFR_SnC_HDR) + sizeof(STL_16B_HDR) ); + if (bth_16->Qp.s.DestQPNumber == 0 || bth_16->Qp.s.DestQPNumber == 1) { + ret = 1; + } + } + } else { /* Could still be a MAD packet even w/o a BTH */ + if (is16BWfrPacket(p)) { /* Check for 16B MAD packet w/o BTH */ + lrh_16 = (STL_16B_HDR *)( (uint8 *)(&blocks[p->blockNum * BLOCKSIZE]) + sizeof(WFR_SnC_HDR)); + if (lrh_16->u1.s.L2 == STL_16B_L4_FM) { + ret = 1; + } + } + } + return ret; +} + +MAD_COMMON *getMAD(packet *p) { + STL_16B_HDR *lrh_16 = NULL; + MAD_COMMON *m = NULL; + + if (hasBTH(p)) { + if (is9BWfrPacket(p)) { + m = (MAD_COMMON *)((uint8 *)(&blocks[p->blockNum * BLOCKSIZE]) + sizeof(WFR_SnC_HDR) + sizeof(IB_LRH) + sizeof(IB_BTH) + sizeof(IB_DETH)); + } else if (is16BWfrPacket(p)) { + m = (MAD_COMMON *)((uint8 *)(&blocks[p->blockNum * BLOCKSIZE]) + sizeof(WFR_SnC_HDR) + sizeof(STL_16B_HDR) + sizeof(STL_16B_BTH) + sizeof(IB_DETH)); + } + } else { /* Could still be a MAD packet even w/o a BTH */ + if (is16BWfrPacket(p)) { /* Check for 16B MAD packet w/o BTH */ + lrh_16 = (STL_16B_HDR *)( (uint8 *)(&blocks[p->blockNum * BLOCKSIZE]) + sizeof(WFR_SnC_HDR)); + if (lrh_16->u1.s.L2 == STL_16B_L4_FM) { + m = (MAD_COMMON *)((uint8 *)(&blocks[p->blockNum * BLOCKSIZE]) + sizeof(WFR_SnC_HDR) + sizeof(STL_16B_HDR) + STL_16B_L4_FM_SIZE); + } + } + } + return m; +} + +STL_LID getSLID(packet *p) { + STL_16B_HDR *lrh_16_raw = NULL; + STL_16B_HDR lrh_16; + IB_LRH *lrh_9 = NULL; + + STL_LID ret = 0; + + if (is9BWfrPacket(p)) { + lrh_9 = (IB_LRH *)( (uint8 *)(&blocks[p->blockNum * BLOCKSIZE]) + sizeof(WFR_SnC_HDR) ); + if (lrh_9->l.LNH == STL_9B_LNH_BTH) { + ret = (STL_LID)ntoh16(lrh_9->SrcLID); + } + } else if (is16BWfrPacket(p)) { + lrh_16_raw = (STL_16B_HDR *)( (uint8 *)(&blocks[p->blockNum * BLOCKSIZE]) + sizeof(WFR_SnC_HDR)); + memcpy((void *)&lrh_16, (void *)lrh_16_raw, sizeof(STL_16B_HDR)); + BSWAP_STL_16B_HDR(&lrh_16); + ret = ((lrh_16.u3.s.SLID_23_20 << 20) | lrh_16.u2.s.SLID_19_0); + } + return ret; +} + +STL_LID getDLID(packet *p) { + STL_16B_HDR *lrh_16_raw = NULL; + STL_16B_HDR lrh_16; + IB_LRH *lrh_9 = NULL; + + STL_LID ret = 0; + + if (is9BWfrPacket(p)) { + lrh_9 = (IB_LRH *)( (uint8 *)(&blocks[p->blockNum * BLOCKSIZE]) + sizeof(WFR_SnC_HDR) ); + if (lrh_9->l.LNH == STL_9B_LNH_BTH) { + ret = (STL_LID)ntoh16(lrh_9->DestLID); + } + } else if (is16BWfrPacket(p)) { + lrh_16_raw = (STL_16B_HDR *)( (uint8 *)(&blocks[p->blockNum * BLOCKSIZE]) + sizeof(WFR_SnC_HDR)); + memcpy((void *)&lrh_16, (void *)lrh_16_raw, sizeof(STL_16B_HDR)); + BSWAP_STL_16B_HDR(&lrh_16); + ret = ((lrh_16.u3.s.DLID_23_20 << 20) | lrh_16.u1.s.DLID_19_0); + } + return ret; +} + +int filterSLID(packet *p, uint32 val) +{ + STL_LID slid = 0; + int res = 0; + + slid = getSLID(p); + + res = (slid == (STL_LID)val); + + return(res); +} + +int filterDLID(packet *p, uint32 val) +{ + STL_LID dlid = 0; + int res = 0; + + dlid = getDLID(p); + + res = (dlid == (STL_LID)val); + + return(res); +} + +int filterServiceLevel(packet *p, uint32 val) +{ + uint8 sl = (uint8)val; + IB_LRH *lrh; + int res = 0; + + if (!is9BWfrPacket(p)) { + return res; + } + + lrh = (IB_LRH *)( (uint8 *)(&blocks[p->blockNum * BLOCKSIZE]) + sizeof(WFR_SnC_HDR) ); + + res = (lrh->l.ServiceLevel == sl); + + return(res); +} + +int filterMgmtClass(packet *p, uint32 val) +{ + uint8 mc = (uint8)val; + MAD_COMMON *m; + int res = 0; + + if (!isMAD(p)) { + return res; + } + + m = getMAD(p); + if (m) { + res = (m->MgmtClass == mc); + } + + return(res); +} + +int filterPKey(packet *p, uint32 val) +{ + uint16 pkey = (uint16)val; + uint16 Pkey = 0; + int res = 0; + + Pkey = getPkey(p); + + res = ((Pkey & PKEY_MASK) == (pkey & PKEY_MASK)); + + return(res); +} + +int filterPacketType(packet *p, uint32 val) +{ + uint8 pktType = (uint8)val; + uint8 opCode = 0; + int res = 0; + + opCode = getOpCode(p); + + res = ((opCode>>5) == pktType); + + return(res); +} + +int filterAttrID(packet *p, uint32 val) +{ + uint16 aid = (uint16)val; + MAD_COMMON *m; + int res = 0; + + if (!isMAD(p)) { + return res; + } + + m = getMAD(p); + if (m) { + res = (ntoh16(m->AttributeID) == aid); + } + + return(res); +} + +int filterTransactionIDLow(packet *p, uint32 val) +{ + MAD_COMMON *m; + int res = 0; + + if (!isMAD(p)) { + return res; + } + + m = getMAD(p); + if (m) { + res = ((uint32)(ntoh64(m->TransactionID) & 0xffffffff) == val); + } + + return(res); +} + +int filterTransactionIDHigh(packet *p, uint32 val) +{ + MAD_COMMON *m; + int res = 0; + + if (!isMAD(p)) { + return res; + } + + m = getMAD(p); + if (m) { + res = ((uint32)((ntoh64(m->TransactionID) >> 32) & 0xffffffff) == val); + } + + return(res); +} + +int filterQueuePair(packet *p, uint32 val) +{ + uint32 qp = val; + uint32 pkt_qp = 0; + int res = 0; + + if (!hasBTH(p)) { + return res; + } + + pkt_qp = getDestQp(p); + pkt_qp = pkt_qp & DESTQP_MASK; + res = (pkt_qp == qp); + + return(res); +} + +int applyFilters(packet *p) +{ + int res; + int i; + + res = (filterCondition == COND_TYPE_AND) ? 1 : 0; + + for (i = 0; (i < numFilterFunctions) && ((filterCondition == COND_TYPE_AND) ? res : !res); i++) { + if (!filters[i].ioctl) { + // XOR result with notFlag + res = filters[i].filterFunc(p, filters[i].filterVal) ^ filters[i].notFlag; + } + } + + return(res); +} + +int applyTriggers(packet *p) +{ + int res; + int i; + + res = (triggerCondition == COND_TYPE_AND) ? 1 : 0; + + for (i = 0; (i < numTriggerFunctions) && ((triggerCondition == COND_TYPE_AND) ? res : !res); i++) { + res = triggers[i].filterFunc(p, triggers[i].filterVal) ^ triggers[i].notFlag; + } + + return(res); +} + +int getFilterType(char *filter) +{ + int res; + if (!strcmp(filter, "COND")) + res = FILTER_COND; + else if (!strcmp(filter, "DLID")) + res = FILTER_DLID; + else if (!strcmp(filter, "SLID")) + res = FILTER_SLID; + else if (!strcmp(filter, "MCLASS")) + res = FILTER_MCLASS; + else if (!strcmp(filter, "PKEY")) + res = FILTER_PKEY; + else if (!strcmp(filter, "PTYPE")) + res = FILTER_PTYPE; + else if (!strcmp(filter, "SVCLEV")) + res = FILTER_SVCLEV; + else if (!strcmp(filter, "ATTRID")) + res = FILTER_ATTRID; + else if (!strcmp(filter, "QP")) + res = FILTER_QP; + else if (!strcmp(filter, "TRANSIDH")) + res = FILTER_TRANS_ID_HIGH; + else if (!strcmp(filter, "TRANSIDL")) + res = FILTER_TRANS_ID_LOW; + else + res = -1; + + return(res); +} + +int getPacketType(char *filter) +{ + int res; + if (!strcmp(filter, "RC")) + res = PACKETTYPE_RC; + else if (!strcmp(filter, "UC")) + res = PACKETTYPE_UC; + else if (!strcmp(filter, "RD")) + res = PACKETTYPE_RD; + else if (!strcmp(filter, "UD")) + res = PACKETTYPE_UD; + else + res = PACKETTYPE_ERR; + + return(res); +} + +int getCondType(char *condition) +{ + int res; + if (!strcmp(condition, "AND")) + res = COND_TYPE_AND; + else if (!strcmp(condition, "OR")) + res = COND_TYPE_OR; + else + res = -1; + + return(res); +} + +void setupIoctl(int filter, uint32 *valPtr) +{ + filterCmd.value_ptr = (void *)valPtr; + switch (filter) { + case FILTER_DLID: + filterCmd.opcode = FILTER_BY_DLID; + filterCmd.length = sizeof(uint16); + break; + case FILTER_SLID: + filterCmd.opcode = FILTER_BY_LID; + filterCmd.length = sizeof(uint16); + break; + case FILTER_MCLASS: + filterCmd.opcode = FILTER_BY_MAD_MGMT_CLASS; + filterCmd.length = sizeof(uint8); + break; + case FILTER_PKEY: + filterCmd.opcode = FILTER_BY_PKEY; + filterCmd.length = sizeof(uint16); + break; + case FILTER_PTYPE: + filterCmd.opcode = FILTER_BY_PKT_TYPE; + filterCmd.length = sizeof(uint8); + break; + case FILTER_SVCLEV: + filterCmd.opcode = FILTER_BY_SERVICE_LEVEL; + filterCmd.length = sizeof(uint8); + break; + case FILTER_ATTRID: + /* not supported in driver */ + fprintf(stderr, "Error: filter on attribute ID not supported in qib driver\n"); + exit(1); + break; + case FILTER_TRANS_ID_HIGH: + /* not supported in driver */ + fprintf(stderr, "Error: filter on transaction ID high not supported in qib driver\n"); + exit(1); + break; + case FILTER_TRANS_ID_LOW: + /* not supported in driver */ + fprintf(stderr, "Error: filter on transaction ID low not supported in qib driver\n"); + exit(1); + break; + case FILTER_QP: + filterCmd.opcode = FILTER_BY_QP_NUMBER; + filterCmd.length = sizeof(uint32); + break; + } + return; +} + +void setupFilters(char *filterFile) +{ + FILE *fp; + char inbuf[128]; + char *p; + char *p1; + char filterType[10]; + int filter; + uint32 val; + char strVal[10]; + int not; + + if ((fp = fopen(filterFile, "r")) == NULL) { + fprintf(stderr, "Error opening file <%s> for input: %s\n", filterFile, strerror(errno)); + exit(1); + } + + while (fgets(inbuf, 128, fp) != NULL) { + p = inbuf; + if (*p == '#') + continue; + if (*p == '\n') + continue; + if (*p == ' ') + continue; + if ((*p == '!') || (*p == '~')) { + not = 1; + p++; + } else + not = 0; + if ((p1 = strchr(p, '#')) != NULL) + *p1 = '\0'; + sscanf(p, "%9s", filterType); + if ((filter = getFilterType(filterType)) < 0) { + fprintf(stderr, "Invalid filter type %s\n", filterType); + exit(1); + } + switch (filter) { + case FILTER_DLID: + sscanf(p, "%9s %u", filterType, &val); + filters[numFilterFunctions].filterFunc = &filterDLID; + filters[numFilterFunctions].filterVal = val; + filters[numFilterFunctions].ioctl = 0; + filters[numFilterFunctions].notFlag = not; + if (!ioctlConfigured && !not) { + ioctlConfigured = 1; + filterValue = val; + setupIoctl(filter, &filterValue); + filters[numFilterFunctions].ioctl = 1; + } + numFilterFunctions++; + break; + case FILTER_SLID: + sscanf(p, "%9s %u", filterType, &val); + filters[numFilterFunctions].filterFunc = &filterSLID; + filters[numFilterFunctions].filterVal = val; + filters[numFilterFunctions].ioctl = 0; + filters[numFilterFunctions].notFlag = not; + if (!ioctlConfigured && !not) { + ioctlConfigured = 1; + filterValue = val; + setupIoctl(filter, &filterValue); + filters[numFilterFunctions].ioctl = 1; + } + numFilterFunctions++; + break; + case FILTER_MCLASS: + sscanf(p, "%9s %u", filterType, &val); + filters[numFilterFunctions].filterFunc = &filterMgmtClass; + filters[numFilterFunctions].filterVal = val; + filters[numFilterFunctions].ioctl = 0; + filters[numFilterFunctions].notFlag = not; + if (!ioctlConfigured && !not) { + ioctlConfigured = 1; + filterValue = val; + setupIoctl(filter, &filterValue); + filters[numFilterFunctions].ioctl = 1; + } + numFilterFunctions++; + break; + case FILTER_PKEY: + sscanf(p, "%9s 0x%x", filterType, &val); + filters[numFilterFunctions].filterFunc = &filterPKey; + filters[numFilterFunctions].filterVal = val; + filters[numFilterFunctions].ioctl = 0; + filters[numFilterFunctions].notFlag = not; + if (!ioctlConfigured && !not) { + ioctlConfigured = 1; + filterValue = (val & PKEY_MASK); + setupIoctl(filter, &filterValue); + filters[numFilterFunctions].ioctl = 1; + } + numFilterFunctions++; + break; + case FILTER_PTYPE: + sscanf(p, "%9s %9s", filterType, strVal); + if ((val = getPacketType(strVal)) == PACKETTYPE_ERR) { + fprintf(stderr, "Invalid packet type %s\n", strVal); + exit(1); + } + filters[numFilterFunctions].filterFunc = &filterPacketType; + filters[numFilterFunctions].filterVal = val; + filters[numFilterFunctions].ioctl = 0; + filters[numFilterFunctions].notFlag = not; + if (!ioctlConfigured && !not) { + ioctlConfigured = 1; + filterValue = val; + setupIoctl(filter, &filterValue); + filters[numFilterFunctions].ioctl = 1; + } + numFilterFunctions++; + break; + case FILTER_SVCLEV: + sscanf(p, "%9s %u", filterType, &val); + filters[numFilterFunctions].filterFunc = &filterServiceLevel; + filters[numFilterFunctions].filterVal = val; + filters[numFilterFunctions].ioctl = 0; + filters[numFilterFunctions].notFlag = not; + if (!ioctlConfigured && !not) { + ioctlConfigured = 1; + filterValue = val; + setupIoctl(filter, &filterValue); + filters[numFilterFunctions].ioctl = 1; + } + numFilterFunctions++; + break; + case FILTER_ATTRID: + sscanf(p, "%9s %9s", filterType, strVal); + if (strstr(strVal, "0x") != NULL) { + sscanf(p, "%9s 0x%x", strVal, &val); + } else { + sscanf(p, "%9s %u", strVal, &val); + } + filters[numFilterFunctions].filterFunc = &filterAttrID; + filters[numFilterFunctions].filterVal = val; + filters[numFilterFunctions].ioctl = 0; + filters[numFilterFunctions].notFlag = not; +#if 0 /* filter on attribute id not supported in driver */ + if (!ioctlConfigured && !not) { + ioctlConfigured = 1; + filterValue = val; + setupIoctl(filter, &filterValue); + filters[numFilterFunctions].ioctl = 1; + } +#endif + numFilterFunctions++; + break; + case FILTER_TRANS_ID_HIGH: + sscanf(p, "%9s %9s", filterType, strVal); + if (strstr(strVal, "0x") != NULL) { + sscanf(p, "%9s 0x%x", strVal, &val); + } else { + sscanf(p, "%9s %u", strVal, &val); + } + filters[numFilterFunctions].filterFunc = &filterTransactionIDHigh; + filters[numFilterFunctions].filterVal = val; + filters[numFilterFunctions].ioctl = 0; + filters[numFilterFunctions].notFlag = not; + numFilterFunctions++; + break; + case FILTER_TRANS_ID_LOW: + sscanf(p, "%9s %9s", filterType, strVal); + if (strstr(strVal, "0x") != NULL) { + sscanf(p, "%9s 0x%x", strVal, &val); + } else { + sscanf(p, "%9s %u", strVal, &val); + } + filters[numFilterFunctions].filterFunc = &filterTransactionIDLow; + filters[numFilterFunctions].filterVal = val; + filters[numFilterFunctions].ioctl = 0; + filters[numFilterFunctions].notFlag = not; + numFilterFunctions++; + break; + case FILTER_QP: + sscanf(p, "%9s %u", filterType, &val); + filters[numFilterFunctions].filterFunc = &filterQueuePair; + filters[numFilterFunctions].filterVal = val; + filters[numFilterFunctions].ioctl = 0; + filters[numFilterFunctions].notFlag = not; + if (!ioctlConfigured && !not) { + ioctlConfigured = 1; + filterValue = val; + setupIoctl(filter, &filterValue); + filters[numFilterFunctions].ioctl = 1; + } + numFilterFunctions++; + break; + case FILTER_COND: + if (not) { + fprintf(stderr, "Not sign not allowed on condition\n"); + exit(1); + } + if (gotCondition) { + fprintf(stderr, "Only one condition statement allowed\n"); + exit(1); + } + gotCondition = 1; + sscanf(p, "%9s %9s", filterType, strVal); + if ((filterCondition = getCondType(strVal)) < 0) { + fprintf(stderr, "Invalid condition type %s\n", strVal); + exit(1); + } + break; + } + } + + fclose(fp); + + /* if condition is OR, turn off ioctl */ + if (filterCondition == COND_TYPE_OR) { + int i; + ioctlConfigured = 0; + for (i = 0; i <= numFilterFunctions; i++) + filters[i].ioctl = 0; + } + return; +} + +void setupTriggers(char *triggerFile) +{ + FILE *fp; + char inbuf[128]; + char *p; + char *p1; + char triggerType[10]; + int trigger; + uint32 val; + char strVal[10]; + int not; + + if ((fp = fopen(triggerFile, "r")) == NULL) { + fprintf(stderr, "Error opening file <%s> for input: %s\n", triggerFile, strerror(errno)); + exit(1); + } + + while (fgets(inbuf, 128, fp) != NULL) { + p = inbuf; + if (*p == '#') + continue; + if (*p == '\n') + continue; + if (*p == ' ') + continue; + if ((*p == '!') || (*p == '~')) { + not = 1; + p++; + } else + not = 0; + if ((p1 = strchr(p, '#')) != NULL) + *p1 = '\0'; + sscanf(p, "%9s", triggerType); + if ((trigger = getFilterType(triggerType)) < 0) { + fprintf(stderr, "Invalid trigger type %s\n", triggerType); + exit(1); + } + switch (trigger) { + case FILTER_DLID: + sscanf(p, "%9s %u", triggerType, &val); + triggers[numTriggerFunctions].filterFunc = &filterDLID; + triggers[numTriggerFunctions].filterVal = val; + triggers[numTriggerFunctions].ioctl = 0; + triggers[numTriggerFunctions].notFlag = not; + numTriggerFunctions++; + break; + case FILTER_SLID: + sscanf(p, "%9s %u", triggerType, &val); + triggers[numTriggerFunctions].filterFunc = &filterSLID; + triggers[numTriggerFunctions].filterVal = val; + triggers[numTriggerFunctions].ioctl = 0; + triggers[numTriggerFunctions].notFlag = not; + numTriggerFunctions++; + break; + case FILTER_MCLASS: + sscanf(p, "%9s %u", triggerType, &val); + triggers[numTriggerFunctions].filterFunc = &filterMgmtClass; + triggers[numTriggerFunctions].filterVal = val; + triggers[numTriggerFunctions].ioctl = 0; + triggers[numTriggerFunctions].notFlag = not; + numTriggerFunctions++; + break; + case FILTER_PKEY: + sscanf(p, "%9s 0x%x", triggerType, &val); + triggers[numTriggerFunctions].filterFunc = &filterPKey; + triggers[numTriggerFunctions].filterVal = val; + triggers[numTriggerFunctions].ioctl = 0; + triggers[numTriggerFunctions].notFlag = not; + numTriggerFunctions++; + break; + case FILTER_PTYPE: + sscanf(p, "%9s %9s", triggerType, strVal); + if ((val = getPacketType(strVal)) == PACKETTYPE_ERR) { + fprintf(stderr, "Invalid packet type %s\n", strVal); + exit(1); + } + triggers[numTriggerFunctions].filterFunc = &filterPacketType; + triggers[numTriggerFunctions].filterVal = val; + triggers[numTriggerFunctions].ioctl = 0; + triggers[numTriggerFunctions].notFlag = not; + numTriggerFunctions++; + break; + case FILTER_SVCLEV: + sscanf(p, "%9s %u", triggerType, &val); + triggers[numTriggerFunctions].filterFunc = &filterServiceLevel; + triggers[numTriggerFunctions].filterVal = val; + triggers[numTriggerFunctions].ioctl = 0; + triggers[numTriggerFunctions].notFlag = not; + numTriggerFunctions++; + break; + case FILTER_ATTRID: + sscanf(p, "%9s %9s", triggerType, strVal); + if (strstr(strVal, "0x") != NULL) { + sscanf(p, "%9s 0x%x", strVal, &val); + } else { + sscanf(p, "%9s %u", strVal, &val); + } + triggers[numTriggerFunctions].filterFunc = &filterAttrID; + triggers[numTriggerFunctions].filterVal = val; + triggers[numTriggerFunctions].ioctl = 0; + triggers[numTriggerFunctions].notFlag = not; + numTriggerFunctions++; + break; + case FILTER_TRANS_ID_HIGH: + sscanf(p, "%9s %9s", triggerType, strVal); + if (strstr(strVal, "0x") != NULL) { + sscanf(p, "%9s 0x%x", strVal, &val); + } else { + sscanf(p, "%9s %u", strVal, &val); + } + triggers[numTriggerFunctions].filterFunc = &filterTransactionIDHigh; + triggers[numTriggerFunctions].filterVal = val; + triggers[numTriggerFunctions].ioctl = 0; + triggers[numTriggerFunctions].notFlag = not; + numTriggerFunctions++; + break; + case FILTER_TRANS_ID_LOW: + sscanf(p, "%9s %9s", triggerType, strVal); + if (strstr(strVal, "0x") != NULL) { + sscanf(p, "%9s 0x%x", strVal, &val); + } else { + sscanf(p, "%9s %u", strVal, &val); + } + triggers[numTriggerFunctions].filterFunc = &filterTransactionIDLow; + triggers[numTriggerFunctions].filterVal = val; + triggers[numTriggerFunctions].ioctl = 0; + triggers[numTriggerFunctions].notFlag = not; + numTriggerFunctions++; + break; + case FILTER_QP: + sscanf(p, "%9s %u", triggerType, &val); + triggers[numTriggerFunctions].filterFunc = &filterQueuePair; + triggers[numTriggerFunctions].filterVal = val; + triggers[numTriggerFunctions].ioctl = 0; + triggers[numTriggerFunctions].notFlag = not; + numTriggerFunctions++; + break; + case FILTER_COND: + if (not) { + fprintf(stderr, "Not sign not allowed on condition\n"); + exit(1); + } + if (gotCondition) { + fprintf(stderr, "Only one condition statement allowed\n"); + exit(1); + } + gotTriggerCondition = 1; + sscanf(p, "%9s %9s", triggerType, strVal); + if ((triggerCondition = getCondType(strVal)) < 0) { + fprintf(stderr, "Invalid condition type %s\n", strVal); + exit(1); + } + break; + } + } + + fclose(fp); + + return; +} + +void growPacketTable() +{ + packet *newPackets; + int i; + uint32 newNumPackets; + uint32 index; + + // grow by a quarter + newNumPackets = numpackets * 1.25; + newPackets = (packet *)malloc(newNumPackets * sizeof(packet)); + if (newPackets == NULL) { + fprintf(stderr, "opapacketcapture: Error allocating new packets array: %s\n", strerror(errno)); + exit(1); + } + + // copy in current table + memcpy(newPackets, packets, numpackets * sizeof(packet)); + + // adjust next pointers + for (i = 0; i < (numpackets-1); i++) { + index = (uint32)(packets[i].next - packets); + newPackets[i].next = newPackets + index; + } + + // initialize rest of table + for (i = (numpackets - 1); i < (newNumPackets - 1); i++) + newPackets[i].next = &newPackets[i+1]; + newPackets[newNumPackets-1].next = NULL; + + // reassign free/oldest/newest pointers + index = (uint32)(freePackets - packets); + freePackets = newPackets + index; + index = (uint32)(oldestPacket - packets); + oldestPacket = newPackets + index; + index = (uint32)(newestPacket - packets); + newestPacket = newPackets + index; + + // free old table and reset pointer + free(packets); + packets = newPackets; + numpackets = newNumPackets; + + return; +} + +packet *getPacket() +{ + packet *ret; + + if (freePackets->next == NULL) + growPacketTable(); + ret = freePackets; + freePackets = freePackets->next; + numPacketsTaken++; + + return(ret); +} + +void returnPacket(packet *p) +{ + p->next = freePackets; + freePackets = p; + numPacketsTaken--; + return; +} + +void addNewPacket(packet *p) +{ + int done; + packet *p1; + packet *formerNewestPacket; + int overlap; + int myEndBlockNum = p->blockNum + p->numBlocks - 1; + int oldestEndBlockNum; + + if (oldestPacket != NULL) { + newestPacket->next = p; + formerNewestPacket = newestPacket; + newestPacket = p; + done = 0; + while (!done) { + /* did this packet overwrite oldest? */ + overlap = 0; + oldestEndBlockNum = oldestPacket->blockNum + oldestPacket->numBlocks - 1; + if ((myEndBlockNum >= oldestPacket->blockNum) && (myEndBlockNum <= oldestEndBlockNum)) /* overwrote part of oldest */ + overlap = 2; + else if ((p->blockNum <= oldestPacket->blockNum) && (myEndBlockNum >= oldestEndBlockNum)) /* new packet engulfs oldest */ + overlap = 3; + if (overlap) { + p1 = oldestPacket; + oldestPacket = oldestPacket->next; + returnPacket(p1); + } else + done = 1; + } + if (!applyFilters(p)) { + p->numBlocks = 0; + newestPacket = formerNewestPacket; + newestPacket->next = NULL; + returnPacket(p); + } else + numPacketsStored++; + if (numTriggerFunctions && applyTriggers(p)) { + if (!triggerSeen) { + triggerSeen = 1; + printf("\nopapacketcapture: Triggered by trigger file conditions\n"); + } + } + } else { + oldestPacket = p; + newestPacket = p; + p->next = NULL; + if (!applyFilters(p)) { + oldestPacket = NULL; + newestPacket = NULL; + p->numBlocks = 0; + } else + numPacketsStored++; + if (numTriggerFunctions && applyTriggers(p)) { + if (!triggerSeen) { + triggerSeen = 1; + printf("\nopapacketcapture: Triggered by trigger file conditions\n"); + } + } + } + + + return; +} + +void advanceCurrentBlock(packet *p) +{ + + currentBlock += (p->numBlocks * BLOCKSIZE); + + /* wrap if big packet will be too big */ + if ((blocksTableSize - (currentBlock - blocks)) < STL_MAX_PACKET_SIZE) { + currentBlock = blocks; + } + return; +} + +int initPcapHeader(int fd) +{ + pcapHdr_t fileHdr; + memset(&fileHdr, 0, sizeof(fileHdr)); + + fileHdr.magicNumber = STL_WIRESHARK_MAGIC; + fileHdr.versionMajor = STL_WIRESHARK_MAJOR; + fileHdr.versionMinor = STL_WIRESHARK_MINOR; +#if 0 + fileHdr.snapLen = IB_PACKET_SIZE; +#else + fileHdr.snapLen = 65535; +#endif + fileHdr.networkType = STL_WIRESHARK_ERF; + + return ((write(fd, &fileHdr, sizeof(fileHdr)) > 0) ? 0 : -1); +} + +void writePCAP(int fd, uint64 pktLen, time_t sec, long nsec, uint8 *pkt) +{ + pcapRecHdr_t pcapRec; + extHeader_t ext; + WFR_SnC_HDR *snc = (WFR_SnC_HDR *)pkt; + WFR_SnC_HDR wfrLiteSnc = {0}; + int i; + int erfRecordLen; + + /* Adjust to keep 'nsec' less than 1 second */ + while (nsec >= 1E9L) { + sec++; + nsec -= 1E9L; + } + + pcapRec.ts_sec = sec; + pcapRec.ts_nsec = nsec; + ext.flags = 4; /* set variable length bit */ + ext.lossCtr = 0; + ext.linkType = ERF_TYPE_OPA_SNC; + + /* The high 32 bits of the timestamp contain the integer number of seconds + * while the lower 32 bits contain the binary fraction of the second. + * Unlike the rest of the ERF header this is little endian + */ + StoreLeU64((uint8*)&ext.ts, ((uint64) sec << 32) + (((uint64) nsec << 32) / 1000 / 1000 / 1000)); + + if (IS_FI_MODE(mode)) { + if (verbose > 1) { + fprintf(stderr, "Direction: %u\n", snc->Direction); + fprintf(stderr, "PortNumber: %u\n", snc->PortNumber); + fprintf(stderr, "PBC/RHF: 0x%"PRIx64"\n", snc->u.AsReg64); + fprintf(stderr, "pktLen: %"PRIu64"\n", pktLen); + } + ext.flags |= (snc->PortNumber & 0x1); + } else { + ext.flags |= 1; + wfrLiteSnc.Direction = 2; + wfrLiteSnc.PortNumber = 1; + pktLen += sizeof(WFR_SnC_HDR); + } + + erfRecordLen = pktLen + sizeof(extHeader_t); + /* PCAP record length, including pseudoheaders(e.g.ERF) but not PCAP header */ + pcapRec.packetSize = erfRecordLen; + /* Technically should be wire length + erf header length but no + * difference for OPA. Usually both set to ERF record length + * because packetSize < packetOrigSize should be true + */ + pcapRec.packetOrigSize = erfRecordLen; + /* Total ERF record length including header and any padding */ + ext.length = hton16(erfRecordLen); + /* Packet wire length */ + ext.realLength = hton16(pktLen); + + if (write(fd, &pcapRec, sizeof(pcapRec)) < 0) { + fprintf(stderr, "Failed to write PCAP packet header\n"); + } + if (write(fd, &ext, sizeof(ext)) < 0) { + fprintf(stderr, "Failed to write Ext packet header\n"); + } + if (wfrLiteSnc.Direction == 2) { + if (write(fd, &wfrLiteSnc, sizeof(WFR_SnC_HDR)) < 0) { + fprintf(stderr, "Failed to write SnC packet header\n"); + } + pktLen -= sizeof(WFR_SnC_HDR); + } + if (write(fd, pkt, pktLen) < 0) { + fprintf(stderr, "Failed to write packet.\n"); + } + + if (verbose > 2) { + fprintf(stderr, "TO PCAP: "); + i=0; + if (wfrLiteSnc.Direction == 2) { + for (; i < sizeof(WFR_SnC_HDR); i++ ){ + if (i % 8 == 0) fprintf(stderr, "\n0x%04x ", i); + fprintf(stderr, "%02x ", ((uint8 *)&wfrLiteSnc)[i] ); + if (i % 8 == 3) fprintf(stderr, " "); + } + } + for (; i < pktLen; i++ ) { + if (i % 8 == 0) fprintf(stderr, "\n0x%04x ", i); + fprintf(stderr,"%02x ", pkt[i]); + if (i % 8 == 3) fprintf(stderr, " "); + } + fprintf(stderr, "\n"); + } + + return; +} + +void showPackets(packet *in) { + packet *p; + IB_LRH *pkt; + MAD_COMMON *m; + char packetType[5]; + STL_LID dlid = 0; + STL_LID slid = 0; + uint8 opcode = 0; + uint16 pkey = 0; + + if (in) { + p = in; + } else { + p = oldestPacket; + } + + while (p != NULL) { + // Don't print anything but 9B and 16B + if (is9BWfrPacket(p)) { + pkt = (IB_LRH *)( (uint8 *)(&blocks[p->blockNum * BLOCKSIZE]) + sizeof(WFR_SnC_HDR)); + dlid = getDLID(p); + slid = getSLID(p); + opcode = getOpCode(p); + pkey = getPkey(p); + switch ( opcode >>5 ) { + case 0: + strcpy(packetType, "RC"); + break; + case 1: + strcpy(packetType, "UC"); + break; + case 2: + strcpy(packetType, "RD"); + break; + case 3: + strcpy(packetType, "UD"); + break; + default: + strcpy(packetType, "??"); + break; + } + printf("showpacket(9b):dest lid 0x%08x\tsrc lid 0x%08x\tsvc lev %d\tpkey is 0x%04x\ttype is %s\n", dlid, slid, pkt->l.ServiceLevel, pkey, packetType); + if (isMAD(p)) { + m = getMAD(p); + if (m != NULL) { + printf("showpacket(9b):mgmt class 0x%02x\tAttributeID 0x%04x\n", m->MgmtClass, ntoh16(m->AttributeID)); + } + } + } else if (is16BWfrPacket(p)) { + dlid = getDLID(p); + slid = getSLID(p); + printf("showpacket(16b):dest lid 0x%08x\tsrc lid 0x%08x\t", dlid, slid); + if (isMAD(p)) { + m = getMAD(p); + if (m != NULL) { + printf("mgmt class 0x%02x\tAttributeID 0x%04x\t", m->MgmtClass, ntoh16(m->AttributeID)); + } + } + printf("\n"); + } + if (in) { + break; + } else { + p = p->next; + } + } + + return; +} + +void writePacketData() +{ + packet *p; + int fd; + + if (gotoutfile) { + fd = open(out_file, O_RDWR|O_CREAT|O_TRUNC, 00644); + } else { + fd = open(PACKET_OUT_FILE, O_RDWR|O_CREAT|O_TRUNC, 00644); + } + if (fd < 0) { + fprintf(stderr, "Error opening output file %s\n", strerror(errno)); + exit(1); + } + if (initPcapHeader(fd) < 0) { + fprintf(stderr, "Error writing pcap header - %s\n", strerror(errno)); + exit(1); + } + + p = oldestPacket; + + while (p != NULL) { + writePCAP(fd, (unsigned short) p->size, p->ts_sec, p->ts_nsec, &blocks[p->blockNum * BLOCKSIZE]); + p = p->next; + } + + close(fd); + + return; +} +int debugtool_capture_device_filter(const struct dirent *d) { + int hfi = -1; + int port = -1; + + if (2 == sscanf(d->d_name, "ipath_capture_%02d_%02d", &hfi, &port)) { + return (hfi != -1 && port != -1 ? 1 : 0); + } + return 0; +} +int wfr_capture_device_filter(const struct dirent *d) { + int gen = -1; + int hfi = -1; + + if (2 == sscanf(d->d_name, "hfi%d_diagpkt%d", &gen, &hfi)) { + return (gen == 1 && hfi != -1 ? 1 : 0); + } + return 0; +} +int all_capture_device_filter(const struct dirent *d) { + int gen = -1; + int hfi = -1; + int port = -1; + + if (2 == sscanf(d->d_name, "hfi%d_diagpkt%d", &gen, &hfi)) { + return ((gen == 1) && hfi != -1 ? 1 : 0); + + } + if (2 == sscanf(d->d_name, "ipath_capture_%02d_%02d", &hfi, &port)) { + return (hfi != -1 && port != -1 ? 1 : 0); + } + return 0; +} + +static char *modeToText(uint8 mode){ + switch (mode) { + case 0: return "All"; + case DEBUG_TOOL_MODE: return "DebugTool"; + case WFR_MODE: return "WFR"; + default: return "Unknown"; + } +} + +static void Usage(int exitcode) +{ + fprintf(stderr, "Usage: opapacketcapture [-o outfile] [-d devfile] [-f filterfile] [-t triggerfile] [-l triggerlag]\n"); + fprintf(stderr, " [-a alarm] [-p packets] [-s maxblocks] [-v [-v]]\n"); + fprintf(stderr, " or\n"); + fprintf(stderr, " opapacketcapture --help\n"); + fprintf(stderr, " --help - produce full help text\n"); + fprintf(stderr, " -o - output file for captured packets - default is "PACKET_OUT_FILE"\n"); + fprintf(stderr, " -d - device file for capturing packets\n"); + fprintf(stderr, " -f - filter file used for filtering - if absent, no filtering\n"); + fprintf(stderr, " -t - trigger file used for triggering a stop capture - if absent, normal triggering \n"); + fprintf(stderr, " -l - trigger lag: number of packets to collect after trigger condition met before dump and exit (default is 10)\n"); + fprintf(stderr, " -a - number of seconds for alarm trigger to dump capture and exit\n"); + fprintf(stderr, " -p - number of packets for alarm trigger to dump capture and exit\n"); + fprintf(stderr, " -s - number of blocks to allocate for ring buffer (in Millions) [block = 64 Bytes] - default is 2 (128 MiB)\n"); +// fprintf(stderr, " -m - protocol mode: 0=All, 1=DebugTool, 2=WFR; default is All\n"); + fprintf(stderr, " -v - verbose output (Use verbose Level 1+ to show levels)\n"); + if (verbose) { + fprintf(stderr, " Level 1: Live Packet Count\n"); + fprintf(stderr, " Level 2: Basic Packet read info \n"); + fprintf(stderr, " Level 3: HEX Dump of packet going into output file\n"); + fprintf(stderr, " Level 4: HEX Dump of data coming over snoop device\n"); + } + fprintf(stderr, "\n"); + fprintf(stderr, "To stop capture and trigger dump, kill with SIGINT or SIGUSR1.\n"); + fprintf(stderr, "Program will dump packets to file and exit\n"); + + exit(exitcode); +} + +int main (int argc, char *argv[]) +{ + int numRead; + int numDevs = 0; + int i; + int c; + packet *newPacket; + char strArg[64] = {0}; + const char *opts="o:d:f:t:l:a:p:s:m:v"; + const struct option longopts[] = {{"help", 0, 0, '$'}, + {0, 0, 0, 0}}; + FILE *fp = NULL; + int fd = 0; + struct timespec ts = {0}; + uint64 numblocks = DEFAULT_NUMBLOCKS; + unsigned lasttime=0; + struct dirent **d; + char deviceCmpStr[80] = {0}; + + while (-1 != (c = getopt_long(argc, argv, opts, longopts, NULL))) { + switch (c) { + case 'a': + strncpy(strArg, optarg, sizeof(strArg)-1); + strArg[sizeof(strArg)-1]=0; + gotAlarmArg = 1; + break; + case 'p': + if (FSUCCESS != StringToUint64(&numPacketsMax, optarg, NULL, 0, TRUE)) { + fprintf(stderr, "opapacketcapture: Invalid size: %s\n", optarg); + Usage(2); + } + break; + case 'm': + if (FSUCCESS != StringToUint8(&mode, optarg, NULL, 0, TRUE)) { + fprintf(stderr, "opapacketcapture: Invalid mode: %s\n", optarg); + Usage(2); + } + gotModeArg = 1; + break; + case 'f': + strncpy(filterFileArg, optarg, sizeof(filterFileArg)-1); + filterFileArg[sizeof(filterFileArg)-1]=0; + gotFilterFileArg = 1; + break; + case 't': + strncpy(triggerFileArg, optarg, sizeof(triggerFileArg)-1); + triggerFileArg[sizeof(triggerFileArg)-1]=0; + gotTriggerFileArg = 1; + break; + case 'd': + strncpy(devfile, optarg, sizeof(devfile)-1); + devfile[sizeof(devfile)-1]=0; + gotdevfile = 1; + break; + case 'o': + strncpy(out_file, optarg, sizeof(out_file)-1); + out_file[sizeof(out_file)-1]=0; + gotoutfile = 1; + break; + case 'l': + sscanf(optarg, "%d", &triggerLag); + gotTriggerLagArg = 1; + break; + case 's': + if (FSUCCESS != StringToUint64(&numblocks, optarg, NULL, 0, TRUE)) { + fprintf(stderr, "opapacketcapture: Invalid size: %s\n", optarg); + Usage(2); + } + numblocks *= (1024 * 1024); + break; + case 'v': + verbose++; + break; + case '$': + Usage(0); + default: + fprintf(stderr, "opapacketcapture: Invalid option -%c\n", c); + Usage(2); + } + } + + if (gotAlarmArg) { + char *p; + int alarmMult = 1; + if ((p = strchr(strArg, 'm')) != NULL) { + alarmMult = 60; + } else if ((p = strchr(strArg, 'h')) != NULL) { + alarmMult = 60*60; + } else if ((p = strchr(strArg, 'd')) != NULL) { + alarmMult = 60*60*24; + } + sscanf(strArg, "%u", &alarmArg); + alarmArg *= alarmMult; + } + + /* Scan "/dev/" directory for capture devices */ + if (gotModeArg) { + switch (mode) { + case DEBUG_TOOL_MODE: + numDevs = scandir("/dev/", &d, debugtool_capture_device_filter, alphasort); + break; + case WFR_MODE: + numDevs = scandir("/dev/", &d, wfr_capture_device_filter, alphasort); + break; + default: + numDevs = scandir("/dev/", &d, all_capture_device_filter, alphasort); + } + } else { + numDevs = scandir("/dev/", &d, all_capture_device_filter, alphasort); + } + if (numDevs == 0) { + fprintf(stderr, "opapacketcapture: Packet capture not supported by installed hfi driver. No capture devices found on system\n"); + exit(1); + } + + /* Check if supplied devfile matches one of the possible found devices */ + if (gotdevfile) { + boolean isFound = FALSE; + for (i = 0; i < numDevs; i++) { + snprintf(deviceCmpStr, sizeof(deviceCmpStr), "/dev/%s", d[i]->d_name); + if (strncmp(devfile, deviceCmpStr, sizeof(deviceCmpStr)) == 0) { + isFound = TRUE; + break; + } + } + if (!isFound) { + fprintf(stderr, "opapacketcapture: Error %s does not match 1 of %u devices found on system: mode %s\n", devfile, numDevs, modeToText(mode)); + for (i = 0; verbose && i < numDevs; i++) { + fprintf(stderr, " /dev/%s\n", d[i]->d_name); + } + exit(1); + } + } else if (numDevs > 1) { + fprintf(stderr, "opapacketcapture: Error %u devices found on system, please choose one: mode %s\n", numDevs, modeToText(mode)); + for (i = 0; verbose && i < numDevs; i++) { + fprintf(stderr, " /dev/%s\n", d[i]->d_name); + } + exit(1); + } else { + snprintf(devfile, sizeof(devfile), "/dev/%s", d[0]->d_name); + } + + /* now that devfile is known try to determine operating mode */ + if (!gotModeArg) { + int gen = -1; + int hfi = -1; + int port = -1; + if (2 == sscanf(devfile, "/dev/hfi%d_diagpkt%d", &gen, &hfi)) { + switch (gen) { + case 1: + mode = WFR_MODE; + break; + default: + fprintf(stderr, "opapacketcapture: Error could not determine operating mode from devfile: %s\n", devfile); + exit(1); + } + } else if (2 == sscanf(devfile, "/dev/ipath_capture_%02d_%02d", &hfi, &port) && (hfi != -1 && port != -1)) { + mode = DEBUG_TOOL_MODE; + } else { + fprintf(stderr, "opapacketcapture: Error could not determine operating mode from devfile: %s\n", devfile); + exit(1); + } + } + + printf("opapacketcapture: Capturing from %s using %s mode\n", devfile, modeToText(mode)); + + blocksTableSize = BLOCKSIZE * numblocks; + blocks = (uint8 *)malloc(blocksTableSize); + if (blocks == NULL) { + fprintf(stderr, "opapacketcapture: Error allocating blocks array: %s\n", strerror(errno)); + exit(1); + } + + numpackets = (numblocks/3); + packets = (packet *)malloc(numpackets * sizeof(packet)); + if (packets == NULL) { + fprintf(stderr, "opapacketcapture: Error allocating packets array: %s\n", strerror(errno)); + exit(1); + } + for (i = 0; i < (numpackets-1); i++) + packets[i].next = &packets[i+1]; + packets[numpackets-1].next = NULL; + + currentBlock = blocks; + freePackets = packets; + oldestPacket = NULL; + newestPacket = NULL; + stopcapture = 0; + retryCount = 0; + + filterCondition = COND_TYPE_AND; + + signal(SIGINT, my_handler); + signal(SIGUSR1, my_handler); + signal(SIGALRM, my_handler); + + if (gotFilterFileArg) + setupFilters(filterFileArg); + + if (gotTriggerFileArg) + setupTriggers(triggerFileArg); + + /* open file */ + fdIn = open(devfile, O_RDONLY); + + if (fdIn < 0) { + if (errno == ENOENT) + fprintf(stderr, "opapacketcapture: Packet capture not supported by installed hfi driver\n"); + else + fprintf(stderr, "opapacketcapture: Unable to open: %s: mode %u: %s\n", + devfile, mode, strerror(errno)); + free(packets); + return -1; + } + + if (alarmArg) + alarm(alarmArg); + + if (writethrough) { + unlink(out_file); + fp = fopen(out_file, "a+"); + if (fp == NULL) { + exit(1); + } + fd = fileno(fp); + if (initPcapHeader(fd) < 0) { + fprintf(stderr, "opapacketcapture: Error writing pcap header: %s\n", strerror(errno)); + exit(1); + } + + } + + if (ioctlConfigured) { + if (ioctl(fdIn, QIB_SNOOP_IOCSETFILTER, &filterCmd) < 0) { + fprintf(stderr, "opapacketcapture: Error issuing ioctl to QIB driver to set filter: %s\n", strerror(errno)); + exit(1); + } + } + + if (!clock_getres(CLOCK_REALTIME, &ts)) { + if (verbose) + printf("opapacketcapture: Clock precision: %ldns\n", ts.tv_nsec); + if (ts.tv_nsec != 1) + fprintf(stderr, "opapacketcapture: Error clock precision not 1ns: %ldns\n", ts.tv_nsec ); + } else { + fprintf(stderr, "opapacketcapture: Error getting clock precision: %s\n", strerror(errno)); + exit(1); + } + + printf("opapacketcapture: Capturing packets using %llu MiB buffer\n", (long long unsigned int)blocksTableSize/(1024*1024)); + + while (!stopcapture) { + numRead = read(fdIn, (char *)currentBlock , STL_MAX_PACKET_SIZE); + + if (numRead == 0) { + stopcapture = 1; + continue; + } + + if (numRead < 0) { + if (errno == EAGAIN) { + if (++retryCount <= 25) + continue; + } + if (errno != EINTR) + fprintf(stderr, "opapacketcapture: Error reading packet: %s\n", strerror(errno)); + stopcapture = 1; + continue; + } + + retryCount = 0; + + clock_gettime(CLOCK_REALTIME, &ts); + numPacketsRead++; + if (verbose > 1) { + fprintf(stderr, "Packet %u", numPacketsRead); + } + if (verbose > 3) { + fprintf(stderr," numRead: %u 0x%x", numRead, numRead); + for ( i = 0; i < numRead; i++) { + if (i % 8 == 0) fprintf(stderr, "\n0x%04x ", i); + fprintf(stderr,"%02x ", currentBlock[i]); + if (i % 8 == 3) fprintf(stderr, " "); + } + } + if (verbose > 1) fprintf(stderr, "\n"); + + /* get next packet and fill it */ + newPacket = getPacket(); + newPacket->blockNum = (currentBlock - blocks) / BLOCKSIZE; + newPacket->size = numRead; + newPacket->numBlocks = (numRead / BLOCKSIZE) + ((numRead % BLOCKSIZE) ? 1 : 0); + newPacket->ts_sec = ts.tv_sec; + newPacket->ts_nsec = ts.tv_nsec; + newPacket->next = NULL; + + addNewPacket(newPacket); + + // Print some parsed content of the new packet + if (verbose >= 2) { + showPackets(newPacket); + } + + if (triggerSeen) { + if (afterTriggerPackets++ == triggerLag) + stopcapture = 1; + } + + advanceCurrentBlock(newPacket); + + if (verbose == 1 && ts.tv_sec > lasttime+5) { + lasttime = ts.tv_sec; + printf("\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b%10u packets", numPacketsRead); + fflush(stdout); + } + + if (numPacketsStored >= numPacketsMax) { + stopcapture = 1; + } + } + if (verbose) + printf("\n"); + + /* clear filter if nec. and close */ + if (ioctlConfigured) { + if (ioctl(fdIn, QIB_SNOOP_IOCCLEARFILTER, NULL) < 0) { + fprintf(stderr, "opapacketcapture: Error issuing ioctl to QIB driver to clear filter: %s\n", strerror(errno)); + exit(1); + } + } + close(fdIn); + + /*showPackets(NULL);*/ + printf("Number of packets stored is %d\n", numPacketsStored); + + writePacketData(); + + exit(0); +} diff --git a/IbaTools/opapacketcapture/opapacketcapture.h b/IbaTools/opapacketcapture/opapacketcapture.h new file mode 100644 index 0000000..973a2f4 --- /dev/null +++ b/IbaTools/opapacketcapture/opapacketcapture.h @@ -0,0 +1,240 @@ +/* BEGIN_ICS_COPYRIGHT5 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + * ** END_ICS_COPYRIGHT5 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +#ifndef __H_IBA_PCAP +#define __H_IBA_PCAP + +#include "iba/stl_types.h" + +#include "iba/public/ipackon.h" + +#define BLOCKSIZE 64 +#if 1 +#define DEFAULT_NUMBLOCKS (2*1024*1024) +#else +#define DEFAULT_NUMBLOCKS (500) +#endif + +#define STL_WIRESHARK_MAJOR 2 +#define STL_WIRESHARK_MINOR 4 +/*PCAP Nanosecond format magic*/ +#define STL_WIRESHARK_MAGIC 0xa1b23c4d +#define STL_WIRESHARK_ERF 197 + +#define ERF_TYPE_OPA_SNC 28 +#define ERF_TYPE_OPA_9B 29 + +#define FILTER_COND 0 +#define FILTER_DLID 1 +#define FILTER_SLID 2 +#define FILTER_MCLASS 3 +#define FILTER_PKEY 4 +#define FILTER_PTYPE 5 +#define FILTER_SVCLEV 6 +#define FILTER_ATTRID 7 +#define FILTER_QP 8 +#define FILTER_TRANS_ID_HIGH 9 +#define FILTER_TRANS_ID_LOW 10 + +#define PACKETTYPE_RC 0 +#define PACKETTYPE_UC 1 +#define PACKETTYPE_RD 2 +#define PACKETTYPE_UD 3 +#define PACKETTYPE_ERR 9999 + +#define COND_TYPE_AND 0 +#define COND_TYPE_OR 1 + +#define DEFAULT_TRIGGER_LAG 10 + +#define PKEY_MASK 0x7fff + +// For Future Use if we add a higher complexity to our debugging +#define DBG_FLAGS_BIT0_X_SNC 1 +#define DBG_FLAGS_BIT1_X_L2 1<<1 +#define DBG_FLAGS_BIT2_X_MAD 1<<2 +#define DBG_FLAGS_BIT3_X_PAYLOAD 1<<3 +#define DBG_FLAGS_BIT4_P_SNC 1<<4 +#define DBG_FLAGS_BIT5_P_SNC 1<<5 +#define DBG_FLAGS_BIT6_P_L2 1<<6 +#define DBG_FLAGS_BIT7_P_MAD 1<<7 + +#define DEBUG_TOOL_MODE 1 +#define WFR_MODE 2 + +#define IS_FI_MODE(m) (m == WFR_MODE) + +#define STL_WFR_INBOUND 1 +#define STL_WFR_OUTBOUND 0 +#define STL_WFR_RCV_BYPASS 0x4 +#define STL_WFR_RCV_IB 0x2 +#define STL_L2_16B 0x2 +#define STL_L2_9B 0x3 +#define STL_9B_LNH_BTH 0x2 +#define STL_9B_LNH_GRH 0x3 +#define STL_16B_L4_FM 0x8 +#define STL_16B_L4_IB 0x9 +#define STL_16B_L4_IB_GLOBAL 0xa + +#define STL_16B_L4_FM_SIZE 8 + +typedef struct _packet { + uint64 blockNum; + uint64 size; + uint64 numBlocks; + time_t ts_sec; + long ts_nsec; + struct _packet *next; +} packet; + +typedef struct _pcapHdr_s { + uint32 magicNumber; + uint16 versionMajor; + uint16 versionMinor; + int32 tzOffset; + uint32 sigFigs; + uint32 snapLen; + uint32 networkType; +} pcapHdr_t; + +typedef struct _pcapRecHdr_s { + uint32 ts_nsec; + uint32 ts_sec; + uint32 packetSize; + uint32 packetOrigSize; +} pcapRecHdr_t; + +typedef struct extHeader_s { + uint64 ts; + uint8 linkType; /* Lyink Type 26 = STL; 21 = IB */ + uint8 flags; /* ERF flags */ + uint16 length; /* Record Length in Bytes */ + uint16 lossCtr; /* Number of packets lost between two captured packets */ + uint16 realLength; /* Wire Length in Bytes */ +} extHeader_t; + +typedef struct _WFR_SnC_HDR { + uint8 PortNumber; // Should be 1 for WFR + uint8 Direction; // 0=Egress (Out), 1=Ingress (In) + uint8 Reserved[6]; + union { + uint64 AsReg64; + STL_FIELDUNION14(PBC, 64, // if Direction == 0 + reserved_63_48:16, + pbcstaticratecontrolcnt:16, + pbcintr:1, + pbcdcinfo:1, + pbctestebp:1, + pbcpacketbypass:1, + pbcinserthcrc:2, + pbccreditreturn:1, + pbcinsertbypassicrc:1, + pbctestbadicrc:1, + pbcfecn:1, + reserved_21_16:6, + pbcvl:4, + pbclengthdws:12); + STL_FIELDUNION17(RHF, 64, // if Direction == 1 + icrcerr:1, + reserved_62_62:1, + eccerr:1, + lenerr:1, + tiderr:1, + rcvtypeerr:3, + dcerr:1, + dcuncerr:1, + khdrlenerr:1, + hdrqoffset:9, + egroffset:12, + rcvseq:4, + dcinfo:1, + egrindex:11, + useegrbfr:1, + rcvtype:3, + pktlen:12); + } u; +} WFR_SnC_HDR; + +#define DESTQP_MASK 0x00ffffff + +typedef struct _filterFunc_s { + int (*filterFunc)(packet *, uint32); + uint32 filterVal; + int ioctl; + int notFlag; +} filterFunc_t; + +typedef struct _qibPacketFilterCommand_s { + int opcode; + int length; + void *value_ptr; +} qibPacketFilterCommand_t; + +/* Driver ioctls */ +#define QIB_SNOOP_IOC_MAGIC IB_IOCTL_MAGIC +#define QIB_SNOOP_IOC_BASE_SEQ 0x80 +/* This starts our ioctl sequence + * numbers *way* off from the ones + * defined in ib_core + */ +#define QIB_SNOOP_IOCGETLINKSTATE \ + _IO(QIB_SNOOP_IOC_MAGIC, QIB_SNOOP_IOC_BASE_SEQ) +#define QIB_SNOOP_IOCSETLINKSTATE \ + _IO(QIB_SNOOP_IOC_MAGIC, QIB_SNOOP_IOC_BASE_SEQ+1) +#define QIB_SNOOP_IOCCLEARQUEUE \ + _IO(QIB_SNOOP_IOC_MAGIC, QIB_SNOOP_IOC_BASE_SEQ+2) +#define QIB_SNOOP_IOCCLEARFILTER \ + _IO(QIB_SNOOP_IOC_MAGIC, QIB_SNOOP_IOC_BASE_SEQ+3) +#define QIB_SNOOP_IOCSETFILTER \ + _IO(QIB_SNOOP_IOC_MAGIC, QIB_SNOOP_IOC_BASE_SEQ+4) + + +enum qib_packet_filter_opcodes { + FILTER_BY_LID, + FILTER_BY_DLID, + FILTER_BY_MAD_MGMT_CLASS, + FILTER_BY_QP_NUMBER, + FILTER_BY_PKT_TYPE, + FILTER_BY_SERVICE_LEVEL, + FILTER_BY_PKEY +}; + +#define IB_PACKET_SIZE 4208 + +#define STL_MAX_PACKET_SIZE 16*1024 // 16K +#define WIRESHARK_MAX_LENGTH 65535 + + +#define PACKET_OUT_FILE "packetDump.pcap" + +#include "iba/public/ipackoff.h" + +#endif /* __H_IBA_PCAP */ diff --git a/IbaTools/opapacketcapture/triggerFile.txt b/IbaTools/opapacketcapture/triggerFile.txt new file mode 100644 index 0000000..8e4027b --- /dev/null +++ b/IbaTools/opapacketcapture/triggerFile.txt @@ -0,0 +1,41 @@ +# Trigger file for opapacketcapture +# [ICS VERSION STRING: unknown] + +# Trigger is keyword followed by whitespace then trigger value + +# Available triggers and values: + +#DLID +#SLID +#MCLASS +#PKEY +#PTYPE +#SVCLEV +#ATTRID +#QP + +# Additionally, condition may be given to handle relationship between multiple +# triggers - AND or OR. Default is AND + +# Any trigger may be negated with first character '!' or '~' + +#COND + +# Examples: (edit as appropriate) + +SLID 2 # trigger on source lid of 2 + +PKEY 0xffff # trigger on pkey of 0xffff + +PTYPE UD # trigger on packet type of UD + +!DLID 4 # trigger on any dest lids except 4 + +~SVCLEV 1 # trigger on any service level except 1 + +#!ATTRID 18 # trigger on any MAD attribute IDs except 18 +!ATTRID 0x12 # trigger on any MAD attribute IDs except 0x12 + +QP 1 # trigger on dest QP of 1 + +COND AND # AND all these conditions together - all must be true diff --git a/IbaTools/opapaextract/Makefile b/IbaTools/opapaextract/Makefile new file mode 100644 index 0000000..c2303ed --- /dev/null +++ b/IbaTools/opapaextract/Makefile @@ -0,0 +1,164 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** +# Makefile for opapaextract + +# Include Make Control Settings +include $(TL_DIR)/$(PROJ_FILE_DIR)/Makesettings.project + +#=============================================================================# +# Definitions: +#-----------------------------------------------------------------------------# + +# Name of SubProjects +DS_SUBPROJECTS = +# name of executable or downloadable image +EXECUTABLE = $(BUILDDIR)/opapaextract$(EXE_SUFFIX) +# list of sub directories to build +DIRS = +# C files (.c) +CFILES = \ + opapaextract.c \ + # Add more c files here +# C++ files (.cpp) +CCFILES = \ + # Add more cpp files here +# lex files (.lex) +LFILES = \ + # Add more lex files here +# archive library files (basename, $ARFILES will add MOD_LIB_DIR/prefix and suffix) +LIBFILES= +# Windows Resource Files (.rc) +RSCFILES = +# Windows IDL File (.idl) +IDLFILE = +# Windows Linker Module Definitions (.def) file for dll's +DEFFILE = +# targets to build during INCLUDES phase (add public includes here) +INCLUDE_TARGETS = \ + # Add more h hpp files here +# Non-compiled files +MISC_FILES = +# all source files +SOURCES = $(CFILES) $(CCFILES) $(LFILES) $(RSCFILES) $(IDLFILE) +# Source files to include in DSP File +DSP_SOURCES = $(INCLUDE_TARGETS) $(SOURCES) $(MISC_FILES) \ + $(RSCFILES) $(DEFFILE) $(MAKEFILE) +# all object files +OBJECTS = $(CFILES:.c=$(OBJ_SUFFIX)) $(CCFILES:.cpp=$(OBJ_SUFFIX)) \ + $(LFILES:.lex=$(OBJ_SUFFIX)) +RSCOBJECTS = $(RSCFILES:.rc=$(RES_SUFFIX)) +# targets to build during LIBS phase +LIB_TARGETS_IMPLIB = +LIB_TARGETS_ARLIB = # $(LIB_PREFIX)ResourceTest$(ARLIB_SUFFIX) +LIB_TARGETS_EXP = $(LIB_TARGETS_IMPLIB:$(ARLIB_SUFFIX)=$(EXP_SUFFIX)) +LIB_TARGETS_MISC = +# targets to build during CMDS phase +CMD_TARGETS_SHLIB = +CMD_TARGETS_EXE = $(EXECUTABLE) +CMD_TARGETS_MISC = +# files to remove during clean phase +CLEAN_TARGETS_MISC = +CLEAN_TARGETS = $(OBJECTS) $(RSCOBJECTS) $(IDL_TARGETS) $(CLEAN_TARGETS_MISC) +# other files to remove during clobber phase +CLOBBER_TARGETS_MISC= +# sub-directory to install to within bin +BIN_SUBDIR = +# sub-directory to install to within include +INCLUDE_SUBDIR = + +# Additional Settings +#CLOCALDEBUG = User defined C debugging compilation flags [Empty] +#CCLOCALDEBUG = User defined C++ debugging compilation flags [Empty] +#CLOCAL = User defined C flags for compiling [Empty] +#CCLOCAL = User defined C++ flags for compiling [Empty] +#BSCLOCAL = User flags for Browse File Builder [Empty] +#DEPENDLOCAL = user defined makedepend flags [Empty] +#LINTLOCAL = User defined lint flags [Empty] +#LOCAL_INCLUDE_DIRS = User include directories to search for C/C++ headers [Empty] +#LDLOCAL = User defined C flags for linking [Empty] +#IMPLIBLOCAL = User flags for Object Lirary Manager [Empty] +#MIDLLOCAL = User flags for IDL compiler [Empty] +#RSCLOCAL = User flags for resource compiler [Empty] +#LOCALDEPLIBS = User libraries to include in dependencies [Empty] +#LOCALLIBS = User libraries to use when linking [Empty] +# (in addition to LOCALDEPLIBS) +#LOCAL_LIB_DIRS = User library directories for libpaths [Empty] + +CLOCAL=$(CIBACCESS) $(CPIE) +LOCAL_INCLUDE_DIRS= +ifeq "$(IB_STACK)" "IBACCESS" +LOCALDEPLIBS =$(IBACCESS_USER_LIBS) IbPrint +LOCALLIBS= +LOCAL_LIB_DIRS=$(IBACCESS_USER_LIB_DIRS) +else +LOCALDEPLIBS =$(IBACCESS_USER_LIBS) opamgt-priv IbPrint Xml Topology +LOCALLIBS=$(OPENIB_USER_LIBS) +LOCAL_LIB_DIRS=$(OPENIB_USER_LIB_DIRS) $(IBACCESS_USER_LIB_DIRS) +endif + + +# Include Make Rules definitions and rules +include $(TL_DIR)/IbaTools/Makerules.module + +#=============================================================================# +# Overrides: +#-----------------------------------------------------------------------------# +#CCOPT = # C++ optimization flags, default lets build config decide +#COPT = # C optimization flags, default lets build config decide +#SUBSYSTEM = Subsystem to build for (none, console or windows) [none] +# (Windows Only) +#USEMFC = How Windows MFC should be used (none, static, shared, no_mfc) [none] +# (Windows Only) +#=============================================================================# + +#=============================================================================# +# Rules: +#-----------------------------------------------------------------------------# +# process Sub-directories +include $(TL_DIR)/Makerules/Maketargets.toplevel + +# build cmds and libs +include $(TL_DIR)/Makerules/Maketargets.build + +# install for includes, libs and cmds phases +include $(TL_DIR)/Makerules/Maketargets.install + +# install for stage phase +include $(TL_DIR)/Makerules/Maketargets.stage +STAGE:: + $(VS)$(STAGE_INSTALL) $(STAGE_INSTALL_DIR_OPT) $(PROJ_STAGE_FASTFABRIC_DIR) $(EXECUTABLE) + +# Unit test execution +#include $(TL_DIR)/Makerules/Maketargets.runtest + +#=============================================================================# + +#=============================================================================# +# DO NOT DELETE THIS LINE -- make depend depends on it. +#=============================================================================# diff --git a/IbaTools/opapaextract/opapaextract.c b/IbaTools/opapaextract/opapaextract.c new file mode 100644 index 0000000..5acb6fa --- /dev/null +++ b/IbaTools/opapaextract/opapaextract.c @@ -0,0 +1,1742 @@ +/* BEGIN_ICS_COPYRIGHT7 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT7 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +#include +#include +#include +#include +#define _GNU_SOURCE +#include + +#include "topology.h" +#ifdef IB_STACK_OPENIB +#include +#endif +#include "ib_status.h" +#include "stl_mad_priv.h" +#include "iba/stl_pa_priv.h" +#include "opamgt_priv.h" +#include "opamgt_pa_priv.h" +#include "opamgt_pa.h" +#include "stl_print.h" +#include + +// control experiments/tuning of tool +#define USE_FREEZE 1 // freeze image while gathering data + // otherwise no freeze, just do queries + // Freeze may help performance of on-disk queries + // recommend 1 +#define USE_ABS_IMAGENUM 1 // use imageNumber returned in a PA query + //as opposed to Live=0 with decreasing offset as walk + // Abs image number avoids definition of live-offset + // changing due to new PM sweeps occuring mid query + // recommend 1 +#define COMPUTE_DELTA 1 // manually compute counter delta using Get PortCounter + // absolute. Works around a PM disk image cache thrash + // which occurs with Get PortCounter delta + +#define MAX_VFABRIC_NAME 64 // from fm_xml.h + +int g_verbose = 0; +STL_LID g_nodeLid = 0; +uint8 g_portNumber = 0; +uint64 g_nodeGUID = 0; +char g_nodeDesc[STL_PM_NODEDESCLEN]; +uint32 g_deltaFlag = 1; +//uint32 g_userCntrsFlag = 0; +//int32 g_focus = 0; +int32 g_start = 0; +int32 g_range = 0; +uint32 g_liveRate = 0; +uint32 g_gotGroup = 0; +uint32 g_gotLid = 0; +uint32 g_gotPort = 0; +uint32 g_gotGUID = 0; +uint32 g_gotDesc = 0; +//uint32 g_gotImgNum = 0; +//uint32 g_gotImgOff = 0; +//uint32 g_gotFocus = 0; +uint32 g_gotStart = 0; +uint32 g_gotRange = 0; +uint32 g_gotLive = 0; +uint32 g_gotXmit = 0; +//uint32 g_gotvfName = 0; +char g_groupName[STL_PM_GROUPNAMELEN]; +//char g_vfName[MAX_VFABRIC_NAME]; +PrintDest_t g_dest; +struct omgt_port *g_portHandle = NULL; + +typedef struct ColumnEntry_s { + uint64 nodeGUID; + char nodeDesc[64]; + STL_LID nodeLid; + uint8 portNumber; +#if COMPUTE_DELTA + uint64 recentValue; + int recentValueValid; +#endif +} ColumnEntry_t; + +// omits 1st column, which is timestamp +ARRAY g_Columns; // array of ColumnEntry_t + +struct option options[] = { + // basic controls + { "verbose", no_argument, NULL, 'v' }, + { "hfi", required_argument, NULL, 'h' }, + { "port", required_argument, NULL, 'p' }, + + // query data + //{ "output", required_argument, NULL, 'o' }, + { "groupName", required_argument, NULL, 'g' }, + { "lid", required_argument, NULL, 'l' }, + { "portNumber", required_argument, NULL, 'P' }, + { "guid", required_argument, NULL, 'G' }, + { "desc", required_argument, NULL, 'D' }, + { "delta", required_argument, NULL, 'd' }, + { "xmit", required_argument, NULL, 'x' }, + //{ "userCntrs", no_argument, NULL, 'U' }, + //{ "select", required_argument, NULL, 's' }, + //{ "imgNum", required_argument, NULL, 'n' }, + //{ "imgOff", required_argument, NULL, 'O' }, + //{ "moveImgNum", required_argument, NULL, 'm' }, + //{ "moveImgOff", required_argument, NULL, 'M' }, + //{ "focus", required_argument, NULL, 'f' }, + { "start", required_argument, NULL, 'S' }, + { "range", required_argument, NULL, 'r' }, + { "live", required_argument, NULL, 'L' }, + { "help", no_argument, NULL, '$' }, + { 0 } +}; + +static FSTATUS opa_pa_init(uint8 hfi, uint8 port) +{ + FSTATUS fstatus = FERROR; + int pa_service_state; + + // Open the port + struct omgt_params params = { + .debug_file = (g_verbose > 3 ? stderr : NULL), + .error_file = stderr + }; + fstatus = omgt_open_port_by_num(&g_portHandle, (int)hfi, port, ¶ms); + if (fstatus == OMGT_STATUS_SUCCESS) { + fstatus = omgt_port_get_pa_service_state(g_portHandle, &pa_service_state, OMGT_REFRESH_SERVICE_BAD_STATE); + if (fstatus == OMGT_STATUS_SUCCESS) { + if (pa_service_state != OMGT_SERVICE_STATE_OPERATIONAL) { + fprintf(stderr, "%s: failed to connect, PA Service State is Not Operational: %s (%d)\n", + __func__, omgt_service_state_totext(pa_service_state), pa_service_state); + fstatus = FUNAVAILABLE; + } + } else { + fprintf(stderr, "%s: failed to get and refresh pa service state: %u\n", __func__, fstatus); + } + } else { + fprintf(stderr, "%s: failed to open hfi %d, port %d: %u\n", __func__, hfi, port, fstatus); + } + + return fstatus; +} + +#if 0 +static FSTATUS GetClassPortInfo(struct omgt_port *port) +{ + FSTATUS status= FERROR; + STL_CLASS_PORT_INFO *response; + + fprintf(stderr, "Getting Class Port Info...\n"); + if ((response = omgt_pa_get_classportinfo(port)) != NULL) { + status = FSUCCESS; + PrintStlClassPortInfo(&g_dest, 0, response); + } else { + fprintf(stderr, "Failed to receive GetClassPortInfo response: %s\n", iba_pa_mad_status_msg(port)); + } + + if (response) + MemoryDeallocate(response); + return status; +} +#endif + +static FSTATUS GetPortCounters(struct omgt_port *port, STL_LID nodeLid, uint8_t portNumber, uint32_t deltaFlag, uint32_t userCntrsFlag, uint64 imageNumber, int32 imageOffset, STL_PORT_COUNTERS_DATA *pCounters) +{ + FSTATUS status= FERROR; + STL_PA_IMAGE_ID_DATA imageId = {0}; + STL_PORT_COUNTERS_DATA *response; + + if (g_verbose) + fprintf(stderr, "Getting Port Counters for Lid 0x%8.8x port %u...\n", nodeLid, portNumber); + imageId.imageNumber = imageNumber; + imageId.imageOffset = imageOffset; + if ((response = iba_pa_single_mad_port_counters_response_query(port, nodeLid, portNumber, deltaFlag, userCntrsFlag, &imageId)) != NULL) { + status = FSUCCESS; + if (g_verbose > 2) + PrintStlPAPortCounters(&g_dest, 0, response, nodeLid, (uint32)portNumber, response->flags); + *pCounters = *response; + } else { + fprintf(stderr, "Failed to receive GetPortCounters response: %s\n", iba_pa_mad_status_msg(port)); + } + + if (response) + MemoryDeallocate(response); + return status; +} + +#if 0 +static FSTATUS GetPMConfig(struct omgt_port *port) +{ + FSTATUS status= FERROR; + STL_PA_PM_CFG_DATA *response; + + fprintf(stderr, "Getting PM Configuration...\n"); + if ((response = iba_pa_single_mad_get_pm_config_response_query(port)) != NULL) { + status = FSUCCESS; + PrintStlPMConfig(&g_dest, 0, response); + } else { + fprintf(stderr, "Failed to receive GetPMConfig response: %s\n", iba_pa_mad_status_msg(port)); + } + if (response) + MemoryDeallocate(response); + return status; +} +#endif + +#if USE_FREEZE +static FSTATUS FreezeImage(struct omgt_port *port, uint64 imageNumber, int32 imageOffset, STL_PA_IMAGE_ID_DATA *pImageId) +{ + FSTATUS status= FERROR; + STL_PA_IMAGE_ID_DATA request = {0}; + STL_PA_IMAGE_ID_DATA *response; + + if (g_verbose) + fprintf(stderr, "Freezing image 0x%lx %d...\n", imageNumber, imageOffset); + request.imageNumber = imageNumber; + request.imageOffset = imageOffset; + if ((response = iba_pa_single_mad_freeze_image_response_query(port, &request)) != NULL) { + status = FSUCCESS; + if (g_verbose > 1) + PrintStlPAImageId(&g_dest, 0, response); + if (pImageId) + *pImageId = *response; + } else { + //if (port->mad_status == STL_MAD_STATUS_STL_PA_NO_IMAGE) + // status = FNOT_FOUND; + fprintf(stderr, "Failed to receive FreezeImage response: %s\n", iba_pa_mad_status_msg(port)); + } + if (response) + MemoryDeallocate(response); + return status; +} +#endif + +#if USE_FREEZE +static FSTATUS ReleaseImage(struct omgt_port *port, uint64 imageNumber, int32 imageOffset) +{ + FSTATUS status= FERROR; + STL_PA_IMAGE_ID_DATA request = {0}; + STL_PA_IMAGE_ID_DATA *response; + + if (g_verbose) + fprintf(stderr, "Releaseing image 0x%lx %d...\n", imageNumber, imageOffset); + request.imageNumber = imageNumber; + request.imageOffset = imageOffset; + if ((response = iba_pa_single_mad_release_image_response_query(port, &request)) != NULL) { + status = FSUCCESS; + if (g_verbose > 1) + PrintStlPAImageId(&g_dest, 0, response); + } else { + fprintf(stderr, "Failed to receive ReleaseImage response: %s\n", iba_pa_mad_status_msg(port)); + } + if (response) + MemoryDeallocate(response); + return status; +} +#endif + +#if 0 +static FSTATUS RenewImage(struct omgt_port *port, uint64 imageNumber, int32 imageOffset) +{ + FSTATUS status= FERROR; + STL_PA_IMAGE_ID_DATA request = {0}; + STL_PA_IMAGE_ID_DATA *response; + + fprintf(stderr, "Renewing image...\n"); + request.imageNumber = imageNumber; + request.imageOffset = imageOffset; + if ((response = iba_pa_single_mad_renew_image_response_query(port, &request)) != NULL) { + status = FSUCCESS; + PrintStlPAImageId(&g_dest, 0, response); + } else { + fprintf(stderr, "Failed to receive RenewImage response: %s\n", iba_pa_mad_status_msg(port)); + } + if (response) + MemoryDeallocate(response); + return status; +} +#endif + +#if USE_FREEZE +static FSTATUS MoveFreeze(struct omgt_port *port, uint64 imageNumber, int32 imageOffset, uint64 moveImageNumber, int32 moveImageOffset, STL_PA_IMAGE_ID_DATA *pImageId) +{ + FSTATUS status= FERROR; + STL_MOVE_FREEZE_DATA request; + STL_MOVE_FREEZE_DATA *response; + + if (g_verbose) + fprintf(stderr, "Moving freeze image 0x%lx %d to 0x%lx %d...\n", imageNumber, imageOffset, moveImageNumber, moveImageOffset); + request.oldFreezeImage.imageNumber = imageNumber; + request.oldFreezeImage.imageOffset = imageOffset; + request.newFreezeImage.imageNumber = moveImageNumber; + request.newFreezeImage.imageOffset = moveImageOffset; + if ((response = iba_pa_single_mad_move_freeze_response_query(port, &request)) != NULL) { + status = FSUCCESS; + if (g_verbose > 1) + PrintStlPAMoveFreeze(&g_dest, 0, response); + if (pImageId) + *pImageId = response->newFreezeImage; + } else { + if (omgt_get_pa_mad_status(port) == STL_MAD_STATUS_STL_PA_NO_IMAGE) + status = FNOT_FOUND; + else + fprintf(stderr, "Failed to receive MoveFreeze response: %s\n", iba_pa_mad_status_msg(port)); + } + if (response) + MemoryDeallocate(response); + return status; +} +#endif + +static FSTATUS GetGroupList(struct omgt_port *port, char groupName[STL_PM_GROUPNAMELEN]) +{ + OMGT_QUERY query; + FSTATUS status; + PQUERY_RESULT_VALUES pQueryResults = NULL; + + memset(&query, 0, sizeof(query)); // initialize reserved fields + query.InputType = InputTypeNoInput; + query.OutputType = OutputTypePaTableRecord; + + if (g_verbose) + fprintf(stderr, "Getting Group List...\n"); + if (g_verbose) + printf("Query: Input=%s, Output=%s\n", + iba_sd_query_input_type_msg(query.InputType), + iba_sd_query_result_type_msg(query.OutputType)); + + // this call is synchronous + status = iba_pa_multi_mad_group_list_response_query(port, &query, &pQueryResults); + + if (! pQueryResults) + { + fprintf(stderr, "%*sPA GroupList query Failed: %s (%s) \n", 0, "", iba_fstatus_msg(status), iba_pa_mad_status_msg(port)); + goto fail; + } else if (pQueryResults->Status != FSUCCESS) { + fprintf(stderr, "%*sPA GroupList query Failed: %s MadStatus 0x%x: %s\n", 0, "", + iba_fstatus_msg(pQueryResults->Status), + pQueryResults->MadStatus, iba_sd_mad_status_msg(pQueryResults->MadStatus)); + goto fail; + } else if (pQueryResults->ResultDataSize == 0) { + fprintf(stderr, "%*sNo Group List Records Returned\n", 0, ""); + } else { + STL_PA_GROUP_LIST_RESULTS *p = (STL_PA_GROUP_LIST_RESULTS*)pQueryResults->QueryResult; + + if (g_verbose) { + fprintf(stderr, "MadStatus 0x%x: %s\n", pQueryResults->MadStatus, + iba_sd_mad_status_msg(pQueryResults->MadStatus)); + fprintf(stderr, "%d Bytes Returned\n", pQueryResults->ResultDataSize); + fprintf(stderr, "PA Multiple MAD Response for Group Data:\n"); + } + + if (g_verbose > 1) + PrintStlPAGroupList(&g_dest, 1, p->NumGroupListRecords, p->GroupListRecords); + // return 1st group name in list + memcpy(groupName, p->GroupListRecords[0].groupName, STL_PM_GROUPNAMELEN); + } + + status = FSUCCESS; + +done: + // iba_sd_query_port_fabric_info will have allocated a result buffer + // we must free the buffer when we are done with it + if (pQueryResults) + omgt_free_query_result_buffer(pQueryResults); + return status; + +fail: + status = FERROR; + goto done; +} + +#if 0 +static FSTATUS GetGroupInfo(struct omgt_port *port, char *groupName, uint64 imageNumber, int32 imageOffset) +{ + OMGT_QUERY query; + FSTATUS status; + PQUERY_RESULT_VALUES pQueryResults = NULL; + STL_PA_IMAGE_ID_DATA imageId = {0}; + + memset(&query, 0, sizeof(query)); // initialize reserved fields + query.InputType = InputTypeNoInput; + query.OutputType = OutputTypePaTableRecord; + + fprintf(stderr, "Getting Group Info...\n"); + imageId.imageNumber = imageNumber; + imageId.imageOffset = imageOffset; + if (g_verbose) + printf("Query: Input=%s, Output=%s\n", + iba_sd_query_input_type_msg(query.InputType), + iba_sd_query_result_type_msg(query.OutputType)); + + // this call is synchronous + status = iba_pa_multi_mad_group_stats_response_query(port, &query, groupName, &pQueryResults, &imageId); + + if (! pQueryResults) + { + fprintf(stderr, "%*sPA Group Info query Failed: %s (%s)\n", 0, "", iba_fstatus_msg(status), iba_pa_mad_status_msg(port)); + goto fail; + } else if (pQueryResults->Status != FSUCCESS) { + fprintf(stderr, "%*sPA Group Info query Failed: %s MadStatus 0x%x: %s\n", 0, "", + iba_fstatus_msg(pQueryResults->Status), + pQueryResults->MadStatus, iba_sd_mad_status_msg(pQueryResults->MadStatus)); + goto fail; + } else if (pQueryResults->ResultDataSize == 0) { + fprintf(stderr, "%*sNo Group Info Records Returned\n", 0, ""); + } else { + STL_PA_GROUP_INFO_RESULTS *p = (STL_PA_GROUP_INFO_RESULTS*)pQueryResults->QueryResult; + + if (g_verbose) { + fprintf(stderr, "MadStatus 0x%x: %s\n", pQueryResults->MadStatus, + iba_sd_mad_status_msg(pQueryResults->MadStatus)); + fprintf(stderr, "%d Bytes Returned\n", pQueryResults->ResultDataSize); + fprintf(stderr, "PA Multiple MAD Response for Group Info group name %s:\n", groupName); + } + + PrintStlPAGroupInfo(&g_dest, 1, p->GroupInfoRecords); + } + + status = FSUCCESS; + +done: + // iba_sd_query_port_fabric_info will have allocated a result buffer + // we must free the buffer when we are done with it + if (pQueryResults) + omgt_free_query_result_buffer(pQueryResults); + return status; + +fail: + status = FERROR; + goto done; +} +#endif + +static void OutputHeading() +{ + int i; + + printf("time"); + for (i=0; i < ArrayGetSize(&g_Columns); i++) { + ColumnEntry_t *q = (ColumnEntry_t*)ArrayGetPtr(&g_Columns, i); + printf(",%.*s:%u", + (int)(unsigned)sizeof(q->nodeDesc), q->nodeDesc, + q->portNumber); + } + printf("\n"); +} + +boolean ColumnCompare(uint32 index, void* const elem, void *const context) +{ + ColumnEntry_t * const p = (ColumnEntry_t* const)elem; + ColumnEntry_t * const q = (ColumnEntry_t* const)context; + return (p->nodeGUID == q->nodeGUID && p->portNumber == q->portNumber); +} + +static FSTATUS GetAndPrintGroupConfig(struct omgt_port *port, char *groupName, + uint64 imageNumber, int32 imageOffset, + STL_PA_IMAGE_INFO_DATA *pImageInfo) +{ + OMGT_QUERY query; + STL_PA_IMAGE_ID_DATA imageId = {0}; + FSTATUS status; + PQUERY_RESULT_VALUES pQueryResults = NULL; + // do we need to output heading line + int heading = (ArrayGetSize(&g_Columns) == 0); + char timestr[81]; + int i; + STL_PA_PM_GROUP_CFG_RSP *q; + uint32 index = 0; + int bad = 0; +#if COMPUTE_DELTA + int printValues = (! heading || ! g_deltaFlag); +#else + int printValues = 1; +#endif + + memset(&query, 0, sizeof(query)); // initialize reserved fields + query.InputType = InputTypeNoInput; + query.OutputType = OutputTypePaTableRecord; + + if (g_verbose) + fprintf(stderr, "Getting Group Config...\n"); + imageId.imageNumber = imageNumber; + imageId.imageOffset = imageOffset; + if (g_verbose) + printf("Query: Input=%s, Output=%s\n", + iba_sd_query_input_type_msg(query.InputType), + iba_sd_query_result_type_msg(query.OutputType)); + + // this call is synchronous + status = iba_pa_multi_mad_group_config_response_query(port, &query, groupName, &pQueryResults, &imageId); + + if (! pQueryResults) + { + fprintf(stderr, "%*sPA Group Config query Failed: %s (%s)\n", 0, "", iba_fstatus_msg(status), iba_pa_mad_status_msg(port)); + goto fail; + } else if (pQueryResults->Status != FSUCCESS) { + fprintf(stderr, "%*sPA Group Config query Failed: %s MadStatus 0x%x: %s\n", 0, "", + iba_fstatus_msg(pQueryResults->Status), + pQueryResults->MadStatus, iba_sd_mad_status_msg(pQueryResults->MadStatus)); + goto fail; + } else if (pQueryResults->ResultDataSize == 0) { + fprintf(stderr, "%*sNo Group Config Records Returned\n", 0, ""); + } else { + STL_PA_GROUP_CONFIG_RESULTS *p = (STL_PA_GROUP_CONFIG_RESULTS*)pQueryResults->QueryResult; + + if (g_verbose) { + fprintf(stderr, "MadStatus 0x%x: %s\n", pQueryResults->MadStatus, + iba_sd_mad_status_msg(pQueryResults->MadStatus)); + fprintf(stderr, "%d Bytes Returned\n", pQueryResults->ResultDataSize); + fprintf(stderr, "PA Multiple MAD Response for Group Config group name %s:\n", groupName); + } + + if (g_verbose > 2) + PrintStlPAGroupConfig(&g_dest, 1, groupName, p->NumGroupConfigRecords, p->GroupConfigRecords); + if (g_verbose) +#if COMPUTE_DELTA + fprintf(stderr, "Processing Records at %s", ctime((time_t *)&pImageInfo->sweepStart)); +#else + fprintf(stderr, "Processing Records for %u sec at %s", pImageInfo->imageInterval, ctime((time_t *)&pImageInfo->sweepStart)); +#endif + + // GroupConfig is unsorted in discovery order, must search and insert + for (i=0, q = p->GroupConfigRecords; i< p->NumGroupConfigRecords; i++,q++) { + ColumnEntry_t entry; + if (g_gotLid && q->nodeLid != g_nodeLid) + continue; + if (g_gotGUID && q->nodeGUID != g_nodeGUID) + continue; + if (g_gotDesc && 0 != strncmp(g_nodeDesc,q->nodeDesc, sizeof(g_nodeDesc)) ) + continue; + if (g_gotPort && q->portNumber != g_portNumber) + continue; + // ColumnCompare only uses GUID and portNumber + entry.nodeGUID = q->nodeGUID; + entry.portNumber = q->portNumber; + // the ConfigRecords will tend to be in the same order from image + // to image so to speed things up start close to where we + // expect to see it + index = ArrayFindFromIndex(&g_Columns, ColumnCompare, &entry, index); + if (index < ArrayGetSize(&g_Columns)) { + // found, refresh nodeLid in case it changed + ((ColumnEntry_t*)ArrayGetPtr(&g_Columns, index))->nodeLid = q->nodeLid; + } else { + // not found, will add at end. + memcpy(entry.nodeDesc, q->nodeDesc, sizeof(entry.nodeDesc)); + entry.nodeLid = q->nodeLid; +#if COMPUTE_DELTA + // save to keep code simple, but unused if ! g_deltaFlag + entry.recentValueValid = FALSE; + entry.recentValue = 0; +#endif + ArraySet(&g_Columns, index, &entry, IBA_MEM_FLAG_NONE, NULL); + } + } + if (heading) + OutputHeading(); + if (printValues) { + snprintf(timestr, sizeof(timestr), "%s", ctime((time_t *)&pImageInfo->sweepStart)); + // replace '\n' character with '\0' + timestr[strlen(timestr) - 1] = 0; +#if COMPUTE_DELTA + printf("%s", timestr); +#else + printf("%s for %u sec", timestr, pImageInfo->imageInterval); +#endif + } + + for (i=0; i < ArrayGetSize(&g_Columns); i++) { + ColumnEntry_t *e = (ColumnEntry_t*)ArrayGetPtr(&g_Columns, i); + STL_PORT_COUNTERS_DATA Counters; + + if (FSUCCESS != GetPortCounters(port, e->nodeLid, e->portNumber, +#if COMPUTE_DELTA + 0, +#else + g_deltaFlag, +#endif + 0, imageNumber, imageOffset, &Counters)) { + // assume port is down during this image + if (printValues) + printf(","); + //status = FERROR; + //goto done; +#if COMPUTE_DELTA + // save to keep code simple, but unused if ! g_deltaFlag + e->recentValueValid = FALSE; +#endif + } else { + uint64 value; + if (g_gotXmit) + value = Counters.portXmitPkts; + else + value = Counters.localLinkIntegrityErrors; +#if COMPUTE_DELTA + if (g_deltaFlag) { + if (e->recentValueValid) { + if (g_gotLive) { + if (g_gotXmit) { + if (printValues) + printf(",%lu", value - e->recentValue); + if (value < e->recentValue) + bad=1; + } else { + // LocalLinkIntegrity is cleared on port bounce + // absolute value can go backwards + if (printValues) { + if (value < e->recentValue) { + printf(",%lu", value); + } else { + printf(",%lu", value - e->recentValue); + } + } + } + } else { + if (g_gotXmit) { + if (printValues) + printf(",%lu", e->recentValue - value); + if (e->recentValue < value) + bad=1; + } else { + // LocalLinkIntegrity is cleared on port bounce + // absolute value can go backwards + if (printValues) { + if (e->recentValue < value) { + printf(",%lu", value); + } else { + printf(",%lu", e->recentValue - value); + } + } + } + } + } else { + if (printValues) + printf(","); + } + } else { + if (printValues) + printf(",%lu", value); + } + // save to keep code simple, but unused if ! g_deltaFlag + e->recentValueValid = TRUE; + e->recentValue = value; +#else + if (printValues) + printf(",%lu", value); + if (g_deltaFlag && value > 18000000000000000000ULL) + bad=1; +#endif + } + } + if (printValues) + printf("\n"); + if (bad) { + fprintf(stderr, "Unexpected negative counter: imageNumber=%lu, offset=%d\n", imageNumber, imageOffset); + //exit(1); + } + } + + status = FSUCCESS; + +done: + // iba_sd_query_port_fabric_info will have allocated a result buffer + // we must free the buffer when we are done with it + if (pQueryResults) + omgt_free_query_result_buffer(pQueryResults); + return status; + +fail: + status = FERROR; + goto done; +} + +#if 0 +static void PrintFocusPorts(uint32 select, + STL_PA_IMAGE_INFO_DATA *pImageInfo, + STL_FOCUS_PORTS_RSP *pFocusPort, + STL_PORT_COUNTERS_DATA *pCounters, + STL_PORT_COUNTERS_DATA *pNeighborCounters) +{ + char timestr[81]; + int reverse = 0; + STL_PORT_COUNTERS_DATA *temp; + + snprintf(timestr, sizeof(timestr), "%s", ctime((time_t *)&pImageInfo->sweepStart)); + // replace '\n' character with '\0' + timestr[strlen(timestr) - 1] = 0; + // TBD - pCounters vs pNeighborCounters will be in order of larger value, we want in a predictable order so can sort or filter on a single column to see all info for a given device + if (pNeighborCounters && + (pFocusPort->nodeGUID > pFocusPort->neighborGuid + || (pFocusPort->nodeGUID == pFocusPort->neighborGuid + && pFocusPort->portNumber > pFocusPort->neighborPortNumber))) + reverse = 1; + + // HEADING: timestamp;rate;nodeDesc;port + // TBD - include GUIDs? + if (reverse) { + printf("%s for %u sec;%4s;%.*s;%u;", timestr, pImageInfo->imageInterval, + StlStaticRateToText(pFocusPort->rate), + (int)(unsigned)sizeof(pFocusPort->neighborNodeDesc), pFocusPort->neighborNodeDesc, + pFocusPort->neighborPortNumber); + temp = pCounters; pCounters=pNeighborCounters;pNeighborCounters=temp; + }else { + printf("%s for %u sec;%4s;%.*s;%u;", timestr, pImageInfo->imageInterval, + StlStaticRateToText(pFocusPort->rate), + (int)(unsigned)sizeof(pFocusPort->nodeDesc), pFocusPort->nodeDesc, + pFocusPort->portNumber); + } + + + switch (select) { + case STL_PA_SELECT_CATEGORY_INTEG: + // HEADING: LinkQualityIndicator;UncorectableErrors;LinkDowned;NumLanesDown;RcvErrors;ExcessiveBufferOverruns;FMConfigErrors;LinkErrorRecovery;LocalLinkIntegrity + printf("%u;%u;%u;%u;%lu;%lu;%lu;%u;%lu", + pCounters->lq.s.linkQualityIndicator, + pCounters->uncorrectableErrors, + pCounters->linkDowned, + pCounters->lq.s.numLanesDown, + pCounters->portRcvErrors, + pCounters->excessiveBufferOverruns, + pCounters->fmConfigErrors, + pCounters->linkErrorRecovery, + pCounters->localLinkIntegrityErrors); + + if (pNeighborCounters) { + // HEADING: nodeDesc;port + if (reverse) { + printf(";%.*s;%u;", + (int)(unsigned)sizeof(pFocusPort->nodeDesc), pFocusPort->nodeDesc, + pFocusPort->portNumber); + } else { + printf(";%.*s;%u;", + (int)(unsigned)sizeof(pFocusPort->neighborNodeDesc), pFocusPort->neighborNodeDesc, + // HEADING: LinkQualityIndicator;UncorectableErrors;LinkDowned;NumLanesDown;RcvErrors;ExcessiveBufferOverruns;FMConfigErrors;LinkErrorRecovery;LocalLinkIntegrity + pFocusPort->neighborPortNumber); + } + printf("%u;%u;%u;%u;%lu;%lu;%lu;%u;%lu", + pNeighborCounters->lq.s.linkQualityIndicator, + pNeighborCounters->uncorrectableErrors, + pNeighborCounters->linkDowned, + pNeighborCounters->lq.s.numLanesDown, + pNeighborCounters->portRcvErrors, + pNeighborCounters->excessiveBufferOverruns, + pNeighborCounters->fmConfigErrors, + pNeighborCounters->linkErrorRecovery, + pNeighborCounters->localLinkIntegrityErrors); + } + printf("\n"); + break; + default: + printf("\n"); + break; + } +} +#endif +#if 0 + PrintFunc(dest, "%*s%u:LID:0x%08x Port:%u Rate: %4s MTU: %5s nbrLID:0x%08x nbrPort:%u\n", + indent, "", i+1, pFocusPorts[i].nodeLid, pFocusPorts[i].portNumber, + StlStaticRateToText(pFocusPorts[i].rate), IbMTUToText(pFocusPorts[i].mtu), + pFocusPorts[i].neighborLid, pFocusPorts[i].neighborPortNumber); + PrintFunc(dest, "%*s Value: %16"PRIu64" nbrValue: %16"PRIu64"\n", + indent, "", pFocusPorts[i].value, pFocusPorts[i].neighborValue); + PrintFunc(dest, "%*s GUID: 0x%016"PRIx64" nbrGuid: 0x%016"PRIx64"\n", + indent, "", pFocusPorts[i].nodeGUID, pFocusPorts[i].neighborGuid); + PrintFunc(dest, "%*s Status: %s Name: %.*s\n", indent, "", + StlFocusFlagToText(pFocusPorts[i].localFlags), + sizeof(pFocusPorts[i].nodeDesc), pFocusPorts[i].nodeDesc); + PrintFunc(dest, "%*s Status: %s Neighbor Name: %.*s\n", indent, "", + StlFocusFlagToText(pFocusPorts[i].neighborFlags), + sizeof(pFocusPorts[i].neighborNodeDesc), pFocusPorts[i].neighborNodeDesc); + PrintStlPAImageId(dest, indent, &pFocusPorts[0].imageId); + + + PrintFunc(dest, "%*s%s controlled Port Counters (%s) for LID 0x%08x, port number %u%s:\n", + indent, "", (flags & STL_PA_PC_FLAG_USER_COUNTERS) ? "User" : "PM", + (flags & STL_PA_PC_FLAG_DELTA) ? "delta" : "total", + nodeLid, portNumber, + (flags&STL_PA_PC_FLAG_UNEXPECTED_CLEAR)?" (Unexpected Clear)":""); + PrintFunc(dest, "%*sPerformance: Transmit\n", indent, ""); + PrintFunc(dest, "%*s Xmit Data %20"PRIu64" MB (%"PRIu64" Flits)\n", + indent, "", + pPortCounters->portXmitData/FLITS_PER_MB, + pPortCounters->portXmitData); + PrintFunc(dest, "%*s Xmit Pkts %20"PRIu64"\n", + indent, "", + pPortCounters->portXmitPkts); + PrintFunc(dest, "%*s MC Xmit Pkts %20"PRIu64"\n", + indent, "", + pPortCounters->portMulticastXmitPkts); + PrintFunc(dest, "%*sPerformance: Receive\n", + indent, ""); + PrintFunc(dest, "%*s Rcv Data %20"PRIu64" MB (%"PRIu64" Flits)\n", + indent, "", + pPortCounters->portRcvData/FLITS_PER_MB, + pPortCounters->portRcvData); + PrintFunc(dest, "%*s Rcv Pkts %20"PRIu64"\n", + indent, "", + pPortCounters->portRcvPkts); + PrintFunc(dest, "%*s MC Rcv Pkts %20"PRIu64"\n", + indent, "", + pPortCounters->portMulticastRcvPkts); + PrintFunc(dest, "%*sSignal Integrity Errors: \n", + indent, ""); + PrintFunc(dest, "%*s Link Quality Ind %10u\n", + indent, "", + pPortCounters->lq.s.linkQualityIndicator); + PrintFunc(dest, "%*s Uncorrectable Err %10u\n", + indent, "", + pPortCounters->uncorrectableErrors); + PrintFunc(dest, "%*s Link Downed %10u\n", + indent, "", + pPortCounters->linkDowned); + PrintFunc(dest, "%*s Num Lanes Down %10u\n", + indent, "", + pPortCounters->lq.s.numLanesDown); + PrintFunc(dest, "%*s Rcv Errors %10u\n", + indent, "", + pPortCounters->portRcvErrors); + PrintFunc(dest, "%*s Exc. Buffer Overrun %10u\n", + indent, "", + pPortCounters->excessiveBufferOverruns); + PrintFunc(dest, "%*s FM Config %10u\n", + indent, "", + pPortCounters->fmConfigErrors); + PrintFunc(dest, "%*s Link Error Recovery %10u\n", + indent, "", + pPortCounters->linkErrorRecovery); + PrintFunc(dest, "%*s Local Link Integrity %10u\n", + indent, "", + pPortCounters->localLinkIntegrityErrors); + PrintFunc(dest, "%*s Rcv Rmt Phys Err %10u\n", + indent, "", + pPortCounters->portRcvRemotePhysicalErrors); + PrintFunc(dest, "%*sSecurity Errors: \n", + indent, ""); + PrintFunc(dest, "%*s Xmit Constraint %10u\n", + indent, "", + pPortCounters->portXmitConstraintErrors); + PrintFunc(dest, "%*s Rcv Constraint %10u\n", + indent, "", + pPortCounters->portRcvConstraintErrors); + PrintFunc(dest, "%*sRouting and Other Errors: \n", + indent, ""); + PrintFunc(dest, "%*s Rcv Sw Relay Err %10u\n", + indent, "", + pPortCounters->portRcvSwitchRelayErrors); + PrintFunc(dest, "%*s Xmit Discards %10u\n", + indent, "", + pPortCounters->portXmitDiscards); + PrintFunc(dest, "%*sCongestion: \n", + indent, ""); + PrintFunc(dest, "%*s Cong Discards %10u\n", + indent, "", + pPortCounters->swPortCongestion); + PrintFunc(dest, "%*s Rcv FECN %10u\n", + indent, "", + pPortCounters->portRcvFECN); + PrintFunc(dest, "%*s Rcv BECN %10u\n", + indent, "", + pPortCounters->portRcvBECN); + PrintFunc(dest, "%*s Mark FECN %10u\n", + indent, "", + pPortCounters->portMarkFECN); + PrintFunc(dest, "%*s Xmit Time Cong %10u\n", + indent, "", + pPortCounters->portXmitTimeCong); + PrintFunc(dest, "%*s Xmit Wait %10u\n", + indent, "", + pPortCounters->portXmitWait); + PrintFunc(dest, "%*sBubbles: \n", + indent, ""); + PrintFunc(dest, "%*s Xmit Wasted BW %10u\n", + indent, "", + pPortCounters->portXmitWastedBW); + PrintFunc(dest, "%*s Xmit Wait Data %10u\n", + indent, "", + pPortCounters->portXmitWaitData); + PrintFunc(dest, "%*s Rcv Bubble %10u\n", + indent, "", + pPortCounters->portRcvBubble); + PrintStlPAImageId(dest, indent+2, &pPortCounters->imageId); +#endif + +#if 0 +static FSTATUS GetAndPrintFocusPorts(struct omgt_port *port, char *groupName, uint32 select, uint32 start, uint32 range, uint64 imageNumber, int32 imageOffset, STL_PA_IMAGE_INFO_DATA *pImageInfo) +{ + OMGT_QUERY query; + STL_PA_IMAGE_ID_DATA imageId = {0}; + FSTATUS status; + PQUERY_RESULT_VALUES pQueryResults = NULL; + + memset(&query, 0, sizeof(query)); // initialize reserved fields + query.InputType = InputTypeNoInput; + query.OutputType = OutputTypePaTableRecord; + + if (g_verbose) + fprintf(stderr, "Getting Focus Ports...\n"); + imageId.imageNumber = imageNumber; + imageId.imageOffset = imageOffset; + if (g_verbose) + fprintf(stderr, "Query: Input=%s, Output=%s\n", + iba_sd_query_input_type_msg(query.InputType), + iba_sd_query_result_type_msg(query.OutputType)); + + // this call is synchronous + // TBD - fails with insufficient resources in PA if range is maxint. What is the limit? Do we need to do a groupconfig query instead? Then how do we get the neighbor information? + status = iba_pa_multi_mad_focus_ports_response_query(port, &query, groupName, select, start, MIN(range, pImageInfo->numSwitchPorts+pImageInfo->numHFIPorts), &pQueryResults, &imageId); + + if (! pQueryResults) + { + fprintf(stderr, "%*sPA Focus Ports query Failed: %s (%s)\n", 0, "", iba_fstatus_msg(status), iba_pa_mad_status_msg(port)); + goto fail; + } else if (pQueryResults->Status != FSUCCESS) { + fprintf(stderr, "%*sPA Focus Ports query Failed: %s MadStatus 0x%x: %s\n", 0, "", + iba_fstatus_msg(pQueryResults->Status), + pQueryResults->MadStatus, iba_sd_mad_status_msg(pQueryResults->MadStatus)); + goto fail; + } else if (pQueryResults->ResultDataSize == 0) { + fprintf(stderr, "%*sNo Focus Ports Records Returned\n", 0, ""); + } else { + STL_PA_FOCUS_PORTS_RESULTS *p = (STL_PA_FOCUS_PORTS_RESULTS*)pQueryResults->QueryResult; + int i; + STL_FOCUS_PORTS_RSP *q; + + if (g_verbose) { + fprintf(stderr, "MadStatus 0x%x: %s\n", pQueryResults->MadStatus, + iba_sd_mad_status_msg(pQueryResults->MadStatus)); + fprintf(stderr, "%d Bytes Returned\n", pQueryResults->ResultDataSize); + fprintf(stderr, "PA Multiple MAD Response for Focus Ports group name %s:\n", groupName); + } + + if (g_verbose > 2) + PrintStlPAFocusPorts(&g_dest, 1, groupName, p->NumFocusPortsRecords, select, start, range, p->FocusPortsRecords); + if (g_verbose) +#if COMPUTE_DELTA + fprintf(stderr, "%s", ctime((time_t *)&pImageInfo->sweepStart)); +#else + fprintf(stderr, "%s for %u sec", ctime((time_t *)&pImageInfo->sweepStart), pImageInfo->imageInterval); +#endif + for (i=0, q = p->FocusPortsRecords; i< p->NumFocusPortsRecords; i++,q++) { + STL_PORT_COUNTERS_DATA Counters; + STL_PORT_COUNTERS_DATA neighborCounters; + + // TBDif (q->value == 0 && q->neighborValue == 0) + // continue; // TBD or break + if (FSUCCESS != GetPortCounters(port, q->nodeLid, q->portNumber, 1, 0, imageNumber, imageOffset, &Counters)) { + status = FERROR; + goto done; + } + if (q->neighborLid) { // has a neighbor + if (FSUCCESS != GetPortCounters(port, q->neighborLid, q->neighborPortNumber, 1, 0, imageNumber, imageOffset, &neighborCounters)) { + status = FERROR; + goto done; + } + } + PrintFocusPorts(select, pImageInfo, q, &Counters, + q->neighborLid?&neighborCounters:NULL); + } + } + + status = FSUCCESS; + +done: + // iba_sd_query_port_fabric_info will have allocated a result buffer + // we must free the buffer when we are done with it + if (pQueryResults) + omgt_free_query_result_buffer(pQueryResults); + return status; + +fail: + status = FERROR; + goto done; +} +#endif + +static FSTATUS GetImageInfo(struct omgt_port *port, uint64 imageNumber, int32 imageOffset, STL_PA_IMAGE_INFO_DATA* pImageInfo) +{ + FSTATUS status= FERROR; + STL_PA_IMAGE_INFO_DATA request = {{0}}; + STL_PA_IMAGE_INFO_DATA *response;; + + if (g_verbose) + fprintf(stderr, "Getting image info... 0x%lx %d\n", imageNumber, imageOffset); + request.imageId.imageNumber = imageNumber; + request.imageId.imageOffset = imageOffset; + if ((response = iba_pa_multi_mad_get_image_info_response_query(port, &request)) != NULL) { + status = FSUCCESS; + *pImageInfo = *response; + if (g_verbose > 1) + PrintStlPAImageInfo(&g_dest, 0, response); + } else { + fprintf(stderr, "Failed to receive GetImageInfo response: %s\n", iba_pa_mad_status_msg(port)); + if (omgt_get_pa_mad_status(port) == STL_MAD_STATUS_STL_PA_NO_IMAGE) + status = FNOT_FOUND; + } + if (response) + MemoryDeallocate(response); + return status; +} + +#if 0 +static FSTATUS GetVFList(struct omgt_port *port) +{ + OMGT_QUERY query; + FSTATUS status; + PQUERY_RESULT_VALUES pQueryResults = NULL; + + memset(&query, 0, sizeof(query)); // initialize reserved fields + query.InputType = InputTypeNoInput; + query.OutputType = OutputTypePaTableRecord; + + fprintf(stderr, "Getting VF List...\n"); + if (g_verbose) + printf("Query: Input=%s, Output=%s\n", + iba_sd_query_input_type_msg(query.InputType), + iba_sd_query_result_type_msg(query.OutputType)); + + // this call is synchronous + status = iba_pa_multi_mad_vf_list_response_query(port, &query, &pQueryResults); + + if (! pQueryResults) + { + fprintf(stderr, "%*sPA vfList query Failed: %s (%s) \n", 0, "", iba_fstatus_msg(status), iba_pa_mad_status_msg(port)); + goto fail; + } else if (pQueryResults->Status != FSUCCESS) { + fprintf(stderr, "%*sPA vfList query Failed: %s MadStatus 0x%x: %s\n", 0, "", + iba_fstatus_msg(pQueryResults->Status), + pQueryResults->MadStatus, iba_sd_mad_status_msg(pQueryResults->MadStatus)); + goto fail; + } else if (pQueryResults->ResultDataSize == 0) { + fprintf(stderr, "%*sNo VF List Records Returned\n", 0, ""); + } else { + STL_PA_VF_LIST_RESULTS *p = (STL_PA_VF_LIST_RESULTS *)pQueryResults->QueryResult; + + if (g_verbose) { + fprintf(stderr, "MadStatus 0x%x: %s\n", pQueryResults->MadStatus, + iba_sd_mad_status_msg(pQueryResults->MadStatus)); + fprintf(stderr, "%d Bytes Returned\n", pQueryResults->ResultDataSize); + fprintf(stderr, "PA Multiple MAD Response for VF list data:\n"); + } + + PrintStlPAVFList(&g_dest, 1, p->NumVFListRecords, p->VFListRecords); + } + + status = FSUCCESS; + +done: + // iba_sd_query_port_fabric_info will have allocated a result buffer + // we must free the buffer when we are done with it + if (pQueryResults) + omgt_free_query_result_buffer(pQueryResults); + return status; + +fail: + status = FERROR; + goto done; +} +#endif + +#if 0 +static FSTATUS GetVFInfo(struct omgt_port *port, char *vfName, uint64 imageNumber, int32 imageOffset) +{ + OMGT_QUERY query; + FSTATUS status; + PQUERY_RESULT_VALUES pQueryResults = NULL; + STL_PA_IMAGE_ID_DATA imageId = {0}; + + memset(&query, 0, sizeof(query)); // initialize reserved fields + query.InputType = InputTypeNoInput; + query.OutputType = OutputTypePaTableRecord; + + fprintf(stderr, "Getting VF Info...\n"); + imageId.imageNumber = imageNumber; + imageId.imageOffset = imageOffset; + if (g_verbose) + printf("Query: Input=%s, Output=%s\n", + iba_sd_query_input_type_msg(query.InputType), + iba_sd_query_result_type_msg(query.OutputType)); + + // this call is synchronous + status = iba_pa_multi_mad_vf_info_response_query(port, &query, vfName, &pQueryResults, &imageId); + + if (! pQueryResults) + { + fprintf(stderr, "%*sPA VF Info query Failed: %s (%s)\n", 0, "", iba_fstatus_msg(status), iba_pa_mad_status_msg(port)); + goto fail; + } else if (pQueryResults->Status != FSUCCESS) { + fprintf(stderr, "%*sPA VF Info query Failed: %s MadStatus 0x%x: %s\n", 0, "", + iba_fstatus_msg(pQueryResults->Status), + pQueryResults->MadStatus, iba_sd_mad_status_msg(pQueryResults->MadStatus)); + goto fail; + } else if (pQueryResults->ResultDataSize == 0) { + fprintf(stderr, "%*sNo VF Info Records Returned\n", 0, ""); + } else { + STL_PA_VF_INFO_RESULTS *p = (STL_PA_VF_INFO_RESULTS*)pQueryResults->QueryResult; + + if (g_verbose) { + fprintf(stderr, "MadStatus 0x%x: %s\n", pQueryResults->MadStatus, + iba_sd_mad_status_msg(pQueryResults->MadStatus)); + fprintf(stderr, "%d Bytes Returned\n", pQueryResults->ResultDataSize); + fprintf(stderr, "PA Multiple MAD Response for VF Info VF name %s:\n", vfName); + } + + PrintStlPAVFInfo(&g_dest, 1, p->VFInfoRecords); + } + + status = FSUCCESS; + +done: + // iba_sd_query_port_fabric_info will have allocated a result buffer + // we must free the buffer when we are done with it + if (pQueryResults) + omgt_free_query_result_buffer(pQueryResults); + return status; + +fail: + status = FERROR; + goto done; +} +#endif + +#if 0 +static FSTATUS GetVFConfig(struct omgt_port *port, char *vfName, uint64 imageNumber, int32 imageOffset) +{ + OMGT_QUERY query; + STL_PA_IMAGE_ID_DATA imageId = {0}; + FSTATUS status; + PQUERY_RESULT_VALUES pQueryResults = NULL; + + memset(&query, 0, sizeof(query)); // initialize reserved fields + query.InputType = InputTypeNoInput; + query.OutputType = OutputTypePaTableRecord; + + fprintf(stderr, "Getting VF Config...\n"); + imageId.imageNumber = imageNumber; + imageId.imageOffset = imageOffset; + if (g_verbose) + printf("Query: Input=%s, Output=%s\n", + iba_sd_query_input_type_msg(query.InputType), + iba_sd_query_result_type_msg(query.OutputType)); + + // this call is synchronous + status = iba_pa_multi_mad_vf_config_response_query(port, &query, vfName, &pQueryResults, &imageId); + + if (! pQueryResults) + { + fprintf(stderr, "%*sPA VF Config query Failed: %s (%s)\n", 0, "", iba_fstatus_msg(status), iba_pa_mad_status_msg(port)); + goto fail; + } else if (pQueryResults->Status != FSUCCESS) { + fprintf(stderr, "%*sPA VF Config query Failed: %s MadStatus 0x%x: %s\n", 0, "", + iba_fstatus_msg(pQueryResults->Status), + pQueryResults->MadStatus, iba_sd_mad_status_msg(pQueryResults->MadStatus)); + goto fail; + } else if (pQueryResults->ResultDataSize == 0) { + fprintf(stderr, "%*sNo VF Config Records Returned\n", 0, ""); + } else { + STL_PA_VF_CONFIG_RESULTS *p = (STL_PA_VF_CONFIG_RESULTS*)pQueryResults->QueryResult; + + if (g_verbose) { + fprintf(stderr, "MadStatus 0x%x: %s\n", pQueryResults->MadStatus, + iba_sd_mad_status_msg(pQueryResults->MadStatus)); + fprintf(stderr, "%d Bytes Returned\n", pQueryResults->ResultDataSize); + fprintf(stderr, "PA Multiple MAD Response for VF Config vf name %s:\n", vfName); + } + + PrintStlPAVFConfig(&g_dest, 1, vfName, p->NumVFConfigRecords, p->VFConfigRecords); + } + + status = FSUCCESS; + +done: + // iba_sd_query_port_fabric_info will have allocated a result buffer + // we must free the buffer when we are done with it + if (pQueryResults) + omgt_free_query_result_buffer(pQueryResults); + return status; + +fail: + status = FERROR; + goto done; +} +#endif + +#if 0 +static FSTATUS GetVFPortCounters(struct omgt_port *port, STL_LID nodeLid, uint8_t portNumber, uint32_t deltaFlag, uint32_t userCntrsFlag, char *vfName, uint64 imageNumber, int32 imageOffset) +{ + FSTATUS status= FERROR; + STL_PA_IMAGE_ID_DATA imageId = {0}; + STL_PA_VF_PORT_COUNTERS_DATA *response; + + fprintf(stderr, "Getting Port Counters...\n"); + imageId.imageNumber = imageNumber; + imageId.imageOffset = imageOffset; + if ((response = iba_pa_single_mad_vf_port_counters_response_query(port, nodeLid, portNumber, deltaFlag, userCntrsFlag, vfName, &imageId)) != NULL) { + status = FSUCCESS; + PrintStlPAVFPortCounters(&g_dest, 0, response, nodeLid, (uint32)portNumber, response->flags); + } else { + fprintf(stderr, "Failed to receive GetVFPortCounters response: %s\n", iba_pa_mad_status_msg(port)); + } + + if (response) + MemoryDeallocate(response); + return status; +} +#endif + +#if 0 +static FSTATUS GetVFFocusPorts(struct omgt_port *port, char *vfName, uint32 select, uint32 start, uint32 range, uint64 imageNumber, int32 imageOffset) +{ + OMGT_QUERY query; + STL_PA_IMAGE_ID_DATA imageId = {0}; + FSTATUS status; + PQUERY_RESULT_VALUES pQueryResults = NULL; + + memset(&query, 0, sizeof(query)); // initialize reserved fields + query.InputType = InputTypeNoInput; + query.OutputType = OutputTypePaTableRecord; + + fprintf(stderr, "Getting VF Focus Ports...\n"); + imageId.imageNumber = imageNumber; + imageId.imageOffset = imageOffset; + if (g_verbose) + printf("Query: Input=%s, Output=%s\n", + iba_sd_query_input_type_msg(query.InputType), + iba_sd_query_result_type_msg(query.OutputType)); + + // this call is synchronous + status = iba_pa_multi_mad_vf_focus_ports_response_query(port, &query, vfName, select, start, range, &pQueryResults, &imageId); + + if (! pQueryResults) + { + fprintf(stderr, "%*sPA VF Focus Ports query Failed: %s (%s)\n", 0, "", iba_fstatus_msg(status), iba_pa_mad_status_msg(port)); + goto fail; + } else if (pQueryResults->Status != FSUCCESS) { + fprintf(stderr, "%*sPA VF Focus Ports query Failed: %s MadStatus 0x%x: %s\n", 0, "", + iba_fstatus_msg(pQueryResults->Status), + pQueryResults->MadStatus, iba_sd_mad_status_msg(pQueryResults->MadStatus)); + goto fail; + } else if (pQueryResults->ResultDataSize == 0) { + fprintf(stderr, "%*sNo VF Focus Ports Records Returned\n", 0, ""); + } else { + STL_PA_VF_FOCUS_PORTS_RESULTS *p = (STL_PA_VF_FOCUS_PORTS_RESULTS*)pQueryResults->QueryResult; + + if (g_verbose) { + fprintf(stderr, "MadStatus 0x%x: %s\n", pQueryResults->MadStatus, + iba_sd_mad_status_msg(pQueryResults->MadStatus)); + fprintf(stderr, "%d Bytes Returned\n", pQueryResults->ResultDataSize); + fprintf(stderr, "PA Multiple MAD Response for VF Focus Ports VF name %s:\n", vfName); + } + + PrintStlPAVFFocusPorts(&g_dest, 1, vfName, p->NumVFFocusPortsRecords, select, start, range, p->FocusPortsRecords); + } + + status = FSUCCESS; + +done: + // iba_sd_query_port_fabric_info will have allocated a result buffer + // we must free the buffer when we are done with it + if (pQueryResults) + omgt_free_query_result_buffer(pQueryResults); + return status; + +fail: + status = FERROR; + goto done; +} +#endif + +void usage(void) +{ + fprintf(stderr, "Usage: opapaextract [-v] [-h hfi] [-p port] [-g groupName]\n"); + fprintf(stderr, " [-l nodeLid] [-G nodeGUID] [-D desc] [-P portNumber]\n"); + fprintf(stderr, " [-S start] [-r range] [-L rate] [-d delta] [-x]\n"); + //fprintf(stderr, "Usage: opapaquery [-v] [-h hfi] [-p port] -o type [-g groupName] [-l nodeLid]\n"); + //fprintf(stderr, " [-P portNumber] [-d delta] [-U] [-s select] [-f focus]\n"); + //fprintf(stderr, " [-S start] [-r range] [-n imgNum] [-O imgOff] [-m moveImgNum]\n"); + //fprintf(stderr, " [-M moveImgOff] [-V vfName]\n"); + fprintf(stderr, " --help - display this help text\n"); + fprintf(stderr, " -v/--verbose - verbose output\n"); + fprintf(stderr, " -h/--hfi hfi - hfi, numbered 1..n, 0= -p port will be a system wide\n"); + fprintf(stderr, " port num (default is 0)\n"); + fprintf(stderr, " -p/--port port - port, numbered 1..n, 0=1st active (default is 1st\n"); + fprintf(stderr, " active)\n"); + //fprintf(stderr, " -o/--output - output type, default is groupList\n"); + fprintf(stderr, " -g/--groupName - PM group to query, default is 1st defined group (All)\n"); + fprintf(stderr, " -l/--lid - lid of node for portCounters query\n"); + fprintf(stderr, " -G/--guid - nodeGUID of node for portCounters query\n"); + fprintf(stderr, " -D/--desc - node desc of node for portCounters query\n"); + fprintf(stderr, " -P/--portNumber - port number for portCounters query\n"); + fprintf(stderr, " -d/--delta - delta flag for portCounters query - 0 or 1 (default 1)\n"); + fprintf(stderr, " -x/--xmit - get xmit counters (default is linkintegrity)\n"); + //fprintf(stderr, " -U/--userCntrs - user controlled counters flag for portCounters query\n"); + //fprintf(stderr, " -f/--focus - focus select value for getting focus ports\n"); + //fprintf(stderr, " focus select values:\n"); + //fprintf(stderr, " utilhigh - sorted by utilization - highest first\n"); // STL_PA_SELECT_UTIL_HIGH 0x00020001 + //fprintf(stderr, " pktrate - sorted by packet rate - highest first\n"); // STL_PA_SELECT_UTIL_PKTS_HIGH 0x00020082 + //fprintf(stderr, " utillow - sorted by utilization - lowest first\n"); // STL_PA_SELECT_UTIL_LOW 0x00020101 + //fprintf(stderr, " integrity - sorted by integrity errors - highest first\n"); // STL_PA_SELECT_CATEGORY_INTEG 0x00030001 + //fprintf(stderr, " congestion - sorted by congestion errors - highest first\n"); // STL_PA_SELECT_CATEGORY_CONG 0x00030002 + //fprintf(stderr, " smacongestion - sorted by sma congestion errors - highest first\n"); // STL_PA_SELECT_CATEGORY_SMA_CONG 0x00030003 + //fprintf(stderr, " bubbles - sorted by bubble errors - highest first\n"); // STL_PA_SELECT_CATEGORY_BUBBLE 0x00030004 + //fprintf(stderr, " security - sorted by security errors - highest first\n"); // STL_PA_SELECT_CATEGORY_SEC 0x00030005 + //fprintf(stderr, " routing - sorted by routing errors - highest first\n"); // STL_PA_SELECT_CATEGORY_ROUT 0x00030006 + //fprintf(stderr, " -S/--start - start of window for focus ports - should always be 0\n"); + //fprintf(stderr, " for now\n"); + //fprintf(stderr, " -r/--range - size of window for focus ports list\n"); + fprintf(stderr, " -S/--start - start image, default is 0 (current time)\n"); + fprintf(stderr, " -r/--range - number of images to output, default is all\n"); + fprintf(stderr, " -L/--live - get live data at given rate in seconds\n"); + //fprintf(stderr, " -n/--imgNum - 64-bit image number - may be used with groupInfo,\n"); + //fprintf(stderr, " groupConfig, portCounters (delta)\n"); + //fprintf(stderr, " -O/--imgOff - image offset - may be used with groupInfo, groupConfig,\n"); + //fprintf(stderr, " portCounters (delta)\n"); + //fprintf(stderr, " -m/--moveImgNum - 64-bit image number - used with moveFreeze to move a\n"); + //fprintf(stderr, " freeze image\n"); + //fprintf(stderr, " -M/--moveImgOff - image offset - may be used with moveFreeze to move a\n"); + //fprintf(stderr, " freeze image\n"); + //fprintf(stderr, " -V/--vfName - VF name for vfInfo query\n"); + fprintf(stderr, "\n"); + fprintf(stderr, "The -h and -p options permit a variety of selections:\n"); + fprintf(stderr, " -h 0 - 1st active port in system (this is the default)\n"); + fprintf(stderr, " -h 0 -p 0 - 1st active port in system\n"); + fprintf(stderr, " -h x - 1st active port on HFI x\n"); + fprintf(stderr, " -h x -p 0 - 1st active port on HFI x\n"); + fprintf(stderr, " -h 0 -p y - port y within system (irrespective of which ports are active)\n"); + fprintf(stderr, " -h x -p y - HFI x, port y\n"); + fprintf(stderr, "\n"); + //fprintf(stderr, "Usage examples:\n"); + //fprintf(stderr, " opapaquery -o classPortInfo\n"); + //fprintf(stderr, " opapaquery -o groupList\n"); + //fprintf(stderr, " opapaquery -o groupInfo -g All\n"); + //fprintf(stderr, " opapaquery -o groupConfig -g All\n"); + //fprintf(stderr, " opapaquery -o portCounters -l 1 -P 1 -d 1\n"); + //fprintf(stderr, " opapaquery -o portCounters -l 1 -P 1 -d 1 -n 0x20000000d02 -O 1\n"); + //fprintf(stderr, " opapaquery -o clrPortCounters -l 1 -P 1 -s 0xC0000000\n"); + //fprintf(stderr, " (clears XmitData & RcvData)\n"); + //fprintf(stderr, " opapaquery -o clrAllPortCounters -s 0xC0000000\n"); + //fprintf(stderr, " (clears XmitData & RcvData on all ports)\n"); + //fprintf(stderr, " opapaquery -o pmConfig\n"); + //fprintf(stderr, " opapaquery -o freezeImage -n 0x20000000d02\n"); + //fprintf(stderr, " opapaquery -o releaseImage -n 0xd01\n"); + //fprintf(stderr, " opapaquery -o renewImage -n 0xd01\n"); + //fprintf(stderr, " opapaquery -o moveFreeze -n 0xd01 -m 0x20000000d02 -M -2\n"); + //fprintf(stderr, " opapaquery -o focusPorts -g All -f integrity -S 0 -r 20\n"); + //fprintf(stderr, " opapaquery -o imageInfo -n 0x20000000d02\n"); + //fprintf(stderr, " opapaquery -o vfList\n"); + //fprintf(stderr, " opapaquery -o vfInfo -V Default\n"); + //fprintf(stderr, " opapaquery -o vfConfig -V Default\n"); + //fprintf(stderr, " opapaquery -o vfPortCounters -l 1 -P 1 -d 1 -V Default\n"); + //fprintf(stderr, " opapaquery -o clrVfPortCounters -l 1 -P 1 -s 0xC0000000\n"); + //fprintf(stderr, " (clears VLXmitData & VLRcvData)\n"); + //fprintf(stderr, " opapaquery -o vfFocusPorts -V Default -f integrity -S 0 -r 20\n"); + + exit(2); +} + +#if 0 +typedef struct OutputFocusMap { + char *string; + int32 focus; + } OutputFocusMap_t; + +OutputFocusMap_t OutputFocusTable[]= { + {"utilhigh", STL_PA_SELECT_UTIL_HIGH }, // 0x00020001 + {"pktrate", STL_PA_SELECT_UTIL_PKTS_HIGH }, // 0x00020082 + {"utillow", STL_PA_SELECT_UTIL_LOW }, // 0x00020101 + {"integrity", STL_PA_SELECT_CATEGORY_INTEG }, // 0x00030001 + {"congestion", STL_PA_SELECT_CATEGORY_CONG }, // 0x00030002 + {"smacongestion", STL_PA_SELECT_CATEGORY_SMA_CONG }, // 0x00030003 + {"bubbles", STL_PA_SELECT_CATEGORY_BUBBLE }, // 0x00030004 + {"security" , STL_PA_SELECT_CATEGORY_SEC }, // 0x00030005 + {"routing", STL_PA_SELECT_CATEGORY_ROUT }, // 0x00030006 + { NULL, 0}, +}; + + +FSTATUS StringToFocus (int32 *value, const char* str) +{ + int i; + + i=0; + while (OutputFocusTable[i].string!=NULL) { + if (0 == strcmp(str,OutputFocusTable[i].string) ){ + *value = OutputFocusTable[i].focus; + return FSUCCESS; + } + else i++; + } + + return FERROR; +} +#endif + +int main(int argc, char ** argv) +{ + FSTATUS fstatus; + int c, index; + uint8 hfi = 0; + uint8 port = 0; + uint32 temp32; + uint8 temp8; + STL_PA_IMAGE_ID_DATA imageId; + STL_PA_IMAGE_INFO_DATA ImageInfo; + + // start at current image + imageId.imageNumber = PACLIENT_IMAGE_CURRENT; + imageId.imageOffset = 0; + + PrintDestInitFile(&g_dest, stderr); + + Top_setcmdname("opapaquery"); + + while (-1 != (c = getopt_long(argc,argv, "vh:p:o:g:l:P:G:D:d:xUs:n:O:f:S:r:L:m:M:V:", options, &index))) + { + switch (c) + { + case 'v': + g_verbose++; + if (g_verbose>4) umad_debug(g_verbose-4); + break; + + case '$': + usage(); + break; + + case 'h': + if (FSUCCESS != StringToUint8(&hfi, optarg, NULL, 0, TRUE)) { + fprintf(stderr, "opapaquery: Invalid HFI Number: %s\n", optarg); + usage(); + } + break; + + case 'p': + if (FSUCCESS != StringToUint8(&port, optarg, NULL, 0, TRUE)) { + fprintf(stderr, "opapaquery: Invalid Port Number: %s\n", optarg); + usage(); + } + break; + + case 'g': + snprintf(g_groupName, STL_PM_GROUPNAMELEN, "%s", optarg); + g_gotGroup = 1; + break; + + case 'l': + if (FSUCCESS != StringToUint32(&temp32, optarg, NULL, 0, TRUE)) { + fprintf(stderr, "opapaquery: Invalid Lid Number: %s\n", optarg); + usage(); + } + g_nodeLid = (STL_LID)temp32; + g_gotLid = TRUE; + break; + + case 'P': + if (FSUCCESS != StringToUint8(&temp8, optarg, NULL, 0, TRUE)) { + fprintf(stderr, "opapaquery: Invalid Port Number: %s\n", optarg); + usage(); + } + g_portNumber = temp8; + g_gotPort = TRUE; + break; + + case 'G': + if (FSUCCESS != StringToUint64(&g_nodeGUID, optarg, NULL, 0, TRUE)) { + fprintf(stderr, "opapaquery: Invalid GUID Number: %s\n", optarg); + usage(); + } + g_gotGUID = TRUE; + break; + + case 'D': + snprintf(g_nodeDesc, sizeof(g_nodeDesc), "%s", optarg); + g_gotDesc = TRUE; + break; + + case 'd': + if (FSUCCESS != StringToUint32(&g_deltaFlag, optarg, NULL, 0, TRUE)) { + fprintf(stderr, "opapaquery: Invalid Delta Flag: %s\n", optarg); + usage(); + } + break; + + case 'x': + g_gotXmit = TRUE; + break; + + //case 'U': + // g_userCntrsFlag = 1; + // break; + + //case 'n': + // if (FSUCCESS != StringToUint64(&imageId.imageNumber, optarg, NULL, 0, TRUE)) { + // fprintf(stderr, "opapaquery: Invalid Image Number: %s\n", optarg); + // usage(); + // } + // g_gotImgNum = TRUE; + // break; + + //case 'O': + // if (FSUCCESS != StringToInt32(&imageId.imageOffset, optarg, NULL, 0, TRUE)) { + // fprintf(stderr, "opapaquery: Invalid Image Offset: %s\n", optarg); + // usage(); + // } + // g_gotImgOff = TRUE; + // break; + + //case 'f': + // if (FSUCCESS != StringToFocus (&g_focus, optarg)) { + // fprintf(stderr, "opapaquery: Invalid Focus Number: %s\n", optarg); + // usage(); + // } + // g_gotFocus = TRUE; + // break; + + case 'S': + if (FSUCCESS != StringToInt32(&g_start, optarg, NULL, 0, TRUE)) { + fprintf(stderr, "opapaquery: Invalid Start Number: %s\n", optarg); + usage(); + } + g_gotStart = TRUE; + break; + + case 'r': + if (FSUCCESS != StringToInt32(&g_range, optarg, NULL, 0, TRUE)) { + fprintf(stderr, "opapaquery: Invalid Range Number: %s\n", optarg); + usage(); + } + g_gotRange = TRUE; + break; + + case 'L': + //fprintf(stderr, "opapaquery: -L option not working yet\n"); + //usage(); + if (FSUCCESS != StringToUint32(&g_liveRate, optarg, NULL, 0, TRUE)) { + fprintf(stderr, "opapaquery: Invalid Range Number: %s\n", optarg); + usage(); + } + g_gotLive = TRUE; + break; + + //case 'V': + // snprintf(g_vfName, STL_PM_VFNAMELEN, "%s", optarg); + // g_gotvfName = TRUE; + // break; + + default: + fprintf(stderr, "opapaquery: Invalid Option %c\n", c); + usage(); + break; + } + } /* end while */ + + if (optind < argc) + { + fprintf(stderr, "opapaquery: invalid argument %s\n", argv[optind]); + usage(); + } + + // Check parameter consistency - TBD + if (g_gotStart && g_gotLive) + { + fprintf(stderr, "opapaquery: -L option cannot be used with -S\n"); + usage(); + } + + if (g_gotLive && g_liveRate == 0) + { + fprintf(stderr, "opapaquery: -L option must be non-zero\n"); + usage(); + } + + + // initialize connections to OPA related entities + if ((fstatus = opa_pa_init(hfi, port)) != FSUCCESS) { + fprintf(stderr, "opapaquery: failed to initialize OPA PA layer - status = %d\n", fstatus); + exit(-1); + } + + if (g_verbose > 3) + set_opapaquery_debug(g_portHandle); + + ArrayInitState(&g_Columns); + ArrayInit(&g_Columns, 0, 50, sizeof(ColumnEntry_t), IBA_MEM_FLAG_NONE); + + if (! g_gotGroup) { + // default to 1st group name which should be "All" + if (FSUCCESS != GetGroupList(g_portHandle, g_groupName)) + goto exit; + fprintf(stderr, "Using Group: %s\n", g_groupName); + } + if (g_gotStart) { + imageId.imageOffset = -g_start; + } + + //if (! g_gotFocus) { + // g_focus = STL_PA_SELECT_CATEGORY_INTEG; + // fprintf(stderr, "Using Focus: integrity\n"); + //} + if (! g_gotRange) { + if (g_gotLive) + g_range = 100; // pick a reasonable fixed limit + else + g_range = IB_INT32_MAX; + fprintf(stderr, "Using range: %d\n", g_range); + } + + // we get image so we can use canonical imageId for freeze and + // subsequent access inside loop, this way our initial query using + // an offset relative to current won't unexpectedly move on us if a + // PM sweep occurs + if (FSUCCESS != GetImageInfo(g_portHandle, imageId.imageNumber, imageId.imageOffset, &ImageInfo)) + goto exit; +#if USE_ABS_IMAGENUM + imageId.imageNumber = ImageInfo.imageId.imageNumber; + imageId.imageOffset = ImageInfo.imageId.imageOffset; +#endif + +#if USE_FREEZE + if (FSUCCESS != FreezeImage(g_portHandle, imageId.imageNumber, imageId.imageOffset, &imageId)) + goto exit; + //fprintf(stderr, "Froze %lu, %d\n", imageId.imageNumber, imageId.imageOffset); +#endif + + do { + if (g_range % 10 == 0) +#if COMPUTE_DELTA + fprintf(stderr, "Processing Records for %s", ctime((time_t *)&ImageInfo.sweepStart)); +#else + fprintf(stderr, "Processing Records for %u sec at %s", ImageInfo.imageInterval, ctime((time_t *)&ImageInfo.sweepStart)); +#endif + + if (FSUCCESS != GetAndPrintGroupConfig(g_portHandle, g_groupName, imageId.imageNumber, imageId.imageOffset, &ImageInfo)) + goto exit; +#if 0 + if (FSUCCESS != GetAndPrintFocusPorts(g_portHandle, g_groupName, g_focus, g_start, g_range, imageId.imageNumber, imageId.imageOffset, &ImageInfo)) + goto exit; +#endif +#if USE_FREEZE + //fprintf(stderr, "Release %lu, %d\n", imageId.imageNumber, imageId.imageOffset); + if (g_gotLive) { + (void)ReleaseImage(g_portHandle, imageId.imageNumber, imageId.imageOffset); + sleep(g_liveRate); + } else { + fstatus = MoveFreeze(g_portHandle, imageId.imageNumber, imageId.imageOffset, imageId.imageNumber, imageId.imageOffset-1, &imageId); + // TBD - should we use unfreeze and freeze in case our lease timed out? + if (FNOT_FOUND == fstatus) + break; + else if (FSUCCESS != fstatus) + goto release; + } + //fprintf(stderr, "Froze %lu, %d\n", imageId.imageNumber, imageId.imageOffset); +#else + if (g_gotLive) { + sleep(g_liveRate); + } else { + imageId.imageOffset -= 1; + } +#endif + if (g_gotLive) { + imageId.imageNumber = PACLIENT_IMAGE_CURRENT; + imageId.imageOffset = 0; + } + fstatus = GetImageInfo(g_portHandle, imageId.imageNumber, imageId.imageOffset, &ImageInfo); + if (FSUCCESS != fstatus && FNOT_FOUND != fstatus) + goto release; +#if USE_ABS_IMAGENUM + if (FSUCCESS == fstatus) { + imageId.imageNumber = ImageInfo.imageId.imageNumber; + imageId.imageOffset = ImageInfo.imageId.imageOffset; + } +#endif +#if USE_FREEZE + if (g_gotLive) { + fstatus = FreezeImage(g_portHandle, imageId.imageNumber, imageId.imageOffset, &imageId); + if (FSUCCESS != fstatus) + break; + } +#endif + } while (FSUCCESS == fstatus && --g_range); +#if USE_FREEZE + //fprintf(stderr, "Release %lu, %d\n", imageId.imageNumber, imageId.imageOffset); + (void)ReleaseImage(g_portHandle, imageId.imageNumber, imageId.imageOffset); +#endif + OutputHeading(); + ArrayDestroy(&g_Columns); + omgt_close_port(g_portHandle); + g_portHandle = NULL; + exit(0); + +release: +#if USE_FREEZE + //fprintf(stderr, "Release %lu, %d\n", imageId.imageNumber, imageId.imageOffset); + (void)ReleaseImage(g_portHandle, imageId.imageNumber, imageId.imageOffset); +#endif +exit: + OutputHeading(); + ArrayDestroy(&g_Columns); + omgt_close_port(g_portHandle); + g_portHandle = NULL; + exit(1); +} + +// TBD - ideas for output +// - allow a -o option to cause output to be similar to: +// opaextracterror - 1 line per port, error counters only +// opaextractperf - 1 line per port, all counters +// opaextractsat - 1 line per linke, LQI and cable/link info (no) +// opaextrastat2 - 1 line per link, link info and all counters per port +// +// focus could limit to ports with non-zero for that focus +// allow focus based on existing categories as well as some individual counters or custom categories +// per VF (mainly useful for data movement or congestion, skip for now) +// +// how to organize output +// one spreadsheet for all info, use can filter and sort +// one csv per device ( tricky since list of devices is different per image) +// diff --git a/IbaTools/opapaquery/Makefile b/IbaTools/opapaquery/Makefile new file mode 100644 index 0000000..e52d5ef --- /dev/null +++ b/IbaTools/opapaquery/Makefile @@ -0,0 +1,167 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** +# Makefile for opapaquery + +# Include Make Control Settings +include $(TL_DIR)/$(PROJ_FILE_DIR)/Makesettings.project + +#=============================================================================# +# Definitions: +#-----------------------------------------------------------------------------# + +# Name of SubProjects +DS_SUBPROJECTS = +# name of executable or downloadable image +EXECUTABLE = $(BUILDDIR)/opapaquery$(EXE_SUFFIX) +# list of sub directories to build +DIRS = +# C files (.c) +CFILES = \ + opapaquery.c \ + # Add more c files here +# C++ files (.cpp) +CCFILES = \ + # Add more cpp files here +# lex files (.lex) +LFILES = \ + # Add more lex files here +# archive library files (basename, $ARFILES will add MOD_LIB_DIR/prefix and suffix) +LIBFILES= +# Windows Resource Files (.rc) +RSCFILES = +# Windows IDL File (.idl) +IDLFILE = +# Windows Linker Module Definitions (.def) file for dll's +DEFFILE = +# targets to build during INCLUDES phase (add public includes here) +INCLUDE_TARGETS = \ + # Add more h hpp files here +# Non-compiled files +MISC_FILES = +# all source files +SOURCES = $(CFILES) $(CCFILES) $(LFILES) $(RSCFILES) $(IDLFILE) +# Source files to include in DSP File +DSP_SOURCES = $(INCLUDE_TARGETS) $(SOURCES) $(MISC_FILES) \ + $(RSCFILES) $(DEFFILE) $(MAKEFILE) +# all object files +OBJECTS = $(CFILES:.c=$(OBJ_SUFFIX)) $(CCFILES:.cpp=$(OBJ_SUFFIX)) \ + $(LFILES:.lex=$(OBJ_SUFFIX)) +RSCOBJECTS = $(RSCFILES:.rc=$(RES_SUFFIX)) +# targets to build during LIBS phase +LIB_TARGETS_IMPLIB = +LIB_TARGETS_ARLIB = # $(LIB_PREFIX)ResourceTest$(ARLIB_SUFFIX) +LIB_TARGETS_EXP = $(LIB_TARGETS_IMPLIB:$(ARLIB_SUFFIX)=$(EXP_SUFFIX)) +LIB_TARGETS_MISC = +# targets to build during CMDS phase +CMD_TARGETS_SHLIB = +CMD_TARGETS_EXE = $(EXECUTABLE) +CMD_TARGETS_MISC = +# files to remove during clean phase +CLEAN_TARGETS_MISC = +CLEAN_TARGETS = $(OBJECTS) $(RSCOBJECTS) $(IDL_TARGETS) $(CLEAN_TARGETS_MISC) +# other files to remove during clobber phase +CLOBBER_TARGETS_MISC= +# sub-directory to install to within bin +BIN_SUBDIR = +# sub-directory to install to within include +INCLUDE_SUBDIR = + +# Additional Settings +#CLOCALDEBUG = User defined C debugging compilation flags [Empty] +#CCLOCALDEBUG = User defined C++ debugging compilation flags [Empty] +#CLOCAL = User defined C flags for compiling [Empty] +#CCLOCAL = User defined C++ flags for compiling [Empty] +#BSCLOCAL = User flags for Browse File Builder [Empty] +#DEPENDLOCAL = user defined makedepend flags [Empty] +#LINTLOCAL = User defined lint flags [Empty] +#LOCAL_INCLUDE_DIRS = User include directories to search for C/C++ headers [Empty] +#LDLOCAL = User defined C flags for linking [Empty] +#IMPLIBLOCAL = User flags for Object Lirary Manager [Empty] +#MIDLLOCAL = User flags for IDL compiler [Empty] +#RSCLOCAL = User flags for resource compiler [Empty] +#LOCALDEPLIBS = User libraries to include in dependencies [Empty] +#LOCALLIBS = User libraries to use when linking [Empty] +# (in addition to LOCALDEPLIBS) +#LOCAL_LIB_DIRS = User library directories for libpaths [Empty] + +CLOCAL=$(CIBACCESS) $(CPIE) +LOCAL_INCLUDE_DIRS= +ifeq "$(IB_STACK)" "IBACCESS" +LOCALDEPLIBS =$(IBACCESS_USER_LIBS) IbPrint Xml +LOCALLIBS= +LOCAL_LIB_DIRS=$(IBACCESS_USER_LIB_DIRS) +else +LOCALDEPLIBS =$(IBACCESS_USER_LIBS) opamgt-priv IbPrint Xml +LOCALLIBS=$(OPENIB_USER_LIBS) +LOCAL_LIB_DIRS=$(OPENIB_USER_LIB_DIRS) $(IBACCESS_USER_LIB_DIRS) +endif + +ifneq "$(BUILD_TARGET_OS)" "VXWORKS" +LOCALLIBS+= expat +endif + +# Include Make Rules definitions and rules +include $(TL_DIR)/IbaTools/Makerules.module + +#=============================================================================# +# Overrides: +#-----------------------------------------------------------------------------# +#CCOPT = # C++ optimization flags, default lets build config decide +#COPT = # C optimization flags, default lets build config decide +#SUBSYSTEM = Subsystem to build for (none, console or windows) [none] +# (Windows Only) +#USEMFC = How Windows MFC should be used (none, static, shared, no_mfc) [none] +# (Windows Only) +#=============================================================================# + +#=============================================================================# +# Rules: +#-----------------------------------------------------------------------------# +# process Sub-directories +include $(TL_DIR)/Makerules/Maketargets.toplevel + +# build cmds and libs +include $(TL_DIR)/Makerules/Maketargets.build + +# install for includes, libs and cmds phases +include $(TL_DIR)/Makerules/Maketargets.install + +# install for stage phase +include $(TL_DIR)/Makerules/Maketargets.stage +STAGE:: + $(VS)$(STAGE_INSTALL) $(STAGE_INSTALL_DIR_OPT) $(PROJ_STAGE_FASTFABRIC_DIR) $(EXECUTABLE) + +# Unit test execution +#include $(TL_DIR)/Makerules/Maketargets.runtest + +#=============================================================================# + +#=============================================================================# +# DO NOT DELETE THIS LINE -- make depend depends on it. +#=============================================================================# diff --git a/IbaTools/opapaquery/opapaquery.c b/IbaTools/opapaquery/opapaquery.c new file mode 100644 index 0000000..a69456b --- /dev/null +++ b/IbaTools/opapaquery/opapaquery.c @@ -0,0 +1,2310 @@ +/* BEGIN_ICS_COPYRIGHT7 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT7 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +#include +#include +#include +#include +#define _GNU_SOURCE +#include + +#include "topology.h" +#ifdef IB_STACK_OPENIB +#include +#endif +#include "ib_status.h" +#include "stl_mad_priv.h" +#include "iba/stl_pa_priv.h" +#include "opamgt_priv.h" +#include "opamgt_pa_priv.h" +#include "opamgt_pa.h" +#include "stl_print.h" +#include + +#define Q_GETGROUPLIST 1 +#define Q_GETGROUPINFO 2 +#define Q_GETGROUPCONFIG 3 +#define Q_GETPORTCOUNTERS 4 +#define Q_CLRPORTCOUNTERS 5 +#define Q_CLRALLPORTCOUNTERS 6 +#define Q_GETPMCONFIG 7 +#define Q_FREEZEIMAGE 8 +#define Q_RELEASEIMAGE 9 +#define Q_RENEWIMAGE 10 +#define Q_GETFOCUSPORTS 11 +#define Q_GETIMAGECONFIG 12 +#define Q_MOVEFREEZE 13 +#define Q_CLASSPORTINFO 14 +#define Q_GETVFLIST 15 +#define Q_GETVFINFO 16 +#define Q_GETVFCONFIG 17 +#define Q_GETVFPORTCOUNTERS 18 +#define Q_CLRVFPORTCOUNTERS 19 +#define Q_GETVFFOCUSPORTS 20 +#define Q_GETGROUPNODEINFO 21 +#define Q_GETGROUPLINKINFO 22 +#define Q_MAXQUERY 22 + +#define MAX_VFABRIC_NAME 64 // from fm_xml.h + +int g_verbose = 0; +STL_LID g_nodeLid = 0; +uint8 g_portNumber = 0; +uint64 g_nodeGuid = 0; +uint32 g_deltaFlag = 0; +uint32 g_userCntrsFlag = 0; +uint32 g_selectFlag = 0; +uint64 g_imageNumber = 0; +int32 g_imageOffset = 0; +uint32 g_imageTime = 0; +uint32 g_beginTime = 0; +uint32 g_endTime = 0; +uint64 g_moveImageNumber = 0; +int32 g_moveImageOffset = 0; +int32 g_focus = 0; +int32 g_start = 0; +int32 g_range = 0; +STL_FOCUS_PORT_TUPLE tuple[MAX_NUM_FOCUS_PORT_TUPLES]; +uint8 tupleID = 0; +uint8 g_logicalOperator = 0; +uint32 g_gotOutput = 0; +uint32 g_gotGroup = 0; +uint32 g_gotLid = 0; +uint32 g_gotPort = 0; +uint32 g_gotGUID = 0; +uint32 g_gotSelect = 0; +uint32 g_gotImgNum = 0; +uint32 g_gotImgOff = 0; +uint32 g_gotImgTime = 0; +uint32 g_gotBegTime = 0; +uint32 g_gotEndTime = 0; +uint32 g_gotMoveImgNum = 0; +uint32 g_gotMoveImgOff = 0; +uint32 g_gotFocus = 0; +uint32 g_gotStart = 0; +uint32 g_gotRange = 0; +uint32 g_gotLogicalOperator = 0; +uint32 g_gotTuple = 0; +uint32 g_gotvfName = 0; +uint32 g_gotNodeDesc = 0; +char g_groupName[STL_PM_GROUPNAMELEN]; +char g_nodeDesc[STL_PM_NODEDESCLEN]; +char g_vfName[MAX_VFABRIC_NAME]; +void *g_SDHandle = NULL; +PrintDest_t g_dest; +struct omgt_port *g_portHandle = NULL; +STL_PA_PM_CFG_DATA g_pmConfigData; +boolean g_valid_pm_config_exists = FALSE; + + +char *g_oob_address = "127.0.0.1"; +uint16 g_oob_port = 3245; +char *g_sslParmsFile = "/etc/opa/opamgt_tls.xml"; +struct omgt_ssl_params g_ssl_params = {0}; +IB_GID g_src_gid = {{0}}; +boolean g_isOOB = FALSE; +boolean g_isFEESM = FALSE; +boolean g_isOOBSSL = FALSE; + +struct option options[] = { + // basic controls + { "verbose", no_argument, NULL, 'v' }, + { "hfi", required_argument, NULL, 'h' }, + { "oob", required_argument, NULL, 'b' }, + { "port", required_argument, NULL, 'p' }, + { "source-gid", required_argument, NULL, 'x' }, + { "feEsm", no_argument, NULL, 'E' }, + { "ssl-params", required_argument, NULL, 'T' }, + + // query data + { "output", required_argument, NULL, 'o' }, + { "groupName", required_argument, NULL, 'g' }, + { "lid", required_argument, NULL, 'l' }, + { "portNumber", required_argument, NULL, 'P' }, + { "nodeGuid", required_argument, NULL, 'G' }, + { "nodeDesc", required_argument, NULL, 'D' }, + { "delta", required_argument, NULL, 'd' }, + { "begin", required_argument, NULL, 'j'}, + { "end", required_argument, NULL, 'q'}, + { "userCntrs", no_argument, NULL, 'U' }, + { "select", required_argument, NULL, 's' }, + { "imgNum", required_argument, NULL, 'n' }, + { "imgOff", required_argument, NULL, 'O' }, + { "imgTime", required_argument, NULL, 'y'}, + { "moveImgNum", required_argument, NULL, 'm' }, + { "moveImgOff", required_argument, NULL, 'M' }, + { "focus", required_argument, NULL, 'f' }, + { "start", required_argument, NULL, 'S' }, + { "range", required_argument, NULL, 'r' }, + { "operator", required_argument, NULL, 'Z'}, + { "tuple", required_argument, NULL, 'Q'}, + { "vfName", required_argument, NULL, 'V'}, + { "timeout", required_argument, NULL, '!'}, + { "help", no_argument, NULL, '$' }, + { 0 } +}; + +int getQueryType(char *outputString) +{ + int q = 0; + + if (strcasecmp(outputString, "groupList") == 0) + q = Q_GETGROUPLIST; + else if (strcasecmp(outputString, "groupInfo") == 0) + q = Q_GETGROUPINFO; + else if (strcasecmp(outputString, "groupConfig") == 0) + q = Q_GETGROUPCONFIG; + else if (strcasecmp(outputString, "portCounters") == 0) + q = Q_GETPORTCOUNTERS; + else if (strcasecmp(outputString, "clrPortCounters") == 0) + q = Q_CLRPORTCOUNTERS; + else if (strcasecmp(outputString, "clrAllPortCounters") == 0) + q = Q_CLRALLPORTCOUNTERS; + else if (strcasecmp(outputString, "pmConfig") == 0) + q = Q_GETPMCONFIG; + else if (strcasecmp(outputString, "freezeImage") == 0) + q = Q_FREEZEIMAGE; + else if (strcasecmp(outputString, "releaseImage") == 0) + q = Q_RELEASEIMAGE; + else if (strcasecmp(outputString, "renewImage") == 0) + q = Q_RENEWIMAGE; + else if (strcasecmp(outputString, "moveFreeze") == 0) + q = Q_MOVEFREEZE; + else if (strcasecmp(outputString, "focusPorts") == 0) + q = Q_GETFOCUSPORTS; + else if (strcasecmp(outputString, "imageInfo") == 0) + q = Q_GETIMAGECONFIG; + else if (strcasecmp(outputString, "classPortInfo") == 0) + q = Q_CLASSPORTINFO; + else if (strcasecmp(outputString, "vfList") == 0) + q = Q_GETVFLIST; + else if (strcasecmp(outputString, "vfInfo") == 0) + q = Q_GETVFINFO; + else if (strcasecmp(outputString, "vfConfig") == 0) + q = Q_GETVFCONFIG; + else if (strcasecmp(outputString, "vfPortCounters") == 0) + q = Q_GETVFPORTCOUNTERS; + else if (strcasecmp(outputString, "clrVfPortCounters") == 0) + q = Q_CLRVFPORTCOUNTERS; + else if (strcasecmp(outputString, "vfFocusPorts") == 0) + q = Q_GETVFFOCUSPORTS; + else if (strcasecmp(outputString, "groupNodeInfo") == 0) + q = Q_GETGROUPNODEINFO; + else if (strcasecmp(outputString, "groupLinkInfo") == 0) + q = Q_GETGROUPLINKINFO; + return(q); +} + +static STL_CLASS_PORT_INFO * GetClassPortInfo(struct omgt_port *port) +{ + STL_CLASS_PORT_INFO *response = NULL; + + if (omgt_pa_get_classportinfo(port, &response) != FSUCCESS) { + fprintf(stderr, "Failed to receive GetClassPortInfo response: %s\n", iba_pa_mad_status_msg(port)); + response = NULL; + } + + return response; +} + +static FSTATUS GetPortCounters(struct omgt_port *port, STL_LID nodeLid, uint8_t portNumber, uint32_t deltaFlag, uint32_t userCntrsFlag, uint64 imageNumber, int32 imageOffset, uint32 begin, uint32 end) +{ + FSTATUS status= FERROR; + STL_PA_IMAGE_ID_DATA imageId = {0}; + STL_PORT_COUNTERS_DATA *response = NULL; + + fprintf(stderr, "Getting Port Counters...\n"); + imageId.imageNumber = end ? PACLIENT_IMAGE_TIMED : imageNumber; + imageId.imageOffset = imageOffset; + imageId.imageTime.absoluteTime = end; + + if (begin){ + STL_PA_IMAGE_ID_DATA beginQuery = {0}, endQuery = {0}; + + beginQuery.imageNumber = PACLIENT_IMAGE_TIMED; + beginQuery.imageTime.absoluteTime = begin; + + endQuery.imageNumber = end ? PACLIENT_IMAGE_TIMED : PACLIENT_IMAGE_CURRENT; + endQuery.imageTime.absoluteTime = end; + + STL_PORT_COUNTERS_DATA *beginCounters = NULL, *endCounters = NULL; + + if ((beginCounters = iba_pa_single_mad_port_counters_response_query(port, nodeLid, portNumber, deltaFlag, userCntrsFlag, &beginQuery)) != NULL + && (endCounters = iba_pa_single_mad_port_counters_response_query(port, nodeLid, portNumber, deltaFlag, userCntrsFlag, &endQuery)) != NULL){ + + CounterSelectMask_t clearedCounters = DiffPACounters(endCounters, beginCounters, endCounters); + if (clearedCounters.AsReg32){ + char counterBuf[128]; + FormatStlCounterSelectMask(counterBuf, clearedCounters); + fprintf(stderr, "Counters reset, reporting latest count: %s\n", counterBuf); + } + status = FSUCCESS; + PrintStlPAPortCounters(&g_dest, 0, endCounters, (uint32)nodeLid, (uint32)portNumber, 0); + } else{ + fprintf(stderr, "Failed to receive GetPortCounters response: %s\n", iba_pa_mad_status_msg(port)); + } + + if (endCounters) + MemoryDeallocate(endCounters); + if (beginCounters) + MemoryDeallocate(beginCounters); + } else if ((response = iba_pa_single_mad_port_counters_response_query(port, nodeLid, portNumber, deltaFlag, userCntrsFlag, &imageId)) != NULL) { + status = FSUCCESS; + PrintStlPAPortCounters(&g_dest, 0, response, nodeLid, (uint32)portNumber, response->flags); + } else { + fprintf(stderr, "Failed to receive GetPortCounters response: %s\n", iba_pa_mad_status_msg(port)); + } + + if (response) + MemoryDeallocate(response); + return status; +} + +static FSTATUS ClrPortCounters(struct omgt_port *port, STL_LID nodeLid, uint8_t portNumber, uint32_t selectFlag) +{ + FSTATUS status= FERROR; + STL_CLR_PORT_COUNTERS_DATA *response; + + fprintf(stderr, "Clearing Port Counters...\n"); + if ((response = iba_pa_single_mad_clr_port_counters_response_query(port, nodeLid, portNumber, selectFlag)) != NULL) { + status = FSUCCESS; + fprintf(stderr, "Port Counters successfully cleared for node %d port number %d select = 0x%04x\n", nodeLid, portNumber, selectFlag); + } else { + fprintf(stderr, "Failed to receive ClrPortCounters response: %s\n", iba_pa_mad_status_msg(port)); + } + if (response) + MemoryDeallocate(response); + return status; +} + +static FSTATUS ClrAllPortCounters(struct omgt_port *port, uint32_t selectFlag) +{ + FSTATUS status= FERROR; + STL_CLR_ALL_PORT_COUNTERS_DATA *response; + + fprintf(stderr, "Clearing All Port Counters...\n"); + if ((response = iba_pa_single_mad_clr_all_port_counters_response_query(port, selectFlag)) != NULL) { + status = FSUCCESS; + fprintf(stderr, "All Port Counters successfully cleared for select = 0x%04x\n", selectFlag); + } else { + fprintf(stderr, "Failed to receive ClrAllPortCounters response: %s\n", iba_pa_mad_status_msg(port)); + } + if (response) + MemoryDeallocate(response); + return status; +} + +static FSTATUS GetPMConfig(struct omgt_port *port, STL_PA_PM_CFG_DATA *pmConfigData) +{ + FSTATUS status= FERROR; + + fprintf(stderr, "Getting PM Configuration...\n"); + memset(pmConfigData,0, sizeof(STL_PA_PM_CFG_DATA)); + if ((status = omgt_pa_get_pm_config(port, pmConfigData)) != FSUCCESS) { + fprintf(stderr, "Failed to receive GetPMConfig response: %s\n", iba_pa_mad_status_msg(port)); + } + return status; +} + +static FSTATUS FreezeImage(struct omgt_port *port, uint64 imageNumber, int32 imageOffset, uint32 imageTime) +{ + FSTATUS status= FERROR; + STL_PA_IMAGE_ID_DATA request = {0}; + STL_PA_IMAGE_ID_DATA *response; + + fprintf(stderr, "Freezing image...\n"); + request.imageNumber = imageTime ? PACLIENT_IMAGE_TIMED : imageNumber; + request.imageOffset = imageOffset; + request.imageTime.absoluteTime = imageTime; + if ((response = iba_pa_single_mad_freeze_image_response_query(port, &request)) != NULL) { + status = FSUCCESS; + PrintStlPAImageId(&g_dest, 0, response); + } else { + fprintf(stderr, "Failed to receive FreezeImage response: %s\n", iba_pa_mad_status_msg(port)); + } + if (response) + MemoryDeallocate(response); + return status; +} + +static FSTATUS ReleaseImage(struct omgt_port *port, uint64 imageNumber, int32 imageOffset) +{ + FSTATUS status= FERROR; + STL_PA_IMAGE_ID_DATA request = {0}; + STL_PA_IMAGE_ID_DATA *response; + + fprintf(stderr, "Releasing image...\n"); + request.imageNumber = imageNumber; + request.imageOffset = imageOffset; + if ((response = iba_pa_single_mad_release_image_response_query(port, &request)) != NULL) { + status = FSUCCESS; + PrintStlPAImageId(&g_dest, 0, response); + } else { + fprintf(stderr, "Failed to receive ReleaseImage response: %s\n", iba_pa_mad_status_msg(port)); + } + if (response) + MemoryDeallocate(response); + return status; +} + +static FSTATUS RenewImage(struct omgt_port *port, uint64 imageNumber, int32 imageOffset) +{ + FSTATUS status= FERROR; + STL_PA_IMAGE_ID_DATA request = {0}; + STL_PA_IMAGE_ID_DATA *response; + + fprintf(stderr, "Renewing image...\n"); + request.imageNumber = imageNumber; + request.imageOffset = imageOffset; + if ((response = iba_pa_single_mad_renew_image_response_query(port, &request)) != NULL) { + status = FSUCCESS; + PrintStlPAImageId(&g_dest, 0, response); + } else { + fprintf(stderr, "Failed to receive RenewImage response: %s\n", iba_pa_mad_status_msg(port)); + } + if (response) + MemoryDeallocate(response); + return status; +} + +static FSTATUS MoveFreeze(struct omgt_port *port, uint64 imageNumber, int32 imageOffset, uint64 moveImageNumber, int32 moveImageOffset) +{ + FSTATUS status= FERROR; + STL_MOVE_FREEZE_DATA request; + STL_MOVE_FREEZE_DATA *response; + + fprintf(stderr, "Moving freeze image...\n"); + request.oldFreezeImage.imageNumber = imageNumber; + request.oldFreezeImage.imageOffset = imageOffset; + request.newFreezeImage.imageNumber = moveImageNumber; + request.newFreezeImage.imageOffset = moveImageOffset; + if ((response = iba_pa_single_mad_move_freeze_response_query(port, &request)) != NULL) { + status = FSUCCESS; + PrintStlPAMoveFreeze(&g_dest, 0, response); + } else { + fprintf(stderr, "Failed to receive MoveFreeze response: %s\n", iba_pa_mad_status_msg(port)); + } + if (response) + MemoryDeallocate(response); + return status; +} + +static FSTATUS GetGroupList(struct omgt_port *port) +{ + OMGT_QUERY query; + FSTATUS status; + PQUERY_RESULT_VALUES pQueryResults = NULL; + + memset(&query, 0, sizeof(query)); // initialize reserved fields + query.InputType = InputTypeNoInput; + query.OutputType = OutputTypePaTableRecord; + + fprintf(stderr, "Getting Group List...\n"); + if (g_verbose) + printf("Query: Input=%s, Output=%s\n", + iba_sd_query_input_type_msg(query.InputType), + iba_sd_query_result_type_msg(query.OutputType)); + + // this call is synchronous + status = iba_pa_multi_mad_group_list_response_query(port, &query, &pQueryResults); + + if (! pQueryResults) + { + fprintf(stderr, "%*sPA GroupList query Failed: %s (%s) \n", 0, "", iba_fstatus_msg(status), iba_pa_mad_status_msg(port)); + goto fail; + } else if (pQueryResults->Status != FSUCCESS) { + fprintf(stderr, "%*sPA GroupList query Failed: %s MadStatus 0x%x: %s\n", 0, "", + iba_fstatus_msg(pQueryResults->Status), + pQueryResults->MadStatus, iba_sd_mad_status_msg(pQueryResults->MadStatus)); + goto fail; + } else if (pQueryResults->ResultDataSize == 0) { + fprintf(stderr, "%*sNo Group List Records Returned\n", 0, ""); + } else { + STL_PA_GROUP_LIST_RESULTS *p = (STL_PA_GROUP_LIST_RESULTS*)pQueryResults->QueryResult; + + if (g_verbose) { + fprintf(stderr, "MadStatus 0x%x: %s\n", pQueryResults->MadStatus, + iba_sd_mad_status_msg(pQueryResults->MadStatus)); + fprintf(stderr, "%d Bytes Returned\n", pQueryResults->ResultDataSize); + fprintf(stderr, "PA Multiple MAD Response for Group Data:\n"); + } + + PrintStlPAGroupList(&g_dest, 1, p->NumGroupListRecords, p->GroupListRecords); + } + + status = FSUCCESS; + +done: + // iba_sd_query_port_fabric_info will have allocated a result buffer + // we must free the buffer when we are done with it + if (pQueryResults) + omgt_free_query_result_buffer(pQueryResults); + return status; + +fail: + status = FERROR; + goto done; +} +static FSTATUS GetGroupList2(struct omgt_port *port, uint64 imageNumber, int32 imageOffset, uint32 imageTime) +{ + OMGT_QUERY query; + FSTATUS status; + PQUERY_RESULT_VALUES pQueryResults = NULL; + STL_PA_IMAGE_ID_DATA imageId = {0}; + + memset(&query, 0, sizeof(query)); // initialize reserved fields + query.InputType = InputTypeNoInput; + query.OutputType = OutputTypePaTableRecord; + + fprintf(stderr, "Getting Group List...\n"); + + imageId.imageNumber = imageTime ? PACLIENT_IMAGE_TIMED : imageNumber; + imageId.imageOffset = imageOffset; + imageId.imageTime.absoluteTime = imageTime; + + if (g_verbose) + printf("Query: Input=%s, Output=%s\n", + iba_sd_query_input_type_msg(query.InputType), + iba_sd_query_result_type_msg(query.OutputType)); + + // this call is synchronous + status = iba_pa_multi_mad_group_list2_response_query(port, &query, &imageId, &pQueryResults); + + if (!pQueryResults) { + fprintf(stderr, "%*sPA GroupList query Failed: %s (%s) \n", 0, "", iba_fstatus_msg(status), iba_pa_mad_status_msg(port)); + goto fail; + } else if (pQueryResults->Status != FSUCCESS) { + fprintf(stderr, "%*sPA GroupList query Failed: %s MadStatus 0x%x: %s\n", 0, "", + iba_fstatus_msg(pQueryResults->Status), + pQueryResults->MadStatus, iba_sd_mad_status_msg(pQueryResults->MadStatus)); + goto fail; + } else if (pQueryResults->ResultDataSize == 0) { + fprintf(stderr, "%*sNo Group List Records Returned\n", 0, ""); + } else { + STL_PA_GROUP_LIST2_RESULTS *p = (STL_PA_GROUP_LIST2_RESULTS *)pQueryResults->QueryResult; + + if (g_verbose) { + fprintf(stderr, "MadStatus 0x%x: %s\n", pQueryResults->MadStatus, + iba_sd_mad_status_msg(pQueryResults->MadStatus)); + fprintf(stderr, "%d Bytes Returned\n", pQueryResults->ResultDataSize); + fprintf(stderr, "PA Multiple MAD Response for Group Data:\n"); + } + + PrintStlPAGroupList2(&g_dest, 1, p->NumGroupList2Records, p->GroupList2Records); + } + + status = FSUCCESS; + +done: + // iba_sd_query_port_fabric_info will have allocated a result buffer + // we must free the buffer when we are done with it + if (pQueryResults) + omgt_free_query_result_buffer(pQueryResults); + return status; + +fail: + status = FERROR; + goto done; +} +static FSTATUS GetGroupInfo(struct omgt_port *port, char *groupName, uint64 imageNumber, int32 imageOffset, uint32 imageTime) +{ + OMGT_QUERY query; + FSTATUS status; + PQUERY_RESULT_VALUES pQueryResults = NULL; + STL_PA_IMAGE_ID_DATA imageId = {0}; + + memset(&query, 0, sizeof(query)); // initialize reserved fields + query.InputType = InputTypeNoInput; + query.OutputType = OutputTypePaTableRecord; + + fprintf(stderr, "Getting Group Info...\n"); + + imageId.imageNumber = imageTime ? PACLIENT_IMAGE_TIMED : imageNumber; + imageId.imageOffset = imageOffset; + imageId.imageTime.absoluteTime = imageTime; + + if (g_verbose) + printf("Query: Input=%s, Output=%s\n", + iba_sd_query_input_type_msg(query.InputType), + iba_sd_query_result_type_msg(query.OutputType)); + + // this call is synchronous + status = iba_pa_multi_mad_group_stats_response_query(port, &query, groupName, &pQueryResults, &imageId); + + if (! pQueryResults) + { + fprintf(stderr, "%*sPA Group Info query Failed: %s (%s)\n", 0, "", iba_fstatus_msg(status), iba_pa_mad_status_msg(port)); + goto fail; + } else if (pQueryResults->Status != FSUCCESS) { + fprintf(stderr, "%*sPA Group Info query Failed: %s MadStatus 0x%x: %s\n", 0, "", + iba_fstatus_msg(pQueryResults->Status), + pQueryResults->MadStatus, iba_sd_mad_status_msg(pQueryResults->MadStatus)); + goto fail; + } else if (pQueryResults->ResultDataSize == 0) { + fprintf(stderr, "%*sNo Group Info Records Returned\n", 0, ""); + } else { + STL_PA_GROUP_INFO_RESULTS *p = (STL_PA_GROUP_INFO_RESULTS*)pQueryResults->QueryResult; + + if (g_verbose) { + fprintf(stderr, "MadStatus 0x%x: %s\n", pQueryResults->MadStatus, + iba_sd_mad_status_msg(pQueryResults->MadStatus)); + fprintf(stderr, "%d Bytes Returned\n", pQueryResults->ResultDataSize); + fprintf(stderr, "PA Multiple MAD Response for Group Info group name %s:\n", groupName); + } + + PrintStlPAGroupInfo(&g_dest, 1, p->GroupInfoRecords); + } + + status = FSUCCESS; + +done: + // iba_sd_query_port_fabric_info will have allocated a result buffer + // we must free the buffer when we are done with it + if (pQueryResults) + omgt_free_query_result_buffer(pQueryResults); + return status; + +fail: + status = FERROR; + goto done; +} + +static FSTATUS GetGroupConfig(struct omgt_port *port, char *groupName, uint64 imageNumber, int32 imageOffset, uint32 imageTime) +{ + OMGT_QUERY query; + STL_PA_IMAGE_ID_DATA imageId = {0}; + FSTATUS status; + PQUERY_RESULT_VALUES pQueryResults = NULL; + + memset(&query, 0, sizeof(query)); // initialize reserved fields + query.InputType = InputTypeNoInput; + query.OutputType = OutputTypePaTableRecord; + + fprintf(stderr, "Getting Group Config...\n"); + + imageId.imageNumber = imageTime ? PACLIENT_IMAGE_TIMED : imageNumber; + imageId.imageOffset = imageOffset; + imageId.imageTime.absoluteTime = imageTime; + if (g_verbose) + printf("Query: Input=%s, Output=%s\n", + iba_sd_query_input_type_msg(query.InputType), + iba_sd_query_result_type_msg(query.OutputType)); + + // this call is synchronous + status = iba_pa_multi_mad_group_config_response_query(port, &query, groupName, &pQueryResults, &imageId); + + if (! pQueryResults) + { + fprintf(stderr, "%*sPA Group Config query Failed: %s (%s)\n", 0, "", iba_fstatus_msg(status), iba_pa_mad_status_msg(port)); + goto fail; + } else if (pQueryResults->Status != FSUCCESS) { + fprintf(stderr, "%*sPA Group Config query Failed: %s MadStatus 0x%x: %s\n", 0, "", + iba_fstatus_msg(pQueryResults->Status), + pQueryResults->MadStatus, iba_sd_mad_status_msg(pQueryResults->MadStatus)); + goto fail; + } else if (pQueryResults->ResultDataSize == 0) { + fprintf(stderr, "%*sNo Group Config Records Returned\n", 0, ""); + } else { + STL_PA_GROUP_CONFIG_RESULTS *p = (STL_PA_GROUP_CONFIG_RESULTS*)pQueryResults->QueryResult; + + if (g_verbose) { + fprintf(stderr, "MadStatus 0x%x: %s\n", pQueryResults->MadStatus, + iba_sd_mad_status_msg(pQueryResults->MadStatus)); + fprintf(stderr, "%d Bytes Returned\n", pQueryResults->ResultDataSize); + fprintf(stderr, "PA Multiple MAD Response for Group Config group name %s:\n", groupName); + } + + PrintStlPAGroupConfig(&g_dest, 1, groupName, p->NumGroupConfigRecords, p->GroupConfigRecords); + } + + status = FSUCCESS; + +done: + // iba_sd_query_port_fabric_info will have allocated a result buffer + // we must free the buffer when we are done with it + if (pQueryResults) + omgt_free_query_result_buffer(pQueryResults); + return status; + +fail: + status = FERROR; + goto done; +} + +static FSTATUS GetGroupNodeInfo(struct omgt_port *port, char *groupName, STL_LID nodeLid, uint64 nodeGuid, char *nodeDesc, uint64 imageNumber, int32 imageOffset, uint32 imageTime) +{ + OMGT_QUERY query; + STL_PA_IMAGE_ID_DATA imageId = {0}; + FSTATUS status; + PQUERY_RESULT_VALUES pQueryResults = NULL; + + memset(&query, 0, sizeof(query)); // initialize reserved fields + query.InputType = InputTypeNoInput; + query.OutputType = OutputTypePaTableRecord; + + fprintf(stderr, "Getting Group NodeInfo...\n"); + + imageId.imageNumber = imageTime ? PACLIENT_IMAGE_TIMED : imageNumber; + imageId.imageOffset = imageOffset; + imageId.imageTime.absoluteTime = imageTime; + if (g_verbose) + printf("Query: Input=%s, Output=%s\n", iba_sd_query_input_type_msg(query.InputType), + iba_sd_query_result_type_msg(query.OutputType)); + + // this call is synchronous + status = iba_pa_multi_mad_group_nodeinfo_response_query(port, &query, groupName, nodeLid, nodeGuid, nodeDesc, &pQueryResults, &imageId); + + if (! pQueryResults) + { + fprintf(stderr, "%*sPA Group NodeInfo query Failed: %s (%s)\n", 0, "", iba_fstatus_msg(status), iba_pa_mad_status_msg(port)); + goto fail; + } else if (pQueryResults->Status != FSUCCESS) { + fprintf(stderr, "%*sPA Group NodeInfo query Failed: %s MadStatus 0x%x: %s\n", 0, "", + iba_fstatus_msg(pQueryResults->Status), + pQueryResults->MadStatus, iba_sd_mad_status_msg(pQueryResults->MadStatus)); + goto fail; + } else if (pQueryResults->ResultDataSize == 0) { + fprintf(stderr, "%*sNo Group NodeInfo Records Returned\n", 0, ""); + } else { + STL_PA_GROUP_NODEINFO_RESULTS *p = (STL_PA_GROUP_NODEINFO_RESULTS*)pQueryResults->QueryResult; + + if (g_verbose) { + fprintf(stderr, "MadStatus 0x%x: %s\n", pQueryResults->MadStatus, + iba_sd_mad_status_msg(pQueryResults->MadStatus)); + fprintf(stderr, "%d Bytes Returned\n", pQueryResults->ResultDataSize); + fprintf(stderr, "PA Multiple MAD Response for Group NodeInfo name %s:\n", groupName); + } + + PrintStlPAGroupNodeInfo(&g_dest, 1, groupName, p->NumGroupNodeInfoRecords, p->GroupNodeInfoRecords); + } + + status = FSUCCESS; + +done: + // iba_sd_query_port_fabric_info will have allocated a result buffer + // we must free the buffer when we are done with it + if (pQueryResults) + omgt_free_query_result_buffer(pQueryResults); + return status; + +fail: + status = FERROR; + goto done; +} + +static FSTATUS GetGroupLinkInfo(struct omgt_port *port, char *groupName, STL_LID inputLid, uint8 inputPort, uint64 imageNumber, int32 imageOffset, uint32 imageTime) +{ + OMGT_QUERY query; + STL_PA_IMAGE_ID_DATA imageId = {0}; + FSTATUS status; + PQUERY_RESULT_VALUES pQueryResults = NULL; + + memset(&query, 0, sizeof(query)); // initialize reserved fields + query.InputType = InputTypeNoInput; + query.OutputType = OutputTypePaTableRecord; + + fprintf(stderr, "Getting Group LinkInfo...\n"); + + imageId.imageNumber = imageTime ? PACLIENT_IMAGE_TIMED : imageNumber; + imageId.imageOffset = imageOffset; + imageId.imageTime.absoluteTime = imageTime; + if (g_verbose) + printf("Query: Input=%s, Output=%s\n", iba_sd_query_input_type_msg(query.InputType), + iba_sd_query_result_type_msg(query.OutputType)); + + // this call is synchronous + status = iba_pa_multi_mad_group_linkinfo_response_query(port, &query, groupName, inputLid, inputPort, &pQueryResults, &imageId); + + if (! pQueryResults) + { + fprintf(stderr, "%*sPA Group LinkInfo query Failed: %s (%s)\n", 0, "", iba_fstatus_msg(status), iba_pa_mad_status_msg(port)); + goto fail; + } else if (pQueryResults->Status != FSUCCESS) { + fprintf(stderr, "%*sPA Group LinkInfo query Failed: %s MadStatus 0x%x: %s\n", 0, "", + iba_fstatus_msg(pQueryResults->Status), + pQueryResults->MadStatus, iba_sd_mad_status_msg(pQueryResults->MadStatus)); + goto fail; + } else if (pQueryResults->ResultDataSize == 0) { + fprintf(stderr, "%*sNo Group LinkInfo Records Returned\n", 0, ""); + } else { + STL_PA_GROUP_LINKINFO_RESULTS *p = (STL_PA_GROUP_LINKINFO_RESULTS*)pQueryResults->QueryResult; + + if (g_verbose) { + fprintf(stderr, "MadStatus 0x%x: %s\n", pQueryResults->MadStatus, + iba_sd_mad_status_msg(pQueryResults->MadStatus)); + fprintf(stderr, "%d Bytes Returned\n", pQueryResults->ResultDataSize); + fprintf(stderr, "PA Multiple MAD Response for Group LinkInfo name %s:\n", groupName); + } + + PrintStlPAGroupLinkInfo(&g_dest, 1, groupName, p->NumGroupLinkInfoRecords, p->GroupLinkInfoRecords); + } + + status = FSUCCESS; + +done: + // iba_sd_query_port_fabric_info will have allocated a result buffer + // we must free the buffer when we are done with it + if (pQueryResults) + omgt_free_query_result_buffer(pQueryResults); + return status; + +fail: + status = FERROR; + goto done; +} + +static FSTATUS GetFocusPorts(struct omgt_port *port, char *groupName, uint32 select, uint32 start, uint32 range, uint64 imageNumber, int32 imageOffset, uint32 imageTime, STL_FOCUS_PORT_TUPLE *tuple, uint8 operator) +{ + OMGT_QUERY query; + STL_PA_IMAGE_ID_DATA imageId = {0}; + FSTATUS status; + PQUERY_RESULT_VALUES pQueryResults = NULL; + + memset(&query, 0, sizeof(query)); // initialize reserved fields + query.InputType = InputTypeNoInput; + query.OutputType = OutputTypePaTableRecord; + + fprintf(stderr, "Getting Focus Ports...\n"); + imageId.imageNumber = imageTime ? PACLIENT_IMAGE_TIMED : imageNumber; + imageId.imageOffset = imageOffset; + imageId.imageTime.absoluteTime = imageTime; + if (g_verbose) + printf("Query: Input=%s, Output=%s\n", + iba_sd_query_input_type_msg(query.InputType), + iba_sd_query_result_type_msg(query.OutputType)); + + // this call is synchronous + if (tuple == NULL) + status = iba_pa_multi_mad_focus_ports_response_query(port, &query, groupName, select, start, range, &pQueryResults, &imageId); + else + status = iba_pa_multi_mad_focus_ports_multiselect_response_query(port, &query, groupName, start, range, &pQueryResults, &imageId, tuple, operator); + + if (! pQueryResults) + { + fprintf(stderr, "%*sPA Focus Ports query Failed: %s (%s)\n", 0, "", iba_fstatus_msg(status), iba_pa_mad_status_msg(port)); + goto fail; + } else if (pQueryResults->Status != FSUCCESS) { + fprintf(stderr, "%*sPA Focus Ports query Failed: %s MadStatus 0x%x: %s\n", 0, "", + iba_fstatus_msg(pQueryResults->Status), + pQueryResults->MadStatus, iba_sd_mad_status_msg(pQueryResults->MadStatus)); + goto fail; + } else if (pQueryResults->ResultDataSize == 0) { + fprintf(stderr, "%*sNo Focus Ports Records Returned\n", 0, ""); + } else { + if (g_verbose) { + fprintf(stderr, "MadStatus 0x%x: %s\n", pQueryResults->MadStatus, + iba_sd_mad_status_msg(pQueryResults->MadStatus)); + fprintf(stderr, "%d Bytes Returned\n", pQueryResults->ResultDataSize); + fprintf(stderr, "PA Multiple MAD Response for Focus Ports group name %s:\n", groupName); + } + + if (tuple == NULL) { + STL_PA_FOCUS_PORTS_RESULTS *p = (STL_PA_FOCUS_PORTS_RESULTS*)pQueryResults->QueryResult; + PrintStlPAFocusPorts(&g_dest, 1, groupName, p->NumFocusPortsRecords, select, start, range, p->FocusPortsRecords); + } else { + STL_PA_FOCUS_PORTS_MULTISELECT_RESULTS *p = (STL_PA_FOCUS_PORTS_MULTISELECT_RESULTS*)pQueryResults->QueryResult; + PrintStlPAFocusPortsMultiSelect(&g_dest, 1, groupName, p->NumFocusPortsRecords, start, range, p->FocusPortsRecords, operator, tuple); + } + } + + status = FSUCCESS; + +done: + // iba_sd_query_port_fabric_info will have allocated a result buffer + // we must free the buffer when we are done with it + if (pQueryResults) + omgt_free_query_result_buffer(pQueryResults); + return status; + +fail: + status = FERROR; + goto done; +} + +static FSTATUS GetImageInfo(struct omgt_port *port, uint64 imageNumber, int32 imageOffset, uint32 imageTime) +{ + FSTATUS status= FERROR; + STL_PA_IMAGE_INFO_DATA request = {{0}}; + STL_PA_IMAGE_INFO_DATA *response; + + fprintf(stderr, "Getting image info...\n"); + request.imageId.imageNumber = imageTime ? PACLIENT_IMAGE_TIMED : imageNumber; + request.imageId.imageOffset = imageOffset; + request.imageId.imageTime.absoluteTime = imageTime; + if ((response = iba_pa_multi_mad_get_image_info_response_query(port, &request)) != NULL) { + status = FSUCCESS; + PrintStlPAImageInfo(&g_dest, 0, response); + } else { + fprintf(stderr, "Failed to receive GetImageInfo response: %s\n", iba_pa_mad_status_msg(port)); + } + if (response) + MemoryDeallocate(response); + return status; +} + +static FSTATUS GetVFList(struct omgt_port *port) +{ + OMGT_QUERY query; + FSTATUS status; + PQUERY_RESULT_VALUES pQueryResults = NULL; + + memset(&query, 0, sizeof(query)); // initialize reserved fields + query.InputType = InputTypeNoInput; + query.OutputType = OutputTypePaTableRecord; + + fprintf(stderr, "Getting VF List...\n"); + if (g_verbose) + printf("Query: Input=%s, Output=%s\n", + iba_sd_query_input_type_msg(query.InputType), + iba_sd_query_result_type_msg(query.OutputType)); + + // this call is synchronous + status = iba_pa_multi_mad_vf_list_response_query(port, &query, &pQueryResults); + + if (! pQueryResults) + { + fprintf(stderr, "%*sPA vfList query Failed: %s (%s) \n", 0, "", iba_fstatus_msg(status), iba_pa_mad_status_msg(port)); + goto fail; + } else if (pQueryResults->Status != FSUCCESS) { + fprintf(stderr, "%*sPA vfList query Failed: %s MadStatus 0x%x: %s\n", 0, "", + iba_fstatus_msg(pQueryResults->Status), + pQueryResults->MadStatus, iba_sd_mad_status_msg(pQueryResults->MadStatus)); + goto fail; + } else if (pQueryResults->ResultDataSize == 0) { + fprintf(stderr, "%*sNo VF List Records Returned\n", 0, ""); + } else { + STL_PA_VF_LIST_RESULTS *p = (STL_PA_VF_LIST_RESULTS *)pQueryResults->QueryResult; + + if (g_verbose) { + fprintf(stderr, "MadStatus 0x%x: %s\n", pQueryResults->MadStatus, + iba_sd_mad_status_msg(pQueryResults->MadStatus)); + fprintf(stderr, "%d Bytes Returned\n", pQueryResults->ResultDataSize); + fprintf(stderr, "PA Multiple MAD Response for VF list data:\n"); + } + + PrintStlPAVFList(&g_dest, 1, p->NumVFListRecords, p->VFListRecords); + } + + status = FSUCCESS; + +done: + // iba_sd_query_port_fabric_info will have allocated a result buffer + // we must free the buffer when we are done with it + if (pQueryResults) + omgt_free_query_result_buffer(pQueryResults); + return status; + +fail: + status = FERROR; + goto done; +} +static FSTATUS GetVFList2(struct omgt_port *port, uint64 imageNumber, int32 imageOffset, uint32 imageTime) +{ + OMGT_QUERY query; + FSTATUS status; + PQUERY_RESULT_VALUES pQueryResults = NULL; + STL_PA_IMAGE_ID_DATA imageId = { 0 }; + + memset(&query, 0, sizeof(query)); // initialize reserved fields + query.InputType = InputTypeNoInput; + query.OutputType = OutputTypePaTableRecord; + + fprintf(stderr, "Getting VF List...\n"); + imageId.imageNumber = imageTime ? PACLIENT_IMAGE_TIMED : imageNumber; + imageId.imageOffset = imageOffset; + imageId.imageTime.absoluteTime = imageTime; + if (g_verbose) + printf("Query: Input=%s, Output=%s\n", + iba_sd_query_input_type_msg(query.InputType), + iba_sd_query_result_type_msg(query.OutputType)); + + // this call is synchronous + status = iba_pa_multi_mad_vf_list2_response_query(port, &query, &imageId, &pQueryResults); + + if (!pQueryResults) { + fprintf(stderr, "%*sPA vfList query Failed: %s (%s) \n", 0, "", iba_fstatus_msg(status), iba_pa_mad_status_msg(port)); + goto fail; + } else if (pQueryResults->Status != FSUCCESS) { + fprintf(stderr, "%*sPA vfList query Failed: %s MadStatus 0x%x: %s\n", 0, "", + iba_fstatus_msg(pQueryResults->Status), + pQueryResults->MadStatus, iba_sd_mad_status_msg(pQueryResults->MadStatus)); + goto fail; + } else if (pQueryResults->ResultDataSize == 0) { + fprintf(stderr, "%*sNo VF List Records Returned\n", 0, ""); + } else { + STL_PA_VF_LIST2_RESULTS *p = (STL_PA_VF_LIST2_RESULTS *)pQueryResults->QueryResult; + + if (g_verbose) { + fprintf(stderr, "MadStatus 0x%x: %s\n", pQueryResults->MadStatus, + iba_sd_mad_status_msg(pQueryResults->MadStatus)); + fprintf(stderr, "%d Bytes Returned\n", pQueryResults->ResultDataSize); + fprintf(stderr, "PA Multiple MAD Response for VF list data:\n"); + } + + PrintStlPAVFList2(&g_dest, 1, p->NumVFList2Records, p->VFList2Records); + } + + status = FSUCCESS; + +done: + // iba_sd_query_port_fabric_info will have allocated a result buffer + // we must free the buffer when we are done with it + if (pQueryResults) + omgt_free_query_result_buffer(pQueryResults); + return status; + +fail: + status = FERROR; + goto done; +} + +static FSTATUS GetVFInfo(struct omgt_port *port, char *vfName, uint64 imageNumber, int32 imageOffset, uint32 imageTime) +{ + OMGT_QUERY query; + FSTATUS status; + PQUERY_RESULT_VALUES pQueryResults = NULL; + STL_PA_IMAGE_ID_DATA imageId = {0}; + + memset(&query, 0, sizeof(query)); // initialize reserved fields + query.InputType = InputTypeNoInput; + query.OutputType = OutputTypePaTableRecord; + + fprintf(stderr, "Getting VF Info...\n"); + imageId.imageNumber = imageTime ? PACLIENT_IMAGE_TIMED : imageNumber; + imageId.imageOffset = imageOffset; + imageId.imageTime.absoluteTime = imageTime; + if (g_verbose) + printf("Query: Input=%s, Output=%s\n", + iba_sd_query_input_type_msg(query.InputType), + iba_sd_query_result_type_msg(query.OutputType)); + + // this call is synchronous + status = iba_pa_multi_mad_vf_info_response_query(port, &query, vfName, &pQueryResults, &imageId); + + if (! pQueryResults) + { + fprintf(stderr, "%*sPA VF Info query Failed: %s (%s)\n", 0, "", iba_fstatus_msg(status), iba_pa_mad_status_msg(port)); + goto fail; + } else if (pQueryResults->Status != FSUCCESS) { + fprintf(stderr, "%*sPA VF Info query Failed: %s MadStatus 0x%x: %s\n", 0, "", + iba_fstatus_msg(pQueryResults->Status), + pQueryResults->MadStatus, iba_sd_mad_status_msg(pQueryResults->MadStatus)); + goto fail; + } else if (pQueryResults->ResultDataSize == 0) { + fprintf(stderr, "%*sNo VF Info Records Returned\n", 0, ""); + } else { + STL_PA_VF_INFO_RESULTS *p = (STL_PA_VF_INFO_RESULTS*)pQueryResults->QueryResult; + + if (g_verbose) { + fprintf(stderr, "MadStatus 0x%x: %s\n", pQueryResults->MadStatus, + iba_sd_mad_status_msg(pQueryResults->MadStatus)); + fprintf(stderr, "%d Bytes Returned\n", pQueryResults->ResultDataSize); + fprintf(stderr, "PA Multiple MAD Response for VF Info VF name %s:\n", vfName); + } + + PrintStlPAVFInfo(&g_dest, 1, p->VFInfoRecords); + } + + status = FSUCCESS; + +done: + // iba_sd_query_port_fabric_info will have allocated a result buffer + // we must free the buffer when we are done with it + if (pQueryResults) + omgt_free_query_result_buffer(pQueryResults); + return status; + +fail: + status = FERROR; + goto done; +} + +static FSTATUS GetVFConfig(struct omgt_port *port, char *vfName, uint64 imageNumber, int32 imageOffset, uint32 imageTime) +{ + OMGT_QUERY query; + STL_PA_IMAGE_ID_DATA imageId = {0}; + FSTATUS status; + PQUERY_RESULT_VALUES pQueryResults = NULL; + + memset(&query, 0, sizeof(query)); // initialize reserved fields + query.InputType = InputTypeNoInput; + query.OutputType = OutputTypePaTableRecord; + + fprintf(stderr, "Getting VF Config...\n"); + imageId.imageNumber = imageTime ? PACLIENT_IMAGE_TIMED : imageNumber; + imageId.imageOffset = imageOffset; + imageId.imageTime.absoluteTime = imageTime; + if (g_verbose) + printf("Query: Input=%s, Output=%s\n", + iba_sd_query_input_type_msg(query.InputType), + iba_sd_query_result_type_msg(query.OutputType)); + + // this call is synchronous + status = iba_pa_multi_mad_vf_config_response_query(port, &query, vfName, &pQueryResults, &imageId); + + if (! pQueryResults) + { + fprintf(stderr, "%*sPA VF Config query Failed: %s (%s)\n", 0, "", iba_fstatus_msg(status), iba_pa_mad_status_msg(port)); + goto fail; + } else if (pQueryResults->Status != FSUCCESS) { + fprintf(stderr, "%*sPA VF Config query Failed: %s MadStatus 0x%x: %s\n", 0, "", + iba_fstatus_msg(pQueryResults->Status), + pQueryResults->MadStatus, iba_sd_mad_status_msg(pQueryResults->MadStatus)); + goto fail; + } else if (pQueryResults->ResultDataSize == 0) { + fprintf(stderr, "%*sNo VF Config Records Returned\n", 0, ""); + } else { + STL_PA_VF_CONFIG_RESULTS *p = (STL_PA_VF_CONFIG_RESULTS*)pQueryResults->QueryResult; + + if (g_verbose) { + fprintf(stderr, "MadStatus 0x%x: %s\n", pQueryResults->MadStatus, + iba_sd_mad_status_msg(pQueryResults->MadStatus)); + fprintf(stderr, "%d Bytes Returned\n", pQueryResults->ResultDataSize); + fprintf(stderr, "PA Multiple MAD Response for VF Config vf name %s:\n", vfName); + } + + PrintStlPAVFConfig(&g_dest, 1, vfName, p->NumVFConfigRecords, p->VFConfigRecords); + } + + status = FSUCCESS; + +done: + // iba_sd_query_port_fabric_info will have allocated a result buffer + // we must free the buffer when we are done with it + if (pQueryResults) + omgt_free_query_result_buffer(pQueryResults); + return status; + +fail: + status = FERROR; + goto done; +} + +static FSTATUS GetVFPortCounters(struct omgt_port *port, STL_LID nodeLid, uint8_t portNumber, uint32_t deltaFlag, uint32_t userCntrsFlag, char *vfName, uint64 imageNumber, int32 imageOffset, uint32 begin, uint32 end) +{ + FSTATUS status= FERROR; + STL_PA_IMAGE_ID_DATA imageId = {0}; + STL_PA_VF_PORT_COUNTERS_DATA *response = NULL; + + fprintf(stderr, "Getting Port Counters...\n"); + imageId.imageNumber = end ? PACLIENT_IMAGE_TIMED : imageNumber; + imageId.imageOffset = imageOffset; + imageId.imageTime.absoluteTime = end; + + if (begin){ + STL_PA_IMAGE_ID_DATA beginQuery = {0}, endQuery = {0}; + + beginQuery.imageNumber = PACLIENT_IMAGE_TIMED; + beginQuery.imageTime.absoluteTime = begin; + + endQuery.imageNumber = end ? PACLIENT_IMAGE_TIMED : PACLIENT_IMAGE_CURRENT; + endQuery.imageTime.absoluteTime = end; + + STL_PA_VF_PORT_COUNTERS_DATA *beginCounters = NULL, *endCounters = NULL; + + if ((beginCounters = iba_pa_single_mad_vf_port_counters_response_query(port, nodeLid, portNumber, 0, 0, vfName, &beginQuery)) != NULL + && (endCounters = iba_pa_single_mad_vf_port_counters_response_query(port, nodeLid, portNumber, 0, 0, vfName, &endQuery)) != NULL){ + + CounterSelectMask_t clearedCounters = DiffPAVFCounters(endCounters, beginCounters, endCounters); + if (clearedCounters.AsReg32){ + char counterBuf[128]; + FormatStlCounterSelectMask(counterBuf, clearedCounters); + fprintf(stderr, "Counters reset, reporting latest count: %s", counterBuf); + } + status = FSUCCESS; + PrintStlPAVFPortCounters(&g_dest, 0, endCounters, (uint32)nodeLid, (uint32)portNumber, 0); + } else{ + fprintf(stderr, "Failed to receive GetVFPortCounters response: %s\n", iba_pa_mad_status_msg(port)); + } + + if (endCounters) + MemoryDeallocate(endCounters); + if (beginCounters) + MemoryDeallocate(beginCounters); + }else if ((response = iba_pa_single_mad_vf_port_counters_response_query(port, nodeLid, portNumber, deltaFlag, userCntrsFlag, vfName, &imageId)) != NULL) { + status = FSUCCESS; + PrintStlPAVFPortCounters(&g_dest, 0, response, nodeLid, (uint32)portNumber, response->flags); + } else { + fprintf(stderr, "Failed to receive GetPortCounters response: %s\n", iba_pa_mad_status_msg(port)); + } + + if (response) + MemoryDeallocate(response); + return status; +} + +static FSTATUS ClrVFPortCounters(struct omgt_port *port, uint32_t nodeLid, uint8_t portNumber, uint32_t selectFlag, char *vfName) +{ + FSTATUS status= FERROR; + STL_PA_CLEAR_VF_PORT_COUNTERS_DATA *response; + + fprintf(stderr, "Clearing VF Port Counters...\n"); + if ((response = iba_pa_single_mad_clr_vf_port_counters_response_query(port, nodeLid, portNumber, selectFlag, vfName)) != NULL) { + status = FSUCCESS; + fprintf(stderr, "VF Port Counters successfully cleared for vf %s node %d port number %d select = 0x%04x\n", vfName, nodeLid, portNumber, selectFlag); + } else { + fprintf(stderr, "Failed to receive ClrVFPortCounters response: %s\n", iba_pa_mad_status_msg(port)); + } + if (response) + MemoryDeallocate(response); + return status; +} + +static FSTATUS GetVFFocusPorts(struct omgt_port *port, char *vfName, uint32 select, uint32 start, uint32 range, uint64 imageNumber, int32 imageOffset, uint32 imageTime) +{ + OMGT_QUERY query; + STL_PA_IMAGE_ID_DATA imageId = {0}; + FSTATUS status; + PQUERY_RESULT_VALUES pQueryResults = NULL; + + memset(&query, 0, sizeof(query)); // initialize reserved fields + query.InputType = InputTypeNoInput; + query.OutputType = OutputTypePaTableRecord; + + fprintf(stderr, "Getting VF Focus Ports...\n"); + imageId.imageNumber = imageTime ? PACLIENT_IMAGE_TIMED : imageNumber; + imageId.imageOffset = imageOffset; + imageId.imageTime.absoluteTime = imageTime; + if (g_verbose) + printf("Query: Input=%s, Output=%s\n", + iba_sd_query_input_type_msg(query.InputType), + iba_sd_query_result_type_msg(query.OutputType)); + + // this call is synchronous + status = iba_pa_multi_mad_vf_focus_ports_response_query(port, &query, vfName, select, start, range, &pQueryResults, &imageId); + + if (! pQueryResults) + { + fprintf(stderr, "%*sPA VF Focus Ports query Failed: %s (%s)\n", 0, "", iba_fstatus_msg(status), iba_pa_mad_status_msg(port)); + goto fail; + } else if (pQueryResults->Status != FSUCCESS) { + fprintf(stderr, "%*sPA VF Focus Ports query Failed: %s MadStatus 0x%x: %s\n", 0, "", + iba_fstatus_msg(pQueryResults->Status), + pQueryResults->MadStatus, iba_sd_mad_status_msg(pQueryResults->MadStatus)); + goto fail; + } else if (pQueryResults->ResultDataSize == 0) { + fprintf(stderr, "%*sNo VF Focus Ports Records Returned\n", 0, ""); + } else { + STL_PA_VF_FOCUS_PORTS_RESULTS *p = (STL_PA_VF_FOCUS_PORTS_RESULTS*)pQueryResults->QueryResult; + + if (g_verbose) { + fprintf(stderr, "MadStatus 0x%x: %s\n", pQueryResults->MadStatus, + iba_sd_mad_status_msg(pQueryResults->MadStatus)); + fprintf(stderr, "%d Bytes Returned\n", pQueryResults->ResultDataSize); + fprintf(stderr, "PA Multiple MAD Response for VF Focus Ports VF name %s:\n", vfName); + } + + PrintStlPAVFFocusPorts(&g_dest, 1, vfName, p->NumVFFocusPortsRecords, select, start, range, p->FocusPortsRecords); + } + + status = FSUCCESS; + +done: + // iba_sd_query_port_fabric_info will have allocated a result buffer + // we must free the buffer when we are done with it + if (pQueryResults) + omgt_free_query_result_buffer(pQueryResults); + return status; + +fail: + status = FERROR; + goto done; +} + + +void usage(void) +{ + fprintf(stderr, "Usage: opapaquery [-v] [-h hfi|-b addr] [-p port] [-x gid] [-E] [-T ssl_params]\n" + " -o type [-g groupName] [-l nodeLid] [-P portNumber]\n" + " [-G nodeGuid] [-D nodeDesc] [-d delta] \n" + " [-j date_time] [-q date_time] [-U] [-s select]\n" + " [-d delta] [-j date_time] [-q date_time] [-U] [-s select]\n" + " [-f focus] [-S start] [-r range] [-n imgNum] [-O imgOff]\n" + " [-y imgTime] [-m moveImgNum] [-M moveImgOff] [-V vfName]\n"); + fprintf(stderr, " --help - display this help text\n"); + fprintf(stderr, " -v/--verbose - verbose output\n"); + fprintf(stderr, " -h/--hfi hfi - hfi, numbered 1..n, 0= -p port will be a system wide\n"); + fprintf(stderr, " port num (default is 0)\n"); + fprintf(stderr, " -b/--oob address - Out-of-Band address of node running the FE. Can be\n" + " either hostname, IPv4, or IPv6 address.\n" + " (default is \"%s\"\n", g_oob_address); + fprintf(stderr, " -p/--port port - port, \n" + " In-band: numbered 1..n, 0=1st active (default\n" + " is 1st active)\n" + " Out-of-band: Port FE is listening on (default\n" + " is %u)\n", g_oob_port); + fprintf(stderr, " -x/--source-gid src_gid - Source GID of the local GID [required for most\n"); + fprintf(stderr, " Path and Trace Record Queries when Out-of-Band]\n"); + fprintf(stderr, " -E/--feEsm - ESM FE\n"); + fprintf(stderr, " -T/--ssl-params file - SSL/TLS parameters XML file\n" + " (default is \"%s\")\n", g_sslParmsFile); + fprintf(stderr, " -o/--output - output type, default is groupList\n"); + fprintf(stderr, " -g/--groupName - group name for groupInfo query\n"); + fprintf(stderr, " -l/--lid - lid of node\n"); + fprintf(stderr, " -P/--portNumber - port number within node\n"); + fprintf(stderr, " --timeout - timeout(response wait time) in ms, default is 1000ms\n"); + fprintf(stderr, " -G/--nodeGuid - node GUID\n"); + fprintf(stderr, " -D/--nodeDesc - node Description\n"); + fprintf(stderr, " -d/--delta - delta flag for portCounters query - 0 or 1\n"); + fprintf(stderr, " -j/--begin date_time - obtain portCounters over interval\n"); + fprintf(stderr, " beginning at date_time.\n"); + fprintf(stderr, " -q/--end date_time - obtain portCounters over interval\n"); + fprintf(stderr, " ending at date_time.\n"); + fprintf(stderr, " For both -j and -q, date_time may be a time\n"); + fprintf(stderr, " entered as HH:MM[:SS] or date as mm/dd/YYYY,\n"); + fprintf(stderr, " dd.mm.YYYY, YYYY-mm-dd or date followed by time\n"); + fprintf(stderr, " e.g. \"2016-07-04 14:40\". Relative times are\n"); + fprintf(stderr, " taken as \"x [second|minute|hour|day](s) ago.\"\n"); + fprintf(stderr, " -U/--userCntrs - user controlled counters flag for portCounters query\n"); + fprintf(stderr, " -s/--select - 32-bit select flag for clearing port counters\n"); + fprintf(stderr, " select bits for clrPortCounters (0 is least significant (rightmost))\n"); + fprintf(stderr, " mask bit location \n"); + fprintf(stderr, " 0x80000000 31 Xmit Data\n"); + fprintf(stderr, " 0x40000000 30 Rcv Data\n"); + fprintf(stderr, " 0x20000000 29 Xmit Pkts\n"); + fprintf(stderr, " 0x10000000 28 Rcv Pkts\n"); + fprintf(stderr, " 0x08000000 27 Multicast Xmit Pkts\n"); + fprintf(stderr, " 0x04000000 26 Multicast Rcv Pkts\n"); + fprintf(stderr, " 0x02000000 25 Xmit Wait\n"); + fprintf(stderr, " 0x01000000 24 Congestion Discards\n"); + fprintf(stderr, " 0x00800000 23 Rcv FECN\n"); + fprintf(stderr, " 0x00400000 22 Rcv BECN\n"); + fprintf(stderr, " 0x00200000 21 Xmit Time Cong.\n"); + fprintf(stderr, " 0x00100000 20 Xmit Time Wasted BW\n"); + fprintf(stderr, " 0x00080000 19 Xmit Time Wait Data\n"); + fprintf(stderr, " 0x00040000 18 Rcv Bubble\n"); + fprintf(stderr, " 0x00020000 17 Mark FECN\n"); + fprintf(stderr, " 0x00010000 16 Rcv Constraint Errors\n"); + fprintf(stderr, " 0x00008000 15 Rcv Switch Relay\n"); + fprintf(stderr, " 0x00004000 14 Xmit Discards\n"); + fprintf(stderr, " 0x00002000 13 Xmit Constraint Errors\n"); + fprintf(stderr, " 0x00001000 12 Rcv Rmt Phys. Errors\n"); + fprintf(stderr, " 0x00000800 11 Local Link Integrity\n"); + fprintf(stderr, " 0x00000400 10 Rcv Errors\n"); + fprintf(stderr, " 0x00000200 9 Exc. Buffer Overrun\n"); + fprintf(stderr, " 0x00000100 8 FM Config Errors\n"); + fprintf(stderr, " 0x00000080 7 Link Error Recovery\n"); + fprintf(stderr, " 0x00000040 6 Link Error Downed\n"); + fprintf(stderr, " 0x00000020 5 Uncorrectable Errors\n"); + fprintf(stderr, " \n"); + fprintf(stderr, " select bits for clrVfPortCounters (0 is least signficant (rightmost))\n"); + fprintf(stderr, " mask bit location \n"); + fprintf(stderr, " 0x80000000 31 VLXmitData \n"); + fprintf(stderr, " 0x40000000 30 VLRcvData \n"); + fprintf(stderr, " 0x20000000 29 VLXmitPkts \n"); + fprintf(stderr, " 0x10000000 28 VLRcvPkts \n"); + fprintf(stderr, " 0x08000000 27 VLXmitDiscards \n"); + fprintf(stderr, " 0x04000000 26 VLCongDiscards\n"); + fprintf(stderr, " 0x02000000 25 VLXmitWait \n"); + fprintf(stderr, " 0x01000000 24 VLRcvFECN\n"); + fprintf(stderr, " 0x00800000 23 VLRcvBECN \n"); + fprintf(stderr, " 0x00400000 22 VLXmitTimeCong\n"); + fprintf(stderr, " 0x00200000 21 VLXmitWastedBW \n"); + fprintf(stderr, " 0x00100000 20 VLXmitWaitData\n"); + fprintf(stderr, " 0x00080000 19 VLRcvBubble \n"); + fprintf(stderr, " 0x00040000 18 VLMarkFECN\n"); + fprintf(stderr, " Bits 17-0 reseved\n"); + fprintf(stderr, " -f/--focus - focus select value for getting focus ports\n"); + fprintf(stderr, " focus select values:\n"); + fprintf(stderr, " unexpclrport - lists unexpectedly cleared ports - LID ordered\n"); // STL_PA_SELECT_UNEXP_CLR_PORT 0x00010101 + fprintf(stderr, " norespport - lists no response ports - LID ordered\n"); // STL_PA_SELECT_NO_RESP_PORT 0x00010102 + fprintf(stderr, " skippedport - lists skipped ports - LID ordered\n"); // STL_PA_SELECT_SKIPPED_PORT 0x00010103 + fprintf(stderr, " utilhigh - sorted by utilization - highest first\n"); // STL_PA_SELECT_UTIL_HIGH 0x00020001 + fprintf(stderr, " pktrate - sorted by packet rate - highest first\n"); // STL_PA_SELECT_UTIL_PKTS_HIGH 0x00020082 + fprintf(stderr, " utillow - sorted by utilization - lowest first\n"); // STL_PA_SELECT_UTIL_LOW 0x00020101 + fprintf(stderr, " integrity - sorted by integrity category - highest first\n"); // STL_PA_SELECT_CATEGORY_INTEG 0x00030001 + fprintf(stderr, " congestion - sorted by congestion category - highest first\n"); // STL_PA_SELECT_CATEGORY_CONG 0x00030002 + fprintf(stderr, " smacongestion - sorted by sma congestion category - highest first\n"); // STL_PA_SELECT_CATEGORY_SMA_CONG 0x00030003 + fprintf(stderr, " bubbles - sorted by bubble category - highest first\n"); // STL_PA_SELECT_CATEGORY_BUBBLE 0x00030004 + fprintf(stderr, " security - sorted by security category - highest first\n"); // STL_PA_SELECT_CATEGORY_SEC 0x00030005 + fprintf(stderr, " routing - sorted by routing category - highest first\n"); // STL_PA_SELECT_CATEGORY_ROUT 0x00030006 + fprintf(stderr, " vfutilhigh - sorted by utilization - highest first\n"); // STL_PA_SELECT_VF_UTIL_HIGH 0x00020083 + fprintf(stderr, " vfpktrate - sorted by packet rate - highest first\n"); // STL_PA_SELECT_VF_UTIL_PKTS_HIGH 0x00020084 + fprintf(stderr, " vfutillow - sorted by utilization - lowest first\n"); // STL_PA_SELECT_VF_UTIL_LOW 0x00020102 + fprintf(stderr, " vfcongestion - sorted by congestion category - highest first\n"); // STL_PA_SELECT_CATEGORY_VF_CONG 0x00030007 + fprintf(stderr, " vfbubbles - sorted by bubble category - highest first\n"); // STL_PA_SELECT_CATEGORY_VF_BUBBLE 0x00030008 + fprintf(stderr, " -S/--start - start of window for focus ports - should always be 0\n"); + fprintf(stderr, " for now\n"); + fprintf(stderr, " -r/--range - size of window for focus ports list\n"); + fprintf(stderr, " -Q/--tuple - a tuple that identifies a focus select value, comparator and argument\n"); + fprintf(stderr, " in the form select:comparator:argument. Up to 8 tuples may be specified as: -Q s1:c1:a1 -Q s2:c2:a2 ... -Q s8:c8:a8\n"); + fprintf(stderr, " Valid focus select values are: utilization, pktrate, integrity, congestion, smacongestion, bubbles, security and routing\n"); + fprintf(stderr, " Valid comparator values are: GT, GE, LT, LE\n"); + fprintf(stderr, " Valid arguments are: any 64-bit value in hexadecimal or decimal.\n"); + fprintf(stderr, " When specifying more than one tuple, a logical operator -Z/--operator must also be specified.\n"); + fprintf(stderr, " -Z/--operator - a logical operator used to join the results of the specified tuples.\n"); + fprintf(stderr, " and - a port is returned if it meets all of the tuple filter criteria\n"); + fprintf(stderr, " or - a port is returned if it meets one or more of the tuple filter criteria\n"); + fprintf(stderr, " -n/--imgNum - 64-bit image number \n"); + fprintf(stderr, " -O/--imgOff - image offset \n"); + fprintf(stderr, " -y/--imgTime - image time - may be used with imageinfo, groupInfo,\n"); + fprintf(stderr, " groupInfo, groupConfig, freezeImage, focusPorts,\n"); + fprintf(stderr, " vfInfo, vfConfig, and vfFocusPorts. Will return\n"); + fprintf(stderr, " closest image within image interval if possible.\n"); + fprintf(stderr, " See --begin/--end above for format.\n"); + fprintf(stderr, " -m/--moveImgNum - 64-bit image number - used with moveFreeze to move a\n"); + fprintf(stderr, " freeze image\n"); + fprintf(stderr, " -M/--moveImgOff - image offset - may be used with moveFreeze to move a\n"); + fprintf(stderr, " freeze image\n"); + fprintf(stderr, " -V/--vfName - VF name for vfInfo query\n"); + fprintf(stderr, "\n"); + fprintf(stderr, "The -h and -p options permit a variety of selections:\n"); + fprintf(stderr, " -h 0 - 1st active port in system (this is the default)\n"); + fprintf(stderr, " -h 0 -p 0 - 1st active port in system\n"); + fprintf(stderr, " -h x - 1st active port on HFI x\n"); + fprintf(stderr, " -h x -p 0 - 1st active port on HFI x\n"); + fprintf(stderr, " -h 0 -p y - port y within system (irrespective of which ports are active)\n"); + fprintf(stderr, " -h x -p y - HFI x, port y\n"); + fprintf(stderr, "\n"); + fprintf(stderr, "Output types:\n"); + fprintf(stderr, " classPortInfo - class port info\n"); + fprintf(stderr, " groupList - list of PA groups (default)\n"); + fprintf(stderr, " groupInfo - summary statistics of a PA group - requires -g option\n"); + fprintf(stderr, " for groupName\n"); + fprintf(stderr, " groupConfig - configuration of a PA group - requires -g option for\n"); + fprintf(stderr, " groupName\n"); + fprintf(stderr, " groupNodeInfo - Node Information of a PA group - requires -g option for\n"); + fprintf(stderr, " groupName, options -l (lid), -G (nodeGuid) and\n"); + fprintf(stderr, " -D (node description) are optional\n"); + fprintf(stderr, " groupLinkInfo - Link Information of a PA group - requires -g option for\n"); + fprintf(stderr, " groupName, options -l (lid) and -P (port) are optional\n"); + fprintf(stderr, " -P 255 is for all ports. Option -P (port) without -l (lid)\n"); + fprintf(stderr, " is ignored\n"); + fprintf(stderr, " portCounters - port counters of fabric port - requires -l (lid) and\n"); + fprintf(stderr, " -P (port) options, -d (delta) is optional\n"); + fprintf(stderr, " clrPortCounters - clear port counters of fabric port - requires -l (lid),\n"); + fprintf(stderr, " -P (port), and -s (select) options\n"); + fprintf(stderr, " clrAllPortCounters - clear all port counters in fabric - requires -s\n"); + fprintf(stderr, " (select) option\n"); + fprintf(stderr, " pmConfig - retrieve PM configuration information\n"); + fprintf(stderr, " freezeImage - create freeze frame for image ID - requires -n (imgNum)\n"); + fprintf(stderr, " releaseImage - release freeze frame for image ID - requires -n\n"); + fprintf(stderr, " (imgNum)\n"); + fprintf(stderr, " renewImage - renew lease for freeze frame for image ID - requires -n\n"); + fprintf(stderr, " (imgNum)\n"); + fprintf(stderr, " moveFreeze - move freeze frame from image ID to new image ID -\n"); + fprintf(stderr, " requires -n (imgNum) and -m (moveImgNum)\n"); + fprintf(stderr, " focusPorts - get sorted list of ports using utilization or error\n"); + fprintf(stderr, " values (from group buckets)\n"); + fprintf(stderr, " imageInfo - get information about a PA image (timestamps, etc.) -\n"); + fprintf(stderr, " requires -n (imgNum)\n"); + fprintf(stderr, " vfList - list of virtual fabrics\n"); + fprintf(stderr, " vfInfo - summary statistics of a virtual fabric - requires -V\n"); + fprintf(stderr, " option for vfName\n"); + fprintf(stderr, " vfConfig - configuration of a virtual fabric - requires -V option\n"); + fprintf(stderr, " for vfName\n"); + fprintf(stderr, " vfPortCounters - port counters of fabric port - requires -V (vfName), -l\n"); + fprintf(stderr, " (lid) and -P (port) options, -d (delta) is optional\n"); + fprintf(stderr, " vfFocusPorts - get sorted list of virtual fabric ports using\n"); + fprintf(stderr, " utilization or error values (from VF buckets) -\n"); + fprintf(stderr, " requires -V (vfname)\n"); + fprintf(stderr, " clrVfPortCounters - clear VF port counters of fabric port - requires -l\n"); + fprintf(stderr, " (lid), -P (port), -s (select), and -V (vfname) options\n"); + fprintf(stderr, "\n"); + fprintf(stderr, "Usage examples:\n"); + fprintf(stderr, " opapaquery -o classPortInfo\n"); + fprintf(stderr, " opapaquery -o groupList\n"); + fprintf(stderr, " opapaquery -o groupInfo -g All\n"); + fprintf(stderr, " opapaquery -o groupConfig -g All\n"); + fprintf(stderr, " opapaquery -o groupNodeInfo -g All -G \n"); + fprintf(stderr, " opapaquery -o groupNodeInfo -g All -D \n"); + fprintf(stderr, " opapaquery -o groupNodeInfo -g All -l 1 \n"); + fprintf(stderr, " opapaquery -o groupNodeInfo -g All -l 1 -G \n"); + fprintf(stderr, " opapaquery -o groupLinkInfo -g All\n"); + fprintf(stderr, " opapaquery -o groupLinkInfo -g All -l 1 -P 1\n"); + fprintf(stderr, " opapaquery -o groupLinkInfo -g All -l 1 -P 255\n"); + fprintf(stderr, " opapaquery -o portCounters -l 1 -P 1 -d 1\n"); + fprintf(stderr, " opapaquery -o portCounters -l 1 -P 1 -d 1 -n 0x20000000d02 -O 1\n"); + fprintf(stderr, " opapaquery -o portCounters -l 1 -P 1 -d 1 -j 13:30 -q 14:20\n"); + fprintf(stderr, " opapaquery -o clrPortCounters -l 1 -P 1 -s 0xC0000000\n"); + fprintf(stderr, " (clears XmitData & RcvData)\n"); + fprintf(stderr, " opapaquery -o clrAllPortCounters -s 0xC0000000\n"); + fprintf(stderr, " (clears XmitData & RcvData on all ports)\n"); + fprintf(stderr, " opapaquery -o pmConfig\n"); + fprintf(stderr, " opapaquery -o freezeImage -n 0x20000000d02\n"); + fprintf(stderr, " opapaquery -o releaseImage -n 0xd01\n"); + fprintf(stderr, " opapaquery -o renewImage -n 0xd01\n"); + fprintf(stderr, " opapaquery -o moveFreeze -n 0xd01 -m 0x20000000d02 -M -2\n"); + fprintf(stderr, " opapaquery -o focusPorts -g All -f integrity -S 0 -r 20\n"); + fprintf(stderr, " opapaquery -o focusPorts -g All -S 0 -r 20 -Z AND -Q integrity:ge:20 -Q bubbles:lt:10\n"); + fprintf(stderr, " opapaquery -o focusPorts -g All -f skippedport -S 0 -r 20\n"); + fprintf(stderr, " opapaquery -o imageInfo -n 0x20000000d02\n"); + fprintf(stderr, " opapaquery -o imageInfo -y \"1 hour ago\"\n"); + fprintf(stderr, " opapaquery -o vfList\n"); + fprintf(stderr, " opapaquery -o vfInfo -V Default\n"); + fprintf(stderr, " opapaquery -o vfConfig -V Default\n"); + fprintf(stderr, " opapaquery -o vfPortCounters -l 1 -P 1 -d 1 -V Default\n"); + fprintf(stderr, " opapaquery -o clrVfPortCounters -l 1 -P 1 -s 0xC0000000 -V Default\n"); + fprintf(stderr, " (clears VLXmitData & VLRcvData)\n"); + fprintf(stderr, " opapaquery -o vfFocusPorts -V Default -f integrity -S 0 -r 20\n"); + exit(2); +} + +/* SSL Paramters XML parse code */ +static void *sslParmsXmlParserStart(IXmlParserState_t *state, void *parent, const char **attr) +{ + struct omgt_ssl_params *sslParmsData = IXmlParserGetContext(state); + memset(sslParmsData, 0, sizeof(struct omgt_ssl_params)); + return sslParmsData; +} +static void sslParmsXmlParserEnd(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ +} +static IXML_FIELD sslSecurityFields[] = { + { tag:"SslSecurityEnabled", format:'u', IXML_FIELD_INFO(struct omgt_ssl_params, enable) }, + { tag:"SslSecurityEnable", format:'u', IXML_FIELD_INFO(struct omgt_ssl_params, enable) }, + { tag:"SslSecurityDir", format:'s', IXML_FIELD_INFO(struct omgt_ssl_params, directory) }, + { tag:"SslSecurityFFCertificate", format:'s', IXML_FIELD_INFO(struct omgt_ssl_params, certificate) }, + { tag:"SslSecurityFFPrivateKey", format:'s', IXML_FIELD_INFO(struct omgt_ssl_params, private_key) }, + { tag:"SslSecurityFFCaCertificate", format:'s', IXML_FIELD_INFO(struct omgt_ssl_params, ca_certificate) }, + { tag:"SslSecurityFFCertChainDepth", format:'u', IXML_FIELD_INFO(struct omgt_ssl_params, cert_chain_depth) }, + { tag:"SslSecurityFFDHParameters", format:'s', IXML_FIELD_INFO(struct omgt_ssl_params, dh_params) }, + { tag:"SslSecurityFFCaCRLEnabled", format:'u', IXML_FIELD_INFO(struct omgt_ssl_params, ca_crl_enable) }, + { tag:"SslSecurityFFCaCRL", format:'s', IXML_FIELD_INFO(struct omgt_ssl_params, ca_crl) }, + { NULL } +}; +static IXML_FIELD sslTopLevelFields[] = { + { tag:"SslSecurityParameters", format:'K', subfields:sslSecurityFields, start_func:sslParmsXmlParserStart, end_func:sslParmsXmlParserEnd }, // structure + { NULL } +}; +FSTATUS ParseSslParmsFile(const char *input_file, int g_verbose, struct omgt_ssl_params *sslParmsData) +{ + unsigned tags_found, fields_found; + const char *filename=input_file; + + if (strcmp(input_file, "-") == 0) { + filename="stdin"; + if (FSUCCESS != IXmlParseFile(stdin, "stdin", IXML_PARSER_FLAG_NONE, sslTopLevelFields, NULL, sslParmsData, NULL, NULL, &tags_found, &fields_found)) { + return FERROR; + } + } else { + if (FSUCCESS != IXmlParseInputFile(input_file, IXML_PARSER_FLAG_NONE, sslTopLevelFields, NULL, sslParmsData, NULL, NULL, &tags_found, &fields_found)) { + return FERROR; + } + } + if (tags_found != 1 || fields_found != 1) { + fprintf(stderr, "Warning: potentially inaccurate input '%s': found %u recognized top level tags, expected 1\n", filename, tags_found); + } + + return FSUCCESS; +} +/* END SSL Paramters XML parse code */ + +typedef struct OutputFocusMap { + char *string; + int32 focus; + } OutputFocusMap_t; + +OutputFocusMap_t OutputFocusTable[]= { + {"unexpclrport", STL_PA_SELECT_UNEXP_CLR_PORT }, // 0x00010101 + {"norespport", STL_PA_SELECT_NO_RESP_PORT }, // 0x00010102 + {"skippedport", STL_PA_SELECT_SKIPPED_PORT }, // 0x00010103 + {"utilhigh", STL_PA_SELECT_UTIL_HIGH }, // 0x00020001 + {"pktrate", STL_PA_SELECT_UTIL_PKTS_HIGH }, // 0x00020082 + {"utillow", STL_PA_SELECT_UTIL_LOW }, // 0x00020101 + {"integrity", STL_PA_SELECT_CATEGORY_INTEG }, // 0x00030001 + {"congestion", STL_PA_SELECT_CATEGORY_CONG }, // 0x00030002 + {"smacongestion", STL_PA_SELECT_CATEGORY_SMA_CONG }, // 0x00030003 + {"bubbles", STL_PA_SELECT_CATEGORY_BUBBLE }, // 0x00030004 + {"security" , STL_PA_SELECT_CATEGORY_SEC }, // 0x00030005 + {"routing", STL_PA_SELECT_CATEGORY_ROUT }, // 0x00030006 + {"vfutilhigh", STL_PA_SELECT_VF_UTIL_HIGH }, // 0x00020083 + {"vfpktrate", STL_PA_SELECT_VF_UTIL_PKTS_HIGH }, // 0x00020084 + {"vfutillow", STL_PA_SELECT_VF_UTIL_LOW }, // 0x00020102 + {"vfcongestion", STL_PA_SELECT_CATEGORY_VF_CONG }, // 0x00030007 + {"vfbubbles", STL_PA_SELECT_CATEGORY_VF_BUBBLE }, // 0x00030008 + { NULL, 0}, +}; + + +FSTATUS StringToFocus (int32 *value, const char* str) +{ + int i; + + i=0; + while (OutputFocusTable[i].string!=NULL) { + if (0 == strcmp(str,OutputFocusTable[i].string) ){ + *value = OutputFocusTable[i].focus; + return FSUCCESS; + } + else i++; + } + + return FERROR; +} + +void opapaquery_exit(FSTATUS status) +{ + if (g_portHandle) { + omgt_close_port(g_portHandle); + g_portHandle = NULL; + } + + fprintf(stderr, "opapaquery completed: %s\n", (status == FSUCCESS) ? "OK" : "FAILED"); + exit((status == FSUCCESS) ? 0 : 1); +} + +int main(int argc, char ** argv) +{ + FSTATUS fstatus; + int c, index; + uint8 hfi = 0; + uint16 port = 0; + char outputType[64]; + STL_LID tempLid; + uint8 temp8; + char tempstr[64]; + int queryType = Q_GETGROUPLIST; + int ms_timeout = OMGT_DEF_TIMEOUT_MS; + g_gotOutput = 1; + + PrintDestInitFile(&g_dest, stdout); + + while (-1 != (c = getopt_long(argc,argv, "vh:p:b:x:ET:o:g:G:l:P:d:D:Us:n:O:f:S:r:m:M:V:j:q:y:Z:Q:", options, &index))) + { + switch (c) + { + case 'v': + g_verbose++; + if (g_verbose > 2) umad_debug(g_verbose - 2); + break; + + case '$': + usage(); + break; + + case 'h': + if (FSUCCESS != StringToUint8(&hfi, optarg, NULL, 0, TRUE)) { + fprintf(stderr, "opapaquery: Invalid HFI Number: %s\n", optarg); + usage(); + } + g_isOOB = FALSE; + break; + case 'p': // port to issue query from + if (FSUCCESS != StringToUint16(&port, optarg, NULL, 0, TRUE)) { + fprintf(stderr, "opapaquery: Invalid Port Number: %s\n", optarg); + usage(); + } + break; + case '!': + if (FSUCCESS != StringToInt32(&ms_timeout, optarg, NULL, 0, TRUE)) { + fprintf(stderr, "opapaquery: Invalid timeout value: %s\n", optarg); + usage(); + } + break; + case 'b': // OOB address of FE + g_oob_address = optarg; + g_isOOB = TRUE; + break; + case 'E': // FE is ESM + g_isFEESM = TRUE; + g_isOOB = TRUE; + break; + case 'T': // FE Uses SSL + g_sslParmsFile = optarg; + g_isOOBSSL = TRUE; + g_isOOB = TRUE; + break; + case 'x': // Source GID + if (FSUCCESS != StringToGid(&g_src_gid.AsReg64s.H, &g_src_gid.AsReg64s.L, optarg, NULL, TRUE)) { + fprintf(stderr, "opapaquery: Invalid Source Gid: %s\n", optarg); + usage(); + } + break; + + case 'o': + memcpy(outputType, optarg, 64); + if ((queryType = getQueryType(outputType)) <= 0) { + fprintf(stderr, "opapaquery: Invalid Output Type: %s\n", outputType); + usage(); + } + g_gotOutput = 1; + break; + case 'g': + snprintf(g_groupName, STL_PM_GROUPNAMELEN, "%s", optarg); + g_gotGroup = 1; + break; + + case 'l': + if (FSUCCESS != StringToUint32(&tempLid, optarg, NULL, 0, TRUE) || tempLid == 0) { + fprintf(stderr, "opapaquery: Invalid Lid Number: %s\n", optarg); + usage(); + } + g_nodeLid = tempLid; + g_gotLid = TRUE; + break; + + case 'P': + if (FSUCCESS != StringToUint8(&temp8, optarg, NULL, 0, TRUE)) { + fprintf(stderr, "opapaquery: Invalid Port Number: %s\n", optarg); + usage(); + } + g_portNumber = temp8; + g_gotPort = TRUE; + break; + + case 'G': + if (FSUCCESS != StringToUint64(&g_nodeGuid, optarg, NULL, 0, TRUE) || g_nodeGuid == 0) { + fprintf(stderr, "opapaquery: Invalid GUID Number: %s\n", optarg); + usage(); + } + g_gotGUID = TRUE; + break; + + case 'D': + if(optarg[0] == '\0') { + fprintf(stderr,"Illegal node descriptor parameter: Empty String\n"); + usage(); + } + snprintf(g_nodeDesc, STL_PM_NODEDESCLEN, "%s", optarg); + g_gotNodeDesc = TRUE; + break; + + case 'd': + if (FSUCCESS != StringToUint32(&g_deltaFlag, optarg, NULL, 0, TRUE)) { + fprintf(stderr, "opapaquery: Invalid Delta Flag: %s\n", optarg); + usage(); + } + break; + + case 'j': + if (FSUCCESS != StringToDateTime(&g_beginTime, optarg)){ + fprintf(stderr, "opapaquery: Invalid Date/Time: %s\n", optarg); + usage(); + } + g_gotBegTime = TRUE; + break; + + case 'q': + if (FSUCCESS != StringToDateTime(&g_endTime, optarg)){ + fprintf(stderr, "opapaquery: Invalid Date/Time: %s\n", optarg); + usage(); + } + g_gotEndTime = TRUE; + break; + + case 'U': + g_userCntrsFlag = 1; + break; + + case 's': + if (FSUCCESS != StringToUint32(&g_selectFlag, optarg, NULL, 0, TRUE)) { + fprintf(stderr, "opapaquery: Invalid Select Flag: %s\n", optarg); + usage(); + } + g_gotSelect = TRUE; + break; + + case 'n': + if (FSUCCESS != StringToUint64(&g_imageNumber, optarg, NULL, 0, TRUE)) { + fprintf(stderr, "opapaquery: Invalid Image Number: %s\n", optarg); + usage(); + } + g_gotImgNum = TRUE; + break; + + case 'O': + if (FSUCCESS != StringToInt32(&g_imageOffset, optarg, NULL, 0, TRUE)) { + fprintf(stderr, "opapaquery: Invalid Image Offset: %s\n", optarg); + usage(); + } + g_gotImgOff = TRUE; + break; + + case 'y': + if (FSUCCESS != StringToDateTime(&g_imageTime, optarg)){ + fprintf(stderr, "opapaquery: Invalid Date/Time: %s\n", optarg); + usage(); + } + g_gotImgTime = TRUE; + break; + + case 'm': + if (FSUCCESS != StringToUint64(&g_moveImageNumber, optarg, NULL, 0, TRUE)) { + fprintf(stderr, "opapaquery: Invalid Move Image Number: %s\n", optarg); + usage(); + } + g_gotMoveImgNum = TRUE; + break; + + case 'M': + if (FSUCCESS != StringToInt32(&g_moveImageOffset, optarg, NULL, 0, TRUE)) { + fprintf(stderr, "opapaquery: Invalid Move Image Offset: %s\n", optarg); + usage(); + } + g_gotMoveImgOff = TRUE; + break; + + case 'f': + if (FSUCCESS != StringToFocus (&g_focus, optarg)) { + fprintf(stderr, "opapaquery: Invalid Focus Select Parameter: %s\n", optarg); + usage(); + } + g_gotFocus = TRUE; + break; + + case 'S': + if (FSUCCESS != StringToInt32(&g_start, optarg, NULL, 0, TRUE)) { + fprintf(stderr, "opapaquery: Invalid Start Number: %s\n", optarg); + usage(); + } + g_gotStart = TRUE; + break; + + case 'r': + if (FSUCCESS != StringToInt32(&g_range, optarg, NULL, 0, TRUE)) { + fprintf(stderr, "opapaquery: Invalid Range Number: %s\n", optarg); + usage(); + } + g_gotRange = TRUE; + break; + + case 'Z': + if (strcasecmp(optarg, "and") == 0) + g_logicalOperator = FOCUS_PORTS_LOGICAL_OPERATOR_AND; + else if (strcasecmp(optarg, "or") == 0) + g_logicalOperator = FOCUS_PORTS_LOGICAL_OPERATOR_OR; + else { + fprintf(stderr, "opapaquery: Invalid Logical Operator value: %s\n", optarg); + usage(); + } + g_gotLogicalOperator = TRUE; + break; + + case 'Q': + + StringCopy(tempstr, optarg, sizeof(tempstr)); + + if (tupleID >= MAX_NUM_FOCUS_PORT_TUPLES) { + fprintf(stderr, "opapaquery: Tuple count exceeded. Limited to %d tuples\n", MAX_NUM_FOCUS_PORT_TUPLES); + usage(); + } + + tuple[tupleID].select = 0; + tuple[tupleID].comparator = FOCUS_PORTS_COMPARATOR_INVALID; + + if (FSUCCESS != StringToTuple(&tuple[tupleID].select, &tuple[tupleID].comparator, &tuple[tupleID].argument, optarg, NULL)) { + fprintf(stderr, "opapaquery: Invalid Tuple value: %s\n", tempstr); + usage(); + } + g_gotTuple = TRUE; + tupleID++; + break; + + + case 'V': + snprintf(g_vfName, STL_PM_VFNAMELEN, "%s", optarg); + g_gotvfName = TRUE; + break; + + default: + fprintf(stderr, "opapaquery: Invalid Option %c\n", c); + usage(); + break; + } + } /* end while */ + + if (optind < argc) + { + fprintf(stderr, "opapaquery: invalid argument %s\n", argv[optind]); + usage(); + } + + // Check parameter consistency + + if ((queryType == Q_GETGROUPINFO) && (!g_gotGroup)) { + fprintf(stderr, "opapaquery: Must provide a group name with output type groupInfo\n"); + usage(); + } + + if ((queryType == Q_GETGROUPCONFIG) && (!g_gotGroup)) { + fprintf(stderr, "opapaquery: Must provide a group name with output type groupConfig\n"); + usage(); + } + + if (queryType == Q_GETFOCUSPORTS) { + if ((!g_gotGroup) || (g_gotFocus == g_gotTuple) || (!g_gotRange) || (!g_gotStart)) { + fprintf(stderr, "opapaquery: Must provide a group name(g), focus(f) or tuple(Q), range(r) and start(S) \n"); + fprintf(stderr, " with output type focusPorts. Image Number(n) and Image Offset(O) are optional.\n"); + usage(); + } + else if (g_deltaFlag || g_gotLid || g_gotPort || g_gotSelect || g_gotMoveImgNum || g_gotMoveImgOff ||g_userCntrsFlag || g_gotvfName) + fprintf(stderr, "opapaquery: for the selected output type only -g, -f or -Q, -r and -S options are required.\n"); + fprintf(stderr, "Ignoring rest..\n"); + + if (!g_gotLogicalOperator) { + if (tupleID > 1) { + fprintf(stderr, "opapaquery: Must supply a logical operator(Z)\n"); + usage(); + } + } + } + + if ((queryType == Q_GETGROUPNODEINFO) && (!g_gotGroup)) { + fprintf(stderr, "opapaquery: Must provide a group name with output type groupNodeInfo \n"); + usage(); + } + + if ((queryType == Q_GETGROUPLINKINFO) && (!g_gotGroup)) { + fprintf(stderr, "opapaquery: Must provide a group name with output type groupLinkInfo \n"); + usage(); + } + + if (queryType == Q_GETVFFOCUSPORTS) { + if ((!g_gotvfName) || (!g_gotFocus) || (!g_gotRange) || (!g_gotStart)) { + fprintf(stderr, "opapaquery: Must provide a vf_name(V), focus(f), range(r) and start(S) \n"); + fprintf(stderr, " with output type VFfocusPorts. Image Number and Image Offset are optional.\n"); + usage(); + } + else if (g_deltaFlag || g_gotLid || g_gotPort || g_gotSelect || g_gotMoveImgNum || + g_gotMoveImgOff ||g_userCntrsFlag || g_gotGroup) { + fprintf(stderr, "opapaquery: for the selected output type only -V, -f, -r and -S options are required.\n"); + fprintf(stderr, "Ignoring rest..\n"); + } + } + + if ((queryType == Q_GETPORTCOUNTERS) && ((!g_gotLid) || (!g_gotPort))) { + fprintf(stderr, "opapaquery: Must provide a lid and port with output type portCounters\n"); + usage(); + } + + if ((queryType == Q_CLRPORTCOUNTERS) && ((!g_gotLid) || (!g_gotPort) || (!g_gotSelect))) { + fprintf(stderr, "opapaquery: Must provide a lid, port, and select flag with output type clrPortCounters\n"); + usage(); + } + + if ((queryType == Q_CLRALLPORTCOUNTERS) && !g_gotSelect) { + fprintf(stderr, "opapaquery: Must provide a select flag with output type clrAllPortCounters\n"); + usage(); + } + + if ((((queryType == Q_RELEASEIMAGE) || (queryType == Q_RENEWIMAGE) || (queryType == Q_MOVEFREEZE)) && + (!g_gotImgNum))) { + fprintf(stderr, "opapaquery: Must provide an imgNum with releaseImage/renewImage/moveFreeze\n"); + usage(); + } + + if ((queryType == Q_FREEZEIMAGE) && !(g_gotImgNum || g_gotImgTime)){ + fprintf(stderr, "opapaquery: Must provide an imgNum or imgTime with freezeImage\n"); + usage(); + } + + if ((queryType == Q_MOVEFREEZE) && !g_gotMoveImgNum) { + fprintf(stderr, "opapaquery: Must provide a moveImgNum with output type moveFreeze\n"); + usage(); + } + + if (g_deltaFlag > 1) { + fprintf(stderr, "opapaquery: delta value must be 0 or 1\n"); + usage(); + } + + if (g_userCntrsFlag && (g_deltaFlag || g_gotImgOff)) { + fprintf(stderr, "opapaquery: delta value and image offset must be 0 when querying User Counters\n"); + usage(); + } + + if (g_gotBegTime && g_gotEndTime && (g_beginTime >= g_endTime)){ + fprintf(stderr, "opapaquery: begin time must be before end time\n"); + usage(); + } + + if ((queryType == Q_GETVFINFO) && (!g_gotvfName)) { + fprintf(stderr, "opapaquery: Must provide a VF name with output type vfInfo\n"); + usage(); + } + + if ((queryType == Q_GETVFCONFIG) && (!g_gotvfName)) { + fprintf(stderr, "opapaquery: Must provide a VF name with output type vfConfig\n"); + usage(); + } + + if ((queryType == Q_GETVFPORTCOUNTERS) && (!g_gotvfName)) { + fprintf(stderr, "opapaquery: Must provide a VF name with output type vfPortCounters\n"); + usage(); + } + + if ((queryType == Q_GETVFPORTCOUNTERS) && ((!g_gotLid) || (!g_gotPort))) { + fprintf(stderr, "opapaquery: Must provide a lid and port with output type vfPortCounters\n"); + usage(); + } + + if ((queryType == Q_CLRVFPORTCOUNTERS) && (!g_gotvfName)) { + fprintf(stderr, "opapaquery: Must provide a VF name with output type clrVfPortCounters\n"); + usage(); + } + + if ((queryType == Q_CLRVFPORTCOUNTERS) && ((!g_gotLid) || (!g_gotPort) || (!g_gotSelect))) { + fprintf(stderr, "opapaquery: Must provide a lid, port, and select flag with output type clrVfPortCounters\n"); + usage(); + } + + if (queryType == Q_GETGROUPLIST || queryType == Q_GETVFLIST) { + // only certain options are valid. Rest are ignored. + if (g_deltaFlag || g_gotGroup || g_gotLid || g_gotPort || g_gotSelect || g_gotGUID || + g_gotMoveImgNum || g_gotMoveImgOff || g_gotNodeDesc || + g_gotFocus || g_gotStart || g_gotRange || g_userCntrsFlag || g_gotvfName + || g_gotBegTime || g_gotEndTime) { + fprintf(stderr, "opapaquery: for the selected output type only -[hpvnOy] options are valid. Ignoring rest..\n"); + } + } + if (queryType == Q_GETPMCONFIG || queryType == Q_CLASSPORTINFO) { + // only -h, -p and -v options are valid. Rest are ignored. + if (g_deltaFlag || g_gotGroup || g_gotLid || g_gotPort || g_gotSelect || g_gotGUID || + g_gotImgNum || g_gotImgOff || g_gotMoveImgNum || g_gotMoveImgOff || g_gotNodeDesc || + g_gotFocus || g_gotStart || g_gotRange || g_userCntrsFlag || g_gotvfName + || g_gotImgTime || g_gotBegTime || g_gotEndTime) { + fprintf(stderr, "opapaquery: for the selected output type only -h, -p and -v options are valid. Ignoring rest..\n"); + } + } + else if (queryType == Q_GETGROUPINFO || queryType == Q_GETGROUPCONFIG) { + // only certain options are valid. Rest are ignored. + if (g_deltaFlag || g_gotLid || g_gotPort || g_gotSelect || g_gotGUID || + g_gotMoveImgNum || g_gotMoveImgOff || g_gotFocus || g_gotStart || g_gotNodeDesc || + g_gotRange || g_userCntrsFlag || g_gotvfName || + g_gotBegTime || g_gotEndTime) { + fprintf(stderr, "opapaquery: for the selected output type only -[hpvgnOy] options are valid. Ignoring rest..\n"); + } + } + else if (queryType == Q_GETVFINFO || queryType == Q_GETVFCONFIG) { + // only certain options are valid. Rest are ignored. + if (g_deltaFlag || g_gotGroup || g_gotLid || g_gotPort || g_gotSelect || g_gotNodeDesc || + g_gotMoveImgNum || g_gotMoveImgOff || g_gotFocus || g_gotStart || g_gotGUID || + g_gotRange || g_userCntrsFlag || g_gotBegTime || + g_gotEndTime) { + fprintf(stderr, "opapaquery: for the selected output type only -[hpvnOVy] options are valid. Ignoring rest..\n"); + } + } + else if (queryType == Q_GETGROUPNODEINFO) { + // only certain options are valid. Rest are ignored. + if (g_deltaFlag || g_gotSelect || g_gotMoveImgNum || g_gotMoveImgOff || g_gotPort || + g_gotvfName || g_gotFocus || g_gotStart || g_gotRange || g_userCntrsFlag || + g_gotBegTime || g_gotEndTime) { + fprintf(stderr, "opapaquery: for the selected output type only -[hpvlngDGOy] options are valid. Ignoring rest..\n"); + } + } + else if (queryType == Q_GETGROUPLINKINFO) { + // only certain options are valid. Rest are ignored. + if (g_deltaFlag || g_gotSelect || g_gotMoveImgNum || g_gotMoveImgOff || g_gotGUID || + g_gotvfName || g_gotFocus || g_gotStart || g_gotRange || g_userCntrsFlag || g_gotNodeDesc || + g_gotBegTime || g_gotEndTime) { + fprintf(stderr, "opapaquery: for the selected output type only -[hpvlngPOy] options are valid. Ignoring rest..\n"); + } + if (g_gotPort && !g_gotLid) { + fprintf(stderr, "opapaquery: -l (lid) also needed with -P (port). Ignoring -P\n"); + } + } + + /* Open omgt_port */ + struct omgt_params params = { + .debug_file = (g_verbose > 1 ? stderr : NULL), + .error_file = stderr + }; + if (g_isOOB) { + if (g_sslParmsFile) { + if ((fstatus = ParseSslParmsFile(g_sslParmsFile, g_verbose, &g_ssl_params)) != FSUCCESS) { + fprintf(stderr, "opapaquery: Must provide a valid SSL/TLS parameters XML file: %s\n", g_sslParmsFile); + usage(); + } + } + struct omgt_oob_input oob_input = { + .host = g_oob_address, + .port = (port ? port : g_oob_port), + .is_esm_fe = g_isFEESM, + .ssl_params = g_ssl_params + }; + fstatus = omgt_oob_connect(&g_portHandle, &oob_input, ¶ms); + if (fstatus != 0) { + fprintf(stderr, "opapaquery: Failed to open connection to FE %s:%u: %s\n", + oob_input.host, oob_input.port, omgt_status_totext(fstatus)); + opapaquery_exit(fstatus); + } + } else { + int pa_service_state; + fstatus = omgt_open_port_by_num(&g_portHandle, (int)hfi, port, ¶ms); + if (fstatus == OMGT_STATUS_SUCCESS) { + fstatus = omgt_port_get_pa_service_state(g_portHandle, &pa_service_state, OMGT_REFRESH_SERVICE_BAD_STATE); + if (fstatus == OMGT_STATUS_SUCCESS) { + if (pa_service_state != OMGT_SERVICE_STATE_OPERATIONAL) { + fprintf(stderr, "opapaquery: failed to connect, PA Service State is Not Operational: %s (%d)\n", + omgt_service_state_totext(pa_service_state), pa_service_state); + opapaquery_exit(FUNAVAILABLE); + } + } else { + fprintf(stderr, "opapaquery: failed to get and refresh pa service state: %u\n", fstatus); + opapaquery_exit(fstatus); + } + } else { + fprintf(stderr, "opapaquery: failed to open hfi %d, port %d: %u\n", hfi, port, fstatus); + opapaquery_exit(fstatus); + } + } + + if (g_verbose) + set_opapaquery_debug(g_portHandle); + + //set timeout for PA operations + omgt_set_timeout(g_portHandle, ms_timeout); + + // verify PA has necessary capabilities + STL_CLASS_PORT_INFO *portInfo; + if ((portInfo = GetClassPortInfo(g_portHandle)) == NULL){ + fprintf(stderr, "opapaquery: failed to determine PA capabilities\n"); + opapaquery_exit(FERROR); + } + STL_PA_CLASS_PORT_INFO_CAPABILITY_MASK paCap; + memcpy(&paCap, &portInfo->CapMask, sizeof(STL_PA_CLASS_PORT_INFO_CAPABILITY_MASK)); + //if trying to query by time, check if feature available + if (g_imageTime || g_beginTime || g_endTime){ + if (!(paCap.s.IsAbsTimeQuerySupported)){ + fprintf(stderr, "PA does not support time queries\n"); + MemoryDeallocate(portInfo); + opapaquery_exit(FERROR); + } + } + + //if trying to query extended focus port selects, check if feature is available + if (g_focus == STL_PA_SELECT_UNEXP_CLR_PORT || g_focus == STL_PA_SELECT_NO_RESP_PORT || + g_focus == STL_PA_SELECT_SKIPPED_PORT || g_gotTuple){ + if (!(paCap.s.IsExtFocusTypesSupported)){ + fprintf(stderr, "PA does not support extended focus ports\n"); + MemoryDeallocate(portInfo); + opapaquery_exit(FERROR); + } + } + + //if querying for nodeinfo and linkinfo check if feature is available + if (queryType == Q_GETGROUPNODEINFO || queryType == Q_GETGROUPLINKINFO){ + if (!(paCap.s.IsTopologyInfoSupported)){ + fprintf(stderr, "PA does not support Topology Information from PM\n"); + MemoryDeallocate(portInfo); + opapaquery_exit(FERROR); + } + } + if (queryType == Q_GETGROUPLIST || queryType == Q_GETVFLIST) { + if (!paCap.s.IsPerImageListsSupported && (g_gotImgNum || g_gotImgOff || g_gotImgTime)) { + fprintf(stderr, "PA does not support Getting historical (Per Image) Group/VF List\n"); + MemoryDeallocate(portInfo); + opapaquery_exit(FERROR); + } + } + + if (IS_VF_FOCUS_SELECT(g_focus)) { + // verify PM config for VL counters + if ((fstatus = GetPMConfig(g_portHandle, &g_pmConfigData)) == FERROR){ + fprintf(stderr, "opapaquery: failed to get GetPMConfig \n"); + MemoryDeallocate(portInfo); + opapaquery_exit(FERROR); + } + g_valid_pm_config_exists = TRUE; + //Check if VF level Focus selects are supported + if (!(paCap.s.IsVFFocusTypesSupported) || + !(g_pmConfigData.pmFlags & STL_PM_PROCESS_VL_COUNTERS)){ + fprintf(stderr, "PA does not support VF Focus selects \n"); + MemoryDeallocate(portInfo); + opapaquery_exit(FERROR); + } + } + + switch (queryType) { + case Q_GETGROUPLIST: + if (paCap.s.IsPerImageListsSupported) { + fstatus = GetGroupList2(g_portHandle, g_imageNumber, g_imageOffset, g_imageTime); + } else { + fstatus = GetGroupList(g_portHandle); + } + if (fstatus != FSUCCESS) { + fprintf(stderr, "opapaquery: failed to get group list\n"); + } + break; + + case Q_GETGROUPINFO: + fstatus = GetGroupInfo(g_portHandle, g_groupName, g_imageNumber, g_imageOffset, g_imageTime); + if (fstatus != FSUCCESS) { + fprintf(stderr, "opapaquery: failed to get group info\n"); + } + break; + + case Q_GETGROUPCONFIG: + fstatus = GetGroupConfig(g_portHandle, g_groupName, g_imageNumber, g_imageOffset, g_imageTime); + if (fstatus != FSUCCESS) { + fprintf(stderr, "opapaquery: failed to get group configuration\n"); + } + break; + + case Q_GETGROUPNODEINFO: + fstatus = GetGroupNodeInfo(g_portHandle, g_groupName, g_nodeLid, g_nodeGuid, g_nodeDesc, g_imageNumber, g_imageOffset, g_imageTime); + if (fstatus != FSUCCESS) { + fprintf(stderr, "opapaquery: failed to get group node info\n"); + } + break; + + case Q_GETGROUPLINKINFO: + fstatus = GetGroupLinkInfo(g_portHandle, g_groupName, g_nodeLid, g_portNumber, g_imageNumber, g_imageOffset, g_imageTime); + if (fstatus != FSUCCESS) { + fprintf(stderr, "opapaquery: failed to get group link info\n"); + } + break; + + + case Q_GETPORTCOUNTERS: + fstatus = GetPortCounters(g_portHandle, g_nodeLid, g_portNumber, g_deltaFlag, g_userCntrsFlag, g_imageNumber, g_imageOffset, g_beginTime, g_endTime); + if (fstatus != FSUCCESS) { + fprintf(stderr, "opapaquery: failed to get port counters\n"); + } + break; + + case Q_CLRPORTCOUNTERS: + fstatus = ClrPortCounters(g_portHandle, g_nodeLid, g_portNumber, g_selectFlag); + if (fstatus != FSUCCESS) { + fprintf(stderr, "opapaquery: failed to clear port counters\n"); + } + break; + + case Q_CLRALLPORTCOUNTERS: + fstatus = ClrAllPortCounters(g_portHandle, g_selectFlag); + if (fstatus != FSUCCESS) { + fprintf(stderr, "opapaquery: failed to clear all port counters\n"); + } + break; + + case Q_GETPMCONFIG: + if (!g_valid_pm_config_exists) { + fstatus = GetPMConfig(g_portHandle, &g_pmConfigData); + if (fstatus != FSUCCESS) { + fprintf(stderr, "opapaquery: failed to get PM configuration\n"); + break; + } + } + PrintStlPMConfig(&g_dest, 0, &g_pmConfigData); + fstatus = FSUCCESS; + break; + + case Q_FREEZEIMAGE: + fstatus = FreezeImage(g_portHandle, g_imageNumber, g_imageOffset, g_imageTime); + if (fstatus != FSUCCESS) { + fprintf(stderr, "opapaquery: failed to freeze image\n"); + } + break; + + case Q_RELEASEIMAGE: + fstatus = ReleaseImage(g_portHandle, g_imageNumber, g_imageOffset); + if (fstatus != FSUCCESS) { + fprintf(stderr, "opapaquery: failed to release image\n"); + } + break; + + case Q_RENEWIMAGE: + fstatus = RenewImage(g_portHandle, g_imageNumber, g_imageOffset); + if (fstatus != FSUCCESS) { + fprintf(stderr, "opapaquery: failed to renew image\n"); + } + break; + + case Q_MOVEFREEZE: + fstatus = MoveFreeze(g_portHandle, g_imageNumber, g_imageOffset, g_moveImageNumber, g_moveImageOffset); + if (fstatus != FSUCCESS) { + fprintf(stderr, "opapaquery: failed to move freeze image\n"); + } + break; + + case Q_GETFOCUSPORTS: + fstatus = GetFocusPorts(g_portHandle, g_groupName, g_focus, g_start, g_range, g_imageNumber, g_imageOffset, g_imageTime, g_gotTuple ? tuple:NULL, g_logicalOperator); + if (fstatus != FSUCCESS) { + fprintf(stderr, "opapaquery: failed to get focus ports\n"); + } + break; + + case Q_GETIMAGECONFIG: + fstatus = GetImageInfo(g_portHandle, g_imageNumber, g_imageOffset, g_imageTime); + if (fstatus != FSUCCESS) { + fprintf(stderr, "opapaquery: failed to get image info\n"); + } + break; + + case Q_CLASSPORTINFO: + PrintStlClassPortInfo(&g_dest, 0, portInfo, MCLASS_VFI_PM); + MemoryDeallocate(portInfo); + fstatus = FSUCCESS; + break; + + case Q_GETVFLIST: + if (paCap.s.IsPerImageListsSupported) { + fstatus = GetVFList2(g_portHandle, g_imageNumber, g_imageOffset, g_imageTime); + } else { + fstatus = GetVFList(g_portHandle); + } + if (fstatus != FSUCCESS) { + fprintf(stderr, "opapaquery: failed to get vf list\n"); + } + break; + + case Q_GETVFINFO: + fstatus = GetVFInfo(g_portHandle, g_vfName, g_imageNumber, g_imageOffset, g_imageTime); + if (fstatus != FSUCCESS) { + fprintf(stderr, "opapaquery: failed to get VF info\n"); + } + break; + case Q_GETVFCONFIG: + fstatus = GetVFConfig(g_portHandle, g_vfName, g_imageNumber, g_imageOffset, g_imageTime); + if (fstatus != FSUCCESS) { + fprintf(stderr, "opapaquery: failed to get vf configuration\n"); + } + break; + + case Q_GETVFPORTCOUNTERS: + fstatus = GetVFPortCounters(g_portHandle, g_nodeLid, g_portNumber, g_deltaFlag, g_userCntrsFlag, g_vfName, g_imageNumber, g_imageOffset, g_beginTime, g_endTime); + if (fstatus != FSUCCESS) { + fprintf(stderr, "opapaquery: failed to get vf port counters\n"); + } + break; + + case Q_CLRVFPORTCOUNTERS: + fstatus = ClrVFPortCounters(g_portHandle, g_nodeLid, g_portNumber, g_selectFlag, g_vfName); + if (fstatus != FSUCCESS) { + fprintf(stderr, "opapaquery: failed to clear vf port counters\n"); + } + break; + + case Q_GETVFFOCUSPORTS: + fstatus = GetVFFocusPorts(g_portHandle, g_vfName, g_focus, g_start, g_range, g_imageNumber, g_imageOffset, g_imageTime); + if (fstatus != FSUCCESS) { + fprintf(stderr, "opapaquery: failed to get VF focus ports\n"); + } + break; + + default: + break; + } + opapaquery_exit(fstatus); + //shouldn't reach here + exit(-1); +} diff --git a/IbaTools/opareport/Makefile b/IbaTools/opareport/Makefile new file mode 100644 index 0000000..b4f9228 --- /dev/null +++ b/IbaTools/opareport/Makefile @@ -0,0 +1,168 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** +# Makefile for opareport + +# Include Make Control Settings +include $(TL_DIR)/$(PROJ_FILE_DIR)/Makesettings.project + +#=============================================================================# +# Definitions: +#-----------------------------------------------------------------------------# + +# Name of SubProjects +DS_SUBPROJECTS = +# name of executable or downloadable image +EXECUTABLE = $(BUILDDIR)/opareport$(EXE_SUFFIX) +# list of sub directories to build +DIRS = +# C files (.c) +CFILES = \ + verify.c \ + opareport.c \ + # Add more c files here +# C++ files (.cpp) +CCFILES = \ + # Add more cpp files here +# lex files (.lex) +LFILES = \ + # Add more lex files here +# archive library files (basename, $ARFILES will add MOD_LIB_DIR/prefix and suffix) +LIBFILES= +# Windows Resource Files (.rc) +RSCFILES = +# Windows IDL File (.idl) +IDLFILE = +# Windows Linker Module Definitions (.def) file for dll's +DEFFILE = +# targets to build during INCLUDES phase (add public includes here) +INCLUDE_TARGETS = \ + # Add more h hpp files here +# Non-compiled files +MISC_FILES = +# all source files +SOURCES = $(CFILES) $(CCFILES) $(LFILES) $(RSCFILES) $(IDLFILE) +# Source files to include in DSP File +DSP_SOURCES = $(INCLUDE_TARGETS) $(SOURCES) $(MISC_FILES) \ + $(RSCFILES) $(DEFFILE) $(MAKEFILE) +# all object files +OBJECTS = $(CFILES:.c=$(OBJ_SUFFIX)) $(CCFILES:.cpp=$(OBJ_SUFFIX)) \ + $(LFILES:.lex=$(OBJ_SUFFIX)) +RSCOBJECTS = $(RSCFILES:.rc=$(RES_SUFFIX)) +# targets to build during LIBS phase +LIB_TARGETS_IMPLIB = +LIB_TARGETS_ARLIB = # $(LIB_PREFIX)ResourceTest$(ARLIB_SUFFIX) +LIB_TARGETS_EXP = $(LIB_TARGETS_IMPLIB:$(ARLIB_SUFFIX)=$(EXP_SUFFIX)) +LIB_TARGETS_MISC = +# targets to build during CMDS phase +CMD_TARGETS_SHLIB = +CMD_TARGETS_EXE = $(EXECUTABLE) +CMD_TARGETS_MISC = opareports +# files to remove during clean phase +CLEAN_TARGETS_MISC = +CLEAN_TARGETS = $(OBJECTS) $(RSCOBJECTS) $(IDL_TARGETS) $(CLEAN_TARGETS_MISC) +# other files to remove during clobber phase +CLOBBER_TARGETS_MISC= +# sub-directory to install to within bin +BIN_SUBDIR = +# sub-directory to install to within include +INCLUDE_SUBDIR = + +# Additional Settings +#CLOCALDEBUG = User defined C debugging compilation flags [Empty] +#CCLOCALDEBUG = User defined C++ debugging compilation flags [Empty] +#CLOCAL = User defined C flags for compiling [Empty] +#CCLOCAL = User defined C++ flags for compiling [Empty] +#BSCLOCAL = User flags for Browse File Builder [Empty] +#DEPENDLOCAL = user defined makedepend flags [Empty] +#LINTLOCAL = User defined lint flags [Empty] +#LOCAL_INCLUDE_DIRS = User include directories to search for C/C++ headers [Empty] +#LDLOCAL = User defined C flags for linking [Empty] +#IMPLIBLOCAL = User flags for Object Lirary Manager [Empty] +#MIDLLOCAL = User flags for IDL compiler [Empty] +#RSCLOCAL = User flags for resource compiler [Empty] +#LOCALDEPLIBS = User libraries to include in dependencies [Empty] +#LOCALLIBS = User libraries to use when linking [Empty] +# (in addition to LOCALDEPLIBS) +#LOCAL_LIB_DIRS = User library directories for libpaths [Empty] + +CLOCAL=$(CIBACCESS) $(CPIE) +LOCAL_INCLUDE_DIRS= +ifeq "$(IB_STACK)" "IBACCESS" +LOCALDEPLIBS=$(IBACCESS_USER_LIBS) Xml Topology IbPrint +LOCALLIBS=m +LOCAL_LIB_DIRS= $(IBACCESS_USER_LIB_DIRS) +else +LOCALDEPLIBS=$(IBACCESS_USER_LIBS) Xml Topology opamgt-priv IbPrint +LOCALLIBS=$(OPENIB_USER_LIBS) m rt +LOCAL_LIB_DIRS=$(OPENIB_USER_LIB_DIRS) $(IBACCESS_USER_LIB_DIRS) +endif + +ifneq "$(BUILD_TARGET_OS)" "VXWORKS" +LOCALLIBS+= expat +endif + +# Include Make Rules definitions and rules +include $(TL_DIR)/IbaTools/Makerules.module + +#=============================================================================# +# Overrides: +#-----------------------------------------------------------------------------# +#CCOPT = # C++ optimization flags, default lets build config decide +#COPT = # C optimization flags, default lets build config decide +#SUBSYSTEM = Subsystem to build for (none, console or windows) [none] +# (Windows Only) +#USEMFC = How Windows MFC should be used (none, static, shared, no_mfc) [none] +# (Windows Only) +#=============================================================================# + +#=============================================================================# +# Rules: +#-----------------------------------------------------------------------------# +# process Sub-directories +include $(TL_DIR)/Makerules/Maketargets.toplevel + +# build cmds and libs +include $(TL_DIR)/Makerules/Maketargets.build + +# install for includes, libs and cmds phases +include $(TL_DIR)/Makerules/Maketargets.install + +# install for stage phase +#include $(TL_DIR)/Makerules/Maketargets.stage +STAGE:: + $(VS)$(STAGE_INSTALL) $(STAGE_INSTALL_DIR_OPT) $(PROJ_STAGE_FASTFABRIC_DIR) $(EXECUTABLE) $(CMD_TARGETS_MISC) + +# Unit test execution +#include $(TL_DIR)/Makerules/Maketargets.runtest + +#=============================================================================# + +#=============================================================================# +# DO NOT DELETE THIS LINE -- make depend depends on it. +#=============================================================================# diff --git a/IbaTools/opareport/README b/IbaTools/opareport/README new file mode 100644 index 0000000..eacfa03 --- /dev/null +++ b/IbaTools/opareport/README @@ -0,0 +1,3 @@ +[ICS VERSION STRING: unknown] + +Query SA and individual node PMAs to construct a topology and error report diff --git a/IbaTools/opareport/badtop.patch b/IbaTools/opareport/badtop.patch new file mode 100644 index 0000000..994fa8b --- /dev/null +++ b/IbaTools/opareport/badtop.patch @@ -0,0 +1,144 @@ +Patch to create a badtop.xml from a good top.xml +top.xml is from a fabric_sim run of -n 50 +this simply adds a few missing objects +--- /nfs/site/home/tmrimmer/top.xml 2016-10-16 15:19:28.468194576 -0400 ++++ /nfs/site/home/tmrimmer/badtop.xml 2016-10-24 17:02:34.204054360 -0400 +@@ -3,11 +3,25 @@ + + + 51 ++ ++ 0x0002b30101555555 ++ FI ++ 1 ++ MISSING_FI ++ MISSING_NODE ++ ++ ++ 0x0002b30101666666 ++ FI ++ 1 ++ MISSING_FI2 ++ + + 0x0002b30101000000 + FI + 1 + SQUIRREL_STL_HFI0 ++ Valid Node + + + 0x0002b30101000001 +@@ -312,6 +326,18 @@ + + + 6 ++ ++ 0x0002b30102555555 ++ SW ++ 2 ++ MISSING_SW ++ ++ ++ 0x0002b30102666666 ++ SW ++ 2 ++ MISSING_SW2 ++ + + 0x0002b30102000000 + SW +@@ -361,14 +387,85 @@ + FI + 1 + ++ ++ 0x0011750101555555 ++ MISSING_FI ++ 1 ++ 0x0011750101555555 ++ FI ++ 1 ++ MISSING ++ ++ ++ 0x0011750101666666 ++ MISSING_FI2 ++ 1 ++ 0x0011750101666666 ++ FI ++ 1 ++ MISSING2 ++ + + + + 147 ++ ++ 25g ++ 2048 ++ 0 ++ ++ MISSING_LABEL ++ MISSING_DETAILS ++ MISSLEN ++ ++ MISSING_LDETAILS ++ ++ 0x0002b30101555555 ++ 0x0002b30101555555 ++ 1 ++ FI ++ 1 ++ MISSING_FI ++ MISSING_PORT ++ ++ ++ 0x0002b30102555555 ++ 1 ++ SW ++ 2 ++ MISSING_SW ++ ++ ++ ++ 100g ++ 16 ++ 0 ++ ++ 0x0002b30101666666 ++ 0x0002b30101666666 ++ 1 ++ FI ++ 1 ++ MISSING_FI2 ++ ++ ++ 0x0002b30102666666 ++ 1 ++ SW ++ 2 ++ MISSING_SW2 ++ ++ + + 100g + 16 + 0 ++ ++ ValidLabel ++ ValidDetails ++ ValidLen ++ ++ ValidLink + + 0x0002b30101000000 + 0x0002b30101000000 +@@ -376,6 +473,7 @@ + FI + 1 + SQUIRREL_STL_HFI0 ++ ValidPort + + + 0x0002b30102000000 diff --git a/IbaTools/opareport/doreport.sh b/IbaTools/opareport/doreport.sh new file mode 100644 index 0000000..f55c4e2 --- /dev/null +++ b/IbaTools/opareport/doreport.sh @@ -0,0 +1,402 @@ +#!/bin/bash +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] + +# for queries we need 2 valid guids and a node description in the fabric +# for ease, guids can be specified as the last 6 digits of a SilverStorm Guid +# for a node in the fabric. or you can edit the assignments below appropriately +#OPA_REPORT='/usr/sbin/opareport -X snap.xml' +OPA_REPORT='/usr/sbin/opareport' +if [ "$1" = "" ] +then + nodedesc=SQUIRREL_STL_HFI1 +else + nodedesc="$1" +fi +if [ "$2" = "" ] +then + nodedesc2=SQUIRREL_STL_HFI2 +else + nodedesc2="$2" +fi +#if [ "$3" = "" ] +#then +# ioudesc='FVIC in Chassis 0x00117501da000159, Slot 8' +#else +# ioudesc="$3" +#fi +# to make this easier to use, we trust saquery and opareport a little +nodeguid=`opasaquery -d "$nodedesc" -o nodeguid|head -1 2>/dev/null` +sysguid=`opasaquery -d "$nodedesc" -o systemguid|head -1 2>/dev/null` +portguid=`opasaquery -d "$nodedesc" -o portguid|head -1 2>/dev/null` +nodepat="`echo "$nodedesc"|cut -c1-$(( $(echo -n "$nodedesc"|wc -c) - 2))`*" +nodepatb="*`echo "$nodedesc"|cut -c3-100`" +nodepatc="*`echo "$nodedesc"|cut -c3-$(( $(echo -n "$nodedesc"|wc -c) - 2))`*" + +nodeguid2=`opasaquery -d "$nodedesc2" -o nodeguid|head -1 2>/dev/null` +portguid2=`opasaquery -d "$nodedesc2" -o portguid|head -1 2>/dev/null` + +#iocname=`opareport -q -o ious -F "node:$ioudesc" -d 2|grep 'ID String'|head -1|sed -e 's/^.*ID String: //' 2>/dev/null` +#iocguid=`opareport -q -o ious -F "node:$ioudesc" -d 2|grep IocSlot|head -1|sed -e 's/^.*0x/0x/' 2>/dev/null` +#iocpat="`echo "$iocname"|cut -c1-$(( $(echo -n "$iocname"|wc -c) - 2))`*" +#iocpatb="*`echo "$iocname"|cut -c3-100`" +#iocpatc="*`echo "$iocname"|cut -c3-$(( $(echo -n "$iocname"|wc -c) - 2))`*" + +#ioctype='SRP' +subnet=0xfe80000000000000 # IBTA defined default subnet prefix +lid=1 # typically SM +topology=~/top.xml +badtopology=~/badtop.xml # with some missing or inaccurate items + +# missing fabric objects listed in badtopology +missfiportguid="0x0002b30101555555" +missfinodeguid="0x0002b30101555555" +missfinodedesc="MISSING_FI" +missfinodepat="*SSING_FI*" +missswnodeguid="0x0002b30102555555" +missswnodedesc="MISSING_SW" +missswnodepat="*SSING_SW" +misssmdetpat="*SSING*" +missrate="25g" +missmtu="2048" +missfinodedetpat="MISSING_N*" +misslabelpat="MISSING_LAB*" +misslengthpat="MISSLE*" +misscabledetpat="MISSING_DET*" +misslinkdetpat="MISSING_LDET*" +missportdetpat="MISSING_P*" + +# show what we concluded: +echo "Running reports using:" +echo " nodedesc='$nodedesc'" +echo " nodeguid='$nodeguid'" +echo " sysguid='$sysguid'" +echo " portguid='$portguid'" +echo " nodepat='$nodepat'" +echo " nodepatb='$nodepatb'" +echo " nodepatc='$nodepatc'" +echo +echo " nodedesc2='$nodedesc2'" +echo " nodeguid2='$nodeguid2'" +echo " portguid2='$portguid2'" +#echo +#echo " ioudesc='$ioudesc'" +#echo " iocname='$iocname'" +#echo " iocpat='$iocpat'" +#echo " iocpatb='$iocpatb'" +#echo " iocpatc='$iocpatc'" +#echo " iocguid='$iocguid'" +#echo " ioctype='$ioctype'" + +# run the command as given +# then if -x option was supplied use opaxmlindent to syntax check the XML +# it will be silent on success or report efforts if bad syntax +test_func() +{ +$* +[[ "X$*" == X*\ -x\ * ]] && $*|opaxmlindent >/dev/null +} + +set -x + +for opts in "" "-T $topology" "-x" "-T $topology -x" +do +echo "Test basic reports" +test_func $OPA_REPORT $opts -o comps -d 10 +test_func $OPA_REPORT $opts -o brcomps -d 10 +test_func $OPA_REPORT $opts -o nodes -d 10 +test_func $OPA_REPORT $opts -o brnodes -d 10 +test_func $OPA_REPORT $opts -o ious -d 10 +test_func $OPA_REPORT $opts -o lids -d 10 +test_func $OPA_REPORT $opts -o links -d 10 +test_func $OPA_REPORT $opts -o extlinks -d 10 +test_func $OPA_REPORT $opts -o slowlinks -d 10 +test_func $OPA_REPORT $opts -o slowconfiglinks -d 10 +test_func $OPA_REPORT $opts -o slowconnlinks -d 10 +test_func $OPA_REPORT $opts -o misconfiglinks -d 10 +test_func $OPA_REPORT $opts -o misconnlinks -d 10 +test_func $OPA_REPORT $opts -o errors -d 10 +test_func $OPA_REPORT $opts -o otherports -d 10 +test_func $OPA_REPORT $opts -o linear -d 10 +test_func $OPA_REPORT $opts -o mcast -d 10 +test_func $OPA_REPORT $opts -o portusage -d 10 +test_func $OPA_REPORT $opts -o pathusage -d 10 +test_func $OPA_REPORT $opts -o treepathusage -d 10 +test_func $OPA_REPORT $opts -o portgroups -d 10 +test_func $OPA_REPORT $opts -o quarantinednodes -d 10 +test_func $OPA_REPORT $opts -o validateroutes -d 10 +test_func $OPA_REPORT $opts -o validatepgs -d 10 +test_func $OPA_REPORT $opts -o validatecreditloops -d 10 +test_func $OPA_REPORT $opts -o vfinfo -d 10 +test_func $OPA_REPORT $opts -o vfmember -d 10 +test_func $OPA_REPORT $opts -o all -d 10 +test_func $OPA_REPORT $opts -o route -S "node:$nodedesc:port:1" -D "node:$nodedesc2:port:1" +test_func $OPA_REPORT $opts -o route -S "node:$nodedesc" -D "node:$nodedesc2" +test_func $OPA_REPORT $opts -o none + +# formats for "point" +echo "Test various Focus formats" +test_func $OPA_REPORT $opts -o nodes -F gid:$subnet:$portguid +test_func $OPA_REPORT $opts -o nodes -F lid:$lid +test_func $OPA_REPORT $opts -o nodes -F lid:$lid:node +test_func $OPA_REPORT $opts -o nodes -F lid:$lid:port:1 +test_func $OPA_REPORT $opts -o nodes -F portguid:$portguid +test_func $OPA_REPORT $opts -o nodes -F nodeguid:$nodeguid +test_func $OPA_REPORT $opts -o nodes -F nodeguid:$nodeguid:port:1 +#test_func $OPA_REPORT $opts -o nodes -F iocguid:$iocguid +#test_func $OPA_REPORT $opts -o nodes -F iocguid:$iocguid:port:1 +test_func $OPA_REPORT $opts -o nodes -F systemguid:$sysguid +test_func $OPA_REPORT $opts -o nodes -F systemguid:$sysguid:port:1 +#test_func $OPA_REPORT $opts -o nodes -F "ioc:$iocname" +#test_func $OPA_REPORT $opts -o nodes -F "ioc:$iocname:port:1" +#test_func $OPA_REPORT $opts -o nodes -F "iocpat:$iocpat" +#test_func $OPA_REPORT $opts -o nodes -F "iocpat:$iocpatb" +#test_func $OPA_REPORT $opts -o nodes -F "iocpat:$iocpatc" +#test_func $OPA_REPORT $opts -o nodes -F "iocpat:$iocpat:port:1" +#test_func $OPA_REPORT $opts -o nodes -F "ioctype:$ioctype" +#test_func $OPA_REPORT $opts -o nodes -F "ioctype:$ioctype:port:1" +test_func $OPA_REPORT $opts -o nodes -F "node:$nodedesc" +test_func $OPA_REPORT $opts -o nodes -F "node:$nodedesc:port:1" +test_func $OPA_REPORT $opts -o nodes -F "nodepat:$nodepat" +test_func $OPA_REPORT $opts -o nodes -F "nodepat:$nodepatb" +test_func $OPA_REPORT $opts -o nodes -F "nodepat:$nodepatc" +test_func $OPA_REPORT $opts -o nodes -F "nodepat:$nodepat:port:1" +#test_func $OPA_REPORT $opts -o nodes -F "nodedetpat:$nodedetpat" +#test_func $OPA_REPORT $opts -o nodes -F "nodedetpat:$nodedetpat:port:1" +test_func $OPA_REPORT $opts -o nodes -F "nodetype:FI" +test_func $OPA_REPORT $opts -o nodes -F "nodetype:FI:port:1" +test_func $OPA_REPORT $opts -o nodes -F "rate:100g" +test_func $OPA_REPORT $opts -o nodes -F "mtucap:8192" +test_func $OPA_REPORT $opts -o nodes -F "portstate:active" +test_func $OPA_REPORT $opts -o nodes -F "portphysstate:linkup" +#test_func $OPA_REPORT $opts -o nodes -F "labelpat:$labelpat" +#test_func $OPA_REPORT $opts -o nodes -F "lengthpat:$lengthpat" +#test_func $OPA_REPORT $opts -o nodes -F "cabledetpat:$cabledetpat" +#test_func $OPA_REPORT $opts -o nodes -F "cabinflenpat:$cabinflenpat" +#test_func $OPA_REPORT $opts -o nodes -F "cabinfvendnamepat:$cabinfvendnamepat" +#test_func $OPA_REPORT $opts -o nodes -F "cabinfvendpnpat:$cabinfvendpnpat" +#test_func $OPA_REPORT $opts -o nodes -F "cabinfvendrevpat:$cabinfvendrevpat" +#test_func $OPA_REPORT $opts -o nodes -F "cabinftype:$cabinftype" +#test_func $OPA_REPORT $opts -o nodes -F "cabinfvendsnpat:$cabinfvendsnpat" +#test_func $OPA_REPORT $opts -o nodes -F "linkdetpat:$linkdetpat" +#test_func $OPA_REPORT $opts -o nodes -F "portdetpat:$portdetpat" +test_func $OPA_REPORT $opts -o nodes -F sm +#test_func $OPA_REPORT $opts -o nodes -F "smdetpat:$smdetpat" +test_func $OPA_REPORT $opts -o nodes -F "route:node:$nodedesc:port:1:node:$nodedesc2:port:1" +test_func $OPA_REPORT $opts -o nodes -F "route:node:$nodedesc:node:$nodedesc2" +test_func $OPA_REPORT $opts -o nodes -F "linkqual:5" +test_func $OPA_REPORT $opts -o nodes -F "linkqualLE:5" +test_func $OPA_REPORT $opts -o nodes -F "linkqualGE:4" + +# TBD other tests of options and flags +done + +for opts in "-T $topology" "-T $topology -x" "-T $badtopology" "-T $badtopology -x" +do +echo "Test verify reports" +test_func $OPA_REPORT $opts -o verifyfis -d 10 +test_func $OPA_REPORT $opts -o verifysws -d 10 +test_func $OPA_REPORT $opts -o verifynodes -d 10 +test_func $OPA_REPORT $opts -o verifysms -d 10 +test_func $OPA_REPORT $opts -o verifylinks -d 10 +test_func $OPA_REPORT $opts -o verifyextlinks -d 10 +test_func $OPA_REPORT $opts -o verifyfilinks -d 10 +test_func $OPA_REPORT $opts -o verifyislinks -d 10 +test_func $OPA_REPORT $opts -o verifyextislinks -d 10 +test_func $OPA_REPORT $opts -o verifyall -d 10 + +# formats for "point" +echo "Test verify with various Focus formats" +test_func $OPA_REPORT $opts -o verifyall -F gid:$subnet:$portguid +test_func $OPA_REPORT $opts -o verifyall -F lid:$lid +test_func $OPA_REPORT $opts -o verifyall -F lid:$lid:node +test_func $OPA_REPORT $opts -o verifyall -F lid:$lid:port:1 +test_func $OPA_REPORT $opts -o verifyall -F portguid:$portguid +test_func $OPA_REPORT $opts -o verifyall -F nodeguid:$nodeguid +test_func $OPA_REPORT $opts -o verifyall -F nodeguid:$nodeguid:port:1 +#test_func $OPA_REPORT $opts -o verifyall -F iocguid:$iocguid +#test_func $OPA_REPORT $opts -o verifyall -F iocguid:$iocguid:port:1 +test_func $OPA_REPORT $opts -o verifyall -F systemguid:$sysguid +test_func $OPA_REPORT $opts -o verifyall -F systemguid:$sysguid:port:1 +#test_func $OPA_REPORT $opts -o verifyall -F "ioc:$iocname" +#test_func $OPA_REPORT $opts -o verifyall -F "ioc:$iocname:port:1" +#test_func $OPA_REPORT $opts -o verifyall -F "iocpat:$iocpat" +#test_func $OPA_REPORT $opts -o verifyall -F "iocpat:$iocpatb" +#test_func $OPA_REPORT $opts -o verifyall -F "iocpat:$iocpatc" +#test_func $OPA_REPORT $opts -o verifyall -F "iocpat:$iocpat:port:1" +#test_func $OPA_REPORT $opts -o verifyall -F "ioctype:$ioctype" +#test_func $OPA_REPORT $opts -o verifyall -F "ioctype:$ioctype:port:1" +test_func $OPA_REPORT $opts -o verifyall -F "node:$nodedesc" +test_func $OPA_REPORT $opts -o verifyall -F "node:$nodedesc:port:1" +test_func $OPA_REPORT $opts -o verifyall -F "nodepat:$nodepat" +test_func $OPA_REPORT $opts -o verifyall -F "nodepat:$nodepatb" +test_func $OPA_REPORT $opts -o verifyall -F "nodepat:$nodepatc" +test_func $OPA_REPORT $opts -o verifyall -F "nodepat:$nodepat:port:1" +#test_func $OPA_REPORT $opts -o verifyall -F "nodedetpat:$nodedetpat" +#test_func $OPA_REPORT $opts -o verifyall -F "nodedetpat:$nodedetpat:port:1" +test_func $OPA_REPORT $opts -o verifyall -F "nodetype:FI" +test_func $OPA_REPORT $opts -o verifyall -F "nodetype:FI:port:1" +test_func $OPA_REPORT $opts -o verifyall -F "rate:100g" +test_func $OPA_REPORT $opts -o verifyall -F "mtucap:8192" +test_func $OPA_REPORT $opts -o verifyall -F "portstate:active" +test_func $OPA_REPORT $opts -o verifyall -F "portphysstate:linkup" +#test_func $OPA_REPORT $opts -o verifyall -F "labelpat:$labelpat" +#test_func $OPA_REPORT $opts -o verifyall -F "lengthpat:$lengthpat" +#test_func $OPA_REPORT $opts -o verifyall -F "cabledetpat:$cabledetpat" +#test_func $OPA_REPORT $opts -o verifyall -F "cabinflenpat:$cabinflenpat" +#test_func $OPA_REPORT $opts -o verifyall -F "cabinfvendnamepat:$cabinfvendnamepat" +#test_func $OPA_REPORT $opts -o verifyall -F "cabinfvendpnpat:$cabinfvendpnpat" +#test_func $OPA_REPORT $opts -o verifyall -F "cabinfvendrevpat:$cabinfvendrevpat" +#test_func $OPA_REPORT $opts -o verifyall -F "cabinftype:$cabinftype" +#test_func $OPA_REPORT $opts -o verifyall -F "cabinfvendsnpat:$cabinfvendsnpat" +#test_func $OPA_REPORT $opts -o verifyall -F "linkdetpat:$linkdetpat" +#test_func $OPA_REPORT $opts -o verifyall -F "portdetpat:$portdetpat" +test_func $OPA_REPORT $opts -o verifyall -F sm +#test_func $OPA_REPORT $opts -o verifyall -F "smdetpat:$smdetpat" +test_func $OPA_REPORT $opts -o verifyall -F "route:node:$nodedesc:port:1:node:$nodedesc2:port:1" +test_func $OPA_REPORT $opts -o verifyall -F "route:node:$nodedesc:node:$nodedesc2" +test_func $OPA_REPORT $opts -o verifyall -F "linkqual:5" +test_func $OPA_REPORT $opts -o verifyall -F "linkqualLE:5" +test_func $OPA_REPORT $opts -o verifyall -F "linkqualGE:4" + +echo "Test verify with various Focus formats on missing objects" +test_func $OPA_REPORT $opts -o verifyall -F gid:$subnet:$missfiportguid +#test_func $OPA_REPORT $opts -o verifyall -F gid:$subnet:$missswportguid +#test_func $OPA_REPORT $opts -o verifyall -F lid:$lid +#test_func $OPA_REPORT $opts -o verifyall -F lid:$lid:node +#test_func $OPA_REPORT $opts -o verifyall -F lid:$lid:port:1 +test_func $OPA_REPORT $opts -o verifyall -F portguid:$missfiportguid +#test_func $OPA_REPORT $opts -o verifyall -F portguid:$missswportguid +test_func $OPA_REPORT $opts -o verifyall -F nodeguid:$missfinodeguid +test_func $OPA_REPORT $opts -o verifyall -F nodeguid:$missswnodeguid +test_func $OPA_REPORT $opts -o verifyall -F nodeguid:$missfinodeguid:port:1 +test_func $OPA_REPORT $opts -o verifyall -F nodeguid:$missswnodeguid:port:1 +#test_func $OPA_REPORT $opts -o verifyall -F iocguid:$iocguid +#test_func $OPA_REPORT $opts -o verifyall -F iocguid:$iocguid:port:1 +#test_func $OPA_REPORT $opts -o verifyall -F systemguid:$sysguid +#test_func $OPA_REPORT $opts -o verifyall -F systemguid:$sysguid:port:1 +#test_func $OPA_REPORT $opts -o verifyall -F "ioc:$iocname" +#test_func $OPA_REPORT $opts -o verifyall -F "ioc:$iocname:port:1" +#test_func $OPA_REPORT $opts -o verifyall -F "iocpat:$iocpat" +#test_func $OPA_REPORT $opts -o verifyall -F "iocpat:$iocpatb" +#test_func $OPA_REPORT $opts -o verifyall -F "iocpat:$iocpatc" +#test_func $OPA_REPORT $opts -o verifyall -F "iocpat:$iocpat:port:1" +#test_func $OPA_REPORT $opts -o verifyall -F "ioctype:$ioctype" +#test_func $OPA_REPORT $opts -o verifyall -F "ioctype:$ioctype:port:1" +test_func $OPA_REPORT $opts -o verifyall -F "node:$missfinodedesc" +test_func $OPA_REPORT $opts -o verifyall -F "node:$missswnodedesc" +test_func $OPA_REPORT $opts -o verifyall -F "node:$missfinodedesc:port:1" +test_func $OPA_REPORT $opts -o verifyall -F "node:$missswnodedesc:port:1" +test_func $OPA_REPORT $opts -o verifyall -F "nodepat:$missfinodepat" +test_func $OPA_REPORT $opts -o verifyall -F "nodepat:$missswnodepat" +test_func $OPA_REPORT $opts -o verifyall -F "nodepat:$missfinodepat:port:1" +test_func $OPA_REPORT $opts -o verifyall -F "nodepat:$missswnodepat:port:1" +test_func $OPA_REPORT $opts -o verifyall -F "nodedetpat:$missfinodedetpat" +#test_func $OPA_REPORT $opts -o verifyall -F "nodedetpat:$missswnodedetpat" +#test_func $OPA_REPORT $opts -o verifyall -F "nodedetpat:$missfinodedetpat:port:1" +#test_func $OPA_REPORT $opts -o verifyall -F "nodedetpat:$missswnodedetpat:port:1" +test_func $OPA_REPORT $opts -o verifyall -F "nodetype:FI" +test_func $OPA_REPORT $opts -o verifyall -F "nodetype:FI:port:1" +test_func $OPA_REPORT $opts -o verifyall -F "rate:$missrate" +test_func $OPA_REPORT $opts -o verifyall -F "mtucap:$missmtu" +#test_func $OPA_REPORT $opts -o verifyall -F "portstate:active" +#test_func $OPA_REPORT $opts -o verifyall -F "portphysstate:linkup" +test_func $OPA_REPORT $opts -o verifyall -F "labelpat:$misslabelpat" +test_func $OPA_REPORT $opts -o verifyall -F "lengthpat:$misslengthpat" +test_func $OPA_REPORT $opts -o verifyall -F "cabledetpat:$misscabledetpat" +#test_func $OPA_REPORT $opts -o verifyall -F "cabinflenpat:$cabinflenpat" +#test_func $OPA_REPORT $opts -o verifyall -F "cabinfvendnamepat:$cabinfvendnamepat" +#test_func $OPA_REPORT $opts -o verifyall -F "cabinfvendpnpat:$cabinfvendpnpat" +#test_func $OPA_REPORT $opts -o verifyall -F "cabinfvendrevpat:$cabinfvendrevpat" +#test_func $OPA_REPORT $opts -o verifyall -F "cabinftype:$cabinftype" +#test_func $OPA_REPORT $opts -o verifyall -F "cabinfvendsnpat:$cabinfvendsnpat" +test_func $OPA_REPORT $opts -o verifyall -F "linkdetpat:$misslinkdetpat" +test_func $OPA_REPORT $opts -o verifyall -F "portdetpat:$missportdetpat" +#test_func $OPA_REPORT $opts -o verifyall -F sm +test_func $OPA_REPORT $opts -o verifyall -F "smdetpat:$misssmdetpat" +#test_func $OPA_REPORT $opts -o verifyall -F "route:node:$nodedesc:port:1:node:$nodedesc2:port:1" +#test_func $OPA_REPORT $opts -o verifyall -F "route:node:$nodedesc:node:$nodedesc2" +#test_func $OPA_REPORT $opts -o verifyall -F "linkqual:5" +#test_func $OPA_REPORT $opts -o verifyall -F "linkqualLE:5" +#test_func $OPA_REPORT $opts -o verifyall -F "linkqualGE:4" + +echo "Test verify with various Focus formats on not found objects" +# these will generate errors, so dont use test_func to verify XML +$OPA_REPORT $opts -o verifyall -F gid:$subnet:0xffffffffffffffff +#$OPA_REPORT $opts -o verifyall -F lid:$lid +#$OPA_REPORT $opts -o verifyall -F lid:$lid:node +#$OPA_REPORT $opts -o verifyall -F lid:$lid:port:1 +$OPA_REPORT $opts -o verifyall -F portguid:0xffffffffffffffff +$OPA_REPORT $opts -o verifyall -F nodeguid:0xffffffffffffffff +$OPA_REPORT $opts -o verifyall -F nodeguid:0xffffffffffffffff:port:1 +#$OPA_REPORT $opts -o verifyall -F iocguid:$iocguid +#$OPA_REPORT $opts -o verifyall -F iocguid:$iocguid:port:1 +#$OPA_REPORT $opts -o verifyall -F systemguid:$sysguid +#$OPA_REPORT $opts -o verifyall -F systemguid:$sysguid:port:1 +#$OPA_REPORT $opts -o verifyall -F "ioc:$iocname" +#$OPA_REPORT $opts -o verifyall -F "ioc:$iocname:port:1" +#$OPA_REPORT $opts -o verifyall -F "iocpat:$iocpat" +#$OPA_REPORT $opts -o verifyall -F "iocpat:$iocpatb" +#$OPA_REPORT $opts -o verifyall -F "iocpat:$iocpatc" +#$OPA_REPORT $opts -o verifyall -F "iocpat:$iocpat:port:1" +#$OPA_REPORT $opts -o verifyall -F "ioctype:$ioctype" +#$OPA_REPORT $opts -o verifyall -F "ioctype:$ioctype:port:1" +$OPA_REPORT $opts -o verifyall -F "node:NO_SUCH_NODE" +$OPA_REPORT $opts -o verifyall -F "node:NO_SUCH_NODE:port:1" +$OPA_REPORT $opts -o verifyall -F "nodepat:NO_SUCH_*" +$OPA_REPORT $opts -o verifyall -F "nodepat:NO_SUCH_*:port:1" +$OPA_REPORT $opts -o verifyall -F "nodedetpat:NO_SUCH_*" +$OPA_REPORT $opts -o verifyall -F "nodedetpat:NO_SUCH_*:port:1" +#$OPA_REPORT $opts -o verifyall -F "nodetype:FI" +#$OPA_REPORT $opts -o verifyall -F "nodetype:FI:port:1" +$OPA_REPORT $opts -o verifyall -F "rate:50g" +$OPA_REPORT $opts -o verifyall -F "mtucap:4096" +#$OPA_REPORT $opts -o verifyall -F "portstate:active" +#$OPA_REPORT $opts -o verifyall -F "portphysstate:linkup" +#$OPA_REPORT $opts -o verifyall -F "labelpat:$labelpat" +#$OPA_REPORT $opts -o verifyall -F "lengthpat:$lengthpat" +#$OPA_REPORT $opts -o verifyall -F "cabledetpat:$cabledetpat" +#$OPA_REPORT $opts -o verifyall -F "cabinflenpat:$cabinflenpat" +#$OPA_REPORT $opts -o verifyall -F "cabinfvendnamepat:$cabinfvendnamepat" +#$OPA_REPORT $opts -o verifyall -F "cabinfvendpnpat:$cabinfvendpnpat" +#$OPA_REPORT $opts -o verifyall -F "cabinfvendrevpat:$cabinfvendrevpat" +#$OPA_REPORT $opts -o verifyall -F "cabinftype:$cabinftype" +#$OPA_REPORT $opts -o verifyall -F "cabinfvendsnpat:$cabinfvendsnpat" +#$OPA_REPORT $opts -o verifyall -F "linkdetpat:$linkdetpat" +#$OPA_REPORT $opts -o verifyall -F "portdetpat:$portdetpat" +#$OPA_REPORT $opts -o verifyall -F sm +$OPA_REPORT $opts -o verifyall -F "smdetpat:NO_SUCH_*" +#$OPA_REPORT $opts -o verifyall -F "route:node:$nodedesc:port:1:node:$nodedesc2:port:1" +#$OPA_REPORT $opts -o verifyall -F "route:node:$nodedesc:node:$nodedesc2" +#$OPA_REPORT $opts -o verifyall -F "linkqual:5" +#$OPA_REPORT $opts -o verifyall -F "linkqualLE:5" +#$OPA_REPORT $opts -o verifyall -F "linkqualGE:4" +done diff --git a/IbaTools/opareport/opareport.c b/IbaTools/opareport/opareport.c new file mode 100644 index 0000000..3cc5134 --- /dev/null +++ b/IbaTools/opareport/opareport.c @@ -0,0 +1,13661 @@ +/* BEGIN_ICS_COPYRIGHT7 **************************************** + +Copyright (c) 2015-2019, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT7 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +#include "opareport.h" +#ifdef IB_STACK_OPENIB +#include +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "stl_print.h" + +// Used for expanding various enumarations into text equivalents +#define SHOW_BUF_SIZE 81 + +// what to output when g_noname set +char *g_name_marker = "xxxxxxxxxx"; + +// amount to subtract from threshold before compare +// 0-> Greater (report error if > threshold) +// 1-> Equal (report error if >= threshold) +uint32 g_threshold_compare = 0; + +/* indicates overall set of reports for Slow Link reports + * also used to indicate which portion of the report is being done + */ +typedef enum { + LINK_EXPECTED_REPORT = 1, + LINK_CONFIG_REPORT =2, + LINK_CONN_REPORT =3 +} LinkReport_t; + +uint8 g_verbose = 0; +int g_exitstatus = 0; +int g_persist = 0; // omit transient data like LIDs +int g_hard = 0; // omit software configured items +int g_noname = 0; // omit names +char* g_snapshot_in_file = NULL; // input file being parsed +char* g_topology_in_file = NULL; // input file being parsed +int g_interval = 0; // interval for port stats in seconds +int g_clearstats = 0; // clear port stats +int g_clearallstats = 0; // clear all port stats +int g_limitstats = 0; // limit stats to specific focus ports +STL_PORT_COUNTERS_DATA g_Thresholds; +STL_CLEAR_PORT_STATUS g_CounterSelectMask; +EUI64 g_portGuid = -1; // local port to use to access fabric +IB_PORT_ATTRIBUTES *g_portAttrib = NULL;// attributes for our local port +int g_quietfocus = 0; // do not include focus desc in report +int g_max_lft = 0; // Size of largest switch LFT +int g_quiet = 0; // omit progress output +uint32 g_begin = 0; // begin time for interval +uint32 g_end = 0; // end time for interval +int g_use_scsc = 0; // should validatecreditloops use scsc tables +int g_rc = 0; // should validateroutes use rc +int g_ms_timeout = OMGT_DEF_TIMEOUT_MS; + +// All the information about the fabric +FabricData_t g_Fabric; + +void XmlPrintHex64(const char *tag, uint64 value, int indent) +{ + printf("%*s<%s>0x%016"PRIx64"\n", indent, "",tag, value, tag); +} + +void XmlPrintHex32(const char *tag, uint32 value, int indent) +{ + printf("%*s<%s>0x%08x\n", indent, "",tag, value, tag); +} + +void XmlPrintHex16(const char *tag, uint16 value, int indent) +{ + printf("%*s<%s>0x%04x\n", indent, "",tag, value, tag); +} + +void XmlPrintHex8(const char *tag, uint8 value, int indent) +{ + printf("%*s<%s>0x%02x\n", indent, "",tag, value, tag); +} + +void XmlPrintDec(const char *tag, unsigned value, int indent) +{ + printf("%*s<%s>%u\n", indent, "",tag, value, tag); +} + +void XmlPrintDec64(const char *tag, uint64 value, int indent) +{ + printf("%*s<%s>%"PRIu64"\n", indent, "",tag, value, tag); +} + +void XmlPrintHex(const char *tag, unsigned value, int indent) +{ + printf("%*s<%s>0x%x\n", indent, "",tag, value, tag); +} + +void XmlPrintStrLen(const char *tag, const char* value, int len, int indent) +{ + printf("%*s<%s>", indent, "",tag); + /* print string taking care to translate special XML characters */ + for (;len && *value; --len, ++value) { + if (*value == '&') + printf("&"); + else if (*value == '<') + printf("<"); + else if (*value == '>') + printf(">"); + else if (*value == '\'') + printf("'"); + else if (*value == '"') + printf("""); + else if (iscntrl(*value)) { + //table in asciitab.h indiciates character codes permitted in XML strings + //Only 3 control characters below 0x1f are permitted: + //0x9 (BT_S), 0xa (BT_LRF), and 0xd (BT_CR) + if ((unsigned char)*value <= 0x08 + || ((unsigned char)*value >= 0x0b + && (unsigned char)*value <= 0x0c) + || ((unsigned char)*value >= 0x0e + && (unsigned char)*value <= 0x1f)) { + // characters which XML does not permit in character fields + printf("!"); + } else { + printf("&#x%x;", (unsigned)(unsigned char)*value); + } + } else if ((unsigned char)*value > 0x7f) + // permitted but generate 2 characters back after parsing, so omit + printf("!"); + else + putchar((int)(unsigned)(unsigned char)*value); + } + printf("\n", tag); +} + +void XmlPrintStr(const char *tag, const char* value, int indent) +{ + XmlPrintStrLen(tag, value, IB_INT32_MAX, indent); +} + +void XmlPrintOptionalStr(const char *tag, const char* value, int indent) +{ + if (value) + XmlPrintStrLen(tag, value, IB_INT32_MAX, indent); +} + +void XmlPrintBool(const char *tag, unsigned value, int indent) +{ + if (value) + XmlPrintStr(tag, "True", indent); + else + XmlPrintStr(tag, "False", indent); +} + +void XmlPrintMLID(const char *tag, STL_LID value, int indent) +{ + // should never be less than 4 hex digits, upper bit should never be 0 + printf("%*s<%s>0x%04x\n", indent, "",tag, value, tag); +} + +void XmlPrintLID(const char *tag, STL_LID value, int indent) +{ + printf("%*s<%s>0x%.*x\n", indent, "", tag, (value <= IB_MAX_UCAST_LID ? 4:8), value, tag); +} + +void XmlPrintPKey(const char *tag, IB_P_KEY value, int indent) +{ + printf("%*s<%s>0x%04x\n", indent, "",tag, value, tag); +} + +void XmlPrintGID(const char *tag, IB_GID value, int indent) +{ + printf("%*s<%s>0x%016"PRIx64":%016"PRIx64"\n", + indent, "", tag, + value.Type.Global.SubnetPrefix, + value.Type.Global.InterfaceID, tag); +} + +void XmlPrintNodeType(uint8 value, int indent) +{ + XmlPrintStr("NodeType", StlNodeTypeToText(value), indent); + XmlPrintDec("NodeType_Int", value, indent); +} + +void XmlPrintNodeDesc(const char *value, int indent) +{ + if (! g_noname) + XmlPrintStrLen("NodeDesc", value, NODE_DESCRIPTION_ARRAY_SIZE, indent); +} + +void XmlPrintIocIDString(const char *value, int indent) +{ + if (! g_noname) + XmlPrintStrLen("IDString", value, IOC_IDSTRING_SIZE, indent); +} + +void XmlPrintServiceName(const uchar *value, int indent) +{ + /* service names are critical, g_noname NA */ + XmlPrintStrLen("Name", (const char*)value, IOC_SERVICE_NAME_SIZE, indent); +} + +void XmlPrintRate(uint8 value, int indent) +{ + XmlPrintStr("Rate", StlStaticRateToText(value), indent); + XmlPrintDec("Rate_Int", value, indent); +} + +void XmlPrintLinkWidth(const char* tag_prefix, uint8 value, int indent) +{ + char buf[64]; + XmlPrintStr(tag_prefix, StlLinkWidthToText(value, buf, sizeof(buf)), indent); + printf("%*s<%s_Int>%u\n", indent, "",tag_prefix, value, tag_prefix); +} + +void XmlPrintLinkSpeed(const char* tag_prefix, uint16 value, int indent) +{ + char buf[64]; + XmlPrintStr(tag_prefix, StlLinkSpeedToText(value, buf, sizeof(buf)), indent); + printf("%*s<%s_Int>%u\n", indent, "",tag_prefix, value, tag_prefix); +} +void XmlPrintPortLtpCrc(const char* tag_prefix, uint16 value, int indent) +{ + char buf[64]; + XmlPrintStr(tag_prefix, StlPortLtpCrcModeToText(value, buf, sizeof(buf)), indent); + printf("%*s<%s_Int>%u\n", indent, "", tag_prefix, value, tag_prefix); +} + +// for predictable output order, should be called with the from port of the +// link record, with the exception of trace routes +void XmlPrintLinkStartTag(const char* tag, PortData *portp, int indent) +{ + //if (! portp->from) + // portp = portp->neighbor; + + printf("%*s<%s id=\"0x%016"PRIx64":%u\">\n", indent, "", tag, + portp->nodep->NodeInfo.NodeGUID, portp->PortNum); +} + +void XmlPrintTagHeader(const char *tag, int indent) +{ + printf("%*s<%s>\n", indent, "", tag); +} +void XmlPrintTagFooter(const char *tag, int indent) +{ + printf("%*s\n", indent, "", tag); +} + +void XmlPrintGroupRecord (McGroupData *pMcGroupRecord, int indent, int detail) +{ + char buf[8]; + XmlPrintGID("MGID",pMcGroupRecord->MGID,indent+8); + XmlPrintMLID("MLID",pMcGroupRecord->MLID, indent+8); + XmlPrintPKey("P_Key", pMcGroupRecord->GroupInfo.P_Key, indent+8); + XmlPrintDec("Mtu", GetBytesFromMtu(pMcGroupRecord->GroupInfo.Mtu), indent+8); + XmlPrintRate(pMcGroupRecord->GroupInfo.Rate,indent+8); + FormatTimeoutMult(buf, pMcGroupRecord->GroupInfo.PktLifeTime); + XmlPrintStr("PktLifeTime", buf, indent+8); + XmlPrintDec("PktLifeTime_Int", pMcGroupRecord->GroupInfo.PktLifeTime, indent+8); + XmlPrintHex32("Q_Key", pMcGroupRecord->GroupInfo.Q_Key, indent+8); + XmlPrintDec("SL", pMcGroupRecord->GroupInfo.u1.s.SL, indent+8); + XmlPrintHex("HopLimit", pMcGroupRecord->GroupInfo.u1.s.HopLimit, indent+8); + XmlPrintHex("FlowLabel", pMcGroupRecord->GroupInfo.u1.s.FlowLabel, indent+8); + XmlPrintHex8("TClass", pMcGroupRecord->GroupInfo.TClass, indent+8); +} + +void McMembershipXmlOutput(const char *tag, McMemberData *pMCGG, int indent) +{ + uint8 Memberstatus; + + Memberstatus = (pMCGG->MemberInfo.JoinSendOnlyMember<<2 | + pMCGG->MemberInfo.JoinNonMember<<1| + pMCGG->MemberInfo.JoinFullMember); + + XmlPrintDec(tag, Memberstatus, indent); +} + +void DisplaySeparator(void) +{ + printf("-------------------------------------------------------------------------------\n"); + +} + +void DisplayGroupRecord(McGroupData *pMcGroupRecord, int indent, int detail) +{ + char buf[8]; + printf("%*sMGID: 0x%016"PRIx64":0x%016"PRIx64"\n", + indent, "", + pMcGroupRecord->MGID.AsReg64s.H, + pMcGroupRecord->MGID.AsReg64s.L); + FormatTimeoutMult(buf, pMcGroupRecord->GroupInfo.PktLifeTime); + printf("%*sMLID: 0x%08x PKey: 0x%04x Mtu: %5s Rate: %4s PktLifeTime: %s\n", + indent, "", + pMcGroupRecord->MLID, + pMcGroupRecord->GroupInfo.P_Key, + IbMTUToText(pMcGroupRecord->GroupInfo.Mtu), + StlStaticRateToText(pMcGroupRecord->GroupInfo.Rate), + buf); + printf("%*sQKey: 0x%08x SL: %2d FlowLabel: 0x%05x HopLimit: 0x%02x TClass: 0x%02x\n", + indent, "", + pMcGroupRecord->GroupInfo.Q_Key, + pMcGroupRecord->GroupInfo.u1.s.SL, + pMcGroupRecord->GroupInfo.u1.s.FlowLabel, + pMcGroupRecord->GroupInfo.u1.s.HopLimit, + pMcGroupRecord->GroupInfo.TClass); +} + +void ShowPathRecord(IB_PATH_RECORD *pPathRecord, Format_t format, + int indent, int detail) +{ + char buf[8]; + switch (format) { + case FORMAT_TEXT: + printf("%*sSGID: 0x%016"PRIx64":%016"PRIx64"\n", + indent, "", + pPathRecord->SGID.Type.Global.SubnetPrefix, + pPathRecord->SGID.Type.Global.InterfaceID); + printf("%*sDGID: 0x%016"PRIx64":%016"PRIx64"\n", + indent, "", + pPathRecord->DGID.Type.Global.SubnetPrefix, + pPathRecord->DGID.Type.Global.InterfaceID); + printf("%*sSLID: 0x%.*x DLID: 0x%.*x Reversible: %s", + indent, "", (pPathRecord->SLID <= IB_MAX_UCAST_LID ? 4:8), pPathRecord->SLID, + (pPathRecord->DLID <= IB_MAX_UCAST_LID ? 4:8), pPathRecord->DLID, + pPathRecord->Reversible?"Y":"N"); + // If this is from a snapshot, stop here - the remaining values cannot be + // deduced. + if (g_snapshot_in_file) { + printf("\n"); + break; + } + + printf(" PKey: 0x%04x\n", pPathRecord->P_Key); + + printf("%*sRaw: %s FlowLabel: 0x%05x HopLimit: 0x%02x TClass: 0x%02x\n", + indent, "", pPathRecord->u1.s.RawTraffic?"Y":"N", + pPathRecord->u1.s.FlowLabel, pPathRecord->u1.s.HopLimit, + pPathRecord->TClass); + FormatTimeoutMult(buf, pPathRecord->PktLifeTime); + printf("%*sSL: %2d Mtu: %5s Rate: %4s PktLifeTime: %s Pref: %d\n", + indent, "", pPathRecord->u2.s.SL, IbMTUToText(pPathRecord->Mtu), + StlStaticRateToText(pPathRecord->Rate), buf, + pPathRecord->Preference); + break; + case FORMAT_XML: + // TBD does this get a unique ID? Is PKey needed too + //printf("%*s\n", indent, "", + // pPathRecord->SGID.Type.Global.SubnetPrefix, + // pPathRecord->SGID.Type.Global.InterfaceID, + // pPathRecord->DGID.Type.Global.SubnetPrefix, + // pPathRecord->DGID.Type.Global.InterfaceID, + // pPathRecord->SLID, pPathRecord->DLID); + printf("%*s\n", indent, ""); + XmlPrintGID("SGID", pPathRecord->SGID, indent+4); + XmlPrintGID("DGID", pPathRecord->DGID, indent+4); + XmlPrintLID("SLID", pPathRecord->SLID, indent+4); + XmlPrintLID("DLID", pPathRecord->DLID, indent+4); + XmlPrintStr("Reversible", pPathRecord->Reversible?"Y":"N", indent+4); + XmlPrintDec("Reversible_Int", pPathRecord->Reversible, indent+4); + // If this is from a snapshot, stop here - the remaining values cannot be + // deduced. + if (g_snapshot_in_file) { + printf("%*s\n", indent, ""); + break; + } + XmlPrintPKey("PKey", pPathRecord->P_Key, indent+4); + XmlPrintStr("Raw", pPathRecord->u1.s.RawTraffic?"Y":"N", indent+4); + XmlPrintDec("Raw_Int", pPathRecord->u1.s.RawTraffic, indent+4); + XmlPrintHex("FlowLabel", pPathRecord->u1.s.FlowLabel, indent+4); + XmlPrintHex8("HopLimit", pPathRecord->u1.s.HopLimit, indent+4); + XmlPrintHex8("TClass", pPathRecord->TClass, indent+4); + XmlPrintDec("SL", pPathRecord->u2.s.SL, indent+4); + XmlPrintDec("Mtu", GetBytesFromMtu(pPathRecord->Mtu), indent+4); + XmlPrintRate(pPathRecord->Rate, indent+4); + FormatTimeoutMult(buf, pPathRecord->PktLifeTime); + XmlPrintStr("PktLifeTime", buf, indent+4); + XmlPrintDec("PktLifeTime_Int", pPathRecord->PktLifeTime, indent+4); + XmlPrintDec("Preference", pPathRecord->Preference, indent+4); + printf("%*s\n", indent, ""); + break; + default: + break; + } +} + +void ShowTraceRecord(STL_TRACE_RECORD *pTraceRecord, Format_t format, int indent, int detail) +{ + switch (format) { + case FORMAT_TEXT: + // DisplayTraceRecord(pTraceRecord, indent); + printf("%*sIDGeneration: 0x%04x\n", + indent, "", pTraceRecord->IDGeneration); + printf("%*sNodeType: 0x%02x\n", + indent, "", pTraceRecord->NodeType); + printf("%*sNodeID: 0x%016"PRIx64" ChassisID: %016"PRIx64"\n", + indent, "", pTraceRecord->NodeID, pTraceRecord->ChassisID); + printf("%*sEntryPortID: 0x%016"PRIx64" ExitPortID: %016"PRIx64"\n", + indent, "", pTraceRecord->EntryPortID, pTraceRecord->ExitPortID); + printf("%*sEntryPort: 0x%02x ExitPort: 0x%02x\n", + indent, "", pTraceRecord->EntryPort, pTraceRecord->ExitPort); + break; + case FORMAT_XML: + // TBD id may not be unique, may need different id based on NodeType + printf("%*s\n", indent, ""); + XmlPrintHex16("IDGeneration", pTraceRecord->IDGeneration, indent+4); + XmlPrintNodeType(pTraceRecord->NodeType, indent+4); + XmlPrintHex64("NodeID", pTraceRecord->NodeID, indent+4); + XmlPrintHex64("ChassisID", pTraceRecord->ChassisID, indent+4); + XmlPrintHex64("EntryPortID", pTraceRecord->EntryPortID, indent+4); + XmlPrintHex64("ExitPortID", pTraceRecord->ExitPortID, indent+4); + XmlPrintHex8("EntryPort", pTraceRecord->EntryPort, indent+4); + XmlPrintHex8("ExitPort", pTraceRecord->ExitPort, indent+4); + printf("%*s\n", indent, ""); + break; + default: + break; + } +} + +// header used before a series of links +void ShowLinkBriefSummaryHeader(Format_t format, int indent, int detail) +{ + switch (format) { + case FORMAT_TEXT: + printf("%*sRate NodeGUID Port Type Name\n", indent, ""); + if (detail && (g_Fabric.flags & FF_CABLEDATA)) { + //printf("%*sPortDetails\n", indent+4, ""); + //printf("%*sLinkDetails\n", indent+4, ""); + printf("%*sCable: %-*s %-*s\n", indent+4, "", + CABLE_LABEL_STRLEN, "CableLabel", + CABLE_LENGTH_STRLEN, "CableLen"); + printf("%*s%s\n", indent+4, "", "CableDetails"); + } + break; + case FORMAT_XML: + break; + default: + break; + } +} + +#define MAX_CABLE_LENGTH_STR_LEN 8 // ~2-3 digits (poss. decimal pt) plus 'm' + +void ShowCableSummary(uint8_t *pCableData, Format_t format, int indent, int detail, uint8 portType) +{ + // CableInfo is organized in 128-byte pages but is stored in 64-byte half-pages + // For portType STANDARD we use STL_CIB_STD_HIGH_PAGE_ADDR to STL_CIB_STD_END_ADDR + // inclusive (128-255) + // To avoid compiler warnings, data pointer is used for the data portion + // of the STL_CABLE_INFO + STL_CABLE_INFO_STD *pCableInfo = (STL_CABLE_INFO_STD *)pCableData; + CableTypeInfoType cableTypeInfo; + boolean cableLenValid; // Copper cable length valid + boolean qsfp_dd; + char tempStr[STL_CIB_STD_MAX_STRING + 1] = {'\0'}; + char tempStr2[32] = {'\0'}; + char tempBuf[192]; + unsigned int i; + + if (pCableData) + qsfp_dd = (*pCableData == STL_CIB_STD_QSFP_DD); + else { + fprintf(stderr, "ShowCableSummary: cableInfoData pointer is invalid\n"); + return; + } + + if (qsfp_dd) { + ShowCableSummaryDD(pCableData, format, indent, detail, portType); + return; + } + + StlCableInfoDecodeCableType(pCableInfo->dev_tech.s.xmit_tech, pCableInfo->connector, pCableInfo->ident, &cableTypeInfo); + cableLenValid = cableTypeInfo.cableLengthValid; + + switch (format) { + case FORMAT_TEXT: + switch (portType) { + case STL_PORT_TYPE_STANDARD: + if (detail <= 6) { + //line1 + memset(tempBuf, ' ', sizeof(tempBuf)); + i = 0; + StringCopy(&tempBuf[i], cableTypeInfo.cableTypeShortDesc, strlen(cableTypeInfo.cableTypeShortDesc)+1); + tempBuf[i + strlen(cableTypeInfo.cableTypeShortDesc)] = ','; +#if 0 + i = STL_CIB_LINE1_FIELD1; + strncpy(&tempBuf[i], cableTypeInfo.cableTypeShortDesc, strlen(cableTypeInfo.cableTypeShortDesc)); + tempBuf[i + strlen(cableTypeInfo.cableTypeShortDesc)] = ','; + tempBuf[i + 1 + strlen(cableTypeInfo.cableTypeShortDesc)] = ' '; +#endif + i = STL_CIB_LINE1_FIELD2; + StlCableInfoOM4LengthToText(pCableInfo->len_om4, cableLenValid, MAX_CABLE_LENGTH_STR_LEN, &tempBuf[i]); + tempBuf[i + strlen(&tempBuf[i])] = ' '; + i = STL_CIB_LINE1_FIELD3; + memcpy(tempStr, pCableInfo->vendor_name, sizeof(pCableInfo->vendor_name)); + StlCableInfoTrimTrailingWS(tempStr, sizeof(pCableInfo->vendor_name)); + memcpy(&tempBuf[i], tempStr, strlen(tempStr)); + i = STL_CIB_LINE1_FIELD4; + strcpy(&tempBuf[i], "P/N "); + i = STL_CIB_LINE1_FIELD5; + memcpy(tempStr, pCableInfo->vendor_pn, sizeof(pCableInfo->vendor_pn)); + StlCableInfoTrimTrailingWS(tempStr, sizeof(pCableInfo->vendor_pn)); + memcpy(&tempBuf[i], tempStr, strlen(tempStr)); + i = STL_CIB_LINE1_FIELD6; + strcpy(&tempBuf[i], "Rev "); + i = STL_CIB_LINE1_FIELD7; + memcpy(tempStr, pCableInfo->vendor_rev, sizeof(pCableInfo->vendor_rev)); + StlCableInfoTrimTrailingWS(tempStr, sizeof(pCableInfo->vendor_rev)); + memcpy(&tempBuf[i], tempStr, strlen(tempStr)); + i = STL_CIB_LINE1_FIELD8; + tempBuf[i] = '\0'; + printf("%*s%s\n", indent, "", tempBuf); + if (detail <=1) + break; + //line2 + memset(tempBuf, ' ', sizeof(tempBuf)); + i = 0; + StringCopy(&tempBuf[i], StlCableInfoPowerClassToText(pCableInfo->ext_ident.s.pwr_class_low, pCableInfo->ext_ident.s.pwr_class_high), + strlen(StlCableInfoPowerClassToText(pCableInfo->ext_ident.s.pwr_class_low, pCableInfo->ext_ident.s.pwr_class_high)) + 1); + tempBuf[i + strlen(&tempBuf[i])] = ' '; + i = STL_CIB_LINE2_FIELD2; + strcpy(&tempBuf[i], "S/N "); + i = STL_CIB_LINE2_FIELD3; + memcpy(tempStr, pCableInfo->vendor_sn, sizeof(pCableInfo->vendor_sn)); + StlCableInfoTrimTrailingWS(tempStr, sizeof(pCableInfo->vendor_sn)); + memcpy(&tempBuf[i], tempStr, strlen(tempStr)); + i = STL_CIB_LINE2_FIELD4; + strcpy(&tempBuf[i], "Mfg "); + i = STL_CIB_LINE2_FIELD5; + StlCableInfoDateCodeToText(pCableInfo->date_code, &tempBuf[i]); + printf("%*s%s\n", indent, "", tempBuf); + //line3 + memset(tempBuf, ' ', sizeof(tempBuf)); + i = 0; + sprintf(&tempBuf[i], "OUI 0x%02X%02X%02X", pCableInfo->vendor_oui[0], pCableInfo->vendor_oui[1], pCableInfo->vendor_oui[2]); + printf("%*s%s\n", indent, "", tempBuf); + break; + } else { + printf("%*sQSFP Interpreted CableInfo:\n", indent, ""); + printf("%*sIdentifier: 0x%x\n", indent+4, "", pCableInfo->ident); + memcpy(tempBuf, cableTypeInfo.connectorType, sizeof(cableTypeInfo.connectorType)); + printf("%*sConnector: %s\n", indent+4, "", tempBuf); + StlCableInfoCableTypeToTextLong(pCableInfo->dev_tech.s.xmit_tech, pCableInfo->connector, tempBuf); + printf("%*sDeviceTech: %s\n", indent+4, "", tempBuf); + StlCableInfoOM4LengthToText(pCableInfo->len_om4, cableLenValid, sizeof(tempBuf), tempBuf); + printf("%*sOM4Length: %s\n", indent+4, "", tempBuf); + memcpy(tempStr, pCableInfo->vendor_name, sizeof(pCableInfo->vendor_name)); + StlCableInfoTrimTrailingWS(tempStr, sizeof(pCableInfo->vendor_name)); + printf("%*sVendorName: %s\n", indent+4, "", tempStr); + printf( "%*sVendorOUI: 0x%02x%02x%02x\n", indent+4, "", pCableInfo->vendor_oui[0], + pCableInfo->vendor_oui[1], pCableInfo->vendor_oui[2] ); + memcpy(tempStr, pCableInfo->vendor_pn, sizeof(pCableInfo->vendor_pn)); + StlCableInfoTrimTrailingWS(tempStr, sizeof(pCableInfo->vendor_pn)); + printf("%*sVendorPN: %s\n", indent+4, "", tempStr); + memcpy(tempStr, pCableInfo->vendor_rev, sizeof(pCableInfo->vendor_rev)); + StlCableInfoTrimTrailingWS(tempStr, sizeof(pCableInfo->vendor_rev)); + printf("%*sVendorRev: %s\n", indent+4, "", tempStr); + memcpy(tempBuf, StlCableInfoPowerClassToText(pCableInfo->ext_ident.s.pwr_class_low, pCableInfo->ext_ident.s.pwr_class_high), + strlen(StlCableInfoPowerClassToText(pCableInfo->ext_ident.s.pwr_class_low, pCableInfo->ext_ident.s.pwr_class_high))); + tempStr[strlen(StlCableInfoPowerClassToText(pCableInfo->ext_ident.s.pwr_class_low, pCableInfo->ext_ident.s.pwr_class_high))] = '\0'; + printf("%*sPoweClass: %s\n", indent+4, "", tempStr); + memcpy(tempStr, pCableInfo->vendor_sn, sizeof(pCableInfo->vendor_sn)); + StlCableInfoTrimTrailingWS(tempStr, sizeof(pCableInfo->vendor_sn)); + printf("%*sVendorSN: %s\n", indent+4, "", tempStr); + StlCableInfoDateCodeToText(pCableInfo->date_code, tempBuf); + printf("%*sDateCode: %s\n", indent+4, "", tempBuf); + } + break; + case STL_PORT_TYPE_SI_PHOTONICS: + default: + //printf("%*sCableInfo: N/A for Port Type: %s \n", indent, "", StlPortTypeToText(portType)); + break; + } + break; + case FORMAT_XML: + switch (portType) { + case STL_PORT_TYPE_STANDARD: + printf("%*s\n", indent, ""); + if (detail <= 6) { + StringCopy(tempStr2, cableTypeInfo.cableTypeShortDesc, sizeof(tempStr2)); + XmlPrintStr("DeviceTechShort", tempStr2, indent+4); + //maps to text line 1 + StlCableInfoOM4LengthToText(pCableInfo->len_om4, cableLenValid, sizeof(tempBuf), tempBuf); + XmlPrintStr("OM4Length", tempBuf, indent+4); + XmlPrintStr("Length", tempBuf, indent+4); + + memcpy(tempStr, pCableInfo->vendor_name, sizeof(pCableInfo->vendor_name)); + StlCableInfoTrimTrailingWS(tempStr, sizeof(pCableInfo->vendor_name)); + XmlPrintStrLen("VendorName", tempStr, sizeof(pCableInfo->vendor_name), indent+4); + memcpy(tempStr, pCableInfo->vendor_pn, sizeof(pCableInfo->vendor_pn)); + StlCableInfoTrimTrailingWS(tempStr, sizeof(pCableInfo->vendor_pn)); + XmlPrintStrLen("VendorPN", tempStr, sizeof(pCableInfo->vendor_pn), indent+4); + memcpy(tempStr, pCableInfo->vendor_rev, sizeof(pCableInfo->vendor_rev)); + StlCableInfoTrimTrailingWS(tempStr, sizeof(pCableInfo->vendor_rev)); + XmlPrintStrLen("VendorRev", tempStr, sizeof(pCableInfo->vendor_rev), indent+4); + memcpy(tempStr, pCableInfo->vendor_sn, sizeof(pCableInfo->vendor_sn)); + StlCableInfoTrimTrailingWS(tempStr, sizeof(pCableInfo->vendor_sn)); + XmlPrintStrLen("VendorSN", tempStr, sizeof(pCableInfo->vendor_sn), indent+4); + StlCableInfoDateCodeToText(pCableInfo->date_code, tempBuf); + XmlPrintStrLen("DateCode", (char*)tempBuf, sizeof(tempBuf), indent+4); + XmlPrintHex("VendorOUI", (pCableInfo->vendor_oui[0]<<16) + (pCableInfo->vendor_oui[1]<<8) + pCableInfo->vendor_oui[2], indent+4); + } else { + snprintf(tempBuf, 5, "0x%x", pCableInfo->ident); + XmlPrintStr("Identifier", tempBuf, indent+4); + memcpy(tempBuf, cableTypeInfo.connectorType, sizeof(cableTypeInfo.connectorType)); + XmlPrintStr("Connector", tempBuf, indent+4); + StlCableInfoCableTypeToTextLong(pCableInfo->dev_tech.s.xmit_tech, pCableInfo->connector, tempBuf); + XmlPrintStr("DeviceTech", tempBuf, indent+4); + StlCableInfoOM4LengthToText(pCableInfo->len_om4, cableLenValid, sizeof(tempBuf), tempBuf); + XmlPrintStr("OM4Length", tempBuf, indent+4); + XmlPrintStr("Length", tempBuf, indent+4); + + memcpy(tempStr, pCableInfo->vendor_name, sizeof(pCableInfo->vendor_name)); + StlCableInfoTrimTrailingWS(tempStr, sizeof(pCableInfo->vendor_name)); + XmlPrintStrLen("VendorName", tempStr, sizeof(pCableInfo->vendor_name), indent+4); + memcpy(tempStr, pCableInfo->vendor_pn, sizeof(pCableInfo->vendor_pn)); + StlCableInfoTrimTrailingWS(tempStr, sizeof(pCableInfo->vendor_pn)); + XmlPrintStrLen("VendorPN", tempStr, sizeof(pCableInfo->vendor_pn), indent+4); + memcpy(tempStr, pCableInfo->vendor_rev, sizeof(pCableInfo->vendor_rev)); + StlCableInfoTrimTrailingWS(tempStr, sizeof(pCableInfo->vendor_rev)); + XmlPrintStrLen("VendorRev", tempStr, sizeof(pCableInfo->vendor_rev), indent+4); + StringCopy(tempBuf, StlCableInfoPowerClassToText(pCableInfo->ext_ident.s.pwr_class_low, pCableInfo->ext_ident.s.pwr_class_high), + strlen(StlCableInfoPowerClassToText(pCableInfo->ext_ident.s.pwr_class_low, pCableInfo->ext_ident.s.pwr_class_high)) + 1); + XmlPrintStr("PowerClass", tempBuf, indent+4); + memcpy(tempStr, pCableInfo->vendor_sn, sizeof(pCableInfo->vendor_sn)); + StlCableInfoTrimTrailingWS(tempStr, sizeof(pCableInfo->vendor_sn)); + XmlPrintStrLen("VendorSN", tempStr, sizeof(pCableInfo->vendor_sn), indent+4); + StlCableInfoDateCodeToText(pCableInfo->date_code, tempBuf); + XmlPrintStrLen("DateCode", (char*)tempBuf, sizeof(tempBuf), indent+4); + XmlPrintHex("VendorOUI", (pCableInfo->vendor_oui[0]<<16) + (pCableInfo->vendor_oui[1]<<8) + pCableInfo->vendor_oui[2], indent+4); + } + printf("%*s\n", indent, ""); + break; + case STL_PORT_TYPE_SI_PHOTONICS: + default: + break; + } + break; + default: + break; + } +} // End of ShowCableSummary() + +void ShowCableSummaryDD(uint8_t *pCableData, Format_t format, int indent, int detail, uint8 portType) +{ + // CableInfo is organized in 128-byte pages but is stored in 64-byte half-pages + // For portType STANDARD we use STL_CIB_STD_HIGH_PAGE_ADDR to STL_CIB_STD_END_ADDR + // inclusive (128-255) + // To avoid compiler warnings, data pointer is used for the data portion + // of the STL_CABLE_INFO + STL_CABLE_INFO_UP0_DD *pCableInfo = (STL_CABLE_INFO_UP0_DD *)pCableData; + CableTypeInfoType cableTypeInfo; + char tempStr[STL_CIB_STD_MAX_STRING + 1] = {'\0'}; + char tempStr2[32] = {'\0'}; + char tempBuf[192]; + unsigned int i; + boolean cableLenValid; + + StlCableInfoDecodeCableType(pCableInfo->cable_type, pCableInfo->connector, pCableInfo->ident, &cableTypeInfo); + cableLenValid = cableTypeInfo.cableLengthValid; + + + switch (format) { + case FORMAT_TEXT: + switch (portType) { + case STL_PORT_TYPE_STANDARD: + if (detail <= 6) { + //line1 + memset(tempBuf, ' ', sizeof(tempBuf)); + i = 0; + StringCopy(&tempBuf[i], cableTypeInfo.cableTypeShortDesc, strlen(cableTypeInfo.cableTypeShortDesc)+1); + tempBuf[i + strlen(cableTypeInfo.cableTypeShortDesc)] = ','; +#if 0 + i = STL_CIB_LINE1_FIELD1; + strncpy(&tempBuf[i], cableTypeInfo.cableTypeShortDesc, strlen(cableTypeInfo.cableTypeShortDesc)); + tempBuf[i + strlen(cableTypeInfo.cableTypeShortDesc)] = ','; + tempBuf[i + 1 + strlen(cableTypeInfo.cableTypeShortDesc)] = ' '; +#endif + i = STL_CIB_LINE1_FIELD2; + StlCableInfoDDCableLengthToText(pCableInfo->cableLengthEnc, cableLenValid, MAX_CABLE_LENGTH_STR_LEN, &tempBuf[i]); + tempBuf[i + strlen(&tempBuf[i])] = ' '; + i = STL_CIB_LINE1_FIELD3; + memcpy(tempStr, pCableInfo->vendor_name, sizeof(pCableInfo->vendor_name)); + StlCableInfoTrimTrailingWS(tempStr, sizeof(pCableInfo->vendor_name)); + memcpy(&tempBuf[i], tempStr, strlen(tempStr)); + i = STL_CIB_LINE1_FIELD4; + strcpy(&tempBuf[i], "P/N "); + i = STL_CIB_LINE1_FIELD5; + memcpy(tempStr, pCableInfo->vendor_pn, sizeof(pCableInfo->vendor_pn)); + StlCableInfoTrimTrailingWS(tempStr, sizeof(pCableInfo->vendor_pn)); + memcpy(&tempBuf[i], tempStr, strlen(tempStr)); + i = STL_CIB_LINE1_FIELD6; + strcpy(&tempBuf[i], "Rev "); + i = STL_CIB_LINE1_FIELD7; + memcpy(tempStr, pCableInfo->vendor_rev, sizeof(pCableInfo->vendor_rev)); + StlCableInfoTrimTrailingWS(tempStr, sizeof(pCableInfo->vendor_rev)); + memcpy(&tempBuf[i], tempStr, strlen(tempStr)); + i = STL_CIB_LINE1_FIELD8; + tempBuf[i] = '\0'; + printf("%*s%s\n", indent, "", tempBuf); + if (detail <=1) + break; + //line2 + memset(tempBuf, ' ', sizeof(tempBuf)); + i = 0; + snprintf(&tempBuf[i], 20, "%.2f W max", (float)pCableInfo->powerMax / 4.0); + tempBuf[i + strlen(&tempBuf[i])] = ' '; + i = STL_CIB_LINE2_FIELD2; + strcpy(&tempBuf[i], "S/N "); + i = STL_CIB_LINE2_FIELD3; + memcpy(tempStr, pCableInfo->vendor_sn, sizeof(pCableInfo->vendor_sn)); + StlCableInfoTrimTrailingWS(tempStr, sizeof(pCableInfo->vendor_sn)); + memcpy(&tempBuf[i], tempStr, strlen(tempStr)); + i = STL_CIB_LINE2_FIELD4; + strcpy(&tempBuf[i], "Mfg "); + i = STL_CIB_LINE2_FIELD5; + StlCableInfoDateCodeToText(pCableInfo->date_code, &tempBuf[i]); + printf("%*s%s\n", indent, "", tempBuf); + //line3 + memset(tempBuf, ' ', sizeof(tempBuf)); + i = 0; + sprintf(&tempBuf[i], "OUI 0x%02X%02X%02X", pCableInfo->vendor_oui[0], pCableInfo->vendor_oui[1], pCableInfo->vendor_oui[2]); + printf("%*s%s\n", indent, "", tempBuf); + break; + } else { + printf("%*sQSFP Interpreted CableInfo:\n", indent, ""); + printf("%*sIdentifier: 0x%x\n", indent+4, "", pCableInfo->ident); + snprintf(tempBuf, 20, "%.2f W max", (float)pCableInfo->powerMax / 4.0); + printf("%*sPowerMax: %s\n", indent+4, "", tempBuf); + memcpy(tempBuf, cableTypeInfo.connectorType, sizeof(cableTypeInfo.connectorType)); + printf("%*sConnector: %s\n", indent+4, "", tempBuf); + StlCableInfoCableTypeToTextLong(pCableInfo->cable_type, pCableInfo->connector, tempBuf); + printf("%*sDeviceTech: %s\n", indent+4, "", tempBuf); + StlCableInfoDDCableLengthToText(pCableInfo->cableLengthEnc, cableLenValid, sizeof(tempBuf), tempBuf); + printf("%*sCableLength: %s\n", indent+4, "", tempBuf); + memcpy(tempStr, pCableInfo->vendor_name, sizeof(pCableInfo->vendor_name)); + StlCableInfoTrimTrailingWS(tempStr, sizeof(pCableInfo->vendor_name)); + printf("%*sVendorName: %s\n", indent+4, "", tempStr); + printf( "%*sVendorOUI: 0x%02x%02x%02x\n", indent+4, "", pCableInfo->vendor_oui[0], + pCableInfo->vendor_oui[1], pCableInfo->vendor_oui[2] ); + memcpy(tempStr, pCableInfo->vendor_pn, sizeof(pCableInfo->vendor_pn)); + StlCableInfoTrimTrailingWS(tempStr, sizeof(pCableInfo->vendor_pn)); + printf("%*sVendorPN: %s\n", indent+4, "", tempStr); + memcpy(tempStr, pCableInfo->vendor_rev, sizeof(pCableInfo->vendor_rev)); + StlCableInfoTrimTrailingWS(tempStr, sizeof(pCableInfo->vendor_rev)); + printf("%*sVendorRev: %s\n", indent+4, "", tempStr); + memcpy(tempStr, pCableInfo->vendor_sn, sizeof(pCableInfo->vendor_sn)); + StlCableInfoTrimTrailingWS(tempStr, sizeof(pCableInfo->vendor_sn)); + printf("%*sVendorSN: %s\n", indent+4, "", tempStr); + StlCableInfoDateCodeToText(pCableInfo->date_code, tempBuf); + printf("%*sDateCode: %s\n", indent+4, "", tempBuf); + } + break; + case STL_PORT_TYPE_SI_PHOTONICS: + default: + //printf("%*sCableInfo: N/A for Port Type: %s \n", indent, "", StlPortTypeToText(portType)); + break; + } + break; + case FORMAT_XML: + switch (portType) { + case STL_PORT_TYPE_STANDARD: + printf("%*s\n", indent, ""); + if (detail <= 6) { + StringCopy(tempStr2, cableTypeInfo.cableTypeShortDesc, sizeof(tempStr2)); + XmlPrintStr("DeviceTechShort", tempStr2, indent+4); + //maps to text line 1 + StlCableInfoDDCableLengthToText(pCableInfo->cableLengthEnc, cableLenValid, sizeof(tempBuf), tempBuf); + XmlPrintStr("CableLength", tempBuf, indent+4); + XmlPrintStr("Length", tempBuf, indent+4); + memcpy(tempStr, pCableInfo->vendor_name, sizeof(pCableInfo->vendor_name)); + StlCableInfoTrimTrailingWS(tempStr, sizeof(pCableInfo->vendor_name)); + XmlPrintStrLen("VendorName", tempStr, sizeof(pCableInfo->vendor_name), indent+4); + memcpy(tempStr, pCableInfo->vendor_pn, sizeof(pCableInfo->vendor_pn)); + StlCableInfoTrimTrailingWS(tempStr, sizeof(pCableInfo->vendor_pn)); + XmlPrintStrLen("VendorPN", tempStr, sizeof(pCableInfo->vendor_pn), indent+4); + memcpy(tempStr, pCableInfo->vendor_rev, sizeof(pCableInfo->vendor_rev)); + StlCableInfoTrimTrailingWS(tempStr, sizeof(pCableInfo->vendor_rev)); + XmlPrintStrLen("VendorRev", tempStr, sizeof(pCableInfo->vendor_rev), indent+4); + snprintf(tempBuf, 20, "%.2f W max", (float)pCableInfo->powerMax / 4.0); + XmlPrintStr("PowerMax", tempBuf, indent+4); + memcpy(tempStr, pCableInfo->vendor_sn, sizeof(pCableInfo->vendor_sn)); + StlCableInfoTrimTrailingWS(tempStr, sizeof(pCableInfo->vendor_sn)); + XmlPrintStrLen("VendorSN", tempStr, sizeof(pCableInfo->vendor_sn), indent+4); + StlCableInfoDateCodeToText(pCableInfo->date_code, tempBuf); + XmlPrintStrLen("DateCode", (char*)tempBuf, sizeof(tempBuf), indent+4); + XmlPrintHex("VendorOUI", (pCableInfo->vendor_oui[0]<<16) + (pCableInfo->vendor_oui[1]<<8) + pCableInfo->vendor_oui[2], indent+4); + } else { + StlCableInfoCableTypeToTextShort(pCableInfo->cable_type, pCableInfo->connector, tempBuf); + snprintf(tempBuf, 5, "0x%x", pCableInfo->ident); + XmlPrintStr("Identifier", tempBuf, indent+4); + snprintf(tempBuf, 20, "%.2f W max", (float)pCableInfo->powerMax / 4.0); + XmlPrintStr("PowerMax", tempBuf, indent+4); + memcpy(tempBuf, cableTypeInfo.connectorType, sizeof(cableTypeInfo.connectorType)); + XmlPrintStr("Connector", tempBuf, indent+4); + StlCableInfoCableTypeToTextLong(pCableInfo->cable_type, pCableInfo->connector, tempBuf); + XmlPrintStr("DeviceTech", tempBuf, indent+4); + //maps to text line 1 + StlCableInfoDDCableLengthToText(pCableInfo->cableLengthEnc, cableLenValid, sizeof(tempBuf), tempBuf); + XmlPrintStr("CableLength", tempBuf, indent+4); + XmlPrintStr("Length", tempBuf, indent+4); + memcpy(tempStr, pCableInfo->vendor_name, sizeof(pCableInfo->vendor_name)); + StlCableInfoTrimTrailingWS(tempStr, sizeof(pCableInfo->vendor_name)); + XmlPrintStrLen("VendorName", tempStr, sizeof(pCableInfo->vendor_name), indent+4); + XmlPrintHex("VendorOUI", (pCableInfo->vendor_oui[0]<<16) + (pCableInfo->vendor_oui[1]<<8) + pCableInfo->vendor_oui[2], indent+4); + memcpy(tempStr, pCableInfo->vendor_pn, sizeof(pCableInfo->vendor_pn)); + StlCableInfoTrimTrailingWS(tempStr, sizeof(pCableInfo->vendor_pn)); + XmlPrintStrLen("VendorPN", tempStr, sizeof(pCableInfo->vendor_pn), indent+4); + memcpy(tempStr, pCableInfo->vendor_rev, sizeof(pCableInfo->vendor_rev)); + StlCableInfoTrimTrailingWS(tempStr, sizeof(pCableInfo->vendor_rev)); + XmlPrintStrLen("VendorRev", tempStr, sizeof(pCableInfo->vendor_rev), indent+4); + memcpy(tempStr, pCableInfo->vendor_sn, sizeof(pCableInfo->vendor_sn)); + StlCableInfoTrimTrailingWS(tempStr, sizeof(pCableInfo->vendor_sn)); + XmlPrintStrLen("VendorSN", tempStr, sizeof(pCableInfo->vendor_sn), indent+4); + StlCableInfoDateCodeToText(pCableInfo->date_code, tempBuf); + XmlPrintStrLen("DateCode", (char*)tempBuf, sizeof(tempBuf), indent+4); + } + printf("%*s\n", indent, ""); + break; + case STL_PORT_TYPE_SI_PHOTONICS: + default: + //printf("%*s\n", indent, ""); + //XmlPrintStr("PortTypeNotSupported", StlPortTypeToText(portType), indent+4 ); + //printf("%*s\n", indent, ""); + break; + } + break; + default: + break; + } +} // End of ShowCableSummaryDD() + +// show 1 port in a link in brief 1 line form +void ShowLinkPortBriefSummary(PortData *portp, const char *prefix, + uint64 context, LinkPortSummaryDetailCallback_t *callback, + Format_t format, int indent, int detail) +{ + switch (format) { + case FORMAT_TEXT: + printf("%*s%4s ", indent, "", prefix); + + printf("0x%016"PRIx64" %3u %2s %.*s\n", + portp->nodep->NodeInfo.NodeGUID, + portp->PortNum, + StlNodeTypeToText(portp->nodep->NodeInfo.NodeType), + NODE_DESCRIPTION_ARRAY_SIZE, + g_noname?g_name_marker:(char*)portp->nodep->NodeDesc.NodeString); + if (portp->nodep->enodep && portp->nodep->enodep->details) { + printf("%*sNodeDetails: %s\n", indent+4, "", portp->nodep->enodep->details); + } + if (detail) { + PortSelector* portselp = GetPortSelector(portp); + if (portselp && portselp->details) { + printf("%*sPortDetails: %s\n", indent+4, "", portselp->details); + } + + } + if (detail > 1 && portp->pCableInfoData) + ShowCableSummary(portp->pCableInfoData, FORMAT_TEXT, indent+4, detail-1, portp->PortInfo.PortPhysConfig.s.PortType); + if (portp->pPortCounters && detail > 3 && ! g_persist && ! g_hard) + ShowPortCounters(portp->pPortCounters, format, indent+4, detail-3); + break; + case FORMAT_XML: + // MTU is output as part of LinkFrom directly in tag + printf("%*s\n", indent, "", + portp->nodep->NodeInfo.NodeGUID, portp->PortNum); + XmlPrintHex64("NodeGUID", + portp->nodep->NodeInfo.NodeGUID, indent+4); + if (portp->PortGUID) + XmlPrintHex64("PortGUID", portp->PortGUID, indent+4); + XmlPrintDec("PortNum", portp->PortNum, indent+4); + XmlPrintNodeType(portp->nodep->NodeInfo.NodeType, + indent+4); + XmlPrintNodeDesc((char*)portp->nodep->NodeDesc.NodeString, indent+4); + if (portp->nodep->enodep && portp->nodep->enodep->details) { + XmlPrintOptionalStr("NodeDetails", portp->nodep->enodep->details, indent+4); + } + if (detail) { + PortSelector* portselp = GetPortSelector(portp); + if (portselp && portselp->details) { + XmlPrintOptionalStr("PortDetails", portselp->details, indent+4); + } + + } + if (portp->pPortCounters && detail > 3 && ! g_persist && ! g_hard) + ShowPortCounters(portp->pPortCounters, format, indent+4, detail-3); + + break; + default: + break; + } + if (callback && detail) + (*callback)(context, portp, format, indent+4, detail-1); + if (format == FORMAT_XML) + printf("%*s\n", indent, ""); +} + +// show 1 port in a link in multi-line form with heading per field +void ShowLinkPortSummary(PortData *portp, const char *prefix, + Format_t format, int indent, int detail) +{ + switch (format) { + case FORMAT_TEXT: + printf("%*s%4s Name: %.*s\n", + indent, "", prefix, + NODE_DESCRIPTION_ARRAY_SIZE, + g_noname?g_name_marker:(char*)portp->nodep->NodeDesc.NodeString); + printf("%*sNodeGUID: 0x%016"PRIx64" Type: %s PortNum: %3u\n", + indent+4, "", + portp->nodep->NodeInfo.NodeGUID, + StlNodeTypeToText(portp->nodep->NodeInfo.NodeType), + portp->PortNum); + if (portp->nodep->enodep && portp->nodep->enodep->details) { + printf("%*sNodeDetails: %s\n", indent+4, "", portp->nodep->enodep->details); + } + if (detail) { + PortSelector* portselp = GetPortSelector(portp); + if (portselp && portselp->details) { + printf("%*sPortDetails: %s\n", indent+4, "", portselp->details); + } + } + break; + case FORMAT_XML: + ShowLinkPortBriefSummary(portp, prefix, + 0, NULL, format, indent, detail); + break; + default: + break; + } +} + +// show cable information for a link in brief summary format +void ShowExpectedLinkBriefSummary(ExpectedLink *elinkp, + Format_t format, int indent, int detail) +{ + if (! elinkp) + return; + switch (format) { + case FORMAT_TEXT: + if (elinkp->details) { + printf("%*sLinkDetails: %s\n", indent, "", elinkp->details); + } + if (elinkp->CableData.length || elinkp->CableData.label + || elinkp->CableData.details) { + // TBD should g_noname suppress some of this? + printf("%*sCable: %-*s %-*s\n", + indent, "", + CABLE_LABEL_STRLEN, OPTIONAL_STR(elinkp->CableData.label), + CABLE_LENGTH_STRLEN, OPTIONAL_STR(elinkp->CableData.length)); + if (elinkp->CableData.details) + printf("%*s%s\n", indent, "", elinkp->CableData.details); + } + break; + case FORMAT_XML: + indent-= 4; // hack to fix indent level + if (elinkp->details) { + XmlPrintOptionalStr("LinkDetails", elinkp->details, indent); + } + if (elinkp->CableData.length || elinkp->CableData.label + || elinkp->CableData.details) { + printf("%*s\n", indent, ""); + XmlPrintOptionalStr("CableLabel", elinkp->CableData.label, indent+4); + XmlPrintOptionalStr("CableLength", elinkp->CableData.length, indent+4); + XmlPrintOptionalStr("CableDetails", elinkp->CableData.details, indent+4); + printf("%*s\n", indent, ""); + } + break; + default: + break; + } +} + +// show cable information for a link in multi-line format with field headings +void ShowExpectedLinkSummary(ExpectedLink *elinkp, + Format_t format, int indent, int detail) +{ + if (! elinkp) + return; + ASSERT(elinkp->portp1 && elinkp->portp1->neighbor == elinkp->portp2); + switch (format) { + case FORMAT_TEXT: + if (elinkp->details) { + printf("%*sLinkDetails: %s\n", indent, "", elinkp->details); + } + if (elinkp->CableData.length || elinkp->CableData.label + || elinkp->CableData.details) { + printf("%*sCableLabel: %-*s CableLen: %-*s\n", + indent, "", + CABLE_LABEL_STRLEN, OPTIONAL_STR(elinkp->CableData.label), + CABLE_LENGTH_STRLEN, OPTIONAL_STR(elinkp->CableData.length)); + printf("%*sCableDetails: %s\n", + indent, "", + OPTIONAL_STR(elinkp->CableData.details)); + } + break; + case FORMAT_XML: + ShowExpectedLinkBriefSummary(elinkp, format, indent, detail); + break; + default: + break; + } +} + +// show from side of a link, need to later call ShowLinkToBriefSummary +// useful when traversing trace route and don't have both sides of link handy +void ShowLinkFromBriefSummary(PortData *portp1, + uint64 context, LinkPortSummaryDetailCallback_t *callback, + Format_t format, int indent, int detail) +{ + if (format == FORMAT_XML) { + XmlPrintLinkStartTag("Link", portp1, indent); + indent+=4; + XmlPrintRate(portp1->rate, indent); + XmlPrintDec("Internal", isInternalLink(portp1)?1:0, indent); + if (detail) + ShowExpectedLinkBriefSummary(portp1->elinkp, format, indent+4, detail-1); + } + ShowLinkPortBriefSummary(portp1, StlStaticRateToText(portp1->rate), + context, callback, format, indent, detail); +} + +// show to side of a link, need to call ShowLinkFromBriefSummary before this +// useful when traversing trace route and don't have both sides of link handy +// portp2 can be NULL to "close" the From Summary without additional +// port information and no cable information +// This is useful when reporting trace routes which stay within a single port +void ShowLinkToBriefSummary(PortData *portp2, const char* toprefix, boolean close_link, + uint64 context, LinkPortSummaryDetailCallback_t *callback, + Format_t format, int indent, int detail) +{ + if (format == FORMAT_XML) + indent +=4; + // portp2 should not be NULL, but code this defensively + if (portp2) { + ShowLinkPortBriefSummary(portp2, toprefix, + context, callback, format, indent, detail); + DEBUG_ASSERT(portp2->elinkp == portp2->neighbor->elinkp); + if (detail && format != FORMAT_XML) + ShowExpectedLinkBriefSummary(portp2->elinkp, format, indent+4, detail-1); + else if ((detail > 1 && portp2->pCableInfoData) && format==FORMAT_XML) + ShowCableSummary(portp2->pCableInfoData, FORMAT_XML, indent, detail-1, portp2->PortInfo.PortPhysConfig.s.PortType); + } + if (format == FORMAT_XML && close_link) + printf("%*s\n", indent-4, ""); +} + +// show both sides of a link, portp1 should be the "from" port +void ShowLinkBriefSummary(PortData *portp1, const char* toprefix, Format_t format, int indent, int detail) +{ + ShowLinkFromBriefSummary(portp1, 0, NULL, format, indent, detail); + ShowLinkToBriefSummary(portp1->neighbor, toprefix, TRUE, 0, NULL, format, indent, detail); +} + +/* + * There are 6 cases for routes: + * 1. FI - FI + * 2. FI to self + * 3. SW Port 0 to FI + * 4. FI to SW Port 0 + * 5. SW Port 0 to SW Port 0 + * 6. SW Port 0 to self + * + * Two self consistent Perspectives of these cases: + * + * Perspective 1: Show all "Links" along the route + * - every Link is a connection between 2 devices + * - every Link involves 2 Ports on different devices + * - never show SW Port 0 in a route + * - never show any ports for a "talk to self" route + * - similarly -F route:... would only select ports which -o route would show + * + * Perspective 2: Show all "Ports" along the route + * - route is a list of Ports (not Links) + * - show every port, including port 0 at start and/or end + * - for "talk to self" routes, show just the 1 port involved + * - similarly -F route:... would select all ports involved in the route + * + * The code below implements Perspective 1. Some code in #if 0 and some + * comments discuss possible approaches to implement perspective 2. + * If the future, perspective 2 could become runtime if flags based on a + * new parameter to this function. + */ + +/* obtain and output the trace route information for the given path between + * the given pair of ports. The ports are provided to aid in tranversing + * the PortData and NodeData records and as an easy way to verify the + * concistency of the trace route query results against our previous + * port, node and link record queries. + */ +FSTATUS ShowTraceRoute(EUI64 portGuid, PortData *portp1, PortData *portp2, + IB_PATH_RECORD *pathp, + Format_t format, int indent, int detail) +{ + FSTATUS status; + STL_TRACE_RECORD *pTraceRecords = NULL; + uint32 NumTraceRecords; + int i = -1; + uint32 links = 0; + PortData *p = portp1; + int p_shown = 0; + PQUERY_RESULT_VALUES pQueryResults = NULL; + struct omgt_port *omgt_port_session = NULL; + + if (format == FORMAT_XML) { + printf("%*s\n", indent, ""); + indent+=4; + } + ShowPathRecord(pathp, format, indent, detail); + + if (portp1 == portp2) { + /* special case, internal loopback */ +#if 0 // enable for perspective 2 + //as coded below this results a with just 1 + //For perspective 2, should instead output a list of Ports + //(one port in this case) and show MTU and Rate per Port + if (detail) { + // detail=0 avoids link info and cable info, LinkTo needed to close + // XML output's tag + //ShowLinkBriefSummaryHeader(format, indent+4, 0); + //ShowLinkFromBriefSummary(portp1, 0, NULL, format, indent+4, 0); + //ShowLinkToBriefSummary(NULL, "-> ", TRUE, 0, NULL, format, indent+4, 0); + show port portp1 in report + } + output "1 Ports Traversed" +#else + switch (format) { + case FORMAT_TEXT: + printf("%*s0 Links Traversed\n", indent, ""); + break; + case FORMAT_XML: + printf("%*s0\n", indent, ""); + break; + default: + break; + } +#endif + status = FSUCCESS; + goto done; + } + if (portp1->neighbor == portp2) { + /* special case, single link traversed */ + // Since portp1 has a neighbor, neither port is SW Port 0 +#if 0 // enable for perspective 2 + if (detail) { + show port portp1 in report + show port portp2 in report + } + output "2 Ports Traversed" +#else + if (detail) { + ShowLinkBriefSummaryHeader(format, indent+4, detail-1); + ShowLinkBriefSummary(portp1, "-> ", format, indent+4, detail-1); + } + switch (format) { + case FORMAT_TEXT: + printf("%*s1 Links Traversed\n", indent, ""); + break; + case FORMAT_XML: + printf("%*s1\n", indent, ""); + break; + default: + break; + } +#endif + status = FSUCCESS; + goto done; + } + + + if (!(g_Fabric.flags & FF_SMADIRECT) && ! g_snapshot_in_file) { + struct omgt_params params = {.debug_file = g_verbose > 2 ? stdout : NULL}; + status = omgt_open_port_by_guid(&omgt_port_session, portGuid, ¶ms); + if (status != FSUCCESS) { + fprintf(stderr, "Unable to open fabric interface.\n"); + goto done; + } else { + omgt_set_timeout(omgt_port_session, g_ms_timeout); + status = GetTraceRoute(omgt_port_session, pathp, &pQueryResults); + if (FSUCCESS != status) { + g_exitstatus = 1; + goto done; + } + } + NumTraceRecords = ((STL_TRACE_RECORD_RESULTS*)pQueryResults->QueryResult)->NumTraceRecords; + pTraceRecords = ((STL_TRACE_RECORD_RESULTS*)pQueryResults->QueryResult)->TraceRecords; + } else { + status = GenTraceRoutePath(&g_Fabric, pathp, g_rc, &pTraceRecords, &NumTraceRecords); + if (FSUCCESS != status) { + if (status == FUNAVAILABLE) { + fprintf(stderr, "opareport: Routing Tables not available in snapshot\n"); + g_exitstatus = 1; + } else if (status == FNOT_DONE) { + switch (format) { + case FORMAT_TEXT: + printf("%*sRoute Incomplete\n", indent, ""); + break; + case FORMAT_XML: + printf("%*s0 \n", indent, ""); + break; + default: + break; + } + // don't fail just because some routes are incomplete + status = FSUCCESS; + } else { + fprintf(stderr, "opareport: Unable to determine route: (status=0x%x): %s\n", status, iba_fstatus_msg(status)); + g_exitstatus = 1; + } + goto done; + } + } + + ASSERT(NumTraceRecords > 0); + //printf("%*s%d Hops\n", indent, "", NumTraceRecords-1); + + /* the first Trace record should be the exit from portp1, however + * not all versions of the SM report this record + */ + if (detail) + ShowLinkBriefSummaryHeader(format, indent+4, detail-1); + if (pTraceRecords[0].NodeType != portp1->nodep->NodeInfo.NodeType) { + /* workaround SM bug, did not report initial exit port */ + // assume portp1 is not a Switch Port 0 + p = portp1->neighbor; + if (! p) { + DBGPRINT("incorrect 1st trace record\n"); + goto badroute; + } + if (detail) { +#if 0 // enable for perspective 2 + show port portp1 in report +#else + ShowLinkFromBriefSummary(portp1, 0, NULL, format, indent+4, detail-1); +#endif + } + } + for (i=0; i< NumTraceRecords; i++) { + if (g_verbose) + ShowTraceRecord(&pTraceRecords[i], format, indent+4, detail-1); + if (p != portp1) { + if (detail) { +#if 0 // enable for perspective 2 + show port p in report +#else + ShowLinkToBriefSummary(p, "-> ", TRUE, 0, NULL, format, indent+4, detail-1); +#endif + } + links++; + p_shown = 1; + } + if (pTraceRecords[i].NodeType != STL_NODE_FI) { +#if 0 // enable for perspective 2 + if (i==0 && p == portp1) // must be starting at switch Port 0 + output portp1 to report +#endif + p = FindNodePort(p->nodep, pTraceRecords[i].ExitPort); + if (! p) { + DBGPRINT("SW port not found\n"); + goto badroute; + } + if (0 == p->PortNum) { + /* Switch Port 0 thus must be final port */ + if (i+1 != NumTraceRecords) { + DBGPRINT("final switch port 0 error\n"); + goto badroute; + } +#if 0 // enable for perspective 2 + if (detail) + show port p in report +#endif + break; + } + + if (detail) { +#if 0 // enable for perspective 2 + show port p in report +#else + ShowLinkFromBriefSummary(p, 0, NULL, format, indent+4, detail-1); +#endif + } + if (p == portp2) { + // this should not happen. If we reach portp2 as the exit + // port of a switch, that implies portp2 must be port 0 of + // the switch which the test above should have caught + // but it doesn't hurt to have this redundant test here to be + // safe. + /* final port must be Switch Port 0 */ + if (i+1 != NumTraceRecords) { + DBGPRINT("final switch port 0 error\n"); + goto badroute; + } + } else { + p = p->neighbor; + if (! p) { + DBGPRINT("incorrect neighbor port\n"); + goto badroute; + } + p_shown = 0; + } + } else if (i == 0) { + /* since we caught FI to FI case above, SM must have given us + * initial Node in path + */ + if (detail) { +#if 0 // enable for perspective 2 + show port portp1 in report +#else + ShowLinkFromBriefSummary(portp1, 0, NULL, format, indent+4, detail-1); +#endif + } + /* unfortunately spec says Exit and Entry Port are 0 for FI, so + * can't verify consistency with portp1 + */ + p = portp1->neighbor; + if (! p) { + DBGPRINT("1st port with no neighbor\n"); + goto badroute; + } + p_shown = 0; + } else if (i+1 != NumTraceRecords) { + DBGPRINT("extra unexpected trace records\n"); + goto badroute; + } + } + if (! p_shown) { + /* workaround SM bug, did not report final hop in route */ + if (detail) { +#if 0 // enable for perspective 2 + show port p in report +#else + ShowLinkToBriefSummary(p, "-> ", TRUE, 0, NULL, format, indent+4, detail-1); +#endif + } + } + if (p != portp2) { + DBGPRINT("ended at wrong port\n"); + goto badroute; + } +#if 0 // enable for perspective 2 + show Ports Traversed +#else + switch (format) { + case FORMAT_TEXT: + printf("%*s%u Links Traversed\n", indent, "", links); + break; + case FORMAT_XML: + printf("%*s%u\n", indent, "", links); + break; + default: + break; + } +#endif + +done: + if (format == FORMAT_XML) { + indent-=4; + printf("%*s\n", indent, ""); + } + + if (pQueryResults) + omgt_free_query_result_buffer(pQueryResults); + if (omgt_port_session != NULL) + omgt_close_port(omgt_port_session); + if (g_snapshot_in_file && pTraceRecords) + MemoryDeallocate(pTraceRecords); + return status; + +badroute: + status = FSUCCESS; // might as well process what we can + fprintf(stderr, "%*sRoute reported by SM inconsistent with Trace Route\n", indent+4, ""); + if (g_verbose && i+1 < NumTraceRecords) { + if (format == FORMAT_TEXT) + printf("%*sRemainder of Route:\n", indent+4, ""); + // Don't repeat records we already output above + for (i=i+1; i< NumTraceRecords; i++) + ShowTraceRecord(&pTraceRecords[i], format, indent+8, detail-1); + } + goto done; +} + +/* show trace routes for all paths between 2 given ports */ +FSTATUS ShowPortsTraceRoutes(EUI64 portGuid, PortData *portp1, PortData *portp2, Format_t format, int indent, int detail) +{ + FSTATUS status; + + PQUERY_RESULT_VALUES pQueryResults = NULL; + uint32 NumPathRecords; + IB_PATH_RECORD *pPathRecords = NULL; + struct omgt_port *omgt_port_session = NULL; + + switch (format) { + case FORMAT_TEXT: + printf("%*sRoutes between ports:\n", indent, ""); + ShowLinkPortBriefSummary(portp1, " ", 0, NULL, format, indent, 0); + ShowLinkPortBriefSummary(portp2, "and ", 0, NULL, format, indent, 0); + break; + case FORMAT_XML: + printf("%*s\n", indent, ""); + ShowLinkPortBriefSummary(portp1, " ", 0, NULL, format, indent+4, 0); + ShowLinkPortBriefSummary(portp2, "and ", 0, NULL, format, indent+4, 0); + break; + default: + break; + } + + if (! g_snapshot_in_file) { + struct omgt_params params = {.debug_file = g_verbose > 2 ? stdout : NULL}; + status = omgt_open_port_by_guid(&omgt_port_session, portGuid, ¶ms); + if (FSUCCESS != status) + goto done; + omgt_set_timeout(omgt_port_session, g_ms_timeout); + status = GetPaths(omgt_port_session, portp1, portp2, &pQueryResults); + if (FSUCCESS != status) + goto done; + NumPathRecords = ((PATH_RESULTS*)pQueryResults->QueryResult)->NumPathRecords; + pPathRecords = ((PATH_RESULTS*)pQueryResults->QueryResult)->PathRecords; + } else { + status = GenPaths(&g_Fabric, portp1, portp2, &pPathRecords, &NumPathRecords); + if (FSUCCESS != status) + goto done; + } + + switch (format) { + case FORMAT_TEXT: + printf("%*s%d Paths\n", indent, "", NumPathRecords); + break; + case FORMAT_XML: + printf("%*s%d\n", indent+4, "", NumPathRecords); + break; + default: + break; + } + if (detail) { + int i; + + for (i=0; i< NumPathRecords; i++) { + ShowTraceRoute(portGuid, portp1, portp2, &pPathRecords[i], format, indent+4, detail-1); + } + } + +done: + if (format == FORMAT_XML) + printf("%*s\n", indent, ""); + + if (pQueryResults) + omgt_free_query_result_buffer(pQueryResults); + if (omgt_port_session != NULL) + omgt_close_port(omgt_port_session); + if (g_snapshot_in_file && pPathRecords) + MemoryDeallocate(pPathRecords); + + return status; +} + +/* show trace routes for all paths between given port and node */ +FSTATUS ShowPortNodeTraceRoutes(EUI64 portGuid, PortData *portp1, NodeData *nodep2, Format_t format, int indent, int detail) +{ + cl_map_item_t *p; + + for (p=cl_qmap_head(&nodep2->Ports); p != cl_qmap_end(&nodep2->Ports); p = cl_qmap_next(p)) { + PortData *portp2= PARENT_STRUCT(p, PortData, NodePortsEntry); + ShowPortsTraceRoutes(portGuid, portp1, portp2, format, indent, detail); + } + return FSUCCESS; +} + +/* show trace routes for all paths between given port and point */ +FSTATUS ShowPortPointTraceRoutes(EUI64 portGuid, PortData *portp1, Point *point2, Format_t format, int indent, int detail) +{ + switch (point2->Type) { + case POINT_TYPE_PORT: + return ShowPortsTraceRoutes(portGuid, portp1, point2->u.portp, format, indent, detail); + case POINT_TYPE_PORT_LIST: + { + LIST_ITERATOR i; + DLIST *pList = &point2->u.portList; + + for (i=ListHead(pList); i != NULL; i = ListNext(pList, i)) { + PortData *portp = (PortData*)ListObj(i); + ShowPortsTraceRoutes(portGuid, portp1, portp, format, indent, detail); + } + } + return FSUCCESS; + case POINT_TYPE_NODE: + return ShowPortNodeTraceRoutes(portGuid, portp1, point2->u.nodep, format, indent, detail); + case POINT_TYPE_NODE_LIST: + { + LIST_ITERATOR i; + DLIST *pList = &point2->u.nodeList; + + for (i=ListHead(pList); i != NULL; i = ListNext(pList, i)) { + NodeData *nodep = (NodeData*)ListObj(i); + ShowPortNodeTraceRoutes(portGuid, portp1, nodep, format, indent, detail); + } + } + return FSUCCESS; + case POINT_TYPE_IOC: + return ShowPortNodeTraceRoutes(portGuid, portp1, point2->u.iocp->ioup->nodep, format, indent, detail); + case POINT_TYPE_IOC_LIST: + { + LIST_ITERATOR i; + DLIST *pList = &point2->u.nodeList; + + for (i=ListHead(pList); i != NULL; i = ListNext(pList, i)) { + IocData *iocp = (IocData*)ListObj(i); + ShowPortNodeTraceRoutes(portGuid, portp1, iocp->ioup->nodep, format, indent, detail); + } + } + return FSUCCESS; + case POINT_TYPE_SYSTEM: + { + cl_map_item_t *p; + SystemData *systemp = point2->u.systemp; + + for (p=cl_qmap_head(&systemp->Nodes); p != cl_qmap_end(&systemp->Nodes); p = cl_qmap_next(p)) { + NodeData *nodep = PARENT_STRUCT(p, NodeData, SystemNodesEntry); + ShowPortNodeTraceRoutes(portGuid, portp1, nodep, format, indent, detail); + } + return FSUCCESS; + } + default: + return FINVALID_PARAMETER; + } +} + +/* show trace routes for all paths between given node and point */ +FSTATUS ShowNodePointTraceRoutes(EUI64 portGuid, NodeData *nodep1, Point *point2, Format_t format, int indent, int detail) +{ + cl_map_item_t *p; + + for (p=cl_qmap_head(&nodep1->Ports); p != cl_qmap_end(&nodep1->Ports); p = cl_qmap_next(p)) { + PortData *portp1 = PARENT_STRUCT(p, PortData, NodePortsEntry); + ShowPortPointTraceRoutes(portGuid, portp1, point2, format, indent, detail); + } + return FSUCCESS; +} + +/* show trace routes for all paths between 2 given points */ +FSTATUS ShowPointsTraceRoutes(EUI64 portGuid, Point *point1, Point *point2, Format_t format, int indent, int detail) +{ + switch (point1->Type) { + case POINT_TYPE_PORT: + return ShowPortPointTraceRoutes(portGuid, point1->u.portp, point2, format, indent, detail); + case POINT_TYPE_PORT_LIST: + { + LIST_ITERATOR i; + DLIST *pList = &point1->u.portList; + + for (i=ListHead(pList); i != NULL; i = ListNext(pList, i)) { + PortData *portp = (PortData*)ListObj(i); + ShowPortPointTraceRoutes(portGuid, portp, point2, format, indent, detail); + } + } + return FSUCCESS; + case POINT_TYPE_NODE: + return ShowNodePointTraceRoutes(portGuid, point1->u.nodep, point2, format, indent, detail); + case POINT_TYPE_NODE_LIST: + { + LIST_ITERATOR i; + DLIST *pList = &point1->u.nodeList; + + for (i=ListHead(pList); i != NULL; i = ListNext(pList, i)) { + NodeData *nodep = (NodeData*)ListObj(i); + ShowNodePointTraceRoutes(portGuid, nodep, point2, format, indent, detail); + } + } + return FSUCCESS; + case POINT_TYPE_IOC: + return ShowNodePointTraceRoutes(portGuid, point1->u.iocp->ioup->nodep, point2, format, indent, detail); + case POINT_TYPE_IOC_LIST: + { + LIST_ITERATOR i; + DLIST *pList = &point1->u.iocList; + + for (i=ListHead(pList); i != NULL; i = ListNext(pList, i)) { + IocData *iocp = (IocData*)ListObj(i); + ShowNodePointTraceRoutes(portGuid, iocp->ioup->nodep, point2, format, indent, detail); + } + } + return FSUCCESS; + case POINT_TYPE_SYSTEM: + { + cl_map_item_t *p; + SystemData *systemp = point1->u.systemp; + + for (p=cl_qmap_head(&systemp->Nodes); p != cl_qmap_end(&systemp->Nodes); p = cl_qmap_next(p)) { + NodeData *nodep = PARENT_STRUCT(p, NodeData, SystemNodesEntry); + ShowNodePointTraceRoutes(portGuid, nodep, point2, format, indent, detail); + } + return FSUCCESS; + } + default: + return FINVALID_PARAMETER; + } +} + +void ShowPointNodeBriefSummary(const char* prefix, NodeData *nodep, Format_t format, int indent, int detail) +{ + switch (format) { + case FORMAT_TEXT: + printf("%*s%s0x%016"PRIx64" %s %.*s\n", + indent, "", prefix, + nodep->NodeInfo.NodeGUID, + StlNodeTypeToText(nodep->NodeInfo.NodeType), + NODE_DESCRIPTION_ARRAY_SIZE, + g_noname?g_name_marker:(char*)nodep->NodeDesc.NodeString); + if (nodep->enodep && nodep->enodep->details) { + printf("%*sNodeDetails: %s\n", indent+4, "", nodep->enodep->details); + } + break; + case FORMAT_XML: + printf("%*s\n", indent, "", + nodep->NodeInfo.NodeGUID); + XmlPrintHex64("NodeGUID", nodep->NodeInfo.NodeGUID, + indent+4); + XmlPrintNodeType(nodep->NodeInfo.NodeType, indent+4); + XmlPrintNodeDesc( + (char*)nodep->NodeDesc.NodeString, indent+4); + if (nodep->enodep && nodep->enodep->details) { + XmlPrintOptionalStr("NodeDetails", nodep->enodep->details, indent+4); + } + printf("%*s\n", indent, ""); + break; + default: + break; + } +} + +void ShowPointPortBriefSummary(const char* prefix, PortData *portp, Format_t format, int indent, int detail) +{ + switch (format) { + case FORMAT_TEXT: + if (portp->PortGUID) + printf("%*s%s%3u 0x%016"PRIx64"\n", + indent, "", prefix, + portp->PortNum, + portp->PortGUID); + else + printf("%*s%s%3u\n", + indent, "", prefix, + portp->PortNum); + ShowPointNodeBriefSummary("in Node: ", portp->nodep, format, + indent+4, detail); + break; + case FORMAT_XML: + printf("%*s\n", indent, "", + portp->nodep->NodeInfo.NodeGUID, portp->PortNum); + XmlPrintDec("PortNum", portp->PortNum, indent+4); + if (portp->PortGUID) + XmlPrintHex64("PortGUID", portp->PortGUID, indent+4); + ShowPointNodeBriefSummary("in Node: ", portp->nodep, format, + indent+4, detail); + printf("%*s\n", indent, ""); + break; + default: + break; + } +} + +// show 1 port selector in link data in brief form +// designed to be called for side 1 then side 2 +void ShowExpectedLinkPortSelBriefSummary(const char* prefix, + ExpectedLink *elinkp, PortSelector *portselp, + uint8 side, ExpectedLinkSummaryDetailCallback_t *callback, + Format_t format, int indent, int detail) +{ + DEBUG_ASSERT(side == 1 || side == 2); + switch (format) { + case FORMAT_TEXT: + { + int prefix_len = strlen(prefix); + if (side == 1) { + printf("%*s%s%4s ", indent, "", prefix, + elinkp->expected_rate? + StlStaticRateToText(elinkp->expected_rate) + :" "); + } else { + printf("%*s%*s%4s ", indent, "", prefix_len, "", + "<-> "); + } + if (side == 1 && elinkp->expected_mtu) + printf("%5s ", + IbMTUToText(elinkp->expected_mtu)); + else + printf(" "); + if (portselp) { + if (portselp->NodeGUID) + printf("0x%016"PRIx64, portselp->NodeGUID); + else + printf(" "); + if (portselp->gotPortNum) + printf(" %3u ",portselp->PortNum); + else if (portselp->PortGUID) + printf(" 0x%016"PRIx64, portselp->PortGUID); + else + printf(" "); + if (portselp->NodeType) + printf(" %s", + StlNodeTypeToText(portselp->NodeType)); + else + printf(" "); + if (portselp->NodeDesc) + printf(" %.*s\n", + NODE_DESCRIPTION_ARRAY_SIZE, g_noname?g_name_marker:portselp->NodeDesc); + else + printf("\n"); + if (detail) { + if (portselp->details) { + // TBD should g_noname suppress some of this? + printf("%*sPortDetails: %s\n", indent+4+prefix_len, "", portselp->details); + } + } + } + } + break; + case FORMAT_XML: + // MTU is output as part of LinkFrom directly in tag + if (portselp) { + printf("%*s\n", indent, "", side); + if (portselp->NodeGUID) + XmlPrintHex64("NodeGUID", portselp->NodeGUID, indent+4); + if (portselp->gotPortNum) + XmlPrintDec("PortNum", portselp->PortNum, indent+4); + if (portselp->PortGUID) + XmlPrintHex64("PortGUID", portselp->PortGUID, indent+4); + if (portselp->NodeType) + XmlPrintNodeType(portselp->NodeType, indent+4); + if (portselp->NodeDesc) + XmlPrintNodeDesc(portselp->NodeDesc, indent+4); + if (detail) { + if (portselp->details) { + // TBD should g_noname suppress some of this? + XmlPrintOptionalStr("PortDetails", portselp->details, indent+4); + } + } + } + break; + default: + break; + } + if (callback && detail) + (*callback)(elinkp, side, format, indent+4, detail-1); + if (format == FORMAT_XML) + printf("%*s\n", indent, ""); +} + +void ShowPointExpectedLinkBriefSummary(const char* prefix, ExpectedLink *elinkp, Format_t format, int indent, int detail) +{ + // top level information about link + if (format == FORMAT_XML) { + printf("%*s\n", indent, "", (uint64)(uintn)elinkp); + indent+=4; + if (elinkp->expected_rate) + XmlPrintRate(elinkp->expected_rate, indent); + if (elinkp->expected_mtu) + XmlPrintDec("MTU", + GetBytesFromMtu(elinkp->expected_mtu), indent); + XmlPrintDec("Internal", elinkp->internal, indent); + if (detail) + ShowExpectedLinkBriefSummary(elinkp, format, indent+4, detail-1); + } + + // From Side (Port 1) + ShowExpectedLinkPortSelBriefSummary(prefix, elinkp, elinkp->portselp1, + 1, NULL, format, indent, detail); + + // To Side (Port 2) + ShowExpectedLinkPortSelBriefSummary(prefix, elinkp, elinkp->portselp2, + 2, NULL, format, indent, detail); + + // Summary information about Link itself + if (detail && format != FORMAT_XML) + ShowExpectedLinkBriefSummary(elinkp, format, indent+4, detail-1); + if (format == FORMAT_XML) + printf("%*s\n", indent-4, ""); +} + +void ShowPointBriefSummary(Point* point, uint8 find_flag, Format_t format, int indent, int detail) +{ + ASSERT(PointValid(point)); + if (find_flag & FIND_FLAG_FABRIC) { + switch (point->Type) { + case POINT_TYPE_NONE: + break; + case POINT_TYPE_PORT: + ShowPointPortBriefSummary("Port: ", point->u.portp, format, indent, detail); + break; + case POINT_TYPE_PORT_LIST: + { + LIST_ITERATOR i; + DLIST *pList = &point->u.portList; + + switch (format) { + case FORMAT_TEXT: + printf("%*s%u Ports:\n", + indent, "", + ListCount(pList)); + break; + case FORMAT_XML: + printf("%*s\n", indent, ""); + XmlPrintDec("Count", ListCount(pList), indent+4); + break; + default: + break; + } + for (i=ListHead(pList); i != NULL; i = ListNext(pList, i)) { + PortData *portp = (PortData*)ListObj(i); + ShowPointPortBriefSummary("", portp, format, indent+4, detail); + } + if (format == FORMAT_XML) { + printf("%*s\n", + indent, ""); + } + break; + } + case POINT_TYPE_NODE: + ShowPointNodeBriefSummary("Node: ", point->u.nodep, format, indent, detail); + break; + case POINT_TYPE_NODE_LIST: + { + LIST_ITERATOR i; + DLIST *pList = &point->u.nodeList; + + switch (format) { + case FORMAT_TEXT: + printf("%*s%u Nodes:\n", + indent, "", + ListCount(pList)); + break; + case FORMAT_XML: + printf("%*s\n", indent, ""); + XmlPrintDec("Count", ListCount(pList), indent+4); + break; + default: + break; + } + for (i=ListHead(pList); i != NULL; i = ListNext(pList, i)) { + NodeData *nodep = (NodeData*)ListObj(i); + ShowPointNodeBriefSummary("", nodep, format, indent+4, detail); + } + if (format == FORMAT_XML) { + printf("%*s\n", indent, ""); + } + break; + } + case POINT_TYPE_IOC: + // TBD extract this and list code into common function + switch (format) { + case FORMAT_TEXT: + printf("%*sIoc: %3u 0x%016"PRIx64" %.*s\n", + indent, "", + point->u.iocp->IocSlot, + point->u.iocp->IocProfile.IocGUID, + IOC_IDSTRING_SIZE, + g_noname?g_name_marker:(char*)point->u.iocp->IocProfile.IDString); + break; + case FORMAT_XML: + printf("%*s\n", indent, "", + point->u.iocp->IocProfile.IocGUID); + XmlPrintDec("Slot", point->u.iocp->IocSlot, indent+4); + XmlPrintHex64("IocGUID", point->u.iocp->IocProfile.IocGUID, indent+4); + XmlPrintIocIDString( + (char*)point->u.iocp->IocProfile.IDString, indent+4); + break; + default: + break; + } + ShowPointNodeBriefSummary("in Node: ", point->u.iocp->ioup->nodep, + format, indent+4, detail); + if (format == FORMAT_XML) { + printf("%*s\n", indent, ""); + } + break; + case POINT_TYPE_IOC_LIST: + { + LIST_ITERATOR i; + DLIST *pList = &point->u.iocList; + + switch (format) { + case FORMAT_TEXT: + printf("%*s%u IOCs:\n", + indent, "", + ListCount(pList)); + break; + case FORMAT_XML: + printf("%*s\n", indent, ""); + XmlPrintDec("Count", ListCount(pList), indent+4); + break; + default: + break; + } + for (i=ListHead(pList); i != NULL; i = ListNext(pList, i)) { + IocData *iocp = (IocData*)ListObj(i); + switch (format) { + case FORMAT_TEXT: + printf("%*s%3u 0x%016"PRIx64" %.*s\n", + indent+4, "", + iocp->IocSlot, + iocp->IocProfile.IocGUID, + IOC_IDSTRING_SIZE, + g_noname?g_name_marker:(char*)iocp->IocProfile.IDString); + break; + case FORMAT_XML: + printf("%*s\n", indent+4, "", + iocp->IocProfile.IocGUID); + XmlPrintDec("Slot", iocp->IocSlot, indent+8); + XmlPrintHex64("IocGUID", iocp->IocProfile.IocGUID, indent+8); + XmlPrintIocIDString( + (char*)iocp->IocProfile.IDString, indent+8); + break; + default: + break; + } + ShowPointNodeBriefSummary("in Node: ", iocp->ioup->nodep, + format, indent+8, detail); + if (format == FORMAT_XML) { + printf("%*s\n", indent+4, ""); + } + } + if (format == FORMAT_XML) { + printf("%*s\n", + indent, ""); + } + break; + } + case POINT_TYPE_SYSTEM: + { + SystemData *systemp = point->u.systemp; + cl_map_item_t *p; + + switch (format) { + case FORMAT_TEXT: + printf("%*sSystem: 0x%016"PRIx64"\n", + indent, "", + systemp->SystemImageGUID); + break; + case FORMAT_XML: + printf("%*s\n", indent, "", + systemp->SystemImageGUID?systemp->SystemImageGUID: + PARENT_STRUCT(cl_qmap_head(&systemp->Nodes), NodeData, SystemNodesEntry)->NodeInfo.NodeGUID); + XmlPrintHex64("SystemImageGUID", systemp->SystemImageGUID, indent+4); + break; + default: + break; + } + for (p=cl_qmap_head(&systemp->Nodes); p != cl_qmap_end(&systemp->Nodes); p = cl_qmap_next(p)) { + NodeData *nodep = PARENT_STRUCT(p, NodeData, SystemNodesEntry); + ShowPointNodeBriefSummary("Node: ", nodep, format, indent+4, detail); + } + if (format == FORMAT_XML) { + printf("%*s\n", indent, ""); + } + break; + } + case POINT_TYPE_NODE_PAIR_LIST: + { + LIST_ITERATOR i, j; + int noOfLeftNodes, noOfRightNodes; + DLIST *pList1 = &point->u.nodePairList.nodePairList1; + DLIST *pList2 = &point->u.nodePairList.nodePairList2; + + noOfLeftNodes = ListCount(pList1); + noOfRightNodes = ListCount(pList2); + + if (noOfLeftNodes != noOfRightNodes) { + fprintf(stderr, "Pairs are not complete \n"); + break; + } + + switch (format) { + case FORMAT_TEXT: + printf("%*s%u Node Pairs:\n", + indent, "", + ListCount(pList1)); + break; + case FORMAT_XML: + printf("%*s\n", indent, ""); + XmlPrintDec("Count", ListCount(pList1), indent+4); + break; + default: + break; + } + for (i = ListHead(pList1), j = ListHead(pList2); (i != NULL && j != NULL); + i = ListNext(pList1, i), j = ListNext(pList2, j) ) { + NodeData *nodep1 = (NodeData*)ListObj(i); + NodeData *nodep2 = (NodeData*)ListObj(j); + ShowPointNodeBriefSummary("NodePair: ", nodep1, format, indent+4, detail); + ShowPointNodeBriefSummary(" ", nodep2, format, indent+4, detail); + } + if (format == FORMAT_XML) { + printf("%*s\n", indent, ""); + } + break; + } + } + } + if (find_flag & FIND_FLAG_ENODE) { + switch (point->EnodeType) { + case POINT_ENODE_TYPE_NONE: + break; + case POINT_ENODE_TYPE_NODE: + ShowExpectedNodeBriefSummary("Input Node: ", point->u2.enodep, "InputNode", TRUE, format, indent, detail); + break; + case POINT_ENODE_TYPE_NODE_LIST: + { + LIST_ITERATOR i; + DLIST *pList = &point->u2.enodeList; + + switch (format) { + case FORMAT_TEXT: + printf("%*s%u Input Nodes:\n", + indent, "", + ListCount(pList)); + break; + case FORMAT_XML: + printf("%*s\n", indent, ""); + XmlPrintDec("Count", ListCount(pList), indent+4); + break; + default: + break; + } + for (i=ListHead(pList); i != NULL; i = ListNext(pList, i)) { + ExpectedNode *enodep = (ExpectedNode*)ListObj(i); + ShowExpectedNodeBriefSummary("", enodep, "InputNode", TRUE, format, indent+4, detail); + } + if (format == FORMAT_XML) { + printf("%*s\n", indent, ""); + } + break; + } + } + } + if (find_flag & FIND_FLAG_ESM) { + switch (point->EsmType) { + case POINT_ESM_TYPE_NONE: + break; + case POINT_ESM_TYPE_SM: + ShowExpectedSMBriefSummary("Input SM: ", point->u3.esmp, "InputSM", TRUE, format, indent, detail); + break; + case POINT_ESM_TYPE_SM_LIST: + { + LIST_ITERATOR i; + DLIST *pList = &point->u3.esmList; + + switch (format) { + case FORMAT_TEXT: + printf("%*s%u Input SMs:\n", + indent, "", + ListCount(pList)); + break; + case FORMAT_XML: + printf("%*s\n", indent, ""); + XmlPrintDec("Count", ListCount(pList), indent+4); + break; + default: + break; + } + for (i=ListHead(pList); i != NULL; i = ListNext(pList, i)) { + ExpectedSM *esmp = (ExpectedSM*)ListObj(i); + ShowExpectedSMBriefSummary("", esmp, "InputSM", TRUE, format, indent+4, detail); + } + if (format == FORMAT_XML) { + printf("%*s\n", indent, ""); + } + break; + } + } + } + if (find_flag & FIND_FLAG_ELINK) { + switch (point->ElinkType) { + case POINT_ELINK_TYPE_NONE: + break; + case POINT_ELINK_TYPE_LINK: + ShowPointExpectedLinkBriefSummary("Input Link: ", point->u4.elinkp, format, indent, detail); + break; + case POINT_ELINK_TYPE_LINK_LIST: + { + LIST_ITERATOR i; + DLIST *pList = &point->u4.elinkList; + + switch (format) { + case FORMAT_TEXT: + printf("%*s%u Input Links:\n", + indent, "", + ListCount(pList)); + break; + case FORMAT_XML: + printf("%*s\n", indent, ""); + XmlPrintDec("Count", ListCount(pList), indent+4); + break; + default: + break; + } + for (i=ListHead(pList); i != NULL; i = ListNext(pList, i)) { + ExpectedLink *elinkp = (ExpectedLink*)ListObj(i); + ShowPointExpectedLinkBriefSummary("", elinkp, format, indent+4, detail); + } + if (format == FORMAT_XML) { + printf("%*s\n", indent, ""); + } + break; + } + } + } +} + +void ShowPointFocus(Point* focus, uint8 find_flag, Format_t format, int indent, int detail) +{ + if (! focus || g_quietfocus) + return; + if (PointValid(focus)) { + switch (format) { + case FORMAT_TEXT: + printf("%*sFocused on:\n", indent, ""); + break; + case FORMAT_XML: + printf("%*s\n", indent, ""); + break; + default: + break; + } + ShowPointBriefSummary(focus, find_flag, format, indent+4, detail); + if (format == FORMAT_XML) + printf("%*s\n", indent, ""); + } + if (format == FORMAT_TEXT) + printf("\n"); +} + +// output verbose summary of a IO Service Entry +void ShowIoServiceSummary(IOC_SERVICE *srvp, Format_t format, int indent, int detail) +{ + switch (format) { + case FORMAT_TEXT: + printf("%*sName: %.*s\n", indent, "", IOC_SERVICE_NAME_SIZE, srvp->Name); + printf("%*sId: 0x%016"PRIx64"\n", indent, "", srvp->Id); + break; + case FORMAT_XML: + printf("%*s\n", indent, "", IOC_SERVICE_NAME_SIZE, srvp->Name); + XmlPrintServiceName(srvp->Name, indent+4); + printf("%*s0x%016"PRIx64"\n", indent+4, "", srvp->Id); + printf("%*s\n", indent, ""); + break; + default: + break; + } +} + +// output verbose summary of a IOC +void ShowIocSummary(IocData *iocp, Format_t format, int indent, int detail) +{ + IOC_PROFILE *pIocProfile = &iocp->IocProfile; + + switch (format) { + case FORMAT_TEXT: + printf("%*sIocSlot: %3u GUID: 0x%016"PRIx64"\n", + indent, "", iocp->IocSlot, pIocProfile->IocGUID); + printf("%*sID String: %.*s\n", + indent+4, "", + IOC_IDSTRING_SIZE, + g_noname?g_name_marker:(char*)pIocProfile->IDString); + printf("%*sIO Class: 0x%x SubClass: 0x%x Protocol: 0x%x Protocol Ver: 0x%x\n", + indent+4, "", + pIocProfile->IOClass, + pIocProfile->IOSubClass, + pIocProfile->Protocol, + pIocProfile->ProtocolVer); + printf("%*sVendorID: 0x%x DeviceID: 0x%x Rev: 0x%x\n", + indent+4, "", + pIocProfile->ven.v.VendorId, + pIocProfile->DeviceId, + pIocProfile->DeviceVersion); + if (detail) { + printf("%*sSubsystem: VendorID: 0x%x DeviceID: 0x%x\n", + indent+4, "", + pIocProfile->sub.s.SubSystemVendorID, + pIocProfile->SubSystemID); + printf("%*sCapability: 0x%02x: %s%s%s%s%s%s%s%s\n", + indent+4, "", + pIocProfile->ccm.CntlCapMask, + pIocProfile->ccm.ctlrCapMask.ST?"ST ":"", + pIocProfile->ccm.ctlrCapMask.SF?"SF ":"", + pIocProfile->ccm.ctlrCapMask.RT?"RT ":"", + pIocProfile->ccm.ctlrCapMask.RF?"RF ":"", + pIocProfile->ccm.ctlrCapMask.WT?"WT ":"", + pIocProfile->ccm.ctlrCapMask.WF?"WF ":"", + pIocProfile->ccm.ctlrCapMask.AT?"AT ":"", + pIocProfile->ccm.ctlrCapMask.AF?"AF ":""); + printf("%*sSend Depth: %u Size: %u; RDMA Read Depth: %u RDMA Size: %u\n", + indent+4, "", + pIocProfile->SendMsgDepth, + pIocProfile->SendMsgSize, + pIocProfile->RDMAReadDepth, + pIocProfile->RDMASize); + } + printf("%*s%u Services%s\n", indent+4, "", pIocProfile->ServiceEntries, detail?":":""); + break; + case FORMAT_XML: + printf("%*s\n", indent, "", + pIocProfile->IocGUID); + XmlPrintDec("IocSlot", iocp->IocSlot, indent+4); + XmlPrintHex64("IocGUID", pIocProfile->IocGUID, indent+4); + XmlPrintIocIDString((char*)pIocProfile->IDString, indent+4); + XmlPrintHex("IOClass", pIocProfile->IOClass, indent+4); + XmlPrintHex("IOSubClass", pIocProfile->IOSubClass, indent+4); + XmlPrintHex("Protocol", pIocProfile->Protocol, indent+4); + XmlPrintHex("ProtocolVer", pIocProfile->ProtocolVer, indent+4); + XmlPrintHex("VendorID", pIocProfile->ven.v.VendorId, indent+4); + XmlPrintHex("DeviceId", pIocProfile->DeviceId, indent+4); + XmlPrintHex("DeviceVersion", pIocProfile->DeviceVersion, indent+4); + if (detail) { + XmlPrintHex("SubSystemVendorID", + pIocProfile->sub.s.SubSystemVendorID, indent+4); + XmlPrintHex("SubSystemID", + pIocProfile->SubSystemID, indent+4); + XmlPrintHex8("CapabilityMask", pIocProfile->ccm.CntlCapMask, + indent+4); + printf("%*s%s%s%s%s%s%s%s%s\n", + indent+4, "", + pIocProfile->ccm.ctlrCapMask.ST?"ST ":"", + pIocProfile->ccm.ctlrCapMask.SF?"SF ":"", + pIocProfile->ccm.ctlrCapMask.RT?"RT ":"", + pIocProfile->ccm.ctlrCapMask.RF?"RF ":"", + pIocProfile->ccm.ctlrCapMask.WT?"WT ":"", + pIocProfile->ccm.ctlrCapMask.WF?"WF ":"", + pIocProfile->ccm.ctlrCapMask.AT?"AT ":"", + pIocProfile->ccm.ctlrCapMask.AF?"AF ":""); + XmlPrintDec("SendMsgDepth", pIocProfile->SendMsgDepth, indent+4); + XmlPrintDec("SendMsgSize", pIocProfile->SendMsgSize, indent+4); + XmlPrintDec("RDMAReadDepth", pIocProfile->RDMAReadDepth, indent+4); + XmlPrintDec("RDMASize", pIocProfile->RDMASize, indent+4); + } + printf("%*s%u\n", indent+4, "", pIocProfile->ServiceEntries); + break; + default: + break; + } + if (detail) { + unsigned i; + if (format == FORMAT_XML) { + printf("%*s\n", indent+4, ""); + } + + for (i=0; i < pIocProfile->ServiceEntries; i++) { + ShowIoServiceSummary(&iocp->Services[i], format, indent+8, detail-1); + } + if (format == FORMAT_XML) { + printf("%*s\n", indent+4, ""); + } + } + if (format == FORMAT_XML) { + printf("%*s\n", indent, ""); + } +} + +// output verbose summary of a IOU +void ShowIouSummary(IouData *ioup, Point *focus, Format_t format, int indent, int detail) +{ + IOUnitInfo *pIouInfo = &ioup->IouInfo; + switch (format) { + case FORMAT_TEXT: + if (g_persist || g_hard) + printf("%*sMax IOCs: %3u Change ID: xxxxx DiagDeviceId: %u Rom: %u\n", + indent, "", pIouInfo->MaxControllers, + pIouInfo->DiagDeviceId, pIouInfo->OptionRom); + else + printf("%*sMax IOCs: %3u Change ID: %5u DiagDeviceId: %u Rom: %u\n", + indent, "", pIouInfo->MaxControllers, pIouInfo->Change_ID, + pIouInfo->DiagDeviceId, pIouInfo->OptionRom); + break; + case FORMAT_XML: + printf("%*s\n", indent, "", + ioup->nodep->NodeInfo.NodeGUID); + XmlPrintDec("MaxIOCs", pIouInfo->MaxControllers, indent+4); + if (! (g_persist || g_hard)) + XmlPrintDec("ChangeID", pIouInfo->Change_ID, indent+4); + XmlPrintDec("DiagDeviceId", pIouInfo->DiagDeviceId, indent+4); + XmlPrintDec("OptionRom", pIouInfo->OptionRom, indent+4); + break; + default: + break; + } + if (detail) { + LIST_ITEM *p; + + for (p=QListHead(&ioup->Iocs); p != NULL; p = QListNext(&ioup->Iocs, p)) { + IocData *iocp = (IocData *)QListObj(p); + if (! CompareIocPoint(iocp, focus)) + continue; + ShowIocSummary(iocp, format, indent+4, detail-1); + } + } + if (format == FORMAT_XML) { + printf("%*s\n", indent, ""); + } +} + +// output verbose summary of SL-to-SC table +void ShowSLSCTable(NodeData *nodep, PortData *portp, Format_t format, int indent, int detail) +{ + STL_SLSCMAP *pSLSC = portp->pQOS->SL2SCMap; + int i; + + if (format == FORMAT_XML) { + printf("%*s\n", indent, ""); + indent+=4; + } else { + printf("%*sSLtoSC:\n", indent, ""); + printf("%*sSL: 00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15\n", + indent, ""); + } + + switch (format) { + case FORMAT_TEXT: + printf("%*sSC: ", indent, ""); + for (i = 0; i < STL_MAX_SLS; i++) { + if (i == 16) { + printf("\n%*sSL: 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31\n", + indent, ""); + printf("%*sSC: ", indent, ""); + } + printf("%02u ", pSLSC->SLSCMap[i].SC); + } + printf("\n"); + break; + case FORMAT_XML: + for (i=0; i%u\n", indent, "", i, pSLSC->SLSCMap[i].SC); + break; + default: + break; + } // End of switch (format) + + + switch (format) { + case FORMAT_TEXT: + break; + case FORMAT_XML: + indent-=4; + printf("%*s\n", indent, ""); + break; + default: + break; + } + +} // End of ShowSLSCTable + +// output verbose summary of SC-to-SL table +void ShowSCSLTable(NodeData *nodep, PortData *portp, Format_t format, int indent, int detail) +{ + STL_SCSLMAP *pSCSL = portp->pQOS->SC2SLMap; + int i; + + if (format == FORMAT_XML) { + printf("%*s\n", indent, ""); + indent+=4; + } else { + printf("%*sSCtoSL:\n", indent, ""); + printf("%*sSC: 00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15\n", + indent, ""); + } + + switch (format) { + case FORMAT_TEXT: + printf("%*sSL: ", indent, ""); + for (i = 0; i < STL_MAX_SCS; i++) { + if (i == 16) { + printf("\n%*sSC: 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31\n", + indent, ""); + printf("%*sSL: ", indent, ""); + } + printf("%02u ", pSCSL->SCSLMap[i].SL); + } + printf("\n"); + break; + case FORMAT_XML: + for (i=0; i%u\n", indent, "", i, pSCSL->SCSLMap[i].SL); + break; + default: + break; + } // End of switch (format) + + + switch (format) { + case FORMAT_TEXT: + break; + case FORMAT_XML: + indent-=4; + printf("%*s\n", indent, ""); + break; + default: + break; + } + +} // End of ShowSCSLTable + +// output verbose summary of SC-to-SC table +void ShowSCSCTable(NodeData *nodep, PortData *portp, int tab, Format_t format, int indent, int detail) +{ + LIST_ITEM *p; + int i; + + if (format == FORMAT_XML) { + if (tab == 0) printf("%*s\n", indent, ""); + else printf("%*s\n", indent, ""); + indent+=4; + } else { + if (tab == 0) printf("%*sSCtoSC:\n", indent, ""); + else printf("%*sSCtoSCExt:\n", indent, ""); + } + + for (p=QListHead(&portp->pQOS->SC2SCMapList[tab]); p != NULL; p = QListNext(&portp->pQOS->SC2SCMapList[tab], p)) + { + PortMaskSC2SCMap *pSC2SC = (PortMaskSC2SCMap *)QListObj(p); + ASSERT(nodep->NodeInfo.NodeType == STL_NODE_SW); + + char outports[nodep->NodeInfo.NumPorts*3]; + FormatStlPortMask(outports, pSC2SC->outports, nodep->NodeInfo.NumPorts, nodep->NodeInfo.NumPorts*3); + switch (format) { + case FORMAT_TEXT: + printf("%*s%s\n", indent, "", outports); + printf("%*s SC: 00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15\n", + indent, ""); + printf("%*s SC': ", indent, ""); + for (i = 0; i < STL_MAX_SCS; i++) { + if (i == 16) { + printf("\n%*s SC: 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31\n", + indent, ""); + printf("%*s SC': ", indent, ""); + } + printf("%02u ", pSC2SC->SC2SCMap->SCSCMap[i].SC); + } + printf("\n"); + break; + case FORMAT_XML: + printf("%*s\n", indent, "", &outports[7]); // don't want to print the 1st 7 chars of the string + indent+=4; + for (i=0; i%u\n", indent, "", i, pSC2SC->SC2SCMap->SCSCMap[i].SC); + indent-=4; + printf("%*s\n", indent, ""); + break; + default: + break; + } // End of switch (format) + + } // End of for ( p=QListHead(&portp->pQOS->SC2SCMapList) + + switch (format) { + case FORMAT_TEXT: + break; + case FORMAT_XML: + indent-=4; + printf("%*s\n", indent, ""); + break; + default: + break; + } + +} // End of ShowSCSCTable + +// output verbose summary of VL arbitration table +void ShowVLArbTable(PortData *portp, Format_t format, int indent, int detail) +{ + // Adjust these to tweak the width of the print out. + const int VLWT_PER_LINE=6; + const int VL_PER_LINE=4; + + int t, i, j; + STL_VLARB_TABLE *pVLArb = portp->pQOS->u.VLArbTable; + + int vlarb; + int res = getVLArb(portp, &vlarb); + + if (res) { + fprintf(stderr, "Error-%s: failed to determine if VLArb is in use.\n", __func__); + return; + } + + if (!vlarb) + return; + + if (format == FORMAT_TEXT) { + for (t=0; t\n", indent, ""); + else if (t==1) printf("%*s\n", indent, ""); + else printf("%*s\n", indent, ""); + + for (i=0; i%u\n", indent+4, "", + pVLArb[t].Elements[i].s.VL, + pVLArb[t].Elements[i].Weight); + } + } + if (t==0) printf("%*s\n", indent, ""); + else if (t==1) printf("%*s\n", indent, ""); + else printf("%*s\n", indent, ""); + } + + printf("%*s\n", indent, ""); + for (i=0; i%u\n", indent+4, "", + i, pVLArb[STL_VLARB_PREEMPT_MATRIX].Matrix[i]); + } + printf("%*s\n", indent, ""); + } + +} // End of ShowVLArbTable + +// output verbose summary of P-Key table +void ShowPKeyTable(NodeData *nodep, PortData *portp, Format_t format, int indent, int detail) +{ +#define PKEY_PER_LINE 6 + + int ix, ix_line, last=0; + STL_PKEY_ELEMENT *pPKey = portp->pPartitionTable; + int ix_capacity = PortPartitionTableSize(portp); + + switch (format) { + case FORMAT_XML: + printf("%*s\n", indent, ""); + indent+=4; + break; + case FORMAT_TEXT: + default: + break; + } + + if (pPKey && ix_capacity) + { + for (ix = 0; ix < ix_capacity; ix++ ) + { + if (pPKey[ix].AsReg16 & 0x7FFF) + last = ix; + } + for (ix = 0; ix <= last; ) + { + switch (format) { + case FORMAT_TEXT: + printf("%*s%12s", indent, "", !ix ? "P_Key Table:" : ""); + for ( ix_line = PKEY_PER_LINE; + ix_line > 0 && ix <= last; ix++) { + printf("0x%04X ", pPKey[ix].AsReg16); + ix_line--; + } + printf("\n"); + break; + case FORMAT_XML: + XmlPrintHex16("PKey", pPKey[ix].AsReg16, indent); + ix++; + break; + default: + break; + } // End of switch (format) + } + } + switch (format) { + case FORMAT_XML: + indent-=4; + printf("%*s\n", indent, ""); + break; + case FORMAT_TEXT: + default: + break; + } + +} // End of ShowPKeyTable + +// output verbose summary of PortCounters +void ShowPortCounters(STL_PORT_COUNTERS_DATA *pPortCounters, Format_t format, int indent, int detail) +{ + if (detail < 1) return; + + switch (format) { + case FORMAT_TEXT: + if (detail >= 3) { + printf("%*sPerformance: Transmit\n", + indent, ""); + printf("%*s Xmit Data %20"PRIu64" MB (%"PRIu64" Flits)\n", + indent, "", + pPortCounters->portXmitData/FLITS_PER_MB, + pPortCounters->portXmitData); + printf("%*s Xmit Pkts %20"PRIu64"\n", + indent, "", + pPortCounters->portXmitPkts); + printf("%*s MC Xmt Pkts %20"PRIu64"\n", + indent, "", + pPortCounters->portMulticastXmitPkts); + printf("%*sPerformance: Receive\n", + indent, ""); + printf("%*s Rcv Data %20"PRIu64" MB (%"PRIu64" Flits)\n", + indent, "", + pPortCounters->portRcvData/FLITS_PER_MB, + pPortCounters->portRcvData); + printf("%*s Rcv Pkts %20"PRIu64"\n", + indent, "", + pPortCounters->portRcvPkts); + printf("%*s MC Rcv Pkts %20"PRIu64"\n", + indent, "", + pPortCounters->portMulticastRcvPkts); + printf("%*sPerformance: Congestion\n", + indent, ""); + printf("%*s Congestion Discards %20"PRIu64"\n", + indent, "", + pPortCounters->swPortCongestion); + printf("%*s Rcv FECN %20"PRIu64"\n", + indent, "", + pPortCounters->portRcvFECN); + printf("%*s Rcv BECN %20"PRIu64"\n", + indent, "", + pPortCounters->portRcvBECN); + printf("%*s Mark FECN %20"PRIu64"\n", + indent, "", + pPortCounters->portMarkFECN); + printf("%*s Xmit Time Congestion %20"PRIu64"\n", + indent, "", + pPortCounters->portXmitTimeCong); + printf("%*s Xmit Wait %20"PRIu64"\n", + indent, "", + pPortCounters->portXmitWait); + printf("%*sPerformance: Bubbles\n", + indent, ""); + printf("%*s Xmit Wasted BW %20"PRIu64"\n", + indent, "", + pPortCounters->portXmitWastedBW); + printf("%*s Xmit Wait Data %20"PRIu64"\n", + indent, "", + pPortCounters->portXmitWaitData); + printf("%*s Rcv Bubble %20"PRIu64"\n", + indent, "", + pPortCounters->portRcvBubble); + + printf("%*sErrors: Signal Integrity\n", + indent, ""); + printf("%*s Link Qual Indicator %20u (%s)\n", + indent, "", + pPortCounters->lq.s.linkQualityIndicator, + StlLinkQualToText(pPortCounters->lq.s.linkQualityIndicator)); + printf("%*s Uncorrectable Errors %20u\n", //8 bit + indent, "", + pPortCounters->uncorrectableErrors); + printf("%*s Link Downed %20u\n", // 32 bit + indent, "", + pPortCounters->linkDowned); + printf("%*s Rcv Errors %20"PRIu64"\n", + indent, "", + pPortCounters->portRcvErrors); + printf("%*s Exc. Buffer Overrun %20"PRIu64"\n", + indent, "", + pPortCounters->excessiveBufferOverruns); + printf("%*s FM Config Errors %20"PRIu64"\n", + indent, "", + pPortCounters->fmConfigErrors); + printf("%*s Link Error Recovery %20u\n", // 32 bit + indent, "", + pPortCounters->linkErrorRecovery); + printf("%*s Local Link Integ Err %20"PRIu64"\n", + indent, "", + pPortCounters->localLinkIntegrityErrors); + printf("%*s Rcv Rmt Phys Err %20"PRIu64"\n", + indent, "", + pPortCounters->portRcvRemotePhysicalErrors); + printf("%*sErrors: Security\n", + indent, ""); + printf("%*s Xmit Constraint %20"PRIu64"\n", + indent, "", + pPortCounters->portXmitConstraintErrors); + printf("%*s Rcv Constraint %20"PRIu64"\n", + indent, "", + pPortCounters->portRcvConstraintErrors); + printf("%*sErrors: Routing and Other\n", + indent, ""); + printf("%*s Rcv Sw Relay Err %20"PRIu64"\n", + indent, "", + pPortCounters->portRcvSwitchRelayErrors); + printf("%*s Xmit Discards %20"PRIu64"\n", + indent, "", + pPortCounters->portXmitDiscards); + } else if (detail == 2) { + printf("%*sPortStatus:\n", indent, ""); + printf("%*sXmit Data %20"PRIu64" MB | Xmit Pkts %20"PRIu64"\n", indent+4, "", + pPortCounters->portXmitData/FLITS_PER_MB, pPortCounters->portXmitPkts); + printf("%*sRcv Data %20"PRIu64" MB | Rcv Pkts %20"PRIu64"\n", indent+4, "", + pPortCounters->portRcvData/FLITS_PER_MB, pPortCounters->portRcvPkts); + if (pPortCounters->portMulticastXmitPkts || pPortCounters->portMulticastRcvPkts) { + printf("%*sMC Xmit Pkts %20"PRIu64" | MC Rcv Pkts %20"PRIu64"\n", indent+4, "", + pPortCounters->portMulticastXmitPkts, pPortCounters->portMulticastRcvPkts); + } + printf("%*sLink Qual Indicator %20u (%s)\n", indent+4, "", + pPortCounters->lq.s.linkQualityIndicator, + StlLinkQualToText(pPortCounters->lq.s.linkQualityIndicator)); + boolean isLeft = TRUE, isAny = FALSE; +#define NON_ZERO_64(cntr, name) \ + if (cntr) { \ + printf("%*s%-22s%20"PRIu64"%s", isLeft ? indent+4 : 0, "", name, cntr, isLeft ? " | " : "\n"); \ + isLeft = !isLeft; isAny = TRUE;\ + } +#define NON_ZERO(cntr, name) \ + if (cntr) { \ + printf("%*s%-22s%20u%s", isLeft ? indent+4 : 0, "", name, cntr, isLeft ? " | " : "\n"); \ + isLeft = !isLeft; isAny = TRUE; \ + } + NON_ZERO_64(pPortCounters->swPortCongestion, "Congestion Discards"); + NON_ZERO_64(pPortCounters->portRcvFECN, "Rcv FECN"); + NON_ZERO_64(pPortCounters->portRcvBECN, "Rcv BECN"); + NON_ZERO_64(pPortCounters->portMarkFECN, "Mark FECN"); + NON_ZERO_64(pPortCounters->portXmitTimeCong, "Xmit Time Congestion"); + NON_ZERO_64(pPortCounters->portXmitWait, "Xmit Wait"); + NON_ZERO_64(pPortCounters->portXmitWastedBW, "Xmit Wasted BW"); + NON_ZERO_64(pPortCounters->portXmitWaitData, "Xmit Wait Data"); + NON_ZERO_64(pPortCounters->portRcvBubble, "Rcv Bubble"); + NON_ZERO(pPortCounters->uncorrectableErrors, "Uncorrectable Errors"); + NON_ZERO(pPortCounters->linkDowned, "Link Downed"); + NON_ZERO_64(pPortCounters->portRcvErrors, "Rcv Errors"); + NON_ZERO_64(pPortCounters->excessiveBufferOverruns, "Exc Buffer Overrun"); + NON_ZERO_64(pPortCounters->fmConfigErrors, "FM Config Errors"); + NON_ZERO(pPortCounters->linkErrorRecovery, "Link Error Recovery"); + NON_ZERO_64(pPortCounters->localLinkIntegrityErrors, "Local Link Integ Err"); + NON_ZERO_64(pPortCounters->portRcvRemotePhysicalErrors, "Rcv Rmt Phys Err"); + NON_ZERO_64(pPortCounters->portXmitConstraintErrors, "Xmit Constraint"); + NON_ZERO_64(pPortCounters->portRcvConstraintErrors, "Rcv Constraint"); + NON_ZERO_64(pPortCounters->portRcvSwitchRelayErrors, "Rcv Sw Relay Err"); + NON_ZERO_64(pPortCounters->portXmitDiscards, "Xmit Discards"); + if (isAny && !isLeft) printf("\n"); +#undef NON_ZERO_64 +#undef NON_ZERO + } else if (detail == 1) { + printf("%*sPortStatus:\n", indent, ""); + printf("%*sXmit Data %20"PRIu64" MB | Xmit Pkts %20"PRIu64"\n", indent+4, "", + pPortCounters->portXmitData/FLITS_PER_MB, pPortCounters->portXmitPkts); + printf("%*sRcv Data %20"PRIu64" MB | Rcv Pkts %20"PRIu64"\n", indent+4, "", + pPortCounters->portRcvData/FLITS_PER_MB, pPortCounters->portRcvPkts); + printf("%*sLink Qual Indicator %20u (%s)\n", indent+4, "", + pPortCounters->lq.s.linkQualityIndicator, + StlLinkQualToText(pPortCounters->lq.s.linkQualityIndicator)); + } + break; + case FORMAT_XML: + printf("%*s\n", indent, ""); + // Data movement + XmlPrintDec64("XmitDataMB", pPortCounters->portXmitData/FLITS_PER_MB, indent+4); + printf("%*s%"PRIu64" \n", + indent+4, "", pPortCounters->portXmitData); + XmlPrintDec64("RcvDataMB", pPortCounters->portRcvData/FLITS_PER_MB, indent+4); + XmlPrintDec64("XmitPkts", pPortCounters->portXmitPkts, indent+4); + printf("%*s%"PRIu64" \n", + indent+4, "", pPortCounters->portRcvData); + XmlPrintDec64("RcvPkts", pPortCounters->portRcvPkts, indent+4); + XmlPrintDec64("MulticastXmitPkts", pPortCounters->portMulticastXmitPkts, indent+4); + XmlPrintDec64("MulticastRcvPkts", pPortCounters->portMulticastRcvPkts, indent+4); + // Signal Integrity and Node/Link Stability + XmlPrintDec("LinkQualityIndicator", pPortCounters->lq.s.linkQualityIndicator, indent+4); + XmlPrintDec("UncorrectableErrors", pPortCounters->uncorrectableErrors, indent+4); // 8 bit + XmlPrintDec("LinkDowned", pPortCounters->linkDowned, indent+4); // 32 bit + XmlPrintDec64("RcvErrors", pPortCounters->portRcvErrors, indent+4); + XmlPrintDec64("ExcessiveBufferOverruns", pPortCounters->excessiveBufferOverruns, indent+4); + XmlPrintDec64("FMConfigErrors", pPortCounters->fmConfigErrors, indent+4); + XmlPrintDec("LinkErrorRecovery", pPortCounters->linkErrorRecovery, indent+4); // 32 bit + XmlPrintDec64("LocalLinkIntegrityErrors", pPortCounters->localLinkIntegrityErrors, indent+4); + XmlPrintDec64("RcvRemotePhysicalErrors", pPortCounters->portRcvRemotePhysicalErrors, indent+4); + // Security + XmlPrintDec64("XmitConstraintErrors", pPortCounters->portXmitConstraintErrors, indent+4); + XmlPrintDec64("RcvConstraintErrors", pPortCounters->portRcvConstraintErrors, indent+4); + // Routing or Down nodes still being sent to + XmlPrintDec64("RcvSwitchRelayErrors", pPortCounters->portRcvSwitchRelayErrors, indent+4); + XmlPrintDec64("XmitDiscards", pPortCounters->portXmitDiscards, indent+4); + // Congestion + XmlPrintDec64("CongDiscards", pPortCounters->swPortCongestion, indent+4); + XmlPrintDec64("RcvFECN", pPortCounters->portRcvFECN, indent+4); + XmlPrintDec64("RcvBECN", pPortCounters->portRcvBECN, indent+4); + XmlPrintDec64("MarkFECN", pPortCounters->portMarkFECN, indent+4); + XmlPrintDec64("XmitTimeCong", pPortCounters->portXmitTimeCong, indent+4); + XmlPrintDec64("XmitWait", pPortCounters->portXmitWait, indent+4); + // Bubbles + XmlPrintDec64("XmitWastedBW", pPortCounters->portXmitWastedBW, indent+4); + XmlPrintDec64("XmitWaitData", pPortCounters->portXmitWaitData, indent+4); + XmlPrintDec64("RcvBubble", pPortCounters->portRcvBubble, indent+4); + printf("%*s\n", indent, ""); + break; + default: + break; + } +} +void ShowPortLinkDownReasonLog(PortData *portp, Format_t format, int indent, int detail) +{ + int i, idx = STL_LINKDOWN_REASON_LAST_INDEX(portp->LinkDownReasons); + if (idx == -1) return; + + STL_LINKDOWN_REASON *ldr = &portp->LinkDownReasons[idx]; + + for (i = 0; i < STL_NUM_LINKDOWN_REASONS; ++i) { + if (ldr->Timestamp == 0) break; + switch (format) { + case FORMAT_TEXT: + printf("%*s", indent, ""); + if (ldr->LinkDownReason) + printf("LinkDownReasonLog: %s ", StlLinkDownReasonToText(ldr->LinkDownReason)); + if (ldr->NeighborLinkDownReason) + printf("NeighborLinkDownReasonLog: %s", StlLinkDownReasonToText(ldr->NeighborLinkDownReason)); + printf("\n%*sTimestamp: %s", indent+4, "", ctime((time_t *)&ldr->Timestamp)); // ctime ends in '\n' + break; + case FORMAT_XML: + printf("%*s\n", indent, "", idx); + XmlPrintDec("LinkDownReason", ldr->LinkDownReason, indent+4); + XmlPrintDec("NeighborLinkDownReason", ldr->NeighborLinkDownReason, indent+4); + XmlPrintDec64("Timestamp", ldr->Timestamp, indent+4); + printf("%*s\n", indent, ""); + break; + default: + return; + } + + if (idx == 0) idx = STL_NUM_LINKDOWN_REASONS; + idx--; + ldr = &portp->LinkDownReasons[idx]; + } +} + +// output verbose summary of an STL Port +void ShowPortSummary(PortData *portp, Format_t format, int indent, int detail) +{ + STL_PORT_INFO *pPortInfo = &portp->PortInfo; + char buf1[SHOW_BUF_SIZE], buf2[SHOW_BUF_SIZE], buf3[SHOW_BUF_SIZE], buf4[SHOW_BUF_SIZE]; + + switch (format) { + case FORMAT_TEXT: + if (portp->PortGUID) + if (g_persist || g_hard) + printf("%*sPortNum: %3u LID: xxxxxxxxxx GUID: 0x%016"PRIx64"\n", + indent, "", portp->PortNum, portp->PortGUID); + else + printf("%*sPortNum: %3u LID: 0x%.*x GUID: 0x%016"PRIx64"\n", + indent, "", portp->PortNum, + (portp->EndPortLID <= IB_MAX_UCAST_LID ? 4:8), + portp->EndPortLID, portp->PortGUID); + else + printf("%*sPortNum: %3u\n", + indent, "", portp->PortNum); + { + PortSelector* portselp = GetPortSelector(portp); + if (portselp && portselp->details) { + printf("%*sPortDetails: %s\n", indent+4, "", portselp->details); + } + } + if (portp->neighbor) { + ShowLinkPortSummary(portp->neighbor, "Neighbor: ", format, indent+4, detail); + if (detail-1) + ShowExpectedLinkSummary(portp->neighbor->elinkp, format, indent+8, detail-1); + } + if (detail) { + if (g_hard) { + printf( "%*sLocalPort: %-3d PortState: xxxxxx PhysState: xxxxxxxx\n", + indent+4, "", pPortInfo->LocalPortNum); + printf( "%*sNeighborNormal: x\n", indent+4, ""); + } + else { + uint8 ldr = 0; + if (pPortInfo->LinkDownReason) + ldr = pPortInfo->LinkDownReason; + else if (pPortInfo->NeighborLinkDownReason) + ldr = pPortInfo->NeighborLinkDownReason; + + // SM will have cleared ldr for ports in Armed and Active + if (pPortInfo->PortStates.s.PortState == IB_PORT_INIT + && pPortInfo->s3.LinkInitReason) { + printf( "%*sLocalPort: %-3d PortState: %-6s (%-13s) PhysState: %-8s\n", + indent+4, "", + pPortInfo->LocalPortNum, + IbPortStateToText(pPortInfo->PortStates.s.PortState), + StlLinkInitReasonToText(pPortInfo->s3.LinkInitReason), + StlPortPhysStateToText(pPortInfo->PortStates.s.PortPhysicalState)); + } else if (pPortInfo->PortStates.s.PortState == IB_PORT_DOWN && ldr && ! g_persist) { + printf( "%*sLocalPort: %-3d PortState: %-6s (%-13s) PhysState: %-8s\n", + indent+4, "", + pPortInfo->LocalPortNum, + IbPortStateToText(pPortInfo->PortStates.s.PortState), + StlLinkDownReasonToText(ldr), + StlPortPhysStateToText(pPortInfo->PortStates.s.PortPhysicalState)); + } else { + printf( "%*sLocalPort: %-3d PortState: %-6s PhysState: %-8s\n", + indent+4, "", + pPortInfo->LocalPortNum, + IbPortStateToText(pPortInfo->PortStates.s.PortState), + StlPortPhysStateToText(pPortInfo->PortStates.s.PortPhysicalState)); + } + if (pPortInfo->PortStates.s.PortPhysicalState == STL_PORT_PHYS_OFFLINE + || pPortInfo->PortStates.s.PortPhysicalState == IB_PORT_PHYS_DISABLED) + + printf("%*sOfflineDisabledReason: %-14s\n", + indent+4, "", + StlPortOfflineDisabledReasonToText(pPortInfo->PortStates.s.OfflineDisabledReason)); + printf( "%*sIsSMConfigurationStarted: %-5s NeighborNormal: %-5s\n", + indent+4, "", + pPortInfo->PortStates.s.IsSMConfigurationStarted?"True":"False", + pPortInfo->PortStates.s.NeighborNormal?"True":"False"); + } + printf("%*sPortType: %-3s\n", indent+4, "", StlPortTypeToText(pPortInfo->PortPhysConfig.s.PortType)); + printf("%*sBundleNextPort: %-3u BundleLane: %-3u\n", indent+4, "", + pPortInfo->BundleNextPort, + pPortInfo->BundleLane); + if (g_hard) { + printf( "%*sLID: xxxxxxxxxx LMC: x Subnet: xxxxxxxxxxxxxxxxxx\n", + indent+4, ""); + printf( "%*sSMLID: xxxxxxxxxx SMSL: xx RespTimeout: xxxxxxx", + indent+4, ""); + printf( " SubnetTimeout: xxxxxxx\n"); + } else if (g_persist) { + printf( "%*sLID: xxxxxxxxxx LMC: %u Subnet: 0x%016"PRIx64"\n", + indent+4, "", + pPortInfo->s1.LMC, + pPortInfo->SubnetPrefix); + FormatTimeoutMult(buf1, pPortInfo->Resp.TimeValue); + printf( "%*sSMLID: xxxxxxxxxx SMSL: %2u RespTimeout: %s", + indent+4, "", + pPortInfo->s2.MasterSMSL, buf1); + FormatTimeoutMult(buf1, pPortInfo->Subnet.Timeout); + printf( " SubnetTimeout: %s\n", buf1); + } else { + if (pPortInfo->LID == STL_LID_PERMISSIVE) + printf( "%*sLID: DontCare LMC: %u Subnet: 0x%016"PRIx64"\n", + indent+4, "", + pPortInfo->s1.LMC, + pPortInfo->SubnetPrefix); + else + printf( "%*sLID: 0x%.*x LMC: %u Subnet: 0x%016"PRIx64"\n", + indent+4, "", + (pPortInfo->LID <= IB_MAX_UCAST_LID ? 4:8), + pPortInfo->LID, pPortInfo->s1.LMC, + pPortInfo->SubnetPrefix); + FormatTimeoutMult(buf1, pPortInfo->Resp.TimeValue); + printf( "%*sSMLID: 0x%.*x SMSL: %2u RespTimeout: %s", + indent+4, "",(pPortInfo->MasterSMLID <= IB_MAX_UCAST_LID ? 4:8), + pPortInfo->MasterSMLID, pPortInfo->s2.MasterSMSL, buf1); + FormatTimeoutMult(buf1, pPortInfo->Subnet.Timeout); + printf( " SubnetTimeout: %s\n", buf1); + } + if (g_hard) + printf( "%*sM_KEY: xxxxxxxxxxxxxxxxxx Lease: xxxxxxx Protect: xxxxxxxx\n", + indent+4, ""); + else + printf( "%*sM_KEY: 0x%016"PRIx64" Lease: %5u s Protect: %s\n", + indent+4, "", + pPortInfo->M_Key, pPortInfo->M_KeyLeasePeriod, + IbMKeyProtectToText(pPortInfo->s1.M_KeyProtectBits)); + printf("%*sMTU Supported: (0x%x) %s bytes\n", + indent+4, "", + pPortInfo->MTU.Cap, + IbMTUToText(pPortInfo->MTU.Cap)); + if (! g_hard) + { + FormatStlVLStalls(buf1, pPortInfo, sizeof(buf1)); + printf("%*sVLStallCount (per VL): %s\n", indent+4, "", buf1); + + printf("%*sMTU Active by VL:\n", indent+4, ""); + printf("%*s00:%5s 01:%5s 02:%5s 03:%5s 04:%5s 05:%5s 06:%5s 07:%5s\n", + indent+4, "", + IbMTUToText(GET_STL_PORT_INFO_NeighborMTU(pPortInfo, 0)), + IbMTUToText(GET_STL_PORT_INFO_NeighborMTU(pPortInfo, 1)), + IbMTUToText(GET_STL_PORT_INFO_NeighborMTU(pPortInfo, 2)), + IbMTUToText(GET_STL_PORT_INFO_NeighborMTU(pPortInfo, 3)), + IbMTUToText(GET_STL_PORT_INFO_NeighborMTU(pPortInfo, 4)), + IbMTUToText(GET_STL_PORT_INFO_NeighborMTU(pPortInfo, 5)), + IbMTUToText(GET_STL_PORT_INFO_NeighborMTU(pPortInfo, 6)), + IbMTUToText(GET_STL_PORT_INFO_NeighborMTU(pPortInfo, 7))); + printf("%*s08:%5s 09:%5s 10:%5s 11:%5s 12:%5s 13:%5s 14:%5s 15:%5s\n", + indent+4, "", + IbMTUToText(GET_STL_PORT_INFO_NeighborMTU(pPortInfo, 8)), + IbMTUToText(GET_STL_PORT_INFO_NeighborMTU(pPortInfo, 9)), + IbMTUToText(GET_STL_PORT_INFO_NeighborMTU(pPortInfo, 10)), + IbMTUToText(GET_STL_PORT_INFO_NeighborMTU(pPortInfo, 11)), + IbMTUToText(GET_STL_PORT_INFO_NeighborMTU(pPortInfo, 12)), + IbMTUToText(GET_STL_PORT_INFO_NeighborMTU(pPortInfo, 13)), + IbMTUToText(GET_STL_PORT_INFO_NeighborMTU(pPortInfo, 14)), + IbMTUToText(GET_STL_PORT_INFO_NeighborMTU(pPortInfo, 15))); + printf("%*s16:%5s 17:%5s 18:%5s 19:%5s 20:%5s 21:%5s 22:%5s 23:%5s\n", + indent+4, "", + IbMTUToText(GET_STL_PORT_INFO_NeighborMTU(pPortInfo, 16)), + IbMTUToText(GET_STL_PORT_INFO_NeighborMTU(pPortInfo, 17)), + IbMTUToText(GET_STL_PORT_INFO_NeighborMTU(pPortInfo, 18)), + IbMTUToText(GET_STL_PORT_INFO_NeighborMTU(pPortInfo, 19)), + IbMTUToText(GET_STL_PORT_INFO_NeighborMTU(pPortInfo, 20)), + IbMTUToText(GET_STL_PORT_INFO_NeighborMTU(pPortInfo, 21)), + IbMTUToText(GET_STL_PORT_INFO_NeighborMTU(pPortInfo, 22)), + IbMTUToText(GET_STL_PORT_INFO_NeighborMTU(pPortInfo, 23))); + printf("%*s24:%5s 25:%5s 26:%5s 27:%5s 28:%5s 29:%5s 30:%5s 31:%5s\n", + indent+4, "", + IbMTUToText(GET_STL_PORT_INFO_NeighborMTU(pPortInfo, 24)), + IbMTUToText(GET_STL_PORT_INFO_NeighborMTU(pPortInfo, 25)), + IbMTUToText(GET_STL_PORT_INFO_NeighborMTU(pPortInfo, 26)), + IbMTUToText(GET_STL_PORT_INFO_NeighborMTU(pPortInfo, 27)), + IbMTUToText(GET_STL_PORT_INFO_NeighborMTU(pPortInfo, 28)), + IbMTUToText(GET_STL_PORT_INFO_NeighborMTU(pPortInfo, 29)), + IbMTUToText(GET_STL_PORT_INFO_NeighborMTU(pPortInfo, 30)), + IbMTUToText(GET_STL_PORT_INFO_NeighborMTU(pPortInfo, 31))); + } + if (g_hard) + printf( "%*sLinkWidth: Active: xxxx Supported: %7s Enabled: xxxxxxx\n", + indent+4, "", + StlLinkWidthToText(pPortInfo->LinkWidth.Supported, buf1, sizeof(buf1))); + else + printf( "%*sLinkWidth: Active: %4s Supported: %7s Enabled: %7s\n", + indent+4, "", + StlLinkWidthToText(pPortInfo->LinkWidth.Active, buf1, sizeof(buf1)), + StlLinkWidthToText(pPortInfo->LinkWidth.Supported, buf2, sizeof(buf2)), + StlLinkWidthToText(pPortInfo->LinkWidth.Enabled, buf3, sizeof(buf3))); + if (g_hard) + printf( "%*sLinkWidthDnGrade: Active: Tx: xx Rx: xx Supported: %7s Enabled: xxxxxxx\n", + indent+4, "", + StlLinkWidthToText(pPortInfo->LinkWidthDowngrade.Supported, buf1, sizeof(buf1))); + else + printf( "%*sLinkWidthDnGrade: ActiveTx: %2.2s Rx: %2.2s Supported: %7s Enabled: %7s\n", + indent+4, "", + StlLinkWidthToText(pPortInfo->LinkWidthDowngrade.TxActive, buf1, sizeof(buf1)), + StlLinkWidthToText(pPortInfo->LinkWidthDowngrade.RxActive, buf2, sizeof(buf2)), + StlLinkWidthToText(pPortInfo->LinkWidthDowngrade.Supported, buf3, sizeof(buf3)), + StlLinkWidthToText(pPortInfo->LinkWidthDowngrade.Enabled, buf4, sizeof(buf4))); + if (g_hard) + printf("%*sPortLinkMode: Active: xxxx Supported: %-16s Enabled: xxxx\n", + indent+4, "", + StlPortLinkModeToText(pPortInfo->PortLinkMode.s.Supported, buf1, sizeof(buf1))); + else + printf("%*sPortLinkMode: Active: %-8s Supported: %-16s Enabled: %-8s\n", + indent+4, "", + StlPortLinkModeToText(pPortInfo->PortLinkMode.s.Active, buf1, sizeof(buf1)), + StlPortLinkModeToText(pPortInfo->PortLinkMode.s.Supported, buf2, sizeof(buf2)), + StlPortLinkModeToText(pPortInfo->PortLinkMode.s.Enabled, buf3, sizeof(buf3))); + if (g_hard) + printf("%*sPortLTPCRCMode: Act: xxxx Sup: %-21s En: xxxx\n", + indent+4, "", + StlPortLtpCrcModeToText(pPortInfo->PortLTPCRCMode.s.Supported, buf1, sizeof(buf1))); + else + printf("%*sPortLTPCRCMode: Act: %-6s Sup: %-21s En: %-21s\n", + indent+4, "", + StlPortLtpCrcModeToText(pPortInfo->PortLTPCRCMode.s.Active, buf1, sizeof(buf1)), + StlPortLtpCrcModeToText(pPortInfo->PortLTPCRCMode.s.Supported, buf2, sizeof(buf2)), + StlPortLtpCrcModeToText(pPortInfo->PortLTPCRCMode.s.Enabled, buf3, sizeof(buf3))); + if (g_hard) + printf( "%*sLinkSpeed: Active: xxxxxxx Supported: %10s Enabled: xxxxxxxxxx\n", + indent+4, "", + StlLinkSpeedToText(pPortInfo->LinkSpeed.Supported, buf1, sizeof(buf1))); + else + printf( "%*sLinkSpeed: Active: %7s Supported: %10s Enabled: %10s\n", + indent+4, "", + StlLinkSpeedToText(pPortInfo->LinkSpeed.Active, buf1, sizeof(buf1)), + StlLinkSpeedToText(pPortInfo->LinkSpeed.Supported, buf2, sizeof(buf2)), + StlLinkSpeedToText(pPortInfo->LinkSpeed.Enabled, buf3, sizeof(buf3))); + + printf("%*sSM_TrapQP: 0x%x SA_QP: 0x%x IPAddr Prim/Sec: %s / %s\n", + indent+4, "", + pPortInfo->SM_TrapQP.s.QueuePair, pPortInfo->SA_QP.s.QueuePair, + inet_ntop(AF_INET6, pPortInfo->IPAddrIPV6.addr, buf1, sizeof(buf1)), + inet_ntop(AF_INET, pPortInfo->IPAddrIPV4.addr, buf2, sizeof(buf2))); + + if (g_hard) { + printf( "%*sVLs: Active: xxxx Supported: %2u+1 HOQLife: xxxxxxxxx\n", + indent+4, "", + pPortInfo->VL.s2.Cap); + } else { + printf( "%*sVLs: Active: %2u+1 Supported: %2u+1 \n", + indent+4, "", + pPortInfo->s4.OperationalVL, + pPortInfo->VL.s2.Cap); +#if 0 + if (pPortInfo->XmitQ.HOQLife > IB_LIFETIME_MAX) + { + strncpy(buf1, "Infinite", 9); + } else { + FormatTimeoutMult(buf1, pPortInfo->XmitQ.HOQLife); + } + printf( "%s\n", buf1); +#else + int i; + printf("%*sHOQLife (Per VL):", indent+8, ""); + for (i = 0; i < STL_MAX_VLS; i++) { + if (!(i % 5)) printf("\n%*s", indent+8, ""); + printf("VL%2d: 0x%x ", i, (uint32)pPortInfo->XmitQ[i].HOQLife); + } + printf("\n\n"); +#endif + } + + if (pPortInfo->CapabilityMask3.s.VLSchedulingConfig == VL_SCHED_MODE_VLARB) { + if (g_hard) { + printf( "%*sVL Arb Cap: High: %4u Low: %4u HiLimit: xxxx PreemptLimit xxxx\n", + indent+4, "", pPortInfo->VL.ArbitrationHighCap, + pPortInfo->VL.ArbitrationLowCap); + + } else { + printf( "%*sVL Arb Cap: High: %4u Low: %4u HiLimit: %4u PreemptLimit %4u\n", + indent+4, "", pPortInfo->VL.ArbitrationHighCap, + pPortInfo->VL.ArbitrationLowCap, pPortInfo->VL.HighLimit, + pPortInfo->VL.PreemptingLimit); + } + } + + printf("%*sVLFlowControlDisabledMask: 0x%08x\n", indent+4, "", pPortInfo->FlowControlMask); + printf("%*sNeighborMode MgmtAllowed: %3s FwAuthenBypass: %3s NeighborNodeType: %s\n", + indent+4, "", + pPortInfo->PortNeighborMode.MgmtAllowed?"Yes":"No", + pPortInfo->PortNeighborMode.NeighborFWAuthenBypass?"On":"Off", + OpaNeighborNodeTypeToText(pPortInfo->PortNeighborMode.NeighborNodeType)); + FormatStlCapabilityMask(buf1, pPortInfo->CapabilityMask); + printf( "%*sCapability 0x%08x: %s\n", + indent+4, "", + pPortInfo->CapabilityMask.AsReg32, buf1); + FormatStlCapabilityMask3(buf1, pPortInfo->CapabilityMask3, sizeof(buf1)); + printf("%*sCapability3 0x%04x: %s\n", + indent+4, "", + pPortInfo->CapabilityMask3.AsReg16, buf1); + + if (g_persist || g_hard) + printf( "%*sViolations: M_Key: xxxxx P_Key: xxxxx Q_Key: xxxxx\n", + indent+4, ""); + else + printf( "%*sViolations: M_Key: %5u P_Key: %5u Q_Key: %5u\n", + indent+4, "", + pPortInfo->Violations.M_Key, pPortInfo->Violations.P_Key, + pPortInfo->Violations.Q_Key); + if (g_hard) + printf("%*sPortMode ActiveOptimize xxxxx PassThrough: xxxxx VLMarker: xxxxx\n", + indent+4, ""); + else + printf("%*sPortMode ActiveOptimize: %3s PassThrough: %3s VLMarker: %3s\n", + indent+4, "", + pPortInfo->PortMode.s.IsActiveOptimizeEnabled?"On":"Off", + pPortInfo->PortMode.s.IsPassThroughEnabled?"On":"Off", + pPortInfo->PortMode.s.IsVLMarkerEnabled?"On":"Off"); + if (g_hard) { + printf("%*sFlitCtrlInterleave Distance Max: %2u Enabled: xxxxx\n", + indent, "", pPortInfo->FlitControl.Interleave.s.DistanceSupported); + printf("%*sMaxNestLevelTxEnabled: xxxx MaxNestLevelRxSupported: %u\n", + indent+4, "", + pPortInfo->FlitControl.Interleave.s.MaxNestLevelRxSupported); + } else { + printf("%*sFlitCtrlInterleave Distance Max: %2u Enabled: %2u\n", + indent+4, "", pPortInfo->FlitControl.Interleave.s.DistanceSupported, + pPortInfo->FlitControl.Interleave.s.DistanceEnabled); + printf("%*sMaxNestLevelTxEnabled: %u MaxNestLevelRxSupported: %u\n", + indent+4, "", + pPortInfo->FlitControl.Interleave.s.MaxNestLevelTxEnabled, + pPortInfo->FlitControl.Interleave.s.MaxNestLevelRxSupported); + } + if (g_hard) { + printf("%*sSmallPktLimit: xxxx MaxSmallPktLimit: 0x%02x PreemptionLimit: xxxx\n", + indent+4, "", + pPortInfo->FlitControl.Preemption.MaxSmallPktLimit); + } else { + printf("%*sSmallPktLimit: 0x%02x MaxSmallPktLimit: 0x%02x PreemptionLimit: 0x%02x\n", + indent+4, "", + pPortInfo->FlitControl.Preemption.SmallPktLimit, + pPortInfo->FlitControl.Preemption.MaxSmallPktLimit, + pPortInfo->FlitControl.Preemption.PreemptionLimit); + // Convert Flits to bytes and display in decimal + printf("%*sFlitCtrlPreemption MinInital: %"PRIu64" MinTail: %"PRIu64" LargePktLim: 0x%02x\n", + indent+4, "", + (uint64_t)(pPortInfo->FlitControl.Preemption.MinInitial * BYTES_PER_FLIT), + (uint64_t)(pPortInfo->FlitControl.Preemption.MinTail * BYTES_PER_FLIT), + pPortInfo->FlitControl.Preemption.LargePktLimit); + } + if (!g_hard) { + if (pPortInfo->CapabilityMask3.s.IsMAXLIDSupported) + printf("%*sMaxLID: %u\n", + indent+4, "", pPortInfo->MaxLID); + } + if (g_hard) + printf("%*sBufferUnits: VL15Init 0x%04x; VL15CreditRate xxxxxx; CreditAck 0x%x; BufferAlloc 0x%x\n", + indent+4, "", + pPortInfo->BufferUnits.s.VL15Init, + pPortInfo->BufferUnits.s.CreditAck, + pPortInfo->BufferUnits.s.BufferAlloc); + else + printf("%*sBufferUnits: VL15Init 0x%04x; VL15CreditRate 0x%02x; CreditAck 0x%x; BufferAlloc 0x%x\n", + indent+4, "", + pPortInfo->BufferUnits.s.VL15Init, + pPortInfo->BufferUnits.s.VL15CreditRate, + pPortInfo->BufferUnits.s.CreditAck, + pPortInfo->BufferUnits.s.BufferAlloc); + + if (! g_hard) + { + FormatStlPortErrorAction(buf1, pPortInfo, SHOW_BUF_SIZE); + printf("%*sPortErrorActions: 0x%x: %s\n", indent+4, "", pPortInfo->PortErrorAction.AsReg32, buf1); + } + + if (!g_persist && !g_hard) + printf("%*sReplayDepth Buffer 0x%02x; Wire 0x%02x\n", indent+4, "", + (pPortInfo->ReplayDepthH.BufferDepthH << 8) | pPortInfo->ReplayDepth.BufferDepth, + (pPortInfo->ReplayDepthH.WireDepthH << 8) | pPortInfo->ReplayDepth.WireDepth); + else + printf("%*sReplayDepth Buffer 0x%02x; Wire xxxx\n", indent+4, "", + (pPortInfo->ReplayDepthH.BufferDepthH << 8) | pPortInfo->ReplayDepth.BufferDepth); + if (g_hard) + printf( "%*sDiagCode: xxxxxx\n", indent+4, ""); + else + printf( "%*sDiagCode: 0x%04x\n", + indent+4, "", + pPortInfo->DiagCode.AsReg16); + printf("%*sOverallBufferSpace: 0x%04x\n", indent+4, "", + pPortInfo->OverallBufferSpace); + if (g_hard) + printf( "%*sP_Key Enforcement: In: xxx Out: xxx\n", + indent+4, ""); + else + printf( "%*sP_Key Enforcement: In: %3s Out: %3s\n", + indent+4, "", + pPortInfo->s3.PartitionEnforcementInbound?"On":"Off", + pPortInfo->s3.PartitionEnforcementOutbound?"On":"Off"); + + if (detail > 1) { + ShowPortLinkDownReasonLog(portp, format, indent+4, detail-2); + } + + if ( portp->nodep && portp->pQOS && + (detail > 1) && !g_persist && !g_hard ) { + if ( portp->pQOS->SL2SCMap ) { + ShowSLSCTable(portp->nodep, portp, format, indent+4, detail-2); + } + if ( portp->pQOS->SC2SLMap ) { + ShowSCSLTable(portp->nodep, portp, format, indent+4, detail-2); + } + int i = 0; + for(i=0; ipQOS->SC2SCMapList[i])) ) { + ShowSCSCTable(portp->nodep, portp, i, format, indent+4, detail-2); + } + } + } + if (portp->pQOS && (detail > 1) && !g_persist && !g_hard) { + ShowVLArbTable(portp, format, indent+4, detail-2); + } + if ( portp->nodep && portp->pPartitionTable && (detail > 1) && + !g_persist && !g_hard ) { + ShowPKeyTable(portp->nodep, portp, format, indent+4, detail-2); + } + if (portp->pPortCounters && detail > 2 && ! g_persist && ! g_hard) { + ShowPortCounters(portp->pPortCounters, format, indent+4, detail-2); + } + } else { + if (g_hard) + printf("%*sWidth: xxxx Speed: xxxxxxx Downgraded? xxx\n", + indent+4, ""); + else + printf("%*sWidth: %4s Speed: %7s Downgraded? %s\n", + indent+4, "", + StlLinkWidthToText(pPortInfo->LinkWidth.Active, buf1, sizeof(buf1)), + StlLinkSpeedToText(pPortInfo->LinkSpeed.Active, buf2, sizeof(buf2)), + ((pPortInfo->LinkWidth.Active == pPortInfo->LinkWidthDowngrade.TxActive) && + (pPortInfo->LinkWidth.Active == pPortInfo->LinkWidthDowngrade.RxActive))? + " No": "Yes"); + } + + if (detail && portp->pCableInfoData) + ShowCableSummary(portp->pCableInfoData, FORMAT_TEXT, indent+4, detail, pPortInfo->PortPhysConfig.s.PortType); + break; + case FORMAT_XML: + printf("%*s\n", indent, "", + portp->nodep->NodeInfo.NodeGUID, portp->PortNum); + XmlPrintDec("PortNum", portp->PortNum, indent+4); + if (portp->PortGUID) { + if (! (g_persist || g_hard)) + XmlPrintLID("LID", portp->EndPortLID, + indent+4); + XmlPrintHex64("GUID", portp->PortGUID, indent+4); + } + { + PortSelector* portselp = GetPortSelector(portp); + if (portselp && portselp->details) { + XmlPrintOptionalStr("PortDetails", portselp->details, indent+4); + } + } + if (portp->neighbor) { + printf("%*s\n", indent+4, ""); + ShowLinkPortSummary(portp->neighbor, "Neighbor: ", format, indent+8, detail); + if (detail-1) + ShowExpectedLinkSummary(portp->neighbor->elinkp, format, indent+12, detail-1); + printf("%*s\n", indent+4, ""); + } + if (detail) { + if (g_hard) { + // noop + XmlPrintDec("LocalPort", pPortInfo->LocalPortNum, indent+4); + XmlPrintStr("PortType", StlPortTypeToText(pPortInfo->PortPhysConfig.s.PortType), indent+4); + XmlPrintHex("PortType_Int", pPortInfo->PortPhysConfig.s.PortType, indent+4); + } else { + XmlPrintDec("LocalPort", pPortInfo->LocalPortNum, indent+4); + XmlPrintStr("PortState", + IbPortStateToText(pPortInfo->PortStates.s.PortState), indent+4); + XmlPrintDec("PortState_Int", + pPortInfo->PortStates.s.PortState, indent+4); + if (pPortInfo->PortStates.s.PortState == IB_PORT_INIT) { + XmlPrintStr("InitReason", + StlLinkInitReasonToText(pPortInfo->s3.LinkInitReason), indent+4); + XmlPrintDec("InitReason_Int", + pPortInfo->s3.LinkInitReason, indent+4); + } + XmlPrintStr("PortType", StlPortTypeToText(pPortInfo->PortPhysConfig.s.PortType), indent+4); + XmlPrintHex("PortType_Int", pPortInfo->PortPhysConfig.s.PortType, indent+4); + + XmlPrintStr("PhysState", + StlPortPhysStateToText(pPortInfo->PortStates.s.PortPhysicalState), + indent+4); + XmlPrintDec("PhysState_Int", + pPortInfo->PortStates.s.PortPhysicalState, indent+4); + XmlPrintStr("IsSMConfigurationStarted", pPortInfo->PortStates.s.IsSMConfigurationStarted?"True":"False", indent+4); + XmlPrintStr("NeighborNormal", pPortInfo->PortStates.s.NeighborNormal?"True":"False", indent+4); + if (pPortInfo->PortStates.s.PortPhysicalState == STL_PORT_PHYS_OFFLINE + || pPortInfo->PortStates.s.PortPhysicalState == IB_PORT_PHYS_DISABLED) { + XmlPrintStr("OfflineDisabledReason", + StlPortOfflineDisabledReasonToText(pPortInfo->PortStates.s.OfflineDisabledReason), + indent+4); + XmlPrintDec("OfflineDisabledReason_Int", + pPortInfo->PortStates.s.OfflineDisabledReason, indent+4); + } + } + if (g_hard) { + // noop + } else { + if (! g_persist) + XmlPrintLID("LID", pPortInfo->LID, indent+4); + XmlPrintDec("LMC", pPortInfo->s1.LMC, indent+4); + XmlPrintHex64("SubnetPrefix", pPortInfo->SubnetPrefix, indent+4); + if (! g_persist) + XmlPrintLID("SMLID", pPortInfo->MasterSMLID, indent+4); + XmlPrintDec("SMSL", pPortInfo->s2.MasterSMSL, indent+4); + FormatTimeoutMult(buf1, pPortInfo->Resp.TimeValue); + XmlPrintStr("RespTimeout", buf1, indent+4); + XmlPrintDec("RespTimeout_Int", pPortInfo->Resp.TimeValue, + indent+4); + FormatTimeoutMult(buf1, pPortInfo->Subnet.Timeout); + XmlPrintStr("SubnetTimeout", buf1, indent+4); + XmlPrintDec("SubnetTimeout_Int", pPortInfo->Subnet.Timeout, + indent+4); + } + if (g_hard) { + // noop + } else { + XmlPrintHex64("M_KEY", pPortInfo->M_Key, indent+4); + printf("%*s%u \n", + indent+4, "", + pPortInfo->M_KeyLeasePeriod); + XmlPrintStr("Protect", + IbMKeyProtectToText(pPortInfo->s1.M_KeyProtectBits), + indent+4); + XmlPrintDec("Protect_Int", + pPortInfo->s1.M_KeyProtectBits, indent+4); + } + + XmlPrintDec("MTUSupported", + GetBytesFromMtu(pPortInfo->MTU.Cap), indent+4); + if (! g_hard) + { + int i; + char indxStr[5]; + printf("%*s\n", indent+4, ""); + for (i = 0; i < STL_MAX_VLS; ++i) + { + snprintf(indxStr, sizeof(indxStr), "VL%u", i); + XmlPrintDec(indxStr, GetBytesFromMtu(GET_STL_PORT_INFO_NeighborMTU(pPortInfo, i)), indent+8); + } + printf("%*s\n", indent+4, ""); + + } + if (! g_hard) + { + int i; + char indxStr[5]; + printf("%*s\n", indent+4, ""); + for (i = 0; i < STL_MAX_VLS; ++i) + { + snprintf(indxStr, sizeof(indxStr), "VL%u", i); + XmlPrintDec(indxStr, pPortInfo->XmitQ[i].VLStallCount, indent+8); + } + printf("%*s\n", indent+4, ""); + } + + if (! g_hard) { + XmlPrintLinkWidth("LinkWidthActive", + pPortInfo->LinkWidth.Active, indent+4); + } + XmlPrintLinkWidth("LinkWidthSupported", + pPortInfo->LinkWidth.Supported, indent+4); + if (! g_hard) { + XmlPrintLinkWidth("LinkWidthEnabled", + pPortInfo->LinkWidth.Enabled, indent+4); + } + if (! g_hard) { + XmlPrintLinkWidth("LinkWidthDnGradeTxActive", + pPortInfo->LinkWidthDowngrade.TxActive, indent+4); + XmlPrintLinkWidth("LinkWidthDnGradeRxActive", + pPortInfo->LinkWidthDowngrade.RxActive, indent+4); + } + XmlPrintLinkWidth("LinkWidthDnGradeSupported", + pPortInfo->LinkWidthDowngrade.Supported, indent+4); + if (! g_hard) { + XmlPrintLinkWidth("LinkWidthDnGradeEnabled", + pPortInfo->LinkWidthDowngrade.Enabled, indent+4); + } + if (! g_hard) { + XmlPrintLinkSpeed("LinkSpeedActive", + pPortInfo->LinkSpeed.Active, indent+4); + } + XmlPrintLinkSpeed("LinkSpeedSupported", + pPortInfo->LinkSpeed.Supported, indent+4); + if (! g_hard) { + XmlPrintLinkSpeed("LinkSpeedEnabled", + pPortInfo->LinkSpeed.Enabled, indent+4); + } + + if (! g_hard) { + XmlPrintStr("PortLinkModeActive", + StlPortLinkModeToText(pPortInfo->PortLinkMode.s.Active, + buf1, sizeof(buf1)), indent+4); + } + XmlPrintStr("PortLinkModeSupported", + StlPortLinkModeToText(pPortInfo->PortLinkMode.s.Supported, + buf1, sizeof(buf1)), indent+4); + if (! g_hard) { + XmlPrintStr("PortLinkModeEnabled", + StlPortLinkModeToText(pPortInfo->PortLinkMode.s.Enabled, + buf1, sizeof(buf1)), indent+4); + } + + if (! g_hard) { + XmlPrintPortLtpCrc("PortLTPCRCModeActive", + pPortInfo->PortLTPCRCMode.s.Active, indent+4); + } + XmlPrintPortLtpCrc("PortLTPCRCModeSupported", + pPortInfo->PortLTPCRCMode.s.Supported, indent+4); + if (! g_hard) { + XmlPrintPortLtpCrc("PortLTPCRCModeEnabled", + pPortInfo->PortLTPCRCMode.s.Enabled, indent+4); + } + + XmlPrintDec("SM_TrapQP", pPortInfo->SM_TrapQP.s.QueuePair, indent+4); + XmlPrintDec("SA_QP", pPortInfo->SA_QP.s.QueuePair, indent+4); + XmlPrintStr("IPV6", inet_ntop(AF_INET6, pPortInfo->IPAddrIPV6.addr, buf1, sizeof(buf1)), indent+4); + XmlPrintStr("IPV4", inet_ntop(AF_INET, pPortInfo->IPAddrIPV4.addr, buf2, sizeof(buf2)), indent+4); + + if (! g_hard) { + printf( "%*s%u+1\n", + indent+4, "", + pPortInfo->s4.OperationalVL); + XmlPrintDec("VLsActive_Int", + pPortInfo->s4.OperationalVL, indent+4); + } + printf( "%*s%u+1\n", + indent+4, "", + pPortInfo->VL.s2.Cap); + XmlPrintDec("VLsSupported_Int", + pPortInfo->VL.s2.Cap, indent+4); + + if (! g_hard) + { + int i; + char indxStr[5]; + printf("%*s\n", indent+4, ""); + for (i = 0; i < STL_MAX_VLS; ++i) + { + snprintf(indxStr, sizeof(indxStr), "VL%u", i); + if (pPortInfo->XmitQ[i].HOQLife > IB_LIFETIME_MAX) + { + strncpy(buf1, "Infinite", 9); + } else { + FormatTimeoutMult(buf1, pPortInfo->XmitQ[i].HOQLife); + } + XmlPrintStr(indxStr, buf1, indent+8); + } + printf("%*s\n", indent+4, ""); + printf("%*s\n", indent+4, ""); + for (i = 0; i < STL_MAX_VLS; ++i) + { + snprintf(indxStr, sizeof(indxStr), "VL%u", i); + if (pPortInfo->XmitQ[i].HOQLife > IB_LIFETIME_MAX) + { + strncpy(buf1, "Infinite", 9); + } else { + FormatTimeoutMult(buf1, pPortInfo->XmitQ[i].HOQLife); + } + XmlPrintDec(indxStr, pPortInfo->XmitQ[i].HOQLife, indent+8); + } + printf("%*s\n", indent+4, ""); + } + + if (pPortInfo->CapabilityMask3.s.VLSchedulingConfig == VL_SCHED_MODE_VLARB) { + XmlPrintDec("VLArbHighCap", pPortInfo->VL.ArbitrationHighCap, + indent+4); + + XmlPrintDec("VLArbLowCap", pPortInfo->VL.ArbitrationLowCap, + indent+4); + if (! g_hard) { + XmlPrintDec("VLArbHighLimit", pPortInfo->VL.HighLimit, + indent+4); + XmlPrintDec("VLArbPreemptLimit", pPortInfo->VL.PreemptingLimit, + indent+4); + } + } + + + + XmlPrintHex32("VLFlowControlDisabledMask", pPortInfo->FlowControlMask, indent+4); + XmlPrintStr("NeighborModeMgmntAllowed", pPortInfo->PortNeighborMode.MgmtAllowed?"Yes":"No", indent+4); + XmlPrintStr("NeighborModeFWAuthenBypass", pPortInfo->PortNeighborMode.NeighborFWAuthenBypass?"Yes":"No", indent+4); + XmlPrintStr("NeighborModeNeighborNodeType", + OpaNeighborNodeTypeToText(pPortInfo->PortNeighborMode.NeighborNodeType), + indent+4); + + FormatStlCapabilityMask(buf1, pPortInfo->CapabilityMask); + XmlPrintHex32("CapabilityMask", + pPortInfo->CapabilityMask.AsReg32, + indent+4); + XmlPrintStr("Capability", buf1, indent+4); + XmlPrintHex16("CapabilityMask3", pPortInfo->CapabilityMask3.AsReg16, indent+4); + FormatStlCapabilityMask3(buf1, pPortInfo->CapabilityMask3, sizeof(buf1)); + XmlPrintStr("Capability3", buf1, indent+4); + if (g_persist || g_hard) { + // noop + } else { + XmlPrintDec("ViolationsM_Key", + pPortInfo->Violations.M_Key, indent+4); + XmlPrintDec("ViolationsP_Key", + pPortInfo->Violations.P_Key, indent+4); + XmlPrintDec("ViolationsQ_Key", + pPortInfo->Violations.Q_Key, indent+4); + } + if (g_hard) { + // noop + } else { + XmlPrintHex16( "DiagCode", pPortInfo->DiagCode.AsReg16, indent+4); + } + + XmlPrintHex16("OverallBufferSpace", pPortInfo->OverallBufferSpace, indent+4); + if (! g_hard && ! g_persist) { + XmlPrintHex8("LinkDownReason", pPortInfo->LinkDownReason, indent+4); + XmlPrintHex8("NeighborLinkDownReason", pPortInfo->NeighborLinkDownReason, indent+4); + } + if (! g_hard ) { + XmlPrintStr("ActiveOptimize", pPortInfo->PortMode.s.IsActiveOptimizeEnabled?"On":"Off", indent+4); + XmlPrintStr("PassThrough", pPortInfo->PortMode.s.IsPassThroughEnabled?"On":"Off", indent+4); + XmlPrintStr("VLMarker", pPortInfo->PortMode.s.IsVLMarkerEnabled?"On":"Off", indent+4); + } + + XmlPrintDec("FlitCtrlInterleaveDistanceMax", pPortInfo->FlitControl.Interleave.s.DistanceSupported,indent+4); + if (! g_hard) { + XmlPrintDec("MaxNestLevelRxSupported", pPortInfo->FlitControl.Interleave.s.MaxNestLevelRxSupported,indent+4); + XmlPrintDec("FlitControlInterleaveDistance", pPortInfo->FlitControl.Interleave.s.DistanceEnabled, indent+4); + } + + XmlPrintDec("SmallPktLimitMax", pPortInfo->FlitControl.Preemption.MaxSmallPktLimit, indent+4); + if (! g_hard) { + XmlPrintDec("SmallPktLimit", pPortInfo->FlitControl.Preemption.SmallPktLimit, indent+4); + XmlPrintDec("PreemptionLimit", pPortInfo->FlitControl.Preemption.PreemptionLimit, indent+4); + // Convert Flits to bytes and display in decimal + XmlPrintDec("MinInitial", pPortInfo->FlitControl.Preemption.MinInitial, indent+4); + // Convert Flits to bytes and display in decimal + XmlPrintDec("MinTail", (pPortInfo->FlitControl.Preemption.MinTail * BYTES_PER_FLIT), indent+4); + XmlPrintDec("LargePktLimit", (pPortInfo->FlitControl.Preemption.LargePktLimit * BYTES_PER_FLIT), indent+4); + } + + if (! g_hard ) { + if(pPortInfo->CapabilityMask3.s.IsMAXLIDSupported) + XmlPrintLID("MaxLID", pPortInfo->MaxLID, indent+4); + + } + + if (! g_hard ) + XmlPrintHex32("PortErrorAction", pPortInfo->PortErrorAction.AsReg32, indent+4); + + XmlPrintHex16("VL15Init", pPortInfo->BufferUnits.s.VL15Init, indent+4); + XmlPrintHex8("CreditAck", pPortInfo->BufferUnits.s.CreditAck, indent+4); + XmlPrintHex8("BufferAlloc", pPortInfo->BufferUnits.s.BufferAlloc, indent+4); + XmlPrintHex16("ReplayDepthBuffer", (pPortInfo->ReplayDepthH.BufferDepthH << 8) | pPortInfo->ReplayDepth.BufferDepth, indent+4); + if (!g_persist && !g_hard) + XmlPrintHex16("ReplayDepthWire", (pPortInfo->ReplayDepthH.WireDepthH << 8) | pPortInfo->ReplayDepth.WireDepth, indent+4); + + if (! g_hard) { + XmlPrintHex8("VL15CreditRate", pPortInfo->BufferUnits.s.VL15CreditRate, indent+4); + } + if (! g_hard) { + XmlPrintStr( "P_KeyEnforcementInbound", + pPortInfo->s3.PartitionEnforcementInbound?"On":"Off", + indent+4); + XmlPrintDec( "P_KeyEnforcementInbound_Int", + pPortInfo->s3.PartitionEnforcementInbound, + indent+4); + XmlPrintStr("P_KeyEnforcementOutbound", + pPortInfo->s3.PartitionEnforcementOutbound?"On":"Off", + indent+4); + XmlPrintDec("P_KeyEnforcementOutbound_Int", + pPortInfo->s3.PartitionEnforcementOutbound, + indent+4); + } + if (detail > 1) { + ShowPortLinkDownReasonLog(portp, format, indent+4, detail-2); + } + if ( portp->nodep && portp->pQOS && + (detail > 1) && !g_persist && !g_hard ) { + if ( portp->pQOS->SL2SCMap ) { + ShowSLSCTable(portp->nodep, portp, format, indent+8, detail-2); + } + if ( portp->pQOS->SC2SLMap ) { + ShowSCSLTable(portp->nodep, portp, format, indent+8, detail-2); + } + int i = 0; + for(i=0; ipQOS->SC2SCMapList[i])) ) { + ShowSCSCTable(portp->nodep, portp, i, format, indent+8, detail-2); + } + } + } + if (portp->pQOS && (detail > 1) && !g_persist && !g_hard) { + ShowVLArbTable(portp, format, indent+8, detail-2); + } + if ( portp->nodep && portp->pPartitionTable && (detail > 1) && + !g_persist && !g_hard ) { + ShowPKeyTable(portp->nodep, portp, format, indent+8, detail-2); + } + if (portp->pPortCounters && detail > 2 && ! g_persist && ! g_hard) { + ShowPortCounters(portp->pPortCounters, format, indent+8, detail-2); + } + } else { + if (! g_hard) { + XmlPrintLinkWidth("LinkWidthActive", + pPortInfo->LinkWidth.Active, indent+4); + XmlPrintLinkSpeed("LinkSpeedActive", + pPortInfo->LinkSpeed.Active, indent+4); + } + } + if (detail && portp->pCableInfoData) + ShowCableSummary(portp->pCableInfoData, FORMAT_XML, indent+4, detail, pPortInfo->PortPhysConfig.s.PortType); + printf("%*s\n", indent, ""); + break; + default: + break; + } +} // End of ShowPortSummary() + +// output verbose summary of a IB Node +void ShowNodeSummary(NodeData *nodep, Point *focus, Format_t format, int indent, int detail) +{ + cl_map_item_t *p; + char buf1[SHOW_BUF_SIZE], buf2[SHOW_BUF_SIZE]; + + switch (format) { + case FORMAT_TEXT: + // omit fields which are port specific: + // LID, PortGUID, LocalPortNum + // TBD - is PartitionCap per Port or per Node? + printf("%*sName: %.*s\n", + indent, "", + STL_NODE_DESCRIPTION_ARRAY_SIZE, + g_noname?g_name_marker:(char*)nodep->NodeDesc.NodeString); + printf("%*sNodeGUID: 0x%016"PRIx64" Type: %s\n", + indent+4, "", nodep->NodeInfo.NodeGUID, + StlNodeTypeToText(nodep->NodeInfo.NodeType)); + if (nodep->enodep && nodep->enodep->details) { + printf("%*sNodeDetails: %s\n", indent+4, "", nodep->enodep->details); + } + printf("%*sPorts: %d PartitionCap: %d SystemImageGuid: 0x%016"PRIx64"\n", + indent+4, "", nodep->NodeInfo.NumPorts, + nodep->NodeInfo.PartitionCap, + nodep->NodeInfo.SystemImageGUID); + printf("%*sBaseVer: %d SmaVer: %d VendorID: 0x%x DeviceID: 0x%x Rev: 0x%x\n", + indent+4, "", nodep->NodeInfo.BaseVersion, + nodep->NodeInfo.ClassVersion, + nodep->NodeInfo.u1.s.VendorID, + nodep->NodeInfo.DeviceID, + nodep->NodeInfo.Revision); + if (nodep->pSwitchInfo) { + STL_SWITCHINFO_RECORD *pSwitchInfoRecord = nodep->pSwitchInfo; + STL_SWITCH_INFO *pSwitchInfo = &pSwitchInfoRecord->SwitchInfoData; + if (g_persist || g_hard) + printf("%*sLID: xxxxxxxxxx", indent+4, ""); + else + printf("%*sLID: 0x%.*x", indent+4, "", (pSwitchInfoRecord->RID.LID <= IB_MAX_UCAST_LID ? 4:8), + pSwitchInfoRecord->RID.LID); + printf( " LinearFDBCap: %5u ", + pSwitchInfo->LinearFDBCap ); + if (g_persist || g_hard) + printf("LinearFDBTop: xxxxxxxxxx"); + else + printf( "LinearFDBTop: 0x%08x", + pSwitchInfo->LinearFDBTop ); + printf( " MCFDBCap: %5u\n", + pSwitchInfo->MulticastFDBCap ); + printf("%*sPartEnfCap: %5u ", indent+4, "", pSwitchInfo->PartitionEnforcementCap); + if (g_persist || g_hard) { + printf("U1: 0x%02x PortStateChange: x SwitchLifeTime x\n", + pSwitchInfo->u1.AsReg8); + printf("%*sU2: 0x%02x: %s\n", + indent+4, "", + pSwitchInfo->u2.AsReg8, + pSwitchInfo->u2.s.EnhancedPort0?"E0 ": ""); + } else { + printf("U1: 0x%02x PortStateChange: %1u SwitchLifeTime %2u\n", + pSwitchInfo->u1.AsReg8, + pSwitchInfo->u1.s.PortStateChange, + pSwitchInfo->u1.s.LifeTimeValue); + printf("%*sU2: 0x%02x: %s\n", + indent+4, "", + pSwitchInfo->u2.AsReg8, + pSwitchInfo->u2.s.EnhancedPort0?"E0 ": ""); + } + + + if (! (g_persist || g_hard)) { + printf("%*sAR: 0x%04x: %s%s%s%sF%u T%u\n", + indent+4, "", + pSwitchInfo->AdaptiveRouting.AsReg16, + pSwitchInfo->AdaptiveRouting.s.Enable?"On ": "", + pSwitchInfo->AdaptiveRouting.s.Pause?"Pause ": "", + pSwitchInfo->AdaptiveRouting.s.Algorithm?((pSwitchInfo->AdaptiveRouting.s.Algorithm==2)?"RGreedy ":"Greedy "): "Random ", + pSwitchInfo->AdaptiveRouting.s.LostRoutesOnly?"LostOnly ": "", + pSwitchInfo->AdaptiveRouting.s.Frequency, + pSwitchInfo->AdaptiveRouting.s.Threshold); + } else { + printf("%*sAR: xxxxxx: x\n", indent+4, ""); + } + printf("%*sCapabilityMask: 0x%04x: %s%s\n", + indent+4, "", + pSwitchInfo->CapabilityMask.AsReg16, + pSwitchInfo->CapabilityMask.s.IsAddrRangeConfigSupported?"ARC ":"", + pSwitchInfo->CapabilityMask.s.IsAdaptiveRoutingSupported?"AR ":""); + + if (! (g_persist || g_hard)) { + printf("%*sRouting Mode: Supported: 0x%x Enabled 0x%x\n", + indent+4, "", + pSwitchInfo->RoutingMode.Supported, + pSwitchInfo->RoutingMode.Enabled); + } else { + printf("%*sRouting Mode: Supported: 0x%x Enabled x\n", + indent+4, "", + pSwitchInfo->RoutingMode.Supported); + } + { + printf("%*sIPAddrIPV6: %s IPAddrIPV4: %s\n", + indent+4, "", + inet_ntop(AF_INET6, + pSwitchInfo->IPAddrIPV6.addr, + buf1, sizeof(buf1)), + inet_ntop(AF_INET, + pSwitchInfo->IPAddrIPV4.addr, + buf2, sizeof(buf2))); + } + } + + printf("%*s%u Connected Ports%s\n", indent, "", + CountInitializedPorts(&g_Fabric, nodep), detail?":":""); + break; + case FORMAT_XML: + // omit fields which are port specific: + // LID, PortGUID, LocalPortNum + // TBD - is PartitionCap per Port or per Node? + printf("%*s\n", indent, "", + nodep->NodeInfo.NodeGUID); + XmlPrintNodeDesc((char*)nodep->NodeDesc.NodeString, indent+4); + XmlPrintNodeType(nodep->NodeInfo.NodeType, indent+4); + if (nodep->enodep && nodep->enodep->details) { + XmlPrintOptionalStr("NodeDetails", nodep->enodep->details, indent+4); + } + XmlPrintDec("BaseVer", nodep->NodeInfo.BaseVersion, indent+4); + XmlPrintDec("SmaVer", nodep->NodeInfo.ClassVersion, indent+4); + XmlPrintDec("NumPorts", nodep->NodeInfo.NumPorts, indent+4); + XmlPrintHex64("SystemImageGUID", nodep->NodeInfo.SystemImageGUID, indent+4); + XmlPrintHex64("NodeGUID", nodep->NodeInfo.NodeGUID, indent+4); + XmlPrintDec("PartitionCap", nodep->NodeInfo.PartitionCap, indent+4); + XmlPrintHex("DeviceID", nodep->NodeInfo.DeviceID, indent+4); + XmlPrintHex("Revision", nodep->NodeInfo.Revision, indent+4); + XmlPrintHex("VendorID", nodep->NodeInfo.u1.s.VendorID, indent+4); + + if (nodep->pSwitchInfo) { + STL_SWITCHINFO_RECORD *pSwitchInfoRecord = nodep->pSwitchInfo; + STL_SWITCH_INFO *pSwitchInfo = &pSwitchInfoRecord->SwitchInfoData; + if (! (g_persist || g_hard)) + XmlPrintLID("LID", pSwitchInfoRecord->RID.LID, indent+4); + XmlPrintDec("LinearFDBCap", pSwitchInfo->LinearFDBCap, indent+4); + XmlPrintDec("MulticastFDBCap", pSwitchInfo->MulticastFDBCap, indent+4); + if (! (g_persist || g_hard)) + XmlPrintDec("LinearFDBTop", pSwitchInfo->LinearFDBTop, indent+4); + + { + XmlPrintStr("IPAddrIPV6", + inet_ntop(AF_INET6, + pSwitchInfo->IPAddrIPV6.addr, + buf1, sizeof(buf1)), + indent+4); + XmlPrintStr("IPAddrIPV4", + inet_ntop(AF_INET, + pSwitchInfo->IPAddrIPV4.addr, + buf1, sizeof(buf1)), + indent+4); + } + XmlPrintHex8("U1",pSwitchInfo->u1.AsReg8,indent+4); + if ( ! (g_persist || g_hard)) { + XmlPrintDec("PortStateChange", + pSwitchInfo->u1.s.PortStateChange, + indent+4); + XmlPrintDec("SwitchLifeTime", + pSwitchInfo->u1.s.LifeTimeValue, + indent+4); + } + XmlPrintDec("PartitionEnforcementCap", + pSwitchInfo->PartitionEnforcementCap, + indent+4); + XmlPrintHex8("RoutingModeSupported", + pSwitchInfo->RoutingMode.Supported, indent+4); + if (!g_hard && !g_persist) { + XmlPrintHex8("RoutingModeEnabled", + pSwitchInfo->RoutingMode.Enabled, indent+4); + } + XmlPrintHex8("U2", + pSwitchInfo->u2.AsReg8, indent+4); + printf("%*s%s\n", + indent+4, "", + pSwitchInfo->u2.s.EnhancedPort0?"E0 ": ""); + if ( ! (g_persist || g_hard)) { + XmlPrintHex8("AdaptiveRouting", + pSwitchInfo->AdaptiveRouting.AsReg16, indent+4); + XmlPrintDec("LostRoutesOnly", + pSwitchInfo->AdaptiveRouting.s.LostRoutesOnly, indent+4); + XmlPrintDec("Pause", + pSwitchInfo->AdaptiveRouting.s.Pause, indent+4); + XmlPrintDec("Enable", + pSwitchInfo->AdaptiveRouting.s.Enable, indent+4); + XmlPrintDec("Algorithm", + pSwitchInfo->AdaptiveRouting.s.Algorithm, indent+4); + XmlPrintDec("Frequency", + pSwitchInfo->AdaptiveRouting.s.Frequency, indent+4); + XmlPrintDec("Threshold", + pSwitchInfo->AdaptiveRouting.s.Threshold, indent+4); + } + + if (pSwitchInfo->CapabilityMask.AsReg16) { + // only output if there are some vendor capabilities + XmlPrintHex16("StlCapabilityMask", + pSwitchInfo->CapabilityMask.AsReg16, indent+4); + printf("%*s%s\n", + indent+4, "", + pSwitchInfo->CapabilityMask.s.IsAdaptiveRoutingSupported?"AR ": ""); + } + } + + XmlPrintDec("ConnectedPorts", CountInitializedPorts(&g_Fabric, nodep), + indent+4); + break; + default: + break; + } + if (detail) { + for (p=cl_qmap_head(&nodep->Ports); p != cl_qmap_end(&nodep->Ports); p = cl_qmap_next(p)) { + PortData *portp = PARENT_STRUCT(p, PortData, NodePortsEntry); + if (! ComparePortPoint(portp, focus)) + continue; + ShowPortSummary(portp, format, indent+4, detail-1); + } + } + if (nodep->ioup) { + /* IOU report is brief, do it at top level detail for Node */ + ShowIouSummary(nodep->ioup, focus, format, indent+4, detail); + } + if (format == FORMAT_XML) { + printf("%*s\n", indent, ""); + } +} // End of ShowNodeSummary() + +// output verbose summary of a IB System +void ShowSystemSummary(SystemData *systemp, Point *focus, + Format_t format, int indent, int detail) +{ + cl_map_item_t *p; + + switch (format) { + case FORMAT_TEXT: + printf("%*sSystemImageGUID: 0x%016"PRIx64"\n", indent, "", systemp->SystemImageGUID); + printf("%*s%u Connected Nodes%s\n", indent, "", (unsigned)cl_qmap_count(&systemp->Nodes), detail?":":""); + break; + case FORMAT_XML: + printf("%*s\n", indent, "", + systemp->SystemImageGUID?systemp->SystemImageGUID: + PARENT_STRUCT(cl_qmap_head(&systemp->Nodes), NodeData, SystemNodesEntry)->NodeInfo.NodeGUID); + XmlPrintHex64("SystemImageGUID", systemp->SystemImageGUID, indent+4); + XmlPrintDec("ConnectedNodes", (unsigned)cl_qmap_count(&systemp->Nodes), + indent+4); + break; + default: + break; + } + if (detail) { + for (p=cl_qmap_head(&systemp->Nodes); p != cl_qmap_end(&systemp->Nodes); p = cl_qmap_next(p)) { + NodeData *nodep = PARENT_STRUCT(p, NodeData, SystemNodesEntry); + if (! CompareNodePoint(nodep, focus)) + continue; + ShowNodeSummary(nodep, focus, format, indent+4, detail-1); + } + } + if (format == FORMAT_XML) { + printf("%*s\n", indent, ""); + } +} + +// output verbose summary of IB SMs +void ShowSMSummary(SMData *smp, Format_t format, int indent, int detail) +{ + switch (format) { + case FORMAT_TEXT: + if (g_hard || g_persist) + printf("%*sState: xxxxxxxxxxx Name: %.*s\n", + indent, "", + NODE_DESCRIPTION_ARRAY_SIZE, + g_noname?g_name_marker:(char*)smp->portp->nodep->NodeDesc.NodeString); + else + printf("%*sState: %-11s Name: %.*s\n", + indent, "", + IbSMStateToText(smp->SMInfoRecord.SMInfo.u.s.SMStateCurrent), + NODE_DESCRIPTION_ARRAY_SIZE, + g_noname?g_name_marker:(char*)smp->portp->nodep->NodeDesc.NodeString); + printf("%*sNodeGUID: 0x%016"PRIx64" Type: %s\n", + indent+4, "", smp->portp->nodep->NodeInfo.NodeGUID, + StlNodeTypeToText(smp->portp->nodep->NodeInfo.NodeType)); + if (smp->portp->nodep->enodep && smp->portp->nodep->enodep->details) { + printf("%*sNodeDetails: %s\n", indent+4, "", smp->portp->nodep->enodep->details); + } + if (smp->esmp && smp->esmp->details) { + printf("%*sSMDetails: %s\n", indent+4, "", smp->esmp->details); + } + if (detail) { + if (g_hard || g_persist) + printf("%*sPortNum: %3u LID: xxxxxxxxxx PortGUID: 0x%016"PRIx64"\n", + indent+4, "", smp->portp->PortNum, + smp->SMInfoRecord.SMInfo.PortGUID); + else + printf("%*sPortNum: %3u LID: 0x%.*x PortGUID: 0x%016"PRIx64"\n", + indent+4, "", smp->portp->PortNum, + (smp->SMInfoRecord.RID.LID <= IB_MAX_UCAST_LID ? 4:8), + smp->SMInfoRecord.RID.LID, smp->SMInfoRecord.SMInfo.PortGUID); + if (g_hard) + printf("%*sSM_Key: xxxxxxxxxxxxxxxxxx Priority: xxx ActCount: xxxxxxxxxx\n", + indent+4, ""); + else if (g_persist) + printf("%*sSM_Key: xxxxxxxxxxxxxxxxxx Priority: %3d ActCount: xxxxxxxxxx\n", + indent+4, "", + smp->SMInfoRecord.SMInfo.u.s.Priority); + else + printf("%*sSM_Key: 0x%016"PRIx64" Priority: %3d ActCount: 0x%08x\n", + indent+4, "", + smp->SMInfoRecord.SMInfo.SM_Key, + smp->SMInfoRecord.SMInfo.u.s.Priority, + smp->SMInfoRecord.SMInfo.ActCount); + } + break; + case FORMAT_XML: + printf("%*s\n", indent, "", + smp->portp->nodep->NodeInfo.NodeGUID, + smp->portp->PortNum); + if (! (g_hard || g_persist)) { + XmlPrintStr("State", + IbSMStateToText(smp->SMInfoRecord.SMInfo.u.s.SMStateCurrent), + indent+4); + XmlPrintDec("State_Int", + smp->SMInfoRecord.SMInfo.u.s.SMStateCurrent, + indent+4); + } + XmlPrintNodeDesc( + (char*)smp->portp->nodep->NodeDesc.NodeString, indent+4); + XmlPrintHex64("NodeGUID", + smp->portp->nodep->NodeInfo.NodeGUID, + indent+4); + XmlPrintNodeType(smp->portp->nodep->NodeInfo.NodeType, + indent+4); + if (smp->portp->nodep->enodep && smp->portp->nodep->enodep->details) { + XmlPrintOptionalStr("NodeDetails", smp->portp->nodep->enodep->details, indent+4); + } + if (smp->esmp && smp->esmp->details) { + XmlPrintOptionalStr("SMDetails", smp->esmp->details, indent+4); + } + if (detail) { + XmlPrintDec("PortNum", smp->portp->PortNum, indent+4); + if (! (g_hard || g_persist)) + XmlPrintLID("LID", + smp->SMInfoRecord.RID.LID, indent+4); + XmlPrintHex64("PortGUID", + smp->SMInfoRecord.SMInfo.PortGUID, indent+4); + if (g_hard) { + // noop + } else if (g_persist) + XmlPrintDec("Priority", + smp->SMInfoRecord.SMInfo.u.s.Priority, indent+4); + else { + XmlPrintHex64("SM_Key", + smp->SMInfoRecord.SMInfo.SM_Key, indent+4); + XmlPrintDec("Priority", + smp->SMInfoRecord.SMInfo.u.s.Priority, indent+4); + XmlPrintHex32("ActCount", + smp->SMInfoRecord.SMInfo.ActCount, indent+4); + } + } + printf("%*s\n", indent, ""); + break; + default: + break; + } +} + +void ShowAllSMSummary(Point *focus, Format_t format, int indent, int detail) +{ + cl_map_item_t *p; + uint32 count = 0; + + switch (format) { + case FORMAT_TEXT: + printf("%*s%u Connected SMs in Fabric%s\n", indent, "", (unsigned)cl_qmap_count(&g_Fabric.AllSMs), detail?":":""); + break; + case FORMAT_XML: + printf("%*s\n", indent, ""); + XmlPrintDec("ConnectedSMCount", (unsigned)cl_qmap_count(&g_Fabric.AllSMs), + indent+4); + break; + default: + break; + } + + for (p=cl_qmap_head(&g_Fabric.AllSMs); p != cl_qmap_end(&g_Fabric.AllSMs); p = cl_qmap_next(p)) { + SMData *smp = PARENT_STRUCT(p, SMData, AllSMsEntry); + if (! CompareSmPoint(smp, focus)) + continue; + if (detail) + ShowSMSummary(smp, format, indent+4, detail-1); + count++; + } + switch (format) { + case FORMAT_TEXT: + if (PointValid(focus)) + printf("%*s%u Matching SMs Found\n", indent, "", count); + break; + case FORMAT_XML: + if (PointValid(focus)) + XmlPrintDec("MatchingSMs", count, indent+4); + printf("%*s\n", indent, ""); + break; + default: + break; + } +} + +// output verbose summary of all IB Components (Systems, Nodes, Ports, SMs) +void ShowComponentReport(Point *focus, Format_t format, int indent, int detail) +{ + cl_map_item_t *p; + uint32 count = 0; + + switch (format) { + case FORMAT_TEXT: + printf("%*sComponent Summary\n", indent, ""); + break; + case FORMAT_XML: + printf("%*s\n", indent, ""); + indent+=4; + break; + default: + break; + } + ShowPointFocus(focus, FIND_FLAG_FABRIC, format, indent, detail); + switch (format) { + case FORMAT_TEXT: + printf("%*s%u Connected Systems%s\n", indent, "", (unsigned)cl_qmap_count(&g_Fabric.AllSystems), detail?":":""); + break; + case FORMAT_XML: + printf("%*s\n", indent, ""); + XmlPrintDec("ConnectedSystems", (unsigned)cl_qmap_count(&g_Fabric.AllSystems), + indent+4); + break; + default: + break; + } + for (p=cl_qmap_head(&g_Fabric.AllSystems); p != cl_qmap_end(&g_Fabric.AllSystems); p = cl_qmap_next(p)) { + SystemData *systemp = PARENT_STRUCT(p, SystemData, AllSystemsEntry); + if (! CompareSystemPoint(systemp, focus)) + continue; + if (detail) + ShowSystemSummary(systemp, focus, format, indent+4, detail-1); + count++; + } + switch (format) { + case FORMAT_TEXT: + if (PointValid(focus)) + printf("%*s%u Matching Systems Found\n", indent, "", count); + if (detail) + printf("\n"); + break; + case FORMAT_XML: + if (PointValid(focus)) + XmlPrintDec("MatchingSystems", count, indent+4); + printf("%*s\n", indent, ""); + break; + default: + break; + } + ShowAllSMSummary(focus, format, indent, detail); + switch (format) { + case FORMAT_TEXT: + DisplaySeparator(); + break; + case FORMAT_XML: + indent-=4; + printf("%*s\n", indent, ""); + break; + default: + break; + } +} + +// output verbose summary of all IB Node Types +void ShowNodeTypeReport(Point *focus, Format_t format, int indent, int detail) +{ + LIST_ITEM *p; + uint32 count; + + switch (format) { + case FORMAT_TEXT: + printf("%*sNode Type Summary\n", indent, ""); + break; + case FORMAT_XML: + printf("%*s\n", indent, ""); + indent+=4; + break; + default: + break; + } + ShowPointFocus(focus, FIND_FLAG_FABRIC, format, indent, detail); + switch (format) { + case FORMAT_TEXT: + printf("%*s%u Connected FIs in Fabric%s\n", indent, "", (unsigned)QListCount(&g_Fabric.AllFIs), detail?":":""); + break; + case FORMAT_XML: + printf("%*s\n", indent, ""); + indent+=4; + XmlPrintDec("ConnectedFICount", (unsigned)QListCount(&g_Fabric.AllFIs), indent); + break; + default: + break; + } + count = 0; + for (p=QListHead(&g_Fabric.AllFIs); p != NULL; p = QListNext(&g_Fabric.AllFIs, p)) { + NodeData *nodep = (NodeData *)QListObj(p); + if (! CompareNodePoint(nodep, focus)) + continue; + if (detail) + ShowNodeSummary(nodep, focus, format, indent+4, detail-1); + count++; + } + switch (format) { + case FORMAT_TEXT: + if (PointValid(focus)) + printf("%*s%u Matching FIs Found\n", indent, "", count); + if (detail) + printf("\n"); + break; + case FORMAT_XML: + if (PointValid(focus)) + XmlPrintDec("MatchingFIs", count, indent+4); + indent-=4; + printf("%*s\n", indent, ""); + break; + default: + break; + } + + switch (format) { + case FORMAT_TEXT: + printf("%*s%u Connected Switches in Fabric%s\n", indent, "", (unsigned)QListCount(&g_Fabric.AllSWs), detail?":":""); + break; + case FORMAT_XML: + printf("%*s\n", indent, ""); + indent+=4; + XmlPrintDec("ConnectedSwitchCount", (unsigned)QListCount(&g_Fabric.AllSWs), + indent); + break; + default: + break; + } + count = 0; + for (p=QListHead(&g_Fabric.AllSWs); p != NULL; p = QListNext(&g_Fabric.AllSWs, p)) { + NodeData *nodep = (NodeData *)QListObj(p); + if (! CompareNodePoint(nodep, focus)) + continue; + if (detail) + ShowNodeSummary(nodep, focus, format, indent+4, detail-1); + count++; + } + switch (format) { + case FORMAT_TEXT: + if (PointValid(focus)) + printf("%*s%u Matching Switches Found\n", indent, "", count); + if (detail) + printf("\n"); + break; + case FORMAT_XML: + if (PointValid(focus)) + XmlPrintDec("MatchingSwitches", count, indent+4); + indent-=4; + printf("%*s\n", indent, ""); + break; + default: + break; + } + + ShowAllSMSummary(focus, format, indent, detail); + switch (format) { + case FORMAT_TEXT: + DisplaySeparator(); + break; + case FORMAT_XML: + indent-=4; + printf("%*s\n", indent, ""); + break; + default: + break; + } +} + +// output verbose summary of all IOUs +void ShowAllIOUReport(Point *focus, Format_t format, int indent, int detail) +{ + LIST_ITEM *p; + uint32 count = 0; + + switch (format) { + case FORMAT_TEXT: + printf("%*sIOU Summary\n", indent, ""); + break; + case FORMAT_XML: + printf("%*s\n", indent, ""); + indent+=4; + break; + default: + break; + } + ShowPointFocus(focus, FIND_FLAG_FABRIC, format, indent, detail); + switch (format) { + case FORMAT_TEXT: + printf("%*s%u IOUs in Fabric%s\n", indent, "", (unsigned)QListCount(&g_Fabric.AllIOUs), detail?":":""); + break; + case FORMAT_XML: + printf("%*s\n", indent, ""); + indent+=4; + XmlPrintDec("ConnectedIOUCount", (unsigned)QListCount(&g_Fabric.AllIOUs), indent); + break; + default: + break; + } + + for (p=QListHead(&g_Fabric.AllIOUs); p != NULL; p = QListNext(&g_Fabric.AllIOUs, p)) { + IouData *ioup = (IouData *)QListObj(p); + if (! CompareIouPoint(ioup, focus)) + continue; + if (detail) + ShowNodeSummary(ioup->nodep, focus, format, indent+4, detail-1); + count++; + } + switch (format) { + case FORMAT_TEXT: + if (PointValid(focus)) + printf("%*s%u Matching IOUs Found\n", indent, "", count); + DisplaySeparator(); + break; + case FORMAT_XML: + if (PointValid(focus)) + XmlPrintDec("MatchingIOUs", count, indent); + indent-=4; + printf("%*s\n", indent, ""); + indent-=4; + printf("%*s\n", indent, ""); + break; + default: + break; + } +} + +void ShowOtherPortSummaryHeader(Format_t format, int indent, int detail) +{ + switch (format) { + case FORMAT_TEXT: + printf("%*sNodeGUID Port Type Name\n", indent, ""); + break; + case FORMAT_XML: + break; + default: + break; + } +} + +// show a non-connected port in a node +void ShowOtherPortSummary(NodeData *nodep, uint8 portNum, + Format_t format, int indent, int detail) +{ + switch (format) { + case FORMAT_TEXT: + printf("%*s0x%016"PRIx64" %3u %s %.*s\n", + indent, "", + nodep->NodeInfo.NodeGUID, + portNum, + StlNodeTypeToText(nodep->NodeInfo.NodeType), + NODE_DESCRIPTION_ARRAY_SIZE, + g_noname?g_name_marker:(char*)nodep->NodeDesc.NodeString); + if (nodep->enodep && nodep->enodep->details) { + printf("%*sNodeDetails: %s\n", indent+4, "", nodep->enodep->details); + } + break; + case FORMAT_XML: + printf("%*s\n", indent, "", + nodep->NodeInfo.NodeGUID, portNum); + XmlPrintHex64("NodeGUID", + nodep->NodeInfo.NodeGUID, indent+4); + XmlPrintDec("PortNum", portNum, indent+4); + XmlPrintNodeType(nodep->NodeInfo.NodeType, + indent+4); + XmlPrintNodeDesc((char*)nodep->NodeDesc.NodeString, indent+4); + if (nodep->enodep && nodep->enodep->details) { + XmlPrintOptionalStr("NodeDetails", nodep->enodep->details, indent+4); + } + break; + default: + break; + } + if (format == FORMAT_XML) + printf("%*s\n", indent, ""); +} + +// show a non-connected port in a node +void ShowNodeOtherPortSummary(NodeData *nodep, + Format_t format, int indent, int detail) +{ + cl_map_item_t *p; + uint8 port; + + for (port=1, p=cl_qmap_head(&nodep->Ports); p != cl_qmap_end(&nodep->Ports);) + { + PortData *portp = PARENT_STRUCT(p, PortData, NodePortsEntry); + if (portp->PortNum == 0) + { + p = cl_qmap_next(p); + continue; /* skip switch port 0 */ + } + if (portp->PortNum != port) { + ShowOtherPortSummary(nodep, port, format, indent, detail); + } else { + if (! IsPortInitialized(portp->PortInfo.PortStates)) + ShowOtherPortSummary(nodep, port, format, indent, detail); + p = cl_qmap_next(p); + } + port++; + } + /* output remaining ports after last connected port */ + for (; port <= nodep->NodeInfo.NumPorts; port++) + ShowOtherPortSummary(nodep, port, format, indent, detail); +} + +// output verbose summary of IB ports not connected to this fabric +void ShowOtherPortsReport(Point *focus, Format_t format, int indent, int detail) +{ + LIST_ITEM *p; + uint32 node_count; + uint32 port_count; + uint32 other_port_count; + + switch (format) { + case FORMAT_TEXT: + printf("%*sOther Ports Summary\n", indent, ""); + break; + case FORMAT_XML: + printf("%*s\n", indent, ""); + indent+=4; + break; + default: + break; + } + ShowPointFocus(focus, FIND_FLAG_FABRIC, format, indent, detail); + switch (format) { + case FORMAT_TEXT: + printf("%*s%u Connected FIs in Fabric%s\n", indent, "", (unsigned)QListCount(&g_Fabric.AllFIs), detail?":":""); + break; + case FORMAT_XML: + printf("%*s\n", indent, ""); + indent+=4; + XmlPrintDec("ConnectedFICount", (unsigned)QListCount(&g_Fabric.AllFIs), indent); + break; + default: + break; + } + node_count = 0; + port_count = 0; + other_port_count = 0; + for (p=QListHead(&g_Fabric.AllFIs); p != NULL; p = QListNext(&g_Fabric.AllFIs, p)) { + NodeData *nodep = (NodeData *)QListObj(p); + uint32 initialized_port_count; + + if (! CompareNodePoint(nodep, focus)) + continue; + initialized_port_count = CountInitializedPorts(&g_Fabric, nodep); + port_count += initialized_port_count; + if (initialized_port_count >= nodep->NodeInfo.NumPorts) + continue; + // for FIs otherports will include ports connected to other fabrics + if (node_count == 0 && detail) + ShowOtherPortSummaryHeader(format, indent+4, detail-1); + other_port_count += nodep->NodeInfo.NumPorts - initialized_port_count; + if (detail) + ShowNodeOtherPortSummary(nodep, format, indent+4, detail-1); + node_count++; + } + switch (format) { + case FORMAT_TEXT: + if (PointValid(focus)) + printf("%*s%u Matching FIs Found\n", indent, "", node_count); + printf("%*s%u Connected FI Ports\n", indent, "", port_count); + printf("%*s%u Other FI Ports\n", indent, "", other_port_count); + if (detail) + printf("\n"); + break; + case FORMAT_XML: + if (PointValid(focus)) + XmlPrintDec("MatchingFIs", node_count, indent+4); + XmlPrintDec("ConnectedFIPorts", port_count, indent+4); + XmlPrintDec("OtherCAPorts", other_port_count, indent+4); + indent-=4; + printf("%*s\n", indent, ""); + break; + default: + break; + } + + switch (format) { + case FORMAT_TEXT: + printf("%*s%u Connected Switches in Fabric%s\n", indent, "", (unsigned)QListCount(&g_Fabric.AllSWs), detail?":":""); + break; + case FORMAT_XML: + printf("%*s\n", indent, ""); + indent+=4; + XmlPrintDec("ConnectedSwitchCount", (unsigned)QListCount(&g_Fabric.AllSWs), + indent); + break; + default: + break; + } + node_count = 0; + port_count = 0; + other_port_count = 0; + for (p=QListHead(&g_Fabric.AllSWs); p != NULL; p = QListNext(&g_Fabric.AllSWs, p)) { + NodeData *nodep = (NodeData *)QListObj(p); + uint32 initialized_port_count; + + if (! CompareNodePoint(nodep, focus)) + continue; + initialized_port_count = CountInitializedPorts(&g_Fabric, nodep); + /* don't count switch port 0 */ + if (initialized_port_count) { + PortData *portp = PARENT_STRUCT(cl_qmap_head(&nodep->Ports), PortData, NodePortsEntry); + if (portp->PortNum == 0 && IsPortInitialized(portp->PortInfo.PortStates)) + initialized_port_count--; + } + port_count += initialized_port_count; + if (initialized_port_count >= nodep->NodeInfo.NumPorts) + continue; + if (node_count == 0 && detail) + ShowOtherPortSummaryHeader(format, indent+4, detail-1); + other_port_count += nodep->NodeInfo.NumPorts - initialized_port_count; + if (detail) + ShowNodeOtherPortSummary(nodep, format, indent+4, detail-1); + node_count++; + } + switch (format) { + case FORMAT_TEXT: + if (PointValid(focus)) + printf("%*s%u Matching Switches Found\n", indent, "", node_count); + printf("%*s%u Connected Switch Ports\n", indent, "", port_count); + printf("%*s%u Other Switch Ports\n", indent, "", other_port_count); + if (detail) + printf("\n"); + break; + case FORMAT_XML: + if (PointValid(focus)) + XmlPrintDec("MatchingSwitches", node_count, indent+4); + XmlPrintDec("ConnectedSwitchPorts", port_count, indent+4); + XmlPrintDec("OtherSwitchPorts", other_port_count, indent+4); + indent-=4; + printf("%*s\n", indent, ""); + break; + default: + break; + } + + switch (format) { + case FORMAT_TEXT: + DisplaySeparator(); + break; + case FORMAT_XML: + indent-=4; + printf("%*s\n", indent, ""); + break; + default: + break; + } +} + +// undocumented report on sizes +void ShowSizesReport(void) +{ + printf("sizeof(SystemData)=%u\n", (unsigned)sizeof(SystemData)); + printf("sizeof(NodeData)=%u\n", (unsigned)sizeof(NodeData)); + printf("sizeof(PortData)=%u\n", (unsigned)sizeof(PortData)); + printf("sizeof(QOSData)=%u (up to 1 per port)\n", (unsigned)sizeof(QOSData)); + printf("sizeof(STL_PORT_COUNTERS_DATA)=%u (up to 1 per port)\n", (unsigned)sizeof(STL_PORT_COUNTERS_DATA)); + printf("sizeof(STL_PKEY_ELEMENT)=%u (up to 1 per port per pkey)\n", (unsigned)sizeof(STL_PKEY_ELEMENT)); + printf("sizeof(IouData)=%u\n", (unsigned)sizeof(IouData)); + printf("sizeof(IocData)=%u\n", (unsigned)sizeof(IocData)); + printf("sizeof(IOC_SERVICE)=%u\n", (unsigned)sizeof(IOC_SERVICE)); + printf("sizeof(SMData)=%u\n", (unsigned)sizeof(SMData)); + printf("sizeof(STL_SWITCHINFO_RECORD)=%u (up to 1 per switch)\n", (unsigned)sizeof(STL_SMINFO_RECORD)); + printf("sizeof(IB_PATH_RECORD)=%u (up to 1 per port)\n", (unsigned)sizeof(IB_PATH_RECORD)); + printf("sizeof(STL_NODE_RECORD)=%u\n", (unsigned)sizeof(STL_NODE_RECORD)); + printf("sizeof(STL_PORTINFO_RECORD)=%u\n", (unsigned)sizeof(STL_PORTINFO_RECORD)); + printf("sizeof(STL_LINK_RECORD)=%u\n", (unsigned)sizeof(STL_LINK_RECORD)); +} + +// output brief summary of a IB Port +void ShowPortBriefSummary(PortData *portp, Format_t format, int indent, int detail) +{ + char buf1[SHOW_BUF_SIZE], buf2[SHOW_BUF_SIZE]; + + switch (format) { + case FORMAT_TEXT: + if (portp->PortGUID) + if (g_hard || g_persist) + printf("%*s%3u xxxxxx 0x%016"PRIx64, + indent, "", portp->PortNum, + portp->PortGUID); + else + printf("%*s%3u 0x%04x 0x%016"PRIx64, + indent, "", portp->PortNum, + portp->EndPortLID, portp->PortGUID); + else + printf("%*s%3u ", + indent, "", portp->PortNum); + if (g_hard) + printf(" xxxx xxxxxxx\n"); + else + printf(" %4s %7s\n", + StlLinkWidthToText(portp->PortInfo.LinkWidth.Active, buf1, sizeof(buf1)), + StlLinkSpeedToText(portp->PortInfo.LinkSpeed.Active, buf2, sizeof(buf2))); + break; + case FORMAT_XML: + printf("%*s\n", indent, "", + portp->nodep->NodeInfo.NodeGUID, portp->PortNum); + XmlPrintDec("PortNum", portp->PortNum, indent+4); + if (portp->PortGUID) { + if (! (g_hard || g_persist)) { + XmlPrintLID("LID", + portp->EndPortLID, indent+4); + if (portp->PortInfo.s1.LMC) + XmlPrintDec("LMC", + portp->PortInfo.s1.LMC, indent+4); + } + XmlPrintHex64("PortGUID", portp->PortGUID, indent+4); + } + if (g_hard) { + // noop + } else { + XmlPrintLinkWidth("LinkWidthActive", + portp->PortInfo.LinkWidth.Active, indent+4); + XmlPrintLinkSpeed("LinkSpeedActive", + portp->PortInfo.LinkSpeed.Active, indent+4); + } + printf("%*s\n", indent, ""); + break; + default: + break; + } +} + +void ShowPortBriefSummaryHeadings(Format_t format, int indent, int detail) +{ + switch (format) { + case FORMAT_TEXT: + printf("%*sPort LID PortGUID Width Speed\n", indent, ""); + break; + case FORMAT_XML: + break; + default: + break; + } +} + +static void PrintXmlNodeSummaryBrief(NodeData *nodep, int indent) +{ + printf("%*s\n", indent, "", nodep->NodeInfo.NodeGUID); + XmlPrintHex64("NodeGUID",nodep->NodeInfo.NodeGUID, indent+4); + XmlPrintNodeType(nodep->NodeInfo.NodeType, indent+4); + XmlPrintNodeDesc((char*)nodep->NodeDesc.NodeString, indent+4); + if (nodep->enodep && nodep->enodep->details) { + XmlPrintOptionalStr("NodeDetails", nodep->enodep->details, indent+4); + } +} + +static void PrintBriefNodePorts(NodeData *nodep, Point *focus, Format_t format, + int indent, int detail) +{ + cl_map_item_t *p; + + for (p=cl_qmap_head(&nodep->Ports); p != cl_qmap_end(&nodep->Ports); p = cl_qmap_next(p)) { + PortData *portp = PARENT_STRUCT(p, PortData, NodePortsEntry); + if (! ComparePortPoint(portp, focus)) + continue; + ShowPortBriefSummary(portp, format, indent+4, detail-1); + } +} +// output brief summary of a IB Node +void ShowNodeBriefSummary(NodeData *nodep, Point *focus, + boolean close_node, Format_t format, int indent, int detail) +{ + switch (format) { + case FORMAT_TEXT: + printf("%*s0x%016"PRIx64" %s %.*s\n", + indent, "", nodep->NodeInfo.NodeGUID, + StlNodeTypeToText(nodep->NodeInfo.NodeType), + NODE_DESCRIPTION_ARRAY_SIZE, + g_noname?g_name_marker:(char*)nodep->NodeDesc.NodeString); + if (nodep->enodep && nodep->enodep->details) { + printf("%*sNodeDetails: %s\n", indent+4, "", nodep->enodep->details); + } + break; + case FORMAT_XML: + PrintXmlNodeSummaryBrief(nodep, indent); + break; + default: + break; + } + if (detail) + PrintBriefNodePorts(nodep, focus, format, indent, detail); + + if (close_node && format == FORMAT_XML) { + printf("%*s\n", indent, ""); + } +} + +void ShowTopologyNodeBriefSummary(NodeData *nodep, Point *focus, int indent, int detail) +{ + PrintXmlNodeSummaryBrief(nodep, indent); + // Print node/port xml tag only for opareport option -d3 or greater detail level + if (detail >= 2) + PrintBriefNodePorts(nodep, focus, FORMAT_XML, indent, detail); + printf("%*s\n", indent, ""); +} + +// output brief summary of an expected IB Node +void ShowExpectedNodeBriefSummary(const char *prefix, ExpectedNode *enodep, + const char *xml_tag, boolean close_node, Format_t format, + int indent, int detail) +{ + switch (format) { + case FORMAT_TEXT: + printf("%*s%s", indent, "", prefix); + if (enodep->NodeGUID) + printf("0x%016"PRIx64, enodep->NodeGUID); + else + printf("%*s", 18, ""); + if (enodep->NodeType) + printf(" %s", StlNodeTypeToText(enodep->NodeType)); + else + printf(" "); + if (enodep->NodeDesc) + printf(" %.*s\n", NODE_DESCRIPTION_ARRAY_SIZE, + g_noname?g_name_marker:enodep->NodeDesc); + else + printf("\n"); + if (enodep->details) + printf("%*sNodeDetails: %s\n", indent+4, "", enodep->details); + break; + case FORMAT_XML: + printf("%*s<%s id=\"0x%016"PRIx64"\">\n", indent, "", + xml_tag, (uint64)(uintn)enodep); + if (enodep->NodeGUID) + XmlPrintHex64("NodeGUID", enodep->NodeGUID, indent+4); + if (enodep->NodeType) + XmlPrintNodeType(enodep->NodeType, indent+4); + if (enodep->NodeDesc) + XmlPrintNodeDesc(enodep->NodeDesc, indent+4); + if (enodep->details) + XmlPrintOptionalStr("NodeDetails", enodep->details, indent+4); + break; + default: + break; + } + if (close_node && format == FORMAT_XML) { + printf("%*s\n", indent, "", xml_tag); + } +} + +void ShowNodeBriefSummaryHeadings(Format_t format, int indent, int detail) +{ + switch (format) { + case FORMAT_TEXT: + printf("%*sNodeGUID Type Name\n", indent, ""); + if (detail) + ShowPortBriefSummaryHeadings(format, indent+4, detail-1); + break; + case FORMAT_XML: + break; + default: + break; + } +} + +// output brief summary of a IB System +void ShowSystemBriefSummary(SystemData *systemp, Point *focus, + Format_t format, int indent, int detail) +{ + cl_map_item_t *p; + + switch (format) { + case FORMAT_TEXT: + printf("%*s0x%016"PRIx64"\n", indent, "", systemp->SystemImageGUID); + break; + case FORMAT_XML: + printf("%*s\n", indent, "", + systemp->SystemImageGUID?systemp->SystemImageGUID: + PARENT_STRUCT(cl_qmap_head(&systemp->Nodes), NodeData, SystemNodesEntry)->NodeInfo.NodeGUID); + XmlPrintHex64("SystemImageGUID", systemp->SystemImageGUID, indent+4); + break; + default: + break; + } + if (detail) { + for (p=cl_qmap_head(&systemp->Nodes); p != cl_qmap_end(&systemp->Nodes); p = cl_qmap_next(p)) { + NodeData *nodep = PARENT_STRUCT(p, NodeData, SystemNodesEntry); + if (! CompareNodePoint(nodep, focus)) + continue; + ShowNodeBriefSummary(nodep, focus, TRUE, format, indent+4, detail-1); + } + } + if (format == FORMAT_XML) { + printf("%*s\n", indent, ""); + } +} + +void ShowSystemBriefSummaryHeadings(Format_t format, int indent, int detail) +{ + switch (format) { + case FORMAT_TEXT: + printf("%*sSystemImage GUID\n", indent, ""); + if (detail) + ShowNodeBriefSummaryHeadings(format, indent+4, detail-1); + break; + case FORMAT_XML: + break; + default: + break; + } +} + +void ShowSMBriefSummary(SMData *smp, Format_t format, int indent, int detail) +{ + switch (format) { + case FORMAT_TEXT: + if (g_hard || g_persist) + printf("%*sxxxxxxxxxxx 0x%016"PRIx64" %.*s\n", + indent, "", + smp->portp->nodep->NodeInfo.NodeGUID, + NODE_DESCRIPTION_ARRAY_SIZE, + g_noname?g_name_marker:(char*)smp->portp->nodep->NodeDesc.NodeString); + else + printf("%*s%-11s 0x%016"PRIx64" %.*s\n", + indent, "", + IbSMStateToText(smp->SMInfoRecord.SMInfo.u.s.SMStateCurrent), + smp->portp->nodep->NodeInfo.NodeGUID, + NODE_DESCRIPTION_ARRAY_SIZE, + g_noname?g_name_marker:(char*)smp->portp->nodep->NodeDesc.NodeString); + if (smp->portp->nodep->enodep && smp->portp->nodep->enodep->details) { + printf("%*sNodeDetails: %s\n", indent+4, "", smp->portp->nodep->enodep->details); + } + if (smp->esmp && smp->esmp->details) { + printf("%*sSMDetails: %s\n", indent+4, "", smp->esmp->details); + } + break; + case FORMAT_XML: + printf("%*s\n", indent, "", + smp->portp->nodep->NodeInfo.NodeGUID, + smp->portp->PortNum); + if ( ! (g_hard || g_persist)) { + XmlPrintStr("SMState", + IbSMStateToText(smp->SMInfoRecord.SMInfo.u.s.SMStateCurrent), + indent+4); + XmlPrintDec("SMState_Int", + smp->SMInfoRecord.SMInfo.u.s.SMStateCurrent, indent+4); + } + XmlPrintHex64("NodeGUID", + smp->portp->nodep->NodeInfo.NodeGUID, + indent+4); + XmlPrintNodeDesc( + (char*)smp->portp->nodep->NodeDesc.NodeString, indent+4); + if (smp->portp->nodep->enodep && smp->portp->nodep->enodep->details) { + XmlPrintOptionalStr("NodeDetails", smp->portp->nodep->enodep->details, indent+4); + } + if (smp->esmp && smp->esmp->details) { + XmlPrintOptionalStr("SMDetails", smp->esmp->details, indent+4); + } + // we output this additional information to aid topology SM verify + XmlPrintDec("PortNum", smp->portp->PortNum, indent+4); + if (smp->portp->PortGUID) { + XmlPrintHex64("PortGUID", smp->portp->PortGUID, indent+4); + } + XmlPrintNodeType(smp->portp->nodep->NodeInfo.NodeType, + indent+4); + printf("%*s\n", indent, ""); + break; + default: + break; + } +} + +void ShowSMBriefSummaryHeadings(Format_t format, int indent, int detail) +{ + switch (format) { + case FORMAT_TEXT: + printf("%*sState GUID Name\n", indent, ""); + break; + case FORMAT_XML: + break; + default: + break; + } +} + +void ShowVerifySMBriefSummary(SMData *smp, + boolean close_sm, Format_t format, int indent, int detail) +{ + switch (format) { + case FORMAT_TEXT: + printf("%*s0x%016"PRIx64" %3u", indent, "", + smp->portp->nodep->NodeInfo.NodeGUID, + smp->portp->PortNum); + if (smp->portp->PortGUID) + printf(" 0x%016"PRIx64, smp->portp->PortGUID); + else + printf(" "); + printf(" %s %.*s\n", + StlNodeTypeToText(smp->portp->nodep->NodeInfo.NodeType), + NODE_DESCRIPTION_ARRAY_SIZE, + g_noname?g_name_marker:(char*)smp->portp->nodep->NodeDesc.NodeString); + if (smp->portp->nodep->enodep && smp->portp->nodep->enodep->details) { + printf("%*sNodeDetails: %s\n", indent+4, "", smp->portp->nodep->enodep->details); + } + if (smp->esmp && smp->esmp->details) { + printf("%*sSMDetails: %s\n", indent+4, "", smp->esmp->details); + } + break; + case FORMAT_XML: + printf("%*s\n", indent, "", + smp->portp->nodep->NodeInfo.NodeGUID, + smp->portp->PortNum); + XmlPrintHex64("NodeGUID", + smp->portp->nodep->NodeInfo.NodeGUID, + indent+4); + XmlPrintDec("PortNum", smp->portp->PortNum, indent+4); + if (smp->portp->PortGUID) { + XmlPrintHex64("PortGUID", smp->portp->PortGUID, indent+4); + } + XmlPrintNodeType(smp->portp->nodep->NodeInfo.NodeType, + indent+4); + XmlPrintNodeDesc( + (char*)smp->portp->nodep->NodeDesc.NodeString, indent+4); + if (smp->portp->nodep->enodep && smp->portp->nodep->enodep->details) { + XmlPrintOptionalStr("NodeDetails", smp->portp->nodep->enodep->details, indent+4); + } + if (smp->esmp && smp->esmp->details) { + XmlPrintOptionalStr("SMDetails", smp->esmp->details, indent+4); + } + if (close_sm) + printf("%*s\n", indent, ""); + break; + default: + break; + } +} + +void ShowExpectedSMBriefSummary(const char *prefix, ExpectedSM *esmp, + const char *xml_tag, boolean close_sm, Format_t format, int indent, int detail) +{ + switch (format) { + case FORMAT_TEXT: + printf("%*s%s", indent, "", prefix); + if (esmp->NodeGUID) + printf("0x%016"PRIx64, esmp->NodeGUID); + else + printf(" "); + if (esmp->gotPortNum) + printf(" %3u", esmp->PortNum); + else + printf(" "); + if (esmp->PortGUID) + printf(" 0x%016"PRIx64, esmp->PortGUID); + else + printf(" "); + if (esmp->NodeType) + printf(" %s", StlNodeTypeToText(esmp->NodeType)); + else + printf(" "); + if (esmp->NodeDesc) + printf(" %s\n", g_noname?g_name_marker:esmp->NodeDesc); + else + printf("\n"); + if (esmp->smp && esmp->smp->portp->nodep->enodep && esmp->smp->portp->nodep->enodep->details) + printf("%*sNodeDetails: %s\n", indent+4, "", esmp->smp->portp->nodep->enodep->details); + if (esmp->details) + printf("%*sSMDetails: %s\n", indent+4, "", esmp->details); + break; + case FORMAT_XML: + printf("%*s<%s id=\"0x%016"PRIx64"\">\n", indent, "", + xml_tag, (uint64)(uintn)esmp); + if (esmp->NodeGUID) + XmlPrintHex64("NodeGUID", esmp->NodeGUID, indent+4); + if (esmp->gotPortNum) + XmlPrintDec("PortNum", esmp->PortNum, indent+4); + if (esmp->NodeType) + XmlPrintNodeType(esmp->NodeType, indent+4); + if (esmp->NodeDesc) + XmlPrintNodeDesc(esmp->NodeDesc, indent+4); + if (esmp->smp && esmp->smp->portp->nodep->enodep && esmp->smp->portp->nodep->enodep->details) + XmlPrintOptionalStr("NodeDetails", esmp->smp->portp->nodep->enodep->details, indent+4); + if (esmp->details) + XmlPrintOptionalStr("SMDetails", esmp->details, indent+4); + if (esmp->PortGUID) { + XmlPrintHex64("PortGUID", esmp->PortGUID, indent+4); + } + if (close_sm) + printf("%*s\n", indent, "", xml_tag); + break; + default: + break; + } +} + +void ShowVerifySMBriefSummaryHeadings(Format_t format, int indent, int detail) +{ + switch (format) { + case FORMAT_TEXT: + printf("%*sNodeGUID Port PortGUID Type Name\n", indent, ""); + break; + case FORMAT_XML: + break; + default: + break; + } +} + +// output brief summary of IB SMs +void ShowAllSMBriefSummary(Point *focus, Format_t format, int indent, int detail) +{ + uint32 count = 0; + cl_map_item_t *p; + + switch (format) { + case FORMAT_TEXT: + printf("%*s%u Connected SMs in Fabric%s\n", indent, "", (unsigned)cl_qmap_count(&g_Fabric.AllSMs), detail?":":""); + break; + case FORMAT_XML: + printf("%*s\n", indent, ""); + indent+=4; + XmlPrintDec("ConnectedSMCount", (unsigned)cl_qmap_count(&g_Fabric.AllSMs), indent); + break; + default: + break; + } + for (p=cl_qmap_head(&g_Fabric.AllSMs); p != cl_qmap_end(&g_Fabric.AllSMs); p = cl_qmap_next(p)) { + SMData *smp = PARENT_STRUCT(p, SMData, AllSMsEntry); + if (! CompareSmPoint(smp, focus)) + continue; + if (detail) { + if (! count) + ShowSMBriefSummaryHeadings(format, indent, detail-1); + ShowSMBriefSummary(smp, format, indent, detail-1); + } + count++; + } + switch (format) { + case FORMAT_TEXT: + if (PointValid(focus)) + printf("%*s%u Matching SMs Found\n", indent, "", count); + break; + case FORMAT_XML: + if (PointValid(focus)) + XmlPrintDec("MatchingSMs", count, indent+4); + indent-=4; + printf("%*s\n", indent, ""); + break; + default: + break; + } +} + +// output verbose summary of all IB Components (Systems, Nodes, Ports) +void ShowComponentBriefReport(Point *focus, Format_t format, int indent, int detail) +{ + cl_map_item_t *p; + uint32 count = 0; + + switch (format) { + case FORMAT_TEXT: + printf("%*sComponent Brief Summary\n", indent, ""); + break; + case FORMAT_XML: + printf("%*s\n", indent, ""); + indent+=4; + break; + default: + break; + } + ShowPointFocus(focus, FIND_FLAG_FABRIC, format, indent, detail); + switch (format) { + case FORMAT_TEXT: + printf("%*s%u Connected Systems in Fabric%s\n", indent, "", (unsigned)cl_qmap_count(&g_Fabric.AllSystems), detail?":":""); + break; + case FORMAT_XML: + printf("%*s\n", indent, ""); + indent+=4; + XmlPrintDec("ConnectedSystemCount", (unsigned)cl_qmap_count(&g_Fabric.AllSystems), indent); + break; + default: + break; + } + for (p=cl_qmap_head(&g_Fabric.AllSystems); p != cl_qmap_end(&g_Fabric.AllSystems); p = cl_qmap_next(p)) { + SystemData *systemp = PARENT_STRUCT(p, SystemData, AllSystemsEntry); + if (! CompareSystemPoint(systemp, focus)) + continue; + if (detail) { + if (! count) + ShowSystemBriefSummaryHeadings(format, indent, detail-1); + ShowSystemBriefSummary(systemp, focus, format, indent, detail-1); + } + count++; + } + switch (format) { + case FORMAT_TEXT: + if (PointValid(focus)) + printf("%*s%u Matching Systems Found\n", indent, "", count); + printf("\n"); + break; + case FORMAT_XML: + if (PointValid(focus)) + XmlPrintDec("MatchingSystems", count, indent); + indent-=4; + printf("%*s\n", indent, ""); + break; + default: + break; + } + ShowAllSMBriefSummary(focus, format, indent, detail); + switch (format) { + case FORMAT_TEXT: + DisplaySeparator(); + break; + case FORMAT_XML: + indent-=4; + printf("%*s\n", indent, ""); + break; + default: + break; + } +} + +// output brief summary of all IB Node Types +void ShowNodeTypeBriefReport(Point *focus, Format_t format, report_t report, int indent, int detail) +{ + LIST_ITEM *p; + uint32 count; + + switch (format) { + case FORMAT_TEXT: + printf("%*sNode Type Brief Summary\n", indent, ""); + break; + case FORMAT_XML: + printf("%*s\n", indent, ""); + indent+=4; + break; + default: + break; + } + ShowPointFocus(focus, FIND_FLAG_FABRIC, format, indent, detail); + switch (format) { + case FORMAT_TEXT: + printf("%*s%u Connected FIs in Fabric%s\n", indent, "", (unsigned)QListCount(&g_Fabric.AllFIs), detail?":":""); + break; + case FORMAT_XML: + printf("%*s\n", indent, ""); + indent+=4; + XmlPrintDec("ConnectedFICount", (unsigned)QListCount(&g_Fabric.AllFIs), indent); + break; + default: + break; + } + count = 0; + for (p=QListHead(&g_Fabric.AllFIs); p != NULL; p = QListNext(&g_Fabric.AllFIs, p)) { + NodeData *nodep = (NodeData *)QListObj(p); + if (! CompareNodePoint(nodep, focus)) + continue; + if (detail) { + if (! count) + ShowNodeBriefSummaryHeadings(format, indent, detail-1); + if (report == REPORT_TOPOLOGY) + ShowTopologyNodeBriefSummary(nodep, focus, indent, detail-1); + else + ShowNodeBriefSummary(nodep, focus, TRUE, format, indent, detail-1); + } + count++; + } + switch (format) { + case FORMAT_TEXT: + if (PointValid(focus)) + printf("%*s%u Matching FI Found\n", indent, "", count); + if (detail) + printf("\n"); + break; + case FORMAT_XML: + if (PointValid(focus)) + XmlPrintDec("MatchingFIs", count, indent); + indent-=4; + printf("%*s\n", indent, ""); + break; + default: + break; + } + + switch (format) { + case FORMAT_TEXT: + printf("%*s%u Connected Switches in Fabric%s\n", indent, "", (unsigned)QListCount(&g_Fabric.AllSWs), detail?":":""); + break; + case FORMAT_XML: + printf("%*s\n", indent, ""); + indent+=4; + XmlPrintDec("ConnectedSwitchCount", (unsigned)QListCount(&g_Fabric.AllSWs), indent); + break; + default: + break; + } + count = 0; + for (p=QListHead(&g_Fabric.AllSWs); p != NULL; p = QListNext(&g_Fabric.AllSWs, p)) { + NodeData *nodep = (NodeData *)QListObj(p); + if (! CompareNodePoint(nodep, focus)) + continue; + if (detail) { + if (! count) + ShowNodeBriefSummaryHeadings(format, indent, detail-1); + if (report == REPORT_TOPOLOGY) + ShowTopologyNodeBriefSummary(nodep, focus, indent, detail-1); + else + ShowNodeBriefSummary(nodep, focus, TRUE, format, indent, detail-1); + } + count++; + } + switch (format) { + case FORMAT_TEXT: + if (PointValid(focus)) + printf("%*s%u Matching Switches Found\n", indent, "", count); + if (detail) + printf("\n"); + break; + case FORMAT_XML: + if (PointValid(focus)) + XmlPrintDec("MatchingSwitches", count, indent); + indent-=4; + printf("%*s\n", indent, ""); + break; + default: + break; + } + + ShowAllSMBriefSummary(focus, format, indent, detail); + switch (format) { + case FORMAT_TEXT: + DisplaySeparator(); + break; + case FORMAT_XML: + indent-=4; + printf("%*s\n", indent, ""); + break; + default: + break; + } +} + +static _inline +boolean PortCounterBelowThreshold(uint32 value, uint32 threshold) +{ + return (threshold && value < threshold); +} + +static _inline +boolean PortCounterExceedsThreshold(uint32 value, uint32 threshold) +{ + return (threshold && value > threshold - g_threshold_compare); +} + +static _inline +boolean PortCounterExceedsThreshold64(uint64 value, uint64 threshold) +{ + return (threshold && value > threshold - g_threshold_compare); +} + +// check the last port counters against the new vs threshold +// returns: TRUE - one or more counters exceed threshold +// FALSE - all counters below threshold +static boolean PortCountersExceedThreshold(PortData *portp) +{ + STL_PORT_COUNTERS_DATA *pPortCounters = portp->pPortCounters; + + if (! pPortCounters) + return FALSE; + +#define EXCEEDS_THRESHOLD(field) \ + PortCounterExceedsThreshold(pPortCounters->field, g_Thresholds.field) +#define EXCEEDS_THRESHOLD64(field) \ + PortCounterExceedsThreshold64(pPortCounters->field, g_Thresholds.field) +#define BELOW_THRESHOLD_LQI(field) \ + PortCounterBelowThreshold(pPortCounters->lq.s.field, g_Thresholds.lq.s.field) +#define EXCEEDS_THRESHOLD_NLD(field) \ + PortCounterExceedsThreshold(pPortCounters->lq.s.field, g_Thresholds.lq.s.field) + + // Data movement + return EXCEEDS_THRESHOLD64(portXmitData) + || EXCEEDS_THRESHOLD64(portRcvData) + || EXCEEDS_THRESHOLD64(portXmitPkts) + || EXCEEDS_THRESHOLD64(portRcvPkts) + || EXCEEDS_THRESHOLD64(portMulticastXmitPkts) + || EXCEEDS_THRESHOLD64(portMulticastRcvPkts) + // Signal Integrity and Node/Link Stability + || BELOW_THRESHOLD_LQI(linkQualityIndicator) + || EXCEEDS_THRESHOLD(uncorrectableErrors) + || EXCEEDS_THRESHOLD(linkDowned) + || EXCEEDS_THRESHOLD64(portRcvErrors) + || EXCEEDS_THRESHOLD64(fmConfigErrors) + || EXCEEDS_THRESHOLD64(excessiveBufferOverruns) + || EXCEEDS_THRESHOLD(linkErrorRecovery) + || EXCEEDS_THRESHOLD64(localLinkIntegrityErrors) + || EXCEEDS_THRESHOLD64(portRcvRemotePhysicalErrors) + || EXCEEDS_THRESHOLD_NLD(numLanesDown) + // Security + || EXCEEDS_THRESHOLD64(portXmitConstraintErrors) + || EXCEEDS_THRESHOLD64(portRcvConstraintErrors) + // Routing or Down nodes still being sent to + || EXCEEDS_THRESHOLD64(portRcvSwitchRelayErrors) + || EXCEEDS_THRESHOLD64(portXmitDiscards) + // Congestion + || EXCEEDS_THRESHOLD64(swPortCongestion) + || EXCEEDS_THRESHOLD64(portRcvFECN) + || EXCEEDS_THRESHOLD64(portRcvBECN) + || EXCEEDS_THRESHOLD64(portMarkFECN) + || EXCEEDS_THRESHOLD64(portXmitTimeCong) + || EXCEEDS_THRESHOLD64(portXmitWait) + // Bubbles + || EXCEEDS_THRESHOLD64(portXmitWastedBW) + || EXCEEDS_THRESHOLD64(portXmitWaitData) + || EXCEEDS_THRESHOLD64(portRcvBubble); +#undef EXCEEDS_THRESHOLD +#undef EXCEEDS_THRESHOLD64 +#undef BELOW_THRESHOLD_LQI +#undef EXCEEDS_THRESHOLD_NLD +} + +void ShowPortCounterBelowThreshold(const char* field, uint32 value, uint32 threshold, Format_t format, int indent, int detail) +{ + if (PortCounterBelowThreshold(value, threshold)) + { + switch (format) { + case FORMAT_TEXT: + printf("%*s%s: %u Below Threshold: %u\n", + indent, "", field, value, threshold); + break; + case FORMAT_XML: + // old format + printf("%*s<%s>\n", indent, "", field); + XmlPrintDec("Value", value, indent+4); + XmlPrintDec("LowerThreshold", threshold, indent+4); + printf("%*s\n", indent, "", field); + // new format + printf("%*s<%sValue>%u\n", indent, "", field, value, field); + printf("%*s<%sThreshold>%u\n", indent, "", field, threshold, field); + break; + default: + break; + } + } +} + +void ShowPortCounterExceedingThreshold(const char* field, uint32 value, uint32 threshold, Format_t format, int indent, int detail) +{ + if (PortCounterExceedsThreshold(value, threshold)) + { + switch (format) { + case FORMAT_TEXT: + printf("%*s%s: %u Exceeds Threshold: %u\n", + indent, "", field, value, threshold); + break; + case FORMAT_XML: + // old format + printf("%*s<%s>\n", indent, "", field); + XmlPrintDec("Value", value, indent+4); + XmlPrintDec("Threshold", threshold, indent+4); + printf("%*s\n", indent, "", field); + // new format + printf("%*s<%sValue>%u\n", indent, "", field, value, field); + printf("%*s<%sThreshold>%u\n", indent, "", field, threshold, field); + break; + default: + break; + } + } +} + +void ShowPortCounterExceedingThreshold64(const char* field, uint64 value, uint64 threshold, Format_t format, int indent, int detail) +{ + if (PortCounterExceedsThreshold64(value, threshold)) + { + switch (format) { + case FORMAT_TEXT: + printf("%*s%s: %"PRIu64" Exceeds Threshold: %"PRIu64"\n", + indent, "", field, value, threshold); + break; + case FORMAT_XML: + // old format + printf("%*s<%s>\n", indent, "", field); + XmlPrintDec64("Value", value, indent+4); + XmlPrintDec64("Threshold", threshold, indent+4); + printf("%*s\n", indent, "", field); + // new format + printf("%*s<%sValue>%"PRIu64"\n", indent, "", field, value, field); + printf("%*s<%sThreshold>%"PRIu64"\n", indent, "", field, threshold, field); + break; + default: + break; + } + } +} + +void ShowPortCounterExceedingMbThreshold64(const char* field, uint64 value, uint64 threshold, Format_t format, int indent, int detail) +{ + if (PortCounterExceedsThreshold(value, threshold)) + { + switch (format) { + case FORMAT_TEXT: + printf("%*s%s: %"PRIu64" MB Exceeds Threshold: %u MB\n", + indent, "", field, value/FLITS_PER_MB, (unsigned int)(threshold/FLITS_PER_MB)); + break; + case FORMAT_XML: + // old format + printf("%*s<%s>\n", indent, "", field); + XmlPrintDec64("ValueMB", value/FLITS_PER_MB, indent+4); + XmlPrintDec64("ThresholdMB", threshold/FLITS_PER_MB, indent+4); + printf("%*s\n", indent, "", field); + // new format + printf("%*s<%sValueMB>%"PRIu64"\n", indent, "", field, value/FLITS_PER_MB, field); + printf("%*s<%sThresholdMB>%u\n", indent, "", field, (unsigned int)(threshold/FLITS_PER_MB), field); + break; + default: + break; + } + } +} + +void ShowLinkPortErrorSummary(PortData *portp, Format_t format, int indent, int detail) +{ + STL_PORT_COUNTERS_DATA *pPortCounters = portp->pPortCounters; + + if (! pPortCounters) + return; + +#define SHOW_BELOW_LQI_THRESHOLD(field, name) \ + ShowPortCounterBelowThreshold(#name, pPortCounters->lq.s.field, g_Thresholds.lq.s.field, format, indent, detail) +#define SHOW_EXCEEDING_THRESHOLD(field, name) \ + ShowPortCounterExceedingThreshold(#name, pPortCounters->field, g_Thresholds.field, format, indent, detail) +#define SHOW_EXCEEDING_THRESHOLD64(field, name) \ + ShowPortCounterExceedingThreshold64(#name, pPortCounters->field, g_Thresholds.field, format, indent, detail) +#define SHOW_EXCEEDING_MB_THRESHOLD(field, name) \ + ShowPortCounterExceedingMbThreshold64(#name, pPortCounters->field, g_Thresholds.field, format, indent, detail) +#define SHOW_EXCEEDING_NLD_THRESHOLD(field, name) \ + ShowPortCounterExceedingThreshold(#name, pPortCounters->lq.s.field, g_Thresholds.lq.s.field, format, indent, detail) + // Data movement + SHOW_EXCEEDING_MB_THRESHOLD(portXmitData, XmitData); + SHOW_EXCEEDING_MB_THRESHOLD(portRcvData, RcvData); + SHOW_EXCEEDING_THRESHOLD64(portXmitPkts, XmitPkts); + SHOW_EXCEEDING_THRESHOLD64(portRcvPkts, RcvPkts); + SHOW_EXCEEDING_THRESHOLD64(portMulticastXmitPkts, MulticastXmitPkts); + SHOW_EXCEEDING_THRESHOLD64(portMulticastRcvPkts, MulticastRcvPkts); + // Signal Integrity and Node/Link Stability + SHOW_BELOW_LQI_THRESHOLD(linkQualityIndicator, LinkQualityIndicator); + SHOW_EXCEEDING_THRESHOLD(linkDowned, LinkDowned); + SHOW_EXCEEDING_THRESHOLD(uncorrectableErrors, UncorrectableErrors); + SHOW_EXCEEDING_THRESHOLD64(fmConfigErrors, FMConfigErrors); + SHOW_EXCEEDING_THRESHOLD64(portRcvErrors, RcvErrors); + SHOW_EXCEEDING_THRESHOLD64(excessiveBufferOverruns, ExcessiveBufferOverruns); + SHOW_EXCEEDING_THRESHOLD(linkErrorRecovery, LinkErrorRecovery); + SHOW_EXCEEDING_THRESHOLD64(localLinkIntegrityErrors, LocalLinkIntegrityErrors); + SHOW_EXCEEDING_THRESHOLD64(portRcvRemotePhysicalErrors, RcvRemotePhysicalErrors); + SHOW_EXCEEDING_NLD_THRESHOLD(numLanesDown, NumLanesDown); + // Security + SHOW_EXCEEDING_THRESHOLD64(portXmitConstraintErrors, XmitConstraintErrors); + SHOW_EXCEEDING_THRESHOLD64(portRcvConstraintErrors, RcvConstraintErrors); + // Routing or Down nodes still being sent to + SHOW_EXCEEDING_THRESHOLD64(portRcvSwitchRelayErrors, RcvSwitchRelayErrors); + SHOW_EXCEEDING_THRESHOLD64(portXmitDiscards, XmitDiscards); + // Congestion + SHOW_EXCEEDING_THRESHOLD64(swPortCongestion, CongDiscards); + SHOW_EXCEEDING_THRESHOLD64(portRcvFECN, RcvFECN); + SHOW_EXCEEDING_THRESHOLD64(portRcvBECN, RcvBECN); + SHOW_EXCEEDING_THRESHOLD64(portMarkFECN, MarkFECN); + SHOW_EXCEEDING_THRESHOLD64(portXmitTimeCong, XmitTimeCong); + SHOW_EXCEEDING_THRESHOLD64(portXmitWait, XmitWait); + // Bubbles + SHOW_EXCEEDING_THRESHOLD64(portXmitWastedBW, XmitWastedBW); + SHOW_EXCEEDING_THRESHOLD64(portXmitWaitData, XmitWaitData); + SHOW_EXCEEDING_THRESHOLD64(portRcvBubble, RcvBubble); +#undef SHOW_BELOW_LQI_THRESHOLD +#undef SHOW_EXCEEDING_THRESHOLD +#undef SHOW_EXCEEDING_THRESHOLD64 +#undef SHOW_EXCEEDING_MB_THRESHOLD +#undef SHOW_EXCEEDING_NLD_THRESHOLD +} + +// returns TRUE if thresholds are configured +boolean ShowThresholds(Format_t format, int indent, int detail) +{ + boolean didoutput = FALSE; + switch (format) { + case FORMAT_TEXT: + printf("%*sConfigured Thresholds:\n",indent, ""); + break; + case FORMAT_XML: + printf("%*s\n",indent, ""); + break; + default: + break; + } +#define SHOW_THRESHOLD(field, name) \ + do { if (g_Thresholds.field) { switch (format) { \ + case FORMAT_TEXT: printf("%*s%-30s %lu\n", indent+4, "", #name, (uint64)g_Thresholds.field); break; \ + case FORMAT_XML: printf("%*s<%s>%lu\n", indent+4, "", #name, (uint64)g_Thresholds.field, #name); break; \ + default: break; } didoutput = TRUE; } } while (0) + +#define SHOW_THRESHOLD_LQI_NLD(field, name) \ + do { if (g_Thresholds.lq.s.field) { switch (format) { \ + case FORMAT_TEXT: printf("%*s%-30s %lu\n", indent+4, "", #name, (uint64)g_Thresholds.lq.s.field); break; \ + case FORMAT_XML: printf("%*s<%s>%lu\n", indent+4, "", #name, (uint64)g_Thresholds.lq.s.field, #name); break; \ + default: break; } didoutput = TRUE; } } while (0) + +#define SHOW_MB_THRESHOLD(field, name) \ + do { if (g_Thresholds.field) { switch (format) { \ + case FORMAT_TEXT: printf("%*s%-30s %lu MB\n", indent+4, "", #name, (uint64)g_Thresholds.field/FLITS_PER_MB); break; \ + case FORMAT_XML: printf("%*s<%sMB>%lu\n", indent+4, "", #name, (uint64)g_Thresholds.field/FLITS_PER_MB, #name); break; \ + default: break; } didoutput = TRUE; } } while (0) + + // Data movement + SHOW_MB_THRESHOLD(portXmitData, XmitData); + SHOW_MB_THRESHOLD(portRcvData, RcvData); + SHOW_THRESHOLD(portXmitPkts, XmitPkts); + SHOW_THRESHOLD(portRcvPkts, RcvPkts); + SHOW_THRESHOLD(portMulticastXmitPkts, MulticastXmitPkts); + SHOW_THRESHOLD(portMulticastRcvPkts, MulticastRcvPkts); + + // Signal Integrity and Node/Link Stability + SHOW_THRESHOLD_LQI_NLD(linkQualityIndicator, LinkQualityIndicator); + SHOW_THRESHOLD(uncorrectableErrors, UncorrectableErrors); + SHOW_THRESHOLD(linkDowned, LinkDowned); + SHOW_THRESHOLD(portRcvErrors, RcvErrors); + SHOW_THRESHOLD(excessiveBufferOverruns, ExcessiveBufferOverruns); + SHOW_THRESHOLD(fmConfigErrors, FMConfigErrors); + SHOW_THRESHOLD(linkErrorRecovery, LinkErrorRecovery); + SHOW_THRESHOLD(localLinkIntegrityErrors, LocalLinkIntegrityErrors); + SHOW_THRESHOLD(portRcvRemotePhysicalErrors, RcvRemotePhysicalErrors); + SHOW_THRESHOLD_LQI_NLD(numLanesDown, NumLanesDown); + + // Security + SHOW_THRESHOLD(portXmitConstraintErrors, XmitConstraintErrors); + SHOW_THRESHOLD(portRcvConstraintErrors, RcvConstraintErrors); + + // Routing or Down nodes still being sent to + SHOW_THRESHOLD(portRcvSwitchRelayErrors, RcvSwitchRelayErrors); + SHOW_THRESHOLD(portXmitDiscards, XmitDiscards); + + // Congestion + SHOW_THRESHOLD(swPortCongestion, CongDiscards); + SHOW_THRESHOLD(portRcvFECN, RcvFECN); + SHOW_THRESHOLD(portRcvBECN, RcvBECN); + SHOW_THRESHOLD(portMarkFECN, MarkFECN); + SHOW_THRESHOLD(portXmitTimeCong, XmitTimeCong); + SHOW_THRESHOLD(portXmitWait, XmitWait); + + // Bubbles + SHOW_THRESHOLD(portXmitWastedBW, XmitWastedBW); + SHOW_THRESHOLD(portXmitWaitData, XmitWaitData); + SHOW_THRESHOLD(portRcvBubble, RcvBubble); + + switch (format) { + case FORMAT_TEXT: + if (! didoutput) + printf("%*sNone\n", indent+4, ""); + break; + case FORMAT_XML: + printf("%*s\n",indent, ""); + break; + default: + break; + } + +#undef SHOW_THRESHOLD +#undef SHOW_MB_THRESHOLD +#undef SHOW_THRESHOLD_LQI_NLD + return didoutput; +} + +// returns TRUE if thresholds are configured for any counters +boolean NeedClearCounters(void) +{ + boolean needclear = FALSE; + +#define CHECK_COUNTER(field) \ + do { needclear |= (0 != g_CounterSelectMask.CounterSelectMask.s.field); } while(0) + + // Data movement + CHECK_COUNTER(PortXmitData); + CHECK_COUNTER(PortRcvData); + CHECK_COUNTER(PortXmitPkts); + CHECK_COUNTER(PortRcvPkts); + CHECK_COUNTER(PortMulticastXmitPkts); + CHECK_COUNTER(PortMulticastRcvPkts); + + // Signal Integrity and Node/Link Stability + // LinkQualityIndicator N/A since readonly can't clear + CHECK_COUNTER(UncorrectableErrors); + CHECK_COUNTER(LinkDowned); + CHECK_COUNTER(PortRcvErrors); + CHECK_COUNTER(ExcessiveBufferOverruns); + CHECK_COUNTER(FMConfigErrors); + CHECK_COUNTER(LinkErrorRecovery); + CHECK_COUNTER(LocalLinkIntegrityErrors); + CHECK_COUNTER(PortRcvRemotePhysicalErrors); + + // Security + CHECK_COUNTER(PortXmitConstraintErrors); + CHECK_COUNTER(PortRcvConstraintErrors); + + // Routing or Down nodes still being sent to + CHECK_COUNTER(PortRcvSwitchRelayErrors); + CHECK_COUNTER(PortXmitDiscards); + + // Congestion + CHECK_COUNTER(SwPortCongestion); + CHECK_COUNTER(PortRcvFECN); + CHECK_COUNTER(PortRcvBECN); + CHECK_COUNTER(PortMarkFECN); + CHECK_COUNTER(PortXmitTimeCong); + CHECK_COUNTER(PortXmitWait); + + // Bubbles + CHECK_COUNTER(PortXmitWastedBW); + CHECK_COUNTER(PortXmitWaitData); + CHECK_COUNTER(PortRcvBubble); +#undef CHECK_COUNTER + + return needclear; +} + +// returns TRUE if thresholds are configured or clearall +boolean ShowClearedCounters(Format_t format, int indent, int detail, boolean clearall) +{ + boolean didoutput = FALSE; + + switch (format) { + case FORMAT_TEXT: + printf("%*sConfigured Counters to Clear:\n",indent, ""); + break; + case FORMAT_XML: + printf("%*s\n",indent, ""); + break; + default: + break; + } +#define SHOW_COUNTER(field, name) \ + do { if (clearall || g_CounterSelectMask.CounterSelectMask.s.field) { switch (format) { case FORMAT_TEXT: printf("%*s%-30s\n", indent+4, "", #name); break; case FORMAT_XML: printf("%*s<%s>\n", indent+4, "", #name, #name); break; default: break; } didoutput = TRUE; } } while (0) + + // Data movement + SHOW_COUNTER(PortXmitData, XmitData); + SHOW_COUNTER(PortRcvData, RcvData); + SHOW_COUNTER(PortXmitPkts, XmitPkts); + SHOW_COUNTER(PortRcvPkts, RcvPkts); + SHOW_COUNTER(PortMulticastXmitPkts, MulticastXmitPkts); + SHOW_COUNTER(PortMulticastRcvPkts, MulticastRcvPkts); + // Signal Integrity and Node/Link Stability + // LinkQualityIndicator N/A since readonly can't clear + SHOW_COUNTER(UncorrectableErrors, UncorrectableErrors); + SHOW_COUNTER(LinkDowned, LinkDowned); + SHOW_COUNTER(PortRcvErrors, RcvErrors); + SHOW_COUNTER(ExcessiveBufferOverruns, ExcessiveBufferOverruns); + SHOW_COUNTER(FMConfigErrors, FMConfigErrors); + SHOW_COUNTER(LinkErrorRecovery, LinkErrorRecovery); + SHOW_COUNTER(LocalLinkIntegrityErrors, LocalLinkIntegrityErrors); + SHOW_COUNTER(PortRcvRemotePhysicalErrors, RcvRemotePhysicalErrors); + // Security + SHOW_COUNTER(PortXmitConstraintErrors, XmitConstraintErrors); + SHOW_COUNTER(PortRcvConstraintErrors, RcvConstraintErrors); + // Routing or Down nodes still being sent to + SHOW_COUNTER(PortRcvSwitchRelayErrors, RcvSwitchRelayErrors); + SHOW_COUNTER(PortXmitDiscards, XmitDiscards); + // Congestion + SHOW_COUNTER(SwPortCongestion, CongDiscards); + SHOW_COUNTER(PortRcvFECN, RcvFECN); + SHOW_COUNTER(PortRcvBECN, RcvBECN); + SHOW_COUNTER(PortMarkFECN, MarkFECN); + SHOW_COUNTER(PortXmitTimeCong, XmitTimeCong); + SHOW_COUNTER(PortXmitWait, XmitWait); + // Bubbles + SHOW_COUNTER(PortXmitWastedBW, XmitWastedBW); + SHOW_COUNTER(PortXmitWaitData, XmitWaitData); + SHOW_COUNTER(PortRcvBubble, RcvBubble); + + switch (format) { + case FORMAT_TEXT: + if (! didoutput) + printf("%*sNone\n", indent+4, ""); + break; + case FORMAT_XML: + printf("%*s\n",indent, ""); + break; + default: + break; + } + +#undef SHOW_COUNTER + return didoutput; +} + +void ShowSlowLinkPortSummaryHeader(LinkReport_t report, Format_t format, int indent, int detail) +{ + ShowLinkBriefSummaryHeader(format, indent, detail); + if (detail) { + switch (format) { + case FORMAT_TEXT: + switch (report) { + case LINK_EXPECTED_REPORT: + printf("%*s Active Enabled\n", indent+4, ""); + printf("%*s Lanes, Used(Tx), Used(Rx), Rate, Lanes, DownTo, Rates\n", indent+4, ""); + break; + case LINK_CONFIG_REPORT: + printf("%*s Enabled Supported\n", indent+4, ""); + printf("%*s Lanes, Used, Rate, Lanes, DownTo, Rates\n", indent+4, ""); + break; + case LINK_CONN_REPORT: + printf("%*s Supported\n", indent+4, ""); + printf("%*s Lanes, DownTo, Rate\n", indent+4, ""); + break; + } + DisplaySeparator(); + break; + case FORMAT_XML: + break; + default: + break; + } + } +} + +void ShowSlowLinkReasonSummary(LinkReport_t report, PortData *portp, Format_t format, int indent, int detail) +{ + char buf1[SHOW_BUF_SIZE], buf2[SHOW_BUF_SIZE], buf3[SHOW_BUF_SIZE], buf4[SHOW_BUF_SIZE]; + char buf5[SHOW_BUF_SIZE], buf6[SHOW_BUF_SIZE], buf7[SHOW_BUF_SIZE]; + + switch (format) { + case FORMAT_TEXT: + switch (report) { + case LINK_EXPECTED_REPORT: + printf("%*s %-6s %-9s %-9s %-8s %-9s %-8s %-12s\n", indent, "", + StlLinkWidthToText(portp->PortInfo.LinkWidth.Active, buf1, sizeof(buf1)), + StlLinkWidthToText(portp->PortInfo.LinkWidthDowngrade.TxActive, buf5, sizeof(buf5)), + StlLinkWidthToText(portp->PortInfo.LinkWidthDowngrade.RxActive, buf7, sizeof(buf7)), + StlLinkSpeedToText(portp->PortInfo.LinkSpeed.Active, buf2, sizeof(buf2)), + StlLinkWidthToText(portp->PortInfo.LinkWidth.Enabled, buf3, sizeof(buf3)), + StlLinkWidthToText(portp->PortInfo.LinkWidthDowngrade.Enabled, buf6, sizeof(buf6)), + StlLinkSpeedToText(portp->PortInfo.LinkSpeed.Enabled, buf4, sizeof(buf4))); + break; + case LINK_CONFIG_REPORT: + printf("%*s %-8s %-7s %-13s %-9s %-8s %-12s\n", indent, "", + StlLinkWidthToText(portp->PortInfo.LinkWidth.Enabled, buf1, sizeof(buf1)), + StlLinkWidthToText(portp->PortInfo.LinkWidthDowngrade.Enabled, buf5, sizeof(buf5)), + StlLinkSpeedToText(portp->PortInfo.LinkSpeed.Enabled, buf2, sizeof(buf2)), + StlLinkWidthToText(portp->PortInfo.LinkWidth.Supported, buf3, sizeof(buf3)), + StlLinkWidthToText(portp->PortInfo.LinkWidthDowngrade.Supported, buf6, sizeof(buf6)), + StlLinkSpeedToText(portp->PortInfo.LinkSpeed.Supported, buf4, sizeof(buf4))); + break; + case LINK_CONN_REPORT: + printf("%*s %-12s %-12s %-12s\n", indent, "", + StlLinkWidthToText(portp->PortInfo.LinkWidth.Supported, buf1, sizeof(buf1)), + StlLinkWidthToText(portp->PortInfo.LinkWidthDowngrade.Supported, buf5, sizeof(buf5)), + StlLinkSpeedToText(portp->PortInfo.LinkSpeed.Supported, buf2, sizeof(buf2))); + break; + } + break; + case FORMAT_XML: + switch (report) { + case LINK_EXPECTED_REPORT: + XmlPrintLinkWidth("LinkWidthActive", + portp->PortInfo.LinkWidth.Active, indent); + XmlPrintLinkWidth("LinkWidthDnGradeTxActive", + portp->PortInfo.LinkWidthDowngrade.TxActive, indent); + XmlPrintLinkWidth("LinkWidthDnGradeRxActive", + portp->PortInfo.LinkWidthDowngrade.RxActive, indent); + XmlPrintLinkSpeed("LinkSpeedActive", + portp->PortInfo.LinkSpeed.Active, indent); + XmlPrintLinkWidth("LinkWidthEnabled", + portp->PortInfo.LinkWidth.Enabled, indent); + XmlPrintLinkWidth("LinkWidthDnGradeEnabled", + portp->PortInfo.LinkWidthDowngrade.Enabled, indent); + XmlPrintLinkSpeed("LinkSpeedEnabled", + portp->PortInfo.LinkSpeed.Enabled, indent); + break; + case LINK_CONFIG_REPORT: + XmlPrintLinkWidth("LinkWidthEnabled", + portp->PortInfo.LinkWidth.Enabled, indent); + XmlPrintLinkWidth("LinkWidthDnGradeEnabled", + portp->PortInfo.LinkWidthDowngrade.Enabled, indent); + XmlPrintLinkSpeed("LinkSpeedEnabled", + portp->PortInfo.LinkSpeed.Enabled, indent); + XmlPrintLinkWidth("LinkWidthSupported", + portp->PortInfo.LinkWidth.Supported, indent); + XmlPrintLinkWidth("LinkWidthDnGradeSupported", + portp->PortInfo.LinkWidthDowngrade.Supported, indent); + XmlPrintLinkSpeed("LinkSpeedSupported", + portp->PortInfo.LinkSpeed.Supported, indent); + break; + case LINK_CONN_REPORT: + XmlPrintLinkWidth("LinkWidthSupported", + portp->PortInfo.LinkWidth.Supported, indent); + XmlPrintLinkWidth("LinkWidthDnGradeSupported", + portp->PortInfo.LinkWidthDowngrade.Supported, indent); + XmlPrintLinkSpeed("LinkSpeedSupported", + portp->PortInfo.LinkSpeed.Supported, indent); + break; + } + break; + default: + break; + } +} + +void ShowSlowLinkReasonSummaryCallback(uint64 context, PortData *portp, + Format_t format, int indent, int detail) +{ + ShowSlowLinkReasonSummary((LinkReport_t)context, portp, format, indent, detail); +} + +void ShowSlowLinkSummary(LinkReport_t report, PortData *portp1, Format_t format, int indent, int detail) +{ + ShowLinkFromBriefSummary(portp1, + (uint64)(uintn)report, ShowSlowLinkReasonSummaryCallback, + format, indent, detail); + ShowLinkToBriefSummary(portp1->neighbor, "<-> ", TRUE, + (uint64)(uintn)report, ShowSlowLinkReasonSummaryCallback, + format, indent, detail); +} + +void ShowLinkPortErrorSummaryCallback(uint64 context, PortData *portp, + Format_t format, int indent, int detail) +{ + ShowLinkPortErrorSummary(portp, format, indent, detail); +} + +// show link errors from portp1 to its neighbor +void ShowLinkErrorSummary(PortData *portp1, Format_t format, int indent, int detail) +{ + ShowLinkFromBriefSummary(portp1, 0, ShowLinkPortErrorSummaryCallback, format, indent, detail); + + ShowLinkToBriefSummary(portp1->neighbor, "<-> ", TRUE, 0, ShowLinkPortErrorSummaryCallback, format, indent, detail); +} + +// output summary of Links for given report +void ShowLinksReport(Point *focus, report_t report, Format_t format, int indent, int detail) +{ + LIST_ITEM *p; + uint32 count = 0; + char *xml_prefix = ""; + char *prefix = ""; + + switch (report) { + default: // should not happen, but just in case + ASSERT(0); + case REPORT_LINKS: + xml_prefix = ""; + prefix = ""; + break; + case REPORT_EXTLINKS: + xml_prefix = "Ext"; + prefix = "External "; + break; + case REPORT_FILINKS: + xml_prefix = "FI"; + prefix = "FI "; + break; + case REPORT_ISLINKS: + xml_prefix = "IS"; + prefix = "Inter-Switch "; + break; + case REPORT_EXTISLINKS: + xml_prefix = "ExtIS"; + prefix = "External Inter-Switch "; + break; + } + + switch (format) { + case FORMAT_TEXT: + printf("%*s%sLink Summary\n", indent, "", prefix); + break; + case FORMAT_XML: + printf("%*s<%sLinkSummary>\n", indent, "", xml_prefix); + indent+=4; + break; + default: + break; + } + + ShowPointFocus(focus, FIND_FLAG_FABRIC, format, indent, detail); + switch (format) { + case FORMAT_TEXT: + switch (report) { + default: // should not happen, but just in case + case REPORT_LINKS: + printf("%*s%u Links in Fabric%s\n", indent, "", g_Fabric.LinkCount, detail?":":""); break; + case REPORT_EXTLINKS: + printf("%*s%u External Links in Fabric%s\n", indent, "", g_Fabric.ExtLinkCount, detail?":":""); break; + case REPORT_FILINKS: + printf("%*s%u FI Links in Fabric%s\n", indent, "", g_Fabric.FILinkCount, detail?":":""); break; + case REPORT_ISLINKS: + printf("%*s%u Inter-Switch Links in Fabric%s\n", indent, "", g_Fabric.ISLinkCount, detail?":":""); break; + case REPORT_EXTISLINKS: + printf("%*s%u External Inter-Switch Links in Fabric%s\n", indent, "", g_Fabric.ExtISLinkCount, detail?":":""); break; + } + break; + case FORMAT_XML: + switch (report) { + default: // should not happen, but just in case + case REPORT_LINKS: + XmlPrintDec("LinkCount", g_Fabric.LinkCount, indent); break; + case REPORT_EXTLINKS: + XmlPrintDec("ExternalLinkCount", g_Fabric.ExtLinkCount, indent); break; + case REPORT_FILINKS: + XmlPrintDec("FILinkCount", g_Fabric.FILinkCount, indent); break; + case REPORT_ISLINKS: + XmlPrintDec("ISLinkCount", g_Fabric.ISLinkCount, indent); break; + case REPORT_EXTISLINKS: + XmlPrintDec("ExternalISLinkCount", g_Fabric.ExtISLinkCount, indent); break; + } + break; + default: + break; + } + + if (detail) + ShowLinkBriefSummaryHeader(format, indent, detail-1); + for (p=QListHead(&g_Fabric.AllPorts); p != NULL; p = QListNext(&g_Fabric.AllPorts, p)) { + PortData *portp1 = (PortData *)QListObj(p); + // to avoid duplicated processing, only process "from" ports in link + if (! portp1->from) + continue; + + switch (report) { + default: // should not happen, but just in case + case REPORT_LINKS: + break; // always show + case REPORT_EXTLINKS: + if (isInternalLink(portp1)) + continue; + break; + case REPORT_FILINKS: + if (! isFILink(portp1)) + continue; + break; + case REPORT_ISLINKS: + if (! isISLink(portp1)) + continue; + break; + case REPORT_EXTISLINKS: + if (isInternalLink(portp1)) + continue; + if (! isISLink(portp1)) + continue; + break; + } + + if (! ComparePortPoint(portp1, focus) && ! ComparePortPoint(portp1->neighbor, focus)) + continue; + count++; + if (detail) + ShowLinkBriefSummary(portp1, "<-> ", format, indent, detail-1); + } + + switch (format) { + case FORMAT_TEXT: + if (PointValid(focus)) + printf("%*s%u Matching Links Found\n", indent, "", count); + DisplaySeparator(); + break; + case FORMAT_XML: + if (PointValid(focus)) + XmlPrintDec("MatchingLinks", count, indent); + indent-=4; + printf("%*s\n", indent, "", xml_prefix); + break; + default: + break; + } +} + +// output summary of all slow IB Links +// detail = 0,1 -> link running < best enabled speed/width +// detail = 2 -> links running < best supported speed/width +// detail = >2 -> links running < max supported speed/width +// one_report indicates if only a single vs stacked reports +// (stacked means separate sections for each previous part of report) +void ShowSlowLinkReport(LinkReport_t report, boolean one_report, Point *focus, Format_t format, int indent, int detail) +{ + LIST_ITEM *p; + int loops; + int firstloop = 1; + int loop; + char *xmltag=""; + + switch (report) { + default: + case LINK_EXPECTED_REPORT: + loops = 1; + switch (format) { + case FORMAT_TEXT: + printf("%*sLinks running slower than expected Summary\n", indent, ""); + break; + case FORMAT_XML: + printf("%*s \n", indent, ""); + xmltag="LinksExpected"; + break; + default: + break; + } + break; + case LINK_CONFIG_REPORT: + loops = 2; + if (one_report) { + firstloop = 2; + switch (format) { + case FORMAT_TEXT: + printf("%*sLinks configured slower than supported Summary\n", indent, ""); + break; + case FORMAT_XML: + printf("%*s \n", indent, ""); + xmltag="LinksConfig"; + break; + default: + break; + } + } else { + switch (format) { + case FORMAT_TEXT: + printf("%*sLinks running slower than supported Summary\n", indent, ""); + break; + case FORMAT_XML: + printf("%*s \n", indent, ""); + xmltag="LinksRunningSupported"; + break; + default: + break; + } + } + break; + case LINK_CONN_REPORT: + loops = 3; + if (one_report) { + firstloop = 3; + switch (format) { + case FORMAT_TEXT: + printf("%*sLinks connected with mismatched supported speeds Summary\n", indent, ""); + break; + case FORMAT_XML: + printf("%*s \n", indent, ""); + xmltag="LinksMismatched"; + break; + default: + break; + } + } else { + switch (format) { + case FORMAT_TEXT: + printf("%*sLinks running slower than faster port Summary\n", indent, ""); + break; + case FORMAT_XML: + printf("%*s \n", indent, ""); + xmltag="LinksRunningSlower"; + break; + default: + break; + } + } + break; + } + if (format == FORMAT_XML) + indent+=4; + ShowPointFocus(focus, FIND_FLAG_FABRIC, format, indent, detail); + if (format == FORMAT_XML) + indent-=4; + + for (loop = firstloop; loop <= loops; ++loop) { + uint32 badcount = 0; + uint32 checked = 0; + LinkReport_t loop_report; + + switch (loop) { + case 1: + switch (format) { + case FORMAT_TEXT: + printf("%*sLinks running slower than expected:\n", indent, ""); + break; + case FORMAT_XML: + /* already output above */ + break; + default: + break; + } + loop_report = LINK_EXPECTED_REPORT; + break; + case 2: + switch (format) { + case FORMAT_TEXT: + printf("%*sLinks configured to run slower than supported:\n", indent, ""); + break; + case FORMAT_XML: + if (loop != firstloop) { + printf("\n", xmltag); + printf("%*s \n", indent, ""); + xmltag="LinksConfig"; + } + break; + default: + break; + } + loop_report = LINK_CONFIG_REPORT; + if (g_hard) { + switch (format) { + case FORMAT_TEXT: + printf("%*sReport skipped: -H option specified\n", indent, ""); + break; + case FORMAT_XML: + printf("%*s\n", indent, ""); + break; + default: + break; + } + continue; + } + break; + case 3: + switch (format) { + case FORMAT_TEXT: + printf("%*sLinks connected with mismatched speed potential:\n", indent, ""); + break; + case FORMAT_XML: + if (loop != firstloop) { + printf("\n", xmltag); + printf("%*s \n", indent, ""); + xmltag="LinksMismatched"; + } + break; + default: + break; + } + loop_report = LINK_CONN_REPORT; + break; + default: + ASSERT(0); + continue; + break; + } + if (format == FORMAT_XML) + indent+=4; + for (p=QListHead(&g_Fabric.AllPorts); p != NULL; p = QListNext(&g_Fabric.AllPorts, p)) { + PortData *portp1, *portp2; + STL_PORT_INFO *pi1, *pi2; + + portp1 = (PortData *)QListObj(p); + // to avoid duplicated processing, only process "from" ports in link + if (! portp1->from) + continue; + portp2 = portp1->neighbor; + if (! ComparePortPoint(portp1, focus) && ! ComparePortPoint(portp2, focus)) + continue; + checked++; + pi1 = &portp1->PortInfo; + pi2 = &portp2->PortInfo; + + // If the data is invalid, declare the test failed + if ( /* Active speed, width, widthDowngrade should all be a single bit value */ + /* - else is invalid data */ + (pi1->LinkSpeed.Active != StlBestLinkSpeed(pi1->LinkSpeed.Active)) || + (pi2->LinkSpeed.Active != StlBestLinkSpeed(pi2->LinkSpeed.Active)) || + (pi1->LinkWidth.Active != StlBestLinkWidth(pi1->LinkWidth.Active)) || + (pi2->LinkWidth.Active != StlBestLinkWidth(pi2->LinkWidth.Active)) || + (pi1->LinkWidthDowngrade.TxActive != StlBestLinkWidth(pi1->LinkWidthDowngrade.TxActive)) || + (pi2->LinkWidthDowngrade.TxActive != StlBestLinkWidth(pi2->LinkWidthDowngrade.TxActive)) || + (pi1->LinkWidthDowngrade.RxActive != StlBestLinkWidth(pi1->LinkWidthDowngrade.RxActive)) || + (pi2->LinkWidthDowngrade.RxActive != StlBestLinkWidth(pi2->LinkWidthDowngrade.RxActive)) ) { + printf(" The speed, width, or widthdowngrade value retrieved is not valid. \n"); + goto show; + } + + // Links running slower than expected (not at highest supported speed that is enabled) + if (firstloop <= 1) { + if ( + /* Active speed should match highest speed enabled on both ports */ + (pi1->LinkSpeed.Active == StlExpectedLinkSpeed( + pi1->LinkSpeed.Enabled, pi2->LinkSpeed.Enabled)) && + (pi2->LinkSpeed.Active == StlExpectedLinkSpeed( + pi1->LinkSpeed.Enabled, pi2->LinkSpeed.Enabled)) && + + /* Actual width (the downgrade width) should match highest width enabled on both ports */ + (pi1->LinkWidthDowngrade.TxActive == StlExpectedLinkWidth( + pi1->LinkWidthDowngrade.Enabled, pi2->LinkWidthDowngrade.Enabled)) && + (pi2->LinkWidthDowngrade.TxActive == StlExpectedLinkWidth( + pi1->LinkWidthDowngrade.Enabled, pi2->LinkWidthDowngrade.Enabled)) && + (pi1->LinkWidthDowngrade.RxActive == StlExpectedLinkWidth( + pi1->LinkWidthDowngrade.Enabled, pi2->LinkWidthDowngrade.Enabled)) && + (pi2->LinkWidthDowngrade.RxActive == StlExpectedLinkWidth( + pi1->LinkWidthDowngrade.Enabled, pi2->LinkWidthDowngrade.Enabled)) && + /* Active width should match highest width enabled on both ports */ + (pi1->LinkWidth.Active == StlExpectedLinkWidth( + pi1->LinkWidth.Enabled, pi2->LinkWidth.Enabled)) && + (pi2->LinkWidth.Active == StlExpectedLinkWidth( + pi1->LinkWidth.Enabled, pi2->LinkWidth.Enabled)) && + + /* And then finally, Actual width (the downgrade width) should match the active width */ + (pi1->LinkWidthDowngrade.TxActive == pi1->LinkWidth.Active) && + (pi2->LinkWidthDowngrade.TxActive == pi2->LinkWidth.Active) && + (pi1->LinkWidthDowngrade.RxActive == pi1->LinkWidth.Active) && + (pi2->LinkWidthDowngrade.RxActive == pi2->LinkWidth.Active) ) { + /* active matches the best enabled, cable is good */ + if (loop == 1) + continue; + } else { + /* bad cable, active doesn't match best enabled */ + if (loop > 1) + continue; /* already reported on loop 1 */ + else + goto show; + } + } + + // links configured to run slower than expected (not configured to highest speed supported) + if (firstloop <= 2) { + if ( + /* The highest supported speed should be what is configured as enabled */ + (StlBestLinkSpeed(pi1->LinkSpeed.Enabled) == StlExpectedLinkSpeed( + pi1->LinkSpeed.Supported, pi2->LinkSpeed.Supported)) && + (StlBestLinkSpeed(pi2->LinkSpeed.Enabled) == StlExpectedLinkSpeed( + pi1->LinkSpeed.Supported, pi2->LinkSpeed.Supported)) && + + /* The highest supported widthdowngrade should be what is configured as enabled */ + (StlBestLinkWidth(pi1->LinkWidthDowngrade.Enabled) == StlExpectedLinkWidth( + pi1->LinkWidthDowngrade.Supported, pi2->LinkWidthDowngrade.Supported)) && + (StlBestLinkWidth(pi2->LinkWidthDowngrade.Enabled) == StlExpectedLinkWidth( + pi1->LinkWidthDowngrade.Supported, pi2->LinkWidthDowngrade.Supported)) && + + /* The highest supported width should be what is configured as enabled */ + (StlBestLinkWidth(pi1->LinkWidth.Enabled) == StlExpectedLinkWidth( + pi1->LinkWidth.Supported, pi2->LinkWidth.Supported)) && + (StlBestLinkWidth(pi2->LinkWidth.Enabled) == StlExpectedLinkWidth( + pi1->LinkWidth.Supported, pi2->LinkWidth.Supported)) ) { + + /* configured matches the best supported, config is good */ + if (loop == 2) + continue; + } else { + /* bad config, active doesn't match best supported */ + if (loop > 2) + continue; /* already reported on loop 2 */ + else + goto show; + } + } + + // Link connected with mismatched speed potential (bi-directional link not symetric) + if (firstloop <= 3) { + if ( + /* Bidirectional speed and width should match */ + (StlBestLinkSpeed(pi1->LinkSpeed.Supported) == StlBestLinkSpeed(pi2->LinkSpeed.Supported)) && + (StlBestLinkWidth(pi1->LinkWidthDowngrade.Supported) == StlBestLinkWidth(pi2->LinkWidthDowngrade.Supported)) && + (StlBestLinkWidth(pi1->LinkWidth.Supported) == StlBestLinkWidth(pi2->LinkWidth.Supported)) ) { + + /* match, connection choice is good */ + if (loop == 3) + continue; + } else { + /* bad config, active doesn't match best supported */ + if (loop > 3) + continue; /* already reported on loop 3 */ + else + goto show; + } + } + + /* bad connection choice, active doesn't match best supported */ +show: + if (detail) { + if (! badcount) + ShowSlowLinkPortSummaryHeader(loop_report, format, indent, detail-1); + ShowSlowLinkSummary(loop_report, portp1, format, indent, detail-1); + } + badcount++; + } + switch (format) { + case FORMAT_TEXT: + printf("%*s%u of %u Links Checked, %u Errors found\n", indent, "", + checked, g_Fabric.LinkCount, badcount); + break; + case FORMAT_XML: + XmlPrintDec("LinksChecked", checked, indent); + XmlPrintDec("TotalLinks", g_Fabric.LinkCount, indent); + XmlPrintDec("LinksWithErrors", badcount, indent); + break; + default: + break; + } + if (format == FORMAT_XML) + indent-=4; + } + switch (format) { + case FORMAT_TEXT: + DisplaySeparator(); + break; + case FORMAT_XML: + printf("\n", xmltag); + break; + default: + break; + } +} + +void ShowLinkInfoReport(Point *focus, Format_t format, int indent, int detail) +{ + cl_map_item_t *p; + PortData *portp1, *portp2; + NodeData *nodep; + LIST_ITEM *q; + + printf("%*sLinkInfo Summary\n", indent, ""); + ShowPointFocus(focus, FIND_FLAG_FABRIC, format, indent, detail); + printf( "%*s%u Links in Fabric%s\n", indent, "",g_Fabric.LinkCount, detail?":":"" ); + if (detail) { + printf("%*s NodeGUID Type LID LMC Name \n", indent, ""); + printf("%*sEgress LinkSpeed Type NodeGUID Port LID Name \n", indent, ""); + } + + // First the switches + for (q=QListHead(&g_Fabric.AllSWs); q != NULL; q = QListNext(&g_Fabric.AllSWs, q)) { + nodep = (NodeData *)QListObj(q); + portp1 = FindNodePort(nodep, 0); + + if (!portp1) + continue; + if (!ComparePortPoint(portp1, focus)) + continue; + + printf("%*s0x%016"PRIx64" %s %5u %u %.*s \n", indent, "", + portp1->nodep->NodeInfo.NodeGUID, + StlNodeTypeToText(portp1->nodep->NodeInfo.NodeType), + portp1->EndPortLID, portp1->PortInfo.s1.LMC, NODE_DESCRIPTION_ARRAY_SIZE, + g_noname?g_name_marker:(char*)portp1->nodep->NodeDesc.NodeString); + + for ( p=cl_qmap_head(&nodep->Ports); + p != cl_qmap_end(&nodep->Ports); + p = cl_qmap_next(p) ){ + portp2 = PARENT_STRUCT(p, PortData, NodePortsEntry); + if (!portp2) + continue; + if (portp2->neighbor) { + printf("%3u %s %s 0x%016"PRIx64" %3u %5u %.*s \n", portp2->PortNum, + StlStaticRateToText(portp2->rate), StlNodeTypeToText(portp2->neighbor->nodep->NodeInfo.NodeType), + portp2->neighbor->nodep->NodeInfo.NodeGUID, portp2->neighbor->PortNum, + portp2->neighbor->EndPortLID, NODE_DESCRIPTION_ARRAY_SIZE, + g_noname?g_name_marker:(char*)portp2->neighbor->nodep->NodeDesc.NodeString); + } + + } // End of ( p=cl_qmap_head(&nodep->Ports) + + } // End of for (q=QListHead(&g_Fabric.AllSWs); + + // now the FIs + for (q=QListHead(&g_Fabric.AllFIs); q != NULL; q = QListNext(&g_Fabric.AllFIs, q)) { + nodep = (NodeData *)QListObj(q); + + for ( p=cl_qmap_head(&nodep->Ports); + p != cl_qmap_end(&nodep->Ports); + p = cl_qmap_next(p) ){ + portp1 = PARENT_STRUCT(p, PortData, NodePortsEntry); + if (!portp1) + continue; + if (! ComparePortPoint(portp1, focus)) + continue; + + printf("%*s0x%016"PRIx64" %s %5u %u %.*s\n", indent, "", + portp1->nodep->NodeInfo.NodeGUID, + StlNodeTypeToText(portp1->nodep->NodeInfo.NodeType), + portp1->EndPortLID, portp1->PortInfo.s1.LMC,NODE_DESCRIPTION_ARRAY_SIZE, + g_noname?g_name_marker:(char*)portp1->nodep->NodeDesc.NodeString); + + if (portp1->neighbor){ + printf("%3u %s %s 0x%016"PRIx64" %3u %5u %.*s\n", portp1->PortNum, + StlStaticRateToText(portp1->rate), StlNodeTypeToText(portp1->neighbor->nodep->NodeInfo.NodeType), + portp1->neighbor->nodep->NodeInfo.NodeGUID, portp1->neighbor->PortNum, + portp1->neighbor->EndPortLID, NODE_DESCRIPTION_ARRAY_SIZE, + g_noname?g_name_marker:(char*)portp1->neighbor->nodep->NodeDesc.NodeString); + } + + } // End of ( p=cl_qmap_head(&nodep->Ports) + + } // End of for (q=QListHead(&g_Fabric.AllFIs); + +} + +void ShowRoutesReport(EUI64 portGuid, Point *point1, Point *point2, Format_t format, int indent, int detail) +{ + switch (format) { + case FORMAT_TEXT: + printf("%*sRoutes Summary Between:\n", indent, ""); + break; + case FORMAT_XML: + printf("%*s\n", indent, ""); + indent+=4; + break; + default: + break; + } + switch (format) { + case FORMAT_TEXT: + ShowPointBriefSummary(point1, FIND_FLAG_FABRIC, format, indent+4, detail); + printf("and "); + ShowPointBriefSummary(point2, FIND_FLAG_FABRIC, format, indent, detail); + break; + case FORMAT_XML: + ShowPointBriefSummary(point1, FIND_FLAG_FABRIC, format, indent, detail); + ShowPointBriefSummary(point2, FIND_FLAG_FABRIC, format, indent, detail); + break; + default: + break; + } + if (format == FORMAT_TEXT) + printf("\n"); + if (g_hard || g_persist) { + switch (format) { + case FORMAT_TEXT: + printf("%*sReport skipped: -H or -P option specified\n", indent, ""); + break; + case FORMAT_XML: + printf("%*s\n", indent, ""); + break; + default: + break; + } + goto done; + } + if (! (g_Fabric.flags & FF_ROUTES) && g_snapshot_in_file) { + switch (format) { + case FORMAT_TEXT: + printf("%*sReport skipped: provided snapshot was created without -r option\n", indent, ""); + break; + case FORMAT_XML: + printf("%*s\n", indent, ""); + break; + default: + break; + } + goto done; + } + + (void)ShowPointsTraceRoutes(portGuid, point1, point2, format, indent, detail); + +done: + switch (format) { + case FORMAT_TEXT: + DisplaySeparator(); + break; + case FORMAT_XML: + indent-=4; + printf("%*s\n", indent, ""); + break; + default: + break; + } +} + +static FSTATUS ValidateCLTimeGetCallback(uint64_t *address, pthread_mutex_t *lock) +{ + uint64_t usecs; + struct timespec now; + + // the system routine clock_gettime is not thread safe, so + // must request global lock. + pthread_mutex_lock(lock); + if (address == 0) { + pthread_mutex_unlock(lock); + return (FINVALID_PARAMETER); + } + clock_gettime(CLOCK_MONOTONIC, &now); + pthread_mutex_unlock(lock); + + usecs = now.tv_sec; + usecs *= 1000000; + usecs += (now.tv_nsec / 1000); + // round up anything greater than 0.5 usecs + if (now.tv_nsec % 1000 > 500) + usecs++; + + *address = usecs; + + return (FSUCCESS); +} + +static void ValidateCLRouteCallback(PortData *portp1, PortData *portp2, void *context) +{ + FSTATUS status; + + Format_t format = FORMAT_TEXT; + int indent = 0; + int detail = 0; + PQUERY_RESULT_VALUES pQueryResults = NULL; + uint32 NumPathRecords; + IB_PATH_RECORD *pPathRecords = NULL; + ValidateCreditLoopRoutesContext_t *cp = (ValidateCreditLoopRoutesContext_t *) context; + struct omgt_port *omgt_port_session = NULL; + + if (cp) { + format = cp->format; + indent = cp->indent; + detail = cp->detail; + } + + switch (format) { + case FORMAT_TEXT: + printf("%*sRoutes Summary Between:\n", indent, ""); + break; + case FORMAT_XML: + printf("%*s\n", indent, ""); + indent += 4; + break; + default: + break; + } + switch (format) { + case FORMAT_TEXT: + ShowPointPortBriefSummary("Port: ", portp1, format, indent, detail); + printf("and "); + ShowPointPortBriefSummary("Port: ", portp2, format, indent, detail); + break; + case FORMAT_XML: + ShowPointPortBriefSummary("Port: ", portp1, format, indent, detail); + ShowPointPortBriefSummary("Port: ", portp2, format, indent, detail); + break; + default: + break; + } + if (format == FORMAT_TEXT) + printf("\n"); + + if (g_hard || g_persist) { + switch (format) { + case FORMAT_TEXT: + printf("%*sReport skipped: -H or -P option specified\n", indent, ""); + break; + case FORMAT_XML: + printf("%*s\n", indent, ""); + break; + default: + break; + } + goto done; + } + if (!(g_Fabric.flags & FF_ROUTES) && g_snapshot_in_file) { + switch (format) { + case FORMAT_TEXT: + printf("%*sReport skipped: provided snapshot was created without -r option\n", indent, ""); + break; + case FORMAT_XML: + printf("%*s\n", indent, ""); + break; + default: + break; + } + goto done; + } + + switch (format) { + case FORMAT_TEXT: + printf("%*sRoutes between ports:\n", indent, ""); + ShowLinkPortBriefSummary(portp1, " ", 0, NULL, format, indent, 0); + ShowLinkPortBriefSummary(portp2, "and ", 0, NULL, format, indent, 0); + break; + case FORMAT_XML: + printf("%*s\n", indent, ""); + ShowLinkPortBriefSummary(portp1, " ", 0, NULL, format, indent + 4, 0); + ShowLinkPortBriefSummary(portp2, "and ", 0, NULL, format, indent + 4, 0); + break; + default: + break; + } + + if (!g_snapshot_in_file) { + struct omgt_params params = {.debug_file = g_verbose > 2 ? stdout : NULL}; + status = omgt_open_port_by_guid(&omgt_port_session, g_portGuid, ¶ms); + if (FSUCCESS != status) + goto done; + omgt_set_timeout(omgt_port_session, g_ms_timeout); + status = GetPaths(omgt_port_session, portp1, portp2, &pQueryResults); + if (FSUCCESS != status) + goto done; + NumPathRecords = ((PATH_RESULTS *)pQueryResults->QueryResult)->NumPathRecords; + pPathRecords = ((PATH_RESULTS *)pQueryResults->QueryResult)->PathRecords; + } else { + status = GenPaths(&g_Fabric, portp1, portp2, &pPathRecords, &NumPathRecords); + if (FSUCCESS != status) + goto done; + } + + switch (format) { + case FORMAT_TEXT: + printf("%*s%d Paths\n", indent, "", NumPathRecords); + break; + case FORMAT_XML: + printf("%*s%d\n", indent + 4, "", NumPathRecords); + break; + default: + break; + } + if (detail) { + int i; + + for (i = 0; i < NumPathRecords; i++) { + ShowTraceRoute(g_portGuid, portp1, portp2, &pPathRecords[i], format, indent + 4, detail - 1); + } + } + +done: + if (format == FORMAT_XML) + printf("%*s\n", indent, ""); + + if (pQueryResults) + omgt_free_query_result_buffer(pQueryResults); + if (omgt_port_session != NULL) + omgt_close_port(omgt_port_session); + if (g_snapshot_in_file && pPathRecords) + MemoryDeallocate(pPathRecords); + + switch (format) { + case FORMAT_TEXT: + DisplaySeparator(); + break; + case FORMAT_XML: + indent -= 4; + printf("%*s\n", indent, ""); + break; + default: + break; + } +} + +static void ValidateCLFabricSummaryCallback(FabricData_t *fabricp, const char *name, + uint32 totalPaths, uint32 totalBadPaths, + void *context) +{ + ValidateCreditLoopRoutesContext_t *cp = (ValidateCreditLoopRoutesContext_t *) context; + int indent = cp->indent; + char title[100]={0}; + + if (!cp->detail) + return; + + switch (cp->format) { + case FORMAT_TEXT: + /*printf("%*s%s summary: %d devices, %d HFIs, %d switches, %d connections, %d routing decisions, %d analyzed routes, %d incomplete routes\n", + indent, "", + name, (int)cl_qmap_count(&fabricp->map_guid_to_ib_device), QListCount(&fabricp->FIs), QListCount(&fabricp->Switches), + fabricp->ConnectionCount, fabricp->RouteCount, totalPaths, totalBadPaths);*/ // DEBUG_CODE --- ??? + printf("%*s%s summary: %d devices, %d HFIs, %d switches,\n", + indent, "", + name, (int)cl_qmap_count(&fabricp->map_guid_to_ib_device), QListCount(&fabricp->FIs), QListCount(&fabricp->Switches)); + printf("%*s\t%d connections, %d routing decisions,\n", + indent, "", + fabricp->ConnectionCount, fabricp->RouteCount); + printf("%*s\t%d analyzed routes, %d incomplete routes\n", + indent, "", + totalPaths, totalBadPaths); + break; + case FORMAT_XML: + snprintf(title, sizeof(title), "CreditLoop%sSummary", name); + XmlPrintTagHeader(title, indent); + indent+= 4; + XmlPrintDec("Devices", cl_qmap_count(&fabricp->map_guid_to_ib_device), indent); + XmlPrintDec("HFIs", QListCount(&fabricp->FIs), indent); + XmlPrintDec("Switches", QListCount(&fabricp->Switches), indent); + XmlPrintDec("Connections", fabricp->ConnectionCount, indent); + XmlPrintDec("RoutingDecisions", fabricp->RouteCount, indent); + XmlPrintDec("AnalyzedRoutes", totalPaths, indent); + XmlPrintDec("IncompleteRoutes", totalBadPaths, indent); + snprintf(title, sizeof(title), "CreditLoop%sSummary", name); + XmlPrintTagFooter(title, indent-4); + break; + default: + break; + } +} + +static void ValidateCLDataSummaryCallback(clGraphData_t *graphp, const char *name, void *context) +{ + ValidateCreditLoopRoutesContext_t *cp = (ValidateCreditLoopRoutesContext_t *) context; + int indent = cp->indent; + char title[100]={0}; + + if (!cp->detail) + return; + + switch (cp->format) { + case FORMAT_TEXT: + printf("%*s%s summary: %d vertices and %d arcs\n", + indent, "", + name, graphp->NumActiveVertices, (int)cl_qmap_count(&graphp->Arcs)); + break; + case FORMAT_XML: + snprintf(title, sizeof(title), "CreditLoop%sSummary", name); + printf("\n"); + XmlPrintTagHeader(title, indent); + indent+= 4; + XmlPrintDec("Vertices", graphp->NumActiveVertices, indent); + XmlPrintDec("Arcs", cl_qmap_count(&graphp->Arcs), indent); + snprintf(title, sizeof(title), "CreditLoop%sSummary", name); + XmlPrintTagFooter(title, indent-4); + break; + default: + break; + } +} + +static void ValidateCLRouteSummaryCallback(uint32 routesPresent, + uint32 routesMissing, + uint32 hopsHistogramEntries, + uint32 *hopsHistogram, + void *context) +{ + ValidateCreditLoopRoutesContext_t *cp = (ValidateCreditLoopRoutesContext_t *) context; + int indent = cp->indent; + uint32 hh; + + if (!cp->detail) + return; + + switch (cp->format) { + case FORMAT_TEXT: + printf("%*sRouting summary: %d routes present, %d routes missing\n", + indent, "", routesPresent, routesMissing); + + //PYTHON: for h in hopsHistogram : + for (hh = 0; hh < hopsHistogramEntries; hh++) { + if (hopsHistogram[hh]) + printf("%*sHops summary: %d routes have %d hops\n", indent, "", hopsHistogram[hh], hh); + } + break; + case FORMAT_XML: + printf("\n"); + XmlPrintTagHeader("CreditLoopRoutingSummary", indent); + indent+= 4; + + XmlPrintTagHeader("RoutingSummary", indent); + XmlPrintDec("RoutesPresent", routesPresent, indent+4); + XmlPrintDec("RoutesMissing", routesMissing, indent+4); + XmlPrintTagFooter("RoutingSummary", indent); + + //PYTHON: for h in hopsHistogram : + for (hh = 0; hh < hopsHistogramEntries; hh++) { + if (hopsHistogram[hh]) { + printf("\n"); + XmlPrintTagHeader("HopsSummary", indent); + XmlPrintDec("Routes", hopsHistogram[hh], indent+4); + XmlPrintDec("Hops", hh, indent+4); + XmlPrintTagFooter("HopsSummary", indent); + } + } + XmlPrintTagFooter("CreditLoopRoutingSummary", indent-4); + break; + default: + break; + } +} + +static void ValidateCLLinkSummaryCallback(uint32 id, const char *name, uint32 cycle, uint8 header, int indent, void *context) +{ + ValidateCreditLoopRoutesContext_t *cp = (ValidateCreditLoopRoutesContext_t *) context; + + switch (cp->format) { + case FORMAT_TEXT: + if (header) + printf("%*sLINK %d (%s) is in a CYCLE of %d:\n", indent, "", id, name, cycle); + break; + + case FORMAT_XML: + if (header) { + printf("\n"); + XmlPrintTagHeader("LinkSummary", indent); + XmlPrintDec("LinkCycle", cycle, indent+4); + XmlPrintDec("LinkId", id, indent+4); + XmlPrintStr("LinkName", name, indent+4); + } else { + XmlPrintTagFooter("LinkSummary", indent); + } + break; + + default: + break; + } +} + +static void ValidateCLLinkStepSummaryCallback(uint32 id, const char *name, uint32 step, uint8 header, int indent, void *context) +{ + ValidateCreditLoopRoutesContext_t *cp = (ValidateCreditLoopRoutesContext_t *) context; + + switch (cp->format) { + case FORMAT_TEXT: + if (header) { + if (cp->detail >= 4) + printf("%*s----------------------------------------\n", indent, ""); + printf("%*s%d: LINK %d (%s)\n", indent, "", step, id, name); + } + break; + + case FORMAT_XML: + if (header) { + printf("\n"); + XmlPrintTagHeader("LinkStepSummary", indent); + XmlPrintDec("LinkStep", step, indent+4); + XmlPrintDec("LinkId", id, indent+4); + XmlPrintStr("LinkName", name, indent+4); + } else { + XmlPrintTagFooter("LinkStepSummary", indent); + } + break; + + default: + break; + } +} + +static void ShowCLPathRecord(IB_PATH_RECORD *pPathRecord, Format_t format, int indent) +{ + char buf[8]; + + switch (format) { + case FORMAT_TEXT: + printf("%*sSGID: 0x%016"PRIx64":%016"PRIx64"\n", + indent, "", + pPathRecord->SGID.Type.Global.SubnetPrefix, + pPathRecord->SGID.Type.Global.InterfaceID); + printf("%*sDGID: 0x%016"PRIx64":%016"PRIx64"\n", + indent, "", + pPathRecord->DGID.Type.Global.SubnetPrefix, + pPathRecord->DGID.Type.Global.InterfaceID); + printf("%*sSLID: 0x%.*x DLID: 0x%.*x Reversible: %s PKey: 0x%04x\n", + indent, "", (pPathRecord->SLID <= IB_MAX_UCAST_LID ? 4:8), pPathRecord->SLID, + (pPathRecord->DLID <= IB_MAX_UCAST_LID ? 4:8), pPathRecord->DLID, + pPathRecord->Reversible ? "Y" : "N", pPathRecord->P_Key); + printf("%*sRaw: %s FlowLabel: 0x%05x HopLimit: 0x%02x TClass: 0x%02x\n", + indent, "", pPathRecord->u1.s.RawTraffic ? "Y" : "N", + pPathRecord->u1.s.FlowLabel, pPathRecord->u1.s.HopLimit, + pPathRecord->TClass); + FormatTimeoutMult(buf, pPathRecord->PktLifeTime); + printf("%*sSL: %2d Mtu: %5s Rate: %4s PktLifeTime: %s Pref: %d\n", + indent, "", pPathRecord->u2.s.SL, IbMTUToText(pPathRecord->Mtu), + StlStaticRateToText(pPathRecord->Rate), buf, + pPathRecord->Preference); + break; + + case FORMAT_XML: + XmlPrintTagHeader("PathRecord", indent); + XmlPrintGID("SGID", pPathRecord->SGID, indent + 4); + XmlPrintGID("DGID", pPathRecord->DGID, indent + 4); + XmlPrintLID("SLID", pPathRecord->SLID, indent + 4); + XmlPrintLID("DLID", pPathRecord->DLID, indent + 4); + XmlPrintStr("Reversible", pPathRecord->Reversible ? "Y" : "N", indent + 4); + XmlPrintDec("Reversible_Int", pPathRecord->Reversible, indent + 4); + XmlPrintPKey("PKey", pPathRecord->P_Key, indent + 4); + XmlPrintStr("Raw", pPathRecord->u1.s.RawTraffic ? "Y" : "N", indent + 4); + XmlPrintDec("Raw_Int", pPathRecord->u1.s.RawTraffic, indent + 4); + XmlPrintHex("FlowLabel", pPathRecord->u1.s.FlowLabel, indent + 4); + XmlPrintHex8("HopLimit", pPathRecord->u1.s.HopLimit, indent + 4); + XmlPrintHex8("TClass", pPathRecord->TClass, indent + 4); + XmlPrintDec("SL", pPathRecord->u2.s.SL, indent + 4); + XmlPrintDec("Mtu", GetBytesFromMtu(pPathRecord->Mtu), indent + 4); + XmlPrintRate(pPathRecord->Rate, indent + 4); + FormatTimeoutMult(buf, pPathRecord->PktLifeTime); + XmlPrintStr("PktLifeTime", buf, indent + 4); + XmlPrintDec("PktLifeTime_Int", pPathRecord->PktLifeTime, indent + 4); + XmlPrintDec("Preference", pPathRecord->Preference, indent + 4); + XmlPrintTagFooter("PathRecord", indent); + break; + + default: + break; + } +} + +static void ShowCLTraceRecord(FabricData_t *fabricp, STL_TRACE_RECORD *pTraceRecord, uint32 record, Format_t format, int indent) +{ + NodeData *nodep; + + switch (format) { + case FORMAT_TEXT: + printf("%*sTrace Record[%d]", indent, "", record); + indent += 4; + printf("%*sIDGeneration: 0x%04x\n", + indent, "", pTraceRecord->IDGeneration); + printf("%*sNodeType: 0x%02x\n", + indent, "", pTraceRecord->NodeType); + printf("%*sNodeID: 0x%016"PRIx64" ChassisID: %016"PRIx64"\n", + indent, "", pTraceRecord->NodeID, pTraceRecord->ChassisID); + printf("%*sEntryPortID: 0x%016"PRIx64" ExitPortID: %016"PRIx64"\n", + indent, "", pTraceRecord->EntryPortID, pTraceRecord->ExitPortID); + printf("%*sEntryPort: 0x%02x ExitPort: 0x%02x\n", + indent, "", pTraceRecord->EntryPort, pTraceRecord->ExitPort); + if ((nodep = FindNodeGuid(fabricp, pTraceRecord->NodeID))) + printf("%*sNodeDesc: %s\n", indent, "", nodep->NodeDesc.NodeString); + break; + + case FORMAT_XML: + XmlPrintTagHeader("TraceRecord", indent); + // TraceRecordId not a standard trace record field. The field was + // added to assist the person analyzing this data. + XmlPrintDec("TraceRecordId", record, indent + 4); + XmlPrintHex16("IDGeneration", pTraceRecord->IDGeneration, indent + 4); + XmlPrintNodeType(pTraceRecord->NodeType, indent + 4); + XmlPrintHex64("NodeID", pTraceRecord->NodeID, indent + 4); + XmlPrintHex64("ChassisID", pTraceRecord->ChassisID, indent + 4); + XmlPrintHex64("EntryPortID", pTraceRecord->EntryPortID, indent + 4); + XmlPrintHex64("ExitPortID", pTraceRecord->ExitPortID, indent + 4); + XmlPrintHex8("EntryPort", pTraceRecord->EntryPort, indent + 4); + XmlPrintHex8("ExitPort", pTraceRecord->ExitPort, indent + 4); + XmlPrintTagFooter("TraceRecord", indent); + break; + + default: + break; + } +} + +static void ValidateCLPathSummaryCallback(FabricData_t *fabricp, clConnData_t *connp, int indent, void *context) +{ + FSTATUS status; + ValidateCreditLoopRoutesContext_t *cp = (ValidateCreditLoopRoutesContext_t *) context; + int i, xmlFmt = (cp->format == 1) ? 1 : 0; + uint32 NumTraceRecords; + STL_TRACE_RECORD *pTraceRecords = NULL; + PQUERY_RESULT_VALUES pQueryResults = NULL; + struct omgt_port *omgt_port_session = NULL; + + // + // display path record associated with the route + if (xmlFmt) + XmlPrintTagHeader("Route", indent); + else + printf("%*sPath Record\n", indent, ""); + ShowCLPathRecord(&connp->PathInfo.path, cp->format, indent+4); + + // + // retrieve trace records associated with the route + if (!((fabricp->flags & FF_ROUTES) && g_snapshot_in_file)) { + struct omgt_params params = {.debug_file = g_verbose > 2 ? stdout : NULL}; + if(omgt_open_port_by_guid(&omgt_port_session, g_portGuid, ¶ms)) + return; + omgt_set_timeout(omgt_port_session, g_ms_timeout); + if (GetTraceRoute(omgt_port_session, &connp->PathInfo.path, &pQueryResults)) { + omgt_close_port(omgt_port_session); + return; + } + NumTraceRecords = ((STL_TRACE_RECORD_RESULTS *)pQueryResults->QueryResult)->NumTraceRecords; + pTraceRecords = ((STL_TRACE_RECORD_RESULTS *)pQueryResults->QueryResult)->TraceRecords; + } else { + if ((status = GenTraceRoutePath(fabricp, &connp->PathInfo.path, g_rc, &pTraceRecords, &NumTraceRecords))) { + if (status == FUNAVAILABLE) { + fprintf(stderr, "opareport: Routing Tables not available in snapshot\n"); + goto done; + } else if (status == FNOT_DONE) { + if (!xmlFmt) + printf("%*sRoute Incomplete\n", indent, ""); + else + printf("%*s0 \n", indent, ""); + // don't fail just because some routes are incomplete + } else { + fprintf(stderr, "opareport: Unable to determine route: (status=0x%x): %s\n", status, iba_fstatus_msg(status)); + if (status == FINSUFFICIENT_MEMORY) + exit(0); + } + goto done; + } + } + + // + // display trace records associated with the route + printf("\n"); + if (xmlFmt) + XmlPrintDec("TraceRecords", NumTraceRecords, indent+4); + else + printf("%*sTrace Records (%d)\n", indent, "", NumTraceRecords); + for (i = 0; i < NumTraceRecords;/* i++*/) { + ShowCLTraceRecord(fabricp, &pTraceRecords[i], i, cp->format, indent+4); + if (++i < NumTraceRecords) + printf("\n"); + } + + if (xmlFmt) + XmlPrintTagFooter("Route", indent); + else + printf("\n"); + +done: + if (pQueryResults) + omgt_free_query_result_buffer(pQueryResults); + if (omgt_port_session != NULL) + omgt_close_port(omgt_port_session); +} + +// output summary of all IB Links with errors > threshold +void ShowLinkErrorReport(Point *focus, Format_t format, int indent, int detail) +{ + LIST_ITEM *p; + uint32 count = 0; + uint32 checked = 0; + + switch (format) { + case FORMAT_TEXT: + printf("%*sLinks with errors %s threshold Summary\n", indent, "", + g_threshold_compare?">=":">"); + break; + case FORMAT_XML: + printf("%*s \n", indent, "", + g_threshold_compare?">=":">"); + indent+=4; + break; + default: + break; + } + if (g_hard || g_persist) { + switch (format) { + case FORMAT_TEXT: + printf("%*sReport skipped: -H or -P option specified\n", indent, ""); + break; + case FORMAT_XML: + printf("%*s\n", indent, ""); + break; + default: + break; + } + goto done; + } else if (! (g_Fabric.flags & FF_STATS) && ! g_snapshot_in_file) { + switch (format) { + case FORMAT_TEXT: + printf("%*sReport skipped: -s nor -X option not specified\n", indent, ""); + break; + case FORMAT_XML: + printf("%*s\n", indent, ""); + break; + default: + break; + } + goto done; + } else if (! (g_Fabric.flags & FF_STATS) && g_snapshot_in_file) { + switch (format) { + case FORMAT_TEXT: + printf("%*sReport skipped: provided snapshot was created without -s option\n", indent, ""); + break; + case FORMAT_XML: + printf("%*s\n", indent, ""); + break; + default: + break; + } + goto done; + } + ShowPointFocus(focus, FIND_FLAG_FABRIC, format, indent, detail); + if (g_limitstats) { + switch (format) { + case FORMAT_TEXT: + printf("Check limited, will not check neighbor ports\n"); + break; + case FORMAT_XML: + printf("\n"); + break; + default: + break; + } + } + if (! ShowThresholds(format, indent, detail)) { + switch (format) { + case FORMAT_TEXT: + printf("%*sReport skipped: no thresholds configured\n", indent, ""); + break; + case FORMAT_XML: + printf("%*s\n", indent, ""); + break; + default: + break; + } + goto done; + } + + for (p=QListHead(&g_Fabric.AllPorts); p != NULL; p = QListNext(&g_Fabric.AllPorts, p)) { + PortData *portp1, *portp2; + + portp1 = (PortData *)QListObj(p); + // to avoid duplicated processing, only process "from" ports in link + if (! portp1->from) + continue; + portp2 = portp1->neighbor; + // if g_limitstats is set, we will not have PortCounters for + // ports outside our focus, so we will not report nor check them + if (! ComparePortPoint(portp1, focus) && ! ComparePortPoint(portp2, focus)) + continue; + checked++; + if (PortCountersExceedThreshold(portp1) || PortCountersExceedThreshold(portp2)) + { + if (detail) { + if (count) { + if (format == FORMAT_TEXT) { + printf("\n"); // blank line between links + } + } else { + ShowLinkBriefSummaryHeader(format, indent, detail-1); + } + ShowLinkErrorSummary(portp1, format, indent, detail-1); + } + count++; + } + } + switch (format) { + case FORMAT_TEXT: + printf("%*s%u of %u Links Checked, %u Errors found\n", indent, "", + checked, g_Fabric.LinkCount, count); + break; + case FORMAT_XML: + XmlPrintDec("LinksChecked", checked, indent); + XmlPrintDec("TotalLinks", g_Fabric.LinkCount, indent); + XmlPrintDec("LinksWithErrors", count, indent); + break; + default: + break; + } + +done: + switch (format) { + case FORMAT_TEXT: + DisplaySeparator(); + break; + case FORMAT_XML: + indent-=4; + printf("%*s\n", indent, ""); + break; + default: + break; + } +} + +/* clear all PortCounters on all ports in fabric + */ +FSTATUS ClearAllPortCountersAndShow(EUI64 portGuid, Point *focus, boolean clearall, Format_t format, boolean quiet) +{ + uint32 node_count=0; + uint32 port_count=0; + uint32 nrsp_node_count=0; + uint32 nrsp_port_count=0; + int indent = 0; + + if (! quiet) { + switch (format) { + case FORMAT_TEXT: + printf("Clearing Port Counters\n"); + break; + case FORMAT_XML: + printf("\n"); + indent+=4; + break; + default: + break; + } + ShowPointFocus(focus, FIND_FLAG_FABRIC, format, indent, 0); + if (g_limitstats) { + switch (format) { + case FORMAT_TEXT: + printf("Clear limited, will not clear neighbor ports\n"); + break; + case FORMAT_XML: + printf("\n"); + break; + default: + break; + } + } + if (! ShowClearedCounters(format, indent, 10, clearall)) { + switch (format) { + case FORMAT_TEXT: + printf("%*sClear skipped: no thresholds configured\n", 0, ""); + break; + case FORMAT_XML: + printf("%*s\n", 0, ""); + break; + default: + break; + } + goto done; + } + } else if (! clearall && ! NeedClearCounters()) { + goto done; + } + + (void)ClearAllPortCounters(portGuid, g_portAttrib->GIDTable[0], &g_Fabric, focus, + clearall?0xffffffff:g_CounterSelectMask.CounterSelectMask.AsReg32, + g_limitstats, g_quiet, &node_count, &port_count, + &nrsp_node_count, &nrsp_port_count); + if (! quiet) { + switch (format) { + case FORMAT_TEXT: + printf("%*sCleared %u Ports on %u Nodes\n", indent, "", port_count, node_count); + if (nrsp_port_count) + printf("%*sUnable to clear %u Ports on %u Nodes\n", indent, "", nrsp_port_count, nrsp_node_count); + break; + case FORMAT_XML: + XmlPrintDec("ClearedPorts", port_count, indent); + XmlPrintDec("ClearedNodes", node_count, indent); + if (nrsp_port_count) { + XmlPrintDec("NoRespPorts", nrsp_port_count, indent); + XmlPrintDec("NoRespNodes", nrsp_node_count, indent); + } + indent-=4; + printf("\n"); + break; + default: + break; + } + } else { + PROGRESS_PRINT(TRUE, "Cleared %u Ports on %u Nodes\n", port_count, node_count); + if (nrsp_port_count) + PROGRESS_PRINT(TRUE, "Unable to clear %u Ports on %u Nodes\n", nrsp_port_count, nrsp_node_count); + } + + done: + return FSUCCESS; // TBD +} + +// output summary of all LIDs +void ShowAllLIDReport(Point *focus, Format_t format, int indent, int detail) +{ + cl_map_item_t *pMap; + NodeData *nodep; + PortData *portp; + PortSelector* portselp; + uint8 lmc_range = 0; // (2 ** lmc) - 1 + uint32 ct_lid; + + switch (format) { + case FORMAT_TEXT: + printf("%*sLID Summary\n", indent, ""); + break; + case FORMAT_XML: + printf("%*s\n", indent, ""); + indent+=4; + break; + default: + break; + } + ShowPointFocus(focus, FIND_FLAG_FABRIC, format, indent, detail); + switch (format) { + case FORMAT_TEXT: + printf( "%*s%u LID(s) in Fabric%s\n", indent, "",g_Fabric.lidCount, detail?":":"" ); + break; + case FORMAT_XML: + XmlPrintDec("FabricLIDCount", g_Fabric.lidCount, indent); + break; + default: + break; + } + // Report LID Summary + ct_lid = 0; + for ( pMap=cl_qmap_head(&g_Fabric.u.AllLids); + pMap != cl_qmap_end(&g_Fabric.u.AllLids); + pMap = cl_qmap_next(pMap) ) { + portp = PARENT_STRUCT(pMap, PortData, AllLidsEntry); + portselp = GetPortSelector(portp); + nodep = portp->nodep; + + if (!ComparePortPoint(portp, focus)) + continue; + lmc_range = (1 << portp->PortInfo.s1.LMC) - 1; + + if (detail) { + if (!ct_lid) { + switch (format) { + case FORMAT_TEXT: + printf("%*s LID(Range) NodeGUID Port Type Name\n", indent, ""); + if (g_topology_in_file) + printf("%*s NodeDetails PortDetails\n", indent, ""); + break; + case FORMAT_XML: + break; + default: + break; + } + } + switch (format) { + case FORMAT_TEXT: + printf( "%*s0x%.*x", indent, "", (portp->PortInfo.LID <= IB_MAX_UCAST_LID ? 4:8), + portp->PortInfo.LID); + if (!lmc_range) + printf(" "); + else + printf( "-0x%.*x", ((portp->PortInfo.LID + lmc_range) <= IB_MAX_UCAST_LID ? 4:8), + portp->PortInfo.LID + lmc_range ); + printf( " 0x%016"PRIx64" %3u %s %s\n", + nodep->NodeInfo.NodeGUID, portp->PortNum, + StlNodeTypeToText(nodep->NodeInfo.NodeType), + (char*)nodep->NodeDesc.NodeString ); + if (nodep->enodep && nodep->enodep->details) + printf( "%*s %s\n", + indent, "", nodep->enodep->details ); + if (portselp && portselp->details) + printf( "%*s %s\n", + indent, "", portselp->details ); + break; + case FORMAT_XML: + if (!ct_lid) + printf("%*s\n", indent, ""); + printf( "%*s\n", indent+4, "", + (portp->PortInfo.LID <= IB_MAX_UCAST_LID ? 4:8), + portp->PortInfo.LID ); + if (lmc_range) + XmlPrintLID( "EndLID", + portp->PortInfo.LID + lmc_range, indent+8 ); + XmlPrintHex64( "NodeGUID", + nodep->NodeInfo.NodeGUID, indent+8 ); + XmlPrintDec("PortNum", portp->PortNum, indent+8); + if (portselp && portselp->details) + XmlPrintStr("PortDetails", portselp->details, indent+8); + XmlPrintStr( "NodeType", + StlNodeTypeToText(nodep->NodeInfo.NodeType), + indent+8 ); + XmlPrintStr( "NodeDesc", + (char*)nodep->NodeDesc.NodeString, indent+8 ); + if (nodep->enodep && nodep->enodep->details) + XmlPrintStr("NodeDetails", nodep->enodep->details, indent+8); + printf("%*s\n", indent+4, ""); + break; + default: + break; + } + } // End of if (detail) + ct_lid = ct_lid + lmc_range + 1; + } // End of for ( pMap=cl_qmap_head(&g_Fabric.AllLids) + + + switch (format) { + case FORMAT_TEXT: + printf("%*s%u Reported LID(s)\n", indent, "", ct_lid); + DisplaySeparator(); + break; + case FORMAT_XML: + if (detail && ct_lid) + printf("%*s\n", indent, ""); + XmlPrintDec("ReportedLIDCount", ct_lid, indent); + indent-=4; + printf("%*s\n", indent, ""); + break; + default: + break; + } + +} // End of ShowAllLIDReport() + +// output linear FDB +void ShowLinearFDBReport(Point *focus, Format_t format, int indent, int detail) +{ + int ix_lid; + LIST_ITEM *pList; + cl_map_item_t *pMap; + NodeData *nodep; + SwitchData *switchp; + PortData *portp; + PortSelector* portselp; + uint32 ct_node = 0; + uint32 ct_lid; + + switch (format) { + case FORMAT_TEXT: + printf("%*sLinear FDB Tables\n", indent, ""); + break; + case FORMAT_XML: + printf("%*s\n", indent, ""); + indent+=4; + break; + default: + break; + } + if (! (g_Fabric.flags & FF_ROUTES) && g_snapshot_in_file) { + switch (format) { + case FORMAT_TEXT: + printf("%*sReport skipped: provided snapshot was created without -r option\n", indent, ""); + break; + case FORMAT_XML: + printf("%*s\n", indent, ""); + break; + default: + break; + } + goto done; + } + ShowPointFocus(focus, FIND_FLAG_FABRIC, format, indent, detail); + switch (format) { + case FORMAT_TEXT: + printf( "%*s%u Connected Switches in Fabric%s\n", indent, "", + (unsigned)QListCount(&g_Fabric.AllSWs), detail?":":"" ); + break; + case FORMAT_XML: + XmlPrintDec("ConnectedSwitchCount", (unsigned)QListCount(&g_Fabric.AllSWs), indent); + break; + default: + break; + } + + // Report Linear FDB + for ( pList=QListHead(&g_Fabric.AllSWs); pList != NULL; + pList = QListNext(&g_Fabric.AllSWs, pList) ) { + nodep = QListObj(pList); + switchp = nodep->switchp; + + if (!CompareNodePoint(nodep, focus)) + continue; + + if (!switchp || !switchp->LinearFDB) + continue; + + if (detail) { + if (!ct_node) { + ShowNodeBriefSummaryHeadings(format, indent, 0); + switch (format) { + case FORMAT_TEXT: + printf("%*s Egress Neighbor\n", indent+4, ""); + printf("%*s LID Port Port Name\n", indent+4, ""); + if (g_topology_in_file) + printf("%*s PortDetails NodeDetails\n", indent+4, ""); + break; + case FORMAT_XML: + break; + default: + break; + } + } + ShowNodeBriefSummary(nodep, focus, FALSE, format, indent, 0); + ct_lid = 0; + for (ix_lid = 0; ix_lid < switchp->LinearFDBSize; ix_lid++) { + if (STL_LFT_PORT_BLOCK(switchp->LinearFDB, ix_lid) == 0xFF) + continue; + + switch (format) { + case FORMAT_TEXT: + printf( "%*s0x%04x %3u", indent+4, "", (uint32)ix_lid, STL_LFT_PORT_BLOCK(switchp->LinearFDB, ix_lid) ); + break; + case FORMAT_XML: + if (!ct_lid++) + printf("%*s\n", indent+4, ""); + printf( "%*s\n", indent+8, "", (ix_lid <= IB_MAX_UCAST_LID ? 4:8), + (uint16)ix_lid ); + XmlPrintDec("EgressPort", STL_LFT_PORT_BLOCK(switchp->LinearFDB, ix_lid), indent+12); + break; + default: + break; + } + for ( pMap=cl_qmap_head(&nodep->Ports); + pMap != cl_qmap_end(&nodep->Ports); + pMap = cl_qmap_next(pMap) ) { + portp = PARENT_STRUCT(pMap, PortData, NodePortsEntry); + if (!portp) + continue; + + if (portp->PortNum == STL_LFT_PORT_BLOCK(switchp->LinearFDB, ix_lid)) { + portselp = GetPortSelector(portp); + switch (format) { + case FORMAT_TEXT: + if (portp->neighbor) { + printf( " %3u %s", + portp->neighbor->PortNum, g_noname?g_name_marker: + (char*)portp->neighbor->nodep->NodeDesc.NodeString ); + if ( portp->neighbor->nodep->enodep && + portp->neighbor->nodep->enodep->details ) + printf( "\n%*s %s", + indent+4, "", portp->neighbor->nodep->enodep->details ); + } + + if (portselp && portselp->details) + printf( "\n%*s %s", + indent+4, "", portselp->details ); + break; + case FORMAT_XML: + if (portselp && portselp->details) + XmlPrintStr("PortDetails", portselp->details, indent+12); + if (portp->neighbor) { + XmlPrintDec("NeighborPort", portp->neighbor->PortNum, indent+12); + XmlPrintStr("NeighborNodeDesc", + g_noname?g_name_marker: + (char *)portp->neighbor->nodep->NodeDesc.NodeString, indent+12); + if ( portp->neighbor->nodep->enodep && + portp->neighbor->nodep->enodep->details ) + XmlPrintStr("NeighborNodeDetails", portp->neighbor->nodep->enodep->details, indent+12); + } + printf("%*s\n", indent+8, ""); + break; + default: + break; + } + break; + + } // End of if (portp->PortNum == switchp->LinearFDB[ix_lid]) + + } // End of for ( pMap=cl_qmap_head(&nodep->Ports) + + switch (format) { + case FORMAT_TEXT: + printf("\n"); + break; + case FORMAT_XML: + break; + default: + break; + } + + } // End of for (ix_lid = 0; ix_lid < switchp->LinearFDBSize + + switch (format) { + case FORMAT_XML: + if (ct_lid) + printf("%*s\n", indent+4, ""); + printf("%*s\n", indent, ""); + break; + default: + break; + } + + } // End of if (detail) + + ct_node++; + + } // End of for (pList=QListHead(&g_Fabric.AllSWs); pList != NULL + +done: + switch (format) { + case FORMAT_TEXT: + printf("%*s%d Reported Switch(es)\n", indent, "", ct_node); + DisplaySeparator(); + break; + case FORMAT_XML: + XmlPrintDec("ReportedSwitchCount", (unsigned)ct_node, indent); + indent-=4; + printf("%*s\n", indent, ""); + break; + default: + break; + } + +} // End of ShowLinearFDBReport() + +// Used by ShowPGReport. +static uint32 ones64(uint64 x) +{ + x -= ((x >> 1) & 0x5555555555555555ULL); + x = (((x >> 2) & 0x3333333333333333ULL) + (x & 0x3333333333333333ULL)); + x = (((x >> 4) + x) & 0x0f0f0f0f0f0f0f0fULL); + x += (x >> 8); + x += (x >> 16); + x += (x >> 32); + return(x & 0x0000003f); +} + +// Information about port groups +void ShowPGReport(Point *focus, Format_t format, int indent, int detail) +{ + int ix_lid; + LIST_ITEM *pList; + NodeData *nodep; + SwitchData *switchp; + uint16 pgCount; + uint32 ct_node = 0; + + /* Statistics block */ + uint32 overallSwitchCount = 0; + uint32 overallGroupCount = 0; + uint32 overallMaxGroupSize = 0; + uint32 overallMinGroupSize = 256; + uint32 overallSumGroupSize = 0; + uint32 overallMaxGroupCount = 0; + uint32 overallMinGroupCount = 256; + uint32 overallMaxLidsGroup = 0; + uint32 overallMinLidsGroup = 0xffffffff; + uint32 overallSumLidsGroup = 0; + + switch (format) { + case FORMAT_TEXT: + printf("%*sPort Groups\n", indent, ""); + break; + case FORMAT_XML: + printf("%*s\n", indent, ""); + indent+=4; + break; + default: + break; + } + + if (! (g_Fabric.flags & FF_ROUTES) && g_snapshot_in_file) { + switch (format) { + case FORMAT_TEXT: + printf("%*sReport skipped: provided snapshot was created without -r option\n", indent, ""); + break; + case FORMAT_XML: + printf("%*s\n", indent, ""); + break; + default: + break; + } + goto done; + } + + overallSwitchCount = QListCount(&g_Fabric.AllSWs); + ShowPointFocus(focus, FIND_FLAG_FABRIC, format, indent, detail); + switch (format) { + case FORMAT_TEXT: + printf( "%*s%u Connected Switches in Fabric%s\n", indent, "", + overallSwitchCount, detail?":":"" ); + break; + case FORMAT_XML: + XmlPrintDec("ConnectedSwitchCount", overallSwitchCount, indent); + break; + default: + break; + } + + // Summary data about Port Group Tables + for ( pList=QListHead(&g_Fabric.AllSWs); pList != NULL; + pList = QListNext(&g_Fabric.AllSWs, pList) ) { + + /* Statistics block */ + uint32 maxGroupSize = 0; + uint32 minGroupSize = 256; + uint32 sumGroupSize = 0; + uint32 maxLidsGroup = 0; + uint32 minLidsGroup = 0xffffffff; + uint32 sumLidsGroup = 0; + uint32 LidsGroup[256]; + + memset(LidsGroup,0,sizeof(LidsGroup)); + + nodep = QListObj(pList); + switchp = nodep->switchp; + + if (!CompareNodePoint(nodep, focus)) + continue; + + if (!switchp || !switchp->PortGroupElements || !switchp->PortGroupFDB) + continue; + + if (nodep->pSwitchInfo && + nodep->pSwitchInfo->SwitchInfoData.AdaptiveRouting.s.Enable && + nodep->pSwitchInfo->SwitchInfoData.PortGroupTop != 0) { + pgCount = nodep->pSwitchInfo->SwitchInfoData.PortGroupTop; + } else { + pgCount = 0; + } + + overallGroupCount += pgCount; + overallMaxGroupCount = MAX(overallMaxGroupCount, pgCount); + overallMinGroupCount = MIN(overallMinGroupCount, pgCount); + + switch (format) { + case FORMAT_XML: + printf("%*s\n", indent, ""); + break; + default: + break; + } + + if (!ct_node) { + ShowNodeBriefSummaryHeadings(format, indent, 0); + } + + if (format == FORMAT_TEXT) { + printf("\n"); + } + + ShowNodeBriefSummary(nodep, focus, FALSE, format, indent, 0); + if (format == FORMAT_TEXT && detail > 2) { + printf("%*s Group : Ports\n",indent+4,""); + } + + if (pgCount == 0) { + switch (format) { + case FORMAT_TEXT: + printf("%*s(no groups)\n", indent+4, ""); + break; + case FORMAT_XML: + break; + default: + break; + } + } else { + for (ix_lid = 0; + switchp->PortGroupElements && ix_lid < pgCount; + ix_lid++) { + uint32 bitCount = ones64((uint64_t)switchp->PortGroupElements[ix_lid]); + + maxGroupSize = MAX(maxGroupSize, bitCount); + minGroupSize = MIN(minGroupSize, bitCount); + sumGroupSize += bitCount; + + if (detail > 2) { + uint64_t msk; + int j; + if (format == FORMAT_TEXT) { + printf("%*s %3d : ", indent+4, "", + ix_lid); + if (switchp->PortGroupElements[ix_lid]==0) { + printf("None"); + } else for (msk = 1, j = 0;j < 64;msk<<= 1, j++) { + if (switchp->PortGroupElements[ix_lid] & msk) { + printf("%d, ", j+1); + } + } + printf("\n"); + } else if (format == FORMAT_XML) { + printf( "%*s\n", indent+4, "", + ix_lid); + XmlPrintHex64("PortGroup", + switchp->PortGroupElements[ix_lid], + indent+8); + printf("%*s\n", indent+4, ""); + } + } + } + + overallMaxGroupSize = MAX(maxGroupSize,overallMaxGroupSize); + overallMinGroupSize = MIN(minGroupSize,overallMinGroupSize); + overallSumGroupSize += sumGroupSize; + + if (detail > 2 && format == FORMAT_TEXT) { + printf("\n"); + } + switch (format) { + case FORMAT_TEXT: + printf("%*s Num Groups : %d\n", indent+4, "", pgCount); + printf("%*sMax Ports/Group : %d\n", indent+4, "", maxGroupSize); + printf("%*sMin Ports/Group : %d\n", indent+4, "", minGroupSize); + printf("%*sAvg Ports/Group : %.1f\n", indent+4, "", + (float)sumGroupSize/(float)pgCount); + break; + case FORMAT_XML: + XmlPrintDec("NumGroups", pgCount, indent+4); + XmlPrintDec("MaxGroupSize",maxGroupSize, indent+4); + XmlPrintDec("MinGroupSize",minGroupSize, indent+4); + break; + } + } + + if (pgCount && switchp->PortGroupFDB) { + uint8 g; + + for (ix_lid = 1; ix_lid < switchp->LinearFDBSize; ix_lid++) { + if (STL_LFT_PORT_BLOCK(switchp->LinearFDB, ix_lid) == 0xFF) + continue; + if (ix_lid >= switchp->PortGroupFDBSize) + break; + g = STL_PGFT_PORT_BLOCK(switchp->PortGroupFDB,ix_lid); + LidsGroup[g]++; + } + + for (g=0; g < pgCount; g++) { + sumLidsGroup += LidsGroup[g]; + maxLidsGroup = MAX(maxLidsGroup,LidsGroup[g]); + minLidsGroup = MIN(minLidsGroup,LidsGroup[g]); + } + + overallSumLidsGroup += sumLidsGroup; + overallMaxLidsGroup = MAX(maxLidsGroup,overallMaxLidsGroup); + overallMinLidsGroup = MIN(minLidsGroup,overallMinLidsGroup); + + switch (format) { + case FORMAT_TEXT: + printf("%*s Max Lids/Group : %d\n", indent+4, "", maxLidsGroup); + printf("%*s Min Lids/Group : %d\n", indent+4, "", minLidsGroup); + printf("%*s Avg Lids/Group : %.1f\n", indent+4, "", + (float)sumLidsGroup/(float)pgCount); + break; + case FORMAT_XML: + XmlPrintDec("MaxLidsGroup",maxLidsGroup, indent+4); + XmlPrintDec("MinLidsGroup",minLidsGroup, indent+4); + break; + } + + if (detail > 2) { + uint32_t currGroup = 0xFFFF; + STL_LID startLid = 0; + + switch (format) { + case FORMAT_TEXT: + printf("%*s---- Lid Range ---- Group #\n", indent+4, ""); + break; + case FORMAT_XML: + printf("%*s\n", indent+4, ""); + break; + default: + break; + } + + for (ix_lid = 1; ix_lid < switchp->LinearFDBSize; ix_lid++) { + if (ix_lid >= switchp->PortGroupFDBSize) + break; + g = STL_PGFT_PORT_BLOCK(switchp->PortGroupFDB,ix_lid); + if (format == FORMAT_XML) { + if (g == 0xFF) + continue; + + printf( "%*s\n", indent+8, "", + (ix_lid <= IB_MAX_UCAST_LID ? 4:8), ix_lid ); + XmlPrintHex("PortGroup", g, indent+12); + printf("%*s\n", indent+8, ""); + } else { + if (g == currGroup) + continue; + if (currGroup != 0xFFFF) { + if (currGroup != 0xFF) { + printf("%*s0x%08x - %08x %3u\n", indent+4, "", + startLid, ix_lid-1, currGroup); + } else { + printf("%*s0x%08x - %08x (none)\n", + indent+4, "", startLid, ix_lid-1); + } + } + currGroup = g; + startLid = ix_lid; + } + } + + switch (format) { + case FORMAT_XML: + printf("%*s\n", indent+4, ""); + break; + default: + if (currGroup != 0xFF) { + printf("%*s0x%08x - %08x %3u\n", indent+4, "", + startLid, ix_lid-1, currGroup); + } else { + printf("%*s0x%08x - %08x (none)\n", indent+4, "", + startLid, ix_lid-1); + } + break; + } + } + } + + switch (format) { + case FORMAT_XML: + printf("%*s\n", indent, ""); + printf("%*s\n", indent, ""); + break; + default: + break; + } + + ct_node++; + + } // End of for (pList=QListHead(&g_Fabric.AllSWs); pList != NULL + + if (overallGroupCount != 0) { + switch (format) { + case FORMAT_TEXT: + printf("\n%*sSummary:\n", indent, ""); + printf("%*s Num Groups : %d\n", indent+4, "", + overallGroupCount); + printf("%*sMax Ports/Group : %d\n", indent+4, "", + overallMaxGroupSize); + printf("%*sMin Ports/Group : %d\n", indent+4, "", + overallMinGroupSize); + printf("%*sAvg Ports/Group : %.1f\n", indent+4, "", + (float)overallSumGroupSize/(float)overallGroupCount); + printf("%*s Max Lids/Group : %d\n", indent+4, "", + overallMaxLidsGroup); + printf("%*s Min Lids/Group : %d\n", indent+4, "", + overallMinLidsGroup); + printf("%*s Avg Lids/Group : %.1f\n", indent+4, "", + (float)overallSumLidsGroup/(float)overallGroupCount); + break; + case FORMAT_XML: + break; + } + } else if (format == FORMAT_TEXT) { + printf("\n%*sNo port groups found.\n",indent,""); + } + +done: + switch (format) { + case FORMAT_TEXT: + printf("%*s%d Reported Switch(es)\n", indent, "", ct_node); + DisplaySeparator(); + break; + case FORMAT_XML: + XmlPrintDec("ReportedSwitchCount", (unsigned)ct_node, indent); + indent-=4; + printf("%*s\n", indent, ""); + break; + default: + break; + } + +} // End of ShowPGReport() + +// Used by PGRouteHop to print out the current node when a adaptive routing +// error is detected. Since PGRouteHop is recursive, this has the effect +// of printing out each hop in the failed route. +// +// nodep - the current node. +// lid - the lid of the current node. +// length - the recursive depth/hop count/path length at this point. +static void POP_NODEDATA(NodeData *nodep, STL_LID lid, + uint32_t length, Format_t format, int indent) +{ + switch(format) { + case FORMAT_XML: + printf("%*s\n",indent+4,"", length); + XmlPrintHex64( "NodeGUID", nodep->NodeInfo.NodeGUID, indent+8 ); + printf("%*s\n",indent+4,""); + break; + default: + printf("%*sHop %d: 0x%016"PRIx64", (LID 0x%x)\n",indent+4,"", \ + length, nodep->NodeInfo.NodeGUID, lid); \ + break; + } +} + +// Note that 128 is an arbitrary limit, but it will be able to +// cope with a 2D mesh/torus that's 64 switches in each dimension, +// which is more than twice the # of LIDs available in STL gen1. +#define MAX_HOPS 128 + +// Used by ShowValidatePGReport. +// olid = originating lid (original slid) +// dlid = destination lid +// nodep = current hop +// length = hop count so far. +// mhops = maximum # of hops we are allowed to traverse. +// lftonly = ignore the port group forwarding table +// +// Returns the total hopcount or -1. +// +static int32_t PGRouteHop(STL_LID olid, NodeData *nodep, STL_LID dlid, + int32_t length, int32_t mhops, int32_t lftonly, + Format_t format, int indent) +{ + PortData *portp; + SwitchData *switchp; + uint8_t ep; + uint8_t pg; + NodeData *nnodep; + PortData *nportp; + uint32_t i; + int32_t pl1, pl2; + STL_LID slid; + STL_PORTMASK pgm; + + // Add the link that was traversed to get here: + length++; + + // If we've already tested this dlid from this switch, + // don't do it again. + if (((uint8_t*)nodep->context)[dlid] != 0) { + return length+((uint8_t*)nodep->context)[dlid]; + } + + portp = FindNodePort(nodep,0); + if (!portp) { + printf("%*sUnable to find port 0\n", indent, ""); + return -1; + } + slid = portp->PortInfo.LID; + switchp = nodep->switchp; + + if (dlid == slid) { + // Inability to route to yourself is checked at the + // top level, so we can just return success here. + return length; + } + + // Have we exceeded the maximum # of hops permitted? + if (length > mhops) { + switch(format) { + case FORMAT_XML: + printf("%*s\n",indent+4,""); + XmlPrintDec("SLID",olid,indent+8); + XmlPrintDec("DLID",dlid,indent+8); + break; + default: + printf("%*sERROR: Path from 0x%x to 0x%x exceeds normal path length or max hops.\n", + indent, "", olid, dlid); + break; + } + POP_NODEDATA(nodep, slid, length, format, indent); + return -1; + } + + ep = STL_LFT_PORT_BLOCK(switchp->LinearFDB,dlid); + pg = STL_PGFT_PORT_BLOCK(switchp->PortGroupFDB,dlid); + + // + // if LFT[dlid] == 0xff then we think this dlid is unused, + // which is inconsistent with the parent switch. + // + if (ep == 0xff) { + printf("%*sNo path to LID 0x%x\n", + indent, "", dlid); + POP_NODEDATA(nodep, slid, length, format, indent); + return -1; + } + + // Find our LFT neighbor node. + portp = FindNodePort(nodep,ep); + if (!portp) { + printf("%*sUnable to find port %d\n", + indent, "", ep); + return -1; + } + nportp = portp->neighbor; + nnodep = nportp->nodep; + + // If our neighbor isn't a switch, then the route better + // terminate and PGFT[dlid] should be 0xff. + if (nnodep->NodeInfo.NodeType != STL_NODE_SW) { + STL_LID mask = ~0 << nportp->PortInfo.s1.LMC; + if ((dlid & mask) != (nportp->PortInfo.LID & mask)) { + switch(format) { + case FORMAT_XML: + printf("%*s\n",indent+4,""); + XmlPrintDec("SLID",olid,indent+8); + XmlPrintDec("DLID",dlid,indent+8); + break; + default: + printf("%*sERROR: Path from 0x%x to 0x%x terminates at the wrong " + "device:\n", + indent, "", olid, dlid); + break; + } + POP_NODEDATA(nnodep, nportp->PortInfo.LID, length+1, format, indent); + POP_NODEDATA(nodep, slid, length, format, indent); + return -1; + } else if (pg != 0xff) { + switch(format) { + case FORMAT_XML: + printf("%*s\n",indent+4,""); + XmlPrintDec("SLID",olid,indent+8); + XmlPrintDec("DLID",dlid,indent+8); + break; + default: + printf("%*sERROR: LFT Path from 0x%x to 0x%x terminates but is also " + "in the PGFT: (1)\n", + indent, "", olid, dlid); + break; + } + POP_NODEDATA(nnodep, nportp->PortInfo.LID, length+1, format, indent); + POP_NODEDATA(nodep, slid, length, format, indent); + return -1; + } + // Everything checks out. Include the egress link in our count. + ((uint8_t*)nodep->context)[dlid]=1; + return length+1; //success. + } + + // Test the LFT route for this DLID. There is another report that + // does this, but we want the hop count to compare the PGFT entries + // against. + pl1 = PGRouteHop(slid, nnodep, dlid, length, mhops, 1, format, indent); + if (pl1 < 0) { + POP_NODEDATA(nodep, slid, length, format, indent); + return pl1; + } else if (lftonly != 0) { + // done. + return pl1; + } + + // If the DLID is in the PGFT, then test the route from this switch to + // DLID via each port in the matching port group. + if (pg != 0xff) for (i=1, pgm = switchp->PortGroupElements[pg]; + pgm != 0; pgm>>=1, i++) { + if (pgm & 1 && i != ep) { + // We only test a port if (a) it is a member of the port group and + // (b) it is not the lft egress port (we already checked that). + // TODO Can we avoid revisiting the same node in the tier0 case? + portp = FindNodePort(nodep,i); + if (!portp) { + printf("%*sUnable to find port %d\n", + indent, "", i); + return -1; + } + nportp = portp->neighbor; + nnodep = nportp->nodep; + + if (nnodep->NodeInfo.NodeType != STL_NODE_SW) { + STL_LID mask = ~0 << nportp->PortInfo.s1.LMC; + if ((dlid & mask) != (nportp->PortInfo.LID & mask)) { + switch(format) { + case FORMAT_XML: + printf("%*s\n",indent+4,""); + XmlPrintDec("SLID",olid,indent+8); + XmlPrintDec("DLID",dlid,indent+8); + break; + default: + printf("%*sERROR: AR Path from 0x%x to 0x%x terminates at the " + "wrong device:\n", indent, "", olid, dlid); + break; + } + } else { + // Even if this is the right device, we still have + // a problem. + switch(format) { + case FORMAT_XML: + printf("%*s\n",indent+4,""); + XmlPrintDec("SLID",olid,indent+8); + XmlPrintDec("DLID",dlid,indent+8); + break; + default: + printf("%*sERROR: AR Path from 0x%x to 0x%x terminates but LFT " + "path does not: (2)\n", + indent, "", olid, dlid); + break; + } + } + POP_NODEDATA(nnodep, nportp->PortInfo.LID, length+1, format, + indent); + POP_NODEDATA(nodep, slid, length, format, indent); + return -1; + } + + // Calculate the length of the path from here to dlid + // via nnodep. It should be the same as the LFT path length. + pl2 = PGRouteHop(slid, nnodep, dlid, length, mhops, 0, format, indent); + if (pl2 < 0) { + // There was a problem further along. Just pop our + // position in the path and return. + POP_NODEDATA(nodep, slid, length, format, indent); + return -1; + } else if (pl2 != pl1) { + // This path was either shorter or longer than + // the linear path. Either way, that's a problem. + switch(format) { + case FORMAT_XML: + printf("%*s\n",indent+4,""); + XmlPrintDec("SLID",olid,indent+8); + XmlPrintDec("DLID",dlid,indent+8); + XmlPrintDec("PL1",pl1-1,indent+8); + XmlPrintDec("PL2",pl2-1,indent+8); + break; + default: + printf("%*sERROR: Paths from 0x%016"PRIx64", (LID 0x%x)" + " to LID 0x%x have inconsistent hop counts: %d vs %d\n", + indent, "", + nodep->NodeInfo.NodeGUID, slid, dlid, pl1-1, pl2-1); + break; + } + POP_NODEDATA(nnodep, nportp->EndPortLID, length, + format, indent); + return -1; + } + } + } + + ((uint8_t*)nodep->context)[dlid]=pl1 - length; + return pl1; +} + +// Used by ShowValidatePGReport. +static int compare_masks(const void *a, const void *b) +{ + STL_PORTMASK *pm1 = (STL_PORTMASK*)a; + STL_PORTMASK *pm2 = (STL_PORTMASK*)b; + + if (*pm1<*pm2) return -1; + if (*pm1>*pm2) return 1; + return 0; +} + +void ShowValidatePGReport(Format_t format, int indent, int detail) +{ + LIST_ITEM *pList; + uint32_t routeCount = 0; + uint32_t ct_node = 0; + + if (! (g_Fabric.flags & FF_ROUTES) && g_snapshot_in_file) { + switch (format) { + case FORMAT_TEXT: + printf("%*sReport skipped: provided snapshot was created without -r option\n", indent, ""); + break; + case FORMAT_XML: + printf("%*s\n", indent, ""); + break; + default: + break; + } + return; + } + + switch (format) { + case FORMAT_TEXT: + printf("%*sValidate Port Groups\n", indent, ""); + break; + case FORMAT_XML: + printf("%*s\n", indent, ""); + indent+=4; + break; + default: + break; + } + + switch (format) { + case FORMAT_TEXT: + printf( "%*s%u LID(s) in Fabric%s\n", indent, "", + (unsigned)cl_qmap_count(&g_Fabric.u.AllLids), detail?":":"" ); + printf("%*s%u Connected HFIs in Fabric%s\n", indent, "", + (unsigned)QListCount(&g_Fabric.AllFIs), detail?":":""); + printf( "%*s%u Connected Switch(es) in Fabric%s\n", indent, "", + (unsigned)QListCount(&g_Fabric.AllSWs), detail?":":"" ); + break; + case FORMAT_XML: + XmlPrintDec("FabricLIDCount", + (unsigned)cl_qmap_count(&g_Fabric.u.AllLids), indent); + XmlPrintDec("ConnectedHFICount", + (unsigned)QListCount(&g_Fabric.AllFIs), indent); + XmlPrintDec("ConnectedSwitchCount", + (unsigned)QListCount(&g_Fabric.AllSWs), indent); + break; + default: + break; + } + + // Allocate buffers for optimizing the search. + for ( pList=QListHead(&g_Fabric.AllSWs); pList != NULL; + pList = QListNext(&g_Fabric.AllSWs, pList) ) { + NodeData *nodep = (NodeData*)QListObj(pList); + STL_SWITCHINFO_RECORD *switchp = nodep->pSwitchInfo; + + assert(switchp); + + nodep->context = MemoryAllocate2AndClear( + switchp->SwitchInfoData.LinearFDBTop+1, + IBA_MEM_FLAG_PREMPTABLE, MYTAG); + + assert(nodep->context); + } + + for ( pList=QListHead(&g_Fabric.AllSWs); pList != NULL; + pList = QListNext(&g_Fabric.AllSWs, pList) ) { + NodeData *nodep = (NodeData*)QListObj(pList); + SwitchData *switchp = nodep->switchp; + STL_PORTMASK pgt[MAX_PGT_ELEMENTS]; + STL_PORTMASK pgo; + int i; + int pgCount = 0; + int dupPGFound = 0; + + if (!ct_node) { + ShowNodeBriefSummaryHeadings(format, indent, 0); + ct_node++; + } + ShowNodeBriefSummary(nodep, NULL, FALSE, format, indent, 0); + + if (nodep->pSwitchInfo && + nodep->pSwitchInfo->SwitchInfoData.AdaptiveRouting.s.Enable && + nodep->pSwitchInfo->SwitchInfoData.PortGroupTop != 0) { + pgCount = nodep->pSwitchInfo->SwitchInfoData.PortGroupTop; + } else if (nodep->pSwitchInfo && nodep->pSwitchInfo->SwitchInfoData.AdaptiveRouting.s.Enable == 0) { + if (format == FORMAT_XML) printf("%*s\n", indent, ""); + else printf("%*sAdaptive Routing Disabled.\n", indent+4, ""); + continue; + } else if (nodep->pSwitchInfo && nodep->pSwitchInfo->SwitchInfoData.PortGroupTop == 0) { + if (format == FORMAT_XML) printf("%*s\n", indent, ""); + else printf("%*sNo port groups defined.\n", indent+4, ""); + continue; + } else { + if (format != FORMAT_XML) printf("%*sNo switch info.\n", indent+4, ""); + } + + // The first test is to check for duplicate port groups. + memcpy(pgt, switchp->PortGroupElements, + pgCount*sizeof(STL_PORTMASK)); + + qsort(pgt,pgCount,sizeof(STL_PORTMASK),compare_masks); + + pgo=pgt[0]; + for (i=1;i\n",indent+4,""); + } + for (i=0; i\n",indent+8,"",i); + XmlPrintHex64( "Value", + switchp->PortGroupElements[i], indent+12); + printf("%*s\n",indent+8,""); + break; + default: + printf("%*sPG %3d : 0x%016llx\n",indent+4,"",i, + (long long unsigned int)switchp->PortGroupElements[i]); + break; + } + } + if (format == FORMAT_XML) { + printf("%*s\n",indent+4,""); + } + } + + // + // Now validate all routes from this switch. + // + { + PortData *portp = FindNodePort(nodep,0); + if (!portp) { + printf("%*sUnable to find port 0\n", + indent, ""); + return; + } + STL_LID slid = portp->PortInfo.LID; + STL_LID dlid; + uint32_t lidCount; + uint32_t arOkay; + uint32_t arCount; + + if (nodep->pSwitchInfo && + nodep->pSwitchInfo->SwitchInfoData.LinearFDBTop != 0) { + lidCount = nodep->pSwitchInfo->SwitchInfoData.LinearFDBTop+1; + } else { + lidCount = switchp->LinearFDBSize; + } + + if (detail>2) { + switch (format) { + case FORMAT_XML: + printf("%*s\n",indent+4,""); + break; + default: + printf("%*sRoute List:\n", indent, ""); + printf("%*sGuid - Lid - Hops - Alts\n", indent+4, ""); + break; + } + } + // Check all DLIDs, even the unused ones. + for(dlid = 1; dlid < lidCount; dlid++) { + uint8_t ep = STL_LFT_PORT_BLOCK(switchp->LinearFDB,dlid); + uint8_t pg; + NodeData *nnodep; + PortData *nportp; + int32_t pl1, pl2; + STL_PORTMASK pgm; + + arOkay = 1; + arCount = 0; + + if (dlid >= switchp->PortGroupFDBSize) + pg = 0xff; + else + pg = STL_PGFT_PORT_BLOCK(switchp->PortGroupFDB,dlid); + // + // Make sure the switch correctly routes to itself. + // LFT[dlid] should be zero and PGFT[dlid] should be 0xff. + // + if (dlid == slid) { + if (ep != 0) switch (format) { + case FORMAT_XML: + printf("%*s\n", + indent+4,""); + break; + default: + printf("%*sERROR: Switch cannot route to itself.\n", + indent, ""); + break; + } + if (pg != 0xff) switch (format) { + case FORMAT_XML: + printf("%*s\n", + indent+4,""); + break; + default: + printf("%*sERROR: Switch is in its own port group " + "forwarding table (LID 0x%x).\n", + indent, "", dlid); + } + continue; + } + + // + // if the dlid is not in use, it should not be in the PGFT. + // + if (ep == 0xff) { + if (pg != 0xff) switch (format) { + case FORMAT_XML: + printf("%*s\n", + indent+4,""); + break; + default: + printf("%*sERROR: LID 0x%x is in the PGFT but not the LFT.\n", + indent, "", dlid); + } + continue; // dlid is not in use. + } else if (ep == 0) + continue; // FIXME MWHEINZ extra LID going to management card? LMC? + else { + if (dlid >= switchp->PortGroupFDBSize) { + switch (format) { + case FORMAT_XML: + printf("%*s\n", + indent+4,""); + break; + default: + printf("%*sERROR: LID 0x%x is in the LFT but not the PGFT.\n", + indent, "", dlid); + } + continue; + } + } + + // Find our LFT neighbor node. + portp = FindNodePort(nodep,ep); + if (!portp) { + printf("%*sUnable to find port %d\n", + indent, "", ep); + return; + } + nportp = portp->neighbor; + nnodep = nportp->nodep; + + // If our neighbor isn't a switch, then the route better + // terminate and PGFT[dlid] should be 0xff. + if (nnodep->NodeInfo.NodeType != STL_NODE_SW) { + STL_LID mask = ~0 << nportp->PortInfo.s1.LMC; + if ((dlid & mask) != (nportp->PortInfo.LID & mask)) { + switch(format) { + case FORMAT_XML: + printf("%*s\n", + indent+4,""); + XmlPrintDec("DLID",dlid,indent+8); + printf("%*s\n",indent+4,""); + break; + default: + printf("%*sPath to 0x%x terminates at the " + "wrong device:\n", indent, "", dlid); + break; + } + } else if (pg != 0xff) { + switch(format) { + case FORMAT_XML: + printf("%*s\n",indent+4,""); + XmlPrintDec("SLID",slid,indent+8); + XmlPrintDec("DLID",dlid,indent+8); + printf("%*s\n",indent+4,""); + break; + default: + printf("%*sERROR: LFT path from 0x%x to 0x%x terminates but is also " + "in the PGFT. (3)\n", + indent, "", slid, dlid); + break; + } + } + pl1 = 1; + } else { + + // Test the LFT route for this DLID. There is another report + // that does this, but we want the hop count to compare the + // PGFT entries against. + pl1 = PGRouteHop(slid, nnodep, dlid, 0, MAX_HOPS, 1, format, indent); + if (pl1 < 0) { + if (format==FORMAT_XML) { + printf("%*s\n",indent+4,""); + } + continue; + } + + // If the DLID is in the PGFT, then test the route from this + // switch to DLID via each port in the matching port group. + if (pg != 0xff) for (i=1, pgm = switchp->PortGroupElements[pg]; + pgm != 0; pgm>>=1, i++) { + if (pgm & 1) { + // FIXME MWHEINZ can we avoid revisiting the same node in the tier0 case? + portp = FindNodePort(nodep,i); + if (!portp) { + printf("%*sUnable to find port %d\n", + indent, "", i); + return; + } + nportp = portp->neighbor; + nnodep = nportp->nodep; + + if (nnodep->NodeInfo.NodeType != STL_NODE_SW) { + STL_LID mask = ~0 << nportp->PortInfo.s1.LMC; + if ((dlid & mask) != (nportp->PortInfo.LID & mask)) switch(format) { + case FORMAT_XML: + printf("%*s\n", + indent+4,""); + XmlPrintDec("DLID",dlid,indent+8); + printf("%*s\n",indent+4,""); + break; + default: + printf("%*sERROR: AR Path from 0x%x to 0x%x " + "terminates at the wrong device.\n", + indent, "", slid, dlid); + } else { + // Even if this is the right device, we still have + // a problem. + switch(format) { + case FORMAT_XML: + printf("%*s\n",indent+4,""); + XmlPrintDec("SLID",slid,indent+8); + XmlPrintDec("DLID",dlid,indent+8); + printf("%*s\n",indent+4,""); + break; + default: + printf("%*sERROR: AR Path from 0x%x to 0x%x terminates but LFT " + "path does not. (4)\n", + indent, "", slid, dlid); + break; + } + } + continue; + } + + // Calculate the length of the path from here to dlid + // via nnodep. It should be the same as the LFT path + // length. + pl2 = PGRouteHop(slid, nnodep, dlid, 0, pl1, 0, format, indent); + if (pl2 < 0) { + POP_NODEDATA(nnodep, + nportp->EndPortLID, 1, + format, indent); + // PGRouteHop detected an error. + if (format==FORMAT_XML) { + printf("%*s\n",indent+4,""); + } + break; // stop looking... + } else if (pl2 != pl1) { + // This path was shorter or longer than the + // linear path. Either way, that's a problem. + switch(format) { + case FORMAT_XML: + printf("%*s\n", + indent+4,""); + XmlPrintDec("SLID",slid,indent+8); + XmlPrintDec("DLID",dlid,indent+8); + XmlPrintDec("PL1",pl1-1,indent+8); + XmlPrintDec("PL2",pl2-1,indent+8); + break; + default: + printf("%*sERROR: Paths from 0x%016"PRIx64", (LID 0x%x)" + " to LID 0x%x have inconsistent hop counts: %d vs %d\n", + indent, "", + nodep->NodeInfo.NodeGUID, slid, dlid, pl1-1, pl2-1); + break; + } + arOkay = 0; + break; + } + arCount++; + } + routeCount++; + } + ((uint8_t*)nodep->context)[dlid]=pl1; + } + if (detail>2 && arOkay) { + PortData *destPortp = FindLid(&g_Fabric,dlid); + EUI64 portGuid = (destPortp)?destPortp->PortGUID:0x0ll; + + switch (format) { + case FORMAT_XML: + printf("%*s\n",indent+4,""); + XmlPrintHex("DLID",dlid, indent+8); + XmlPrintHex("PortGUID", portGuid, indent+8); + XmlPrintHex("HopCount",pl1, indent+8); + XmlPrintDec("Alternates", arCount, indent+8); + printf("%*s\n",indent+4,""); + break; + default: + printf("%*s0x%016llx - 0x%08x - %2d - %2d\n", + indent+4, "", (long long unsigned int)portGuid, + dlid, pl1-1, arCount); + break; + } + } + } + if (detail>2) switch (format) { + case FORMAT_XML: + printf("%*s\n",indent+4,""); + break; + case FORMAT_TEXT: + break; + } + } + if (format == FORMAT_XML) { + printf("%*s\n", indent, ""); + } + } // for ( pList=QListHead(&g_Fabric.AllSWs); + + switch (format) { + case FORMAT_XML: + XmlPrintDec("RoutesTested",routeCount,indent); + printf("%*s\n", indent-4, ""); + break; + default: + printf("%*sAlternate Routes Tested: %d\n", indent, "", routeCount); + break; + } + +} + +FSTATUS ShowMcGroups(FabricData_t *fabricp, Format_t format, int detail, int indent) +{ + LIST_ITEM *n1, *p1; + + if (detail >= 0) + switch (format) { + case FORMAT_TEXT: + if (fabricp->NumOfMcGroups == 1) + printf("Number of MC Group: %d\n", fabricp->NumOfMcGroups); + else + printf("Number of MC Groups: %d\n", fabricp->NumOfMcGroups); + if (detail > 0 ) printf("\n"); + break; + case FORMAT_XML: + printf("%*s%d\n",indent+4,"",fabricp->NumOfMcGroups); + break; + default: + break; + } + +// collecting information about MC Groups + for (n1 = QListHead (&fabricp->AllMcGroups); n1 != NULL; n1 = QListNext(&fabricp->AllMcGroups, n1)) { + McGroupData *pmcgroup = (McGroupData *)QListObj(n1); + //for this PortGID get member group information + // do not get info on empty groups + McMemberData *pMCGM = (McMemberData *)QListObj(QListHead(&pmcgroup->AllMcGroupMembers)); + + if ((pMCGM->MemberInfo.RID.PortGID.AsReg64s.H ==0) && (pMCGM->MemberInfo.RID.PortGID.AsReg64s.L==0)) + continue; + if (detail > 0 ) + switch (format) { + case FORMAT_TEXT: + DisplayGroupRecord (pmcgroup, indent, detail); + printf("Number of Group Members: %d\n", pmcgroup->NumOfMembers); + break; + case FORMAT_XML: + printf("%*s<%s id=\"0x%016"PRIx64":0x%016"PRIx64"\">\n", indent+4, "", "MulticastGroup", + pmcgroup->MGID.AsReg64s.H, pmcgroup->MGID.AsReg64s.L); + printf("%*s%d\n",indent+8,"", pmcgroup->NumOfMembers); + XmlPrintGroupRecord (pmcgroup, indent, detail); + break; + default: + break; + } + + if (detail > 1 ) { + //if the list is not empty) + + for (p1=QListHead(&pmcgroup->AllMcGroupMembers); p1 != NULL; p1 = QListNext(&pmcgroup->AllMcGroupMembers, p1)) { + McMemberData *pMCGG = (McMemberData *)QListObj(p1); + + if ((pMCGG->MemberInfo.RID.PortGID.AsReg64s.H !=0) || (pMCGG->MemberInfo.RID.PortGID.AsReg64s.L!=0)) { + switch (format) { // do not print "zero" members + case FORMAT_TEXT: + printf("PortGid: 0x%016"PRIx64":0x%016"PRIx64" Membership: %s%s%s\n", + pMCGG->MemberInfo.RID.PortGID.AsReg64s.H, + pMCGG->MemberInfo.RID.PortGID.AsReg64s.L, + pMCGG->MemberInfo.JoinFullMember ? "Full " : "", + pMCGG->MemberInfo.JoinNonMember ? "Non " : "", + pMCGG->MemberInfo.JoinSendOnlyMember ? "Sendonly " : ""); + break; + case FORMAT_XML: + printf("%*s<%s id=\"0x%016"PRIx64":0x%016"PRIx64"\">\n", indent+8, "", "McMembers", + pMCGG->MemberInfo.RID.PortGID.AsReg64s.H, pMCGG->MemberInfo.RID.PortGID.AsReg64s.L); + XmlPrintGID("GID",pMCGG->MemberInfo.RID.PortGID,indent+12); + XmlPrintTagHeader("Membership", indent+12); + XmlPrintStr("Full", pMCGG->MemberInfo.JoinFullMember? "1":"0", indent+16); + XmlPrintStr("NonMember", pMCGG->MemberInfo.JoinNonMember? "1":"0", indent+16); + XmlPrintStr("SendOnly", pMCGG->MemberInfo.JoinSendOnlyMember? "1":"0", indent+16); + XmlPrintTagFooter("Membership", indent+12); + McMembershipXmlOutput("Membership_Int", pMCGG,indent+12); + break; + default: + break; + }// case end + + // this list is sorted/keyed by NodeGUID + PortData *portp=FindPortGuid(fabricp, pMCGG->MemberInfo.RID.PortGID.AsReg64s.L); + if (portp !=NULL) { + switch (format) { + case FORMAT_TEXT: + printf("Name: %.*s \n", NODE_DESCRIPTION_ARRAY_SIZE, + g_noname?g_name_marker:(char*)portp->nodep->NodeDesc.NodeString); + break; + case FORMAT_XML: + XmlPrintNodeDesc((char*)portp->nodep->NodeDesc.NodeString, indent+12); + // print end tag + break; + default: + break; + }// end case + } //end if + else { + switch (format) { + case FORMAT_TEXT: + printf("Name: Not available\n"); + break; + default: + break; + } + } + + if (format == FORMAT_XML) + printf("%*s\n", indent+8, ""); + } + } // end for p1 + }//end if detail + + + if (detail > 0) + switch (format) { + case FORMAT_TEXT: + printf("\n"); + break; + case FORMAT_XML: + printf("%*s\n", indent+4, ""); + break; + } + } //end for n1 + + + return FSUCCESS; + +} //end of ShowMcGroups + + + +//output multicast groups +void ShowMulticastGroupsReport(Format_t format, int indent, int detail) +{ + FSTATUS status; + + + if (g_hard) { + fprintf(stderr, "opareport -H -o mcgroups: No report provided for -H\n" ); + g_exitstatus=1; + } + + switch (format) { + case FORMAT_TEXT: + printf("%*sMulticast Group Summary\n",indent, ""); + break; + case FORMAT_XML: + printf("%*s\n",indent,""); + indent+=4; + break; + default: + break; + } + + status = ShowMcGroups(&g_Fabric,format, detail, indent); + + if (status != FSUCCESS) { + fprintf(stderr, "opareport -o mcgroups: Unable to find multicast group members (status=0x%x): %s\n", status, iba_fstatus_msg(status)); + g_exitstatus=1; + } + + switch (format) { + case FORMAT_TEXT: + DisplaySeparator(); + break; + case FORMAT_XML: + indent-=4; + printf("%*s\n",indent, ""); + break; + default: + break; + } + + return; +} //end of ShowMulticastGroupsReport + +// output multicast FDB +void ShowMulticastFDBReport(Point *focus, Format_t format, int indent, int detail) +{ + int ix_lid, ix_port, ix_pos; + LIST_ITEM *pList; + NodeData *nodep; + SwitchData *switchp; + STL_PORTMASK **pPortMask; + uint64 portMask; + uint32 ct_node = 0; + uint32 ct_lid, ct_port; + + switch (format) { + case FORMAT_TEXT: + printf("%*sMulticast FDB Tables\n", indent, ""); + break; + case FORMAT_XML: + printf("%*s\n", indent, ""); + indent+=4; + break; + default: + break; + } + if (! (g_Fabric.flags & FF_ROUTES) && g_snapshot_in_file) { + switch (format) { + case FORMAT_TEXT: + printf("%*sReport skipped: provided snapshot was created without -r option\n", indent, ""); + break; + case FORMAT_XML: + printf("%*s\n", indent, ""); + break; + default: + break; + } + goto done; + } + ShowPointFocus(focus, FIND_FLAG_FABRIC, format, indent, detail); + switch (format) { + case FORMAT_TEXT: + printf( "%*s%u Connected Switches in Fabric%s\n", indent, "", + (unsigned)QListCount(&g_Fabric.AllSWs), detail?":":"" ); + break; + case FORMAT_XML: + XmlPrintDec("ConnectedSwitchCount", (unsigned)QListCount(&g_Fabric.AllSWs), indent); + break; + default: + break; + } + + // Report Multicast FDB + for ( pList=QListHead(&g_Fabric.AllSWs); pList != NULL; + pList = QListNext(&g_Fabric.AllSWs, pList) ) { + nodep = QListObj(pList); + switchp = nodep->switchp; + + if (!CompareNodePoint(nodep, focus)) + continue; + + if (!switchp || !switchp->MulticastFDB[0]) + continue; + + if (detail) { + if (!ct_node) { + ShowNodeBriefSummaryHeadings(format, indent, 0); + switch (format) { + case FORMAT_TEXT: + printf("%*s LID Ports\n", indent+4, ""); + break; + case FORMAT_XML: + break; + default: + break; + } + } + ShowNodeBriefSummary(nodep, focus, FALSE, format, indent, 0); + ct_lid = 0; + const size_t NumMcfdbEntries = switchp->MulticastFDBSize - STL_LID_MULTICAST_BEGIN; + + for ( ix_lid = 0, pPortMask = switchp->MulticastFDB; ix_lid < NumMcfdbEntries; ix_lid++ ) { + + for ( ix_pos = 0; ix_pos < STL_NUM_MFT_POSITIONS_MASK; ix_pos++) { + + portMask = pPortMask[ix_pos][ix_lid]; + if (!portMask) + continue; + + switch (format) { + case FORMAT_TEXT: + printf("%*s0x%08x", indent+4, "", (uint32)(ix_lid + STL_LID_MULTICAST_BEGIN)); + break; + case FORMAT_XML: + if (!ix_pos && !ct_lid++) + printf("%*s\n", indent+4, ""); + printf( "%*s", indent+8, "", + ix_pos, (ix_lid + STL_LID_MULTICAST_BEGIN) ); + break; + default: + break; + } + + switch (format) { + case FORMAT_TEXT: + ct_port = 0; + for (ix_port = 0; ix_port < STL_PORT_MASK_WIDTH; portMask >>= 1, ix_port++) { + if (!(portMask & 1)) + continue; + + printf(" %02u", (uint32)(ix_pos*STL_PORT_MASK_WIDTH)+ix_port); + if (++ct_port%20 == 0) + printf("\n%*s ", indent+4, ""); + } // End of for (ix_port = 0; ix_port < STL_PORT_MASK_WIDTH + break; + case FORMAT_XML: + printf("0x%"PRIx64, portMask); + break; + default: + break; + } + + switch (format) { + case FORMAT_TEXT: + printf("\n"); + break; + case FORMAT_XML: + printf("\n"); + break; + default: + break; + } + } // End of for ( ix_pos = 0; ix_pos < STL_NUM_MFT_POSITIONS_MASK + } // End of for ( ix_lid = 0; pPortMask = switchp->MulticastFDB + + switch (format) { + case FORMAT_XML: + if (ct_lid) + printf("%*s\n", indent+4, ""); + printf("%*s\n", indent, ""); + break; + default: + break; + } + + } // End of if (detail) + + ct_node++; + + } // End of for (pList=QListHead(&g_Fabric.AllSWs); pList != NULL + +done: + switch (format) { + case FORMAT_TEXT: + printf("%*s%d Reported Switch(es)\n", indent, "", ct_node); + DisplaySeparator(); + break; + case FORMAT_XML: + XmlPrintDec("ReportedSwitchCount", (unsigned)ct_node, indent); + indent-=4; + printf("%*s\n", indent, ""); + break; + default: + break; + } + +} // End of ShowMulticastFDBReport() + + +// output port usage in linear FDB +void ShowPortUsageReport(Point *focus, Format_t format, int indent, int detail) +{ + int ix_lid, ix_port, ix_lmc; + LIST_ITEM *pList; + cl_map_item_t *pMap, *pMap_2; + NodeData *nodep; + SwitchData *switchp; + PortData *portp; + uint32 ct_node = 0; + uint32 ct_port; + uint16 tb_nodeData[g_max_lft+1]; + uint32 tb_usageCaAll[256]; + uint32 tb_usageCaBase[256]; + uint32 tb_usageSwitch[256]; + + switch (format) { + case FORMAT_TEXT: + printf("%*sPort Usage\n", indent, ""); + break; + case FORMAT_XML: + printf("%*s\n", indent, ""); + indent+=4; + break; + default: + break; + } + if (! (g_Fabric.flags & FF_ROUTES) && g_snapshot_in_file) { + switch (format) { + case FORMAT_TEXT: + printf("%*sReport skipped: provided snapshot was created without -r option\n", indent, ""); + break; + case FORMAT_XML: + printf("%*s\n", indent, ""); + break; + default: + break; + } + goto done; + } + ShowPointFocus(focus, FIND_FLAG_FABRIC, format, indent, detail); + switch (format) { + case FORMAT_TEXT: + printf( "%*s%u Connected Switch(es) in Fabric%s\n", indent, "", + (unsigned)QListCount(&g_Fabric.AllSWs), detail?":":"" ); + break; + case FORMAT_XML: + XmlPrintDec("ConnectedSwitchCount", (unsigned)QListCount(&g_Fabric.AllSWs), indent); + break; + default: + break; + } + + // Report Port Usage in Linear FDB + // Make list of node type and lmc by LID + memset(tb_nodeData, 0xFF, (g_max_lft+1) * sizeof(uint16)); + for ( pMap=cl_qmap_head(&g_Fabric.AllNodes); + pMap != cl_qmap_end(&g_Fabric.AllNodes); + pMap = cl_qmap_next(pMap) ) { + nodep = PARENT_STRUCT(pMap, NodeData, AllNodesEntry); + + for ( pMap_2=cl_qmap_head(&nodep->Ports); pMap_2 != cl_qmap_end(&nodep->Ports); + pMap_2 = cl_qmap_next(pMap_2) ) { + portp = PARENT_STRUCT(pMap_2, PortData, NodePortsEntry); + + if ((nodep->NodeInfo.NodeType == STL_NODE_FI) || + ((nodep->NodeInfo.NodeType == STL_NODE_SW) && (portp->PortNum ==0))) { + if ( portp->PortInfo.LID && + (portp->PortInfo.LID <= g_max_lft) ) { + for ( ix_lmc = (1 << portp->PortInfo.s1.LMC) - 1; + ix_lmc >= 0; ix_lmc-- ) { + tb_nodeData[portp->PortInfo.LID + ix_lmc] = + (ix_lmc << 8) + nodep->NodeInfo.NodeType; + } + } + } + } // End of for ( pMap_2=cl_qmap_head(&nodep->Ports) + + } // End of for ( pMap=cl_qmap_head(&g_Fabric.AllNodes) + + for ( pList=QListHead(&g_Fabric.AllSWs); pList != NULL; + pList = QListNext(&g_Fabric.AllSWs, pList) ) { + nodep = QListObj(pList); + switchp = nodep->switchp; + + if (! CompareNodePoint(nodep, focus)) + continue; + + if (!switchp || !switchp->LinearFDB) + continue; + + if (detail) { + ShowNodeBriefSummaryHeadings(format, indent, 0); + switch (format) { + case FORMAT_TEXT: + printf("%*sPort Total FI-All FI-Base Switch\n", indent+4, ""); + ShowNodeBriefSummary(nodep, focus, FALSE, format, indent, 0); + break; + case FORMAT_XML: + ShowNodeBriefSummary(nodep, focus, FALSE, format, indent, 0); + break; + default: + break; + } + + memset(tb_usageCaAll, 0, 256 * sizeof(uint32)); + memset(tb_usageCaBase, 0, 256 * sizeof(uint32)); + memset(tb_usageSwitch, 0, 256 * sizeof(uint32)); + + for (ix_lid = 0; ix_lid < switchp->LinearFDBSize; ix_lid++) { + if ( STL_LFT_PORT_BLOCK(switchp->LinearFDB, ix_lid) == 0 || STL_LFT_PORT_BLOCK(switchp->LinearFDB, ix_lid) == 0xFF ) + continue; + + ix_lmc = (tb_nodeData[ix_lid] >> 8) & 0xFF; + ix_port = STL_LFT_PORT_BLOCK(switchp->LinearFDB, ix_lid); + switch (tb_nodeData[ix_lid] & 0xFF) { + case STL_NODE_FI: + tb_usageCaAll[ix_port]++; + + if (!ix_lmc) + tb_usageCaBase[ix_port]++; + break; + + case STL_NODE_SW: + tb_usageSwitch[ix_port]++; + break; + + default: + break; + + } // End of switch (tb_nodeData[ix_lid] & 0xFF) + + } // End of for (ix_lid = 0; ix_lid < switchp->LinearFDBSize + + ct_node++; + ct_port = 0; + for (ix_port = 0; ix_port < 256; ix_port++) { + if ( !tb_usageCaAll[ix_port] && !tb_usageCaBase[ix_port] && + !tb_usageSwitch[ix_port]) + continue; + + switch (format) { + case FORMAT_TEXT: + printf( "%*s%3u %5u %5u %5u %5u\n", indent+4, "", + (uint32)ix_port, tb_usageCaAll[ix_port] + + tb_usageSwitch[ix_port], + tb_usageCaAll[ix_port], tb_usageCaBase[ix_port], + tb_usageSwitch[ix_port]); + break; + case FORMAT_XML: + if (!ct_port++) + printf("%*s\n", indent+4, ""); + printf("%*s\n", indent+8, "", ix_port); + XmlPrintDec( "TotalLid", tb_usageCaAll[ix_port] + + tb_usageSwitch[ix_port], indent+12 ); + if (tb_usageCaAll[ix_port]) + XmlPrintDec("CaAllLid", tb_usageCaAll[ix_port], indent+12); + if (tb_usageCaBase[ix_port]) + XmlPrintDec("CaBaseLid", tb_usageCaBase[ix_port], indent+12); + if (tb_usageSwitch[ix_port]) + XmlPrintDec("SwitchLid", tb_usageSwitch[ix_port], indent+12); + printf("%*s\n", indent+8, ""); + break; + default: + break; + } + + } // End of for (ix_port = 0; ix_port < 256; ix_port++) + + switch (format) { + case FORMAT_XML: + if (ct_port) + printf("%*s\n", indent+4, ""); + printf("%*s\n", indent, ""); + break; + default: + break; + } + + } // End of if (detail) + + } // End of for ( pList=QListHead(&g_Fabric.AllSWs); pList != NULL + +done: + switch (format) { + case FORMAT_TEXT: + printf("%*s%d Reported Switch(es)\n", indent, "", ct_node); + DisplaySeparator(); + break; + case FORMAT_XML: + XmlPrintDec("ReportedSwitchCount", (unsigned)ct_node, indent); + indent-=4; + printf("%*s\n", indent, ""); + break; + default: + break; + } + +} // End of ShowPortUsageReport() + +struct ShowPathContext { + Format_t format; + int indent; + int detail; +}; + +void ReportCallback(PortData *portp1, PortData *portp2, STL_LID dlid, boolean isBaseLid, boolean flag /* TRUE=uplink or recv */, void *context) +{ + struct ShowPathContext *ShowPathContext = (struct ShowPathContext*)context; + int indent = ShowPathContext->indent; + + switch (ShowPathContext->format) { + case FORMAT_TEXT: + // output portp1 + // output -> dlid portp2 + printf("%*s 0x%016"PRIx64" %3u %s %.*s\n", + indent, "", + portp1->nodep->NodeInfo.NodeGUID, + portp1->PortNum, + StlNodeTypeToText(portp1->nodep->NodeInfo.NodeType), + NODE_DESCRIPTION_ARRAY_SIZE, + g_noname?g_name_marker:(char*)portp1->nodep->NodeDesc.NodeString); + printf("%*s-> 0x%08x 0x%016"PRIx64" %3u %s %.*s\n", + indent, "", dlid, + portp2->nodep->NodeInfo.NodeGUID, + portp2->PortNum, + StlNodeTypeToText(portp2->nodep->NodeInfo.NodeType), + NODE_DESCRIPTION_ARRAY_SIZE, + g_noname?g_name_marker:(char*)portp2->nodep->NodeDesc.NodeString); + break; + case FORMAT_XML: + printf("%*s\n", indent, ""); + + printf("%*s\n", indent+4, "", + portp1->nodep->NodeInfo.NodeGUID, portp1->PortNum); + XmlPrintHex64("NodeGUID", + portp1->nodep->NodeInfo.NodeGUID, indent+8); + if (portp1->PortGUID) + XmlPrintHex64("PortGUID", portp1->PortGUID, indent+8); + XmlPrintDec("PortNum", portp1->PortNum, indent+8); + XmlPrintNodeType(portp1->nodep->NodeInfo.NodeType, + indent+8); + XmlPrintNodeDesc((char*)portp1->nodep->NodeDesc.NodeString, indent+8); + printf("%*s\n", indent+4, ""); + + printf("%*s\n", indent+4, "", + portp2->nodep->NodeInfo.NodeGUID, portp2->PortNum); + XmlPrintLID("DLID", dlid, indent+8); + XmlPrintHex64("NodeGUID", + portp2->nodep->NodeInfo.NodeGUID, indent+8); + if (portp2->PortGUID) + XmlPrintHex64("PortGUID", portp2->PortGUID, indent+8); + XmlPrintDec("PortNum", portp2->PortNum, indent+8); + XmlPrintNodeType(portp2->nodep->NodeInfo.NodeType, + indent+8); + XmlPrintNodeDesc((char*)portp2->nodep->NodeDesc.NodeString, indent+8); + printf("%*s\n", indent+4, ""); + printf("%*s\n", indent, ""); + break; + default: + break; + } +} + +// Standard Deviation is computed as: +// SQRT(S0 * S2 - (S1*S1))/S0 +// Where: +// S0 = sum(data^0) = N +// S1 = sum(data^1) = sum(data) [held in Total] +// S2 = sum(data^2) [held in Total2] +struct statistics_s { + uint32 min; // must initialize to IB_UINT32_MAX + uint32 max; + uint32 total; // total of datum + uint64 total2; // total of datum^2 + uint32 avg; + float stddev; +}; + +// add a single data point to the statistical variables +static _inline +void add_datum(struct statistics_s *stat, uint32 datum) +{ + stat->min = MIN(datum, stat->min); + stat->max = MAX(datum, stat->max); + stat->total += datum; + stat->total2 += ((uint64)datum * (uint64)datum); +} + +// add data points tabulated for stats2 to the running stat statistics +static _inline +void add_datums(struct statistics_s *stat, struct statistics_s *stat2) +{ + stat->min = MIN(stat2->min, stat->min); + stat->max = MAX(stat2->max, stat->max); + stat->total += stat2->total; + stat->total2 += stat2->total2; +} + +// compute summary statistics +static _inline +void compute_statistics(struct statistics_s *stat, uint32 n) +{ + if (n) { + stat->avg = stat->total / n; + stat->stddev = sqrt(n * stat->total2 + - ((uint64)(stat->total)*(uint64)(stat->total)))/n; + } else { + stat->min = 0; // make output a litle cleaner + } +} + +// print text format of statistics +static _inline +void print_text_statistics(int indent, const char* title, struct statistics_s *stat) +{ + printf("%*s%s Total: %u Avg: %u StdDev: %u\n", indent, "", title, + stat->total, stat->avg, (unsigned)stat->stddev); + printf("%*s Min: %u Max: %u\n", (int)(indent+strlen(title)-1), "", + stat->min, stat->max); +} + + +// print XML format of statistics +static _inline +void print_xml_statistics(int indent, const char* title, struct statistics_s *stat) +{ + char buf[64]; + + snprintf(buf, sizeof(buf), "%sTotal", title); + XmlPrintDec(buf, (unsigned)stat->total, indent); + snprintf(buf, sizeof(buf), "%sAvg", title); + XmlPrintDec(buf, (unsigned)stat->avg, indent); + snprintf(buf, sizeof(buf),"%sStdDev", title); + XmlPrintDec(buf, (unsigned)stat->stddev, indent); + snprintf(buf, sizeof(buf), "%sMin", title); + XmlPrintDec(buf, (unsigned)stat->min, indent); + snprintf(buf, sizeof(buf), "%sMax", title); + XmlPrintDec(buf, (unsigned)stat->max, indent); +} + +// output path usage in linear FDBs +void ShowPathUsageReport(Point *focus, Format_t format, int indent, int detail) +{ + LIST_ITEM *pList; + NodeData *nodep; + SwitchData *switchp; + uint32 ct_node = 0; + uint32 ct_port; + FSTATUS status; + uint32 totalPorts = 0; + uint32 totalPaths; + uint32 badPaths; + struct ShowPathContext ShowPathContext = { format:format, detail:detail }; + + struct statistics_s fabricRecvBasePaths = { min:IB_UINT32_MAX }; + struct statistics_s fabricXmitBasePaths = { min:IB_UINT32_MAX }; + + struct statistics_s fabricRecvNonBasePaths = { min:IB_UINT32_MAX }; + struct statistics_s fabricXmitNonBasePaths = { min:IB_UINT32_MAX }; + + struct statistics_s fabricRecvAllPaths = { min:IB_UINT32_MAX }; + struct statistics_s fabricXmitAllPaths = { min:IB_UINT32_MAX }; + + if (! (g_Fabric.flags & FF_ROUTES) && g_snapshot_in_file) { + switch (format) { + case FORMAT_TEXT: + printf("%*sReport skipped: provided snapshot was created without -r option\n", indent, ""); + break; + case FORMAT_XML: + printf("%*s\n", indent, ""); + break; + default: + break; + } + return; + } + /* If there is a node pair list or node list then only tabulate routes in the focus */ + status = TabulateCARoutes(&g_Fabric, focus, &totalPaths, &badPaths, FALSE); + if (status != FSUCCESS) { + fprintf(stderr, "opareport: -o pathusage: Unable to tabulate routes (status=0x%x): %s\n", status, iba_fstatus_msg(status)); + g_exitstatus = 1; + } + + switch (format) { + case FORMAT_TEXT: + printf("%*sPath Usage\n", indent, ""); + break; + case FORMAT_XML: + printf("%*s\n", indent, ""); + indent+=4; + break; + default: + break; + } + ShowPointFocus(focus, FIND_FLAG_FABRIC, format, indent, detail); + switch (format) { + case FORMAT_TEXT: + printf( "%*s%u Connected Switch(es) in Fabric%s\n", indent, "", + (unsigned)QListCount(&g_Fabric.AllSWs), detail?":":"" ); + break; + case FORMAT_XML: + XmlPrintDec("ConnectedSwitchCount", (unsigned)QListCount(&g_Fabric.AllSWs), indent); + break; + default: + break; + } + + // Report Path Usage in Linear FDB + for ( pList=QListHead(&g_Fabric.AllSWs); pList != NULL; + pList = QListNext(&g_Fabric.AllSWs, pList) ) { + cl_map_item_t *p; + + struct statistics_s swRecvBasePaths = { min:IB_UINT32_MAX }; + struct statistics_s swXmitBasePaths = { min:IB_UINT32_MAX }; + + struct statistics_s swRecvNonBasePaths = { min:IB_UINT32_MAX }; + struct statistics_s swXmitNonBasePaths = { min:IB_UINT32_MAX }; + + struct statistics_s swRecvAllPaths = { min:IB_UINT32_MAX }; + struct statistics_s swXmitAllPaths = { min:IB_UINT32_MAX }; + + nodep = QListObj(pList); + switchp = nodep->switchp; + + if (!switchp || !switchp->LinearFDB) + continue; + + //If haveSW flag is set, then Switches are present in the focus + if(PointHaveSw(focus)) { + // filter on switches that are listed in the focus + if( ! CompareNodePoint(nodep, focus)) + continue; + } + + if (detail) { + switch (format) { + case FORMAT_TEXT: + printf("%*sNodeGUID Type Name\n", indent, ""); + if (detail > 1) + printf("%*sPort Rcv: FI-All FI-Base FI-NonBase Xmt: FI-All FI-Base FI-NonBase\n", indent+4, ""); + if (detail > 2) + printf("%*s DLID NodeGUID Port Type Name\n", indent+8, ""); + printf("%*s0x%016"PRIx64" %s %s\n", indent, "", + nodep->NodeInfo.NodeGUID, + StlNodeTypeToText(nodep->NodeInfo.NodeType), + (char*)nodep->NodeDesc.NodeString); + break; + case FORMAT_XML: + printf( "%*s\n", indent, "", + nodep->NodeInfo.NodeGUID ); + XmlPrintHex64( "NodeGUID", + nodep->NodeInfo.NodeGUID, indent+4 ); + XmlPrintStr( "NodeType", + StlNodeTypeToText(nodep->NodeInfo.NodeType), + indent+4 ); + XmlPrintStr( "NodeDesc", + (char*)nodep->NodeDesc.NodeString, indent+4 ); + break; + default: + break; + } + indent += 4; + } + + ct_node++; + ct_port = 0; + for (p=cl_qmap_head(&nodep->Ports); p != cl_qmap_end(&nodep->Ports); p = cl_qmap_next(p)) { + PortData *portp= PARENT_STRUCT(p, PortData, NodePortsEntry); + uint32 recvNonBasePaths; + uint32 xmitNonBasePaths; + + if (! portp->PortNum) + continue; // skip switch port 0 + + // only report on ISLs, FI-SW links are boring + if (! portp->neighbor + || portp->neighbor->nodep->NodeInfo.NodeType != STL_NODE_SW) + continue; + + totalPorts++; + ct_port++; + recvNonBasePaths = portp->analysisData.routes.recvAllPaths - portp->analysisData.routes.recvBasePaths; + xmitNonBasePaths = portp->analysisData.routes.xmitAllPaths - portp->analysisData.routes.xmitBasePaths; + + add_datum(&swRecvBasePaths, portp->analysisData.routes.recvBasePaths); + add_datum(&swXmitBasePaths, portp->analysisData.routes.xmitBasePaths); + + add_datum(&swRecvNonBasePaths, recvNonBasePaths); + add_datum(&swXmitNonBasePaths, xmitNonBasePaths); + + add_datum(&swRecvAllPaths, portp->analysisData.routes.recvAllPaths); + add_datum(&swXmitAllPaths, portp->analysisData.routes.xmitAllPaths); + + if (detail > 1) { + switch (format) { + case FORMAT_TEXT: + printf( "%*s%3u %10u %10u %10u %10u %10u %10u\n", indent, "", + (uint32)portp->PortNum, + portp->analysisData.routes.recvAllPaths, portp->analysisData.routes.recvBasePaths, + recvNonBasePaths, + portp->analysisData.routes.xmitAllPaths, portp->analysisData.routes.xmitBasePaths, + xmitNonBasePaths); + if (detail > 2) { + ShowPathContext.indent = indent+4; + (void)ReportCARoutes(&g_Fabric, portp, ReportCallback, + &ShowPathContext, FALSE); + } + break; + case FORMAT_XML: + if (1 == ct_port) + printf("%*s\n", indent, ""); + printf("%*s\n", indent+4, "", portp->PortNum); + XmlPrintDec("CaRecvAllPath", portp->analysisData.routes.recvAllPaths, indent+8); + XmlPrintDec("CaRecvBaseLid", portp->analysisData.routes.recvBasePaths, indent+8); + XmlPrintDec("CaRecvNonBaseLid", recvNonBasePaths, indent+8); + XmlPrintDec("CaXmitAllPath", portp->analysisData.routes.xmitAllPaths, indent+8); + XmlPrintDec("CaXmitBaseLid", portp->analysisData.routes.xmitBasePaths, indent+8); + XmlPrintDec("CaXmitNonBaseLid", xmitNonBasePaths, indent+8); + if (detail > 2) { + ShowPathContext.indent = indent+8; + (void)ReportCARoutes(&g_Fabric, portp, ReportCallback, + &ShowPathContext, FALSE); + } + printf("%*s\n", indent+4, ""); + break; + default: + break; + } + } + + } // End of for all ports + + if (detail > 1 && ct_port && format == FORMAT_XML) + printf("%*s\n", indent, ""); + + // if there are no paths through switch, add_datums is no net change + add_datums(&fabricRecvBasePaths, &swRecvBasePaths); + add_datums(&fabricXmitBasePaths, &swXmitBasePaths); + + add_datums(&fabricRecvNonBasePaths, &swRecvNonBasePaths); + add_datums(&fabricXmitNonBasePaths, &swXmitNonBasePaths); + + add_datums(&fabricRecvAllPaths, &swRecvAllPaths); + add_datums(&fabricXmitAllPaths, &swXmitAllPaths); + + compute_statistics(&swRecvBasePaths, ct_port); + compute_statistics(&swXmitBasePaths, ct_port); + + compute_statistics(&swRecvNonBasePaths, ct_port); + compute_statistics(&swXmitNonBasePaths, ct_port); + + compute_statistics(&swRecvAllPaths, ct_port); + compute_statistics(&swXmitAllPaths, ct_port); + + if (detail) { + switch (format) { + case FORMAT_TEXT: + printf("%*s%d Reported Port(s)\n", indent, "", ct_port); + if (ct_port) { + print_text_statistics(indent, "Recv All Paths: ", &swRecvAllPaths); + print_text_statistics(indent, "Recv Base Paths: ", &swRecvBasePaths); + print_text_statistics(indent, "Recv Non-Base Paths:", &swRecvNonBasePaths); + print_text_statistics(indent, "Xmit All Paths: ", &swXmitAllPaths); + print_text_statistics(indent, "Xmit Base Paths: ", &swXmitBasePaths); + print_text_statistics(indent, "Xmit Non-Base Paths:", &swXmitNonBasePaths); + } + indent-=4; + break; + case FORMAT_XML: + XmlPrintDec("ReportedPortCount", (unsigned)ct_port, indent); + if (ct_port) { + print_xml_statistics(indent, "RecvAllPaths", &swRecvAllPaths); + print_xml_statistics(indent, "RecvBasePaths", &swRecvBasePaths); + print_xml_statistics(indent, "RecvNonBasePaths", &swRecvNonBasePaths); + print_xml_statistics(indent, "XmitAllPaths", &swXmitAllPaths); + print_xml_statistics(indent, "XmitBasePaths", &swXmitBasePaths); + print_xml_statistics(indent, "XmitNonBasePaths", &swXmitNonBasePaths); + } + indent-=4; + printf("%*s\n", indent, ""); + break; + default: + break; + } + } // End of if (detail) + + } // End of for ( pList=QListHead(&g_Fabric.AllSWs); pList != NULL + + if (totalPorts) { + compute_statistics(&fabricRecvBasePaths, totalPorts); + compute_statistics(&fabricXmitBasePaths, totalPorts); + + compute_statistics(&fabricRecvNonBasePaths, totalPorts); + compute_statistics(&fabricXmitNonBasePaths, totalPorts); + + compute_statistics(&fabricRecvAllPaths, totalPorts); + compute_statistics(&fabricXmitAllPaths, totalPorts); + } + + switch (format) { + case FORMAT_TEXT: + printf("%*s%d Reported Switch(es)\n", indent, "", ct_node); + printf("%*s%d Reported Port(s)\n", indent, "", totalPorts); + printf("%*s%d Incomplete Route(s)\n", indent, "", badPaths); + if (totalPorts) { + print_text_statistics(indent, "Recv All Paths: ", &fabricRecvAllPaths); + print_text_statistics(indent, "Recv Base Paths: ", &fabricRecvBasePaths); + print_text_statistics(indent, "Recv Non-Base Paths:", &fabricRecvNonBasePaths); + print_text_statistics(indent, "Xmit All Paths: ", &fabricXmitAllPaths); + print_text_statistics(indent, "Xmit Base Paths: ", &fabricXmitBasePaths); + print_text_statistics(indent, "Xmit Non-Base Paths:", &fabricXmitNonBasePaths); + } + break; + case FORMAT_XML: + XmlPrintDec("ReportedSwitchCount", (unsigned)ct_node, indent); + XmlPrintDec("ReportedPortCount", (unsigned)totalPorts, indent); + XmlPrintDec("IncompleteRoutes", (unsigned)badPaths, indent); + if (totalPorts) { + print_xml_statistics(indent, "RecvAllPaths", &fabricRecvAllPaths); + print_xml_statistics(indent, "RecvBasePaths", &fabricRecvBasePaths); + print_xml_statistics(indent, "RecvNonBasePaths", &fabricRecvNonBasePaths); + print_xml_statistics(indent, "XmitAllPaths", &fabricXmitAllPaths); + print_xml_statistics(indent, "XmitBasePaths", &fabricXmitBasePaths); + print_xml_statistics(indent, "XmitNonBasePaths", &fabricXmitNonBasePaths); + } + break; + default: + break; + } + switch (format) { + case FORMAT_TEXT: + DisplaySeparator(); + break; + case FORMAT_XML: + indent-=4; + printf("%*s\n", indent, ""); + break; + default: + break; + } +} // End of ShowPathUsageReport() + +// output path usage in linear FDBs +void ShowTreePathUsageReport(Point *focus, Format_t format, int indent, + int detail) +{ + LIST_ITEM *pList; + NodeData *nodep; + SwitchData *switchp; + uint32 ct_node = 0; + uint32 ct_port = 0; + FSTATUS status; + uint32 totalPorts = 0; + uint32 totalPaths; + uint32 badPaths; + struct ShowPathContext ShowPathContext = { format:format, detail:detail }; + + uint32 fabricUplinkCount = 0; + uint32 fabricDownlinkCount = 0; + + struct statistics_s fabricDownlinkBasePaths = { min:IB_UINT32_MAX }; + struct statistics_s fabricUplinkBasePaths = { min:IB_UINT32_MAX }; + + struct statistics_s fabricDownlinkNonBasePaths = { min:IB_UINT32_MAX }; + struct statistics_s fabricUplinkNonBasePaths = { min:IB_UINT32_MAX }; + + struct statistics_s fabricDownlinkAllPaths = { min:IB_UINT32_MAX }; + struct statistics_s fabricUplinkAllPaths = { min:IB_UINT32_MAX }; + + if (! (g_Fabric.flags & FF_ROUTES) && g_snapshot_in_file) { + switch (format) { + case FORMAT_TEXT: + printf("%*sReport skipped: provided snapshot was created without -r option\n", indent, ""); + break; + case FORMAT_XML: + printf("%*s\n", indent, ""); + break; + default: + break; + } + return; + } + /* If there is a focus then only tabulate routes in the focus */ + status = TabulateCARoutes(&g_Fabric, focus, &totalPaths, &badPaths, TRUE); + if (status != FSUCCESS) { + fprintf(stderr, "opareport: -o treepathusage: Unable to tabulate routes (status=0x%x): %s\n", status, iba_fstatus_msg(status)); + g_exitstatus = 1; + } + + switch (format) { + case FORMAT_TEXT: + printf("%*sTree Path Usage\n", indent, ""); + break; + case FORMAT_XML: + printf("%*s\n", indent, ""); + indent+=4; + break; + default: + break; + } + ShowPointFocus(focus, FIND_FLAG_FABRIC, format, indent, detail); + switch (format) { + case FORMAT_TEXT: + printf( "%*s%u Connected Switch(es) in Fabric%s\n", indent, "", + (unsigned)QListCount(&g_Fabric.AllSWs), detail?":":"" ); + break; + case FORMAT_XML: + XmlPrintDec("ConnectedSwitchCount", (unsigned)QListCount(&g_Fabric.AllSWs), indent); + break; + default: + break; + } + + // Report Tree Path Usage in Linear FDB + for ( pList=QListHead(&g_Fabric.AllSWs); pList != NULL; + pList = QListNext(&g_Fabric.AllSWs, pList) ) { + cl_map_item_t *p; + uint32 swUplinkCount = 0; + uint32 swDownlinkCount = 0; + struct statistics_s swDownlinkBasePaths = { min:IB_UINT32_MAX }; + struct statistics_s swUplinkBasePaths = { min:IB_UINT32_MAX }; + + struct statistics_s swDownlinkNonBasePaths = { min:IB_UINT32_MAX }; + struct statistics_s swUplinkNonBasePaths = { min:IB_UINT32_MAX }; + + struct statistics_s swDownlinkAllPaths = { min:IB_UINT32_MAX }; + struct statistics_s swUplinkAllPaths = { min:IB_UINT32_MAX }; + + nodep = QListObj(pList); + switchp = nodep->switchp; + + if (!switchp || !switchp->LinearFDB) + continue; + + //If haveSW flag is set, then Switches are present in the focus + if(PointHaveSw(focus)) { + // filter on switches that are listed in the focus + if( ! CompareNodePoint(nodep, focus)) + continue; + } + + if (detail) { + switch (format) { + case FORMAT_TEXT: + printf("%*sNodeGUID Type Tier Name\n", indent, ""); + if (detail > 1) + printf("%*sPort Up: FI-All FI-Base FI-NonBase Down: FI-All FI-Base FI-NonBase\n", indent+4, ""); + if (detail > 2) + printf("%*s DLID NodeGUID Port Type Name\n", indent+8, ""); + printf("%*s0x%016"PRIx64" %s %4u %s\n", indent, "", + nodep->NodeInfo.NodeGUID, + StlNodeTypeToText(nodep->NodeInfo.NodeType), + nodep->analysis, + (char*)nodep->NodeDesc.NodeString); + break; + case FORMAT_XML: + printf( "%*s\n", indent, "", + nodep->NodeInfo.NodeGUID ); + XmlPrintHex64( "NodeGUID", + nodep->NodeInfo.NodeGUID, indent+4 ); + XmlPrintStr( "NodeType", + StlNodeTypeToText(nodep->NodeInfo.NodeType), + indent+4 ); + XmlPrintDec( "Tier", nodep->analysis, indent+4 ); + XmlPrintStr( "NodeDesc", + (char*)nodep->NodeDesc.NodeString, indent+4 ); + break; + default: + break; + } + indent += 4; + } + + ct_node++; + ct_port = 0; + for (p=cl_qmap_head(&nodep->Ports); p != cl_qmap_end(&nodep->Ports); p = cl_qmap_next(p)) { + PortData *portp= PARENT_STRUCT(p, PortData, NodePortsEntry); + uint32 downlinkNonBasePaths; + uint32 uplinkNonBasePaths; + + if (! portp->PortNum) + continue; // skip switch port 0 + + // only report on ISLs, FI-SW links are boring + if (! portp->neighbor + || portp->neighbor->nodep->NodeInfo.NodeType != STL_NODE_SW) + continue; + + totalPorts++; + ct_port++; + if (portp->analysisData.fatTreeRoutes.uplinkAllPaths) + swUplinkCount++; + if (portp->analysisData.fatTreeRoutes.downlinkAllPaths) + swDownlinkCount++; + downlinkNonBasePaths = portp->analysisData.fatTreeRoutes.downlinkAllPaths - portp->analysisData.fatTreeRoutes.downlinkBasePaths; + uplinkNonBasePaths = portp->analysisData.fatTreeRoutes.uplinkAllPaths - portp->analysisData.fatTreeRoutes.uplinkBasePaths; + + add_datum(&swDownlinkBasePaths, portp->analysisData.fatTreeRoutes.downlinkBasePaths); + add_datum(&swUplinkBasePaths, portp->analysisData.fatTreeRoutes.uplinkBasePaths); + + add_datum(&swDownlinkNonBasePaths, downlinkNonBasePaths); + add_datum(&swUplinkNonBasePaths, uplinkNonBasePaths); + + add_datum(&swDownlinkAllPaths, portp->analysisData.fatTreeRoutes.downlinkAllPaths); + add_datum(&swUplinkAllPaths, portp->analysisData.fatTreeRoutes.uplinkAllPaths); + if (detail > 1) { + switch (format) { + case FORMAT_TEXT: + printf( "%*s%3u %10u %10u %10u %10u %10u %10u\n", indent, "", + (uint32)portp->PortNum, + portp->analysisData.fatTreeRoutes.uplinkAllPaths, portp->analysisData.fatTreeRoutes.uplinkBasePaths, + uplinkNonBasePaths, + portp->analysisData.fatTreeRoutes.downlinkAllPaths, portp->analysisData.fatTreeRoutes.downlinkBasePaths, + downlinkNonBasePaths); + if (detail > 2) { + ShowPathContext.indent = indent+4; + (void)ReportCARoutes(&g_Fabric, portp, ReportCallback, + &ShowPathContext, TRUE); + } + break; + case FORMAT_XML: + if (1 == ct_port) + printf("%*s\n", indent, ""); + printf("%*s\n", indent+4, "", portp->PortNum); + XmlPrintDec("CaUplinkAllPath", portp->analysisData.fatTreeRoutes.uplinkAllPaths, indent+8); + XmlPrintDec("CaUplinkBaseLid", portp->analysisData.fatTreeRoutes.uplinkBasePaths, indent+8); + XmlPrintDec("CaUplinkNonBaseLid", uplinkNonBasePaths, indent+8); + XmlPrintDec("CaDownlinkAllPath", portp->analysisData.fatTreeRoutes.downlinkAllPaths, indent+8); + XmlPrintDec("CaDownlinkBaseLid", portp->analysisData.fatTreeRoutes.downlinkBasePaths, indent+8); + XmlPrintDec("CaDownlinkNonBaseLid", downlinkNonBasePaths, indent+8); + if (detail > 2) { + ShowPathContext.indent = indent+8; + (void)ReportCARoutes(&g_Fabric, portp, ReportCallback, + &ShowPathContext, TRUE); + } + printf("%*s\n", indent+4, ""); + break; + default: + break; + } + } + + } // End of for all ports + + if (detail > 1 && ct_port && format == FORMAT_XML) + printf("%*s\n", indent, ""); + + // if there are no uplinks, add_datums is no net change + fabricUplinkCount += swUplinkCount; + add_datums(&fabricUplinkBasePaths, &swUplinkBasePaths); + add_datums(&fabricUplinkNonBasePaths, &swUplinkNonBasePaths); + add_datums(&fabricUplinkAllPaths, &swUplinkAllPaths); + + // if there are no downlinks, add_datums is no net change + fabricDownlinkCount += swDownlinkCount; + add_datums(&fabricDownlinkBasePaths, &swDownlinkBasePaths); + add_datums(&fabricDownlinkNonBasePaths, &swDownlinkNonBasePaths); + add_datums(&fabricDownlinkAllPaths, &swDownlinkAllPaths); + + compute_statistics(&swUplinkBasePaths, swUplinkCount); + compute_statistics(&swUplinkNonBasePaths, swUplinkCount); + compute_statistics(&swUplinkAllPaths, swUplinkCount); + + compute_statistics(&swDownlinkBasePaths, swDownlinkCount); + compute_statistics(&swDownlinkNonBasePaths, swDownlinkCount); + compute_statistics(&swDownlinkAllPaths, swDownlinkCount); + + if (detail) { + switch (format) { + case FORMAT_TEXT: + printf("%*s%d Reported Port(s)\n", indent, "", ct_port); + printf("%*s%d Incomplete Route(s)\n", indent, "", badPaths); + if (ct_port) { + printf("%*s%u Uplink Port(s) %u Downlink Port(s)\n", indent, "", swUplinkCount, swDownlinkCount); + if (swUplinkCount) { + print_text_statistics(indent, "Up All Paths: ", &swUplinkAllPaths); + print_text_statistics(indent, "Up Base Paths: ", &swUplinkBasePaths); + print_text_statistics(indent, "Up Non-Base Paths:", &swUplinkNonBasePaths); + } + if (swDownlinkCount) { + print_text_statistics(indent, "Down All Paths: ", &swDownlinkAllPaths); + print_text_statistics(indent, "Down Base Paths: ", &swDownlinkBasePaths); + print_text_statistics(indent, "Down Non-Base Paths:", &swDownlinkNonBasePaths); + } + } + indent-=4; + break; + case FORMAT_XML: + XmlPrintDec("ReportedPortCount", (unsigned)ct_port, indent); + XmlPrintDec("IncompleteRoutes", (unsigned)badPaths, indent); + if (ct_port) { + XmlPrintDec("UplinkPortCount", (unsigned)swUplinkCount, indent); + XmlPrintDec("DownlinkPortCount", (unsigned)swDownlinkCount, indent); + // always output, even if count is 0, simplifies scripts + print_xml_statistics(indent, "UplinkAllPaths", &swUplinkAllPaths); + print_xml_statistics(indent, "UplinkBasePaths", &swUplinkBasePaths); + print_xml_statistics(indent, "UplinkNonBasePaths", &swUplinkNonBasePaths); + print_xml_statistics(indent, "DownlinkAllPaths", &swDownlinkAllPaths); + print_xml_statistics(indent, "DownlinkBasePaths", &swDownlinkBasePaths); + print_xml_statistics(indent, "DownlinkNonBasePaths", &swDownlinkNonBasePaths); + } + indent-=4; + printf("%*s\n", indent, ""); + break; + default: + break; + } + } // End of if (detail) + + } // End of for ( pList=QListHead(&g_Fabric.AllSWs); pList != NULL + + compute_statistics(&fabricUplinkBasePaths, fabricUplinkCount); + compute_statistics(&fabricUplinkNonBasePaths, fabricUplinkCount); + compute_statistics(&fabricUplinkAllPaths, fabricUplinkCount); + + compute_statistics(&fabricDownlinkBasePaths, fabricDownlinkCount); + compute_statistics(&fabricDownlinkNonBasePaths, fabricDownlinkCount); + compute_statistics(&fabricDownlinkAllPaths, fabricDownlinkCount); + + switch (format) { + case FORMAT_TEXT: + printf("%*s%d Reported Switch(es)\n", indent, "", ct_node); + printf("%*s%d Reported Port(s)\n", indent, "", totalPorts); + if (totalPorts) { + printf("%*s%u Uplink Port(s) %u Downlink Port(s)\n", indent, "", fabricUplinkCount, fabricDownlinkCount); + if (fabricUplinkCount) { + print_text_statistics(indent, "Up All Paths: ", &fabricUplinkAllPaths); + print_text_statistics(indent, "Up Base Paths: ", &fabricUplinkBasePaths); + print_text_statistics(indent, "Up Non-Base Paths:", &fabricUplinkNonBasePaths); + } + if (fabricDownlinkCount) { + print_text_statistics(indent, "Down All Paths: ", &fabricDownlinkAllPaths); + print_text_statistics(indent, "Down Base Paths: ", &fabricDownlinkBasePaths); + print_text_statistics(indent, "Down Non-Base Paths:", &fabricDownlinkNonBasePaths); + } + } + break; + case FORMAT_XML: + XmlPrintDec("ReportedSwitchCount", (unsigned)ct_node, indent); + XmlPrintDec("ReportedPortCount", (unsigned)totalPorts, indent); + if (totalPorts) { + XmlPrintDec("UplinkPortCount", (unsigned)fabricUplinkCount, indent); + XmlPrintDec("DownlinkPortCount", (unsigned)fabricDownlinkCount, indent); + // always output, even if count is 0, simplifies scripts + print_xml_statistics(indent, "UplinkAllPaths", &fabricUplinkAllPaths); + print_xml_statistics(indent, "UplinkBasePaths", &fabricUplinkBasePaths); + print_xml_statistics(indent, "UplinkNonBasePaths", &fabricUplinkNonBasePaths); + print_xml_statistics(indent, "DownlinkAllPaths", &fabricDownlinkAllPaths); + print_xml_statistics(indent, "DownlinkBasePaths", &fabricDownlinkBasePaths); + print_xml_statistics(indent, "DownlinkNonBasePaths", &fabricDownlinkNonBasePaths); + } + break; + default: + break; + } + switch (format) { + case FORMAT_TEXT: + DisplaySeparator(); + break; + case FORMAT_XML: + indent-=4; + printf("%*s\n", indent, ""); + break; + default: + break; + } +} // End of ShowTreePathUsageReport() + +struct ValidateRoutesContext { + Format_t format; + int indent; + int detail; +}; + +void ValidateRouteCallback(PortData *portp1, PortData *portp2, STL_LID dlid, boolean isBaseLid, uint8 SL, void *context) +{ + struct ValidateRoutesContext *ValidateRoutesContext = (struct ValidateRoutesContext*)context; + int indent = ValidateRoutesContext->indent; + + if (! ValidateRoutesContext->detail) + return; + + switch (ValidateRoutesContext->format) { + case FORMAT_TEXT: + // output portp1 + // output -> dlid portp2 + printf("%*s 0x%016"PRIx64" %3u ", + indent, "", + portp1->nodep->NodeInfo.NodeGUID, + portp1->PortNum); + if (g_use_scsc) printf("%2u", SL); + printf(" %s %.*s\n", + StlNodeTypeToText(portp1->nodep->NodeInfo.NodeType), + NODE_DESCRIPTION_ARRAY_SIZE, + g_noname?g_name_marker:(char*)portp1->nodep->NodeDesc.NodeString); + printf("%*s-> 0x%08x 0x%016"PRIx64" %3u ", + indent, "", dlid, + portp2->nodep->NodeInfo.NodeGUID, + portp2->PortNum); + if (g_use_scsc) printf(" "); + printf(" %s %.*s\n", + StlNodeTypeToText(portp2->nodep->NodeInfo.NodeType), + NODE_DESCRIPTION_ARRAY_SIZE, + g_noname?g_name_marker:(char*)portp2->nodep->NodeDesc.NodeString); + if (ValidateRoutesContext->detail >= 2) { + printf("%*sIncompletePath:\n", indent, ""); + printf("%*sNodeGUID Port Type ", indent+4, ""); + if (g_use_scsc) printf("VL "); + printf("Name\n"); + } else { + printf("\n"); + } + break; + case FORMAT_XML: + printf("%*s\n", indent, ""); + + printf("%*s\n", indent+4, "", + portp1->nodep->NodeInfo.NodeGUID, portp1->PortNum); + XmlPrintHex64("NodeGUID", + portp1->nodep->NodeInfo.NodeGUID, indent+8); + if (portp1->PortGUID) + XmlPrintHex64("PortGUID", portp1->PortGUID, indent+8); + XmlPrintDec("PortNum", portp1->PortNum, indent+8); + XmlPrintNodeType(portp1->nodep->NodeInfo.NodeType, + indent+8); + XmlPrintNodeDesc((char*)portp1->nodep->NodeDesc.NodeString, indent+8); + printf("%*s\n", indent+4, ""); + + printf("%*s\n", indent+4, "", + portp2->nodep->NodeInfo.NodeGUID, portp2->PortNum); + XmlPrintLID("DLID", dlid, indent+8); + XmlPrintHex64("NodeGUID", + portp2->nodep->NodeInfo.NodeGUID, indent+8); + if (portp2->PortGUID) + XmlPrintHex64("PortGUID", portp2->PortGUID, indent+8); + XmlPrintDec("PortNum", portp2->PortNum, indent+8); + XmlPrintNodeType(portp2->nodep->NodeInfo.NodeType, + indent+8); + XmlPrintNodeDesc((char*)portp2->nodep->NodeDesc.NodeString, indent+8); + printf("%*s\n", indent+4, ""); + if (g_use_scsc) XmlPrintDec("SL", SL, indent+4); + if (ValidateRoutesContext->detail >= 2) + printf("%*s\n", indent+4, ""); + else + printf("%*s\n", indent, ""); + break; + default: + break; + } +} + +struct MCRoutesContext { + Format_t format; + int indent; + int detail; + MCROUTESTATUS status; +}; + +void PrintMCRouteMembers(McNodeLoopInc *LoopIncp, void *context) +{ + struct MCRoutesContext *MCRoutesContext = (struct MCRoutesContext*)context; + int indent = MCRoutesContext->indent; + + if (! MCRoutesContext->detail) + return; + + switch (MCRoutesContext->format) { + case FORMAT_TEXT: + printf("0x%016"PRIx64"\t%s\t%.*s\t%3u\t", + LoopIncp->pPort->nodep->NodeInfo.NodeGUID, + StlNodeTypeToText(LoopIncp->pPort->nodep->NodeInfo.NodeType), + NODE_DESCRIPTION_ARRAY_SIZE, + g_noname?g_name_marker:(char*)LoopIncp->pPort->nodep->NodeDesc.NodeString, + LoopIncp->entryPort); + if(LoopIncp->exitPort != 0) + printf("%3u\n",LoopIncp->exitPort); + else + printf("-\n"); + + break; + case FORMAT_XML: + printf("%*s\n", indent+4, "", + LoopIncp->pPort->nodep->NodeInfo.NodeGUID, LoopIncp->pPort->PortNum); + XmlPrintHex64("NodeGUID", + LoopIncp->pPort->nodep->NodeInfo.NodeGUID, indent+8); + if (LoopIncp->pPort->PortGUID) + XmlPrintHex64("PortGUID", LoopIncp->pPort->PortGUID, indent+8); + XmlPrintNodeType(LoopIncp->pPort->nodep->NodeInfo.NodeType, + indent+8); + XmlPrintNodeDesc((char*)LoopIncp->pPort->nodep->NodeDesc.NodeString, indent+8); + XmlPrintDec("EntryPort", LoopIncp->entryPort, indent+8); + if(LoopIncp->exitPort != 0) + XmlPrintDec("ExitPort", LoopIncp->exitPort, indent+8); + printf("%*s\n", indent+4, ""); + break; + default: + break; + } +} + + +void PrintEndMCRoute(void *context) +{ + struct MCRoutesContext *MCRoutesContext = (struct MCRoutesContext*)context; + int indent = MCRoutesContext->indent+4; + + if (MCRoutesContext->detail <= 1) + return; + + switch (MCRoutesContext->format) { + case FORMAT_TEXT: + printf("\n"); + break; + case FORMAT_XML: + printf("%*s\n", indent-4, ""); + break; + default: + break; + } + return; +} + +void PrintInitMCRoute(uint32 count,void *context) +{ + struct MCRoutesContext *MCRoutesContext = (struct MCRoutesContext*)context; + int indent = MCRoutesContext->indent+4; + MCROUTESTATUS mcstatus = MCRoutesContext->status; + char statusstr[80], statusxml[80]; + + if (MCRoutesContext->detail <= 1) + return; + + if (count == 0) { + if (MCRoutesContext->format== FORMAT_XML) + printf("%*s\n", indent-4, ""); + } + else { + switch (mcstatus) { + case MC_NO_TRACE: + strncpy(statusstr,"Unable to trace route",sizeof(statusstr)); + strncpy(statusxml,"UnableToTraceRoute",sizeof(statusxml)); + break; + case MC_NOT_FOUND: + strncpy(statusstr,"No start point",sizeof(statusstr)); + strncpy(statusxml,"NoStartPoint",sizeof(statusxml)); + break; + case MC_UNAVAILABLE: + strncpy(statusstr,"No MFT Route Table",sizeof(statusstr)); + strncpy(statusxml,"NoMFTRouteTable",sizeof(statusxml)); + break; + case MC_LOOP: + strncpy(statusstr,"Found Loop",sizeof(statusstr)); + strncpy(statusxml,"FoundLoop",sizeof(statusxml)); + break; + case MC_NOGROUP: + strncpy(statusstr,"End-node does not belong to McGroup",sizeof(statusstr)); + strncpy(statusxml,"EndNodeNoGroup",sizeof(statusxml)); + break; + default: + strcpy(statusstr,""); + strcpy(statusxml,""); + break; + } + + switch (MCRoutesContext->format) { + case FORMAT_TEXT: + printf("%s. Num. of paths: %d\n",statusstr,count); + if (MCRoutesContext->detail >= 2) { + printf(" NodeGUID\t\tType\tName\tEntry Port\tExitPort\n"); + } else + printf("\n"); + break; + case FORMAT_XML: + printf("%*s<%s>%d\n", indent-4, "",statusxml,count,statusxml); + break; + default: + break; + } + } + +} + +void ValidateRouteCallback2(PortData *portp, uint8 vl, void *context) +{ + struct ValidateRoutesContext *ValidateRoutesContext = (struct ValidateRoutesContext*)context; + int indent = ValidateRoutesContext->indent+4; + + if (ValidateRoutesContext->detail <= 1) + return; + + if (! portp) { + // special case, indicates end of path + switch (ValidateRoutesContext->format) { + case FORMAT_TEXT: + printf("\n"); + break; + case FORMAT_XML: + printf("%*s\n", indent, ""); + printf("%*s\n", indent-4, ""); + break; + default: + break; + } + return; + } + + switch (ValidateRoutesContext->format) { + case FORMAT_TEXT: + // output portp1 + // output -> dlid portp2 + printf("%*s0x%016"PRIx64" %3u %s ", + indent, "", + portp->nodep->NodeInfo.NodeGUID, + portp->PortNum, + StlNodeTypeToText(portp->nodep->NodeInfo.NodeType)); + if (g_use_scsc) printf(" %2d ", vl); + printf("%.*s\n", + NODE_DESCRIPTION_ARRAY_SIZE, + g_noname?g_name_marker:(char*)portp->nodep->NodeDesc.NodeString); + break; + case FORMAT_XML: + printf("%*s\n", indent+4, "", + portp->nodep->NodeInfo.NodeGUID, portp->PortNum); + XmlPrintHex64("NodeGUID", + portp->nodep->NodeInfo.NodeGUID, indent+8); + if (portp->PortGUID) + XmlPrintHex64("PortGUID", portp->PortGUID, indent+8); + XmlPrintDec("PortNum", portp->PortNum, indent+8); + XmlPrintNodeType(portp->nodep->NodeInfo.NodeType, + indent+8); + if (g_use_scsc) XmlPrintDec("VL", vl, indent+8); + XmlPrintNodeDesc((char*)portp->nodep->NodeDesc.NodeString, indent+8); + printf("%*s\n", indent+4, ""); + break; + default: + break; + } +} + +// Validate all routes in linear FDBs +void ShowValidateRoutesReport(Format_t format, int indent, int detail) +{ + FSTATUS status; + uint32 totalPaths; + uint32 badPaths; + + struct ValidateRoutesContext ValidateRoutesContext = { format:format, detail:detail }; + + if (! (g_Fabric.flags & FF_ROUTES) && g_snapshot_in_file) { + switch (format) { + case FORMAT_TEXT: + printf("%*sReport skipped: provided snapshot was created without -r option\n", indent, ""); + break; + case FORMAT_XML: + printf("%*s\n", indent, ""); + break; + default: + break; + } + return; + } + switch (format) { + case FORMAT_TEXT: + printf("%*sValidate Routes\n", indent, ""); + break; + case FORMAT_XML: + printf("%*s\n", indent, ""); + indent+=4; + break; + default: + break; + } + + switch (format) { + case FORMAT_TEXT: + printf( "%*s%u LID(s) in Fabric%s\n", indent, "", + (unsigned)cl_qmap_count(&g_Fabric.u.AllLids), detail?":":"" ); + printf("%*s%u Connected FIs in Fabric%s\n", indent, "", (unsigned)QListCount(&g_Fabric.AllFIs), detail?":":""); + printf( "%*s%u Connected Switch(es) in Fabric%s\n", indent, "", + (unsigned)QListCount(&g_Fabric.AllSWs), detail?":":"" ); + break; + case FORMAT_XML: + XmlPrintDec("FabricLIDCount", (unsigned)cl_qmap_count(&g_Fabric.u.AllLids), indent); + XmlPrintDec("ConnectedFICount", (unsigned)QListCount(&g_Fabric.AllFIs), indent); + XmlPrintDec("ConnectedSwitchCount", (unsigned)QListCount(&g_Fabric.AllSWs), indent); + break; + default: + break; + } + + if (detail) { + switch (format) { + case FORMAT_TEXT: + printf("%*sIncomplete Paths:\n", indent, ""); + if (g_use_scsc) printf("%*s DLID NodeGUID Port SL Type Name\n", indent, ""); + else printf("%*s DLID NodeGUID Port Type Name\n", indent, ""); + break; + case FORMAT_XML: + printf( "%*s\n", indent, ""); + indent+=4; + break; + default: + break; + } + } + + ValidateRoutesContext.indent = indent; + status = ValidateAllRoutes(&g_Fabric, g_portGuid, (uint8)g_rc, &totalPaths, &badPaths, + ValidateRouteCallback, &ValidateRoutesContext, + detail >=2 ?ValidateRouteCallback2:NULL, + &ValidateRoutesContext, ((g_Fabric.flags & FF_QOSDATA) && g_use_scsc)); + if (status != FSUCCESS) { + fprintf(stderr, "opareport: -o validateroutes: Unable to validate routes (status=0x%x): %s\n", status, iba_fstatus_msg(status)); + g_exitstatus = 1; + } + + if (detail) { + switch (format) { + case FORMAT_TEXT: + break; + case FORMAT_XML: + indent-=4; + printf( "%*s\n", indent, ""); + break; + default: + break; + } + } + + + switch (format) { + case FORMAT_TEXT: + printf("%*s%d Analyzed Routes\n", indent, "", totalPaths); + printf("%*s%d Incomplete Route(s)\n", indent, "", badPaths); + break; + case FORMAT_XML: + XmlPrintDec("AnalyzedRoutes", (unsigned)totalPaths, indent); + XmlPrintDec("IncompleteRoutes", (unsigned)badPaths, indent); + break; + default: + break; + } + switch (format) { + case FORMAT_TEXT: + DisplaySeparator(); + break; + case FORMAT_XML: + indent-=4; + printf("%*s\n", indent, ""); + break; + default: + break; + } +} // End of ShowValidateRoutesReport() + +void PrintHeadGroup(STL_LID mlid, void *context) +{ + struct MCRoutesContext *MCRoutesContext = (struct MCRoutesContext*)context; + int indent = MCRoutesContext->indent; + int NOM=0; + LIST_ITEM *p; + + if (! MCRoutesContext->detail) + return; + + //Search number of members for MLID mcgroup + for ( p= QListHead(&g_Fabric.AllMcGroups); p!=NULL; p=QListNext(&g_Fabric.AllMcGroups,p)){ + McGroupData *pMCGD = (McGroupData *)QListObj(p); + if (pMCGD->MLID == mlid) { + NOM = pMCGD->NumOfMembers; + break; + } + } + + if (NOM !=0) { + switch (MCRoutesContext->format) { + case FORMAT_TEXT: + printf("MC Group 0x%04x\n", mlid); + printf("Number of Members:%d \n", NOM); + break; + case FORMAT_XML: + XmlPrintMLID("MLID",mlid,indent+4); + printf("%*s%d\n", indent+4, "",NOM); + break; + } + } + + return; +} + + +// Validate MC routes in multicast tables MCDBs +void ShowValidateMCRoutesReport(Format_t format, int indent, int detail) +{ + FSTATUS status; + uint32 totalPaths, badPaths=0, listcount=0; + LIST_ITEM *p, *q; + int i; + struct MCRoutesContext MCRoutesContext = { format:format, detail:detail, status:MC_NO_TRACE }; + + if (! (g_Fabric.flags & FF_ROUTES) && g_snapshot_in_file) { + switch (format) { + case FORMAT_TEXT: + printf("%*sReport skipped: provided snapshot was created without -r option\n", indent, ""); + break; + case FORMAT_XML: + printf("%*s\n", indent, ""); + break; + default: + break; + } + return; + } + + if (QListCount(&g_Fabric.AllSWs) ==0) { + printf("Cannot Validate MC Routes: No Switches Connected\n"); + return; + } + + switch (format) { + case FORMAT_TEXT: + printf("%*sValidate Multicast Routes\n", indent, ""); + break; + case FORMAT_XML: + printf("%*s\n", indent, ""); + indent+=4; + break; + default: + break; + } + /////////////////////////////////////////////////////////////////////// + //Get MCGroups + + switch (format) { // do not print "zero" members + case FORMAT_TEXT: + printf(" %d Multicast groups\n", g_Fabric.NumOfMcGroups); + break; + case FORMAT_XML: + printf("%*s%d\n", indent, "",g_Fabric.NumOfMcGroups); + break; + default: + break; + }// case end + + MCRoutesContext.indent = indent; + + status = ValidateAllMCRoutes(&g_Fabric, &totalPaths); + + if (status != FSUCCESS) { + fprintf(stderr, "opareport: -o validatemcroutes: Unable to validate multicast routes (status=0x%x): %s\n", status, iba_fstatus_msg(status)); + FreeValidateMCRoutes(&g_Fabric); + g_exitstatus = 1; + return; + } + + // Display all MC routes with problems: + for (i=0;imlid,&MCRoutesContext); + for (q = QListHead(&pmcloop->AllMcNodeLoopIncR ); q!= NULL; + q = QListNext(&pmcloop->AllMcNodeLoopIncR,q)) { + + McNodeLoopInc *pmcnodeloop = (McNodeLoopInc *) QListObj(q); + PrintMCRouteMembers(pmcnodeloop, &MCRoutesContext); // print node + } // end for q + PrintEndMCRoute(&MCRoutesContext); // print closure + }// end for p + } + + switch (format) { + case FORMAT_TEXT: + printf(" Total Analyzed MC Routes from Entry Switch to HFI: %d\n MC Bad Paths %d\n",totalPaths, badPaths); + break; + case FORMAT_XML: + printf("%*s%d\n", indent, "",totalPaths); + printf("%*s%d\n", indent, "",badPaths); + indent-=4; + break; + default: + break; + }// case end + + switch (format) { + case FORMAT_TEXT: + printf("\n"); + DisplaySeparator(); + break; + case FORMAT_XML: + printf("%*s\n", indent, ""); + indent-=4; + break; + default: + break; + } + + // delete MC routes structure + // deallocate memory for the MC route + FreeValidateMCRoutes(&g_Fabric); + +} // End of ShowValidateMCRoutesReport() + + +// Validate all routes for credit loops +void ShowValidateCreditLoopsReport(Format_t format, int indent, int detail) +{ + FSTATUS status; + ValidateCreditLoopRoutesContext_t ValidateCreditLoopRoutesContext = { format:format, detail:detail }; + + if (!(g_Fabric.flags & FF_ROUTES) && g_snapshot_in_file) { + switch (format) { + case FORMAT_TEXT: + printf("%*sReport skipped: provided snapshot was created without -r option\n", indent, ""); + break; + case FORMAT_XML: + printf("%*s\n", indent, ""); + break; + default: + break; + } + return; + } + + switch (format) { + case FORMAT_TEXT: + printf("%*sValidate Credit Loop Routes\n", indent, ""); + break; + case FORMAT_XML: + printf("\n"); + printf("%*s\n", indent, ""); + indent += 4; + break; + default: + break; + } + + ValidateCreditLoopRoutesContext.indent = indent; + ValidateCreditLoopRoutesContext.quiet = g_quiet; + status = ValidateAllCreditLoopRoutes(&g_Fabric, g_portGuid, (uint8)g_rc, + ValidateCLRouteCallback, + ValidateCLFabricSummaryCallback, + ValidateCLDataSummaryCallback, + ValidateCLRouteSummaryCallback, + ValidateCLLinkSummaryCallback, + ValidateCLLinkStepSummaryCallback, + ValidateCLPathSummaryCallback, + ValidateCLTimeGetCallback, + &ValidateCreditLoopRoutesContext, + ((g_Fabric.flags & FF_ROUTES) && g_snapshot_in_file), + ((g_Fabric.flags & FF_QOSDATA) && g_use_scsc)); + if (status != FSUCCESS) { + fprintf(stderr, "opareport: -o validateroutes: Unable to validate credit loop routes (status=0x%x): %s\n", status, iba_fstatus_msg(status)); + g_exitstatus = 1; + } + switch (format) { + case FORMAT_TEXT: + DisplaySeparator(); + break; + case FORMAT_XML: + indent -= 4; + printf("%*s\n", indent, ""); + break; + default: + break; + } +} // End of ShowValidateCreditLoopsReport() + +// output LID usage in linear FDB (undocumented) +void ShowLIDUsageReport(Point *focus, Format_t format, int indent, int detail) +{ + int ix_lid; + LIST_ITEM *pList; + NodeData *nodep; + SwitchData *switchp; + uint32 ct_node = 0; + uint32 ct_lid = 0; + uint16 usageLinearFDBSize = 0; + uint32 tb_usageLID[g_max_lft+1]; + + switch (format) { + case FORMAT_TEXT: + printf("%*sLID Usage\n", indent, ""); + break; + case FORMAT_XML: + printf("%*s\n", indent, ""); + indent+=4; + break; + default: + break; + } + if (! (g_Fabric.flags & FF_ROUTES) && g_snapshot_in_file) { + switch (format) { + case FORMAT_TEXT: + printf("%*sReport skipped: provided snapshot was created without -r option\n", indent, ""); + break; + case FORMAT_XML: + printf("%*s\n", indent, ""); + break; + default: + break; + } + goto done; + } + ShowPointFocus(focus, FIND_FLAG_FABRIC, format, indent, detail); + switch (format) { + case FORMAT_TEXT: + printf( "%*s%u Connected Switch(es) in Fabric%s\n", indent, "", + (unsigned)QListCount(&g_Fabric.AllSWs), detail?":":"" ); + break; + case FORMAT_XML: + XmlPrintDec("ConnectedSwitchCount", (unsigned)QListCount(&g_Fabric.AllSWs), indent); + break; + default: + break; + } + + // Report LID usage in Linear FDB + memset(tb_usageLID, 0, (g_max_lft+1) * sizeof(uint32)); + + for ( pList=QListHead(&g_Fabric.AllSWs); pList != NULL; + pList = QListNext(&g_Fabric.AllSWs, pList) ) { + nodep = QListObj(pList); + switchp = nodep->switchp; + + if (! CompareNodePoint(nodep, focus)) + continue; + + if (!switchp || !switchp->LinearFDB ) + continue; + + if (detail) { + if (!ct_node) { + ShowNodeBriefSummaryHeadings(format, indent, 0); + switch (format) { + case FORMAT_TEXT: + printf("%*s LID Count\n", indent+4, ""); + case FORMAT_XML: + break; + default: + break; + } + } + ShowNodeBriefSummary(nodep, focus, TRUE, format, indent, 0); + if (switchp->LinearFDBSize > usageLinearFDBSize) + usageLinearFDBSize = switchp->LinearFDBSize; + + for (ix_lid = 0; ix_lid < switchp->LinearFDBSize; ix_lid++) { + if (STL_LFT_PORT_BLOCK(switchp->LinearFDB, ix_lid) == 0xFF) + continue; + + tb_usageLID[ix_lid]++; + + } // End of for (ix_lid = 0; ix_lid < switchp->LinearFDBSize + + } // End of if (detail) + + ct_node++; + + } // End of for ( pList=QListHead(&g_Fabric.AllSWs); pList != NULL + + for (ix_lid = 0; ix_lid < usageLinearFDBSize; ix_lid++) + if (tb_usageLID[ix_lid]) + switch (format) { + case FORMAT_TEXT: + printf( "%*s0x%.*x %u\n", indent+4, "", (ix_lid <= IB_MAX_UCAST_LID ? 4:8) , (uint32)ix_lid, + tb_usageLID[ix_lid] ); + break; + case FORMAT_XML: + if (!ct_lid++) + printf("%*s\n", indent, ""); + printf( "%*s%u\n", indent+4, "", (ix_lid <= IB_MAX_UCAST_LID ? 4:8), + (uint32)ix_lid, tb_usageLID[ix_lid] ); + break; + default: + break; + } + +done: + switch (format) { + case FORMAT_TEXT: + printf("%*s%d Reported Switch(es)\n", indent, "", ct_node); + DisplaySeparator(); + break; + case FORMAT_XML: + if (ct_lid) + printf("%*s\n", indent, ""); + XmlPrintDec("ReportedSwitchCount", (unsigned)ct_node, indent); + indent-=4; + printf("%*s\n", indent, ""); + break; + default: + break; + } + +} // End of ShowLIDUsageReport() + +// output vFabric information +void ShowVFInfoReport(Point *focus, Format_t format, int indent, int detail) +{ + LIST_ITEM *p; + int cnt = 0; + + ShowPointFocus(focus, FIND_FLAG_FABRIC, format, indent, detail); + + switch (format) { + case FORMAT_TEXT: + printf("%*svFabrics:\n", indent, ""); + break; + case FORMAT_XML: + printf("%*s\n", indent, ""); + indent += 4; + break; + default: + break; + } + + PrintDest_t print; + PrintDestInitFile(&print, stdout); + + // Report vFabric records + if (detail) { + for (p = QListHead(&g_Fabric.AllVFs); p; p = QListNext(&g_Fabric.AllVFs, p), cnt++) + { + VFData_t *pVFData = (VFData_t *)QListObj(p); + STL_VFINFO_RECORD *pR = &pVFData->record; + char buf[8]; + + switch (format) { + case FORMAT_TEXT: + if (cnt) + printf("\n"); + + PrintStlVfInfoRecord_detail(&print, indent, detail, pR, 0); + break; + + case FORMAT_XML: + printf("%*s\n", indent, ""); + indent += 4; + XmlPrintDec("Index", pR->vfIndex, indent); + XmlPrintStr("Name", (char *)pR->vfName, indent); + // ServiceID and MGID are always zero when SA query asks for + // all VFs + //XmlPrintHex64("ServiceID", pR->ServiceID, indent); + //printf( "%*s0x%016"PRIx64":0x%016"PRIx64"\n", + // indent, "", pR->MGID.AsReg64s.H, pR->MGID.AsReg64s.L ); + XmlPrintPKey("PKey", pR->pKey, indent); + XmlPrintDec("SL", pR->s1.slBase, indent); + + + if (pR->slMulticastSpecified) + XmlPrintDec("MulticastSL", pR->slMulticast, indent); + + if (detail >1) { + printf( "%*s\n", indent, "", + (pR->s1.selectFlags & STL_VFINFO_REC_SEL_PKEY_QUERY) ? "PKEY " : "", + (pR->s1.selectFlags & STL_VFINFO_REC_SEL_SL_QUERY) ? "SL " : "" ); + XmlPrintHex8("Select_Hex", pR->s1.selectFlags, indent); + + // get the value of Packet Lifetime Multiplier + snprintf(buf, sizeof(buf), "%d", 1<s1.pktLifeTimeInc); + XmlPrintStr( "PktLifeTimeMult", + pR->s1.pktLifeSpecified ? buf : "unspecified", + indent ); + if (pR->s1.mtuSpecified) + XmlPrintDec("MaxMtu", GetBytesFromMtu(pR->s1.mtu), indent); + else + XmlPrintStr("MaxMtu", "unlimited", indent); + XmlPrintStr( "MaxRate", + pR->s1.rateSpecified ? StlStaticRateToText(pR->s1.rate) : "unlimited", + indent ); + printf( "%*s%s%s%s\n", indent, "", + (pR->optionFlags & STL_VFINFO_REC_OPT_SECURITY) ? "Security " : "", + (pR->optionFlags & STL_VFINFO_REC_OPT_QOS) ? "QoS " : "", + (pR->optionFlags & STL_VFINFO_REC_OPT_FLOW_DISABLE) ? "FlowCtrlDisable " : "" ); + XmlPrintHex8("Options_Hex", pR->optionFlags, indent); + + printf("%*s\n", indent, ""); + indent += 4; + if (pR->optionFlags & STL_VFINFO_REC_OPT_QOS) + { + XmlPrintDec("Bandwidth_Percent", pR->bandwidthPercent, indent); + XmlPrintBool("Priority", pR->priority, indent); + } + indent -= 4; + printf("%*s\n", indent, ""); + XmlPrintDec("PreemptionRank", pR->preemptionRank, indent); + FormatTimeoutMult(buf, pR->hoqLife); + XmlPrintStr("HoQLife", buf, indent); + XmlPrintDec("HoQLife_Int", pR->hoqLife, indent); + } + break; + + default: + break; + } // End of switch (format) + + // we need QOSDATA to have the SL2SC and PKey tables which are + // used by isVFMember + if (detail > 2 && (g_Fabric.flags & FF_QOSDATA)) { + LIST_ITEM *q; + cl_map_item_t *r; + if (format == FORMAT_TEXT) + printf("%*s NodeGUID Port Type Name\n", indent, ""); + // show all endpoints (FIs and switch port 0) which are in + // the given vFabric + for (q=QListHead(&g_Fabric.AllFIs); q != NULL; q = QListNext(&g_Fabric.AllFIs, q)) { + NodeData *nodep = (NodeData *)QListObj(q); + for (r=cl_qmap_head(&nodep->Ports); r != cl_qmap_end(&nodep->Ports); r = cl_qmap_next(r)) { + PortData *portp = PARENT_STRUCT(r, PortData, NodePortsEntry); + + if (! ComparePortPoint(portp, focus)) + continue; + if (isVFMember(portp, pVFData)) + ShowLinkPortBriefSummary(portp, "", 0, NULL, + format, indent, 0); + } + } + //for all SWs + for (q=QListHead(&g_Fabric.AllSWs); q != NULL; q = QListNext(&g_Fabric.AllSWs, q)) { + NodeData *nodep = (NodeData *)QListObj(q); + PortData *portp = FindNodePort(nodep,0); + if (!portp) + continue; + if (! ComparePortPoint(portp, focus)) + continue; + if (isVFMember(portp, pVFData)) + ShowLinkPortBriefSummary(portp, "", 0, NULL, + format, indent, 0); + } + } + switch (format) { + case FORMAT_TEXT: + break; + case FORMAT_XML: + indent -= 4; + printf("%*s\n", indent, ""); + break; + default: + break; + } + } // End of for each VF + } + + switch (format) { + case FORMAT_TEXT: + if (cnt) + printf("\n"); + printf("%*s%u VFs\n", indent, "", QListCount(&g_Fabric.AllVFs)); + DisplaySeparator(); + break; + case FORMAT_XML: + XmlPrintDec("Count", QListCount(&g_Fabric.AllVFs), indent); + indent -= 4; + printf("%*s\n", indent, ""); + break; + default: + break; + } +} // End of ShowVFInfoReport() + + +void ShowBCTForPortText(PortData *port, Format_t format, int indent, int detail) +{ + PortData *rport = port->neighbor; + uint16_t bytesPerAU = 0; + uint32_t remLim = 0; + uint8_t vl; + + indent+=4; + + if (rport) { + printf("%*sRemote Port 0x%016"PRIx64" %u %s %.*s (LID %u)\n", indent, "", + rport->nodep->NodeInfo.NodeGUID, + rport->PortNum, + StlNodeTypeToText(rport->nodep->NodeInfo.NodeType), + NODE_DESCRIPTION_ARRAY_SIZE, + g_noname?g_name_marker:(char*)rport->nodep->NodeDesc.NodeString, + rport->EndPortLID); + bytesPerAU = 8 * (1 << rport->PortInfo.BufferUnits.s.BufferAlloc); + remLim = rport->PortInfo.OverallBufferSpace; + } + + printf("%*sBufferControlTable\n", indent, ""); + + indent +=4; + + if (bytesPerAU) + printf("%*sOverallBufferSpace (AU/B): %6u/%8u\n", indent, "", + remLim, remLim * bytesPerAU); + + uint16_t bufferDepth = (port->PortInfo.ReplayDepthH.BufferDepthH << 8) | port->PortInfo.ReplayDepth.BufferDepth; + printf("%*sTx Buffer Depth (LTP/B): %6u/%8u\n", indent, "", + bufferDepth, bufferDepth * BYTES_PER_LTP); + + if (!g_persist && !g_hard) { + uint16_t wireDepth = (port->PortInfo.ReplayDepthH.WireDepthH << 8) | port->PortInfo.ReplayDepth.WireDepth; + printf("%*sWire Depth (LTP/B): %6u/%8u\n", indent, "", + wireDepth, wireDepth * BYTES_PER_LTP); + } else { + printf("%*sWire Depth (LTP/B): xxxxxx/xxxxxxxx\n", indent, ""); + } + + printf("%*sTxOverallSharedLimit (AU/B): %6u/", indent, "", + port->pBufCtrlTable->TxOverallSharedLimit); + if (bytesPerAU) + printf("%8u\n", port->pBufCtrlTable->TxOverallSharedLimit * bytesPerAU); + else + printf(" N/A\n"); + + indent += 4; + + printf("%*sVL | Dedicated ( Bytes) | Shared ( Bytes) | MTU\n", indent, ""); + + for (vl = 0; vl < STL_MAX_VLS; vl++) { + if (port->pBufCtrlTable->VL[vl].TxDedicatedLimit == 0 && port->pBufCtrlTable->VL[vl].TxSharedLimit == 0) + continue; + + uint32_t dBytes = 0; + uint32_t sBytes = 0; + uint16_t mtu = 0; + + if (bytesPerAU) { + dBytes = port->pBufCtrlTable->VL[vl].TxDedicatedLimit * bytesPerAU; + sBytes = port->pBufCtrlTable->VL[vl].TxSharedLimit * bytesPerAU; + } + + if (vl%2 == 0) { + mtu = port->PortInfo.NeighborMTU[vl/2].s.VL0_to_MTU; + } else { + mtu = port->PortInfo.NeighborMTU[vl/2].s.VL1_to_MTU; + } + mtu = GetBytesFromMtu(mtu); + + printf("%*s%2d | %6u (%8u) | %6u (%8u) | %6u\n", indent, "", + vl, + port->pBufCtrlTable->VL[vl].TxDedicatedLimit, dBytes, + port->pBufCtrlTable->VL[vl].TxSharedLimit, sBytes, + mtu); + } +} + +void ShowBCTForPortXML(PortData *port, Format_t format, int indent, int detail) +{ + PortData *rport = port->neighbor; + uint16_t bytesPerAU = 0; + uint32_t remLim = 0; + uint8_t vl; + + indent+=4; + + if (rport) { + printf("%*s\n", indent, "", + rport->nodep->NodeInfo.NodeGUID, rport->PortNum); + bytesPerAU = 8 * (1 << rport->PortInfo.BufferUnits.s.BufferAlloc); + remLim = rport->PortInfo.OverallBufferSpace; + } + + printf("%*s\n", indent, ""); + + indent += 4; + + uint16_t bufferDepth = (port->PortInfo.ReplayDepthH.BufferDepthH << 8) | port->PortInfo.ReplayDepth.BufferDepth; + printf("%*s%u\n", indent, "", + bufferDepth); + printf("%*s%u\n", indent, "", + bufferDepth * BYTES_PER_LTP); + + if (!g_persist && !g_hard) { + uint16_t wireDepth = (port->PortInfo.ReplayDepthH.WireDepthH << 8) | port->PortInfo.ReplayDepth.WireDepth; + printf("%*s%u\n", indent, "", + wireDepth); + printf("%*s%u\n", indent, "", + wireDepth * BYTES_PER_LTP); + } + + if (bytesPerAU) { + printf("%*s%u\n", indent, "", remLim); + printf("%*s%u\n", indent, "", + remLim * bytesPerAU); + } + + printf("%*s%u\n", indent, "", + port->pBufCtrlTable->TxOverallSharedLimit); + if (bytesPerAU) + printf("%*s%u\n", indent, "", + port->pBufCtrlTable->TxOverallSharedLimit * bytesPerAU); + + for (vl = 0; vl < STL_MAX_VLS; vl++) + { + if (port->pBufCtrlTable->VL[vl].TxDedicatedLimit == 0 && port->pBufCtrlTable->VL[vl].TxSharedLimit == 0) + continue; + + printf("%*s\n", indent, "", vl); + + indent += 4; + + printf("%*s%u\n", indent, "", + port->pBufCtrlTable->VL[vl].TxDedicatedLimit); + if (bytesPerAU) + printf("%*s%u\n", indent, "", + port->pBufCtrlTable->VL[vl].TxDedicatedLimit * bytesPerAU); + printf("%*s%u\n", indent, "", + port->pBufCtrlTable->VL[vl].TxSharedLimit); + if (bytesPerAU) + printf("%*s%u\n", indent, "", + port->pBufCtrlTable->VL[vl].TxSharedLimit * bytesPerAU); + + indent -= 4; + + printf("%*s\n", indent, ""); + } + indent -= 4; + + printf("%*s\n", indent, ""); +} + +void ShowAllBCTReports(Point *focus, Format_t format, int indent, int detail) +{ + int ct_port = 0; + LIST_ITEM *p; + + ShowPointFocus(focus, FIND_FLAG_FABRIC, format, indent, detail); + switch (format) { + case FORMAT_TEXT: + printf("%*sBufferControlTable Report\n", indent, ""); + break; + case FORMAT_XML: + indent+=4; + printf("%*s\n", indent, ""); + break; + default: + break; + } + + indent+=4; + + if (g_snapshot_in_file && !(g_Fabric.flags & FF_BUFCTRLTABLE)) { + switch (format) { + case FORMAT_TEXT: + printf("%*sReport skipped: provided snapshot was created without -V option\n", indent, ""); + break; + case FORMAT_XML: + printf("%*s\n", indent, ""); + break; + default: + break; + } + goto done; + } + + for (p=QListHead(&g_Fabric.AllPorts); p != NULL; p = QListNext(&g_Fabric.AllPorts, p)) { + PortData *port = (PortData *)QListObj(p); + + if (!ComparePortPoint(port, focus)) + continue; + + if (port->nodep->NodeInfo.NodeType == STL_NODE_SW && port->PortNum == 0) + continue; + + if (! port->pBufCtrlTable) + continue; + + switch (format) { + case FORMAT_TEXT: + printf("%*sPort 0x%016"PRIx64" %u %s %.*s (LID %u)\n", indent, "", + port->nodep->NodeInfo.NodeGUID, + port->PortNum, + StlNodeTypeToText(port->nodep->NodeInfo.NodeType), + NODE_DESCRIPTION_ARRAY_SIZE, + g_noname?g_name_marker:(char*)port->nodep->NodeDesc.NodeString, + port->EndPortLID); + + ShowBCTForPortText(port, format, indent, detail); + + break; + case FORMAT_XML: + printf("%*s\n", indent, "", + port->nodep->NodeInfo.NodeGUID, port->PortNum); + XmlPrintHex64("NodeGUID", + port->nodep->NodeInfo.NodeGUID, indent+4); + if (port->PortGUID) + XmlPrintHex64("PortGUID", port->PortGUID, indent+4); + XmlPrintDec("PortNum", port->PortNum, indent+4); + XmlPrintNodeType(port->nodep->NodeInfo.NodeType, + indent+4); + XmlPrintNodeDesc((char*)port->nodep->NodeDesc.NodeString, indent+4); + + ShowBCTForPortXML(port, format, indent, detail); + + printf("%*s\n", indent, ""); + break; + default: + break; + } + ct_port++; + } + +done: + switch (format) { + case FORMAT_TEXT: + indent -= 4; + printf("%*s%d Reported Port(s)\n", indent, "", ct_port); + DisplaySeparator(); + break; + case FORMAT_XML: + XmlPrintDec("ReportedPortCount", (unsigned)ct_port, indent); + indent -= 4; + printf("%*s\n", indent, ""); + break; + default: + break; + } +} + +void CheckVFAllocation(PortData *port, int indent, int format, int detail) +{ + // caller checks FF_QOSDATA, but play it safe + if (detail <= 3 || !(g_Fabric.flags & FF_QOSDATA)) + return; + + // we need QOSDATA to have the SL2SC and PKey tables which are used by + // isVFMember + int sl, sc, vl, ded, share; + STL_VFINFO_RECORD *pR; + LIST_ITEM *p; + + uint8_t vfsPerVl[STL_MAX_VLS] = {0}; + uint8_t slsPerVl[STL_MAX_VLS] = {0}; + uint32_t vlSlsMap[STL_MAX_VLS] = {0}; + for (p = QListHead(&g_Fabric.AllVFs); p; p = QListNext(&g_Fabric.AllVFs, p)) { + VFData_t *pVFData = (VFData_t *)QListObj(p); + STL_VFINFO_RECORD *pR = &pVFData->record; + // check that every VF that the port is a member of has a VL assigned to it + if (!isVFMember(port, pVFData)) + continue; + + sl = pR->s1.slBase; + sc = port->pQOS->SL2SCMap->SLSCMap[sl].SC; + vl = port->pQOS->SC2VLMaps[Enum_SCVLt].SCVLMap[sc].VL; + if (vl == 15) { + // no VL allocated for this VF + switch (format) { + case FORMAT_TEXT: + printf("%*sNo VL allocated for VF: %s\n", indent, "", pR->vfName); + break; + case FORMAT_XML: + printf("%*s%s", indent, "", pR->vfName); + break; + default: + break; + } + continue; + } + + // check that every VF that the port is a member of has buffers + // allocated to it + // skip port 0 since it doesn't get configured for buffers + // and will confuse user by saying no buffers allocated + if ((g_Fabric.flags & FF_BUFCTRLTABLE) && port->pBufCtrlTable + && port->PortNum) { + ded = port->pBufCtrlTable->VL[vl].TxDedicatedLimit; + share = port->pBufCtrlTable->VL[vl].TxSharedLimit; + if (!ded && !share) { + switch (format) { + case FORMAT_TEXT: + printf("%*sNo buffers allocated for VF: %s\n", indent, "", pR->vfName); + break; + case FORMAT_XML: + printf("%*s%s", indent, "", pR->vfName); + break; + default: + break; + } + } + } + + int slSet[2] = { + pR->s1.slBase, + (pR->slMulticastSpecified? pR->slMulticast: -1) + }; + + // if qos is enabled, make note that this VL has a vfabric mapped + // to it, so we can check for contracted links + if (pR->optionFlags & STL_VFINFO_REC_OPT_QOS) { + uint32_t vls = 0; + + int i; + for (i = 0; i < 2; ++i) { + sl = slSet[i]; + if (sl == -1) continue; + + sc = port->pQOS->SL2SCMap->SLSCMap[sl].SC; + vl = port->pQOS->SC2VLMaps[Enum_SCVLt].SCVLMap[sc].VL; + if (vl == 15) continue; + + + if (!(vlSlsMap[vl] & (1 << sl))) { + // Only count VFs that reach this VL via an SL + // that hasn't been shared before + if (!(vls & (1 << vl))) { + // Only count this (VF,VL) pair once + ++vfsPerVl[vl]; + vls |= 1 << vl; + } + + // Only count this (SL,VL) pair once + slsPerVl[vl]++; + vlSlsMap[vl] |= (1 << sl); + } + } + } + } + + // check for contracted links + for (vl = 0; vl < STL_MAX_VLS; vl++) { + if (slsPerVl[vl]>1){ + switch (format) { + case FORMAT_TEXT: + printf("%*sContracted link: %d unique SLs in %d unique VFs (not counting shared SLs) mapped to VL %d\n", indent, "", slsPerVl[vl], vfsPerVl[vl], vl); + break; + case FORMAT_XML: + printf("%*s%d\n", indent, "", vl, slsPerVl[vl]); + break; + default: + break; + } + } + } + + // check that every allocated buffer is mapped to a VF + // skip port 0 since it doesn't get configured for buffers + // and will confuse user by saying no buffers allocated + if ((g_Fabric.flags & FF_BUFCTRLTABLE) && port->pBufCtrlTable + && port->PortNum) { + + for (vl=0; vlpBufCtrlTable->VL[vl].TxDedicatedLimit; + share = port->pBufCtrlTable->VL[vl].TxSharedLimit; + if (!ded && !share) + continue; + // this VL has buffers dedicated to it + // first need to find out if there is an SC for this VL + boolean match_found = FALSE; + for (sc=0; scpQOS->SC2VLMaps[Enum_SCVLt].SCVLMap[sc].VL) { + match_found = TRUE; + break; + } + } + if (match_found) { + // now find the Sl for this SC + match_found = FALSE; + for (sl=0; slpQOS->SL2SCMap->SLSCMap[sl].SC) { + match_found = TRUE; + break; + } + } + if (match_found) { + // now find the vfabric + match_found = FALSE; + for (p = QListHead(&g_Fabric.AllVFs); p; p = QListNext(&g_Fabric.AllVFs, p)) { + pR = &((VFData_t *)QListObj(p))->record; + if (sl == pR->s1.slBase || + (pR->slMulticastSpecified && sl == pR->slMulticast)) { + match_found = TRUE; + break; + } + } + } + } + // we never found a match + if (!match_found) { + switch (format) { + case FORMAT_TEXT: + printf("%*sBuffers allocated to VL: %d, but it is not mapped to any VirtualFabric\n",indent, "", vl); + break; + case FORMAT_XML: + printf("%*s%d\n", indent, "", vl); + break; + default: + break; + } + } + } + } + + if (port->neighbor && port->neighbor->pQOS) { + // check that SCVLt matches SCVLnt of the neighbor + for (sc=0; scpQOS->SC2VLMaps[Enum_SCVLt].SCVLMap[sc].VL; + int vl2 = port->neighbor->pQOS->SC2VLMaps[Enum_SCVLnt].SCVLMap[sc].VL; + if (vl1!=vl2) { + switch (format) { + case FORMAT_TEXT: + printf("%*sSCVLt/SCVLnt mapping mismatch:\n", indent, ""); + printf("%*s%s Port %d: SC %d -> VL %d\n", indent+4, "", + port->nodep->NodeDesc.NodeString, port->PortNum, sc, vl1); + printf("%*sNeighbor %s Port %d: SC %d -> VL %d\n", indent+4, "", + port->neighbor->nodep->NodeDesc.NodeString, port->neighbor->PortNum, sc, vl2); + break; + case FORMAT_XML: + printf("%*s\n", indent, ""); + printf("%*s%d\n", indent+4, "", + sc, vl1); + printf("%*s%d\n", indent+4, "", + sc, vl2); + printf("%*s\n", indent, ""); + break; + default: + break; + } + } + } + } + + switch (format) { + case FORMAT_TEXT: + printf("%*sVF Allocation Validated\n", indent, ""); + break; + default: + break; + } +} + +void ShowPortVFMembershipText(PortData *port, int indent, int detail) +{ + int sc, vl, ded, share; + LIST_ITEM *p; + + // we need QOSDATA to have the SL2SC and PKey tables which are used by + // isVFMember + if (! (g_Fabric.flags & FF_QOSDATA)) // caller checks, should be true + return; + printf("%*sVF Membership:\n", indent, ""); + indent+=4; + printf("%*sVF Name\tVF Index\tBaseSL\tBaseSC\tBaseVL", indent, ""); + printf("\t\tMcastSL\tMcastSC\tMcastVL"); + + if ((g_Fabric.flags & FF_BUFCTRLTABLE) && port->pBufCtrlTable + && detail>2 && port->PortNum) + printf("\tDedicated\tShared"); + printf("\n"); + // look over every vFabric + for (p = QListHead(&g_Fabric.AllVFs); p; p = QListNext(&g_Fabric.AllVFs, p)) { + VFData_t *pVFData = (VFData_t *)QListObj(p); + STL_VFINFO_RECORD *pR = &pVFData->record; + if (!isVFMember(port, pVFData)) + continue; + printf("%*s%-4s\t%d", indent, "", pR->vfName, pR->vfIndex); + + + uint8_t sls[2] = { + pR->s1.slBase, + (pR->slMulticastSpecified? pR->slMulticast: pR->s1.slBase) + }; + + int i; + for (i = 0; i < 2; ++i) { + int sl = sls[i]; + sc = port->pQOS->SL2SCMap->SLSCMap[sl].SC; + vl = port->pQOS->SC2VLMaps[Enum_SCVLt].SCVLMap[sc].VL; + + if (i > 0 && sl == pR->s1.slBase) + printf("\t\tN/A\tN/A\tN/A"); + else + printf("\t\t%d\t%d\t%d", sl, sc, vl); + } + + if ((g_Fabric.flags & FF_BUFCTRLTABLE) && port->pBufCtrlTable + && detail>2 && port->PortNum) { + ded = port->pBufCtrlTable->VL[vl].TxDedicatedLimit; + share = port->pBufCtrlTable->VL[vl].TxSharedLimit; + printf("\t%d\t\t%d", ded, share); + } + printf("\n"); + } + printf("\n"); + CheckVFAllocation(port, indent, FORMAT_TEXT, detail); +} + +void ShowPortVFMembershipXML(PortData *port, int indent, int detail) +{ + int sc, vl, ded, share; + LIST_ITEM *p; + + // we need QOSDATA to have the SL2SC and PKey tables which are used by + // isVFMember + if (! (g_Fabric.flags & FF_QOSDATA)) // caller checks, should be true + return; + printf("%*s\n", indent, ""); + indent+=4; + + for (p = QListHead(&g_Fabric.AllVFs); p; p = QListNext(&g_Fabric.AllVFs, p)) { + VFData_t *pVFData = (VFData_t *)QListObj(p); + STL_VFINFO_RECORD *pR = &pVFData->record; + if (!isVFMember(port, pVFData)) + continue; + + printf("%*s\n", indent, "", pR->vfIndex); + indent+=4; + XmlPrintStr("Name", (char *)pR->vfName, indent); + XmlPrintDec("Index", pR->vfIndex, indent); + XmlPrintDec("BaseSL", pR->s1.slBase, indent); + sc = port->pQOS->SL2SCMap->SLSCMap[pR->s1.slBase].SC; + vl = port->pQOS->SC2VLMaps[Enum_SCVLt].SCVLMap[sc].VL; + XmlPrintDec("BaseSC", sc, indent); + XmlPrintDec("VL", vl, indent); + + + if (pR->slMulticastSpecified) { + sc = port->pQOS->SL2SCMap->SLSCMap[pR->slMulticast].SC; + vl = port->pQOS->SC2VLMaps[Enum_SCVLt].SCVLMap[sc].VL; + XmlPrintDec("MulticastSL", pR->slMulticast, indent); + XmlPrintDec("MulticastSC", sc, indent); + XmlPrintDec("MulticastVL", vl, indent); + } + + if ((g_Fabric.flags & FF_BUFCTRLTABLE) && port->pBufCtrlTable + && detail>2 && port->PortNum) { + ded = port->pBufCtrlTable->VL[vl].TxDedicatedLimit; + share = port->pBufCtrlTable->VL[vl].TxSharedLimit; + XmlPrintDec("DedicatedBuffer", ded, indent); + XmlPrintDec("SharedBuffer", share, indent); + } + indent-=4; + printf("%*s\n", indent, ""); + } + indent-=4; + printf("%*s\n", indent, ""); + CheckVFAllocation(port, indent, FORMAT_XML, detail); +} + +void ShowVFMemberReport(Point *focus, Format_t format, int indent, int detail) +{ + int ct_port = 0; + LIST_ITEM *p; + + switch (format) { + case FORMAT_TEXT: + printf("%*sVF Membership Report\n", indent, ""); + break; + case FORMAT_XML: + indent +=4; + printf("%*s\n", indent, ""); + break; + default: + break; + } + ShowPointFocus(focus, FIND_FLAG_FABRIC, format, indent, detail); + + // we need QOSDATA to have the SL2SC and PKey tables which are used by + // isVFMember + if (! (g_Fabric.flags & FF_QOSDATA) && g_snapshot_in_file) { + switch (format) { + case FORMAT_TEXT: + printf("%*sReport skipped: provided snapshot was created without -V option\n", indent, ""); + break; + case FORMAT_XML: + printf("%*s\n", indent, ""); + break; + default: + break; + } + goto done; + } + + for (p=QListHead(&g_Fabric.AllPorts); p != NULL; p = QListNext(&g_Fabric.AllPorts, p)) { + PortData *port = (PortData *)QListObj(p); + PortData *neighbor = (PortData *)port->neighbor; + + // VF Membership is based on SL2SC tables so N/A to ISLs + if (port->nodep->NodeInfo.NodeType == STL_NODE_SW && port->PortNum) { + if (! (neighbor && neighbor->nodep->NodeInfo.NodeType == STL_NODE_FI)) + continue; + } + + if (!ComparePortPoint(port, focus)) + continue; + + switch (format) { + case FORMAT_TEXT: + printf("%*s%.*s\n", indent, "", + NODE_DESCRIPTION_ARRAY_SIZE, + g_noname?g_name_marker:(char*)port->nodep->NodeDesc.NodeString ); + printf("%*sLID %u\t%s\tNodeGUID 0x%016"PRIx64"\n", indent, "", + port->EndPortLID, + StlNodeTypeToText(port->nodep->NodeInfo.NodeType), + port->nodep->NodeInfo.NodeGUID ); + printf("%*sPort %u\n", indent, "", port->PortNum); + + if (neighbor) { + indent+=4; + printf("%*sNeighbor Node: %.*s\n", indent, "", + NODE_DESCRIPTION_ARRAY_SIZE, + g_noname?g_name_marker:(char*)neighbor->nodep->NodeDesc.NodeString ); + printf("%*sLID %u\t%s\tNodeGUID 0x%016"PRIx64"\n", indent, "", + neighbor->EndPortLID, + StlNodeTypeToText(neighbor->nodep->NodeInfo.NodeType), + neighbor->nodep->NodeInfo.NodeGUID); + printf("%*sPort %u\n", indent, "", neighbor->PortNum); + indent-=4; + } + if (port->nodep->NodeInfo.NodeType == STL_NODE_SW && port->PortNum) { + if (neighbor && neighbor->nodep->NodeInfo.NodeType == STL_NODE_FI) { + // if the node is a switch and the neighbor is a CA, + // use the mappings from the CA + ShowPortVFMembershipText(neighbor, indent, detail); + } + // if the node is a switch and the neighbor is a switch + // then there is no VF membership + } else { + // node is a CA or switch port 0 + ShowPortVFMembershipText(port, indent, detail); + } + printf("\n"); + break; + case FORMAT_XML: + indent+=4; + printf("%*s\n", indent, "", + port->nodep->NodeInfo.NodeGUID, port->PortNum); + indent+=4; + XmlPrintHex64("NodeGUID", + port->nodep->NodeInfo.NodeGUID, indent); + XmlPrintDec("PortNum", port->PortNum, indent); + XmlPrintNodeType(port->nodep->NodeInfo.NodeType, indent); + XmlPrintNodeDesc((char*)port->nodep->NodeDesc.NodeString, indent); + if (port->nodep->NodeInfo.NodeType == STL_NODE_SW && port->PortNum) { + if (neighbor && neighbor->nodep->NodeInfo.NodeType == STL_NODE_FI) { + // if the node is a switch and the neighbor is a CA, + // use the mappings from the CA + ShowPortVFMembershipXML(neighbor, indent, detail); + } + // if the node is a switch and the neighbor is a switch + // then there is no VF membership + } else { + // node is a CA or switch port 0 + ShowPortVFMembershipXML(port, indent, detail); + } + indent-=4; + printf("%*s\n", indent, ""); + indent-=4; + break; + default: + break; + } + ct_port++; + } + + switch (format) { + case FORMAT_TEXT: + indent -= 4; + printf("%*s%d Reported Port(s)\n", indent, "", ct_port); + break; + case FORMAT_XML: + XmlPrintDec("ReportedPortCount", (unsigned)ct_port, indent+4); + break; + default: + break; + } +done: + switch (format) { + case FORMAT_TEXT: + DisplaySeparator(); + break; + case FORMAT_XML: + printf("%*s\n", indent, ""); + break; + default: + break; + } +} + +static void printQuarantinedNodeRecord(int indent, const STL_QUARANTINED_NODE_RECORD *pQuarantinedNodeRecord) +{ + int violStrLen = 256; + char violationString[violStrLen]; + int previousViolation = 0; + memset(violationString, 0, sizeof(violationString)); + + if(pQuarantinedNodeRecord->quarantineReasons & STL_QUARANTINE_REASON_SPOOF_GENERIC) { + strncat(violationString, "NodeGUID/NodeType Spoofing", violStrLen - strlen(violationString)); + previousViolation = 1; + } + if(pQuarantinedNodeRecord->quarantineReasons & STL_QUARANTINE_REASON_TOPO_NODE_DESC) { + strncat(violationString, previousViolation ? ", NodeDesc Mismatch" : "NodeDesc Mismatch", + violStrLen - strlen(violationString)); + previousViolation = 1; + } + if(pQuarantinedNodeRecord->quarantineReasons & STL_QUARANTINE_REASON_TOPO_NODE_GUID) { + strncat(violationString, previousViolation ? ", NodeGUID Mismatch" : "NodeGUID Mismatch", + violStrLen - strlen(violationString)); + previousViolation = 1; + } + if(pQuarantinedNodeRecord->quarantineReasons & STL_QUARANTINE_REASON_TOPO_PORT_GUID) { + strncat(violationString, previousViolation ? ", PortGUID Mismatch" : "PortGUID Mismatch", + violStrLen - strlen(violationString)); + previousViolation = 1; + } + if(pQuarantinedNodeRecord->quarantineReasons & STL_QUARANTINE_REASON_TOPO_UNDEFINED_LINK) { + strncat(violationString, previousViolation ? ", Undefined Link" : "Undefined Link", + violStrLen - strlen(violationString)); + previousViolation = 1; + } + if(pQuarantinedNodeRecord->quarantineReasons & STL_QUARANTINE_REASON_SMALL_MTU_SIZE) { + strncat(violationString, previousViolation ? ", Small MTU Size" : "Small MTU Size", + violStrLen - strlen(violationString)); + previousViolation = 1; + } + if(pQuarantinedNodeRecord->quarantineReasons & STL_QUARANTINE_REASON_VL_COUNT) { + strncat(violationString, previousViolation ? ", Incorrect VL Count" : "Incorrect VL Count", + violStrLen - strlen(violationString)); + previousViolation = 1; + } + + printf("%*sConnected to Port %d of (LID: 0x%x, NodeGUID: 0x%016" PRIx64 ")\n", indent, "", pQuarantinedNodeRecord->trustedPortNum, pQuarantinedNodeRecord->trustedLid, pQuarantinedNodeRecord->trustedNodeGUID); + printf("%*s Offending Node Actual NodeGUID: 0x%016" PRIx64 "\n", indent, "", pQuarantinedNodeRecord->trustedNeighborNodeGUID); + printf("%*s Violation(s): %s\n", indent, "", violationString); + + if(pQuarantinedNodeRecord->quarantineReasons & STL_QUARANTINE_REASON_TOPO_NODE_DESC) { + printf("%*s Expected Node Description: %.*s\n", indent, "", STL_NODE_DESCRIPTION_ARRAY_SIZE, pQuarantinedNodeRecord->expectedNodeInfo.nodeDesc.NodeString); + } + if(pQuarantinedNodeRecord->quarantineReasons & STL_QUARANTINE_REASON_TOPO_NODE_GUID) { + printf("%*s Expected NodeGUID: 0x%016" PRIx64 "\n", indent, "", pQuarantinedNodeRecord->expectedNodeInfo.nodeGUID); + } + if(pQuarantinedNodeRecord->quarantineReasons & STL_QUARANTINE_REASON_TOPO_PORT_GUID) { + printf("%*s Expected PortGUID: 0x%016" PRIx64 "\n", indent, "", pQuarantinedNodeRecord->expectedNodeInfo.portGUID); + } + + if(pQuarantinedNodeRecord->quarantineReasons & STL_QUARANTINE_REASON_SPOOF_GENERIC) { + printf("%*s \n", indent, ""); + } else { + printf("%*s Received node Information:\n", indent, ""); + } + + printf("%*s Node Description: %.*s\n", indent, "", NODE_DESCRIPTION_ARRAY_SIZE, pQuarantinedNodeRecord->NodeDesc.NodeString); + printf("%*s Type: %s Ports: %d PortNum: %d PartitionCap: %d\n", indent, "", StlNodeTypeToText(pQuarantinedNodeRecord->NodeInfo.NodeType), pQuarantinedNodeRecord->NodeInfo.NumPorts, pQuarantinedNodeRecord->NodeInfo.u1.s.LocalPortNum, pQuarantinedNodeRecord->NodeInfo.PartitionCap); + printf("%*s NodeGUID: 0x%016" PRIx64 " PortGUID: 0x%016" PRIx64 "\n", indent, "", pQuarantinedNodeRecord->NodeInfo.NodeGUID, pQuarantinedNodeRecord->NodeInfo.PortGUID); + printf("%*s SystemImageGuid: 0x%016" PRIx64 " BaseVersion: %d SmaVersion: %d\n", indent, "", pQuarantinedNodeRecord->NodeInfo.SystemImageGUID, pQuarantinedNodeRecord->NodeInfo.BaseVersion, pQuarantinedNodeRecord->NodeInfo.ClassVersion); + printf("%*s VendorID: 0x%x DeviceId: 0x%x Revision: 0x%x\n", indent, "", pQuarantinedNodeRecord->NodeInfo.u1.s.VendorID, pQuarantinedNodeRecord->NodeInfo.DeviceID, pQuarantinedNodeRecord->NodeInfo.Revision); +} + +void ShowQuarantineNodeReport(Point *focus, Format_t format, int indent, int detail) +{ + int ix; + PQUERY_RESULT_VALUES pQueryResults = NULL; + STL_QUARANTINED_NODE_RECORD_RESULTS *pQNRR; + STL_QUARANTINED_NODE_RECORD *pR; + struct omgt_port *omgt_port_session = NULL; + + ShowPointFocus(focus, FIND_FLAG_FABRIC, format, indent, detail); + + struct omgt_params params = {.debug_file = g_verbose > 2 ? stdout : NULL}; + if(omgt_open_port_by_guid(&omgt_port_session, g_portGuid, ¶ms) != FSUCCESS) + return; + omgt_set_timeout(omgt_port_session, g_ms_timeout); + if ( !(( pQueryResults = + GetAllQuarantinedNodes(omgt_port_session, &g_Fabric, focus, g_quiet) )) ) + return; + + pQNRR = (STL_QUARANTINED_NODE_RECORD_RESULTS *)pQueryResults->QueryResult; + pR = pQNRR->QuarantinedNodeRecords; + if (!pQNRR->NumQuarantinedNodeRecords) { /* no quarantined nodes found. */ + return; + } + switch (format) { + case FORMAT_TEXT: + printf("%*sQuarantinedNodes:\n", indent, ""); + break; + + case FORMAT_XML: + indent +=4; + printf("%*s\n", indent, ""); + indent +=4; + break; + + default: + break; + } + + // dump quarantined records data + for (ix = 0; ix < pQNRR->NumQuarantinedNodeRecords; ix++, pR++) + { + switch (format) { + case FORMAT_TEXT: + if (ix > 0) + DisplaySeparator(); + printQuarantinedNodeRecord(indent, pR); + break; + + case FORMAT_XML: + printf("%*s\n", indent, ""); + indent += 4; + XmlPrintHex64("TrustedNodeGUID", pR->trustedNodeGUID, indent); + XmlPrintDec("TrustedPortNum", pR->trustedPortNum, indent); + XmlPrintLID("TrustedLID", pR->trustedLid, indent); + XmlPrintHex64("NodeGUID", pR->NodeInfo.NodeGUID, indent); + XmlPrintHex64("PortGUID", pR->NodeInfo.PortGUID, indent); + XmlPrintNodeType(pR->NodeInfo.NodeType, indent); + XmlPrintNodeDesc((char*)pR->NodeDesc.NodeString, indent); + XmlPrintDec("BaseVer", pR->NodeInfo.BaseVersion, indent); + XmlPrintDec("SmaVer", pR->NodeInfo.ClassVersion, indent); + XmlPrintDec("NumPorts", pR->NodeInfo.NumPorts, indent); + XmlPrintHex64("SystemImageGUID", pR->NodeInfo.SystemImageGUID, indent); + XmlPrintDec("PartitionCap", pR->NodeInfo.PartitionCap, indent); + XmlPrintHex("DeviceID", pR->NodeInfo.DeviceID, indent); + XmlPrintHex("Revision", pR->NodeInfo.Revision, indent); + XmlPrintHex("VendorID", pR->NodeInfo.u1.s.VendorID, indent); + + if(pR->quarantineReasons) { + int expectedInfo = 0; + + printf("%*s\n", indent, ""); + indent += 4; + + if(pR->quarantineReasons & STL_QUARANTINE_REASON_SPOOF_GENERIC) { + printf("%*sNodeGUID/NodeType Spoofing\n", indent, ""); + } + if(pR->quarantineReasons & STL_QUARANTINE_REASON_TOPO_NODE_DESC) { + printf("%*sNodeDesc Mismatch\n", indent, ""); + expectedInfo = 1; + } + if(pR->quarantineReasons & STL_QUARANTINE_REASON_TOPO_NODE_GUID) { + printf("%*sNodeGUID Mismatch\n", indent, ""); + expectedInfo = 1; + } + if(pR->quarantineReasons & STL_QUARANTINE_REASON_TOPO_PORT_GUID) { + printf("%*sPortGUID Mismatch\n", indent, ""); + expectedInfo = 1; + } + if(pR->quarantineReasons & STL_QUARANTINE_REASON_TOPO_UNDEFINED_LINK) { + printf("%*sUndefined Link\n", indent, ""); + } + if(pR->quarantineReasons & STL_QUARANTINE_REASON_SMALL_MTU_SIZE) { + printf("%*sSmall MTU Size\n", indent, ""); + } + if(pR->quarantineReasons & STL_QUARANTINE_REASON_VL_COUNT) { + printf("%*sIncorrect VL Count\n", indent, ""); + } + + indent -= 4; + printf("%*s\n", indent, ""); + + if(expectedInfo) { + printf("%*s\n", indent, ""); + indent += 4; + + if(pR->quarantineReasons & STL_QUARANTINE_REASON_TOPO_NODE_DESC) { + XmlPrintStrLen("ExpectedNodeDesc", (char*) pR->expectedNodeInfo.nodeDesc.NodeString, STL_NODE_DESCRIPTION_ARRAY_SIZE, indent); + } + if(pR->quarantineReasons & STL_QUARANTINE_REASON_TOPO_NODE_GUID) { + XmlPrintHex64("ExpectedNodeGUID", pR->expectedNodeInfo.nodeGUID, indent); + } + if(pR->quarantineReasons & STL_QUARANTINE_REASON_TOPO_PORT_GUID) { + XmlPrintHex64("ExpectedPortGUID", pR->expectedNodeInfo.portGUID, indent); + } + + indent -= 4; + printf("%*s\n", indent, ""); + } + + + } + + indent -= 4; + printf("%*s\n", indent, ""); + default: + break; + } // End of switch (format) + + } // End of for (ix = 0; ix < pQNRR->NumQuarantinedNodeRecords; ix++, pR++) + + switch (format) { + case FORMAT_TEXT: + DisplaySeparator(); + break; + + case FORMAT_XML: + indent -= 4; + printf("%*s\n", indent, ""); + break; + + default: + break; + } + + if (pQueryResults != NULL) + omgt_free_query_result_buffer(pQueryResults); + if (omgt_port_session != NULL) + omgt_close_port(omgt_port_session); +} + +static void printDGMemberRecord(int indent, const STL_DEVICE_GROUP_MEMBER_RECORD *pRecord) +{ + printf("%*s LID: 0x%.*x\n", indent, "", (pRecord->LID <= IB_MAX_UCAST_LID ? 4:8) , pRecord->LID); + printf("%*s PortNum: %d\n", indent, "", pRecord->Port); + printf("%*s PortGUID: 0x%016" PRIx64 "\n", indent, "", pRecord->GUID); + printf("%*s NodeDesc: %s\n\n", indent, "", pRecord->NodeDescription.NodeString); +} + +void ShowDGMemberReport(Point *focus, Format_t format, int indent, int detail) +{ + int ix, printDGName=1; + int groupIndex, memberIndex; + PQUERY_RESULT_VALUES pQueryResults = NULL; + STL_DEVICE_GROUP_MEMBER_RECORD_RESULTS *pDGMR; + STL_DEVICE_GROUP_MEMBER_RECORD *pR; + struct omgt_port *omgt_port_session = NULL; + + ShowPointFocus(focus, FIND_FLAG_FABRIC, format, indent, detail); + + struct omgt_params params = {.debug_file = g_verbose > 2 ? stdout : NULL}; + if(omgt_open_port_by_guid(&omgt_port_session, g_portGuid, ¶ms) != FSUCCESS) + return; + omgt_set_timeout(omgt_port_session, g_ms_timeout); + if ( !(( pQueryResults = + GetAllDeviceGroupMemberRecords(omgt_port_session, &g_Fabric, focus, g_quiet) )) ) + return; + + pDGMR = (STL_DEVICE_GROUP_MEMBER_RECORD_RESULTS *)pQueryResults->QueryResult; + pR = pDGMR->Records; + if (!pDGMR->NumRecords) { /* no device group member records were found. */ + return; + } + switch (format) { + case FORMAT_TEXT: + printf("%*sDG Membership Report\n", indent, ""); + break; + case FORMAT_XML: + indent +=4; + printf("%*s\n", indent, ""); + indent +=4; + break; + default: + break; + } + + groupIndex=0; + memberIndex=0; + // dump device group member record data + for (ix = 0; ix < pDGMR->NumRecords; ix++, pR++) + { + switch (format) { + case FORMAT_TEXT: + if (printDGName) { + ++groupIndex; + if (ix > 0) + DisplaySeparator(); + printf("%*sDevice Group: %s\n", indent, "", pR->DeviceGroupName); + } + printDGMemberRecord(indent, pR); + printDGName=0; + // detect last record or last member of device group + if (ix < (pDGMR->NumRecords-1) && + strncmp((char*)&pR->DeviceGroupName, (char*)&((pR+1)->DeviceGroupName), MAX_DG_NAME)) { + printDGName=1; + } + break; + + case FORMAT_XML: + if (printDGName) { + printf("%*s\n", indent, "", groupIndex); + ++groupIndex; + memberIndex=0; + XmlPrintStrLen("Name", (char*)pR->DeviceGroupName, sizeof(pR->DeviceGroupName), indent); + indent += 4; + } + printf("%*s\n", indent, "", memberIndex); + ++memberIndex; + XmlPrintLID("LID", pR->LID, indent+4); + XmlPrintDec("PortNum", pR->Port, indent+4); + XmlPrintHex64("PortGUID", pR->GUID, indent+4); + XmlPrintNodeDesc((char*)pR->NodeDescription.NodeString, indent+4); + printf("%*s\n", indent, ""); + printDGName=0; + // detect last record or last member of device group + if ((ix == pDGMR->NumRecords-1) || + (ix < (pDGMR->NumRecords-1) && + strncmp((char*)&pR->DeviceGroupName, (char*)&((pR+1)->DeviceGroupName), MAX_DG_NAME))) { + indent -= 4; + printf("%*s\n", indent, ""); + printDGName=1; + } + default: + break; + } // End of switch (format) + + } // End of for (ix = 0; ix < pDGMR->NumRecords; ix++, pR++) + + switch (format) { + case FORMAT_TEXT: + printf("%*s%d Reported Device Group(s)\n", indent+4, "", groupIndex); + DisplaySeparator(); + break; + case FORMAT_XML: + XmlPrintDec("ReportedDeviceGroupCount", (unsigned)groupIndex, indent); + indent -= 4; + printf("%*s\n", indent, ""); + break; + default: + break; + } + + if (pQueryResults != NULL) + omgt_free_query_result_buffer(pQueryResults); + if (omgt_port_session != NULL) + omgt_close_port(omgt_port_session); +} + +// CableInfo is organized in 128-byte pages but is stored in 64-byte half-pages +// STL_CABLE_INFO_UP0_DD/STL_CABLE_INFO_STD use STL_CIB_STD_HIGH_PAGE_ADDR to +// STL_CIB_STD_END_ADDR inclusive (128-255). STL_CABLE_INFO_LOW0_STD/STL_CABLE_INFO_LOW0_DD +// use STL_CIB_STD_LOW_PAGE_ADDR to 127. +FSTATUS ShowPortCableHealth(PortData *portp, int indent, char *buf, uint16 length ){ + boolean qsfp_dd; + PrintDest_t destBuf; + CableTypeInfoType cableTypeInfo; + boolean cableLenValid; // Copper cable length valid + float rx_1, rx_2, rx_3, rx_4; // rx average optical power for lanes + float tx_1, tx_2, tx_3, tx_4; // tx average optical power for lanes + float temperature, voltage; + char tempStr[STL_CIB_STD_MAX_STRING + 1] = {'\0'}; + + // check input parameters + if (!portp) + return FINVALID_PARAMETER; + + //Initialize the buffer to store cable info per port + PrintDestInitBuffer(&destBuf, buf, length); + + PrintFunc(&destBuf,"%*s%s;%d;0x%016"PRIx64";", + indent, + "", + portp->nodep->NodeDesc.NodeString, + portp->nodep->NodeInfo.NodeType, + portp->nodep->NodeInfo.NodeGUID); + + // LID is displayed as xxx when persist or hard flag is set + if (g_persist || g_hard){ + PrintFunc(&destBuf,"xxxxxxxx;%3u;",portp->PortNum); + } else { + PrintFunc(&destBuf,"0x%x;%3u;", + portp->EndPortLID, portp->PortNum); + } + + //check if cabledata exists + if (!portp->pCableInfoData){ + PrintFunc(&destBuf,"NA;NA;NA;NA;NA;NA;NA;NA;NA;NA;NA;NA;NA;NA;NA;"); + return FSUCCESS; + } + + //Check for port type + if (STL_PORT_TYPE_STANDARD != portp->PortInfo.PortPhysConfig.s.PortType){ + fprintf(stderr, "ShowPortCableHealth: Not a standard port\n"); + return FUNAVAILABLE; + } + + //Get cable type + qsfp_dd = (*(portp->pCableInfoData) == STL_CIB_STD_QSFP_DD); + + //Handle DD cable info + if (qsfp_dd) { + //Handle data in Low Address page + STL_CABLE_INFO_LOW0_DD *pCableData = (STL_CABLE_INFO_LOW0_DD*)(portp->pCableInfoData + STL_CIB_STD_LOW_PAGE_ADDR); + //Access temperature and voltage + temperature = ntoh16(pCableData->temperature)/256.0; + voltage = ntoh16(pCableData->voltage)/10000.0; + PrintFunc(&destBuf,"%.2f;%.2f;",temperature, voltage); + + //Rx and Tx data in High Address page 17 is not accessible so displayed as "NA" + PrintFunc(&destBuf,"NA;NA;NA;NA;NA;NA;NA;NA;"); + + //Handle Data in High address page 0 + STL_CABLE_INFO_UP0_DD *pCableInfo = (STL_CABLE_INFO_UP0_DD *)(portp->pCableInfoData + STL_CIB_STD_HIGH_PAGE_ADDR); + StlCableInfoDecodeCableType(pCableInfo->cable_type, pCableInfo->connector, pCableInfo->ident, &cableTypeInfo); + cableLenValid = cableTypeInfo.cableLengthValid; + StlCableInfoDDCableLengthToText(pCableInfo->cableLengthEnc, cableLenValid, MAX_CABLE_LENGTH_STR_LEN, tempStr); + PrintFunc(&destBuf, "%s;", tempStr); + + memset(tempStr, 0, STL_CIB_STD_MAX_STRING + 1); + memcpy(tempStr, (char *)pCableInfo->vendor_name, sizeof(pCableInfo->vendor_name)); + StlCableInfoTrimTrailingWS(tempStr, sizeof(pCableInfo->vendor_name)); + PrintFunc(&destBuf, "%s;", tempStr); + + memset(tempStr, 0, STL_CIB_STD_MAX_STRING + 1); + memcpy(tempStr, (char *)pCableInfo->vendor_pn, sizeof(pCableInfo->vendor_pn)); + StlCableInfoTrimTrailingWS(tempStr, sizeof(pCableInfo->vendor_pn)); + PrintFunc(&destBuf, "%s;", tempStr); + + memset(tempStr, 0, STL_CIB_STD_MAX_STRING + 1); + memcpy(tempStr, (char *)pCableInfo->vendor_sn, sizeof(pCableInfo->vendor_sn)); + StlCableInfoTrimTrailingWS(tempStr, sizeof(pCableInfo->vendor_sn)); + PrintFunc(&destBuf, "%s;", tempStr); + + memset(tempStr, 0, STL_CIB_STD_MAX_STRING + 1); + StlCableInfoDateCodeToText(pCableInfo->date_code, tempStr); + PrintFunc(&destBuf, "%s;", tempStr); + //Handle cable info based on SFF-8636 Rev 2-5 + }else { + //Handle data in Low Address page + STL_CABLE_INFO_LOW0_STD *pCableData = (STL_CABLE_INFO_LOW0_STD*)(portp->pCableInfoData + STL_CIB_STD_LOW_PAGE_ADDR); + //Access temperature and voltage + temperature = ntoh16(pCableData->temperature)/256.0; + voltage = ntoh16(pCableData->voltage)/10000.0; + PrintFunc(&destBuf,"%.2f;%.2f;",temperature, voltage); + + //RX average optical power is stored in 2bytes, total of 8 bytes for RX_1, RX_2, RX_3, RX_4 + rx_1 = ntoh16(pCableData->rxOpticalPwr1)/10000.0; + rx_2 = ntoh16(pCableData->rxOpticalPwr2)/10000.0; + rx_3 = ntoh16(pCableData->rxOpticalPwr3)/10000.0; + rx_4 = ntoh16(pCableData->rxOpticalPwr4)/10000.0; + //TX average optical power is stored in 2bytes, total of 8 bytes for TX_1, TX_2, TX_3, TX_4 + tx_1 = ntoh16(pCableData->txOpticalPwr1)/10000.0; + tx_2 = ntoh16(pCableData->txOpticalPwr2)/10000.0; + tx_3 = ntoh16(pCableData->txOpticalPwr3)/10000.0; + tx_4 = ntoh16(pCableData->txOpticalPwr4)/10000.0; + + PrintFunc(&destBuf,"%.2f;%.2f;%.2f;%.2f;%.2f;%.2f;%.2f;%.2f;", + rx_1, rx_2, rx_3, rx_4, tx_1, tx_2, tx_3, tx_4 ); + + //Handle Data in High address page 0 + STL_CABLE_INFO_STD *pCableInfo = (STL_CABLE_INFO_STD *)(portp->pCableInfoData + STL_CIB_STD_HIGH_PAGE_ADDR); + StlCableInfoDecodeCableType(pCableInfo->dev_tech.s.xmit_tech, pCableInfo->connector, pCableInfo->ident, &cableTypeInfo); + cableLenValid = cableTypeInfo.cableLengthValid; + StlCableInfoOM4LengthToText(pCableInfo->len_om4, cableLenValid, MAX_CABLE_LENGTH_STR_LEN, tempStr); + PrintFunc(&destBuf, "%s;", tempStr); + + memset(tempStr, 0, STL_CIB_STD_MAX_STRING + 1); + memcpy(tempStr, (char *)pCableInfo->vendor_name, sizeof(pCableInfo->vendor_name)); + StlCableInfoTrimTrailingWS(tempStr, sizeof(pCableInfo->vendor_name)); + PrintFunc(&destBuf, "%s;", tempStr); + + memset(tempStr, 0, STL_CIB_STD_MAX_STRING + 1); + memcpy(tempStr, (char *)pCableInfo->vendor_pn, sizeof(pCableInfo->vendor_pn)); + StlCableInfoTrimTrailingWS(tempStr, sizeof(pCableInfo->vendor_pn)); + PrintFunc(&destBuf, "%s;", tempStr); + + memset(tempStr, 0, STL_CIB_STD_MAX_STRING + 1); + memcpy(tempStr, (char *)pCableInfo->vendor_sn, sizeof(pCableInfo->vendor_sn)); + StlCableInfoTrimTrailingWS(tempStr, sizeof(pCableInfo->vendor_sn)); + PrintFunc(&destBuf, "%s;", tempStr); + + memset(tempStr, 0, STL_CIB_STD_MAX_STRING + 1); + StlCableInfoDateCodeToText(pCableInfo->date_code, tempStr); + PrintFunc(&destBuf, "%s;", tempStr); + } + + return FSUCCESS; +} + +//Cable health Data length per port +#define STL_CABLEHEALTH_DATA_LENGTH_PER_PORT 256 + +//Cable Health Report Header string +#define STL_CABLEHEALTH_HEADER_STRING \ +"Pri Node Name;" "Pri Node Type;" "Pri Node GUID;"\ +"Pri LID;" "Pri PortNum;" "Pri Temperature;"\ +"Pri Voltage;" "Pri RX_1;" "Pri RX_2;"\ +"Pri RX_3;" "Pri RX_4;" "Pri TX_1;"\ +"Pri TX_2;" "Pri TX_3;" "Pri TX_4;"\ +"Pri Cable Length;" "Pri Vendor Name;" "Pri Vendor PartNumber;"\ +"Pri Vendor SerialNumber;" "Pri Vendor Manufacture Date;"\ +"Sec Node Name;" "Sec Node Type;" "Sec Node GUID;"\ +"Sec LID;" "Sec PortNum;" "Sec Temperature;"\ +"Sec Voltage;" "Sec RX_1;" "Sec RX_2;"\ +"Sec RX_3;" "Sec RX_4;" "Sec TX_1;"\ +"Sec TX_2;" "Sec TX_3;" "Sec TX_4;"\ +"Sec Cable Length;" "Sec Vendor Name;" "Sec Vendor PartNumber;"\ +"Sec Vendor SerialNumber;" "Sec Vendor Manufacture Date;" + +#define CABLEHEALTH_EMPTY_FIELD ";;;;;;;;;;;;;;;" + + +void ShowCableHealthReport(Point *focus, Format_t format, int indent, int detail) +{ + LIST_ITEM *p; + char tempBuf1[STL_CABLEHEALTH_DATA_LENGTH_PER_PORT]; + char tempBuf2[STL_CABLEHEALTH_DATA_LENGTH_PER_PORT]; + boolean first_entry = 1; + FSTATUS status1 = FERROR; + FSTATUS status2 = FERROR; + PrintDest_t destFile; + + PrintDestInitFile(&destFile, stdout); + + ShowPointFocus(focus, FIND_FLAG_FABRIC, format, indent, detail); + + for (p=QListHead(&g_Fabric.AllPorts); p != NULL; p = QListNext(&g_Fabric.AllPorts, p)) { + PortData *portp1, *portp2; + portp1 = (PortData *)QListObj(p); + + // skip backplane (ISL) ports + if(isInternalLink(portp1)) + continue; + + // to avoid duplicated processing, only process "from" ports in link + if (!portp1->from) + continue; + + if (! ComparePortPoint(portp1, focus) && ! ComparePortPoint(portp1->neighbor, focus)) + continue; + + //Get Cable Health report for from-port + memset(tempBuf1, 0, STL_CABLEHEALTH_DATA_LENGTH_PER_PORT); + status1 = ShowPortCableHealth(portp1, indent, tempBuf1, STL_CABLEHEALTH_DATA_LENGTH_PER_PORT); + + // get port on the other side + portp2 = portp1->neighbor; + + if(portp2) { + //Get Cable Health report for to-port + memset(tempBuf2, 0, STL_CABLEHEALTH_DATA_LENGTH_PER_PORT); + status2 = ShowPortCableHealth(portp2, indent, tempBuf2, STL_CABLEHEALTH_DATA_LENGTH_PER_PORT); + } + + if((FSUCCESS == status1)|| (FSUCCESS == status2)) { + //show header once + if(first_entry ){ + PrintFunc(&destFile, "%s\n", "Cable Health Report"); + PrintFunc(&destFile, "%s\n", STL_CABLEHEALTH_HEADER_STRING); + first_entry = 0; + } + + PrintFunc(&destFile, "%s%s\n", + (FSUCCESS == status1)?tempBuf1: + strncat(tempBuf1,CABLEHEALTH_EMPTY_FIELD,strlen(CABLEHEALTH_EMPTY_FIELD) + 1), + (FSUCCESS == status2)?tempBuf2: + strncat(tempBuf2,CABLEHEALTH_EMPTY_FIELD,strlen(CABLEHEALTH_EMPTY_FIELD) + 1)); + } + } + + if(first_entry) + fprintf(stderr, "No Cable Health Records Returned\n"); +} + +// command line options, each has a short and long flag name +struct option options[] = { + // basic controls + { "verbose", no_argument, NULL, 'v' }, + { "quiet", no_argument, NULL, 'q' }, + { "hfi", required_argument, NULL, 'h' }, + { "port", required_argument, NULL, 'p' }, + { "output", required_argument, NULL, 'o' }, + { "detail", required_argument, NULL, 'd' }, + { "persist", no_argument, NULL, 'P' }, + { "hard", no_argument, NULL, 'H' }, + { "noname", no_argument, NULL, 'N' }, + { "stats", no_argument, NULL, 's' }, + { "interval", required_argument, NULL, 'i' }, + { "clear", no_argument, NULL, 'C' }, + { "clearall", no_argument, NULL, 'a' }, + { "smadirect", no_argument, NULL, 'm' }, + { "pmadirect", no_argument, NULL, 'M' }, + { "routes", no_argument, NULL, 'r' }, + { "limit", no_argument, NULL, 'L' }, + { "config", required_argument, NULL, 'c' }, + { "focus", required_argument, NULL, 'F' }, + { "src", required_argument, NULL, 'S' }, + { "dest", required_argument, NULL, 'D' }, + { "xml", no_argument, NULL, 'x' }, + { "infile", required_argument, NULL, 'X' }, + { "topology", required_argument, NULL, 'T' }, + { "quietfocus", no_argument, NULL, 'Q' }, + { "vltables", no_argument, NULL, 'V' }, + { "allports", no_argument, NULL, 'A' }, + { "begin", required_argument, NULL, 'b'}, + { "end", required_argument, NULL, 'e'}, + { "rc", required_argument, NULL, 'z' }, + { "timeout", required_argument, NULL, '!' }, + { "help", no_argument, NULL, '$' }, // use an invalid option character + + { 0 } +}; + +void Usage_full(void) +{ + fprintf(stderr, "Usage: opareport [-v][-q] [-h hfi] [-p port] [-o report] [-d detail]\n" + " [-P|-H] [-N] [-x] [-X snapshot_input] [-T topology_input]\n" + " [-s] [-r] [-V] [-i seconds] [-b date_time] [-e date_time]\n" + " [-C] [-a] [-m] [-M] [-A] [-c file] [-L] [-F point]\n" + " [-S point] [-D point] [-Q]\n"); + fprintf(stderr, " or\n"); + fprintf(stderr, " opareport --help\n"); + fprintf(stderr, " --help - produce full help text\n"); + fprintf(stderr, " -v/--verbose - verbose output\n"); + fprintf(stderr, " -q/--quiet - disable progress reports\n"); + fprintf(stderr, " -h/--hfi hfi - hfi, numbered 1..n, 0= -p port will be a\n"); + fprintf(stderr, " system wide port num (default is 0)\n"); + fprintf(stderr, " -p/--port port - port, numbered 1..n, 0=1st active\n"); + fprintf(stderr, " (default is 1st active)\n"); + fprintf(stderr, " --timeout - timeout(wait time for response) in ms, default is 1000ms\n"); + fprintf(stderr, " -o/--output report - report type for output\n"); + fprintf(stderr, " -d/--detail level - level of detail 0-n for output, default is 2\n"); + fprintf(stderr, " -P/--persist - only include data persistent across reboots\n"); + fprintf(stderr, " -H/--hard - only include permanent hardware data\n"); + fprintf(stderr, " -N/--noname - omit node and IOC names\n"); + fprintf(stderr, " -x/--xml - output in xml\n"); + fprintf(stderr, " -X/--infile snapshot_input\n"); + fprintf(stderr, " - generate report using data in snapshot_input\n"); + fprintf(stderr, " snapshot_input must have been generated via\n"); + fprintf(stderr, " previous -o snapshot run.\n"); + fprintf(stderr, " When used, -s, -i, -C and -a options are ignored\n"); + fprintf(stderr, " '-' may be used to specify stdin\n"); + fprintf(stderr, " -T/--topology topology_input\n"); + fprintf(stderr, " - use topology_input file to augment and\n"); + fprintf(stderr, " verify fabric information. When used various\n"); + fprintf(stderr, " reports can be augmented with information\n"); + fprintf(stderr, " not available electronically (such as cable\n"); + fprintf(stderr, " labels).\n"); + fprintf(stderr, " '-' may be used to specify stdin\n"); + fprintf(stderr, " -s/--stats - get performance stats for all ports\n"); + fprintf(stderr, " -i/--interval seconds - obtain performance stats over interval seconds\n"); + fprintf(stderr, " clears all stats, waits interval seconds,\n"); + fprintf(stderr, " then generates report. Implies -s\n"); + fprintf(stderr, " -b/--begin date_time - obtain past performance stats over interval\n"); + fprintf(stderr, " beginning at date_time. Implies -s\n"); + fprintf(stderr, " -e/--end date_time - obtain past performance stats over interval\n"); + fprintf(stderr, " ending at date_time. Implies -s\n"); + fprintf(stderr, " For both -b and -e, date_time may be a time\n"); + fprintf(stderr, " entered as HH:MM[:SS] or date as mm/dd/YYYY,\n"); + fprintf(stderr, " dd.mm.YYYY, YYYY-mm-dd or date followed by time\n"); + fprintf(stderr, " e.g. \"2016-07-04 14:40\". Relative times are\n"); + fprintf(stderr, " taken as \"x [second|minute|hour|day](s) ago.\"\n"); + fprintf(stderr, " -C/--clear - clear performance stats for all ports\n"); + fprintf(stderr, " - only stats with error thresholds are cleared\n"); + fprintf(stderr, " - clear occurs after generating report\n"); + fprintf(stderr, " -a/--clearall - clear all performance stats for all ports\n"); + fprintf(stderr, " -m/--smadirect - access fabric information directly from SMA\n"); + fprintf(stderr, " -M/--pmadirect - access performance stats via direct PMA\n"); + fprintf(stderr, " -A/--allports - also get PortInfo for down switch ports.\n"); + fprintf(stderr, " uses direct SMA to get this data.\n"); + fprintf(stderr, " If used with -M will also get PMA stats\n"); + fprintf(stderr, " for down switch ports.\n"); + fprintf(stderr, " -c/--config file - error thresholds config file, default is\n"); + fprintf(stderr, " %s\n", CONFIG_FILE); + fprintf(stderr, " -L/--limit - For port error counters check (-o errors)\n"); + fprintf(stderr, " and port counters clear (-C or -i) with -F\n"); + fprintf(stderr, " limit operation to exact specified focus.\n"); + fprintf(stderr, " Normally the neighbor of each selected\n"); + fprintf(stderr, " port would also be checked/cleared\n"); + fprintf(stderr, " Does not affect other reports\n"); + fprintf(stderr, " -F/--focus point - focus area for report\n"); + fprintf(stderr, " Limits output to reflect a subsection of\n"); + fprintf(stderr, " the fabric. May not work with all reports.\n"); + fprintf(stderr, " (For example, route, mcgroups, and the verify*\n"); + fprintf(stderr, " reports may ignore the option or not generate\n"); + fprintf(stderr, " useful results.)\n"); + fprintf(stderr, " -S/--src point - source for trace route, default is local port\n"); + fprintf(stderr, " -D/--dest point - destination for trace route\n"); + fprintf(stderr, " -Q/--quietfocus - do not include focus description in report\n"); + fprintf(stderr, "The -h and -p options permit a variety of selections:\n"); + fprintf(stderr, " -h 0 - 1st active port in system (this is the default)\n"); + fprintf(stderr, " -h 0 -p 0 - 1st active port in system\n"); + fprintf(stderr, " -h x - 1st active port on HFI x\n"); + fprintf(stderr, " -h x -p 0 - 1st active port on HFI x\n"); + fprintf(stderr, " -h 0 -p y - port y within system (irrespective of which\n"); + fprintf(stderr, " ports are active)\n"); + fprintf(stderr, " -h x -p y - HFI x, port y\n"); + fprintf(stderr, "Snapshot specific Options:\n"); + fprintf(stderr, " -r/--routes - get routing tables for all switches\n"); + fprintf(stderr, " -V/--vltables - get the P-Key tables for all nodes and\n"); + fprintf(stderr, " QOS VL-related tables for all ports\n"); + fprintf(stderr, "Report Types:\n"); + fprintf(stderr, " comps - summary of all systems and SMs in fabric\n"); + fprintf(stderr, " brcomps - brief summary of all systems and SMs in fabric\n"); + fprintf(stderr, " nodes - summary of all node types and SMs in fabric\n"); + fprintf(stderr, " brnodes - brief summary of all node types and SMs in\n"); + fprintf(stderr, " fabric\n"); + fprintf(stderr, " ious - summary of all IO Units in fabric\n"); + fprintf(stderr, " lids - summary of all LIDs in fabric\n"); + fprintf(stderr, " linkinfo - summary of all links with LIDs in fabric\n"); + fprintf(stderr, " links - summary of all links\n"); + fprintf(stderr, " extlinks - summary of links external to systems\n"); + fprintf(stderr, " filinks - summary of links to FIs\n"); + fprintf(stderr, " islinks - summary of inter-switch links\n"); + fprintf(stderr, " extislinks - summary of inter-switch links external to systems\n"); + fprintf(stderr, " slowlinks - summary of links running slower than expected\n"); + fprintf(stderr, " slowconfiglinks - summary of links configured to run slower than\n"); + fprintf(stderr, " supported includes slowlinks\n"); + fprintf(stderr, " slowconnlinks - summary of links connected with mismatched speed\n"); + fprintf(stderr, " potential includes slowconfiglinks\n"); + fprintf(stderr, " misconfiglinks - summary of links configured to run slower than\n"); + fprintf(stderr, " supported\n"); + fprintf(stderr, " misconnlinks - summary of links connected with mismatched speed\n"); + fprintf(stderr, " potential\n"); + fprintf(stderr, " errors - summary of links whose errors exceed counts in\n"); + fprintf(stderr, " config file\n"); + fprintf(stderr, " otherports - summary of ports not connected to this fabric\n"); + fprintf(stderr, " linear - summary of linear forwarding data base (FDB) for\n"); + fprintf(stderr, " each Switch\n"); + fprintf(stderr, " mcast - summary of multicast FDB for each Switch\n"); + fprintf(stderr, " mcgroups - summary of multicast groups\n"); + fprintf(stderr, " portusage - summary of ports referenced in linear FDB for\n"); + fprintf(stderr, " each Switch, broken down by NodeType of DLID\n"); + fprintf(stderr, " pathusage - summary of number of FI to FI paths routed\n"); + fprintf(stderr, " through each switch port\n"); + fprintf(stderr, " treepathusage - analysis of number of FI to FI paths routed\n"); + fprintf(stderr, " through each switch port for a fat tree\n"); + fprintf(stderr, " portgroups - summary of adaptive routing port groups for each\n"); + fprintf(stderr, " Switch\n"); + fprintf(stderr, " quarantinednodes - summary of quarantined nodes\n"); + fprintf(stderr, " validateroutes - validate all routes in the fabric\n"); + fprintf(stderr, " validatevlroutes - validate all routes in the fabric using SLSC,\n"); + fprintf(stderr, " SCSC, and SCVL tables\n"); + fprintf(stderr, " validatepgs - validate all port groups in the fabric\n"); + fprintf(stderr, " validatecreditloops - validate topology configuration of the fabric to\n"); + fprintf(stderr, " identify any existing credit loops\n"); + fprintf(stderr, " validatevlcreditloops - validate topology configuration of the fabric\n"); + fprintf(stderr, " including SLSC, SCSC, and SCVL tables to identify\n"); + fprintf(stderr, " any existing credit loops\n"); + fprintf(stderr, " validatemcroutes - validate multicast routes of the fabric to\n"); + fprintf(stderr, " identify loops in multicast forwarding tables and\n"); + fprintf(stderr, " detect MFT-multicast membership inconsistencies.\n"); + fprintf(stderr, " vfinfo - summary of vFabric information\n"); + fprintf(stderr, " vfmember - summary of vFabric membership information\n"); + fprintf(stderr, " dgmember - summary of DeviceGroup membership information\n"); + fprintf(stderr, " verifyfis - compare fabric (or snapshot) FIs to supplied\n"); + fprintf(stderr, " topology and identify differences and omissions\n"); + fprintf(stderr, " verifysws - compare fabric (or snapshot) Switches to\n"); + fprintf(stderr, " supplied topology and identify differences and\n"); + fprintf(stderr, " omissions\n"); + fprintf(stderr, " verifynodes - verifyfis and verifysws reports\n"); + fprintf(stderr, " verifysms - compare fabric (or snapshot) SMs to supplied\n"); + fprintf(stderr, " topology and identify differences and omissions\n"); + fprintf(stderr, " verifylinks - compare fabric (or snapshot) links to supplied\n"); + fprintf(stderr, " topology and identify differences and omissions\n"); + fprintf(stderr, " verifyextlinks - compare fabric (or snapshot) links to supplied\n"); + fprintf(stderr, " topology and identify differences and omissions\n"); + fprintf(stderr, " limit analysis to links external to systems\n"); + fprintf(stderr, " verifyfilinks - compare fabric (or snapshot) links to supplied\n"); + fprintf(stderr, " topology and identify differences and omissions\n"); + fprintf(stderr, " limit analysis to links to FIs\n"); + fprintf(stderr, " verifyislinks - compare fabric (or snapshot) links to supplied\n"); + fprintf(stderr, " topology and identify differences and omissions\n"); + fprintf(stderr, " limit analysis to inter-switch links\n"); + fprintf(stderr, " verifyextislinks - compare fabric (or snapshot) links to supplied\n"); + fprintf(stderr, " topology and identify differences and omissions\n"); + fprintf(stderr, " limit analysis to inter-switch links external to\n"); + fprintf(stderr, " systems\n"); + fprintf(stderr, " verifyall - verifyfis, verifysws, verifysms and verifylinks\n"); + fprintf(stderr, " reports\n"); + fprintf(stderr, " all - comp, nodes, ious, links, extlinks,\n"); + fprintf(stderr, " slowconnlinks, and errors reports\n"); + fprintf(stderr, " route - trace route between -S and -D points\n"); + fprintf(stderr, " bfrctrl - report Buffer Control Tables for all ports\n"); + fprintf(stderr, " snapshot - output snapshot of fabric state for later use as\n"); + fprintf(stderr, " snapshot_input implies -x. May not be combined\n"); + fprintf(stderr, " with other reports. When selected, -F, -P, -H,\n"); + fprintf(stderr, " -N options are ignored\n"); + fprintf(stderr, " topology - output the topology of the fabric for later use\n"); + fprintf(stderr, " as topology_input implies -x. May not be\n"); + fprintf(stderr, " combined with other reports\n"); + fprintf(stderr, " Use with detail level 3 or more to get Port element\n"); + fprintf(stderr, " under Node in output xml\n"); + fprintf(stderr, " none - no report, useful if just want to clear stats\n"); + fprintf(stderr, "Point Syntax:\n"); + fprintf(stderr, " gid:value - value is numeric port gid of form: subnet:guid\n"); + fprintf(stderr, " lid:value - value is numeric lid\n"); + fprintf(stderr, " lid:value:node - value is numeric lid, selects node with given\n"); + fprintf(stderr, " lid\n"); + fprintf(stderr, " lid:value:port:value2 - value is numeric lid of node, value2 is port #\n"); + fprintf(stderr, " portguid:value - value is numeric port guid\n"); + fprintf(stderr, " nodeguid:value - value is numeric node guid\n"); + fprintf(stderr, " nodeguid:value1:port:value2\n"); + fprintf(stderr, " - value1 is numeric node guid, value2 is port #\n"); + fprintf(stderr, " iocguid:value - value is numeric IOC guid\n"); + fprintf(stderr, " iocguid:value1:port:value2 - value1 is numeric IOC guid, value2 is port #\n"); + fprintf(stderr, " systemguid:value - value is numeric system image guid\n"); + fprintf(stderr, " systemguid:value1:port:value2\n"); + fprintf(stderr, " - value1 is numeric system image guid\n"); + fprintf(stderr, " value2 is port #\n"); + fprintf(stderr, " ioc:value - value is IOC Profile ID String (IOC Name)\n"); + fprintf(stderr, " ioc:value1:port:value2 - value1 is IOC Profile ID String (IOC Name)\n"); + fprintf(stderr, " value2 is port #\n"); + fprintf(stderr, " iocpat:value - value is glob pattern for IOC Profile ID String\n"); + fprintf(stderr, " (IOC Name)\n"); + fprintf(stderr, " iocpat:value1:port:value2 - value1 is glob pattern for IOC Profile ID String\n"); + fprintf(stderr, " (IOC Name), value2 is port #\n"); + fprintf(stderr, " ioctype:value - value is IOC type (SRP or OTHER)\n"); + fprintf(stderr, " ioctype:value1:port:value2 - value1 is IOC type (SRP or OTHER)\n"); + fprintf(stderr, " value2 is port #\n"); + fprintf(stderr, " node:value - value is node description (node name)\n"); + fprintf(stderr, " node:value1:port:value2 - value1 is node description (node name)\n"); + fprintf(stderr, " value2 is port #\n"); + fprintf(stderr, " nodepat:value - value is glob pattern for node description (node\n"); + fprintf(stderr, " name)\n"); + fprintf(stderr, " nodepat:value1:port:value2 - value1 is glob pattern for node description\n"); + fprintf(stderr, " (node name), value2 is port #\n"); + fprintf(stderr, " nodedetpat:value - value is glob pattern for node details\n"); + fprintf(stderr, " nodedetpat:value1:port:value2\n"); + fprintf(stderr, " - value1 is glob pattern for node details,\n"); + fprintf(stderr, " value2 is port #\n"); + fprintf(stderr, " nodetype:value - value is node type (SW or FI)\n"); + fprintf(stderr, " nodetype:value1:port:value2\n"); + fprintf(stderr, " - value1 is node type (SW or FI)\n"); + fprintf(stderr, " value2 is port #\n"); + fprintf(stderr, " rate:value - value is string for rate (25g, 50g, 75g, 100g)\n"); + fprintf(stderr, " omits switch mgmt port 0\n"); + fprintf(stderr, " portstate:value - value is string for state (down, init, armed,\n"); + fprintf(stderr, " active, notactive, initarmed)\n"); + fprintf(stderr, " portphysstate:value - value is string for phys state (polling,\n"); + fprintf(stderr, " disabled, training, linkup, recovery, offline,\n"); + fprintf(stderr, " test)\n"); + fprintf(stderr, " mtucap:value - value is MTU size (2048, 4096, 8192, 10240)\n"); + fprintf(stderr, " omits switch mgmt port 0\n"); + fprintf(stderr, " labelpat:value - value is glob pattern for cable label\n"); + fprintf(stderr, " lengthpat:value - value is glob pattern for cable length\n"); + fprintf(stderr, " cabledetpat:value - value is glob pattern for cable details\n"); + fprintf(stderr, " cabinflenpat:value - value is glob pattern for cable info length\n"); + fprintf(stderr, " cabinfvendnamepat:value - value is glob pattern for cable info vendor name\n"); + fprintf(stderr, " cabinfvendpnpat:value - value is glob pattern for cable info vendor PN\n"); + fprintf(stderr, " cabinfvendrevpat:value - value is glob pattern for cable info vendor rev\n"); + fprintf(stderr, " cabinfvendsnpat:value - value is glob pattern for cable info vendor SN\n"); + fprintf(stderr, " cabinftype:value - value is either 'optical', 'passive_copper', \n"); + fprintf(stderr, " 'active_copper' or 'unknown' \n"); + fprintf(stderr, " linkdetpat:value - value is glob pattern for link details\n"); + fprintf(stderr, " portdetpat:value - value is glob pattern for port details\n"); + fprintf(stderr, " sm - master SM\n"); + fprintf(stderr, " smdetpat:value - value is glob pattern for sm details\n"); + fprintf(stderr, " route:point1:point2 - all ports along the routes between the 2 given\n"); + fprintf(stderr, " points\n"); + fprintf(stderr, " led:value - value is either 'on' or 'off' for LED port beacon\n"); + fprintf(stderr, " linkqual:value - ports with a link quality equal to value\n"); + fprintf(stderr, " linkqualLE:value - ports with a link quality less than or equal to\n"); + fprintf(stderr, " value\n"); + fprintf(stderr, " linkqualGE:value - ports with a link quality greater than or equal\n"); + fprintf(stderr, " to value\n"); + fprintf(stderr, " nodepatfile:FILENAME - name of file with list of nodes\n"); + fprintf(stderr, " nodepairpatfile:FILENAME - name of file with list of node pairs separated by colon\n"); + fprintf(stderr, " ldr - ports with a non-zero link down reason or neighbor\n"); + fprintf(stderr, " link down reason\n"); + fprintf(stderr, " ldr:value - ports with a link down reason or neighbor link down\n"); + fprintf(stderr, " reason equal to value\n"); + fprintf(stderr, "Examples:\n"); + fprintf(stderr, " opareport -o comps -d 3\n"); + fprintf(stderr, " opareport -o errors -o slowlinks\n"); + fprintf(stderr, " opareport -o nodes -F portguid:0x00066a00a000447b\n"); + fprintf(stderr, " opareport -o nodes -F nodeguid:0x001175019800447b:port:1\n"); + fprintf(stderr, " opareport -o nodes -F nodeguid:0x001175019800447b\n"); + fprintf(stderr, " opareport -o nodes -F 'node:duster hfi1_0'\n"); + fprintf(stderr, " opareport -o nodes -F 'node:duster hfi1_0:port:1'\n"); + fprintf(stderr, " opareport -o nodes -F 'nodepat:d*'\n"); + fprintf(stderr, " opareport -o nodes -F 'nodepat:d*:port:1'\n"); + fprintf(stderr, " opareport -o nodes -F 'nodedetpat:compute*'\n"); + fprintf(stderr, " opareport -o nodes -F 'nodedetpat:compute*:port:1'\n"); + fprintf(stderr, " opareport -o nodes -F nodetype:FI\n"); + fprintf(stderr, " opareport -o nodes -F nodetype:FI:port:1\n"); + fprintf(stderr, " opareport -o nodes -F lid:1\n"); + fprintf(stderr, " opareport -o nodes -F led:on\n"); + fprintf(stderr, " opareport -o nodes -F led:off\n"); + fprintf(stderr, " opareport -o nodes -F lid:1:node\n"); + fprintf(stderr, " opareport -o nodes -F lid:1:port:2\n"); + fprintf(stderr, " opareport -o nodes -F gid:0xfe80000000000000:0x00066a00a000447b\n"); + fprintf(stderr, " opareport -o nodes -F systemguid:0x001175019800447b\n"); + fprintf(stderr, " opareport -o nodes -F systemguid:0x001175019800447b:port:1\n"); + fprintf(stderr, " opareport -o nodes -F iocguid:0x00117501300001e0\n"); + fprintf(stderr, " opareport -o nodes -F iocguid:0x00117501300001e0:port:2\n"); + fprintf(stderr, " opareport -o nodes -F 'ioc:Chassis 0x00066A005000010C, Slot 2, IOC 1'\n"); + fprintf(stderr, " opareport -o nodes -F 'ioc:Chassis 0x00066A005000010C, Slot 2, IOC 1:port:2'\n"); + fprintf(stderr, " opareport -o nodes -F 'iocpat:*Slot 2*'\n"); + fprintf(stderr, " opareport -o nodes -F 'iocpat:*Slot 2*:port:2'\n"); + fprintf(stderr, " opareport -o nodes -F ioctype:SRP\n"); + fprintf(stderr, " opareport -o nodes -F ioctype:SRP:port:2\n"); + fprintf(stderr, " opareport -o extlinks -F rate:100g\n"); + fprintf(stderr, " opareport -o extlinks -F portstate:armed\n"); + fprintf(stderr, " opareport -o extlinks -F portphysstate:linkup\n"); + fprintf(stderr, " opareport -o extlinks -F 'labelpat:S1345*'\n"); + fprintf(stderr, " opareport -o extlinks -F 'lengthpat:11m'\n"); + fprintf(stderr, " opareport -o extlinks -F 'cabledetpat:*hitachi*'\n"); + fprintf(stderr, " opareport -o extlinks -F 'linkdetpat:*core ISL*'\n"); + fprintf(stderr, " opareport -o extlinks -F 'portdetpat:*mgmt*'\n"); + fprintf(stderr, " opareport -o links -F mtucap:2048\n"); + fprintf(stderr, " opareport -o nodes -F sm\n"); + fprintf(stderr, " opareport -o nodes -F 'smdetpat:primary*'\n"); + fprintf(stderr, " opareport -o nodes -F 'route:node:duster hfi1_0:node:cuda hfi1_0'\n"); + fprintf(stderr, " opareport -o nodes -F \\\n"); + fprintf(stderr, " 'route:node:duster hfi1_0:port:1:node:cuda hfi1_0:port:2'\n"); + fprintf(stderr, " opareport -o treepathusage -F nodepairpatfile:FILENAME\n"); + fprintf(stderr, " opareport -o pathusage -F nodepatfile:FILENAME\n"); + fprintf(stderr, " opareport -s -o snapshot > file\n"); + fprintf(stderr, " opareport -o topology > topology.xml\n"); + fprintf(stderr, " opareport -o errors -X file\n"); + fprintf(stderr, " opareport -s --begin \"2 days ago\"\n"); + fprintf(stderr, " opareport -s --begin \"12:30\" --end \"14:00\"\n"); + fprintf(stderr, " opareport -o linkinfo -x > file\n"); + exit(0); +} + +void Usage(void) +{ + fprintf(stderr, "Usage: opareport [-v][-q] [-o report] [-d detail] [-x] [-s] [-i seconds] [-C]\n"); + fprintf(stderr, " [-b date_time] [-e date_time]\n"); + fprintf(stderr, " or\n"); + fprintf(stderr, " opareport --help\n"); + fprintf(stderr, " --help - produce full help text\n"); + fprintf(stderr, " -v/--verbose - verbose output\n"); + fprintf(stderr, " -q/--quiet - disable progress reports\n"); + fprintf(stderr, " -o/--output report - report type for output\n"); + fprintf(stderr, " -d/--detail level - level of detail 0-n for output, default is 2\n"); + fprintf(stderr, " -x/--xml - output in xml\n"); + fprintf(stderr, " -s/--stats - get performance stats for all ports\n"); + fprintf(stderr, " -i/--interval seconds - obtain performance stats over interval seconds\n"); + fprintf(stderr, " clears all stats, waits interval seconds,\n"); + fprintf(stderr, " then generates report. Implies -s\n"); + fprintf(stderr, " -b/--begin date_time - obtain past performance stats over interval\n"); + fprintf(stderr, " beginning at date_time. Implies -s\n"); + fprintf(stderr, " -e/--end date_time - obtain past performance stats over interval\n"); + fprintf(stderr, " ending at date_time. Implies -s\n"); + fprintf(stderr, " -C/--clear - clear performance stats for all ports\n"); + fprintf(stderr, " - only stats with error thresholds are cleared\n"); + fprintf(stderr, " - clear occurs after generating report\n"); + fprintf(stderr, "Report Types (abridged):\n"); + fprintf(stderr, " comps - summary of all systems and SMs in fabric\n"); + fprintf(stderr, " brcomps - brief summary of all systems and SMs in fabric\n"); + fprintf(stderr, " nodes - summary of all node types and SMs in fabric\n"); + fprintf(stderr, " brnodes - brief summary of all node types and SMs in\n"); + fprintf(stderr, " fabric\n"); + fprintf(stderr, " ious - summary of all IO Units in fabric\n"); + fprintf(stderr, " lids - summary of all LIDs in fabric\n"); + fprintf(stderr, " links - summary of all links\n"); + fprintf(stderr, " extlinks - summary of links external to systems\n"); + fprintf(stderr, " slowlinks - summary of links running slower than expected\n"); + fprintf(stderr, " slowconfiglinks - summary of links configured to run slower than\n"); + fprintf(stderr, " supported includes slowlinks\n"); + fprintf(stderr, " slowconnlinks - summary of links connected with mismatched speed\n"); + fprintf(stderr, " potential includes slowconfiglinks\n"); + fprintf(stderr, " misconfiglinks - summary of links configured to run slower than\n"); + fprintf(stderr, " supported\n"); + fprintf(stderr, " misconnlinks - summary of links connected with mismatched speed\n"); + fprintf(stderr, " potential\n"); + fprintf(stderr, " errors - summary of links whose errors exceed counts in\n"); + fprintf(stderr, " config file\n"); + fprintf(stderr, " otherports - summary of ports not connected to this fabric\n"); + fprintf(stderr, " all - comp, nodes, ious, links, extlinks,\n"); + fprintf(stderr, " slowconnlinks, and error reports\n"); + fprintf(stderr, " none - no report, useful if just want to clear stats\n"); + fprintf(stderr, "Examples:\n"); + fprintf(stderr, " opareport -o comps -d 3\n"); + fprintf(stderr, " opareport -o errors -o slowlinks\n"); + exit(2); +} + +int parse(const char* filename) +{ + FILE *fp = NULL; + char param[80]; + unsigned long long threshold; + int ret; + char buffer[81]; + int skipping = 0; + + fp = fopen(filename, "r"); + if (fp == NULL) { + fprintf(stderr, "opareport: Can't open %s: %s\n", filename, strerror(errno)); + return -1; + } + while (NULL != fgets(buffer, sizeof(buffer), fp)) + { + // just ignore long lines + if (buffer[strlen(buffer)-1] != '\n') { + skipping=1; + continue; + } + if (skipping) { + skipping = 0; + continue; + } + ret = sscanf(buffer, "%70s\n", param); + if (ret != 1) + continue; // blank line + if ( param[0]=='#') + continue; // ignore comments + if (strcmp(param, "Threshold") == 0) { + char compare[21]; + ret = sscanf(buffer,"%70s %20s\n", param, compare); + if (ret != 2) { + fprintf(stderr, "opareport: Invalid Config Line: %s, ignoring\n", buffer); + continue; + } + if (strcmp(compare, "Greater") == 0) { + g_threshold_compare = 0; + } else if (strcmp(compare, "Equal") == 0) { + g_threshold_compare = 1; + } else { + fprintf(stderr, "opareport: Invalid Threshold: %s, ignoring\n", compare); + } + continue; + } + ret = sscanf(buffer, "%70s %llu\n", param, &threshold); + if (ret == 2) { + if (param[0]=='#') { + // ignore comments + } else if (strcmp(param,"LinkQualityIndicator") == 0) { + if (threshold > 5) { + fprintf(stderr, "opareport: LinkQualityIndicator max threshold setting is 5, ignoring: %llu\n", threshold); + } else { + g_Thresholds.lq.s.linkQualityIndicator = threshold; + /* can't be cleared. */ + } + } else if (strcmp(param,"NumLanesDown") == 0) { + if (threshold > 4) { + fprintf(stderr, "opareport: NumLanesDown max threshold setting is 4, ignoring: %llu\n", threshold); + } else { + g_Thresholds.lq.s.numLanesDown = threshold; + } +#define PARSE_THRESHOLD(field, sel, name, max) \ + if (strcmp(param, #name) == 0) { \ + if (threshold > (max)) { \ + fprintf(stderr, "opareport: " #name " max threshold is %u, ignoring: %llu\n", (max), threshold); \ + } else { \ + g_Thresholds.field = threshold; \ + if (threshold) { \ + g_CounterSelectMask.CounterSelectMask.s.sel = 1; \ + } \ + } \ + } +#define PARSE_THRESHOLD64(field, sel, name) \ + if (strcmp(param, #name) == 0) { \ + if (threshold >= UINT64_MAX) { \ + fprintf(stderr, "opareport: " #name " max threshold is %llu, ignoring: %llu\n",(unsigned long long)UINT64_MAX-1, threshold); \ + } else { \ + g_Thresholds.field = threshold; \ + if (threshold) { \ + g_CounterSelectMask.CounterSelectMask.s.sel = 1; \ + } \ + } \ + } +#define PARSE_MB_THRESHOLD(field, sel, name) \ + if (strcmp(param, #name) == 0) { \ + if (threshold > ((1ULL << 63)-1)/(FLITS_PER_MB/2)) { \ + fprintf(stderr, "opareport: " #name " max threshold is %llu, ignoring: %llu\n", ((1ULL << 63)-1)/(FLITS_PER_MB/2), threshold); \ + } else { \ + threshold = threshold * FLITS_PER_MB; \ + g_Thresholds.field = threshold; \ + if (threshold) { \ + g_CounterSelectMask.CounterSelectMask.s.sel = 1; \ + } \ + } \ + } + // Data movement + } else PARSE_MB_THRESHOLD(portXmitData, PortXmitData, XmitData) + else PARSE_MB_THRESHOLD(portRcvData, PortRcvData, RcvData) + else PARSE_THRESHOLD64(portXmitPkts, PortXmitPkts, XmitPkts) + else PARSE_THRESHOLD64(portRcvPkts, PortRcvPkts, RcvPkts) + else PARSE_THRESHOLD64(portMulticastXmitPkts, PortMulticastXmitPkts, MulticastXmitPkts) + else PARSE_THRESHOLD64(portMulticastRcvPkts, PortMulticastRcvPkts, MulticastRcvPkts) + // Signal Integrity and Node/Link Stability + // LinkQualityIndicator parsed above + else PARSE_THRESHOLD(uncorrectableErrors, UncorrectableErrors, UncorrectableErrors, 255) + else PARSE_THRESHOLD(linkDowned, LinkDowned, LinkDowned, UINT_MAX) + else PARSE_THRESHOLD64(portRcvErrors, PortRcvErrors, RcvErrors) + else PARSE_THRESHOLD64(excessiveBufferOverruns, ExcessiveBufferOverruns, ExcessiveBufferOverruns) + else PARSE_THRESHOLD64(fmConfigErrors, FMConfigErrors, FMConfigErrors) + else PARSE_THRESHOLD(linkErrorRecovery, LinkErrorRecovery, LinkErrorRecovery, UINT_MAX) + else PARSE_THRESHOLD64(localLinkIntegrityErrors, LocalLinkIntegrityErrors, LocalLinkIntegrityErrors) + else PARSE_THRESHOLD64(portRcvRemotePhysicalErrors, PortRcvRemotePhysicalErrors, RcvRemotePhysicalErrors) + // Security + else PARSE_THRESHOLD64(portXmitConstraintErrors, PortXmitConstraintErrors, XmitConstraintErrors) + else PARSE_THRESHOLD64(portRcvConstraintErrors, PortRcvConstraintErrors, RcvConstraintErrors) + // Routing or Down nodes still being sent to + else PARSE_THRESHOLD64(portRcvSwitchRelayErrors, PortRcvSwitchRelayErrors, RcvSwitchRelayErrors) + else PARSE_THRESHOLD64(portXmitDiscards, PortXmitDiscards, XmitDiscards) + // Congestion + else PARSE_THRESHOLD64(swPortCongestion, SwPortCongestion, CongDiscards) + else PARSE_THRESHOLD64(portRcvFECN, PortRcvFECN, RcvFECN) + else PARSE_THRESHOLD64(portRcvBECN, PortRcvBECN, RcvBECN) + else PARSE_THRESHOLD64(portMarkFECN, PortMarkFECN, MarkFECN) + else PARSE_THRESHOLD64(portXmitTimeCong, PortXmitTimeCong, XmitTimeCong) + else PARSE_THRESHOLD64(portXmitWait, PortXmitWait, XmitWait) + // Bubbles + else PARSE_THRESHOLD64(portXmitWastedBW, PortXmitWastedBW, XmitWastedBW) + else PARSE_THRESHOLD64(portXmitWaitData, PortXmitWaitData, XmitWaitData) + else PARSE_THRESHOLD64(portRcvBubble, PortRcvBubble, RcvBubble) +#undef PARSE_THRESHOLD +#undef PARSE_MB_THRESHOLD + else { + fprintf(stderr, "opareport: Invalid parameter: %s, ignoring\n", param); + } + } else { + fprintf(stderr, "opareport: Invalid Config Line: %s, ignoring\n", buffer); + } + } + fclose(fp); + return 0; +} + +// convert a output type argument to the proper constant +report_t checkOutputType(const char* name) +{ + if (0 == strcmp(optarg, "comps")) { + return REPORT_COMP; + } else if (0 == strcmp(optarg, "brcomps")) { + return REPORT_BRCOMP; + } else if (0 == strcmp(optarg, "nodes")) { + return REPORT_NODES; + } else if (0 == strcmp(optarg, "brnodes")) { + return REPORT_BRNODES; + } else if (0 == strcmp(optarg, "ious")) { + return REPORT_IOUS; + } else if (0 == strcmp(optarg, "linkinfo")) { + return REPORT_LINKINFO; + } else if (0 == strcmp(optarg, "links")) { + return REPORT_LINKS; + } else if (0 == strcmp(optarg, "extlinks")) { + return REPORT_EXTLINKS; + } else if (0 == strcmp(optarg, "filinks")) { + return REPORT_FILINKS; + } else if (0 == strcmp(optarg, "islinks")) { + return REPORT_ISLINKS; + } else if (0 == strcmp(optarg, "extislinks")) { + return REPORT_EXTISLINKS; + } else if (0 == strcmp(optarg, "slowlinks")) { + return REPORT_SLOWLINKS; + } else if (0 == strcmp(optarg, "slowconfiglinks")) { + return REPORT_SLOWCONFIGLINKS; + } else if (0 == strcmp(optarg, "slowconnlinks")) { + return REPORT_SLOWCONNLINKS; + } else if (0 == strcmp(optarg, "misconfiglinks")) { + return REPORT_MISCONFIGLINKS; + } else if (0 == strcmp(optarg, "misconnlinks")) { + return REPORT_MISCONNLINKS; + } else if (0 == strcmp(optarg, "errors")) { + return REPORT_ERRORS; + } else if (0 == strcmp(optarg, "otherports")) { + return REPORT_OTHERPORTS; + } else if (0 == strcmp(optarg, "verifylinks")) { + return REPORT_VERIFYLINKS; + } else if (0 == strcmp(optarg, "verifyextlinks")) { + return REPORT_VERIFYEXTLINKS; + } else if (0 == strcmp(optarg, "verifyfilinks")) { + return REPORT_VERIFYFILINKS; + } else if (0 == strcmp(optarg, "verifyislinks")) { + return REPORT_VERIFYISLINKS; + } else if (0 == strcmp(optarg, "verifyextislinks")) { + return REPORT_VERIFYEXTISLINKS; + } else if (0 == strcmp(optarg, "verifynodes")) { + return REPORT_VERIFYFIS|REPORT_VERIFYSWS; + } else if (0 == strcmp(optarg, "verifyfis")) { + return REPORT_VERIFYFIS; + } else if (0 == strcmp(optarg, "verifysws")) { + return REPORT_VERIFYSWS; + } else if (0 == strcmp(optarg, "verifysms")) { + return REPORT_VERIFYSMS; + } else if (0 == strcmp(optarg, "verifyall")) { + /* verifylinks is a superset of verifyextlinks, verifyfilinks, */ + /* verifyislinks, verifyextislinks */ + return REPORT_VERIFYFIS|REPORT_VERIFYSWS|REPORT_VERIFYLINKS|REPORT_VERIFYSMS; + } else if (0 == strcmp(optarg, "route")) { + return REPORT_ROUTE; + } else if (0 == strcmp(optarg, "none")) { + return REPORT_SKIP; + } else if (0 == strcmp(optarg, "sizes")) { + return REPORT_SIZES; + } else if (0 == strcmp(optarg, "snapshot")) { + return REPORT_SNAPSHOT; + } else if (0 == strcmp(optarg, "lids")) { + return REPORT_LIDS; + } else if (0 == strcmp(optarg, "linear")) { + return REPORT_LINEARFDBS; + } else if (0 == strcmp(optarg, "mcast")) { + return REPORT_MCASTFDBS; + } else if (0 == strcmp(optarg, "mcgroups")) { + return REPORT_MCGROUPS; + } else if (0 == strcmp(optarg, "vfinfo")) { + return REPORT_VFINFO; + } else if (0 == strcmp(optarg, "validatemcroutes")) { + return REPORT_VALIDATEMCROUTES; + } else if (0 == strcmp(optarg, "portusage")) { + return REPORT_PORTUSAGE; + } else if (0 == strcmp(optarg, "lidusage")) { + return REPORT_LIDUSAGE; + } else if (0 == strcmp(optarg, "pathusage")) { + return REPORT_PATHUSAGE; + } else if (0 == strcmp(optarg, "treepathusage")) { + return REPORT_TREEPATHUSAGE; + } else if (0 == strcmp(optarg, "validateroutes")) { + return REPORT_VALIDATEROUTES; + } else if (0 == strcmp(optarg, "validatevlroutes")) { + return REPORT_VALIDATEVLROUTES; + } else if (0 == strcmp(optarg, "validatecreditloops")) { + return REPORT_VALIDATECREDITLOOPS; + } else if (0 == strcmp(optarg, "validatevlcreditloops")) { + return REPORT_VALIDATEVLCREDITLOOPS; + } else if (0 == strcmp(optarg, "bfrctrl")) { + return REPORT_BUFCTRLTABLES; + } else if (0 == strcmp(optarg, "portgroups")) { + return REPORT_PORTGROUPS; + } else if (0 == strcmp(optarg, "validatepgs")) { + return REPORT_VERIFYPGS; + } else if (0 == strcmp(optarg, "vfmember")) { + return REPORT_VFMEMBER; + } else if (0 == strcmp(optarg, "dgmember")) { + return REPORT_DGMEMBER; + } else if (0 == strcmp(optarg, "quarantinednodes")) { + return REPORT_QUARANTINE_NODES; + } else if (0 == strcmp(optarg, "topology")) { + return REPORT_TOPOLOGY; + } else if (0 == strcmp(optarg, "cablehealth")) { + return REPORT_CABLEHEALTH; + } else if (0 == strcmp(optarg, "all")) { + /* note we omit brcomp and brnodes since comp and nodes is superset */ + /* similarly links is a suprset of filinks, islinks, extislinks */ + /* omit snapshot */ + return REPORT_COMP|REPORT_NODES|REPORT_IOUS|REPORT_LINKS + |REPORT_EXTLINKS|REPORT_SLOWCONNLINKS|REPORT_ERRORS; + } else { + fprintf(stderr, "opareport: Invalid Output Type: %s\n", name); + Usage(); + // NOTREACHED + return 0; + } +} + +int main(int argc, char ** argv) +{ + FSTATUS fstatus; + int c; + uint8 hfi = 0; + uint8 port = 0; + boolean gothfi=FALSE, gotport=FALSE; + Format_t format = FORMAT_TEXT; + int detail = 2; + int index; + report_t report = REPORT_NONE; + int stats = 0; // get port stats + int routes = 0; // get routing FDB + int fl_vlqos = 0; // get QOS VL-related tables + int bfrctrl = 0; // get Buffer Control Tables + int mcgroups = 0; // get multicast group members + char *config_file = CONFIG_FILE; + char *route_src = NULL; + char *route_dest = NULL; + char *focus_arg = NULL; + Point focus; + uint32 temp; + FabricFlags_t sweepFlags = FF_NONE; + uint8 find_flag = FIND_FLAG_FABRIC; // always check fabric + + Top_setcmdname("opareport"); + PointInit(&focus); + g_quiet = ! isatty(2); // disable progress if stderr is not tty + + // process command line arguments + while (-1 != (c = getopt_long(argc,argv, "vVAqh:p:o:d:PHNsri:CamK:MLc:S:D:F:xX:T:" + "Qb:e:", options, &index))) + { + switch (c) + { + case '$': + Usage_full(); + // NOTREACHED + break; + case 'v': + g_verbose++; + if (g_verbose > 3) umad_debug(g_verbose-2); + break; + case 'q': + g_quiet = 1; + break; + case 'h': // hfi to issue query from + if (FSUCCESS != StringToUint8(&hfi, optarg, NULL, 0, TRUE)) { + fprintf(stderr, "opareport: Invalid HFI Number: %s\n", optarg); + Usage(); + // NOTREACHED + } + gothfi=TRUE; + break; + case 'p': // port to issue query from + if (FSUCCESS != StringToUint8(&port, optarg, NULL, 0, TRUE)) { + fprintf(stderr, "opareport: Invalid Port Number: %s\n", optarg); + Usage(); + // NOTREACHED + } + gotport=TRUE; + break; + case '!': + if (FSUCCESS != StringToInt32(&g_ms_timeout, optarg, NULL, 0, TRUE)) { + fprintf(stderr, "opareport: Invalid timeout value: %s\n", optarg); + Usage(); + } + break; + case 'o': // select output record desired + report = (report_t) report | checkOutputType(optarg); + if (report & REPORT_ERRORS) + stats = 1; + if (report & (REPORT_MCGROUPS | REPORT_SNAPSHOT | REPORT_VALIDATEMCROUTES)) + mcgroups = 1; + if ( report & ( REPORT_LINEARFDBS | REPORT_MCASTFDBS | + REPORT_PORTUSAGE | REPORT_LIDUSAGE | + REPORT_PATHUSAGE | REPORT_TREEPATHUSAGE | + REPORT_VALIDATEROUTES | REPORT_VALIDATECREDITLOOPS | REPORT_VALIDATEMCROUTES | + REPORT_PORTGROUPS | REPORT_VERIFYPGS | + REPORT_VALIDATEVLCREDITLOOPS | REPORT_VALIDATEVLROUTES ) ) + routes = 1; + if (report & REPORT_BUFCTRLTABLES) + bfrctrl = 1; + if (report & (REPORT_VALIDATEVLCREDITLOOPS | REPORT_VALIDATEVLROUTES )) { + fl_vlqos = 1; + g_use_scsc = 1; + } + if (report & REPORT_VFMEMBER) + fl_vlqos = 1; + if (report & (REPORT_VERIFYFIS|REPORT_VERIFYSWS)) + find_flag |= FIND_FLAG_ENODE; + if (report & REPORT_VERIFYSMS) + find_flag |= FIND_FLAG_ESM; + if (report & (REPORT_VERIFYLINKS|REPORT_VERIFYEXTLINKS + |REPORT_VERIFYFILINKS|REPORT_VERIFYISLINKS + |REPORT_VERIFYEXTISLINKS)) + find_flag |= FIND_FLAG_ELINK; + if (report & REPORT_CABLEHEALTH) + sweepFlags |= FF_SMADIRECT|FF_CABLELOWPAGE; + break; + case 'd': // detail level + if (FSUCCESS != StringToUint32(&temp, optarg, NULL, 0, TRUE)) { + fprintf(stderr, "opareport: Invalid Detail Level: %s\n", optarg); + Usage(); + // NOTREACHED + } + detail = (int)temp; + break; + case 'P': // persistent data only + g_persist = 1; + break; + case 'H': // hardware data only + g_hard = 1; + break; + case 'N': // omit names + g_noname = 1; + break; + case 's': // get performance stats + stats = 1; + break; + case 'i': // get performance stats over interval + if (FSUCCESS != StringToUint32(&temp, optarg, NULL, 0, TRUE)) { + fprintf(stderr, "opareport: Invalid Interval: %s\n", optarg); + Usage(); + // NOTREACHED + } + g_interval = (int)temp; + break; + case 'C': // clear all monitored performance stats + g_clearstats = 1; + break; + case 'a': // clear all performance stats + g_clearallstats = 1; + break; + case 'm': // access fabric information through direct SMA + sweepFlags |= FF_SMADIRECT; + break; + case 'M': // access performance stats through direct PMA + sweepFlags |= FF_PMADIRECT; + break; + case 'A': // get PortInfo for all switch ports, including down ones + sweepFlags |= FF_DOWNPORTINFO; + break; + case 'r': // get routing FDBs + routes = 1; + break; + case 'L': // limit to specific ports + g_limitstats = 1; + break; + case 'c': // config file for thresholds in errors report + config_file = optarg; + break; + case 'S': // source for trace route + if (route_src) { + fprintf(stderr, "opareport: -S option may only be specified once\n"); + Usage(); + // NOTREACHED + } + route_src = optarg; + break; + case 'D': // dest for trace route + if (route_dest) { + fprintf(stderr, "opareport: -D option may only be specified once\n"); + Usage(); + // NOTREACHED + } + route_dest = optarg; + break; + case 'F': // focus for report + if (focus_arg) { + fprintf(stderr, "opareport: -F option may only be specified once\n"); + Usage(); + // NOTREACHED + } + focus_arg = optarg; + break; + case 'V': // get QOS VL-related tables + fl_vlqos = 1; + bfrctrl = 1; + break; + case 'x': // output in xml + format = FORMAT_XML; + break; + case 'X': // snapshot_input in xml + g_snapshot_in_file = optarg; + break; + case 'T': // topology_input in xml + g_topology_in_file = optarg; + break; + case 'Q': // do not include focus description in report + g_quietfocus = 1; + break; + case 'b': + if (FSUCCESS != StringToDateTime(&temp, optarg)) { + fprintf(stderr, "opareport: Invalid Date/Time: %s\n", optarg); + Usage(); + // NOTREACHED + } + g_begin = temp; + break; + case 'e': + if (FSUCCESS != StringToDateTime(&temp, optarg)) { + fprintf(stderr, "opareport: Invalid Date/Time: %s\n", optarg); + Usage(); + // NOTREACHED + } + g_end = temp; + break; + default: + fprintf(stderr, "opareport: Invalid option -%c\n", c); + Usage(); + // NOTREACHED + break; + } + } /* end while */ + + if (optind < argc) + { + Usage(); + // NOTREACHED + } + + // check for incompatible reports + if (report & REPORT_TOPOLOGY) { + if((report != REPORT_TOPOLOGY)){ + fprintf(stderr, "opareport: -o topology cannot be run with other reports\n"); + Usage(); + // NOTREACHED + } else { + format = FORMAT_XML; + } + } + if ((report & REPORT_SNAPSHOT) && (report != REPORT_SNAPSHOT)) { + fprintf(stderr, "opareport: -o snapshot cannot be run with other reports\n"); + Usage(); + // NOTREACHED + } + + // check for missing required arguments + if ((report & REPORT_ROUTE) && route_dest == NULL) { + fprintf(stderr, "opareport: -o route require -D option\n"); + Usage(); + // NOTREACHED + } + + // check for incompatible arguments + if (g_begin && g_end && (g_begin > g_end)){ + fprintf(stderr, "opareport: begin time must be before end time\n"); + Usage(); + // NOTREACHED + } + + // check for incompatible reports + if ((report & REPORT_CABLEHEALTH) && (report != REPORT_CABLEHEALTH)) { + fprintf(stderr, "opareport: -o cablehealth cannot be run with other reports.\n"); + Usage(); + // NOTREACHED + } + + // check for incompatible arguments + if ((report & REPORT_CABLEHEALTH) && g_snapshot_in_file) { + fprintf(stderr, "opareport: -o cablehealth option is not permitted against a snapshot.\n"); + Usage(); + // NOTREACHED + } + + // check for incompatible arguments + if ((report & REPORT_CABLEHEALTH) && (format == FORMAT_XML)) { + fprintf(stderr, "opareport: -o cablehealth option only supports CSV output\n"); + Usage(); + // NOTREACHED + } + + // check for incompatible arguments + if ((report & REPORT_LINKINFO) && (format == FORMAT_XML)) { + fprintf(stderr, "opareport: -o linkinfo option does not support XML output\n"); + Usage(); + // NOTREACHED + } + + // Warn for extraneous arguments and ignore them + if ((route_dest || route_src) && ! (report & REPORT_ROUTE)) { + fprintf(stderr, "opareport: -S or -D option given without -o route, ignoring -S and -D\n"); + route_src = NULL; + route_dest = NULL; + } + + if (focus_arg) { + char *name = "report"; + int suppress = 0; + if (report & REPORT_ROUTE) { suppress = 1; name = "route"; } + if (report & REPORT_SNAPSHOT) { suppress = 1; name = "snapshot"; } + if (report & REPORT_MCGROUPS) { suppress = 1; name = "mcgroups"; } + if (report & REPORT_VALIDATEROUTES) { suppress = 1; name = "validateroutes"; } + if (report & REPORT_VALIDATECREDITLOOPS) { suppress = 1; name = "validatecreditloops"; } + if (report & REPORT_VALIDATEVLCREDITLOOPS) { suppress = 1; name = "validatevlcreditloops"; } + if (report & REPORT_VALIDATEMCROUTES) { suppress = 1; name = "validatemcroutes"; } + if (report & REPORT_VERIFYPGS) { suppress = 1; name = "validatepgs"; } + if (report & REPORT_SKIP) { suppress = 1; name = "none"; } + + if (suppress) { + fprintf(stderr,"opareport: %s does not support -F option.\n", name); + fprintf(stderr," -F ignored for all reports.\n"); + focus_arg = NULL; + } + } + + if (report == REPORT_SNAPSHOT && g_limitstats) { + fprintf(stderr, "opareport: -L ignored for -o snapshot\n"); + g_limitstats = 0; + } + + if (g_limitstats && ! focus_arg) { + fprintf(stderr, "opareport: -L ignored when -F not specified\n"); + g_limitstats = 0; + } + if ((report & REPORT_SNAPSHOT) && (g_noname || g_hard || g_persist)) { + fprintf(stderr, "opareport: -N, -H and -P ignored for -o snapshot\n"); + g_noname = 0; + g_hard = 0; + g_persist = 0; + } + + if ((report & REPORT_MCGROUPS ) && (sweepFlags & FF_SMADIRECT)) { + fprintf(stderr, "opareport: -m ignored for -o mcgroups\n"); + } + + if ((report & REPORT_VALIDATEMCROUTES ) && (sweepFlags & FF_SMADIRECT)) { + fprintf(stderr, "opareport: -m ignored for -o validatemcroutes\n"); + } + + //In a live cluster, implicitly fetch the routing tables when route report or route focus is requested with -m option + if (!g_snapshot_in_file && (sweepFlags & FF_SMADIRECT)&& ((report & REPORT_ROUTE ) || ( focus_arg && NULL != ComparePrefix(focus_arg, "route:")))) + routes = 1; + + if ((report & REPORT_DGMEMBER) && g_snapshot_in_file) { + fprintf(stderr, "opareport: -o dgmember option is not permitted against a snapshot.\n"); + Usage(); + // NOTREACHED + } + + if (g_snapshot_in_file && (g_interval || g_clearstats || g_clearallstats || g_begin || g_end)) { + fprintf(stderr, "opareport: -i, -C, -a, -b, and -e ignored for -X\n"); + g_interval = 0; + g_clearstats = 0; + g_clearallstats = 0; + g_begin = 0; + g_end = 0; + } + if (g_snapshot_in_file) { + if (sweepFlags & FF_SMADIRECT) + fprintf(stderr, "opareport: -m ignored for -X\n"); + if (sweepFlags & FF_PMADIRECT) + fprintf(stderr, "opareport: -M ignored for -X\n"); + if (sweepFlags & FF_DOWNPORTINFO) + fprintf(stderr, "opareport: -A ignored for -X\n"); + sweepFlags &= ~(FF_SMADIRECT|FF_PMADIRECT|FF_DOWNPORTINFO); + } + if (g_snapshot_in_file && stats) { + if (! (report & REPORT_ERRORS)) { + // -s must have been explicitly specified + fprintf(stderr, "opareport: -s ignored for -X\n"); + } + stats = 0; + } + if (g_snapshot_in_file && (fl_vlqos || bfrctrl)) { + if (! (report & (REPORT_BUFCTRLTABLES|REPORT_VFINFO|REPORT_VFMEMBER))) { + // -V must have been explicitly specified + fprintf(stderr, "opareport: -V ignored for -X\n"); + } + } + if (g_snapshot_in_file && routes) { + if ( ! ( report & ( REPORT_LINEARFDBS | REPORT_MCASTFDBS | + REPORT_PORTUSAGE | REPORT_LIDUSAGE | REPORT_PATHUSAGE | + REPORT_TREEPATHUSAGE | REPORT_VALIDATEROUTES | REPORT_VALIDATECREDITLOOPS | + REPORT_VALIDATEVLROUTES | REPORT_VALIDATEVLCREDITLOOPS | REPORT_VALIDATEMCROUTES) ) ) { + // -r must have been explicitly specified + fprintf(stderr, "opareport: -r ignored for -X\n"); + } + } + if (g_limitstats && ! (report & (REPORT_ERRORS|REPORT_SNAPSHOT)) && ! g_clearstats && ! g_clearallstats && ! g_interval) { + fprintf(stderr, "opareport: -L ignored without -C, -a, -i, -o errors nor -o snapshot\n"); + g_limitstats = 0; + } + if (g_interval && (g_hard || g_persist)) { + fprintf(stderr, "opareport: -i ignored with -H or -P\n"); + g_interval = 0; + } + + if ((report & REPORT_VFINFO) && detail > 2) + fl_vlqos = 1; + // check for unignored arguments which imply need to get stats + if (! g_snapshot_in_file && focus_arg && NULL != ComparePrefix(focus_arg, "linkqual")) + stats = 1; // using the linkqual focus option implies -s + if (g_interval || g_begin | g_end) + stats = 1; + + // now that we have final value for "stats" option, make sure consistent + if ((sweepFlags & FF_DOWNPORTINFO) && ! (sweepFlags & FF_PMADIRECT) + && (stats || g_interval || g_clearstats || g_clearallstats)) { + fprintf(stderr, "opareport: Use of -A requires performance stats be gathered directly (via -M)\n"); + Usage(); + // NOTREACHED + } + if (g_interval && focus_arg && NULL != ComparePrefix(focus_arg, "linkqual")) { + fprintf(stderr, "opareport: -i option not permitted in conjunction with -F linkqual, linkqualLE\n nor linkqualGE\n"); + Usage(); + // NOTREACHED + } + + if (report == REPORT_NONE) + report = REPORT_BRNODES; + + // Initialize Sweep Verbose option, for -X still used for Focus processing + fstatus = InitSweepVerbose(g_verbose?stderr:NULL); + if (fstatus != FSUCCESS) { + fprintf(stderr, "opareport: Initialize Verbose option (status=0x%x): %s\n", fstatus, iba_fstatus_msg(fstatus)); + g_exitstatus = 1; + goto done; + } + + // figure out which local port we will use to gather data + if (g_snapshot_in_file) { + if (gotport || gothfi) + fprintf(stderr, "opareport: -p and -h ignored for -X\n"); + } else { +#ifdef IB_STACK_IBACCESS + // we must initialize user mode iba library first + fstatus = iba_init(); + if (fstatus != FSUCCESS) { + fprintf(stderr, "opareport: iba_init failed (status=0x%x): %s\n", fstatus, iba_fstatus_msg(fstatus)); + g_exitstatus = 1; + goto done; + } +#endif + + // find portGuid for hfi/port specified + { + uint32 caCount, portCount; + + fstatus = iba_get_portguid(hfi, port, NULL, &g_portGuid, NULL, &g_portAttrib, + &caCount, &portCount); + + if (FNOT_FOUND == fstatus) { + fprintf(stderr, "opareport: %s\n", + iba_format_get_portguid_error(hfi, port, caCount, portCount)); + g_exitstatus = 1; + goto done; + } else if (FSUCCESS != fstatus) { + fprintf(stderr, "opareport: iba_get_portguid Failed: %s\n", + iba_fstatus_msg(fstatus)); + g_exitstatus = 1; + goto done; + } + DBGPRINT("USING SUBNET PREFIX 0x%016"PRIx64"\n", g_portAttrib->GIDTable[0].Type.Global.SubnetPrefix); + } + } + + // get thresholds config file + if ((report & REPORT_ERRORS) || g_clearstats) { + if (0 != parse(config_file)) { + g_exitstatus = 1; + goto done; + } + } + + // get the fabric data + if (g_snapshot_in_file) { + if (FSUCCESS != Xml2ParseSnapshot(g_snapshot_in_file, g_quiet, &g_Fabric, FF_NONE, 0)) { + g_exitstatus = 1; + goto done; + } + } else { + if (FSUCCESS != InitMad(g_portGuid, g_verbose?stderr:NULL)) { + g_exitstatus = 1; + goto done; + } + if (sweepFlags & FF_SMADIRECT) { + if (FSUCCESS != InitSmaMkey(0)) { + g_exitstatus = 1; + goto done; + } + } + if (FSUCCESS != Sweep(g_portGuid, &g_Fabric, sweepFlags, SWEEP_ALL, g_quiet, g_ms_timeout)) { + g_exitstatus = 1; + goto done; + } + } + + // parse topology input file and cross reference to fabric data + if (g_topology_in_file) { + if (FSUCCESS != Xml2ParseTopology(g_topology_in_file, g_quiet, &g_Fabric, TOPOVAL_NONE)) { + g_exitstatus = 1; + goto done_fabric; + } + //if (g_verbose) + // Xml2PrintTopology(stdout, &g_Fabric); // for debug + } + + // we can't do a linkqual focus until after the port counters have been collected + // nor can we do route focus with -m until FDBs are collected. So will handle route focus with and without -m later. + if (focus_arg && (NULL == ComparePrefix(focus_arg, "linkqual")) && (NULL == ComparePrefix(focus_arg, "route"))) { + char *p; + FSTATUS status; + + status = ParseFocusPoint(g_snapshot_in_file?0:g_portGuid, + &g_Fabric, focus_arg, &focus, find_flag, &p, TRUE); + if (FINVALID_PARAMETER == status || (FSUCCESS == status && *p != '\0')) { + fprintf(stderr, "opareport: Invalid Point Syntax: '%s'\n", focus_arg); + fprintf(stderr, "opareport: %*s^\n", (int)(p-focus_arg), ""); + PointDestroy(&focus); + Usage_full(); + // NOTREACHED + } + if (FSUCCESS != status) { + fprintf(stderr, "opareport: Unable to resolve Point: '%s': %s\n", focus_arg, iba_fstatus_msg(status)); + g_exitstatus = 1; + goto done_fabric; + } + } + + // output the desired reports + if (g_interval) { + (void)ClearAllPortCountersAndShow(g_portGuid, &focus, TRUE, format, report == REPORT_SNAPSHOT); + PROGRESS_PRINT(TRUE, "Waiting %d seconds", g_interval); + sleep(g_interval); + } + + if (!g_snapshot_in_file && stats && ! g_hard && ! g_persist) { + if (FSUCCESS != GetAllPortCounters(g_portGuid, g_portAttrib->GIDTable[0], + &g_Fabric, &focus, g_limitstats, g_quiet, g_begin, g_end)) { + g_exitstatus = 1; + report &= ~REPORT_ERRORS; + fprintf(stderr, "opareport: Failed to Get Port Counters\n"); + } + } + + // get other optional fabric data + // now that the port counters have been collected, we can do the link quality focus + if (focus_arg && NULL != ComparePrefix(focus_arg, "linkqual")) { + if (!(g_Fabric.flags & FF_STATS) && g_snapshot_in_file ) { + fprintf(stderr, "opareport: '-F linkqual' with snapshot must be created with -s option\n"); + Usage(); + // NOTREACHED + } + char *p; + FSTATUS status; + // use FIND_FLAG_FABRIC, no use checking anything other than fabric + status = ParseFocusPoint(g_snapshot_in_file?0:g_portGuid, + &g_Fabric, focus_arg, &focus, FIND_FLAG_FABRIC, &p, TRUE); + if (FINVALID_PARAMETER == status || (FSUCCESS == status && *p != '\0')) { + fprintf(stderr, "opareport: Invalid Point Syntax: '%s'\n", focus_arg); + fprintf(stderr, "opareport: %*s^\n", (int)(p-focus_arg), ""); + PointDestroy(&focus); + Usage_full(); + // NOTREACHED + } + if (FSUCCESS != status) { + fprintf(stderr, "opareport: Unable to resolve Point: '%s': %s\n", focus_arg, iba_fstatus_msg(status)); + g_exitstatus = 1; + goto done_fabric; + } + } + + if ((!g_snapshot_in_file && routes && ! g_hard && ! g_persist) || (g_snapshot_in_file && (report & REPORT_PORTUSAGE))) { + // Scanning through all switches is required to get LinearFDB to tabulate routes for path usage reports. It is not limited to switches in focus. + if (!g_snapshot_in_file && (FSUCCESS != GetAllFDBs(g_portGuid, &g_Fabric, + ((report & REPORT_PATHUSAGE) || ((report & REPORT_TREEPATHUSAGE)))?NULL:&focus, g_quiet))) { + g_exitstatus = 1; + goto done_fabric; + } + /* Traverse the switches and find the largest LFT */ + LIST_ITEM *p; + for (p=QListHead(&g_Fabric.AllSWs); p != NULL; p = QListNext(&g_Fabric.AllSWs, p)) { + NodeData *nodep; + SwitchData *switchp; + + nodep = QListObj(p); + switchp = nodep->switchp; + if (!switchp || !switchp->LinearFDB) continue; + if (switchp->LinearFDBSize > g_max_lft) g_max_lft = switchp->LinearFDBSize; + } + } + + // now that the FDBs have been fetched for -m option, , we can do the route focus + if (focus_arg && NULL != ComparePrefix(focus_arg, "route")) { + char *p; + FSTATUS status; + if ( !(g_Fabric.flags & FF_ROUTES) && g_snapshot_in_file ) { + fprintf(stderr, "opareport: '-F route:' with snapshot must be created with -r option\n"); + Usage(); + // NOTREACHED + } + status = ParseFocusPoint(g_snapshot_in_file?0:g_portGuid, + &g_Fabric, focus_arg, &focus, find_flag, &p, TRUE); + if (FINVALID_PARAMETER == status || (FSUCCESS == status && *p != '\0')) { + fprintf(stderr, "opareport: Invalid Point Syntax: '%s'\n", focus_arg); + fprintf(stderr, "opareport: %*s^\n", (int)(p-focus_arg), ""); + PointDestroy(&focus); + Usage_full(); + // NOTREACHED + } + if (FSUCCESS != status) { + fprintf(stderr, "opareport: Unable to resolve Point: '%s': %s\n", focus_arg, iba_fstatus_msg(status)); + g_exitstatus = 1; + goto done_fabric; + } + } + + if (!g_snapshot_in_file && fl_vlqos && ! g_hard && ! g_persist) { + if (FSUCCESS != GetAllPortVLInfo(g_portGuid, &g_Fabric, &focus, g_quiet, &g_use_scsc)) { + g_exitstatus = 1; + goto done_fabric; + } + } + + if (!g_snapshot_in_file && bfrctrl && ! g_hard && ! g_persist) { + if (FSUCCESS != GetAllBCTs(g_portGuid, &g_Fabric, &focus, g_quiet)) { + g_exitstatus = 1; + goto done_fabric; + } + } + + if (!g_snapshot_in_file && mcgroups && ! g_hard && ! g_persist) { + if (FSUCCESS != GetAllMCGroups(g_portGuid, &g_Fabric, &focus, g_quiet)) { + g_exitstatus = 1; + goto done_fabric; + } + } + + if (format == FORMAT_XML && ! (report & REPORT_SNAPSHOT)) { +// TBD - use IXml functions for XML output + char datestr[80] = ""; + int i; + + printf("\n"); + Top_formattime(datestr, sizeof(datestr), g_Fabric.time); + printf("1?" ":"", argv[i]); + printf("\" >\n"); + } + if (report & REPORT_COMP) + ShowComponentReport(&focus, format, 0, detail); + if (report & REPORT_BRCOMP) + ShowComponentBriefReport(&focus, format, 0, detail); + if (report & REPORT_NODES) + ShowNodeTypeReport(&focus, format, 0, detail); + if (report & REPORT_BRNODES) + ShowNodeTypeBriefReport(&focus, format, REPORT_BRNODES, 0, detail); + if (report & REPORT_IOUS) + ShowAllIOUReport(&focus, format, 0, detail); + if (report & REPORT_LINKS) + ShowLinksReport(&focus, REPORT_LINKS, format, 0, detail); + if (report & REPORT_EXTLINKS) + ShowLinksReport(&focus, REPORT_EXTLINKS, format, 0, detail); + if (report & REPORT_FILINKS) + ShowLinksReport(&focus, REPORT_FILINKS, format, 0, detail); + if (report & REPORT_ISLINKS) + ShowLinksReport(&focus, REPORT_ISLINKS, format, 0, detail); + if (report & REPORT_EXTISLINKS) + ShowLinksReport(&focus, REPORT_EXTISLINKS, format, 0, detail); + if (report & REPORT_SLOWLINKS) + ShowSlowLinkReport(LINK_EXPECTED_REPORT, FALSE, &focus, format, 0, detail); + if (report & REPORT_SLOWCONFIGLINKS) + ShowSlowLinkReport(LINK_CONFIG_REPORT, FALSE, &focus, format, 0, detail); + if (report & REPORT_SLOWCONNLINKS) + ShowSlowLinkReport(LINK_CONN_REPORT, FALSE, &focus, format, 0, detail); + if (report & REPORT_MISCONFIGLINKS) + ShowSlowLinkReport(LINK_CONFIG_REPORT, TRUE, &focus, format, 0, detail); + if (report & REPORT_MISCONNLINKS) + ShowSlowLinkReport(LINK_CONN_REPORT, TRUE, &focus, format, 0, detail); + if (report & REPORT_ERRORS) + ShowLinkErrorReport(&focus, format, 0, detail); + if (report & REPORT_OTHERPORTS) + ShowOtherPortsReport(&focus, format, 0, detail); + if (report & REPORT_VERIFYFIS) + ShowVerifyNodesReport(&focus, STL_NODE_FI, format, 0, detail); + if (report & REPORT_VERIFYSWS) + ShowVerifyNodesReport(&focus, STL_NODE_SW, format, 0, detail); + if (report & REPORT_VERIFYSMS) + ShowVerifySMsReport(&focus, format, 0, detail); + if (report & REPORT_VERIFYLINKS) + ShowVerifyLinksReport(&focus, REPORT_VERIFYLINKS, format, 0, detail); + if (report & REPORT_VERIFYEXTLINKS) + ShowVerifyLinksReport(&focus, REPORT_VERIFYEXTLINKS, format, 0, detail); + if (report & REPORT_VERIFYFILINKS) + ShowVerifyLinksReport(&focus, REPORT_VERIFYFILINKS, format, 0, detail); + if (report & REPORT_VERIFYISLINKS) + ShowVerifyLinksReport(&focus, REPORT_VERIFYISLINKS, format, 0, detail); + if (report & REPORT_VERIFYEXTISLINKS) + ShowVerifyLinksReport(&focus, REPORT_VERIFYEXTISLINKS, format, 0, detail); + if (report & REPORT_TOPOLOGY) { + ShowNodeTypeBriefReport(&focus, format, REPORT_TOPOLOGY, 0, detail); + ShowLinksReport(&focus, REPORT_LINKS, format, 0, detail); + } + if (report & REPORT_ROUTE) { + Point point1, point2; + int skip = 0; + + PointInit(&point1); + PointInit(&point2); + + if (route_src) { + char *p; + if (FSUCCESS != (fstatus = ParsePoint(&g_Fabric, route_src, &point1, FIND_FLAG_FABRIC, &p)) || *p != '\0') { + PointDestroy(&point1); + PointDestroy(&point2); + if (FINVALID_PARAMETER == fstatus || (FSUCCESS == fstatus && *p != '\0')) { + fprintf(stderr, "opareport: Invalid Source Point Syntax: '%s'\n", route_src); + fprintf(stderr, "opareport: %*s^\n", (int)(p-route_src), ""); + } + + fprintf(stderr, "opareport: Unable to resolve Source Point: '%s': %s\n", route_src, iba_fstatus_msg(fstatus)); + + switch (format) { + case FORMAT_TEXT: + printf("%*sReport skipped: Invalid source point syntax: %s:%s\n",0,"", + route_src, iba_fstatus_msg(fstatus)); + break; + case FORMAT_XML: + printf("%*s\n",0,"", + route_src, iba_fstatus_msg(fstatus)); + break; + default: + break; + } + + goto done_route; + } + } else { + PortData *portp1 = FindPortGuid(&g_Fabric, g_portGuid); + if (! portp1) { + fprintf(stderr, "opareport: Local Port GUID Not Found: 0x%016"PRIx64"\n", g_portGuid); + fprintf(stderr, "opareport: Skipping trace route report\n"); + skip = 1; + } else { + point1.Type = POINT_TYPE_SYSTEM; + point1.u.systemp = portp1->nodep->systemp; + if (! point1.u.systemp) { + fprintf(stderr, "opareport: System for Local Port GUID Not Found: 0x%016"PRIx64"\n", g_portGuid); + fprintf(stderr, "opareport: Skipping trace route report\n"); + skip = 1; + } + } + } + if ((!skip) && route_dest) { + char *p; + if (FSUCCESS != (fstatus = ParsePoint(&g_Fabric, route_dest, &point2, FIND_FLAG_FABRIC, &p)) || *p != '\0') { + PointDestroy(&point1); + PointDestroy(&point2); + if (FINVALID_PARAMETER == fstatus || (FSUCCESS == fstatus && *p != '\0')) { + fprintf(stderr, "opareport: Invalid Dest Point Syntax: '%s'\n", route_dest); + fprintf(stderr, "opareport: %*s^\n", (int)(p-route_dest), ""); + } + + switch (format) { + case FORMAT_TEXT: + printf("%*sReport skipped: Invalid destination point syntax: %s:%s\n",0,"", + route_dest, iba_fstatus_msg(fstatus)); + break; + case FORMAT_XML: + printf("%*s\n",0,"", + route_dest, iba_fstatus_msg(fstatus)); + break; + default: + break; + } + + goto done_route; + } + + ShowRoutesReport(g_portGuid, &point1, &point2, format, 0, detail); + } + done_route: + PointDestroy(&point1); + PointDestroy(&point2); + } + if (report & REPORT_SIZES) + ShowSizesReport(); + if (report == REPORT_SNAPSHOT) { + SnapshotOutputInfo_t info; + + info.fabricp = &g_Fabric; + info.argc = argc; + info.argv = argv; + + Xml2PrintSnapshot(stdout, &info); + } + + if (report & REPORT_LIDS) + ShowAllLIDReport(&focus, format, 0, detail); + + if (report & REPORT_LINEARFDBS) + ShowLinearFDBReport(&focus, format, 0, detail); + + if (report & REPORT_MCASTFDBS) + ShowMulticastFDBReport(&focus, format, 0, detail); + + + if (report & REPORT_MCGROUPS) + ShowMulticastGroupsReport(format, 0, detail); + + if (report & REPORT_PORTUSAGE) + ShowPortUsageReport(&focus, format, 0, detail); + + if (report & REPORT_PATHUSAGE) + ShowPathUsageReport(&focus, format, 0, detail); + + if (report & REPORT_TREEPATHUSAGE) + ShowTreePathUsageReport(&focus, format, 0, detail); + + if (report & REPORT_VALIDATEROUTES || report & REPORT_VALIDATEVLROUTES) { + ShowValidateRoutesReport(format, 0, detail); + } + + if (report & REPORT_VALIDATECREDITLOOPS || report & REPORT_VALIDATEVLCREDITLOOPS) { + ShowValidateCreditLoopsReport(format, 0, detail); + } + + if (report & REPORT_VALIDATEMCROUTES) { + ShowValidateMCRoutesReport(format, 0, detail); + } + + if (report & REPORT_VFINFO) + ShowVFInfoReport(&focus, format, 0, detail); + + if (report & REPORT_PORTGROUPS) + ShowPGReport(&focus, format, 0, detail); + + if (report & REPORT_VERIFYPGS) + ShowValidatePGReport(format, 0, detail); + + // Undocumented LID usage report + if (report & REPORT_LIDUSAGE) + ShowLIDUsageReport(&focus, format, 0, detail); + + if (report & REPORT_BUFCTRLTABLES) + ShowAllBCTReports(&focus, format, 0, detail); + + if (report & REPORT_VFMEMBER) + ShowVFMemberReport(&focus, format, 0, detail); + + if (report & REPORT_DGMEMBER) + ShowDGMemberReport(&focus, format, 0, detail); + + if (report & REPORT_QUARANTINE_NODES) + ShowQuarantineNodeReport(&focus, format, 0, detail); + + if (report & REPORT_CABLEHEALTH) + ShowCableHealthReport(&focus, format, 0, detail); + + if (report & REPORT_LINKINFO) + ShowLinkInfoReport(&focus, format, 0, detail); + + if (g_clearstats || g_clearallstats) + (void)ClearAllPortCountersAndShow(g_portGuid, &focus, g_clearallstats, format, report == REPORT_SNAPSHOT); + if (format == FORMAT_XML && ! (report & REPORT_SNAPSHOT)) { + printf("\n"); + } +done_fabric: + DestroyFabricData(&g_Fabric); +done: + PointDestroy(&focus); + DestroyMad(); + + if (g_exitstatus == 2) { + Usage(); + // NOTREACHED + } + + return g_exitstatus; +} diff --git a/IbaTools/opareport/opareport.h b/IbaTools/opareport/opareport.h new file mode 100644 index 0000000..2e5ee90 --- /dev/null +++ b/IbaTools/opareport/opareport.h @@ -0,0 +1,243 @@ +/* BEGIN_ICS_COPYRIGHT7 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT7 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +#ifndef _OPAREPORT_H +#define _OPAREPORT_H + +#include + +#include +#include +#include +#include +#include +#include +#define _GNU_SOURCE + +#include +#include + +#ifdef LINUX +#define CONFIG_FILE "/etc/opa/opamon.conf" +#else +#error "unsupported OS" +#endif + +#define MYTAG MAKE_MEM_TAG('i','r', 'e', 'p') + +#ifdef __cplusplus +extern "C" { +#endif + +/* output format */ +typedef enum { + FORMAT_TEXT, + FORMAT_XML, +} Format_t; + +// list of reports which may be selected, bitmask so can select more than one +typedef enum { + REPORT_NONE =0x0, + REPORT_COMP =0x1, + REPORT_BRCOMP =0x2, + REPORT_NODES =0x4, + REPORT_BRNODES =0x8, + REPORT_IOUS =0x10, + REPORT_SLOWLINKS =0x20, + REPORT_SLOWCONFIGLINKS =0x40, + REPORT_SLOWCONNLINKS =0x80, + REPORT_MISCONFIGLINKS =0x100, + REPORT_MISCONNLINKS =0x200, + REPORT_LINKS =0x400, + REPORT_EXTLINKS =0x800, + REPORT_FILINKS =0x1000, + REPORT_ISLINKS =0x2000, + REPORT_EXTISLINKS =0x4000, + REPORT_ERRORS =0x8000, + REPORT_OTHERPORTS =0x10000, + REPORT_ROUTE =0x20000, + REPORT_SKIP =0x40000, + REPORT_SIZES =0x80000, // undocumented report for sizeof structures + REPORT_SNAPSHOT =0x100000, + REPORT_VERIFYLINKS =0x200000, + REPORT_VERIFYEXTLINKS =0x400000, + REPORT_VERIFYFILINKS =0x800000, + REPORT_VERIFYISLINKS =0x1000000, + REPORT_VERIFYEXTISLINKS =0x2000000, + REPORT_VERIFYFIS =0x4000000, + REPORT_VERIFYSWS =0x8000000, + REPORT_VERIFYSMS =0x10000000, + REPORT_LIDS =0x20000000, + REPORT_LINEARFDBS =0x40000000, + REPORT_MCASTFDBS =0x80000000, + REPORT_PORTUSAGE =0x100000000, + REPORT_LIDUSAGE =0x200000000, // undocumented report LinearFDB LID usage + REPORT_VFINFO =0x400000000, + REPORT_PATHUSAGE =0x800000000, + REPORT_TREEPATHUSAGE =0x1000000000ULL, + REPORT_VALIDATEROUTES =0x2000000000ULL, + REPORT_VALIDATECREDITLOOPS =0x4000000000ULL, + REPORT_BUFCTRLTABLES =0x8000000000ULL, + REPORT_PORTGROUPS =0x10000000000ULL, + REPORT_VERIFYPGS =0x20000000000ULL, + REPORT_VFMEMBER =0x40000000000ULL, + REPORT_QUARANTINE_NODES =0x80000000000ULL, + REPORT_TOPOLOGY =0x100000000000ULL, + REPORT_MCGROUPS =0x400000000000ULL, + REPORT_VALIDATEVLCREDITLOOPS=0x800000000000ULL, + REPORT_VALIDATEVLROUTES =0x1000000000000ULL, + REPORT_VALIDATEMCROUTES =0x2000000000000ULL, + REPORT_DGMEMBER =0x4000000000000ULL, + REPORT_CABLEHEALTH =0x8000000000000ULL, + REPORT_LINKINFO =0x10000000000000ULL, +} report_t; + +// convert a output type argument to the proper constant +extern char *g_name_marker; // what to output when g_noname set +extern uint8 g_verbose; +extern int g_quiet; // omit progress output +extern int g_noname; // omit names +extern int g_stats; // get port stats +extern char* g_topology_in_file; // input file being parsed +extern EUI64 g_portGuid; // local port to use to access fabric +extern IB_PORT_ATTRIBUTES *g_portAttrib; // attributes for our local port +extern int g_exitstatus; // TBD make this static for opareport.c +extern FabricData_t g_Fabric; // fabric we are analyzing + +#define DBGPRINT(format, args...) \ + do { if (g_verbose) { fflush(stdout); fprintf(stderr, format, ##args); } } while (0) + +#define PROGRESS_PRINT(newline, format, args...) \ + do { if (! g_quiet) { ProgressPrint(newline, format, ##args); } } while (0) + +// macro to always return a valid pointer for use in %s formats +#define OPTIONAL_STR(s) (s?s:"") + +//extern void DisplayTraceRecord(STL_TRACE_RECORD *pTraceRecord, int indent); + +extern void DisplaySeparator(void); +extern void ShowLinkBriefSummaryHeader(Format_t format, int indent, int detail); +typedef enum { + LINKPORT_NOMTU=1, + LINKPORT_MTU=2, + LINKPORT_BLANKMTU=3 +} LinkPortMtu_t; +void ShowPortCounters(STL_PORT_COUNTERS_DATA *pPortCounters, Format_t format, int indent, int detail); +typedef void LinkPortSummaryDetailCallback_t(uint64 context, PortData *portp, Format_t format, int indent, int detail); +extern void ShowLinkPortBriefSummary(PortData *portp, const char *prefix, + uint64 context, LinkPortSummaryDetailCallback_t *callback, + Format_t format, int indent, int detail); +extern void ShowCableSummary(uint8_t *pCable, Format_t format, + int indent, int detail, uint8 portType); +extern void ShowCableSummaryDD(uint8_t *pCable, Format_t format, + int indent, int detail, uint8 portType); +// show cable information for a link in brief summary format +extern void ShowExpectedLinkBriefSummary(ExpectedLink *elinkp, + Format_t format, int indent, int detail); +// show from side of a link, need to later call ShowLinkToBriefSummary +// useful when traversing trace route and don't have both sides of link handy +extern void ShowLinkFromBriefSummary(PortData *portp1, + uint64 context, LinkPortSummaryDetailCallback_t *callback, + Format_t format, int indent, int detail); +// show to side of a link, need to call ShowLinkFromBriefSummary before this +// useful when traversing trace route and don't have both sides of link handy +// portp2 can be NULL to "close" the From Summary without additional +// port information and no cable information +// This is useful when reporting trace routes which stay within a single port +extern void ShowLinkToBriefSummary(PortData *portp2, const char* toprefix, boolean close_link, + uint64 context, LinkPortSummaryDetailCallback_t *callback, + Format_t format, int indent, int detail); + +extern void ShowNodeBriefSummaryHeadings(Format_t format, int indent, int detail); + +// output brief summary of a IB Node +extern void ShowNodeBriefSummary(NodeData *nodep, Point *focus, + boolean close_node, Format_t format, int indent, int detail); +extern void ShowTraceRecord(STL_TRACE_RECORD *pTraceRecord, Format_t format, int indent, int detail); + +// output brief summary of an expected IB Node +extern void ShowExpectedNodeBriefSummary( + const char* prefix, ExpectedNode *enodep, + const char *xml_tag, boolean close_node, Format_t format, + int indent, int detail); + +extern void ShowVerifySMBriefSummary(SMData *smp, + boolean close_sm, Format_t format, int indent, int detail); + +extern void ShowVerifySMBriefSummaryHeadings(Format_t format, int indent, int detail); + +extern void ShowExpectedSMBriefSummary(const char* prefix, ExpectedSM *esmp, + const char *xml_tag, boolean close_sm, Format_t format, + int indent, int detail); + +typedef void ExpectedLinkSummaryDetailCallback_t(ExpectedLink *elinkp, uint8 side, Format_t format, int indent, int detail); +extern void ShowExpectedLinkPortSelBriefSummary(const char* prefix, + ExpectedLink *elinkp, PortSelector *portselp, + uint8 side, ExpectedLinkSummaryDetailCallback_t *callback, + Format_t format, int indent, int detail); + +extern void ShowPointFocus(Point* focus, uint8 find_flag, Format_t format, int indent, int detail); + +// Verify ports in fabric against specified topology +extern void ShowVerifyLinksReport(Point *focus, report_t report, Format_t format, int indent, int detail); + +// Verify nodes in fabric against specified topology +extern void ShowVerifyNodesReport(Point *focus, uint8 NodeType, Format_t format, int indent, int detail); + +// Verify SMs in fabric against specified topology +extern void ShowVerifySMsReport(Point *focus, Format_t format, int indent, int detail); + +extern void XmlPrintHex64(const char *tag, uint64 value, int indent); +extern void XmlPrintHex32(const char *tag, uint32 value, int indent); +extern void XmlPrintHex16(const char *tag, uint16 value, int indent); +extern void XmlPrintHex8(const char *tag, uint8 value, int indent); +extern void XmlPrintDec(const char *tag, unsigned value, int indent); +extern void XmlPrintHex(const char *tag, unsigned value, int indent); +extern void XmlPrintStrLen(const char *tag, const char* value, int len, int indent); +extern void XmlPrintStr(const char *tag, const char* value, int indent); +extern void XmlPrintOptionalStr(const char *tag, const char* value, int indent); +extern void XmlPrintLID(const char *tag, STL_LID value, int indent); +extern void XmlPrintPKey(const char *tag, IB_P_KEY value, int indent); +extern void XmlPrintGID(const char *tag, IB_GID value, int indent); +extern void XmlPrintNodeType(uint8 value, int indent); +extern void XmlPrintNodeDesc(const char *value, int indent); +extern void XmlPrintIocIDString(const char *value, int indent); +extern void XmlPrintServiceName(const uchar *value, int indent); +extern void XmlPrintRate(uint8 value, int indent); +extern void XmlPrintLinkWidth(const char* tag_prefix, uint8 value, int indent); +extern void XmlPrintLinkSpeed(const char* tag_prefix, uint16 value, int indent); +extern void XmlPrintLinkStartTag(const char* tag, PortData *portp, int indent); + +#ifdef __cplusplus +}; +#endif + +#endif /* _OPAREPORT_H */ diff --git a/IbaTools/opareport/opareports.sh b/IbaTools/opareport/opareports.sh new file mode 100644 index 0000000..4b8d963 --- /dev/null +++ b/IbaTools/opareport/opareports.sh @@ -0,0 +1,225 @@ +#!/bin/bash +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] +# This script provides a wrapper for opareport which can be run +# against multiple fabrics via multiple local HFI ports + +# optional override of defaults +if [ -f /etc/opa/opafastfabric.conf ] +then + . /etc/opa/opafastfabric.conf +fi + +. /usr/lib/opa/tools/opafastfabric.conf.def + +. /usr/lib/opa/tools/ff_funcs + +trap "exit 1" SIGHUP SIGTERM SIGINT + +Usage_full() +{ + echo "Usage: opareports [-t portsfile] [-p ports] [-T topology_input]" >&2 + echo " [opareport arguments]" >&2 + echo " or" >&2 + echo " opareports --help" >&2 + echo " --help - produce full help text" >&2 + echo " -t portsfile - file with list of local HFI ports used to access" >&2 + echo " fabric(s) for analysis, default is $CONFIG_DIR/opa/ports" >&2 + echo " -p ports - list of local HFI ports used to access fabric(s) for analysis" >&2 + echo " default is 1st active port" >&2 + echo " This is specified as hfi:port" >&2 + echo " 0:0 = 1st active port in system" >&2 + echo " 0:y = port y within system" >&2 + echo " x:0 = 1st active port on HFI x" >&2 + echo " x:y = HFI x, port y" >&2 + echo " The first HFI in the system is 1. The first port on an HFI is 1." >&2 + echo " -T topology_input - name of a topology input file to use." >&2 + echo " Any %P markers in this filename will be replaced with the" >&2 + echo " hfi:port being operated on (such as 0:0 or 1:2)" >&2 + echo " default is $CONFIG_DIR/opa/topology.%P.xml" >&2 + echo " if NONE is specified, will not use any topology_input files" >&2 + echo " See opareport for more information on topology_input files" >&2 + echo " opareport arguments - any of the other opareport arguments." >&2 + echo " The following options are not available: -h, -X" >&2 + echo " Note -p is interpreted as indicated above" >&2 + echo " When run against multiple fabrics, the following options are not" >&2 + echo " available: -x, -o snapshot" >&2 + echo " Beware: when run against multiple fabrics the -F option will" >&2 + echo " be applied to all fabrics." >&2 + echo " Environment:" >&2 + echo " PORTS - list of ports, used in absence of -t and -p" >&2 + echo " PORTS_FILE - file containing list of ports, used in absence of -t and -p" >&2 + echo " FF_TOPOLOGY_FILE - file containing topology_input, used in absence of -T" >&2 + echo "for example:" >&2 + echo " opareports" >&2 + echo " opareports -p '1:1 1:2 2:1 2:2'" >&2 + echo "opareport arguments:" >&2 + /usr/sbin/opareport --help + exit 2 +} + +Usage() +{ + echo "Usage: opareports [opareport arguments]" >&2 + echo " or" >&2 + echo " opareports --help" >&2 + echo " --help - produce full help text" >&2 + echo " opareport arguments - any of the other opareport arguments." >&2 + echo "for example:" >&2 + echo " opareports" >&2 + echo "opareport arguments:" >&2 + /usr/sbin/opareport -? + exit 2 +} + +if [ x"$1" = "x--help" ] +then + Usage_full +fi + +status=ok + +TEMP=`getopt -a -n opareports -o 'p:t:vqo:d:PHmMNxT:sri:Cac:LF:S:D:QVA' -l 'verbose,quiet,output:,detail:,persist,hard,smadirect,pmadirect,noname,xml,topology:,stats,routes,interval:,clear,clearall,config:,limit,focus:,src:,dest:,quietfocus,vltables,allports' -- "$@"` +if [ $? != 0 ] +then + Usage +fi +eval set -- "$TEMP" +xopt=n +report= +while true +do + case "$1" in + -p) export PORTS="$2"; shift 2;; + -t) export PORTS_FILE="$2"; shift 2;; + #-h|--hfi) echo "$1 option not allowed"; Usage; shift 2;; + -x|--xml) xopt=y; opts="$opts $1"; shift;; + -o|--output) opts="$opts $1 '$2'"; report="$report $2"; shift 2;; + -d|--detail) opts="$opts $1 '$2'"; shift 2;; + #-X|--infile) echo "$1 option not allowed"; Usage; shift 2;; + -T|--topology) export FF_TOPOLOGY_FILE="$2"; shift 2;; + -i|--interval) opts="$opts $1 '$2'"; shift 2;; + -c|--config) opts="$opts $1 '$2'"; shift 2;; + -F|--focus) opts="$opts $1 '$2'"; shift 2;; + -S|--src) opts="$opts $1 '$2'"; shift 2;; + -D|--dest) opts="$opts $1 '$2'"; shift 2;; + --) shift; break;; # end of options + *) opts="$opts $1"; shift;; # catches all other options without args + esac +done +for arg in "$@" +do + # no additional arguments are allowed + Usage + opts="$opts $arg" +done + +# process ports and count how many we have +check_ports_args opareports +ports=0 +for hfi_port in $PORTS +do + ports=$(($ports + 1)) +done +if [ $ports -lt 1 ] +then + # should not happen, but be safe + ports=1 + PORTS="0:0" +fi + +if [ $ports -gt 1 ] +then + if [ "$xopt" = y ] + then + echo "opareports: -x/--xml option not allowed for > 1 port" >&2 + Usage_full + fi + if echo "$report"|grep snapshot >/dev/null 2>/dev/null + then + echo "opareports: snapshot report option not allowed for > 1 port" >&2 + Usage_full + fi +fi + +run_report() +{ + # $1 = hfi + # $2 = port + if [ "$port" -eq 0 ] + then + port_opts="-h $hfi" # default port to 1st active + else + port_opts="-h $hfi -p $port" + fi + if [ $ports -gt 1 ] + then + echo "Fabric $hfi:$port Report:" + fi + resolve_topology_file opareports "$hfi:$port" + topt="" + if [ "$TOPOLOGY_FILE" != "" ] + then + topt="-T '$TOPOLOGY_FILE'" + fi + #echo "/usr/sbin/opareport $port_opts $topt $opts" + eval /usr/sbin/opareport $port_opts $topt $opts + if [ $? -ne 0 ] + then + status=bad + fi + if [ $ports -gt 1 ] + then + echo "-------------------------------------------------------------------------------" + fi +} + + +for hfi_port in $PORTS +do + hfi=$(expr $hfi_port : '\([0-9]*\):[0-9]*') + port=$(expr $hfi_port : '[0-9]*:\([0-9]*\)') + if [ "$hfi" = "" -o "$port" = "" ] + then + echo "opareports: Error: Invalid port specification: $hfi_port" >&2 + status=bad + continue + fi + + run_report "$hfi" "$port" +done + +if [ "$status" != "ok" ] +then + exit 1 +else + exit 0 +fi diff --git a/IbaTools/opareport/pma.redirect.test.diff b/IbaTools/opareport/pma.redirect.test.diff new file mode 100644 index 0000000..e3306e1 --- /dev/null +++ b/IbaTools/opareport/pma.redirect.test.diff @@ -0,0 +1,122 @@ +Simple hacks to aid testing of PMA redirection code in opareport without +requiring Galaxy HFIs +*** IbaTools/opareport/opareport.c Wed Aug 29 19:02:10 2007 +--- IbaTools/opareport/opareport.c Wed Aug 29 17:40:16 2007 +*************** +*** 1171,1176 **** +--- 1163,1170 ---- + /* initialize path */ + (*redirectp)->path = *orig_pathp; + } ++ DBGPRINT("Version = 0x%x:0x%x LID=0x%x\n", classp->BaseVersion, classp->ClassVersion, classp->RedirectLID); ++ PrintDump(classp, sizeof(*classp), _DBG_DUMP_FORMAT_BYTES); + /* update redirect info from ClassPortInfo */ + pathp = &(*redirectp)->path; + pathp->DLID = classp->RedirectLID; +*************** +*** 1194,1199 **** +--- 1196,1202 ---- + { + FSTATUS fstatus; + ++ DBGPRINT("Sending PM attr 0x%x QP 0x%x QKey 0x%x to LID %u\n", attr, qpn, qkey, pathp->DLID); + mad->common.BaseVersion = IB_BASE_VERSION; + mad->common.MgmtClass = MCLASS_PERF; + mad->common.ClassVersion = IB_PERF_CLASS_VERSION; +*************** +*** 1239,1249 **** + } + + fstatus = pm_send_recv_mad(pathp, qpn, qkey, +! method, attr, modifier, portNum, mad); + if (FSUCCESS != fstatus) + goto fail; +! if (mad->common.u.NS.Status.AsReg16 == MAD_STATUS_REDIRECT_REQD) { + fstatus = UpdateRedirectInfo(&portp->pma_redirect, (IB_CLASS_PORT_INFO*)mad->PerfData, pathp); + if (FSUCCESS != fstatus) + goto fail; + fstatus = FERROR; // force retry +--- 1242,1252 ---- + } + + fstatus = pm_send_recv_mad(pathp, qpn, qkey, +! method, attempts==2?MCLASS_ATTRIB_ID_CLASS_PORT_INFO:attr, modifier, portNum, mad); + if (FSUCCESS != fstatus) + goto fail; +! if (attempts == 2 || mad->common.u.NS.Status.AsReg16 == MAD_STATUS_REDIRECT_REQD) { + fstatus = UpdateRedirectInfo(&portp->pma_redirect, (IB_CLASS_PORT_INFO*)mad->PerfData, pathp); + if (FSUCCESS != fstatus) + goto fail; + fstatus = FERROR; // force retry +Index: IbAccess/Common/Ibt/Pma/pmacallb.c +=================================================================== +RCS file: /cvs/vendor/linux/Iba/Common/Ibt/Pma/pmacallb.c,v +retrieving revision 1.20 +diff -c -r1.20 pmacallb.c +*** IbAccess/Common/Ibt/Pma/pmacallb.c 18 Feb 2007 20:26:06 -0000 1.20 +--- IbAccess/Common/Ibt/Pma/pmacallb.c 29 Aug 2007 21:17:33 -0000 +*************** +*** 253,258 **** +--- 253,259 ---- + { + case PM_ATTRIB_ID_CLASS_PORTINFO: + // post process ++ //_DBG_DUMP_MEMORY(_DBG_LVL_ERROR, ("ClassPortInfo final response"), pPmGmp, sizeof(*pPmGmp)); + PmaClassPortInfo(pPmGmp); + BSWAP_IB_CLASS_PORT_INFO((IB_CLASS_PORT_INFO*)&pPmGmp->PerfData); + break; +*************** +*** 313,319 **** + { + IB_CLASS_PORT_INFO* pClassPortInfo = (IB_CLASS_PORT_INFO*)&pMad->PerfData; + uint16 capMask = pClassPortInfo->CapMask; +! MemoryClear(pClassPortInfo, sizeof(*pClassPortInfo)); + pClassPortInfo->BaseVersion = IB_BASE_VERSION; + pClassPortInfo->ClassVersion = IB_PERF_CLASS_VERSION; + pClassPortInfo->CapMask = (capMask & PM_CLASS_PORT_CAPMASK_ALL_PORT_SELECT); +--- 314,320 ---- + { + IB_CLASS_PORT_INFO* pClassPortInfo = (IB_CLASS_PORT_INFO*)&pMad->PerfData; + uint16 capMask = pClassPortInfo->CapMask; +! // MemoryClear(pClassPortInfo, sizeof(*pClassPortInfo)); + pClassPortInfo->BaseVersion = IB_BASE_VERSION; + pClassPortInfo->ClassVersion = IB_PERF_CLASS_VERSION; + pClassPortInfo->CapMask = (capMask & PM_CLASS_PORT_CAPMASK_ALL_PORT_SELECT); +Index: IbAccess/Common/Ibt/Pma/vpdpma.c +=================================================================== +RCS file: /cvs/vendor/linux/Iba/Common/Ibt/Pma/vpdpma.c,v +retrieving revision 1.1.4.1 +diff -c -r1.1.4.1 vpdpma.c +*** IbAccess/Common/Ibt/Pma/vpdpma.c 29 Mar 2007 18:51:15 -0000 1.1.4.1 +--- IbAccess/Common/Ibt/Pma/vpdpma.c 29 Aug 2007 21:28:19 -0000 +*************** +*** 60,65 **** +--- 60,77 ---- + MemoryCopy(Pmp, mad, sizeof(*Pmp)); + BSWAP_IB_CLASS_PORT_INFO((IB_CLASS_PORT_INFO*)&Pmp->PerfData); + BSWAP_MAD_HEADER((MAD*)Pmp); ++ // hack to simulate redirection ++ { ++ IB_CLASS_PORT_INFO *classp = (IB_CLASS_PORT_INFO*)&Pmp->PerfData; ++ classp->RedirectLID = DevInfop->dev_port_info_list[PortNum-1].PortAttributes->Address.BaseLID; ++ classp->u3.s.RedirectQP = 1; ++ classp->Redirect_Q_Key = QP1_WELL_KNOWN_Q_KEY; ++ classp->Redirect_P_Key = 0xffff; ++ classp->RedirectGID.AsReg64s.H=0x1234; ++ classp->RedirectGID.AsReg64s.L=0; ++ // leave rest 0 ++ MsgOut("similate direction to %d:%d LID 0x%x rc=%d\n", classp->BaseVersion, classp->ClassVersion, classp->RedirectLID, rc); ++ } + if (rc == FSUCCESS) + { + // Nothing to do +*************** +*** 289,294 **** +--- 301,307 ---- + status = VpdPmaClassPortInfo(DevInfop, PortNum, SLID, + MadInOut->common.mr.s.Method, + MadInOut); ++ //_DBG_DUMP_MEMORY(_DBG_LVL_ERROR, ("ClassPortInfo response"), MadInOut, sizeof(*MadInOut)); + break; + case PM_ATTRIB_ID_PORT_SAMPLES_CONTROL: + _DBG_INFO(("PerfGetSet(PortSamplesControl)\n")); diff --git a/IbaTools/opareport/verify.c b/IbaTools/opareport/verify.c new file mode 100644 index 0000000..fc453fb --- /dev/null +++ b/IbaTools/opareport/verify.c @@ -0,0 +1,1298 @@ +/* BEGIN_ICS_COPYRIGHT7 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT7 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +#include "opareport.h" +#include +#include + +// Fabric Topology Verification and related reports + +void ShowProblem(Format_t format, int indent, int detail, const char* pformat, ...) +{ + va_list args; + static char buffer[100]; + int cnt; + + if (detail >= 0) { + va_start(args, pformat); + switch (format) { + case FORMAT_TEXT: + printf("%*s", indent, ""); + vprintf(pformat, args); + printf("\n"); + break; + case FORMAT_XML: + cnt = vsnprintf(buffer, sizeof(buffer), pformat, args); + ASSERT(cnt <= sizeof(buffer)-1); /* make sure message fits */ + XmlPrintStr("Problem", buffer, indent); + break; + default: + break; + } + va_end(args); + } +} + +// verify a port against its corresponding ExpectedLink->PortSelector +// Only valid to be called for ports with ExpectedLink +// returns FALSE if any discrepencies +// only does output if detail >= 0 +boolean PortVerify(PortData *portp, Format_t format, int indent, int detail) +{ + ExpectedLink *elinkp = portp->elinkp; + PortSelector *portselp = NULL; + boolean ret=TRUE; + + if (elinkp->portp1 == portp) { + portselp = elinkp->portselp1; + } else if (elinkp->portp2 == portp) { + portselp = elinkp->portselp2; + } + if (portselp) { // not specified in input topology xml file; accept any port on the other end of the link + if (portselp->NodeGUID && portselp->NodeGUID != portp->nodep->NodeInfo.NodeGUID) { + ret = FALSE; + ShowProblem(format, indent, detail, + "NodeGuid mismatch: expected: 0x%016"PRIx64" found: 0x%016"PRIx64, + portselp->NodeGUID, portp->nodep->NodeInfo.NodeGUID); + } + if (portselp->NodeDesc + && 0 != strncmp(portselp->NodeDesc, + (char*)portp->nodep->NodeDesc.NodeString, + NODE_DESCRIPTION_ARRAY_SIZE)) { + ret = FALSE; + ShowProblem(format, indent, detail, + "NodeDesc mismatch: expected: '%s' found: '%.*s'", + portselp->NodeDesc, NODE_DESCRIPTION_ARRAY_SIZE, + (char*)portp->nodep->NodeDesc.NodeString); + } + if (portselp->gotPortNum && portselp->PortNum != portp->PortNum) { + ret = FALSE; + ShowProblem(format, indent, detail, + "PortNum mismatch: expected: %3u found: %3u", + portselp->PortNum, portp->PortNum); + } + if (portselp->PortGUID && portselp->PortGUID != portp->PortGUID) { + ret = FALSE; + ShowProblem(format, indent, detail, + "PortGuid mismatch: expected: 0x%016"PRIx64" found: 0x%016"PRIx64, + portselp->PortGUID, portp->PortGUID); + } + if (portselp->NodeType && portselp->NodeType != portp->nodep->NodeInfo.NodeType) { + ret = FALSE; + ShowProblem(format, indent, detail, + "NodeType mismatch: expected: %s found: %s", + StlNodeTypeToText(portselp->NodeType), + StlNodeTypeToText(portp->nodep->NodeInfo.NodeType)); + } + } + /* to get here the port must have a neighbor and hence should be linkup + * but it could be quarantined or failing to move to Active + */ + if (portp->PortInfo.PortStates.s.PortState != IB_PORT_ACTIVE) { + ret = FALSE; + ShowProblem(format, indent, detail, + "Port not Active: PortState: %s", + StlPortStateToText(portp->PortInfo.PortStates.s.PortState)); + } + + return ret; +} + +// check attributes of link against input topology +// Only valid to be called for ports with ExpectedLink +// returns FALSE if link fails to verify +// only does output if detail >= 0 +boolean LinkAttrVerify(ExpectedLink *elinkp, PortData *portp1, Format_t format, int indent, int detail) +{ + PortData *portp2 = portp1->neighbor; + boolean ret = TRUE; + + if (elinkp->expected_rate && elinkp->expected_rate != portp1->rate) { + ret = FALSE; + ShowProblem(format, indent, detail, + "Link Rate mismatch: expected: %4s found: %4s", + StlStaticRateToText(elinkp->expected_rate), + StlStaticRateToText(portp1->rate)); + } + + if (elinkp->expected_mtu && elinkp->expected_mtu != MIN(portp1->PortInfo.MTU.Cap, portp2->PortInfo.MTU.Cap)) { + ret = FALSE; + ShowProblem(format, indent, detail, + "Link MTU mismatch: expected minimum MTU: %5s found MTU: %5s", + IbMTUToText(elinkp->expected_mtu), + IbMTUToText(MIN(portp1->PortInfo.MTU.Cap, portp2->PortInfo.MTU.Cap))); + } + return ret; +} + +typedef enum { + LINK_VERIFY_OK = 0, // link matches input topology + LINK_VERIFY_DIFF = 1, // link fully resolved but diff from input topology + LINK_VERIFY_UNEXPECTED = 2, // link not found in input topology + LINK_VERIFY_MISSING = 3, // link not found in fabric, but in input topology + LINK_VERIFY_DUP = 4, // possible duplicate in input topology + LINK_VERIFY_CONN = 5, // link partially resolved, wrong cabling + LINK_VERIFY_MAX=5 // maximum value of the above +} LinkVerifyResult_t; + +// check both fabric ports and link attributes against input topology +// only does output if detail >= 0 +LinkVerifyResult_t LinkFabricVerify(PortData *portp, Format_t format, int indent, int detail) +{ + LinkVerifyResult_t ret = LINK_VERIFY_OK; + + // all checks which are based off of found ports/links in fabric + if (portp->elinkp && portp->neighbor->elinkp) { + ExpectedLink *elinkp = portp->elinkp; + DEBUG_ASSERT(portp->elinkp == portp->neighbor->elinkp); + // check both sides for expected characteristics + if (! PortVerify(portp, format, indent, detail)) + ret = LINK_VERIFY_DIFF; + if (! PortVerify(portp->neighbor, format, indent, detail)) + ret = LINK_VERIFY_DIFF; + // check expected link characteristics + if (! LinkAttrVerify(elinkp, portp, format, indent, detail)) + ret = LINK_VERIFY_DIFF; + } else if (! portp->elinkp && ! portp->neighbor->elinkp) { + ret = LINK_VERIFY_UNEXPECTED; // extra link + ShowProblem(format, indent, detail, "Unexpected Link"); + } else { + // only one side resolved + DEBUG_ASSERT(0); // we only set elinkp if both sides resolved + ret = LINK_VERIFY_UNEXPECTED; // internal error + } + return ret; +} + +// compare ExpectedLink against fabric +// LinkFabricVerify will have caught links which are different or extra +// this is focused on duplicate ExpectedLink or missing links +// only does output if detail >= 0 +// side controls message output: +// 0 - both ports and link info - for initial checks +// 1 - elinkp->port 1 - when in process of outputting port 1 info +// 2 - elinkp->port 2 - when in process of outputting port 2 info +// 3 - link info only - when in process of outputting summary link info +LinkVerifyResult_t ExpectedLinkVerify(ExpectedLink *elinkp, uint8 side, Format_t format, int indent, int detail) +{ + LinkVerifyResult_t ret = LINK_VERIFY_OK; + + if (! elinkp->portp1 && ! elinkp->portp2) { + if (side == 0 || side == 3) + ShowProblem(format, indent, detail, "Missing Link"); + ret = LINK_VERIFY_MISSING; // missing link + } else if (elinkp->portp1 && elinkp->portp2) { + if (elinkp->portp1->elinkp != elinkp) { + // duplicate port, or incomplete/duplicate link in input topology + ret = LINK_VERIFY_DUP; + if (side == 0 || side == 1) + ShowProblem(format, indent, detail, "Duplicate Port in input or incorrectly cabled"); + } + if (elinkp->portp2->elinkp != elinkp) { + // duplicate port, or incomplete/duplicate link in input topology + ret = LINK_VERIFY_DUP; + if (side == 0 || side == 2) + ShowProblem(format, indent, detail, "Duplicate Port in input or incorrectly cabled"); + } + if (ret == LINK_VERIFY_DUP && side == 3) { + ShowProblem(format, indent, detail, "Duplicate Port in input or incorrectly cabled"); + } + } else { /* elinkp->portp1 || elinkp->portp2 */ + // only 1 side resolved -> incorrectly cabled + ret = LINK_VERIFY_CONN; + if (detail >= 0 && (side == 0 || side == 3)) { + if (elinkp->portp1) { + if (elinkp->portp1->neighbor) { + ShowProblem(format, indent, detail, "Incorrect Link, 2nd port found to be:"); + ShowLinkPortBriefSummary(elinkp->portp1->neighbor, " ", + 0, NULL, format, indent, 0); + } else { + ShowProblem(format, indent, detail, "Incorrect Link, 2nd port not found"); + } + } else /* elinkp->portp2 */ { + if (elinkp->portp2->neighbor) { + ShowProblem(format, indent, detail, "Incorrect Link, 1st port found to be:"); + ShowLinkPortBriefSummary(elinkp->portp2->neighbor, " ", + 0, NULL, format, indent, 0); + } else { + ShowProblem(format, indent, detail, "Incorrect Link, 1st port not found"); + } + } + } + } + return ret; +} + +void ShowLinkPortVerifySummaryCallback(uint64 context, PortData *portp, + Format_t format, int indent, int detail) +{ + if (portp->elinkp && portp->neighbor->elinkp) { + (void)PortVerify(portp, format, indent, detail); + } +} + +// show fabric link verify errors from portp to its neighbor +void ShowLinkVerifySummary(PortData *portp, Format_t format, int indent, int detail) +{ + ShowLinkFromBriefSummary(portp, 0, ShowLinkPortVerifySummaryCallback, format, indent, detail); + + ShowLinkToBriefSummary(portp->neighbor, "<-> ", FALSE, 0, ShowLinkPortVerifySummaryCallback, format, indent, detail); + + if (format == FORMAT_XML) + indent +=4; + if (portp->elinkp && portp->neighbor->elinkp + && (! PortVerify(portp, format, indent, -1) + || ! PortVerify(portp->neighbor, format, indent, -1))) + ShowProblem(format, indent, detail, "Port Attributes Inconsistent"); + if (portp->elinkp && portp->neighbor->elinkp) { + (void)LinkAttrVerify(portp->elinkp, portp, format, indent, detail); + } else if (! portp->elinkp && ! portp->neighbor->elinkp) { + ShowProblem(format, indent, detail, "Unexpected Link"); + } + if (format == FORMAT_XML) + printf("%*s\n", indent-4, ""); +} + +// header used before a series of links +void ShowExpectedLinkBriefSummaryHeader(Format_t format, int indent, int detail) +{ + switch (format) { + case FORMAT_TEXT: + printf("%*sRate MTU NodeGUID Port or PortGUID Type Name\n", indent, ""); + if (detail && (g_Fabric.flags & FF_CABLEDATA)) { + //printf("%*sPortDetails\n", indent+4, ""); + //printf("%*sLinkDetails\n", indent+4, ""); + printf("%*sCable: %-*s %-*s\n", indent+4, "", + CABLE_LABEL_STRLEN, "CableLabel", + CABLE_LENGTH_STRLEN, "CableLen"); + printf("%*s%s\n", indent+4, "", "CableDetails"); + } + break; + case FORMAT_XML: + break; + default: + break; + } +} + +void ShowExpectedLinkPortVerifySummaryCallback(ExpectedLink *elinkp, uint8 side, + Format_t format, int indent, int detail) +{ + (void)ExpectedLinkVerify(elinkp, side, format, indent, detail); +} + +// show input link verify errors +void ShowExpectedLinkVerifySummary(ExpectedLink *elinkp, Format_t format, int indent, int detail) +{ + // top level information about link + if (format == FORMAT_XML) { + printf("%*s\n", indent, "", (uint64)(uintn)elinkp); + indent+=4; + if (elinkp->expected_rate) + XmlPrintRate(elinkp->expected_rate, indent); + if (elinkp->expected_mtu) + XmlPrintDec("MTU", + GetBytesFromMtu(elinkp->expected_mtu), indent); + XmlPrintDec("Internal", elinkp->internal, indent); + if (detail) + ShowExpectedLinkBriefSummary(elinkp, format, indent+4, detail-1); + } + + // From Side (Port 1) + ShowExpectedLinkPortSelBriefSummary("", elinkp, elinkp->portselp1, + 1, ShowExpectedLinkPortVerifySummaryCallback, + format, indent, detail); + + // To Side (Port 2) + ShowExpectedLinkPortSelBriefSummary("", elinkp, elinkp->portselp2, + 2, ShowExpectedLinkPortVerifySummaryCallback, + format, indent, detail); + + // Summary information about Link itself + if (detail && format != FORMAT_XML) + ShowExpectedLinkBriefSummary(elinkp, format, indent+4, detail-1); + (void)ExpectedLinkVerify(elinkp, 3, format, indent, detail); + if (format == FORMAT_XML) + printf("%*s\n", indent-4, ""); +} + +// Verify links in fabric against specified topology +void ShowVerifyLinksReport(Point *focus, report_t report, Format_t format, int indent, int detail) +{ + LIST_ITEM *p; + uint32 counts[LINK_VERIFY_MAX+1] = {0}; + uint32 port_errors = 0; + uint32 link_errors = 0; + uint32 fabric_checked = 0; + uint32 input_checked = 0; + char *xml_prefix = ""; + char *prefix = ""; + char *report_name = ""; + LinkVerifyResult_t res; + + switch (report) { + default: // should not happen, but just in case + ASSERT(0); + case REPORT_VERIFYLINKS: + report_name = "verifylinks"; + xml_prefix = ""; + prefix = ""; + break; + case REPORT_VERIFYEXTLINKS: + report_name = "verifyextlinks"; + xml_prefix = "Ext"; + prefix = "External "; + break; + case REPORT_VERIFYFILINKS: + report_name = "verifyfilinks"; + xml_prefix = "FI"; + prefix = "FI "; + break; + case REPORT_VERIFYISLINKS: + report_name = "verifyislinks"; + xml_prefix = "IS"; + prefix = "Inter-Switch "; + break; + case REPORT_VERIFYEXTISLINKS: + report_name = "verifyextislinks"; + xml_prefix = "ExtIS"; + prefix = "External Inter-Switch "; + break; + } + // intro for report + switch (format) { + case FORMAT_TEXT: + printf("%*s%sLinks Topology Verification\n", indent, "", prefix); + break; + case FORMAT_XML: + printf("%*s \n", indent, "", xml_prefix, prefix); + indent+=4; + break; + default: + break; + } + if (! g_topology_in_file) { + switch (format) { + case FORMAT_TEXT: + printf("%*sReport skipped: -T option not specified\n", indent, ""); + break; + case FORMAT_XML: + printf("%*s\n", indent, ""); + break; + default: + break; + } + goto done; + } + if (! (g_Fabric.flags & (FF_EXPECTED_LINKS|FF_EXPECTED_EXTLINKS))) { + switch (format) { + case FORMAT_TEXT: + printf("%*sReport skipped: no LinkSummary nor ExternalLinkSummary information provided\n", indent, ""); + break; + case FORMAT_XML: + printf("%*s\n", indent, ""); + break; + default: + break; + } + goto done; + } + if (0 == (report & (REPORT_VERIFYEXTLINKS|REPORT_VERIFYEXTISLINKS)) + && ((g_Fabric.flags & (FF_EXPECTED_LINKS|FF_EXPECTED_EXTLINKS)) == FF_EXPECTED_EXTLINKS)) { + fprintf(stderr, "opareport: Warning: %s requested, but only ExternalLinkSummary information provided\n", report_name); + } + + ShowPointFocus(focus, (FIND_FLAG_FABRIC|FIND_FLAG_ELINK), format, indent, detail); + + // First we look at all the fabric links + switch (format) { + case FORMAT_TEXT: + printf("%*s%sLinks Found with incorrect configuration:\n", indent, "", prefix); + break; + case FORMAT_XML: + printf("%*s\n", indent, "", prefix); + break; + default: + break; + } + for (p=QListHead(&g_Fabric.AllPorts); p != NULL; p = QListNext(&g_Fabric.AllPorts, p)) { + PortData *portp1, *portp2; + + portp1 = (PortData *)QListObj(p); + // to avoid duplicated processing, only process "from" ports in link + if (! portp1->from) + continue; + + switch (report) { + default: // should not happen, but just in case + case REPORT_VERIFYLINKS: + // process all links + break; + case REPORT_VERIFYEXTLINKS: + if (isInternalLink(portp1)) + continue; + break; + case REPORT_VERIFYFILINKS: + if (! isFILink(portp1)) + continue; + break; + case REPORT_VERIFYISLINKS: + if (! isISLink(portp1)) + continue; + break; + case REPORT_VERIFYEXTISLINKS: + if (isInternalLink(portp1)) + continue; + if (! isISLink(portp1)) + continue; + break; + } + + portp2 = portp1->neighbor; + // We process only links whose PortData or resolved ExpectedLink + // match the focus + if (! ( ComparePortPoint(portp1, focus) + || ComparePortPoint(portp2, focus) + || (portp1->elinkp && CompareExpectedLinkPoint(portp1->elinkp, focus)) + || (portp2->elinkp && CompareExpectedLinkPoint(portp2->elinkp, focus)))) + continue; + fabric_checked++; + // detail=-1 in LinkFabricVerify will suppress its output + res = LinkFabricVerify(portp1, format, indent, -1); + counts[res]++; + if (res != LINK_VERIFY_OK) { + if (detail) { + if (port_errors) { + if (format == FORMAT_TEXT) { + printf("\n"); // blank line between links + } + } else { + ShowLinkBriefSummaryHeader(format, indent, detail-1); + } + ShowLinkVerifySummary(portp1, format, indent, detail-1); + } + port_errors++; + } + } + switch (format) { + case FORMAT_TEXT: + if (detail && port_errors) + printf("\n"); // blank line between links + printf("%*s%u of %u Fabric Links Checked\n", indent, "", + fabric_checked, g_Fabric.LinkCount); + break; + case FORMAT_XML: + XmlPrintDec("FabricLinksChecked", fabric_checked, indent); + XmlPrintDec("TotalFabricLinks", g_Fabric.LinkCount, indent); + break; + default: + break; + } + + // now look at all the expected Links from the input topology + switch (format) { + case FORMAT_TEXT: + printf("\n%*s%sLinks Expected but Missing, Duplicate in input or Incorrect:\n", indent, "", prefix); + break; + case FORMAT_XML: + printf("%*s\n", indent, "", prefix); + break; + default: + break; + } + for (p=QListHead(&g_Fabric.ExpectedLinks); p != NULL; p = QListNext(&g_Fabric.ExpectedLinks, p)) { + ExpectedLink *elinkp = (ExpectedLink *)QListObj(p); + + // do our best to filter expected links + // the is*ExpectedLink functions are purposely generously inclusive + switch (report) { + default: // should not happen, but just in case + case REPORT_VERIFYLINKS: + // process all links + break; + case REPORT_VERIFYEXTLINKS: + if (! isExternalExpectedLink(elinkp)) + continue; + break; + case REPORT_VERIFYFILINKS: + if (! isFIExpectedLink(elinkp)) + continue; + break; + case REPORT_VERIFYISLINKS: + if (! isISExpectedLink(elinkp)) + continue; + break; + case REPORT_VERIFYEXTISLINKS: + if (! isExternalExpectedLink(elinkp)) + continue; + if (! isISExpectedLink(elinkp)) + continue; + break; + } + + // We process only elinks whose resolved ports or ExpectedLink + // match the focus + if (! ( (elinkp->portp1 && ComparePortPoint(elinkp->portp1, focus)) + || (elinkp->portp2 && ComparePortPoint(elinkp->portp2, focus)) + || CompareExpectedLinkPoint(elinkp, focus))) + continue; + input_checked++; + // detail=-1 in ExpectedLinkVerify will suppress its output + res = ExpectedLinkVerify(elinkp, 0, format, indent, -1); + counts[res]++; + if (res != LINK_VERIFY_OK) { + if (detail) { + if (link_errors) { + if (format == FORMAT_TEXT) { + printf("\n"); // blank line between links + } + } else { + ShowExpectedLinkBriefSummaryHeader(format, indent, detail-1); + } + ShowExpectedLinkVerifySummary(elinkp, format, indent, detail-1); + } + link_errors++; + } + } + switch (format) { + case FORMAT_TEXT: + if (detail && link_errors) + printf("\n"); // blank line between links + printf("%*s%u of %u Input Links Checked\n", indent, "", + input_checked, QListCount(&g_Fabric.ExpectedLinks)); + break; + case FORMAT_XML: + XmlPrintDec("InputLinksChecked", input_checked, indent); + XmlPrintDec("TotalInputLinks", QListCount(&g_Fabric.ExpectedLinks), indent); + break; + default: + break; + } + + // final summary information + switch (format) { + case FORMAT_TEXT: + printf("\n%*sTotal of %u Incorrect Links found\n", indent, "", port_errors+link_errors); + printf("%*s%u Missing, %u Unexpected, %u Misconnected, %u Duplicate, %u Different\n", indent, "", + counts[LINK_VERIFY_MISSING], counts[LINK_VERIFY_UNEXPECTED], + counts[LINK_VERIFY_CONN], counts[LINK_VERIFY_DUP], + counts[LINK_VERIFY_DIFF]); + break; + case FORMAT_XML: + XmlPrintDec("TotalLinksIncorrect", port_errors+link_errors, indent); + XmlPrintDec("Missing", counts[LINK_VERIFY_MISSING], indent); + XmlPrintDec("Unexpected", counts[LINK_VERIFY_UNEXPECTED], indent); + XmlPrintDec("Misconnected", counts[LINK_VERIFY_CONN], indent); + XmlPrintDec("Duplicate", counts[LINK_VERIFY_DUP], indent); + XmlPrintDec("Different", counts[LINK_VERIFY_DIFF], indent); + break; + default: + break; + } + +done: + switch (format) { + case FORMAT_TEXT: + DisplaySeparator(); + break; + case FORMAT_XML: + indent-=4; + printf("%*s\n", indent, "", xml_prefix); + break; + default: + break; + } +} + +// verify a node against its corresponding ExpectedNode +// Only valid to be called for SMs with ExpectedNode +// returns FALSE if any discrepencies +// only does output if detail >= 0 +boolean NodeVerify(NodeData *nodep, Format_t format, int indent, int detail) +{ + ExpectedNode *enodep = nodep->enodep; + boolean ret=TRUE; + + ASSERT(enodep); + if (enodep->NodeGUID && enodep->NodeGUID != nodep->NodeInfo.NodeGUID) { + ret = FALSE; + ShowProblem(format, indent, detail, + "NodeGuid mismatch: expected: 0x%016"PRIx64" found: 0x%016"PRIx64, + enodep->NodeGUID, nodep->NodeInfo.NodeGUID); + } + if (enodep->NodeDesc + && 0 != strncmp(enodep->NodeDesc, + (char*)nodep->NodeDesc.NodeString, + NODE_DESCRIPTION_ARRAY_SIZE)) { + ret = FALSE; + ShowProblem(format, indent, detail, + "NodeDesc mismatch: expected: '%s' found: '%.*s'", + enodep->NodeDesc, NODE_DESCRIPTION_ARRAY_SIZE, + (char*)nodep->NodeDesc.NodeString); + } + if (enodep->NodeType && enodep->NodeType != nodep->NodeInfo.NodeType) { + ret = FALSE; + ShowProblem(format, indent, detail, + "NodeType mismatch: expected: %s found: %s", + StlNodeTypeToText(enodep->NodeType), + StlNodeTypeToText(nodep->NodeInfo.NodeType)); + } + return ret; +} + +typedef enum { + NODE_VERIFY_OK = 0, // node matches input topology + NODE_VERIFY_DIFF = 1, // node fully resolved but diff from input topology + NODE_VERIFY_UNEXPECTED = 2, // node not found in input topology + NODE_VERIFY_MISSING = 3, // node not found in fabric, but in input topology + NODE_VERIFY_DUP = 4, // possible duplicate in input topology + NODE_VERIFY_MAX=4 // maximum value of the above +} NodeVerifyResult_t; + +// check both fabric node against input topology +// only does output if detail >= 0 +NodeVerifyResult_t NodeFabricVerify(NodeData *nodep, Format_t format, int indent, int detail) +{ + NodeVerifyResult_t ret = NODE_VERIFY_OK; + + // all checks which are based off of found node in fabric + if (nodep->enodep) { + if (! NodeVerify(nodep, format, indent, detail)) + ret = NODE_VERIFY_DIFF; + } else { + ret = NODE_VERIFY_UNEXPECTED; // extra node + ShowProblem(format, indent, detail, "Unexpected %s", + StlNodeTypeToText(nodep->NodeInfo.NodeType)); + } + return ret; +} + +// compare ExpectedNode against fabric +// NodeFabricVerify will have caught nodes which are different or extra +// this is focused on duplicate ExpectedNodes or missing nodes +// only does output if detail >= 0 +NodeVerifyResult_t ExpectedNodeVerify(ExpectedNode *enodep, Format_t format, int indent, int detail) +{ + NodeVerifyResult_t ret = NODE_VERIFY_OK; + + if (! enodep->nodep) { + ShowProblem(format, indent, detail, "Missing %s", + StlNodeTypeToText(enodep->NodeType)); + ret = NODE_VERIFY_MISSING; // missing link + } else { + if (enodep->nodep->enodep != enodep) { + // duplicate node in input topology + ret = NODE_VERIFY_DUP; + ShowProblem(format, indent, detail, "Duplicate %s in input", + StlNodeTypeToText(enodep->NodeType)); + } + } + return ret; +} + +// show fabric node verify errors +void ShowNodeVerifySummary(NodeData *nodep, Format_t format, int indent, int detail) +{ + ShowNodeBriefSummary(nodep, NULL, FALSE, format, indent, 0); + + if (format == FORMAT_XML) + indent +=4; + if (nodep->enodep && ! NodeVerify(nodep, format, indent, detail-1)) { + ShowProblem(format, indent, detail, "Node Attributes Inconsistent"); + } else { + ShowProblem(format, indent, detail, "Unexpected %s", + StlNodeTypeToText(nodep->NodeInfo.NodeType)); + } + if (format == FORMAT_XML) + printf("%*s\n", indent-4, ""); +} + +// show input node verify errors +void ShowExpectedNodeVerifySummary(ExpectedNode *enodep, Format_t format, int indent, int detail) +{ + ShowExpectedNodeBriefSummary("", enodep, "Node", FALSE, format, indent, detail-1); + if (format == FORMAT_XML) + indent+=4; + (void)ExpectedNodeVerify(enodep, format, indent, detail); + if (format == FORMAT_XML) + printf("%*s\n", indent-4, ""); +} + +// Verify nodes in fabric against specified topology +void ShowVerifyNodesReport(Point *focus, uint8 NodeType, Format_t format, int indent, int detail) +{ + LIST_ITEM *p; + uint32 counts[NODE_VERIFY_MAX+1] = {0}; + uint32 fabric_errors = 0; + uint32 input_errors = 0; + uint32 fabric_checked = 0; + uint32 input_checked = 0; + NodeVerifyResult_t res; + const char *NodeTypeText = StlNodeTypeToText(NodeType); + QUICK_LIST *fabric_listp; + QUICK_LIST *input_listp; + + switch (NodeType) { + case STL_NODE_FI: + fabric_listp = &g_Fabric.AllFIs; + input_listp = &g_Fabric.ExpectedFIs; + break; + case STL_NODE_SW: + fabric_listp = &g_Fabric.AllSWs; + input_listp = &g_Fabric.ExpectedSWs; + break; + default: + ASSERT(0); + break; + } + + // intro for report + switch (format) { + case FORMAT_TEXT: + printf("%*s%ss Topology Verification\n", indent, "", NodeTypeText); + break; + case FORMAT_XML: + printf("%*s \n", indent, "", NodeTypeText, NodeTypeText); + indent+=4; + break; + default: + break; + } + if (! g_topology_in_file) { + switch (format) { + case FORMAT_TEXT: + printf("%*sReport skipped: -T option not specified\n", indent, ""); + break; + case FORMAT_XML: + printf("%*s\n", indent, ""); + break; + default: + break; + } + goto done; + } + if (! (g_Fabric.flags & FF_EXPECTED_NODES)) { + switch (format) { + case FORMAT_TEXT: + printf("%*sReport skipped: no Nodes information provided\n", indent, ""); + break; + case FORMAT_XML: + printf("%*s\n", indent, ""); + break; + default: + break; + } + goto done; + } + + ShowPointFocus(focus, (FIND_FLAG_FABRIC|FIND_FLAG_ENODE), format, indent, detail); + + // First we look at all the fabric nodes + switch (format) { + case FORMAT_TEXT: + printf("%*s%ss Found with incorrect configuration:\n", indent, "", NodeTypeText); + break; + case FORMAT_XML: + printf("%*s\n", indent, "", NodeTypeText); + break; + default: + break; + } + for (p=QListHead(fabric_listp); p != NULL; p = QListNext(fabric_listp, p)) { + NodeData *nodep = (NodeData *)QListObj(p); + + // We process only nodes whose NodeData or resolved ExpectedNode + // match the focus + if (! ( CompareNodePoint(nodep, focus) + || (nodep->enodep && CompareExpectedNodePoint(nodep->enodep, focus)))) + continue; + fabric_checked++; + // detail=-1 in NodeFabricVerify will suppress its output + res = NodeFabricVerify(nodep, format, indent, -1); + counts[res]++; + if (res != NODE_VERIFY_OK) { + if (detail) { + if (fabric_errors) { + if (format == FORMAT_TEXT) { + printf("\n"); // blank line between links + } + } else { + // use detail 0 so don't show Port stuff + ShowNodeBriefSummaryHeadings(format, indent, 0 /*detail-1*/); + } + ShowNodeVerifySummary(nodep, format, indent, detail-1); + } + fabric_errors++; + } + } + switch (format) { + case FORMAT_TEXT: + if (detail && fabric_errors) + printf("\n"); // blank line between links + printf("%*s%u of %u Fabric %ss Checked\n", indent, "", + fabric_checked, QListCount(fabric_listp), NodeTypeText); + break; + case FORMAT_XML: + switch (NodeType) { + case STL_NODE_FI: + XmlPrintDec("FabricFIsChecked", fabric_checked, indent); + XmlPrintDec("TotalFabricFIs", QListCount(fabric_listp), indent); + break; + case STL_NODE_SW: + XmlPrintDec("FabricSWsChecked", fabric_checked, indent); + XmlPrintDec("TotalFabricSWs", QListCount(fabric_listp), indent); + break; + default: + break; + } + default: + break; + } + + // now look at all the expected Nodes from the input topology + switch (format) { + case FORMAT_TEXT: + printf("\n%*s%ss Expected but Missing or Duplicate in input:\n", indent, "", NodeTypeText); + break; + case FORMAT_XML: + printf("%*s\n", indent, "", NodeTypeText); + break; + default: + break; + } + for (p=QListHead(input_listp); p != NULL; p = QListNext(input_listp, p)) { + ExpectedNode *enodep = (ExpectedNode *)QListObj(p); + + // We process only enodes whose resolved node or ExpectedNode + // match the focus + if (! ( (enodep->nodep && CompareNodePoint(enodep->nodep, focus)) + || CompareExpectedNodePoint(enodep, focus))) + continue; + input_checked++; + // detail=-1 in ExpectedNodeVerify will suppress its output + res = ExpectedNodeVerify(enodep, format, indent, -1); + counts[res]++; + if (res != NODE_VERIFY_OK) { + if (detail) { + if (input_errors) { + if (format == FORMAT_TEXT) { + printf("\n"); // blank line between links + } + } else { + // use detail 0 so don't show Port stuff + ShowNodeBriefSummaryHeadings(format, indent, 0 /*detail-1*/); + } + ShowExpectedNodeVerifySummary(enodep, format, indent, detail-1); + } + input_errors++; + } + } + switch (format) { + case FORMAT_TEXT: + if (detail && input_errors) + printf("\n"); // blank line between links + printf("%*s%u of %u Input %ss Checked\n", indent, "", + input_checked, QListCount(input_listp), NodeTypeText); + break; + case FORMAT_XML: + switch (NodeType) { + case STL_NODE_FI: + XmlPrintDec("InputFIsChecked", input_checked, indent); + XmlPrintDec("TotalInputFIs", QListCount(input_listp), indent); + break; + case STL_NODE_SW: + XmlPrintDec("InputSWsChecked", input_checked, indent); + XmlPrintDec("TotalInputSWs", QListCount(input_listp), indent); + break; + default: + break; + } + default: + break; + } + + // final summary information + switch (format) { + case FORMAT_TEXT: + printf("\n%*sTotal of %u Incorrect %ss found\n", indent, "", fabric_errors+input_errors, NodeTypeText); + printf("%*s%u Missing, %u Unexpected, %u Duplicate, %u Different\n", indent, "", + counts[NODE_VERIFY_MISSING], counts[NODE_VERIFY_UNEXPECTED], + counts[NODE_VERIFY_DUP], + counts[NODE_VERIFY_DIFF]); + break; + case FORMAT_XML: + switch (NodeType) { + case STL_NODE_FI: + XmlPrintDec("TotalFIsIncorrect", fabric_errors+input_errors, indent); + break; + case STL_NODE_SW: + XmlPrintDec("TotalSWsIncorrect", fabric_errors+input_errors, indent); + break; + default: + break; + } + XmlPrintDec("Missing", counts[NODE_VERIFY_MISSING], indent); + XmlPrintDec("Unexpected", counts[NODE_VERIFY_UNEXPECTED], indent); + XmlPrintDec("Duplicate", counts[NODE_VERIFY_DUP], indent); + XmlPrintDec("Different", counts[NODE_VERIFY_DIFF], indent); + break; + default: + break; + } + +done: + switch (format) { + case FORMAT_TEXT: + DisplaySeparator(); + break; + case FORMAT_XML: + indent-=4; + printf("%*s\n", indent, "", NodeTypeText); + break; + default: + break; + } +} + +// verify a SM against its corresponding ExpectedSM +// Only valid to be called for nodes with ExpectedSM +// returns FALSE if any discrepencies +// only does output if detail >= 0 +boolean SMVerify(SMData *smp, Format_t format, int indent, int detail) +{ + ExpectedSM *esmp = smp->esmp; + boolean ret=TRUE; + + ASSERT(esmp); + if (esmp->NodeGUID && esmp->NodeGUID != smp->portp->nodep->NodeInfo.NodeGUID) { + ret = FALSE; + ShowProblem(format, indent, detail, + "NodeGuid mismatch: expected: 0x%016"PRIx64" found: 0x%016"PRIx64, + esmp->NodeGUID, smp->portp->nodep->NodeInfo.NodeGUID); + } + if (esmp->NodeDesc + && 0 != strncmp(esmp->NodeDesc, + (char*)smp->portp->nodep->NodeDesc.NodeString, + NODE_DESCRIPTION_ARRAY_SIZE)) { + ret = FALSE; + ShowProblem(format, indent, detail, + "NodeDesc mismatch: expected: '%s' found: '%.*s'", + esmp->NodeDesc, NODE_DESCRIPTION_ARRAY_SIZE, + (char*)smp->portp->nodep->NodeDesc.NodeString); + } + if (esmp->gotPortNum && esmp->PortNum != smp->portp->PortNum) { + ret = FALSE; + ShowProblem(format, indent, detail, + "PortNum mismatch: expected: %3u found: %3u", + esmp->PortNum, smp->portp->PortNum); + } + if (esmp->PortGUID && esmp->PortGUID != smp->portp->PortGUID) { + ret = FALSE; + ShowProblem(format, indent, detail, + "PortGuid mismatch: expected: 0x%016"PRIx64" found: 0x%016"PRIx64, + esmp->PortGUID, smp->portp->PortGUID); + } + if (esmp->NodeType && esmp->NodeType != smp->portp->nodep->NodeInfo.NodeType) { + ret = FALSE; + ShowProblem(format, indent, detail, + "NodeType mismatch: expected: %s found: %s", + StlNodeTypeToText(esmp->NodeType), + StlNodeTypeToText(smp->portp->nodep->NodeInfo.NodeType)); + } + return ret; +} + +typedef enum { + SM_VERIFY_OK = 0, // SM matches input topology + SM_VERIFY_DIFF = 1, // SM fully resolved but diff from input topology + SM_VERIFY_UNEXPECTED = 2, // SM not found in input topology + SM_VERIFY_MISSING = 3, // SM not found in fabric, but in input topology + SM_VERIFY_DUP = 4, // possible duplicate in input topology + SM_VERIFY_MAX=4 // maximum value of the above +} SMVerifyResult_t; + +// check both fabric node against input topology +// only does output if detail >= 0 +SMVerifyResult_t SMFabricVerify(SMData *smp, Format_t format, int indent, int detail) +{ + SMVerifyResult_t ret = SM_VERIFY_OK; + + // all checks which are based off of found SM in fabric + if (smp->esmp) { + if (! SMVerify(smp, format, indent, detail)) + ret = SM_VERIFY_DIFF; + } else { + ret = SM_VERIFY_UNEXPECTED; // extra node + ShowProblem(format, indent, detail, "Unexpected SM"); + } + return ret; +} + +// compare ExpectedSM against fabric +// SMFabricVerify will have caught nodes which are different or extra +// this is focused on duplicate ExpectedSMs or missing SMs +// only does output if detail >= 0 +SMVerifyResult_t ExpectedSMVerify(ExpectedSM *esmp, Format_t format, int indent, int detail) +{ + SMVerifyResult_t ret = SM_VERIFY_OK; + + if (! esmp->smp) { + ShowProblem(format, indent, detail, "Missing SM"); + ret = SM_VERIFY_MISSING; // missing link + } else { + if (esmp->smp->esmp != esmp) { + // duplicate node in input topology + ret = SM_VERIFY_DUP; + ShowProblem(format, indent, detail, "Duplicate SM in input"); + } + } + return ret; +} + +// show fabric SM verify errors +void ShowSMVerifySummary(SMData *smp, Format_t format, int indent, int detail) +{ + ShowVerifySMBriefSummary(smp, FALSE, format, indent, 0); + + if (format == FORMAT_XML) + indent +=4; + if (smp->esmp && ! SMVerify(smp, format, indent, detail-1)) { + ShowProblem(format, indent, detail, "SM Attributes Inconsistent"); + } else { + ShowProblem(format, indent, detail, "Unexpected SM"); + } + if (format == FORMAT_XML) + printf("%*s\n", indent-4, ""); +} + +// show input SM verify errors +void ShowExpectedSMVerifySummary(ExpectedSM *esmp, Format_t format, int indent, int detail) +{ + ShowExpectedSMBriefSummary("", esmp, "SM", FALSE, format, indent, detail-1); + if (format == FORMAT_XML) + indent+=4; + (void)ExpectedSMVerify(esmp, format, indent, detail); + if (format == FORMAT_XML) + printf("%*s\n", indent-4, ""); +} + +// Verify SMs in fabric against specified topology +void ShowVerifySMsReport(Point *focus, Format_t format, int indent, int detail) +{ + LIST_ITEM *p; + cl_map_item_t *ip; + uint32 counts[SM_VERIFY_MAX+1] = {0}; + uint32 fabric_errors = 0; + uint32 input_errors = 0; + uint32 fabric_checked = 0; + uint32 input_checked = 0; + SMVerifyResult_t res; + + // intro for report + switch (format) { + case FORMAT_TEXT: + printf("%*sSMs Topology Verification\n", indent, ""); + break; + case FORMAT_XML: + printf("%*s \n", indent, ""); + indent+=4; + break; + default: + break; + } + if (! g_topology_in_file) { + switch (format) { + case FORMAT_TEXT: + printf("%*sReport skipped: -T option not specified\n", indent, ""); + break; + case FORMAT_XML: + printf("%*s\n", indent, ""); + break; + default: + break; + } + goto done; + } + if (! (g_Fabric.flags & FF_EXPECTED_NODES)) { + switch (format) { + case FORMAT_TEXT: + printf("%*sReport skipped: no Nodes information provided\n", indent, ""); + break; + case FORMAT_XML: + printf("%*s\n", indent, ""); + break; + default: + break; + } + goto done; + } + + ShowPointFocus(focus, (FIND_FLAG_FABRIC|FIND_FLAG_ESM), format, indent, detail); + + // First we look at all the fabric SMs + switch (format) { + case FORMAT_TEXT: + printf("%*sSMs Found with incorrect configuration:\n", indent, ""); + break; + case FORMAT_XML: + printf("%*s\n", indent, ""); + break; + default: + break; + } + for (ip=cl_qmap_head(&g_Fabric.AllSMs); ip != cl_qmap_end(&g_Fabric.AllSMs); ip = cl_qmap_next(ip)) { + SMData *smp = PARENT_STRUCT(ip, SMData, AllSMsEntry); + + // We process only SMs whose SMData or resolved ExpectedSM + // match the focus + if (! ( CompareSmPoint(smp, focus) + || (smp->esmp && CompareExpectedSMPoint(smp->esmp, focus)))) + continue; + fabric_checked++; + // detail=-1 in SMFabricVerify will suppress its output + res = SMFabricVerify(smp, format, indent, -1); + counts[res]++; + if (res != SM_VERIFY_OK) { + if (detail) { + if (fabric_errors) { + if (format == FORMAT_TEXT) { + printf("\n"); // blank line between links + } + } else { + ShowVerifySMBriefSummaryHeadings(format, indent, detail-1); + } + ShowSMVerifySummary(smp, format, indent, detail-1); + } + fabric_errors++; + } + } + switch (format) { + case FORMAT_TEXT: + if (detail && fabric_errors) + printf("\n"); // blank line between links + printf("%*s%u of %u Fabric SMs Checked\n", indent, "", + fabric_checked, (unsigned)cl_qmap_count(&g_Fabric.AllSMs)); + break; + case FORMAT_XML: + XmlPrintDec("FabricSMsChecked", fabric_checked, indent); + XmlPrintDec("TotalFabricSMs", (unsigned)cl_qmap_count(&g_Fabric.AllSMs), indent); + break; + default: + break; + } + + // now look at all the expected Nodes from the input topology + switch (format) { + case FORMAT_TEXT: + printf("\n%*sSMs Expected but Missing or Duplicate in input:\n", indent, ""); + break; + case FORMAT_XML: + printf("%*s\n", indent, ""); + break; + default: + break; + } + for (p=QListHead(&g_Fabric.ExpectedSMs); p != NULL; p = QListNext(&g_Fabric.ExpectedSMs, p)) { + ExpectedSM *esmp = (ExpectedSM *)QListObj(p); + + // We process only ExpectedSMs whose resolved SMData or ExpectedSM + // match the focus + if (! ( (esmp->smp && CompareSmPoint(esmp->smp, focus)) + || CompareExpectedSMPoint(esmp, focus))) + continue; + input_checked++; + // detail=-1 in ExpectedSMVerify will suppress its output + res = ExpectedSMVerify(esmp, format, indent, -1); + counts[res]++; + if (res != SM_VERIFY_OK) { + if (detail) { + if (input_errors) { + if (format == FORMAT_TEXT) { + printf("\n"); // blank line between links + } + } else { + ShowVerifySMBriefSummaryHeadings(format, indent, detail-1); + } + ShowExpectedSMVerifySummary(esmp, format, indent, detail-1); + } + input_errors++; + } + } + switch (format) { + case FORMAT_TEXT: + if (detail && input_errors) + printf("\n"); // blank line between links + printf("%*s%u of %u Input SMs Checked\n", indent, "", + input_checked, QListCount(&g_Fabric.ExpectedSMs)); + break; + case FORMAT_XML: + XmlPrintDec("InputSMsChecked", input_checked, indent); + XmlPrintDec("TotalInputSMs", QListCount(&g_Fabric.ExpectedSMs), indent); + break; + default: + break; + } + + // final summary information + switch (format) { + case FORMAT_TEXT: + printf("\n%*sTotal of %u Incorrect SMs found\n", indent, "", fabric_errors+input_errors); + printf("%*s%u Missing, %u Unexpected, %u Duplicate, %u Different\n", indent, "", + counts[SM_VERIFY_MISSING], counts[SM_VERIFY_UNEXPECTED], + counts[SM_VERIFY_DUP], + counts[SM_VERIFY_DIFF]); + break; + case FORMAT_XML: + XmlPrintDec("TotalSMsIncorrect", fabric_errors+input_errors, indent); + break; + XmlPrintDec("Missing", counts[SM_VERIFY_MISSING], indent); + XmlPrintDec("Unexpected", counts[SM_VERIFY_UNEXPECTED], indent); + XmlPrintDec("Duplicate", counts[SM_VERIFY_DUP], indent); + XmlPrintDec("Different", counts[SM_VERIFY_DIFF], indent); + break; + default: + break; + } + +done: + switch (format) { + case FORMAT_TEXT: + DisplaySeparator(); + break; + case FORMAT_XML: + indent-=4; + printf("%*s\n", indent, ""); + break; + default: + break; + } +} + diff --git a/IbaTools/oparesolvehfiport/Makefile b/IbaTools/oparesolvehfiport/Makefile new file mode 100644 index 0000000..7905a4d --- /dev/null +++ b/IbaTools/oparesolvehfiport/Makefile @@ -0,0 +1,155 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** +# Makefile for oparesolvehfiport + +# Include Make Control Settings +include $(TL_DIR)/$(PROJ_FILE_DIR)/Makesettings.project + +#=============================================================================# +# Definitions: +#-----------------------------------------------------------------------------# + +# Name of SubProjects +DS_SUBPROJECTS = +# name of executable or downloadable image +EXECUTABLE = $(BUILDDIR)/oparesolvehfiport$(EXE_SUFFIX) +# list of sub directories to build +DIRS = +# C files (.c) +CFILES = \ + oparesolvehfiport.c \ + # Add more c files here +# C++ files (.cpp) +CCFILES = \ + # Add more cpp files here +# lex files (.lex) +LFILES = \ + # Add more lex files here +# archive library files (basename, $ARFILES will add MOD_LIB_DIR/prefix and suffix) +LIBFILES= +# Windows Resource Files (.rc) +RSCFILES = +# Windows IDL File (.idl) +IDLFILE = +# Windows Linker Module Definitions (.def) file for dll's +DEFFILE = +# targets to build during INCLUDES phase (add public includes here) +INCLUDE_TARGETS = \ + # Add more h hpp files here +# Non-compiled files +MISC_FILES = +# all source files +SOURCES = $(CFILES) $(CCFILES) $(LFILES) $(RSCFILES) $(IDLFILE) +# Source files to include in DSP File +DSP_SOURCES = $(INCLUDE_TARGETS) $(SOURCES) $(MISC_FILES) \ + $(RSCFILES) $(DEFFILE) $(MAKEFILE) +# all object files +OBJECTS = $(CFILES:.c=$(OBJ_SUFFIX)) $(CCFILES:.cpp=$(OBJ_SUFFIX)) \ + $(LFILES:.lex=$(OBJ_SUFFIX)) +RSCOBJECTS = $(RSCFILES:.rc=$(RES_SUFFIX)) +# targets to build during LIBS phase +LIB_TARGETS_IMPLIB = +LIB_TARGETS_ARLIB = # $(LIB_PREFIX)ResourceTest$(ARLIB_SUFFIX) +LIB_TARGETS_EXP = $(LIB_TARGETS_IMPLIB:$(ARLIB_SUFFIX)=$(EXP_SUFFIX)) +LIB_TARGETS_MISC = +# targets to build during CMDS phase +CMD_TARGETS_SHLIB = +CMD_TARGETS_EXE = $(EXECUTABLE) +CMD_TARGETS_MISC = +# files to remove during clean phase +CLEAN_TARGETS_MISC = +CLEAN_TARGETS = $(OBJECTS) $(RSCOBJECTS) $(IDL_TARGETS) $(CLEAN_TARGETS_MISC) +# other files to remove during clobber phase +CLOBBER_TARGETS_MISC= +# sub-directory to install to within bin +BIN_SUBDIR = +# sub-directory to install to within include +INCLUDE_SUBDIR = + +# Additional Settings +#CLOCALDEBUG = User defined C debugging compilation flags [Empty] +#CCLOCALDEBUG = User defined C++ debugging compilation flags [Empty] +#CLOCAL = User defined C flags for compiling [Empty] +#CCLOCAL = User defined C++ flags for compiling [Empty] +#BSCLOCAL = User flags for Browse File Builder [Empty] +#DEPENDLOCAL = user defined makedepend flags [Empty] +#LINTLOCAL = User defined lint flags [Empty] +#LOCAL_INCLUDE_DIRS = User include directories to search for C/C++ headers [Empty] +#LDLOCAL = User defined C flags for linking [Empty] +#IMPLIBLOCAL = User flags for Object Lirary Manager [Empty] +#MIDLLOCAL = User flags for IDL compiler [Empty] +#RSCLOCAL = User flags for resource compiler [Empty] +#LOCALDEPLIBS = User libraries to include in dependencies [Empty] +#LOCALLIBS = User libraries to use when linking [Empty] +# (in addition to LOCALDEPLIBS) +#LOCAL_LIB_DIRS = User library directories for libpaths [Empty] + +CLOCAL=$(CIBACCESS) $(CPIE) +LOCAL_INCLUDE_DIRS= +LOCALDEPLIBS=$(IBACCESS_USER_LIBS) opamgt-priv +LOCALLIBS=$(OPENIB_USER_LIBS) +LOCAL_LIB_DIRS=$(OPENIB_USER_LIB_DIRS) $(IBACCESS_USER_LIB_DIRS) + +# Include Make Rules definitions and rules +include $(TL_DIR)/IbaTools/Makerules.module + +#=============================================================================# +# Overrides: +#-----------------------------------------------------------------------------# +#CCOPT = # C++ optimization flags, default lets build config decide +#COPT = # C optimization flags, default lets build config decide +#SUBSYSTEM = Subsystem to build for (none, console or windows) [none] +# (Windows Only) +#USEMFC = How Windows MFC should be used (none, static, shared, no_mfc) [none] +# (Windows Only) +#=============================================================================# + +#=============================================================================# +# Rules: +#-----------------------------------------------------------------------------# +# process Sub-directories +include $(TL_DIR)/Makerules/Maketargets.toplevel + +# build cmds and libs +include $(TL_DIR)/Makerules/Maketargets.build + +# install for includes, libs and cmds phases +include $(TL_DIR)/Makerules/Maketargets.install + +# install for stage phase +include $(TL_DIR)/Makerules/Maketargets.stage + +# Unit test execution +#include $(TL_DIR)/Makerules/Maketargets.runtest + +#=============================================================================# + +#=============================================================================# +# DO NOT DELETE THIS LINE -- make depend depends on it. +#=============================================================================# diff --git a/IbaTools/oparesolvehfiport/README b/IbaTools/oparesolvehfiport/README new file mode 100644 index 0000000..e8f3108 --- /dev/null +++ b/IbaTools/oparesolvehfiport/README @@ -0,0 +1,3 @@ +[ICS VERSION STRING: unknown] + +resolve a FF style hfi and port to an OFED HFI name and physical port number diff --git a/IbaTools/oparesolvehfiport/oparesolvehfiport.c b/IbaTools/oparesolvehfiport/oparesolvehfiport.c new file mode 100644 index 0000000..5d7307c --- /dev/null +++ b/IbaTools/oparesolvehfiport/oparesolvehfiport.c @@ -0,0 +1,149 @@ +/* BEGIN_ICS_COPYRIGHT7 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT7 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + + + +#include +#include +#include +#include +#define _GNU_SOURCE +#include + +#include +#include + +void Usage(int exitcode) +{ + fprintf(stderr, "Usage: oparesolvehfiport [-o output] [hfi] [port]\n"); + fprintf(stderr, " or\n"); + fprintf(stderr, " oparesolvehfiport --help\n"); + fprintf(stderr, " hfi - hfi, numbered 1..n, 0 = system wide port num\n"); + fprintf(stderr, " (default is 0)\n"); + fprintf(stderr, " port - port, numbered 1..n, 0 = 1st active\n"); + fprintf(stderr, " (default is 0)\n"); + fprintf(stderr, " -o/--output - output type\n"); + fprintf(stderr, "\n"); + fprintf(stderr, "Output Type:\n"); + fprintf(stderr, " devname - prints the device name, in the format hfiname:portnum\n"); + fprintf(stderr, " (default)\n"); + fprintf(stderr, " hfinum - prints the hfi number\n"); + fprintf(stderr, "\n"); + fprintf(stderr, "The hfi and port permit a variety of selections:\n"); + fprintf(stderr, " 0 0 - 1st active port in system\n"); + fprintf(stderr, " x 0 - 1st active port on HFI x\n"); + fprintf(stderr, " 0 y - port y within system (irrespective of which ports are active)\n"); + fprintf(stderr, " x y - HFI x, port y\n"); + fprintf(stderr, "\n"); + fprintf(stderr, "Example:\n"); + fprintf(stderr, " oparesolvehfiport 0 1 #Output: hfi1_0:1\n"); + fprintf(stderr, " oparesolvehfiport -o devname 0 1 #Output: hfi1_0:1\n"); + fprintf(stderr, " oparesolvehfiport -o hfinum 0 1 #Output: 1\n"); + + exit(exitcode); +} + +int main(int argc, char ** argv) +{ + FSTATUS fstatus; + uint8 hfi = 0; + uint8 port = 0; + EUI64 portGuid = -1; + int c; + int devName_out = 1; //default output + int hfiNum, hfiNum_out = 0; + const char *options = "o:"; + const struct option longopts[] = {{"help", 0, 0, '$'}, + {"output", required_argument, 0, 'o'}, + {0, 0, 0, 0}}; + uint32 caCount, portCount; + char fiName[255]; + int caPort; + + while (-1 != (c = getopt_long(argc, argv, options, longopts, NULL))) { + switch (c) { + case '$': + Usage(0); + break; + case 'o': + if (strcmp(optarg, "hfinum") == 0) { + hfiNum_out = 1; + } + else if (strcmp(optarg, "devname") == 0) { + devName_out = 1; + } + else { + fprintf(stderr, "oparesolvehfiport: Invalid Output Type\n"); + Usage(2); + } + break; + default: + Usage(2); + } + } + + if (argc > optind) { + if (FSUCCESS != StringToUint8(&hfi, argv[optind], NULL, 0, TRUE)) { + fprintf(stderr, "oparesolvehfiport: Invalid HFI Number: %s\n", argv[optind]); + Usage(2); + } + } + if (argc > optind+1) { + if (FSUCCESS != StringToUint8(&port, argv[optind+1], NULL, 0, TRUE)) { + fprintf(stderr, "oparesolvehfiport: Invalid Port Number: %s\n", argv[optind+1]); + Usage(2); + } + } + + // find portGuid specified + fstatus = omgt_get_portguid(hfi, port, NULL, NULL, NULL, &portGuid, NULL, NULL, + &caCount, &portCount, fiName, &caPort, NULL); + + if (FNOT_FOUND == fstatus) { + fprintf(stderr, "oparesolvehfiport: %s\n", + iba_format_get_portguid_error(hfi, port, caCount, portCount)); + return 1; + } else if (FSUCCESS != fstatus) { + fprintf(stderr, "opasaquery: iba_get_portguid Failed: %s\n", iba_fstatus_msg(fstatus)); + return 1; + } + //printf("PORT GUID 0x%016"PRIx64"\n",portGuid); + + if(hfiNum_out) { + hfiNum = omgt_get_hfi_num(fiName); + printf("%d\n", hfiNum); + } + else if(devName_out) { + printf("%s:%d\n", fiName, caPort); + } + + return 0; +} diff --git a/IbaTools/opasmaquery/Makefile b/IbaTools/opasmaquery/Makefile new file mode 100644 index 0000000..f089883 --- /dev/null +++ b/IbaTools/opasmaquery/Makefile @@ -0,0 +1,167 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** +# Makefile for portdown + +# Include Make Control Settings +include $(TL_DIR)/$(PROJ_FILE_DIR)/Makesettings.project + +#=============================================================================# +# Definitions: +#-----------------------------------------------------------------------------# + +# Name of SubProjects +DS_SUBPROJECTS = +# name of executable or downloadable image +EXECUTABLE = $(BUILDDIR)/opasmaquery$(EXE_SUFFIX) +# list of sub directories to build +DIRS = +# C files (.c) +CFILES = \ + opasmaquery.c \ + sma.c \ + pma.c \ + # Add more c files here +# C++ files (.cpp) +CCFILES = \ + # Add more cpp files here +# lex files (.lex) +LFILES = \ + # Add more lex files here +# archive library files (basename, $ARFILES will add MOD_LIB_DIR/prefix and suffix) +LIBFILES= +# Windows Resource Files (.rc) +RSCFILES = +# Windows IDL File (.idl) +IDLFILE = +# Windows Linker Module Definitions (.def) file for dll's +DEFFILE = +# targets to build during INCLUDES phase (add public includes here) +INCLUDE_TARGETS = \ + # Add more h hpp files here +# Non-compiled files +MISC_FILES = +# all source files +SOURCES = $(CFILES) $(CCFILES) $(LFILES) $(RSCFILES) $(IDLFILE) +# Source files to include in DSP File +DSP_SOURCES = $(INCLUDE_TARGETS) $(SOURCES) $(MISC_FILES) \ + $(RSCFILES) $(DEFFILE) $(MAKEFILE) +# all object files +OBJECTS = $(CFILES:.c=$(OBJ_SUFFIX)) $(CCFILES:.cpp=$(OBJ_SUFFIX)) \ + $(LFILES:.lex=$(OBJ_SUFFIX)) +RSCOBJECTS = $(RSCFILES:.rc=$(RES_SUFFIX)) +# targets to build during LIBS phase +LIB_TARGETS_IMPLIB = +LIB_TARGETS_ARLIB = # $(LIB_PREFIX)ResourceTest$(ARLIB_SUFFIX) +LIB_TARGETS_EXP = $(LIB_TARGETS_IMPLIB:$(ARLIB_SUFFIX)=$(EXP_SUFFIX)) +LIB_TARGETS_MISC = +# targets to build during CMDS phase +CMD_TARGETS_SHLIB = +CMD_TARGETS_EXE = $(EXECUTABLE) + +CMD_TARGETS_MISC = $(BUILDDIR)/opapmaquery$(EXE_SUFFIX) +# files to remove during clean phase +CLEAN_TARGETS_MISC = +CLEAN_TARGETS = $(OBJECTS) $(RSCOBJECTS) $(IDL_TARGETS) $(CLEAN_TARGETS_MISC) +# other files to remove during clobber phase +CLOBBER_TARGETS_MISC= +# sub-directory to install to within bin +BIN_SUBDIR = +# sub-directory to install to within include +INCLUDE_SUBDIR = + +# Additional Settings +#CLOCALDEBUG = User defined C debugging compilation flags [Empty] +#CCLOCALDEBUG = User defined C++ debugging compilation flags [Empty] +#CLOCAL = User defined C flags for compiling [Empty] +#CCLOCAL = User defined C++ flags for compiling [Empty] +#BSCLOCAL = User flags for Browse File Builder [Empty] +#DEPENDLOCAL = user defined makedepend flags [Empty] +#LINTLOCAL = User defined lint flags [Empty] +#LOCAL_INCLUDE_DIRS = User include directories to search for C/C++ headers [Empty] +#LDLOCAL = User defined C flags for linking [Empty] +#IMPLIBLOCAL = User flags for Object Lirary Manager [Empty] +#MIDLLOCAL = User flags for IDL compiler [Empty] +#RSCLOCAL = User flags for resource compiler [Empty] +#LOCALDEPLIBS = User libraries to include in dependencies [Empty] +#LOCALLIBS = User libraries to use when linking [Empty] +# (in addition to LOCALDEPLIBS) +#LOCAL_LIB_DIRS = User library directories for libpaths [Empty] + +CLOCAL=$(CIBACCESS) $(CPIE) +LOCAL_INCLUDE_DIRS= +ifeq "$(IB_STACK)" "IBACCESS" +LOCALDEPLIBS = $(IBACCESS_USER_LIBS) IbPrint +LOCALLIBS= +LOCAL_LIB_DIRS=$(IBACCESS_USER_LIB_DIRS) +else +LOCALDEPLIBS = $(IBACCESS_USER_LIBS) IbPrint opamgt-priv +LOCALLIBS=$(OPENIB_USER_LIBS) +LOCAL_LIB_DIRS=$(OPENIB_USER_LIB_DIRS) $(IBACCESS_USER_LIB_DIRS) +endif + +# Include Make Rules definitions and rules +include $(TL_DIR)/IbaTools/Makerules.module + +#=============================================================================# +# Overrides: +#-----------------------------------------------------------------------------# +#CCOPT = # C++ optimization flags, default lets build config decide +#COPT = # C optimization flags, default lets build config decide +#SUBSYSTEM = Subsystem to build for (none, console or windows) [none] +# (Windows Only) +#USEMFC = How Windows MFC should be used (none, static, shared, no_mfc) [none] +# (Windows Only) +#=============================================================================# + +#=============================================================================# +# Rules: +#-----------------------------------------------------------------------------# +# process Sub-directories +include $(TL_DIR)/Makerules/Maketargets.toplevel + +# build cmds and libs +include $(TL_DIR)/Makerules/Maketargets.build + +# install for includes, libs and cmds phases +include $(TL_DIR)/Makerules/Maketargets.install + +$(BUILDDIR)/opapmaquery$(EXE_SUFFIX): $(BUILDDIR)/opasmaquery$(EXE_SUFFIX) + cp $(BUILDDIR)/opasmaquery$(EXE_SUFFIX) $(BUILDDIR)/opapmaquery$(EXE_SUFFIX) + +# install for stage phase +include $(TL_DIR)/Makerules/Maketargets.stage + +# Unit test execution +#include $(TL_DIR)/Makerules/Maketargets.runtest + +#=============================================================================# + +#=============================================================================# +# DO NOT DELETE THIS LINE -- make depend depends on it. +#=============================================================================# diff --git a/IbaTools/opasmaquery/opasmaquery.c b/IbaTools/opasmaquery/opasmaquery.c new file mode 100644 index 0000000..1632218 --- /dev/null +++ b/IbaTools/opasmaquery/opasmaquery.c @@ -0,0 +1,406 @@ +/* BEGIN_ICS_COPYRIGHT7 **************************************** + +Copyright (c) 2015-2018, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT7 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +#include + +#include "opasmaquery.h" + + +uint8 g_detail = CABLEINFO_DETAIL_BRIEF; +unsigned g_verbose = 0; +PrintDest_t g_dest; +uint8 g_drpath[64] = {0}; +char *g_cmdname; + +/* for pmaquery */ +uint32 g_counterSelectMask = 0xffffffff; // default is all counters, so set all bits +uint64 g_portSelectMask[4] = {0}; // 256 bitmask +uint64 g_vlSelectMask = 0; + +/* for pma/sma query*/ +uint64_t g_transactID = 0xffffffff12340000; // Upper half overwritten by driver. + + +optypes_t *g_optypes; + +static FSTATUS parsePortMask(const char *str) +{ + unsigned int cnt = 0; + size_t len = 0; + char tempStr[65] = {0}; + + if (!str) + return FINVALID_PARAMETER; + + while (isspace(*str)) ++str; + + /* Require leading '0x' */ + if (str[0] != '0' || str[1] != 'x') + return FINVALID_PARAMETER; + + str = &str[2]; + + len = strlen(str); + + snprintf(tempStr, sizeof(tempStr), "%.*s%s", + (int)(64-len), "0000000000000000000000000000000000000000000000000000000000000000", + str); + + cnt = sscanf(tempStr, "%16"SCNx64"%16"SCNx64"%16"SCNx64"%16"SCNx64, + &g_portSelectMask[0], &g_portSelectMask[1], &g_portSelectMask[2], + &g_portSelectMask[3]); + + if (cnt != 4) + return FINVALID_PARAMETER; + + return FSUCCESS; +} + +void Usage(boolean displayAbridged) +{ + if ( (strcmp(g_cmdname, "opasmaquery") == 0)) { + sma_Usage(displayAbridged); + } else if ( (strcmp(g_cmdname, "opapmaquery") == 0)) { + pma_Usage(displayAbridged); + } + exit(1); +} //Usage + +int +string_to_otype(const char *str) +{ + int otype; + for (otype=0; g_optypes[otype].name; otype++) + { + if (strcmp(str, g_optypes[otype].name)==0) + break; + } + return (otype); +} + +int main(int argc, char** argv) +{ + int rc; + STL_SMP smp; + int c; + uint8 hfi = 0; + uint8 port = 0; // default to port 0, this way pma can will choose first active. + uint32 slid = 0; + const char *options; + int otype = 0; + uint8 i; + char *mports = NULL; + query_func_t func; + argrec args = {0}; + int status = 0; + args.sl = 0xff; // set to invalid number to detect if set. + + g_cmdname = strrchr(argv[0], '/'); + if (g_cmdname != NULL) { + g_cmdname++; + } else { + g_cmdname = argv[0]; + } + + if ( (strcmp(g_cmdname, "opasmaquery") == 0)) { + options = "vd:nl:m:h:p:o:b:f:gt:c:i?"; + g_optypes = sma_query; + otype = string_to_otype("nodeinfo"); + } else if ( (strcmp(g_cmdname, "opapmaquery") == 0)) { + options = "vn:s:l:m:h:p:o:e:w:?"; + g_optypes = stl_pma_query; + otype = string_to_otype("getportstatus"); + } else { + fprintf(stderr, "Invalid command name (must be opasmaquery or opapmaquery)\n"); + exit(1); + } + + VRBSE_PRINT("Debug: cmdname=%s; Options=%s\n", g_cmdname, options); + + if (argc>1) { + if (!strcmp(argv[1],"--help")) { + Usage(FALSE); + exit(2); + } + } + + while (-1 != (c = getopt(argc, argv, options))) { + switch (c) { + case 'g': + args.printLineByLine++; + break; + case 'd': + if (FSUCCESS != StringToUint8(&g_detail, optarg, NULL, 0, TRUE)) { + fprintf(stderr, "%s: Invalid Detail Level: %s\n", g_cmdname, optarg); + Usage(FALSE); + } + break; + case 'i': + args.iflag = TRUE; + break; + case 'v': + g_verbose++; + if (g_verbose>3) umad_debug(g_verbose-3); + break; + case 's': + if (FSUCCESS != StringToUint8(&args.sl, optarg, NULL, 0, TRUE) + || args.sl > 15 ) { + fprintf(stderr, "%s: Invalid Service Level: %s\n", g_cmdname, optarg); + Usage(FALSE); + } + break; + case 'l': + if (FSUCCESS != StringToUint32(&args.dlid, optarg, NULL, 0, TRUE)) { + fprintf(stderr, "%s: Invalid DLID: %s\n", g_cmdname, optarg); + Usage(FALSE); + } + break; + case 't': + if (FSUCCESS != StringToUint8(&args.table, optarg, NULL, 0, TRUE)) { + fprintf(stderr, "%s: Invalid table: %s\n", g_cmdname, optarg); + Usage(FALSE); + } + args.tflag = TRUE; + break; + case 'c': + args.cflag = TRUE; + break; + case 'b': + { + char *sTemp; + + if (*(sTemp = optarg) == ',') { + args.block = 0; + sTemp++; + + if (FSUCCESS != StringToUint8(&args.bcount, sTemp, NULL, 0, TRUE)) { + fprintf(stderr, "%s: Invalid block count: %s\n", g_cmdname, optarg); + Usage(FALSE); + } + + args.bflag = TRUE; + break; + } + + if (FSUCCESS != StringToUint16(&args.block, optarg, &sTemp, 0, TRUE)) { + fprintf(stderr, "%s: Invalid block: %s\n", g_cmdname, optarg); + Usage(FALSE); + } + + if (*sTemp == ',') { + sTemp++; + if (FSUCCESS != StringToUint8(&args.bcount, sTemp, NULL, 0, TRUE)) { + fprintf(stderr, "%s: Invalid block count: %s\n", g_cmdname, optarg); + Usage(FALSE); + } + } else { + args.bcount=1; + } + + args.bflag = TRUE; + } + break; + case 'f': + if (FSUCCESS != StringToUint32(&args.flid, optarg, NULL, 0, TRUE)) { + fprintf(stderr, "%s: Invalid FLID: %s\n", g_cmdname, optarg); + Usage(FALSE); + } + break; + case 'm': + args.mflag = TRUE; + mports = optarg; // Can be a single port or a pair. + break; + case 'h': + if (FSUCCESS != StringToUint8(&hfi, optarg, NULL, 0, TRUE)) { + fprintf(stderr, "%s: Invalid HFI Number: %s\n", g_cmdname, optarg); + Usage(FALSE); + } + break; + case 'p': + if (FSUCCESS != StringToUint8(&port, optarg, NULL, 0, TRUE)) { + fprintf(stderr, "%s: Invalid Port Number: %s\n", g_cmdname, optarg); + Usage(FALSE); + } + break; + case 'o': + otype = string_to_otype(optarg); + if (! g_optypes[otype].name) + { + fprintf(stderr, "%s: invalid arg for -o %s\n", g_cmdname, optarg); + Usage(FALSE); + } + break; + case 'e': + if (FSUCCESS != StringToUint32(&g_counterSelectMask, optarg, NULL, 0, TRUE)) { + fprintf(stderr, "%s: Invalid error select mask: %s\n", g_cmdname, optarg); + Usage(FALSE); + } + args.eflag = TRUE; + break; + case 'n': + if (FSUCCESS != parsePortMask(optarg)) { + fprintf(stderr, "%s: Invalid port select mask: %s\n", g_cmdname, optarg); + Usage(FALSE); + } + break; + case 'w': + if (FSUCCESS != StringToUint64(&g_vlSelectMask, optarg, NULL, 0, TRUE)) { + fprintf(stderr, "%s: Invalid VL select mask: %s\n", g_cmdname, optarg); + Usage(FALSE); + } + break; + + default: + Usage(TRUE); + break; + } + } + + func = g_optypes[otype].pf; + args.oname = g_optypes[otype].name; + DBGPRINT("argc=%d optind=%d argv[optind] in string= %s\n", argc, optind, argv[optind]); + if ( (strcmp(g_cmdname, "opasmaquery") == 0)) { + // for SMA only: allow DR path as additional arguments + if ((argc - optind) > MAX_DR_PATH) + Usage(FALSE); + + for (i=1;optind optind) + Usage(FALSE); + } + + + + if (args.flid && ! g_optypes[otype].fflag) { + fprintf(stderr, "%s: -f ignored for -o %s\n", g_cmdname, g_optypes[otype].name); + } + if (args.bflag && ! g_optypes[otype].bflag) { + fprintf(stderr, "%s: -b ignored for -o %s\n", g_cmdname, g_optypes[otype].name); + } + if (args.eflag && ! g_optypes[otype].eflag) { + fprintf(stderr, "%s: -e ignored for -o %s\n", g_cmdname, g_optypes[otype].name); + } + if (args.cflag && ! g_optypes[otype].cflag) { + fprintf(stderr, "%s: -c ignored for -o %s\n", g_cmdname, g_optypes[otype].name); + } + + if (args.mflag) { + if (! g_optypes[otype].mflag && ! g_optypes[otype].mflag2) { + fprintf(stderr, "%s: -m ignored for -o %s\n", g_cmdname, g_optypes[otype].name); + } else if (g_optypes[otype].mflag && !strchr(mports,',')) { + // simple port number + if (FSUCCESS != StringToUint8(&args.dport, mports, NULL, 0, TRUE)) { + fprintf(stderr, "%s: Invalid port: %s\n", g_cmdname, mports); + Usage(FALSE); + } + args.mcount=1; + } else if (g_optypes[otype].mflag2 && strchr(mports,',')) { + // inport,outport + char *sTemp; + if (FSUCCESS != StringToUint8(&args.inport, mports, &sTemp, 0, TRUE) + || ! sTemp || *sTemp != ',') { + fprintf(stderr, "%s: Invalid ports: %s, ports must be the form \n", g_cmdname, mports); + Usage(FALSE); + } + sTemp++; + if (FSUCCESS != StringToUint8(&args.outport, sTemp, NULL, 0, TRUE)) { + fprintf(stderr, "%s: Invalid outport: %s\n", g_cmdname, mports); + Usage(FALSE); + } + args.mflag2=1; + } else if (otype == string_to_otype("portinfo") && strchr(mports,',')) { + // port,count + char *sTemp; + if (FSUCCESS != StringToUint8(&args.dport, mports, &sTemp, 0, TRUE) + || ! sTemp || *sTemp != ',') { + fprintf(stderr, "%s: Invalid ports: %s, ports must be the form \n", g_cmdname, mports); + Usage(FALSE); + } + sTemp++; + if (FSUCCESS != StringToUint8(&args.mcount, sTemp, NULL, 0, TRUE) || args.mcount == 0) { + fprintf(stderr, "%s: Invalid Port Count: %s\n", g_cmdname, mports); + Usage(FALSE); + } + } else { + fprintf(stderr, "%s: illegal value for -m: \"%s\"\n", + g_cmdname, mports); + Usage(FALSE); + } + } + + struct omgt_params params = {.debug_file = g_verbose > 2 ? stdout : NULL}; + status = omgt_open_port_by_num (&args.omgt_port, hfi, port, ¶ms); + if (status == OMGT_STATUS_NOT_DONE) { + // Wildcard search for either/or port & hfi yielded no ACTIVE ports. + if (!port) { + char *sErr_msg="No Active port found"; + if(!hfi) { + // System wildcard search for Active port failed. + // Fallback and query default hfi:1, port:1 + fprintf(stderr, "%s in System. Trying default hfi:1 port:1\n", sErr_msg); + hfi = 1; + port = 1; + status = omgt_open_port_by_num(&args.omgt_port, hfi, port, ¶ms); + } else { + fprintf(stderr, "%s on hfi:%d\n", sErr_msg, hfi); + exit (1); + } + } + } + if (status != 0) { + fprintf(stderr, "failed to open port hfi %d:%d: %s\n", hfi, port, strerror(status)); + exit(1); + } + + (void)omgt_port_get_port_lid(args.omgt_port, &slid); + (void)omgt_port_get_hfi_port_num(args.omgt_port, &args.port); + args.slid = (STL_LID)slid; + + PrintDestInitFile(&g_dest, stdout); + + if (! func(&args, (uint8_t *)&smp, sizeof(smp), TRUE)) { + rc = 1; + } else { + rc = 0; + } + + omgt_close_port(args.omgt_port); + + return rc; +} //main diff --git a/IbaTools/opasmaquery/opasmaquery.h b/IbaTools/opasmaquery/opasmaquery.h new file mode 100644 index 0000000..67a70ce --- /dev/null +++ b/IbaTools/opasmaquery/opasmaquery.h @@ -0,0 +1,124 @@ +/* BEGIN_ICS_COPYRIGHT7 **************************************** + +Copyright (c) 2015-2018, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT7 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +#include +#include +#include + +// work around conflicting names +#include "infiniband/umad.h" +#include "iba/ib_types.h" +#include "iba/ib_sm_priv.h" +#include "iba/ib_helper.h" +#include "iba/ib_ibt.h" +#include "iba/ipublic.h" +#include "ibprint.h" + +#include "iba/stl_mad_priv.h" +#include "iba/stl_sm_priv.h" +#include "iba/stl_pm.h" +#include "stl_print.h" + +extern uint8 g_detail; +extern unsigned g_verbose; +extern PrintDest_t g_dest; +extern uint8 g_drpath[64]; +extern char *g_cmdname; + +extern uint64_t g_transactID; +#define RESP_WAIT_TIME (1000) // 1000 milliseconds for receive response + +#if defined(DBGPRINT) +#undef DBGPRINT +#endif +#define VRBSE_PRINT(format, args...) do { if (g_verbose) { fflush(stdout); fprintf(stdout, format, ##args); } } while (0) +#define DBGPRINT(format, args...) do { if (g_verbose>1) { fflush(stdout); fprintf(stderr, format, ##args); } } while (0) + +#define MAX_DR_PATH 63 + +typedef struct _argrec { + uint8 port; // local port (-p) + STL_LID slid; //source lid + STL_LID dlid; //dest lid (-l) + STL_LID flid; // -f lid to lookup in fwd table to select block + boolean bflag; // was -b option supplied + boolean eflag; // was -e option used + uint16 block; // block specified via -b + uint8 bcount; // optional count specified via -b + uint8 drpaths;// additional SMA command line arguments + boolean mflag; // was -m option supplied + boolean mflag2; // were two ports supplied + boolean iflag; // switch internal + boolean tflag; // was -t option supplied + uint8 table; // optional table specification + uint8 dport; // typical -m option + uint8 mcount; // optional count specified via -m + uint8 inport; // used for pstate, BCT, SCVL and SCSC maps. + uint8 outport;// used for pstate, BCT, SCVL and SCSC maps. + const char* oname; // -o name + struct omgt_port *omgt_port; + boolean printLineByLine; // modify output to be line by line + uint8 sl; + boolean cflag; +} argrec; + +typedef boolean (*query_func_t)(argrec *args, uint8_t *mad, size_t mad_len, boolean print); +typedef struct optypes_s { + const char *name; + query_func_t pf; + boolean displayWithAbridged; + const char* description; + boolean mflag; // is -m port option applicable + boolean mflag2; // is -m inport,outport option applicable + boolean fflag; // is -f option applicable + boolean bflag; // is -b block option applicable + boolean iflag; // is -i option applicable + boolean tflag; // is -t option applicable + boolean cflag; // is -c option applicable + boolean nflag; // is -n option applicable + boolean lflag; // is -l option applicable + boolean eflag; // is -e option applicable + boolean wflag; // is -w option applicable +} optypes_t; + +extern void Usage(boolean displayAbridged); + +// SMA Query +extern optypes_t sma_query []; +extern void sma_Usage(boolean displayAbridged); + +// PMA Query +extern optypes_t stl_pma_query []; +extern void pma_Usage(boolean displayAbridged); +extern uint32 g_counterSelectMask; +extern uint64 g_portSelectMask[4]; +extern uint64 g_vlSelectMask; + diff --git a/IbaTools/opasmaquery/pma.c b/IbaTools/opasmaquery/pma.c new file mode 100644 index 0000000..e0bc707 --- /dev/null +++ b/IbaTools/opasmaquery/pma.c @@ -0,0 +1,514 @@ +/* BEGIN_ICS_COPYRIGHT7 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT7 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +#include + +#include "opasmaquery.h" + + +#define MSG_PMA_SEND_RECV_FAILURE "failed PMA Send or Receive" + +static FSTATUS perform_stl_pma_query(uint8 method, uint16 attrid, uint32 attrmod, argrec *args, STL_PERF_MAD *mad, size_t send_size) +{ + FSTATUS status; + STL_LID dlid; + uint8_t sl = args->sl; + uint8_t port_state; + if (sl == 0xff) { + // check if sl has been set, if not use default sl (SM SL) + (void)omgt_port_get_port_sm_sl(args->omgt_port, &sl); + } + + mad->common.BaseVersion = STL_BASE_VERSION; + mad->common.ClassVersion = STL_PM_CLASS_VERSION; + mad->common.MgmtClass = MCLASS_PERF; + mad->common.u.NS.Status.AsReg16 = 0; + mad->common.mr.AsReg8 = 0; + mad->common.mr.s.Method = method; + mad->common.AttributeID = attrid; + mad->common.TransactionID = (++g_transactID); + mad->common.AttributeModifier = attrmod; + + (void)omgt_port_get_port_state(args->omgt_port, &port_state); + if (port_state != IB_PORT_ACTIVE) { + uint8_t port_num; + char hfi_name[IBV_SYSFS_NAME_MAX] = {0}; + (void)omgt_port_get_hfi_port_num(args->omgt_port, &port_num); + (void)omgt_port_get_hfi_name(args->omgt_port, hfi_name); + fprintf(stderr, "WARNING port (%s:%d) is not ACTIVE!\n", + hfi_name, port_num); + dlid = args->dlid ? args->dlid : STL_LID_PERMISSIVE; // perm lid for local query + } else { + dlid = args->dlid ? args->dlid : args->slid; // use slid for local query + } + + // Determine which pkey to use (full or limited) + // Attempt to use full at all times, otherwise, can + // use the limited for queries of the local port. + uint16_t pkey = omgt_get_mgmt_pkey(args->omgt_port, args->dlid, args->drpaths); + if (pkey==0) { + fprintf(stderr, "ERROR: Local port does not have management privileges\n"); + return (FPROTECTION); + } + + if (g_verbose) { + PrintFunc(&g_dest, "Sending MAD to 0x%08x:\n", dlid); + PrintMadHeader(&g_dest, 2, &mad->common); + PrintSeparator(&g_dest); + } + + BSWAP_MAD_HEADER((MAD*)mad); + { + struct omgt_mad_addr addr = { + lid : dlid, + qpn : 1, + qkey : QP1_WELL_KNOWN_Q_KEY, + pkey : pkey, + sl : sl + }; + size_t recv_size = sizeof(*mad); + status = omgt_send_recv_mad_no_alloc(args->omgt_port, (uint8_t *)mad, send_size+sizeof(MAD_COMMON), &addr, + (uint8_t *)mad, &recv_size, RESP_WAIT_TIME, 0); + } + BSWAP_MAD_HEADER((MAD*)mad); + if (status == FSUCCESS && g_verbose) { + PrintFunc(&g_dest, "Received MAD:\n"); + PrintMadHeader(&g_dest, 2, &mad->common); + PrintSeparator(&g_dest); + } + + if (FSUCCESS == status && mad->common.u.NS.Status.AsReg16 != MAD_STATUS_SUCCESS) { + fprintf(stderr, "MAD returned with Bad Status: %s\n", + iba_mad_status_msg2(mad->common.u.NS.Status.AsReg16)); + return FERROR; + } + return status; +} //perform_stl_pma_query + +static int getNumPortsFromSelMask(uint64 portSelectMask[]) +{ + int i = 0; + int numPorts = 0; + + while (i < 4) { + uint64 temp = portSelectMask[i++]; + + while (temp) { + if ( temp & (uint64)1 ) ++numPorts; + temp>>=1; + } + } + + return(numPorts); +} + +// get portSelect value to use for port counter query/clear +static uint8 pma_get_portNum(argrec *args) +{ + uint8 port; + if (args->mflag) { + // TBD - verify dport is valid: + // for Switch: 0-maxPort or ALL_PORT_SELECT + // for CA: must match port number of dlid (perhaps default it to that) + port = args->dport; + } else if (! args->dlid) { + // local query, use same port as local HFI port for query + port = args->port; + } else { + fprintf(stderr, "%s: Error: -m option required for -o %s\n", g_cmdname, args->oname); + Usage(FALSE); // exits application + port = 0; // keep compiler happy + } + VRBSE_PRINT("PortSelect=%u\n", port); + return port; +} + +static void getStlPortSelectMask(uint64 *dest, argrec *args) +{ + if (g_portSelectMask[3] || g_portSelectMask[2] || + g_portSelectMask[1] || g_portSelectMask[0]) { + // ok as is + memcpy(dest, g_portSelectMask, sizeof(g_portSelectMask)); + } else if (! args->dlid) { + // local query, use same port as local HFI port for query + memset(dest, 0, sizeof(uint64) * 4); + dest[3] = (1 << args->port); + } else { + fprintf(stderr, "Error: portSelectMask must be non-zero - must select at least one port\n"); + Usage(FALSE); // exits application + } + VRBSE_PRINT("PortSelectMask=0x%016"PRIx64" 0x%016"PRIx64" 0x%016"PRIx64" 0x%016"PRIx64"\n", + dest[0], dest[1], dest[2], dest[3]); +} + +#if 0 +static boolean checkStlVLSelectMask(uint64 VLSelectMask) +{ + int i; + + /* check that only bits 0-7 and 15 can be set */ + for (i = 8; i < 15; i++) { + if ((VLSelectMask >> i) & 1) { + fprintf(stderr, "Error: VLSelectMask cannot select VL %d - invalid\n", i); + return(FALSE); + } + } + for (i = 16; i < 63; i++) { + if ((VLSelectMask >> i) & 1) { + fprintf(stderr, "Error: VLSelectMask cannot select VL %d - invalid\n", i); + return(FALSE); + } + } + return(TRUE); +} +#endif + +static boolean stl_pma_get_class_port_info(argrec *args, uint8_t *pm, size_t pm_len, boolean print) +{ + STL_PERF_MAD *mad = (STL_PERF_MAD*)pm; + FSTATUS status = FSUCCESS; + + STL_CLASS_PORT_INFO *pClassPortInfo = (STL_CLASS_PORT_INFO *)&(mad->PerfData); + MemoryClear(mad, sizeof(*mad)); + + if ( FSUCCESS != (status = perform_stl_pma_query (MMTHD_GET, STL_PM_ATTRIB_ID_CLASS_PORTINFO, 0, args, mad, 0))) { + fprintf(stderr, "%s: %s: %s\n", __func__, MSG_PMA_SEND_RECV_FAILURE, iba_fstatus_msg(status)); + return FALSE; + } else { + BSWAP_STL_CLASS_PORT_INFO(pClassPortInfo ); + if (print) + PrintStlClassPortInfo(&g_dest, 0 /* indent */, pClassPortInfo, MCLASS_PERF); + return TRUE; + } +} //stl_pma_get_class_port_info + +static boolean stl_pma_get_PortStatus(argrec *args, uint8_t *pm, size_t pm_len, boolean print) +{ + STL_PERF_MAD *mad = (STL_PERF_MAD*)pm; + FSTATUS status = FSUCCESS; + + STL_PORT_STATUS_REQ *pStlPortStatus = (STL_PORT_STATUS_REQ *)&(mad->PerfData); + STL_PORT_STATUS_RSP *pStlPortStatusRsp; + MemoryClear(mad, sizeof(*mad)); + + pStlPortStatus->PortNumber = pma_get_portNum(args); + pStlPortStatus->VLSelectMask = g_vlSelectMask; + memset(pStlPortStatus->Reserved, 0, sizeof(pStlPortStatus->Reserved)); + BSWAP_STL_PORT_STATUS_REQ(pStlPortStatus ); + + if ( FSUCCESS != (status = perform_stl_pma_query (MMTHD_GET, STL_PM_ATTRIB_ID_PORT_STATUS, 0x01000000, args, mad, sizeof(STL_PORT_STATUS_REQ)))) { + fprintf(stderr, "%s: %s: %s\n", __func__, MSG_PMA_SEND_RECV_FAILURE, iba_fstatus_msg(status)); + return FALSE; + } else { + pStlPortStatusRsp = (STL_PORT_STATUS_RSP *)pStlPortStatus; + BSWAP_STL_PORT_STATUS_RSP(pStlPortStatusRsp); + if (print) + PrintStlPortStatusRsp(&g_dest, 0 /* indent */, pStlPortStatusRsp); + return TRUE; + } +} + +static boolean stl_pma_clear_PortStatus(argrec *args, uint8_t *pm, size_t pm_len, boolean print) +{ + STL_PERF_MAD *mad = (STL_PERF_MAD*)pm; + uint32 attrmod; + FSTATUS status = FSUCCESS; + + STL_CLEAR_PORT_STATUS *pStlClearPortStatus = (STL_CLEAR_PORT_STATUS *)&(mad->PerfData); + MemoryClear(mad, sizeof(*mad)); + + getStlPortSelectMask(pStlClearPortStatus->PortSelectMask, args); + attrmod = 1 << 24; + pStlClearPortStatus->CounterSelectMask.AsReg32 = g_counterSelectMask; + BSWAP_STL_CLEAR_PORT_STATUS_REQ(pStlClearPortStatus); + + if ( FSUCCESS != (status = perform_stl_pma_query (MMTHD_SET, STL_PM_ATTRIB_ID_CLEAR_PORT_STATUS, attrmod, args, mad, sizeof(STL_CLEAR_PORT_STATUS)))) { + fprintf(stderr, "%s: %s: %s\n", __func__, MSG_PMA_SEND_RECV_FAILURE, iba_fstatus_msg(status)); + return FALSE; + } else { + BSWAP_STL_CLEAR_PORT_STATUS_REQ(pStlClearPortStatus); + if (print) + PrintStlClearPortStatus(&g_dest, 0 /* indent */, pStlClearPortStatus); + return TRUE; + } +} + +static boolean stl_pma_get_DataCounters(argrec *args, uint8_t *pm, size_t pm_len, boolean print) +{ + STL_PERF_MAD *mad = (STL_PERF_MAD*)pm; + uint32 attrmod; + FSTATUS status = FSUCCESS; + + STL_DATA_PORT_COUNTERS_REQ *pStlDataPortCountersReq = (STL_DATA_PORT_COUNTERS_REQ *)&(mad->PerfData); + STL_DATA_PORT_COUNTERS_RSP *pStlDataPortCountersRsp; + MemoryClear(mad, sizeof(*mad)); + + getStlPortSelectMask(pStlDataPortCountersReq->PortSelectMask, args); + attrmod = getNumPortsFromSelMask(pStlDataPortCountersReq->PortSelectMask) << 24; + pStlDataPortCountersReq->VLSelectMask = g_vlSelectMask; + BSWAP_STL_DATA_PORT_COUNTERS_REQ(pStlDataPortCountersReq); + + if ( FSUCCESS != (status = perform_stl_pma_query (MMTHD_GET, STL_PM_ATTRIB_ID_DATA_PORT_COUNTERS, attrmod, args, mad, sizeof(STL_DATA_PORT_COUNTERS_REQ)))) { + fprintf(stderr, "%s: %s: %s\n", __func__, MSG_PMA_SEND_RECV_FAILURE, iba_fstatus_msg(status)); + return FALSE; + } else { + pStlDataPortCountersRsp = (STL_DATA_PORT_COUNTERS_RSP *)pStlDataPortCountersReq; + BSWAP_STL_DATA_PORT_COUNTERS_RSP(pStlDataPortCountersRsp); + if (print) + PrintStlDataPortCountersRsp(&g_dest, 0 /* indent */, pStlDataPortCountersRsp); + return TRUE; + } +} + +static boolean stl_pma_get_ErrorCounters(argrec *args, uint8_t *pm, size_t pm_len, boolean print) +{ + STL_PERF_MAD *mad = (STL_PERF_MAD*)pm; + uint32 attrmod; + FSTATUS status = FSUCCESS; + + STL_ERROR_PORT_COUNTERS_REQ *pStlErrorPortCountersReq = (STL_ERROR_PORT_COUNTERS_REQ *)&(mad->PerfData); + STL_ERROR_PORT_COUNTERS_RSP *pStlErrorPortCountersRsp; + MemoryClear(mad, sizeof(*mad)); + + getStlPortSelectMask(pStlErrorPortCountersReq->PortSelectMask, args); + attrmod = getNumPortsFromSelMask(pStlErrorPortCountersReq->PortSelectMask) << 24; + pStlErrorPortCountersReq->VLSelectMask = g_vlSelectMask; + + BSWAP_STL_ERROR_PORT_COUNTERS_REQ(pStlErrorPortCountersReq); + + if ( FSUCCESS != (status = perform_stl_pma_query (MMTHD_GET, STL_PM_ATTRIB_ID_ERROR_PORT_COUNTERS, attrmod, args, mad, sizeof(STL_ERROR_PORT_COUNTERS_REQ)))) { + fprintf(stderr, "%s: %s: %s\n", __func__, MSG_PMA_SEND_RECV_FAILURE, iba_fstatus_msg(status)); + return FALSE; + } else { + pStlErrorPortCountersRsp = (STL_ERROR_PORT_COUNTERS_RSP *)pStlErrorPortCountersReq; + BSWAP_STL_ERROR_PORT_COUNTERS_RSP(pStlErrorPortCountersRsp); + if (print) + PrintStlErrorPortCountersRsp(&g_dest, 0 /* indent */, pStlErrorPortCountersRsp); + return TRUE; + } +} + +static boolean stl_pma_get_ErrorInfo(argrec *args, uint8_t *pm, size_t pm_len, boolean print) +{ + STL_PERF_MAD *mad = (STL_PERF_MAD*)pm; + uint32 attrmod; + uint32 portCount = 0; + FSTATUS status = FSUCCESS; + + STL_ERROR_INFO_REQ *pStlErrorInfoReq = (STL_ERROR_INFO_REQ *)&(mad->PerfData); + MemoryClear(mad, sizeof(*mad)); + + getStlPortSelectMask(pStlErrorInfoReq->PortSelectMask, args); + pStlErrorInfoReq->ErrorInfoSelectMask.AsReg32 = g_counterSelectMask; + portCount = getNumPortsFromSelMask(pStlErrorInfoReq->PortSelectMask); + attrmod = portCount << 24; + + if (portCount == 0) + return FALSE; + + BSWAP_STL_ERROR_INFO_REQ(pStlErrorInfoReq); + + if ( FSUCCESS != (status = perform_stl_pma_query (MMTHD_GET, STL_PM_ATTRIB_ID_ERROR_INFO, attrmod, args, mad, sizeof(STL_ERROR_INFO_REQ)))) { + fprintf(stderr, "%s: %s: %s\n", __func__, MSG_PMA_SEND_RECV_FAILURE, iba_fstatus_msg(status)); + return FALSE; + } else { + BSWAP_STL_ERROR_INFO_RSP((STL_ERROR_INFO_RSP*)pStlErrorInfoReq); + if (print) + PrintStlErrorInfoRsp(&g_dest, 0 /* indent */, + (STL_ERROR_INFO_RSP*)pStlErrorInfoReq, 0); + return TRUE; + } +} + +static boolean stl_pma_clear_ErrorInfo(argrec *args, uint8_t *pm, size_t pm_len, boolean print) +{ + STL_PERF_MAD *mad = (STL_PERF_MAD*)pm; + uint32 attrmod; + uint32 portCount = 0; + FSTATUS status = FSUCCESS; + + STL_ERROR_INFO_REQ *pStlErrorInfoReq = (STL_ERROR_INFO_REQ *)&(mad->PerfData); + MemoryClear(mad, sizeof(*mad)); + + getStlPortSelectMask(pStlErrorInfoReq->PortSelectMask, args); + pStlErrorInfoReq->ErrorInfoSelectMask.AsReg32 = g_counterSelectMask; + portCount = getNumPortsFromSelMask(pStlErrorInfoReq->PortSelectMask); + attrmod = portCount << 24; + + if (portCount == 0) + return FALSE; + + BSWAP_STL_ERROR_INFO_REQ(pStlErrorInfoReq); + + if ( FSUCCESS != (status = perform_stl_pma_query (MMTHD_SET, STL_PM_ATTRIB_ID_ERROR_INFO, attrmod, args, mad, sizeof(STL_ERROR_INFO_REQ)))) { + fprintf(stderr, "%s: %s: %s\n", __func__, MSG_PMA_SEND_RECV_FAILURE, iba_fstatus_msg(status)); + return FALSE; + } else { + // Do not try to swap the ports + BSWAP_STL_ERROR_INFO_REQ(pStlErrorInfoReq); + if (print) + PrintStlErrorInfoRsp(&g_dest, 0 /* indent */, + (STL_ERROR_INFO_RSP*)pStlErrorInfoReq, 1); + return TRUE; + } +} + + +optypes_t stl_pma_query [] = { +//name func displayAbridged, description, Flags m, m2, f, b, i, t, c, n, l, e, w +{ "classportinfo", stl_pma_get_class_port_info, TRUE, "class of port info", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE}, +{ "getportstatus", stl_pma_get_PortStatus, TRUE, "list of port counters", TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, TRUE}, +{ "clearportstatus", stl_pma_clear_PortStatus, FALSE, "clears the port counters", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE}, +{ "getdatacounters", stl_pma_get_DataCounters, TRUE, "list of data counters", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, FALSE, TRUE}, +{ "geterrorcounters", stl_pma_get_ErrorCounters, TRUE, "list of error counters", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, FALSE, TRUE}, +{ "geterrorinfo", stl_pma_get_ErrorInfo, TRUE, "list of error info", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, FALSE, FALSE}, +{ "clearerrorinfo", stl_pma_clear_ErrorInfo, FALSE, "clears the error info", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, FALSE}, + + +{ NULL } +}; + +void pma_Usage(boolean displayAbridged) +{ + int i = 0; + + fprintf(stderr, "Usage: opapmaquery -o otype [standard options] [otype options]\n"); + fprintf(stderr, " or\n"); + fprintf(stderr, " opapmaquery --help\n"); + fprintf(stderr, " --help - produce full help text\n\n"); + + fprintf(stderr, "Standard Options: [-v] [-s sl] [-l lid] [-h hfi] [-p port]\n"); + fprintf(stderr, " -o otype Output type. See below for list.\n"); + fprintf(stderr, " -v Verbose output. Can be specified more than once for\n"); + fprintf(stderr, " additional openib debugging and libibumad debugging.\n"); + fprintf(stderr, " -s Specify different Service Level (default is SM SL)\n"); + fprintf(stderr, " -l lid Destination lid, default is local port\n"); + fprintf(stderr, " -h hfi hfi, numbered 1..n, 0= -p port will be a\n"); + fprintf(stderr, " system wide port num (default is 0)\n"); + fprintf(stderr, " -p port port, numbered 1..n, 0=1st active (default\n"); + fprintf(stderr, " is 1st active)\n"); + fprintf(stderr, "\n"); + fprintf(stderr, "The -h and -p options permit a variety of selections:\n"); + fprintf(stderr, " -h 0 - 1st active port in system (this is the default)\n"); + fprintf(stderr, " -h 0 -p 0 - 1st active port in system\n"); + fprintf(stderr, " -h x - 1st active port on HFI x\n"); + fprintf(stderr, " -h x -p 0 - 1st active port on HFI x\n"); + fprintf(stderr, " -h 0 -p y - port y within system (irrespective of which ports are active)\n"); + fprintf(stderr, " -h x -p y - HFI x, port y\n"); + fprintf(stderr, "\n"); + fprintf(stderr, "otype options vary by report: [-m port] [-n mask] [-e mask] [-w mask]\n"); + fprintf(stderr, " -m port Port in destination device to query.\n"); + fprintf(stderr, " -n mask Port Mask, in hex, bits represent ports 63-0\n"); + fprintf(stderr, " (e.g. 0x2 for port 1, 0x6 for ports 1,2)\n"); + if(!displayAbridged) { + fprintf(stderr, " -e mask Counter/error Select Mask, select bit positions as shown below\n"); + fprintf(stderr, " 0 is least significant (rightmost)\n"); + fprintf(stderr, " default is all bits set (e.g. 0xffffffe0)\n"); + fprintf(stderr, " (for Counters): (for Error Info):\n"); + fprintf(stderr, " mask bit location \n"); + fprintf(stderr, " 0x80000000 31 Xmit Data Rcv Error Info\n"); + fprintf(stderr, " 0x40000000 30 Rcv Data Excessive Buffer Overrun\n"); + fprintf(stderr, " 0x20000000 29 Xmit Pkts Xmit Const Error Info\n"); + fprintf(stderr, " 0x10000000 28 Rcv Pkts Rcv Const Error Info\n"); + fprintf(stderr, " 0x08000000 27 Multicast Xmit Pkts Rcv Switch Relay Error Info\n"); + fprintf(stderr, " 0x04000000 26 Multicast Rcv Pkts Uncorrectable Error Info\n"); + fprintf(stderr, " 0x02000000 25 Xmit Wait FM Config Error Info\n"); + fprintf(stderr, " 0x01000000 24 Congestion Discards\n"); + fprintf(stderr, " 0x00800000 23 Rcv FECN\n"); + fprintf(stderr, " 0x00400000 22 Rcv BECN\n"); + fprintf(stderr, " 0x00200000 21 Xmit Time Cong.\n"); + fprintf(stderr, " 0x00100000 20 Xmit Time Wasted BW\n"); + fprintf(stderr, " 0x00080000 19 Xmit Time Wait Data\n"); + fprintf(stderr, " 0x00040000 18 Rcv Bubble\n"); + fprintf(stderr, " 0x00020000 17 Mark FECN\n"); + fprintf(stderr, " 0x00010000 16 Rcv Constraint Errors\n"); + fprintf(stderr, " 0x00008000 15 Rcv Switch Relay\n"); + fprintf(stderr, " 0x00004000 14 Xmit Discards\n"); + fprintf(stderr, " 0x00002000 13 Xmit Constraint Errors\n"); + fprintf(stderr, " 0x00001000 12 Rcv Rmt Phys. Errors\n"); + fprintf(stderr, " 0x00000800 11 Local Link Integrity\n"); + fprintf(stderr, " 0x00000400 10 Rcv Errors\n"); + fprintf(stderr, " 0x00000200 9 Exc. Buffer Overrun\n"); + fprintf(stderr, " 0x00000100 8 FM Config Errors\n"); + fprintf(stderr, " 0x00000080 7 Link Error Recovery\n"); + fprintf(stderr, " 0x00000040 6 Link Error Downed\n"); + fprintf(stderr, " 0x00000020 5 Uncorrectable Errors\n"); + } + fprintf(stderr, " -w mask Virtual Lane Select Mask, in hex, bits represent VL number 31-0\n"); + fprintf(stderr, " (e.g. 0x1 for VL 0, 0x3 for VL 0,1) default is none\n"); + fprintf(stderr, "\n"); + fprintf(stderr, "Possible output types (default is getportstatus):\n"); + fprintf(stderr, " %-17s: %-45s\n","Output Type","Description"); + fprintf(stderr, " : %-45s\n","Supported Options"); + fprintf(stderr, " %-17s: %-45s\n","----------------","-----------------------------------------"); + i = 0; + while (stl_pma_query[i].name != NULL) { + if ( (displayAbridged && stl_pma_query[i].displayWithAbridged) || (!displayAbridged) ) { + fprintf(stderr, " %-17s: %-45s\n",stl_pma_query[i].name,stl_pma_query[i].description); + + if ((stl_pma_query[i].mflag)||(stl_pma_query[i].mflag2)||(stl_pma_query[i].bflag)||(stl_pma_query[i].fflag) + ||(stl_pma_query[i].nflag)||(stl_pma_query[i].eflag)||(stl_pma_query[i].wflag)){ + fprintf(stderr, " %-17s:", " "); + if (stl_pma_query[i].mflag) fprintf(stderr, " [-m port]"); + if (stl_pma_query[i].mflag2) fprintf(stderr, " [-m port1,port2]"); + if (stl_pma_query[i].bflag) fprintf(stderr, " [-b block[,count]]"); + if (stl_pma_query[i].fflag) fprintf(stderr, " [-f flid]"); + if (stl_pma_query[i].nflag) fprintf(stderr, " [-n port mask]"); + if (stl_pma_query[i].eflag) fprintf(stderr, " [-e counter mask]"); + if (stl_pma_query[i].wflag) fprintf(stderr, " [-w vl mask]"); + fprintf(stderr, "\n"); + } + fprintf(stderr, "\n"); + } + i++; + } + fprintf(stderr, "\n"); + if (!displayAbridged) { + fprintf(stderr, "Basic Examples:\n"); + fprintf(stderr, "---------------\n"); + fprintf(stderr, "opapmaquery -o classportinfo\n"); + fprintf(stderr, "opapmaquery -o getportstatus # get data and error counts, local port\n"); + fprintf(stderr, "opapmaquery -o getdatacounters -n 0x2 # get data counts, local port 1\n"); + fprintf(stderr, "opapmaquery -o geterrorcounters -n 0x2 # get error counts, local port 1\n"); + fprintf(stderr, "opapmaquery -o clearportstatus -n 0x2 # clear all counters local port 1\n"); + fprintf(stderr, "opapmaquery -o geterrorinfo -n 0x2 # get error info for local port 1\n"); + fprintf(stderr, "opapmaquery -o clearerrorinfo -n 0x2 # clear all error info, local port 1\n"); + fprintf(stderr, "Additional examples:\n"); + fprintf(stderr, "--------------------\n"); + fprintf(stderr, "For device at lid 6, get data counters on ports 1-6, inclusive of VL 0 data\n"); + fprintf(stderr, " opapmaquery -o getdatacounters -l 6 -n 0x7e -w 0x1\n"); + fprintf(stderr, "For device at lid 6, on port 1, clear only error counters:\n"); + fprintf(stderr, " opapmaquery -o clearportstatus -l 6 -n 0x2 -e 0x1ffff\n"); + fprintf(stderr, "For device at lid 6, on ports 1, clear Uncorrectable Error Info\n"); + fprintf(stderr, " opapmaquery -o clearerrorinfo -l 6 -n 0x2 -e 0x04000000\n"); + } + exit(2); +} //Usage diff --git a/IbaTools/opasmaquery/sma.c b/IbaTools/opasmaquery/sma.c new file mode 100644 index 0000000..4672151 --- /dev/null +++ b/IbaTools/opasmaquery/sma.c @@ -0,0 +1,2334 @@ +/* BEGIN_ICS_COPYRIGHT7 **************************************** + +Copyright (c) 2015-2018, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT7 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ +#include "stl_mad_priv.h" +#include "stl_helper.h" +#include +#include "opasmaquery.h" + +#define MSG_SMP_SEND_RECV_FAILURE "failed SMP Send or Receive" + +static void set_route(argrec *args, SMP* smp) +{ + int i; + + DBGPRINT("-> set_route: dlid=0x%08x slid=0x%08x drpaths=%d\n", args->dlid,args->slid,args->drpaths); + + if (args->dlid && !args->drpaths) //lid routed only + { + DBGPRINT("set_route: LID ROUTED\n"); + smp->common.MgmtClass = MCLASS_SM_LID_ROUTED; + smp->common.u.NS.Status.AsReg16 = 0; + return; + } + + //Directed Route + + smp->common.MgmtClass = MCLASS_SM_DIRECTED_ROUTE; + smp->common.u.DR.s.D = 0; + smp->common.u.DR.s.Status = 0; + smp->common.u.DR.HopPointer = 0; + smp->common.u.DR.HopCount = args->drpaths; + + if (!args->dlid && !args->drpaths) //local + { + DBGPRINT("set_route: LOCAL\n"); + + smp->SmpExt.DirectedRoute.DrSLID = LID_PERMISSIVE; + smp->SmpExt.DirectedRoute.DrDLID = LID_PERMISSIVE; + return; + } + + for (i=1;i<=args->drpaths;i++) + { + smp->SmpExt.DirectedRoute.InitPath[i]= g_drpath[i]; + } + + if (!args->dlid && args->drpaths) //pure DR + { + DBGPRINT("set_route: PURE DR\n"); + smp->SmpExt.DirectedRoute.DrSLID = LID_PERMISSIVE; + smp->SmpExt.DirectedRoute.DrDLID = LID_PERMISSIVE; + return; + } + + if (args->dlid && args->drpaths) // LID then DR + { + DBGPRINT("set_route: LID then DR\n"); + smp->SmpExt.DirectedRoute.DrSLID = args->slid; + smp->SmpExt.DirectedRoute.DrDLID = LID_PERMISSIVE; + return; + } + +} //set_route + +static void stl_set_route(argrec *args, STL_SMP* smp) +{ + int i; + + DBGPRINT("-> stl_set_route: dlid=0x%08x slid=0x%08x drpaths=%d\n", args->dlid,args->slid,args->drpaths); + + if (args->dlid && !args->drpaths) //lid routed only + { + DBGPRINT("stl_set_route: LID ROUTED\n"); + smp->common.MgmtClass = MCLASS_SM_LID_ROUTED; + smp->common.u.NS.Status.AsReg16 = 0; + return; + } + + //Directed Route + + smp->common.MgmtClass = MCLASS_SM_DIRECTED_ROUTE; + smp->common.u.DR.s.D = 0; + smp->common.u.DR.s.Status = 0; + smp->common.u.DR.HopPointer = 0; + smp->common.u.DR.HopCount = args->drpaths; + + if (!args->dlid && !args->drpaths) //local + { + DBGPRINT("stl_set_route: LOCAL\n"); + + smp->SmpExt.DirectedRoute.DrSLID = STL_LID_PERMISSIVE; + smp->SmpExt.DirectedRoute.DrDLID = STL_LID_PERMISSIVE; + return; + } + + for (i=1;i<=args->drpaths;i++) + { + smp->SmpExt.DirectedRoute.InitPath[i]= g_drpath[i]; + } + + if (!args->dlid && args->drpaths) //pure DR + { + DBGPRINT("stl_set_route: PURE DR\n"); + smp->SmpExt.DirectedRoute.DrSLID = STL_LID_PERMISSIVE; + smp->SmpExt.DirectedRoute.DrDLID = STL_LID_PERMISSIVE; + return; + } + + if (args->dlid && args->drpaths) // LID then DR + { + DBGPRINT("stl_set_route: LID then DR\n"); + smp->SmpExt.DirectedRoute.DrSLID = args->slid; + smp->SmpExt.DirectedRoute.DrDLID = STL_LID_PERMISSIVE; + return; + } + +} //stl_set_route + + +static FSTATUS perform_sma_query(uint16 attrid, uint32 attrmod, argrec *args, SMP *smp) +{ + FSTATUS status; + MemoryClear(smp, sizeof(*smp)); + smp->common.BaseVersion = IB_BASE_VERSION; + smp->common.ClassVersion = IB_SM_CLASS_VERSION; + set_route(args, smp); + smp->common.mr.AsReg8 = 0; + smp->common.mr.s.Method = MMTHD_GET; + smp->common.AttributeID = attrid; + smp->common.AttributeModifier = attrmod; + smp->common.TransactionID = (++g_transactID); + + // Determine which pkey to use (full or limited) + // Attempt to use full at all times, otherwise, can + // use the limited for queries of the local port. + uint16_t pkey = omgt_get_mgmt_pkey(args->omgt_port, args->dlid, args->drpaths); + if (pkey==0) { + fprintf(stderr, "ERROR: Local port does not have management privileges\n"); + return (FPROTECTION); + } + + if (g_verbose) { + PrintFunc(&g_dest, "Sending SMP:\n"); + PrintSmpHeader(&g_dest, 2, smp); + PrintSeparator(&g_dest); + } + + BSWAP_SMP_HEADER(smp); + { + struct omgt_mad_addr addr = { + lid : args->dlid, + qpn : 0, + qkey : 0, + pkey : pkey + }; + size_t recv_size = sizeof(*smp); + status = omgt_send_recv_mad_no_alloc(args->omgt_port, (uint8_t *)smp, sizeof(*smp), &addr, + (uint8_t *)smp, &recv_size, RESP_WAIT_TIME, 0); + } + BSWAP_SMP_HEADER(smp); + if (status == FSUCCESS && g_verbose) { + PrintFunc(&g_dest, "Received SMP:\n"); + PrintSmpHeader(&g_dest, 2, smp); + PrintSeparator(&g_dest); + } + + if (FSUCCESS == status && smp->common.u.DR.s.Status != MAD_STATUS_SUCCESS) { + fprintf(stderr, "MAD returned with Bad Status: %s\n", + iba_mad_status_msg2(smp->common.u.DR.s.Status)); + return FERROR; + } + return status; +} //perform_sma_query + +static FSTATUS perform_stl_aggregate_query(argrec *args, STL_SMP *smp) +{ + FSTATUS status; + + // Determine which pkey to use (full or limited) + // Attempt to use full at all times, otherwise, can + // use the limited for queries of the local port. + uint16_t pkey = omgt_get_mgmt_pkey(args->omgt_port, args->dlid, args->drpaths); + if (pkey==0) { + fprintf(stderr, "ERROR: Local port does not have management privileges\n"); + return (FPROTECTION); + } + + struct omgt_mad_addr addr = { + lid : args->dlid, + qpn : 0, + qkey : 0, + pkey : pkey + }; + size_t recv_size; + + if (g_verbose) { + int i; + STL_AGGREGATE *aggr; + + aggr = STL_AGGREGATE_FIRST(smp); + + PrintFunc(&g_dest, "Sending STL AGGREGATE:\n"); + PrintStlSmpHeader(&g_dest, 2, smp); + for (i=0; icommon.AttributeModifier; i++) { + uint16 r = ntoh16(aggr->Result.AsReg16); + uint16 l = (r&0x7f) * 8; + PrintFunc(&g_dest, "%*sAttrID: 0x%04x\n", 4, "", + ntoh16(aggr->AttributeID)); + PrintFunc(&g_dest, "%*sResult: 0x%04x (RLen=%d)\n", 6, "", + ntoh16(aggr->Result.AsReg16), l); + PrintFunc(&g_dest, "%*sModifier: 0x%08x\n", 6, "", + ntoh32(aggr->AttributeModifier)); + PrintSeparator(&g_dest); + // Can't use STL_AGGREGATE_NEXT because we're in network byte order. + aggr = (STL_AGGREGATE*)((void*)aggr+l+sizeof(STL_AGGREGATE)); + } + PrintSeparator(&g_dest); + } + + + STL_BSWAP_SMP_HEADER(smp); + recv_size = sizeof(*smp); + status = omgt_send_recv_mad_no_alloc(args->omgt_port, (uint8_t *)smp, + sizeof(*smp), &addr, (uint8_t *)smp, &recv_size, RESP_WAIT_TIME, 0); + + STL_BSWAP_SMP_HEADER(smp); + if (status == FSUCCESS && g_verbose) { + PrintFunc(&g_dest, "Received STL SMP:\n"); + PrintStlSmpHeader(&g_dest, 2, smp); + PrintSeparator(&g_dest); + } + + + if (FSUCCESS == status && smp->common.u.DR.s.Status != MAD_STATUS_SUCCESS) { + fprintf(stderr, "Aggregate MAD returned with Bad Status: %s\n", + iba_mad_status_msg2(smp->common.u.DR.s.Status)); + return FERROR; + } + return status; +} //perform_stl_aggregate_query + + +static FSTATUS perform_stl_sma_query(uint16 attrid, uint32 attrmod, argrec *args, + STL_SMP *smp, size_t attr_len, uint8_t *req_data, size_t req_len) +{ + FSTATUS status; + int i; + MemoryClear(smp, sizeof(*smp)); + uint8 requestInitPath[64]; + MemoryClear(requestInitPath, sizeof(requestInitPath)); + + smp->common.BaseVersion = STL_BASE_VERSION; + smp->common.ClassVersion = STL_SM_CLASS_VERSION; + stl_set_route(args, smp); + smp->common.mr.AsReg8 = 0; + smp->common.mr.s.Method = MMTHD_GET; + smp->common.AttributeID = attrid; + smp->common.AttributeModifier = attrmod; + smp->common.TransactionID = (++g_transactID); + + if (req_data && req_len > 0) { + uint8_t *reqData = (uint8_t *)stl_get_smp_data((STL_SMP *)smp); + memcpy(reqData, req_data, req_len); + } + + if (smp->common.MgmtClass == MCLASS_SM_DIRECTED_ROUTE) { + memcpy(requestInitPath, smp->SmpExt.DirectedRoute.InitPath, sizeof(requestInitPath)); + } + + if (g_verbose) { + PrintFunc(&g_dest, "Sending STL SMP:\n"); + PrintStlSmpHeader(&g_dest, 2, smp); + PrintSeparator(&g_dest); + } + + uint8_t port_state; + (void)omgt_port_get_port_state(args->omgt_port, &port_state); + if (port_state == IB_PORT_DOWN && ((args->dlid && args->dlid != args->slid) || args->drpaths)) { + uint8_t port_num; + char hfi_name[IBV_SYSFS_NAME_MAX] = {0}; + (void)omgt_port_get_hfi_port_num(args->omgt_port, &port_num); + (void)omgt_port_get_hfi_name(args->omgt_port, hfi_name); + fprintf(stderr, "WARNING port (%s:%d) is not ACTIVE!\n", + hfi_name, port_num); + } + + // Determine which pkey to use (full or limited) + // Attempt to use full at all times, otherwise, can + // use the limited for queries of the local port. + uint16_t pkey = omgt_get_mgmt_pkey(args->omgt_port, args->dlid, args->drpaths); + if (pkey==0) { + fprintf(stderr, "ERROR: Local port does not have management privileges\n"); + return (FPROTECTION); + } + + attr_len += stl_get_smp_header_size(smp); + attr_len = ROUNDUP_TYPE(size_t, attr_len, 8); + STL_BSWAP_SMP_HEADER(smp); + { + struct omgt_mad_addr addr = { + lid : args->dlid, + qpn : 0, + qkey : 0, + pkey : pkey + }; + size_t recv_size = sizeof(*smp); + status = omgt_send_recv_mad_no_alloc(args->omgt_port, (uint8_t *)smp, attr_len, &addr, + (uint8_t *)smp, &recv_size, RESP_WAIT_TIME, 0); + } + STL_BSWAP_SMP_HEADER(smp); + if (status == FSUCCESS && g_verbose) { + PrintFunc(&g_dest, "Received STL SMP:\n"); + PrintStlSmpHeader(&g_dest, 2, smp); + PrintSeparator(&g_dest); + } + + if (smp->common.MgmtClass == MCLASS_SM_DIRECTED_ROUTE && memcmp(requestInitPath, smp->SmpExt.DirectedRoute.InitPath, sizeof(requestInitPath)) != 0) { + fprintf(stderr, "Response failed directed route validation, received packet with path: "); + for(i = 1; i < 64; i++) { + if(smp->SmpExt.DirectedRoute.InitPath[i] != 0) { + fprintf(stderr, "%d ", smp->SmpExt.DirectedRoute.InitPath[i]); + } else { + break; + } + } + fprintf(stderr, "\n"); + + status = FERROR; + } + + if (FSUCCESS == status && smp->common.u.DR.s.Status != MAD_STATUS_SUCCESS) { + fprintf(stderr, "MAD returned with Bad Status: %s\n", + iba_mad_status_msg2(smp->common.u.DR.s.Status)); + return FERROR; + } + return status; +} //perform_stl_sma_query + +/* + * Initializes an SMP as an aggregate SMP. Returns offset of the first member. + * argrecs standard opasmaquery arguments (for building the route) + * smp pointer to an SMP structure (or a 2k buffer...) + * + * NOTE: SMP is in HOST byte order. + */ +static uint32 init_stl_aggregate_query(argrec *args, STL_SMP *smp) +{ + uint32 len = 0; + + MemoryClear(smp, sizeof(STL_SMP)); + + smp->common.BaseVersion = STL_BASE_VERSION; + smp->common.ClassVersion = STL_SM_CLASS_VERSION; + stl_set_route(args, smp); + smp->common.mr.AsReg8 = 0; + smp->common.mr.s.Method = MMTHD_GET; + smp->common.AttributeID = STL_MCLASS_ATTRIB_ID_AGGREGATE; + smp->common.AttributeModifier = 0; + + if (g_verbose) { + PrintFunc(&g_dest, "Preparing STL Aggregate SMP:\n"); + PrintStlSmpHeader(&g_dest, 2, smp); + PrintSeparator(&g_dest); + } + + if (smp->common.MgmtClass == MCLASS_SM_LID_ROUTED) { + len = ((void*)&(smp->SmpExt.LIDRouted.SMPData)-(void*)smp); + } else { + len = ((void*)&(smp->SmpExt.DirectedRoute.SMPData)-(void*)smp); + } + + return len; +} + +/* + * Adds attribute attrid to the aggregate query, along with required padding. + * + * Returns new length of aggregate or zero if length would exceed the max + * size of the MAD. + * + * NOTE: AGGREGATE IS ADDED IN NETWORK BYTE ORDER. + * + */ +static uint32 add_stl_aggregate_member(STL_SMP *smp, uint16 attrid, + uint32 member_modifier, uint32 member_len) +{ + STL_AGGREGATE *member; + uint32 modifier; + uint32 offset; + uint32 i; + + DBGPRINT("-> add_stl_aggregate_member: smp = %p, attrid = 0x%04x, " + "modifier = %d, len = %d\n", smp, attrid, member_modifier, + member_len); + + // Offset of first member + if (smp->common.MgmtClass == MCLASS_SM_LID_ROUTED) { + member = (STL_AGGREGATE*)&(smp->SmpExt.LIDRouted.SMPData); + } else { + member = (STL_AGGREGATE*)&(smp->SmpExt.DirectedRoute.SMPData); + } + + // Find the end. Slow, but not critical for our purposes. + modifier = smp->common.AttributeModifier; + for (i=0; iResult.AsReg16)&0x7f; + offset = r*8; + member = (STL_AGGREGATE*)(((void*)member)+sizeof(STL_AGGREGATE)+offset); + } + + member_len = ROUNDUP(member_len,8); + + // Make sure we haven't run off the end. + ASSERT(((void*)member - (void*)smp) < (2048-member_len)); + + member->AttributeID = ntoh16(attrid); + member->Result.AsReg16 = 0; + + DBGPRINT("add_stl_aggregate_member: member_len = %d\n", member_len); + + member->AttributeID = ntoh16(attrid); + member->AttributeModifier = ntoh32(member_modifier); + member->Result.AsReg16 = ntoh16(member_len/8); + + // Updates the member count. + modifier++; + if (modifier > MAX_AGGREGATE_ATTRIBUTES) return 0; + smp->common.AttributeModifier = modifier; + + return member_len; +} + +static boolean get_node_aggr(argrec *args, uint8_t *mad, size_t mad_len, boolean print) +{ + FSTATUS status; + uint32 len; + STL_SMP *smp = (STL_SMP *)mad; + STL_AGGREGATE *aggr; + + if (mad_len < sizeof(STL_SMP)) + return FALSE; + + DBGPRINT("-->get_node_aggr\n"); + + len = init_stl_aggregate_query(args, smp); + if (len == 0 ) { + fprintf(stderr, "get_node_aggr: failed to initialize MAD.\n"); + return FALSE; + } + + len = add_stl_aggregate_member(smp, STL_MCLASS_ATTRIB_ID_NODE_INFO, + 0, sizeof(STL_NODE_INFO)); + if (len == 0 ) { + fprintf(stderr, "get_node_aggr: failed to add Node Info member.\n"); + return FALSE; + } + + len = add_stl_aggregate_member(smp, STL_MCLASS_ATTRIB_ID_NODE_DESCRIPTION, + 0, sizeof(STL_NODE_DESCRIPTION)); + if (len == 0 ) { + fprintf(stderr, "get_node_aggr: failed to add Node Desc member.\n"); + return FALSE; + } + + status = perform_stl_aggregate_query (args, smp); + if (status != FSUCCESS) { + fprintf(stderr, "%s: %s: %s\n", __func__, MSG_SMP_SEND_RECV_FAILURE, iba_fstatus_msg(status)); + return FALSE; + } + + if (smp->common.u.DR.s.Status != MAD_STATUS_SUCCESS) { + fprintf(stderr, "MAD returned with Bad Status: %s\n", + iba_mad_status_msg2(smp->common.u.DR.s.Status)); + } + + aggr = STL_AGGREGATE_FIRST(smp); + + BSWAP_STL_AGGREGATE_HEADER(aggr); + + if (aggr->Result.s.Error != 0) { + fprintf(stderr,"get_node_aggr: Node Info query failed.\n"); + } else if (print || g_verbose) { + STL_NODE_INFO *pNodeInfo = (STL_NODE_INFO *)(aggr->Data); + BSWAP_STL_NODE_INFO(pNodeInfo); + PrintStlNodeInfo(&g_dest, 0 /* indent */, pNodeInfo, args->printLineByLine); + } + + PrintSeparator(&g_dest); + + aggr = STL_AGGREGATE_NEXT(aggr); + + BSWAP_STL_AGGREGATE_HEADER(aggr); + + if (aggr->Result.s.Error != 0) { + fprintf(stderr,"get_node_aggr: Node Description query failed.\n"); + } else if (print || g_verbose) { + STL_NODE_DESCRIPTION *pNodeDesc = (STL_NODE_DESCRIPTION *)(aggr->Data); + BSWAP_STL_NODE_DESCRIPTION(pNodeDesc); + PrintStlNodeDesc(&g_dest, 0, pNodeDesc, args->printLineByLine); + } + return TRUE; +} //get_node_aggr + +static boolean get_switch_aggr(argrec *args, uint8_t *mad, size_t mad_len, boolean print) +{ + FSTATUS status; + uint32 len; + STL_SMP *smp = (STL_SMP *)mad; + STL_AGGREGATE *aggr = NULL; + + if (mad_len < sizeof(STL_SMP)) + return FALSE; + + DBGPRINT("-->get_node_aggr\n"); + + len = init_stl_aggregate_query(args, smp); + if (len == 0 ) { + fprintf(stderr, "get_node_aggr: failed to initialize MAD.\n"); + return FALSE; + } + + len = add_stl_aggregate_member(smp, STL_MCLASS_ATTRIB_ID_NODE_INFO, 0, sizeof(STL_NODE_INFO)); + if (len == 0 ) { + fprintf(stderr, "get_node_aggr: failed to add Node Info member.\n"); + return FALSE; + } + + len = add_stl_aggregate_member(smp, STL_MCLASS_ATTRIB_ID_SWITCH_INFO, 0, sizeof(STL_SWITCH_INFO)); + if (len == 0 ) { + fprintf(stderr, "get_node_aggr: failed to add Switch Info member.\n"); + return FALSE; + } + + status = perform_stl_aggregate_query (args, smp); + if (status != FSUCCESS) { + fprintf(stderr, "%s: %s: %s\n", __func__, MSG_SMP_SEND_RECV_FAILURE, iba_fstatus_msg(status)); + return FALSE; + } else { + if (g_verbose) { + PrintFunc(&g_dest, "Received STL Aggregate SMP:\n"); + PrintStlSmpHeader(&g_dest, 2, smp); + PrintSeparator(&g_dest); + } + } + + if (smp->common.u.DR.s.Status != MAD_STATUS_SUCCESS) { + fprintf(stderr, "MAD returned with Bad Status: %s\n", + iba_mad_status_msg2(smp->common.u.DR.s.Status)); + } + + BSWAP_STL_SMP_HEADER(smp); + + aggr = STL_AGGREGATE_FIRST(smp); + + BSWAP_STL_AGGREGATE_HEADER(aggr); + + if (aggr->Result.s.Error != 0) { + fprintf(stderr,"get_switch_aggr: Node Info query failed.\n"); + } else if (print || g_verbose) { + STL_NODE_INFO *pNodeInfo = (STL_NODE_INFO *)(aggr->Data); + BSWAP_STL_NODE_INFO(pNodeInfo); + PrintStlNodeInfo(&g_dest, 0 /* indent */, pNodeInfo, args->printLineByLine ); + } + + PrintSeparator(&g_dest); + + aggr = STL_AGGREGATE_NEXT(aggr); + + BSWAP_STL_AGGREGATE_HEADER(aggr); + + if (aggr->Result.s.Error != 0) { + fprintf(stderr,"get_switch_aggr: Switch Info query failed.\n"); + } else if (print || g_verbose) { + STL_SWITCH_INFO *pSwitchInfo = (STL_SWITCH_INFO *)(aggr->Data); + BSWAP_STL_SWITCH_INFO(pSwitchInfo); + PrintStlSwitchInfo(&g_dest, 0/*indent*/, pSwitchInfo, 0/*lid*/, args->printLineByLine ); + } + return TRUE; +} //get_switch_aggr + +static boolean get_node_desc(argrec *args, uint8_t *mad, size_t mad_len, boolean print) +{ + FSTATUS status; + STL_SMP *smp = (STL_SMP *)mad; + + if (mad_len < sizeof(STL_SMP)) + return FALSE; + + + DBGPRINT("-->get_node_desc"); + status = perform_stl_sma_query(STL_MCLASS_ATTRIB_ID_NODE_DESCRIPTION, + 0, args, smp, sizeof(STL_NODE_DESCRIPTION), NULL, 0); + + + if (status != FSUCCESS) { + fprintf(stderr, "%s: %s: %s\n", __func__, MSG_SMP_SEND_RECV_FAILURE, iba_fstatus_msg(status)); + return FALSE; + } else { + if (print || g_verbose) { + STL_NODE_DESCRIPTION *pNodeDesc = (STL_NODE_DESCRIPTION *)stl_get_smp_data(smp); + BSWAP_STL_NODE_DESCRIPTION(pNodeDesc); + PrintStlNodeDesc(&g_dest, 0, pNodeDesc, args->printLineByLine); + } + return TRUE; + } + +} //get_node_desc + +static boolean get_ib_node_info(argrec *args, uint8_t *mad, size_t mad_len, boolean print) +{ + FSTATUS status; + NODE_INFO *pNodeInfo; + SMP *smp = (SMP *)mad; + + if (mad_len < sizeof(SMP)) + return FALSE; + + pNodeInfo = (NODE_INFO *)&(smp->SmpExt.DirectedRoute.SMPData); + + DBGPRINT("-->get_ib_node_info\n"); + status = perform_sma_query (MCLASS_ATTRIB_ID_NODE_INFO, 0, args, smp); + BSWAP_NODE_INFO(pNodeInfo); + + if (status != FSUCCESS) { + fprintf(stderr, "%s: %s: %s\n", __func__, MSG_SMP_SEND_RECV_FAILURE, iba_fstatus_msg(status)); + return FALSE; + } else { + if (print || g_verbose) + PrintNodeInfo(&g_dest, 0 /* indent */, pNodeInfo); + return TRUE; + } +} //get_ib_node_info + +static boolean get_node_info(argrec *args, uint8_t *mad, size_t mad_len, boolean print) +{ + FSTATUS status; + STL_SMP *smp = (STL_SMP *)mad; + + if (mad_len < sizeof(STL_SMP)) + return FALSE; + + DBGPRINT("-->get_node_info\n"); + status = perform_stl_sma_query(STL_MCLASS_ATTRIB_ID_NODE_INFO, + 0, args, smp, sizeof(STL_NODE_INFO), NULL, 0); + + if (status != FSUCCESS) { + fprintf(stderr, "%s: %s: %s\n", __func__, MSG_SMP_SEND_RECV_FAILURE, iba_fstatus_msg(status)); + return FALSE; + } + + STL_NODE_INFO *pNodeInfo = (STL_NODE_INFO *)stl_get_smp_data(smp); + BSWAP_STL_NODE_INFO(pNodeInfo); + + if (print || g_verbose) { + PrintStlNodeInfo(&g_dest, 0 /* indent */, pNodeInfo, args->printLineByLine ); + } + return TRUE; +} //get_node_info + +static boolean get_port_info(argrec *args, uint8_t *mad, size_t mad_len, boolean print) +{ + FSTATUS status; + STL_SMP *smp = (STL_SMP *)mad; + STL_PORT_INFO *pPortInfo; + STL_NODE_INFO *pNodeInfo; + uint32_t amod = 0x01000000; + int i; + uint16_t firstPort = 0; + + if (!get_node_info(args, (uint8_t *)smp, sizeof(*smp), g_verbose)) { + fprintf(stderr, "%s failed: unable to get_node_info\n", __func__); + return FALSE; + } + pNodeInfo = (STL_NODE_INFO*)stl_get_smp_data(smp); + + if (args->mflag) { + if (pNodeInfo->NodeType == STL_NODE_SW) { + if ((args->dport + args->mcount - 1) > pNodeInfo->NumPorts) { + fprintf(stderr, "%s failed: specified port [%u-%u] invalid must be %u - %u for this SW\n", + __func__, args->dport, (args->dport + args->mcount - 1), 1, pNodeInfo->NumPorts); + return FALSE; + } + amod = (uint32_t)(args->mcount << 24); + amod |= (uint32_t)args->dport; + firstPort = args->dport; + } else if (strcmp(args->oname, "portinfo") == 0) + fprintf(stderr, "%s: -m ignored for port_info against an HFI\n", g_cmdname); + } + if (pNodeInfo->NodeType == STL_NODE_FI) + firstPort = pNodeInfo->u1.s.LocalPortNum; + + + DBGPRINT("---->get_port_info\n"); + DBGPRINT("->dlid=0x%08x slid=0x%08x dport=%d,%d drpaths=%d\n", + args->dlid,args->slid,args->dport,args->mcount,args->drpaths); + + // Get PortInfo using attrmod + status = perform_stl_sma_query(STL_MCLASS_ATTRIB_ID_PORT_INFO, + amod, args, smp, sizeof(*pPortInfo), NULL, 0); + + if (status != FSUCCESS) { + fprintf(stderr, "%s: %s: %s\n", __func__, MSG_SMP_SEND_RECV_FAILURE, iba_fstatus_msg(status)); + return FALSE; + } + + pPortInfo = (STL_PORT_INFO *)stl_get_smp_data(smp); + for (i = 0; i < ((amod>>24)&0xFF); i++) { + BSWAP_STL_PORT_INFO(pPortInfo); + if (print) { + PrintFunc(&g_dest, "%*sPort %u Info\n", 0, "", firstPort + i); + PrintStlPortInfo(&g_dest, 3, pPortInfo, 0 /*portGuid*/, args->printLineByLine); + } + pPortInfo = (STL_PORT_INFO *)((size_t)(pPortInfo) + ROUNDUPP2(sizeof(STL_PORT_INFO), 8)); + } + + return TRUE; +} //get_port_info + +static boolean get_led_info(argrec *args, uint8_t *mad, size_t mad_len, boolean print) +{ + FSTATUS status; + STL_SMP *smp = (STL_SMP *)mad; + STL_LED_INFO *pLedInfo; + STL_NODE_INFO *pNodeInfo; + uint32_t amod = 0x01000000; + + if (!get_node_info(args, (uint8_t *)smp, sizeof(*smp), g_verbose)) { + fprintf(stderr, "%s failed: unable to get_node_info\n", __func__); + return FALSE; + } + pNodeInfo = (STL_NODE_INFO*)stl_get_smp_data(smp); + + if (args->mflag) { + if (pNodeInfo->NodeType == STL_NODE_FI) + fprintf(stderr, "%s: -m ignored for led_info against an HFI\n", g_cmdname); + else + amod |= (uint32_t)args->dport; + } + + DBGPRINT("---->get_led_info\n"); + DBGPRINT("->dlid=0x%08x slid=0x%08x dport=%d drpaths=%d\n", + args->dlid,args->slid,args->dport,args->drpaths); + + status = perform_stl_sma_query(STL_MCLASS_ATTRIB_ID_LED_INFO, + amod, args, smp, sizeof(*pLedInfo), NULL, 0); + + if (status != FSUCCESS) { + fprintf(stderr, "%s: %s: %s\n", __func__, MSG_SMP_SEND_RECV_FAILURE, iba_fstatus_msg(status)); + return FALSE; + } + + pLedInfo = (STL_LED_INFO *)stl_get_smp_data(smp); + BSWAP_STL_LED_INFO(pLedInfo); + + if (print) + PrintStlLedInfo(&g_dest, 0/*indent*/, pLedInfo, 0/*portGuid*/, args->printLineByLine); + + return TRUE; +} //get_led_info + + +static boolean get_pstate_info(argrec *args, uint8_t *mad, size_t mad_len, boolean print) +{ + FSTATUS status; + uint8 startPort = args->inport; + uint8 endPort = args->outport; + STL_SMP *smp = (STL_SMP *)mad; + uint32_t amod; + uint8_t count; + uint16_t firstPort; + + if (mad_len < sizeof(SMP)) + return FALSE; + + if (args->mflag && !args->mflag2) + startPort = endPort = args->dport; + + DBGPRINT("---->get_pstate_info\n"); + { + uint8 maxPort; + uint8 nodetype; + STL_NODE_INFO *pNodeInfo; + + if (!get_node_info(args, (uint8_t *)smp, sizeof(*smp), g_verbose)) { + fprintf(stderr, "get_pstate_info failed: unable to get_node_info\n"); + return FALSE; + } + pNodeInfo = (STL_NODE_INFO *)stl_get_smp_data(smp); + + nodetype = pNodeInfo->NodeType; + maxPort = pNodeInfo->NumPorts; + + if (nodetype == STL_NODE_FI) { + if (args->mflag) + fprintf(stderr, "%s: -m ignored for pstateinfo against an HFI\n", g_cmdname); + startPort = endPort = 0; + firstPort = pNodeInfo->u1.s.LocalPortNum; + } else { + if (startPort > endPort) { + fprintf(stderr, "%s failed: start port > end port!\n", __func__); + return FALSE; + } + if (endPort > maxPort) { + fprintf(stderr, "%s failed: request exceeds " + "port count: %d max ports\n", __func__, maxPort); + return FALSE; + } + + if (startPort == 0 && endPort == 0 && !args->mflag2 && !args->mflag) { + startPort = 0; + endPort = maxPort; + } + firstPort = startPort; + } + } + + count = endPort - startPort + 1; + amod = (count<<24) | startPort; + STL_PORT_STATE_INFO *psip; + status = perform_stl_sma_query(STL_MCLASS_ATTRIB_ID_PORT_STATE_INFO, + amod, args, smp, sizeof(STL_PORT_STATE_INFO)*count, NULL, 0); + if (status != FSUCCESS) { + fprintf(stderr, "%s: %s: %s\n", __func__, MSG_SMP_SEND_RECV_FAILURE, iba_fstatus_msg(status)); + return FALSE; + } + + psip = (STL_PORT_STATE_INFO *)stl_get_smp_data(smp); + BSWAP_STL_PORT_STATE_INFO(psip, count); + if (print) + PrintStlPortStateInfo(&g_dest, 0, psip, count, firstPort, args->printLineByLine); + + return TRUE; +} //get_pstate_info + + +static boolean get_sm_info(argrec *args, uint8_t *mad, size_t mad_len, boolean print) +{ + FSTATUS status; + STL_SMP *smp = (STL_SMP *)mad; + STL_SM_INFO *pSmInfo; + + if (mad_len < sizeof(STL_SMP)) + return FALSE; + + DBGPRINT("-->get_sm_info\n"); + + status = perform_stl_sma_query (STL_MCLASS_ATTRIB_ID_SM_INFO, + 0, args, smp, sizeof(*pSmInfo), NULL, 0); + + pSmInfo = (STL_SM_INFO *)stl_get_smp_data(smp); + BSWAP_STL_SM_INFO(pSmInfo); + + if (status != FSUCCESS) { + fprintf(stderr, "%s: %s: %s\n", __func__, MSG_SMP_SEND_RECV_FAILURE, iba_fstatus_msg(status)); + return FALSE; + } else { + if (print) + PrintStlSMInfo(&g_dest, 0/*indent*/, pSmInfo, 0/*lid*/, args->printLineByLine); + return TRUE; + } +}//get_sm_info + +static boolean get_sw_info(argrec *args, uint8_t *mad, size_t mad_len, boolean print) +{ + FSTATUS status; + STL_SMP *smp = (STL_SMP *)mad; + + if (mad_len < sizeof(STL_SMP)) + return FALSE; + + DBGPRINT("-->get_sw_info\n"); + { + STL_NODE_INFO *pNodeInfo; + + if (!get_node_info(args, (uint8_t *)smp, sizeof(*smp), g_verbose)) { + fprintf(stderr, "get_sw_info failed: unable to get_node_info\n"); + return FALSE; + } + pNodeInfo = (STL_NODE_INFO *)stl_get_smp_data(smp); + if (pNodeInfo->NodeType != STL_NODE_SW) { + fprintf(stderr, "get_sw_info failed: node is not a switch\n"); + return FALSE; + } + } + + status = perform_stl_sma_query (STL_MCLASS_ATTRIB_ID_SWITCH_INFO, + 0, args, smp, sizeof(STL_SWITCH_INFO), NULL, 0); + if (status != FSUCCESS) { + fprintf(stderr, "%s: %s: %s\n", __func__, MSG_SMP_SEND_RECV_FAILURE, iba_fstatus_msg(status)); + return FALSE; + } else { + STL_SWITCH_INFO *pSwitchInfo = (STL_SWITCH_INFO *)stl_get_smp_data(smp); + BSWAP_STL_SWITCH_INFO(pSwitchInfo); + + if (print) + PrintStlSwitchInfo(&g_dest, 0/*indent*/, pSwitchInfo, 0/*lid*/, args->printLineByLine ); + return TRUE; + } +} //get_sw_info + +static boolean get_slsc_map(argrec *args, uint8_t *mad, size_t mad_len, boolean print) +{ + FSTATUS status = FSUCCESS; + STL_SMP *smp = (STL_SMP *)mad; + + if (mad_len < sizeof(STL_SMP)) + return FALSE; + + DBGPRINT("---->get_slsc_map\n"); + + STL_SLSCMAP *pSLSCMap; + status = perform_stl_sma_query(STL_MCLASS_ATTRIB_ID_SL_SC_MAPPING_TABLE, + 0, args, smp, sizeof(*pSLSCMap), NULL, 0); + pSLSCMap = (STL_SLSCMAP *)stl_get_smp_data(smp); + BSWAP_STL_SLSCMAP(pSLSCMap); + if (status != FSUCCESS) + goto done; + if (print || g_verbose) + PrintStlSLSCMapSmp(&g_dest, 0 /* indent */, smp, args->printLineByLine); + +done: + if (status != FSUCCESS) { + fprintf(stderr, "get_slsc_map failed: error obtaining scsl\n"); + return FALSE; + } else { + return TRUE; + } +} //get_slsc_map + +static boolean get_scsc_map(argrec *args, uint8_t *mad, size_t mad_len, boolean print) +{ + FSTATUS status = FSUCCESS; + STL_SMP *smp = (STL_SMP *)mad; + NODE_TYPE nodetype; + int i, extended = 0; + uint8 maxPort; + uint8 inport, startInPort, endInPort; + uint8 outport, startOutPort, endOutPort; + + if (mad_len < sizeof(STL_SMP)) + return FALSE; + + + DBGPRINT("---->get_scsc_map\n"); + + { + STL_NODE_INFO *pNodeInfo; + if (!get_node_info(args, (uint8_t *)smp, sizeof(*smp), g_verbose)) + return FALSE; + + pNodeInfo = (STL_NODE_INFO *)stl_get_smp_data(smp); + nodetype = pNodeInfo->NodeType; + maxPort = pNodeInfo->NumPorts; + } + if (nodetype != STL_NODE_SW) { + fprintf(stderr, "get_scsc_map failed: node is not a switch\n"); + return FALSE; + } + + + uint8 firstPort = 1; + if (args->mflag && !args->mflag2) { + // Get the set of tables for [inport, *] + if (args->dport > maxPort || args->dport < firstPort) { + fprintf(stderr, "get_scsc_map failed: specified port %u invalid must be %u - %u for this SW\n", + args->dport, firstPort, maxPort); + return FALSE; + } + startInPort = endInPort = args->dport; + startOutPort = firstPort; + endOutPort = maxPort; + } else if (args->mflag2) { + // Get the set of tables for the single pair [inport, outport] + if (args->inport > maxPort || args->inport < firstPort) { + fprintf(stderr, "get_scsc_map failed: specified port %u invalid must be %u - %u for this SW\n", + args->inport, firstPort, maxPort); + return FALSE; + } + if (args->outport > maxPort || args->outport < firstPort) { + fprintf(stderr, "get_scsc_map failed: specified port %u invalid must be %u - %u for this SW\n", + args->outport, firstPort, maxPort); + return FALSE; + } + startInPort = endInPort = args->inport; + startOutPort = endOutPort = args->outport; + } else { + // Get the tables for all possible pairs of ports. + startInPort=startOutPort = firstPort; + endInPort = endOutPort = maxPort; + } + + for (i=0; i<=extended; i++) { + for (inport = startInPort; inport <= endInPort; inport++) { + /** + * Technically we could fit 4 more blocks (ports) in a LID + * routed SMP. But it is not worth it in this tool. + */ + for (outport = startOutPort; outport <= endOutPort; outport += STL_NUM_SCSC_BLOCKS_PER_DRSMP) { + STL_SCSCMAP *pSCSCMap; + uint16_t numBlocks = 1; + uint32_t attrmod = 0; + + numBlocks = MIN(STL_NUM_SCSC_BLOCKS_PER_DRSMP, (endOutPort - outport)+1); + attrmod = (numBlocks << 24) | (i << 20) | (inport << 8) | outport; + + status = perform_stl_sma_query (STL_MCLASS_ATTRIB_ID_SC_SC_MAPPING_TABLE, + attrmod, args, smp, sizeof(*pSCSCMap)*numBlocks, NULL, 0); + pSCSCMap = (STL_SCSCMAP *)stl_get_smp_data(smp); + BSWAP_STL_SCSCMAP(pSCSCMap); + if (status != FSUCCESS) + goto done; + if (print || g_verbose) + PrintStlSCSCMapSmp(&g_dest, 0 /* indent */, smp, + (inport==startInPort && outport==startOutPort), args->printLineByLine); + } + } + } +done: + if (status != FSUCCESS) { + fprintf(stderr, "get_scsc_map failed: error obtaining scsc\n"); + return FALSE; + } else { + return TRUE; + } +} //get_scsc_map + +static boolean get_scsl_map(argrec *args, uint8_t *mad, size_t mad_len, boolean print) +{ + FSTATUS status = FSUCCESS; + STL_SMP *smp = (STL_SMP *)mad; + + if (mad_len < sizeof(STL_SMP)) + return FALSE; + + DBGPRINT("---->get_scsl_map\n"); + + STL_SCSLMAP *pSCSLMap; + status = perform_stl_sma_query(STL_MCLASS_ATTRIB_ID_SC_SL_MAPPING_TABLE, + 0, args, smp, sizeof(*pSCSLMap), NULL, 0); + pSCSLMap = (STL_SCSLMAP *)stl_get_smp_data(smp); + BSWAP_STL_SCSLMAP(pSCSLMap); + if (status != FSUCCESS) + goto done; + if (print || g_verbose) + PrintStlSCSLMapSmp(&g_dest, 0 /* indent */, smp, args->printLineByLine); + +done: + if (status != FSUCCESS) { + fprintf(stderr, "get_scsl_map failed: error obtaining scsl\n"); + return FALSE; + } else { + return TRUE; + } +} //get_scsl_map + +/** ========================================================================= + * Generic scvlx call + * attribute defines which table is queried. + */ +static boolean get_scvlx_map(argrec *args, uint8_t *mad, size_t mad_len, + boolean print, uint16_t attribute) +{ + FSTATUS status = FSUCCESS; + STL_SMP *smp = (STL_SMP *)mad; + NODE_TYPE nodetype; + STL_NODE_INFO *pNodeInfo; + uint8 maxPort; + uint16 port = 0; + uint8 startPort = 0; + uint8 endPort = 0; + + if (mad_len < sizeof(STL_SMP)) + return FALSE; + + + DBGPRINT("---->get_scvlx_map\n"); + + { + if (!get_node_info(args, (uint8_t *)smp, sizeof(*smp), g_verbose)) + return FALSE; + + pNodeInfo = (STL_NODE_INFO *)stl_get_smp_data(smp); + nodetype = pNodeInfo->NodeType; + maxPort = pNodeInfo->NumPorts; + } + if (nodetype == STL_NODE_SW) { + uint8 firstPort = (attribute == STL_MCLASS_ATTRIB_ID_SC_VLNT_MAPPING_TABLE)? 1 : 0; + if (args->mflag2) { + if (args->inport > maxPort || args->inport < firstPort) { + fprintf(stderr, "get_scvlx_map failed: specified port %u invalid must be %u - %u for this SW\n", + args->inport, firstPort, maxPort); + return FALSE; + } + if (args->outport > maxPort || args->outport < firstPort) { + fprintf(stderr, "get_scvlx_map failed: specified port %u invalid must be %u - %u for this SW\n", + args->outport, firstPort, maxPort); + return FALSE; + } + startPort = args->inport; + endPort = args->outport; + } else if (args->mflag) { + if (args->dport > maxPort || args->dport < firstPort) { + fprintf(stderr, "get_scvlx_map failed: specified port %u invalid must be %u - %u for this SW\n", + args->dport, firstPort, maxPort); + return FALSE; + } + startPort = args->dport; + endPort = args->dport; + } else { + startPort = firstPort; + endPort = maxPort; + } + } else { + startPort = endPort = 0; + if (args->mflag) + fprintf(stderr, "%s: -m ignored for SCVLx against an HFI\n", g_cmdname); + } + + /** + * Technically we could fit 4 more blocks (ports) in a LID routed SMP. + * But it is not worth it in this tool. + */ + for (port = startPort; port <= endPort; port += STL_NUM_SCVL_BLOCKS_PER_DRSMP) { + STL_SCVLMAP *pSCVLMap; + uint16_t numBlocks = MIN(STL_NUM_SCVL_BLOCKS_PER_DRSMP, (endPort - port)+1); + uint32_t attrmod = (numBlocks << 24) | port; + + status = perform_stl_sma_query(attribute, attrmod, args, + smp, sizeof(*pSCVLMap)*numBlocks, NULL, 0); + pSCVLMap = (STL_SCVLMAP *)stl_get_smp_data(smp); + BSWAP_STL_SCVLMAP(pSCVLMap); + if (status != FSUCCESS) + goto done; + if (print || g_verbose) + PrintStlSCVLxMapSmp(&g_dest, 0 /* indent */, smp, nodetype, (port==startPort), args->printLineByLine); + } +done: + if (status != FSUCCESS) { + fprintf(stderr, "get_scvlx_map failed: error obtaining scvlx\n"); + return FALSE; + } else { + return TRUE; + } +} //get_scvlx_map + +static boolean get_scvlt_map(argrec *args, uint8_t *mad, size_t mad_len, boolean print) { + boolean rc = get_scvlx_map(args, mad, mad_len, print, STL_MCLASS_ATTRIB_ID_SC_VLT_MAPPING_TABLE); + if (!rc) { + fprintf(stderr, "get_scvlt_map failed\n"); + } + return (rc); +} //get_scvlt_map + +static boolean get_scvlnt_map(argrec *args, uint8_t *mad, size_t mad_len, boolean print) { + boolean rc = get_scvlx_map(args, mad, mad_len, print, STL_MCLASS_ATTRIB_ID_SC_VLNT_MAPPING_TABLE); + if (!rc) { + fprintf(stderr, "get_scvlnt_map failed\n"); + } + return (rc); +} //get_scvlnt_map + +static boolean get_scvlr_map(argrec *args, uint8_t *mad, size_t mad_len, boolean print) { + boolean rc = get_scvlx_map(args, mad, mad_len, print, STL_MCLASS_ATTRIB_ID_SC_VLR_MAPPING_TABLE); + if (!rc) { + fprintf(stderr, "get_scvlr_map failed\n"); + } + return (rc); +} //get_scvlr_map + +static boolean print_vlarb_element(argrec *args, STL_SMP *smp, uint8_t startPort, + uint8_t endPort, uint8_t section, + uint8_t nodeType) +{ + int indent = 0; + uint16_t port; + FSTATUS status; + + /** + * Technically we could fit more blocks (ports) in a LID routed SMP. + * But it is not worth it in this tool. + */ + for (port=startPort; port <= endPort; port += STL_NUM_VLARB_PORTS_PER_DRSMP) { + uint8_t numPorts = MIN(STL_NUM_VLARB_PORTS_PER_DRSMP, endPort - port + 1); + uint32_t attrmod = (numPorts << 24) | (section << 16) | port; + status = perform_stl_sma_query(STL_MCLASS_ATTRIB_ID_VL_ARBITRATION, + attrmod, args, smp, sizeof(STL_VLARB_TABLE)*numPorts, NULL, 0); + if (status != FSUCCESS) { + fprintf(stderr, "%s: %s: %s\n", "get_vlarb", MSG_SMP_SEND_RECV_FAILURE, iba_fstatus_msg(status)); + return status; + } + + PrintStlVLArbTableSmp(&g_dest, indent, smp, nodeType, args->printLineByLine); + } + return FSUCCESS; +} + +static boolean get_vlarb(argrec *args, uint8_t *mad, size_t mad_len, boolean print) +{ + FSTATUS status; + uint8 vlCap; + uint8 startPort = 1, endPort = 1; + NODE_TYPE nodeType; + STL_SMP *smp = (STL_SMP *)mad; + STL_NODE_INFO *pNodeInfo; + STL_PORT_INFO *pPortInfo; + STL_SWITCH_INFO *pSwitchInfo; + uint8_t numPorts; + int vlarb = 1; + + if (mad_len < sizeof(SMP)) + return FALSE; + + DBGPRINT("-->get_vlarb\n"); + + if (!get_node_info(args, (uint8_t *)smp, sizeof(*smp), g_verbose)) + return FALSE; + + pNodeInfo = (STL_NODE_INFO *)stl_get_smp_data(smp); + nodeType = pNodeInfo->NodeType; + numPorts = pNodeInfo->NumPorts; + + if (nodeType == STL_NODE_SW) { + argrec argsCpy = *args; + argsCpy.mflag = 1; + argsCpy.dport = 0; + argsCpy.mcount = 1; + + if (!get_port_info(&argsCpy, (uint8_t *)smp, sizeof(*smp), g_verbose)) + return FALSE; + + pPortInfo = (STL_PORT_INFO *)stl_get_smp_data(smp); + vlarb = pPortInfo->CapabilityMask3.s.VLSchedulingConfig == STL_VL_SCHED_MODE_VLARB; + } + + if (!get_port_info(args, (uint8_t *)smp, sizeof(*smp), g_verbose)) + return FALSE; + + pPortInfo = (STL_PORT_INFO *)stl_get_smp_data(smp); + DBGPRINT("get_vlarb: dlid 0x%08x dport %d has VLCap=%d\n", + pPortInfo->LID, args->dport, pPortInfo->VL.s2.Cap); + + vlCap = pPortInfo->VL.s2.Cap; + + if (args->mflag && vlCap == 1) { + fprintf(stderr, "get_vlarb failed: no vlarbtable as this port only has 1 vl; VL0\n"); + return FALSE; + } + + if (nodeType != STL_NODE_SW) + vlarb = pPortInfo->CapabilityMask3.s.VLSchedulingConfig == STL_VL_SCHED_MODE_VLARB; + + if (!vlarb) { + fprintf(stderr, "get_vlarb failed: vlarbtable not supported\n"); + return FALSE; + } + + if (nodeType == STL_NODE_SW) { + if (!get_sw_info(args,(uint8_t *)smp, sizeof(*smp), g_verbose)) + return FALSE; + + pSwitchInfo = (STL_SWITCH_INFO *)stl_get_smp_data(smp); + if ((pSwitchInfo->u2.s.EnhancedPort0 == 1) && (vlCap > 1)) + startPort = 0; + + endPort = numPorts; + } + + if (args->mflag) { + if (nodeType == STL_NODE_SW) { + if (args->dport > endPort) { + fprintf(stderr, "get_vlarb failed: port number is higher than switch's number of ports\n"); + return FALSE; + } + startPort = endPort = args->dport; + } else + fprintf(stderr, "%s: -m ignored for vlarb against an HFI\n", g_cmdname); + } + + status = print_vlarb_element(args, smp, startPort, endPort, STL_VLARB_LOW_ELEMENTS, nodeType); + if (status != FSUCCESS) + return status; + + status = print_vlarb_element(args, smp, startPort, endPort, STL_VLARB_HIGH_ELEMENTS, nodeType); + if (status != FSUCCESS) + return status; + + status = print_vlarb_element(args, smp, startPort, endPort, STL_VLARB_PREEMPT_ELEMENTS, nodeType); + if (status != FSUCCESS) + return status; + + status = print_vlarb_element(args, smp, startPort, endPort, STL_VLARB_PREEMPT_MATRIX, nodeType); + if (status != FSUCCESS) + return status; + + return TRUE; +} //get_vlarb + + +static boolean get_pkey(argrec *args, uint8_t *mad, size_t mad_len, boolean print) +{ + FSTATUS status = FSUCCESS; + STL_SMP *smp = (STL_SMP *)mad; + uint8 nodetype; + uint16 cap; + uint16 block, startBlock, endBlock; + uint8 port; + + if (mad_len < sizeof(STL_SMP)) + return FALSE; + + DBGPRINT("---->get_pkey\n"); + + { + STL_NODE_INFO *pNodeInfo; + + if (!get_node_info(args, (uint8_t *)smp, sizeof(*smp), g_verbose)) + return FALSE; + + pNodeInfo = (STL_NODE_INFO *)stl_get_smp_data(smp); + nodetype = pNodeInfo->NodeType; + cap = pNodeInfo->PartitionCap; + } + if (nodetype == STL_NODE_SW) { + STL_SWITCH_INFO *pSwInfo; + if (args->dport) { + if (!get_sw_info(args, (uint8_t *)smp, sizeof(*smp), g_verbose)) + return FALSE; + pSwInfo = (STL_SWITCH_INFO *)stl_get_smp_data(smp); + cap = pSwInfo->PartitionEnforcementCap; + } + port = args->dport; + } else { + if (args->mflag) + fprintf(stderr, "%s: -m ignored for pkey against an HFI\n", g_cmdname); + port = 0; + } + + if (args->bflag) { + if (args->block > MAX_PKEY_BLOCK_NUM) { + fprintf(stderr, "get_pkey failed: block specified: %u must be 0 - %u\n", args->block, + MAX_PKEY_BLOCK_NUM); + return FALSE; + } + if (args->block > (cap-1)/ NUM_PKEY_ELEMENTS_BLOCK) { + fprintf(stderr, "get_pkey failed: specified block %u exceeds cap: cap=%u\n", + args->block, cap); + return FALSE; + } + startBlock = args->block; + endBlock = startBlock + args->bcount - 1; + } else { + startBlock=0; + endBlock = ((cap-1) / NUM_PKEY_ELEMENTS_BLOCK); + } + + for (block = startBlock; block <= endBlock; block += STL_NUM_PKEY_BLOCKS_PER_DRSMP) { + uint16_t sub; + uint16_t numBlocks = MIN(STL_NUM_PKEY_BLOCKS_PER_DRSMP, (endBlock - block)+1); + uint32_t attrmod = 0; + + attrmod = port << 16; + attrmod |= PKEY_BLOCK_NUM_MASK & block; + attrmod |= (0xff & numBlocks) << 24; + status = perform_stl_sma_query(STL_MCLASS_ATTRIB_ID_PART_TABLE, + attrmod, args, smp, sizeof(STL_PARTITION_TABLE)*numBlocks, NULL, 0); + if (status != FSUCCESS) + break; + + for (sub = 0; sub < numBlocks; sub++) { + STL_PARTITION_TABLE *pPartTab = (STL_PARTITION_TABLE *) + (stl_get_smp_data(smp) + + (sub * + sizeof(STL_PARTITION_TABLE))); + BSWAP_STL_PARTITION_TABLE(pPartTab); + } + if (print) + PrintStlPKeyTableSmp(&g_dest, 0/*indent*/, smp, nodetype, + (block==startBlock), (startBlock==endBlock), args->printLineByLine); + } + + if (status != FSUCCESS) { + fprintf(stderr, "get_pkey failed: error obtaining pkeys\n"); + return FALSE; + } else + return TRUE; +} //get_pkey + + +static boolean get_linfdb(argrec *args, uint8_t *mad, size_t mad_len, boolean print) +{ + FSTATUS status = FSUCCESS; + STL_LID maxLid; + uint16 block, startBlock, endBlock; + uint32 attribute = STL_MCLASS_ATTRIB_ID_LINEAR_FWD_TABLE; + STL_SMP *smp = (STL_SMP *)mad; + + if (mad_len < sizeof(STL_SMP)) + return FALSE; + + DBGPRINT ("-->get_linfdb\n"); + + { + STL_NODE_INFO *pNodeInfo = NULL; + STL_SWITCH_INFO *pSwInfo = NULL; + if (!get_node_info(args, (uint8_t *)smp, sizeof(*smp), g_verbose)) { + fprintf(stderr, "get_linfdb failed: unable to get_node_info\n"); + return FALSE; + } + pNodeInfo = (STL_NODE_INFO *)stl_get_smp_data(smp); + if (pNodeInfo->NodeType != STL_NODE_SW) { + fprintf(stderr, "get_linfdb failed: node is not a switch\n"); + return FALSE; + } + + if (!get_sw_info(args, (uint8_t *)smp, sizeof(*smp), g_verbose)) { + fprintf(stderr, "get_linfdb failed: unable to get_sw_info\n"); + return FALSE; + } + + pSwInfo = (STL_SWITCH_INFO *)stl_get_smp_data(smp); + if (pSwInfo->LinearFDBCap == 0) { + fprintf(stderr, "get_linfdb failed: Linear Forwarding Table not supported\n"); + return FALSE; + } + maxLid = MIN(pSwInfo->LinearFDBTop, pSwInfo->LinearFDBCap-1); + if(maxLid == 0){ + printf("Linear Forwarding Table is empty.\n"); + return TRUE; + } + } + + if (args->flid) { + if (args->flid > maxLid) { + fprintf(stderr, "get_linfdb failed: FLID 0x%x is greater than maxLid 0x%x\n", args->flid, maxLid); + return FALSE; + } + startBlock = endBlock = args->flid / MAX_LFT_ELEMENTS_BLOCK; + } else if (args->bflag) { + startBlock = args->block; + endBlock = startBlock + args->bcount - 1; + } else { + startBlock = 0; + endBlock = maxLid / MAX_LFT_ELEMENTS_BLOCK; + } + + for (block = startBlock; block <= endBlock; block += STL_NUM_LFT_BLOCKS_PER_DRSMP) { + uint16_t sub; + uint16_t numBlocks = MIN(STL_NUM_LFT_BLOCKS_PER_DRSMP, (endBlock - block)+1); + uint32_t attrmod = 0; + STL_LINEAR_FORWARDING_TABLE *pForwardBlock; + + attrmod = block; + attrmod |= (0xff & numBlocks) << 24; + + status = perform_stl_sma_query (attribute, attrmod, args, + smp, sizeof(*pForwardBlock)*numBlocks, NULL, 0); + if (status != FSUCCESS) + break; + + if (print) for (sub = 0, pForwardBlock=(STL_LINEAR_FORWARDING_TABLE*)stl_get_smp_data(smp); + sub < numBlocks; sub++, pForwardBlock ++) { + BSWAP_STL_LINEAR_FORWARDING_TABLE(pForwardBlock); + PrintStlLinearFDB(&g_dest, 0/*indent*/, pForwardBlock, block+sub, args->printLineByLine); + } + } + if (status != FSUCCESS) { + fprintf(stderr, "get_linfdb failed: unable to obtain LFT\n"); + return FALSE; + } else + return TRUE; +} //get_linfdb + + +static boolean get_mcfdb(argrec *args, uint8_t *mad, size_t mad_len, boolean print) +{ + FSTATUS status = FSUCCESS; + STL_LID maxLid; + uint32 block, startBlock, endBlock; + uint8 maxPosition; + uint8 maxPort; + uint16 position, startPosition, endPosition; + STL_SMP *smp = (STL_SMP *)mad; + + if (mad_len < sizeof(STL_SMP)) + return FALSE; + + DBGPRINT ("-->get_mcfdb\n"); + { + STL_NODE_INFO *pNodeInfo = NULL; + STL_SWITCH_INFO *pSwInfo = NULL; + + if (!get_node_info(args, (uint8_t *)smp, sizeof(*smp), g_verbose)) + return FALSE; + pNodeInfo = (STL_NODE_INFO *)stl_get_smp_data(smp); + if (pNodeInfo->NodeType != STL_NODE_SW) { + fprintf(stderr, "get_mcfdb failed: node is not a switch\n"); + return FALSE; + } + maxPort = pNodeInfo->NumPorts; + maxPosition = (pNodeInfo->NumPorts+1)/STL_PORT_MASK_WIDTH; + + if (!get_sw_info(args, (uint8_t *)smp, sizeof(*smp), g_verbose)) { + fprintf(stderr, "get_mcfdb failed: unable to get_sw_info\n"); + return FALSE; + } + + pSwInfo = (STL_SWITCH_INFO *)stl_get_smp_data(smp); + if (pSwInfo->MulticastFDBCap == 0) { + fprintf(stderr, "get_mcfdb failed: Multicast Forwarding Table not supported\n"); + return FALSE; + } + maxLid = pSwInfo->MulticastFDBTop; + } + + if (maxLid == 0 || (maxLid < STL_LID_MULTICAST_BEGIN)) { + fprintf(stderr, "get_mcfdb failed: Multicast FDB Top is zero.\n"); + return FALSE; + } + if (args->flid) { + if ((args->flid < STL_LID_MULTICAST_BEGIN) || (args->flid > STL_LID_MULTICAST_END)) { + fprintf(stderr, "get_mcfdb failed: Multicast LID specified: 0x%x must be 0x%x - 0x%x\n", args->flid, STL_LID_MULTICAST_BEGIN, STL_LID_MULTICAST_END); + return FALSE; + } + if (args->flid > maxLid) { + fprintf(stderr, "get_mcfdb failed: Multicast LID specified: 0x%x in exceeds Switch Max Multicast Lid 0x%x\n", + args->flid, maxLid); + return FALSE; + } + + startBlock = endBlock = (args->flid - STL_LID_MULTICAST_BEGIN) / STL_NUM_MFT_ELEMENTS_BLOCK; + + } else if (args->bflag) { + startBlock = args->block; + endBlock = startBlock + args->bcount - 1; + + } else { + startBlock = 0; + endBlock = (maxLid - STL_LID_MULTICAST_BEGIN) / STL_NUM_MFT_ELEMENTS_BLOCK; + } + + if (args->mflag) { + if (args->dport > maxPort) { + fprintf(stderr, "get_mcfdb failed: specified port %u exceeds available ports: %u\n", + args->dport, maxPort); + return FALSE; + } + startPosition = endPosition = args->dport / STL_PORT_MASK_WIDTH; + } else { + startPosition = 0; + endPosition = maxPosition; + } + + for (block = startBlock; block <= endBlock; block += STL_NUM_MFT_BLOCKS_PER_DRSMP) { + uint16_t numBlocks = MIN(STL_NUM_MFT_BLOCKS_PER_DRSMP, (endBlock - block)+1); + + for (position = startPosition; position <= endPosition; position++) { + uint32_t attrmod = ((0xff & numBlocks) << 24) | (position << 22) | + (0x0fffff & block); + status = perform_stl_sma_query (STL_MCLASS_ATTRIB_ID_MCAST_FWD_TABLE, + attrmod, args, smp, sizeof(STL_MULTICAST_FORWARDING_TABLE)*numBlocks, NULL, 0); + if (status != FSUCCESS) + break; + + if (print) + PrintStlMCastSmp(&g_dest, 0, smp, position, block, numBlocks, args->printLineByLine); + } + if (status != FSUCCESS) + break; + } + if (status != FSUCCESS) { + fprintf(stderr, "get_mcfdb failed: unable to obtain MFT\n"); + return FALSE; + } else + return TRUE; +} //get_mcfdb + + + +static boolean get_portgroup(argrec *args, uint8_t *mad, size_t mad_len, boolean print) +{ + FSTATUS status = FSUCCESS; + int maxGrps; + uint16 block, startBlock, endBlock; + uint32 attribute = STL_MCLASS_ATTRIB_ID_PORT_GROUP_TABLE; + STL_SMP *smp = (STL_SMP *)mad; + + if (mad_len < sizeof(STL_SMP)) + return FALSE; + + DBGPRINT ("-->get_portgroup\n"); + + { + STL_NODE_INFO *pNodeInfo = NULL; + STL_SWITCH_INFO *pSwInfo = NULL; + if (!get_node_info(args, (uint8_t *)smp, sizeof(*smp), g_verbose)) { + fprintf(stderr, "get_portgroup failed: unable to get_node_info\n"); + return FALSE; + } + pNodeInfo = (STL_NODE_INFO *)stl_get_smp_data(smp); + DBGPRINT("STL_NODE_INFO\n"); + if (pNodeInfo->NodeType != STL_NODE_SW) { + fprintf(stderr, "get_portgroup failed: node is not a switch\n"); + return FALSE; + } + + if (!get_sw_info(args, (uint8_t *)smp, sizeof(*smp), g_verbose)) { + fprintf(stderr, "get_portgroup failed: unable to get_sw_info\n"); + return FALSE; + } + + pSwInfo = (STL_SWITCH_INFO *)stl_get_smp_data(smp); + if (pSwInfo->CapabilityMask.s.IsAdaptiveRoutingSupported == 0) { + fprintf(stderr, "get_portgroup failed: Adaptive Routing not supported\n"); + return FALSE; + } + + // Use cap for now.. + uint8_t pgtop = pSwInfo->PortGroupTop; + if (pgtop==0) { + fprintf(stderr, "get_portgroup failed: No port groups defined\n"); + return FALSE; + } + maxGrps = (pgtop-1)/NUM_PGT_ELEMENTS_BLOCK; + } + + if (args->bflag) { + startBlock = args->block; + if (startBlock > maxGrps) { + fprintf(stderr, "get_portgroup failed: Start block out exceeds max blocks\n"); + return FALSE; + } + endBlock = (args->bcount>0) ? startBlock+args->bcount-1 : startBlock; + if (endBlock > maxGrps) { + // If requested block count exceeds max, just limit to max + endBlock = maxGrps; + } + } else { + startBlock = 0; + endBlock = maxGrps; + } + + for (block = startBlock; block <= endBlock; block += STL_NUM_PGTABLE_BLOCKS_PER_DRSMP) { + uint16_t sub; + uint16_t numBlocks = MIN(STL_NUM_PGTABLE_BLOCKS_PER_DRSMP, (endBlock - block)+1); + uint32_t attrmod = 0; + STL_PORT_GROUP_TABLE *pPortGroupBlock; + + attrmod = block; + attrmod |= (0xff & numBlocks) << 24; + + status = perform_stl_sma_query (attribute, attrmod, args, smp, + sizeof(*pPortGroupBlock) * numBlocks, NULL, 0); + if (status != FSUCCESS) + break; + + if (print) for (sub = 0, pPortGroupBlock=(STL_PORT_GROUP_TABLE*)stl_get_smp_data(smp); + sub < numBlocks; sub++, pPortGroupBlock ++) { + BSWAP_STL_PORT_GROUP_TABLE(pPortGroupBlock); + PrintStlPortGroupTable(&g_dest, 0/*indent*/, (uint64_t *)(pPortGroupBlock->PgtBlock), block+sub, 0, args->printLineByLine); + } + } + if (status != FSUCCESS) { + fprintf(stderr, "get_portgroup failed: unable to obtain PGT\n"); + return FALSE; + } else + return TRUE; +} + +static boolean get_portgroupfdb(argrec *args, uint8_t *mad, size_t mad_len, boolean print) +{ + FSTATUS status = FSUCCESS; + STL_LID maxLid; + uint16 block, startBlock, endBlock; + uint32 attribute = STL_MCLASS_ATTRIB_ID_PORT_GROUP_FWD_TABLE; + STL_SMP *smp = (STL_SMP *)mad; + + if (mad_len < sizeof(STL_SMP)) + return FALSE; + + DBGPRINT ("-->get_portgroupfdb\n"); + + { + STL_NODE_INFO *pNodeInfo = NULL; + STL_SWITCH_INFO *pSwInfo = NULL; + if (!get_node_info(args, (uint8_t *)smp, sizeof(*smp), g_verbose)) { + fprintf(stderr, "get_portgroupfdb failed: unable to get_node_info\n"); + return FALSE; + } + pNodeInfo = (STL_NODE_INFO *)stl_get_smp_data(smp); + if (pNodeInfo->NodeType != STL_NODE_SW) { + fprintf(stderr, "get_portgroupfdb failed: node is not a switch\n"); + return FALSE; + } + + if (!get_sw_info(args, (uint8_t *)smp, sizeof(*smp), g_verbose)) { + fprintf(stderr, "get_portgroupfdb failed: unable to get_sw_info\n"); + return FALSE; + } + + pSwInfo = (STL_SWITCH_INFO *)stl_get_smp_data(smp); + if (pSwInfo->CapabilityMask.s.IsAdaptiveRoutingSupported == 0) { + fprintf(stderr, "get_portgroupfdb failed: Adaptive Routing not supported\n"); + return FALSE; + } + maxLid = MIN(pSwInfo->LinearFDBTop, + pSwInfo->PortGroupFDBCap ? pSwInfo->PortGroupFDBCap - 1 : DEFAULT_MAX_PGFT_LID); + } + + if (args->flid) { + if (args->flid > maxLid) { + fprintf(stderr, "get_portgroupfdb failed: FLID 0x%x is greater than maxLid 0x%x\n", args->flid, maxLid); + return FALSE; + } + startBlock = endBlock = args->flid / NUM_PGFT_ELEMENTS_BLOCK; + } else if (args->bflag) { + startBlock = args->block; + if (startBlock > maxLid / NUM_PGFT_ELEMENTS_BLOCK) { + fprintf(stderr, "get_portgroupfdb failed: Start block out exceeds max blocks\n"); + return FALSE; + } + endBlock = startBlock + args->bcount - 1; + if (endBlock > maxLid / NUM_PGFT_ELEMENTS_BLOCK) { + endBlock = maxLid / NUM_PGFT_ELEMENTS_BLOCK; + fprintf(stderr, "portgroupfdb failed: Requested blocks(%d) exceeds max blocks(%d)\n", + args->bcount, endBlock+1); + return FALSE; + } + } else { + startBlock = 0; + endBlock = maxLid / NUM_PGFT_ELEMENTS_BLOCK; + } + + for (block = startBlock; block <= endBlock; block += STL_NUM_PGFT_BLOCKS_PER_DRSMP) { + uint16_t sub; + uint16_t numBlocks = MIN(STL_NUM_PGFT_BLOCKS_PER_DRSMP, (endBlock - block)+1); + uint32_t attrmod = 0; + STL_PORT_GROUP_FORWARDING_TABLE *pPortGroupBlock; + + attrmod = block; + attrmod |= (0xff & numBlocks) << 24; + + status = perform_stl_sma_query (attribute, attrmod, args, smp, + sizeof(*pPortGroupBlock) * numBlocks, NULL, 0); + if (status != FSUCCESS) + break; + + if (print) for (sub = 0, pPortGroupBlock=(STL_PORT_GROUP_FORWARDING_TABLE*)stl_get_smp_data(smp); + sub < numBlocks; sub++, pPortGroupBlock ++) { + BSWAP_STL_PORT_GROUP_FORWARDING_TABLE(pPortGroupBlock); + PrintStlPortGroupFDB(&g_dest, 0/*indent*/, pPortGroupBlock, block+sub, args->printLineByLine); + } + } + if (status != FSUCCESS) { + fprintf(stderr, "get_portgroupfdb failed: unable to obtain LFT\n"); + return FALSE; + } else + return TRUE; +} + + + +static boolean get_cong_info(argrec *args, uint8_t *mad, size_t mad_len, boolean print) +{ + STL_CONGESTION_INFO *pCongestionInfo; + STL_SMP *smp = (STL_SMP*)mad; + + if (mad_len < sizeof(STL_SMP)) + return FALSE; + + DBGPRINT("--->get_cong_info\n"); + + if (perform_stl_sma_query(STL_MCLASS_ATTRIB_ID_CONGESTION_INFO, 0, args, + smp, sizeof(*pCongestionInfo), NULL, 0) != FSUCCESS) { + fprintf(stderr, "get_cong_info failed: unable to obtain congestion info\n"); + return FALSE; + } + + pCongestionInfo = (STL_CONGESTION_INFO *)stl_get_smp_data(smp); + BSWAP_STL_CONGESTION_INFO(pCongestionInfo); + if (print) + PrintStlCongestionInfo(&g_dest, 0, pCongestionInfo, args->printLineByLine); + + return TRUE; + +} + +static boolean get_sw_cong_log(argrec *args, uint8_t *mad, size_t mad_len, boolean print) +{ + STL_SWITCH_CONGESTION_LOG *pSwitchCongestionLog; + STL_SMP *smp = (STL_SMP *)mad; + + if (mad_len < sizeof(STL_SMP)) + return FALSE; + + + DBGPRINT("--->get_sw_cong_log\n"); + { + STL_NODE_INFO *pNodeInfo = NULL; + if (!get_node_info(args, (uint8_t *)smp, sizeof(*smp), g_verbose)) + return FALSE; + + pNodeInfo = (STL_NODE_INFO *)stl_get_smp_data(smp); + if (pNodeInfo->NodeType != STL_NODE_SW) { + fprintf(stderr, "get_sw_cong_log failed: node is not a switch\n"); + return FALSE; + } + } + + + if (perform_stl_sma_query(STL_MCLASS_ATTRIB_ID_SWITCH_CONGESTION_LOG, 0, args, + smp, sizeof(*pSwitchCongestionLog), NULL, 0) != FSUCCESS) { + fprintf(stderr, "get_sw_cong_log failed: unable to obtain switch congestion log\n"); + return FALSE; + } + + pSwitchCongestionLog = (STL_SWITCH_CONGESTION_LOG *) stl_get_smp_data(smp); + BSWAP_STL_SWITCH_CONGESTION_LOG(pSwitchCongestionLog); + if (print) + PrintStlSwitchCongestionLog(&g_dest, 0, pSwitchCongestionLog, args->printLineByLine); + + return TRUE; +} + + +static boolean get_hfi_cong_log(argrec *args, uint8_t *mad, size_t mad_len, boolean print) +{ + STL_HFI_CONGESTION_LOG *pHfiCongestionLog; + STL_SMP *smp = (STL_SMP *)mad; + + if (mad_len < sizeof(STL_SMP)) + return FALSE; + + DBGPRINT("--->get_hfi_cong_log\n"); + { + STL_NODE_INFO *pNodeInfo = NULL; + + if (!get_node_info(args, (uint8_t *)smp, sizeof(*smp), g_verbose)) + return FALSE; + + pNodeInfo = (STL_NODE_INFO *)stl_get_smp_data(smp); + + if (pNodeInfo->NodeType == STL_NODE_SW) { + STL_SWITCH_INFO *pSwitchInfo = NULL; + + if (perform_stl_sma_query(STL_MCLASS_ATTRIB_ID_SWITCH_INFO, 0, args, + smp, sizeof(*pSwitchInfo), NULL, 0) != FSUCCESS) + { + fprintf(stderr, "get_hfi_cong_log failed: Couldn't get SwitchInfo for switch\n"); + return FALSE; + } + + pSwitchInfo = (STL_SWITCH_INFO *)stl_get_smp_data(smp); + BSWAP_STL_SWITCH_INFO(pSwitchInfo); + + if (!pSwitchInfo->u2.s.EnhancedPort0) { + fprintf(stderr, "get_hfi_cong_log failed: Switch Port 0 not enhanced.\n"); + return FALSE; + } + } + } + + if (perform_stl_sma_query(STL_MCLASS_ATTRIB_ID_HFI_CONGESTION_LOG, 0, args, + smp, sizeof(*pHfiCongestionLog), NULL, 0) != FSUCCESS) + { + fprintf(stderr, "get_hfi_cong_sett failed: unable to get HFI congestion log\n"); + return FALSE; + } + + pHfiCongestionLog = (STL_HFI_CONGESTION_LOG *)stl_get_smp_data(smp); + BSWAP_STL_HFI_CONGESTION_LOG(pHfiCongestionLog); + + if (print) + PrintStlHfiCongestionLog(&g_dest, 0, pHfiCongestionLog, args->printLineByLine); + + return TRUE; +} + +static boolean get_hfi_cong_sett(argrec *args, uint8_t *mad, size_t mad_len, boolean print) +{ + STL_HFI_CONGESTION_SETTING *pHfiCongestionSetting; + STL_SMP *smp = (STL_SMP *)mad; + + if (mad_len < sizeof(STL_SMP)) + return FALSE; + + DBGPRINT("--->get_hfi_cong_sett\n"); + + if (perform_stl_sma_query(STL_MCLASS_ATTRIB_ID_HFI_CONGESTION_SETTING, 0, + args, smp, sizeof(*pHfiCongestionSetting), NULL, 0) != FSUCCESS) + { + fprintf(stderr, "get_hfi_cong_sett failed: unable to obtain hfi congestion setting\n"); + return FALSE; + } + + pHfiCongestionSetting = (STL_HFI_CONGESTION_SETTING *) stl_get_smp_data(smp); + BSWAP_STL_HFI_CONGESTION_SETTING(pHfiCongestionSetting); + if (print) + PrintStlHfiCongestionSetting(&g_dest, 0, pHfiCongestionSetting, args->printLineByLine); + + return TRUE; +} + +static boolean get_sw_cong_sett(argrec *args, uint8_t *mad, size_t mad_len, boolean print) +{ + STL_SWITCH_CONGESTION_SETTING *pSwitchCongestionSetting; + STL_SMP *smp = (STL_SMP *)mad; + + if (mad_len < sizeof(STL_SMP)) + return FALSE; + + DBGPRINT("--->get_sw_cong_sett\n"); + + if (perform_stl_sma_query(STL_MCLASS_ATTRIB_ID_SWITCH_CONGESTION_SETTING, + 0, args, smp, sizeof(*pSwitchCongestionSetting), NULL, 0) != FSUCCESS) + { + fprintf(stderr, "get_sw_cong_sett failed: unable to obtain switch congestion setting\n"); + return FALSE; + } + + pSwitchCongestionSetting = (STL_SWITCH_CONGESTION_SETTING *) stl_get_smp_data(smp); + BSWAP_STL_SWITCH_CONGESTION_SETTING(pSwitchCongestionSetting); + if (print) + PrintStlSwitchCongestionSetting(&g_dest, 0, pSwitchCongestionSetting, args->printLineByLine); + + return TRUE; +} + +static boolean get_swport_cong_sett(argrec *args, uint8_t *mad, size_t mad_len, boolean print) +{ + STL_SWITCH_PORT_CONGESTION_SETTING *pSwitchPortCongestionSetting; + STL_SMP *smp = (STL_SMP *)mad; + uint32_t amod = 1<<24; + + if (mad_len < sizeof(STL_SMP)) + return FALSE; + + if (args->bflag) amod = (args->bcount<<24) | (args->block & 0xff); + + + DBGPRINT("--->get_swport_cong_sett\n"); + + if (perform_stl_sma_query(STL_MCLASS_ATTRIB_ID_SWITCH_PORT_CONGESTION_SETTING, + amod, args, smp, sizeof(*pSwitchPortCongestionSetting), NULL, 0) != FSUCCESS) + { + fprintf(stderr, "get_swport_cong_sett failed: unable to obtain switch congestion setting\n"); + return FALSE; + } + + pSwitchPortCongestionSetting = (STL_SWITCH_PORT_CONGESTION_SETTING *) stl_get_smp_data(smp); + BSWAP_STL_SWITCH_PORT_CONGESTION_SETTING(pSwitchPortCongestionSetting, (amod >> 24)); + + if (print) + PrintStlSwitchPortCongestionSettingSmp(&g_dest, 0, smp, args->printLineByLine); + + return TRUE; + +} + +static boolean get_hfi_congcont_table(argrec *args, uint8_t *mad, size_t mad_len, boolean print) +{ + STL_HFI_CONGESTION_CONTROL_TABLE *pHfiCongestionControl; + STL_SMP *smp = (STL_SMP *)mad; + uint32_t amod = 1<<24; + + if (mad_len < sizeof(STL_SMP)) + return FALSE; + + if (args->bcount > 14) { // 14 blocks is approximately the maximum number of blocks per MAD + fprintf(stderr, "get_hfi_congcont_table failed: Requested number of blocks for this query is too large. Maximum of 14 blocks.\n"); + return FALSE; + } + + if (args->bflag) amod = (args->bcount<<24 | (args->block & 0xff)); + + DBGPRINT("--->get_hfi_congcont_table\n"); + + if (perform_stl_sma_query(STL_MCLASS_ATTRIB_ID_HFI_CONGESTION_CONTROL_TABLE, + amod, args, smp, sizeof(*pHfiCongestionControl), NULL, 0) != FSUCCESS) + { + fprintf(stderr, "get_hfi_congcont_table failed: unable to obtain HFI congestion control table\n"); + return FALSE; + } + + pHfiCongestionControl = (STL_HFI_CONGESTION_CONTROL_TABLE *) stl_get_smp_data(smp); + BSWAP_STL_HFI_CONGESTION_CONTROL_TABLE(pHfiCongestionControl, amod>>24 & 0xff); + + if (print) + PrintStlHfiCongestionControlTab(&g_dest, 0, pHfiCongestionControl, amod>>24, amod & 0xff, args->printLineByLine); + + return TRUE; +} + +static boolean get_bfr_ctrl_table(argrec *args, uint8_t *mad, size_t mad_len, boolean print) +{ + FSTATUS status; + uint8 maxPort; + uint8 startPort = args->inport; + uint8 endPort = args->outport; + uint8 nodetype; + STL_SMP *smp = (STL_SMP *)mad; + uint8 maxcount = STL_NUM_BFRCTLTAB_BLOCKS_PER_DRSMP; + uint8_t block; + + if (mad_len < sizeof(SMP)) + return FALSE; + + if (args->mflag && !args->mflag2) + startPort = endPort = args->dport; + + DBGPRINT("-->get_bfr_ctrl_table\n"); + { + STL_NODE_INFO *pNodeInfo; + + if (!get_node_info(args, (uint8_t *)smp, sizeof(*smp), g_verbose)) { + fprintf(stderr, "get_bfr_ctrl_table failed: unable to get_node_info\n"); + return FALSE; + } + pNodeInfo = (STL_NODE_INFO *)stl_get_smp_data(smp); + + nodetype = pNodeInfo->NodeType; + maxPort = pNodeInfo->NumPorts; + + if (nodetype == STL_NODE_FI) { + if (args->mflag) + fprintf(stderr, "%s: -m ignored for bfrctrl against an HFI\n", g_cmdname); + + startPort = 0; + endPort = 0; + } else if (startPort > endPort || endPort > maxPort) { + fprintf(stderr, "get_bfr_ctrl_table failed: request exceeds " + "port count: %d max ports\n", maxPort); + return FALSE; + } + + if (nodetype == STL_NODE_SW && startPort == 0 && endPort == 0 && + !args->mflag2 && !args->mflag) { + startPort = 1; + endPort = maxPort; + } + } + + for (block = startPort; block <= endPort; block += maxcount) { + uint8_t n = MIN(maxcount, (endPort - block)+1); + uint32_t amod = (n << 24) | block; + status = perform_stl_sma_query (STL_MCLASS_ATTRIB_ID_BUFFER_CONTROL_TABLE, + amod, args, smp, sizeof(STL_BUFFER_CONTROL_TABLE)*n, NULL, 0); + + if (status != FSUCCESS) { + fprintf(stderr, "%s: %s: %s\n", __func__, MSG_SMP_SEND_RECV_FAILURE, iba_fstatus_msg(status)); + return FALSE; + } + + // PrintStlBfrCtlTableSmp will do BSWAP + if (print) + PrintStlBfrCtlTableSmp(&g_dest, 0, smp, nodetype, args->printLineByLine); + } + + return TRUE; +} //get_bfr_ctrl_table + +static boolean get_cable_info(argrec *args, uint8_t *mad, size_t mad_len, boolean print) +{ + FSTATUS status; + STL_SMP *smp = (STL_SMP *)mad; + uint16_t startAddr = STL_CIB_STD_LOW_PAGE_ADDR; + uint16_t len = 2*STL_CIB_STD_LEN; + STL_NODE_INFO *pNodeInfo; + NODE_TYPE nodetype; + uint8_t maxPort; + uint8_t cableInfoData[STL_CABLE_INFO_PAGESZ]; + uint8_t get_len = 0; + uint8_t bufoffset = 0; // where to add next data to cableInfoData + uint16_t bufstart = 0; // startAddr for cableInfoData[0] + uint8_t buflen = 0; // amount of data in cableInfoData + boolean hexOnly = FALSE; //indicates if only hexdump of cableInfoData should be produced + + if (args->bflag) { + startAddr = args->block; + if (args->bcount==0) { + fprintf(stderr, "get_cable_info failed: Invalid length specified\n"); + return FALSE; + } + len = args->bcount; + hexOnly = TRUE; + } + uint8_t portType; + + if (mad_len < sizeof(SMP)) + return FALSE; + + { + if (!get_node_info(args, (uint8_t *)smp, sizeof(*smp), g_verbose)) { + fprintf(stderr, "get_cable_info failed: unable to get_node_info\n"); + return FALSE; + } + + pNodeInfo = (STL_NODE_INFO *)stl_get_smp_data(smp); + nodetype = pNodeInfo->NodeType; + maxPort = pNodeInfo->NumPorts; + } + + if (nodetype == STL_NODE_SW) { + if (args->mflag) { + if (args->dport > maxPort || args->dport < 1) { + fprintf(stderr, "get_cable_info failed: specified port %u invalid must be %u - %u for this SW\n", + args->dport, 1, maxPort); + return FALSE; + } + } else { + fprintf(stderr, "get_cable_info failed: Must specify destination port on SW\n"); + return FALSE; + } + } else { + args->dport = pNodeInfo->u1.s.LocalPortNum; + if (args->mflag) { + fprintf(stderr, "%s: -m ignored for cable_info against an HFI\n", g_cmdname); + } + } + + if (startAddr + len-1 > STL_CABLE_INFO_MAXADDR) { + fprintf(stderr, "get_cable_info failed: Invalid address range\n"); + return FALSE; + } + + DBGPRINT("-->get_cable_info\n"); + { + STL_PORT_INFO *pPortInfo; + + if (!get_port_info(args, (uint8_t *)smp, sizeof(*smp), g_verbose)) { + fprintf(stderr, "get_cable_info_failed: unable to get_port_info\n"); + return FALSE; + } + + pPortInfo = (STL_PORT_INFO *)stl_get_smp_data(smp); + + portType = pPortInfo->PortPhysConfig.s.PortType; + } + + for (; len > 0; startAddr += get_len, len -= get_len) { + if (bufoffset == 0) { + bufstart = startAddr; + buflen = 0; + } + // can't cross page in single query + get_len = MIN(len, STL_CABLE_INFO_DATA_SIZE); + get_len = MIN(get_len, STL_CABLE_INFO_PAGESZ - (startAddr % STL_CABLE_INFO_PAGESZ)); + + DEBUG_ASSERT(startAddr/STL_CABLE_INFO_PAGESZ == (startAddr + get_len-1)/STL_CABLE_INFO_PAGESZ); + + uint32_t amod = (startAddr & 0x0fff)<<19 | ((get_len-1) & 0x3f)<<13 | (args->dport & 0xff); + + status = perform_stl_sma_query(STL_MCLASS_ATTRIB_ID_CABLE_INFO, + amod, args, smp, sizeof(STL_CABLE_INFO), NULL, 0); + if (status != FSUCCESS) { + fprintf(stderr, "%s: %s: %s\n", __func__, MSG_SMP_SEND_RECV_FAILURE, iba_fstatus_msg(status)); + return FALSE; + } + + if (print) { + uint8_t detail = g_detail; + STL_CABLE_INFO *pCableInfo = (STL_CABLE_INFO*)stl_get_smp_data(smp); + + if (detail > CABLEINFO_DETAIL_ALL) + detail = CABLEINFO_DETAIL_ALL; + BSWAP_STL_CABLE_INFO(pCableInfo); + memcpy(&cableInfoData[bufoffset], pCableInfo->Data, get_len); + buflen += get_len; + if (len <= get_len /* final SMP */ + || ((startAddr + get_len) % STL_CABLE_INFO_PAGESZ) == 0 /* page end */ + ) { + PrintStlCableInfo(&g_dest, 0, cableInfoData, bufstart, buflen, portType, detail, args->printLineByLine,hexOnly); + bufoffset = 0; + } else { + bufoffset += get_len; + } + } + } + + return TRUE; +} //get_cable_info + +optypes_t sma_query [] = { +//name func displayAbridged, description, mflag mflag2 fflag bflag iflag tflag cflag +{ "bfrctrl", get_bfr_ctrl_table, TRUE, "Buffer control tables", TRUE, TRUE, }, +{ "cableinfo", get_cable_info, TRUE, "Cable info", TRUE, FALSE, FALSE, TRUE}, +{ "conginfo", get_cong_info, TRUE, "Congestion info", FALSE }, +{ "desc", get_node_desc, TRUE, "Node descriptions/names", FALSE }, +{ "hficongcon", get_hfi_congcont_table,FALSE, "HFI congesting control settings", FALSE, FALSE, TRUE, TRUE }, +{ "hficonglog", get_hfi_cong_log, FALSE, "HFI congestion logs", FALSE, FALSE, FALSE, TRUE }, +{ "hficongset", get_hfi_cong_sett, FALSE, "HFI congestion settings", FALSE }, +{ "linfdb", get_linfdb, FALSE, "Switch linear FDB tables", FALSE, FALSE, TRUE, TRUE }, +{ "mcfdb", get_mcfdb, FALSE, "Switch multicast FDB tables", TRUE, FALSE, TRUE, TRUE }, +{ "portgroup", get_portgroup, FALSE, "Adaptive Routing port groups", FALSE, FALSE, FALSE, TRUE}, +{ "portgroupfdb",get_portgroupfdb, FALSE, "Adaptive Routing port group FWD tables", FALSE, FALSE, TRUE, TRUE }, +{ "nodeaggr", get_node_aggr, TRUE, "Node info and node descriptions", FALSE }, +{ "nodedesc", get_node_desc, FALSE, "Node descriptions/names", FALSE }, +{ "nodeinfo", get_node_info, FALSE, "Node info", TRUE }, +{ "node", get_node_info, FALSE, "Node info", TRUE }, +{ "portinfo", get_port_info, TRUE, "Port info", TRUE, FALSE, FALSE, FALSE, TRUE }, +{ "pstateinfo", get_pstate_info, FALSE, "Switch port state info", TRUE, TRUE }, +{ "pkey", get_pkey, FALSE, "P-Key tables ", TRUE, FALSE, FALSE, TRUE }, +{ "slsc", get_slsc_map, FALSE, "SL to SC mapping tables", FALSE }, +{ "scsl", get_scsl_map, FALSE, "SC to SL mapping tables", FALSE }, +{ "scsc", get_scsc_map, FALSE, "SC to SC mapping tables", TRUE, TRUE }, +{ "scvlt", get_scvlt_map, FALSE, "SC to VLt tables", TRUE, TRUE }, +{ "scvlnt", get_scvlnt_map, FALSE, "SC to VLnt tables", TRUE, TRUE }, +{ "scvlr", get_scvlr_map, FALSE, "SC to VLr tables", TRUE, TRUE }, +{ "sminfo", get_sm_info, FALSE, "SM info", FALSE }, +{ "swaggr", get_switch_aggr, FALSE, "Node info and switch info", FALSE }, +{ "swconglog", get_sw_cong_log, FALSE, "Switch congestion logs", FALSE, FALSE, FALSE, TRUE }, +{ "swcongset", get_sw_cong_sett, FALSE, "Switch congestion settings", FALSE }, +{ "swinfo", get_sw_info, TRUE, "Switch info", FALSE }, +{ "swportcong", get_swport_cong_sett, FALSE, "Switch congestion settings", FALSE, FALSE, FALSE, TRUE }, +{ "vlarb", get_vlarb, FALSE, "VL arbitration tables", TRUE }, +{ "ibnodeinfo", get_ib_node_info, FALSE, "IB node info", FALSE }, +{ "ledinfo", get_led_info, FALSE, "Led Info", TRUE }, +{ NULL } +}; + +void sma_Usage(boolean displayAbridged) +{ + DBGPRINT("sma_Usage\n"); + int i = 0; + + fprintf(stderr, "Usage: %s -o otype [standard options] [otype options] [hop hop hop...]\n", g_cmdname); + fprintf(stderr, " or\n"); + fprintf(stderr, " opasmaquery --help\n"); + fprintf(stderr, " --help - produce full help text\n\n"); + + fprintf(stderr, "Standard options: [-v] [-d detail] [-g] [-l lid] [-h hfi] [-p port]\n"); + fprintf(stderr, " -o otype Output type. See below for list.\n"); + fprintf(stderr, " -v Verbose output. Can be specified more than once for\n"); + fprintf(stderr, " additional openib debugging and libibumad debugging.\n"); + fprintf(stderr, " -d detail Output detail level 0-n CableInfo only (default is 2)\n"); + fprintf(stderr, " -g Display in line-by-line format (default is summary format)\n"); + fprintf(stderr, " -l lid Destination lid, default is local port\n"); + fprintf(stderr, " -h hfi hfi, numbered 1..n, 0= -p port will be a\n"); + fprintf(stderr, " system wide port num (default is 0)\n"); + fprintf(stderr, " -p port port, numbered 1..n, 0=1st active (default\n"); + fprintf(stderr, " is 1st active)\n"); + fprintf(stderr, "The -h and -p options permit a variety of selections:\n"); + fprintf(stderr, " -h 0 - 1st active port in system (this is the default)\n"); + fprintf(stderr, " -h 0 -p 0 - 1st active port in system\n"); + fprintf(stderr, " -h x - 1st active port on HFI x\n"); + fprintf(stderr, " -h x -p 0 - 1st active port on HFI x\n"); + fprintf(stderr, " -h 0 -p y - port y within system (irrespective of which ports are active)\n"); + fprintf(stderr, " -h x -p y - HFI x, port y\n"); + fprintf(stderr, "Note: will fallback to h:1 p:1 if no active port is found in system\n\n"); + fprintf(stderr, "otype options vary by report: [-m port|port1,port2]\n"); + fprintf(stderr, " [-f lid] [-b block[,count]]\n"); + fprintf(stderr, " -m port port in destination device to query\n"); + fprintf(stderr, " -m port1,port2 for some reports, a range of ports between\n"); + fprintf(stderr, " port1 and port2. For others, this is describes\n"); + fprintf(stderr, " an inport/outport pair.\n"); + fprintf(stderr, " -f lid lid to lookup in forwarding table to select an LFT or MFT block\n"); + fprintf(stderr, " Default is to show entire table\n"); + fprintf(stderr, " -b b display block or byte \"b\" of a larger table\n"); + fprintf(stderr, " -b b,c display \"c\" blocks or bytes of data starting with block/byte \"b\"\n"); + fprintf(stderr, " -b ,c display \"c\" blocks or bytes of data starting with block/byte 0\n"); + + fprintf(stderr, "\nPossible output types (default is nodeinfo):\n"); + i=0; + fprintf(stderr, " %-12s: %-55s\n","Output Type","Description"); + fprintf(stderr, " : %-55s\n","Supported Options"); + fprintf(stderr, " %-12s: %-55s\n","-----------","---------------------------------------------------"); + while (sma_query[i].name != NULL) { + if ( (displayAbridged && sma_query[i].displayWithAbridged) || (!displayAbridged) ) { + fprintf(stderr, " %-12s: %-55s\n",sma_query[i].name,sma_query[i].description); + + if ((sma_query[i].mflag)||(sma_query[i].mflag2)||(sma_query[i].bflag)||(sma_query[i].fflag)|| + (sma_query[i].tflag)||(sma_query[i].cflag)) { + fprintf(stderr, " %-12s:", " "); + if (sma_query[i].mflag) fprintf(stderr, " [-m dest_port]"); + if (sma_query[i].mflag2) fprintf(stderr, " [-m port1,port2]"); + if (sma_query[i].bflag) fprintf(stderr, " [-b %s]", + strcmp(sma_query[i].name, "cableinfo") == 0 ? "address[,length]" : "block[,count]"); + if (sma_query[i].fflag) fprintf(stderr, " [-f flid]"); + fprintf(stderr,"\n"); + } + fprintf(stderr,"\n"); + } + i++; + } + + if (!displayAbridged) { + fprintf(stderr, "\n"); + fprintf(stderr, "Examples:\n"); + fprintf(stderr, "---------\n"); + fprintf(stderr, "opasmaquery -o desc -l 6 # get nodedesc via lid routed\n"); + fprintf(stderr, "opasmaquery -o nodedesc 1 3 # get nodedesc via directed route\n"); + fprintf(stderr, " # (2 dr hops)\n"); + fprintf(stderr, "opasmaquery -o nodeinfo -l 2 3 # get nodeinfo via a combination of\n"); + fprintf(stderr, " # lid routed and directed route\n"); + fprintf(stderr, " # (1 dr hop)\n"); + fprintf(stderr, "opasmaquery -o portinfo # get local port info\n"); + fprintf(stderr, "opasmaquery -o portinfo -l 6 -m 1 # get port info of port 1 of lid 6\n"); + fprintf(stderr, "opasmaquery -o pkey -l 2 3 # get pkey table entries starting\n"); + fprintf(stderr, " # (lid routed to lid 2,\n"); + fprintf(stderr, " # then 1 dr hop to port 3)\n"); + fprintf(stderr, "opasmaquery -o vlarb -l 6 # get vlarb table entries from lid 6\n"); + fprintf(stderr, "opasmaquery -o swinfo -l 2 # get switch info\n"); + fprintf(stderr, "opasmaquery -o sminfo -l 1 # get SM info\n"); + fprintf(stderr, "opasmaquery -o slsc -l 3 # get sl2sc table entries from lid 3\n"); + fprintf(stderr, "opasmaquery -o scsl -l 3 # get sc2sl table entries from lid 3\n"); + } + exit(2); +} //Usage diff --git a/IbaTools/opasw/Makefile b/IbaTools/opasw/Makefile new file mode 100755 index 0000000..4f0954e --- /dev/null +++ b/IbaTools/opasw/Makefile @@ -0,0 +1,157 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** +# Makefile for xedge mgmt dirs + +# Include Make Control Settings +include $(TL_DIR)/$(PROJ_FILE_DIR)/Makesettings.project + +#=============================================================================# +# Definitions: +#-----------------------------------------------------------------------------# + +# Name of SubProjects +DS_SUBPROJECTS = +# name of executable or downloadable image +EXECUTABLE = # $(EXE_SUFFIX) +# list of sub directories to build +DIRS=opaswcommon opaswconfigure opaswfwupdate opaswfwverify opaswfwconfigure opaswping opaswquery opaswreset +ifeq "$(BUILD_XEDGE_TEST)" "YES" +DIRS+=opaswtest +endif + +# C files (.c) +CFILES = \ + # Add more c files here +# C++ files (.cpp) +CCFILES = \ + # Add more cpp files here +# lex files (.lex) +LFILES = \ + # Add more lex files here +# archive library files (basename, $ARFILES will add MOD_LIB_DIR/prefix and suffix) +LIBFILES= +# Windows Resource Files (.rc) +RSCFILES = +# Windows IDL File (.idl) +IDLFILE = +# Windows Linker Module Definitions (.def) file for dll's +DEFFILE = +# targets to build during INCLUDES phase (add public includes here) +INCLUDE_TARGETS = \ + # Add more h hpp files here +# Non-compiled files +MISC_FILES = +# all source files +SOURCES = $(CFILES) $(CCFILES) $(LFILES) $(RSCFILES) $(IDLFILE) +# Source files to include in DSP File +DSP_SOURCES = $(INCLUDE_TARGETS) $(SOURCES) $(MISC_FILES) \ + $(RSCFILES) $(DEFFILE) $(MAKEFILE) Makerules.module +# all object files +OBJECTS = $(CFILES:.c=$(OBJ_SUFFIX)) $(CCFILES:.cpp=$(OBJ_SUFFIX)) \ + $(LFILES:.lex=$(OBJ_SUFFIX)) +RSCOBJECTS = $(RSCFILES:.rc=$(RES_SUFFIX)) +# targets to build during LIBS phase +LIB_TARGETS_IMPLIB = +LIB_TARGETS_ARLIB = +LIB_TARGETS_EXP = $(LIB_TARGETS_IMPLIB:$(ARLIB_SUFFIX)=$(EXP_SUFFIX)) +LIB_TARGETS_MISC = +# targets to build during CMDS phase +CMD_TARGETS_SHLIB = +CMD_TARGETS_EXE = $(EXECUTABLE) +CMD_TARGETS_MISC = +# files to remove during clean phase +CLEAN_TARGETS_MISC = +CLEAN_TARGETS = $(OBJECTS) $(RSCOBJECTS) $(IDL_TARGETS) $(CLEAN_TARGETS_MISC) +# other files to remove during clobber phase +CLOBBER_TARGETS_MISC= +# sub-directory to install to within bin +BIN_SUBDIR = +# sub-directory to install to within include +INCLUDE_SUBDIR = + +# Additional Settings +#CLOCALDEBUG = User defined C debugging compilation flags [Empty] +#CCLOCALDEBUG = User defined C++ debugging compilation flags [Empty] +#CLOCAL = User defined C flags for compiling [Empty] +#CCLOCAL = User defined C++ flags for compiling [Empty] +#BSCLOCAL = User flags for Browse File Builder [Empty] +#DEPENDLOCAL = user defined makedepend flags [Empty] +#LINTLOCAL = User defined lint flags [Empty] +#LOCAL_INCLUDE_DIRS = User include directories to search for C/C++ headers [Empty] +#LDLOCAL = User defined C flags for linking [Empty] +#IMPLIBLOCAL = User flags for Object Lirary Manager [Empty] +#MIDLLOCAL = User flags for IDL compiler [Empty] +#RSCLOCAL = User flags for resource compiler [Empty] +#LOCALDEPLIBS = User libraries to include in dependencies [Empty] +#LOCALLIBS = User libraries to use when linking [Empty] +# (in addition to LOCALDEPLIBS) +#LOCAL_LIB_DIRS = User library directories for libpaths [Empty] + +CLOCAL = $(CPIE) +LOCALDEPLIBS = + +# Include Make Rules definitions and rules +include $(TL_DIR)/IbAccess/Makerules.module + +#=============================================================================# +# Overrides: +#-----------------------------------------------------------------------------# +#CCOPT = # C++ optimization flags, default lets build config decide +#COPT = # C optimization flags, default lets build config decide +#SUBSYSTEM = Subsystem to build for (none, console or windows) [none] +# (Windows Only) +#USEMFC = How Windows MFC should be used (none, static, shared, no_mfc) [none] +# (Windows Only) +#=============================================================================# + +#=============================================================================# +# Rules: +#-----------------------------------------------------------------------------# +# process Sub-directories +include $(TL_DIR)/Makerules/Maketargets.toplevel + +# build cmds and libs +include $(TL_DIR)/Makerules/Maketargets.build + +# install for includes, libs and cmds phases +include $(TL_DIR)/Makerules/Maketargets.moduleinstall + +# install for stage phase +include $(TL_DIR)/Makerules/Maketargets.modulestage + +# Unit test execution +#include $(TL_DIR)/Makerules/Maketargets.runtest + +clobber:: clobber_module + +#=============================================================================# + +#=============================================================================# +# DO NOT DELETE THIS LINE -- make depend depends on it. +#=============================================================================# diff --git a/IbaTools/opasw/opaswcommon/Makefile b/IbaTools/opasw/opaswcommon/Makefile new file mode 100644 index 0000000..eb0a1e8 --- /dev/null +++ b/IbaTools/opasw/opaswcommon/Makefile @@ -0,0 +1,163 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** +# Makefile for common xedge code files + +# Include Make Control Settings +include $(TL_DIR)/$(PROJ_FILE_DIR)/Makesettings.project + +#=============================================================================# +# Definitions: +#-----------------------------------------------------------------------------# + +# Name of SubProjects +DS_SUBPROJECTS = +# name of executable or downloadable image +EXECUTABLE = # +# list of sub directories to build +DIRS = +# C files (.c) +CFILES = \ + opaswcommon.c \ + opaswcommonMads.c \ + opaswmetadata.c \ + opaswpassword.c \ + # Add more c files here +# C++ files (.cpp) +CCFILES = \ + # Add more cpp files here +# lex files (.lex) +LFILES = \ + # Add more lex files here +# archive library files (basename, $ARFILES will add MOD_LIB_DIR/prefix and suffix) +LIBFILES= +# Windows Resource Files (.rc) +RSCFILES = +# Windows IDL File (.idl) +IDLFILE = +# Windows Linker Module Definitions (.def) file for dll's +DEFFILE = +# targets to build during INCLUDES phase (add public includes here) +INCLUDE_TARGETS = \ + opaswcommon.h \ + opaswmetadata.h \ + # Add more h hpp files here +# Non-compiled files +MISC_FILES = +# all source files +SOURCES = $(CFILES) $(CCFILES) $(LFILES) $(RSCFILES) $(IDLFILE) +# Source files to include in DSP File +DSP_SOURCES = $(INCLUDE_TARGETS) $(SOURCES) $(MISC_FILES) \ + $(RSCFILES) $(DEFFILE) $(MAKEFILE) +# all object files +OBJECTS = $(CFILES:.c=$(OBJ_SUFFIX)) $(CCFILES:.cpp=$(OBJ_SUFFIX)) \ + $(LFILES:.lex=$(OBJ_SUFFIX)) +RSCOBJECTS = $(RSCFILES:.rc=$(RES_SUFFIX)) +# targets to build during LIBS phase +LIB_TARGETS_IMPLIB = +LIB_TARGETS_ARLIB = $(LIB_PREFIX)opaswcommon$(ARLIB_SUFFIX) +LIB_TARGETS_EXP = $(LIB_TARGETS_IMPLIB:$(ARLIB_SUFFIX)=$(EXP_SUFFIX)) +LIB_TARGETS_MISC = +# targets to build during CMDS phase +CMD_TARGETS_SHLIB = +CMD_TARGETS_EXE = $(EXECUTABLE) +CMD_TARGETS_MISC = +# files to remove during clean phase +CLEAN_TARGETS_MISC = +CLEAN_TARGETS = $(OBJECTS) $(RSCOBJECTS) $(IDL_TARGETS) $(CLEAN_TARGETS_MISC) +# other files to remove during clobber phase +CLOBBER_TARGETS_MISC= +# sub-directory to install to within bin +BIN_SUBDIR = +# sub-directory to install to within include +INCLUDE_SUBDIR = + +# Additional Settings +#CLOCALDEBUG = User defined C debugging compilation flags [Empty] +#CCLOCALDEBUG = User defined C++ debugging compilation flags [Empty] +#CLOCAL = User defined C flags for compiling [Empty] +#CCLOCAL = User defined C++ flags for compiling [Empty] +#BSCLOCAL = User flags for Browse File Builder [Empty] +#DEPENDLOCAL = user defined makedepend flags [Empty] +#LINTLOCAL = User defined lint flags [Empty] +#LOCAL_INCLUDE_DIRS = User include directories to search for C/C++ headers [Empty] +#LDLOCAL = User defined C flags for linking [Empty] +#IMPLIBLOCAL = User flags for Object Lirary Manager [Empty] +#MIDLLOCAL = User flags for IDL compiler [Empty] +#RSCLOCAL = User flags for resource compiler [Empty] +#LOCALDEPLIBS = User libraries to include in dependencies [Empty] +#LOCALLIBS = User libraries to use when linking [Empty] +# (in addition to LOCALDEPLIBS) +#LOCAL_LIB_DIRS = User library directories for libpaths [Empty] + +CLOCAL=$(CIBACCESS) $(CPIE) +LOCALDEPLIBS=$(IBACCESS_USER_LIBS) +LOCAL_INCLUDE_DIRS= +LOCALLIBS=$(OPENIB_USER_LIBS) +LOCAL_LIB_DIRS=$(OPENIB_USER_LIB_DIRS) $(IBACCESS_USER_LIB_DIRS) + +# Include Make Rules definitions and rules +include $(TL_DIR)/$(PROJ_FILE_DIR)/Makerules.project + + +#=============================================================================# +# Overrides: +#-----------------------------------------------------------------------------# +#CCOPT = # C++ optimization flags, default lets build config decide +#COPT = # C optimization flags, default lets build config decide +#SUBSYSTEM = Subsystem to build for (none, console or windows) [none] +# (Windows Only) +#USEMFC = How Windows MFC should be used (none, static, shared, no_mfc) [none] +# (Windows Only) +#=============================================================================# + +#=============================================================================# +# Rules: +#-----------------------------------------------------------------------------# +# process Sub-directories +include $(TL_DIR)/Makerules/Maketargets.toplevel + +# build cmds and libs +include $(TL_DIR)/Makerules/Maketargets.build + +# install for includes, libs and cmds phases +include $(TL_DIR)/Makerules/Maketargets.install + +# install for stage phase +#include $(TL_DIR)/Makerules/Maketargets.stage +STAGE:: + +# Unit test execution +#include $(TL_DIR)/Makerules/Maketargets.runtest + +#=============================================================================# + +#=============================================================================# +# DO NOT DELETE THIS LINE -- make depend depends on it. +#=============================================================================# + diff --git a/IbaTools/opasw/opaswcommon/opaswcommon.c b/IbaTools/opasw/opaswcommon/opaswcommon.c new file mode 100644 index 0000000..5642ac4 --- /dev/null +++ b/IbaTools/opasw/opaswcommon/opaswcommon.c @@ -0,0 +1,1004 @@ +/* BEGIN_ICS_COPYRIGHT7 **************************************** + +Copyright (c) 2015-2018, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT7 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +#include +#include +#include +#include +#include + +/* work around conflicting names */ + +#include "iba/ib_types.h" +#include "iba/ib_sm_priv.h" +#include "iba/ib_helper.h" +#include "opamgt_sa_priv.h" +#include +#include "opaswcommon.h" +#include "openssl/sha.h" + + +#ifndef stringize +#define stringize(x) #x +#endif + +#ifndef add_quotes +#define add_quotes(x) stringize(x) +#endif + +#ifdef DBGPRINT +#undef DBGPRINT +#endif +#define DBGPRINT(format, args...) \ + do { if (g_verbose) { fflush(stdout); fprintf(stderr, format, ##args); } } while (0) + +#define MODULUS_LEN 256 +#define MODULUS_OFFSET 128 +#define MAX_PATH_RECS 1 + +extern int g_verbose; + + +FSTATUS getDestPath(struct omgt_port *port, EUI64 destPortGuid, char *cmd, IB_PATH_RECORD *pathp) +{ + FSTATUS fstatus; + EUI64 portGuid = -1; + uint64_t portPrefix = -1; + OMGT_QUERY query; + PQUERY_RESULT_VALUES pq = NULL; + uint8_t sm_sl = -1; + + (void)omgt_port_get_port_guid(port, &portGuid); + (void)omgt_port_get_port_prefix(port, &portPrefix); + (void)omgt_port_get_port_sm_sl(port, &sm_sl); + + memset(&query, 0, sizeof(query)); // initialize reserved fields + query.InputType = InputTypePathRecord; + query.InputValue.IbPathRecord.PathRecord.ComponentMask = IB_PATH_RECORD_COMP_SGID | + IB_PATH_RECORD_COMP_DGID | + IB_PATH_RECORD_COMP_PKEY | + IB_PATH_RECORD_COMP_NUMBPATH | + IB_PATH_RECORD_COMP_REVERSIBLE | + IB_PATH_RECORD_COMP_SL; + query.InputValue.IbPathRecord.PathRecord.PathRecord.SGID.Type.Global.SubnetPrefix = portPrefix; + query.InputValue.IbPathRecord.PathRecord.PathRecord.SGID.Type.Global.InterfaceID = portGuid; + query.InputValue.IbPathRecord.PathRecord.PathRecord.DGID.Type.Global.SubnetPrefix = portPrefix; + query.InputValue.IbPathRecord.PathRecord.PathRecord.DGID.Type.Global.InterfaceID = destPortGuid; + query.InputValue.IbPathRecord.PathRecord.PathRecord.P_Key = 0x7fff; + query.InputValue.IbPathRecord.PathRecord.PathRecord.NumbPath = MAX_PATH_RECS; + query.InputValue.IbPathRecord.PathRecord.PathRecord.Reversible = 1; + query.InputValue.IbPathRecord.PathRecord.PathRecord.u2.s.SL = sm_sl; + query.OutputType = OutputTypePathRecord; + + DBGPRINT("Query: Input=%s, Output=%s\n", + iba_sd_query_input_type_msg(query.InputType), + iba_sd_query_result_type_msg(query.OutputType)); + + // this call is synchronous + fstatus = omgt_query_sa(port, &query, &pq); + + if (! pq) + { + fprintf(stderr, "%*sSA PathRecord query Failed: %s\n", 0, "", FSTATUS_MSG(fstatus)); + goto fail; + } else if (pq->Status != FSUCCESS) + { + fprintf(stderr, "%*sSA PathRecord query Failed: %s MadStatus 0x%x: %s\n", 0, "", + FSTATUS_MSG(pq->Status), + pq->MadStatus, iba_sd_mad_status_msg(pq->MadStatus)); + free(pq); + goto fail; + } else if (pq->ResultDataSize == 0) + { + fprintf(stderr, "%*sNo Path Records Returned\n", 0, ""); + fstatus = FNOT_FOUND; + free(pq); + goto fail; + } else + { + PATH_RESULTS *p = (PATH_RESULTS*)pq->QueryResult; + + DBGPRINT("MadStatus 0x%x: %s\n", pq->MadStatus, + iba_sd_mad_status_msg(pq->MadStatus)); + DBGPRINT("%d Bytes Returned\n", pq->ResultDataSize); + if (p->NumPathRecords == 0) + { + fprintf(stderr, "%*sNo Path Records Returned\n", 0, ""); + fstatus = FNOT_FOUND; + goto fail; + } + *pathp = p->PathRecords[0]; + return(FSUCCESS); + + } + +fail: + return(FERROR); +} + +void opaswDisplayBuffer(char *buffer, int dataLen) +{ + + char *p = buffer; + int i; + + for (i = 0; i < dataLen; i+=2) { + if (!(i % 16)) + printf("\n%05x: ", i); + printf("%02x%02x ", *p & 0xff, *(p+1) & 0xff); + p += 2; + } + + printf("\n"); + + return; +} + +uint16 getSessionID(struct omgt_port *port, IB_PATH_RECORD *path) +{ + + VENDOR_MAD mad; + FSTATUS status; + uint16 sessionID; + + status = sendSessionMgmtGetMad(port, path, &mad, &sessionID); + if ((status == FSUCCESS) && (sessionID != 0)) + return(sessionID); + else + return((uint16)-1); +} + +void releaseSession(struct omgt_port *port, IB_PATH_RECORD *path, uint16 sessionID) +{ + VENDOR_MAD mad; + FSTATUS status; + + status = sendSessionMgmtReleaseMad(port, path, &mad, sessionID); + if (status != FSUCCESS) + fprintf(stderr, "Error: failed to release session\n"); + + return; +} + +uint16 getMadStatus(VENDOR_MAD *mad) +{ + uint16 status; + return(status = ntoh16(mad->common.u.NS.Status.AsReg16)); +} + +void displayStatusMessage(uint16 madStatus) +{ + switch (madStatus) { + + case MAD_STATUS_SUCCESS: + printf("Valid Field\n"); + break; + + case MAD_STATUS_BUSY: + printf("Invalid MAD: Busy\n"); + break; + + case MAD_STATUS_UNSUPPORTED_CLASS_VER: + printf("Invalid MAD: Unsupported Class or Version\n"); + break; + + case MAD_STATUS_UNSUPPORTED_METHOD: + printf("Invalid MAD: Unsupported Method\n"); + break; + + case MAD_STATUS_UNSUPPORTED_METHOD_ATTRIB: + printf("Invalid MAD: Unsupported Method/Attribute combination\n"); + break; + + case MAD_STATUS_INVALID_ATTRIB: + printf("Invalid MAD: Invalid Attribute or Attribute modifier\n"); + break; + + case VM_MAD_STATUS_SESSION_ID: + printf("Invalid MAD: Invalid Session ID\n"); + break; + + case VM_MAD_STATUS_NACK: + printf("Invalid MAD: Nack\n"); + break; + + case VM_MAD_STATUS_BUS_BUSY: + printf("Invalid MAD: Bus busy\n"); + break; + + case VM_MAD_STATUS_BUS_HUNG: + printf("Invalid MAD: Bus hung\n"); + break; + + case VM_MAD_STATUS_LOST_ARB: + printf("Invalid MAD: Lost ARB\n"); + break; + + case VM_MAD_STATUS_TIMEOUT: + printf("Invalid MAD: Operation timeout\n"); + break; + + case VM_MAD_STATUS_SAVE_ERROR: + printf("Invalid MAD: Save error\n"); + break; + + default: + printf("Invalid MAD: Invalid value in status field\n"); + break; + } +} + +int compareFwVersion(uint8 *version1, uint8 *version2) +{ + int versionParts1[5]; + int versionParts2[5]; + int i; + + // parse versions + + sscanf((char *)version1, "%d.%d.%d.%d.%d", + &versionParts1[0], + &versionParts1[1], + &versionParts1[2], + &versionParts1[3], + &versionParts1[4]); + sscanf((char *)version2, "%d.%d.%d.%d.%d", + &versionParts2[0], + &versionParts2[1], + &versionParts2[2], + &versionParts2[3], + &versionParts2[4]); + for (i = 0; i < 5; i++) { + if (versionParts1[0] != versionParts2[0]) + return((versionParts1[0] > versionParts2[0]) ? 1 : -1); + if (versionParts1[1] != versionParts2[1]) + return((versionParts1[1] > versionParts2[1]) ? 1 : -1); + if (versionParts1[2] != versionParts2[2]) + return((versionParts1[2] > versionParts2[2]) ? 1 : -1); + if (versionParts1[3] != versionParts2[3]) + return((versionParts1[3] > versionParts2[3]) ? 1 : -1); + if (versionParts1[4] != versionParts2[4]) + return((versionParts1[4] > versionParts2[4]) ? 1 : -1); + } + return(0); +} + +FSTATUS getFwVersion(struct omgt_port *port, + IB_PATH_RECORD *path, + VENDOR_MAD *mad, + uint16 sessionID, + uint8 *fwVersion) +{ + + FSTATUS status; + uint8 fwVerBuf[FWVERSION_SIZE]; + uint32 fwUpper; + uint32 fwLower; + + status = sendGetFwVersionMad(port, path, mad, sessionID, fwVerBuf); + if (status == FSUCCESS) { + fwUpper = ntoh32(*(uint32 *)&fwVerBuf[0]); + fwLower = ntoh32(*(uint32 *)&fwVerBuf[4]); + sprintf((char *)fwVersion, "%d.%d.%d.%d.%d", + (fwUpper >> 24) & 0xff, + (fwUpper >> 16) & 0xff, + (fwUpper >> 8) & 0xff, + fwUpper & 0xff, + fwLower); + } + return(status); +} + +#define ADDRESS_CHANGE_VERSION "5.0.3.0.4" +#define DEVELOPMENT_VERSION "0.0.0.0.0" + +FSTATUS getVPDInfo(struct omgt_port *port, + IB_PATH_RECORD *path, + VENDOR_MAD *mad, + uint16 sessionID, + uint32 module, + uint8 BoardID, + vpd_fruInfo_rec_t *vpdInfo) +{ + + FSTATUS status = FSUCCESS; + uint8 *vpdBuffer = NULL; + uint8 devHdrBuf[DEVICE_HDR_SIZE]; + uint8 *v; + uint8 *dp; + uint32 vpdOffset = 0; + uint32 vpdBufSize; + uint32 vpdReadSize; + uint32 vpdBytesRead = 0; + uint32 vpdAddress = 0; + int oemInfoPresent = (BoardID == STL_PRR_BOARD_ID_HPE7K); + int len; + int numOEMFields; + + switch (module) { + case OPASW_MODULE: + vpdAddress = I2C_OPASW_VPD_EEPROM_ADDR; + break; + default: + fprintf(stderr, "getVPDInfo: Invalid module\n"); + status = FERROR; + break; + } + + status = sendI2CAccessMad(port, path, sessionID, (void *)mad, NOJUMBOMAD, MMTHD_GET, RESP_WAIT_TIME, vpdAddress, DEVICE_HDR_SIZE, 0, devHdrBuf); + if (status == FSUCCESS) { + vpdBufSize = (devHdrBuf[5]<<8) + devHdrBuf[4]; + if ((vpdBuffer = malloc(vpdBufSize)) == NULL) { + fprintf(stderr, "getVpdInfo: Error allocating vpd buffer\n"); + status = FERROR; + goto bail; + } + v = vpdBuffer; + } else { + fprintf(stderr, "getVpdInfo: Error sending MAD packet to switch\n"); + goto bail; + } + + while ((status == FSUCCESS) && (vpdBytesRead < vpdBufSize)) { + if ((vpdBufSize - vpdBytesRead) < VPD_READ_SIZE) + vpdReadSize = vpdBufSize - vpdBytesRead; + else + vpdReadSize = VPD_READ_SIZE; + status = sendI2CAccessMad(port, path, sessionID, (void *)mad, NOJUMBOMAD, MMTHD_GET, RESP_WAIT_TIME, vpdAddress, vpdReadSize, vpdOffset, v); + if (status == FSUCCESS) { + v += vpdReadSize; + vpdBytesRead += vpdReadSize; + vpdOffset += vpdReadSize; + } else { + fprintf(stderr, "getVpdInfo: Error sending MAD packet to switch\n"); + goto bail; + } + } + +#define LOOPLIMIT 15 // cap loop to search for FRUINFO + if (status == FSUCCESS) { + + int loopCount; + memset(vpdInfo, 0, sizeof(vpd_fruInfo_rec_t)); + dp = vpdBuffer; + dp += DEVICE_HDR_SIZE; + // Walk xinfo records until fruInfo record is found + for (loopCount = 0; (loopCount < LOOPLIMIT) && (*dp != FRUINFO_TYPE); loopCount++) + { + len = *(dp + 2); + dp += len; + } + if (loopCount == LOOPLIMIT) + { + fprintf(stderr, "getVpdInfo: Error parsing VPD info\n"); + status = FERROR; + goto bail; + } + // Advance to FRU GUID + dp += (RECORD_HDR_SIZE + FRU_TYPE_SIZE + FRU_HANDLE_SIZE); + // advance past length (for appropriate guid type) plus one (for type code itself) + switch (*dp) + { + case 0: + dp++; + break; + case 1: + dp += (8 + 1); + break; + case 2: + dp += (6 + 1); + break; + case 3: + dp += (16 + 1); + break; + case 4: + dp += (8 + 1); + break; + default: + fprintf(stderr, "invalid GUID type %d\n", *dp); + break; + } + + // copy serial number + len = *dp & LEN_MASK; + memcpy(vpdInfo->serialNum, dp + 1, len); + vpdInfo->serialNum[len] = '\0'; + dp += len + 1; + + // copy part number + len = *dp & LEN_MASK; + memcpy(vpdInfo->partNum, dp + 1, len); + vpdInfo->partNum[len] = '\0'; + dp += len + 1; + + // Copy model + len = *dp & LEN_MASK; + memcpy(vpdInfo->model, dp + 1, len); + vpdInfo->model[len] = '\0'; + dp += len + 1; + + // Copy version + len = *dp & LEN_MASK; + memcpy(vpdInfo->version, dp + 1, len); + vpdInfo->version[len] = '\0'; + dp += len + 1; + + // Copy mfgName + len = *dp & LEN_MASK; + memcpy(vpdInfo->mfgName, dp + 1, len); + vpdInfo->mfgName[len] = '\0'; + dp += len + 1; + + // Copy productName + len = *dp & LEN_MASK; + memcpy(vpdInfo->productName, dp + 1, len); + vpdInfo->productName[len] = '\0'; + dp += len + 1; + + // Copy mfgID + switch (*dp) + { + case 0: + vpdInfo->mfgID[0] = '\0'; + dp++; + break; + case 1: + case 2: + dp++; + /* looks like mfgID is not least sig. byte first in the EEPROM, so copy in as is (do not byteswap) */ + memcpy(vpdInfo->mfgID, dp, 3); + dp += 3; + break; + default: + fprintf(stderr, "invalid Manufacturer ID code %d\n", *dp); + break; + } + + // Parse Mfg Date/Time + if (*dp & 0x80 ){ + vpdInfo->mfgYear = (*(dp + 3) << 2) + ((*(dp + 2) & 0xc0) >> 6); /* least sig byte 1st: bits 31-22 */ + vpdInfo->mfgMonth = (*(dp + 2) & 0x3c) >> 2; /* least sig byte 1st: bits 21-18 */ + vpdInfo->mfgDay = ((*(dp + 2) & 0x03) << 3) + ((*(dp + 1) & 0xe0) >> 5); /* least sig byte 1st: bits 17-13 */ + vpdInfo->mfgHours = *(dp + 1) & 0x1f; /* least sig byte 1st: bits 12-8 */ + vpdInfo->mfgMins = *dp & 0x3f; /* least sig byte 1st: bits 5-0 */ + } else { + vpdInfo->mfgYear = 0; + vpdInfo->mfgMonth = 0; + vpdInfo->mfgDay = 0; + vpdInfo->mfgHours = 0; + vpdInfo->mfgMins = 0; + } + + dp += 4; + numOEMFields = *dp & LEN_MASK; + if (oemInfoPresent && (numOEMFields == 3)) { + // only process if exactly 3 OEM fields + + dp++; + + // copy serial number + len = *dp & LEN_MASK; + memcpy(vpdInfo->serialNum, dp + 1, len); + vpdInfo->serialNum[len] = '\0'; + dp += len + 1; + + // copy part number + len = *dp & LEN_MASK; + memcpy(vpdInfo->partNum, dp + 1, len); + vpdInfo->partNum[len] = '\0'; + + // oem rev is the last part of part number, after second hyphen + if ((dp = (uint8 *)strchr((char *)vpdInfo->partNum, '-')) != NULL) { + if ((dp = (uint8 *)strchr((char *)dp + 1, '-')) != NULL) { + dp++; + len = strlen((char *)dp); + memcpy(vpdInfo->version, dp, len); + vpdInfo->version[len] = '\0'; + } else { + vpdInfo->version[0] = '\0'; + } + } else { + vpdInfo->version[0] = '\0'; + } + } + } + +bail: + if (vpdBuffer) free(vpdBuffer); + return(status); +} + +int ltc2974_L11_to_Celsius(uint16 half16) +{ + int exponent; + int mantissa; + int celsius; + + /* extract components from LinearFloat5_11 (L11) format */ + exponent = half16 >> 11; + mantissa = half16 & 0x7ff; + + /* if mantissa is negative, sign extend */ + if (mantissa > 0x03FF) + mantissa |= 0xFFFFF800; + + /* determine sign of exponent */ + if (exponent > 0x0F) { + /* exponent is negative, sign extend */ + exponent |= 0xFFFFFFE0; + /* make exponent positive */ + exponent = (~exponent)+1; + /* divide instead of multiply */ + celsius = mantissa / (1 << exponent); + } + else /* exponent is positive */ + celsius = mantissa * (1 << exponent); + + return celsius; +} + +FSTATUS getTempReadings(struct omgt_port *port, IB_PATH_RECORD *path, + VENDOR_MAD *mad, uint16 sessionID, char tempStrs[I2C_OPASW_TEMP_SENSOR_COUNT][TEMP_STR_LENGTH], uint8 BoardID) +{ + FSTATUS status = FSUCCESS; + uint8 ErrorFlags = 0; + uint16 mgmtFpgaOffset = 0; + boolean maxDetected; + union { + uint8 u8[2]; + uint16 u16; + } value; + +//for GMF modules, LTC2974 may not be there + + if (BoardID == STL_PRR_BOARD_ID_HPE7K) { + snprintf(tempStrs[0], TEMP_STR_LENGTH, "LTC2974: N/A"); + } + else { + // LTC2974 + // It is possible the LTC2974 temp sensor may need to be initilized + status = sendI2CAccessMad(port, path, sessionID, (void *)mad, NOJUMBOMAD, MMTHD_GET, RESP_WAIT_TIME, + I2C_OPASW_LTC2974_TEMP_ADDR, 2, I2C_OPASW_LTC2974_TEMP_OFFSET, &value.u8[0]); + + if (status != FSUCCESS) { + //fprintf(stderr, "getTempReadings: Error sending MAD packet to switch to read LTC2974 temp\n"); + snprintf(tempStrs[0], TEMP_STR_LENGTH, "LTC2974: N/A"); + ErrorFlags |= (1<<0); + } else { + snprintf(tempStrs[0], TEMP_STR_LENGTH, "LTC2974: %dC", ltc2974_L11_to_Celsius(value.u16)); + } + } + + { // PRR ASIC + mgmtFpgaOffset = (I2C_OPASW_MGMT_FPGA_REG_RD << 8) | I2C_OPASW_PRR_ASIC_TEMP_MGMT_FPGA_OFFSET; + status = sendI2CAccessMad(port, path, sessionID, (void *)mad, NOJUMBOMAD, MMTHD_GET, RESP_WAIT_TIME, + I2C_OPASW_MGMT_FPGA_ADDR, 1, mgmtFpgaOffset, &value.u8[0]); + + if (status != FSUCCESS) { + //fprintf(stderr, "getTempReadings: Error sending MAD packet to switch to read PRR ASIC temp\n"); + snprintf(tempStrs[1], TEMP_STR_LENGTH, "PRR ASIC: N/A"); + ErrorFlags |= (1<<2); + } else { + snprintf(tempStrs[1], TEMP_STR_LENGTH, "PRR ASIC: %dC", value.u8[0]); + } + } + { // CHECK QSFPTemperatureMaxDetected + status = getMaxQsfpTemperatureMaxDetected(port, path, mad, sessionID, &maxDetected); + if (status != FSUCCESS) { + fprintf(stderr,"Error: getMaxQsfpTemperatureMaxDetected failed\n"); + iba_fstatus_msg(status); + } + } + + { // MAX QSFP + if (maxDetected) { + mgmtFpgaOffset = (I2C_OPASW_MGMT_FPGA_REG_RD << 8) | I2C_OPASW_MAX_QSFP_TEMP_MGMT_FPGA_OFFSET; + status = sendI2CAccessMad(port, path, sessionID, (void *)mad, NOJUMBOMAD, MMTHD_GET, RESP_WAIT_TIME, + I2C_OPASW_MGMT_FPGA_ADDR, 1, mgmtFpgaOffset, &value.u8[0]); + + if (status != FSUCCESS) { + //fprintf(stderr, "getTempReadings: Error sending MAD packet to switch to read MAX QSFP temp\n"); + snprintf(tempStrs[2], TEMP_STR_LENGTH, "MAX QSFP: N/A"); + ErrorFlags |= (1<<1); + } else { + snprintf(tempStrs[2], TEMP_STR_LENGTH, "MAX QSFP: %dC", value.u8[0]); + } + } else { + snprintf(tempStrs[2], TEMP_STR_LENGTH, "MAX QSFP: N/A"); + } + } + + return(status | (ErrorFlags << 8)); + +} + +FSTATUS getFanSpeed(struct omgt_port *port, + IB_PATH_RECORD *path, + VENDOR_MAD *mad, + uint16 sessionID, + uint32 fanNum, + uint32 *fanSpeed) +{ + FSTATUS status = FSUCCESS; + uint32 readOffset = 0; + union { + uint8 u8[2]; + uint16 u16; + } value; + + // validate the fan number + if (fanNum >= OPASW_PSOC_FAN_CTRL_TACHS) { + fprintf(stderr, "getFanSpeed: Invalid fan index: %d\n", fanNum); + return FERROR; + } + + // readOffset calculated as seen in BSP/bpscommon/ibml/psocFanCtrl.c - psocFanCtrl_ReadTach + readOffset = OPASW_PSOC_FAN1_ACTUAL_SPEED_OFFSET + (fanNum * 2); + + status = sendI2CAccessMad(port, path, sessionID, (void *)mad, NOJUMBOMAD, MMTHD_GET, RESP_WAIT_TIME, + I2C_OPASW_PSOC_FAN_ADDR, 2, readOffset, &value.u8[0]); + + if (status != FSUCCESS) { + fprintf(stderr, "getFanSpeed: Error sending MAD packet to switch to read\n"); + } else { + // tachReading obtained as seen in BSP/bspcommon/i2c.c - i2cReadWordReg (sort of) + int tachReading = value.u16; + // fanSpeed calculated as seen in BSP/bpscommon/ibml/psocFanCtrl.c - psocFanCtrl_ReadTach + int temp = (tachReading & 0xFF) << 8; + *fanSpeed = (((tachReading >> 8) & 0xFF) | temp); + } + + return(status); + + // TODO: do we still need to check if the fan needs to be initialized? Its not + // clear to me from the bsp code +} + +int getNumPS() { + return 2; + //This function will always return 2 for now, but in the future this number may change based upon manufacturer or design. +} + +FSTATUS getPowerSupplyStatus(struct omgt_port *port, + IB_PATH_RECORD *path, + VENDOR_MAD *mad, + uint16 sessionID, + uint32 psNum, + uint32 *psStatus) +{ + FSTATUS status = FSUCCESS; + uint32 mgmtFpgaAddress = 0; + uint16 mgmtFpgaOffset = 0; + uint32 powerSupplyStatus = 0; + uint8 dataBuffer[10]; + uint8 *psPtr; + uint8 value; + int numPS; + + numPS = getNumPS(); + mgmtFpgaAddress = I2C_OPASW_MGMT_FPGA_ADDR; + mgmtFpgaOffset = (I2C_OPASW_MGMT_FPGA_REG_RD << 8) | I2C_OPASW_PS_MGMT_FPGA_OFFSET; + + if ((psNum < 1) || (psNum > 2)) { + status = FERROR; + fprintf(stderr, "getPowerSupplyStatus: bad power supply number %d\n", psNum); + } + + if (status == FSUCCESS) { + status = sendI2CAccessMad(port, path, sessionID, (void *)mad, NOJUMBOMAD, MMTHD_GET, RESP_WAIT_TIME, + mgmtFpgaAddress, 1, mgmtFpgaOffset, dataBuffer); + + if (status != FSUCCESS) { + fprintf(stderr, "getPowerSupplyStatus: Error sending MAD packet to switch\n"); + } else { + psPtr = dataBuffer; + value = *psPtr; + if (psNum == 1) { + powerSupplyStatus = ((value >> PSU1_MGMT_FPGA_BIT_PRESENT) & 0x01); + if (powerSupplyStatus) { + if ((value >> PSU1_MGMT_FPGA_BIT_PWR_OK) & 0x01) + *psStatus = PS_ONLINE; + else + *psStatus = PS_OFFLINE; + } else { + *psStatus = PS_NOT_PRESENT; + } + } + else if (numPS<2) { + *psStatus = PS_INVALID; + } + else { + powerSupplyStatus = ((value >> PSU2_MGMT_FPGA_BIT_PRESENT) & 0x01); + if (powerSupplyStatus) { + if ((value >> PSU2_MGMT_FPGA_BIT_PWR_OK) & 0x01) + *psStatus = PS_ONLINE; + else + *psStatus = PS_OFFLINE; + } else { + *psStatus = PS_NOT_PRESENT; + } + } + } + } + + return(status); +} + +FSTATUS getMaxQsfpTemperatureMaxDetected(struct omgt_port *port, + IB_PATH_RECORD *path, + VENDOR_MAD *mad, + uint16 sessionID, + boolean *maxDetected) +{ + + FSTATUS status; + uint32 location = QSFP_MGR_TEMPERATURE_MAX_DETECTED_MEM_ADDR; + uint32 nextLocation; + uint32 result; + uint8 memoryData[4]; //32 bits + + *maxDetected = FALSE; + status = sendMemAccessGetMad(port, path, mad, sessionID, location, (uint8)4, memoryData); + if (status == FSUCCESS) { + nextLocation = ntoh32(*(uint32 *)memoryData); + } else { + fprintf(stderr, "sendMemAccessGetMad error\n"); + return(status); + } + status = sendMemAccessGetMad(port, path, mad, sessionID, nextLocation, (uint8)4, memoryData); + if (status == FSUCCESS) { + result = ntoh32(*(uint32 *)memoryData); + *maxDetected = !((0x80000000 & result) >> 31); + //If the 31st bit is 1 the value is NOT valid + //If the 31st bit is 0 the value is valid + } else { + fprintf(stderr, "sendMemAccessGetMad error\n"); + } + + return(status); +} + + +FSTATUS getAsicVersion(struct omgt_port *port, + IB_PATH_RECORD *path, + VENDOR_MAD *mad, + uint16 sessionID, + uint32 *asicVersion) +{ + + FSTATUS status; + uint32 location = ASIC_VERSION_MEM_ADDR; + uint8 memoryData[10]; + + status = sendMemAccessGetMad(port, path, mad, sessionID, location, (uint8)10, memoryData); + if (status == FSUCCESS) { + *asicVersion = ntoh32(*(uint32 *)memoryData); + } + return(status); +} + +FSTATUS getOemHash(struct omgt_port *port, + IB_PATH_RECORD *path, + VENDOR_MAD *mad, + uint16 sessionID, + uint32 *oemHash,uint32 *acb) +{ + + FSTATUS status; + uint32 location = OEM_HASH_SIGNER_START_ADDRESS; + uint8 memoryData[4]; + int i = 0; + status = sendMemAccessGetMad(port, path, mad, sessionID, AUTHENTICATION_CONTROL_BIT_ADDRESS, (uint8)4, memoryData); + if(status != FSUCCESS) + return status; + *acb = ntoh32 (*(uint32 *)memoryData); + for(location = OEM_HASH_SIGNER_START_ADDRESS; location <= OEM_HASH_SIGNER_END_ADDRESS; location++){ + status = sendMemAccessGetMad(port, path, mad, sessionID, location, (uint8)4, memoryData); + if (status == FSUCCESS) { + oemHash[i] = ntoh32 (*(uint32 *)memoryData); + i++; + } + else + return(status); + } + return(status); +} + + +FSTATUS getBoardID(struct omgt_port *port, + IB_PATH_RECORD *path, + VENDOR_MAD *mad, + uint16 sessionID, + uint8 *boardID) +{ + + FSTATUS status; + uint32 boardIdAddress = I2C_BOARD_ID_ADDR; + uint16 offset; + uint8 dataBuffer; + + offset = (I2C_OPASW_MGMT_FPGA_REG_RD << 8) | I2C_OPASW_BD_MGMT_FPGA_OFFSET; + + status = sendI2CAccessMad(port, path, sessionID, (void *)mad, NOJUMBOMAD, MMTHD_GET, RESP_WAIT_TIME, + boardIdAddress, 1, offset, &dataBuffer); + if (status == FSUCCESS) { + dataBuffer &= STL_PRR_BOARD_ID_MASK; + *boardID = dataBuffer; + } + return(status); +} + +FSTATUS doPingSwitch(struct omgt_port *port, IB_PATH_RECORD *path, STL_PERF_MAD *mad) +{ + + FSTATUS status; + + status = sendSTLPortStatsPort1Mad(port, path, mad); + + return(status); +} + + +FSTATUS getEMFWFileNames(struct omgt_port *port, + IB_PATH_RECORD *path, + uint16 sessionID, + char *fwFileName, + char *inibinFileName) +{ + FSTATUS status = FSUCCESS; + VENDOR_MAD mad; + uint8 boardID; + FILE *fpInibinMap = NULL; + char readBuf[80]; + char fwName[FNAME_SIZE]; + char inibinName[FNAME_SIZE]; + unsigned int id; + + fwFileName[0] = 0; + inibinFileName[0] = 0; + + status = getBoardID(port, path, &mad, sessionID, &boardID); + + if (status == FSUCCESS) { + fpInibinMap = fopen("emfwMapFile", "r"); + if (fpInibinMap == NULL) { + status = FINVALID_PARAMETER; + } else { + while (fgets(readBuf, 80, fpInibinMap) != NULL) { + if (readBuf[0] != '0') + continue; + sscanf(readBuf, "%x %"add_quotes(FNAME_SIZE)"s %"add_quotes(FNAME_SIZE)"s", &id, fwName, inibinName); + if (id == boardID) { + strcpy(fwFileName, fwName); + strcpy(inibinFileName, inibinName); + break; + } + } + } + if (fpInibinMap) + fclose(fpInibinMap); + } + + return(status); +} + +FSTATUS getBinaryHash(char *fwFileName,uint32 *binaryHash) +{ + FILE *fp; + int nread; + char buf[MODULUS_LEN]; + unsigned char hash[SHA256_DIGEST_LENGTH]; + if (fwFileName == NULL || strlen(fwFileName) == 0) { + fprintf(stderr, "Error: Firmware file name is invalid\n"); + return FERROR; + } + else if ((fp = fopen(fwFileName,"rb")) == NULL) { + return FERROR; + } + else if (fseek(fp, MODULUS_OFFSET, 0)) { + fclose(fp); + return FERROR; + } + else if ((nread = fread(buf,1,MODULUS_LEN,fp)) == MODULUS_LEN) { + fclose(fp); + int i = 0; + (void *)SHA256((unsigned char*)buf,sizeof(buf),hash); + for(i = 0; i < (SHA256_DIGEST_LENGTH/sizeof(uint32)); i++) + binaryHash[i] = ntoh32(*(uint32 *)(hash +(i * sizeof(uint32)))); + + return FSUCCESS; + } + + fclose(fp); + return FERROR; +} +/* opaswEepromRW: Reads from or Writes to the switch EEPROM + based on prrEepromRW in prrFwUpdate.c */ +FSTATUS opaswEepromRW(struct omgt_port *port, IB_PATH_RECORD *path, uint16 sessionID, void *mad, int timeout, + uint32 len, uint32 offset, uint8 *data, boolean writeData, boolean secondary) { + uint32 maxXfer = 128; + uint32 xferLen; + int result; + uint32 remainingLen = len; + uint32 eepromAddrIncrement; + uint32 location = secondary ? STL_PRR_SEC_EEPROM1_ADDR : STL_PRR_PRI_EEPROM1_ADDR; + + + while (remainingLen) { + xferLen = MIN(remainingLen, maxXfer); + + eepromAddrIncrement = ((offset >> 16) & 0x03) << 1; + + // update the location to account for the 4 EEPROMs + location = (secondary ? STL_PRR_SEC_EEPROM1_ADDR : STL_PRR_PRI_EEPROM1_ADDR) + (eepromAddrIncrement << STL_PRR_I2C_LOCATION_ADDR); + + // for now, access the secondary bus at 100KHz for writing + if (secondary && writeData) + location &= 0x7fffffff; + + if (writeData) { + result = sendI2CAccessMad(port, path, sessionID, mad, NOJUMBOMAD, MMTHD_SET, timeout, location, xferLen, offset & 0xffff, data); + } else { + result = sendI2CAccessMad(port, path, sessionID, mad, NOJUMBOMAD, MMTHD_GET, timeout, location, xferLen, offset & 0xffff, data); + } + + if (result != FSUCCESS) { + return result; + } + offset += xferLen; + data += xferLen; + remainingLen -= xferLen; + } + return FSUCCESS; +} + +const char* +StlPortLtpCrcModeVMAToText(uint16_t mode, char *str, size_t len) +{ + size_t n = 0; + size_t i = 0; + + str[0]='\0'; + + PRINT_OR_OUT(str, len, "16-bit,"); + if (mode & STL_PRR_PORT_LTP_CRC_MODE_VMA_14) + PRINT_OR_OUT(str, len, "14-bit,"); + if (mode & STL_PRR_PORT_LTP_CRC_MODE_VMA_48) + PRINT_OR_OUT(str, len, "48-bit,"); + if (mode & STL_PRR_PORT_LTP_CRC_MODE_VMA_12_16_PER_LANE) + PRINT_OR_OUT(str, len, "12-16/lane,"); + + str[n-1] = 0; // Eliminate trailing comma + +out: + return str; +} + diff --git a/IbaTools/opasw/opaswcommon/opaswcommon.h b/IbaTools/opasw/opaswcommon/opaswcommon.h new file mode 100644 index 0000000..a2b9eff --- /dev/null +++ b/IbaTools/opasw/opaswcommon/opaswcommon.h @@ -0,0 +1,418 @@ +/* BEGIN_ICS_COPYRIGHT3 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT3 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +/*********************** + * MACROS + ***********************/ + +#ifndef _OPASW_COMMON_H_ +#define _OPASW_COMMON_H_ + +#include "iba/stl_mad_priv.h" +#include "iba/stl_pm.h" + +/*********************** + * CONSTANTS + ***********************/ + +#define QP1_WELL_KNOWN_Q_KEY 0x80010000U +#define GSI_QUEUE_PAIR 1 +#define OMGT_GLOBAL_PORTID -1 +#define RESP_WAIT_TIME (1000) +#define DEF_RETRIES 3 +#define FW_RETRIES 5 +#define CSS_HEADER_SIZE 644 +#define OPASW_BUFFER_PAD 20 + +#define PS_NOT_PRESENT 0 +#define PS_OFFLINE 1 +#define PS_ONLINE 2 +#define PS_INVALID 3 + +#define MCLASS_PERF 0x04 /* Mgmt Class for Performance Mgmt (used for ping) */ +#define MCLASS_VENDOR_OPASW 0x0A /* Mgmt Class for OPASW Vendor Mad protocol */ +#define STL_VENDOR_SPEC_CLASS_VERSION 0x80 + +#define MCLASS_ATTRIB_ID_CLASSPORTINFO 0x0001 /* Class Port Info */ +#define MCLASS_ATTRIB_ID_SESSION_MGMT 0x0011 /* Session management function */ +#define MCLASS_ATTRIB_ID_S20_MEM_ACCESS 0x0012 /* S20 Memory Access function */ +#define MCLASS_ATTRIB_ID_INI_SYS_TABLE_ACC 0x0013 /* Ini System Table Access function */ +#define MCLASS_ATTRIB_ID_INI_PORT_TABLE_ACC 0x0014 /* Ini Port Table Access function */ +#define MCLASS_ATTRIB_ID_INI_DESCR_GET 0x0015 /* Ini Descriptor Get function */ +#define MCLASS_ATTRIB_ID_I2C_ACCESS 0x0016 /* I2C Access function */ +#define MCLASS_ATTRIB_ID_QSFP_ACCESS 0x0017 /* QSFP Access function */ +#define MCLASS_ATTRIB_ID_FW_VERSION 0x0018 /* FW Version function */ +#define MCLASS_ATTRIB_ID_REBOOT 0x0019 /* Reboot function */ +#define MCLASS_ATTRIB_ID_SAVE_CONFIG 0x001A /* Save Configuration function */ +#define MCLASS_ATTRIB_ID_DUMP 0x001B /* Dump function */ +#define MCLASS_ATTRIB_ID_LED_STATUS 0x001C /* LED Status function */ +#define MCLASS_ATTRIB_ID_PORT_BEACONING 0x001D /* Port Beaconing function */ +#define MCLASS_ATTRIB_ID_REG_ACCESS 0x001E /* Register Access function */ +#define MCLASS_ATTRIB_ID_JUMP_TO_ADDR 0x001F /* Jump To Address function */ +#define MCLASS_ATTRIB_ID_CALL_ROUTINE 0x0020 /* Call Routine function */ + +#define PM_ATTRIB_ID_PORT_COUNTERS 0x0012 /* PM Port Counters - used for ping */ + +#define VM_MAD_STATUS_SESSION_ID 0x100 /* Invalid session ID */ +#define VM_MAD_STATUS_NACK 0x200 /* NACK - device is busy */ +#define VM_MAD_STATUS_BUS_BUSY 0x400 /* Bus busy */ +#define VM_MAD_STATUS_BUS_HUNG 0x600 /* Bus hung */ +#define VM_MAD_STATUS_LOST_ARB 0x800 /* Lost ARB */ +#define VM_MAD_STATUS_TIMEOUT 0xA00 /* Timeout */ +#define VM_MAD_STATUS_SAVE_ERROR 0x1000 /* Save Error */ + +#define MEM_DATA_SIZE 200 +#define SYS_TBL_DATA_SIZE 200 +#define PORT_TBL_DATA_SIZE 200 +#define I2C_DATA_SIZE 1024 +#define QSFP_DATA_SIZE 200 +#define FWVERSION_SIZE 24 +#define NODE_DESC_SIZE 64 +#define DNAME_SIZE 256 +#define FNAME_SIZE 64 + +#define STL_EEPROM_COUNT 4 +#define STL_MAX_TOTAL_EEPROM_SIZE (256 * 1024) // This is the *total* size of all of the EEPROMs +#define STL_MAX_EEPROM_SIZE (64 * 1024) // This is the size of each individual EEPROM + +// TODO: Updates for PRR board specifics as needed +// TODO: Chassis EEPROM is 0xA8 +// TODO: Module EEPROM is 0xAA +// TODO: PS access through Management FPGA part at 0xE2 + +// TODO: Update PRR FW addresses: 0xA0, 0xA2, 0xA4, 0xA6 +#define STL_PRR_PRI_EEPROM1_ADDR (uint32)0x8160A000 +#define STL_PRR_SEC_EEPROM1_ADDR (uint32)0x8161A000 +#define STL_PRR_PRI_EEPROM2_ADDR (uint32)0x8160A200 +#define STL_PRR_SEC_EEPROM2_ADDR (uint32)0x8161A200 +#define STL_PRR_PRI_EEPROM3_ADDR (uint32)0x8160A400 +#define STL_PRR_SEC_EEPROM3_ADDR (uint32)0x8161A400 +#define STL_PRR_PRI_EEPROM4_ADDR (uint32)0x8160A600 +#define STL_PRR_SEC_EEPROM4_ADDR (uint32)0x8161A600 + +/* + * PRR VMA packets use 3 bits for Port LTP CRC mode + */ +#define STL_PRR_PORT_LTP_CRC_MODE_VMA_14 0x1 /* 14-bit LTP CRC mode VMA (optional) */ +#define STL_PRR_PORT_LTP_CRC_MODE_VMA_48 0x2 /* 48-bit LTP CRC mode VMA (optional) */ +#define STL_PRR_PORT_LTP_CRC_MODE_VMA_12_16_PER_LANE 0x4 /* 12/16-bit per lane LTP CRC mode VMA (optional) */ + +#define STL_PRR_EEPROM_INI_OFFSET (uint32)((256 * 1024) - 256) // reserved last 256 bytes in EEPROM potentially for module VPD +#define STL_PRR_I2C_LOCATION_ADDR 8 + +#define STL_PRR_BOARD_ID_MASK 0x1f +#define STL_PRR_BOARD_ID_EDGE48 0x04 +#define STL_PRR_BOARD_ID_EDGE24 0x05 +#define STL_PRR_BOARD_ID_HPE7K 0x09 + +#define I2C_OPASW_PRI_EEPROM_ADDR (uint32)0x8000A000 +#define I2C_OPASW_SEC_EEPROM_ADDR (uint32)0x8001A000 + +#define I2C_OPASW_VPD_EEPROM_ADDR (uint32)0x8160AA00 + +#define I2C_OPASW_PSOC_FAN_ADDR (uint32)0x8000C200 +#define I2C_OPASW_LTC2974_TEMP_ADDR (uint32)0x80009800 +#define I2C_OPASW_LTC2974_TEMP_OFFSET (uint16)0x008D + +#define I2C_OPASW_MGMT_FPGA_ADDR (uint32)0x80407200 // used for power supply access + +#define I2C_BOARD_ID_ADDR I2C_OPASW_MGMT_FPGA_ADDR + +#define I2C_OPASW_FAN_SPEED_OFFSET 0x00 +#define I2C_OPASW_FAN_CONFIG_OFFSET 0x02 +#define I2C_OPASW_FAN_ALARM_OFFSET 0x08 +#define I2C_OPASW_FAN_COUNT_OFFSET 0x16 + +#define I2C_OPASW_FAN_COUNT_VALUE 0x01 +#define I2C_OPASW_FAN_ALARM_VALUE 0x07 +#define I2C_OPASW_FAN_CONFIG_VALUE 0x23 +#define I2C_OPASW_FAN_SPEED_VALUE 0x2e + +#define I2C_OPASW_MGMT_FPGA_REG_RD 0x0B +#define I2C_OPASW_MGMT_FPGA_REG_WR 0x02 + +#define I2C_OPASW_BD_MGMT_FPGA_OFFSET 0x0000 +#define I2C_OPASW_PS_MGMT_FPGA_OFFSET 0x0021 +#define I2C_OPASW_PRR_ASIC_TEMP_MGMT_FPGA_OFFSET 0x00e8 +#define I2C_OPASW_MAX_QSFP_TEMP_MGMT_FPGA_OFFSET 0x00e6 +#define I2C_OPASW_TEMP_SENSOR_COUNT 3 + +#define PSU1_MGMT_FPGA_BIT_PRESENT 0 +#define PSU1_MGMT_FPGA_BIT_PWR_OK 1 +#define PSU2_MGMT_FPGA_BIT_PRESENT 2 +#define PSU2_MGMT_FPGA_BIT_PWR_OK 3 + +#define ASIC_VERSION_MEM_ADDR 0x000012D6 +#define QSFP_MGR_TEMPERATURE_MAX_DETECTED_MEM_ADDR 0x0002000E + +#define ASIC_ARCH_VERSION_MASK 0x00FF0000 +#define ASIC_ARCH_VERSION_SHFT 16 +#define ASIC_CHIP_NAME_MASK 0x0000FF00 +#define ASIC_CHIP_NAME_SHFT 8 +#define ASIC_CHIP_STEP_MASK 0x000000F0 +#define ASIC_CHIP_STEP_SHFT 4 +#define ASIC_CHIP_REV_MASK 0x0000000F +#define ASIC_CHIP_REV_SHFT 0 + +#define ASIC_CHIP_STEP_A 0 +#define ASIC_CHIP_STEP_B 1 +#define ASIC_CHIP_STEP_C 2 + +#define OPASW_MODULE 1 + +#define DEVICE_HDR_SIZE 7 // xinfo device header size +#define RECORD_HDR_SIZE 4 // xinfo record header size +#define FRU_TYPE_SIZE 1 // size for fru type field in fruInfo record +#define FRU_HANDLE_SIZE 1 // size for fru handle field in fruInfo record +#define FRUINFO_TYPE 2 // type code for fruInfo record +#define LEN_MASK 0x3f // mask for encoded length field +#define VPD_READ_SIZE 60 // size of VPD read block + +#define MAX_FAN_SPEED 25300 // 15% above the max operating speed of 22000 RPM +#define MIN_FAN_SPEED 5525 // 15% below the min operating speed of 6500 RPM +#define TOP_FAN_SPEED (0xff * 60) // absolute max if register remains at 0xff +#define OPASW_PSOC_FAN_CTRL_TACHS 6 +#define OPASW_PSOC_FAN1_ACTUAL_SPEED_OFFSET 4 + +#define MAX_VENDOR_KEY_LEN 16 + +#define NOJUMBOMAD 0 +#define JUMBOMAD 1 + +#define TEMP_STR_LENGTH 64 +#define OEM_HASH_SIGNER_START_ADDRESS 0x12c4 +#define OEM_HASH_SIGNER_END_ADDRESS 0x12cb +#define AUTHENTICATION_CONTROL_BIT_ADDRESS 0x12c3 + +/*********************** + * DATA TYPES + ***********************/ + +#include "iba/public/ipackon.h" + +/* Vendor Specific Management MAD formats */ +typedef struct _VENDOR_MAD_JUMBO { + MAD_COMMON common; /* Generic MAD Header */ + + uint8_t VendorData[STL_IBA_GS_DATASIZE]; /* Data Payload */ +} PACK_SUFFIX VENDOR_MAD_JUMBO, *PVENDOR_MAD_JUMBO; + +typedef struct _VENDOR_MAD { + MAD_COMMON common; /* Generic MAD Header */ + + uint8_t VendorData[256 - 24]; /* Data Payload */ +} PACK_SUFFIX VENDOR_MAD, *PVENDOR_MAD; + +#include "iba/public/ipackoff.h" + +typedef struct opasw_vendor_mad_s { + uint32_t data[56]; +} opasw_vendor_mad_t; + +typedef struct opasw_vendor_jmad_s { + uint32_t data[STL_IBA_GS_DATASIZE/4]; +} opasw_vendor_jmad_t; + +/* MAD data payload types */ + +typedef struct opasw_session_mgmt_s { + uint16 sessionID; +} opasw_session_mgmt_t; + +typedef struct opasw_s20_mem_access_s { + uint32 memoryAddr; + uint16 dataLen; + uint16 reserved; + uint8 memoryData[MEM_DATA_SIZE]; +} opasw_s20_mem_access_t; + +typedef struct opasw_ini_sys_table_access_s { + uint8 sysTableIndex; + uint8 reserved; + uint16 dataLen; + uint32 reserved2; + uint8 sysTableData[SYS_TBL_DATA_SIZE]; +} opasw_ini_sys_table_access_t; + +typedef struct opasw_ini_port_table_access_s { + uint8 portTableIndex; + uint8 reserved; + uint16 portNum; + uint32 dataLen; + uint8 portTableData[PORT_TBL_DATA_SIZE]; +} opasw_ini_port_table_access_t; + +typedef struct opasw_ini_descriptor_get_s { + uint32 sysMetaDataAddr; + uint32 sysMetaDataLen; + uint32 sysDataAddr; + uint32 sysDataLen; + uint32 portMetaDataAddr; + uint32 portMetaDataLen; + uint32 portDataAddr; + uint32 portDataLen; +} opasw_ini_descriptor_get_t; + +typedef struct opasw_i2c_access_s { + uint32 locationDescriptor; + uint16 dataLen; + uint16 dataOffset; + uint8 i2cData[I2C_DATA_SIZE]; + uint8 reserved2[16]; +} opasw_i2c_access_t; + +typedef struct opasw_qsfp_access_s { + uint32 qsfpNumber; + uint16 dataLen; + uint16 dataOffset; + uint8 qsfpData[QSFP_DATA_SIZE]; + uint8 reserved2[16]; +} opasw_qsfp_access_t; + +typedef struct opasw_fw_version_s { + uint8 fwVersion[FWVERSION_SIZE]; +} opasw_fw_version_t; + +typedef struct opasw_reboot_s { + uint32 delay; +} opasw_reboot_t; + +typedef struct opasw_save_config_s { + uint32 reserved; +} opasw_save_config_t; + +typedef struct opasw_dump_s { + uint32 reserved; +} opasw_dump_t; + +typedef struct opasw_led_status_s { + uint32 reserved; +} opasw_led_status_t; + +typedef struct opasw_port_beaconing_s { + uint32 reserved; +} opasw_port_beaconing_t; + +typedef struct opasw_register_access_s { + uint8 registerAddr; + uint8 shadowIndicator; + uint16 reserved; + uint32 registerValue; +} opasw_register_access_t; + +typedef struct opasw_jump_to_addr_s { + uint32 jumpAddr; + uint32 delay; +} opasw_jump_to_addr_t; + +typedef struct opasw_call_routine_s { + uint32 procedureAddr; + uint32 param1; + uint32 param2; + uint32 param3; + uint32 param4; + uint32 returnValue; +} opasw_call_routine_t; + +typedef struct vpd_fruInfo_rec_s { + char serialNum[256]; + char partNum[256]; + char model[256]; + char version[256]; + char mfgName[256]; + char productName[256]; + char mfgID[3]; + int mfgYear; + int mfgMonth; + int mfgDay; + int mfgHours; + int mfgMins; +} vpd_fruInfo_rec_t; + +typedef struct pm_port_counters_s { + uint8 reserved; + uint8 portSelect; +} pm_port_counters_t; + +static inline STL_LID get_dlid_from_path(IB_PATH_RECORD *path) +{ + if((ntoh64(path->DGID.Type.Global.InterfaceID) >> 40) == + OMGT_STL_OUI) + return ntoh64(path->DGID.Type.Global.InterfaceID) + & 0xFFFFFFFF; + return path->DLID; +} + +/*********************** + * FUNCTION PROTOTYPES + ***********************/ + +FSTATUS getDestPath(struct omgt_port *port, EUI64 destPortGuid, char *cmd, IB_PATH_RECORD *pathp); +uint16 getSessionID(struct omgt_port *port, IB_PATH_RECORD *path); +void releaseSession(struct omgt_port *port, IB_PATH_RECORD *path, uint16 sessionID); +FSTATUS getFwVersion(struct omgt_port *port, IB_PATH_RECORD *path, VENDOR_MAD *mad, uint16 sessionID, uint8 *fwVersion); +FSTATUS getVPDInfo(struct omgt_port *port, IB_PATH_RECORD *path, VENDOR_MAD *mad, uint16 sessionID, uint32 module, uint8 BoardID, vpd_fruInfo_rec_t *vpdInfo); +FSTATUS getFanSpeed(struct omgt_port *port, IB_PATH_RECORD *path, VENDOR_MAD *mad, uint16 sessionID, uint32 fanNum, uint32 *fanSpeed); +FSTATUS getTempReadings(struct omgt_port *port, IB_PATH_RECORD *path, VENDOR_MAD *mad, uint16 sessionID, char tempStrs[I2C_OPASW_TEMP_SENSOR_COUNT][TEMP_STR_LENGTH], uint8 BoardID); +FSTATUS getPowerSupplyStatus(struct omgt_port *port, IB_PATH_RECORD *path, VENDOR_MAD *mad, uint16 sessionID, uint32 psNum, uint32 *psStatus); +FSTATUS getAsicVersion(struct omgt_port *port, IB_PATH_RECORD *path, VENDOR_MAD *mad, uint16 sessionID, uint32 *asicVersion); +FSTATUS getMaxQsfpTemperatureMaxDetected(struct omgt_port *port, IB_PATH_RECORD *path, VENDOR_MAD *mad, uint16 sessionID, boolean *maxDetected); +FSTATUS getBoardID(struct omgt_port *port, IB_PATH_RECORD *path, VENDOR_MAD *mad, uint16 sessionID, uint8 *boardID); +FSTATUS doPingSwitch(struct omgt_port *port, IB_PATH_RECORD *path, STL_PERF_MAD *mad); +FSTATUS getOemHash(struct omgt_port *port, IB_PATH_RECORD *path, VENDOR_MAD *mad, uint16 sessionID, uint32 *oemhash, uint32 *acb); +FSTATUS getEMFWFileNames(struct omgt_port *port, IB_PATH_RECORD *path, uint16 sessionID, char *fwFileName, char *inibinFileName); +FSTATUS getBinaryHash(char *fwFileName, uint32 *binaryHash); + +void opaswDisplayBuffer(char *buffer, int dataLen); + +FSTATUS sendClassPortInfoMad(struct omgt_port *port, IB_PATH_RECORD *path, VENDOR_MAD *mad); +FSTATUS sendSessionMgmtGetMad(struct omgt_port *port, IB_PATH_RECORD *path, VENDOR_MAD *mad, uint16 *sessionID); +FSTATUS sendSessionMgmtReleaseMad(struct omgt_port *port, IB_PATH_RECORD *path, VENDOR_MAD *mad, uint16 sessionID); +FSTATUS sendMemAccessGetMad(struct omgt_port *port, IB_PATH_RECORD *path, VENDOR_MAD *mad, uint16 sessionID, uint32 memAddr, uint8 dataLen, uint8 *memData); +FSTATUS sendIniDescriptorGetMad(struct omgt_port *port, IB_PATH_RECORD *path, VENDOR_MAD *mad, uint16 sessionID, opasw_ini_descriptor_get_t *descriptors); +FSTATUS sendSysTableAccessGetMad(struct omgt_port *port, IB_PATH_RECORD *path, VENDOR_MAD *mad, uint16 sessionID, uint8 sysTableIndex, uint8 dataLen, uint8 *sysTableData); +FSTATUS sendSysTableAccessSetMad(struct omgt_port *port, IB_PATH_RECORD *path, VENDOR_MAD *mad, uint16 sessionID, uint8 sysTableIndex, uint8 dataLen, uint8 *sysTableData); +FSTATUS sendPortTableAccessSetMad(struct omgt_port *port, IB_PATH_RECORD *path, VENDOR_MAD *mad, uint16 sessionID, uint8 portTableIndex, uint16 portNum, uint8 dataLen, uint8 *portTableData); +FSTATUS sendGetFwVersionMad(struct omgt_port *port, IB_PATH_RECORD *path, VENDOR_MAD *mad, uint16 sessionID, uint8 *fwVersion); +FSTATUS sendRegisterAccessMad(struct omgt_port *port, IB_PATH_RECORD *path, VENDOR_MAD *mad, uint16 sessionID, uint8 regAddr, uint32 *regValue, int get); +FSTATUS sendRebootMad(struct omgt_port *port, IB_PATH_RECORD *path, uint16 sessionID, VENDOR_MAD *mad, uint32 delay); +FSTATUS sendI2CAccessMad(struct omgt_port *port, IB_PATH_RECORD *path, uint16 sessionID, void *mad, uint8 jumbo, uint8 method, int timeout, uint32 locationDescriptor, uint16 dataLen, + uint16 dataOffset, uint8 *data); +FSTATUS sendSTLPortStatsPort1Mad(struct omgt_port *port, IB_PATH_RECORD *path, STL_PERF_MAD *mad); +FSTATUS sendSaveConfigMad(struct omgt_port *port, IB_PATH_RECORD *path, VENDOR_MAD *mad, uint16 sessionID); +uint16 getMadStatus(VENDOR_MAD *mad); +void displayStatusMessage(uint16 madStatus); + +FSTATUS opaswEepromRW(struct omgt_port *port, IB_PATH_RECORD *path, uint16 sessionID, void *mad, int timeout, uint32 len, uint32 offset, uint8 *data, boolean writeData, boolean secondary); + +const char* StlPortLtpCrcModeVMAToText(uint16_t mode, char *str, size_t len); + +#endif /* _OPASW_COMMON_H_ */ diff --git a/IbaTools/opasw/opaswcommon/opaswcommonMads.c b/IbaTools/opasw/opaswcommon/opaswcommonMads.c new file mode 100644 index 0000000..b4fe45e --- /dev/null +++ b/IbaTools/opasw/opaswcommon/opaswcommonMads.c @@ -0,0 +1,1209 @@ +/* BEGIN_ICS_COPYRIGHT7 **************************************** + +Copyright (c) 2015-2018, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT7 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +#include +#include +#include +#include + +/* work around conflicting names */ + +#include "iba/stl_types.h" +#include "iba/stl_sm_priv.h" +#include "iba/stl_pm.h" +#include "iba/stl_helper.h" +#include "opamgt_priv.h" +#include +#include "opaswcommon.h" + +#define NEED_TO_RETRY(madStatus) ((madStatus == MAD_STATUS_BUSY) || (madStatus == VM_MAD_STATUS_NACK) || (madStatus == VM_MAD_STATUS_BUS_BUSY) || (madStatus == VM_MAD_STATUS_BUS_HUNG) || (madStatus == VM_MAD_STATUS_LOST_ARB) || (madStatus == VM_MAD_STATUS_TIMEOUT)) + +// globals + +static int g_transID = 0x0114; + +extern int g_debugMode; +extern int g_verbose; + +FSTATUS sendClassPortInfoMad(struct omgt_port *port, + IB_PATH_RECORD *path, + VENDOR_MAD *mad) +{ + FSTATUS status = FSUCCESS; + uint16 madStatus; + // Determine which pkey to use (full or limited) + uint16_t pkey = omgt_get_mgmt_pkey(port, get_dlid_from_path(path), 0); + if (pkey==0) { + fprintf(stderr, "ERROR: Local port does not have management privileges\n"); + return (FPROTECTION); + } + + struct omgt_mad_addr addr = { + sl : path->u2.s.SL, + lid : path->DLID, + qpn : GSI_QUEUE_PAIR, + qkey : QP1_WELL_KNOWN_Q_KEY, + pkey : pkey, + }; + size_t recv_size; + + // MAD header + memset(mad, 0, sizeof(VENDOR_MAD)); + mad->common.BaseVersion = STL_BASE_VERSION; + mad->common.MgmtClass = MCLASS_VENDOR_OPASW; + mad->common.ClassVersion = STL_VENDOR_SPEC_CLASS_VERSION; + mad->common.mr.AsReg8 = 0; + mad->common.mr.s.Method = MMTHD_GET; +#ifdef IB_STACK_IBACCESS + mad->common.TransactionID = (++g_transID)<<24; +#else + mad->common.TransactionID = (++g_transID) & 0xffffffff; +#endif + mad->common.AttributeID = MCLASS_ATTRIB_ID_CLASSPORTINFO; + mad->common.AttributeModifier = 0; + + BSWAP_MAD_HEADER((MAD*)mad); + + // Send mad & recv response + + if (g_debugMode) { + printf("send buffer for ClassPortInfo:\n"); + opaswDisplayBuffer((char *)mad, sizeof(VENDOR_MAD)); + } + + recv_size = sizeof(*mad); + status = omgt_send_recv_mad_no_alloc(port, + (uint8_t *)mad, sizeof(*mad), + &addr, + (uint8_t *)mad, &recv_size, + RESP_WAIT_TIME, + DEF_RETRIES); + + if (g_debugMode) { + printf("recv buffer for ClassPortInfo rsp:\n"); + opaswDisplayBuffer((char *)mad, sizeof(VENDOR_MAD)); + } + if (FSUCCESS != status) { + fprintf(stderr, "Error: Failed to send MAD or receive response MAD status is %d\n", status); + return(status); + } + if ((madStatus = getMadStatus(mad)) > 0) { + displayStatusMessage(madStatus); + return(status = FINVALID_OPERATION); + } + + return(status); +} + +FSTATUS sendSessionMgmtGetMad(struct omgt_port *port, + IB_PATH_RECORD *path, + VENDOR_MAD *mad, + uint16 *sessionID) +{ + FSTATUS status = FSUCCESS; + opasw_vendor_mad_t *vendorData; + opasw_session_mgmt_t *sessionMgmtDataP; + + // Determine which pkey to use (full or limited) + uint16_t pkey = omgt_get_mgmt_pkey(port, get_dlid_from_path(path), 0); + if (pkey==0) { + fprintf(stderr, "ERROR: Local port does not have management privileges\n"); + return (FPROTECTION); + } + + struct omgt_mad_addr addr = { + sl : path->u2.s.SL, + lid : path->DLID, + qpn : GSI_QUEUE_PAIR, + qkey : QP1_WELL_KNOWN_Q_KEY, + pkey : pkey, + }; + size_t recv_size; + + // MAD header + memset(mad, 0, sizeof(VENDOR_MAD)); + mad->common.BaseVersion = STL_BASE_VERSION; + mad->common.MgmtClass = MCLASS_VENDOR_OPASW; + mad->common.ClassVersion = STL_VENDOR_SPEC_CLASS_VERSION; + mad->common.mr.AsReg8 = 0; + mad->common.mr.s.Method = MMTHD_GET; +#ifdef IB_STACK_IBACCESS + mad->common.TransactionID = (++g_transID)<<24; +#else + mad->common.TransactionID = (++g_transID) & 0xffffffff; +#endif + mad->common.AttributeID = MCLASS_ATTRIB_ID_SESSION_MGMT; + mad->common.AttributeModifier = 0; + + BSWAP_MAD_HEADER((MAD*)mad); + + // Vendor data + vendorData = (opasw_vendor_mad_t *)mad->VendorData; + sessionMgmtDataP = (opasw_session_mgmt_t *)&vendorData->data[0]; + + // Send mad & recv response + + if (g_debugMode) { + printf("send buffer for session mgmt:\n"); + opaswDisplayBuffer((char *)mad, sizeof(VENDOR_MAD)); + } + + recv_size = sizeof(*mad); + status = omgt_send_recv_mad_no_alloc(port, + (uint8_t *)mad, sizeof(*mad), + &addr, + (uint8_t *)mad, &recv_size, + RESP_WAIT_TIME, + DEF_RETRIES); + + if (g_debugMode) { + printf("recv buffer for session mgmt rsp:\n"); + opaswDisplayBuffer((char *)mad, sizeof(VENDOR_MAD)); + } + if (FSUCCESS != status) { + fprintf(stderr, "Error: Failed to send MAD or receive response MAD status is %d\n", status); + return(status); + } + + *sessionID = ntoh16(sessionMgmtDataP->sessionID); + return(status); +} + +FSTATUS sendSessionMgmtReleaseMad(struct omgt_port *port, + IB_PATH_RECORD *path, + VENDOR_MAD *mad, + uint16 sessionID) +{ + FSTATUS status = FSUCCESS; + opasw_vendor_mad_t *vendorData; + opasw_session_mgmt_t *sessionMgmtDataP; + uint16 madStatus; + + // Determine which pkey to use (full or limited) + uint16_t pkey = omgt_get_mgmt_pkey(port, get_dlid_from_path(path), 0); + if (pkey==0) { + fprintf(stderr, "ERROR: Local port does not have management privileges\n"); + return (FPROTECTION); + } + + struct omgt_mad_addr addr = { + sl : path->u2.s.SL, + lid : path->DLID, + qpn : GSI_QUEUE_PAIR, + qkey : QP1_WELL_KNOWN_Q_KEY, + pkey : pkey, + }; + size_t recv_size; + + // MAD header + memset(mad, 0, sizeof(VENDOR_MAD)); + mad->common.BaseVersion = STL_BASE_VERSION; + mad->common.MgmtClass = MCLASS_VENDOR_OPASW; + mad->common.ClassVersion = STL_VENDOR_SPEC_CLASS_VERSION; + mad->common.mr.AsReg8 = 0; + mad->common.mr.s.Method = MMTHD_SET; +#ifdef IB_STACK_IBACCESS + mad->common.TransactionID = (++g_transID)<<24; +#else + mad->common.TransactionID = (++g_transID) & 0xffffffff; +#endif + mad->common.AttributeID = MCLASS_ATTRIB_ID_SESSION_MGMT; + mad->common.AttributeModifier = sessionID; + + BSWAP_MAD_HEADER((MAD*)mad); + + // Vendor data + vendorData = (opasw_vendor_mad_t *)mad->VendorData; + sessionMgmtDataP = (opasw_session_mgmt_t *)&vendorData->data[0]; + sessionMgmtDataP->sessionID = sessionID; + + // Send mad & recv response + + if (g_debugMode) { + printf("send buffer for session release:\n"); + opaswDisplayBuffer((char *)mad, sizeof(VENDOR_MAD)); + } + + recv_size = sizeof(*mad); + status = omgt_send_recv_mad_no_alloc(port, + (uint8_t *)mad, sizeof(*mad), + &addr, + (uint8_t *)mad, &recv_size, + RESP_WAIT_TIME, + DEF_RETRIES); + + if (g_debugMode) { + printf("recv buffer for session release rsp:\n"); + opaswDisplayBuffer((char *)mad, sizeof(VENDOR_MAD)); + } + if (FSUCCESS != status) { + fprintf(stderr, "Error: Failed to send MAD or receive response MAD status is %d\n", status); + return(status); + } + if ((madStatus = getMadStatus(mad)) > 0) { + displayStatusMessage(madStatus); + return(status = FINVALID_OPERATION); + } + + return(status); +} + +FSTATUS sendMemAccessGetMad(struct omgt_port *port, + IB_PATH_RECORD *path, + VENDOR_MAD *mad, + uint16 sessionID, + uint32 memAddr, + uint8 dataLen, + uint8 *memData) +{ + FSTATUS status = FSUCCESS; + opasw_vendor_mad_t *vendorData; + opasw_s20_mem_access_t *memoryDataP; + uint16 madStatus; + + // Determine which pkey to use (full or limited) + uint16_t pkey = omgt_get_mgmt_pkey(port, get_dlid_from_path(path), 0); + if (pkey==0) { + fprintf(stderr, "ERROR: Local port does not have management privileges\n"); + return (FPROTECTION); + } + + struct omgt_mad_addr addr = { + sl : path->u2.s.SL, + lid : path->DLID, + qpn : GSI_QUEUE_PAIR, + qkey : QP1_WELL_KNOWN_Q_KEY, + pkey : pkey, + }; + size_t recv_size; + + // MAD header + memset(mad, 0, sizeof(VENDOR_MAD)); + mad->common.BaseVersion = STL_BASE_VERSION; + mad->common.MgmtClass = MCLASS_VENDOR_OPASW; + mad->common.ClassVersion = STL_VENDOR_SPEC_CLASS_VERSION; + mad->common.mr.AsReg8 = 0; + mad->common.mr.s.Method = MMTHD_GET; +#ifdef IB_STACK_IBACCESS + mad->common.TransactionID = (++g_transID)<<24; +#else + mad->common.TransactionID = (++g_transID) & 0xffffffff; +#endif + mad->common.AttributeID = MCLASS_ATTRIB_ID_S20_MEM_ACCESS; + mad->common.AttributeModifier = sessionID; + + BSWAP_MAD_HEADER((MAD*)mad); + + // Vendor data + vendorData = (opasw_vendor_mad_t *)mad->VendorData; + memoryDataP = (opasw_s20_mem_access_t *)&vendorData->data[0]; + memoryDataP->memoryAddr = ntoh32(memAddr); + memoryDataP->dataLen = ntoh16(dataLen); + + // Send mad & recv response + + if (g_debugMode) { + printf("send buffer for mem access:\n"); + opaswDisplayBuffer((char *)mad, sizeof(VENDOR_MAD)); + } + + recv_size = sizeof(*mad); + status = omgt_send_recv_mad_no_alloc(port, + (uint8_t *)mad, sizeof(*mad), + &addr, + (uint8_t *)mad, &recv_size, + RESP_WAIT_TIME, + DEF_RETRIES); + + if (g_debugMode) { + printf("recv buffer for mem access rsp:\n"); + opaswDisplayBuffer((char *)mad, sizeof(VENDOR_MAD)); + } + if (FSUCCESS != status) { + fprintf(stderr, "Error: Failed to send MAD or receive response MAD status is %d\n", status); + return(status); + } + if ((madStatus = getMadStatus(mad)) > 0) { + displayStatusMessage(madStatus); + return(status = FINVALID_OPERATION); + } + + // copy the data + + memcpy(memData, memoryDataP->memoryData, dataLen); + + return(status); + +} + +FSTATUS sendSysTableAccessGetMad(struct omgt_port *port, + IB_PATH_RECORD *path, + VENDOR_MAD *mad, + uint16 sessionID, + uint8 sysTableIndex, + uint8 dataLen, + uint8 *sysTableData) +{ + FSTATUS status = FSUCCESS; + opasw_vendor_mad_t *vendorData; + opasw_ini_sys_table_access_t *sysTableP; + uint16 madStatus; + + // Determine which pkey to use (full or limited) + uint16_t pkey = omgt_get_mgmt_pkey(port, get_dlid_from_path(path), 0); + if (pkey==0) { + fprintf(stderr, "ERROR: Local port does not have management privileges\n"); + return (FPROTECTION); + } + + struct omgt_mad_addr addr = { + sl : path->u2.s.SL, + lid : path->DLID, + qpn : GSI_QUEUE_PAIR, + qkey : QP1_WELL_KNOWN_Q_KEY, + pkey : pkey, + }; + size_t recv_size; + + // MAD header + memset(mad, 0, sizeof(VENDOR_MAD)); + mad->common.BaseVersion = STL_BASE_VERSION; + mad->common.MgmtClass = MCLASS_VENDOR_OPASW; + mad->common.ClassVersion = STL_VENDOR_SPEC_CLASS_VERSION; + mad->common.mr.AsReg8 = 0; +#if GET + mad->common.mr.s.Method = MMTHD_GET; +#else + mad->common.mr.s.Method = MMTHD_SET; +#endif +#ifdef IB_STACK_IBACCESS + mad->common.TransactionID = (++g_transID)<<24; +#else + mad->common.TransactionID = (++g_transID) & 0xffffffff; +#endif + mad->common.AttributeID = MCLASS_ATTRIB_ID_INI_SYS_TABLE_ACC; + mad->common.AttributeModifier = sessionID; + + BSWAP_MAD_HEADER((MAD*)mad); + + // Vendor data + vendorData = (opasw_vendor_mad_t *)mad->VendorData; + sysTableP = (opasw_ini_sys_table_access_t *)&vendorData->data[0]; + sysTableP->sysTableIndex = sysTableIndex; + sysTableP->dataLen = ntoh16(dataLen); + memcpy(sysTableP->sysTableData, sysTableData, dataLen); + + // Send mad & recv response + + if (g_debugMode) { + printf("send buffer for in sys table access:\n"); + opaswDisplayBuffer((char *)mad, sizeof(VENDOR_MAD)); + } + + recv_size = sizeof(*mad); + status = omgt_send_recv_mad_no_alloc(port, + (uint8_t *)mad, sizeof(*mad), + &addr, + (uint8_t *)mad, &recv_size, + RESP_WAIT_TIME, + DEF_RETRIES); + + if (g_debugMode) { + printf("recv buffer for in sys table access rsp:\n"); + opaswDisplayBuffer((char *)mad, sizeof(VENDOR_MAD)); + } + if (FSUCCESS != status) { + fprintf(stderr, "Error: Failed to send MAD or receive response MAD status is %d\n", status); + return(status); + } + if ((madStatus = getMadStatus(mad)) > 0) { + displayStatusMessage(madStatus); + return(status = FINVALID_OPERATION); + } + +#if GET + // copy the data + memcpy(sysTableData, sysTableP->sysTableData, dataLen); +#endif + + return(status); + +} + +FSTATUS sendSysTableAccessSetMad(struct omgt_port *port, + IB_PATH_RECORD *path, + VENDOR_MAD *mad, + uint16 sessionID, + uint8 sysTableIndex, + uint8 dataLen, + uint8 *sysTableData) +{ + FSTATUS status = FSUCCESS; + opasw_vendor_mad_t *vendorData; + opasw_ini_sys_table_access_t *sysTableP; + uint16 madStatus; + + // Determine which pkey to use (full or limited) + uint16_t pkey = omgt_get_mgmt_pkey(port, get_dlid_from_path(path), 0); + if (pkey==0) { + fprintf(stderr, "ERROR: Local port does not have management privileges\n"); + return (FPROTECTION); + } + + struct omgt_mad_addr addr = { + sl : path->u2.s.SL, + lid : path->DLID, + qpn : GSI_QUEUE_PAIR, + qkey : QP1_WELL_KNOWN_Q_KEY, + pkey : pkey, + }; + size_t recv_size; + + // MAD header + memset(mad, 0, sizeof(VENDOR_MAD)); + mad->common.BaseVersion = STL_BASE_VERSION; + mad->common.MgmtClass = MCLASS_VENDOR_OPASW; + mad->common.ClassVersion = STL_VENDOR_SPEC_CLASS_VERSION; + mad->common.mr.AsReg8 = 0; + mad->common.mr.s.Method = MMTHD_SET; +#ifdef IB_STACK_IBACCESS + mad->common.TransactionID = (++g_transID)<<24; +#else + mad->common.TransactionID = (++g_transID) & 0xffffffff; +#endif + mad->common.AttributeID = MCLASS_ATTRIB_ID_INI_SYS_TABLE_ACC; + mad->common.AttributeModifier = sessionID; + + BSWAP_MAD_HEADER((MAD*)mad); + + // Vendor data + vendorData = (opasw_vendor_mad_t *)mad->VendorData; + sysTableP = (opasw_ini_sys_table_access_t *)&vendorData->data[0]; + sysTableP->sysTableIndex = sysTableIndex; + sysTableP->dataLen = ntoh16(dataLen); + memcpy(sysTableP->sysTableData, sysTableData, dataLen); + + // Send mad & recv response + + // opaswDisplayBuffer((char *)mad, sizeof(VENDOR_MAD)); + + recv_size = sizeof(*mad); + status = omgt_send_recv_mad_no_alloc(port, + (uint8_t *)mad, sizeof(*mad), + &addr, + (uint8_t *)mad, &recv_size, + RESP_WAIT_TIME, + DEF_RETRIES); + + if (FSUCCESS != status) { + fprintf(stderr, "Error: Failed to send MAD or receive response MAD status is %d\n", status); + return(status); + } + if ((madStatus = getMadStatus(mad)) > 0) { + displayStatusMessage(madStatus); + return(status = FINVALID_OPERATION); + } + + return(status); + +} +FSTATUS sendPortTableAccessSetMad(struct omgt_port *port, + IB_PATH_RECORD *path, + VENDOR_MAD *mad, + uint16 sessionID, + uint8 portTableIndex, + uint16 portNum, + uint8 dataLen, + uint8 *portTableData) +{ + FSTATUS status = FSUCCESS; + opasw_vendor_mad_t *vendorData; + opasw_ini_port_table_access_t *portTableP; + uint16 madStatus; + + // Determine which pkey to use (full or limited) + uint16_t pkey = omgt_get_mgmt_pkey(port, get_dlid_from_path(path), 0); + if (pkey==0) { + fprintf(stderr, "ERROR: Local port does not have management privileges\n"); + return (FPROTECTION); + } + + struct omgt_mad_addr addr = { + sl : path->u2.s.SL, + lid : path->DLID, + qpn : GSI_QUEUE_PAIR, + qkey : QP1_WELL_KNOWN_Q_KEY, + pkey : pkey, + }; + size_t recv_size; + + // MAD header + memset(mad, 0, sizeof(VENDOR_MAD)); + mad->common.BaseVersion = STL_BASE_VERSION; + mad->common.MgmtClass = MCLASS_VENDOR_OPASW; + mad->common.ClassVersion = STL_VENDOR_SPEC_CLASS_VERSION; + mad->common.mr.AsReg8 = 0; +#if GET + mad->common.mr.s.Method = MMTHD_GET; +#else + mad->common.mr.s.Method = MMTHD_SET; +#endif +#ifdef IB_STACK_IBACCESS + mad->common.TransactionID = (++g_transID)<<24; +#else + mad->common.TransactionID = (++g_transID) & 0xffffffff; +#endif + mad->common.AttributeID = MCLASS_ATTRIB_ID_INI_PORT_TABLE_ACC; + mad->common.AttributeModifier = sessionID; + + BSWAP_MAD_HEADER((MAD*)mad); + + // Vendor data + vendorData = (opasw_vendor_mad_t *)mad->VendorData; + portTableP = (opasw_ini_port_table_access_t *)&vendorData->data[0]; + portTableP->portTableIndex = portTableIndex; + portTableP->portNum = ntoh16(portNum); + portTableP->dataLen = ntoh32(dataLen); + memcpy(portTableP->portTableData, portTableData, dataLen); + + // Send mad & recv response + + if (g_debugMode) { + printf("send buffer for port table access:\n"); + opaswDisplayBuffer((char *)mad, sizeof(VENDOR_MAD)); + } + + recv_size = sizeof(*mad); + status = omgt_send_recv_mad_no_alloc(port, + (uint8_t *)mad, sizeof(*mad), + &addr, + (uint8_t *)mad, &recv_size, + RESP_WAIT_TIME, + DEF_RETRIES); + + if (g_debugMode) { + printf("recv buffer for port table access rsp:\n"); + opaswDisplayBuffer((char *)mad, sizeof(VENDOR_MAD)); + } + if (FSUCCESS != status) { + fprintf(stderr, "Error: Failed to send MAD or receive response MAD status is %d\n", status); + return(status); + } + if ((madStatus = getMadStatus(mad)) > 0) { + displayStatusMessage(madStatus); + return(status = FINVALID_OPERATION); + } + + return(status); + +} + +FSTATUS sendIniDescriptorGetMad(struct omgt_port *port, + IB_PATH_RECORD *path, + VENDOR_MAD *mad, + uint16 sessionID, + opasw_ini_descriptor_get_t *descriptors) +{ + FSTATUS status = FSUCCESS; + opasw_vendor_mad_t *vendorData; + opasw_ini_descriptor_get_t *iniDescriptorData; + uint16 madStatus; + + // Determine which pkey to use (full or limited) + uint16_t pkey = omgt_get_mgmt_pkey(port, get_dlid_from_path(path), 0); + if (pkey==0) { + fprintf(stderr, "ERROR: Local port does not have management privileges\n"); + return (FPROTECTION); + } + + struct omgt_mad_addr addr = { + sl : path->u2.s.SL, + lid : path->DLID, + qpn : GSI_QUEUE_PAIR, + qkey : QP1_WELL_KNOWN_Q_KEY, + pkey : pkey, + }; + size_t recv_size; + + // MAD header + memset(mad, 0, sizeof(VENDOR_MAD)); + mad->common.BaseVersion = STL_BASE_VERSION; + mad->common.MgmtClass = MCLASS_VENDOR_OPASW; + mad->common.ClassVersion = STL_VENDOR_SPEC_CLASS_VERSION; + mad->common.mr.AsReg8 = 0; + mad->common.mr.s.Method = MMTHD_GET; +#ifdef IB_STACK_IBACCESS + mad->common.TransactionID = (++g_transID)<<24; +#else + mad->common.TransactionID = (++g_transID) & 0xffffffff; +#endif + mad->common.AttributeID = MCLASS_ATTRIB_ID_INI_DESCR_GET; + mad->common.AttributeModifier = sessionID; + + BSWAP_MAD_HEADER((MAD*)mad); + + // Vendor data + vendorData = (opasw_vendor_mad_t *)mad->VendorData; + iniDescriptorData = (opasw_ini_descriptor_get_t *)&vendorData->data[0]; + + // Send mad & recv response + + // opaswDisplayBuffer((char *)mad, sizeof(VENDOR_MAD)); + recv_size = sizeof(*mad); + status = omgt_send_recv_mad_no_alloc(port, + (uint8_t *)mad, sizeof(*mad), + &addr, + (uint8_t *)mad, &recv_size, + RESP_WAIT_TIME, + DEF_RETRIES); + + if (FSUCCESS != status) { + fprintf(stderr, "Error: Failed to send MAD or receive response MAD status is %d\n", status); + return(status); + } + if ((madStatus = getMadStatus(mad)) > 0) { + displayStatusMessage(madStatus); + return(status = FINVALID_OPERATION); + } + + // harvest the descriptors - need to byte swap + + descriptors->sysMetaDataAddr = ntoh32(iniDescriptorData->sysMetaDataAddr); + descriptors->sysMetaDataLen = ntoh32(iniDescriptorData->sysMetaDataLen); + descriptors->sysDataAddr = ntoh32(iniDescriptorData->sysDataAddr); + descriptors->sysDataLen = ntoh32(iniDescriptorData->sysDataLen); + descriptors->portMetaDataAddr = ntoh32(iniDescriptorData->portMetaDataAddr); + descriptors->portMetaDataLen = ntoh32(iniDescriptorData->portMetaDataLen); + descriptors->portDataAddr = ntoh32(iniDescriptorData->portDataAddr); + descriptors->portDataLen = ntoh32(iniDescriptorData->portDataLen); +#if 0 + descriptors->rxPresetAddr = ntoh32(iniDescriptorData->rxPresetAddr); + descriptors->rxPresetLen = ntoh32(iniDescriptorData->rxPresetLen); + descriptors->txPresetAddr = ntoh32(iniDescriptorData->txPresetAddr); + descriptors->txPresetLen = ntoh32(iniDescriptorData->txPresetLen); + descriptors->qsfpAttenuationAddr = ntoh32(iniDescriptorData->qsfpAttenuationAddr); + descriptors->qsfpAttenuationLen = ntoh32(iniDescriptorData->qsfpAttenuationLen); + descriptors->variableSettingsAddr = ntoh32(iniDescriptorData->variableSettingsAddr); + descriptors->variableSettingsLen = ntoh32(iniDescriptorData->variableSettingsLen); +#endif + + + return(status); + +} + +FSTATUS sendGetFwVersionMad(struct omgt_port *port, + IB_PATH_RECORD *path, + VENDOR_MAD *mad, + uint16 sessionID, + uint8 *fwVersion) +{ + FSTATUS status = FSUCCESS; + opasw_vendor_mad_t *vendorData; + opasw_fw_version_t *fwVersionP; + uint16 madStatus; + + // Determine which pkey to use (full or limited) + uint16_t pkey = omgt_get_mgmt_pkey(port, get_dlid_from_path(path), 0); + if (pkey==0) { + fprintf(stderr, "ERROR: Local port does not have management privileges\n"); + return (FPROTECTION); + } + + struct omgt_mad_addr addr = { + sl : path->u2.s.SL, + lid : path->DLID, + qpn : GSI_QUEUE_PAIR, + qkey : QP1_WELL_KNOWN_Q_KEY, + pkey : pkey, + }; + size_t recv_size; + + // MAD header + memset(mad, 0, sizeof(VENDOR_MAD)); + mad->common.BaseVersion = STL_BASE_VERSION; + mad->common.MgmtClass = MCLASS_VENDOR_OPASW; + mad->common.ClassVersion = STL_VENDOR_SPEC_CLASS_VERSION; + mad->common.mr.AsReg8 = 0; + mad->common.mr.s.Method = MMTHD_GET; +#ifdef IB_STACK_IBACCESS + mad->common.TransactionID = (++g_transID)<<24; +#else + mad->common.TransactionID = (++g_transID) & 0xffffffff; +#endif + mad->common.AttributeID = MCLASS_ATTRIB_ID_FW_VERSION; + mad->common.AttributeModifier = sessionID; + + BSWAP_MAD_HEADER((MAD*)mad); + + // Vendor data + vendorData = (opasw_vendor_mad_t *)mad->VendorData; + fwVersionP = (opasw_fw_version_t *)&vendorData->data[0]; + + // Send mad & recv response + + // opaswDisplayBuffer((char *)mad, sizeof(VENDOR_MAD)); + recv_size = sizeof(*mad); + status = omgt_send_recv_mad_no_alloc(port, + (uint8_t *)mad, sizeof(*mad), + &addr, + (uint8_t *)mad, &recv_size, + RESP_WAIT_TIME, + DEF_RETRIES); + + if (FSUCCESS != status) { + fprintf(stderr, "Error: Failed to send MAD or receive response MAD status is %d\n", status); + return(status); + } + if ((madStatus = getMadStatus(mad)) > 0) { + displayStatusMessage(madStatus); + return(status = FINVALID_OPERATION); + } + + // copy the fw version from the MAD + memcpy(fwVersion, fwVersionP->fwVersion, FWVERSION_SIZE); + + return(status); +} + +FSTATUS sendRegisterAccessMad(struct omgt_port *port, + IB_PATH_RECORD *path, + VENDOR_MAD *mad, + uint16 sessionID, + uint8 regAddr, + uint32 *regValue, + int get) +{ + FSTATUS status = FSUCCESS; + opasw_vendor_mad_t *vendorData; + opasw_register_access_t *regAccessP; + uint16 madStatus; + + // Determine which pkey to use (full or limited) + uint16_t pkey = omgt_get_mgmt_pkey(port, get_dlid_from_path(path), 0); + if (pkey==0) { + fprintf(stderr, "ERROR: Local port does not have management privileges\n"); + return (FPROTECTION); + } + + struct omgt_mad_addr addr = { + sl : path->u2.s.SL, + lid : path->DLID, + qpn : GSI_QUEUE_PAIR, + qkey : QP1_WELL_KNOWN_Q_KEY, + pkey : pkey, + }; + size_t recv_size; + + // MAD header + memset(mad, 0, sizeof(VENDOR_MAD)); + mad->common.BaseVersion = STL_BASE_VERSION; + mad->common.MgmtClass = MCLASS_VENDOR_OPASW; + mad->common.ClassVersion = STL_VENDOR_SPEC_CLASS_VERSION; + mad->common.mr.AsReg8 = 0; + if (get) + mad->common.mr.s.Method = MMTHD_GET; + else + mad->common.mr.s.Method = MMTHD_SET; +#ifdef IB_STACK_IBACCESS + mad->common.TransactionID = (++g_transID)<<24; +#else + mad->common.TransactionID = (++g_transID) & 0xffffffff; +#endif + mad->common.AttributeID = MCLASS_ATTRIB_ID_REG_ACCESS; + mad->common.AttributeModifier = sessionID; + + BSWAP_MAD_HEADER((MAD*)mad); + + // Vendor data + vendorData = (opasw_vendor_mad_t *)mad->VendorData; + regAccessP = (opasw_register_access_t *)&vendorData->data[0]; + regAccessP->registerAddr = regAddr; + if (!get) + regAccessP->registerValue = *regValue; + + // Send mad & recv response + + // opaswDisplayBuffer((char *)mad, sizeof(VENDOR_MAD)); + recv_size = sizeof(*mad); + status = omgt_send_recv_mad_no_alloc(port, + (uint8_t *)mad, sizeof(*mad), + &addr, + (uint8_t *)mad, &recv_size, + RESP_WAIT_TIME, + DEF_RETRIES); + + if (FSUCCESS != status) { + fprintf(stderr, "Error: Failed to send MAD or receive response MAD status is %d\n", status); + return(status); + } + if ((madStatus = getMadStatus(mad)) > 0) { + displayStatusMessage(madStatus); + return(status = FINVALID_OPERATION); + } + + if (get) + *regValue = regAccessP->registerValue; + + return(status); +} + +FSTATUS sendRebootMad(struct omgt_port *port, + IB_PATH_RECORD *path, + uint16 sessionID, + VENDOR_MAD *mad, + uint32 delay) +{ + FSTATUS status; + opasw_vendor_mad_t *vendorData; + opasw_reboot_t *rebootData; +#ifndef RESET_NORSP + uint16 madStatus; +#endif + + // Determine which pkey to use (full or limited) + uint16_t pkey = omgt_get_mgmt_pkey(port, get_dlid_from_path(path), 0); + if (pkey==0) { + fprintf(stderr, "ERROR: Local port does not have management privileges\n"); + return (FPROTECTION); + } + + struct omgt_mad_addr addr = { + sl : path->u2.s.SL, + lid : path->DLID, + qpn : GSI_QUEUE_PAIR, + qkey : QP1_WELL_KNOWN_Q_KEY, + pkey : pkey, + }; + size_t recv_size; + + // MAD header + memset(mad, 0, sizeof(VENDOR_MAD)); + mad->common.BaseVersion = STL_BASE_VERSION; + mad->common.MgmtClass = MCLASS_VENDOR_OPASW; + mad->common.ClassVersion = STL_VENDOR_SPEC_CLASS_VERSION; + mad->common.mr.AsReg8 = 0; + mad->common.mr.s.Method = MMTHD_SET; +#ifdef IB_STACK_IBACCESS + mad->common.TransactionID = (++g_transID)<<24; +#else + mad->common.TransactionID = (++g_transID) & 0xffffffff; +#endif + mad->common.AttributeID = MCLASS_ATTRIB_ID_REBOOT; + mad->common.AttributeModifier = sessionID; + + BSWAP_MAD_HEADER((MAD*)mad); + + // Vendor data + vendorData = (opasw_vendor_mad_t *)mad->VendorData; + rebootData = (opasw_reboot_t *)&vendorData->data[0]; + rebootData->delay = ntoh32(delay); + + // Send mad & recv response + + if (g_debugMode) { + printf("send buffer for reboot:\n"); + opaswDisplayBuffer((char *)mad, sizeof(VENDOR_MAD)); + } +#ifndef RESET_NORSP + recv_size = sizeof(*mad); + status = omgt_send_recv_mad_no_alloc(port, + (uint8_t *)mad, sizeof(*mad), + &addr, + (uint8_t *)mad, &recv_size, + RESP_WAIT_TIME, + DEF_RETRIES); + if (g_debugMode) { + printf("recv buffer for reboot rsp:\n"); + opaswDisplayBuffer((char *)mad, sizeof(VENDOR_MAD)); + } + if (FSUCCESS != status) { + fprintf(stderr, "Error: Failed to send MAD or receive response MAD status is %d\n", status); + return(status); + } + if ((madStatus = getMadStatus(mad)) > 0) { + displayStatusMessage(madStatus); + return(status = FINVALID_OPERATION); + } +#else + recv_size = sizeof(*mad); + status = omgt_send_recv_mad_no_alloc(port, + (uint8_t *)mad, sizeof(*mad), + &addr, + (uint8_t *)mad, &recv_size, + RESP_WAIT_TIME, + DEF_RETRIES); + + if (FSUCCESS != status) { + fprintf(stderr, "Error: Failed to send MAD status is %d\n", status); + return(status); + } +#endif + + return(status); +} + +FSTATUS sendI2CAccessMad(struct omgt_port *port, + IB_PATH_RECORD *path, + uint16 sessionID, + void *mp, + uint8 jumbo, /* set to 1 if mad is a jumbo mad */ + uint8 method, + int timeout, + uint32 locationDescriptor, + uint16 dataLen, + uint16 dataOffset, + uint8 *data) +{ + FSTATUS status = FSUCCESS; + opasw_vendor_mad_t *vendorData; + opasw_i2c_access_t *i2cAccessData; + uint16 madStatus; + int retries = 0;; + int done = 0; + VENDOR_MAD *mad = (VENDOR_MAD *)mp; + + // Determine which pkey to use (full or limited) + uint16_t pkey = omgt_get_mgmt_pkey(port, get_dlid_from_path(path), 0); + if (pkey==0) { + fprintf(stderr, "ERROR: Local port does not have management privileges\n"); + return (FPROTECTION); + } + + struct omgt_mad_addr addr = { + sl : path->u2.s.SL, + lid : path->DLID, + qpn : GSI_QUEUE_PAIR, + qkey : QP1_WELL_KNOWN_Q_KEY, + pkey : pkey, + }; + size_t recv_size; + + while (!done) { + + // MAD header + memset(mad, 0, sizeof(VENDOR_MAD)); + mad->common.BaseVersion = STL_BASE_VERSION; + mad->common.MgmtClass = MCLASS_VENDOR_OPASW; + mad->common.ClassVersion = STL_VENDOR_SPEC_CLASS_VERSION; + mad->common.mr.AsReg8 = 0; + mad->common.mr.s.Method = method; +#ifdef IB_STACK_IBACCESS + mad->common.TransactionID = (++g_transID)<<24; +#else + mad->common.TransactionID = (++g_transID) & 0xffffffff; +#endif + mad->common.AttributeID = MCLASS_ATTRIB_ID_I2C_ACCESS; + mad->common.AttributeModifier = sessionID; + /* ??? set bit to indicate jumbo MAD here??? */ +#if 0 + if (jumbo) + mad->common.AttributeModifier ^= (1 << 31); +#endif + + BSWAP_MAD_HEADER((MAD*)mad); + + // Vendor data + vendorData = (opasw_vendor_mad_t *)mad->VendorData; + i2cAccessData = (opasw_i2c_access_t *)&vendorData->data[0]; + i2cAccessData->locationDescriptor = ntoh32(locationDescriptor); + i2cAccessData->dataLen = ntoh16(dataLen); + i2cAccessData->dataOffset = ntoh16(dataOffset); + if (method == MMTHD_SET) + memcpy(i2cAccessData->i2cData, data, dataLen); + + // Send mad & recv response + + if (g_debugMode) { + printf("send buffer for in i2c access:\n"); + opaswDisplayBuffer((char *)mad, jumbo ? sizeof(VENDOR_MAD_JUMBO) : sizeof(VENDOR_MAD)); + } + + recv_size = sizeof(*mad); + status = omgt_send_recv_mad_no_alloc(port, + (uint8_t *)mad, sizeof(*mad), + &addr, + (uint8_t *)mad, &recv_size, + timeout, + FW_RETRIES); + + if (g_debugMode) { + printf("recv buffer for in i2c access rcp:\n"); + opaswDisplayBuffer((char *)mad, jumbo ? sizeof(VENDOR_MAD_JUMBO) : sizeof(VENDOR_MAD)); + } + if (FSUCCESS != status) { + fprintf(stderr, "Error: Failed to send MAD or receive response MAD status is %d\n", status); + return(status); + } + if ((madStatus = getMadStatus(mad)) > 0) { + if (g_verbose) + printf("non-zero madStatus received: 0x%04x\n", madStatus); + if (NEED_TO_RETRY(madStatus)) { + if (++retries > 9) { + displayStatusMessage(madStatus); + status = FINVALID_OPERATION; + done = 1; + } else { + usleep(250000); + continue; + } + } else { + displayStatusMessage(madStatus); + return(status = FINVALID_OPERATION); + } + } else + done = 1; + } + + if (method == MMTHD_GET) + memcpy(data, i2cAccessData->i2cData, dataLen); + return(status); +} + +FSTATUS sendSaveConfigMad(struct omgt_port *port, + IB_PATH_RECORD *path, + VENDOR_MAD *mad, + uint16 sessionID) +{ + FSTATUS status = FSUCCESS; + opasw_vendor_mad_t *vendorData; + opasw_save_config_t *saveConfigP; + uint16 madStatus; + + // Determine which pkey to use (full or limited) + uint16_t pkey = omgt_get_mgmt_pkey(port, get_dlid_from_path(path), 0); + if (pkey==0) { + fprintf(stderr, "ERROR: Local port does not have management privileges\n"); + return (FPROTECTION); + } + + struct omgt_mad_addr addr = { + sl : path->u2.s.SL, + lid : path->DLID, + qpn : GSI_QUEUE_PAIR, + qkey : QP1_WELL_KNOWN_Q_KEY, + pkey : pkey, + }; + size_t recv_size; + + // MAD header + memset(mad, 0, sizeof(VENDOR_MAD)); + mad->common.BaseVersion = STL_BASE_VERSION; + mad->common.MgmtClass = MCLASS_VENDOR_OPASW; + mad->common.ClassVersion = STL_VENDOR_SPEC_CLASS_VERSION; + mad->common.mr.AsReg8 = 0; + mad->common.mr.s.Method = MMTHD_SET; +#ifdef IB_STACK_IBACCESS + mad->common.TransactionID = (++g_transID)<<24; +#else + mad->common.TransactionID = (++g_transID) & 0xffffffff; +#endif + mad->common.AttributeID = MCLASS_ATTRIB_ID_SAVE_CONFIG; + mad->common.AttributeModifier = sessionID; + + BSWAP_MAD_HEADER((MAD*)mad); + + // Vendor data + vendorData = (opasw_vendor_mad_t *)mad->VendorData; + saveConfigP = (opasw_save_config_t *)&vendorData->data[0]; + saveConfigP->reserved = 0; + + // Send mad & recv response + recv_size = sizeof(*mad); + status = omgt_send_recv_mad_no_alloc(port, + (uint8_t *)mad, sizeof(*mad), + &addr, + (uint8_t *)mad, &recv_size, + RESP_WAIT_TIME, + DEF_RETRIES); + + if (FSUCCESS != status) { + fprintf(stderr, "Error: Failed to send MAD or receive response MAD status is %d\n", status); + return(status); + } + if ((madStatus = getMadStatus(mad)) > 0) { + displayStatusMessage(madStatus); + return(status = FINVALID_OPERATION); + } + + return(status); +} + +FSTATUS sendSTLPortStatsPort1Mad(struct omgt_port *port, IB_PATH_RECORD *path, STL_PERF_MAD *mad) +{ + FSTATUS status = FSUCCESS; + STL_DATA_PORT_COUNTERS_REQ *portCounters; + size_t recv_size = sizeof(*mad); + + + // Determine which pkey to use (full or limited) + uint16_t pkey = omgt_get_mgmt_pkey(port, get_dlid_from_path(path), 0); + if (pkey==0) { + fprintf(stderr, "ERROR: Local port does not have management privileges\n"); + return (FPROTECTION); + } + + struct omgt_mad_addr addr = { + .lid = path->DLID, + .qpn = GSI_QUEUE_PAIR, + .qkey = QP1_WELL_KNOWN_Q_KEY, + .pkey = pkey, + .sl = path->u2.s.SL + }; + + memset(mad, 0, sizeof(STL_PERF_MAD)); + mad->common.BaseVersion = STL_BASE_VERSION; + mad->common.ClassVersion = STL_PM_CLASS_VERSION; + mad->common.MgmtClass = MCLASS_PERF; + mad->common.mr.AsReg8 = 0; + mad->common.mr.s.Method = MMTHD_GET; + mad->common.TransactionID = ++g_transID; + mad->common.AttributeID = STL_PM_ATTRIB_ID_DATA_PORT_COUNTERS; + + mad->common.AttributeModifier = 1<<24; + + portCounters = (STL_DATA_PORT_COUNTERS_REQ *)&(mad->PerfData); + portCounters->PortSelectMask[3] = 1; + + + BSWAP_MAD_HEADER((MAD*)mad); + + status = omgt_send_recv_mad_no_alloc(port, (uint8_t *)mad, sizeof(*mad), &addr, + (uint8_t *)mad, &recv_size, RESP_WAIT_TIME, 0); + BSWAP_MAD_HEADER((MAD*)mad); + + if (status != FSUCCESS) { + fprintf(stderr, "Error: Failed to send MAD or receive response MAD status is %d\n", status); + return status; + } + + return status; +} diff --git a/IbaTools/opasw/opaswcommon/opaswmetadata.c b/IbaTools/opasw/opaswcommon/opaswmetadata.c new file mode 100644 index 0000000..e3a5c81 --- /dev/null +++ b/IbaTools/opasw/opaswcommon/opaswmetadata.c @@ -0,0 +1,490 @@ +/* BEGIN_ICS_COPYRIGHT7 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT7 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +#include +#include +#include +#include + +#include "iba/ib_types.h" +#include "iba/ib_sm_priv.h" +#include "iba/ib_helper.h" +#include +#include "opamgt_sa_priv.h" +#include "opaswcommon.h" +#include "opaswmetadata.h" + + +table_meta_data_t systemMetaData[] = +{ +// IDX LEN START PROTECTED DATA_TYPE FIELD + /* 0 */ {0, 0, 1, DT_INTVAL, "RESERVED" }, + /* 1 */ {512, 0, 0, DT_ASCII_STRING, "NODE_STRING"}, + /* 2 */ {64, 512, 1, DT_NUMERIC_STRING, "SYSTEM_IMAGE_GUID"}, + /* 3 */ {64, 576, 1, DT_NUMERIC_STRING, "NODE_GUID"}, + /* 4 */ {32, 640, 1, DT_NUMERIC_STRING, "CAPABILITY_MASK"}, + /* 5 */ {32, 672, 1, DT_NUMERIC_STRING, "PORT0_CAPABILITY_MASK"}, + /* 6 */ {32, 704, 1, DT_NUMERIC_STRING, "REVISION"}, + /* 7 */ {24, 736, 1, DT_INTVAL, "VENDOR_ID"}, + /* 8 */ {8, 760, 1, DT_INTVAL, "NUM_PORTS"}, + /* 9 */ {8, 768, 1, DT_INTVAL, "INI_META_VERSION"}, + /* 10 */ {8, 776, 1, DT_INTVAL, "MODULE_TYPE"}, + /* 11 */ {16, 784, 1, DT_INTVAL, "PARTITION_CAP"}, + /* 12 */ {16, 800, 1, DT_INTVAL, "DEVICE_ID"}, + /* 13 */ {16, 816, 1, DT_INTVAL, "LINEAR_FDB_CAP"}, + /* 14 */ {16, 832, 1, DT_INTVAL, "MULTICAST_FDB_CAP"}, + /* 15 */ {16, 848, 1, DT_INTVAL, "PARTITION_ENFORCEMENT_CAP"}, + /* 16 */ {0, 0, 1, DT_INTVAL, "RESERVED16"}, + /* 17 */ {0, 0, 1, DT_INTVAL, "RESERVED17"}, + /* 18 */ {0, 0, 1, DT_INTVAL, "RESERVED18"}, + /* 19 */ {5, 872, 1, DT_INTVAL, "QSFP_RESET_INIT_ASSERT_TIME_IN_US"}, + /* 20 */ {16, 896, 1, DT_INTVAL, "QSFP_POWER_BUDGET_WATTS_IN_TENTHS"}, + /* 21 */ {16, 912, 1, DT_INTVAL, "QSFP_MODSEL_SETUP_TIME_IN_US"}, + /* 22 */ {32, 928, 1, DT_INTVAL, "QSFP_INITIALIZATION_TIME_IN_US"}, + /* 23 */ {32, 960, 1, DT_INTVAL, "QSFP_RESET_TIME_IN_US"}, + /* 24 */ {32, 992, 1, DT_INTVAL, "QSFP_POWER_UP_TIME_IN_US"}, + /* 25 */ {8, 1024, 1, DT_INTVAL, "QSFP_POWER_PER_QSFP_MAX_IN_TENTHS"}, + /* 26 */ {16, 1040, 1, DT_INTVAL, "QSFP_MGR_TASK_DELAY_IN_MS"}, + /* 27 */ {0, 0, 0, DT_INTVAL, "RESERVED27"}, + /* 28 */ {8, 1064, 0, DT_INTVAL, "QSFP_ATTENUATION_DEFAULT_25G"}, + /* 29 */ {8, 1072, 1, DT_INTVAL, "VARIABLE_TABLE_ENTRIES_PER_PORT"}, + /* 30 */ {8, 1080, 1, DT_INTVAL, "VARIABLE_TABLE_BASE_PORT"}, + /* 31 */ {16, 1088, 1, DT_INTVAL, "VARIABLE_TABLE_SLOT_OFFSET"}, + /* 32 */ {16, 1104, 1, DT_INTVAL, "AR_PORTGROUP_FDB_CAP"}, + /* 33 */ {2, 877, 1, DT_INTVAL, "FM_PUSH_BUTTON_STATE"}, + /* 34 */ {32, 1120, 1, DT_INTVAL, "QSFP_TEMPERATURE_POLL_TIME_IN_US"}, + /* 35 */ {2, 879, 1, DT_INTVAL, "PLATFORM_I2C_WRITE_BYTE_COUNT_TEMP"}, + /* 36 */ {32, 1152, 1, DT_INTVAL, "PLATFORM_I2C_LOCATION_TEMP"}, + /* 37 */ {16, 1184, 1, DT_INTVAL, "PLATFORM_I2C_REGISTER_QSFP_MAX_TEMP"}, + /* 38 */ {16, 1200, 1, DT_INTVAL, "PLATFORM_I2C_REGISTER_ASIC_TEMP"}, + /* 39 */ {64, 1216, 1, DT_INTVAL, "IPV6_ADDR_127_64"}, + /* 40 */ {64, 1280, 1, DT_INTVAL, "IPV6_ADDR_63_0"}, + /* 41 */ {32, 1344, 1, DT_INTVAL, "IPV4_ADDR"}, + /* 42 */ {16, 1376, 0, DT_INTVAL, "ASIC_TEMP_POLL_DELAY_IN_MS"}, + /* 43 */ {3, 864, 1, DT_INTVAL, "QSFP_INHIBIT_RXCDR_PWRSAVINGS_IN_TENTHS"} +}; + +const int systemMetaDataSize = sizeof(systemMetaData) / sizeof(table_meta_data_t); + +table_meta_data_t portMetaData[] = +{ +// IDX LEN START PROTECTED DATA_TYPE FIELD + /* 0 */ {0, 0, 1, DT_INTVAL, "RESERVED" }, + /* 1 */ {8, 0, 1, DT_INTVAL, "PHYS_PORT_NUMBER"}, + /* 2 */ {4, 8, 1, DT_INTVAL, "PORT_TYPE"}, + /* 3 */ {5, 12, 1, DT_INTVAL, "QSFP_MODSEL_GRP"}, + /* 4 */ {3, 17, 1, DT_INTVAL, "QSFP_MODSEL_BIT"}, + /* 5 */ {5, 20, 1, DT_INTVAL, "REMOTE_ATTEN_25G"}, + /* 6 */ {5, 25, 1, DT_INTVAL, "LOCAL_ATTEN_25G"}, + /* 7 */ {10, 32, 1, DT_INTVAL, "LINK_SPEED_SUPPORTED"}, + /* 8 */ {4, 42, 1, DT_INTVAL, "LINK_WIDTH_SUPPORTED"}, + /* 9 */ {4, 46, 1, DT_INTVAL, "RX_LANE_POLARITY_INVERSION_MASK"}, + /* 10 */ {4, 50, 1, DT_INTVAL, "TX_LANE_POLARITY_INVERSION_MASK"}, + /* 11 */ {1, 54, 1, DT_INTVAL, "EXT_DEV_CFG"}, + /* 12 */ {4, 55, 0, DT_INTVAL, "VL_CAP"}, + /* 13 */ {4, 59, 0, DT_INTVAL, "MTU_CAP"}, + /* 14 */ {0, 0, 0, DT_INTVAL, "RESERVED14"}, + /* 15 */ {0, 0, 0, DT_INTVAL, "RESERVED15"}, + /* 16 */ {1, 63, 0, DT_INTVAL, "USER_ENABLED"}, + /* 17 */ {1, 64, 0, DT_INTVAL, "FM_ENABLED"}, + /* 18 */ {1, 65, 0, DT_INTVAL, "AUTO_LANE_SHEDDING"}, + /* 19 */ {1, 66, 0, DT_INTVAL, "MAX_BER_TARGET"}, + /* 20 */ {1, 67, 0, DT_INTVAL, "ISL_ENABLED"}, + /* 21 */ {0, 0, 0, DT_INTVAL, "RESERVED21"}, + /* 22 */ {3, 70, 0, DT_INTVAL, "LTP_CRC_MODE_SUPPORTED"}, + /* 23 */ {8, 96, 0, DT_INTVAL, "TARGET_BER_0"}, + /* 24 */ {8, 104, 0, DT_INTVAL, "TARGET_BER_1"}, + /* 25 */ {8, 112, 0, DT_INTVAL, "LOCAL_MAX_TIMEOUT"}, + /* 26 */ {4, 120, 0, DT_INTVAL, "TX_LANE_ENABLE_MASK"}, + /* 27 */ {1, 124, 0, DT_INTVAL, "CONTINOUS_REMOTE_UPDATES"}, + /* 28 */ {3, 125, 0, DT_INTVAL, "VCU"}, + /* 29 */ {14, 136, 0, DT_INTVAL, "VL15_BUFFER_SPACE_IN_BYTES"}, + /* 30 */ {1, 150, 0, DT_INTVAL, "EXTERNAL_LOOPBACK_ALLOWED"}, + /* 31 */ {12, 160, 1, DT_INTVAL, "TX_PRESET_IDX_FIXED_PORT"}, + /* 32 */ {12, 172, 1, DT_INTVAL, "TX_PRESET_IDX_ACTIVE_NO_EQ"}, + /* 33 */ {12, 192, 1, DT_INTVAL, "TX_PRESET_IDX_ACTIVE_EQ"}, + /* 34 */ {12, 204, 1, DT_INTVAL, "RX_PRESET_IDX"}, + /* 35 */ {1, 216, 1, DT_INTVAL, "SIDEBAND_CREDIT_RETURN"}, + /* 36 */ {8, 78, 1, DT_INTVAL, "CHANNEL_BASE"}, + /* 37 */ {4, 128, 1, DT_INTVAL, "LINK_WIDTH_DOWNGRADE_SUPPORTED"}, + /* 38 */ {0, 0, 1, DT_INTVAL, "RESERVED38"}, + /* 39 */ {1, 74, 1, DT_INTVAL, "QSFP_PWRCLASS4_INHIBIT_RXCDR"}, + /* 40 */ {1, 75, 1, DT_INTVAL, "QSFP_MAX_AMPLITUDE_APPLY"}, + /* 41 */ {2, 76, 1, DT_INTVAL, "QSFP_MAX_AMPLITUDE"} +}; + +int portMetaDataSize = sizeof(portMetaData) / sizeof(table_meta_data_t); + +table_meta_data_t rxPresetsMetaData[] = +{ +// IDX LEN START PROTECTED DATA_TYPE FIELD + /* 0 */ {0, 0, 1, DT_INTVAL, "RESERVED"}, + /* 1 */ {1, 0, 1, DT_INTVAL, "QSFP_RX_OUTPUT_CDR_APPLY"}, + /* 2 */ {1, 1, 1, DT_INTVAL, "QSFP_RX_OUTPUT_EMP_APPLY"}, + /* 3 */ {1, 2, 1, DT_INTVAL, "QSFP_RX_OUTPUT_AMP_APPLY"}, + /* 4 */ {1, 3, 1, DT_INTVAL, "QSFP_RX_OUTPUT_CDR"}, + /* 5 */ {4, 4, 1, DT_INTVAL, "QSFP_RX_OUTPUT_EMP"}, + /* 6 */ {2, 8, 1, DT_INTVAL, "QSFP_RX_OUTPUT_AMP"} +}; + +int rxPresetsMetaDataSize = sizeof(rxPresetsMetaData) / sizeof(table_meta_data_t); + +table_meta_data_t txPresetsMetaData[] = +{ +// IDX LEN START PROTECTED DATA_TYPE FIELD + /* 0 */ {0, 0, 1, DT_INTVAL, "RESERVED"}, + /* 1 */ {4, 0, 1, DT_INTVAL, "PRECUR"}, + /* 2 */ {5, 4, 1, DT_INTVAL, "ATTN"}, + /* 3 */ {5, 9, 1, DT_INTVAL, "POSTCUR"}, + /* 4 */ {1, 14, 1, DT_INTVAL, "QSFP_TX_INPUT_CDR_APPLY"}, + /* 5 */ {1, 15, 1, DT_INTVAL, "QSFP_TX_INPUT_EQ_APPLY"}, + /* 6 */ {1, 16, 1, DT_INTVAL, "QSFP_TX_INPUT_CDR"}, + /* 7 */ {4, 17, 1, DT_INTVAL, "QSFP_TX_INPUT_EQ"} +}; + +int txPresetsMetaDataSize = sizeof(txPresetsMetaData) / sizeof(table_meta_data_t); + +table_meta_data_t qsfpAttenuationMetaData[] = +{ +// IDX LEN START PROTECTED DATA_TYPE FIELD + /* 0 */ {0, 0, 1, DT_INTVAL, "RESERVED"}, + /* 1 */ {12, 0, 1, DT_INTVAL, "TX_PRESET_IDX"}, + /* 2 */ {12, 12, 1, DT_INTVAL, "RX_PRESET_IDX"} +}; + +int qsfpAttenuationMetaDataSize = sizeof(qsfpAttenuationMetaData) / sizeof(table_meta_data_t); + +table_meta_data_t variableSettingsMetaData[] = +{ +// IDX LEN START PROTECTED DATA_TYPE FIELD + /* 0 */ {0, 0, 1, DT_INTVAL, "RESERVED"}, + /* 1 */ {12, 0, 1, DT_INTVAL, "TX_PRESET_IDX"}, + /* 2 */ {12, 12, 1, DT_INTVAL, "RX_PRESET_IDX"} +}; + +int variableSettingsMetaDataSize = sizeof(variableSettingsMetaData) / sizeof(table_meta_data_t); + +int32 getMetaDataIndexByField(table_meta_data_t *table, int tableSize, const char *field) +{ + int32 returnIdx = -1; + int tableIdx; + table_meta_data_t *tp = table; + + for (tableIdx = 0, tp = table; (tableIdx <= tableSize); tableIdx++, tp++) { + if (strcmp(field, tp->field) == 0) { + returnIdx = tableIdx; + break; + } + } + + return(returnIdx); +} + +#define MASK32(numBits) ((1<> 5); + byteOffset = (wordOffset << 2); + tempWord = (dataBuffer[byteOffset] << 24) + (dataBuffer[byteOffset + 1] << 16) + (dataBuffer[byteOffset + 2] << 8) + dataBuffer[byteOffset + 3]; + lengthInBytes = (metaData[i].length / 8) + (metaData[i].length % 8); + if (metaData[i].length <= 32) + fieldValue = (tempWord >> (metaData[i].start & 0x1f)) & ((1 << metaData[i].length) - 1); + else + fieldValue = tempWord; + if (metaData[i].dataType != DT_INTVAL) { + p = (uint8 *)&dataBuffer[byteOffset]; + parsedData[i].val.arrayPtr = (uint8 *)malloc(lengthInBytes * sizeof(uint8)); + memcpy(parsedData[i].val.arrayPtr, (char *)p, lengthInBytes); + parsedData[i].lengthInBytes = lengthInBytes; + } else { + p = (uint8 *)&fieldValue; + parsedData[i].val.intVal = fieldValue; + parsedData[i].lengthInBytes = 4; + } + } + + if (showme) { + for (i = 0; i < tableLen; i++) { + int j; + printf("Field %s:\t", metaData[i].field); + if (metaData[i].dataType != DT_INTVAL) { + printf("Array len %d: ", parsedData[i].lengthInBytes); + for (j = 0; j < parsedData[i].lengthInBytes; j++) + printf("0x%02x ", parsedData[i].val.arrayPtr[j]); + printf("\n"); + } else { + printf("Numerical value 0x%08x\n", parsedData[i].val.intVal); + } + } + } + + return(status); +} + +uint32 getModuleType(struct omgt_port *port, IB_PATH_RECORD *path, uint16 sessionID) +{ + FSTATUS status = FSUCCESS; + uint8 *p; + uint8 memoryData[200]; + opasw_ini_descriptor_get_t tableDescriptors; + table_parsed_data_t *parsedDataTable; + VENDOR_MAD mad; + int32 metaIndex; + uint32 retValue; + + status = sendIniDescriptorGetMad(port, path, &mad, sessionID, &tableDescriptors); + if (status != FSUCCESS) { + fprintf(stderr, "Error: Failed to get ini descriptors - status %d\n", status); + return((uint32)-1); + } + + parsedDataTable = malloc(tableDescriptors.sysDataLen * sizeof(table_parsed_data_t)); + if (parsedDataTable == NULL) { + fprintf(stderr, "Error: Failed to allocate required memory.\n"); + return((uint32)-1); + } + + status = sendMemAccessGetMad(port, path, &mad, sessionID, tableDescriptors.sysDataAddr, (uint8)200, memoryData); + if (status != FSUCCESS) { + fprintf(stderr, "Error: Failed to access system table memory - status %d\n", status); + free(parsedDataTable); + return((uint32)-1); + } + p = memoryData; + status = parseDataTable(systemMetaData, p, MIN(tableDescriptors.sysMetaDataLen,systemMetaDataSize), &parsedDataTable[0], 0); + if (status != FSUCCESS) { + fprintf(stderr, "Error: Failed to parse system data table - status %d\n", status); + free(parsedDataTable); + return((uint32)-1); + } + + metaIndex = getMetaDataIndexByField(systemMetaData, MIN(tableDescriptors.sysMetaDataLen,systemMetaDataSize), "MODULE_TYPE"); + retValue = parsedDataTable[metaIndex].val.intVal; + free(parsedDataTable); + return retValue; +} + +uint32 getNumPorts(struct omgt_port *port, IB_PATH_RECORD *path, uint16 sessionID) +{ + FSTATUS status = FSUCCESS; + uint8 *p; + uint8 memoryData[200]; + opasw_ini_descriptor_get_t tableDescriptors; + table_parsed_data_t *parsedDataTable; + VENDOR_MAD mad; + int32 metaIndex; + uint32 retValue; + + status = sendIniDescriptorGetMad(port, path, &mad, sessionID, &tableDescriptors); + if (status != FSUCCESS) { + fprintf(stderr, "Error: Failed to get ini descriptors - status %d\n", status); + return((uint32)-1); + } + + parsedDataTable = malloc(tableDescriptors.sysDataLen * sizeof(table_parsed_data_t)); + if (parsedDataTable == NULL) { + fprintf(stderr, "Error: Failed to allocate required memory.\n"); + return((uint32)-1); + } + + status = sendMemAccessGetMad(port, path, &mad, sessionID, tableDescriptors.sysDataAddr, (uint8)200, memoryData); + if (status != FSUCCESS) { + fprintf(stderr, "Error: Failed to access system table memory - status %d\n", status); + free(parsedDataTable); + return((uint32)-1); + } + p = memoryData; + status = parseDataTable(systemMetaData, p, MIN(tableDescriptors.sysMetaDataLen,systemMetaDataSize), &parsedDataTable[0], 0); + if (status != FSUCCESS) { + fprintf(stderr, "Error: Failed to parse system data table - status %d\n", status); + free(parsedDataTable); + return((uint32)-1); + } + + metaIndex = getMetaDataIndexByField(systemMetaData, MIN(tableDescriptors.sysMetaDataLen,systemMetaDataSize), "NUM_PORTS"); + retValue = parsedDataTable[metaIndex].val.intVal; + free(parsedDataTable); + return retValue; +} + +FSTATUS getNodeDescription(struct omgt_port *port, IB_PATH_RECORD *path, uint16 sessionID, uint8 *nodeDesc) +{ + FSTATUS status = FSUCCESS; + uint8 *p; + uint8 memoryData[200]; + opasw_ini_descriptor_get_t tableDescriptors; + table_parsed_data_t *parsedDataTable; + VENDOR_MAD mad; + int32 metaIndex; + + status = sendIniDescriptorGetMad(port, path, &mad, sessionID, &tableDescriptors); + if (status != FSUCCESS) { + fprintf(stderr, "Error: Failed to get ini descriptors - status %d\n", status); + return((uint32)-1); + } + + parsedDataTable = malloc(tableDescriptors.sysDataLen * sizeof(table_parsed_data_t)); + if (parsedDataTable == NULL) { + fprintf(stderr, "Error: Failed to allocate required memory.\n"); + return((uint32)-1); + } + + status = sendMemAccessGetMad(port, path, &mad, sessionID, tableDescriptors.sysDataAddr, (uint8)200, memoryData); + if (status != FSUCCESS) { + fprintf(stderr, "Error: Failed to access system table memory - status %d\n", status); + free(parsedDataTable); + return((uint32)-1); + } + p = memoryData; + status = parseDataTable(&systemMetaData[0], p, MIN(tableDescriptors.sysMetaDataLen, systemMetaDataSize), &parsedDataTable[0], 0); + if (status != FSUCCESS) { + fprintf(stderr, "Error: Failed to parse system data table - status %d\n", status); + free(parsedDataTable); + return((uint32)-1); + } + + metaIndex = getMetaDataIndexByField(&systemMetaData[0], MIN(tableDescriptors.sysMetaDataLen, systemMetaDataSize), "NODE_STRING"); + memcpy(nodeDesc, parsedDataTable[metaIndex].val.arrayPtr, parsedDataTable[metaIndex].lengthInBytes); + nodeDesc[parsedDataTable[metaIndex].lengthInBytes] = '\0'; + free(parsedDataTable); + return(status); +} + +FSTATUS getFmPushButtonState(struct omgt_port *port, IB_PATH_RECORD *path, uint16 sessionID, uint32 *state) +{ + FSTATUS status = FSUCCESS; + uint8 *p; + uint8 memoryData[200]; + opasw_ini_descriptor_get_t tableDescriptors; + table_parsed_data_t *parsedDataTable; + VENDOR_MAD mad; + int32 metaIndex; + + status = sendIniDescriptorGetMad(port, path, &mad, sessionID, &tableDescriptors); + if (status != FSUCCESS) { + fprintf(stderr, "Error: Failed to get ini descriptors - status %d\n", status); + return((uint32)-1); + } + + parsedDataTable = malloc(tableDescriptors.sysDataLen * sizeof(table_parsed_data_t)); + if (parsedDataTable == NULL) { + fprintf(stderr, "Error: Failed to allocate required memory.\n"); + return((uint32)-1); + } + + status = sendMemAccessGetMad(port, path, &mad, sessionID, tableDescriptors.sysDataAddr, (uint8)200, memoryData); + if (status != FSUCCESS) { + fprintf(stderr, "Error: Failed to access system table memory - status %d\n", status); + free(parsedDataTable); + return((uint32)-1); + } + p = memoryData; + status = parseDataTable(&systemMetaData[0], p, MIN(tableDescriptors.sysMetaDataLen, systemMetaDataSize), &parsedDataTable[0], 0); + if (status != FSUCCESS) { + fprintf(stderr, "Error: Failed to parse system data table - status %d\n", status); + free(parsedDataTable); + return((uint32)-1); + } + + metaIndex = getMetaDataIndexByField(&systemMetaData[0], MIN(tableDescriptors.sysMetaDataLen, systemMetaDataSize), "FM_PUSH_BUTTON_STATE"); + memcpy(state, (char *)&parsedDataTable[metaIndex].val.intVal,parsedDataTable[metaIndex].lengthInBytes); + free(parsedDataTable); + return(status); +} + + +FSTATUS getGuid(struct omgt_port *port, IB_PATH_RECORD *path, uint16 sessionID, EUI64 *guid, int which) +{ + FSTATUS status = FSUCCESS; + uint8 *p; + uint8 memoryData[200]; + opasw_ini_descriptor_get_t tableDescriptors; + table_parsed_data_t *parsedDataTable; + VENDOR_MAD mad; + int32 metaIndex; + + status = sendIniDescriptorGetMad(port, path, &mad, sessionID, &tableDescriptors); + if (status != FSUCCESS) { + fprintf(stderr, "Error: Failed to get ini descriptors - status %d\n", status); + return((uint32)-1); + } + + parsedDataTable = malloc(tableDescriptors.sysDataLen * sizeof(table_parsed_data_t)); + if (parsedDataTable == NULL) { + fprintf(stderr, "Error: Failed to allocate required memory.\n"); + return((uint32)-1); + } + + status = sendMemAccessGetMad(port, path, &mad, sessionID, tableDescriptors.sysDataAddr, (uint8)200, memoryData); + if (status != FSUCCESS) { + fprintf(stderr, "Error: Failed to access system table memory - status %d\n", status); + free(parsedDataTable); + return((uint32)-1); + } + p = memoryData; + status = parseDataTable(systemMetaData, p, MIN(tableDescriptors.sysMetaDataLen, systemMetaDataSize), &parsedDataTable[0], 0); + if (status != FSUCCESS) { + fprintf(stderr, "Error: Failed to parse system data table - status %d\n", status); + free(parsedDataTable); + return((uint32)-1); + } + + if (which == SYSTEM_IMAGE_GUID) { + metaIndex = getMetaDataIndexByField(systemMetaData, MIN(tableDescriptors.sysDataLen, systemMetaDataSize), "SYSTEM_IMAGE_GUID"); + memcpy(guid, parsedDataTable[metaIndex].val.arrayPtr, parsedDataTable[metaIndex].lengthInBytes); + } else if (which == NODE_GUID) { + metaIndex = getMetaDataIndexByField(systemMetaData, MIN(tableDescriptors.sysDataLen, systemMetaDataSize), "NODE_GUID"); + memcpy(guid, parsedDataTable[metaIndex].val.arrayPtr, parsedDataTable[metaIndex].lengthInBytes); + } else { + fprintf(stderr, "Error: Invalid guid type\n"); + status = FERROR; + } + free(parsedDataTable); + return(status); +} diff --git a/IbaTools/opasw/opaswcommon/opaswmetadata.h b/IbaTools/opasw/opaswcommon/opaswmetadata.h new file mode 100644 index 0000000..088e9f5 --- /dev/null +++ b/IbaTools/opasw/opaswcommon/opaswmetadata.h @@ -0,0 +1,219 @@ +/* BEGIN_ICS_COPYRIGHT3 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT3 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +/*********************** + * MACROS + ***********************/ + +#ifndef _XEDGE_METADATA_H_ +#define _XEDGE_METADATA_H_ + + +/*********************** + * CONSTANTS + ***********************/ + + +#define ENC_DISABLED 0 +#define ENC_ENABLED 1 + +#define ENC_NO 0 +#define ENC_YES 1 + +#define ENC_MOD_TYPE_EDGE 0 +#define ENC_MOD_TYPE_SPINE 1 +#define ENC_MOD_TYPE_LEAF 2 + +#define ENC_PORT_TYPE_DISC 1 +#define ENC_PORT_TYPE_FIXED 2 +#define ENC_PORT_TYPE_VARIABLE 3 +#define ENC_PORT_TYPE_QSFP 4 +#define ENC_PORT_TYPE_SIPHx16 5 + +#define ENC_VLCAP_VL0 1 +#define ENC_VLCAP_VL0_1 2 +#define ENC_VLCAP_VL0_2 3 +#define ENC_VLCAP_VL0_3 4 +#define ENC_VLCAP_VL0_4 5 +#define ENC_VLCAP_VL0_5 6 +#define ENC_VLCAP_VL0_6 7 +#define ENC_VLCAP_VL0_7 8 +#define ENC_VLCAP_VL0_8 9 +#define ENC_VLCAP_VL0_9 10 +#define ENC_VLCAP_VL0_10 11 +#define ENC_VLCAP_VL0_11 12 +#define ENC_VLCAP_VL0_12 13 +#define ENC_VLCAP_VL0_13 14 +#define ENC_VLCAP_VL0_14 15 + +#define ENC_MTU_CAP_512 2 +#define ENC_MTU_CAP_1024 3 +#define ENC_MTU_CAP_2048 4 +#define ENC_MTU_CAP_4096 5 +#define ENC_MTU_CAP_8192 8 +#define ENC_MTU_CAP_10240 9 + +#define ENC_LINK_SPEED_12G 1 +#define ENC_LINK_SPEED_25G 2 +#define ENC_LINK_SPEED_12G_25G 3 + +#define ENC_LINK_WIDTH_1X 1 +#define ENC_LINK_WIDTH_2X 2 +#define ENC_LINK_WIDTH_2X_1X 3 +#define ENC_LINK_WIDTH_3X 4 +#define ENC_LINK_WIDTH_3X_1X 5 +#define ENC_LINK_WIDTH_3X_2X 6 +#define ENC_LINK_WIDTH_3X_2X_1X 7 +#define ENC_LINK_WIDTH_4X 8 +#define ENC_LINK_WIDTH_4X_1X 9 +#define ENC_LINK_WIDTH_4X_2X 10 +#define ENC_LINK_WIDTH_4X_2X_1X 11 +#define ENC_LINK_WIDTH_4X_3X 12 +#define ENC_LINK_WIDTH_4X_3X_1X 13 +#define ENC_LINK_WIDTH_4X_3X_2X 14 +#define ENC_LINK_WIDTH_4X_3X_2X_1X 15 + +#define ENC_POLARITY_NORMAL 0 +#define ENC_POLARITY_REVERSE 1 + +#define ENC_LREV_4X_MODE_NORMAL 0 +#define ENC_LREV_4X_MODE_REVERSE 4 + +#define ENC_LREV_8X_MODE_NORMAL 0 +#define ENC_LREV_8X_MODE_REV_UPPER 1 +#define ENC_LREV_8X_MODE_REV_LOWER 4 +#define ENC_LREV_8X_MODE_REV_ALL 5 +#define ENC_LREV_8X_MODE_SWAP 10 +#define ENC_LREV_8X_MODE_SW_REV_LOWER 11 +#define ENC_LREV_8X_MODE_SW_REV_UPPER 14 +#define ENC_LREV_8X_MODE_SW_REV_ALL 15 + +#define ENC_PKT_FOR_MODE_CUT_THRU 0 +#define ENC_PKT_FOR_MODE_ST_FW 1 + +#define ENC_DISTRIBUTION_BAL 0 +#define ENC_DISTRIBUTION_VL0_LDED 1 +#define ENC_DISTRIBUTION_VLH_LDED 2 +#define ENC_DISTRIBUTION_UP_ELVTR 3 +#define ENC_DISTRIBUTION_DWN_ELVTR 4 +#define ENC_DISTRIBUTION_EX_BAL 5 + +#define ENC_DMSEL_DFE5 0 +#define ENC_DMSEL_DFE2 1 +#define ENC_DMSEL_NRZ 2 +#define ENC_DMSEL_NRZLP 3 + +#define ENC_SLEW_32PS 0 +#define ENC_SLEW_50PS 3 +#define ENC_SLEW_54PS 5 +#define ENC_SLEW_88PS 7 + +#define ENC_FM_BUTTON_STATE_ALL 0 +#define ENC_FM_BUTTON_STATE_NONE 1 +#define ENC_FM_BUTTON_STATE_PORT1 2 +#define ENC_FM_BUTTON_STATE_FM_ENABLED 3 + +#define ENC_CRC_16b 0 +#define ENC_CRC_14b_16b 1 +#define ENC_CRC_48b_16b 2 +#define ENC_CRC_48b_14b_16b 3 +#define ENC_CRC_PERLANE_16b 4 +#define ENC_CRC_PERLANE_14b_16b 5 +#define ENC_CRC_PERLANE_48b_16b 6 +#define ENC_CRC_PERLANE_48b_14b_16b 7 + +#define SYSMETATABLESIZE 32 +#define PORTMETATABLESIZE 43 + +#define DT_INTVAL 1 +#define DT_ASCII_STRING 2 +#define DT_NUMERIC_STRING 3 + +#define NODE_GUID 1 +#define SYSTEM_IMAGE_GUID 2 + +/*********************** + * DATA TYPES + ***********************/ + +typedef struct table_meta_data_s { + // index is the actual index in the table + uint16 length; + uint16 start; + uint16 protected; + uint16 dataType; + char field[256]; + +} table_meta_data_t; + +typedef struct table_parsed_data_s { + // index is the actual index in the table + uint32 lengthInBytes; + uint16 dataType; + union { + uint8 *arrayPtr; + uint32 intVal; + } val; +} table_parsed_data_t; + + +/*********************** + * EXTERNS + ***********************/ + +extern table_meta_data_t systemMetaData[]; +extern table_meta_data_t portMetaData[]; +extern table_meta_data_t rxPresetsMetaData[]; +extern table_meta_data_t txPresetsMetaData[]; +extern table_meta_data_t qsfpAttenuationMetaData[]; +extern table_meta_data_t variableSettingsMetaData[]; +extern const int systemMetaDataSize; +extern int portMetaDataSize; +extern int rxPresetsMetaDataSize; +extern int txPresetsMetaDataSize; +extern int qsfpAttenuationMetaDataSize; +extern int variableSettingsMetaDataSize; + + + +/*********************** + * FUNCTION PROTOTYPES + ***********************/ + +int32 getMetaDataIndexByField (table_meta_data_t *table, int tableSize, const char *field); +FSTATUS parseDataTable(table_meta_data_t *metaData, uint8 *dataBuffer, uint16 tableLen, table_parsed_data_t *parsedData, int showme); +uint32 getModuleType(struct omgt_port *port, IB_PATH_RECORD *path, uint16 sessionID); +uint32 getNumPorts(struct omgt_port *port, IB_PATH_RECORD *path, uint16 sessionID); +FSTATUS getNodeDescription(struct omgt_port *port, IB_PATH_RECORD *path, uint16 sessionID, uint8 *nodeDesc); +FSTATUS getFmPushButtonState(struct omgt_port *port, IB_PATH_RECORD *path, uint16 sessionID, uint32 *state); +FSTATUS getGuid(struct omgt_port *port, IB_PATH_RECORD *path, uint16 sessionID, EUI64 *guid, int which); + +#endif /* _XEDGE_METADATA_H_ */ diff --git a/IbaTools/opasw/opaswcommon/opaswpassword.c b/IbaTools/opasw/opaswcommon/opaswpassword.c new file mode 100644 index 0000000..1618772 --- /dev/null +++ b/IbaTools/opasw/opaswcommon/opaswpassword.c @@ -0,0 +1,97 @@ +/* BEGIN_ICS_COPYRIGHT7 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT7 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +#include +#include +#include +#include +#include + +/* work around conflicting names */ + +#include "iba/ib_types.h" +#include "iba/ib_sm_priv.h" +#include "iba/ib_helper.h" +#include "opamgt_priv.h" +#include +#include +#include "opaswcommon.h" + +int vkey_prompt_user(uint8 *vendorKey, int vkeyChange) +{ + int status = 1; + MD5_CTX state; + char *password; + char password1[65]; + char password2[65]; + const char *psw1Prompt = (vkeyChange) ? "Enter new password:" : "Enter password:"; + const char *psw2Prompt = (vkeyChange) ? "Re-enter new password:" : "Re-enter password:"; + + memset(password1, 0, sizeof(password1)); + memset(password2, 0, sizeof(password2)); + + if ( !vkeyChange && ((password = getenv("opaswpassword")) != NULL)) { + strncpy(password1, password, sizeof(password1) - 1); + } else if ( vkeyChange && ((password = getenv("xedge_save_password")) != NULL)) { + strncpy(password1, password, sizeof(password1) - 1); + } else { + if ((password = getpass(psw1Prompt)) == NULL) { + fprintf(stderr, "Unable to get password\n"); + status = 0; + } + + if (status) { + strncpy(password1, password, sizeof(password1) - 1); + if ((password = getpass(psw2Prompt)) == NULL) { + fprintf(stderr, "Unable to get re-entered password\n"); + status = 0; + } + } + } + + if (status) { + strncpy(password2, password, sizeof(password2) - 1); + if (strcmp(password1, password2) == 0) { + if (strlen(password1) == 0 && strlen(password2) == 0) { + memset(vendorKey, 0, MAX_VENDOR_KEY_LEN); + } else { + MD5_Init(&state); + MD5_Update(&state, (uint8 *)password1, strlen(password1)); + MD5_Final(vendorKey, &state); + } + } else { + fprintf(stderr, "Password entries do not match\n"); + status = 0; + } + } + + return(status); +} diff --git a/IbaTools/opasw/opaswconfigure/Makefile b/IbaTools/opasw/opaswconfigure/Makefile new file mode 100644 index 0000000..40a4c47 --- /dev/null +++ b/IbaTools/opasw/opaswconfigure/Makefile @@ -0,0 +1,159 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** +# Makefile for opaswconfigure + +# Include Make Control Settings +include $(TL_DIR)/$(PROJ_FILE_DIR)/Makesettings.project + +#=============================================================================# +# Definitions: +#-----------------------------------------------------------------------------# + +# Name of SubProjects +DS_SUBPROJECTS = +# name of executable or downloadable image +EXECUTABLE = $(BUILDDIR)/opaswconfigure$(EXE_SUFFIX) +# list of sub directories to build +DIRS = +# C files (.c) +CFILES = \ + opaswconfigure.c \ + # Add more c files here +# C++ files (.cpp) +CCFILES = \ + # Add more cpp files here +# lex files (.lex) +LFILES = \ + # Add more lex files here +# archive library files (basename, $ARFILES will add MOD_LIB_DIR/prefix and suffix) +LIBFILES= +# Windows Resource Files (.rc) +RSCFILES = +# Windows IDL File (.idl) +IDLFILE = +# Windows Linker Module Definitions (.def) file for dll's +DEFFILE = +# targets to build during INCLUDES phase (add public includes here) +INCLUDE_TARGETS = \ + # Add more h hpp files here +# Non-compiled files + # Add more files here +MISC_FILES = +# all source files +SOURCES = $(CFILES) $(CCFILES) $(LFILES) $(RSCFILES) $(IDLFILE) +# Source files to include in DSP File +DSP_SOURCES = $(INCLUDE_TARGETS) $(SOURCES) $(MISC_FILES) \ + $(RSCFILES) $(DEFFILE) $(MAKEFILE) +# all object files +OBJECTS = $(CFILES:.c=$(OBJ_SUFFIX)) $(CCFILES:.cpp=$(OBJ_SUFFIX)) \ + $(LFILES:.lex=$(OBJ_SUFFIX)) +RSCOBJECTS = $(RSCFILES:.rc=$(RES_SUFFIX)) +# targets to build during LIBS phase +LIB_TARGETS_IMPLIB = +LIB_TARGETS_ARLIB = # $(LIB_PREFIX)ResourceTest$(ARLIB_SUFFIX) +LIB_TARGETS_EXP = $(LIB_TARGETS_IMPLIB:$(ARLIB_SUFFIX)=$(EXP_SUFFIX)) +LIB_TARGETS_MISC = +# targets to build during CMDS phase +CMD_TARGETS_SHLIB = +CMD_TARGETS_EXE = $(EXECUTABLE) +CMD_TARGETS_MISC = +# files to remove during clean phase +CLEAN_TARGETS_MISC = +CLEAN_TARGETS = $(OBJECTS) $(RSCOBJECTS) $(IDL_TARGETS) $(CLEAN_TARGETS_MISC) +# other files to remove during clobber phase +CLOBBER_TARGETS_MISC= +# sub-directory to install to within bin +BIN_SUBDIR = +# sub-directory to install to within include +INCLUDE_SUBDIR = + +# Additional Settings +#CLOCALDEBUG = User defined C debugging compilation flags [Empty] +#CCLOCALDEBUG = User defined C++ debugging compilation flags [Empty] +#CLOCAL = User defined C flags for compiling [Empty] +#CCLOCAL = User defined C++ flags for compiling [Empty] +#BSCLOCAL = User flags for Browse File Builder [Empty] +#DEPENDLOCAL = user defined makedepend flags [Empty] +#LINTLOCAL = User defined lint flags [Empty] +#LOCAL_INCLUDE_DIRS = User include directories to search for C/C++ headers [Empty] +#LDLOCAL = User defined C flags for linking [Empty] +#IMPLIBLOCAL = User flags for Object Lirary Manager [Empty] +#MIDLLOCAL = User flags for IDL compiler [Empty] +#RSCLOCAL = User flags for resource compiler [Empty] +#LOCALDEPLIBS = User libraries to include in dependencies [Empty] +#LOCALLIBS = User libraries to use when linking [Empty] +# (in addition to LOCALDEPLIBS) +#LOCAL_LIB_DIRS = User library directories for libpaths [Empty] + +CLOCAL = $(CPIE) +LOCALDEPLIBS=$(IBACCESS_USER_LIBS) opaswcommon opamgt-priv +LOCAL_INCLUDE_DIRS= +LOCALLIBS=$(OPENIB_USER_LIBS) crypto +LOCAL_LIB_DIRS=$(OPENIB_USER_LIB_DIRS) $(IBACCESS_USER_LIB_DIRS) + +# Include Make Rules definitions and rules +include $(TL_DIR)/IbaTools/Makerules.module + +#=============================================================================# +# Overrides: +#-----------------------------------------------------------------------------# +#CCOPT = # C++ optimization flags, default lets build config decide +#COPT = # C optimization flags, default lets build config decide +#SUBSYSTEM = Subsystem to build for (none, console or windows) [none] +# (Windows Only) +#USEMFC = How Windows MFC should be used (none, static, shared, no_mfc) [none] +# (Windows Only) +#=============================================================================# + +#=============================================================================# +# Rules: +#-----------------------------------------------------------------------------# +# process Sub-directories +include $(TL_DIR)/Makerules/Maketargets.toplevel + +# build cmds and libs +include $(TL_DIR)/Makerules/Maketargets.build + +# install for includes, libs and cmds phases +include $(TL_DIR)/Makerules/Maketargets.install + +# install for stage phase +include $(TL_DIR)/Makerules/Maketargets.stage +STAGE:: + #$(VS)$(STAGE_INSTALL) $(STAGE_INSTALL_DIR_OPT) $(PROJ_STAGE_FASTFABRIC_DIR) $(EXECUTABLE) + $(VS)$(STAGE_INSTALL) $(STAGE_INSTALL_DIR_OPT) $(PROJ_STAGE_BIN_DIR) $(EXECUTABLE) + +# Unit test execution +#include $(TL_DIR)/Makerules/Maketargets.runtest + +#=============================================================================# + +#=============================================================================# +# DO NOT DELETE THIS LINE -- make depend depends on it. +#=============================================================================# diff --git a/IbaTools/opasw/opaswconfigure/opaswconfigure.c b/IbaTools/opasw/opaswconfigure/opaswconfigure.c new file mode 100644 index 0000000..be8e6ec --- /dev/null +++ b/IbaTools/opasw/opaswconfigure/opaswconfigure.c @@ -0,0 +1,556 @@ +/* BEGIN_ICS_COPYRIGHT7 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT7 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +#include +#include +#include +#include +#include + +/* work around conflicting names */ + +#include "iba/ib_types.h" +#include "iba/ib_sm_priv.h" +#include "iba/ib_helper.h" +#include "opamgt_sa_priv.h" +#include +#include "opaswcommon.h" +#include "opaswmetadata.h" + +#define EEPROM_MASK 0x100 + +// globals + + +int g_debugMode = 0; +int g_verbose = 0; +int g_quiet = 0; +int g_gotHfi = 0; +int g_gotPort = 0; +uint8 g_configNum = 0; +int g_gotIntParam = 0; +int g_gotStrParam = 0; +int g_gotSave = 0; + + +#define LIST_FILE_SUPPORTED 0 + +static void usage(char *app_name) +{ + fprintf(stderr, "usage: %s -t target ", app_name); +#if LIST_FILE_SUPPORTED + fprintf(stderr, "[-l list_file] "); +#endif + fprintf(stderr, "[-v|-q] [-h hfi] [-o port] -C config-option-number -S [-i integer-val] [-s string-val]"); + fprintf(stderr, "\n"); + fprintf(stderr, " -t - target to configure\n"); +#if LIST_FILE_SUPPORTED + fprintf(stderr, " -l - file that holds a list of targets to reset\n"); +#endif + fprintf(stderr, " -v - verbose output\n"); + fprintf(stderr, " -q - no output\n"); + fprintf(stderr, " -h - hfi, numbered 1..n, 0= -o port will be a\n"); + fprintf(stderr, " system wide port num (default is 0)\n"); + fprintf(stderr, " -o - port, numbered 1..n, 0=1st active (default\n"); + fprintf(stderr, " is 1st active)\n"); + fprintf(stderr, " -C - query number to run:\n"); + fprintf(stderr, " 1 - node description - -s for string value\n"); + fprintf(stderr, " 5 - link width supported - -i for integer value (1-1X, 2-2X, 3-2X_1X, 4-3X, 5-3_1X, 6-3X_2X, 7-3X_2X_1X, 8-4X, 9-4X_1X, 10-4X_2X, 11-4X_2X_1X, 12-4X_3X, 13-4X_3X_1X, 14-4X_3X_2X, 15-4X_3X_2X_1X)\n"); + fprintf(stderr, " 7 - link speed supported - -i for integer value (1-12G, 2-25G, 3-12G_25G)\n"); + fprintf(stderr, " 8 - FM Enabled - -i for integer value (0-disabled, 1-enabled)\n"); + fprintf(stderr, " 9 - Link CRC Mode - i for integer value (0-16b, 1-14b/16b, 2-48b/16b, 3-48b/14b/16b, 4-per lane/16b, 5-per lane/14b/16b, 6-per lane/48b/16b, 7-per lane/48b/14b/16b)\n"); + fprintf(stderr, " 10 - vCU - i for integer value\n"); +#if 0 /* non-documented options */ + fprintf(stderr, " 11 - External loopback allowed\n"); +#endif +/* remember to update opaswfwconfigure.c when adding new configuration items */ + fprintf(stderr, " -S - save configuration\n"); + fprintf(stderr, " -i - integer value parameter\n"); + fprintf(stderr, " -s - string value parameter\n"); + fprintf(stderr, "\n"); + fprintf(stderr, "The -h and -o options permit a variety of selections:\n"); + fprintf(stderr, " -h 0 - 1st active port in system (this is the default)\n"); + fprintf(stderr, " -h 0 -o 0 - 1st active port in system\n"); + fprintf(stderr, " -h x - 1st active port on HFI x\n"); + fprintf(stderr, " -h x -o 0 - 1st active port on HFI x\n"); + fprintf(stderr, " -h 0 -o y - port y within system (irrespective of which ports are active)\n"); + fprintf(stderr, " -h x -o y - HFI x, port y\n"); + + exit(2); +} + +int main(int argc, char *argv[]) +{ + char *cmdName; + const char *opts="DvqSt:l:h:o:m:C:i:s:"; + char parameter[100]; + char strParameter[100]; + int32 integerParameter = 0; + char *p; + EUI64 destPortGuid = -1; + int c; + int i; + uint8 hfi = 0; + uint8 port = 0; + IB_PATH_RECORD path; + uint16 sessionID = 0; + int32 metaIndex = -1; + uint32 numPorts; + uint32 linkWidth; + uint32 linkSpeed; + uint32 port1LinkWidth; + uint32 fmEnabled; + uint32 linkCRCMode; + uint32 vCU; + uint32 extLoopbackAllowed; + VENDOR_MAD mad; + FSTATUS status = FSUCCESS; + uint8 nodeDescription[NODE_DESC_SIZE]; + struct omgt_port *omgt_port_session = NULL; + + // determine how we've been invoked + cmdName = strrchr(argv[0], '/'); // Find last '/' in path + if (cmdName != NULL) { + cmdName++; // Skip over last '/' + } else { + cmdName = argv[0]; + } + + // Initialize + + strParameter[0] = '\0'; + + + // parse options and parameters + while (-1 != (c = getopt(argc, argv, opts))) { + switch (c) { + case 'D': + g_debugMode = 1; + break; + + case 't': + errno = 0; + StringCopy(parameter, optarg, sizeof(parameter)); + if ((p = strchr(parameter, ',')) != NULL) { + *p = '\0'; + } + if (FSUCCESS != StringToUint64(&destPortGuid, parameter, NULL, 0, TRUE)) { + fprintf(stderr, "%s: Error: Invalid GUID: %s\n", cmdName, optarg); + usage(cmdName); + } + break; + + case 'l': +#if !LIST_FILE_SUPPORTED + fprintf(stderr, "Error: l option is not supported at this time\n"); + exit(1); +#endif + break; + + case 'v': + g_verbose = 1; + break; + + case 'q': + g_quiet = 1; + break; + + case 'h': + if (FSUCCESS != StringToUint8(&hfi, optarg, NULL, 0, TRUE)) { + fprintf(stderr, "%s: Error: Invalid HFI Number: %s\n", cmdName, optarg); + usage(cmdName); + } + g_gotHfi = 1; + break; + + case 'o': + if (FSUCCESS != StringToUint8(&port, optarg, NULL, 0, TRUE)) { + fprintf(stderr, "%s: Error: Invalid Port Number: %s\n", cmdName, optarg); + usage(cmdName); + } + g_gotPort = 1; + break; + + case 'C': + if (!g_configNum) { + if (FSUCCESS != StringToUint8(&g_configNum, optarg, NULL, 0, TRUE)) { + fprintf(stderr, "%s: Error: Invalid Config-option Number: %s\n", cmdName, optarg); + usage(cmdName); + } + } else { + fprintf(stderr, "%s: Error: Only one instance of -C allowed\n\n", cmdName); + usage(cmdName); + } + break; + + case 's': + g_gotStrParam = 1; + StringCopy(strParameter, optarg, sizeof(strParameter)); + break; + + case 'i': + g_gotIntParam = 1; + if (FSUCCESS != StringToInt32(&integerParameter, optarg, NULL, 0, TRUE)) { + fprintf(stderr, "%s: Error: Invalid integer parameter: %s\n", cmdName, optarg); + usage(cmdName); + } + break; + + case 'S': + g_gotSave = 1; + break; + + default: + usage(cmdName); + break; + + } + } + + // user has requested display of help + if (argc == 1) { + usage(cmdName); + exit(0); + } + + if (-1 == destPortGuid) { + fprintf(stderr, "%s: Error: Must specify a target GUID\n", cmdName); + exit(1); + } + + if (g_configNum == 0) { + fprintf(stderr, "%s: Error: must enter a configuration option number\n", cmdName); + exit(1); + } + + if (g_quiet && (g_debugMode || g_verbose)) { + fprintf(stderr, "%s: Error: Can not specify both -q and -D|-v\n", cmdName); + exit(1); + } + + // Get the LID + + struct omgt_params params = {.debug_file = (g_verbose || g_debugMode) ? stderr : NULL}; + status = omgt_open_port_by_num(&omgt_port_session, hfi, port, ¶ms); + if (status != 0) { + fprintf(stderr, "%s: Error: Unable to open fabric interface.\n", cmdName); + exit(1); + } + + if (getDestPath(omgt_port_session, destPortGuid, cmdName, &path) != FSUCCESS) { + fprintf(stderr, "%s: Error finding destination path\n", cmdName); + status = FERROR; + goto err_exit; + } + + // Send a ClassPortInfo to see if the switch is responding + + status = sendClassPortInfoMad(omgt_port_session, &path, &mad); + if (status != FSUCCESS) { + fprintf(stderr, "%s: Error: Failed to send/rcv ClassPortInfo\n", cmdName); + goto err_exit; + } + + // Get a session ID + + sessionID = getSessionID(omgt_port_session, &path); + if (sessionID == (uint16)-1) { + fprintf(stderr, "%s: Error: Failed to obtain sessionID\n", cmdName); + status = FERROR; + goto err_exit; + } + + // Perform the config option + + switch (g_configNum) { + case 1: + if (!g_gotStrParam) { + fprintf(stderr, "%s: Error: must enter a string parameter (-s) with configuration option 1\n", cmdName); + status = FERROR; + } else if (strlen(strParameter) > 63) { + fprintf(stderr, "%s: Error: Invalid node description: %s\n", cmdName, strParameter); + status = FERROR; + } else { + metaIndex = getMetaDataIndexByField(systemMetaData, systemMetaDataSize, "NODE_STRING"); + } + if (metaIndex < 0) { + fprintf(stderr, "%s: Error: can not find NODE_STRING in metaData table\n", cmdName); + status = FERROR; + } + if (status == FSUCCESS) { + strncpy((char*)nodeDescription, strParameter, NODE_DESC_SIZE); + nodeDescription[NODE_DESC_SIZE-1]=0; + status = sendSysTableAccessSetMad(omgt_port_session, &path, &mad, sessionID, (uint8)metaIndex, + (uint8)NODE_DESC_SIZE, nodeDescription); + if (status != FSUCCESS) { + fprintf(stderr, "%s: Error: Failed to send/rcv SysTableAccessSet MAD\n", cmdName); + status = FERROR; + } + } + break; + + case 2: + fprintf(stderr, "%s: Error: vendor key no longer supported\n", cmdName); + status = FERROR; + break; + + case 3: + fprintf(stderr, "%s: Error: MTU Capability no longer supported\n", cmdName); + status = FERROR; + break; + + case 4: + fprintf(stderr, "%s: Error: VL Capability no longer supported\n", cmdName); + status = FERROR; + break; + + case 5: + if (!g_gotIntParam) { + fprintf(stderr, "%s: Error: must enter a integer parameter (-i) with configuration option 5\n", cmdName); + status = FERROR; + } else if ((integerParameter < 1) || (integerParameter > 15)) { + fprintf(stderr, "%s: Error: bad integer value %d; must be 1-1X, 2-2X, 3-2X_1X, 4-3X, 5-3_1X, 6-3X_2X, 7-3X_2X_1X, 8-4X, 9-4X_1X, 10-4X_2X, 11-4X_2X_1X, 12-4X_3X, 13-4X_3X_1X, 14-4X_3X_2X, 15-4X_3X_2X_1X\n", cmdName, integerParameter); + status = FERROR; + } else { + metaIndex = getMetaDataIndexByField(&portMetaData[0], portMetaDataSize, "LINK_WIDTH_SUPPORTED"); + if (metaIndex < 0) { + fprintf(stderr, "%s: Error: can not find LINK WIDTH SUPPORTED in metaData table\n", cmdName); + status = FERROR; + } + } + if (status == FSUCCESS) { + numPorts = getNumPorts(omgt_port_session, &path, sessionID); + linkWidth = integerParameter; + // make sure that port1 always has 4x enabled + port1LinkWidth = linkWidth | 0x8; + + linkWidth = ntoh32(linkWidth); + port1LinkWidth = ntoh32(port1LinkWidth); + + // first set port 1 + status = sendPortTableAccessSetMad(omgt_port_session, &path, &mad, sessionID, + (uint8)metaIndex, 1, 4, (uint8 *)&port1LinkWidth); + if (status != FSUCCESS) { + fprintf(stderr, "%s: Error: Failed to send/rcv PortTableAccessSet MAD for port %d\n", cmdName, 1); + status = FERROR; + } + + // now set ports 2 through numPorts + for (i = 2; i <= numPorts; i++) { + status = sendPortTableAccessSetMad(omgt_port_session, &path, &mad, sessionID, + (uint8)metaIndex, i, 4, (uint8 *)&linkWidth); + if (status != FSUCCESS) { + fprintf(stderr, "%s: Error: Failed to send/rcv PortTableAccessSet MAD for port %d\n", cmdName, i); + status = FERROR; + } + } + } + break; + + case 7: + if (!g_gotIntParam) { + fprintf(stderr, "%s: Error: must enter a integer parameter (-i) with configuration option 7\n", cmdName); + status = FERROR; + } else if ((integerParameter < 1) || (integerParameter > 3)) { + fprintf(stderr, "%s: Error: bad integer value %d; must be 1 for 12G, 2 for 25G, 3 for 12G/25G\n", cmdName, integerParameter); + status = FERROR; + } else { + metaIndex = getMetaDataIndexByField(&portMetaData[0], portMetaDataSize, "LINK_SPEED_SUPPORTED"); + if (metaIndex < 0) { + fprintf(stderr, "%s: Error: can not find LINK SPEED SUPPORTED in metaData table\n", cmdName); + status = FERROR; + } + } + if (status == FSUCCESS) { + numPorts = getNumPorts(omgt_port_session, &path, sessionID); + linkSpeed = integerParameter; + + linkSpeed = ntoh32(linkSpeed); + // set ports 1 through numPorts + for (i = 1; i <= numPorts; i++) { + status = sendPortTableAccessSetMad(omgt_port_session, &path, &mad, sessionID, + (uint8)metaIndex, i, 4, (uint8 *)&linkSpeed); + if (status != FSUCCESS) { + fprintf(stderr, "%s: Error: Failed to send/rcv PortTableAccessSet MAD for port %d\n", cmdName, i); + status = FERROR; + } + } + } + break; + case 8: + if (!g_gotIntParam) { + fprintf(stderr, "%s: Error: must enter an integer paramemter (-i) with configuration option 8\n", cmdName); + status = FERROR; + } else if ((integerParameter < 0) || (integerParameter > 1)) { + fprintf(stderr, "%s: Error: bad integer value %d; must be 0 for disable or 1 for enable\n", cmdName, integerParameter); + status = FERROR; + } else { + metaIndex = getMetaDataIndexByField(&portMetaData[0], portMetaDataSize, "FM_ENABLED"); + if (metaIndex < 0) { + fprintf(stderr, "%s: Error: can not find FM ENABLED in metaData table\n", cmdName); + status = FERROR; + } + } + if (status == FSUCCESS) { + numPorts = getNumPorts(omgt_port_session, &path, sessionID); + fmEnabled = integerParameter; + + fmEnabled = ntoh32(fmEnabled); + // set ports 1 through numPorts + for (i = 1; i <= numPorts; i++) { + status = sendPortTableAccessSetMad(omgt_port_session, &path, &mad, sessionID, + (uint8)metaIndex, i, 4, (uint8 *)&fmEnabled); + if (status != FSUCCESS) { + fprintf(stderr, "%s: Error: Failed to send/rcv PortTableAccessSet MAD for port %d\n", cmdName, i); + status = FERROR; + } + } + } + break; + case 9: + if (!g_gotIntParam) { + fprintf(stderr, "%s: Error: must enter an integer paramemter (-i) with configuration option 9\n", cmdName); + status = FERROR; + } else if ((integerParameter < 0) || (integerParameter > 7)) { + fprintf(stderr, "%s: Error: bad integer value %d; must be 0-16b, 1-14b/16b, 2-48b/16b, 3-48b/14b/16b, 4-per lane/16b, 5-per lane/14b/16b, 6-per lane/48b/16b, 7-per lane/48b/14b/16b\n", cmdName, integerParameter); + status = FERROR; + } else { + metaIndex = getMetaDataIndexByField(&portMetaData[0], portMetaDataSize, "LTP_CRC_MODE_SUPPORTED"); + if (metaIndex < 0) { + fprintf(stderr, "%s: Error: can not find CRC in metaData table\n", cmdName); + status = FERROR; + } + } + if (status == FSUCCESS) { + numPorts = getNumPorts(omgt_port_session, &path, sessionID); + linkCRCMode = integerParameter; + + linkCRCMode = ntoh32(linkCRCMode); + // set ports 1 through numPorts + for (i = 1; i <= numPorts; i++) { + status = sendPortTableAccessSetMad(omgt_port_session, &path, &mad, sessionID, + (uint8)metaIndex, i, 4, (uint8 *)&linkCRCMode); + if (status != FSUCCESS) { + fprintf(stderr, "%s: Error: Failed to send/rcv PortTableAccessSet MAD for port %d\n", cmdName, i); + status = FERROR; + } + } + } + break; + case 10: + if (!g_gotIntParam) { + fprintf(stderr, "%s: Error: must enter an integer paramemter (-i) with configuration option 10\n", cmdName); + status = FERROR; + } else if (integerParameter < 0 || integerParameter > 7) { + fprintf(stderr, "%s: Error: bad integer value %d; Must be 0-7", cmdName, integerParameter); + status = FERROR; + } else { + metaIndex = getMetaDataIndexByField(&portMetaData[0], portMetaDataSize, "VCU"); + if (metaIndex < 0) { + fprintf(stderr, "%s: Error: can not find vCU in metaData table\n", cmdName); + status = FERROR; + } + } + if (status == FSUCCESS) { + numPorts = getNumPorts(omgt_port_session, &path, sessionID); + vCU = integerParameter; + + vCU = ntoh32(vCU); + // set ports 1 through numPorts + for (i = 1; i <= numPorts; i++) { + status = sendPortTableAccessSetMad(omgt_port_session, &path, &mad, sessionID, + (uint8)metaIndex, i, 4, (uint8 *)&vCU); + if (status != FSUCCESS) { + fprintf(stderr, "%s: Error: Failed to send/rcv PortTableAccessSet MAD for port %d\n", cmdName, i); + status = FERROR; + } + } + } + break; + case 11: + if (!g_gotIntParam) { + fprintf(stderr, "%s: Error: must enter an integer paramemter (-i) with configuration option 11\n", cmdName); + status = FERROR; + } else if (integerParameter < 0 || integerParameter > 1) { + fprintf(stderr, "%s: Error: bad integer value %d; must be 0 for disable or 1 for enable\n", cmdName, integerParameter); + status = FERROR; + } else { + metaIndex = getMetaDataIndexByField(&portMetaData[0], portMetaDataSize, "EXTERNAL_LOOPBACK_ALLOWED"); + if (metaIndex < 0) { + fprintf(stderr, "%s: Error: can not find EXTERNAL LOOPBACK ALLOWED in metaData table\n", cmdName); + status = FERROR; + } + } + if (status == FSUCCESS) { + numPorts = getNumPorts(omgt_port_session, &path, sessionID); + extLoopbackAllowed = integerParameter; + + extLoopbackAllowed = ntoh32(extLoopbackAllowed); + // set ports 1 through numPorts + for (i = 1; i <= numPorts; i++) { + status = sendPortTableAccessSetMad(omgt_port_session, &path, &mad, sessionID, + (uint8)metaIndex, i, 4, (uint8 *)&extLoopbackAllowed); + if (status != FSUCCESS) { + fprintf(stderr, "%s: Error: Failed to send/rcv PortTableAccessSet MAD for port %d\n", cmdName, i); + status = FERROR; + } + } + } + break; + default: + if (sessionID>0) releaseSession(omgt_port_session, &path, sessionID); + fprintf(stderr, "Error: Invalid configuration option number %d\n", g_configNum); + usage(cmdName); + break; + } + + if (g_gotSave) { + // save configuration to make change permanent + status = sendSaveConfigMad(omgt_port_session, &path, &mad, sessionID); + if (status != FSUCCESS) { + fprintf(stderr, "%s: Error: Failed to send/rcv SaveConfig MAD\n", cmdName); + status = FERROR; + } + } + + if (sessionID>0) releaseSession(omgt_port_session, &path, sessionID); + + printf("opaswconfigure completed\n"); + +err_exit: + omgt_close_port(omgt_port_session); + + if (status == FSUCCESS) + exit(0); + else + exit(1); + +} diff --git a/IbaTools/opasw/opaswfwconfigure/Makefile b/IbaTools/opasw/opaswfwconfigure/Makefile new file mode 100644 index 0000000..1229851 --- /dev/null +++ b/IbaTools/opasw/opaswfwconfigure/Makefile @@ -0,0 +1,158 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** +# Makefile for opaswfwconfigure + +# Include Make Control Settings +include $(TL_DIR)/$(PROJ_FILE_DIR)/Makesettings.project + +#=============================================================================# +# Definitions: +#-----------------------------------------------------------------------------# + +# Name of SubProjects +DS_SUBPROJECTS = +# name of executable or downloadable image +EXECUTABLE = $(BUILDDIR)/opaswfwconfigure$(EXE_SUFFIX) +# list of sub directories to build +DIRS = +# C files (.c) +CFILES = \ + opaswfwconfigure.c + # Add more c files here +# C++ files (.cpp) +CCFILES = \ + # Add more cpp files here +# lex files (.lex) +LFILES = \ + # Add more lex files here +# archive library files (basename, $ARFILES will add MOD_LIB_DIR/prefix and suffix) +LIBFILES= +# Windows Resource Files (.rc) +RSCFILES = +# Windows IDL File (.idl) +IDLFILE = +# Windows Linker Module Definitions (.def) file for dll's +DEFFILE = +# targets to build during INCLUDES phase (add public includes here) +INCLUDE_TARGETS = \ + # Add more h hpp files here +# Non-compiled files + # Add more files here +MISC_FILES = +# all source files +SOURCES = $(CFILES) $(CCFILES) $(LFILES) $(RSCFILES) $(IDLFILE) +# Source files to include in DSP File +DSP_SOURCES = $(INCLUDE_TARGETS) $(SOURCES) $(MISC_FILES) \ + $(RSCFILES) $(DEFFILE) $(MAKEFILE) +# all object files +OBJECTS = $(CFILES:.c=$(OBJ_SUFFIX)) $(CCFILES:.cpp=$(OBJ_SUFFIX)) \ + $(LFILES:.lex=$(OBJ_SUFFIX)) +RSCOBJECTS = $(RSCFILES:.rc=$(RES_SUFFIX)) +# targets to build during LIBS phase +LIB_TARGETS_IMPLIB = +LIB_TARGETS_ARLIB = # $(LIB_PREFIX)ResourceTest$(ARLIB_SUFFIX) +LIB_TARGETS_EXP = $(LIB_TARGETS_IMPLIB:$(ARLIB_SUFFIX)=$(EXP_SUFFIX)) +LIB_TARGETS_MISC = +# targets to build during CMDS phase +CMD_TARGETS_SHLIB = +CMD_TARGETS_EXE = $(EXECUTABLE) +CMD_TARGETS_MISC = +# files to remove during clean phase +CLEAN_TARGETS_MISC = +CLEAN_TARGETS = $(OBJECTS) $(RSCOBJECTS) $(IDL_TARGETS) $(CLEAN_TARGETS_MISC) +# other files to remove during clobber phase +CLOBBER_TARGETS_MISC= +# sub-directory to install to within bin +BIN_SUBDIR = +# sub-directory to install to within include +INCLUDE_SUBDIR = + +# Additional Settings +#CLOCALDEBUG = User defined C debugging compilation flags [Empty] +#CCLOCALDEBUG = User defined C++ debugging compilation flags [Empty] +#CLOCAL = User defined C flags for compiling [Empty] +#CCLOCAL = User defined C++ flags for compiling [Empty] +#BSCLOCAL = User flags for Browse File Builder [Empty] +#DEPENDLOCAL = user defined makedepend flags [Empty] +#LINTLOCAL = User defined lint flags [Empty] +#LOCAL_INCLUDE_DIRS = User include directories to search for C/C++ headers [Empty] +#LDLOCAL = User defined C flags for linking [Empty] +#IMPLIBLOCAL = User flags for Object Lirary Manager [Empty] +#MIDLLOCAL = User flags for IDL compiler [Empty] +#RSCLOCAL = User flags for resource compiler [Empty] +#LOCALDEPLIBS = User libraries to include in dependencies [Empty] +#LOCALLIBS = User libraries to use when linking [Empty] +# (in addition to LOCALDEPLIBS) +#LOCAL_LIB_DIRS = User library directories for libpaths [Empty] + +LOCALDEPLIBS=$(IBACCESS_USER_LIBS) opaswcommon opamgt-priv +LOCAL_INCLUDE_DIRS= +LOCALLIBS=$(OPENIB_USER_LIBS) z crypto +LOCAL_LIB_DIRS=$(OPENIB_USER_LIB_DIRS) $(IBACCESS_USER_LIB_DIRS) + +# Include Make Rules definitions and rules +include $(TL_DIR)/IbaTools/Makerules.module + +#=============================================================================# +# Overrides: +#-----------------------------------------------------------------------------# +#CCOPT = # C++ optimization flags, default lets build config decide +#COPT = # C optimization flags, default lets build config decide +#SUBSYSTEM = Subsystem to build for (none, console or windows) [none] +# (Windows Only) +#USEMFC = How Windows MFC should be used (none, static, shared, no_mfc) [none] +# (Windows Only) +#=============================================================================# + +#=============================================================================# +# Rules: +#-----------------------------------------------------------------------------# +# process Sub-directories +include $(TL_DIR)/Makerules/Maketargets.toplevel + +# build cmds and libs +include $(TL_DIR)/Makerules/Maketargets.build + +# install for includes, libs and cmds phases +include $(TL_DIR)/Makerules/Maketargets.install + +# install for stage phase +include $(TL_DIR)/Makerules/Maketargets.stage +STAGE:: + #$(VS)$(STAGE_INSTALL) $(STAGE_INSTALL_DIR_OPT) $(PROJ_STAGE_FASTFABRIC_DIR) $(EXECUTABLE) + $(VS)$(STAGE_INSTALL) $(STAGE_INSTALL_DIR_OPT) $(PROJ_STAGE_BIN_DIR) $(EXECUTABLE) + +# Unit test execution +#include $(TL_DIR)/Makerules/Maketargets.runtest + +#=============================================================================# + +#=============================================================================# +# DO NOT DELETE THIS LINE -- make depend depends on it. +#=============================================================================# diff --git a/IbaTools/opasw/opaswfwconfigure/opaswfwconfigure.c b/IbaTools/opasw/opaswfwconfigure/opaswfwconfigure.c new file mode 100644 index 0000000..caa2917 --- /dev/null +++ b/IbaTools/opasw/opaswfwconfigure/opaswfwconfigure.c @@ -0,0 +1,1478 @@ +/* BEGIN_ICS_COPYRIGHT7 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT7 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* work around conflicting names */ + +#include "iba/ib_types.h" +#include "iba/ib_sm_priv.h" +#include "iba/ib_helper.h" +#include "opamgt_sa_priv.h" +#include +#include "opaswcommon.h" +#include "opaswmetadata.h" +#include "zlib.h" + +/* defines */ + +#define LIST_FILE_SUPPORTED 0 + +#define CR '\r' +#define NL '\n' +#define NUL '\0' +#define OB '[' +#define CB ']' +#define EQ '=' +#define QU '\"' +#define SP ' ' + +#define TABLE_BLOCKSIZE 25 +#define INBUFFERSIZE 4096 + +#define OPASW_INIBIN "iniXedge.inibin" +#define VIPER_INIBIN "iniViper.inibin" +#define PRR_INIBIN "prrIniEdge.inibin" + +#define INI_MAX_SIZE (16 * 1024) + +#define SIGNATURE 0x50724F6d +#define EEPROMSIZE (64 * 1024) + +#define FW_RESP_WAIT_TIME 2000 + +#ifndef min +#define min(a,b) (((a)<(b))?(a):(b)) +#endif +#ifndef max +#define max(a,b) (((a)>(b))?(a):(b)) +#endif + +/* typedefs */ + +/* global variables */ + +int g_debugMode = 0; +int g_verbose = 0; +int g_quiet = 0; +int g_gotHfi = 0; +int g_gotPort = 0; +int g_gotModule = 0; +int g_gotSecondary = 0; +int g_fileParam = 0; +int g_dirParam = 0; +int g_respTimeout = FW_RESP_WAIT_TIME; + +char fwFileName[FNAME_SIZE]; +char inibinFileName[FNAME_SIZE]; +char dirName[DNAME_SIZE]; + +char *cmdName; + +uint8 switchNodeDesc[64]; +EUI64 switchNodeGuid; +EUI64 switchSystemImageGuid; +uint32 newNumPorts; +uint32 fmPushButtonState; +uint32 newPortEntrySize; +uint32 oldNumPorts; +uint32 oldPortEntrySize; +uint32 *oldPortDataTable; +uint32 *oldPortMetaTable; +IB_PATH_RECORD path; +VENDOR_MAD mad; +uint16 sessionID = 0; +uint32 max_data_table_type; + +#define DEBUG_USE_FILE 0 + +/* for PRR stuff */ + +// SYSTEM_TABLE definitions +#define SYSTEM_TABLE_FIELD_RESERVED 0 +#define SYSTEM_TABLE_FIELD_NODE_STRING 1 +#define SYSTEM_TABLE_FIELD_SYSTEM_IMAGE_GUID 2 +#define SYSTEM_TABLE_FIELD_NODE_GUID 3 +#define SYSTEM_TABLE_FIELD_NUM_PORTS 8 +#define SYSTEM_TABLE_FIELD_FM_PUSH_BUTTON_STATE 33 + +// PORT_TABLE definitions +#define PORT_TABLE_FIELD_LINK_SPEED_SUPPORTED 7 +#define PORT_TABLE_FIELD_LINK_WIDTH_SUPPORTED 8 +#define PORT_TABLE_FIELD_CRC 22 +#define PORT_TABLE_FIELD_FM_ENABLED 17 +#define PORT_TABLE_FIELD_VCU 28 +#define PORT_TABLE_FIELD_EXTERNAL_LOOPBACK_ALLOWED 30 + +// INI TABLE types +#define INI_TYPE_END_TABLE 0 +#define INI_TYPE_SYSTEM_TABLE 1 +#define INI_TYPE_PORT_TABLE 2 +#define INI_TYPE_DFE_TABLE 3 +#define INI_TYPE_FFE_TABLE 4 +#define INI_TYPE_FFE_INDIRECT_TABLE 5 +#define INI_TYPE_PORT_TYPE_QSFP_TABLE 6 +#define INI_TYPE_PORT_TYPE_CUSTOM_TABLE 7 +#define INI_TYPE_DATA_TABLE_MAX (INI_TYPE_PORT_TYPE_CUSTOM_TABLE + 1) +#define INI_TYPE_META_DATA_TABLE_MAX (INI_TYPE_FFE_INDIRECT_TABLE + 1) + +#define S_S20INI_META_TABLE_ENTRY_START_BIT 0 +#define L_S20INI_META_TABLE_ENTRY_START_BIT 15 +#define S_S20INI_META_TABLE_ENTRY_PROTECTED 15 +#define L_S20INI_META_TABLE_ENTRY_PROTECTED 1 +#define S_S20INI_META_TABLE_ENTRY_BITS 16 +#define L_S20INI_META_TABLE_ENTRY_BITS 16 + +#define S_S20INI_RECORD_HEADER_RECORD_IDX 0 +#define L_S20INI_RECORD_HEADER_RECORD_IDX 6 +#define M_S20INI_RECORD_HEADER_RECORD_IDX (((1 << L_S20INI_RECORD_HEADER_RECORD_IDX) - 1) << S_S20INI_RECORD_HEADER_RECORD_IDX) +#define S_S20INI_RECORD_HEADER_DATA_WORDS 16 +#define L_S20INI_RECORD_HEADER_DATA_WORDS 12 +#define M_S20INI_RECORD_HEADER_DATA_WORDS (((1 << L_S20INI_RECORD_HEADER_DATA_WORDS) - 1) << S_S20INI_RECORD_HEADER_DATA_WORDS) +#define S_S20INI_RECORD_HEADER_TABLE_TYPE 28 +#define L_S20INI_RECORD_HEADER_TABLE_TYPE 4 +#define M_S20INI_RECORD_HEADER_TABLE_TYPE (((1 << L_S20INI_RECORD_HEADER_TABLE_TYPE) - 1) << S_S20INI_RECORD_HEADER_TABLE_TYPE) + +#define FFE_INDIRECT_TABLE_RECORDS_PER_WORD 2 + +#define SimPrintf printf + +typedef uint8 U8_t; +typedef uint32 U32_t; +typedef uint64 U64_t; +typedef int BOOL; + +typedef struct { + U32_t *ptr; + U32_t entries; + U32_t allocated; + U32_t dataWords; +} S20INI_TABLE_REF; + +typedef struct { + struct S20 *s20; + U32_t numPorts; + U32_t tableType; + U32_t field; + U32_t *v; + U32_t vLenInWords; + U32_t vLenInBits; + U32_t v32; + U32_t recordIdx; + U32_t recordBits; + const char *argv; + S20INI_TABLE_REF *metaDataRef; + S20INI_TABLE_REF *dataRef; + S20INI_TABLE_REF dataTables[INI_TYPE_DATA_TABLE_MAX]; + S20INI_TABLE_REF metaDataTables[INI_TYPE_META_DATA_TABLE_MAX]; +} S20INI; + +typedef struct { + U32_t val; + const char *text; +} S20INI_ENCODING; + +struct s20iniHandler; + +typedef struct { + struct S20 *s20; + const struct s20iniHandler *infoTable; + const char *outputFn; + U32_t line; + const char *inputFn; + int argi; + int argc; + int tableType; // this needs to be an int for the logic below to work correctly + U32_t field; + U32_t recordIdx; + U32_t portWordsPerPort; + U32_t wordsPerIdx; + U32_t startBitIncrement; + U32_t recordsPerWord; + U32_t numPorts; + U32_t *recordData; + const U32_t *metaDataPtr; + int result; + U32_t scanIdx; + S20INI_TABLE_REF *recordDataRef; + S20INI_TABLE_REF metaData[INI_TYPE_DATA_TABLE_MAX]; // yes this should be INI_TYPE_DATA_TABLE_MAX + S20INI_TABLE_REF tableData[INI_TYPE_DATA_TABLE_MAX]; + S20INI_TABLE_REF portCommon; + BOOL portCommonCopied[256]; // assumes max of 255 ports + char *argv[256]; + char src[2048]; + char dst[4096]; +} S20INI_TOBIN; + +typedef BOOL(*procFieldTextIn_t)(S20INI_TOBIN *, int idx, BOOL *insert, U32_t *value); +typedef BOOL(*procFieldTextOut_t)(S20INI *); + +typedef struct s20iniHandler { + procFieldTextIn_t procTextIn; + procFieldTextOut_t procTextOut; + const S20INI_ENCODING *encoding; + const char *name; +} s20iniHandler_t; + +#define CRC32_POLYNOMIAL 0x04C11DB7 +#define CRC32_PRELOAD 0x46af6449 +#define CRC32_REFLECT_POLYNOMIAL 0xEDB88320 // 1110-1101-1011-1000-1000-0011-0010-0000 +#define CRC32_REFLECT_PRELOAD 0x9226f562 // 1001-0010-0010-0110-1111-0101-0110-0010 + +S20INI ini; + +static U32_t crc32AddByte(U32_t crc, U8_t u8) { + U32_t i = 8; + do { + crc = ((crc >> 1) | (u8 << 31)) ^ ((crc & 1) ? CRC32_REFLECT_POLYNOMIAL : 0); + u8 >>= 1; + } while(--i); + return crc; +} + +U32_t crc32AddBytes(U32_t crc, U32_t u32, U8_t bytes) { + // note that we are doing this using big-endian byte ordering, since S20 is big-endian + do { + crc = crc32AddByte(crc, u32 >> 24); + u32 <<= 8; + } while(--bytes); + return crc; +} + +U32_t crc32Finish(U32_t crc) { + crc = ~crc32AddBytes(crc, 0, 4); + crc = (crc >> 24) | ((crc >> 8) & 0xff00) | (crc << 24) | ((crc << 8) & 0xff0000); + return crc; +} + +U32_t crc32Init() { + return CRC32_REFLECT_PRELOAD; +} + +U32_t crc32Calculate(U8_t *data, U32_t bytes) { + U32_t crc = crc32Init(); + U32_t i; + U32_t val; + + for(i = 0; i < bytes; i += 4) { + val = (data[i] << 24) + (data[i + 1] << 16) + (data[i + 2] << 8) + data[i + 3]; + crc = crc32AddBytes(crc, val, 4); + } + return crc32Finish(crc); +} + +void s20iniFieldInsert(const U32_t *metaData, U32_t *dst, U32_t entryIdx, U32_t data) { + U32_t meta = metaData[entryIdx]; + U32_t start = (meta >> S_S20INI_META_TABLE_ENTRY_START_BIT) & ((1 << L_S20INI_META_TABLE_ENTRY_START_BIT) - 1); + U32_t startBit = start & 0x1f; + U32_t startIdx = start >> 5; + U32_t bits = (meta >> S_S20INI_META_TABLE_ENTRY_BITS) & ((1 << L_S20INI_META_TABLE_ENTRY_BITS) - 1); + U32_t mask = ((1 << bits) - 1) << startBit; + dst[startIdx] = ((data << startBit) & mask) | (dst[startIdx] & ~mask); +} + +int s20iniFieldIsolate(const U32_t *metaData, U32_t *src, U32_t entryIdx) { + U32_t meta = metaData[entryIdx]; + U32_t start = (meta >> S_S20INI_META_TABLE_ENTRY_START_BIT) & ((1 << L_S20INI_META_TABLE_ENTRY_START_BIT) - 1); + U32_t startBit = start & 0x1f; + U32_t startIdx = start >> 5; + U32_t bits = (meta >> S_S20INI_META_TABLE_ENTRY_BITS) & ((1 << L_S20INI_META_TABLE_ENTRY_BITS) - 1); + return (src[startIdx] >> startBit) & ((1 << bits) - 1); +} + +int readIniBinFile(char *fileName, U8_t *binBuf) +{ + int totalRead = -1; + int nread; + U8_t *p; + FILE *fp; + + if ((fp = fopen(fileName, "r")) == NULL) { + if (errno == ENOENT) + fprintf(stderr, "Error opening file %s ... old style EMFW not supported\n", fileName); + else + fprintf(stderr, "Error opening file %s for input: %s\n", fileName, strerror(errno)); + return(-1); + } + + p = binBuf; + while ((nread = fread(p, 1, 1024, fp)) > 0) { + totalRead += nread; + p += nread; + } + + fclose(fp); + return(totalRead); +} + +#if DEBUG_USE_FILE +int writeIniBinFile(char *fileName, U8_t *binBuf, int bufSize) +{ + int totalWritten = 0; + int nwritten; + int chunkSize; + U8_t *p; + FILE *fp; + + if ((fp = fopen(fileName, "w")) == NULL) { + fprintf(stderr, "Error opening file %s for output: %s\n", fileName, strerror(errno)); + return(-1); + } + + p = binBuf; + while (totalWritten < bufSize) { + if ((bufSize - totalWritten) < 1024) + chunkSize = bufSize - totalWritten; + else + chunkSize = 1024; + nwritten = fwrite(p, 1, chunkSize, fp); + totalWritten += nwritten; + p += nwritten; + } + + fclose(fp); + return(totalWritten); +} +#endif + +static U32_t S20iniMetaDataEntryLenGet(U32_t entry) { + return (entry >> S_S20INI_META_TABLE_ENTRY_BITS) & ((1 << L_S20INI_META_TABLE_ENTRY_BITS) - 1); +} + +static U32_t S20iniMetaDataEntryStartGet(U32_t entry) { + return (entry >> S_S20INI_META_TABLE_ENTRY_START_BIT) & ((1 << L_S20INI_META_TABLE_ENTRY_START_BIT) - 1); +} + +static U32_t S20iniMetaDataEntryProtectedGet(U32_t entry) { + return (entry >> S_S20INI_META_TABLE_ENTRY_PROTECTED) & ((1 << L_S20INI_META_TABLE_ENTRY_PROTECTED) - 1); +} + +void S20iniMetaDataDump(S20INI *ini) { + U32_t i; + U32_t entry; + S20INI_TABLE_REF *tableRef = &ini->metaDataTables[ini->tableType]; + + printf("Dumping table type %d\n", ini->tableType); + + for(i = 0; i < tableRef->entries; ++i) { + entry = tableRef->ptr[i]; + printf("idx keyword %d len keyword %d start keyword %d protected keyword %d\n", + i, S20iniMetaDataEntryLenGet(entry), + S20iniMetaDataEntryStartGet(entry), + S20iniMetaDataEntryProtectedGet(entry)); + } +} + +BOOL S20iniFieldOut(S20INI *ini) { + + if (ini->vLenInBits <= 32) { + char s[16]; + if (ini->vLenInBits <= 3) { + strcpy(s, "field %d=%lu"); + } else { + if (ini->vLenInBits <= 4) { + strcpy(s, "field %d=0x%x"); + } else { + snprintf(s, sizeof(s), "field %%d=0x%%0%dx", (int)((ini->vLenInBits + 3) >> 2)); + } + } + printf(s, ini->field, *ini->v); + } else { + printf("field %d=0x%08x", ini->field, *ini->v); + while(--ini->vLenInWords) { + ++ini->v; + printf("%08x", *ini->v); + } + } + printf("\n"); + return FALSE; +} + +BOOL S20iniFieldValue(S20INI *ini) { + U32_t startBit; + U32_t entry; + + entry = ini->metaDataRef->ptr[ini->field]; + ini->vLenInBits = S20iniMetaDataEntryLenGet(entry); + if (ini->vLenInBits == 0) + return TRUE; + ini->vLenInWords = ((ini->vLenInBits + 31) >> 5); + + startBit = S20iniMetaDataEntryStartGet(entry) + (ini->recordIdx * ini->recordBits); + + if (ini->vLenInBits <= 32) { + if (ini->recordBits & 31) { + U32_t recordsPerU32 = 32 / ini->recordBits; + U32_t modIdx = ini->recordIdx % recordsPerU32; + startBit -= (modIdx * ini->recordBits); + startBit += ((recordsPerU32 - modIdx - 1) * ini->recordBits); + } + ini->v32 = ini->dataRef->ptr[startBit >> 5]; + if (ini->vLenInBits < 32) + ini->v32 = (ini->v32 >> (startBit & 0x1f)) & ((1 << ini->vLenInBits) - 1); + ini->v = &ini->v32; + ini->vLenInWords = 1; + if ((ini->tableType == INI_TYPE_SYSTEM_TABLE) && (ini->field == SYSTEM_TABLE_FIELD_NUM_PORTS)) + ini->numPorts = ini->v32; + } else { + ini->v = &ini->dataRef->ptr[startBit >> 5]; + ini->vLenInWords = ((ini->vLenInBits + 31) >> 5); + } + return FALSE; +} + +U32_t S20iniFieldValueOccurrences(S20INI *ini, U32_t value) { + U32_t count = 0; + + for(ini->recordIdx = 0; ini->recordIdx < ini->numPorts; ++ini->recordIdx) { + if (S20iniFieldValue(ini)) + break; + if (ini->vLenInWords == 1) + if (ini->v32 == value) + ++count; + } + return count; +} + +static U32_t s20iniTableWords(S20INI_TABLE_REF *tref) { + U32_t result = 0; + U32_t i; + U32_t entry; + U32_t bits; + U32_t val; + + for(i = 0; i < tref->entries; ++i) { + entry = tref->ptr[i]; + bits = S20iniMetaDataEntryLenGet(entry); + if (bits) { + val = (S20iniMetaDataEntryStartGet(entry) + bits + 31) >> 5; + if (val > result) + result = val; + } + } + return result; +} + +void S20iniDataDump(S20INI *ini) { + struct S20INI_COMMON { + U32_t count; + U32_t value; + U32_t recordIdx; + } *common; + + ini->recordBits = 0; + ini->recordIdx = 0; + ini->dataRef = &ini->dataTables[ini->tableType]; + + switch(ini->tableType) { + case INI_TYPE_SYSTEM_TABLE: + ini->metaDataRef = &ini->metaDataTables[INI_TYPE_SYSTEM_TABLE]; + + printf("dump of system data table type %d\n", ini->tableType); + for(ini->field = 0; ini->field < ini->metaDataRef->entries; ++ini->field) { + if (S20iniFieldValue(ini)) + continue; + if (S20iniFieldOut(ini)) + return; + printf("\n"); + } + break; + case INI_TYPE_PORT_TABLE: + ini->metaDataRef = &ini->metaDataTables[INI_TYPE_PORT_TABLE]; + printf("dump of port data table type %d\n", ini->tableType); + + if (ini->numPorts) + ini->recordBits = (ini->dataRef->entries / ini->numPorts) * 32; + + if (ini->metaDataRef->entries) { + BOOL anyCommon = FALSE; + common = (struct S20INI_COMMON *)malloc(ini->metaDataRef->entries * sizeof(*common)); + if (common != NULL) { + memset(common, 0, ini->metaDataRef->entries * sizeof(*common)); + + for(ini->field = 1; ini->field < ini->metaDataRef->entries; ++ini->field) { + U32_t recordIdx; + for(recordIdx = 0; recordIdx < ini->numPorts; ++recordIdx) { + ini->recordIdx = recordIdx; // this gets corrupted by S20iniFieldValueOccurrences + if (S20iniFieldValue(ini)) + continue; + if (ini->vLenInWords == 1) { + if ((common[ini->field].count == 0) || (common[ini->field].value != ini->v32)) { + U32_t value = ini->v32; + U32_t count = S20iniFieldValueOccurrences(ini, value); + if ((count >= (ini->numPorts >> 2)) && (count > common[ini->field].count)) { + common[ini->field].count = count; + common[ini->field].value = value; + common[ini->field].recordIdx = recordIdx; + anyCommon = TRUE; + if (count >= (ini->numPorts >> 1)) + break; + } + } + } + } + } + if (anyCommon) { + printf("***port==Common\n"); + for(ini->field = 1; ini->field < ini->metaDataRef->entries; ++ini->field) { + if (common[ini->field].count) { + ini->recordIdx = common[ini->field].recordIdx; + if (S20iniFieldValue(ini)) + continue; + if (S20iniFieldOut(ini)) + return; + printf("\n"); + } + } + } + } + } else + common = NULL; + + for(ini->recordIdx = 0; ini->recordIdx < ini->numPorts; ++ini->recordIdx) { + printf("\n"); + printf("***port=%lu\n", (long)(ini->recordIdx + 1)); + for(ini->field = 0; ini->field < ini->metaDataRef->entries; ++ini->field) { + if (S20iniFieldValue(ini)) + continue; + if (common && common[ini->field].count && (common[ini->field].value == ini->v32)) + continue; + if (S20iniFieldOut(ini)) + return; + printf("\n"); + } + } + if (common != NULL) + free(common); + break; + case INI_TYPE_DFE_TABLE: + case INI_TYPE_FFE_TABLE: + case INI_TYPE_FFE_INDIRECT_TABLE: + ini->metaDataRef = &ini->metaDataTables[ini->tableType]; + if (ini->metaDataRef->entries) { + ini->recordBits = s20iniTableWords(ini->metaDataRef) * 32; + if (ini->tableType == INI_TYPE_FFE_INDIRECT_TABLE) + if (ini->recordBits) + ini->recordBits = 32 / FFE_INDIRECT_TABLE_RECORDS_PER_WORD; + + if (ini->recordBits) { + U32_t records = (ini->dataRef->entries * 32) / ini->recordBits; + + printf("table type %d\n\n", ini->tableType); + for(ini->recordIdx = 0; ini->recordIdx < records; ++ini->recordIdx) { + printf("IDX=%u", ini->recordIdx); + for(ini->field = 0; ini->field < ini->metaDataRef->entries; ++ini->field) { + if (S20iniFieldValue(ini)) + continue; + printf(" "); + if (S20iniFieldOut(ini)) + return; + } + printf("\n"); + } + } + } + break; + case INI_TYPE_PORT_TYPE_QSFP_TABLE: + case INI_TYPE_PORT_TYPE_CUSTOM_TABLE: + ini->metaDataRef = NULL; + + printf("table type %d\n\n", ini->tableType); + ini->field = 0; + + U32_t i; + for(i = 0; i < ini->dataRef->entries; ++i) { + U32_t value = ini->dataRef->ptr[i]; + ini->v = &ini->v32; + ini->vLenInWords = 1; + ini->vLenInBits = 8; + U32_t j; + for(j = 0; j < 4; ++j) { + printf("IDX_KEYWORD =%-4lu", (long)((i << 2) + j)); + ini->v32 = (value >> (24 - (j << 3))) & 0xff; + S20iniFieldOut(ini); + printf("\n"); + } + } + break; + default: + break; + } +} + +void S20iniBinToText(struct S20 *s20, U8_t *data, U32_t dataLen, BOOL show, const char *metaFn, const char *dataFn) { + U32_t i = 0; + S20INI_TABLE_REF *tableRef; + + memset(&ini, 0, sizeof(ini)); + + while((i + 7) < dataLen) { + U32_t header1; + U32_t header2; + U32_t dataWords; + U32_t crc = 0; + U32_t crcCheck; + U32_t tableType; + U32_t recordIdx; + U32_t dataIdx; + + header1 = (data[i + 0] << 24) + (data[i + 1] << 16) + (data[i + 2] << 8) + data[i + 3]; + header2 = (data[i + 4] << 24) + (data[i + 5] << 16) + (data[i + 6] << 8) + data[i + 7]; + if (header1 != ~header2) { + SimPrintf("Header check failed offset=%lu\n", (long)i); + break; + } + i += 8; + dataIdx = i; + dataWords = (header1 & M_S20INI_RECORD_HEADER_DATA_WORDS) >> S_S20INI_RECORD_HEADER_DATA_WORDS; + if (dataWords) { + crcCheck = crc32Calculate(&data[i], dataWords << 2); + i += (dataWords << 2); + crc = (data[i + 0] << 24) + (data[i + 1] << 16) + (data[i + 2] << 8) + data[i + 3]; + i += 4; + if (crcCheck != crc) { + SimPrintf("crc check failed at offset %lu\n", (long)(i - 4)); + break; + } + } + tableType = (header1 & M_S20INI_RECORD_HEADER_TABLE_TYPE) >> S_S20INI_RECORD_HEADER_TABLE_TYPE; + recordIdx = (header1 & M_S20INI_RECORD_HEADER_RECORD_IDX) >> S_S20INI_RECORD_HEADER_RECORD_IDX; + // SimPrintf("tableType=%lu recordIdx=%lu dataWords=%lu\n", (long)tableType, (long)recordIdx, (long)dataWords); + if (recordIdx == 0) { + if (tableType > INI_TYPE_META_DATA_TABLE_MAX) { + SimPrintf("Unrecognized meta data tableType=%lu\n", (long)tableType); + break; + } + tableRef = &ini.metaDataTables[tableType]; + } else { + if (recordIdx == 1) { + if (tableType >= INI_TYPE_DATA_TABLE_MAX) { + SimPrintf("Unrecognized tableType=%lu\n", (long)tableType); + break; + } + tableRef = &ini.dataTables[tableType]; + max_data_table_type = tableType + 1; + } else { + SimPrintf("Unrecognized recordIdx=%lu\n", (long)recordIdx); + break; + } + } + + if (tableRef->ptr != NULL) { + tableRef->ptr = NULL; + free(tableRef->ptr); + } + + tableRef->entries = 0; + tableRef->ptr = 0; + if (dataWords) { + tableRef->dataWords = dataWords; + if ((tableRef->ptr = (U32_t *)malloc(dataWords * sizeof(U32_t))) != NULL) { + U32_t j; + + tableRef->entries = dataWords; + for(j = 0; j < dataWords; ++j) { + tableRef->ptr[j] = (data[dataIdx] << 24) + (data[dataIdx + 1] << 16) + + (data[dataIdx + 2] << 8) + data[dataIdx + 3]; + dataIdx += 4; + } + } else { + SimPrintf("Out of memory allocating dataWords=%lu\n", (long)dataWords); + break; + } + } + } + +} + +int buildNewIniBin(U8_t *binBuffer) +{ + U32_t header1; + U32_t header2; + U32_t crc = 0; + U32_t recordIdx; + U32_t bufSize = 0; + U32_t *newSystemMetaTable; + U32_t *newSystemDataTable; + U32_t *newPortMetaTable; + U32_t *newPortDataTable; + + U8_t *p = binBuffer; + U8_t *q; + int i; + int j; + U32_t ports; + U32_t oldPortBaseIdx; + U32_t newPortBaseIdx; + U32_t startBit; + U8_t segBuffer[2048]; + int segSize; + U32_t nodeBuf[16]; + U32_t guidBuf[2]; + + memset(binBuffer, 0, INI_MAX_SIZE); + + newPortMetaTable = ini.metaDataTables[INI_TYPE_PORT_TABLE].ptr; + newPortDataTable = ini.dataTables[INI_TYPE_PORT_TABLE].ptr; + + oldPortBaseIdx = 0; + newPortBaseIdx = 0; + ports = min(oldNumPorts, newNumPorts); + for (j = 0; j < ports; j++) { + s20iniFieldInsert(newPortMetaTable, &newPortDataTable[newPortBaseIdx], PORT_TABLE_FIELD_LINK_WIDTH_SUPPORTED, + s20iniFieldIsolate(oldPortMetaTable, &oldPortDataTable[oldPortBaseIdx], PORT_TABLE_FIELD_LINK_WIDTH_SUPPORTED)); + s20iniFieldInsert(newPortMetaTable, &newPortDataTable[newPortBaseIdx], PORT_TABLE_FIELD_LINK_SPEED_SUPPORTED, + s20iniFieldIsolate(oldPortMetaTable, &oldPortDataTable[oldPortBaseIdx], PORT_TABLE_FIELD_LINK_SPEED_SUPPORTED)); + s20iniFieldInsert(newPortMetaTable, &newPortDataTable[newPortBaseIdx], PORT_TABLE_FIELD_FM_ENABLED, + s20iniFieldIsolate(oldPortMetaTable, &oldPortDataTable[oldPortBaseIdx], PORT_TABLE_FIELD_FM_ENABLED)); + s20iniFieldInsert(newPortMetaTable, &newPortDataTable[newPortBaseIdx], PORT_TABLE_FIELD_CRC, + s20iniFieldIsolate(oldPortMetaTable, &oldPortDataTable[oldPortBaseIdx], PORT_TABLE_FIELD_CRC)); + s20iniFieldInsert(newPortMetaTable, &newPortDataTable[newPortBaseIdx], PORT_TABLE_FIELD_VCU, + s20iniFieldIsolate(oldPortMetaTable, &oldPortDataTable[oldPortBaseIdx], PORT_TABLE_FIELD_VCU)); + s20iniFieldInsert(newPortMetaTable, &newPortDataTable[newPortBaseIdx], PORT_TABLE_FIELD_EXTERNAL_LOOPBACK_ALLOWED, + s20iniFieldIsolate(oldPortMetaTable, &oldPortDataTable[oldPortBaseIdx], PORT_TABLE_FIELD_EXTERNAL_LOOPBACK_ALLOWED)); + oldPortBaseIdx += oldPortEntrySize; + newPortBaseIdx += newPortEntrySize; + } + + newSystemMetaTable = ini.metaDataTables[INI_TYPE_SYSTEM_TABLE].ptr; + newSystemDataTable = ini.dataTables[INI_TYPE_SYSTEM_TABLE].ptr; + + // convert node description to big endian format + for (i = 0; i < 16; i++) + nodeBuf[i] = ntoh32(*(U32_t *)&switchNodeDesc[i << 2]); + + // insert node desc + startBit = S20iniMetaDataEntryStartGet(newSystemMetaTable[SYSTEM_TABLE_FIELD_NODE_STRING]); + memcpy(&newSystemDataTable[(startBit >> 5)], nodeBuf, 64); + + // convert system image guid to big endian format + for (i = 0; i < 2; i++) { + U32_t val; + memcpy(&val, ((char *)&switchSystemImageGuid) + (i * 4), 4); + guidBuf[i] = ntoh32(val); + } + + // insert system image GUID + startBit = S20iniMetaDataEntryStartGet(newSystemMetaTable[SYSTEM_TABLE_FIELD_SYSTEM_IMAGE_GUID]); + memcpy(&newSystemDataTable[(startBit >> 5)], guidBuf, 8); + + // convert node guid to big endian format + for (i = 0; i < 2; i++) { + U32_t val; + memcpy(&val, ((char *)&switchNodeGuid) + (i * 4), 4); + guidBuf[i] = ntoh32(val); + } + + // insert node GUID + startBit = S20iniMetaDataEntryStartGet(newSystemMetaTable[SYSTEM_TABLE_FIELD_NODE_GUID]); + memcpy(&newSystemDataTable[(startBit >> 5)], guidBuf, 8); + + //insert FM Push Button State + s20iniFieldInsert(newSystemMetaTable, &newSystemDataTable[0], SYSTEM_TABLE_FIELD_FM_PUSH_BUTTON_STATE, fmPushButtonState); + + for(ini.tableType = 1; ini.tableType < INI_TYPE_META_DATA_TABLE_MAX; ++ini.tableType) { + S20INI_TABLE_REF *newMetaTableRef; + + //S20iniMetaDataDump(&ini); + memset(segBuffer, 0, 1024); + segSize = 0; + q = segBuffer; + newMetaTableRef = &ini.metaDataTables[ini.tableType]; + recordIdx = 0; + header1 = 0; + header1 |= (newMetaTableRef->dataWords << S_S20INI_RECORD_HEADER_DATA_WORDS); + header1 |= (ini.tableType << S_S20INI_RECORD_HEADER_TABLE_TYPE); + header1 |= (recordIdx << S_S20INI_RECORD_HEADER_RECORD_IDX); + header1 = ntoh32(header1); + header2 = ~header1; + memcpy(q, &header1, sizeof(header1)); + q += sizeof(header1); + segSize += sizeof(header1); + memcpy(q, &header2, sizeof(header1)); + q += sizeof(header2); + segSize += sizeof(header2); + memcpy(q, newMetaTableRef->ptr, newMetaTableRef->dataWords * 4); + for (i = 0; i < newMetaTableRef->dataWords; i++) { + ((U32_t*)q)[i] = ntoh32(((U32_t*)q)[i]); + } + q += newMetaTableRef->dataWords * 4; + segSize += newMetaTableRef->dataWords * 4; + crc = crc32Calculate(&segBuffer[2*sizeof(header1)], newMetaTableRef->dataWords << 2); + crc = ntoh32(crc); + memcpy(q, &crc, sizeof(crc)); + q += sizeof(crc); + segSize += sizeof(crc); + memcpy(p, segBuffer, segSize); + p += segSize; + bufSize += segSize; + } + + for(ini.tableType = 1; ini.tableType < max_data_table_type; ++ini.tableType) { + S20INI_TABLE_REF *newDataTableRef; + + //S20iniDataDump(&ini); + memset(segBuffer, 0, 1024); + segSize = 0; + q = segBuffer; + newDataTableRef = &ini.dataTables[ini.tableType]; + recordIdx = 1; + header1 = 0; + header1 |= (newDataTableRef->dataWords << S_S20INI_RECORD_HEADER_DATA_WORDS); + header1 |= (ini.tableType << S_S20INI_RECORD_HEADER_TABLE_TYPE); + header1 |= (recordIdx << S_S20INI_RECORD_HEADER_RECORD_IDX); + header1 = ntoh32(header1); + header2 = ~header1; + memcpy(q, &header1, sizeof(header1)); + q += sizeof(header1); + segSize += sizeof(header1); + memcpy(q, &header2, sizeof(header1)); + q += sizeof(header2); + segSize += sizeof(header2); + memcpy(q, newDataTableRef->ptr, newDataTableRef->dataWords * 4); + for (i = 0; i < newDataTableRef->dataWords; i++) { + ((U32_t*)q)[i] = ntoh32(((U32_t*)q)[i]); + } + q += newDataTableRef->dataWords * 4; + segSize += newDataTableRef->dataWords * 4; + crc = crc32Calculate(&segBuffer[2*sizeof(header1)], newDataTableRef->dataWords << 2); + crc = ntoh32(crc); + memcpy(q, &crc, sizeof(crc)); + q += sizeof(crc); + segSize += sizeof(crc); + memcpy(p, segBuffer, segSize); + p += segSize; + bufSize += segSize; + } + + while (bufSize & 3) { + binBuffer[bufSize] = 0; + ++bufSize; + } + + return(bufSize); + +} + +void buildEEPROMTrailer(int dataLen, uint8 *trailerBuf) { + uint32 i; + + i = hton32(SIGNATURE); + memcpy(trailerBuf, (char *)&i, 4); + i = dataLen >> 2; + i = hton32(i); + memcpy(&trailerBuf[4], (char *)&i, 4); + i = 0; + memcpy(&trailerBuf[8], (char *)&i, 4); + i = crc32Calculate(trailerBuf, 12); + i = hton32(i); + memcpy(&trailerBuf[12], (char *)&i, 4); +} + + +static void usage(char *app_name) +{ + fprintf(stderr, "usage: %s -t target ", app_name); +#if LIST_FILE_SUPPORTED + fprintf(stderr, " [-l list_file]"); +#endif + fprintf(stderr, " [-v|-q] [-h hfi] [-o port] [-f ini_file | -d ini_directory ]"); + fprintf(stderr, "\n"); + fprintf(stderr, " -t - target on which to update fw\n"); +#if LIST_FILE_SUPPORTED + fprintf(stderr, " -l - file that holds a list of targets to update\n"); +#endif + fprintf(stderr, " -v - verbose output\n"); + fprintf(stderr, " -q - no output\n"); + fprintf(stderr, " -h - hfi, numbered 1..n, 0= -o port will be a\n"); + fprintf(stderr, " system wide port num (default is 0)\n"); + fprintf(stderr, " -o - port, numbered 1..n, 0=1st active (default\n"); + fprintf(stderr, " is 1st active)\n"); + fprintf(stderr, " -f - ini file\n"); + fprintf(stderr, " -d - directory for ini file\n"); + fprintf(stderr, "\n"); + fprintf(stderr, "The -h and -o options permit a variety of selections:\n"); + fprintf(stderr, " -h 0 - 1st active port in system (this is the default)\n"); + fprintf(stderr, " -h 0 -o 0 - 1st active port in system\n"); + fprintf(stderr, " -h x - 1st active port on HFI x\n"); + fprintf(stderr, " -h x -o 0 - 1st active port on HFI x\n"); + fprintf(stderr, " -h 0 -o y - port y within system (irrespective of which ports are active)\n"); + fprintf(stderr, " -h x -o y - HFI x, port y\n"); +#if 0 /* non-documented options */ + fprintf(stderr, " -F - do secondary EEPROM (default if primary)\n"); +#endif + + exit(2); +} + +int s20ReadMem(struct omgt_port *port, U32_t addr, U32_t words, uint32 *data) { + U32_t remainingWords = words; + int status = FSUCCESS; + U32_t xferWords; + uint32 *p = data; + + while(remainingWords && (status == FSUCCESS)) { + xferWords = 16; + if (remainingWords < xferWords) + xferWords = remainingWords; + + status = sendMemAccessGetMad(port, &path, &mad, sessionID, addr, xferWords * 4, (U8_t *)p); + if (status == FSUCCESS) { + U32_t i; + for(i = 0; i < xferWords; ++i) + p[i] = hton32(p[i]); + p += xferWords; + remainingWords -= xferWords; + addr += xferWords; + } + } + return status; +} + +/* offsets need to be adjusted for multi EEPROM setup */ +int adjustEepromOffset(int totalOffset, uint16 *newOffset, uint32 *newLocation) { + *newOffset = totalOffset % STL_MAX_EEPROM_SIZE; + int numEeprom = totalOffset / STL_MAX_EEPROM_SIZE; + switch (numEeprom) { + case 0: + *newLocation = g_gotSecondary ? STL_PRR_SEC_EEPROM1_ADDR : STL_PRR_PRI_EEPROM1_ADDR; + break; + case 1: + *newLocation = g_gotSecondary ? STL_PRR_SEC_EEPROM2_ADDR : STL_PRR_PRI_EEPROM2_ADDR; + break; + case 2: + *newLocation = g_gotSecondary ? STL_PRR_SEC_EEPROM3_ADDR : STL_PRR_PRI_EEPROM3_ADDR; + break; + case 3: + *newLocation = g_gotSecondary ? STL_PRR_SEC_EEPROM4_ADDR : STL_PRR_PRI_EEPROM4_ADDR; + break; + default: + *newLocation = g_gotSecondary ? STL_PRR_SEC_EEPROM1_ADDR : STL_PRR_PRI_EEPROM1_ADDR; + numEeprom = 0; + break; + } + return numEeprom; +} + +uint32 getLocationOfEeprom(int eeprom) { + switch (eeprom) { + case 0: + return g_gotSecondary ? STL_PRR_SEC_EEPROM1_ADDR : STL_PRR_PRI_EEPROM1_ADDR; + case 1: + return g_gotSecondary ? STL_PRR_SEC_EEPROM2_ADDR : STL_PRR_PRI_EEPROM2_ADDR; + case 2: + return g_gotSecondary ? STL_PRR_SEC_EEPROM3_ADDR : STL_PRR_PRI_EEPROM3_ADDR; + case 3: + return g_gotSecondary ? STL_PRR_SEC_EEPROM4_ADDR : STL_PRR_PRI_EEPROM4_ADDR; + default: + return g_gotSecondary ? STL_PRR_SEC_EEPROM1_ADDR : STL_PRR_PRI_EEPROM1_ADDR; + } +} + +FSTATUS EepromRW(struct omgt_port *port, IB_PATH_RECORD *path, uint16 sessionID, + void *mad, uint8 jumbo, uint8 method, int timeout, uint32 locationDescriptor, + uint16 dataLen, uint16 dataOffset, uint8 *data) +{ + FSTATUS status; + uint32 maxXfer = 128; + uint32 remainingLen; + uint32 xferLen; + uint32 secondary; + + remainingLen = dataLen; + secondary = locationDescriptor & 0x00010000; + + if (secondary && (method == MMTHD_SET)) + locationDescriptor &= 0x7fffffff; + + while (remainingLen) { + xferLen = MIN(remainingLen, maxXfer); + + status = sendI2CAccessMad(port, path, sessionID, mad, jumbo, method, timeout, locationDescriptor, xferLen, dataOffset, data); + if (status != FSUCCESS) { + return(status); + } + dataOffset += xferLen; + data += xferLen; + remainingLen -= xferLen; + } + + return FSUCCESS; +} + +int main(int argc, char *argv[]) +{ + const char *opts="DFvqKBbt:l:h:o:d:m:f:T:"; + char parameter[100]; + char *p; + EUI64 destPortGuid = -1; + int c; + uint8 hfi = 0; + uint8 port = 0; + FSTATUS status; + + int iniBinSize; + int iniBinSizeOut; + U8_t iniBinBuf[INI_MAX_SIZE]; + U8_t iniBinBufOut[INI_MAX_SIZE]; + opasw_ini_descriptor_get_t tableDescriptors; + uint8 trailer[16]; + uint8 eepromBuffer[INI_MAX_SIZE]; + uint8 eepromBuffer2[INI_MAX_SIZE]; + uint32 eepromReadSize; + uint32 crcSize; + uint16 eepromReadOffset; + uint32 crcOut, crcIn; + uint8 *ep; + uint32 eepromWriteSize; + uint16 eepromOffset; + uint32 locationDescriptor; + uint32 byteCount; + int primary = 1; + int overwriteFactoryDefaults = 0; + struct stat fileStat; + struct omgt_port *omgt_port_session = NULL; + int currentEeprom; + + + // determine how we've been invoked + cmdName = strrchr(argv[0], '/'); // Find last '/' in path + if (cmdName != NULL) { + cmdName++; // Skip over last '/' + } else { + cmdName = argv[0]; + } + + // parse options and parameters + while (-1 != (c = getopt(argc, argv, opts))) { + switch (c) { + case 'D': + g_debugMode = 1; + break; + + case 't': + errno = 0; + strncpy(parameter, optarg, sizeof(parameter)-1); + parameter[sizeof(parameter)-1] = 0; + if ((p = strchr(parameter, ',')) != NULL) { + *p = '\0'; + } + if (FSUCCESS != StringToUint64(&destPortGuid, parameter, NULL, 0, TRUE)) { + fprintf(stderr, "%s: Error: Invalid GUID: %s\n", cmdName, optarg); + usage(cmdName); + } + break; + + case 'l': +#if !LIST_FILE_SUPPORTED + fprintf(stderr, "Error: l option is not supported at this time\n"); + exit(1); +#endif + break; + + case 'v': + g_verbose = 1; + break; + + case 'q': + g_quiet = 1; + break; + + case 'h': + if (FSUCCESS != StringToUint8(&hfi, optarg, NULL, 0, TRUE)) { + fprintf(stderr, "%s: Error: Invalid HFI Number: %s\n", cmdName, optarg); + usage(cmdName); + } + g_gotHfi = 1; + break; + + case 'o': + if (FSUCCESS != StringToUint8(&port, optarg, NULL, 0, TRUE)) { + fprintf(stderr, "%s: Error: Invalid Port Number: %s\n", cmdName, optarg); + usage(cmdName); + } + g_gotPort = 1; + break; + + case 'f': + g_fileParam = 1; + strncpy(inibinFileName, optarg, FNAME_SIZE-1); + inibinFileName[FNAME_SIZE-1] = 0; + if (!inibinFileName[0]) { + fprintf(stderr, "%s: Error: null input filename\n", cmdName); + exit(1); + } + break; + + case 'd': + g_dirParam = 1; + strncpy(dirName, optarg, DNAME_SIZE-1); + dirName[DNAME_SIZE-1]=0; + break; + + case 'b': + primary = 1 - primary; + break; + + case 'B': + overwriteFactoryDefaults = 1 - overwriteFactoryDefaults; + break; + + case 'F': + g_gotSecondary = 1; + break; + + case 'T': + if (FSUCCESS != StringToInt32(&g_respTimeout, optarg, NULL, 0, TRUE) + || g_respTimeout < 0) { + fprintf(stderr, "%s: Error: Invalid delay value: %s\n", cmdName, optarg); + usage(cmdName); + } + break; + + default: + usage(cmdName); + break; + + } + } + + // user has requested display of help + if (argc == 1) { + usage(cmdName); + } + + if (-1 == destPortGuid) { + fprintf(stderr, "%s: Error: Must specify a target GUID\n", cmdName); + exit(1); + } + + if ((!g_fileParam) && (!g_dirParam)) { + fprintf(stderr, "%s: Error: Must specify either a directory or file for the ini files\n", cmdName); + exit(1); + } else if ((g_fileParam) && (g_dirParam)) { + fprintf(stderr, "%s: Error: Cannot specify both a directory and file for the ini files\n", cmdName); + exit(1); + } + + if (g_quiet && (g_debugMode || g_verbose)) { + fprintf(stderr, "%s: Error: Can not specify both -q and -D|-v\n", cmdName); + exit(1); + } + + if (g_gotSecondary) + primary = 0; + + locationDescriptor = primary ? STL_PRR_PRI_EEPROM1_ADDR : STL_PRR_SEC_EEPROM1_ADDR; + + // Get the path + + struct omgt_params params = {.debug_file = g_debugMode ? stderr : NULL}; + status = omgt_open_port_by_num(&omgt_port_session, hfi, port, ¶ms); + if (status != 0) { + fprintf(stderr, "%s: Error: Unable to open fabric interface.\n", cmdName); + exit(1); + } + + if (getDestPath(omgt_port_session, destPortGuid, cmdName, &path) != FSUCCESS) { + fprintf(stderr, "%s: Error: Failed to get destination path\n", cmdName); + status = FERROR; + goto err_exit; + } + + // Send a ClassPortInfo to see if the switch is responding + + status = sendClassPortInfoMad(omgt_port_session, &path, &mad); + if (status != FSUCCESS) { + fprintf(stderr, "%s: Error: Failed to send/rcv ClassPortInfo\n", cmdName); + goto err_exit; + } + + // Get a session ID + + sessionID = getSessionID(omgt_port_session, &path); + if (sessionID == (uint16)-1) { + fprintf(stderr, "%s: Error: Failed to obtain sessionID\n", cmdName); + status = FERROR; + goto err_exit; + } + + // Read in the inibin file and parse it + + if (g_dirParam) { + if (chdir(dirName) < 0) { + fprintf(stderr, "Error: cannot change directory to %s: %s\n", dirName, strerror(errno)); + if (sessionID>0) releaseSession(omgt_port_session, &path, sessionID); + goto err_exit; + } + strcpy(inibinFileName, PRR_INIBIN); + if (stat("emfwMapFile", &fileStat) < 0) { + if (errno == ENOENT) { + strcpy(inibinFileName, OPASW_INIBIN); + } else { + fprintf(stderr, "Error: cannot validate emfwMapFile: %s\n", strerror(errno)); + if (sessionID>0) releaseSession(omgt_port_session, &path, sessionID); + status = FERROR; + goto err_exit; + } + } else { + getEMFWFileNames(omgt_port_session, &path, sessionID, fwFileName, inibinFileName); + } + } + + if (strstr(inibinFileName, ".inibin") == NULL) { + fprintf(stderr, "Error: old style EMFW not valid with this release\n"); + if (sessionID>0) releaseSession(omgt_port_session, &path, sessionID); + status = FERROR; + goto err_exit; + } + + iniBinSize = readIniBinFile(inibinFileName, iniBinBuf); + if (iniBinSize < 0) { + if (sessionID>0) releaseSession(omgt_port_session, &path, sessionID); + goto err_exit; + } + + S20iniBinToText(NULL, iniBinBuf, iniBinSize, 0, "metaFn", "dataFn"); + + + status = getNodeDescription(omgt_port_session, &path, sessionID, switchNodeDesc); + if (status != FSUCCESS) { + fprintf(stderr, "Error: Failed to acquire node description - status %d\n", status); + } + + status = getFmPushButtonState(omgt_port_session, &path, sessionID, &fmPushButtonState); + if (status != FSUCCESS) { + fprintf(stderr, "Error: Failed to acquire FM Push Button Status - status %d\n", status); + } + + status = getGuid(omgt_port_session, &path, sessionID, &switchSystemImageGuid, SYSTEM_IMAGE_GUID); + if (status != FSUCCESS) { + fprintf(stderr, "Error: Failed to acquire system image guid - status %d\n", status); + } + + status = getGuid(omgt_port_session, &path, sessionID, &switchNodeGuid, NODE_GUID); + if (status != FSUCCESS) { + fprintf(stderr, "Error: Failed to acquire node guid - status %d\n", status); + } + + status = sendIniDescriptorGetMad(omgt_port_session, &path, &mad, sessionID, &tableDescriptors); + if (status != FSUCCESS) { + fprintf(stderr, "%s: Error: Failed to get ini descriptors - status %d\n", cmdName, status); + if (sessionID>0) releaseSession(omgt_port_session, &path, sessionID); + goto err_exit; + } + oldNumPorts = getNumPorts(omgt_port_session, &path, sessionID); + oldPortEntrySize = tableDescriptors.portDataLen / oldNumPorts; + newNumPorts = s20iniFieldIsolate(ini.metaDataTables[INI_TYPE_SYSTEM_TABLE].ptr, + ini.dataTables[INI_TYPE_SYSTEM_TABLE].ptr, SYSTEM_TABLE_FIELD_NUM_PORTS), + newPortEntrySize = ini.dataTables[INI_TYPE_PORT_TABLE].dataWords / newNumPorts; + + // fetch the port meta data + oldPortMetaTable = (uint32 *)malloc(tableDescriptors.portMetaDataLen * sizeof(uint32)); + status = s20ReadMem(omgt_port_session, tableDescriptors.portMetaDataAddr, tableDescriptors.portMetaDataLen, oldPortMetaTable); + + // fetch the port table data + oldPortDataTable = (uint32 *)malloc(tableDescriptors.portDataLen * sizeof(uint32)); + status = s20ReadMem(omgt_port_session, tableDescriptors.portDataAddr, tableDescriptors.portDataLen, oldPortDataTable); + + if (g_verbose) { + printf("Port Data dump:\n"); + opaswDisplayBuffer((char *)oldPortDataTable, tableDescriptors.portDataLen * 4); + } + + int totalEepromOffset = STL_MAX_TOTAL_EEPROM_SIZE - 256 - sizeof(trailer); + currentEeprom = adjustEepromOffset(totalEepromOffset, &eepromOffset, &locationDescriptor); + + if (overwriteFactoryDefaults == 0) { + status = EepromRW(omgt_port_session, &path, sessionID, (void *)&mad, NOJUMBOMAD, MMTHD_GET, + g_respTimeout, locationDescriptor, sizeof(trailer), + eepromOffset, trailer); + if (status != FSUCCESS) { + fprintf(stderr, "%s: Error: Failed to get eeprom trailer - status %d\n", cmdName, status); + if (sessionID>0) releaseSession(omgt_port_session, &path, sessionID); + goto err_exit; + } + U32_t signature = ntoh32(*(U32_t *)&trailer[0]); + U32_t len = ntoh32(*(U32_t *)&trailer[4]); + U32_t crc = ntoh32(*(U32_t *)&trailer[12]); + + if (signature == SIGNATURE) { + if (crc32Calculate(trailer, 12) == crc) { + // move backwards past the factory default INI setting to the user trailer + eepromOffset -= ((len << 2) + sizeof(trailer)); + } else { + overwriteFactoryDefaults = 1; + printf("INI trailer crc mismatch expected=0x%x actual=0x%x\n", + crc32Calculate(trailer, 12), crc); + } + } else { + overwriteFactoryDefaults = 1; + printf("INI trailer signature mismatch expected=0x%x actual=0x%x\n", + SIGNATURE, signature); + } + } + + // format new inibin now that we have user-settable values + + iniBinSizeOut = buildNewIniBin(iniBinBufOut); + totalEepromOffset -= iniBinSizeOut; + currentEeprom = adjustEepromOffset(totalEepromOffset, &eepromOffset, &locationDescriptor); + int totalEepromReadOffset = totalEepromOffset; + + // construct the trailer + + buildEEPROMTrailer(iniBinSizeOut, trailer); + + ep = eepromBuffer; + eepromWriteSize = 0; + if (overwriteFactoryDefaults) { + // invalidate the previous trailer + memset (ep, 0xff, sizeof(trailer)); + ep += sizeof(trailer); + eepromWriteSize = sizeof(trailer); + totalEepromOffset -= sizeof(trailer); // will also be updating the previous trailer + currentEeprom = adjustEepromOffset(totalEepromOffset, &eepromOffset, &locationDescriptor); + totalEepromReadOffset = totalEepromOffset; + } + + memcpy(ep, iniBinBufOut, iniBinSizeOut); + memcpy(ep + iniBinSizeOut, trailer, sizeof(trailer)); + eepromWriteSize += iniBinSizeOut + sizeof(trailer); + eepromReadSize = eepromWriteSize; + + if (overwriteFactoryDefaults) { + printf("overwriting factory defaults in %s eeprom\n", primary ? "primary" : "secondary"); + } else { + if (!primary) + printf("overwriting configuration in secondary eeprom\n"); + } + + // calculate checkout on outgoing buffer + crcOut = crc32Calculate(eepromBuffer, eepromWriteSize); + + // write to EEPROM in loop + +#if DEBUG_USE_FILE == 0 + ep = eepromBuffer; + status = FSUCCESS; + byteCount = 0; + while ((status == FSUCCESS) && eepromWriteSize) { + U32_t xferLen = I2C_DATA_SIZE; + + if (xferLen > eepromWriteSize) + xferLen = eepromWriteSize; + + if (byteCount < STL_MAX_EEPROM_SIZE && (xferLen + eepromOffset) > STL_MAX_EEPROM_SIZE) + xferLen = STL_MAX_EEPROM_SIZE - eepromOffset; + + if (g_verbose) + printf("Sending offset %d (0x%04x)\n", eepromOffset, eepromOffset); + status = EepromRW(omgt_port_session, &path, sessionID, (void *)&mad, NOJUMBOMAD, MMTHD_SET, + g_respTimeout, locationDescriptor, + xferLen, eepromOffset, ep); + if (status == FSUCCESS) { + ep += xferLen; + eepromWriteSize -= xferLen; + if (byteCount < STL_MAX_EEPROM_SIZE && (xferLen + eepromOffset) > STL_MAX_EEPROM_SIZE) + locationDescriptor = getLocationOfEeprom(--currentEeprom); + eepromOffset += xferLen; + byteCount += xferLen; + } else { + /* retry ??? */ + fprintf(stderr, "%s: Error sending MAD packet to switch\n", cmdName); + } + } +#else + printf("eepromOffset=0x%x eepromWriteSize=0x%x\n", eepromOffset, eepromWriteSize); + writeIniBinFile("eeprom.bin", eepromBuffer, eepromWriteSize); +#endif + + // Read back and calculate checksum + usleep(250000); + ep = eepromBuffer2; + status = FSUCCESS; + byteCount = 0; + crcSize = eepromReadSize; + + currentEeprom = adjustEepromOffset(totalEepromReadOffset, &eepromReadOffset, &locationDescriptor); + + while ((status == FSUCCESS) && eepromReadSize) { + U32_t xferLen = I2C_DATA_SIZE; + if (xferLen > eepromReadSize) + xferLen = eepromReadSize; + + if (byteCount < STL_MAX_EEPROM_SIZE && (xferLen + eepromReadOffset) > STL_MAX_EEPROM_SIZE) + xferLen = STL_MAX_EEPROM_SIZE - eepromReadOffset; + + if (g_verbose) + printf("Reading offset %d (0x%04x)\n", eepromReadOffset, eepromReadOffset); + + status = EepromRW(omgt_port_session, &path, sessionID, (void *)&mad, NOJUMBOMAD, MMTHD_GET, + g_respTimeout, locationDescriptor, + xferLen, eepromReadOffset, ep); + if (status == FSUCCESS) { + ep += xferLen; + eepromReadSize -= xferLen; + if (byteCount < STL_MAX_EEPROM_SIZE && (xferLen + eepromReadOffset) > STL_MAX_EEPROM_SIZE) + locationDescriptor = getLocationOfEeprom(--currentEeprom); + eepromReadOffset += xferLen; + byteCount += xferLen; + } else { + /* retry ??? */ + fprintf(stderr, "%s: Error reading MAD packet to switch\n", cmdName); + } + } + crcIn = crc32Calculate(eepromBuffer2, crcSize); + printf("%s: Config block in EEPROM is %s\n", cmdName, (crcOut == crcIn) ? "valid" : "invalid"); + + if (sessionID>0) releaseSession(omgt_port_session, &path, sessionID); + + printf("opaswfwconfigure completed\n"); + +err_exit: + omgt_close_port(omgt_port_session); + + if (status == FSUCCESS) + exit(0); + else + exit(1); + +} diff --git a/IbaTools/opasw/opaswfwupdate/Makefile b/IbaTools/opasw/opaswfwupdate/Makefile new file mode 100644 index 0000000..a4ef5b6 --- /dev/null +++ b/IbaTools/opasw/opaswfwupdate/Makefile @@ -0,0 +1,160 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** +# Makefile for opaswfwupdate + +# Include Make Control Settings +include $(TL_DIR)/$(PROJ_FILE_DIR)/Makesettings.project + +#=============================================================================# +# Definitions: +#-----------------------------------------------------------------------------# + +# Name of SubProjects +DS_SUBPROJECTS = +# name of executable or downloadable image +EXECUTABLE = $(BUILDDIR)/opaswfwupdate$(EXE_SUFFIX) +# list of sub directories to build +DIRS = +# C files (.c) +CFILES = \ + opaswfwupdate.c + # Add more c files here +# C++ files (.cpp) +CCFILES = \ + # Add more cpp files here +# lex files (.lex) +LFILES = \ + # Add more lex files here +# archive library files (basename, $ARFILES will add MOD_LIB_DIR/prefix and suffix) +LIBFILES= +# Windows Resource Files (.rc) +RSCFILES = +# Windows IDL File (.idl) +IDLFILE = +# Windows Linker Module Definitions (.def) file for dll's +DEFFILE = +# targets to build during INCLUDES phase (add public includes here) +INCLUDE_TARGETS = \ + # Add more h hpp files here +# Non-compiled files + # Add more files here +MISC_FILES = +# all source files +SOURCES = $(CFILES) $(CCFILES) $(LFILES) $(RSCFILES) $(IDLFILE) +# Source files to include in DSP File +DSP_SOURCES = $(INCLUDE_TARGETS) $(SOURCES) $(MISC_FILES) \ + $(RSCFILES) $(DEFFILE) $(MAKEFILE) +# all object files +OBJECTS = $(CFILES:.c=$(OBJ_SUFFIX)) $(CCFILES:.cpp=$(OBJ_SUFFIX)) \ + $(LFILES:.lex=$(OBJ_SUFFIX)) +RSCOBJECTS = $(RSCFILES:.rc=$(RES_SUFFIX)) +# targets to build during LIBS phase +LIB_TARGETS_IMPLIB = +LIB_TARGETS_ARLIB = # $(LIB_PREFIX)ResourceTest$(ARLIB_SUFFIX) +LIB_TARGETS_EXP = $(LIB_TARGETS_IMPLIB:$(ARLIB_SUFFIX)=$(EXP_SUFFIX)) +LIB_TARGETS_MISC = +# targets to build during CMDS phase +CMD_TARGETS_SHLIB = +CMD_TARGETS_EXE = $(EXECUTABLE) +CMD_TARGETS_MISC = +# files to remove during clean phase +CLEAN_TARGETS_MISC = +CLEAN_TARGETS = $(OBJECTS) $(RSCOBJECTS) $(IDL_TARGETS) $(CLEAN_TARGETS_MISC) +# other files to remove during clobber phase +CLOBBER_TARGETS_MISC= +# sub-directory to install to within bin +BIN_SUBDIR = +# sub-directory to install to within include +INCLUDE_SUBDIR = + +# Additional Settings +#CLOCALDEBUG = User defined C debugging compilation flags [Empty] +#CCLOCALDEBUG = User defined C++ debugging compilation flags [Empty] +#CLOCAL = User defined C flags for compiling [Empty] +#CCLOCAL = User defined C++ flags for compiling [Empty] +#BSCLOCAL = User flags for Browse File Builder [Empty] +#DEPENDLOCAL = user defined makedepend flags [Empty] +#LINTLOCAL = User defined lint flags [Empty] +#LOCAL_INCLUDE_DIRS = User include directories to search for C/C++ headers [Empty] +#LDLOCAL = User defined C flags for linking [Empty] +#IMPLIBLOCAL = User flags for Object Lirary Manager [Empty] +#MIDLLOCAL = User flags for IDL compiler [Empty] +#RSCLOCAL = User flags for resource compiler [Empty] +#LOCALDEPLIBS = User libraries to include in dependencies [Empty] +#LOCALLIBS = User libraries to use when linking [Empty] +# (in addition to LOCALDEPLIBS) +#LOCAL_LIB_DIRS = User library directories for libpaths [Empty] + +LOCALDEPLIBS=$(IBACCESS_USER_LIBS) opaswcommon opamgt-priv +LOCAL_INCLUDE_DIRS= +LOCALLIBS=$(OPENIB_USER_LIBS) z crypto +LOCAL_LIB_DIRS=$(OPENIB_USER_LIB_DIRS) $(IBACCESS_USER_LIB_DIRS) + +# Include Make Rules definitions and rules +include $(TL_DIR)/IbaTools/Makerules.module + +#=============================================================================# +# Overrides: +#-----------------------------------------------------------------------------# +#CCOPT = # C++ optimization flags, default lets build config decide +#COPT = # C optimization flags, default lets build config decide +#SUBSYSTEM = Subsystem to build for (none, console or windows) [none] +# (Windows Only) +#USEMFC = How Windows MFC should be used (none, static, shared, no_mfc) [none] +# (Windows Only) +#=============================================================================# + +CLOCAL=-DFWDELAY_WORKAROUND $(CPIE) + +#=============================================================================# +# Rules: +#-----------------------------------------------------------------------------# +# process Sub-directories +include $(TL_DIR)/Makerules/Maketargets.toplevel + +# build cmds and libs +include $(TL_DIR)/Makerules/Maketargets.build + +# install for includes, libs and cmds phases +include $(TL_DIR)/Makerules/Maketargets.install + +# install for stage phase +include $(TL_DIR)/Makerules/Maketargets.stage +STAGE:: + #$(VS)$(STAGE_INSTALL) $(STAGE_INSTALL_DIR_OPT) $(PROJ_STAGE_FASTFABRIC_DIR) $(EXECUTABLE) + $(VS)$(STAGE_INSTALL) $(STAGE_INSTALL_DIR_OPT) $(PROJ_STAGE_BIN_DIR) $(EXECUTABLE) + +# Unit test execution +#include $(TL_DIR)/Makerules/Maketargets.runtest + +#=============================================================================# + +#=============================================================================# +# DO NOT DELETE THIS LINE -- make depend depends on it. +#=============================================================================# diff --git a/IbaTools/opasw/opaswfwupdate/opaswfwupdate.c b/IbaTools/opasw/opaswfwupdate/opaswfwupdate.c new file mode 100644 index 0000000..c26945f --- /dev/null +++ b/IbaTools/opasw/opaswfwupdate/opaswfwupdate.c @@ -0,0 +1,535 @@ +/* BEGIN_ICS_COPYRIGHT7 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT7 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +#include +#include +#include +#include +#include +#include +#include +#include + +/* work around conflicting names */ + +#include "iba/ib_types.h" +#include "iba/ib_sm_priv.h" +#include "iba/ib_helper.h" +#include "opamgt_sa_priv.h" +#include +#include "opaswcommon.h" +#include "zlib.h" +#include + +#define FW_FILENAME_BASE "prrFw" + +#define FW_RESP_WAIT_TIME 2000 +#define FW_PAUSE 50000 + +typedef uint8_t bool_t; + +// globals + +int g_debugMode = 0; +int g_verbose = 0; +int g_quiet = 0; +int g_gotHfi = 0; +int g_gotPort = 0; +int g_gotSecondary = 0; +int g_fileParam = 0; +int g_dirParam = 0; +int32 g_sleepParam = 0; +int32 g_usleepParam = 0; +int32 g_dataLenParam = 0; +int32 g_respTimeout = FW_RESP_WAIT_TIME; +int g_resetSwitch = 0; + +char fwFileName[FNAME_SIZE]; +char inibinFileName[FNAME_SIZE]; +char fwDirName[DNAME_SIZE]; + +uint32 loadFirmwareBuffer(struct omgt_port *port, char **fwBuffer, IB_PATH_RECORD *path, uint16 sessionID) +{ + FILE *fp; + DIR *fwDir; + struct dirent *dp; + int nread; + uint32 totalRead = 0; + uint32 bufSize; + char *p; + struct stat fileStat; + uint32 oemHash[8],binaryHash[8]; + VENDOR_MAD mad; + FSTATUS status = FSUCCESS; + int isValid = 1; + uint32 acb; + if (g_dirParam) { + if (chdir(fwDirName) < 0) { + fprintf(stderr, "Error: cannot change directory to %s: %s\n", fwDirName, strerror(errno)); + return(0); + } + if (stat("emfwMapFile", &fileStat) < 0) { + if (errno == ENOENT) { + if ((fwDir = opendir(fwDirName)) == NULL) { + fprintf(stderr, "Error opening directory %s: %s\n", fwDirName, strerror(errno)); + return(0); + } + while ((dp = readdir(fwDir)) != NULL) { + if (strstr(dp->d_name, FW_FILENAME_BASE) != NULL) { + snprintf(fwFileName, FNAME_SIZE, "%s/%s", fwDirName, dp->d_name); + fwFileName[FNAME_SIZE-1]=0; + break; + } + } + closedir(fwDir); + if (strlen(fwFileName) == 0) { + fprintf(stderr, "Error: no firmware file for %s found in directory %s\n", FW_FILENAME_BASE, fwDirName); + return(0); + } + } else { + fprintf(stderr, "Error: cannot validate emfwMapFile: %s\n", strerror(errno)); + return(0); + } + } else { + getEMFWFileNames(port, path, sessionID, fwFileName, inibinFileName); + } + } + status = getOemHash(port,path,&mad,sessionID,oemHash,&acb); + if (status == FSUCCESS) { + if (acb & 0x10000000) { + if (getBinaryHash(fwFileName,binaryHash) == FSUCCESS) { + if (memcmp(binaryHash, oemHash, sizeof(binaryHash))) + isValid = 0; + } + else { + fprintf(stderr,"Unable to get Signature from Binary\n"); + return(0); + } + } + } + else { + fprintf(stderr,"Unable to get OEM hash\n"); + return(0); + } + + if(isValid){ + if (stat(fwFileName, &fileStat) < 0) { + fprintf(stderr, "Error taking stat of file {%s}: %s\n", + fwFileName, strerror(errno)); + return(0); + } + + bufSize = (uint32)fileStat.st_size + 1024; /* pad by 1K to be safe */ + + if ((*fwBuffer = malloc(bufSize)) == NULL) { + fprintf(stderr, "Error allocating memory for firmware buffer\n"); + return(0); + } + + if ((fp = fopen(fwFileName, "r")) == NULL) { + fprintf(stderr, "Error opening file %s for input: %s\n", fwFileName, strerror(errno)); + return(0); + } + memset(*fwBuffer, 0, bufSize); + p = *fwBuffer + 4; + while ((nread = fread(p, 1, 1024, fp)) > 0) { + totalRead += nread; + p += nread; + } + + fclose(fp); + + // xedgeDisplayBuffer(fwBuffer, totalRead); + + return(totalRead); + } + else{ + fprintf(stderr,"Firmware signature mismatch\n"); + return(0); + } +} + +#define LIST_FILE_SUPPORTED 0 + +static void usage(char *app_name) +{ + fprintf(stderr, "usage: %s -t target\n", app_name); +#if LIST_FILE_SUPPORTED + fprintf(stderr, " [-l list_file]"); +#endif + fprintf(stderr, " [-v|-q] [-h hfi] [-o port] [-f fw_file | -d fw_directory] [-S]"); + fprintf(stderr, "\n"); + fprintf(stderr, " -t - target on which to update fw\n"); +#if LIST_FILE_SUPPORTED + fprintf(stderr, " -l - file that holds a list of targets to update\n"); +#endif + fprintf(stderr, " -v - verbose output\n"); + fprintf(stderr, " -q - no output\n"); + fprintf(stderr, " -h - hfi, numbered 1..n, 0= -o port will be a\n"); + fprintf(stderr, " system wide port num (default is 0)\n"); + fprintf(stderr, " -o - port, numbered 1..n, 0=1st active (default\n"); + fprintf(stderr, " is 1st active)\n"); + fprintf(stderr, " -f - firmware file (extracted .bin file from emfw) \n"); + fprintf(stderr, " -d - firmware directory\n"); + fprintf(stderr, " -S - reset switch after update\n"); + fprintf(stderr, "\n"); + fprintf(stderr, "The -h and -o options permit a variety of selections:\n"); + fprintf(stderr, " -h 0 - 1st active port in system (this is the default)\n"); + fprintf(stderr, " -h 0 -o 0 - 1st active port in system\n"); + fprintf(stderr, " -h x - 1st active port on HFI x\n"); + fprintf(stderr, " -h x -o 0 - 1st active port on HFI x\n"); + fprintf(stderr, " -h 0 -o y - port y within system (irrespective of which ports are active)\n"); + fprintf(stderr, " -h x -o y - HFI x, port y\n"); + +#if 0 /* non-documented options */ + fprintf(stderr, " -F - do secondary EEPROM (default if primary)\n"); + fprintf(stderr, " -s - delay in seconds between requests\n"); + fprintf(stderr, " -u - delay in microseconds between requests\n"); + fprintf(stderr, " -T - response timeout in microseconds\n"); + fprintf(stderr, " -z - write data length in bytes\n"); +#endif + + exit(2); +} + +int main(int argc, char *argv[]) +{ + char *cmdName; + const char *opts="FDSvqt:l:h:o:d:f:m:s:u:T:z:"; + uint8 *fwBuffer = NULL; + uint8 *fwBuffer2 = NULL; + char parameter[100]; + uint8 *p; +#if FWDELAY_WORKAROUND + char *sleepVal; +#endif + uint32 fwSize; + EUI64 destPortGuid = -1; + int c; + uint8 hfi = 0; + uint8 port = 0; + IB_PATH_RECORD path; + uint16 sessionID = 0; + uint32 *u; + uint32 crcEEPROM; + uint32 crc; + VENDOR_MAD_JUMBO mad; + FSTATUS status = FSUCCESS; + struct omgt_port *omgt_port_session = NULL; + + // determine how we've been invoked + cmdName = strrchr(argv[0], '/'); // Find last '/' in path + if (cmdName != NULL) { + cmdName++; // Skip over last '/' + } else { + cmdName = argv[0]; + } + + // initialize + fwFileName[0] = '\0'; + + + // parse options and parameters + while (-1 != (c = getopt(argc, argv, opts))) { + switch (c) { + case 'D': + g_debugMode = 1; + break; + + case 't': + errno = 0; + strncpy(parameter, optarg, sizeof(parameter)-1); + parameter[sizeof(parameter)-1] = 0; + if ((p = (uint8 *)strchr(parameter, ',')) != NULL) { + *p = '\0'; + } + if (FSUCCESS != StringToUint64(&destPortGuid, parameter, NULL, 0, TRUE)) { + fprintf(stderr, "%s: Error: Invalid GUID: %s\n", cmdName, optarg); + usage(cmdName); + } + break; + + case 'l': +#if !LIST_FILE_SUPPORTED + fprintf(stderr, "Error: l option is not supported at this time\n"); + exit(1); +#endif + break; + + case 'v': + g_verbose = 1; + break; + + case 'q': + g_quiet = 1; + break; + + case 'h': + if (FSUCCESS != StringToUint8(&hfi, optarg, NULL, 0, TRUE)) { + fprintf(stderr, "%s: Error: Invalid HFI Number: %s\n", cmdName, optarg); + usage(cmdName); + } + g_gotHfi = 1; + break; + + case 'o': + if (FSUCCESS != StringToUint8(&port, optarg, NULL, 0, TRUE)) { + fprintf(stderr, "%s: Error: Invalid Port Number: %s\n", cmdName, optarg); + usage(cmdName); + } + g_gotPort = 1; + break; + + case 'f': + g_fileParam = 1; + memcpy(fwFileName, optarg, FNAME_SIZE); + // Validate Filename + if (!fwFileName[0]) { + fprintf(stderr, "%s: Error: null input filename\n", cmdName); + exit(2); + } + break; + + case 'd': + g_dirParam = 1; + memcpy(fwDirName, optarg, DNAME_SIZE); + break; + + case 's': + if (FSUCCESS != StringToInt32(&g_sleepParam, optarg, NULL, 0, TRUE) + || g_sleepParam < 0) { + fprintf(stderr, "%s: Error: Invalid delay value: %s\n", cmdName, optarg); + usage(cmdName); + } + break; + + case 'u': + if (FSUCCESS != StringToInt32(&g_usleepParam, optarg, NULL, 0, TRUE) + || g_usleepParam < 0) { + fprintf(stderr, "%s: Error: Invalid delay value: %s\n", cmdName, optarg); + usage(cmdName); + } + break; + + case 'z': + if (FSUCCESS != StringToInt32(&g_dataLenParam, optarg, NULL, 0, TRUE) + || g_dataLenParam < 0) { + fprintf(stderr, "%s: Error: Invalid data length value: %s\n", cmdName, optarg); + usage(cmdName); + } + break; + + case 'T': + if (FSUCCESS != StringToInt32(&g_respTimeout, optarg, NULL, 0, TRUE) + || g_respTimeout < 0) { + fprintf(stderr, "%s: Error: Invalid delay value: %s\n", cmdName, optarg); + usage(cmdName); + } + break; + + case 'S': + g_resetSwitch = 1; + break; + + case 'F': + g_gotSecondary = 1; + break; + + default: + usage(cmdName); + break; + + } + } + + // user has requested display of help + if (argc == 1) { + usage(cmdName); + } + + if (-1 == destPortGuid) { + fprintf(stderr, "%s: Error: Must specify a target GUID\n", cmdName); + exit(1); + } + + if ((!g_fileParam) && (!g_dirParam)) { + fprintf(stderr, "%s: Error: Must specify either a directory or file for the firmware\n", cmdName); + exit(1); + } else if ((g_fileParam) && (g_dirParam)) { + fprintf(stderr, "%s: Error: Cannot specify both a directory and file for the firmware\n", cmdName); + exit(1); + } + + if (g_quiet && (g_debugMode || g_verbose)) { + fprintf(stderr, "%s: Error: Can not specify both -q and -D|-v\n", cmdName); + exit(1); + } + + if (g_sleepParam && g_usleepParam) { + fprintf(stderr, "%s: Error: Can not specify both -s and -u\n", cmdName); + exit(1); + } + +#if FWDELAY_WORKAROUND + if ((sleepVal = getenv("FWDELAY")) != NULL) { + g_usleepParam = atoi(sleepVal); + printf("Overriding delay with value %d\n", g_usleepParam); + } +#endif + + // Get the path + + struct omgt_params params = {.debug_file = g_debugMode ? stderr : NULL}; + status = omgt_open_port_by_num(&omgt_port_session, hfi, port, ¶ms); + if (status != 0) { + fprintf(stderr, "%s: Error: Unable to open fabric interface.\n", cmdName); + exit(1); + } + + if (getDestPath(omgt_port_session, destPortGuid, cmdName, &path) != FSUCCESS) { + fprintf(stderr, "%s: Error: Failed to get destination path\n", cmdName); + goto err_exit; + } + + // Send a ClassPortInfo to see if the switch is responding + + status = sendClassPortInfoMad(omgt_port_session, &path, (VENDOR_MAD*)&mad); + if (status != FSUCCESS) { + fprintf(stderr, "%s: Error: Failed to send/rcv ClassPortInfo\n", cmdName); + status = FERROR; + goto err_exit; + } + + // Get a session ID + + sessionID = getSessionID(omgt_port_session, &path); + if (sessionID == (uint16)-1) { + fprintf(stderr, "%s: Error: Failed to obtain sessionID\n", cmdName); + status = FERROR; + goto err_exit; + } + + // read the file into the buffer + + fwSize = loadFirmwareBuffer(omgt_port_session, (char **)&fwBuffer, &path, sessionID); + if (fwSize == 0) { + fprintf(stderr, "%s: Error: Failed to load firmware file\n", cmdName); + if (sessionID>0) releaseSession(omgt_port_session, &path, sessionID); + status = FERROR; + goto err_exit; + } + u = (uint32 *)&fwBuffer[fwSize - 4]; + + // Loop sending i2cAccess sets to update firmware + + if (!g_quiet) { + printf("Updating firmware... "); + fflush(stdout); + } + + if (status != FSUCCESS) { + // error trying to erase the old firmware + fprintf(stderr, "%s: Error erasing old firmware rc: %d\n", cmdName, status); + } else { + status = opaswEepromRW(omgt_port_session, &path, sessionID, (void *)&mad, g_respTimeout, + fwSize + 4, 0, (uint8 *)fwBuffer, TRUE, g_gotSecondary); + if (status != FSUCCESS) { + // error trying to update the firmware + fprintf(stderr, "%s: Error updating firmware rc: %d\n", cmdName, status); + } + } + + // now read firmware back in and verify checksum + + if (!g_quiet) { + printf("\nUpdate complete ... verifying ... "); + fflush(stdout); + } + if ((fwBuffer2 = malloc(fwSize + 1024)) == NULL) { + fprintf(stderr, "Error allocating memory for firmware read back buffer\n"); + if (sessionID>0) releaseSession(omgt_port_session, &path, sessionID); + goto err_exit; + } + + if (status == FSUCCESS) { + memset(fwBuffer2, 0, fwSize + 1024); + + status = opaswEepromRW(omgt_port_session, &path, sessionID, (void *)&mad, g_respTimeout, + fwSize + 4, 0, (uint8 *)fwBuffer2, FALSE, g_gotSecondary); + + if (!g_quiet) { + printf("\n"); + fflush(stdout); + } + if (status == FSUCCESS) { + u = (uint32 *)&fwBuffer2[fwSize]; + crcEEPROM = *u; + crc = crc32(0, (uint8 *)&fwBuffer2[CSS_HEADER_SIZE + 4], fwSize - 4 - CSS_HEADER_SIZE); + if (crcEEPROM != crc) { + printf("Verification failed\n"); + fprintf(stderr, "Error: CRC mismatch: 0x%08x : 0x%08x\n", ntoh32(crc), ntoh32(crcEEPROM)); + status = FERROR; + } else { + if (g_verbose) + fprintf(stderr, "CRC match: 0x%08x : 0x%08x\n", ntoh32(crc), ntoh32(crcEEPROM)); + printf("Verification succeeded\n"); + } + } + // reset switch if necessary + if ((status == FSUCCESS) && g_resetSwitch) { + printf("Resetting switch...\n"); + status = sendRebootMad(omgt_port_session, &path, sessionID, (VENDOR_MAD*)&mad, 2000); + if (status != FSUCCESS) { + fprintf(stderr, "%s: Error sending MAD packet to switch\n", cmdName); + } + } + } + + if (!g_resetSwitch) + if (sessionID>0) releaseSession(omgt_port_session, &path, sessionID); + + printf("opaswfwupdate completed\n"); + +err_exit: + omgt_close_port(omgt_port_session); + + if (fwBuffer != NULL) + free(fwBuffer); + + if (fwBuffer2 != NULL) + free(fwBuffer2); + + if (status == FSUCCESS) + exit(0); + else + exit(1); + +} diff --git a/IbaTools/opasw/opaswfwverify/Makefile b/IbaTools/opasw/opaswfwverify/Makefile new file mode 100644 index 0000000..beb1f71 --- /dev/null +++ b/IbaTools/opasw/opaswfwverify/Makefile @@ -0,0 +1,158 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** +# Makefile for opaswfwverify + +# Include Make Control Settings +include $(TL_DIR)/$(PROJ_FILE_DIR)/Makesettings.project + +#=============================================================================# +# Definitions: +#-----------------------------------------------------------------------------# + +# Name of SubProjects +DS_SUBPROJECTS = +# name of executable or downloadable image +EXECUTABLE = $(BUILDDIR)/opaswfwverify$(EXE_SUFFIX) +# list of sub directories to build +DIRS = +# C files (.c) +CFILES = \ + opaswfwverify.c \ + # Add more c files here +# C++ files (.cpp) +CCFILES = \ + # Add more cpp files here +# lex files (.lex) +LFILES = \ + # Add more lex files here +# archive library files (basename, $ARFILES will add MOD_LIB_DIR/prefix and suffix) +LIBFILES= +# Windows Resource Files (.rc) +RSCFILES = +# Windows IDL File (.idl) +IDLFILE = +# Windows Linker Module Definitions (.def) file for dll's +DEFFILE = +# targets to build during INCLUDES phase (add public includes here) +INCLUDE_TARGETS = \ + # Add more h hpp files here +# Non-compiled files + # Add more files here +MISC_FILES = +# all source files +SOURCES = $(CFILES) $(CCFILES) $(LFILES) $(RSCFILES) $(IDLFILE) +# Source files to include in DSP File +DSP_SOURCES = $(INCLUDE_TARGETS) $(SOURCES) $(MISC_FILES) \ + $(RSCFILES) $(DEFFILE) $(MAKEFILE) +# all object files +OBJECTS = $(CFILES:.c=$(OBJ_SUFFIX)) $(CCFILES:.cpp=$(OBJ_SUFFIX)) \ + $(LFILES:.lex=$(OBJ_SUFFIX)) +RSCOBJECTS = $(RSCFILES:.rc=$(RES_SUFFIX)) +# targets to build during LIBS phase +LIB_TARGETS_IMPLIB = +LIB_TARGETS_ARLIB = # $(LIB_PREFIX)ResourceTest$(ARLIB_SUFFIX) +LIB_TARGETS_EXP = $(LIB_TARGETS_IMPLIB:$(ARLIB_SUFFIX)=$(EXP_SUFFIX)) +LIB_TARGETS_MISC = +# targets to build during CMDS phase +CMD_TARGETS_SHLIB = +CMD_TARGETS_EXE = $(EXECUTABLE) +CMD_TARGETS_MISC = +# files to remove during clean phase +CLEAN_TARGETS_MISC = +CLEAN_TARGETS = $(OBJECTS) $(RSCOBJECTS) $(IDL_TARGETS) $(CLEAN_TARGETS_MISC) +# other files to remove during clobber phase +CLOBBER_TARGETS_MISC= +# sub-directory to install to within bin +BIN_SUBDIR = +# sub-directory to install to within include +INCLUDE_SUBDIR = + +# Additional Settings +#CLOCALDEBUG = User defined C debugging compilation flags [Empty] +#CCLOCALDEBUG = User defined C++ debugging compilation flags [Empty] +#CLOCAL = User defined C flags for compiling [Empty] +#CCLOCAL = User defined C++ flags for compiling [Empty] +#BSCLOCAL = User flags for Browse File Builder [Empty] +#DEPENDLOCAL = user defined makedepend flags [Empty] +#LINTLOCAL = User defined lint flags [Empty] +#LOCAL_INCLUDE_DIRS = User include directories to search for C/C++ headers [Empty] +#LDLOCAL = User defined C flags for linking [Empty] +#IMPLIBLOCAL = User flags for Object Lirary Manager [Empty] +#MIDLLOCAL = User flags for IDL compiler [Empty] +#RSCLOCAL = User flags for resource compiler [Empty] +#LOCALDEPLIBS = User libraries to include in dependencies [Empty] +#LOCALLIBS = User libraries to use when linking [Empty] +# (in addition to LOCALDEPLIBS) +#LOCAL_LIB_DIRS = User library directories for libpaths [Empty] + +LOCALDEPLIBS=$(IBACCESS_USER_LIBS) opaswcommon opamgt-priv +LOCAL_INCLUDE_DIRS= +LOCALLIBS=$(OPENIB_USER_LIBS) z crypto +LOCAL_LIB_DIRS=$(OPENIB_USER_LIB_DIRS) $(IBACCESS_USER_LIB_DIRS) + +# Include Make Rules definitions and rules +include $(TL_DIR)/IbaTools/Makerules.module + +#=============================================================================# +# Overrides: +#-----------------------------------------------------------------------------# +#CCOPT = # C++ optimization flags, default lets build config decide +#COPT = # C optimization flags, default lets build config decide +#SUBSYSTEM = Subsystem to build for (none, console or windows) [none] +# (Windows Only) +#USEMFC = How Windows MFC should be used (none, static, shared, no_mfc) [none] +# (Windows Only) +#=============================================================================# + +#=============================================================================# +# Rules: +#-----------------------------------------------------------------------------# +# process Sub-directories +include $(TL_DIR)/Makerules/Maketargets.toplevel + +# build cmds and libs +include $(TL_DIR)/Makerules/Maketargets.build + +# install for includes, libs and cmds phases +include $(TL_DIR)/Makerules/Maketargets.install + +# install for stage phase +include $(TL_DIR)/Makerules/Maketargets.stage +STAGE:: + #$(VS)$(STAGE_INSTALL) $(STAGE_INSTALL_DIR_OPT) $(PROJ_STAGE_FASTFABRIC_DIR) $(EXECUTABLE) + $(VS)$(STAGE_INSTALL) $(STAGE_INSTALL_DIR_OPT) $(PROJ_STAGE_BIN_DIR) $(EXECUTABLE) + +# Unit test execution +#include $(TL_DIR)/Makerules/Maketargets.runtest + +#=============================================================================# + +#=============================================================================# +# DO NOT DELETE THIS LINE -- make depend depends on it. +#=============================================================================# diff --git a/IbaTools/opasw/opaswfwverify/opaswfwverify.c b/IbaTools/opasw/opaswfwverify/opaswfwverify.c new file mode 100644 index 0000000..e427e65 --- /dev/null +++ b/IbaTools/opasw/opaswfwverify/opaswfwverify.c @@ -0,0 +1,398 @@ +/* BEGIN_ICS_COPYRIGHT7 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT7 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +#include +#include +#include +#include +#include +#include + +/* work around conflicting names */ + +#include "iba/ib_types.h" +#include "iba/ib_sm_priv.h" +#include "iba/ib_helper.h" +#include "opamgt_sa_priv.h" +#include +#include "opaswcommon.h" +#include "zlib.h" + +#define FW_RESP_WAIT_TIME 2000 + +#define NEED_TO_RETRY(madStatus) ((madStatus == VM_MAD_STATUS_NACK) || (madStatus == VM_MAD_STATUS_BUS_BUSY) || (madStatus == VM_MAD_STATUS_BUS_HUNG) || (madStatus == VM_MAD_STATUS_LOST_ARB) || (madStatus == VM_MAD_STATUS_TIMEOUT)) + +// globals + +int g_debugMode = 0; +int g_verbose = 0; +int g_quiet = 0; +int g_gotHfi = 0; +int g_gotPort = 0; +int g_gotSecondary = 0; +int g_fileParam = 0; +int g_dirParam = 0; +int32 g_sleepParam = 0; +int32 g_usleepParam = 0; +int32 g_dataLenParam = 0; +int32 g_respTimeout = FW_RESP_WAIT_TIME; +int g_compareEEPROMs = 0; + +typedef uint8_t bool_t; + +#define LIST_FILE_SUPPORTED 0 + +static void usage(char *app_name) +{ + fprintf(stderr, "usage: %s -t target\n", app_name); +#if LIST_FILE_SUPPORTED + fprintf(stderr, " [-l list_file]"); +#endif + fprintf(stderr, " [-v|-q] [-h hfi] [-o port] [-m module] [-F]"); + fprintf(stderr, "\n"); + fprintf(stderr, " -t - target for which to verify fw\n"); +#if LIST_FILE_SUPPORTED + fprintf(stderr, " -l - file that holds a list of targets to update\n"); +#endif + fprintf(stderr, " -v - verbose output\n"); + fprintf(stderr, " -q - no output\n"); + fprintf(stderr, " -h - hfi, numbered 1..n, 0= -o port will be a\n"); + fprintf(stderr, " system wide port num (default is 0)\n"); + fprintf(stderr, " -o - port, numbered 1..n, 0=1st active (default\n"); + fprintf(stderr, " is 1st active)\n"); + fprintf(stderr, " -F - do secondary EEPROM (default is primary)\n"); + fprintf(stderr, "\n"); + fprintf(stderr, "The -h and -o options permit a variety of selections:\n"); + fprintf(stderr, " -h 0 - 1st active port in system (this is the default)\n"); + fprintf(stderr, " -h 0 -o 0 - 1st active port in system\n"); + fprintf(stderr, " -h x - 1st active port on HFI x\n"); + fprintf(stderr, " -h x -o 0 - 1st active port on HFI x\n"); + fprintf(stderr, " -h 0 -o y - port y within system (irrespective of which ports are active)\n"); + fprintf(stderr, " -h x -o y - HFI x, port y\n"); + +#if 0 /* non-documented options */ + fprintf(stderr, " -s - delay in seconds between requests\n"); + fprintf(stderr, " -u - delay in microseconds between requests\n"); + fprintf(stderr, " -T - response timeout in microseconds\n"); + fprintf(stderr, " -z - read data length in bytes\n"); + fprintf(stderr, " -C - compare primary and secondary EEPROM, verify same\n"); +#endif + + exit(2); +} + +int main(int argc, char *argv[]) +{ + char *cmdName; + char *opts="CDFvqt:l:h:o:m:s:u:T:z:"; + char *fwBuffer = NULL; + char *imageDesc = "primary"; + char parameter[100]; + char *p; + uint8 initialBuffer[32]; + uint8 *data = NULL; + int fwSize = 0;; + int bufferSize; + EUI64 destPortGuid = -1; + int c; + uint8 hfi = 0; + uint8 port = 0; + IB_PATH_RECORD path; + uint16 sessionID=(uint16)-1; + uint32 locationDescriptor; + uint32 dataLen = 0; + uint32 dataOffset; + uint32 *u; + uint32 crcEEPROM; + uint32 crc; + VENDOR_MAD mad; + FSTATUS status = FSUCCESS; + struct omgt_port *omgt_port_session = NULL; + + // determine how we've been invoked + cmdName = strrchr(argv[0], '/'); // Find last '/' in path + if (cmdName != NULL) { + cmdName++; // Skip over last '/' + } else { + cmdName = argv[0]; + } + + // parse options and parameters + while (-1 != (c = getopt(argc, argv, opts))) { + switch (c) { + case 'D': + g_debugMode = 1; + break; + + case 't': + errno = 0; + strncpy(parameter, optarg, sizeof(parameter)-1); + parameter[sizeof(parameter)-1] = 0; + if ((p = strchr(parameter, ',')) != NULL) { + *p = '\0'; + } + if (FSUCCESS != StringToUint64(&destPortGuid, parameter, NULL, 0, TRUE)) { + fprintf(stderr, "%s: Error: Invalid GUID: %s\n", cmdName, optarg); + usage(cmdName); + } + break; + + case 'l': +#if !LIST_FILE_SUPPORTED + fprintf(stderr, "Error: l option is not supported at this time\n"); + exit(1); +#endif + break; + + case 'v': + g_verbose = 1; + break; + + case 'q': + g_quiet = 1; + break; + + case 'h': + if (FSUCCESS != StringToUint8(&hfi, optarg, NULL, 0, TRUE)) { + fprintf(stderr, "%s: Error: Invalid HFI Number: %s\n", cmdName, optarg); + usage(cmdName); + } + g_gotHfi = 1; + break; + + case 'o': + if (FSUCCESS != StringToUint8(&port, optarg, NULL, 0, TRUE)) { + fprintf(stderr, "%s: Error: Invalid Port Number: %s\n", cmdName, optarg); + usage(cmdName); + } + g_gotPort = 1; + break; + + case 's': + if (FSUCCESS != StringToInt32(&g_sleepParam, optarg, NULL, 0, TRUE) + || g_sleepParam < 0) { + fprintf(stderr, "%s: Error: Invalid delay value: %s\n", cmdName, optarg); + usage(cmdName); + } + break; + + case 'u': + if (FSUCCESS != StringToInt32(&g_usleepParam, optarg, NULL, 0, TRUE) + || g_usleepParam < 0) { + fprintf(stderr, "%s: Error: Invalid delay value: %s\n", cmdName, optarg); + usage(cmdName); + } + break; + + case 'z': + if (FSUCCESS != StringToInt32(&g_dataLenParam, optarg, NULL, 0, TRUE) + || g_dataLenParam < 0) { + fprintf(stderr, "%s: Error: Invalid data length value: %s\n", cmdName, optarg); + usage(cmdName); + } + break; + + case 'T': + if (FSUCCESS != StringToInt32(&g_respTimeout, optarg, NULL, 0, TRUE) + || g_respTimeout < 0) { + fprintf(stderr, "%s: Error: Invalid delay value: %s\n", cmdName, optarg); + usage(cmdName); + } + break; + + case 'F': + g_gotSecondary = 1; + imageDesc = "secondary"; + break; + + case 'C': + g_compareEEPROMs = 1; + break; + + default: + usage(cmdName); + break; + + } + } + + // user has requested display of help + if (argc == 1) { + usage(cmdName); + } + + if (-1 == destPortGuid) { + fprintf(stderr, "%s: Error: Must specify a target GUID\n", cmdName); + exit(1); + } + + if (g_quiet && (g_debugMode || g_verbose)) { + fprintf(stderr, "%s: Error: Can not specify both -q and -D|-v\n", cmdName); + exit(1); + } + + if (g_sleepParam && g_usleepParam) { + fprintf(stderr, "%s: Error: Can not specify both -s and -u\n", cmdName); + exit(1); + } + + + // read the file into the buffer + + // Get the path + + struct omgt_params params = {.debug_file = g_debugMode ? stderr : NULL}; + status = omgt_open_port_by_num(&omgt_port_session, hfi, port, ¶ms); + if (status != 0) { + fprintf(stderr, "%s: Error: Unable to open fabric interface.\n", cmdName); + exit(1); + } + + if (getDestPath(omgt_port_session, destPortGuid, cmdName, &path) != FSUCCESS) { + fprintf(stderr, "%s: Error: Failed to get destination path\n", cmdName); + status = FERROR; + goto err_exit; + } + + // Send a ClassPortInfo to see if the switch is responding + + status = sendClassPortInfoMad(omgt_port_session, &path, &mad); + if (status != FSUCCESS) { + fprintf(stderr, "%s: Error: Failed to send/rcv ClassPortInfo\n", cmdName); + goto err_exit; + } + + // Get a session ID + + sessionID = getSessionID(omgt_port_session, &path); + if (sessionID == (uint16)-1) { + fprintf(stderr, "%s: Error: Failed to obtain sessionID\n", cmdName); + status = FERROR; + goto err_exit; + } + + locationDescriptor = g_gotSecondary ? STL_PRR_SEC_EEPROM1_ADDR : + STL_PRR_PRI_EEPROM1_ADDR; + dataOffset = 4; + + if (g_compareEEPROMs) { + uint8 primaryBuf[STL_MAX_EEPROM_SIZE]; + uint8 secondaryBuf[STL_MAX_EEPROM_SIZE]; + uint32 crc1, crc2; + int currentEEPROM; + + for (currentEEPROM = 0; currentEEPROM < STL_EEPROM_COUNT; currentEEPROM++) { + + status = opaswEepromRW(omgt_port_session, &path, sessionID, (void *)&mad, g_respTimeout, + STL_MAX_EEPROM_SIZE, currentEEPROM * STL_MAX_EEPROM_SIZE, + (uint8 *)primaryBuf, FALSE, FALSE); + + status = opaswEepromRW(omgt_port_session, &path, sessionID, (void *)&mad, g_respTimeout, + STL_MAX_EEPROM_SIZE, currentEEPROM * STL_MAX_EEPROM_SIZE, + (uint8 *)secondaryBuf, FALSE, TRUE); + + crc1 = crc32(0, (uint8 *)primaryBuf, STL_MAX_EEPROM_SIZE); + crc2 = crc32(0, (uint8 *)secondaryBuf, STL_MAX_EEPROM_SIZE); + if (crc1 != crc2) { + printf("EEPROM #%u CRC mismatch\n", currentEEPROM+1); + } else { + printf("EEPROM #%u CRC match\n", currentEEPROM+1); + } + + } + + /* yes, we are exiting with success via the error path */ + goto err_exit; + } + + // first, read 16 bytes to access the firmware size + + status = sendI2CAccessMad(omgt_port_session, &path, sessionID, &mad, + NOJUMBOMAD, MMTHD_GET, g_respTimeout, locationDescriptor, 16, + dataOffset + CSS_HEADER_SIZE + 4, initialBuffer); + if (status == FSUCCESS) { + fwSize = ntoh32(*(uint32 *)&initialBuffer[0]) * 4; + if (fwSize < 0) { + fprintf(stderr, "%s: Error: Invalid firmware length: %d\n", cmdName, fwSize); + status = FERROR; + goto err_exit; + } else { + bufferSize = fwSize + CSS_HEADER_SIZE + 1024 + OPASW_BUFFER_PAD; + fwBuffer = malloc(bufferSize); + if (fwBuffer) { + memset(fwBuffer, 0, sizeof(bufferSize)); + data = (uint8 *)fwBuffer; + } else { + fprintf(stderr, "%s: Error: Failed to allocate memory of length: %d\n", cmdName, fwSize); + status = FERROR; + goto err_exit; + } + } + } else goto err_exit; + + dataLen = fwSize + CSS_HEADER_SIZE; + data = (uint8 *)fwBuffer; + dataOffset = 0; + + status = opaswEepromRW(omgt_port_session, &path, sessionID, &mad, g_respTimeout, + dataLen + 4, dataOffset, data, FALSE, g_gotSecondary); + if (!g_quiet && (status == FSUCCESS)) { + printf("\n"); + fflush(stdout); + } + if (status == FSUCCESS) { + u = (uint32 *)&fwBuffer[fwSize + CSS_HEADER_SIZE]; + crcEEPROM = *u; + crc = crc32(0, (uint8 *)&fwBuffer[CSS_HEADER_SIZE + 4], fwSize - 4); + if (crcEEPROM != crc) { + printf("%s: invalid %s image found\n", cmdName, imageDesc); + fprintf(stderr, "CRC mismatch: 0x%08x : 0x%08x\n", ntoh32(crc), ntoh32(crcEEPROM)); + status = FERROR; + } else { + if (g_verbose) + fprintf(stderr, "CRC match: 0x%08x : 0x%08x\n", ntoh32(crc), ntoh32(crcEEPROM)); + printf("%s: valid %s image found\n", cmdName, imageDesc); + } + } + +err_exit: + if (sessionID != (uint16)-1) + releaseSession(omgt_port_session, &path, sessionID); + + omgt_close_port(omgt_port_session); + + if (status == FSUCCESS) { + printf("opaswfwverify completed\n"); + exit(0); + } else + exit(1); + +} diff --git a/IbaTools/opasw/opaswping/Makefile b/IbaTools/opasw/opaswping/Makefile new file mode 100644 index 0000000..4d11384 --- /dev/null +++ b/IbaTools/opasw/opaswping/Makefile @@ -0,0 +1,159 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** +# Makefile for opaswping + +# Include Make Control Settings +include $(TL_DIR)/$(PROJ_FILE_DIR)/Makesettings.project + +#=============================================================================# +# Definitions: +#-----------------------------------------------------------------------------# + +# Name of SubProjects +DS_SUBPROJECTS = +# name of executable or downloadable image +EXECUTABLE = $(BUILDDIR)/opaswping$(EXE_SUFFIX) +# list of sub directories to build +DIRS = +# C files (.c) +CFILES = \ + opaswping.c \ + # Add more c files here +# C++ files (.cpp) +CCFILES = \ + # Add more cpp files here +# lex files (.lex) +LFILES = \ + # Add more lex files here +# archive library files (basename, $ARFILES will add MOD_LIB_DIR/prefix and suffix) +LIBFILES= +# Windows Resource Files (.rc) +RSCFILES = +# Windows IDL File (.idl) +IDLFILE = +# Windows Linker Module Definitions (.def) file for dll's +DEFFILE = +# targets to build during INCLUDES phase (add public includes here) +INCLUDE_TARGETS = \ + # Add more h hpp files here +# Non-compiled files + # Add more files here +MISC_FILES = +# all source files +SOURCES = $(CFILES) $(CCFILES) $(LFILES) $(RSCFILES) $(IDLFILE) +# Source files to include in DSP File +DSP_SOURCES = $(INCLUDE_TARGETS) $(SOURCES) $(MISC_FILES) \ + $(RSCFILES) $(DEFFILE) $(MAKEFILE) +# all object files +OBJECTS = $(CFILES:.c=$(OBJ_SUFFIX)) $(CCFILES:.cpp=$(OBJ_SUFFIX)) \ + $(LFILES:.lex=$(OBJ_SUFFIX)) +RSCOBJECTS = $(RSCFILES:.rc=$(RES_SUFFIX)) +# targets to build during LIBS phase +LIB_TARGETS_IMPLIB = +LIB_TARGETS_ARLIB = # $(LIB_PREFIX)ResourceTest$(ARLIB_SUFFIX) +LIB_TARGETS_EXP = $(LIB_TARGETS_IMPLIB:$(ARLIB_SUFFIX)=$(EXP_SUFFIX)) +LIB_TARGETS_MISC = +# targets to build during CMDS phase +CMD_TARGETS_SHLIB = +CMD_TARGETS_EXE = $(EXECUTABLE) +CMD_TARGETS_MISC = +# files to remove during clean phase +CLEAN_TARGETS_MISC = +CLEAN_TARGETS = $(OBJECTS) $(RSCOBJECTS) $(IDL_TARGETS) $(CLEAN_TARGETS_MISC) +# other files to remove during clobber phase +CLOBBER_TARGETS_MISC= +# sub-directory to install to within bin +BIN_SUBDIR = +# sub-directory to install to within include +INCLUDE_SUBDIR = + +# Additional Settings +#CLOCALDEBUG = User defined C debugging compilation flags [Empty] +#CCLOCALDEBUG = User defined C++ debugging compilation flags [Empty] +#CLOCAL = User defined C flags for compiling [Empty] +#CCLOCAL = User defined C++ flags for compiling [Empty] +#BSCLOCAL = User flags for Browse File Builder [Empty] +#DEPENDLOCAL = user defined makedepend flags [Empty] +#LINTLOCAL = User defined lint flags [Empty] +#LOCAL_INCLUDE_DIRS = User include directories to search for C/C++ headers [Empty] +#LDLOCAL = User defined C flags for linking [Empty] +#IMPLIBLOCAL = User flags for Object Lirary Manager [Empty] +#MIDLLOCAL = User flags for IDL compiler [Empty] +#RSCLOCAL = User flags for resource compiler [Empty] +#LOCALDEPLIBS = User libraries to include in dependencies [Empty] +#LOCALLIBS = User libraries to use when linking [Empty] +# (in addition to LOCALDEPLIBS) +#LOCAL_LIB_DIRS = User library directories for libpaths [Empty] + +CLOCAL = $(CPIE) +LOCALDEPLIBS=$(IBACCESS_USER_LIBS) opaswcommon opamgt-priv +LOCAL_INCLUDE_DIRS= +LOCALLIBS=$(OPENIB_USER_LIBS) crypto +LOCAL_LIB_DIRS=$(OPENIB_USER_LIB_DIRS) $(IBACCESS_USER_LIB_DIRS) + +# Include Make Rules definitions and rules +include $(TL_DIR)/IbaTools/Makerules.module + +#=============================================================================# +# Overrides: +#-----------------------------------------------------------------------------# +#CCOPT = # C++ optimization flags, default lets build config decide +#COPT = # C optimization flags, default lets build config decide +#SUBSYSTEM = Subsystem to build for (none, console or windows) [none] +# (Windows Only) +#USEMFC = How Windows MFC should be used (none, static, shared, no_mfc) [none] +# (Windows Only) +#=============================================================================# + +#=============================================================================# +# Rules: +#-----------------------------------------------------------------------------# +# process Sub-directories +include $(TL_DIR)/Makerules/Maketargets.toplevel + +# build cmds and libs +include $(TL_DIR)/Makerules/Maketargets.build + +# install for includes, libs and cmds phases +include $(TL_DIR)/Makerules/Maketargets.install + +# install for stage phase +include $(TL_DIR)/Makerules/Maketargets.stage +STAGE:: + #$(VS)$(STAGE_INSTALL) $(STAGE_INSTALL_DIR_OPT) $(PROJ_STAGE_FASTFABRIC_DIR) $(EXECUTABLE) + $(VS)$(STAGE_INSTALL) $(STAGE_INSTALL_DIR_OPT) $(PROJ_STAGE_BIN_DIR) $(EXECUTABLE) + +# Unit test execution +#include $(TL_DIR)/Makerules/Maketargets.runtest + +#=============================================================================# + +#=============================================================================# +# DO NOT DELETE THIS LINE -- make depend depends on it. +#=============================================================================# diff --git a/IbaTools/opasw/opaswping/opaswping.c b/IbaTools/opasw/opaswping/opaswping.c new file mode 100644 index 0000000..a61cada --- /dev/null +++ b/IbaTools/opasw/opaswping/opaswping.c @@ -0,0 +1,219 @@ +/* BEGIN_ICS_COPYRIGHT7 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT7 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +#include +#include +#include +#include +#include + +/* work around conflicting names */ + +#include "iba/ib_types.h" +#include "iba/ib_sm_priv.h" +#include "iba/ib_helper.h" +#include "opamgt_sa_priv.h" +#include +#include "opaswcommon.h" + +// globals + +int g_debugMode = 0; +int g_verbose = 0; +int g_quiet = 0; +int g_gotHfi = 0; +int g_gotPort = 0; + +#define LIST_FILE_SUPPORTED 0 + +static void usage(char *app_name) +{ + fprintf(stderr, "usage: %s -t target ", app_name); +#if LIST_FILE_SUPPORTED + fprintf(stderr, "[-l list_file] "); +#endif + fprintf(stderr, "[-v|-q] [-h hfi] [-o port]"); + fprintf(stderr, "\n"); + fprintf(stderr, " -t - target to ping\n"); +#if LIST_FILE_SUPPORTED + fprintf(stderr, " -l - file that holds a list of targets to ping\n"); +#endif + fprintf(stderr, " -v - verbose output\n"); + fprintf(stderr, " -q - no output\n"); + fprintf(stderr, " -h - hfi, numbered 1..n, 0= -o port will be a\n"); + fprintf(stderr, " system wide port num (default is 0)\n"); + fprintf(stderr, " -o - port, numbered 1..n, 0=1st active (default\n"); + fprintf(stderr, " is 1st active)\n"); + fprintf(stderr, "\n"); + fprintf(stderr, "The -h and -o options permit a variety of selections:\n"); + fprintf(stderr, " -h 0 - 1st active port in system (this is the default)\n"); + fprintf(stderr, " -h 0 -o 0 - 1st active port in system\n"); + fprintf(stderr, " -h x - 1st active port on HFI x\n"); + fprintf(stderr, " -h x -o 0 - 1st active port on HFI x\n"); + fprintf(stderr, " -h 0 -o y - port y within system (irrespective of which ports are active)\n"); + fprintf(stderr, " -h x -o y - HFI x, port y\n"); + + exit(2); +} + +int main(int argc, char *argv[]) +{ + char *cmdName; + const char *opts="Dvqt:l:h:o:"; + char parameter[100]; + char *p; + EUI64 destPortGuid = -1; + int c; + uint8 hfi = 0; + uint8 port = 0; + IB_PATH_RECORD path; + STL_PERF_MAD mad; + FSTATUS status; + struct omgt_port *omgt_port_session = NULL; + + // determine how we've been invoked + cmdName = strrchr(argv[0], '/'); // Find last '/' in path + if (cmdName != NULL) { + cmdName++; // Skip over last '/' + } else { + cmdName = argv[0]; + } + + // Initialize + + + // parse options and parameters + while (-1 != (c = getopt(argc, argv, opts))) { + switch (c) { + case 'D': + g_debugMode = 1; + break; + + case 't': + errno = 0; + strncpy(parameter, optarg, sizeof(parameter)-1); + parameter[sizeof(parameter)-1] = 0; + if ((p = strchr(parameter, ',')) != NULL) { + *p = '\0'; + } + if (FSUCCESS != StringToUint64(&destPortGuid, parameter, NULL, 0, TRUE)) { + fprintf(stderr, "%s: Error: Invalid GUID: %s\n", cmdName, optarg); + usage(cmdName); + } + break; + + case 'l': +#if !LIST_FILE_SUPPORTED + fprintf(stderr, "Error: l option is not supported at this time\n"); + exit(1); +#endif + break; + + case 'v': + g_verbose = 1; + break; + + case 'q': + g_quiet = 1; + break; + + case 'h': + if (FSUCCESS != StringToUint8(&hfi, optarg, NULL, 0, TRUE)) { + fprintf(stderr, "%s: Error: Invalid HFI Number: %s\n", cmdName, optarg); + usage(cmdName); + } + g_gotHfi = 1; + break; + + case 'o': + if (FSUCCESS != StringToUint8(&port, optarg, NULL, 0, TRUE)) { + fprintf(stderr, "%s: Error: Invalid Port Number: %s\n", cmdName, optarg); + usage(cmdName); + } + g_gotPort = 1; + break; + + default: + usage(cmdName); + break; + + } + } + + // user has requested display of help + if (argc == 1) { + usage(cmdName); + exit(0); + } + + if (-1 == destPortGuid) { + fprintf(stderr, "%s: Error: Must specify a target GUID\n", cmdName); + exit(1); + } + + if (g_quiet && (g_debugMode || g_verbose)) { + fprintf(stderr, "%s: Error: Can not specify both -q and -D|-v\n", cmdName); + exit(1); + } + + // Get the path + + struct omgt_params params = {.debug_file = (g_verbose || g_debugMode) ? stderr : NULL}; + status = omgt_open_port_by_num(&omgt_port_session, hfi, port, ¶ms); + if (status != 0) { + fprintf(stderr, "%s: Error: Unable to open fabric interface.\n", cmdName); + exit(1); + } + + if (getDestPath(omgt_port_session, destPortGuid, cmdName, &path) != FSUCCESS) { + fprintf(stderr, "%s: Error: Failed to get destination path\n", cmdName); + omgt_close_port(omgt_port_session); + exit(1); + } + + status = doPingSwitch(omgt_port_session, &path, &mad); + if (status != FSUCCESS) { + if (status != FTIMEOUT) { + fprintf(stderr, "%s: Error: Failed to ping switch\n", cmdName); + omgt_close_port(omgt_port_session); + exit(1); + } else { + printf("%s: Unit is not present\n", cmdName); + omgt_close_port(omgt_port_session); + exit(0); + } + } + + printf("%s: Unit is present\n", cmdName); + omgt_close_port(omgt_port_session); + exit(0); + +} diff --git a/IbaTools/opasw/opaswquery/Makefile b/IbaTools/opasw/opaswquery/Makefile new file mode 100644 index 0000000..d7ebd6d --- /dev/null +++ b/IbaTools/opasw/opaswquery/Makefile @@ -0,0 +1,159 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** +# Makefile for opaswquery + +# Include Make Control Settings +include $(TL_DIR)/$(PROJ_FILE_DIR)/Makesettings.project + +#=============================================================================# +# Definitions: +#-----------------------------------------------------------------------------# + +# Name of SubProjects +DS_SUBPROJECTS = +# name of executable or downloadable image +EXECUTABLE = $(BUILDDIR)/opaswquery$(EXE_SUFFIX) +# list of sub directories to build +DIRS = +# C files (.c) +CFILES = \ + opaswquery.c \ + # Add more c files here +# C++ files (.cpp) +CCFILES = \ + # Add more cpp files here +# lex files (.lex) +LFILES = \ + # Add more lex files here +# archive library files (basename, $ARFILES will add MOD_LIB_DIR/prefix and suffix) +LIBFILES= +# Windows Resource Files (.rc) +RSCFILES = +# Windows IDL File (.idl) +IDLFILE = +# Windows Linker Module Definitions (.def) file for dll's +DEFFILE = +# targets to build during INCLUDES phase (add public includes here) +INCLUDE_TARGETS = \ + # Add more h hpp files here +# Non-compiled files + # Add more files here +MISC_FILES = +# all source files +SOURCES = $(CFILES) $(CCFILES) $(LFILES) $(RSCFILES) $(IDLFILE) +# Source files to include in DSP File +DSP_SOURCES = $(INCLUDE_TARGETS) $(SOURCES) $(MISC_FILES) \ + $(RSCFILES) $(DEFFILE) $(MAKEFILE) +# all object files +OBJECTS = $(CFILES:.c=$(OBJ_SUFFIX)) $(CCFILES:.cpp=$(OBJ_SUFFIX)) \ + $(LFILES:.lex=$(OBJ_SUFFIX)) +RSCOBJECTS = $(RSCFILES:.rc=$(RES_SUFFIX)) +# targets to build during LIBS phase +LIB_TARGETS_IMPLIB = +LIB_TARGETS_ARLIB = # $(LIB_PREFIX)ResourceTest$(ARLIB_SUFFIX) +LIB_TARGETS_EXP = $(LIB_TARGETS_IMPLIB:$(ARLIB_SUFFIX)=$(EXP_SUFFIX)) +LIB_TARGETS_MISC = +# targets to build during CMDS phase +CMD_TARGETS_SHLIB = +CMD_TARGETS_EXE = $(EXECUTABLE) +CMD_TARGETS_MISC = +# files to remove during clean phase +CLEAN_TARGETS_MISC = +CLEAN_TARGETS = $(OBJECTS) $(RSCOBJECTS) $(IDL_TARGETS) $(CLEAN_TARGETS_MISC) +# other files to remove during clobber phase +CLOBBER_TARGETS_MISC= +# sub-directory to install to within bin +BIN_SUBDIR = +# sub-directory to install to within include +INCLUDE_SUBDIR = + +# Additional Settings +#CLOCALDEBUG = User defined C debugging compilation flags [Empty] +#CCLOCALDEBUG = User defined C++ debugging compilation flags [Empty] +#CLOCAL = User defined C flags for compiling [Empty] +#CCLOCAL = User defined C++ flags for compiling [Empty] +#BSCLOCAL = User flags for Browse File Builder [Empty] +#DEPENDLOCAL = user defined makedepend flags [Empty] +#LINTLOCAL = User defined lint flags [Empty] +#LOCAL_INCLUDE_DIRS = User include directories to search for C/C++ headers [Empty] +#LDLOCAL = User defined C flags for linking [Empty] +#IMPLIBLOCAL = User flags for Object Lirary Manager [Empty] +#MIDLLOCAL = User flags for IDL compiler [Empty] +#RSCLOCAL = User flags for resource compiler [Empty] +#LOCALDEPLIBS = User libraries to include in dependencies [Empty] +#LOCALLIBS = User libraries to use when linking [Empty] +# (in addition to LOCALDEPLIBS) +#LOCAL_LIB_DIRS = User library directories for libpaths [Empty] + +CLOCAL = $(CPIE) +LOCALDEPLIBS=$(IBACCESS_USER_LIBS) opaswcommon opamgt-priv +LOCAL_INCLUDE_DIRS= +LOCALLIBS=$(OPENIB_USER_LIBS) crypto +LOCAL_LIB_DIRS=$(OPENIB_USER_LIB_DIRS) $(IBACCESS_USER_LIB_DIRS) + +# Include Make Rules definitions and rules +include $(TL_DIR)/IbaTools/Makerules.module + +#=============================================================================# +# Overrides: +#-----------------------------------------------------------------------------# +#CCOPT = # C++ optimization flags, default lets build config decide +#COPT = # C optimization flags, default lets build config decide +#SUBSYSTEM = Subsystem to build for (none, console or windows) [none] +# (Windows Only) +#USEMFC = How Windows MFC should be used (none, static, shared, no_mfc) [none] +# (Windows Only) +#=============================================================================# + +#=============================================================================# +# Rules: +#-----------------------------------------------------------------------------# +# process Sub-directories +include $(TL_DIR)/Makerules/Maketargets.toplevel + +# build cmds and libs +include $(TL_DIR)/Makerules/Maketargets.build + +# install for includes, libs and cmds phases +include $(TL_DIR)/Makerules/Maketargets.install + +# install for stage phase +include $(TL_DIR)/Makerules/Maketargets.stage +STAGE:: + #$(VS)$(STAGE_INSTALL) $(STAGE_INSTALL_DIR_OPT) $(PROJ_STAGE_FASTFABRIC_DIR) $(EXECUTABLE) + $(VS)$(STAGE_INSTALL) $(STAGE_INSTALL_DIR_OPT) $(PROJ_STAGE_BIN_DIR) $(EXECUTABLE) + +# Unit test execution +#include $(TL_DIR)/Makerules/Maketargets.runtest + +#=============================================================================# + +#=============================================================================# +# DO NOT DELETE THIS LINE -- make depend depends on it. +#=============================================================================# diff --git a/IbaTools/opasw/opaswquery/opaswquery.c b/IbaTools/opasw/opaswquery/opaswquery.c new file mode 100644 index 0000000..4dd45f4 --- /dev/null +++ b/IbaTools/opasw/opaswquery/opaswquery.c @@ -0,0 +1,616 @@ +/* BEGIN_ICS_COPYRIGHT7 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT7 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +#include +#include +#include +#include +#include + +/* work around conflicting names */ + +#include "iba/ib_types.h" +#include "iba/ib_sm_priv.h" +#include "iba/ib_helper.h" +#include "iba/stl_helper.h" +#include "iba/stl_types.h" +#include "opamgt_sa_priv.h" +#include +#include "opaswcommon.h" +#include "opaswmetadata.h" + +#define EEPROM_MASK 0x100 +// defining valid values for fan tray and power supply +// TODO: update when actual information becomres available +#define MAX_FT 4 +#define MIN_FT 1 +#define MAX_PS 2 +#define MIN_PS 1 + +//defining values for fan tray status +#define FAN_STATUS_0 0X01 +#define FAN_STATUS_1 0X02 +#define FAN_STATUS_2 0X04 +#define FAN_STATUS_3 0X08 +#define FAN_STATUS_4 0X10 +#define FAN_STATUS_5 0X20 +#define FAN_STATUS_TRAY1 (FAN_STATUS_0 | FAN_STATUS_1 | FAN_STATUS_2) +#define FAN_STATUS_TRAY2 (FAN_STATUS_3 | FAN_STATUS_4 | FAN_STATUS_5) + +// globals + +int g_debugMode = 0; +int g_verbose = 0; +int g_quiet = 0; +int g_gotHfi = 0; +int g_gotPort = 0; +uint8 g_queryNum = 0; +int g_gotModule = 0; +int8 g_intParam = 0; + +#define LIST_FILE_SUPPORTED 0 + +static void usage(char *app_name) +{ + fprintf(stderr, "usage: %s -t target ", app_name); +#if LIST_FILE_SUPPORTED + fprintf(stderr, "[-l list_file] "); +#endif + fprintf(stderr, "[-v|-q] [-h hfi] [-o port] -Q query-number [-i int]"); + fprintf(stderr, "\n"); + fprintf(stderr, " -t - target to query\n"); +#if LIST_FILE_SUPPORTED + fprintf(stderr, " -l - file that holds a list of targets to query\n"); +#endif + fprintf(stderr, " -v - verbose output\n"); + fprintf(stderr, " -q - no output\n"); + fprintf(stderr, " -h - hfi, numbered 1..n, 0= -o port will be a\n"); + fprintf(stderr, " system wide port num (default is 0)\n"); + fprintf(stderr, " -o - port, numbered 1..n, 0=1st active (default\n"); + fprintf(stderr, " is 1st active)\n"); + fprintf(stderr, " -Q - query number to run:\n"); + fprintf(stderr, " 2 - boot from primary or secondary EEPROM\n"); + fprintf(stderr, " 3 - display firwmare version\n"); + fprintf(stderr, " 4 - display VPD Info - comma-separated list\n"); + fprintf(stderr, " 5 - get node description\n"); + fprintf(stderr, " 6 - temperature readings\n"); + fprintf(stderr, " 7 - fan speed\n"); + fprintf(stderr, " 8 - power supply status - use with -i [%d-%d]\n", MIN_PS, MAX_PS); + fprintf(stderr, " 9 - display asic version\n"); + fprintf(stderr, " 10 - display session ID\n"); + fprintf(stderr, " 11 - display basic configuration\n"); + fprintf(stderr, " 12 - board ID\n"); + fprintf(stderr, " -i - integer parameter - use with queries 7,8\n"); + fprintf(stderr, "\n"); + fprintf(stderr, "The -h and -o options permit a variety of selections:\n"); + fprintf(stderr, " -h 0 - 1st active port in system (this is the default)\n"); + fprintf(stderr, " -h 0 -o 0 - 1st active port in system\n"); + fprintf(stderr, " -h x - 1st active port on HFI x\n"); + fprintf(stderr, " -h x -o 0 - 1st active port on HFI x\n"); + fprintf(stderr, " -h 0 -o y - port y within system (irrespective of which ports are active)\n"); + fprintf(stderr, " -h x -o y - HFI x, port y\n"); + + exit(2); +} +int main(int argc, char *argv[]) +{ + char *cmdName; + const char *opts="Dvqt:l:h:o:m:Q:i:"; + char parameter[100]; + char *p; + EUI64 destPortGuid = -1; + int c; + int i; + uint8 hfi = 0; + uint8 port = 0; + IB_PATH_RECORD path; + uint16 sessionID; + uint32 regValue; + uint32 fanSpeed[OPASW_PSOC_FAN_CTRL_TACHS]; + char tempStrs[I2C_OPASW_TEMP_SENSOR_COUNT][TEMP_STR_LENGTH]; + uint32 psStatus; + uint8 fwVersion[40]; + vpd_fruInfo_rec_t vpdInfo; + char mfgID[10]; + char mfgDate[20]; + char mfgTime[10]; + uint8 nodeDesc[80]; + opasw_ini_descriptor_get_t tableDescriptors; + table_parsed_data_t *portParsedDataTable=NULL; + uint32 numPorts; + uint32 portEntrySize; + uint8 memoryData[200]; + uint8 boardID; + VENDOR_MAD mad; + FSTATUS status = FSUCCESS; + uint32 asicVersion; + uint8 chipStep; + uint8 chipRev; + + + + table_parsed_data_t *portPtrs=NULL; + uint32 portLinkWidthSupportedIndex; + uint32 portLinkSpeedSupportedIndex; + uint32 portFMEnabledIndex; + uint32 portLinkCRCModeIndex; + uint32 portvCUIndex; + uint32 portExternalLoopbackAllowedIndex; + char portLinkCRCModeValue[35]; + char portLinkWidthSupportedText[20]; + char portLinkSpeedSupportedText[20]; + struct omgt_port *omgt_port_session = NULL; + + uint8 fanStatus; + + // determine how we've been invoked + cmdName = strrchr(argv[0], '/'); // Find last '/' in path + if (cmdName != NULL) { + cmdName++; // Skip over last '/' + } else { + cmdName = argv[0]; + } + + // Initialize + + + // parse options and parameters + while (-1 != (c = getopt(argc, argv, opts))) { + switch (c) { + case 'D': + g_debugMode = 1; + break; + + case 't': + errno = 0; + strncpy(parameter, optarg, sizeof(parameter)-1); + parameter[sizeof(parameter)-1] = 0; + if ((p = strchr(parameter, ',')) != NULL) { + *p = '\0'; + } + if (FSUCCESS != StringToUint64(&destPortGuid, parameter, NULL, 0, TRUE)) { + fprintf(stderr, "%s: Error: Invalid GUID: %s\n", cmdName, optarg); + usage(cmdName); + } + break; + + case 'l': +#if !LIST_FILE_SUPPORTED + fprintf(stderr, "Error: l option is not supported at this time\n"); + exit(1); +#endif + break; + + case 'v': + g_verbose = 1; + break; + + case 'q': + g_quiet = 1; + break; + + case 'h': + if (FSUCCESS != StringToUint8(&hfi, optarg, NULL, 0, TRUE)) { + fprintf(stderr, "%s: Error: Invalid HFI Number: %s\n", cmdName, optarg); + usage(cmdName); + } + g_gotHfi = 1; + break; + + case 'o': + if (FSUCCESS != StringToUint8(&port, optarg, NULL, 0, TRUE)) { + fprintf(stderr, "%s: Error: Invalid Port Number: %s\n", cmdName, optarg); + usage(cmdName); + } + g_gotPort = 1; + break; + + case 'Q': + if (FSUCCESS != StringToUint8(&g_queryNum, optarg, NULL, 0, TRUE)) { + fprintf(stderr, "%s: Error: Invalid Query Number: %s\n", cmdName, optarg); + usage(cmdName); + } + break; + + case 'i': + if (FSUCCESS != StringToInt8(&g_intParam, optarg, NULL, 0, TRUE) + || g_intParam < 0) { + fprintf(stderr, "%s: Error: Invalid integer parameter: %s\n", cmdName, optarg); + usage(cmdName); + } + break; + + default: + usage(cmdName); + break; + + } + } + + // user has requested display of help + if (argc == 1) { + usage(cmdName); + exit(0); + } + + if (-1 == destPortGuid) { + fprintf(stderr, "%s: Error: Must specify a target GUID\n", cmdName); + exit(1); + } + + if (g_queryNum == 0) { + fprintf(stderr, "%s: Error: must enter a query number\n", cmdName); + exit(1); + } + + if ((g_queryNum == 8) && ((g_intParam > MAX_PS) || (g_intParam < MIN_PS))) { + fprintf(stderr, "%s: Error: Query number 8 - must use -i for valid Power Supply number %d - %d\n", cmdName, MIN_PS, MAX_PS); + usage(cmdName); + } + + if (g_quiet && (g_debugMode || g_verbose)) { + fprintf(stderr, "%s: Error: Can not specify both -q and -D|-v\n", cmdName); + exit(1); + } + + // Get the path + + struct omgt_params params = {.debug_file = (g_verbose || g_debugMode) ? stderr : NULL}; + status = omgt_open_port_by_num(&omgt_port_session, hfi, port, ¶ms); + if (status != 0) { + fprintf(stderr, "%s: Error: Unable to open fabric interface.\n", cmdName); + exit(1); + } + + if (getDestPath(omgt_port_session, destPortGuid, cmdName, &path) != FSUCCESS) { + fprintf(stderr, "%s: Error: Failed to get destination path\n", cmdName); + goto err_exit; + } + + // Send a ClassPortInfo to see if the switch is responding + + status = sendClassPortInfoMad(omgt_port_session, &path, &mad); + if (status != FSUCCESS) { + fprintf(stderr, "%s: Error: Failed to send/rcv ClassPortInfo\n", cmdName); + goto err_exit; + } + + // Get a session ID + + sessionID = getSessionID(omgt_port_session, &path); + if (sessionID == (uint16)-1) { + fprintf(stderr, "%s: Error: Failed to obtain sessionID\n", cmdName); + status = FERROR; + goto err_exit; + } + + // Send the test mad + + switch (g_queryNum) { + case 1: + fprintf(stderr, "Error: Module type query no longer supported.\n"); + status = FERROR; + break; + + case 2: + status = sendRegisterAccessMad(omgt_port_session, &path, &mad, sessionID, + (uint8)0x6f, ®Value, 1); + if (status != FSUCCESS) { + fprintf(stderr, "Error: Failed to access register - status %d\n", status); + break; + } + printf("Switch has booted from %s firmware image\n", (regValue & EEPROM_MASK) ? "failsafe" : "primary"); + break; + + case 3: + status = getFwVersion(omgt_port_session, &path, &mad, sessionID, fwVersion); + if (status != FSUCCESS) { + fprintf(stderr, "Error: Failed to acquire fw version - status %d\n", status); + break; + } + printf("FW Version is %s\n", fwVersion); + break; + + case 4: + status = getBoardID(omgt_port_session, &path, &mad, sessionID, &boardID); + if (status != FSUCCESS) { + fprintf(stderr, "Error, Failed to get board id - status %d\n",status); + break; + } + status = getVPDInfo(omgt_port_session, &path, &mad, sessionID, OPASW_MODULE, boardID, &vpdInfo); + if (status != FSUCCESS) { + fprintf(stderr, "Error: Failed to access vpd info - status %d\n", status); + break; + } + snprintf(mfgID, sizeof(mfgID), "%02x%02x%02x", vpdInfo.mfgID[0] & 0xff, vpdInfo.mfgID[1] & 0xff, vpdInfo.mfgID[2] & 0xff); + snprintf(mfgDate, sizeof(mfgDate), "%d-%02d-%d", vpdInfo.mfgMonth, vpdInfo.mfgDay, vpdInfo.mfgYear + 2000); + snprintf(mfgTime, sizeof(mfgTime), "%02d:%02d", vpdInfo.mfgHours, vpdInfo.mfgMins); + printf("VPD \"%s\",\"%s\",\"%s\",\"%s\",\"%s\",\"%s\",\"%s\",\"%s\",\"%s\"\n", + vpdInfo.serialNum, + vpdInfo.partNum, + vpdInfo.model, + vpdInfo.version, + vpdInfo.mfgName, + vpdInfo.productName, + mfgID, + mfgDate, + mfgTime); + break; + + case 5: + status = getNodeDescription(omgt_port_session, &path, sessionID, nodeDesc); + if (status != FSUCCESS) { + fprintf(stderr, "Error: Failed to acquire node description - status %d\n", status); + break; + } + printf("Node description is %s\n", nodeDesc); + break; + case 6: + status = getBoardID(omgt_port_session, &path, &mad, sessionID, &boardID); + if (status != FSUCCESS) { + fprintf(stderr, "Error, Failed to get board id - status %d\n",status); + break; + } + status = getTempReadings(omgt_port_session, &path, &mad, sessionID, tempStrs, boardID); + + for (i=0; i MAX_FAN_SPEED) + printf("FAN %d:FAST ", i); + else if (fanSpeed[i] < MIN_FAN_SPEED) + printf("FAN %d:SLOW ", i); + else + printf("FAN %d:NORMAL ", i); + } + }// end else TRAY1 + if ((fanStatus & FAN_STATUS_TRAY2) == FAN_STATUS_TRAY2) { + printf("FAN 3:NOTPRESENT "); + printf("FAN 4:NOTPRESENT "); + printf("FAN 5:NOTPRESENT "); + } + else { + for (i=3; i<6; i++) { + if (fanSpeed[i] > MAX_FAN_SPEED) + printf("FAN %d:FAST ", i); + else if (fanSpeed[i] < MIN_FAN_SPEED) + printf("FAN %d:SLOW ", i); + else + printf("FAN %d:NORMAL ", i); + } + }// end els TRAY2 + + printf("\n"); + } + break; + + case 8: + status = getPowerSupplyStatus(omgt_port_session, &path, &mad, sessionID, g_intParam, + &psStatus); + if (status != FSUCCESS) { + fprintf(stderr, "Error: Failed to get power supply status for ps %d - status %d\n", g_intParam, status); + break; + } + switch (psStatus) { + case PS_ONLINE: + printf("PS %d: ONLINE\n", g_intParam); + break; + case PS_OFFLINE: + printf("PS %d: OFFLINE\n", g_intParam); + break; + case PS_NOT_PRESENT: + printf("PS %d: NOT PRESENT\n", g_intParam); + break; + case PS_INVALID: + printf("PS %d: INVALID\n", g_intParam); + break; + default: + fprintf(stderr, "Error: Failed to get power supply status for ps %d\n", g_intParam); + break; + } + break; + + case 9: + status = getAsicVersion(omgt_port_session, &path, &mad, sessionID, &asicVersion); + if (status != FSUCCESS) { + fprintf(stderr, "Error: Failed to get ASIC version - status %d\n", status); + break; + } + + chipStep = (asicVersion & ASIC_CHIP_STEP_MASK) >> ASIC_CHIP_STEP_SHFT; + chipRev = (asicVersion & ASIC_CHIP_REV_MASK) >> ASIC_CHIP_REV_SHFT; + printf("ASIC Version: V"); + if (chipRev == 0) { + switch (chipStep) { + case ASIC_CHIP_STEP_A: + printf("1\n"); + break; + case ASIC_CHIP_STEP_B: + printf("2\n"); + break; + case ASIC_CHIP_STEP_C: + printf("3\n"); + break; + default: + printf("0\n"); + break; + } + } else { + printf("0\n"); + } + break; + + case 10: + printf("Session ID: %d\n", sessionID); + break; + case 11: + { + /* query port 2 */ + int dest_port_query=1; + printf("Switch configuration values\n"); + status = sendIniDescriptorGetMad(omgt_port_session, &path, &mad, sessionID, &tableDescriptors); + if (status != FSUCCESS) { + fprintf(stderr, "%s: Error: Failed to get ini descriptors - status %d\n", cmdName, status); + goto retErr; + } + numPorts = getNumPorts(omgt_port_session, &path, sessionID); + + if( numPorts <= 0){ + fprintf(stderr,"error in fetching port records\n"); + goto retErr; + } + portEntrySize = tableDescriptors.portDataLen / numPorts; + status = sendMemAccessGetMad(omgt_port_session, &path, &mad, sessionID, tableDescriptors.portDataAddr + (dest_port_query * portEntrySize), portEntrySize*4, memoryData); + if (status != FSUCCESS) { + printf("Mem Access MAD Failed \n"); + goto retErr; + } + + if (g_verbose) { + printf("MemoryData dump:\n"); + opaswDisplayBuffer((char *)memoryData, portEntrySize * 4); + } + portParsedDataTable = malloc(tableDescriptors.portMetaDataLen * sizeof(table_parsed_data_t)); + if(portParsedDataTable == NULL) + { + fprintf(stderr,"Not enough memory \n"); + goto retErr; + } + status = parseDataTable(&portMetaData[0], memoryData, portMetaDataSize, portParsedDataTable, 0); + if(status != FSUCCESS) { + fprintf(stderr," failed: parseDataTable \n"); + goto retErr; + } + portPtrs = portParsedDataTable; + portLinkWidthSupportedIndex = getMetaDataIndexByField(&portMetaData[0], tableDescriptors.portMetaDataLen, "LINK_WIDTH_SUPPORTED"); + portLinkSpeedSupportedIndex = getMetaDataIndexByField(&portMetaData[0], tableDescriptors.portMetaDataLen, "LINK_SPEED_SUPPORTED"); + portFMEnabledIndex = getMetaDataIndexByField(&portMetaData[0], tableDescriptors.portMetaDataLen, "FM_ENABLED"); + portLinkCRCModeIndex = getMetaDataIndexByField(&portMetaData[0], tableDescriptors.portMetaDataLen, "LTP_CRC_MODE_SUPPORTED"); + portvCUIndex = getMetaDataIndexByField(&portMetaData[0], tableDescriptors.portMetaDataLen, "VCU"); + portExternalLoopbackAllowedIndex = getMetaDataIndexByField(&portMetaData[0], tableDescriptors.portMetaDataLen, "EXTERNAL_LOOPBACK_ALLOWED"); + + status = getNodeDescription(omgt_port_session, &path, sessionID, nodeDesc); + if (status != FSUCCESS) { + fprintf(stderr, "Error: Failed to acquire node description - status %d\n", status); + goto retErr; + } +#define PRINT_REC(str,fmt,arg...) printf(" %-*s : "fmt,35,str,arg); + + StlLinkWidthToText(portPtrs[portLinkWidthSupportedIndex].val.intVal, portLinkWidthSupportedText, 20); + StlLinkSpeedToText(portPtrs[portLinkSpeedSupportedIndex].val.intVal, portLinkSpeedSupportedText, 20); + + PRINT_REC("Link Width"," %s\n", portLinkWidthSupportedText); + PRINT_REC("Link Speed"," %s\n", portLinkSpeedSupportedText); + PRINT_REC("FM Enabled"," %s\n", portPtrs[portFMEnabledIndex].val.intVal ? "Yes" : "No"); + PRINT_REC("Link CRC Mode"," %s\n", StlPortLtpCrcModeVMAToText(portPtrs[portLinkCRCModeIndex].val.intVal,portLinkCRCModeValue,sizeof(portLinkCRCModeValue))); + PRINT_REC("vCU"," %d\n", portPtrs[portvCUIndex].val.intVal); + PRINT_REC("External Loopback Allowed"," %s\n", portPtrs[portExternalLoopbackAllowedIndex].val.intVal ? "Yes" : "No"); + PRINT_REC("Node Description"," %s\n", strlen((const char *)nodeDesc)==0?(const char *)"no description":(char *)nodeDesc); +retErr: + if(portParsedDataTable) + free(portParsedDataTable); + break; + } + case 12: + status = getBoardID(omgt_port_session, &path, &mad, sessionID, &boardID); + if (status != FSUCCESS) { + fprintf(stderr, "Error: Failed to get board id - status %d\n", status); + break; + } + printf("BoardID: 0x%02x\n", boardID); + break; + + default: + fprintf(stderr, "Error: Invalid query number %d\n", g_queryNum); + releaseSession(omgt_port_session, &path, sessionID); + usage(cmdName); + break; + } + + releaseSession(omgt_port_session, &path, sessionID); + + printf("opaswquery completed\n"); + +err_exit: + omgt_close_port(omgt_port_session); + + if (status == FSUCCESS) + exit(0); + else + exit(1); + +} diff --git a/IbaTools/opasw/opaswreset/Makefile b/IbaTools/opasw/opaswreset/Makefile new file mode 100644 index 0000000..1d67ce7 --- /dev/null +++ b/IbaTools/opasw/opaswreset/Makefile @@ -0,0 +1,159 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** +# Makefile for opaswreset + +# Include Make Control Settings +include $(TL_DIR)/$(PROJ_FILE_DIR)/Makesettings.project + +#=============================================================================# +# Definitions: +#-----------------------------------------------------------------------------# + +# Name of SubProjects +DS_SUBPROJECTS = +# name of executable or downloadable image +EXECUTABLE = $(BUILDDIR)/opaswreset$(EXE_SUFFIX) +# list of sub directories to build +DIRS = +# C files (.c) +CFILES = \ + opaswreset.c \ + # Add more c files here +# C++ files (.cpp) +CCFILES = \ + # Add more cpp files here +# lex files (.lex) +LFILES = \ + # Add more lex files here +# archive library files (basename, $ARFILES will add MOD_LIB_DIR/prefix and suffix) +LIBFILES= +# Windows Resource Files (.rc) +RSCFILES = +# Windows IDL File (.idl) +IDLFILE = +# Windows Linker Module Definitions (.def) file for dll's +DEFFILE = +# targets to build during INCLUDES phase (add public includes here) +INCLUDE_TARGETS = \ + # Add more h hpp files here +# Non-compiled files + # Add more files here +MISC_FILES = +# all source files +SOURCES = $(CFILES) $(CCFILES) $(LFILES) $(RSCFILES) $(IDLFILE) +# Source files to include in DSP File +DSP_SOURCES = $(INCLUDE_TARGETS) $(SOURCES) $(MISC_FILES) \ + $(RSCFILES) $(DEFFILE) $(MAKEFILE) +# all object files +OBJECTS = $(CFILES:.c=$(OBJ_SUFFIX)) $(CCFILES:.cpp=$(OBJ_SUFFIX)) \ + $(LFILES:.lex=$(OBJ_SUFFIX)) +RSCOBJECTS = $(RSCFILES:.rc=$(RES_SUFFIX)) +# targets to build during LIBS phase +LIB_TARGETS_IMPLIB = +LIB_TARGETS_ARLIB = # $(LIB_PREFIX)ResourceTest$(ARLIB_SUFFIX) +LIB_TARGETS_EXP = $(LIB_TARGETS_IMPLIB:$(ARLIB_SUFFIX)=$(EXP_SUFFIX)) +LIB_TARGETS_MISC = +# targets to build during CMDS phase +CMD_TARGETS_SHLIB = +CMD_TARGETS_EXE = $(EXECUTABLE) +CMD_TARGETS_MISC = +# files to remove during clean phase +CLEAN_TARGETS_MISC = +CLEAN_TARGETS = $(OBJECTS) $(RSCOBJECTS) $(IDL_TARGETS) $(CLEAN_TARGETS_MISC) +# other files to remove during clobber phase +CLOBBER_TARGETS_MISC= +# sub-directory to install to within bin +BIN_SUBDIR = +# sub-directory to install to within include +INCLUDE_SUBDIR = + +# Additional Settings +#CLOCALDEBUG = User defined C debugging compilation flags [Empty] +#CCLOCALDEBUG = User defined C++ debugging compilation flags [Empty] +#CLOCAL = User defined C flags for compiling [Empty] +#CCLOCAL = User defined C++ flags for compiling [Empty] +#BSCLOCAL = User flags for Browse File Builder [Empty] +#DEPENDLOCAL = user defined makedepend flags [Empty] +#LINTLOCAL = User defined lint flags [Empty] +#LOCAL_INCLUDE_DIRS = User include directories to search for C/C++ headers [Empty] +#LDLOCAL = User defined C flags for linking [Empty] +#IMPLIBLOCAL = User flags for Object Lirary Manager [Empty] +#MIDLLOCAL = User flags for IDL compiler [Empty] +#RSCLOCAL = User flags for resource compiler [Empty] +#LOCALDEPLIBS = User libraries to include in dependencies [Empty] +#LOCALLIBS = User libraries to use when linking [Empty] +# (in addition to LOCALDEPLIBS) +#LOCAL_LIB_DIRS = User library directories for libpaths [Empty] + +CLOCAL = $(CPIE) +LOCALDEPLIBS=$(IBACCESS_USER_LIBS) opaswcommon opamgt-priv +LOCAL_INCLUDE_DIRS= +LOCALLIBS=$(OPENIB_USER_LIBS) crypto +LOCAL_LIB_DIRS=$(OPENIB_USER_LIB_DIRS) $(IBACCESS_USER_LIB_DIRS) + +# Include Make Rules definitions and rules +include $(TL_DIR)/IbaTools/Makerules.module + +#=============================================================================# +# Overrides: +#-----------------------------------------------------------------------------# +#CCOPT = # C++ optimization flags, default lets build config decide +#COPT = # C optimization flags, default lets build config decide +#SUBSYSTEM = Subsystem to build for (none, console or windows) [none] +# (Windows Only) +#USEMFC = How Windows MFC should be used (none, static, shared, no_mfc) [none] +# (Windows Only) +#=============================================================================# + +#=============================================================================# +# Rules: +#-----------------------------------------------------------------------------# +# process Sub-directories +include $(TL_DIR)/Makerules/Maketargets.toplevel + +# build cmds and libs +include $(TL_DIR)/Makerules/Maketargets.build + +# install for includes, libs and cmds phases +include $(TL_DIR)/Makerules/Maketargets.install + +# install for stage phase +include $(TL_DIR)/Makerules/Maketargets.stage +STAGE:: + #$(VS)$(STAGE_INSTALL) $(STAGE_INSTALL_DIR_OPT) $(PROJ_STAGE_FASTFABRIC_DIR) $(EXECUTABLE) + $(VS)$(STAGE_INSTALL) $(STAGE_INSTALL_DIR_OPT) $(PROJ_STAGE_BIN_DIR) $(EXECUTABLE) + +# Unit test execution +#include $(TL_DIR)/Makerules/Maketargets.runtest + +#=============================================================================# + +#=============================================================================# +# DO NOT DELETE THIS LINE -- make depend depends on it. +#=============================================================================# diff --git a/IbaTools/opasw/opaswreset/opaswreset.c b/IbaTools/opasw/opaswreset/opaswreset.c new file mode 100644 index 0000000..ecbbaeb --- /dev/null +++ b/IbaTools/opasw/opaswreset/opaswreset.c @@ -0,0 +1,257 @@ +/* BEGIN_ICS_COPYRIGHT7 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT7 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +#include +#include +#include +#include +#include + +/* work around conflicting names */ + +#include "iba/ib_types.h" +#include "iba/ib_sm_priv.h" +#include "iba/ib_helper.h" +#include "opamgt_sa_priv.h" +#include +#include "opaswcommon.h" + +#define RESET_DELAY 2000 + +// globals + +int g_debugMode = 0; +int g_verbose = 0; +int g_quiet = 0; +int g_gotHfi = 0; +int g_gotPort = 0; +int g_gotDelay = 0; + +#define LIST_FILE_SUPPORTED 0 + +static void usage(char *app_name) +{ + fprintf(stderr, "usage: %s -t target ", app_name); +#if LIST_FILE_SUPPORTED + fprintf(stderr, "[-l list_file] "); +#endif + fprintf(stderr, "[-v|-q] [-h hfi] [-o port] [-i delay-interval]"); + fprintf(stderr, "\n"); + fprintf(stderr, " -t - target to reset\n"); +#if LIST_FILE_SUPPORTED + fprintf(stderr, " -l - file that holds a list of targets to reset\n"); +#endif + fprintf(stderr, " -v - verbose output\n"); + fprintf(stderr, " -q - no output\n"); + fprintf(stderr, " -h - hfi, numbered 1..n, 0= -o port will be a\n"); + fprintf(stderr, " system wide port num (default is 0)\n"); + fprintf(stderr, " -o - port, numbered 1..n, 0=1st active (default\n"); + fprintf(stderr, " is 1st active)\n"); + fprintf(stderr, " -i - delay interval in seconds before switch reset (must be in range 1-1800)\n"); + fprintf(stderr, "\n"); + fprintf(stderr, "The -h and -o options permit a variety of selections:\n"); + fprintf(stderr, " -h 0 - 1st active port in system (this is the default)\n"); + fprintf(stderr, " -h 0 -o 0 - 1st active port in system\n"); + fprintf(stderr, " -h x - 1st active port on HFI x\n"); + fprintf(stderr, " -h x -o 0 - 1st active port on HFI x\n"); + fprintf(stderr, " -h 0 -o y - port y within system (irrespective of which ports are active)\n"); + fprintf(stderr, " -h x -o y - HFI x, port y\n"); + + exit(2); +} + +int main(int argc, char *argv[]) +{ + char *cmdName; + const char *opts="Dvqt:l:h:o:i:"; + char parameter[100]; + char *p; + EUI64 destPortGuid = -1; + int c; + uint8 hfi = 0; + uint8 port = 0; + uint32 delay = RESET_DELAY; + IB_PATH_RECORD path; + uint16 sessionID = 0; + VENDOR_MAD mad; + FSTATUS status = FSUCCESS; + struct omgt_port *omgt_port_session = NULL; + + // determine how we've been invoked + cmdName = strrchr(argv[0], '/'); // Find last '/' in path + if (cmdName != NULL) { + cmdName++; // Skip over last '/' + } else { + cmdName = argv[0]; + } + + // Initialize + + + // parse options and parameters + while (-1 != (c = getopt(argc, argv, opts))) { + switch (c) { + case 'D': + g_debugMode = 1; + break; + + case 't': + errno = 0; + strncpy(parameter, optarg, sizeof(parameter)-1); + parameter[sizeof(parameter)-1] = 0; + if ((p = strchr(parameter, ',')) != NULL) { + *p = '\0'; + } + if (FSUCCESS != StringToUint64(&destPortGuid, parameter, NULL, 0, TRUE)) { + fprintf(stderr, "%s: Error: Invalid GUID: %s\n", cmdName, optarg); + usage(cmdName); + } + break; + + case 'l': +#if !LIST_FILE_SUPPORTED + fprintf(stderr, "Error: l option is not supported at this time\n"); + exit(1); +#endif + break; + + case 'v': + g_verbose = 1; + break; + + case 'q': + g_quiet = 1; + break; + + case 'h': + if (FSUCCESS != StringToUint8(&hfi, optarg, NULL, 0, TRUE)) { + fprintf(stderr, "%s: Error: Invalid HFI Number: %s\n", cmdName, optarg); + usage(cmdName); + } + g_gotHfi = 1; + break; + + case 'o': + if (FSUCCESS != StringToUint8(&port, optarg, NULL, 0, TRUE)) { + fprintf(stderr, "%s: Error: Invalid Port Number: %s\n", cmdName, optarg); + usage(cmdName); + } + g_gotPort = 1; + break; + + case 'i': + if (FSUCCESS != StringToUint32(&delay, optarg, NULL, 0, TRUE)) { + fprintf(stderr, "%s: Error: Invalid Delay Value: %s\n", cmdName, optarg); + usage(cmdName); + } + g_gotDelay = 1; + break; + + default: + usage(cmdName); + break; + + } + } + + // user has requested display of help + if (argc == 1) { + usage(cmdName); + exit(0); + } + + if (-1 == destPortGuid) { + fprintf(stderr, "%s: Error: Must specify a target GUID\n", cmdName); + exit(1); + } + + if (g_quiet && (g_debugMode || g_verbose)) { + fprintf(stderr, "%s: Error: Can not specify both -q and -D|-v\n", cmdName); + exit(1); + } + + if (g_gotDelay) { + if ((delay < 1) || (delay > 1800)) { + fprintf(stderr, "%s: Error: Invalid delay value %d, must be in range 1-1800\n", cmdName, delay); + exit(1); + } else + delay *= 1000; /* convert to milliseconds */ + } + + // Get the path + + struct omgt_params params = {.debug_file = (g_verbose || g_debugMode) ? stderr : NULL}; + status = omgt_open_port_by_num(&omgt_port_session, hfi, port, ¶ms); + if (status != 0) { + fprintf(stderr, "%s: Error: Unable to open fabric interface.\n", cmdName); + exit(1); + } + + if (getDestPath(omgt_port_session, destPortGuid, cmdName, &path) != FSUCCESS) { + fprintf(stderr, "%s: Error: Failed to get destination path\n", cmdName); + status = FERROR; + goto err_exit; + } + + // Send a ClassPortInfo to see if the switch is responding + + status = sendClassPortInfoMad(omgt_port_session, &path, &mad); + if (status != FSUCCESS) { + fprintf(stderr, "%s: Error: Failed to send/rcv ClassPortInfo\n", cmdName); + goto err_exit; + } + + // Get a session ID + + sessionID = getSessionID(omgt_port_session, &path); + if (sessionID == (uint16)-1) { + fprintf(stderr, "%s: Error: Failed to obtain sessionID\n", cmdName); + status = FERROR; + goto err_exit; + } + + // Send a reboot MAD to the LID + + status = sendRebootMad(omgt_port_session, &path, sessionID, &mad, delay); + if (status != FSUCCESS) { + if (sessionID>0) releaseSession(omgt_port_session, &path, sessionID); + } + printf("opaswreset completed\n"); + +err_exit: + omgt_close_port(omgt_port_session); + + if (status == FSUCCESS) + exit(0); + else + exit(1); + +} diff --git a/IbaTools/opasw/opaswtest/Makefile b/IbaTools/opasw/opaswtest/Makefile new file mode 100644 index 0000000..0eef4c4 --- /dev/null +++ b/IbaTools/opasw/opaswtest/Makefile @@ -0,0 +1,159 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** +# Makefile for opaswtest + +# Include Make Control Settings +include $(TL_DIR)/$(PROJ_FILE_DIR)/Makesettings.project + +#=============================================================================# +# Definitions: +#-----------------------------------------------------------------------------# + +# Name of SubProjects +DS_SUBPROJECTS = +# name of executable or downloadable image +EXECUTABLE = $(BUILDDIR)/opaswtest$(EXE_SUFFIX) +# list of sub directories to build +DIRS = +# C files (.c) +CFILES = \ + opaswtest.c \ + # Add more c files here +# C++ files (.cpp) +CCFILES = \ + # Add more cpp files here +# lex files (.lex) +LFILES = \ + # Add more lex files here +# archive library files (basename, $ARFILES will add MOD_LIB_DIR/prefix and suffix) +LIBFILES= +# Windows Resource Files (.rc) +RSCFILES = +# Windows IDL File (.idl) +IDLFILE = +# Windows Linker Module Definitions (.def) file for dll's +DEFFILE = +# targets to build during INCLUDES phase (add public includes here) +INCLUDE_TARGETS = \ + # Add more h hpp files here +# Non-compiled files + # Add more files here +MISC_FILES = +# all source files +SOURCES = $(CFILES) $(CCFILES) $(LFILES) $(RSCFILES) $(IDLFILE) +# Source files to include in DSP File +DSP_SOURCES = $(INCLUDE_TARGETS) $(SOURCES) $(MISC_FILES) \ + $(RSCFILES) $(DEFFILE) $(MAKEFILE) +# all object files +OBJECTS = $(CFILES:.c=$(OBJ_SUFFIX)) $(CCFILES:.cpp=$(OBJ_SUFFIX)) \ + $(LFILES:.lex=$(OBJ_SUFFIX)) +RSCOBJECTS = $(RSCFILES:.rc=$(RES_SUFFIX)) +# targets to build during LIBS phase +LIB_TARGETS_IMPLIB = +LIB_TARGETS_ARLIB = # $(LIB_PREFIX)ResourceTest$(ARLIB_SUFFIX) +LIB_TARGETS_EXP = $(LIB_TARGETS_IMPLIB:$(ARLIB_SUFFIX)=$(EXP_SUFFIX)) +LIB_TARGETS_MISC = +# targets to build during CMDS phase +CMD_TARGETS_SHLIB = +CMD_TARGETS_EXE = $(EXECUTABLE) +CMD_TARGETS_MISC = +# files to remove during clean phase +CLEAN_TARGETS_MISC = +CLEAN_TARGETS = $(OBJECTS) $(RSCOBJECTS) $(IDL_TARGETS) $(CLEAN_TARGETS_MISC) +# other files to remove during clobber phase +CLOBBER_TARGETS_MISC= +# sub-directory to install to within bin +BIN_SUBDIR = +# sub-directory to install to within include +INCLUDE_SUBDIR = + +# Additional Settings +#CLOCALDEBUG = User defined C debugging compilation flags [Empty] +#CCLOCALDEBUG = User defined C++ debugging compilation flags [Empty] +#CLOCAL = User defined C flags for compiling [Empty] +#CCLOCAL = User defined C++ flags for compiling [Empty] +#BSCLOCAL = User flags for Browse File Builder [Empty] +#DEPENDLOCAL = user defined makedepend flags [Empty] +#LINTLOCAL = User defined lint flags [Empty] +#LOCAL_INCLUDE_DIRS = User include directories to search for C/C++ headers [Empty] +#LDLOCAL = User defined C flags for linking [Empty] +#IMPLIBLOCAL = User flags for Object Lirary Manager [Empty] +#MIDLLOCAL = User flags for IDL compiler [Empty] +#RSCLOCAL = User flags for resource compiler [Empty] +#LOCALDEPLIBS = User libraries to include in dependencies [Empty] +#LOCALLIBS = User libraries to use when linking [Empty] +# (in addition to LOCALDEPLIBS) +#LOCAL_LIB_DIRS = User library directories for libpaths [Empty] + +CLOCAL = $(CPIE) +LOCALDEPLIBS=$(IBACCESS_USER_LIBS) opaswcommon opamgt-priv +LOCAL_INCLUDE_DIRS= +LOCALLIBS=$(OPENIB_USER_LIBS) crypto +LOCAL_LIB_DIRS=$(OPENIB_USER_LIB_DIRS) $(IBACCESS_USER_LIB_DIRS) + +# Include Make Rules definitions and rules +include $(TL_DIR)/IbaTools/Makerules.module + +#=============================================================================# +# Overrides: +#-----------------------------------------------------------------------------# +#CCOPT = # C++ optimization flags, default lets build config decide +#COPT = # C optimization flags, default lets build config decide +#SUBSYSTEM = Subsystem to build for (none, console or windows) [none] +# (Windows Only) +#USEMFC = How Windows MFC should be used (none, static, shared, no_mfc) [none] +# (Windows Only) +#=============================================================================# + +#=============================================================================# +# Rules: +#-----------------------------------------------------------------------------# +# process Sub-directories +include $(TL_DIR)/Makerules/Maketargets.toplevel + +# build cmds and libs +include $(TL_DIR)/Makerules/Maketargets.build + +# install for includes, libs and cmds phases +include $(TL_DIR)/Makerules/Maketargets.install + +# install for stage phase +include $(TL_DIR)/Makerules/Maketargets.stage +STAGE:: + #$(VS)$(STAGE_INSTALL) $(STAGE_INSTALL_DIR_OPT) $(PROJ_STAGE_FASTFABRIC_DIR) $(EXECUTABLE) + $(VS)$(STAGE_INSTALL) $(STAGE_INSTALL_DIR_OPT) $(PROJ_STAGE_BIN_DIR) $(EXECUTABLE) + +# Unit test execution +#include $(TL_DIR)/Makerules/Maketargets.runtest + +#=============================================================================# + +#=============================================================================# +# DO NOT DELETE THIS LINE -- make depend depends on it. +#=============================================================================# diff --git a/IbaTools/opasw/opaswtest/opaswtest.c b/IbaTools/opasw/opaswtest/opaswtest.c new file mode 100644 index 0000000..f07cc34 --- /dev/null +++ b/IbaTools/opasw/opaswtest/opaswtest.c @@ -0,0 +1,1077 @@ +/* BEGIN_ICS_COPYRIGHT7 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT7 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +#include +#include +#include +#include +#include + +/* work around conflicting names */ + +#include "iba/ib_types.h" +#include "iba/ib_sm_priv.h" +#include "iba/ib_helper.h" +#include "opamgt_sa_priv.h" +#include +#include "opaswcommon.h" +#include "opaswmetadata.h" + +// globals + +int g_debugMode = 0; +int g_verbose = 0; +int g_quiet = 0; +int g_gotHfi = 0; +int g_gotPort = 0; +uint8 g_testNum = 0; +int g_promptForPassword = 0; + +#define EEPROMSIZE (64 * 1024) + +#define LIST_FILE_SUPPORTED 0 + +static void usage(char *app_name) +{ + fprintf(stderr, "usage: %s -t target ", app_name); +#if LIST_FILE_SUPPORTED + fprintf(stderr, "[-l list_file] "); +#endif + fprintf(stderr, "[-v|-q] [-h hfi] [-o port] -r testnum"); + fprintf(stderr, " [-K] [-w password]"); + fprintf(stderr, "\n"); + fprintf(stderr, " -t - target to test\n"); +#if LIST_FILE_SUPPORTED + fprintf(stderr, " -l - file that holds a list of targets to test\n"); +#endif + fprintf(stderr, " -v - verbose output\n"); + fprintf(stderr, " -q - no output\n"); + fprintf(stderr, " -h - hfi, numbered 1..n, 0= -o port will be a\n"); + fprintf(stderr, " system wide port num (default is 0)\n"); + fprintf(stderr, " -o - port, numbered 1..n, 0=1st active (default\n"); + fprintf(stderr, " is 1st active)\n"); + fprintf(stderr, " -r - test number to run\n"); + fprintf(stderr, " 1 - simple sys table access\n"); + fprintf(stderr, " 2 - fw version\n"); + fprintf(stderr, " 3 - ini descriptors, sys table\n"); + fprintf(stderr, " 4 - address access (prompt)(disabled)\n"); + fprintf(stderr, " 5 - module type\n"); + fprintf(stderr, " 6 - reg 0x6f - which eeprom switch booted from\n"); + fprintf(stderr, " 7 - port table access\n"); + fprintf(stderr, " 8 - port table access - all ports\n"); + fprintf(stderr, " 9 - VPD access\n"); + fprintf(stderr, " 10 - save config\n"); + fprintf(stderr, " 11 - fan status\n"); + fprintf(stderr, " 12 - power supply status\n"); + fprintf(stderr, " 13 - set MTU size to 4K\n"); + fprintf(stderr, " 14 - bus walk\n"); + fprintf(stderr, " 15 - address 0x1040 - v0 or v1\n"); + fprintf(stderr, " 16 - explore EEPROM trailer & config\n"); + fprintf(stderr, " 17 - get board id\n"); + fprintf(stderr, " 18 - dump primary FW EEPROMs\n"); + fprintf(stderr, " 19 - probe mgmt fpga on EDF\n"); + fprintf(stderr, " 20 - asic rev\n"); + fprintf(stderr, " 21 - VMA I2C read using arbitrary Location, length, and offset\n"); + fprintf(stderr, " 22 - VMA I2C write using arbitrary Location, offset, and data bytes\n"); + fprintf(stderr, " -K - enforce password based security for all operations - prompts for password\n"); + fprintf(stderr, " -w - enforce password based security for all operations - password on command line\n"); + fprintf(stderr, "\n"); + fprintf(stderr, "The -h and -o options permit a variety of selections:\n"); + fprintf(stderr, " -h 0 - 1st active port in system (this is the default)\n"); + fprintf(stderr, " -h 0 -o 0 - 1st active port in system\n"); + fprintf(stderr, " -h x - 1st active port on HFI x\n"); + fprintf(stderr, " -h x -o 0 - 1st active port on HFI x\n"); + fprintf(stderr, " -h 0 -o y - port y within system (irrespective of which ports are active)\n"); + fprintf(stderr, " -h x -o y - HFI x, port y\n"); + + exit(2); +} + +int main(int argc, char *argv[]) +{ + char *cmdName; + char *opts="DvqKt:l:h:o:w:r:"; + char parameter[100]; + char buf[20]; + char *pp; + EUI64 destPortGuid = -1; + int c; + uint32 moduleType; + uint32 numPorts; + uint8 hfi = 0; + uint8 port = 0; + IB_PATH_RECORD path; + uint16 sessionID = 0; + uint8 sysTableIndex; + uint8 dataLen; + uint8 sysTableData[200]; + uint8 memoryData[200]; + uint8 fwVersion[40]; + uint8 *p; + int i; + uint32 location; +#if 0 + uint32 tableIdx; + table_meta_data_t *tp; +#endif + opasw_ini_descriptor_get_t tableDescriptors; + table_parsed_data_t *sysParsedDataTable; + table_parsed_data_t *portParsedDataTable; + table_parsed_data_t **portPtrs; + uint32 portEntrySize; + uint32 regValue; + VENDOR_MAD mad; + FSTATUS status = FSUCCESS; + uint32 portNumMetaIndex; + uint32 portSpeedMetaIndex; + uint32 portMTUMetaIndex; + uint32 portVLCAPMetaIndex; + uint32 portLinkWidthMetaIndex; + uint32 portLinkSpeedMetaIndex; + uint8 vpdBuffer[300]; + uint8 *v = vpdBuffer; + uint32 vpdOffset = 0; + uint32 vpdReadSize; + uint32 vpdBytesRead = 0; +#if 0 + uint32 vpdAddress; +#endif + vpd_fruInfo_rec_t fruInfo; + uint8 *dp; + int len; + uint8 statusBuffer[64]; + uint32 mtuCap; + uint32 vlCap; + uint16 asicVal; + uint32 asicVal2; + uint16 dataOffset; + uint32 dataSize; + uint16 readLen; + uint16 bytesRecd; + uint8 dataBuffer[EEPROMSIZE]; + uint8 bigDataBuffer[4 * EEPROMSIZE]; + uint8 *data; + uint16 boardID; + struct omgt_port *omgt_port_session = NULL; + FILE *fp; + char dumpFileName[64]; + + // determine how we've been invoked + cmdName = strrchr(argv[0], '/'); // Find last '/' in path + if (cmdName != NULL) { + cmdName++; // Skip over last '/' + } else { + cmdName = argv[0]; + } + + // Initialize + + + // parse options and parameters + while (-1 != (c = getopt(argc, argv, opts))) { + switch (c) { + case 'D': + g_debugMode = 1; + break; + + case 't': + errno = 0; + strncpy(parameter, optarg, sizeof(parameter)-1); + if ((pp = strchr(parameter, ',')) != NULL) { + *pp = '\0'; + } + if (FSUCCESS != StringToUint64(&destPortGuid, parameter, NULL, 0, TRUE)) { + fprintf(stderr, "%s: Error: Invalid GUID: %s\n", cmdName, optarg); + usage(cmdName); + } + break; + + case 'l': +#if !LIST_FILE_SUPPORTED + fprintf(stderr, "Error: l option is not supported at this time\n"); + exit(1); +#endif + break; + + case 'v': + g_verbose = 1; + break; + + case 'q': + g_quiet = 1; + break; + + case 'h': + if (FSUCCESS != StringToUint8(&hfi, optarg, NULL, 0, TRUE)) { + fprintf(stderr, "%s: Error: Invalid HFI Number: %s\n", cmdName, optarg); + usage(cmdName); + } + g_gotHfi = 1; + break; + + case 'o': + if (FSUCCESS != StringToUint8(&port, optarg, NULL, 0, TRUE)) { + fprintf(stderr, "%s: Error: Invalid Port Number: %s\n", cmdName, optarg); + usage(cmdName); + } + g_gotPort = 1; + break; + + case 'r': + if (FSUCCESS != StringToUint8(&g_testNum, optarg, NULL, 0, TRUE)) { + fprintf(stderr, "%s: Error: Invalid Port Number: %s\n", cmdName, optarg); + usage(cmdName); + } + break; + + case 'K': + g_promptForPassword = 1; + break; + + case 'w': + fprintf(stderr, "Error: w option is not supported at this time\n"); + exit(1); + break; + + default: + usage(cmdName); + break; + + } + } + + // user has requested display of help + if (argc == 1) { + usage(cmdName); + exit(0); + } + + if (-1 == destPortGuid) { + fprintf(stderr, "%s: Error: Must specify a target GUID\n", cmdName); + exit(1); + } + + if (g_testNum == 0) { + fprintf(stderr, "%s: Error: must enter a test number\n", cmdName); + exit(1); + } + + if (g_quiet && (g_debugMode || g_verbose)) { + fprintf(stderr, "%s: Error: Can not specify both -q and -D|-v\n", cmdName); + exit(1); + } + +#if 0 +#if SECURITY_SUPPORTED + if (g_promptForPassword) { + c = vkey_prompt_user(vendorKey, 0); + if (c) { + printf("vendor key is : "); + for (c = 0; c < sizeof(vendorKey); c++) + printf("%02x ", vendorKey[c]); + printf("\n"); + } + else + fprintf(stderr, "vkey_prompt_user failed\n"); + } +#endif +#endif + +#if 0 + if (g_promptForPassword) { + c = vkey_prompt_user(vendorKey, 0); + if (c) { + if (g_verbose) { + printf("vendor key is : "); + for (c = 0; c < sizeof(vendorKey); c++) + printf("%02x ", vendorKey[c]); + printf("\n"); + } + } + else { + fprintf(stderr, "%s: Error generating vendor key\n", cmdName); + exit(1); + } + } else + memset(vendorKey, 0, MAX_VENDOR_KEY_LEN); +#endif + + // Get the LID + + struct omgt_params params = {.debug_file = (g_verbose || g_debugMode) ? stderr : NULL}; + status = omgt_open_port_by_num(&omgt_port_session, hfi, port, ¶ms); + if (status != 0) { + fprintf(stderr, "%s: Error: Unable to open fabric interface.\n", cmdName); + exit(1); + } + + if (getDestPath(omgt_port_session, destPortGuid, cmdName, &path) != FSUCCESS) { + fprintf(stderr, "%s: Error finding destination path\n", cmdName); + status = FERROR; + goto err_exit; + } + + // Send a ClassPortInfo to see if the switch is responding + + status = sendClassPortInfoMad(omgt_port_session, &path, &mad); + if (status != FSUCCESS) { + fprintf(stderr, "%s: Error: Failed to send/rcv ClassPortInfo\n", cmdName); + goto err_exit; + } + + // Get a session ID + + sessionID = getSessionID(omgt_port_session, &path); + if (sessionID == (uint16)-1) { + fprintf(stderr, "%s: Error: Failed to obtain sessionID\n", cmdName); + status = FERROR; + goto err_exit; + } + + // Send the test mad + + switch (g_testNum) { + case 1: +#if GET + sysTableIndex = 10; +#else + sysTableIndex = 1; +#endif + dataLen = 2; + sysTableData[0] = 'A'; + status = sendSysTableAccessGetMad(omgt_port_session, &path, &mad, sessionID, sysTableIndex, dataLen, sysTableData); + if (status != FSUCCESS) { + fprintf(stderr, "%s: Error: Failed to access Sys table data - status %d\n", cmdName, status); + if (sessionID>0) releaseSession(omgt_port_session, &path, sessionID); + goto err_exit; + } + break; + + case 2: + status = getFwVersion(omgt_port_session, &path, &mad, sessionID, fwVersion); +#if 0 + printf("fw version is %s\n", fwVersion); + opaswDisplayBuffer((char *)fwVersion, FWVERSION_SIZE); +#endif + printf("FW Version is %s\n", fwVersion); + break; + + case 3: + status = sendIniDescriptorGetMad(omgt_port_session, &path, &mad, sessionID, &tableDescriptors); + if (status != FSUCCESS) { + fprintf(stderr, "%s: Error: Failed to get ini descriptors - status %d\n", cmdName, status); + if (sessionID>0) releaseSession(omgt_port_session, &path, sessionID); + goto err_exit; + } + printf("Sys Meta Data : addr 0x%08x len %d\n", tableDescriptors.sysMetaDataAddr, tableDescriptors.sysMetaDataLen); + printf("Sys Data : addr 0x%08x len %d\n", tableDescriptors.sysDataAddr, tableDescriptors.sysDataLen); + printf("Port Meta Data : addr 0x%08x len %d\n", tableDescriptors.portMetaDataAddr, tableDescriptors.portMetaDataLen); + printf("Port Data : addr 0x%08x len %d\n", tableDescriptors.portDataAddr, tableDescriptors.portDataLen); + + printf("parsing sys data:\n"); + sysParsedDataTable = malloc(tableDescriptors.sysDataLen * sizeof(table_parsed_data_t)); +#if 0 + status = sendMemAccessGetMad(&path, &mad, sessionID, tableDescriptors.sysDataAddr, (uint8)200, memoryData); +#else + status = sendMemAccessGetMad(omgt_port_session, &path, &mad, sessionID, tableDescriptors.sysDataAddr, (uint8)(tableDescriptors.sysDataLen * 4) + 8, memoryData); +#endif + status = parseDataTable(&systemMetaData[0], memoryData, systemMetaDataSize, &sysParsedDataTable[0], 1); + break; + + case 4: +#if 0 + // prompt for location + printf("Enter location in hex: "); + scanf("%x", &location); + printf("Querying location 0x%x\n", location); + status = sendMemAccessGetMad(&path, &mad, sessionID, location, (uint8)200, memoryData); + + for (tp = &systemMetaData[0], i = 0; i <= SYSMETATABLESIZE; tp++, i++) { + int j, len; + p = &memoryData[(tp->start)/8]; + printf("%s: ", tp->field); + len = (tp->length)/8 ? (tp->length)/8 : 1; + for (j = 0; j < len; j++) { + printf("0x%02x ", *(p + j) & 0xff); + } + printf("\n"); + } +#else + fprintf(stderr, "Test 4 disabled\n"); +#endif + break; + +#if 0 + case 5: + moduleType = getModuleType(omgt_port_session, &path, sessionID); + switch(moduleType) { + case ENC_MOD_TYPE_OPASW: + printf("module type of dlid %d is OPASW\n", path.DLID); + break; + + case ENC_MOD_TYPE_VIPER: + printf("module type of dlid %d is VIPER\n", path.DLID); + break; + + default: + printf("module type of dlid %d is unsupported\n", path.DLID); + break; + + } + break; +#endif + +#define EEPROM_MASK 0x100 + case 6: + status = sendRegisterAccessMad(omgt_port_session, &path, &mad, sessionID, + (uint8)0x6f, ®Value, 1); + printf("Reg value is 0x%08x\n", regValue); + printf("Switch has booted from %s EEPROM\n", (regValue & EEPROM_MASK) ? "secondary" : "primary"); + break; + + case 7: + status = sendIniDescriptorGetMad(omgt_port_session, &path, &mad, sessionID, &tableDescriptors); + if (status != FSUCCESS) { + fprintf(stderr, "%s: Error: Failed to get ini descriptors - status %d\n", cmdName, status); + if (sessionID>0) releaseSession(omgt_port_session, &path, sessionID); + goto err_exit; + } + printf("Sys Meta Data : addr 0x%08x len %d\n", tableDescriptors.sysMetaDataAddr, tableDescriptors.sysMetaDataLen); + printf("Sys Data : addr 0x%08x len %d\n", tableDescriptors.sysDataAddr, tableDescriptors.sysDataLen); + printf("Port Meta Data : addr 0x%08x len %d\n", tableDescriptors.portMetaDataAddr, tableDescriptors.portMetaDataLen); + printf("Port Data : addr 0x%08x len %d\n", tableDescriptors.portDataAddr, tableDescriptors.portDataLen); + numPorts = getNumPorts(omgt_port_session, &path, sessionID); + printf("numPorts is %d\n", numPorts); + +#if 0 + portEntrySize = (tableDescriptors.portDataLen * 4) / numPorts; +#else + portEntrySize = tableDescriptors.portDataLen / numPorts; +#endif + printf("portEntrySize is %d\n", (int)portEntrySize); + portPtrs = malloc(numPorts * sizeof(void *)); + for (i = 0; i < numPorts; i++) { + status = sendMemAccessGetMad(omgt_port_session, &path, &mad, sessionID, tableDescriptors.portDataAddr + (i * portEntrySize), portEntrySize*4, memoryData); + if (g_verbose) { + printf("MemoryData dump:\n"); + opaswDisplayBuffer((char *)memoryData, portEntrySize * 4); + } + printf("\n**** parsing port data for port %d:\n", i + 1); + portParsedDataTable = malloc(tableDescriptors.portDataLen * sizeof(table_parsed_data_t)); + status = parseDataTable(&portMetaData[0], memoryData, portMetaDataSize, &portParsedDataTable[0], 1); + portPtrs[i] = portParsedDataTable; + } + portNumMetaIndex = getMetaDataIndexByField(&portMetaData[0], tableDescriptors.portDataLen, "PHYS_PORT_NUMBER"); + portSpeedMetaIndex = getMetaDataIndexByField(&portMetaData[0], tableDescriptors.portDataLen, "LINK_SPEED_SUPPORTED"); + portMTUMetaIndex = getMetaDataIndexByField(&portMetaData[0], tableDescriptors.portDataLen, "MTU_CAP"); + portVLCAPMetaIndex = getMetaDataIndexByField(&portMetaData[0], tableDescriptors.portDataLen, "VL_CAP"); + portLinkWidthMetaIndex = getMetaDataIndexByField(&portMetaData[0], tableDescriptors.portDataLen, "LINK_WIDTH_SUPPORTED"); + portLinkSpeedMetaIndex = getMetaDataIndexByField(&portMetaData[0], tableDescriptors.portDataLen, "LINK_SPEED_SUPPORTED"); + for (i = 0; i < numPorts; i++) { + printf("Port %d: \n", i+1); + printf(" physical port %d\n", portPtrs[i][portNumMetaIndex].val.intVal); + printf(" port speed %d\n", portPtrs[i][portSpeedMetaIndex].val.intVal); + printf(" port mtu cap %d\n", portPtrs[i][portMTUMetaIndex].val.intVal); + printf(" port vl cap %d\n", portPtrs[i][portVLCAPMetaIndex].val.intVal); + printf(" port lk wid %d\n", portPtrs[i][portLinkWidthMetaIndex].val.intVal); + printf(" port lk spd %d\n", portPtrs[i][portLinkSpeedMetaIndex].val.intVal); + } + break; + + case 8: + status = sendIniDescriptorGetMad(omgt_port_session, &path, &mad, sessionID, &tableDescriptors); + if (status != FSUCCESS) { + fprintf(stderr, "%s: Error: Failed to get ini descriptors - status %d\n", cmdName, status); + if (sessionID>0) releaseSession(omgt_port_session, &path, sessionID); + goto err_exit; + } + numPorts = getNumPorts(omgt_port_session, &path, sessionID); + printf("numPorts is %d\n", numPorts); + + status = sendMemAccessGetMad(omgt_port_session, &path, &mad, sessionID, tableDescriptors.portDataAddr, tableDescriptors.portDataLen * 4, memoryData); + if (g_verbose) { + printf("MemoryData dump:\n"); + opaswDisplayBuffer((char *)memoryData, tableDescriptors.portDataLen * 4); + } + p = memoryData; + portPtrs = malloc(numPorts * sizeof(void *)); + + for (i = 0; i < numPorts; i++) { + portParsedDataTable = malloc(tableDescriptors.portDataLen * sizeof(table_parsed_data_t)); + status = parseDataTable(&portMetaData[0], p, portMetaDataSize, &portParsedDataTable[0], 0); + p += tableDescriptors.portDataLen / numPorts * 4; + portPtrs[i] = portParsedDataTable; + } + portNumMetaIndex = getMetaDataIndexByField(&portMetaData[0], tableDescriptors.portDataLen, "PHYS_PORT_NUMBER"); + for (i = 0; i < numPorts; i++) { + printf("Port %d: physical port %d\n", i+1, portPtrs[i][portNumMetaIndex].val.intVal); + } + break; + + case 9: +#if 1 +#define VPDREADSIZE 60 +#define VPDEEPROMLOCATION 0x8160AA00 + status = FSUCCESS; + while ((status == FSUCCESS) && (vpdBytesRead < 256)) { + if ((256 - vpdBytesRead) < VPDREADSIZE) { + vpdReadSize = 256 - vpdBytesRead; + } else { + vpdReadSize = VPDREADSIZE; + } + printf("sending read access to 0x%08x for size %d offset %d\n", + VPDEEPROMLOCATION, vpdReadSize, vpdOffset); + status = sendI2CAccessMad(omgt_port_session, &path, sessionID, &mad, + NOJUMBOMAD, MMTHD_GET, 10000, VPDEEPROMLOCATION, vpdReadSize, + vpdOffset, v); + if (status == FSUCCESS) { + v += vpdReadSize; + vpdBytesRead += vpdReadSize; + vpdOffset += vpdReadSize; + } else { + fprintf(stderr, "%s: Error sending MAD packet to switch\n", cmdName); + } + } + if (status == FSUCCESS) { + printf("vpd buffer:\n"); + opaswDisplayBuffer((char *)vpdBuffer, 256); + } + memset(&fruInfo, 0, sizeof(fruInfo)); +#if 0 + dp = vpdBuffer + FRU_OFFSET; +#else + dp = vpdBuffer; + dp += DEVICE_HDR_SIZE; + // Walk xinfo records until fruInfo record is found + while (*dp != FRUINFO_TYPE) + { + len = *(dp + 2); + dp += len; + } +#endif + // Advance to FRU GUID + dp += (RECORD_HDR_SIZE + FRU_TYPE_SIZE + FRU_HANDLE_SIZE); + // advance past length (for appropriate guid type) plus one (for type code itself) + switch (*dp) + { + case 0: + dp++; + break; + case 1: + dp += (8 + 1); + break; + case 2: + dp += (6 + 1); + break; + case 3: + dp += (16 + 1); + break; + case 4: + dp += (8 + 1); + break; + default: + fprintf(stderr, "invalid GUID type %d\n", *dp); + break; + } + + // copy serial number + len = *dp & LEN_MASK; + memcpy(&fruInfo.serialNum, dp + 1, len); + fruInfo.serialNum[len] = '\0'; + dp += len + 1; + + // copy part number + len = *dp & LEN_MASK; + memcpy(&fruInfo.partNum, dp + 1, len); + fruInfo.partNum[len] = '\0'; + dp += len + 1; + + // Copy model + len = *dp & LEN_MASK; + memcpy(&fruInfo.model, dp + 1, len); + fruInfo.model[len] = '\0'; + dp += len + 1; + + // Copy version + len = *dp & LEN_MASK; + memcpy(&fruInfo.version, dp + 1, len); + fruInfo.version[len] = '\0'; + dp += len + 1; + + // Copy mfgName + len = *dp & LEN_MASK; + memcpy(&fruInfo.mfgName, dp + 1, len); + fruInfo.mfgName[len] = '\0'; + dp += len + 1; + + // Copy productName + len = *dp & LEN_MASK; + memcpy(&fruInfo.productName, dp + 1, len); + fruInfo.productName[len] = '\0'; + dp += len + 1; + + // Copy mfgID + switch (*dp) + { + case 0: + fruInfo.mfgID[0] = '\0'; + dp++; + break; + case 1: + case 2: + dp++; +#if 0 /* looks like mfgID is not least sig. byte first in the EEPROM, so copy in as is */ + for (i = 0; i < 3; i++) + fruInfo.mfgID[i] = *(dp + 2 - i); +#else + memcpy(&fruInfo.mfgID, dp, 3); +#endif + dp += 3; + break; + default: + fprintf(stderr, "invalid Manufacturer ID code %d\n", *dp); + break; + } + + // Parse Mfg Date/Time + if (*dp & 0x80 ){ + fruInfo.mfgYear = (*(dp + 3) << 2) + ((*(dp + 2) & 0xc0) >> 6); /* least sig byte 1st: bits 31-22 */ + fruInfo.mfgMonth = (*(dp + 2) & 0x3c) >> 2; /* least sig byte 1st: bits 21-18 */ + fruInfo.mfgDay = ((*(dp + 2) & 0x03) << 3) + ((*(dp + 1) & 0xe0) >> 5); /* least sig byte 1st: bits 17-13 */ + fruInfo.mfgHours = *(dp + 1) & 0x1f; /* least sig byte 1st: bits 12-8 */ + fruInfo.mfgMins = *dp & 0x3f; /* least sig byte 1st: bits 5-0 */ + } else { + fruInfo.mfgYear = 0; + fruInfo.mfgMonth = 0; + fruInfo.mfgDay = 0; + fruInfo.mfgHours = 0; + fruInfo.mfgMins = 0; + } + printf("VPD:\n"); + printf(" Serial Number: %s\n", fruInfo.serialNum); + printf(" Part Number : %s\n", fruInfo.partNum); + printf(" Model : %s\n", fruInfo.model); + printf(" Version : %s\n", fruInfo.version); + printf(" Mfg Name : %s\n", fruInfo.mfgName); + printf(" Product Name : %s\n", fruInfo.productName); + printf(" Mfg ID : %02x %02x %02x\n", fruInfo.mfgID[0] & 0xff, + fruInfo.mfgID[1] & 0xff, + fruInfo.mfgID[2] & 0xff); + printf(" Mfg Date : %d-%02d-%d\n", fruInfo.mfgMonth, fruInfo.mfgDay, fruInfo.mfgYear + 2000); + printf(" Mfg Time : %02d:%02d\n", fruInfo.mfgHours, fruInfo.mfgMins); +#else + for (c = 0; c < 1; c++) + { + for (i = 128; i < 256; i+=128) + { + vpdAddress = (c << 24) | (i << 16) | 0xC400; + status = sendI2CAccessMad(&path, sessionID, &mad, NOJUMBOMAD, MMTHD_GET, 10, vpdAddress, 60, 0, v); + if (status == FSUCCESS) { + fprintf(stderr, "%s: Success sending MAD packet to switch - addr 0x%08x\n", cmdName, vpdAddress); + printf("vpd buffer:\n"); + opaswDisplayBuffer((char *)vpdBuffer, 60); + } + else + fprintf(stderr, "%s: Error sending MAD packet to switch - addr 0x%08x\n", cmdName, vpdAddress); + } + } +#endif + break; + + case 10: + printf("Are you sure you want to send the save config mad?? "); + fgets(buf, 20, stdin); + if ((buf[0] == 'Y') || (buf[0] == 'y')) { + printf("sending save config mad\n"); + status = sendSaveConfigMad(omgt_port_session, &path, &mad, sessionID); + if (status != FSUCCESS) { + fprintf(stderr, "%s: Error: Failed to send/rcv SaveConfig MAD\n", cmdName); + status = FERROR; + } + } + break; + + case 11: +#if 0 +#define FT_PREFIX 0x8000 +#else +#define FT_PREFIX 0x8180 +#endif + +#if 1 +#define FT1LOCATION (FT_PREFIX << 16) | 0x96dd +#define FT2LOCATION (FT_PREFIX << 16) | 0x90de +#else +#define FT1LOCATION 0x000196dd +#define FT2LOCATION 0x000196de +#endif + printf("reading fan status: FT1 0x%08x FT2 0x%08x\n", FT1LOCATION, FT2LOCATION); + status = FSUCCESS; + status = sendI2CAccessMad(omgt_port_session, &path, sessionID, &mad, + NOJUMBOMAD, MMTHD_GET, 2000, FT1LOCATION, 4, 0, + statusBuffer); +#if 0 +sendI2CAccessMad(uint16 &path, uint16 sessionID, VENDOR_MAD *mad, uint8 jumbo, uint8 method, int timeout, uint32 locationDescriptor, uint16 dataLen, uint16 dataOffset, uint8 *data, +#endif + if (status == FSUCCESS) { + printf("Success reading 0x%08x - buffer:\n", FT1LOCATION); + opaswDisplayBuffer((char *)statusBuffer, 4); + printf("FAN Speed of FT1 = %d\n", statusBuffer[0] * 60); + } else { + fprintf(stderr, "%s: Error: Failed to send/rcv i2cAccess MAD\n", cmdName); + status = FERROR; + } + if (status == FSUCCESS) { + status = FSUCCESS; + status = sendI2CAccessMad(omgt_port_session, &path, sessionID, &mad, + NOJUMBOMAD, MMTHD_GET, 2000, FT2LOCATION, 4, 0, + statusBuffer); + if (status == FSUCCESS) { + printf("Success reading 0x%08x - buffer:\n", FT2LOCATION); + opaswDisplayBuffer((char *)statusBuffer, 4); + printf("FAN Speed of FT2 = %d\n", statusBuffer[0] * 60); + } else { + fprintf(stderr, "%s: Error: Failed to send/rcv i2cAccess MAD\n", cmdName); + status = FERROR; + } + } + break; + +#if 0 + case 12: + printf("reading ps status: PS 0x%08x\n", PSLOCATION); + status = FSUCCESS; + status = sendI2CAccessMad(omgt_port_session, &path, sessionID, &mad, + NOJUMBOMAD, MMTHD_GET, 2000, I2C_OPASW_PS_ADDR, 4, PS_MGMT_FPGA_OFFSET, + statusBuffer); + if (status == FSUCCESS) { + uint16 val; + char *c; + printf("Success reading 0x%08x - buffer:\n", PSLOCATION); + opaswDisplayBuffer((char *)statusBuffer, 4); + val = *(uint16 *)statusBuffer; +#if 1 + val = ntoh16(val); +#endif + printf("val is 0x%04x\n", val); + c = (char *)&val; + printf("val bytes 0x%02x 0x%02x\n", *c & 0xff, *(c + 1) & 0xff); + + printf("PS1_PRESENT = %d\n", (val >> PSU1_MGMT_FPGA_BIT_PRESENT) & 0x1); + printf("PS1_PWR_OK = %d\n", (val >> PSU1_MGMT_FPGA_BIT_PWR_OK) & 0x1); + printf("PS2_PRESENT = %d\n", (val >> PSU2_MGMT_FPGA_BIT_PRESENT) & 0x1); + printf("PS2_PWR_OK = %d\n", (val >> PSU2_MGMT_FPGA_BIT_PWR_OK) & 0x1); + } else { + fprintf(stderr, "%s: Error: Failed to send/rcv i2cAccess MAD\n", cmdName); + status = FERROR; + } + break; +#endif + + case 13: + status = sendIniDescriptorGetMad(omgt_port_session, &path, &mad, sessionID, &tableDescriptors); + if (status != FSUCCESS) { + fprintf(stderr, "%s: Error: Failed to get ini descriptors - status %d\n", cmdName, status); + if (sessionID>0) releaseSession(omgt_port_session, &path, sessionID); + goto err_exit; + } + printf("Sys Meta Data : addr 0x%08x len %d\n", tableDescriptors.sysMetaDataAddr, tableDescriptors.sysMetaDataLen); + printf("Sys Data : addr 0x%08x len %d\n", tableDescriptors.sysDataAddr, tableDescriptors.sysDataLen); + printf("Port Meta Data : addr 0x%08x len %d\n", tableDescriptors.portMetaDataAddr, tableDescriptors.portMetaDataLen); + printf("Port Data : addr 0x%08x len %d\n", tableDescriptors.portDataAddr, tableDescriptors.portDataLen); + numPorts = getNumPorts(omgt_port_session, &path, sessionID); + printf("numPorts is %d\n", numPorts); + portMTUMetaIndex = getMetaDataIndexByField(&portMetaData[0], tableDescriptors.portDataLen, "MTU_CAP"); + printf("portMTUMetaIndex is %d\n", portMTUMetaIndex); + if (portMTUMetaIndex < 0) { + fprintf(stderr, "%s: Error: can not find MTU in metaData table\n", cmdName); + if (sessionID>0) releaseSession(omgt_port_session, &path, sessionID); + goto err_exit; + } + portVLCAPMetaIndex = getMetaDataIndexByField(&portMetaData[0], tableDescriptors.portDataLen, "VL_CAP"); + printf("portVLCAPMetaIndex is %d\n", portVLCAPMetaIndex); + if (portVLCAPMetaIndex < 0) { + fprintf(stderr, "%s: Error: can not find VLCAP in metaData table\n", cmdName); + if (sessionID>0) releaseSession(omgt_port_session, &path, sessionID); + goto err_exit; + } +#if 1 + mtuCap = ntoh32(ENC_MTU_CAP_4096); +#else + mtuCap = ntoh32(1); +#endif + vlCap = ntoh32(ENC_VLCAP_VL0_3); +#if 0 + status = sendPortTableAccessSetMad(&path, &mad, sessionID, (uint8)portVLCAPMetaIndex, 1, 4, (uint8 *)&vlCap); +#endif + for (i = 1; i <= numPorts; i++) { + status = sendPortTableAccessSetMad(omgt_port_session, &path, &mad, sessionID, + (uint8)portMTUMetaIndex, i, 4, (uint8 *)&mtuCap); + if (status != FSUCCESS) { + fprintf(stderr, "%s: Error: Failed to set port table - status %d\n", cmdName, status); + if (sessionID>0) releaseSession(omgt_port_session, &path, sessionID); + goto err_exit; + } + } + break; + + case 14: +#define EEPROMLOCATION 0x00000000 + for (i = EEPROMLOCATION; i <= EEPROMLOCATION + 0xffffffff; i++) { + status = sendI2CAccessMad(omgt_port_session, &path, sessionID, &mad, + NOJUMBOMAD, MMTHD_GET, 2000, i, 4, 0, statusBuffer); + if (status == FSUCCESS) { + printf("Success reading 0x%08x - buffer:\n", i); + opaswDisplayBuffer((char *)statusBuffer, 4); + } else { + fprintf(stderr, "%s: Error: Failed to send/rcv i2cAccess MAD for loc 0x%08x\n", cmdName, i); + status = FERROR; + } + } + break; + + case 15: + location = 0x1040; + status = sendMemAccessGetMad(omgt_port_session, &path, &mad, sessionID, location, (uint8)200, memoryData); + if (g_verbose) { + printf("MemoryData dump:\n"); + opaswDisplayBuffer((char *)memoryData, 10); + } + p = memoryData; + asicVal = *(uint16 *)p; + printf("Data at 0x1040: 0x%02x 0x%02x\n", *p & 0xff, *(p + 1) & 0xff); + printf("Asic val is %d\n", asicVal >> 16); + break; + + case 16: +#if 1 +#define DATALEN (EEPROMSIZE / 2) +#else +#define DATALEN (256 + 16) +#endif +printf("TEST 16!!!\n"); + memset(dataBuffer, 0, EEPROMSIZE); + location = I2C_OPASW_PRI_EEPROM_ADDR; + dataOffset = EEPROMSIZE - DATALEN; + dataSize = DATALEN; + data = dataBuffer; + bytesRecd = 0; + while (bytesRecd < dataSize) { + if ((dataSize - bytesRecd) < 192) + readLen = dataSize - bytesRecd; + else + readLen = 192; + printf("reading loc 0x%08x offset %d len %d\n", location, dataOffset, readLen); + status = sendI2CAccessMad(omgt_port_session, &path, sessionID, &mad, + NOJUMBOMAD, MMTHD_GET, 2000, location, readLen, dataOffset, data); + if (status == FSUCCESS) { + data += readLen; + bytesRecd += readLen; + dataOffset += readLen; + } else { + fprintf(stderr, "%s: Error: Failed to send/rcv i2cAccess MAD for loc 0x%08x offset %d\n", cmdName, location, dataOffset); + status = FERROR; + } + usleep(200); + } + opaswDisplayBuffer((char *)dataBuffer, dataSize); + break; + + case 17: + location = 0x80407200; + data = dataBuffer; + memset(dataBuffer, 0, EEPROMSIZE); + status = sendI2CAccessMad(omgt_port_session, &path, sessionID, &mad, + NOJUMBOMAD, MMTHD_GET, 2000, location, 4, 0x0b00, data); + boardID = (uint16)data[0]; + printf("board ID is 0x%04x\n", boardID); + printf("data back is 0x%02x 0x%02x 0x%02x 0x%02x\n", data[0], data[1], data[2], data[3]); + break; + + case 18: + data = bigDataBuffer; + status = opaswEepromRW(omgt_port_session, &path, sessionID, &mad, 2000, 4 * EEPROMSIZE, 0, data, FALSE, FALSE); + data = bigDataBuffer; + for (i = 0; i < 4; i++) { + sprintf(dumpFileName, "dumpEEPROM-%d", i); + fp = fopen(dumpFileName, "w"); + fwrite(data, 1, EEPROMSIZE, fp); + fclose(fp); + data += EEPROMSIZE; + } + break; + + case 19: + location = I2C_OPASW_MGMT_FPGA_ADDR; + for (i = 0; i <= 0x22; i++) { + if ((i == 0x10) || + (i == 0x17) || + (i == 0x02) || + (i == 0x05) || + (i == 0x0c) || + (i == 0x0d) || + (i == 0x0e) || + (i == 0x0f) || + (i == 0x11) || + (i == 0x15) || + (i == 0x1c) || + (i == 0x1e) || + (i == 0x1f) || + (i == 0x20) || + (i == 0x22) || + (i == 0x18)) + continue; + memset(dataBuffer, 0, EEPROMSIZE); + memset(&mad, 0, sizeof(VENDOR_MAD)); + data = dataBuffer; + printf("probing register 0x%x\n", i); + dataOffset = (0xb << 8) | i; + status = sendI2CAccessMad(omgt_port_session, &path, sessionID, &mad, + NOJUMBOMAD, MMTHD_GET, 2000, location, 1, dataOffset, data); + printf("returned 0x%x\n", dataBuffer[0] & 0xff); + } + break; + + case 20: + status = sendMemAccessGetMad(omgt_port_session, &path, &mad, sessionID, 0x12d6, (uint8)4, memoryData); + p = memoryData; + asicVal2 = ntoh32(*(uint32 *)p); + printf("Value for asic rev is 0x%08x\n", asicVal2); + printf("Version is 0x%02x Chip name is %s step&rev %c%d \n", (asicVal2 & 0x00ff0000) >> 16, ((asicVal2 & 0x0000ff00) >> 8) == 2 ? "PRR" : "Unknown", ((asicVal2 & 0x000000f0) >> 4) + 'A', asicVal2 & 0x0000000f); + break; + + case 21: + { + int rc; + uint32 offset; + char *in; + // prompt for location and, optionally, offset, & length + printf("Enter location in hex (speed:2,reserved:6,flags:4,bus:4,addr:8,slot:8), [offset & length]: "); + rc = scanf("%m[^\n]", &in); + if (rc > 0) { + rc = sscanf(in, "%x %x %x", &location, &offset, &dataSize); + if (rc >= 1) { + if (rc < 3) { + // defaults if user didn't specify + dataSize = 1; + offset = 0; + } + dataOffset = (uint16) offset; + printf("Querying location 0x%08x, offset 0x%08x for %d bytes\n", location, dataOffset, dataSize); + status = sendI2CAccessMad(omgt_port_session, &path, sessionID, &mad, + NOJUMBOMAD, MMTHD_GET, 2000, location, dataSize, dataOffset, dataBuffer); + if (status == FSUCCESS) { + opaswDisplayBuffer((char *)dataBuffer, dataSize); + } else { + fprintf(stderr, "%s: Error: Failed to send/rcv i2cAccess MAD for loc 0x%08x offset %d\n", cmdName, location, dataOffset); + } + } + free(in); + } + break; + } + + case 22: + { + int rc; + int i = 0; + char *in; + char *tok; + char *ctxt; + char *delim = " \t\n"; + uint32 tmp; + dataOffset = 0; // keep compiler happy + printf("Enter location, offset, and data bytes (in hex): "); + rc = scanf("%m[^\n]", &in); + if (rc > 0) { + tok = strtok_r(in, delim, &ctxt); + while (NULL != tok) { + rc = sscanf(tok, "%x", &tmp); + if (rc > 0) { + if (0 == i) + location = tmp; + else if (1 == i) + dataOffset = (uint16)tmp; + else { + dataBuffer[i-2] = (uint8)tmp; + } + i++; + } else { + fprintf(stderr, "%s: Error: \"%s\" is not a hex number\n",cmdName, tok); + status = FERROR; + break; + } + tok = strtok_r(NULL, delim, &ctxt); + } + if (status == FSUCCESS) { + if (i > 2) { + // parsing was successful and we got location, offset, and at least 1 data byte + dataSize = i-2; + printf("Writing location 0x%08x, offset 0x%08x with %d bytes\n", location, dataOffset, dataSize); + status = sendI2CAccessMad(omgt_port_session, &path, sessionID, &mad, + NOJUMBOMAD, MMTHD_SET, 2000, location, dataSize, dataOffset, dataBuffer); + if (status != FSUCCESS) { + fprintf(stderr, "%s: Error: Failed to send/rcv i2cAccess MAD for loc 0x%08x offset %d\n", cmdName, location, dataOffset); + } + } else { + fprintf(stderr, "%s: Error: Expected at least 3 tokens, only got %d\n", cmdName, i); + status = FERROR; + } + } + free(in); + } + break; + } + default: + fprintf(stderr, "Invalid test number\n"); + usage(cmdName); + break; + } + +#if GET + opaswDisplayBuffer((char *)sysTableData, dataLen); +#endif + + if (sessionID>0) releaseSession(omgt_port_session, &path, sessionID); + + printf("opaswtest completed\n"); + +err_exit: + if (omgt_port_session != NULL) { + omgt_close_port(omgt_port_session); + } + + if (status == FSUCCESS) + exit(0); + else + exit(1); + +} diff --git a/IbaTools/opatop/Makefile b/IbaTools/opatop/Makefile new file mode 100644 index 0000000..bb0964b --- /dev/null +++ b/IbaTools/opatop/Makefile @@ -0,0 +1,171 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** +# Makefile for opatop + +# Include Make Control Settings +include $(TL_DIR)/$(PROJ_FILE_DIR)/Makesettings.project + +#=============================================================================# +# Definitions: +#-----------------------------------------------------------------------------# + +# Name of SubProjects +DS_SUBPROJECTS = +# name of executable or downloadable image +EXECUTABLE = $(BUILDDIR)/opatop$(EXE_SUFFIX) +# list of sub directories to build +DIRS = +# C files (.c) +CFILES = \ + opatop.c \ + # Add more c files here +# C++ files (.cpp) +CCFILES = \ + # Add more cpp files here +# lex files (.lex) +LFILES = \ + # Add more lex files here +# archive library files (basename, $ARFILES will add MOD_LIB_DIR/prefix and suffix) +LIBFILES = +# Windows Resource Files (.rc) +RSCFILES = +# Windows IDL File (.idl) +IDLFILE = +# Windows Linker Module Definitions (.def) file for dll's +DEFFILE = +# targets to build during INCLUDES phase (add public includes here) +INCLUDE_TARGETS = \ + # Add more h hpp files here +# Non-compiled files +MISC_FILES = opatop_group_bw.hlp opatop_group_config.hlp \ + opatop_group_ctg.hlp opatop_group_focus.hlp \ + opatop_group_info_sel.hlp opatop_img_config.hlp \ + opatop_pm_config.hlp opatop_port_stats.hlp \ + opatop_summary.hlp opatop_vf_bw.hlp \ + opatop_vf_config.hlp opatop_vf_info_sel.hlp \ + opatop_vf_port_stats.hlp \ + # Add more MISC_FILES here +# all source files +SOURCES = $(CFILES) $(CCFILES) $(LFILES) $(RSCFILES) $(IDLFILE) +# Source files to include in DSP File +DSP_SOURCES = $(INCLUDE_TARGETS) $(SOURCES) $(MISC_FILES) \ + $(RSCFILES) $(DEFFILE) $(MAKEFILE) +# all object files +OBJECTS = $(CFILES:.c=$(OBJ_SUFFIX)) $(CCFILES:.cpp=$(OBJ_SUFFIX)) \ + $(LFILES:.lex=$(OBJ_SUFFIX)) +RSCOBJECTS = $(RSCFILES:.rc=$(RES_SUFFIX)) +# targets to build during LIBS phase +LIB_TARGETS_IMPLIB = +LIB_TARGETS_ARLIB = +LIB_TARGETS_EXP = $(LIB_TARGETS_IMPLIB:$(ARLIB_SUFFIX)=$(EXP_SUFFIX)) +LIB_TARGETS_MISC = +# targets to build during CMDS phase +SHLIB_VERSION = +CMD_TARGETS_SHLIB = +CMD_TARGETS_EXE = $(EXECUTABLE) +CMD_TARGETS_MISC = +CMD_TARGETS_DRIVER = +CMD_TARGETS_KEXT = +# files to remove during clean phase +CLEAN_TARGETS_MISC = +CLEAN_TARGETS = $(OBJECTS) $(RSCOBJECTS) $(IDL_TARGETS) $(CLEAN_TARGETS_MISC) +# other files to remove during clobber phase +CLOBBER_TARGETS_MISC= +# sub-directory to install to within bin +BIN_SUBDIR = +# sub-directory to install to within include +INCLUDE_SUBDIR = + +# Additional Settings +#CLOCALDEBUG = User defined C debugging compilation flags [Empty] +#CCLOCALDEBUG = User defined C++ debugging compilation flags [Empty] +#CLOCAL = User defined C flags for compiling [Empty] +#CCLOCAL = User defined C++ flags for compiling [Empty] +#BSCLOCAL = User flags for Browse File Builder [Empty] +#DEPENDLOCAL = user defined makedepend flags [Empty] +#LINTLOCAL = User defined lint flags [Empty] +#LOCAL_INCLUDE_DIRS = User include directories to search for C/C++ headers [Empty] +#LDLOCAL = User defined C flags for linking [Empty] +#IMPLIBLOCAL = User flags for Object Lirary Manager [Empty] +#MIDLLOCAL = User flags for IDL compiler [Empty] +#RSCLOCAL = User flags for resource compiler [Empty] +#LOCALDEPLIBS = User libraries to include in dependencies [Empty] +#LOCALLIBS = User libraries to use when linking [Empty] +# (in addition to LOCALDEPLIBS) +#LOCAL_LIB_DIRS = User library directories for libpaths [Empty] + +CLOCAL=$(CIBACCESS) $(CPIE) +ifeq "$(IB_STACK)" "IBACCESS" +LOCALDEPLIBS=$(IBACCESS_USER_LIBS) Xml Topology +LOCAL_LIB_DIRS= $(IBACCESS_USER_LIB_DIRS) +else +LOCALDEPLIBS=$(IBACCESS_USER_LIBS) Xml Topology opamgt-priv +LOCALLIBS=$(OPENIB_USER_LIBS) +LOCAL_LIB_DIRS=$(OPENIB_USER_LIB_DIRS) $(IBACCESS_USER_LIB_DIRS) +endif + +# Include Make Rules definitions and rules +include $(TL_DIR)/$(PROJ_FILE_DIR)/Makerules.project + +#=============================================================================# +# Overrides: +#-----------------------------------------------------------------------------# +#CCOPT = # C++ optimization flags, default lets build config decide +#COPT = # C optimization flags, default lets build config decide +#SUBSYSTEM = Subsystem to build for (none, console or windows) [none] +# (Windows Only) +#USEMFC = How Windows MFC should be used (none, static, shared, no_mfc) [none] +# (Windows Only) +#=============================================================================# + +#=============================================================================# +# Rules: +#-----------------------------------------------------------------------------# +# process Sub-directories +include $(TL_DIR)/Makerules/Maketargets.toplevel + +# build cmds and libs +include $(TL_DIR)/Makerules/Maketargets.build + +# install for includes, libs and cmds phases +include $(TL_DIR)/Makerules/Maketargets.install + +# install for stage phase +#include $(TL_DIR)/Makerules/Maketargets.stageS +STAGE:: + $(VS)$(STAGE_INSTALL) $(STAGE_INSTALL_DIR_OPT) $(PROJ_STAGE_FASTFABRIC_DIR) $(EXECUTABLE) $(MISC_FILES) + +# Unit test execution +#include $(TL_DIR)/Makerules/Maketargets.runtest + +#=============================================================================# + +#=============================================================================# +# DO NOT DELETE THIS LINE -- make depend depends on it. +#=============================================================================# diff --git a/IbaTools/opatop/opatop.c b/IbaTools/opatop/opatop.c new file mode 100644 index 0000000..751783e --- /dev/null +++ b/IbaTools/opatop/opatop.c @@ -0,0 +1,3526 @@ +/* BEGIN_ICS_COPYRIGHT7 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT7 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +#include +#include +#include +#include +#include "stl_pm.h" +#include "topology.h" +#include "opamgt_priv.h" +#include "opamgt_pa_priv.h" +#include "opamgt_pa.h" +#include +#include +#include + +#undef DBGPRINT +#define DBGPRINT(format, args...) \ + do { if (g_verbose & VERBOSE_STDERR) { fprintf(stderr, format, ##args); } } while (0) + +#define PROGRESS_PRINT(newline, format, args...) \ + do { if (! g_quiet) { ProgressPrint(newline, format, ##args); } } while (0) + +#define NAME_PROG "opatop" // Program name +#define MAX_COLUMNS_PER_LINE 80 +#define MAX_LINES_PER_SCREEN 24 +#define MAX_LEVELS_MENU 10 +#define MAX_SUMMARY_GROUP_LINES_PER_SCREEN 10 +#define MAX_VF_SUMMARY_PER_SCREEN 5 +#define MAX_GROUPCONFIG_PORTS_PER_SCREEN (MAX_LINES_PER_SCREEN - 5) +#define MAX_GROUPFOCUS_PORTS_PER_SCREEN ((MAX_LINES_PER_SCREEN - 5) / 2) +#define MAX_VFCONFIG_PORTS_PER_SCREEN MAX_GROUPCONFIG_PORTS_PER_SCREEN +#define MAX_VFFOCUS_PORTS_PER_SCREEN MAX_GROUPFOCUS_PORTS_PER_SCREEN + + +#define PACLIENT_SEL_ALL 0x00010000 // All ports in group + + +/* Screen hierarchy map: + * + * LEVEL: SCREEN_NAME: + * 0 SCREEN_SUMMARY + * 1 SCREEN_PM_CONFIG + * 1 SCREEN_IMAGE_INFO + * 1 SCREEN_GROUP_INFO_SELECT + * 2 SCREEN_GROUP_BW_STATS + * 3 SCREEN_GROUP_FOCUS + * 4 SCREEN_PORT_STATS + * 2 SCREEN_GROUP_CTG_STATS + * 3 SCREEN_GROUP_FOCUS + * 4 SCREEN_PORT_STATS + * 2 SCREEN_GROUP_CONFIG + * 3 SCREEN_PORT_STATS + * 0 SCREEN_VF_SUMMARY + * 1 SCREEN_PM_CONFIG + * 1 SCREEN_IMAGE_INFO + * 1 SCREEN_VF_INFO_SELECT + * 2 SCREEN_VF_BW_STATS + * 3 SCREEN_VF_FOCUS + * 4 SCREEN_PORT_STATS + * 2 SCREEN_VF_CONFIG + * 3 SCREEN_PORT_STATS + * 2 SCREEN_VF_CTG_STATS + * 3 SCREEN_VF_FOCUS + * 4 SCREEN_PORT_STATS + */ +#define SCREEN_SUMMARY 0 +#define SCREEN_PM_CONFIG 1 +#define SCREEN_IMAGE_INFO 2 +#define SCREEN_GROUP_INFO_SELECT 3 +#define SCREEN_GROUP_BW_STATS 4 +#define SCREEN_GROUP_CTG_STATS 5 +#define SCREEN_GROUP_CONFIG 6 +#define SCREEN_GROUP_FOCUS 7 +#define SCREEN_PORT_STATS 8 +#define SCREEN_VF_SUMMARY 9 +#define SCREEN_VF_INFO_SELECT 10 +#define SCREEN_VF_BW_STATS 11 +#define SCREEN_VF_CONFIG 12 +#define SCREEN_VF_CTG_STATS 13 +#define SCREEN_VF_FOCUS 14 +#define SCREEN_VF_PORT_STATS 15 + +#define VERBOSE_NONE 0 // No verbose output +#define VERBOSE_SCREEN 0x0001 // Verbose screen displays +#define VERBOSE_SCREEN_2 0x0002 // Verbose screen more displays +#define VERBOSE_STDERR 0x0004 // Verbose stderr (opatop) +#define VERBOSE_PACLIENT 0x0010 // Verbose stderr PaClient +#define VERBOSE_TOP_MAD 0x0020 // Verbose stderr Topology MADs +#define VERBOSE_TOP_SWEEP 0x0040 // Verbose stderr Topology sweep + +#define DEBUG_NONE 0 // No debug functions +#define DEBUG_GROUP 0x0001 // Display group information +#define DEBUG_IMGID 0x0002 // Display single image ID +#define DEBUG_IMGID_2 0x0004 // Display multiple image IDs + +#define PATH_HELP "/usr/share/opa/help/" +// if help files are bigger than this, extra will be silently ignored +#define MAX_HELP_CHARS 10240 // allows for about 10x growth +#define MAX_HELP_LINES 999 // allows for about 10x growth + +// ANSI terminal sequences to change color +char bf_color_off[] = {27, '[', '0', 'm', 0}; +char bf_color_red[] = {27, '[', '3', '1', 'm', 0}; +char bf_color_green[] = {27, '[', '3', '2', 'm', 0}; +char bf_color_yellow[] = {27, '[', '3', '3', 'm', 0}; +char bf_color_blue[] = {27, '[', '3', '4', 'm', 0}; +char bf_color_cyan[] = {27, '[', '3', '6', 'm', 0}; +// ANSI terminal sequence to clear screen +char bf_clear_screen[] = {27, '[', 'H', 27, '[', '2', 'J', 0}; + +struct termios g_term; // terminal I/O settings +struct termios g_term_save; // saved terminal I/O settings +int g_exitstatus = 0; +EUI64 g_portGuid = -1; // local port to use to access fabric +uint32 g_interval = 10; +struct omgt_port *g_portHandle = NULL; + +uint32 g_verbose = VERBOSE_NONE; +uint32 g_debug = DEBUG_NONE; +int g_quiet = 0; // omit progress output +int g_expr_funct = 0; // Experimental functionality (undocumented) + +uint8 hfi = 0; +uint8 port = 0; + +uint32 ct_interval = 0; +uint8 n_level_menu = 0; +uint8 tb_menu[MAX_LEVELS_MENU]; +char *p_multi_input = "qQ"; + +typedef struct _opatop_group_cfg { + char groupName[STL_PM_GROUPNAMELEN]; + uint32 numPorts; + STL_PA_PM_GROUP_CFG_RSP *portList; +} OPATOP_GROUP_CFG; + +typedef struct _opatop_vf_cfg { + char vfName[STL_PM_VFNAMELEN]; + uint32 numPorts; + STL_PA_VF_CFG_RSP *portList; +} OPATOP_VF_CFG; + +typedef struct _opatop_group_focus { + char groupName[STL_PM_GROUPNAMELEN]; + uint32 numPorts; + uint32 select; + uint32 start; + uint32 range; + STL_FOCUS_PORTS_RSP *portList; +} OPATOP_GROUP_FOCUS; + +typedef struct _opatop_vf_focus { + char vfName[STL_PM_VFNAMELEN]; + uint32 numPorts; + uint32 select; + uint32 start; + uint32 range; + STL_PA_VF_FOCUS_PORTS_RSP *portList; +} OPATOP_VF_FOCUS; + +typedef struct _opatop_group_list { + uint32 numGroups; + STL_PA_GROUP_LIST *groupList; +} OPATOP_GROUP_LIST; + +typedef struct _opatop_vf_list { + uint32 numVFs; + STL_PA_VF_LIST *vfList; +} OPATOP_VF_LIST; +typedef struct _opatop_group_list2 { + uint32 numGroups; + STL_PA_GROUP_LIST2 *groupList; +} OPATOP_GROUP_LIST2; +typedef struct _opatop_vf_list2 { + uint32 numVFs; + STL_PA_VF_LIST2 *vfList; +} OPATOP_VF_LIST2; + +STL_PA_IMAGE_ID_DATA g_imageIdQuery = {PACLIENT_IMAGE_CURRENT, 0}; +STL_PA_IMAGE_ID_DATA g_imageIdResp = {PACLIENT_IMAGE_CURRENT, 0}; +STL_PA_IMAGE_ID_DATA g_imageIdFreeze = {PACLIENT_IMAGE_CURRENT, 0}; +STL_PA_IMAGE_ID_DATA g_imageIdBookmark = {PACLIENT_IMAGE_CURRENT, 0}; +STL_PA_IMAGE_ID_DATA g_imageIdTemp = {PACLIENT_IMAGE_CURRENT, 0}; +STL_CLASS_PORT_INFO *g_PaClassPortInfo = NULL; +STL_PA_PM_CFG_DATA g_PmConfig; +STL_PA_IMAGE_INFO_DATA g_PmImageInfo; +OPATOP_GROUP_LIST g_PmGroupList = {0}; +OPATOP_GROUP_LIST2 g_PmGroupList2 = {0}; +STL_PA_PM_GROUP_INFO_DATA g_PmGroupInfo; +OPATOP_GROUP_CFG pg_PmGroupConfig = {{0}}; +OPATOP_GROUP_FOCUS pg_PmGroupFocus = {{0}}; +OPATOP_VF_LIST g_PmVFList = {0}; +OPATOP_VF_LIST2 g_PmVFList2 = {0}; +STL_PA_VF_INFO_DATA g_PmVFInfo; +OPATOP_VF_CFG g_pPmVFConfig = {{0}}; + +STL_PORT_COUNTERS_DATA g_portCounters = {0}; +STL_PA_VF_PORT_COUNTERS_DATA g_hiddenVfPortCounters; +STL_PA_VF_PORT_COUNTERS_DATA g_vfPortCounters; +OPATOP_VF_FOCUS g_pPmVFFocus = {{0}}; +uint32 g_portCounterFlags; +uint32 g_hiddenVfPortCounterFlags; +uint32 g_vfPortCounterFlags; +int g_offset = 0; +int g_group = -1; +int g_vf = -1; +int g_ix_port = -1; +STL_LID g_portlid = 0; +uint8 g_portnum = 0; +uint32 g_select = STL_PA_SELECT_UTIL_HIGH; +uint32 g_start = 0; +uint32 g_range = 10; +int g_scroll = 0; +int g_scroll_summary = 0; +int g_scroll_summary_forward = 0; +int g_scroll_summary_backward = 0; +int g_scroll_vf_summary = 0; +int g_scroll_cntrs = 0; +boolean fb_help = FALSE; +boolean fb_valid_pa_client = FALSE; +boolean fb_valid_pa_cpi = FALSE; +boolean fb_valid_pa_cpi_vf_focus_types = FALSE; +boolean fb_valid_pa_cpi_list2 = FALSE; + +#define GROUPNAME(IDX) (fb_valid_pa_cpi_list2 ? \ + g_PmGroupList2.groupList[IDX].groupName : g_PmGroupList.groupList[IDX].groupName) +#define VFNAME(IDX) (fb_valid_pa_cpi_list2 ? \ + g_PmVFList2.vfList[IDX].vfName : g_PmVFList.vfList[IDX].vfName) + +boolean fb_valid_group_list = FALSE; +boolean fb_valid_pm_config = FALSE; +boolean fb_valid_image_info = FALSE; +boolean fb_valid_group_info = FALSE; +boolean fb_valid_group_config = FALSE; +boolean fb_valid_group_focus = FALSE; +boolean fb_valid_port_stats = FALSE; +boolean fb_valid_vf_port_stats_hidden = FALSE; +boolean fb_port_neighbor; +boolean fb_port_has_neighbor; +boolean fb_error_displayed; +boolean fb_valid_VF_list = FALSE; +boolean fb_valid_VF_info = FALSE; +boolean fb_valid_VF_config = FALSE; +boolean fb_valid_VF_focus = FALSE; +boolean fb_valid_VF_port_counters = FALSE; + +char bf_error[81]; + +/* Array containing util criterias */ +uint32 conditionUtilArray[] = { + STL_PA_SELECT_UTIL_HIGH, + STL_PA_SELECT_UTIL_PKTS_HIGH, + STL_PA_SELECT_UTIL_LOW, + STL_PA_SELECT_VF_UTIL_HIGH, + STL_PA_SELECT_VF_UTIL_PKTS_HIGH, + STL_PA_SELECT_VF_UTIL_LOW +}; +uint32 g_utilGroupArrayEndIdx = 2; +uint32 g_utilVFArrayEndIdx = 5; + +/* Array containing category criterias */ +uint32 conditionCtgArray[] = { + STL_PA_SELECT_CATEGORY_INTEG, + STL_PA_SELECT_CATEGORY_CONG, + STL_PA_SELECT_CATEGORY_SMA_CONG, + STL_PA_SELECT_CATEGORY_BUBBLE, + STL_PA_SELECT_CATEGORY_SEC, + STL_PA_SELECT_CATEGORY_ROUT, + STL_PA_SELECT_CATEGORY_VF_CONG, + STL_PA_SELECT_CATEGORY_VF_BUBBLE +}; +uint32 g_ctgGroupArrayEndIdx = 5; +uint32 g_ctgVFArrayEndIdx = 7; + +/* Array containing all criterias */ +uint32 conditionFocusArray[] = { + STL_PA_SELECT_UTIL_HIGH, + STL_PA_SELECT_UTIL_PKTS_HIGH, + STL_PA_SELECT_UTIL_LOW, + STL_PA_SELECT_CATEGORY_INTEG, + STL_PA_SELECT_CATEGORY_CONG, + STL_PA_SELECT_CATEGORY_SMA_CONG, + STL_PA_SELECT_CATEGORY_BUBBLE, + STL_PA_SELECT_CATEGORY_SEC, + STL_PA_SELECT_CATEGORY_ROUT, + STL_PA_SELECT_VF_UTIL_HIGH, + STL_PA_SELECT_VF_UTIL_PKTS_HIGH, + STL_PA_SELECT_VF_UTIL_LOW, + STL_PA_SELECT_CATEGORY_VF_CONG, + STL_PA_SELECT_CATEGORY_VF_BUBBLE +}; +uint32 g_focusGroupArrayEndIdx = 8; +uint32 g_focusVFArrayEndIdx = 13; + +/******************************************************************************* +* +* get_input - get user input +* +* Inputs: +* n_optn - Options as: Fxxx xxxx +* F = 1 - Flush input +* +* n_char - Number of input chars (including trailing 0x0A) +* bf_input - Pointer to caller input buffer +* bf_multi - Pointer to multi-char commands (case sensitive) +* +* Return: +* -1 - Invalid parameter +* 0 - No input available +* >0 - Number of input characters available +* +*******************************************************************************/ +static int get_input( uint32 n_optn, uint32 n_chars, char *bf_input, + char *bf_multi, boolean *isdelchar ) +{ + int32 ret_val = 0; + static uint32 ct_hold = 0; + static boolean fl_multi = FALSE; + fd_set fd_set_read; + struct timeval time_select; + static char bf_hold[64]; + + if (!ct_hold || (n_optn & 0x80)) + { + memset(bf_hold, 0, sizeof(bf_hold)); + ct_hold = 0; + fl_multi = FALSE; + } + + if (!bf_input || !n_chars || (n_chars > sizeof(bf_hold))) + return (-1); + + FD_ZERO(&fd_set_read); + FD_SET(0, &fd_set_read); + time_select.tv_sec = 0; + time_select.tv_usec = 10000; // 10 mSec + + if (select(1, &fd_set_read, NULL, NULL, &time_select) > 0) { + char input = fgetc(stdin); + if (ct_hold > 0 && (input == 0x08 || input == 127)) { // BackSpace Or Del + bf_hold[ct_hold--] = 0; + *isdelchar = TRUE; // reprint line so we can handle delchar. + } else if (isprint(input) || input == 0x0A) { + bf_hold[ct_hold++] = input; + } + } + + if (ct_hold >= n_chars) + bf_hold[(ct_hold = n_chars) - 1] = 0x0A; + + if (!fl_multi && bf_multi && strchr(bf_multi, bf_hold[0])) + fl_multi = TRUE; + + if (ct_hold && (!fl_multi || (bf_hold[ct_hold - 1] == 0x0A))) + { + // Return input string and clean-up for next input sequence + memcpy(bf_input, bf_hold, ct_hold); + ret_val = ct_hold; + ct_hold = 0; + } else if (ct_hold > 0) { + // Return input string, so we can reprint on screen refresh + memcpy(bf_input, bf_hold, ct_hold); + bf_input[ct_hold] = 0; + } + + return (ret_val); + +} // End of get_input() + +// for the (maxlen+1)'th character in display of a string, return what to show +// ' ' - string is <= maxlen characters +// '*' - string is > maxlen+1 characters +// str[maxlen] - string is exactly maxlen+1 characters +// designed for output which has strict column widths +char strgetlastchar(const char* str, int maxlen) +{ + int len = strlen(str); + if (len <= maxlen) return ' '; + else if (len == maxlen+1) return str[maxlen]; + else /* (len > maxlen+1) */ return '*'; +} + +// similar to strgetlastchar, except if string is <= maxlen returns "" +// design for output where we don't want extra trailing spaces for str +const char* strgetlaststr(const char* str, int maxlen) +{ + static char buf[2]; + + int len = strlen(str); + if (len <= maxlen) return " "; + else if (len == maxlen+1) { buf[0] = str[maxlen]; buf[1]='\0'; return buf;} + else /* (len > maxlen+1) */ return "*"; +} + + +int DisplayScreen_SMs(void) +{ + if (g_PmImageInfo.numSMs > 0) + { + printf( " Master-SM: LID: 0x%.*X Port: %-3u Priority: %-2u State: %s\n", + (g_PmImageInfo.SMInfo[0].lid <= IB_MAX_UCAST_LID ? 4:8), + g_PmImageInfo.SMInfo[0].lid, + g_PmImageInfo.SMInfo[0].portNumber, + g_PmImageInfo.SMInfo[0].priority, + IbSMStateToText(g_PmImageInfo.SMInfo[0].state) ); + + // Truncate smNodeDesc to keep line at 80 columns + printf( " Name: %-.58s%s\n", + g_PmImageInfo.SMInfo[0].smNodeDesc, + strgetlaststr(g_PmImageInfo.SMInfo[0].smNodeDesc, 58)); + printf( " PortGUID: 0x%016" PRIX64"\n", + g_PmImageInfo.SMInfo[0].smPortGuid); + } + + else + printf( " Master-SM: none\n\n\n" ); + + if (g_PmImageInfo.numSMs > 1) + { + printf( " Secondary-SM: LID: 0x%.*X Port: %-3u Priority: %-2u State: %s\n", + (g_PmImageInfo.SMInfo[1].lid <= IB_MAX_UCAST_LID ? 4:8), + g_PmImageInfo.SMInfo[1].lid, + g_PmImageInfo.SMInfo[1].portNumber, + g_PmImageInfo.SMInfo[1].priority, + IbSMStateToText(g_PmImageInfo.SMInfo[1].state) ); + + // Truncate smNodeDesc to keep line at 80 columns + printf( " Name: %-.58s%s\n", + g_PmImageInfo.SMInfo[1].smNodeDesc, + strgetlaststr(g_PmImageInfo.SMInfo[1].smNodeDesc, 58)); + printf( " PortGUID: 0x%016" PRIX64 "\n", + g_PmImageInfo.SMInfo[1].smPortGuid); + } + + else + printf( " Secondary-SM: none\n\n\n" ); + + return 6; +} + +int DisplayScreen_Err(STL_PM_CATEGORY_STATS * p_PmErrStats, char * p_title) +{ + printf( "%-4s Max 0+%% 25+%% 50+%% 75+%% 100+%%\n", + p_title ); + printf( " Integrity %10u %9u %9u %9u %9u %9u\n", + p_PmErrStats->categoryMaximums.integrityErrors, + p_PmErrStats->ports[0].integrityErrors, + p_PmErrStats->ports[1].integrityErrors, + p_PmErrStats->ports[2].integrityErrors, + p_PmErrStats->ports[3].integrityErrors, + p_PmErrStats->ports[4].integrityErrors ); + printf( " Congestion %10u %9u %9u %9u %9u %9u\n", + p_PmErrStats->categoryMaximums.congestion, + p_PmErrStats->ports[0].congestion, + p_PmErrStats->ports[1].congestion, + p_PmErrStats->ports[2].congestion, + p_PmErrStats->ports[3].congestion, + p_PmErrStats->ports[4].congestion ); + printf( " SmaCongest %10u %9u %9u %9u %9u %9u\n", + p_PmErrStats->categoryMaximums.smaCongestion, + p_PmErrStats->ports[0].smaCongestion, + p_PmErrStats->ports[1].smaCongestion, + p_PmErrStats->ports[2].smaCongestion, + p_PmErrStats->ports[3].smaCongestion, + p_PmErrStats->ports[4].smaCongestion ); + printf( " Bubble %10u %9u %9u %9u %9u %9u\n", + p_PmErrStats->categoryMaximums.bubble, + p_PmErrStats->ports[0].bubble, + p_PmErrStats->ports[1].bubble, + p_PmErrStats->ports[2].bubble, + p_PmErrStats->ports[3].bubble, + p_PmErrStats->ports[4].bubble ); + printf( " Security %10u %9u %9u %9u %9u %9u\n", + p_PmErrStats->categoryMaximums.securityErrors, + p_PmErrStats->ports[0].securityErrors, + p_PmErrStats->ports[1].securityErrors, + p_PmErrStats->ports[2].securityErrors, + p_PmErrStats->ports[3].securityErrors, + p_PmErrStats->ports[4].securityErrors ); + printf( " Routing %10u %9u %9u %9u %9u %9u\n", + p_PmErrStats->categoryMaximums.routingErrors, + p_PmErrStats->ports[0].routingErrors, + p_PmErrStats->ports[1].routingErrors, + p_PmErrStats->ports[2].routingErrors, + p_PmErrStats->ports[3].routingErrors, + p_PmErrStats->ports[4].routingErrors ); + printf(" Utilization: %3u.%1u%% Discards: %3u.%1u%%\n", + p_PmErrStats->categoryMaximums.utilizationPct10 / 10, + p_PmErrStats->categoryMaximums.utilizationPct10 % 10, + p_PmErrStats->categoryMaximums.discardsPct10 / 10, + p_PmErrStats->categoryMaximums.discardsPct10 % 10); + + return (8); + +} // End of DisplayScreen_Err() + +int DisplayScreen_Group(STL_PA_PM_GROUP_INFO_DATA * p_PmGroupInfo, int n_group) +{ + int ct_lines = 0; + STL_PA_PM_UTIL_STATS * p_PmUtilStats; + char *p_state_integ, *p_color_integ; + char *p_state_congst, *p_color_congst; + char *p_state_smacong, *p_color_smacong; + char *p_state_bubble, *p_color_bubble; + char *p_state_secure, *p_color_secure; + char *p_state_routing, *p_color_routing; + +#define EVAL_ERR_STAT2(statistic, state, color) \ + if (p_PmGroupInfo->internalCategoryStats.ports[4].statistic > 0 \ + || p_PmGroupInfo->externalCategoryStats.ports[4].statistic > 0) \ + { state = "OVER"; color = bf_color_red; } \ + else if (p_PmGroupInfo->internalCategoryStats.ports[3].statistic > 0 \ + || p_PmGroupInfo->externalCategoryStats.ports[3].statistic > 0) \ + { state = "Warn"; color = bf_color_yellow; } \ + else if (p_PmGroupInfo->internalCategoryStats.ports[2].statistic > 0 \ + || p_PmGroupInfo->externalCategoryStats.ports[2].statistic > 0) \ + { state = "Mod"; color = bf_color_cyan; } \ + else if (p_PmGroupInfo->internalCategoryStats.ports[1].statistic > 0 \ + || p_PmGroupInfo->externalCategoryStats.ports[1].statistic > 0) \ + { state = "Low"; color = bf_color_blue; } \ + else \ + { state = "min"; color = bf_color_green; } + + // Summarize internal utilization + if (p_PmGroupInfo->numInternalPorts) + { + p_PmUtilStats = &p_PmGroupInfo->internalUtilStats; + printf( "%d %-10.10s%c Int %9u %9u %9u %9u %9u %9u\n", + n_group - g_scroll_summary, + p_PmGroupInfo->groupName, + strgetlastchar(p_PmGroupInfo->groupName, 10), + p_PmUtilStats->avgMBps, + p_PmUtilStats->minMBps != UINT_MAX ? p_PmUtilStats->minMBps : 0, + p_PmUtilStats->maxMBps, p_PmUtilStats->avgKPps, + p_PmUtilStats->minKPps != UINT_MAX ? p_PmUtilStats->minKPps : 0, + p_PmUtilStats->maxKPps ); + + ct_lines += 1; + } + + // Summarize send and recv utilization + if (p_PmGroupInfo->numExternalPorts) + { + p_PmUtilStats = &p_PmGroupInfo->sendUtilStats; + + if (p_PmGroupInfo->numInternalPorts) + printf(" "); + else + printf("%d %-10.10s%c", n_group - g_scroll_summary, + p_PmGroupInfo->groupName, + strgetlastchar(p_PmGroupInfo->groupName, 10)); + + printf( " Snd %9u %9u %9u %9u %9u %9u\n", p_PmUtilStats->avgMBps, + p_PmUtilStats->minMBps != UINT_MAX ? p_PmUtilStats->minMBps : 0, + p_PmUtilStats->maxMBps, p_PmUtilStats->avgKPps, + p_PmUtilStats->minKPps != UINT_MAX ? p_PmUtilStats->minKPps : 0, + p_PmUtilStats->maxKPps ); + p_PmUtilStats = &p_PmGroupInfo->recvUtilStats; + printf( " Rcv %9u %9u %9u %9u %9u %9u\n", + p_PmUtilStats->avgMBps, + p_PmUtilStats->minMBps != UINT_MAX ? p_PmUtilStats->minMBps : 0, + p_PmUtilStats->maxMBps, p_PmUtilStats->avgKPps, + p_PmUtilStats->minKPps != UINT_MAX ? p_PmUtilStats->minKPps : 0, + p_PmUtilStats->maxKPps ); + + ct_lines += 2; + } + if (p_PmGroupInfo->numInternalPorts == 0 + && p_PmGroupInfo->numExternalPorts == 0) + { + printf( "%d %-10.10s%c No ports in group\n", n_group - g_scroll_summary, + p_PmGroupInfo->groupName, + strgetlastchar(p_PmGroupInfo->groupName, 10)); + ct_lines += 1; + } else { + // Summarize errors + EVAL_ERR_STAT2(integrityErrors, p_state_integ, p_color_integ); + EVAL_ERR_STAT2(congestion, p_state_congst, p_color_congst); + EVAL_ERR_STAT2(smaCongestion, p_state_smacong, p_color_smacong); + EVAL_ERR_STAT2(bubble, p_state_bubble, p_color_bubble); + EVAL_ERR_STAT2(securityErrors, p_state_secure, p_color_secure); + EVAL_ERR_STAT2(routingErrors, p_state_routing, p_color_routing); + + printf( " %sInteg:%-4s%s %sCongst:%-4s%s %sSmaCong:%-4s%s %sBubble:%-4s%s %sSecure:%-4s%s %sRouting:%-4s%s\n", + p_color_integ, p_state_integ, bf_color_off, + p_color_congst, p_state_congst, bf_color_off, + p_color_smacong, p_state_smacong, bf_color_off, + p_color_bubble, p_state_bubble, bf_color_off, + p_color_secure, p_state_secure, bf_color_off, + p_color_routing, p_state_routing, bf_color_off ); + + ct_lines += 1; + } + + return (ct_lines); + +} // End of DisplayScreen_Group() + +int ScreenLines_Group(STL_PA_PM_GROUP_INFO_DATA * p_PmGroupInfo, int n_group) +{ + int ct_lines = 0; + if (p_PmGroupInfo->numInternalPorts) + ct_lines += 1; // Int + if (p_PmGroupInfo->numExternalPorts) + ct_lines += 2; // Send and Rcv + ct_lines += 1; // error summary + return (ct_lines); + +} // End of ScreenLines_Group() + +int DisplayScreen_Util(STL_PA_PM_UTIL_STATS * p_PmUtilStats, char * p_title) +{ + printf( "%-4s TotMBps AvgMBps MinMBps MaxMBps TotKPps AvgKPps MinKPps MaxKPps\n", + p_title ); + printf( " %10" PRIu64 " %8u %8u %8u %12" PRIu64 " %8u %8u %8u\n", + p_PmUtilStats->totalMBps, p_PmUtilStats->avgMBps, + p_PmUtilStats->minMBps != UINT_MAX ? p_PmUtilStats->minMBps : 0, + p_PmUtilStats->maxMBps, p_PmUtilStats->totalKPps, p_PmUtilStats->avgKPps, + p_PmUtilStats->minKPps != UINT_MAX ? p_PmUtilStats->minKPps : 0, + p_PmUtilStats->maxKPps ); + printf(" Buckt 0+%% 10+%% 20+%% 30+%% 40+%% 50+%% 60+%% 70+%% 80+%% 90+%%\n"); + printf(" %6u %6u %6u %6u %6u %6u %6u %6u %6u %6u\n", + p_PmUtilStats->BWBuckets[0], p_PmUtilStats->BWBuckets[1], + p_PmUtilStats->BWBuckets[2], p_PmUtilStats->BWBuckets[3], + p_PmUtilStats->BWBuckets[4], p_PmUtilStats->BWBuckets[5], + p_PmUtilStats->BWBuckets[6], p_PmUtilStats->BWBuckets[7], + p_PmUtilStats->BWBuckets[8], p_PmUtilStats->BWBuckets[9] ); + printf(" NoResp %-.3s Ports: PMA: %6u Topo: %6u\n", p_title, + p_PmUtilStats->pmaNoRespPorts, p_PmUtilStats->topoIncompPorts); + + return (5); + +} // End of DisplayScreen_Util() + +int DisplayScreen_VFGroup(STL_PA_VF_INFO_DATA* p_PmVfGrpInfo, int n_group) +{ + STL_PA_PM_UTIL_STATS *p_PmUtilStats = &p_PmVfGrpInfo->internalUtilStats; + char *p_state_integ, *p_color_integ; + char * p_state_congst, * p_color_congst; + char * p_state_smacong, * p_color_smacong; + char * p_state_bubble, * p_color_bubble; + char * p_state_secure, * p_color_secure; + char * p_state_routing, * p_color_routing; + + if (p_PmVfGrpInfo->numPorts == 0) + { + printf( "%d %-10.10s%c No ports in vf\n", n_group - g_scroll_summary, + p_PmVfGrpInfo->vfName, + strgetlastchar(p_PmVfGrpInfo->vfName, 10)); + return 1; + } + +#define VFEVAL_ERR_STAT(statistic, state, color) \ + if (p_PmVfGrpInfo->internalCategoryStats.ports[4].statistic > 0 ) \ + { state = "OVER"; color = bf_color_red; } \ + else if (p_PmVfGrpInfo->internalCategoryStats.ports[3].statistic > 0 )\ + { state = "Warn"; color = bf_color_yellow; } \ + else if (p_PmVfGrpInfo->internalCategoryStats.ports[2].statistic > 0 )\ + { state = "Mod"; color = bf_color_cyan; } \ + else if (p_PmVfGrpInfo->internalCategoryStats.ports[1].statistic > 0 )\ + { state = "Low"; color = bf_color_blue; } \ + else \ + { state = "min"; color = bf_color_green; } + + printf("%d %-10.10s%c Int %9u %9u %9u %9u %9u %9u\n", + n_group - g_scroll_vf_summary, + p_PmVfGrpInfo->vfName, + strgetlastchar(p_PmVfGrpInfo->vfName, 10), + p_PmUtilStats->avgMBps, + p_PmUtilStats->minMBps != UINT_MAX ? p_PmUtilStats->minMBps : 0, + p_PmUtilStats->maxMBps, p_PmUtilStats->avgKPps, + p_PmUtilStats->minKPps != UINT_MAX ? p_PmUtilStats->minKPps : 0, + p_PmUtilStats->maxKPps ); + + VFEVAL_ERR_STAT(integrityErrors, p_state_integ, p_color_integ); + VFEVAL_ERR_STAT(congestion, p_state_congst, p_color_congst); + VFEVAL_ERR_STAT(smaCongestion, p_state_smacong, p_color_smacong); + VFEVAL_ERR_STAT(bubble, p_state_bubble, p_color_bubble); + VFEVAL_ERR_STAT(securityErrors, p_state_secure, p_color_secure); + VFEVAL_ERR_STAT(routingErrors, p_state_routing, p_color_routing); + + printf( " %sInteg:%-4s%s %sCongst:%-4s%s %sSmaCong:%-4s%s %sBubble:%-4s%s %sSecure:%-4s%s %sRouting:%-4s%s\n", + p_color_integ, p_state_integ, bf_color_off, + p_color_congst, p_state_congst, bf_color_off, + p_color_smacong, p_state_smacong, bf_color_off, + p_color_bubble, p_state_bubble, bf_color_off, + p_color_secure, p_state_secure, bf_color_off, + p_color_routing, p_state_routing, bf_color_off ); + + return 2; +} + +// display the given help file and allow the user to scroll through it +// this is purposely kept simple since all our help files are less than +// 1KB and less than 100 lines (most are only 1-2 screens long). +// For security reasons, we don't want to callout to an external tool +// we expect the help text files to have newlines to limit lines to 80 columns +void DisplayScreen_Help(const char* helpfile) +{ + char help_text[MAX_HELP_CHARS]; + char *help_line[MAX_HELP_LINES]; // pointers into help_text + int fd; + int chars; + int lines; + int i; + char *p; + int cur_line; + + fd = open(helpfile, O_RDONLY); + if (fd < 0) + { + printf("Unable to open help file: %s: %s\n", helpfile, strerror(errno)); + printf("Press return to continue:\n"); + fgetc(stdin); + return; + } + // if file is too big silently ignore extra + chars = read(fd, help_text, MAX_HELP_CHARS-1); + if (chars < 0) + { + printf("Unable to read help file: %s: %s\n", helpfile, strerror(errno)); + printf("Press return continue:\n"); + fgetc(stdin); + close(fd); + return; + } + if (! chars) + { + printf("Help File empty: %s\n", helpfile); + printf("Press return to continue:\n"); + fgetc(stdin); + close(fd); + return; + } + help_text[chars] = '\0'; // null terminate + if (close(fd) < 0) + { + printf("Unable to close help file: %s: %s\n", helpfile, strerror(errno)); + printf("Press return to continue:\n"); + fgetc(stdin); + return; + } + // figure out where each line starts + // if we reach MAX_HELP_LINES, ignore the extra + for (lines=0, p=help_text; *p && lines< MAX_HELP_LINES;) + { + help_line[lines++] = p; + // find start of next line + p = strchr(p, '\n'); + if (! p) // file ended last line without a \n + break; + // replace \n with \0 so we can printf single lines + *p++ = '\0'; + } + + cur_line = 1; + if (lines > 0) while (TRUE) + { + // first line is a title of help page + printf("%s" NAME_PROG ": %s: Lines %3d-%3d of %3d\n", bf_clear_screen, + help_line[0], cur_line, MIN(cur_line+20, lines-1), lines-1); + for (i=0; i<21; i++) + { + if (cur_line+i < lines) + printf("%s\n", help_line[cur_line+i]); + else + printf("\n"); + } + // this command line is a little more verbose since it may be the + // first time user is reading help and learning how commands work + // scroll commands are nop on single screen help files,so omit in prompt + if (lines > 22) + printf("Press Command Key: u=up (done help) s=scroll fwd S=scroll back =next line:\n"); + else + printf("Press Command Key: u=up (done help):\n"); + switch (fgetc(stdin)) + { + case (int)(unsigned char)'u': + case (int)(unsigned char)'U': + case EOF: + return; + case (int)(unsigned char)'s': // scroll forward to next screen + if (cur_line+21 < lines) + cur_line+=21; + break; + case (int)(unsigned char)'S': // scross back to prev screen + if (cur_line <= 22) + cur_line = 1; + else + cur_line -= 21; + break; + case (int)(unsigned char)' ': // forward 1 line + if (cur_line+21 < lines) // no use scrolling on last screen + cur_line++; + break; + default: + // ignore input, redisplay at cur_line + break; + } + } // End of while (TRUE) +} + +void DisplayScreen(char *text_input) +{ + int ix; + int ct_lines; + time_t time_now = time(NULL); + char *p_select; + char bf_screen[81]; + + // Display help screens if requested + if (fb_help) + { + if (tb_menu[n_level_menu] == SCREEN_SUMMARY || + tb_menu[n_level_menu] == SCREEN_VF_SUMMARY) + DisplayScreen_Help(PATH_HELP "opatop_summary.hlp"); + else if (tb_menu[n_level_menu] == SCREEN_PM_CONFIG) + DisplayScreen_Help(PATH_HELP "opatop_pm_config.hlp"); + else if (tb_menu[n_level_menu] == SCREEN_IMAGE_INFO) + DisplayScreen_Help(PATH_HELP "opatop_img_config.hlp"); + else if (tb_menu[n_level_menu] == SCREEN_GROUP_INFO_SELECT) + DisplayScreen_Help(PATH_HELP "opatop_group_info_sel.hlp"); + else if (tb_menu[n_level_menu] == SCREEN_GROUP_BW_STATS) + DisplayScreen_Help(PATH_HELP "opatop_group_bw.hlp"); + else if (tb_menu[n_level_menu] == SCREEN_GROUP_CTG_STATS || + tb_menu[n_level_menu] == SCREEN_VF_CTG_STATS) + DisplayScreen_Help(PATH_HELP "opatop_group_ctg.hlp"); + else if (tb_menu[n_level_menu] == SCREEN_GROUP_CONFIG) + DisplayScreen_Help(PATH_HELP "opatop_group_config.hlp"); + else if (tb_menu[n_level_menu] == SCREEN_GROUP_FOCUS || + tb_menu[n_level_menu] == SCREEN_VF_FOCUS) + DisplayScreen_Help(PATH_HELP "opatop_group_focus.hlp"); + else if (tb_menu[n_level_menu] == SCREEN_PORT_STATS) + DisplayScreen_Help(PATH_HELP "opatop_port_stats.hlp"); + else if (tb_menu[n_level_menu] == SCREEN_VF_INFO_SELECT) + DisplayScreen_Help(PATH_HELP "opatop_vf_info_sel.hlp"); + else if (tb_menu[n_level_menu] == SCREEN_VF_BW_STATS) + DisplayScreen_Help(PATH_HELP "opatop_vf_bw.hlp"); + else if (tb_menu[n_level_menu] == SCREEN_VF_CONFIG) + DisplayScreen_Help(PATH_HELP "opatop_vf_config.hlp"); + else if (tb_menu[n_level_menu] == SCREEN_VF_PORT_STATS) + DisplayScreen_Help(PATH_HELP "opatop_vf_port_stats.hlp"); + + printf("Waiting for screen refresh...\n"); + fb_help = FALSE; + return; + } + + // Query for congestion data based on screen being displayed; + // Note that queries are done only for the data needed for a screen; + // Also note that when SCREEN_PORT_STATS has SCREEN_GROUP_FOCUS as its + // parent screen, GroupFocus data must not change + g_imageIdResp.imageNumber = PACLIENT_IMAGE_CURRENT; + g_imageIdResp.imageOffset = 0; + + if (!fb_valid_pa_client) + { + int pa_service_state = OMGT_SERVICE_STATE_UNKNOWN; + struct omgt_params params = { .debug_file = (g_verbose & VERBOSE_PACLIENT ? stderr : NULL) }; + if (!omgt_open_port_by_num(&g_portHandle, hfi, port, ¶ms)) + { + if (!omgt_port_get_pa_service_state(g_portHandle, &pa_service_state, OMGT_REFRESH_SERVICE_BAD_STATE)) + { + fb_valid_pa_client = (pa_service_state == OMGT_SERVICE_STATE_OPERATIONAL); + } + } + } + + if (!fb_valid_pa_cpi) { + if (omgt_pa_get_classportinfo(g_portHandle, &g_PaClassPortInfo) == FSUCCESS) { + + fb_valid_pa_cpi = TRUE; + + + fb_valid_pa_cpi_vf_focus_types = (g_PaClassPortInfo->CapMask & STL_PA_CPI_CAPMASK_VF_FOCUSTYPES ? TRUE : FALSE); + + fb_valid_pa_cpi_list2 = (g_PaClassPortInfo->CapMask & STL_PA_CPI_CAPMASK_IMAGE_LISTS ? TRUE : FALSE); + MemoryDeallocate(g_PaClassPortInfo); + } + } + + if (omgt_pa_get_image_info(g_portHandle, g_imageIdQuery, &g_PmImageInfo) == FSUCCESS) + fb_valid_image_info = TRUE; + else + { + fb_valid_pa_client = FALSE; + fb_valid_image_info = FALSE; + } + + if ( (tb_menu[n_level_menu] == SCREEN_PM_CONFIG) || + !fb_valid_pm_config ) + { + if (omgt_pa_get_pm_config(g_portHandle, &g_PmConfig) == FSUCCESS){ + fb_valid_pm_config = TRUE; + //Check if VF level Focus selects are supported + if (!fb_valid_pa_cpi_vf_focus_types || !(g_PmConfig.pmFlags & STL_PM_PROCESS_VL_COUNTERS)){ + g_utilVFArrayEndIdx = g_utilGroupArrayEndIdx; + g_ctgVFArrayEndIdx = g_ctgGroupArrayEndIdx; + g_focusVFArrayEndIdx = g_focusGroupArrayEndIdx; + } + } + else + fb_valid_pm_config = FALSE; + } + + if ((tb_menu[n_level_menu] == SCREEN_SUMMARY) || + (tb_menu[n_level_menu] == SCREEN_PM_CONFIG)) + { + FSTATUS status = FERROR; + if (fb_valid_pa_cpi_list2) { + omgt_pa_release_group_list2(&g_PmGroupList2.groupList); + status = omgt_pa_get_group_list2(g_portHandle, g_imageIdQuery, + &g_PmGroupList2.numGroups, &g_PmGroupList2.groupList); + g_PmGroupList.numGroups = g_PmGroupList2.numGroups; + } else { + omgt_pa_release_group_list(&g_PmGroupList.groupList); + status = omgt_pa_get_group_list(g_portHandle, &g_PmGroupList.numGroups, + &g_PmGroupList.groupList); + } + fb_valid_group_list = (status == FSUCCESS ? TRUE : FALSE); + } + + if (tb_menu[n_level_menu] == SCREEN_VF_SUMMARY) + { + FSTATUS status = FERROR; + if (fb_valid_pa_cpi_list2) { + omgt_pa_release_vf_list2(&g_PmVFList2.vfList); + status = omgt_pa_get_vf_list2(g_portHandle, g_imageIdQuery, + &g_PmVFList2.numVFs, &g_PmVFList2.vfList); + g_PmVFList.numVFs = g_PmVFList2.numVFs; + } else { + omgt_pa_release_vf_list(&g_PmVFList.vfList); + status = omgt_pa_get_vf_list(g_portHandle, &g_PmVFList.numVFs, + &g_PmVFList.vfList); + } + fb_valid_VF_list = (status == FSUCCESS ? TRUE : FALSE); + } + + if ( (tb_menu[n_level_menu] == SCREEN_GROUP_INFO_SELECT) || + (tb_menu[n_level_menu] == SCREEN_GROUP_BW_STATS) || + (tb_menu[n_level_menu] == SCREEN_GROUP_CTG_STATS) || + (tb_menu[n_level_menu] == SCREEN_GROUP_FOCUS) ) + { + if ( fb_valid_group_list && ( omgt_pa_get_group_info( g_portHandle, g_imageIdQuery, + GROUPNAME(g_group), &g_imageIdResp, &g_PmGroupInfo) == FSUCCESS ) ) + fb_valid_group_info = TRUE; + else + fb_valid_group_info = FALSE; + } + + if (tb_menu[n_level_menu] == SCREEN_VF_INFO_SELECT || + tb_menu[n_level_menu] == SCREEN_VF_BW_STATS || + tb_menu[n_level_menu] == SCREEN_VF_CTG_STATS || + tb_menu[n_level_menu] == SCREEN_VF_FOCUS) { + if (fb_valid_VF_list) { + OMGT_QUERY query = {0}; + PQUERY_RESULT_VALUES pQueryResults = NULL; + + query.InputType = InputTypeNoInput; + query.OutputType = OutputTypePaTableRecord; + + if (iba_pa_multi_mad_vf_info_response_query(g_portHandle, &query, VFNAME(g_vf), + &pQueryResults, &g_imageIdResp) == FSUCCESS) { + + g_PmVFInfo = ((STL_PA_VF_INFO_RESULTS*)pQueryResults->QueryResult)->VFInfoRecords[0]; + fb_valid_VF_info = TRUE; + } else fb_valid_VF_info = FALSE; + } else fb_valid_VF_info = FALSE; + } + + // Do default query to get g_imageIdResp + if ((g_group < 0) && fb_valid_group_list) + omgt_pa_get_group_info(g_portHandle, g_imageIdQuery, GROUPNAME(0), + &g_imageIdResp, &g_PmGroupInfo); + + if (tb_menu[n_level_menu] == SCREEN_GROUP_CONFIG) + { + omgt_pa_release_group_config(&pg_PmGroupConfig.portList); + if (fb_valid_group_list && (omgt_pa_get_group_config(g_portHandle, g_imageIdQuery, + GROUPNAME(g_group), &g_imageIdResp, &pg_PmGroupConfig.numPorts, + &pg_PmGroupConfig.portList) == FSUCCESS)) + { + fb_valid_group_config = TRUE; + strcpy(pg_PmGroupConfig.groupName, GROUPNAME(g_group)); + } + else + fb_valid_group_config = FALSE; + } + + if (tb_menu[n_level_menu] == SCREEN_VF_CONFIG) { + omgt_pa_release_vf_config(&g_pPmVFConfig.portList); + if (fb_valid_VF_list && (omgt_pa_get_vf_config(g_portHandle, g_imageIdQuery, + VFNAME(g_vf), &g_imageIdResp, &g_pPmVFConfig.numPorts, &g_pPmVFConfig.portList) == FSUCCESS)) + { + fb_valid_VF_config = TRUE; + strcpy(g_pPmVFConfig.vfName, VFNAME(g_vf)); + } + else fb_valid_VF_config = FALSE; + } + + if (tb_menu[n_level_menu] == SCREEN_GROUP_FOCUS) + { + omgt_pa_release_group_focus(&pg_PmGroupFocus.portList); + if (fb_valid_group_list && (omgt_pa_get_group_focus(g_portHandle, g_imageIdQuery, + GROUPNAME(g_group), g_select, g_start, g_range, &g_imageIdResp, + &pg_PmGroupFocus.numPorts, &pg_PmGroupFocus.portList) == FSUCCESS)) + { + fb_valid_group_focus = TRUE; + strcpy(pg_PmGroupFocus.groupName, GROUPNAME(g_group)); + } + else + fb_valid_group_focus = FALSE; + + pg_PmGroupFocus.select = g_select; + pg_PmGroupFocus.start = g_start; + pg_PmGroupFocus.range = g_range; + } + + if (tb_menu[n_level_menu] == SCREEN_VF_FOCUS) { + + omgt_pa_release_vf_focus(&g_pPmVFFocus.portList); + if (fb_valid_VF_list && (omgt_pa_get_vf_focus(g_portHandle, g_imageIdQuery, + VFNAME(g_vf), g_select, g_start, g_range, &g_imageIdResp, + &g_pPmVFFocus.numPorts, &g_pPmVFFocus.portList) == FSUCCESS)) + { + fb_valid_VF_focus = TRUE; + strcpy(g_pPmVFFocus.vfName, VFNAME(g_vf)); + } + else + fb_valid_VF_focus = FALSE; + + g_pPmVFFocus.select = g_select; + g_pPmVFFocus.start = g_start; + g_pPmVFFocus.range = g_range; + } + + if (tb_menu[n_level_menu] == SCREEN_PORT_STATS) + { + fb_valid_port_stats = FALSE; + + { + if ( omgt_pa_get_port_stats2(g_portHandle, g_imageIdQuery, g_portlid, g_portnum, + &g_imageIdResp, &g_portCounters, &g_portCounterFlags, 1, 0) == FSUCCESS) { + fb_valid_port_stats = TRUE; + } + } + if (fb_valid_port_stats && (g_PmConfig.pmFlags & STL_PM_PROCESS_VL_COUNTERS) && + omgt_pa_get_vf_port_stats2(g_portHandle, g_imageIdQuery, "HIDDEN_VL15_VF", + g_portlid, g_portnum, &g_imageIdResp, &g_hiddenVfPortCounters, + &g_hiddenVfPortCounterFlags, 1, 0 ) == FSUCCESS ) { + fb_valid_vf_port_stats_hidden = TRUE; + } else { + fb_valid_vf_port_stats_hidden = FALSE; + } + } + if (tb_menu[n_level_menu] == SCREEN_VF_PORT_STATS) + { + fb_valid_VF_port_counters = FALSE; + if ( omgt_pa_get_vf_port_stats2(g_portHandle, g_imageIdQuery, VFNAME(g_vf), + g_portlid, g_portnum, &g_imageIdResp, &g_vfPortCounters, + &g_vfPortCounterFlags, 1, 0 ) == FSUCCESS ) { + fb_valid_VF_port_counters = TRUE; + } + } + + + // Display header lines + if (fb_valid_image_info) + { + if (g_PmImageInfo.imageInterval) { + // Display ImageInterval if present + snprintf(bf_screen, sizeof(bf_screen), " %us @ %s", g_PmImageInfo.imageInterval, + ctime((time_t *)&g_PmImageInfo.sweepStart)); + } else { + snprintf(bf_screen, sizeof(bf_screen), " %s", ctime((time_t *)&g_PmImageInfo.sweepStart)); + } + // replace '\n' character with '\0' + bf_screen[strlen(bf_screen) - 1] = 0; + + if (g_imageIdQuery.imageNumber == PACLIENT_IMAGE_CURRENT) + { + sprintf(&bf_screen[strlen(bf_screen)], ", Live"); + + if (g_debug & DEBUG_IMGID) + sprintf( &bf_screen[strlen(bf_screen)], " (0x%016" PRIX64 ",%d)", + g_imageIdQuery.imageNumber, g_imageIdQuery.imageOffset ); + + strcat(bf_screen, "\n"); + } + + else if (g_imageIdFreeze.imageNumber != PACLIENT_IMAGE_CURRENT) + { + if (g_verbose & VERBOSE_SCREEN) + sprintf(&bf_screen[strlen(bf_screen)], ", %d", g_offset); + else + sprintf(&bf_screen[strlen(bf_screen)], ", Hist"); + + if (g_debug & DEBUG_IMGID) + sprintf( &bf_screen[strlen(bf_screen)], " (0x%016" PRIX64 ",%d)", + g_imageIdFreeze.imageNumber, g_imageIdFreeze.imageOffset ); + + sprintf(&bf_screen[strlen(bf_screen)], " Now:%s", ctime(&time_now)); + } + + else if (g_imageIdBookmark.imageNumber != PACLIENT_IMAGE_CURRENT) + { + sprintf(&bf_screen[strlen(bf_screen)], ", Bkmk"); + + if (g_debug & DEBUG_IMGID) + sprintf( &bf_screen[strlen(bf_screen)], " (0x%016" PRIX64 ",%d)", + g_imageIdBookmark.imageNumber, g_imageIdBookmark.imageOffset ); + + sprintf(&bf_screen[strlen(bf_screen)], " Now:%s", ctime(&time_now)); + } + + printf("%s" NAME_PROG ": Img:%s", bf_clear_screen, bf_screen); + } + + else + printf( "%s" NAME_PROG ": IMAGE SUMMARY NOT AVAILABLE\n", + bf_clear_screen ); + + ct_lines = MAX_LINES_PER_SCREEN - 1 - 2; // -1 for head, 2 for menu + if (g_debug & DEBUG_GROUP) + ct_lines += 1; + if (g_debug & DEBUG_IMGID_2) + ct_lines += 4; + + if (g_debug & DEBUG_IMGID_2) + { + printf( " ImgRsp:0x%" PRIX64 ",%d\n", g_imageIdResp.imageNumber, + g_imageIdResp.imageOffset ); + printf( " ImgFrz:0x%" PRIX64 ",%d\n", + g_imageIdFreeze.imageNumber, g_imageIdFreeze.imageOffset ); + printf( " ImgBkm:0x%" PRIX64 ",%d\n", + g_imageIdBookmark.imageNumber, g_imageIdBookmark.imageOffset ); + printf( " ImgTmp:0x%" PRIX64 ",%d\n", g_imageIdTemp.imageNumber, + g_imageIdTemp.imageOffset ); + ct_lines -= 4; + } + + if (g_debug & DEBUG_GROUP) + { + printf( "Interval:%u Grp:%d PortIx:%d Offset:%d\n", ct_interval, + g_group, g_ix_port, g_offset ); + ct_lines -= 1; + } + + // Display selected screen + switch (tb_menu[n_level_menu]) + { + case SCREEN_SUMMARY: + if (fb_valid_image_info) + { + char* status_color = bf_color_off; + char* status_message = ""; + + printf( "Summary: SW: %5u Ports: SW: %5u HFI: %5u Link: %5u\n", + g_PmImageInfo.numSwitchNodes, g_PmImageInfo.numSwitchPorts, + g_PmImageInfo.numHFIPorts, g_PmImageInfo.numLinks); + printf( " SM: %5u Node NRsp: %5u Skip: %5u Port NRsp: %5u Skip: %5u\n", + g_PmImageInfo.numSMs, g_PmImageInfo.numNoRespNodes, + g_PmImageInfo.numSkippedNodes, g_PmImageInfo.numNoRespPorts, + g_PmImageInfo.numSkippedPorts ); + if (g_PmImageInfo.numUnexpectedClearPorts) { + status_color = bf_color_red; + status_message = "Unexpected Clear"; + } + printf("%s%-17s%s AvgMBps MinMBps MaxMBps AvgKPps MinKPps MaxKPps\n", + status_color, status_message, bf_color_off); + ct_lines -= 3; + + if ( fb_valid_group_list && g_PmGroupList.numGroups ) + { + // if PM groups we were showing are removed, go to last + if (g_scroll_summary >= g_PmGroupList.numGroups) + g_scroll_summary = g_PmGroupList.numGroups-1; + // compute how far we can scroll back + int ct_group_lines = MAX_SUMMARY_GROUP_LINES_PER_SCREEN; + g_scroll_summary_backward = 0; // default if at start + for (ix = g_scroll_summary-1; ix >= 0; ix--) + { + if ( omgt_pa_get_group_info(g_portHandle, g_imageIdQuery, + GROUPNAME(ix), &g_imageIdResp, + &g_PmGroupInfo) == FSUCCESS ) + ct_group_lines -= ScreenLines_Group(&g_PmGroupInfo, ix); + if (ct_group_lines >= 0) + g_scroll_summary_backward = ix; // can go here + else + break; + } + // display what fits and save scroll forward point + ct_group_lines = MAX_SUMMARY_GROUP_LINES_PER_SCREEN; + g_scroll_summary_forward = g_scroll_summary; // initialize + for (ix = g_scroll_summary; ix < g_PmGroupList.numGroups; ix++) + { + if ( omgt_pa_get_group_info(g_portHandle, g_imageIdQuery, + GROUPNAME(ix), &g_imageIdResp, + &g_PmGroupInfo) == FSUCCESS ) + { + // only output if it will fit + ct_group_lines -= ScreenLines_Group(&g_PmGroupInfo, ix); + g_scroll_summary_forward = ix; // go here if scroll fwd + if (ct_group_lines < 0) + break; + ct_lines -= DisplayScreen_Group(&g_PmGroupInfo, ix); + } + } + } + + else + { + printf("Summary: GROUP LIST NOT AVAILABLE\n"); + ct_lines -= 1; + } + + // put SM at bottom of screen (6 lines), leave 1 line for bf_error + // and 1 for extra menu line + for ( ; ct_lines > 8; ct_lines--) + printf("\n"); + + ct_lines -= DisplayScreen_SMs(); + } + + else + { + printf("Summary: IMAGE INFO NOT AVAILABLE\n"); + ct_lines -= 1; + } + + break; + + case SCREEN_VF_SUMMARY: + if (fb_valid_VF_list) { + char* status_color = bf_color_off; + char* status_message = ""; + + printf( "Summary: SW: %5u Ports: SW: %5u HFI: %5u Link: %5u\n", + g_PmImageInfo.numSwitchNodes, g_PmImageInfo.numSwitchPorts, + g_PmImageInfo.numHFIPorts, g_PmImageInfo.numLinks); + printf( " SM: %5u Node NRsp: %5u Skip: %5u Port NRsp: %5u Skip: %5u\n", + g_PmImageInfo.numSMs, g_PmImageInfo.numNoRespNodes, + g_PmImageInfo.numSkippedNodes, g_PmImageInfo.numNoRespPorts, + g_PmImageInfo.numSkippedPorts ); + if (g_PmImageInfo.numUnexpectedClearPorts) { + status_color = bf_color_red; + status_message = "Unexpected Clear"; + } + printf("%s%-17s%s AvgMBps MinMBps MaxMBps AvgKPps MinKPps MaxKPps\n", + status_color, status_message, bf_color_off); + ct_lines -= 3; + + if (g_PmVFList.numVFs < 1) { + printf("Summary: VF LIST NOT AVAILABLE\n"); + ct_lines -= 1; + } else { + // if VFs we were showing are removed, go to last + if (g_scroll_vf_summary >= g_PmVFList.numVFs) + g_scroll_vf_summary = g_PmVFList.numVFs-1; + for (ix = g_scroll_vf_summary; ix < MIN(g_scroll_vf_summary + MAX_VF_SUMMARY_PER_SCREEN, g_PmVFList.numVFs) ; ++ix) { + OMGT_QUERY query = {0}; + PQUERY_RESULT_VALUES pQueryResults = NULL; + + query.InputType = InputTypeNoInput; + query.OutputType = OutputTypePaTableRecord; + + if (iba_pa_multi_mad_vf_info_response_query(g_portHandle, &query, VFNAME(ix), + &pQueryResults, &g_imageIdResp) == FSUCCESS) { + STL_PA_VF_INFO_DATA *p = &((STL_PA_VF_INFO_RESULTS*)pQueryResults->QueryResult)->VFInfoRecords[0]; + ct_lines -= DisplayScreen_VFGroup(p, ix); + } + } + } + + // put SM at bottom of screen (6 lines), leave 1 line for bf_error + // and 1 for extra menu line + for ( ; ct_lines > 8; ct_lines--) + printf("\n"); + + ct_lines -= DisplayScreen_SMs(); + } + + break; + + case SCREEN_PM_CONFIG: + if (fb_valid_pm_config) + { + char buf[80]; + + printf( "PM Config:\n" ); + printf( " Sweep Interval: %u sec PM Flags(0x%X):\n", + g_PmConfig.sweepInterval, g_PmConfig.pmFlags); + StlFormatPmFlags(buf, g_PmConfig.pmFlags); + printf( " %s\n", buf); + StlFormatPmFlags2(buf, g_PmConfig.pmFlags); + printf( " %s\n", buf); + printf( " Max Clients: %7u\n", g_PmConfig.maxClients); + printf( " Total Images: %7u Freeze Images: %-7u Freeze Lease: %u seconds\n", + g_PmConfig.sizeHistory, g_PmConfig.sizeFreeze, g_PmConfig.lease ); + printf( " Ctg Thresholds: Integrity: %4u Congestion: %4u\n", + g_PmConfig.categoryThresholds.integrityErrors, + g_PmConfig.categoryThresholds.congestion ); + printf( " SmaCongest: %4u Bubble: %4u\n", + g_PmConfig.categoryThresholds.smaCongestion, + g_PmConfig.categoryThresholds.bubble ); + printf( " Security: %4u Routing: %4u\n", + g_PmConfig.categoryThresholds.securityErrors, + g_PmConfig.categoryThresholds.routingErrors ); + printf( " Integrity Wts: Link Qual: %4u Uncorrectable: %4u\n", + g_PmConfig.integrityWeights.LinkQualityIndicator, + g_PmConfig.integrityWeights.UncorrectableErrors ); + printf( " Link Downed: %4u Rcv Errors: %4u\n", + g_PmConfig.integrityWeights.LinkDowned, + g_PmConfig.integrityWeights.PortRcvErrors ); + printf( " Excs Bfr Ovrn: %4u FM Config Err: %4u\n", + g_PmConfig.integrityWeights.ExcessiveBufferOverruns, + g_PmConfig.integrityWeights.FMConfigErrors ); + printf( " Link Err Reco: %4u Loc Link Integ:%4u\n", + g_PmConfig.integrityWeights.PortRcvErrors, + g_PmConfig.integrityWeights.LocalLinkIntegrityErrors); + printf( " Lnk Wdth Dngd: %4u \n", + g_PmConfig.integrityWeights.LinkWidthDowngrade ); + printf( " Congest Wts: Cong Discards: %4u Rcv FECN: %4u\n", + g_PmConfig.congestionWeights.SwPortCongestion, + g_PmConfig.congestionWeights.PortRcvFECN); + printf( " Rcv BECN: %4u Mark FECN: %4u\n", + g_PmConfig.congestionWeights.PortRcvBECN, + g_PmConfig.congestionWeights.PortMarkFECN); + printf( " Xmit Time Cong: %4u Xmit Wait: %4u \n", + g_PmConfig.congestionWeights.PortXmitTimeCong, + g_PmConfig.congestionWeights.PortXmitWait); + printf( " PM Memory Size: %"PRIu64" MB (%" PRIu64 " bytes)\n", + g_PmConfig.memoryFootprint/(1000*1000), + g_PmConfig.memoryFootprint ); + printf( " PMA MADs: MaxAttempts: %3u MinRespTimeout: %3u RespTimeout: %4u\n", + g_PmConfig.maxAttempts, g_PmConfig.minRespTimeout, g_PmConfig.respTimeout ); + printf( " Sweep: MaxParallelNodes: %3u PmaBatchSize: %3u ErrorClear: %4u\n", + g_PmConfig.maxParallelNodes, g_PmConfig.pmaBatchSize, + g_PmConfig.errorClear); + ct_lines -= 20; + } + else + { + printf("PM Config: PM CONFIG NOT AVAILABLE\n"); + ct_lines -= 1; + } + + if (g_verbose & VERBOSE_SCREEN_2) + { + printf("\n" NAME_PROG " Config:\n"); + printf(" Interval: %7u seconds PortGUID: 0x%016" PRIX64 "\n", + g_interval, g_portGuid ); + printf(" Verbose: 0x%04X", g_verbose); + + if (g_debug) + printf(" Debug:0x%04X\n", g_debug); + else + printf("\n"); + + printf(" NumGroups: %5u\n", g_PmGroupList.numGroups); + printf(" Quiet: %5s\n", g_quiet ? "TRUE" : "FALSE"); + ct_lines -= 6; + } + + break; + + case SCREEN_IMAGE_INFO: + if (fb_valid_image_info) + { + printf("Image Info:\n"); + ct_lines -= 1; + + if (g_debug & DEBUG_IMGID) + { + printf( " Img Number: 0x%" PRIX64 ", Offset: %d\n", + g_PmImageInfo.imageId.imageNumber, + g_PmImageInfo.imageId.imageOffset ); + ct_lines -= 1; + } + + printf(" Sweep Start: %s", ctime((time_t *)&g_PmImageInfo.sweepStart)); + + if (g_verbose & VERBOSE_SCREEN) + printf( " Sweep Duration: %8.6f Seconds\n", + (float)g_PmImageInfo.sweepDuration / 1000000. ); + else + printf( " Sweep Duration: %5.3f Seconds\n", + (float)g_PmImageInfo.sweepDuration / 1000000. ); + + if (g_PmImageInfo.imageInterval) { + printf(" Image Interval: %u Seconds\n\n", g_PmImageInfo.imageInterval); + } else { + printf("\n\n"); + } + + printf( " Num SW-Ports: %7u HFI-Ports: %7u\n", + g_PmImageInfo.numSwitchPorts, g_PmImageInfo.numHFIPorts); + printf( " Num SWs: %7u Num Links: %7u Num SMs: %7u\n\n", + g_PmImageInfo.numSwitchNodes, g_PmImageInfo.numLinks, + g_PmImageInfo.numSMs ); + printf( " Num NRsp Nodes: %7u Ports: %7u Unexpected Clear Ports: %u\n", + g_PmImageInfo.numNoRespNodes, g_PmImageInfo.numNoRespPorts, + g_PmImageInfo.numUnexpectedClearPorts); + printf( " Num Skip Nodes: %7u Ports: %7u\n\n", + g_PmImageInfo.numSkippedNodes, g_PmImageInfo.numSkippedPorts ); + ct_lines -= 10; + + ct_lines -= DisplayScreen_SMs(); + } + + else + { + printf("Image Info: IMAGE INFO NOT AVAILABLE\n"); + ct_lines -= 1; + } + + break; + + case SCREEN_GROUP_INFO_SELECT: + if (fb_valid_group_info) + { + printf( "Group Info Sel: %s\n", g_PmGroupInfo.groupName); + if (g_PmGroupInfo.minInternalRate != IB_STATIC_RATE_DONTCARE + || g_PmGroupInfo.maxInternalRate != IB_STATIC_RATE_DONTCARE) + printf( "Int NumPorts: %u Rate Min: %4s Max: %4s\n", + g_PmGroupInfo.numInternalPorts, + StlStaticRateToText(g_PmGroupInfo.minInternalRate), + StlStaticRateToText(g_PmGroupInfo.maxInternalRate)); + else + printf( "Int NumPorts: %u\n", g_PmGroupInfo.numInternalPorts); + + if (g_PmGroupInfo.minExternalRate != IB_STATIC_RATE_DONTCARE + || g_PmGroupInfo.maxExternalRate != IB_STATIC_RATE_DONTCARE) + printf( "Ext NumPorts: %u Rate Min: %4s Max: %4s\n", + g_PmGroupInfo.numExternalPorts, + StlStaticRateToText(g_PmGroupInfo.minExternalRate), + StlStaticRateToText(g_PmGroupInfo.maxExternalRate)); + else + printf( "Ext NumPorts: %u\n", g_PmGroupInfo.numExternalPorts); + printf(" Group Performance (P)\n"); + printf(" Group Statistics (S)\n"); + printf(" Group Config (C)\n"); + ct_lines -= 6; + } + + else + { + printf("Group Info Select: GROUP INFO NOT AVAILABLE\n"); + ct_lines -= 1; + } + + break; + case SCREEN_VF_INFO_SELECT: + if (fb_valid_VF_info) { + printf("VF Info Select: %s\n", g_PmVFInfo.vfName); + if (g_PmVFInfo.minInternalRate != IB_STATIC_RATE_DONTCARE + || g_PmVFInfo.maxInternalRate != IB_STATIC_RATE_DONTCARE) + printf( "NumPorts: %u Rate Min: %4s Max: %4s\n", + g_PmVFInfo.numPorts, + StlStaticRateToText(g_PmVFInfo.minInternalRate), + StlStaticRateToText(g_PmVFInfo.maxInternalRate)); + else + printf( "NumPorts: %u\n", g_PmVFInfo.numPorts); + + printf(" Group Performance (P)\n"); + printf(" Group Statistics (S)\n"); + printf(" Group Config (C)\n"); + ct_lines -= 5; + } else { + printf("VF Info Select: VF INFO NOT AVAILABLE\n"); + ct_lines -= 1; + } + break; + + case SCREEN_GROUP_BW_STATS: + if (fb_valid_group_info) + { + if (g_select == STL_PA_SELECT_UTIL_PKTS_HIGH) + p_select = "UtlPkt-Hi"; + else if (g_select == STL_PA_SELECT_UTIL_LOW) + p_select = "Util-Low"; +// Future enhancement +#if 0 + else if (g_select == PACLIENT_SEL_ALL) + p_select = "ALL"; +#endif + else + { + g_select = STL_PA_SELECT_UTIL_HIGH; + p_select = "Util-High"; + } + + printf( "Group BW Util: %-.44s%s Criteria: %s", + g_PmGroupInfo.groupName, + strgetlaststr(g_PmGroupInfo.groupName, 44), + p_select ); + if (g_expr_funct) + printf(" Start: %d", g_start); + printf(" Number: %d\n", g_range); + ct_lines -= 1; + + if (g_PmGroupInfo.numInternalPorts) + ct_lines -= DisplayScreen_Util(&g_PmGroupInfo.internalUtilStats, "Int:"); + + if (g_PmGroupInfo.numExternalPorts) + { + ct_lines -= DisplayScreen_Util(&g_PmGroupInfo.sendUtilStats, "Snd:"); + ct_lines -= 1; + ct_lines -= DisplayScreen_Util(&g_PmGroupInfo.recvUtilStats, "Rcv:"); + } + + + if (g_PmGroupInfo.numInternalPorts == 0 + && g_PmGroupInfo.numExternalPorts == 0) + { + printf("\n"); + printf( "No ports in group\n"); + ct_lines -= 2; + } else { + printf("\n"); + printf(" Max 0+%% 25+%% 50+%% 75+%% 100+%%\n"); + ct_lines-=2; + + if (g_PmGroupInfo.numInternalPorts) { + printf( "Int Congestion %10u %9u %9u %9u %9u %9u\n", + g_PmGroupInfo.internalCategoryStats.categoryMaximums.congestion, + g_PmGroupInfo.internalCategoryStats.ports[0].congestion, + g_PmGroupInfo.internalCategoryStats.ports[1].congestion, + g_PmGroupInfo.internalCategoryStats.ports[2].congestion, + g_PmGroupInfo.internalCategoryStats.ports[3].congestion, + g_PmGroupInfo.internalCategoryStats.ports[4].congestion ); + ct_lines-=1; + } + + if (g_PmGroupInfo.numExternalPorts) { + printf( "Ext Congestion %10u %9u %9u %9u %9u %9u\n", + g_PmGroupInfo.externalCategoryStats.categoryMaximums.congestion, + g_PmGroupInfo.externalCategoryStats.ports[0].congestion, + g_PmGroupInfo.externalCategoryStats.ports[1].congestion, + g_PmGroupInfo.externalCategoryStats.ports[2].congestion, + g_PmGroupInfo.externalCategoryStats.ports[3].congestion, + g_PmGroupInfo.externalCategoryStats.ports[4].congestion ); + ct_lines -=1; + } + } + } + + else + { + printf("Group BW Util: GROUP INFO NOT AVAILABLE\n"); + ct_lines -= 1; + } + + break; + case SCREEN_VF_BW_STATS: + if (fb_valid_VF_info) { + if (g_select == STL_PA_SELECT_UTIL_PKTS_HIGH) + p_select = "UtlPkt-Hi"; + else if (g_select == STL_PA_SELECT_UTIL_LOW) + p_select = "Util-Low"; + else if (g_select == STL_PA_SELECT_VF_UTIL_PKTS_HIGH) + p_select = "VF-Pkt-Hi"; + else if (g_select == STL_PA_SELECT_VF_UTIL_LOW) + p_select = "VF-Ut-Low"; + else if (g_select == STL_PA_SELECT_VF_UTIL_HIGH) + p_select = "VF-Ut-Hi"; +// Future enhancement +#if 0 + else if (g_select == PACLIENT_SEL_ALL) + p_select = "ALL"; +#endif + else + { + g_select = STL_PA_SELECT_UTIL_HIGH; + p_select = "Util-High"; + } + + printf("VF BW Util: %-.45s%s Criteria: %s", + g_PmVFInfo.vfName, + strgetlaststr(g_PmVFInfo.vfName, 45), + p_select); + if (g_expr_funct) + printf(" Start: %d", g_start); + printf(" Number: %d\n", g_range); + ct_lines -= 1; + + if (g_PmVFInfo.numPorts == 0) + { + printf("\n"); + printf( "No ports in vf\n"); + ct_lines -= 2; + } + else { + ct_lines -= DisplayScreen_Util(&g_PmVFInfo.internalUtilStats, "Int:"); + printf("\n"); + printf(" Max 0+%% 25+%% 50+%% 75+%% 100+%%\n"); + ct_lines -=2; + printf( "Int Congestion %10u %9u %9u %9u %9u %9u\n", + g_PmVFInfo.internalCategoryStats.categoryMaximums.congestion, + g_PmVFInfo.internalCategoryStats.ports[0].congestion, + g_PmVFInfo.internalCategoryStats.ports[1].congestion, + g_PmVFInfo.internalCategoryStats.ports[2].congestion, + g_PmVFInfo.internalCategoryStats.ports[3].congestion, + g_PmVFInfo.internalCategoryStats.ports[4].congestion ); + ct_lines-=1; + } + } else { + printf("VF BW Util: VF INFO NOT AVAILABLE\n"); + ct_lines -= 1; + } + + break; + + case SCREEN_GROUP_CTG_STATS: + if (fb_valid_group_info) + { + if (g_select == STL_PA_SELECT_CATEGORY_CONG) + p_select = "Congst"; + else if (g_select == STL_PA_SELECT_CATEGORY_SMA_CONG) + p_select = "SmaCong"; + else if (g_select == STL_PA_SELECT_CATEGORY_BUBBLE) + p_select = "Bubble"; + else if (g_select == STL_PA_SELECT_CATEGORY_SEC) + p_select = "Secure"; + else if (g_select == STL_PA_SELECT_CATEGORY_ROUT) + p_select = "Routing"; +// Future enhancement +#if 0 + else if (g_select == PACLIENT_SEL_ALL) + p_select = "ALL"; +#endif + else + { + g_select = STL_PA_SELECT_CATEGORY_INTEG; + p_select = "Integ"; + } + + printf( "Group Ctg Stats: %-.43s%s Criteria: %s", + g_PmGroupInfo.groupName, + strgetlaststr(g_PmGroupInfo.groupName, 43), + p_select ); + if (g_expr_funct) + printf(" Start: %d", g_start); + printf(" Number: %d\n", g_range); + ct_lines -= 1; + + if (g_PmGroupInfo.numInternalPorts) + ct_lines -= DisplayScreen_Err(&g_PmGroupInfo.internalCategoryStats, "Int"); + + if (g_PmGroupInfo.numExternalPorts) + { + printf("\n"); + ct_lines -= 1; + ct_lines -= DisplayScreen_Err(&g_PmGroupInfo.externalCategoryStats, "Ext"); + } + + if (g_PmGroupInfo.numInternalPorts == 0 + && g_PmGroupInfo.numExternalPorts == 0) + { + printf("\n"); + printf( "No ports in group\n"); + ct_lines -= 2; + } + } + + else + { + printf("Group Ctg Stats: GROUP INFO NOT AVAILABLE\n"); + ct_lines -= 1; + } + + break; + + case SCREEN_VF_CTG_STATS: + if (fb_valid_VF_info) { + if (g_select == STL_PA_SELECT_CATEGORY_CONG) + p_select = "Congst"; + else if (g_select == STL_PA_SELECT_CATEGORY_SMA_CONG) + p_select = "SmaCong"; + else if (g_select == STL_PA_SELECT_CATEGORY_BUBBLE) + p_select = "Bubble"; + else if (g_select == STL_PA_SELECT_CATEGORY_SEC) + p_select = "Secure"; + else if (g_select == STL_PA_SELECT_CATEGORY_ROUT) + p_select = "Routing"; + else if (g_select == STL_PA_SELECT_CATEGORY_VF_CONG) + p_select = "VF Congst"; + else if (g_select == STL_PA_SELECT_CATEGORY_VF_BUBBLE) + p_select = "VF Bubble"; +// Future enhancement +#if 0 + else if (g_select == PACLIENT_SEL_ALL) + p_select = "ALL"; +#endif + else + { + g_select = STL_PA_SELECT_CATEGORY_INTEG; + p_select = "Integ"; + } + + printf("VF Ctg Stats: %-.46s%s Criteria: %s", + g_PmVFInfo.vfName, + strgetlaststr(g_PmVFInfo.vfName, 46), + p_select); + if (g_expr_funct) + printf(" Start: %d", g_start); + printf(" Number: %d\n", g_range); + ct_lines -= 1; + + if (g_PmVFInfo.numPorts == 0) + { + printf("\n"); + printf( "No ports in vf\n"); + ct_lines -= 2; + } + else { + ct_lines -= DisplayScreen_Err(&g_PmVFInfo.internalCategoryStats, "Int"); + } + } else { + printf("VF Ctg Stats: VF INFO NOT AVAILABLE\n"); + ct_lines -= 1; + } + + break; + + case SCREEN_GROUP_CONFIG: + if (fb_valid_group_config) + { + printf( "Group Config: %-.45s%s NumPorts: %u\n", + pg_PmGroupConfig.groupName, + strgetlaststr(pg_PmGroupConfig.groupName, 45), + pg_PmGroupConfig.numPorts ); + printf(" Idx LID 0x Port Node GUID 0x NodeDesc\n"); + ct_lines -= 2; + + // if ports we were showing are removed, go to last port + if (g_scroll >= pg_PmGroupConfig.numPorts) + g_scroll = pg_PmGroupConfig.numPorts-1; + for ( ix = g_scroll; (ix < pg_PmGroupConfig.numPorts) && + ((ix - g_scroll) < MAX_GROUPCONFIG_PORTS_PER_SCREEN); ix++ ) + { + // Truncate nodeDesc to keep line at 80 columns + printf( "%5d %.*X %3u %016" PRIX64 " %-.42s%s\n", ix, + (pg_PmGroupConfig.portList[ix].nodeLid <= IB_MAX_UCAST_LID ? 4:8), + pg_PmGroupConfig.portList[ix].nodeLid, + pg_PmGroupConfig.portList[ix].portNumber, + pg_PmGroupConfig.portList[ix].nodeGUID, + pg_PmGroupConfig.portList[ix].nodeDesc, + strgetlaststr(pg_PmGroupConfig.portList[ix].nodeDesc, 42) ); + ct_lines -= 1; + } + + } + else if (fb_valid_group_info && + g_PmGroupInfo.numInternalPorts == 0 && + g_PmGroupInfo.numExternalPorts == 0) + { + printf("\n"); + printf( "No ports in group\n"); + ct_lines -= 2; + } + else + { + printf("Group Config: GROUP CONFIG NOT AVAILABLE\n"); + ct_lines -= 1; + } + + break; + + case SCREEN_VF_CONFIG: + if (fb_valid_VF_config) { + printf("VF Config: %-.45s%s NumPorts: %u\n", + g_pPmVFConfig.vfName, + strgetlaststr(g_pPmVFConfig.vfName, 45), + g_pPmVFConfig.numPorts); + printf(" Idx LID 0x Port Node GUID 0x NodeDesc\n"); + ct_lines -= 2; + + // if ports we were showing are removed, go to last port + if (g_scroll >= g_pPmVFConfig.numPorts) + g_scroll = g_pPmVFConfig.numPorts-1; + for ( ix = g_scroll; (ix < g_pPmVFConfig.numPorts) && + ((ix - g_scroll) < MAX_GROUPCONFIG_PORTS_PER_SCREEN); ix++ ) + { + // Truncate nodeDesc to keep line at 80 columns + printf( "%5d %.*X %3u %016" PRIX64 " %-.42s%s\n", ix, + (g_pPmVFConfig.portList[ix].nodeLid <= IB_MAX_UCAST_LID ? 4:8), + g_pPmVFConfig.portList[ix].nodeLid, + g_pPmVFConfig.portList[ix].portNumber, + g_pPmVFConfig.portList[ix].nodeGUID, + g_pPmVFConfig.portList[ix].nodeDesc, + strgetlaststr(g_pPmVFConfig.portList[ix].nodeDesc, 42) ); + ct_lines -= 1; + } + + } else if (fb_valid_VF_info && g_PmVFInfo.numPorts == 0) { + printf("\n"); + printf( "No ports in vf\n"); + ct_lines -= 2; + } else { + printf("VF Config: VF CONFIG NOT AVAILABLE\n"); + ct_lines -= 1; + } + break; + + case SCREEN_GROUP_FOCUS: + if (fb_valid_group_focus) + { + char* status_color_local = bf_color_off; + char* status_symbol_local = " "; + char* status_color_neighbor = bf_color_off; + char* status_symbol_neighbor = " "; + + if (pg_PmGroupFocus.select == STL_PA_SELECT_UTIL_PKTS_HIGH) + p_select = "UtlPkt-Hi"; + else if (pg_PmGroupFocus.select == STL_PA_SELECT_UTIL_LOW) + p_select = " Util-Low"; + else if (pg_PmGroupFocus.select == STL_PA_SELECT_CATEGORY_INTEG) + p_select = "Integrity"; + else if (pg_PmGroupFocus.select == STL_PA_SELECT_CATEGORY_CONG) + p_select = " Congestn"; + else if (pg_PmGroupFocus.select == STL_PA_SELECT_CATEGORY_SMA_CONG) + p_select = "SmaCongst"; + else if (pg_PmGroupFocus.select == STL_PA_SELECT_CATEGORY_BUBBLE) + p_select = " Bubble"; + else if (pg_PmGroupFocus.select == STL_PA_SELECT_CATEGORY_SEC) + p_select = " Security"; + else if (pg_PmGroupFocus.select == STL_PA_SELECT_CATEGORY_ROUT) + p_select = " Routing"; +// Future enhancement +#if 0 + else if (pg_PmGroupFocus.select == PACLIENT_SEL_ALL) + p_select = " ALL"; +#endif + else + { + pg_PmGroupFocus.select = STL_PA_SELECT_UTIL_HIGH; + p_select = "Util-High"; + } + + printf( "Group Focus: %-.29s%s GrpNumPorts: %u NumPorts: %u", + pg_PmGroupFocus.groupName, + strgetlaststr(pg_PmGroupFocus.groupName, 29), + g_PmGroupInfo.numInternalPorts + g_PmGroupInfo.numExternalPorts, + pg_PmGroupFocus.numPorts ); + if (g_expr_funct) + printf(" StartIx: %u", pg_PmGroupFocus.start); + printf(" Number: %u\n", pg_PmGroupFocus.range); + printf(" Idx %9s LID 0x Port Node GUID 0x NodeDesc\n", p_select); + ct_lines -= 2; + + // if ports we were showing are removed, go to last port + if (g_scroll >= pg_PmGroupFocus.numPorts) + g_scroll = pg_PmGroupFocus.numPorts-1; + for ( ix = g_scroll; (ix < pg_PmGroupFocus.numPorts) && + ((ix - g_scroll) < MAX_GROUPFOCUS_PORTS_PER_SCREEN); ix++ ) + { + switch (pg_PmGroupFocus.portList[ix].localStatus) { + case STL_PA_FOCUS_STATUS_PMA_IGNORE: + status_color_local = bf_color_blue; + status_symbol_local = "~"; + break; + case STL_PA_FOCUS_STATUS_PMA_FAILURE: + status_color_local = bf_color_yellow; + status_symbol_local = "!"; + break; + case STL_PA_FOCUS_STATUS_TOPO_FAILURE: + status_color_local = bf_color_red; + status_symbol_local = "?"; + break; + case STL_PA_FOCUS_STATUS_OK: + default: + status_color_local = bf_color_off; + status_symbol_local = " "; + } + switch (pg_PmGroupFocus.portList[ix].neighborStatus) { + case STL_PA_FOCUS_STATUS_PMA_IGNORE: + status_color_neighbor = bf_color_blue; + status_symbol_neighbor = "~"; + break; + case STL_PA_FOCUS_STATUS_PMA_FAILURE: + status_color_neighbor = bf_color_yellow; + status_symbol_neighbor = "!"; + break; + case STL_PA_FOCUS_STATUS_TOPO_FAILURE: + status_color_neighbor = bf_color_red; + status_symbol_neighbor = "?"; + break; + case STL_PA_FOCUS_STATUS_OK: + default: + status_color_neighbor = bf_color_off; + status_symbol_neighbor = " "; + } + printf("%s%s%4u ", status_color_local, status_symbol_local, ix); + + if ( ( (pg_PmGroupFocus.select >= STL_PA_SELECT_CATEGORY_INTEG) && + (pg_PmGroupFocus.select <= STL_PA_SELECT_CATEGORY_ROUT) ) || + (pg_PmGroupFocus.select == STL_PA_SELECT_UTIL_PKTS_HIGH) ) + printf("%9" PRIu64 "%s", + pg_PmGroupFocus.portList[ix].value, + bf_color_off); + else + printf( "%9.1f%s", + (float)pg_PmGroupFocus.portList[ix].value / 10.0, + bf_color_off); + + printf( " %.*X %3u %016" PRIX64 " %-.32s%s\n", + (pg_PmGroupFocus.portList[ix].nodeLid <= IB_MAX_UCAST_LID ? 4:8), + pg_PmGroupFocus.portList[ix].nodeLid, + pg_PmGroupFocus.portList[ix].portNumber, + pg_PmGroupFocus.portList[ix].nodeGUID, + pg_PmGroupFocus.portList[ix].nodeDesc, + strgetlaststr(pg_PmGroupFocus.portList[ix].nodeDesc, 32) ); + + if (pg_PmGroupFocus.portList[ix].neighborLid) + { + printf("%s%s <-> ", status_color_neighbor, + status_symbol_neighbor); + + if ( ( (pg_PmGroupFocus.select >= STL_PA_SELECT_CATEGORY_INTEG) && + (pg_PmGroupFocus.select <= STL_PA_SELECT_CATEGORY_ROUT) ) || + (pg_PmGroupFocus.select == STL_PA_SELECT_UTIL_PKTS_HIGH) ) + printf( "%9" PRIu64 "%s", + pg_PmGroupFocus.portList[ix].neighborValue, + bf_color_off); + else + printf( "%9.1f%s", + (float)pg_PmGroupFocus.portList[ix].neighborValue / 10.0, + bf_color_off); + + // Truncate neighborNodeDesc to keep line at 80 columns + printf( " %.*X %3u %016" PRIX64 " %-.34s%s\n", + (pg_PmGroupFocus.portList[ix].neighborLid <= IB_MAX_UCAST_LID ? 4:8), + pg_PmGroupFocus.portList[ix].neighborLid, + pg_PmGroupFocus.portList[ix].neighborPortNumber, + pg_PmGroupFocus.portList[ix].neighborGuid, + pg_PmGroupFocus.portList[ix].neighborNodeDesc, + strgetlaststr(pg_PmGroupFocus.portList[ix].neighborNodeDesc, 34) ); + } + else + printf("%s%s <-> none%s\n", status_color_neighbor, + status_symbol_neighbor, bf_color_off); + + ct_lines -= 2; + } + } else if (fb_valid_group_info && + g_PmGroupInfo.numInternalPorts == 0 && + g_PmGroupInfo.numExternalPorts == 0) { + printf("\n"); + printf( "No ports in group\n"); + ct_lines -= 2; + } else { + printf("Group Focus: GROUP FOCUS NOT AVAILABLE\n"); + ct_lines -= 1; + } + + break; + + case SCREEN_VF_FOCUS: + if (fb_valid_VF_focus) + { + char* status_color_local = bf_color_off; + char* status_symbol_local = " "; + char* status_color_neighbor = bf_color_off; + char* status_symbol_neighbor = " "; + + if (g_pPmVFFocus.select == STL_PA_SELECT_UTIL_PKTS_HIGH) + p_select = "UtlPkt-Hi"; + else if (g_pPmVFFocus.select == STL_PA_SELECT_UTIL_LOW) + p_select = " Util-Low"; + else if (g_pPmVFFocus.select == STL_PA_SELECT_VF_UTIL_PKTS_HIGH) + p_select = "VF-Pkt-Hi"; + else if (g_pPmVFFocus.select == STL_PA_SELECT_VF_UTIL_LOW) + p_select = "VF-Ut-Low"; + else if (g_pPmVFFocus.select == STL_PA_SELECT_VF_UTIL_HIGH) + p_select = "VF-Ut-Hi"; + else if (g_pPmVFFocus.select == STL_PA_SELECT_CATEGORY_INTEG) + p_select = "Integrity"; + else if (g_pPmVFFocus.select == STL_PA_SELECT_CATEGORY_CONG) + p_select = " Congestn"; + else if (g_pPmVFFocus.select == STL_PA_SELECT_CATEGORY_SMA_CONG) + p_select = "SmaCongst"; + else if (g_pPmVFFocus.select == STL_PA_SELECT_CATEGORY_BUBBLE) + p_select = " Bubble"; + else if (g_pPmVFFocus.select == STL_PA_SELECT_CATEGORY_SEC) + p_select = " Security"; + else if (g_pPmVFFocus.select == STL_PA_SELECT_CATEGORY_ROUT) + p_select = " Routing"; + else if (g_pPmVFFocus.select == STL_PA_SELECT_CATEGORY_VF_CONG) + p_select = "VF Congst"; + else if (g_pPmVFFocus.select == STL_PA_SELECT_CATEGORY_VF_BUBBLE) + p_select = "VF Bubble"; +// Future enhancement +#if 0 + else if (g_pPmVFFocus.select == PACLIENT_SEL_ALL) + p_select = " ALL"; +#endif + else + { + g_pPmVFFocus.select = STL_PA_SELECT_UTIL_HIGH; + p_select = "Util-High"; + } + + printf( "VF Focus: %-.30s%s GrpNumPorts: %u NumPorts: %u", + g_pPmVFFocus.vfName, + strgetlaststr(g_pPmVFFocus.vfName, 30), + g_PmVFInfo.numPorts, + g_pPmVFFocus.numPorts ); + if (g_expr_funct) + printf(" StartIx: %u", g_pPmVFFocus.start); + printf(" Number: %u\n", g_pPmVFFocus.range); + printf(" Idx %9s LID 0x Port Node GUID 0x NodeDesc\n", p_select); + ct_lines -= 2; + + // if ports we were showing are removed, go to last port + if (g_scroll >= g_pPmVFFocus.numPorts) + g_scroll = g_pPmVFFocus.numPorts-1; + for ( ix = g_scroll; (ix < g_pPmVFFocus.numPorts) && + ((ix - g_scroll) < MAX_VFFOCUS_PORTS_PER_SCREEN); ix++ ) + { + switch (g_pPmVFFocus.portList[ix].localStatus) { + case STL_PA_FOCUS_STATUS_PMA_IGNORE: + status_color_local = bf_color_blue; + status_symbol_local = "~"; + break; + case STL_PA_FOCUS_STATUS_PMA_FAILURE: + status_color_local = bf_color_yellow; + status_symbol_local = "!"; + break; + case STL_PA_FOCUS_STATUS_TOPO_FAILURE: + status_color_local = bf_color_red; + status_symbol_local = "?"; + break; + case STL_PA_FOCUS_STATUS_OK: + default: + status_color_local = bf_color_off; + status_symbol_local = " "; + } + switch (g_pPmVFFocus.portList[ix].neighborStatus) { + case STL_PA_FOCUS_STATUS_PMA_IGNORE: + status_color_neighbor = bf_color_blue; + status_symbol_neighbor = "~"; + break; + case STL_PA_FOCUS_STATUS_PMA_FAILURE: + status_color_neighbor = bf_color_yellow; + status_symbol_neighbor = "!"; + break; + case STL_PA_FOCUS_STATUS_TOPO_FAILURE: + status_color_neighbor = bf_color_red; + status_symbol_neighbor = "?"; + break; + case STL_PA_FOCUS_STATUS_OK: + default: + status_color_neighbor = bf_color_off; + status_symbol_neighbor = " "; + } + printf("%s%s%4u ", status_color_local, status_symbol_local, ix); + + if (IS_FOCUS_SELECT_UTIL(g_pPmVFFocus.select)) + printf( "%9.1f%s", + (float)g_pPmVFFocus.portList[ix].value / 10.0, + bf_color_off); + else + printf("%9" PRIu64 "%s", + g_pPmVFFocus.portList[ix].value, bf_color_off); + + // Truncate nodeDesc to keep line at 80 columns + printf( " %.*X %3u %016" PRIX64 " %-.32s%s\n", + (g_pPmVFFocus.portList[ix].nodeLid <= IB_MAX_UCAST_LID ? 4:8), + g_pPmVFFocus.portList[ix].nodeLid, + g_pPmVFFocus.portList[ix].portNumber, + g_pPmVFFocus.portList[ix].nodeGUID, + g_pPmVFFocus.portList[ix].nodeDesc, + strgetlaststr(g_pPmVFFocus.portList[ix].nodeDesc, 32) ); + + if (g_pPmVFFocus.portList[ix].neighborLid) + { + printf("%s%s <-> ", status_color_neighbor, + status_symbol_neighbor); + + if (IS_FOCUS_SELECT_UTIL(g_pPmVFFocus.select)) + printf( "%9.1f%s", + (float)g_pPmVFFocus.portList[ix].neighborValue / 10.0, + bf_color_off); + else + printf( "%9" PRIu64 "%s", + g_pPmVFFocus.portList[ix].neighborValue, + bf_color_off); + + // Truncate neighborNodeDesc to keep line at 80 columns + printf( " %.*X %3u %016" PRIX64 " %-.34s%s\n", + (g_pPmVFFocus.portList[ix].neighborLid <= IB_MAX_UCAST_LID ? 4:8), + g_pPmVFFocus.portList[ix].neighborLid, + g_pPmVFFocus.portList[ix].neighborPortNumber, + g_pPmVFFocus.portList[ix].neighborGuid, + g_pPmVFFocus.portList[ix].neighborNodeDesc, + strgetlaststr(g_pPmVFFocus.portList[ix].neighborNodeDesc, 34) ); + } + else + printf("%s%s <-> none%s\n", status_color_neighbor, + status_symbol_neighbor, bf_color_off); + + ct_lines -= 2; + } + } + else if (fb_valid_VF_info && + g_PmVFInfo.numPorts == 0) + { + printf("\n"); + printf( "No ports in vf\n"); + ct_lines -= 2; + } + else + { + printf("VF Focus: VF FOCUS NOT AVAILABLE\n"); + ct_lines -= 1; + } + + break; + + case SCREEN_PORT_STATS: + if (fb_valid_port_stats) + { + if (tb_menu[n_level_menu - 1] == SCREEN_GROUP_CONFIG) + { + if (fb_valid_group_config) + { + printf( "Port Stats: %-.44s%s LID: 0x%X PortNum: %u\n", + pg_PmGroupConfig.groupName, + strgetlaststr(pg_PmGroupConfig.groupName, 44), + pg_PmGroupConfig.portList[g_ix_port - g_start].nodeLid, + pg_PmGroupConfig.portList[g_ix_port - g_start].portNumber ); + printf( "NodeDesc: %-.41s%s NodeGUID: 0x%016"PRIX64"\n\n", + pg_PmGroupConfig.portList[g_ix_port - g_start].nodeDesc, + strgetlaststr(pg_PmGroupConfig.portList[g_ix_port - g_start].nodeDesc, 41), + pg_PmGroupConfig.portList[g_ix_port - g_start].nodeGUID ); + ct_lines -= 3; + } + + else + { + printf("Port Stats: GROUP CONFIG NOT AVAILABLE\n"); + ct_lines -= 1; + } + } else if (tb_menu[n_level_menu - 1] == SCREEN_VF_CONFIG) { + if (fb_valid_VF_config) { + printf( "Port Stats: %-.44s%s LID: 0x%X PortNum: %u\n", + g_pPmVFConfig.vfName, + strgetlaststr(g_pPmVFConfig.vfName, 44), + g_pPmVFConfig.portList[g_ix_port - g_start].nodeLid, + g_pPmVFConfig.portList[g_ix_port - g_start].portNumber ); + printf( "NodeDesc: %-.41s%c NodeGUID: 0x%016"PRIX64"\n\n", + g_pPmVFConfig.portList[g_ix_port - g_start].nodeDesc, + strgetlastchar(g_pPmVFConfig.portList[g_ix_port - g_start].nodeDesc, 41), + g_pPmVFConfig.portList[g_ix_port - g_start].nodeGUID ); + ct_lines -= 3; + } else { + printf("Port Stats: VF CONFIG NOT AVAILABLE\n"); + ct_lines -= 1; + } + } + + else + { + char *status_color = bf_color_off; + char *status_message = ""; + if (g_portCounterFlags & STL_PA_PC_FLAG_UNEXPECTED_CLEAR) { + status_color = bf_color_red; + status_message = " Unexp Clear"; + } + + if (tb_menu[n_level_menu - 1] == SCREEN_GROUP_FOCUS) { + if (fb_valid_group_focus) + { + if (fb_port_neighbor) + { + printf( "Port Stats: %-.10s%s LID: 0x%X PortNum: %u Rate: %4s MTU:%5s%s%s%s\n", + pg_PmGroupFocus.groupName, + strgetlaststr(pg_PmGroupFocus.groupName, 10), + pg_PmGroupFocus.portList[g_ix_port - g_start].neighborLid, + pg_PmGroupFocus.portList[g_ix_port - g_start].neighborPortNumber, + StlStaticRateToText(pg_PmGroupFocus.portList[g_ix_port - g_start].rate), + IbMTUToText(pg_PmGroupFocus.portList[g_ix_port - g_start].maxVlMtu), + status_color, status_message, bf_color_off ); + printf( "NodeDesc: %-.41s%s NodeGUID: 0x%016"PRIX64"\n", + pg_PmGroupFocus.portList[g_ix_port - g_start].neighborNodeDesc, + strgetlaststr(pg_PmGroupFocus.portList[g_ix_port - g_start].neighborNodeDesc, 41), + pg_PmGroupFocus.portList[g_ix_port - g_start].neighborGuid ); + printf( "Neighbor: %-.41s%s LID: 0x%X PortNum: %u\n", + pg_PmGroupFocus.portList[g_ix_port - g_start].nodeDesc, + strgetlaststr(pg_PmGroupFocus.portList[g_ix_port - g_start].nodeDesc, 41), + pg_PmGroupFocus.portList[g_ix_port - g_start].nodeLid, + pg_PmGroupFocus.portList[g_ix_port - g_start].portNumber ); + } + + else + { + printf( "Port Stats: %-.10s%s LID: 0x%X PortNum: %u Rate: %4s MTU:%5s%s%s%s\n", + pg_PmGroupFocus.groupName, + strgetlaststr(pg_PmGroupFocus.groupName, 10), + pg_PmGroupFocus.portList[g_ix_port - g_start].nodeLid, + pg_PmGroupFocus.portList[g_ix_port - g_start].portNumber, + StlStaticRateToText(pg_PmGroupFocus.portList[g_ix_port - g_start].rate), + IbMTUToText(pg_PmGroupFocus.portList[g_ix_port - g_start].maxVlMtu), + status_color, status_message, bf_color_off ); + printf( "NodeDesc: %-.41s%s NodeGUID: 0x%016"PRIX64"\n", + pg_PmGroupFocus.portList[g_ix_port - g_start].nodeDesc, + strgetlaststr(pg_PmGroupFocus.portList[g_ix_port - g_start].nodeDesc, 41), + pg_PmGroupFocus.portList[g_ix_port - g_start].nodeGUID ); + + if (pg_PmGroupFocus.portList[g_ix_port - g_start].neighborLid) + printf( "Neighbor: %-.41s%s LID: 0x%X PortNum: %u\n", + pg_PmGroupFocus.portList[g_ix_port - g_start].neighborNodeDesc, + strgetlaststr(pg_PmGroupFocus.portList[g_ix_port - g_start].neighborNodeDesc, 41), + pg_PmGroupFocus.portList[g_ix_port - g_start].neighborLid, + pg_PmGroupFocus.portList[g_ix_port - g_start].neighborPortNumber ); + else + printf("Neighbor:none\n"); + } + + ct_lines -= 3; + } + + else + { + printf("Port Stats: GROUP FOCUS NOT AVAILABLE\n"); + ct_lines -= 1; + } + } else if (tb_menu[n_level_menu - 1] == SCREEN_VF_FOCUS) { + if (fb_valid_VF_focus) + { + if (fb_port_neighbor) + { + printf( "Port Stats: %-.10s%s LID: 0x%X PortNum: %u Rate: %4s MTU:%5s%s%s%s\n", + g_pPmVFFocus.vfName, + strgetlaststr(g_pPmVFFocus.vfName, 10), + g_pPmVFFocus.portList[g_ix_port - g_start].neighborLid, + g_pPmVFFocus.portList[g_ix_port - g_start].neighborPortNumber, + StlStaticRateToText(g_pPmVFFocus.portList[g_ix_port - g_start].rate), + IbMTUToText(g_pPmVFFocus.portList[g_ix_port - g_start].maxVlMtu), + status_color, status_message, bf_color_off ); + printf( "NodeDesc: %-.41s%s NodeGUID: 0x%016"PRIX64"\n", + g_pPmVFFocus.portList[g_ix_port - g_start].neighborNodeDesc, + strgetlaststr(g_pPmVFFocus.portList[g_ix_port - g_start].neighborNodeDesc, 41), + g_pPmVFFocus.portList[g_ix_port - g_start].neighborGuid ); + printf( "Neighbor: %-.41s%s LID: 0x%X PortNum: %u\n", + g_pPmVFFocus.portList[g_ix_port - g_start].nodeDesc, + strgetlaststr(g_pPmVFFocus.portList[g_ix_port - g_start].nodeDesc, 41), + g_pPmVFFocus.portList[g_ix_port - g_start].nodeLid, + g_pPmVFFocus.portList[g_ix_port - g_start].portNumber ); + } + + else + { + printf( "Port Stats: %-.10s%s LID: 0x%X PortNum: %u Rate: %4s MTU:%5s%s%s%s\n", + g_pPmVFFocus.vfName, + strgetlaststr(g_pPmVFFocus.vfName, 10), + g_pPmVFFocus.portList[g_ix_port - g_start].nodeLid, + g_pPmVFFocus.portList[g_ix_port - g_start].portNumber, + StlStaticRateToText(g_pPmVFFocus.portList[g_ix_port - g_start].rate), + IbMTUToText(g_pPmVFFocus.portList[g_ix_port - g_start].maxVlMtu), + status_color, status_message, bf_color_off ); + printf( "NodeDesc: %-.41s%s NodeGUID: 0x%016"PRIX64"\n", + g_pPmVFFocus.portList[g_ix_port - g_start].nodeDesc, + strgetlaststr(g_pPmVFFocus.portList[g_ix_port - g_start].nodeDesc, 41), + g_pPmVFFocus.portList[g_ix_port - g_start].nodeGUID ); + + if (g_pPmVFFocus.portList[g_ix_port - g_start].neighborLid) + printf( "Neighbor: %-.41s%s LID: 0x%X PortNum: %u\n", + g_pPmVFFocus.portList[g_ix_port - g_start].neighborNodeDesc, + strgetlaststr(g_pPmVFFocus.portList[g_ix_port - g_start].neighborNodeDesc, 41), + g_pPmVFFocus.portList[g_ix_port - g_start].neighborLid, + g_pPmVFFocus.portList[g_ix_port - g_start].neighborPortNumber ); + else + printf("Neighbor: none\n"); + } + + ct_lines -= 3; + } + + else + { + printf("Port Stats: VF FOCUS NOT AVAILABLE\n"); + ct_lines -= 1; + } + } + + } + + /* First half of counters (Data, Cong, Integ) */ + if (g_scroll_cntrs == 0) { + printf(" Xmit: Data: %10"PRIu64" MB (%10"PRIu64" Flits) Pkts: %10"PRIu64"\n", + g_portCounters.portXmitData / FLITS_PER_MB, + g_portCounters.portXmitData, g_portCounters.portXmitPkts); + printf( " Recv: Data: %10"PRIu64" MB (%10"PRIu64" Flits) Pkts: %10"PRIu64"\n", + g_portCounters.portRcvData / FLITS_PER_MB, + g_portCounters.portRcvData, g_portCounters.portRcvPkts ); + printf( " Multicast: Xmit Pkts: %-10"PRIu64" Recv Pkts: %-10"PRIu64"\n", + g_portCounters.portMulticastXmitPkts, g_portCounters.portMulticastRcvPkts ); + + { + printf("\n\n"); + } + //ct_lines -= 5; + printf( " Integrity:\n"); + printf( " Link Quality: %10u | Lanes Down: %10u\n", + g_portCounters.lq.s.linkQualityIndicator, + g_portCounters.lq.s.numLanesDown); + printf( " Uncorrectable: %10llu | Link Downed: %10llu\n", + (unsigned long long)g_portCounters.uncorrectableErrors, + (unsigned long long)g_portCounters.linkDowned); + printf( " Loc Lnk Integ: %10llu | Lnk Err Recov: %10llu\n", + (unsigned long long)g_portCounters.localLinkIntegrityErrors, + (unsigned long long)g_portCounters.linkErrorRecovery); + printf( " Rcv Errors: %10llu | Excs Bfr Ovrn*: %10llu\n", + (unsigned long long)g_portCounters.portRcvErrors, + (unsigned long long)g_portCounters.excessiveBufferOverruns); + printf( " FM Conf Err: %10llu |\n", + (unsigned long long)g_portCounters.fmConfigErrors); + //ct_lines -= 6; //11 + printf( " Congestion:\n"); + printf( " Cong Discards: %10llu | Rcv FECN*: %10llu\n", + (unsigned long long)g_portCounters.swPortCongestion, + (unsigned long long)g_portCounters.portRcvFECN); + printf( " Mark FECN: %10llu | Rcv BECN: %10llu\n", + (unsigned long long)g_portCounters.portMarkFECN, + (unsigned long long)g_portCounters.portRcvBECN); + printf( " Xmit Wait: %10llu | Xmit Time Cong: %10llu\n", + (unsigned long long)g_portCounters.portXmitWait, + (unsigned long long)g_portCounters.portXmitTimeCong); + //ct_lines -= 4; //15 + ct_lines -= 15; + } else if (g_scroll_cntrs == 1) { + printf( " Bubble:\n" ); + printf( " Xmit Wasted BW: %10llu | Rcv Bubble*: %10llu\n", + (unsigned long long)g_portCounters.portXmitWastedBW, + (unsigned long long)g_portCounters.portRcvBubble); + printf( " Xmit Wait Data: %10llu |\n", + (unsigned long long)g_portCounters.portXmitWaitData); + printf( " Security:\n"); + printf( " Xmit Constrain: %10llu | Rcv Constrain*: %10llu\n", + (unsigned long long)g_portCounters.portXmitConstraintErrors, + (unsigned long long)g_portCounters.portRcvConstraintErrors); + printf( " Routing and Others:\n"); + printf( " Rcv Sw Relay: %10llu | Xmit Discards: %10llu\n", + (unsigned long long)g_portCounters.portRcvSwitchRelayErrors, + (unsigned long long)g_portCounters.portXmitDiscards); + ct_lines -= 7; + if(fb_valid_vf_port_stats_hidden) { + printf( " SmaCongestion (VL15):\n"); + printf( " Cong Discards: %10llu | Xmit Wait: %10llu\n", + (unsigned long long)g_hiddenVfPortCounters.swPortVFCongestion, + (unsigned long long)g_hiddenVfPortCounters.portVFXmitWait); + ct_lines -= 2; + } + } + } + else + { + printf("Port Stats: PORT COUNTERS NOT AVAILABLE\n"); + ct_lines -= 1; + } + break; + + case SCREEN_VF_PORT_STATS: + if (fb_valid_VF_port_counters) + { + if (tb_menu[n_level_menu - 2] == SCREEN_VF_CONFIG) { + if (fb_valid_VF_config) { + printf( "VF Port Stats: %-.41s%s LID: 0x%X PortNum: %u\n", + g_pPmVFConfig.vfName, + strgetlaststr(g_pPmVFConfig.vfName, 41), + g_pPmVFConfig.portList[g_ix_port - g_start].nodeLid, + g_pPmVFConfig.portList[g_ix_port - g_start].portNumber ); + printf( "NodeDesc: %-.41s%c NodeGUID: 0x%016"PRIX64"\n\n", + g_pPmVFConfig.portList[g_ix_port - g_start].nodeDesc, + strgetlastchar(g_pPmVFConfig.portList[g_ix_port - g_start].nodeDesc, 41), + g_pPmVFConfig.portList[g_ix_port - g_start].nodeGUID ); + ct_lines -= 3; + } else { + printf("VF Port Stats: VF CONFIG NOT AVAILABLE\n"); + ct_lines -= 1; + } + } + else + { + char* status_color = bf_color_off; + char* status_message = ""; + + if (tb_menu[n_level_menu - 2] == SCREEN_VF_FOCUS) { + if (fb_valid_VF_focus) + { + if (fb_port_neighbor) + { + printf( "VF Port Stats: %-.7s%s LID: 0x%X PortNum: %u Rate: %4s MTU:%5s%s%s%s\n", + g_pPmVFFocus.vfName, + strgetlaststr(g_pPmVFFocus.vfName, 10), + g_pPmVFFocus.portList[g_ix_port - g_start].neighborLid, + g_pPmVFFocus.portList[g_ix_port - g_start].neighborPortNumber, + StlStaticRateToText(g_pPmVFFocus.portList[g_ix_port - g_start].rate), + IbMTUToText(g_pPmVFFocus.portList[g_ix_port - g_start].maxVlMtu), + status_color, status_message, bf_color_off ); + printf( "NodeDesc: %-.41s%s NodeGUID: 0x%016"PRIX64"\n", + g_pPmVFFocus.portList[g_ix_port - g_start].neighborNodeDesc, + strgetlaststr(g_pPmVFFocus.portList[g_ix_port - g_start].neighborNodeDesc, 41), + g_pPmVFFocus.portList[g_ix_port - g_start].neighborGuid ); + printf( "Neighbor: %-.41s%s LID: 0x%X PortNum: %u\n", + g_pPmVFFocus.portList[g_ix_port - g_start].nodeDesc, + strgetlaststr(g_pPmVFFocus.portList[g_ix_port - g_start].nodeDesc, 41), + g_pPmVFFocus.portList[g_ix_port - g_start].nodeLid, + g_pPmVFFocus.portList[g_ix_port - g_start].portNumber ); + } + else + { + printf( "VF Port Stats: %-.7s%s LID: 0x%X PortNum: %u Rate: %4s MTU:%5s%s%s%s\n", + g_pPmVFFocus.vfName, + strgetlaststr(g_pPmVFFocus.vfName, 10), + g_pPmVFFocus.portList[g_ix_port - g_start].nodeLid, + g_pPmVFFocus.portList[g_ix_port - g_start].portNumber, + StlStaticRateToText(g_pPmVFFocus.portList[g_ix_port - g_start].rate), + IbMTUToText(g_pPmVFFocus.portList[g_ix_port - g_start].maxVlMtu), + status_color, status_message, bf_color_off ); + printf( "NodeDesc: %-.41s%s NodeGUID: 0x%016"PRIX64"\n", + g_pPmVFFocus.portList[g_ix_port - g_start].nodeDesc, + strgetlaststr(g_pPmVFFocus.portList[g_ix_port - g_start].nodeDesc, 41), + g_pPmVFFocus.portList[g_ix_port - g_start].nodeGUID ); + + if (g_pPmVFFocus.portList[g_ix_port - g_start].neighborLid) + printf( "Neighbor: %-.41s%s LID: 0x%X PortNum: %u\n", + g_pPmVFFocus.portList[g_ix_port - g_start].neighborNodeDesc, + strgetlaststr(g_pPmVFFocus.portList[g_ix_port - g_start].neighborNodeDesc, 41), + g_pPmVFFocus.portList[g_ix_port - g_start].neighborLid, + g_pPmVFFocus.portList[g_ix_port - g_start].neighborPortNumber ); + else + printf("Neighbor: none\n"); + } + ct_lines -= 3; + } + else + { + printf("VF Port Stats: VF FOCUS NOT AVAILABLE\n"); + ct_lines -= 1; + } + } + } + printf(" Xmit: Data: %10"PRIu64" MB (%10"PRIu64" Flits) Pkts: %10"PRIu64"\n", + g_vfPortCounters.portVFXmitData / FLITS_PER_MB, + g_vfPortCounters.portVFXmitData, g_vfPortCounters.portVFXmitPkts); + printf( " Recv: Data: %10"PRIu64" MB (%10"PRIu64" Flits) Pkts: %10"PRIu64"\n", + g_vfPortCounters.portVFRcvData / FLITS_PER_MB, + g_vfPortCounters.portVFRcvData, g_vfPortCounters.portVFRcvPkts ); + printf("\n\n"); + //ct_lines -= 4; + printf( " Congestion:\n"); + printf( " Cong Discards: %10llu | Rcv FECN*: %10llu\n", + (unsigned long long)g_vfPortCounters.swPortVFCongestion, + (unsigned long long)g_vfPortCounters.portVFRcvFECN); + printf( " Mark FECN: %10llu | Rcv BECN: %10llu\n", + (unsigned long long)g_vfPortCounters.portVFMarkFECN, + (unsigned long long)g_vfPortCounters.portVFRcvBECN); + printf( " Xmit Wait: %10llu | Xmit Time Cong: %10llu\n", + (unsigned long long)g_vfPortCounters.portVFXmitWait, + (unsigned long long)g_vfPortCounters.portVFXmitTimeCong); + //ct_lines -= 4; //8 + printf( " Bubble:\n" ); + printf( " Xmit Wasted BW: %10llu | Rcv Bubble*: %10llu\n", + (unsigned long long)g_vfPortCounters.portVFXmitWastedBW, + (unsigned long long)g_vfPortCounters.portVFRcvBubble); + printf( " Xmit Wait Data: %10llu |\n", + (unsigned long long)g_portCounters.portXmitWaitData); + //ct_lines -= 3; //11 + printf( " Routing and Others:\n"); + printf( " Xmit Discards: %10llu\n", + (unsigned long long)g_vfPortCounters.portVFXmitDiscards); + ct_lines -= 13; + if (g_vfPortCounterFlags & STL_PA_PC_FLAG_SHARED_VL) + { + printf("\nCounters may be shared between Virtual Fabrics\n"); + ct_lines -= 2; + } + if (g_vfPortCounterFlags & STL_PA_PC_FLAG_CLEAR_FAIL) + { + printf("\nPort Counter Clear was Unsuccessful\n"); + ct_lines -= 2; + } + } + else + { + printf("VF Port Stats: VF PORT COUNTERS NOT AVAILABLE\n"); + ct_lines -= 1; + } + break; + + default: + printf("INVALID MENU VALUE\n"); + ct_lines -= 1; + break; + + } // End of switch (tb_menu[n_level_menu]) + + // Display error line + if (bf_error[0]) + { + printf("ERROR: %s\n", bf_error); + fb_error_displayed = TRUE; + ct_lines -= 1; + } + + // Display input prompt + if (tb_menu[n_level_menu] == SCREEN_VF_SUMMARY || + tb_menu[n_level_menu] == SCREEN_SUMMARY) + ct_lines -= 1; // extra line for menu in these screens + for ( ; ct_lines > 0; ct_lines--) + printf("\n"); + + printf("Quit up Live/rRev/fFwd/time/bookmrked Bookmrk Unbookmrk ?help |%c", + (tb_menu[n_level_menu] == SCREEN_VF_SUMMARY || + tb_menu[n_level_menu] == SCREEN_SUMMARY) ? '\n' : ' '); + p_multi_input = "qQt"; + + switch (tb_menu[n_level_menu]) + { + case SCREEN_VF_SUMMARY: + case SCREEN_SUMMARY: + printf("sS Pmcfg Imginfo View 0-n:\n"); + break; + + case SCREEN_VF_INFO_SELECT: + case SCREEN_GROUP_INFO_SELECT: + printf("P S C:\n"); + break; + + case SCREEN_VF_CTG_STATS: + case SCREEN_VF_BW_STATS: + case SCREEN_GROUP_BW_STATS: + case SCREEN_GROUP_CTG_STATS: + if (g_expr_funct) + { + printf("cC I0-n N0-n Detail:\n"); + p_multi_input = "iInNqQt"; + } + else + { + printf("cC N0-n Detail:\n"); + p_multi_input = "nNqQt"; + } + break; + + case SCREEN_VF_CONFIG: + case SCREEN_GROUP_CONFIG: + printf("sS P0-n:\n"); + p_multi_input = "pPqQt"; + break; + + case SCREEN_VF_FOCUS: + case SCREEN_GROUP_FOCUS: + if (g_expr_funct) + { + printf("sS cC I0-n N0-n P0-n:\n"); + p_multi_input = "iInNpPqQt"; + } + else + { + printf("sS cC N0-n P0-n:\n"); + p_multi_input = "nNpPqQt"; + } + break; + + case SCREEN_PORT_STATS: + if (tb_menu[n_level_menu - 1] == SCREEN_GROUP_FOCUS || + tb_menu[n_level_menu - 1] == SCREEN_VF_FOCUS ) + { + if (fb_port_has_neighbor) + printf("Neighbor "); + } + printf("sS%s:\n", ((tb_menu[n_level_menu - 1] == SCREEN_VF_FOCUS )|| + (tb_menu[n_level_menu - 1] == SCREEN_VF_CONFIG)) ? " vV" : ""); + break; + + case SCREEN_VF_PORT_STATS: + if (tb_menu[n_level_menu - 2] == SCREEN_GROUP_FOCUS || + tb_menu[n_level_menu - 2] == SCREEN_VF_FOCUS ) + { + if (fb_port_has_neighbor) + printf("Neighbor "); + } + printf("vV:\n"); + break; + + default: + printf("\n "); + break; + + } // End of switch (tb_menu[n_level_menu]) + + // Print stdin input buffer after screen refresh + if (text_input) printf("%s", text_input); + fflush(stdout); + +} // End of DisplayScreen() + +// command line options, each has a short and long flag name +struct option options[] = { + // basic controls + { "verbose", no_argument, NULL, 'v' }, + { "quiet", no_argument, NULL, 'q' }, + { "hfi", required_argument, NULL, 'h' }, + { "port", required_argument, NULL, 'p' }, + { "interval", no_argument, NULL, 'i' }, + { "timeout", required_argument, NULL, '!' }, + { "help", no_argument, NULL, '$' }, // use an invalid option character + { 0 } +}; + +void Usage_full(void) +{ + fprintf(stderr, "Usage: " NAME_PROG " [-v][-q] [-h hfi] [-p port]\n [-i seconds]\n"); + fprintf(stderr, " or\n"); + fprintf(stderr, " " NAME_PROG " --help\n"); + fprintf(stderr, " --help - produce full help text\n"); + fprintf(stderr, " -v/--verbose level - verbose output level (additive):\n"); + fprintf(stderr, " 1 - Screen\n"); + fprintf(stderr, " 4 - STDERR (" NAME_PROG ")\n"); + fprintf(stderr, " 16 - STDERR PaClient\n"); + fprintf(stderr, " -q/--quiet - disable progress reports\n"); + fprintf(stderr, " -h/--hfi hfi - hfi, numbered 1..n, 0= -p port will be a\n"); + fprintf(stderr, " system wide port num (default is 0)\n"); + fprintf(stderr, " -p/--port port - port, numbered 1..n, 0=1st active (default\n"); + fprintf(stderr, " is 1st active)\n"); + fprintf(stderr, " --timeout - timeout(response wait time) in ms, default is 1000ms\n"); + fprintf(stderr, " -i/--interval seconds - interval at which PA queries will be performed\n"); + fprintf(stderr, " to refresh to the latest PA image (default=10s) \n"); + fprintf(stderr, "\n"); + fprintf(stderr, "The -h and -p options permit a variety of selections:\n"); + fprintf(stderr, " -h 0 - 1st active port in system (this is the default)\n"); + fprintf(stderr, " -h 0 -p 0 - 1st active port in system\n"); + fprintf(stderr, " -h x - 1st active port on HFI x\n"); + fprintf(stderr, " -h x -p 0 - 1st active port on HFI x\n"); + fprintf(stderr, " -h 0 -p y - port y within system (irrespective of which ports are active)\n"); + fprintf(stderr, " -h x -p y - HFI x, port y\n"); + + exit(2); +} + +void Usage(void) +{ + fprintf(stderr, "Usage: " NAME_PROG " [-v][-q] [-i seconds]\n"); + fprintf(stderr, " or\n"); + fprintf(stderr, " " NAME_PROG " --help\n"); + fprintf(stderr, " --help - produce full help text\n"); + fprintf(stderr, " -v/--verbose level - verbose output level\n"); + fprintf(stderr, " -q/--quiet - disable progress reports\n"); + fprintf(stderr, " -i/--interval seconds - interval at which PA queries will be performed\n"); + fprintf(stderr, " to refresh to the latest PA image (default=10s)\n"); + exit(2); +} + +int main(int argc, char ** argv) +{ + FSTATUS fstatus; + int c; + int index; + unsigned long temp; + long int temp2 = 0; + char *endptr; + int n_cmd; + char tb_cmd[64] = ""; + time_t time_start; + int pa_service_state = OMGT_SERVICE_STATE_UNKNOWN; + int ms_timeout = OMGT_DEF_TIMEOUT_MS; + int select_idx = 0; + + Top_setcmdname(NAME_PROG); + g_quiet = ! isatty(2); // disable progress if stderr is not tty + + // process command line arguments + while (-1 != (c = getopt_long(argc,argv, "v:qh:p:i:D:X", options, &index))) + { + switch (c) + { + case '$': + Usage_full(); + break; + case 'v': + errno = 0; + temp = strtoul(optarg, &endptr, 0); + if (temp > INT_MAX || errno || ! endptr || *endptr != '\0') { + fprintf(stderr, "pm: Invalid Verbose Value: %s\n", optarg); + Usage(); + } + g_verbose = temp; +#ifdef IB_STACK_OPENIB + //_openib_debug_ = 1; +#endif + break; + case 'q': + g_quiet = 1; + break; + case 'h': // hfi to issue query from + errno = 0; + temp = strtoul(optarg, &endptr, 0); + if (temp > IB_UINT8_MAX || errno || ! endptr || *endptr != '\0') { + fprintf(stderr, "pm: Invalid HFI Number: %s\n", optarg); + Usage(); + } + hfi = (uint8)temp; + break; + case 'p': // port to issue query from + errno = 0; + temp = strtoul(optarg, &endptr, 0); + if (temp > IB_UINT8_MAX || errno || ! endptr || *endptr != '\0') { + fprintf(stderr, "pm: Invalid Port Number: %s\n", optarg); + Usage(); + } + port = (uint8)temp; + break; + case '!': // timeout + errno = 0; + temp = strtoul(optarg, &endptr, 0); + if (temp > INT_MAX || errno || ! endptr || *endptr != '\0') { + fprintf(stderr, "pm: Invalid timeout value: %s\n", optarg); + Usage(); + } + ms_timeout = (int)temp; + break; + case 'i': // get performance stats over interval + errno = 0; + temp = strtoul(optarg, &endptr, 0); + if (temp > INT_MAX || errno || ! endptr || *endptr != '\0') { + fprintf(stderr, "pm: Invalid Interval: %s\n", optarg); + Usage(); + } + g_interval = temp; + break; + case 'D': // NOTE: this option is not documented in usage + errno = 0; + temp = strtoul(optarg, &endptr, 0); + if (temp > INT_MAX || errno || ! endptr || *endptr != '\0') { + fprintf(stderr, "pm: Invalid Debug Value: %s\n", optarg); + Usage(); + } + g_debug = temp; + break; + case 'X': // NOTE: this option is not documented in usage + g_expr_funct = 1; + break; + default: + fprintf(stderr, "pm: Invalid option -%c\n", c); + Usage(); + break; + } + } /* end while */ + + if (optind < argc) + { + Usage(); + } + + printf(NAME_PROG " Initializing...(%d seconds)\n", g_interval); + tb_menu[0] = SCREEN_SUMMARY; + bf_error[0] = 0; + fb_error_displayed = FALSE; + + struct omgt_params params = {.debug_file = (g_verbose & VERBOSE_PACLIENT ? stderr : NULL)}; + if (!omgt_open_port_by_num(&g_portHandle, hfi, port, ¶ms)) + { + /* Port is open, check PA Service */ + fstatus = omgt_port_get_pa_service_state(g_portHandle, &pa_service_state, OMGT_REFRESH_SERVICE_BAD_STATE); + if (fstatus != FSUCCESS || pa_service_state != OMGT_SERVICE_STATE_OPERATIONAL) + { + printf(NAME_PROG " PA Service Not Operational: %s (%d)\n", + omgt_service_state_totext(pa_service_state), pa_service_state ); + g_exitstatus = 1; + goto done; + } + fb_valid_pa_client = TRUE; + } + + //set timeout for PA operations + omgt_set_timeout(g_portHandle, ms_timeout); + + // Configure terminal for single character at a time input + if (tcgetattr(fileno(stdin), &g_term_save) < 0) + { + printf(NAME_PROG " Unable to Get Terminal Configuration\n"); + g_exitstatus = 1; + goto done; + } + + g_term = g_term_save; + g_term.c_lflag &= ~(ICANON | ECHOCTL); + if (tcsetattr(fileno(stdin), TCSAFLUSH, &g_term) < 0) + { + printf(NAME_PROG " Unable to Configure Terminal\n"); + g_exitstatus = 1; + goto quit; + } + + while (TRUE) + { + time_start = time(NULL); + ct_interval += 1; + DisplayScreen(tb_cmd); + + while ((time(NULL) - time_start) < g_interval) + { + boolean isdelchar = FALSE; + if (get_input(0, sizeof(tb_cmd)-1, tb_cmd, p_multi_input, &isdelchar) > 0) + { + // Clear displayed error + if (fb_error_displayed) + { + bf_error[0] = 0; + fb_error_displayed = FALSE; + } + + // Process command + if ((n_cmd = tb_cmd[0]) == 0x0A) + ; + + else if (n_cmd == '?') + fb_help = TRUE; + + else if ((n_cmd == 'u') && (n_level_menu > 0)) + { + if (tb_menu[--n_level_menu] == SCREEN_SUMMARY || tb_menu[n_level_menu] == SCREEN_VF_SUMMARY) + g_group = -1; + + if ( (tb_menu[n_level_menu] == SCREEN_GROUP_CONFIG) || + (tb_menu[n_level_menu] == SCREEN_GROUP_FOCUS) || + (tb_menu[n_level_menu] == SCREEN_VF_CONFIG) || + (tb_menu[n_level_menu] == SCREEN_VF_FOCUS) ) + g_ix_port = -1; + } + + else if (toupper(n_cmd) == 'L') + { + if (g_imageIdFreeze.imageNumber != PACLIENT_IMAGE_CURRENT) + { + if ( (fstatus = omgt_pa_release_image(g_portHandle, g_imageIdFreeze)) != + FSUCCESS ) + snprintf( &bf_error[strlen(bf_error)], sizeof(bf_error)-strlen(bf_error), + "UNABLE TO UNFREEZE HISTORY IMAGE fstatus:%u %s", + fstatus, iba_fstatus_msg(fstatus) ); + + g_imageIdFreeze.imageNumber = PACLIENT_IMAGE_CURRENT; + } + + g_imageIdQuery.imageNumber = PACLIENT_IMAGE_CURRENT; + g_offset = g_imageIdQuery.imageOffset = 0; + } + + else if ((toupper(n_cmd) == 'F') || (toupper(n_cmd) == 'R')) + { + if (n_cmd > 'R') + temp2 = 1; + else + temp2 = 5; + + if (toupper(n_cmd) == 'R') + temp2 = -temp2; + + if (g_imageIdQuery.imageNumber == PACLIENT_IMAGE_CURRENT) + { + g_imageIdTemp.imageNumber = g_imageIdResp.imageNumber; + g_imageIdTemp.imageOffset = temp2; + + if ( ( fstatus = omgt_pa_freeze_image(g_portHandle, g_imageIdTemp, + &g_imageIdResp) ) == FSUCCESS ) + { + g_imageIdQuery = g_imageIdFreeze = g_imageIdResp; + g_offset = temp2; + } + + else + snprintf( &bf_error[strlen(bf_error)], sizeof(bf_error)-strlen(bf_error), + "%s IMAGE NOT AVAILABLE FROM LIVE fstatus:%u %s", + temp2 < 0 ? "REVERSE" : "FORWARD", + fstatus, iba_fstatus_msg(fstatus) ); + } + + else if ( g_imageIdFreeze.imageNumber != + PACLIENT_IMAGE_CURRENT ) + { + g_imageIdTemp.imageNumber = + g_imageIdFreeze.imageNumber; + g_imageIdTemp.imageOffset = + g_imageIdFreeze.imageOffset + temp2; + + if ( ( fstatus = omgt_pa_move_image_freeze(g_portHandle, g_imageIdFreeze, + &g_imageIdTemp) ) == FSUCCESS ) + { + g_imageIdQuery = g_imageIdFreeze = g_imageIdTemp; + g_offset += temp2; + } + + else + snprintf( &bf_error[strlen(bf_error)], sizeof(bf_error)-strlen(bf_error), + "%s IMAGE NOT AVAILABLE FROM HIST fstatus:%u %s", + temp2 < 0 ? "REVERSE" : "FORWARD", + fstatus, iba_fstatus_msg(fstatus) ); + } + + else if ( g_imageIdBookmark.imageNumber != + PACLIENT_IMAGE_CURRENT ) + { + g_imageIdTemp.imageNumber = + g_imageIdBookmark.imageNumber; + g_imageIdTemp.imageOffset = temp2; + + if ( ( fstatus = omgt_pa_freeze_image( g_portHandle, g_imageIdTemp, + &g_imageIdResp) ) == FSUCCESS ) + { + g_imageIdQuery = g_imageIdFreeze = g_imageIdResp; + g_offset = temp2; + } + + else + snprintf( &bf_error[strlen(bf_error)], sizeof(bf_error)-strlen(bf_error), + "%s IMAGE NOT AVAILABLE FROM BKMK fstatus:%u %s", + temp2 < 0 ? "REVERSE" : "FORWARD", + fstatus, iba_fstatus_msg(fstatus) ); + } + + else + snprintf( &bf_error[strlen(bf_error)], sizeof(bf_error)-strlen(bf_error), + "NO IMAGE FROM WHICH TO SELECT" ); + } + + else if ( n_cmd == 't' ) { + uint32 time_val = 0; + + char *ret = strchr(tb_cmd+1, 0x0A); + if (ret) *ret = 0; // clear after enter + + if (( fstatus = StringToDateTime(&time_val, tb_cmd+1)) == FSUCCESS && time_val > 0) + { + if ( g_imageIdQuery.imageNumber == PACLIENT_IMAGE_CURRENT ) + { + g_imageIdTemp.imageNumber = PACLIENT_IMAGE_TIMED; + g_imageIdTemp.imageOffset = 0; + g_imageIdTemp.imageTime.absoluteTime = time_val; + + if ( ( fstatus = omgt_pa_freeze_image(g_portHandle, g_imageIdTemp, + &g_imageIdResp) ) == FSUCCESS ) + { + g_imageIdQuery = g_imageIdFreeze = g_imageIdResp; + g_offset = 0; + } else { + snprintf( &bf_error[strlen(bf_error)], sizeof(bf_error)-strlen(bf_error), + "TIME (%s) IMAGE NOT AVAILABLE fstatus:%u %s", + tb_cmd+1, fstatus, iba_fstatus_msg(fstatus) ); + } + } + else if ( g_imageIdFreeze.imageNumber != PACLIENT_IMAGE_CURRENT ) + { + g_imageIdTemp.imageNumber = PACLIENT_IMAGE_TIMED; + g_imageIdTemp.imageOffset = 0; + g_imageIdTemp.imageTime.absoluteTime = time_val; + + if ( ( fstatus = omgt_pa_move_image_freeze(g_portHandle, g_imageIdFreeze, + &g_imageIdTemp) ) == FSUCCESS ) + { + g_imageIdQuery = g_imageIdFreeze = g_imageIdTemp; + g_offset = 0; + } else { + snprintf( &bf_error[strlen(bf_error)], sizeof(bf_error)-strlen(bf_error), + "TIME (%s) IMAGE NOT AVAILABLE fstatus:%u %s", + tb_cmd+1, fstatus, iba_fstatus_msg(fstatus) ); + } + } + else if ( g_imageIdBookmark.imageNumber != PACLIENT_IMAGE_CURRENT ) + { + g_imageIdTemp.imageNumber = PACLIENT_IMAGE_TIMED; + g_imageIdTemp.imageOffset = 0; + g_imageIdTemp.imageTime.absoluteTime = time_val; + + if ( ( fstatus = omgt_pa_freeze_image( g_portHandle, g_imageIdTemp, + &g_imageIdResp) ) == FSUCCESS ) + { + g_imageIdQuery = g_imageIdFreeze = g_imageIdResp; + g_offset = 0; + } else { + snprintf( &bf_error[strlen(bf_error)], sizeof(bf_error)-strlen(bf_error), + "TIME (%s) IMAGE NOT AVAILABLE fstatus:%u %s", + tb_cmd+1, fstatus, iba_fstatus_msg(fstatus) ); + } + } + } else { + snprintf(&bf_error[strlen(bf_error)], sizeof(bf_error)-strlen(bf_error), + "TIME (%s) FORMAT INVALID fstatus:%u %s", + tb_cmd+1, fstatus, iba_fstatus_msg(fstatus) ); + } + } + + else if ( (n_cmd == 'b') && + ( g_imageIdBookmark.imageNumber != + PACLIENT_IMAGE_CURRENT ) ) + { + if ( g_imageIdFreeze.imageNumber != + PACLIENT_IMAGE_CURRENT ) + { + omgt_pa_release_image(g_portHandle, g_imageIdFreeze); + g_imageIdFreeze.imageNumber = PACLIENT_IMAGE_CURRENT; + } + + g_imageIdQuery.imageNumber = g_imageIdBookmark.imageNumber; + g_offset = g_imageIdQuery.imageOffset = 0; + } + + else if ( (n_cmd == 'B') && + ( g_imageIdBookmark.imageNumber == + PACLIENT_IMAGE_CURRENT ) ) + { + if (g_imageIdQuery.imageNumber == PACLIENT_IMAGE_CURRENT) + { + if ( ( fstatus = omgt_pa_freeze_image(g_portHandle, g_imageIdResp, + &g_imageIdBookmark) ) == FSUCCESS ) + g_imageIdQuery.imageNumber = + g_imageIdBookmark.imageNumber; + + else + snprintf( &bf_error[strlen(bf_error)], sizeof(bf_error)-strlen(bf_error), + "UNABLE TO BOOKMARK LIVE IMAGE fstatus:%u %s", + fstatus, iba_fstatus_msg(fstatus) ); + } + + else if ( g_imageIdFreeze.imageNumber != + PACLIENT_IMAGE_CURRENT ) + { + g_imageIdQuery = g_imageIdBookmark = g_imageIdFreeze; + g_imageIdFreeze.imageNumber = PACLIENT_IMAGE_CURRENT; + } + + else + snprintf( &bf_error[strlen(bf_error)], sizeof(bf_error)-strlen(bf_error), + "NO IMAGE FROM WHICH TO BOOKMARK" ); + + g_offset = 0; + } + + else if ( (n_cmd == 'U') && + ( g_imageIdBookmark.imageNumber != + PACLIENT_IMAGE_CURRENT ) ) + { + if (omgt_pa_release_image(g_portHandle, g_imageIdBookmark) != FSUCCESS) + snprintf( &bf_error[strlen(bf_error)], sizeof(bf_error)-strlen(bf_error), + "UNABLE TO UNBOOKMARK IMAGE"); + + if ( ( g_imageIdQuery.imageNumber == + g_imageIdBookmark.imageNumber ) && + (g_imageIdQuery.imageOffset == 0) ) + g_imageIdQuery.imageNumber = PACLIENT_IMAGE_CURRENT; + + g_imageIdBookmark.imageNumber = PACLIENT_IMAGE_CURRENT; + } + + else if (toupper(n_cmd) == 'Q') + goto quit; + + if (n_level_menu == 0 && toupper(n_cmd) == 'V') { + tb_menu[n_level_menu] = + tb_menu[n_level_menu] == SCREEN_VF_SUMMARY ? + SCREEN_SUMMARY : SCREEN_VF_SUMMARY; + g_group = -1; + //continue; + } + + if (tb_menu[n_level_menu] == SCREEN_SUMMARY || + tb_menu[n_level_menu] == SCREEN_VF_SUMMARY) + { + if (toupper(n_cmd) == 'P') + tb_menu[++n_level_menu] = SCREEN_PM_CONFIG; + + else if (toupper(n_cmd) == 'I') + tb_menu[++n_level_menu] = SCREEN_IMAGE_INFO; + else if (n_cmd == 's' && tb_menu[n_level_menu] == SCREEN_SUMMARY) + g_scroll_summary = g_scroll_summary_forward; + else if (n_cmd == 'S' && tb_menu[n_level_menu] == SCREEN_SUMMARY) + g_scroll_summary = g_scroll_summary_backward; + else if (n_cmd == 's' && tb_menu[n_level_menu] == SCREEN_VF_SUMMARY) + g_scroll_vf_summary = MIN(g_scroll_vf_summary + MAX_VF_SUMMARY_PER_SCREEN, g_PmVFList.numVFs - 1); + else if (n_cmd == 'S' && tb_menu[n_level_menu] == SCREEN_VF_SUMMARY) + g_scroll_vf_summary = MAX(g_scroll_vf_summary - MAX_VF_SUMMARY_PER_SCREEN, 0); + else if (n_cmd >= '0') + { + n_cmd -= '0'; + + if (tb_menu[n_level_menu] == SCREEN_SUMMARY && + fb_valid_group_list && + (g_scroll_summary + n_cmd) < g_PmGroupList.numGroups) { + + g_group = n_cmd + g_scroll_summary; + tb_menu[++n_level_menu] = SCREEN_GROUP_INFO_SELECT; + } + else if (tb_menu[n_level_menu] == SCREEN_VF_SUMMARY && + fb_valid_VF_list && + (g_scroll_vf_summary + n_cmd) < g_PmVFList.numVFs) { + + g_vf = n_cmd + g_scroll_vf_summary; + tb_menu[++n_level_menu] = SCREEN_VF_INFO_SELECT; + } + } + } + + if (tb_menu[n_level_menu] == SCREEN_GROUP_INFO_SELECT) + { + if (toupper(n_cmd) == 'P') + { + tb_menu[++n_level_menu] = SCREEN_GROUP_BW_STATS; + select_idx = 0; + g_select = conditionUtilArray[select_idx]; + } + + else if (toupper(n_cmd) == 'S') + { + tb_menu[++n_level_menu] = SCREEN_GROUP_CTG_STATS; + select_idx = 0; + g_select = conditionCtgArray[select_idx]; + } + else if (toupper(n_cmd) == 'C') + { + g_scroll = 0; + tb_menu[++n_level_menu] = SCREEN_GROUP_CONFIG; + } + } + + if (tb_menu[n_level_menu] == SCREEN_VF_INFO_SELECT) { + if (toupper(n_cmd) == 'P') { + tb_menu[++n_level_menu] = SCREEN_VF_BW_STATS; + select_idx = 0; + g_select = conditionUtilArray[select_idx]; + } else if (toupper(n_cmd) == 'S') { + tb_menu[++n_level_menu] = SCREEN_VF_CTG_STATS; + select_idx = 0; + g_select = conditionCtgArray[select_idx]; + } else if (toupper(n_cmd) == 'C') { + g_scroll = 0; + tb_menu[++n_level_menu] = SCREEN_VF_CONFIG; + } + } + + if ( (tb_menu[n_level_menu] == SCREEN_GROUP_BW_STATS) || + (tb_menu[n_level_menu] == SCREEN_GROUP_CTG_STATS) || + (tb_menu[n_level_menu] == SCREEN_GROUP_FOCUS) ) + { + if ((toupper(n_cmd) == 'I') && g_expr_funct) + if ( (sscanf(tb_cmd + 1, "%lu", &temp) == 1) && + fb_valid_group_config && + (temp < pg_PmGroupConfig.numPorts) ) + g_start = temp; + + if (toupper(n_cmd) == 'N') + if (sscanf(tb_cmd + 1, "%lu", &temp) == 1) + g_range = temp; + } + + if (tb_menu[n_level_menu] == SCREEN_VF_BW_STATS || + tb_menu[n_level_menu] == SCREEN_VF_CTG_STATS || + tb_menu[n_level_menu] == SCREEN_VF_FOCUS) { + /* + if ((toupper(n_cmd) == 'I') && g_expr_funct) + if ( (sscanf(tb_cmd + 1, "%lu", &temp) == 1) && + fb_valid_VF_config && + (temp < pg_PmGroupConfig->numPorts) ) + g_start = temp; + */ + if (toupper(n_cmd) == 'N') + if (sscanf(tb_cmd + 1, "%lu", &temp) == 1) + g_range = temp; + } + + /* if 'c' increment select_idx and handle overflow */ + /* else (if 'C') decrement select_idx and handle underflow */ + if (tb_menu[n_level_menu] == SCREEN_GROUP_BW_STATS ) { + if (toupper(n_cmd) == 'C') { + select_idx = ((n_cmd == 'c') ? ((select_idx + 1) % (g_utilGroupArrayEndIdx + 1)) : + (select_idx ? (select_idx - 1): g_utilGroupArrayEndIdx)); + g_select = conditionUtilArray[select_idx]; + } + } + + if (tb_menu[n_level_menu] == SCREEN_VF_BW_STATS) { + if (toupper(n_cmd) == 'C') { + select_idx = ((n_cmd == 'c') ? ((select_idx + 1) % (g_utilVFArrayEndIdx + 1)) : + (select_idx ? (select_idx - 1) : g_utilVFArrayEndIdx)); + g_select = conditionUtilArray[select_idx]; + } + } + + if (tb_menu[n_level_menu] == SCREEN_GROUP_CTG_STATS ){ + if (toupper(n_cmd) == 'C') { + select_idx = ((n_cmd == 'c') ? ((select_idx + 1) % (g_ctgGroupArrayEndIdx + 1)) : + (select_idx ? (select_idx - 1) : g_ctgGroupArrayEndIdx)); + g_select = conditionCtgArray[select_idx]; + } + } + + if (tb_menu[n_level_menu] == SCREEN_VF_CTG_STATS ){ + if (toupper(n_cmd) == 'C') { + select_idx = ((n_cmd == 'c') ? ((select_idx + 1) % (g_ctgVFArrayEndIdx + 1)) : + (select_idx ? (select_idx - 1) : g_ctgVFArrayEndIdx)); + g_select = conditionCtgArray[select_idx]; + } + } + + if (tb_menu[n_level_menu] == SCREEN_GROUP_FOCUS || + tb_menu[n_level_menu] == SCREEN_VF_FOCUS ) + { + if (toupper(n_cmd) == 'P') + { + if ( (sscanf(tb_cmd + 1, "%lu", &temp) == 1) && + (temp >= g_start) ) + { + if (tb_menu[n_level_menu] == SCREEN_GROUP_FOCUS && + fb_valid_group_focus && + (temp < g_start + pg_PmGroupFocus.numPorts) ) { + g_ix_port = temp; + g_portlid = + pg_PmGroupFocus.portList[g_ix_port - g_start].nodeLid; + g_portnum = + pg_PmGroupFocus.portList[g_ix_port - g_start].portNumber; + fb_port_has_neighbor = (0 != pg_PmGroupFocus.portList[g_ix_port - g_start].neighborLid); + fb_port_neighbor = FALSE; + tb_menu[++n_level_menu] = SCREEN_PORT_STATS; + g_scroll_cntrs = 0; + } else if (tb_menu[n_level_menu] == SCREEN_VF_FOCUS && + fb_valid_VF_focus && + (temp < g_start + g_pPmVFFocus.numPorts)) { + g_ix_port = temp; + g_portlid = + g_pPmVFFocus.portList[g_ix_port - g_start].nodeLid; + g_portnum = + g_pPmVFFocus.portList[g_ix_port - g_start].portNumber; + fb_port_has_neighbor = (0 != g_pPmVFFocus.portList[g_ix_port - g_start].neighborLid); + fb_port_neighbor = FALSE; + tb_menu[++n_level_menu] = SCREEN_PORT_STATS; + g_scroll_cntrs = 0; + } + } + } + else if (toupper(n_cmd) == 'C') { + if (tb_menu[n_level_menu] == SCREEN_GROUP_FOCUS){ + select_idx = ((n_cmd == 'c') ? ((select_idx + 1) % (g_focusGroupArrayEndIdx + 1)) : + (select_idx ? (select_idx - 1) : g_focusGroupArrayEndIdx)); + g_select = conditionFocusArray[select_idx]; + } + else if (tb_menu[n_level_menu] == SCREEN_VF_FOCUS ){ + select_idx = ((n_cmd == 'c') ? ((select_idx + 1) % (g_focusVFArrayEndIdx + 1)) : + (select_idx ? (select_idx - 1) : g_focusVFArrayEndIdx)); + g_select = conditionFocusArray[select_idx]; + } + } + } + + if ( (tb_menu[n_level_menu] == SCREEN_GROUP_BW_STATS) || + (tb_menu[n_level_menu] == SCREEN_GROUP_CTG_STATS) ) + { + if (toupper(n_cmd) == 'D') + { + g_scroll = 0; + tb_menu[++n_level_menu] = SCREEN_GROUP_FOCUS; + } + } + + if ( (tb_menu[n_level_menu] == SCREEN_VF_BW_STATS) || + (tb_menu[n_level_menu] == SCREEN_VF_CTG_STATS) ) { + + if (toupper(n_cmd) == 'D') { + g_scroll = 0; + tb_menu[++n_level_menu] = SCREEN_VF_FOCUS; + } + } + + if (tb_menu[n_level_menu] == SCREEN_GROUP_CONFIG) + { + if (toupper(n_cmd) == 'P') + if ( (sscanf(tb_cmd + 1, "%lu", &temp) == 1) && + fb_valid_group_config && + (temp < pg_PmGroupConfig.numPorts) ) + { + g_ix_port = temp; + g_portlid = + pg_PmGroupConfig.portList[g_ix_port].nodeLid; + g_portnum = + pg_PmGroupConfig.portList[g_ix_port].portNumber; + fb_port_has_neighbor = FALSE; + fb_port_neighbor = FALSE; + tb_menu[++n_level_menu] = SCREEN_PORT_STATS; + g_scroll_cntrs = 0; + } + } + + if (tb_menu[n_level_menu] == SCREEN_GROUP_CONFIG) + { + if (n_cmd == 's' && fb_valid_group_config) + g_scroll = MIN(g_scroll + MAX_GROUPCONFIG_PORTS_PER_SCREEN, pg_PmGroupConfig.numPorts - 1); + else if (n_cmd == 'S') + g_scroll = MAX(g_scroll - MAX_GROUPCONFIG_PORTS_PER_SCREEN, 0); + } + + if (tb_menu[n_level_menu] == SCREEN_VF_CONFIG) + { + if (n_cmd == 's' && fb_valid_VF_config) + g_scroll = MIN(g_scroll + MAX_VFCONFIG_PORTS_PER_SCREEN, g_pPmVFConfig.numPorts - 1); + else if (n_cmd == 'S') + g_scroll = MAX(g_scroll - MAX_VFCONFIG_PORTS_PER_SCREEN, 0); + } + + if (tb_menu[n_level_menu] == SCREEN_VF_CONFIG) + { + if (toupper(n_cmd) == 'P') + if ( (sscanf(tb_cmd + 1, "%lu", &temp) == 1) && + fb_valid_VF_config && + (temp < g_pPmVFConfig.numPorts) ) + { + g_ix_port = temp; + g_portlid = + g_pPmVFConfig.portList[g_ix_port].nodeLid; + g_portnum = + g_pPmVFConfig.portList[g_ix_port].portNumber; + fb_port_has_neighbor = FALSE; + fb_port_neighbor = FALSE; + tb_menu[++n_level_menu] = SCREEN_PORT_STATS; + } + } + + if (tb_menu[n_level_menu] == SCREEN_GROUP_FOCUS) + { + if (n_cmd == 's' && fb_valid_group_focus) + g_scroll = MIN(g_scroll + MAX_GROUPFOCUS_PORTS_PER_SCREEN, pg_PmGroupFocus.numPorts - 1); + else if (n_cmd == 'S') + g_scroll = MAX(g_scroll - MAX_GROUPFOCUS_PORTS_PER_SCREEN, 0); + } + + if (tb_menu[n_level_menu] == SCREEN_VF_FOCUS) { + + if (n_cmd == 's' && fb_valid_VF_focus) + g_scroll = MIN(g_scroll + MAX_VFFOCUS_PORTS_PER_SCREEN, g_pPmVFFocus.numPorts - 1); + else if (n_cmd == 'S') + g_scroll = MAX(g_scroll - MAX_VFFOCUS_PORTS_PER_SCREEN, 0); + } + + if ( (tb_menu[n_level_menu] == SCREEN_PORT_STATS) && + (tb_menu[n_level_menu - 1] == SCREEN_GROUP_FOCUS) ) + { + if ((toupper(n_cmd) == 'N') && fb_valid_group_focus + && fb_port_has_neighbor) + { + if ((fb_port_neighbor = !fb_port_neighbor)) + { + g_portlid = + pg_PmGroupFocus.portList[g_ix_port - g_start].neighborLid; + g_portnum = + pg_PmGroupFocus.portList[g_ix_port - g_start].neighborPortNumber; + } + + else + { + g_portlid = + pg_PmGroupFocus.portList[g_ix_port - g_start].nodeLid; + g_portnum = + pg_PmGroupFocus.portList[g_ix_port - g_start].portNumber; + } + } + } + + if (tb_menu[n_level_menu] == SCREEN_PORT_STATS) { + if (n_cmd == 's') { + g_scroll_cntrs = 1; + } else if (n_cmd == 'S') { + g_scroll_cntrs = 0; + } + } + + if ( (tb_menu[n_level_menu] == SCREEN_PORT_STATS) && + (tb_menu[n_level_menu - 1] == SCREEN_VF_FOCUS) ) + { + if ((toupper(n_cmd) == 'N') && fb_valid_VF_focus + && fb_port_has_neighbor) + { + if ((fb_port_neighbor = !fb_port_neighbor)) + { + g_portlid = + g_pPmVFFocus.portList[g_ix_port - g_start].neighborLid; + g_portnum = + g_pPmVFFocus.portList[g_ix_port - g_start].neighborPortNumber; + } + + else + { + g_portlid = + g_pPmVFFocus.portList[g_ix_port - g_start].nodeLid; + g_portnum = + g_pPmVFFocus.portList[g_ix_port - g_start].portNumber; + } + } + else if ((toupper(n_cmd) == 'V') && fb_valid_VF_focus) + { + g_portlid = + g_pPmVFFocus.portList[g_ix_port - g_start].nodeLid; + g_portnum = + g_pPmVFFocus.portList[g_ix_port - g_start].portNumber; + fb_port_has_neighbor = (0 != g_pPmVFFocus.portList[g_ix_port - g_start].neighborLid); + fb_port_neighbor = FALSE; + tb_menu[++n_level_menu] = SCREEN_VF_PORT_STATS; + } + } + else if ( (tb_menu[n_level_menu] == SCREEN_PORT_STATS) && + (tb_menu[n_level_menu - 1] == SCREEN_VF_CONFIG) ) + { + if ((toupper(n_cmd) == 'V') && fb_valid_VF_focus) + { + g_portlid = + g_pPmVFFocus.portList[g_ix_port - g_start].nodeLid; + g_portnum = + g_pPmVFFocus.portList[g_ix_port - g_start].portNumber; + fb_port_has_neighbor = (0 != g_pPmVFFocus.portList[g_ix_port - g_start].neighborLid); + fb_port_neighbor = FALSE; + tb_menu[++n_level_menu] = SCREEN_VF_PORT_STATS; + } + } + else if ((tb_menu[n_level_menu] == SCREEN_VF_PORT_STATS) && + (tb_menu[n_level_menu - 2] == SCREEN_VF_FOCUS) ) + { + if ((toupper(n_cmd) == 'N') && fb_valid_VF_focus + && fb_port_has_neighbor) + { + if ((fb_port_neighbor = !fb_port_neighbor)) + { + g_portlid = + g_pPmVFFocus.portList[g_ix_port - g_start].neighborLid; + g_portnum = + g_pPmVFFocus.portList[g_ix_port - g_start].neighborPortNumber; + } + else + { + g_portlid = + g_pPmVFFocus.portList[g_ix_port - g_start].nodeLid; + g_portnum = + g_pPmVFFocus.portList[g_ix_port - g_start].portNumber; + } + } + else if ((toupper(n_cmd) == 'V') && fb_valid_VF_focus) + { + --n_level_menu; + } + } + else if ( (tb_menu[n_level_menu] == SCREEN_VF_PORT_STATS) && + (tb_menu[n_level_menu - 2] == SCREEN_VF_CONFIG) ) + { + if ((toupper(n_cmd) == 'V') && fb_valid_VF_focus) + { + --n_level_menu; + } + } + tb_cmd[0] = 0; + DisplayScreen(NULL); + + } // End of if ((temp2 = select(1, &fd_set_read, NULL, NULL + else if (isdelchar) { + printf("\b \b"); + fflush(stdout); + } + } // End of while ((time(NULL) - time_start) < g_interval) + + // Renew frozen image if present + if (g_imageIdFreeze.imageNumber != PACLIENT_IMAGE_CURRENT) + omgt_pa_renew_image(g_portHandle, g_imageIdFreeze); + + // Renew bookmark image if present + if (g_imageIdBookmark.imageNumber != PACLIENT_IMAGE_CURRENT) + omgt_pa_renew_image(g_portHandle, g_imageIdBookmark); + + } // End of while (TRUE) + +quit: + // release any frozen image + if (g_imageIdFreeze.imageNumber != PACLIENT_IMAGE_CURRENT) + omgt_pa_release_image(g_portHandle, g_imageIdFreeze); + + // release any bookmark image + if (g_imageIdBookmark.imageNumber != PACLIENT_IMAGE_CURRENT) + omgt_pa_release_image(g_portHandle, g_imageIdBookmark); + + // restore terminal settings + tcsetattr(fileno(stdin), TCSAFLUSH, &g_term_save); + +done: + if (g_portHandle) omgt_close_port(g_portHandle); + g_portHandle = NULL; + + if (g_exitstatus == 2) + Usage(); + + return g_exitstatus; +} diff --git a/IbaTools/opatop/opatop_group_bw.hlp b/IbaTools/opatop/opatop_group_bw.hlp new file mode 100644 index 0000000..719a623 --- /dev/null +++ b/IbaTools/opatop/opatop_group_bw.hlp @@ -0,0 +1,29 @@ +HELP: GROUP BW UTIL SCREEN +The Bandwidth Utilization screen shows, for each valid performance data +subgroup (Internal, Send, Receive), the total, average, minimum and maximum +MBps and KPps (see SUMMARY SCREEN help for terminology). For each subgroup +ten performance 'buckets', from 0+% to 90+% in 10% increments, count the number +of ports whose 'MBps compared to link speed' value corresponds to that bucket. +This provides an indication of how the data rate of the group compares to its +potential. Also present on the screen are two categories of port issues per +subgroup: No response on PM query (PMA) and PM topology incomplete (Topo). PMA +issues occur when the PM does not receive a response during the PM Sweep. Topo +issues occur whem PM cannot determine the neighbor information of the local +port in the topology. + +The BW Util screen accepts input commands which specify parameters to be +used in a group focus query, which will provide a list of ports (in the port +group) sorted according to a specified performance criterion. The second +line of the BW Util screen displays the group name, and the currently +selected focus criterion and number of ports for a group focus query. The +'D' command causes the group focus query to be performed and displayed in +a Group Focus screen. The following input commands are accepted in the +BW Util screen. + + C: Select group focus criterion forward (c*) or reverse (C*): + Utilization (highest first) + Utilization Packets (highest first) + Utilization (lowest first) + Nn: Number of entries n in group focus list + D: Display detail group focus list + diff --git a/IbaTools/opatop/opatop_group_config.hlp b/IbaTools/opatop/opatop_group_config.hlp new file mode 100644 index 0000000..5a0b739 --- /dev/null +++ b/IbaTools/opatop/opatop_group_config.hlp @@ -0,0 +1,12 @@ +HELP: GROUP CONFIG SCREEN +The Group Configuration screen displays a list of the ports in a group, +including the LID, port number, node GUID and NodeDesc of each. The second +line of the screen displays the group name and the number of ports returned in +the group config query. If more ports exist than will fit on a screen, the +list can be scrolled forward and backward. An index value, shown with each +port, can be used to select the port and show the port's counters in a Port +Stats screen. The Group Config screen accepts the following input commands. + + S: Scroll forward (s*) or backward (S*) through port list + Pn: Select port index value n + diff --git a/IbaTools/opatop/opatop_group_ctg.hlp b/IbaTools/opatop/opatop_group_ctg.hlp new file mode 100644 index 0000000..b2ae02a --- /dev/null +++ b/IbaTools/opatop/opatop_group_ctg.hlp @@ -0,0 +1,68 @@ +HELP: GROUP/VF CATEGORY STATS SCREEN +Category Stats for a port group/VF are divided into up to two subgroups - +Internal or External - based on whether a port's neighbor port is in its group +(Internal) or not (External). In the All group all ports are Internal. For +example in the HFIs group all ports are External. In the SWs group ports may be +Internal or External. The six categories are based on mapping each port +counter into one of the categories as follows. The integrity and congestion +counter values are calculated by using a weighted sum. The weights for each +and the threshold value for each category can be seen in the PM Config screen. +Some counters are gathered from the neighbor's port instead. + + Integrity: + Local Link Integrity Errors + Port Receive Errors + Excessive Buffer Overrun Errors (neighbor port) + Link Error Recovery + Link Downed + Uncorrectable Errors + FM Config Errors + + Congestion: + Port Transmit Wait + Switch Port Congestion + Port Receive FECN (neighbor port) + Port Receive BECN (only from FIs) + Port Transmit Time Congestion + Port Mark FECN + + SmaCongestion: + The counters included in the SMA Congestion category are the VL 15 counters + equivalent to the port counters in the Congestion category. + + Bubble: + Port Transmit Wasted Bandwidth + Port Transmit Wait Data + Port Receive Bubble (neighbor port) + + Security: + Port Receive Constraint Errors (neighbor port) + Port Transmit Constraint Errors + + Routing: + Port Receive Switch Relay Errors + +For each subgroup within a category, there are five histogram buckets. Each +bucket has a width of 25%(0+%, 25+%, etc) and the last bucket for over the +threshold(100+%). A bucket is used to measure the number of ports whose category +value when compared to the threshold falls within the range of the bucket. This +provides an indication of how counter rates compare to their thresholds. + +The Ctg Stats screen accepts input commands which specify parameters to be +used in a group focus query, which will provide a list of ports sorted +according to a specified category criterion. The second line of the Ctg Stats +screen displays the group name, and the currently selected focus criterion +and number of ports for a group focus query. The 'D' command causes the group +focus query to be performed and displayed in a Group Focus screen. The +following input commands are accepted in the Ctg Stats screen. + + C: Select group focus criterion forward (c*) or reverse (C*): + Integrity category (highest first) + Congestion category (highest first) + SmaCongestion category (highest first) + Bubble category (highest first) + Security category (highest first) + Routing category (highest first) + Nn: Number of entries n in group focus list + D: Display detail group focus list + diff --git a/IbaTools/opatop/opatop_group_focus.hlp b/IbaTools/opatop/opatop_group_focus.hlp new file mode 100644 index 0000000..e51e652 --- /dev/null +++ b/IbaTools/opatop/opatop_group_focus.hlp @@ -0,0 +1,33 @@ +HELP: GROUP/VF FOCUS SCREEN +The Group/VF Focus screen displays a list of the focus ports in a group/VF, +including the LID, port number, focus criterion value, node GUID and +NodeDesc of each. If the port has a neighbor port, the same information +is displayed for the neighbor. The second line of the screen displays +the group/VF name, the number of ports returned in the group/VF focus query, +and the number of ports requested in the group/VF focus query. If more ports +exist than will fit on a screen, the list can be scrolled forward and +backward. Like the BW Stats and Ctg Stats screens which preceed this screen, +the focus criterion and number of requested focus ports can be changed to +modify the focus port list. An index value, shown with each port, can be +used to select the port and show the port's counters in a Port Stats screen. +A symbol may be present on the first character of the line to indicate a +non-ideal condition was observed when calculating this ports data. The +possible conditions are, the PM was told to ignore this port ('~'), the port +did not respond to the PM query('!'), and the PM topology does not know +this port's identity ('?'). + +The Group/VF Focus screen accepts the following input commands. + S: Scroll forward (s*) or backward (S*) through port list + C: Select group/VF focus criteria forward (c*) or reverse (C*): + Utilization (highest first) + Utilization Packets (highest first) + Utilization (lowest first) + Integrity category (highest first) + Congestion category (highest first) + SmaCongestion category (highest first) + Bubble category (highest first) + Security category (highest first) + Routing category (highest first) + Nn: Number of entries n in group/VF focus list + Pn: Select port index value n + diff --git a/IbaTools/opatop/opatop_group_info_sel.hlp b/IbaTools/opatop/opatop_group_info_sel.hlp new file mode 100644 index 0000000..b31c0af --- /dev/null +++ b/IbaTools/opatop/opatop_group_info_sel.hlp @@ -0,0 +1,9 @@ +HELP: GROUP INFO SELECT SCREEN +The Group Info Select screen allows the user to select the type of group +information to display for the group selected in the summary screen. The +following input commands are accepted and lead to the corresponding screen. + + P: Performance (Bandwidth Utilization) + S: Category statistics + C: Group configuration (port list) + diff --git a/IbaTools/opatop/opatop_img_config.hlp b/IbaTools/opatop/opatop_img_config.hlp new file mode 100644 index 0000000..60d44aa --- /dev/null +++ b/IbaTools/opatop/opatop_img_config.hlp @@ -0,0 +1,6 @@ +HELP: IMAGE INFO SCREEN +The Image Info screen displays image information as provided by +the PM. Sweep start and duration, numbers of ports in each group, node +and port information for the sweep, and SM information is shown. The +Image Info screen has no screen-specific input commands. + diff --git a/IbaTools/opatop/opatop_pm_config.hlp b/IbaTools/opatop/opatop_pm_config.hlp new file mode 100644 index 0000000..2cf26ce --- /dev/null +++ b/IbaTools/opatop/opatop_pm_config.hlp @@ -0,0 +1,8 @@ +HELP: PM CONFIG SCREEN +The PM Configuration screen displays information as provided by the PM. +The Sweep Interval parameter is separate from the opatop interval. +Normally the opatop interval should be set to a value >= Sweep Interval. +PM image configuration information (total images, freeze images, freeze +lease time), category thresholds and weights, PM memory footprint, and PM MAD +retry/timeout information is shown. The PM Config screen has no +screen-specific input commands. diff --git a/IbaTools/opatop/opatop_port_stats.hlp b/IbaTools/opatop/opatop_port_stats.hlp new file mode 100644 index 0000000..d65c7bf --- /dev/null +++ b/IbaTools/opatop/opatop_port_stats.hlp @@ -0,0 +1,27 @@ +HELP: PORT STATS SCREEN +The Port Statistics screen displays a port's performance counters. +Performance counters are grouped according to the category to which they +belong. A trailing asterisk ('*') on the counter name indicates the counter +will be tabulated against the neighbor ports category statistics. + +The Port Statistics screen is split over two pages, which can be accessed by +scrolling forward or backward to access more port statistics. When the Port +Stats screen is entered from the Group Focus or VF Focus screen, port neighbor +and link information is available. When the Port Stats screen is entered from +the Group Config or VF Config screen, this information is not available. The +second line of the Port Stats screen displays the group name, and LID and port +number of the port, as well as link rate and MTU (if available). The third line +of the screen displays the NodeDesc and node GUID of the port. The fourth line +of the screen displays the NodeDesc, LID and port number of the neighbor port +(if available). These four lines repeat on both pages of the Port Statistics +screen. + +The remaining lines on the pages are used to display the groups of error +counters. The last category, SmaCongestion, shows counters gathered using VF +Port Counters query (if available). The Port Stats screen accepts the following +input commands. + + V: Switch to VF port statistics for the port in the selected VF (if available) + N: Switch between statistics for port and port's neighbor (if available) + S: Scroll forward (s*) or backward (S*) through counter pages + diff --git a/IbaTools/opatop/opatop_summary.hlp b/IbaTools/opatop/opatop_summary.hlp new file mode 100644 index 0000000..e12bbde --- /dev/null +++ b/IbaTools/opatop/opatop_summary.hlp @@ -0,0 +1,132 @@ +HELP: SUMMARY SCREEN +opatop is a command line tool which displays performance analysis +information about a fabric. Performance analysis information is divided +into two areas - utilization and category statistics, which are main starting +points for analyzing fabric traffic. Utilization can identify over-utilized +areas (bottle necks) and under-utilized areas (potentially misconfigured); +category statistics can identify problems in fabric hardware or configuration. + +On the help screens you may use these commands: + u: Up to previous screen (done help) + S: Scroll forward (s) or backward (S) by 1 screen through help + : Scroll forward 1 line (space key) + +The top level (summary) screen of opatop shows basic fabric configuration +information as well as utilization and category statistics. Fabric +configuration information includes numbers of links, switches, SMs, and +ports, as well as details about the master and secondary (if present) SMs. +Fabric utilization and category statistics are presented based on PM port +groups, which include the predefined PM groups: All (all ports in the fabric), +HFIs, and SWs. These groups provide a natural subdivision of the ports in +a fabric for performance analysis. The summary screen also will include any +sysadmin defined PmPortGroups. + +The user may toggle between a PM group based summary display and a Virtual +Fabric (VF) based summary display. The VF display will show all presently +enabled Virtual Fabrics. + +After looking at the summary screen a user can decide which area of +performance (utilization or category statistics) and which group of ports +most warrants investigation, and can then "drill down" into that area. + +If the message "Unexpected Clear" (or "Unexp Clear") is reported, this means +one or more devices have had their PMA counters unexpectedly cleared by +something other than the PM. For Intel switches, make sure ismAutoClearConf +is disabled. For HFIs make sure that other tools such as opareport or +OFED diagnostics are not being run in a manner which would directly clear +PMA counters. The Image Info Screen will indicate how many such ports +were affected. + +For each port group or VF, average, minimum and maximum MBps (megabytes +per second), and KPps (kilo-packets per second) are shown, as well +as a status indicator for each of six counter categories. +(Note: mega=1,000,000; kilo=1000) + +Performance utilization for each port group are further divided into up to +three subgroups - Internal, Send and Receive - based on whether a port's +neighbor port is in its group. If a port's neighbor port is in its group, +all performance utilization are contained in the Internal subgroup. If a port's +neighbor is not in its group, utilization for data leaving the port (group) are +contained in the Send subgroup and utilization for data entering the port are +contained in the Receive subgroup. + +In the All group all ports are Internal since, by definition, the neighbor port +must be in the All group. In the HFIs group all neighbor ports are outside the +group so utilization are contained in the Send and Receive subgroups. In the +SWs group neighbor ports are either outside the group (HFI) or inside the +group (another switch) so utilization are contained in all three subgroups. + +For VF summary display, all information is reported as Internal. + +The six category statistics are: Integrity, Congestion, SMA Congestion, +Bubble, Security and Routing, and are based on mapping each port counter +into one of the six categories. Each category status indicator is shown at +one of five values/colors: minimum/green, Low/blue, Moderate/cyan, +Warning/yellow or OVER/red based on the category value as compared +to a threshold value. + +opatop allows the user to access statistics from sequential PM sweeps +(the PM keeps a history of previous sweep images) and queries the PM at a +user-specified interval (10 seconds by default). + +When opatop queries for statistics for the most recent PM sweep it is in +'Live' mode. In Live mode data will change, at the opatop interval rate, +as opatop queries new PM sweeps. At each screen (summary or detail) the data +being displayed is refreshed for the current PM sweep. + +A PM sweep can be 'frozen'; the data in a frozen sweep will not change, +allowing the statistics to be examined in summary and detail screens. +Two user actions result in a sweep being frozen. The first is when the user +'Bookmarks' a sweep. A Bookmarked sweep will remain frozen until the user +explicitly 'Unbookmarks' it; one sweep at a time can be Bookmarked. +The second action is when the user moves (navigates) opatop's focus to another +sweep within the history of sweeps maintained by the PM. For the duration +of opatop's focus on such a sweep it will remain frozen. Navigation can occur +from Live mode or when displaying a Bookmarked image; during navigation opatop +is in 'Historic' mode. Navigation can be performed backward or forward, +moving 1 or 5 sweeps at a time. + +opatop is designed to fit within an 80x24 terminal screen. It is recommended +to use a fixed width font, such as Courier. While STL supports up to 63 +character names for many things (PM port groups, Virtual Fabrics, node +descriptions, etc), in order to fit on the screen opatop may truncate these +and show only the beginning characters. When opatop truncates a name, it will +show a * as the last character. For example, MyStoragePmPortGroup will be +truncated to MyStorageP* when displayed in the Port group summary screen. + +The first display line of opatop shows the image interval, if available, the +timestamp for the image being displayed, and the type of image (Live, Hist, +Bkmk). The image interval is the time over which this image data is relevant. +For in memory images this value is equal to the PM Sweep Interval. For +images stored on disk (Short Term History), the interval is equal to the sum +of all the intervals for each image compounded into the composite (disk) +image. The interval can change when transitioning between images stored in +memory and images stored on disk. If a Live image is not being displayed, +the current time ('Now:') is also shown. The last display line of opatop is +a prompt showing available input commands. The left section of commands are +available in every screen and perform the same action. The right section are +screen-specific. Commands are case insensitive except as noted by '*'; the +ENTER key must be pressed after a command. Note that a help command '?' is +available at every screen and provides information about the screen contents +and input commands. + +The following input commands are available in every screen: + Q: Quit program + u*: Up to previous screen + L: Select Live image + R: Navigate reverse 1 (r*) or 5 (R*) sweeps + F: Navigate forward 1 (f*) or 5 (F*) sweeps + t*: Navigate to a provided time + b*: Select (previously) Bookmarked image + B*: Bookmark currently selected image + U*: Unbookmark Bookmarked image + ?: Help + +The summary screen accepts the following input commands: + + S: Scroll forward (s*) or backward (S*) through list + P: PM Configuration screen + I: Image Info screen + 0-n: Select item from list + V: Change between Virtual Fabrics and Port Group based views. + diff --git a/IbaTools/opatop/opatop_vf_bw.hlp b/IbaTools/opatop/opatop_vf_bw.hlp new file mode 100644 index 0000000..2207bf5 --- /dev/null +++ b/IbaTools/opatop/opatop_vf_bw.hlp @@ -0,0 +1,28 @@ +HELP: VF BW UTIL SCREEN +The Bandwidth Utilization screen shows the total, average, minimum and maximum +MBps and KPps (see SUMMARY SCREEN help for terminology). There exist ten +utilization 'buckets', from 0+% to 90+% in 10% increments, count the number +of ports whose 'MBps compared to link speed' value corresponds to that bucket. +This provides an indication of how the data rate of the group compares to its +potential. Also present on the screen are two categories of port issues: No +response on PM query (PMA) and PM topology incomplete (Topo). PMA issues occur +when the PM does not receive a successful response during the PM Sweep. Topo +issues occur whem PM cannot determine the neighbor information of the local +port in the topology. + +The BW Util screen accepts input commands which specify parameters to be +used in a group focus query, which will provide a list of ports (in the port +group) sorted according to a specified performance criterion. The second +line of the BW Util screen displays the group name, and the currently +selected focus criterion and number of ports for a group focus query. The +'D' command causes the group focus query to be performed and displayed in +a Group Focus screen. The following input commands are accepted in the +BW Util screen. + + C: Select group focus criterion forward (c*) or reverse (C*): + Utilization (highest first) + Utilization Packets (highest first) + Utilization (lowest first) + Nn: Number of entries n in VF focus list + D: Display detail VF focus list + diff --git a/IbaTools/opatop/opatop_vf_config.hlp b/IbaTools/opatop/opatop_vf_config.hlp new file mode 100644 index 0000000..3f195a8 --- /dev/null +++ b/IbaTools/opatop/opatop_vf_config.hlp @@ -0,0 +1,12 @@ +HELP: VF CONFIG SCREEN +The VF Configuration screen displays a list of the ports in a VF, +including the LID, port number, port GUID and NodeDesc of each. The second +line of the screen displays the VF name and the number of ports returned in +the VF config query. If more ports exist than will fit on a screen, the +list can be scrolled forward and backward. An index value, shown with each +port, can be used to select the port and show the port's counters in a Port +Stats screen. The VF Config screen accepts the following input commands. + + S: Scroll forward (s*) or backward (S*) through port list + Pn: Select port index value n + diff --git a/IbaTools/opatop/opatop_vf_info_sel.hlp b/IbaTools/opatop/opatop_vf_info_sel.hlp new file mode 100644 index 0000000..fe87fab --- /dev/null +++ b/IbaTools/opatop/opatop_vf_info_sel.hlp @@ -0,0 +1,9 @@ +HELP: VF INFO SELECT SCREEN +The VF Info Select screen allows the user to select the type of VF +information to display for the group selected in the summary screen. The +following input commands are accepted and lead to the corresponding screen. + + P: Performance (Bandwidth Utilization) + S: Category statistics + C: Group configuration (port list) + diff --git a/IbaTools/opatop/opatop_vf_port_stats.hlp b/IbaTools/opatop/opatop_vf_port_stats.hlp new file mode 100644 index 0000000..887adc0 --- /dev/null +++ b/IbaTools/opatop/opatop_vf_port_stats.hlp @@ -0,0 +1,20 @@ +HELP: VF PORT STATS SCREEN +The VF Port Statistics screen displays a VF port's performance counters +Performance counters are grouped according to the category to which they +belong. A trailing asterisk ('*') on the counter name indicates the counter +will be tabulated against the neighbor ports category statistics. + +When the VF Port Stats screen is entered from VF Focus screen, port neighbor +and link information is available. When the VF Port Stats screen is entered +from the VF Config screen, this information is not available. The second +line of the VF Port Stats screen displays the group name, and LID and port +number of the port, as well as link rate and MTU (if available). The third +line of the screen displays the NodeDesc and node GUID of the port. The fourth +line of the screen displays the NodeDesc, LID and port number of the neighbor +port(if available). + +The remaining lines on the pages are used to display the groups of VF port +counters. + + N: Switch between statistics for port and port's neighbor (if available) + V: Switch between Port Stats and VF Port Stats screens for the selected port diff --git a/IbaTools/opaxlattopology/Makefile b/IbaTools/opaxlattopology/Makefile new file mode 100644 index 0000000..81b1ecd --- /dev/null +++ b/IbaTools/opaxlattopology/Makefile @@ -0,0 +1,160 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** +# Makefile for opaxlattopology + +# Include Make Control Settings +include $(TL_DIR)/$(PROJ_FILE_DIR)/Makesettings.project + +#=============================================================================# +# Definitions: +#-----------------------------------------------------------------------------# + +# Name of SubProjects +DS_SUBPROJECTS = +# name of executable or downloadable image +EXECUTABLE = +# list of sub directories to build +DIRS = +# C files (.c) +CFILES = \ + # Add more c files here +# C++ files (.cpp) +CCFILES = \ + # Add more cpp files here +# lex files (.lex) +LFILES = \ + # Add more lex files here +# archive library files (basename, $ARFILES will add MOD_LIB_DIR/prefix and suffix) +LIBFILES= +# Windows Resource Files (.rc) +RSCFILES = +# Windows IDL File (.idl) +IDLFILE = +# Windows Linker Module Definitions (.def) file for dll's +DEFFILE = +# targets to build during INCLUDES phase (add public includes here) +INCLUDE_TARGETS = \ + # Add more h hpp files here +# Non-compiled files +MISC_FILES = \ + minimal_topology.xlsx detailed_topology.xlsx \ + linksum_swd06.csv linksum_swd24.csv \ + README.xlat_topology +# all source files +SOURCES = $(CFILES) $(CCFILES) $(LFILES) $(RSCFILES) $(IDLFILE) +# Source files to include in DSP File +DSP_SOURCES = $(INCLUDE_TARGETS) $(SOURCES) $(MISC_FILES) \ + $(RSCFILES) $(DEFFILE) $(MAKEFILE) +# all object files +OBJECTS = $(CFILES:.c=$(OBJ_SUFFIX)) $(CCFILES:.cpp=$(OBJ_SUFFIX)) \ + $(LFILES:.lex=$(OBJ_SUFFIX)) +RSCOBJECTS = $(RSCFILES:.rc=$(RES_SUFFIX)) +# targets to build during LIBS phase +LIB_TARGETS_IMPLIB = +LIB_TARGETS_ARLIB = # $(LIB_PREFIX)ResourceTest$(ARLIB_SUFFIX) +LIB_TARGETS_EXP = $(LIB_TARGETS_IMPLIB:$(ARLIB_SUFFIX)=$(EXP_SUFFIX)) +LIB_TARGETS_MISC = +# targets to build during CMDS phase +CMD_TARGETS_SHLIB = +CMD_TARGETS_EXE = $(EXECUTABLE) +CMD_TARGETS_MISC = opaxlattopology +# files to remove during clean phase +CLEAN_TARGETS_MISC = +CLEAN_TARGETS = $(OBJECTS) $(RSCOBJECTS) $(IDL_TARGETS) $(CLEAN_TARGETS_MISC) +# other files to remove during clobber phase +CLOBBER_TARGETS_MISC= detailed_topology.xlsx +# sub-directory to install to within bin +BIN_SUBDIR = +# sub-directory to install to within include +INCLUDE_SUBDIR = + +# Additional Settings +#CLOCALDEBUG = User defined C debugging compilation flags [Empty] +#CCLOCALDEBUG = User defined C++ debugging compilation flags [Empty] +#CLOCAL = User defined C flags for compiling [Empty] +#CCLOCAL = User defined C++ flags for compiling [Empty] +#BSCLOCAL = User flags for Browse File Builder [Empty] +#DEPENDLOCAL = user defined makedepend flags [Empty] +#LINTLOCAL = User defined lint flags [Empty] +#LOCAL_INCLUDE_DIRS = User include directories to search for C/C++ headers [Empty] +#LDLOCAL = User defined C flags for linking [Empty] +#IMPLIBLOCAL = User flags for Object Lirary Manager [Empty] +#MIDLLOCAL = User flags for IDL compiler [Empty] +#RSCLOCAL = User flags for resource compiler [Empty] +#LOCALDEPLIBS = User libraries to include in dependencies [Empty] +#LOCALLIBS = User libraries to use when linking [Empty] +# (in addition to LOCALDEPLIBS) +#LOCAL_LIB_DIRS = User library directories for libpaths [Empty] + +CLOCAL=$(CIBACCESS) $(CPIE) +LOCALDEPLIBS = +LOCAL_INCLUDE_DIRS= +LOCALLIBS= +LOCAL_LIB_DIRS= + +# Include Make Rules definitions and rules +include $(TL_DIR)/IbaTools/Makerules.module + +#=============================================================================# +# Overrides: +#-----------------------------------------------------------------------------# +#CCOPT = # C++ optimization flags, default lets build config decide +#COPT = # C optimization flags, default lets build config decide +#SUBSYSTEM = Subsystem to build for (none, console or windows) [none] +# (Windows Only) +#USEMFC = How Windows MFC should be used (none, static, shared, no_mfc) [none] +# (Windows Only) +#=============================================================================# + +#=============================================================================# +# Rules: +#-----------------------------------------------------------------------------# +# process Sub-directories +include $(TL_DIR)/Makerules/Maketargets.toplevel + +# build cmds and libs +include $(TL_DIR)/Makerules/Maketargets.build + +# install for includes, libs and cmds phases +include $(TL_DIR)/Makerules/Maketargets.install + +# install for stage phase +#include $(TL_DIR)/Makerules/Maketargets.stage +STAGE:: + $(VS)$(STAGE_INSTALL) $(STAGE_INSTALL_DIR_OPT) $(PROJ_STAGE_FASTFABRIC_DIR) $(EXECUTABLE) opaxlattopology + $(VS)$(STAGE_INSTALL) $(STAGE_INSTALL_DIR_OPT) $(PROJ_STAGE_FASTFABRIC_DIR)/samples minimal_topology.xlsx detailed_topology.xlsx linksum_swd06.csv linksum_swd24.csv README.xlat_topology + +# Unit test execution +#include $(TL_DIR)/Makerules/Maketargets.runtest + +#=============================================================================# + +#=============================================================================# +# DO NOT DELETE THIS LINE -- make depend depends on it. +#=============================================================================# diff --git a/IbaTools/opaxlattopology/README.xlat_topology b/IbaTools/opaxlattopology/README.xlat_topology new file mode 100644 index 0000000..792a8e3 --- /dev/null +++ b/IbaTools/opaxlattopology/README.xlat_topology @@ -0,0 +1,41 @@ +[ICS VERSION STRING: unknown] + +Script opaxlattopology and accompanying sample spreadsheet minimal_topology.xlsx +and detailed_topology.xlsx (named as topology.xlsx hence forth) +provide the capability to document the topology of a customer cluster, +and generate a topology XML file based on that topology ("translate" +the spread sheet to a topology file). The topology file can be used +to bring up and verify the cluster. The exact steps to be used in +the verification process are beyond the scope of this description. + +topology.xlsx provides a standard format for representing each +external link in a cluster. Each link contains source, destination +and cable fields with one link per line (row) of the spread sheet. Link +fields must not contain commas. Source and destination fields each are: +Rack Group ("rack row"), Rack, Name (primary name), Name-2 (secondary name), +Port Number and Port Type. Cable fields are: Label, Length and Details. + +opaxlattopology takes as inputs the CSV (Comma-Separated-Values) form of +the topology.xlsx cluster tab, and CSV files for (internal) core switch +links (100SWD06 and/or 100SWD24). The CSV spread sheet cluster tab +is named topology.csv; the core switch links files are linksum_swd06.csv +and linksum_swd24.csv respectively. topology.csv is created from topology.xlsx +by saving/exporting the tab as 'CSV' to topology.csv. (topology.csv +should be inspected to ensure that output rows contain the correct number +of link fields; extraneous entries on the spread sheet can cause excel +to output extra fields.) opaxlattopology produces as output one or more +topology files 'topology.0:0.xml'. Output at the top-level as well as +(optionally) Group, Rack, and Switch level can be produced. Input files +must be present in the directory from which the script operates. + +linksum_swd06.csv and linksum_swd24.csv are provided as stand-alone source +files. However, they can be recreated (or modified) from topology.xlsx, +if needed, by the following: +1) Save/export, individually as CSV files, the 'Internal SWD06 Links' and + 'Internal SWD24 Links' tabs of topology.xlsx as 'topology.csv'. +2) For each saved topology.csv file, run opaxlattopology with the -K + option. Upon completion of the script save the top-level 'linksum.csv' + file as 'linksum_swd06.csv' or 'linksum_swd24.csv' as appropriate. + +See release notes for more information on using opaxlattopology and +topology.xlsx. diff --git a/IbaTools/opaxlattopology/detailed_topology.xlsx b/IbaTools/opaxlattopology/detailed_topology.xlsx new file mode 100755 index 0000000..6b37f67 Binary files /dev/null and b/IbaTools/opaxlattopology/detailed_topology.xlsx differ diff --git a/IbaTools/opaxlattopology/detailed_topology.xlsx.base b/IbaTools/opaxlattopology/detailed_topology.xlsx.base new file mode 100755 index 0000000..6b37f67 Binary files /dev/null and b/IbaTools/opaxlattopology/detailed_topology.xlsx.base differ diff --git a/IbaTools/opaxlattopology/detailed_topology.xlsx.opa10 b/IbaTools/opaxlattopology/detailed_topology.xlsx.opa10 new file mode 100755 index 0000000..6b37f67 Binary files /dev/null and b/IbaTools/opaxlattopology/detailed_topology.xlsx.opa10 differ diff --git a/IbaTools/opaxlattopology/detailed_topology.xlsx.opa11 b/IbaTools/opaxlattopology/detailed_topology.xlsx.opa11 new file mode 100644 index 0000000..48935d7 Binary files /dev/null and b/IbaTools/opaxlattopology/detailed_topology.xlsx.opa11 differ diff --git a/IbaTools/opaxlattopology/linksum_swd06.csv b/IbaTools/opaxlattopology/linksum_swd06.csv new file mode 100644 index 0000000..3858cfe --- /dev/null +++ b/IbaTools/opaxlattopology/linksum_swd06.csv @@ -0,0 +1,288 @@ +100g;10240;1;;;;01;SW;ZzNAMEqQ S201A;48;SW;ZzNAMEqQ L101A +100g;10240;1;;;;01;SW;ZzNAMEqQ S201B;48;SW;ZzNAMEqQ L102B +100g;10240;1;;;;01;SW;ZzNAMEqQ S202A;48;SW;ZzNAMEqQ L103A +100g;10240;1;;;;01;SW;ZzNAMEqQ S202B;48;SW;ZzNAMEqQ L104B +100g;10240;1;;;;01;SW;ZzNAMEqQ S203A;48;SW;ZzNAMEqQ L105A +100g;10240;1;;;;01;SW;ZzNAMEqQ S203B;48;SW;ZzNAMEqQ L106B +100g;10240;1;;;;02;SW;ZzNAMEqQ S201A;47;SW;ZzNAMEqQ L101A +100g;10240;1;;;;02;SW;ZzNAMEqQ S201B;47;SW;ZzNAMEqQ L102B +100g;10240;1;;;;02;SW;ZzNAMEqQ S202A;47;SW;ZzNAMEqQ L103A +100g;10240;1;;;;02;SW;ZzNAMEqQ S202B;47;SW;ZzNAMEqQ L104B +100g;10240;1;;;;02;SW;ZzNAMEqQ S203A;47;SW;ZzNAMEqQ L105A +100g;10240;1;;;;02;SW;ZzNAMEqQ S203B;47;SW;ZzNAMEqQ L106B +100g;10240;1;;;;03;SW;ZzNAMEqQ S201A;46;SW;ZzNAMEqQ L105A +100g;10240;1;;;;03;SW;ZzNAMEqQ S201B;46;SW;ZzNAMEqQ L106B +100g;10240;1;;;;03;SW;ZzNAMEqQ S202A;46;SW;ZzNAMEqQ L101A +100g;10240;1;;;;03;SW;ZzNAMEqQ S202B;46;SW;ZzNAMEqQ L102B +100g;10240;1;;;;03;SW;ZzNAMEqQ S203A;46;SW;ZzNAMEqQ L103A +100g;10240;1;;;;03;SW;ZzNAMEqQ S203B;46;SW;ZzNAMEqQ L104B +100g;10240;1;;;;04;SW;ZzNAMEqQ S201A;45;SW;ZzNAMEqQ L105A +100g;10240;1;;;;04;SW;ZzNAMEqQ S201B;45;SW;ZzNAMEqQ L106B +100g;10240;1;;;;04;SW;ZzNAMEqQ S202A;45;SW;ZzNAMEqQ L101A +100g;10240;1;;;;04;SW;ZzNAMEqQ S202B;45;SW;ZzNAMEqQ L102B +100g;10240;1;;;;04;SW;ZzNAMEqQ S203A;45;SW;ZzNAMEqQ L103A +100g;10240;1;;;;04;SW;ZzNAMEqQ S203B;45;SW;ZzNAMEqQ L104B +100g;10240;1;;;;05;SW;ZzNAMEqQ S201A;44;SW;ZzNAMEqQ L103A +100g;10240;1;;;;05;SW;ZzNAMEqQ S201B;44;SW;ZzNAMEqQ L104B +100g;10240;1;;;;05;SW;ZzNAMEqQ S202A;44;SW;ZzNAMEqQ L105A +100g;10240;1;;;;05;SW;ZzNAMEqQ S202B;44;SW;ZzNAMEqQ L106B +100g;10240;1;;;;05;SW;ZzNAMEqQ S203A;44;SW;ZzNAMEqQ L101A +100g;10240;1;;;;05;SW;ZzNAMEqQ S203B;44;SW;ZzNAMEqQ L102B +100g;10240;1;;;;06;SW;ZzNAMEqQ S201A;43;SW;ZzNAMEqQ L103A +100g;10240;1;;;;06;SW;ZzNAMEqQ S201B;43;SW;ZzNAMEqQ L104B +100g;10240;1;;;;06;SW;ZzNAMEqQ S202A;43;SW;ZzNAMEqQ L105A +100g;10240;1;;;;06;SW;ZzNAMEqQ S202B;43;SW;ZzNAMEqQ L106B +100g;10240;1;;;;06;SW;ZzNAMEqQ S203A;43;SW;ZzNAMEqQ L101A +100g;10240;1;;;;06;SW;ZzNAMEqQ S203B;43;SW;ZzNAMEqQ L102B +100g;10240;1;;;;07;SW;ZzNAMEqQ S201A;31;SW;ZzNAMEqQ L103B +100g;10240;1;;;;07;SW;ZzNAMEqQ S201B;31;SW;ZzNAMEqQ L106A +100g;10240;1;;;;07;SW;ZzNAMEqQ S202A;31;SW;ZzNAMEqQ L105B +100g;10240;1;;;;07;SW;ZzNAMEqQ S202B;31;SW;ZzNAMEqQ L102A +100g;10240;1;;;;07;SW;ZzNAMEqQ S203A;31;SW;ZzNAMEqQ L101B +100g;10240;1;;;;07;SW;ZzNAMEqQ S203B;31;SW;ZzNAMEqQ L104A +100g;10240;1;;;;08;SW;ZzNAMEqQ S201A;32;SW;ZzNAMEqQ L103B +100g;10240;1;;;;08;SW;ZzNAMEqQ S201B;32;SW;ZzNAMEqQ L106A +100g;10240;1;;;;08;SW;ZzNAMEqQ S202A;32;SW;ZzNAMEqQ L105B +100g;10240;1;;;;08;SW;ZzNAMEqQ S202B;32;SW;ZzNAMEqQ L102A +100g;10240;1;;;;08;SW;ZzNAMEqQ S203A;32;SW;ZzNAMEqQ L101B +100g;10240;1;;;;08;SW;ZzNAMEqQ S203B;32;SW;ZzNAMEqQ L104A +100g;10240;1;;;;09;SW;ZzNAMEqQ S201A;33;SW;ZzNAMEqQ L105B +100g;10240;1;;;;09;SW;ZzNAMEqQ S201B;33;SW;ZzNAMEqQ L102A +100g;10240;1;;;;09;SW;ZzNAMEqQ S202A;33;SW;ZzNAMEqQ L101B +100g;10240;1;;;;09;SW;ZzNAMEqQ S202B;33;SW;ZzNAMEqQ L104A +100g;10240;1;;;;09;SW;ZzNAMEqQ S203A;33;SW;ZzNAMEqQ L103B +100g;10240;1;;;;09;SW;ZzNAMEqQ S203B;33;SW;ZzNAMEqQ L106A +100g;10240;1;;;;10;SW;ZzNAMEqQ S201A;34;SW;ZzNAMEqQ L105B +100g;10240;1;;;;10;SW;ZzNAMEqQ S201B;34;SW;ZzNAMEqQ L102A +100g;10240;1;;;;10;SW;ZzNAMEqQ S202A;34;SW;ZzNAMEqQ L101B +100g;10240;1;;;;10;SW;ZzNAMEqQ S202B;34;SW;ZzNAMEqQ L104A +100g;10240;1;;;;10;SW;ZzNAMEqQ S203A;34;SW;ZzNAMEqQ L103B +100g;10240;1;;;;10;SW;ZzNAMEqQ S203B;34;SW;ZzNAMEqQ L106A +100g;10240;1;;;;11;SW;ZzNAMEqQ S201A;35;SW;ZzNAMEqQ L101B +100g;10240;1;;;;11;SW;ZzNAMEqQ S201B;35;SW;ZzNAMEqQ L104A +100g;10240;1;;;;11;SW;ZzNAMEqQ S202A;35;SW;ZzNAMEqQ L103B +100g;10240;1;;;;11;SW;ZzNAMEqQ S202B;35;SW;ZzNAMEqQ L106A +100g;10240;1;;;;11;SW;ZzNAMEqQ S203A;35;SW;ZzNAMEqQ L105B +100g;10240;1;;;;11;SW;ZzNAMEqQ S203B;35;SW;ZzNAMEqQ L102A +100g;10240;1;;;;12;SW;ZzNAMEqQ S201A;36;SW;ZzNAMEqQ L101B +100g;10240;1;;;;12;SW;ZzNAMEqQ S201B;36;SW;ZzNAMEqQ L104A +100g;10240;1;;;;12;SW;ZzNAMEqQ S202A;36;SW;ZzNAMEqQ L103B +100g;10240;1;;;;12;SW;ZzNAMEqQ S202B;36;SW;ZzNAMEqQ L106A +100g;10240;1;;;;12;SW;ZzNAMEqQ S203A;36;SW;ZzNAMEqQ L105B +100g;10240;1;;;;12;SW;ZzNAMEqQ S203B;36;SW;ZzNAMEqQ L102A +100g;10240;1;;;;13;SW;ZzNAMEqQ S201A;37;SW;ZzNAMEqQ L101B +100g;10240;1;;;;13;SW;ZzNAMEqQ S201B;37;SW;ZzNAMEqQ L104A +100g;10240;1;;;;13;SW;ZzNAMEqQ S202A;37;SW;ZzNAMEqQ L103B +100g;10240;1;;;;13;SW;ZzNAMEqQ S202B;37;SW;ZzNAMEqQ L106A +100g;10240;1;;;;13;SW;ZzNAMEqQ S203A;37;SW;ZzNAMEqQ L105B +100g;10240;1;;;;13;SW;ZzNAMEqQ S203B;37;SW;ZzNAMEqQ L102A +100g;10240;1;;;;14;SW;ZzNAMEqQ S201A;38;SW;ZzNAMEqQ L101B +100g;10240;1;;;;14;SW;ZzNAMEqQ S201B;38;SW;ZzNAMEqQ L104A +100g;10240;1;;;;14;SW;ZzNAMEqQ S202A;38;SW;ZzNAMEqQ L103B +100g;10240;1;;;;14;SW;ZzNAMEqQ S202B;38;SW;ZzNAMEqQ L106A +100g;10240;1;;;;14;SW;ZzNAMEqQ S203A;38;SW;ZzNAMEqQ L105B +100g;10240;1;;;;14;SW;ZzNAMEqQ S203B;38;SW;ZzNAMEqQ L102A +100g;10240;1;;;;15;SW;ZzNAMEqQ S201A;39;SW;ZzNAMEqQ L105B +100g;10240;1;;;;15;SW;ZzNAMEqQ S201B;39;SW;ZzNAMEqQ L102A +100g;10240;1;;;;15;SW;ZzNAMEqQ S202A;39;SW;ZzNAMEqQ L101B +100g;10240;1;;;;15;SW;ZzNAMEqQ S202B;39;SW;ZzNAMEqQ L104A +100g;10240;1;;;;15;SW;ZzNAMEqQ S203A;39;SW;ZzNAMEqQ L103B +100g;10240;1;;;;15;SW;ZzNAMEqQ S203B;39;SW;ZzNAMEqQ L106A +100g;10240;1;;;;16;SW;ZzNAMEqQ S201A;40;SW;ZzNAMEqQ L105B +100g;10240;1;;;;16;SW;ZzNAMEqQ S201B;40;SW;ZzNAMEqQ L102A +100g;10240;1;;;;16;SW;ZzNAMEqQ S202A;40;SW;ZzNAMEqQ L101B +100g;10240;1;;;;16;SW;ZzNAMEqQ S202B;40;SW;ZzNAMEqQ L104A +100g;10240;1;;;;16;SW;ZzNAMEqQ S203A;40;SW;ZzNAMEqQ L103B +100g;10240;1;;;;16;SW;ZzNAMEqQ S203B;40;SW;ZzNAMEqQ L106A +100g;10240;1;;;;17;SW;ZzNAMEqQ S201A;41;SW;ZzNAMEqQ L103B +100g;10240;1;;;;17;SW;ZzNAMEqQ S201B;41;SW;ZzNAMEqQ L106A +100g;10240;1;;;;17;SW;ZzNAMEqQ S202A;41;SW;ZzNAMEqQ L105B +100g;10240;1;;;;17;SW;ZzNAMEqQ S202B;41;SW;ZzNAMEqQ L102A +100g;10240;1;;;;17;SW;ZzNAMEqQ S203A;41;SW;ZzNAMEqQ L101B +100g;10240;1;;;;17;SW;ZzNAMEqQ S203B;41;SW;ZzNAMEqQ L104A +100g;10240;1;;;;18;SW;ZzNAMEqQ S201A;42;SW;ZzNAMEqQ L103B +100g;10240;1;;;;18;SW;ZzNAMEqQ S201B;42;SW;ZzNAMEqQ L106A +100g;10240;1;;;;18;SW;ZzNAMEqQ S202A;42;SW;ZzNAMEqQ L105B +100g;10240;1;;;;18;SW;ZzNAMEqQ S202B;42;SW;ZzNAMEqQ L102A +100g;10240;1;;;;18;SW;ZzNAMEqQ S203A;42;SW;ZzNAMEqQ L101B +100g;10240;1;;;;18;SW;ZzNAMEqQ S203B;42;SW;ZzNAMEqQ L104A +100g;10240;1;;;;19;SW;ZzNAMEqQ S201A;30;SW;ZzNAMEqQ L103A +100g;10240;1;;;;19;SW;ZzNAMEqQ S201B;30;SW;ZzNAMEqQ L104B +100g;10240;1;;;;19;SW;ZzNAMEqQ S202A;30;SW;ZzNAMEqQ L105A +100g;10240;1;;;;19;SW;ZzNAMEqQ S202B;30;SW;ZzNAMEqQ L106B +100g;10240;1;;;;19;SW;ZzNAMEqQ S203A;30;SW;ZzNAMEqQ L101A +100g;10240;1;;;;19;SW;ZzNAMEqQ S203B;30;SW;ZzNAMEqQ L102B +100g;10240;1;;;;20;SW;ZzNAMEqQ S201A;29;SW;ZzNAMEqQ L103A +100g;10240;1;;;;20;SW;ZzNAMEqQ S201B;29;SW;ZzNAMEqQ L104B +100g;10240;1;;;;20;SW;ZzNAMEqQ S202A;29;SW;ZzNAMEqQ L105A +100g;10240;1;;;;20;SW;ZzNAMEqQ S202B;29;SW;ZzNAMEqQ L106B +100g;10240;1;;;;20;SW;ZzNAMEqQ S203A;29;SW;ZzNAMEqQ L101A +100g;10240;1;;;;20;SW;ZzNAMEqQ S203B;29;SW;ZzNAMEqQ L102B +100g;10240;1;;;;21;SW;ZzNAMEqQ S201A;28;SW;ZzNAMEqQ L105A +100g;10240;1;;;;21;SW;ZzNAMEqQ S201B;28;SW;ZzNAMEqQ L106B +100g;10240;1;;;;21;SW;ZzNAMEqQ S202A;28;SW;ZzNAMEqQ L101A +100g;10240;1;;;;21;SW;ZzNAMEqQ S202B;28;SW;ZzNAMEqQ L102B +100g;10240;1;;;;21;SW;ZzNAMEqQ S203A;28;SW;ZzNAMEqQ L103A +100g;10240;1;;;;21;SW;ZzNAMEqQ S203B;28;SW;ZzNAMEqQ L104B +100g;10240;1;;;;22;SW;ZzNAMEqQ S201A;27;SW;ZzNAMEqQ L105A +100g;10240;1;;;;22;SW;ZzNAMEqQ S201B;27;SW;ZzNAMEqQ L106B +100g;10240;1;;;;22;SW;ZzNAMEqQ S202A;27;SW;ZzNAMEqQ L101A +100g;10240;1;;;;22;SW;ZzNAMEqQ S202B;27;SW;ZzNAMEqQ L102B +100g;10240;1;;;;22;SW;ZzNAMEqQ S203A;27;SW;ZzNAMEqQ L103A +100g;10240;1;;;;22;SW;ZzNAMEqQ S203B;27;SW;ZzNAMEqQ L104B +100g;10240;1;;;;23;SW;ZzNAMEqQ S201A;26;SW;ZzNAMEqQ L101A +100g;10240;1;;;;23;SW;ZzNAMEqQ S201B;26;SW;ZzNAMEqQ L102B +100g;10240;1;;;;23;SW;ZzNAMEqQ S202A;26;SW;ZzNAMEqQ L103A +100g;10240;1;;;;23;SW;ZzNAMEqQ S202B;26;SW;ZzNAMEqQ L104B +100g;10240;1;;;;23;SW;ZzNAMEqQ S203A;26;SW;ZzNAMEqQ L105A +100g;10240;1;;;;23;SW;ZzNAMEqQ S203B;26;SW;ZzNAMEqQ L106B +100g;10240;1;;;;24;SW;ZzNAMEqQ S201A;25;SW;ZzNAMEqQ L101A +100g;10240;1;;;;24;SW;ZzNAMEqQ S201B;25;SW;ZzNAMEqQ L102B +100g;10240;1;;;;24;SW;ZzNAMEqQ S202A;25;SW;ZzNAMEqQ L103A +100g;10240;1;;;;24;SW;ZzNAMEqQ S202B;25;SW;ZzNAMEqQ L104B +100g;10240;1;;;;24;SW;ZzNAMEqQ S203A;25;SW;ZzNAMEqQ L105A +100g;10240;1;;;;24;SW;ZzNAMEqQ S203B;25;SW;ZzNAMEqQ L106B +100g;10240;1;;;;25;SW;ZzNAMEqQ S201A;48;SW;ZzNAMEqQ L102A +100g;10240;1;;;;25;SW;ZzNAMEqQ S201B;48;SW;ZzNAMEqQ L101B +100g;10240;1;;;;25;SW;ZzNAMEqQ S202A;48;SW;ZzNAMEqQ L104A +100g;10240;1;;;;25;SW;ZzNAMEqQ S202B;48;SW;ZzNAMEqQ L103B +100g;10240;1;;;;25;SW;ZzNAMEqQ S203A;48;SW;ZzNAMEqQ L106A +100g;10240;1;;;;25;SW;ZzNAMEqQ S203B;48;SW;ZzNAMEqQ L105B +100g;10240;1;;;;26;SW;ZzNAMEqQ S201A;47;SW;ZzNAMEqQ L102A +100g;10240;1;;;;26;SW;ZzNAMEqQ S201B;47;SW;ZzNAMEqQ L101B +100g;10240;1;;;;26;SW;ZzNAMEqQ S202A;47;SW;ZzNAMEqQ L104A +100g;10240;1;;;;26;SW;ZzNAMEqQ S202B;47;SW;ZzNAMEqQ L103B +100g;10240;1;;;;26;SW;ZzNAMEqQ S203A;47;SW;ZzNAMEqQ L106A +100g;10240;1;;;;26;SW;ZzNAMEqQ S203B;47;SW;ZzNAMEqQ L105B +100g;10240;1;;;;27;SW;ZzNAMEqQ S201A;46;SW;ZzNAMEqQ L106A +100g;10240;1;;;;27;SW;ZzNAMEqQ S201B;46;SW;ZzNAMEqQ L105B +100g;10240;1;;;;27;SW;ZzNAMEqQ S202A;46;SW;ZzNAMEqQ L102A +100g;10240;1;;;;27;SW;ZzNAMEqQ S202B;46;SW;ZzNAMEqQ L101B +100g;10240;1;;;;27;SW;ZzNAMEqQ S203A;46;SW;ZzNAMEqQ L104A +100g;10240;1;;;;27;SW;ZzNAMEqQ S203B;46;SW;ZzNAMEqQ L103B +100g;10240;1;;;;28;SW;ZzNAMEqQ S201A;45;SW;ZzNAMEqQ L106A +100g;10240;1;;;;28;SW;ZzNAMEqQ S201B;45;SW;ZzNAMEqQ L105B +100g;10240;1;;;;28;SW;ZzNAMEqQ S202A;45;SW;ZzNAMEqQ L102A +100g;10240;1;;;;28;SW;ZzNAMEqQ S202B;45;SW;ZzNAMEqQ L101B +100g;10240;1;;;;28;SW;ZzNAMEqQ S203A;45;SW;ZzNAMEqQ L104A +100g;10240;1;;;;28;SW;ZzNAMEqQ S203B;45;SW;ZzNAMEqQ L103B +100g;10240;1;;;;29;SW;ZzNAMEqQ S201A;44;SW;ZzNAMEqQ L104A +100g;10240;1;;;;29;SW;ZzNAMEqQ S201B;44;SW;ZzNAMEqQ L103B +100g;10240;1;;;;29;SW;ZzNAMEqQ S202A;44;SW;ZzNAMEqQ L106A +100g;10240;1;;;;29;SW;ZzNAMEqQ S202B;44;SW;ZzNAMEqQ L105B +100g;10240;1;;;;29;SW;ZzNAMEqQ S203A;44;SW;ZzNAMEqQ L102A +100g;10240;1;;;;29;SW;ZzNAMEqQ S203B;44;SW;ZzNAMEqQ L101B +100g;10240;1;;;;30;SW;ZzNAMEqQ S201A;43;SW;ZzNAMEqQ L104A +100g;10240;1;;;;30;SW;ZzNAMEqQ S201B;43;SW;ZzNAMEqQ L103B +100g;10240;1;;;;30;SW;ZzNAMEqQ S202A;43;SW;ZzNAMEqQ L106A +100g;10240;1;;;;30;SW;ZzNAMEqQ S202B;43;SW;ZzNAMEqQ L105B +100g;10240;1;;;;30;SW;ZzNAMEqQ S203A;43;SW;ZzNAMEqQ L102A +100g;10240;1;;;;30;SW;ZzNAMEqQ S203B;43;SW;ZzNAMEqQ L101B +100g;10240;1;;;;31;SW;ZzNAMEqQ S201A;31;SW;ZzNAMEqQ L104B +100g;10240;1;;;;31;SW;ZzNAMEqQ S201B;31;SW;ZzNAMEqQ L105A +100g;10240;1;;;;31;SW;ZzNAMEqQ S202A;31;SW;ZzNAMEqQ L106B +100g;10240;1;;;;31;SW;ZzNAMEqQ S202B;31;SW;ZzNAMEqQ L101A +100g;10240;1;;;;31;SW;ZzNAMEqQ S203A;31;SW;ZzNAMEqQ L102B +100g;10240;1;;;;31;SW;ZzNAMEqQ S203B;31;SW;ZzNAMEqQ L103A +100g;10240;1;;;;32;SW;ZzNAMEqQ S201A;32;SW;ZzNAMEqQ L104B +100g;10240;1;;;;32;SW;ZzNAMEqQ S201B;32;SW;ZzNAMEqQ L105A +100g;10240;1;;;;32;SW;ZzNAMEqQ S202A;32;SW;ZzNAMEqQ L106B +100g;10240;1;;;;32;SW;ZzNAMEqQ S202B;32;SW;ZzNAMEqQ L101A +100g;10240;1;;;;32;SW;ZzNAMEqQ S203A;32;SW;ZzNAMEqQ L102B +100g;10240;1;;;;32;SW;ZzNAMEqQ S203B;32;SW;ZzNAMEqQ L103A +100g;10240;1;;;;33;SW;ZzNAMEqQ S201A;33;SW;ZzNAMEqQ L106B +100g;10240;1;;;;33;SW;ZzNAMEqQ S201B;33;SW;ZzNAMEqQ L101A +100g;10240;1;;;;33;SW;ZzNAMEqQ S202A;33;SW;ZzNAMEqQ L102B +100g;10240;1;;;;33;SW;ZzNAMEqQ S202B;33;SW;ZzNAMEqQ L103A +100g;10240;1;;;;33;SW;ZzNAMEqQ S203A;33;SW;ZzNAMEqQ L104B +100g;10240;1;;;;33;SW;ZzNAMEqQ S203B;33;SW;ZzNAMEqQ L105A +100g;10240;1;;;;34;SW;ZzNAMEqQ S201A;34;SW;ZzNAMEqQ L106B +100g;10240;1;;;;34;SW;ZzNAMEqQ S201B;34;SW;ZzNAMEqQ L101A +100g;10240;1;;;;34;SW;ZzNAMEqQ S202A;34;SW;ZzNAMEqQ L102B +100g;10240;1;;;;34;SW;ZzNAMEqQ S202B;34;SW;ZzNAMEqQ L103A +100g;10240;1;;;;34;SW;ZzNAMEqQ S203A;34;SW;ZzNAMEqQ L104B +100g;10240;1;;;;34;SW;ZzNAMEqQ S203B;34;SW;ZzNAMEqQ L105A +100g;10240;1;;;;35;SW;ZzNAMEqQ S201A;35;SW;ZzNAMEqQ L102B +100g;10240;1;;;;35;SW;ZzNAMEqQ S201B;35;SW;ZzNAMEqQ L103A +100g;10240;1;;;;35;SW;ZzNAMEqQ S202A;35;SW;ZzNAMEqQ L104B +100g;10240;1;;;;35;SW;ZzNAMEqQ S202B;35;SW;ZzNAMEqQ L105A +100g;10240;1;;;;35;SW;ZzNAMEqQ S203A;35;SW;ZzNAMEqQ L106B +100g;10240;1;;;;35;SW;ZzNAMEqQ S203B;35;SW;ZzNAMEqQ L101A +100g;10240;1;;;;36;SW;ZzNAMEqQ S201A;36;SW;ZzNAMEqQ L102B +100g;10240;1;;;;36;SW;ZzNAMEqQ S201B;36;SW;ZzNAMEqQ L103A +100g;10240;1;;;;36;SW;ZzNAMEqQ S202A;36;SW;ZzNAMEqQ L104B +100g;10240;1;;;;36;SW;ZzNAMEqQ S202B;36;SW;ZzNAMEqQ L105A +100g;10240;1;;;;36;SW;ZzNAMEqQ S203A;36;SW;ZzNAMEqQ L106B +100g;10240;1;;;;36;SW;ZzNAMEqQ S203B;36;SW;ZzNAMEqQ L101A +100g;10240;1;;;;37;SW;ZzNAMEqQ S201A;37;SW;ZzNAMEqQ L102B +100g;10240;1;;;;37;SW;ZzNAMEqQ S201B;37;SW;ZzNAMEqQ L103A +100g;10240;1;;;;37;SW;ZzNAMEqQ S202A;37;SW;ZzNAMEqQ L104B +100g;10240;1;;;;37;SW;ZzNAMEqQ S202B;37;SW;ZzNAMEqQ L105A +100g;10240;1;;;;37;SW;ZzNAMEqQ S203A;37;SW;ZzNAMEqQ L106B +100g;10240;1;;;;37;SW;ZzNAMEqQ S203B;37;SW;ZzNAMEqQ L101A +100g;10240;1;;;;38;SW;ZzNAMEqQ S201A;38;SW;ZzNAMEqQ L102B +100g;10240;1;;;;38;SW;ZzNAMEqQ S201B;38;SW;ZzNAMEqQ L103A +100g;10240;1;;;;38;SW;ZzNAMEqQ S202A;38;SW;ZzNAMEqQ L104B +100g;10240;1;;;;38;SW;ZzNAMEqQ S202B;38;SW;ZzNAMEqQ L105A +100g;10240;1;;;;38;SW;ZzNAMEqQ S203A;38;SW;ZzNAMEqQ L106B +100g;10240;1;;;;38;SW;ZzNAMEqQ S203B;38;SW;ZzNAMEqQ L101A +100g;10240;1;;;;39;SW;ZzNAMEqQ S201A;39;SW;ZzNAMEqQ L106B +100g;10240;1;;;;39;SW;ZzNAMEqQ S201B;39;SW;ZzNAMEqQ L101A +100g;10240;1;;;;39;SW;ZzNAMEqQ S202A;39;SW;ZzNAMEqQ L102B +100g;10240;1;;;;39;SW;ZzNAMEqQ S202B;39;SW;ZzNAMEqQ L103A +100g;10240;1;;;;39;SW;ZzNAMEqQ S203A;39;SW;ZzNAMEqQ L104B +100g;10240;1;;;;39;SW;ZzNAMEqQ S203B;39;SW;ZzNAMEqQ L105A +100g;10240;1;;;;40;SW;ZzNAMEqQ S201A;40;SW;ZzNAMEqQ L106B +100g;10240;1;;;;40;SW;ZzNAMEqQ S201B;40;SW;ZzNAMEqQ L101A +100g;10240;1;;;;40;SW;ZzNAMEqQ S202A;40;SW;ZzNAMEqQ L102B +100g;10240;1;;;;40;SW;ZzNAMEqQ S202B;40;SW;ZzNAMEqQ L103A +100g;10240;1;;;;40;SW;ZzNAMEqQ S203A;40;SW;ZzNAMEqQ L104B +100g;10240;1;;;;40;SW;ZzNAMEqQ S203B;40;SW;ZzNAMEqQ L105A +100g;10240;1;;;;41;SW;ZzNAMEqQ S201A;41;SW;ZzNAMEqQ L104B +100g;10240;1;;;;41;SW;ZzNAMEqQ S201B;41;SW;ZzNAMEqQ L105A +100g;10240;1;;;;41;SW;ZzNAMEqQ S202A;41;SW;ZzNAMEqQ L106B +100g;10240;1;;;;41;SW;ZzNAMEqQ S202B;41;SW;ZzNAMEqQ L101A +100g;10240;1;;;;41;SW;ZzNAMEqQ S203A;41;SW;ZzNAMEqQ L102B +100g;10240;1;;;;41;SW;ZzNAMEqQ S203B;41;SW;ZzNAMEqQ L103A +100g;10240;1;;;;42;SW;ZzNAMEqQ S201A;42;SW;ZzNAMEqQ L104B +100g;10240;1;;;;42;SW;ZzNAMEqQ S201B;42;SW;ZzNAMEqQ L105A +100g;10240;1;;;;42;SW;ZzNAMEqQ S202A;42;SW;ZzNAMEqQ L106B +100g;10240;1;;;;42;SW;ZzNAMEqQ S202B;42;SW;ZzNAMEqQ L101A +100g;10240;1;;;;42;SW;ZzNAMEqQ S203A;42;SW;ZzNAMEqQ L102B +100g;10240;1;;;;42;SW;ZzNAMEqQ S203B;42;SW;ZzNAMEqQ L103A +100g;10240;1;;;;43;SW;ZzNAMEqQ S201A;30;SW;ZzNAMEqQ L104A +100g;10240;1;;;;43;SW;ZzNAMEqQ S201B;30;SW;ZzNAMEqQ L103B +100g;10240;1;;;;43;SW;ZzNAMEqQ S202A;30;SW;ZzNAMEqQ L106A +100g;10240;1;;;;43;SW;ZzNAMEqQ S202B;30;SW;ZzNAMEqQ L105B +100g;10240;1;;;;43;SW;ZzNAMEqQ S203A;30;SW;ZzNAMEqQ L102A +100g;10240;1;;;;43;SW;ZzNAMEqQ S203B;30;SW;ZzNAMEqQ L101B +100g;10240;1;;;;44;SW;ZzNAMEqQ S201A;29;SW;ZzNAMEqQ L104A +100g;10240;1;;;;44;SW;ZzNAMEqQ S201B;29;SW;ZzNAMEqQ L103B +100g;10240;1;;;;44;SW;ZzNAMEqQ S202A;29;SW;ZzNAMEqQ L106A +100g;10240;1;;;;44;SW;ZzNAMEqQ S202B;29;SW;ZzNAMEqQ L105B +100g;10240;1;;;;44;SW;ZzNAMEqQ S203A;29;SW;ZzNAMEqQ L102A +100g;10240;1;;;;44;SW;ZzNAMEqQ S203B;29;SW;ZzNAMEqQ L101B +100g;10240;1;;;;45;SW;ZzNAMEqQ S201A;28;SW;ZzNAMEqQ L106A +100g;10240;1;;;;45;SW;ZzNAMEqQ S201B;28;SW;ZzNAMEqQ L105B +100g;10240;1;;;;45;SW;ZzNAMEqQ S202A;28;SW;ZzNAMEqQ L102A +100g;10240;1;;;;45;SW;ZzNAMEqQ S202B;28;SW;ZzNAMEqQ L101B +100g;10240;1;;;;45;SW;ZzNAMEqQ S203A;28;SW;ZzNAMEqQ L104A +100g;10240;1;;;;45;SW;ZzNAMEqQ S203B;28;SW;ZzNAMEqQ L103B +100g;10240;1;;;;46;SW;ZzNAMEqQ S201A;27;SW;ZzNAMEqQ L106A +100g;10240;1;;;;46;SW;ZzNAMEqQ S201B;27;SW;ZzNAMEqQ L105B +100g;10240;1;;;;46;SW;ZzNAMEqQ S202A;27;SW;ZzNAMEqQ L102A +100g;10240;1;;;;46;SW;ZzNAMEqQ S202B;27;SW;ZzNAMEqQ L101B +100g;10240;1;;;;46;SW;ZzNAMEqQ S203A;27;SW;ZzNAMEqQ L104A +100g;10240;1;;;;46;SW;ZzNAMEqQ S203B;27;SW;ZzNAMEqQ L103B +100g;10240;1;;;;47;SW;ZzNAMEqQ S201A;26;SW;ZzNAMEqQ L102A +100g;10240;1;;;;47;SW;ZzNAMEqQ S201B;26;SW;ZzNAMEqQ L101B +100g;10240;1;;;;47;SW;ZzNAMEqQ S202A;26;SW;ZzNAMEqQ L104A +100g;10240;1;;;;47;SW;ZzNAMEqQ S202B;26;SW;ZzNAMEqQ L103B +100g;10240;1;;;;47;SW;ZzNAMEqQ S203A;26;SW;ZzNAMEqQ L106A +100g;10240;1;;;;47;SW;ZzNAMEqQ S203B;26;SW;ZzNAMEqQ L105B +100g;10240;1;;;;48;SW;ZzNAMEqQ S201A;25;SW;ZzNAMEqQ L102A +100g;10240;1;;;;48;SW;ZzNAMEqQ S201B;25;SW;ZzNAMEqQ L101B +100g;10240;1;;;;48;SW;ZzNAMEqQ S202A;25;SW;ZzNAMEqQ L104A +100g;10240;1;;;;48;SW;ZzNAMEqQ S202B;25;SW;ZzNAMEqQ L103B +100g;10240;1;;;;48;SW;ZzNAMEqQ S203A;25;SW;ZzNAMEqQ L106A +100g;10240;1;;;;48;SW;ZzNAMEqQ S203B;25;SW;ZzNAMEqQ L105B diff --git a/IbaTools/opaxlattopology/linksum_swd24.csv b/IbaTools/opaxlattopology/linksum_swd24.csv new file mode 100644 index 0000000..0b21484 --- /dev/null +++ b/IbaTools/opaxlattopology/linksum_swd24.csv @@ -0,0 +1,1152 @@ +100g;10240;1;;;;01;SW;ZzNAMEqQ S201A;48;SW;ZzNAMEqQ L113A +100g;10240;1;;;;01;SW;ZzNAMEqQ S201B;48;SW;ZzNAMEqQ L102B +100g;10240;1;;;;01;SW;ZzNAMEqQ S202A;48;SW;ZzNAMEqQ L115A +100g;10240;1;;;;01;SW;ZzNAMEqQ S202B;48;SW;ZzNAMEqQ L104B +100g;10240;1;;;;01;SW;ZzNAMEqQ S203A;48;SW;ZzNAMEqQ L117A +100g;10240;1;;;;01;SW;ZzNAMEqQ S203B;48;SW;ZzNAMEqQ L106B +100g;10240;1;;;;01;SW;ZzNAMEqQ S204A;48;SW;ZzNAMEqQ L119A +100g;10240;1;;;;01;SW;ZzNAMEqQ S204B;48;SW;ZzNAMEqQ L108B +100g;10240;1;;;;01;SW;ZzNAMEqQ S205A;48;SW;ZzNAMEqQ L121A +100g;10240;1;;;;01;SW;ZzNAMEqQ S205B;48;SW;ZzNAMEqQ L110B +100g;10240;1;;;;01;SW;ZzNAMEqQ S206A;48;SW;ZzNAMEqQ L123A +100g;10240;1;;;;01;SW;ZzNAMEqQ S206B;48;SW;ZzNAMEqQ L112B +100g;10240;1;;;;01;SW;ZzNAMEqQ S207A;48;SW;ZzNAMEqQ L101A +100g;10240;1;;;;01;SW;ZzNAMEqQ S207B;48;SW;ZzNAMEqQ L114B +100g;10240;1;;;;01;SW;ZzNAMEqQ S208A;48;SW;ZzNAMEqQ L103A +100g;10240;1;;;;01;SW;ZzNAMEqQ S208B;48;SW;ZzNAMEqQ L116B +100g;10240;1;;;;01;SW;ZzNAMEqQ S209A;48;SW;ZzNAMEqQ L105A +100g;10240;1;;;;01;SW;ZzNAMEqQ S209B;48;SW;ZzNAMEqQ L118B +100g;10240;1;;;;01;SW;ZzNAMEqQ S210A;48;SW;ZzNAMEqQ L107A +100g;10240;1;;;;01;SW;ZzNAMEqQ S210B;48;SW;ZzNAMEqQ L120B +100g;10240;1;;;;01;SW;ZzNAMEqQ S211A;48;SW;ZzNAMEqQ L109A +100g;10240;1;;;;01;SW;ZzNAMEqQ S211B;48;SW;ZzNAMEqQ L122B +100g;10240;1;;;;01;SW;ZzNAMEqQ S212A;48;SW;ZzNAMEqQ L111A +100g;10240;1;;;;01;SW;ZzNAMEqQ S212B;48;SW;ZzNAMEqQ L124B +100g;10240;1;;;;02;SW;ZzNAMEqQ S201A;47;SW;ZzNAMEqQ L115A +100g;10240;1;;;;02;SW;ZzNAMEqQ S201B;47;SW;ZzNAMEqQ L112B +100g;10240;1;;;;02;SW;ZzNAMEqQ S202A;47;SW;ZzNAMEqQ L117A +100g;10240;1;;;;02;SW;ZzNAMEqQ S202B;47;SW;ZzNAMEqQ L114B +100g;10240;1;;;;02;SW;ZzNAMEqQ S203A;47;SW;ZzNAMEqQ L119A +100g;10240;1;;;;02;SW;ZzNAMEqQ S203B;47;SW;ZzNAMEqQ L116B +100g;10240;1;;;;02;SW;ZzNAMEqQ S204A;47;SW;ZzNAMEqQ L121A +100g;10240;1;;;;02;SW;ZzNAMEqQ S204B;47;SW;ZzNAMEqQ L118B +100g;10240;1;;;;02;SW;ZzNAMEqQ S205A;47;SW;ZzNAMEqQ L123A +100g;10240;1;;;;02;SW;ZzNAMEqQ S205B;47;SW;ZzNAMEqQ L120B +100g;10240;1;;;;02;SW;ZzNAMEqQ S206A;47;SW;ZzNAMEqQ L101A +100g;10240;1;;;;02;SW;ZzNAMEqQ S206B;47;SW;ZzNAMEqQ L122B +100g;10240;1;;;;02;SW;ZzNAMEqQ S207A;47;SW;ZzNAMEqQ L103A +100g;10240;1;;;;02;SW;ZzNAMEqQ S207B;47;SW;ZzNAMEqQ L124B +100g;10240;1;;;;02;SW;ZzNAMEqQ S208A;47;SW;ZzNAMEqQ L105A +100g;10240;1;;;;02;SW;ZzNAMEqQ S208B;47;SW;ZzNAMEqQ L102B +100g;10240;1;;;;02;SW;ZzNAMEqQ S209A;47;SW;ZzNAMEqQ L107A +100g;10240;1;;;;02;SW;ZzNAMEqQ S209B;47;SW;ZzNAMEqQ L104B +100g;10240;1;;;;02;SW;ZzNAMEqQ S210A;47;SW;ZzNAMEqQ L109A +100g;10240;1;;;;02;SW;ZzNAMEqQ S210B;47;SW;ZzNAMEqQ L106B +100g;10240;1;;;;02;SW;ZzNAMEqQ S211A;47;SW;ZzNAMEqQ L111A +100g;10240;1;;;;02;SW;ZzNAMEqQ S211B;47;SW;ZzNAMEqQ L108B +100g;10240;1;;;;02;SW;ZzNAMEqQ S212A;47;SW;ZzNAMEqQ L113A +100g;10240;1;;;;02;SW;ZzNAMEqQ S212B;47;SW;ZzNAMEqQ L110B +100g;10240;1;;;;03;SW;ZzNAMEqQ S201A;46;SW;ZzNAMEqQ L117A +100g;10240;1;;;;03;SW;ZzNAMEqQ S201B;46;SW;ZzNAMEqQ L110B +100g;10240;1;;;;03;SW;ZzNAMEqQ S202A;46;SW;ZzNAMEqQ L119A +100g;10240;1;;;;03;SW;ZzNAMEqQ S202B;46;SW;ZzNAMEqQ L112B +100g;10240;1;;;;03;SW;ZzNAMEqQ S203A;46;SW;ZzNAMEqQ L121A +100g;10240;1;;;;03;SW;ZzNAMEqQ S203B;46;SW;ZzNAMEqQ L114B +100g;10240;1;;;;03;SW;ZzNAMEqQ S204A;46;SW;ZzNAMEqQ L123A +100g;10240;1;;;;03;SW;ZzNAMEqQ S204B;46;SW;ZzNAMEqQ L116B +100g;10240;1;;;;03;SW;ZzNAMEqQ S205A;46;SW;ZzNAMEqQ L101A +100g;10240;1;;;;03;SW;ZzNAMEqQ S205B;46;SW;ZzNAMEqQ L118B +100g;10240;1;;;;03;SW;ZzNAMEqQ S206A;46;SW;ZzNAMEqQ L103A +100g;10240;1;;;;03;SW;ZzNAMEqQ S206B;46;SW;ZzNAMEqQ L120B +100g;10240;1;;;;03;SW;ZzNAMEqQ S207A;46;SW;ZzNAMEqQ L105A +100g;10240;1;;;;03;SW;ZzNAMEqQ S207B;46;SW;ZzNAMEqQ L122B +100g;10240;1;;;;03;SW;ZzNAMEqQ S208A;46;SW;ZzNAMEqQ L107A +100g;10240;1;;;;03;SW;ZzNAMEqQ S208B;46;SW;ZzNAMEqQ L124B +100g;10240;1;;;;03;SW;ZzNAMEqQ S209A;46;SW;ZzNAMEqQ L109A +100g;10240;1;;;;03;SW;ZzNAMEqQ S209B;46;SW;ZzNAMEqQ L102B +100g;10240;1;;;;03;SW;ZzNAMEqQ S210A;46;SW;ZzNAMEqQ L111A +100g;10240;1;;;;03;SW;ZzNAMEqQ S210B;46;SW;ZzNAMEqQ L104B +100g;10240;1;;;;03;SW;ZzNAMEqQ S211A;46;SW;ZzNAMEqQ L113A +100g;10240;1;;;;03;SW;ZzNAMEqQ S211B;46;SW;ZzNAMEqQ L106B +100g;10240;1;;;;03;SW;ZzNAMEqQ S212A;46;SW;ZzNAMEqQ L115A +100g;10240;1;;;;03;SW;ZzNAMEqQ S212B;46;SW;ZzNAMEqQ L108B +100g;10240;1;;;;04;SW;ZzNAMEqQ S201A;45;SW;ZzNAMEqQ L119A +100g;10240;1;;;;04;SW;ZzNAMEqQ S201B;45;SW;ZzNAMEqQ L108B +100g;10240;1;;;;04;SW;ZzNAMEqQ S202A;45;SW;ZzNAMEqQ L121A +100g;10240;1;;;;04;SW;ZzNAMEqQ S202B;45;SW;ZzNAMEqQ L110B +100g;10240;1;;;;04;SW;ZzNAMEqQ S203A;45;SW;ZzNAMEqQ L123A +100g;10240;1;;;;04;SW;ZzNAMEqQ S203B;45;SW;ZzNAMEqQ L112B +100g;10240;1;;;;04;SW;ZzNAMEqQ S204A;45;SW;ZzNAMEqQ L101A +100g;10240;1;;;;04;SW;ZzNAMEqQ S204B;45;SW;ZzNAMEqQ L114B +100g;10240;1;;;;04;SW;ZzNAMEqQ S205A;45;SW;ZzNAMEqQ L103A +100g;10240;1;;;;04;SW;ZzNAMEqQ S205B;45;SW;ZzNAMEqQ L116B +100g;10240;1;;;;04;SW;ZzNAMEqQ S206A;45;SW;ZzNAMEqQ L105A +100g;10240;1;;;;04;SW;ZzNAMEqQ S206B;45;SW;ZzNAMEqQ L118B +100g;10240;1;;;;04;SW;ZzNAMEqQ S207A;45;SW;ZzNAMEqQ L107A +100g;10240;1;;;;04;SW;ZzNAMEqQ S207B;45;SW;ZzNAMEqQ L120B +100g;10240;1;;;;04;SW;ZzNAMEqQ S208A;45;SW;ZzNAMEqQ L109A +100g;10240;1;;;;04;SW;ZzNAMEqQ S208B;45;SW;ZzNAMEqQ L122B +100g;10240;1;;;;04;SW;ZzNAMEqQ S209A;45;SW;ZzNAMEqQ L111A +100g;10240;1;;;;04;SW;ZzNAMEqQ S209B;45;SW;ZzNAMEqQ L124B +100g;10240;1;;;;04;SW;ZzNAMEqQ S210A;45;SW;ZzNAMEqQ L113A +100g;10240;1;;;;04;SW;ZzNAMEqQ S210B;45;SW;ZzNAMEqQ L102B +100g;10240;1;;;;04;SW;ZzNAMEqQ S211A;45;SW;ZzNAMEqQ L115A +100g;10240;1;;;;04;SW;ZzNAMEqQ S211B;45;SW;ZzNAMEqQ L104B +100g;10240;1;;;;04;SW;ZzNAMEqQ S212A;45;SW;ZzNAMEqQ L117A +100g;10240;1;;;;04;SW;ZzNAMEqQ S212B;45;SW;ZzNAMEqQ L106B +100g;10240;1;;;;05;SW;ZzNAMEqQ S201A;44;SW;ZzNAMEqQ L121A +100g;10240;1;;;;05;SW;ZzNAMEqQ S201B;44;SW;ZzNAMEqQ L106B +100g;10240;1;;;;05;SW;ZzNAMEqQ S202A;44;SW;ZzNAMEqQ L123A +100g;10240;1;;;;05;SW;ZzNAMEqQ S202B;44;SW;ZzNAMEqQ L108B +100g;10240;1;;;;05;SW;ZzNAMEqQ S203A;44;SW;ZzNAMEqQ L101A +100g;10240;1;;;;05;SW;ZzNAMEqQ S203B;44;SW;ZzNAMEqQ L110B +100g;10240;1;;;;05;SW;ZzNAMEqQ S204A;44;SW;ZzNAMEqQ L103A +100g;10240;1;;;;05;SW;ZzNAMEqQ S204B;44;SW;ZzNAMEqQ L112B +100g;10240;1;;;;05;SW;ZzNAMEqQ S205A;44;SW;ZzNAMEqQ L105A +100g;10240;1;;;;05;SW;ZzNAMEqQ S205B;44;SW;ZzNAMEqQ L114B +100g;10240;1;;;;05;SW;ZzNAMEqQ S206A;44;SW;ZzNAMEqQ L107A +100g;10240;1;;;;05;SW;ZzNAMEqQ S206B;44;SW;ZzNAMEqQ L116B +100g;10240;1;;;;05;SW;ZzNAMEqQ S207A;44;SW;ZzNAMEqQ L109A +100g;10240;1;;;;05;SW;ZzNAMEqQ S207B;44;SW;ZzNAMEqQ L118B +100g;10240;1;;;;05;SW;ZzNAMEqQ S208A;44;SW;ZzNAMEqQ L111A +100g;10240;1;;;;05;SW;ZzNAMEqQ S208B;44;SW;ZzNAMEqQ L120B +100g;10240;1;;;;05;SW;ZzNAMEqQ S209A;44;SW;ZzNAMEqQ L113A +100g;10240;1;;;;05;SW;ZzNAMEqQ S209B;44;SW;ZzNAMEqQ L122B +100g;10240;1;;;;05;SW;ZzNAMEqQ S210A;44;SW;ZzNAMEqQ L115A +100g;10240;1;;;;05;SW;ZzNAMEqQ S210B;44;SW;ZzNAMEqQ L124B +100g;10240;1;;;;05;SW;ZzNAMEqQ S211A;44;SW;ZzNAMEqQ L117A +100g;10240;1;;;;05;SW;ZzNAMEqQ S211B;44;SW;ZzNAMEqQ L102B +100g;10240;1;;;;05;SW;ZzNAMEqQ S212A;44;SW;ZzNAMEqQ L119A +100g;10240;1;;;;05;SW;ZzNAMEqQ S212B;44;SW;ZzNAMEqQ L104B +100g;10240;1;;;;06;SW;ZzNAMEqQ S201A;43;SW;ZzNAMEqQ L123A +100g;10240;1;;;;06;SW;ZzNAMEqQ S201B;43;SW;ZzNAMEqQ L104B +100g;10240;1;;;;06;SW;ZzNAMEqQ S202A;43;SW;ZzNAMEqQ L101A +100g;10240;1;;;;06;SW;ZzNAMEqQ S202B;43;SW;ZzNAMEqQ L106B +100g;10240;1;;;;06;SW;ZzNAMEqQ S203A;43;SW;ZzNAMEqQ L103A +100g;10240;1;;;;06;SW;ZzNAMEqQ S203B;43;SW;ZzNAMEqQ L108B +100g;10240;1;;;;06;SW;ZzNAMEqQ S204A;43;SW;ZzNAMEqQ L105A +100g;10240;1;;;;06;SW;ZzNAMEqQ S204B;43;SW;ZzNAMEqQ L110B +100g;10240;1;;;;06;SW;ZzNAMEqQ S205A;43;SW;ZzNAMEqQ L107A +100g;10240;1;;;;06;SW;ZzNAMEqQ S205B;43;SW;ZzNAMEqQ L112B +100g;10240;1;;;;06;SW;ZzNAMEqQ S206A;43;SW;ZzNAMEqQ L109A +100g;10240;1;;;;06;SW;ZzNAMEqQ S206B;43;SW;ZzNAMEqQ L114B +100g;10240;1;;;;06;SW;ZzNAMEqQ S207A;43;SW;ZzNAMEqQ L111A +100g;10240;1;;;;06;SW;ZzNAMEqQ S207B;43;SW;ZzNAMEqQ L116B +100g;10240;1;;;;06;SW;ZzNAMEqQ S208A;43;SW;ZzNAMEqQ L113A +100g;10240;1;;;;06;SW;ZzNAMEqQ S208B;43;SW;ZzNAMEqQ L118B +100g;10240;1;;;;06;SW;ZzNAMEqQ S209A;43;SW;ZzNAMEqQ L115A +100g;10240;1;;;;06;SW;ZzNAMEqQ S209B;43;SW;ZzNAMEqQ L120B +100g;10240;1;;;;06;SW;ZzNAMEqQ S210A;43;SW;ZzNAMEqQ L117A +100g;10240;1;;;;06;SW;ZzNAMEqQ S210B;43;SW;ZzNAMEqQ L122B +100g;10240;1;;;;06;SW;ZzNAMEqQ S211A;43;SW;ZzNAMEqQ L119A +100g;10240;1;;;;06;SW;ZzNAMEqQ S211B;43;SW;ZzNAMEqQ L124B +100g;10240;1;;;;06;SW;ZzNAMEqQ S212A;43;SW;ZzNAMEqQ L121A +100g;10240;1;;;;06;SW;ZzNAMEqQ S212B;43;SW;ZzNAMEqQ L102B +100g;10240;1;;;;07;SW;ZzNAMEqQ S201A;31;SW;ZzNAMEqQ L113B +100g;10240;1;;;;07;SW;ZzNAMEqQ S201B;31;SW;ZzNAMEqQ L114A +100g;10240;1;;;;07;SW;ZzNAMEqQ S202A;31;SW;ZzNAMEqQ L115B +100g;10240;1;;;;07;SW;ZzNAMEqQ S202B;31;SW;ZzNAMEqQ L116A +100g;10240;1;;;;07;SW;ZzNAMEqQ S203A;31;SW;ZzNAMEqQ L117B +100g;10240;1;;;;07;SW;ZzNAMEqQ S203B;31;SW;ZzNAMEqQ L118A +100g;10240;1;;;;07;SW;ZzNAMEqQ S204A;31;SW;ZzNAMEqQ L119B +100g;10240;1;;;;07;SW;ZzNAMEqQ S204B;31;SW;ZzNAMEqQ L120A +100g;10240;1;;;;07;SW;ZzNAMEqQ S205A;31;SW;ZzNAMEqQ L121B +100g;10240;1;;;;07;SW;ZzNAMEqQ S205B;31;SW;ZzNAMEqQ L122A +100g;10240;1;;;;07;SW;ZzNAMEqQ S206A;31;SW;ZzNAMEqQ L123B +100g;10240;1;;;;07;SW;ZzNAMEqQ S206B;31;SW;ZzNAMEqQ L124A +100g;10240;1;;;;07;SW;ZzNAMEqQ S207A;31;SW;ZzNAMEqQ L101B +100g;10240;1;;;;07;SW;ZzNAMEqQ S207B;31;SW;ZzNAMEqQ L102A +100g;10240;1;;;;07;SW;ZzNAMEqQ S208A;31;SW;ZzNAMEqQ L103B +100g;10240;1;;;;07;SW;ZzNAMEqQ S208B;31;SW;ZzNAMEqQ L104A +100g;10240;1;;;;07;SW;ZzNAMEqQ S209A;31;SW;ZzNAMEqQ L105B +100g;10240;1;;;;07;SW;ZzNAMEqQ S209B;31;SW;ZzNAMEqQ L106A +100g;10240;1;;;;07;SW;ZzNAMEqQ S210A;31;SW;ZzNAMEqQ L107B +100g;10240;1;;;;07;SW;ZzNAMEqQ S210B;31;SW;ZzNAMEqQ L108A +100g;10240;1;;;;07;SW;ZzNAMEqQ S211A;31;SW;ZzNAMEqQ L109B +100g;10240;1;;;;07;SW;ZzNAMEqQ S211B;31;SW;ZzNAMEqQ L110A +100g;10240;1;;;;07;SW;ZzNAMEqQ S212A;31;SW;ZzNAMEqQ L111B +100g;10240;1;;;;07;SW;ZzNAMEqQ S212B;31;SW;ZzNAMEqQ L112A +100g;10240;1;;;;08;SW;ZzNAMEqQ S201A;32;SW;ZzNAMEqQ L115B +100g;10240;1;;;;08;SW;ZzNAMEqQ S201B;32;SW;ZzNAMEqQ L112A +100g;10240;1;;;;08;SW;ZzNAMEqQ S202A;32;SW;ZzNAMEqQ L117B +100g;10240;1;;;;08;SW;ZzNAMEqQ S202B;32;SW;ZzNAMEqQ L114A +100g;10240;1;;;;08;SW;ZzNAMEqQ S203A;32;SW;ZzNAMEqQ L119B +100g;10240;1;;;;08;SW;ZzNAMEqQ S203B;32;SW;ZzNAMEqQ L116A +100g;10240;1;;;;08;SW;ZzNAMEqQ S204A;32;SW;ZzNAMEqQ L121B +100g;10240;1;;;;08;SW;ZzNAMEqQ S204B;32;SW;ZzNAMEqQ L118A +100g;10240;1;;;;08;SW;ZzNAMEqQ S205A;32;SW;ZzNAMEqQ L123B +100g;10240;1;;;;08;SW;ZzNAMEqQ S205B;32;SW;ZzNAMEqQ L120A +100g;10240;1;;;;08;SW;ZzNAMEqQ S206A;32;SW;ZzNAMEqQ L101B +100g;10240;1;;;;08;SW;ZzNAMEqQ S206B;32;SW;ZzNAMEqQ L122A +100g;10240;1;;;;08;SW;ZzNAMEqQ S207A;32;SW;ZzNAMEqQ L103B +100g;10240;1;;;;08;SW;ZzNAMEqQ S207B;32;SW;ZzNAMEqQ L124A +100g;10240;1;;;;08;SW;ZzNAMEqQ S208A;32;SW;ZzNAMEqQ L105B +100g;10240;1;;;;08;SW;ZzNAMEqQ S208B;32;SW;ZzNAMEqQ L102A +100g;10240;1;;;;08;SW;ZzNAMEqQ S209A;32;SW;ZzNAMEqQ L107B +100g;10240;1;;;;08;SW;ZzNAMEqQ S209B;32;SW;ZzNAMEqQ L104A +100g;10240;1;;;;08;SW;ZzNAMEqQ S210A;32;SW;ZzNAMEqQ L109B +100g;10240;1;;;;08;SW;ZzNAMEqQ S210B;32;SW;ZzNAMEqQ L106A +100g;10240;1;;;;08;SW;ZzNAMEqQ S211A;32;SW;ZzNAMEqQ L111B +100g;10240;1;;;;08;SW;ZzNAMEqQ S211B;32;SW;ZzNAMEqQ L108A +100g;10240;1;;;;08;SW;ZzNAMEqQ S212A;32;SW;ZzNAMEqQ L113B +100g;10240;1;;;;08;SW;ZzNAMEqQ S212B;32;SW;ZzNAMEqQ L110A +100g;10240;1;;;;09;SW;ZzNAMEqQ S201A;33;SW;ZzNAMEqQ L117B +100g;10240;1;;;;09;SW;ZzNAMEqQ S201B;33;SW;ZzNAMEqQ L110A +100g;10240;1;;;;09;SW;ZzNAMEqQ S202A;33;SW;ZzNAMEqQ L119B +100g;10240;1;;;;09;SW;ZzNAMEqQ S202B;33;SW;ZzNAMEqQ L112A +100g;10240;1;;;;09;SW;ZzNAMEqQ S203A;33;SW;ZzNAMEqQ L121B +100g;10240;1;;;;09;SW;ZzNAMEqQ S203B;33;SW;ZzNAMEqQ L114A +100g;10240;1;;;;09;SW;ZzNAMEqQ S204A;33;SW;ZzNAMEqQ L123B +100g;10240;1;;;;09;SW;ZzNAMEqQ S204B;33;SW;ZzNAMEqQ L116A +100g;10240;1;;;;09;SW;ZzNAMEqQ S205A;33;SW;ZzNAMEqQ L101B +100g;10240;1;;;;09;SW;ZzNAMEqQ S205B;33;SW;ZzNAMEqQ L118A +100g;10240;1;;;;09;SW;ZzNAMEqQ S206A;33;SW;ZzNAMEqQ L103B +100g;10240;1;;;;09;SW;ZzNAMEqQ S206B;33;SW;ZzNAMEqQ L120A +100g;10240;1;;;;09;SW;ZzNAMEqQ S207A;33;SW;ZzNAMEqQ L105B +100g;10240;1;;;;09;SW;ZzNAMEqQ S207B;33;SW;ZzNAMEqQ L122A +100g;10240;1;;;;09;SW;ZzNAMEqQ S208A;33;SW;ZzNAMEqQ L107B +100g;10240;1;;;;09;SW;ZzNAMEqQ S208B;33;SW;ZzNAMEqQ L124A +100g;10240;1;;;;09;SW;ZzNAMEqQ S209A;33;SW;ZzNAMEqQ L109B +100g;10240;1;;;;09;SW;ZzNAMEqQ S209B;33;SW;ZzNAMEqQ L102A +100g;10240;1;;;;09;SW;ZzNAMEqQ S210A;33;SW;ZzNAMEqQ L111B +100g;10240;1;;;;09;SW;ZzNAMEqQ S210B;33;SW;ZzNAMEqQ L104A +100g;10240;1;;;;09;SW;ZzNAMEqQ S211A;33;SW;ZzNAMEqQ L113B +100g;10240;1;;;;09;SW;ZzNAMEqQ S211B;33;SW;ZzNAMEqQ L106A +100g;10240;1;;;;09;SW;ZzNAMEqQ S212A;33;SW;ZzNAMEqQ L115B +100g;10240;1;;;;09;SW;ZzNAMEqQ S212B;33;SW;ZzNAMEqQ L108A +100g;10240;1;;;;10;SW;ZzNAMEqQ S201A;34;SW;ZzNAMEqQ L119B +100g;10240;1;;;;10;SW;ZzNAMEqQ S201B;34;SW;ZzNAMEqQ L108A +100g;10240;1;;;;10;SW;ZzNAMEqQ S202A;34;SW;ZzNAMEqQ L121B +100g;10240;1;;;;10;SW;ZzNAMEqQ S202B;34;SW;ZzNAMEqQ L110A +100g;10240;1;;;;10;SW;ZzNAMEqQ S203A;34;SW;ZzNAMEqQ L123B +100g;10240;1;;;;10;SW;ZzNAMEqQ S203B;34;SW;ZzNAMEqQ L112A +100g;10240;1;;;;10;SW;ZzNAMEqQ S204A;34;SW;ZzNAMEqQ L101B +100g;10240;1;;;;10;SW;ZzNAMEqQ S204B;34;SW;ZzNAMEqQ L114A +100g;10240;1;;;;10;SW;ZzNAMEqQ S205A;34;SW;ZzNAMEqQ L103B +100g;10240;1;;;;10;SW;ZzNAMEqQ S205B;34;SW;ZzNAMEqQ L116A +100g;10240;1;;;;10;SW;ZzNAMEqQ S206A;34;SW;ZzNAMEqQ L105B +100g;10240;1;;;;10;SW;ZzNAMEqQ S206B;34;SW;ZzNAMEqQ L118A +100g;10240;1;;;;10;SW;ZzNAMEqQ S207A;34;SW;ZzNAMEqQ L107B +100g;10240;1;;;;10;SW;ZzNAMEqQ S207B;34;SW;ZzNAMEqQ L120A +100g;10240;1;;;;10;SW;ZzNAMEqQ S208A;34;SW;ZzNAMEqQ L109B +100g;10240;1;;;;10;SW;ZzNAMEqQ S208B;34;SW;ZzNAMEqQ L122A +100g;10240;1;;;;10;SW;ZzNAMEqQ S209A;34;SW;ZzNAMEqQ L111B +100g;10240;1;;;;10;SW;ZzNAMEqQ S209B;34;SW;ZzNAMEqQ L124A +100g;10240;1;;;;10;SW;ZzNAMEqQ S210A;34;SW;ZzNAMEqQ L113B +100g;10240;1;;;;10;SW;ZzNAMEqQ S210B;34;SW;ZzNAMEqQ L102A +100g;10240;1;;;;10;SW;ZzNAMEqQ S211A;34;SW;ZzNAMEqQ L115B +100g;10240;1;;;;10;SW;ZzNAMEqQ S211B;34;SW;ZzNAMEqQ L104A +100g;10240;1;;;;10;SW;ZzNAMEqQ S212A;34;SW;ZzNAMEqQ L117B +100g;10240;1;;;;10;SW;ZzNAMEqQ S212B;34;SW;ZzNAMEqQ L106A +100g;10240;1;;;;11;SW;ZzNAMEqQ S201A;35;SW;ZzNAMEqQ L121B +100g;10240;1;;;;11;SW;ZzNAMEqQ S201B;35;SW;ZzNAMEqQ L106A +100g;10240;1;;;;11;SW;ZzNAMEqQ S202A;35;SW;ZzNAMEqQ L123B +100g;10240;1;;;;11;SW;ZzNAMEqQ S202B;35;SW;ZzNAMEqQ L108A +100g;10240;1;;;;11;SW;ZzNAMEqQ S203A;35;SW;ZzNAMEqQ L101B +100g;10240;1;;;;11;SW;ZzNAMEqQ S203B;35;SW;ZzNAMEqQ L110A +100g;10240;1;;;;11;SW;ZzNAMEqQ S204A;35;SW;ZzNAMEqQ L103B +100g;10240;1;;;;11;SW;ZzNAMEqQ S204B;35;SW;ZzNAMEqQ L112A +100g;10240;1;;;;11;SW;ZzNAMEqQ S205A;35;SW;ZzNAMEqQ L105B +100g;10240;1;;;;11;SW;ZzNAMEqQ S205B;35;SW;ZzNAMEqQ L114A +100g;10240;1;;;;11;SW;ZzNAMEqQ S206A;35;SW;ZzNAMEqQ L107B +100g;10240;1;;;;11;SW;ZzNAMEqQ S206B;35;SW;ZzNAMEqQ L116A +100g;10240;1;;;;11;SW;ZzNAMEqQ S207A;35;SW;ZzNAMEqQ L109B +100g;10240;1;;;;11;SW;ZzNAMEqQ S207B;35;SW;ZzNAMEqQ L118A +100g;10240;1;;;;11;SW;ZzNAMEqQ S208A;35;SW;ZzNAMEqQ L111B +100g;10240;1;;;;11;SW;ZzNAMEqQ S208B;35;SW;ZzNAMEqQ L120A +100g;10240;1;;;;11;SW;ZzNAMEqQ S209A;35;SW;ZzNAMEqQ L113B +100g;10240;1;;;;11;SW;ZzNAMEqQ S209B;35;SW;ZzNAMEqQ L122A +100g;10240;1;;;;11;SW;ZzNAMEqQ S210A;35;SW;ZzNAMEqQ L115B +100g;10240;1;;;;11;SW;ZzNAMEqQ S210B;35;SW;ZzNAMEqQ L124A +100g;10240;1;;;;11;SW;ZzNAMEqQ S211A;35;SW;ZzNAMEqQ L117B +100g;10240;1;;;;11;SW;ZzNAMEqQ S211B;35;SW;ZzNAMEqQ L102A +100g;10240;1;;;;11;SW;ZzNAMEqQ S212A;35;SW;ZzNAMEqQ L119B +100g;10240;1;;;;11;SW;ZzNAMEqQ S212B;35;SW;ZzNAMEqQ L104A +100g;10240;1;;;;12;SW;ZzNAMEqQ S201A;36;SW;ZzNAMEqQ L123B +100g;10240;1;;;;12;SW;ZzNAMEqQ S201B;36;SW;ZzNAMEqQ L104A +100g;10240;1;;;;12;SW;ZzNAMEqQ S202A;36;SW;ZzNAMEqQ L101B +100g;10240;1;;;;12;SW;ZzNAMEqQ S202B;36;SW;ZzNAMEqQ L106A +100g;10240;1;;;;12;SW;ZzNAMEqQ S203A;36;SW;ZzNAMEqQ L103B +100g;10240;1;;;;12;SW;ZzNAMEqQ S203B;36;SW;ZzNAMEqQ L108A +100g;10240;1;;;;12;SW;ZzNAMEqQ S204A;36;SW;ZzNAMEqQ L105B +100g;10240;1;;;;12;SW;ZzNAMEqQ S204B;36;SW;ZzNAMEqQ L110A +100g;10240;1;;;;12;SW;ZzNAMEqQ S205A;36;SW;ZzNAMEqQ L107B +100g;10240;1;;;;12;SW;ZzNAMEqQ S205B;36;SW;ZzNAMEqQ L112A +100g;10240;1;;;;12;SW;ZzNAMEqQ S206A;36;SW;ZzNAMEqQ L109B +100g;10240;1;;;;12;SW;ZzNAMEqQ S206B;36;SW;ZzNAMEqQ L114A +100g;10240;1;;;;12;SW;ZzNAMEqQ S207A;36;SW;ZzNAMEqQ L111B +100g;10240;1;;;;12;SW;ZzNAMEqQ S207B;36;SW;ZzNAMEqQ L116A +100g;10240;1;;;;12;SW;ZzNAMEqQ S208A;36;SW;ZzNAMEqQ L113B +100g;10240;1;;;;12;SW;ZzNAMEqQ S208B;36;SW;ZzNAMEqQ L118A +100g;10240;1;;;;12;SW;ZzNAMEqQ S209A;36;SW;ZzNAMEqQ L115B +100g;10240;1;;;;12;SW;ZzNAMEqQ S209B;36;SW;ZzNAMEqQ L120A +100g;10240;1;;;;12;SW;ZzNAMEqQ S210A;36;SW;ZzNAMEqQ L117B +100g;10240;1;;;;12;SW;ZzNAMEqQ S210B;36;SW;ZzNAMEqQ L122A +100g;10240;1;;;;12;SW;ZzNAMEqQ S211A;36;SW;ZzNAMEqQ L119B +100g;10240;1;;;;12;SW;ZzNAMEqQ S211B;36;SW;ZzNAMEqQ L124A +100g;10240;1;;;;12;SW;ZzNAMEqQ S212A;36;SW;ZzNAMEqQ L121B +100g;10240;1;;;;12;SW;ZzNAMEqQ S212B;36;SW;ZzNAMEqQ L102A +100g;10240;1;;;;13;SW;ZzNAMEqQ S201A;37;SW;ZzNAMEqQ L101B +100g;10240;1;;;;13;SW;ZzNAMEqQ S201B;37;SW;ZzNAMEqQ L102A +100g;10240;1;;;;13;SW;ZzNAMEqQ S202A;37;SW;ZzNAMEqQ L103B +100g;10240;1;;;;13;SW;ZzNAMEqQ S202B;37;SW;ZzNAMEqQ L104A +100g;10240;1;;;;13;SW;ZzNAMEqQ S203A;37;SW;ZzNAMEqQ L105B +100g;10240;1;;;;13;SW;ZzNAMEqQ S203B;37;SW;ZzNAMEqQ L106A +100g;10240;1;;;;13;SW;ZzNAMEqQ S204A;37;SW;ZzNAMEqQ L107B +100g;10240;1;;;;13;SW;ZzNAMEqQ S204B;37;SW;ZzNAMEqQ L108A +100g;10240;1;;;;13;SW;ZzNAMEqQ S205A;37;SW;ZzNAMEqQ L109B +100g;10240;1;;;;13;SW;ZzNAMEqQ S205B;37;SW;ZzNAMEqQ L110A +100g;10240;1;;;;13;SW;ZzNAMEqQ S206A;37;SW;ZzNAMEqQ L111B +100g;10240;1;;;;13;SW;ZzNAMEqQ S206B;37;SW;ZzNAMEqQ L112A +100g;10240;1;;;;13;SW;ZzNAMEqQ S207A;37;SW;ZzNAMEqQ L113B +100g;10240;1;;;;13;SW;ZzNAMEqQ S207B;37;SW;ZzNAMEqQ L114A +100g;10240;1;;;;13;SW;ZzNAMEqQ S208A;37;SW;ZzNAMEqQ L115B +100g;10240;1;;;;13;SW;ZzNAMEqQ S208B;37;SW;ZzNAMEqQ L116A +100g;10240;1;;;;13;SW;ZzNAMEqQ S209A;37;SW;ZzNAMEqQ L117B +100g;10240;1;;;;13;SW;ZzNAMEqQ S209B;37;SW;ZzNAMEqQ L118A +100g;10240;1;;;;13;SW;ZzNAMEqQ S210A;37;SW;ZzNAMEqQ L119B +100g;10240;1;;;;13;SW;ZzNAMEqQ S210B;37;SW;ZzNAMEqQ L120A +100g;10240;1;;;;13;SW;ZzNAMEqQ S211A;37;SW;ZzNAMEqQ L121B +100g;10240;1;;;;13;SW;ZzNAMEqQ S211B;37;SW;ZzNAMEqQ L122A +100g;10240;1;;;;13;SW;ZzNAMEqQ S212A;37;SW;ZzNAMEqQ L123B +100g;10240;1;;;;13;SW;ZzNAMEqQ S212B;37;SW;ZzNAMEqQ L124A +100g;10240;1;;;;14;SW;ZzNAMEqQ S201A;38;SW;ZzNAMEqQ L103B +100g;10240;1;;;;14;SW;ZzNAMEqQ S201B;38;SW;ZzNAMEqQ L124A +100g;10240;1;;;;14;SW;ZzNAMEqQ S202A;38;SW;ZzNAMEqQ L105B +100g;10240;1;;;;14;SW;ZzNAMEqQ S202B;38;SW;ZzNAMEqQ L102A +100g;10240;1;;;;14;SW;ZzNAMEqQ S203A;38;SW;ZzNAMEqQ L107B +100g;10240;1;;;;14;SW;ZzNAMEqQ S203B;38;SW;ZzNAMEqQ L104A +100g;10240;1;;;;14;SW;ZzNAMEqQ S204A;38;SW;ZzNAMEqQ L109B +100g;10240;1;;;;14;SW;ZzNAMEqQ S204B;38;SW;ZzNAMEqQ L106A +100g;10240;1;;;;14;SW;ZzNAMEqQ S205A;38;SW;ZzNAMEqQ L111B +100g;10240;1;;;;14;SW;ZzNAMEqQ S205B;38;SW;ZzNAMEqQ L108A +100g;10240;1;;;;14;SW;ZzNAMEqQ S206A;38;SW;ZzNAMEqQ L113B +100g;10240;1;;;;14;SW;ZzNAMEqQ S206B;38;SW;ZzNAMEqQ L110A +100g;10240;1;;;;14;SW;ZzNAMEqQ S207A;38;SW;ZzNAMEqQ L115B +100g;10240;1;;;;14;SW;ZzNAMEqQ S207B;38;SW;ZzNAMEqQ L112A +100g;10240;1;;;;14;SW;ZzNAMEqQ S208A;38;SW;ZzNAMEqQ L117B +100g;10240;1;;;;14;SW;ZzNAMEqQ S208B;38;SW;ZzNAMEqQ L114A +100g;10240;1;;;;14;SW;ZzNAMEqQ S209A;38;SW;ZzNAMEqQ L119B +100g;10240;1;;;;14;SW;ZzNAMEqQ S209B;38;SW;ZzNAMEqQ L116A +100g;10240;1;;;;14;SW;ZzNAMEqQ S210A;38;SW;ZzNAMEqQ L121B +100g;10240;1;;;;14;SW;ZzNAMEqQ S210B;38;SW;ZzNAMEqQ L118A +100g;10240;1;;;;14;SW;ZzNAMEqQ S211A;38;SW;ZzNAMEqQ L123B +100g;10240;1;;;;14;SW;ZzNAMEqQ S211B;38;SW;ZzNAMEqQ L120A +100g;10240;1;;;;14;SW;ZzNAMEqQ S212A;38;SW;ZzNAMEqQ L101B +100g;10240;1;;;;14;SW;ZzNAMEqQ S212B;38;SW;ZzNAMEqQ L122A +100g;10240;1;;;;15;SW;ZzNAMEqQ S201A;39;SW;ZzNAMEqQ L105B +100g;10240;1;;;;15;SW;ZzNAMEqQ S201B;39;SW;ZzNAMEqQ L122A +100g;10240;1;;;;15;SW;ZzNAMEqQ S202A;39;SW;ZzNAMEqQ L107B +100g;10240;1;;;;15;SW;ZzNAMEqQ S202B;39;SW;ZzNAMEqQ L124A +100g;10240;1;;;;15;SW;ZzNAMEqQ S203A;39;SW;ZzNAMEqQ L109B +100g;10240;1;;;;15;SW;ZzNAMEqQ S203B;39;SW;ZzNAMEqQ L102A +100g;10240;1;;;;15;SW;ZzNAMEqQ S204A;39;SW;ZzNAMEqQ L111B +100g;10240;1;;;;15;SW;ZzNAMEqQ S204B;39;SW;ZzNAMEqQ L104A +100g;10240;1;;;;15;SW;ZzNAMEqQ S205A;39;SW;ZzNAMEqQ L113B +100g;10240;1;;;;15;SW;ZzNAMEqQ S205B;39;SW;ZzNAMEqQ L106A +100g;10240;1;;;;15;SW;ZzNAMEqQ S206A;39;SW;ZzNAMEqQ L115B +100g;10240;1;;;;15;SW;ZzNAMEqQ S206B;39;SW;ZzNAMEqQ L108A +100g;10240;1;;;;15;SW;ZzNAMEqQ S207A;39;SW;ZzNAMEqQ L117B +100g;10240;1;;;;15;SW;ZzNAMEqQ S207B;39;SW;ZzNAMEqQ L110A +100g;10240;1;;;;15;SW;ZzNAMEqQ S208A;39;SW;ZzNAMEqQ L119B +100g;10240;1;;;;15;SW;ZzNAMEqQ S208B;39;SW;ZzNAMEqQ L112A +100g;10240;1;;;;15;SW;ZzNAMEqQ S209A;39;SW;ZzNAMEqQ L121B +100g;10240;1;;;;15;SW;ZzNAMEqQ S209B;39;SW;ZzNAMEqQ L114A +100g;10240;1;;;;15;SW;ZzNAMEqQ S210A;39;SW;ZzNAMEqQ L123B +100g;10240;1;;;;15;SW;ZzNAMEqQ S210B;39;SW;ZzNAMEqQ L116A +100g;10240;1;;;;15;SW;ZzNAMEqQ S211A;39;SW;ZzNAMEqQ L101B +100g;10240;1;;;;15;SW;ZzNAMEqQ S211B;39;SW;ZzNAMEqQ L118A +100g;10240;1;;;;15;SW;ZzNAMEqQ S212A;39;SW;ZzNAMEqQ L103B +100g;10240;1;;;;15;SW;ZzNAMEqQ S212B;39;SW;ZzNAMEqQ L120A +100g;10240;1;;;;16;SW;ZzNAMEqQ S201A;40;SW;ZzNAMEqQ L107B +100g;10240;1;;;;16;SW;ZzNAMEqQ S201B;40;SW;ZzNAMEqQ L120A +100g;10240;1;;;;16;SW;ZzNAMEqQ S202A;40;SW;ZzNAMEqQ L109B +100g;10240;1;;;;16;SW;ZzNAMEqQ S202B;40;SW;ZzNAMEqQ L122A +100g;10240;1;;;;16;SW;ZzNAMEqQ S203A;40;SW;ZzNAMEqQ L111B +100g;10240;1;;;;16;SW;ZzNAMEqQ S203B;40;SW;ZzNAMEqQ L124A +100g;10240;1;;;;16;SW;ZzNAMEqQ S204A;40;SW;ZzNAMEqQ L113B +100g;10240;1;;;;16;SW;ZzNAMEqQ S204B;40;SW;ZzNAMEqQ L102A +100g;10240;1;;;;16;SW;ZzNAMEqQ S205A;40;SW;ZzNAMEqQ L115B +100g;10240;1;;;;16;SW;ZzNAMEqQ S205B;40;SW;ZzNAMEqQ L104A +100g;10240;1;;;;16;SW;ZzNAMEqQ S206A;40;SW;ZzNAMEqQ L117B +100g;10240;1;;;;16;SW;ZzNAMEqQ S206B;40;SW;ZzNAMEqQ L106A +100g;10240;1;;;;16;SW;ZzNAMEqQ S207A;40;SW;ZzNAMEqQ L119B +100g;10240;1;;;;16;SW;ZzNAMEqQ S207B;40;SW;ZzNAMEqQ L108A +100g;10240;1;;;;16;SW;ZzNAMEqQ S208A;40;SW;ZzNAMEqQ L121B +100g;10240;1;;;;16;SW;ZzNAMEqQ S208B;40;SW;ZzNAMEqQ L110A +100g;10240;1;;;;16;SW;ZzNAMEqQ S209A;40;SW;ZzNAMEqQ L123B +100g;10240;1;;;;16;SW;ZzNAMEqQ S209B;40;SW;ZzNAMEqQ L112A +100g;10240;1;;;;16;SW;ZzNAMEqQ S210A;40;SW;ZzNAMEqQ L101B +100g;10240;1;;;;16;SW;ZzNAMEqQ S210B;40;SW;ZzNAMEqQ L114A +100g;10240;1;;;;16;SW;ZzNAMEqQ S211A;40;SW;ZzNAMEqQ L103B +100g;10240;1;;;;16;SW;ZzNAMEqQ S211B;40;SW;ZzNAMEqQ L116A +100g;10240;1;;;;16;SW;ZzNAMEqQ S212A;40;SW;ZzNAMEqQ L105B +100g;10240;1;;;;16;SW;ZzNAMEqQ S212B;40;SW;ZzNAMEqQ L118A +100g;10240;1;;;;17;SW;ZzNAMEqQ S201A;41;SW;ZzNAMEqQ L109B +100g;10240;1;;;;17;SW;ZzNAMEqQ S201B;41;SW;ZzNAMEqQ L118A +100g;10240;1;;;;17;SW;ZzNAMEqQ S202A;41;SW;ZzNAMEqQ L111B +100g;10240;1;;;;17;SW;ZzNAMEqQ S202B;41;SW;ZzNAMEqQ L120A +100g;10240;1;;;;17;SW;ZzNAMEqQ S203A;41;SW;ZzNAMEqQ L113B +100g;10240;1;;;;17;SW;ZzNAMEqQ S203B;41;SW;ZzNAMEqQ L122A +100g;10240;1;;;;17;SW;ZzNAMEqQ S204A;41;SW;ZzNAMEqQ L115B +100g;10240;1;;;;17;SW;ZzNAMEqQ S204B;41;SW;ZzNAMEqQ L124A +100g;10240;1;;;;17;SW;ZzNAMEqQ S205A;41;SW;ZzNAMEqQ L117B +100g;10240;1;;;;17;SW;ZzNAMEqQ S205B;41;SW;ZzNAMEqQ L102A +100g;10240;1;;;;17;SW;ZzNAMEqQ S206A;41;SW;ZzNAMEqQ L119B +100g;10240;1;;;;17;SW;ZzNAMEqQ S206B;41;SW;ZzNAMEqQ L104A +100g;10240;1;;;;17;SW;ZzNAMEqQ S207A;41;SW;ZzNAMEqQ L121B +100g;10240;1;;;;17;SW;ZzNAMEqQ S207B;41;SW;ZzNAMEqQ L106A +100g;10240;1;;;;17;SW;ZzNAMEqQ S208A;41;SW;ZzNAMEqQ L123B +100g;10240;1;;;;17;SW;ZzNAMEqQ S208B;41;SW;ZzNAMEqQ L108A +100g;10240;1;;;;17;SW;ZzNAMEqQ S209A;41;SW;ZzNAMEqQ L101B +100g;10240;1;;;;17;SW;ZzNAMEqQ S209B;41;SW;ZzNAMEqQ L110A +100g;10240;1;;;;17;SW;ZzNAMEqQ S210A;41;SW;ZzNAMEqQ L103B +100g;10240;1;;;;17;SW;ZzNAMEqQ S210B;41;SW;ZzNAMEqQ L112A +100g;10240;1;;;;17;SW;ZzNAMEqQ S211A;41;SW;ZzNAMEqQ L105B +100g;10240;1;;;;17;SW;ZzNAMEqQ S211B;41;SW;ZzNAMEqQ L114A +100g;10240;1;;;;17;SW;ZzNAMEqQ S212A;41;SW;ZzNAMEqQ L107B +100g;10240;1;;;;17;SW;ZzNAMEqQ S212B;41;SW;ZzNAMEqQ L116A +100g;10240;1;;;;18;SW;ZzNAMEqQ S201A;42;SW;ZzNAMEqQ L111B +100g;10240;1;;;;18;SW;ZzNAMEqQ S201B;42;SW;ZzNAMEqQ L116A +100g;10240;1;;;;18;SW;ZzNAMEqQ S202A;42;SW;ZzNAMEqQ L113B +100g;10240;1;;;;18;SW;ZzNAMEqQ S202B;42;SW;ZzNAMEqQ L118A +100g;10240;1;;;;18;SW;ZzNAMEqQ S203A;42;SW;ZzNAMEqQ L115B +100g;10240;1;;;;18;SW;ZzNAMEqQ S203B;42;SW;ZzNAMEqQ L120A +100g;10240;1;;;;18;SW;ZzNAMEqQ S204A;42;SW;ZzNAMEqQ L117B +100g;10240;1;;;;18;SW;ZzNAMEqQ S204B;42;SW;ZzNAMEqQ L122A +100g;10240;1;;;;18;SW;ZzNAMEqQ S205A;42;SW;ZzNAMEqQ L119B +100g;10240;1;;;;18;SW;ZzNAMEqQ S205B;42;SW;ZzNAMEqQ L124A +100g;10240;1;;;;18;SW;ZzNAMEqQ S206A;42;SW;ZzNAMEqQ L121B +100g;10240;1;;;;18;SW;ZzNAMEqQ S206B;42;SW;ZzNAMEqQ L102A +100g;10240;1;;;;18;SW;ZzNAMEqQ S207A;42;SW;ZzNAMEqQ L123B +100g;10240;1;;;;18;SW;ZzNAMEqQ S207B;42;SW;ZzNAMEqQ L104A +100g;10240;1;;;;18;SW;ZzNAMEqQ S208A;42;SW;ZzNAMEqQ L101B +100g;10240;1;;;;18;SW;ZzNAMEqQ S208B;42;SW;ZzNAMEqQ L106A +100g;10240;1;;;;18;SW;ZzNAMEqQ S209A;42;SW;ZzNAMEqQ L103B +100g;10240;1;;;;18;SW;ZzNAMEqQ S209B;42;SW;ZzNAMEqQ L108A +100g;10240;1;;;;18;SW;ZzNAMEqQ S210A;42;SW;ZzNAMEqQ L105B +100g;10240;1;;;;18;SW;ZzNAMEqQ S210B;42;SW;ZzNAMEqQ L110A +100g;10240;1;;;;18;SW;ZzNAMEqQ S211A;42;SW;ZzNAMEqQ L107B +100g;10240;1;;;;18;SW;ZzNAMEqQ S211B;42;SW;ZzNAMEqQ L112A +100g;10240;1;;;;18;SW;ZzNAMEqQ S212A;42;SW;ZzNAMEqQ L109B +100g;10240;1;;;;18;SW;ZzNAMEqQ S212B;42;SW;ZzNAMEqQ L114A +100g;10240;1;;;;19;SW;ZzNAMEqQ S201A;30;SW;ZzNAMEqQ L103A +100g;10240;1;;;;19;SW;ZzNAMEqQ S201B;30;SW;ZzNAMEqQ L124B +100g;10240;1;;;;19;SW;ZzNAMEqQ S202A;30;SW;ZzNAMEqQ L105A +100g;10240;1;;;;19;SW;ZzNAMEqQ S202B;30;SW;ZzNAMEqQ L102B +100g;10240;1;;;;19;SW;ZzNAMEqQ S203A;30;SW;ZzNAMEqQ L107A +100g;10240;1;;;;19;SW;ZzNAMEqQ S203B;30;SW;ZzNAMEqQ L104B +100g;10240;1;;;;19;SW;ZzNAMEqQ S204A;30;SW;ZzNAMEqQ L109A +100g;10240;1;;;;19;SW;ZzNAMEqQ S204B;30;SW;ZzNAMEqQ L106B +100g;10240;1;;;;19;SW;ZzNAMEqQ S205A;30;SW;ZzNAMEqQ L111A +100g;10240;1;;;;19;SW;ZzNAMEqQ S205B;30;SW;ZzNAMEqQ L108B +100g;10240;1;;;;19;SW;ZzNAMEqQ S206A;30;SW;ZzNAMEqQ L113A +100g;10240;1;;;;19;SW;ZzNAMEqQ S206B;30;SW;ZzNAMEqQ L110B +100g;10240;1;;;;19;SW;ZzNAMEqQ S207A;30;SW;ZzNAMEqQ L115A +100g;10240;1;;;;19;SW;ZzNAMEqQ S207B;30;SW;ZzNAMEqQ L112B +100g;10240;1;;;;19;SW;ZzNAMEqQ S208A;30;SW;ZzNAMEqQ L117A +100g;10240;1;;;;19;SW;ZzNAMEqQ S208B;30;SW;ZzNAMEqQ L114B +100g;10240;1;;;;19;SW;ZzNAMEqQ S209A;30;SW;ZzNAMEqQ L119A +100g;10240;1;;;;19;SW;ZzNAMEqQ S209B;30;SW;ZzNAMEqQ L116B +100g;10240;1;;;;19;SW;ZzNAMEqQ S210A;30;SW;ZzNAMEqQ L121A +100g;10240;1;;;;19;SW;ZzNAMEqQ S210B;30;SW;ZzNAMEqQ L118B +100g;10240;1;;;;19;SW;ZzNAMEqQ S211A;30;SW;ZzNAMEqQ L123A +100g;10240;1;;;;19;SW;ZzNAMEqQ S211B;30;SW;ZzNAMEqQ L120B +100g;10240;1;;;;19;SW;ZzNAMEqQ S212A;30;SW;ZzNAMEqQ L101A +100g;10240;1;;;;19;SW;ZzNAMEqQ S212B;30;SW;ZzNAMEqQ L122B +100g;10240;1;;;;20;SW;ZzNAMEqQ S201A;29;SW;ZzNAMEqQ L105A +100g;10240;1;;;;20;SW;ZzNAMEqQ S201B;29;SW;ZzNAMEqQ L122B +100g;10240;1;;;;20;SW;ZzNAMEqQ S202A;29;SW;ZzNAMEqQ L107A +100g;10240;1;;;;20;SW;ZzNAMEqQ S202B;29;SW;ZzNAMEqQ L124B +100g;10240;1;;;;20;SW;ZzNAMEqQ S203A;29;SW;ZzNAMEqQ L109A +100g;10240;1;;;;20;SW;ZzNAMEqQ S203B;29;SW;ZzNAMEqQ L102B +100g;10240;1;;;;20;SW;ZzNAMEqQ S204A;29;SW;ZzNAMEqQ L111A +100g;10240;1;;;;20;SW;ZzNAMEqQ S204B;29;SW;ZzNAMEqQ L104B +100g;10240;1;;;;20;SW;ZzNAMEqQ S205A;29;SW;ZzNAMEqQ L113A +100g;10240;1;;;;20;SW;ZzNAMEqQ S205B;29;SW;ZzNAMEqQ L106B +100g;10240;1;;;;20;SW;ZzNAMEqQ S206A;29;SW;ZzNAMEqQ L115A +100g;10240;1;;;;20;SW;ZzNAMEqQ S206B;29;SW;ZzNAMEqQ L108B +100g;10240;1;;;;20;SW;ZzNAMEqQ S207A;29;SW;ZzNAMEqQ L117A +100g;10240;1;;;;20;SW;ZzNAMEqQ S207B;29;SW;ZzNAMEqQ L110B +100g;10240;1;;;;20;SW;ZzNAMEqQ S208A;29;SW;ZzNAMEqQ L119A +100g;10240;1;;;;20;SW;ZzNAMEqQ S208B;29;SW;ZzNAMEqQ L112B +100g;10240;1;;;;20;SW;ZzNAMEqQ S209A;29;SW;ZzNAMEqQ L121A +100g;10240;1;;;;20;SW;ZzNAMEqQ S209B;29;SW;ZzNAMEqQ L114B +100g;10240;1;;;;20;SW;ZzNAMEqQ S210A;29;SW;ZzNAMEqQ L123A +100g;10240;1;;;;20;SW;ZzNAMEqQ S210B;29;SW;ZzNAMEqQ L116B +100g;10240;1;;;;20;SW;ZzNAMEqQ S211A;29;SW;ZzNAMEqQ L101A +100g;10240;1;;;;20;SW;ZzNAMEqQ S211B;29;SW;ZzNAMEqQ L118B +100g;10240;1;;;;20;SW;ZzNAMEqQ S212A;29;SW;ZzNAMEqQ L103A +100g;10240;1;;;;20;SW;ZzNAMEqQ S212B;29;SW;ZzNAMEqQ L120B +100g;10240;1;;;;21;SW;ZzNAMEqQ S201A;28;SW;ZzNAMEqQ L107A +100g;10240;1;;;;21;SW;ZzNAMEqQ S201B;28;SW;ZzNAMEqQ L120B +100g;10240;1;;;;21;SW;ZzNAMEqQ S202A;28;SW;ZzNAMEqQ L109A +100g;10240;1;;;;21;SW;ZzNAMEqQ S202B;28;SW;ZzNAMEqQ L122B +100g;10240;1;;;;21;SW;ZzNAMEqQ S203A;28;SW;ZzNAMEqQ L111A +100g;10240;1;;;;21;SW;ZzNAMEqQ S203B;28;SW;ZzNAMEqQ L124B +100g;10240;1;;;;21;SW;ZzNAMEqQ S204A;28;SW;ZzNAMEqQ L113A +100g;10240;1;;;;21;SW;ZzNAMEqQ S204B;28;SW;ZzNAMEqQ L102B +100g;10240;1;;;;21;SW;ZzNAMEqQ S205A;28;SW;ZzNAMEqQ L115A +100g;10240;1;;;;21;SW;ZzNAMEqQ S205B;28;SW;ZzNAMEqQ L104B +100g;10240;1;;;;21;SW;ZzNAMEqQ S206A;28;SW;ZzNAMEqQ L117A +100g;10240;1;;;;21;SW;ZzNAMEqQ S206B;28;SW;ZzNAMEqQ L106B +100g;10240;1;;;;21;SW;ZzNAMEqQ S207A;28;SW;ZzNAMEqQ L119A +100g;10240;1;;;;21;SW;ZzNAMEqQ S207B;28;SW;ZzNAMEqQ L108B +100g;10240;1;;;;21;SW;ZzNAMEqQ S208A;28;SW;ZzNAMEqQ L121A +100g;10240;1;;;;21;SW;ZzNAMEqQ S208B;28;SW;ZzNAMEqQ L110B +100g;10240;1;;;;21;SW;ZzNAMEqQ S209A;28;SW;ZzNAMEqQ L123A +100g;10240;1;;;;21;SW;ZzNAMEqQ S209B;28;SW;ZzNAMEqQ L112B +100g;10240;1;;;;21;SW;ZzNAMEqQ S210A;28;SW;ZzNAMEqQ L101A +100g;10240;1;;;;21;SW;ZzNAMEqQ S210B;28;SW;ZzNAMEqQ L114B +100g;10240;1;;;;21;SW;ZzNAMEqQ S211A;28;SW;ZzNAMEqQ L103A +100g;10240;1;;;;21;SW;ZzNAMEqQ S211B;28;SW;ZzNAMEqQ L116B +100g;10240;1;;;;21;SW;ZzNAMEqQ S212A;28;SW;ZzNAMEqQ L105A +100g;10240;1;;;;21;SW;ZzNAMEqQ S212B;28;SW;ZzNAMEqQ L118B +100g;10240;1;;;;22;SW;ZzNAMEqQ S201A;27;SW;ZzNAMEqQ L109A +100g;10240;1;;;;22;SW;ZzNAMEqQ S201B;27;SW;ZzNAMEqQ L118B +100g;10240;1;;;;22;SW;ZzNAMEqQ S202A;27;SW;ZzNAMEqQ L111A +100g;10240;1;;;;22;SW;ZzNAMEqQ S202B;27;SW;ZzNAMEqQ L120B +100g;10240;1;;;;22;SW;ZzNAMEqQ S203A;27;SW;ZzNAMEqQ L113A +100g;10240;1;;;;22;SW;ZzNAMEqQ S203B;27;SW;ZzNAMEqQ L122B +100g;10240;1;;;;22;SW;ZzNAMEqQ S204A;27;SW;ZzNAMEqQ L115A +100g;10240;1;;;;22;SW;ZzNAMEqQ S204B;27;SW;ZzNAMEqQ L124B +100g;10240;1;;;;22;SW;ZzNAMEqQ S205A;27;SW;ZzNAMEqQ L117A +100g;10240;1;;;;22;SW;ZzNAMEqQ S205B;27;SW;ZzNAMEqQ L102B +100g;10240;1;;;;22;SW;ZzNAMEqQ S206A;27;SW;ZzNAMEqQ L119A +100g;10240;1;;;;22;SW;ZzNAMEqQ S206B;27;SW;ZzNAMEqQ L104B +100g;10240;1;;;;22;SW;ZzNAMEqQ S207A;27;SW;ZzNAMEqQ L121A +100g;10240;1;;;;22;SW;ZzNAMEqQ S207B;27;SW;ZzNAMEqQ L106B +100g;10240;1;;;;22;SW;ZzNAMEqQ S208A;27;SW;ZzNAMEqQ L123A +100g;10240;1;;;;22;SW;ZzNAMEqQ S208B;27;SW;ZzNAMEqQ L108B +100g;10240;1;;;;22;SW;ZzNAMEqQ S209A;27;SW;ZzNAMEqQ L101A +100g;10240;1;;;;22;SW;ZzNAMEqQ S209B;27;SW;ZzNAMEqQ L110B +100g;10240;1;;;;22;SW;ZzNAMEqQ S210A;27;SW;ZzNAMEqQ L103A +100g;10240;1;;;;22;SW;ZzNAMEqQ S210B;27;SW;ZzNAMEqQ L112B +100g;10240;1;;;;22;SW;ZzNAMEqQ S211A;27;SW;ZzNAMEqQ L105A +100g;10240;1;;;;22;SW;ZzNAMEqQ S211B;27;SW;ZzNAMEqQ L114B +100g;10240;1;;;;22;SW;ZzNAMEqQ S212A;27;SW;ZzNAMEqQ L107A +100g;10240;1;;;;22;SW;ZzNAMEqQ S212B;27;SW;ZzNAMEqQ L116B +100g;10240;1;;;;23;SW;ZzNAMEqQ S201A;26;SW;ZzNAMEqQ L111A +100g;10240;1;;;;23;SW;ZzNAMEqQ S201B;26;SW;ZzNAMEqQ L116B +100g;10240;1;;;;23;SW;ZzNAMEqQ S202A;26;SW;ZzNAMEqQ L113A +100g;10240;1;;;;23;SW;ZzNAMEqQ S202B;26;SW;ZzNAMEqQ L118B +100g;10240;1;;;;23;SW;ZzNAMEqQ S203A;26;SW;ZzNAMEqQ L115A +100g;10240;1;;;;23;SW;ZzNAMEqQ S203B;26;SW;ZzNAMEqQ L120B +100g;10240;1;;;;23;SW;ZzNAMEqQ S204A;26;SW;ZzNAMEqQ L117A +100g;10240;1;;;;23;SW;ZzNAMEqQ S204B;26;SW;ZzNAMEqQ L122B +100g;10240;1;;;;23;SW;ZzNAMEqQ S205A;26;SW;ZzNAMEqQ L119A +100g;10240;1;;;;23;SW;ZzNAMEqQ S205B;26;SW;ZzNAMEqQ L124B +100g;10240;1;;;;23;SW;ZzNAMEqQ S206A;26;SW;ZzNAMEqQ L121A +100g;10240;1;;;;23;SW;ZzNAMEqQ S206B;26;SW;ZzNAMEqQ L102B +100g;10240;1;;;;23;SW;ZzNAMEqQ S207A;26;SW;ZzNAMEqQ L123A +100g;10240;1;;;;23;SW;ZzNAMEqQ S207B;26;SW;ZzNAMEqQ L104B +100g;10240;1;;;;23;SW;ZzNAMEqQ S208A;26;SW;ZzNAMEqQ L101A +100g;10240;1;;;;23;SW;ZzNAMEqQ S208B;26;SW;ZzNAMEqQ L106B +100g;10240;1;;;;23;SW;ZzNAMEqQ S209A;26;SW;ZzNAMEqQ L103A +100g;10240;1;;;;23;SW;ZzNAMEqQ S209B;26;SW;ZzNAMEqQ L108B +100g;10240;1;;;;23;SW;ZzNAMEqQ S210A;26;SW;ZzNAMEqQ L105A +100g;10240;1;;;;23;SW;ZzNAMEqQ S210B;26;SW;ZzNAMEqQ L110B +100g;10240;1;;;;23;SW;ZzNAMEqQ S211A;26;SW;ZzNAMEqQ L107A +100g;10240;1;;;;23;SW;ZzNAMEqQ S211B;26;SW;ZzNAMEqQ L112B +100g;10240;1;;;;23;SW;ZzNAMEqQ S212A;26;SW;ZzNAMEqQ L109A +100g;10240;1;;;;23;SW;ZzNAMEqQ S212B;26;SW;ZzNAMEqQ L114B +100g;10240;1;;;;24;SW;ZzNAMEqQ S201A;25;SW;ZzNAMEqQ L101A +100g;10240;1;;;;24;SW;ZzNAMEqQ S201B;25;SW;ZzNAMEqQ L114B +100g;10240;1;;;;24;SW;ZzNAMEqQ S202A;25;SW;ZzNAMEqQ L103A +100g;10240;1;;;;24;SW;ZzNAMEqQ S202B;25;SW;ZzNAMEqQ L116B +100g;10240;1;;;;24;SW;ZzNAMEqQ S203A;25;SW;ZzNAMEqQ L105A +100g;10240;1;;;;24;SW;ZzNAMEqQ S203B;25;SW;ZzNAMEqQ L118B +100g;10240;1;;;;24;SW;ZzNAMEqQ S204A;25;SW;ZzNAMEqQ L107A +100g;10240;1;;;;24;SW;ZzNAMEqQ S204B;25;SW;ZzNAMEqQ L120B +100g;10240;1;;;;24;SW;ZzNAMEqQ S205A;25;SW;ZzNAMEqQ L109A +100g;10240;1;;;;24;SW;ZzNAMEqQ S205B;25;SW;ZzNAMEqQ L122B +100g;10240;1;;;;24;SW;ZzNAMEqQ S206A;25;SW;ZzNAMEqQ L111A +100g;10240;1;;;;24;SW;ZzNAMEqQ S206B;25;SW;ZzNAMEqQ L124B +100g;10240;1;;;;24;SW;ZzNAMEqQ S207A;25;SW;ZzNAMEqQ L113A +100g;10240;1;;;;24;SW;ZzNAMEqQ S207B;25;SW;ZzNAMEqQ L102B +100g;10240;1;;;;24;SW;ZzNAMEqQ S208A;25;SW;ZzNAMEqQ L115A +100g;10240;1;;;;24;SW;ZzNAMEqQ S208B;25;SW;ZzNAMEqQ L104B +100g;10240;1;;;;24;SW;ZzNAMEqQ S209A;25;SW;ZzNAMEqQ L117A +100g;10240;1;;;;24;SW;ZzNAMEqQ S209B;25;SW;ZzNAMEqQ L106B +100g;10240;1;;;;24;SW;ZzNAMEqQ S210A;25;SW;ZzNAMEqQ L119A +100g;10240;1;;;;24;SW;ZzNAMEqQ S210B;25;SW;ZzNAMEqQ L108B +100g;10240;1;;;;24;SW;ZzNAMEqQ S211A;25;SW;ZzNAMEqQ L121A +100g;10240;1;;;;24;SW;ZzNAMEqQ S211B;25;SW;ZzNAMEqQ L110B +100g;10240;1;;;;24;SW;ZzNAMEqQ S212A;25;SW;ZzNAMEqQ L123A +100g;10240;1;;;;24;SW;ZzNAMEqQ S212B;25;SW;ZzNAMEqQ L112B +100g;10240;1;;;;25;SW;ZzNAMEqQ S201A;48;SW;ZzNAMEqQ L114A +100g;10240;1;;;;25;SW;ZzNAMEqQ S201B;48;SW;ZzNAMEqQ L101B +100g;10240;1;;;;25;SW;ZzNAMEqQ S202A;48;SW;ZzNAMEqQ L116A +100g;10240;1;;;;25;SW;ZzNAMEqQ S202B;48;SW;ZzNAMEqQ L103B +100g;10240;1;;;;25;SW;ZzNAMEqQ S203A;48;SW;ZzNAMEqQ L118A +100g;10240;1;;;;25;SW;ZzNAMEqQ S203B;48;SW;ZzNAMEqQ L105B +100g;10240;1;;;;25;SW;ZzNAMEqQ S204A;48;SW;ZzNAMEqQ L120A +100g;10240;1;;;;25;SW;ZzNAMEqQ S204B;48;SW;ZzNAMEqQ L107B +100g;10240;1;;;;25;SW;ZzNAMEqQ S205A;48;SW;ZzNAMEqQ L122A +100g;10240;1;;;;25;SW;ZzNAMEqQ S205B;48;SW;ZzNAMEqQ L109B +100g;10240;1;;;;25;SW;ZzNAMEqQ S206A;48;SW;ZzNAMEqQ L124A +100g;10240;1;;;;25;SW;ZzNAMEqQ S206B;48;SW;ZzNAMEqQ L111B +100g;10240;1;;;;25;SW;ZzNAMEqQ S207A;48;SW;ZzNAMEqQ L102A +100g;10240;1;;;;25;SW;ZzNAMEqQ S207B;48;SW;ZzNAMEqQ L113B +100g;10240;1;;;;25;SW;ZzNAMEqQ S208A;48;SW;ZzNAMEqQ L104A +100g;10240;1;;;;25;SW;ZzNAMEqQ S208B;48;SW;ZzNAMEqQ L115B +100g;10240;1;;;;25;SW;ZzNAMEqQ S209A;48;SW;ZzNAMEqQ L106A +100g;10240;1;;;;25;SW;ZzNAMEqQ S209B;48;SW;ZzNAMEqQ L117B +100g;10240;1;;;;25;SW;ZzNAMEqQ S210A;48;SW;ZzNAMEqQ L108A +100g;10240;1;;;;25;SW;ZzNAMEqQ S210B;48;SW;ZzNAMEqQ L119B +100g;10240;1;;;;25;SW;ZzNAMEqQ S211A;48;SW;ZzNAMEqQ L110A +100g;10240;1;;;;25;SW;ZzNAMEqQ S211B;48;SW;ZzNAMEqQ L121B +100g;10240;1;;;;25;SW;ZzNAMEqQ S212A;48;SW;ZzNAMEqQ L112A +100g;10240;1;;;;25;SW;ZzNAMEqQ S212B;48;SW;ZzNAMEqQ L123B +100g;10240;1;;;;26;SW;ZzNAMEqQ S201A;47;SW;ZzNAMEqQ L116A +100g;10240;1;;;;26;SW;ZzNAMEqQ S201B;47;SW;ZzNAMEqQ L111B +100g;10240;1;;;;26;SW;ZzNAMEqQ S202A;47;SW;ZzNAMEqQ L118A +100g;10240;1;;;;26;SW;ZzNAMEqQ S202B;47;SW;ZzNAMEqQ L113B +100g;10240;1;;;;26;SW;ZzNAMEqQ S203A;47;SW;ZzNAMEqQ L120A +100g;10240;1;;;;26;SW;ZzNAMEqQ S203B;47;SW;ZzNAMEqQ L115B +100g;10240;1;;;;26;SW;ZzNAMEqQ S204A;47;SW;ZzNAMEqQ L122A +100g;10240;1;;;;26;SW;ZzNAMEqQ S204B;47;SW;ZzNAMEqQ L117B +100g;10240;1;;;;26;SW;ZzNAMEqQ S205A;47;SW;ZzNAMEqQ L124A +100g;10240;1;;;;26;SW;ZzNAMEqQ S205B;47;SW;ZzNAMEqQ L119B +100g;10240;1;;;;26;SW;ZzNAMEqQ S206A;47;SW;ZzNAMEqQ L102A +100g;10240;1;;;;26;SW;ZzNAMEqQ S206B;47;SW;ZzNAMEqQ L121B +100g;10240;1;;;;26;SW;ZzNAMEqQ S207A;47;SW;ZzNAMEqQ L104A +100g;10240;1;;;;26;SW;ZzNAMEqQ S207B;47;SW;ZzNAMEqQ L123B +100g;10240;1;;;;26;SW;ZzNAMEqQ S208A;47;SW;ZzNAMEqQ L106A +100g;10240;1;;;;26;SW;ZzNAMEqQ S208B;47;SW;ZzNAMEqQ L101B +100g;10240;1;;;;26;SW;ZzNAMEqQ S209A;47;SW;ZzNAMEqQ L108A +100g;10240;1;;;;26;SW;ZzNAMEqQ S209B;47;SW;ZzNAMEqQ L103B +100g;10240;1;;;;26;SW;ZzNAMEqQ S210A;47;SW;ZzNAMEqQ L110A +100g;10240;1;;;;26;SW;ZzNAMEqQ S210B;47;SW;ZzNAMEqQ L105B +100g;10240;1;;;;26;SW;ZzNAMEqQ S211A;47;SW;ZzNAMEqQ L112A +100g;10240;1;;;;26;SW;ZzNAMEqQ S211B;47;SW;ZzNAMEqQ L107B +100g;10240;1;;;;26;SW;ZzNAMEqQ S212A;47;SW;ZzNAMEqQ L114A +100g;10240;1;;;;26;SW;ZzNAMEqQ S212B;47;SW;ZzNAMEqQ L109B +100g;10240;1;;;;27;SW;ZzNAMEqQ S201A;46;SW;ZzNAMEqQ L118A +100g;10240;1;;;;27;SW;ZzNAMEqQ S201B;46;SW;ZzNAMEqQ L109B +100g;10240;1;;;;27;SW;ZzNAMEqQ S202A;46;SW;ZzNAMEqQ L120A +100g;10240;1;;;;27;SW;ZzNAMEqQ S202B;46;SW;ZzNAMEqQ L111B +100g;10240;1;;;;27;SW;ZzNAMEqQ S203A;46;SW;ZzNAMEqQ L122A +100g;10240;1;;;;27;SW;ZzNAMEqQ S203B;46;SW;ZzNAMEqQ L113B +100g;10240;1;;;;27;SW;ZzNAMEqQ S204A;46;SW;ZzNAMEqQ L124A +100g;10240;1;;;;27;SW;ZzNAMEqQ S204B;46;SW;ZzNAMEqQ L115B +100g;10240;1;;;;27;SW;ZzNAMEqQ S205A;46;SW;ZzNAMEqQ L102A +100g;10240;1;;;;27;SW;ZzNAMEqQ S205B;46;SW;ZzNAMEqQ L117B +100g;10240;1;;;;27;SW;ZzNAMEqQ S206A;46;SW;ZzNAMEqQ L104A +100g;10240;1;;;;27;SW;ZzNAMEqQ S206B;46;SW;ZzNAMEqQ L119B +100g;10240;1;;;;27;SW;ZzNAMEqQ S207A;46;SW;ZzNAMEqQ L106A +100g;10240;1;;;;27;SW;ZzNAMEqQ S207B;46;SW;ZzNAMEqQ L121B +100g;10240;1;;;;27;SW;ZzNAMEqQ S208A;46;SW;ZzNAMEqQ L108A +100g;10240;1;;;;27;SW;ZzNAMEqQ S208B;46;SW;ZzNAMEqQ L123B +100g;10240;1;;;;27;SW;ZzNAMEqQ S209A;46;SW;ZzNAMEqQ L110A +100g;10240;1;;;;27;SW;ZzNAMEqQ S209B;46;SW;ZzNAMEqQ L101B +100g;10240;1;;;;27;SW;ZzNAMEqQ S210A;46;SW;ZzNAMEqQ L112A +100g;10240;1;;;;27;SW;ZzNAMEqQ S210B;46;SW;ZzNAMEqQ L103B +100g;10240;1;;;;27;SW;ZzNAMEqQ S211A;46;SW;ZzNAMEqQ L114A +100g;10240;1;;;;27;SW;ZzNAMEqQ S211B;46;SW;ZzNAMEqQ L105B +100g;10240;1;;;;27;SW;ZzNAMEqQ S212A;46;SW;ZzNAMEqQ L116A +100g;10240;1;;;;27;SW;ZzNAMEqQ S212B;46;SW;ZzNAMEqQ L107B +100g;10240;1;;;;28;SW;ZzNAMEqQ S201A;45;SW;ZzNAMEqQ L120A +100g;10240;1;;;;28;SW;ZzNAMEqQ S201B;45;SW;ZzNAMEqQ L107B +100g;10240;1;;;;28;SW;ZzNAMEqQ S202A;45;SW;ZzNAMEqQ L122A +100g;10240;1;;;;28;SW;ZzNAMEqQ S202B;45;SW;ZzNAMEqQ L109B +100g;10240;1;;;;28;SW;ZzNAMEqQ S203A;45;SW;ZzNAMEqQ L124A +100g;10240;1;;;;28;SW;ZzNAMEqQ S203B;45;SW;ZzNAMEqQ L111B +100g;10240;1;;;;28;SW;ZzNAMEqQ S204A;45;SW;ZzNAMEqQ L102A +100g;10240;1;;;;28;SW;ZzNAMEqQ S204B;45;SW;ZzNAMEqQ L113B +100g;10240;1;;;;28;SW;ZzNAMEqQ S205A;45;SW;ZzNAMEqQ L104A +100g;10240;1;;;;28;SW;ZzNAMEqQ S205B;45;SW;ZzNAMEqQ L115B +100g;10240;1;;;;28;SW;ZzNAMEqQ S206A;45;SW;ZzNAMEqQ L106A +100g;10240;1;;;;28;SW;ZzNAMEqQ S206B;45;SW;ZzNAMEqQ L117B +100g;10240;1;;;;28;SW;ZzNAMEqQ S207A;45;SW;ZzNAMEqQ L108A +100g;10240;1;;;;28;SW;ZzNAMEqQ S207B;45;SW;ZzNAMEqQ L119B +100g;10240;1;;;;28;SW;ZzNAMEqQ S208A;45;SW;ZzNAMEqQ L110A +100g;10240;1;;;;28;SW;ZzNAMEqQ S208B;45;SW;ZzNAMEqQ L121B +100g;10240;1;;;;28;SW;ZzNAMEqQ S209A;45;SW;ZzNAMEqQ L112A +100g;10240;1;;;;28;SW;ZzNAMEqQ S209B;45;SW;ZzNAMEqQ L123B +100g;10240;1;;;;28;SW;ZzNAMEqQ S210A;45;SW;ZzNAMEqQ L114A +100g;10240;1;;;;28;SW;ZzNAMEqQ S210B;45;SW;ZzNAMEqQ L101B +100g;10240;1;;;;28;SW;ZzNAMEqQ S211A;45;SW;ZzNAMEqQ L116A +100g;10240;1;;;;28;SW;ZzNAMEqQ S211B;45;SW;ZzNAMEqQ L103B +100g;10240;1;;;;28;SW;ZzNAMEqQ S212A;45;SW;ZzNAMEqQ L118A +100g;10240;1;;;;28;SW;ZzNAMEqQ S212B;45;SW;ZzNAMEqQ L105B +100g;10240;1;;;;29;SW;ZzNAMEqQ S201A;44;SW;ZzNAMEqQ L122A +100g;10240;1;;;;29;SW;ZzNAMEqQ S201B;44;SW;ZzNAMEqQ L105B +100g;10240;1;;;;29;SW;ZzNAMEqQ S202A;44;SW;ZzNAMEqQ L124A +100g;10240;1;;;;29;SW;ZzNAMEqQ S202B;44;SW;ZzNAMEqQ L107B +100g;10240;1;;;;29;SW;ZzNAMEqQ S203A;44;SW;ZzNAMEqQ L102A +100g;10240;1;;;;29;SW;ZzNAMEqQ S203B;44;SW;ZzNAMEqQ L109B +100g;10240;1;;;;29;SW;ZzNAMEqQ S204A;44;SW;ZzNAMEqQ L104A +100g;10240;1;;;;29;SW;ZzNAMEqQ S204B;44;SW;ZzNAMEqQ L111B +100g;10240;1;;;;29;SW;ZzNAMEqQ S205A;44;SW;ZzNAMEqQ L106A +100g;10240;1;;;;29;SW;ZzNAMEqQ S205B;44;SW;ZzNAMEqQ L113B +100g;10240;1;;;;29;SW;ZzNAMEqQ S206A;44;SW;ZzNAMEqQ L108A +100g;10240;1;;;;29;SW;ZzNAMEqQ S206B;44;SW;ZzNAMEqQ L115B +100g;10240;1;;;;29;SW;ZzNAMEqQ S207A;44;SW;ZzNAMEqQ L110A +100g;10240;1;;;;29;SW;ZzNAMEqQ S207B;44;SW;ZzNAMEqQ L117B +100g;10240;1;;;;29;SW;ZzNAMEqQ S208A;44;SW;ZzNAMEqQ L112A +100g;10240;1;;;;29;SW;ZzNAMEqQ S208B;44;SW;ZzNAMEqQ L119B +100g;10240;1;;;;29;SW;ZzNAMEqQ S209A;44;SW;ZzNAMEqQ L114A +100g;10240;1;;;;29;SW;ZzNAMEqQ S209B;44;SW;ZzNAMEqQ L121B +100g;10240;1;;;;29;SW;ZzNAMEqQ S210A;44;SW;ZzNAMEqQ L116A +100g;10240;1;;;;29;SW;ZzNAMEqQ S210B;44;SW;ZzNAMEqQ L123B +100g;10240;1;;;;29;SW;ZzNAMEqQ S211A;44;SW;ZzNAMEqQ L118A +100g;10240;1;;;;29;SW;ZzNAMEqQ S211B;44;SW;ZzNAMEqQ L101B +100g;10240;1;;;;29;SW;ZzNAMEqQ S212A;44;SW;ZzNAMEqQ L120A +100g;10240;1;;;;29;SW;ZzNAMEqQ S212B;44;SW;ZzNAMEqQ L103B +100g;10240;1;;;;30;SW;ZzNAMEqQ S201A;43;SW;ZzNAMEqQ L124A +100g;10240;1;;;;30;SW;ZzNAMEqQ S201B;43;SW;ZzNAMEqQ L103B +100g;10240;1;;;;30;SW;ZzNAMEqQ S202A;43;SW;ZzNAMEqQ L102A +100g;10240;1;;;;30;SW;ZzNAMEqQ S202B;43;SW;ZzNAMEqQ L105B +100g;10240;1;;;;30;SW;ZzNAMEqQ S203A;43;SW;ZzNAMEqQ L104A +100g;10240;1;;;;30;SW;ZzNAMEqQ S203B;43;SW;ZzNAMEqQ L107B +100g;10240;1;;;;30;SW;ZzNAMEqQ S204A;43;SW;ZzNAMEqQ L106A +100g;10240;1;;;;30;SW;ZzNAMEqQ S204B;43;SW;ZzNAMEqQ L109B +100g;10240;1;;;;30;SW;ZzNAMEqQ S205A;43;SW;ZzNAMEqQ L108A +100g;10240;1;;;;30;SW;ZzNAMEqQ S205B;43;SW;ZzNAMEqQ L111B +100g;10240;1;;;;30;SW;ZzNAMEqQ S206A;43;SW;ZzNAMEqQ L110A +100g;10240;1;;;;30;SW;ZzNAMEqQ S206B;43;SW;ZzNAMEqQ L113B +100g;10240;1;;;;30;SW;ZzNAMEqQ S207A;43;SW;ZzNAMEqQ L112A +100g;10240;1;;;;30;SW;ZzNAMEqQ S207B;43;SW;ZzNAMEqQ L115B +100g;10240;1;;;;30;SW;ZzNAMEqQ S208A;43;SW;ZzNAMEqQ L114A +100g;10240;1;;;;30;SW;ZzNAMEqQ S208B;43;SW;ZzNAMEqQ L117B +100g;10240;1;;;;30;SW;ZzNAMEqQ S209A;43;SW;ZzNAMEqQ L116A +100g;10240;1;;;;30;SW;ZzNAMEqQ S209B;43;SW;ZzNAMEqQ L119B +100g;10240;1;;;;30;SW;ZzNAMEqQ S210A;43;SW;ZzNAMEqQ L118A +100g;10240;1;;;;30;SW;ZzNAMEqQ S210B;43;SW;ZzNAMEqQ L121B +100g;10240;1;;;;30;SW;ZzNAMEqQ S211A;43;SW;ZzNAMEqQ L120A +100g;10240;1;;;;30;SW;ZzNAMEqQ S211B;43;SW;ZzNAMEqQ L123B +100g;10240;1;;;;30;SW;ZzNAMEqQ S212A;43;SW;ZzNAMEqQ L122A +100g;10240;1;;;;30;SW;ZzNAMEqQ S212B;43;SW;ZzNAMEqQ L101B +100g;10240;1;;;;31;SW;ZzNAMEqQ S201A;31;SW;ZzNAMEqQ L114B +100g;10240;1;;;;31;SW;ZzNAMEqQ S201B;31;SW;ZzNAMEqQ L113A +100g;10240;1;;;;31;SW;ZzNAMEqQ S202A;31;SW;ZzNAMEqQ L116B +100g;10240;1;;;;31;SW;ZzNAMEqQ S202B;31;SW;ZzNAMEqQ L115A +100g;10240;1;;;;31;SW;ZzNAMEqQ S203A;31;SW;ZzNAMEqQ L118B +100g;10240;1;;;;31;SW;ZzNAMEqQ S203B;31;SW;ZzNAMEqQ L117A +100g;10240;1;;;;31;SW;ZzNAMEqQ S204A;31;SW;ZzNAMEqQ L120B +100g;10240;1;;;;31;SW;ZzNAMEqQ S204B;31;SW;ZzNAMEqQ L119A +100g;10240;1;;;;31;SW;ZzNAMEqQ S205A;31;SW;ZzNAMEqQ L122B +100g;10240;1;;;;31;SW;ZzNAMEqQ S205B;31;SW;ZzNAMEqQ L121A +100g;10240;1;;;;31;SW;ZzNAMEqQ S206A;31;SW;ZzNAMEqQ L124B +100g;10240;1;;;;31;SW;ZzNAMEqQ S206B;31;SW;ZzNAMEqQ L123A +100g;10240;1;;;;31;SW;ZzNAMEqQ S207A;31;SW;ZzNAMEqQ L102B +100g;10240;1;;;;31;SW;ZzNAMEqQ S207B;31;SW;ZzNAMEqQ L101A +100g;10240;1;;;;31;SW;ZzNAMEqQ S208A;31;SW;ZzNAMEqQ L104B +100g;10240;1;;;;31;SW;ZzNAMEqQ S208B;31;SW;ZzNAMEqQ L103A +100g;10240;1;;;;31;SW;ZzNAMEqQ S209A;31;SW;ZzNAMEqQ L106B +100g;10240;1;;;;31;SW;ZzNAMEqQ S209B;31;SW;ZzNAMEqQ L105A +100g;10240;1;;;;31;SW;ZzNAMEqQ S210A;31;SW;ZzNAMEqQ L108B +100g;10240;1;;;;31;SW;ZzNAMEqQ S210B;31;SW;ZzNAMEqQ L107A +100g;10240;1;;;;31;SW;ZzNAMEqQ S211A;31;SW;ZzNAMEqQ L110B +100g;10240;1;;;;31;SW;ZzNAMEqQ S211B;31;SW;ZzNAMEqQ L109A +100g;10240;1;;;;31;SW;ZzNAMEqQ S212A;31;SW;ZzNAMEqQ L112B +100g;10240;1;;;;31;SW;ZzNAMEqQ S212B;31;SW;ZzNAMEqQ L111A +100g;10240;1;;;;32;SW;ZzNAMEqQ S201A;32;SW;ZzNAMEqQ L116B +100g;10240;1;;;;32;SW;ZzNAMEqQ S201B;32;SW;ZzNAMEqQ L111A +100g;10240;1;;;;32;SW;ZzNAMEqQ S202A;32;SW;ZzNAMEqQ L118B +100g;10240;1;;;;32;SW;ZzNAMEqQ S202B;32;SW;ZzNAMEqQ L113A +100g;10240;1;;;;32;SW;ZzNAMEqQ S203A;32;SW;ZzNAMEqQ L120B +100g;10240;1;;;;32;SW;ZzNAMEqQ S203B;32;SW;ZzNAMEqQ L115A +100g;10240;1;;;;32;SW;ZzNAMEqQ S204A;32;SW;ZzNAMEqQ L122B +100g;10240;1;;;;32;SW;ZzNAMEqQ S204B;32;SW;ZzNAMEqQ L117A +100g;10240;1;;;;32;SW;ZzNAMEqQ S205A;32;SW;ZzNAMEqQ L124B +100g;10240;1;;;;32;SW;ZzNAMEqQ S205B;32;SW;ZzNAMEqQ L119A +100g;10240;1;;;;32;SW;ZzNAMEqQ S206A;32;SW;ZzNAMEqQ L102B +100g;10240;1;;;;32;SW;ZzNAMEqQ S206B;32;SW;ZzNAMEqQ L121A +100g;10240;1;;;;32;SW;ZzNAMEqQ S207A;32;SW;ZzNAMEqQ L104B +100g;10240;1;;;;32;SW;ZzNAMEqQ S207B;32;SW;ZzNAMEqQ L123A +100g;10240;1;;;;32;SW;ZzNAMEqQ S208A;32;SW;ZzNAMEqQ L106B +100g;10240;1;;;;32;SW;ZzNAMEqQ S208B;32;SW;ZzNAMEqQ L101A +100g;10240;1;;;;32;SW;ZzNAMEqQ S209A;32;SW;ZzNAMEqQ L108B +100g;10240;1;;;;32;SW;ZzNAMEqQ S209B;32;SW;ZzNAMEqQ L103A +100g;10240;1;;;;32;SW;ZzNAMEqQ S210A;32;SW;ZzNAMEqQ L110B +100g;10240;1;;;;32;SW;ZzNAMEqQ S210B;32;SW;ZzNAMEqQ L105A +100g;10240;1;;;;32;SW;ZzNAMEqQ S211A;32;SW;ZzNAMEqQ L112B +100g;10240;1;;;;32;SW;ZzNAMEqQ S211B;32;SW;ZzNAMEqQ L107A +100g;10240;1;;;;32;SW;ZzNAMEqQ S212A;32;SW;ZzNAMEqQ L114B +100g;10240;1;;;;32;SW;ZzNAMEqQ S212B;32;SW;ZzNAMEqQ L109A +100g;10240;1;;;;33;SW;ZzNAMEqQ S201A;33;SW;ZzNAMEqQ L118B +100g;10240;1;;;;33;SW;ZzNAMEqQ S201B;33;SW;ZzNAMEqQ L109A +100g;10240;1;;;;33;SW;ZzNAMEqQ S202A;33;SW;ZzNAMEqQ L120B +100g;10240;1;;;;33;SW;ZzNAMEqQ S202B;33;SW;ZzNAMEqQ L111A +100g;10240;1;;;;33;SW;ZzNAMEqQ S203A;33;SW;ZzNAMEqQ L122B +100g;10240;1;;;;33;SW;ZzNAMEqQ S203B;33;SW;ZzNAMEqQ L113A +100g;10240;1;;;;33;SW;ZzNAMEqQ S204A;33;SW;ZzNAMEqQ L124B +100g;10240;1;;;;33;SW;ZzNAMEqQ S204B;33;SW;ZzNAMEqQ L115A +100g;10240;1;;;;33;SW;ZzNAMEqQ S205A;33;SW;ZzNAMEqQ L102B +100g;10240;1;;;;33;SW;ZzNAMEqQ S205B;33;SW;ZzNAMEqQ L117A +100g;10240;1;;;;33;SW;ZzNAMEqQ S206A;33;SW;ZzNAMEqQ L104B +100g;10240;1;;;;33;SW;ZzNAMEqQ S206B;33;SW;ZzNAMEqQ L119A +100g;10240;1;;;;33;SW;ZzNAMEqQ S207A;33;SW;ZzNAMEqQ L106B +100g;10240;1;;;;33;SW;ZzNAMEqQ S207B;33;SW;ZzNAMEqQ L121A +100g;10240;1;;;;33;SW;ZzNAMEqQ S208A;33;SW;ZzNAMEqQ L108B +100g;10240;1;;;;33;SW;ZzNAMEqQ S208B;33;SW;ZzNAMEqQ L123A +100g;10240;1;;;;33;SW;ZzNAMEqQ S209A;33;SW;ZzNAMEqQ L110B +100g;10240;1;;;;33;SW;ZzNAMEqQ S209B;33;SW;ZzNAMEqQ L101A +100g;10240;1;;;;33;SW;ZzNAMEqQ S210A;33;SW;ZzNAMEqQ L112B +100g;10240;1;;;;33;SW;ZzNAMEqQ S210B;33;SW;ZzNAMEqQ L103A +100g;10240;1;;;;33;SW;ZzNAMEqQ S211A;33;SW;ZzNAMEqQ L114B +100g;10240;1;;;;33;SW;ZzNAMEqQ S211B;33;SW;ZzNAMEqQ L105A +100g;10240;1;;;;33;SW;ZzNAMEqQ S212A;33;SW;ZzNAMEqQ L116B +100g;10240;1;;;;33;SW;ZzNAMEqQ S212B;33;SW;ZzNAMEqQ L107A +100g;10240;1;;;;34;SW;ZzNAMEqQ S201A;34;SW;ZzNAMEqQ L120B +100g;10240;1;;;;34;SW;ZzNAMEqQ S201B;34;SW;ZzNAMEqQ L107A +100g;10240;1;;;;34;SW;ZzNAMEqQ S202A;34;SW;ZzNAMEqQ L122B +100g;10240;1;;;;34;SW;ZzNAMEqQ S202B;34;SW;ZzNAMEqQ L109A +100g;10240;1;;;;34;SW;ZzNAMEqQ S203A;34;SW;ZzNAMEqQ L124B +100g;10240;1;;;;34;SW;ZzNAMEqQ S203B;34;SW;ZzNAMEqQ L111A +100g;10240;1;;;;34;SW;ZzNAMEqQ S204A;34;SW;ZzNAMEqQ L102B +100g;10240;1;;;;34;SW;ZzNAMEqQ S204B;34;SW;ZzNAMEqQ L113A +100g;10240;1;;;;34;SW;ZzNAMEqQ S205A;34;SW;ZzNAMEqQ L104B +100g;10240;1;;;;34;SW;ZzNAMEqQ S205B;34;SW;ZzNAMEqQ L115A +100g;10240;1;;;;34;SW;ZzNAMEqQ S206A;34;SW;ZzNAMEqQ L106B +100g;10240;1;;;;34;SW;ZzNAMEqQ S206B;34;SW;ZzNAMEqQ L117A +100g;10240;1;;;;34;SW;ZzNAMEqQ S207A;34;SW;ZzNAMEqQ L108B +100g;10240;1;;;;34;SW;ZzNAMEqQ S207B;34;SW;ZzNAMEqQ L119A +100g;10240;1;;;;34;SW;ZzNAMEqQ S208A;34;SW;ZzNAMEqQ L110B +100g;10240;1;;;;34;SW;ZzNAMEqQ S208B;34;SW;ZzNAMEqQ L121A +100g;10240;1;;;;34;SW;ZzNAMEqQ S209A;34;SW;ZzNAMEqQ L112B +100g;10240;1;;;;34;SW;ZzNAMEqQ S209B;34;SW;ZzNAMEqQ L123A +100g;10240;1;;;;34;SW;ZzNAMEqQ S210A;34;SW;ZzNAMEqQ L114B +100g;10240;1;;;;34;SW;ZzNAMEqQ S210B;34;SW;ZzNAMEqQ L101A +100g;10240;1;;;;34;SW;ZzNAMEqQ S211A;34;SW;ZzNAMEqQ L116B +100g;10240;1;;;;34;SW;ZzNAMEqQ S211B;34;SW;ZzNAMEqQ L103A +100g;10240;1;;;;34;SW;ZzNAMEqQ S212A;34;SW;ZzNAMEqQ L118B +100g;10240;1;;;;34;SW;ZzNAMEqQ S212B;34;SW;ZzNAMEqQ L105A +100g;10240;1;;;;35;SW;ZzNAMEqQ S201A;35;SW;ZzNAMEqQ L122B +100g;10240;1;;;;35;SW;ZzNAMEqQ S201B;35;SW;ZzNAMEqQ L105A +100g;10240;1;;;;35;SW;ZzNAMEqQ S202A;35;SW;ZzNAMEqQ L124B +100g;10240;1;;;;35;SW;ZzNAMEqQ S202B;35;SW;ZzNAMEqQ L107A +100g;10240;1;;;;35;SW;ZzNAMEqQ S203A;35;SW;ZzNAMEqQ L102B +100g;10240;1;;;;35;SW;ZzNAMEqQ S203B;35;SW;ZzNAMEqQ L109A +100g;10240;1;;;;35;SW;ZzNAMEqQ S204A;35;SW;ZzNAMEqQ L104B +100g;10240;1;;;;35;SW;ZzNAMEqQ S204B;35;SW;ZzNAMEqQ L111A +100g;10240;1;;;;35;SW;ZzNAMEqQ S205A;35;SW;ZzNAMEqQ L106B +100g;10240;1;;;;35;SW;ZzNAMEqQ S205B;35;SW;ZzNAMEqQ L113A +100g;10240;1;;;;35;SW;ZzNAMEqQ S206A;35;SW;ZzNAMEqQ L108B +100g;10240;1;;;;35;SW;ZzNAMEqQ S206B;35;SW;ZzNAMEqQ L115A +100g;10240;1;;;;35;SW;ZzNAMEqQ S207A;35;SW;ZzNAMEqQ L110B +100g;10240;1;;;;35;SW;ZzNAMEqQ S207B;35;SW;ZzNAMEqQ L117A +100g;10240;1;;;;35;SW;ZzNAMEqQ S208A;35;SW;ZzNAMEqQ L112B +100g;10240;1;;;;35;SW;ZzNAMEqQ S208B;35;SW;ZzNAMEqQ L119A +100g;10240;1;;;;35;SW;ZzNAMEqQ S209A;35;SW;ZzNAMEqQ L114B +100g;10240;1;;;;35;SW;ZzNAMEqQ S209B;35;SW;ZzNAMEqQ L121A +100g;10240;1;;;;35;SW;ZzNAMEqQ S210A;35;SW;ZzNAMEqQ L116B +100g;10240;1;;;;35;SW;ZzNAMEqQ S210B;35;SW;ZzNAMEqQ L123A +100g;10240;1;;;;35;SW;ZzNAMEqQ S211A;35;SW;ZzNAMEqQ L118B +100g;10240;1;;;;35;SW;ZzNAMEqQ S211B;35;SW;ZzNAMEqQ L101A +100g;10240;1;;;;35;SW;ZzNAMEqQ S212A;35;SW;ZzNAMEqQ L120B +100g;10240;1;;;;35;SW;ZzNAMEqQ S212B;35;SW;ZzNAMEqQ L103A +100g;10240;1;;;;36;SW;ZzNAMEqQ S201A;36;SW;ZzNAMEqQ L124B +100g;10240;1;;;;36;SW;ZzNAMEqQ S201B;36;SW;ZzNAMEqQ L103A +100g;10240;1;;;;36;SW;ZzNAMEqQ S202A;36;SW;ZzNAMEqQ L102B +100g;10240;1;;;;36;SW;ZzNAMEqQ S202B;36;SW;ZzNAMEqQ L105A +100g;10240;1;;;;36;SW;ZzNAMEqQ S203A;36;SW;ZzNAMEqQ L104B +100g;10240;1;;;;36;SW;ZzNAMEqQ S203B;36;SW;ZzNAMEqQ L107A +100g;10240;1;;;;36;SW;ZzNAMEqQ S204A;36;SW;ZzNAMEqQ L106B +100g;10240;1;;;;36;SW;ZzNAMEqQ S204B;36;SW;ZzNAMEqQ L109A +100g;10240;1;;;;36;SW;ZzNAMEqQ S205A;36;SW;ZzNAMEqQ L108B +100g;10240;1;;;;36;SW;ZzNAMEqQ S205B;36;SW;ZzNAMEqQ L111A +100g;10240;1;;;;36;SW;ZzNAMEqQ S206A;36;SW;ZzNAMEqQ L110B +100g;10240;1;;;;36;SW;ZzNAMEqQ S206B;36;SW;ZzNAMEqQ L113A +100g;10240;1;;;;36;SW;ZzNAMEqQ S207A;36;SW;ZzNAMEqQ L112B +100g;10240;1;;;;36;SW;ZzNAMEqQ S207B;36;SW;ZzNAMEqQ L115A +100g;10240;1;;;;36;SW;ZzNAMEqQ S208A;36;SW;ZzNAMEqQ L114B +100g;10240;1;;;;36;SW;ZzNAMEqQ S208B;36;SW;ZzNAMEqQ L117A +100g;10240;1;;;;36;SW;ZzNAMEqQ S209A;36;SW;ZzNAMEqQ L116B +100g;10240;1;;;;36;SW;ZzNAMEqQ S209B;36;SW;ZzNAMEqQ L119A +100g;10240;1;;;;36;SW;ZzNAMEqQ S210A;36;SW;ZzNAMEqQ L118B +100g;10240;1;;;;36;SW;ZzNAMEqQ S210B;36;SW;ZzNAMEqQ L121A +100g;10240;1;;;;36;SW;ZzNAMEqQ S211A;36;SW;ZzNAMEqQ L120B +100g;10240;1;;;;36;SW;ZzNAMEqQ S211B;36;SW;ZzNAMEqQ L123A +100g;10240;1;;;;36;SW;ZzNAMEqQ S212A;36;SW;ZzNAMEqQ L122B +100g;10240;1;;;;36;SW;ZzNAMEqQ S212B;36;SW;ZzNAMEqQ L101A +100g;10240;1;;;;37;SW;ZzNAMEqQ S201A;37;SW;ZzNAMEqQ L102B +100g;10240;1;;;;37;SW;ZzNAMEqQ S201B;37;SW;ZzNAMEqQ L101A +100g;10240;1;;;;37;SW;ZzNAMEqQ S202A;37;SW;ZzNAMEqQ L104B +100g;10240;1;;;;37;SW;ZzNAMEqQ S202B;37;SW;ZzNAMEqQ L103A +100g;10240;1;;;;37;SW;ZzNAMEqQ S203A;37;SW;ZzNAMEqQ L106B +100g;10240;1;;;;37;SW;ZzNAMEqQ S203B;37;SW;ZzNAMEqQ L105A +100g;10240;1;;;;37;SW;ZzNAMEqQ S204A;37;SW;ZzNAMEqQ L108B +100g;10240;1;;;;37;SW;ZzNAMEqQ S204B;37;SW;ZzNAMEqQ L107A +100g;10240;1;;;;37;SW;ZzNAMEqQ S205A;37;SW;ZzNAMEqQ L110B +100g;10240;1;;;;37;SW;ZzNAMEqQ S205B;37;SW;ZzNAMEqQ L109A +100g;10240;1;;;;37;SW;ZzNAMEqQ S206A;37;SW;ZzNAMEqQ L112B +100g;10240;1;;;;37;SW;ZzNAMEqQ S206B;37;SW;ZzNAMEqQ L111A +100g;10240;1;;;;37;SW;ZzNAMEqQ S207A;37;SW;ZzNAMEqQ L114B +100g;10240;1;;;;37;SW;ZzNAMEqQ S207B;37;SW;ZzNAMEqQ L113A +100g;10240;1;;;;37;SW;ZzNAMEqQ S208A;37;SW;ZzNAMEqQ L116B +100g;10240;1;;;;37;SW;ZzNAMEqQ S208B;37;SW;ZzNAMEqQ L115A +100g;10240;1;;;;37;SW;ZzNAMEqQ S209A;37;SW;ZzNAMEqQ L118B +100g;10240;1;;;;37;SW;ZzNAMEqQ S209B;37;SW;ZzNAMEqQ L117A +100g;10240;1;;;;37;SW;ZzNAMEqQ S210A;37;SW;ZzNAMEqQ L120B +100g;10240;1;;;;37;SW;ZzNAMEqQ S210B;37;SW;ZzNAMEqQ L119A +100g;10240;1;;;;37;SW;ZzNAMEqQ S211A;37;SW;ZzNAMEqQ L122B +100g;10240;1;;;;37;SW;ZzNAMEqQ S211B;37;SW;ZzNAMEqQ L121A +100g;10240;1;;;;37;SW;ZzNAMEqQ S212A;37;SW;ZzNAMEqQ L124B +100g;10240;1;;;;37;SW;ZzNAMEqQ S212B;37;SW;ZzNAMEqQ L123A +100g;10240;1;;;;38;SW;ZzNAMEqQ S201A;38;SW;ZzNAMEqQ L104B +100g;10240;1;;;;38;SW;ZzNAMEqQ S201B;38;SW;ZzNAMEqQ L123A +100g;10240;1;;;;38;SW;ZzNAMEqQ S202A;38;SW;ZzNAMEqQ L106B +100g;10240;1;;;;38;SW;ZzNAMEqQ S202B;38;SW;ZzNAMEqQ L101A +100g;10240;1;;;;38;SW;ZzNAMEqQ S203A;38;SW;ZzNAMEqQ L108B +100g;10240;1;;;;38;SW;ZzNAMEqQ S203B;38;SW;ZzNAMEqQ L103A +100g;10240;1;;;;38;SW;ZzNAMEqQ S204A;38;SW;ZzNAMEqQ L110B +100g;10240;1;;;;38;SW;ZzNAMEqQ S204B;38;SW;ZzNAMEqQ L105A +100g;10240;1;;;;38;SW;ZzNAMEqQ S205A;38;SW;ZzNAMEqQ L112B +100g;10240;1;;;;38;SW;ZzNAMEqQ S205B;38;SW;ZzNAMEqQ L107A +100g;10240;1;;;;38;SW;ZzNAMEqQ S206A;38;SW;ZzNAMEqQ L114B +100g;10240;1;;;;38;SW;ZzNAMEqQ S206B;38;SW;ZzNAMEqQ L109A +100g;10240;1;;;;38;SW;ZzNAMEqQ S207A;38;SW;ZzNAMEqQ L116B +100g;10240;1;;;;38;SW;ZzNAMEqQ S207B;38;SW;ZzNAMEqQ L111A +100g;10240;1;;;;38;SW;ZzNAMEqQ S208A;38;SW;ZzNAMEqQ L118B +100g;10240;1;;;;38;SW;ZzNAMEqQ S208B;38;SW;ZzNAMEqQ L113A +100g;10240;1;;;;38;SW;ZzNAMEqQ S209A;38;SW;ZzNAMEqQ L120B +100g;10240;1;;;;38;SW;ZzNAMEqQ S209B;38;SW;ZzNAMEqQ L115A +100g;10240;1;;;;38;SW;ZzNAMEqQ S210A;38;SW;ZzNAMEqQ L122B +100g;10240;1;;;;38;SW;ZzNAMEqQ S210B;38;SW;ZzNAMEqQ L117A +100g;10240;1;;;;38;SW;ZzNAMEqQ S211A;38;SW;ZzNAMEqQ L124B +100g;10240;1;;;;38;SW;ZzNAMEqQ S211B;38;SW;ZzNAMEqQ L119A +100g;10240;1;;;;38;SW;ZzNAMEqQ S212A;38;SW;ZzNAMEqQ L102B +100g;10240;1;;;;38;SW;ZzNAMEqQ S212B;38;SW;ZzNAMEqQ L121A +100g;10240;1;;;;39;SW;ZzNAMEqQ S201A;39;SW;ZzNAMEqQ L106B +100g;10240;1;;;;39;SW;ZzNAMEqQ S201B;39;SW;ZzNAMEqQ L121A +100g;10240;1;;;;39;SW;ZzNAMEqQ S202A;39;SW;ZzNAMEqQ L108B +100g;10240;1;;;;39;SW;ZzNAMEqQ S202B;39;SW;ZzNAMEqQ L123A +100g;10240;1;;;;39;SW;ZzNAMEqQ S203A;39;SW;ZzNAMEqQ L110B +100g;10240;1;;;;39;SW;ZzNAMEqQ S203B;39;SW;ZzNAMEqQ L101A +100g;10240;1;;;;39;SW;ZzNAMEqQ S204A;39;SW;ZzNAMEqQ L112B +100g;10240;1;;;;39;SW;ZzNAMEqQ S204B;39;SW;ZzNAMEqQ L103A +100g;10240;1;;;;39;SW;ZzNAMEqQ S205A;39;SW;ZzNAMEqQ L114B +100g;10240;1;;;;39;SW;ZzNAMEqQ S205B;39;SW;ZzNAMEqQ L105A +100g;10240;1;;;;39;SW;ZzNAMEqQ S206A;39;SW;ZzNAMEqQ L116B +100g;10240;1;;;;39;SW;ZzNAMEqQ S206B;39;SW;ZzNAMEqQ L107A +100g;10240;1;;;;39;SW;ZzNAMEqQ S207A;39;SW;ZzNAMEqQ L118B +100g;10240;1;;;;39;SW;ZzNAMEqQ S207B;39;SW;ZzNAMEqQ L109A +100g;10240;1;;;;39;SW;ZzNAMEqQ S208A;39;SW;ZzNAMEqQ L120B +100g;10240;1;;;;39;SW;ZzNAMEqQ S208B;39;SW;ZzNAMEqQ L111A +100g;10240;1;;;;39;SW;ZzNAMEqQ S209A;39;SW;ZzNAMEqQ L122B +100g;10240;1;;;;39;SW;ZzNAMEqQ S209B;39;SW;ZzNAMEqQ L113A +100g;10240;1;;;;39;SW;ZzNAMEqQ S210A;39;SW;ZzNAMEqQ L124B +100g;10240;1;;;;39;SW;ZzNAMEqQ S210B;39;SW;ZzNAMEqQ L115A +100g;10240;1;;;;39;SW;ZzNAMEqQ S211A;39;SW;ZzNAMEqQ L102B +100g;10240;1;;;;39;SW;ZzNAMEqQ S211B;39;SW;ZzNAMEqQ L117A +100g;10240;1;;;;39;SW;ZzNAMEqQ S212A;39;SW;ZzNAMEqQ L104B +100g;10240;1;;;;39;SW;ZzNAMEqQ S212B;39;SW;ZzNAMEqQ L119A +100g;10240;1;;;;40;SW;ZzNAMEqQ S201A;40;SW;ZzNAMEqQ L108B +100g;10240;1;;;;40;SW;ZzNAMEqQ S201B;40;SW;ZzNAMEqQ L119A +100g;10240;1;;;;40;SW;ZzNAMEqQ S202A;40;SW;ZzNAMEqQ L110B +100g;10240;1;;;;40;SW;ZzNAMEqQ S202B;40;SW;ZzNAMEqQ L121A +100g;10240;1;;;;40;SW;ZzNAMEqQ S203A;40;SW;ZzNAMEqQ L112B +100g;10240;1;;;;40;SW;ZzNAMEqQ S203B;40;SW;ZzNAMEqQ L123A +100g;10240;1;;;;40;SW;ZzNAMEqQ S204A;40;SW;ZzNAMEqQ L114B +100g;10240;1;;;;40;SW;ZzNAMEqQ S204B;40;SW;ZzNAMEqQ L101A +100g;10240;1;;;;40;SW;ZzNAMEqQ S205A;40;SW;ZzNAMEqQ L116B +100g;10240;1;;;;40;SW;ZzNAMEqQ S205B;40;SW;ZzNAMEqQ L103A +100g;10240;1;;;;40;SW;ZzNAMEqQ S206A;40;SW;ZzNAMEqQ L118B +100g;10240;1;;;;40;SW;ZzNAMEqQ S206B;40;SW;ZzNAMEqQ L105A +100g;10240;1;;;;40;SW;ZzNAMEqQ S207A;40;SW;ZzNAMEqQ L120B +100g;10240;1;;;;40;SW;ZzNAMEqQ S207B;40;SW;ZzNAMEqQ L107A +100g;10240;1;;;;40;SW;ZzNAMEqQ S208A;40;SW;ZzNAMEqQ L122B +100g;10240;1;;;;40;SW;ZzNAMEqQ S208B;40;SW;ZzNAMEqQ L109A +100g;10240;1;;;;40;SW;ZzNAMEqQ S209A;40;SW;ZzNAMEqQ L124B +100g;10240;1;;;;40;SW;ZzNAMEqQ S209B;40;SW;ZzNAMEqQ L111A +100g;10240;1;;;;40;SW;ZzNAMEqQ S210A;40;SW;ZzNAMEqQ L102B +100g;10240;1;;;;40;SW;ZzNAMEqQ S210B;40;SW;ZzNAMEqQ L113A +100g;10240;1;;;;40;SW;ZzNAMEqQ S211A;40;SW;ZzNAMEqQ L104B +100g;10240;1;;;;40;SW;ZzNAMEqQ S211B;40;SW;ZzNAMEqQ L115A +100g;10240;1;;;;40;SW;ZzNAMEqQ S212A;40;SW;ZzNAMEqQ L106B +100g;10240;1;;;;40;SW;ZzNAMEqQ S212B;40;SW;ZzNAMEqQ L117A +100g;10240;1;;;;41;SW;ZzNAMEqQ S201A;41;SW;ZzNAMEqQ L110B +100g;10240;1;;;;41;SW;ZzNAMEqQ S201B;41;SW;ZzNAMEqQ L117A +100g;10240;1;;;;41;SW;ZzNAMEqQ S202A;41;SW;ZzNAMEqQ L112B +100g;10240;1;;;;41;SW;ZzNAMEqQ S202B;41;SW;ZzNAMEqQ L119A +100g;10240;1;;;;41;SW;ZzNAMEqQ S203A;41;SW;ZzNAMEqQ L114B +100g;10240;1;;;;41;SW;ZzNAMEqQ S203B;41;SW;ZzNAMEqQ L121A +100g;10240;1;;;;41;SW;ZzNAMEqQ S204A;41;SW;ZzNAMEqQ L116B +100g;10240;1;;;;41;SW;ZzNAMEqQ S204B;41;SW;ZzNAMEqQ L123A +100g;10240;1;;;;41;SW;ZzNAMEqQ S205A;41;SW;ZzNAMEqQ L118B +100g;10240;1;;;;41;SW;ZzNAMEqQ S205B;41;SW;ZzNAMEqQ L101A +100g;10240;1;;;;41;SW;ZzNAMEqQ S206A;41;SW;ZzNAMEqQ L120B +100g;10240;1;;;;41;SW;ZzNAMEqQ S206B;41;SW;ZzNAMEqQ L103A +100g;10240;1;;;;41;SW;ZzNAMEqQ S207A;41;SW;ZzNAMEqQ L122B +100g;10240;1;;;;41;SW;ZzNAMEqQ S207B;41;SW;ZzNAMEqQ L105A +100g;10240;1;;;;41;SW;ZzNAMEqQ S208A;41;SW;ZzNAMEqQ L124B +100g;10240;1;;;;41;SW;ZzNAMEqQ S208B;41;SW;ZzNAMEqQ L107A +100g;10240;1;;;;41;SW;ZzNAMEqQ S209A;41;SW;ZzNAMEqQ L102B +100g;10240;1;;;;41;SW;ZzNAMEqQ S209B;41;SW;ZzNAMEqQ L109A +100g;10240;1;;;;41;SW;ZzNAMEqQ S210A;41;SW;ZzNAMEqQ L104B +100g;10240;1;;;;41;SW;ZzNAMEqQ S210B;41;SW;ZzNAMEqQ L111A +100g;10240;1;;;;41;SW;ZzNAMEqQ S211A;41;SW;ZzNAMEqQ L106B +100g;10240;1;;;;41;SW;ZzNAMEqQ S211B;41;SW;ZzNAMEqQ L113A +100g;10240;1;;;;41;SW;ZzNAMEqQ S212A;41;SW;ZzNAMEqQ L108B +100g;10240;1;;;;41;SW;ZzNAMEqQ S212B;41;SW;ZzNAMEqQ L115A +100g;10240;1;;;;42;SW;ZzNAMEqQ S201A;42;SW;ZzNAMEqQ L112B +100g;10240;1;;;;42;SW;ZzNAMEqQ S201B;42;SW;ZzNAMEqQ L115A +100g;10240;1;;;;42;SW;ZzNAMEqQ S202A;42;SW;ZzNAMEqQ L114B +100g;10240;1;;;;42;SW;ZzNAMEqQ S202B;42;SW;ZzNAMEqQ L117A +100g;10240;1;;;;42;SW;ZzNAMEqQ S203A;42;SW;ZzNAMEqQ L116B +100g;10240;1;;;;42;SW;ZzNAMEqQ S203B;42;SW;ZzNAMEqQ L119A +100g;10240;1;;;;42;SW;ZzNAMEqQ S204A;42;SW;ZzNAMEqQ L118B +100g;10240;1;;;;42;SW;ZzNAMEqQ S204B;42;SW;ZzNAMEqQ L121A +100g;10240;1;;;;42;SW;ZzNAMEqQ S205A;42;SW;ZzNAMEqQ L120B +100g;10240;1;;;;42;SW;ZzNAMEqQ S205B;42;SW;ZzNAMEqQ L123A +100g;10240;1;;;;42;SW;ZzNAMEqQ S206A;42;SW;ZzNAMEqQ L122B +100g;10240;1;;;;42;SW;ZzNAMEqQ S206B;42;SW;ZzNAMEqQ L101A +100g;10240;1;;;;42;SW;ZzNAMEqQ S207A;42;SW;ZzNAMEqQ L124B +100g;10240;1;;;;42;SW;ZzNAMEqQ S207B;42;SW;ZzNAMEqQ L103A +100g;10240;1;;;;42;SW;ZzNAMEqQ S208A;42;SW;ZzNAMEqQ L102B +100g;10240;1;;;;42;SW;ZzNAMEqQ S208B;42;SW;ZzNAMEqQ L105A +100g;10240;1;;;;42;SW;ZzNAMEqQ S209A;42;SW;ZzNAMEqQ L104B +100g;10240;1;;;;42;SW;ZzNAMEqQ S209B;42;SW;ZzNAMEqQ L107A +100g;10240;1;;;;42;SW;ZzNAMEqQ S210A;42;SW;ZzNAMEqQ L106B +100g;10240;1;;;;42;SW;ZzNAMEqQ S210B;42;SW;ZzNAMEqQ L109A +100g;10240;1;;;;42;SW;ZzNAMEqQ S211A;42;SW;ZzNAMEqQ L108B +100g;10240;1;;;;42;SW;ZzNAMEqQ S211B;42;SW;ZzNAMEqQ L111A +100g;10240;1;;;;42;SW;ZzNAMEqQ S212A;42;SW;ZzNAMEqQ L110B +100g;10240;1;;;;42;SW;ZzNAMEqQ S212B;42;SW;ZzNAMEqQ L113A +100g;10240;1;;;;43;SW;ZzNAMEqQ S201A;30;SW;ZzNAMEqQ L104A +100g;10240;1;;;;43;SW;ZzNAMEqQ S201B;30;SW;ZzNAMEqQ L123B +100g;10240;1;;;;43;SW;ZzNAMEqQ S202A;30;SW;ZzNAMEqQ L106A +100g;10240;1;;;;43;SW;ZzNAMEqQ S202B;30;SW;ZzNAMEqQ L101B +100g;10240;1;;;;43;SW;ZzNAMEqQ S203A;30;SW;ZzNAMEqQ L108A +100g;10240;1;;;;43;SW;ZzNAMEqQ S203B;30;SW;ZzNAMEqQ L103B +100g;10240;1;;;;43;SW;ZzNAMEqQ S204A;30;SW;ZzNAMEqQ L110A +100g;10240;1;;;;43;SW;ZzNAMEqQ S204B;30;SW;ZzNAMEqQ L105B +100g;10240;1;;;;43;SW;ZzNAMEqQ S205A;30;SW;ZzNAMEqQ L112A +100g;10240;1;;;;43;SW;ZzNAMEqQ S205B;30;SW;ZzNAMEqQ L107B +100g;10240;1;;;;43;SW;ZzNAMEqQ S206A;30;SW;ZzNAMEqQ L114A +100g;10240;1;;;;43;SW;ZzNAMEqQ S206B;30;SW;ZzNAMEqQ L109B +100g;10240;1;;;;43;SW;ZzNAMEqQ S207A;30;SW;ZzNAMEqQ L116A +100g;10240;1;;;;43;SW;ZzNAMEqQ S207B;30;SW;ZzNAMEqQ L111B +100g;10240;1;;;;43;SW;ZzNAMEqQ S208A;30;SW;ZzNAMEqQ L118A +100g;10240;1;;;;43;SW;ZzNAMEqQ S208B;30;SW;ZzNAMEqQ L113B +100g;10240;1;;;;43;SW;ZzNAMEqQ S209A;30;SW;ZzNAMEqQ L120A +100g;10240;1;;;;43;SW;ZzNAMEqQ S209B;30;SW;ZzNAMEqQ L115B +100g;10240;1;;;;43;SW;ZzNAMEqQ S210A;30;SW;ZzNAMEqQ L122A +100g;10240;1;;;;43;SW;ZzNAMEqQ S210B;30;SW;ZzNAMEqQ L117B +100g;10240;1;;;;43;SW;ZzNAMEqQ S211A;30;SW;ZzNAMEqQ L124A +100g;10240;1;;;;43;SW;ZzNAMEqQ S211B;30;SW;ZzNAMEqQ L119B +100g;10240;1;;;;43;SW;ZzNAMEqQ S212A;30;SW;ZzNAMEqQ L102A +100g;10240;1;;;;43;SW;ZzNAMEqQ S212B;30;SW;ZzNAMEqQ L121B +100g;10240;1;;;;44;SW;ZzNAMEqQ S201A;29;SW;ZzNAMEqQ L106A +100g;10240;1;;;;44;SW;ZzNAMEqQ S201B;29;SW;ZzNAMEqQ L121B +100g;10240;1;;;;44;SW;ZzNAMEqQ S202A;29;SW;ZzNAMEqQ L108A +100g;10240;1;;;;44;SW;ZzNAMEqQ S202B;29;SW;ZzNAMEqQ L123B +100g;10240;1;;;;44;SW;ZzNAMEqQ S203A;29;SW;ZzNAMEqQ L110A +100g;10240;1;;;;44;SW;ZzNAMEqQ S203B;29;SW;ZzNAMEqQ L101B +100g;10240;1;;;;44;SW;ZzNAMEqQ S204A;29;SW;ZzNAMEqQ L112A +100g;10240;1;;;;44;SW;ZzNAMEqQ S204B;29;SW;ZzNAMEqQ L103B +100g;10240;1;;;;44;SW;ZzNAMEqQ S205A;29;SW;ZzNAMEqQ L114A +100g;10240;1;;;;44;SW;ZzNAMEqQ S205B;29;SW;ZzNAMEqQ L105B +100g;10240;1;;;;44;SW;ZzNAMEqQ S206A;29;SW;ZzNAMEqQ L116A +100g;10240;1;;;;44;SW;ZzNAMEqQ S206B;29;SW;ZzNAMEqQ L107B +100g;10240;1;;;;44;SW;ZzNAMEqQ S207A;29;SW;ZzNAMEqQ L118A +100g;10240;1;;;;44;SW;ZzNAMEqQ S207B;29;SW;ZzNAMEqQ L109B +100g;10240;1;;;;44;SW;ZzNAMEqQ S208A;29;SW;ZzNAMEqQ L120A +100g;10240;1;;;;44;SW;ZzNAMEqQ S208B;29;SW;ZzNAMEqQ L111B +100g;10240;1;;;;44;SW;ZzNAMEqQ S209A;29;SW;ZzNAMEqQ L122A +100g;10240;1;;;;44;SW;ZzNAMEqQ S209B;29;SW;ZzNAMEqQ L113B +100g;10240;1;;;;44;SW;ZzNAMEqQ S210A;29;SW;ZzNAMEqQ L124A +100g;10240;1;;;;44;SW;ZzNAMEqQ S210B;29;SW;ZzNAMEqQ L115B +100g;10240;1;;;;44;SW;ZzNAMEqQ S211A;29;SW;ZzNAMEqQ L102A +100g;10240;1;;;;44;SW;ZzNAMEqQ S211B;29;SW;ZzNAMEqQ L117B +100g;10240;1;;;;44;SW;ZzNAMEqQ S212A;29;SW;ZzNAMEqQ L104A +100g;10240;1;;;;44;SW;ZzNAMEqQ S212B;29;SW;ZzNAMEqQ L119B +100g;10240;1;;;;45;SW;ZzNAMEqQ S201A;28;SW;ZzNAMEqQ L108A +100g;10240;1;;;;45;SW;ZzNAMEqQ S201B;28;SW;ZzNAMEqQ L119B +100g;10240;1;;;;45;SW;ZzNAMEqQ S202A;28;SW;ZzNAMEqQ L110A +100g;10240;1;;;;45;SW;ZzNAMEqQ S202B;28;SW;ZzNAMEqQ L121B +100g;10240;1;;;;45;SW;ZzNAMEqQ S203A;28;SW;ZzNAMEqQ L112A +100g;10240;1;;;;45;SW;ZzNAMEqQ S203B;28;SW;ZzNAMEqQ L123B +100g;10240;1;;;;45;SW;ZzNAMEqQ S204A;28;SW;ZzNAMEqQ L114A +100g;10240;1;;;;45;SW;ZzNAMEqQ S204B;28;SW;ZzNAMEqQ L101B +100g;10240;1;;;;45;SW;ZzNAMEqQ S205A;28;SW;ZzNAMEqQ L116A +100g;10240;1;;;;45;SW;ZzNAMEqQ S205B;28;SW;ZzNAMEqQ L103B +100g;10240;1;;;;45;SW;ZzNAMEqQ S206A;28;SW;ZzNAMEqQ L118A +100g;10240;1;;;;45;SW;ZzNAMEqQ S206B;28;SW;ZzNAMEqQ L105B +100g;10240;1;;;;45;SW;ZzNAMEqQ S207A;28;SW;ZzNAMEqQ L120A +100g;10240;1;;;;45;SW;ZzNAMEqQ S207B;28;SW;ZzNAMEqQ L107B +100g;10240;1;;;;45;SW;ZzNAMEqQ S208A;28;SW;ZzNAMEqQ L122A +100g;10240;1;;;;45;SW;ZzNAMEqQ S208B;28;SW;ZzNAMEqQ L109B +100g;10240;1;;;;45;SW;ZzNAMEqQ S209A;28;SW;ZzNAMEqQ L124A +100g;10240;1;;;;45;SW;ZzNAMEqQ S209B;28;SW;ZzNAMEqQ L111B +100g;10240;1;;;;45;SW;ZzNAMEqQ S210A;28;SW;ZzNAMEqQ L102A +100g;10240;1;;;;45;SW;ZzNAMEqQ S210B;28;SW;ZzNAMEqQ L113B +100g;10240;1;;;;45;SW;ZzNAMEqQ S211A;28;SW;ZzNAMEqQ L104A +100g;10240;1;;;;45;SW;ZzNAMEqQ S211B;28;SW;ZzNAMEqQ L115B +100g;10240;1;;;;45;SW;ZzNAMEqQ S212A;28;SW;ZzNAMEqQ L106A +100g;10240;1;;;;45;SW;ZzNAMEqQ S212B;28;SW;ZzNAMEqQ L117B +100g;10240;1;;;;46;SW;ZzNAMEqQ S201A;27;SW;ZzNAMEqQ L110A +100g;10240;1;;;;46;SW;ZzNAMEqQ S201B;27;SW;ZzNAMEqQ L117B +100g;10240;1;;;;46;SW;ZzNAMEqQ S202A;27;SW;ZzNAMEqQ L112A +100g;10240;1;;;;46;SW;ZzNAMEqQ S202B;27;SW;ZzNAMEqQ L119B +100g;10240;1;;;;46;SW;ZzNAMEqQ S203A;27;SW;ZzNAMEqQ L114A +100g;10240;1;;;;46;SW;ZzNAMEqQ S203B;27;SW;ZzNAMEqQ L121B +100g;10240;1;;;;46;SW;ZzNAMEqQ S204A;27;SW;ZzNAMEqQ L116A +100g;10240;1;;;;46;SW;ZzNAMEqQ S204B;27;SW;ZzNAMEqQ L123B +100g;10240;1;;;;46;SW;ZzNAMEqQ S205A;27;SW;ZzNAMEqQ L118A +100g;10240;1;;;;46;SW;ZzNAMEqQ S205B;27;SW;ZzNAMEqQ L101B +100g;10240;1;;;;46;SW;ZzNAMEqQ S206A;27;SW;ZzNAMEqQ L120A +100g;10240;1;;;;46;SW;ZzNAMEqQ S206B;27;SW;ZzNAMEqQ L103B +100g;10240;1;;;;46;SW;ZzNAMEqQ S207A;27;SW;ZzNAMEqQ L122A +100g;10240;1;;;;46;SW;ZzNAMEqQ S207B;27;SW;ZzNAMEqQ L105B +100g;10240;1;;;;46;SW;ZzNAMEqQ S208A;27;SW;ZzNAMEqQ L124A +100g;10240;1;;;;46;SW;ZzNAMEqQ S208B;27;SW;ZzNAMEqQ L107B +100g;10240;1;;;;46;SW;ZzNAMEqQ S209A;27;SW;ZzNAMEqQ L102A +100g;10240;1;;;;46;SW;ZzNAMEqQ S209B;27;SW;ZzNAMEqQ L109B +100g;10240;1;;;;46;SW;ZzNAMEqQ S210A;27;SW;ZzNAMEqQ L104A +100g;10240;1;;;;46;SW;ZzNAMEqQ S210B;27;SW;ZzNAMEqQ L111B +100g;10240;1;;;;46;SW;ZzNAMEqQ S211A;27;SW;ZzNAMEqQ L106A +100g;10240;1;;;;46;SW;ZzNAMEqQ S211B;27;SW;ZzNAMEqQ L113B +100g;10240;1;;;;46;SW;ZzNAMEqQ S212A;27;SW;ZzNAMEqQ L108A +100g;10240;1;;;;46;SW;ZzNAMEqQ S212B;27;SW;ZzNAMEqQ L115B +100g;10240;1;;;;47;SW;ZzNAMEqQ S201A;26;SW;ZzNAMEqQ L112A +100g;10240;1;;;;47;SW;ZzNAMEqQ S201B;26;SW;ZzNAMEqQ L115B +100g;10240;1;;;;47;SW;ZzNAMEqQ S202A;26;SW;ZzNAMEqQ L114A +100g;10240;1;;;;47;SW;ZzNAMEqQ S202B;26;SW;ZzNAMEqQ L117B +100g;10240;1;;;;47;SW;ZzNAMEqQ S203A;26;SW;ZzNAMEqQ L116A +100g;10240;1;;;;47;SW;ZzNAMEqQ S203B;26;SW;ZzNAMEqQ L119B +100g;10240;1;;;;47;SW;ZzNAMEqQ S204A;26;SW;ZzNAMEqQ L118A +100g;10240;1;;;;47;SW;ZzNAMEqQ S204B;26;SW;ZzNAMEqQ L121B +100g;10240;1;;;;47;SW;ZzNAMEqQ S205A;26;SW;ZzNAMEqQ L120A +100g;10240;1;;;;47;SW;ZzNAMEqQ S205B;26;SW;ZzNAMEqQ L123B +100g;10240;1;;;;47;SW;ZzNAMEqQ S206A;26;SW;ZzNAMEqQ L122A +100g;10240;1;;;;47;SW;ZzNAMEqQ S206B;26;SW;ZzNAMEqQ L101B +100g;10240;1;;;;47;SW;ZzNAMEqQ S207A;26;SW;ZzNAMEqQ L124A +100g;10240;1;;;;47;SW;ZzNAMEqQ S207B;26;SW;ZzNAMEqQ L103B +100g;10240;1;;;;47;SW;ZzNAMEqQ S208A;26;SW;ZzNAMEqQ L102A +100g;10240;1;;;;47;SW;ZzNAMEqQ S208B;26;SW;ZzNAMEqQ L105B +100g;10240;1;;;;47;SW;ZzNAMEqQ S209A;26;SW;ZzNAMEqQ L104A +100g;10240;1;;;;47;SW;ZzNAMEqQ S209B;26;SW;ZzNAMEqQ L107B +100g;10240;1;;;;47;SW;ZzNAMEqQ S210A;26;SW;ZzNAMEqQ L106A +100g;10240;1;;;;47;SW;ZzNAMEqQ S210B;26;SW;ZzNAMEqQ L109B +100g;10240;1;;;;47;SW;ZzNAMEqQ S211A;26;SW;ZzNAMEqQ L108A +100g;10240;1;;;;47;SW;ZzNAMEqQ S211B;26;SW;ZzNAMEqQ L111B +100g;10240;1;;;;47;SW;ZzNAMEqQ S212A;26;SW;ZzNAMEqQ L110A +100g;10240;1;;;;47;SW;ZzNAMEqQ S212B;26;SW;ZzNAMEqQ L113B +100g;10240;1;;;;48;SW;ZzNAMEqQ S201A;25;SW;ZzNAMEqQ L102A +100g;10240;1;;;;48;SW;ZzNAMEqQ S201B;25;SW;ZzNAMEqQ L113B +100g;10240;1;;;;48;SW;ZzNAMEqQ S202A;25;SW;ZzNAMEqQ L104A +100g;10240;1;;;;48;SW;ZzNAMEqQ S202B;25;SW;ZzNAMEqQ L115B +100g;10240;1;;;;48;SW;ZzNAMEqQ S203A;25;SW;ZzNAMEqQ L106A +100g;10240;1;;;;48;SW;ZzNAMEqQ S203B;25;SW;ZzNAMEqQ L117B +100g;10240;1;;;;48;SW;ZzNAMEqQ S204A;25;SW;ZzNAMEqQ L108A +100g;10240;1;;;;48;SW;ZzNAMEqQ S204B;25;SW;ZzNAMEqQ L119B +100g;10240;1;;;;48;SW;ZzNAMEqQ S205A;25;SW;ZzNAMEqQ L110A +100g;10240;1;;;;48;SW;ZzNAMEqQ S205B;25;SW;ZzNAMEqQ L121B +100g;10240;1;;;;48;SW;ZzNAMEqQ S206A;25;SW;ZzNAMEqQ L112A +100g;10240;1;;;;48;SW;ZzNAMEqQ S206B;25;SW;ZzNAMEqQ L123B +100g;10240;1;;;;48;SW;ZzNAMEqQ S207A;25;SW;ZzNAMEqQ L114A +100g;10240;1;;;;48;SW;ZzNAMEqQ S207B;25;SW;ZzNAMEqQ L101B +100g;10240;1;;;;48;SW;ZzNAMEqQ S208A;25;SW;ZzNAMEqQ L116A +100g;10240;1;;;;48;SW;ZzNAMEqQ S208B;25;SW;ZzNAMEqQ L103B +100g;10240;1;;;;48;SW;ZzNAMEqQ S209A;25;SW;ZzNAMEqQ L118A +100g;10240;1;;;;48;SW;ZzNAMEqQ S209B;25;SW;ZzNAMEqQ L105B +100g;10240;1;;;;48;SW;ZzNAMEqQ S210A;25;SW;ZzNAMEqQ L120A +100g;10240;1;;;;48;SW;ZzNAMEqQ S210B;25;SW;ZzNAMEqQ L107B +100g;10240;1;;;;48;SW;ZzNAMEqQ S211A;25;SW;ZzNAMEqQ L122A +100g;10240;1;;;;48;SW;ZzNAMEqQ S211B;25;SW;ZzNAMEqQ L109B +100g;10240;1;;;;48;SW;ZzNAMEqQ S212A;25;SW;ZzNAMEqQ L124A +100g;10240;1;;;;48;SW;ZzNAMEqQ S212B;25;SW;ZzNAMEqQ L111B diff --git a/IbaTools/opaxlattopology/minimal_topology.xlsx b/IbaTools/opaxlattopology/minimal_topology.xlsx new file mode 100755 index 0000000..88c40b5 Binary files /dev/null and b/IbaTools/opaxlattopology/minimal_topology.xlsx differ diff --git a/IbaTools/opaxlattopology/opaxlattopology.sh b/IbaTools/opaxlattopology/opaxlattopology.sh new file mode 100755 index 0000000..6c2b670 --- /dev/null +++ b/IbaTools/opaxlattopology/opaxlattopology.sh @@ -0,0 +1,2083 @@ +#!/bin/bash +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2018, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: @(#) ./fastfabric/opaxlattopology 10_0_0_0_135 [09/08/14 23:46] + +# Topology script to translate the CSV form (topology.csv) of a +# standard-format topology spread sheet for a fabric to one or more topology +# XML files (topology.0:0.xml) at the specified levels (top-level, rack group, +# rack, edge switch). This script operates from the fabric directory and +# populates it. + +# The following topology directories and files are generated: +# FILE_LINKSUM - Host-to-Edge, Edge-to-Core, Host-to-Core links; +# includes cable data +# FILE_LINKSUM_NOCORE - No Edge-to-Core or Host-to-Core links; +# includes cable data +# FILE_LINKSUM_NOCABLE - Leaf-to-Spine links, no cable data +# FILE_NODEFIS - Host FIs, includes NodeDetails +# FILE_NODESWITCHES - Edge, Leaf and Spine switches +# FILE_NODECHASSIS - Core switches +# FILE_NODESM - Nodes running SM +# FILE_NODELEAVES - Leaf switches +# FILE_TOPOLOGY_OUT - Topology: FILE_LINKSUM + FILE_LINKSUM_NOCABLE + +# FILE_NODEFIS + FILE_NODESWITCHES +# OUT_FOLDER - Folder to redirect the topology files +# FILE_HOSTS - 'hosts' file +# FILE_CHASSIS - 'chassis' file + +# User topology CSV format: +# Lines 1 - x ignored +# Line y header line 1 (ignored) +# Line n header line 2 +# Lines n+1 - m topology CSV +# Line m+1 blank +# Lines m+2 - z core specification(s) + +# Links Fields: +# Minimal Fields Required +# Source Rack Group: 01 +# Source Rack: 02 +# Source Name: 03 +# Source Name-2: 04 +# Source Port: 05 +# Source Type: 06 +# Dest Rack Group: 07 +# Dest Rack: 08 +# Dest Name: 09 +# Dest Name-2: 10 +# Dest Port: 11 +# Dest Type: 12 +# Cable Label: 13 +# Cable Length: 14 +# Cable Details: 15 + +# Additional Fields (Optional) +# Link Rate: 16 +# Link MTU: 17 +# Link Details: 18 +# Node Fields: 19 and above +# Node/PortNum Field Calculated + +# Core specifications (same line): +# Core Name:X +# Core Size:X (288 or 1152) +# Core Group:X +# Core Rack:X +# Core Full:X (0 or 1) + +FIELD_COUNT=18 + +## Defines: +XML_GENERATE="/usr/sbin/opaxmlgenerate" +XML_INDENT="/usr/sbin/opaxmlindent" +FILE_TOPOLOGY_LINKS="topology.csv" +FILE_LINKSUM_SWD06="/usr/share/opa/samples/linksum_swd06.csv" +FILE_LINKSUM_SWD24="/usr/share/opa/samples/linksum_swd24.csv" +FILE_LINKSUM="linksum.csv" +FILE_LINKSUM_NOCORE="linksum_nocore.csv" +FILE_LINKSUM_NOCABLE="linksum_nocable.csv" +FILE_NODEFIS="nodefis.csv" +FILE_NODESWITCHES="nodeswitches.csv" +FILE_NODELEAVES="nodeleaves.csv" +FILE_NODECHASSIS="nodechassis.csv" +FILE_NODESM="nodesm.csv" +FILE_CHASSIS="chassis" +FILE_HOSTS="hosts" +FILE_TOPOLOGY_OUT="topology.0:0.xml" +OUT_FOLDER="" +FILE_RESERVE="file_reserve" +FILE_TEMP=$(mktemp "opaxlattopo-1.XXXX") +FILE_TEMP2=$(mktemp "opaxlattopo-2.XXXX") +FILE_TOPOLOGY_TEMP="topology_temp.xml" +# Note: there are no real limits on numbers of groups, racks or switches; +# these defines simply allow error messages before too much thrashing +# takes place in cases where FILE_TOPOLOGY_LINKS has bad data +MAX_GROUPS=21 +MAX_RACKS=501 +MAX_SWITCHES=20001 +OUTPUT_SWITCHES=1 +OUTPUT_RACKS=2 +OUTPUT_GROUPS=4 +OUTPUT_EDGE_LEAF_LINKS=8 +OUTPUT_SPINE_LEAF_LINKS=16 +NODETYPE_HFI="FI" +NODETYPE_EDGE="SW" +NODETYPE_LEAF="CL" +NODETYPE_SPINE="CS" +NODETYPE_ENDPOINT="EN" +NODETYPE_SWITCH="SW" +DUMMY_CORE_NAME="ZzNAMEqQ" +CORE_GROUP="Core Group:" +CORE_RACK="Core Rack:" +CORE_NAME="Core Name:" +CORE_SIZE="Core Size:" +CORE_FULL="Core Full:" +CAT_CHAR_CORE=" " +HFI_SUFFIX_REGEX="hfi[1-9]_[0-9]+$" +HOST_HFI_REGEX="^[a-zA-Z0-9_-]+[ ]hfi[1-9]_[0-9]+$" +CAT_CHAR=" " + +MTU_SW_SW_DEFAULT=${MTU_SW_SW:-10240} +MTU_SW_HFI_DEFAULT=${MTU_SW_HFI:-10240} + +## Global variables: +hfi_suffix="hfi1_0" + +# Parsing tokens: +declare -a t=() + +t_srcgroup="" +t_srcrack="" +t_srcname="" +t_srcname2="" +t_srcport="" +t_srctype="" +t_dstgroup="" +t_dstrack="" +t_dstname="" +t_dstname2="" +t_dstport="" +t_dsttype="" +t_cablelabel="" +t_cablelength="" +t_cabledetails="" +t_linkdetails="" +output_section="all" + +# Output CSV values: +rate="" +internal="" +nodedesc1="" +nodedetails1="" +nodetype1="" +nodedesc2="" +nodedetails2="" +nodetype2="" +link="" + +# Operating variables: +cts_parse=0 +ix=0 +n_detail=0 +fl_output_edge_leaf=1 +fl_output_spine_leaf=1 +n_verbose=2 +indent=4 +fl_clean=1 +ix_srcgroup=0 +ix_srcrack=0 +ix_srcswitch=0 +ix_dstgroup=0 +ix_dstrack=0 +ix_dstswitch=0 +core_group="" +core_rack="" +core_name="" +core_size= +core_full= +rack="" +switch="" +leaves="" +additional_fields=0 +portnum_field=0 +ix_line=0 +group_cnt=1 +rack_cnt=1 + +# Check Bash Version for hash tables +if (( "${BASH_VERSINFO[0]}" < 4 )) +then + echo "opaxlattopology: At least bash-4.0 is required to run this script" >&2 + exit 1 +fi + +# Hash table: +declare -A core_name_size +declare -A core_name_rack +declare -A core_name_group + +# Arrays +tb_group[0]="" +tb_rack[0]="" +tb_switch[0]="" +core=() +partially_populated_core=() +spine_array=() +leaf_array=() +external_leaves=() +expected_sm=() +hfi=() + +# Debug variables: +debug_0= +debug_1= +debug_2= +debug_3= +debug_4= +debug_5= +debug_6= +debug_7= +#echo "DEBUG-x.y: 0:$debug_0: 1:$debug_1: 2:$debug_2: 3:$debug_3: 4:$debug_4: 5:$debug_5: 6:$debug_6: 7:$debug_7:" + +array_contains() { + local array=("${!1}") + local seeking=$2 + local found=1 + for element in "${array[@]}"; do + if [[ "$element" == "$seeking" ]] ; then + found=0 + break + fi + done + return $found +} + +misc_params="" + +declare -A misc_sw_table +declare -A misc_fi_table +declare -A sw_portlist_table + +declare -a misc_param_index + +remove_file() { + if [ -f $1 ]; then + rm -f $1 + fi +} + +clean_tempfiles() { + if [ $fl_clean == 1 ] + then + remove_file "$FILE_TEMP" + remove_file "$FILE_TEMP2" + remove_file "$FILE_LINKSUM" + remove_file "$FILE_LINKSUM_NOCORE" + remove_file "$FILE_LINKSUM_NOCABLE" + remove_file "$FILE_NODEFIS" + remove_file "$FILE_NODESWITCHES" + remove_file "$FILE_NODELEAVES" + remove_file "$FILE_NODECHASSIS" + remove_file "$FILE_NODESM" + fi +} + +topology_file_cleanup() { + if [ -f $FILE_TOPOLOGY_TEMP ]; then + remove_file "$FILE_TOPOLOGY_TEMP" + fi +} + +trap 'clean_tempfiles; topology_file_cleanup; exit 1' SIGINT SIGHUP SIGTERM +trap 'clean_tempfiles' EXIT + +## Local functions: +functout= + +# Output usage information +usage_full() +{ + echo "Usage: opaxlattopology [-d level] [-v level] [-i level] [-K]" >&2 + echo " [-s hfi_suffix] [source [dest]]" >&2 + echo " or" >&2 + echo " opaxlattopology --help" >&2 + echo " --help - produce full help text" >&2 + echo " -d level - output detail level (default 0)" >&2 + echo " values are additive" >&2 + echo " 1 - edge switch topology files" >&2 + echo " 2 - rack topology files" >&2 + echo " 4 - rack group topology files" >&2 +# TBD - these options are disabled for now +# echo " 8 - DO NOT output edge-to-leaf links" >&2 +# echo " 16 - DO NOT output spine-to-leaf links" >&2 + echo " -v level - verbose level (0-8, default 2)" >&2 + echo " 0 - no output" >&2 + echo " 1 - progress output" >&2 + echo " 2 - reserved" >&2 + echo " 4 - time stamps" >&2 + echo " 8 - reserved" >&2 + echo " -i level - output indent level (default 4)" >&2 + echo " -K - DO NOT clean temporary files" >&2 + echo " -s hfi_suffix - Used on Multi-Rail or Multi-Plane fabrics" >&2 + echo " Can be used to override the default hfi1_0." >&2 + echo " For Multi-Plane fabric, use the tool multiple" >&2 + echo " times with different hfi-suffix. For Multi-Rail" >&2 + echo " specify HostName as \"HostName HfiName\" in spreadsheet" >&2 + echo " -o report - report type for output; by default, all the sections" >&2 + echo " are generated" >&2 + echo " Report Types:" >&2 + echo " brnodes - Creates section xml for the csv input" >&2 + echo " links - Creates section xml for the csv input" >&2 + echo " source - source csv file; default is topology.csv" >&2 + echo " dest - output xml file; default is topology.0:0.xml" >&2 + echo " default output file name may vary if used with -s option." >&2 + echo " It can also be used to specify destinstion folder" >&2 + echo "" >&2 + echo " The following environment variables allow user-specified MTU" >&2 + echo " MTU_SW_SW - If set will override default MTU on switch<->switch links" >&2 + echo " (default is 10240)" >&2 + echo " MTU_SW_HFI - If set will override default MTU on switch<->HFI links" >&2 + echo " (default is 10240)" >&2 + exit $1 +} # End of usage_full() + +if [ x"$1" = "x--help" ] +then + usage_full "0" +fi + +# Convert general node types to standard node types +# Inputs: +# $1 = general node type +# +# Outputs: +# Standard node type +cvt_nodetype() +{ + + local nodetype=$(echo "$1" | awk '{print toupper($0)}') + case $nodetype in + $NODETYPE_HFI) + echo "$NODETYPE_HFI" + ;; + $NODETYPE_EDGE) + echo "$NODETYPE_SWITCH" + ;; + $NODETYPE_LEAF) + echo "$NODETYPE_SWITCH" + ;; + $NODETYPE_SPINE) + echo "$NODETYPE_SWITCH" + ;; + $NODETYPE_ENDPOINT) + echo "$NODETYPE_ENDPOINT" + ;; + *) + echo "" + ;; + esac + +} # End of cvt_nodetype() + +# Display progress information (to STDOUT) +# Inputs: +# $1 - progress string +# +# Outputs: +# none +display_progress() +{ + if [ $n_verbose -ge 1 ] + then + echo "$1" + if [ $n_verbose -ge 4 ] + then + echo " "`date` + fi + fi +} # End of display_progress() + +# Generate directory-level FILE_TOPOLOGY_OUT file from directory-level +# CSV files; consolidate directory-level CSV files. +# Inputs: +# $1 = 1 - Use FILE_LINKSUM +# 0 - Use FILE_LINKSUM_NOCORE +# $2 = 1 - Use FILE_LINKSUM_NOCABLE +# 0 - Do not use FILE_LINKSUM_NOCABLE +# FILE_LINKSUM +# FILE_LINKSUM_NOCORE (optional) +# FILE_LINKSUM_NOCABLE (optional) +# FILE_NODEFIS +# FILE_NODESWITCHES +# FILE_NODECHASSIS +# FILE_NODESM +# +# Outputs: +# FILE_TOPOLOGY_OUT +# FILE_HOSTS +# FILE_CHASSIS +gen_topology() +{ + local args="" + if [ -f $FILE_LINKSUM ] + then + remove_file "$FILE_TEMP" + mv $FILE_LINKSUM $FILE_TEMP + sort -u $FILE_TEMP > $FILE_LINKSUM + fi + if [ -f $FILE_LINKSUM_NOCORE ] + then + remove_file "$FILE_TEMP" + mv $FILE_LINKSUM_NOCORE $FILE_TEMP + sort -u $FILE_TEMP > $FILE_LINKSUM_NOCORE + fi + if [ -f $FILE_LINKSUM_NOCABLE ] + then + remove_file "$FILE_TEMP" + mv $FILE_LINKSUM_NOCABLE $FILE_TEMP + sort -u $FILE_TEMP > $FILE_LINKSUM_NOCABLE + fi + + if [ -f $FILE_NODEFIS ] + then + remove_file "$FILE_HOSTS" + remove_file "$FILE_TEMP" + remove_file "$FILE_TEMP2" + mv $FILE_NODEFIS $FILE_TEMP + sort -u $FILE_TEMP > $FILE_TEMP2 + + # Read list of FI node data + while IFS='' read -r node_in + do + # Extract node detail content from FI node data + details="" + if [[ "$node_in" =~ ";" ]]; then + details=`echo "$node_in" | cut -d ';' -f 2 -` + fi + # Use node desc to lookup optional XML data (misc entries) + node=${node_in/;*/} + lookup_misc_table_entry "$node" "$NODETYPE_HFI" args + # opaxmlgenerate is pedantic about the exact number of delimiters ';' + if [ "$args" == "" ]; then + echo "$node;$details" >> $FILE_NODEFIS + else + echo "$node;$details;$args" >> $FILE_NODEFIS + fi + done < $FILE_TEMP2 + cut -d ';' -f 1 $FILE_NODEFIS | sed -e "s/$CAT_CHAR$HFI_SUFFIX_REGEX//" > $FILE_HOSTS + fi + + if [ -f $FILE_NODESWITCHES ] + then + remove_file "$FILE_TEMP" + mv $FILE_NODESWITCHES $FILE_TEMP + sort -u $FILE_TEMP > $FILE_TEMP2 + + # Read list of SW node data + while IFS='' read -r node_in + do + # Use node desc to lookup optional XML data (misc entries) + node=${node_in/;*/} + + # Destination Node Descriptions might be blank if it is an endpoint (ignore them) + if [[ "${node//[[:space:]]/}" == "" ]]; then + continue + fi + + lookup_misc_table_entry "$node" "$NODETYPE_EDGE" args + + if [ "$args" != "" ]; then + echo "$node;$args" >> $FILE_NODESWITCHES + else + echo "$node" >> $FILE_NODESWITCHES + fi + done < $FILE_TEMP2 + fi + if [ -f $FILE_NODECHASSIS ] + then + remove_file "$FILE_CHASSIS" + remove_file "$FILE_TEMP" + mv $FILE_NODECHASSIS $FILE_TEMP + sort -u $FILE_TEMP > $FILE_NODECHASSIS + cp -p $FILE_NODECHASSIS $FILE_CHASSIS + fi + if [ -f $FILE_NODESM ] + then + remove_file "$FILE_TEMP" + mv $FILE_NODESM $FILE_TEMP + sort -u $FILE_TEMP > $FILE_NODESM + fi + + remove_file "$FILE_TOPOLOGY_TEMP" + echo '' >> $FILE_TOPOLOGY_TEMP + echo "" >> $FILE_TOPOLOGY_TEMP + + if [ "$output_section" == "all" ] || [ "$output_section" == "links" ] ; then + # Generate LinkSummary section + echo "" >> $FILE_TOPOLOGY_TEMP + if [ -s $FILE_LINKSUM -a $1 == 1 ] + then + $XML_GENERATE -X $FILE_LINKSUM -d \; -i 2 -h Link -g Rate -g MTU -g LinkDetails -g Internal -h Cable -g CableLength -g CableLabel -g CableDetails -e Cable -h Port -g PortNum -g NodeType -g NodeDesc -e Port -h Port -g PortNum -g NodeType -g NodeDesc -e Port -e Link >> $FILE_TOPOLOGY_TEMP + elif [ -s $FILE_LINKSUM_NOCORE -a $1 == 0 ] + then + $XML_GENERATE -X $FILE_LINKSUM_NOCORE -d \; -i 2 -h Link -g Rate -g MTU -g LinkDetails -g Internal -h Cable -g CableLength -g CableLabel -g CableDetails -e Cable -h Port -g PortNum -g NodeType -g NodeDesc -e Port -h Port -g PortNum -g NodeType -g NodeDesc -e Port -e Link >> $FILE_TOPOLOGY_TEMP + fi + + if [ -s $FILE_LINKSUM_NOCABLE -a $2 == 1 ] + then + # Note: header not needed because cable data is null + $XML_GENERATE -X $FILE_LINKSUM_NOCABLE -d \; -i 2 -h Link -g Rate -g MTU -g LinkDetails -g Internal -g CableLength -g CableLabel -g CableDetails -h Port -g PortNum -g NodeType -g NodeDesc -e Port -h Port -g PortNum -g NodeType -g NodeDesc -e Port -e Link >> $FILE_TOPOLOGY_TEMP + fi + echo "" >> $FILE_TOPOLOGY_TEMP + fi + + if [ "$output_section" == "all" ] || [ "$output_section" == "brnodes" ] ; then + # Generate Nodes/FIs section + echo "" >> $FILE_TOPOLOGY_TEMP + echo "" >> $FILE_TOPOLOGY_TEMP + if [ -s $FILE_NODEFIS ] + then + $XML_GENERATE -X $FILE_NODEFIS -d \; -i 2 -h Node -g NodeDesc -g NodeDetails $misc_params -e Node >> $FILE_TOPOLOGY_TEMP + fi + echo "" >> $FILE_TOPOLOGY_TEMP + + # Generate Switch Section + generate_switch_section + + # Generate SM section + echo "" >> $FILE_TOPOLOGY_TEMP + if [ -s $FILE_NODESM ] + then + $XML_GENERATE -X $FILE_NODESM -i 2 -h SM -g NodeDesc -g PortNum -e SM >> $FILE_TOPOLOGY_TEMP + fi + echo "" >> $FILE_TOPOLOGY_TEMP + echo "" >> $FILE_TOPOLOGY_TEMP + fi + + echo "" >> $FILE_TOPOLOGY_TEMP + + # trim leading and trailing whitespace from tag contents and add indent + $XML_INDENT -t $FILE_TOPOLOGY_TEMP -i $indent > $FILE_TEMP 2>/dev/null + cat $FILE_TEMP > $FILE_TOPOLOGY_OUT + + # Clean temporary files + clean_tempfiles + topology_file_cleanup +} # End of gen_topology + +# Append to LINKSUM_NOCABLE file using parameter as input. +# Inputs: +# $1 = FILE_LINKSUM_SWD06 or FILE_LINKSUM_SWD24 +# Outputs: FILE_LINKSUM_NOCABLE +generate_linksum_nocable() +{ + if ! [ -z "$1" ] + then + local IFS=";" + cat $1 | sed -e "s/$DUMMY_CORE_NAME/$core_name/g" -e "s/$CAT_CHAR_CORE/$CAT_CHAR/g" | grep -E "$leaves" > $FILE_TEMP + + while read -a t + do + if [ "${t[7]}" == "$NODETYPE_SWITCH" ] && [ "${t[10]}" == "$NODETYPE_SWITCH" ]; then + local IFS="|" link="${t[0]};${MTU_SW_SW};;${t[2]};${t[3]};${t[4]};${t[5]};${t[6]};${t[7]};${t[8]};${t[9]};${t[10]};${t[11]}" + # Add Source Spine + add_portnum_to_switchportlist "${t[6]}" "${t[8]}" "1" + # Add Destination Leaf + add_portnum_to_switchportlist "${t[9]}" "${t[11]}" "1" + else + local IFS="|" link="${t[0]};${MTU_SW_HFI};;${t[2]};${t[3]};${t[4]};${t[5]};${t[6]};${t[7]};${t[8]};${t[9]};${t[10]};${t[11]}" + fi + echo "$link" >> ${FILE_LINKSUM_NOCABLE} + local IFS=";" + done < $FILE_TEMP + fi +} + +# Process rack group name; check for non-null name and find in tb_group[]. +# If present return tb_group[] index, otherwise make entry and return index. +# Note that tb_group[0] is always null and is the default rack group. +# Inputs: +# $1 = rack group name (may be null) +# +# Outputs: +# functout - index of rack group name, or 0 +# tb_rack[index] - name of rack group (written when new group) +proc_group() +{ + local val + local ix + + val=0 + + if [ $((n_detail & OUTPUT_GROUPS)) != 0 ] || [ $((n_detail & OUTPUT_RACKS)) != 0 ] || [ $((n_detail & OUTPUT_SWITCHES)) != 0 ] + then + if [ -n "$1" ] + then + # Check for group name already in tb_group[] + for (( ix=1 ; $ix<$MAX_GROUPS ; ix=$((ix+1)) )) + do + if [ -n "${tb_group[$ix]}" ] + then + if [ "$1/" == "${tb_group[$ix]}" ] + then + val=$ix + break + fi + # New group name, save in tb_group[] and make group directory + else + tb_group[$ix]="$1/" + rm -f -r ${tb_group[$ix]} + mkdir ${tb_group[$ix]} + val=$ix + (( group_cnt++ )) + break + fi + + done # for (( ix=1 ; $ix<$MAX_GROUPS + + if [ $ix == $MAX_GROUPS ] + then + echo "Too many rack groups (>= $MAX_GROUPS)" >&2 + usage_full "2" + fi + + else + echo "Must have rack group name when outputting rack group (line:$ix_line)" >&2 + usage_full "2" + fi # End of if [ -n "$1" ] + + fi # End of if [ $((n_detail & OUTPUT_GROUPS)) != 0 ] + + functout=$val + +} # End of proc_group() + +# Process rack name; check for non-null name and find in tb_rack[]. +# If present return tb_rack[] index, otherwise make entry and return index. +# Note that tb_rack[0] is always null and is the default rack. +# Inputs: +# $1 = rack name (may be null) +# $2 = rack group name (may be null) +# +# Outputs: +# functout - index of rack name, or 0 +# tb_rack[index] - name of rack (written when new rack) +proc_rack() +{ + local val + local ix + + val=0 + + if [ $((n_detail & OUTPUT_RACKS)) != 0 ] || [ $((n_detail & OUTPUT_SWITCHES)) != 0 ] + then + if [ -n "$1" ] + then + # Check for rack name already in tb_rack[] + for (( ix=1 ; $ix<$MAX_RACKS ; ix=$((ix+1)) )) + do + if [ -n "${tb_rack[$ix]}" ] + then + if [ "$1/" == "${tb_rack[$ix]}" ] + then + val=$ix + break + fi + # New rack name, save in tb_rack[] and make rack directory + else + tb_rack[$ix]="$1/" + rm -f -r $2${tb_rack[$ix]} + mkdir $2${tb_rack[$ix]} + val=$ix + (( rack_cnt++ )) + break + fi + + done # for (( ix=1 ; $ix<$MAX_RACKS + + if [ $ix == $MAX_RACKS ] + then + echo "Too many racks (>= $MAX_RACKS)" >&2 + usage_full "2" + fi + + else + echo "Must have rack name when outputting rack (line:$ix_line)" >&2 + usage_full "2" + fi # End of if [ -n "$1" ] + + fi # End of if [ $((n_detail & OUTPUT_RACKS)) != 0 ] + + functout=$val + +} # End of proc_rack() + +# Process switch name; check for non-null name and find in tb_switch[]. +# If present return tb_switch[] index, otherwise make entry and return index. +# Note that tb_switch[0] is always null and is the default switch. +# Inputs: +# $1 = switch name (may be null) +# $2 = rack group/rack name (may be null) +# +# Outputs: +# functout - index of switch name, or 0 +# tb_switch[index] - name of switch (written when new switch) +proc_switch() +{ + local val + local ix + + val=0 + + if [ $((n_detail & OUTPUT_SWITCHES)) != 0 ] + then + if [ -n "$1" ] + then + # Check for switch name already in tb_switch[] + for (( ix=1 ; $ix<$MAX_SWITCHES ; ix=$((ix + 1)) )) + do + if [ -n "${tb_switch[$ix]}" ] + then + if [ "$1/" == "${tb_switch[$ix]}" ] + then + val=$ix + break + fi + # New switch name, save in tb_switch[] and make switch directory + else + tb_switch[$ix]="$1/" + rm -f -r $2${tb_switch[$ix]} + mkdir $2${tb_switch[$ix]} + val=$ix + break + fi + + done # for (( ix=1 ; $ix<$MAX_SWITCHES + + if [ $ix == $MAX_SWITCHES ] + then + echo "Too many switches (>= $MAX_SWITCHES)" >&2 + usage_full "2" + fi + + else + echo "Must have switch name when outputting switch (line:$ix_line)" >&2 + usage_full "2" + fi # End of if [ -n "$1" ] + + fi # End of if [ $((n_detail & OUTPUT_RACKS)) != 0 ] + + functout=$val + +} # End of proc_switch() + +# Function to trim the trailing whitespace which +# a user may enter by mistake +trim_trailing_whitespace() +{ + echo "$(echo -e "${1}" | sed -e 's/[[:space:]]*$//')" +} + +process_sm() +{ + for element in "${t[@]:1}" + do + if [ -n "$element" ]; then + host=`echo "$element" | cut -d : -f 1` + port=`echo "$element" | cut -s -d : -f 2` + if [ -z "$port" ]; then + if array_contains hfi[@] "$host" ; then + port=1 + else + port=0 + fi + fi + if array_contains hfi[@] "$host" && ! [[ "$host" =~ $HOST_HFI_REGEX ]] ; then + expected_sm+=("${host}${CAT_CHAR}${hfi_suffix};$port") + else + expected_sm+=("$host;$port") + fi + fi + done + # Add expected sm to FILE_NODESM + for element in "${expected_sm[@]}" + do + echo "$element" >> $FILE_NODESM + done +} + + +# Join miscellaneous fields of global $t[] into a user specified delimited string +join_fields_into_string() +{ + local __res=$1 + local delimiter=$2 + local entry="" + local string="" + local args="" + local i="" + local start=$FIELD_COUNT + local end=$((FIELD_COUNT+additional_fields)) + local IFS + + eval $__res="''" + + ((end--)) + for i in `seq $start $end`; do + entry="${t[$i]}" + if [ "$string" == "" ]; then + string=$entry + else + string="${string}${delimiter}${entry}" + fi + done + + # Add a terminating delimeter (this helps parsers account for empty last column cells) + if [ "$string" != "" ]; then + string="${string}${delimiter}" + fi + + eval $__res="'$string'" +} + +parse_table_header() +{ + local IFS="," + declare -a element_list + declare -a subelement_list + declare -a misc_hdr_list + local misc_column_list="" + local element="" + local subelement="" + local subelement_test="" + local nested_element="" + local entry="" + local index_pos=-1 + misc_param_index=() + + join_fields_into_string misc_column_list "," + + # Excel will put a cell in quotes if it contains a comma during CSV generation + if [[ "$misc_column_list" =~ "\"" ]]; then + echo "Parse error no quoted strings in miscellaneous header cell: $misc_column_list" >&2 + exit 2 + return + fi + + if [[ "$misc_column_list" =~ ";" ]]; then + echo "Parse error no semicolons in miscellaneous header: $misc_column_list" >&2 + exit 2 + return + fi + + for element in $misc_column_list; do + if [[ "$element" == "" ]]; then + echo "Parse error empty element in miscellaneous header" >&2 + exit 2 + fi + + if [[ $element =~ [[:space:]] ]]; then + echo "Parse error whitespace in miscellaneous element '${element}'" >&2 + exit 2 + fi + + element_list+=($element) + + # check if entry is part of subelement + if [[ "$element" =~ ":" ]]; then + # sanity check subelement + subelement=${element/:*/} + if [[ "$subelement" == "" ]]; then + echo "Parse error subelement name not specified '${element}'" >&2 + exit 2 + fi + + # sanity check nested element + nested_element=`echo $element | cut -d ':' -f 2` + if [[ "$nested_element" == "" ]]; then + echo "Parse error nested element name not specified '${element}'" >&2 + exit 2 + fi + subelement_list+=($subelement) + fi + done + + IFS=' ' + # sort subelements and remove duplicates + subelement_list=($(echo ${subelement_list[@]} | tr ' ' '\n' | sort -u| tr '\n' ' ')) + + # add the root element too beginning of list + subelement_list=($(echo "__root ${subelement_list[@]}")) + + for subelement in "${subelement_list[@]}"; do + for element in "${element_list[@]}"; do + + if [[ "$subelement" == "__root" ]]; then + # a root element has is a element without : seperator + if ! [[ "$element" =~ ":" ]]; then + misc_hdr_list+=($element) + continue + fi + fi + + # check if entry is a member of subelement + subelement_test=${element/:*/} + if [[ "$subelement" == "$subelement_test" ]]; then + misc_hdr_list+=($element) + fi + done + done + + # Build parameter list for opaxmlgenerate + subelement="__root" + args="" + subelement_test="" + nested_element="" + + for entry in "${misc_hdr_list[@]}"; do + if [[ "$entry" =~ ":" ]]; then + subelement_test=${entry/:*/} + nested_element=`echo $entry | cut -d ':' -f 2` + if [[ "$subelement" != "$subelement_test" ]]; then + if [[ "$subelement" == "__root" ]]; then + args="$args -h $subelement_test -g $nested_element" + else + args="$args -e $subelement -h $subelement_test -g $nested_element" + fi + subelement=$subelement_test; + else + args="$args -g $nested_element" + fi + else + if [[ "$subelement" != "__root" ]]; then + echo "Unexpected error root element" >&2 + exit 2 + fi + args="$args -g $entry" + fi + done + if [[ "$nested_element" != "" ]]; then + args="$args -e $subelement" + fi + + misc_params=$args + + # Now that columns are in a different order build an index to map the data set + index_pos=-1 + for element in "${element_list[@]}"; do + ((index_pos++)) + entry_pos=0 + for entry in "${misc_hdr_list[@]}"; do + if [[ "$entry" == "$element" ]]; then + misc_param_index[$index_pos]=$entry_pos + break + fi + ((entry_pos++)) + done + done +} + +add_fields_to_misc_table() +{ + # save entry $3 to lookup table via node desc $1 and type $2 + local node_desc=$1 + local node_type=$2 + local arg="" + local node_misc_entry="" + local i=0 + local index_pos=0 + local cnt=0 + local IFS + declare -a node_misc_entry_array=() + declare -a sorted_node_misc_entry_array=() + + if [ "$node_desc" == "" ]; then + return + fi + + # Join node field arguments into a comma-delimited string + join_fields_into_string node_misc_entry "," + + if [ "$node_misc_entry" == "" ]; then + return + fi + + # Excel will put a cell in quotes if it contains a comma during CSV generation + if [[ "$node_misc_entry" =~ "\"" ]]; then + echo "Parse error no quoted strings in cell $node_misc_entry" >&2 + exit 2 + return + fi + + # Convert comma delimiter to semicolon delimiter for opaxmlgenerate + IFS="," node_misc_entry_array=($node_misc_entry) + + cnt=${#node_misc_entry_array[@]} + ((cnt--)) + + # Sort input entries using the parameter index for opaxmlgenerate + # Create a semicolon delmited string + unset IFS + + if [[ "$cnt" -ge 0 ]]; then + for i in `seq 0 $cnt` + do + index_pos=${misc_param_index[$i]} + if [[ "$index_pos" == "" ]]; then + echo "Unexpected error index not defined for position $i" >&2 + exit 2 + fi + sorted_node_misc_entry_array[$index_pos]=${node_misc_entry_array[$i]} + done + + node_misc_entry="${sorted_node_misc_entry_array[0]}" + for i in `seq 1 $cnt` + do + node_misc_entry="$node_misc_entry;${sorted_node_misc_entry_array[$i]}" + done + fi + + # Remove whitespace in node description for associative array lookup (required by Bash) + node_desc=${node_desc//[[:space:]]/_} + + case $node_type in + $NODETYPE_EDGE ) + misc_sw_table[$node_desc]="$node_misc_entry" + ;; + $NODETYPE_LEAF ) + misc_sw_table[$node_desc]="$node_misc_entry" + ;; + $NODETYPE_SPINE ) + misc_sw_table[$node_desc]="$node_misc_entry" + ;; + $NODETYPE_HFI ) + misc_fi_table[$node_desc]="$node_misc_entry" + ;; + *) + echo "Error invalid node type '${node_type}'" >&2 + exit 2 + ;; + esac +} + +add_portnum_to_switchportlist() +{ + local portnum=$1 + local node_desc=$2 + local internal=$3 + local portlist="" + local IFS + + if [ "$node_desc" == "" ]; then + return + fi + + # Remove whitespace in node description for associative array lookup (required by Bash) + node_desc=${node_desc//[[:space:]]/_} + portlist=${sw_portlist_table[$node_desc]} + + # Make sure internal parameter numerical value + if [[ ${internal//[[:digit:]]/} ]]; then + echo "Internal Error: internal parameter is non-numerical \"$internal\"" >&2 + exit 1 + fi + + # Make sure port number is numerical value + if [[ ${portnum//[[:digit:]]/} ]]; then + echo "Error port number is non-numerical \"$portnum\" (line:$ix_line)" >&2 + exit 2 + fi + + # Make sure this port is not already in the portlist + IFS=',' + for port in $portlist + do + if [ "$port" == "$portnum" ]; then + # check to make sure there are not duplicate entries in the CSV files + # accept duplicate internal ports and drop them from list + if [ "$internal" == "1" ]; then + return + else + echo "Error port number \"$portnum\" is already in the list of ports processed for \"$node_desc\" (line:$ix_line)" >&2 + exit 2 + fi + fi + done + + if [ "$portlist" == "" ]; then + portlist="$portnum" + else + portlist="${portlist},${portnum}" + fi + + sw_portlist_table[$node_desc]="$portlist" +} + +lookup_portnum_from_switchportlist() +{ + local node_desc=$1 + local __res=$2 + local portlist="" + + if [ "$node_desc" == "" ]; then + return + fi + + # Remove whitespace in node description for associative array lookup (required by Bash) + node_desc=${node_desc//[[:space:]]/_} + portlist=${sw_portlist_table[$node_desc]} + + eval $__res="'$portlist'" +} + +generate_switch_section() +{ + local line="" + local node_desc="" + local node_desc_key="" + local port_list="" + declare -a port_array + local portnum="" + local switch_entry="" + local portnum_entry="" + local IFS + + # Generate Nodes/Switches section in XML + echo "" >> $FILE_TOPOLOGY_TEMP + if [ -s $FILE_NODESWITCHES ] + then + while read -r line; do + portnum_entry="" + switch_entry="" + node_desc=${line//;*} + if [ "$node_desc" == "" ]; then + echo "Internal Error: Node Description Empty" >&2 + exit 1 + fi + + # Sanity check Switch Node ports + lookup_portnum_from_switchportlist "$node_desc" port_list + if [ "$port_list" == "" ]; then + echo "Internal Error: Switch defined (${node_desc}) with no ports" >&2 + exit 1 + fi + + # If Switch entry has additional parameters, generate XML entry with $XML_GENERATE + unset IFS + if [[ "$line" =~ ";" ]]; then + switch_entry=`echo $line | $XML_GENERATE -X - -d \; -i 2 -h Node -g NodeDesc $misc_params` + else + # Otherwise manually create Switch entries + switch_entry=""$'\n' + switch_entry=${switch_entry}"${node_desc}" + switch_entry=${switch_entry}$'\n' + + # Add required PortNum 0 definition + if [ "$port_field" == "required" ]; then + portnum_entry=${portnum_entry}$'\n' + portnum_entry=${portnum_entry}"" + portnum_entry=${portnum_entry}$'\n' + portnum_entry=${portnum_entry}"0" + portnum_entry=${portnum_entry}$'\n' + portnum_entry=${portnum_entry}"" + fi + fi + + if [ "$port_field" == "required" ]; then + # Sort Port number list to make output more readable + IFS=',' + port_array="" + for portnum in $port_list; do + port_array+=($portnum) + done + port_array=($(echo ${port_array[@]} | tr ' ' '\n' | sort -n -u| tr '\n' ' ')) + + unset IFS + # Insert Port number list to XML + for portnum in ${port_array[@]} + do + portnum_entry=${portnum_entry}$'\n' + portnum_entry=${portnum_entry}"" + portnum_entry=${portnum_entry}$'\n' + portnum_entry=${portnum_entry}"${portnum}" + portnum_entry=${portnum_entry}$'\n' + portnum_entry=${portnum_entry}"" + done + fi + + # Write entry to XML file + echo $switch_entry >> $FILE_TOPOLOGY_TEMP + echo $portnum_entry >> $FILE_TOPOLOGY_TEMP + echo "" >> $FILE_TOPOLOGY_TEMP + done < $FILE_NODESWITCHES + fi + echo "" >> $FILE_TOPOLOGY_TEMP +} + +lookup_misc_table_entry() +{ + # lookup entry via node desc $1 and type $2 and return by updating $3 + local node_desc=$1 + local node_type=$2 + local __res=$3 + local entry="" + + if [ "$node_desc" == "" ]; then + return + fi + + # Remove whitespace in node description for associative array lookup (required by Bash) + node_desc=${node_desc//[[:space:]]/_} + + case $node_type in + $NODETYPE_EDGE ) + entry=${misc_sw_table[$node_desc]} + ;; + $NODETYPE_LEAF ) + entry=${misc_sw_table[$node_desc]} + ;; + $NODETYPE_SPINE ) + entry=${misc_sw_table[$node_desc]} + ;; + $NODETYPE_HFI ) + entry=${misc_fi_table[$node_desc]} + ;; + *) + echo "Error invalid node type '${node_type}'" >&2 + exit 2 + ;; + esac + + eval $__res="'$entry'" +} + +## Main function: + +# Get options +while getopts d:i:Kv:s:o: option +do + case $option in + d) + n_detail=$OPTARG + if [ $((n_detail & OUTPUT_EDGE_LEAF_LINKS)) != 0 ] + then + fl_output_edge_leaf=0 + fi + if [ $((n_detail & OUTPUT_SPINE_LEAF_LINKS)) != 0 ] + then + fl_output_spine_leaf=0 + fi + ;; + + i) + indent=$OPTARG + ;; + + K) + fl_clean=0 + ;; + + v) + n_verbose=$OPTARG + ;; + + o) + output_section=$OPTARG + if [ "$output_section" != "brnodes" ] && [ "$output_section" != "links" ] ; then + echo "opaxlattopology -o: Invalid Argument - $output_section" + usage_full "2" + exit 1 + fi + ;; + + s) + hfi_suffix=$OPTARG + if [[ "$hfi_suffix" =~ $HFI_SUFFIX_REGEX ]] ; then + hfiNum=`echo "$hfi_suffix" | cut -d "_" -f2` + # Change the name of FILE_TOPOLOGY_OUT as per the hfi name + # This can be overwritten by specifying output file name through command line + FILE_TOPOLOGY_OUT="topology.$((hfiNum+1)):0.xml" + elif [[ "$hfi_suffix" == "" ]] ; then + # Do nothing + : + else + echo "opaxlattopology -s: Invalid Argument, should be like hfi1_0 or empty string" + usage_full "2" + exit 1 + fi + ;; + + *) + usage_full "2" + ;; + esac +done + +shift $((OPTIND -1)) + +if [ $# -ge 1 ]; then + FILE_TOPOLOGY_LINKS=$1 + shift; +fi +if [ $# -ge 1 ]; then + if [ -d $1 ]; then + OUT_FOLDER="$1" + else + FILE_TOPOLOGY_OUT=$1 + fi +fi + +# if output folder is specified, cd to that folder after +# moving the temp files to this out folder and make sure +# that the input FILE_TOPOLOGY_LINK file is absolute +if [ $OUT_FOLDER ]; then + working_dir=$(pwd) + mv $FILE_TEMP $OUT_FOLDER + mv $FILE_TEMP2 $OUT_FOLDER + # if path is relative; convert it to absolute + if [[ "${FILE_TOPOLOGY_LINKS:0:1}" != "/" ]]; then + FILE_TOPOLOGY_LINKS="${working_dir}/${FILE_TOPOLOGY_LINKS}" + fi + cd $OUT_FOLDER +fi + +# Parse FILE_TOPOLOGY_LINKS2 +display_progress "Parsing $FILE_TOPOLOGY_LINKS" + +remove_file "$FILE_LINKSUM" +remove_file "$FILE_LINKSUM_NOCORE" +remove_file "$FILE_LINKSUM_NOCABLE" +remove_file "$FILE_NODEFIS" +remove_file "$FILE_NODESWITCHES" +remove_file "$FILE_NODELEAVES" +remove_file "$FILE_NODECHASSIS" + +# default rate +RATE_DEFAULT=${RATE_DEFAULT:-"100g"} + +while IFS="," read -a t +do + ((ix_line++)) + + case $cts_parse in + # Syncing to beginning of link data + 0) + if [ "${t[0]}" == "Rack Group" ] + then + # Parse remaining optional (CSV formatted) column headers + # Generate additional parameters for opaxmlgenerate + # based on the optional column headers + # Count additional optional fields + additional_fields=${#t[@]} + additional_fields=$((additional_fields-FIELD_COUNT)) + # This may happen if user is using minimal sample csv + if [[ "$additional_fields" -lt "0" ]]; then + additional_fields=0 + portnum_field=FIELD_COUNT + else + # Topology XMLs require a Node/Port/PortNum Field + portnum_field=${#t[@]} + if [[ "$additional_fields" -gt "0" ]] ; then + t_additional=${t[@]:$FIELD_COUNT} + if array_contains t_additional[@] "Port:LID" || array_contains t_additional[@] "Port:LMC" ; then + port_field="required" + t[$portnum_field]="Port:PortNum" + ((additional_fields++)) + fi + fi + fi + parse_table_header + cts_parse=1 + fi + ;; + + # Process link tokens + 1) + if [ -n "${t[0]}" ] + then + t_srcgroup=`trim_trailing_whitespace "${t[0]}"` + fi + if [ -n "${t[1]}" ] + then + t_srcrack=`trim_trailing_whitespace "${t[1]}"` + fi + t_srcname=`trim_trailing_whitespace "${t[2]}"` + t_srcname2=`trim_trailing_whitespace "${t[3]}"` + if [ -n "${t[5]}" ] + then + t_srctype=`trim_trailing_whitespace "${t[5]}"` + fi + if [ -z "${t[4]}" -a "$t_srctype" == "$NODETYPE_HFI" ] + then + t_srcport=1 + else + t_srcport=`trim_trailing_whitespace "${t[4]}"` + fi + + if [ -n "${t[6]}" ] + then + t_dstgroup=`trim_trailing_whitespace "${t[6]}"` + fi + if [ -n "${t[7]}" ] + then + t_dstrack=`trim_trailing_whitespace "${t[7]}"` + fi + t_dstname=`trim_trailing_whitespace "${t[8]}"` + t_dstname2=`trim_trailing_whitespace "${t[9]}"` + if [ -n "${t[11]}" ] + then + t_dsttype=`trim_trailing_whitespace "${t[11]}"` + fi + if [ -z "${t[10]}" -a "$t_dsttype" == "$NODETYPE_HFI" ] + then + t_dstport=1 + else + t_dstport=`trim_trailing_whitespace "${t[10]}"` + fi + + if [ `cvt_nodetype "$t_srctype"` == "$NODETYPE_SWITCH" ]; then + t[$portnum_field]=0 + else + t[$portnum_field]=$t_srcport + fi + + t_cablelabel=`trim_trailing_whitespace "${t[12]}"` + t_cablelength=`trim_trailing_whitespace "${t[13]}"` + t_cabledetails=`trim_trailing_whitespace "${t[14]}"` + + rate=`trim_trailing_whitespace "${t[15]}"` + + if [ "$rate" == "" ]; then + rate=$RATE_DEFAULT + fi + if [ `cvt_nodetype "$t_srctype"` == "$NODETYPE_HFI" ]; then + MTU_SW_HFI=`trim_trailing_whitespace "${t[16]}"` + + if [ "$MTU_SW_HFI" == "" ]; then + MTU_SW_HFI=$MTU_SW_HFI_DEFAULT + fi + + # Make sure MTU is numerical value + if [[ "${MTU_SW_HFI//[[:digit:]]/}" != "" ]]; then + echo "Error MTU is non-numerical \"$MTU_SW_HFI\"" >&2 + exit 2 + fi + + else + MTU_SW_SW=`trim_trailing_whitespace "${t[16]}"` + + if [ "$MTU_SW_SW" == "" ]; then + MTU_SW_SW=$MTU_SW_SW_DEFAULT + fi + + # Make sure MTU is numerical value + if [[ "${MTU_SW_SW//[[:digit:]]/}" != "" ]]; then + echo "Error MTU is non-numerical \"$MTU_SW_SW\"" >&2 + exit 2 + fi + + fi + t_linkdetails=`trim_trailing_whitespace "${t[17]}"` + + if [ "$t_srctype" == "$NODETYPE_SPINE" ] + then + internal="1" + else + internal="0" + fi + + # Process group, rack and switch names + if [ -n "$t_srcname" ] + then + proc_group "$t_srcgroup" + ix_srcgroup=$functout + proc_rack "$t_srcrack" "${tb_group[$ix_srcgroup]}" + ix_srcrack=$functout + proc_group "$t_dstgroup" + ix_dstgroup=$functout + proc_rack "$t_dstrack" "${tb_group[$ix_dstgroup]}" + ix_dstrack=$functout + if [ "$t_srctype" == "$NODETYPE_EDGE" ] + then + proc_switch "$t_srcname" "${tb_group[$ix_srcgroup]}${tb_rack[$ix_srcrack]}" + ix_srcswitch=$functout + else + ix_srcswitch=0 + fi + if [ "$t_dsttype" == "$NODETYPE_EDGE" ] + then + proc_switch "$t_dstname" "${tb_group[$ix_dstgroup]}${tb_rack[$ix_dstrack]}" + ix_dstswitch=$functout + else + ix_dstswitch=0 + fi + + # Form consolidated output data + nodedesc1="${t_srcname}" + if [ "$t_srctype" == "$NODETYPE_HFI" ] + then + if ! [[ "$nodedesc1" =~ $HOST_HFI_REGEX ]]; then + nodedesc1="${nodedesc1}${CAT_CHAR}${hfi_suffix}" + fi + nodedetails1="${t_srcname2}" + hfi+=("$t_srcname") + else + nodedetails1="" + if [ "$t_srctype" != "$NODETYPE_EDGE" ] + then + nodedesc1="${nodedesc1}${CAT_CHAR}${t_srcname2}" + fi + fi + + nodedesc2="${t_dstname}" + if [ "$t_dsttype" != "$NODETYPE_EDGE" ] + then + nodedesc2="${nodedesc2}${CAT_CHAR}${t_dstname2}" + fi + + nodetype1=`cvt_nodetype "$t_srctype"` + if [ -z "$nodetype1" ] + then + echo "NodeType of "$t_srctype" is not valid. Valid types are FI, SW, CL, CS" >&2 + usage_full "2" + fi + + nodetype2=`cvt_nodetype "$t_dsttype"` + if [ -z "$nodetype2" ] + then + echo "NodeType of "$t_dsttype" is not valid. Valid types are FI, SW, CL, CS" >&2 + usage_full "2" + fi + + # Validate sources and destinations + if [ "$t_dsttype" == "$NODETYPE_HFI" ]; then + echo "Error: HFIs cannot be destination nodes (line:$ix_line)" >&2 + usage_full "2" + fi + + if [[ "$t_srctype" == "$NODETYPE_HFI" ]] && [[ "$t_dsttype" != "$NODETYPE_EDGE" && "$t_dsttype" != "$NODETYPE_LEAF" ]]; then + echo "Error: HFIs must connect to Edge/Leaf Switches (line:$ix_line)" >&2 + usage_full "2" + fi + + if [ "$t_srctype" != "$NODETYPE_LEAF" ] && [ "$t_dsttype" == "$NODETYPE_SPINE" ]; then + echo "Error: Only Leaf switches can connect to Spine switches (line:$ix_line)" >&2 + usage_full "2" + fi + + if [ "$t_srctype" == "$NODETYPE_SPINE" ]; then + echo "Error: Spine switches cannot be source nodes (line:$ix_line)" >&2 + usage_full "2" + fi + + # Add miscellaneous content to lookup table (keyed by node desc and node type) + # This will be used in XML output generation + + add_fields_to_misc_table "$nodedesc1" "$t_srctype" + + if [ "$nodetype1" == "$NODETYPE_SWITCH" ]; then + # Add Source Port to PortList if Source Node is Switch + add_portnum_to_switchportlist "$t_srcport" "$nodedesc1" "$internal" + fi + + if [ "$nodetype2" == "$NODETYPE_SWITCH" ]; then + # Add Destination Port to PortList if Destination Node is Switch + add_portnum_to_switchportlist "$t_dstport" "$nodedesc2" "$internal" + fi + + # Output CSV FILE_LINKSUM + if [ $nodetype2 != "$NODETYPE_ENDPOINT" ]; then + if [ $nodetype1 == "$NODETYPE_SWITCH" ] && [ $nodetype2 == "$NODETYPE_SWITCH" ]; then + link="${rate};${MTU_SW_SW};${t_linkdetails};${internal};${t_cablelength};${t_cablelabel};${t_cabledetails};${t_srcport};${nodetype1};${nodedesc1};${t_dstport};${nodetype2};${nodedesc2}" + else + link="${rate};${MTU_SW_HFI};${t_linkdetails};${internal};${t_cablelength};${t_cablelabel};${t_cabledetails};${t_srcport};${nodetype1};${nodedesc1};${t_dstport};${nodetype2};${nodedesc2}" + fi + echo "${link}" >> ${FILE_LINKSUM} + fi + + if [ $((n_detail & OUTPUT_GROUPS)) != 0 ] + then + echo "${link}" >> ${tb_group[$ix_srcgroup]}${FILE_LINKSUM} + if [ $ix_dstgroup != $ix_srcgroup ] + then + echo "${link}" >> ${tb_group[$ix_dstgroup]}${FILE_LINKSUM} + fi + fi + + if [ $((n_detail & OUTPUT_RACKS)) != 0 ] + then + echo "${link}" >> ${tb_group[$ix_srcgroup]}${tb_rack[$ix_srcrack]}${FILE_LINKSUM} + if [ $ix_dstrack != $ix_srcrack ] + then + echo "${link}" >> ${tb_group[$ix_dstgroup]}${tb_rack[$ix_dstrack]}${FILE_LINKSUM} + fi + fi + + if [ $((n_detail & OUTPUT_SWITCHES)) != 0 ] + then + if [ "$t_srctype" == "$NODETYPE_EDGE" ] + then + echo "${link}" >> ${tb_group[$ix_srcgroup]}${tb_rack[$ix_srcrack]}${tb_switch[$ix_srcswitch]}${FILE_LINKSUM} + fi + if [ "$t_dsttype" == "$NODETYPE_EDGE" ] + then + echo "${link}" >> ${tb_group[$ix_dstgroup]}${tb_rack[$ix_dstrack]}${tb_switch[$ix_dstswitch]}${FILE_LINKSUM} + fi + fi + + # Output CSV FILE_LINKSUM_NOCORE + if [ "$t_dsttype" != "$NODETYPE_LEAF" ] + then + echo "${link}" >> ${FILE_LINKSUM_NOCORE} + if [ $((n_detail & OUTPUT_GROUPS)) != 0 ] + then + echo "${link}" >> ${tb_group[$ix_srcgroup]}${FILE_LINKSUM_NOCORE} + if [ $ix_dstgroup != $ix_srcgroup ] + then + echo "${link}" >> ${tb_group[$ix_dstgroup]}${FILE_LINKSUM_NOCORE} + fi + fi + + if [ $((n_detail & OUTPUT_RACKS)) != 0 ] + then + echo "${link}" >> ${tb_group[$ix_srcgroup]}${tb_rack[$ix_srcrack]}${FILE_LINKSUM_NOCORE} + if [ $ix_dstrack != $ix_srcrack ] + then + echo "${link}" >> ${tb_group[$ix_dstgroup]}${tb_rack[$ix_dstrack]}${FILE_LINKSUM_NOCORE} + fi + fi + + if [ $((n_detail & OUTPUT_SWITCHES)) != 0 ] + then + if [ "$t_srctype" == "$NODETYPE_EDGE" ] + then + echo "${link}" >> ${tb_group[$ix_srcgroup]}${tb_rack[$ix_srcrack]}${tb_switch[$ix_srcswitch]}${FILE_LINKSUM_NOCORE} + fi + if [ "$t_dsttype" == "$NODETYPE_EDGE" ] + then + echo "${link}" >> ${tb_group[$ix_dstgroup]}${tb_rack[$ix_dstrack]}${tb_switch[$ix_dstswitch]}${FILE_LINKSUM_NOCORE} + fi + fi + fi + + # Output CSV FILE_LINKSUM_NOCABLE + # Note: output only needed at top-level to bootstrap FILE_LINKSUM_SWD06 + # and FILE_LINKSUM_SWD24 + if [ "$t_srctype" == "$NODETYPE_SPINE" ] + then + echo "${link}" >> ${FILE_LINKSUM_NOCABLE} + fi + + # Output CSV nodedesc1 + if [ "$t_srctype" == "$NODETYPE_HFI" ] + then + echo "${nodedesc1};${nodedetails1}" >> ${FILE_NODEFIS} + if [ $((n_detail & OUTPUT_GROUPS)) != 0 ] + then + echo "${nodedesc1};${nodedetails1}" >> ${tb_group[$ix_srcgroup]}${FILE_NODEFIS} + fi + + if [ $((n_detail & OUTPUT_RACKS)) != 0 ] + then + echo "${nodedesc1};${nodedetails1}" >> ${tb_group[$ix_srcgroup]}${tb_rack[$ix_srcrack]}${FILE_NODEFIS} + fi + + if [ $((n_detail & OUTPUT_SWITCHES)) != 0 ] + then + if [ "$t_dsttype" == "$NODETYPE_EDGE" ] + then + if [ "x${tb_group[$ix_dstgroup]}${tb_rack[$ix_dstrack]}" == "x${tb_group[$ix_srcgroup]}${tb_rack[$ix_srcrack]}" ] + then + echo "${nodedesc1};${nodedetails1}" >> ${tb_group[$ix_dstgroup]}${tb_rack[$ix_dstrack]}${tb_switch[$ix_dstswitch]}${FILE_NODEFIS} + fi + fi + fi + else + echo "${nodedesc1}" >> ${FILE_NODESWITCHES} + if [ $((n_detail & OUTPUT_GROUPS)) != 0 ] + then + echo "${nodedesc1}" >> ${tb_group[$ix_srcgroup]}${FILE_NODESWITCHES} + fi + + if [ $((n_detail & OUTPUT_RACKS)) != 0 ] + then + echo "${nodedesc1}" >> ${tb_group[$ix_srcgroup]}${tb_rack[$ix_srcrack]}${FILE_NODESWITCHES} + fi + + if [ $((n_detail & OUTPUT_SWITCHES)) != 0 ] + then + echo "${nodedesc1}" >> ${tb_group[$ix_srcgroup]}${tb_rack[$ix_srcrack]}${tb_switch[$ix_srcswitch]}${FILE_NODESWITCHES} + fi + fi + + # Output CSV nodedesc2 + if [ "$nodetype2" != "$NODETYPE_ENDPOINT" ]; then + echo "${nodedesc2}" >> ${FILE_NODESWITCHES} + fi + if [ "$t_dsttype" == "$NODETYPE_LEAF" ] + then + echo "${nodedesc2}" >> ${FILE_NODELEAVES} + echo "${t_dstname}" >> ${FILE_NODECHASSIS} + external_leaves+=("`echo "${nodedesc2}" | sed -e 's/[AB]$//'`") + fi + if [ $((n_detail & OUTPUT_GROUPS)) != 0 ] && [ "$nodetype2" != "$NODETYPE_ENDPOINT" ] + then + echo "${nodedesc2}" >> ${tb_group[$ix_dstgroup]}${FILE_NODESWITCHES} + if [ "$t_dsttype" == "$NODETYPE_LEAF" ] + then + echo "${nodedesc2}" >> ${tb_group[$ix_dstgroup]}${FILE_NODELEAVES} + echo "${t_dstname}" >> ${tb_group[$ix_dstgroup]}${FILE_NODECHASSIS} + fi + fi + + if [ $((n_detail & OUTPUT_RACKS)) != 0 ] && [ "$nodetype2" != "$NODETYPE_ENDPOINT" ] + then + echo "${nodedesc2}" >> ${tb_group[$ix_dstgroup]}${tb_rack[$ix_dstrack]}${FILE_NODESWITCHES} + if [ "$t_dsttype" == "$NODETYPE_LEAF" ] + then + echo "${nodedesc2}" >> ${tb_group[$ix_dstgroup]}${tb_rack[$ix_dstrack]}${FILE_NODELEAVES} + echo "${t_dstname}" >> ${tb_group[$ix_dstgroup]}${tb_rack[$ix_dstrack]}${FILE_NODECHASSIS} + fi + fi + + if [ $((n_detail & OUTPUT_SWITCHES)) != 0 ] && [ "$nodetype2" != "$NODETYPE_ENDPOINT" ] + then + if [ "$t_dsttype" == "$NODETYPE_EDGE" ] + then + echo "${nodedesc2}" >> ${tb_group[$ix_dstgroup]}${tb_rack[$ix_dstrack]}${tb_switch[$ix_dstswitch]}${FILE_NODESWITCHES} + elif [ "$t_dsttype" == "$NODETYPE_LEAF" ] + then + echo "${nodedesc2}" >> ${tb_group[$ix_dstgroup]}${tb_rack[$ix_dstrack]}${tb_switch[$ix_dstswitch]}${FILE_NODELEAVES} + echo "${t_dstname}" >> ${tb_group[$ix_dstgroup]}${tb_rack[$ix_dstrack]}${tb_switch[$ix_dstswitch]}${FILE_NODECHASSIS} + fi + fi + + # End of link information + else + cts_parse=2 + fi + ;; + + # Process core switch data + 2) + if echo "${t[0]}" | grep -e "$CORE_NAME" > /dev/null 2>&1 + then + core_name=`echo "${t[0]}" | cut -d ':' -f 2` + # Make sure that core name do not have space char + if [[ "$core_name" =~ [[:space:]] ]] + then + echo "opaxlattopology: Error - core name cannot have space char: $core_name" >&2 + exit 2 + fi + core+=("$core_name") + display_progress "Generating links for Core:$core_name" + if echo "${t[1]}" | grep -e "$CORE_GROUP" > /dev/null 2>&1 + then + core_group=`echo "${t[1]}" | cut -d ':' -f 2` + elif [ $((n_detail & OUTPUT_GROUPS)) != 0 ] + then + echo "Must have rack group name when outputting rack group (line:$ix_line)" + usage_full "2" + else + core_group="" + fi + # Make sure that core group do not have space char + if [[ "$core_group" =~ [[:space:]] ]] + then + echo "opaxlattopology: Error - core group name cannot have space char: $core_group" >&2 + exit 2 + fi + # Store core group + core_name_group["$core_name"]="$core_group" + if echo "${t[2]}" | grep -e "$CORE_RACK" > /dev/null 2>&1 + then + core_rack=`echo "${t[2]}" | cut -d ':' -f 2` + elif [ $((n_detail & OUTPUT_RACKS)) != 0 ] + then + echo "Must have rack name when outputting rack (line:$ix_line)" + usage_full "2" + else + core_rack="" + fi + # Make sure that core rack do not have space char + if [[ "$core_rack" =~ [[:space:]] ]] + then + echo "opaxlattopology: Error - core rack name cannot have space char: $core_rack" >&2 + exit 2 + fi + # Store core rack + core_name_rack["$core_name"]="$core_rack" + if echo "${t[3]}" | grep -e "$CORE_SIZE" > /dev/null 2>&1 + then + core_size=`echo ${t[3]} | cut -d ':' -f 2` + if [ $core_size -ne 288 -a $core_size -ne 1152 ] + then + echo "Invalid $CORE_SIZE parameter (${t[3]})" + usage_full "2" + fi + else + echo "No $CORE_SIZE parameter" + usage_full "2" + fi + # Store core size + core_name_size["$core_name"]="$core_size" + if echo "${t[4]}" | grep -e "$CORE_FULL" > /dev/null 2>&1 + then + core_full=`echo ${t[4]} | cut -d ':' -f 2` + if [ $core_full -ne 0 -a $core_full -ne 1 ] + then + echo "Invalid $CORE_FULL parameter (${t[4]})" + usage_full "2" + fi + else + core_full=0 + fi + + # Output CSV FILE_LINKSUM_NOCABLE + if [ $core_full == 1 ] + then + leaves="" + else + partially_populated_core+=($core_name) + leaves=`cat $FILE_NODELEAVES | tr '\012' '|' | sed -e 's/|$//'` + fi + if [ $core_size == 288 ] + then + generate_linksum_nocable $FILE_LINKSUM_SWD06 + else + generate_linksum_nocable $FILE_LINKSUM_SWD24 + fi + cat ${FILE_LINKSUM_NOCABLE} | cut -d ';' -f 10 | sort -u >> ${FILE_NODESWITCHES} + cat ${FILE_LINKSUM_NOCABLE} | cut -d ';' -f 13 | sort -u >> ${FILE_NODESWITCHES} + cat ${FILE_LINKSUM_NOCABLE} | cut -d ';' -f 13 | cut -d "$CAT_CHAR" -f 1 | sort -u >> ${FILE_NODECHASSIS} + + if [ $((n_detail & OUTPUT_GROUPS)) != 0 ] + then + if [ $core_full == 1 ] + then + leaves="" + else + leaves=`cat $core_group/$FILE_NODELEAVES | tr '\012' '|' | sed -e 's/|$//'` + fi + cp ${FILE_LINKSUM_NOCABLE} "$core_group"/${FILE_LINKSUM_NOCABLE} + cat ${FILE_LINKSUM_NOCABLE} | cut -d ';' -f 10 | sort -u >> "$core_group"/${FILE_NODESWITCHES} + cat ${FILE_LINKSUM_NOCABLE} | cut -d ';' -f 13 | sort -u >> "$core_group"/${FILE_NODESWITCHES} + cat ${FILE_LINKSUM_NOCABLE} | cut -d ';' -f 13 | cut -d "$CAT_CHAR" -f 1 | sort -u >> "$core_group"/${FILE_NODECHASSIS} + fi + + if [ $((n_detail & OUTPUT_RACKS)) != 0 ] + then + if [ $core_full == 1 ] + then + leaves="" + else + leaves=`cat "$core_group"/"$core_rack"/$FILE_NODELEAVES | tr '\012' '|' | sed -e 's/|$//'` + fi + cp ${FILE_LINKSUM_NOCABLE} "$core_group"/"$core_rack"/${FILE_LINKSUM_NOCABLE} + cat ${FILE_LINKSUM_NOCABLE} | cut -d ';' -f 10 | sort -u >> "$core_group"/"$core_rack"/${FILE_NODESWITCHES} + cat ${FILE_LINKSUM_NOCABLE} | cut -d ';' -f 13 | sort -u >> "$core_group"/"$core_rack"/${FILE_NODESWITCHES} + cat ${FILE_LINKSUM_NOCABLE} | cut -d ';' -f 13 | cut -d "$CAT_CHAR" -f 1 | sort -u >> "$core_group"/"$core_rack"/${FILE_NODECHASSIS} + fi + + # End of core switch information + elif [ "${t[0]}" == "SM" ] + then + # Process SM section + process_sm + else + cts_parse=3 + fi + ;; + + # Finding "Present Leaves" or "Omitted Spine" or "SM" tag. Process if "SM" tag is found + 3) + if [ "${t[0]}" == "Present Leafs" ] || [ "${t[0]}" == "Present Leaves" ] + then + cts_parse=4 + elif [ "${t[0]}" == "Omitted Spines" ] + then + cts_parse=5 + elif [ "${t[0]}" == "SM" ] + then + # Process SM section + process_sm + else + cts_parse=3 + fi + ;; + + # Process Present Leaves + 4) + if echo "${t[0]}" | grep -e "$CORE_NAME" > /dev/null 2>&1 + then + core_name=`echo ${t[0]} | cut -d ':' -f 2` + if ! array_contains core[@] $core_name + then + echo "opaxlattopology: Error - No Core details found for $core_name, specified in \"Present Leaves\" section">&2 + exit 2 + fi + if array_contains partially_populated_core[@] $core_name + then + display_progress "Processing Leaves of partially populated Core:$core_name" + # add external leaves to the leaf_array + for element in "${external_leaves[@]}" + do + if [[ "$element" =~ "$core_name"" "L[0-9]+$ ]] + then + leaf_array+=("$element") + fi + done + for element in "${t[@]:1}" + do + if [ -n "$element" ]; then + leaf_array+=("$core_name ${element}") + fi + done + # Adding present leaves to temporary files + if [ ${#leaf_array[@]} != 0 ] + then + leaves="" + for element in "${leaf_array[@]}" + do + leaves="$leaves$element|" + done + leaves=`echo $leaves | sed -e 's/|$//'` + if [ ${core_name_size["$core_name"]} == 288 ] + then + generate_linksum_nocable $FILE_LINKSUM_SWD06 + else + generate_linksum_nocable $FILE_LINKSUM_SWD24 + fi + cat ${FILE_LINKSUM_NOCABLE} | cut -d ';' -f 10 | sort -u >> ${FILE_NODESWITCHES} + cat ${FILE_LINKSUM_NOCABLE} | cut -d ';' -f 13 | sort -u >> ${FILE_NODESWITCHES} + if [ $((n_detail & OUTPUT_GROUPS)) != 0 ] + then + cat ${FILE_LINKSUM_NOCABLE} | cut -d ';' -f 10 | sort -u >> "${core_name_group["$core_name"]}"/${FILE_NODESWITCHES} + cat ${FILE_LINKSUM_NOCABLE} | cut -d ';' -f 13 | sort -u >> "$core_group"/${FILE_NODESWITCHES} + fi + if [ $((n_detail & OUTPUT_RACKS)) != 0 ] + then + cat ${FILE_LINKSUM_NOCABLE} | cut -d ';' -f 10 | sort -u >> "${core_name_group["$core_name"]}"/"${core_name_rack["$core_name"]}"/${FILE_NODESWITCHES} + cat ${FILE_LINKSUM_NOCABLE} | cut -d ';' -f 13 | sort -u >> "${core_name_group["$core_name"]}"/"${core_name_rack["$core_name"]}"/${FILE_NODESWITCHES} + fi + fi + leaf_array=() + else + echo "opaxlattopology: Warning - Listed \"Present Leaves\" for Fully Populated Core. Ignoring this row" + fi + # End of Present Leaves information + else + cts_parse=3 + fi + ;; + + # Process Omited Spine + 5) + if echo "${t[0]}" | grep -e "$CORE_NAME" > /dev/null 2>&1 + then + core_name=`echo ${t[0]} | cut -d ':' -f 2` + if ! array_contains core[@] $core_name + then + echo "opaxlattopology: Error - No Core details found for $core_name, specified in \"Omitted Spines\" section" >&2 + exit 2 + fi + if array_contains partially_populated_core[@] $core_name + then + display_progress "Processing spines of partially populated Core:$core_name" + for element in "${t[@]:1}" + do + if [ -n "$element" ]; then + spine_array+=("$core_name ${element}") + fi + done + if [ ${#spine_array[@]} != 0 ] + then + for element in "${spine_array[@]}" + do + # Remove Spine from FILE_LINKSUM_NOCABLE and FILE_NODESWITCHES + sed -i "/$element/d" ${FILE_LINKSUM_NOCABLE} + sed -i "/$element/d" ${FILE_NODESWITCHES} + if [ $((n_detail & OUTPUT_GROUPS)) != 0 ] + then + sed -i "/$element/d" ${core_name_group["$core_name"]}/${FILE_LINKSUM_NOCABLE} + sed -i "/$element/d" ${core_name_group["$core_name"]}/${FILE_NODESWITCHES} + fi + if [ $((n_detail & OUTPUT_RACKS)) != 0 ] + then + sed -i "/$element/d" ${core_name_group["$core_name"]}/${core_name_rack["$core_name"]}/${FILE_LINKSUM_NOCABLE} + sed -i "/$element/d" ${core_name_group["$core_name"]}/${core_name_rack["$core_name"]}/${FILE_NODESWITCHES} + fi + done + fi + spine_array=() + else + echo "opaxlattopology: Warning - Listed \"Omitted Spines\" for Fully Populated Core. Ignoring this row" + fi + else + cts_parse=3 + fi + ;; + + esac # end of case $cts_parse in +done < <( cat $FILE_TOPOLOGY_LINKS | tr -d '\015' ) # End of while read ... do + +# Generate topology file(s) +display_progress "Generating $FILE_TOPOLOGY_OUT file(s)" + +# Generate top-level topology file +gen_topology "$fl_output_edge_leaf" "$fl_output_spine_leaf" + +if [ "$n_detail" != "0" ]; then + # iterate through groups + for (( iy=1 ; $iy<$group_cnt ; iy=$((iy+1)) )); do + + if [ -d "${tb_group[$iy]}" ]; then + cd ${tb_group[$iy]} + + if [ $((n_detail & OUTPUT_GROUPS)) != 0 ]; then + gen_topology "$fl_output_edge_leaf" "$fl_output_spine_leaf" + fi + + # iterate through racks + for (( ix=1 ; $ix<$rack_cnt ; ix=$((ix+1)) )); do + if [ -d "${tb_rack[$ix]}" ]; then + cd ${tb_rack[$ix]} + + if [ $((n_detail & OUTPUT_RACKS)) != 0 ]; then + gen_topology "$fl_output_edge_leaf" "$fl_output_spine_leaf" + fi + + # iterate through switches + if [ $((n_detail & OUTPUT_SWITCHES)) != 0 ]; then + for switch in *; do + if [ -d $switch ]; then + cd $switch + gen_topology "$fl_output_edge_leaf" "$fl_output_spine_leaf" + cd .. + fi # switch directory create + done # next switch + fi # switch detail + + cd .. # go up to group directory + fi # end rack topology create + done # next rack + cd .. # go up to base directory + fi # rack detail + done # next group + +fi # detail output + +if [ $OUT_FOLDER ]; then + cd $working_dir +fi + +display_progress "Done" +exit 0 diff --git a/IbaTools/opaxmlextract/Makefile b/IbaTools/opaxmlextract/Makefile new file mode 100644 index 0000000..c1ada61 --- /dev/null +++ b/IbaTools/opaxmlextract/Makefile @@ -0,0 +1,161 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** +# Makefile for opaxmlextract + +# Include Make Control Settings +include $(TL_DIR)/$(PROJ_FILE_DIR)/Makesettings.project + +#=============================================================================# +# Definitions: +#-----------------------------------------------------------------------------# + +# Name of SubProjects +DS_SUBPROJECTS = +# name of executable or downloadable image +EXECUTABLE = $(BUILDDIR)/opaxmlextract$(EXE_SUFFIX) +# list of sub directories to build +DIRS = +# C files (.c) +CFILES = \ + opaxmlextract.c \ + # Add more c files here +# C++ files (.cpp) +CCFILES = \ + # Add more cpp files here +# lex files (.lex) +LFILES = \ + # Add more lex files here +# archive library files (basename, $ARFILES will add MOD_LIB_DIR/prefix and suffix) +LIBFILES= +# Windows Resource Files (.rc) +RSCFILES = +# Windows IDL File (.idl) +IDLFILE = +# Windows Linker Module Definitions (.def) file for dll's +DEFFILE = +# targets to build during INCLUDES phase (add public includes here) +INCLUDE_TARGETS = \ + # Add more h hpp files here +# Non-compiled files +MISC_FILES = +# all source files +SOURCES = $(CFILES) $(CCFILES) $(LFILES) $(RSCFILES) $(IDLFILE) +# Source files to include in DSP File +DSP_SOURCES = $(INCLUDE_TARGETS) $(SOURCES) $(MISC_FILES) \ + $(RSCFILES) $(DEFFILE) $(MAKEFILE) +# all object files +OBJECTS = $(CFILES:.c=$(OBJ_SUFFIX)) $(CCFILES:.cpp=$(OBJ_SUFFIX)) \ + $(LFILES:.lex=$(OBJ_SUFFIX)) +RSCOBJECTS = $(RSCFILES:.rc=$(RES_SUFFIX)) +# targets to build during LIBS phase +LIB_TARGETS_IMPLIB = +LIB_TARGETS_ARLIB = # $(LIB_PREFIX)ResourceTest$(ARLIB_SUFFIX) +LIB_TARGETS_EXP = $(LIB_TARGETS_IMPLIB:$(ARLIB_SUFFIX)=$(EXP_SUFFIX)) +LIB_TARGETS_MISC = +# targets to build during CMDS phase +CMD_TARGETS_SHLIB = +CMD_TARGETS_EXE = $(EXECUTABLE) +CMD_TARGETS_MISC = opaextracterror opaextractperf opaextractperf2 \ + opaextractstat opaextractstat2 opaextractlink opamergeperf2 +# files to remove during clean phase +CLEAN_TARGETS_MISC = +CLEAN_TARGETS = $(OBJECTS) $(RSCOBJECTS) $(IDL_TARGETS) $(CLEAN_TARGETS_MISC) +# other files to remove during clobber phase +CLOBBER_TARGETS_MISC= +# sub-directory to install to within bin +BIN_SUBDIR = +# sub-directory to install to within include +INCLUDE_SUBDIR = + +# Additional Settings +#CLOCALDEBUG = User defined C debugging compilation flags [Empty] +#CCLOCALDEBUG = User defined C++ debugging compilation flags [Empty] +#CLOCAL = User defined C flags for compiling [Empty] +#CCLOCAL = User defined C++ flags for compiling [Empty] +#BSCLOCAL = User flags for Browse File Builder [Empty] +#DEPENDLOCAL = user defined makedepend flags [Empty] +#LINTLOCAL = User defined lint flags [Empty] +#LOCAL_INCLUDE_DIRS = User include directories to search for C/C++ headers [Empty] +#LDLOCAL = User defined C flags for linking [Empty] +#IMPLIBLOCAL = User flags for Object Lirary Manager [Empty] +#MIDLLOCAL = User flags for IDL compiler [Empty] +#RSCLOCAL = User flags for resource compiler [Empty] +#LOCALDEPLIBS = User libraries to include in dependencies [Empty] +#LOCALLIBS = User libraries to use when linking [Empty] +# (in addition to LOCALDEPLIBS) +#LOCAL_LIB_DIRS = User library directories for libpaths [Empty] + +CLOCAL=$(CIBACCESS) $(CPIE) +LOCALDEPLIBS=$(IBACCESS_USER_LIBS) Xml +LOCAL_INCLUDE_DIRS= +LOCALLIBS= + +ifneq "$(BUILD_TARGET_OS)" "VXWORKS" +LOCALLIBS+= expat +endif + +# Include Make Rules definitions and rules +include $(TL_DIR)/IbaTools/Makerules.module + +#=============================================================================# +# Overrides: +#-----------------------------------------------------------------------------# +#CCOPT = # C++ optimization flags, default lets build config decide +#COPT = # C optimization flags, default lets build config decide +#SUBSYSTEM = Subsystem to build for (none, console or windows) [none] +# (Windows Only) +#USEMFC = How Windows MFC should be used (none, static, shared, no_mfc) [none] +# (Windows Only) +#=============================================================================# + +#=============================================================================# +# Rules: +#-----------------------------------------------------------------------------# +# process Sub-directories +include $(TL_DIR)/Makerules/Maketargets.toplevel + +# build cmds and libs +include $(TL_DIR)/Makerules/Maketargets.build + +# install for includes, libs and cmds phases +include $(TL_DIR)/Makerules/Maketargets.install + +# install for stage phase +#include $(TL_DIR)/Makerules/Maketargets.stage +STAGE:: + $(VS)$(STAGE_INSTALL) $(STAGE_INSTALL_DIR_OPT) $(PROJ_STAGE_FASTFABRIC_DIR) $(EXECUTABLE) opaextracterror opaextractperf opaextractperf2 opaextractstat opaextractstat2 opaextractlink opamergeperf2 + +# Unit test execution +#include $(TL_DIR)/Makerules/Maketargets.runtest + +#=============================================================================# + +#=============================================================================# +# DO NOT DELETE THIS LINE -- make depend depends on it. +#=============================================================================# diff --git a/IbaTools/opaxmlextract/opaextracterror.sh b/IbaTools/opaxmlextract/opaextracterror.sh new file mode 100755 index 0000000..2330170 --- /dev/null +++ b/IbaTools/opaxmlextract/opaextracterror.sh @@ -0,0 +1,90 @@ +#!/bin/bash +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] + +# Run opareport with standard options and pipe output to opaxmlextract to extract +# error counts + +cmd=`basename $0` +Usage_full() +{ + echo >&2 + echo "Usage: ${cmd} [--help]|[opareport options]" >&2 + echo " --help - produce full help text" >&2 + echo " [opareport options] - options will be passed to opareport." >&2 + echo >&2 + echo "${cmd} is a front end to the opareport tool that generates" >&2 + echo "a report listing all or some of the errors in the current fabric." >&2 + echo "The output is in a CSV format suitable for importing into a spreadsheet or" >&2 + echo "parsed by other scripts." >&2 + echo >&2 + echo "for example:" >&2 + echo " List all the link errors in the fabric:" >&2 + echo " ${cmd}" >&2 + echo >&2 + echo " List all the link errors related to a switch named \"coresw1\":" >&2 + echo " ${cmd} -F \"node:coresw1\"" >&2 + echo >&2 + echo " List all the link errors for end-nodes:" >&2 + echo " ${cmd} -F \"nodetype:FI\"" >&2 + echo >&2 + echo " List all the link errors on the 2nd HFI's fabric of a multi-plane fabric:" >&2 + echo " ${cmd} -h 2" >&2 + echo >&2 + echo "See the man page for \"opareport\" for the full set of options." >&2 + echo "By design, the tool ignores \"-o/--output\" report option." >&2 + echo >&2 + exit 0 +} + +Usage() +{ + echo >&2 + echo "Usage: ${cmd} [--help]|[opareport options]" >&2 + echo " --help - produce full help text" >&2 + echo " [opareport options] - options will be passed to opareport." >&2 + echo >&2 +} + +if [ x"$1" = "x--help" ] +then + Usage_full +fi + +BINDIR=${BINDIR:-/usr/sbin} + + +$BINDIR/opareport -o comps -s -x -d 10 "$@" | $BINDIR/opaxmlextract -d \; -e NodeDesc -e SystemImageGUID -e PortNum -e LinkSpeedActive -e LinkWidthDnGradeTxActive -e LinkWidthDnGradeRxActive -e LinkQualityIndicator -e RcvSwitchRelayErrors -e LocalLinkIntegrityErrors -e RcvErrors -e ExcessiveBufferOverruns -e FMConfigErrors -e LinkErrorRecovery -e LinkDowned -e UncorrectableErrors -e RcvConstraintErrors -e XmitConstraintErrors -s Neighbor -s SMs +if [ $? -ne 0 ]; then + echo "${cmd}: Unable to get error report" >&2 + Usage + exit 1 +fi diff --git a/IbaTools/opaxmlextract/opaextractlink.sh b/IbaTools/opaxmlextract/opaextractlink.sh new file mode 100755 index 0000000..9b6e769 --- /dev/null +++ b/IbaTools/opaxmlextract/opaextractlink.sh @@ -0,0 +1,198 @@ +#!/bin/bash +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] + +# Run opareport -o links, then: +# Extract optional cable values, and values for both ports of each link +# Remove redundant information and combine cable and port information + +Usage_full() +{ + cmd=`basename $0` + echo >&2 + echo "Usage: ${cmd} [--help]|[opareport options]" >&2 + echo " --help - produce full help text" >&2 + echo " [opareport options] - options will be passed to opareport." >&2 + echo >&2 + echo "${cmd} is a front end to the opareport tool that generates" >&2 + echo "a report listing all or some of the links in the fabric." >&2 + echo "The output is in a CSV format suitable for importing into a spreadsheet or" >&2 + echo "parsed by other scripts." >&2 + echo >&2 + echo "for example:" >&2 + echo " List all the links in the fabric:" >&2 + echo " ${cmd}" >&2 + echo >&2 + echo " List all the links to a switch named \"coresw1\":" >&2 + echo " ${cmd} -F \"node:coresw1\"" >&2 + echo >&2 + echo " List all the links to end-nodes:" >&2 + echo " ${cmd} -F \"nodetype:FI\"" >&2 + echo >&2 + echo " List all the links on the 2nd HFI's fabric of a multi-plane fabric:" >&2 + echo " ${cmd} -h 2" >&2 + echo >&2 + echo "See the man page for \"opareport\" for the full set of options." >&2 + echo "By design, the tool ignores \"-o/--output\" report option." >&2 + echo >&2 + exit 0 +} + +if [[ "$1" == "--help" ]] +then + Usage_full +fi + + # opareport -o links generates XML output of this general form: + # + # .... + # .... + # + # ... cable information from topology.xml + # + # + # .. information about 1st port excluding its CableInfo + # + # + # .. information about 2nd port excluding its CableInfo + # + # + # .. information about the CableInfo for the cable between the two ports + # + # + # opaxmlextract produces the following CSV format on each line: + # 1 Link ID (CSV 1) LinkID + # 2 Link values (CSV 2-3) (Rate, LinkDetails) + # 3 Cable values (CSV 4-6) (CableLength, CableLabel, CableDetails) + # 5 CableInfo values (CSV 7-11) (DeviceTechShort, ... VendorRev) + # 2 Port values (CSV 12-13) (NodeDesc, PortNum) + # due to the nesting of tags, opaxmlextract will output the following + # All lines have LinkID and Rate and one set of Cable values, Cableinfo values, or Port Values + +## Main function: +function genReport() +{ + link1=0 + link2=0 + printHeader=1 + curLinkID="" + prevLinkID="" + tempresults="" + + while read line + do + curLinkID=`echo $line | cut -d \; -f 1` + + # When the LinkL:ID changes, we're now reading a line of data from a new link record. + # We can print the previous link record now that we know it is complete. + if [ "$curLinkID" != "$prevLinkID" ] + then + # Display the header the first time through + if [ $printHeader -eq 1 ] + then + echo "Rate;LinkDetails;CableLength;CableLabel;CableDetails;DeviceTechShort;CableInfo.Length;CableInfo.VendorName;CableInfo.VendorPN;CableInfo.VendorRev;Port.NodeDesc;Port.PortNum;Port.NodeDesc;Port.PortNum" + printHeader=0 + fi + + # Display the link line. + echo $tempresults + + # Reset for the next set of data + link1=0 + link2=0 + RateStr="" + LinkDetailsStr="" + CableValuesStr=";;" + CableInfoValuesStr=";;;;" + Port1ValuesStr=";" + Port2ValuesStr=";" + + prevLinkID=$curLinkID + fi + + if [ "$RateStr" == "" ] + then + RateStr=`echo $line | cut -d \; -f 2` + fi + + if [ "$LinkDetailsStr" == "" ] + then + LinkDetailsStr=`echo $line | cut -d \; -f 3` + fi + + if [ "$CableValuesStr" == ";;" ] + then + CableValuesStr=`echo $line | cut -d \; -f 4-6` + fi + + if [ "$CableInfoValuesStr" == ";;;;" ] + then + CableInfoValuesStr=`echo $line | cut -d \; -f 7-11` + tempresults=$RateStr";"$LinkDetailsStr";"$CableValuesStr";"$CableInfoValuesStr";"$Port1ValuesStr";"$Port2ValuesStr + fi + + if [ $link1 -eq 0 ] + then + if [ "$Port1ValuesStr" == ";" ] + then + Port1ValuesStr=`echo $line | cut -d \; -f 12-13` + fi + + if [ "$Port1ValuesStr" != ";" ] + then + link1=1 + fi + elif [ $link2 -eq 0 ] + then + if [ "$Port2ValuesStr" == ";" ] + then + Port2ValuesStr=`echo $line | cut -d \; -f 12-13` + fi + + if [ "$Port2ValuesStr" != ";" ] + then + link2=1 + tempresults=$RateStr";"$LinkDetailsStr";"$CableValuesStr";"$CableInfoValuesStr";"$Port1ValuesStr";"$Port2ValuesStr + fi + fi + done < <(/usr/sbin/opareport -x -Q -o links "$@" -d 3 | \ + /usr/sbin/opaxmlextract -H -d \; -e Link:id -e Rate -e LinkDetails -e CableLength \ + -e CableLabel -e CableDetails -e DeviceTechShort -e CableInfo.Length \ + -e CableInfo.VendorName -e CableInfo.VendorPN -e CableInfo.VendorRev \ + -e Port.NodeDesc -e Port.PortNum) + + + # Now print the final link record + echo $tempresults +} + +genReport "$@" +exit 0 diff --git a/IbaTools/opaxmlextract/opaextractperf.sh b/IbaTools/opaxmlextract/opaextractperf.sh new file mode 100755 index 0000000..d63b7ae --- /dev/null +++ b/IbaTools/opaxmlextract/opaextractperf.sh @@ -0,0 +1,88 @@ +#!/bin/bash +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] + +# Run opareport with standard options and pipe output to opaxmlextract to extract +# performance counts + + + +Usage_full() +{ + echo "Usage: ${cmd} [opareport options]" >&2 + echo " or" >&2 + echo " ${cmd} --help" >&2 + echo " --help - produce full help text." >&2 + echo " opareport options - options will be passed to opareport." >&2 + echo >&2 + echo "${cmd} provides a report of all performance counters in a " >&2 + echo "CVS format suitable for importing into a spreadsheet or parsed by" >&2 + echo "other scripts." >&2 + echo >&2 + echo "for example:" >&2 + echo " ${cmd}" >&2 + echo >&2 + echo " ${cmd} -h 1 -p 2" >&2 + echo >&2 + echo "See the man page for \"opareport\" for the full set of options.">&2 + echo "By design, the tool ignores \"-o/--output\" report option." >&2 + echo >&2 + exit 0 +} + +Usage() +{ + echo "Usage: ${cmd} [opareport options]" >&2 + echo " or" >&2 + echo " ${cmd} --help" >&2 + echo " --help - produce full help text." >&2 + echo " opareport options - options will be passed to opareport." >&2 + echo "for example:" >&2 + echo " ${cmd}" >&2 + echo >&2 + exit 2 +} + +## Main function + +cmd=`basename $0` +if [ x"$1" = "x--help" ] +then + Usage_full +fi + +/usr/sbin/opareport -o comps -s -x -d 10 "$@" | /usr/sbin/opaxmlextract -d \; -e NodeDesc -e SystemImageGUID -e PortNum -e LinkSpeedActive -e LinkWidthDnGradeTxActive -e LinkWidthDnGradeRxActive -e XmitDataMB -e XmitData -e XmitPkts -e MulticastXmitPkts -e RcvDataMB -e RcvData -e RcvPkts -e MulticastRcvPkts -e XmitWait -e CongDiscards -e XmitTimeCong -e MarkFECN -e RcvFECN -e RcvBECN -e RcvBubble -e XmitWastedBW -e XmitWaitData -e LinkQualityIndicator -e LocalLinkIntegrityErrors -e RcvErrors -e ExcessiveBufferOverruns -e LinkErrorRecovery -e LinkDowned -e UncorrectableErrors -e FMConfigErrors -e XmitConstraintErrors -e RcvConstraintErrors -e RcvSwitchRelayErrors -e XmitDiscards -e RcvRemotePhysicalErrors -s Neighbor -s SMs +if [ $? -ne 0 ]; then + echo "${cmd}: Unable to get performance report" >&2 + Usage + exit 1 +fi +exit 0 diff --git a/IbaTools/opaxmlextract/opaextractperf2.sh b/IbaTools/opaxmlextract/opaextractperf2.sh new file mode 100755 index 0000000..bfefc4b --- /dev/null +++ b/IbaTools/opaxmlextract/opaextractperf2.sh @@ -0,0 +1,122 @@ +#!/bin/bash +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2019, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] + +# Run opareport with standard options and pipe output to opaxmlextract to +# extract all performance counters into a csv file format +tempfile="$(mktemp)" +trap "rm -f $tempfile; exit 1" SIGHUP SIGTERM SIGINT +trap "rm -f $tempfile" EXIT + + +Usage_full() +{ + echo "Usage: ${cmd} [opareport options]" >&2 + echo " or" >&2 + echo " ${cmd} --help" >&2 + echo " --help - produce full help text." >&2 + echo " opareport options - options will be passed to opareport." >&2 + echo >&2 + echo "${cmd} provides a report of all performance counters in a " >&2 + echo "CSV format suitable for importing into a spreadsheet or parsed by" >&2 + echo "other scripts." >&2 + echo >&2 + echo "for example:" >&2 + echo " ${cmd}" >&2 + echo >&2 + echo " ${cmd} -h 1 -p 2" >&2 + echo >&2 + echo "See the man page for \"opareport\" for the full set of options.">&2 + echo "Do no use \"-o/--output\" report option." >&2 + echo >&2 + exit 0 +} + +Usage() +{ + echo "Usage: ${cmd} [opareport options]" >&2 + echo " or" >&2 + echo " ${cmd} --help" >&2 + echo " --help - produce full help text." >&2 + echo " opareport options - options will be passed to opareport." >&2 + echo "for example:" >&2 + echo " ${cmd}" >&2 + echo >&2 + exit 2 +} + +## Main function + +cmd=`basename $0` +if [ x"$1" = "x--help" ] +then + Usage_full +fi + +IFS=';' +/usr/sbin/opareport -o comps -s -x -Q -d 10 "$@" > $tempfile +if [ -s $tempfile ] +then + # minor reformatting of header line to condense column names + echo "NodeDesc;NodeType;NodeGUID;PortNum;nNodeDesc;nNodeType;nNodeGUID;nPortNum;LinkSpeedActive;LinkWidthDnGradeTxActive;LinkWidthDnGradeRxActive;XmitDataMB;XmitData;XmitPkts;MulticastXmitPkts;RcvDataMB;RcvData;RcvPkts;MulticastRcvPkts;XmitWait;CongDiscards;XmitTimeCong;MarkFECN;RcvFECN;RcvBECN;RcvBubble;XmitWastedBW;XmitWaitData;LinkQualityIndicator;LocalLinkIntegrityErrors;RcvErrors;ExcessiveBufferOverruns;LinkErrorRecovery;LinkDowned;UncorrectableErrors;FMConfigErrors;XmitConstraintErrors;RcvConstraintErrors;RcvSwitchRelayErrors;XmitDiscards;RcvRemotePhysicalErrors" + cat $tempfile | /usr/sbin/opaxmlextract -H -d \; -e Node.NodeDesc -e Node.NodeType -e Node.NodeGUID -e PortInfo.PortNum -e Neighbor.Port.NodeDesc -e Neighbor.Port.NodeType -e Neighbor.Port.NodeGUID -e Neighbor.Port.PortNum -e LinkSpeedActive -e LinkWidthDnGradeTxActive -e LinkWidthDnGradeRxActive -e XmitDataMB -e XmitData -e XmitPkts -e MulticastXmitPkts -e RcvDataMB -e RcvData -e RcvPkts -e MulticastRcvPkts -e XmitWait -e CongDiscards -e XmitTimeCong -e MarkFECN -e RcvFECN -e RcvBECN -e RcvBubble -e XmitWastedBW -e XmitWaitData -e LinkQualityIndicator -e LocalLinkIntegrityErrors -e RcvErrors -e ExcessiveBufferOverruns -e LinkErrorRecovery -e LinkDowned -e UncorrectableErrors -e FMConfigErrors -e XmitConstraintErrors -e RcvConstraintErrors -e RcvSwitchRelayErrors -e XmitDiscards -e RcvRemotePhysicalErrors -s SMs | \ + while read NodeDesc NodeType NodeGUID PortNum nNodeDesc nNodeType nNodeGUID nPortNum LinkSpeedActive LinkWidthDnGradeTxActive LinkWidthDnGradeRxActive XmitDataMB XmitData XmitPkts MulticastXmitPkts RcvDataMB RcvData RcvPkts MulticastRcvPkts XmitWait CongDiscards XmitTimeCong MarkFECN RcvFECN RcvBECN RcvBubble XmitWastedBW XmitWaitData LinkQualityIndicator LocalLinkIntegrityErrors RcvErrors ExcessiveBufferOverruns LinkErrorRecovery LinkDowned UncorrectableErrors FMConfigErrors XmitConstraintErrors RcvConstraintErrors RcvSwitchRelayErrors XmitDiscards RcvRemotePhysicalErrors + do + # output will be: + # for switch port 0 + # just 1 line, no neighbor + # for other links + # 1st line with neighbor + # 2nd line with most fields except neighbor fields + # both lines will have NodeDesc, NodeType, NodeGUID, PortNum + lineno=$(($lineno + 1)) + if [ x"$nNodeGUID" = x ] + then + # must be a port without a neighbor (switch port 0) + echo "$NodeDesc;$NodeType;$NodeGUID;$PortNum;$nNodeDesc;$nNodeType;$nNodeGUID;$nPortNum;$LinkSpeedActive;$LinkWidthDnGradeTxActive;$LinkWidthDnGradeRxActive;$XmitDataMB;$XmitData;$XmitPkts;$MulticastXmitPkts;$RcvDataMB;$RcvData;$RcvPkts;$MulticastRcvPkts;$XmitWait;$CongDiscards;$XmitTimeCong;$MarkFECN;$RcvFECN;$RcvBECN;$RcvBubble;$XmitWastedBW;$XmitWaitData;$LinkQualityIndicator;$LocalLinkIntegrityErrors;$RcvErrors;$ExcessiveBufferOverruns;$LinkErrorRecovery;$LinkDowned;$UncorrectableErrors;$FMConfigErrors;$XmitConstraintErrors;$RcvConstraintErrors;$RcvSwitchRelayErrors;$XmitDiscards;$RcvRemotePhysicalErrors" + else + # port with a neighbor will have a second line + read NodeDesc_2 NodeType_2 NodeGUID_2 PortNum_2 nNodeDesc_2 nNodeType_2 nNodeGUID_2 nPortNum_2 LinkSpeedActive_2 LinkWidthDnGradeTxActive_2 LinkWidthDnGradeRxActive_2 XmitDataMB_2 XmitData_2 XmitPkts_2 MulticastXmitPkts_2 RcvDataMB_2 RcvData_2 RcvPkts_2 MulticastRcvPkts_2 XmitWait_2 CongDiscards_2 XmitTimeCong_2 MarkFECN_2 RcvFECN_2 RcvBECN_2 RcvBubble_2 XmitWastedBW_2 XmitWaitData_2 LinkQualityIndicator_2 LocalLinkIntegrityErrors_2 RcvErrors_2 ExcessiveBufferOverruns_2 LinkErrorRecovery_2 LinkDowned_2 UncorrectableErrors_2 FMConfigErrors_2 XmitConstraintErrors_2 RcvConstraintErrors_2 RcvSwitchRelayErrors_2 XmitDiscards_2 RcvRemotePhysicalErrors_2 + if [ x"$NodeGUID" != x"$NodeGUID_2" -o x"$PortNum" != x"$PortNum_2" ] + then + echo "line: $lineno: Out of synchronization" >&2 + fi + echo "$NodeDesc;$NodeType;$NodeGUID;$PortNum;$nNodeDesc;$nNodeType;$nNodeGUID;$nPortNum;$LinkSpeedActive_2;$LinkWidthDnGradeTxActive_2;$LinkWidthDnGradeRxActive_2;$XmitDataMB_2;$XmitData_2;$XmitPkts_2;$MulticastXmitPkts_2;$RcvDataMB_2;$RcvData_2;$RcvPkts_2;$MulticastRcvPkts_2;$XmitWait_2;$CongDiscards_2;$XmitTimeCong_2;$MarkFECN_2;$RcvFECN_2;$RcvBECN_2;$RcvBubble_2;$XmitWastedBW_2;$XmitWaitData_2;$LinkQualityIndicator_2;$LocalLinkIntegrityErrors_2;$RcvErrors_2;$ExcessiveBufferOverruns_2;$LinkErrorRecovery_2;$LinkDowned_2;$UncorrectableErrors_2;$FMConfigErrors_2;$XmitConstraintErrors_2;$RcvConstraintErrors_2;$RcvSwitchRelayErrors_2;$XmitDiscards_2;$RcvRemotePhysicalErrors_2" + fi + done + res=0 +else + echo "${cmd}: Unable to get performance report" >&2 + Usage + res=1 +fi +rm -rf $tempfile +exit $res diff --git a/IbaTools/opaxmlextract/opaextractstat.sh b/IbaTools/opaxmlextract/opaextractstat.sh new file mode 100755 index 0000000..405374f --- /dev/null +++ b/IbaTools/opaxmlextract/opaextractstat.sh @@ -0,0 +1,229 @@ +#!/bin/bash +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2018, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] + +# Run opareport -o errors with topology XML, then: +# Extract values (including port statistics) for both ports of each link +# Remove redundant information for each link and combine link port information + + +## Local functions: + +# Usage() +# +# Description: +# Output information about program usage and parameters +# +# Inputs: +# none +# +# Outputs: +# Information about program usage and parameters + + + +usage() +{ + echo "Usage: ${cmd} topology_file [opareport options]" >&2 + echo " or ${cmd} --help" >&2 + echo " --help - produce full help text" >&2 + echo " [opareport options] - options will be passed to opareport." >&2 + exit 2 +} + +Usage_full() +{ + echo >&2 + echo "Usage: ${cmd} topology_file [opareport options]" >&2 + echo " or ${cmd} --help" >&2 + echo " --help - produce full help text" >&2 + echo " [opareport options] - options will be passed to opareport." >&2 + echo >&2 + echo "${cmd} is a front end to the opareport and opaxmlextract tools that" >&2 + echo "performs an error analysis of a fabric and provides augmented information" >&2 + echo "from a topology file. Report provides cable information as well" >&2 + echo "as symbol error count." >&2 + echo "The output is in a CSV format suitable for importing into a spreadsheet or" >&2 + echo "parsed by other scripts." >&2 + echo >&2 + echo "for example:" >&2 + echo " ${cmd} topology_file" + echo >&2 + echo " ${cmd} topology_file -c my_opamon.conf" + echo >&2 + echo "See the man page for \"opareport\" for the full set of options." >&2 + echo "By design, the tool ignores \"-o/--output\" report option." >&2 + echo >&2 + exit 0 + +} + +## Main function: + +cmd=`basename $0` +if [ x"$1" = "x--help" ] +then + Usage_full +fi + +if [[ $# -lt 1 || "$1" == -* ]] +then + usage +fi + +# NOTE: opareport -o errors generates XML output of this general form: +# +# .... +# .... +# +# ... cable information from topology.xml +# +# +# .. information about 1st port excluding its CableInfo +# +# +# .. information about 2nd port excluding its CableInfo +# +# +# .. information about the CableInfo for the cable between the two ports +# +# + # opaxmlextract produces the following CSV format on each line: + # 1 Link ID (CSV 1) LinkID + # 2 Link values (CSV 2-3) (Rate, LinkDetails) + # 3 Cable values (CSV 4-6) (CableLength, CableLabel, CableDetails) + # 3 Port values (CSV 7-9) (NodeDesc, PortNum, LinkQualityIndicator) + # due to the nesting of tags, opaxmlextract will output the following + # All lines have LinkID and Rate and one set of Cable values or Port Values + +# Combine 2 ports for each link onto 1 line, removing redundant Link and Cable values +link1=0 +link2=0 +printHeader=1 +curLinkID="" +prevLinkID="" +RateStr="" +LinkDetailsStr="" +CableValuesStr=";;" +Port1ValuesStr=";;" +Port2ValuesStr=";;" + +header="Rate;LinkDetails;CableLength;CableLabel;CableDetails;Port.NodeDesc;Port.PortNum;LinkQualityIndicator.Value;Port.NodeDesc;Port.PortNum;LinkQualityIndicator.Value" + +while read line +do + + curLinkID=`echo $line | cut -d \; -f 1` + + # When Link:ID changes, print previous link and start new one + if [ "$curLinkID" != "$prevLinkID" ] + then + # Display header first time + if [ $printHeader -eq 1 ] + then + echo $header + printHeader=0 + fi + + # Display the previous link before starting this new one + if [ "$prevLinkID" != "" ] + then + echo $RateStr";"$LinkDetailsStr";"$CableValuesStr";"$Port1ValuesStr";"$Port2ValuesStr + fi + + # Reset for the next set of data + link1=0 + link2=0 + RateStr="" + LinkDetailsStr="" + CableValuesStr=";;" + Port1ValuesStr=";;" + Port2ValuesStr=";;" + prevLinkID=$curLinkID + fi + + if [ "$RateStr" == "" ] + then + RateStr=`echo $line | cut -d \; -f 2` + fi + + if [ "$LinkDetailsStr" == "" ] + then + LinkDetailsStr=`echo $line | cut -d \; -f 3` + fi + + if [ "$CableValuesStr" == ";;" ] + then + CableValuesStr=`echo $line | cut -d \; -f 4-6` + fi + + if [ $link1 -eq 0 ] + then + if [ "$Port1ValuesStr" == ";;" ] + then + Port1ValuesStr=`echo $line | cut -d \; -f 7-` + fi + if [ "$Port1ValuesStr" != ";;" ] + then + link1=1 + fi + elif [ $link2 -eq 0 ] + then + if [ "$Port2ValuesStr" == ";;" ] + then + Port2ValuesStr=`echo $line | cut -d \; -f 7-` + fi + if [ "$Port2ValuesStr" != ";;" ] + then + link2=1 + fi + fi + +done < <(/usr/sbin/opareport -x -Q -d 10 -s -o errors -T "$@" | \ + /usr/sbin/opaxmlextract -H -d \; -e Link:id -e Rate -e LinkDetails -e CableLength \ + -e CableLabel -e CableDetails -e Port.NodeDesc -e Port.PortNum \ + -e LinkQualityIndicator.Value) + +if [ $printHeader -eq 1 ] +then + # No links displayed, still print header + echo $header +fi + + +# print the last link record +if [ "$prevLinkID" != "" ] +then + echo $RateStr";"$LinkDetailsStr";"$CableValuesStr";"$Port1ValuesStr";"$Port2ValuesStr +fi + +exit 0 + diff --git a/IbaTools/opaxmlextract/opaextractstat2.sh b/IbaTools/opaxmlextract/opaextractstat2.sh new file mode 100755 index 0000000..bdf8b4c --- /dev/null +++ b/IbaTools/opaxmlextract/opaextractstat2.sh @@ -0,0 +1,224 @@ +#!/bin/bash +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2018, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] + +# Run opareport -o errors with topology XML, then: +# Extract values (including port statistics) for both ports of each link +# Remove redundant information for each link and combine link port information + +## Local functions: + +# Usage() +# +# Description: +# Output information about program usage and parameters +# +# Inputs: +# none +# +# Outputs: +# Information about program usage and parameters + + + +usage() +{ + echo "Usage: ${cmd} topology_file [opareport options]" >&2 + echo " or ${cmd} --help" >&2 + echo " --help - produce full help text" >&2 + echo " [opareport options] - options will be passed to opareport." >&2 + echo >&2 + exit 2 +} + +Usage_full() +{ + echo "Usage: ${cmd} topology_file [opareport options]" >&2 + echo " or ${cmd} --help" >&2 + echo " --help - produce full help text" >&2 + echo " [opareport options] - options will be passed to opareport." >&2 + echo >&2 + echo "${cmd} is a front end to the opareport and opaxmlextract tools that" >&2 + echo "performs an error analysis of a fabric and provides augmented information" >&2 + echo "from a topology file including all error counters." >&2 + echo "The output is in a CSV format suitable for importing into a spreadsheet or" >&2 + echo "parsed by other scripts." >&2 + echo >&2 + echo "for example" >&2 + echo " ${cmd} topology_file" >&2 + echo >&2 + echo " ${cmd} topology_file -c my_opamon.conf" >&2 + echo >&2 + echo "See the man page for \"opareport\" for the full set of options." >&2 + echo "By design, the tool ignores \"-o/--output\" report option." >&2 + echo >&2 + exit 0 + +} + +## Main function: + +cmd=`basename $0` +if [ x"$1" = "x--help" ] +then + Usage_full +fi + +if [[ $# -lt 1 || "$1" == -* ]] +then + usage +fi + + +# NOTE: opareport -o errors generates XML output of this general form: +# +# .... +# .... +# +# ... cable information from topology.xml +# +# +# .. information about 1st port excluding its CableInfo +# +# +# .. information about 2nd port excluding its CableInfo +# +# +# .. information about the CableInfo for the cable between the two ports +# +# + # opaxmlextract produces the following CSV format on each line: + # 1 Link ID (CSV 1) LinkID + # 3 Link values (CSV 2-4) (Rate, Internal, LinkDetails) + # 3 Cable values (CSV 5-7) (CableLength, CableLabel, CableDetails) + # Port values (CSV 8-) (port details and error stats) + # due to the nesting of tags, opaxmlextract will output the following + # All lines have LinkID and Rate and one set of Cable values or Port Values + +# Combine 2 ports for each link onto 1 line, removing redundant Link and Cable values +EMPTY_PORT_STR=";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;" +link1=0 +link2=0 +printHeader=1 +curLinkID="" +prevLinkID="" +RateDetailsStr=";;" +CableValuesStr=";;" +Port1ValuesStr=$EMPTY_PORT_STR +Port2ValuesStr=$EMPTY_PORT_STR +while read line +do + curLinkID=`echo $line | cut -d \; -f 1` + + # When Link_ID changes, print previous link and start new one + if [ "$curLinkID" != "$prevLinkID" ] + then + # Display header first time + if [ $printHeader -eq 1 ] + then + echo `echo $line | cut -d \; -f 2-`";"`echo $line | cut -d \; -f 8-` + printHeader=0 + continue + fi + + # Display the previous link before starting this new one + if [ "$prevLinkID" != "" ] + then + echo $RateDetailsStr";"$CableValuesStr";"$Port1ValuesStr";"$Port2ValuesStr + fi + + # Reset for the next set of data + link1=0 + link2=0 + RateDetailsStr=";;" + CableValuesStr=";;" + Port1ValuesStr=$EMPTY_PORT_STR + Port2ValuesStr=$EMPTY_PORT_STR + prevLinkID=$curLinkID + fi + + if [ "$RateDetailsStr" == ";;" ] + then + RateDetailsStr=`echo $line | cut -d \; -f 2-4` + fi + + if [ "$CableValuesStr" == ";;" ] + then + CableValuesStr=`echo $line | cut -d \; -f 5-7` + fi + + if [ $link1 -eq 0 ] + then + if [ "$Port1ValuesStr" == "$EMPTY_PORT_STR" ] + then + Port1ValuesStr=`echo $line | cut -d \; -f 8-` + fi + if [ "$Port1ValuesStr" != "$EMPTY_PORT_STR" ] + then + link1=1 + fi + elif [ $link2 -eq 0 ] + then + if [ "$Port2ValuesStr" == "$EMPTY_PORT_STR" ] + then + Port2ValuesStr=`echo $line | cut -d \; -f 8-` + fi + if [ "$Port2ValuesStr" != "$EMPTY_PORT_STR" ] + then + link2=1 + fi + fi + +done < <(/usr/sbin/opareport -x -Q -d 10 -s -o errors -T "$@" | \ + /usr/sbin/opaxmlextract -d \; -e Link:id -e Rate -e Internal -e LinkDetails \ + -e CableLength -e CableLabel -e CableDetails -e Port.NodeGUID \ + -e Port.PortGUID -e Port.PortNum -e Port.NodeType -e Port.NodeDesc \ + -e Port.PortDetails \ + -e XmitDataValue -e XmitPktsValue -e PortMulticastXmitPktsValue \ + -e RcvDataValue -e RcvPktsValue -e MulticastRcvPktsValue \ + -e XmitWaitValue -e CongDiscardsValue -e XmitTimeCongValue \ + -e MarkFECNValue -e RcvFECNValue -e RcvBECNValue \ + -e RcvBubbleValue -e XmitWastedBWValue -e XmitWaitDataValue \ + -e LinkQualityIndicatorValue -e LocalLinkIntegrityErrorsValue \ + -e RcvErrorsValue -e ExcessiveBufferOverrunsValue \ + -e LinkErrorRecoveryValue -e LinkDownedValue -e UncorrectableErrorsValue \ + -e FMConfigErrorsValue -e XmitConstraintErrorsValue \ + -e RcvConstraintErrorsValue -e RcvSwitchRelayErrorsValue \ + -e XmitDiscardsValue -e RcvRemotePhysicalErrorsValue) + +# print the last link record +if [ "$prevLinkID" != "" ] +then + echo $RateDetailsStr";"$CableValuesStr";"$Port1ValuesStr";"$Port2ValuesStr +fi + +exit 0 + diff --git a/IbaTools/opaxmlextract/opamergeperf2.sh b/IbaTools/opaxmlextract/opamergeperf2.sh new file mode 100755 index 0000000..0ec0bbc --- /dev/null +++ b/IbaTools/opaxmlextract/opamergeperf2.sh @@ -0,0 +1,243 @@ +#!/bin/bash +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2019, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] + +# take output from two runs of opaextractperf2 and merge them by computing +# differences in performance counters +tempfile="$(mktemp)" +trap "rm -f ${tempfile}.prefix1 ${tempfile}.prefix2; exit 1" SIGHUP SIGTERM SIGINT +trap "rm -f ${tempfile}.prefix1 ${tempfile}.prefix2" EXIT + + +Usage_full() +{ + echo "Usage: ${cmd} before.csv after.csv" >&2 + echo " or" >&2 + echo " ${cmd} --help" >&2 + echo " --help - produce full help text." >&2 + echo " before.csv - output from a opaextractperf2 run" >&2 + echo " after.csv - output from a opaextractperf2 run" >&2 + echo >&2 + echo "${cmd} merges output from two opaextactperf2 runs from the same fabric" >&2 + echo "Counters for matching links will be computed (before subtracted from after)" >&2 + echo "and a CSV file equivalent to opaextractperf2's output format will be generated" >&2 + echo "suitable for importing into a spreadsheet or parsing by other scripts." >&2 + echo >&2 + echo "The before.csv and after.csv input files must be generated from the same" >&2 + echo "fabric, with before.csv containing counters prior to after.csv." >&2 + echo "Both files must have been generated to contain the running counters without" >&2 + echo "any counter clears between before.csv and after.csv and without using any" >&2 + echo "interval options to opareport which might report delta counters as" >&2 + echo "opposed to running counters, such as opareport -i" >&2 + echo "or opareport with both --begin and --end options." >&2 + echo >&2 + echo "for example:" >&2 + echo " ${cmd} before.csv after.csv > delta.csv" >&2 + echo >&2 + exit 0 +} + +Usage() +{ + echo "Usage: ${cmd} before.csv after.csv" >&2 + echo " or" >&2 + echo " ${cmd} --help" >&2 + echo " --help - produce full help text." >&2 + echo " before.csv - output from a opaextractperf2 run" >&2 + echo " after.csv - output from a opaextractperf2 run" >&2 + echo >&2 + echo "for example:" >&2 + echo " ${cmd} before.csv after.csv > delta.csv" >&2 + echo >&2 + exit 2 +} + +## Main function +res=0 + +cmd=`basename $0` +if [ x"$1" = "x--help" ] +then + Usage_full +fi + +if [ "$#" != 2 ] +then + Usage +fi + +f1="$1" +f2="$2" +if [ ! -e "$f1" ] +then + echo "$f1: Not Found" >&2 + Usage +fi +if [ ! -e "$f2" ] +then + echo "$f2: Not Found" >&2 + Usage +fi + +IFS=';' + +# omit heading line +# add sequencing number and line number before desc;type;guid;port so same +# device in each file will sort next to eachother and f1 sorts before f2. +nl -s';' "$f1"|tail -n+2 | sed -e 's/^ */1;/'|sort --field-separator=';' --key='5,6' > ${tempfile}.prefix1 +nl -s';' "$f2"|tail -n+2 | sed -e 's/^ */2;/'|sort --field-separator=';' --key='5,6' > ${tempfile}.prefix2 +# some debug code which can help identify nodes which are not in both files +#cut -f3-6 -d';' ${tempfile}.prefix1 > ${tempfile}.nodes1 +#cut -f3-6 -d';' ${tempfile}.prefix2 > ${tempfile}.nodes2 +#if ! diff ${tempfile}.nodes1 ${tempfile}.nodes2 > /dev/null +#then +# echo "$cmd: Warning: node list mismatch" >&2 +# #diff -c ${tempfile}.nodes1 ${tempfile}.nodes2 | head -20 +#fi + +IFS=';' +{ +# output heading +head -1 "$f1" +# compute counter differences f2 - f1 +use_2=n # do _2 variables potentially have 1st line ("1") for a port +# sort by guid;port then prefix, this puts same ports next to eachother with +# line from f1 before line from f2 +# the loop must handle cases where a device appears only in f1 or f2 +# as well as where the neighbor to a device has changed between f1 and f2 +# in a stable fabric these will not happen. However in a fabric with a few +# bad links, devices offline or where cables have been moved, this can happen +( cat ${tempfile}.prefix1 ${tempfile}.prefix2|sort --field-separator=';' --key='5,6' --key '1,1'; echo "END" ) | \ + while read num_1 lineno_1 NodeDesc_1 NodeType_1 NodeGUID_1 PortNum_1 nNodeDesc_1 nNodeType_1 nNodeGUID_1 nPortNum_1 LinkSpeedActive_1 LinkWidthDnGradeTxActive_1 LinkWidthDnGradeRxActive_1 XmitDataMB_1 XmitData_1 XmitPkts_1 MulticastXmitPkts_1 RcvDataMB_1 RcvData_1 RcvPkts_1 MulticastRcvPkts_1 XmitWait_1 CongDiscards_1 XmitTimeCong_1 MarkFECN_1 RcvFECN_1 RcvBECN_1 RcvBubble_1 XmitWastedBW_1 XmitWaitData_1 LinkQualityIndicator_1 LocalLinkIntegrityErrors_1 RcvErrors_1 ExcessiveBufferOverruns_1 LinkErrorRecovery_1 LinkDowned_1 UncorrectableErrors_1 FMConfigErrors_1 XmitConstraintErrors_1 RcvConstraintErrors_1 RcvSwitchRelayErrors_1 XmitDiscards_1 RcvRemotePhysicalErrors_1 +do + if [ x"$num_1" = x"END" ] + then + # normal end of file + break + fi + if ! [[ x"$RcvRemotePhysicalErrors_1" =~ ^x[0-9]+$ ]] + then + # lines with insufficient columns, extra columns or non-numeric in + # last column will fail the test. To balance performance and input + # checking we only check the last column since invalid input files + # will typically have the wrong number of columns + if [ x"$num_1" = x"1" ] + then + echo "$cmd: Invalid input line: $lineno_1 file: $f1" >&2 + else + echo "$cmd: Invalid input line: $lineno_1 file: $f2" >&2 + fi + exit 1 + fi + if [ x"$num_1" = x"2" ] + then + #echo "process num_1=2" >&2 + if [ "$use_2" != y ] + then + # "2" without a preceeding "1", skip line just read into _1 + echo "$cmd: Warning: skipping unmatched line $lineno_1 in after: $NodeDesc_1;$NodeType_1;$NodeGUID_1;$PortNum_1" >&2 + else + # _2 has our "1", _1 has our "2" + if [ x"$NodeGUID_1" != x"$NodeGUID_2" -o x"$PortNum_1" != x"$PortNum_2" ] + then + # got a "1" followed by a "2" and they don't match, skip both + echo "$cmd: Warning: skipping unmatched line $lineno_2 in before: $NodeDesc_2;$NodeType_2;$NodeGUID_2;$PortNum_2" >&2 + echo "$cmd: Warning: skipping unmatched line $lineno_1 in after: $NodeDesc_1;$NodeType_1;$NodeGUID_1;$PortNum_1" >&2 + elif [ x"$nNodeGUID_1" != x"$nNodeGUID_2" -o x"$nPortNum_1" != x"$nPortNum_2" ] + then + # we got a "1" followed by "2", however neighbor changed + echo "$cmd: Warning: skipping changed line $lineno_2 in before: $NodeDesc_2;$NodeType_2;$NodeGUID_2;$PortNum_2;$nNodeDesc_2;$nNodeType_2;$nNodeGUID_2;$nPortNum_2" >&2 + echo "$cmd: Warning: skipping changed line $lineno_1 in after: $NodeDesc_1;$NodeType_1;$NodeGUID_1;$PortNum_1;$nNodeDesc_1;$nNodeType_1;$nNodeGUID_1;$nPortNum_1" >&2 + else + #echo "process num_1=2 use_2" >&2 + # use _2 as before and _1 as after when compute delta + # for fields not subtracted, show after (_1) as more recent + echo "$NodeDesc_1;$NodeType_1;$NodeGUID_1;$PortNum_1;$nNodeDesc_1;$nNodeType_1;$nNodeGUID_1;$nPortNum_1;$LinkSpeedActive_1;$LinkWidthDnGradeTxActive_1;$LinkWidthDnGradeRxActive_1;$(($XmitDataMB_1 - $XmitDataMB_2));$(($XmitData_1 - $XmitData_2));$(($XmitPkts_1 - $XmitPkts_2));$(($MulticastXmitPkts_1 - $MulticastXmitPkts_2));$(($RcvDataMB_1 - $RcvDataMB_2));$(($RcvData_1 - $RcvData_2));$(($RcvPkts_1 - $RcvPkts_2));$(($MulticastRcvPkts_1 - $MulticastRcvPkts_2));$(($XmitWait_1 - $XmitWait_2));$(($CongDiscards_1 - $CongDiscards_2));$(($XmitTimeCong_1 - $XmitTimeCong_2));$(($MarkFECN_1 - $MarkFECN_2));$(($RcvFECN_1 - $RcvFECN_2));$(($RcvBECN_1 - $RcvBECN_2));$(($RcvBubble_1 - $RcvBubble_2));$(($XmitWastedBW_1 - $XmitWastedBW_2));$(($XmitWaitData_1 - $XmitWaitData_2));$(($LinkQualityIndicator_1 < $LinkQualityIndicator_2?$LinkQualityIndicator_1:$LinkQualityIndicator_2));$(($LocalLinkIntegrityErrors_1 - $LocalLinkIntegrityErrors_2));$(($RcvErrors_1 - $RcvErrors_2));$(($ExcessiveBufferOverruns_1 - $ExcessiveBufferOverruns_2));$(($LinkErrorRecovery_1 - $LinkErrorRecovery_2));$(($LinkDowned_1 - $LinkDowned_2));$(($UncorrectableErrors_1 - $UncorrectableErrors_2));$(($FMConfigErrors_1 - $FMConfigErrors_2));$(($XmitConstraintErrors_1 - $XmitConstraintErrors_2));$(($RcvConstraintErrors_1 - $RcvConstraintErrors_2));$(($RcvSwitchRelayErrors_1 - $RcvSwitchRelayErrors_2));$(($XmitDiscards_1 - $XmitDiscards_2));$(($RcvRemotePhysicalErrors_1 - $RcvRemotePhysicalErrors_2))" + fi + fi + else + # num_1 is "1" + read num_2 lineno_2 NodeDesc_2 NodeType_2 NodeGUID_2 PortNum_2 nNodeDesc_2 nNodeType_2 nNodeGUID_2 nPortNum_2 LinkSpeedActive_2 LinkWidthDnGradeTxActive_2 LinkWidthDnGradeRxActive_2 XmitDataMB_2 XmitData_2 XmitPkts_2 MulticastXmitPkts_2 RcvDataMB_2 RcvData_2 RcvPkts_2 MulticastRcvPkts_2 XmitWait_2 CongDiscards_2 XmitTimeCong_2 MarkFECN_2 RcvFECN_2 RcvBECN_2 RcvBubble_2 XmitWastedBW_2 XmitWaitData_2 LinkQualityIndicator_2 LocalLinkIntegrityErrors_2 RcvErrors_2 ExcessiveBufferOverruns_2 LinkErrorRecovery_2 LinkDowned_2 UncorrectableErrors_2 FMConfigErrors_2 XmitConstraintErrors_2 RcvConstraintErrors_2 RcvSwitchRelayErrors_2 XmitDiscards_2 RcvRemotePhysicalErrors_2 + #echo "process num_2=$num_2" >&2 + if [ x"$num_2" = x"END" ] + then + # "1" without a "2" at end of file + echo "$cmd: Warning: skipping unmatched line $lineno_1 in before: $NodeDesc_1;$NodeType_1;$NodeGUID_1;$PortNum_1" >&2 + break + fi + if ! [[ x"$RcvRemotePhysicalErrors_2" =~ ^x[0-9]+$ ]] + then + # lines with insufficient columns, extra columns or non-numeric in + # last column will fail the test. To balance performance and input + # checking we only check the last column since invalid input files + # will typically have the wrong number of columns + if [ x"$num_2" = x"1" ] + then + echo "$cmd: Invalid input line: $lineno_2 file: $f1" >&2 + else + echo "$cmd: Invalid input line: $lineno_2 file: $f2" >&2 + fi + exit 1 + fi + if [ x"$num_2" = x"1" ] + then + # two "1" in a row, skip _1, use this line for next pairing + echo "$cmd: Warning: skipping unmatched line $lineno_1 in before: $NodeDesc_1;$NodeType_1;$NodeGUID_1;$PortNum_1" >&2 + use_2=y + continue + elif [ x"$num_1" != "x1" -o x"$num_2" != "x2" ] # paranoid check + then + echo "$num_1 $num_2" >&2 + echo "$cmd: Script Error: Incorrect sort order" >&2 + exit 1 + else + if [ x"$NodeGUID_1" != x"$NodeGUID_2" -o x"$PortNum_1" != x"$PortNum_2" ] + then + # "1" followed by non-matching "2", skip both + echo "$cmd: Warning: skipping unmatched line $lineno_1 in before: $NodeDesc_1;$NodeType_1;$NodeGUID_1;$PortNum_1" >&2 + echo "$cmd: Warning: skipping unmatched line $lineno_2 in after: $NodeDesc_2;$NodeType_2;$NodeGUID_2;$PortNum_2" >&2 + elif [ x"$nNodeGUID_1" != x"$nNodeGUID_2" -o x"$nPortNum_1" != x"$nPortNum_2" ] + then + # we got a "1" followed by "2", however neighbor changed + echo "$cmd: Warning: skipping changed line $lineno_1 in before: $NodeDesc_1;$NodeType_1;$NodeGUID_1;$PortNum_1;$nNodeDesc_1;$nNodeType_1;$nNodeGUID_1;$nPortNum_1" >&2 + echo "$cmd: Warning: skipping changed line $lineno_2 in after: $NodeDesc_2;$NodeType_2;$NodeGUID_2;$PortNum_2;$nNodeDesc_2;$nNodeType_2;$nNodeGUID_2;$nPortNum_2" >&2 + else + # for fields not subtracted, show after (_2) as more recent + echo "$NodeDesc_2;$NodeType_2;$NodeGUID_2;$PortNum_2;$nNodeDesc_2;$nNodeType_2;$nNodeGUID_2;$nPortNum_2;$LinkSpeedActive_2;$LinkWidthDnGradeTxActive_2;$LinkWidthDnGradeRxActive_2;$(($XmitDataMB_2 - $XmitDataMB_1));$(($XmitData_2 - $XmitData_1));$(($XmitPkts_2 - $XmitPkts_1));$(($MulticastXmitPkts_2 - $MulticastXmitPkts_1));$(($RcvDataMB_2 - $RcvDataMB_1));$(($RcvData_2 - $RcvData_1));$(($RcvPkts_2 - $RcvPkts_1));$(($MulticastRcvPkts_2 - $MulticastRcvPkts_1));$(($XmitWait_2 - $XmitWait_1));$(($CongDiscards_2 - $CongDiscards_1));$(($XmitTimeCong_2 - $XmitTimeCong_1));$(($MarkFECN_2 - $MarkFECN_1));$(($RcvFECN_2 - $RcvFECN_1));$(($RcvBECN_2 - $RcvBECN_1));$(($RcvBubble_2 - $RcvBubble_1));$(($XmitWastedBW_2 - $XmitWastedBW_1));$(($XmitWaitData_2 - $XmitWaitData_1));$(($LinkQualityIndicator_2 < $LinkQualityIndicator_1?$LinkQualityIndicator_2:$LinkQualityIndicator_1));$(($LocalLinkIntegrityErrors_2 - $LocalLinkIntegrityErrors_1));$(($RcvErrors_2 - $RcvErrors_1));$(($ExcessiveBufferOverruns_2 - $ExcessiveBufferOverruns_1));$(($LinkErrorRecovery_2 - $LinkErrorRecovery_1));$(($LinkDowned_2 - $LinkDowned_1));$(($UncorrectableErrors_2 - $UncorrectableErrors_1));$(($FMConfigErrors_2 - $FMConfigErrors_1));$(($XmitConstraintErrors_2 - $XmitConstraintErrors_1));$(($RcvConstraintErrors_2 - $RcvConstraintErrors_1));$(($RcvSwitchRelayErrors_2 - $RcvSwitchRelayErrors_1));$(($XmitDiscards_2 - $XmitDiscards_1));$(($RcvRemotePhysicalErrors_2 - $RcvRemotePhysicalErrors_1))" + fi + fi + fi + use_2=n +done +} +res=$? +rm -rf ${tempfile}.prefix1 ${tempfile}.prefix2 +exit $res diff --git a/IbaTools/opaxmlextract/opaxmlextract.c b/IbaTools/opaxmlextract/opaxmlextract.c new file mode 100644 index 0000000..d8373d6 --- /dev/null +++ b/IbaTools/opaxmlextract/opaxmlextract.c @@ -0,0 +1,1333 @@ +/* BEGIN_ICS_COPYRIGHT7 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT7 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + + +/******************************************************************************* + * + * File: opaxmlextract.c + * + * Description: + * This file implements the opaxmlextract program. opaxmlextract takes + * well-formed XML as input, extracts element values as specified by user + * input, and outputs data as lines (records) of data in CSV format. + * + * opaxmlextract uses XML Lib to parse the XML. It uses the folowing library + * functions: + * IXmlParseFile() + * + * opaxmlextract implements the following call-backs (handlers): + * IXML_START_TAG_FUNC() + * IXML_END_TAG_FUNC() + * + * opaxmlextract takes 2 types of element names as input from the user - elements + * to be extracted, and those for which extraction is to be suppressed. Both + * types of elements are stored in the Element Table (tbElements[]). As + * opaxmlextract processes the XML (through the call-backs), it saves the values + * of elements to be extracted. opaxmlextract outputs a record containing those + * values under the following conditions: + * 1 or more elements being extracted and containing a non-null value go out + * of scope (the element containing those elements is ended) + * An element changes value while it is in scope + * + * During operation, opaxmlextract maintains the hierarchical "level" at which + * it is extracting (top-most level is 1). Each nested element increases the + * level by 1. opaxmlextract performs extraction on a (specified) element + * regardless of the level at which the element is found. + * + * When an element is specified for suppression then no extraction will be + * performed during the extent of that element (begin through end). + * Suppression is maintained for elements specified inside the suppressed + * element, even if those elements have extraction specified. Suppressed + * elements can be nested - opaxmlextract will resume extraction after the + * outermost suppressed element is ended. + * + * Element names for extraction or suppression can be made context sensitive + * with an enclosing element name using syntax 'elem1.elem2'. elem2 will + * be extracted (or extraction will be suppressed) when elem2 is enclosed + * by elem1. The wildcard handling capability of XML Lib allows '*' to + * be specified as all or part of an element name. The following are valid: + * *.elem3 - elem3 enclosed by any sequence of elements + * (elem1.elem3 or elem1.elem2.elem3) + * elem1.*.elem3 - elem3 enclosed by elem1 with any number of (but at + * least 1) intermediate elements. + * + * opaxmlextract prepends any entered element name not containing '*' + * (anywhere) with '*.'. + * + * NOTES: + * opaxmlextract performs extraction using XML Lib without maintaining + * its own stack of elements or element values. Therefore it has the + * following characteristics: + * Enclosing elements cannot contain values; + * + * If an element name specification is such that the element can be + * extracted at multiple levels within the same context (enclosing + * element), then when the inner-most element specification ends, + * the element value becomes null (it does not revert to the outer + * value). + */ + + +/******************************************************************************* + * + * INCLUDES + */ + +#include +#include +#include +#include +#include +#include +#include +#include "ixml.h" +#include "fnmatch.h" + + +/******************************************************************************* + * + * DEFINES + */ +#define ALLOW_MULTI_MATCH 1 // allow 1 tag to match mult elements +#define SUPPRESS_AND_EXTRACT 0 // allow 1 tag to suppress and extract + // this option not fully implemented + // procElementEnd would need more work + +#define OK 0 +#define ERROR (-1) + +#define NAME_PROG "opaxmlextract" // Program name +#define MAX_PARAMS_FILE 512 // Max number of param file parameters +#define MAX_ELEMENTS 100 // Max number of elements parsable +#define MAX_LEVEL_PARSE MAX_ELEMENTS // Max parsing level +#define MAX_DELIMIT_CHARS 16 // Max size of delimiter string +#define MAX_INPUT_BUF 8192 // Max size of input buffer +#define MAX_PARAM_BUF 8192 // Max size of parameter file +#define MAX_FILENAME_CHARS 256 // Max size of file name +#define WHITE_SPACE " \t\r\n" // White space characters +#define OPTION_LEN 2 // string length of an option(eg. -P) + +// Element table entry, elements selected by user and present parsed value +typedef struct +{ + char *pName; // Element name + char *pAttrName; // optional Attribute Name + char *pAttrValue; // optional Attribute Value + int lenValue; // Length of element value + // < 0 : pValue alloc'd but not in use + char *pValue; // Element value + int flags; // Flags (see ELEM_xxx below) + int level; // Element nesting level (0 - not open) +} ELEMENT_TABLE_ENTRY; + +// Element table flags: +#define ELEM_NAMEPREPEND 0x80 // Data prepended to element name + +// list of elements which a given tag matched and the attribute value +// which the element selected. This is generated by the start tag handler +// and used by the end tag handler for a given "matched" tag +typedef struct +{ + int ix; // element table index + int lenAttrValue; // length of value + char *pAttrValue; // value, NULL if not outputting attr +} ELEMENT_LIST_ENTRY; + +typedef struct +{ + int numElements; // number of entrys in list + ELEMENT_LIST_ENTRY Elements[1]; // variable length list +} ELEMENT_LIST; + + +/******************************************************************************* + * + * LOCAL FUNCTION PROTOTYPES + */ + +int delWsLead(char *pStr); +int delWsTrail(char *pStr); +void dispExtractionRecord(); +void dispHeaderRecord(int argc, char ** argv); +void errUsage(void); +int findElement(int start, const char *pElement, const char **pAttrib, + char **pValue, int *length); +int findElementDup(const ELEMENT_TABLE_ENTRY *pElement); +void getRecu_opt( int argc, char ** argv, const char *pOptShort, + struct option tbOptLong[] ); +void *procElementBeg(IXmlParserState_t *pParserState, void *pParent, const char **ppAttrib); +void procElementEnd( IXmlParserState_t *pParserState, const IXML_FIELD *pField, + void *pObject, void *pParent, XML_Char *pContent, unsigned length, + boolean flValid ); + + +/******************************************************************************* + * + * GLOBAL VARIABLES + */ + +int g_exitstatus = 0; +int g_verbose = 0; +int g_quiet = 0; + + +/******************************************************************************* + * + * LOCAL VARIABLES + */ + +int levelParse = 0; // Parse nesting level +int numElementsTable = 0; // Number of elements in tbElements[] +int numElementsExtract = 0; // Number of elements to extract +int ctElementsSuppress = 0; // Count of suppress elements being parsed +int flElementChangeLast = FALSE; // tbElement[] value change flag (last line) +int flElementChange = FALSE; // tbElement[] value change flag +int flHeaderOutput = TRUE; // Header output flag +XML_Parser pParser = NULL; // Pointer to expat parser object + +FILE * hFileInput = NULL; // Input file handle (default stdin) + // Input file name (default stdin) +char nameFileInput[MAX_FILENAME_CHARS + 1] = "stdin"; +uint32 fvDebugProg = 0; // Debug/Trace variable as: + // 0MMM MMMM NNNN NNNN SSSS 21RC SIEB SNEB + +// Command line option table, each has a short and long flag name +static const char* tbShortOptions="#vHe:s:X:P:d:Z:"; +struct option tbOptions[] = +{ + // Basic controls + { "help", no_argument, NULL, 'h' }, + { "verbose", no_argument, NULL, 'v' }, + { "extract", required_argument, NULL, 'e' }, + { "suppress", required_argument, NULL, 's' }, + { "infile", required_argument, NULL, 'X' }, + { "pfile", required_argument, NULL, 'P' }, + { "delimit", required_argument, NULL, 'd' }, + { "noheader", no_argument, NULL, 'H' }, + { "debug", required_argument, NULL, 'Z' }, + { 0 } +}; + +// Element table; contains information about each element of interest. +// Elements to be extracted are contained at the beginning of the table +// (0 - numElementsExtract-1); elements for which extraction is suppressed +// are contained at the end of the table +// (numElementsExtract - numElementsTable-1). +ELEMENT_TABLE_ENTRY tbElements[MAX_ELEMENTS + 1]; + +// IXML_FIELD table; contains information for the XML Lib parser. For +// purposes of opaxmlextract, a call-back on every start tag and end tag +// is required; therefore IXML_FIELD tag is set to "*" and format to 'w'. +IXML_FIELD tbFields[] = +{ + {tag:"*", format:'w', subfields:tbFields, start_func:procElementBeg, + end_func:procElementEnd}, + {NULL} +}; + +// Delimiter string buffer +char bfDelimit[MAX_DELIMIT_CHARS + 1] = ";"; + +// Input buffer +char bfInput[MAX_INPUT_BUF]; + +void *mymalloc(size_t size, const char* desc) +{ + void *ret = malloc(size); + if (! ret) + { + fprintf(stderr, NAME_PROG ": Unable to Allocate %s Memory\n", desc); + exit(1); + } + return ret; +} + +void *myrealloc(void* ptr, size_t size, const char* desc) +{ + void *ret = realloc(ptr, size); + if (! ret) + { + fprintf(stderr, NAME_PROG ": Unable to Re-Allocate %s Memory\n", desc); + exit(1); + } + return ret; +} + +/******************************************************************************* + * + * delWsLead() + * + * Description: + * Delete leading white space from a string. White space is defined by the + * string WHITE_SPACE. + * + * Inputs: + * pStr - Pointer to string from which to delete leading white space + * + * Outputs: + * ERROR - pStr NULL + * OK - white space deleted, no white space to delete + */ +int delWsLead(char *pStr) +{ + int nChar; + char *pChar; + + if (!pStr) + return (ERROR); + + nChar = strspn(pStr, WHITE_SPACE); + if (nChar != 0) + { + pChar = pStr + nChar; + memmove(pStr, pChar, strlen(pChar) + 1); + } + + return (OK); + +} // End of delWsLead() + + +/******************************************************************************* + * + * delWsTrail() + * + * Description: + * Delete trailing white space from a string. White space is defined by the + * string WHITE_SPACE. + * + * Inputs: + * pStr - Pointer to string from which to delete trailing white space + * + * Outputs: + * ERROR - pStr NULL + * OK - white space deleted, no white space to delete + */ +int delWsTrail(char *pStr) +{ + int nChar; + char *pChar; + + if (!(pChar = pStr)) + return (ERROR); // pStr is NULL + + while (TRUE) + { + // Find next non-white space char + nChar = strspn(pChar, WHITE_SPACE); + if (pChar[nChar]) + { + // Find next white space char + pChar += nChar; + pChar += strcspn(pChar, WHITE_SPACE); + if (!*pChar) + break; // No trailing white space + } + + // Found first white space char after last non-white space char + else + { + *pChar = 0; + break; + } + + } // End of while (TRUE) + + return (OK); + +} // End of delWsTrail() + + +/******************************************************************************* + * + * dispExtractionRecord() + * + * Description: + * Display (output) 1 record of extraction data if element change flag + * indicates an element has changed since the last output. + * + * Inputs: + * none + * + * Outputs: + * none + */ +void dispExtractionRecord() +{ + int ix; // Loop index + + // Check element change flag + if (!flElementChangeLast) + return; + + // Output extraction record: element values + for (ix = 0; ix < numElementsExtract; ix++) + { + (void)delWsTrail(tbElements[ix].pValue); + + if (ix > 0) + printf("%s", bfDelimit); + + printf("%s", tbElements[ix].pValue ? tbElements[ix].pValue : "" ); + } + printf("\n"); + flElementChangeLast = FALSE; + +} // End of dispExtractionRecord() + +void printElement(FILE *f, ELEMENT_TABLE_ENTRY *pElement, int verbose) +{ + // Output complete name string if verbose or name not prepended + if (verbose || !(pElement->flags & ELEM_NAMEPREPEND)) + fprintf(f, "%s", pElement->pName); + else + fprintf(f, "%s", &pElement->pName[2]); + if (pElement->pAttrName) + { + fprintf(f, ":%s", pElement->pAttrName); + if (pElement->pAttrValue) + fprintf(f, ":%s", pElement->pAttrValue); + } +} + +/******************************************************************************* + * + * dispHeaderRecord() + * + * Description: + * Display (output) header line containing names of elements extracted. This + * line preceeds the extraction data. If verbose is set, preceed the header + * line with a line containing the program name and command line options. + * + * Inputs: + * argc, argv - Inputs to main() + * + * Outputs: + * none + */ +void dispHeaderRecord(int argc, char ** argv) +{ + int ix; // Loop index + + // Output header record only if output enabled + if (flHeaderOutput) + { + // Output element names as a header + for (ix = 0; ix < numElementsExtract; ix++) + { + if (ix > 0) + printf("%s", bfDelimit); + + printElement(stdout,&tbElements[ix], g_verbose); + } + printf("\n"); + } + +} // End of dispHeaderRecord() + + +/******************************************************************************* + * + * errUsage() + * + * Description: + * Output information about program usage and parameters. + * + * Inputs: + * none + * + * Outputs: + * none + */ +void errUsage(void) +{ + fprintf(stderr, "Usage: " NAME_PROG " [-v][-H][-d delimiter][-e element][-s element]\n"); + fprintf(stderr, " [-X input_file] [-P param_file]\n"); + fprintf(stderr, " -e/--extract element - name of an XML element to extract\n"); + fprintf(stderr, " can be used multiple times\n"); + fprintf(stderr, " elements can be nested in any order, but will\n"); + fprintf(stderr, " be output in the order specified\n"); + fprintf(stderr, " optionally an attribute or\n"); + fprintf(stderr, " attribute and value can be specified\n"); + fprintf(stderr, " -e element\n"); + fprintf(stderr, " -e element:attrName\n"); + fprintf(stderr, " -e element:attrName:attrValue\n\n"); + fprintf(stderr, " Note that elements can be compound values\n"); + fprintf(stderr, " separated by a dot. For example,\n"); + fprintf(stderr, " 'Switches.Node' is a Node element contained\n"); + fprintf(stderr, " within a Switches element.\n\n"); + fprintf(stderr, " If its desired to output the attribute value as\n"); + fprintf(stderr, " opposed to the element value, a specification such\n"); + fprintf(stderr, " as '-e FIs.Node:id' can be used, which will return\n"); + fprintf(stderr, " the value of the id attribute of any Node elements\n"); + fprintf(stderr, " within FIs element. If desired a specific element\n"); + fprintf(stderr, " can be selected by its attribute value, such as\n"); + fprintf(stderr, " '-e MulticastFDB.Value:LID:0xc000', which will\n"); + fprintf(stderr, " return the value of the Value element within\n"); + fprintf(stderr, " Multicast FDB element where the Value element has\n"); + fprintf(stderr, " an attribute of LID with a value of 0xc000.\n\n"); + +#if ALLOW_MULTI_MATCH + fprintf(stderr, " A given element can be specified multiple\n"); + fprintf(stderr, " times each with a different AttrName or attrValue\n"); +#else + fprintf(stderr, " a given element can be specified only once\n"); +#endif + fprintf(stderr, " -s/--suppress element - name of XML element to suppress extraction\n"); + fprintf(stderr, " can be used multiple times, order does not matter\n"); + fprintf(stderr, " supports same syntaxes as -e\n"); + fprintf(stderr, " -d/--delimit delimiter - delimiter output between element names and values\n"); + fprintf(stderr, " default is semicolon\n"); + fprintf(stderr, " -X/--infile input_file - parse XML in input_file\n"); + fprintf(stderr, " -P/--pfile param_file - read command parameters from param_file\n"); + fprintf(stderr, " -H/--noheader - do not output element name header record\n"); + fprintf(stderr, " -v/--verbose - verbose output: progress reports during extraction\n"); + fprintf(stderr, " and element name prepended wildcard characters\n"); + fprintf(stderr, " --help - print this usage text.\n"); + + if (hFileInput && (hFileInput != stdin)) + fclose(hFileInput); + + exit(2); +} // End of errUsage() + + +/******************************************************************************* + * + * findElement() + * + * Description: + * Find specified element name in element table using wildcard matching. + * Search suppression elements first by starting search at end of table + * and searching toward beginning. + * + * Inputs: + * start - first element in table to check (end of table) + * pElement - Pointer to element name + * ppAttrib - attribute list from tag being processed + * + * Outputs: + * Index of element table containing element name, else + * ERROR - Element name not found + * + * *pValue, *length - if matched a Name:attrName style specifier, the value of + * the attribute matched. Otherwise NULL,0 + * (caller must free *pValue if non-NULL) + */ +int findElement(int start, const char *pElement, const char **ppAttrib, + char **pValue, int *length) +{ + int ix; + + *pValue = NULL; + *length = 0; + for (ix = start; ix >= 0; ix--) + { + ELEMENT_TABLE_ENTRY *p = &tbElements[ix]; + if (!fnmatch(p->pName, pElement, 0)) + { + int i; + if (! p->pAttrName) + return (ix); // match only on tag name + + // search for matching attribute + // even index in ppAttrib is name, odd is corresponding value + for (i=0; ppAttrib[i]; i += 2) + { + if (!fnmatch(p->pAttrName, ppAttrib[i], 0)) + { + if (! p->pAttrValue) + { + // match on Attr Name and return attr value + *length = strlen(ppAttrib[i+1]); + *pValue = mymalloc(*length+1, "Attribute Value"); + strcpy(*pValue, ppAttrib[i+1]); + return (ix); + } + // match on attr value + if (! fnmatch(p->pAttrValue, ppAttrib[i+1], 0)) + return (ix); + } + } + } + } + + return (ERROR); + +} // End of findElement() + + +/******************************************************************************* + * + * findElementDup() + * + * Description: + * Find specified element name in element table using duplicate (2-way) + * wildcard matching. Search element table from beginning to end since + * there is no need to check suppression elements first. + * + * Inputs: + * pElement - Pointer to element name + * + * Outputs: + * Index of element table containing element name, else + * ERROR - Element name not found + */ +int findElementDup(const ELEMENT_TABLE_ENTRY *pElement) +{ + int ix; + + for (ix = 0; ix < numElementsTable; ix++) + { + ELEMENT_TABLE_ENTRY *p = &tbElements[ix]; + if (0 == fnmatch(p->pName, pElement->pName, 0) + || 0 == fnmatch(pElement->pName, p->pName, 0)) + { +#if ALLOW_MULTI_MATCH + if ((p->pAttrName == NULL) != (pElement->pAttrName == NULL)) + continue; + if (p->pAttrName && pElement->pAttrName) + { + if ( 0 == fnmatch(p->pAttrName, pElement->pAttrName, 0) || + 0 == fnmatch(pElement->pAttrName, p->pAttrName, 0) ) + { + if ((p->pAttrValue == NULL) != (pElement->pAttrValue == NULL)) + continue; + if ( p->pAttrValue && pElement->pAttrValue && + ! ( 0 == fnmatch(p->pAttrValue, pElement->pAttrValue, 0) || + 0 == fnmatch(pElement->pAttrValue, p->pAttrValue, 0) ) ) + continue; + + return (ix); + } + + continue; + } +#else + // allow different values for same attr because won't both match + // the same tag + if (p->pAttrName && pElement->pAttrName + && (0 == fnmatch(p->pAttrName, pElement->pAttrName, 0) + || 0 == fnmatch(pElement->pAttrName, p->pAttrName, 0)) + && p->pAttrValue && pElement->pAttrValue + && ! (0 == fnmatch(p->pAttrValue, pElement->pAttrValue, 0) + || 0 == fnmatch(pElement->pAttrValue, p->pAttrValue, 0))) + continue; +#endif + return (ix); + + } // End of if (0 == fnmatch(p->pName, pElement->pName, 0) + + } // End of for (ix = 0; ix < numElementsTable; ix++) + + return (ERROR); + +} // End of findElementDup() + +void getNextField(const char *arg, int extra, char **field, const char **rest) +{ + const char *p = rest?strchr(arg, ':'):NULL; + int len; + + if (p) + { + len = (p-arg); + *rest = p+1; + } else { + len = strlen(arg); + if (rest) + *rest = NULL; + } + *field = mymalloc(len+1+extra, "Name"); + strncpy(*field, arg, len); + (*field)[len] = '\0'; +} + + +/******************************************************************************* + * + * getRecu_opt() + * + * Description: + * Get command line options (recursively). Parses command line options + * using short and long option (parameter) definitions. Parameters (global + * variables) are updated appropriately. The parameter '-P param_file' which + * takes command line options from a file is also handled. The -P parameter + * can be used within a parameter file; in such cases the function will call + * itself recursively. + * + * Inputs: + * argc - Number of input parameters + * argv - Array of pointers to input parameters + * pOptShort - Pointer to string of short option definitions + * tbOptLong - Array of long option definitions + * + * Outputs: + * none + */ +void getRecu_opt( int argc, char ** argv, const char *pOptShort, + struct option tbOptLong[] ) +{ + int ix; + int cOpt; // Option parsing char + int ixOpt; // Option parsing index + int lenStr; // String length + char *pChar; // Pointer to char + ELEMENT_TABLE_ENTRY *pElement1, // Pointers to element entries + *pElement2; + int argc_recu; // Recursive argc + char *argv_recu[MAX_PARAMS_FILE]; // Recursive argv + int optind_recu; // Recursive optind + char *optarg_recu; // Recursive optarg + + int ctCharParam; // Parameter file char count + FILE *hFileParam = NULL; // Parameter file handle + char nameFileParam[MAX_FILENAME_CHARS +1]; // Parameter file name + char bfParam[MAX_PARAM_BUF + 1]; + + // Input command line arguments + while ((cOpt = getopt_long(argc, argv, pOptShort, tbOptLong, &ixOpt)) != -1) + { + lenStr = 0; + switch (cOpt) + { + // Verbose + case 'v': + g_verbose = 1; + break; + + // Extract element name specification + case 'e': + // Suppress element name specification + case 's': + // syntaxes supported: + // Name - match Tag with given name + // Name:attr - select attr field of Tag with given name and attr + // Name:attr:value - match Tag with given name and attr value + // All three components allow "glob" style patterns + if (numElementsTable == MAX_ELEMENTS) + { + fprintf(stderr, NAME_PROG ": Too many Elements\n"); + errUsage(); + } + + else if (!optarg || ! *optarg) + { + fprintf(stderr, NAME_PROG ": Missing Element\n"); + errUsage(); + } + + else + { + ELEMENT_TABLE_ENTRY *pElement = &tbElements[numElementsTable]; + const char *rest; + + // Tag Name + getNextField(optarg, 2, &pElement->pName, &rest); + if (! strchr(optarg, '*')) + { + // insert *. before string (extra 2 above allowed space) + memmove(pElement->pName+2, pElement->pName, strlen(pElement->pName)+1); + pElement->pName[0] = '*'; pElement->pName[1] = '.'; + pElement->flags |= ELEM_NAMEPREPEND; + } + if (rest) { + // optional AttrName + if (! *rest) // trailing colon + { + fprintf(stderr, NAME_PROG ": Attr Name missing: %s\n", optarg); + errUsage(); + } + getNextField(rest, 0, &pElement->pAttrName, &rest); + if (rest) { + // optional AttrValue + if (! *rest) // trailing colon + { + fprintf(stderr, NAME_PROG ": Attr Value missing: %s\n", optarg); + errUsage(); + } + getNextField(rest, 0, &pElement->pAttrValue, NULL); + } + } + if ((ix = findElementDup(&tbElements[numElementsTable])) != ERROR) + { + fprintf(stderr, NAME_PROG ": Duplicate (matching) Element: %s (matches: ", optarg); + printElement(stderr, &tbElements[ix], FALSE); + fprintf(stderr, ")\n"); + errUsage(); + } + + } + + // If suppress specification, leave at end of tbElements[] + if (cOpt == 's') + numElementsTable++; + + // If extraction specification w/no suppress elements, leave at + // end of tbElements[] + else if ((cOpt == 'e') && (numElementsExtract == numElementsTable)) + { + numElementsTable++; + numElementsExtract++; + } + + // If extraction specification w/suppress elements, move extraction + // to end of other extractions + else if ((cOpt == 'e') && (numElementsExtract < numElementsTable)) + { + // Swap last element table entry with first suppress element entry + // (NOTE: lenValue, pValue and level are zero, so no swap needed) + pElement1 = &tbElements[numElementsExtract++]; + pElement2 = &tbElements[numElementsTable++]; + + pChar = pElement1->pName; + pElement1->pName = pElement2->pName; + pElement2->pName = pChar; + + pChar = pElement1->pAttrName; + pElement1->pAttrName = pElement2->pAttrName; + pElement2->pAttrName = pChar; + + pChar = pElement1->pAttrValue; + pElement1->pAttrValue = pElement2->pAttrValue; + pElement2->pAttrValue = pChar; + + lenStr = pElement1->flags; + pElement1->flags = pElement2->flags; + pElement2->flags = lenStr; + } + + break; + + // Delimiter string specification + case 'd': + if ( !optarg || ((lenStr = strlen(optarg)) == 0) || + (lenStr > MAX_DELIMIT_CHARS) ) + { + fprintf(stderr, NAME_PROG ": Invalid delimiter size: %d\n", lenStr); + errUsage(); + } + + strncpy(bfDelimit, optarg, sizeof(bfDelimit)-1); + // Ensure null termination + bfDelimit[MAX_DELIMIT_CHARS]=0; + break; + + // Input file specification + case 'X': + if ( !optarg || ((lenStr = strlen(optarg)) == 0) || + (lenStr > MAX_FILENAME_CHARS) ) + { + fprintf(stderr, NAME_PROG ": Missing Input File Name.\n"); + errUsage(); + } + + else if (hFileInput != stdin) + { + fprintf( stderr, NAME_PROG ": Multiple Input Files: %s and %s\n", + nameFileInput, optarg ); + errUsage(); + } + + strncpy(nameFileInput, optarg, sizeof(nameFileInput)-1); + // Ensure null termination + nameFileInput[MAX_FILENAME_CHARS]=0; + hFileInput = fopen(nameFileInput, "r"); + + if (!hFileInput) + { + fprintf( stderr, NAME_PROG ": Unable to Open Input File: %s\n", + nameFileInput ); + perror(""); + errUsage(); + } + break; + + // Parameter file specification + case 'P': + if (!optarg || ((lenStr = strlen(optarg)) == 0) || + (lenStr > MAX_FILENAME_CHARS) ) + { + fprintf(stderr, NAME_PROG ": Missing Parameter File Name.\n"); + errUsage(); + } + + // Open parameter file + strncpy(nameFileParam, optarg, sizeof(nameFileParam)-1); + // Ensure null termination + nameFileParam[MAX_FILENAME_CHARS]=0; + hFileParam = fopen(nameFileParam, "r"); + + if (!hFileParam) + { + fprintf( stderr, NAME_PROG ": Unable to Open Parameter File: %s\n", + nameFileParam ); + perror(""); + errUsage(); + } + + // Read parameter file + if (g_verbose) + fprintf(stderr, NAME_PROG ": Reading Param File: %s\n", nameFileParam); + + ctCharParam = (int)fread(bfParam, 1, MAX_PARAM_BUF, hFileParam); + + if (ferror(hFileParam)) + { + fclose(hFileParam); + fprintf(stderr, NAME_PROG ": Read Error: %s\n", nameFileParam); + errUsage(); + } + + if ((ctCharParam == MAX_PARAM_BUF) && !feof(hFileParam)) + { + fclose(hFileParam); + fprintf( stderr, NAME_PROG ": Parameter file (%s) too large (> %d bytes)\n", + nameFileParam, MAX_PARAM_BUF ); + errUsage(); + } + + // Make sure the buffer is null terminated. + bfParam[MAX_PARAM_BUF] = 0; + + fclose(hFileParam); + + if (ctCharParam > 0) + { + // Parse parameter file into tokens + argc_recu = 2; + argv_recu[0] = nameFileParam; + + for (ix = 1; ; ix++, argc_recu++) + { + if (ix == MAX_PARAMS_FILE) + { + fprintf( stderr, NAME_PROG ": Parameter file (%s) has too many parameters (> %d)\n", + nameFileParam, MAX_PARAMS_FILE ); + errUsage(); + } + + if ( (argv_recu[ix] = strtok((ix == 1) ? bfParam : NULL, WHITE_SPACE)) + == NULL ) + { + argc_recu--; + break; + } + + if (!strncmp(argv_recu[ix], "-P", OPTION_LEN)) + { + fprintf( stderr, NAME_PROG ": Parameter file (%s) cannot contain -P option\n", nameFileParam); + errUsage(); + } + + if ( (argv_recu[ix] - bfParam + strlen(argv_recu[ix]) + 1) == + ctCharParam ) + break; + } + + // Process parameter file parameters + if (argc_recu > 1) + { + optind_recu = optind; // Save optind & optarg + optarg_recu = optarg; + optind = 1; // Init optind & optarg + optarg = NULL; + getRecu_opt(argc_recu, argv_recu, pOptShort, tbOptLong); + optind = optind_recu; // Restore optind & optarg + optarg = optarg_recu; + } + + } // End of if (ctCharParam > 0) + + break; + + // No Header + case 'H': + flHeaderOutput = FALSE; + break; + + // Debug trace specification + case 'Z': + if (FSUCCESS != StringToUint32(&fvDebugProg, optarg, NULL, 0, TRUE)) { + fprintf(stderr, NAME_PROG ": Invalid Debug Setting: %s\n", optarg); + errUsage(); + } + break; + + case '#': + default: + errUsage(); + break; + + } // End of switch (cOpt) + + } // End of while ( ( cOpt = getopt_long( argc, argv, + + // Validate command line arguments + if (optind < argc) + { + fprintf(stderr, "%s: invalid argument %s\n", NAME_PROG, argv[optind]); + errUsage(); + } + +} // End of getRecu_opt() + + +/******************************************************************************* + * + * main() + * + * Description: + * main function for program. + * + * Inputs: + * argc - Number of input parameters + * argv - Array of pointers to input parameters + * + * Outputs: + * Exit status 0 - no errors + * Exit status 2 - error (input parameter, resources, file I/O, XML parsing) + */ +int main(int argc, char ** argv) +{ + int ix; // Loop index + + // Initialize for extraction + hFileInput = stdin; + + for (ix = 0; ix < MAX_ELEMENTS; ix++) + { + tbElements[ix].pName = NULL; + tbElements[ix].pAttrName = NULL; + tbElements[ix].pAttrValue = NULL; + tbElements[ix].lenValue = 0; + tbElements[ix].pValue = NULL; + tbElements[ix].flags = 0; + tbElements[ix].level = 0; + } + + // Get and validate command line arguments + getRecu_opt(argc, argv, tbShortOptions, tbOptions); + + dispHeaderRecord(argc, argv); + + // Output progress report if g_verbose + if (g_verbose) + fprintf(stderr, NAME_PROG ": Parsing XML buffer\n"); + + if ( IXmlParseFile(hFileInput, nameFileInput, IXML_PARSER_FLAG_NONE, tbFields, NULL, NULL, NULL, NULL, NULL, NULL) != + FSUCCESS ) + { + fprintf(stderr, NAME_PROG ": XML Parse error\n"); + exit(1); + } + + if (hFileInput && (hFileInput != stdin)) + fclose(hFileInput); + + return (g_exitstatus); + +} // End of main() + +void ProcessMatchedElement( ELEMENT_TABLE_ENTRY *pElement, char *pValue, + int length, int level ) +{ + if (!length) + { + // Existing element value being replaced by NULL + if (pElement->lenValue > 0) + { + dispExtractionRecord(); + pElement->pValue[0] = 0; + pElement->level = level; + flElementChange = TRUE; + } + } + else + { + // Null element value being replaced by new value + if (!pElement->lenValue) + { + // Allocate block of memory x2 + pElement->pValue = mymalloc(length + length, "Value"); + strcpy(pElement->pValue, pValue); + pElement->lenValue = length + length; + pElement->level = level; + flElementChange = TRUE; + } + else if (pElement->lenValue < 0) + { + if (-pElement->lenValue <= length) + { + // Reallocate to larger block of memory x2 + pElement->pValue = + myrealloc(pElement->pValue, length + length, "Value"); + pElement->lenValue = -(length + length); + } + + strcpy(pElement->pValue, pValue); + pElement->lenValue = -pElement->lenValue; + pElement->level = level; + flElementChange = TRUE; + } + + else + { + // Existing element value being replaced by new (non-equal) value + if (strcmp(pElement->pValue, pValue)) + { + dispExtractionRecord(); + if (pElement->lenValue <= length) + { + // Reallocate to larger block of memory x2 + pElement->pValue = + myrealloc(pElement->pValue, length + length, "Value"); + pElement->lenValue = length + length; + } + + strcpy(pElement->pValue, pValue); + pElement->level = level; + flElementChange = TRUE; + + } // End of if (strcmp(pElement->pValue, pValue)) + + } // End of else (else if (pElement->lenValue < 0)) + + } // End of else (!length) + +} // End of ProcessMatchedElement() + +/******************************************************************************* + * + * procElementBeg() + * + * Description: + * Process begin element specification. Check for whether element suppresses + * extraction. + * + * Inputs: + * pParserState - Pointer to IXml parser state + * pParent - Pointer to element parent + * ppAttrib - Pointer to pointer to element attribute data + * + * Outputs: + * none + */ +void *procElementBeg(IXmlParserState_t *pParserState, void *pParent, const char **ppAttrib) +{ + int ix; + char *pNameFull; + ELEMENT_LIST* pList = NULL; + char *pValue; + int length; + + if (levelParse++ > MAX_LEVEL_PARSE) + { + fprintf( stderr, NAME_PROG ": Max Parsing Level (%d) Exceeded\n", + MAX_LEVEL_PARSE ); + exit(1); + } + + pNameFull = (char *)IXmlParserGetCurrentFullTag(pParserState); + ix = numElementsTable - 1; + do { + if ((ix = findElement(ix, pNameFull, ppAttrib, &pValue, &length)) >= 0) + { +#if ! SUPPRESS_AND_EXTRACT + if (pList && ix >= numElementsExtract) // Check for suppression Element + { + int i; + + // discard matched extractions; replace with this suppression (below) + for (i=0; inumElements; i++) + { + if (pList->Elements[i].pAttrValue) + free(pList->Elements[i].pAttrValue); + } + free(pList); + pList=NULL; + } +#endif + // Process extraction of attribute value immediately so that value + // is available with (potential) extraction values of nested lines + if (pValue && ix < numElementsExtract) + { + dispExtractionRecord(); + ProcessMatchedElement( &tbElements[ix], pValue, length, + levelParse + 1 ); + free(pValue); + } + + // Add to pList: extraction of element value + // extraction of element:attribute:value + // any suppression specification + else + { + if (pList) + { + // sizeof(*pList) includes 1st element + pList = myrealloc(pList, sizeof(*pList) + + pList->numElements + * sizeof(pList->Elements[0]), + "object list"); + } + else + { + pList = mymalloc(sizeof(*pList), "object list"); + pList->numElements = 0; + } + // findElement has malloced pValue as needed + pList->Elements[pList->numElements].ix = ix; + pList->Elements[pList->numElements].lenAttrValue = length; + pList->Elements[pList->numElements].pAttrValue = pValue; + pList->numElements++; + + // Check for suppression Element + if (ix >= numElementsExtract) + { + ctElementsSuppress++; + break; // no use going past 1st match of a suppressed + } + } + + ix--; + + } // End of if ((ix = findElement(ix, pNameFull, ppAttrib + +#if ALLOW_MULTI_MATCH + } while (ix >= 0); +#else /* just use 1st match, like the old code did */ + } while (0); +#endif + + // return list of elements matched (NULL if none matched) + return (void*)pList; + +} // End of procElementBeg() + + +/******************************************************************************* + * + * procElementEnd() + * + * Description: + * Process end element specification. Check for whether element is being + * extracted, whether element suppresses extraction, or neither. If the + * element being ended is an extraction element and is the outermost enclosing + * element for a group of extraction elements, output an extraction record. + * + * Inputs: + * pParserState - Pointer to IXml parser state + * pField - Pointer to field + * pObject - Pointer to object + * pParent - Pointer to element parent + * pValue - Pointer to element value (NULL terminated) + * length - Length of value + * ppAttrib - Pointer to pointer to element attribute data + * flValid - Valid flag + * + * Outputs: + * none + */ +void procElementEnd( IXmlParserState_t *pParserState, const IXML_FIELD *pField, + void *pObject, void *pParent, XML_Char *pValue, unsigned length, + boolean flValid ) +{ + int ix; + ELEMENT_TABLE_ENTRY *pElement = NULL; + ELEMENT_LIST* pList = (ELEMENT_LIST*)pObject; + + if (pList) + { + // this tag Matched one or more elements + int i; + for (i=0; inumElements; i++) + { + ix = pList->Elements[i].ix; + ASSERT(ix >= 0); + pElement = &tbElements[ix]; + + // Check for extracted element + if (ix < numElementsExtract) + { + // Check for suppression, ignore matches within suppression + if (ctElementsSuppress == 0) + { + // matched extraction element + if (!pElement->pAttrName || pElement->pAttrValue) + { + // operate on element value + ProcessMatchedElement( pElement, pValue, length, + levelParse ); + } + + } // End of if (ctElementsSuppress == 0) + + } // End of if (ix < numElementsExtract) + else + { + // Suppress extraction element + ctElementsSuppress--; + } + + if (pList->Elements[i].pAttrValue) + free(pList->Elements[i].pAttrValue); + + } // End of for (i=0; inumElements; i++) + free(pList); + + } // End of if (pList) + + // Merge current element change flag into last change flag + if (!ctElementsSuppress) + flElementChangeLast |= flElementChange; + + flElementChange = FALSE; + + // Check for end of element which encloses extracted element(s) + for (ix = 0; ix < numElementsExtract; ix++) + { + if (tbElements[ix].level > levelParse) + { + dispExtractionRecord(); + tbElements[ix].lenValue = -tbElements[ix].lenValue; + tbElements[ix].pValue[0] = 0; + tbElements[ix].level = 0; + } + } + + levelParse--; + +} // End of procElementEnd() + + +// End of file + diff --git a/IbaTools/opaxmlextract/test2.xml b/IbaTools/opaxmlextract/test2.xml new file mode 100644 index 0000000..efb8a06 --- /dev/null +++ b/IbaTools/opaxmlextract/test2.xml @@ -0,0 +1,208 @@ + + + + + + + + v4 + v5 + + + + v3 + v4a + + + + + + + v3a + + + v3a + + + + + v3b + v3c + v3b + + + + v3d + v3d + + + + + + + + v5 + + + + v6 + + v6a + + + + + + + v5b + + + + v5c + + + v4c + + v5d + + + + + + v4e + + + + + + v3 + + v3 + + + + + v3a + + v3b + + + + + + + + v3 + + + v3a + + + + + v3b + + v3c + + + + + + v4 + v5 + + + + v3 + v4a + + + + + v3 + v3a + v3b + + + + v3c + v3c + v3d + v3d + v3d + + + + + + v4 + + + v4a + + + + + + v4b + v4c + + + + + + v3a + v3b + v3c + v3d + v3e + + + + v3f + v3g + + v3h + v4 + + + + + v4a + + v4b + + v5 + + + + + + v3a + + v3b + + v3c + + v3d + + v3e + + v3f + + v3g + + v3h + + + + + + v7a + v7b + v7c + v7d + v7e + + + diff --git a/IbaTools/opaxmlextract/test2.xml.out b/IbaTools/opaxmlextract/test2.xml.out new file mode 100644 index 0000000..fd274c4 --- /dev/null +++ b/IbaTools/opaxmlextract/test2.xml.out @@ -0,0 +1,58 @@ +t3;t4;t5;t6;t3:a3;t4:a4;t5:a5;t4:aa4;t3:a3:va3K;t7;t7:a7 +;v4;v5;;;;;;;; +v3;v4a;;;;;;;;; +v3a;;;;;;;;;; +v3a;;;;;;;;;; +v3b;;;;;;;;;; +v3c;;;;;;;;;; +v3b;;;;;;;;;; +v3d;;;;;;;;;; +;;v5;;;;;;;; +;;;v6;;;;;;; +;;;v6a;;;;;;; +;;v5b;;;;;;;; +;;v5c;;;;;;;; +;v4c;v5d;;;;;;;; +;;v5d;;;;;;;; +;v4e;;;;;;;;; +v3;;;;;;;;;; +v3a;;;;;;;;;; +v3b;;;;;;;;;; +v3;;;;;;;;;; +v3b;;;;;;;;;; +;v4;;;;va4;;;;; +;v4;v5;;;;va5;;;; +v3;;;;va3;;;;;; +v3;v4a;;;;va4a;;;;; +v3;;;;va3;;;;;; +v3a;;;;va3a;;;;;; +v3b;;;;va3b;;;;;; +v3c;;;;va3c;;;;;; +v3c;;;;va3c;;;;;; +v3d;;;;va3c;;;;;; +v3d;;;;va3d;;;;;; +v3d;;;;va3d;;;;;; +;v4;;;va3;;;;;; +;v4a;;;va3a;;;;;; +;v4b;;;va3b;va4;;;;; +;v4c;;;va3b;va4a;;;;; +v3a;;;;va3a;;;;;; +v3b;;;;va3K;;;;v3b;; +v3c;;;;va3c;;;;v3b;; +v3d;;;;va3K;;;;v3d;; +v3e;;;;va3e;;;;v3d;; +v3f;;;;;;;;;; +v3g;;;;va3K;;;;v3g;; +v3h;v4;;;;;;;v3g;; +;v4a;;;va3f;va4;;vaa4;;; +;v4b;;;va3f;va4a;va5;;;; +;;v5;;va3f;;va5a;;;; +v3a;;;;va3a;;;;;; +v3c;;;;va3b;;;;;; +v3d;;;;;;;;;; +v3e;;;;va3c;;;;;; +v3g;;;;va3K;;;;v3g;; +;;;;;;;;;v7a;va7a +;;;;;;;;;v7b;va7b +;;;;;;;;;v7d;va7c +;;;;;;;;;v7e;va7d diff --git a/IbaTools/opaxmlextract/test_xml_extract.sh b/IbaTools/opaxmlextract/test_xml_extract.sh new file mode 100644 index 0000000..20dc465 --- /dev/null +++ b/IbaTools/opaxmlextract/test_xml_extract.sh @@ -0,0 +1,33 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +#[ICS VERSION STRING: unknown] + +/usr/sbin/opaxmlextract -e t3 -e t4 -e t5 -e t6 -e t3:a3 -e t4:a4 -e t5:a5 -e t4:aa4 -e t3:a3:va3K -e t7 -e t7:a7 -s t7:a7:va7K -s t9 -s t10:a10 -s t11:a11:va11K < test2.xml > out +diff test2.xml.out out diff --git a/IbaTools/opaxmlfilter/Makefile b/IbaTools/opaxmlfilter/Makefile new file mode 100644 index 0000000..61f6a12 --- /dev/null +++ b/IbaTools/opaxmlfilter/Makefile @@ -0,0 +1,161 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** +# Makefile for opaxmlfilter + +# Include Make Control Settings +include $(TL_DIR)/$(PROJ_FILE_DIR)/Makesettings.project + +#=============================================================================# +# Definitions: +#-----------------------------------------------------------------------------# + +# Name of SubProjects +DS_SUBPROJECTS = +# name of executable or downloadable image +EXECUTABLE = $(BUILDDIR)/opaxmlfilter$(EXE_SUFFIX) +# list of sub directories to build +DIRS = +# C files (.c) +CFILES = \ + opaxmlfilter.c \ + # Add more c files here +# C++ files (.cpp) +CCFILES = \ + # Add more cpp files here +# lex files (.lex) +LFILES = \ + # Add more lex files here +# archive library files (basename, $ARFILES will add MOD_LIB_DIR/prefix and suffix) +LIBFILES= +# Windows Resource Files (.rc) +RSCFILES = +# Windows IDL File (.idl) +IDLFILE = +# Windows Linker Module Definitions (.def) file for dll's +DEFFILE = +# targets to build during INCLUDES phase (add public includes here) +INCLUDE_TARGETS = \ + # Add more h hpp files here +# Non-compiled files +MISC_FILES = +# all source files +SOURCES = $(CFILES) $(CCFILES) $(LFILES) $(RSCFILES) $(IDLFILE) +# Source files to include in DSP File +DSP_SOURCES = $(INCLUDE_TARGETS) $(SOURCES) $(MISC_FILES) \ + $(RSCFILES) $(DEFFILE) $(MAKEFILE) +# all object files +OBJECTS = $(CFILES:.c=$(OBJ_SUFFIX)) $(CCFILES:.cpp=$(OBJ_SUFFIX)) \ + $(LFILES:.lex=$(OBJ_SUFFIX)) +RSCOBJECTS = $(RSCFILES:.rc=$(RES_SUFFIX)) +# targets to build during LIBS phase +LIB_TARGETS_IMPLIB = +LIB_TARGETS_ARLIB = # $(LIB_PREFIX)ResourceTest$(ARLIB_SUFFIX) +LIB_TARGETS_EXP = $(LIB_TARGETS_IMPLIB:$(ARLIB_SUFFIX)=$(EXP_SUFFIX)) +LIB_TARGETS_MISC = +# targets to build during CMDS phase +CMD_TARGETS_SHLIB = +CMD_TARGETS_EXE = $(EXECUTABLE) +CMD_TARGETS_MISC = +# files to remove during clean phase +CLEAN_TARGETS_MISC = +CLEAN_TARGETS = $(OBJECTS) $(RSCOBJECTS) $(IDL_TARGETS) $(CLEAN_TARGETS_MISC) +# other files to remove during clobber phase +CLOBBER_TARGETS_MISC= +# sub-directory to install to within bin +BIN_SUBDIR = +# sub-directory to install to within include +INCLUDE_SUBDIR = + +# Additional Settings +#CLOCALDEBUG = User defined C debugging compilation flags [Empty] +#CCLOCALDEBUG = User defined C++ debugging compilation flags [Empty] +#CLOCAL = User defined C flags for compiling [Empty] +#CCLOCAL = User defined C++ flags for compiling [Empty] +#BSCLOCAL = User flags for Browse File Builder [Empty] +#DEPENDLOCAL = user defined makedepend flags [Empty] +#LINTLOCAL = User defined lint flags [Empty] +#LOCAL_INCLUDE_DIRS = User include directories to search for C/C++ headers [Empty] +#LDLOCAL = User defined C flags for linking [Empty] +#IMPLIBLOCAL = User flags for Object Lirary Manager [Empty] +#MIDLLOCAL = User flags for IDL compiler [Empty] +#RSCLOCAL = User flags for resource compiler [Empty] +#LOCALDEPLIBS = User libraries to include in dependencies [Empty] +#LOCALLIBS = User libraries to use when linking [Empty] +# (in addition to LOCALDEPLIBS) +#LOCAL_LIB_DIRS = User library directories for libpaths [Empty] + +CLOCAL=$(CIBACCESS) $(CPIE) +LOCALDEPLIBS = $(IBACCESS_USER_LIBS) Xml +LOCAL_INCLUDE_DIRS= +LOCALLIBS= +LOCAL_LIB_DIRS= + +ifneq "$(BUILD_TARGET_OS)" "VXWORKS" +LOCALLIBS+= expat +endif + +# Include Make Rules definitions and rules +include $(TL_DIR)/IbaTools/Makerules.module + +#=============================================================================# +# Overrides: +#-----------------------------------------------------------------------------# +#CCOPT = # C++ optimization flags, default lets build config decide +#COPT = # C optimization flags, default lets build config decide +#SUBSYSTEM = Subsystem to build for (none, console or windows) [none] +# (Windows Only) +#USEMFC = How Windows MFC should be used (none, static, shared, no_mfc) [none] +# (Windows Only) +#=============================================================================# + +#=============================================================================# +# Rules: +#-----------------------------------------------------------------------------# +# process Sub-directories +include $(TL_DIR)/Makerules/Maketargets.toplevel + +# build cmds and libs +include $(TL_DIR)/Makerules/Maketargets.build + +# install for includes, libs and cmds phases +include $(TL_DIR)/Makerules/Maketargets.install + +# install for stage phase +#include $(TL_DIR)/Makerules/Maketargets.stage +STAGE:: + $(VS)$(STAGE_INSTALL) $(STAGE_INSTALL_DIR_OPT) $(PROJ_STAGE_FASTFABRIC_DIR) $(EXECUTABLE) + +# Unit test execution +#include $(TL_DIR)/Makerules/Maketargets.runtest + +#=============================================================================# + +#=============================================================================# +# DO NOT DELETE THIS LINE -- make depend depends on it. +#=============================================================================# diff --git a/IbaTools/opaxmlfilter/opaxmlfilter.c b/IbaTools/opaxmlfilter/opaxmlfilter.c new file mode 100644 index 0000000..3142306 --- /dev/null +++ b/IbaTools/opaxmlfilter/opaxmlfilter.c @@ -0,0 +1,280 @@ +/* BEGIN_ICS_COPYRIGHT7 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT7 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +#include +#include +#include +#include +#include +#include +#include +#include +#define _GNU_SOURCE + +#include + +boolean g_trim = FALSE; +boolean g_keep_newline = FALSE; +boolean g_add_lineno = FALSE; + +boolean g_filter = FALSE; + +#define MAX_ELEMENTS 100 +char *g_elements[MAX_ELEMENTS] = { 0 }; +int g_numElements = 0; + +/* example of simple non-predefined parser */ +/* for an example of a predefined parser, see opareport/topology.c */ + +static void *FieldXmlParserStart(IXmlParserState_t *input_state, void *parent, const char **attr); +static void FieldXmlParserEnd(IXmlParserState_t *input_state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid); + +static IXML_FIELD UntrimmedFields[] = { + { tag:"*", format:'w', subfields:UntrimmedFields, start_func:FieldXmlParserStart, end_func:FieldXmlParserEnd }, // wildcard to traverse xml tree, keep all whitespace + { NULL } +}; + +#if 0 +static IXML_FIELD TrimmedFields[] = { + { tag:"*", format:'y', subfields:TrimmedFields, start_func:FieldXmlParserStart, end_func:FieldXmlParserEnd }, // wildcard to traverse xml tree, trim whitespace + { NULL } +}; +#endif + +static void FieldXmlFormatAttr(IXmlOutputState_t *output_state, void *data) +{ + const char **attr = (const char **)data; + int i; + + for (i = 0; attr[i]; i += 2) { + IXmlOutputPrint(output_state, " %s=\"", attr[i]); + IXmlOutputPrintStr(output_state, attr[i+1]); + IXmlOutputPrint(output_state, "\""); + } +} + +static boolean compareElement(const char* element) +{ + int i; + for (i=0; iparser)); + else + IXmlOutputEndTag(output_state, IXmlParserGetCurrentTag(input_state)); + } +} + +FSTATUS Xml2ParseInputFile(const char *input_file, void *context, IXML_FIELD *fields) +{ + if (strcmp(input_file, "-") == 0) { + fprintf(stderr, "Parsing stdin...\n"); + if (FSUCCESS != IXmlParseFile(stdin, "stdin", IXML_PARSER_FLAG_NONE, fields, NULL, context, NULL, NULL, NULL, NULL)) { + return FERROR; + } + } else { + fprintf(stderr, "Parsing %s...\n", input_file); + if (FSUCCESS != IXmlParseInputFile(input_file, IXML_PARSER_FLAG_NONE, fields, NULL, context, NULL, NULL, NULL, NULL)) { + return FERROR; + } + } + return FSUCCESS; +} + +void Usage(int exitcode) +{ + fprintf(stderr, "Usage: opaxmlfilter [-t|-k] [-l] [-i indent] [-s element] [input_file]\n"); + fprintf(stderr, " or\n"); + fprintf(stderr, " opaxmlfilter --help\n"); + fprintf(stderr, " --help - produce full help text\n"); + fprintf(stderr, " -t - trim leading and trailing whitespace in tag contents\n"); + fprintf(stderr, " -k - in tags with purely whitespace which contain newlines,\n"); + fprintf(stderr, " keep newlines as is (default is to format as an empty list)\n"); + fprintf(stderr, " -l - add comments with line numbers after each end tag\n"); + fprintf(stderr, " This can make comparison of resulting files easier\n"); + fprintf(stderr, " since original line numbers will be available\n"); + fprintf(stderr, " -i indent - set indentation to use per level (default 4)\n"); + fprintf(stderr, " -s element - name of XML element to suppress\n"); + fprintf(stderr, " can be used multiple times (max 100), order does not matter\n"); + + fprintf(stderr, " input_file - xml file to read. default is stdin\n"); + exit(exitcode); +} + +static void addElement(const char *element) +{ + int len = 0; + + if (g_numElements >= MAX_ELEMENTS) { + fprintf(stderr, "opaxmlfilter: Too many suppressed elements, limit of %d\n", MAX_ELEMENTS); + exit(1); + } + + if (! element || ! (len = strlen(element))) { + fprintf(stderr, "opaxmlfilter: Missing element.\n"); + Usage(2); + } + + len += 3; // allow for \0 and possible wildcards + g_elements[g_numElements] = malloc(len); + if (! g_elements[g_numElements]) { + fprintf(stderr, "opaxmlfilter: Unable to allocate memory\n"); + exit(1); + } + + snprintf(g_elements[g_numElements], len, "%s%s", strchr(element, '*') ? "" : "*.", element); + // no issue with duplicates, so no need to check + g_numElements++; +} + +int main(int argc, char **argv) +{ + IXmlOutputState_t output_state; + int exit_code = 0; + uint32 indent = 4; + const char *opts="tkli:s:"; + const struct option longopts[] = {{"help", 0, 0, '$'}, + {0, 0, 0, 0}}; + char *filename = "-"; // default to stdin + IXML_FIELD *fields = UntrimmedFields; + int c; + + while (-1 != (c = getopt_long(argc, argv, opts, longopts, NULL))) { + switch (c) { + case '$': + Usage(0); + case 't': + // TrimmedFields treats empty list as tag with no content + //fields = TrimmedFields; + g_trim = TRUE; + break; + case 'i': + if (FSUCCESS != StringToUint32(&indent, optarg, NULL, 0, TRUE)) { + fprintf(stderr, "opaxmlfilter: Invalid indent: %s\n", optarg); + Usage(2); + } + break; + case 'k': + g_keep_newline = TRUE; + break; + case 'l': + g_add_lineno = TRUE; + break; + case 's': + addElement(optarg); + break; + default: + Usage(2); + } + } + if (g_trim && g_keep_newline) { + fprintf(stderr, "opaxmlfilter: Can't use -k and -t together\n"); + Usage(2); + } + if (argc > optind){ + filename = argv[optind++]; + if (!filename) { + fprintf(stderr, "opaxmlfilter: Error: null input filename\n"); + exit(1); + } + } + if (argc > optind) + Usage(2); + if (FSUCCESS != IXmlOutputInit(&output_state, stdout, indent, IXML_OUTPUT_FLAG_NONE, NULL)) + exit(1); + if (FSUCCESS != Xml2ParseInputFile(filename, &output_state, fields)) + exit_code = 1; + IXmlOutputDestroy(&output_state); + exit(exit_code); +} diff --git a/IbaTools/opaxmlgenerate/COPYING b/IbaTools/opaxmlgenerate/COPYING new file mode 100644 index 0000000..0b0f4b3 --- /dev/null +++ b/IbaTools/opaxmlgenerate/COPYING @@ -0,0 +1,32 @@ +The files in this directory are subject to the following license: + +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +#[ICS VERSION STRING: unknown] diff --git a/IbaTools/opaxmlgenerate/Makefile b/IbaTools/opaxmlgenerate/Makefile new file mode 100644 index 0000000..46b021e --- /dev/null +++ b/IbaTools/opaxmlgenerate/Makefile @@ -0,0 +1,162 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** +# Makefile for opaxmlgenerate + +# Include Make Control Settings +include $(TL_DIR)/$(PROJ_FILE_DIR)/Makesettings.project + +#=============================================================================# +# Definitions: +#-----------------------------------------------------------------------------# + +# Name of SubProjects +DS_SUBPROJECTS = +# name of executable or downloadable image +EXECUTABLE = $(BUILDDIR)/opaxmlgenerate$(EXE_SUFFIX) +# list of sub directories to build +DIRS = +# C files (.c) +CFILES = \ + opaxmlgenerate.c \ + # Add more c files here +# C++ files (.cpp) +CCFILES = \ + # Add more cpp files here +# lex files (.lex) +LFILES = \ + # Add more lex files here +# archive library files (basename, $ARFILES will add MOD_LIB_DIR/prefix and suffix) +LIBFILES= +# Windows Resource Files (.rc) +RSCFILES = +# Windows IDL File (.idl) +IDLFILE = +# Windows Linker Module Definitions (.def) file for dll's +DEFFILE = +# targets to build during INCLUDES phase (add public includes here) +INCLUDE_TARGETS = \ + # Add more h hpp files here +# Non-compiled files +MISC_FILES = opatopology_links.txt opatopology_FIs.txt opatopology_SWs.txt opatopology_SMs.txt README.topology +# all source files +SOURCES = $(CFILES) $(CCFILES) $(LFILES) $(RSCFILES) $(IDLFILE) +# Source files to include in DSP File +DSP_SOURCES = $(INCLUDE_TARGETS) $(SOURCES) $(MISC_FILES) \ + $(RSCFILES) $(DEFFILE) $(MAKEFILE) +# all object files +OBJECTS = $(CFILES:.c=$(OBJ_SUFFIX)) $(CCFILES:.cpp=$(OBJ_SUFFIX)) \ + $(LFILES:.lex=$(OBJ_SUFFIX)) +RSCOBJECTS = $(RSCFILES:.rc=$(RES_SUFFIX)) +# targets to build during LIBS phase +LIB_TARGETS_IMPLIB = +LIB_TARGETS_ARLIB = # $(LIB_PREFIX)ResourceTest$(ARLIB_SUFFIX) +LIB_TARGETS_EXP = $(LIB_TARGETS_IMPLIB:$(ARLIB_SUFFIX)=$(EXP_SUFFIX)) +LIB_TARGETS_MISC = +# targets to build during CMDS phase +CMD_TARGETS_SHLIB = +CMD_TARGETS_EXE = $(EXECUTABLE) +CMD_TARGETS_MISC = opagentopology +# files to remove during clean phase +CLEAN_TARGETS_MISC = +CLEAN_TARGETS = $(OBJECTS) $(RSCOBJECTS) $(IDL_TARGETS) $(CLEAN_TARGETS_MISC) +# other files to remove during clobber phase +CLOBBER_TARGETS_MISC= +# sub-directory to install to within bin +BIN_SUBDIR = +# sub-directory to install to within include +INCLUDE_SUBDIR = + +# Additional Settings +#CLOCALDEBUG = User defined C debugging compilation flags [Empty] +#CCLOCALDEBUG = User defined C++ debugging compilation flags [Empty] +#CLOCAL = User defined C flags for compiling [Empty] +#CCLOCAL = User defined C++ flags for compiling [Empty] +#BSCLOCAL = User flags for Browse File Builder [Empty] +#DEPENDLOCAL = user defined makedepend flags [Empty] +#LINTLOCAL = User defined lint flags [Empty] +#LOCAL_INCLUDE_DIRS = User include directories to search for C/C++ headers [Empty] +#LDLOCAL = User defined C flags for linking [Empty] +#IMPLIBLOCAL = User flags for Object Lirary Manager [Empty] +#MIDLLOCAL = User flags for IDL compiler [Empty] +#RSCLOCAL = User flags for resource compiler [Empty] +#LOCALDEPLIBS = User libraries to include in dependencies [Empty] +#LOCALLIBS = User libraries to use when linking [Empty] +# (in addition to LOCALDEPLIBS) +#LOCAL_LIB_DIRS = User library directories for libpaths [Empty] + +CLOCAL=$(CIBACCESS) $(CPIE) +LOCALDEPLIBS=$(IBACCESS_USER_LIBS) Xml +LOCAL_INCLUDE_DIRS= +LOCALLIBS= +LOCAL_LIB_DIRS= + +ifneq "$(BUILD_TARGET_OS)" "VXWORKS" +LOCALLIBS+= expat +endif + +# Include Make Rules definitions and rules +include $(TL_DIR)/IbaTools/Makerules.module + +#=============================================================================# +# Overrides: +#-----------------------------------------------------------------------------# +#CCOPT = # C++ optimization flags, default lets build config decide +#COPT = # C optimization flags, default lets build config decide +#SUBSYSTEM = Subsystem to build for (none, console or windows) [none] +# (Windows Only) +#USEMFC = How Windows MFC should be used (none, static, shared, no_mfc) [none] +# (Windows Only) +#=============================================================================# + +#=============================================================================# +# Rules: +#-----------------------------------------------------------------------------# +# process Sub-directories +include $(TL_DIR)/Makerules/Maketargets.toplevel + +# build cmds and libs +include $(TL_DIR)/Makerules/Maketargets.build + +# install for includes, libs and cmds phases +include $(TL_DIR)/Makerules/Maketargets.install + +# install for stage phase +#include $(TL_DIR)/Makerules/Maketargets.stage +STAGE:: + $(VS)$(STAGE_INSTALL) $(STAGE_INSTALL_DIR_OPT) $(PROJ_STAGE_FASTFABRIC_DIR) $(EXECUTABLE) + $(VS)$(STAGE_INSTALL) $(STAGE_INSTALL_DIR_OPT) $(PROJ_STAGE_FASTFABRIC_DIR)/samples opatopology_links.txt opatopology_FIs.txt opatopology_SWs.txt opatopology_SMs.txt README.topology opagentopology + +# Unit test execution +#include $(TL_DIR)/Makerules/Maketargets.runtest + +#=============================================================================# + +#=============================================================================# +# DO NOT DELETE THIS LINE -- make depend depends on it. +#=============================================================================# diff --git a/IbaTools/opaxmlgenerate/README.topology b/IbaTools/opaxmlgenerate/README.topology new file mode 100644 index 0000000..3c3f93d --- /dev/null +++ b/IbaTools/opaxmlgenerate/README.topology @@ -0,0 +1,17 @@ +A sample use of opaxmlgenerate is provided in the script opagentopology, +which is in /sbin. The script invokes opaxmlgenerate, directing it to +read the following CSV input files which are in /usr/share/opa/samples: + +opatopology_links.txt contains the text CSV values for LinkSummary information. +opatopology_FIs.txt contains the text CSV values for HFI Nodes information. +opatopology_SWs.txt contains the text CSV values for SW Nodes information. +opatopology_SMs.txt contains the text CSV values for SM information. + +opagentopology invokes opaxmlgenerate, with command line options specifying +the XML element names for the CSV text data it will read. These names include +Link Rate, MTU Size, Cable Length, Cable Label, Port NodeGUID, Port Number, +Node Description, Port GUID, and Node Type among others. + +Note that opagentopology (not opaxmlgenerate) generates the XML version +string as well as the outermost enclosing element tags (LinkSummary, Nodes, +etc). diff --git a/IbaTools/opaxmlgenerate/opagentopology.sh b/IbaTools/opaxmlgenerate/opagentopology.sh new file mode 100644 index 0000000..6bf2c73 --- /dev/null +++ b/IbaTools/opaxmlgenerate/opagentopology.sh @@ -0,0 +1,88 @@ +#!/bin/bash +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] + + +Usage() +{ + echo "Usage: /usr/share/opa/samples/opagentopology [--help]" >&2 + echo " --help - produce full help text" >&2 + echo " opagentopology should be invoked using the full path - /usr/share/opa/samples/opagentopology " >&2 + + exit 2 +} + +Usage_full() +{ + echo "Usage: /usr/share/opa/samples/opagentopology [--help]" >&2 + echo " --help - produce full help text" >&2 + echo >&2 + echo " should be invoked using the full path - /usr/share/opa/samples/opagentopology." >&2 + echo " generates (to stdout) sample topology XML with subsections:" >&2 + echo " " >&2 + echo " " >&2 + echo " " >&2 + echo " " >&2 + + exit 0 +} + +# Run opaxmlgenerate with fabric topology link information + +if [ x"$1" = "x--help" ] +then + Usage_full +fi + +if [ $# -ge 1 ] +then + Usage +fi + +echo '' +echo '' +echo '' +/usr/sbin/opaxmlgenerate -X /usr/share/opa/samples/opatopology_links.txt -d \; -h Link -g Rate -g MTU -g Internal -g LinkDetails -h Cable -g CableLength -g CableLabel -g CableDetails -e Cable -h Port -g NodeGUID -g PortNum -g NodeDesc -g PortGUID -g NodeType -g PortDetails -e Port -h Port -g NodeGUID -g PortNum -g NodeDesc -g PortGUID -g NodeType -g PortDetails -e Port -e Link +echo '' +echo '' +echo '' +/usr/sbin/opaxmlgenerate -X /usr/share/opa/samples/opatopology_FIs.txt -d \; -h Node -g NodeGUID -g NodeDesc -g NodeDetails -e Node +echo '' +echo '' +/usr/sbin/opaxmlgenerate -X /usr/share/opa/samples/opatopology_SWs.txt -d \; -h Node -g NodeGUID -g NodeDesc -g NodeDetails -e Node +echo '' +echo '' +/usr/sbin/opaxmlgenerate -X /usr/share/opa/samples/opatopology_SMs.txt -d \; -h SM -g NodeGUID -g PortNum -g NodeDesc -g PortGUID -g NodeType -g SMDetails -e SM +echo '' +echo '' +echo '' + +exit 0 diff --git a/IbaTools/opaxmlgenerate/opatopology_FIs.txt b/IbaTools/opaxmlgenerate/opatopology_FIs.txt new file mode 100644 index 0000000..0aa977c --- /dev/null +++ b/IbaTools/opaxmlgenerate/opatopology_FIs.txt @@ -0,0 +1,2 @@ +0x0002c9020020e004;bender hfi1_0;More details about node +0x0002c9020025a678;mindy2 hfi1_0;Node details diff --git a/IbaTools/opaxmlgenerate/opatopology_SMs.txt b/IbaTools/opaxmlgenerate/opatopology_SMs.txt new file mode 100644 index 0000000..9d5f164 --- /dev/null +++ b/IbaTools/opaxmlgenerate/opatopology_SMs.txt @@ -0,0 +1 @@ +0x001175010025a678;1;mindy2 hfi1_0;0x0011750107000e6d;FI;details about SM diff --git a/IbaTools/opaxmlgenerate/opatopology_SWs.txt b/IbaTools/opaxmlgenerate/opatopology_SWs.txt new file mode 100644 index 0000000..5f11022 --- /dev/null +++ b/IbaTools/opaxmlgenerate/opatopology_SWs.txt @@ -0,0 +1,2 @@ +0x0011750107000df6;Switch 1234 Leaf 4; +0x0011750107000e6d;Switch 2345 Leaf 5; diff --git a/IbaTools/opaxmlgenerate/opatopology_links.txt b/IbaTools/opaxmlgenerate/opatopology_links.txt new file mode 100644 index 0000000..cf75fcf --- /dev/null +++ b/IbaTools/opaxmlgenerate/opatopology_links.txt @@ -0,0 +1,2 @@ +25g;2048;0;IO Server Link;11m;S4567;cable model 456;0x001175010020e004;1;bender hfi1_0;0x001175010020e004;FI;Some info about port;0x0011750107000df6;7;Switch 1234 Leaf 4;;SW; +25g;;0;;;;;0x001175010025a678;1;mindy2 hfi1_0;;FI;;0x0011750107000e6d;4;Switch 2345 Leaf 5;;SW; diff --git a/IbaTools/opaxmlgenerate/opaxmlgenerate.c b/IbaTools/opaxmlgenerate/opaxmlgenerate.c new file mode 100644 index 0000000..55305e4 --- /dev/null +++ b/IbaTools/opaxmlgenerate/opaxmlgenerate.c @@ -0,0 +1,717 @@ +/* BEGIN_ICS_COPYRIGHT7 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT7 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + + +/******************************************************************************* + * + * File: opaxmlgenerate.c + * + * Description: + * This file implements the opaxmlgenerate program. opaxmlgenerate takes + * CSV data as input and, with user-specified element names, generates + * sequences of XML containing the element values within start and end tag + * specifications. + * + * opaxmlgenerate uses libXml to manage the XML generation state and for ouptut + * functions. It calls the following functions: + * IXmlInit() + * IXmlOutputStartAttrTag() + * IXmlOutputEndTag() + * IXmlOutputStrLen() + * + * opaxmlgenerate uses 3 types of element names specified by the user. The + * types are distinguished by their command line option. -g specifies an + * an element name that, along with a value from the CSV input file, will + * be used to generate XML of the form 'value'. + * -h specifies an element name that will be used to generate an "enclosing" + * XML header start tag of the form ''. -e specifies an + * element name that will be used to generate an enclosing XML header end + * tag of the form ''. Enclosing elements do not contain + * a value, but serve to separate and organize the elements that do contain + * values. + * + * The operation of opaxmlgenerate is further controlled by the following + * command line options: + * -d delimiter - specifies the delimiter character that separates input + * values in the CSV input file; default is semicolon + * -i indent - specifies the number of spaces to indent each level of + * XML output; default is zero + * -X input_file - input CSV data from input_file + * -P param_file - input command line options (parameters) from param_file + * -v - verbose output: output progress reports during generation + * + * opaxmlgenerate generates sequences (fragments) of XML, as opposed to + * complete XML specifications. It is intended that opaxmlgenerate be + * invoked from within a script (typically multiple times), using multiple + * input files (with possibly different CSV formats) to create the desired + * XML output. The script would output any necessary XML header or trailer + * information (XML version or report information) as well as "glue" XML + * between fragments. + * + * NOTES: + * Output of start and end tags for enclosing elements is controlled by + * the placement of command line options -h and -e respectively with + * respect to -g options. No check for matching tags or proper nesting + * of tags is performed by opaxmlgenerate. + */ + + +/******************************************************************************* + * + * INCLUDES + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "ixml.h" + + +/******************************************************************************* + * + * DEFINES + */ + +#define OK 0 +#define ERROR (-1) + +#define NAME_PROG "opaxmlgenerate" // Program name +#define MAX_PARAMS_FILE 512 // Max number of param file parameters +#define MAX_ELEMENTS 100 // Max number of elements parsable +#define MAX_DELIMIT_CHARS 16 // Max size of delimiter string +#define MAX_INPUT_BUF 8192 // Max size of input buffer +#define MAX_PARAM_BUF 8192 // Max size of parameter file +#define MAX_FILENAME_CHARS 256 // Max size of file name +#define WHITE_SPACE " \t\r\n" // White space characters +#define OPTION_LEN 2 // string length of an option(eg. -P) + +// Element table entry +typedef struct +{ + int lenName; // Length of element name + char *pName; // Element name + int lenValue; // Length of element value + char *pValue; // Element value + int flags; // Flags as: xxxx xEHG + // E = 1 - End header + // H = 1 - Header + // G = 1 - Generate value +} ELEMENT_TABLE_ENTRY; + +// Element table flags: +#define ELEM_GENERATE 0x01 +#define ELEM_HEADER 0x02 +#define ELEM_END 0x04 + + +/******************************************************************************* + * + * GLOBAL VARIABLES + */ + +int g_exitstatus = 0; +int g_verbose = 0; +int g_quiet = 0; + + +/******************************************************************************* + * + * LOCAL VARIABLES + */ + +int numElementsTable = 0; // Number of elements in tbElements[] +uint32 numIndentChars = 0; // Num of chars per indent level + +FILE * hFileInput = NULL; // Input file handle (default stdin) + // Input file name (default stdin) +char nameFileInput[MAX_FILENAME_CHARS + 1] = "stdin"; +FILE * hFileOutput = NULL; // Output file handle (default stdout) +char nameFileOutput[MAX_FILENAME_CHARS] = "stdout"; // Output file name (default stdout) + +uint32 fvDebugProg = 0; // Debug/Trace variable as: + // 0MMM MMMM NNNN NNNN SSSS 21RC SIEB SNEB + +// Command line option table, each has a short and long flag name +struct option tbOptions[] = +{ + // Basic controls + { "verbose", no_argument, NULL, 'v' }, + { "generate", required_argument, NULL, 'g' }, + { "header", required_argument, NULL, 'h' }, + { "end", required_argument, NULL, 'e' }, + { "infile", required_argument, NULL, 'X' }, + { "pfile", required_argument, NULL, 'P' }, + { "delimit", required_argument, NULL, 'd' }, + { "indent", required_argument, NULL, 'i' }, + { "debug", required_argument, NULL, 'Z' }, + { 0 } +}; + +// Element table; contains information about each element of interest. +// Elements are contained in the table (0 - numElementsTable-1) in the +// order they appear on the command line. +ELEMENT_TABLE_ENTRY tbElements[MAX_ELEMENTS]; + +// IXml Output State +IXmlOutputState_t state; + +// Delimiter string buffer +char bfDelimit[MAX_DELIMIT_CHARS + 1] = ";"; + +// Input buffer +char bfInput[MAX_INPUT_BUF]; + + +/******************************************************************************* + * + * LOCAL FUNCTION PROTOTYPES + */ + +void dispElementRecord(ELEMENT_TABLE_ENTRY * pElement, const char * pValue); +void errUsage(void); +int findElement(const char *pElement); +void getRecu_opt( int argc, char ** argv, const char *pOptShort, + struct option tbOptLong[] ); + + +/******************************************************************************* + * + * dispElementRecord() + * + * Description: + * Display (output) an element, either generate (with value) or header (Start + * or End). + * + * Inputs: + * pElement - Pointer to tbElement to output + * pValue - Pointer to value string to output (NULL means no value) + * + * Outputs: + * none + */ +void dispElementRecord(ELEMENT_TABLE_ENTRY * pElement, const char * pValue) +{ + // Output header element name (as Start tag or End tag) + if (pElement->flags & ELEM_HEADER) + IXmlOutputStartAttrTag(&state, pElement->pName, NULL, NULL); + + else if (pElement->flags & ELEM_END) + IXmlOutputEndTag(&state, pElement->pName); + + // Output generate element name and value + else if ((pElement->flags & ELEM_GENERATE) && pValue) + IXmlOutputStrLen(&state, pElement->pName, pValue, strlen(pValue)); + +} // End of dispElementRecord() + + +/******************************************************************************* + * + * errUsage() + * + * Description: + * Output information about program usage and parameters. + * + * Inputs: + * none + * + * Outputs: + * none + */ +void errUsage(void) +{ + fprintf(stderr, "Usage: " NAME_PROG " [-v][-d delimiter][-i number][-g element][-h element]\n"); + fprintf(stderr, " [-e element][-X input_file][-P param_file]\n"); + fprintf(stderr, " At least 1 element must be specified\n"); + fprintf(stderr, " -g/--generate element - name of XML element to generate\n"); + fprintf(stderr, " can be used multiple times\n"); + fprintf(stderr, " values assigned to elements in order xxx ... \n"); + fprintf(stderr, " -h/--header element - name of XML element in which to enclose generated\n"); + fprintf(stderr, " XML elements\n"); + fprintf(stderr, " -e/--end element - name of header XML element to end (close)\n"); + fprintf(stderr, " -d/--delimit delimiter - delimiter char input between element values\n"); + fprintf(stderr, " default is semicolon\n"); + fprintf(stderr, " -i/--indent number - number of spaces to indent each level of XML\n"); + fprintf(stderr, " output; default is zero\n"); + fprintf(stderr, " -X/--infile input_file - generate XML from CSV in input_file\n"); + fprintf(stderr, " -P/--pfile param_file - read command parameters from param_file\n"); + fprintf(stderr, " -v/--verbose - verbose output: progress reports during generation\n"); + + if (hFileInput && (hFileInput != stdin)) + fclose(hFileInput); + + exit(2); +} // End of errUsage() + + +/******************************************************************************* + * + * findElement() + * + * Description: + * Find specified element in element table. + * + * Inputs: + * pElement - Pointer to element name + * + * Outputs: + * Index of element table containing element name, else + * -1 - Element name not found + */ +int findElement(const char *pElement) +{ + int ix; + int length; + + length = strlen(pElement); + for (ix = 0; ix < numElementsTable; ix++) + { + if ((tbElements[ix].lenName - 1) == length) + if (!strcmp(pElement, tbElements[ix].pName)) + return (ix); + } + + return (ERROR); + +} // End of findElement() + + +/******************************************************************************* + * + * getRecu_opt() + * + * Description: + * Get command line options (recursively). Parses command line options + * using short and long option (parameter) definitions. Parameters (global + * variables) are updated appropriately. The parameter '-P param_file' which + * takes command line options from a file is also handled. The -P parameter + * can be used within a parameter file; in such cases the function will call + * itself recursively. + * + * Inputs: + * argc - Number of input parameters + * argv - Array of pointers to input parameters + * pOptShort - Pointer to string of short option definitions + * tbOptLong - Array of long option definitions + * + * Outputs: + * none + */ +void getRecu_opt( int argc, char ** argv, const char *pOptShort, + struct option tbOptLong[] ) +{ + int ix; + int cOpt; // Option parsing char + int ixOpt; // Option parsing index + int lenStr; // String length + int argc_recu; // Recursive argc + char *argv_recu[MAX_PARAMS_FILE]; // Recursive argv + int optind_recu; // Recursive optind + char *optarg_recu; // Recursive optarg + + int ctCharParam; // Parameter file char count + FILE *hFileParam = NULL; // Parameter file handle + char nameFileParam[MAX_FILENAME_CHARS +1]; // Parameter file name + char bfParam[MAX_PARAM_BUF + 1]; + + // Input command line arguments + while ((cOpt = getopt_long(argc, argv, pOptShort, tbOptLong, &ixOpt)) != -1) + { + lenStr = 0; + switch (cOpt) + { + // Verbose + case 'v': + g_verbose = 1; + break; + + // Generate element name specification + case 'g': + // Header element name specification + case 'h': + // End (header) element name specification + case 'e': + if (numElementsTable == MAX_ELEMENTS) + { + fprintf(stderr, NAME_PROG ": Too many Element Names\n"); + errUsage(); + } + + else if (!optarg || ((lenStr = strlen(optarg) + 1) == 1)) + { + fprintf(stderr, NAME_PROG ": Invalid Element Name: %s\n", optarg ? optarg:""); + errUsage(); + } + + else + { + if ( (tbElements[numElementsTable].pName = malloc(lenStr)) ) + { + strcpy(tbElements[numElementsTable].pName, optarg); + tbElements[numElementsTable].lenName = lenStr; + } + + else + { + fprintf(stderr, NAME_PROG ": Unable to Allocate Name Memory\n"); + errUsage(); + } + + if (cOpt == 'g') + tbElements[numElementsTable++].flags |= ELEM_GENERATE; + + else if (cOpt == 'h') + tbElements[numElementsTable++].flags |= ELEM_HEADER; + + else if (cOpt == 'e') + tbElements[numElementsTable++].flags |= ELEM_END; + } + + break; + + // Delimiter string specification + case 'd': + if ( !optarg || ((lenStr = strlen(optarg)) == 0) || + (lenStr > MAX_DELIMIT_CHARS) ) + { + fprintf(stderr, NAME_PROG ": Invalid delimiter size: %d\n", lenStr); + errUsage(); + } + + strncpy(bfDelimit, optarg, MAX_DELIMIT_CHARS); + bfDelimit[MAX_DELIMIT_CHARS]=0; // Ensure null terminated + break; + + // Indent chars specification + case 'i': + if (FSUCCESS != StringToUint32(&numIndentChars, optarg, NULL, 0, TRUE)) { + fprintf(stderr, NAME_PROG ": Invalid indent parameter size: %d\n", lenStr); + errUsage(); + } + break; + + // Input file specification + case 'X': + if ( !optarg || ((lenStr = strlen(optarg)) == 0) || + (lenStr > MAX_FILENAME_CHARS) ) + { + fprintf(stderr, NAME_PROG ": Invalid Input File Name: %s\n", optarg ? optarg:""); + errUsage(); + } + + else if (hFileInput != stdin) + { + fprintf( stderr, NAME_PROG ": Multiple Input Files: %s and %s\n", + nameFileInput, optarg ); + errUsage(); + } + + if (strcmp(optarg, "-")) + { + strncpy(nameFileInput, optarg, MAX_FILENAME_CHARS); + nameFileInput[MAX_FILENAME_CHARS]=0; // Ensure null terminated + hFileInput = fopen(nameFileInput, "r"); + + if (!hFileInput) + { + fprintf( stderr, NAME_PROG ": Unable to Open Input File: %s\n", + nameFileInput ); + perror(""); + errUsage(); + } + } + + break; + + // Parameter file specification + case 'P': + if (!optarg || ((lenStr = strlen(optarg)) == 0) || + (lenStr > MAX_FILENAME_CHARS) ) + { + fprintf(stderr, NAME_PROG ": Invalid Parameter File Name: %s\n", optarg ? optarg:""); + errUsage(); + } + + // Open parameter file + strncpy(nameFileParam, optarg,MAX_FILENAME_CHARS); + nameFileParam[MAX_FILENAME_CHARS]=0; // Ensure null terminated. + hFileParam = fopen(nameFileParam, "r"); + + if (!hFileParam) + { + fprintf( stderr, NAME_PROG ": Unable to Open Parameter File: %s\n", + nameFileParam ); + perror(""); + errUsage(); + } + + // Read parameter file + if (g_verbose) + fprintf(stderr, NAME_PROG ": Reading Param File: %s\n", nameFileParam); + + ctCharParam = (int)fread(bfParam, 1, MAX_PARAM_BUF, hFileParam); + bfParam[MAX_PARAM_BUF-1]=0; + + if (ferror(hFileParam)) + { + fclose(hFileParam); + fprintf(stderr, NAME_PROG ": Read Error: %s\n", nameFileParam); + errUsage(); + } + + if ((ctCharParam == MAX_PARAM_BUF) && !feof(hFileParam)) + { + fclose(hFileParam); + fprintf( stderr, NAME_PROG ": Parameter file (%s) too large (> %d bytes)\n", + nameFileParam, MAX_PARAM_BUF ); + errUsage(); + } + + fclose(hFileParam); + + if (ctCharParam > 0) + { + // Parse parameter file into tokens + argc_recu = 2; + argv_recu[0] = nameFileParam; + + for (ix = 1; ; ix++, argc_recu++) + { + if (ix == MAX_PARAMS_FILE) + { + fprintf( stderr, NAME_PROG ": Parameter file (%s) has too many parameters (> %d)\n", + nameFileParam, MAX_PARAMS_FILE ); + errUsage(); + } + if ( (argv_recu[ix] = strtok((ix == 1) ? bfParam : NULL, WHITE_SPACE)) + == NULL ) + { + argc_recu--; + break; + } + + if (!strncmp(argv_recu[ix], "-P", OPTION_LEN)) + { + fprintf( stderr, NAME_PROG ": Parameter file (%s) cannot contain -P option\n", nameFileParam); + errUsage(); + } + + if ( (argv_recu[ix] - bfParam + strlen(argv_recu[ix]) + 1) == + ctCharParam ) + break; + + } + + // Process parameter file parameters + if (argc_recu > 1) + { + optind_recu = optind; // Save optind & optarg + optarg_recu = optarg; + optind = 1; // Init optind & optarg + optarg = NULL; + getRecu_opt(argc_recu, argv_recu, pOptShort, tbOptLong); + optind = optind_recu; // Restore optind & optarg + optarg = optarg_recu; + } + + } // End of if (ctCharParam > 0) + + break; + + // Debug trace specification + case 'Z': + if (FSUCCESS != StringToUint32(&fvDebugProg, optarg, NULL, 0, TRUE)) { + fprintf(stderr, NAME_PROG ": Invalid Debug Setting: %s\n", optarg); + errUsage(); + } + break; + + default: + fprintf(stderr, NAME_PROG ": Invalid Option -<%c>\n", cOpt); + errUsage(); + break; + + } // End of switch (cOpt) + + } // End of while ((cOpt = getopt_long(argc, argv, + + // Validate command line arguments + if (optind < argc) + { + fprintf(stderr, "%s: invalid argument %s\n", NAME_PROG, argv[optind]); + errUsage(); + } + +} // End of getRecu_opt() + + +/******************************************************************************* + * + * main() + * + * Description: + * main function for program. + * + * Inputs: + * argc - Number of input parameters + * argv - Array of pointers to input parameters + * + * Outputs: + * Exit status 0 - no errors + * Exit status 2 - error (input parameter, resources, file I/O, XML parsing) + */ +int main(int argc, char ** argv) +{ + int ix; // Loop index + int ctCharInput = 0; // Input file char count + char *pValue = NULL; // Pointer to current input value + char *pValueNext = bfInput + MAX_INPUT_BUF; // Ptr to next input value + + // Initialize for generation + hFileInput = stdin; + hFileOutput = stdout; + + for (ix = 0; ix < MAX_ELEMENTS; ix++) + { + tbElements[ix].lenName = 0; + tbElements[ix].pName = NULL; + tbElements[ix].lenValue = 0; + tbElements[ix].pValue = NULL; + tbElements[ix].flags = 0; + } + + // Get and validate command line arguments + getRecu_opt(argc, argv, "vg:h:e:X:P:d:i:Z:", tbOptions); + if (numElementsTable <= 0) + { + fprintf(stderr, NAME_PROG ": No Elements Specified\n"); + errUsage(); + } + + IXmlInit(&state, hFileOutput, numIndentChars, IXML_OUTPUT_FLAG_NONE, NULL); + + // Output Report + strcat(bfDelimit, "\n"); // Append New Line to bfDelimit + + for (ix = 0; ; ) + { + // Generate element + if (tbElements[ix].flags & ELEM_GENERATE) + { + // Check for end of bfInput + if ( ((pValueNext - bfInput) > (MAX_INPUT_BUF >> 1)) && + !feof(hFileInput) ) + { + // Shift bfInput[] and read input file + memmove(bfInput, pValueNext, MAX_INPUT_BUF + bfInput - pValueNext); + + if (g_verbose) + fprintf( stderr, NAME_PROG ": Reading Input File: %s\n", + nameFileInput ); + + ctCharInput = MAX_INPUT_BUF + bfInput - pValueNext + + (int)fread( bfInput + MAX_INPUT_BUF - pValueNext + bfInput, + 1, pValueNext - bfInput, hFileInput ); + pValueNext = bfInput; + + if (ferror(hFileInput)) + { + fprintf(stderr, NAME_PROG ": Read Error: %s\n", nameFileInput); + errUsage(); + } + } + + // Check for end of input file + if ((pValueNext - bfInput) >= ctCharInput) + { + fprintf( stderr, + NAME_PROG ": WARNING End of Input file (%s) before End of Element List (%d items)\n", + nameFileInput, numElementsTable ); + g_exitstatus = 2; + break; + } + + /* strtok() skips over multiple consecutive delimiters as a group; + the following causes a NULL element value to be processed if 2 + consecutive delimiters are encountered. + */ + if (!strchr(bfDelimit, *pValueNext)) + { + pValue = strtok(pValueNext, bfDelimit); + if (!pValue) + { + fprintf( stderr, + NAME_PROG ": WARNING Malformed Input file (%s) strtok() error.\n", + nameFileInput); + break; + } + dispElementRecord(&tbElements[ix++], pValue); + pValueNext = pValue + strlen(pValue) + 1; + } + + else + { + dispElementRecord(&tbElements[ix++], NULL); + pValueNext += 1; + } + } + + // Header or Header End element + else + dispElementRecord(&tbElements[ix++], NULL); + + // Check for end of tbElements[] + if (ix >= numElementsTable) + { + if ((pValueNext - bfInput) < ctCharInput) + ix = 0; // Wrap to beg of tbElements[] + + else // End of report + break; + } + + } // End of for (ix = 0; ; ) + + if (hFileInput && (hFileInput != stdin)) + fclose(hFileInput); + + return (g_exitstatus); + +} // End of main() + + +// End of file + diff --git a/IbaTools/portdown/Makefile b/IbaTools/portdown/Makefile new file mode 100644 index 0000000..caf9ca0 --- /dev/null +++ b/IbaTools/portdown/Makefile @@ -0,0 +1,163 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** +# Makefile for opaportconfig + +# Include Make Control Settings +include $(TL_DIR)/$(PROJ_FILE_DIR)/Makesettings.project + +#=============================================================================# +# Definitions: +#-----------------------------------------------------------------------------# + +# Name of SubProjects +DS_SUBPROJECTS = +# name of executable or downloadable image +EXECUTABLE = $(BUILDDIR)/opaportinfo$(EXE_SUFFIX) +# list of sub directories to build +DIRS = +# C files (.c) +CFILES = \ + opaportconfig.c \ + # Add more c files here +# C++ files (.cpp) +CCFILES = \ + # Add more cpp files here +# lex files (.lex) +LFILES = \ + # Add more lex files here +# archive library files (basename, $ARFILES will add MOD_LIB_DIR/prefix and suffix) +LIBFILES= +# Windows Resource Files (.rc) +RSCFILES = +# Windows IDL File (.idl) +IDLFILE = +# Windows Linker Module Definitions (.def) file for dll's +DEFFILE = +# targets to build during INCLUDES phase (add public includes here) +INCLUDE_TARGETS = \ + # Add more h hpp files here +# Non-compiled files +MISC_FILES = opaportconfig.sh +# all source files +SOURCES = $(CFILES) $(CCFILES) $(LFILES) $(RSCFILES) $(IDLFILE) +# Source files to include in DSP File +DSP_SOURCES = $(INCLUDE_TARGETS) $(SOURCES) $(MISC_FILES) \ + $(RSCFILES) $(DEFFILE) $(MAKEFILE) +# all object files +OBJECTS = $(CFILES:.c=$(OBJ_SUFFIX)) $(CCFILES:.cpp=$(OBJ_SUFFIX)) \ + $(LFILES:.lex=$(OBJ_SUFFIX)) +RSCOBJECTS = $(RSCFILES:.rc=$(RES_SUFFIX)) +# targets to build during LIBS phase +LIB_TARGETS_IMPLIB = +LIB_TARGETS_ARLIB = # $(LIB_PREFIX)ResourceTest$(ARLIB_SUFFIX) +LIB_TARGETS_EXP = $(LIB_TARGETS_IMPLIB:$(ARLIB_SUFFIX)=$(EXP_SUFFIX)) +LIB_TARGETS_MISC = +# targets to build during CMDS phase +CMD_TARGETS_SHLIB = +CMD_TARGETS_EXE = $(EXECUTABLE) +CMD_TARGETS_MISC = $(BUILDDIR)/opaportconfig$(EXE_SUFFIX) +# files to remove during clean phase +CLEAN_TARGETS_MISC = +CLEAN_TARGETS = $(OBJECTS) $(RSCOBJECTS) $(IDL_TARGETS) $(CLEAN_TARGETS_MISC) +# other files to remove during clobber phase +CLOBBER_TARGETS_MISC= +# sub-directory to install to within bin +BIN_SUBDIR = +# sub-directory to install to within include +INCLUDE_SUBDIR = + +# Additional Settings +#CLOCALDEBUG = User defined C debugging compilation flags [Empty] +#CCLOCALDEBUG = User defined C++ debugging compilation flags [Empty] +#CLOCAL = User defined C flags for compiling [Empty] +#CCLOCAL = User defined C++ flags for compiling [Empty] +#BSCLOCAL = User flags for Browse File Builder [Empty] +#DEPENDLOCAL = user defined makedepend flags [Empty] +#LINTLOCAL = User defined lint flags [Empty] +#LOCAL_INCLUDE_DIRS = User include directories to search for C/C++ headers [Empty] +#LDLOCAL = User defined C flags for linking [Empty] +#IMPLIBLOCAL = User flags for Object Lirary Manager [Empty] +#MIDLLOCAL = User flags for IDL compiler [Empty] +#RSCLOCAL = User flags for resource compiler [Empty] +#LOCALDEPLIBS = User libraries to include in dependencies [Empty] +#LOCALLIBS = User libraries to use when linking [Empty] +# (in addition to LOCALDEPLIBS) +#LOCAL_LIB_DIRS = User library directories for libpaths [Empty] + +CLOCAL=$(CIBACCESS) $(CPIE) +LOCAL_INCLUDE_DIRS= +ifeq "$(IB_STACK)" "IBACCESS" +LOCALDEPLIBS = $(IBACCESS_USER_LIBS) IbPrint +LOCALLIBS= +LOCAL_LIB_DIRS=$(IBACCESS_USER_LIB_DIRS) +else +LOCALDEPLIBS = $(IBACCESS_USER_LIBS) IbPrint opamgt-priv +LOCALLIBS=$(OPENIB_USER_LIBS) +LOCAL_LIB_DIRS=$(OPENIB_USER_LIB_DIRS) $(IBACCESS_USER_LIB_DIRS) +endif + +# Include Make Rules definitions and rules +include $(TL_DIR)/IbaTools/Makerules.module + +#=============================================================================# +# Overrides: +#-----------------------------------------------------------------------------# +#CCOPT = # C++ optimization flags, default lets build config decide +#COPT = # C optimization flags, default lets build config decide +#SUBSYSTEM = Subsystem to build for (none, console or windows) [none] +# (Windows Only) +#USEMFC = How Windows MFC should be used (none, static, shared, no_mfc) [none] +# (Windows Only) +#=============================================================================# + +#=============================================================================# +# Rules: +#-----------------------------------------------------------------------------# +# process Sub-directories +include $(TL_DIR)/Makerules/Maketargets.toplevel + +# build cmds and libs +include $(TL_DIR)/Makerules/Maketargets.build +$(BUILDDIR)/opaportconfig$(EXE_SUFFIX): $(BUILDDIR)/opaportinfo$(EXE_SUFFIX) + cp $(BUILDDIR)/opaportinfo$(EXE_SUFFIX) $(BUILDDIR)/opaportconfig$(EXE_SUFFIX) + +# install for includes, libs and cmds phases +include $(TL_DIR)/Makerules/Maketargets.install + +# install for stage phase +include $(TL_DIR)/Makerules/Maketargets.stage + +# Unit test execution +#include $(TL_DIR)/Makerules/Maketargets.runtest + +#=============================================================================# + +#=============================================================================# +# DO NOT DELETE THIS LINE -- make depend depends on it. +#=============================================================================# diff --git a/IbaTools/portdown/README b/IbaTools/portdown/README new file mode 100644 index 0000000..73dac90 --- /dev/null +++ b/IbaTools/portdown/README @@ -0,0 +1 @@ +Utility to query port state and/or change port state diff --git a/IbaTools/portdown/opaportconfig.c b/IbaTools/portdown/opaportconfig.c new file mode 100644 index 0000000..a906c4f --- /dev/null +++ b/IbaTools/portdown/opaportconfig.c @@ -0,0 +1,962 @@ +/* BEGIN_ICS_COPYRIGHT7 **************************************** + +Copyright (c) 2015-2018, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT7 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +#include +#include +#include +#include + +/* work around conflicting names */ +#include "infiniband/umad.h" +#include "infiniband/verbs.h" + +#include + +#include "iba/ib_types.h" +#include "iba/ib_sm_priv.h" +#include "iba/ib_helper.h" +#include "iba/ib_ibt.h" + +#include "iba/ipublic.h" +#include "ibprint.h" +#include "stl_print.h" + +PrintDest_t g_dest; +uint8 g_verbose = 0; // Debug aid: data turn on global verbose => debugging +uint32 debug_level = 0; // Debug aid: User passed-in clo; 0 = portdown; 1 = open-ib_utils; 2=debug for mad calls +struct omgt_port *g_omgt_port; +uint16_t mgmt_pkey = OMGT_DEFAULT_PKEY; + +#define SEND_WAIT_TIME (100) // 100 milliseconds for sends +#define FLUSH_WAIT_TIME (100) // 100 milliseconds for sends/recv during flush +#define RESP_WAIT_TIME (1000) // 1000 milliseconds for response recv + + +#define MGT_POOL_TAG MAKE_MEM_TAG('t','g', 'm', 'V') + +#define VRBSE_PRINT(format, args...) \ + do { if (g_verbose > 0) { printf(format, ##args); fflush(stdout); } } while (0) + +#if defined(DBGPRINT) +#undef DBGPRINT +#endif + +#define DBGPRINT(format, args...) \ + do { if (g_verbose > 1) { fflush(stdout); fprintf(stderr, format, ##args); } } while (0) + +// What command are we doing based on argv[0] and sub-command +enum cmd_t { + portdown=1, + portconfig=2, + portenable=3, + portdisable=4, + portinfo=5, + portbounce=6, + ledon=7, + ledoff=8 +} cmd; +char *cmdname; + +/** + * set the routing portion of the SMP packet + * + * @param dlid + * @param slid + * @param port + * @param smp + */ +void set_route(STL_LID dlid, STL_LID slid, uint8_t port, STL_SMP* smp) +{ + if (dlid) { + // lid routed to a remote node + smp->common.MgmtClass = MCLASS_SM_LID_ROUTED; + smp->common.AttributeModifier = 0x01000000 | port; + } else { + // local port control + smp->common.MgmtClass = MCLASS_SM_DIRECTED_ROUTE; + smp->common.AttributeModifier = 0x01000000 | port; + smp->SmpExt.DirectedRoute.DrSLID = STL_LID_PERMISSIVE; + smp->SmpExt.DirectedRoute.DrDLID = STL_LID_PERMISSIVE; + smp->common.u.DR.HopCount = 0; + smp->common.u.DR.HopPointer = 0; + smp->common.u.DR.s.D = 0; + } + + smp->common.u.DR.s.Status = 0; +} + +/** + * perform a Get(PortInfo) SMA request and wait for response + * + * @param dlid + * @param slid + * @param port + * @param smp + * + * @return int + */ +int get_port_info(STL_LID dlid, STL_LID slid, uint8_t port, STL_SMP* smp) +{ + STL_PORT_INFO* pPortInfo; + + MemoryClear(smp, sizeof(*smp)); + smp->common.BaseVersion = STL_BASE_VERSION; + smp->common.ClassVersion = STL_SM_CLASS_VERSION; + set_route(dlid, slid, port, smp); // MgmtClass and AttributeModifier + smp->common.mr.AsReg8 = 0; + smp->common.mr.s.Method = MMTHD_GET; + smp->common.AttributeID = MCLASS_ATTRIB_ID_PORT_INFO; + + // rest of fields should be ignored for a Get, zero'ed above + + if (cmd == portdown || cmd == portconfig || g_verbose) + { + if (dlid) { + VRBSE_PRINT("Sending Get(STLPortInfo) to LID 0x%08x Port %u\n", dlid, port); + } else { + VRBSE_PRINT("Sending Get(STLPortInfo) to Port %u\n", port); + } + } + + STL_BSWAP_SMP_HEADER(smp); + + { + struct omgt_mad_addr addr = { + lid : dlid, + qpn : 0, + qkey : 0, + pkey : mgmt_pkey + }; + size_t recv_size = sizeof(*smp); + if (FSUCCESS != omgt_send_recv_mad_no_alloc(g_omgt_port, (uint8_t *)smp, sizeof(*smp), &addr, + (uint8_t *)smp, &recv_size, RESP_WAIT_TIME, 0)) { + fprintf(stderr, "Failed to send MAD or receive response MAD\n"); + return FALSE; + } + } + + STL_BSWAP_SMP_HEADER(smp); + if (smp->common.u.DR.s.Status != MAD_STATUS_SUCCESS) { + fprintf(stderr, "MAD returned with Bad Status: %s\n", + iba_mad_status_msg2(smp->common.u.DR.s.Status)); + return FALSE; + } + + pPortInfo = (STL_PORT_INFO *)stl_get_smp_data(smp); + BSWAP_STL_PORT_INFO(pPortInfo); + + return TRUE; +} + +/** + * output the contents of a PortInfo SMP packet + * + * @param title + * @param portGuid + * @param smp + */ +void show_port_info(const char* title, EUI64 portGuid, STL_SMP* smp) +{ + STL_PORT_INFO* pPortInfo = (STL_PORT_INFO *)stl_get_smp_data(smp); + int32_t hfi_num = -1; + char hfi_name[IBV_SYSFS_NAME_MAX] = {0}; + (void)omgt_port_get_hfi_num(g_omgt_port, &hfi_num); + (void)omgt_port_get_hfi_name(g_omgt_port, hfi_name); + + printf("%s\n", title); + printf("Port %u Info on HFI %u (%.*s)\n", smp->common.AttributeModifier & 0xFF, + hfi_num, IBV_SYSFS_NAME_MAX, hfi_name); + PrintStlPortInfo(&g_dest, 3, pPortInfo, portGuid, 0); +} + +/** + * build a Set(PortInfo) SMP packet + * + * @param dlid + * @param slid + * @param port + * @param smp + * @param state + * @param physstate + * @param width + * @param speed + * @param portGuid + * @param getInfo + */ +void initialize_set_port_info(STL_LID dlid, STL_LID slid, int have_nlid, STL_LID nlid, uint8_t port, + STL_SMP *smp, uint8_t state, uint8_t physstate, uint16_t width, uint16_t speed, uint8_t crc, + EUI64 portGuid, uint16_t pkey8b, const STL_SMP *getInfo) +{ + STL_PORT_INFO* pPortInfo; + + if (! getInfo) { + // no Get data available + MemoryClear(smp, sizeof(*smp)); + } else { + // use attributes in get as starting point + MemoryCopy(smp, getInfo, sizeof(*smp)); + } + + smp->common.BaseVersion = STL_BASE_VERSION; + smp->common.ClassVersion = STL_SM_CLASS_VERSION; + smp->common.mr.AsReg8 = 0; + smp->common.mr.s.Method = MMTHD_SET; + set_route(dlid, slid, port, smp); // MgmtClass and AttributeModifier + smp->common.AttributeID = MCLASS_ATTRIB_ID_PORT_INFO; + smp->M_Key = 0; + pPortInfo = (STL_PORT_INFO *)stl_get_smp_data(smp); + if (! getInfo) { + // no Get data available + pPortInfo->LID = 0; + pPortInfo->MasterSMLID = 0; + pPortInfo->Subnet.Timeout = 8; + // hopefully other invalid fields won't stop port state change + } + if (have_nlid) + pPortInfo->LID = nlid; + pPortInfo->PortStates.s.PortState = state; + pPortInfo->PortStates.s.PortPhysicalState = physstate; + pPortInfo->LinkWidth.Enabled = width; + pPortInfo->LinkSpeed.Enabled = speed; + pPortInfo->PortLTPCRCMode.s.Enabled = crc; + pPortInfo->s4.OperationalVL = 0; + if (pkey8b) { + if (g_verbose) + printf("Enabling 8B and 10B PKey: 0x%x\n", pkey8b); + pPortInfo->P_Keys.P_Key_8B = pkey8b; + pPortInfo->P_Keys.P_Key_10B = pkey8b; + } + if (g_verbose) + show_port_info("Setting Port State:", dlid?0:portGuid, smp); + BSWAP_STL_PORT_INFO(pPortInfo); + STL_BSWAP_SMP_HEADER(smp); +} + +/** + * send a pre-built MAD and output what we are doing + * + * @param hfi + * @param portGuid + * @param dlid + * @param slid + * @param port + * @param smp + * + * @return int + */ +FSTATUS send_led_info(bool enabled, unsigned hfi, EUI64 portGuid, STL_LID dlid, uint8_t dport, STL_LID slid, uint8_t lport) +{ + FSTATUS fstatus = FSUCCESS; + + const char *str; + char hfistr[40]; + STL_SMP returnedSmp; + STL_SMP smp; + + STL_LED_INFO* pLedInfo; + + MemoryClear(&smp, sizeof(smp)); + + smp.common.BaseVersion = STL_BASE_VERSION; + smp.common.ClassVersion = STL_SM_CLASS_VERSION; + smp.common.mr.AsReg8 = 0; + smp.common.mr.s.Method = MMTHD_SET; + set_route(dlid, slid, dport, &smp); // MgmtClass and AttributeModifier + smp.common.AttributeID = MCLASS_ATTRIB_ID_LED_INFO; + + + pLedInfo = (STL_LED_INFO *)stl_get_smp_data(&smp); + pLedInfo->u.s.LedMask = enabled? 1: 0; + + BSWAP_STL_LED_INFO(pLedInfo); + STL_BSWAP_SMP_HEADER(&smp); + + + str = enabled ? "Enabling LED" : "Disabling LED"; + if (hfi > 0) + { + snprintf(hfistr, sizeof(hfistr), " on HFI %u", hfi); + } else { + hfistr[0] = '\0'; + } + if (dlid) { + printf("%s at LID 0x%08x Port %u via local port %u (0x%016"PRIx64")%s\n", + str, dlid, dport, lport, portGuid, hfistr); + } else { + printf("%s %u (0x%016"PRIx64")%s\n", str, lport, portGuid, hfistr); + } + + MemoryClear(&returnedSmp, sizeof(returnedSmp)); + { + struct omgt_mad_addr addr = { + lid : dlid, + qpn : 0, + qkey : 0, + pkey : mgmt_pkey + }; + size_t recv_size = sizeof(returnedSmp); + fstatus = omgt_send_recv_mad_no_alloc(g_omgt_port, (uint8_t *)&smp, sizeof(smp), &addr, + (uint8_t *)&returnedSmp, &recv_size, RESP_WAIT_TIME, 0); + } + if (FSUCCESS == fstatus) + { + STL_BSWAP_SMP_HEADER(&returnedSmp); + if (returnedSmp.common.u.DR.s.Status != MAD_STATUS_SUCCESS) { + fprintf(stderr, "MAD returned with Bad Status: %s\n", + iba_mad_status_msg2(returnedSmp.common.u.DR.s.Status)); + } + if (g_verbose) + { + printf("status: 0x%x\n", returnedSmp.common.u.NS.Status.AsReg16); + } + } + + return fstatus; +} + + + + +FSTATUS send_port_info(unsigned hfi, EUI64 portGuid, STL_LID dlid, uint8_t dport, STL_LID slid, uint8_t lport, STL_SMP* smp) +{ + FSTATUS fstatus = FSUCCESS; + const char *str; + char hfistr[IBV_SYSFS_NAME_MAX + 40]; + STL_SMP returnedSmp; + + switch (cmd) + { + case portenable: + str = "Enabling Port"; + break; + case portdisable: + str = "Disabling Port"; + break; + case portbounce: + str = "Bouncing Port"; + break; + case portinfo: + str = "Querying Port"; + break; + default: + fprintf(stdout,"Designed for use by expert users only!\n"); + str = "Sending Set(STLPortInfo) to Port"; + break; + } + + if (hfi > 0) + { + snprintf(hfistr, sizeof(hfistr), " on HFI %u", hfi); + } else { + int32_t hfi_num; + char hfi_name[IBV_SYSFS_NAME_MAX] = {0}; + (void)omgt_port_get_hfi_num(g_omgt_port, &hfi_num); + (void)omgt_port_get_hfi_name(g_omgt_port, hfi_name); + snprintf(hfistr, sizeof(hfistr), " on HFI %d (%.*s)", hfi_num, + IBV_SYSFS_NAME_MAX, hfi_name); + } + if (dlid) { + printf("%s at LID 0x%08x Port %u via local port %u (0x%016"PRIx64")%s\n", + str, dlid, dport, lport, portGuid, hfistr); + } else { + printf("%s %u (0x%016"PRIx64")%s\n", str, lport, portGuid, hfistr); + } + + MemoryClear(&returnedSmp, sizeof(returnedSmp)); + + { + struct omgt_mad_addr addr = { + lid : dlid, + qpn : 0, + qkey : 0, + pkey : mgmt_pkey + }; + size_t recv_size = sizeof(returnedSmp); + fstatus = omgt_send_recv_mad_no_alloc(g_omgt_port, (uint8_t *)smp, sizeof(*smp), &addr, + (uint8_t *)&returnedSmp, &recv_size, RESP_WAIT_TIME, 0); + } + if (FSUCCESS == fstatus) + { + STL_PORT_INFO* pPortInfo = (STL_PORT_INFO *)stl_get_smp_data(&returnedSmp); + STL_BSWAP_SMP_HEADER(&returnedSmp); + if (returnedSmp.common.u.DR.s.Status != MAD_STATUS_SUCCESS) { + fprintf(stderr, "MAD returned with Bad Status: %s\n", + iba_mad_status_msg2(returnedSmp.common.u.DR.s.Status)); + } + if (g_verbose) + { + BSWAP_STL_PORT_INFO(pPortInfo); + printf("status: 0x%x\n", returnedSmp.common.u.NS.Status.AsReg16); + show_port_info("New Port State:", dlid?0:portGuid, &returnedSmp); + } + } + + return fstatus; +} + +/** ========================================================================= + * Global param's for the 2 modes + */ +struct { + STL_LID dlid; + uint8 dport; + int have_dport; // was dport provided (dport can be provided as 0) + STL_LID slid; + STL_LID nlid; + int have_nlid; // was nlid provided (nlid can be provided as 0) + uint8 hfi; + uint32 repeat; + EUI64 portGuid; + unsigned get; + uint8 state; + uint8 physstate; + uint16_t width; + uint16_t speed; + uint8 crc; + unsigned cycle; + int port_in_hfi; + uint16 pkey8b; +} param = { + dlid : 0, // if dlid provided by user, use MCLASS_SM_LID_ROUTED else MCLASS_SM_DIRECTED_ROUTE + dport : 0, // default is the port that the request was issued to + have_dport : 0, + slid : 0, // our local LID + nlid : 0, // Used the change the base lid of the port. + have_nlid : 0, + hfi : 0, + repeat : 0, + portGuid : 0, + get : 1, + state : IB_PORT_NOP, // default to no link state change + physstate : IB_PORT_PHYS_NOP, // default to no physical state change + width : STL_LINK_WIDTH_NOP, + speed : STL_LINK_SPEED_NOP, + crc : STL_PORT_LTP_CRC_MODE_NONE, + cycle : 0, // cycle port to cause speed or link change to activate + port_in_hfi : 0, + pkey8b : 0 // value to program in 8B and 10B pkey in PortInfo +}; + +static void run_stl_mode(void) +{ + STL_SMP setPortInfo; + STL_SMP getPortInfo; + + + if(cmd == ledon) { + send_led_info(true, param.hfi, param.portGuid, param.dlid, param.dport, param.slid, + param.port_in_hfi); + return; + }; + if(cmd == ledoff) { + send_led_info(false, param.hfi, param.portGuid, param.dlid, param.dport, param.slid, + param.port_in_hfi); + return; + } + + + memset( &setPortInfo, 0, sizeof(setPortInfo)); + memset( &getPortInfo, 0, sizeof(getPortInfo)); + + // for explicit param.physstate of sleep or disabled, do not cycle port + if (param.cycle && param.physstate == IB_PORT_PHYS_NOP) + { + if (param.have_dport && param.dport == 0) + // for Switch Port 0, Set to Down will bounce port + param.state = IB_PORT_DOWN; + else { + // Set to Polling will bounce port + param.physstate = IB_PORT_PHYS_POLLING; + } + } + + if (param.get) { + STL_PORT_INFO* pPortInfo; + + if (get_port_info(param.dlid, param.slid, + param.dlid?param.dport:param.port_in_hfi, &getPortInfo)) { + if (g_verbose || cmd == portinfo) + show_port_info("Present Port State:", param.dlid?0:param.portGuid, &getPortInfo); + } else { + exit(1); + } + if (cmd == portinfo) + return; + + pPortInfo = (STL_PORT_INFO *)stl_get_smp_data(&getPortInfo); + + if (cmd == portenable + && !param.cycle + && (pPortInfo->PortStates.s.PortPhysicalState == IB_PORT_PHYS_POLLING + || pPortInfo->PortStates.s.PortPhysicalState == IB_PORT_PHYS_LINKUP)) { + /* no need to "enable" a port which is already "enabled" */ + return; + } + + { + char buf1[64]; + char buf2[64]; + + if (param.speed != IB_LINK_SPEED_NOP) { + uint16_t supported = pPortInfo->LinkSpeed.Supported; + uint16_t unsupported = (param.speed & ~supported); + if (unsupported) { + fprintf(stderr, "%s: ignoring unsupported speed bits: 0x%x [%s] (port supports 0x%x [%s])\n", + cmdname, unsupported, + StlLinkSpeedToText(unsupported, buf1, sizeof(buf1)), + supported, + StlLinkSpeedToText(supported, buf2, sizeof(buf2))); + fprintf (stderr,"%s: Error: Unsupported speed: %u [%s]\n", + cmdname, param.speed, + StlLinkSpeedToText(param.speed, buf1, sizeof(buf1))); + exit(1); + } + } + if (param.width != STL_LINK_WIDTH_NOP) { + uint16_t supported = pPortInfo->LinkWidth.Supported; + uint16_t unsupported = (param.width & ~supported); + if (unsupported) { + fprintf(stderr, "%s: ignoring unsupported width bits: 0x%x [%s] (port supports 0x%x [%s])\n", + cmdname, unsupported, + StlLinkWidthToText(unsupported, buf1, sizeof(buf1)), + supported, + StlLinkWidthToText(supported, buf2, sizeof(buf2))); + fprintf(stderr, "%s: Error: Unsupported width: %u [%s]\n", + cmdname, param.width, + StlLinkWidthToText(param.width, buf1, sizeof(buf1))); + exit(1); + } + } + if (param.crc != STL_PORT_LTP_CRC_MODE_NONE) { + uint16_t supported = pPortInfo->PortLTPCRCMode.s.Supported; + uint16_t unsupported = (param.crc & ~supported); + if (unsupported) { + fprintf(stderr, "%s: ignoring unsupported CRC bits: 0x%x [%s] (port supports 0x%x [%s])\n", + cmdname, unsupported, + StlPortLtpCrcModeToText(unsupported, buf1, sizeof(buf1)), + supported, + StlPortLtpCrcModeToText(supported, buf2, sizeof(buf2))); + fprintf(stderr, "%s: Error: Unsupported CRC: %u [%s]\n", + cmdname, param.crc, + StlPortLtpCrcModeToText(param.crc, buf1, sizeof(buf1))); + exit(1); + } + } + switch (param.physstate) { + case IB_PORT_PHYS_NOP: + case IB_PORT_PHYS_DISABLED: + case IB_PORT_PHYS_POLLING: + case STL_PORT_PHYS_TEST: + break; + default: + fprintf(stderr, "%s: Error: Unsupported Port Physical State: %u\n", + cmdname, param.physstate); + exit(1); + } + } + initialize_set_port_info(param.dlid, param.slid, param.have_nlid, param.nlid, + param.dlid?param.dport:param.port_in_hfi, + &setPortInfo, param.state, param.physstate, + param.width, param.speed, param.crc, param.portGuid, param.pkey8b, &getPortInfo); + } else { + initialize_set_port_info(param.dlid, param.slid, param.have_nlid, param.nlid, + param.dlid?param.dport:param.port_in_hfi, + &setPortInfo, param.state, param.physstate, + param.width, param.speed, param.crc, param.portGuid, param.pkey8b, NULL); + } + + + FSTATUS status; + status = send_port_info(param.hfi, param.portGuid, param.dlid, param.dport, param.slid, + param.port_in_hfi, &setPortInfo); + + if (FSUCCESS == status) { + struct timeval nowTime, endTime; + if(gettimeofday(&nowTime, NULL) < 0) { + fprintf(stderr, "Unable to get current time, aborting\n"); + exit(1); + } + endTime = nowTime; + endTime.tv_sec+=param.repeat; + while((timercmp(&nowTime,&endTime,<))) { + sleep(1); + if (FSUCCESS != send_port_info(param.hfi, param.portGuid, param.dlid, param.dport, + param.slid, param.port_in_hfi, &setPortInfo)) { + exit(1); + } + if(gettimeofday(&nowTime, NULL) < 0) { + fprintf(stderr, "Unable to get current time, aborting\n"); + exit(1); + } + } + } else { + fprintf(stderr, "%s: Unable to send port information; status=%d\n", cmdname, status); + } + +} + +/** + * determine how we've been invoked + */ +static enum cmd_t determine_invocation(const char *argv0, char **command, const char **options, + struct option **longopts) +{ + enum cmd_t rc; + + *command = strrchr(argv0, '/'); // Find last '/' in path + if (*command != NULL) { + (*command)++; // Skip over last '/' + } else { + *command = (char *)argv0; + } + + if ( (strcmp(*command, "opaportconfig") == 0)) { + static struct option long_options[] = { + {"pkey8b", 0, 0, 1}, // undoc opt to override pkey cntrl for testing + {"help", 0, 0, 2}, // display help text. + {0,0,0,0} + }; + *longopts = long_options; + rc = portconfig; + *options = "l:m:h:p:r:zS:P:s:w:c:vL:"; + } else if ( (strcmp(*command, "opaportinfo") == 0)) { + static struct option long_options[] = { + {"help", 0, 0, 2}, // display help text. + {0,0,0,0} + }; + *longopts = long_options; + rc = portinfo; + *options = "l:m:h:p:v"; + } else { + fprintf(stderr, "Invalid command name '%s' (must be opaportinfo or opaportconfig\n", + *command); + exit(1); + } + return (rc); +} + +static void initialize_opamgt(uint8_t hfi, uint8_t port, int *port_in_hfi, + STL_LID *slid, EUI64 *portGuid) +{ + int status = 0; + uint8_t port_num; + + struct omgt_params params = {.debug_file = g_verbose > 2 ? stderr : NULL}; + if ((status = omgt_open_port_by_num (&g_omgt_port, hfi, port, ¶ms)) != 0) { + fprintf(stderr, "failed to open port hfi %d:%d: %s\n", hfi, port, omgt_status_totext(status)); + exit(1); + } + + (void)omgt_port_get_hfi_port_num(g_omgt_port, &port_num); + (void)omgt_port_get_port_lid(g_omgt_port, slid); + (void)omgt_port_get_port_guid(g_omgt_port, portGuid); + *port_in_hfi = port_num; + if (omgt_find_pkey(g_omgt_port, mgmt_pkey) < 0) { + if (param.dlid) { + fprintf(stderr, "ERROR: Local port does not have management privileges\n"); + goto error; + } + mgmt_pkey = 0x7fff; + if (omgt_find_pkey(g_omgt_port, mgmt_pkey) < 0) { + fprintf(stderr, "ERROR: Local port does not have management connectivity!!!\n" + "neither 0xffff nor 0x7fff is in pkey table???\n"); + goto error; + } + } + + return; + +error: + omgt_close_port(g_omgt_port); + exit(1); +} + +/** + * display usage + */ +void Usage(void) +{ + if (cmd == portconfig) { + fprintf(stderr, "%s manually programs a local port; Designed for use by expert users only.\n\b Non-expert users should use other tools such as opaenableports, opadisableports and\n\b opaportinfo for basic functionality\n\n", cmdname); + fprintf(stderr, "Usage: %s [-l lid [-m dest_port]] [-h hfi] [-p port] [-r secs] [-z]\n", cmdname); + fprintf(stderr, " [-z] [-S state] [-P physstate] [-s speed] [-w width]\n"); + fprintf(stderr, " [-c LTPCRC] [-v] [-L lid] []\n"); + fprintf(stderr, " : %s [--help]\n", cmdname); + } else { + fprintf(stderr, "%s displays local port info.\n\n", cmdname); + fprintf(stderr, "Usage: %s [-l lid [-m dest_port]] [-h hfi] [-p port] [-v]\n", cmdname); + fprintf(stderr, " : %s [--help]\n", cmdname); + } + + fprintf(stderr, "\n"); + fprintf(stderr, " -l lid - destination lid, default is local port\n"); + fprintf(stderr, " -m dest_port - destination port, default is port with given lid\n"); + fprintf(stderr, " useful to access switch ports\n"); + fprintf(stderr, " -h hfi - HFI to send through/to. Default is first HFI\n"); + fprintf(stderr, " -p port - Port to send through/to. Default is first port\n"); + + if (cmd == portconfig) + { + fprintf(stderr, "\n"); + fprintf(stderr, " -- one of the following\n"); + fprintf(stderr, " enable - Enable port\n"); + fprintf(stderr, " disable - disable port\n"); + fprintf(stderr, " bounce - bounce port\n"); + fprintf(stderr, " Bouncing remote ports may cause timeouts.\n"); + fprintf(stderr, " ledon - port LED on\n"); + fprintf(stderr, " ledoff - port LED off\n"); + fprintf(stderr, "\n"); + fprintf(stderr, " Configuration options\n"); + fprintf(stderr, "\n"); + fprintf(stderr, " -r secs - repeat to keep port down for secs\n"); + fprintf(stderr, " -S state - new State (default is 0)\n"); + fprintf(stderr, " 0 - no-op\n"); + fprintf(stderr, " 1 - down\n"); + fprintf(stderr, " 2 - init\n"); + fprintf(stderr, " 3 - armed\n"); + fprintf(stderr, " 4 - active\n"); + fprintf(stderr, " -P physstate - new physical State (default is 0)\n"); + fprintf(stderr, " Note: Not all transitions are valid.\n"); + fprintf(stderr, " 0 - no-op\n"); + fprintf(stderr, " 2 - polling\n"); + fprintf(stderr, " 3 - disabled\n"); + fprintf(stderr, " 11 - Phy-Test - current physstate must be 'disabled'\n"); + fprintf(stderr, " -s speed - new link speeds enabled (default is 0)\n"); + fprintf(stderr, " To enable multiple speeds, use sum of desired speeds\n"); + fprintf(stderr, " 0 - no-op\n"); + fprintf(stderr, " 2 - 0x0002 - 25 Gb/s\n"); + fprintf(stderr, " -w width - new link widths enabled (default is 0)\n"); + fprintf(stderr, " To enable multiple widths, use sum of desired widths\n"); + fprintf(stderr, " 0 - no-op\n"); + fprintf(stderr, " 1 - 0x01 - 1x\n"); + fprintf(stderr, " 2 - 0x02 - 2x\n"); + fprintf(stderr, " 4 - 0x04 - 3x\n"); + fprintf(stderr, " 8 - 0x08 - 4x\n"); + fprintf(stderr, " -c CRC - new CRCs enabled (default is 0)\n"); + fprintf(stderr, " to enable multiple CRCs, use sum of desired CRCs\n"); + fprintf(stderr, " 0 - no-op\n"); + fprintf(stderr, " 1 - 0x1 - 14-bit LTP CRC mode\n"); + fprintf(stderr, " 2 - 0x2 - 16-bit LTP CRC mode\n"); + fprintf(stderr, " 4 - 0x4 - 48-bit LTP CRC mode\n"); + fprintf(stderr, " 8 - 0x8 - 12/16 bits per lane LTP CRC mode\n"); + } + + fprintf(stderr, "\n"); + fprintf(stderr, "The -h and -p options permit a variety of selections:\n"); + fprintf(stderr, " -h 0 1st port in system (this is the default)\n"); + fprintf(stderr, " -h x 1st port on HFI x\n"); + fprintf(stderr, " -h 0 -p y port y within system\n"); + fprintf(stderr, " -h x -p y HFI x, port y\n"); + + fprintf(stderr, "\n"); + fprintf(stderr, " DEBUG options\n"); + fprintf(stderr, "\n"); + fprintf(stderr, " -v - verbose output. Additional invocations will turn on debugging,\n" + " openib debugging and libibumad debugging.\n"); + + if (cmd == portconfig) { + fprintf(stderr, " -z - do not get port info first, clear most port attributes\n"); + fprintf(stderr, " -L lid - set PortInfo.LID = lid\n"); + } + + fprintf(stderr, "\n"); + + exit(2); +} + +/** + * main + * + * @param argc + * @param argv + * + * @return int + */ +int main(int argc, char** argv) +{ + uint8 port = 1; + int c; + const char *options; + struct option *longopts; + int opt_idx; + int cycleOverride = 0; + + cmd = determine_invocation(argv[0], &cmdname, &options, &longopts); + VRBSE_PRINT("Debug: Cmd=%s(%d); Options=%s\n", cmdname, cmd, options); + + PrintDestInitFile(&g_dest, stdout); + + while (-1 != (c = getopt_long(argc, argv, options, longopts, &opt_idx))) { + switch (c) { + /* Process Long options */ + case 1: /* --pkey8b */ + param.pkey8b=0x8001; + break; + case 2: /* --help */ + Usage(); + break; + /* End Long options */ + case 'v': + g_verbose++; + if (g_verbose>3) umad_debug(g_verbose-3); + break; + case 'L': + if (FSUCCESS != StringToUint32(¶m.nlid, optarg, NULL, 0, TRUE)) { + fprintf(stderr, "%s: Invalid LID: %s\n", cmdname, optarg); + Usage(); + } else + param.have_nlid = 1; + break; + case 'l': + if (FSUCCESS != StringToUint32(¶m.dlid, optarg, NULL, 0, TRUE)) { + fprintf(stderr, "%s: Invalid DLID: %s\n", cmdname, optarg); + Usage(); + } + break; + case 'm': + if (FSUCCESS != StringToUint8(¶m.dport, optarg, NULL, 0, TRUE)) { + fprintf(stderr, "%s: Invalid destination port: %s\n", cmdname, optarg); + Usage(); + } else + param.have_dport = 1; + break; + case 'h': + if (FSUCCESS != StringToUint8(¶m.hfi, optarg, NULL, 0, TRUE)) { + fprintf(stderr, "%s: Invalid HFI Number: %s\n", cmdname, optarg); + Usage(); + } + break; + case 'p': + if (FSUCCESS != StringToUint8(&port, optarg, NULL, 0, TRUE)) { + fprintf(stderr, "%s: Invalid Port Number: %s\n", cmdname, optarg); + Usage(); + } + if (port == 0) { + fprintf(stderr, "%s: Invalid port number, First Port is 1\n", cmdname); + exit(1); + } + break; + case 'r': + if (FSUCCESS != StringToUint32(¶m.repeat, optarg, NULL, 0, TRUE)) { + fprintf(stderr, "%s: Invalid Repeat: %s\n", cmdname, optarg); + Usage(); + } + break; + case 'z': + param.get=0; + break; + case 's': + if (FSUCCESS != StringToUint16(¶m.speed, optarg, NULL, 0, TRUE)) { + fprintf(stderr, "%s: Invalid Speed: %s\n", cmdname, optarg); + Usage(); + } + if (param.speed) + param.cycle = 1; + break; + case 'w': + if (FSUCCESS != StringToUint16(¶m.width, optarg, NULL, 0, TRUE)) { + fprintf(stderr, "%s: Invalid Width: %s\n", cmdname, optarg); + Usage(); + } + if (param.width) + param.cycle = 1; + break; + case 'c': + if (FSUCCESS != StringToUint8(¶m.crc, optarg, NULL, 0, TRUE)) { + fprintf(stderr, "%s: Invalid CRC: %s\n", cmdname, optarg); + Usage(); + } + if (param.crc) + param.cycle = 1; + break; + case 'S': + if (FSUCCESS != StringToUint8(¶m.state, optarg, NULL, 0, TRUE) + || param.state > IB_PORT_STATE_MAX) { + fprintf(stderr, "%s: Invalid State: %s\n", cmdname, optarg); + Usage(); + } + break; + case 'P': + if (FSUCCESS != StringToUint8(¶m.physstate, optarg, NULL, 0, TRUE)) { + fprintf(stderr, "%s: Invalid PhysState: %s\n", cmdname, optarg); + Usage(); + } + cycleOverride = 1; + break; + default: + Usage(); + break; + } + } + + if(cycleOverride) + param.cycle = 0; + + /* process sub-command */ + if (argc != optind) { + char *subcmd = argv[optind]; + + if (strcmp(cmdname, "opaportinfo") == 0) { + Usage(); + } + + if ( (strcmp(subcmd, "enable") == 0)) { + cmd = portenable; + param.state = IB_PORT_NOP; + param.physstate = IB_PORT_PHYS_POLLING; + } else if ( (strcmp(subcmd, "disable") == 0)) { + cmd = portdisable; + param.state = IB_PORT_NOP; + param.physstate = IB_PORT_PHYS_DISABLED; + } else if ( (strcmp(subcmd, "bounce") == 0)) { + cmd = portbounce; + param.cycle = 1; + } else if ( (strcmp(subcmd, "ledon") == 0)) { + cmd = ledon; + } else if ( (strcmp(subcmd, "ledoff") == 0)) { + cmd = ledoff; + } else { + fprintf(stderr, "Error: sub command '%s' not found\n", subcmd); + Usage(); + } + } + + if (param.have_dport && ! param.dlid) { + fprintf(stderr, "%s: -m option only valid in conjunction with -l\n", cmdname); + Usage(); + } + + initialize_opamgt(param.hfi, port, ¶m.port_in_hfi, ¶m.slid, ¶m.portGuid); + + run_stl_mode(); + + return 0; +} // int main(int argc, char** argv) diff --git a/IbaTools/portdown/opaportconfig.sh b/IbaTools/portdown/opaportconfig.sh new file mode 100755 index 0000000..6a84bc9 --- /dev/null +++ b/IbaTools/portdown/opaportconfig.sh @@ -0,0 +1,187 @@ +#!/bin/bash +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] + +# opaportconfig arguments +# -s speed = new link speeds enabled (default is 0) +# 0 - no-op +# 1 - 2.5 Gb/s +# 2 - 5 Gb/s +# 4 - 10 Gb/s +# to enable multiple speeds, use sum of desired speeds +# 255 - enable all supported +# +HFIPORTS="1:1" # space separated list of HFI:PORT to act on +# other examples: (uncomment exactly 1) +#HFIPORTS="1:2" # port 2 on HFI 1 +#HFIPORTS="1:1 1:2" # port 1 and 2 on HFI 1 +#HFIPORTS="1:1 2:1" # port 1 on HFI 1 and port 1 on HFI 2 +# Below will force DDR +ARGS="-s 2" # additional arguments to use for all HFIs/PORTs +# Other examples: (uncomment exactly 1) +#ARGS="-s 1" # force SDR +#ARGS="-s 4" # force QDR +#ARGS="-s 3" # negotiate SDR or DDR +#ARGS="-s 7" # negotiate SDR, DDR or QDR + +# opaportconfig use opaportconfig to force link speed +# +# chkconfig: 35 16 84 +# description: Force HFI port speed +# processname: +### BEGIN INIT INFO +# Provides: opaportconfig +# Required-Start: openibd +# Required-Stop: +# Default-Start: 2 3 5 +# Default-Stop: 0 1 2 +# Description: use opaportconfig to force link speed +### END INIT INFO + +PATH=/bin:/sbin:/usr/bin:/usr/sbin + +# just in case no functions script +echo_success() { echo "[ OK ]"; } +echo_failure() { echo "[FAILED]"; } + +my_rc_status_v() +{ + res=$? + if [ $res -eq 0 ] + then + echo_success + else + echo_failure + fi + echo + my_rc_status_all=$(($my_rc_status_all || $res)) +} + +if [ -f /etc/init.d/functions ]; then + . /etc/init.d/functions +elif [ -f /etc/rc.d/init.d/functions ] ; then + . /etc/rc.d/init.d/functions +elif [ -s /etc/rc.status ]; then + . /etc/rc.status + rc_reset + my_rc_status_v() + { + res=$? + [ $res -eq 0 ] || false + rc_status -v + my_rc_status_all=$(($my_rc_status_all || $res)) + } +fi + +my_rc_status_all=0 +my_rc_exit() { exit $my_rc_status_all; } +my_rc_status() { my_rc_status_all=$(($my_rc_status_all || $?)); } + +cmd=$1 + +Usage() +{ + echo "Usage: $0 [start|stop|restart]" >&2 + echo " start - configure port" >&2 + echo " stop - Noop" >&2 + echo " restart - restart (eg. stop then start) the Port config" >&2 + echo " status - show present port configuration" >&2 + exit 2 +} + +start() +{ + local res hfi port hfiport + + echo -n "Starting opaportconfig: " + res=0 + for hfiport in $HFIPORTS + do + hfi=$(echo $hfiport|cut -f1 -d:) + port=$(echo $hfiport|cut -f2 -d:) + echo -n "Setting HFI $hfi Port $port: " + /sbin/opaportconfig -h $hfi -p $port $ARGS >/dev/null + res=$(($res || $?)) + [ $res -eq 0 ] || false + my_rc_status_v + done + if [ $res -eq 0 ] + then + touch /var/lock/subsys/opaportconfig + fi + return $res +} + +stop() +{ + local res + + echo -n "Stopping opaportconfig: " + # nothing to do + res=0 + my_rc_status_v + rm -f /var/lock/subsys/opaportconfig + return $res +} + +status() +{ + local res hfi port hfiport + + echo -n "Checking port state: " + res=0 + for hfiport in $HFIPORTS + do + hfi=$(echo $hfiport|cut -f1 -d:) + port=$(echo $hfiport|cut -f2 -d:) + echo -n "HFI $hfi " + /sbin/opaportconfig -h $hfi -p $port -v|tail -15 + res=$(($res || $?)) + [ $res -eq 0 ] || false + my_rc_status_v + done + return $res +} + +case "$cmd" in + start) + start;; + stop) + stop;; + restart) + stop; start;; + status) + status;; + *) + Usage;; +esac + +my_rc_exit diff --git a/IbaTools/saquery/Makefile b/IbaTools/saquery/Makefile new file mode 100644 index 0000000..8bf897b --- /dev/null +++ b/IbaTools/saquery/Makefile @@ -0,0 +1,174 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** +# Makefile for saquery + +# Include Make Control Settings +include $(TL_DIR)/$(PROJ_FILE_DIR)/Makesettings.project + +#=============================================================================# +# Definitions: +#-----------------------------------------------------------------------------# + +# Name of SubProjects +DS_SUBPROJECTS = +# name of executable or downloadable image +EXECUTABLE = $(BUILDDIR)/opasaquery$(EXE_SUFFIX) +# list of sub directories to build +DIRS = +# C files (.c) +CFILES = \ + saquery.c \ + # Add more c files here +# C++ files (.cpp) +CCFILES = \ + # Add more cpp files here +# lex files (.lex) +LFILES = \ + # Add more lex files here +# archive library files (basename, $ARFILES will add MOD_LIB_DIR/prefix and suffix) +LIBFILES= +# Windows Resource Files (.rc) +RSCFILES = +# Windows IDL File (.idl) +IDLFILE = +# Windows Linker Module Definitions (.def) file for dll's +DEFFILE = +# targets to build during INCLUDES phase (add public includes here) +INCLUDE_TARGETS = \ + # Add more h hpp files here +# Non-compiled files +MISC_FILES = opamgt_tls.xml opamgt_tls.xml-sample +# all source files +SOURCES = $(CFILES) $(CCFILES) $(LFILES) $(RSCFILES) $(IDLFILE) +# Source files to include in DSP File +DSP_SOURCES = $(INCLUDE_TARGETS) $(SOURCES) $(MISC_FILES) \ + $(RSCFILES) $(DEFFILE) $(MAKEFILE) +# all object files +OBJECTS = $(CFILES:.c=$(OBJ_SUFFIX)) $(CCFILES:.cpp=$(OBJ_SUFFIX)) \ + $(LFILES:.lex=$(OBJ_SUFFIX)) +RSCOBJECTS = $(RSCFILES:.rc=$(RES_SUFFIX)) +# targets to build during LIBS phase +LIB_TARGETS_IMPLIB = +LIB_TARGETS_ARLIB = # $(LIB_PREFIX)ResourceTest$(ARLIB_SUFFIX) +LIB_TARGETS_EXP = $(LIB_TARGETS_IMPLIB:$(ARLIB_SUFFIX)=$(EXP_SUFFIX)) +LIB_TARGETS_MISC = +# targets to build during CMDS phase +CMD_TARGETS_SHLIB = +CMD_TARGETS_EXE = $(EXECUTABLE) +CMD_TARGETS_MISC = opashowmc opagetvf opagetvf_env +# files to remove during clean phase +CLEAN_TARGETS_MISC = +CLEAN_TARGETS = $(OBJECTS) $(RSCOBJECTS) $(IDL_TARGETS) $(CLEAN_TARGETS_MISC) +# other files to remove during clobber phase +CLOBBER_TARGETS_MISC= +# sub-directory to install to within bin +BIN_SUBDIR = +# sub-directory to install to within include +INCLUDE_SUBDIR = + +# Additional Settings +#CLOCALDEBUG = User defined C debugging compilation flags [Empty] +#CCLOCALDEBUG = User defined C++ debugging compilation flags [Empty] +#CLOCAL = User defined C flags for compiling [Empty] +#CCLOCAL = User defined C++ flags for compiling [Empty] +#BSCLOCAL = User flags for Browse File Builder [Empty] +#DEPENDLOCAL = user defined makedepend flags [Empty] +#LINTLOCAL = User defined lint flags [Empty] +#LOCAL_INCLUDE_DIRS = User include directories to search for C/C++ headers [Empty] +#LDLOCAL = User defined C flags for linking [Empty] +#IMPLIBLOCAL = User flags for Object Lirary Manager [Empty] +#MIDLLOCAL = User flags for IDL compiler [Empty] +#RSCLOCAL = User flags for resource compiler [Empty] +#LOCALDEPLIBS = User libraries to include in dependencies [Empty] +#LOCALLIBS = User libraries to use when linking [Empty] +# (in addition to LOCALDEPLIBS) +#LOCAL_LIB_DIRS = User library directories for libpaths [Empty] + +CLOCAL=$(CIBACCESS) $(CPIE) +LOCAL_INCLUDE_DIRS= +ifeq "$(IB_STACK)" "IBACCESS" +LOCALDEPLIBS=$(IBACCESS_USER_LIBS) IbPrint Xml +LOCALLIBS= +LOCAL_LIB_DIRS=$(IBACCESS_USER_LIB_DIRS) +else +LOCALDEPLIBS=$(IBACCESS_USER_LIBS) IbPrint opamgt-priv Xml +LOCALLIBS=$(OPENIB_USER_LIBS) +LOCAL_LIB_DIRS=$(OPENIB_USER_LIB_DIRS) $(IBACCESS_USER_LIB_DIRS) +endif + +ifneq "$(BUILD_TARGET_OS)" "VXWORKS" +LOCALLIBS+= expat +endif + +# Include Make Rules definitions and rules +include $(TL_DIR)/IbaTools/Makerules.module + +#=============================================================================# +# Overrides: +#-----------------------------------------------------------------------------# +#CCOPT = # C++ optimization flags, default lets build config decide +#COPT = # C optimization flags, default lets build config decide +#SUBSYSTEM = Subsystem to build for (none, console or windows) [none] +# (Windows Only) +#USEMFC = How Windows MFC should be used (none, static, shared, no_mfc) [none] +# (Windows Only) +#=============================================================================# + +#=============================================================================# +# Rules: +#-----------------------------------------------------------------------------# + +opamgt_tls.xml-sample: opamgt_tls.xml + $(CP) $< $@ + +# process Sub-directories +include $(TL_DIR)/Makerules/Maketargets.toplevel + +# build cmds and libs +include $(TL_DIR)/Makerules/Maketargets.build + +# install for includes, libs and cmds phases +include $(TL_DIR)/Makerules/Maketargets.install + +# install for stage phase +include $(TL_DIR)/Makerules/Maketargets.stage +STAGE:: + $(VS)$(STAGE_INSTALL) $(STAGE_INSTALL_DIR_OPT) $(PROJ_STAGE_SAMPLES_DIR)/saquery $(CFILES) README Makefile.sample doqueries.sh + $(VS)$(STAGE_INSTALL) $(STAGE_INSTALL_DIR_OPT) $(PROJ_STAGE_FASTFABRIC_DIR) opashowmc opamgt_tls.xml + $(VS)$(STAGE_INSTALL) $(STAGE_INSTALL_DIR_OPT) $(PROJ_STAGE_FASTFABRIC_DIR)/samples opamgt_tls.xml-sample + + +# Unit test execution +#include $(TL_DIR)/Makerules/Maketargets.runtest + +#=============================================================================# + +#=============================================================================# +# DO NOT DELETE THIS LINE -- make depend depends on it. +#=============================================================================# diff --git a/IbaTools/saquery/Makefile.sample b/IbaTools/saquery/Makefile.sample new file mode 100644 index 0000000..1622775 --- /dev/null +++ b/IbaTools/saquery/Makefile.sample @@ -0,0 +1,41 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] + +all: opasaquery doqueries + +opasaquery: saquery.c + $(CC) $(CFLAGS) -DIB_STACK_IBACCESS $< -o $@ -libt -lpublic + +clean: + rm -f saquery.o + +clobber: clean + rm -f opasaquery doqueries diff --git a/IbaTools/saquery/README b/IbaTools/saquery/README new file mode 100644 index 0000000..6f1730c --- /dev/null +++ b/IbaTools/saquery/README @@ -0,0 +1,4 @@ +[ICS VERSION STRING: unknown] + +Perform uncached queries of the SA, demonstrates most of the queries +supported by the Subnet Data interface diff --git a/IbaTools/saquery/create_mcast.sh b/IbaTools/saquery/create_mcast.sh new file mode 100755 index 0000000..608b326 --- /dev/null +++ b/IbaTools/saquery/create_mcast.sh @@ -0,0 +1,63 @@ +#!/bin/bash +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +#[ICS VERSION STRING: unknown] + +# test script, not in any build. Helps to create many multicast groups +set -x +for k in 0 1 2 3 4 5 6 7 8 9 a b c d e f +do +for j in 0 1 2 3 4 5 6 7 8 9 a b c d e f +do + for i in 0 1 2 3 4 5 6 7 8 9 a b c d e f + do + #route add -net 224.0.$j.$i netmask 255.255.255.255 gw 172.21.35.23 + #route add -net 224.0.$j.$i netmask 255.255.255.255 gw 172.21.35.23 + #ipmaddr add 00:ff:ff:ff:ff:12:60:1b:00:00:00:00:00:00:00:01:ff:00:0$k:$i$j dev ib0 + ipmaddr delete 00:ff:ff:ff:ff:12:60:1b:00:00:00:00:00:00:00:01:ff:00:0$k:$i$j dev ib0 + #ipmaddr add 00:ff:ff:ff:ff:12:60:1b:00:00:00:00:00:00:00:02:ff:00:0$k:$i$j dev ib0 + ipmaddr delete 00:ff:ff:ff:ff:12:60:1b:00:00:00:00:00:00:00:02:ff:00:0$k:$i$j dev ib0 + > /dev/null + done +done +done +for k in 0 1 2 3 +do +for j in 0 +do + for i in 0 + do + #ipmaddr add 00:ff:ff:ff:ff:12:60:1b:00:00:00:00:00:00:00:02:ff:00:0$k:$i$j dev ib0 + #ipmaddr delete 00:ff:ff:ff:ff:12:60:1b:00:00:00:00:00:00:00:02:ff:00:0$k:$i$j dev ib0 + > /dev/null + done +done +done + diff --git a/IbaTools/saquery/doqueries.sh b/IbaTools/saquery/doqueries.sh new file mode 100755 index 0000000..d3a03b3 --- /dev/null +++ b/IbaTools/saquery/doqueries.sh @@ -0,0 +1,256 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] + +# for queries we need 2 valid guids and a node description in the fabric +# for ease, guids can be specified as the last 6 digits of a SilverStorm Guid +# for a node in the fabric. or you can edit the assignments below appropriately +if [ "$1" = "" ] +then + serial=000380 +else + serial="$1" +fi +if [ "$2" = "" ] +then + serial2=000101 +else + serial2="$2" +fi +if [ "$3" = "" ] +then + nodedesc=duster +else + nodedesc="$3" +fi +nodeguid=0x0011750198$serial2 +sysguid=0x0011750198$serial2 +portguid=0x00117501a0$serial2 +portguid2=0x00117501a0$serial2 +subnet=0xfe80000000000000 # IBTA defined default subnet prefix + +set -x + +# sample of all valid queries +# note some combinations of inputs and outputs are not supported + +# query all records of a given type +opasaquery -v +opasaquery -v -o systemguid +opasaquery -v -o nodeguid +opasaquery -v -o portguid +opasaquery -v -o lid +opasaquery -v -o desc +opasaquery -v -o path +opasaquery -v -o node +opasaquery -v -o portinfo +opasaquery -v -o sminfo +opasaquery -v -o swinfo +opasaquery -v -o link +opasaquery -v -o service +opasaquery -v -o mcmember +opasaquery -v -o inform +opasaquery -v -o scsc +opasaquery -v -o scsl +opasaquery -v -o scvlnt +opasaquery -v -o linfdb +opasaquery -v -o mcfdb +opasaquery -v -o vlarb +opasaquery -v -o pkey +opasaquery -v -o vfinfo +opasaquery -v -o vfinfocsv +opasaquery -v -o vfinfocsv2 +opasaquery -v -o classportinfo +opasaquery -v -o fabricinfo +opasaquery -v -o quarantine +opasaquery -v -o conginfo +opasaquery -v -o swcongset +opasaquery -v -o swportcong +opasaquery -v -o hficongset +opasaquery -v -o hficongcon +opasaquery -v -o bfrctrl +opasaquery -v -o cableinfo +opasaquery -v -o portgroup +opasaquery -v -o portgroupfdb + + +# query by node type +opasaquery -v -t fi +opasaquery -v -t sw +opasaquery -v -o systemguid -t fi +opasaquery -v -o nodeguid -t fi +opasaquery -v -o portguid -t fi +opasaquery -v -o lid -t fi +opasaquery -v -o desc -t fi +opasaquery -v -o node -t fi + +# query by lid +opasaquery -v -l 1 +opasaquery -v -l 1 -o systemguid +opasaquery -v -l 1 -o nodeguid +opasaquery -v -l 1 -o portguid +opasaquery -v -l 1 -o lid +opasaquery -v -l 1 -o desc +opasaquery -v -l 1 -o path +opasaquery -v -l 1 -o node +opasaquery -v -l 1 -o portinfo +opasaquery -v -l 0xc000 -o mcmember +opasaquery -v -l 1 -o inform +opasaquery -v -l 1 -o swinfo +opasaquery -v -l 1 -o linfdb +opasaquery -v -l 1 -o mcfdb +opasaquery -v -l 1 -o vlarb +opasaquery -v -l 1 -o pkey +opasaquery -v -l 1 -o scsc +opasaquery -v -l 1 -o slsc +opasaquery -v -l 1 -o scvlt +opasaquery -v -l 1 -o scvlnt +opasaquery -v -l 1 -o classportinfo +opasaquery -v -l 1 -o fabricinfo +opasaquery -v -l 1 -o quarantine +opasaquery -v -l 1 -o conginfo +opasaquery -v -l 1 -o swcongset +opasaquery -v -l 1 -o swportcong +opasaquery -v -l 1 -o hficongset +opasaquery -v -l 1 -o hficongcon +opasaquery -v -l 1 -o bfrctrl +opasaquery -v -l 1 -o cableinfo +opasaquery -v -l 1 -o portgroup +opasaquery -v -l 1 -o portgroupfdb + + +# query by system image guid +opasaquery -v -s $sysguid +opasaquery -v -o systemguid -s $sysguid +opasaquery -v -o nodeguid -s $sysguid +opasaquery -v -o portguid -s $sysguid +opasaquery -v -o lid -s $sysguid +opasaquery -v -o desc -s $sysguid +opasaquery -v -o node -s $sysguid + +# query by system image guid of 0 (eg. nodes not supporting this optional field) +opasaquery -v -s 0 +opasaquery -v -o systemguid -s 0 +opasaquery -v -o nodeguid -s 0 +opasaquery -v -o portguid -s 0 +opasaquery -v -o lid -s 0 +opasaquery -v -o desc -s 0 +opasaquery -v -o node -s 0 + +# query by node guid +opasaquery -v -n $nodeguid +opasaquery -v -o systemguid -n $nodeguid +opasaquery -v -o nodeguid -n $nodeguid +opasaquery -v -o portguid -n $nodeguid +opasaquery -v -o lid -n $nodeguid +opasaquery -v -o desc -n $nodeguid + +# query by port guid +opasaquery -v -g $portguid +opasaquery -v -o systemguid -g $portguid +opasaquery -v -o nodeguid -g $portguid +opasaquery -v -o portguid -g $portguid +opasaquery -v -o lid -g $portguid +opasaquery -v -o desc -g $portguid +opasaquery -v -o path -g $portguid +opasaquery -v -o node -g $portguid +opasaquery -v -o service -g $portguid +opasaquery -v -o mcmember -g $portguid # SM bug +#opasaquery -v -I -o inform -g $portguid #IB legacy +opasaquery -v -o trace -g $portguid + +# query by port gid +opasaquery -v -o path -u $subnet:$portguid +opasaquery -v -o service -u $subnet:$portguid # sm does not support +opasaquery -v -o mcmember -u $subnet:$portguid +#opasaquery -v -I -o inform -u $subnet:$portguid #IB legacy +opasaquery -v -o trace -u $subnet:$portguid + +# query by mc gid +opasaquery -v -o mcmember -m 0xff02000000000000:0x0000000000000001 +opasaquery -v -o vfinfo -m 0xff02000000000000:0x0000000000000001 +opasaquery -v -o vfinfocsv -m 0xff02000000000000:0x0000000000000001 +opasaquery -v -o vfinfocsv2 -m 0xff02000000000000:0x0000000000000001 + +# query by node desc +opasaquery -v -d $nodedesc +opasaquery -v -o systemguid -d $nodedesc +opasaquery -v -o nodeguid -d $nodedesc +opasaquery -v -o portguid -d $nodedesc +opasaquery -v -o lid -d $nodedesc +opasaquery -v -o desc -d $nodedesc +opasaquery -v -o node -d $nodedesc +opasaquery -v -o vfinfo -d "Default" # VF Name +opasaquery -v -o vfinfocsv -d "Default" # VF Name +opasaquery -v -o vfinfocsv2 -d "Default" # VF Name + +# query by port guid pair +opasaquery -v -o path -P "$portguid2 $portguid" +opasaquery -v -o trace -P "$portguid2 $portguid" + +# query by gid pair +opasaquery -v -o path -G "$subnet:$portguid2 $subnet:$portguid" +opasaquery -v -o trace -G "$subnet:$portguid2 $subnet:$portguid" + +# query by port guid list +opasaquery -v -o path -a "$portguid2;$portguid" + +# query by gid list +opasaquery -v -o path -A "$subnet:$portguid2;$subnet:$portguid" + +# query by SL +opasaquery -v -L 0 -o path +opasaquery -v -L 0 -o vfinfo +opasaquery -v -L 0 -o vfinfocsv +opasaquery -v -L 0 -o vfinfocsv2 + +# query by serviceId +opasaquery -v -S 1 -o path +opasaquery -v -S 1 -o vfinfo +opasaquery -v -S 1 -o vfinfocsv +opasaquery -v -S 1 -o vfinfocsv2 + +# query by VfIndex +opasaquery -v -i 0 -o vfinfo +opasaquery -v -i 0 -o vfinfocsv +opasaquery -v -i 0 -o vfinfocsv2 + +# query by pkey +opasaquery -v -k 0x7fff -o path +opasaquery -v -k 0x7fff -o mcmember # unsupported +opasaquery -v -k 0x7fff -o vfinfo +opasaquery -v -k 0x7fff -o vfinfocsv +opasaquery -v -k 0x7fff -o vfinfocsv2 + +#new queries added in STL-2 +#opasaquery -v -o bwarb +#opasaquery -v -o dglist +#opasaquery -v -o dgmember +#opasaquery -v -o dgmember -D All diff --git a/IbaTools/saquery/opagetvf.sh b/IbaTools/saquery/opagetvf.sh new file mode 100755 index 0000000..a891591 --- /dev/null +++ b/IbaTools/saquery/opagetvf.sh @@ -0,0 +1,156 @@ +#!/bin/bash +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] + +# This script selects a VF based on the parameters given +# It will return exactly 1 VF, represented in a CSV format +# name:index:pkey:sl:mtu:rate:option_flags +# if there is no matching VF, a non-zero exit code is returned +# this script is intended for use in mpirun and wrapper scripts to +# select a VF and aid in exported env variables + +Usage_full() +{ + echo "Usage: opagetvf [-h hfi] [-p port] [-e]" >&2 + echo " [-d vfname|-S serviceId|-m mcgid|-i vfIndex|-k pkey|-L sl]" >&2 + echo " or" >&2 + echo " opagetvf --help" >&2 + echo " --help - produce full help text" >&2 + echo " -h hfi - hfi to send via, default is 1st hfi" >&2 + echo " -p port - port to send via, default is 1st active port" >&2 + echo " -e - output mtu and rate as enum values, 0=unspecified" >&2 + echo " -d vfname - query by VirtualFabric Name" >&2 + echo " -S serviceId - query by Application ServiceId" >&2 + echo " -m gid - query by Application Multicast GID" >&2 + echo " -i vfindex - query by VirtualFabric Index" >&2 + echo " -k pkey - query by VirtualFabric PKey" >&2 + echo " -L SL - query by VirtualFabric SL" >&2 + + echo "for example:" >&2 + echo " opagetvf -d 'Compute'" >&2 + echo " opagetvf -h 2 -p 2 -d 'Compute'" >&2 + exit 0 +} + +Usage() +{ + echo "Usage: opagetvf [-e] [-d vfname|-S serviceId|-m mcgid]" >&2 + echo " or" >&2 + echo " opagetvf --help" >&2 + echo " --help - produce full help text" >&2 + echo " -e - output mtu and rate as enum values, 0=unspecified" >&2 + echo " -d vfname - query by VirtualFabric Name" >&2 + echo " -S serviceId - query by Application ServiceId" >&2 + echo " -m gid - query by Application Multicast GID" >&2 + + echo "for example:" >&2 + echo " opagetvf -d 'Compute'" >&2 + exit 2 +} + +if [ x"$1" = "x--help" ] +then + Usage_full +fi + +query_args="" +output_arg=vfinfocsv +while getopts h:p:ed:S:m:i:k:L: param +do + case $param in + h) query_args="$query_args -$param '$OPTARG'";; + p) query_args="$query_args -$param '$OPTARG'";; + e) output_arg=vfinfocsv2;; + d) query_args="$query_args -$param '$OPTARG'";; + S) query_args="$query_args -$param '$OPTARG'";; + m) query_args="$query_args -$param '$OPTARG'";; + i) query_args="$query_args -$param '$OPTARG'";; + k) query_args="$query_args -$param '$OPTARG'";; + L) query_args="$query_args -$param '$OPTARG'";; + ?) Usage;; + esac +done +shift $((OPTIND -1)) +if [ $# -ge 1 ] +then + Usage +fi + +vfs=$(eval /usr/sbin/opasaquery -o $output_arg $query_args) +if [ $? != 0 ] +then + echo "opagetvf: SA query failed" >&2 + exit 1 +fi +if [ -z "$vfs" -o "$vfs" = "No Records Returned" ] +then + echo "opagetvf: VirtualFabric Not Found: $query_args" >&2 + exit 1 +fi + +# if more than 1 VF was returned, filter out the default partition +# and return the 1st one after it +# if the 1st two are both for the default partition, return the 1st one +lines=$(echo "$vfs"|wc -l) +candidate_vf=$(echo "$vfs"|head -1) +candidate_pkey=$(echo "$candidate_vf"|cut -d ':' -f 3) +for line in $(seq 2 $lines) +do + vf=$(echo "$vf"|head -$line|tail -1) + [ -z "$vf" ] && continue # should not happen + pkey=$(echo "$vf"|cut -d ':' -f 3) + + # prefer a VF which we are a full member of + if [ $(($candidate_pkey & 0x8000)) -ne 0 -a $(($pkey & 0x8000)) -eq 0 ] + then + continue + fi + if [ $(($candidate_pkey & 0x8000)) -eq 0 -a $(($pkey & 0x8000)) -ne 0 ] + then + candidate_vf="$vf" + candidate_pkey="$pkey" + continue + fi + + # prefer a non-default partition + if [ $(($candidate_pkey & 0x7fff)) -eq $((0x7fff)) \ + -a $(($pkey & 0x7fff)) -ne $((0x7fff)) ] + then + candidate_vf="$vf" + candidate_pkey="$pkey" + continue + fi + + # otherwise, stick with our existing candidate +done + +echo "$candidate_vf" +exit 0 diff --git a/IbaTools/saquery/opagetvf_env.sh b/IbaTools/saquery/opagetvf_env.sh new file mode 100755 index 0000000..9236cc0 --- /dev/null +++ b/IbaTools/saquery/opagetvf_env.sh @@ -0,0 +1,163 @@ +#!/bin/bash +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] + +# This script selects a VF based on the parameters given +# It will return exactly 1 VF, represented in a CSV format +# name:index:pkey:sl:mtu:rate +# if there is no matching VF, a non-zero exit code is returned +# this script is intended for use in mpirun and wrapper scripts to +# select a VF and aid in exported env variables + +# convert opagetvf output to environment variables +# MTU and RATE represented as absolute values +opagetvf_env_func() +{ + # $1 = vf cvs string from opagetvf + # $2 = PKEY env variable to set + # $3 = SL env variable to set + # $4 = MTU env variable to set + # $5 = RATE env variable to set + local pkey sl mtu rate + [ -z "$1" ] && return 1 + + pkey=$(echo "$1"|cut -d : -f 3) + sl=$(echo "$1"|cut -d : -f 4) + mtu=$(echo "$1"|cut -d : -f 5) + rate=$(echo "$1"|cut -d : -f 6) + + [ ! -z "$2" ] && eval export $2=$pkey + [ ! -z "$3" ] && eval export $3=$sl + [ ! -z "$4" -a "$mtu" != "unlimited" ] && eval export $4=$mtu + [ ! -z "$5" -a "$rate" != "unlimited" ] && eval export $5=$rate + return 0 +} + +# query vfinfo and put into env variables +# MTU and RATE represented as absolute values +opagetvf_func() +{ + # $1 = arguments to opagetvf to select VF + # $2 = PKEY env variable to set + # $3 = SL env variable to set + # $4 = MTU env variable to set + # $5 = RATE env variable to set + local vf + + vf=$(eval opagetvf $1) + if [ $? -ne 0 ] + then + return 1 + else + opagetvf_env_func "$vf" $2 $3 $4 $5 + fi + return 0 +} + +# convert opagetvf output to environment variables +# MTU and RATE represented as enum values +opagetvf2_env_func() +{ + # $1 = vf cvs string from opagetvf + # $2 = PKEY env variable to set + # $3 = SL env variable to set + # $4 = MTU env variable to set + # $5 = RATE env variable to set + local pkey sl mtu rate + [ -z "$1" ] && return 1 + + pkey=$(echo "$1"|cut -d : -f 3) + sl=$(echo "$1"|cut -d : -f 4) + mtu=$(echo "$1"|cut -d : -f 5) + rate=$(echo "$1"|cut -d : -f 6) + + [ ! -z "$2" ] && eval export $2=$pkey + [ ! -z "$3" ] && eval export $3=$sl + [ ! -z "$4" -a "$mtu" != "0" ] && eval export $4=$mtu + [ ! -z "$5" -a "$rate" != "0" ] && eval export $5=$rate + return 0 +} + +# query vfinfo and put into env variables +# MTU and RATE represented as enum values +opagetvf2_func() +{ + # $1 = arguments to opagetvf to select VF + # $2 = PKEY env variable to set + # $3 = SL env variable to set + # $4 = MTU env variable to set + # $5 = RATE env variable to set + local vf + + vf=$(eval opagetvf -e $1) + if [ $? -ne 0 ] + then + return 1 + else + opagetvf2_env_func "$vf" $2 $3 $4 $5 + fi + return 0 +} + +iba_getpsm_func() +{ + # $1 = arguments to to select PSM multi-rails + + rc=0 + # extract parameter values + echo "$1"|tr \, \\n > .mrail_map_file.$$ + + # validate parameter values + while read line + do + unit=${line%:*} + port=${line#*:} + + # verify unit number + if ! [[ $unit =~ ^[0-9]+$ ]] + then + rc=1 + echo "iba_getpsm_func: Invalid unit number" + fi + # verify port number + if ! [[ $port =~ ^[0-9]+$ ]]; + then + rc=1 + echo "iba_getpsm_func: Invalid port number" + fi + done <.mrail_map_file.$$ + + # remove temp file + rm .mrail_map_file.$$ + + return $rc +} + diff --git a/IbaTools/saquery/opamgt_tls.xml b/IbaTools/saquery/opamgt_tls.xml new file mode 100644 index 0000000..117b0a6 --- /dev/null +++ b/IbaTools/saquery/opamgt_tls.xml @@ -0,0 +1,11 @@ + +0 +/usr/local/ssl/opafm +ff_cert.pem +ff_key.pem +ff_ca_cert.pem +1 +ff_dh_parms.pem +0 +ff_ca_crl.pem + diff --git a/IbaTools/saquery/opashowmc.sh b/IbaTools/saquery/opashowmc.sh new file mode 100755 index 0000000..2d6c601 --- /dev/null +++ b/IbaTools/saquery/opashowmc.sh @@ -0,0 +1,178 @@ +#!/bin/bash +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] + +# This script provides a summary of multicast membership +# it uses saquery to gather the information from the SM + +# optional override of defaults +if [ -f /etc/opa/opafastfabric.conf ] +then + . /etc/opa/opafastfabric.conf +fi + +. /usr/lib/opa/tools/opafastfabric.conf.def + +. /usr/lib/opa/tools/ff_funcs + +trap "exit 1" SIGHUP SIGTERM SIGINT + +show_mc() +{ + # $1 = hfi + # $2 = port + # $3 = showname (y or n) + if [ "$port" -eq 0 ] + then + port_opts="-h $hfi" # default port to 1st active + else + port_opts="-h $hfi -p $port" + fi + groups=$MGID + if [ "$groups" == "" ]; then + echo "Fabric $hfi:$port Multicast Information:" + groups=`/usr/sbin/opasaquery $port_opts -o mcmember 2>/dev/null | grep GID: | sed -e 's/GID: //'` + else + echo "Fabric $hfi:$port Multicast Information for group(s) : '$groups'" + fi + for mgid in $groups + do + /usr/sbin/opasaquery $port_opts -o mcmember -m $mgid 2> /dev/null |head -4|grep -v 'PortGid:' + if [ "$?" != "0" ] + then + (>&2 echo "opasaquery error MGID '$mgid'; Port '$hfi:$port'") + (>&2 echo " Likely cause is non-existent, invalid, or not visible MGID: $mgid") + continue + fi + if [ "$showname" = "y" ] + then + /usr/sbin/opasaquery $port_opts -o mcmember -m $mgid|grep 'PortGid:'|while read heading portgid rest + do + echo "$heading $portgid $rest" + portguid=$(echo $portgid|cut -f 2 -d :) + if [ $(($portguid)) -ne 0 ] + then + echo -n " Name: " + /usr/sbin/opasaquery $port_opts -o desc -g $(echo $portgid|cut -f 2 -d :) + fi + done + else + /usr/sbin/opasaquery $port_opts -o mcmember -m $mgid|grep 'PortGid:' + fi + echo + done +} + +Usage_full() +{ + echo "Usage: opashowmc [-v] [-t portsfile] [-p ports]" >&2 + echo " or" >&2 + echo " opashowmc --help" >&2 + echo " --help - produce full help text" >&2 + echo " -v - verbose output, show name for each member" >&2 + echo " -m mgid - show membership of group only" >&2 + echo " -t portsfile - file with list of local HFI ports used to access" >&2 + echo " fabric(s) for analysis, default is $CONFIG_DIR/opa/ports" >&2 + echo " -p ports - list of local HFI ports used to access fabric(s) for analysis" >&2 + echo " default is 1st active port" >&2 + echo " This is specified as hfi:port" >&2 + echo " 0:0 = 1st active port in system" >&2 + echo " 0:y = port y within system" >&2 + echo " x:0 = 1st active port on HFI x" >&2 + echo " x:y = HFI x, port y" >&2 + echo " The first HFI in the system is 1. The first port on an HFI is 1." >&2 + echo " Environment:" >&2 + echo " PORTS - list of ports, used in absence of -t and -p" >&2 + echo " PORTS_FILE - file containing list of ports, used in absence of -t and -p" >&2 + echo "for example:" >&2 + echo " opashowmc" >&2 + echo " opashowmc -p '1:1 1:2 2:1 2:2'" >&2 + echo " opashowmc -m 0xff12401b80010000:0x00000000ffffffff" >&2 + exit 0 +} + +Usage() +{ + echo "Usage: opashowmc [-v]" >&2 + echo " or" >&2 + echo " opashowmc --help" >&2 + echo " -v - verbose output, show name for each member" >&2 + echo " --help - produce full help text" >&2 + echo "for example:" >&2 + echo " opashowmc" >&2 + exit 2 +} + +if [ x"$1" = "x--help" ] +then + Usage_full +fi + +status=ok +showname=n +while getopts p:t:vm: param +do + case $param in + p) export PORTS="$OPTARG";; + t) export PORTS_FILE="$OPTARG";; + v) showname=y;; + m) export MGID="$OPTARG";; + ?) Usage;; + esac +done +shift $((OPTIND -1)) +if [ $# -ge 1 ] +then + Usage +fi + +check_ports_args opashowmc + +for hfi_port in $PORTS +do + hfi=$(expr $hfi_port : '\([0-9]*\):[0-9]*') + port=$(expr $hfi_port : '[0-9]*:\([0-9]*\)') + if [ "$hfi" = "" -o "$port" = "" ] + then + echo "opashowmc: Error: Invalid port specification: $hfi_port" >&2 + status=bad + continue + fi + + show_mc "$hfi" "$port" "$showname" +done + +if [ "$status" != "ok" ] +then + exit 1 +else + exit 0 +fi diff --git a/IbaTools/saquery/saquery.c b/IbaTools/saquery/saquery.c new file mode 100644 index 0000000..bf9a084 --- /dev/null +++ b/IbaTools/saquery/saquery.c @@ -0,0 +1,957 @@ +/* BEGIN_ICS_COPYRIGHT7 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT7 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + + + +#include +#include +#include +#include +#define _GNU_SOURCE +#include + +#include +#include +#include +#include +#include +#include "ixml.h" + +#define MAX_NUM_INPUT_ARGS 20 + +uint8 g_IB = 0; // perform query in legacy InfiniBand format +uint8 g_verbose = 0; +int g_exitstatus = 0; +int g_CSV = 0; // output should use CSV style + // only valid for OutputTypeVfInfoRecord + // 1=absolute value for mtu and rate + // 2=enum value for mtu and rate +char *g_oob_address = "127.0.0.1"; +uint16 g_oob_port = 3245; +char *g_sslParmsFile = "/etc/opa/opamgt_tls.xml"; +struct omgt_ssl_params g_ssl_params = {0}; +IB_GID g_src_gid = {{0}}; +boolean g_isOOB = FALSE; +boolean g_isFEESM = FALSE; +boolean g_isOOBSSL = FALSE; + +#ifdef DBGPRINT +#undef DBGPRINT +#endif +#define DBGPRINT(format, args...) \ + do { if (g_verbose) { fflush(stdout); fprintf(stderr, format, ##args); } } while (0) + +static struct omgt_port *sa_omgt_session; +PrintDest_t g_dest; +PrintDest_t g_dbgDest; + +// perform the given query and display the results +// if portGuid is -1, 1st active port is used to issue query +//void do_query(EUI64 portGuid, QUERY *pQuery) +void do_query(struct omgt_port *port, OMGT_QUERY *pQuery, QUERY_INPUT_VALUE *old_input_value) +{ + FSTATUS status; + PQUERY_RESULT_VALUES pQueryResults = NULL; + DBGPRINT("Query: Input=%s (0x%x), Output=%s (0x%x)\n", + iba_sd_query_input_type_msg(pQuery->InputType), pQuery->InputType, + iba_sd_query_result_type_msg(pQuery->OutputType), pQuery->OutputType); + + if (!g_isOOB) { + (void)omgt_port_get_port_guid(port, &g_src_gid.Type.Global.InterfaceID); + (void)omgt_port_get_port_prefix(port, &g_src_gid.Type.Global.SubnetPrefix); + } + status = omgt_input_value_conversion(pQuery, old_input_value, g_src_gid); + if (status) { + fprintf(stderr, "%s: Error: InputValue conversion failed: Status %u\n" + "Query: Input=%s (0x%x), Output=%s (0x%x)\n" + "SourceGid: 0x%.16"PRIx64":%.16"PRIx64"\n", __func__, status, + iba_sd_query_input_type_msg(pQuery->InputType), pQuery->InputType, + iba_sd_query_result_type_msg(pQuery->OutputType), pQuery->OutputType, + g_src_gid.AsReg64s.H, g_src_gid.AsReg64s.L); + if (status == FERROR) { + fprintf(stderr, "Source Gid (-x) must be supplied for Input/Output combination.\n"); + } + g_exitstatus = 1; + return; + } + // this call is synchronous + status = omgt_query_sa(port, pQuery, &pQueryResults); + + g_exitstatus = PrintQueryResult(&g_dest, 0, &g_dbgDest, pQuery->OutputType, + g_CSV, status, pQueryResults); + + // iba_sd_query_port_fabric_info will have allocated a result buffer + // we must free the buffer when we are done with it + if (pQueryResults) + omgt_free_query_result_buffer(pQueryResults); +} + +// command line options, each has a short and long flag name +struct option options[] = { + // basic controls + { "verbose", no_argument, NULL, 'v' }, + { "IB", no_argument, NULL, 'I' }, + { "hfi", required_argument, NULL, 'h' }, + { "oob", required_argument, NULL, 'b' }, + { "port", required_argument, NULL, 'p' }, + { "source-gid", required_argument, NULL, 'x' }, + { "feEsm", no_argument, NULL, 'E' }, + { "ssl-params", required_argument, NULL, 'T' }, + + // input data + { "lid", required_argument, NULL, 'l' }, + { "pkey", required_argument, NULL, 'k' }, + { "vfindex", required_argument, NULL, 'i' }, + { "serviceId", required_argument, NULL, 'S' }, + { "SL", required_argument, NULL, 'L' }, + { "type", required_argument, NULL, 't' }, + { "sysguid", required_argument, NULL, 's' }, + { "nodeguid", required_argument, NULL, 'n' }, + { "portguid", required_argument, NULL, 'g' }, + { "portgid", required_argument, NULL, 'u' }, + { "mcgid", required_argument, NULL, 'm' }, + { "desc", required_argument, NULL, 'd' }, + { "guidpair", required_argument, NULL, 'P' }, + { "gidpair", required_argument, NULL, 'G' }, + { "dgname", required_argument, NULL, 'D' }, + // output type + { "output", required_argument, NULL, 'o' }, + { "timeout", required_argument, NULL, '!'}, + { "help", no_argument, NULL, '$' }, // use an invalid option character + { 0 } +}; + +void Usage_full(void) +{ + fprintf(stderr, "Usage: opasaquery [basic options] [SA options] -o type \n"); + fprintf(stderr, " or\n"); + fprintf(stderr, " opasaquery --help\n"); + fprintf(stderr, " --help - produce full help text\n"); + fprintf(stderr, "\n"); + fprintf(stderr, "Basic Options:\n"); + fprintf(stderr, " -v/--verbose - verbose output. A second invocation will\n" + " activate openib debugging, a 3rd will\n" + " activate libibumad debugging.\n"); + fprintf(stderr, " -I/--IB - issue query in legacy InfiniBand format\n"); + fprintf(stderr, " -h/--hfi hfi - hfi, numbered 1..n, 0= -p port will be a\n"); + fprintf(stderr, " system wide port num (default is 0)\n"); + fprintf(stderr, " -b/--oob address - Out-of-Band address of node running the FE. Can be\n" + " either hostname, IPv4, or IPv6 address.\n" + " (default is \"%s\"\n", g_oob_address); + fprintf(stderr, " -p/--port port - port, \n" + " In-band: numbered 1..n, 0=1st active (default\n" + " is 1st active)\n" + " Out-of-band: Port FE is listening on (default\n" + " is %u)\n", g_oob_port); + fprintf(stderr, " --timeout - timeout(response wait time) in ms, default is 1000ms\n"); + fprintf(stderr, " -x/--source-gid src_gid - Source GID of the local GID [required for most\n"); + fprintf(stderr, " Path and Trace Record Queries when Out-of-Band]\n"); + fprintf(stderr, " -E/--feEsm - ESM FE\n"); + fprintf(stderr, " -T/--ssl-params file - SSL/TLS parameters XML file\n" + " (default is \"%s\")\n", g_sslParmsFile); + fprintf(stderr, "\n"); + fprintf(stderr, "SA Options:\n"); + fprintf(stderr, " -l/--lid lid - query a specific lid\n"); + fprintf(stderr, " -k/--pkey pkey - query a specific pkey\n"); + fprintf(stderr, " -i/--vfindex vfindex - query a specific vfindex\n"); + fprintf(stderr, " -S/--serviceId serviceId - query a specific service id\n"); + fprintf(stderr, " -L/--SL SL - query by service level\n"); + fprintf(stderr, " -t/--type nodetype - query by node type\n"); + fprintf(stderr, " -s/--sysguid guid - query by system image guid\n"); + fprintf(stderr, " -n/--nodeguid guid - query by node guid\n"); + fprintf(stderr, " -g/--portguid guid - query by port guid\n"); + fprintf(stderr, " -u/--portgid gid - query by port gid\n"); + fprintf(stderr, " -m/--mcgid gid - query by multicast gid\n"); + fprintf(stderr, " -d/--desc name - query by node name/description\n"); + fprintf(stderr, " -D/--dgname name - query by device group name/description\n"); + fprintf(stderr, " -P/--guidpair 'guid guid' - query by a pair of port Guids\n"); + fprintf(stderr, " -G/--gidpair 'gid gid' - query by a pair of Gids\n"); + fprintf(stderr, "\n"); + fprintf(stderr, "The -h and -p options permit a variety of selections:\n"); + fprintf(stderr, " -h 0 - 1st active port in system (this is the default)\n"); + fprintf(stderr, " -h 0 -p 0 - 1st active port in system\n"); + fprintf(stderr, " -h x - 1st active port on HFI x\n"); + fprintf(stderr, " -h x -p 0 - 1st active port on HFI x\n"); + fprintf(stderr, " -h 0 -p y - port y within system (irrespective of which ports are active)\n"); + fprintf(stderr, " -h x -p y - HFI x, port y\n"); + fprintf(stderr, "\n"); + fprintf(stderr, "nodetype:\n"); + fprintf(stderr, " fi - fabric interface\n"); + fprintf(stderr, " sw - switch\n"); + fprintf(stderr, "\n"); + fprintf(stderr, "gids:\n"); + fprintf(stderr, " specify 64 bit subnet and 64 bit interface id as:\n"); + fprintf(stderr, " subnet:interface\n"); + fprintf(stderr, " such as: 0xfe80000000000000:0x00117501a0000380\n"); + fprintf(stderr, "\n"); + fprintf(stderr, "type: (default is node)\n"); + fprintf(stderr, " classportinfo - classportinfo of the SA\n"); + fprintf(stderr, " systemguid - list of system image guids\n"); + fprintf(stderr, " nodeguid - list of node guids\n"); + fprintf(stderr, " portguid - list of port guids\n"); + fprintf(stderr, " lid - list of lids\n"); + //fprintf(stderr, " gid - list of gids\n"); + fprintf(stderr, " desc - list of node descriptions/names\n"); + fprintf(stderr, " path - list of path records\n"); + fprintf(stderr, " node - list of node records\n"); + fprintf(stderr, " portinfo - list of port info records\n"); + fprintf(stderr, " sminfo - list of SM info records\n"); + fprintf(stderr, " swinfo - list of switch info records\n"); + fprintf(stderr, " link - list of link records\n"); + fprintf(stderr, " scsc - list of SC to SC mapping table records\n"); + fprintf(stderr, " slsc - list of SL to SC mapping table records\n"); + fprintf(stderr, " scsl - list of SC to SL mapping table records\n"); + fprintf(stderr, " scvlt - list of SC to VLt table records\n"); + fprintf(stderr, " scvlr - list of SC to VLr table records\n"); + fprintf(stderr, " scvlnt - list of SC to VLnt table records\n"); + fprintf(stderr, " vlarb - list of VL arbitration table records\n"); + fprintf(stderr, " pkey - list of P-Key table records\n"); + fprintf(stderr, " service - list of service records\n"); + fprintf(stderr, " mcmember - list of multicast member records\n"); + fprintf(stderr, " inform - list of inform info records\n"); + fprintf(stderr, " linfdb - list of switch linear FDB records\n"); + fprintf(stderr, " mcfdb - list of switch multicast FDB records\n"); + fprintf(stderr, " trace - list of trace records\n"); + fprintf(stderr, " vfinfo - list of vFabrics\n"); + fprintf(stderr, " vfinfocsv - list of vFabrics in CSV format\n"); + fprintf(stderr, " vfinfocsv2 - list of vFabrics in CSV format with enums\n"); + fprintf(stderr, " fabricinfo - summary of fabric devices\n"); + fprintf(stderr, " quarantine - list of quarantined nodes\n"); + fprintf(stderr, " conginfo - list of Congestion Info Records\n"); + fprintf(stderr, " swcongset - list of Switch Congestion Settings\n"); + fprintf(stderr, " swportcong - list of Switch Port Congestion Settings\n"); + fprintf(stderr, " hficongset - list of HFI Congestion Settings\n"); + fprintf(stderr, " hficongcon - list of HFI Congesting Control Settings\n"); + fprintf(stderr, " bfrctrl - list of buffer control tables\n"); + fprintf(stderr, " cableinfo - list of Cable Info records\n"); + fprintf(stderr, " portgroup - list of AR Port Group records\n"); + fprintf(stderr, " portgroupfdb - list of AR Port Group FWD records\n"); + fprintf(stderr, " dglist - list of Device Group Names\n"); + fprintf(stderr, " dgmember - list of Device Group records\n"); + fprintf(stderr, " dtree - list of Device Tree records\n"); + fprintf(stderr ," swcost - list of switch cost records\n"); + fprintf(stderr, "\n"); + fprintf(stderr, "Usage examples:\n"); + fprintf(stderr, " opasaquery -o desc -t fi\n"); + exit(0); + +} + +void Usage(void) +{ + fprintf(stderr, "Usage: opasaquery [-v] [-o type] [-l lid] [-t type] [-s guid] [-n guid]\n"); + fprintf(stderr, " [-k pkey] [-g guid] [-u gid] [-m gid] [-d name]\n"); + fprintf(stderr, " or\n"); + fprintf(stderr, " opasaquery --help\n"); + fprintf(stderr, " --help - produce full help text\n"); + fprintf(stderr, " -v/--verbose - verbose output\n"); + fprintf(stderr, " -l/--lid lid - query a specific lid\n"); + fprintf(stderr, " -k/--pkey pkey - query a specific pkey\n"); + fprintf(stderr, " -t/--type nodetype - query by node type\n"); + fprintf(stderr, " -s/--sysguid guid - query by system image guid\n"); + fprintf(stderr, " -n/--nodeguid guid - query by node guid\n"); + fprintf(stderr, " -g/--portguid guid - query by port guid\n"); + fprintf(stderr, " -m/--mcgid gid - query by multicast gid\n"); + fprintf(stderr, " -d/--desc name - query by node name/description\n"); + fprintf(stderr, " -o/--output type - output type for query (default is node)\n"); + fprintf(stderr, "\n"); + fprintf(stderr, "Node Type:\n"); + fprintf(stderr, " fi - fabric interface\n"); + fprintf(stderr, " sw - switch\n"); + fprintf(stderr, "\n"); + fprintf(stderr, "gids:\n"); + fprintf(stderr, " specify 64 bit subnet and 64 bit interface id as:\n"); + fprintf(stderr, " subnet:interface\n"); + fprintf(stderr, " such as: 0xfe80000000000000:0x00117501a0000380\n"); + fprintf(stderr, "\n"); + fprintf(stderr, "Output types (abridged):\n"); + fprintf(stderr, " systemguid - list of system image guids\n"); + fprintf(stderr, " nodeguid - list of node guids\n"); + fprintf(stderr, " portguid - list of port guids\n"); + fprintf(stderr, " lid - list of lids\n"); + //fprintf(stderr, " gid - list of gids\n"); + fprintf(stderr, " desc - list of node descriptions/names\n"); + fprintf(stderr, " node - list of node records\n"); + fprintf(stderr, " portinfo - list of port info records\n"); + fprintf(stderr, " sminfo - list of SM info records\n"); + fprintf(stderr, " swinfo - list of switch info records\n"); + fprintf(stderr, " service - list of service records\n"); + fprintf(stderr, " mcmember - list of multicast member records\n"); + fprintf(stderr, " vfinfo - list of vFabrics\n"); + fprintf(stderr, " vfinfocsv - list of vFabrics in CSV format\n"); + fprintf(stderr, " vfinfocsv2 - list of vFabrics in CSV format\n"); + fprintf(stderr, " bfrctrl - list of buffer control tables\n"); + fprintf(stderr, "\n"); + fprintf(stderr, "Usage examples:\n"); + fprintf(stderr, " opasaquery -o desc -t fi\n"); + fprintf(stderr, " opasaquery -o portinfo -l 2\n"); + fprintf(stderr, " opasaquery -o sminfo\n"); + exit(2); +} +/* SSL Paramters XML parse code */ +static void *sslParmsXmlParserStart(IXmlParserState_t *state, void *parent, const char **attr) +{ + struct omgt_ssl_params *sslParmsData = IXmlParserGetContext(state); + memset(sslParmsData, 0, sizeof(struct omgt_ssl_params)); + return sslParmsData; +} +static void sslParmsXmlParserEnd(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ +} +static IXML_FIELD sslSecurityFields[] = { + { tag:"SslSecurityEnabled", format:'u', IXML_FIELD_INFO(struct omgt_ssl_params, enable) }, + { tag:"SslSecurityEnable", format:'u', IXML_FIELD_INFO(struct omgt_ssl_params, enable) }, + { tag:"SslSecurityDir", format:'s', IXML_FIELD_INFO(struct omgt_ssl_params, directory) }, + { tag:"SslSecurityFFCertificate", format:'s', IXML_FIELD_INFO(struct omgt_ssl_params, certificate) }, + { tag:"SslSecurityFFPrivateKey", format:'s', IXML_FIELD_INFO(struct omgt_ssl_params, private_key) }, + { tag:"SslSecurityFFCaCertificate", format:'s', IXML_FIELD_INFO(struct omgt_ssl_params, ca_certificate) }, + { tag:"SslSecurityFFCertChainDepth", format:'u', IXML_FIELD_INFO(struct omgt_ssl_params, cert_chain_depth) }, + { tag:"SslSecurityFFDHParameters", format:'s', IXML_FIELD_INFO(struct omgt_ssl_params, dh_params) }, + { tag:"SslSecurityFFCaCRLEnabled", format:'u', IXML_FIELD_INFO(struct omgt_ssl_params, ca_crl_enable) }, + { tag:"SslSecurityFFCaCRL", format:'s', IXML_FIELD_INFO(struct omgt_ssl_params, ca_crl) }, + { NULL } +}; +static IXML_FIELD sslTopLevelFields[] = { + { tag:"SslSecurityParameters", format:'K', subfields:sslSecurityFields, start_func:sslParmsXmlParserStart, end_func:sslParmsXmlParserEnd }, // structure + { NULL } +}; +FSTATUS ParseSslParmsFile(const char *input_file, int g_verbose, struct omgt_ssl_params *sslParmsData) +{ + unsigned tags_found, fields_found; + const char *filename=input_file; + + if (strcmp(input_file, "-") == 0) { + filename="stdin"; + if (FSUCCESS != IXmlParseFile(stdin, "stdin", IXML_PARSER_FLAG_NONE, sslTopLevelFields, NULL, sslParmsData, NULL, NULL, &tags_found, &fields_found)) { + return FERROR; + } + } else { + if (FSUCCESS != IXmlParseInputFile(input_file, IXML_PARSER_FLAG_NONE, sslTopLevelFields, NULL, sslParmsData, NULL, NULL, &tags_found, &fields_found)) { + return FERROR; + } + } + if (tags_found != 1 || fields_found != 1) { + fprintf(stderr, "Warning: potentially inaccurate input '%s': found %u recognized top level tags, expected 1\n", filename, tags_found); + } + + return FSUCCESS; +} +/* END SSL Paramters XML parse code */ + +// convert a node type argument to the proper constant +NODE_TYPE checkNodeType(const char* name) +{ + if (0 == strcasecmp(optarg, "fi")) { + return STL_NODE_FI; + } else if (0 == strcasecmp(optarg, "sw")) { + return STL_NODE_SW; + } else { + fprintf(stderr, "opasaquery: Invalid Node Type: %s\n", name); + Usage(); + // NOTREACHED + return STL_NODE_FI; + } +} + +void multiInputCheck(int inputType) { + const char* typestr; + switch (inputType) { + case InputTypeNoInput: + return; + case InputTypePKey: + typestr = "pkey"; + break; + case InputTypeIndex: + typestr = "index"; + break; + case InputTypeServiceId: + typestr = "serviceId"; + break; + case InputTypeLid: + typestr = "lid"; + break; + case InputTypeSL: + typestr = "SL"; + break; + case InputTypeNodeType: + typestr = "NodeType"; + break; + case InputTypeSystemImageGuid: + typestr = "SystemImageGuid"; + break; + case InputTypeNodeGuid: + typestr = "NodeGuid"; + break; + case InputTypePortGuid: + typestr = "PortGuid"; + break; + case InputTypePortGid: + typestr = "PortGid"; + break; + case InputTypeMcGid: + typestr = "McGid"; + break; + case InputTypeNodeDesc: + typestr = "NodeDesc"; + break; + case InputTypePortGuidPair: + typestr = "PortGuidPair"; + break; + case InputTypeGidPair: + typestr = "GidPair"; + break; + case InputTypeDeviceGroup: + typestr = "DeviceGroup"; + break; + default: + typestr = "parameter"; + } + fprintf(stderr, "opasaquery: multiple selection criteria not supported, ignoring %s\n", typestr); +} + + + + +typedef struct InputFlags { + QUERY_INPUT_TYPE flags[MAX_NUM_INPUT_ARGS]; +} InputFlags_t; + +#define END_INPUT_TYPE 0xFFFF +//Note: The last initialized element of every InputFlags_t array must be END_INPUT_TYPE +InputFlags_t NodeInput = {{InputTypeNoInput, InputTypeNodeType,InputTypeLid,InputTypeSystemImageGuid,InputTypeNodeGuid,InputTypePortGuid, + InputTypeNodeDesc, END_INPUT_TYPE}}; +InputFlags_t PathInput = {{InputTypeNoInput, InputTypeLid,InputTypePKey,InputTypePortGuid,InputTypePortGid,InputTypePortGuidPair, + InputTypeGidPair,InputTypeServiceId,InputTypeSL,END_INPUT_TYPE}}; +InputFlags_t ServiceInput = {{InputTypeNoInput,InputTypePortGuid,InputTypePortGid,InputTypeServiceId,END_INPUT_TYPE}}; +InputFlags_t McmemberInput = {{InputTypeNoInput, InputTypeLid, InputTypePKey,InputTypePortGuid,InputTypePortGid,InputTypeMcGid,InputTypeSL,END_INPUT_TYPE}}; +InputFlags_t InformInput = {{InputTypeNoInput,InputTypePortGuid,InputTypePortGid,InputTypeLid,END_INPUT_TYPE}}; +InputFlags_t TraceInput = {{InputTypePortGuid,InputTypePortGid,InputTypePortGuidPair,InputTypeGidPair,InputTypeLid,END_INPUT_TYPE}}; +InputFlags_t VfinfoInput = {{InputTypeNoInput,InputTypePKey,InputTypeIndex,InputTypeMcGid,InputTypeServiceId,InputTypeSL,InputTypeNodeDesc,END_INPUT_TYPE}}; +InputFlags_t MiscInput = {{InputTypeNoInput,InputTypeLid,END_INPUT_TYPE}}; +InputFlags_t DgMemberInput = {{InputTypeNoInput,InputTypeLid, InputTypePortGuid, InputTypeNodeDesc,InputTypeDeviceGroup,END_INPUT_TYPE}}; + +typedef struct OutputStringMap { + char *string; + QUERY_RESULT_TYPE stl_type; + QUERY_RESULT_TYPE ib_type; + InputFlags_t *valid_input_types; + int csv; +} OutputStringMap_t; + +#define NO_OUTPUT_TYPE 0xffff +OutputStringMap_t OutputTypeTable[] = { +//--input string--------StlOutputType-------------------------IbOutputType----------------InputFlags----csv-// + {"systemguid", OutputTypeStlSystemImageGuid, NO_OUTPUT_TYPE, &NodeInput, 0}, + {"classportinfo", OutputTypeStlClassPortInfo, OutputTypeClassPortInfo, NULL, 0}, + {"nodeguid", OutputTypeStlNodeGuid, NO_OUTPUT_TYPE, &NodeInput, 0}, + {"portguid", OutputTypeStlPortGuid, NO_OUTPUT_TYPE, &NodeInput, 0}, + {"lid", OutputTypeStlLid, NO_OUTPUT_TYPE, &NodeInput, 0}, + {"desc", OutputTypeStlNodeDesc, NO_OUTPUT_TYPE, &NodeInput, 0}, + {"path", NO_OUTPUT_TYPE, OutputTypePathRecord, &PathInput, 0}, + {"node", OutputTypeStlNodeRecord, OutputTypeNodeRecord, &NodeInput, 0}, + {"portinfo", OutputTypeStlPortInfoRecord, OutputTypePortInfoRecord, &MiscInput, 0}, + {"sminfo", OutputTypeStlSMInfoRecord, NO_OUTPUT_TYPE, NULL, 0}, + {"link", OutputTypeStlLinkRecord, NO_OUTPUT_TYPE, &MiscInput, 0}, + {"service", NO_OUTPUT_TYPE, OutputTypeServiceRecord, &ServiceInput, 0}, + {"mcmember", NO_OUTPUT_TYPE, OutputTypeMcMemberRecord, &McmemberInput, 0}, + {"inform", OutputTypeStlInformInfoRecord, OutputTypeInformInfoRecord, &InformInput, 0}, + {"trace", OutputTypeStlTraceRecord, NO_OUTPUT_TYPE, &TraceInput, 0}, + {"scsc", OutputTypeStlSCSCTableRecord, NO_OUTPUT_TYPE, &MiscInput, 0}, + {"slsc", OutputTypeStlSLSCTableRecord, NO_OUTPUT_TYPE, &MiscInput, 0}, + {"scsl", OutputTypeStlSCSLTableRecord, NO_OUTPUT_TYPE, &MiscInput, 0}, + {"scvlt", OutputTypeStlSCVLtTableRecord, NO_OUTPUT_TYPE, &MiscInput, 0}, + {"scvlnt", OutputTypeStlSCVLntTableRecord, NO_OUTPUT_TYPE, &MiscInput, 0}, + {"scvlr", OutputTypeStlSCVLrTableRecord, NO_OUTPUT_TYPE, &MiscInput, 0}, + {"swinfo", OutputTypeStlSwitchInfoRecord, NO_OUTPUT_TYPE, &MiscInput, 0}, + {"linfdb", OutputTypeStlLinearFDBRecord, NO_OUTPUT_TYPE, &MiscInput, 0}, + {"mcfdb", OutputTypeStlMCastFDBRecord, NO_OUTPUT_TYPE, &MiscInput, 0}, + {"vlarb", OutputTypeStlVLArbTableRecord, NO_OUTPUT_TYPE, &MiscInput, 0}, + {"pkey", OutputTypeStlPKeyTableRecord, NO_OUTPUT_TYPE, &MiscInput, 0}, + {"vfinfo", OutputTypeStlVfInfoRecord, NO_OUTPUT_TYPE, &VfinfoInput, 0}, + {"vfinfocsv", OutputTypeStlVfInfoRecord, NO_OUTPUT_TYPE, &VfinfoInput, 1}, + {"vfinfocsv2", OutputTypeStlVfInfoRecord, NO_OUTPUT_TYPE, &VfinfoInput, 2}, + {"fabricinfo", OutputTypeStlFabricInfoRecord, NO_OUTPUT_TYPE, NULL, 0}, + {"quarantine", OutputTypeStlQuarantinedNodeRecord, NO_OUTPUT_TYPE, NULL, 0}, + {"conginfo", OutputTypeStlCongInfoRecord, NO_OUTPUT_TYPE, &MiscInput, 0}, + {"swcongset", OutputTypeStlSwitchCongRecord, NO_OUTPUT_TYPE, &MiscInput, 0}, + {"swportcong", OutputTypeStlSwitchPortCongRecord, NO_OUTPUT_TYPE, &MiscInput, 0}, + {"hficongset", OutputTypeStlHFICongRecord, NO_OUTPUT_TYPE, &MiscInput, 0}, + {"hficongcon", OutputTypeStlHFICongCtrlRecord, NO_OUTPUT_TYPE, &MiscInput, 0}, + {"bfrctrl", OutputTypeStlBufCtrlTabRecord, NO_OUTPUT_TYPE, &MiscInput, 0}, + {"cableinfo", OutputTypeStlCableInfoRecord, NO_OUTPUT_TYPE, &MiscInput, 0}, + {"portgroup", OutputTypeStlPortGroupRecord, NO_OUTPUT_TYPE, &MiscInput, 0}, + {"portgroupfdb", OutputTypeStlPortGroupFwdRecord, NO_OUTPUT_TYPE, &MiscInput, 0}, + {"dgmember", OutputTypeStlDeviceGroupMemberRecord, NO_OUTPUT_TYPE, &DgMemberInput, 0}, + {"dglist", OutputTypeStlDeviceGroupNameRecord, NO_OUTPUT_TYPE, NULL, 0}, + {"dtree", OutputTypeStlDeviceTreeMemberRecord, NO_OUTPUT_TYPE, &MiscInput, 0}, + {"swcost", OutputTypeStlSwitchCostRecord, NO_OUTPUT_TYPE, &MiscInput, 0}, + //Last entry must be null, insert new attributes above here! + {NULL, NO_OUTPUT_TYPE, NO_OUTPUT_TYPE, NULL, 0} +}; + +// convert a output type argument to the proper constant +QUERY_RESULT_TYPE GetOutputType(OutputStringMap_t *in) +{ + QUERY_RESULT_TYPE res = NO_OUTPUT_TYPE; + + //by default use STL type unless there is no STL + //specific type, or the user specified '-I" option + res = in->stl_type; + g_CSV = in->csv; + if (g_IB || res == NO_OUTPUT_TYPE) + res = in->ib_type; + + if(res == NO_OUTPUT_TYPE) { + if (g_IB) + fprintf(stderr, "opasaquery: Invalid IB Output Type: %s\n", in->string); + else + fprintf(stderr, "opasaquery: Invalid Output Type: %s\n", in->string); + Usage(); + // NOTREACHED + return OutputTypeStlNodeRecord; + } + return res; +} + +OutputStringMap_t *GetOutputTypeMap(const char* name) { + + int i =0; + while(OutputTypeTable[i].string != NULL) { + if (0 == strcmp(name, OutputTypeTable[i].string)) { + return &OutputTypeTable[i]; + } + i++; + } + + fprintf(stderr, "opasaquery: Invalid Output Type: %s\n", name); + Usage(); + // NOTREACHED + return NULL; +} + +typedef struct InputStringMap { + char *string; + QUERY_INPUT_TYPE in_type; +} InputStringMap_t; + +InputStringMap_t InputStrTable[] = { + { "No Input", InputTypeNoInput }, + { "pkey", InputTypePKey }, + { "index", InputTypeIndex}, + { "serviceId", InputTypeServiceId }, + { "lid", InputTypeLid }, + { "SL", InputTypeSL }, + { "NodeType", InputTypeNodeType }, + { "SystemImageGuid", InputTypeSystemImageGuid }, + { "NodeGuid", InputTypeNodeGuid }, + { "PortGuid", InputTypePortGuid }, + { "PortGid", InputTypePortGid }, + { "McGid", InputTypeMcGid }, + { "NodeDesc", InputTypeNodeDesc }, + { "PortGuidPair", InputTypePortGuidPair }, + { "GidPair", InputTypeGidPair }, + { "DeviceGroup", InputTypeDeviceGroup}, + //Last entry must be null, insert new inputs above here! + {NULL, 0} +}; + +static void PrintValidInputTypes(OutputStringMap_t *in) { + + int i = 0; + int j = 0; + + fprintf(stderr, "opasaquery: for the selected output option (%s), the following \n",in->string); + fprintf(stderr, "input types are valid: "); + + while (in->valid_input_types->flags[i] != END_INPUT_TYPE){ + // look for the string corresponding to the flag + j=0; + while (InputStrTable[j].string !=NULL){ + if (in->valid_input_types->flags[i] == InputStrTable[j].in_type) { + fprintf(stderr,"%s ",InputStrTable[j].string); + break; + } + j++; + + } + i++; + } + + fprintf(stderr, "\n"); + return; +} + +static FSTATUS CheckInputOutput(OMGT_QUERY *pQuery, OutputStringMap_t *in) { + + int i=0; + + if(in->valid_input_types == NULL) { + if (pQuery->InputType != InputTypeNoInput) { + fprintf(stderr, "opasaquery: This option (%s) does not accept input. ",in->string); + fprintf(stderr, "Ignoring input argument\n"); + pQuery->InputType = InputTypeNoInput; + return FSUCCESS; + } + else { + return FSUCCESS; + } + } + + while (in->valid_input_types->flags[i] != END_INPUT_TYPE){ + if (pQuery->InputType == in->valid_input_types->flags[i]){ + return FSUCCESS; + } + i++; + } + + // Invalid Input Type detected + fprintf(stderr, "opasaquery: Invalid input-output pair\n"); + PrintValidInputTypes(in); + return FERROR; +} + + +int main(int argc, char ** argv) +{ + int c; + uint8 hfi = 0; + uint16 port = 0; + int index; + OMGT_QUERY query; + QUERY_INPUT_VALUE old_input_values; + OutputStringMap_t *outputTypeMap = NULL; + int ms_timeout = OMGT_DEF_TIMEOUT_MS; + + memset(&query, 0, sizeof(query)); // initialize reserved fields + + // default query for this application is for all node records + query.InputType = InputTypeNoInput; + query.OutputType = OutputTypeStlNodeRecord; + + // process command line arguments + while (-1 != (c = getopt_long(argc,argv, "vIh:p:b:x:ET:l:k:i:t:s:n:g:u:m:d:P:G:o:S:L:D:H:", options, &index))) + { + switch (c) + { + case '$': + Usage_full(); + break; + case 'v': + g_verbose++; + if (g_verbose > 2) umad_debug(g_verbose - 2); + break; + case 'I': // issue query in legacy InfiniBand format (IB) + g_IB = 1; + query.OutputType = OutputTypeNodeRecord; + break; + case 'h': // hfi to issue query from + if (FSUCCESS != StringToUint8(&hfi, optarg, NULL, 0, TRUE)) { + fprintf(stderr, "opasaquery: Invalid HFI Number: %s\n", optarg); + Usage(); + } + g_isOOB = FALSE; + break; + case 'p': // port to issue query from + if (FSUCCESS != StringToUint16(&port, optarg, NULL, 0, TRUE)) { + fprintf(stderr, "opasaquery: Invalid Port Number: %s\n", optarg); + Usage(); + } + break; + case '!': + if (FSUCCESS != StringToInt32(&ms_timeout, optarg, NULL, 0, TRUE)) { + fprintf(stderr, "opasaquery: Invalid timeout value: %s\n", optarg); + Usage(); + } + break; + case 'b': // OOB address of FE + g_oob_address = optarg; + g_isOOB = TRUE; + break; + case 'E': // FE is ESM + g_isFEESM = TRUE; + g_isOOB = TRUE; + break; + case 'T': // FE Uses SSL + g_sslParmsFile = optarg; + g_isOOBSSL = TRUE; + g_isOOB = TRUE; + break; + case 'x': // Source GID + if (FSUCCESS != StringToGid(&g_src_gid.AsReg64s.H, &g_src_gid.AsReg64s.L, optarg, NULL, TRUE)) { + fprintf(stderr, "opasaquery: Invalid Source Gid: %s\n", optarg); + Usage(); + } + break; + + case 'l': // query by lid + multiInputCheck(query.InputType); + query.InputType = InputTypeLid; + if (FSUCCESS != StringToUint32(&old_input_values.Lid, optarg, NULL, 0, TRUE)) { + fprintf(stderr, "opasaquery: Invalid LID: %s\n", optarg); + Usage(); + } + break; + case 'k': // query by pkey + multiInputCheck(query.InputType); + query.InputType = InputTypePKey; + if (FSUCCESS != StringToUint16(&old_input_values.PKey, optarg, NULL, 0, TRUE)) { + fprintf(stderr, "opasaquery: Invalid PKey: %s\n", optarg); + Usage(); + } + break; + case 'i': // query by vfindex + multiInputCheck(query.InputType); + query.InputType = InputTypeIndex; + if (FSUCCESS != StringToUint16(&old_input_values.vfIndex, optarg, NULL, 0, TRUE)) { + fprintf(stderr, "opasaquery: Invalid vfIndex: %s\n", optarg); + Usage(); + } + break; + case 'S': // query by serviceId + multiInputCheck(query.InputType); + query.InputType = InputTypeServiceId; + if (FSUCCESS != StringToUint64(&old_input_values.ServiceId, optarg, NULL, 0, TRUE)) { + fprintf(stderr, "opasaquery: Invalid ServiceId: %s\n", optarg); + Usage(); + } + break; + case 'L': // query by service level + multiInputCheck(query.InputType); + query.InputType = InputTypeSL; + if (FSUCCESS != StringToUint8(&old_input_values.SL, optarg, NULL, 0, TRUE) + || old_input_values.SL > 31) { + fprintf(stderr, "opasaquery: Invalid SL: %s\n", optarg); + Usage(); + } + break; + case 't': // query by node type + multiInputCheck(query.InputType); + query.InputType = InputTypeNodeType; + old_input_values.TypeOfNode = checkNodeType(optarg); + break; + case 's': // query by system image guid + multiInputCheck(query.InputType); + query.InputType = InputTypeSystemImageGuid; + if (FSUCCESS != StringToUint64(&old_input_values.Guid, optarg, NULL, 0, TRUE)) { + fprintf(stderr, "opasaquery: Invalid GUID: %s\n", optarg); + Usage(); + } + break; + case 'n': // query by node guid + multiInputCheck(query.InputType); + query.InputType = InputTypeNodeGuid; + if (FSUCCESS != StringToUint64(&old_input_values.Guid, optarg, NULL, 0, TRUE)) { + fprintf(stderr, "opasaquery: Invalid GUID: %s\n", optarg); + Usage(); + } + break; + case 'g': // query by port guid + multiInputCheck(query.InputType); + query.InputType = InputTypePortGuid; + if (FSUCCESS != StringToUint64(&old_input_values.Guid, optarg, NULL, 0, TRUE)) { + fprintf(stderr, "opasaquery: Invalid GUID: %s\n", optarg); + Usage(); + } + break; + case 'u': // query by gid + multiInputCheck(query.InputType); + query.InputType = InputTypePortGid; + if (FSUCCESS != StringToGid(&old_input_values.Gid.AsReg64s.H,&old_input_values.Gid.AsReg64s.L, optarg, NULL, TRUE)) { + fprintf(stderr, "opasaquery: Invalid GID: %s\n", optarg); + Usage(); + } + break; + case 'm': // query by multicast gid + multiInputCheck(query.InputType); + query.InputType = InputTypeMcGid; + if (FSUCCESS != StringToGid(&old_input_values.Gid.AsReg64s.H,&old_input_values.Gid.AsReg64s.L, optarg, NULL, TRUE)) { + fprintf(stderr, "opasaquery: Invalid GID: %s\n", optarg); + Usage(); + } + break; + case 'd': // query by node description + multiInputCheck(query.InputType); + query.InputType = InputTypeNodeDesc; + old_input_values.NodeDesc.NameLength = MIN(strlen(optarg), NODE_DESCRIPTION_ARRAY_SIZE); + strncpy((char*)old_input_values.NodeDesc.Name, optarg, NODE_DESCRIPTION_ARRAY_SIZE); + break; + case 'D': // query by device group name + multiInputCheck(query.InputType); + query.InputType = InputTypeDeviceGroup; + old_input_values.DeviceGroup.NameLength = MIN(strlen(optarg), MAX_DG_NAME); + memset((char *)old_input_values.DeviceGroup.Name, 0, MAX_DG_NAME); + strncpy((char*)old_input_values.DeviceGroup.Name, optarg, MAX_DG_NAME-1); + break; + case 'P': // query by source:dest port guids + { + char *p; + multiInputCheck(query.InputType); + query.InputType = InputTypePortGuidPair; + if (FSUCCESS != StringToUint64(&old_input_values.PortGuidPair.SourcePortGuid, optarg, &p, 0, TRUE) + || ! p || *p == '\0') { + fprintf(stderr, "opasaquery: Invalid GUID Pair: %s\n", optarg); + Usage(); + } + if (FSUCCESS != StringToUint64(&old_input_values.PortGuidPair.DestPortGuid, p, NULL, 0, TRUE)) { + fprintf(stderr, "opasaquery: Invalid GUID Pair: %s\n", optarg); + Usage(); + } + } + break; + case 'G': // query by source:dest port gids + { + char *p; + multiInputCheck(query.InputType); + query.InputType = InputTypeGidPair; + if (FSUCCESS != StringToGid(&old_input_values.GidPair.SourceGid.AsReg64s.H,&old_input_values.GidPair.SourceGid.AsReg64s.L, optarg, &p, TRUE) + || ! p || *p == '\0') { + fprintf(stderr, "opasaquery: Invalid GID Pair: %s\n", optarg); + Usage(); + } + if (FSUCCESS != StringToGid(&old_input_values.GidPair.DestGid.AsReg64s.H,&old_input_values.GidPair.DestGid.AsReg64s.L, p, NULL, TRUE)) { + fprintf(stderr, "opasaquery: Invalid GID Pair: %s\n", optarg); + Usage(); + } + } + break; + case 'o': // select output record desired + outputTypeMap = GetOutputTypeMap(optarg); + break; + default: + fprintf(stderr, "opasaquery: Invalid option -%c\n", c); + Usage(); + break; + } + } /* end while */ + + if (optind < argc) + { + Usage(); + } + + if (NULL != outputTypeMap){ + if (CheckInputOutput(&query, outputTypeMap )!= 0) + Usage(); + else + query.OutputType = GetOutputType(outputTypeMap); + } + + if (g_IB && query.InputType == InputTypeLid && + old_input_values.Lid > IB_MAX_UCAST_LID && + query.OutputType != OutputTypeMcMemberRecord) { + + fprintf(stderr, "opasaquery: lid value must be less than or equal to 0x%x for IB queries\n",IB_MAX_UCAST_LID); + Usage(); + } + + if (g_IB && query.InputType == InputTypeSL) + if (old_input_values.SL > 15) + { + fprintf(stderr, "opasaquery: SL value must be less than or equal to 15 for IB queries\n"); + Usage(); + } + + if (query.InputType == InputTypeLid && + query.OutputType == OutputTypeMcMemberRecord) { + + if (IS_MCAST32(old_input_values.Lid)) { + // allow 32-bit as long as it only uses the IB MLID subset + IB_LID mlid16 = MCAST32_TO_MCAST16(old_input_values.Lid); + STL_LID mlid32 = MCAST16_TO_MCAST32(mlid16); + if (mlid32 != old_input_values.Lid || + (mlid16 & LID_PERMISSIVE) == LID_PERMISSIVE) { + + fprintf(stderr, "opasaquery: MLID 0x%x is outside acceptable range" + " (0xf0000000 to 0xf003ffe) for using 32-bit MLID format with" + " IB MulticastMemberRecord query\n", old_input_values.Lid); + Usage(); + } + + old_input_values.Lid = MCAST32_TO_MCAST16(old_input_values.Lid); + } else if (!IS_MCAST16(old_input_values.Lid)) { + fprintf(stderr, "opasaquery: must use either 16-bit or 32-bit MLID" + " format for IB MulticastMemberRecord queries\n"); + Usage(); + } + } + + + PrintDestInitFile(&g_dest, stdout); + if (g_verbose) + PrintDestInitFile(&g_dbgDest, stdout); + else + PrintDestInitNone(&g_dbgDest); + + FSTATUS status; + struct omgt_params params = { + .debug_file = (g_verbose > 1 ? stderr : NULL), + .error_file = stderr + }; + if (g_isOOB) { + if (g_sslParmsFile) { + if ((status = ParseSslParmsFile(g_sslParmsFile, g_verbose, &g_ssl_params)) != FSUCCESS) { + fprintf(stderr, "opasaquery: Must provide a valid SSL/TLS parameters XML file: %s\n", g_sslParmsFile); + Usage(); + } + } + struct omgt_oob_input oob_input = { + .host = g_oob_address, + .port = (port ? port : g_oob_port), + .is_esm_fe = g_isFEESM, + .ssl_params = g_ssl_params + }; + status = omgt_oob_connect(&sa_omgt_session, &oob_input, ¶ms); + if (status != 0) { + fprintf(stderr, "opasaquery: Failed to open connection to FE %s:%u: %s\n", + oob_input.host, oob_input.port, omgt_status_totext(status)); + exit(1); + } + } else { + status = omgt_open_port_by_num(&sa_omgt_session, hfi, port, ¶ms); + if (status != 0) { + fprintf(stderr, "opasaquery: Failed to open port hfi %d:%d: %s\n", hfi, port, omgt_status_totext(status)); + exit(1); + } + } + + //set timeout for SA operations + omgt_set_timeout(sa_omgt_session, ms_timeout); + + // perform the query and display output + do_query(sa_omgt_session, &query, &old_input_values); + + omgt_close_port(sa_omgt_session); + + if (g_exitstatus == 2) + Usage(); + + return g_exitstatus; +} diff --git a/IbaTools/setup_self_ssh/Makefile b/IbaTools/setup_self_ssh/Makefile new file mode 100644 index 0000000..32643c1 --- /dev/null +++ b/IbaTools/setup_self_ssh/Makefile @@ -0,0 +1,152 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** +# Makefile for setup_self_ssh + +# Include Make Control Settings +include $(TL_DIR)/$(PROJ_FILE_DIR)/Makesettings.project + +#=============================================================================# +# Definitions: +#-----------------------------------------------------------------------------# + +# Name of SubProjects +DS_SUBPROJECTS = +# name of executable or downloadable image +EXECUTABLE = #$(BUILDDIR)/setup_self_ssh$(EXE_SUFFIX) +# list of sub directories to build +DIRS = +# C files (.c) +CFILES = \ + # Add more c files here +# C++ files (.cpp) +CCFILES = \ + # Add more cpp files here +# lex files (.lex) +LFILES = \ + # Add more lex files here +# archive library files (basename, $ARFILES will add MOD_LIB_DIR/prefix and suffix) +LIBFILES= +# Windows Resource Files (.rc) +RSCFILES = +# Windows IDL File (.idl) +IDLFILE = +# Windows Linker Module Definitions (.def) file for dll's +DEFFILE = +# targets to build during INCLUDES phase (add public includes here) +INCLUDE_TARGETS = \ + # Add more h hpp files here + +# Non-compiled files +MISC_FILES = + +# all source files +SOURCES = $(CFILES) $(CCFILES) $(LFILES) $(RSCFILES) $(IDLFILE) +# Source files to include in DSP File +DSP_SOURCES = $(INCLUDE_TARGETS) $(SOURCES) $(MISC_FILES) \ + $(RSCFILES) $(DEFFILE) $(MAKEFILE) +# all object files +OBJECTS = $(CFILES:.c=$(OBJ_SUFFIX)) $(CCFILES:.cpp=$(OBJ_SUFFIX)) \ + $(LFILES:.lex=$(OBJ_SUFFIX)) +RSCOBJECTS = $(RSCFILES:.rc=$(RES_SUFFIX)) +# targets to build during LIBS phase +LIB_TARGETS_IMPLIB = +LIB_TARGETS_ARLIB = # $(LIB_PREFIX)ResourceTest$(ARLIB_SUFFIX) +LIB_TARGETS_EXP = $(LIB_TARGETS_IMPLIB:$(ARLIB_SUFFIX)=$(EXP_SUFFIX)) +LIB_TARGETS_MISC = +# targets to build during CMDS phase +CMD_TARGETS_SHLIB = +CMD_TARGETS_EXE = $(EXECUTABLE) +CMD_TARGETS_MISC = setup_self_ssh +# files to remove during clean phase +CLEAN_TARGETS_MISC = +CLEAN_TARGETS = $(OBJECTS) $(RSCOBJECTS) $(IDL_TARGETS) $(CLEAN_TARGETS_MISC) +# other files to remove during clobber phase +CLOBBER_TARGETS_MISC= +# sub-directory to install to within bin +BIN_SUBDIR = +# sub-directory to install to within include +INCLUDE_SUBDIR = + +# Additional Settings +#CLOCALDEBUG = User defined C debugging compilation flags [Empty] +#CCLOCALDEBUG = User defined C++ debugging compilation flags [Empty] +#CLOCAL = User defined C flags for compiling [Empty] +#CCLOCAL = User defined C++ flags for compiling [Empty] +#BSCLOCAL = User flags for Browse File Builder [Empty] +#DEPENDLOCAL = user defined makedepend flags [Empty] +#LINTLOCAL = User defined lint flags [Empty] +#LOCAL_INCLUDE_DIRS = User include directories to search for C/C++ headers [Empty] +#LDLOCAL = User defined C flags for linking [Empty] +#IMPLIBLOCAL = User flags for Object Lirary Manager [Empty] +#MIDLLOCAL = User flags for IDL compiler [Empty] +#RSCLOCAL = User flags for resource compiler [Empty] +#LOCALDEPLIBS = User libraries to include in dependencies [Empty] +#LOCALLIBS = User libraries to use when linking [Empty] +# (in addition to LOCALDEPLIBS) +#LOCAL_LIB_DIRS = User library directories for libpaths [Empty] + +CLOCAL = $(CPIE) + +# Include Make Rules definitions and rules +include $(TL_DIR)/IbaTools/Makerules.module + +#=============================================================================# +# Overrides: +#-----------------------------------------------------------------------------# +#CCOPT = # C++ optimization flags, default lets build config decide +#COPT = # C optimization flags, default lets build config decide +#SUBSYSTEM = Subsystem to build for (none, console or windows) [none] +# (Windows Only) +#USEMFC = How Windows MFC should be used (none, static, shared, no_mfc) [none] +# (Windows Only) +#=============================================================================# + +#=============================================================================# +# Rules: +#-----------------------------------------------------------------------------# +# process Sub-directories +include $(TL_DIR)/Makerules/Maketargets.toplevel + +# build cmds and libs +include $(TL_DIR)/Makerules/Maketargets.build + +# install for includes, libs and cmds phases +include $(TL_DIR)/Makerules/Maketargets.install + +# install for stage phase +include $(TL_DIR)/Makerules/Maketargets.stage + +# Unit test execution +#include $(TL_DIR)/Makerules/Maketargets.runtest + +#=============================================================================# + +#=============================================================================# +# DO NOT DELETE THIS LINE -- make depend depends on it. +#=============================================================================# diff --git a/IbaTools/setup_self_ssh/setup_self_ssh.sh b/IbaTools/setup_self_ssh/setup_self_ssh.sh new file mode 100755 index 0000000..ed8e898 --- /dev/null +++ b/IbaTools/setup_self_ssh/setup_self_ssh.sh @@ -0,0 +1,174 @@ +#!/bin/bash +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] +# setup password-less ssh on a single host so it can ssh to itself +# This is part of IntelOPA-Basic for use by opasetupssh in FastFabric + +trap "exit 1" SIGHUP SIGTERM SIGINT + +Usage() +{ + echo "Usage: setup_self_ssh [-U] [-i ipoib_hostname]" >&2 + echo " or" >&2 + echo " setup_self_ssh --help" >&2 + echo " --help - produce full help text" >&2 + echo " -U - only perform connect (to enter in local hosts knownhosts)" >&2 + echo " -i ipoib_hostname - ipoib hostname for this host" >&2 + echo " default is to skip setup for ipoib to self" >&2 + echo "example:">&2 + echo " setup_self_ssh -i myhost-ib" >&2 + echo " setup_self_ssh -U" >&2 + exit 2 +} + +if [ x"$1" = "x--help" ] +then + Usage +fi + +user=`id -u -n` +Uopt=n +ihost_ib= +while getopts Ui: param +do + case $param in + U) + Uopt=y;; + i) + ihost_ib="$OPTARG";; + ?) + Usage;; + esac +done +shift $((OPTIND -1)) +if [ $# -gt 0 ] +then + Usage +fi + +# connect to host via ssh +connect_to_host() +{ + # $1 = user + # $2 = host + + # We use an alternate file to build up the new keys + # this way parallel calls can let ssh itself handle file locking + # then update_known_hosts can replace data in real known_hosts file + ssh -o 'UserKnownHostsFile=~/.ssh/.known_hosts-ffnew' -o 'StrictHostKeyChecking=no' $1@$2 echo "$2: Connected" +} + +# update known_hosts file with information from connect_to_host calls +update_known_hosts() +{ + if [ -e ~/.ssh/.known_hosts-ffnew ] + then + if [ -e ~/.ssh/known_hosts ] + then + ( + IFS=" , " + while read name trash + do + # remove old entry from known hosts in case key changed + if grep "^$name[, ]" < ~/.ssh/known_hosts > /dev/null 2>&1 + then + grep -v "^$name[, ]" < ~/.ssh/known_hosts > ~/.ssh/.known_hosts-fftmp + mv ~/.ssh/.known_hosts-fftmp ~/.ssh/known_hosts + fi + done < ~/.ssh/.known_hosts-ffnew + ) + fi + cat ~/.ssh/.known_hosts-ffnew >> ~/.ssh/known_hosts + chmod go-w ~/.ssh/known_hosts + + rm -rf ~/.ssh/.known_hosts-ffnew ~/.ssh/.known_hosts-fftmp + fi +} + +# Generate public and private SSH key pairs +cd ~ +mkdir -m 0700 -p ~/.ssh ~/.ssh2 +if [ ! -f .ssh/id_rsa.pub -o ! -f .ssh/id_rsa ] +then + ssh-keygen -t rsa -N '' -f ~/.ssh/id_rsa +fi +if [ ! -f .ssh/id_dsa.pub -o ! -f .ssh/id_dsa ] +then + ssh-keygen -t dsa -N '' -f ~/.ssh/id_dsa +fi +# recreate public key in Reflection format for ssh2 +if [ ! -e .ssh2/ssh2_id_dsa.pub ] +then + # older distros may not support this, ignore error + ssh-keygen -O ~/.ssh/id_dsa.pub -o ~/.ssh2/ssh2_id_dsa.pub 2>/dev/null +fi + +# configure ssh on the host(s) +rm -rf ~/.ssh/.known_hosts-ffnew ~/.ssh/.known_hosts-fftmp + +#stty_settings=`stty -g` +ihost=`hostname | cut -f1 -d.` + +# setup ssh to ourselves +if [ $Uopt = n ] +then + echo "$ihost: Configuring localhost ssh..." + rm -f ~/.ssh/.tmp_keys$$ + + >> ~/.ssh/authorized_keys + cat ~/.ssh/authorized_keys ~/.ssh/id_rsa.pub ~/.ssh/id_dsa.pub|sort -u > ~/.ssh/.tmp_keys$$ + mv ~/.ssh/.tmp_keys$$ ~/.ssh/authorized_keys + + >> ~/.ssh/authorized_keys2 + cat ~/.ssh/authorized_keys2 ~/.ssh/id_rsa.pub ~/.ssh/id_dsa.pub|sort -u > ~/.ssh/.tmp_keys$$ + mv ~/.ssh/.tmp_keys$$ ~/.ssh/authorized_keys2 + + # set up ssh2 DSA authorization + # older distros may not support this + [ -f ~/.ssh2/ssh2_id_dsa.pub ] && ! grep '^Key ssh2_id_dsa.pub$' ~/.ssh2/authorization >/dev/null 2>&1 && echo "Key ssh2_id_dsa.pub" >> ~/.ssh2/authorization + + chmod go-w ~/.ssh/authorized_keys ~/.ssh/authorized_keys2 + test -f ~/.ssh2/authorization && chmod go-w ~/.ssh2/authorization +fi + +echo "$ihost: Verifying localhost ssh..." +# make sure we can ssh ourselves so ipoibping test works +connect_to_host $user localhost +connect_to_host $user $ihost +# make sure we can ssh to ourselves over ipoib, so MPI can be run on master +if [ x"$ihost_ib" != "x" ] +then + connect_to_host $user $ihost_ib +fi +echo "$ihost: Configured localhost ssh" + +#stty $stty_settings +update_known_hosts diff --git a/IbaTools/stream/HISTORY.txt b/IbaTools/stream/HISTORY.txt new file mode 100644 index 0000000..496fca6 --- /dev/null +++ b/IbaTools/stream/HISTORY.txt @@ -0,0 +1,152 @@ +------------------------------------------------------------------------- + +Revisions as of Thu, Jan 17, 2013 3:50:01 PM + +Version 5.10 of stream.c has been released. +This version includes improved validation code and will automatically +use 64-bit array indices on 64-bit systems to allow very large arrays. + +------------------------------------------------------------------------- + +Revisions as of Thu Feb 19 08:16:57 CST 2009 + +Note that the codes in the "Versions" subdirectory should be +considered obsolete -- the versions of stream.c and stream.f +in this main directory include the OpenMP directives and structure +for creating "TUNED" versions. + +Only the MPI version in the "Versions" subdirectory should be +of any interest, and I have not recently checked that version for +errors or compliance with the current versions of stream.c and +stream.f. + +I added a simple Makefile to this directory. It works under Cygwin +on my Windows XP box (using gcc and g77). + +A user suggested a sneaky trick for "mysecond.c" -- instead of using +the #ifdef UNDERSCORE to generate the function name that the Fortran +compiler expects, the new version simply defines both "mysecond()" +and "mysecond_()", so it should automagically link with most Fortran +compilers. + +------------------------------------------------------------------------- + +Revisions as of Wed Nov 17 09:15:37 CST 2004 + +The most recent "official" versions have been renamed "stream.f" and +"stream.c" -- all other versions have been moved to the "Versions" +subdirectory. + +The "official" timer (was "second_wall.c") has been renamed "mysecond.c". +This is embedded in the C version ("stream.c"), but still needs to be +externally linked to the FORTRAN version ("stream.f"). + +------------------------------------------------------------------------- + +Revisions as of Tue May 27 11:51:23 CDT 2003 + +Copyright and License info added to stream_d.f, stream_mpi.f, and +stream_tuned.f + + +------------------------------------------------------------------------- + +Revisions as of Tue Apr 8 10:26:48 CDT 2003 + +I changed the name of the timer interface from "second" to "mysecond" +and removed the dummy argument in all versions of the source code (but +not the "Contrib" versions). + + +------------------------------------------------------------------------- + +Revisions as of Mon Feb 25 06:48:14 CST 2002 + +Added an OpenMP version of stream_d.c, called stream_d_omp.c. This is +still not up to date with the Fortran version, which includes error +checking and advanced data flow to prevent overoptimization, but it is +a good start.... + + +------------------------------------------------------------------------- + +Revisions as of Tue Jun 4 16:31:31 EDT 1996 + +I have fixed an "off-by-one" error in the RMS time calculation in +stream_d.f. This was already corrected in stream_d.c. No results are +invalidated, since I use minimum time instead of RMS time anyway.... + +------------------------------------------------------------------------- + +Revisions as of Fri Dec 8 14:49:56 EST 1995 + +I have renamed the timer routines to: + second_cpu.c + second_wall.c + second_cpu.f + +All have a function interface named 'second' which returns a double +precision floating point number. It should be possible to link +second_wall.c with stream_d.f without too much trouble, though the +details will depend on your environment. + +If anyone builds versions of these timers for machines running the +Macintosh O/S or DOS/Windows, I would appreciate getting a copy. + +To clarify: + * For single-user machines, the wallclock timer is preferred. + * For parallel machines, the wallclock timer is required. + * For time-shared systems, the cpu timer is more reliable, + though less accurate. + + +------------------------------------------------------------------------- + +Revisions as of Wed Oct 25 09:40:32 EDT 1995 + +(1) NOTICE to C users: + + stream_d.c has been updated to version 4.0 (beta), and + should be functionally identical to stream_d.f + + Two timers are provided --- second_cpu.c and second_wall.c + second_cpu.c measures cpu time, while second_wall.c measures + elapsed (real) time. + + For single-user machines, the wallclock timer is preferred. + For parallel machines, the wallclock timer is required. + For time-shared systems, the cpu timer is more reliable, + though less accurate. + +(2) cstream.c has been removed -- use stream_d.c + +(3) stream_wall.f has been removed --- to do parallel aggregate + bandwidth runs, comment out the definition of FUNCTION SECOND + in stream_d.f and compile/link with second_wall.c + +(4) stream_offset has been deprecated. It is still here + and usable, but stream_d.f is the "standard" version. + There are easy hooks in stream_d.f to change the + array offsets if you want to. + +(5) The rules of the game are clarified as follows: + + The reference case uses array sizes of 2,000,000 elements + and no additional offsets. I would like to see results + for this case. + + But, you are free to use any array size and any offset + you want, provided that the arrays are each bigger than + the last-level of cache. The output will show me what + parameters you chose. + + I expect that I will report just the best number, but + if there is a serious discrepancy between the reference + case and the "best" case, I reserve the right to report + both. + + Of course, I also reserve the right to reject any results + that I do not trust.... +-- +John D. McCalpin, Ph.D. +john@mccalpin.com diff --git a/IbaTools/stream/LICENSE.txt b/IbaTools/stream/LICENSE.txt new file mode 100644 index 0000000..cf1c8e0 --- /dev/null +++ b/IbaTools/stream/LICENSE.txt @@ -0,0 +1,34 @@ +*======================================================================= +*----------------------------------------------------------------------- +* Copyright 1991-2003: John D. McCalpin +*----------------------------------------------------------------------- +* License: +* 1. You are free to use this program and/or to redistribute +* this program. +* 2. You are free to modify this program for your own use, +* including commercial use, subject to the publication +* restrictions in item 3. +* 3. You are free to publish results obtained from running this +* program, or from works that you derive from this program, +* with the following limitations: +* 3a. In order to be referred to as "STREAM benchmark results", +* published results must be in conformance to the STREAM +* Run Rules, (briefly reviewed below) published at +* http://www.cs.virginia.edu/stream/ref.html +* and incorporated herein by reference. +* As the copyright holder, John McCalpin retains the +* right to determine conformity with the Run Rules. +* 3b. Results based on modified source code or on runs not in +* accordance with the STREAM Run Rules must be clearly +* labelled whenever they are published. Examples of +* proper labelling include: +* "tuned STREAM benchmark results" +* "based on a variant of the STREAM benchmark code" +* Other comparable, clear and reasonable labelling is +* acceptable. +* 3c. Submission of results to the STREAM benchmark web site +* is encouraged, but not required. +* 4. Use of this program or creation of derived works based on this +* program constitutes acceptance of these licensing restrictions. +* 5. Absolutely no warranty is expressed or implied. +*----------------------------------------------------------------------- diff --git a/IbaTools/stream/Makefile b/IbaTools/stream/Makefile new file mode 100644 index 0000000..7ed670d --- /dev/null +++ b/IbaTools/stream/Makefile @@ -0,0 +1,153 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2018, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** +# Makefile for stream + +# Include Make Control Settings +include $(TL_DIR)/$(PROJ_FILE_DIR)/Makesettings.project + +#=============================================================================# +# Definitions: +#-----------------------------------------------------------------------------# + +# Name of SubProjects +DS_SUBPROJECTS = +# name of executable or downloadable image +EXECUTABLE = $(BUILDDIR)/stream$(EXE_SUFFIX) +# list of sub directories to build +DIRS = +# C files (.c) +CFILES = \ + stream.c \ + # Add more c files here +# C++ files (.cpp) +CCFILES = \ + # Add more cpp files here +# lex files (.lex) +LFILES = \ + # Add more lex files here +# archive library files (basename, $ARFILES will add MOD_LIB_DIR/prefix and suffix) +LIBFILES= +# Windows Resource Files (.rc) +RSCFILES = +# Windows IDL File (.idl) +IDLFILE = +# Windows Linker Module Definitions (.def) file for dll's +DEFFILE = +# targets to build during INCLUDES phase (add public includes here) +INCLUDE_TARGETS = \ + # Add more h hpp files here +# Non-compiled files +MISC_FILES = +# all source files +SOURCES = $(CFILES) $(CCFILES) $(LFILES) $(RSCFILES) $(IDLFILE) +# Source files to include in DSP File +DSP_SOURCES = $(INCLUDE_TARGETS) $(SOURCES) $(MISC_FILES) \ + $(RSCFILES) $(DEFFILE) $(MAKEFILE) +# all object files +OBJECTS = $(CFILES:.c=$(OBJ_SUFFIX)) $(CCFILES:.cpp=$(OBJ_SUFFIX)) \ + $(LFILES:.lex=$(OBJ_SUFFIX)) +RSCOBJECTS = $(RSCFILES:.rc=$(RES_SUFFIX)) +# targets to build during LIBS phase +LIB_TARGETS_IMPLIB = +LIB_TARGETS_ARLIB = # $(LIB_PREFIX)ResourceTest$(ARLIB_SUFFIX) +LIB_TARGETS_EXP = $(LIB_TARGETS_IMPLIB:$(ARLIB_SUFFIX)=$(EXP_SUFFIX)) +LIB_TARGETS_MISC = +# targets to build during CMDS phase +CMD_TARGETS_SHLIB = +CMD_TARGETS_EXE = $(EXECUTABLE) +CMD_TARGETS_MISC = +# files to remove during clean phase +CLEAN_TARGETS_MISC = +CLEAN_TARGETS = $(OBJECTS) $(RSCOBJECTS) $(IDL_TARGETS) $(CLEAN_TARGETS_MISC) +# other files to remove during clobber phase +CLOBBER_TARGETS_MISC= +# sub-directory to install to within bin +BIN_SUBDIR = +# sub-directory to install to within include +INCLUDE_SUBDIR = + +# Additional Settings +#CLOCALDEBUG = User defined C debugging compilation flags [Empty] +#CCLOCALDEBUG = User defined C++ debugging compilation flags [Empty] +#CLOCAL = User defined C flags for compiling [Empty] +#CCLOCAL = User defined C++ flags for compiling [Empty] +#BSCLOCAL = User flags for Browse File Builder [Empty] +#DEPENDLOCAL = user defined makedepend flags [Empty] +#LINTLOCAL = User defined lint flags [Empty] +#LOCAL_INCLUDE_DIRS = User include directories to search for C/C++ headers [Empty] +#LDLOCAL = User defined C flags for linking [Empty] +#IMPLIBLOCAL = User flags for Object Lirary Manager [Empty] +#MIDLLOCAL = User flags for IDL compiler [Empty] +#RSCLOCAL = User flags for resource compiler [Empty] +#LOCALDEPLIBS = User libraries to include in dependencies [Empty] +#LOCALLIBS = User libraries to use when linking [Empty] +# (in addition to LOCALDEPLIBS) +#LOCAL_LIB_DIRS = User library directories for libpaths [Empty] + +CLOCAL = $(CPIE) -mcmodel=medium -DSTREAM_ARRAY_SIZE=353783808 -fopenmp +LDLOCAL = -fopenmp + +# Include Make Rules definitions and rules +include $(TL_DIR)/IbaTools/Makerules.module + +#=============================================================================# +# Overrides: +#-----------------------------------------------------------------------------# +#CCOPT = # C++ optimization flags, default lets build config decide +#COPT = # C optimization flags, default lets build config decide +#SUBSYSTEM = Subsystem to build for (none, console or windows) [none] +# (Windows Only) +#USEMFC = How Windows MFC should be used (none, static, shared, no_mfc) [none] +# (Windows Only) +COPT = -O3 +#=============================================================================# + +#=============================================================================# +# Rules: +#-----------------------------------------------------------------------------# +# process Sub-directories +include $(TL_DIR)/Makerules/Maketargets.toplevel + +# build cmds and libs +include $(TL_DIR)/Makerules/Maketargets.build + +# install for includes, libs and cmds phases +include $(TL_DIR)/Makerules/Maketargets.install + +# install for stage phase +include $(TL_DIR)/Makerules/Maketargets.stage + +# Unit test execution +#include $(TL_DIR)/Makerules/Maketargets.runtest + +#=============================================================================# + +#=============================================================================# +# DO NOT DELETE THIS LINE -- make depend depends on it. +#=============================================================================# diff --git a/IbaTools/stream/README b/IbaTools/stream/README new file mode 100644 index 0000000..bb3d2bc --- /dev/null +++ b/IbaTools/stream/README @@ -0,0 +1 @@ +STREAM: Sustainable Memory Bandwidth in High Performance Computers diff --git a/IbaTools/stream/stream.c b/IbaTools/stream/stream.c new file mode 100644 index 0000000..b9a2cee --- /dev/null +++ b/IbaTools/stream/stream.c @@ -0,0 +1,585 @@ +/*-----------------------------------------------------------------------*/ +/* Program: STREAM */ +/* Revision: $Id: stream.c,v 5.10 2013/01/17 16:01:06 mccalpin Exp mccalpin $ */ +/* Original code developed by John D. McCalpin */ +/* Programmers: John D. McCalpin */ +/* Joe R. Zagar */ +/* */ +/* This program measures memory transfer rates in MB/s for simple */ +/* computational kernels coded in C. */ +/*-----------------------------------------------------------------------*/ +/* Copyright 1991-2013: John D. McCalpin */ +/*-----------------------------------------------------------------------*/ +/* License: */ +/* 1. You are free to use this program and/or to redistribute */ +/* this program. */ +/* 2. You are free to modify this program for your own use, */ +/* including commercial use, subject to the publication */ +/* restrictions in item 3. */ +/* 3. You are free to publish results obtained from running this */ +/* program, or from works that you derive from this program, */ +/* with the following limitations: */ +/* 3a. In order to be referred to as "STREAM benchmark results", */ +/* published results must be in conformance to the STREAM */ +/* Run Rules, (briefly reviewed below) published at */ +/* http://www.cs.virginia.edu/stream/ref.html */ +/* and incorporated herein by reference. */ +/* As the copyright holder, John McCalpin retains the */ +/* right to determine conformity with the Run Rules. */ +/* 3b. Results based on modified source code or on runs not in */ +/* accordance with the STREAM Run Rules must be clearly */ +/* labelled whenever they are published. Examples of */ +/* proper labelling include: */ +/* "tuned STREAM benchmark results" */ +/* "based on a variant of the STREAM benchmark code" */ +/* Other comparable, clear, and reasonable labelling is */ +/* acceptable. */ +/* 3c. Submission of results to the STREAM benchmark web site */ +/* is encouraged, but not required. */ +/* 4. Use of this program or creation of derived works based on this */ +/* program constitutes acceptance of these licensing restrictions. */ +/* 5. Absolutely no warranty is expressed or implied. */ +/*-----------------------------------------------------------------------*/ +# include +# include +# include +# include +# include +# include + +/*----------------------------------------------------------------------- + * INSTRUCTIONS: + * + * 1) STREAM requires different amounts of memory to run on different + * systems, depending on both the system cache size(s) and the + * granularity of the system timer. + * You should adjust the value of 'STREAM_ARRAY_SIZE' (below) + * to meet *both* of the following criteria: + * (a) Each array must be at least 4 times the size of the + * available cache memory. I don't worry about the difference + * between 10^6 and 2^20, so in practice the minimum array size + * is about 3.8 times the cache size. + * Example 1: One Xeon E3 with 8 MB L3 cache + * STREAM_ARRAY_SIZE should be >= 4 million, giving + * an array size of 30.5 MB and a total memory requirement + * of 91.5 MB. + * Example 2: Two Xeon E5's with 20 MB L3 cache each (using OpenMP) + * STREAM_ARRAY_SIZE should be >= 20 million, giving + * an array size of 153 MB and a total memory requirement + * of 458 MB. + * (b) The size should be large enough so that the 'timing calibration' + * output by the program is at least 20 clock-ticks. + * Example: most versions of Windows have a 10 millisecond timer + * granularity. 20 "ticks" at 10 ms/tic is 200 milliseconds. + * If the chip is capable of 10 GB/s, it moves 2 GB in 200 msec. + * This means the each array must be at least 1 GB, or 128M elements. + * + * Version 5.10 increases the default array size from 2 million + * elements to 10 million elements in response to the increasing + * size of L3 caches. The new default size is large enough for caches + * up to 20 MB. + * Version 5.10 changes the loop index variables from "register int" + * to "ssize_t", which allows array indices >2^32 (4 billion) + * on properly configured 64-bit systems. Additional compiler options + * (such as "-mcmodel=medium") may be required for large memory runs. + * + * Array size can be set at compile time without modifying the source + * code for the (many) compilers that support preprocessor definitions + * on the compile line. E.g., + * gcc -O -DSTREAM_ARRAY_SIZE=100000000 stream.c -o stream.100M + * will override the default size of 10M with a new size of 100M elements + * per array. + */ +#ifndef STREAM_ARRAY_SIZE +# define STREAM_ARRAY_SIZE 10000000 +#endif + +/* 2) STREAM runs each kernel "NTIMES" times and reports the *best* result + * for any iteration after the first, therefore the minimum value + * for NTIMES is 2. + * There are no rules on maximum allowable values for NTIMES, but + * values larger than the default are unlikely to noticeably + * increase the reported performance. + * NTIMES can also be set on the compile line without changing the source + * code using, for example, "-DNTIMES=7". + */ +#ifdef NTIMES +#if NTIMES<=1 +# define NTIMES 10 +#endif +#endif +#ifndef NTIMES +# define NTIMES 10 +#endif + +/* Users are allowed to modify the "OFFSET" variable, which *may* change the + * relative alignment of the arrays (though compilers may change the + * effective offset by making the arrays non-contiguous on some systems). + * Use of non-zero values for OFFSET can be especially helpful if the + * STREAM_ARRAY_SIZE is set to a value close to a large power of 2. + * OFFSET can also be set on the compile line without changing the source + * code using, for example, "-DOFFSET=56". + */ +#ifndef OFFSET +# define OFFSET 0 +#endif + +/* + * 3) Compile the code with optimization. Many compilers generate + * unreasonably bad code before the optimizer tightens things up. + * If the results are unreasonably good, on the other hand, the + * optimizer might be too smart for me! + * + * For a simple single-core version, try compiling with: + * cc -O stream.c -o stream + * This is known to work on many, many systems.... + * + * To use multiple cores, you need to tell the compiler to obey the OpenMP + * directives in the code. This varies by compiler, but a common example is + * gcc -O -fopenmp stream.c -o stream_omp + * The environment variable OMP_NUM_THREADS allows runtime control of the + * number of threads/cores used when the resulting "stream_omp" program + * is executed. + * + * To run with single-precision variables and arithmetic, simply add + * -DSTREAM_TYPE=float + * to the compile line. + * Note that this changes the minimum array sizes required --- see (1) above. + * + * The preprocessor directive "TUNED" does not do much -- it simply causes the + * code to call separate functions to execute each kernel. Trivial versions + * of these functions are provided, but they are *not* tuned -- they just + * provide predefined interfaces to be replaced with tuned code. + * + * + * 4) Optional: Mail the results to mccalpin@cs.virginia.edu + * Be sure to include info that will help me understand: + * a) the computer hardware configuration (e.g., processor model, memory type) + * b) the compiler name/version and compilation flags + * c) any run-time information (such as OMP_NUM_THREADS) + * d) all of the output from the test case. + * + * Thanks! + * + *-----------------------------------------------------------------------*/ + +# define HLINE "-------------------------------------------------------------\n" + +# ifndef MIN +# define MIN(x,y) ((x)<(y)?(x):(y)) +# endif +# ifndef MAX +# define MAX(x,y) ((x)>(y)?(x):(y)) +# endif + +#ifndef STREAM_TYPE +#define STREAM_TYPE double +#endif + +static STREAM_TYPE a[STREAM_ARRAY_SIZE+OFFSET], + b[STREAM_ARRAY_SIZE+OFFSET], + c[STREAM_ARRAY_SIZE+OFFSET]; + +static double avgtime[4] = {0}, maxtime[4] = {0}, + mintime[4] = {FLT_MAX,FLT_MAX,FLT_MAX,FLT_MAX}; + +static char *label[4] = {"Copy: ", "Scale: ", + "Add: ", "Triad: "}; + +static double bytes[4] = { + 2 * sizeof(STREAM_TYPE) * STREAM_ARRAY_SIZE, + 2 * sizeof(STREAM_TYPE) * STREAM_ARRAY_SIZE, + 3 * sizeof(STREAM_TYPE) * STREAM_ARRAY_SIZE, + 3 * sizeof(STREAM_TYPE) * STREAM_ARRAY_SIZE + }; + +extern double mysecond(); +extern void checkSTREAMresults(); +#ifdef TUNED +extern void tuned_STREAM_Copy(); +extern void tuned_STREAM_Scale(STREAM_TYPE scalar); +extern void tuned_STREAM_Add(); +extern void tuned_STREAM_Triad(STREAM_TYPE scalar); +#endif +#ifdef _OPENMP +extern int omp_get_num_threads(); +#endif +int +main() + { + int quantum, checktick(); + int BytesPerWord; + int k; + ssize_t j; + STREAM_TYPE scalar; + double t, times[4][NTIMES]; + + /* --- SETUP --- determine precision and check timing --- */ + + printf(HLINE); + printf("STREAM version $Revision: 5.10 $\n"); + printf(HLINE); + BytesPerWord = sizeof(STREAM_TYPE); + printf("This system uses %d bytes per array element.\n", + BytesPerWord); + + printf(HLINE); +#ifdef N + printf("***** WARNING: ******\n"); + printf(" It appears that you set the preprocessor variable N when compiling this code.\n"); + printf(" This version of the code uses the preprocesor variable STREAM_ARRAY_SIZE to control the array size\n"); + printf(" Reverting to default value of STREAM_ARRAY_SIZE=%llu\n",(unsigned long long) STREAM_ARRAY_SIZE); + printf("***** WARNING: ******\n"); +#endif + + printf("Array size = %llu (elements), Offset = %d (elements)\n" , (unsigned long long) STREAM_ARRAY_SIZE, OFFSET); + printf("Memory per array = %.1f MiB (= %.1f GiB).\n", + BytesPerWord * ( (double) STREAM_ARRAY_SIZE / 1024.0/1024.0), + BytesPerWord * ( (double) STREAM_ARRAY_SIZE / 1024.0/1024.0/1024.0)); + printf("Total memory required = %.1f MiB (= %.1f GiB).\n", + (3.0 * BytesPerWord) * ( (double) STREAM_ARRAY_SIZE / 1024.0/1024.), + (3.0 * BytesPerWord) * ( (double) STREAM_ARRAY_SIZE / 1024.0/1024./1024.)); + printf("Each kernel will be executed %d times.\n", NTIMES); + printf(" The *best* time for each kernel (excluding the first iteration)\n"); + printf(" will be used to compute the reported bandwidth.\n"); + +#ifdef _OPENMP + printf(HLINE); +#pragma omp parallel + { +#pragma omp master + { + k = omp_get_num_threads(); + printf ("Number of Threads requested = %i\n",k); + } + } +#endif + +#ifdef _OPENMP + k = 0; +#pragma omp parallel +#pragma omp atomic + k++; + printf ("Number of Threads counted = %i\n",k); +#endif + + /* Get initial value for system clock. */ +#pragma omp parallel for + for (j=0; j= 1) + printf("Your clock granularity/precision appears to be " + "%d microseconds.\n", quantum); + else { + printf("Your clock granularity appears to be " + "less than one microsecond.\n"); + quantum = 1; + } + + t = mysecond(); +#pragma omp parallel for + for (j = 0; j < STREAM_ARRAY_SIZE; j++) + a[j] = 2.0E0 * a[j]; + t = 1.0E6 * (mysecond() - t); + + printf("Each test below will take on the order" + " of %d microseconds.\n", (int) t ); + printf(" (= %d clock ticks)\n", (int) (t/quantum) ); + printf("Increase the size of the arrays if this shows that\n"); + printf("you are not getting at least 20 clock ticks per test.\n"); + + printf(HLINE); + + printf("WARNING -- The above is only a rough guideline.\n"); + printf("For best results, please be sure you know the\n"); + printf("precision of your system timer.\n"); + printf(HLINE); + + /* --- MAIN LOOP --- repeat test cases NTIMES times --- */ + + scalar = 3.0; + for (k=0; k + +double mysecond() +{ + struct timeval tp; + struct timezone tzp; + int i; + + i = gettimeofday(&tp,&tzp); + return ( (double) tp.tv_sec + (double) tp.tv_usec * 1.e-6 ); +} + +#ifndef abs +#define abs(a) ((a) >= 0 ? (a) : -(a)) +#endif +void checkSTREAMresults () +{ + STREAM_TYPE aj,bj,cj,scalar; + STREAM_TYPE aSumErr,bSumErr,cSumErr; + STREAM_TYPE aAvgErr,bAvgErr,cAvgErr; + double epsilon; + ssize_t j; + int k,ierr,err; + + /* reproduce initialization */ + aj = 1.0; + bj = 2.0; + cj = 0.0; + /* a[] is modified during timing check */ + aj = 2.0E0 * aj; + /* now execute timing loop */ + scalar = 3.0; + for (k=0; k epsilon) { + err++; + printf ("Failed Validation on array a[], AvgRelAbsErr > epsilon (%e)\n",epsilon); + printf (" Expected Value: %e, AvgAbsErr: %e, AvgRelAbsErr: %e\n",aj,aAvgErr,abs(aAvgErr)/aj); + ierr = 0; + for (j=0; j epsilon) { + ierr++; +#ifdef VERBOSE + if (ierr < 10) { + printf(" array a: index: %ld, expected: %e, observed: %e, relative error: %e\n", + j,aj,a[j],abs((aj-a[j])/aAvgErr)); + } +#endif + } + } + printf(" For array a[], %d errors were found.\n",ierr); + } + if (abs(bAvgErr/bj) > epsilon) { + err++; + printf ("Failed Validation on array b[], AvgRelAbsErr > epsilon (%e)\n",epsilon); + printf (" Expected Value: %e, AvgAbsErr: %e, AvgRelAbsErr: %e\n",bj,bAvgErr,abs(bAvgErr)/bj); + printf (" AvgRelAbsErr > Epsilon (%e)\n",epsilon); + ierr = 0; + for (j=0; j epsilon) { + ierr++; +#ifdef VERBOSE + if (ierr < 10) { + printf(" array b: index: %ld, expected: %e, observed: %e, relative error: %e\n", + j,bj,b[j],abs((bj-b[j])/bAvgErr)); + } +#endif + } + } + printf(" For array b[], %d errors were found.\n",ierr); + } + if (abs(cAvgErr/cj) > epsilon) { + err++; + printf ("Failed Validation on array c[], AvgRelAbsErr > epsilon (%e)\n",epsilon); + printf (" Expected Value: %e, AvgAbsErr: %e, AvgRelAbsErr: %e\n",cj,cAvgErr,abs(cAvgErr)/cj); + printf (" AvgRelAbsErr > Epsilon (%e)\n",epsilon); + ierr = 0; + for (j=0; j epsilon) { + ierr++; +#ifdef VERBOSE + if (ierr < 10) { + printf(" array c: index: %ld, expected: %e, observed: %e, relative error: %e\n", + j,cj,c[j],abs((cj-c[j])/cAvgErr)); + } +#endif + } + } + printf(" For array c[], %d errors were found.\n",ierr); + } + if (err == 0) { + printf ("Solution Validates: avg error less than %e on all three arrays\n",epsilon); + } +#ifdef VERBOSE + printf ("Results Validation Verbose Results: \n"); + printf (" Expected a(1), b(1), c(1): %f %f %f \n",aj,bj,cj); + printf (" Observed a(1), b(1), c(1): %f %f %f \n",a[1],b[1],c[1]); + printf (" Rel Errors on a, b, c: %e %e %e \n",abs(aAvgErr/aj),abs(bAvgErr/bj),abs(cAvgErr/cj)); +#endif +} + +#ifdef TUNED +/* stubs for "tuned" versions of the kernels */ +void tuned_STREAM_Copy() +{ + ssize_t j; +#pragma omp parallel for + for (j=0; j +#include +#include +#include +#include +#include +#include +#include "iba/stl_types.h" + +/* Info for all switches */ +int LinkWidthSelection; /* selection for Link Width */ +int NodeDescSelection; /* selection for Node Description */ +int FMEnabledSelection; /* selection for FM Enabled */ +int LinkCRCModeSelection; /* selection for link CRC mode */ + +/* Globals for chassis specifics */ + +void stripCR(char *buf) +{ + char *p; + + if ((p = strchr(buf, '\n')) != NULL) + *p = '\0'; + if ((p = strchr(buf, '\r')) != NULL) + *p = '\0'; + + return; +} + +int getYesNo(char *question, int def) +{ + int done = 0; + int res = 1; + char answerBuf[8]; + + while (!done) + { + printf("%s: ", question); + if (fgets(answerBuf, 8, stdin) != NULL) { + stripCR(answerBuf); + if ((answerBuf[0] == 'n') || (answerBuf[0] == 'N')) + { + res = 0; + done = 1; + } + else if ((answerBuf[0] == 'y') || (answerBuf[0] == 'Y')) + { + res = 1; + done = 1; + } + else if (strlen(answerBuf) == 0) + { + res = def; + done = 1; + } + else + { + fprintf(stderr, "<%s> is not a valid entry - please enter y or n ... \n", answerBuf); + } + } else { + fprintf(stderr, "<%s> is not a valid entry - please enter y or n ... \n", answerBuf); + } + } + return(res); +} + +int getInt(char *question, int low, int high) +{ + int done = 0; + int selection; + int res = 1; + int i; + int goodInt; + char answerBuf[64]; + + while (!done) + { + printf("%s: ", question); + if (fgets(answerBuf, 64, stdin) != NULL) { + stripCR(answerBuf); + + if (strlen(answerBuf) == 0) + goodInt = 0; + else { + for (i = 0, goodInt = 1; (i < strlen(answerBuf)) && goodInt; i++) { + if (!isdigit(answerBuf[i])) + goodInt = 0; + } + } + + if (goodInt) + selection = atoi(answerBuf); + else + selection = -1; + + if ((selection < low) || (selection > high)) + fprintf(stderr, "<%s> is not a valid entry - please select a choice from %d to %d ...\n", answerBuf, low, high); + else + { + res = selection; + done = 1; + } + } else { + fprintf(stderr, "<%s> is not a valid entry - please select a choice from %d to %d ...\n", answerBuf, low, high); + } + } + return(res); +} + +int getIntRange(char *question, int low, int high, int other) +{ + int done = 0; + int selection; + int res = 1; + int i; + int goodInt; + char answerBuf[64]; + + while (!done) + { + printf("%s: ", question); + if (fgets(answerBuf, 64, stdin) != NULL) { + stripCR(answerBuf); + + if (strlen(answerBuf) == 0) + goodInt = 0; + else { + for (i = 0, goodInt = 1; (i < strlen(answerBuf)) && goodInt; i++) { + if (!isdigit(answerBuf[i])) + goodInt = 0; + } + } + + if (goodInt) + selection = atoi(answerBuf); + else + selection = -1; + + if (((selection < low) || (selection > high)) && (selection != other)) + fprintf(stderr, "<%s> is not a valid entry - please select a choice from %d to %d, or %d ...\n", answerBuf, low, high, other); + else + { + res = selection; + done = 1; + } + } else { + fprintf(stderr, "<%s> is not a valid entry - please select a choice from %d to %d, or %d ...\n", answerBuf, low, high, other); + } + } + return(res); +} + + +void removeCR(char *buf) +{ + char *p; + + if ((p = strchr(buf, '\n')) != NULL) + *p = '\0'; +} + +int getGeneralInfo() +{ + int setLinkWidthOptions = 0; + int setNodeDesc = 0; + int setFMEnabled = 0; + int setLinkCRCMode = 0; + int res = 1; + + setLinkWidthOptions = getYesNo("Do you wish to configure the switch Link Width Options? [n]", 0); + if (setLinkWidthOptions) + { + printf("\t1 : 1X\n\t2 : 2X\n\t3 : 1X/2X\n\t4 : 3X\n\t5 : 1X/3X\n\t6 : 2X/3X\n\t7 : 1X/2X/3X\n\t8 : 4X\n\t9 : 1X/4X\n\t10 : 2X/4X\n\t11 : 1X/2X/4X\n\t12 : 3X/4X\n\t13 : 1X/3X/4X\n\t14 : 2X/3X/4X\n\t15 : 1X/2X/3X/4X\n"); + LinkWidthSelection = getInt("Enter selection", 1, 15); + printf("********************************************************************************************\n"); + printf("*** Note: port 1 on each switch device will always be set to include 4X link width enabled\n"); + printf("*** Note: a reboot of all switch devices is required in order to activate\n*** changes to the switch link width\n"); + printf("********************************************************************************************\n"); + } else + LinkWidthSelection = 0; + + setNodeDesc = getYesNo("Do you wish to configure the switch Node Description as it is set in the switches file? [n]", 0); + NodeDescSelection = setNodeDesc; + + setFMEnabled = getYesNo("Do you wish to configure the switch FM Enabled option? [n]", 0); + if (setFMEnabled) { + FMEnabledSelection = getInt("Enter 0 for disable, 1 for enable", 0, 1); + printf("********************************************************************************************\n"); + printf("*** Note: a reboot of all switch devices is required in order to activate\n*** changes to the FM Enabled setting\n"); + printf("********************************************************************************************\n"); + } else + FMEnabledSelection = -1; + + setLinkCRCMode = getYesNo("Do you wish to configure the switch Link CRC Mode? [n]", 0); + if (setLinkCRCMode) { + printf("\t0 : 16b,\n\t1 : 14b/16b,\n\t2 : 48b/16b,\n\t3 : 48b/14b/16b,\n\t4 : per-lane/16b,\n\t5 : per-lane/14b/16b,\n\t6 : per-lane/48b/16b,\n\t7 : per-lane/48b/14b/16b\n"); + LinkCRCModeSelection = getInt("Enter selection", 0, 7); + printf("********************************************************************************************\n"); + printf("*** Note: a reboot of all switch devices is required in order to activate\n*** changes to the Link CRC Mode \n"); + printf("********************************************************************************************\n"); + } else + LinkCRCModeSelection = -1; + + return(res); +} + +int +main(int argc, char *argv[]) +{ + FILE *fp_out; + char *dirName; + + dirName = argv[1]; + if (dirName == NULL) + dirName = "."; + + if (chdir(dirName) < 0) { + fprintf(stderr, "Error changing directory to %s: %s\n", dirName, strerror(errno)); + exit(1); + } + + getGeneralInfo(); + + if ((fp_out = fopen("./.switchSetup.out","w")) == NULL) + { + fprintf(stderr, "Error opening .switchSetup.out for output: %s\n", strerror(errno)); + exit(1); + } + + /* display general info */ + fprintf(fp_out, "Link Width Selection:%d\n", LinkWidthSelection); + fprintf(fp_out, "Node Description Selection:%d\n", NodeDescSelection); + fprintf(fp_out, "FM Enabled Selection:%d\n", FMEnabledSelection); + fprintf(fp_out, "Link CRC Mode Selection:%d\n", LinkCRCModeSelection); + + fclose(fp_out); + exit(0); +} diff --git a/IbaTools/usemem/Makefile b/IbaTools/usemem/Makefile new file mode 100644 index 0000000..7d03bbe --- /dev/null +++ b/IbaTools/usemem/Makefile @@ -0,0 +1,156 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** +# Makefile for usemem tool + +# Include Make Control Settings +include $(TL_DIR)/$(PROJ_FILE_DIR)/Makesettings.project + +#=============================================================================# +# Definitions: +#-----------------------------------------------------------------------------# + +# Name of SubProjects +DS_SUBPROJECTS = +# name of executable or downloadable image +EXECUTABLE = $(BUILDDIR)/usemem$(EXE_SUFFIX) +# list of sub directories to build +DIRS = +# C files (.c) +CFILES = \ + usemem.c \ + # Add more files here +# C++ files (.cpp) +CCFILES = \ + # Add more files here +# lex files (.lex) +LFILES = \ + # Add more lex files here +# archive library files (basename, $ARFILES will add MOD_LIB_DIR/prefix and suffix) +LIBFILES = +# Windows Resource Files (.rc) +RSCFILES = +# Windows IDL File (.idl) +IDLFILE = +# Windows Linker Module Definitions (.def) file for dll's +DEFFILE = +# targets to build during INCLUDES phase (add public includes here) +INCLUDE_TARGETS = \ + # Add more h hpp files here +# Non-compiled files +MISC_FILES = +# all source files +SOURCES = $(CFILES) $(CCFILES) $(LFILES) $(RSCFILES) $(IDLFILE) +# Source files to include in DSP File +DSP_SOURCES = $(INCLUDE_TARGETS) $(SOURCES) $(MISC_FILES) \ + $(RSCFILES) $(DEFFILE) $(MAKEFILE) +# all object files +OBJECTS = $(CFILES:.c=$(OBJ_SUFFIX)) $(CCFILES:.cpp=$(OBJ_SUFFIX)) \ + $(LFILES:.lex=$(OBJ_SUFFIX)) +RSCOBJECTS = $(RSCFILES:.rc=$(RES_SUFFIX)) + +# targets to build during LIBS phase +LIB_TARGETS_IMPLIB = +LIB_TARGETS_ARLIB = +LIB_TARGETS_EXP = $(LIB_TARGETS_IMPLIB:$(ARLIB_SUFFIX)=$(EXP_SUFFIX)) +LIB_TARGETS_MISC = +# targets to build during CMDS phase +CMD_TARGETS_SHLIB = +CMD_TARGETS_EXE = $(EXECUTABLE) +CMD_TARGETS_MISC = +CMD_TARGETS_DRIVER = +# files to remove during clean phase +CLEAN_TARGETS_MISC = +CLEAN_TARGETS = $(OBJECTS) $(RSCOBJECTS) $(IDL_TARGETS) $(CLEAN_TARGETS_MISC) +# other files to remove during clobber phase +CLOBBER_TARGETS_MISC= +# sub-directory to install to within bin +BIN_SUBDIR = +# sub-directory to install to within include +INCLUDE_SUBDIR = + +# Additional Settings +#CLOCALDEBUG = User defined C debugging compilation flags [Empty] +#CCLOCALDEBUG = User defined C++ debugging compilation flags [Empty] +#CLOCAL = User defined C flags for compiling [Empty] +#CCLOCAL = User defined C++ flags for compiling [Empty] +#BSCLOCAL = User flags for Browse File Builder [Empty] +#DEPENDLOCAL = user defined makedepend flags [Empty] +#LINTLOCAL = User defined lint flags [Empty] +#LOCAL_INCLUDE_DIRS = User include directories to search for C/C++ headers [Empty] +#LDLOCAL = User defined C flags for linking [Empty] +#IMPLIBLOCAL = User flags for Object Lirary Manager [Empty] +#MIDLLOCAL = User flags for IDL compiler [Empty] +#RSCLOCAL = User flags for resource compiler [Empty] +#LOCALDEPLIBS = User libraries to include in dependencies [Empty] +#LOCALLIBS = User libraries to use when linking [Empty] +# (in addition to LOCALDEPLIBS) +# = User library directories for libpaths [Empty] + +CLOCAL = $(CPIE) + +LOCAL_LIB_DIRS = +LOCALLIBS=m + +# Include Make Rules definitions and rules +include $(TL_DIR)/IbaTools/Makerules.module + +#=============================================================================# +# Overrides: +#-----------------------------------------------------------------------------# +#CCOPT = # C++ optimization flags, default lets build config decide +#COPT = # C optimization flags, default lets build config decide +#SUBSYSTEM = Subsystem to build for (none, console or windows) [none] +# (Windows Only) +#USEMFC = How Windows MFC should be used (none, static, shared, no_mfc) [none] +# (Windows Only) +#=============================================================================# + +#=============================================================================# +# Rules: +#-----------------------------------------------------------------------------# +# process Sub-directories +include $(TL_DIR)/Makerules/Maketargets.toplevel + +# build cmds and libs +include $(TL_DIR)/Makerules/Maketargets.build + +# install for includes, libs and cmds phases +include $(TL_DIR)/Makerules/Maketargets.install + +# install for stage phase +include $(TL_DIR)/Makerules/Maketargets.stage + +# Unit test execution +#include $(TL_DIR)/Makerules/Maketargets.runtest + +#=============================================================================# + +#=============================================================================# +# DO NOT DELETE THIS LINE -- make depend depends on it. +#=============================================================================# diff --git a/IbaTools/usemem/usemem.c b/IbaTools/usemem/usemem.c new file mode 100644 index 0000000..bf3c2a7 --- /dev/null +++ b/IbaTools/usemem/usemem.c @@ -0,0 +1,130 @@ +/* BEGIN_ICS_COPYRIGHT5 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + * ** END_ICS_COPYRIGHT5 ****************************************/ +/* [ICS VERSION STRING: unknown] */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +void a(int *f) +{ +#ifdef USE__STACK + int z[16384]; + + f[0] = 1; + f[16383] = 2; +#else + int *z = sbrk(16384); + if(z == (int *)-1) { + perror("couldn't allocate more memory while recursing"); + exit(1); + } + +#endif + + printf("a(%p)\n", f); + sched_yield(); + a(z); +} + + +int +main(int cnt, char **args) +{ + unsigned long mem, i, pages, pgsz, passes; + uint64_t tot, totmem=0x1000000000; // 64GB + // volatile int val; + volatile char *p; + int zfirst[16384]; + int verbose=0; + + if(cnt < 2 || (mem = strtoul(args[1], NULL, 0)) <= 0) { + printf("Usage: %s mem_incr [totmem]\n", args[0]); + return 1; + } + if(cnt == 3 && (totmem = strtoul(args[2], NULL, 0)) <= 0) { + printf("Usage: %s mem_incr [totmem]\n", args[0]); + return 1; + } + + if (mem > totmem) { + printf("mem_incr is larger than totmem.\n"); + return 1; + } else if (totmem > 0x100000000000) { // 16 terabytes... + printf("totmem is too large.\n"); + return 1; + } + + if(0 && mlockall(MCL_CURRENT|MCL_FUTURE)) + perror("mlockall failed"); + + pgsz = getpagesize(); + + for(tot=passes=0; tot + +#if defined(VXWORKS) +#include "vxWorks.h" +#else +#include +#define UINT8 uint8_t +#define UINT32 uint32_t +#endif + +#define ICS_IMAGE_HEADER_RECORD_TYPE_INFO 0x49435301 /* file magic number - 'I' 'C' 'S' 0x01 */ +#define ICS_IMAGE_HEADER_RECORD_TYPE_INFO_WRONG_ENDIAN 0x01534349 /* what you would see in the wrong endian */ +#define ICS_IMAGE_HEADER_RECORD_TYPE_MD5 1 +#define ICS_IMAGE_HEADER_RECORD_TYPE_TERMINATOR 2 +#define ICS_IMAGE_HEADER_RECORD_TYPE_VXWORKSIMAGETYPE 3 +#define ICS_IMAGE_HEADER_RECORD_TYPE_CBC_FILE_INFO 4 +#define ICS_IMAGE_HEADER_RECORD_TYPE_MBC_FILE_INFO 5 +#define ICS_IMAGE_HEADER_RECORD_TYPE_ACM_FILE_INFO 6 +#define ICS_IMAGE_HEADER_RECORD_TYPE_XIO_FPGA_CFG 7 +#define ICS_IMAGE_HEADER_RECORD_TYPE_Q7IMAGETYPE 8 + +#define ICS_IMAGE_HEADER_VERSION_SIZE 20 +#define ICS_IMAGE_HEADER_FILE_VERSION_SIZE 40 + +#define ICS_IMAGE_HEADER_FILE_INFO_FLAG_NONE 0 +#define ICS_IMAGE_HEADER_FILE_INFO_FLAG_GZIPPED 1 +#define ICS_IMAGE_HEADER_FILE_INFO_FLAG_VXDEFLATED 2 + +#define ICS_IMAGE_HEADER_PAYLOAD_SIZE(record_name) (sizeof(IcsImageHeader_##record_name##Payload_t)) +#define ICS_IMAGE_HEADER_PAYLOAD_SIZE_INFO ICS_IMAGE_HEADER_PAYLOAD_SIZE(Info) +#define ICS_IMAGE_HEADER_PAYLOAD_SIZE_MD5 ICS_IMAGE_HEADER_PAYLOAD_SIZE(Md5) +#define ICS_IMAGE_HEADER_PAYLOAD_SIZE_TERMINATOR ICS_IMAGE_HEADER_PAYLOAD_SIZE(Terminator) +#define ICS_IMAGE_HEADER_PAYLOAD_SIZE_VXWORKSIMAGETYPE ICS_IMAGE_HEADER_PAYLOAD_SIZE(VxWorksImageType) +#define ICS_IMAGE_HEADER_PAYLOAD_SIZE_CBC_FILE_INFO ICS_IMAGE_HEADER_PAYLOAD_SIZE(FileInfo) +#define ICS_IMAGE_HEADER_PAYLOAD_SIZE_MBC_FILE_INFO ICS_IMAGE_HEADER_PAYLOAD_SIZE(FileInfo) +#define ICS_IMAGE_HEADER_PAYLOAD_SIZE_ACM_FILE_INFO ICS_IMAGE_HEADER_PAYLOAD_SIZE(FileInfo) +#define ICS_IMAGE_HEADER_PAYLOAD_SIZE_XIO_FPGA_CFG ICS_IMAGE_HEADER_PAYLOAD_SIZE(XioFpgaCfgType) +#define ICS_IMAGE_HEADER_PAYLOAD_SIZE_Q7IMAGETYPE ICS_IMAGE_HEADER_PAYLOAD_SIZE(q7ImageType) + +#define ICS_IMAGE_HEADER_ENUM_VXWORKSIMAGETYPE_BOOTROM 1 +#define ICS_IMAGE_HEADER_ENUM_VXWORKSIMAGETYPE_LOADABLE 2 +#define ICS_IMAGE_HEADER_ENUM_Q7IMAGETYPE_BIOS 3 +#define ICS_IMAGE_HEADER_ENUM_Q7IMAGETYPE_BOARD_CONTROLLER 4 +#define ICS_IMAGE_HEADER_ENUM_XIO_FPGA_CFG_SUBTYPE 1 + +typedef struct IcsImageHeaderInfoPayloadStruct { + UINT32 productCode; + UINT32 bspCode; + char version[ICS_IMAGE_HEADER_VERSION_SIZE]; + UINT32 headerSize; + UINT32 recordCount; + UINT32 imageSize; +} __attribute__ ((packed)) IcsImageHeader_InfoPayload_t ; + + +typedef UINT8 IcsImageHeader_Md5Payload_t[16]; + + +typedef struct IcsImageHeaderTerminatorPayloadStruct { + UINT32 recordCount; +} __attribute__ ((packed)) IcsImageHeader_TerminatorPayload_t ; + + +typedef UINT32 IcsImageHeader_VxWorksImageTypePayload_t; + +typedef UINT32 IcsImageHeader_XioFpgaCfgTypePayload_t; + +typedef UINT32 IcsImageHeader_q7ImageTypePayload_t; + +typedef struct FileInfoPayloadStruct { + UINT32 offset; + UINT32 size; + UINT32 flags; + char version[ICS_IMAGE_HEADER_FILE_VERSION_SIZE]; +} __attribute__ ((packed)) IcsImageHeader_FileInfoPayload_t ; + + +typedef struct IcsImageHeaderRecordStruct { + UINT32 type; + UINT32 size; + union IcsImageHeaderRecordPayloadUnion { + IcsImageHeader_InfoPayload_t info; + IcsImageHeader_Md5Payload_t md5; + IcsImageHeader_TerminatorPayload_t terminator; + IcsImageHeader_VxWorksImageTypePayload_t vxWorksImageType; + IcsImageHeader_FileInfoPayload_t fileInfo; + IcsImageHeader_XioFpgaCfgTypePayload_t xioFpgaCfgType; + IcsImageHeader_q7ImageTypePayload_t q7ImageType; + } payload; +} __attribute__ ((packed)) IcsImageHeader_Record_t ; + + +#endif /* ICS_IMAGE_HEADER_H_INCLUDED */ + + diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..d8eb6e5 --- /dev/null +++ b/LICENSE @@ -0,0 +1,36 @@ +Copyright (c) 2015, Intel Corporation +All rights reserved. + +BSD 3-clause License: +Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: +- Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. +- Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. +- Neither the name of Intel Corporation nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL INTEL, THE COPYRIGHT OWNER OR CONTRIBUTORS +BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. + +EXPORT LAWS: THIS LICENSE ADDS NO RESTRICTIONS TO THE EXPORT LAWS OF YOUR +JURISDICTION. It is licensee's responsibility to comply with any export +regulations applicable in licensee's jurisdiction. Under CURRENT (May 2000) +U.S. export regulations this software is eligible for export from the U.S. +and can be downloaded by or otherwise exported or reexported worldwide EXCEPT +to U.S. embargoed destinations which include Cuba, Iraq, Libya, North Korea, +Iran, Syria, Sudan, Afghanistan and any other country to which the U.S. has +embargoed goods and services. + diff --git a/Lsf/Makefile b/Lsf/Makefile new file mode 100644 index 0000000..5ac44c8 --- /dev/null +++ b/Lsf/Makefile @@ -0,0 +1,164 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** +# Makefile for xedge_swreset + +# Include Make Control Settings +include $(TL_DIR)/$(PROJ_FILE_DIR)/Makesettings.project + +#=============================================================================# +# Definitions: +#-----------------------------------------------------------------------------# + +# Name of SubProjects +DS_SUBPROJECTS = +# name of executable or downloadable image +EXECUTABLE = +# list of sub directories to build +DIRS = +# C files (.c) +CFILES = \ + # Add more c files here +# C++ files (.cpp) +CCFILES = \ + # Add more cpp files here +# lex files (.lex) +LFILES = \ + # Add more lex files here +# archive library files (basename, $ARFILES will add MOD_LIB_DIR/prefix and suffix) +LIBFILES= +# Windows Resource Files (.rc) +RSCFILES = +# Windows IDL File (.idl) +IDLFILE = +# Windows Linker Module Definitions (.def) file for dll's +DEFFILE = +# targets to build during INCLUDES phase (add public includes here) +INCLUDE_TARGETS = \ + # Add more h hpp files here +# Non-compiled files + # Add more files here +MISC_FILES = \ + edit.openmpi.wrapper \ + lsf.submit.mvapich2.job \ + lsf.submit.mvapich.job \ + lsf.submit.openmpi.job \ + lsf.submit.openmpi-q.job \ + openmpi_wrapper \ + README \ + ssh.script +# all source files +SOURCES = $(CFILES) $(CCFILES) $(LFILES) $(RSCFILES) $(IDLFILE) +# Source files to include in DSP File +DSP_SOURCES = $(INCLUDE_TARGETS) $(SOURCES) $(MISC_FILES) \ + $(RSCFILES) $(DEFFILE) $(MAKEFILE) +# all object files +OBJECTS = $(CFILES:.c=$(OBJ_SUFFIX)) $(CCFILES:.cpp=$(OBJ_SUFFIX)) \ + $(LFILES:.lex=$(OBJ_SUFFIX)) +RSCOBJECTS = $(RSCFILES:.rc=$(RES_SUFFIX)) +# targets to build during LIBS phase +LIB_TARGETS_IMPLIB = +LIB_TARGETS_ARLIB = # $(LIB_PREFIX)ResourceTest$(ARLIB_SUFFIX) +LIB_TARGETS_EXP = $(LIB_TARGETS_IMPLIB:$(ARLIB_SUFFIX)=$(EXP_SUFFIX)) +LIB_TARGETS_MISC = +# targets to build during CMDS phase +CMD_TARGETS_SHLIB = +CMD_TARGETS_EXE = $(EXECUTABLE) +CMD_TARGETS_MISC = +# files to remove during clean phase +CLEAN_TARGETS_MISC = +CLEAN_TARGETS = $(OBJECTS) $(RSCOBJECTS) $(IDL_TARGETS) $(CLEAN_TARGETS_MISC) +# other files to remove during clobber phase +CLOBBER_TARGETS_MISC= +# sub-directory to install to within bin +BIN_SUBDIR = +# sub-directory to install to within include +INCLUDE_SUBDIR = + +# Additional Settings +#CLOCALDEBUG = User defined C debugging compilation flags [Empty] +#CCLOCALDEBUG = User defined C++ debugging compilation flags [Empty] +#CLOCAL = User defined C flags for compiling [Empty] +#CCLOCAL = User defined C++ flags for compiling [Empty] +#BSCLOCAL = User flags for Browse File Builder [Empty] +#DEPENDLOCAL = user defined makedepend flags [Empty] +#LINTLOCAL = User defined lint flags [Empty] +#LOCAL_INCLUDE_DIRS = User include directories to search for C/C++ headers [Empty] +#LDLOCAL = User defined C flags for linking [Empty] +#IMPLIBLOCAL = User flags for Object Lirary Manager [Empty] +#MIDLLOCAL = User flags for IDL compiler [Empty] +#RSCLOCAL = User flags for resource compiler [Empty] +#LOCALDEPLIBS = User libraries to include in dependencies [Empty] +#LOCALLIBS = User libraries to use when linking [Empty] +# (in addition to LOCALDEPLIBS) +#LOCAL_LIB_DIRS = User library directories for libpaths [Empty] + +LOCALDEPLIBS=$(IBACCESS_USER_LIBS) xedge_common opamgt-priv Md5 +LOCAL_INCLUDE_DIRS= +LOCALLIBS=$(OPENIB_USER_LIBS) +LOCAL_LIB_DIRS=$(OPENIB_USER_LIB_DIRS) $(IBACCESS_USER_LIB_DIRS) + +# Include Make Rules definitions and rules +include $(TL_DIR)/IbaTools/Makerules.module + +#=============================================================================# +# Overrides: +#-----------------------------------------------------------------------------# +#CCOPT = # C++ optimization flags, default lets build config decide +#COPT = # C optimization flags, default lets build config decide +#SUBSYSTEM = Subsystem to build for (none, console or windows) [none] +# (Windows Only) +#USEMFC = How Windows MFC should be used (none, static, shared, no_mfc) [none] +# (Windows Only) +#=============================================================================# + +#=============================================================================# +# Rules: +#-----------------------------------------------------------------------------# +# process Sub-directories +include $(TL_DIR)/Makerules/Maketargets.toplevel + +# build cmds and libs +include $(TL_DIR)/Makerules/Maketargets.build + +# install for includes, libs and cmds phases +include $(TL_DIR)/Makerules/Maketargets.install + +# install for stage phase +include $(TL_DIR)/Makerules/Maketargets.stage +STAGE:: + $(VS)$(STAGE_INSTALL) $(STAGE_INSTALL_DIR_OPT) $(PROJ_STAGE_LSF_DIR) $(MISC_FILES) + +# Unit test execution +#include $(TL_DIR)/Makerules/Maketargets.runtest + +#=============================================================================# + +#=============================================================================# +# DO NOT DELETE THIS LINE -- make depend depends on it. +#=============================================================================# diff --git a/Lsf/README b/Lsf/README new file mode 100644 index 0000000..a9531c6 --- /dev/null +++ b/Lsf/README @@ -0,0 +1,189 @@ +Copyright (c) 2015, Intel Corporation +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: +- Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. +- Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. +- Neither the name of Intel Corporation nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL INTEL, THE COPYRIGHT OWNER OR CONTRIBUTORS +BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. + +EXPORT LAWS: THIS LICENSE ADDS NO RESTRICTIONS TO THE EXPORT LAWS OF YOUR +JURISDICTION. It is licensee's responsibility to comply with any export +regulations applicable in licensee's jurisdiction. Under CURRENT (May 2000) +U.S. export regulations this software is eligible for export from the U.S. +and can be downloaded by or otherwise exported or reexported worldwide EXCEPT +to U.S. embargoed destinations which include Cuba, Iraq, Libya, North Korea, +Iran, Syria, Sudan, Afghanistan and any other country to which the U.S. has +embargoed goods and services. + +[ICS VERSION STRING: unknown] + +README for Lsf scripts directory +-------------------------------- + +This directory contains: + +* Four scripts for submitting LSF jobs, one each for OpenMPI, mvapich, and mvapich2, plus a fourth + for using standard OpenMPI (verbs), which is tightly integrated with LSF +* A substitute script for ssh that is required for using MPI with LSF, as per LSF documentation +* A sample of the edited openmpi_wrapper from LSF code +* A vi input script to modify openmpi_wrapper to work with IntelOPA OFED OpenMPI verbs +* This file + + +Virtual Fabric integration with LSF +----------------------------------- + +The sole intent of the LSF scripts is to act as templates for the administrator, on how to enable +LSF to take advantage of Virtual Fabric (vFabric) functionality. In order to make these scripts +accessible to common users, the administrator must do the following: + + 1. (Optional) If necessary, edit the scripts to meet the configuration and usage criteria + requirements specific to your LSF environment. + 2. Copy the scripts to a shared file system service that provides the appropriate access rights + for common users. + +In order for LSF to take advantage of vFabric functionality, vFabric must be integrated with LSF. +There are several integration methods that could be used, these scripts use the method of LSF based +queues. This method requires that the administrator perform the following steps (for detailed +information on vFabric, reference "Fabric Manager Users Guide"): + + 1. For LSF, create a queue for each vFabric defined within the FM configuration file + (/etc/sysconfig/ifs_fm.xml). + 2. Configure each vFabric queue defined within LSF with the compute nodes assigned to it within + the FM configuration file. + 3. (Optional) Configure each vFabric queue defined within LSF with the priorities, policies, QoS, + and attributes that are specific to the needs of the organization and fabric environment. + + +Configuring Nodes for LSF +------------------------- + +It is recommended that the changes described in this README be performed on or propogated to +all nodes in the fabric. This will ensure proper job submission and operation. + +Fast Fabric may be used to set up password-less ssh. Once that is set up, it can be used to copy +the changed files to all nodes in the fabric. + + +LSF Submit Scripts +------------------ + +LSF submit scripts utilize the LSF primitive "bsub", encapsulating the arguments and call structure +for ease-of-use. They query the SA for information regarding virtual fabrics, or in the case of PSM +with dist_sa, pass the appropriate arguments to PSM for SA lookup. + +The submit scripts default the MPICH_PREFIX if it is not set in the environment, although it is +recommended to be set explicitly in the environment to avoid any confusion. The mvapich and +mvapich2 script default to the -qlc versions of MPI. There are two openmpi scripts; one for standard +mpi and one for the -qlc version. The bsub is different for standard openmpi, so it is in its own +script. + +Here are some examples of how to call the scripts and pass vFabric parameters: + +Example 1: + + lsf.submit.openmpi-q.job -p 2 -V vf_name -n Compute -d 3 osu2/osu_bibw + +This submits a job with the openmpi-qlc subsystem, i.e. the run file osu_bibw is expected to have been +compiled with the openmpi-qlc compiler under gcc. The number of processes is given as 2, and the virtual +fabric to use is identified by name, and that name is "Compute". Lastly, option 3 is given to denote +a dispersive routing option of static_dest. + +Example 2: + + lsf.submit.openmpi-q.job -p 2 -V sid -s 0x0000000000000022 -d 1 osu2/osu_bibw + +This submits a job with the openmpi-qlc subsystem, i.e. the run file osu_bibw is expected to have been +compiled with the openmpi-qlc compiler under gcc. The number of processes is given as 2, and the virtual +fabric to use is identified by service id, and that id is "0x0000000000000022". Lastly, option 1 is given +to denote a dispersive routing option of adaptive. + +Example 3: + + lsf.submit.openmpi-q.job -p 2 -V sid_qlc -s 0x1000117500000000 -q night osu2/osu_bibw + +This submits a job with the openmpi-qlc subsystem, i.e. the run file osu_bibw is expected to have been +compiled with the openmpi-qlc compiler under gcc. The number of processes is given as 2. The virtual fabric +to use is identified by service id, and that service id is "0x1000117500000000". The job will be passed to the +QIB driver which will perform the vFabric lookup on behalf of the job. No dispersive routing instructions are +given. The job is being requested for submission via the "night" LSF queue. + +To view the vFabric parameters associated with the job, use the "bjobs -l " command in LSF for +the long format of output. + + + +LSF Script Administration +------------------------- + +The scripts are intended to be tailored by the LSF administrator in order to structure the bsub +parameters appropriately. Any parameters, such as queue name, application profile, etc. may be inserted +into the script either using script options, accessing environment variables, or by hardcoding. + +Additionally, the scripts use mpirun_rsh to start MPI jobs. This method enables the vFabric parameters +to be passed to the MPI jobs so that the appropriate lower level actions can be taken based on those +settings (e.g. inserting Service Level information into data messages). Any MPI job command parameters +should be used on the script command line, and will be passed to the MPI run job. + + + +SSH Script +---------- + +In accordance with instructions in the Platform document "Integrating LSF's blaunch with MPI Applications", +a script for ssh is provided, so that LSF may intercept MPI jobs and convey them to the blaunch facility. +The script is constucted in such a way so that normal users of ssh are not affected, while LSF usage is +bypassed to blaunch. + +Instuctions to install the ssh script: + + 1. Log in as root + 2. cd /usr/bin + 3. mv ssh ssh.bin + 4. copy ssh.script as /usr/bin/ssh + + +Modifying openmpi_wrapper +------------------------- + +The openmpi_wrapper script provided with LSF, located in LSF_BINDIR, contains a hard-coded path to +the OpenMPI directory as installed by Platform's HPC kit. Since this installation supercedes that +one with the Intel kit, the location of the OpenMPI files is different. Therefore, the openmpi_wrapper +script needs to be modified. + +The ex script, edit.openmpi.wrapper, may be used to modify the openmpi_wrapper. It uses an ex editor +session to change the path from $MPIHOME to $MPICH_PREFIX. The file may be modified by using the script +while logged in as root, as follows: + +ex /opt/lsf/7.0/linux2.6-glibc2.3-x86_64/bin/openmpi_wrapper < edit.openmpi.wrapper + +If editing with the script fails, openmpi_wrapper may be edited manually to ensure that the path to +the MPIRUN_CMD is correct. + + +Configuration changes in lsf.conf +--------------------------------- + +The following change should be made to the lsf.conf file in order to ensure proper operation: + +- add "LSF_ROOT_REX=all" + +The LSF daemons need to be restarted for the configuration change to take effect. diff --git a/Lsf/edit.openmpi.wrapper b/Lsf/edit.openmpi.wrapper new file mode 100644 index 0000000..6f19c68 --- /dev/null +++ b/Lsf/edit.openmpi.wrapper @@ -0,0 +1,5 @@ +" [ICS VERSION STRING: unknown] +1 +/MPIRUN_CMD= +s/MPIHOME/MPICH_PREFIX/ +wq diff --git a/Lsf/lsf.submit.mvapich.job b/Lsf/lsf.submit.mvapich.job new file mode 100755 index 0000000..ebe5d57 --- /dev/null +++ b/Lsf/lsf.submit.mvapich.job @@ -0,0 +1,206 @@ +#! /bin/bash +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] + + +# initialize + +# BASE PATH TO MPI EXECUTABLES: To use an alternate location, +# either edit this line or set MPICH_PREFIX in your environment. +# see iba_select_mpi for the set of default MPI selections +# default to MPI used for build +MPICH_PREFIX= + +mpirunfile= +vfselectmethod=sid_qlc +vfname= +vfsid= +dsprtg= +qname= +mrailmap= + +MPI_CMD_ARGS= + +LSB_DJOB_NUMPROC=3 + +# Usage - display usage syntax and exit + +Usage() +{ + echo "Usage: submit.mvapich.job [-p num_processes] [-V vf_select_method] [-s vf_sid] [-n vf_name] [-d dsp_rtg] [-q queue_name] [-m [,]] mpi_run_file [mpi_run_file args]" + echo " where vf_select_method is one of:" + echo " vf_name: Name of virtual fabric - use -n to define vf name" + echo " sid : ServiceId of virtual fabric - use -s option to define service id" + echo " sid_qlc: ServiceId of virtual fabric - use -s option to define service id, uses dist_sa (default)" + echo " where dsp_rtg is one of: 1-adaptive, 2-static_src, 3-static_dest, 4-static_base" + echo " where queue_name is a valid LSF queue name (use bqueues for a list)" + echo " where unit:port is the unit/port pair is used to setup a rail" + exit 2 +} + + + + +# process opts and args + +while getopts V:s:n:d:p:q:m: param +do + case $param in + V) + export vfselectmethod=$OPTARG;; + s) + export vfsid=$OPTARG;; + n) + export vfname=$OPTARG;; + d) + export dsprtg=$OPTARG;; + p) + export LSB_DJOB_NUMPROC=$OPTARG;; + q) + export qname=$OPTARG;; + m) + export mrailmap=$OPTARG;; + ?) + Usage + esac +done +shift $(($OPTIND -1)) + +mpirunfile=$1 + +# validate args + +if [ "$mpirunfile" = "" ] +then + echo "Must provide an mpi_run_file" + Usage +fi + +if [ ! -f $mpirunfile ] +then + echo "mpi_run_file \"$mpirunfile\" does not exist" + Usage +fi + +if [ "$dsprtg" != "" ] +then + if [ $dsprtg -lt 1 -o $dsprtg -gt 4 ] + then + echo dispersive routing value must be between 1 and 4 + Usage + fi +fi + +# get opagetvf_func definition +. /usr/bin/opagetvf_env + +case $vfselectmethod in + vf_name) + opagetvf_func "-d '$vfname'" VIADEV_DEFAULT_PKEY VIADEV_DEFAULT_SERVICE_LEVEL MTU + if [ $? -ne 0 ] + then + echo "Failed to get environment variables for VF with Name \"$vfname\"" + Usage + fi + export MPI_CMD_ARGS="VIADEV_DEFAULT_PKEY=$VIADEV_DEFAULT_PKEY VIADEV_DEFAULT_SERVICE_LEVEL=$VIADEV_DEFAULT_SERVICE_LEVEL VIADEV_DEFAULT_MTU=MTU$MTU MV_MTU=$MTU PSM_PKEY=$VIADEV_DEFAULT_PKEY IPATH_SL=$VIADEV_DEFAULT_SERVICE_LEVEL PSM_MTU=$MTU";; + sid) + opagetvf_func "-S '$vfsid'" VIADEV_DEFAULT_PKEY VIADEV_DEFAULT_SERVICE_LEVEL MTU + if [ $? -ne 0 ] + then + echo "Failed to get environment variables for VF with SID \"$vfsid\"" + Usage + fi + export MPI_CMD_ARGS="VIADEV_DEFAULT_PKEY=$VIADEV_DEFAULT_PKEY VIADEV_DEFAULT_SERVICE_LEVEL=$VIADEV_DEFAULT_SERVICE_LEVEL VIADEV_DEFAULT_MTU=MTU$MTU MV_MTU=$MTU PSM_PKEY=$VIADEV_DEFAULT_PKEY IPATH_SL=$VIADEV_DEFAULT_SERVICE_LEVEL PSM_MTU=$MTU";; + sid_qlc) + export MPI_CMD_ARGS="PSM_PATH_REC=opp PSM_IB_SERVICE_ID=$vfsid";; + *) + echo Unknown vfselectmethod $vfselectmethod + Usage;; +esac + +if [ "$dsprtg" != "" ] +then + case $dsprtg in + 1) + export routing=adaptive;; + 2) + export routing=static_src;; + 3) + export routing=static_dest;; + 4) + export routing=static_base;; + esac + export MPI_CMD_ARGS="$MPI_CMD_ARGS PSM_PATH_SELECTION=$routing" +fi + +if [ "$MPICH_PREFIX" = "" ] +then + . /usr/bin/iba_select_mpi + if ! valid_mpich_prefix + then + find_mpi $prefix/mpi/gcc/mvapich-1*qlc + fi + if ! valid_mpich_prefix + then + find_mpi $prefix/mpi/gcc/mvapich-1* + fi +fi + +if [ "$mrailmap" != "" ] +then + . /usr/bin/opagetvf_env + + iba_getpsm_func $mrailmap + if [ $? -ne 0 ] + then + echo "Failed to get environment variable for PSM with value \"$mrailmap\"" + Usage + else + export MPI_CMD_ARGS="$MPI_CMD_ARGS PSM_MULTIRAIL=1 PSM_MULTIRAIL_MAP=$mrailmap" + fi +fi + +# write job script and submit it, then delete + +echo "#! /bin/sh" > .run.mvapich +echo "#BSUB -n $LSB_DJOB_NUMPROC" >> .run.mvapich +echo "#BSUB -o %J.out" >> .run.mvapich +echo "#BSUB -e %J.err" >> .run.mvapich +if [ "$qname" != "" ] +then + echo "#BSUB -q $qname" >> .run.mvapich +fi +echo $MPICH_PREFIX/bin/mpirun_rsh -np $LSB_DJOB_NUMPROC -hostfile \$LSB_DJOB_HOSTFILE $MPI_CMD_ARGS $* >> .run.mvapich + +bsub < .run.mvapich +rm .run.mvapich + +exit 0 diff --git a/Lsf/lsf.submit.mvapich2.job b/Lsf/lsf.submit.mvapich2.job new file mode 100755 index 0000000..eb2b459 --- /dev/null +++ b/Lsf/lsf.submit.mvapich2.job @@ -0,0 +1,206 @@ +#! /bin/bash +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] + + +# initialize + +# BASE PATH TO MPI EXECUTABLES: To use an alternate location, +# either edit this line or set MPICH_PREFIX in your environment. +# see iba_select_mpi for the set of default MPI selections +# default to MPI used for build +MPICH_PREFIX= + +mpirunfile= +vfselectmethod=sid_qlc +vfname= +vfsid= +dsprtg= +qname= +mrailmap= + +MPI_CMD_ARGS= + +LSB_DJOB_NUMPROC=3 + +# Usage - display usage syntax and exit + +Usage() +{ + echo "Usage: submit.mvapich2.job [-p num_proceses] [-V vf_select_method] [-s vf_sid] [-n vf_name] [-d dsp_rtg] [-q queue_name] [-m [,]] mpi_run_file [mpi_run_file args]" + echo " where vf_select_method is one of:" + echo " vf_name: Name of virtual fabric - use -n to define vf name" + echo " sid : ServiceId of virtual fabric - use -s option to define service id" + echo " sid_qlc: ServiceId of virtual fabric - use -s option to define service id, uses dist_sa (default)" + echo " where dsp_rtg is one of: 1-adaptive, 2-static_src, 3-static_dest, 4-static_base" + echo " where queue_name is a valid LSF queue name (use bqueues for a list)" + echo " where unit:port is the unit/port pair is used to setup a rail" + exit 2 +} + + + + +# process opts and args + +while getopts V:s:n:d:p:q:m: param +do + case $param in + V) + export vfselectmethod=$OPTARG;; + s) + export vfsid=$OPTARG;; + n) + export vfname=$OPTARG;; + d) + export dsprtg=$OPTARG;; + p) + export LSB_DJOB_NUMPROC=$OPTARG;; + q) + export qname=$OPTARG;; + m) + export mrailmap=$OPTARG;; + ?) + Usage + esac +done +shift $(($OPTIND -1)) + +mpirunfile=$1 + +# validate args + +if [ "$mpirunfile" = "" ] +then + echo "Must provide an mpi_run_file" + Usage +fi + +if [ ! -f $mpirunfile ] +then + echo "mpi_run_file \"$mpirunfile\" does not exist" + Usage +fi + +if [ "$dsprtg" != "" ] +then + if [ $dsprtg -lt 1 -o $dsprtg -gt 4 ] + then + echo dispersive routing value must be between 1 and 4 + Usage + fi +fi + +# get opagetvf_func definition +. /usr/bin/opagetvf_env + +case $vfselectmethod in + vf_name) + opagetvf_func "-d '$vfname'" MV2_DEFAULT_PKEY MV2_DEFAULT_SERVICE_LEVEL MTU + if [ $? -ne 0 ] + then + echo "Failed to get environment variables for VF with Name \"$vfname\"" + Usage + fi + export MPI_CMD_ARGS="MV2_DEFAULT_PKEY=$MV2_DEFAULT_PKEY MV2_DEFAULT_SERVICE_LEVEL=$MV2_DEFAULT_SERVICE_LEVEL MV2_DEFAULT_MTU=IBV_MTU_$MTU PSM_PKEY=$MV2_DEFAULT_PKEY IPATH_SL=$MV2_DEFAULT_SERVICE_LEVEL PSM_MTU=$MTU";; + sid) + opagetvf_func "-S '$vfsid'" MV2_DEFAULT_PKEY MV2_DEFAULT_SERVICE_LEVEL MTU + if [ $? -ne 0 ] + then + echo "Failed to get environment variables for VF with SID \"$vfsid\"" + Usage + fi + export MPI_CMD_ARGS="MV2_DEFAULT_PKEY=$MV2_DEFAULT_PKEY MV2_DEFAULT_SERVICE_LEVEL=$MV2_DEFAULT_SERVICE_LEVEL MV2_DEFAULT_MTU=IBV_MTU_$MTU PSM_PKEY=$MV2_DEFAULT_PKEY IPATH_SL=$MV2_DEFAULT_SERVICE_LEVEL PSM_MTU=$MTU";; + sid_qlc) + export MPI_CMD_ARGS="PSM_PATH_REC=opp PSM_IB_SERVICE_ID=$vfsid";; + *) + echo Unknown vfselectmethod $vfselectmethod + Usage;; +esac + +if [ "$dsprtg" != "" ] +then + case $dsprtg in + 1) + export routing=adaptive;; + 2) + export routing=static_src;; + 3) + export routing=static_dest;; + 4) + export routing=static_base;; + esac + export MPI_CMD_ARGS="$MPI_CMD_ARGS PSM_PATH_SELECTION=$routing" +fi + +if [ "$MPICH_PREFIX" = "" ] +then + . /usr/bin/iba_select_mpi + if ! valid_mpich_prefix + then + find_mpi $prefix/mpi/gcc/mvapich2*qlc + fi + if ! valid_mpich_prefix + then + find_mpi $prefix/mpi/gcc/mvapich2* + fi +fi + +if [ "$mrailmap" != "" ] +then + . /usr/bin/opagetvf_env + + iba_getpsm_func $mrailmap + if [ $? -ne 0 ] + then + echo "Failed to get environment variable for PSM with value \"$mrailmap\"" + Usage + else + export MPI_CMD_ARGS="$MPI_CMD_ARGS PSM_MULTIRAIL=1 PSM_MULTIRAIL_MAP=$mrailmap" + fi +fi + +# submit the job from stdin + +echo "#! /bin/sh" > .run.mvapich2 +echo "#BSUB -n $LSB_DJOB_NUMPROC" >> .run.mvapich2 +echo "#BSUB -o %J.out" >> .run.mvapich2 +echo "#BSUB -e %J.err" >> .run.mvapich2 +if [ "$qname" != "" ] +then +echo "#BSUB -q $qname" >> .run.mvapich2 +fi +echo $MPICH_PREFIX/bin/mpirun_rsh -np $LSB_DJOB_NUMPROC -hostfile \$LSB_DJOB_HOSTFILE $MPI_CMD_ARGS $* >> .run.mvapich2 + +bsub < .run.mvapich2 +rm .run.mvapich2 + +exit 0 diff --git a/Lsf/lsf.submit.openmpi-q.job b/Lsf/lsf.submit.openmpi-q.job new file mode 100755 index 0000000..2dc3c49 --- /dev/null +++ b/Lsf/lsf.submit.openmpi-q.job @@ -0,0 +1,215 @@ +#! /bin/bash +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] + + +# initialize + +# BASE PATH TO MPI EXECUTABLES: To use an alternate location, +# either edit this line or set MPICH_PREFIX in your environment. +# see iba_select_mpi for the set of default MPI selections +# default to MPI used for build +MPICH_PREFIX= + +mpirunfile= +vfselectmethod=sid_qlc +vfname= +vfsid= +dsprtg= +qname= +mrailmap= + +MPI_CMD_ARGS= + +LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$MPICH_PREFIX/lib64/ +LSB_DJOB_NUMPROC=3 + +# Usage - display usage syntax and exit + +Usage() +{ + echo "Usage: submit.openmpi.job [-p num_proceses] [-V vf_select_method] [-s vf_sid] [-n vf_name] [-d dsp_rtg] [-q queue_name] [-m [,]] mpi_run_file" + echo " where vf_select_method is one of:" + echo " vf_name: Name of virtual fabric - use -n to define vf name" + echo " sid : ServiceId of virtual fabric - use -s option to define service id" + echo " sid_qlc: ServiceId of virtual fabric - use -s option to define service id, uses dist_sa (default)" + echo " where dsp_rtg is one of: 1-adaptive, 2-static_src, 3-static_dest, 4-static_base" + echo " where queue_name is a valid LSF queue name (use bqueues for a list)" + echo " where unit:port is the unit/port pair is used to setup a rail" + exit 2 +} + + + + +# process opts and args + +while getopts V:s:n:d:p:q:m: param +do + case $param in + V) + export vfselectmethod=$OPTARG;; + s) + export vfsid=$OPTARG;; + n) + export vfname=$OPTARG;; + d) + export dsprtg=$OPTARG;; + p) + export LSB_DJOB_NUMPROC=$OPTARG;; + q) + export qname=$OPTARG;; + m) + export mrailmap=$OPTARG;; + ?) + Usage + esac +done +shift $(($OPTIND -1)) + +mpirunfile=$1 + +# validate args + +if [ "$mpirunfile" = "" ] +then + echo "Must provide an mpi_run_file" + Usage +fi + +if [ ! -f $mpirunfile ] +then + echo "mpi_run_file \"$mpirunfile\" does not exist" + Usage +fi + +if [ "$dsprtg" != "" ] +then + if [ $dsprtg -lt 1 -o $dsprtg -gt 4 ] + then + echo dispersive routing value must be between 1 and 4 + Usage + fi +fi + +# get opagetvf_func definition +. /usr/bin/opagetvf_env + +case $vfselectmethod in + vf_name) + opagetvf2_func "-d '$vfname'" OMPI_MCA_btl_openib_pkey OMPI_MCA_btl_openib_ib_service_level OMPI_MCA_btl_openib_mtu + if [ $? -ne 0 ] + then + echo "Failed to get environment variables for VF with Name \"$vfname\"" + Usage + fi + export OMPI_MCA_mtl_psm_ib_pkey=$OMPI_MCA_btl_openib_pkey + export OMPI_MCA_mtl_psm_ib_service_level=$OMPI_MCA_btl_openib_ib_service_level + export PSM_MTU=$OMPI_MCA_btl_openib_mtu;; + sid) + opagetvf2_func "-S '$vfsid'" OMPI_MCA_btl_openib_pkey OMPI_MCA_btl_openib_ib_service_level OMPI_MCA_btl_openib_mtu + if [ $? -ne 0 ] + then + echo "Failed to get environment variables for VF with SID \"$vfsid\"" + Usage + fi + export OMPI_MCA_mtl_psm_ib_pkey=$OMPI_MCA_btl_openib_pkey + export OMPI_MCA_mtl_psm_ib_service_level=$OMPI_MCA_btl_openib_ib_service_level + export PSM_MTU=$OMPI_MCA_btl_openib_mtu;; + sid_qlc) + export OMPI_MCA_mtl_psm_path_query=opp + export OMPI_MCA_mtl_psm_ib_service_id=$vfsid;; + *) + echo Unknown vfselectmethod $vfselectmethod + Usage;; +esac + +if [ "$dsprtg" != "" ] +then + case $dsprtg in + 1) + export routing=adaptive;; + 2) + export routing=static_src;; + 3) + export routing=static_dest;; + 4) + export routing=static_base;; + esac + export MPI_CMD_ARGS="PSM_PATH_SELECTION=$routing" +fi + +if [ "$MPICH_PREFIX" = "" ] +then + . /usr/bin/iba_select_mpi + if ! valid_mpich_prefix + then + find_mpi $prefix/mpi/gcc/openmpi*qlc + fi +fi + +if [ "$mrailmap" != "" ] +then + . /usr/bin/opagetvf_env + + iba_getpsm_func $mrailmap + if [ $? -ne 0 ] + then + echo "Failed to get environment variable for PSM with value \"$mrailmap\"" + Usage + else + export MPI_CMD_ARGS="$MPI_CMD_ARGS PSM_MULTIRAIL=1 PSM_MULTIRAIL_MAP=$mrailmap" + fi +fi + +temp= +for arg in $MPI_CMD_ARGS +do + temp="$temp -x '$arg'" +done +MPI_CMD_ARGS="$temp" + +# submit the job + +echo "#! /bin/sh" > .run.openmpi-q +echo "#BSUB -n $LSB_DJOB_NUMPROC" >> .run.openmpi-q +echo "#BSUB -o %J.out" >> .run.openmpi-q +echo "#BSUB -e %J.err" >> .run.openmpi-q +if [ "$qname" != "" ] +then + echo "#BSUB -q $qname" >> .run.openmpi-q +fi +echo $MPICH_PREFIX/bin/mpirun -np $LSB_DJOB_NUMPROC -hostfile \$LSB_DJOB_HOSTFILE $MPI_CMD_ARGS $* >> .run.openmpi-q + +bsub < .run.openmpi-q +rm .run.openmpi-q + +exit 0 diff --git a/Lsf/lsf.submit.openmpi.job b/Lsf/lsf.submit.openmpi.job new file mode 100755 index 0000000..ec4fcdb --- /dev/null +++ b/Lsf/lsf.submit.openmpi.job @@ -0,0 +1,188 @@ +#! /bin/bash +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] + + +# initialize + +# BASE PATH TO MPI EXECUTABLES: To use an alternate location, +# either edit this line or set MPICH_PREFIX in your environment. +# see iba_select_mpi for the set of default MPI selections +# default to MPI used for build +MPICH_PREFIX= + +mpirunfile= +vfselectmethod=sid +vfname= +vfsid= +qname= + +MPI_CMD_ARGS= + +LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$MPICH_PREFIX/lib64/ +LSB_DJOB_NUMPROC=3 + +# Usage - display usage syntax and exit + +Usage() +{ + echo "Usage: submit.openmpi.job [-p num_processes] [-V vf_select_method] [-s vf_sid] [-n vf_name] [-q queue_name] mpi_run_file [mpi_run_file args]" + echo " where vf_select_method is one of:" + echo " vf_name: Name of virtual fabric - use -n to define vf name" + echo " sid : ServiceId of virtual fabric - use -s option to define service id" + echo " where queue_name is a valid LSF queue name (use bqueues for a list)" + exit 2 +} + + + + +# process opts and args + +while getopts V:s:n:p:q: param +do + case $param in + V) + export vfselectmethod=$OPTARG;; + s) + export vfsid=$OPTARG;; + n) + export vfname=$OPTARG;; + p) + export LSB_DJOB_NUMPROC=$OPTARG;; + q) + export qname=$OPTARG;; + ?) + Usage + esac +done +shift $(($OPTIND -1)) + +mpirunfile=$1 + +# validate args + +if [ "$mpirunfile" = "" ] +then + echo "Must provide an mpi_run_file" + Usage +fi + +if [ ! -f $mpirunfile ] +then + echo "mpi_run_file \"$mpirunfile\" does not exist" + Usage +fi + +# get opagetvf_func definition +. /usr/bin/opagetvf_env + +case $vfselectmethod in + vf_name) + opagetvf2_func "-d '$vfname'" OMPI_MCA_btl_openib_pkey OMPI_MCA_btl_openib_ib_service_level OMPI_MCA_btl_openib_mtu + if [ $? -ne 0 ] + then + echo "Failed to get environment variables for VF with Name \"$vfname\"" + Usage + fi + export OMPI_MCA_mtl_psm_ib_pkey=$OMPI_MCA_btl_openib_pkey + export OMPI_MCA_mtl_psm_ib_service_level=$OMPI_MCA_btl_openib_ib_service_level + export PSM_MTU=$OMPI_MCA_btl_openib_mtu;; + sid) + opagetvf2_func "-S '$vfsid'" OMPI_MCA_btl_openib_pkey OMPI_MCA_btl_openib_ib_service_level OMPI_MCA_btl_openib_mtu + if [ $? -ne 0 ] + then + echo "Failed to get environment variables for VF with SID \"$vfsid\"" + Usage + fi + export OMPI_MCA_mtl_psm_ib_pkey=$OMPI_MCA_btl_openib_pkey + export OMPI_MCA_mtl_psm_ib_service_level=$OMPI_MCA_btl_openib_ib_service_level + export PSM_MTU=$OMPI_MCA_btl_openib_mtu;; + *) + echo Unknown vfselectmethod $vfselectmethod + Usage;; +esac + +if [ "$MPICH_PREFIX" = "" ] +then + . /usr/bin/iba_select_mpi + if ! valid_mpich_prefix + then + find_mpi $prefix/mpi/gcc/openmpi* + fi +fi + +lsid -V 2>&1 | tee lsid.out > /dev/null +version=`cat lsid.out | grep LSF | awk -F" " '{print $4}' | cut -d"." -f 1` +if [ "$version" = "9" ] || [ "$version" = "8" ] +then + + temp= + for arg in $MPI_CMD_ARGS + do + temp="$temp -x '$arg'" + done + MPI_CMD_ARGS="$temp" + + # submit the job + echo "#! /bin/sh" > .run.openmpi + echo "#BSUB -n $LSB_DJOB_NUMPROC" >> .run.openmpi + echo "#BSUB -o %J.out" >> .run.openmpi + echo "#BSUB -e %J.err" >> .run.openmpi + if [ "$qname" != "" ] + then + echo "#BSUB -q $qname" >> .run.openmpi + fi + echo $MPICH_PREFIX/bin/mpirun -np $LSB_DJOB_NUMPROC -hostfile \$LSB_DJOB_HOSTFILE $MPI_CMD_ARGS $* >> .run.openmpi + + bsub < .run.openmpi + rm .run.openmpi +else + # submit the job from stdin - user mpirun.lsf + + if [ "$qname" != "" ] + then + qparam="#BSUB -q $qname" + else + qparam="" + fi + + bsub -a openmpi << EOF + #BSUB -n $LSB_DJOB_NUMPROC + #BSUB -o %J.out + #BSUB -e %J.err + $qparam + mpirun.lsf $MPI_CMD_ARGS $* +EOF +fi + +rm lsid.out +exit 0 diff --git a/Lsf/openmpi_wrapper b/Lsf/openmpi_wrapper new file mode 100644 index 0000000..89c17d6 --- /dev/null +++ b/Lsf/openmpi_wrapper @@ -0,0 +1,297 @@ +#!/bin/sh +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] + + +#------------------------------------------------------------------ +# Initialization: +# - specify the absolute paths mpirun if is is not in $PATH +# - EXIT_VALUE should not be set to 0 +#------------------------------------------------------------------ +cleanup_openmpi() +{ + trap "" 1 2 3 15 + + for afile in $APP_FILE $HOST_FILE + do + if [ -f "$afile" ]; then + rm -f $afile >/dev/null 1>&2 + fi + done +} + +sig_handler_opempi() +{ + trap "" 1 2 3 15 + echo "Signal received. Exiting ..." | tee -a $LOGFILE + cleanup_openmpi + exit 1 +} + +# ----------------------------------------------------- +# Source the LSF environment. Optional. +# ----------------------------------------------------- +. ${LSF_ENVDIR}/lsf.conf + +# ----------------------------------------------------- +# Set up the variable LSF_TS representing the TaskStarter. +# ----------------------------------------------------- +LSF_TS="$LSF_BINDIR/TaskStarter" +USR_APP_FILE="" + +# This script assumes mpirun of OPENMPI can be found in PATH +# environment variable. +MPIHOME=/opt/openmpi/gnu +#MPIRUN_CMD="$MPIHOME/bin/mpirun" +MPIRUN_CMD="$MPICH_PREFIX/bin/mpirun" + +LOGFILE="/dev/null" +EXIT_VALUE="66" +TASK_GEOM_OK="0" +JOB_SHAREDIR="$HOME" +OPENMPI_OPTS=" " +if [ "$JOB_SHAREDIR" = "" ]; then + JOB_SHAREDIR=`pwd` +fi + +# +# If task geometry is not used +# Reverse order of the host list to gain better performance +# +if [ -n "$LSB_PJL_TASK_GEOMETRY" ]; then + REVERSE_ORDER="n" +else + REVERSE_ORDER="y" +fi + +#------------------------------------------------------------------ +# Create files with a unique name based on the LSF job ID: +# - log file +# - machine file +# - temp file +#------------------------------------------------------------------ +if [ "$LSB_BATCH_JID" != "" ]; then + UNIQUE_ID="$LSB_BATCH_JID" +else + UNIQUE_ID=`hostname`_"$$" +fi + +APP_FILE="$JOB_SHAREDIR/.openmpi_appfile_${UNIQUE_ID}" +HOST_FILE="$JOB_SHAREDIR/.host_file_${UNIQUE_ID}" + +trap "sig_handler_opempi" 1 2 3 15 + +# +# Reverse LSB_MCPU_HOSTS +# +if [ "$REVERSE_ORDER" = "y" ]; then + HOST="" + NEW_LSB_MCPU_HOSTS="" + for i in $LSB_MCPU_HOSTS + do + if [ -z "$HOST" ] + then + HOST="$i" + else + NEW_LSB_MCPU_HOSTS="$HOST $i $NEW_LSB_MCPU_HOSTS" + HOST="" + fi + done + LSB_MCPU_HOSTS=$NEW_LSB_MCPU_HOSTS +fi + +# ----------------------------------------------------- +# Process the command line: +# - extract [mpiopts] from the command line +# - extract jobname [jobopts] from the command line +# ----------------------------------------------------- +while [ $# -gt 0 ] +do + case "$1" in + -aborted|--aborted|-path|--path|--tmpdir|--universe|-x|-wdir|--wdir|--prefix|-debugger|--debugger) + OPENMPI_OPTS="$OPENMPI_OPTS $1 $2 " + shift + shift + ;; + -app|--app) + # --app Provide an appfile; ignore all other command line options + echo "User defined -app option found" >> $LOGFILE + USR_APP_FILE="$2" + shift + shift + ;; + -bynode|--bynode|-byslot|--byslot) + if [ -z "$LSB_PJL_TASK_GEOMETRY" ]; then + OPENMPI_OPTS="$OPENMPI_OPTS $1 " + else + echo "LSB_PJL_TASK_GEOMETRY is defined, mpirun option $1 will be ignored" >> $LOGFILE + fi + shift + ;; + -c|-np|--np|-n|--n|-tv|--tv) + echo "mpirun option $1 $2 will be ignored" >> $LOGFILE + # Number of processes to run + shift + shift + ;; + -d|-debug|--debug|--debug-daemons|--debug-daemons-file|--no-daemonize|--debug-devel|-q|--quiet|-V|--version|-nooversubscribe|--nooversubscribe ) + OPENMPI_OPTS="$OPENMPI_OPTS $1 " + shift + ;; + -gmca|--gmca|-mca|--mca) + # + OPENMPI_OPTS="$OPENMPI_OPTS $1 $2 $3 " + shift + shift + shift + ;; + -h|--help|-nw|--nw|-v|--verbose) + OPENMPI_OPTS="$OPENMPI_OPTS $1 " + shift + ;; + -H|-host|--host|-hostfile|--hostfile|-machinefile|--machinefile) + echo "mpirun option $1 $2 will be ignored" >> $LOGFILE + # List of hosts to invoke processes on + shift + shift + ;; + -nolocal|--nolocal) + echo "mpirun option $1 will be ignored" >> $LOGFILE + shift + ;; + *) + break + ;; + esac +done + +JOB_CMDLN="$*" + +# ----------------------------------------------------- +# Set up the CMD_LINE variable representing the integrated section of the command line: +# - LSF_TS, script variable representing the TaskStarter binary. +# TaskStarter must start each and every job task process. +# - LSF_TS_OPTIONS, LSF environment variable containing all necessary information +# for TaskStarter to callback to LSF's Parallel Application Manager. +# - JOB_CMDLN, script variable containing the job and job options +#-------------------------------------------------------------------------------- +if [ -z "$LSF_TS_OPTIONS" ] +then + echo CMD_LINE="$JOB_CMDLN" >> $LOGFILE + CMD_LINE="$JOB_CMDLN " +else + echo CMD_LINE="$LSF_TS $LSF_TS_OPTIONS $JOB_CMDLN" >> $LOGFILE + CMD_LINE="$LSF_TS $LSF_TS_OPTIONS $JOB_CMDLN " +fi + +#------------------------------------------------------------------ +# Construct LSF Job -app file +#------------------------------------------------------------------ +if [ "$USR_APP_FILE" != "" ]; then + # User defined --app + echo "User defined -app $USR_APP_FILE is not allowed. Exiting..." | tee -a $LOGFILE + cleanup_openmpi + exit 1 +elif [ "$LSB_PJL_TASK_GEOMETRY" != "" ]; then + #------------------------------------------------------------------ + # handle $LSB_PJL_TASK_GEOMETRY + # It will shuffle the order the appfile + # based on the order of task geometry + #------------------------------------------------------------------ + . $LSF_BINDIR/pjllib.sh + TOTAL_CPUS=`echo $LSB_MCPU_HOSTS | /bin/awk ' +BEGIN {counter=0} +{ + size = split($0, a, " "); + for (i = 1; i <= size; i += 2) { + counter = counter + a[i + 1]; + for (j = 0; j < a[i + 1]; ++j) { + print a[i] > hfile; + } + } +} +END { print counter}' hfile=$HOST_FILE` + + if [ -f "${LSF_BINDIR}/pjllib.sh" ]; then + # get a host list each host per line that satisfies the task geometry + # then construct the appfile based on new host list + . ${LSF_BINDIR}/pjllib.sh + reorder_file_based_on_task_geom "$HOST_FILE" "sort" + EXIT_VALUE=$? + if [ "$EXIT_VALUE" != "0" ]; then + echo "Error in reorder_file_based_on_task_geom \"$HOST_FILE\" \"sort\", Exit ..." 1>&2 + cleanup_openmpi + exit ${EXIT_VALUE} + + fi + _new_host_list=`cat $HOST_FILE` + echo $_new_host_list | /bin/awk ' { + size = split($0, a, " "); + for (i = 1; i <= size; i++) { + newln = sprintf("-host %s -n 1 %s %s",a[i], (openmpi_opt)?openmpi_opt:" ", (cmdln)?cmdln:" "); + print newln > appfile + } + }' appfile="$APP_FILE" cmdln="$CMD_LINE" openmpi_opt="$OPENMPI_OPTS" + else + echo "Cannot find pjllib.sh in $LSF_BINDIR. Exiting..." 1>&2 + cleanup_openmpi + exit 1 + + fi +else + echo $LSB_MCPU_HOSTS | /bin/awk ' { + size = split($0, a, " "); + for (i = 1; i < size; i++) { + newln = ""; + newln = sprintf("-host %s -n %s %s %s",a[i], a[++i], (openmpi_opt)?openmpi_opt:" ", (cmdln)?cmdln:" "); + print newln > appfile + } + }' appfile="$APP_FILE" cmdln="$CMD_LINE" openmpi_opt="$OPENMPI_OPTS" +fi + +echo "appfile $APP_FILE reads" >> $LOGFILE +cat $APP_FILE >> $LOGFILE +echo "command used to launch the job : " >> $LOGFILE +echo " $MPIRUN_CMD -app $APP_FILE " >> $LOGFILE +$MPIRUN_CMD --app $APP_FILE +EXIT_VALUE=$? + +#------------------------------------------------------------------ +# Clean up: +# - remove temporary files +# - exit with the exit value of the mpirun command +#------------------------------------------------------------------ +cleanup_openmpi +exit $EXIT_VALUE + +#------------------------------------------------------------------------- +# End the script. +#------------------------------------------------------------------------- diff --git a/Lsf/ssh.script b/Lsf/ssh.script new file mode 100755 index 0000000..ccfa0f4 --- /dev/null +++ b/Lsf/ssh.script @@ -0,0 +1,45 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +#[ICS VERSION STRING: unknown] + +# +# wrapper /usr/bin/ssh +# blaunch is used when applicable +# +if [ -z "$LSF_BINDIR" \ +-o -z "$LSB_JOBID" \ +-o -z "$LSB_JOBINDEX" \ +-o -z "$LSB_JOBRES_CALLBACK" \ +-o -z "$LSB_DJOB_HOSTFILE" ]; then +SSH="/usr/bin/ssh.bin" +else +SSH=$LSF_BINDIR/blaunch +fi +$SSH "$@" diff --git a/MakeTemplates/Makefile b/MakeTemplates/Makefile new file mode 100644 index 0000000..cb05f51 --- /dev/null +++ b/MakeTemplates/Makefile @@ -0,0 +1,47 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** +# Makefile for Makerules, just to create a dsp file + +# Include Make Control Settings +include $(TL_DIR)/$(PROJ_FILE_DIR)/Makesettings.project + +DS_SUBPROJECTS = +DSP_SOURCES= Makefile \ + Makefile.basic \ + Makefile.middle \ + Makefile.modHeading \ + Makefile.projHeading \ + Makerules.module \ + Makerules.project \ + buildMakefile +DIRS = +INCLUDE_TARGETS = + +include $(TL_DIR)/$(PROJ_FILE_DIR)/Makerules.project + diff --git a/MakeTemplates/Makefile.basic b/MakeTemplates/Makefile.basic new file mode 100644 index 0000000..d972a70 --- /dev/null +++ b/MakeTemplates/Makefile.basic @@ -0,0 +1,148 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# Include Make Control Settings +include $(TL_DIR)/$(PROJ_FILE_DIR)/Makesettings.project + +#=============================================================================# +# Definitions: +#-----------------------------------------------------------------------------# + +# Name of SubProjects +DS_SUBPROJECTS = FILL IN SUB PROJECTS as directories relative to project dir +# name of executable or downloadable image +EXECUTABLE = $(BUILDDIR)NAME$(EXE_SUFFIX) FILL IN NAME - 1 file only +# list of sub directories to build +DIRS = FILL IN SUBDIRECTORIES +# C files (.c) +CFILES = FILL IN C FILES +# C++ files (.cpp) +CCFILES = FILL IN C++ FILES +# lex files (.lex) +LFILES = FILL IN lex FILES +# archive library files (basename, $ARFILES will add MOD_LIB_DIR/prefix and suffix) +LIBFILES = FILL IN libraries built to $(MOD_LIB_DIR) +# Windows Resource Files (.rc) +RSCFILES = +# Windows IDL File (.idl) +IDLFILE = +# Windows Linker Module Definitions (.def) file for dll's +DEFFILE = +# targets to build during INCLUDES phase (add public includes here) +INCLUDE_TARGETS = FILL IN HEADER (.hpp & .h) FILES TO EXPORT +# Non-compiled files +MISC_FILES = +# all source files +SOURCES = $(CFILES) $(CCFILES) $(LFILES) $(RSCFILES) $(IDLFILE) +# Source files to include in DSP File +DSP_SOURCES = $(INCLUDE_TARGETS) $(SOURCES) $(MISC_FILES) \ + $(RSCFILES) $(DEFFILE) $(MAKEFILE) +# all object files +OBJECTS = $(CFILES:.c=$(OBJ_SUFFIX)) $(CCFILES:.cpp=$(OBJ_SUFFIX)) \ + $(LFILES:.lex=$(OBJ_SUFFIX)) +RSCOBJECTS = $(RSCFILES:.rc=$(RES_SUFFIX)) +# targets to build during LIBS phase +LIB_TARGETS_IMPLIB = +LIB_TARGETS_ARLIB = +LIB_TARGETS_EXP = $(LIB_TARGETS_IMPLIB:$(ARLIB_SUFFIX)=$(EXP_SUFFIX)) +LIB_TARGETS_MISC = +# targets to build during CMDS phase +SHLIB_VERSION = +CMD_TARGETS_SHLIB = +CMD_TARGETS_EXE = $(EXECUTABLE) +CMD_TARGETS_MISC = +CMD_TARGETS_DRIVER = +CMD_TARGETS_KEXT = +# files to remove during clean phase +CLEAN_TARGETS_MISC= +CLEAN_TARGETS = $(OBJECTS) $(RSCOBJECTS) $(IDL_TARGETS) $(CLEAN_TARGETS_MISC) +# other files to remove during clobber phase +CLOBBER_TARGETS_MISC= +# sub-directory to install to within bin +BIN_SUBDIR = +# sub-directory to install to within include +INCLUDE_SUBDIR = + +# Additional Settings +#CLOCALDEBUG = User defined C debugging compilation flags [Empty] +#CCLOCALDEBUG = User defined C++ debugging compilation flags [Empty] +#CLOCAL = User defined C flags for compiling [Empty] +#CCLOCAL = User defined C++ flags for compiling [Empty] +#BSCLOCAL = User flags for Browse File Builder [Empty] +#DEPENDLOCAL = user defined makedepend flags [Empty] +#LINTLOCAL = User defined lint flags [Empty] +#LOCAL_INCLUDE_DIRS = User include directories to search for C/C++ headers [Empty] +#LDLOCAL = User defined C flags for linking [Empty] +#IMPLIBLOCAL = User flags for Object Lirary Manager [Empty] +#MIDLLOCAL = User flags for IDL compiler [Empty] +#RSCLOCAL = User flags for resource compiler [Empty] +#LOCALDEPLIBS = User libraries to include in dependencies [Empty] +#LOCALLIBS = User libraries to use when linking [Empty] +# (in addition to LOCALDEPLIBS) +#LOCAL_LIB_DIRS = User library directories for libpaths [Empty] + +LOCALDEPLIBS= + +# Include Make Rules definitions and rules +include $(TL_DIR)/$(PROJ_FILE_DIR)/Makerules.project + +#=============================================================================# +# Overrides: +#-----------------------------------------------------------------------------# +#CCOPT = # C++ optimization flags, default lets build config decide +#COPT = # C optimization flags, default lets build config decide +#SUBSYSTEM = Subsystem to build for (none, console or windows) [none] +# (Windows Only) +#USEMFC = How Windows MFC should be used (none, static, shared, no_mfc) [none] +# (Windows Only) +#=============================================================================# + +#=============================================================================# +# Rules: +#-----------------------------------------------------------------------------# +# process Sub-directories +include $(TL_DIR)/Makerules/Maketargets.toplevel + +# build cmds and libs +include $(TL_DIR)/Makerules/Maketargets.build + +# install for includes, libs and cmds phases +include $(TL_DIR)/Makerules/Maketargets.install + +# install for stage phase +include $(TL_DIR)/Makerules/Maketargets.stage + +# Unit test execution +#include $(TL_DIR)/Makerules/Maketargets.runtest + +#=============================================================================# + +#=============================================================================# +# DO NOT DELETE THIS LINE -- make depend depends on it. +#=============================================================================# diff --git a/MakeTemplates/Makefile.idl b/MakeTemplates/Makefile.idl new file mode 100644 index 0000000..f379b3b --- /dev/null +++ b/MakeTemplates/Makefile.idl @@ -0,0 +1,167 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** +# Sample makefile for building a shared library for a proxy, from an idl file +# for windows com objects + +# Include Make Control Settings +include $(TL_DIR)/$(PROJ_FILE_DIR)/Makesettings.project + +#=============================================================================# +# Definitions: +#-----------------------------------------------------------------------------# + +# Name of SubProjects +DS_SUBPROJECTS = FILL IN SUB PROJECTS as directories relative to project dir +# name of executable or downloadable image +EXECUTABLE = +# list of sub directories to build +DIRS = +# C files (.c) +CFILES = $(IDLFILE:.idl=_i.c) +# .c files - for proxy/stub .dll +PS_CFILES = $(IDLFILE:.idl=_p.c) \ + $(IDLFILE:.idl=_dlldata.c) +# C++ files (.cpp) +CCFILES = +# lex files (.lex) +LFILES = +# Windows Resource Files (.rc) +RSCFILES = $(IDLFILE:.idl=_ps.rc) +# Windows IDL File (.idl) +IDLFILE = MYFILE.idl +# Windows Linker Module Definitions (.def) file for dll's +DEFFILE = $(IDLFILE:.idl=_ps.def) +# targets to build during INCLUDES phase (add public includes here) +INCLUDE_TARGETS = +# Non-compiled files +MISC_FILES = +# all source files +SOURCES = $(CFILES) $(CCFILES) $(LFILES) $(RSCFILES) $(IDLFILE) +# Source files to include in DSP File +DSP_SOURCES = $(INCLUDE_TARGETS) $(SOURCES) $(MISC_FILES) \ + $(RSCFILES) $(DEFFILE) $(MAKEFILE) +# all object files +OBJECTS = $(CFILES:.c=$(OBJ_SUFFIX)) $(CCFILES:.cpp=$(OBJ_SUFFIX)) \ + $(LFILES:.lex=$(OBJ_SUFFIX)) +# all object files - for proxy/stub .dll +PS_OBJECTS = $(PS_CFILES:.c=$(OBJ_SUFFIX)) $(PS_CCFILES:.cpp=$(OBJ_SUFFIX)) +RSCOBJECTS = $(RSCFILES:.rc=$(RES_SUFFIX)) +# targets to build during LIBS phase +LIB_TARGETS_IMPLIB = +LIB_TARGETS_ARLIB = +LIB_TARGETS_ARLIB = $(DS_PROJECT)$(ARLIB_SUFFIX) +LIB_TARGETS_EXP = $(LIB_TARGETS_IMPLIB:$(ARLIB_SUFFIX)=$(EXP_SUFFIX)) +LIB_TARGETS_MISC = +# targets to build during CMDS phase +CMD_TARGETS_PSSHLIB = $(IDLFILE:.idl=_ps$(SHLIB_SUFFIX)) +CMD_TARGETS_SHLIB = +CMD_TARGETS_EXE = $(EXECUTABLE) +CMD_TARGETS_MISC = +CMD_TARGETS_DRIVER = +CMD_TARGETS_KEXT = +# files to remove during clean phase +CLEAN_TARGETS_MISC= +CLEAN_TARGETS = $(OBJECTS) $(RSCOBJECTS) $(IDL_TARGETS) $(CLEAN_TARGETS_MISC) $(PS_OBJECTS) +# other files to remove during clobber phase +CLOBBER_TARGETS_MISC= $(CMD_TARGETS_PSSHLIB) +# sub-directory to install to within bin +BIN_SUBDIR = +# sub-directory to install to within include +INCLUDE_SUBDIR = + +# Include Make Rules definitions and rules +include $(TL_DIR)/$(PROJ_FILE_DIR)/Makerules.project + +#=============================================================================# +# Overrides: +#-----------------------------------------------------------------------------# +#CLOCALDEBUG = User defined C debugging compilation flags [Empty] +#CCLOCALDEBUG = User defined C++ debugging compilation flags [Empty] +#CLOCAL = User defined C flags for compiling [Empty] +#CCLOCAL = User defined C++ flags for compiling [Empty] +#BSCLOCAL = User flags for Browse File Builder [Empty] +#CCOPT = # C++ optimization flags, default lets build config decide +#COPT = # C optimization flags, default lets build config decide +#DEPENDLOCAL = user defined makedepend flags [Empty] +#LINTLOCAL = User defined lint flags [Empty] +#LOCAL_INCLUDE_DIRS = User include directories to search for C/C++ headers [Empty] +#LDLOCAL = User defined C flags for linking [Empty] +#IMPLIBLOCAL = User flags for Object Lirary Manager [Empty] +#MIDLLOCAL = User flags for IDL compiler [Empty] +#RSCLOCAL = User flags for resource compiler [Empty] +#LOCALDEPLIBS = User libraries to include in dependencies [Empty] +#LOCALLIBS = User libraries to use when linking [Empty] +# (in addition to LOCALDEPLIBS) +#LOCAL_LIB_DIRS = User library directories for libpaths [Empty] +#SUBSYSTEM = Subsystem to build for (none, console or windows) [none] +# (Windows Only) +#USEMFC = How Windows MFC should be used (none, static, shared, no_mfc) [none] +# (Windows Only) + +LOCALDEPLIBS = +CLOCAL = /D "_USRDLL" /D "REGISTER_PROXY_DLL" /D "_WIN32_WINNT=0x400" + +CCLOCAL = $(CLOCAL) + +LOCALLIBS = MYFILE rpcndr rpcns4 rpcrt4 oleaut32 +#=============================================================================# + +#=============================================================================# +# Rules: +#-----------------------------------------------------------------------------# +# process Sub-directories +include $(TL_DIR)/Makerules/Maketargets.toplevel + +# build cmds and libs +include $(TL_DIR)/Makerules/Maketargets.build + +LIBS:: $(CMD_TARGETS_PSSHLIB) +$(CMD_TARGETS_PSSHLIB): $(PS_OBJECTS) $(EXP_TARGET) $(RSCOBJECTS) $(DEPLIBS_TARGETS) + @echo Linking dynamic library... + $(VS)$(MKSHLIB) $(LDFLAGS)$@ $(PS_OBJECTS) $(EXP_TARGET) $(RSCOBJECT) $(LDLIBS) + +# install for includes, libs and cmds phases +include $(TL_DIR)/Makerules/Maketargets.install +CMDS:: + $(VS)$(INSTALL) -d $(PROJ_BIN_DIR)/$(BIN_SUBDIR) $(CMD_TARGETS_PSSHLIB) + + +# install for stage phase +include $(TL_DIR)/Makerules/Maketargets.stage +STAGE:: + $(VS)$(INSTALL) -d $(PROJ_STAGE_BIN_DIR)/$(BIN_SUBDIR) $(CMD_TARGETS_PSSHLIB) + +# Unit test execution +#include $(TL_DIR)/Makerules/Maketargets.runtest + +#=============================================================================# + +#=============================================================================# +# DO NOT DELETE THIS LINE -- make depend depends on it. +#=============================================================================# diff --git a/MakeTemplates/Makefile.middle b/MakeTemplates/Makefile.middle new file mode 100644 index 0000000..5028ef7 --- /dev/null +++ b/MakeTemplates/Makefile.middle @@ -0,0 +1,46 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# Include Make Control Settings +include $(TL_DIR)/$(PROJ_FILE_DIR)/Makesettings.project + +DS_SUBPROJECTS = FILL IN SUBPROJECTS - do not include Makerules +DSP_SOURCES = Makefile + +DIRS = FILL IN SUBDIRECTORIES - do not include Makerules + +include $(TL_DIR)/$(PROJ_FILE_DIR)/Makerules.project + +include $(TL_DIR)/Makerules/Maketargets.toplevel + +# install for includes, libs and cmds phases +include $(TL_DIR)/Makerules/Maketargets.install + +# install for stage phase +include $(TL_DIR)/Makerules/Maketargets.stage diff --git a/MakeTemplates/Makefile.modHeading b/MakeTemplates/Makefile.modHeading new file mode 100644 index 0000000..fc166c6 --- /dev/null +++ b/MakeTemplates/Makefile.modHeading @@ -0,0 +1,30 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** +# Makefile for Module + diff --git a/MakeTemplates/Makefile.projHeading b/MakeTemplates/Makefile.projHeading new file mode 100644 index 0000000..88dbdde --- /dev/null +++ b/MakeTemplates/Makefile.projHeading @@ -0,0 +1,38 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** +# Makefile for Project + +# default target for project level makefile is stage +stage:: + +prepfiles:: prepfiles_global +clobber:: clobber_global + +BSP_SPECIFIC_DIRS= list of directories which need to be rebuilt when BSP changes + diff --git a/MakeTemplates/Makerules.module b/MakeTemplates/Makerules.module new file mode 100755 index 0000000..8603561 --- /dev/null +++ b/MakeTemplates/Makerules.module @@ -0,0 +1,129 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** +## Rules for module +#=============================================================================# +## Module Make Rules File +## ----------------------- +## +#=============================================================================# +## +#=============================================================================# +# The following list is the standard list of definitions which will be defined +# for all platforms. It consists of general and machine specific sections that +# contain many system parameters which may be used in a makefile. Please keep +# the list(s) in strictly aphabetical order to facilitate simple searches. +# +# See Makerules.global for the meaning of these flags +#-----------------------------------------------------------------------------# +# Common platform definitions: +#-----------------------------------------------------------------------------# +MOD_DIR=$(PROJ_DIR) +MOD_INCLUDE_DIR=$(PROJ_INCLUDE_DIR) +MOD_LIB_DIR=$(PROJ_LIB_DIR) # or $(MOD_DIR)/builtlibs +MOD_BIN_DIR=$(PROJ_BIN_DIR) +MOD_SHLIB_DIR=$(PROJ_SHLIB_DIR) +MOD_SBR_DIR=$(PROJ_SBR_DIR) +MOD_DRIVER_BIN_DIR=$(PROJ_DRIVER_BIN_DIR) + +MOD_STAGE_DIR=$(PROJ_STAGE_DIR) +MOD_STAGE_INCLUDE_DIR=$(PROJ_STAGE_INCLUDE_DIR) +MOD_STAGE_LIB_DIR=$(PROJ_STAGE_LIB_DIR) # or $(MOD_DIR)/builtlibs +MOD_STAGE_BIN_DIR=$(PROJ_STAGE_BIN_DIR) +MOD_STAGE_SHLIB_DIR=$(PROJ_STAGE_SHLIB_DIR) +MOD_STAGE_SBR_DIR=$(PROJ_STAGE_SBR_DIR) +MOD_STAGE_DRIVER_BIN_DIR=$(PROJ_STAGE_DRIVER_BIN_DIR) + +MOD_BIN_SUBDIR = +MOD_DRIVER_BIN_SUBDIR = +MOD_INCLUDE_SUBDIR = # or module_name + +MOD_INCLUDE_DIRS = # or $(GLOBAL_INCLUDE_DIR)/$(MOD_INCLUDE_SUBDIR) +MOD_LIB_DIRS = # or $(MOD_LIB_DIR) +MODDEPLIBS = +MODLIBS = + +BSCMOD = +CMOD = +CCMOD = +DEPENDMOD = +LDMOD = +LINTMOD = +MIDLMOD = +RSCMOD = + +#-----------------------------------------------------------------------------# +# Platform specific definitions: +#-----------------------------------------------------------------------------# +ifeq "$(TARGET_OS)" "VXWORKS" +endif # VXWORKS +ifeq "$(TARGET_OS)" "LINUX" +endif # LINUX +ifeq "$(TARGET_OS)" "WIN32" +endif # WIN32 +ifeq "$(TARGET_OS)" "DARWIN" +endif # DARWIN +#=============================================================================# +# Include Global makerules definitions and rules +include $(TL_DIR)/$(PROJ_FILE_DIR)/Makerules.project +#=============================================================================# + +#=============================================================================# +## The project makerules file also contains the following basic make target +## rules for simplifying application build processes: +## +#=============================================================================# +# The following section contains a list of standard targets which will be used +# by all of the makefiles. The targets are listed in alphabetical order and +# depend on the above definitions section as well as externally defined items +# from the user specific makefile. +#=============================================================================# +# General Rules: +#-----------------------------------------------------------------------------# +#=============================================================================# + +#=============================================================================# +# This section contains a set of targets which override the standard ones +# provided for by GNU make. +#=============================================================================# +# Standard Makefile Rules Overrides: +#-----------------------------------------------------------------------------# +#=============================================================================# + +#=============================================================================# +# Targets to make sure the initial environment is properly configured +#=============================================================================# +#ifndef ENVIRONMENT +#check_env: +# @echo "The ENVIRONMENT environment variable must be set to be valid" +# @exit 1 +#else #ENVIRONMENT +#check_env: +#endif #ENVIRONMENT +#.PHONY: check_env +#=============================================================================# diff --git a/MakeTemplates/Makerules.project b/MakeTemplates/Makerules.project new file mode 100755 index 0000000..a27ac51 --- /dev/null +++ b/MakeTemplates/Makerules.project @@ -0,0 +1,163 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** +## Rules for project +#=============================================================================# +## Project Make Rules File +## ----------------------- +## +## All tools local makefiles should include this makerules file after its own +## local definitions section and before the local rules section. Use +## Makefile.template as a base makefile and modify the template according to +## your application needs. The template makefile includes this makerules file +## and this project makerules file includes the global makerules file. Any +## modifications to this makerules file or to local makefiles should be made +## in a portable fashion using 'ifdef' structures where necessary so that the +## same makefile can be used on multiple platforms. The main purpose of this +## include makerules file is for local variable definitions and rules which are +## specific to the project at hand. Global modifications should be made in the +## global makerules file and local items should be in the local makefile, not +## in this makerules file. Any modifications to the source should be made with +## portability in mind and should follow the embedded notations. Documentation +## is automatically generated from this makefile! Use the correct conventions +## for those items which should be documented. +## +## NOTE: This makefile inclusion (the global makerules, and the template +## makefile) depend on using the GNU version of make. GNU make must be +## installed on your system prior to using this makefile. +#=============================================================================# +## +#=============================================================================# +# The following list is the standard list of definitions which will be defined +# for all platforms. It consists of general and machine specific sections that +# contain many system parameters which may be used in a makefile. Please keep +# the list(s) in strictly aphabetical order to facilitate simple searches. +# +# See Makerules.global for the meaning of these flags +#-----------------------------------------------------------------------------# +# Common platform definitions: +#-----------------------------------------------------------------------------# + +PROJ_DIR = $(GLOBAL_DIR) +PROJ_BIN_DIR = $(GLOBAL_BIN_DIR) +PROJ_DRIVER_BIN_DIR = $(GLOBAL_BIN_DIR) +PROJ_INCLUDE_DIR = $(GLOBAL_INCLUDE_DIR) +PROJ_LIB_DIR = $(GLOBAL_LIB_DIR) +PROJ_SHLIB_DIR = $(GLOBAL_SHLIB_DIR) +PROJ_SBR_DIR = $(GLOBAL_SBR_DIR) +PROJ_DRIVER_BIN_DIR = $(GLOBAL_BIN_DIR) + +PROJ_STAGE_DIR = $(STAGE_DIR) +PROJ_STAGE_BIN_DIR = $(STAGE_BIN_DIR) +PROJ_STAGE_INCLUDE_DIR = $(STAGE_INCLUDE_DIR) +PROJ_STAGE_LIB_DIR = $(STAGE_LIB_DIR) +PROJ_STAGE_SHLIB_DIR= $(STAGE_SHLIB_DIR) +PROJ_STAGE_SBR_DIR = $(STAGE_SBR_DIR) +PROJ_STAGE_DRIVER_BIN_DIR = $(STAGE_BIN_DIR) + +PROJ_INCLUDE_DIRS = $(COMN_INCLUDE_DIRS) +PROJ_LIB_DIRS = $(COMN_LIB_DIRS) +PROJDEPLIBS = +PROJLIBS = $(CCLIBS) + +BSCPROJ = +CPROJ = -DPRODUCT=$(PRODUCT) -DPRODUCT_$(PRODUCT) -DIB_STACK_OPENIB +CCPROJ = $(CCNORTTI) $(CCNOEXH) -DPRODUCT=$(PRODUCT) -DPRODUCT_$(PRODUCT) -DIB_STACK_OPENIB +DEPENDPROJ = +LDPROJ = +LINTPROJ = +MIDLPROJ = +RSCPROJ = + +# On Windows ACE needs MFC DLL +USEMFC = shared + +#-----------------------------------------------------------------------------# +# Platform specific definitions: +#-----------------------------------------------------------------------------# +ifeq "$(BUILD_TARGET_OS)" "VXWORKS" +endif # VXWORKS +ifeq "$(BUILD_TARGET_OS)" "LINUX" +endif # LINUX +ifeq "$(BUILD_TARGET_OS)" "WIN32" +endif # WIN32 +ifeq "$(BUILD_TARGET_OS)" "DARWIN" +endif # DARWIN + +PROJECT_SSP = # ssp name for TMS +PROJECT_PACKAGE_EXTERNAL_NAME = # external name for package file +PRODUCT_CODE = # product code enumeration + +CMDS_FIRMWARE_ONLY ?= yes + +#=============================================================================# +#=============================================================================# +## TL_DIR must be set in the environment for the 'make' to succeed. +## icsmake will do this for you +#-----------------------------------------------------------------------------# +# Include Global makerules definitions and rules +include $(TL_DIR)/Makerules/Makerules.global +#=============================================================================# + +#=============================================================================# +## The project makerules file also contains the following basic make target +## rules for simplifying application build processes: +## +#=============================================================================# +# The following section contains a list of standard targets which will be used +# by all of the makefiles. The targets are listed in alphabetical order and +# depend on the above definitions section as well as externally defined items +# from the user specific makefile. +#=============================================================================# +# General Rules: +#-----------------------------------------------------------------------------# +#=============================================================================# +include $(TL_DIR)/Makerules/Maketargets.product +CPROJ += $(PRODUCT_DEFINES) +CCPROJ += $(PRODUCT_DEFINES) + +#=============================================================================# +# This section contains a set of targets which override the standard ones +# provided for by GNU make. +#=============================================================================# +# Standard Makefile Rules Overrides: +#-----------------------------------------------------------------------------# +#=============================================================================# + +#=============================================================================# +# Targets to make sure the initial environment is properly configured +#=============================================================================# +#ifndef ENVIRONMENT +#check_env: +# @echo "The ENVIRONMENT environment variable must be set to be valid" +# @exit 1 +#else #ENVIRONMENT +#check_env: +#endif #ENVIRONMENT +#.PHONY: check_env +#=============================================================================# diff --git a/MakeTemplates/Makesettings.project b/MakeTemplates/Makesettings.project new file mode 100644 index 0000000..a6cec8f --- /dev/null +++ b/MakeTemplates/Makesettings.project @@ -0,0 +1,94 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** +## Make Settings at project level +#=============================================================================# +## Project Make Settings File +## ----------------------- +## +## This file allows setting variables which can be used by Makefiles to make +## decisions on which targets or DIRS to build. This allows such controls +## to be placed here as opposed to extending the build system environment +## variable tools like setenv, target, etc. +## +## All tools local makefiles should include this makerules file before its own +## local definitions section. Use +## Makefile.template as a base makefile and modify the template according to +## your application needs. The template makefile includes this file +## and this project makesettings file includes the global makesettings file. +## Any modifications to this makesettings file or to local makefiles should be +## made in a portable fashion using 'ifdef' structures where necessary so that +## the same makefile can be used on multiple platforms. +## The main purpose of this +## include makesettings file is for local variable definitions +## specific to the project at hand. Global modifications should be made in the +## global makesettings file and local items should be in the local makefile, not +## in this makesettings file. +## Any modifications to the source should be made with +## portability in mind and should follow the embedded notations. Documentation +## is automatically generated from this makefile! Use the correct conventions +## for those items which should be documented. +## +## NOTE: This makefile inclusion (the global makesettings, and the template +## makefile) depend on using the GNU version of make. GNU make must be +## installed on your system prior to using this makefile. +#=============================================================================# +## +#=============================================================================# +# The following list is the standard list of settings which will be defined +# for all platforms. It consists of general and machine specific sections that +# contain many system parameters which may be used in a makefile. Please keep +# the list(s) in strictly aphabetical order to facilitate simple searches. +# +# See Makerules.global for the meaning of these flags +#-----------------------------------------------------------------------------# +# Common platform definitions: +#-----------------------------------------------------------------------------# + +IB_STACK=OPENIB +#PROJ_SM_DIR=$(TL_DIR)/Esm/ib + +#-----------------------------------------------------------------------------# +# Platform specific definitions: +#-----------------------------------------------------------------------------# +ifeq "$(BUILD_TARGET_OS)" "VXWORKS" +endif # VXWORKS +#ifeq "$(BUILD_TARGET_OS)" "DARWIN" +#endif # DARWIN +ifeq "$(BUILD_TARGET_OS)" "LINUX" +endif # LINUX +ifeq "$(BUILD_TARGET_OS)" "WIN32" +endif # WIN32 +#=============================================================================# +#=============================================================================# +## TL_DIR must be set in the environment for the 'make' to succeed. +## icsmake will do this for you +#-----------------------------------------------------------------------------# +# Include Global makerules definitions and rules +include $(TL_DIR)/Makerules/Makesettings.global +#=============================================================================# diff --git a/MakeTemplates/README b/MakeTemplates/README new file mode 100644 index 0000000..ba0a41a --- /dev/null +++ b/MakeTemplates/README @@ -0,0 +1,2 @@ +Templates for makefiles and body of buildMakefile tool to help +create makefiles diff --git a/MakeTemplates/buildMakefile b/MakeTemplates/buildMakefile new file mode 100755 index 0000000..efbf79a --- /dev/null +++ b/MakeTemplates/buildMakefile @@ -0,0 +1,699 @@ +#!/bin/bash +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** +# This script will create a basic makefile for all the source code +# files found in the present directory. + +# +# It handles the following special cases automatically: +# if the directory name is Test, a unit test makefile is build +# to unit test the parent directory's library +# if the directory is a top level directory, a project makefile is built +# if the directory is a middle level directory, a middle makefile is built +# if the directory is sub-directory of a module which has a +# Makerules.module file, a module sub-directory makefile is built +# (it is best to build the module top level makefile first +# then buildMakefile for sub-directories will properly build) +# For other directories, a library Makefile is built +# Any source files which should not be processed by the Makefile +# should have the strings: "INTERNAL USE ONLY" or "DO NOT BUILD" +# "INTERNAL USE ONLY" should be used for non-public headers +# "DO NOT BUILD" should be used for source which is not ready yet +# +# In update mode (-u) an existing makefile is rebuilt, retaining selected +# customizations. The original is renamed Makefile-old +# +# Other Options: +# -x - create a makefile for building an executable +# -d - create a makefile for building a driver +# -k - create a makefile for building a darwin kernel extension +# -s - create a makefile for building a shared library +# -a - create a makefile for building an archive library (the default) +# -m - create a makefile for the toplevel directory of a module +# -c dir - create a makefile which builds code from this directory and dir +# (dir is relative to MOD_DIR) +# this option is only valid within a module style tree +# -p project - project name, default is current dir name + +# Known Limitations: +# The update option (-u) only handles LOCALDEPLIBS and DS_SUBPROJECTS +# other customizations will be lost +# All include files will be installed as visible to other modules +# one exception is file containing the string "INTERNAL USE ONLY" +# on "DO NOT BUILD" +# out of the ordinary situations are not handled +# all non-special sub-directories are simply included in the Makefile +# .rc, .idl, .def files not handled +# misc source files not handled +# building of shared libraries not handled +# building makefiles for integration tests is not supported + +. $ICSBIN/funcs.sh + +tempFiles= +foundSource=n +# This will always be run when we exit, so it can do all our cleanup +trap 'rm -f $tempFiles' 0 1 2 9 15 + +Usage() { + echo "Usage: buildMakefile [-p project] [-u] [-m] [-c dir] [-x|-sad]" >&2 + echo " -p project project name, default is current dir name" >&2 + echo " -x create a makefile for building an executable" >&2 + echo " -d create a makefile for building a driver" >&2 + echo " -k create a makefile for building a darwin kernel extension" >&2 + echo " -s create a makefile for building a shared library" >&2 + echo " -a create a makefile for building an archive library (the default)" >&2 + echo " -m create a makefile for the toplevel directory of a module" >&2 + echo " -c dir create a makefile which builds code from this directory and dir" >&2 + echo " (dir is relative to MOD_DIR)" >&2 + echo " this option is only valid within a module style tree" >&2 + echo " -u In update mode (-u) an existing makefile is rebuilt, retaining selected" >&2 + echo " customizations. The original is renamed Makefile-old" >&2 + + + exit 2 +} + +grepValue() +{ + # grep for the value of a variable in the present Makefile + # $1 = variable name + # returns on stdout, the value of the variable + # leading spaces are removed from the value + grep "^$1" Makefile|cut -f2- -d=|sed -e's/^[ ]*//' +} + + +uflag=n +xflag=n +sflag=n +aflag=n +dflag=n +kflag=n +mflag=n +cdir= +project= +while getopts uxsadkmc:p: opt +do + case $opt in + u) uflag=y;; + x) xflag=y;; + s) sflag=y;; + a) aflag=y;; + d) dflag=y;; + k) dflag=y # -d implied by -k + kflag=y;; + m) mflag=y;; + c) cdir=$OPTARG;; + p) project=$OPTARG;; + ?) Usage;; + esac +done +shift `expr $OPTIND - 1` +if [ $# != 0 ] +then + Usage +fi +if [ "$xflag" = y ] +then + if [ "$aflag" = y -o "$sflag" = y -o "$dflag" = y ] + then + Usage + fi +fi + +if [ -f Makefile ] +then + if [ "$uflag" = n ] + then + echo "buildMakefile aborted. A Makefile already exists in this directory!" >&2 + echo "To update an existing makefile, use buildMakefile -u" >&2 + exit 1 + else + ds_subprojects=`grepValue DS_SUBPROJECTS` + shlib_version=`grepValue SHLIB_VERSION` + localdeplibs=`grepValue LOCALDEPLIBS` + clocal=`grepValue CLOCAL` + cclocal=`grepValue CCLOCAL` + copt=`grepValue COPT` + ccopt=`grepValue CCOPT` + local_include_dirs=`grepValue LOCAL_INCLUDE_DIRS` + libfiles=`grepValue LIBFILES` + mv Makefile Makefile-old + fi +else + ds_subprojects="" + shlib_version="" + localdeplibs="" + clocal="" + cclocal="" + copt="" + ccopt="" + if [ "$mflag" = y ] + then + libfiles='FILL IN libraries built to $(MOD_LIB_DIR)' + else + libfiles= + fi + if [ "$uflag" = y ] + then + uflag=n # ignore -u, no existing makefile + echo "buildMakefile: ignoring -u, no existing Makefile" + fi +fi + +extractModuleDir() +{ + # extract the module sub-directory from a full path + # and set module_dir to the resulting sub-directory path + # $1 = full path to module (should be within TL_DIR) + module_dir=`expr "$1" : "$TL_DIR/\(.*\)"` +} + +findModuleDir() +{ + # sets module_dir to the sub-directory under TL_DIR for this module + # if this is not a module, module_dir is set to "" + # uses $TL_DIR + full_module_dir="$pwd" + while [ ! -f "$full_module_dir/Makerules.module" ] + do + full_module_dir=`dirname $full_module_dir` + if [ "$full_module_dir" = "/" -o "$full_module_dir" = "$TL_DIR" -o -f "$full_module_dir"/Makerules/Makerules.global ] + then + full_module_dir="" + module_dir="" + return + fi + done + + extractModuleDir "$full_module_dir" +} + + +formatFileList() +{ + # Create a variable specifying a source file list + # and output the value to the given temp file + # $1 = output temp file name + # $2 = list of directories to process + # $3 = prefix to use for filenames not in directory . + # cheat for now, assumes dir list is only . and 1 other + # hence we can get away with a single prefix + # $4 = list of extra filenames to explicitly add to list + # $5 = heading to declare variable for list + # $6 ... = suffixes for files to include in list + output=$1 + list_dirs=$2 + dir_prefix=$3 + extra="$4" + heading=$5 + shift; shift; shift; shift; shift + echo "$heading \\" > $output + { + for file in $extra + do + echo " $file \\" + done + for suffix in $* + do + for dir in $list_dirs + do + for i in $dir/*.$suffix + do + if [ -f "$i" ] + then + foundSource=y + base=`basename $i` + if egrep 'DO NOT BUILD|INTERNAL USE ONLY' $i > /dev/null + then + > /dev/null + elif [ "$base" != "$extra" ] + then + # This is a cheat, should test extra as a list, but for now we know it only has 1 filename + if [ "$dir" != "." -a "$dir_prefix" != "" ] + then + echo " $dir_prefix/$base \\" + else + echo " $base \\" + fi + fi + fi + done + done + done + } > temp$$ + sort < temp$$ >> $output + echo " # Add more $* files here" >> $output + rm -f temp$$ + tempFiles="$tempFiles $output temp$$" +} + +formatVariable() +{ + # Create a variable specifying a target file or 1 line list + # and output the value to the given temp file + # $1 = output temp file name + # $2 = heading to declare variable + # $3 = value for variable + if [ "$2" = "" ] + then + > $1 + else + echo "$2 $3" > $1 + fi + tempFiles="$tempFiles $1" +} + +formatOptionalVariable() +{ + # Create a variable specifying a target file or 1 line list + # and output the value to the given temp file + # If the value ($3) is null, an empty file is created + # $1 = output temp file name + # $2 = heading to declare variable + # $3 = value for variable + if [ x"$3" = "x" ] + then + formatVariable "$1" "" "" + else + formatVariable "$1" "$2" "$3" + fi +} + +formatRule() +{ + # Create a makefile rule line + # and output the line to the given temp file + # $1 = output temp file name + # $2 = rule line + echo -e "$2" > $1 + tempFiles="$tempFiles $1" +} + +CommonMakefileEdits() +{ +# Edits of Makefile applicable to most Makefiles +ex Makefile </$project/" < $TL_DIR/MakeTemplates/Makerules.project > Makerules.project + fi + sed -e "s//$project/" < $TL_DIR/MakeTemplates/Makefile.projHeading > Makefile + cat $TL_DIR/MakeTemplates/Makefile.basic >> Makefile + CommonMakefileEdits + ex Makefile </$project/" < $TL_DIR/MakeTemplates/Makerules.module > Makerules.module + ex Makerules.module </$project/" < $TL_DIR/MakeTemplates/Makefile.modHeading > Makefile + cat $TL_DIR/MakeTemplates/Makefile.basic >> Makefile + CommonMakefileEdits + ex Makefile < Makefile + echo >> Makefile + if [ "$foundSource" = n ] + then + cat $TL_DIR/MakeTemplates/Makefile.middle >> Makefile + ex Makefile <> Makefile + CommonMakefileEdits + fi +} + +rm -f $tempFiles + +TL_DIR=`findTopDir` +pwd=`pwd` + +if [ -f Makerules/Makerules.global ] +then + projectDir=y + if [ "$mflag" = y ] + then + echo "Project level directories cannot be module Makefiles" 2>&1 + exit 1 + fi + module_dir="" +else + projectDir=n + if [ "$mflag" = y ] + then + extractModuleDir "$pwd" + else + findModuleDir + fi +fi +dirName=`basename $pwd` +if [ "$cdir" != "" -a "$module_dir" = "" ] +then + echo "-c option is not valid outside a module Makefile tree" 2>&1 + exit 1 +fi + +# find all directories +dirs= +for i in * +do + if [ -d "$i" -a "$i" != CVS -a "$i" != "builtbin" -a "$i" != builtinclude \ + -a "$i" != builtlibs -a "$i" != stage -a "$i" != Makerules \ + -a "$i" != MakeTools \ + -a "$i" != MakeTemplates -a "$i" != CodeTemplates ] + then + if [ "$i" = Test ] + then + # translate to make variable so unit tests are optional + i='$(TEST)' + fi + if [ "$dirs" = "" ] + then + dirs="$i" + else + dirs="$dirs $i" + fi + fi +done + +if [ -f "$dirName".msg ] +then + # Message files to be built + message_file="${dirName}.msg" + message_hfile="${dirName}_Messages.h" + message_cfile="${dirName}_Messages.c" +elif [ "$cdir" != "" -a -f "$dirName".msg ] +then + # Message files to be built from common dir + message_file="${dirName}.msg" + message_hfile="${dirName}_Messages.h" + message_cfile="${dirName}_Messages.c" +else + message_file="" + message_hfile="" + message_cfile="" +fi + +formatVariable DIRS.tmp 'DIRS =' "$dirs" + +if [ "$cdir" != "" ] +then + file_dirs=". $full_module_dir/$cdir" +else + file_dirs="." +fi +formatFileList CFILES.tmp "$file_dirs" "" "$message_cfile" "CFILES =" c +formatFileList CCFILES.tmp "$file_dirs" "" "" "CCFILES =" cpp +formatFileList LFILES.tmp "$file_dirs" "" "" "LFILES =" lex +foundCode=$foundSource +formatFileList INCLUDE_TARGETS.tmp "$file_dirs" "\$(COMMON_SRCDIR)" "$message_hfile" "INCLUDE_TARGETS =" h hpp +formatVariable CLEAN_TARGETS_MISC.tmp 'CLEAN_TARGETS_MISC =' "$message_hfile $message_cfile" + +if [ "$project" = "" ] +then + project="$dirName" +fi +if [ "$dirName" = "Test" ] +then + if [ "$mflag" = y ] + then + echo "Module makefiles cannot be Unit Test directories" 2>&1 + Usage + fi + # Unit Test + parent=`dirname $pwd` + parent=`basename $parent` + project=${parent}_Test + libTarget=n + exeTarget=y + driverTarget=n + kextTarget=n + if [ "$uflag" = n ] + then + ds_subprojects="$parent Osa Gen Log Err Rai UiUtil UTest" + localdeplibs="$parent Osa Gen Log Err Rai UiUtil UTest" + fi + formatRule runtest.tmp 'include $(TL_DIR)/Makerules/Maketargets.runtest' +else + # TBD other tests, projectDir should be y for exe, check for a main? + # if we didn't find any real code files (just headers) + # we don't build a library nor executable + if [ "$foundCode" = y -a "$dflag" != y ] + then + libTarget=y + exeTarget=n + driverTarget=n + kextTarget=n + else + libTarget=n + exeTarget=n + driverTarget=n + kextTarget=n + fi + formatRule runtest.tmp '#include $(TL_DIR)/Makerules/Maketargets.runtest' +fi +# -x, -a and -s, -d override the above heuristics +if [ "$xflag" = y ] +then + exeTarget=y + libTarget=n +elif [ "$sflag" = y -o "$aflag" = y ] +then + exeTarget=n + libTarget=y +fi +if [ "$dflag" = y ] +then + driverTarget=y +fi +if [ "$kflag" = y ] +then + kextTarget=y +fi + +arlib="" +shlib="" +driver="" +kext="" +if [ "$libTarget" = y ] +then + if [ "$sflag" = y ] + then + shlib='$(LIB_PREFIX)'"${project}"'$(SHLIB_VERSION_SUFFIX)' + if [ "$shlib_version" = "" ] + then + shlib_version="0.0" + fi + fi + if [ "$aflag" = y -o "$sflag" = n ] + then + arlib='$(LIB_PREFIX)'"${project}"'$(ARLIB_SUFFIX)' + fi +fi +if [ "$driverTarget" = y ] +then + driver="${project}"'$(KOBJ_SUFFIX)' +fi +if [ "$kextTarget" = y ] +then + kext="${project}"'$(KEXT_SUFFIX)' +fi +formatVariable LIB_TARGETS_ARLIB.tmp 'LIB_TARGETS_ARLIB =' "$arlib" +formatVariable SHLIB_VERSION.tmp 'SHLIB_VERSION =' "$shlib_version" +formatVariable CMD_TARGETS_SHLIB.tmp 'CMD_TARGETS_SHLIB =' "$shlib" +formatVariable CMD_TARGETS_DRIVER.tmp 'CMD_TARGETS_DRIVER =' "$driver" +formatVariable CMD_TARGETS_KEXT.tmp 'CMD_TARGETS_KEXT =' "$kext" + +if [ "$exeTarget" = y ] +then + executable="${project}"'$(EXE_SUFFIX)' +else + executable='# '"${project}"'$(EXE_SUFFIX)' +fi +formatVariable EXECUTABLE.tmp 'EXECUTABLE =' "\$(BUILDDIR)/$executable" + +formatVariable DS_SUBPROJECTS.tmp 'DS_SUBPROJECTS =' "$ds_subprojects" +formatVariable LOCALDEPLIBS.tmp 'LOCALDEPLIBS =' "$localdeplibs" +formatOptionalVariable CLOCAL.tmp 'CLOCAL =' "$clocal" +formatOptionalVariable CCLOCAL.tmp 'CCLOCAL =' "$cclocal" +formatOptionalVariable LOCAL_INCLUDE_DIRS.tmp 'LOCAL_INCLUDE_DIRS =' "$local_include_dirs" +formatVariable LIBFILES.tmp 'LIBFILES =' "$libfiles" +if [ "$module_dir" != "" ] +then + if [ "$cdir" != "" ] + then + cdir_def="\n\nCOMMON_SRCDIR = \$(MOD_DIR)/$cdir" + else + cdir_def="" + fi + formatRule rules.tmp "include \$(TL_DIR)/$module_dir/Makerules.module$cdir_def" +else + formatRule rules.tmp "include \$(TL_DIR)/\$(PROJ_FILE_DIR)/Makerules.project" +fi +if [ "$driverTarget" = y ] +then + formatOptionalVariable COPT.tmp 'COPT =' "# set by CKERNEL for drivers" + formatOptionalVariable CCOPT.tmp 'CCOPT =' "# set by CKERNEL for drivers" +else + formatOptionalVariable COPT.tmp 'COPT =' "$copt" + formatOptionalVariable CCOPT.tmp 'COPT =' "$ccopt" +fi + +if [ "$projectDir" = y ] +then + # building a project level makefile + buildProjectMakefile +elif [ "$mflag" = y ] +then + # building a lower level module makefile + formatRule MOD_DIR.tmp "MOD_DIR=\$(TL_DIR)/$module_dir" + buildModuleMakefile +else + # building a lower level makefile + buildBasicMakefile +fi diff --git a/MakeTools/Makefile b/MakeTools/Makefile new file mode 100644 index 0000000..9682763 --- /dev/null +++ b/MakeTools/Makefile @@ -0,0 +1,97 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** +# Makefile for MakeTools + +# Include Make Control Settings +include $(TL_DIR)/$(PROJ_FILE_DIR)/Makesettings.project + +DS_SUBPROJECTS = +DSP_SOURCES= Makefile \ + buildmsgs.pl \ + build_srpms.sh \ + expand_source.sh \ + expand_ofed.sh \ + get_ofed_files.sh \ + getsmpopt.sh \ + get_comp.sh \ + get_input_comp_files.sh \ + lnshlib.sh \ + lnshlib.darwin.sh \ + ln-install.sh \ + makeiso.sh \ + mkarlib.sh \ + builddsw.sh \ + finddspfiles.sh \ + makewin32depend.sh \ + prep.sh \ + unpack_comp.sh +DIRS = \ + patch_version \ + installtargets \ + stripdepends \ + rm_version \ + $(TEST) +CMD_TARGETS_MISC = \ + builddsw \ + build_srpms \ + expand_source \ + expand_ofed \ + get_ofed_files \ + get_comp \ + get_input_comp_files \ + finddspfiles \ + ln-install \ + makewin32depend \ + unpack_comp +ifeq "$(PRODUCT)" "devtools" +CMD_TARGETS_MISC += prep \ + patch_engineer_version \ + convert_releasetag \ + format_releasetag +endif + +INCLUDE_TARGETS = + +include $(TL_DIR)/$(PROJ_FILE_DIR)/Makerules.project + +include $(TL_DIR)/Makerules/Maketargets.toplevel + +include $(TL_DIR)/Makerules/Maketargets.build +convert_releasetag: convert_releasetag.pl + cp $< $@ + chmod 755 $@ + +format_releasetag: format_releasetag.sh + cp $< $@ + chmod 755 $@ + +include $(TL_DIR)/Makerules/Maketargets.stage + +include $(TL_DIR)/Makerules/Maketargets.install + diff --git a/MakeTools/README b/MakeTools/README new file mode 100755 index 0000000..8a23ede --- /dev/null +++ b/MakeTools/README @@ -0,0 +1 @@ +Tools used during build to assist in generating code/building product diff --git a/MakeTools/Test/Err.msg b/MakeTools/Test/Err.msg new file mode 100755 index 0000000..f522aa4 --- /dev/null +++ b/MakeTools/Test/Err.msg @@ -0,0 +1,108 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +#[ICS VERSION STRING: unknown] +# +# $Source: /cvs/ics/MakeTools/Test/Err.msg,v $ +# $Name: $ +# $Revision: 1.3 $ +# $Date: 2015/01/28 20:18:11 $ +# + +# +# Message Definitions for Err module +# + +[Module] +Name=Err + +[String] +Name=OK +Comment=ERR_OK text +String.English="Success" + +[String] +Name=FAILED_CONSTRUCTOR +Comment=ERR_FAILED_CONSTRUCTOR and ERR_KIND_FAILED_CONSTRUCTORtext +String.English="Failed Constructor" + +[String] +Name=END_OF_DATA +Comment=ERR_END_OF_DATA and ERR_KIND_END_OF_DATA text +String.English="End of Data" + +[String] +Name=IO_ERROR +Comment=ERR_IO_ERROR and ERR_KIND_IO_ERROR text +String.English="IO Error" + +[String] +Name=INVALID +Comment=ERR_INVALID and ERR_KIND_INVALID text +String.English="Invalid" + +[String] +Name=MISSING +Comment=ERR_MISSING and ERR_KIND_MISSING text +String.English="Missing" + +[String] +Name=DUPLICATE +Comment=ERR_DUPLICATE and ERR_KIND_DUPLICATE text +String.English="Duplicate" + +[String] +Name=OVERFLOW +Comment=ERR_OVERFLOW and ERR_KIND_OVERFLOW text +String.English="Overflow" + +[String] +Name=TIMEOUT +Comment=ERR_TIMEOUT and ERR_KIND_TIMEOUT text +String.English="Timeout" + +[String] +Name=UNDERFLOW +Comment=ERR_UNDERFLOW and ERR_KIND_UNDERFLOW text +String.English="Underflow" + +[String] +Name=OUT_OF_RESOURCES +Comment=ERR_OUT_OF_RESOURCES and ERR_KIND_OUT_OF_RESOURCES text +String.English="Out of Resources" + +[String] +Name=UNKNOWN +Comment=ERR_KIND_UNKNOWN text +String.English="Unknown" + +[String] +Name=BAD +Comment=invalid Err_Code_t value for Err module defined errors +String.English="Bad" diff --git a/MakeTools/Test/ErrTest.in b/MakeTools/Test/ErrTest.in new file mode 100755 index 0000000..ee9a78f --- /dev/null +++ b/MakeTools/Test/ErrTest.in @@ -0,0 +1,485 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +#[ICS VERSION STRING: unknown] +# +# Test error detection +# + +# check module +[Module] +Name=Test + +# extra module section +[Module] +Name=Again + +# invalid names +[Module] +Name=This one is not an identifier + +[Module] +Name=1bad1 + +[Module] +Name=This_is_2_long + +[Module] +Name=SameWithThisOne + +# OK, but yet another Module section +[Module] +Name=Good4U + +[Module] +Name=AName +Name=Again + +[Module] +Name=WithUC +UcName=WITH_UC + +[Module] +Name=DupUc +UcName=DUP_UC +UcName=DUP_UC + +# +# Check Message Name +# +[Message] +Name=MIN_MESSAGE +Severity=Warning +Description.English="As simple as it gets" + +# duplicate name +[Message] +Name=MIN_MESSAGE +Severity=Warning +Description.English="A duplicate name" + +# slip in another Module section +[Module] +Name=Bad2 + +# back to messages +[Message] +# missing name +Severity=Warning +Description.English="Missing Name" + +[Message] +Name=MixedCase +Severity=Warning +Description.English="Mixed Case Name" + +[Message] +Name=WITH SPACES +Severity=Warning +Description.English="Name with spaces" + +[Message] +Name=4_A_BAD_NAME +Severity=Warning +Description.English="Name with leading digit" + +[Message] +Name=MIN_MESSAGE +Severity=Warning +Description.English="A duplicate again" + +# +# Comments +# +[Message] +Name=WITH_COMMENT +Comment=This is OK +Severity=Warning +Description.English="With a comment" + +[Message] +Name=MULTIPLE_COMMENTS +Comment=This is OK +Comment=But this is not +Severity=Warning +Description.English="With multiple comments" + +# +# Arg list +# +[Message] +Name=ARG_1 +Arglist=arg1 +Severity=Warning +Description.English="%d" + +[Message] +Name=ARG_2 +Arglist=arg1,arg2 +Severity=Warning +Description.English="%d%d" + +[Message] +Name=ARG_3 +Arglist=arg1,arg2,arg3 +Severity=Warning +Description.English="%d%d%d" + +[Message] +Name=ARG_4 +Arglist=arg1,arg2,arg3,arg4 +Severity=Warning +Description.English="%d%d%d%d" + +[Message] +Name=ARG_5 +Arglist=arg1,arg2,arg3,arg4,arg5 +Severity=Warning +Description.English="%d%d%d%d%d" + +[Message] +Name=ARG_6 +Arglist=arg1,arg2,arg3,arg4,arg5,arg6 +Severity=Warning +Description.English="%d%d%d%d%d%d" + +# too many args +[Message] +Name=ARG_7 +Arglist=arg1,arg2,arg3,arg4,arg5,arg6,arg7 +Severity=Warning +Description.English="%d%d%d%d%d%d%d" + +[Message] +Name=MISSING_ARGS +Severity=Warning +Description.English="%d%d%d%d%d%d%d" + +[Message] +Name=EXTRA_ARGS +Arglist=arg1,arg2,arg3,arg4,arg5,arg6 +Severity=Warning +Description.English="%d%d%d%d%d" + +[Message] +Name=INSUFFICIENT_ARGS +Arglist=arg1,arg2,arg3,arg4 +Severity=Warning +Description.English="%d%d%d%d%d" + +[Message] +Name=NAMED_ARGS +Arglist=first: arg1, second: arg2 +Severity=Warning +Description.English="%d%d" + +[Message] +Name=BAD_ARG_NAMES +Arglist=1badName: has a leading number, second: this is OK, + third one: has a space, B*d_character: as it says +Severity=Warning +Description.English="%d%d%d%d" + +# +# UnitArg +# +[Message] +Name=UNIT_0 +Arglist=arg1,arg2,arg3,arg4,arg5,arg6 +UnitArg=0 +Severity=Warning +Description.English="Unit arg is 0 %d%d%d%d%d%d" + +[Message] +Name=UNIT_1 +Arglist=arg1,arg2,arg3,arg4,arg5,arg6 +UnitArg=1 +Severity=Warning +Description.English="Unit arg is 1 %d%d%d%d%d%d" + +[Message] +Name=UNIT_2 +Arglist=arg1,arg2,arg3,arg4,arg5,arg6 +UnitArg=2 +Severity=Warning +Description.English="Unit arg is 2 %d%d%d%d%d%d" + +[Message] +Name=UNIT_3 +Arglist=arg1,arg2,arg3,arg4,arg5,arg6 +UnitArg=3 +Severity=Warning +Description.English="Unit arg is 3 %d%d%d%d%d%d" + +[Message] +Name=UNIT_4 +Arglist=arg1,arg2,arg3,arg4,arg5,arg6 +UnitArg=4 +Severity=Warning +Description.English="Unit arg is 4 %d%d%d%d%d%d" + +[Message] +Name=UNIT_5 +Arglist=arg1,arg2,arg3,arg4,arg5,arg6 +UnitArg=5 +Severity=Warning +Description.English="Unit arg is 5 %d%d%d%d%d%d" + +[Message] +Name=UNIT_6 +Arglist=arg1,arg2,arg3,arg4,arg5,arg6 +UnitArg=6 +Severity=Warning +Description.English="Unit arg is 6 %d%d%d%d%d%d" + +[Message] +Name=UNIT_7 +Arglist=arg1,arg2,arg3,arg4,arg5,arg6 +UnitArg=7 +Severity=Warning +Description.English="Unit arg is 7 %d%d%d%d%d%d" + +[Message] +Name=UNIT_OUT_OF_LIST +Arglist=arg1,arg2,arg3,arg4,arg5 +UnitArg=6 +Severity=Warning +Description.English="Unit arg is 6 %d%d%d%d%d" + +[Message] +Name=BAD_UNIT_ARG_VAL +Arglist=arg1,arg2,arg3,arg4,arg5,arg6 +UnitArg=six +Severity=Warning +Description.English="Unit arg is six %d%d%d%d%d%d" + +# +# TrapFunc +# +[Message] +Name=TRAP_GOOD +Trapfunc=goodId +Severity=Warning +Description.English="Check trap func" + +[Message] +Name=TRAP_NUM +Trapfunc=1badFuncName +Severity=Warning +Description.English="Check trap func" + +[Message] +Name=TRAP_SPACE +Trapfunc=No spaces allowed +Severity=Warning +Description.English="Check trap func" + +[Message] +Name=TRAP_PUNC +Trapfunc=BadToo!!! +Severity=Warning +Description.English="Check trap func" + +# +# Severity +# +[Message] +Name=SEV_NONE +Description.English="No Severity" + +[Message] +Name=SEV_ADD_PART +Severity=ADD_PART +Description.English="Partial" + +[Message] +Name=SEV_PARTIAL +Severity=PARTIAL +Description.English="Partial again" + +[Message] +Name=SEV_ALARM +Severity=ALARM +Description.English="Alarm" + +[Message] +Name=SEV_ERROR +Severity=ERROR +Description.English="Error" + +[Message] +Name=SEV_WARNING +Severity=WARNING +Description.English="Warning" + +[Message] +Name=SEV_FATAL +Severity=FATAL +Description.English="Fatal" + +[Message] +Name=SEV_DUMP +Severity=DUMP +Description.English="Dump" + +[Message] +Name=SEV_CONFIG +Severity=CONFIG +Description.English="Config" + +[Message] +Name=SEV_PROGRAM_INFO +Severity=PROGRAM_INFO +Description.English="Program Info" + +[Message] +Name=SEV_PERIODIC_INFO +Severity=PERIODIC_INFO +Description.English="Periodic Info" + +[Message] +Name=SEV_BAD +Severity=Unknown +Description.English="Bad Severity" + +# +# Description +# +[Message] +Name=MISSING_DESCRIPTION +Severity=Warning + +[Message] +Name=BAD_LANGUAGE +Severity=Warning +Description.BorkBork="Bork Bork Bork" +Description.English="Huh?" + +[Message] +Name=MISSING_LANGUAGE +Severity=Warning +Description="Say what?" + +# Format tests + +# Mix positional and non-positional +[Message] +Name=FMT_1 +Severity=Warning +Arglist=arg1,arg2,arg3,arg4 +Description.English="%*4$d" + +[Message] +Name=FMT_2 +Severity=Warning +Arglist=arg1,arg2,arg3,arg4 +Description.English="%4$*d" + +[Message] +Name=FMT_3 +Severity=Warning +Arglist=arg1,arg2,arg3,arg4 +Description.English="%.*4$d" + +[Message] +Name=FMT_4 +Severity=Warning +Arglist=arg1,arg2,arg3,arg4 +Description.English="%4$.*d" + +# no warning, uses last arg only +[Message] +Name=FMT_5 +Severity=Warning +Arglist=arg1,arg2,arg3,arg4 +Description.English="%4$d" + +# warning, uses next-to-last arg only +[Message] +Name=FMT_6 +Severity=Warning +Arglist=arg1,arg2,arg3,arg4 +Description.English="%3$d" + +# invalid format (no fp support) +[Message] +Name=FMT_7 +Severity=Warning +Description.English="%f" + +# warn about duplicate flags (and don't use # in quotes to start comments) +[Message] +Name=FMT_8 +Severity=Warning +Arglist=arg1 +Description.English="%# #d" + +# positional can be before or after width.precision +[Message] +Name=FMT_9 +Severity=Warning +Arglist=arg1,arg2,arg3 +Description.English="%2$*3$.*1$d" + +[Message] +Name=FMT_10 +Severity=Warning +Arglist=arg1,arg2,arg3 +Description.English="%*3$.*1$2$d" + +# but not both +[Message] +Name=FMT_11 +Severity=Warning +Arglist=arg1,arg2,arg3,arg4 +Description.English="%4$*3$.*1$2$d" + +# format tests should go in Format.in + +# +# Response and Correction are handled with the same logic as Description +# + +# +# Check Strings, format parsing, comments, arglists, and duplicates are +# checked above (same logic as for messages) +# +[String] +# missing name +String.English="Missing Name" + +[String] +Name=MISSING_STRING + +[String] +Name=GOOD_STRING +String.English="End on a high note" + +[String] +Name=MAYBE_NOT diff --git a/MakeTools/Test/Formats.in b/MakeTools/Test/Formats.in new file mode 100755 index 0000000..3e5c5b4 --- /dev/null +++ b/MakeTools/Test/Formats.in @@ -0,0 +1,18 @@ +Mix positional and non-positional: %*4$F +Mix positional and non-positional: %4$*F +Mix positional and non-positional: %.*4$F +Mix positional and non-positional: %4$.*F +Simple Positional: %4$F +Simple Positional: %3$F +Invalid Type (no fp): %f +Duplicate flags: %# #F +Full Positional: %2$*3$.*1$F +Full Positional: %*3$.*1$2$F +Multiple Positionals: %4$*3$.*1$2$F +Multiple Positionals: %4$#6$*3$.*1$2$F +Positional before flags: %4$#*3$.*6$F +Positional after flags: %#4$*3$.*6$F +Zero is a flag: %04$F +Out of range, but should select correctly: %64$F +Multiple args: %4$F %1$F %*3$7$F +Reused arg: %p %d %1$F diff --git a/MakeTools/Test/Log.msg b/MakeTools/Test/Log.msg new file mode 100755 index 0000000..43c4a98 --- /dev/null +++ b/MakeTools/Test/Log.msg @@ -0,0 +1,168 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +#[ICS VERSION STRING: unknown] +# +# $Source: /cvs/ics/MakeTools/Test/Log.msg,v $ +# $Name: $ +# $Revision: 1.3 $ +# $Date: 2015/01/28 20:18:11 $ +# + +# +# Message Definitions for Log module +# + +# WHEN TRANSLATING, ALSO UPDATE DUMMY MESSAGES IN Log_Subsystem.cpp + +[Module] +Name=Log + +[Message] +Name=TRUNCATED +Severity=Warning +Description.English="Message truncated, out of Log Resources" +Response.English="Some log text has been discarded" +Correction.English="To avoid the loss of log text, reduce the logging options enabled" + +[Message] +Name=TRAP_FAILED +Severity=Warning +Arglist=erc +Description.English="Unable to Send Trap: %C" + +[String] +Name=RESPONSE +Comment=Prefix for Response part of message +String.English="Response: " + +[String] +Name=CORRECTION +Comment=Prefix for Correction part of message +String.English="Correction: " + +[String] +Name=TASK +Comment=Task Id reporting message +String.English="Task" + +[String] +Name=FILENAME +Comment=Source file generating message +String.English="Filename" + +[String] +Name=LINE +Comment=Source file line number generating message +String.English="Line" + +[String] +Name=NULL +Comment=marker to indicate a NULL %s or %F argument was passed +String.English="(NULL)" + +[String] +Name=NOMEMORY +Comment=marker to indicate a LOG_ALLOC_ERROR argument was passed +String.English="(No Memory)" + +[String] +Name=SEV_DUMP +Comment=1 character indication of severity +String.English="D" + +[String] +Name=SEV_FATAL +Comment=1 character indication of severity +String.English="F" + +[String] +Name=SEV_ERROR +Comment=1 character indication of severity +String.English="E" + +[String] +Name=SEV_ALARM +Comment=1 character indication of severity +String.English="A" + +[String] +Name=SEV_WARNING +Comment=1 character indication of severity +String.English="W" + +[String] +Name=SEV_PARTIAL +Comment=1 character indication of severity +String.English="p" + +[String] +Name=SEV_CONFIG +Comment=1 character indication of severity +String.English="C" + +[String] +Name=SEV_PROGRAM_INFO +Comment=1 character indication of severity +String.English="I" + +[String] +Name=SEV_PERIODIC_INFO +Comment=1 character indication of severity +String.English="P" + +[String] +Name=SEV_DEBUG1 +Comment=1 character indication of severity +String.English="1" + +[String] +Name=SEV_DEBUG2 +Comment=1 character indication of severity +String.English="2" + +[String] +Name=SEV_DEBUG3 +Comment=1 character indication of severity +String.English="3" + +[String] +Name=SEV_DEBUG4 +Comment=1 character indication of severity +String.English="4" + +[String] +Name=SEV_DEBUG5 +Comment=1 character indication of severity +String.English="5" + +[String] +Name=SEV_PURGE +Comment=1 character indication of severity +String.English="X" diff --git a/MakeTools/Test/Makefile b/MakeTools/Test/Makefile new file mode 100644 index 0000000..39f6959 --- /dev/null +++ b/MakeTools/Test/Makefile @@ -0,0 +1,49 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** +# Makefile for Test + +# Include Make Control Settings +include $(TL_DIR)/$(PROJ_FILE_DIR)/Makesettings.project + +DS_SUBPROJECTS = +DSP_SOURCES= Makefile \ + Err.msg \ + Log.msg \ + Osa.msg \ + Test.msg \ + UiUtil.msg \ + buildmsgs_test.sh \ +DIRS = expect +INCLUDE_TARGETS = + +include $(TL_DIR)/$(PROJ_FILE_DIR)/Makerules.project + +runtest:: + $(SHELL) buildmsgs_test.sh + diff --git a/MakeTools/Test/Osa.msg b/MakeTools/Test/Osa.msg new file mode 100755 index 0000000..55ac6d4 --- /dev/null +++ b/MakeTools/Test/Osa.msg @@ -0,0 +1,51 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +#[ICS VERSION STRING: unknown] +# +# $Source: /cvs/ics/MakeTools/Test/Osa.msg,v $ +# $Name: $ +# $Revision: 1.3 $ +# $Date: 2015/01/28 20:18:11 $ +# + +# +# Message Definitions for Osa module +# + +[Module] +Name=Osa + +[Message] +Name=ASSERT_FAILED +Severity=Fatal +Arglist=expr: text for failed expression +Description.English="Assertion Failed: %s" +Response.English="Firmware will dump and reboot" +Correction.English="Save the Dump and send it to support" diff --git a/MakeTools/Test/README b/MakeTools/Test/README new file mode 100644 index 0000000..9e89e9f --- /dev/null +++ b/MakeTools/Test/README @@ -0,0 +1 @@ +Test cases for buildmsgs.pl diff --git a/MakeTools/Test/Test.msg b/MakeTools/Test/Test.msg new file mode 100755 index 0000000..1c5e260 --- /dev/null +++ b/MakeTools/Test/Test.msg @@ -0,0 +1,109 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +#[ICS VERSION STRING: unknown] +# +# $Source: /cvs/ics/MakeTools/Test/Test.msg,v $ +# $Name: $ +# $Revision: 1.4 $ +# $Date: 2015/01/28 20:18:11 $ +# + +# +# Message Definitions for Osa module +# + +[Module] +Name=Osa + +[Message] +Name=ASSERT_FAILED +Severity=Fatal +Arglist=expr: text for failed expression +Description.English="Assertion Failed: %s" +Response.English="Firmware will dump and reboot" +Correction.English="Save the Dump and send it to support" + +[Message] +Name=TEST1 +Severity=Fatal +Arglist=obj1 +Description.English="%F" # strip this +[Message] +Name=TEST2 +Severity=Fatal +Arglist=arg1, arg2, obj1, obj2 +Description.English="%3$F %4$F" +[Message] +Name=TEST3 +Severity=Fatal +Arglist=obj1, obj2, width1, width2 +Description.English="%1$*3$F %2$*4$F" +[Message] +Name=TEST4 +Severity=Fatal +Arglist=obj1, obj2, width1, width2 +Description.English="%1$.*3$F %2$.*4$F" +[Message] +Name=TEST5 +Severity=Fatal +Arglist=width1, obj1, width2, obj2 +Description.English="%*F %*F" +[Message] +Name=TEST6 +Severity=Fatal +Arglist=width1, obj1, width2, obj2 +Description.English="%.*F %.*F" +[Message] +Name=TEST7 +Severity=Fatal +Arglist=width1a, width1b, obj1, width2a, width2b, obj2 +Description.English="%*.*F %*.*F" +[Message] +Name=TEST8 +Severity=Fatal +Arglist=dec, obj2, width1, width2 +Description.English="%*3$2$F %*4$1$d" + +[Message] +Name=TEST9 +Severity=Partial +Description.English="#" +[Message] +Name=TEST10 +Severity=Partial +Description.English="\"#" +[Message] +Name=TEST11 +Severity=Partial +Description.English="#\"" +[Message] +Name=TEST12 +Severity=Partial +Description.English="\" #" # strip diff --git a/MakeTools/Test/UiUtil.msg b/MakeTools/Test/UiUtil.msg new file mode 100755 index 0000000..e2aacab --- /dev/null +++ b/MakeTools/Test/UiUtil.msg @@ -0,0 +1,249 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +#[ICS VERSION STRING: unknown] +# +# $Source: /cvs/ics/MakeTools/Test/UiUtil.msg,v $ +# $Name: $ +# $Revision: 1.3 $ +# $Date: 2015/01/28 20:18:11 $ +# + +# +# Message Definitions for UiUtil module +# + +[Module] +Name=UiUtil + +[Message] +Name=INVALID_UTC_OFFSET +Severity=Partial +Arglist=hour: invalid hour, minute: invalid minutes, minHour: low hours, + maxHour: high hours, minMinute: low minutes, maxMinute: high minutes +Description.English="Invalid UTC Offset: %d:%2.2d" +Correction.English="UTC Offset must be %3$d:%4$2.2d to %5$d:%6$2.2d" + +[Message] +Name=INVALID_DST_OFFSET +Severity=Partial +Arglist=offset: invalid value, min: range low, max: range high +Description.English="Invalid Daylight Savings Time Offset: %d" +Correction.English="Daylight Savings Time Offset must be %2$d to %3$d" + +[Message] +Name=INVALID_ZERO_DSTEND +Severity=Partial +Description.English="Daylight Savings Start specified without Daylight Savings End" + +[Message] +Name=INVALID_DSTSTART_MON +Severity=Partial +Arglist=month: start month name +Description.English="Invalid Daylight Savings Start: %S" +Correction.English="Cannot be Jan nor Feb" + +[Message] +Name=INVALID_DSTEND_MON +Severity=Partial +Arglist=month: end month name +Description.English="Invalid Daylight Savings End: %S" +Correction.English="Cannot be Jan, Feb, nor Dec" + +[Message] +Name=INVALID_DSTRANGE +Severity=Partial +Arglist=start: month name, end: month name +Description.English="Invalid Daylight Savings Range (%S-%S)" +Correction.English="Start must be a month prior to End" + +[Message] +Name=INVALID_DSTEND_HOUR +Severity=Partial +Arglist=hour: end hour, offset: dst Offset +Description.English="Invalid Daylight Savings End Hour: %d" +Correction.English="Cannot be within %2$d hours of start nor end of day" + +[Message] +Name=INVALID_ZERO_DSTSTART +Severity=Partial +Description.English="Daylight Savings End specified without Daylight Savings Start" + +[Message] +Name=INVALID_NONZERO_DSTOFFSET +Severity=Partial +Description.English="Daylight Savings Offset specified without Daylight Savings Start/End" + +[Message] +Name=INVALID_TIMEZONE_INFO +Severity=Partial +Description.English="Invalid TimeZone Information" +Response.English="The TimeZone Information will not be changed" +Correction.English="Correct the Information and re-enter as needed" + +[Message] +Name=INVALID_DST_MON +Severity=Partial +Arglist=month: month name +Description.English="Invalid Daylight Savings Transition Month: %S" +Correction.English="Cannot be Feb" + +[Message] +Name=INVALID_DST_MONNUM +Severity=Partial +Arglist=month: month number, min: mon low, max: mon high +Description.English="Invalid Daylight Savings Month: %d" +Correction.English="Must be %2$d to %3$d" + +[Message] +Name=INVALID_DST_DAYNUM +Severity=Partial +Arglist=day: day number, min: day low, max: day high +Description.English="Invalid Daylight Savings Day: %d" +Correction.English="Must be %2$d to %3$d" + +[Message] +Name=INVALID_DST_WEEKNUM +Severity=Partial +Arglist=week: week number, min: week low, max: week high +Description.English="Invalid Daylight Savings Week: %d" +Correction.English="Must be %2$d to %3$d" + +[Message] +Name=INVALID_DST_WDAYNUM +Severity=Partial +Arglist=wday: wday number, min: wday low, max: wday high +Description.English="Invalid Daylight Savings Weekday: %d" +Correction.English="Must be %2$d to %3$d" + +[Message] +Name=INVALID_DST_HOURNUM +Severity=Partial +Arglist=hour: hour number, min: hour low, max: hour high +Description.English="Invalid Daylight Savings Hour: %d" +Correction.English="Must be %2$d to %3$d" + +[String] +Name=DATEFORMAT +Comment=format to use for real Dates +Arglist=year: (4 digit), mon, day +String.English="%4.4d/%2.2d/%2.2d" +# US Style would be: "%2$2.2d/%3$2.2d/%1$4.4d" + +[String] +Name=BOOTDELTAFORMAT +Comment=format to use days since boot +Arglist=daysUp: days since boot (up to 30 years = 10957) +String.English="%5d" + +[String] +Name=TIMEFORMAT +Comment=format to use for Time +Arglist=hour, min, sec, msec, usec, DstFlag +String.English="%2.2d:%2.2d:%2.2d.%3.3d%6$1.1S" + +[String] +Name=DSTFLAG_BOOT +Comment=1 character, mark time as since boot +String.English="B" + +[String] +Name=DSTFLAG_UTC +Comment=1 character, mark time as UTC +String.English="U" + +[String] +Name=DSTFLAG_STD +Comment=1 character, mark time as standard +String.English="S" + +[String] +Name=DSTFLAG_DST +Comment=1 character, mark time as Daylight Savings +String.English="D" + +[String] +Name=JAN +Comment=January abbreviation +String.English="Jan" + +[String] +Name=FEB +Comment=February abbreviation +String.English="Feb" + +[String] +Name=MAR +Comment=March abbreviation +String.English="Mar" + +[String] +Name=APR +Comment=April abbreviation +String.English="Apr" + +[String] +Name=MAY +Comment=May abbreviation +String.English="May" + +[String] +Name=JUN +Comment=June abbreviation +String.English="Jun" + +[String] +Name=JUL +Comment=July abbreviation +String.English="Jul" + +[String] +Name=AUG +Comment=August abbreviation +String.English="Aug" + +[String] +Name=SEP +Comment=September abbreviation +String.English="Sep" + +[String] +Name=OCT +Comment=October abbreviation +String.English="Oct" + +[String] +Name=NOV +Comment=November abbreviation +String.English="Nov" + +[String] +Name=DEC +Comment=December abbreviation +String.English="Dec" diff --git a/MakeTools/Test/buildmsgs_test.sh b/MakeTools/Test/buildmsgs_test.sh new file mode 100755 index 0000000..6287c1b --- /dev/null +++ b/MakeTools/Test/buildmsgs_test.sh @@ -0,0 +1,135 @@ +#! /bin/bash +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +failed=0 +tests=0 +log=test.$$ +cmd="perl ../buildmsgs.pl" + +error() { + echo $* + [ -s $log ] && cat $log + let failed+=1 +} + +test_file() { + let tests+=1 + out=`basename $1 .msg`_Messages + if $cmd $1 > $log 2>&1 ; then + if [ -s $log ] ; then + error "Unexpected output from buildmsgs.pl $1" + return 1 + else + for file in $out.*; do + echo "diff expect/$file $file" > $log + diff expect/$file $file >> $log + if [ $? != 0 ]; then + error "$file" + return 1 + fi + done + fi + else + error "buildmsgs.pl $1 FAILED" + return 1 + fi + rm $out.* + return 0 +} + +# regression tests +for msg in *.msg; do + echo -n "$msg: " + if test_file $msg; then + echo "PASSED" + else + echo "FAILED" + fi +done + +# check error output +echo -n "Errors: " +let tests+=1 +if $cmd 'ErrTest.in' > $log 2> 'ErrTest.err'; then + error "No error returned" + echo "FAILED" +elif [ -s $log ]; then + error "Unexpected output to stdout" + echo "FAILED" +elif [ -f "ErrTest_Messages.c" ] || [ -f "ErrTest_Messages.h" ]; then + error "Output files created" + echo "FAILED" +else + echo "diff expect/ErrTest.err ErrTest.err" > $log + diff expect/ErrTest.err ErrTest.err >> $log + if [ $? != 0 ]; then + error "ErrTest.err" + echo "FAILED" + else + echo "PASSED" + rm ErrTest.err + fi +fi + +# check format strings +echo -n "Formats: " +let tests+=1 +if $cmd --test < Formats.in > Formats.out 2> $log ; then + if [ -s $log ]; then + error "Unexpect output to stderr" + echo "FAILED" + else + echo "diff expect/Formats.out Formats.out" > $log + diff expect/Formats.out Formats.out >> $log + if [ $? != 0 ]; then + error "Formats.out" + echo "FAILED" + else + echo "PASSED" + rm Formats.out + fi + fi +else + error "Error returned" + echo "FAILED" +fi + +let passed=tests-failed +echo "$tests Tests Run, $passed Passed, $failed Failed" + +rm $log + +if [ $failed != 0 ] +then + exit 1 +else + exit 0 +fi + diff --git a/MakeTools/Test/expect/ErrTest.err b/MakeTools/Test/expect/ErrTest.err new file mode 100755 index 0000000..1b2ca6c --- /dev/null +++ b/MakeTools/Test/expect/ErrTest.err @@ -0,0 +1,65 @@ +ErrTest.in:10: ERROR: Module Test: Only one Module section is permitted +ErrTest.in:14: ERROR: Module Again: Only one Module section is permitted +ErrTest.in:15: ERROR: Module: Name must be an identifier +ErrTest.in:17: ERROR: Module: Only one Module section is permitted +ErrTest.in:17: ERROR: Module: Missing Name attribute +ErrTest.in:18: ERROR: Module: Name must be an identifier +ErrTest.in:20: ERROR: Module: Only one Module section is permitted +ErrTest.in:20: ERROR: Module: Missing Name attribute +ErrTest.in:21: ERROR: Module: Name must be no more than 6 characters +ErrTest.in:23: ERROR: Module: Only one Module section is permitted +ErrTest.in:23: ERROR: Module: Missing Name attribute +ErrTest.in:24: ERROR: Module: Name must be no more than 6 characters +ErrTest.in:27: ERROR: Module: Only one Module section is permitted +ErrTest.in:27: ERROR: Module: Missing Name attribute +ErrTest.in:30: ERROR: Module Good4U: Only one Module section is permitted +ErrTest.in:32: ERROR: Module AName: Duplicate attribute Name +ErrTest.in:34: ERROR: Module AName: Only one Module section is permitted +ErrTest.in:38: ERROR: Module WithUC: Only one Module section is permitted +ErrTest.in:41: ERROR: Module DupUc: Duplicate attribute Ucname +ErrTest.in:58: ERROR: Message MIN_MESSAGE: Only one Module section is permitted +ErrTest.in:58: ERROR: Message MIN_MESSAGE: Duplicate Message definition with Name=MIN_MESSAGE +ErrTest.in:67: ERROR: Message: Missing Name attribute +ErrTest.in:68: ERROR: Message: Name must be an uppercase identifier +ErrTest.in:72: ERROR: Message: Missing Name attribute +ErrTest.in:73: ERROR: Message: Name must be an uppercase identifier +ErrTest.in:77: ERROR: Message: Missing Name attribute +ErrTest.in:78: ERROR: Message: Name must be an uppercase identifier +ErrTest.in:82: ERROR: Message: Missing Name attribute +ErrTest.in:90: ERROR: Message MIN_MESSAGE: Duplicate Message definition with Name=MIN_MESSAGE +ErrTest.in:99: ERROR: Message MULTIPLE_COMMENTS: Duplicate attribute Comment +ErrTest.in:145: ERROR: Message ARG_7: Arglist must be no more than 6 elements +ErrTest.in:149: ERROR: Message ARG_7: Missing Arglist (7 args used) +ErrTest.in:154: ERROR: Message MISSING_ARGS: Missing Arglist (7 args used) +ErrTest.in:160: WARNING: Message EXTRA_ARGS: Extra arguments (6) for format (5 args used) +ErrTest.in:166: ERROR: Message INSUFFICIENT_ARGS: Insufficient arguments (4) for format (5 args used) +ErrTest.in:182: WARNING: Message BAD_ARG_NAMES: No name given for BAD_ARG_NAMES argument 1, defaulting to arg1 +ErrTest.in:182: WARNING: Message BAD_ARG_NAMES: No name given for BAD_ARG_NAMES argument 3, defaulting to arg3 +ErrTest.in:182: WARNING: Message BAD_ARG_NAMES: No name given for BAD_ARG_NAMES argument 4, defaulting to arg4 +ErrTest.in:234: ERROR: Message UNIT_7: Unitarg must be <= 6 +ErrTest.in:245: ERROR: Message UNIT_OUT_OF_LIST: Insufficient arguments (5) for UnitArg (6) +ErrTest.in:248: ERROR: Message BAD_UNIT_ARG_VAL: Non-integer value six for Unitarg +ErrTest.in:263: ERROR: Message TRAP_NUM: Trapfunc must be an identifier +ErrTest.in:269: ERROR: Message TRAP_SPACE: Trapfunc must be an identifier +ErrTest.in:275: ERROR: Message TRAP_PUNC: Trapfunc must be an identifier +ErrTest.in:286: WARNING: Message SEV_NONE: Missing Severity attribute +ErrTest.in:338: ERROR: Message SEV_BAD: Invalid Severity +ErrTest.in:344: WARNING: Message SEV_BAD: Missing Severity attribute +ErrTest.in:348: ERROR: Message MISSING_DESCRIPTION: Missing Description attribute +ErrTest.in:351: ERROR: Message BAD_LANGUAGE: Unknown language 'BORKBORK' +ErrTest.in:357: ERROR: Message MISSING_LANGUAGE: Missing language +ErrTest.in:362: ERROR: Message MISSING_LANGUAGE: Missing Description attribute +ErrTest.in:366: ERROR: Message FMT_1: Format mixes positional and non positional parameters +ErrTest.in:372: ERROR: Message FMT_2: Format mixes positional and non positional parameters +ErrTest.in:374: ERROR: Message FMT_2: Insufficient arguments (4) for format (5 args used) +ErrTest.in:378: ERROR: Message FMT_3: Format mixes positional and non positional parameters +ErrTest.in:384: ERROR: Message FMT_4: Format mixes positional and non positional parameters +ErrTest.in:387: ERROR: Message FMT_4: Insufficient arguments (4) for format (5 args used) +ErrTest.in:401: WARNING: Message FMT_6: Extra arguments (4) for format (3 args used) +ErrTest.in:404: ERROR: Message FMT_7: Invalid format specifier at "%f"" +ErrTest.in:411: WARNING: Message FMT_8: Repeated flag '#' in format specifier +ErrTest.in:431: ERROR: Message FMT_11: Multiple positional specifiers '4$' and '.*1$' in format specifier +ErrTest.in:447: ERROR: String: Missing Name attribute +ErrTest.in:450: ERROR: String MISSING_STRING: Missing String attribute +ErrTest.in:455: ERROR: String MAYBE_NOT: Missing String attribute +ErrTest.in: 8 warnings, 56 errors diff --git a/MakeTools/Test/expect/Err_Messages.c b/MakeTools/Test/expect/Err_Messages.c new file mode 100644 index 0000000..d245419 --- /dev/null +++ b/MakeTools/Test/expect/Err_Messages.c @@ -0,0 +1,125 @@ +/* BEGIN_ICS_COPYRIGHT7 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT7 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ +/*! + @file Err/Err_Messages.c + @brief Nationalizable Strings and Messages for Err Package generated from Err.msg + */ + +#include "Err_Messages.h" + + +/*! +Module specific string table, referenced by Log_StringId_t. +*/ + +static Log_StringEntry_t err_stringTable[] = +{ + { ERR_STR_MODNAME, /* first entry must be 1-6 character package name */ + { /* LOG_LANG_ENGLISH */ "Err", + }, + }, + { ERR_STR_OK, /* ERR_OK text */ + { /* LOG_LANG_ENGLISH */ "Success", + }, + }, + { ERR_STR_FAILED_CONSTRUCTOR, /* ERR_FAILED_CONSTRUCTOR and ERR_KIND_FAILED_CONSTRUCTORtext */ + { /* LOG_LANG_ENGLISH */ "Failed Constructor", + }, + }, + { ERR_STR_END_OF_DATA, /* ERR_END_OF_DATA and ERR_KIND_END_OF_DATA text */ + { /* LOG_LANG_ENGLISH */ "End of Data", + }, + }, + { ERR_STR_IO_ERROR, /* ERR_IO_ERROR and ERR_KIND_IO_ERROR text */ + { /* LOG_LANG_ENGLISH */ "IO Error", + }, + }, + { ERR_STR_INVALID, /* ERR_INVALID and ERR_KIND_INVALID text */ + { /* LOG_LANG_ENGLISH */ "Invalid", + }, + }, + { ERR_STR_MISSING, /* ERR_MISSING and ERR_KIND_MISSING text */ + { /* LOG_LANG_ENGLISH */ "Missing", + }, + }, + { ERR_STR_DUPLICATE, /* ERR_DUPLICATE and ERR_KIND_DUPLICATE text */ + { /* LOG_LANG_ENGLISH */ "Duplicate", + }, + }, + { ERR_STR_OVERFLOW, /* ERR_OVERFLOW and ERR_KIND_OVERFLOW text */ + { /* LOG_LANG_ENGLISH */ "Overflow", + }, + }, + { ERR_STR_TIMEOUT, /* ERR_TIMEOUT and ERR_KIND_TIMEOUT text */ + { /* LOG_LANG_ENGLISH */ "Timeout", + }, + }, + { ERR_STR_UNDERFLOW, /* ERR_UNDERFLOW and ERR_KIND_UNDERFLOW text */ + { /* LOG_LANG_ENGLISH */ "Underflow", + }, + }, + { ERR_STR_OUT_OF_RESOURCES, /* ERR_OUT_OF_RESOURCES and ERR_KIND_OUT_OF_RESOURCES text */ + { /* LOG_LANG_ENGLISH */ "Out of Resources", + }, + }, + { ERR_STR_UNKNOWN, /* ERR_KIND_UNKNOWN text */ + { /* LOG_LANG_ENGLISH */ "Unknown", + }, + }, + { ERR_STR_BAD, /* invalid Err_Code_t value for Err module defined errors */ + { /* LOG_LANG_ENGLISH */ "Bad", + }, + }, +}; + +/*! +Add String table to logging subsystem's tables. + +This must be run early in the boot to initialize tables prior to +any logging functions being available. + +@return None + +@heading Concurrency Considerations + Must be run once, early in boot + +@heading Special Cases and Error Handling + None + +@see Log_AddStringTable +*/ + +void +Err_AddMessages() +{ + Log_AddStringTable(MOD_ERR, err_stringTable, + GEN_NUMENTRIES(err_stringTable)); +} diff --git a/MakeTools/Test/expect/Err_Messages.h b/MakeTools/Test/expect/Err_Messages.h new file mode 100644 index 0000000..734ee22 --- /dev/null +++ b/MakeTools/Test/expect/Err_Messages.h @@ -0,0 +1,62 @@ +/* BEGIN_ICS_COPYRIGHT7 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT7 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ +#ifndef ERR_MESSAGES_H_INCLUDED +#define ERR_MESSAGES_H_INCLUDED + +/*! + @file Err/Err_Messages.h + @brief Nationalizable Strings and Messages for Err Package generated from Err.msg + */ + +#include "Gen_Arch.h" +#include "Gen_Macros.h" +#include "Log.h" + + +/* Constant Strings for use as substitutionals in Messages */ +#define ERR_STR_MODNAME LOG_BUILD_STRID(MOD_ERR, 0) +#define ERR_STR_OK LOG_BUILD_STRID(MOD_ERR, 1) +#define ERR_STR_FAILED_CONSTRUCTOR LOG_BUILD_STRID(MOD_ERR, 2) +#define ERR_STR_END_OF_DATA LOG_BUILD_STRID(MOD_ERR, 3) +#define ERR_STR_IO_ERROR LOG_BUILD_STRID(MOD_ERR, 4) +#define ERR_STR_INVALID LOG_BUILD_STRID(MOD_ERR, 5) +#define ERR_STR_MISSING LOG_BUILD_STRID(MOD_ERR, 6) +#define ERR_STR_DUPLICATE LOG_BUILD_STRID(MOD_ERR, 7) +#define ERR_STR_OVERFLOW LOG_BUILD_STRID(MOD_ERR, 8) +#define ERR_STR_TIMEOUT LOG_BUILD_STRID(MOD_ERR, 9) +#define ERR_STR_UNDERFLOW LOG_BUILD_STRID(MOD_ERR, 10) +#define ERR_STR_OUT_OF_RESOURCES LOG_BUILD_STRID(MOD_ERR, 11) +#define ERR_STR_UNKNOWN LOG_BUILD_STRID(MOD_ERR, 12) +#define ERR_STR_BAD LOG_BUILD_STRID(MOD_ERR, 13) + +GEN_EXTERNC(extern void Err_AddMessages();) + +#endif /* ERR_MESSAGES_H_INCLUDED */ diff --git a/MakeTools/Test/expect/Log_Messages.c b/MakeTools/Test/expect/Log_Messages.c new file mode 100644 index 0000000..a82e6cb --- /dev/null +++ b/MakeTools/Test/expect/Log_Messages.c @@ -0,0 +1,204 @@ +/* BEGIN_ICS_COPYRIGHT7 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT7 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ +/*! + @file Log/Log_Messages.c + @brief Nationalizable Strings and Messages for Log Package generated from Log.msg + */ + +#include "Log_Messages.h" + + +/*! +Module specific message table, referenced by Log_MessageId_t. + +The entries in the table must provide equivalent argument usage for +all languages. Argument usage in format strings is used to determine +which arguments may need to be freed +*/ + +static Log_MessageEntry_t log_messageTable[] = +{ + { LOG_MSG_TRUNCATED, + 0, /* argument number which holds unit number, 0 -> none */ + LOG_TRAP_NONE, /* trap func associated with message */ + /* FUTURE - Binary Data */ + /* Arguments: None */ + { /* Language Specific Entries */ + { /* LOG_LANG_ENGLISH */ + /* description */ "Message truncated, out of Log Resources", + /* response */ "Some log text has been discarded", + /* correction */ "To avoid the loss of log text, reduce the logging options enabled", + }, + }, + }, + { LOG_MSG_TRAP_FAILED, + 0, /* argument number which holds unit number, 0 -> none */ + LOG_TRAP_NONE, /* trap func associated with message */ + /* FUTURE - Binary Data */ + /* Arguments: + * arg1 -> erc + */ + { /* Language Specific Entries */ + { /* LOG_LANG_ENGLISH */ + /* description */ "Unable to Send Trap: %C", + /* response */ NULL, + /* correction */ NULL, + }, + }, + }, +}; + + +/*! +Module specific string table, referenced by Log_StringId_t. +*/ + +static Log_StringEntry_t log_stringTable[] = +{ + { LOG_STR_MODNAME, /* first entry must be 1-6 character package name */ + { /* LOG_LANG_ENGLISH */ "Log", + }, + }, + { LOG_STR_RESPONSE, /* Prefix for Response part of message */ + { /* LOG_LANG_ENGLISH */ "Response: ", + }, + }, + { LOG_STR_CORRECTION, /* Prefix for Correction part of message */ + { /* LOG_LANG_ENGLISH */ "Correction: ", + }, + }, + { LOG_STR_TASK, /* Task Id reporting message */ + { /* LOG_LANG_ENGLISH */ "Task", + }, + }, + { LOG_STR_FILENAME, /* Source file generating message */ + { /* LOG_LANG_ENGLISH */ "Filename", + }, + }, + { LOG_STR_LINE, /* Source file line number generating message */ + { /* LOG_LANG_ENGLISH */ "Line", + }, + }, + { LOG_STR_NULL, /* marker to indicate a NULL %s or %F argument was passed */ + { /* LOG_LANG_ENGLISH */ "(NULL)", + }, + }, + { LOG_STR_NOMEMORY, /* marker to indicate a LOG_ALLOC_ERROR argument was passed */ + { /* LOG_LANG_ENGLISH */ "(No Memory)", + }, + }, + { LOG_STR_SEV_DUMP, /* 1 character indication of severity */ + { /* LOG_LANG_ENGLISH */ "D", + }, + }, + { LOG_STR_SEV_FATAL, /* 1 character indication of severity */ + { /* LOG_LANG_ENGLISH */ "F", + }, + }, + { LOG_STR_SEV_ERROR, /* 1 character indication of severity */ + { /* LOG_LANG_ENGLISH */ "E", + }, + }, + { LOG_STR_SEV_ALARM, /* 1 character indication of severity */ + { /* LOG_LANG_ENGLISH */ "A", + }, + }, + { LOG_STR_SEV_WARNING, /* 1 character indication of severity */ + { /* LOG_LANG_ENGLISH */ "W", + }, + }, + { LOG_STR_SEV_PARTIAL, /* 1 character indication of severity */ + { /* LOG_LANG_ENGLISH */ "p", + }, + }, + { LOG_STR_SEV_CONFIG, /* 1 character indication of severity */ + { /* LOG_LANG_ENGLISH */ "C", + }, + }, + { LOG_STR_SEV_PROGRAM_INFO, /* 1 character indication of severity */ + { /* LOG_LANG_ENGLISH */ "I", + }, + }, + { LOG_STR_SEV_PERIODIC_INFO, /* 1 character indication of severity */ + { /* LOG_LANG_ENGLISH */ "P", + }, + }, + { LOG_STR_SEV_DEBUG1, /* 1 character indication of severity */ + { /* LOG_LANG_ENGLISH */ "1", + }, + }, + { LOG_STR_SEV_DEBUG2, /* 1 character indication of severity */ + { /* LOG_LANG_ENGLISH */ "2", + }, + }, + { LOG_STR_SEV_DEBUG3, /* 1 character indication of severity */ + { /* LOG_LANG_ENGLISH */ "3", + }, + }, + { LOG_STR_SEV_DEBUG4, /* 1 character indication of severity */ + { /* LOG_LANG_ENGLISH */ "4", + }, + }, + { LOG_STR_SEV_DEBUG5, /* 1 character indication of severity */ + { /* LOG_LANG_ENGLISH */ "5", + }, + }, + { LOG_STR_SEV_PURGE, /* 1 character indication of severity */ + { /* LOG_LANG_ENGLISH */ "X", + }, + }, +}; + +/*! +Add String table to logging subsystem's tables. + +This must be run early in the boot to initialize tables prior to +any logging functions being available. + +@return None + +@heading Concurrency Considerations + Must be run once, early in boot + +@heading Special Cases and Error Handling + None + +@see Log_AddStringTable +*/ + +void +Log_AddMessages() +{ + Log_AddStringTable(MOD_LOG, log_stringTable, + GEN_NUMENTRIES(log_stringTable)); + Log_AddMessageTable(MOD_LOG, log_messageTable, + GEN_NUMENTRIES(log_messageTable)); +} diff --git a/MakeTools/Test/expect/Log_Messages.h b/MakeTools/Test/expect/Log_Messages.h new file mode 100644 index 0000000..400e236 --- /dev/null +++ b/MakeTools/Test/expect/Log_Messages.h @@ -0,0 +1,85 @@ +/* BEGIN_ICS_COPYRIGHT7 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT7 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ +#ifndef LOG_MESSAGES_H_INCLUDED +#define LOG_MESSAGES_H_INCLUDED + +/*! + @file Log/Log_Messages.h + @brief Nationalizable Strings and Messages for Log Package generated from Log.msg + */ + +#include "Gen_Arch.h" +#include "Gen_Macros.h" +#include "Log.h" + +/* Messages */ +#define LOG_MSG_TRUNCATED LOG_BUILD_MSGID(MOD_LOG, 0) +#define LOG_MSG_TRAP_FAILED LOG_BUILD_MSGID(MOD_LOG, 1) + +/* Logging Macros */ +/* LOG_MSG_TRUNCATED */ +#define LOG_LOG_FINAL_TRUNCATED()\ + LOG_WARNING(MOD_LOG, LOG_MSG_TRUNCATED, 0, 0, 0, 0, 0, 0) +/* LOG_MSG_TRAP_FAILED + * Arguments: + * erc + */ +#define LOG_LOG_FINAL_TRAP_FAILED(erc)\ + LOG_WARNING(MOD_LOG, LOG_MSG_TRAP_FAILED, erc, 0, 0, 0, 0, 0) + +/* Constant Strings for use as substitutionals in Messages */ +#define LOG_STR_MODNAME LOG_BUILD_STRID(MOD_LOG, 0) +#define LOG_STR_RESPONSE LOG_BUILD_STRID(MOD_LOG, 1) +#define LOG_STR_CORRECTION LOG_BUILD_STRID(MOD_LOG, 2) +#define LOG_STR_TASK LOG_BUILD_STRID(MOD_LOG, 3) +#define LOG_STR_FILENAME LOG_BUILD_STRID(MOD_LOG, 4) +#define LOG_STR_LINE LOG_BUILD_STRID(MOD_LOG, 5) +#define LOG_STR_NULL LOG_BUILD_STRID(MOD_LOG, 6) +#define LOG_STR_NOMEMORY LOG_BUILD_STRID(MOD_LOG, 7) +#define LOG_STR_SEV_DUMP LOG_BUILD_STRID(MOD_LOG, 8) +#define LOG_STR_SEV_FATAL LOG_BUILD_STRID(MOD_LOG, 9) +#define LOG_STR_SEV_ERROR LOG_BUILD_STRID(MOD_LOG, 10) +#define LOG_STR_SEV_ALARM LOG_BUILD_STRID(MOD_LOG, 11) +#define LOG_STR_SEV_WARNING LOG_BUILD_STRID(MOD_LOG, 12) +#define LOG_STR_SEV_PARTIAL LOG_BUILD_STRID(MOD_LOG, 13) +#define LOG_STR_SEV_CONFIG LOG_BUILD_STRID(MOD_LOG, 14) +#define LOG_STR_SEV_PROGRAM_INFO LOG_BUILD_STRID(MOD_LOG, 15) +#define LOG_STR_SEV_PERIODIC_INFO LOG_BUILD_STRID(MOD_LOG, 16) +#define LOG_STR_SEV_DEBUG1 LOG_BUILD_STRID(MOD_LOG, 17) +#define LOG_STR_SEV_DEBUG2 LOG_BUILD_STRID(MOD_LOG, 18) +#define LOG_STR_SEV_DEBUG3 LOG_BUILD_STRID(MOD_LOG, 19) +#define LOG_STR_SEV_DEBUG4 LOG_BUILD_STRID(MOD_LOG, 20) +#define LOG_STR_SEV_DEBUG5 LOG_BUILD_STRID(MOD_LOG, 21) +#define LOG_STR_SEV_PURGE LOG_BUILD_STRID(MOD_LOG, 22) + +GEN_EXTERNC(extern void Log_AddMessages();) + +#endif /* LOG_MESSAGES_H_INCLUDED */ diff --git a/MakeTools/Test/expect/Osa_Messages.c b/MakeTools/Test/expect/Osa_Messages.c new file mode 100644 index 0000000..a9d3e5d --- /dev/null +++ b/MakeTools/Test/expect/Osa_Messages.c @@ -0,0 +1,103 @@ +/* BEGIN_ICS_COPYRIGHT7 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT7 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ +/*! + @file Osa/Osa_Messages.c + @brief Nationalizable Strings and Messages for Osa Package generated from Osa.msg + */ + +#include "Osa_Messages.h" + + +/*! +Module specific message table, referenced by Log_MessageId_t. + +The entries in the table must provide equivalent argument usage for +all languages. Argument usage in format strings is used to determine +which arguments may need to be freed +*/ + +static Log_MessageEntry_t osa_messageTable[] = +{ + { OSA_MSG_ASSERT_FAILED, + 0, /* argument number which holds unit number, 0 -> none */ + LOG_TRAP_NONE, /* trap func associated with message */ + /* FUTURE - Binary Data */ + /* Arguments: + * arg1 -> expr: text for failed expression + */ + { /* Language Specific Entries */ + { /* LOG_LANG_ENGLISH */ + /* description */ "Assertion Failed: %s", + /* response */ "Firmware will dump and reboot", + /* correction */ "Save the Dump and send it to support", + }, + }, + }, +}; + + +/*! +Module specific string table, referenced by Log_StringId_t. +*/ + +static Log_StringEntry_t osa_stringTable[] = +{ + { OSA_STR_MODNAME, /* first entry must be 1-6 character package name */ + { /* LOG_LANG_ENGLISH */ "Osa", + }, + }, +}; + +/*! +Add String table to logging subsystem's tables. + +This must be run early in the boot to initialize tables prior to +any logging functions being available. + +@return None + +@heading Concurrency Considerations + Must be run once, early in boot + +@heading Special Cases and Error Handling + None + +@see Log_AddStringTable +*/ + +void +Osa_AddMessages() +{ + Log_AddStringTable(MOD_OSA, osa_stringTable, + GEN_NUMENTRIES(osa_stringTable)); + Log_AddMessageTable(MOD_OSA, osa_messageTable, + GEN_NUMENTRIES(osa_messageTable)); +} diff --git a/MakeTools/Test/expect/Osa_Messages.h b/MakeTools/Test/expect/Osa_Messages.h new file mode 100644 index 0000000..a929464 --- /dev/null +++ b/MakeTools/Test/expect/Osa_Messages.h @@ -0,0 +1,59 @@ +/* BEGIN_ICS_COPYRIGHT7 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT7 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ +#ifndef OSA_MESSAGES_H_INCLUDED +#define OSA_MESSAGES_H_INCLUDED + +/*! + @file Osa/Osa_Messages.h + @brief Nationalizable Strings and Messages for Osa Package generated from Osa.msg + */ + +#include "Gen_Arch.h" +#include "Gen_Macros.h" +#include "Log.h" + +/* Messages */ +#define OSA_MSG_ASSERT_FAILED LOG_BUILD_MSGID(MOD_OSA, 0) + +/* Logging Macros */ +/* OSA_MSG_ASSERT_FAILED + * Arguments: + * expr: text for failed expression + */ +#define OSA_LOG_FINAL_ASSERT_FAILED(expr)\ + LOG_FATAL(MOD_OSA, OSA_MSG_ASSERT_FAILED, expr, 0, 0, 0, 0, 0) + +/* Constant Strings for use as substitutionals in Messages */ +#define OSA_STR_MODNAME LOG_BUILD_STRID(MOD_OSA, 0) + +GEN_EXTERNC(extern void Osa_AddMessages();) + +#endif /* OSA_MESSAGES_H_INCLUDED */ diff --git a/MakeTools/Test/expect/Test_Messages.c b/MakeTools/Test/expect/Test_Messages.c new file mode 100644 index 0000000..cad872c --- /dev/null +++ b/MakeTools/Test/expect/Test_Messages.c @@ -0,0 +1,298 @@ +/* BEGIN_ICS_COPYRIGHT7 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT7 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ +/*! + @file Osa/Test_Messages.c + @brief Nationalizable Strings and Messages for Osa Package generated from Test.msg + */ + +#include "Test_Messages.h" + + +/*! +Module specific message table, referenced by Log_MessageId_t. + +The entries in the table must provide equivalent argument usage for +all languages. Argument usage in format strings is used to determine +which arguments may need to be freed +*/ + +static Log_MessageEntry_t osa_messageTable[] = +{ + { OSA_MSG_ASSERT_FAILED, + 0, /* argument number which holds unit number, 0 -> none */ + LOG_TRAP_NONE, /* trap func associated with message */ + /* FUTURE - Binary Data */ + /* Arguments: + * arg1 -> expr: text for failed expression + */ + { /* Language Specific Entries */ + { /* LOG_LANG_ENGLISH */ + /* description */ "Assertion Failed: %s", + /* response */ "Firmware will dump and reboot", + /* correction */ "Save the Dump and send it to support", + }, + }, + }, + { OSA_MSG_TEST1, + 0, /* argument number which holds unit number, 0 -> none */ + LOG_TRAP_NONE, /* trap func associated with message */ + /* FUTURE - Binary Data */ + /* Arguments: + * arg1 -> obj1 + */ + { /* Language Specific Entries */ + { /* LOG_LANG_ENGLISH */ + /* description */ "%F", + /* response */ NULL, + /* correction */ NULL, + }, + }, + }, + { OSA_MSG_TEST2, + 0, /* argument number which holds unit number, 0 -> none */ + LOG_TRAP_NONE, /* trap func associated with message */ + /* FUTURE - Binary Data */ + /* Arguments: + * arg1 -> arg1 + * arg2 -> arg2 + * arg3 -> obj1 + * arg4 -> obj2 + */ + { /* Language Specific Entries */ + { /* LOG_LANG_ENGLISH */ + /* description */ "%3$F %4$F", + /* response */ NULL, + /* correction */ NULL, + }, + }, + }, + { OSA_MSG_TEST3, + 0, /* argument number which holds unit number, 0 -> none */ + LOG_TRAP_NONE, /* trap func associated with message */ + /* FUTURE - Binary Data */ + /* Arguments: + * arg1 -> obj1 + * arg2 -> obj2 + * arg3 -> width1 + * arg4 -> width2 + */ + { /* Language Specific Entries */ + { /* LOG_LANG_ENGLISH */ + /* description */ "%1$*3$F %2$*4$F", + /* response */ NULL, + /* correction */ NULL, + }, + }, + }, + { OSA_MSG_TEST4, + 0, /* argument number which holds unit number, 0 -> none */ + LOG_TRAP_NONE, /* trap func associated with message */ + /* FUTURE - Binary Data */ + /* Arguments: + * arg1 -> obj1 + * arg2 -> obj2 + * arg3 -> width1 + * arg4 -> width2 + */ + { /* Language Specific Entries */ + { /* LOG_LANG_ENGLISH */ + /* description */ "%1$.*3$F %2$.*4$F", + /* response */ NULL, + /* correction */ NULL, + }, + }, + }, + { OSA_MSG_TEST5, + 0, /* argument number which holds unit number, 0 -> none */ + LOG_TRAP_NONE, /* trap func associated with message */ + /* FUTURE - Binary Data */ + /* Arguments: + * arg1 -> width1 + * arg2 -> obj1 + * arg3 -> width2 + * arg4 -> obj2 + */ + { /* Language Specific Entries */ + { /* LOG_LANG_ENGLISH */ + /* description */ "%*F %*F", + /* response */ NULL, + /* correction */ NULL, + }, + }, + }, + { OSA_MSG_TEST6, + 0, /* argument number which holds unit number, 0 -> none */ + LOG_TRAP_NONE, /* trap func associated with message */ + /* FUTURE - Binary Data */ + /* Arguments: + * arg1 -> width1 + * arg2 -> obj1 + * arg3 -> width2 + * arg4 -> obj2 + */ + { /* Language Specific Entries */ + { /* LOG_LANG_ENGLISH */ + /* description */ "%.*F %.*F", + /* response */ NULL, + /* correction */ NULL, + }, + }, + }, + { OSA_MSG_TEST7, + 0, /* argument number which holds unit number, 0 -> none */ + LOG_TRAP_NONE, /* trap func associated with message */ + /* FUTURE - Binary Data */ + /* Arguments: + * arg1 -> width1a + * arg2 -> width1b + * arg3 -> obj1 + * arg4 -> width2a + * arg5 -> width2b + * arg6 -> obj2 + */ + { /* Language Specific Entries */ + { /* LOG_LANG_ENGLISH */ + /* description */ "%*.*F %*.*F", + /* response */ NULL, + /* correction */ NULL, + }, + }, + }, + { OSA_MSG_TEST8, + 0, /* argument number which holds unit number, 0 -> none */ + LOG_TRAP_NONE, /* trap func associated with message */ + /* FUTURE - Binary Data */ + /* Arguments: + * arg1 -> dec + * arg2 -> obj2 + * arg3 -> width1 + * arg4 -> width2 + */ + { /* Language Specific Entries */ + { /* LOG_LANG_ENGLISH */ + /* description */ "%*3$2$F %*4$1$d", + /* response */ NULL, + /* correction */ NULL, + }, + }, + }, + { OSA_MSG_TEST9, + 0, /* argument number which holds unit number, 0 -> none */ + LOG_TRAP_NONE, /* trap func associated with message */ + /* FUTURE - Binary Data */ + /* Arguments: None */ + { /* Language Specific Entries */ + { /* LOG_LANG_ENGLISH */ + /* description */ "#", + /* response */ NULL, + /* correction */ NULL, + }, + }, + }, + { OSA_MSG_TEST10, + 0, /* argument number which holds unit number, 0 -> none */ + LOG_TRAP_NONE, /* trap func associated with message */ + /* FUTURE - Binary Data */ + /* Arguments: None */ + { /* Language Specific Entries */ + { /* LOG_LANG_ENGLISH */ + /* description */ "\"#", + /* response */ NULL, + /* correction */ NULL, + }, + }, + }, + { OSA_MSG_TEST11, + 0, /* argument number which holds unit number, 0 -> none */ + LOG_TRAP_NONE, /* trap func associated with message */ + /* FUTURE - Binary Data */ + /* Arguments: None */ + { /* Language Specific Entries */ + { /* LOG_LANG_ENGLISH */ + /* description */ "#\"", + /* response */ NULL, + /* correction */ NULL, + }, + }, + }, + { OSA_MSG_TEST12, + 0, /* argument number which holds unit number, 0 -> none */ + LOG_TRAP_NONE, /* trap func associated with message */ + /* FUTURE - Binary Data */ + /* Arguments: None */ + { /* Language Specific Entries */ + { /* LOG_LANG_ENGLISH */ + /* description */ "\" #", + /* response */ NULL, + /* correction */ NULL, + }, + }, + }, +}; + + +/*! +Module specific string table, referenced by Log_StringId_t. +*/ + +static Log_StringEntry_t osa_stringTable[] = +{ + { OSA_STR_MODNAME, /* first entry must be 1-6 character package name */ + { /* LOG_LANG_ENGLISH */ "Osa", + }, + }, +}; + +/*! +Add String table to logging subsystem's tables. + +This must be run early in the boot to initialize tables prior to +any logging functions being available. + +@return None + +@heading Concurrency Considerations + Must be run once, early in boot + +@heading Special Cases and Error Handling + None + +@see Log_AddStringTable +*/ + +void +Osa_AddMessages() +{ + Log_AddStringTable(MOD_OSA, osa_stringTable, + GEN_NUMENTRIES(osa_stringTable)); + Log_AddMessageTable(MOD_OSA, osa_messageTable, + GEN_NUMENTRIES(osa_messageTable)); +} diff --git a/MakeTools/Test/expect/Test_Messages.h b/MakeTools/Test/expect/Test_Messages.h new file mode 100644 index 0000000..17b742e --- /dev/null +++ b/MakeTools/Test/expect/Test_Messages.h @@ -0,0 +1,154 @@ +/* BEGIN_ICS_COPYRIGHT7 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT7 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ +#ifndef OSA_MESSAGES_H_INCLUDED +#define OSA_MESSAGES_H_INCLUDED + +/*! + @file Osa/Test_Messages.h + @brief Nationalizable Strings and Messages for Osa Package generated from Test.msg + */ + +#include "Gen_Arch.h" +#include "Gen_Macros.h" +#include "Log.h" + +/* Messages */ +#define OSA_MSG_ASSERT_FAILED LOG_BUILD_MSGID(MOD_OSA, 0) +#define OSA_MSG_TEST1 LOG_BUILD_MSGID(MOD_OSA, 1) +#define OSA_MSG_TEST2 LOG_BUILD_MSGID(MOD_OSA, 2) +#define OSA_MSG_TEST3 LOG_BUILD_MSGID(MOD_OSA, 3) +#define OSA_MSG_TEST4 LOG_BUILD_MSGID(MOD_OSA, 4) +#define OSA_MSG_TEST5 LOG_BUILD_MSGID(MOD_OSA, 5) +#define OSA_MSG_TEST6 LOG_BUILD_MSGID(MOD_OSA, 6) +#define OSA_MSG_TEST7 LOG_BUILD_MSGID(MOD_OSA, 7) +#define OSA_MSG_TEST8 LOG_BUILD_MSGID(MOD_OSA, 8) +#define OSA_MSG_TEST9 LOG_BUILD_MSGID(MOD_OSA, 9) +#define OSA_MSG_TEST10 LOG_BUILD_MSGID(MOD_OSA, 10) +#define OSA_MSG_TEST11 LOG_BUILD_MSGID(MOD_OSA, 11) +#define OSA_MSG_TEST12 LOG_BUILD_MSGID(MOD_OSA, 12) + +/* Logging Macros */ +/* OSA_MSG_ASSERT_FAILED + * Arguments: + * expr: text for failed expression + */ +#define OSA_LOG_FINAL_ASSERT_FAILED(expr)\ + LOG_FATAL(MOD_OSA, OSA_MSG_ASSERT_FAILED, expr, 0, 0, 0, 0, 0) +/* OSA_MSG_TEST1 + * Arguments: + * obj1 + */ +#define OSA_LOG_FINAL_TEST1(obj1)\ + LOG_FATAL(MOD_OSA, OSA_MSG_TEST1, LOG_FORMATTABLE(obj1), 0, 0, 0, 0, 0) +/* OSA_MSG_TEST2 + * Arguments: + * arg1 + * arg2 + * obj1 + * obj2 + */ +#define OSA_LOG_FINAL_TEST2(arg1, arg2, obj1, obj2)\ + LOG_FATAL(MOD_OSA, OSA_MSG_TEST2, arg1, arg2, LOG_FORMATTABLE(obj1), LOG_FORMATTABLE(obj2), 0, 0) +/* OSA_MSG_TEST3 + * Arguments: + * obj1 + * obj2 + * width1 + * width2 + */ +#define OSA_LOG_FINAL_TEST3(obj1, obj2, width1, width2)\ + LOG_FATAL(MOD_OSA, OSA_MSG_TEST3, LOG_FORMATTABLE(obj1), LOG_FORMATTABLE(obj2), width1, width2, 0, 0) +/* OSA_MSG_TEST4 + * Arguments: + * obj1 + * obj2 + * width1 + * width2 + */ +#define OSA_LOG_FINAL_TEST4(obj1, obj2, width1, width2)\ + LOG_FATAL(MOD_OSA, OSA_MSG_TEST4, LOG_FORMATTABLE(obj1), LOG_FORMATTABLE(obj2), width1, width2, 0, 0) +/* OSA_MSG_TEST5 + * Arguments: + * width1 + * obj1 + * width2 + * obj2 + */ +#define OSA_LOG_FINAL_TEST5(width1, obj1, width2, obj2)\ + LOG_FATAL(MOD_OSA, OSA_MSG_TEST5, width1, LOG_FORMATTABLE(obj1), width2, LOG_FORMATTABLE(obj2), 0, 0) +/* OSA_MSG_TEST6 + * Arguments: + * width1 + * obj1 + * width2 + * obj2 + */ +#define OSA_LOG_FINAL_TEST6(width1, obj1, width2, obj2)\ + LOG_FATAL(MOD_OSA, OSA_MSG_TEST6, width1, LOG_FORMATTABLE(obj1), width2, LOG_FORMATTABLE(obj2), 0, 0) +/* OSA_MSG_TEST7 + * Arguments: + * width1a + * width1b + * obj1 + * width2a + * width2b + * obj2 + */ +#define OSA_LOG_FINAL_TEST7(width1a, width1b, obj1, width2a, width2b, obj2)\ + LOG_FATAL(MOD_OSA, OSA_MSG_TEST7, width1a, width1b, LOG_FORMATTABLE(obj1), width2a, width2b, LOG_FORMATTABLE(obj2)) +/* OSA_MSG_TEST8 + * Arguments: + * dec + * obj2 + * width1 + * width2 + */ +#define OSA_LOG_FINAL_TEST8(dec, obj2, width1, width2)\ + LOG_FATAL(MOD_OSA, OSA_MSG_TEST8, dec, LOG_FORMATTABLE(obj2), width1, width2, 0, 0) +/* OSA_MSG_TEST9 */ +#define OSA_LOG_PART_TEST9()\ + LOG_ADD_PART(MOD_OSA, OSA_MSG_TEST9, 0, 0, 0, 0, 0, 0) +/* OSA_MSG_TEST10 */ +#define OSA_LOG_PART_TEST10()\ + LOG_ADD_PART(MOD_OSA, OSA_MSG_TEST10, 0, 0, 0, 0, 0, 0) +/* OSA_MSG_TEST11 */ +#define OSA_LOG_PART_TEST11()\ + LOG_ADD_PART(MOD_OSA, OSA_MSG_TEST11, 0, 0, 0, 0, 0, 0) +/* OSA_MSG_TEST12 */ +#define OSA_LOG_PART_TEST12()\ + LOG_ADD_PART(MOD_OSA, OSA_MSG_TEST12, 0, 0, 0, 0, 0, 0) + +/* Constant Strings for use as substitutionals in Messages */ +#define OSA_STR_MODNAME LOG_BUILD_STRID(MOD_OSA, 0) + +GEN_EXTERNC(extern void Osa_AddMessages();) + +#endif /* OSA_MESSAGES_H_INCLUDED */ diff --git a/MakeTools/Test/expect/UiUtil_Messages.c b/MakeTools/Test/expect/UiUtil_Messages.c new file mode 100644 index 0000000..d199f49 --- /dev/null +++ b/MakeTools/Test/expect/UiUtil_Messages.c @@ -0,0 +1,431 @@ +/* BEGIN_ICS_COPYRIGHT7 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT7 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ +/*! + @file UiUtil/UiUtil_Messages.c + @brief Nationalizable Strings and Messages for UiUtil Package generated from UiUtil.msg + */ + +#include "UiUtil_Messages.h" + + +/*! +Module specific message table, referenced by Log_MessageId_t. + +The entries in the table must provide equivalent argument usage for +all languages. Argument usage in format strings is used to determine +which arguments may need to be freed +*/ + +static Log_MessageEntry_t uiUtil_messageTable[] = +{ + { UIUTIL_MSG_INVALID_UTC_OFFSET, + 0, /* argument number which holds unit number, 0 -> none */ + LOG_TRAP_NONE, /* trap func associated with message */ + /* FUTURE - Binary Data */ + /* Arguments: + * arg1 -> hour: invalid hour + * arg2 -> minute: invalid minutes + * arg3 -> minHour: low hours + * arg4 -> maxHour: high hours + * arg5 -> minMinute: low minutes + * arg6 -> maxMinute: high minutes + */ + { /* Language Specific Entries */ + { /* LOG_LANG_ENGLISH */ + /* description */ "Invalid UTC Offset: %d:%2.2d", + /* response */ NULL, + /* correction */ "UTC Offset must be %3$d:%4$2.2d to %5$d:%6$2.2d", + }, + }, + }, + { UIUTIL_MSG_INVALID_DST_OFFSET, + 0, /* argument number which holds unit number, 0 -> none */ + LOG_TRAP_NONE, /* trap func associated with message */ + /* FUTURE - Binary Data */ + /* Arguments: + * arg1 -> offset: invalid value + * arg2 -> min: range low + * arg3 -> max: range high + */ + { /* Language Specific Entries */ + { /* LOG_LANG_ENGLISH */ + /* description */ "Invalid Daylight Savings Time Offset: %d", + /* response */ NULL, + /* correction */ "Daylight Savings Time Offset must be %2$d to %3$d", + }, + }, + }, + { UIUTIL_MSG_INVALID_ZERO_DSTEND, + 0, /* argument number which holds unit number, 0 -> none */ + LOG_TRAP_NONE, /* trap func associated with message */ + /* FUTURE - Binary Data */ + /* Arguments: None */ + { /* Language Specific Entries */ + { /* LOG_LANG_ENGLISH */ + /* description */ "Daylight Savings Start specified without Daylight Savings End", + /* response */ NULL, + /* correction */ NULL, + }, + }, + }, + { UIUTIL_MSG_INVALID_DSTSTART_MON, + 0, /* argument number which holds unit number, 0 -> none */ + LOG_TRAP_NONE, /* trap func associated with message */ + /* FUTURE - Binary Data */ + /* Arguments: + * arg1 -> month: start month name + */ + { /* Language Specific Entries */ + { /* LOG_LANG_ENGLISH */ + /* description */ "Invalid Daylight Savings Start: %S", + /* response */ NULL, + /* correction */ "Cannot be Jan nor Feb", + }, + }, + }, + { UIUTIL_MSG_INVALID_DSTEND_MON, + 0, /* argument number which holds unit number, 0 -> none */ + LOG_TRAP_NONE, /* trap func associated with message */ + /* FUTURE - Binary Data */ + /* Arguments: + * arg1 -> month: end month name + */ + { /* Language Specific Entries */ + { /* LOG_LANG_ENGLISH */ + /* description */ "Invalid Daylight Savings End: %S", + /* response */ NULL, + /* correction */ "Cannot be Jan, Feb, nor Dec", + }, + }, + }, + { UIUTIL_MSG_INVALID_DSTRANGE, + 0, /* argument number which holds unit number, 0 -> none */ + LOG_TRAP_NONE, /* trap func associated with message */ + /* FUTURE - Binary Data */ + /* Arguments: + * arg1 -> start: month name + * arg2 -> end: month name + */ + { /* Language Specific Entries */ + { /* LOG_LANG_ENGLISH */ + /* description */ "Invalid Daylight Savings Range (%S-%S)", + /* response */ NULL, + /* correction */ "Start must be a month prior to End", + }, + }, + }, + { UIUTIL_MSG_INVALID_DSTEND_HOUR, + 0, /* argument number which holds unit number, 0 -> none */ + LOG_TRAP_NONE, /* trap func associated with message */ + /* FUTURE - Binary Data */ + /* Arguments: + * arg1 -> hour: end hour + * arg2 -> offset: dst Offset + */ + { /* Language Specific Entries */ + { /* LOG_LANG_ENGLISH */ + /* description */ "Invalid Daylight Savings End Hour: %d", + /* response */ NULL, + /* correction */ "Cannot be within %2$d hours of start nor end of day", + }, + }, + }, + { UIUTIL_MSG_INVALID_ZERO_DSTSTART, + 0, /* argument number which holds unit number, 0 -> none */ + LOG_TRAP_NONE, /* trap func associated with message */ + /* FUTURE - Binary Data */ + /* Arguments: None */ + { /* Language Specific Entries */ + { /* LOG_LANG_ENGLISH */ + /* description */ "Daylight Savings End specified without Daylight Savings Start", + /* response */ NULL, + /* correction */ NULL, + }, + }, + }, + { UIUTIL_MSG_INVALID_NONZERO_DSTOFFSET, + 0, /* argument number which holds unit number, 0 -> none */ + LOG_TRAP_NONE, /* trap func associated with message */ + /* FUTURE - Binary Data */ + /* Arguments: None */ + { /* Language Specific Entries */ + { /* LOG_LANG_ENGLISH */ + /* description */ "Daylight Savings Offset specified without Daylight Savings Start/End", + /* response */ NULL, + /* correction */ NULL, + }, + }, + }, + { UIUTIL_MSG_INVALID_TIMEZONE_INFO, + 0, /* argument number which holds unit number, 0 -> none */ + LOG_TRAP_NONE, /* trap func associated with message */ + /* FUTURE - Binary Data */ + /* Arguments: None */ + { /* Language Specific Entries */ + { /* LOG_LANG_ENGLISH */ + /* description */ "Invalid TimeZone Information", + /* response */ "The TimeZone Information will not be changed", + /* correction */ "Correct the Information and re-enter as needed", + }, + }, + }, + { UIUTIL_MSG_INVALID_DST_MON, + 0, /* argument number which holds unit number, 0 -> none */ + LOG_TRAP_NONE, /* trap func associated with message */ + /* FUTURE - Binary Data */ + /* Arguments: + * arg1 -> month: month name + */ + { /* Language Specific Entries */ + { /* LOG_LANG_ENGLISH */ + /* description */ "Invalid Daylight Savings Transition Month: %S", + /* response */ NULL, + /* correction */ "Cannot be Feb", + }, + }, + }, + { UIUTIL_MSG_INVALID_DST_MONNUM, + 0, /* argument number which holds unit number, 0 -> none */ + LOG_TRAP_NONE, /* trap func associated with message */ + /* FUTURE - Binary Data */ + /* Arguments: + * arg1 -> month: month number + * arg2 -> min: mon low + * arg3 -> max: mon high + */ + { /* Language Specific Entries */ + { /* LOG_LANG_ENGLISH */ + /* description */ "Invalid Daylight Savings Month: %d", + /* response */ NULL, + /* correction */ "Must be %2$d to %3$d", + }, + }, + }, + { UIUTIL_MSG_INVALID_DST_DAYNUM, + 0, /* argument number which holds unit number, 0 -> none */ + LOG_TRAP_NONE, /* trap func associated with message */ + /* FUTURE - Binary Data */ + /* Arguments: + * arg1 -> day: day number + * arg2 -> min: day low + * arg3 -> max: day high + */ + { /* Language Specific Entries */ + { /* LOG_LANG_ENGLISH */ + /* description */ "Invalid Daylight Savings Day: %d", + /* response */ NULL, + /* correction */ "Must be %2$d to %3$d", + }, + }, + }, + { UIUTIL_MSG_INVALID_DST_WEEKNUM, + 0, /* argument number which holds unit number, 0 -> none */ + LOG_TRAP_NONE, /* trap func associated with message */ + /* FUTURE - Binary Data */ + /* Arguments: + * arg1 -> week: week number + * arg2 -> min: week low + * arg3 -> max: week high + */ + { /* Language Specific Entries */ + { /* LOG_LANG_ENGLISH */ + /* description */ "Invalid Daylight Savings Week: %d", + /* response */ NULL, + /* correction */ "Must be %2$d to %3$d", + }, + }, + }, + { UIUTIL_MSG_INVALID_DST_WDAYNUM, + 0, /* argument number which holds unit number, 0 -> none */ + LOG_TRAP_NONE, /* trap func associated with message */ + /* FUTURE - Binary Data */ + /* Arguments: + * arg1 -> wday: wday number + * arg2 -> min: wday low + * arg3 -> max: wday high + */ + { /* Language Specific Entries */ + { /* LOG_LANG_ENGLISH */ + /* description */ "Invalid Daylight Savings Weekday: %d", + /* response */ NULL, + /* correction */ "Must be %2$d to %3$d", + }, + }, + }, + { UIUTIL_MSG_INVALID_DST_HOURNUM, + 0, /* argument number which holds unit number, 0 -> none */ + LOG_TRAP_NONE, /* trap func associated with message */ + /* FUTURE - Binary Data */ + /* Arguments: + * arg1 -> hour: hour number + * arg2 -> min: hour low + * arg3 -> max: hour high + */ + { /* Language Specific Entries */ + { /* LOG_LANG_ENGLISH */ + /* description */ "Invalid Daylight Savings Hour: %d", + /* response */ NULL, + /* correction */ "Must be %2$d to %3$d", + }, + }, + }, +}; + + +/*! +Module specific string table, referenced by Log_StringId_t. +*/ + +static Log_StringEntry_t uiUtil_stringTable[] = +{ + { UIUTIL_STR_MODNAME, /* first entry must be 1-6 character package name */ + { /* LOG_LANG_ENGLISH */ "UiUtil", + }, + }, + { UIUTIL_STR_DATEFORMAT, /* format to use for real Dates */ + /* Arguments: + * arg1 -> year: (4 digit) + * arg2 -> mon + * arg3 -> day + */ + { /* LOG_LANG_ENGLISH */ "%4.4d/%2.2d/%2.2d", + }, + }, + { UIUTIL_STR_BOOTDELTAFORMAT, /* format to use days since boot */ + /* Arguments: + * arg1 -> daysUp: days since boot (up to 30 years = 10957) + */ + { /* LOG_LANG_ENGLISH */ "%5d", + }, + }, + { UIUTIL_STR_TIMEFORMAT, /* format to use for Time */ + /* Arguments: + * arg1 -> hour + * arg2 -> min + * arg3 -> sec + * arg4 -> msec + * arg5 -> usec + * arg6 -> DstFlag + */ + { /* LOG_LANG_ENGLISH */ "%2.2d:%2.2d:%2.2d.%3.3d%6$1.1S", + }, + }, + { UIUTIL_STR_DSTFLAG_BOOT, /* 1 character, mark time as since boot */ + { /* LOG_LANG_ENGLISH */ "B", + }, + }, + { UIUTIL_STR_DSTFLAG_UTC, /* 1 character, mark time as UTC */ + { /* LOG_LANG_ENGLISH */ "U", + }, + }, + { UIUTIL_STR_DSTFLAG_STD, /* 1 character, mark time as standard */ + { /* LOG_LANG_ENGLISH */ "S", + }, + }, + { UIUTIL_STR_DSTFLAG_DST, /* 1 character, mark time as Daylight Savings */ + { /* LOG_LANG_ENGLISH */ "D", + }, + }, + { UIUTIL_STR_JAN, /* January abbreviation */ + { /* LOG_LANG_ENGLISH */ "Jan", + }, + }, + { UIUTIL_STR_FEB, /* February abbreviation */ + { /* LOG_LANG_ENGLISH */ "Feb", + }, + }, + { UIUTIL_STR_MAR, /* March abbreviation */ + { /* LOG_LANG_ENGLISH */ "Mar", + }, + }, + { UIUTIL_STR_APR, /* April abbreviation */ + { /* LOG_LANG_ENGLISH */ "Apr", + }, + }, + { UIUTIL_STR_MAY, /* May abbreviation */ + { /* LOG_LANG_ENGLISH */ "May", + }, + }, + { UIUTIL_STR_JUN, /* June abbreviation */ + { /* LOG_LANG_ENGLISH */ "Jun", + }, + }, + { UIUTIL_STR_JUL, /* July abbreviation */ + { /* LOG_LANG_ENGLISH */ "Jul", + }, + }, + { UIUTIL_STR_AUG, /* August abbreviation */ + { /* LOG_LANG_ENGLISH */ "Aug", + }, + }, + { UIUTIL_STR_SEP, /* September abbreviation */ + { /* LOG_LANG_ENGLISH */ "Sep", + }, + }, + { UIUTIL_STR_OCT, /* October abbreviation */ + { /* LOG_LANG_ENGLISH */ "Oct", + }, + }, + { UIUTIL_STR_NOV, /* November abbreviation */ + { /* LOG_LANG_ENGLISH */ "Nov", + }, + }, + { UIUTIL_STR_DEC, /* December abbreviation */ + { /* LOG_LANG_ENGLISH */ "Dec", + }, + }, +}; + +/*! +Add String table to logging subsystem's tables. + +This must be run early in the boot to initialize tables prior to +any logging functions being available. + +@return None + +@heading Concurrency Considerations + Must be run once, early in boot + +@heading Special Cases and Error Handling + None + +@see Log_AddStringTable +*/ + +void +UiUtil_AddMessages() +{ + Log_AddStringTable(MOD_UIUTIL, uiUtil_stringTable, + GEN_NUMENTRIES(uiUtil_stringTable)); + Log_AddMessageTable(MOD_UIUTIL, uiUtil_messageTable, + GEN_NUMENTRIES(uiUtil_messageTable)); +} diff --git a/MakeTools/Test/expect/UiUtil_Messages.h b/MakeTools/Test/expect/UiUtil_Messages.h new file mode 100644 index 0000000..15a0e47 --- /dev/null +++ b/MakeTools/Test/expect/UiUtil_Messages.h @@ -0,0 +1,217 @@ +/* BEGIN_ICS_COPYRIGHT7 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT7 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ +#ifndef UIUTIL_MESSAGES_H_INCLUDED +#define UIUTIL_MESSAGES_H_INCLUDED + +/*! + @file UiUtil/UiUtil_Messages.h + @brief Nationalizable Strings and Messages for UiUtil Package generated from UiUtil.msg + */ + +#include "Gen_Arch.h" +#include "Gen_Macros.h" +#include "Log.h" + +/* Messages */ +#define UIUTIL_MSG_INVALID_UTC_OFFSET LOG_BUILD_MSGID(MOD_UIUTIL, 0) +#define UIUTIL_MSG_INVALID_DST_OFFSET LOG_BUILD_MSGID(MOD_UIUTIL, 1) +#define UIUTIL_MSG_INVALID_ZERO_DSTEND LOG_BUILD_MSGID(MOD_UIUTIL, 2) +#define UIUTIL_MSG_INVALID_DSTSTART_MON LOG_BUILD_MSGID(MOD_UIUTIL, 3) +#define UIUTIL_MSG_INVALID_DSTEND_MON LOG_BUILD_MSGID(MOD_UIUTIL, 4) +#define UIUTIL_MSG_INVALID_DSTRANGE LOG_BUILD_MSGID(MOD_UIUTIL, 5) +#define UIUTIL_MSG_INVALID_DSTEND_HOUR LOG_BUILD_MSGID(MOD_UIUTIL, 6) +#define UIUTIL_MSG_INVALID_ZERO_DSTSTART LOG_BUILD_MSGID(MOD_UIUTIL, 7) +#define UIUTIL_MSG_INVALID_NONZERO_DSTOFFSET LOG_BUILD_MSGID(MOD_UIUTIL, 8) +#define UIUTIL_MSG_INVALID_TIMEZONE_INFO LOG_BUILD_MSGID(MOD_UIUTIL, 9) +#define UIUTIL_MSG_INVALID_DST_MON LOG_BUILD_MSGID(MOD_UIUTIL, 10) +#define UIUTIL_MSG_INVALID_DST_MONNUM LOG_BUILD_MSGID(MOD_UIUTIL, 11) +#define UIUTIL_MSG_INVALID_DST_DAYNUM LOG_BUILD_MSGID(MOD_UIUTIL, 12) +#define UIUTIL_MSG_INVALID_DST_WEEKNUM LOG_BUILD_MSGID(MOD_UIUTIL, 13) +#define UIUTIL_MSG_INVALID_DST_WDAYNUM LOG_BUILD_MSGID(MOD_UIUTIL, 14) +#define UIUTIL_MSG_INVALID_DST_HOURNUM LOG_BUILD_MSGID(MOD_UIUTIL, 15) + +/* Logging Macros */ +/* UIUTIL_MSG_INVALID_UTC_OFFSET + * Arguments: + * hour: invalid hour + * minute: invalid minutes + * minHour: low hours + * maxHour: high hours + * minMinute: low minutes + * maxMinute: high minutes + */ +#define UIUTIL_LOG_PART_INVALID_UTC_OFFSET(hour, minute, minHour, maxHour, minMinute, maxMinute)\ + LOG_ADD_PART(MOD_UIUTIL, UIUTIL_MSG_INVALID_UTC_OFFSET, hour, minute, minHour, maxHour, minMinute, maxMinute) +/* UIUTIL_MSG_INVALID_DST_OFFSET + * Arguments: + * offset: invalid value + * min: range low + * max: range high + */ +#define UIUTIL_LOG_PART_INVALID_DST_OFFSET(offset, min, max)\ + LOG_ADD_PART(MOD_UIUTIL, UIUTIL_MSG_INVALID_DST_OFFSET, offset, min, max, 0, 0, 0) +/* UIUTIL_MSG_INVALID_ZERO_DSTEND */ +#define UIUTIL_LOG_PART_INVALID_ZERO_DSTEND()\ + LOG_ADD_PART(MOD_UIUTIL, UIUTIL_MSG_INVALID_ZERO_DSTEND, 0, 0, 0, 0, 0, 0) +/* UIUTIL_MSG_INVALID_DSTSTART_MON + * Arguments: + * month: start month name + */ +#define UIUTIL_LOG_PART_INVALID_DSTSTART_MON(month)\ + LOG_ADD_PART(MOD_UIUTIL, UIUTIL_MSG_INVALID_DSTSTART_MON, month, 0, 0, 0, 0, 0) +/* UIUTIL_MSG_INVALID_DSTEND_MON + * Arguments: + * month: end month name + */ +#define UIUTIL_LOG_PART_INVALID_DSTEND_MON(month)\ + LOG_ADD_PART(MOD_UIUTIL, UIUTIL_MSG_INVALID_DSTEND_MON, month, 0, 0, 0, 0, 0) +/* UIUTIL_MSG_INVALID_DSTRANGE + * Arguments: + * start: month name + * end: month name + */ +#define UIUTIL_LOG_PART_INVALID_DSTRANGE(start, end)\ + LOG_ADD_PART(MOD_UIUTIL, UIUTIL_MSG_INVALID_DSTRANGE, start, end, 0, 0, 0, 0) +/* UIUTIL_MSG_INVALID_DSTEND_HOUR + * Arguments: + * hour: end hour + * offset: dst Offset + */ +#define UIUTIL_LOG_PART_INVALID_DSTEND_HOUR(hour, offset)\ + LOG_ADD_PART(MOD_UIUTIL, UIUTIL_MSG_INVALID_DSTEND_HOUR, hour, offset, 0, 0, 0, 0) +/* UIUTIL_MSG_INVALID_ZERO_DSTSTART */ +#define UIUTIL_LOG_PART_INVALID_ZERO_DSTSTART()\ + LOG_ADD_PART(MOD_UIUTIL, UIUTIL_MSG_INVALID_ZERO_DSTSTART, 0, 0, 0, 0, 0, 0) +/* UIUTIL_MSG_INVALID_NONZERO_DSTOFFSET */ +#define UIUTIL_LOG_PART_INVALID_NONZERO_DSTOFFSET()\ + LOG_ADD_PART(MOD_UIUTIL, UIUTIL_MSG_INVALID_NONZERO_DSTOFFSET, 0, 0, 0, 0, 0, 0) +/* UIUTIL_MSG_INVALID_TIMEZONE_INFO */ +#define UIUTIL_LOG_PART_INVALID_TIMEZONE_INFO()\ + LOG_ADD_PART(MOD_UIUTIL, UIUTIL_MSG_INVALID_TIMEZONE_INFO, 0, 0, 0, 0, 0, 0) +/* UIUTIL_MSG_INVALID_DST_MON + * Arguments: + * month: month name + */ +#define UIUTIL_LOG_PART_INVALID_DST_MON(month)\ + LOG_ADD_PART(MOD_UIUTIL, UIUTIL_MSG_INVALID_DST_MON, month, 0, 0, 0, 0, 0) +/* UIUTIL_MSG_INVALID_DST_MONNUM + * Arguments: + * month: month number + * min: mon low + * max: mon high + */ +#define UIUTIL_LOG_PART_INVALID_DST_MONNUM(month, min, max)\ + LOG_ADD_PART(MOD_UIUTIL, UIUTIL_MSG_INVALID_DST_MONNUM, month, min, max, 0, 0, 0) +/* UIUTIL_MSG_INVALID_DST_DAYNUM + * Arguments: + * day: day number + * min: day low + * max: day high + */ +#define UIUTIL_LOG_PART_INVALID_DST_DAYNUM(day, min, max)\ + LOG_ADD_PART(MOD_UIUTIL, UIUTIL_MSG_INVALID_DST_DAYNUM, day, min, max, 0, 0, 0) +/* UIUTIL_MSG_INVALID_DST_WEEKNUM + * Arguments: + * week: week number + * min: week low + * max: week high + */ +#define UIUTIL_LOG_PART_INVALID_DST_WEEKNUM(week, min, max)\ + LOG_ADD_PART(MOD_UIUTIL, UIUTIL_MSG_INVALID_DST_WEEKNUM, week, min, max, 0, 0, 0) +/* UIUTIL_MSG_INVALID_DST_WDAYNUM + * Arguments: + * wday: wday number + * min: wday low + * max: wday high + */ +#define UIUTIL_LOG_PART_INVALID_DST_WDAYNUM(wday, min, max)\ + LOG_ADD_PART(MOD_UIUTIL, UIUTIL_MSG_INVALID_DST_WDAYNUM, wday, min, max, 0, 0, 0) +/* UIUTIL_MSG_INVALID_DST_HOURNUM + * Arguments: + * hour: hour number + * min: hour low + * max: hour high + */ +#define UIUTIL_LOG_PART_INVALID_DST_HOURNUM(hour, min, max)\ + LOG_ADD_PART(MOD_UIUTIL, UIUTIL_MSG_INVALID_DST_HOURNUM, hour, min, max, 0, 0, 0) + +/* Constant Strings for use as substitutionals in Messages */ +#define UIUTIL_STR_MODNAME LOG_BUILD_STRID(MOD_UIUTIL, 0) +#define UIUTIL_STR_DATEFORMAT LOG_BUILD_STRID(MOD_UIUTIL, 1) +#define UIUTIL_STR_BOOTDELTAFORMAT LOG_BUILD_STRID(MOD_UIUTIL, 2) +#define UIUTIL_STR_TIMEFORMAT LOG_BUILD_STRID(MOD_UIUTIL, 3) +#define UIUTIL_STR_DSTFLAG_BOOT LOG_BUILD_STRID(MOD_UIUTIL, 4) +#define UIUTIL_STR_DSTFLAG_UTC LOG_BUILD_STRID(MOD_UIUTIL, 5) +#define UIUTIL_STR_DSTFLAG_STD LOG_BUILD_STRID(MOD_UIUTIL, 6) +#define UIUTIL_STR_DSTFLAG_DST LOG_BUILD_STRID(MOD_UIUTIL, 7) +#define UIUTIL_STR_JAN LOG_BUILD_STRID(MOD_UIUTIL, 8) +#define UIUTIL_STR_FEB LOG_BUILD_STRID(MOD_UIUTIL, 9) +#define UIUTIL_STR_MAR LOG_BUILD_STRID(MOD_UIUTIL, 10) +#define UIUTIL_STR_APR LOG_BUILD_STRID(MOD_UIUTIL, 11) +#define UIUTIL_STR_MAY LOG_BUILD_STRID(MOD_UIUTIL, 12) +#define UIUTIL_STR_JUN LOG_BUILD_STRID(MOD_UIUTIL, 13) +#define UIUTIL_STR_JUL LOG_BUILD_STRID(MOD_UIUTIL, 14) +#define UIUTIL_STR_AUG LOG_BUILD_STRID(MOD_UIUTIL, 15) +#define UIUTIL_STR_SEP LOG_BUILD_STRID(MOD_UIUTIL, 16) +#define UIUTIL_STR_OCT LOG_BUILD_STRID(MOD_UIUTIL, 17) +#define UIUTIL_STR_NOV LOG_BUILD_STRID(MOD_UIUTIL, 18) +#define UIUTIL_STR_DEC LOG_BUILD_STRID(MOD_UIUTIL, 19) + +/* String Formatting Macros */ +/* UIUTIL_STR_DATEFORMAT: format to use for real Dates + * Arguments: + * year: (4 digit) + * mon + * day + */ +#define UIUTIL_FMT_DATEFORMAT(buffer, year, mon, day)\ + LOG_FORMATBUF(buffer, Log_GetString(UIUTIL_STR_DATEFORMAT, (buffer).GetLanguage()), year, mon, day, 0, 0, 0) +/* UIUTIL_STR_BOOTDELTAFORMAT: format to use days since boot + * Arguments: + * daysUp: days since boot (up to 30 years = 10957) + */ +#define UIUTIL_FMT_BOOTDELTAFORMAT(buffer, daysUp)\ + LOG_FORMATBUF(buffer, Log_GetString(UIUTIL_STR_BOOTDELTAFORMAT, (buffer).GetLanguage()), daysUp, 0, 0, 0, 0, 0) +/* UIUTIL_STR_TIMEFORMAT: format to use for Time + * Arguments: + * hour + * min + * sec + * msec + * usec + * DstFlag + */ +#define UIUTIL_FMT_TIMEFORMAT(buffer, hour, min, sec, msec, usec, DstFlag)\ + LOG_FORMATBUF(buffer, Log_GetString(UIUTIL_STR_TIMEFORMAT, (buffer).GetLanguage()), hour, min, sec, msec, usec, DstFlag) + +GEN_EXTERNC(extern void UiUtil_AddMessages();) + +#endif /* UIUTIL_MESSAGES_H_INCLUDED */ diff --git a/MakeTools/build_srpms.sh b/MakeTools/build_srpms.sh new file mode 100755 index 0000000..4d4c5b9 --- /dev/null +++ b/MakeTools/build_srpms.sh @@ -0,0 +1,282 @@ +#!/bin/bash +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** +## +## build_srpms +## ----------- +## create SRPMS from an expanded source tree +## designed to work with trees built by expand_source. Supports OFED source. +## +## Usage: +## build_srpms [-c] [-d SRPMS_dir] [-s source_dir] [-p] [-V kernel_ver] [package...] +## +## Arguments: +## -c - cleanup SOURCES, SPECS and SRPMS in each package when done +## -d - SRPMS directory to create, default is ./SRPMS +## -s - source for build, default is ., ignored if package(s) specified +## -p - unapply patches for ofa_kernel +## -V - kernel version to unapply patches for, default is `uname -r` +## package - a package source directory +## Environment: + +#. $ICSBIN/funcs.sh + +Usage() +{ + # include "ERROR" in message so weeklybuild catches it in error log + echo "ERROR: build_srpms failed" >&2 + echo "Usage: build_srpms [-c] [-d SRPMS_dir] [-s source_dir] [-p] [-V kernel_ver] [package...]" >&2 + echo " -c - cleanup SOURCES, SPECS and SRPMS in each package when done" >&2 + echo " -d - SRPMS directory to create, default is ./SRPMS" >&2 + echo " -s - source for build, default is ., ignored if package(s) specified" >&2 + echo " -p - unapply patches for ofa_kernel" >&2 + echo " -V - kernel version to unapply patches for, default is `uname -r`" >&2 + echo " -v - verbose output" >&2 + echo " package - a package source directory" >&2 + exit 2 +} + +# convert $1 to an absolute path +fix_dir() +{ + if [ x$(echo $1|cut -c1) != x"/" ] + then + echo $PWD/$1 + else + echo $1 + fi +} + +build_flags= +patch_kernel=n +kernel_ver=`uname -r` +srpms_dir=$PWD/SRPMS +source_dir=$PWD +vopt="" +packages= +clean=n +while getopts cs:d:pV:v param +do + case $param in + c) clean=y;; + d) srpms_dir="$OPTARG";; + s) source_dir="$OPTARG";; + p) patch_kernel=y;; + V) kernel_ver="$OPTARG";; + v) vopt="-v";; + *) Usage;; + esac +done +shift $(($OPTIND -1)) + +unset IFS # use default so enable word expansion + +source_dir=$(fix_dir $source_dir) +srpms_dir=$(fix_dir $srpms_dir) + +echo "Building SRPMS in $srpms_dir from $source_dir..." + +mkdir -p $srpms_dir + +gettaropt() +{ + case $1 in + *.tgz) taropt=z;; + *.tar.gz) taropt=z;; + *.tar.bz2) taropt=j;; + *) echo "Unknown tarfile format: $tarfile"; exit 1 + esac +} + +checkfiles() +{ + local ret + + ret=0 + if [ ! -f SPECS/$specfile ] + then + echo "$srpm: missing file: SPECS/$specfile" + ret=1 + fi + for f in $tarfile $otherfiles + do + if [ ! -f SOURCES/$f ] + then + echo "$srpm: missing file: SOURCES/$f" + ret=1 + fi + done + return $ret +} + +if [ $# -eq 0 ] +then + #if [ ! -f package_list ] + #then + # echo "ERROR: build_srpms: package_list not found in $source_dir" >&2 + # echo "ERROR: build_srpms: source_dir must be created by expand_source" >&2 + # exit 1 + #fi + + #set -- $(grep -v '^#' package_list) + #set -- $(cat package_list) + + cd $source_dir + set -- $(ls */namemap|cut -f1 -d /) + + if [ $# -eq 0 ] + then + echo "build_srpms: ERROR: No packages found in $source_dir" >&2 + exit 1 + fi +fi + +for package in "$@" +do + ( + if [ ! -f $package/namemap -o ! -f $package/make_symlinks ] + then + echo "ERROR: build_srpms: namemap not found in $source_dir/$package" >&2 + echo "ERROR: build_srpms: source_dir must be created by expand_source" >&2 + exit 1 + fi + cd $package + bash -x ./make_symlinks + + # tail is just to be paranoid, should only be 1 non-comment line + grep -v "^#" namemap|tail -1|while read package srpm specfile srcdir tarfile otherfiles + do + echo "Generating $srpm from $package..." + + gettaropt $tarfile + + case $srpm in + *ofa_kernel*) + if [ $patch_kernel = y ] + then + echo "Un-Patching ofa_kernel for $kernel_ver..." + ( + cd src + # TBD - undo ofed_scripts/ofed_patch.sh + # need an unapply option or a separate unpatch script + echo "build_srpms: ERROR: -p option not implemented" >&2; exit 1 + ) + fi + ;; + esac + + rm -rf SOURCES SPECS SRPMS + mkdir SOURCES SPECS SRPMS + + # copy all the source files to the proper directory name + # omit CVS directories + # Note we can't symlink because we need tar below to not follow symlinks + ( + mkdir SOURCES/$srcdir; + cd src; find . -name CVS -prune -o -name '*~' -prune -o -print|cpio -pdum ../SOURCES/$srcdir + if [ $? != 0 -o ! -e ../SOURCES/$srcdir ] + then + echo "$srpm: ERROR: unable to create: $package/SOURCES/$srcdir" >&2 + exit 1 + fi + ) + [ $? -eq 0 ] || exit 1 + + # create the final tarfile which will be included in the srpm + ( + cd SOURCES + # set timestamp order for files which are typically pregenerated + # this avoids the need to upgrade to autoconf 2.60 on older distros + find $srcdir -name 'configure.in'|xargs -r touch + sleep 1 + find $srcdir -name '*.m4'|xargs -r touch + sleep 1 + find $srcdir -name 'configure'|xargs -r touch + sleep 1 + find $srcdir -name 'config.status'|xargs -r touch + sleep 1 + find $srcdir -name 'Makefile.in'|xargs -r touch + sleep 1 + find $srcdir -name '*h.in'|xargs -r touch + sleep 1 + + tar cf$taropt $tarfile $vopt $srcdir + if [ $? != 0 -o ! -e $tarfile ] + then + echo "$srpm: ERROR: unable to create: $package/SOURCES/$tarfile" >&2 + exit 1 + fi + rm -rf $srcdir + ) + [ $? -eq 0 ] || exit 1 + + if [ x"$otherfiles" != x ] + then + cp $otherfiles SOURCES/ + if [ $? != 0 ] + then + echo "$srpm: ERROR: unable to copy: $otherfiles to $package/SOURCES" >&2 + exit 1 + fi + fi + + cp $specfile SPECS/$specfile + if [ $? != 0 -o ! -e SPECS/$specfile ] + then + echo "$srpm: ERROR: unable to create: $package/SPECS/$specfile" >&2 + exit 1 + fi + + checkfiles || exit 1 + rpmbuild --nodeps -bs --define "_topdir `pwd`" SPECS/$specfile + if [ $? != 0 -o ! -e SRPMS/$srpm ] + then + echo "$srpm: ERROR: unable to create: $package/SRPMS/$srpm" >&2 + exit 1 + fi + cp SRPMS/$srpm $srpms_dir + echo "Built $package/SRPMS/$srpm" + if [ $? != 0 -o ! -e $srpms_dir/$srpm ] + then + echo "$srpm: ERROR: unable to create: $srpms_dir/$srpm" >&2 + exit 1 + fi + if [ "$clean" = y ] + then + rm -rf SOURCES SPECS SRPMS + fi + echo "Copied $package/SRPMS/$srpm to $srpms_dir/$srpm" + done + ) + if [ $? -ne 0 ] + then + echo "build_srpms: ERROR building $package" >&2 + exit 1 + fi +done diff --git a/MakeTools/builddsw.sh b/MakeTools/builddsw.sh new file mode 100755 index 0000000..47d5b6d --- /dev/null +++ b/MakeTools/builddsw.sh @@ -0,0 +1,117 @@ +#!/bin/bash +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** +# +# File: builddsw +# +# Purpose: Creates a Dev Studio Workspace (.dsw) file +# which references the given list of dsp files +# + +Usage() { + cmd="Usage: ${0} -f [file1.dsp file2.dsp ...]" + echo -e ${cmd} + return +} + +createDswHeader() { + echo -e "Microsoft Developer Studio Workspace File, Format Version 6.00" > ${dswFile} + echo -e "# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!\n" >> ${dswFile} + echo -e "###############################################################################" >> ${dswFile} +} + +createDswTrailer() { + echo -e "\nGlobal:\n" >> ${dswFile} + echo -e "Package=<5>" >> ${dswFile} + echo -e "{{{" >> ${dswFile} + echo -e "}}}\n" >> ${dswFile} + echo -e "Package=<3>" >> ${dswFile} + echo -e "{{{" >> ${dswFile} + echo -e "}}}\n" >> ${dswFile} + echo -e "###############################################################################" >> ${dswFile} +} + + +# Function to create a .dsp entry in the workspace file. +createDswEntry() { + dspDir=`dirname ${1}` + #the version of sed below occasionally dumps on DOS, so explicitly + # remove .dsp suffix using basename + #dspName=`basename ${1} | sed 's/\..*$//'` + dspName=`basename ${1} .dsp` + + echo -e "\nProject: \"${dspName}\"=${1} - Package Owner=<4>\n" >> ${dswFile} + echo -e "Package=<5>" >> ${dswFile} + echo -e "{{{" >> ${dswFile} + echo -e " ${dspName}" >> ${dswFile} + echo -e " ${dspDir}" >> ${dswFile} + echo -e "}}}\n" >> ${dswFile} + echo -e "Package=<4>" >> ${dswFile} + echo -e "{{{" >> ${dswFile} + echo -e "}}}\n" >> ${dswFile} + echo -e "###############################################################################" >> ${dswFile} +} + +# Script main starts here +dswFile="" +needHeader=0 + +while [ "${1}" != "" ] ; do + case "${1}" in + -f) shift + dswFile=${1} + shift + ;; + + *) if [ "${dswFile}" = "" ] ; then + Usage + exit 1 + else + if [ ${needHeader} -eq 0 ] ; then + createDswHeader + needHeader=1 + fi + createDswEntry ${1} + fi + shift + ;; + + esac +done + +if [ "${dswFile}" = "" -o ${needHeader} -eq 0 ] ; then + Usage + exit 1 +fi + +if [ ${needHeader} -eq 1 ] ; then + createDswTrailer +fi + +exit 0 diff --git a/MakeTools/buildmsgs.pl b/MakeTools/buildmsgs.pl new file mode 100755 index 0000000..a36008a --- /dev/null +++ b/MakeTools/buildmsgs.pl @@ -0,0 +1,1061 @@ +#! perl -w +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# +# Converts a message file to a pair of C files (a source file and a header) +# that define macros and data structures for use with the Err module for error +# reporting. +# +# If you encounter any problems with this program please notify Frank Szczerba +# (fszczerba@infiniconsys.com). +# + +use strict; +use integer; +use FileHandle; +use File::Basename; + +# list of supported languages ( LOG_LANG_ is prepended on output ) must be uppercase +my @languages = qw( ENGLISH ); + +#### end configuration +my %languages; # @languages by name +for (my $i = 0; $i < scalar(@languages); $i++) { + $languages{$languages[$i]} = $i; +} + +my $msgFile; +my $msgFileLine; +my $warnCount = 0; +my $errorCount = 0; +my $context; +my $testMode = 0; + +sub output { + my $level = shift; + my $out = $testMode ? *STDOUT : *STDERR; + print $out ("$msgFile:$msgFileLine: $level: ", + defined $context ? "$context: ": "", @_, "\n"); +} + +sub warning { + output "WARNING", @_; + $warnCount++; +} + +sub error { + output "ERROR", @_; + $errorCount++; +} + +my $defModName; + +sub validate_format($); +sub get_names(\%); + +# +# file format definition +# +# All sections and attributes should be ucfirst(lower($_)) case +# +my $Format = { + File => { # default scope + }, + Module => { + Singular => 1, + Attributes => { + Name => { Required => 1, Type => "Ident", Min => 1}, + Ucname => { Type => "UcIdent", Calculate => sub { uc $_[0]->{Name}; } }, + }, + Calculate => sub { {Name => $defModName}; }, + }, + Message => { + Key => "Name", + Attributes => { + Name => { Required => 1, Type => "UcIdent" }, + Comment => { }, + Arglist => { Type => "CSV", Max => 6 }, + Unitarg => { Type => "Int", Min => 0, Max => 6, Default => 0, }, + Trapfunc => { Type => "Ident", Default => "LOG_TRAP_NONE" }, + Severity => { + Recomended => 1, + Type => "Picklist", + Transform => sub { $_[0] =~ tr/ /_/; + $_[0] =~ s/PARTIAL/ADD_PART/; }, + Set => "Class", + # Class is set to the RHS below: + Values => { + ADD_PART => "LOG_PART", + ALARM => "LOG_FINAL", + ERROR => "LOG_FINAL", + WARNING => "LOG_FINAL", + FATAL => "LOG_FINAL", + DUMP => "LOG", + CONFIG => "LOG", + PROGRAM_INFO => "LOG", + PERIODIC_INFO => "LOG", + DEBUG1_INFO => "LOG", + DEBUG2_INFO => "LOG", + DEBUG3_INFO => "LOG", + DEBUG4_INFO => "LOG", + DEBUG5_INFO => "LOG", + NOTICE => "LOG_FINAL", + }, + }, + Description => { + Required => 1, + Type => "FmtStr", + i18n => 1, + }, + Response => { + i18n => 1, + Type => "FmtStr", + Default => "NULL", + }, + Correction => { + i18n => 1, + Type => "FmtStr", + Default => "NULL", + }, + }, + }, + String => { + Key => "Name", + Attributes => { + Name => { Required => 1, Type => "UcIdent" }, + Comment => { }, + Arglist => { Type => "CSV", Max => 6 }, + String => { + Required => 1, + Type => "FmtStr", + i18n => 1, + }, + }, + } +}; + +my $File = {}; # the master object +my $object = {}; # temp object + +{ + my $scope = 'File'; + + # + # Completes and validates and object and adds it to $File + # + sub new_scope($) { + VALIDATE_OBJ: { + # validate the object + #print "new_scope: $scope -> $_[0]\n"; + foreach my $attr (keys(%{$Format->{$scope}{Attributes}})) { + my $def = $Format->{$scope}{Attributes}{$attr}; + + if (not defined $object->{$attr}) { + if ($def->{Required}) { + error "Missing $attr attribute"; + last VALIDATE_OBJ; + } + else { + if ($def->{Recomended}) { + warning "Missing $attr attribute"; + } + if (defined $def->{Default} or defined $def->{Calculate}) { + my $default = defined $def->{Default} ? $def->{Default} + : &{$def->{Calculate}}($object); + if ($def->{i18n}) { + # set default for all languages + $object->{$attr} = {}; + foreach my $lang (@languages) { + $object->{$attr}{$lang} = $default; + } + } + else { + # set default + $object->{$attr} = $default; + } + } + } + } + elsif ($def->{i18n}) { + # if a message is provided for one language, it must be provided for all + foreach my $lang (@languages) { + if (not $object->{$attr}{$lang}) { + error "$attr: Missing $lang translation"; + last VALIDATE_OBJ; + } + } + } + } + + if (defined $object->{FmtArgs}) { + my $numArgs = $object->{FmtArgs}; + if (not defined $object->{Arglist}) { + error "Missing Arglist ($numArgs args used)"; + } + else { + my $listLen = scalar(@{$object->{Arglist}}); + if (defined $Format->{$scope}{Attributes}{Unitarg} and $object->{Unitarg} > $listLen) { + error "Insufficient arguments ($listLen) for UnitArg ($object->{Unitarg})"; + } + if ($numArgs > $listLen) { + error "Insufficient arguments ($listLen) for format ($numArgs args used)"; + } + elsif ($numArgs < $listLen) { + warning "Extra arguments ($listLen) for format ($numArgs args used)"; + } + # check argument names + get_names(%$object); + } + } + if ($Format->{$scope}{Singular}) { + $File->{$scope} = $object; + } + else { + if (not exists $File->{$scope}) { + $File->{$scope} = []; + } + elsif ($Format->{$scope}{Key}) { + my $key = $Format->{$scope}{Key}; + foreach my $exist (@{$File->{$scope}}) { + if ($exist->{$key} eq $object->{$key}) { + error "Duplicate $scope definition with $key=$object->{$key}"; + last VALIDATE_OBJ; + } + } + } + push @{$File->{$scope}}, $object; + } + } # VALIDATE_OBJ + $object = {}; + $scope = $_[0]; + $context = $scope; + } + + # + # Parser + # + sub parse_line($) { + my $line = $_[0]; + + #print "$scope: $line\n"; + # parse the line + LINE: for ($line) { + # attribute assignement + /^(\w+)(?:.(\w+))?\s*=\s*(.*)$/ and do { + my $attr = ucfirst lc $1; + my $lang; + my $val = $3; + + if (defined $2) { + $lang = uc $2; + if (not defined $languages{$lang}) { + error "Unknown language '$lang'"; + last; + } + } + + if (not exists $Format->{$scope}{Attributes}{$attr}) { + error "Unknown attribute $attr for section $scope"; + last; + } + + my $def = $Format->{$scope}{Attributes}{$attr}; + + # type and range check + for ($def->{Type} ? $def->{Type} : "Str") { + /Int/ and do { + if ($val !~ /^\d*$/) { + error "Non-integer value $val for $attr"; + last LINE; + } + elsif (defined $def->{Min} and $val < $def->{Min}) { + error "$attr must be >= $def->{Min}"; + last LINE; + } + elsif (defined $def->{Max} and $val > $def->{Max}) { + error "$attr must be <= $def->{Max}"; + last LINE; + } + last; + }; + /CSV/ and do { + # convert to a list ref + $val = [split /\s*,\s*/, $val]; + + if (defined $def->{Min} and scalar(@$val) < $def->{Min}) { + error "$attr must be at least $def->{Min} element(s)"; + last LINE; + } + elsif (defined $def->{Max} and scalar(@$val) > $def->{Max}) { + error "$attr must be no more than $def->{Max} elements"; + last LINE; + } + last; + }; + /CStr|FmtStr/ and do { + # strip continuation sequences + $val =~ s/([^\\])(?:"\s*")+/$1/g; + # and validate + if ($val !~ /^"(?:[^"\\]*|\\.)*"$/) { + error "$attr must be a double-quoted C string"; + last LINE; + } + # Use Str length check for now, but it will over-count escape sequences + # and the quotes + + # Fallthrough + }; + /FmtStr/ and do { + my $numArgs = validate_format($val); + $object->{FmtArgs} = $numArgs if (($object->{FmtArgs} || 0) < $numArgs); + # Fallthrough + }; + /UcIdent/ and do { + if ($val !~ /^[A-Z_][A-Z0-9_]*$/) { + error "$attr must be an uppercase identifier"; + last LINE; + } + # Fallthrough + }; + /Ident/ and do { + if ($val !~ /^[A-Za-z_][A-Za-z0-9_]*$/) { + error "$attr must be an identifier"; + last LINE; + } + # Fallthrough + }; + /Ident|Str/ and do { + if (defined $def->{Min} and length($val) < $def->{Min}) { + error "$attr must be at least $def->{Min} character(s)"; + last LINE; + } + elsif (defined $def->{Max} and length($val) > $def->{Max}) { + error "$attr must be no more than $def->{Max} characters"; + last LINE; + } + last; + }; + /Picklist/ and do { + $val = uc $val; + if (exists $def->{Transform}) { + &{$def->{Transform}}($val); + } + if (not exists $def->{Values}{$val}) { + error "Invalid $attr"; + last LINE; + } + else { + $object->{$def->{Set}} = $def->{Values}{$val}; + } + last; + }; + die "Internal Error, Bad type $def->{Type}\n"; + } + + if ($Format->{$scope}{Attributes}{$attr}{i18n}) { + if (not defined $lang) { + error "Missing language"; + last LINE; + } + elsif (not exists $object->{$attr}) { + $object->{$attr} = { $lang => $val }; + } + else { + if (exists $object->{$attr}{$lang}) { + error "Duplicate"; + last LINE; + } + $object->{$attr}{$lang} = $val; + } + } + else { + if (defined $lang) { + error "Non-internationalized attribute $attr"; + last LINE; + } + elsif (exists $object->{$attr}) { + error "Duplicate attribute $attr"; + last LINE; + } + else { + $object->{$attr} = $val; + if ($attr eq "Name") { + $context = "$scope $val"; + } + } + } + last; + }; + + # section header + /^\[(\w+)\]$/ and do { + my $new_scope = ucfirst lc $1; + + if ($new_scope eq "Done") { + # flush + new_scope("Done"); + # validate sections + foreach my $check_scope (keys %$Format) { + #print "check $check_scope: "; + if (not exists $File->{$check_scope}) { + #print "Missing "; + if ($Format->{$check_scope}{Required}) { + #print "Required\n"; + error "Missing required section $check_scope"; + } + elsif ($Format->{$check_scope}{Default} or + $Format->{$check_scope}{Calculate}) + { + #print "Defaulting "; + $object = $Format->{$check_scope}{Default} + ? $Format->{$check_scope}{Default} + : &{$Format->{$check_scope}{Calculate}}; + #print "Validating "; + $scope = $check_scope; + new_scope("Done"); + } + } + #print "Done\n"; + } + } + elsif ($scope eq "Done") { + # internal use + $scope = $new_scope; + } + elsif (not exists $Format->{$new_scope}) { + error "Unknown section $new_scope"; + } + else { + if ($Format->{$new_scope}{Singular} and + (exists $File->{$new_scope} or $scope eq $new_scope)) + { + error "Only one $new_scope section is permitted"; + } + new_scope($new_scope); + } + last; + }; + + error "Syntax Error"; + } + } +} + +{ + my $f_posarg = '[1-9]\d*\$'; + my $f_flags = '[ #+0\-]'; + my $f_width = "(?:[1-9]\\d*|\\*(?:$f_posarg)?)"; + my $f_precis = "(?:\\.(?:\\d*|\\*(?:$f_posarg)?))"; + my $f_size = '[hq]|(?:ll?)'; + my $f_type = '[cCdiFopsSuxXM]'; + + # $1 $2 $3 $4 $5 $6 $7 $8 + my $fmt = "($f_posarg)?($f_flags*)($f_posarg)?($f_width)?($f_precis)?($f_posarg)?($f_size)?($f_type)"; + + # + # Scan a string and validate printf format specifiers. Returns the number of + # arguments on success, dies with a descriptive string on error. + # + sub validate_format($) { + my $str = $_[0]; + my $have_pos = 0; + my $pos_mixed = 0; + my $numargs = 0; + + $testMode and print "validate_format($str)\n"; + while (length($str) and not $pos_mixed) { + # strip stuff before the first % + $str =~ s/^[^%]*//; + + if (length($str)) { + # is it a valid format? + if ($str =~ s/^(?:\%\%|\%$fmt)//o) { + my $numPos = (defined $1) + (defined $3) + (defined $6); + if ($numPos > 1) { + error "Multiple positional specifiers '", defined $1 ? $1 : $3, + $numPos == 3 ? "', '$3'," : "'", + " and '", defined $5 ? $5 : $3, "' in format specifier"; + } + my $pos = defined $1 ? $1 : defined $3 ? $3 : $6; + my $flags = $2; + my $width = $4; + my $precis = $5; + my $size = $7; + my $type = $8; + + # check for repeating flags (not really a problem, but ugly) + $flags = join('', sort(split //, $flags)); + $testMode and print "Flags are: '$flags'\n"; + if ($flags =~ /(.)\1/) { + warning "Repeated flag '$1' in format specifier"; + } + + # check for positional and non-positional parameters + if (defined $pos) { + my $arg = substr($pos, 0, length($pos) - 1); + $testMode and print "positional $pos, arg is $arg\n"; + $numargs = $arg if ($arg > $numargs); + $have_pos = 1; + } + else { + $pos_mixed = $have_pos; + $numargs++; # not the right place, but gets the right count + } + if (defined $width and $width =~ /^\*($f_posarg)?$/o) { + if (defined $1) { + my $arg = substr($1, 0, length($1) - 1); + $testMode and print "width $width, arg is $arg\n"; + $numargs = $arg if ($arg > $numargs); + $have_pos = 1; + } + else { + $pos_mixed = $have_pos; + $numargs++; + } + } + if (defined $precis and $precis =~ /^\.\*($f_posarg)?$/o) { + if (defined $1) { + my $arg = substr($1, 0, length($1) - 1); + $testMode and print "precision $precis, arg is $arg\n"; + $numargs = $arg if ($arg > $numargs); + $have_pos = 1; + } + else { + $pos_mixed = $have_pos; + $numargs++; + } + } + if ($have_pos and not defined $pos) { + $pos_mixed = 1; + } + + # TODO: validate size-type combos? + } + else { + error "Invalid format specifier at \"$str\""; + # strip the '%' so we can recover + $str = substr($str, 1); + } + } + } + if ($pos_mixed) { + error "Format mixes positional and non positional parameters"; + } + + return $numargs; + } + + # + # Scan a string and return a list of arguments which are IFormattable objects + # + sub find_formattable($) { + my $str = $_[0]; + my $nextarg = 1; + my %formattable = (); + + while ($str =~ /\G(?:[^\%]|\%\%)*\%$fmt/go) + { + my $pos = defined $1 ? $1 : defined $3 ? $3 : $6; + my $width = $4; + my $precis = $5; + my $type = $8; + + if (defined $pos) { + substr($pos, -1) = ''; + $nextarg = $pos; + } + if (defined $width and $width eq '*') { + $nextarg++; + } + if (defined $precis and substr($precis, 1) eq '*') { + $nextarg++; + } + if ($type eq 'F') { + $formattable{$nextarg}++; + } + $nextarg++; + } + + return sort keys %formattable; + } + + # + # Scan a string and return a list of arguments which are pointers + # + sub find_pointer($) { + my $str = $_[0]; + my $nextarg = 1; + my %pointer = (); + + while ($str =~ /\G(?:[^\%]|\%\%)*\%$fmt/go) + { + my $pos = defined $1 ? $1 : defined $3 ? $3 : $6; + my $width = $4; + my $precis = $5; + my $type = $8; + + if (defined $pos) { + substr($pos, -1) = ''; + $nextarg = $pos; + } + if (defined $width and $width eq '*') { + $nextarg++; + } + if (defined $precis and substr($precis, 1) eq '*') { + $nextarg++; + } + if ($type eq 's' or $type eq 'p') { + $pointer{$nextarg}++; + } + $nextarg++; + } + + return sort keys %pointer; + } +} + +# +# Extract names of arguments from an argument list +# +sub get_names(\%) { + my $obj = $_[0]; + my @list; + my %seen = (); + + if (not defined $obj->{Arglist}) { + return (); + } + + for (my $i = 1; $i <= scalar(@{$obj->{Arglist}}); $i++) { + if ($obj->{Arglist}[$i-1] =~ /^([a-zA-Z_]\w+)(?:\s*:.*)?$/) { + $list[$i-1] = $1; + } + else { + warning "No name given for $obj->{Name} argument $i, defaulting to arg$i"; + $list[$i-1] = "arg$i"; + } + if ($seen{$list[$i-1]}) { + error "Duplicate argument name ", $list[$i-1], " for $obj->{Name}"; + } + $seen{$list[$i-1]} = 1; + } + + return @list; +} + +# +# Find the union of two (or more) lists +# +sub union { + my %union = (); + + foreach my $i (@_) { + $union{$i}++; + } + + return sort keys %union; +} + +# +# Main Loop +# + +#main() + +my $cur_line = ""; + +if (scalar @ARGV != 1) { + print "Usage: buildmsgs.pl Module.msg\n"; + print "\nCreates/overwrites Module_Messages.c and Module_Messages.h.\n"; + exit(1); +} + +$msgFile = shift; +($defModName,undef,undef) = fileparse($msgFile, '\..*'); +$msgFileLine = 0; +my $fileBase = $defModName . "_Messages"; + +if ($msgFile eq '--test') { + $testMode = 1; + while (<>) { + my $line = $_; + chomp $line; + ++$msgFileLine; + my $rslt = validate_format($line); + print "$rslt arguments\n"; + my @formattable = find_formattable($line); + my @pointer = find_pointer($line); + print "IFormattable args: ", join(', ', @formattable), "\n" if (@formattable); + print "Pointer args: ", join(', ', @pointer), "\n" if (@pointer); + print "\n"; + } + exit 0; +} + +my $msg_file = new FileHandle "$msgFile" or die "$msgFile: ERROR: $!\n"; + +while (<$msg_file>) { + s/((?:".*")*)\s*(?:#.*)?$/$1/; # strip comments + s/\s*$//; # strip trailing whitespace + if (s/^\t[ \t]*/ /) { # continuation line + $cur_line .= $_; + } + else { + if (length($cur_line)) { + parse_line($cur_line); + } + $cur_line = $_; + } + ++$msgFileLine; +} + +# handle last line +if (length($cur_line)) { + parse_line($cur_line); +} + +# flush any in-progress object +parse_line("[Done]"); + +close $msg_file; + +# ensure we have a MODNAME str as the first string +if (not exists $File->{String} or $File->{String}[0]{Name} ne "MODNAME") { + if (exists $File->{String}) { + for (my $i = 1; $i < scalar(@{$File->{String}}); $i++) { + if ($File->{String}[$i]{Name} eq "MODNAME") { + error "MODNAME must be the first string"; + } + } + } + parse_line("[String]"); + parse_line("Name=MODNAME"); + parse_line("comment=first entry must be 1-6 character package name"); + foreach my $lang (@languages) { + parse_line("String.$lang=\"$File->{Module}{Name}\""); + } + parse_line("[Done]"); + + # rotate to the beginning of the list + unshift @{$File->{String}}, pop @{$File->{String}}; +} + +# ensure MODNAME str is 1-6 characters +foreach my $lang (@languages) { + my $str = $File->{String}[0]{String}{$lang}; + + # value includes quotes + if (length $str < 3 or length $str > 9) { + error "MODNAME string must be 1-6 characters ($lang string $str is ", + length($str)- 2, " characters"; + } +} + +if ($errorCount) { + die "$msgFile: $warnCount warnings, $errorCount errors\n"; +} +elsif ($warnCount) { + warn "$msgFile: $warnCount warnings\n" +} + +# +# generate output +# + +my $modName = $File->{Module}{Name}; +my $ucModName = $File->{Module}{Ucname}; +my $lcModName = lcfirst $modName; +my $mod = "MOD_$ucModName"; + +my $header = new FileHandle ">$fileBase.h" or die "$msgFile: ERROR: Could not open $fileBase.h for write\n"; +my $source = new FileHandle ">$fileBase.c" or die "$msgFile: ERROR: Could not open $fileBase.c for write\n"; + +# +# Mod_Messages.h +# +my $oldfh = select $header; +print <<"EOF"; +#ifndef ${ucModName}_MESSAGES_H_INCLUDED +#define ${ucModName}_MESSAGES_H_INCLUDED + +/*! + \@file $modName/$fileBase.h + \@brief Nationalizable Strings and Messages for $modName Package generated from $msgFile + */ + +#include "Gen_Arch.h" +#include "Gen_Macros.h" +#include "Log.h" + +EOF + +if (exists $File->{Message}) { + my $need_macros = 0; + print "/* Messages */\n"; + for (my $i = 0; $i < scalar(@{$File->{Message}}); $i++) { + printf "#define %s_MSG_%-25s LOG_BUILD_MSGID(%s, %d)\n", + $ucModName, $File->{Message}->[$i]->{Name}, $mod, $i; + $need_macros = 1 if (exists $File->{Message}->[$i]->{Severity}); + } + if ($need_macros) { + print "\n/* Logging Macros */\n"; + for (my $i = 0; $i < scalar(@{$File->{Message}}); $i++) { + my $msg = $File->{Message}->[$i]; + + next if (not exists $msg->{Severity}); + + my $msgName = $msg->{Name}; + my @args = get_names(%$msg); + my @fmt = find_formattable($msg->{Description}{$languages[0]}); + my @ptr = find_pointer($msg->{Description}{$languages[0]}); + if (defined $msg->{Response}) { + @fmt = union(@fmt, find_formattable($msg->{Response}{$languages[0]})); + @ptr = union(@ptr, find_pointer($msg->{Response}{$languages[0]})); + } + if (defined $msg->{Correction}) { + @fmt = union(@fmt, find_formattable($msg->{Correction}{$languages[0]})); + @ptr = union(@ptr, find_pointer($msg->{Correction}{$languages[0]})); + } + my @rvArgs = @args; + foreach my $arg (@fmt) { + $rvArgs[$arg-1] = 'LOG_FORMATTABLE('. $rvArgs[$arg-1] . ')'; + } + foreach my $arg (@ptr) { + $rvArgs[$arg-1] = 'LOG_PTR('. $rvArgs[$arg-1] . ')'; + } + for (my $arg = scalar(@rvArgs); $arg < 6; $arg++) { + $rvArgs[$arg] = 0; + } + #printf STDOUT "%s: %d, %d\n", $msgName, scalar(@args), scalar(@rvArgs); + + printf "/* %s_MSG_%s", $ucModName, $msgName; + if (exists $msg->{Comment}) { + print ": $msg->{Comment}"; + } + if (exists $msg->{Arglist}) { + print "\n * Arguments: \n"; + for (my $i = 0; $i < scalar(@{$msg->{Arglist}}); $i++) { + printf " *\t%s\n", $msg->{Arglist}[$i]; + } + } + print " */\n"; + printf "#define %s_%s_%s(%s)\\\n\tLOG_%s(MOD_%s, %s_MSG_%s, %s)\n", + $ucModName, $msg->{Class}, $msgName, join(', ', @args), + $msg->{Severity}, $ucModName, $ucModName, $msgName, join(', ', @rvArgs); + } + } +} + +print "\n/* Constant Strings for use as substitutionals in Messages */\n"; +my $need_macros = 0; +for (my $i = 0; $i < scalar(@{$File->{String}}); $i++) { + printf "#define %s_STR_%-25s LOG_BUILD_STRID(%s, %d)\n", + $ucModName, $File->{String}->[$i]->{Name}, $mod, $i; + $need_macros = 1 if (exists $File->{String}->[$i]->{Arglist}); +} +if ($need_macros) { + print "\n/* String Formatting Macros */\n"; + for (my $i = 0; $i < scalar(@{$File->{String}}); $i++) { + my $str = $File->{String}->[$i]; + + next if (not exists $str->{Arglist}); + + my @args = get_names(%$str); + my @fmt = find_formattable($str->{String}{$languages[0]}); + my @ptr = find_pointer($str->{String}{$languages[0]}); + my @rvArgs = @args; + foreach my $arg (@fmt) { + $rvArgs[$arg-1] = 'LOG_FORMATTABLE('. $rvArgs[$arg-1] . ')'; + } + foreach my $arg (@ptr) { + $rvArgs[$arg-1] = 'LOG_PTR('. $rvArgs[$arg-1] . ')'; + } + for (my $arg = scalar(@rvArgs); $arg < 6; $arg++) { + $rvArgs[$arg] = 0; + } + printf "/* %s_STR_%s", $ucModName, $str->{Name}; + if (exists $str->{Comment}) { + print ": $str->{Comment}"; + } + if (exists $str->{Arglist}) { + print "\n * Arguments: \n"; + for (my $i = 0; $i < scalar(@{$str->{Arglist}}); $i++) { + printf " *\t%s\n", $str->{Arglist}[$i]; + } + } + print " */\n"; + printf "#define %s_FMT_%s(buffer, %s)\\\n\t", $ucModName, $str->{Name}, join(', ', @args); + printf "LOG_FORMATBUF(buffer, Log_GetString(%s_STR_%s, (buffer).GetLanguage()), %s)\n", + $ucModName, $str->{Name}, join(', ', @rvArgs); + } +} +print "\n"; + +print <<"EOF"; +GEN_EXTERNC(extern void ${modName}_AddMessages();) + +#endif /* ${ucModName}_MESSAGES_H_INCLUDED */ +EOF + +# +# Mod_Messages.c +# +select $source; +print <<"EOF"; +/*! + \@file $modName/$fileBase.c + \@brief Nationalizable Strings and Messages for $modName Package generated from $msgFile + */ + +#include "$fileBase.h" + +EOF + + + + + +if (exists $File->{Message}) { + # Loop through and add all the trap fun ptr prototypes at the top + foreach my $msg (@{$File->{Message}}) { + if(not $msg->{Trapfunc} eq "LOG_TRAP_NONE"){ + printf "extern Log_TrapFunc_t %s;\n", $msg->{Trapfunc}; + } + } + print "\n\n"; + + + print <<"EOF"; + +/*! +Module specific message table, referenced by Log_MessageId_t. + +The entries in the table must provide equivalent argument usage for +all languages. Argument usage in format strings is used to determine +which arguments may need to be freed +*/ + +static Log_MessageEntry_t ${lcModName}_messageTable[] = +{ +EOF + foreach my $msg (@{$File->{Message}}) { + printf "\t{\t%s_MSG_%s,%s\n", $ucModName, $msg->{Name}, + exists $msg->{Comment} ? "\t/* $msg->{'comment'} */" : ''; + printf "\t\t%d,\t/* argument number which holds unit number, 0 -> none */\n", $msg->{Unitarg}; + printf "\t\t%s,\t/* trap func associated with message */\n", $msg->{Trapfunc}; + print "\t\t/* FUTURE - Binary Data */\n"; + if (exists $msg->{Arglist}) { + my $args = $msg->{Arglist}; + print "\t\t/* Arguments: \n"; + for (my $i = 0; $i < scalar(@$args); $i++) { + printf "\t\t *\targ%d -> %s\n", $i + 1, $args->[$i]; + } + print "\t\t */\n"; + } + else { + print "\t\t/* Arguments: None */\n"; + } + print "\t\t{ /* Language Specific Entries */\n"; + foreach my $lang (@languages) { + print "\t\t\t{ /* LOG_LANG_$lang */\n"; + printf "\t\t\t\t/* description */ %s,\n", $msg->{Description}->{$lang}; + printf "\t\t\t\t/* response */ %s,\n", $msg->{Response}->{$lang}; + printf "\t\t\t\t/* correction */ %s,\n", $msg->{Correction}->{$lang}; + print "\t\t\t},\n"; + } + print "\t\t},\n\t},\n"; + } + print "};\n\n"; +} + +print <<"EOF"; + +/*! +Module specific string table, referenced by Log_StringId_t. +*/ + +static Log_StringEntry_t ${lcModName}_stringTable[] = +{ +EOF +foreach my $str (@{$File->{String}}) { + printf "\t{\t%s_STR_%s,%s\n", $ucModName, $str->{Name}, + exists $str->{Comment} ? "\t/* $str->{Comment} */" : ''; + if (defined $str->{Arglist}) { + my $args = $str->{Arglist}; + print "\t\t/* Arguments: \n"; + for (my $i = 0; $i < scalar(@$args); $i++) { + printf "\t\t *\targ%d -> %s\n", $i + 1, $args->[$i]; + } + print "\t\t */\n"; + } + my $lch = '{'; + foreach my $lang (@languages) { + printf "\t\t$lch /* LOG_LANG_$lang */ %s,\n", $str->{String}->{$lang}; + $lch = ' '; + } + print "\t\t},\n\t},\n"; +} +print "};\n\n"; + +print <<'EOF'; +/*! +Add String table to logging subsystem's tables. + +This must be run early in the boot to initialize tables prior to +any logging functions being available. + +@return None + +@heading Concurrency Considerations + Must be run once, early in boot + +@heading Special Cases and Error Handling + None + +@see Log_AddStringTable +*/ + +EOF + +printf "void\n%s_AddMessages()\n{\n", $modName; + printf "\tLog_AddStringTable(MOD_%s, %s_stringTable,\n". + "\t\t\t\t\t\tGEN_NUMENTRIES(%s_stringTable));\n", + $ucModName, $lcModName, $lcModName; +if (exists $File->{Message}) { + printf "\tLog_AddMessageTable(MOD_%s, %s_messageTable,\n". + "\t\t\t\t\t\tGEN_NUMENTRIES(%s_messageTable));\n", + $ucModName, $lcModName, $lcModName; +} +print "}\n"; + +select $oldfh; + +close $header; +close $source; diff --git a/MakeTools/check_results b/MakeTools/check_results new file mode 100755 index 0000000..556cfea --- /dev/null +++ b/MakeTools/check_results @@ -0,0 +1,179 @@ +#!/bin/bash +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** +## +## check_results +## ----------- +## Examine the output from the build and filter it into warning and error +## files allowing for quick analysis of the success of the build +## This is used by the weeklybuild script to provide product specific +## build operations for product's whose analysis of results is more complex +## than simply grepping for various error keywords +## +## Usage: +## When this is invoked, the current directory will be the TL_DIR for a +## full checkout of the product to be built +## +## Usage: +## check_results [-r] [-e add_error] [-E add_error_filter] +## [-w add_warn] [-W add_warn_filter] +## results_file errors_file warn_file +## +## Arguments: +## -r - generate a report on success/failure of a build and +## exit with a status of 1 for failure, 0 for success +## -e add_error - additional egrep patterns for identifying errors +## must start with | +## -E add_error_filter - additional egrep patterns to filter out of errors +## must start with | +## -w add_warn - additional egrep patterns for identifying warnings +## must start with | +## -W add_warn_filter - additional egrep patterns to filter out of warnings +## must start with | +## results_file - input file containing results from a weeklybuild +## could be a full or partial (limited OS/build_config/build_smp combos) +## build +## errors_file - output file where serious errors should be output which +## reflect a build failure +## warn_file - output file where non-serious errors and warning should be +## output which might reflect a minor problem or a bug in code detected by +## the compilers +## +## In addition, the following environment variables are expected to be set: +## RELEASE_TAG, BRANCH_TAG, BUILD_TARGET, PRODUCT, RELEASE_HOME, BUILD_CONFIG +## The target command is expected to have already been run to set up the +## environment for the specified target +## + +results_file=/dev/null +errors_file=/dev/null +warn_file=/dev/null + +Usage() +{ + echo "Error: check_results failed" >&2 + echo "Usage: check_results [-r] [-e add_error] [-E add_error_filter]">&2 + echo " [-w add_warn] [-W add_warn_filter]">&2 + echo " results_file errors_file warn_file">&2 + echo " -r - generate a report on success/failure of a build and">&2 + echo " exit with a status of 1 for failure, 0 for success">&2 + echo " -e add_error - additional egrep patterns for identifying errors">&2 + echo " must start with |">&2 + echo " -E add_error_filter - additional egrep patterns to filter out of errors">&2 + echo " must start with |">&2 + echo " -w add_warn - additional egrep patterns for identifying warnings">&2 + echo " must start with |">&2 + echo " -W add_warn_filter - additional egrep patterns to filter out of warnings">&2 + echo " must start with |">&2 + echo " results_file - input file containing results from a weeklybuild">&2 + echo " could be a full or partial (limited OS/build_config/build_smp combos)">&2 + echo " build">&2 + echo " errors_file - output file where serious errors should be output which">&2 + echo " reflect a build failure">&2 + echo " warn_file - output file where non-serious errors and warning should be">&2 + echo " output which might reflect a minor problem or a bug in code detected by">&2 + echo " the compilers">&2 + exit 2 +} + +filter() +{ + # stdin is to be filtered using $1 + # lines in both stdin and $1 are filtered + # lines in just $1 are ignored + # lines in just stdin are put to stdout + # if the file $1 does not exist, all lines in stdin are put to stdout + if [ -f $1 ] + then + # since build can be run multiple times for various OS combos + comm -23 - $1 + else + cat + fi +} + +ropt=n +add_error= +add_error_filter= +add_warn= +add_warn_filter= +while getopts "re:E:w:W:" param +do + case $param in + r) ropt=y;; + e) add_error="$OPTARG";; + E) add_error_filter="$OPTARG";; + w) add_warn="$OPTARG";; + W) add_warn_filter="$OPTARG";; + ?) + Usage;; + esac +done +shift $(($OPTIND -1)) + +if [ $# != 3 ] +then + Usage +fi +results_file=$1 +errors_file=$2 +warn_file=$3 + +# filter out _ERROR defines used in mellanox code and in some warnings +# sort out duplicated messages from multiple build runs +sort -u expected.err > .expected.err +# future: add back in check for "No such file" +egrep " Error |ERROR|^Bad | Bad |failed|FAILED|unifdef:| Stop|No space left on device$add_error" $results_file |egrep -v "_ERROR|_failed|failed_"| sort -u|filter .expected.err > $errors_file + +sort -u expected.warn > .expected.warn +egrep -i "warning:$add_warn" $results_file |egrep -v "Warnings$add_warn_filter" | sort -u |filter .expected.warn > $warn_file + +if [ "$ropt" = "n" ] +then + exit 0 +fi + +if [ -s $errors_file ] +then + echo "Build Errors:" + sort -u $errors_file + echo + echo "FAILED Build, errors detected: $PRODUCT $SUBPRODUCT $BUILD_TARGET $BUILD_CONFIG" + exit 1 +else + if [ -s $warn_file ] + then + echo "SUCCESSFUL Build, no errors detected, BUT THERE WERE $(sort -u $warn_file|wc -l) WARNINGS..: $PRODUCT $SUBPRODUCT $BUILD_TARGET $BUILD_CONFIG" + sort -u $warn_file + exit 0 + else + echo "SUCCESSFUL Build, no errors or warnings detected: $PRODUCT $SUBPRODUCT $BUILD_TARGET $BUILD_CONFIG" + exit 0 + fi +fi diff --git a/MakeTools/cleanCVSDir.sh b/MakeTools/cleanCVSDir.sh new file mode 100755 index 0000000..2c47eee --- /dev/null +++ b/MakeTools/cleanCVSDir.sh @@ -0,0 +1,39 @@ +#!/bin/bash + +if [ "$1" = "" ] +then + echo Usage: cleanCVSDir.sh dirname + exit 1 +fi + +if [ -d "$1" ] +then + for i in $1/* + do + if [ -f "$1/$i" ] + then + # it is a file, just remove it + rm -f $1/$i + elif [ "$i" != "CVS" ] + then + # it is a directory, not the CVS directory + # if it does not have a CVS directory in it, remove it + # otherwise, it is a repository directory, so recurse +# LS=`ls -d $1/$i/CVS 2>/dev/null` +# if [ "$LS" == "" ] + + if [ ! -d "$1/$i/CVS" ] + then + rm -rf $1/$i + else + $TL_DIR/MakeTools/cleanCVSDir.sh $1/$i + fi + fi + done + + if [ \( ! -d "$1/CVS" \) -a "$1" != "." ] + then + rm -rf "$1" + fi + +fi diff --git a/MakeTools/convert_releasetag.pl b/MakeTools/convert_releasetag.pl new file mode 100755 index 0000000..15e48fc --- /dev/null +++ b/MakeTools/convert_releasetag.pl @@ -0,0 +1,137 @@ +#!/usr/bin/perl +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** +# +# [ICS VERSION STRING: unknown] +use strict; + +# convert release tag in $1 to a version number +# +sub Usage() +{ + print "Usage: $0 [-i] releasetag\n"; + print " -i - omit integration build number (I#)\n"; + print " sample release tag formats:\n"; + print " release_tag Version String w/ -i Version String w/o -i\n"; + print " R1_0I5 1.0 1.0.5\n"; + print " R1_0M1I2 1.0.1 1.0.1.2\n"; + print " R1_0B1I2 1.0B1 1.0B1.2\n"; + print " R1_0M1A1I3 1.0.1A1 1.0.1A1.3\n"; + print " R1_0M0P4I5 1.0.0.4 1.0.0.4.5\n"; + print " R1_0B1P4 1.0B1.4 1.0B1.4\n"; + print " R0capemayI7 0capemay 0capemay.7\n"; + print " R0capemayP4I1 0capemay.4 0capemay.4.1\n"; + print " R0tmri.103114.1522 0tmri.103114.1522 0tmri.103114.1522\n"; + print " ICS_R2_0I5 2.0 2.0.5\n"; + + exit 2; +} + +# TBD "dropI" option +if (scalar @ARGV < 1) { + Usage; +} +my $releasetag= shift; +my $dropI = 0; +if ("$releasetag" eq "-i") { + $dropI=1; + if (scalar @ARGV < 1) { + Usage; + } + $releasetag= shift; +} + +#print "releasetag=$releasetag\n"; + +# The algorithm here is purposely copied from ParseReleaseTag and for +# ease of comparison is structured the same as the C version in patch_version.c +# this algorithm must exactly match the one in patch_version. + +# remove leading non-digits +$releasetag =~ s/^[^0-9]+//; +#print "releasetag=$releasetag\n"; +my $version = ""; + +my $done=0; +my $processedM=0; +my $processedP=0; +for (my $i = 0; ! $done && $i < length($releasetag); $i++) { + my $c = substr($releasetag, $i, 1); + if ($c eq 'I') { + #print "match I\n"; + # I starts the trailer for the release tag, it is not placed + # in the version string + if ($dropI) { + $done=1; + } else { + # replaced with a . + + # if no M tag was processed, must insert a zero placeholder + if (! $processedM) { + $version .= '.0'; + } + # if no P tag was processed, must insert a zero placeholder + if (! $processedP) { + $version .= '.0'; + } + $version .= '.'; + } + } elsif ($c eq '_') { + #print "match _\n"; + # replaced with a . + $version .= '.'; + } elsif ($c eq 'M') { + #print "match M\n"; + # replaced with a . + $version .= '.'; + $processedM = 1; + } elsif ($c eq 'P') { + #print "match P\n"; + # replaced with a . + # if no M tag was processed, must insert a zero placeholder + if (! $processedM) { + $version .= '.0'; + $processedM = 1; + } + $version .= '.'; + $processedP = 1; + } else { + #print "no match\n"; + $version .= "$c"; + } + #printf "c=$c version=$version\n"; +} +# version strings must start with a digit +if ($version !~ /^[0-9]/) { + printf STDERR "\nInvalid release tag format yields: $version\n"; + Usage; +} + +print "$version\n"; +exit 0; diff --git a/MakeTools/expand_ofed.sh b/MakeTools/expand_ofed.sh new file mode 100755 index 0000000..5d19a53 --- /dev/null +++ b/MakeTools/expand_ofed.sh @@ -0,0 +1,158 @@ +#!/bin/bash +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** +## +## expand_ofed +## ----------- +## expand an OFED tgz in preparation for source control in OFED vendor branch +## +## Usage: +## expand_ofed [-d dest_dir] [-c compare_dir] ofed.tgz +## +## Arguments: +## -d - destination for expansion, default is ./SOURCE_TREE +## -c - optional expanded ofed to compare to +## ofed.tgz - ofed tgz to expand +## Environment: + +tempdir=/usr/tmp/expand$$ + +# handle various places we could find our tools +if [ -e ./expand_source.sh ] +then + expand_source=$PWD/expand_source.sh +#elif [ -e $TL_DIR/MakeTools/expand_source.sh ] +#then +# expand_source=$TL_DIR/MakeTools/expand_source.sh +else + expand_source=expand_source +fi +if ! type $expand_source +then + exit 1 +fi + +Usage() +{ + echo "Usage: expand_ofed [-d dest_dir] [-c compare_dir] ofed.tgz" >&2 + echo " -d - destination for expansion, default is ./SOURCE_TREE" >&2 + echo " -c - optional expanded ofed to compare to" >&2 + echo " ofed.tgz - ofed tgz to expand" >&2 + exit 2 +} + +# convert $1 to an absolute path +fix_dir() +{ + local dir + if [ x$(echo $1|cut -c1) != x"/" ] + then + dir="$PWD/$1" + else + dir="$1" + fi + # drop trailing / + if [ "$dir" != "/" ] + then + echo "$dir"|sed -e 's|/*$||' + else + echo "$dir" + fi +} + +dest_dir=$PWD/SOURCE_TREE +compare_dir= +while getopts d:c: param +do + case $param in + d) dest_dir="$OPTARG";; + c) compare_dir="$OPTARG";; + *) Usage;; + esac +done +shift $(($OPTIND -1)) +if [ $# -ne 1 ] +then + Usage +fi +ofed_tgz=$1 + +if [ ! -f $ofed_tgz ] +then + echo "expand_ofed: Can't find: $ofed_tgz" >&2 + exit 1 +fi +dest_dir=$(fix_dir $dest_dir) +ofed_tgz=$(fix_dir $ofed_tgz) + +mkdir -p $dest_dir + +# assume tarfile creates one dir +ofed_dir=$(tar tfz $ofed_tgz|sed -e 's/\/.*//'|sort -u) +if [ x"$ofed_dir" = x ] +then + echo "expand_ofed: Can't figure out top dir of $ofed_tgz" >&2 + exit 1 +fi + +mkdir -p $tempdir +tar xvfz $ofed_tgz -C $tempdir +if [ $? -ne 0 -o ! -d $tempdir/$ofed_dir ] +then + echo "expand_ofed: unable to untar $ofed_tgz" >&2 + exit 1 +fi +$expand_source -a -s $tempdir/$ofed_dir -d $dest_dir +if [ $? -ne 0 ] +then + echo "expand_ofed: expand_source failed" >&2 + exit 1 +fi +rm -rf $tempdir + +if [ x"$compare_dir" != x ] +then + + echo "Comparing $compare_dir and $dest_dir..." + compare_dir=$(fix_dir $compare_dir) + diff -r --exclude CVS $compare_dir $dest_dir > ./diffs + + # list of new files in drop relative to $compare_dir drop + grep "^Only in $dest_dir[:/]" < ./diffs|sed -e 's/^Only in //' -e 's/: /\//' -e "s|$dest_dir|.|" > ./added_files + + # list of files moved/removed in drop relative to $compare_dir drop + grep "^Only in $compare_dir[:/]" < ./diffs|grep -v ': CVS'|sed -e 's/^Only in //' -e 's/: /\//' -e "s|$compare_dir|.|" > ./removed_files + + # summary + echo "New files in this drop is in ./added_files: $(wc -l < ./added_files) files" + echo "Files removed in this drop is in ./removed_files: $(wc -l < ./removed_files) files" + echo "All diffs are in ./diffs: $(wc -l < ./diffs) lines" +fi + +exit 0 diff --git a/MakeTools/expand_source.sh b/MakeTools/expand_source.sh new file mode 100755 index 0000000..1b6a784 --- /dev/null +++ b/MakeTools/expand_source.sh @@ -0,0 +1,287 @@ +#!/bin/bash +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** +## +## expand_source +## ----------- +## expand the SRPMs found in a SRPMS source tree into their component files +## designed to work with OFED packagings. build_srpms can rebuild the srpms. +## +## Usage: +## expand_source [-a] [-s source_dir] [-d dest_dir] [-p] [-L] [-V kernel_ver] [srpm ...] +## +## Arguments: +## -s - source directory to expand, default is ., ignored if srpm(s) specified +## -a - expand all of OFED, -s is OFED install tree +## -d - destination for expansion, default is ./SOURCE_TREE +## -p - apply patches for ofa_kernel +## -V - kernel version to apply patches for, default is `uname -r` +## -L - clean any symlinks +## srpm - srpm file to expand +## Environment: + +#. $ICSBIN/funcs.sh + +Usage() +{ + # include "ERROR" in message so weeklybuild catches it in error log + echo "ERROR: expand_source failed" >&2 + echo "Usage: expand_source [-a] [-s source_dir] [-d dest_dir] [-p] [-L] [-V kernel_ver] [srpm ...]" >&2 + echo " -s - source directory to expand, default is ., ignored if srpm(s) specified" >&2 + echo " -a - expand all of OFED, -s is OFED install tree" >&2 + echo " -d - destination for expansion, default is ./SOURCE_TREE" >&2 + echo " -p - apply patches for ofa_kernel" >&2 + echo " -V - kernel version to apply patches for, default is `uname -r`" >&2 + echo " -v - verbose output" >&2 + echo " -L - clean any symlinks" >&2 + echo " srpm - srpm file to expand" >&2 + exit 2 +} + +# convert $1 to an absolute path +fix_dir() +{ + if [ x$(echo $1|cut -c1) != x"/" ] + then + echo $PWD/$1 + else + echo $1 + fi +} + +build_make_symlinks() +{ + # $1 = directory to check + # $2 = make_symlinks file to create or append to + dir=$1 + outfile=$2 + # outputs make_symlinks contents + ( + cd $dir + # file outputs: + # ./makefile: symbolic link to `ofed_scripts/makefile' + find . -type l|xargs -r file|sed -e 's/:[ ]*symbolic link to `/ /' -e 's/:[ ]*broken symbolic link to `/ /' -e "s/'\$//"|sort|while read dest source + do + subdir=$(dirname $dest) + if [ "$subdir" = "." ] + then + echo "[ -h $dest ] || ln -s $source $dest" + else + echo "[ -h $dest ] || { mkdir -p $subdir && ln -s $source $dest; }" + fi + done + ) >> $outfile + chmod +x $outfile +} + + +build_flags= +patch_kernel=n +kernel_ver=`uname -r` +source_dir=$PWD +dest_dir=$PWD/SOURCE_TREE +vopt="" +aflag=n +cleansym=n +while getopts as:d:pLV:v param +do + case $param in + a) aflag=y;; + s) source_dir="$OPTARG";; + d) dest_dir="$OPTARG";; + p) patch_kernel=y;; + L) cleansym=y;; + V) kernel_ver="$OPTARG";; + v) vopt="-v";; + *) Usage;; + esac +done +shift $(($OPTIND -1)) + +unset IFS # use default so enable word expansion + +dest_dir=$(fix_dir $dest_dir) +source_dir=$(fix_dir $source_dir) + +mkdir -p $dest_dir + + +gettaropt() +{ + # $1 is tarfile name + case $1 in + *.tgz) taropt=z;; + *.tar.gz) taropt=z;; + *.tar.bz2) taropt=j;; + *) echo "Unknown tarfile format: $tarfile"; exit 1 + esac +} + +querysrpm() +{ + # $1 = src.rpm file + package=$(rpm -q --queryformat '[%{NAME}\n]' -p $1) + [ x"$package" != x ] || exit 1 + # OFED has 2 versions of open-iscsi-generic. Separate out the RH4 version + if [ $(basename $1 .src.rpm) = "open-iscsi-generic-2.0-754.1" ] + then + package="open-iscsi-generic-rh4" + fi + specfile=$(rpm -q --queryformat '[%{FILENAMES}\n]' -p $1|grep '.spec$') + [ x"$specfile" != x ] || exit 1 + tarfile=$(rpm -q --queryformat '[%{FILENAMES}\n]' -p $1|egrep '.tgz$|.tar.gz$|.tar.bz2$') + [ x"$tarfile" != x ] || exit 1 + otherfiles=$(rpm -q --queryformat '[%{FILENAMES}\n]' -p $1|egrep -v '.spec$|.tgz$|.tar.gz$|.tar.bz2$'|tr '\n' ' ') + + gettaropt $tarfile +} + +copy_ofed_misc() +{ + # source_dir is a OFED install tree + package=ofed_misc + ( + rm -rf $dest_dir/$package + mkdir $dest_dir/$package + cd $source_dir + #cp -r docs BUILD_ID LICENSE README.txt install.pl uninstall.sh $dest_dir/$package + find . -type f ! -name '*.src.rpm'| sed -e 's|^\./||'|sort > $dest_dir/$package/FILELIST + build_make_symlinks . $dest_dir/$package/make_symlinks + cat $dest_dir/$package/FILELIST|cpio -pdv $dest_dir/$package + ) + [ -d $dest_dir/$package ] || exit 1 +} + +if [ $# -eq 0 ] +then + if [ "$aflag" = y ] + then + copy_ofed_misc + srpms_dir=$source_dir/SRPMS + rm -f $dest_dir/package_list + else + srpms_dir=$source_dir + fi + + echo "Expanding SRPMS in $srpms_dir into $dest_dir..." + + cd $srpms_dir + set $(echo *.src.rpm) + if [ x"$1" = x'*src.rpm' ] + then + echo "expand_source: No SRPMS found in $srpms_dir" >&2 + exit 2 + fi +fi + +for srpm in "$@" +do + if [ ! -e $srpm ] + then + echo "expand_source: $srpm: Not Found" >&2 + exit 1 + fi + + echo "Expanding $srpm into $dest_dir..." + querysrpm $srpm + srpm_basename=$(basename $srpm) + + ( + # OFED has some packages with the same .spec filename (eg. dapl and + # compat-dapl), so we need to keep each package completely separated + rm -rf $dest_dir/$package + mkdir $dest_dir/$package + rpm -ivh --define "_topdir $dest_dir/$package" $srpm + if [ ! -d $dest_dir/$package ] + then + echo "expand_source: unable to install $srpm to $dest_dir/$package" >&2 + exit 1 + fi + cd $dest_dir/$package + + cd SOURCES + # assume tarfile creates one srcdir + srcdir=$(tar tf$taropt $tarfile|sed -e 's/\/.*//'|sort -u) + rm -rf $srcdir + tar xf$taropt $tarfile $vopt + if [ $? -ne 0 -o ! -d "$srcdir" ] + then + echo "expand_source: $srpm: Failed to untar $tarfile into $srcdir" + exit 1 + fi + rm -f $tarfile + mv $srcdir ../src + if [ x"$otherfiles" != x ] + then + mv $otherfiles .. + fi + cd .. + + mv SPECS/$specfile . + rmdir SOURCES SPECS + + # add $package to package list + if [ -f $dest_dir/package_list ] + then + echo "$package"|cat - $dest_dir/package_list|sort -u > $dest_dir/.temp + mv $dest_dir/.temp $dest_dir/package_list + else + echo "$package" > $dest_dir/package_list + fi + + echo "#package srpm specfile srcdir tarfile otherfiles" > $dest_dir/$package/namemap + echo "$package $srpm_basename $specfile $srcdir $tarfile $otherfiles" >> $dest_dir/$package/namemap + + # the source control system will not store symlinks + # so make a file which can re-create symbolic links. + echo "cd src" > $dest_dir/$package/make_symlinks + build_make_symlinks $dest_dir/$package/src $dest_dir/$package/make_symlinks + + # optional patching of ofa_kernel + case $srpm in + *ofa_kernel*) + if [ $patch_kernel = y ] + then + echo "Patching ofa_kernel for $kernel_ver..." + cd src + ofed_scripts/ofed_patch.sh --kernel-version=$kernel_ver + rm -rf kernel_patches */patches + cd .. + fi + ;; + esac + if [ $cleansym = y ] + then + find . -type l|xargs rm -f + fi + exit 0 + ) + [ $? -ne 0 ] && exit 1 +done +exit 0 diff --git a/MakeTools/finddspfiles.sh b/MakeTools/finddspfiles.sh new file mode 100755 index 0000000..3a35f4a --- /dev/null +++ b/MakeTools/finddspfiles.sh @@ -0,0 +1,81 @@ +#!/bin/bash +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** +# +# File: finddspfiles +# +# Purpose: outputs a list of dsp files for use in building a dsw file +# +# The DSP names provided as arguments can be actual dsp filenames or +# the names of directories (relative to TL_DIR) +# When a directory name is provided, the corresponding dsp filename is +# constructed by appending DSP_SUFFIX to to. +# +# At present absolute path names for dsp files are not supported +# $TL_DIR will be prefixed to all names given. In the future +# absolute paths could be supported (would they be C: or /cygwin style?) +# +# The output will be full pathnames to stdout +# +# Typical use is: +# NAMES=Gen Osa Something/Dir/project.dsp +# builddsw -f dswfile `finddspfiles $TL_DIR $DSP_SUFFIX $NAMES` +# + +Usage() { + cmd="Usage: ${0} \$TL_DIR \$DSP_SUFFIX name1 name2 ..." + echo -e ${cmd} + return +} + +if [ $# -le 2 ] +then + Usage + exit 2 +fi + +TL_DIR="${1}" +DSP_SUFFIX="${2}" +shift +shift +while [ "${1}" != "" ] +do + pathname="${TL_DIR}/${1}" + if [ -d "$pathname" ] + then + # append project.dsp, where project is last directories name + project=`basename "$pathname"` + echo "$pathname/${project}${DSP_SUFFIX}" + else + # assume its a full dsp filename + echo "$pathname" + fi + shift +done +exit 0 diff --git a/MakeTools/format_releasetag.sh b/MakeTools/format_releasetag.sh new file mode 100755 index 0000000..3f978d0 --- /dev/null +++ b/MakeTools/format_releasetag.sh @@ -0,0 +1,496 @@ +#!/bin/bash +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2019, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +#[ICS VERSION STRING: unknown] + + +# Parse release tags to create version strings +# - X.Y.m.p.b - a build on the way to final +# - X.Y.mAn.b – Alpha “n” build (sometimes called release candidate in redhat terminology) +# - X.Y.mBn.b – Beta “n” build (sometimes called release candidate in redhat terminology) +# - X.Y.mRCn.b – final release candidate “n” build +# - X.Y.m.0.b – a final PV release +# - X.Y.m.p.b – a patch of a PV release +# +# 32-bit hex (UEFI) +# - X – 4 bits +# - Y - 8 bits +# - m – 4 bits +# quality – 4 bits (0-2=power on, 3-5 = Alpha, 6-8=Beta, 9-13=release candidates, 14=PRQ/PV, 15=patch) +# for quality=0-14: b – 12 bits +# when quality==15: p-4 bits, b - 8 bits [unlikely to be used, but covers in case we need it] +# +# 64-bit hex (switch firmware) +# - X – 8 bits +# - Y - 8 bits +# - m – 8 bits +# - quality – 4 bit (0-2=power on, 3-5 = Alpha, 6-8=Beta, 9-13=release candidates, 14=PRQ/PV or patch) +# - patch – 4 bits +# - build – 32 bits +# +# Also allow for user-named version of format 0 + + + +checkAlpha() +{ + if [ $user_ver -eq 1 ] + then + return 0 + fi + + pos=$1 + ver=$2 + + if [ "$ver" = "" ] + then + return 0 + fi + + if echo $ver | grep -qe [[:alpha:]] + then + if echo $ver | grep -qv I + then + echo Error: invalid alpha character in $pos: $ver + return 1 + fi + fi + return 0 +} + +parseOutI() +{ + ver=$1 + + iP=$(echo $ver | grep -bo I | head -n 1 | cut -d: -f1) + v1=${ver:0:iP} + echo $v1 +} + +parseBldI() +{ + ver=$1 + + iP=$(echo $ver | grep -bo I | head -n 1 | cut -d: -f1) + bld=${ver:$((iP + 1))} + echo $bld +} + +getQual() +{ + qual=$1 + pat=$2 + n=$3 + + if [ $pat -ne 0 ] + then + echo 15 + else + case $qual in + poweron) + if [ $n -gt 2 ] + then + (>&2 echo "Warning: Encoded Quality out of range: $n Clamping to: 2") + n=2 + fi + echo $n + ;; + alpha) + n=$((3 + n)) + if [ $n -gt 5 ] + then + (>&2 echo "Warning: Encoded Quality out of range: $n Clamping to: 5") + n=5 + fi + echo $n + ;; + beta) + n=$((6 + n)) + if [ $n -gt 8 ] + then + (>&2 echo "Warning: Encoded Quality out of range: $n Clamping to: 8") + n=8 + fi + echo $n + ;; + rc) + n=$((9 + n)) + if [ $n -gt 13 ] + then + (>&2 echo "Warning: Encoded Quality out of range: $n Clamping to: 13") + n=13 + fi + echo $n + ;; + pv) + echo 14 + ;; + esac + fi + return +} + +if [ "$#" -eq 0 ] +then + echo Error: too few arguments + echo Usage: format_releasetag.sh [-f format] version-string + exit 1 +fi + +if [ "$1" = "" ] +then + echo Error: invalid version string argument + echo Usage: format_releasetag.sh [-f format] version-string + exit 1 +fi + +fmt= +ver= + +while getopts "f:" opt +do + case "$opt" in + f) + fmt=$OPTARG + ;; + ?) + echo Error: unsupported option $opt + echo Usage: format_releasetag.sh [-f format] version-string + exit 1 + ;; + esac +done + +shift $((OPTIND-1)) + +ver=$1 + +# check for user-named release tag - leading 0 followed by alpha + +user_ver=0 +if echo ${ver:0:1} | grep -q 0 +then + if echo ${ver:1:1} | grep -q '[[:alpha:]]' + then + user_ver=1 + fi +fi + +if [ "$2" != "" ] +then + echo Error: extra arguments + echo Usage: format_releasetag.sh [-f format] version-string + exit 1 +fi + +if [ "$fmt" = "" ] +then + fmt=text +fi + +if echo $ver | grep -q '[^ A-Za-z0-9_.]' +then + echo Error: bad format of version $ver + exit 1 +fi + +# strip off leading 'R' + +if echo ${ver:0:1} | grep -q R +then + ver=${ver:1} +fi + +# get to all underscores and parse + +newver=$(echo $ver | sed 's/\./_/g') +numseparators=$(echo $newver | grep -bo '_'|wc -l) +maj=$(echo $newver | cut -d_ -f1) +if [ $numseparators -gt 0 ] +then + min=$(echo $newver | cut -d_ -f2) +else + min=0 +fi +if [ $numseparators -gt 1 ] +then + mai=$(echo $newver | cut -d_ -f3) +else + mai=0 +fi +if [ $numseparators -gt 2 ] +then + pat=$(echo $newver | cut -d_ -f4) +else + pat=0 +fi +if [ $numseparators -gt 3 ] +then + bld=$(echo $newver | cut -d_ -f5) +else + bld=0 +fi + +# alpha only allowed in $mai +checkAlpha major "$maj" || exit 1 +checkAlpha minor "$min" || exit 1 +checkAlpha patch "$pat" || exit 1 +checkAlpha build "$bld" || exit 1 + +# Handle no mai/pat/bld + +if [ "$mai" = "" ] +then + mai=0 +fi +if [ "$pat" = "" ] +then + pat=0 +fi +if [ "$bld" = "" ] +then + bld=0 +fi + +# handle I format + +if echo $maj | grep -q I +then + bld=$(parseBldI $maj) + maj=$(parseOutI $maj) +fi +if echo $min | grep -q I +then + bld=$(parseBldI $min) + min=$(parseOutI $min) +fi +if echo $mai | grep -q I +then + bld=$(parseBldI $mai) + mai=$(parseOutI $mai) +fi +if echo $pat | grep -q I +then + bld=$(parseBldI $pat) + pat=$(parseOutI $pat) +fi + +# parse maintenance in the form mn + +mai_alpha=0 + +m= +n= +alpha=PV +if echo $mai | grep -q [[:alpha:]] +then + mai_alpha=1 + pat=0 + alphaP=$(echo $mai | grep -bo '[[:alpha:]]'|head -n 1|cut -d: -f1) + nP1=$(echo ${mai:$alphaP} | grep -bo '[[:digit:]]'|head -n 1|cut -d: -f1) + nP=$((alphaP + nP1)) + m=${mai:0:alphaP} + alpha=${mai:alphaP:$((dP-alphaP))} + n=${mai:$nP} + bld=$(echo $newver | cut -d_ -f4) + if echo $alpha | grep -q I + then + iformat=1 + else + iformat=0 + fi + if echo $alpha | grep -q P + then + qual=poweron + elif echo $alpha | grep -q A + then + qual=alpha + alpha=$(echo $alpha | tr '[:upper:]' '[:lower:]') + elif echo $alpha | grep -q B + then + qual=beta + alpha=$(echo $alpha | tr '[:upper:]' '[:lower:]') + elif echo $alpha | grep -q RC + then + qual=rc + alpha=$(echo $alpha | tr '[:upper:]' '[:lower:]') + elif echo $alpha | grep -q PV + then + qual=pv + elif [ $user_ver -eq 1 ] + then + qual=pv + elif [ $iformat -eq 0 ] + then + echo Error: Unknown release tag quality: $alpha + exit 1 + fi + if [ $iformat -eq 1 ] + then + iP=$(echo $mai | grep -bo I |head -n 1|cut -d: -f1) + bld=${mai:$((iP+1))} + else + bld=$(echo $newver | cut -d_ -f4) + fi +else + qual=pv +fi + + +case $fmt in + text) + if [ $user_ver -eq 1 ] + then + echo $ver + exit 0 + fi + q=$(getQual $qual $pat $n) + if [ $mai_alpha -eq 1 ] + then + echo ${maj}.${min}.${mai}.${bld} + else + echo ${maj}.${min}.${mai}.${pat}.${bld} + fi + ;; + rpm) + if [ $user_ver -eq 1 ] + then + echo $ver + exit 0 + fi + q=$(getQual $qual $pat $n) + if [ $mai_alpha -eq 1 ] + then + echo ${maj}.${min}.${m}.0-${alpha}${n}.${bld} + else + echo ${maj}.${min}.${mai}.${pat}-${bld} + fi + ;; + briefrpm) + if [ $user_ver -eq 1 ] + then + echo $ver + exit 0 + fi + if [ $mai_alpha -eq 1 ] + then + m1=$m + else + m1=$mai + fi + if [ $pat -gt 0 ] + then + maint=".${m1}.${pat}" + elif [ $m1 -gt 0 ] + then + maint=".${m1}" + else + maint= + fi + q=$(getQual $qual $pat $n) + if [ $mai_alpha -eq 1 ] + then + echo ${maj}.${min}${maint}-${alpha}${n}.${bld} + else + echo ${maj}.${min}${maint}-${bld} + fi + ;; + debian) + if [ $user_ver -eq 1 ] + then + echo $ver + exit 0 + fi + q=$(getQual $qual $pat $n) + if [ $mai_alpha -eq 1 ] + then + echo ${maj}.${min}.${m}.0${alpha}${n}.${bld} + else + echo ${maj}.${min}.${mai}.${pat}.${bld} + fi + ;; + 32bit) + if [ $user_ver -eq 1 ] + then + echo 0x00000000 + exit 0 + fi + if [ $mai_alpha -eq 1 ] + then + m1=$m + else + m1=$mai + fi + byte1=$((maj<<4 | min&0xf0)) + byte2=$(((min & 0x0f)<<4 | (m1 & 0x0f))) + q=$(getQual $qual $pat $n) + if [ $pat -gt 0 ] + then + byte3=$((q<<4 | (pat & 0xff))) + else + bldHiBits=$(((bld & 0xf00) >> 8)) + byte3=$((q<<4 | bldHiBits)) + fi + byte4=$((bld & 0xff)) + printf "0x%02X%02X%02X%02X\n" $byte1 $byte2 $byte3 $byte4 + ;; + 64bit) + if [ $user_ver -eq 1 ] + then + echo 0x0000000000000000 + exit 0 + fi + byte1=${maj} + byte2=${min} + if [ $mai_alpha -eq 1 ] + then + m1=$m + else + m1=$mai + fi + byte3=${m1} + if [ $pat -gt 0 ] + then + q=14 + else + q=$(getQual $qual $pat $n) + fi + byte4=$((q<<4 | (pat & 0xff))) + bytes5to8=$bld + printf "0x%02X%02X%02X%02X%08X\n" $byte1 $byte2 $byte3 $byte4 $bytes5to8 + ;; + ?) + echo Error: bad format: $fmt + exit 1 + ;; +esac + + +exit 0 diff --git a/MakeTools/funcs-ext.sh b/MakeTools/funcs-ext.sh new file mode 100755 index 0000000..9aa4cd2 --- /dev/null +++ b/MakeTools/funcs-ext.sh @@ -0,0 +1,1316 @@ +#!/bin/bash -v +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# Override default funcs.sh functions from $ICSBIN. + +#Following taken from funcs.sh +# These are included here to permit rpm builds by customers without needing +# our devtools (which includes funcs.sh) +# to aid tracking, if a change is needed for any of these functions +# move the given function toward the bottom of the script after the +# "END TAKEN FROM FUNCS.SH" line and then make the necessary edits +# this way it will be clear which functions should track devtools and which +# represent possibly product or generation specific adjustments +# This way this script will also have only 1 copy of each function and +# hence will avoid confusion to others reading it + +#--------------------------------------------------------------------------- +# Function: toupper +# In Script: funcs.sh +# Arguments: a string to convert to upper case +# Description: converts the given string to upper case +# and returns the result to stdout +# only alphabetic characters are affected +# Uses: +# None +#--------------------------------------------------------------------------- +function toupper() +{ + echo "$1"|tr '[a-z]' '[A-Z]' +} # end function + +#--------------------------------------------------------------------------- +# Function: getBuildPlatform +# In Script: funcs.sh +# Arguments: none +# Description: echo only the first six characters of the system name +# Uses: +# None +#--------------------------------------------------------------------------- +function getBuildPlatform() +{ + echo `uname -s | cut -c1-6` +} # end function + +#--------------------------------------------------------------------------- +# Function: findTopDir +# In Script: funcs.sh +# Arguments: $1 --silent +# Description: return top level directory +# if --silent, the if top level not found then return $PWD +# else return an error message +# Uses: +# None +#--------------------------------------------------------------------------- +function findTopDir() +{ + if [ `getBuildPlatform` == "CYGWIN" ]; then + tl_dir=`cygpath -w $PWD | sed 's/\\\/\//g'` + else + tl_dir=`pwd` + fi + while [ ! -f "$tl_dir/Makerules/Makerules.global" ] + do + tl_dir=`dirname $tl_dir` + if [ "$tl_dir" == "/" -o "$tl_dir" == "." ] + then + if [ "$1" == "--silent" ]; then + return + else + echo "Unable to locate TL_DIR, Makerules not found" >&2 + return + fi + fi + done + + echo $tl_dir +} # end function + +#--------------------------------------------------------------------------- +# Function: settl +# In Script: funcs.sh +# Arguments: +# Description: find the top level directory, and set TL_DIR, else +# set TL_DIR to the currect directory +# Uses: +# None +#--------------------------------------------------------------------------- +function settl() +{ + + export TL_DIR=`findTopDir --silent` +} # end function + +#--------------------------------------------------------------------------- +# Function: setwindbase +# In Script: funcs.sh +# Arguments: directory for WIND_BASE +# Description: sets WIND_BASE and related variables +# WIND_BASE, WIND_HOST_TYPE, WRS_HOST, WRS_BIN, +# MIPS_BIN, MIPS_LIB, MIPS_PATH, UWIND_BASE, WIN_WRS_BIN +# Uses: +# None +#--------------------------------------------------------------------------- +setwindbase() +{ + #### WindRiver Tornado 2 Environment Variables + ## we compute UWIND_BASE and WIN_WRS_BIN here to save time + ## during make (ie. it doesn't have to be recomputed in each makefile) + + + if [ "$1" == "" ]; then + export WIND_BASE= + return + fi + + + if [ `getBuildPlatform` == "CYGWIN" ]; then + + export WIND_BASE=`cygpath -w $1 | sed 's/\\\/\//g'` + export WIND_HOST_TYPE=x86-win32 + + else + + export WIND_BASE=$1 + export WIND_HOST_TYPE=unix + fi + + export WRS_HOST=$WIND_BASE/host/$WIND_HOST_TYPE + export WRS_BIN=$WRS_HOST/bin + +} # end function + +#--------------------------------------------------------------------------- +# Function: isAllEmb +# In Script: funcs.sh +# Arguments: +# Description: determine if environment is an embedded checkout +# Uses: +# None +#--------------------------------------------------------------------------- +function isAllEmb() +{ + if [ "$TL_DIR" == "" ]; then + settl + fi + + [ `ls -d $TL_DIR/*_Firmware 2>/dev/null|wc -l` -ne 0 ] +} # end function + +#--------------------------------------------------------------------------- +# Function: setbsp +# In Script: funcs.sh +# Arguments: none +# Description: show available bsp's for TL_DIR project. +# Uses: +# None +#--------------------------------------------------------------------------- +function setbsp() +{ + local x=0 + local topLevelDir + local the_selection + + if [ "$1" == "" ]; then + if [ "$TL_DIR" == "" ]; then + topLevelDir=`findTopDir` + else + topLevelDir=$TL_DIR + fi + + SUPPORTED_BSP_FILE="" + if [ -f "$topLevelDir/SUPPORTED_TARGET_BSPS" ]; then + SUPPORTED_BSP_FILE="$topLevelDir/SUPPORTED_TARGET_BSPS" + fi + if [ -f "$topLevelDir/$PROJ_FILE_DIR/SUPPORTED_TARGET_BSPS" ]; then + SUPPORTED_BSP_FILE="$topLevelDir/$PROJ_FILE_DIR/SUPPORTED_TARGET_BSPS" + fi + if [ "$SUPPORTED_BSP_FILE" != "" ]; then + for i in `cat $SUPPORTED_BSP_FILE` + do + echo "$(( x += 1 )) ) $i" + done + + printf "choice: " + read the_selection + + export TARGET_BSP=`cut -d" " -f$the_selection $SUPPORTED_BSP_FILE` + if [ "$TL_DIR" != "" ]; then + echo $TARGET_BSP > $TL_DIR/.defaultBSP + fi + else + echo "Can not find SUPPORTED_TARGET_BSPS file in TL_DIR ($TL_DIR) or in a Firmware directory - try doing setct first" + fi + else + export TARGET_BSP=$1 + if [ "$TL_DIR" != "" ]; then + echo $TARGET_BSP > $TL_DIR/.defaultBSP + fi + fi + if [ "$TARGET_BSP" != "" ]; then + if [ "$PROJ_FILE_DIR" != "" ]; then + grep -qsw "$TARGET_BSP" "$TL_DIR/$PROJ_FILE_DIR/SUPPORTED_TARGET_BSPS" + else + grep -qsw "$TARGET_BSP" "$TL_DIR/SUPPORTED_TARGET_BSPS" + fi + + if [ $? -ne 0 ] ; then + echo "Warning: '$TARGET_BSP' does not appear do be a supported BSP (using it anyway)" + fi + fi + +} # end function + +#--------------------------------------------------------------------------- +# Function: resetct +# In Script: funcs.sh +# Arguments: none +# Description: clear card type for ALL_EMB builds +# Uses: +# None +#--------------------------------------------------------------------------- +function resetct() +{ + unset CARD_TYPE + unset PROJ_FILE_DIR + if [ "$TL_DIR" != "" ]; then + rm -f $TL_DIR/.defaultCT + fi + echo "CARD_TYPE has been reset" +} + +#--------------------------------------------------------------------------- +# Function: targetos +# In Script: funcs.sh +# Arguments: 1 = target operating system +# Description: specify target operating system for make to build for +# Uses: +# sets BUILD_TARGET_OS +#--------------------------------------------------------------------------- +function targetos() +{ + local targetOsType=`toupper $1` + + if [ `getBuildPlatform` == "CYGWIN" ]; then + + case $targetOsType in + VXWORKS) + export BUILD_TARGET_OS=VXWORKS + ;; + WIN32) + export BUILD_TARGET_OS=WIN32 + ;; + CYGWIN) + export BUILD_TARGET_OS=CYGWIN + ;; + *) + printf "Usage: targetos [cygwin|vxworks|win32]\n\n" + return + ;; + esac + elif [ `getBuildPlatform` == "Darwin" ]; then + case $targetOsType in + DARWIN) + export BUILD_TARGET_OS=DARWIN + ;; + *) + printf "Usage: targetos [darwin]\n\n" + return + ;; + esac + else + case $targetOsType in + VXWORKS) + export BUILD_TARGET_OS=VXWORKS + ;; + LINUX) + export BUILD_TARGET_OS=LINUX + ;; + *) + printf "Usage: targetos [linux]\n\n" + return + ;; + esac + fi + + echo "Build target operating system set to $BUILD_TARGET_OS" +} # end function + + + +################################################################################ +####END TAKEN FROM FUNCS.SH +################################################################################ + + + +# NOTE: This function changes often when environment variables are added +# to display to end users. +#--------------------------------------------------------------------------- +# Function: showenv +# In Script: funcs-ext.sh +# Arguments: none +# Description: show the intel cde environment settings +# Uses: +# None +#--------------------------------------------------------------------------- +function showenv() +{ + local SMP + + printf "Intel CDE Environment Settings:\n\n" + + if [[ "$BUILD_TARGET" == "" || "$1" == "-h" ]]; then + local TARGET_COMMENT="[use: target] " + fi + if [[ "$BUILD_UNIT_TEST" == "" || "$1" == "-h" ]]; then + local UNIT_TEST_COMMENT="[use: settest|setnotest] " + fi + if [[ "$BUILD_CONFIG" == "" || "$1" == "-h" ]]; then + local CONFIG_COMMENT="[use: setdbg|setrel command] " + fi + if [[ "$BUILD_TARGET_OS_VERSION" == "" || "$1" == "-h" ]]; then + local OS_COMMENT="[use: setver] " + fi + if [[ "$RELEASE_TAG" == "" || "$1" == "-h" ]]; then + local RELEASE_TAG_COMMENT="[use: export RELEASE_TAG=R#] " + fi + if [[ "$OPA_FEATURE_SET" == "" || "$1" == "-h" ]]; then + local OPA_FEATURE_SET_COMMENT="[use: setfs] " + fi + + echo "Build Target : $TARGET_COMMENT$BUILD_TARGET" + echo "Build Target OS : $TARGET_COMMENT$OS_COMMENT$BUILD_TARGET_OS_VENDOR $BUILD_TARGET_OS $BUILD_TARGET_OS_VERSION $SMP" + echo "Build Platform : $TARGET_COMMENT$BUILD_PLATFORM_OS_VENDOR $BUILD_PLATFORM" + echo "Build Target Tools : $TARGET_COMMENT$BUILD_TARGET_TOOLCHAIN" + echo "Build Unit Test : $UNIT_TEST_COMMENT$BUILD_UNIT_TEST" + echo "Build Configuration: $CONFIG_COMMENT$BUILD_CONFIG" + echo "Release Tag : $RELEASE_TAG_COMMENT$RELEASE_TAG" + echo "Build Feature Set : $OPA_FEATURE_SET_COMMENT$OPA_FEATURE_SET" + + if [ "$BUILD_TARGET_OS" == "VXWORKS" ]; then + if [[ "$BUILD_TMS" == "" || "$1" == "-h" ]]; then + local TMS_COMMENT="[use: export BUILD_TMS=(yes|no)] " + fi + if [[ "$TGT_SUBDIR_NAME" == "" || "$1" == "-h" ]]; then + local SUBDIR_COMMENT="[use: export TGT_SUBDIR_NAME=(target|tmsTarget)] " + fi + if [[ "$EVAL_HARDWARE" == "" || "$1" == "-h" ]]; then + local EVAL_COMMENT="[use: export EVAL_HARDWARE=(yes|no)] " + fi + if [[ "$NO_SSP" == "" || "$1" == "-h" ]]; then + local SSP_COMMENT="[use: export NO_SSP=(1|0)] " + fi + if [[ "$STOP_ON_ERROR" == "" || "$1" == "-h" ]]; then + local STOP_ON_ERROR_COMMENT="[use: export STOP_ON_ERROR=(yes|no)] " + fi + if [[ "$TARGET_BSP" == "" || "$1" == "-h" ]]; then + local BSP_COMMENT="[use: setbsp (`cat $TL_DIR/SUPPORTED_TARGET_BSPS 2> /dev/null`)] " + fi + if [[ "$WIND_BASE" == "" || "$1" == "-h" ]]; then + local WIND_BASE_COMMENT="[use: target | setwindbase] " + fi + local CARD_TYPE_COMMENT + if isAllEmb; then + if [[ "$CARD_TYPE" == "" || "$1" == "-h" ]]; then + CARD_TYPE_COMMENT="[use: setct] " + fi + else + if [[ "$CARD_TYPE" != "" || "$1" == "-h" ]]; then + CARD_TYPE_COMMENT="[ALL_EMB only, use: resetct] " + else + CARD_TYPE_COMMENT="[ALL_EMB only] " + fi + fi + if [[ "$WEB_STANDALONE" == "" || "$1" == "-h" ]]; then + local WEB_STANDALONE_COMMENT="[use: export WEB_STANDALONE=(1|0)] " + fi + + echo "Build TMS : $TMS_COMMENT$BUILD_TMS" + echo "Build Target Subdir: $SUBDIR_COMMENT$TGT_SUBDIR_NAME" + echo "EVAL HARDWARE : $EVAL_COMMENT$EVAL_HARDWARE" + echo "NO SSP : $SSP_COMMENT$NO_SSP" + echo "STOP ON ERROR : $STOP_ON_ERROR_COMMENT$STOP_ON_ERROR" + echo "Target BSP : $BSP_COMMENT$TARGET_BSP" + echo "Tornado Base : $WIND_BASE_COMMENT$WIND_BASE" + echo "Card Type : $CARD_TYPE_COMMENT$CARD_TYPE" + echo "Web Standalone : $WEB_STANDALONE_COMMENT$WEB_STANDALONE" + else + if [[ "$OFED_STACK_PREFIX" == "" || "$1" == "-h" ]]; then + local OFED_STACK_PREFIX_COMMENT="[use: export OFED_STACK_PREFIX=/dir] " + fi + #if [[ "$BUILD_ULPS" == "" || "$1" == "-h" ]]; then + # local BUILD_ULPS_COMMENT="[use: setulps 'ulp list'] " + #fi + #if [[ "$BUILD_SKIP_ULPS" == "" || "$1" == "-h" ]]; then + # local BUILD_SKIP_ULPS_COMMENT="[use: setskipulps 'ulp list'] " + #fi + echo "OFED Stack Prefix : $OFED_STACK_PREFIX_COMMENT$OFED_STACK_PREFIX" + #echo "Build ULPs : $BUILD_ULPS_COMMENT$BUILD_ULPS" + #echo "Build Skip ULPs : $BUILD_SKIP_ULPS_COMMENT$BUILD_SKIP_ULPS" + fi + + if [[ "$TL_DIR" == "" || "$1" == "-h" ]]; then + local TL_DIR_COMMENT="[use: target] " + fi + echo "Top Level Directory: $TL_DIR_COMMENT$TL_DIR" + + if [[ "$PROJ_FILE_DIR" == "" || "$1" == "-h" ]]; then + local PROJ_FILE_DIR_COMMENT="[use: export PROJ_FILE_DIR as needed] " + fi + echo "Proj File Dir : $PROJ_FILE_DIR_COMMENT$PROJ_FILE_DIR" + + if [[ "$PRODUCT" == "" || "$1" == "-h" ]]; then + local PRODUCT_COMMENT="[use: export PRODUCT as needed] " + fi + echo "Product : $PRODUCT_COMMENT$PRODUCT" + +} # end function + +setbsp () +{ + local x=0; + local topLevelDir; + local the_selection; + if [ "$1" == "" ]; then + if [ "$TL_DIR" == "" ]; then + topLevelDir=`findTopDir`; + else + topLevelDir=$TL_DIR; + fi; + SUPPORTED_BSP_FILE=""; + if [ -f "$topLevelDir/SUPPORTED_TARGET_BSPS" ]; then + SUPPORTED_BSP_FILE="$topLevelDir/SUPPORTED_TARGET_BSPS"; + fi; + if [ -f "$topLevelDir/$PROJ_FILE_DIR/SUPPORTED_TARGET_BSPS" ]; then + SUPPORTED_BSP_FILE="$topLevelDir/$PROJ_FILE_DIR/SUPPORTED_TARGET_BSPS"; + fi; + if [ "$SUPPORTED_BSP_FILE" != "" ]; then + for i in `cat $SUPPORTED_BSP_FILE`; + do + echo "$(( x += 1 )) ) $i"; + done; + printf "choice: "; + read the_selection; + export TARGET_BSP=`cut -d" " -f$the_selection $SUPPORTED_BSP_FILE`; + export TARGET_BSP_UPCASE=`echo $TARGET_BSP | tr '[:lower:]' '[:upper:]'` + if [ "$TL_DIR" != "" ]; then + echo $TARGET_BSP >$TL_DIR/.defaultBSP; + fi; + else + echo "Can not find SUPPORTED_TARGET_BSPS file in TL_DIR ($TL_DIR) or in a Firmware directory - try doing setct first"; + fi; + else + export TARGET_BSP=$1; + export TARGET_BSP_UPCASE=`echo $TARGET_BSP | tr '[:lower:]' '[:upper:]'` + if [ "$TL_DIR" != "" ]; then + echo $TARGET_BSP >$TL_DIR/.defaultBSP; + fi; + fi; + if [ "$TARGET_BSP" != "" ]; then + export TARGET_BSP_UPCASE=`echo $TARGET_BSP | tr '[:lower:]' '[:upper:]'` + if [ "$PROJ_FILE_DIR" != "" ]; then + grep -qsw "$TARGET_BSP" "$TL_DIR/$PROJ_FILE_DIR/SUPPORTED_TARGET_BSPS"; + else + grep -qsw "$TARGET_BSP" "$TL_DIR/SUPPORTED_TARGET_BSPS"; + fi; + if [ $? -ne 0 ]; then + echo "Warning: '$TARGET_BSP' does not appear do be a supported BSP (using it anyway)"; + fi; + fi +} + +function settarget() +{ + local targetType=`toupper $1` + local message + + if [[ "$1" == "-h" ]]; then + printf "Usage: target ia32|ia64|x86_64|em64t|mips|atom|ppc|ppc64\n" + return + fi + + export BUILD_PLATFORM_OS_VENDOR=`os_vendor` + export BUILD_PLATFORM_OS_VENDOR_VERSION=`os_vendor_version $BUILD_PLATFORM_OS_VENDOR` + export BUILD_TARGET_OS_VENDOR=$BUILD_PLATFORM_OS_VENDOR + export BUILD_TARGET_OS_VENDOR_VERSION=$BUILD_PLATFORM_OS_VENDOR_VERSION + + if [ `getBuildPlatform` == "CYGWIN" ]; then + + if [ "$TL_DIR" == "" ]; then + settl + fi + + if [ "$WIND_BASE" == "" ]; then + setwindbase $TL_DIR + fi + + isBSP=`toupper $2` + + case $targetType in + MIPS) + targetos VXWORKS + export MIPS_LIB=$WRS_HOST/lib/gcc-lib/mips-wrs-vxworks/cygnus-2.7.2-960126 + export MIPS_PATH=`cygpath -u $WRS_BIN 2> /dev/null` + export BUILD_TARGET_TOOLCHAIN=GNU + export BUILD_TARGET_OS_VERSION=5.4 + export BUILD_TARGET_OS_VENDOR=WindRiver + export BUILD_TARGET=MIPS + ;; + X86|I386) + targetos VXWORKS + export I386_LIB=$WRS_HOST/lib/gcc-lib/i386-wrs-vxworks/cygnus-2.7.2-960126 + export I386_PATH=$WRS_BIN + export BUILD_TARGET_TOOLCHAIN=GNU + export BUILD_TARGET_OS_VERSION=5.4 + export BUILD_TARGET=I386 + ;; + CYGWIN) + targetos CYGWIN + export BUILD_TARGET_TOOLCHAIN=GNU + export BUILD_TARGET=CYGWIN + ;; + WIN32) + targetos WIN32 + export BUILD_TARGET_TOOLCHAIN=WIN32 + export BUILD_TARGET=WIN32 + ;; + *) + printf "Unknown target $1\n" + printf "Usage: target [cygwin | mips | win32] [bsp]\n\n" + return + ;; + esac + + if [ "$isBSP" == "BSP" ]; then + message="for BSP development" + UWRS_BIN=`cygpath -u $WRS_BIN` + export WIND_BASE=`cygpath -w $WIND_BASE 2> /dev/null` + export PATH=`update_path_start $PATH $UWRS_BIN $UWRS_BIN` + fi + elif [ `getBuildPlatform` == "Darwin" ]; then + settl + case $targetType in + PPC) + targetos DARWIN + export BUILD_TARGET_TOOLCHAIN=GNU + export BUILD_TARGET=PPC + ;; + *) + if [ "$1" != "" ]; then + printf "Unknown target $1\n" + fi + printf "Usage: target ppc\n\n" + return + ;; + esac + else + + settl + setwindbase $TL_DIR + + case $targetType in + ATOM) + targetos VXWORKS + export TGT_SUBDIR_NAME=target + export TGT_DIR=$TL_DIR/target + export ATOM_PATH= + export ATOM_LIB=$TGT_DIR/lib/pentium/ATOM/common/libgcc.a + export BUILD_TARGET_TOOLCHAIN=GNU + export BUILD_TARGET_OS_VENDOR=WindRiver + export BUILD_TARGET_OS_VERSION=6.9.4.6 + export BUILD_TARGET=ATOM + export WIND_HOST_TYPE=x86-linux2 + if [ "$LD_LIBRARY_PATH" == "" ] ; then + export LD_LIBRARY_PATH=$TL_DIR/host/wrs/gnu/lib64 + else + export LD_LIBRARY_PATH=$TL_DIR/host/wrs/gnu/lib64:$LD_LIBRARY_PATH + fi + export PATH=$PATH:$ICSLOCAL/Emb_Utils:$TL_DIR/host/wrs/gnu/4.3.3-vxworks-6.9/x86-linux2/bin:$TL_DIR/host/wrs/gnu/4.3.3-vxworks-6.9/x86-linux2/libexec/gcc/i586-wrs-vxworks/4.3.3 + + ;; + MIPS) + targetos VXWORKS + export TGT_SUBDIR_NAME=tmsTarget + export TGT_DIR=$TL_DIR/tmsTarget + export MIPS_PATH= + export MIPS_LIB=$TL_DIR/host/$WIND_HOST_TYPE/lib/gcc-lib/mips-wrs-vxworks/cygnus-2.7.2-960126/mips3/libgcc.a + export BUILD_TARGET_TOOLCHAIN=GNU + export BUILD_TARGET_OS_VENDOR=WindRiver + export BUILD_TARGET_OS_VERSION=5.4 + export BUILD_TARGET=MIPS + ;; + LINUX) + targetos LINUX + export BUILD_TARGET_TOOLCHAIN=GNU + export BUILD_TARGET=IA32 + ;; + IA32) + targetos LINUX + export BUILD_TARGET_TOOLCHAIN=GNU + export BUILD_TARGET=IA32 + ;; + LINUX64) + targetos LINUX + export BUILD_TARGET_TOOLCHAIN=GNU + export BUILD_TARGET=IA64 + ;; + IA64) + targetos LINUX + export BUILD_TARGET_TOOLCHAIN=GNU + export BUILD_TARGET=IA64 + ;; + X86_64) + targetos LINUX + export BUILD_TARGET_TOOLCHAIN=GNU + export BUILD_TARGET=X86_64 + ;; + PPC64) + targetos LINUX + export BUILD_TARGET_TOOLCHAIN=GNU + export BUILD_TARGET=PPC64 + ;; + EM64T) + targetos LINUX + export BUILD_TARGET_TOOLCHAIN=GNU + export BUILD_TARGET=EM64T + ;; + *) + if [ "$1" != "" ]; then + printf "Unknown target $1\n" + fi + printf "Usage: target ia32|ia64|x86_64|em64t|mips|atom|ppc64\n\n" + return + ;; + esac + fi + set_os_identifier + + echo "Build target set to $BUILD_TARGET $message" + + if isAllEmb && [[ "$BUILD_TARGET_OS" = "VXWORKS" ]]; then + if [ -e "$TL_DIR/.defaultCT" ]; then + export CARD_TYPE=`cat $TL_DIR/.defaultCT 2>&1 /dev/null` + export PROJ_FILE_DIR=$CARD_TYPE"_Firmware" + echo "Card type set to $CARD_TYPE" + fi + else + resetct > /dev/null + fi + + if [[ "$BUILD_TARGET_OS" = "VXWORKS" && -e "$TL_DIR/.defaultBSP" ]]; then + export TARGET_BSP=`cat $TL_DIR/.defaultBSP 2>&1 /dev/null` + export TARGET_BSP_UPCASE=`echo $TARGET_BSP | tr '[:lower:]' '[:upper:]'` + echo "Target BSP is ${TARGET_BSP:-empty.}" + fi + + if [[ -e "$TL_DIR/.defaultBuildConfig" ]]; then + export BUILD_CONFIG=`cat $TL_DIR/.defaultBuildConfig 2>&1 /dev/null` + echo "Build Configuration is ${BUILD_CONFIG:-empty.}" + fi + if [[ -e "$TL_DIR/.defaultBuildUlps" ]]; then + export BUILD_ULPS=`cat $TL_DIR/.defaultBuildUlps 2>&1 /dev/null` + echo "Build ULPs is ${BUILD_ULPS:-empty.}" + else + export BUILD_ULPS=${BUILD_ULPS:-all} + fi + if [[ -e "$TL_DIR/.defaultBuildSkipUlps" ]]; then + export BUILD_SKIP_ULPS=`cat $TL_DIR/.defaultBuildSkipUlps 2>&1 /dev/null` + echo "Build Skip ULPs is ${BUILD_SKIP_ULPS:-empty.}" + else + export BUILD_SKIP_ULPS=${BUILD_SKIP_ULPS:-none} + fi +} # end function + +# NOTE: This function is changed whenever we add different platform or +# target support. +#--------------------------------------------------------------------------- +# Function: os_vendor +# In Script: funcs-ext.sh +# Arguments: none +# Description: determine the os vendor based on build system +#--------------------------------------------------------------------------- +function os_vendor() +{ + if [ -f /etc/os-release ] + then + id=$(grep ^ID= /etc/os-release | cut -f2 -d= | cut -f2 -d\") + case $id in + rhel) + rval=redhat + ;; + sles) + rval=SuSE + ;; + centos) + rval=redhat + ;; + fedora) + rval=redhat + ;; + *) + rval="" + ;; + esac + elif [ `uname -s` == "Darwin" ] + then + # Apple Mac + rval=apple + else + filelist=($('ls' /etc/*-release | egrep -v lsb | egrep -v os)) + rval="" + if [ ${#filelist[@]} -eq 0 ] && [ -f /etc/lsb-release ]; then + rval=$(cat /etc/lsb-release | egrep DISTRIB_ID | cut -d'=' -f2 | tr '[:upper:]' '[:lower:]') + fi + for file in $filelist + do + if [ -f $file ] + then + rval=$(basename $file -release) + if [ $rval = 'SuSE' ] + then + if [ -f /etc/UnitedLinux-release ] + then + rval=UnitedLinux + fi + elif [ $rval = 'centos' ] + then + rval=redhat + elif [ $rval != 'os' ] + then + break + fi + fi + done + fi + echo $rval +} + +# NOTE: This function is changed whenever we add different platform or +# target support. +#--------------------------------------------------------------------------- +# Function: os_vendor_version +# In Script: funcs-ext.sh +# Arguments: 1 = os_vendor +# Description: determine the os vendor release level based on build system +#--------------------------------------------------------------------------- +function os_vendor_version() +{ + if [[ -e /etc/os-release ]]; then + . /etc/os-release + # - use VERSION_ID - it has a common format among distros + # - mimic old way and drop $minor if eq 0 (see redhat handling below) + # - drop '.'(dot) + if [ $1 = "ubuntu" ]; then + rval=ES$(echo $VERSION_ID | sed -e 's/\.//') + else + rval=ES$(echo $VERSION_ID | sed -e 's/\.[0]//' -e 's/\.//') + fi + echo $rval + return + fi + + # using old way if '/etc/os-release' not found + case $1 in + apple) + rval=`sw_vers -productVersion|cut -f1-2 -d.` + ;; + rocks) + rval=`cat /etc/rocks-release | cut -d' ' -f3` + ;; + scyld) + rval=`cat /etc/scyld-release | cut -d' ' -f4` + ;; + mandrake) + rval=`cat /etc/mandrake-release | cut -d' ' -f4` + ;; + fedora) + if grep -qi core /etc/fedora-release + then + rval=`cat /etc/fedora-release | cut -d' ' -f4` + else + rval=`cat /etc/fedora-release | cut -d' ' -f3` + fi + ;; + redhat) + if grep -qi advanced /etc/redhat-release + then + rval=`cat /etc/redhat-release | cut -d' ' -f7` + elif grep -qi enterprise /etc/redhat-release + then + # /etc/redhat-release = "Red Hat Enterprise Linux Server release $a.$b ($c)" + rval="ES"`cat /etc/redhat-release | cut -d' ' -f7 | cut -d. -f1` + major=`cat /etc/redhat-release | cut -d' ' -f7 | cut -d. -f1` + minor=`cat /etc/redhat-release | cut -d' ' -f7 | cut -d. -f2` + if [ \( $major -ge 7 -a $minor -ne 0 \) -o \( $major -eq 6 -a $minor -ge 7 \) ] + then + rval=$rval$minor + fi + elif grep -qi centos /etc/redhat-release + then + # CentOS + rval="ES"`cat /etc/redhat-release | sed -r 's/^.+([[:digit:]])\.([[:digit:]]).+$/\1\2/'` + elif grep -qi scientific /etc/redhat-release + then + # Scientific Linux. + rval="ES"`cat /etc/redhat-release | sed -r 's/^.+([[:digit:]])\.([[:digit:]]).+$/\1/'` + else + rval=`cat /etc/redhat-release | cut -d' ' -f5` + fi + ;; + UnitedLinux) + rval=`grep United /etc/UnitedLinux-release | cut -d' ' -f2` + ;; + SuSE) + if grep -qi enterprise /etc/SuSE-release + then + rval="ES"`grep -i enterprise /etc/SuSE-release | cut -d' ' -f5` + else + rval=`grep -i SuSE /etc/SuSE-release | cut -d' ' -f3` + fi + ;; + turbolinux) + rval=`cat /etc/turbolinux-release | cut -d' ' -f3` + ;; + esac + echo $rval +} + +# NOTE: This function is changed whenever we add different platform or +# target support. +#--------------------------------------------------------------------------- +# Function: os_identifier +# In Script: funcs-ext.sh +# Arguments: None +# Description: generate concise ID for targer/vendor/major version +# Uses: +# BUILD_TARGET, BUILD_TARGET_OS_VENDOR, BUILD_TARGET_OS_VENDOR_VERSION +# sets BUILD_TARGET_OS_ID +function set_os_identifier() +{ + local arch ver + arch=`echo $BUILD_TARGET | tr '[:upper:]' '[:lower:]'` + case "$BUILD_TARGET_OS_VENDOR" in + redhat) + ver=RH$(echo $BUILD_TARGET_OS_VENDOR_VERSION|sed -e 's/ES/EL/' -e 's/\..*//');; + SuSE) + ver=SL$(echo $BUILD_TARGET_OS_VENDOR_VERSION|sed -e 's/\..*//');; + *) + ver="$BUILD_TARGET_OS_VENDOR.$BUILD_TARGET_OS_VENDOR_VERSION"'' + esac + export BUILD_TARGET_OS_ID=$ver-$arch +} + +# NOTE: This function is changed whenever we add different platform or +# target support. +#--------------------------------------------------------------------------- +# Function: target +# In Script: funcs-ext.sh +# Arguments: 1 = target platform +# 2 = bsp [optional] on cygwin build platform only +# Description: specify target platform for make to build for +# Uses: +# sets BUILD_TARGET +# if bsp development is specified then export PATH to allow the +# compiler to be used on the command line +#--------------------------------------------------------------------------- +function target() +{ + local targetType=`toupper $1` + local message + + # always set top level directoy + settl + + export BUILD_PLATFORM_OS_VENDOR=`os_vendor` + export BUILD_PLATFORM_OS_VENDOR_VERSION=`os_vendor_version $BUILD_PLATFORM_OS_VENDOR` + export BUILD_TARGET_OS_VENDOR=$BUILD_PLATFORM_OS_VENDOR + export BUILD_TARGET_OS_VENDOR_VERSION=$BUILD_PLATFORM_OS_VENDOR_VERSION + + # Allows us to override functions that change often. + if [[ "$TL_DIR" != "" && -e "$TL_DIR/MakeTools/funcs-ext.sh" ]]; then + if [[ -e "$ICSBIN/funcs.sh" ]]; then + echo "Resourcing default $ICSBIN/funcs.sh" + . $ICSBIN/funcs.sh $* + . $TL_DIR/MakeTools/funcs-ext.sh $* + echo "Using $TL_DIR/MakeTools/funcs-ext.sh" + settarget $* + else + echo "The development environment is not properly configured. Please source ics.sh file." + return + fi + else + if [[ "$1" == "-h" ]]; then + printf "Usage: target ia32|ia64|x86_64|em64t|mips|atom|ppc64\n" + return + fi + + echo "Using default functions." + if [ `getBuildPlatform` == "CYGWIN" ]; then + + if [ "$TL_DIR" == "" ]; then + settl + fi + + if [ "$WIND_BASE" == "" ]; then + setwindbase $TL_DIR + fi + + isBSP=`toupper $2` + + case $targetType in + ATOM) + targetos VXWORKS + export TGT_SUBDIR_NAME=target + export TGT_DIR=$TL_DIR/target + export ATOM_PATH= + export ATOM_LIB=$TGT_DIR/lib/pentium/ATOM/common/libgcc.a + export BUILD_TARGET_TOOLCHAIN=GNU + export BUILD_TARGET_OS_VENDOR=WindRiver + export BUILD_TARGET_OS_VERSION=6.9.2 + export BUILD_TARGET=ATOM + export WIND_HOST_TYPE=x86-linux2 + ;; + MIPS) + #if checkwindbase; then + # return + #fi + + targetos VXWORKS + export TGT_SUBDIR_NAME=tmsTarget + export TGT_DIR=$TL_DIR/tmsTarget + export MIPS_LIB=$WRS_HOST/lib/gcc-lib/mips-wrs-vxworks/cygnus-2.7.2-960126 + export MIPS_PATH=`cygpath -u $WRS_BIN 2> /dev/null` + export BUILD_TARGET_TOOLCHAIN=GNU + export BUILD_TARGET_OS_VERSION=5.4 + export BUILD_TARGET=MIPS + ;; + X86|I386) + #if checkwindbase; then + # return + #fi + + targetos VXWORKS + export I386_LIB=$WRS_HOST/lib/gcc-lib/i386-wrs-vxworks/cygnus-2.7.2-960126 + export I386_PATH=$WRS_BIN + export BUILD_TARGET_TOOLCHAIN=GNU + export BUILD_TARGET_OS_VERSION=5.4 + export BUILD_TARGET=I386 + ;; + CYGWIN) + targetos CYGWIN + export BUILD_TARGET_TOOLCHAIN=GNU + export BUILD_TARGET=CYGWIN + ;; + WIN32) + targetos WIN32 + export BUILD_TARGET_TOOLCHAIN=WIN32 + export BUILD_TARGET=WIN32 + ;; + *) + printf "Unknown target $1\n" + printf "Usage: target [cygwin | mips | atom | win32] [bsp]\n\n" + return + ;; + esac + + if [ "$isBSP" == "BSP" ]; then + message="for BSP development" + UWRS_BIN=`cygpath -u $WRS_BIN` + export WIND_BASE=`cygpath -w $WIND_BASE 2> /dev/null` + export PATH=`update_path_start $PATH $UWRS_BIN $UWRS_BIN` + fi + elif [ `getBuildPlatform` == "DARWIN" ]; then + case $targetType in + PPC) + targetos DARWIN + export BUILD_TARGET_TOOLCHAIN=GNU + export BUILD_TARGET=PPC + ;; + *) + if [ "$1" != "" ]; then + printf "Unknown target $1\n" + fi + printf "Usage: target ppc\n\n" + return + esac + else + + if [[ "$TL_DIR" == "" ]]; then + echo "Unable to determine top level directory." + echo "The top level directory must have a ./Makerules/Makerules.global file." + return + fi + + setwindbase $TL_DIR + + case $targetType in + MIPS) + targetos VXWORKS + export MIPS_PATH= + export MIPS_LIB=$TL_DIR/host/$WIND_HOST_TYPE/lib/gcc-lib/mips-wrs-vxworks/cygnus-2.7.2-960126/mips3/libgcc.a + export BUILD_TARGET_TOOLCHAIN=GNU + export BUILD_TARGET_OS_VERSION=5.4 + export BUILD_TARGET=MIPS + ;; + LINUX) + targetos LINUX + export BUILD_TARGET_TOOLCHAIN=GNU + export BUILD_TARGET=IA32 + ;; + IA32) + targetos LINUX + export BUILD_TARGET_TOOLCHAIN=GNU + export BUILD_TARGET=IA32 + ;; + LINUX64) + targetos LINUX + export BUILD_TARGET_TOOLCHAIN=GNU + export BUILD_TARGET=IA64 + ;; + IA64) + targetos LINUX + export BUILD_TARGET_TOOLCHAIN=GNU + export BUILD_TARGET=IA64 + ;; + X86_64) + targetos LINUX + export BUILD_TARGET_TOOLCHAIN=GNU + export BUILD_TARGET=X86_64 + ;; + PPC64) + targetos LINUX + export BUILD_TARGET_TOOLCHAIN=GNU + export BUILD_TARGET=PPC64 + ;; + EM64T) + targetos LINUX + export BUILD_TARGET_TOOLCHAIN=GNU + export BUILD_TARGET=EM64T + ;; + *) + if [ "$1" != "" ]; then + printf "Unknown target $1\n" + fi + printf "Usage: target ia32|ia64|x86_64|em64t|mips|atom|ppc64\n\n" + return + ;; + esac + fi + + set_os_identifier + echo "Build target set to $BUILD_TARGET $message" + + if isAllEmb; then + if [ -e "$TL_DIR/.defaultCT" ]; then + export CARD_TYPE=`cat $TL_DIR/.defaultCT 2>&1 /dev/null` + export PROJ_FILE_DIR=$CARD_TYPE"_Firmware" + echo "Card type set to $CARD_TYPE" + fi + else + resetct > /dev/null + fi + + if [[ "$BUILD_TARGET_OS" != "LINUX" && -e "$TL_DIR/.defaultBSP" ]]; then + export TARGET_BSP=`cat $TL_DIR/.defaultBSP 2>&1 /dev/null` + export TARGET_BSP_UPCASE=`echo $TARGET_BSP | tr '[:lower:]' '[:upper:]'` + echo "Target BSP is ${TARGET_BSP:-empty.}" + fi + + if [[ -e "$TL_DIR/.defaultBuildConfig" ]]; then + export BUILD_CONFIG=`cat $TL_DIR/.defaultBuildConfig 2>&1 /dev/null` + echo "Build Configuration is ${BUILD_CONFIG:-empty.}" + fi + + if [[ -e "$TL_DIR/.defaultFS" ]]; then + export OPA_FEATURE_SET=`cat $TL_DIR/.defaultFS 2>&1 /dev/null` + echo "OPA_FEATURE_SET is ${OPA_FEATURE_SET:-empty.}" + fi + + fi + +} # end function + +function setrel() +{ + export BUILD_CONFIG=release + if [ "$TL_DIR" != "" ]; then + echo $BUILD_CONFIG > $TL_DIR/.defaultBuildConfig + fi +} + +function setdbg() +{ + export BUILD_CONFIG=debug + if [ "$TL_DIR" != "" ]; then + echo $BUILD_CONFIG > $TL_DIR/.defaultBuildConfig + fi +} + +setulps() +{ + export BUILD_ULPS="${1:-all}" + if [ "$TL_DIR" != "" ]; then + echo $BUILD_ULPS > $TL_DIR/.defaultBuildUlps + fi +} + +setskipulps() +{ + export BUILD_SKIP_ULPS="${1:-none}" + if [ "$TL_DIR" != "" ]; then + echo $BUILD_SKIP_ULPS > $TL_DIR/.defaultBuildSkipUlps + fi +} + + +settools() +{ + local choices + local x=0 + + if [ "$TL_DIR" == "" -o "$BUILD_TARGET_OS" == "" -o "$BUILD_TARGET" == "" ]; then + echo "Please use the target command to enable the build environment." + return + fi + + if [ "$1" != "" ]; then + export BUILD_TARGET_TOOLCHAIN=$1 + else + choices=`for x in $TL_DIR/Makerules/Target.*; do echo ${x##*/} | cut -d. -f3; done | sort | uniq` + if [ "$choices" != "" ]; then + for choice in $choices + do + echo "$(( x += 1 )) ) $choice" + done + printf "choice: " + read the_selection + x=0 + for choice in $choices + do + if [ "$the_selection" == "$(( x += 1 ))" ]; then + export BUILD_TARGET_TOOLCHAIN="$choice" + echo "Setting target tool chain to $choice." + return + fi + done + echo "Unknown choice." + else + echo "No choices available." + fi + fi +} #end function + +#--------------------------------------------------------------------------- +# Function: getosversions +# In Script: funcs-ext.sh +# Arguments: none +# Description: returns relevant os version +# Uses: +# Control the version string for all builds. +#--------------------------------------------------------------------------- +function getosversions() +{ + if [ `getBuildPlatform` == "Darwin" ]; then + tempchoices=`ls -1 $TL_DIR/Makerules/$BUILD_TARGET_OS/$BUILD_TARGET.$BUILD_TARGET_OS_VENDOR.*.h|xargs -n 1 basename|cut -d"." -f2-|xargs -n 1 -J % basename % .h 2> /dev/null` + else + tempchoices=`ls --indicator-style=none /lib/modules` + fi + rval="" + if [ "$BUILD_TARGET_OS" == "LINUX" ]; then + for rel in $tempchoices + do + if [ -d /lib/modules/$rel/build ] + then + rval="$rval ${BUILD_TARGET_OS_VENDOR}.${rel}" + fi + done + else + rval="$tempchoices" + fi + echo "$rval ${BUILD_TARGET_OS_VENDOR}.NONE" +} + +#--------------------------------------------------------------------------- +# Function: computebuild26 +# In Script: funcs-ext.sh +# Arguments: None +# Description: Set BUILD_26 for LINUX +# Uses: BUILD_TARGET_OS, BUILD_TARGET_OS_VERSION +function computebuild26() +{ + if [ "$BUILD_TARGET_OS" == "LINUX" ] + then + if echo $BUILD_TARGET_OS_VERSION|grep -q '^2\.6' + then + export BUILD_26=1 + elif echo $BUILD_TARGET_OS_VERSION | grep -q '^3.' + then + export BUILD_26=1 + else + unset BUILD_26 + fi + fi +} + +#--------------------------------------------------------------------------- +# Function: setver +# In Script: funcs-ext.sh +# Arguments: $1 [optional], set the os version at the command line. +# Description: Set the BUILD_TARGET_OS_VERSION for the os, and arch. +# Uses: +# Control the version string for all builds. +#--------------------------------------------------------------------------- +function setver() +{ + local x=0 + local vendor + local version + if [ "$TL_DIR" == "" -o "$BUILD_TARGET_OS" == "" -o "$BUILD_TARGET" == "" ]; then + echo "Please use the target command to enable the build environment." + return + fi + if [ "$1" != "" ]; then + export BUILD_TARGET_OS_VENDOR=$1 + export BUILD_TARGET_OS_VERSION=$2 + computebuild26 + set_os_identifier + echo "Setting os version to $BUILD_TARGET_OS_VENDOR $BUILD_TARGET_OS_VERSION (26=${BUILD_26:-0})." + else + if [ "$TL_DIR" == "" -o "$BUILD_TARGET_OS" == "" -o "$BUILD_TARGET" == "" ]; then + echo "Please use the target command to enable the build environment." + return + fi + choices=`getosversions` + if [ "$choices" != "" ]; then + for choice in $choices + do + vendor=`echo $choice|cut -d"." -f1` + version=`echo $choice|cut -d"." -f2-` + echo "$(( x += 1 )) ) $vendor $version" + done + printf "choice: " + read the_selection + x=0 + for choice in $choices + do + if [ "$the_selection" == "$(( x += 1 ))" ]; then + vendor=`echo $choice|cut -d"." -f1` + version=`echo $choice|cut -d"." -f2-` + export BUILD_TARGET_OS_VENDOR="$vendor" + export BUILD_TARGET_OS_VERSION="$version" + computebuild26 + set_os_identifier + echo "Setting os version to $BUILD_TARGET_OS_VENDOR $BUILD_TARGET_OS_VERSION (26=${BUILD_26:-0})." + return + fi + done + echo "Unknown choice." + else + echo "No version choices available." + fi + fi +} #end function + +## +## getIntelcompilervarsfile +## +## Parameters: +## prefix - directory pattern to search for in /opt/intel +## subdir - subdirectory under the pattern - can be null +## +## Looks for a list of directories matching the pattern and selects the newest +## + +getIntelcompilervarsfile() +{ + prefix=$1 + subdir=$2 + foundfile= + for f in $(ls -rd /opt/intel/${prefix}*) + do + if [ -f $f/$subdir/bin/compilervars.sh ] + then + foundfile=$f/$subdir/bin/compilervars.sh + break + fi + done + echo "$foundfile" +} diff --git a/MakeTools/get_comp.sh b/MakeTools/get_comp.sh new file mode 100644 index 0000000..f671ec0 --- /dev/null +++ b/MakeTools/get_comp.sh @@ -0,0 +1,225 @@ +#!/bin/bash +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** +## +## get_comp +## ----------- +## get a component which will be wrapped into the install wrapper +## the component is fetched from the ftp server based on the locations +## and files identified by get_input_comp_files based on the WrappedProducts +## configuration script. +## +## Usage: +## get_comp component bundle downloadsdir [comp.pl ...] +## Arguments: +## component - one of OFED, SRP, VNIC, FF, FV or FM +## bundle - one of Basic or IFS or TestTools or TESTS, PRs or RELEASE_NOTES +## downloadsdir - intermediate local directory to put +## component files will be downloaded into downloadsdir/component-bundle +## downloadsdir will be created if needed +## comp.pl - files to cat together to form comp.pl if product is NONE +## Required Environment (as set via setenv or similar tools): +## TL_DIR +## BUILD_PLATFORM_OS_VENDOR_VERSION +## BUILD_TARGET +## BUILD_TARGET_OS_VENDOR +## +## Additional Environment: +## +## FTPSERVER - ftp server to get files from of the form: +## ftp:password@server +## defaults to: ftp:ftp@kop-sds-ftp +## if FTPSERVER is cp:self@localhost the directory name for the source file +## of the component is ignored. In its place the directory name part of +## FTPINT is used. Note that typically FTPSERVER is derrived from FTPINT +## hence an FTPINT of cp:self@localhost:mydir will do a cp from mydir +## instead of an ftp. +## +## SCPSERVER - host to get packages from via SCP. Takes the form: +## "server" or "user@server:. Defaults to "phcvs2@phlsvlogin02" +## +## SCPTOP - root directory to get SCP files from. Takes the form: +## "directory". Defaults to "/nfs/site/proj/stlbuilds". +## +## This is designed for use in higher level scripts and makefiles, as such it +## will only download files which have not already been downloaded. +## It is expected that the higher level script or the makefile's clobber +## removes components-bundle directories in downloadsdir when it wants to +## force this to re-download + +. $ICSBIN/funcs.sh + +Usage() +{ + # include "ERROR" in message so weeklybuild catches it in error log + echo "ERROR: get_comp failed" >&2 + echo "Usage: get_comp component bundle downloadsdir [comp.pl ...]" >&2 + exit 2 +} + +if [ $# -lt 3 ] +then + Usage +fi + +set -e # exit on any error returns + +# $1 = Component Product Name +# $2 = Packaging Bundle +component=$1 +bundle=$2 +downloadsdir=$3 +shift 3 + + +# These variables control where the pre-built packages are pulled from. +# See documentation above. +export FTPSERVER=${FTPSERVER:-"ftp:ftp@kop-sds-ftp"} +export SCPTOP=${SCPTOP:-"/nfs/site/proj/stlbuilds"} +export SCPSERVER=${SCPSERVER:-"phcvs2@phlsvlogin02"}:$SCPTOP + +# ftp_get_files is defined in newer versions of devtools +if ! type ftp_get_files > /dev/null 2>/dev/null +then +#--------------------------------------------------------------------------- +# Function: ftp_get_files +# In Script: funcs.sh +# Arguments: $1 - ftp login and top level dir (user:password@server:dir) +# $2 - local directory to get files to +# $3 ... - list of files to get to current directory +# Description: copy a set of binary files from the ftp server +# example: ftp_files ftp:password@ftpserver:Integration/GA3_2_0_0 . myfile +#--------------------------------------------------------------------------- +function ftp_get_files() +{ + local user password dir server tempdir ldir files + + user=$(echo $1|cut -f1 -d@) + password=$(echo $user|cut -f2 -d:) + user=$(echo $user|cut -f1 -d:) + server=$(echo $1|cut -f2 -d@) + dir=$(echo $server|cut -f2 -d:) + server=$(echo $server|cut -f1 -d:) + ldir=$2 + shift; shift + + files="$*" + echo "Copying $files from $dir on ftp server $server as User $user..." + ftp -n $server << EOF +user $user $password +cd $dir +lcd $ldir +binary +prompt +mget $files +quit +EOF +} #end function +fi + +function get_file() +{ + # $1 - file to get + # $2 - directory to put it + local srcfile file srcdir destdir temp + + srcfile=$1 + destdir=$2 + srcdir=$(dirname $srcfile) + file=$(basename $srcfile) + + if [ "$FTPSERVER" = "cp:self@localhost" ] + then + temp=$(echo $FTPINT|cut -f2 -d@) + srcdir=$(echo $temp|cut -f2 -d:) + echo "Copying $srcdir/$file to $destdir/$file..." + cp $srcdir/$file $destdir/$file + else + if [ -d $SCPTOP ] + then + echo "Copying $srcfile from $SCPTOP/$srcdir to $destdir/$file..." + cp $SCPTOP/$srcfile $destdir + else + echo "Getting $srcfile from scp: $SCPSERVER:$srcfile to $destdir..." + scp_get_files $SCPSERVER $srcfile $destdir + fi + fi + +} + +retcode=0 + +localdir=$downloadsdir/$component-$bundle +mkdir -p $localdir +> $localdir/filelist +files=$($TL_DIR/MakeTools/get_input_comp_files $component $bundle) +if [ $? != 0 ] +then + echo "ERROR: get_input_comp failed" >&2 + exit 1 +fi +echo "$component $bundle Files: $files" +for file in $files +do + if [ "$file" != "NONE" ] + then + echo "$(basename $file)" >> $localdir/filelist + localfile=$localdir/$(basename $file) + # get $file from ftp server to $localdir + get_file $file $localdir + if [ ! -e $localfile ] + then + echo "ERROR - Unable to download $localfile" + retcode=1 + continue + fi + + # extract comp.pl file from any .tgz files with one + case $localfile in + *.tgz) + if comp=$(tar tfz $localfile 2>/dev/null | grep '/comp.pl$') + then + temp_dir=$localdir/temp + mkdir $temp_dir + tar xvfz $localfile -C $temp_dir $comp + mv $temp_dir/*/comp.pl $localdir + rm -rf $temp_dir + fi;; + esac + elif [ $# != 0 ] + then + cat $* > $localdir/comp.pl + fi +done +if [ $retcode = 0 ] +then + echo "$(date): $files" > $localdir/download_done +fi + +exit $retcode diff --git a/MakeTools/get_input_comp_files.sh b/MakeTools/get_input_comp_files.sh new file mode 100755 index 0000000..381b8a6 --- /dev/null +++ b/MakeTools/get_input_comp_files.sh @@ -0,0 +1,110 @@ +#!/bin/bash +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** +## +## get_input_comp_files +## ----------- +## function to lookup the files needed for a specific bundle/component combo +## get value of appropriate product variable in WrappedProducts +## returns value of the line (eg. files for Component-Bundle combo) +## +## Usage: +## get_input_comp_files component bundle +## +## Arguments: +## component - one of OFED, SRP, VNIC, FF, FV or FM +## bundle - one of Basic or IFS or TestTools or TESTS, PRs or RELEASE_NOTES +## Required Environment (as set via setenv or similar tools): +## TL_DIR +## BUILD_PLATFORM_OS_VENDOR_VERSION +## BUILD_TARGET +## BUILD_TARGET_OS_VENDOR + +. $ICSBIN/funcs.sh + +Usage() +{ + # include "ERROR" in message so weeklybuild catches it in error log + echo "ERROR: get_input_comp_files failed" >&2 + echo "Usage: get_input_comp_files component bundle" >&2 + exit 2 +} + +if [ $# != 2 ] +then + Usage +fi + +if [ "$1" = "IFS" ] +then + # special mistake which can trigger use of $IFS below and cause confusing + # result + Usage +fi + +# $1 = Component Product Name +# $2 = Packaging Bundle +component=$1 +bundle=$2 + +. $TL_DIR/$PROJ_FILE_DIR/WrappedProducts + +# workaround broken versions of target command +if [ x"$BUILD_TARGET_OS_VENDOR_VERSION" = x"" ] +then + BUILD_TARGET_OS_VENDOR_VERSION=$BUILD_PLATFORM_OS_VENDOR_VERSION +fi +os_vendor_ver=$(echo $BUILD_TARGET_OS_VENDOR_VERSION | tr '.' '_') +os_vendor_brief_ver=$(echo $os_vendor_ver|sed -e 's/_.*//') +os_id="${BUILD_TARGET}_${BUILD_TARGET_OS_VENDOR}_$os_vendor_ver" +# also handle the case of os_vendor_ver with minor rev part removed +brief_os_id="${BUILD_TARGET}_${BUILD_TARGET_OS_VENDOR}_$os_vendor_brief_ver" + +value="" +for parameter in ${bundle}_${component}_${os_id} ${bundle}_${component}_${brief_os_id} ${bundle}_${component} ALL_${component}_${os_id} ALL_${component}_${brief_os_id} ALL_$component +do + value=$(eval echo \"\$"$parameter"\") + if [ ! -z "$value" ] + then + break + fi +done +if [ -z "$value" ] +then + echo "ERROR: $component not found in WrappedProducts" >&2 + echo "ERROR: Tried: ${bundle}_${component}_${os_id}" >&2 + echo " ${bundle}_${component}_${brief_os_id}" >&2 + echo " ${bundle}_${component}" >&2 + echo " ALL_${component}_${os_id}" >&2 + echo " ALL_${component}_${brief_os_id}" >&2 + echo " ALL_$component" >&2 + exit 1 +fi +echo "$value" +exit 0 diff --git a/MakeTools/get_ofed_files.sh b/MakeTools/get_ofed_files.sh new file mode 100755 index 0000000..3bba32f --- /dev/null +++ b/MakeTools/get_ofed_files.sh @@ -0,0 +1,79 @@ +#!/bin/bash +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +#[ICS VERSION STRING: unknown] +# this script builds a tgz with all the header and library files needed +# in order to build applications against a new version of OFED +# this should be run on each distro. It uninstalls OFED, gets a file list for +# /usr, then builds and installs ofed and builds the list of new files +# which came from OFED. Those files are tared up and made ready to be +# put in the /usr/ofed-$version directory on the given build or sds machine + +if [ $# -ne 1 ] +then + echo "Usage: get_ofed_files.sh version" >&2 + exit 2 +fi +version=$1 + +set -x +dir=$PWD + +# uninstall any QLogic code +opaconfig -u + +# untar OFED installer +rm -rf OFED-$version +#tar xvfz OFED-$version.tar +tar xvfz OFED-$version.tgz +cd OFED-$version + +# uninstall OFED +echo y|./uninstall.sh + +# list of files before OFED +find /usr > $dir/usr.before + +# install all of OFED +./install.pl --all + +# list of files after OFED +cd $dir +find /usr > $dir/usr.after + +# figure out what OFED added in /usr +diff $dir/usr.before $dir/usr.after > $dir/usr.ofed + +# prune out some directories which do not have headers nor libraries +sed -e '/^[0-9]/d' -e 's/^> //' -e '/^< /d' -e '/^---/d' -e '/^\/usr\/sbin/d' -e '/^\/usr\/bin/d' -e '/^\/usr\/src/d' -e '/^\/usr\/mpi/d' -e '/^\/usr\/share\/man/d' -e 's/^\/usr\///' < $dir/usr.ofed > $dir/usr.ofed.files + +# tar up the files of interest +cd /usr +tar cvfz $dir/ofed-$version.tgz -T $dir/usr.ofed.files diff --git a/MakeTools/getsmpopt.sh b/MakeTools/getsmpopt.sh new file mode 100755 index 0000000..920bd45 --- /dev/null +++ b/MakeTools/getsmpopt.sh @@ -0,0 +1,62 @@ +#!/bin/bash +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** +# return BUILD_SMP option value based on present system +# 0->uniproc, 1->smp, 2->enterprise, 3->bigmem, 4->debug 5->kgdb 6->kgdbsmp +if [ `uname -s` = Darwin ] +then + # all MAC kernels are SMP + echo 1 +else + name=`uname -r` + case $name in + *smp*) rval="1";; + *enterprise*) rval="2";; + *bigmem*) rval="3";; + *debug*) rval="4";; + *kgdbsmp*) rval="6";; + *kgdb*) rval="5";; + *) rval="0";; + esac + if [ "$BUILD_TARGET_OS_VENDOR_VERSION" = "ES3" ] + then + if [ "$BUILD_TARGET" = "IA64" -o "$BUILD_TARGET" = "EM64T" ] + then + rval="1" + fi + fi + if [ "$BUILD_TARGET_OS_VENDOR_VERSION" = "ES9" ] + then + if [ "$BUILD_TARGET" = "IA64" ] + then + rval="1" + fi + fi +fi +echo $rval diff --git a/MakeTools/gitpull.sh b/MakeTools/gitpull.sh new file mode 100755 index 0000000..f0524a5 --- /dev/null +++ b/MakeTools/gitpull.sh @@ -0,0 +1,218 @@ +#!/bin/bash +# github servers where WFR repos are found +server1=git-amr-1.devtools.intel.com:29418 +server2=git-amr-2.devtools.intel.com:29418 + +Usage() +{ + echo "Usage: gitpull.sh [-PSdcv] [-b branch] [-t topdir] [-g gitdir] [repo ...]" >&2 + echo " -P - skip pulling/cloning from repro" >&2 + echo " -S - skip building and expanding the srpm" >&2 + echo " -d - diff against CVS" >&2 + echo " -c - copy to CVS" >&2 + echo " -v - verbose output" >&2 + echo " -b branch - git branch to checkout" >&2 + echo " (by default will read branch name from CVS commitids)" >&2 + echo " -t topdir - top directory in CVS tree (default is $PWD)" >&2 + echo " -g gitdir - parent directory for git repo(s) (defailt is GIT_REPOS)" >&2 + echo " repo - list of wfr repos to operate on, default is all repos" >&2 + exit 2 +} + +# a few aren't working yet +repos="wfr-driver wfr-firmware wfr-psm wfr-diagtools-sw" +repos="$repos wfr-lite wfr-ibacm wfr-libverbs" +repos="$repos wfr-libibumad" +repos="$repos wfr-mvapich2" +repos="$repos wfr-openmpi" +repos="$repos wfr-gasnet" +repos="$repos wfr-openshmem" +repos="$repos wfr-openshmem-tests" + +# skip this, linux kernel 3.12.18 for devel +#repos="$repos wfr-linux-devel" + +in_branch= +pull=y +makesrpm=y +diff=n +copy=n +topdir=$PWD +gitdir=GIT_REPOS +verbose=n +while getopts PSdcvb:t:g: param +do + case $param in + P) pull=n;; + S) makesrpm=n;; + d) diff=y;; + c) copy=y;; + v) verbose=y;; + b) in_branch="$OPTARG";; + t) topdir="$OPTARG";; + g) gitdir="$OPTARG";; + *) Usage;; + esac +done +shift $((OPTIND -1)) +if [ $# -gt 0 ] +then + repos="$*" +fi + +if [ ! -d $topdir ] +then + echo "gitpull: FAILED: topdir Directory Not Found: $topdir" >&2 + Usage +fi +if [ ! -d $gitdir ] +then + echo "gitpull: FAILED: gitdir Directory Not Found: $gitdir" >&2 + Usage +fi + +# convert topdir to an absolute path +if [ `echo $topdir | cut -c 1` != '/' ] +then + topdir=$PWD/$topdir +fi +# convert gitdir to an absolute path +if [ `echo $gitdir | cut -c 1` != '/' ] +then + gitdir=$PWD/$gitdir +fi + +[ $verbose = y ] && echo "Using topdir= $topdir; gitdir= $gitdir" + + +# different repo servers +get_server() +{ + case $1 in + wfr-lite|wfr-openshmem|wfr-oshmem|wfr-openshmem-tests) echo $server1;; + *) echo $server2;; + esac +} + +# some repos have names different from Ofed/ tree name, remap +get_ofed_dir() +{ + case $1 in + wfr-ibacm) echo "ibacm";; + wfr-libibumad) echo "libibumad";; + wfr-openshmem-tests) echo "wfr-openshmem-tests/openshmem-test-suite";; + *) echo "$1";; + esac +} + +get_git_branch() +{ + if [ ! -e $topdir/Ofed/$1/commitids ] + then + echo "FAILED: Unable to get git branch. Not Found: $topdir/Ofed/$1/commitids" >&2 + else + tail -1 $topdir/Ofed/$1/commitids|cut -f 1 -d ' ' + fi +} + +for i in $repos +do + branch=$in_branch + ofed_dir=`get_ofed_dir $i` + echo "Processing git repo $i against Ofed/$ofed_dir" + if [ $pull = y ] + then + # lookup git branch in commitids file in CVS + if [ x"$branch" = x ] + then + branch=`get_git_branch $ofed_dir` + fi + if [ x"$branch" = x ] + then + echo "FAILED: unable to determine git branch for $i" >&2 + continue + fi + [ $verbose = y ] && echo "Using git branch $branch" + + ## get the latest copy of source from the repos + if [ ! -d $gitdir/$i ] + then + server=`get_server $i` + [ $verbose = y ] && echo "(cd $gitdir; git clone ssh://$USER@$server/$i)" + (cd $gitdir; git clone ssh://$USER@$server/$i) + else + [ $verbose = y ] && echo "(cd $gitdir/$i; git pull)" + (cd $gitdir/$i; git pull) + fi + ##Next, checkout the desired branch in each directory + [ $verbose = y ] && echo "(cd $gitdir/$i; git checkout $branch )" + (cd $gitdir/$i; git checkout $branch ) + fi + if [ ! -d $gitdir/$i ] + then + echo "FAILED: Need to pull, Directory not found: $gitdir" >&2 + continue + fi + + ##show the branch we are on + (cd $gitdir/$i; git branch ) + + if [ $makesrpm = y ] + then + if [ ! -e $gitdir/$i/makesrpm.sh ] + then + echo "FAILED: Unable to makesrpm, File not found: $gitdir/$i/makesrpm.sh" >&2 + continue + fi + + ##make the srpm + [ $verbose = y ] && echo "rm -rf $gitdir/$i/SOURCE_TREE" + rm -rf $gitdir/$i/SOURCE_TREE + [ $verbose = y ] && echo "(cd $gitdir/$i/; bash -x ./makesrpm.sh )" + (cd $gitdir/$i/; bash -x ./makesrpm.sh ) + + ##expand it + if [ `ls $gitdir/$i/SRPMS/*.src.rpm|wc -l` != 1 ] + then + echo "FAILED: srpm missing or too many, File not found: $gitdir/$i/SRPMS/*.src.rpm" >&2 + continue + fi + [ $verbose = y ] && echo "Expanding source into $gitdir/$i/SOURCE_TREE" + (cd $gitdir/$i/; mkdir SOURCE_TREE; $topdir/MakeTools/expand_source.sh -d SOURCE_TREE SRPMS/*.src.rpm) + fi + + if [ $diff = y ] + then + if [ ! -e $gitdir/$i/SOURCE_TREE/package_list ] + then + echo "FAILED: Unable to diff, File not found: $gitdir/$i/SOURCE_TREE/package_list" >&2 + continue + fi + + ## use package_list because srpm name is not necessarily $i + package=`head -1 $gitdir/$i/SOURCE_TREE/package_list` + [ $verbose = y ] && echo "Diff $gitdir/$i/SOURCE_TREE/$package/ $topdir/Ofed/$ofed_dir/ ..." + diff -b -u --no-dereference --exclude CVS --exclude .git --exclude package_list -r $gitdir/$i/SOURCE_TREE/$package/ $topdir/Ofed/$ofed_dir/ + fi + + if [ $copy = y ] + then + if [ ! -e $gitdir/$i/SOURCE_TREE/package_list ] + then + echo "FAILED: Unable to copy, File not found: $gitdir/$i/SOURCE_TREE/package_list" >&2 + continue + fi + + [ $verbose = y ] && echo "Replacing source in $topdir/Ofed/$i ..." + ##copy expanded srpm source from SOURCE_TREE to CVS Ofed/ tree + ##remove existing files in Ofed/ checkout + find $topdir/Ofed/$ofed_dir/src/ ! -type d| grep -v CVS|xargs rm -f + ##replace with new files from srpm + ## use package_list because srpm name is not necessarily $i + package=`head -1 $gitdir/$i/SOURCE_TREE/package_list` + # use find to avoid symlinks, make_symlinks will handle them when build + #cp -r $gitdir/$i/SOURCE_TREE/$package/* $topdir/Ofed/$ofed_dir/ + (cd $gitdir/$i/SOURCE_TREE/$package; find . -type d -o -type f|cpio -pdvum $topdir/Ofed/$ofed_dir/) + + fi +done 2>&1|tee -a gitpull.log diff --git a/MakeTools/installtargets/Makefile b/MakeTools/installtargets/Makefile new file mode 100755 index 0000000..0281ef4 --- /dev/null +++ b/MakeTools/installtargets/Makefile @@ -0,0 +1,155 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** +# Makefile for installtargets + +# Include Make Control Settings +include $(TL_DIR)/$(PROJ_FILE_DIR)/Makesettings.project + +#=============================================================================# +# Definitions: +#-----------------------------------------------------------------------------# +# avoid catch22 +AUTODEP=no + +# Name of SubProjects +DS_SUBPROJECTS = +# name of executable or downloadable image +# FIXME: at this time can't put installtargets in BUILDDIR since rest of +# make system expects it to be found here +EXECUTABLE = installtargets$(EXE_SUFFIX) +# list of sub directories to build +DIRS = +# C files (.c) +CFILES = \ + installtargets.c \ + # Add more c files here +# C++ files (.cpp) +CCFILES = \ + # Add more cpp files here +# lex files (.lex) +LFILES = \ + # Add more lex files here +# Windows Resource Files (.rc) +RSCFILES = +# Windows IDL File (.idl) +IDLFILE = +# Windows Linker Module Definitions (.def) file for dll's +DEFFILE = +# targets to build during INCLUDES phase (add public includes here) +INCLUDE_TARGETS = \ + # Add more h hpp files here +# Non-compiled files +MISC_FILES = +# all source files +SOURCES = $(CFILES) $(CCFILES) $(LFILES) $(RSCFILES) $(IDLFILE) +# Source files to include in DSP File +DSP_SOURCES = $(INCLUDE_TARGETS) $(SOURCES) $(MISC_FILES) \ + $(RSCFILES) $(DEFFILE) $(MAKEFILE) +# all object files +OBJECTS = $(CFILES:.c=$(OBJ_SUFFIX)) $(CCFILES:.cpp=$(OBJ_SUFFIX)) \ + $(LFILES:.lex=$(OBJ_SUFFIX)) +RSCOBJECTS = $(RSCFILES:.rc=$(RES_SUFFIX)) +# targets to build during LIBS phase +LIB_TARGETS_IMPLIB = +LIB_TARGETS_ARLIB = +LIB_TARGETS_EXP = $(LIB_TARGETS_IMPLIB:$(ARLIB_SUFFIX)=$(EXP_SUFFIX)) +LIB_TARGETS_MISC = +# targets to build during CMDS phase +CMD_TARGETS_SHLIB = +CMD_TARGETS_EXE = $(EXECUTABLE) +CMD_TARGETS_MISC = +# files to remove during clean phase +CLEAN_TARGETS_MISC= +CLEAN_TARGETS = $(OBJECTS) $(RSCOBJECTS) $(IDL_TARGETS) $(CLEAN_TARGETS_MISC) +# other files to remove during clobber phase +CLOBBER_TARGETS_MISC= +# sub-directory to install to within bin +BIN_SUBDIR = + +# Additional Settings +#CLOCALDEBUG = User defined C debugging compilation flags [Empty] +#CCLOCALDEBUG = User defined C++ debugging compilation flags [Empty] +#CLOCAL = User defined C flags for compiling [Empty] +#CCLOCAL = User defined C++ flags for compiling [Empty] +#BSCLOCAL = User flags for Browse File Builder [Empty] +#DEPENDLOCAL = user defined makedepend flags [Empty] +#LINTLOCAL = User defined lint flags [Empty] +#LOCAL_INCLUDE_DIRS = User include directories to search for C/C++ headers [Empty] +#LDLOCAL = User defined C flags for linking [Empty] +#IMPLIBLOCAL = User flags for Object Lirary Manager [Empty] +#MIDLLOCAL = User flags for IDL compiler [Empty] +#RSCLOCAL = User flags for resource compiler [Empty] +#LOCALDEPLIBS = User libraries to include in dependencies [Empty] +#LOCALLIBS = User libraries to use when linking [Empty] +# (in addition to LOCALDEPLIBS) +#LOCAL_LIB_DIRS = User library directories for libpaths [Empty] + +LOCALDEPLIBS = + +# Include Make Rules definitions and rules +include $(TL_DIR)/$(PROJ_FILE_DIR)/Makerules.project + +#=============================================================================# +# Overrides: +#-----------------------------------------------------------------------------# +#CCOPT = # C++ optimization flags, default lets build config decide +#COPT = # C optimization flags, default lets build config decide +#SUBSYSTEM = Subsystem to build for (none, console or windows) [none] +# (Windows Only) +#USEMFC = How Windows MFC should be used (none, static, shared, no_mfc) [none] +# (Windows Only) +#=============================================================================# + +#=============================================================================# +# Rules: +#-----------------------------------------------------------------------------# +# process Sub-directories +include $(TL_DIR)/Makerules/Maketargets.toplevel + +# build cmds and libs +include $(TL_DIR)/Makerules/Maketargets.build + +ifeq "$(PRODUCT)" "devtools" +# install for includes, libs and cmds phases +include $(TL_DIR)/Makerules/Maketargets.install + +# install for stage phase +include $(TL_DIR)/Makerules/Maketargets.stage +endif +CMDS:: $(CMD_TARGETS) +STAGE:: + +# Unit test execution +#include $(TL_DIR)/Makerules/Maketargets.runtest + +#=============================================================================# + +#=============================================================================# +# DO NOT DELETE THIS LINE -- make depend depends on it. +#=============================================================================# diff --git a/MakeTools/installtargets/installtargets.c b/MakeTools/installtargets/installtargets.c new file mode 100644 index 0000000..57a2969 --- /dev/null +++ b/MakeTools/installtargets/installtargets.c @@ -0,0 +1,353 @@ +/* BEGIN_ICS_COPYRIGHT7 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT7 ****************************************/ +#include +#include +#include +#include +#include +#ifdef WIN32 +#include +#include +#endif +#include +#include +#include +#include +#include + +typedef int boolean; +#define TRUE 1 +#define FALSE 0 + +int Mkdir(const char* dir); +int InstallTarget(const char* targetDir, const char* srcFileName, const boolean forceFlag, unsigned modeMask); +boolean CopyFile( const char* targetFileName, const char* srcFileName, struct stat srcStat, unsigned modeMask ); +boolean CompareFiles( const char* targetFileName, const char* srcFileName ); + +void Usage(const char* progname) +{ + printf("usage: %s -d [ -f ] [file name 1] ... [file name n]\n", progname); + printf("\n"); + exit(1); +} + +int main(int argc, char *argv[]) + { + const char* targetDir = NULL; + boolean forceFlag = FALSE; + unsigned modeMask = ~0u; + int argNum = 0; + + while( ++argNum < argc ) + { + switch( argv[argNum][0] ) + { + case '-': + switch( argv[argNum][1] ) + { + case 'd': + /* target directory specified */ + if( ++argNum == argc) + { + Usage(argv[0]); + return 1; + } + targetDir = argv[argNum]; + if( Mkdir(targetDir) == -1 ) + { + printf("...Can't create target directory %s \n", targetDir); + return 1; + } + break; + + case 'f': + /* force flag specified; error in accessing any source file is ignored */ + forceFlag = TRUE; + break; + case 'r': + /* readonly flag specified; make destination file readonly */ + modeMask = ~(S_IWUSR|S_IWGRP|S_IWOTH); + break; + + default: + Usage(argv[0]); + return 1; + } + break; + + default: + if( targetDir == NULL ) + { + Usage(argv[0]); + return 1; + } + if( InstallTarget(targetDir, argv[argNum], forceFlag, modeMask) != 0 ) + { + printf("...Unable to install file %s \n", argv[argNum]); + return 1; + } + break; + } + } + + return 0; +} /* End main function */ + + +int Mkdir(const char* dir) +{ + int result = 0; + int lenPlusOne = 0; + char* newDir; + const char* pDir = dir; + char* pNewDir; + + /* No relative path permitted. Will return an error result if it occurs. */ + if( dir == NULL || (lenPlusOne = strlen(dir)+1) == 1 || *dir == '.' ) + { + return -1; + } + + /* If the directory already exists, no need to do anything else */ + if( access(dir, 0) == 0 ) + { + return 0; + } + + newDir = (char*)malloc(lenPlusOne); + if (!newDir) { + return -1; + } + + for( pNewDir = newDir; lenPlusOne--; ++pDir, ++pNewDir ) + { + /* If a dir component delimiter is found AND it is not the 1st char of dir spec AND */ + /* the previous dir spec char was not a colon (ie drive letter delimiter), then create */ + /* the new directory if not already existent. Note this parsing will not handle relative */ + /* paths. */ + if( (*pDir == '/' || *pDir == '\\' || *pDir == '\0') && + pDir != dir && + *(pDir-1) != ':' ) + { + *pNewDir = '\0'; + if( access(newDir, 0) == -1 && mkdir(newDir, 0755) == -1 ) + { + result = -1; + break; + } + } + *pNewDir = *pDir; + } + + free(newDir); + return result; +} + + +int InstallTarget(const char* targetDir, const char* srcFileName, const boolean forceFlag, unsigned modeMask) +{ + struct stat srcStat; + struct stat targetStat; + char targetFileName[2000]; + boolean copyResult = TRUE; + int res = 0; + + /* If the source file does not exist as a regular file, return an error unless the */ + /* force flag is set. */ + if( stat(srcFileName, &srcStat) != 0 || ! S_ISREG(srcStat.st_mode) ) + { + if( forceFlag ) + { + return 0; + } + else + { + return 1; + } + } + + /* Build the target file name spec */ + res = snprintf(targetFileName, 2000, "%s/%s", targetDir, basename((char*)srcFileName)); + if(res <= 0 || res > 2000) + return 1; /* Path could not be created or is too long (very unlikely) */ + + /* If the target file does not exist OR the source file modified time is greater than */ + /* the target file modified time, OR the source file size is not equal to the target */ + /* file size, no need to compare, just do the copy */ +#if defined(linux) || defined(__DARWIN__) + if( stat(targetFileName, &targetStat) != 0 || + ! S_ISREG(targetStat.st_mode) || + srcStat.st_mtime > targetStat.st_mtime || + srcStat.st_size != targetStat.st_size ) +#else + if( _stat(targetFileName, &targetStat) != 0 || + ! S_ISREG(targetStat.st_mode) || + srcStat.st_mtime > targetStat.st_mtime || + srcStat.st_size != targetStat.st_size ) +#endif + { + copyResult = CopyFile( targetFileName, srcFileName, srcStat, modeMask); + } + else + { + /* If the compare says the source and target files are different, do the copy */ + if( CompareFiles(targetFileName, srcFileName) ) + { + copyResult = CopyFile( targetFileName, srcFileName, srcStat, modeMask ); + } + } + +#if 0 + if( forceflag ) + { + copyResult = TRUE; + } +#endif + + return copyResult ? 0 : 1; +} + + +boolean CopyFile( const char* targetFileName, const char* srcFileName, struct stat srcStat, const unsigned modeMask ) +{ + FILE *srcFile = NULL; + FILE *targetFile = NULL; + boolean copyResult = TRUE; + int srcChr; + unsigned mode = srcStat.st_mode & modeMask; + + printf("Copying %s to %s...", srcFileName, targetFileName); + srcFile = fopen(srcFileName, "rb"); + chmod(targetFileName, mode|(S_IWUSR|S_IWGRP)); + targetFile = fopen(targetFileName, "wb"); + if( srcFile != NULL && targetFile != NULL ) + { + while ( (srcChr = fgetc(srcFile)) != EOF ) + { + if( putc( srcChr, targetFile) == EOF ) + { + copyResult = FALSE; + break; + } + } + } + else + { + copyResult = FALSE; + } + + if( srcFile ) + { + fclose(srcFile); + } + + if( targetFile ) + { + fclose(targetFile); + chmod(targetFileName, mode); + } + + if ( copyResult ) + { + static struct utimbuf utb; + int rval; + +#if defined(__DARWIN__) + utb.actime = srcStat.st_atimespec.tv_sec; + utb.modtime = srcStat.st_mtimespec.tv_sec; +#else + utb.actime = srcStat.st_atime; + utb.modtime = srcStat.st_mtime; +#endif + if ((rval=utime(targetFileName,&utb))) { + printf("Could not set utime: %d/%s..",rval,strerror(rval)); + } + } + + if( copyResult ) + { + printf("Copy Complete!!!\n"); + } + else + { + printf("Copy Failed!!!\n"); + } + + return copyResult; +} + +boolean CompareFiles( const char* targetFileName, const char* srcFileName ) +{ + FILE *srcFile = NULL; + FILE *targetFile = NULL; + int srcChr, targetChr; + unsigned long limitByteCount = 1000; + boolean filesAreDifferent; + + /* Byte check the 1st 1000 bytes */ + srcFile = fopen(srcFileName, "rb"); + targetFile = fopen(targetFileName, "rb"); + if ( !srcFile && targetFile) { + printf("Could not open %s\n", srcFileName); + fclose(targetFile); + return TRUE; + } else if ( srcFile && !targetFile) { + printf("Could not open %s\n", targetFileName); + fclose(srcFile); + return TRUE; + } else if ( !srcFile && !targetFile) { + printf("Could not open either %s, %s\n", srcFileName, targetFileName); + return FALSE; + } + while ( (srcChr = fgetc(srcFile)) != EOF && limitByteCount ) + { + /* If the target is smaller than the source file or the byte comparison fails, */ + /* then the files are different. */ + if( (targetChr = fgetc(targetFile)) == EOF || srcChr != targetChr ) + { + fclose(srcFile); + fclose(targetFile); + return TRUE; + } + /* If the limit number of bytes to be compared are all equal, assume the files */ + /* are the same. */ + else if( --limitByteCount == 0 ) + { + fclose(srcFile); + fclose(targetFile); + return FALSE; + } + } + + filesAreDifferent = fgetc(targetFile) != EOF; + fclose(srcFile); + fclose(targetFile); + + return filesAreDifferent; +} diff --git a/MakeTools/ln-install.sh b/MakeTools/ln-install.sh new file mode 100755 index 0000000..40d108d --- /dev/null +++ b/MakeTools/ln-install.sh @@ -0,0 +1,62 @@ +#!/bin/bash +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +if [ "$1" == "-d" ]; then +shift +fi + +BUILD_INCLUDE_DIR=$1 + +shift + +if [ ! -d "$BUILD_INCLUDE_DIR" ]; then + echo "Making directory $BUILD_INCLUDE_DIR" + mkdir -p $BUILD_INCLUDE_DIR +fi + +for i in $*; +do + if [ ! -f "$i" ]; then + rm -f $BUILD_INCLUDE_DIR/$i + else + if [ ! -f "$BUILD_INCLUDE_DIR/`basename $i`" ]; then + if expr "$i" : '/.*' > /dev/null; then + # absolute path + ln -sf $i $BUILD_INCLUDE_DIR + else + # relative path + ln -sf $PWD/$i $BUILD_INCLUDE_DIR + fi + fi + fi +done + + + diff --git a/MakeTools/lnshlib.darwin.sh b/MakeTools/lnshlib.darwin.sh new file mode 100755 index 0000000..0703ff4 --- /dev/null +++ b/MakeTools/lnshlib.darwin.sh @@ -0,0 +1,55 @@ +#!/bin/bash +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** +# Link versioned shared libraries to the .dylib suffixed version +# Example: +# lnshlib.sh $(TL_DIR)/builtlibs libmy.0.1.dylib libmy2.0.0.dylib + +Usage() +{ + echo "Usage: lnshlib.sh dir dylib_file ..." >&2 + exit 2 +} + +if [ $# -lt 2 ] +then + Usage +fi + +cd $1 +shift +for dylib_file in $* +do + dylib_file=`basename $dylib_file` + dest=`echo "$dylib_file"|sed -e 's/\..*\.dylib/.dylib/'` + if [ "$dest" != "$dylib_file" ] + then + ln -sf $dylib_file $dest + fi +done diff --git a/MakeTools/lnshlib.sh b/MakeTools/lnshlib.sh new file mode 100755 index 0000000..c69b8da --- /dev/null +++ b/MakeTools/lnshlib.sh @@ -0,0 +1,55 @@ +#!/bin/bash +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** +# Link versioned shared libraries to the .so suffixed version +# Example: +# lnshlib.sh $(TL_DIR)/builtlibs libmy.so.0.1 libmy2.so.0.0 + +Usage() +{ + echo "Usage: lnshlib.sh dir so_file ..." >&2 + exit 2 +} + +if [ $# -lt 2 ] +then + Usage +fi + +cd $1 +shift +for so_file in $* +do + so_file=`basename $so_file` + dest=`echo "$so_file"|sed -e 's/\.so\..*/.so/'` + if [ "$dest" != "$so_file" ] + then + ln -sf $so_file $dest + fi +done diff --git a/MakeTools/make_src_tar.sh b/MakeTools/make_src_tar.sh new file mode 100755 index 0000000..69edf55 --- /dev/null +++ b/MakeTools/make_src_tar.sh @@ -0,0 +1,105 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +#[ICS VERSION STRING: unknown] +#!/bin/sh +# This script is used to to create source tar for rpm +# Required arguments: $RELEASE_TYPE $SrcRoot $USE_UNIFDEF $ARCHIVE $FILES_TO_TAR $FILE_TO_EXCLUDE +set -x +RELEASE_TYPE="$1" +SrcRoot="$2" +USE_UNIFDEF="$3" +ARCHIVE="$4" +FILES_TO_TAR="$5" +FILE_TO_EXCLUDE="$6" + +comp_arg= +if echo $ARCHIVE | grep opa-fm.tar.gz > /dev/null +then + comp_arg=HFM +fi +if echo $ARCHIVE | grep opa.tgz > /dev/null +then + comp_arg=FF +fi +if echo $ARCHIVE | grep opa-sim.tgz > /dev/null +then + comp_arg=SIM +fi + +if [[ "${RELEASE_TYPE}" == "EMBARGOED" ]] +then + echo "Building Embargoed Release." + export OPA_LICENSE_DIR=${TL_DIR}/CodeTemplates/EmbargoedNotices + export LICENSE_FUNCS=${TL_DIR}/CodeTemplates/license_funcs.sh + # use tar command to copy files to temp dir + # then run update_all_licenses on files in temp dir + TMP=$(mktemp -d) + tar c -C ${SrcRoot} --exclude-vcs --ignore-case $FILE_TO_EXCLUDE ${FILES_TO_TAR} | \ + tar x -C ${TMP} + ${TL_DIR}/CodeTemplates/update_all_licenses.sh -c -q $TMP + SrcRoot=${TMP} +else + echo "Building Public Release." +fi + +SrcTmp=$(mktemp -d) + +# Use tar command to copy files to temp dirs +# For unifdef, then run unifdef on files in temp dir + +tar c -C ${SrcRoot} --exclude-vcs --ignore-case $FILE_TO_EXCLUDE ${FILES_TO_TAR} | \ + tar x -C ${SrcTmp} +if [[ $USE_UNIFDEF = "yes" ]] ; then + # Check if unifdef tool exists + type unifdef > /dev/null 2>&1 || { echo "error: unifdef tool missing"; exit 1; } + find ${SrcTmp}/ -type f -regex ".*\.[ch][p]*$" -exec unifdef -m -f "${TL_DIR}/Fd/buildFeatureDefs" {} \; + # Delete content of buildFeatureDefs before creating source tar for rpm + mkdir -p ${SrcTmp}/Fd + >${SrcTmp}/Fd/buildFeatureDefs + >${SrcTmp}/Fd/buildFeatureDefs.base +fi + +# Copy processed base files as .base + +while read comp fn +do + if echo $comp | grep $comp_arg > /dev/null + then + cp ${TL_DIR}/$fn ${SrcTmp}/${fn}.base + fi +done < ${TL_DIR}/Fd/BaseFiles + +tar cvzf ${ARCHIVE} -C ${SrcTmp} --exclude-vcs --ignore-case $FILE_TO_EXCLUDE ${FILES_TO_TAR} + +# Remove temp dir +if [[ "${RELEASE_TYPE}" == "EMBARGOED" ]] ; then + rm -rf ${TMP} +fi +rm -rf ${SrcTmp} diff --git a/MakeTools/makeiso.sh b/MakeTools/makeiso.sh new file mode 100755 index 0000000..ee888ba --- /dev/null +++ b/MakeTools/makeiso.sh @@ -0,0 +1,118 @@ +#!/bin/bash +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** +# Environment variable: BUILD_ISO=y will enable generation of ISO Images, +# Any other value disables hence saving disk space for developer builds +# If BUILD_ISO is not defined, it defaults based on RELEASE_TAG +# y - if release tag starts with R (eg. an offical build) +# n - if release tag does not start with R (eg. a developer build) + +MKZFTREE=${MKZFTREE:-$TL_DIR/MakeTools/zisofs-tools/mkzftree} +PATCH_BRAND=${PATCH_BRAND:-$TL_DIR/MakeTools/patch_version/patch_brand} + +Usage() +{ + echo "Usage: makeiso.sh [-z] [-l 'label'] file.iso dir" >&2 + echo " default label is dir name" >&2 + echo " -z - create compressed CD" >&2 + exit 2 +} + +label= +opts= +zflag=n +while getopts zl: param +do + case $param in + l) + label="$OPTARG";; + z) + zflag=y + opts="$opts -z";; + ?) + Usage;; + esac +done +shift $((OPTIND -1)) + +if [ $# -ne 2 ] +then + Usage +fi + +if [ x"$BUILD_ISO" = x ] +then + # default based on RELEASE_TAG + if [ x`echo $RELEASE_TAG|cut -c1` = xR ] + then + BUILD_ISO=y + else + BUILD_ISO=n + fi +fi +if [ x"$BUILD_ISO" != xy ] +then + echo "Iso Image Generation Disabled" + echo "export BUILD_ISO=y to enable" + exit 0 +fi + +iso=$1 +dir=$2 + +if [ ! -d $dir ] +then + echo "makeiso.sh: $dir is not a directory" >&2 + Usage +fi + +if [ -z "$label" ] +then + label="$dir" +fi + +if [ "$zflag" = y ] +then + echo "Compressing $dir into $dir.comp..." + $MKZFTREE -p 5 $dir $dir.comp + srcdir=$dir.comp +else + srcdir=$dir +fi +echo "Creating $iso using $srcdir, Label is $label..." + +# TBD -copyright file +# TBD -abstract file +author=`$PATCH_BRAND "$BUILD_BRAND"` +mkisofs $opts -A "$label" -p "$author" -P "$author" -sysid "$label" -V "$label" -volset "$label" -volset-size 1 -volset-seqno 1 -o $iso -r -L $srcdir + +if [ "$zflag" = y ] +then + rm -rf $dir.comp +fi diff --git a/MakeTools/makewin32depend.sh b/MakeTools/makewin32depend.sh new file mode 100755 index 0000000..ad20c7f --- /dev/null +++ b/MakeTools/makewin32depend.sh @@ -0,0 +1,128 @@ +#!/bin/bash +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** +# +# File: makedepend +# +# Purpose: Creates a dependency make file for Visual Studio Source +# + + +# Function to create a dependency file for a given source file. +create_depend() { + stem=`echo ${2} | ${sed} 's/\(^.*\)\..*/\1/'` + suffix=`echo ${2} | ${sed} 's/^.*\.\(.*$\)/\1/'` + + # Do not process IDL dependencies with the C/C++ compiler. + if [[ "${suffix}" = "idl" ]] ; then + return + fi + + depend=`cl /E ${1} ${2} |\ + ${grep} '^[ \t]*#line[ \t].' | \ + ${egrep} -v -i 'devstudio|VC98|Microsoft Platform SDK' | \ + ${sed} -e 's/^[ \t]*#/#/'\ + -e 's/^.*#line[ \t].*[ \t]"\(.*\)".*/\1/g' \ + -e "/${2}/d" | \ + ${sort} -n | \ + ${uniq}` + if [[ "${suffix}" = "rc" || "${suffix}" = "RC" ]] ; then + object="${stem}.res" + else + object="${stem}.obj" + fi + depend="${object} : ${2} ${depend}" + echo ${depend} | ${sed} 's#\\\\#/#g' > ${3} +} + +Usage() { + cmd="Usage: ${0} -p -f -- -- [file1 file2 ...]" + echo ${cmd} + return +} + +if [[ "${1}" = "" ]] ; then + Usage + exit 1 +fi + +while [[ "${1}" != "" ]] ; do + case "${1}" in + '') Usage + exit 1;; + + -p) shift + tool_path=${1} + sed=${tool_path}/sed + grep=${tool_path}/grep + egrep=${tool_path}/egrep + sort=${tool_path}/sort + uniq=${tool_path}/uniq + shift + ;; + + -f) shift + out_file=${1} + shift + ;; + + --) if [[ "${flag_start}" = "" ]] ; then + flag_start=start + flags=/E + else + flag_stop=stop + fi + shift + ;; + + *) if [[ "${flag_start}" = "start" ]] ; then + if [[ "${flag_stop}" = "" ]] ; then + flags="${flags} ${1}" + else + if [[ "${tool_path}" = "" || "${out_file}" = "" ]] ; then + Usage + exit 1 + fi + create_depend "${flags}" "${1}" "${out_file}" + fi + else + Usage + exit 1 + fi + shift + ;; + + esac +done + +if [[ "${flag_start}" != "start" || "${flag_stop}" != "stop" ]] ; then + Usage + exit 1 +fi +exit 0 diff --git a/MakeTools/mkarlib.sh b/MakeTools/mkarlib.sh new file mode 100755 index 0000000..9d973ca --- /dev/null +++ b/MakeTools/mkarlib.sh @@ -0,0 +1,102 @@ +#!/bin/bash +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** +# This script is similar to the ar command, however it handles .a arguments +# as well as .o arguments. It is used when LIBFILES != "" (ie. for module +# makefiles) to assist in combining multiple archice files into one .a file +# +# This is coded for use in VxWorks, Cygwin and Linux builds. All of which +# use variations of ar and use .o and .a suffixes. +# +# This is not used for BUILD_CONFIG=loadable, where .rel files are created + +Usage() +{ + echo "Usage: mkarlib ar_tool ar_options archive file ..." >&2 + exit 2 +} + +if [ $# -lt 4 ] +then + Usage +fi + +tempDir=tmp$$ +cwd=`pwd` +trap 'rm -rf $cwd/$tempDir' 0 1 2 9 15 + +ar=$1 +options=$2 +archive=$3 +shift +shift +shift +rm -f $archive +rm -rf $tempDir +mkdir $tempDir +for file in $* +do + if expr "$file" : ".*\.a$" > /dev/null + then + ( + echo "expanding archive " $file + # for now assumes $file is a full pathname + cd $tempDir + $ar x $file + ) + if [ $? != 0 ] + then + rm -f $cwd/$archive + exit 1 + fi + elif expr "$file" : ".*\.o" > /dev/null + then + echo "copying file " $file + cp $file $tempDir + if [ $? != 0 ] + then + rm -f $cwd/$archive + exit 1 + fi + else + echo "Unsupported file type: $file" >&2 + rm -f $cwd/$archive + exit 1 + fi +done +echo "done" +ls $tempDir +$ar $options $archive $tempDir/*.o +if [ $? != 0 ] +then + rm -f $cwd/$archive + exit 1 +else + exit 0 +fi diff --git a/MakeTools/mkconfig.pl b/MakeTools/mkconfig.pl new file mode 100755 index 0000000..e5c7a5c --- /dev/null +++ b/MakeTools/mkconfig.pl @@ -0,0 +1,135 @@ +#! perl -w +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +use strict; +use Text::ParseWords; +use IO::File; + +my $bsp = shift; +my $product = uc(shift); +my $csvfile = shift; +my $inhfile = shift; +my $outfile = shift; + +if (not $outfile) { + die "usage: $0 bsp product input.csv input.h.in output.h\n"; +} + +my $CSV = IO::File->new($csvfile, "r") or die "$csvfile: $!\n"; +my $INH = IO::File->new($inhfile, "r") or die "$inhfile: $!\n"; +my $OUT = IO::File->new($outfile, "w") or die "$outfile: $!\n"; + +sub split_line { + $_[0] =~ s/^\s+//; + $_[0] =~ s/\s+$//; + $_[0] =~ s/\\n/\n /g; + return quotewords(",",0,$_[0]); +} + +my @bsps = split_line(scalar <$CSV>); +my $index = 0; +my $comment_idx = scalar @bsps - 1; + +for (my $i = 1; $i < $comment_idx; $i++) { + if ($bsps[$i] eq $bsp) { + $index = $i; + last; + } +} + +unless ($index) { + shift @bsps; + pop @bsps; + die "Unknown BSP \"$bsp\". Supported values are (", join(", ", @bsps), ")\n"; +} + +while (<$INH>) { + $OUT->print("$_"); + last if (m#\*/#); +} + +$OUT->print(<<"EOF" + +/************************************************************** + * EVERYTHING BETWEEN THESE MARKERS IS GENERATED FROM + * $csvfile + **************************************************************/ + +/* + * DO NOT EDIT BY HAND + * + * Use a spreadsheet program (such as kspread) to edit + * $csvfile + * then run make to rebuild this file. + * + */ +EOF +); + +while (<$CSV>) { + my ($flag, $value, $comment) = (split_line($_))[0,$index,$comment_idx]; + if (defined $value) { + if ($value =~ /(?:PRODUCT_)?$product\{([^}]*)\}/o) { + # got something like FCIOU{2, 1} or EIOU{} + $value = $1; + } + else { + $value =~ s/\b[A-Z][A-Z0-9_]*\{[^}]*\}//g; + $value =~ s/^\s+//; + $value =~ s/\s+$//; + } + } + if ($comment) { + $OUT->print("\n/*! $comment\n*/\n"); + } + else { + $OUT->print("\n"); + } + if ($value) { + $OUT->print("#define $flag\t$value\n"); + } + else { + $OUT->print("#undef $flag\n"); + } +} + +$OUT->print(<<"EOF" + +/************************************************************** + * END GENERATED CODE FROM + * $csvfile + **************************************************************/ + +EOF +); + +while (<$INH>) { + $OUT->print("$_"); +} diff --git a/MakeTools/optionaldir.sh b/MakeTools/optionaldir.sh new file mode 100755 index 0000000..add8427 --- /dev/null +++ b/MakeTools/optionaldir.sh @@ -0,0 +1,105 @@ +#!/bin/bash +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] +## optionaldir +## ---- +## This script is for use in toplevel makefiles to filter out optional +## directories +## +## Usage: +## optionaldir dir [ulp ...] +## Usage in a makefile: +## DIRS = $(shell $OPTIONALDIR Sdp SDP Cluster) +## +## Arguments: +## dir - directory which is optional. +## ulp - one or more ulps/components which this directory is part of +## if any of these components are enabled, this the directory will be +## output. If no ulps are specified, the directory is enabled. +## +## Environment expected: +## BUILD_ULPS - ulps/components to be enabled (defaults to all) +## BUILD_SKIP_ULPS - ulps/components to be disabled (defaults to none) +## if a ulp matches both, it will be skipped +## +## Additional Information: +## If the directory is enabled and present, this script will +## output the directory name. +## If the directory is disabled or not present, this script will +## output nothing. +USAGE="Usage: $0 dir [ulps ...]" + +BUILD_ULPS=${BUILD_ULPS:-all} +BUILD_SKIP_ULPS=${BUILD_SKIP_ULPS:-none} + +if [ "$#" -lt 1 ] +then + # omit usage string so we don't mess up Make + #echo "$USAGE" >&2 + exit 2 +fi + +dir=$1 +shift + +if [ ! -d $dir ] +then + exit 0 +fi + +if [ "$#" -eq 0 ] +then + echo "$dir" + exit 0 +fi + +enabled=0 +disabled=0 +while [ "$#" -gt 0 ] +do + ulp="$1" + if echo "$BUILD_ULPS"|egrep "$ulp|all" > /dev/null 2>/dev/null + then + enabled=1 + fi + if echo "$BUILD_SKIP_ULPS"|egrep "$ulp|all" > /dev/null 2>/dev/null + then + disabled=1 + fi + shift +done + +if [ "$disabled" = 0 -a "$enabled" = 1 ] +then + echo "$dir" +fi + +exit 0 diff --git a/MakeTools/patch_engineer_version.sh b/MakeTools/patch_engineer_version.sh new file mode 100755 index 0000000..c3a6045 --- /dev/null +++ b/MakeTools/patch_engineer_version.sh @@ -0,0 +1,51 @@ +#!/bin/sh +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +engineer=`echo $USER | cut -c-4` +timestamp='_'`date +%m%d%y_%H%M` +echo "R0$engineer$timestamp" > .ICSBOOTROMVERSIONSTRING +if [ $# != 0 ] +then + # handle case of embedded builds which don't build MakeTools patch_version + if [ -e $TL_DIR/MakeTools/patch_version/patch_version ] + then + PATCH_VERSION=${PATCH_VERSION:-$TL_DIR/MakeTools/patch_version/patch_version} + else + PATCH_VERSION=${PATCH_VERSION:-patch_version} + fi + $PATCH_VERSION R0$engineer$timestamp $1 +else + if [ -e $TL_DIR/MakeTools/convert_releasetag.pl ] + then + $TL_DIR/MakeTools/convert_releasetag.pl R0$engineer$timestamp + else + convert_releasetag R0$engineer$timestamp + fi +fi diff --git a/MakeTools/patch_version/Makefile b/MakeTools/patch_version/Makefile new file mode 100755 index 0000000..de6338c --- /dev/null +++ b/MakeTools/patch_version/Makefile @@ -0,0 +1,160 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** +# Makefile for patch_version + +# Include Make Control Settings +include $(TL_DIR)/$(PROJ_FILE_DIR)/Makesettings.project + +#=============================================================================# +# Definitions: +#-----------------------------------------------------------------------------# +# avoid catch22 +AUTODEP=no + +# Name of SubProjects +DS_SUBPROJECTS = +# name of executable or downloadable image +# FIXME: at this time can't put patch_version in BUILDDIR since rest of +# make system expects it to be found here +EXECUTABLE = patch_version$(EXE_SUFFIX) +# list of sub directories to build +DIRS = +# C files (.c) +CFILES = \ + patch_version.c \ + # Add more c files here +# C++ files (.cpp) +CCFILES = \ + # Add more cpp files here +# lex files (.lex) +LFILES = \ + # Add more lex files here +# Windows Resource Files (.rc) +RSCFILES = +# Windows IDL File (.idl) +IDLFILE = +# Windows Linker Module Definitions (.def) file for dll's +DEFFILE = +# targets to build during INCLUDES phase (add public includes here) +INCLUDE_TARGETS = \ + # Add more h hpp files here +# Non-compiled files +MISC_FILES = +# all source files +SOURCES = $(CFILES) $(CCFILES) $(LFILES) $(RSCFILES) $(IDLFILE) +# Source files to include in DSP File +DSP_SOURCES = $(INCLUDE_TARGETS) $(SOURCES) $(MISC_FILES) \ + $(RSCFILES) $(DEFFILE) $(MAKEFILE) +# all object files +OBJECTS = $(CFILES:.c=$(OBJ_SUFFIX)) $(CCFILES:.cpp=$(OBJ_SUFFIX)) \ + $(LFILES:.lex=$(OBJ_SUFFIX)) +RSCOBJECTS = $(RSCFILES:.rc=$(RES_SUFFIX)) +# targets to build during LIBS phase +LIB_TARGETS_IMPLIB = +LIB_TARGETS_ARLIB = +LIB_TARGETS_EXP = $(LIB_TARGETS_IMPLIB:$(ARLIB_SUFFIX)=$(EXP_SUFFIX)) +LIB_TARGETS_MISC = +# targets to build during CMDS phase +CMD_TARGETS_SHLIB = +CMD_TARGETS_EXE = $(EXECUTABLE) +CMD_TARGETS_MISC = patch_brand$(EXE_SUFFIX) +# files to remove during clean phase +CLEAN_TARGETS_MISC= +CLEAN_TARGETS = $(OBJECTS) $(RSCOBJECTS) $(IDL_TARGETS) $(CLEAN_TARGETS_MISC) +# other files to remove during clobber phase +CLOBBER_TARGETS_MISC= +# sub-directory to install to within bin +BIN_SUBDIR = + +# Additional Settings +#CLOCALDEBUG = User defined C debugging compilation flags [Empty] +#CCLOCALDEBUG = User defined C++ debugging compilation flags [Empty] +#CLOCAL = User defined C flags for compiling [Empty] +#CCLOCAL = User defined C++ flags for compiling [Empty] +#BSCLOCAL = User flags for Browse File Builder [Empty] +#DEPENDLOCAL = user defined makedepend flags [Empty] +#LINTLOCAL = User defined lint flags [Empty] +#LOCAL_INCLUDE_DIRS = User include directories to search for C/C++ headers [Empty] +#LDLOCAL = User defined C flags for linking [Empty] +#IMPLIBLOCAL = User flags for Object Lirary Manager [Empty] +#MIDLLOCAL = User flags for IDL compiler [Empty] +#RSCLOCAL = User flags for resource compiler [Empty] +#LOCALDEPLIBS = User libraries to include in dependencies [Empty] +#LOCALLIBS = User libraries to use when linking [Empty] +# (in addition to LOCALDEPLIBS) +#LOCAL_LIB_DIRS = User library directories for libpaths [Empty] + +LOCALDEPLIBS = + +# Include Make Rules definitions and rules +include $(TL_DIR)/$(PROJ_FILE_DIR)/Makerules.project + +#=============================================================================# +# Overrides: +#-----------------------------------------------------------------------------# +#CCOPT = # C++ optimization flags, default lets build config decide +#COPT = # C optimization flags, default lets build config decide +#SUBSYSTEM = Subsystem to build for (none, console or windows) [none] +# (Windows Only) +#USEMFC = How Windows MFC should be used (none, static, shared, no_mfc) [none] +# (Windows Only) +#=============================================================================# +# override use of patch_engineer_version to avoid error +CPROJ= + +#=============================================================================# +# Rules: +#-----------------------------------------------------------------------------# +# process Sub-directories +include $(TL_DIR)/Makerules/Maketargets.toplevel + +# build cmds and libs +include $(TL_DIR)/Makerules/Maketargets.build + +ifeq "$(PRODUCT)" "devtools" +# install for includes, libs and cmds phases +include $(TL_DIR)/Makerules/Maketargets.install +# install for stage phase +include $(TL_DIR)/Makerules/Maketargets.stage +endif + +patch_brand$(EXE_SUFFIX): $(EXECUTABLE) + $(CP) $(EXECUTABLE) patch_brand$(EXE_SUFFIX) +CMDS:: $(CMD_TARGETS) + +STAGE:: + +# Unit test execution +#include $(TL_DIR)/Makerules/Maketargets.runtest + +#=============================================================================# + +#=============================================================================# +# DO NOT DELETE THIS LINE -- make depend depends on it. +#=============================================================================# diff --git a/MakeTools/patch_version/patch_version.c b/MakeTools/patch_version/patch_version.c new file mode 100755 index 0000000..52181ad --- /dev/null +++ b/MakeTools/patch_version/patch_version.c @@ -0,0 +1,667 @@ +/*! + @file $Source: /cvs/ics/MakeTools/patch_version/patch_version.c,v $ + $Name: $ + $Revision: 1.14 $ + $Date: 2015/01/22 18:03:59 $ + @brief Utility to manage version and branding strings in executable code + */ +/* BEGIN_ICS_COPYRIGHT7 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + * ** END_ICS_COPYRIGHT7 ****************************************/ +/* [ICS VERSION STRING: unknown] */ + +/*! +This program can be invoked in 2 ways: + +When invoked as patch_version, this program has 2 main uses: +In its simplest form, it can take a tag number of the form: R#_#M#P#I# +and convert it to #.#.#.# format (it does allow for alpha and beta +release of the form: R#_#A#I# and R#_#B#I#, they get converted to +#.#A# or #.#B#). + +In addition, if given an executable, compiled program with an embedded +version string, it can alter the embedded version string. This can be +useful to change version strings after the build, especially when the +decisions for the final version # are changing, and/or the product takes +a long amount of time to compile. + +When invoked as patch_brand, this program has a simple purpose: + +In its simplest form it can take a brand (or an empty string) as its argument +and it will report on stdout the brand which will be used (and will verify the +brand's length). This can be useful to obtain the default brand. + +In addition, if given an executable, compiled program with an embedded +brand string, it can alter the embedded brand string. This can be +useful to change brand strings after the build, especially when the +decisions for the final brand are changing (or to brand for multiple customers), +and/or the product takes a long amount of time to compile. + +@heading Usage + patch_version release_tag [file ...] + patch_brand brand [file ...] + +@param release_tag - version tag of the form R#_#M#P#I# or R#_#A#I# or R#_#B#I# +@param brand - a branding string such as "Intel" +@param file - object/exe file(s) to place the #.#.#.# style version string in + If no files are specified, the program merely + performs the simpler behaviour of outputing the #.#.#.# + style version string. + +@example + The version string and brand in programs to be patched + should be coded as follows: + + // GetCodeVersion + // ----------------- + // GetCodeVersion - retrieve the code version as set by build process. + // The static string contained in this function will be changed + // by patch_version after the build is complete and the string + // has been compiled into the application. This string will be + // modified as necessary to set the version number to match that of + // the build cycle. This routine extracts the version number from + // the string and returns it. + // It accepts no arguments and returns NULL if the string cannot + // be evaluated. + // The version number created can also be extracted by the strings command + // or the internal whatversion tool + // + #define ICS_BUILD_VERSION "THIS_IS_THE_ICS_VERSION_NUMBER:@(#)000.000.000.000B000" + const char* GetCodeVersion(void) + { + static const char* BuildVersion=ICS_BUILD_VERSION; + static char* version; + static int built=0; + if (!built) + { + // locate start of version string, + // its the first digit in BuildVersion + version = strpbrk(BuildVersion, "0123456789"); + built=1; + } + return(version); + } + + #define ICS_BUILD_BRAND "THIS_IS_THE_ICS_BRAND:Intel\000 " + const char* GetCodeBrand(void) + { + static const char* BuildBrand=ICS_BUILD_BRAND; + static char* brand; + static int built=0; + if (!built) + { + // locate start of brand string, + // its the first : in BuildBrand + brand = strpbrk(BuildBrand, ":")+1; + built=1; + } + return(brand); + } + + Then use the brand and version string as follows: + printf("%s XYZ version %s\n", GetCodeBrand(), GetCodeVersion()); + + The version strings can actually be more flexibly specified than + outlined above. + +@see UiUtil::GetCodeVersion(); +@see UiUtil::GetCodeBrand(); +*/ + +#include +#include +#include +#include +#include +#include + +#define ICS_BUILD_VERSION "THIS_IS_THE_ICS_VERSION_NUMBER:@(#)000.000.000.000B000" +#define ICS_BUILD_INTERNAL_VERSION "THIS_IS_THE_ICS_INTERNAL_VERSION_NUMBER:@(#)000.000.000.000B000I0000" +#define ICS_BUILD_BRAND "THIS_IS_THE_ICS_BRAND:Intel\000 " +#define DEFAULT_BRAND "Intel" + +typedef enum { B_FALSE=0, B_TRUE } boolean; + +#define BUFFER_SIZE 8192 + +typedef enum { + NO_ERROR=0, /* Program terminated normally */ + INTERNAL_ERROR, /* Error occurred in processing */ + USAGE_ERROR /* Improper commandline arguments */ +} ApplicationExitcode; + +/*! +display a usage message to the user if the incorrect +set of arguments is passed to the application. +*/ +void Usage(const char *program_name) +{ + fprintf(stderr,"\nUsage: %s [-i][-m marker][-n version] release_tag [file ...]\n",program_name); + exit(USAGE_ERROR); +} +void UsageBrand(const char *program_name) +{ + fprintf(stderr,"\nUsage: %s [-m marker] brand [file ...]\n",program_name); + exit(USAGE_ERROR); +} + +/*! +parse the command line argument for the release tag into the external version +numbers. + +The following transformations on the release tag are done: + - All non-digits up to the 1st digit are dropped + - _ is changed to . + - M is changed to . + - P is changed to . + - I and all characters after it are dropped if the -i option is used + +Note to properly conform to the release numbering scheme +Tags must include an M level if they include a P level. +To work properly with this and other programs, the 1st character +in the resulting version # must be a digit (0-9). Hence when +using code names as the temporary version string during +development they should be started with a digit. For example: + R0capemay +will result in a version number of 0capemay + +This would be the typical way to build releases for a product +with a code name of "capemay". + +For Example: + release_tag Version String + R1_0I5 1.0 + R1_0M1I2 1.0.1 + R1_0B1I2 1.0B1 + R1_0M1A1I3 1.0.1A1 + R1_0M0P4I5 1.0.0.4 + R1_0B1P4 1.0B1.4 + R0capemayI7 0capemay + R0capemayP4I1 0capemay.4 + ICS_R2_0I5 2.0 + +@param string the string to be parsed. +@param dropI should I level be omitted + +@return pointer to a static string containing the constructed version string. + +@heading Special Cases and Error Handling + prints an error message and returns NULL on failure. +*/ +const char* ParseReleaseTag(const char* string, int dropI) +{ + static char version[100]; + const char* p; + char* q; + int done; + int processedM = 0; + int processedP = 0; + + if (! string || ! *string) + { + fprintf(stderr,"\nInvalid release tag format, empty string\n"); + return(NULL); + } + for (p=string; *p && ! isdigit(*p); p++) + ; + for (done=0, q=version; ! done && *p; p++) + { + switch (*p) + { + case 'I': + /* I starts the trailer for the release tag, it is not placed + * in the version string + */ + if (dropI) + done=1; + else + { + /* replaced with a . */ + + /* if no M tag was processed, must insert a zero placeholder */ + if (!processedM) + { + *q++ = '.'; + *q++ = '0'; + } + /* if no P tag was processed, must insert a zero placeholder */ + if (!processedP) + { + *q++ = '.'; + *q++ = '0'; + } + *q++ = '.'; + } + break; + case '_': + /* replaced with a . */ + *q++ = '.'; + break; + case 'M': + /* replaced with a . */ + *q++ = '.'; + processedM = 1; + break; + case 'P': + /* replaced with a . */ + /* if no M tag was processed, must insert a zero placeholder */ + if (!processedM) + { + *q++ = '.'; + *q++ = '0'; + processedM = 1; + } + *q++ = '.'; + processedP = 1; + break; + default: + *q++ = *p; + break; + } + } + /* version strings must start with a digit */ + if (*version < '0' || *version > '9') + { + fprintf(stderr,"\nInvalid release tag format yields: %s\n", version); + return(NULL); + } + return(version); +} + +/*! +append a marker character to the string + +@param string - string to add marker to +@param marker - marker character to add + +@return new string + +@heading Special Cases and Error Handling +*/ +char* append_marker(const char* string, char marker) +{ + char *result; + + result = malloc(strlen(string)+2); + if (result) { + strcpy(result, string); + if (marker) + strncat(result, &marker, 1); + } + return result; +} + +/*! +build the pattern string to search for and verifies the +version string will fit within the patch area + +@param version - version string intended to be placed into file + +@return pattern to search for + +@heading Special Cases and Error Handling + if version is larger than space alloted in Pattern, outputs error and + returns NULL +*/ +const char* BuildPattern(char* dest, const char* pattern, const char* version) +{ + int length; + + strcpy(dest, pattern); + /* determine length of pattern itself */ + length = strcspn(dest, "0123456789"); + /* confirm the version can be used to overwrite the rest of the + * default version string + */ + if (strlen(dest) - length < strlen(version)) + { + fprintf(stderr,"\nInvalid release tag format, too long, yields: %s\n", version); + return(NULL); /* won't fit */ + } + + dest[length] = '\0'; + return(dest); +} + +/*! +build the pattern string to search for and verifies the +brand string will fit within the patch area + +@param brand - brand string intended to be placed into file + +@return pattern to search for + +@heading Special Cases and Error Handling + if brand is larger than space alloted in Pattern, outputs error and + returns NULL +*/ +const char* BuildBrandPattern(char* dest, const char* pattern, size_t brand_size, const char* brand) +{ + int length; + + strcpy(dest, pattern); + /* determine length of pattern itself */ + length = strcspn(dest, ":")+1; + /* confirm the brand can be used to overwrite the rest of the + * default brand string + * brand_size includes \0 terminator + */ + if ((brand_size-1) - length < strlen(brand)) + { + fprintf(stderr,"\nInvalid brand, too long: '%s'\n", brand); + return(NULL); /* won't fit */ + } + + dest[length] = '\0'; + return(dest); +} + +/*! +Patch the File + +This function does an lseek, hence the position in fp is not important +when called. However it will leave fp after the bytes written. + +@param fp - file to patch. +@param offset - offset in file to place version +@param version - version string to write +@param verlen - strlen(version)+1 + +@return B_TRUE on success, or prints an error message and returns B_FALSE + on error. +*/ +boolean PerformPatch(FILE* fp, long offset, const char* version, size_t verlen) +{ + if (fp) + { + long current=ftell(fp); + if (!fseek(fp,offset,SEEK_SET)) + { + if (fwrite(version,sizeof(char),verlen,fp)==verlen) + { + if (!fseek(fp,current,SEEK_SET)) + { + return(B_TRUE); + } + fprintf(stderr,"\nRead seek on file (stream) failed\n"); + } else { + fprintf(stderr,"\nWrite of patched data failed\n"); + } + } else { + fprintf(stderr,"\nWrite seek on file (stream) failed\n"); + } + } + return(B_FALSE); +} + +/*! +Patch the version string into the given filename at the position where pattern +is found. + +The function opens the filename specified, searches the file for the +matching ID string, patches the version number and closes the file. + +@param filename - file to patch +@param pattern - search pattern +@param patlen - strlen(pattern) +@param version - version string +@param verlen - strlen(version)+1 + +@return B_TRUE on success, otherwise it prints an error message + and returns B_FALSE. +*/ +boolean PatchFilename(const char* filename, const char* pattern, int patlen, + const char* version, size_t verlen) +{ + FILE* fp = NULL; + char buffer[BUFFER_SIZE]; + char* bufp; + char* bufp2; + const char* patp; + int i; + boolean patched=B_FALSE; + boolean finished=B_FALSE; + if (filename && *filename) + { + if ((fp=fopen(filename,"r+"))==NULL) + { + perror(filename); + goto patch_error; + } + while (!finished) + { + int nbytes=fread(buffer,sizeof(char),BUFFER_SIZE,fp); + bufp=buffer; + if (!nbytes) /* End of file */ + { + finished=B_TRUE; + continue; + } + if (nbytes<0) /* Error */ + { + fprintf(stderr,"\nPremature EOF: %s\n",filename); + goto patch_error; + } + while ((bufp-buffer)+patlen<=nbytes) + { + i = 0; + patp = pattern; + bufp2 = bufp; + while ((*bufp++ == *patp++) && (i < patlen)) i++; + + if (i == patlen) + { + long match_offset=(ftell(fp)-nbytes)+(bufp2-buffer)+patlen; + if (!PerformPatch(fp,match_offset,version, verlen)) + { + goto patch_error; + } + patched=B_TRUE; + } + + bufp = bufp2 + 1; + } + if (nbytes <= patlen) + { + /* must have just processed the last part of the file */ + finished=B_TRUE; + continue; + } + /* go to next buffer, but include patlen bytes from previous + * in case version string crosses a buffer boundary + */ + if (fseek(fp, -patlen, SEEK_CUR) == -1) + { + fprintf(stderr,"\nCan't seek: %s\n",filename); + goto patch_error; + } + } + fclose(fp); + fp = NULL; + if (!patched) + { + fprintf(stderr,"\nVersion string search pattern not found: %.*s\n", patlen, pattern); + goto patch_error; + } + return(B_TRUE); + } +patch_error: + if (fp != NULL) + { + fclose(fp); + } + fprintf(stderr,"Patch failed for filename: %s\n\n",(filename)?filename:"NULL"); + return(B_FALSE); +} + +char *basename(char *filename) +{ + char *p; + + p = strrchr(filename, '/'); + if (p == NULL) + return filename; + else + return p+1; +} + +/*! +search through binary a.out files looking for the ICS version string +and updating the internal field so that the executables will have the correct +version string information usable internally from a post build scenario. +This application is not used to place a version reference in all a.out files, +but specifically in a few with a certain internal static buffer. +The program accepts two or more arguments on the command line. + +The first argument must specify the source repository tag. + +The other arguments specify filenames. + +The tag is split into four numeric fields (major, minor, patch, +and integration build). All four fields +must be valid and the tag argument is required. At least one filename must +also be specified and all filename arguments are opened in sequence and the +patch performed. The program returns a 0 on success and a positive number +on error. (1=Error in processing, 2=Usage). +*/ +int main(int argc,char* argv[]) +{ + ApplicationExitcode result=NO_ERROR; + const char* version = NULL; + const char* internalVersion; + int position; + int numArgs; + int rc; + int dropI = 0; + char pattern[1024]; + char marker = '\0'; + /*char pattern[MAX(sizeof(ICS_BUILD_VERSION)+1,sizeof(ICS_BUILD_BRAND)+1]; */ + char internalPattern[sizeof(ICS_BUILD_INTERNAL_VERSION)+1]; + int brand = 0; + + brand = (strcmp(basename(argv[0]), "patch_brand") == 0); + + while ((rc = getopt(argc, argv, "im:n:")) != -1) + { + switch (rc) + { + case 'i': + dropI = 1; + break; + case 'm': + marker = optarg[0]; + break; + case 'n': + /* Override ParseReleaseTag() functionality by supplying an already-formatted version string. */ + version = optarg; + break; + default: + break; + } + } + numArgs = argc - optind; + if (brand) + { + if (numArgs<1) + { + UsageBrand(argv[0]); + } + version = argv[optind]; + if (strlen(version) == 0) + { + version = DEFAULT_BRAND; + } + version = append_marker(version, marker); + if (!version) + { + exit(INTERNAL_ERROR); + } + internalVersion = NULL; + if ((BuildBrandPattern(pattern, ICS_BUILD_BRAND, sizeof(ICS_BUILD_BRAND), version)) == NULL) + { + exit(USAGE_ERROR); + } + } else { + if (numArgs<1) + { + Usage(argv[0]); + } + + if (version == NULL && (version = ParseReleaseTag(argv[optind], dropI)) == NULL) + { + exit(USAGE_ERROR); + } + version = append_marker(version, marker); + if (!version) + { + exit(INTERNAL_ERROR); + } + internalVersion = append_marker(argv[optind], marker); + if (!internalVersion) + { + exit(INTERNAL_ERROR); + } + if ((BuildPattern(pattern, ICS_BUILD_VERSION, version)) == NULL) + { + exit(USAGE_ERROR); + } + if ((BuildPattern(internalPattern, ICS_BUILD_INTERNAL_VERSION, internalVersion)) == NULL) + { + exit(USAGE_ERROR); + } + } + if (numArgs == 1) + { + /* no program names, just put version string to stdout */ + printf("%s\n", version); + exit(NO_ERROR); + } + for (position = optind + 1; position < argc; position++) + { + /* include the '\0' in the version in the patch so that the version string + * is properly terminated when version is shorter than the space allowed + */ + if (brand) + printf("Patching %s with brand '%s'\n", argv[position], version); + else + printf("Patching %s with version strings %s and %s\n", argv[position], version, + internalVersion?internalVersion:""); + if (!PatchFilename(argv[position], pattern, strlen(pattern), version, strlen(version)+1)) + { + result=INTERNAL_ERROR; + } + if (internalVersion) + { + if (!PatchFilename(argv[position], internalPattern, strlen(internalPattern), internalVersion, strlen(internalVersion)+1)) + { + result=INTERNAL_ERROR; + } + } + } + exit(result); +} diff --git a/MakeTools/prep.sh b/MakeTools/prep.sh new file mode 100755 index 0000000..e7f4c86 --- /dev/null +++ b/MakeTools/prep.sh @@ -0,0 +1,197 @@ +#!/bin/bash +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] +## prep +## ---- +## This script will mark all the files in a release with the appropriate +## release tag +## +## Usage: +## cd $CODE_DIR; find . -print|prep [version_marker] +## +## Arguments: +## version_marker - the string to look for at the start of each +## version string in scripts, and the string to add (with tag +## appended) to mark all files. For example: "ICS VERSION STRING" +## The default is "ICS VERSION STRING" +## +## Environment expected: +## TL_DIR = top level directory +## RELEASE_TAG = cvs release tag to mark in each file +## MCS = mcs program to use (defaults to mcs) +## AR = ar program to use (default to ar) +## DATE = date string to include in file (defaults to current date/time) +## +## Method of marking: +## archives, executables, dynamic libraries, relocatable .o's +## On Linux/Cygwin: +## - version string appended at end of file +## Future/Other: +## - mcs used to put version string in .comment section of ELF file +## other files (text, etc) +## - sed used to replace "$version_marker:.*]" with the version +## string. Note that the version string in text files ends in a +## ] and will include "$version_marker:", hence prep can be +## run multiple times against a given file/tree + +USAGE="Usage: $0 [version_marker] < filelist" + +trap 'rm -f /tmp/prep$$; exit 1' 1 2 3 9 15 + +MCS=${MCS:-mcs} +AR=${AR:-ar} +if [ -e $TL_DIR/MakeTools/rm_version/rm_version ] +then + RM_VERSION=${RM_VERSION:-$TL_DIR/MakeTools/rm_version/rm_version} +else + RM_VERSION=${RM_VERSION:-rm_version} +fi + +if [ "${RELEASE_TAG:-}" = "" ] +then + echo "$0: RELEASE_TAG must be exported" + exit 1 +fi + +DATE_FMT='%m/%d/%y %H:%M' +[ -z "$SOURCE_DATE_EPOCH" ] ||\ + DATE=${DATE:-"`date -u -d@$SOURCE_DATE_EPOCH "+$DATE_FMT"`"} +DATE=${DATE:-"`date "+$DATE_FMT"`"} + +if [ "$#" = 1 ] +then + version_marker="$1" + shift +else + version_marker="ICS VERSION STRING" +fi +if [ "$#" != 0 ] +then + echo "$USAGE" + exit 2 +fi +# determine gcc version, 2.96 level of tools can have some problems +gcc_major=`gcc -v 2>&1|fgrep 'gcc version'|cut -f3 -d' '|cut -f1 -d'.'` + +echo "$0: $RELEASE_TAG [$DATE]" + +# stdin is the input to xargs +xargs file | sed -e 's/:[ ]/ /'| \ + while read name filetype + do + if [ -L $name ] + then + # skip symbolic links + continue + fi + VERSION_STRING="@(#) $name $RELEASE_TAG [$DATE]" + case "$name" in + *.uid) + # no mcs command equivalent for uid files + # however appending to the end the .uid file + # doesn't seem to hurt + $RM_VERSION -m "$version_marker" $name >/dev/null + echo "$version_marker: $VERSION_STRING" >> $name + echo "Version string added to: $name" + continue;; + *.gz|*.tgz) + # skip compressed files + continue;; + *.res) + # skip result files + continue;; + esac + case "$filetype" in + *directory*) + echo "Processing Directory $name..." + ;; + *text*|*script*) + # only sed files which have the pattern, + # this avoids corrupting data files + # -q causes grep to exit on first match (for performance) + if grep -q "$version_marker:" $name >/dev/null + then + sed -e "s|$version_marker:.*]|$version_marker: $VERSION_STRING|" < $name > /tmp/prep$$ + # this keeps original permissions on the file + cat /tmp/prep$$ > $name + echo "Version string added to: $name" + else + > /dev/null + #echo "warning: No version string in file: $name" + fi;; + *ELF*|*executable*|*archive*|*relocatable*|*dynamic?lib*|*shared?lib*) + if false + then + # no objcopy/msc command equivalent + # however appending to the end of a.out or .sl file + # doesn't seem to hurt + $RM_VERSION -m "$version_marker" $name >/dev/null + echo "$version_marker: $VERSION_STRING" >> $name + echo "Version string added to: $name" + else + #$MCS -d -a "$VERSION_STRING" $name + #case "$filetype" in + #*archive*) + # echo "Adding symbol table back to $name ($AR ts $name)" + # $AR ts $name >/dev/null + # ;; + #esac + echo "$version_marker: $VERSION_STRING" > /tmp/prep$$ + #set -x + # RH7 tools have an issue here, not sure if its gcc 2.96 or + # objcopy 2.11 issue, key off gcc version for now + if [ "$gcc_major" -gt 2 ] + then + objcopy --remove-section=.ics_comment --add-section .ics_comment=/tmp/prep$$ $name + fi + #set +x + echo "Version string added to: $name" + fi + ;; + *) + # only sed files which have the pattern, + # this avoids corrupting data files + # -q causes grep to exit on first match (for performance) + if grep -q "$version_marker:" $name >/dev/null + then + sed -e "s|$version_marker:.*]|$version_marker: $VERSION_STRING|" < $name > /tmp/prep$$ + # this keeps original permissions on the file + cat /tmp/prep$$ > $name + echo "Version string added to: $name" + else + > /dev/null + #echo "warning: No version string in file: $name" + fi + esac + done + +rm -f /tmp/prep$$ +exit 0 diff --git a/MakeTools/repackage_srpm.sh b/MakeTools/repackage_srpm.sh new file mode 100755 index 0000000..2caf72e --- /dev/null +++ b/MakeTools/repackage_srpm.sh @@ -0,0 +1,40 @@ +#!/bin/sh +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +#[ICS VERSION STRING: unknown] + +# sample of how to repackage a rpm which was taken apart using +# rpm2cpio|cpio -icv + +mkdir SOURCES SPECS SRPMS +cp ofa_kernel-1.4.tgz SOURCES/ +cp ofa_kernel.spec SPECS/ +rpmbuild -bs --define "_topdir `pwd`" SPECS/ofa_kernel.spec + diff --git a/MakeTools/rm_fastfabric.sh b/MakeTools/rm_fastfabric.sh new file mode 100755 index 0000000..01b1eb4 --- /dev/null +++ b/MakeTools/rm_fastfabric.sh @@ -0,0 +1,44 @@ +#!/bin/bash +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +#[ICS VERSION STRING: unknown] +# remove fast fabric from InfiniServ object package $1 + +rm -rf obj +mkdir obj + +cd obj +echo "Packaging $1..." +tar xvfz ../$1 +rm -rf */bin/opafabricinfo */bin/opascpall */bin/opauploadall */bin/opadownloadall \ + */bin/opasetupssh */bin/opapingall */bin/opacmdall */bin/opacaptureall \ + */bin/opashowallports */bin/opatest */tools +tar cvfz ../$1 InfiniServ* +rm -rf obj diff --git a/MakeTools/rm_version/Makefile b/MakeTools/rm_version/Makefile new file mode 100755 index 0000000..17b009e --- /dev/null +++ b/MakeTools/rm_version/Makefile @@ -0,0 +1,155 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** +# Makefile for rm_version + +# Include Make Control Settings +include $(TL_DIR)/$(PROJ_FILE_DIR)/Makesettings.project + +#=============================================================================# +# Definitions: +#-----------------------------------------------------------------------------# +# avoid catch22 +AUTODEP=no + +# Name of SubProjects +DS_SUBPROJECTS = +# name of executable or downloadable image +# FIXME: at this time can't put rm_version in BUILDDIR since rest of +# make system expects it to be found here +EXECUTABLE = rm_version$(EXE_SUFFIX) +# list of sub directories to build +DIRS = +# C files (.c) +CFILES = \ + rm_version.c \ + # Add more c files here +# C++ files (.cpp) +CCFILES = \ + # Add more cpp files here +# lex files (.lex) +LFILES = \ + # Add more lex files here +# Windows Resource Files (.rc) +RSCFILES = +# Windows IDL File (.idl) +IDLFILE = +# Windows Linker Module Definitions (.def) file for dll's +DEFFILE = +# targets to build during INCLUDES phase (add public includes here) +INCLUDE_TARGETS = \ + # Add more h hpp files here +# Non-compiled files +MISC_FILES = +# all source files +SOURCES = $(CFILES) $(CCFILES) $(LFILES) $(RSCFILES) $(IDLFILE) +# Source files to include in DSP File +DSP_SOURCES = $(INCLUDE_TARGETS) $(SOURCES) $(MISC_FILES) \ + $(RSCFILES) $(DEFFILE) $(MAKEFILE) +# all object files +OBJECTS = $(CFILES:.c=$(OBJ_SUFFIX)) $(CCFILES:.cpp=$(OBJ_SUFFIX)) \ + $(LFILES:.lex=$(OBJ_SUFFIX)) +RSCOBJECTS = $(RSCFILES:.rc=$(RES_SUFFIX)) +# targets to build during LIBS phase +LIB_TARGETS_IMPLIB = +LIB_TARGETS_ARLIB = +LIB_TARGETS_EXP = $(LIB_TARGETS_IMPLIB:$(ARLIB_SUFFIX)=$(EXP_SUFFIX)) +LIB_TARGETS_MISC = +# targets to build during CMDS phase +CMD_TARGETS_SHLIB = +CMD_TARGETS_EXE = $(EXECUTABLE) +CMD_TARGETS_MISC = +# files to remove during clean phase +CLEAN_TARGETS_MISC= +CLEAN_TARGETS = $(OBJECTS) $(RSCOBJECTS) $(IDL_TARGETS) $(CLEAN_TARGETS_MISC) +# other files to remove during clobber phase +CLOBBER_TARGETS_MISC= +# sub-directory to install to within bin +BIN_SUBDIR = + +# Additional Settings +#CLOCALDEBUG = User defined C debugging compilation flags [Empty] +#CCLOCALDEBUG = User defined C++ debugging compilation flags [Empty] +#CLOCAL = User defined C flags for compiling [Empty] +#CCLOCAL = User defined C++ flags for compiling [Empty] +#BSCLOCAL = User flags for Browse File Builder [Empty] +#DEPENDLOCAL = user defined makedepend flags [Empty] +#LINTLOCAL = User defined lint flags [Empty] +#LOCAL_INCLUDE_DIRS = User include directories to search for C/C++ headers [Empty] +#LDLOCAL = User defined C flags for linking [Empty] +#IMPLIBLOCAL = User flags for Object Lirary Manager [Empty] +#MIDLLOCAL = User flags for IDL compiler [Empty] +#RSCLOCAL = User flags for resource compiler [Empty] +#LOCALDEPLIBS = User libraries to include in dependencies [Empty] +#LOCALLIBS = User libraries to use when linking [Empty] +# (in addition to LOCALDEPLIBS) +#LOCAL_LIB_DIRS = User library directories for libpaths [Empty] + +LOCALDEPLIBS = + +# Include Make Rules definitions and rules +include $(TL_DIR)/$(PROJ_FILE_DIR)/Makerules.project + +#=============================================================================# +# Overrides: +#-----------------------------------------------------------------------------# +#CCOPT = # C++ optimization flags, default lets build config decide +#COPT = # C optimization flags, default lets build config decide +#SUBSYSTEM = Subsystem to build for (none, console or windows) [none] +# (Windows Only) +#USEMFC = How Windows MFC should be used (none, static, shared, no_mfc) [none] +# (Windows Only) +#=============================================================================# + +#=============================================================================# +# Rules: +#-----------------------------------------------------------------------------# +# process Sub-directories +include $(TL_DIR)/Makerules/Maketargets.toplevel + +# build cmds and libs +include $(TL_DIR)/Makerules/Maketargets.build + +ifeq "$(PRODUCT)" "devtools" +# install for includes, libs and cmds phases +include $(TL_DIR)/Makerules/Maketargets.install +# install for stage phase +include $(TL_DIR)/Makerules/Maketargets.stage +endif + +CMDS:: $(CMD_TARGETS) +STAGE:: + +# Unit test execution +#include $(TL_DIR)/Makerules/Maketargets.runtest + +#=============================================================================# + +#=============================================================================# +# DO NOT DELETE THIS LINE -- make depend depends on it. +#=============================================================================# diff --git a/MakeTools/rm_version/rm_version.c b/MakeTools/rm_version/rm_version.c new file mode 100755 index 0000000..cc99c60 --- /dev/null +++ b/MakeTools/rm_version/rm_version.c @@ -0,0 +1,194 @@ +/* BEGIN_ICS_COPYRIGHT7 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT7 ****************************************/ +/*! + @file $Source: /cvs/ics/MakeTools/rm_version/rm_version.c,v $ + $Name: $ + $Revision: 1.5 $ + $Date: 2015/01/22 18:04:00 $ + @brief Program to remove version strings appended at end of file by prep + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern int ftruncate(int __fd, off_t __length); + + +/*! +Remove the version string from a .uid or Linux/Cygwin/MIPS a.out file + +This scans the last 1024 bytes of the given file for a +version string which starts with "version_marker:" +If the pattern is matched, the file is truncated such that +"version_marker:" and all bytes which follow it are +removed from the file. + +THIS SHOULD ONLY BE RUN AGAINST FILES WHICH prep MAY HAVE +APPENDED A VERSION STRING TO. FOR OTHER FILES WHICH PREP +EDITS WITH mcs OR sed, THIS MAY CORRUPT THE FILE. + +The scan for "version_marker" is done by a reverse scan +of the last 1024 bytes of the file, it stops on the first match + +@heading Usage + rm_version [-m version_marker] file ... +@param version_marker - version marker to look for, default is + "ICS VERSION STRING" +@param file - name of a file which may have a version string + appended to it +*/ + +/* the string we are looking for */ +#define MAGIC_STRING "ICS VERSION STRING:" +int magiclen; /* length of MAGIC_STRING */ +const char* magic=MAGIC_STRING; + +/*! +remove the version string from the specified file + +@param filename - name of file to fix + +@return 0 on success, 1 on failure +*/ +int fix_file(char* filename) +{ + int fd; + struct stat statbuf; + int end; /* offset of last 1024 bytes of file */ + int size; /* size of file starting at offset end */ +#define MAXBUF 1024 + char buffer[MAXBUF]; /* holding area for scan */ + int offset; /* current offset from end for scan */ + + if (stat(filename, &statbuf) == -1 + || (fd = open(filename, O_RDWR)) == -1) + { + fprintf(stderr, "rm_version: Can't open: "); + perror(filename); + return(1); + } + if (statbuf.st_size < MAXBUF) + { + /* small file, limit to file size */ + end = 0; + size = statbuf.st_size; + } else { + end = statbuf.st_size - MAXBUF; + size = MAXBUF; + } + if (lseek(fd, end, SEEK_SET) == -1) + { + fprintf(stderr, "rm_version: Can't seek: "); + perror(filename); + close(fd); + return(1); + } + /* unfortunately CYGWIN or NT seem to be off on st_size since + * you typically can't read size bytes here. Linux is fine + */ + /*if (read(fd, buffer, size) != size)*/ + if (read(fd, buffer, size) == -1) + { + fprintf(stderr, "rm_version: Can't read: "); + perror(filename); + close(fd); + return(1); + } + /* scan buffer for 'ICS VERSION STRING' */ + for (offset = size-magiclen; offset >= 0; offset--) + { + if (strncmp(buffer+offset, magic, magiclen) == 0) + { + goto found; + } + } + /* not found */ + close(fd); + return(0); + +found: + /* found the string at offset */ + if (ftruncate(fd, end+offset) == -1) + { + fprintf(stderr, "rm_version: Can't truncate: "); + perror(filename); + close(fd); + return(1); + } + close(fd); + printf("%s: %d bytes removed\n", filename, size-offset); + return(0); +} + +void usage(void) +{ + fprintf(stderr, "Usage: rm_version [-m version_marker] file ..."); + exit(2); +} + +int main(int argc, char** argv) +{ + int i; + int res; + int c; + extern char* optarg; + extern int optind; + + while ((c = getopt(argc, argv, "m:")) != -1) + { + switch (c) + { + case 'm': /* version_marker */ + magic = optarg; + break; + case '?': + usage(); + } + } + + if (argc == optind) + { + usage(); + } + magiclen = strlen(magic); + res = 0; + for (i=optind; i< argc; i++) + { + res |= fix_file(argv[i]); + } + + return res; +} diff --git a/MakeTools/setenv b/MakeTools/setenv new file mode 100755 index 0000000..e3a2c1b --- /dev/null +++ b/MakeTools/setenv @@ -0,0 +1,101 @@ +#!/bin/bash +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# Simple script to setup environment for a build for current OS version/type +. $ICSBIN/funcs.sh +settl + +. $TL_DIR/MakeTools/funcs-ext.sh +export BUILD_PLATFORM_OS_VENDOR=`os_vendor` +export BUILD_UNIT_TEST=no +export BUILD_CONFIG=${BUILD_CONFIG:-release} # can be exported as "debug" +export BUILD_TARGET_OS_VENDOR=$BUILD_PLATFORM_OS_VENDOR +if [ `uname -s` == "Darwin" ] +then + export BUILD_PLATFORM=DARWIN + export BUILD_TARGET_OS=DARWIN + export BUILD_TARGET_TOOLCHAIN=GNU + export BUILD_TARGET_OS_VERSION=`sw_vers -productVersion|cut -f1-2 -d.` +else + export BUILD_PLATFORM=LINUX + export BUILD_TARGET_OS=LINUX + export BUILD_TARGET_TOOLCHAIN=GNU + export BUILD_TARGET_OS_VERSION=${BUILD_TARGET_OS_VERSION:-`uname -r`} + if [ ${BUILD_TARGET_OS_VERSION:0:3} = '2.6' -o \ + ${BUILD_TARGET_OS_VERSION:0:2} = '3.' -o \ + ${BUILD_TARGET_OS_VERSION:0:2} = '4.' ] + then + export BUILD_26=1 + else + unset BUILD_26 + fi +fi + +case `uname -m` in +"Power Macintosh") + export BUILD_TARGET=PPC + ;; +ppc64) + export BUILD_TARGET=PPC64 + ;; +i686|ia32|IA32) + export BUILD_TARGET=IA32 + ;; +ia64|IA64) + export BUILD_TARGET=IA64 + ;; +x86_64|X86_64) + chip_vendor=`grep vendor_id /proc/cpuinfo | tail -1 | awk '{print $3}'` + BUILD_TARGET=X86_64 + # should just be redhat and rocks + if [ x$BUILD_26 = x -a "$chip_vendor" = "GenuineIntel" ] + then + BUILD_TARGET=EM64T + fi + export BUILD_TARGET + ;; +*) + echo "Unsupported platform: `uname -m`" >&2 + exit 1 + ;; +esac +export BUILD_PLATFORM_OS_VENDOR_VERSION=`os_vendor_version $BUILD_PLATFORM_OS_VENDOR` +export BUILD_TARGET_OS_VENDOR_VERSION=$BUILD_PLATFORM_OS_VENDOR_VERSION +set_os_identifier +if [ -e Version ] +then + export RELEASE_TAG=`cat Version`G +else + export RELEASE_TAG=${RELEASE_TAG:-`patch_engineer_version|cut -d"." -f1`} +fi +export BUILD_ULPS=${BUILD_ULPS:-all} +export BUILD_SKIP_ULPS=${BUILD_SKIP_ULPS:-none} + +showenv diff --git a/MakeTools/stripdepends.sh b/MakeTools/stripdepends.sh new file mode 100755 index 0000000..9a24e7d --- /dev/null +++ b/MakeTools/stripdepends.sh @@ -0,0 +1,52 @@ +#!/bin/sh +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# remove dependencies on system include files from the generated dependency file +# this will allow make to run a little faster since we don't expect to see +# system files change between runs of make + +if [ $# != 1 ] +then + echo "Usage: stripdepends.sh filename" >&2 + exit 2 +fi + +tmp=.`basename $1` + +sed -e '{ :start + s|[^ ]*usr/include[^ ]*|| + s|[^ ]*usr/lib[^ ]*|| + s|[^ ]*/cygwin/usr[^ ]*|| + s|[^ ]*/Tornado[^ ]*|| + t start + } + /^[ ]*$/d + /^[ ]*\\$/d' < $1 > $tmp +mv $tmp $1 diff --git a/MakeTools/stripdepends/Makefile b/MakeTools/stripdepends/Makefile new file mode 100755 index 0000000..a8faad2 --- /dev/null +++ b/MakeTools/stripdepends/Makefile @@ -0,0 +1,155 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** +# Makefile for stripdepends + +# Include Make Control Settings +include $(TL_DIR)/$(PROJ_FILE_DIR)/Makesettings.project + +#=============================================================================# +# Definitions: +#-----------------------------------------------------------------------------# +# avoid catch22 +AUTODEP=no + +# Name of SubProjects +DS_SUBPROJECTS = +# name of executable or downloadable image +# FIXME: at this time can't put stripdepends in BUILDDIR since rest of +# make system expects it to be found here +EXECUTABLE = stripdepends$(EXE_SUFFIX) +# list of sub directories to build +DIRS = +# C files (.c) +CFILES = \ + # Add more c files here +# C++ files (.cpp) +CCFILES = \ + stripdepends.cpp \ + # Add more cpp files here +# lex files (.lex) +LFILES = \ + # Add more lex files here +# Windows Resource Files (.rc) +RSCFILES = +# Windows IDL File (.idl) +IDLFILE = +# Windows Linker Module Definitions (.def) file for dll's +DEFFILE = +# targets to build during INCLUDES phase (add public includes here) +INCLUDE_TARGETS = \ + # Add more h hpp files here +# Non-compiled files +MISC_FILES = +# all source files +SOURCES = $(CFILES) $(CCFILES) $(LFILES) $(RSCFILES) $(IDLFILE) +# Source files to include in DSP File +DSP_SOURCES = $(INCLUDE_TARGETS) $(SOURCES) $(MISC_FILES) \ + $(RSCFILES) $(DEFFILE) $(MAKEFILE) +# all object files +OBJECTS = $(CFILES:.c=$(OBJ_SUFFIX)) $(CCFILES:.cpp=$(OBJ_SUFFIX)) \ + $(LFILES:.lex=$(OBJ_SUFFIX)) +RSCOBJECTS = $(RSCFILES:.rc=$(RES_SUFFIX)) +# targets to build during LIBS phase +LIB_TARGETS_IMPLIB = +LIB_TARGETS_ARLIB = +LIB_TARGETS_EXP = $(LIB_TARGETS_IMPLIB:$(ARLIB_SUFFIX)=$(EXP_SUFFIX)) +LIB_TARGETS_MISC = +# targets to build during CMDS phase +CMD_TARGETS_SHLIB = +CMD_TARGETS_EXE = $(EXECUTABLE) +CMD_TARGETS_MISC = +# files to remove during clean phase +CLEAN_TARGETS_MISC= +CLEAN_TARGETS = $(OBJECTS) $(RSCOBJECTS) $(IDL_TARGETS) $(CLEAN_TARGETS_MISC) +# other files to remove during clobber phase +CLOBBER_TARGETS_MISC= +# sub-directory to install to within bin +BIN_SUBDIR = + +# Additional Settings +#CLOCALDEBUG = User defined C debugging compilation flags [Empty] +#CCLOCALDEBUG = User defined C++ debugging compilation flags [Empty] +#CLOCAL = User defined C flags for compiling [Empty] +#CCLOCAL = User defined C++ flags for compiling [Empty] +#BSCLOCAL = User flags for Browse File Builder [Empty] +#DEPENDLOCAL = user defined makedepend flags [Empty] +#LINTLOCAL = User defined lint flags [Empty] +#LOCAL_INCLUDE_DIRS = User include directories to search for C/C++ headers [Empty] +#LDLOCAL = User defined C flags for linking [Empty] +#IMPLIBLOCAL = User flags for Object Lirary Manager [Empty] +#MIDLLOCAL = User flags for IDL compiler [Empty] +#RSCLOCAL = User flags for resource compiler [Empty] +#LOCALDEPLIBS = User libraries to include in dependencies [Empty] +#LOCALLIBS = User libraries to use when linking [Empty] +# (in addition to LOCALDEPLIBS) +#LOCAL_LIB_DIRS = User library directories for libpaths [Empty] + +LOCALDEPLIBS = + +# Include Make Rules definitions and rules +include $(TL_DIR)/$(PROJ_FILE_DIR)/Makerules.project + +#=============================================================================# +# Overrides: +#-----------------------------------------------------------------------------# +#CCOPT = # C++ optimization flags, default lets build config decide +#COPT = # C optimization flags, default lets build config decide +#SUBSYSTEM = Subsystem to build for (none, console or windows) [none] +# (Windows Only) +#USEMFC = How Windows MFC should be used (none, static, shared, no_mfc) [none] +# (Windows Only) +#=============================================================================# + +#=============================================================================# +# Rules: +#-----------------------------------------------------------------------------# +# process Sub-directories +include $(TL_DIR)/Makerules/Maketargets.toplevel + +# build cmds and libs +include $(TL_DIR)/Makerules/Maketargets.build + +ifeq "$(PRODUCT)" "devtools" +# install for includes, libs and cmds phases +include $(TL_DIR)/Makerules/Maketargets.install +# install for stage phase +include $(TL_DIR)/Makerules/Maketargets.stage +endif + +CMDS:: $(CMD_TARGETS) +STAGE:: + +# Unit test execution +#include $(TL_DIR)/Makerules/Maketargets.runtest + +#=============================================================================# + +#=============================================================================# +# DO NOT DELETE THIS LINE -- make depend depends on it. +#=============================================================================# diff --git a/MakeTools/stripdepends/stripdepends.cpp b/MakeTools/stripdepends/stripdepends.cpp new file mode 100755 index 0000000..02dbf55 --- /dev/null +++ b/MakeTools/stripdepends/stripdepends.cpp @@ -0,0 +1,154 @@ +/* BEGIN_ICS_COPYRIGHT7 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT7 ****************************************/ + +// This is an optimized program which edits the input file to accomplish +// the following set of edits +// sed -e '{ :start +// s|[^ ]*usr/include[^ ]*|| +// s|[^ ]*usr/lib[^ ]*|| +// s|[^ ]*/cygwin/usr[^ ]*|| +// s|[^ ]*/Tornado[^ ]*|| +// t start +// } +// /^[ ]*$/d +// /^[ ]*\\$/d' < $1 > $tmp +//mv $tmp $1 + +#include +#include +#include +#include +#include +#include + +#define BUFSIZE 256 +#define SBUFSIZE 64 + +#define TRUE 1 +#define FALSE 0 + +#define BACKSLASH '\\' +#define NL '\n' + +#define SYSTEM_STRING1 "usr/include" +#define SYSTEM_STRING2 "usr/lib" +#define CYGWIN_STRING "/cygwin/usr" +#define TORNADO_STRING "/Tornado" + +#define FIND_BAD_STRING(p, buf) \ +{ \ + if (((p) = strstr((buf), SYSTEM_STRING1)) == NULL) \ + if (((p) = strstr((buf), SYSTEM_STRING2)) == NULL) \ + if (((p) = strstr((buf), CYGWIN_STRING)) == NULL) \ + (p) = strstr((buf), TORNADO_STRING); \ +} + +int compress_buf(char *buf) +{ + char *p = buf; + + while (isspace(*p)) + p++; + if ((*p == NL) || + ((*p == BACKSLASH) && (*(p+1) == NL))) + return(0); + else + return(1); +} + +int main(int argc, char *argv[]) +{ + + FILE *fp_in, *fp_out; + char inbuf[BUFSIZE]; + char outbuf[BUFSIZE]; + char *ip, *op; + char infname[BUFSIZE]; + char outfname[BUFSIZE]; + char *outbase; + int move_len; + + if (argc != 2) + { + fprintf(stderr, "Usage: stripdepends filename\n"); + exit(1); + } + + strncpy(infname, argv[1], BUFSIZE-1); + infname[BUFSIZE-1] = 0; + + if ((fp_in = fopen(argv[1], "r")) == NULL) + { + fprintf(stderr, "Error opening file <%s> for input: %s\n", + argv[1], strerror(errno)); + exit(1); + } + + outbase = basename(argv[1]); + snprintf(outfname, sizeof outfname, ".%s", outbase); + if ((fp_out = fopen(outfname, "w")) == NULL) + { + fprintf(stderr, "Error opening file <%s> for output: %s\n", + outfname, strerror(errno)); + exit(1); + } + + while (fgets(inbuf, BUFSIZE, fp_in) != NULL) + { + snprintf(outbuf, sizeof outbuf, "%s", inbuf); + FIND_BAD_STRING(ip, outbuf); + while (ip) + { + op = ip; + /* put ip at beginning, op at end */ + while (!isspace(*ip)) + ip--; + while (!isspace(*op)) + op++; + /* move op to ip */ + move_len = strlen(op); + memmove(ip, op, move_len + 1); /* add 1 to include NUL */ + FIND_BAD_STRING(ip, outbuf); + } + if (compress_buf(outbuf)) + fprintf(fp_out, "%s", outbuf); + } + + + fclose(fp_in); + fclose(fp_out); + if (rename(outfname, infname) < 0) + { + fprintf(stderr, "Error renaming file %s to %s: %s\n", + outfname, infname, strerror(errno)); + exit(1); + } + + exit(0); +} diff --git a/MakeTools/unifdef2.sh b/MakeTools/unifdef2.sh new file mode 100755 index 0000000..05cf084 --- /dev/null +++ b/MakeTools/unifdef2.sh @@ -0,0 +1,200 @@ +#!/bin/bash + +################################################################################### +# +# unifdef2.sh script +# +# Arguments: +# featureset-tag - this names the feature set and is used to identify sections +# in the in-file to be considered in the out-file +# in-file - the input file. The file must contain at least one instance of +# "ifdef " and "endif " bracketing some text +# out-file - the output file to be written after applying the filtering +# +# unifdef2.sh filters a file by including everything outside of ifdef-endif +# brackets, and including only lines inside ifdef-endif brackets with the +# given featureset tag. All other lines are filtered out. +# +# Syntax of ifdef-endif pairs: +# Bracketing lines is accomplished by using "#ifdef " and "#endif " +# lines starting in the first colunm. There must be a single space between +# the ifdef/endif keyword and the tag. The tag can be followed by whitespace +# and then optional commenting text. +# Tags can be made up of alphnumeric and underscore characters, for example, +# "opa10", "opa11_2", etc. +# Examples: +# #ifdef opa10 +# "$where" + echo featureset can only be alphanumeric and underscores + rm -f .greps .greps1 + exit 1 + fi +} + +# shut off globbing +set -f + +if [ $# -ne 3 ] +then + echo ERROR: unifdef2.sh: wrong number of arguments: $# + echo Usage: unifdef2.sh featureset-tag in-file out-file + exit 1 +fi + +featureset=$1 +in_file=$2 +out_file=$3 + +check_tag_syntax $featureset "on command line" + +# check existence of in_file + +if [ ! -f $in_file ] +then + echo ERROR: unifdef2.sh: no such file $in_file + exit 1 +fi + +# check that in_file and out_file are different + +if [ "$in_file" = "$out_file" ] +then + echo ERROR: unifdef2.sh: in-file must be different than out-file + echo Usage: unifdef2.sh featureset-tag in-file out-file + exit 1 +fi + +# parse for syntax - check ifdef and endif tags, ensure matching and no nesting + +# first extract all #ifdef and #endif directives to make it run faster +# ... in the grep, record the line nu㏔ers as well, we will use in main loop below + +grep -n "^#ifdef .*" $in_file > .greps1 +grep -n "^#endif .*" $in_file >> .greps1 +sort -g .greps1 > .greps # sort using line numbers with general-number-sort +rm -f .greps1 + +# check for: +# - mismatched ifdef-endif pairs +# - endif before ifdef +# - nesting + +outside_bracket=1 +save_tag= +while read line +do + if [ $outside_bracket = 1 ] + then + if echo $line | grep "#ifdef " > /dev/null + then + save_tag=$(echo $line | cut -d' ' -f 2 | cut -f1) + check_tag_syntax $save_tag "in $in_file" + outside_bracket=0 + elif echo $line | grep "#endif " > /dev/null + then + save_tag=$(echo $line | cut -d' ' -f 2 | cut -f1) + check_tag_syntax $save_tag "in $in_file" + echo ERROR: unifdef2.sh: endif tag before ifdef for $save_tag in $in_file + exit 1 + fi + else # inside bracket - look for endif for this tag + if echo $line | grep "#endif $save_tag" > /dev/null + then + save_tag= + outside_bracket=1 + elif echo $line | grep "#ifdef " > /dev/null + then + save_tag2=$(echo $line | cut -d' ' -f 2 | cut -f1) + check_tag_syntax $save_tag2 "in $in_file" + echo ERROR: unifdef2.sh: ifdef tag for $save_tag2 before endif for $save_tag in $in_file + exit 1 + elif echo $line | grep "#endif " > /dev/null + then + save_tag2=$(echo $line | cut -d' ' -f 2 | cut -f1) + check_tag_syntax $save_tag2 "in $in_file" + echo ERROR: unifdef2.sh: endif tag for $save_tag2 inside bracket for $save_tag in $in_file + exit 1 + fi + fi +done < .greps +if [ $outside_bracket = 0 ] +then + echo ERROR: unifdef2.sh: no endif for ifdef for $save_tag in $in_file + exit 1 +fi + + +# +# now filter the file to create the out file +# +# Set writing to 1 (write everything except what is inside other ifdefs) +# Set line number to 1 +# +# Loop through lines in in_file: +# read a line +# if the line number matches an ifdef/endif directive +# grab tag and directive from line +# if directive is ifdef +# if tag does not match featureset +# set writing to 0 (filter out this stuff) +# else (directive is endif) +# if tag does not match featureset +# set writing to 1 (start writing again, "filter out" bracket is closed) +# else (not a directive, just a normal line) +# if writing is 1, write line to out_file +# increment line number +# + +> $out_file +chmod --reference=$in_file $out_file # match permissions of in-file + +writing=1 +line_number=1 + +while IFS= read -r line +do + # is line_number in .greps? + if grep -w $line_number .greps > /dev/null + then + ltag=$(grep -w $line_number .greps|cut -f2 -d' '|cut -f1) + ldirective=$(grep -w $line_number .greps | cut -d' ' -f1 | cut -d# -f2) + if [ "$ldirective" = "ifdef" ] + then + if [ "$ltag" != "$featureset" ] + then + writing=0 + fi + else # it is endif + if [ "$ltag" != "$featureset" ] + then + writing=1 + fi + fi + elif [ $writing -eq 1 ] + then + echo "$line" >> $out_file + fi + line_number=$((line_number+1)) +done < $in_file + +rm -f .greps + +exit 0 diff --git a/MakeTools/unpack_comp.sh b/MakeTools/unpack_comp.sh new file mode 100755 index 0000000..2e6b2f6 --- /dev/null +++ b/MakeTools/unpack_comp.sh @@ -0,0 +1,124 @@ +#!/bin/bash +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** +## +## unpack_comp +## ----------- +## copy a component previously downloaded by get_comp to the stage area +## the component is processed based on the files identified by +## the WrappedProducts configuration script. +## +## Usage: +## unpack_comp component bundle downloadsdir tempdir +## Arguments: +## component - one of OFED, TRUESCALE +## bundle - ALL is only supported value for now +## downloadsdir - intermediate local directory +## component files were be downloaded into +## actual directory per component will be of the form: +## downloadsdir/component-bundle +## tempdir - stage sub-directory to copy component to +## Required Environment (as set via setenv or similar tools): +## TL_DIR +## BUILD_PLATFORM_OS_VENDOR_VERSION +## BUILD_TARGET +## BUILD_TARGET_OS_VENDOR +## Additional Environment: +## + +. $ICSBIN/funcs.sh + +Usage() +{ + # include "ERROR" in message so weeklybuild catches it in error log + echo "ERROR: unpack_comp failed" >&2 + echo "Usage: unpack_comp component bundle downloadsdir tempdir" >&2 + exit 2 +} + +if [ $# != 4 ] +then + Usage +fi + +# $1 = Component Product Name +# $2 = Packaging Bundle +component=$1 +bundle=$2 +downloadsdir=$3 +tempdir=$4 + +. $TL_DIR/$PROJ_FILE_DIR/WrappedProducts + +retcode=0 + +localdir=$downloadsdir/$component-$bundle +files=$(cat $localdir/filelist) +dir="" +# 'STAGE COMPONENTS ' keyword looked for by build_relnotes +# put $files outside quotes so shell translates newlines to spaces +echo "STAGE COMPONENTS $component $bundle Files:" $files +for file in $files +do + if [ "$file" != "NONE" ] + then + localfile=$localdir/$(basename $file) + if [ ! -e $localfile ] + then + echo "ERROR - $localfile: Not Found" + retcode=1 + continue + fi + case $localfile in + *.tgz) + dir=$(basename $localfile .tgz) + (cd $tempdir; tar xvfz $localfile) ;; + *) + echo "ERROR: unable to process $component file: $file" + retcode=1 + continue + esac + fi +done + +if [ "$dir" = "" ] +then + echo "Warning: Skipping $component for $bundle: No files" +elif [ $retcode = 0 ] +then + # now process the component by installing or extracting what we need + $TL_DIR/$PROJ_FILE_DIR/extract_comp $component $bundle $tempdir/$dir + if [ $? != 0 ] + then + echo "ERROR: unable to extract $component for $bundle" + retcode=1; + fi +fi + +exit $retcode diff --git a/MakeTools/unpackage.sh b/MakeTools/unpackage.sh new file mode 100644 index 0000000..5682c6e --- /dev/null +++ b/MakeTools/unpackage.sh @@ -0,0 +1,113 @@ +#/bin/sh +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +#[ICS VERSION STRING: unknown] + +#set -x + +if [ -d src ] +then + rm -rf src +fi +mkdir src + +if [ -f cvsignores.tgz ] +then + rm -f cvsignores.tgz +fi + +rm -rf SOURCES/* +rm -rf SPECS/* + +for x in SRPMS/*.src.rpm; +do + SRC_RPM=${x##*/} + PACKAGE_DIR=${SRC_RPM/.src.rpm} + + echo "Installing $SRC_RPM" + + rpm -i --define '_topdir '$PWD'' $x 2> /dev/null + + mkdir src/$PACKAGE_DIR; + + for y in SPECS/*; + do + mv $y src/$PACKAGE_DIR + done + + for y in SOURCES/*; + do + mv $y src/$PACKAGE_DIR + pushd src/$PACKAGE_DIR 1> /dev/null + + for z in *; + do + if [ ${z##*.} == "gz" -o ${z##*.} == "tgz" ] + then + tar xzf $z + else + if [ ${z##*.} == "bz2" ] + then + tar xjf $z + fi + fi + + done + + popd 1> /dev/null + done +done + +find ./src -name .cvsignore | xargs tar -c -z --remove-files -f cvsignores.tgz + +for x in src/*; +do + BASE_DIR="src/ofa_kernel" + if [ ${x:0:${#BASE_DIR}} == $BASE_DIR ] + then + for y in $x/* + do + if [ -d $y ] + then + pushd $y 1> /dev/null + rm -f configure Makefile makefile + cp ofed_scripts/configure . + cp ofed_scripts/Makefile . + cp ofed_scripts/makefile . + pushd drivers/scsi 1> /dev/null + rm Makefile + cp ../../ofed_scripts/iscsi_scsi_makefile Makefile + popd +2 1> /dev/null + break + fi + done + break + fi +done diff --git a/Makerules/DARWIN/PPC.apple.10.3.h b/Makerules/DARWIN/PPC.apple.10.3.h new file mode 100644 index 0000000..c0c6b93 --- /dev/null +++ b/Makerules/DARWIN/PPC.apple.10.3.h @@ -0,0 +1,55 @@ +/* BEGIN_ICS_COPYRIGHT4 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT4 ****************************************/ +// this file has MAC OS specific defines/config settings + +// TBD we may not need these +#define __SMP__ +#define CONFIG_SMP 1 + +#define UTS_RELEASE "10.3" + +// enable /proc simulation +#define CONFIG_PROC_FS 1 + +#define HAS_KALLOC 1 +#define HAS_CPU_NUMBER 1 // For cpu_number() +#define HAS_KERNEL_FUNNEL 1 // For CNetworkInterface +#define HAS_OPAQUE_PROCPTR 0 +#define HAS_KERNEL_SOCKETS 1 // For CNetworkInterface +#define HAS_ENABLE_PREEMPTION 1 +#define HAS_ABSOLUTETIME 1 // All the clock calls in Tiger use uint64 +#define HAS_THREAD_DEADLINE 1 // Has routines like thread_set_timer_deadline()... +#define HAS_NETWORK_LOGGING 1 // Do we use CNetworkInterface +#define HAS_PANTHER_DEBUGGING 1 // Supports CTrace::BackTrace(), CTrace::PointerCheck() +#define HAS_HOSTNAME 1 // For the hostname variable in the kernel +#define HAS_MEMORY_GLOBALS 1 +#define NEEDS_VSNPRINTF_EXTERNED 1 +#define NEEDS_REPORT_LUNS_DEFS 1 +#define HAS_MBUF_FUNCS 0 +#define HAS_IFNET_T 0 diff --git a/Makerules/DARWIN/PPC.apple.10.4.h b/Makerules/DARWIN/PPC.apple.10.4.h new file mode 100644 index 0000000..1241b76 --- /dev/null +++ b/Makerules/DARWIN/PPC.apple.10.4.h @@ -0,0 +1,45 @@ +/* BEGIN_ICS_COPYRIGHT4 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT4 ****************************************/ +// this file has MAC OS specific defines/config settings + +// TBD we may not need these +#define __SMP__ +#define CONFIG_SMP 1 + +#define UTS_RELEASE "10.4" + +// enable /proc simulation +#define CONFIG_PROC_FS 1 + +// Indicate that the kernel has header support for stdio +#define KERNEL_SUPPORTS_STDIO 1 +#define HAS_OPAQUE_PROCPTR 1 +#define HAS_TIGER_TIMER 1 +#define HAS_MBUF_FUNCS 1 +#define HAS_IFNET_T 1 diff --git a/Makerules/DARWIN/README b/Makerules/DARWIN/README new file mode 100644 index 0000000..78f07cb --- /dev/null +++ b/Makerules/DARWIN/README @@ -0,0 +1 @@ +Darwin specific Makerules or -included files diff --git a/Makerules/DARWIN/README-KERNEL-FLAGS b/Makerules/DARWIN/README-KERNEL-FLAGS new file mode 100644 index 0000000..3bf98ac --- /dev/null +++ b/Makerules/DARWIN/README-KERNEL-FLAGS @@ -0,0 +1,31 @@ +The .h files in Makerules/DARWIN/ contain defines that key special case handling +for the various kernels that this source base supports (currently Panther [10.3.x] +and Tiger [10.4.x]). + +When adding new flags please following the following guidelines: + +- Make the sense of the flags positive instead of negative so that old files + don't need to be changed when a new kernel is added to the build +- Make the flag specific to API difference + +Currently the KERNEL_VERSION flag is not used. + +The following flags are currently defined: + +CONFIG_PROC_FS - Enables/Disables the "/proc" implementation under Darwin +HAS_KALLOC - kalloc() is exported for use by the kernel. +HAS_CPU_NUMBER - cpu_number() is exported for use by the kernel. +HAS_KERNEL_FUNNEL - kernel funnel is exported for use by the kernel. +HAS_KERNEL_SOCKETS - kernel sockets are exported for use by the kernel. +HAS_ENABLE_PREEMPTION - preemption values are exported for getting and setting +by the kernel. +HAS_ABSOLUTETIME - enable if clock calls use AbsoluteTime instead of uint64_t +HAS_THREAD_DEADLINE - thread_set_timer_deadline() is exported for use by the kernel. +HAS_NETWORK_LOGGING - indicates whether or not to use the CNetworkInterface class. +This is a temporary measure until the CNetworkInterface class is ported to Tiger. +HAS_PANTHER_DEBUGGING - Supports CTrace::BackTrace(), CTrace::PointerCheck() +HAS_HOSTNAME - kernel exports the _hostname symbol. +HAS_MEMORY_GLOBALS - kernel exports the _mem_actual symbol. +HAS_OPAQUE_PROCPTR - struct proc is an opaque data type, use proc_t instead. +HAS_MBUF_FUNCS - struct mbuf is opaque type, use mbuf_* functions to access +HAS_IFNET_T - struct ifnet replaced with ifnet_t diff --git a/Makerules/Defs.BuildPlatform.CYGWIN b/Makerules/Defs.BuildPlatform.CYGWIN new file mode 100755 index 0000000..6834e21 --- /dev/null +++ b/Makerules/Defs.BuildPlatform.CYGWIN @@ -0,0 +1,57 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** +# Paths to basic tools when BUILD_PLATFORM=CYGWIN +# settings to build embedded products under cygwin - depricated + +BINTOOLS = /bin +TOOLCHAIN_DIR = $(TORNADO_BIN_DIR) + +export PATH = $(ICS_PATH):$(MIPS_PATH):$(CYGWIN_PATH):$(WINDOWS_PATH):$(USR_PATH) + +CAT = $(BINTOOLS)/cat +CHMOD = $(BINTOOLS)/chmod +CP = $(BINTOOLS)/cp +ECHO = $(BINTOOLS)/echo +LEX = $(BINTOOLS)/flex +LNSHLIB = $(MAKETOOLS_DIR)/lnshlib.sh +INSTALL = $(MAKETOOLS_DIR)/installtargets/installtargets +INSTALL_RDONLY_OPT = -r +INSTALL_DIR_OPT = -d +STAGE_INSTALL = $(MAKETOOLS_DIR)/installtargets/installtargets +STAGE_INSTALL_RDONLY_OPT = -r +STAGE_INSTALL_DIR_OPT = -d +MV = $(BINTOOLS)/mv +PERL = $(BINTOOLS)/perl +RM = $(BINTOOLS)/rm +RMFORCE = -f +RMRECURSE = -r +SED = $(BINTOOLS)/sed +TOUCH = $(BINTOOLS)/touch +# force assignment to SHELL so that makefile will use bash for all commands +SHELL := $(BINTOOLS)/bash diff --git a/Makerules/Defs.BuildPlatform.DARWIN b/Makerules/Defs.BuildPlatform.DARWIN new file mode 100755 index 0000000..8d76aa4 --- /dev/null +++ b/Makerules/Defs.BuildPlatform.DARWIN @@ -0,0 +1,62 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** +# Paths to basic tools when BUILD_PLATFORM=DARWIN +# settings to build under darwin + +BINTOOLS = /bin +USRBINTOOLS = /usr/bin +TOOLCHAIN_DIR = /usr/local/bin + +CAT = $(BINTOOLS)/cat +CHMOD = $(BINTOOLS)/chmod +CP = $(BINTOOLS)/cp +ECHO = $(BINTOOLS)/echo +LNSHLIB = $(MAKETOOLS_DIR)/lnshlib.darwin.sh +INSTALL = $(MAKETOOLS_DIR)/ln-install.sh +INSTALL_RDONLY_OPT = +INSTALL_DIR_OPT = +ifeq "$(BUILD_TARGET_OS)" "VXWORKS" +# for vxWorks cross builds we use devtools +STAGE_INSTALL = installtargets +else +# the prefered setting, use tools in source itself +STAGE_INSTALL = $(MAKETOOLS_DIR)/installtargets/installtargets +endif +STAGE_INSTALL_RDONLY_OPT = -r +STAGE_INSTALL_DIR_OPT = -d +LEX = /usr/bin/flex +MV = $(BINTOOLS)/mv +PERL = /usr/bin/perl +RM = $(BINTOOLS)/rm +RMFORCE = -f +RMRECURSE = -r +SED = $(USRBINTOOLS)/sed +TOUCH = $(USRBINTOOLS)/touch +# force assignment to SHELL so that makefile will use bash for all commands +SHELL := $(BINTOOLS)/bash diff --git a/Makerules/Defs.BuildPlatform.DOS b/Makerules/Defs.BuildPlatform.DOS new file mode 100755 index 0000000..4aa79c7 --- /dev/null +++ b/Makerules/Defs.BuildPlatform.DOS @@ -0,0 +1,59 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** +# Paths to basic tools when BUILD_PLATFORM=DOS +# settings to build embedded products under DOS - depricated + +BINTOOLS = /bin +TOOLCHAIN_DIR = $(TORNADO_BIN_DIR) + +ifneq "$(BUILD_TARGET)" "WIN32" +export PATH = $(ICS_PATH):$(MIPS_PATH):$(CYGWIN_PATH):$(WINDOWS_PATH):$(USR_PATH) +endif + +CAT = $(BINTOOLS)/cat +CHMOD = $(BINTOOLS)/chmod +CP = $(BINTOOLS)/cp +ECHO = $(BINTOOLS)/echo +LEX = $(BINTOOLS)/flex +LNSHLIB = $(MAKETOOLS_DIR)/lnshlib.sh +INSTALL = $(MAKETOOLS_DIR)/installtargets/installtargets +INSTALL_RDONLY_OPT = -r +INSTALL_DIR_OPT = -d +STAGE_INSTALL = $(MAKETOOLS_DIR)/installtargets/installtargets +STAGE_INSTALL_RDONLY_OPT = -r +STAGE_INSTALL_DIR_OPT = -d +MV = $(BINTOOLS)/mv +PERL = $(BINTOOLS)/perl +RM = $(BINTOOLS)/rm +RMFORCE = -f +RMRECURSE = -r +SED = $(BINTOOLS)/sed +TOUCH = $(BINTOOLS)/touch +# force assignment to SHELL so that makefile will use bash for all commands +SHELL := $(BINTOOLS)/bash diff --git a/Makerules/Defs.BuildPlatform.LINUX b/Makerules/Defs.BuildPlatform.LINUX new file mode 100755 index 0000000..50fcdba --- /dev/null +++ b/Makerules/Defs.BuildPlatform.LINUX @@ -0,0 +1,69 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** +# Paths to basic tools when BUILD_PLATFORM=LINUX +# settings to build under linux + +BINTOOLS = /bin +ifeq "$(BUILD_TARGET_OS)" "VXWORKS" +ifeq "$(BUILD_TARGET)" "ATOM" +TOOLCHAIN_DIR = $(TL_DIR)/host/wrs/gnu/4.3.3-vxworks-6.9/x86-linux2/bin +else +TOOLCHAIN_DIR = /usr/local/bin +endif +else +TOOLCHAIN_DIR = /usr/local/bin +endif + +CAT = $(BINTOOLS)/cat +CHMOD = $(BINTOOLS)/chmod +CP = $(BINTOOLS)/cp +ECHO = $(BINTOOLS)/echo +LNSHLIB = $(MAKETOOLS_DIR)/lnshlib.sh +INSTALL = $(MAKETOOLS_DIR)/ln-install.sh +INSTALL_RDONLY_OPT = +INSTALL_DIR_OPT = +ifeq "$(BUILD_TARGET_OS)" "VXWORKS" +# for vxWorks cross builds we use devtools +STAGE_INSTALL = installtargets +else +# the prefered setting, use tools in source itself +STAGE_INSTALL = $(MAKETOOLS_DIR)/installtargets/installtargets +endif +STAGE_INSTALL_RDONLY_OPT = -r +STAGE_INSTALL_DIR_OPT = -d +LEX = /usr/bin/flex +MV = $(BINTOOLS)/mv +PERL = /usr/bin/perl +RM = $(BINTOOLS)/rm +RMFORCE = -f +RMRECURSE = -r +SED = $(BINTOOLS)/sed +TOUCH = $(BINTOOLS)/touch +# force assignment to SHELL so that makefile will use bash for all commands +SHELL := $(BINTOOLS)/bash diff --git a/Makerules/Defs.Common b/Makerules/Defs.Common new file mode 100755 index 0000000..d7745c2 --- /dev/null +++ b/Makerules/Defs.Common @@ -0,0 +1,87 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** +# some common settings which are platform independent + +# dependency file "compression" +# ---------------------------- +ifeq "$(BUILD_TARGET_OS)" "VXWORKS" +# for vxWorks cross builds we use devtools +STRIPDEPENDS = stripdepends +else +# the prefered setting, use tools in source itself +STRIPDEPENDS = $(MAKETOOLS_DIR)/stripdepends/stripdepends +endif + +# building Developer Studio workspace/project files. +# ---------------------------- +ifeq "$(BUILD_TARGET_OS)" "VXWORKS" +# for vxWorks cross builds we use devtools +BUILDDSW = builddsw +FINDDSPFILES= finddspfiles +else +# the prefered setting, use tools in source itself +BUILDDSW = $(MAKETOOLS_DIR)/builddsw.sh +FINDDSPFILES= $(MAKETOOLS_DIR)/finddspfiles.sh $(TL_DIR) $(DSP_SUFFIX) +endif + +# Message Table Translator +# ---------------- +BUILDMSGS_PL = $(MAKETOOLS_DIR)/buildmsgs.pl +BUILDMSGS = $(PERL) $(BUILDMSGS_PL) + +# Config File Translator +# ---------------------- +MKCONFIG_PL = $(MAKETOOLS_DIR)/mkconfig.pl +MKCONFIG = $(PERL) $(MKCONFIG_PL) + +# File Preparer +# ------------- +ifeq "$(BUILD_TARGET_OS)" "VXWORKS" +# for vxWorks cross builds we use devtools +PREP = prep +PATCH_VERSION = patch_version +PATCH_ENG_VERSION = $(MAKETOOLS_DIR)/patch_engineer_version.sh +PATCH_BRAND = patch_brand +CONVERT_RELEASETAG = $(MAKETOOLS_DIR)/format_releasetag.sh +else +# the prefered setting, use tools in source itself +PREP = $(MAKETOOLS_DIR)/prep.sh +PATCH_VERSION = $(MAKETOOLS_DIR)/patch_version/patch_version +PATCH_ENG_VERSION = $(MAKETOOLS_DIR)/patch_engineer_version.sh +PATCH_BRAND = $(MAKETOOLS_DIR)/patch_version/patch_brand +CONVERT_RELEASETAG = $(MAKETOOLS_DIR)/format_releasetag.sh +endif + +# CD Generation +# ------------- +MAKEISO = $(MAKETOOLS_DIR)/makeiso.sh + +# Optional Directory selection +# ---------------------------- +OPTIONALDIR = $(MAKETOOLS_DIR)/optionaldir.sh diff --git a/Makerules/Defs.Dsp b/Makerules/Defs.Dsp new file mode 100755 index 0000000..e50b775 --- /dev/null +++ b/Makerules/Defs.Dsp @@ -0,0 +1,44 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** +# Windows Visual Studio DSP stuff +# this is part of the make system ability to create dsp/dsw +# files for Microsoft Visual Studio, hence make is primary tool +# but users who want to use Visual Studio can still use it for edit +# and build, but not so much for execute and debug + +DS_PROJECT = $(notdir $(CURDIR)) +DSP_SUFFIX = _$(BUILD_TARGET).dsp +DSW_SUFFIX = _$(BUILD_TARGET).dsw +DSP_FILE = $(DS_PROJECT)$(DSP_SUFFIX) +DSW_FILE = $(DS_PROJECT)$(DSW_SUFFIX) +DSP_TMP_FILE = $(DS_PROJECT)_tmp$(DSP_SUFFIX) +DSW_TMP_FILE = $(DS_PROJECT)_tmp$(DSW_SUFFIX) +DS_PROJECTS = Makerules MakeTemplates CodeTemplates +DS_PROJECT_DIR = $(CURDIR) +DSP_SRC_DIR = .$(DSP_GROUP) diff --git a/Makerules/Defs.Flags b/Makerules/Defs.Flags new file mode 100755 index 0000000..c4ceb27 --- /dev/null +++ b/Makerules/Defs.Flags @@ -0,0 +1,64 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** +# common flags for compiler/linker/tools + +# Build Command Flags: +# we force all these to empty value here, so that local makefiles +# need not assign them, they can override these as needed +CLOCALDEBUG ?= # Empty by default +CCLOCALDEBUG ?= # Empty by default +CLOCAL ?= # Empty by default +CCLOCAL ?= # Empty by default +BSCLOCAL ?= # Empty by default +DEPENDLOCAL ?= # Empty by default +LOCAL_INCLUDE_DIRS ?= # Empty by default +LDLOCAL ?= # Empty by default +MIDLLOCAL ?= # Empty by default +IMPLIBLOCAL ?= # Empty by default +RSCLOCAL ?= # Empty by default +LOCAL_LIB_DIRS ?= # Empty by default +LOCALLIBS ?= # Empty by default (ie. Use only standard system libraries) +LOCALDEPLIBS ?= # Empty by default (ie. Use only standard system libraries) +LINTLOCAL ?= # Empty by default + + +DEPENDFLAGS = $(CFLAGS) $(DEPENDENV) $(DEPENDPROJ) $(DEPENDMOD) $(DEPENDLOCAL) +CCDEPENDFLAGS = $(CCFLAGS) $(DEPENDENV) $(DEPENDPROJ) $(DEPENDMOD) $(DEPENDLOCAL) + +CINCLUDE_DIRS = $(LOCAL_INCLUDE_DIRS) $(MOD_INCLUDE_DIRS) $(PROJ_INCLUDE_DIRS) $(SYS_INCLUDE_DIRS) +ifndef KERNELRELEASE +CFLAGS = $(CMACH) $(CSYS) $(CENV) $(CENVFS) $(CPROJ) $(CMOD) $(CLOCAL) $(COPT) $(CDEBUG) $(CINCSRCH) +CCFLAGS = $(CCMACH) $(CCSYS) $(CCENV) $(CCENVFS) $(CCPROJ) $(CCMOD) $(CCLOCAL) $(CCOPT) $(CCDEBUG) $(CINCSRCH) + +LDFLAGS = $(LDMACH) $(LDSYS) $(LDENV) $(LDENVFS) $(LDPROJ) $(LDMOD) $(LDLOCAL) $(LDLIBSRCH) $(LDSTRIP) $(LDOUTPUT) +LD_LIB_DIRS = $(LOCAL_LIB_DIRS) $(MOD_LIB_DIRS) $(PROJ_LIB_DIRS) $(SYS_LIB_DIRS) + +LINTFLAGS = $(CMACH) $(CSYS) $(CENV) $(CPROJ) $(CMOD) $(CLOCAL) \ + $(LINTENV) $(LINTPROJ) $(LINTMOD) $(LINTLOCAL) $(CINCSRCH) +endif diff --git a/Makerules/Defs.GNU b/Makerules/Defs.GNU new file mode 100755 index 0000000..6488ec1 --- /dev/null +++ b/Makerules/Defs.GNU @@ -0,0 +1,70 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** +# included by Target.* files, typically only used by those for +# BUILD_TARGET_TOOLCHAIN=GNU +# flags for building with GNU compilers + +# C/C++ compilation +# ---------------------------- +CANSI = -ansi +CPIC = -fPIC +CPIE = +CCPIC = $(CPIC) +CCEXH = -fexceptions +CCNOEXH = -fno-exceptions +CCRTTI = -frtti +CCNORTTI = -fno-rtti +CSHARED = +CCSHARED = +CINCSRCH = $(foreach inc,$(CINCLUDE_DIRS),-I$(inc)) + +# linking +# ---------------------------- +LDSTRIP = +LDOUTPUT = -o$(space) +LDLIBSRCH = $(foreach lib,$(LD_LIB_DIRS),-L$(lib)) +LDSTATIC = -Xlinker -non_shared + +LEX_LIB = fl + +# to assist module makefiles, create ARLIBS listing libraries to include +# in build and be combined into one module level library +ifeq "$(strip $(LIBFILES))" "" +ARLIBS= +else +ARLIBS=$(foreach lib, $(notdir $(LIBFILES)), $(MOD_LIB_DIR)/$(notdir $(LIB_PREFIX)$(lib)$(ARLIB_SUFFIX))) +endif + +__GNUC__ = $(shell touch tmp_dME.c;gcc -dM -E tmp_dME.c|grep -w __GNUC__|cut -d" " -f3;rm -f tmp_dME.c) +__GNUC_MINOR__ = $(shell touch tmp_dME.c;gcc -dM -E tmp_dME.c|grep -w __GNUC_MINOR__|cut -d" " -f3;rm -f tmp_dME.c) +__GNUC_PATCHLEVEL__ = $(shell touch tmp_dME.c;gcc -dM -E tmp_dME.c|grep -w __GNUC_PATCHLEVEL__|cut -d" " -f3;rm -f tmp_dME.c) + +# for now keep these distinct +GCC_MAJOR_VERSION ?= $(shell $(CC) -v 2>&1 | fgrep 'gcc version' | cut -f3 -d' ' | cut -f1 -d'.') +GCC_MINOR_VERSION ?= $(shell $(CC) -v 2>&1 | fgrep 'gcc version' | cut -f3 -d' ' | cut -f2 -d'.') diff --git a/Makerules/Defs.INTEL b/Makerules/Defs.INTEL new file mode 100755 index 0000000..89fdeed --- /dev/null +++ b/Makerules/Defs.INTEL @@ -0,0 +1,62 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** +# included by Target.* files, typically only used by those for +# BUILD_TARGET_TOOLCHAIN=INTEL +# flags for building with Intel compilers + +# C/C++ compilation +# ---------------------------- +CANSI = -ansi +CPIC = -fPIC +CPIE = -fPIE +CCPIC = $(CPIC) +CCEXH = +CCNOEXH = +CCRTTI = +CCNORTTI = +CSHARED = +CCSHARED = +CINCSRCH = $(foreach inc,$(CINCLUDE_DIRS),-I$(inc)) + +# linking +# ---------------------------- +LDSTRIP = +LDOUTPUT = -o$(space) +LDLIBSRCH = $(foreach lib,$(LD_LIB_DIRS),-L$(lib)) +LDSTATIC = -Xlinker -non_shared + +LEX_LIB = fl + +# to assist module makefiles, create ARLIBS listing libraries to include +# in build and be combined into one module level library +ifeq "$(strip $(LIBFILES))" "" +ARLIBS= +else +ARLIBS=$(foreach lib, $(notdir $(LIBFILES)), $(MOD_LIB_DIR)/$(notdir $(LIB_PREFIX)$(lib)$(ARLIB_SUFFIX))) +endif diff --git a/Makerules/Defs.Paths b/Makerules/Defs.Paths new file mode 100755 index 0000000..0ccac49 --- /dev/null +++ b/Makerules/Defs.Paths @@ -0,0 +1,139 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# standard paths within build tree. These are mostly platform +# independent, there are a few if tests below + +# make sure TL_DIR from topmost makefile sticks in lower level makefiles +export TL_DIR + +ifeq "$(filter-out No no NO,$(BUILD_UNIT_TEST))" "" +TEST= +else +TEST=Test +endif # BUILD_UNIT_TEST + +# we use product information in filenames for build outputs so that +# developers can quickly flip between products in a ALL or ALL_EMB checkout +ifeq "$(CARD_TYPE)" "" +# Non-embedded product build +PRODUCT?=$(strip $(notdir $(TL_DIR))) +else +# embedded product build +# override PRODUCT from env and always use CARD_TYPE +PRODUCT=$(strip $(CARD_TYPE)) +endif +export PRODUCT + +# FIXME - this is a hack to override use of BUILDDIR and built* suffixes +# which is used by a few products such as OFED_SOURCE and HostTestCases +ifeq "$(NO_BUILD_SUFFIX)" "y" +BUILT_SUFFIX= +STAGE_SUFFIX= +BUILDDIR=. +BUILDDIR_RM= +else + +ifeq "$(CARD_TYPE)" "" +# Non-embedded product build +BUILT_SUFFIX=.$(PRODUCT).$(BUILD_CONFIG) +STAGE_SUFFIX=$(BUILT_SUFFIX)/$(BUILD_TARGET_OS_VENDOR)/$(BUILD_TARGET) +else +# embedded product build +BUILT_SUFFIX=.$(CARD_TYPE).$(TARGET_BSP).$(BUILD_CONFIG) +STAGE_SUFFIX=$(BUILT_SUFFIX) +endif +# BUILDDIR is guaranteed not to be "". Hence it is always safe +# to use $(BUILDDIR)/ or to cd $(BUILDDIR) +# on some future environments, BUILDDIR may be defined as "." +BUILDDIR=build$(BUILT_SUFFIX) +# BUILDDIR_RM is safe to use in clobber and rm targets. If BUILDDIR is "." +# this will be "" +BUILDDIR_RM=$(BUILDDIR) +endif + + +# Paths: +GLOBAL_DIR = $(TL_DIR) +GLOBAL_BIN_DIR = $(GLOBAL_DIR)/builtbin$(BUILT_SUFFIX) +GLOBAL_INCLUDE_DIR = $(GLOBAL_DIR)/builtinclude$(BUILT_SUFFIX) +GLOBAL_LIB_DIR = $(GLOBAL_DIR)/builtlibs$(BUILT_SUFFIX) +ifeq "$(BUILD_TARGET)" "WIN32" +GLOBAL_SHLIB_DIR = $(GLOBAL_DIR)/builtbin$(BUILT_SUFFIX) +else +GLOBAL_SHLIB_DIR = $(GLOBAL_DIR)/builtlibs$(BUILT_SUFFIX) +endif +GLOBAL_SBR_DIR = $(GLOBAL_DIR)/builtsbr$(BUILT_SUFFIX) + +STAGE_DIR = $(TL_DIR)/stage$(STAGE_SUFFIX) +STAGE_BIN_DIR = $(STAGE_DIR)/bin +STAGE_INCLUDE_DIR = $(STAGE_DIR)/include +STAGE_LIB_DIR = $(STAGE_DIR)/lib +ifeq "$(BUILD_TARGET)" "WIN32" +STAGE_SHLIB_DIR = $(STAGE_DIR)/bin +else +STAGE_SHLIB_DIR = $(STAGE_DIR)/lib +endif +STAGE_SBR_DIR = $(STAGE_DIR)/sbr + +RELEASE_DIR = $(TL_DIR)/release$(STAGE_SUFFIX) +RELEASE_BIN_DIR = $(RELEASE_DIR)/bin +RELEASE_INCLUDE_DIR = $(RELEASE_DIR)/include +RELEASE_LIB_DIR = $(RELEASE_DIR)/lib +ifeq "$(BUILD_TARGET)" "WIN32" +RELEASE_SHLIB_DIR = $(RELEASE_DIR)/bin +else +RELEASE_SHLIB_DIR = $(RELEASE_DIR)/lib +endif +RELEASE_SBR_DIR = $(RELEASE_DIR)/sbr + +TOOLS_DIR = $(subst \,/,$(ICSBIN)) +MAKETOOLS_DIR = $(TL_DIR)/MakeTools + +#COMN_INCLUDE_DIRS = $(GLOBAL_INCLUDE_DIR) $(RELEASE_INCLUDE_DIR) +COMN_INCLUDE_DIRS = $(GLOBAL_INCLUDE_DIR) + +# Paths for installing the results of a build +# if MOD paths are not defined, default to PROJ paths +MOD_BIN_DIR?=$(PROJ_BIN_DIR) +MOD_DRIVER_BIN_DIR?=$(PROJ_DRIVER_BIN_DIR) +MOD_INCLUDE_DIR?=$(PROJ_INCLUDE_DIR) +MOD_LIB_DIR?=$(PROJ_LIB_DIR) +MOD_SHLIB_DIR?=$(PROJ_SHLIB_DIR) +MOD_SBR_DIR?=$(PROJ_SBR_DIR) +# if MOD_STAGE paths are not defined, default to PROJ_STAGE paths +MOD_STAGE_BIN_DIR?=$(PROJ_STAGE_BIN_DIR) +MOD_STAGE_DRIVER_BIN_DIR?=$(PROJ_STAGE_DRIVER_BIN_DIR) +MOD_STAGE_INCLUDE_DIR?=$(PROJ_STAGE_INCLUDE_DIR) +MOD_STAGE_LIB_DIR?=$(PROJ_STAGE_LIB_DIR) +MOD_STAGE_SHLIB_DIR?=$(PROJ_STAGE_SHLIB_DIR) +MOD_STAGE_SBR_DIR?=$(PROJ_STAGE_SBR_DIR) + +#COMN_LIB_DIRS = $(GLOBAL_LIB_DIR) $(RELEASE_LIB_DIR) +COMN_LIB_DIRS = $(GLOBAL_LIB_DIR) diff --git a/Makerules/Defs.Targets b/Makerules/Defs.Targets new file mode 100755 index 0000000..e583dd6 --- /dev/null +++ b/Makerules/Defs.Targets @@ -0,0 +1,42 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** +# Basic Targets to be produced during assorted phases of build + +LIB_TARGETS = $(LIB_TARGETS_IMPLIB) $(LIB_TARGETS_ARLIB) $(LIB_TARGETS_EXP) $(LIB_TARGETS_MISC) +CMD_TARGETS = $(CMD_TARGETS_SHLIB) $(CMD_TARGETS_EXE) $(CMD_TARGETS_MISC) +CLOBBER_TARGETS = $(LIB_TARGETS) $(CMD_TARGETS) $(CLOBBER_TARGETS_MISC) $(BUILDDIR_RM) +DEPLIBS_TARGETS = $(notdir $(foreach lib,$(PROJDEPLIBS) $(MODDEPLIBS) $(LOCALDEPLIBS),$(LIB_PREFIX)$(lib)$(ARLIB_SUFFIX))) + +# definition of preprocessed files for clean +PREPROCESSED_FILES = $(CFILES:.c=$(PRE_SUFFIX)) $(CCFILES:.cpp=$(PRE_SUFFIX)) + +# markers for includes, libs, and bins being built +INC_FILE = .includes$(BUILT_SUFFIX) +LIB_FILE = .libraries$(BUILT_SUFFIX) +BIN_FILE = .binaries$(BUILT_SUFFIX) diff --git a/Makerules/Defs.Tornado b/Makerules/Defs.Tornado new file mode 100755 index 0000000..4b33b70 --- /dev/null +++ b/Makerules/Defs.Tornado @@ -0,0 +1,50 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** +# settings for building with VxWorks Tornado + +TGT_SUBDIR_NAME ?= tmsTarget +TORNADO_HOME = $(TL_DIR)/$(TGT_SUBDIR_NAME) + +ifndef USE_NETF1_IP_STACK +TORNADO_INCLUDE_DIR = $(TORNADO_HOME)/h +SYS_INCLUDE_DIRS = $(TORNADO_INCLUDE_DIR) +else +NETF1_TGT_SUBDIR_NAME ?= netF1Target +NETF1_HOME = $(GLOBAL_INCLUDE_DIR)/$(NETF1_TGT_SUBDIR_NAME) +TORNADO_INCLUDE_DIR = $(NETF1_HOME)/h +SYS_INCLUDE_DIRS = $(TORNADO_INCLUDE_DIR) +SYS_INCLUDE_DIRS += $(NETF1_HOME)/h/arch/mips $(NETF1_HOME)/h/port/vxworks +endif + +TORNADO_LIB_DIR = $(TORNADO_HOME)/lib +TORNADO_BIN_DIR = $(WRS_BIN) +TORNADO_TCL_DIR = $(WRS_BIN) +TORNADO_CPU = R4000 +TORNADO_TOOL = gnu +ELFXSYMS = $(WRS_BIN)/elfXsyms diff --git a/Makerules/Defs.wrs b/Makerules/Defs.wrs new file mode 100755 index 0000000..a3b3bd3 --- /dev/null +++ b/Makerules/Defs.wrs @@ -0,0 +1,49 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** +# settings for building with VxWorks Tornado + +TGT_SUBDIR_NAME ?= target +TORNADO_HOME = $(TL_DIR)/$(TGT_SUBDIR_NAME) + +#no NETF1 with new WRS 6.9.2 +TORNADO_INCLUDE_DIR = $(TORNADO_HOME)/h +SYS_INCLUDE_DIRS = $(TORNADO_INCLUDE_DIR) + +TORNADO_LIB_DIR = $(TORNADO_HOME)/lib +TORNADO_BIN_DIR = $(WRS_BIN) +TORNADO_TCL_DIR = $(WRS_BIN) +TORNADO_CPU = ATOM +TORNADO_TOOL = gnu +ELFXSYMS = $(WRS_BIN)/elfXsyms + +# export this so target/h/make/defs.default picks it up for -DCPU=_VX_ATOM +# because during target/tmsTarget/src builds, CPU is not a simple processor +# name but includes product name, build type(debug), etc. +export TORNADO_CPU + diff --git a/Makerules/Makefile b/Makerules/Makefile new file mode 100644 index 0000000..9d736ae --- /dev/null +++ b/Makerules/Makefile @@ -0,0 +1,90 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** +# Makefile for Makerules, just to create a dsp file + +# Include Make Control Settings +include $(TL_DIR)/$(PROJ_FILE_DIR)/Makesettings.project + +DS_SUBPROJECTS = +DSP_SOURCES= Defs.BuildPlatform.CYGWIN \ + Defs.BuildPlatform.DOS \ + Defs.BuildPlatform.LINUX \ + Defs.BuildPlatform.DARWIN \ + Defs.Common \ + Defs.Dsp \ + Defs.Flags \ + Defs.GNU \ + Defs.Paths \ + Defs.Targets \ + Defs.Tornado \ + Defs.Wrs \ + Makefile \ + Makerules.global \ + Maketargets.bsp \ + Maketargets.build \ + Maketargets.install \ + Maketargets.moduleinstall \ + Maketargets.modulestage \ + Maketargets.runtest \ + Maketargets.stage \ + Maketargets.tms \ + Maketargets.toplevel \ + README \ + Rules.Common \ + Rules.CYGWIN \ + Rules.DOS \ + Rules.LINUX \ + Rules.DARWIN \ + Target.CYGWIN.GNU.CYGWIN \ + Target.LINUX.GNU.EM64T \ + Target.LINUX.GNU.IA32 \ + Target.LINUX.GNU.IA64 \ + Target.LINUX.GNU.MIPS64 \ + Target.LINUX.GNU.X86_64 \ + Target.LINUX.INTEL.IA32 \ + Target.LINUX.INTEL.IA64 \ + Target.DARWIN.GNU.PPC \ + Target.VXWORKS.GNU.ATOM \ + Target.VXWORKS.GNU.I386 \ + Target.VXWORKS.GNU.MIPS \ + Target.VXWORKS.GNU.MIPS64 \ + Target.WIN32.WIN32.WIN32 \ + template.dsp + +DIRS = + +INCLUDE_TARGETS = + +include $(TL_DIR)/$(PROJ_FILE_DIR)/Makerules.project + +include $(TL_DIR)/Makerules/Maketargets.toplevel + +INSTALL:: + +STAGE:: diff --git a/Makerules/Makerules.global b/Makerules/Makerules.global new file mode 100755 index 0000000..f85cde6 --- /dev/null +++ b/Makerules/Makerules.global @@ -0,0 +1,59 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** +# primary makerules file, includes appropriate settings based on build env + +# for more information about the variables and operation of Makerules.global +# see README + +# a little trick to get a variable which has 1 space, so we can define +# other variables with intentional trailing whitespace +empty= +space= $(empty) $(empty) + +# Make Control Variables +AUTODEP?=yes +BUILD_CONFIG?=debug +BUILD_TMS?=yes +EVAL_HARDWARE?=no +MAKEFILE= Makefile +SUBSYSTEM?= console +USEMFC?=none + +VS?= + +include $(TL_DIR)/Makerules/Defs.Paths +include $(TL_DIR)/Makerules/Defs.Flags +include $(TL_DIR)/Makerules/Defs.BuildPlatform.$(BUILD_PLATFORM) +include $(TL_DIR)/Makerules/Defs.Targets +include $(TL_DIR)/Makerules/Defs.Common +include $(TL_DIR)/Makerules/Defs.Dsp +include $(TL_DIR)/Makerules/Target.$(BUILD_TARGET_OS).$(BUILD_TARGET_TOOLCHAIN).$(BUILD_TARGET) +ifndef KERNELRELEASE +include $(TL_DIR)/Makerules/Rules.Common +endif diff --git a/Makerules/Makesettings.global b/Makerules/Makesettings.global new file mode 100755 index 0000000..993d0c4 --- /dev/null +++ b/Makerules/Makesettings.global @@ -0,0 +1,37 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** +# primary makesettings file, makes appropriate settings based on build env + +# for more information about the variables and operation of Makesettings.global +# see README + +# +# This should always be set +# +.DELETE_ON_ERROR: diff --git a/Makerules/Maketargets.bsp b/Makerules/Maketargets.bsp new file mode 100755 index 0000000..e7b93d8 --- /dev/null +++ b/Makerules/Maketargets.bsp @@ -0,0 +1,230 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** +#=============================================================================# +# Rules: +#-----------------------------------------------------------------------------# +# These rules build a Embedded Firmware image + +PRODUCT_HOME=$(TL_DIR)/$(notdir $(PRODUCT_DIR)) + +ifdef TARGET_BSP +# the start-group and end-group options cause the linker to loop through +# all the libraries within the given group and resolve symbols until it can do +# no more. This avoids the need to have libraries in a specific order on the +# linker line. It also nicely handles co-dependent libraries + +# BSP's are built with an older version of Cygwin. It requires Windows style +# paths for the libraries +ifeq "$(strip $(EXECUTABLE))" "" +BSP_TARGETS= +else +BSP_TARGETS= $(EXECUTABLE) $(EXECUTABLE).map $(EXECUTABLE).map2 +endif + +ifeq "$(strip $(BOOTEXE))" "" +BOOTEXE= $(EXECUTABLE) +endif + +# default the BSP target if not specified in the Firmware Makefile +ifeq (,$(BSP_MAKE_TARGET)) +BSP_MAKE_TARGET=vxWorks +endif + +# determine whether or not the build will include a .sym file +ifeq (vxWorks,$(BSP_MAKE_TARGET)) +BSP_TARGETS += $(EXECUTABLE).sym +endif + +# DEMOHACK - get FCIOU sb1250 bsp to work +ifeq (FCIOU,$(PRODUCT)) +ifeq (vxWorks.st,$(BSP_MAKE_TARGET)) +BSP_TARGETS += $(EXECUTABLE).sym +endif +endif + +# add the list of output files to our list +CMD_TARGETS_MISC += $(BSP_TARGETS) + +CT_OBJECTS = $(foreach obj,$(OBJECTS),$(BUILDDIR)/$(obj)) +OBJS = $(CT_OBJECTS) +TMP_O = $(BUILDDIR)/tmp.o + +include $(TL_DIR)/Makerules/Maketargets.product + +ifneq "$(PRODUCT_ALIAS)" "" +BSP_OPTIONS += PRODUCT_ALIAS=$(PRODUCT_ALIAS) +endif + +$(BSP_TARGETS): $(OBJS) $(DEPLIBS_TARGETS) + echo "$(BSP_TARGETS)" + echo "$(OBJS)" + cd $(TL_DIR)/BSP/$(TARGET_BSP); \ + echo "$(DEPLIBS_TARGETS)"; \ + ICS_DEFINES=" $(PRODUCT_DEFINES) $(BSP_DEFINES) " \ + ICS_LIBS="$(foreach obj,$(OBJS),$(TL_DIR)/$(PROJ_FILE_DIR)/Firmware/$(obj)) $(foreach lib,$(DEPLIBS_TARGETS),$(PROJ_LIB_DIR)/$(lib))" BUILD_ESM=$(BUILD_ESM) make $(BSP_MAKE_TARGET) $(BSP_OPTIONS); + $(NM) --numeric-sort $(TL_DIR)/BSP/$(TARGET_BSP)/$(BSP_MAKE_TARGET) > $(EXECUTABLE).map2 + $(NM) --size-sort $(TL_DIR)/BSP/$(TARGET_BSP)/$(BSP_MAKE_TARGET) > $(EXECUTABLE).map3 + $(CP) $(TL_DIR)/BSP/$(TARGET_BSP)/$(BSP_MAKE_TARGET) $(EXECUTABLE) + $(CP) $(TL_DIR)/BSP/$(TARGET_BSP)/$(BSP_MAKE_TARGET).map $(EXECUTABLE).map +ifeq "$(RELEASE_TAG)" "" + $(PATCH_ENG_VERSION) $(EXECUTABLE) +else + $(PATCH_VERSION) -n `$(CONVERT_RELEASETAG) $(RELEASE_TAG)` $(RELEASE_TAG) $(EXECUTABLE) +endif + $(PATCH_BRAND) "$(BUILD_BRAND)" $(EXECUTABLE) + +# DEMOHACK - get FCIOU sb1250 bsp to work +ifeq (FCIOU,$(PRODUCT)) +ifeq (vxWorks.st,$(BSP_MAKE_TARGET)) + $(ELFXSYMS) < $(TL_DIR)/BSP/$(TARGET_BSP)/$(BSP_MAKE_TARGET) > $(TL_DIR)/BSP/$(TARGET_BSP)/vxWorks.sym + $(CP) $(TL_DIR)/BSP/$(TARGET_BSP)/vxWorks.sym $(EXECUTABLE).sym + $(CP) $(TL_DIR)/BSP/$(TARGET_BSP)/$(BSP_MAKE_TARGET) $(TL_DIR)/BSP/$(TARGET_BSP)/vxWorks +endif +endif +ifeq (vxWorks,$(BSP_MAKE_TARGET)) + $(CP) $(TL_DIR)/BSP/$(TARGET_BSP)/$(BSP_MAKE_TARGET).sym $(EXECUTABLE).sym +endif + +CLEAN:: + cd $(TL_DIR)/BSP/$(TARGET_BSP); \ + PATH="$(MIPS_PATH):$(PATH)" BUILD_ESM=$(BUILD_ESM) make clean SSP_NAME=$(PROJECT_SSP); \ + $(RM) $(RMFORCE) -- --start-group --end-group -Xlinker + $(RM) $(RMFORCE) $(BSP_TARGETS) + +safenoclobber: +ifeq "$(BUILD_TARGET)" "ATOM" + $(MAKE) NO_SSP=1 BUILD_SAFEBOOT=yes DEBUG_CODE="" ADVBOOT +endif + +safeboot advboot: $(TL_DIR)/Fd/buildFeatureDefs +# don't checked NETF1 stuff for atom safe boot +ifeq "$(BUILD_TARGET)" "ATOM" + cd $(PRODUCT_HOME) && make clobber; + cd $(PRODUCT_HOME) && make NO_NETF1_IP_STACK=TRUE includes; + cd $(PRODUCT_HOME) && make BUILD_SAFEBOOT=yes NO_NETF1_IP_STACK=TRUE libs; + echo "here atom" $(OBJECTS) " " $(DEPLIBS_TARGETS) + $(MAKE) NO_SSP=1 BUILD_SAFEBOOT=yes DEBUG_CODE="" ADVBOOT +else +ifneq (,$(USE_NETF1_IP_STACK)) +ifeq "$(PRESERVE_BOOT_OBJECTS)" "" + cd $(PRODUCT_HOME) && make clobber; \ + cd $(PRODUCT_HOME) && make NO_NETF1_IP_STACK=TRUE includes; \ + cd $(PRODUCT_HOME) && make BUILD_SAFEBOOT=yes NO_NETF1_IP_STACK=TRUE libs +endif +endif + $(MAKE) NO_SSP=1 BUILD_SAFEBOOT=yes DEBUG_CODE="" ADVBOOT +endif + +ifeq "$(LAMINATE)" "" +LAM_SUFFIX= +else +LAM_SUFFIX=.$(LAMINATE) +endif +ADVBOOT: $(OBJECTS) $(DEPLIBS_TARGETS) + echo "OBJECTS is $(OBJECTS)" + echo "DEPLIBS is $(DEPLIBS_TARGETS)" + cd $(TL_DIR)/BSP/$(TARGET_BSP); \ + echo "$(DEPLIBS_TARGETS)"; \ + ICS_DEFINES=" $(PRODUCT_DEFINES) $(BSP_DEFINES) " \ + ICS_LIBS="$(foreach lib,$(DEPLIBS_TARGETS),$(PROJ_LIB_DIR)/$(lib))" make bootrom.img $(BSP_OPTIONS); +ifneq "$(BUILDDIR)" "" + @ if [ ! -d $(BUILDDIR) ]; then \ + mkdir $(BUILDDIR); \ + fi +endif + $(NM) --numeric-sort $(TL_DIR)/BSP/$(TARGET_BSP)/$(TMP_O) > $(BOOTEXE)$(LAM_SUFFIX).img.map + $(CP) $(TL_DIR)/BSP/$(TARGET_BSP)/$(BUILDDIR)/bootrom.img $(BOOTEXE)$(LAM_SUFFIX).img +ifeq "$(CARD_TYPE)" "" + cd $(BUILDDIR);mkbootpkg $(notdir $(BOOTEXE)$(LAM_SUFFIX).img) $(PROJECT_PACKAGE_EXTERNAL_NAME) $(PRODUCT_CODE) $(BSP_CODE) $(TL_DIR)/BSP/$(TARGET_BSP)/$(BUILDDIR) +else + +ifeq "$(BUILD_TARGET)" "MIPS" + cd $(BUILDDIR);mkbootpkg $(notdir $(BOOTEXE)$(LAM_SUFFIX).img) $(CARD_TYPE) $(PRODUCT_CODE) $(BSP_CODE) $(TL_DIR)/BSP/$(TARGET_BSP)/$(BUILDDIR) +else +ifeq "$(BUILD_TARGET)" "ATOM" + $(CP) $(TL_DIR)/BSP/$(TARGET_BSP)/$(BUILDDIR)/bootrom.img $(BOOTEXE)$(LAM_SUFFIX).bootapp + $(CP) $(TL_DIR)/BSP/$(TARGET_BSP)/$(BUILDDIR)/vxStage1Boot.bin $(BOOTEXE)$(LAM_SUFFIX).bootrom + cd $(BUILDDIR);mkbootpkg $(notdir $(BOOTEXE)$(LAM_SUFFIX).img) $(CARD_TYPE) $(PRODUCT_CODE) $(BSP_CODE) $(TL_DIR)/BSP/$(TARGET_BSP)/$(BUILDDIR) +else + cd $(BUILDDIR);mkbootpkg $(notdir $(BOOTEXE)$(LAM_SUFFIX).img) $(PROJECT_PACKAGE_EXTERNAL_NAME) $(PRODUCT_CODE) $(BSP_CODE) $(TL_DIR)/BSP/$(TARGET_BSP)/$(BUILDDIR) +endif +endif +endif + + +# The package target only works in the Firmware directory. + +ifneq "$(strip $(EXECUTABLE))" "" +ifeq "$(CARD_TYPE)" "" +ICS_PACKAGE = $(BUILDDIR)/$(PROJECT_PACKAGE_EXTERNAL_NAME).$(TARGET_BSP).pkg +else +ifeq "$(BUILD_TARGET)" "MIPS" +ICS_PACKAGE = $(BUILDDIR)/$(CARD_TYPE).$(TARGET_BSP).pkg +else +ifeq "$(BUILD_TARGET)" "ATOM" +ifeq "$(DEBUG_SIGN)" "no" +ICS_PACKAGE = $(BUILDDIR)/$(CARD_TYPE).$(TARGET_BSP).pkg +else +ICS_PACKAGE = $(BUILDDIR)/$(CARD_TYPE).$(TARGET_BSP).spkg +endif +else +ICS_PACKAGE = $(BUILDDIR)/$(PROJECT_PACKAGE_EXTERNAL_NAME).$(TARGET_BSP).pkg +endif +endif +endif +CMD_TARGETS_MISC += $(ICS_PACKAGE) +$(ICS_PACKAGE): icspkg + +package: $(EXECUTABLE) + echo "The package target only works in the Firmware directory." + $(CP) $(EXECUTABLE) $(EXECUTABLE).stripped + $(STRIP) -S $(EXECUTABLE).stripped + $(DEFLATE) < $(EXECUTABLE).stripped > $(EXECUTABLE).Z + +icspkg: $(EXECUTABLE) + echo "The icspkg target only works in the Firmware directory." +ifeq "$(CARD_TYPE)" "" + mkpkg $(EXECUTABLE) $(PROJECT_PACKAGE_EXTERNAL_NAME) $(TARGET_BSP) $(PRODUCT_CODE) $(BSP_CODE) $(STRIP) $(DEFLATE) +else +ifeq "$(BUILD_TARGET)" "MIPS" + mkpkg $(EXECUTABLE) $(CARD_TYPE) $(TARGET_BSP) $(PRODUCT_CODE) $(BSP_CODE) $(STRIP) $(DEFLATE) +else +ifeq "$(BUILD_TARGET)" "ATOM" + mkpkg $(EXECUTABLE) $(CARD_TYPE) $(TARGET_BSP) $(PRODUCT_CODE) $(BSP_CODE) $(STRIP) $(DEFLATE) +else + mkpkg $(EXECUTABLE) $(PROJECT_PACKAGE_EXTERNAL_NAME) $(TARGET_BSP) $(PRODUCT_CODE) $(BSP_CODE) $(STRIP) $(DEFLATE) +endif +endif +endif + +endif # EXECUTABLE + +endif # TARGET_BSP + + diff --git a/Makerules/Maketargets.build b/Makerules/Maketargets.build new file mode 100755 index 0000000..ebf9fdf --- /dev/null +++ b/Makerules/Maketargets.build @@ -0,0 +1,166 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** +#=============================================================================# +# Rules: +#-----------------------------------------------------------------------------# +# These rules perform the standard build steps + +ifneq "$(strip $(IDL_TARGETS))" "" +# Windows IDL files +# FIXME: BUILDDIR path prefix for target +$(IDL_TARGETS): $(IDLFILE) + @echo Compiling IDL files... + @mkdir -p $(dir $@) + $(VS)$(MIDL) $(MIDLFLAGS) /h $(^:.idl=.h) /iid $(^:.idl=_i.c) /tlb $(^:.idl=.tlb) /dlldata $(^:.idl=_dlldata.c) /proxy $(^:.idl=_p.c) $^ +endif + +ifneq "$(strip $(LIB_TARGETS_IMPLIB))" "" +# Windows import library files for DLLs +# FIXME: BUILDDIR path prefix for target +$(LIB_TARGETS_IMPLIB): $(ARLIBS) $(OBJECTS) $(RSCOBJECTS) + @echo Creating import library files... + @mkdir -p $(dir $@) + $(VS)$(MKIMPLIB)$@ $^ +endif + +ifneq "$(strip $(LIB_TARGETS_ARLIB))" "" +# archive/static library +# BUILDDIR is in LIB_PREFIX and hence in LIB_TARGETS_ARLIB +CT_OBJECTS = $(foreach f,$(OBJECTS),$(BUILDDIR)/$(f)) +$(LIB_TARGETS_ARLIB): $(ARLIBS) $(CT_OBJECTS) $(RSCOBJECTS) + @mkdir -p $(dir $@) + @echo Creating static library file... + @echo $(PWD) + $(VS)$(MKARLIB)$@ $^ +endif + +ifneq "$(strip $(LIB_TARGETS_EXP))" "" +# windows export file for DLLs +$(LIB_TARGETS_EXP): TBD +endif + +ifneq "$(strip $(CMD_TARGETS_SHLIB))" "" +# shared library/DLL +# BUILDDIR is in LIB_PREFIX and hence in CMD_TARGETS_SHLIB +CT_OBJECTS = $(foreach f,$(OBJECTS),$(BUILDDIR)/$(f)) +# don't use $^, would have deplibs explicit on line +$(CMD_TARGETS_SHLIB): $(ARLIBS) $(CT_OBJECTS) $(EXP_TARGET) $(RSCOBJECTS) $(DEPLIBS_TARGETS) + @echo Linking dynamic library... + @mkdir -p $(dir $@) +ifeq "$(BUILD_TARGET_OS)" "DARWIN" + $(VS)$(MKSHLIB) $(LDFLAGS)$@ -install_name $(SHLIB_SONAME) $(ARLIBS) $(CT_OBJECTS) $(LDLIBS) +else +ifneq "$(strip $(SHLIB_SONAME))" "" + $(VS)$(MKSHLIB) $(LDFLAGS)$@ -Xlinker -soname -Xlinker $(SHLIB_SONAME) $(ARLIBS) $(CT_OBJECTS) $(EXP_TARGET) $(RSCOBJECTS) $(LDLIBS) +else + $(VS)$(MKSHLIB) $(LDFLAGS)$@ $(ARLIBS) $(CT_OBJECTS) $(EXP_TARGET) $(RSCOBJECTS) $(LDLIBS) +endif +endif +endif + +ifneq "$(strip $(LIB_BSC_TARGET)$(CMD_BSC_TARGET))" "" +# windows browse file builder +# FIXME: BUILDDIR path prefix for target +$(LIB_BSC_TARGET) $(CMD_BSC_TARGET) : $(OBJECTS) + @echo Creating browse info file... + @mkdir -p $(dir $@) + $(VS)$(BSC) $(BSCFLAGS)$@ $(OBJECTS:.obj=.sbr) +endif + +## Rules for building executables and images (.out files for VXWORKS) + +#ifneq "$(strip $(CMD_TARGETS_EXE))" "" +# This is a much simpler version, which could be used +# if the mips munch code were scripted or simplified +# don't use $^, would have deplibs explicit on line +#CT_OBJECTS = $(foreach f,$(OBJECTS),$(BUILDDIR)/$(f)) +#$(CMD_TARGETS_EXE): $(CT_OBJECTS) $(RSCOBJECTS) $(DEPLIBS_TARGETS) +# @echo Linking executable... +# @mkdir -p $(dir $@) +# $(VS)$(LD) $(LDFLAGS)$@ $(CT_OBJECTS) $(RSCOBJECTS) $(LDLIBS) +#endif +ifneq "$(strip $(CMD_TARGETS_EXE))" "" +# user applications/commands build +CT_OBJECTS = $(foreach f,$(OBJECTS),$(BUILDDIR)/$(f)) +ifeq "$(BUILD_TARGET_OS)" "VXWORKS" + +$(CMD_TARGETS_EXE) : $(BUILDDIR)/$(CMD_TARGETS_EXE) +$(BUILDDIR)/$(CMD_TARGETS_EXE) : $(CT_OBJECTS) $(RSCOBJECTS) $(DEPLIBS_TARGETS) +# @echo Linking executable... +# $(VS)$(LD) $(LDFLAGS)$@ $(OBJECTS) $(RSCOBJECTS) $(LDLIBS) + @echo Linking builddir executable... + echo $(CT_OBJECTS) + $(VS)$(CC) $(LDFLAGS) partialImage.o -Wl,$(CT_OBJECTS) $(RSCOBJECTS) $(LDLIBS) + $(VS)$(NM) -g partialImage.o | wtxtcl $(TORNADO_TCL_DIR)/munch.tcl -asm mips > ctdt.c + $(VS)$(CC) $(CFLAGS) -c ctdt.c -o ctdt.o + $(VS)$(CC) $(LDMACH) partialImage.o ctdt.o -o $@ + $(RM) $(RMFORCE) partialImage.o ctdt.c ctdt.o + +else # BUILD_TARGET_OS is not VXWORKS +# In Makefiles CMD_TARGETS_EXE must have BUILDDIR prefixing it +$(CMD_TARGETS_EXE) : $(CT_OBJECTS) $(RSCOBJECTS) $(DEPLIBS_TARGETS) + @echo Linking executable... + @mkdir -p $(dir $@) + $(VS)$(CC) $(LDFLAGS)$@ $(CT_OBJECTS) $(LDLIBS) +endif # BUILD_TARGET_OS is VXWORKS +endif # CMD_TARGETS_EXE non-null + +ifneq "$(BUILD_26)" "1" +ifneq "$(strip $(CMD_TARGETS_DRIVER))" "" +# kernel driver builds +CT_OBJECTS = $(foreach f,$(OBJECTS),$(BUILDDIR)/$(f)) +ifeq "$(BUILD_TARGET_OS)" "LINUX" +$(CMD_TARGETS_DRIVER): $(CT_OBJECTS) $(ARLIBS) $(DEPLIBS_TARGETS) + @echo Linking Kernel Module... + @mkdir -p $(dir $@) + $(VS)$(MKMODULE) $@ $(CT_OBJECTS) $(ARLIBS) +endif +ifeq "$(BUILD_TARGET_OS)" "DARWIN" +$(CMD_TARGETS_DRIVER): $(CT_OBJECTS) $(ARLIBS) $(DEPLIBS_TARGETS) + @echo Linking Kernel Module... + @mkdir -p $(dir $@) + $(VS)$(MKMODULE) $@ $(CT_OBJECTS) $(KERNELOPTS) $(ARLIBS) +endif +endif +endif + +ifneq "$(strip $(CMD_TARGETS_KEXT))" "" +# Darwin kernel extension packaging +ifeq "$(BUILD_TARGET_OS)" "DARWIN" +$(CMD_TARGETS_KEXT) $(CMD_TARGETS_KEXT)/Contents/Info.plist $(CMD_TARGETS_KEXT)/Contents/MacOS/$(CMD_TARGETS_DRIVER) $(CMD_TARGETS_KEXT)/Contents/Resources/English.lproj: $(CMD_TARGETS_DRIVER) IOKit/Info.plist IOKit/English.lproj/InfoPlist.strings + echo Packaging $(CMD_TARGETS_KEXT) + mkdir -p $(CMD_TARGETS_KEXT)/Contents + mkdir -p $(CMD_TARGETS_KEXT)/Contents/MacOS + mkdir -p $(CMD_TARGETS_KEXT)/Contents/Resources/English.lproj + ${PBXCP} -exclude .DS_Store -exclude CVS -resolve-src-symlinks IOKit/Info.plist $(CMD_TARGETS_KEXT)/Contents + cp $(CMD_TARGETS_DRIVER) $(CMD_TARGETS_KEXT)/Contents/MacOS/ + ${PBXCP} -exclude .DS_Store -exclude CVS -resolve-src-symlinks IOKit/English.lproj/InfoPlist.strings $(CMD_TARGETS_KEXT)/Contents/Resources/English.lproj + touch $(CMD_TARGETS_KEXT) +endif +endif diff --git a/Makerules/Maketargets.install b/Makerules/Maketargets.install new file mode 100755 index 0000000..65f3412 --- /dev/null +++ b/Makerules/Maketargets.install @@ -0,0 +1,83 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** +#=============================================================================# +# Rules: +#-----------------------------------------------------------------------------# +# These rules perform the standard install steps + +INCLUDES:: $(INC_FILE) +LIBS:: $(LIB_FILE) +CMDS:: $(BIN_FILE) + +# changes to Makefile will force re-install +$(INC_FILE): $(INCLUDE_TARGETS) $(IDL_HEADERS) $(IDLFILE) $(MAKEFILE) + $(VS)$(INSTALL) $(INSTALL_RDONLY_OPT) $(INSTALL_DIR_OPT) $(MOD_INCLUDE_DIR)/$(MOD_INCLUDE_SUBDIR)/$(INCLUDE_SUBDIR) $(INCLUDE_TARGETS) $(IDL_HEADERS) $(IDLFILE) + $(VS)echo done > $(INC_FILE) + +$(LIB_FILE): $(LIB_TARGETS) $(LIB_MISC_TARGETS) +ifneq "$(strip $(LIB_TARGETS)$(LIB_MISC_TARGETS))" "" + $(VS)$(INSTALL) $(INSTALL_RDONLY_OPT) $(INSTALL_DIR_OPT) $(MOD_LIB_DIR) $(LIB_TARGETS) $(LIB_MISC_TARGETS) +endif + $(VS)echo done > $(LIB_FILE) + +$(BIN_FILE): $(CMD_TARGETS) $(CMD_TARGETS_MISC) $(MISC_FILES) +ifneq "$(strip $(CMD_TARGETS_EXE)$(CMD_TARGETS_MISC)$(MISC_FILES))" "" + $(VS)$(INSTALL) $(INSTALL_RDONLY_OPT) $(INSTALL_DIR_OPT) $(MOD_BIN_DIR)/$(MOD_BIN_SUBDIR)/$(BIN_SUBDIR) $(CMD_TARGETS_EXE) $(CMD_TARGETS_MISC) $(MISC_FILES) +endif +ifneq "$(strip $(CMD_TARGETS_DRIVER))" "" +ifeq "$(BUILD_TARGET_OS)" "LINUX" + $(VS)$(INSTALL) $(INSTALL_RDONLY_OPT) $(INSTALL_DIR_OPT) $(MOD_DRIVER_BIN_DIR)/$(MOD_DRIVER_BIN_SUBDIR)/$(DRIVER_BIN_SUBDIR) $(CMD_TARGETS_DRIVER) +endif +ifeq "$(BUILD_TARGET_OS)" "DARWIN" + $(VS)$(INSTALL) $(INSTALL_RDONLY_OPT) $(INSTALL_DIR_OPT) $(MOD_DRIVER_BIN_DIR)/$(MOD_DRIVER_BIN_SUBDIR)/$(DRIVER_BIN_SUBDIR) $(CMD_TARGETS_DRIVER) +endif +endif +ifneq "$(strip $(CMD_TARGETS_KEXT))" "" +ifeq "$(BUILD_TARGET_OS)" "DARWIN" + $(VS)$(INSTALL) $(INSTALL_RDONLY_OPT) $(INSTALL_DIR_OPT) $(MOD_DRIVER_BIN_DIR)/$(MOD_DRIVER_BIN_SUBDIR)/$(DRIVER_BIN_SUBDIR)/$(CMD_TARGETS_KEXT)/Contents $(CMD_TARGETS_KEXT)/Contents/Info.plist + $(VS)$(INSTALL) $(INSTALL_RDONLY_OPT) $(INSTALL_DIR_OPT) $(MOD_DRIVER_BIN_DIR)/$(MOD_DRIVER_BIN_SUBDIR)/$(DRIVER_BIN_SUBDIR)/$(CMD_TARGETS_KEXT)/Contents/MacOS $(CMD_TARGETS_KEXT)/Contents/MacOS/$(CMD_TARGETS_DRIVER) + $(VS)$(INSTALL) $(INSTALL_RDONLY_OPT) $(INSTALL_DIR_OPT) $(MOD_DRIVER_BIN_DIR)/$(MOD_DRIVER_BIN_SUBDIR)/$(DRIVER_BIN_SUBDIR)/$(CMD_TARGETS_KEXT)/Contents/Resources/English.lproj $(CMD_TARGETS_KEXT)/Contents/Resources/English.lproj/InfoPlist.strings +endif +endif +ifneq "$(strip $(CMD_TARGETS_SHLIB))" "" + $(VS)$(INSTALL) $(INSTALL_RDONLY_OPT) $(INSTALL_DIR_OPT) $(MOD_SHLIB_DIR) $(CMD_TARGETS_SHLIB) + $(VS)$(LNSHLIB) $(MOD_SHLIB_DIR) $(CMD_TARGETS_SHLIB) +endif +ifneq "$(strip $(CMD_TARGETS_PDB))" "" + $(VS)$(INSTALL) $(INSTALL_RDONLY_OPT) $(INSTALL_DIR_OPT) $(MOD_BIN_DIR)/$(MOD_BIN_SUBDIR)/$(BIN_SUBDIR) $(CMD_TARGETS_PDB) +endif +ifeq "$$(BUILD_TARGET_OS)" "WIN32" +ifneq "$(strip $(OBJECTS))" "" + $(VS)$(INSTALL) $(INSTALL_RDONLY_OPT) $(INSTALL_DIR_OPT) $(MOD_SBR_DIR) $(OBJECTS:$(OBJ_SUFFIX)=.sbr) +endif +endif + $(VS)echo done > $(BIN_FILE) + +# actual installation is handled in individual builds +INSTALL:: diff --git a/Makerules/Maketargets.moduleinstall b/Makerules/Maketargets.moduleinstall new file mode 100755 index 0000000..52aa437 --- /dev/null +++ b/Makerules/Maketargets.moduleinstall @@ -0,0 +1,82 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** +#=============================================================================# +# Rules: +#-----------------------------------------------------------------------------# +# These rules perform the standard module toplevel directory install steps + +INCLUDES:: $(INC_FILE) +LIBS:: $(LIB_FILE) +CMDS:: $(BIN_FILE) + +# changes to Makefile will force re-install +$(INC_FILE):: $(INCLUDE_TARGETS) $(IDL_HEADERS) $(IDLFILE) $(MAKEFILE) +ifneq "$(strip $(INCLUDE_TARGETS))" "" + $(VS)$(INSTALL) $(INSTALL_RDONLY_OPT) $(INSTALL_DIR_OPT) $(PROJ_INCLUDE_DIR)/$(MOD_INCLUDE_SUBDIR)/$(INCLUDE_SUBDIR) $(INCLUDE_TARGETS) $(IDL_HEADERS) $(IDLFILE) + $(VS)echo done > $(INC_FILE) +endif + +$(LIB_FILE): $(LIB_TARGETS) $(LIB_MISC_TARGETS) +ifneq "$(strip $(LIB_TARGETS)$(LIB_MISC_TARGETS))" "" + $(VS)$(INSTALL) $(INSTALL_DIR_OPT) $(PROJ_LIB_DIR) $(LIB_TARGETS) $(LIB_MISC_TARGETS) +endif + $(VS)echo done > $(LIB_FILE) + +$(BIN_FILE): $(CMD_TARGETS) $(CMD_TARGETS_MISC) $(MISC_FILES) +ifneq "$(strip $(CMD_TARGETS_EXE)$(CMD_TARGETS_MISC)$(MISC_FILES))" "" + $(VS)$(INSTALL) $(INSTALL_RDONLY_OPT) $(INSTALL_DIR_OPT) $(PROJ_BIN_DIR)/$(MOD_BIN_SUBDIR)/$(BIN_SUBDIR) $(CMD_TARGETS_EXE) $(CMD_TARGETS_MISC) $(MISC_FILES) +endif +ifneq "$(strip $(CMD_TARGETS_DRIVER))" "" +ifeq "$(BUILD_TARGET_OS)" "LINUX" + $(VS)$(INSTALL) $(INSTALL_RDONLY_OPT) $(INSTALL_DIR_OPT) $(PROJ_BIN_DIR)/$(MOD_BIN_SUBDIR)/$(BIN_SUBDIR) $(CMD_TARGETS_DRIVER) +endif +ifeq "$(BUILD_TARGET_OS)" "DARWIN" + $(VS)$(INSTALL) $(INSTALL_RDONLY_OPT) $(INSTALL_DIR_OPT) $(PROJ_BIN_DIR)/$(MOD_BIN_SUBDIR)/$(BIN_SUBDIR) $(CMD_TARGETS_DRIVER) +endif +endif +ifneq "$(strip $(CMD_TARGETS_KEXT))" "" +ifeq "$(BUILD_TARGET_OS)" "DARWIN" + $(VS)$(INSTALL) $(INSTALL_RDONLY_OPT) $(INSTALL_DIR_OPT) $(PROJ_BIN_DIR)/$(MOD_BIN_SUBDIR)/$(BIN_SUBDIR)/$(CMD_TARGETS_KEXT)/Contents $(CMD_TARGETS_KEXT)/Contents/Info.plist + $(VS)$(INSTALL) $(INSTALL_RDONLY_OPT) $(INSTALL_DIR_OPT) $(PROJ_BIN_DIR)/$(MOD_BIN_SUBDIR)/$(BIN_SUBDIR)/$(CMD_TARGETS_KEXT)/Contents/MacOS $(CMD_TARGETS_KEXT)/Contents/MacOS/$(CMD_TARGETS_DRIVER) + $(VS)$(INSTALL) $(INSTALL_RDONLY_OPT) $(INSTALL_DIR_OPT) $(PROJ_BIN_DIR)/$(MOD_BIN_SUBDIR)/$(BIN_SUBDIR)/$(CMD_TARGETS_KEXT)/Contents/Resources/English.lproj $(CMD_TARGETS_KEXT)/Contents/Resources/English.lproj/InfoPlist.strings +endif +endif +ifneq "$(strip $(CMD_TARGETS_SHLIB))" "" + $(VS)$(INSTALL) $(INSTALL_DIR_OPT) $(PROJ_SHLIB_DIR) $(CMD_TARGETS_SHLIB) + $(VS)$(LNSHLIB) $(PROJ_SHLIB_DIR) $(CMD_TARGETS_SHLIB) +endif +ifneq "$(strip $(CMD_TARGETS_PDB))" "" + $(VS)$(INSTALL) $(INSTALL_DIR_OPT) $(PROJ_BIN_DIR)/$(MOD_BIN_SUBDIR)/$(BIN_SUBDIR) $(CMD_TARGETS_PDB) +endif +ifeq "$$(BUILD_TARGET_OS)" "WIN32" +ifneq "$(strip $(OBJECTS))" "" + $(VS)$(INSTALL) $(INSTALL_DIR_OPT) $(PROJ_SBR_DIR) $(OBJECTS:$(OBJ_SUFFIX)=.sbr) +endif +endif + $(VS)echo done > $(BIN_FILE) diff --git a/Makerules/Maketargets.modulestage b/Makerules/Maketargets.modulestage new file mode 100755 index 0000000..85f41a3 --- /dev/null +++ b/Makerules/Maketargets.modulestage @@ -0,0 +1,67 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +#=============================================================================# +# Rules: +#-----------------------------------------------------------------------------# +# These rules perform the standard module toplevel directory stage steps + +STAGE:: +ifneq "$(strip $(INCLUDE_TARGETS)$(IDL_HEADERS)$(IDLFILE))" "" + $(VS)$(STAGE_INSTALL) $(STAGE_INSTALL_DIR_OPT) $(PROJ_STAGE_INCLUDE_DIR)/$(MOD_INCLUDE_SUBDIR)/$(INCLUDE_SUBDIR) $(INCLUDE_TARGETS) $(IDL_HEADERS) $(IDLFILE) +endif +ifneq "$(strip $(LIB_TARGETS)$(LIB_MISC_TARGETS))" "" + $(VS)$(STAGE_INSTALL) $(STAGE_INSTALL_DIR_OPT) $(PROJ_STAGE_LIB_DIR) $(LIB_TARGETS) $(LIB_MISC_TARGETS) +endif +ifneq "$(strip $(CMD_TARGETS_EXE)$(CMD_TARGETS_MISC)$(MISC_FILES))" "" + $(VS)$(STAGE_INSTALL) $(STAGE_INSTALL_DIR_OPT) $(PROJ_STAGE_BIN_DIR)/$(MOD_BIN_SUBDIR)/$(BIN_SUBDIR) $(CMD_TARGETS_EXE) $(CMD_TARGETS_MISC) $(MISC_FILES) +endif +ifneq "$(strip $(CMD_TARGETS_DRIVER))" "" +ifeq "$(BUILD_TARGET_OS)" "LINUX" + $(VS)$(STAGE_INSTALL) $(STAGE_INSTALL_DIR_OPT) $(PROJ_STAGE_DRIVER_BIN_DIR)/$(MOD_DRIVER_BIN_SUBDIR)/$(DRIVER_BIN_SUBDIR) $(CMD_TARGETS_DRIVER) +endif +endif +ifneq "$(strip $(CMD_TARGETS_KEXT))" "" +ifeq "$(BUILD_TARGET_OS)" "DARWIN" + $(VS)$(STAGE_INSTALL) $(STAGE_INSTALL_RDONLY_OPT) $(STAGE_INSTALL_DIR_OPT) $(PROJ_STAGE_DRIVER_BIN_DIR)/$(MOD_DRIVER_BIN_SUBDIR)/$(DRIVER_BIN_SUBDIR)/$(CMD_TARGETS_KEXT)/Contents $(CMD_TARGETS_KEXT)/Contents/Info.plist + $(VS)$(STAGE_INSTALL) $(STAGE_INSTALL_RDONLY_OPT) $(STAGE_INSTALL_DIR_OPT) $(PROJ_STAGE_DRIVER_BIN_DIR)/$(MOD_DRIVER_BIN_SUBDIR)/$(DRIVER_BIN_SUBDIR)/$(CMD_TARGETS_KEXT)/Contents/MacOS $(CMD_TARGETS_KEXT)/Contents/MacOS/$(CMD_TARGETS_DRIVER) + $(VS)$(STAGE_INSTALL) $(STAGE_INSTALL_RDONLY_OPT) $(STAGE_INSTALL_DIR_OPT) $(PROJ_STAGE_DRIVER_BIN_DIR)/$(MOD_DRIVER_BIN_SUBDIR)/$(DRIVER_BIN_SUBDIR)/$(CMD_TARGETS_KEXT)/Contents/Resources/English.lproj $(CMD_TARGETS_KEXT)/Contents/Resources/English.lproj/InfoPlist.strings +endif +endif +ifneq "$(strip $(CMD_TARGETS_SHLIB))" "" + $(VS)$(STAGE_INSTALL) $(STAGE_INSTALL_DIR_OPT) $(PROJ_STAGE_SHLIB_DIR) $(CMD_TARGETS_SHLIB) +endif +ifneq "$(strip $(CMD_TARGETS_PDB))" "" + $(VS)$(STAGE_INSTALL) $(STAGE_INSTALL_DIR_OPT) $(PROJ_STAGE_BIN_DIR)/$(MOD_BIN_SUBDIR)/$(BIN_SUBDIR) $(CMD_TARGETS_PDB) +endif +ifeq "$(BUILD_TARGET_OS)" "WIN32" +ifneq "$(strip $(OBJECTS))" "" + $(VS)$(STAGE_INSTALL) $(STAGE_INSTALL_DIR_OPT) $(PROJ_SBR_DIR) $(OBJECTS:.obj=.sbr) +endif +endif diff --git a/Makerules/Maketargets.product b/Makerules/Maketargets.product new file mode 100755 index 0000000..fd06765 --- /dev/null +++ b/Makerules/Maketargets.product @@ -0,0 +1,147 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** +#=============================================================================# +# Rules: +#-----------------------------------------------------------------------------# +# These rules define product flags for embedded firmware images + +ifeq "$(PRODUCT)" "" +PROJECT_PACKAGE_EXTERNAL_NAME = Unknown +endif + +ifeq "$(TARGET_BSP)" "capemay" +BSP_CODE = 1 +endif +ifeq "$(TARGET_BSP)" "FCIOU_1XD2G" +BSP_CODE = 2 +endif +ifeq "$(TARGET_BSP)" "sw_aux" +BSP_CODE = 3 +endif +ifeq "$(TARGET_BSP)" "sb1250" +BSP_CODE = 4 +endif +ifeq "$(TARGET_BSP)" "gt64120a" +BSP_CODE = 5 +endif +ifeq "$(TARGET_BSP)" "gt64240" +BSP_CODE = 6 +endif +ifeq "$(TARGET_BSP)" "pcix" +BSP_CODE = 7 +endif +ifeq "$(TARGET_BSP)" "4131_rh" +BSP_CODE = 8 +endif +ifeq "$(TARGET_BSP)" "mc1125" +BSP_CODE = 9 +endif +ifeq "$(TARGET_BSP)" "t3" +BSP_CODE = 10 +endif +ifeq "$(TARGET_BSP)" "vio" +BSP_CODE = 11 +endif +ifeq "$(TARGET_BSP)" "bc2" +BSP_CODE = 12 +endif +ifeq "$(TARGET_BSP)" "xt3" +BSP_CODE = 13 +endif +ifeq "$(TARGET_BSP)" "n450" +BSP_CODE = 14 +endif +ifeq "$(TARGET_BSP)" "q7" +BSP_CODE = 15 +endif +ifeq "$(TARGET_BSP)" "" +BSP_CODE = 0 +endif + +PRODUCT_DEFINES = -DPRODUCT_NAME="$(PROJECT_PACKAGE_EXTERNAL_NAME)" -DPRODUCT_$(PRODUCT) -DPRODUCT_CODE=$(PRODUCT_CODE) +PRODUCT_DEFINES += -DBSP_$(TARGET_BSP_UPCASE) -DBSP_NAME="$(TARGET_BSP)" -DBSP_CODE=$(BSP_CODE) +ifneq "$(VXWORKS_REV)" "" +PRODUCT_DEFINES += -DVXWORKS_REV=$(VXWORKS_REV) +endif +ifneq "$(VXWORKS_REV_6_9)" "" +PRODUCT_DEFINES += -DVXWORKS_REV_6_9=$(VXWORKS_REV_6_9) +endif +ifeq "$(BUILD_OPAFISH)" "yes" +PRODUCT_DEFINES += -DBUILD_OPAFISH +endif +ifeq "$(BUILD_CHASSISGUI2)" "yes" +PRODUCT_DEFINES += -DBUILD_CHASSISGUI2 +endif + +# include buildFeatureDefs to let inplace build work for stream consistency +PRODUCT_DEFINES += -include $(TL_DIR)/Fd/buildFeatureDefs + +ifeq "$(BIOS_UPDATE_ENABLED)" "yes" +PRODUCT_DEFINES += -DBIOS_UPDATE_ENABLED +endif +ifeq "$(FWVERSION_CHECK_ENABLED)" "yes" +PRODUCT_DEFINES += -DFWVERSION_CHECK_ENABLED +endif +ifneq "$(STL_GEN)" "" +PRODUCT_DEFINES += -DSTL_GEN=$(STL_GEN) +endif +ifneq "$(INCLUDE_PRR)" "" +PRODUCT_DEFINES += -DINCLUDE_PRR=$(INCLUDE_PRR) +endif +ifneq "$(INCLUDE_APR)" "" +PRODUCT_DEFINES += -DINCLUDE_APR=$(INCLUDE_APR) +endif +ifneq "$(INCLUDE_16B)" "" +PRODUCT_DEFINES += -DINCLUDE_16B=$(INCLUDE_16B) +endif +ifeq "$(INCLUDE_STLEEP)" "yes" +PRODUCT_DEFINES += -DINCLUDE_STLEEP +endif +ifeq "$(CHECK_HEADERS)" "yes" +PRODUCT_DEFINES += -DCHECK_HEADERS +endif +ifeq "$(BUILD_DMC)" "yes" +PRODUCT_DEFINES += -DBUILD_DMC +endif +ifeq "$(BUILD_BMA)" "yes" +PRODUCT_DEFINES += -DBUILD_BMA +endif +ifeq "$(BUILD_CM)" "yes" +PRODUCT_DEFINES += -DBUILD_CM +endif +ifeq "$(FAKE_PRR_ON_PCI)" "yes" +PRODUCT_DEFINES += -DFAKE_PRR_ON_PCI +endif +BSP_DEFINES += -DP_NAME=\\\"$(PROJECT_PACKAGE_EXTERNAL_NAME)\\\" -DB_NAME=\\\"$(TARGET_BSP)\\\" + +ifneq "$(PRODUCT_ALIAS)" "" +PRODUCT_DEFINES += -DALIAS_$(PRODUCT_ALIAS) -D$(PRODUCT_ALIAS) +endif + +.DELETE_ON_ERROR: diff --git a/Makerules/Maketargets.runtest b/Makerules/Maketargets.runtest new file mode 100755 index 0000000..796aa69 --- /dev/null +++ b/Makerules/Maketargets.runtest @@ -0,0 +1,43 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** +#=============================================================================# +# Rules: +#-----------------------------------------------------------------------------# +# These rules perform the runtest operations for unit test Makefiles + +RUNTEST:: +ifeq "$(BUILD_TARGET_OS)" "LINUX" + $(VS)./$(EXECUTABLE) +endif # BUILD_TARGET_OS LINUX +ifeq "$(BUILD_TARGET_OS)" "DARWIN" + $(VS)./$(EXECUTABLE) +endif # BUILD_TARGET_OS DARWIN +ifeq "$(BUILD_TARGET_OS)" "WIN32" + $(VS)./$(EXECUTABLE) +endif # BUILD_TARGET_OS WIN32 diff --git a/Makerules/Maketargets.stage b/Makerules/Maketargets.stage new file mode 100755 index 0000000..82aa85e --- /dev/null +++ b/Makerules/Maketargets.stage @@ -0,0 +1,81 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** +#=============================================================================# +# Rules: +#-----------------------------------------------------------------------------# +# These rules perform the standard stage steps + +#FIXME, BUILDDIR for non-embedded +ifneq "$(CARD_TYPE)" "" +STAGE_CMD_TARGETS_EXE:=$(foreach c,$(CMD_TARGETS_EXE),$(BUILDDIR)/$(c)) +STAGE_BOOTLOADER_TARGETS:=$(foreach c,$(BOOTLOADER_TARGETS),$(BUILDDIR)/$(c)) +endif + +STAGE:: +ifneq "$(strip $(INCLUDE_TARGETS)$(IDL_HEADERS)$(IDLFILE))" "" + $(VS)$(STAGE_INSTALL) $(STAGE_INSTALL_DIR_OPT) $(MOD_STAGE_INCLUDE_DIR)/$(MOD_INCLUDE_SUBDIR)/$(INCLUDE_SUBDIR) $(INCLUDE_TARGETS) $(IDL_HEADERS) $(IDLFILE) +endif +ifneq "$(strip $(LIB_TARGETS)$(LIB_MISC_TARGETS))" "" + $(VS)$(STAGE_INSTALL) $(STAGE_INSTALL_DIR_OPT) $(MOD_STAGE_LIB_DIR) $(LIB_TARGETS) $(LIB_MISC_TARGETS) +endif +ifneq "$(strip $(CMD_TARGETS_EXE)$(CMD_TARGETS_MISC)$(MISC_FILES))" "" +ifeq "$(CARD_TYPE)" "" + $(VS)$(STAGE_INSTALL) $(STAGE_INSTALL_DIR_OPT) $(MOD_STAGE_BIN_DIR)/$(MOD_BIN_SUBDIR)/$(BIN_SUBDIR) $(CMD_TARGETS_EXE) $(CMD_TARGETS_MISC) $(MISC_FILES) +else + $(VS)$(STAGE_INSTALL) $(STAGE_INSTALL_DIR_OPT) $(MOD_STAGE_BIN_DIR)/$(MOD_BIN_SUBDIR)/$(BIN_SUBDIR) $(STAGE_CMD_TARGETS_EXE) $(CMD_TARGETS_MISC) $(MISC_FILES) +endif +endif +ifneq "$(strip $(CMD_TARGETS_DRIVER))" "" +ifeq "$(BUILD_TARGET_OS)" "LINUX" + $(VS)$(STAGE_INSTALL) $(STAGE_INSTALL_DIR_OPT) $(MOD_STAGE_DRIVER_BIN_DIR)/$(MOD_DRIVER_BIN_SUBDIR)/$(DRIVER_BIN_SUBDIR) $(CMD_TARGETS_DRIVER) +endif +endif +ifneq "$(strip $(CMD_TARGETS_KEXT))" "" +ifeq "$(BUILD_TARGET_OS)" "DARWIN" + $(VS)$(STAGE_INSTALL) $(STAGE_INSTALL_DIR_OPT) $(MOD_STAGE_DRIVER_BIN_DIR)/$(MOD_DRIVER_BIN_SUBDIR)/$(DRIVER_BIN_SUBDIR)/$(CMD_TARGETS_KEXT)/Contents $(CMD_TARGETS_KEXT)/Contents/Info.plist + $(VS)$(STAGE_INSTALL) $(STAGE_INSTALL_DIR_OPT) $(MOD_STAGE_DRIVER_BIN_DIR)/$(MOD_DRIVER_BIN_SUBDIR)/$(DRIVER_BIN_SUBDIR)/$(CMD_TARGETS_KEXT)/Contents/MacOS $(CMD_TARGETS_KEXT)/Contents/MacOS/$(CMD_TARGETS_DRIVER) + $(VS)$(STAGE_INSTALL) $(STAGE_INSTALL_DIR_OPT) $(MOD_STAGE_DRIVER_BIN_DIR)/$(MOD_DRIVER_BIN_SUBDIR)/$(DRIVER_BIN_SUBDIR)/$(CMD_TARGETS_KEXT)/Contents/Resources/English.lproj $(CMD_TARGETS_KEXT)/Contents/Resources/English.lproj/InfoPlist.strings +endif +endif +ifneq "$(strip $(CMD_TARGETS_SHLIB))" "" + $(VS)$(STAGE_INSTALL) $(STAGE_INSTALL_DIR_OPT) $(MOD_STAGE_SHLIB_DIR) $(CMD_TARGETS_SHLIB) +endif +ifneq "$(strip $(CMD_TARGETS_PDB))" "" + $(VS)$(STAGE_INSTALL) $(STAGE_INSTALL_DIR_OPT) $(MOD_STAGE_BIN_DIR)/$(MOD_BIN_SUBDIR)/$(BIN_SUBDIR) $(CMD_TARGETS_PDB) +endif +ifeq "$(BUILD_TARGET_OS)" "WIN32" +ifneq "$(strip $(OBJECTS))" "" + $(VS)$(STAGE_INSTALL) $(STAGE_INSTALL_DIR_OPT) $(PROJ_SBR_DIR) $(OBJECTS:.obj=.sbr) +endif +endif + +STAGEBOOT:: +ifneq "$(strip $(STAGE_BOOTLOADER_TARGETS))" "" + $(VS)$(STAGE_INSTALL) $(STAGE_INSTALL_DIR_OPT) $(MOD_STAGE_BIN_DIR)/$(MOD_BIN_SUBDIR)/$(BIN_SUBDIR) $(STAGE_BOOTLOADER_TARGETS) +endif diff --git a/Makerules/Maketargets.tms b/Makerules/Maketargets.tms new file mode 100755 index 0000000..3867999 --- /dev/null +++ b/Makerules/Maketargets.tms @@ -0,0 +1,94 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** +# These rules build VxWorks TMS + +.PHONY: buildtms cleantms + +include $(TL_DIR)/Makerules/Maketargets.product + +ifneq "$(CARD_TYPE)" "" +TMS_OBJECT_TAGS= envoy $(PROJECT_SSP) test tms vx zlib +TMS_OBJECT_DIRECTORIES=$(foreach d,$(TMS_OBJECT_TAGS),$(TL_DIR)/tmsTarget/lib/obj$(CARD_TYPE).$(TARGET_BSP).$(BUILD_CONFIG).$(TORNADO_CPU)$(TORNADO_TOOL)$(d)) +TMS_OBJECT_DIR_MARKER_FILE=.tmsObjDirs +TMS_DEFS_FILE=$(TL_DIR)/tmsTarget/h/make/make.$(CARD_TYPE).$(TARGET_BSP).$(BUILD_CONFIG).$(TORNADO_CPU)$(TORNADO_TOOL) +obj$(CARD_TYPE).$(TARGET_BSP).$(BUILD_CONFIG).% : obj% + cp -rpv $< $@ + find $@ -name CVS | xargs rm -rf +endif + +# FIXME, can use a BUILT_SUFFIX type define and remove ifeq +ifeq "$(CARD_TYPE)" "" +TMS_LIBRARIES=$(notdir $(wildcard $(TORNADO_LIB_DIR)/lib$(TORNADO_CPU)$(TORNADO_TOOL)*.a)) +else +TMS_LIBRARIES=$(notdir $(wildcard $(TORNADO_LIB_DIR)/lib$(CARD_TYPE).$(TARGET_BSP).$(BUILD_CONFIG).$(TORNADO_CPU)$(TORNADO_TOOL)*.a)) +endif + +#$(TL_DIR)/target: +# mv $(TL_DIR)/tmsTarget $(TL_DIR)/target + +ifneq (1,$(NO_SSP)) +TMS_OPTIONS = SSP_NAME=$(PROJECT_SSP) TMS_CFLAGS="-DINCLUDE_L2 $(PRODUCT_DEFINES)" +else +endif + + +ifeq "$(CARD_TYPE)" "" + +buildtms: + cd $(TL_DIR)/tmsTarget/src;PATH=$(MIPS_PATH):$(PATH) BUILD_CONFIG="$(BUILD_CONFIG)" BUILD_ESM=$(BUILD_ESM) make CPU=R4000 $(TMS_OPTIONS) + cd $(TORNADO_LIB_DIR); $(VS)$(INSTALL) $(INSTALL_DIR_OPT) $(PROJ_SHLIB_DIR) lib$(TORNADO_CPU)$(TORNADO_TOOL)*.a + +cleantms: + cd $(TL_DIR)/tmsTarget/src;BUILD_CONFIG="$(BUILD_CONFIG)" PATH=$(MIPS_PATH):$(PATH) CLEANING=true BUILD_ESM=$(BUILD_ESM) make CPU=R4000 SSP_NAME=$(PROJECT_SSP) TMS_CFLAGS=-DINCLUDE_L2 rclean + +else + +$(TMS_OBJECT_DIR_MARKER_FILE): $(TMS_OBJECT_DIRECTORIES) + echo done > $(TMS_OBJECT_DIR_MARKER_FILE) +$(TMS_DEFS_FILE): $(TL_DIR)/tmsTarget/h/make/make.$(TORNADO_CPU)$(TORNADO_TOOL) + cp $< $@ +buildtms: $(TMS_OBJECT_DIR_MARKER_FILE) $(TMS_DEFS_FILE) + cd $(TL_DIR)/tmsTarget/src;PATH=$(MIPS_PATH):$(PATH) BUILD_CONFIG="$(BUILD_CONFIG)" BUILD_ESM=$(BUILD_ESM) make CPU=$(CARD_TYPE).$(TARGET_BSP).$(BUILD_CONFIG).$(TORNADO_CPU) CARD_TYPE=$(CARD_TYPE) TARGET_BSP=$(TARGET_BSP) $(TMS_OPTIONS) + cd $(TORNADO_LIB_DIR); $(VS)$(INSTALL) $(INSTALL_DIR_OPT) $(PROJ_SHLIB_DIR) lib$(CARD_TYPE).$(TARGET_BSP).$(BUILD_CONFIG).$(TORNADO_CPU)$(TORNADO_TOOL)*.a + +cleantms: + cd $(TL_DIR)/tmsTarget/src;BUILD_CONFIG="$(BUILD_CONFIG)" PATH=$(MIPS_PATH):$(PATH) CLEANING=true BUILD_ESM=$(BUILD_ESM) make CPU=$(CARD_TYPE).$(TARGET_BSP).$(BUILD_CONFIG).$(TORNADO_CPU) SSP_NAME=$(PROJECT_SSP) TMS_CFLAGS=-DINCLUDE_L2 rclean + rm -f $(TMS_DEFS_FILE) + +endif + +ifeq "$(BUILD_TMS)" "yes" +LIBS:: buildtms +endif + +ifneq "$(CLEAN_TMS)" "no" +clobber:: cleantms +endif + +.DELETE_ON_ERROR: diff --git a/Makerules/Maketargets.tms-for-wrs b/Makerules/Maketargets.tms-for-wrs new file mode 100755 index 0000000..4c11b2c --- /dev/null +++ b/Makerules/Maketargets.tms-for-wrs @@ -0,0 +1,96 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** +# These rules build VxWorks TMS + +.PHONY: buildtms cleantms + +include $(TL_DIR)/Makerules/Maketargets.product + +ifneq "$(CARD_TYPE)" "" +#TMS_OBJECT_TAGS= envoy $(PROJECT_SSP) test tms vx zlib +# new WRS has test, zlib but it's for linux - not sure if i can use it +#TMS_OBJECT_TAGS= envoy $(PROJECT_SSP) tms vx +TMS_OBJECT_TAGS= envoy tms vx zlib +TMS_OBJECT_DIRECTORIES=$(foreach d,$(TMS_OBJECT_TAGS),$(TL_DIR)/target/lib/obj$(CARD_TYPE).$(TARGET_BSP).$(BUILD_CONFIG).$(TORNADO_CPU)$(TORNADO_TOOL)$(d)) +TMS_OBJECT_DIR_MARKER_FILE=.tmsObjDirs +TMS_DEFS_FILE=$(TL_DIR)/target/h/tool/gnu/make.$(CARD_TYPE).$(TARGET_BSP).$(BUILD_CONFIG).$(TORNADO_CPU)$(TORNADO_TOOL) +# previously, this is where binaries from old obj directories were copied +# into new location where it could be replaced by new binaries. +# But, for atom, there is no need for all this. +obj$(CARD_TYPE).$(TARGET_BSP).$(BUILD_CONFIG).% : + echo $@ "to be built" +endif + +ifeq "$(CARD_TYPE)" "" +TMS_LIBRARIES=$(notdir $(wildcard $(TORNADO_LIB_DIR)/lib$(TORNADO_CPU)$(TORNADO_TOOL)*.a)) +else +TMS_LIBRARIES=$(notdir $(wildcard $(TORNADO_LIB_DIR)/lib$(CARD_TYPE).$(TARGET_BSP).$(BUILD_CONFIG).$(TORNADO_CPU)$(TORNADO_TOOL)*.a)) +endif + +ifneq (1,$(NO_SSP)) +TMS_OPTIONS = SSP_NAME=$(PROJECT_SSP) TMS_CFLAGS="-DINCLUDE_L2 $(PRODUCT_DEFINES)" +else +endif + + +ifeq "$(CARD_TYPE)" "" + +buildtms: + cd $(TL_DIR)/target/tmsTarget/src;PATH=$(ATOM_PATH):$(PATH) BUILD_CONFIG="$(BUILD_CONFIG)" BUILD_ESM=$(BUILD_ESM) make CPU=ATOM $(TMS_OPTIONS) + cd $(TORNADO_LIB_DIR); $(VS)$(INSTALL) $(INSTALL_DIR_OPT) $(PROJ_SHLIB_DIR) lib$(TORNADO_CPU)$(TORNADO_TOOL)*.a + +cleantms: + cd $(TL_DIR)/target/tmsTarget/src;BUILD_CONFIG="$(BUILD_CONFIG)" PATH=$(ATOM_PATH):$(PATH) CLEANING=true BUILD_ESM=$(BUILD_ESM) make CPU=ATOM SSP_NAME=$(PROJECT_SSP) TMS_CFLAGS=-DINCLUDE_L2 rclean + +else + +$(TMS_OBJECT_DIR_MARKER_FILE): $(TMS_OBJECT_DIRECTORIES) + echo $(TMS_DEFS_FILE) + echo done > $(TMS_OBJECT_DIR_MARKER_FILE) +$(TMS_DEFS_FILE): $(TL_DIR)/target/h/tool/gnu/make.$(TORNADO_CPU)$(TORNADO_TOOL) + cp $< $@ +buildtms: $(TMS_OBJECT_DIR_MARKER_FILE) $(TMS_DEFS_FILE) + cd $(TL_DIR)/target/tmsTarget/src;PATH=$(ATOM_PATH):$(PATH) BUILD_CONFIG="$(BUILD_CONFIG)" BUILD_ESM=$(BUILD_ESM) make CPU=$(CARD_TYPE).$(TARGET_BSP).$(BUILD_CONFIG).$(TORNADO_CPU) CARD_TYPE=$(CARD_TYPE) TARGET_BSP=$(TARGET_BSP) $(TMS_OPTIONS) + cd $(TORNADO_LIB_DIR); $(VS)$(INSTALL) $(INSTALL_DIR_OPT) $(PROJ_SHLIB_DIR) lib$(CARD_TYPE).$(TARGET_BSP).$(BUILD_CONFIG).$(TORNADO_CPU)$(TORNADO_TOOL)*.a + +cleantms: + cd $(TL_DIR)/target/tmsTarget/src;BUILD_CONFIG="$(BUILD_CONFIG)" PATH=$(ATOM_PATH):$(PATH) CLEANING=true BUILD_ESM=$(BUILD_ESM) make CPU=$(CARD_TYPE).$(TARGET_BSP).$(BUILD_CONFIG).$(TORNADO_CPU) SSP_NAME=$(PROJECT_SSP) TMS_CFLAGS=-DINCLUDE_L2 rclean + rm -f $(TMS_DEFS_FILE) + +endif + +ifeq "$(BUILD_TMS)" "yes" +LIBS:: buildtms +endif + +ifneq "$(CLEAN_TMS)" "no" +clobber:: cleantms +endif + +.DELETE_ON_ERROR: diff --git a/Makerules/Maketargets.toplevel b/Makerules/Maketargets.toplevel new file mode 100755 index 0000000..06caa27 --- /dev/null +++ b/Makerules/Maketargets.toplevel @@ -0,0 +1,154 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** +#=============================================================================# + +# Rules: +#-----------------------------------------------------------------------------# +# These rules iterate on all the directories in DIRS +# if DIRS is "", we ifdef out all these rules +ifneq "$(strip $(DIRS))" "" + + +ifneq "$(STOP_ON_ERROR)" "yes" +TEST_EXIT= +else +ERROR_EXIT_STATUS=127 +TEST_EXIT=if test $$? -ne 0; then exit $(ERROR_EXIT_STATUS); fi +endif + +# if DIR itself is specified as a target, run install build in it +$(DIRS): + cd $@ && $(MAKE) $(MFLAGS) install +.PHONY: $(DIRS) + +# iterate on sub-directories for simple targets +# for CMDS, STAGE, INSTALL and RUNTEST we can directly invoke them +# we know an earlier pass (ie. libs) build the dependency files + +# if CMDS_FIRMWARE_ONLY is yes and make has been invoked in TL_DIR, +# only do the CMDS phase in the firmware directory. Do nothing if +# it is set and make has not been invoked in TL_DIR. + +ifeq "$(CMDS_FIRMWARE_ONLY)" "yes" + +ifeq "$(CARD_TYPE)" "" +FIRMWARE_DIR = Firmware +else +FIRMWARE_DIR = $(PROJ_FILE_DIR)/Firmware +endif + +clean clobber cleandepend depend force STAGE INSTALL RUNTEST build_dsfiles clobber_dsfiles lint cflow :: + $(VS)for d in $(DIRS) ;\ + do \ + echo "cd $$d && $(MAKE) $(MFLAGS) $@";\ + ( cd $$d && $(MAKE) $(MFLAGS) $@ ); \ + $(TEST_EXIT) \ + done + +CMDS:: +ifeq ($(TL_DIR),$(PWD)) + echo "cd $(FIRMWARE_DIR) && $(MAKE) $(MFLAGS) cmdsonly";\ + ( cd $(FIRMWARE_DIR) && $(MAKE) $(MFLAGS) cmdsonly ); \ + $(TEST_EXIT) +endif +ifeq ($(TL_DIR)/All_Emb,$(PWD)) + echo "cd $(TL_DIR)/$(FIRMWARE_DIR) && $(MAKE) $(MFLAGS) cmdsonly";\ + ( cd $(TL_DIR)/$(FIRMWARE_DIR) && $(MAKE) $(MFLAGS) cmdsonly ); \ + $(TEST_EXIT) +endif + +else # CMDS_FIRMWARE_ONLY is not yes + +clean clobber cleandepend depend force STAGE INSTALL RUNTEST build_dsfiles clobber_dsfiles lint cflow :: + $(VS)for d in $(DIRS) ;\ + do \ + echo "cd $$d && $(MAKE) $(MFLAGS) $@";\ + ( cd $$d && $(MAKE) $(MFLAGS) $@ ); \ + $(TEST_EXIT) \ + done +CMDS:: + $(VS)for d in $(DIRS) ;\ + do \ + echo "cd $$d && $(MAKE) $(MFLAGS) cmdsonly";\ + ( cd $$d && $(MAKE) $(MFLAGS) cmdsonly ); \ + $(TEST_EXIT) \ + done +endif # if CMDS_FIRMWARE_ONLY + +# special clobber used between BSP builds during weeklybuild +# only hits directories which are bsp specific, hence speeding up +# overall weeklybuild performance for multi-bsp products +clobber_bsp_specific:: +ifneq "$(BSP_SPECIFIC_DIRS)" "" + $(VS)for d in $(BSP_SPECIFIC_DIRS) ;\ + do \ + echo "cd $$d && $(MAKE) $(MFLAGS) clobber";\ + ( cd $$d && $(MAKE) $(MFLAGS) clobber ); \ + $(TEST_EXIT) \ + done +endif + + +# descend the tree while building a DSP file +# add the directory names to the GROUP and ../ to the Filename +# so that everything in the DSP can stay as relative pathnames +dsp_body :: + $(VS)for d in $(DIRS) ;\ + do \ + echo "cd $$d && $(MAKE) $(MFLAGS) dsp_group" ;\ + ( cd $$d && $(MAKE) $(MFLAGS) dsp_group DSP_TMP_FILE=../$(DSP_TMP_FILE) \ + DSP_GROUP=$(DSP_GROUP)/$$d ); \ + $(TEST_EXIT) \ + done + +# For ALL we must iterate the sub-directories for INCLUDES, LIBS then CMDS +# we can't simply iterate for ALL/all because of possible cross-dependencies +# for include files and libraries between directories +# We use the lowercase targets here so that makedepend can be properly +# invoked as needed +ALL :: INCLUDES LIBS CMDS +#ALL :: LIBS CMDS +INCLUDES:: + $(VS)for d in $(DIRS) ;\ + do \ + echo "cd $$d && $(MAKE) $(MFLAGS) includes";\ + ( cd $$d && $(MAKE) $(MFLAGS) includes ); \ + $(TEST_EXIT) \ + done +LIBS :: + $(VS)for d in $(DIRS) ;\ + do \ + echo "cd $$d && $(MAKE) $(MFLAGS) libsonly";\ + ( cd $$d && $(MAKE) $(MFLAGS) libsonly ); \ + $(TEST_EXIT) \ + done +endif # DIRS + +.DELETE_ON_ERROR: +#=============================================================================# diff --git a/Makerules/README b/Makerules/README new file mode 100755 index 0000000..246849e --- /dev/null +++ b/Makerules/README @@ -0,0 +1,450 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# This directory contains makerules files. These files control the compiler and +# linker flags and provide mechanisms for individual makefiles to augment the +# defaults as needed + +## Global Make Settings File +## ---------------------- +## All project makesettings files (or local makefiles not associated with a +## specific project) should include this file +## before the local definitions section. +## This file allows setting variables which can be used by Makefiles to make +## decisions on which targets or DIRS to build. This allows such controls +## to be placed here as opposed to extending the build system environment +## variable tools like setenv, target, etc. +## +## Global Make Rules File +## ---------------------- +## All project makerules files (or local makefiles not associated with a +## specific project) should include this file +## after the local definitions section and before the local rules section. The +## function of the global makerules file is to define the system applications, +## standardized make targets (rules) and commonly used variables and structure. +## The makefile is coded so that it is platform independent. Specifics to a +## given platform are taken care of in 'ifdef' type statements so that the +## makefile can be used on all platforms with little or no modification. Any +## modifications to the source should be made with portability in mind and +## should follow the embedded notations. +## +## More information about the +## execution of the makefile can be had by specifying the -d option on the +## command line to make. +## +## NOTE: This makerules file (as well as the project makerules and the template +## makefiles) depend on using the GNU version of make. GNU make +## (which is included in cygwin) must be +## installed on your system prior to using this makefile. +#=============================================================================# +## +#=============================================================================# +## The following list is the standard list of definitions which will be defined +## or are used in other variable definitions or rules in this makerules file. +## Each global variable name is listed with a definition of the purpose and +## intended use. Defaults for items are shown in brackets, and may be +## overridden by the user in a local makefile or project makerules file. If +## no default is shown, the user can use the variable, but should not change +## the value. +## +## Make Control Variables: +##AUTODEP = environment defined to enable/disable makedepend during +## make all phase of build (default is yes, set to no to +## disable makedepend) +##BUILD_CONFIG= Type of build to do: debug or release or loadable [debug] +## Debug release includes CDEBUG/CCDEBUG flags and does not use +## COPT/CCOPT. Non-debug omits CDEBUG/CCDEBUG and uses COPT/CCOPT +## loadable is only allowed for MIPS/VxWorks builds. This does: +## Libraries build to .rel files which have all objects in +## Only SYSLIBS in included in link +## Firmware/BSP is built with .rel files, BSP has all symbols +## Hence Unit Tests can be built to a .out and downloaded +## against a full firmware which was built as loadable as well +## loadable builds define -DBUILD_LOADABLE so initialization +## code for system libraries can be disabled in unit tests +##BUILD_PLATFORM= system build is running on (DOS, CYGWIN, LINUX, or DARWIN) +## determined dynamically in this file if not pre-defined +##BUILD_TARGET= Target for build (MIPS, MIPS_BSP, IA32, IA64, X86_64, WIN32, CYGWIN, PPC) +##BUILD_UNIT_TEST= should build of UNIT_TEST directories be enabled (!="" or "") +## when set to != "", the variable $(TEST) is defined as Test +## when set to "" $(TEST) is set to "" +## $(TEST) should be used in DIRS and DS_SUBPROJECTS to select +## unit test directories +##MAKE = System make application +##MAKEFILE = Name of makefile [Makefile] +##BUILD_TARGET_OS= OS to build for (VXWORKS, LINUX, WIN32, CYGWIN, DARWIN) +##BUILD_TARGET_OS_VERSION= version of OS to build for (2.4.7-10, etc). +##BUILD_BRAND= branding for product, default is "SilverStorm Technologies Inc." +##REGISTER = Enable Registration, set to "#" to disable registration of +## Windows DLLs and applications built (Windows Only) +##VS = Visible shell commands [""], set to "" to see more +## set to "@" to see less +## +## Make Targets and Byproducts: +##PRODUCT = actual product name, used in BSPs and other common code +## as needed to create a product specific flavor +## created as basename of TL_DIR +##DIRS = list of subdirectories to build (for toplevel & middle makefiles) +##BSP_SPECIFIC_DIRS = list of subdirectories to clobber when rebuilding +## for a different BSP +##CFILES = list of C source files to compile (.c suffix) +##CCFILES = list of C++ source files to compile (.cpp suffix) +##LFILES = list of lex source files to compiler (.lex suffix) +##LIBFILES = list of library names to combine into archive/shlib built +##IDLFILE = idl source file (.idl suffix) (Windows Only) +##IDL_TARGETS = files to build from IDLFILE during INCLUDES phase (Windows Only) +##IDL_HEADERS = .h files to build from IDLFILE during INCLUDES phase +## (Windows Only) +##IDL_OTHER = .c and .tlb files to build from IDLFILE during INCLUDES phase +## (Windows Only) +##RSCFILES = list of resource source files (.rc suffix) (Windows Only) +##SOURCES = list of source files, used to drive dependency generation +##OBJECTS = Intermediate object file names [Not Defined] +##ARLIBS = Intermediate archive libraries to combine in archive and +## shared library targets +##INCLUDE_TARGETS = include files to install (not clobbered) +##LIB_TARGETS_IMPLIB = import libraries built during libs phase +##LIB_TARGETS_ARLIB = archive libraries built during libs phase +##LIB_TARGETS_EXP= .exp file built during libs phase (Windows Only) +##LIB_TARGETS_MISC= Miscellaneous targets built during libs phase +##LIB_TARGETS = complete set of targets built during libs phase +##CMD_TARGETS_SHLIB = shared libraries built during cmds phase +##CMD_TARGETS_EXE = executables built during cmds phase +##CMD_TARGETS_DRIVER= Device Drivers built during cmds phase +## can also be a partial link of a device driver +## (LINUX and DARWIN only) +##CMD_TARGETS_KEXT= Final IOKit packaged Kernel Extension built during cmds +## phase and packaged using CMD_TARGETS_DRIVER (DARWIN only) +##CMD_TARGETS_MISC= Miscellaneous targets built during cmds phase +##CMD_TARGETS = complete set of targets built during cmds phase +##EXECUTABLE= executable to be run when testing/debugging [Not Defined] +##MISC_FILES= Miscellaneous files not-build (nor clobbered) +##CLEAN_TARGETS_MISC= Miscellaneous backup and junk files created during a +## build [Empty], removed during clean +##CLEAN_TARGETS = Intermediate build process file names to remove during clean +## or clobber (in addition to $(OBJECTS) [Not Defined] +##CLOBBER_TARGETS_MISC = Miscellaneous backup and junk files created during a +## build [Empty], removed during clobber +##CLOBBER_TARGETS = Targets to remove on a clobber [Not Defined] +## +## Suffixes (all include the . ): +##LIB_PREFIX = prefix for shared and archive libraries (e.g., lib or "") +##SHLIB_SUFFIX = suffix for shared libraries (e.g., .dll, .sl, .so, etc) +##ARLIB_SUFFIX = suffix for static/archive libraries (e.g., .a, .lib, etc) +##EXE_SUFFIX = suffix for executable files (e.g, "", .exe, .out, etc) +##OBJ_SUFFIX = suffix for object files (e.g, .o, .obj, etc) +##KEXT_SUFFIX = suffix for kernel extensions (e.g, .kext) (DARWIN only) +##EXP_SUFFIX = suffix for export files (e.g, .exp, etc) +##PRE_SUFFIX = suffix for preprocessor output files (e.g, .pre, etc) +##RES_SUFFIX = suffix for compiled resource object files (e.g, .res, etc) +##DSP_SUFFIX = suffix for generated dsp files (e.g, _$(BUILD_TARGET).dsp) +##DSW_SUFFIX = suffix for generated dsw files (e.g, _$(BUILD_TARGET).dsw) +## +## Basic Commands: +##CAT = Unix cat command +##CHMOD = change file permissions +##CP = copy file +##ECHO = echo output to stdout +##INSTALL = tool to copy files if changed +##MV = command to rename or move files +##PERL = Perl Interpreter +##RM = command to remove file(s) +##RMFORCE = option to RM to ignore missing files and permissions problems +##RMRECURSE = option to RM to recursively remove directories +##SED = stream editor +##SHELL = Default system shell (bash) +##TOUCH = update file date (or create empty file) +## +## Paths: +##BIN_SUBDIR= subdirectory to install cmds to within +## PROJ_BIN_DIR/MOD_BIN_SUBDIR or PROJ_STAGE_BIN_DIR/MOD_BIN_SUBDIR +##INCLUDE_SUBDIR= subdirectory to install includes to within +## PROJ_INCLUDE_DIR/MOD_INCLUDE_SUBDIR or +## PROJ_STAGE_INCLUDE_DIR/MOD_INCLUDE_SUBDIR +##TOOLS_DIR - where to get development environment tools [/usr/local/ics/bin] +##TOOLCHAIN_DIR - where to get cross compilation tools [varies based on BUILD_TARGET] +##MAKETOOLS_DIR - where to get make tools [$(TL_DIR)/MakeTools] +##TL_DIR = defines Top Level directory for build +## (ie. where Makerules directory exists.) +##COMN_INCLUDE_DIRS = global include directories +## (include in PROJ_INCLUDE_DIRS or LOCAL_INCLUDE_DIRS when +## appropriate) +##COMN_LIB_DIRS = global library directories +## (include in PROJ_LIB_DIRS or LOCAL_LIB_DIRS when appropriate) +## +##The following paths are of the form: +## X_DIR - base directory for the subdirs below +## X_BIN_DIR - where to copy executable files built +## X_INCLUDE_DIR - where to copy include files built +## X_LIB_DIR - where to copy archive lib files built +## X_SHLIB_DIR - where to copy shared lib files built +## X_SBR_DIR - where to copy sbr files built (Windows Only) +##Where X is: +## GLOBAL - during basic build pass, use to define PROJ versions +## PROJ - in a local makefile without Makerules.module during +## basic build pass [Empty] +## MOD - in a local makefile during basic build pass [Empty] +## STAGE - during stage build pass, use to define PROJ_STAGE versions +## PROJ_STAGE - in a local makefile without Makerules.module during +## stage build pass [Empty] +## MOD_STAGE - in a local makefile during stage build pass [Empty] +## RELEASE - during release step,(used to be part of COMN_ paths above) +## if the MOD and MOD_STAGE versions are not defined (as would be +## the case for a local makefile which is not part of a module) +## The PROJ and PROJ_STATE versions will be used. This occurs on +## a path by path basis. This applies to all the paths above +## except X_DIR. +## +## Compilation/Build Commands and flags: +##Within the execution of commands, a common style is used for naming +##the variables: +## X = tool name +## XSYS = special windows options required to make tool work properly +## for combination of BUILD_TARGET and BUILD_PLATFORM +## defined in makerules.global +## XLOCAL = User supplied flags for tool [Empty] +## these can be defined in the local makefile +## XMOD = User supplied flags for tool [Not Defined] +## these can be defined in the local module makefile +## for multiple level modules (ie. with sub-directories) +## these will drive down into the sub-directories, much as +## XPROJ flags drive into all the modules in a project +## XPROJ = project level flags for tool [Not Defined] +## these should only be defined in the makerules.project file +## XENV = environment supplied flags for tool [Not Defined] +## these can be defined in the environment +## XMACH - flags to tell tool the machine type being built for +## (does not apply to all tool types) +## XFLAGS = complete set of flags for tool +## composed from all the above flags +## +##BSC = Browse File Builder (Windows Only) +##BSCSYS = Win32 flags for Browse File Builder +##BSCLOCAL = User flags for Browse File Builder [Empty] +##BSCMOD = module level flags for Browse File Builder [Not Defined] +##BSCPROJ = project level flags for Browse File Builder [Not Defined] +##BSCENV = Environment defined Browse File Builder flags [Not Defined] +##BSCFLAGS = complete set of flags for Browse File Builder +## +##TARGET_BSP = BSP to be built. This indicates the sub-directory in +## BSP/ to build when doing a maketargets.bsp +## If this is not defined, BSP builds do not occur +## This only applies to VXWORKS based BUILD_TARGETs +##BSP_TARGETS = set of files which are created by the BSP build (e.g. vxWorks, map, sym) +## during a BSP build [internal value set in maketargets.bsp] +##BSP_MAKE_TARGET= which BSP to build (e.g. vxWorks, vxWorks,st, defaults to vxWorks) +## [internal value set in maketargets.bsp] +## +##BUILDMSGS = Message Table translator command +##BUILDMSGS_PL = Message Table translator script file +## +##CC = Platform C compiler program +##CCC = Platform C++ compiler program +##CLOCALDEBUG= User defined C debugging compilation flags [Empty] +## only used when BUILD_CONFIG=debug +##CCLOCALDEBUG= User defined C++ debugging compilation flags [Empty] +## only used when BUILD_CONFIG=debug +##CDEBUG = C debugging compilation flags +##CCDEBUG = C++ debugging compilation flags +##COPT = C optimization options +##CCOPT = C++ optimization options +##CANSI = C Compilation flags for ANSI C (Use in CLOCAL, CMOD or CPROJ for +## ANSI-C compatible C source code) +##CPIC = C Compilation flags for Position Indepdent Code +## (Use in CLOCAL, CMOD or CPROJ for Shared Library builds) +##CCPIC = C++ Compilation flags for Position Indepdent Code +## (Use in CLOCAL, CMOD or CPROJ for Shared Library builds) +##CCRTTI = C++ compilation flags to enable C++ Run Time Type Information +##CCEXH = C++ compilation flags to enable C++ Exception handling +##CLOCAL = User defined C flags for compiling [Empty] +##CCLOCAL = User defined C++ flags for compiling [Empty] +##CENV = Environment defined C compilation flags [Not Defined] +##CCENV = Environment defined C++ compilation flags [Not Defined] +##CENVFS = Environment defined C compilation flags per feature set [Not Defined] +##CCENVFS = Environment defined C++ compilation flags per feature set [Not Defined] +##CMOD = module level defined C compilation flags [Not Defined] +##CCMOD = module level defined C++ compilation flags [Not Defined] +##CPROJ = project level defined C compilation flags [Not Defined] +##CCPROJ = project level defined C++ compilation flags [Not Defined] +##CMACH = defines for system type +##CSYS = target/platform specific C compilation flags +##CCSYS = target/platform specific C++ compilation flags +##SYS_INCLUDE_DIRS = target/platform specific include directories +##LOCAL_INCLUDE_DIRS = User include directories to search for C/C++ headers [Empty] +##MOD_INCLUDE_DIRS = module level directories to search for C/C++ headers [Not Defined] +##PROJ_INCLUDE_DIRS = project level directories to search for C/C++ headers [Not Defined] +##CSHARED = C compilation flags for shared library .o files (include in +## CLOCAL, CMOD or CPROJ when appropriate) +##CCSHARED = C++ compilation flags for shared library .o files (include in +## CCLOCAL, CMOD or CCPROJ when appropriate) +##CFLAGS = Complete set of C compilation flags +##CCFLAGS = Complete set of C++ compilation flags +##CINCLUDE_DIRS = Complete set of C include directories +##CINCSRCH = full compiler directives for include paths to search +##SUBSYSTEM = Subsystem to build for (none, console or windows) (Windows Only) +## [default console] +##USEMFC = How Windows MFC should be used (none, static, shared, no_mfc) +## (Windows Only) [default none] +## +## +##MAKEDEPEND = System makedepend application (Windows Only, on others +## $(CC) $(DEPENDFLAGS) -MT $(BUILDIR)/$*.o -MM is used) +##DEPENDFLAGS = makedepend flags for .c files +##CCDEPENDFLAGS = makedepend flags for .cpp files +##DEPENDMOD = module level defined makedepend flags [Not Defined] +##DEPENDPROJ = project level defined makedepend flags [Not Defined] +##DEPENDLOCAL = user defined makedepend flags [Empty] +##DEPENDENV = Environment defined makedepend flags [Not Defined] +## +##LD = System linker +##LDSTRIP = LD option to strip [-s] ("" on Win32) +##LDPDB_DEBUG = LD option to create pdb file for debug builds [/debug /pdbtype:sept /debugtype:both] (Windows Only) +##LDPDB_RELEASE = LD option to create pdb file for release builds [/debug /pdbtype:sept /debugtype:both] (Windows Only) +##LDLOCAL = User defined C flags for linking [Empty] +##LDENV = Environment defined linker flags [Not Defined] +##LDENVFS = Environment defined linker flags per feature set [Not Defined] +##LDMOD = module level defined linker flags [Not Defined] +##LDPROJ = project level defined linker flags [Not Defined] +##LDMACH = Flags to specify machine type to linker +##LDSYS = target/platform specific Linker flags +##LDOUTPUT = platform specific linker flag to specify output file +##LDSTATIC = platform specific linker flag to specify linking only with static +## (eg. non-dynamic) libraries +##LDFLAGS = Complete set of Linker flags +##CCLIBS = basic C++ libraries (include in MODLIBS, PROJLIBS or LIBS when appropriate) +##LOCALDEPLIBS = User archive libraries to include in dependencies [Empty] +## (omit the lib prefix and .a suffix) +##LOCALLIBS = User libraries to use when linking [Empty] +## (in addition to LOCALDEPLIBS) +## (omit the lib prefix and .a suffix) +##LOCAL_LIB_DIRS = User library directories for libpaths [Empty] +##MODDEPLIBS = module level archive libraries to include in dependencies [Empty] +## (omit the lib prefix and .a suffix) +##MODLIBS = module level libraries to use when linking [Empty] +## (in addition to MODDEPLIBS) +##MOD_LIB_DIRS = module level library directories for libpaths [Empty] +##PROJDEPLIBS = project level archive libraries to include in dependencies [Empty] +## (omit the lib prefix and .a suffix) +##PROJLIBS = project level libraries to use when linking [Empty] +## (in addition to PROJDEPLIBS) +## (omit the lib prefix and .a suffix) +##PROJ_LIB_DIRS = project level library directories for libpaths [Empty] +##SYSLIBS = target/platform specific library link directives +##SYS_LIB_DIRS = target/platform specific library directories +##LD_LIB_DIRS = full list of library paths to search +##LDLIBSRCH = full link directives for library paths to search +##LDLIBS = full link directives for libraries +##DEPLIBS_TARGETS = target names for make dependencies based on archive libraries +## +##LEX = platform specific Lexical analyzer generator +##LEX_LIB = library needed by code compiled with lex +## +##LINT = platform specific Lint code analyzer +##LINTENV = Environment defined lint flags [Not Defined] +##LINTLOCAL = User defined lint flags [Empty] +##LINTMOD = module level lint flags [Not Defined] +##LINTPROJ = project level lint flags [Not Defined] +##LINTFLAGS = lint flags (includes CFLAGS) +## +## Flags for building kernel modules/drivers/kext: +##CKERNEL = C/C++ compiler flags to use +##CKERNELOPS= base C/C++ compiler flags to use [Darwin only] +##KERNEL_INCLUDE_DIRS= directories to get include files from +##KERNELLIBS = libraries to link with (and linker options) +##KERNELDIR = primary path to kernel headers/libs/etc for desired kernel version +##CPROJKERNEL= project level C compiler flags for use by individual makefiles +## as part of CLOCAL and/or CCLOCAL for makefiles building +## drivers, typically composed of $(CKERNEL) [Not Defined] +## +##MIDL = IDL compiler (Windows Only) +##MIDLSYS = Win32 specific IDL compiler flags +##MIDLLOCAL = User flags for IDL compiler [Empty] +##MIDLMOD = module level flags for IDL compiler [Not Defined] +##MIDLPROJ = project level flags for IDL compiler [Not Defined] +##MIDLENV = Environment defined IDL compiler flags [Not Defined] +##MIDLFLAGS = Complete set of IDL compiler flags +## +##REGEXE = command to update registry from a .exe file (Windows Only) +##REGDLL = command to update registry from a .dll file (Windows Only) +## +##MKSHLIB = command to build dynamic/shared library from .o's built w/CSHARED +##MKARLIB = command to build static/archive library from .o's +##MKPARTIAL = command to partially link .o's into a single .o's +##MKMODULE = command to link .o's into a single kernel module (Linux only) +##DEFFILE = definition file for dynamic/shared library used by MKSHLIB +## (Windows Only) +##IMPLIBLOCAL = User flags for Object Lirary Manager [Empty] +## +##PREP = File post-processor to prepare files for release, by marking with +## build date and version string +##PATCH_VERSION = program to patch version into data in code file +##PATCH_ENG_VERSION = program to patch version into data in code file for +## engineer non-offical builds/releases +##CONVERT_RELEASETAG= program to convert RELEASE_TAG to a doted version format +## +##RSC = resource compiler (Windows Only) +##RSCMACH = flags to specify machine type to RSC compiler +##RSCLOCAL = User flags for resource compiler [Empty] +##RSCMOD = module level flags for resource compiler [Not Defined] +##RSCPROJ = project level flags for resource compiler [Not Defined] +##RSCSYS = Win32 specific resource compiler flags +##RSCENV = Environment defined resource compiler flags [Not Defined] +##RSCFLAGS = Compile set of Resource compiler flags +## +## The parameters below control the construction of Visual Studio Project Files +## These are only used on BUILD_PLATFORMS of DOS and CYGWIN when building +## for CYGWIN, WIN32 or MIPS. +##BUILDDSW = command to build DSW file from a list of project files +##FINDDSPFILES= command to expand module names into complete pathnames +## to dsp files +##DS_PROJECT= Developer Studio Project name (set to this directory name), +## for use in .dsp and .dsw filenames +##DS_SUBPROJECTS= User specified other dsp files to include as subprojects +## in dsw. [Not Defined] +## These must be pathnames relative to TL_DIR. They can be +## directory names (in which case the .dsp is assumed to have the +## same basename as the directory) or dsp filenames. +##DS_PROJECTS= Base set of projects to include in all dsw files +##DSP_SOURCES= User specified list of source files, in the present directory +## which are to be included in the dsp file [Not Defined] +##DSP_FILE = dsp file to build +##DSP_TMP_FILE=temp dsp file to build to +##DSW_FILE = dsw file to build +##DSW_TMP_FILE= temp dsw file to build to +##DSP_SRC_DIR= Source directory to use for files in this directory +##DSP_GROUP = Group name to use for this source directory in dsp file +## +##FUTURE - on windows allow PCH_TARGET to be defined, which will cause a +## precompiled header to be built or used +## PCHFLAGS - compiler files to make PCH_TARGET into a precompiled header +## FUTURE - support SUSYSTEM=posix on Windows +## FUTURE - rename DEPLIBS as DEPARLIBS and DEPSHLIBS if need to support +## dependent shared libraries +## +#=============================================================================# diff --git a/Makerules/Rules.CYGWIN b/Makerules/Rules.CYGWIN new file mode 100755 index 0000000..12447d8 --- /dev/null +++ b/Makerules/Rules.CYGWIN @@ -0,0 +1,37 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** +# paths to libraries when BUILD_PLATFORM=CYGWIN +# rules when building on cygwin + +ULOCAL_LIB_DIRS=$(foreach path,$(LOCAL_LIB_DIRS),$(subst c:,/cygdrive/c,$(path))) +UMOD_LIB_DIRS=$(foreach path,$(MOD_LIB_DIRS),$(subst c:,/cygdrive/c,$(path))) +UPROJ_LIB_DIRS=$(foreach path,$(PROJ_LIB_DIRS),$(subst c:,/cygdrive/c,$(path))) + +vpath %$(ARLIB_SUFFIX) $(ULOCAL_LIB_DIRS) $(UMOD_LIB_DIRS) $(UPROJ_LIB_DIRS) +vpath %$(SHLIB_SUFFIX) $(ULOCAL_LIB_DIRS) $(UMOD_LIB_DIRS) $(UPROJ_LIB_DIRS) diff --git a/Makerules/Rules.Common b/Makerules/Rules.Common new file mode 100755 index 0000000..5c17e96 --- /dev/null +++ b/Makerules/Rules.Common @@ -0,0 +1,941 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** +#=============================================================================# +# +# Common Rules +# +#=============================================================================# +## The global makerules file also contains the following basic make target +## rules for simplifying application build processes: +## +## stage:: This extensible target should be overridden in the local makefile +## to provide staging of the application. The local makefile should +## make reference to staging variables which should be defined in the +## project level makerules file. The stage target depends on a +## successful completion of the all target. +## To allow integration with developer studio (which does not allow +## custom build tool options for the incremental build case) +## this target should be the first target in the makefile +## stream and will be if this makerules file is included before the rules +## section of any project makerules file or local makefile. +## STAGE:: The purpose of this extensible target +## is to stage all of the application target objects including +## executable(s) and readme file(s). +## This target is strictly for internal use within a makefile +## +## prepfiles_global:: This extensible target is used to prep file stage +## directory. It should be a dependent of prepfiles in the topmost makefile +## for a project. +## +## vars_include_global:: This extensible target is used to create +## ./vars_include file listing variables often needed by runmake scripts +## It should be a dependent of var_include in the topmost makefile +## for a project. +## +## clobber_vars_include:: This extensible target is used to remove the +## ./vars_include file. +## It should be a dependent of clobber in the topmost makefile +## for a project or may be invoked by runmake for products which iterate +## on clobbering and rebuilding for a variety of configurations. +## +## all: The purpose of +## the all target is to optionally build the depend.mk makefile +## (which includes dependencies) and all of the application target objects +## including executable(s) and readme file(s) (ALL). +## This target is strictly for use as an argument to make. +## Individual makefiles should not define this target. +## +## ALL:: The purpose of this extensible target +## is to build all of the application target objects including +## executable(s) and readme file(s). +## This target is strictly for internal use within a makefile +## +## check_target: This non-extensible target will verify that the BUILD_TARGET +## environment variable is defined and can be used as a dependency for +## use in project or local makefiles. The target validates the +## value of the variable. The BUILD_TARGET variable +## should be set by the target command prior to running make. +## +## clean: This target is used to remove all intermediate files +## created during the build process. All object $(OBJECTS) and core files will +## automatically removed along with those defined in OBJECTS and +## CLEAN_TARGETS. (it does this by running CLEAN). +## This target is strictly for use as an argument to make. +## Individual makefiles should not define this target. +## +## CLEAN:: This extensible target is used to remove all intermediate files +## created during the build process. All object $(OBJECTS) and core files will +## automatically removed along with those defined in OBJECTS and +## CLEAN_TARGETS. +## This target is strictly for internal use within a makefile +## +## cleandepend: This target is used to remove targets built +## by the depend target (or automatically built if AUTODEP!=no). +## It is useful when external factors invalidate the results of the +## depend target. (It does this by running CLEANDEPEND). +## This target is strictly for use as an argument to make. +## Individual makefiles should not define this target. +## +## CLEANDEPEND:: This extensible target is used to remove targets built +## by the depend target (or automatically built if AUTODEP!=no). +## It is useful when external factors invalidate the results of the +## depend target +## This target is strictly for internal use within a makefile +## +## clobber: This extensible target is used to remove all intermediate and +## target files and should restore the directory to a checkout state where +## only source files exist. This target has a dependency on the clean +## and ClOBBER targets, and removes CLOBBER_TARGETS and MISC_TARGETS files. +## CLOBBER:: This extensible target is used to remove target files +## created during the build process. +## This target is strictly for internal use within a makefile +## +## clobber_global:: This extensible target is used to remove the GLOBAL_X +## directories. It should be a dependent of clobber in the topmost makefile +## for a project. +## +## clobber_module:: This extensible target is used to remove the MOD_X +## directories. It should be a dependent of clobber in the topmost makefile +## for a module. Only MOD_X directories whose names don't match the +## corresponding PROJ_X directories will be removed. +## +## clobber_bsp_specific:: This extensible target is used to perform a clobber +## in the BSP_SPECIFIC_DIRS. Useful between BSP builds during weeklybuild +## so that only the BSP specific directories are clobbered +## +## clobber_dsfiles:: This extensible target is used to remove the dsp and dsw +## files built by dsfiles. It purposely does not remove the +## ncb, plg and opt files which are used to retain the present dsw views +## +## clobber_stage:: This extensible target is used to remove the STAGE_DIR +## directories and related packaging files. +## It should be a dependent of clobber in the topmost makefile +## for a project or may be invoked by runmake for products which iterate +## on clobbering and rebuilding for a variety of configurations. +## +## clobber_release:: This extensible target is used to remove the RELEASE_DIR +## directories and related packaging files. +## It should be a dependent of clobber in the topmost makefile +## for a project or may be invoked by runmake for products which iterate +## on clobbering and rebuilding for a variety of configurations. +## +## depend:: This extensible target will update the project dependencies in +## the local makefile provided that the MAKEFILE variable is set to the +## name of the local makefile (default: "Makfile"). To accomplish this, +## the target uses MAKEDEPEND with the output placed in the file MAKEFILE. +## +## force:: This extensible target is used to force a rebuild of the entire +## application by performing a clobber operation and then building the +## all target. With a properly constructed makefile, all targets and +## intermediates will be removed leaving only source. When all is made, +## all targets should be rebuilt from scratch. +## +## INSTALL:: This extensible target should be overridden in the local makefile +## to provide installation of the application. The local makefile should +## make reference to installation variables which should be defined in the +## project level makerules file. The install target depends on a +## successful completion of the all target. +## +## lint:: This extensible target is used to lint the CFILES and create lint.res +## +## cflow:: This extensible target is used to cflow the CFILES and create +## cflow.res +## +## dsfiles:: This target creates the dsp and dsw files for Visual Studio +## build_dsfiles: performs dsfiles iteratively throughout the subdirs +## dsp_file: This target creates the dsp file for Visual Studio for this directory only +## dsw_file: This target creates the dsw file for Visual Studio for this directory only +## +#=============================================================================# +# The following section contains a list of standard targets which will be used + +#default target is ALL +# project level makefiles will provide a default of stage by declaring it +# in the makefile itself before including this file +all:: + +include $(TL_DIR)/Makerules/Rules.$(BUILD_PLATFORM) + +# libsonly and cmdsonly versions are for use in recursive makes to avoid +# repeating steps. recursive makes will recurse on includes, then on +# libsonly, then on cmdsonly, then on STAGE +ifeq ($(MAKECMDGOALS),clobber) +AUTODEP=no +endif +ifeq ($(MAKECMDGOALS),INCLUDES) +AUTODEP=no +endif +ifeq ($(MAKECMDGOALS),includes) +AUTODEP=no +endif +ifeq "$(AUTODEP)" "no" + all:: check_env ALL + includes: check_env INCLUDES + libs: check_env INCLUDES LIBS + libsonly: check_env LIBS + cmds: check_env INCLUDES LIBS CMDS + cmdsonly: check_env CMDS +else # AUTODEP + all:: check_env buildall + includes: check_env buildincludes + libs: check_env buildlibs + libsonly: check_env buildlibsonly + cmds: check_env buildcmds + cmdsonly: check_env buildcmdsonly +endif #AUTODEP +.PHONY: libsonly cmdsonly + +DEPEND_MK_FILE = $(BUILDDIR)/depend.mk + +buildincludes: INCLUDES +buildlibs: $(DEPEND_MK_FILE) + $(MAKE) -f $(DEPEND_MK_FILE) INCLUDES LIBS +buildlibsonly: $(DEPEND_MK_FILE) + $(MAKE) -f $(DEPEND_MK_FILE) LIBS +buildcmds: $(DEPEND_MK_FILE) + $(MAKE) -f $(DEPEND_MK_FILE) INCLUDES LIBS CMDS +buildcmdsonly: $(DEPEND_MK_FILE) + $(MAKE) -f $(DEPEND_MK_FILE) CMDS +buildall: $(DEPEND_MK_FILE) + $(MAKE) -f $(DEPEND_MK_FILE) ALL + +.PHONY: INCLUDES LIBS CMDS +.PHONY: includes imports libs cmds +.PHONY: buildincludes buildimports buildlibs buildlibsonly buildcmds buildcmdsonly buildall check_env + +check_env:: check_target check_config check_platform check_subsystem check_usemfc check_windbase check_mipspath check_i386path check_target_bsp + +ALL:: INCLUDES LIBS CMDS + @echo "Product(s) Built" + +clean:: CLEAN +CLEAN:: + @echo "Removing Intermediate Files" + -$(VS)$(RM) $(RMFORCE) $(OBJECTS) $(PREPROCESSED_FILES) $(CLEAN_TARGETS) $(INC_FILE) $(LIB_FILE) $(BIN_FILE) core .ICSBOOTROMVERSIONSTRING + ifneq "$(RSCOBJECTS)" "" + -$(VS)$(RM) $(RMFORCE) $(RSCOBJECTS) + endif + +clobber:: check_env CLEANDEPEND CLEAN CLOBBER +CLOBBER:: + @echo "Removing Target/Build Files" + -$(VS)$(RM) $(RMFORCE) $(RMRECURSE) $(CLOBBER_TARGETS) + +check_brand:: + ifneq "$(BRANDIT)" "" + BRAND_DIRS := $(BRANDIT) + endif +.PHONY: check_brand + + +#FIXME - this CARD_TYPE check should be cleaned up +prepfiles:: +# use of PATCH_VERSION below is a quick hack. Really project makefile +# should decide what to patch. But this works for now +ifeq "$(CARD_TYPE)" "X" +prepfiles_global:: check_env check_brand + cd $(PROJ_STAGE_DIR) && find . -print| $(PREP) + -cd $(PROJ_STAGE_BIN_DIR) && $(PATCH_VERSION) -n `$(CONVERT_RELEASETAG) $(RELEASE_TAG)` $(RELEASE_TAG) * + -if [ -n "$(BRANDIT)" ]; then \ + for x in $(BRAND_DIRS);\ + do\ + y=`echo $$x | sed 's/_/ /g'`;\ + imgU=`which icsImageUtil`;\ + rm -rf $(PROJ_STAGE_BIN_DIR)_$$x;\ + cp -r $(PROJ_STAGE_BIN_DIR) $(PROJ_STAGE_BIN_DIR)_$$x;\ + cd $(PROJ_STAGE_BIN_DIR)_$$x;\ + bspcode=`$$imgU -d *.pkg| awk -F= ' /BSP/ {print $$NF}' | sed 's/[^0-9]//g'`;\ + rm -rf *.pkg;\ + $(PATCH_BRAND) "$$y" *;\ + mkpkg `ls | sed '/.*\..*\..*/d'` $(CARD_TYPE) $(TARGET_BSP) $(PRODUCT_CODE) $$bspcode $(STRIP) $(DEFLATE);\ + rm -rf *.Z *.stripped;\ + done;\ + fi +else +prepfiles_global:: check_env check_brand + cd $(PROJ_STAGE_DIR) && find . -print| $(PREP) + -cd $(PROJ_STAGE_BIN_DIR) && $(PATCH_VERSION) -n `$(CONVERT_RELEASETAG) $(RELEASE_TAG)` $(RELEASE_TAG) * + -if [ -n "$(BRANDIT)" ]; then \ + for x in $(BRAND_DIRS);\ + do\ + y=`echo $$x | sed 's/_/ /g'`;\ + imgU=`which icsImageUtil`;\ + rm -rf $(PROJ_STAGE_BIN_DIR)_$$x;\ + cp -r $(PROJ_STAGE_BIN_DIR) $(PROJ_STAGE_BIN_DIR)_$$x;\ + cd $(PROJ_STAGE_BIN_DIR)_$$x;\ + bspcode=`$$imgU -d *.pkg| awk -F= ' /BSP/ {print $$NF}' | sed 's/[^0-9]//g'`;\ + rm -rf *.pkg;\ + $(PATCH_BRAND) "$$y" *;\ + mkpkg `ls | sed '/.*\..*\..*/d'` $(PROJECT_PACKAGE_EXTERNAL_NAME) $(TARGET_BSP) $(PRODUCT_CODE) $$bspcode $(STRIP) $(DEFLATE);\ + rm -rf *.Z *.stripped;\ + done;\ + fi +endif +.PHONY: prepfiles_global + +vars_include_global:: check_env + rm -f vars_include + echo STAGE_DIR='$(STAGE_DIR)' >> vars_include + echo STAGE_SUB_DIR='$(STAGE_SUB_DIR)' >> vars_include + echo PROJ_STAGE_DIR='$(PROJ_STAGE_DIR)' >> vars_include + echo RELEASE_DIR='$(RELEASE_DIR)' >> vars_include + $(CHMOD) +x vars_include +# marked as phony so we force rebuild each time asked +.PHONY: vars_include_global + +clobber_vars_include:: check_env + rm -f vars_include +.PHONY: clobber_vars_include + +clobber_global:: check_env + -$(VS)$(RM) $(RMFORCE) $(RMRECURSE) $(GLOBAL_INCLUDE_DIR) + -$(VS)$(RM) $(RMFORCE) $(RMRECURSE) $(GLOBAL_LIB_DIR) + -$(VS)$(RM) $(RMFORCE) $(RMRECURSE) $(GLOBAL_SHLIB_DIR) + -$(VS)$(RM) $(RMFORCE) $(RMRECURSE) $(GLOBAL_BIN_DIR) + -$(VS)$(RM) $(RMFORCE) $(RMRECURSE) $(GLOBAL_SBR_DIR) + +clobber_module:: check_env +ifneq "$(MOD_INCLUDE_DIR)" "$(PROJ_INCLUDE_DIR)" + -$(VS)$(RM) $(RMFORCE) $(RMRECURSE) $(MOD_INCLUDE_DIR) +endif +ifneq "$(MOD_LIB_DIR)" "$(PROJ_LIB_DIR)" + -$(VS)$(RM) $(RMFORCE) $(RMRECURSE) $(MOD_LIB_DIR) +endif +ifneq "$(MOD_SHLIB_DIR)" "$(PROJ_SHLIB_DIR)" + -$(VS)$(RM) $(RMFORCE) $(RMRECURSE) $(MOD_SHLIB_DIR) +endif +ifneq "$(MOD_BIN_DIR)" "$(PROJ_BIN_DIR)" + -$(VS)$(RM) $(RMFORCE) $(RMRECURSE) $(MOD_BIN_DIR) +endif +ifneq "$(MOD_SBR_DIR)" "$(PROJ_SBR_DIR)" + -$(VS)$(RM) $(RMFORCE) $(RMRECURSE) $(MOD_SBR_DIR) +endif +.PHONY: clobber_module + +clobber_stage:: check_env + -$(VS)$(RM) $(RMFORCE) $(RMRECURSE) $(STAGE_DIR) + +clobber_release:: check_env + -$(VS)$(RM) $(RMFORCE) $(RMRECURSE) $(RELEASE_DIR) + +#release:: check_env +# cd $(PROJ_STAGE_INCLUDE_DIR) && $(INSTALL) -d $(PROJ_RELEASE_INCLUDE_DIR) * +# cd $(PROJ_STAGE_LIB_DIR) && $(INSTALL) -d $(PROJ_RELEASE_LIB_DIR) * +# cd $(PROJ_STAGE_BIN_DIR) && $(INSTALL) -d $(PROJ_RELEASE_BIN_DIR) * +# cd $(PROJ_STAGE_SBR_DIR) && $(INSTALL) -d $(PROJ_RELEASE_SBR_DIR) * +#.PHONY: release + +cleandepend:: check_env CLEANDEPEND +CLEANDEPEND:: + @echo "Removing Generated Dependency Files" + -$(VS)$(RM) $(RMFORCE) $(DEPEND_MK_FILE) $(DEPEND_MK_FILE).bak $(addsuffix .dep,$(SOURCES)) $(addsuffix .dep.bak,$(SOURCES)) + +depend:: check_env $(DEPEND_MK_FILE) + +# This was kind of a kludge to get things going, dependences may depend on +# include files be available. For a top level makefile which has source files +# this can cause a catch 22, those files will fail to build since the +# INCLUDES pass have not been done on the subdirs. However this approach +# adds overhead. A better fix is for top level directories to not have code +# instead a Main module could be included below it which actually builds the +# executable. In which case INCLUDES below can be removed! +#depend.mk: INCLUDES $(MAKEFILE) $(addsuffix .dep,$(SOURCES)) +DEPEND_FILES = $(foreach dep, $(addsuffix .dep,$(SOURCES)), $(BUILDDIR)/$(dep)) + +$(DEPEND_MK_FILE): $(MAKEFILE) $(DEPEND_FILES) $(BUILDDIR) + @echo "Updating Makefile Dependencies" + $(VS)> $(DEPEND_MK_FILE) + $(VS)$(CHMOD) 666 $(DEPEND_MK_FILE) + $(VS)for f in $^ ;\ + do \ + if [ ! -d $$f ]; then \ + $(ECHO) "include $$f" >> $(DEPEND_MK_FILE) ;\ + fi \ + done + +$(BUILDDIR): + @mkdir -p $@ + + +.SUFFIXES: .dep +%.cpp.dep: %.cpp + @echo "Updating $< Dependencies" +ifeq "$(BUILD_TARGET_OS)" "WIN32" + $(VS)$(MAKEDEPEND) -p /usr/bin -f $@ -- $(CCDEPENDFLAGS) -- $< + @$(RM) $(RMFORCE) $@.bak +else + $(CCC) $(CCDEPENDFLAGS) -MM $< > $@ +ifneq "$(CARD_TYPE)" "" + $(STRIPDEPENDS) $@ +endif +endif + +%.c.dep: %.c + @echo "Updating $< Dependencies" +ifeq "$(BUILD_TARGET_OS)" "WIN32" + $(VS)$(MAKEDEPEND) -p /usr/bin -f $@ -- $(DEPENDFLAGS) -- $< + @$(RM) $(RMFORCE) $@.bak +else + $(CC) $(DEPENDFLAGS) -MM $< > $@ +ifneq "$(CARD_TYPE)" "" + $(STRIPDEPENDS) $@ +endif +endif + + +ifneq "$(strip $(BUILDDIR))" "" +$(BUILDDIR)/%.c.dep: %.c + @echo "Updating $< Dependencies" + @mkdir -p $(dir $@) + $(CC) $(DEPENDFLAGS) -MT $(BUILDDIR)/$*.o -MM $< > $@ +ifneq "$(CARD_TYPE)" "" + $(STRIPDEPENDS) $@ +endif +$(BUILDDIR)/%.cpp.dep: %.cpp + @echo "Updating $< Dependencies" + @mkdir -p $(dir $@) + $(CC) $(CCDEPENDFLAGS) -MT $(BUILDDIR)/$*.o -MM $< > $@ +ifneq "$(CARD_TYPE)" "" + $(STRIPDEPENDS) $@ +endif +endif + +.SUFFIXES: .gz .1 .8 .manPage +%.gz: % + $(GZIP) $< +%.1: %.manPage + $(CP) $< $@ +%.8: %.manPage + $(CP) $< $@ + + +# Rules for buildFeatureDefs + +# create buildFeatureDefs using unifdef2.sh + +#$(TL_DIR)/buildFeatureDefs: $(TL_DIR)/Fd/buildFeatureDefs.base +# $(TL_DIR)/MakeTools/unifdef2.sh $(OPA_FEATURE_SET) $< $@ + +# Rules for base files + +# create file from base file using unifdef2.sh + +%: %.base + $(TL_DIR)/MakeTools/unifdef2.sh $(OPA_FEATURE_SET) $< $@ +%.sh: %.sh.base + $(TL_DIR)/MakeTools/unifdef2.sh $(OPA_FEATURE_SET) $< $@ +%.xlsx: %.xlsx.$(OPA_FEATURE_SET) + cp $< $@ + + +# TBD - makerules.build has this rule in it +#ifeq "$(BUILD_TARGET_OS)" "LINUX" +#lib%.so : %.o +# $(MKSHLIB) $^ $(LDLOCAL) $(LDLIBS) -o $@ +#endif # BUILD_TARGET_OS is LINUX + +force:: clobber all + +stage:: check_env all + @echo "Staging Product(s)" +stage:: STAGE + +# special target for boot loaders +stageboot:: check_env + @echo "Staging Bootloader Product(s)" +stageboot:: STAGEBOOT +.PHONY: stageboot + +runtest:: check_env all + @echo "Running Unit Test(s)" +runtest:: RUNTEST + +install:: check_env stage + @echo "Building Installable Product(s)" +install:: INSTALL + +lint:: check_env $(CFILES) + $(LINT) $(LINTFLAGS) $(CFILES) > lint.res 2>&1 + +cflow:: check_env $(CFILES) + $(LINT) $(CFLOWFLAGS) $(CFILES) > cflow.res 2>&1 + + +.PHONY: ALL all clean clobber depend force stage install runtest lint cflow \ + clobber_global clobber_stage clobber_release finish \ + cleandepend CLEAN CLEANDEPEND CLOBBER + +.SUFFIXES: .lex $(OBJ_SUFFIX) $(PRE_SUFFIX) +%$(OBJ_SUFFIX) : %.cpp + $(VS)$(CCC) $(CCFLAGS) -c $< +%$(OBJ_SUFFIX) : %.c + $(VS)$(CC) $(CFLAGS) -c $< +%$(PRE_SUFFIX) : %.cpp + $(VS)$(CCC) $(CCFLAGS) -E $< > $@ +%$(PRE_SUFFIX) : %.c + $(VS)$(CC) $(CFLAGS) -E $< > $@ + +$(BUILDDIR)/%$(OBJ_SUFFIX) : %.cpp + @mkdir -p $(dir $@) + $(VS)$(CCC) $(CCFLAGS) -c $< -o $@ +$(BUILDDIR)/%$(OBJ_SUFFIX) : %.c + @mkdir -p $(dir $@) + $(VS)$(CC) $(CFLAGS) -c $< -o $@ +$(BUILDDIR)/%$(OBJ_SUFFIX) : $(BUILDDIR)/%.s + @mkdir -p $(dir $@) + $(VS)$(CC) $(CFLAGS) -c $< -o $@ +$(BUILDDIR)/%$(PRE_SUFFIX) : %.cpp + @mkdir -p $(dir $@) + $(VS)$(CCC) $(CCFLAGS) -E $< > $@ +$(BUILDDIR)/%$(PRE_SUFFIX) : %.c + @mkdir -p $(dir $@) + $(VS)$(CC) $(CFLAGS) -E $< > $@ +ifeq "$(BUILD_TARGET_OS)" "VXWORKS" +$(BUILDDIR)/Config.h : Config.h.in $(TL_DIR)/BSP/Config.csv $(BUILDDIR) + $(VS)$(MKCONFIG) $(TARGET_BSP) $(PRODUCT) $(TL_DIR)/BSP/Config.csv Config.h.in $@ +endif + +.lex.c: + @rm -f $@ + $(LEX) $< + mv lex.yy.c $@ + + +.SUFFIXES: .msg _Messages.h _Messages.c +%_Messages.h %_Messages.c: %.msg $(BUILDMSGS_PL) + $(VS)$(BUILDMSGS) $< + +#.y.c: +# $(YACC) -d $< +# mv y.tab.c $@ + + + +ifneq "$(strip $(BUILDDSW))" "" +# optimize performance when not doing dsp files, by skipping this $(shell) +ifneq "$(strip $(DO_DSP_SUBPROJECTS))" "" +# we have a dependency on the subprojects by our dsw file +# this rule will rebuild the missing subprojects +DSP_SUBPROJECTS= $(foreach dir,$(DIRS),$(DS_PROJECT_DIR)/$(dir)/$(dir)$(DSP_SUFFIX)) $(shell $(FINDDSPFILES) $(DS_SUBPROJECTS) $(DS_PROJECTS)) + +$(DSP_SUBPROJECTS): + cd $(@D) && $(MAKE) dsp_file +endif # DO_DSP_SUBPROJECTS + +# don't build dsw_file if no project defined +ifneq "$(DS_PROJECT)" "" +# paths given to BUILDDSW go into a dsw file, hence they must be windows paths +# but we can get away with forward slashes +dsw_file: + $(MAKE) DO_DSP_SUBPROJECTS=yes DSW_FILE +DSW_FILE: $(DSP_SUBPROJECTS) $(DSW_FILE) +$(DSW_FILE): $(MAKEFILE) + @echo "Building Dev Studio Workspace file ($(DSW_FILE))..." + $(VS)$(RM) $(RMFORCE) $(DSW_TMP_FILE) +ifneq "$(BUILD_PLATFORM)" "LINUX" +ifneq "$(BUILD_PLATFORM)" "DARWIN" + $(VS)$(BUILDDSW) -f $(DSW_TMP_FILE) $(DSP_FILE) $(foreach path,$(DSP_SUBPROJECTS),$(subst \,/,$(shell cygpath -w $(path)))) +else + $(VS)$(BUILDDSW) -f $(DSW_TMP_FILE) $(DSP_FILE) $(DSP_SUBPROJECTS) +endif +else + $(VS)$(BUILDDSW) -f $(DSW_TMP_FILE) $(DSP_FILE) $(DSP_SUBPROJECTS) +endif # LINUX + $(VS)$(MV) -f $(DSW_TMP_FILE) $(DSW_FILE) +else +dsw_file: + @echo "DS_PROJECT undefined, Can't Build Dev Studio Workspace file" +endif # DS_PROJECT + +# The building of dsp files is a little involved, however all this work +# makes it easy to keep the dsp consistent with the makefiles +# The build proceeds as follows: +# In makefile dsp is being built for: +# dsp_file - main summary target +# dsp_header - customize the generic dsp boilerplate to DSP_TMP_FILE +# using MAKE and DS_PROJECT +# dsp_group - summary target for building a group in dsp file +# dsp_group_header - output #Begin Group directive to DSP_TMP_FILE +# dsp_body - output source file directives for each entry in DSP_SOURCES +# recursively do a make dsp_group on sub-directories +# setting DSP_GROUP and DSP_TMP_FILE with the appropriate +# relative path settings +# dsp_group_trailer - output #End Group to DSP_TMP_FILE +# dsp_trailer - output generic end of dsp boilerplate to DSP_TMP_FILE +# and rename DSP_TMP_FILE as DSP_FILE to its now visible to VS +# file rename is done at the end so that Visual Studio will not see the +# updates until the new dsp file is completely written +# Note the recusive make invokation allows the make system to automatically +# generate a dsp group heirarchy which exactly matches the source tree + +dsp_header: + @echo "Building Dev Studio Project file ($(DSP_FILE))..." + $(VS)$(RM) $(RMFORCE) $(DSP_TMP_FILE) + $(VS)$(SED) \ + -e 's|ProjectTemplate|$(DS_PROJECT)|g' \ + -e 's|ProjectMake|icstargetmake $(BUILD_TARGET)|g' \ + -e 's|ProjectExecute|$(EXECUTABLE)|g' \ + < $(TL_DIR)/Makerules/template.dsp \ + > $(DSP_TMP_FILE) + +dsp_group_header: + ifneq "$(DSP_GROUP)" "" + $(VS)$(ECHO) '# Begin Group "'$(DSP_SRC_DIR)'"' >> $(DSP_TMP_FILE) + endif #DSP_GROUP + +dsp_body:: + $(VS)for d in $(DSP_SOURCES) ;\ + do \ + $(ECHO) '# Begin Source File' >> $(DSP_TMP_FILE) ;\ + $(ECHO) "SOURCE=$(DSP_SRC_DIR)/$$d" >> $(DSP_TMP_FILE) ;\ + $(ECHO) '# End Source File' >> $(DSP_TMP_FILE) ;\ + done + +dsp_group_trailer: + ifneq "$(DSP_GROUP)" "" + $(VS)$(ECHO) '# End Group' >> $(DSP_TMP_FILE) + endif #DSP_GROUP + +dsp_trailer: + $(VS)$(ECHO) '# End Target' >> $(DSP_TMP_FILE) + $(VS)$(ECHO) '# End Project' >> $(DSP_TMP_FILE) + $(VS)$(MV) -f $(DSP_TMP_FILE) $(DSP_FILE) + +dsp_group:: dsp_group_header dsp_body dsp_group_trailer +# don't build dsp_file if no project defined +ifneq "$(DS_PROJECT)" "" +dsp_file: $(DSP_FILE) +# for toplevel/middle makefile, always rebuild dsp (can't be sure if sub-dirs makefiles have changed) +# for local makefile, only rebuild dsp if makefile has changed +ifneq "$(strip $(DIRS))" "" +$(DSP_FILE): dsp_header dsp_group dsp_trailer +else +$(DSP_FILE): $(MAKEFILE) + $(VS)$(MAKE) dsp_header dsp_group dsp_trailer +endif # DIRS +else +dsp_file: + @echo "DS_PROJECT undefined, Can't Build Dev Studio Project file" +endif # DS_PROJECT +build_dsfiles:: dsfiles +dsfiles:: check_env dsp_file dsw_file +clobber_dsfiles:: check_env + @echo "Removing Developer Studio Project and Workspace Files" +ifneq "$(DS_PROJECT)" "" + $(VS)$(RM) $(RMFORCE) $(DSP_FILE) $(DSP_TMP_FILE) $(DSW_FILE) $(DSW_TMP_FILE) +endif # DS_PROJECT + + +.PHONY: dsfiles dsp_file dsw_file dsp_group dsp_group_header \ + dsp_group_trailer dsp_header dsp_body dsp_trailer clobber_dsfiles +else # BUILDDSW not defined +build_dsfiles:: dsfiles +dsfiles:: + @echo "Can't Build Dev Studio Project files in $(BUILD_PLATFORM) for $(BUILD_TARGET)" +dsw_file: + @echo "Can't Build Dev Studio Project files in $(BUILD_PLATFORM) for $(BUILD_TARGET)" +dsp_file: + @echo "Can't Build Dev Studio Project files in $(BUILD_PLATFORM) for $(BUILD_TARGET)" +clobber_dsfiles:: + @echo "Removing Developer Studio Project and Workspace Files" +ifneq "$(DS_PROJECT)" "" + $(VS)$(RM) $(RMFORCE) $(DSP_FILE) $(DSP_TMP_FILE) $(DSW_FILE) $(DSW_TMP_FILE) +endif # DS_PROJECT + +endif # BUILDDSW defined + +#=============================================================================# +# +# Platform specific Rules +# +#=============================================================================# + +ifeq "$(BUILD_TARGET_OS)" "WIN32" +.SUFFIXES: .rc .res .sbr .bsc +%.res:%.rc + $(VS)$(RSC) $(RSCFLAGS) /fo"$@" $< +%.sbr:%.cpp + $(VS)$(CCC) $(CCFLAGS) -c $< +%.sbr:%.c + $(VS)$(CC) $(CFLAGS) -c $< +%.bsc:%.sbr + $(VS)$(BSC) $(BSCFLAGS)$@ $< +endif # BUILD_TARGET_OS is WIN32 + +#-----------------------------------------------------------------------------# +# Check the environment for the BUILD_TARGET variable for validity + +SUPPORTED_TARGETS = ATOM MIPS I386 IA32 IA64 MIPS_BSP CYGWIN WIN32 X86_64 PPC PPC64 EM64T +badtarget: + @echo "Invalid BUILD_TARGET value was specified: $(BUILD_TARGET)" + @echo "Must be one of: $(SUPPORTED_TARGETS)" + @echo "Please run the target shell function and try again." + @exit 1 +ifeq "$(strip $(BUILD_TARGET))" "" +check_target: badtarget +else +ifneq "$(findstring $(BUILD_TARGET),$(SUPPORTED_TARGETS))" "$(BUILD_TARGET)" +check_target: badtarget +else +check_target: +endif # BUILD_TARGET in SUPPORTED_TARGETS +endif # BUILD_TARGET defined +.PHONY: check_target +#-----------------------------------------------------------------------------# +# Check the environment for the BUILD_CONFIG variable for validity +ifeq "$(BUILD_TARGET_OS)" "VXWORKS" +SUPPORTED_CONFIGS = debug release loadable +else + +SUPPORTED_CONFIGS = debug release +endif +badconfig: + @echo "Invalid BUILD_CONFIG value was specified: $(BUILD_CONFIG)" + @echo "Must be one of: $(SUPPORTED_CONFIGS)" + @echo "Please set BUILD_CONFIG and try again." + @exit 1 +ifeq "$(strip $(BUILD_CONFIG))" "" +check_config: badconfig +else +ifneq "$(findstring $(BUILD_CONFIG),$(SUPPORTED_CONFIGS))" "$(BUILD_CONFIG)" +check_config: badconfig +else +check_config: +endif # BUILD_CONFIG in SUPPORTED_CONFIGS +endif # BUILD_CONFIG defined +.PHONY: SUPPORTED_CONFIGS check_config + +ifeq "$(BUILD_TARGET_OS)" "WIN32" +#-----------------------------------------------------------------------------# +# Check the environment for the SUBSYSTEM variable for validity +SUPPORTED_SUBSYSTEMS = none console windows +badsubsystem: + @echo "Invalid SUBSYSTEM value was specified: $(SUBSYSTEM)" + @echo "Must be one of: $(SUPPORTED_SUBSYSTEMS)" + @echo "Please check your configuration and try again." + @exit 1 +ifneq "$(findstring $(SUBSYSTEM),$(SUPPORTED_SUBSYSTEMS))" "$(SUBSYSTEM)" +check_subsystem: badsubsystem +else +check_subsystem: +endif # SUBSYSTEM in SUPPORTED_SUBSYSTEMS +else +check_subsystem: +endif # BUILD_TARGET_OS of WIN32 +.PHONY: check_subsystem + +ifeq "$(BUILD_TARGET_OS)" "WIN32" +#-----------------------------------------------------------------------------# +# Check the environment for the USEMFC variable for validity +SUPPORTED_USEMFCS = none no_mfc shared static +badusemfc: + @echo "Invalid USEMFC value was specified: $(USEMFC)" + @echo "Must be one of: $(SUPPORTED_USEMFCS)" + @echo "Please check your configuration and try again." + @exit 1 +ifneq "$(findstring $(USEMFC),$(SUPPORTED_USEMFCS))" "$(USEMFC)" +check_usemfc: badusemfc +else +check_usemfc: +endif # USEMFC in SUPPORTED_USEMFCS +else +check_usemfc: +endif # BUILD_TARGET_OS of WIN32 +.PHONY: check_usemfc +#-----------------------------------------------------------------------------# + +ifeq "$(BUILD_TARGET_OS)" "VXWORKS" +#-----------------------------------------------------------------------------# +# Check the environment for the TARGET_BSP variable for validity +# TBD - this dumps the shell, hardcode possible BSPs for now +CAT?=cat +SUPPORTED_TARGET_BSPS = $(shell $(CAT) $(TL_DIR)/$(PROJ_FILE_DIR)/SUPPORTED_TARGET_BSPS) +badtarget_bsp: + @echo "Invalid TARGET_BSP value was specified: $(TARGET_BSP)" + @echo "Must be one of: $(SUPPORTED_TARGET_BSPS)" + @echo "Please check your configuration and try again." + @exit 1 +ifeq "$(strip $(TARGET_BSP))" "" +check_target_bsp: badtarget_bsp +else +ifneq "$(findstring $(TARGET_BSP),$(SUPPORTED_TARGET_BSPS))" "$(TARGET_BSP)" +check_target_bsp: badtarget_bsp +else +check_target_bsp: +endif # TARGET_BSP in SUPPORTED_TARGET_BSPS +endif # TARGET_BSP defined +else +check_target_bsp: +endif # BUILD_TARGET_OS of VXWORKS +.PHONY: check_target_bsp + +#-----------------------------------------------------------------------------# +# Check the environment for the BUILD_PLATFORM variable for validity +# BUILD_PLATFORM is set within this rules file based on "uname -s" + +SUPPORTED_PLATFORMS = CYGWIN LINUX DOS DARWIN +badplatform: + @echo "Invalid BUILD_PLATFORM value was specified: $(BUILD_PLATFORM)" + @echo "Must be one of: $(SUPPORTED_PLATFORMS)" + @echo "Please update the make files to support this platform and try again." + @exit 1 +ifeq "$(strip $(BUILD_PLATFORM))" "" +check_platform: badplatform +else +ifneq "$(findstring $(BUILD_PLATFORM),$(SUPPORTED_PLATFORMS))" "$(BUILD_PLATFORM)" +check_platform: badplatform +else +check_platform: +endif # BUILD_PLATFORM in SUPPORTED_PLATFORMS +endif # BUILD_PLATFORM defined +.PHONY: check_platform + +#-----------------------------------------------------------------------------# +# Check the environment for the WIND_BASE variable begin set + +ifeq "$(BUILD_TARGET_OS)" "VXWORKS" +badwindbase: + @echo "WIND_BASE value was not defined" + @echo "Please export WIND_BASE and try again." + @exit 1 +ifeq "$(strip $(WIND_BASE))" "" +check_windbase: badwindbase +else +check_windbase: +endif # WIND_BASE defined +else +check_windbase: +endif # BUILD_TARGET_OS VXWORKS +.PHONY: check_windbase + +#-----------------------------------------------------------------------------# +# Check the environment for the MIPS_PATH variable begin set + +# really VXWORKS/MIPS, but CYGWIN is defunct anyway so no need to refine test +ifeq "$(BUILD_TARGET_OS)" "VXWORKS" +ifeq "$(BUILD_PLATFORM)" "CYGWIN" +badmipspath: + @echo "MIPS_PATH value was not defined" + @echo 'Please run the target function and try again.' + @exit 1 +ifeq "$(strip $(MIPS_PATH))" "" +check_mipspath: badmipspath +else +check_mipspath: +endif # MIPS_PATH defined +else +check_mipspath: +endif # BUILD_PLATFORM CYGWIN defined +else +check_mipspath: +endif # BUILD_TARGET_OS VXWORKS +.PHONY: check_mipspath + +#-----------------------------------------------------------------------------# +# Check the environment for the I386_PATH variable begin set + +ifeq "$(BUILD_TARGET)" "I386" +ifeq "$(BUILD_PLATFORM)" "CYGWIN" +badi386path: + @echo "I386_PATH value was not defined" + @echo 'Please run the target function and try again.' + @exit 1 +ifeq "$(strip $(I386_PATH))" "" +check_i386path: i386mipspath +else +check_i386path: +endif # I386_PATH defined +else +check_i386path: +endif # BUILD_PLATFORM CYGWIN defined +else +check_i386path: +endif # BUILD_TARGET I386 +.PHONY: check_i386path + + +#-----------------------------------------------------------------------------# +ifeq "$(BUILD_PLATFORM)" "LINUX" +# Check if running as root + +badroot: + @echo "You must be running as root for this step." + @echo "Please log in as root and try again." + @exit 1 +ifneq "$(shell id -u)" "0" +check_root: badroot +else +check_root: +endif # UID is 0 +else +check_root: +endif # BUILD_PLATFORM LINUX +ifeq "$(BUILD_PLATFORM)" "DARWIN" +# Check if running as root + +badroot: + @echo "You must be running as root for this step." + @echo "Please log in as root and try again." + @exit 1 +ifneq "$(shell id -u)" "0" +check_root: badroot +else +check_root: +endif # UID is 0 +else +check_root: +endif # BUILD_PLATFORM DARWIN +.PHONY: check_root + +#-----------------------------------------------------------------------------# + +ifneq (,$(USE_NETF1_IP_STACK)) +CFLAGS += -DUSE_NETF1_IP_STACK +CCFLAGS += -DUSE_NETF1_IP_STACK +ifneq (,$(USE_NETF1_IP_V6)) +CFLAGS += -DINET6 +CCFLAGS += -DINET6 +endif + +.PHONY: $(GLOBAL_INCLUDE_DIR)/netF1Target +$(GLOBAL_INCLUDE_DIR)/netF1Target: + rm -rf $(GLOBAL_INCLUDE_DIR)/netF1Target +ifneq (ATOM,$(BUILD_TARGET)) + mkdir -p $(GLOBAL_INCLUDE_DIR)/netF1Target/h + # NB: lndir doesn't overwrite existing links, so netF1 goes first + lndir -silent $(TL_DIR)/tmsTarget/src/netF1/h $(GLOBAL_INCLUDE_DIR)/netF1Target/h 2>/dev/null + lndir -silent $(TL_DIR)/tmsTarget/src/netF1/h/port/vxworks $(GLOBAL_INCLUDE_DIR)/netF1Target/h 2>/dev/null + # NB: want newest version of adaptos used by ssecure users + mkdir -p $(GLOBAL_INCLUDE_DIR)/netF1Target/h/ssecure + mkdir -p $(GLOBAL_INCLUDE_DIR)/netF1Target/h/ssecure/adaptos + lndir -silent $(TL_DIR)/tmsTarget/src/netF1/h/adaptos $(GLOBAL_INCLUDE_DIR)/netF1Target/h/ssecure/adaptos 2>/dev/null + lndir -silent $(TL_DIR)/tmsTarget/h $(GLOBAL_INCLUDE_DIR)/netF1Target/h 2>/dev/null +endif + +endif diff --git a/Makerules/Rules.DARWIN b/Makerules/Rules.DARWIN new file mode 100755 index 0000000..127534f --- /dev/null +++ b/Makerules/Rules.DARWIN @@ -0,0 +1,34 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** +# rules for building under darwin + +vpath %$(ARLIB_SUFFIX) $(LOCAL_LIB_DIRS) $(MOD_LIB_DIRS) $(PROJ_LIB_DIRS) +vpath %$(SHLIB_SUFFIX) $(LOCAL_LIB_DIRS) $(MOD_LIB_DIRS) $(PROJ_LIB_DIRS) + +CMD_TARGETS += $(CMD_TARGETS_DRIVER) $(CMD_TARGETS_KEXT) diff --git a/Makerules/Rules.DOS b/Makerules/Rules.DOS new file mode 100755 index 0000000..7908cf4 --- /dev/null +++ b/Makerules/Rules.DOS @@ -0,0 +1,37 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** +# paths to libraries when BUILD_PLATFORM=DOS +# rules for building under DOS + +ULOCAL_LIB_DIRS=$(foreach path,$(LOCAL_LIB_DIRS),$(subst c:,/cygdrive/c,$(path))) +UMOD_LIB_DIRS=$(foreach path,$(MOD_LIB_DIRS),$(subst c:,/cygdrive/c,$(path))) +UPROJ_LIB_DIRS=$(foreach path,$(PROJ_LIB_DIRS),$(subst c:,/cygdrive/c,$(path))) + +vpath %$(ARLIB_SUFFIX) $(ULOCAL_LIB_DIRS) $(UMOD_LIB_DIRS) $(UPROJ_LIB_DIRS) +vpath %$(SHLIB_SUFFIX) $(ULOCAL_LIB_DIRS) $(UMOD_LIB_DIRS) $(UPROJ_LIB_DIRS) diff --git a/Makerules/Rules.LINUX b/Makerules/Rules.LINUX new file mode 100755 index 0000000..cf0f22b --- /dev/null +++ b/Makerules/Rules.LINUX @@ -0,0 +1,35 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** +# paths to libraries when BUILD_PLATFORM=LINUX +# rules for building under linux + +vpath %$(ARLIB_SUFFIX) $(LOCAL_LIB_DIRS) $(MOD_LIB_DIRS) $(PROJ_LIB_DIRS) +vpath %$(SHLIB_SUFFIX) $(LOCAL_LIB_DIRS) $(MOD_LIB_DIRS) $(PROJ_LIB_DIRS) + +CMD_TARGETS += $(CMD_TARGETS_DRIVER) diff --git a/Makerules/Rules.Tests b/Makerules/Rules.Tests new file mode 100644 index 0000000..756a472 --- /dev/null +++ b/Makerules/Rules.Tests @@ -0,0 +1,236 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** +#=============================================================================# +## Automated Testing makerules +## --------------------------- +## +#=============================================================================# +## +#=============================================================================# +## The following list is the standard list of definitions which will be defined +## or are used in other variable definitions or rules in this makerules file. +## Each project variable name is listed with a definition of the purpose and +## intended use. Defaults for items are shown in brackets, and may be +## overridden by the user in a local makefile. If no default is shown, the +## user can use the variable, but should not change the value. +## +## CLEAN_TARGETS = Intermediate build process file names to be deleted +## on a clean operation [Not defined] +## CLOBBER_TARGETS = Intermediate build process file names to be deleted +## on a clobber operation [Not defined] +## DIRS = List of directories containing the next level of the testing +## hierarchy. [Not defined] +## EXPECT = name of the expect program to use +## ID_FILENAME = Name of the file in which test case information is placed. +## The default is identify.res +## MAKE = System make application +## SUITES = List of test suites in the current makefile [Not defined] +## TEE = UNIX tee command +## VS = Visible shell commands (may be overridden in local makefiles) +## +#=============================================================================# +# Common platform definitions: +#-----------------------------------------------------------------------------# +EXPECT = TCLLIBPATH="$(TL_DIR)/TestTools $(TL_DIR)/TestOnly /usr/lib/tcl /usr/lib/tdom0.8.3 $(TL_DIR)/iv/TestOnly" expect +MAKE = make +MAKEFILE = Makefile +TEE = tee +ID_FILENAME = identify.res +SUMMARY_REPORT = $(TL_DIR)/TestOnly/summary_report +VS = @ +#-----------------------------------------------------------------------------# +# Platform specific definitions: +#-----------------------------------------------------------------------------# +#=============================================================================# + +#=============================================================================# +## The makerules file also contains the following basic make target rules for +## simplifying the testing processes: +## +## all: This target should be the first target in the makefile stream and +## will be if this makerules file is included before the rules section +## of any local makefile. The purpose of this target is to run the ALL +## target. +## +## ALL:: The purpose of this extensible target is to run all of the test +## targets. +## +## check_test_config: This non-extensible target will verify that the +## TEST_CONFIG_FILE environment variable is defined and can be used as a +## dependency for use in local makefiles. The target does not validate +## the value of the variable, only that it is set. The TEST_CONFIG_FILE +## variable should be set by the setup_tests script. +## +## clean:: This extensible target is used to remove all intermediate files +## created during the tests process. All of the temporary files will +## automatically be deleted along with those defined in CLEAN_TARGETS. +## +## clobber:: This extensible target is used to remove all intermediate and +## target files and should restore the directory to a checkout state where +## only source tests exist. This target has a dependency on the clean +## target, and removes CLOBBER_TARGETS files. +## +## identify: This non-extensible target is used to generate an output file with +## the test case information. This data is used by the user selection front +## end to allow user selection of the various test cases available and to +## construct the proper operating environment. +## +#=============================================================================# +# The following section contains a list of standard targets which will be used +# by all of the makefiles. The targets are listed in alphabetical order and +# depend on the above definitions section as well as externally defined items +# from the user specific makefile. +#=============================================================================# +# General Rules: +#-----------------------------------------------------------------------------# +ifdef DIRS + +ifdef SUITES +all: defboth badmake +else #SUITES +all: ALL +endif #SUITES + +.PHONY: $(DIRS) +else #DIRS + +ifdef SUITES +all: ALL +else #SUITES +all: defnone badmake +endif #SUITES + +endif #DIRS + +defboth: + @echo "DIRS and SUITES may not both be set in the same makefile." +defnone: + @echo "DIRS or SUITES must be set in the makefile." +badmake: + @echo "Separate the directories into a top level makefile, create" + @echo "directories as appropriate, and place the test suites in one" + @echo "or more of the directories with their own makefiles." + @exit 1 + +ALL:: check_test_config $(SUITES) +ifdef DIRS +ALL:: $(DIRS) +$(DIRS): +ifdef TEST_IDENTIFY + $(VS)echo '*******************************************************************************' >> $(ID_FILENAME) + $(VS)echo "Directory: $@" >> $(ID_FILENAME) + $(VS)cd $@; $(MAKE) identify + $(VS)cat $@/$(ID_FILENAME) >> $(ID_FILENAME) +else #TEST_IDENTIFY +$(DIRS): $(SUMMARY_REPORT) + $(VS)( echo "Executing $@ Tests `date` ..." ;\ + cd $@; $(MAKE) ;\ + echo "Done $@ Tests `date`" ) | $(SUMMARY_REPORT) -r -o + @echo "Test(s) Complete" +endif #TEST_IDENTIFY +else # DIRS + @echo "Test(s) Complete" +endif #DIRS + +clean:: + @echo "Removing Intermediate Files" +ifdef DIRS + $(VS)for i in $(DIRS) ;\ + do \ + ( cd $$i; $(MAKE) clean ) ;\ + done +endif + rm -fr *.log case_tmp save_tmp core test_tmp* + rm -fr $(CLEAN_TARGETS) + +ifeq "$(MAKELEVEL)" "0" +clobber:: clean +else +clobber:: +endif + @echo "Removing Target/Build Files" +ifdef DIRS + $(VS)for i in $(DIRS) ;\ + do \ + ( cd $$i; $(MAKE) clobber ) ;\ + done +endif +ifdef TEST_IDENTIFY + rm -rf identify.res +else + rm -fr test.res test.items.res test.cases.res test.suites.res $(CLOBBER_TARGETS) +endif + +identify: + $(VS)rm -f $(ID_FILENAME) + $(VS)$(MAKE) $(ID_FILENAME) + +$(ID_FILENAME): + $(VS)TEST_IDENTIFY=yes $(MAKE) all > /dev/null + +$(SUMMARY_REPORT): + $(VS)cd $(TL_DIR)/TestTools; $(MAKE) all > /dev/null + $(VS)cd $(TL_DIR)/TestOnly; $(MAKE) all > /dev/null + $(VS)cd $(TL_DIR)/iv/TestOnly; $(MAKE) all > /dev/null + +%: %.exp + $(VS)cd $(TL_DIR)/TestTools; $(MAKE) all > /dev/null + $(VS)cd $(TL_DIR)/TestOnly; $(MAKE) all > /dev/null + $(VS)cd $(TL_DIR)/iv/TestOnly; $(MAKE) all > /dev/null + +ifdef TEST_IDENTIFY + $(VS)TEST_IDENTIFY=$(TEST_IDENTIFY) $(EXPECT) -f $^ >> $(ID_FILENAME) +else #TEST_IDENTIFY + >> test.log + $(VS)$(EXPECT) -f $^ | $(SUMMARY_REPORT) -r -o +endif #TEST_IDENTIFY +#=============================================================================# + +#=============================================================================# +# This section contains a set of targets which override the standard ones +# provided for by GNU make. +#=============================================================================# +# Standard Makefile Rules Overrides: +#-----------------------------------------------------------------------------# +#=============================================================================# + +#=============================================================================# +# Targets to make sure the initial environment is properly configured +#=============================================================================# +ifndef TEST_CONFIG_FILE +check_test_config: + @echo "The TEST_CONFIG_FILE environment variable must be set to be valid" + @echo "run setup_tests first" + @exit 1 +else #TEST_CONFIG_FILE +check_test_config: +endif #TEST_CONFIG_FILE +.PHONY: check_test_config +#=============================================================================# + diff --git a/Makerules/Target.CYGWIN.GNU.CYGWIN b/Makerules/Target.CYGWIN.GNU.CYGWIN new file mode 100755 index 0000000..e207926 --- /dev/null +++ b/Makerules/Target.CYGWIN.GNU.CYGWIN @@ -0,0 +1,96 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** +# suffixes and commands to build targets for: +# BUILD_TARGET_OS=CYGWIN +# BUILD_TARGET_TOOLCHAIN=GNU +# BUILD_TARGET=CYGWIN +# CYGWIN BUILD_TARGET is used only to build devtools to run on Windows + +SHLIB_VERSION ?= 0.0 +LIB_PREFIX = $(BUILDDIR)/lib +SHLIB_SUFFIX = .so +SHLIB_VERSION_SUFFIX= .so.$(SHLIB_VERSION) +ARLIB_SUFFIX = .a +EXE_SUFFIX = .exe +OBJ_SUFFIX = .o +EXP_SUFFIX = .exp +RES_SUFFIX = .res +PRE_SUFFIX = .pre + +# Paths: +SYS_INCLUDE_DIRS= $(subst \,/,$(shell cygpath -w /usr/include)) +SYS_LIB_DIRS = + +CC = gcc +CCC = g++ +LD = ld +LINT = lint +AR = ar +NM = nm + +include $(TL_DIR)/Makerules/Defs.GNU + +# for GNU we set an soname on shared libraries +SHLIB_SONAME=$(notdir $(CMD_TARGETS_SHLIB)) + +# C/C++ compilation +# ---------------------------- +CMACH = -DTARGET_CPU_FAMILY_X86 -Wall -DCPU_LE +CCMACH = $(CMACH) +CSYS = +CCSYS = +CSHARED = +CCSHARED = +CCLIBS = +release_CCOPT_Flags =-O +debug_CCOPT_Flags = +# Assemble the optimization flags based upon desired build configuration. +CCOPT = $($(strip $(BUILD_CONFIG))_CCOPT_Flags) +# for now assume C++ flags are valid on C compiler +COPT = $(CCOPT) +release_CCDEBUG_Flags = +debug_CCDEBUG_Flags =-g -DIB_DEBUG -DIB_TRACE $(CCPROJDEBUG) $(CCLOCALDEBUG) +debug_CDEBUG_Flags =-g -DIB_DEBUG -DIB_TRACE $(CPROJDEBUG) $(CLOCALDEBUG) +# Assemble the debug flags based upon desired build configuration. +CCDEBUG = $($(strip $(BUILD_CONFIG))_CCDEBUG_Flags) +CDEBUG = $($(strip $(BUILD_CONFIG))_CDEBUG_Flags) + +# linking +# ---------------------------- +LDMACH = +MKSHLIB = $(CCC) $(CCDEBUG) $(COPT) -shared +ifeq "$(strip $(LIBFILES))" "" +MKARLIB = $(AR) crus$(space) +else +MKARLIB = $(MAKETOOLS_DIR)/mkarlib.sh $(AR) crus$(space) +endif +MKPARTIAL = $(LD) -r -o + +SYSLIBS = +LDLIBS = -Xlinker --start-group $(foreach lib,$(LOCALLIBS) $(LOCALDEPLIBS) $(MODLIBS) $(MODDEPLIBS) $(PROJLIBS) $(PROJDEPLIBS),-l$(lib)) -Xlinker --end-group $(SYSLIBS) diff --git a/Makerules/Target.DARWIN.GNU.PPC b/Makerules/Target.DARWIN.GNU.PPC new file mode 100755 index 0000000..cd23e00 --- /dev/null +++ b/Makerules/Target.DARWIN.GNU.PPC @@ -0,0 +1,148 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** +# Target specific defines for building PPC target using GNU tools + +SHLIB_VERSION ?= 0.0 +LIB_PREFIX = $(BUILDDIR)/lib +SHLIB_SUFFIX = .dylib +SHLIB_VERSION_SUFFIX= .$(SHLIB_VERSION).dylib +ARLIB_SUFFIX = .a +EXE_SUFFIX = +KEXT_SUFFIX = .kext +OBJ_SUFFIX = .o +EXP_SUFFIX = .exp +RES_SUFFIX = .res +PRE_SUFFIX = .pre + +# Paths: +# let compiler default inclusion of /usr/include, otherwise g++ builds broken +SYS_INCLUDE_DIRS = +SYS_LIB_DIRS = + +CC = /usr/bin/distcc /usr/bin/gcc-3.3 +CCC = /usr/bin/distcc /usr/bin/gcc-3.3 -x c++ +LD = ld +LINT = lint +AR = ar +NM = nm +OBJCOPY = objcopy + +include $(TL_DIR)/Makerules/Defs.GNU + +# for GNU we set an soname on shared libraries +# on MAC it must be a full pathname +# this is a bit of a HACK since we hardcode the pathname +SHLIB_SONAME=/usr/lib/$(notdir $(CMD_TARGETS_SHLIB)) + +# C/C++ compilation +# ---------------------------- +# no-common - will put globals uninitialized in .bss instead of .common +# hence get link error if multiple declaration +# -fcheck-new does the opposite of what the manual implies. +# -fcheck-new DISABLES the run-time test of return value from new +# TBD - should the following only be for kernel: +# -fno-common +# TBD -mcpu=970 +CMACH = -Wall -arch ppc -pipe -Wno-trigraphs -fasm-blocks -mtune=G5 -fmessage-length=0 -fpch-preprocess -fno-common -finline -fno-keep-inline-functions -force_cpusubtype_ALL -DCPU_BE -D__PPC__ +CCMACH = $(CMACH) -fcheck-new -Wno-ctor-dtor-privacy -fno-rtti +CSYS = -D__DARWIN__ -DAPPLE -DNeXT +CCSYS = $(CSYS) +CCLIBS = +release_CCOPT_Flags =-O2 -fno-strength-reduce +debug_CCOPT_Flags = -O0 +release_COPT_Flags =-O2 -fno-strength-reduce +debug_COPT_Flags = -O0 +# Assemble the optimization flags based upon desired build configuration. +CCOPT = $($(strip $(BUILD_CONFIG))_CCOPT_Flags) +COPT = $($(strip $(BUILD_CONFIG))_COPT_Flags) +release_CCDEBUG_Flags = +release_CDEBUG_Flags = +debug_CCDEBUG_Flags =-g -DIB_DEBUG -D_DEBUG -DDEBUG -DIB_TRACE $(CCPROJDEBUG) $(CCLOCALDEBUG) +debug_CDEBUG_Flags =-g -DIB_DEBUG -D_DEBUG -DDEBUG -DIB_TRACE $(CPROJDEBUG) $(CLOCALDEBUG) +# Assemble the debug flags based upon desired build configuration. +CCDEBUG = $($(strip $(BUILD_CONFIG))_CCDEBUG_Flags) +CDEBUG = $($(strip $(BUILD_CONFIG))_CDEBUG_Flags) + +# Kernel build settings +#--------------------------------------------- +# use CKERNEL and KERNEL_INCLUDE_DIRS to augment CLOCAL, LOCAL_INCLUDE_DIRS when +# building a kernel module + +# TBD -fno-strict-aliasing - disables optimizations related to unions/casts +# -include picks up special kernel version specific flags, this allows portable +# kernel modules to be built for multiple system types from a single running +# system +# TBD keep -g on release builds to aid stack backtraces +CKERNELOPTS = -fno-exceptions -msoft-float -mlong-branch -fno-builtin -nostdinc -DKERNEL -DKERNEL_PRIVATE -DDRIVER_PRIVATE -D__KERNEL__ -D_KERNEL -static -include $(TL_DIR)/Makerules/DARWIN/$(BUILD_TARGET).$(BUILD_TARGET_OS_VENDOR).$(BUILD_TARGET_OS_VERSION).h +# omit frame pointer for simple functions +ifeq "$(BUILD_CONFIG)" "release" +#CKERNELOPTS+= -Os -fomit-frame-pointer +CKERNELOPTS+= -O2 -fomit-frame-pointer +else +CKERNELOPTS+= -O1 +endif +CKERNEL = -x c++ -fapple-kext $(CKERNELOPTS) + +# Include directories for kernel +KERNELDIR=/System/Library/Frameworks/Kernel.framework +KERNEL_INCLUDE_DIRS=$(KERNELDIR)/Headers $(KERNELDIR)/Headers/bsd $(KERNELDIR)/PrivateHeaders /usr/include/g++-3/ke /usr/include/g++-3 + +# linking +# ---------------------------- +LDMACH = -arch ppc +LDSYS = +#MKSHLIB = $(CCC) $(CCDEBUG) $(COPT) -shared +#MKSHLIB = $(LD) -dylib +MKSHLIB = $(CC) -dynamiclib -Wl,-prebind_allow_overlap -Wl,-single_module -compatibility_version 1 -current_version 1 +#MKSHLIB = /usr/bin/libtool -dynamic -prebind -compatibility_version 1 -current_version 1 +#MKSHLIB = /usr/bin/libtool -dynamic +ifeq "$(strip $(LIBFILES))" "" +MKARLIB = $(AR) crus$(space) +else +MKARLIB = $(MAKETOOLS_DIR)/mkarlib.sh $(AR) crus$(space) +endif +MKPARTIAL = $(LD) -r -o +#MKMODULE = /usr/bin/g++-3.3 -arch ppc -static -nostdlib -r -lkmodc++ -lkmod -lcc_kext -o +MKMODULE = /usr/bin/g++-3.3 -o + +KERNELOPTS = -arch ppc -static -nostdlib -r -lkmodc++ -lkmod -lcc_kext + +SYSLIBS = -lpthread -lstdc++ +#LDLIBS = -Xlinker --start-group $(foreach lib,$(LOCALLIBS) $(LOCALDEPLIBS) $(MODLIBS) $(MODDEPLIBS) $(PROJLIBS) $(PROJDEPLIBS),-l$(lib)) -Xlinker --end-group $(SYSLIBS) +LDLIBS = $(foreach lib,$(LOCALLIBS) $(LOCALDEPLIBS) $(MODLIBS) $(MODDEPLIBS) $(PROJLIBS) $(PROJDEPLIBS),-l$(lib)) $(SYSLIBS) +# libraries for partial link of a kernel loadable module +#KERNELLIBS = -static -r -Xlinker --start-group -nostdlib -lkmodc++ -lkmod -lcc_kext $(foreach lib,$(LOCALLIBS) $(LOCALDEPLIBS) $(MODLIBS) $(MODDEPLIBS) $(PROJLIBS) $(PROJDEPLIBS),-l$(lib)) -Xlinker --end-group +KERNELLIBS = $(KERNELOPTS) + +# KEXT creation +ifeq "$(BUILD_PLATFORM_OS_VENDOR_VERSION)" "10.3" +PBXCP = "/Developer/Tools/pbxcp" +else +PBXCP = "/System/Library/PrivateFrameworks/DevToolsCore.framework/Resources/pbxcp" +endif diff --git a/Makerules/Target.LINUX.GNU.EM64T b/Makerules/Target.LINUX.GNU.EM64T new file mode 100755 index 0000000..ef1a3cb --- /dev/null +++ b/Makerules/Target.LINUX.GNU.EM64T @@ -0,0 +1,158 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** +# suffixes and commands to build targets for: +# BUILD_TARGET_OS=LINUX +# BUILD_TARGET_TOOLCHAIN=GNU +# BUILD_TARGET=EM64T +# Target specific defines for building LINUX target using GNU tools + +SHLIB_VERSION ?= 0.0 +LIB_PREFIX = $(BUILDDIR)/lib +SHLIB_SUFFIX = .so +SHLIB_VERSION_SUFFIX= .so.$(SHLIB_VERSION) +ARLIB_SUFFIX = .a +EXE_SUFFIX = +OBJ_SUFFIX = .o +ifdef BUILD_26 +KOBJ_SUFFIX = .ko +else +KOBJ_SUFFIX = .o +endif +EXP_SUFFIX = .exp +RES_SUFFIX = .res +PRE_SUFFIX = .pre + +# Paths: +# let compiler default inclusion of /usr/include, otherwise g++ builds broken +SYS_INCLUDE_DIRS = +SYS_LIB_DIRS = + +CC = gcc +CCC = g++ +LD = ld +LINT = lint +AR = ar +NM = nm +OBJCOPY = objcopy + +include $(TL_DIR)/Makerules/Defs.GNU + +# for GNU we set an soname on shared libraries +SHLIB_SONAME=$(notdir $(CMD_TARGETS_SHLIB)) + +# C/C++ compilation +# ---------------------------- +# -fcheck-new does the opposite of what the manual implies. +# -fcheck-new DISABLES the run-time test of return value from new +CMACH = -pipe -DTARGET_CPU_FAMILY_X86 -Wall -D__X86_64__ -D__EM64T__ -DCPU_LE -m64 -fno-strict-aliasing +CCMACH = $(CMACH) -fcheck-new -Wno-ctor-dtor-privacy +CSYS = -DLINUX -Dlinux -D__LINUX__ +CCSYS = $(CSYS) +CCLIBS = +release_CCOPT_Flags =-O2 -fno-strength-reduce +debug_CCOPT_Flags = +release_COPT_Flags =-O2 -fno-strength-reduce +0debug_COPT_Flags = +# Assemble the optimization flags based upon desired build configuration. +CCOPT = $($(strip $(BUILD_CONFIG))_CCOPT_Flags) +COPT = $($(strip $(BUILD_CONFIG))_COPT_Flags) +release_CCDEBUG_Flags = +release_CDEBUG_Flags = +debug_CCDEBUG_Flags =-g -DIB_DEBUG -DIB_TRACE $(CCPROJDEBUG) $(CCLOCALDEBUG) +debug_CDEBUG_Flags =-g -DIB_DEBUG -DIB_TRACE $(CPROJDEBUG) $(CLOCALDEBUG) +# Assemble the debug flags based upon desired build configuration. +CCDEBUG = $($(strip $(BUILD_CONFIG))_CCDEBUG_Flags) +CDEBUG = $($(strip $(BUILD_CONFIG))_CDEBUG_Flags) + +# Kernel build settings +#--------------------------------------------- +# use CKERNEL and KERNEL_INCLUDE_DIRS to augment CLOCAL, LOCAL_INCLUDE_DIRS when +# building a kernel module + +# strict-aliasing - disables optimizations related to unions/casts +# no-common - will put globals uninitialized in .bss instead of common +# hence get link error if multiple declaration +# preferred-stack-boundary=2 -align stack to 2^2 byte boundary, +# possible performance penalty for 64 bit data +# TBD, what does kernel use +# -D_I386_PTRACE_H was a workaround for a ptrace.h header file inclusion issue +# identify where needed and just put in that one makefile +# -include picks up special flags for SMP and MODVERSIONS, this allows portable +# kernel modules to be built for multiple system types from a single running +# system + +ifndef BUILD_26 + +CKERNEL=-D_KERNEL -D__KERNEL__ -DMODULE -DEXPORT_SYMTAB -mcmodel=kernel -Wno-trigraphs -mno-red-zone -fno-reorder-blocks -finline-limit=2000 -fno-strict-aliasing -fno-common -msoft-float +# omit frame pointer for simple functions +# take advantage of pentium pro instructions, default is i386 compatible code + +ifeq "$(BUILD_CONFIG)" "release" +CKERNEL+= -fomit-frame-pointer -O2 -fno-strength-reduce +else +# due to extern inline virt_to_phys in io.h in kernel, we must use at least -O1 +# COPT will follow CLOCAL in CFLAGS, so it can request a different level +# of optimization if needed +CKERNEL+= -O1 +endif + +ifeq "$(GCC_MAJOR_VERSION)" "3" +ifeq "$(GCC_MINOR_VERSION)" "3" +ifeq "$(BUILD_PLATFORM_OS_VENDOR)" "SuSE" +CKERNEL+=-fno-unit-at-a-time +endif +endif +endif + +endif +CKERNEL+=-include $(TL_DIR)/Makerules/LINUX/$(BUILD_TARGET).$(BUILD_TARGET_OS_VENDOR).$(BUILD_TARGET_OS_VERSION).h + +# Include directories for kernel +KERNELDIR=/lib/modules/$(BUILD_TARGET_OS_VERSION)/build +KERNEL_INCLUDE_DIRS=$(KERNELDIR)/include + +# linking +# ---------------------------- +LDMACH = +LDSYS = +MKSHLIB = $(CCC) $(CCDEBUG) $(COPT) -shared +ifeq "$(strip $(LIBFILES))" "" +MKARLIB = $(AR) crus$(space) +else +MKARLIB = $(MAKETOOLS_DIR)/mkarlib.sh $(AR) crus$(space) +endif +MKPARTIAL = $(LD) -r -o +MKMODULE = $(LD) -r -o + +LDLIBSRCH += $(foreach lib,$(LD_LIB_DIRS),-Xlinker -rpath-link -Xlinker $(lib)) +SYSLIBS = -lpthread +LDLIBS = -Xlinker --start-group $(foreach lib,$(LOCALLIBS) $(LOCALDEPLIBS) $(MODLIBS) $(MODDEPLIBS) $(PROJLIBS) $(PROJDEPLIBS),-l$(lib)) -Xlinker --end-group $(SYSLIBS) + +# libraries for partial link of a kernel loadable module +KERNELLIBS = diff --git a/Makerules/Target.LINUX.GNU.IA32 b/Makerules/Target.LINUX.GNU.IA32 new file mode 100755 index 0000000..08683b5 --- /dev/null +++ b/Makerules/Target.LINUX.GNU.IA32 @@ -0,0 +1,151 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** +# suffixes and commands to build targets for: +# BUILD_TARGET_OS=LINUX +# BUILD_TARGET_TOOLCHAIN=GNU +# BUILD_TARGET=IA32 +# Target specific defines for building LINUX target using GNU tools + +SHLIB_VERSION ?= 0.0 +LIB_PREFIX = $(BUILDDIR)/lib +SHLIB_SUFFIX = .so +SHLIB_VERSION_SUFFIX= .so.$(SHLIB_VERSION) +ARLIB_SUFFIX = .a +EXE_SUFFIX = +OBJ_SUFFIX = .o +ifdef BUILD_26 +KOBJ_SUFFIX = .ko +else +KOBJ_SUFFIX = .o +endif +EXP_SUFFIX = .exp +RES_SUFFIX = .res +PRE_SUFFIX = .pre + +# Paths: +# let compiler default inclusion of /usr/include, otherwise g++ builds broken +SYS_INCLUDE_DIRS = +SYS_LIB_DIRS = + +CC = gcc +CCC = g++ +LD = ld +LINT = lint +AR = ar +NM = nm +OBJCOPY = objcopy + +include $(TL_DIR)/Makerules/Defs.GNU + +# for GNU we set an soname on shared libraries +SHLIB_SONAME=$(notdir $(CMD_TARGETS_SHLIB)) + +# C/C++ compilation +# ---------------------------- +# -fcheck-new does the opposite of what the manual implies. +# -fcheck-new DISABLES the run-time test of return value from new + +CMACH = -pipe -DTARGET_CPU_FAMILY_X86 -Wall -D__IA32__ -falign-functions=2 -falign-loops=2 -falign-jumps=2 -DCPU_LE -fno-strict-aliasing +CCMACH = $(CMACH) -fcheck-new -Wno-ctor-dtor-privacy +CSYS = -DLINUX -Dlinux -D__LINUX__ +CCSYS = $(CSYS) +CCLIBS = +release_CCOPT_Flags =-O2 -fno-strength-reduce +debug_CCOPT_Flags = +release_COPT_Flags =-O2 -fno-strength-reduce +debug_COPT_Flags = +# Assemble the optimization flags based upon desired build configuration. +CCOPT = $($(strip $(BUILD_CONFIG))_CCOPT_Flags) +COPT = $($(strip $(BUILD_CONFIG))_COPT_Flags) +release_CCDEBUG_Flags = +release_CDEBUG_Flags = +debug_CCDEBUG_Flags =-g -DIB_DEBUG -DIB_TRACE $(CCPROJDEBUG) $(CCLOCALDEBUG) +debug_CDEBUG_Flags =-g -DIB_DEBUG -DIB_TRACE $(CPROJDEBUG) $(CLOCALDEBUG) +# Assemble the debug flags based upon desired build configuration. +CCDEBUG = $($(strip $(BUILD_CONFIG))_CCDEBUG_Flags) +CDEBUG = $($(strip $(BUILD_CONFIG))_CDEBUG_Flags) + +# Kernel build settings +#--------------------------------------------- +# use CKERNEL and KERNEL_INCLUDE_DIRS to augment CLOCAL, LOCAL_INCLUDE_DIRS when +# building a kernel module + +# strict-aliasing - disables optimizations related to unions/casts +# no-common - will put globals uninitialized in .bss instead of common +# hence get link error if multiple declaration +# preferred-stack-boundary=2 -align stack to 2^2 byte boundary, +# possible performance penalty for 64 bit data +# TBD, what does kernel use +# -D_I386_PTRACE_H was a workaround for a ptrace.h header file inclusion issue +# identify where needed and just put in that one makefile +# -include picks up special flags for SMP and MODVERSIONS, this allows portable +# kernel modules to be built for multiple system types from a single running +# system +ifndef BUILD_26 + +CKERNEL=-D_KERNEL -D__KERNEL__ -DMODULE -DEXPORT_SYMTAB -fno-strict-aliasing -fno-common -mpreferred-stack-boundary=2 + +# omit frame pointer for simple functions +# take advantage of pentium pro instructions, default is i386 compatible code +ifeq "$(BUILD_CONFIG)" "release" +CKERNEL+=-O2 -fomit-frame-pointer -march=i686 +else +# due to extern inline virt_to_phys in io.h in kernel, we must use at least -O1 +# COPT will follow CLOCAL in CFLAGS, so it can request a different level +# of optimization if needed +CKERNEL+=-O1 +endif + +endif +CKERNEL+=-include $(TL_DIR)/Makerules/LINUX/$(BUILD_TARGET).$(BUILD_TARGET_OS_VENDOR).$(BUILD_TARGET_OS_VERSION).h + + +# Include directories for kernel +KERNELDIR=/lib/modules/$(BUILD_TARGET_OS_VERSION)/build +KERNEL_INCLUDE_DIRS=$(KERNELDIR)/include + +# linking +# ---------------------------- +LDMACH = +LDSYS = +MKSHLIB = $(CCC) $(CCDEBUG) $(COPT) -shared +ifeq "$(strip $(LIBFILES))" "" +MKARLIB = $(AR) crus$(space) +else +MKARLIB = $(MAKETOOLS_DIR)/mkarlib.sh $(AR) crus$(space) +endif +MKPARTIAL = $(LD) -r -o +MKMODULE = $(LD) -r -o + +LDLIBSRCH += $(foreach lib,$(LD_LIB_DIRS),-Xlinker -rpath-link -Xlinker $(lib)) +SYSLIBS = -lpthread +LDLIBS = -Xlinker --start-group $(foreach lib,$(LOCALLIBS) $(LOCALDEPLIBS) $(MODLIBS) $(MODDEPLIBS) $(PROJLIBS) $(PROJDEPLIBS),-l$(lib)) -Xlinker --end-group $(SYSLIBS) + +# libraries for partial link of a kernel loadable module +KERNELLIBS = diff --git a/Makerules/Target.LINUX.GNU.IA64 b/Makerules/Target.LINUX.GNU.IA64 new file mode 100755 index 0000000..4ab295a --- /dev/null +++ b/Makerules/Target.LINUX.GNU.IA64 @@ -0,0 +1,151 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** +# suffixes and commands to build targets for: +# BUILD_TARGET_OS=LINUX +# BUILD_TARGET_TOOLCHAIN=GNU +# BUILD_TARGET=IA64 +# Target specific defines for building LINUX target using GNU tools + +SHLIB_VERSION ?= 0.0 +LIB_PREFIX = $(BUILDDIR)/lib +SHLIB_SUFFIX = .so +SHLIB_VERSION_SUFFIX= .so.$(SHLIB_VERSION) +ARLIB_SUFFIX = .a +EXE_SUFFIX = +OBJ_SUFFIX = .o +ifdef BUILD_26 +KOBJ_SUFFIX = .ko +else +KOBJ_SUFFIX = .o +endif +EXP_SUFFIX = .exp +RES_SUFFIX = .res +PRE_SUFFIX = .pre + +# Paths: +# let compiler default inclusion of /usr/include, otherwise g++ builds broken +SYS_INCLUDE_DIRS = +SYS_LIB_DIRS = + +CC = gcc +CCC = g++ +LD = ld +LINT = lint +AR = ar +NM = nm +OBJCOPY = objcopy + +include $(TL_DIR)/Makerules/Defs.GNU + +# for GNU we set an soname on shared libraries +SHLIB_SONAME=$(notdir $(CMD_TARGETS_SHLIB)) + +# C/C++ compilation +# ---------------------------- +# -fcheck-new does the opposite of what the manual implies. +# -fcheck-new DISABLES the run-time test of return value from new +CMACH = -pipe -DTARGET_CPU_FAMILY_IA64 -Wall -Wno-multichar -Wstrict-prototypes -D__IA64__ -ffixed-r13 -mfixed-range=f10-f15,f32-f127 -DCPU_LE -fno-strict-aliasing +CCMACH = $(CMACH) -fcheck-new -Wno-ctor-dtor-privacy +CSYS = -DLINUX -Dlinux -D__LINUX__ +CCSYS = $(CSYS) +CCLIBS = +release_CCOPT_Flags =-O2 -funwind-tables -fno-strength-reduce +debug_CCOPT_Flags = +release_COPT_Flags =-O2 -funwind-tables -fno-strength-reduce +debug_COPT_Flags = +# Assemble the optimization flags based upon desired build configuration. +CCOPT = $($(strip $(BUILD_CONFIG))_CCOPT_Flags) +COPT = $($(strip $(BUILD_CONFIG))_COPT_Flags) +release_CCDEBUG_Flags = +release_CDEBUG_Flags = +debug_CCDEBUG_Flags =-g -DIB_DEBUG -DIB_TRACE $(CCPROJDEBUG) $(CCLOCALDEBUG) +debug_CDEBUG_Flags =-g -DIB_DEBUG -DIB_TRACE $(CPROJDEBUG) $(CLOCALDEBUG) +# Assemble the debug flags based upon desired build configuration. +CCDEBUG = $($(strip $(BUILD_CONFIG))_CCDEBUG_Flags) +CDEBUG = $($(strip $(BUILD_CONFIG))_CDEBUG_Flags) + +# Kernel build settings +#--------------------------------------------- +# use CKERNEL and KERNEL_INCLUDE_DIRS to augment CLOCAL, LOCAL_INCLUDE_DIRS when +# building a kernel module + +# strict-aliasing - disables optimizations related to unions/casts +# no-common - will put globals uninitialized in .bss instead of common +# hence get link error if multiple declaration +# preferred-stack-boundary=2 -align stack to 2^2 byte boundary, +# possible performance penalty for 64 bit data +# TBD, what does kernel use +# -D_I386_PTRACE_H was a workaround for a ptrace.h header file inclusion issue +# identify where needed and just put in that one makefile +# -include picks up special flags for SMP and MODVERSIONS, this allows portable +# kernel modules to be built for multiple system types from a single running +# system +ifndef BUILD_26 + +CKERNEL=-D_KERNEL -D__KERNEL__ -DMODULE -DEXPORT_SYMTAB -fno-strict-aliasing -fno-common +# omit frame pointer for simple functions +# take advantage of pentium pro instructions, default is i386 compatible code +ifeq "$(BUILD_CONFIG)" "release" +CKERNEL+=-fomit-frame-pointer -O2 -funwind-tables -fno-strength-reduce +else +# due to extern inline virt_to_phys in io.h in kernel, we must use at least -O1 +# COPT will follow CLOCAL in CFLAGS, so it can request a different level +# of optimization if needed +CKERNEL+=-O1 +endif +ifeq ($(GCC_MAJOR_VERSION),3) +CKERNEL+=-frename-registers --param max-inline-insns=5000 +endif + +endif +CKERNEL+=-DLINUX -Dlinux -include $(TL_DIR)/Makerules/LINUX/$(BUILD_TARGET).$(BUILD_TARGET_OS_VENDOR).$(BUILD_TARGET_OS_VERSION).h + +# Include directories for kernel +KERNELDIR=/lib/modules/$(BUILD_TARGET_OS_VERSION)/build +KERNEL_INCLUDE_DIRS=$(KERNELDIR)/include + +# linking +# ---------------------------- +LDMACH = +LDSYS = +MKSHLIB = $(CCC) $(CCDEBUG) $(COPT) -shared +ifeq "$(strip $(LIBFILES))" "" +MKARLIB = $(AR) crus$(space) +else +MKARLIB = $(MAKETOOLS_DIR)/mkarlib.sh $(AR) crus$(space) +endif +MKPARTIAL = $(LD) -r -o +MKMODULE = $(LD) -r -o + +LDLIBSRCH += $(foreach lib,$(LD_LIB_DIRS),-Xlinker -rpath-link -Xlinker $(lib)) +SYSLIBS = -lpthread +LDLIBS = -Xlinker --start-group $(foreach lib,$(LOCALLIBS) $(LOCALDEPLIBS) $(MODLIBS) $(MODDEPLIBS) $(PROJLIBS) $(PROJDEPLIBS),-l$(lib)) -Xlinker --end-group $(SYSLIBS) + +# libraries for partial link of a kernel loadable module +KERNELLIBS = diff --git a/Makerules/Target.LINUX.GNU.MIPS64 b/Makerules/Target.LINUX.GNU.MIPS64 new file mode 100755 index 0000000..9faec53 --- /dev/null +++ b/Makerules/Target.LINUX.GNU.MIPS64 @@ -0,0 +1,107 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** +# suffixes and commands to build targets for: +# BUILD_TARGET_OS=LINUX +# BUILD_TARGET_TOOLCHAIN=GNU +# BUILD_TARGET=MIPS64 +# Target specific defines for building LINUX target using GNU tools + +SHLIB_VERSION ?= 0.0 +LIB_PREFIX = $(BUILDDIR)/lib +SHLIB_SUFFIX = .so +SHLIB_VERSION_SUFFIX= .so.$(SHLIB_VERSION) +ARLIB_SUFFIX = .a +EXE_SUFFIX = +OBJ_SUFFIX = .o +ifdef BUILD_26 +KOBJ_SUFFIX = .ko +else +KOBJ_SUFFIX = .o +endif +EXP_SUFFIX = .exp +RES_SUFFIX = .res +PRE_SUFFIX = .pre + +# Paths: +# let compiler default inclusion of /usr/include, otherwise g++ builds broken +SYS_INCLUDE_DIRS = +SYS_LIB_DIRS = + +SBTOOLS_PATH = /usr/local/sbtools/x86-linux-rh7.2/mips-linux-2.3.1/bin + +CC = $(SBTOOLS_PATH)gcc +CCC = g++ +LD = ld +LINT = lint +AR = ar +NM = nm + +include $(TL_DIR)/Makerules/Defs.GNU + +# for GNU we set an soname on shared libraries +SHLIB_SONAME=$(notdir $(CMD_TARGETS_SHLIB)) + +# C/C++ compilation +# ---------------------------- +# -fcheck-new does the opposite of what the manual implies. +# -fcheck-new DISABLES the run-time test of return value from new +CMACH = -DTARGET_CPU_FAMILY_X86 -Wall -DCPU_BE -fno-strict-aliasing +CCMACH = $(CMACH) -fcheck-new -Wno-ctor-dtor-privacy +CSYS = +CCSYS = $(CSYS) +CCLIBS = +release_CCOPT_Flags =-O +debug_CCOPT_Flags = +# Assemble the optimization flags based upon desired build configuration. +CCOPT = $($(strip $(BUILD_CONFIG))_CCOPT_Flags) -DLINUX -Dlinux -D__LINUX__ +# for now assume C++ flags are valid on C compiler +COPT = $(CCOPT) +release_CCDEBUG_Flags = +release_CDEBUG_Flags = +debug_CCDEBUG_Flags =-g -DIB_DEBUG -DIB_TRACE $(CCPROJDEBUG) $(CCLOCALDEBUG) +debug_CDEBUG_Flags =-g -DIB_DEBUG -DIB_TRACE $(CPROJDEBUG) $(CLOCALDEBUG) +# Assemble the debug flags based upon desired build configuration. +CCDEBUG = $($(strip $(BUILD_CONFIG))_CCDEBUG_Flags) +CDEBUG = $($(strip $(BUILD_CONFIG))_CDEBUG_Flags) + +# linking +# ---------------------------- +LDMACH = +LDSYS = +MKSHLIB = $(CCC) $(CCDEBUG) $(COPT) -shared +ifeq "$(strip $(LIBFILES))" "" +MKARLIB = $(AR) crus$(space) +else +MKARLIB = $(MAKETOOLS_DIR)/mkarlib.sh $(AR) crus$(space) +endif +MKPARTIAL = $(LD) -r -o + +LDLIBSRCH += $(foreach lib,$(LD_LIB_DIRS),-Xlinker -rpath-link -Xlinker $(lib)) +SYSLIBS = -lpthread +LDLIBS = -Xlinker --start-group $(foreach lib,$(LOCALLIBS) $(LOCALDEPLIBS) $(MODLIBS) $(MODDEPLIBS) $(PROJLIBS) $(PROJDEPLIBS),-l$(lib)) -Xlinker --end-group $(SYSLIBS) diff --git a/Makerules/Target.LINUX.GNU.PPC64 b/Makerules/Target.LINUX.GNU.PPC64 new file mode 100755 index 0000000..6fdfba6 --- /dev/null +++ b/Makerules/Target.LINUX.GNU.PPC64 @@ -0,0 +1,159 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** +# suffixes and commands to build targets for: +# BUILD_TARGET_OS=LINUX +# BUILD_TARGET_TOOLCHAIN=GNU +# BUILD_TARGET=X86_64 +# Target specific defines for building LINUX target using GNU tools + +SHLIB_VERSION ?= 0.0 +LIB_PREFIX = $(BUILDDIR)/lib +SHLIB_SUFFIX = .so +SHLIB_VERSION_SUFFIX= .so.$(SHLIB_VERSION) +ARLIB_SUFFIX = .a +EXE_SUFFIX = +OBJ_SUFFIX = .o +ifdef BUILD_26 +KOBJ_SUFFIX = .ko +else +KOBJ_SUFFIX = .o +endif +EXP_SUFFIX = .exp +RES_SUFFIX = .res +PRE_SUFFIX = .pre + +# Paths: +# let compiler default inclusion of /usr/include, otherwise g++ builds broken +SYS_INCLUDE_DIRS = +SYS_LIB_DIRS = + +CC = gcc +CCC = g++ +# unfortunately defining ld breaks kbuild +#LD = ld +LINT = lint +AR = ar +NM = nm +OBJCOPY = objcopy + +include $(TL_DIR)/Makerules/Defs.GNU + +# for GNU we set an soname on shared libraries +SHLIB_SONAME=$(notdir $(CMD_TARGETS_SHLIB)) + +# C/C++ compilation +# ---------------------------- +# -fcheck-new does the opposite of what the manual implies. +# -fcheck-new DISABLES the run-time test of return value from new +CMACH = -pipe -DTARGET_CPU_FAMILY_PPC -Wall -D__PPC__ -DCPU_BE -m64 -fno-strict-aliasing +CCMACH = $(CMACH) -fcheck-new -Wno-ctor-dtor-privacy -fno-rtti +CSYS = -DLINUX -Dlinux -D__LINUX__ -DHAVEIOMMU +CCSYS = $(CSYS) +CCLIBS = +release_CCOPT_Flags = -O2 -fno-strength-reduce +debug_CCOPT_Flags = -O0 +release_COPT_Flags = -O2 -fno-strength-reduce +debug_COPT_Flags = -O0 +# Assemble the optimization flags based upon desired build configuration. +CCOPT = $($(strip $(BUILD_CONFIG))_CCOPT_Flags) +COPT = $($(strip $(BUILD_CONFIG))_COPT_Flags) +release_CCDEBUG_Flags = +release_CDEBUG_Flags = +debug_CCDEBUG_Flags =-g -DIB_DEBUG -DIB_TRACE $(CCPROJDEBUG) $(CCLOCALDEBUG) +debug_CDEBUG_Flags =-g -DIB_DEBUG -DIB_TRACE $(CPROJDEBUG) $(CLOCALDEBUG) +# Assemble the debug flags based upon desired build configuration. +CCDEBUG = $($(strip $(BUILD_CONFIG))_CCDEBUG_Flags) +CDEBUG = $($(strip $(BUILD_CONFIG))_CDEBUG_Flags) + +# Kernel build settings +#--------------------------------------------- +# use CKERNEL and KERNEL_INCLUDE_DIRS to augment CLOCAL, LOCAL_INCLUDE_DIRS when +# building a kernel module + +# strict-aliasing - disables optimizations related to unions/casts +# no-common - will put globals uninitialized in .bss instead of common +# hence get link error if multiple declaration +# preferred-stack-boundary=2 -align stack to 2^2 byte boundary, +# possible performance penalty for 64 bit data +# TBD, what does kernel use +# -D_I386_PTRACE_H was a workaround for a ptrace.h header file inclusion issue +# identify where needed and just put in that one makefile +# -include picks up special flags for SMP and MODVERSIONS, this allows portable +# kernel modules to be built for multiple system types from a single running +# system + +ifndef BUILD_26 + +CKERNEL=-D_KERNEL -D__KERNEL__ -DMODULE -DEXPORT_SYMTAB -mcmodel=kernel -Wno-trigraphs -mno-red-zone -fno-reorder-blocks -finline-limit=2000 -fno-strict-aliasing -fno-common -msoft-float +# omit frame pointer for simple functions +# take advantage of pentium pro instructions, default is i386 compatible code + +ifeq "$(BUILD_CONFIG)" "release" +CKERNEL+= -fomit-frame-pointer -O2 -fno-strength-reduce +else +# due to extern inline virt_to_phys in io.h in kernel, we must use at least -O1 +# COPT will follow CLOCAL in CFLAGS, so it can request a different level +# of optimization if needed +CKERNEL+= -O1 +endif + +ifeq "$(GCC_MAJOR_VERSION)" "3" +ifeq "$(GCC_MINOR_VERSION)" "3" +ifeq "$(BUILD_PLATFORM_OS_VENDOR)" "SuSE" +CKERNEL+=-fno-unit-at-a-time +endif +endif +endif + +endif +CKERNEL+=-m64 -include $(TL_DIR)/Makerules/LINUX/$(BUILD_TARGET).$(BUILD_TARGET_OS_VENDOR).$(BUILD_TARGET_OS_VERSION).h + +# Include directories for kernel +KERNELDIR=/lib/modules/$(BUILD_TARGET_OS_VERSION)/build +KERNEL_INCLUDE_DIRS=$(KERNELDIR)/include + +# linking +# ---------------------------- +LDMACH = -m64 +LDSYS = +MKSHLIB = $(CCC) $(CCDEBUG) $(COPT) -shared +ifeq "$(strip $(LIBFILES))" "" +MKARLIB = $(AR) crus$(space) +else +MKARLIB = $(MAKETOOLS_DIR)/mkarlib.sh $(AR) crus$(space) +endif +MKPARTIAL = $(LD) -melf64ppc -r -o +MKMODULE = $(LD) -melf64ppc -r -o + +LDLIBSRCH += $(foreach lib,$(LD_LIB_DIRS),-Xlinker -rpath-link -Xlinker $(lib)) +SYSLIBS = -lpthread +LDLIBS = -Xlinker --start-group $(foreach lib,$(LOCALLIBS) $(LOCALDEPLIBS) $(MODLIBS) $(MODDEPLIBS) $(PROJLIBS) $(PROJDEPLIBS),-l$(lib)) -Xlinker --end-group $(SYSLIBS) + +# libraries for partial link of a kernel loadable module +KERNELLIBS = diff --git a/Makerules/Target.LINUX.GNU.X86_64 b/Makerules/Target.LINUX.GNU.X86_64 new file mode 100755 index 0000000..5a852b3 --- /dev/null +++ b/Makerules/Target.LINUX.GNU.X86_64 @@ -0,0 +1,170 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** +# suffixes and commands to build targets for: +# BUILD_TARGET_OS=LINUX +# BUILD_TARGET_TOOLCHAIN=GNU +# BUILD_TARGET=X86_64 +# Target specific defines for building LINUX target using GNU tools + +SHLIB_VERSION ?= 0.0 +LIB_PREFIX = $(BUILDDIR)/lib +SHLIB_SUFFIX = .so +SHLIB_VERSION_SUFFIX= .so.$(SHLIB_VERSION) +ARLIB_SUFFIX = .a +EXE_SUFFIX = +OBJ_SUFFIX = .o +ifdef BUILD_26 +KOBJ_SUFFIX = .ko +else +KOBJ_SUFFIX = .o +endif +EXP_SUFFIX = .exp +RES_SUFFIX = .res +PRE_SUFFIX = .pre + +# Paths: +# let compiler default inclusion of /usr/include, otherwise g++ builds broken +SYS_INCLUDE_DIRS = +SYS_LIB_DIRS = + +CC = gcc +CCC = g++ +LD = ld +LINT = lint +AR = ar +NM = nm +OBJCOPY = objcopy +GZIP = gzip + +include $(TL_DIR)/Makerules/Defs.GNU + +# +# Override the GNU defaults. +# +CPIE = -fpie +CPIC = -fpic + +# for GNU we set an soname on shared libraries +SHLIB_SONAME=$(notdir $(CMD_TARGETS_SHLIB)) + +# C/C++ compilation +# ---------------------------- +# -fcheck-new does the opposite of what the manual implies. +# -fcheck-new DISABLES the run-time test of return value from new +CMACH = -pipe -DTARGET_CPU_FAMILY_X86 -Wall -Werror=format-security -D__X86_64__ -DCPU_LE -m64 -fno-strict-aliasing -fstack-protector +CCMACH = -pipe -DTARGET_CPU_FAMILY_X86 -Wall -Werror=format-security -D__X86_64__ -DCPU_LE -m64 -fno-strict-aliasing -fstack-protector -fcheck-new -Wno-ctor-dtor-privacy +ifeq ($(shell expr $(GCC_MAJOR_VERSION) \>= 7), 1) +ifeq ($(shell expr $(GCC_MINOR_VERSION) \>= 0), 1) +CMACH+= -std=gnu90 -Wno-misleading-indentation -Wno-format-truncation +endif +endif +CSYS = -DLINUX -Dlinux -D__LINUX__ +CCSYS = $(CSYS) +CCLIBS = +release_CCOPT_Flags =-O3 -fno-strength-reduce -D_FORTIFY_SOURCE=2 +debug_CCOPT_Flags = -O0 +release_COPT_Flags =-O3 -fno-strength-reduce -D_FORTIFY_SOURCE=2 +debug_COPT_Flags = -O0 +# Assemble the optimization flags based upon desired build configuration. +CCOPT = $($(strip $(BUILD_CONFIG))_CCOPT_Flags) +COPT = $($(strip $(BUILD_CONFIG))_COPT_Flags) +release_CCDEBUG_Flags =-g +release_CDEBUG_Flags =-g +debug_CCDEBUG_Flags =-g -DIB_DEBUG -DIB_TRACE $(CCPROJDEBUG) $(CCLOCALDEBUG) +debug_CDEBUG_Flags =-g -DIB_DEBUG -DIB_TRACE $(CPROJDEBUG) $(CLOCALDEBUG) +# Assemble the debug flags based upon desired build configuration. +CCDEBUG = $($(strip $(BUILD_CONFIG))_CCDEBUG_Flags) +CDEBUG = $($(strip $(BUILD_CONFIG))_CDEBUG_Flags) + +# Kernel build settings +#--------------------------------------------- +# use CKERNEL and KERNEL_INCLUDE_DIRS to augment CLOCAL, LOCAL_INCLUDE_DIRS when +# building a kernel module + +# strict-aliasing - disables optimizations related to unions/casts +# no-common - will put globals uninitialized in .bss instead of common +# hence get link error if multiple declaration +# preferred-stack-boundary=2 -align stack to 2^2 byte boundary, +# possible performance penalty for 64 bit data +# TBD, what does kernel use +# -D_I386_PTRACE_H was a workaround for a ptrace.h header file inclusion issue +# identify where needed and just put in that one makefile +# -include picks up special flags for SMP and MODVERSIONS, this allows portable +# kernel modules to be built for multiple system types from a single running +# system + +ifndef BUILD_26 + +CKERNEL=-D_KERNEL -D__KERNEL__ -DMODULE -DEXPORT_SYMTAB -mcmodel=kernel -Wno-trigraphs -mno-red-zone -fno-reorder-blocks -finline-limit=2000 -fno-strict-aliasing -fno-common -msoft-float +# omit frame pointer for simple functions +# take advantage of pentium pro instructions, default is i386 compatible code + +ifeq "$(BUILD_CONFIG)" "release" +CKERNEL+= -fomit-frame-pointer -O2 -fno-strength-reduce +else +# due to extern inline virt_to_phys in io.h in kernel, we must use at least -O1 +# COPT will follow CLOCAL in CFLAGS, so it can request a different level +# of optimization if needed +CKERNEL+= -O1 +endif + +ifeq "$(GCC_MAJOR_VERSION)" "3" +ifeq "$(GCC_MINOR_VERSION)" "3" +ifeq "$(BUILD_PLATFORM_OS_VENDOR)" "SuSE" +CKERNEL+=-fno-unit-at-a-time +endif +endif +endif + +endif +CKERNEL+=-include $(TL_DIR)/Makerules/LINUX/$(BUILD_TARGET).$(BUILD_TARGET_OS_VENDOR).$(BUILD_TARGET_OS_VERSION).h + +# Include directories for kernel +KERNELDIR=/lib/modules/$(BUILD_TARGET_OS_VERSION)/build +KERNEL_INCLUDE_DIRS=$(KERNELDIR)/include + +# linking +# ---------------------------- +LDMACH = +LDSYS = -Wl,-z,noexecstack -z relro -z now +MKSHLIB = $(CCC) $(CCDEBUG) $(COPT) -shared +ifeq "$(strip $(LIBFILES))" "" +MKARLIB = $(AR) crus$(space) +else +MKARLIB = $(MAKETOOLS_DIR)/mkarlib.sh $(AR) crus$(space) +endif +MKPARTIAL = $(LD) -r -o +MKMODULE = $(LD) -r -o + +LDLIBSRCH += $(foreach lib,$(LD_LIB_DIRS),-Xlinker -rpath-link -Xlinker $(lib)) +SYSLIBS = -lpthread +LDLIBS = -Xlinker --start-group $(foreach lib,$(LOCALLIBS) $(LOCALDEPLIBS) $(MODLIBS) $(MODDEPLIBS) $(PROJLIBS) $(PROJDEPLIBS),-l$(lib)) $(EXPLICITLIBS) -Xlinker --end-group $(SYSLIBS) + +# libraries for partial link of a kernel loadable module +KERNELLIBS = diff --git a/Makerules/Target.LINUX.INTEL.IA32 b/Makerules/Target.LINUX.INTEL.IA32 new file mode 100755 index 0000000..6507176 --- /dev/null +++ b/Makerules/Target.LINUX.INTEL.IA32 @@ -0,0 +1,132 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** +# suffixes and commands to build targets for: +# BUILD_TARGET_OS=LINUX +# BUILD_TARGET_TOOLCHAIN=INTEL +# BUILD_TARGET=IA32 +# Target specific defines for building Linux target using Intel Compiler 7.0 tools + +SHLIB_VERSION ?= 0.0 +LIB_PREFIX = $(BUILDDIR)/lib +SHLIB_SUFFIX = .so +SHLIB_VERSION_SUFFIX= .so.$(SHLIB_VERSION) +ARLIB_SUFFIX = .a +EXE_SUFFIX = +OBJ_SUFFIX = .o +EXP_SUFFIX = .exp +RES_SUFFIX = .res +PRE_SUFFIX = .pre + +# Paths: +# let compiler default inclusion of /usr/include, otherwise g++ builds broken +SYS_INCLUDE_DIRS = +SYS_LIB_DIRS = + +CC = icc +CCC = icc +LD = ld +LINT = lint +AR = xiar +NM = nm +OBJCOPY = objcopy + +include $(TL_DIR)/Makerules/Defs.INTEL + +# for GNU we set an soname on shared libraries +SHLIB_SONAME=$(notdir $(CMD_TARGETS_SHLIB)) + +# C/C++ compilation +# ---------------------------- +CMACH = -tpp7 -xW -parallel -ip -DTARGET_CPU_FAMILY_X86 -D__IA32__ -DLINUX -Dlinux -D__LINUX__ -D__GNUC__=3 -D____cacheline_aligned= -w# use Wall later -fno-strict-aliasing +CCMACH = $(CMACH) +CSYS = +CCSYS = +CCLIBS = +release_CCOPT_Flags = +debug_CCOPT_Flags = +release_COPT_Flags = +debug_COPT_Flags = +# Assemble the optimization flags based upon desired build configuration. +CCOPT = $($(strip $(BUILD_CONFIG))_CCOPT_Flags) +COPT = $($(strip $(BUILD_CONFIG))_COPT_Flags) +release_CCDEBUG_Flags = +release_CDEBUG_Flags = +debug_CCDEBUG_Flags =-g -O0 -DIB_DEBUG -DIB_TRACE $(CCPROJDEBUG) $(CCLOCALDEBUG) +debug_CDEBUG_Flags =-g -O0 -DIB_DEBUG -DIB_TRACE $(CPROJDEBUG) $(CLOCALDEBUG) +# Assemble the debug flags based upon desired build configuration. +CCDEBUG = $($(strip $(BUILD_CONFIG))_CCDEBUG_Flags) +CDEBUG = $($(strip $(BUILD_CONFIG))_CDEBUG_Flags) + +# Kernel build settings +#--------------------------------------------- +# use CKERNEL and KERNEL_INCLUDE_DIRS to augment CLOCAL, LOCAL_INCLUDE_DIRS when +# building a kernel module + +# strict-aliasing - disables optimizations related to unions/casts +# no-common - will put globals uninitialized in .bss instead of common +# hence get link error if multiple declaration +# -D_I386_PTRACE_H was a workaround for a ptrace.h header file inclusion issue +# identify where needed and just put in that one makefile +# -include picks up special flags for SMP and MODVERSIONS, this allows portable +# kernel modules to be built for multiple system types from a single running +# system +CKERNEL= -tpp7 -xW -parallel -ip -D__GNUC__=3 -D____cacheline_aligned= -D_KERNEL -D__KERNEL__ -DMODULE -DEXPORT_SYMTAB -include $(TL_DIR)/Makerules/LINUX/$(BUILD_TARGET).$(BUILD_TARGET_OS_VENDOR).$(BUILD_TARGET_OS_VERSION).h + +# omit frame pointer for simple functions +ifeq "$(BUILD_CONFIG)" "release" +CKERNEL+= #-fomit-frame-pointer +else +# due to extern inline virt_to_phys in io.h in kernel, we must use at least -O1 +# COPT will follow CLOCAL in CFLAGS, so it can request a different level +# of optimization if needed +CKERNEL+= #-O1 +endif + +# Include directories for kernel +KERNELDIR=/lib/modules/$(BUILD_TARGET_OS_VERSION)/build +KERNEL_INCLUDE_DIRS=$(KERNELDIR)/include /usr/include/g++-3/ke /usr/include/g++-3 + +# linking +# ---------------------------- +LDMACH = +LDSYS = +MKSHLIB = $(CCC) $(CCDEBUG) $(COPT) -shared +ifeq "$(strip $(LIBFILES))" "" +MKARLIB = $(AR) crus$(space) +else +MKARLIB = $(MAKETOOLS_DIR)/mkarlib.sh $(AR) crus$(space) +endif +MKPARTIAL = $(LD) -r -o +MKMODULE = $(LD) -r -o + +SYSLIBS = -lpthread +LDLIBS = -Xlinker --start-group $(foreach lib,$(LOCALLIBS) $(LOCALDEPLIBS) $(MODLIBS) $(MODDEPLIBS) $(PROJLIBS) $(PROJDEPLIBS),-l$(lib)) -Xlinker --end-group $(SYSLIBS) + +# libraries for partial link of a kernel loadable module +KERNELLIBS = diff --git a/Makerules/Target.LINUX.INTEL.IA64 b/Makerules/Target.LINUX.INTEL.IA64 new file mode 100755 index 0000000..010150f --- /dev/null +++ b/Makerules/Target.LINUX.INTEL.IA64 @@ -0,0 +1,132 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** +# suffixes and commands to build targets for: +# BUILD_TARGET_OS=LINUX +# BUILD_TARGET_TOOLCHAIN=INTEL +# BUILD_TARGET=IA64 +# Target specific defines for building Linux target using Intel Compiler 7.0 tools + +SHLIB_VERSION ?= 0.0 +LIB_PREFIX = $(BUILDDIR)/lib +SHLIB_SUFFIX = .so +SHLIB_VERSION_SUFFIX= .so.$(SHLIB_VERSION) +ARLIB_SUFFIX = .a +EXE_SUFFIX = +OBJ_SUFFIX = .o +EXP_SUFFIX = .exp +RES_SUFFIX = .res +PRE_SUFFIX = .pre + +# Paths: +# let compiler default inclusion of /usr/include, otherwise g++ builds broken +SYS_INCLUDE_DIRS = +SYS_LIB_DIRS = + +CC = ecc +CCC = ecc +LD = xild +LINT = lint +AR = xiar +NM = nm +OBJCOPY = objcopy + +include $(TL_DIR)/Makerules/Defs.INTEL + +# for GNU we set an soname on shared libraries +SHLIB_SONAME=$(notdir $(CMD_TARGETS_SHLIB)) + +# C/C++ compilation +# ---------------------------- +CMACH = -DTARGET_CPU_FAMILY_IA64 -D__IA64__ -DLINUX -Dlinux -D__LINUX__ -fno-strict-aliasing # use Wall later +CCMACH = $(CMACH) +CSYS = +CCSYS = +CCLIBS = +release_CCOPT_Flags = +debug_CCOPT_Flags = +release_COPT_Flags = +debug_COPT_Flags = +# Assemble the optimization flags based upon desired build configuration. +CCOPT = $($(strip $(BUILD_CONFIG))_CCOPT_Flags) +COPT = $($(strip $(BUILD_CONFIG))_COPT_Flags) +release_CCDEBUG_Flags = +release_CDEBUG_Flags = +debug_CCDEBUG_Flags =-g -O0 -DIB_DEBUG -DIB_TRACE $(CCPROJDEBUG) $(CCLOCALDEBUG) +debug_CDEBUG_Flags =-g -O0 -DIB_DEBUG -DIB_TRACE $(CPROJDEBUG) $(CLOCALDEBUG) +# Assemble the debug flags based upon desired build configuration. +CCDEBUG = $($(strip $(BUILD_CONFIG))_CCDEBUG_Flags) +CDEBUG = $($(strip $(BUILD_CONFIG))_CDEBUG_Flags) + +# Kernel build settings +#--------------------------------------------- +# use CKERNEL and KERNEL_INCLUDE_DIRS to augment CLOCAL, LOCAL_INCLUDE_DIRS when +# building a kernel module + +# strict-aliasing - disables optimizations related to unions/casts +# no-common - will put globals uninitialized in .bss instead of common +# hence get link error if multiple declaration +# -D_I386_PTRACE_H was a workaround for a ptrace.h header file inclusion issue +# identify where needed and just put in that one makefile +# -include picks up special flags for SMP and MODVERSIONS, this allows portable +# kernel modules to be built for multiple system types from a single running +# system +CKERNEL=-D_KERNEL -D__KERNEL__ -DMODULE -DEXPORT_SYMTAB -include $(TL_DIR)/Makerules/LINUX/$(BUILD_TARGET).$(BUILD_TARGET_OS_VENDOR).$(BUILD_TARGET_OS_VERSION).h + +# omit frame pointer for simple functions +ifeq "$(BUILD_CONFIG)" "release" +CKERNEL+= #-fomit-frame-pointer +else +# due to extern inline virt_to_phys in io.h in kernel, we must use at least -O1 +# COPT will follow CLOCAL in CFLAGS, so it can request a different level +# of optimization if needed +CKERNEL+= #-O1 +endif + +# Include directories for kernel +KERNELDIR=/lib/modules/$(BUILD_TARGET_OS_VERSION)/build +KERNEL_INCLUDE_DIRS=$(KERNELDIR)/include /usr/include/g++-3/ke /usr/include/g++-3 + +# linking +# ---------------------------- +LDMACH = +LDSYS = +MKSHLIB = $(CCC) $(CCDEBUG) $(COPT) -shared +ifeq "$(strip $(LIBFILES))" "" +MKARLIB = $(AR) crus$(space) +else +MKARLIB = $(MAKETOOLS_DIR)/mkarlib.sh $(AR) crus$(space) +endif +MKPARTIAL = $(LD) -r -o +MKMODULE = $(LD) -r -o + +SYSLIBS = -lpthread -lstdc++ +LDLIBS = -Xlinker --start-group $(foreach lib,$(LOCALLIBS) $(LOCALDEPLIBS) $(MODLIBS) $(MODDEPLIBS) $(PROJLIBS) $(PROJDEPLIBS),-l$(lib)) -Xlinker --end-group $(SYSLIBS) + +# libraries for partial link of a kernel loadable module +KERNELLIBS = diff --git a/Makerules/Target.LINUX.INTEL.X86_64 b/Makerules/Target.LINUX.INTEL.X86_64 new file mode 100755 index 0000000..a373262 --- /dev/null +++ b/Makerules/Target.LINUX.INTEL.X86_64 @@ -0,0 +1,158 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** +# suffixes and commands to build targets for: +# BUILD_TARGET_OS=LINUX +# BUILD_TARGET_TOOLCHAIN=GNU +# BUILD_TARGET=X86_64 +# Target specific defines for building LINUX target using GNU tools + +SHLIB_VERSION ?= 0.0 +LIB_PREFIX = $(BUILDDIR)/lib +SHLIB_SUFFIX = .so +SHLIB_VERSION_SUFFIX= .so.$(SHLIB_VERSION) +ARLIB_SUFFIX = .a +EXE_SUFFIX = +OBJ_SUFFIX = .o +ifdef BUILD_26 +KOBJ_SUFFIX = .ko +else +KOBJ_SUFFIX = .o +endif +EXP_SUFFIX = .exp +RES_SUFFIX = .res +PRE_SUFFIX = .pre + +# Paths: +# let compiler default inclusion of /usr/include, otherwise g++ builds broken +SYS_INCLUDE_DIRS = +SYS_LIB_DIRS = + +CC = icc +CCC = icc +LD = xild +LINT = lint +AR = xiar +NM = nm +OBJCOPY = objcopy + +include $(TL_DIR)/Makerules/Defs.GNU + +# for GNU we set an soname on shared libraries +SHLIB_SONAME=$(notdir $(CMD_TARGETS_SHLIB)) + +# C/C++ compilation +# ---------------------------- +# -fcheck-new does the opposite of what the manual implies. +# -fcheck-new DISABLES the run-time test of return value from new +CMACH = -DMWHEINZ -DTARGET_CPU_FAMILY_X86 -Wall -D__X86_64__ -DCPU_LE -Wall +CCMACH = $(CMACH) +CSYS = -DLINUX -Dlinux -D__LINUX__ +CCSYS = $(CSYS) +CCLIBS = +release_CCOPT_Flags =-fast -axSSE4.2 +debug_CCOPT_Flags =-axSSE4.2 +release_COPT_Flags =-fast -axSSE4.2 +debug_COPT_Flags =-axSSE4.2 +# Assemble the optimization flags based upon desired build configuration. +CCOPT = $($(strip $(BUILD_CONFIG))_CCOPT_Flags) +COPT = $($(strip $(BUILD_CONFIG))_COPT_Flags) +release_CCDEBUG_Flags = +release_CDEBUG_Flags = +debug_CCDEBUG_Flags =-g -DIB_DEBUG -DIB_TRACE $(CCPROJDEBUG) $(CCLOCALDEBUG) +debug_CDEBUG_Flags =-g -DIB_DEBUG -DIB_TRACE $(CPROJDEBUG) $(CLOCALDEBUG) +# Assemble the debug flags based upon desired build configuration. +CCDEBUG = $($(strip $(BUILD_CONFIG))_CCDEBUG_Flags) +CDEBUG = $($(strip $(BUILD_CONFIG))_CDEBUG_Flags) + +# Kernel build settings +#--------------------------------------------- +# use CKERNEL and KERNEL_INCLUDE_DIRS to augment CLOCAL, LOCAL_INCLUDE_DIRS when +# building a kernel module + +# strict-aliasing - disables optimizations related to unions/casts +# no-common - will put globals uninitialized in .bss instead of common +# hence get link error if multiple declaration +# preferred-stack-boundary=2 -align stack to 2^2 byte boundary, +# possible performance penalty for 64 bit data +# TBD, what does kernel use +# -D_I386_PTRACE_H was a workaround for a ptrace.h header file inclusion issue +# identify where needed and just put in that one makefile +# -include picks up special flags for SMP and MODVERSIONS, this allows portable +# kernel modules to be built for multiple system types from a single running +# system + +ifndef BUILD_26 + +CKERNEL=-D_KERNEL -D__KERNEL__ -DMODULE -DEXPORT_SYMTAB -mcmodel=kernel -Wno-trigraphs -mno-red-zone -fno-reorder-blocks -finline-limit=2000 -fno-strict-aliasing -fno-common -msoft-float +# omit frame pointer for simple functions +# take advantage of pentium pro instructions, default is i386 compatible code + +ifeq "$(BUILD_CONFIG)" "release" +CKERNEL+= -fomit-frame-pointer -O2 -fno-strength-reduce +else +# due to extern inline virt_to_phys in io.h in kernel, we must use at least -O1 +# COPT will follow CLOCAL in CFLAGS, so it can request a different level +# of optimization if needed +CKERNEL+= -O1 +endif + +ifeq "$(GCC_MAJOR_VERSION)" "3" +ifeq "$(GCC_MINOR_VERSION)" "3" +ifeq "$(BUILD_PLATFORM_OS_VENDOR)" "SuSE" +CKERNEL+=-fno-unit-at-a-time +endif +endif +endif + +endif +CKERNEL+=-include $(TL_DIR)/Makerules/LINUX/$(BUILD_TARGET).$(BUILD_TARGET_OS_VENDOR).$(BUILD_TARGET_OS_VERSION).h + +# Include directories for kernel +KERNELDIR=/lib/modules/$(BUILD_TARGET_OS_VERSION)/build +KERNEL_INCLUDE_DIRS=$(KERNELDIR)/include + +# linking +# ---------------------------- +LDMACH = +LDSYS = +MKSHLIB = $(CCC) $(CCDEBUG) $(COPT) -shared +ifeq "$(strip $(LIBFILES))" "" +MKARLIB = $(AR) crus$(space) +else +MKARLIB = $(MAKETOOLS_DIR)/mkarlib.sh $(AR) crus$(space) +endif +MKPARTIAL = $(LD) -r -o +MKMODULE = $(LD) -r -o + +LDLIBSRCH += $(foreach lib,$(LD_LIB_DIRS),-Xlinker -rpath-link -Xlinker $(lib)) +SYSLIBS = -lpthread +LDLIBS = -Xlinker --start-group $(foreach lib,$(LOCALLIBS) $(LOCALDEPLIBS) $(MODLIBS) $(MODDEPLIBS) $(PROJLIBS) $(PROJDEPLIBS),-l$(lib)) $(EXPLICITLIBS) -Xlinker --end-group $(SYSLIBS) + +# libraries for partial link of a kernel loadable module +KERNELLIBS = diff --git a/Makerules/Target.WIN32.GNU.I386 b/Makerules/Target.WIN32.GNU.I386 new file mode 100755 index 0000000..515512f --- /dev/null +++ b/Makerules/Target.WIN32.GNU.I386 @@ -0,0 +1,98 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** +# suffixes and commands to build targets for: +# BUILD_TARGET_OS=WIN32 +# BUILD_TARGET_TOOLCHAIN=GNU +# BUILD_TARGET=I386 +# CYGWIN BUILD_TARGET is used only to build devtools to run on Windows + +SHLIB_VERSION ?= 0.0 +LIB_PREFIX = $(BUILDDIR)/ +SHLIB_SUFFIX = .dll +SHLIB_VERSION_SUFFIX= .dll# or .$(SHLIB_VERSION).dll +ARLIB_SUFFIX = .lib +EXE_SUFFIX = .exe +OBJ_SUFFIX = .o +EXP_SUFFIX = .exp +RES_SUFFIX = .res +PRE_SUFFIX = .pre + +# Paths: +SYS_INCLUDE_DIRS= /usr/include /usr/local/ics/include/WIN32 +SYS_LIB_DIRS = + +CC = $(TOOLCHAIN_DIR)/i586-pc-mingw32-gcc +CCC = $(TOOLCHAIN_DIR)/i586-pc-mingw32-g++ +LD = $(TOOLCHAIN_DIR)/i586-pc-mingw32-ld +LINT = lint +AR = $(TOOLCHAIN_DIR)/i586-pc-mingw32-ar +NM = $(TOOLCHAIN_DIR)/i586-pc-mingw32-nm + +include $(TL_DIR)/Makerules/Defs.GNU + +# for GNU we set an soname on shared libraries +SHLIB_SONAME=$(notdir $(CMD_TARGETS_SHLIB)) + +# C/C++ compilation +# ---------------------------- +CMACH = -DTARGET_CPU_FAMILY_X86 -Wall -DWIN32 -DCPU_LE +CCMACH = $(CMACH) +CSYS = +CCSYS = +CSHARED = +CCSHARED = +CCLIBS = +release_CCOPT_Flags =-O +debug_CCOPT_Flags = +# Assemble the optimization flags based upon desired build configuration. +CCOPT = $($(strip $(BUILD_CONFIG))_CCOPT_Flags) +# for now assume C++ flags are valid on C compiler +COPT = $(CCOPT) +release_CCDEBUG_Flags = +release_CDEBUG_Flags = +debug_CCDEBUG_Flags =-g -DIB_DEBUG -D_DEBUG -DDEBUG -DIB_TRACE $(CCPROJDEBUG) $(CCLOCALDEBUG) +debug_CDEBUG_Flags =-g -DIB_DEBUG -D_DEBUG -DDEBUG -DIB_TRACE $(CPROJDEBUG) $(CLOCALDEBUG) +# Assemble the debug flags based upon desired build configuration. +CCDEBUG = $($(strip $(BUILD_CONFIG))_CCDEBUG_Flags) +# for now assume C++ flags are valid on C compiler +CDEBUG = $($(strip $(BUILD_CONFIG))_CDEBUG_Flags) + +# linking +# ---------------------------- +LDMACH = +MKSHLIB = $(CCC) $(CCDEBUG) $(COPT) -shared +ifeq "$(strip $(LIBFILES))" "" +MKARLIB = $(AR) crus$(space) +else +MKARLIB = $(MAKETOOLS_DIR)/mkarlib.sh $(AR) crus$(space) +endif +MKPARTIAL = $(LD) -r -o + +SYSLIBS = +LDLIBS = -Xlinker --start-group $(foreach lib,$(LOCALLIBS) $(LOCALDEPLIBS) $(MODLIBS) $(MODDEPLIBS) $(PROJLIBS) $(PROJDEPLIBS),-l$(lib)) -Xlinker --end-group $(SYSLIBS) diff --git a/Makerules/Target.WIN32.MSVS.WIN32 b/Makerules/Target.WIN32.MSVS.WIN32 new file mode 100755 index 0000000..bccdedf --- /dev/null +++ b/Makerules/Target.WIN32.MSVS.WIN32 @@ -0,0 +1,222 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** +# suffixes and commands to build targets for: +# BUILD_TARGET_OS=WIN32 +# BUILD_TARGET_TOOLCHAIN=MSVS +# BUILD_TARGET=WIN32 +# Target specific defines for building WIN32 Target using WIN32 tools (visual C++) + +SHLIB_VERSION ?= 0.0 +LIB_PREFIX = $(BUILDDIR)/ +SHLIB_SUFFIX = .dll +SHLIB_VERSION_SUFFIX= .dll # or .$(SHLIB_VERSION).dll +ARLIB_SUFFIX = .lib +EXE_SUFFIX = .exe +OBJ_SUFFIX = .obj +EXP_SUFFIX = .exp +RES_SUFFIX = .res +PRE_SUFFIX = .pre + +# Paths: +SYS_INCLUDE_DIRS= +SYS_LIB_DIRS = + +REGISTER?= + +# Basic Commands: +#RUNDOS = $(TOOLS_DIR)/rundos.exe + +# Compilation/Build Commands and flags: + +# Browse Compiler +# ---------------------------- +BSC = bscmake.exe +BSCSYS = /nologo /n +BSCLOCAL = # Empty by default +BSCFLAGS = $(BSCSYS) $(BSCENV) $(BSCPROJ) $(BSCMOD) $(BSCLOCAL) /o + +# C/C++ compilation +# ---------------------------- +CC = cl.exe +CCC = cl.exe +LINT = lint # TBD + # convert include dirs to windows paths so Windows tools can understand + # however use forward slashes so make is not confused +CINCSRCH = $(foreach inc,$(CINCLUDE_DIRS),/I $(subst \,/,$(shell cygpath -w $(inc)))) +#CANSI = /D "__STDC__=1" +CANSI = +CPIC = +CCPIC = +CMACH = /D TARGET_CPU_FAMILY_X86 /D WIN32 /D CPU_LE +CCEXH = /GX +CCNOEXH = /GX- +CCRTTI = /GR +CCNORTTI = /GR- +CSHARED = +CCSHARED = +CCLIBS = +ifdef PCH_TARGET +PCHFLAGS = $(addprefix /YX /Fp,$(PCH_TARGET)) +endif + # Define all variations of C/CC compiler flags. + # Subsystem based flags +none_CC_Flags = +console_CC_Flags =/D "_CONSOLE" /D "_MBCS" +windows_CC_Flags =/D "_WINDOWS" + # Build_Config and UseMFC based flags +common_CC_Flags =/D "STRICT" /nologo /W3 $(PCHFLAGS) /Fo /Fd /FR /FD +release_none_CC_Flags =$(common_CC_Flags) /Zi /D "NDEBUG" +release_no_mfc_CC_Flags =$(common_CC_Flags) /Zi /D "NDEBUG" /ML +release_shared_CC_Flags =$(common_CC_Flags) /Zi /D "NDEBUG" /MD /D "_AFXDLL" +release_static_CC_Flags =$(common_CC_Flags) /Zi /D "NDEBUG" /MT +debug_none_CC_Flags =$(common_CC_Flags) /Gm /Zi /D "IB_DEBUG" /D "_DEBUG" /D "DEBUG" /D "IB_TRACE" +debug_no_mfc_CC_Flags =$(common_CC_Flags) /Gm /Zi /D "IB_DEBUG" /D "_DEBUG" /D "DEBUG" /D "IB_TRACE" /MLd +debug_shared_CC_Flags =$(common_CC_Flags) /Gm /Zi /D "IB_DEBUG" /D "_DEBUG" /D "DEBUG" /D "IB_TRACE" /MDd /D "_AFXDLL" +debug_static_CC_Flags =$(common_CC_Flags) /Gm /Zi /D "IB_DEBUG" /D "_DEBUG" /D "DEBUG" /D "IB_TRACE" /MTd + # Config based flags for debug options +release_CCDEBUG_Flags = +debug_CCDEBUG_Flags = $(CCPROJDEBUG) $(CCLOCALDEBUG) +release_CDEBUG_Flags = +debug_CDEBUG_Flags = $(CPROJDEBUG) $(CLOCALDEBUG) + # Assemble the compiler flags based upon desired build configuration. +CCSYS =$($(strip $(SUBSYSTEM))_CC_Flags)\ + $($(strip $(BUILD_CONFIG))_$(strip $(USEMFC))_CC_Flags) \ + $($(strip $(BUILD_CONFIG))_CCDEBUG_Flags) + # for now assume most C++ flags are valid on C compiler +CSYS =$($(strip $(SUBSYSTEM))_CC_Flags)\ + $($(strip $(BUILD_CONFIG))_$(strip $(USEMFC))_CC_Flags) \ + $($(strip $(BUILD_CONFIG))_CDEBUG_Flags) + + # Define all variations of the C/CC compiler optimization flags. + # Config based flags for optimization options +release_CCOPT_Flags =/O2 +debug_CCOPT_Flags =/Od +# Assemble the optimization flags based upon desired build configuration. +CCOPT = $($(strip $(BUILD_CONFIG))_CCOPT_Flags) +# for now assume C++ flags are valid on C compiler +COPT = $(CCOPT) + +# linking +# ---------------------------- +LD = link.exe +LDMACH = /machine:I386 + # convert lib dirs to windows paths so Windows tools can understand + # however use forward slashes so make is not confused +LDLIBSRCH = $(foreach lib,$(LD_LIB_DIRS),/libpath:"$(subst \,/,$(shell cygpath -w $(lib)))") +LDSTRIP = +# the /debug option causes creation of the pdb file, however it does increase +# the exe file size significantly +LDPDB_RELEASE = /debug /pdbtype:sept /debugtype:both +LDPDB_DEBUG = /debug /pdbtype:sept /debugtype:both +LDOUTPUT = /out: + # Windows does not use -l + # DLLs and static libraries use a .lib file to link against +LDLIBS = $(foreach lib,$(LOCALLIBS) $(LOCALDEPLIBS) $(MODLIBS) $(MODDEPLIBS) $(PROJLIBS) $(PROJDEPLIBS),$(lib).lib) $(SYSLIBS) +LDSTATIC =/noshared + # Define all variations of linker flags. +none_LD_Flags = +console_LD_Flags =/subsystem:console +windows_LD_Flags =/subsystem:windows +common_LD_Flags =/nologo +release_LD_Flags =$(common_LD_Flags) /incremental:no $(LDPDB_RELEASE) +debug_LD_Flags =$(common_LD_Flags) /incremental:no $(LDPDB_DEBUG) + # Assemble the linker flags based upon desired build configuration. +LDSYS =$($(strip $(strip $(SUBSYSTEM)))_LD_Flags) $($(strip $(BUILD_CONFIG))_LD_Flags) + # Specify the default Microsoft WIN32 libs to link, if any. + # WIN32 libraries based on UseMFC selection +none_SYSLIBS = +no_mfc_SYSLIBS =kernel32.lib user32.lib gdi32.lib winspool.lib\ + comdlg32.lib advapi32.lib shell32.lib ole32.lib\ + oleaut32.lib uuid.lib odbc32.lib odbccp32.lib +shared_SYSLIBS = +static_SYSLIBS = +# Assemble the Common libraries based upon desired MFC configuration. +SYSLIBS =$($(strip $(USEMFC))_SYSLIBS) + +# Lexical Analyzer Generator +# -------------------------- +#LEX_LIB = fl # TBD + +# makedepend +# ---------------------------- +MAKEDEPEND = $(SHELL) $(MAKETOOLS_DIR)/makewin32depend.sh + +# IDL Compiler +# ---------------------------- +MIDL = midl.exe +MIDLSYS = /ms_ext /c_ext /win32 /nologo +MIDLLOCAL = # Empty by default +MIDLFLAGS = $(MIDLSYS) $(MIDLENV) $(MIDLPROJ) $(MIDLMOD) $(MIDLLOCAL) $(CINCSRCH) + +# targets to build from IDLFILE during INCLUDES phase +IDL_HEADERS = $(IDLFILE:.idl=.h) +IDL_OTHER = $(IDLFILE:.idl=_i.c) $(IDLFILE:.idl=_p.c) \ + $(IDLFILE:.idl=_dlldata.c) $(IDLFILE:.idl=.tlb) +IDL_TARGETS = $(IDL_HEADERS) $(IDL_OTHER) + +# building libraries +# ---------------------------- +MKARLIB = link.exe -lib /nologo /out: +MKPARTIAL = link.exe /nologo /r /out: +MKIMPLIB = link.exe -lib /nologo /def:"$(DEFFILE)" $(IMPLIBLOCAL) /out: +MKSHLIB = link.exe /nologo /dll +# Only add the /def option to the MKSHLIB link command if there is a .def file and no import +# library is being created. +ifneq "$(DEFFILE)" "" +ifeq "$(strip $(LIB_TARGETS_EXP))" "" + MKSHLIB+=/def:"$(DEFFILE)" +endif # LIB_TARGETS_EXP +endif # DEFFILE +ifeq "$(strip $(LIBFILES))" "" +ARLIBS= +else +ARLIBS=$(foreach lib, $(LIBFILES), $(subst \,/,$(shell cygpath -w $(MOD_LIB_DIR)/$(LIB_PREFIX)$(lib)$(ARLIB_SUFFIX)))) +endif + +# updating registry +# ---------------------------- +REGEXE = $(REGISTER)$(MAKETOOLS_DIR)/regexe.bat +REGDLL = $(REGISTER)$(MAKETOOLS_DIR)/regdll.bat + +# resource compiler +# ---------------------------- +RSC = rc.exe +# this defines the "CodePage" (ie. character set) which the text is in +RSCMACH = /l 0x409 +# Define all variations of resource compiler flags. +none_RSC_Flags = +release_RSC_Flags =/D "NDEBUG" +nodebug_RSC_Flags =/D "NDEBUG" +debug_RSC_Flags =/D "_DEBUG" /D "DEBUG" +# Assemble the resource compiler flags based upon desired build configuration. +RSCLOCAL = # Empty by default +RSCSYS = $($(strip $(BUILD_CONFIG))_RSC_Flags) +# stupid RSC compiler uses /i instead of /I for include paths +RSCINCSRCH = $(foreach inc,$(CINCLUDE_DIRS),/i $(subst \,/,$(shell cygpath -w $(inc)))) +RSCFLAGS= $(RSCMACH) $(RSCSYS) $(RSCENV) $(RSCPROJ) $(RSCMOD) $(RSCLOCAL) $(RSCINCSRCH) diff --git a/Makerules/Target.WIN32.WIN32.WIN32 b/Makerules/Target.WIN32.WIN32.WIN32 new file mode 100755 index 0000000..27761f7 --- /dev/null +++ b/Makerules/Target.WIN32.WIN32.WIN32 @@ -0,0 +1,222 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** +# suffixes and commands to build targets for: +# BUILD_TARGET_OS=WIN32 +# BUILD_TARGET_TOOLCHAIN=WIN32 +# BUILD_TARGET=WIN32 +# Target specific defines for building WIN32 Target using WIN32 tools (visual C++) + +SHLIB_VERSION ?= 0.0 +LIB_PREFIX = $(BUILDDIR)/ +SHLIB_SUFFIX = .dll +SHLIB_VERSION_SUFFIX= .dll # or .$(SHLIB_VERSION).dll +ARLIB_SUFFIX = .lib +EXE_SUFFIX = .exe +OBJ_SUFFIX = .obj +EXP_SUFFIX = .exp +RES_SUFFIX = .res +PRE_SUFFIX = .pre + +# Paths: +SYS_INCLUDE_DIRS= +SYS_LIB_DIRS = + +REGISTER?= + +# Basic Commands: +#RUNDOS = $(TOOLS_DIR)/rundos.exe + +# Compilation/Build Commands and flags: + +# Browse Compiler +# ---------------------------- +BSC = bscmake.exe +BSCSYS = /nologo /n +BSCLOCAL = # Empty by default +BSCFLAGS = $(BSCSYS) $(BSCENV) $(BSCPROJ) $(BSCMOD) $(BSCLOCAL) /o + +# C/C++ compilation +# ---------------------------- +CC = cl.exe +CCC = cl.exe +LINT = lint # TBD + # convert include dirs to windows paths so Windows tools can understand + # however use forward slashes so make is not confused +CINCSRCH = $(foreach inc,$(CINCLUDE_DIRS),/I $(subst \,/,$(shell cygpath -w $(inc)))) +#CANSI = /D "__STDC__=1" +CANSI = +CPIC = +CCPIC = +CMACH = /D TARGET_CPU_FAMILY_X86 /D WIN32 /D CPU_LE +CCEXH = /GX +CCNOEXH = /GX- +CCRTTI = /GR +CCNORTTI = /GR- +CSHARED = +CCSHARED = +CCLIBS = +ifdef PCH_TARGET +PCHFLAGS = $(addprefix /YX /Fp,$(PCH_TARGET)) +endif + # Define all variations of C/CC compiler flags. + # Subsystem based flags +none_CC_Flags = +console_CC_Flags =/D "_CONSOLE" /D "_MBCS" +windows_CC_Flags =/D "_WINDOWS" + # Build_Config and UseMFC based flags +common_CC_Flags =/D "STRICT" /nologo /W3 $(PCHFLAGS) /Fo /Fd /FR /FD +release_none_CC_Flags =$(common_CC_Flags) /Zi /D "NDEBUG" +release_no_mfc_CC_Flags =$(common_CC_Flags) /Zi /D "NDEBUG" /ML +release_shared_CC_Flags =$(common_CC_Flags) /Zi /D "NDEBUG" /MD /D "_AFXDLL" +release_static_CC_Flags =$(common_CC_Flags) /Zi /D "NDEBUG" /MT +debug_none_CC_Flags =$(common_CC_Flags) /Gm /Zi /D "IB_DEBUG" /D "_DEBUG" /D "DEBUG" /D "IB_TRACE" +debug_no_mfc_CC_Flags =$(common_CC_Flags) /Gm /Zi /D "IB_DEBUG" /D "_DEBUG" /D "DEBUG" /D "IB_TRACE" /MLd +debug_shared_CC_Flags =$(common_CC_Flags) /Gm /Zi /D "IB_DEBUG" /D "_DEBUG" /D "DEBUG" /D "IB_TRACE" /MDd /D "_AFXDLL" +debug_static_CC_Flags =$(common_CC_Flags) /Gm /Zi /D "IB_DEBUG" /D "_DEBUG" /D "DEBUG" /D "IB_TRACE" /MTd + # Config based flags for debug options +release_CCDEBUG_Flags = +debug_CCDEBUG_Flags = $(CCPROJDEBUG) $(CCLOCALDEBUG) +release_CDEBUG_Flags = +debug_CDEBUG_Flags = $(CPROJDEBUG) $(CLOCALDEBUG) + # Assemble the compiler flags based upon desired build configuration. +CCSYS =$($(strip $(SUBSYSTEM))_CC_Flags)\ + $($(strip $(BUILD_CONFIG))_$(strip $(USEMFC))_CC_Flags) \ + $($(strip $(BUILD_CONFIG))_CCDEBUG_Flags) + # for now assume most C++ flags are valid on C compiler +CSYS =$($(strip $(SUBSYSTEM))_CC_Flags)\ + $($(strip $(BUILD_CONFIG))_$(strip $(USEMFC))_CC_Flags) \ + $($(strip $(BUILD_CONFIG))_CDEBUG_Flags) + + # Define all variations of the C/CC compiler optimization flags. + # Config based flags for optimization options +release_CCOPT_Flags =/O2 +debug_CCOPT_Flags =/Od +# Assemble the optimization flags based upon desired build configuration. +CCOPT = $($(strip $(BUILD_CONFIG))_CCOPT_Flags) +# for now assume C++ flags are valid on C compiler +COPT = $(CCOPT) + +# linking +# ---------------------------- +LD = link.exe +LDMACH = /machine:I386 + # convert lib dirs to windows paths so Windows tools can understand + # however use forward slashes so make is not confused +LDLIBSRCH = $(foreach lib,$(LD_LIB_DIRS),/libpath:"$(subst \,/,$(shell cygpath -w $(lib)))") +LDSTRIP = +# the /debug option causes creation of the pdb file, however it does increase +# the exe file size significantly +LDPDB_RELEASE = /debug /pdbtype:sept /debugtype:both +LDPDB_DEBUG = /debug /pdbtype:sept /debugtype:both +LDOUTPUT = /out: + # Windows does not use -l + # DLLs and static libraries use a .lib file to link against +LDLIBS = $(foreach lib,$(LOCALLIBS) $(LOCALDEPLIBS) $(MODLIBS) $(MODDEPLIBS) $(PROJLIBS) $(PROJDEPLIBS),$(lib).lib) $(SYSLIBS) +LDSTATIC =/noshared + # Define all variations of linker flags. +none_LD_Flags = +console_LD_Flags =/subsystem:console +windows_LD_Flags =/subsystem:windows +common_LD_Flags =/nologo +release_LD_Flags =$(common_LD_Flags) /incremental:no $(LDPDB_RELEASE) +debug_LD_Flags =$(common_LD_Flags) /incremental:no $(LDPDB_DEBUG) + # Assemble the linker flags based upon desired build configuration. +LDSYS =$($(strip $(strip $(SUBSYSTEM)))_LD_Flags) $($(strip $(BUILD_CONFIG))_LD_Flags) + # Specify the default Microsoft WIN32 libs to link, if any. + # WIN32 libraries based on UseMFC selection +none_SYSLIBS = +no_mfc_SYSLIBS =kernel32.lib user32.lib gdi32.lib winspool.lib\ + comdlg32.lib advapi32.lib shell32.lib ole32.lib\ + oleaut32.lib uuid.lib odbc32.lib odbccp32.lib +shared_SYSLIBS = +static_SYSLIBS = +# Assemble the Common libraries based upon desired MFC configuration. +SYSLIBS =$($(strip $(USEMFC))_SYSLIBS) + +# Lexical Analyzer Generator +# -------------------------- +#LEX_LIB = fl # TBD + +# makedepend +# ---------------------------- +MAKEDEPEND = $(SHELL) $(MAKETOOLS_DIR)/makewin32depend.sh + +# IDL Compiler +# ---------------------------- +MIDL = midl.exe +MIDLSYS = /ms_ext /c_ext /win32 /nologo +MIDLLOCAL = # Empty by default +MIDLFLAGS = $(MIDLSYS) $(MIDLENV) $(MIDLPROJ) $(MIDLMOD) $(MIDLLOCAL) $(CINCSRCH) + +# targets to build from IDLFILE during INCLUDES phase +IDL_HEADERS = $(IDLFILE:.idl=.h) +IDL_OTHER = $(IDLFILE:.idl=_i.c) $(IDLFILE:.idl=_p.c) \ + $(IDLFILE:.idl=_dlldata.c) $(IDLFILE:.idl=.tlb) +IDL_TARGETS = $(IDL_HEADERS) $(IDL_OTHER) + +# building libraries +# ---------------------------- +MKARLIB = link.exe -lib /nologo /out: +MKPARTIAL = link.exe /nologo /r /out: +MKIMPLIB = link.exe -lib /nologo /def:"$(DEFFILE)" $(IMPLIBLOCAL) /out: +MKSHLIB = link.exe /nologo /dll +# Only add the /def option to the MKSHLIB link command if there is a .def file and no import +# library is being created. +ifneq "$(DEFFILE)" "" +ifeq "$(strip $(LIB_TARGETS_EXP))" "" + MKSHLIB+=/def:"$(DEFFILE)" +endif # LIB_TARGETS_EXP +endif # DEFFILE +ifeq "$(strip $(LIBFILES))" "" +ARLIBS= +else +ARLIBS=$(foreach lib, $(LIBFILES), $(subst \,/,$(shell cygpath -w $(MOD_LIB_DIR)/$(LIB_PREFIX)$(lib)$(ARLIB_SUFFIX)))) +endif + +# updating registry +# ---------------------------- +REGEXE = $(REGISTER)$(MAKETOOLS_DIR)/regexe.bat +REGDLL = $(REGISTER)$(MAKETOOLS_DIR)/regdll.bat + +# resource compiler +# ---------------------------- +RSC = rc.exe +# this defines the "CodePage" (ie. character set) which the text is in +RSCMACH = /l 0x409 +# Define all variations of resource compiler flags. +none_RSC_Flags = +release_RSC_Flags =/D "NDEBUG" +nodebug_RSC_Flags =/D "NDEBUG" +debug_RSC_Flags =/D "_DEBUG" /D "DEBUG" +# Assemble the resource compiler flags based upon desired build configuration. +RSCLOCAL = # Empty by default +RSCSYS = $($(strip $(BUILD_CONFIG))_RSC_Flags) +# stupid RSC compiler uses /i instead of /I for include paths +RSCINCSRCH = $(foreach inc,$(CINCLUDE_DIRS),/i $(subst \,/,$(shell cygpath -w $(inc)))) +RSCFLAGS= $(RSCMACH) $(RSCSYS) $(RSCENV) $(RSCPROJ) $(RSCMOD) $(RSCLOCAL) $(RSCINCSRCH) diff --git a/Makerules/generic-2.4.22-i686-bigmem.config b/Makerules/generic-2.4.22-i686-bigmem.config new file mode 100644 index 0000000..23ad918 --- /dev/null +++ b/Makerules/generic-2.4.22-i686-bigmem.config @@ -0,0 +1,1748 @@ +# +# Automatically generated by make menuconfig: don't edit +# +CONFIG_X86=y +# CONFIG_SBUS is not set +CONFIG_UID16=y + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y + +# +# Loadable module support +# +CONFIG_MODULES=y +CONFIG_MODVERSIONS=y +CONFIG_KMOD=y + +# +# Processor type and features +# +# CONFIG_M386 is not set +# CONFIG_M486 is not set +# CONFIG_M586 is not set +# CONFIG_M586TSC is not set +# CONFIG_M586MMX is not set +CONFIG_M686=y +# CONFIG_MPENTIUMIII is not set +# CONFIG_MPENTIUM4 is not set +# CONFIG_MK6 is not set +# CONFIG_MK7 is not set +# CONFIG_MK8 is not set +# CONFIG_MELAN is not set +# CONFIG_MCRUSOE is not set +# CONFIG_MWINCHIPC6 is not set +# CONFIG_MWINCHIP2 is not set +# CONFIG_MWINCHIP3D is not set +# CONFIG_MCYRIXIII is not set +# CONFIG_MVIAC3_2 is not set +CONFIG_X86_WP_WORKS_OK=y +CONFIG_X86_INVLPG=y +CONFIG_X86_CMPXCHG=y +CONFIG_X86_XADD=y +CONFIG_X86_BSWAP=y +CONFIG_X86_POPAD_OK=y +# CONFIG_RWSEM_GENERIC_SPINLOCK is not set +CONFIG_RWSEM_XCHGADD_ALGORITHM=y +CONFIG_X86_L1_CACHE_SHIFT=5 +CONFIG_X86_HAS_TSC=y +CONFIG_X86_GOOD_APIC=y +CONFIG_X86_PGE=y +CONFIG_X86_USE_PPRO_CHECKSUM=y +CONFIG_X86_PPRO_FENCE=y +CONFIG_X86_F00F_WORKS_OK=y +CONFIG_X86_MCE=y +CONFIG_TOSHIBA=m +CONFIG_I8K=m +CONFIG_MICROCODE=m +CONFIG_X86_MSR=m +CONFIG_X86_CPUID=m +# CONFIG_NOHIGHMEM is not set +# CONFIG_HIGHMEM4G is not set +CONFIG_HIGHMEM64G=y +CONFIG_HIGHMEM=y +CONFIG_X86_PAE=y +CONFIG_HIGHIO=y +# CONFIG_MATH_EMULATION is not set +CONFIG_MTRR=y +CONFIG_SMP=y +# CONFIG_X86_NUMA is not set +# CONFIG_X86_TSC_DISABLE is not set +CONFIG_X86_TSC=y +CONFIG_HAVE_DEC_LOCK=y + +# +# General setup +# +CONFIG_NET=y +CONFIG_X86_IO_APIC=y +CONFIG_X86_LOCAL_APIC=y +CONFIG_PCI=y +# CONFIG_PCI_GOBIOS is not set +# CONFIG_PCI_GODIRECT is not set +CONFIG_PCI_GOANY=y +CONFIG_PCI_BIOS=y +CONFIG_PCI_DIRECT=y +CONFIG_ISA=y +CONFIG_PCI_NAMES=y +CONFIG_EISA=y +# CONFIG_MCA is not set +CONFIG_HOTPLUG=y + +# +# PCMCIA/CardBus support +# +CONFIG_PCMCIA=m +CONFIG_CARDBUS=y +CONFIG_TCIC=y +CONFIG_I82092=y +CONFIG_I82365=y + +# +# PCI Hotplug Support +# +CONFIG_HOTPLUG_PCI=y +# CONFIG_HOTPLUG_PCI_COMPAQ is not set +# CONFIG_HOTPLUG_PCI_COMPAQ_NVRAM is not set +CONFIG_HOTPLUG_PCI_IBM=m +CONFIG_SYSVIPC=y +CONFIG_BSD_PROCESS_ACCT=y +CONFIG_SYSCTL=y +CONFIG_KCORE_ELF=y +# CONFIG_KCORE_AOUT is not set +CONFIG_BINFMT_AOUT=y +CONFIG_BINFMT_ELF=y +CONFIG_BINFMT_MISC=y +CONFIG_PM=y +CONFIG_APM=y +# CONFIG_APM_IGNORE_USER_SUSPEND is not set +# CONFIG_APM_DO_ENABLE is not set +CONFIG_APM_CPU_IDLE=y +# CONFIG_APM_DISPLAY_BLANK is not set +CONFIG_APM_RTC_IS_GMT=y +# CONFIG_APM_ALLOW_INTS is not set +# CONFIG_APM_REAL_MODE_POWER_OFF is not set + +# +# ACPI Support +# +# CONFIG_ACPI is not set + +# +# Memory Technology Devices (MTD) +# +# CONFIG_MTD is not set + +# +# Parallel port support +# +CONFIG_PARPORT=m +CONFIG_PARPORT_PC=m +CONFIG_PARPORT_PC_CML1=m +CONFIG_PARPORT_SERIAL=m +# CONFIG_PARPORT_PC_FIFO is not set +# CONFIG_PARPORT_PC_SUPERIO is not set +CONFIG_PARPORT_PC_PCMCIA=m +# CONFIG_PARPORT_AMIGA is not set +# CONFIG_PARPORT_MFC3 is not set +# CONFIG_PARPORT_ATARI is not set +# CONFIG_PARPORT_GSC is not set +# CONFIG_PARPORT_SUNBPP is not set +# CONFIG_PARPORT_OTHER is not set +CONFIG_PARPORT_1284=y + +# +# Plug and Play configuration +# +CONFIG_PNP=y +CONFIG_ISAPNP=y + +# +# Block devices +# +CONFIG_BLK_DEV_FD=y +CONFIG_BLK_DEV_XD=m +CONFIG_PARIDE=m +CONFIG_PARIDE_PARPORT=m +CONFIG_PARIDE_PD=m +CONFIG_PARIDE_PCD=m +CONFIG_PARIDE_PF=m +CONFIG_PARIDE_PT=m +CONFIG_PARIDE_PG=m +CONFIG_PARIDE_ATEN=m +CONFIG_PARIDE_BPCK=m +CONFIG_PARIDE_BPCK6=m +CONFIG_PARIDE_COMM=m +CONFIG_PARIDE_DSTR=m +CONFIG_PARIDE_FIT2=m +CONFIG_PARIDE_FIT3=m +CONFIG_PARIDE_EPAT=m +CONFIG_PARIDE_EPATC8=y +CONFIG_PARIDE_EPIA=m +CONFIG_PARIDE_FRIQ=m +CONFIG_PARIDE_FRPW=m +CONFIG_PARIDE_KBIC=m +CONFIG_PARIDE_KTTI=m +CONFIG_PARIDE_ON20=m +CONFIG_PARIDE_ON26=m +CONFIG_BLK_CPQ_DA=m +CONFIG_BLK_CPQ_CISS_DA=m +CONFIG_CISS_SCSI_TAPE=y +CONFIG_BLK_DEV_DAC960=m +CONFIG_BLK_DEV_UMEM=m +CONFIG_BLK_DEV_LOOP=m +CONFIG_BLK_DEV_NBD=m +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_SIZE=4096 +CONFIG_BLK_DEV_INITRD=y +CONFIG_BLK_STATS=y + +# +# Multi-device support (RAID and LVM) +# +CONFIG_MD=y +CONFIG_BLK_DEV_MD=y +CONFIG_MD_LINEAR=m +CONFIG_MD_RAID0=m +CONFIG_MD_RAID1=m +CONFIG_MD_RAID5=m +CONFIG_MD_MULTIPATH=m +CONFIG_BLK_DEV_LVM=m + +# +# Networking options +# +CONFIG_PACKET=y +CONFIG_PACKET_MMAP=y +CONFIG_NETLINK_DEV=y +CONFIG_NETFILTER=y +# CONFIG_NETFILTER_DEBUG is not set +CONFIG_FILTER=y +CONFIG_UNIX=y +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +CONFIG_IP_ADVANCED_ROUTER=y +CONFIG_IP_MULTIPLE_TABLES=y +CONFIG_IP_ROUTE_FWMARK=y +CONFIG_IP_ROUTE_NAT=y +CONFIG_IP_ROUTE_MULTIPATH=y +CONFIG_IP_ROUTE_TOS=y +CONFIG_IP_ROUTE_VERBOSE=y +# CONFIG_IP_PNP is not set +CONFIG_NET_IPIP=m +CONFIG_NET_IPGRE=m +CONFIG_NET_IPGRE_BROADCAST=y +CONFIG_IP_MROUTE=y +CONFIG_IP_PIMSM_V1=y +CONFIG_IP_PIMSM_V2=y +# CONFIG_ARPD is not set +# CONFIG_INET_ECN is not set +CONFIG_SYN_COOKIES=y + +# +# IP: Netfilter Configuration +# +CONFIG_IP_NF_CONNTRACK=m +CONFIG_IP_NF_FTP=m +CONFIG_IP_NF_AMANDA=m +CONFIG_IP_NF_TFTP=m +CONFIG_IP_NF_IRC=m +CONFIG_IP_NF_QUEUE=m +CONFIG_IP_NF_IPTABLES=m +CONFIG_IP_NF_MATCH_LIMIT=m +CONFIG_IP_NF_MATCH_MAC=m +CONFIG_IP_NF_MATCH_PKTTYPE=m +CONFIG_IP_NF_MATCH_MARK=m +CONFIG_IP_NF_MATCH_MULTIPORT=m +CONFIG_IP_NF_MATCH_TOS=m +CONFIG_IP_NF_MATCH_RECENT=m +CONFIG_IP_NF_MATCH_ECN=m +CONFIG_IP_NF_MATCH_DSCP=m +CONFIG_IP_NF_MATCH_AH_ESP=m +CONFIG_IP_NF_MATCH_LENGTH=m +CONFIG_IP_NF_MATCH_TTL=m +CONFIG_IP_NF_MATCH_TCPMSS=m +CONFIG_IP_NF_MATCH_HELPER=m +CONFIG_IP_NF_MATCH_STATE=m +CONFIG_IP_NF_MATCH_CONNTRACK=m +CONFIG_IP_NF_MATCH_UNCLEAN=m +CONFIG_IP_NF_MATCH_OWNER=m +CONFIG_IP_NF_FILTER=m +CONFIG_IP_NF_TARGET_REJECT=m +CONFIG_IP_NF_TARGET_MIRROR=m +CONFIG_IP_NF_NAT=m +CONFIG_IP_NF_NAT_NEEDED=y +CONFIG_IP_NF_TARGET_MASQUERADE=m +CONFIG_IP_NF_TARGET_REDIRECT=m +CONFIG_IP_NF_NAT_AMANDA=m +CONFIG_IP_NF_NAT_LOCAL=y +CONFIG_IP_NF_NAT_SNMP_BASIC=m +CONFIG_IP_NF_NAT_IRC=m +CONFIG_IP_NF_NAT_FTP=m +CONFIG_IP_NF_NAT_TFTP=m +CONFIG_IP_NF_MANGLE=m +CONFIG_IP_NF_TARGET_TOS=m +CONFIG_IP_NF_TARGET_ECN=m +CONFIG_IP_NF_TARGET_DSCP=m +CONFIG_IP_NF_TARGET_MARK=m +CONFIG_IP_NF_TARGET_LOG=m +CONFIG_IP_NF_TARGET_ULOG=m +CONFIG_IP_NF_TARGET_TCPMSS=m +CONFIG_IP_NF_ARPTABLES=m +CONFIG_IP_NF_ARPFILTER=m +CONFIG_IP_NF_ARP_MANGLE=m +CONFIG_IP_NF_COMPAT_IPCHAINS=m +CONFIG_IP_NF_NAT_NEEDED=y +CONFIG_IP_NF_COMPAT_IPFWADM=m +CONFIG_IP_NF_NAT_NEEDED=y +CONFIG_IPV6=m + +# +# IPv6: Netfilter Configuration +# +# CONFIG_IP6_NF_QUEUE is not set +CONFIG_IP6_NF_IPTABLES=m +CONFIG_IP6_NF_MATCH_LIMIT=m +CONFIG_IP6_NF_MATCH_MAC=m +CONFIG_IP6_NF_MATCH_RT=m +CONFIG_IP6_NF_MATCH_OPTS=m +CONFIG_IP6_NF_MATCH_FRAG=m +CONFIG_IP6_NF_MATCH_HL=m +CONFIG_IP6_NF_MATCH_MULTIPORT=m +CONFIG_IP6_NF_MATCH_OWNER=m +CONFIG_IP6_NF_MATCH_MARK=m +CONFIG_IP6_NF_MATCH_IPV6HEADER=m +CONFIG_IP6_NF_MATCH_AHESP=m +CONFIG_IP6_NF_MATCH_LENGTH=m +CONFIG_IP6_NF_MATCH_EUI64=m +CONFIG_IP6_NF_FILTER=m +CONFIG_IP6_NF_TARGET_LOG=m +CONFIG_IP6_NF_MANGLE=m +# CONFIG_IP6_NF_TARGET_MARK is not set +# CONFIG_KHTTPD is not set +CONFIG_ATM=m +CONFIG_ATM_CLIP=m +# CONFIG_ATM_CLIP_NO_ICMP is not set +CONFIG_ATM_LANE=m +CONFIG_ATM_MPOA=m +CONFIG_ATM_BR2684=m +CONFIG_ATM_BR2684_IPFILTER=y +CONFIG_VLAN_8021Q=m +CONFIG_IPX=m +# CONFIG_IPX_INTERN is not set +CONFIG_ATALK=m + +# +# Appletalk devices +# +CONFIG_DEV_APPLETALK=y +CONFIG_LTPC=m +CONFIG_COPS=m +CONFIG_COPS_DAYNA=y +CONFIG_COPS_TANGENT=y +CONFIG_IPDDP=m +CONFIG_IPDDP_ENCAP=y +CONFIG_IPDDP_DECAP=y +CONFIG_DECNET=m +CONFIG_DECNET_SIOCGIFCONF=y +CONFIG_DECNET_ROUTER=y +CONFIG_DECNET_ROUTE_FWMARK=y +CONFIG_BRIDGE=m +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_LLC is not set +CONFIG_NET_DIVERT=y +# CONFIG_ECONET is not set +CONFIG_WAN_ROUTER=m +# CONFIG_NET_FASTROUTE is not set +# CONFIG_NET_HW_FLOWCONTROL is not set + +# +# QoS and/or fair queueing +# +CONFIG_NET_SCHED=y +CONFIG_NET_SCH_CBQ=m +CONFIG_NET_SCH_HTB=m +CONFIG_NET_SCH_CSZ=m +# CONFIG_NET_SCH_ATM is not set +CONFIG_NET_SCH_PRIO=m +CONFIG_NET_SCH_RED=m +CONFIG_NET_SCH_SFQ=m +CONFIG_NET_SCH_TEQL=m +CONFIG_NET_SCH_TBF=m +CONFIG_NET_SCH_GRED=m +CONFIG_NET_SCH_DSMARK=m +CONFIG_NET_SCH_INGRESS=m +CONFIG_NET_QOS=y +CONFIG_NET_ESTIMATOR=y +CONFIG_NET_CLS=y +CONFIG_NET_CLS_TCINDEX=m +CONFIG_NET_CLS_ROUTE4=m +CONFIG_NET_CLS_ROUTE=y +CONFIG_NET_CLS_FW=m +CONFIG_NET_CLS_U32=m +CONFIG_NET_CLS_RSVP=m +CONFIG_NET_CLS_RSVP6=m +CONFIG_NET_CLS_POLICE=y + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set + +# +# Telephony Support +# +CONFIG_PHONE=m +CONFIG_PHONE_IXJ=m +CONFIG_PHONE_IXJ_PCMCIA=m + +# +# ATA/IDE/MFM/RLL support +# +CONFIG_IDE=y + +# +# IDE, ATA and ATAPI Block devices +# +CONFIG_BLK_DEV_IDE=y +# CONFIG_BLK_DEV_HD_IDE is not set +# CONFIG_BLK_DEV_HD is not set +CONFIG_BLK_DEV_IDEDISK=y +CONFIG_IDEDISK_MULTI_MODE=y +# CONFIG_IDEDISK_STROKE is not set +CONFIG_BLK_DEV_IDECS=m +CONFIG_BLK_DEV_IDECD=m +CONFIG_BLK_DEV_IDETAPE=m +CONFIG_BLK_DEV_IDEFLOPPY=y +CONFIG_BLK_DEV_IDESCSI=m +# CONFIG_IDE_TASK_IOCTL is not set +CONFIG_BLK_DEV_CMD640=y +# CONFIG_BLK_DEV_CMD640_ENHANCED is not set +# CONFIG_BLK_DEV_ISAPNP is not set +CONFIG_BLK_DEV_IDEPCI=y +CONFIG_BLK_DEV_GENERIC=y +CONFIG_IDEPCI_SHARE_IRQ=y +CONFIG_BLK_DEV_IDEDMA_PCI=y +# CONFIG_BLK_DEV_OFFBOARD is not set +# CONFIG_BLK_DEV_IDEDMA_FORCED is not set +CONFIG_IDEDMA_PCI_AUTO=y +# CONFIG_IDEDMA_ONLYDISK is not set +CONFIG_BLK_DEV_IDEDMA=y +# CONFIG_IDEDMA_PCI_WIP is not set +CONFIG_BLK_DEV_ADMA100=y +CONFIG_BLK_DEV_AEC62XX=y +CONFIG_BLK_DEV_ALI15X3=y +# CONFIG_WDC_ALI15X3 is not set +CONFIG_BLK_DEV_AMD74XX=y +# CONFIG_AMD74XX_OVERRIDE is not set +CONFIG_BLK_DEV_CMD64X=y +CONFIG_BLK_DEV_TRIFLEX=y +CONFIG_BLK_DEV_CY82C693=y +CONFIG_BLK_DEV_CS5530=y +CONFIG_BLK_DEV_HPT34X=y +# CONFIG_HPT34X_AUTODMA is not set +CONFIG_BLK_DEV_HPT366=y +CONFIG_BLK_DEV_PIIX=y +# CONFIG_BLK_DEV_NS87415 is not set +# CONFIG_BLK_DEV_OPTI621 is not set +CONFIG_BLK_DEV_PDC202XX_OLD=y +# CONFIG_PDC202XX_BURST is not set +CONFIG_BLK_DEV_PDC202XX_NEW=y +CONFIG_PDC202XX_FORCE=y +CONFIG_BLK_DEV_RZ1000=y +# CONFIG_BLK_DEV_SC1200 is not set +CONFIG_BLK_DEV_SVWKS=y +CONFIG_BLK_DEV_SIIMAGE=y +# CONFIG_BLK_DEV_SIS5513 is not set +# CONFIG_BLK_DEV_SLC90E66 is not set +# CONFIG_BLK_DEV_TRM290 is not set +# CONFIG_BLK_DEV_VIA82CXXX is not set +# CONFIG_IDE_CHIPSETS is not set +CONFIG_IDEDMA_AUTO=y +# CONFIG_IDEDMA_IVB is not set +# CONFIG_DMA_NONPCI is not set +CONFIG_BLK_DEV_PDC202XX=y +CONFIG_BLK_DEV_IDE_MODES=y +CONFIG_BLK_DEV_ATARAID=m +CONFIG_BLK_DEV_ATARAID_PDC=m +CONFIG_BLK_DEV_ATARAID_HPT=m +CONFIG_BLK_DEV_ATARAID_SII=m + +# +# SCSI support +# +CONFIG_SCSI=m +CONFIG_BLK_DEV_SD=m +CONFIG_SD_EXTRA_DEVS=40 +CONFIG_CHR_DEV_ST=m +CONFIG_CHR_DEV_OSST=m +CONFIG_BLK_DEV_SR=m +CONFIG_BLK_DEV_SR_VENDOR=y +CONFIG_SR_EXTRA_DEVS=2 +CONFIG_CHR_DEV_SG=m +# CONFIG_SCSI_DEBUG_QUEUES is not set +# CONFIG_SCSI_MULTI_LUN is not set +CONFIG_SCSI_CONSTANTS=y +CONFIG_SCSI_LOGGING=y + +# +# SCSI low-level drivers +# +CONFIG_BLK_DEV_3W_XXXX_RAID=m +CONFIG_SCSI_7000FASST=m +CONFIG_SCSI_ACARD=m +CONFIG_SCSI_AHA152X=m +CONFIG_SCSI_AHA1542=m +CONFIG_SCSI_AHA1740=m +CONFIG_SCSI_AACRAID=m +CONFIG_SCSI_AIC7XXX=m +CONFIG_AIC7XXX_CMDS_PER_DEVICE=253 +CONFIG_AIC7XXX_RESET_DELAY_MS=15000 +# CONFIG_AIC7XXX_PROBE_EISA_VL is not set +# CONFIG_AIC7XXX_BUILD_FIRMWARE is not set +# CONFIG_AIC7XXX_DEBUG_ENABLE is not set +CONFIG_AIC7XXX_DEBUG_MASK=0 +# CONFIG_AIC7XXX_REG_PRETTY_PRINT is not set +# CONFIG_SCSI_AIC79XX is not set +# CONFIG_SCSI_AIC7XXX_OLD is not set +CONFIG_SCSI_DPT_I2O=m +CONFIG_SCSI_ADVANSYS=m +CONFIG_SCSI_IN2000=m +CONFIG_SCSI_AM53C974=m +CONFIG_SCSI_MEGARAID=m +CONFIG_SCSI_BUSLOGIC=m +# CONFIG_SCSI_OMIT_FLASHPOINT is not set +CONFIG_SCSI_CPQFCTS=m +CONFIG_SCSI_DMX3191D=m +CONFIG_SCSI_DTC3280=m +CONFIG_SCSI_EATA=m +CONFIG_SCSI_EATA_TAGGED_QUEUE=y +# CONFIG_SCSI_EATA_LINKED_COMMANDS is not set +CONFIG_SCSI_EATA_MAX_TAGS=16 +CONFIG_SCSI_EATA_DMA=m +CONFIG_SCSI_EATA_PIO=m +CONFIG_SCSI_FUTURE_DOMAIN=m +CONFIG_SCSI_GDTH=m +CONFIG_SCSI_GENERIC_NCR5380=m +# CONFIG_SCSI_GENERIC_NCR53C400 is not set +CONFIG_SCSI_G_NCR5380_PORT=y +# CONFIG_SCSI_G_NCR5380_MEM is not set +CONFIG_SCSI_IPS=m +CONFIG_SCSI_INITIO=m +CONFIG_SCSI_INIA100=m +CONFIG_SCSI_PPA=m +CONFIG_SCSI_IMM=m +# CONFIG_SCSI_IZIP_EPP16 is not set +# CONFIG_SCSI_IZIP_SLOW_CTR is not set +CONFIG_SCSI_NCR53C406A=m +CONFIG_SCSI_NCR53C7xx=m +# CONFIG_SCSI_NCR53C7xx_sync is not set +CONFIG_SCSI_NCR53C7xx_FAST=y +CONFIG_SCSI_NCR53C7xx_DISCONNECT=y +CONFIG_SCSI_SYM53C8XX_2=m +CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=1 +CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16 +CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64 +# CONFIG_SCSI_SYM53C8XX_IOMAPPED is not set +CONFIG_SCSI_NCR53C8XX=m +CONFIG_SCSI_SYM53C8XX=m +CONFIG_SCSI_NCR53C8XX_DEFAULT_TAGS=8 +CONFIG_SCSI_NCR53C8XX_MAX_TAGS=32 +CONFIG_SCSI_NCR53C8XX_SYNC=20 +# CONFIG_SCSI_NCR53C8XX_PROFILE is not set +# CONFIG_SCSI_NCR53C8XX_IOMAPPED is not set +# CONFIG_SCSI_NCR53C8XX_PQS_PDS is not set +# CONFIG_SCSI_NCR53C8XX_SYMBIOS_COMPAT is not set +CONFIG_SCSI_PAS16=m +CONFIG_SCSI_PCI2000=m +CONFIG_SCSI_PCI2220I=m +CONFIG_SCSI_PSI240I=m +CONFIG_SCSI_QLOGIC_FAS=m +CONFIG_SCSI_QLOGIC_ISP=m +CONFIG_SCSI_QLOGIC_FC=m +# CONFIG_SCSI_QLOGIC_FC_FIRMWARE is not set +CONFIG_SCSI_QLOGIC_1280=m +CONFIG_SCSI_SEAGATE=m +CONFIG_SCSI_SIM710=m +CONFIG_SCSI_SYM53C416=m +CONFIG_SCSI_DC390T=m +# CONFIG_SCSI_DC390T_NOGENSUPP is not set +CONFIG_SCSI_T128=m +CONFIG_SCSI_U14_34F=m +# CONFIG_SCSI_U14_34F_LINKED_COMMANDS is not set +CONFIG_SCSI_U14_34F_MAX_TAGS=8 +CONFIG_SCSI_ULTRASTOR=m +CONFIG_SCSI_NSP32=m +CONFIG_SCSI_DEBUG=m + +# +# PCMCIA SCSI adapter support +# +CONFIG_SCSI_PCMCIA=y +CONFIG_PCMCIA_AHA152X=m +CONFIG_PCMCIA_FDOMAIN=m +CONFIG_PCMCIA_NINJA_SCSI=m +CONFIG_PCMCIA_QLOGIC=m + +# +# Fusion MPT device support +# +CONFIG_FUSION=m +# CONFIG_FUSION_BOOT is not set +CONFIG_FUSION_MAX_SGE=40 +# CONFIG_FUSION_ISENSE is not set +CONFIG_FUSION_CTL=m +CONFIG_FUSION_LAN=m +CONFIG_NET_FC=y + +# +# IEEE 1394 (FireWire) support (EXPERIMENTAL) +# +CONFIG_IEEE1394=m +# CONFIG_IEEE1394_PCILYNX is not set +CONFIG_IEEE1394_OHCI1394=m +CONFIG_IEEE1394_VIDEO1394=m +CONFIG_IEEE1394_SBP2=m +CONFIG_IEEE1394_SBP2_PHYS_DMA=y +CONFIG_IEEE1394_ETH1394=m +CONFIG_IEEE1394_DV1394=m +CONFIG_IEEE1394_RAWIO=m +CONFIG_IEEE1394_CMP=m +CONFIG_IEEE1394_AMDTP=m +# CONFIG_IEEE1394_VERBOSEDEBUG is not set +# CONFIG_IEEE1394_OUI_DB is not set + +# +# I2O device support +# +CONFIG_I2O=m +CONFIG_I2O_PCI=m +CONFIG_I2O_BLOCK=m +CONFIG_I2O_LAN=m +CONFIG_I2O_SCSI=m +CONFIG_I2O_PROC=m + +# +# Network device support +# +CONFIG_NETDEVICES=y + +# +# ARCnet devices +# +# CONFIG_ARCNET is not set +CONFIG_DUMMY=m +CONFIG_BONDING=m +CONFIG_EQUALIZER=m +CONFIG_TUN=m +CONFIG_ETHERTAP=m +CONFIG_NET_SB1000=m + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +# CONFIG_SUNLANCE is not set +CONFIG_HAPPYMEAL=m +# CONFIG_SUNBMAC is not set +# CONFIG_SUNQE is not set +CONFIG_SUNGEM=m +CONFIG_NET_VENDOR_3COM=y +CONFIG_EL1=m +CONFIG_EL2=m +CONFIG_ELPLUS=m +CONFIG_EL16=m +CONFIG_EL3=m +CONFIG_3C515=m +# CONFIG_ELMC is not set +# CONFIG_ELMC_II is not set +CONFIG_VORTEX=m +CONFIG_TYPHOON=m +CONFIG_LANCE=m +CONFIG_NET_VENDOR_SMC=y +CONFIG_WD80x3=m +# CONFIG_ULTRAMCA is not set +CONFIG_ULTRA=m +CONFIG_ULTRA32=m +CONFIG_SMC9194=m +CONFIG_NET_VENDOR_RACAL=y +CONFIG_NI5010=m +CONFIG_NI52=m +CONFIG_NI65=m +CONFIG_AT1700=m +CONFIG_DEPCA=m +CONFIG_HP100=m +CONFIG_NET_ISA=y +CONFIG_E2100=m +CONFIG_EWRK3=m +CONFIG_EEXPRESS=m +CONFIG_EEXPRESS_PRO=m +CONFIG_HPLAN_PLUS=m +CONFIG_HPLAN=m +CONFIG_LP486E=m +CONFIG_ETH16I=m +CONFIG_NE2000=m +CONFIG_NET_PCI=y +CONFIG_PCNET32=m +CONFIG_AMD8111_ETH=m +CONFIG_ADAPTEC_STARFIRE=m +CONFIG_AC3200=m +CONFIG_APRICOT=m +CONFIG_B44=m +CONFIG_CS89x0=m +CONFIG_TULIP=m +# CONFIG_TULIP_MWI is not set +CONFIG_TULIP_MMIO=y +CONFIG_DE4X5=m +CONFIG_DGRS=m +CONFIG_DM9102=m +CONFIG_EEPRO100=m +# CONFIG_EEPRO100_PIO is not set +CONFIG_E100=m +CONFIG_LNE390=m +CONFIG_FEALNX=m +CONFIG_NATSEMI=m +CONFIG_NE2K_PCI=m +CONFIG_NE3210=m +CONFIG_ES3210=m +CONFIG_8139CP=m +CONFIG_8139TOO=m +# CONFIG_8139TOO_PIO is not set +# CONFIG_8139TOO_TUNE_TWISTER is not set +CONFIG_8139TOO_8129=y +# CONFIG_8139_OLD_RX_RESET is not set +CONFIG_SIS900=m +CONFIG_EPIC100=m +CONFIG_SUNDANCE=m +# CONFIG_SUNDANCE_MMIO is not set +CONFIG_TLAN=m +CONFIG_VIA_RHINE=m +# CONFIG_VIA_RHINE_MMIO is not set +CONFIG_WINBOND_840=m +CONFIG_NET_POCKET=y +CONFIG_ATP=m +CONFIG_DE600=m +CONFIG_DE620=m + +# +# Ethernet (1000 Mbit) +# +CONFIG_ACENIC=m +# CONFIG_ACENIC_OMIT_TIGON_I is not set +CONFIG_DL2K=m +CONFIG_E1000=m +CONFIG_E1000_NAPI=y +# CONFIG_MYRI_SBUS is not set +CONFIG_NS83820=m +CONFIG_HAMACHI=m +CONFIG_YELLOWFIN=m +CONFIG_R8169=m +CONFIG_SK98LIN=m +CONFIG_TIGON3=m +CONFIG_FDDI=y +CONFIG_DEFXX=m +CONFIG_SKFP=m +# CONFIG_HIPPI is not set +CONFIG_PLIP=m +CONFIG_PPP=m +CONFIG_PPP_MULTILINK=y +CONFIG_PPP_FILTER=y +CONFIG_PPP_ASYNC=m +CONFIG_PPP_SYNC_TTY=m +CONFIG_PPP_DEFLATE=m +# CONFIG_PPP_BSDCOMP is not set +CONFIG_PPPOE=m +CONFIG_PPPOATM=m +CONFIG_SLIP=m +CONFIG_SLIP_COMPRESSED=y +CONFIG_SLIP_SMART=y +CONFIG_SLIP_MODE_SLIP6=y + +# +# Wireless LAN (non-hamradio) +# +CONFIG_NET_RADIO=y +CONFIG_STRIP=m +CONFIG_WAVELAN=m +CONFIG_ARLAN=m +CONFIG_AIRONET4500=m +CONFIG_AIRONET4500_NONCS=m +CONFIG_AIRONET4500_PNP=y +CONFIG_AIRONET4500_PCI=y +CONFIG_AIRONET4500_ISA=y +CONFIG_AIRONET4500_I365=y +CONFIG_AIRONET4500_PROC=m +CONFIG_AIRO=m +CONFIG_HERMES=m +CONFIG_PLX_HERMES=m +CONFIG_PCI_HERMES=m +CONFIG_PCMCIA_HERMES=m +CONFIG_AIRO_CS=m +CONFIG_NET_WIRELESS=y + +# +# Token Ring devices +# +CONFIG_TR=y +CONFIG_IBMTR=m +CONFIG_IBMOL=m +CONFIG_IBMLS=m +CONFIG_3C359=m +CONFIG_TMS380TR=m +CONFIG_TMSPCI=m +CONFIG_TMSISA=m +CONFIG_ABYSS=m +# CONFIG_MADGEMC is not set +CONFIG_SMCTR=m +CONFIG_NET_FC=y +CONFIG_IPHASE5526=m +CONFIG_RCPCI=m +CONFIG_SHAPER=m + +# +# Wan interfaces +# +CONFIG_WAN=y +CONFIG_HOSTESS_SV11=m +CONFIG_COSA=m +# CONFIG_COMX is not set +# CONFIG_DSCC4 is not set +# CONFIG_LANMEDIA is not set +CONFIG_ATI_XX20=m +CONFIG_SEALEVEL_4021=m +# CONFIG_SYNCLINK_SYNCPPP is not set +# CONFIG_HDLC is not set +CONFIG_DLCI=m +CONFIG_DLCI_COUNT=24 +CONFIG_DLCI_MAX=8 +CONFIG_SDLA=m +CONFIG_WAN_ROUTER_DRIVERS=y +CONFIG_VENDOR_SANGOMA=m +CONFIG_WANPIPE_CHDLC=y +CONFIG_WANPIPE_FR=y +CONFIG_WANPIPE_X25=y +CONFIG_WANPIPE_PPP=y +CONFIG_WANPIPE_MULTPPP=y +CONFIG_CYCLADES_SYNC=m +CONFIG_CYCLOMX_X25=y +# CONFIG_LAPBETHER is not set +# CONFIG_X25_ASY is not set +CONFIG_SBNI=m +CONFIG_SBNI_MULTILINE=y + +# +# PCMCIA network device support +# +CONFIG_NET_PCMCIA=y +CONFIG_PCMCIA_3C589=m +CONFIG_PCMCIA_3C574=m +CONFIG_PCMCIA_FMVJ18X=m +CONFIG_PCMCIA_PCNET=m +CONFIG_PCMCIA_AXNET=m +CONFIG_PCMCIA_NMCLAN=m +CONFIG_PCMCIA_SMC91C92=m +CONFIG_PCMCIA_XIRC2PS=m +# CONFIG_ARCNET_COM20020_CS is not set +CONFIG_PCMCIA_IBMTR=m +CONFIG_PCMCIA_XIRCOM=m +CONFIG_PCMCIA_XIRTULIP=m +CONFIG_NET_PCMCIA_RADIO=y +CONFIG_PCMCIA_RAYCS=m +CONFIG_PCMCIA_NETWAVE=m +CONFIG_PCMCIA_WAVELAN=m +CONFIG_AIRONET4500_CS=m + +# +# ATM drivers +# +# CONFIG_ATM_TCP is not set +CONFIG_ATM_LANAI=m +CONFIG_ATM_ENI=m +# CONFIG_ATM_ENI_DEBUG is not set +# CONFIG_ATM_ENI_TUNE_BURST is not set +CONFIG_ATM_FIRESTREAM=m +CONFIG_ATM_ZATM=m +# CONFIG_ATM_ZATM_DEBUG is not set +CONFIG_ATM_ZATM_EXACT_TS=y +CONFIG_ATM_NICSTAR=m +CONFIG_ATM_NICSTAR_USE_SUNI=y +CONFIG_ATM_NICSTAR_USE_IDT77105=y +CONFIG_ATM_IDT77252=m +# CONFIG_ATM_IDT77252_DEBUG is not set +# CONFIG_ATM_IDT77252_RCV_ALL is not set +CONFIG_ATM_IDT77252_USE_SUNI=y +CONFIG_ATM_AMBASSADOR=m +# CONFIG_ATM_AMBASSADOR_DEBUG is not set +CONFIG_ATM_HORIZON=m +# CONFIG_ATM_HORIZON_DEBUG is not set +CONFIG_ATM_IA=m +# CONFIG_ATM_IA_DEBUG is not set +CONFIG_ATM_FORE200E_MAYBE=m +CONFIG_ATM_FORE200E_PCA=y +CONFIG_ATM_FORE200E_PCA_DEFAULT_FW=y +CONFIG_ATM_FORE200E_TX_RETRY=16 +CONFIG_ATM_FORE200E_DEBUG=0 +CONFIG_ATM_FORE200E=m +CONFIG_ATM_HE=m +CONFIG_ATM_HE_USE_SUNI=y + +# +# Amateur Radio support +# +CONFIG_HAMRADIO=y +CONFIG_AX25=m +# CONFIG_AX25_DAMA_SLAVE is not set +CONFIG_NETROM=m +CONFIG_ROSE=m + +# +# AX.25 network device drivers +# +# CONFIG_MKISS is not set +# CONFIG_6PACK is not set +# CONFIG_BPQETHER is not set +# CONFIG_DMASCC is not set +# CONFIG_SCC is not set +# CONFIG_BAYCOM_SER_FDX is not set +# CONFIG_BAYCOM_SER_HDX is not set +# CONFIG_BAYCOM_PAR is not set +# CONFIG_BAYCOM_EPP is not set +CONFIG_SOUNDMODEM=m +CONFIG_SOUNDMODEM_SBC=y +CONFIG_SOUNDMODEM_WSS=y +CONFIG_SOUNDMODEM_AFSK1200=y +CONFIG_SOUNDMODEM_AFSK2400_7=y +CONFIG_SOUNDMODEM_AFSK2400_8=y +CONFIG_SOUNDMODEM_AFSK2666=y +CONFIG_SOUNDMODEM_HAPN4800=y +CONFIG_SOUNDMODEM_PSK4800=y +CONFIG_SOUNDMODEM_FSK9600=y +# CONFIG_YAM is not set + +# +# IrDA (infrared) support +# +CONFIG_IRDA=m +CONFIG_IRLAN=m +CONFIG_IRNET=m +CONFIG_IRCOMM=m +CONFIG_IRDA_ULTRA=y +CONFIG_IRDA_CACHE_LAST_LSAP=y +CONFIG_IRDA_FAST_RR=y +# CONFIG_IRDA_DEBUG is not set + +# +# Infrared-port device drivers +# +CONFIG_IRTTY_SIR=m +CONFIG_IRPORT_SIR=m +CONFIG_DONGLE=y +CONFIG_ESI_DONGLE=m +CONFIG_ACTISYS_DONGLE=m +CONFIG_TEKRAM_DONGLE=m +CONFIG_GIRBIL_DONGLE=m +CONFIG_LITELINK_DONGLE=m +CONFIG_MCP2120_DONGLE=m +CONFIG_OLD_BELKIN_DONGLE=m +CONFIG_ACT200L_DONGLE=m +CONFIG_MA600_DONGLE=m +CONFIG_USB_IRDA=m +CONFIG_NSC_FIR=m +CONFIG_WINBOND_FIR=m +CONFIG_TOSHIBA_OLD=m +CONFIG_TOSHIBA_FIR=m +CONFIG_SMC_IRCC_FIR=m +CONFIG_ALI_FIR=m +CONFIG_VLSI_FIR=m + +# +# ISDN subsystem +# +CONFIG_ISDN=m +CONFIG_ISDN_BOOL=y +CONFIG_ISDN_PPP=y +CONFIG_IPPP_FILTER=y +CONFIG_ISDN_PPP_VJ=y +CONFIG_ISDN_MPP=y +CONFIG_ISDN_PPP_BSDCOMP=m +CONFIG_ISDN_AUDIO=y +CONFIG_ISDN_TTY_FAX=y + +# +# ISDN feature submodules +# +CONFIG_ISDN_DRV_LOOP=m +# CONFIG_ISDN_DIVERSION is not set + +# +# Passive ISDN cards +# +CONFIG_ISDN_DRV_HISAX=m +CONFIG_ISDN_HISAX=y +CONFIG_HISAX_EURO=y +CONFIG_DE_AOC=y +# CONFIG_HISAX_NO_SENDCOMPLETE is not set +# CONFIG_HISAX_NO_LLC is not set +# CONFIG_HISAX_NO_KEYPAD is not set +CONFIG_HISAX_1TR6=y +CONFIG_HISAX_NI1=y +CONFIG_HISAX_MAX_CARDS=8 +CONFIG_HISAX_16_0=y +CONFIG_HISAX_16_3=y +CONFIG_HISAX_AVM_A1=y +CONFIG_HISAX_IX1MICROR2=y +CONFIG_HISAX_ASUSCOM=y +CONFIG_HISAX_TELEINT=y +CONFIG_HISAX_HFCS=y +CONFIG_HISAX_SPORTSTER=y +CONFIG_HISAX_MIC=y +CONFIG_HISAX_ISURF=y +CONFIG_HISAX_HSTSAPHIR=y +CONFIG_HISAX_TELESPCI=y +CONFIG_HISAX_S0BOX=y +CONFIG_HISAX_FRITZPCI=y +CONFIG_HISAX_AVM_A1_PCMCIA=y +CONFIG_HISAX_ELSA=y +CONFIG_HISAX_DIEHLDIVA=y +CONFIG_HISAX_SEDLBAUER=y +CONFIG_HISAX_NETJET=y +CONFIG_HISAX_NETJET_U=y +CONFIG_HISAX_NICCY=y +CONFIG_HISAX_BKM_A4T=y +CONFIG_HISAX_SCT_QUADRO=y +CONFIG_HISAX_GAZEL=y +CONFIG_HISAX_HFC_PCI=y +CONFIG_HISAX_W6692=y +CONFIG_HISAX_HFC_SX=y +CONFIG_HISAX_ENTERNOW_PCI=y +CONFIG_HISAX_DEBUG=y +CONFIG_HISAX_SEDLBAUER_CS=m +CONFIG_HISAX_ELSA_CS=m +CONFIG_HISAX_AVM_A1_CS=m +CONFIG_HISAX_ST5481=m +CONFIG_HISAX_FRITZ_PCIPNP=m +CONFIG_USB_AUERISDN=m + +# +# Active ISDN cards +# +CONFIG_ISDN_DRV_ICN=m +CONFIG_ISDN_DRV_PCBIT=m +# CONFIG_ISDN_DRV_SC is not set +# CONFIG_ISDN_DRV_ACT2000 is not set +CONFIG_ISDN_DRV_EICON=y +CONFIG_ISDN_DRV_EICON_DIVAS=m +# CONFIG_ISDN_DRV_EICON_OLD is not set +CONFIG_ISDN_DRV_TPAM=m +CONFIG_ISDN_CAPI=m +CONFIG_ISDN_DRV_AVMB1_VERBOSE_REASON=y +CONFIG_ISDN_CAPI_MIDDLEWARE=y +CONFIG_ISDN_CAPI_CAPI20=m +CONFIG_ISDN_CAPI_CAPIFS_BOOL=y +CONFIG_ISDN_CAPI_CAPIFS=m +CONFIG_ISDN_CAPI_CAPIDRV=m +CONFIG_ISDN_DRV_AVMB1_B1ISA=m +CONFIG_ISDN_DRV_AVMB1_B1PCI=m +CONFIG_ISDN_DRV_AVMB1_B1PCIV4=y +CONFIG_ISDN_DRV_AVMB1_T1ISA=m +CONFIG_ISDN_DRV_AVMB1_B1PCMCIA=m +CONFIG_ISDN_DRV_AVMB1_AVM_CS=m +CONFIG_ISDN_DRV_AVMB1_T1PCI=m +CONFIG_ISDN_DRV_AVMB1_C4=m +CONFIG_HYSDN=m +CONFIG_HYSDN_CAPI=y + +# +# Old CD-ROM drivers (not SCSI, not IDE) +# +# CONFIG_CD_NO_IDESCSI is not set + +# +# Input core support +# +CONFIG_INPUT=m +CONFIG_INPUT_KEYBDEV=m +CONFIG_INPUT_MOUSEDEV=m +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +CONFIG_INPUT_JOYDEV=m +CONFIG_INPUT_EVDEV=m + +# +# Character devices +# +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_SERIAL=y +CONFIG_SERIAL_CONSOLE=y +CONFIG_SERIAL_EXTENDED=y +CONFIG_SERIAL_MANY_PORTS=y +CONFIG_SERIAL_SHARE_IRQ=y +# CONFIG_SERIAL_DETECT_IRQ is not set +CONFIG_SERIAL_MULTIPORT=y +# CONFIG_HUB6 is not set +CONFIG_SERIAL_NONSTANDARD=y +CONFIG_COMPUTONE=m +CONFIG_ROCKETPORT=m +CONFIG_CYCLADES=m +# CONFIG_CYZ_INTR is not set +CONFIG_DIGIEPCA=m +CONFIG_ESPSERIAL=m +CONFIG_MOXA_INTELLIO=m +CONFIG_MOXA_SMARTIO=m +CONFIG_ISI=m +CONFIG_SYNCLINK=m +# CONFIG_SYNCLINKMP is not set +CONFIG_N_HDLC=m +CONFIG_RISCOM8=m +CONFIG_SPECIALIX=m +CONFIG_SPECIALIX_RTSCTS=y +CONFIG_SX=m +# CONFIG_RIO is not set +CONFIG_STALDRV=y +CONFIG_STALLION=m +CONFIG_ISTALLION=m +CONFIG_UNIX98_PTYS=y +CONFIG_UNIX98_PTY_COUNT=2048 +CONFIG_PRINTER=m +CONFIG_LP_CONSOLE=y +CONFIG_PPDEV=m +CONFIG_TIPAR=m + +# +# I2C support +# +CONFIG_I2C=m +CONFIG_I2C_ALGOBIT=m +CONFIG_I2C_PHILIPSPAR=m +CONFIG_I2C_ELV=m +CONFIG_I2C_VELLEMAN=m +# CONFIG_SCx200_I2C is not set +# CONFIG_SCx200_ACB is not set +CONFIG_I2C_ALGOPCF=m +CONFIG_I2C_ELEKTOR=m +CONFIG_I2C_CHARDEV=m +CONFIG_I2C_PROC=m + +# +# Mice +# +CONFIG_BUSMOUSE=m +CONFIG_ATIXL_BUSMOUSE=m +CONFIG_LOGIBUSMOUSE=m +CONFIG_MS_BUSMOUSE=m +CONFIG_MOUSE=y +CONFIG_PSMOUSE=y +CONFIG_82C710_MOUSE=m +CONFIG_PC110_PAD=m +CONFIG_MK712_MOUSE=m + +# +# Joysticks +# +CONFIG_INPUT_GAMEPORT=m +CONFIG_INPUT_NS558=m +CONFIG_INPUT_LIGHTNING=m +CONFIG_INPUT_PCIGAME=m +CONFIG_INPUT_CS461X=m +CONFIG_INPUT_EMU10K1=m +CONFIG_INPUT_SERIO=m +CONFIG_INPUT_SERPORT=m +CONFIG_INPUT_ANALOG=m +CONFIG_INPUT_A3D=m +CONFIG_INPUT_ADI=m +CONFIG_INPUT_COBRA=m +CONFIG_INPUT_GF2K=m +CONFIG_INPUT_GRIP=m +CONFIG_INPUT_INTERACT=m +CONFIG_INPUT_TMDC=m +CONFIG_INPUT_SIDEWINDER=m +CONFIG_INPUT_IFORCE_USB=m +CONFIG_INPUT_IFORCE_232=m +CONFIG_INPUT_WARRIOR=m +CONFIG_INPUT_MAGELLAN=m +CONFIG_INPUT_SPACEORB=m +CONFIG_INPUT_SPACEBALL=m +CONFIG_INPUT_STINGER=m +CONFIG_INPUT_DB9=m +CONFIG_INPUT_GAMECON=m +CONFIG_INPUT_TURBOGRAFX=m +# CONFIG_QIC02_TAPE is not set +CONFIG_IPMI_HANDLER=m +# CONFIG_IPMI_PANIC_EVENT is not set +CONFIG_IPMI_DEVICE_INTERFACE=m +CONFIG_IPMI_KCS=m +CONFIG_IPMI_WATCHDOG=m + +# +# Watchdog Cards +# +CONFIG_WATCHDOG=y +# CONFIG_WATCHDOG_NOWAYOUT is not set +CONFIG_ACQUIRE_WDT=m +CONFIG_ADVANTECH_WDT=m +CONFIG_ALIM1535_WDT=m +CONFIG_ALIM7101_WDT=m +CONFIG_SC520_WDT=m +CONFIG_PCWATCHDOG=m +CONFIG_EUROTECH_WDT=m +CONFIG_IB700_WDT=m +CONFIG_WAFER_WDT=m +CONFIG_I810_TCO=m +# CONFIG_MIXCOMWD is not set +# CONFIG_60XX_WDT is not set +CONFIG_SC1200_WDT=m +# CONFIG_SCx200_WDT is not set +CONFIG_SOFT_WATCHDOG=m +CONFIG_W83877F_WDT=m +CONFIG_WDT=m +CONFIG_WDTPCI=m +# CONFIG_WDT_501 is not set +CONFIG_MACHZ_WDT=m +CONFIG_AMD7XX_TCO=m +# CONFIG_SCx200_GPIO is not set +CONFIG_AMD_RNG=m +CONFIG_INTEL_RNG=m +CONFIG_AMD_PM768=m +CONFIG_NVRAM=m +CONFIG_RTC=y +CONFIG_DTLK=m +CONFIG_R3964=m +# CONFIG_APPLICOM is not set +CONFIG_SONYPI=m + +# +# Ftape, the floppy tape device driver +# +# CONFIG_FTAPE is not set +CONFIG_AGP=y +CONFIG_AGP_INTEL=y +CONFIG_AGP_I810=y +CONFIG_AGP_VIA=y +CONFIG_AGP_AMD=y +CONFIG_AGP_AMD_8151=y +CONFIG_AGP_SIS=y +CONFIG_AGP_ALI=y +CONFIG_AGP_SWORKS=y +CONFIG_AGP_NVIDIA=y +CONFIG_DRM=y +# CONFIG_DRM_OLD is not set +CONFIG_DRM_NEW=y +CONFIG_DRM_TDFX=m +CONFIG_DRM_R128=m +CONFIG_DRM_RADEON=m +CONFIG_DRM_I810=m +# CONFIG_DRM_I810_XFREE_41 is not set +CONFIG_DRM_I830=m +CONFIG_DRM_MGA=m +# CONFIG_DRM_SIS is not set + +# +# PCMCIA character devices +# +CONFIG_PCMCIA_SERIAL_CS=m +CONFIG_SYNCLINK_CS=m +CONFIG_MWAVE=m + +# +# Multimedia devices +# +CONFIG_VIDEO_DEV=m + +# +# Video For Linux +# +CONFIG_VIDEO_PROC_FS=y +CONFIG_I2C_PARPORT=m +CONFIG_VIDEO_BT848=m +CONFIG_VIDEO_PMS=m +CONFIG_VIDEO_BWQCAM=m +CONFIG_VIDEO_CQCAM=m +CONFIG_VIDEO_W9966=m +CONFIG_VIDEO_CPIA=m +CONFIG_VIDEO_CPIA_PP=m +CONFIG_VIDEO_CPIA_USB=m +CONFIG_VIDEO_SAA5249=m +CONFIG_TUNER_3036=m +CONFIG_VIDEO_STRADIS=m +CONFIG_VIDEO_ZORAN=m +CONFIG_VIDEO_ZORAN_BUZ=m +CONFIG_VIDEO_ZORAN_DC10=m +CONFIG_VIDEO_ZORAN_LML33=m +CONFIG_VIDEO_ZR36120=m +CONFIG_VIDEO_MEYE=m + +# +# Radio Adapters +# +CONFIG_RADIO_CADET=m +CONFIG_RADIO_RTRACK=m +CONFIG_RADIO_RTRACK2=m +CONFIG_RADIO_AZTECH=m +CONFIG_RADIO_GEMTEK=m +CONFIG_RADIO_GEMTEK_PCI=m +CONFIG_RADIO_MAXIRADIO=m +CONFIG_RADIO_MAESTRO=m +CONFIG_RADIO_MIROPCM20=m +CONFIG_RADIO_MIROPCM20_RDS=m +CONFIG_RADIO_SF16FMI=m +CONFIG_RADIO_SF16FMR2=m +CONFIG_RADIO_TERRATEC=m +CONFIG_RADIO_TRUST=m +CONFIG_RADIO_TYPHOON=m +CONFIG_RADIO_TYPHOON_PROC_FS=y +CONFIG_RADIO_ZOLTRIX=m + +# +# File systems +# +CONFIG_QUOTA=y +CONFIG_QFMT_V2=y +CONFIG_AUTOFS_FS=m +CONFIG_AUTOFS4_FS=m +CONFIG_REISERFS_FS=m +# CONFIG_REISERFS_CHECK is not set +CONFIG_REISERFS_PROC_INFO=y +# CONFIG_ADFS_FS is not set +# CONFIG_ADFS_FS_RW is not set +# CONFIG_AFFS_FS is not set +CONFIG_HFS_FS=m +# CONFIG_HFSPLUS_FS is not set +CONFIG_BEFS_FS=m +# CONFIG_BEFS_DEBUG is not set +CONFIG_BFS_FS=m +CONFIG_EXT3_FS=m +CONFIG_JBD=m +# CONFIG_JBD_DEBUG is not set +CONFIG_FAT_FS=m +CONFIG_MSDOS_FS=m +CONFIG_UMSDOS_FS=m +CONFIG_VFAT_FS=m +# CONFIG_EFS_FS is not set +# CONFIG_JFFS_FS is not set +# CONFIG_JFFS2_FS is not set +CONFIG_CRAMFS=m +CONFIG_TMPFS=y +CONFIG_RAMFS=y +CONFIG_ISO9660_FS=y +CONFIG_JOLIET=y +CONFIG_ZISOFS=y +CONFIG_JFS_FS=m +# CONFIG_JFS_DEBUG is not set +# CONFIG_JFS_STATISTICS is not set +CONFIG_MINIX_FS=m +CONFIG_VXFS_FS=m +# CONFIG_NTFS_FS is not set +# CONFIG_NTFS_RW is not set +# CONFIG_HPFS_FS is not set +CONFIG_PROC_FS=y +# CONFIG_DEVFS_FS is not set +# CONFIG_DEVFS_MOUNT is not set +# CONFIG_DEVFS_DEBUG is not set +CONFIG_DEVPTS_FS=y +# CONFIG_QNX4FS_FS is not set +# CONFIG_QNX4FS_RW is not set +CONFIG_ROMFS_FS=m +CONFIG_EXT2_FS=y +CONFIG_SYSV_FS=m +CONFIG_UDF_FS=m +CONFIG_UDF_RW=y +CONFIG_UFS_FS=m +# CONFIG_UFS_FS_WRITE is not set + +# +# Network File Systems +# +CONFIG_CODA_FS=m +CONFIG_INTERMEZZO_FS=m +CONFIG_NFS_FS=m +CONFIG_NFS_V3=y +# CONFIG_NFS_DIRECTIO is not set +# CONFIG_ROOT_NFS is not set +CONFIG_NFSD=m +CONFIG_NFSD_V3=y +CONFIG_NFSD_TCP=y +CONFIG_SUNRPC=m +CONFIG_LOCKD=m +CONFIG_LOCKD_V4=y +CONFIG_SMB_FS=m +# CONFIG_SMB_NLS_DEFAULT is not set +CONFIG_NCP_FS=m +# CONFIG_NCPFS_PACKET_SIGNING is not set +# CONFIG_NCPFS_IOCTL_LOCKING is not set +# CONFIG_NCPFS_STRONG is not set +# CONFIG_NCPFS_NFS_NS is not set +# CONFIG_NCPFS_OS2_NS is not set +# CONFIG_NCPFS_SMALLDOS is not set +# CONFIG_NCPFS_NLS is not set +# CONFIG_NCPFS_EXTRAS is not set +CONFIG_ZISOFS_FS=y + +# +# Partition Types +# +CONFIG_PARTITION_ADVANCED=y +# CONFIG_ACORN_PARTITION is not set +CONFIG_OSF_PARTITION=y +# CONFIG_AMIGA_PARTITION is not set +# CONFIG_ATARI_PARTITION is not set +CONFIG_MAC_PARTITION=y +CONFIG_MSDOS_PARTITION=y +CONFIG_BSD_DISKLABEL=y +CONFIG_MINIX_SUBPARTITION=y +CONFIG_SOLARIS_X86_PARTITION=y +CONFIG_UNIXWARE_DISKLABEL=y +# CONFIG_LDM_PARTITION is not set +CONFIG_SGI_PARTITION=y +# CONFIG_ULTRIX_PARTITION is not set +CONFIG_SUN_PARTITION=y +# CONFIG_EFI_PARTITION is not set +CONFIG_SMB_NLS=y +CONFIG_NLS=y + +# +# Native Language Support +# +CONFIG_NLS_DEFAULT="iso8859-1" +CONFIG_NLS_CODEPAGE_437=m +CONFIG_NLS_CODEPAGE_737=m +CONFIG_NLS_CODEPAGE_775=m +CONFIG_NLS_CODEPAGE_850=m +CONFIG_NLS_CODEPAGE_852=m +CONFIG_NLS_CODEPAGE_855=m +CONFIG_NLS_CODEPAGE_857=m +CONFIG_NLS_CODEPAGE_860=m +CONFIG_NLS_CODEPAGE_861=m +CONFIG_NLS_CODEPAGE_862=m +CONFIG_NLS_CODEPAGE_863=m +CONFIG_NLS_CODEPAGE_864=m +CONFIG_NLS_CODEPAGE_865=m +CONFIG_NLS_CODEPAGE_866=m +CONFIG_NLS_CODEPAGE_869=m +CONFIG_NLS_CODEPAGE_936=m +CONFIG_NLS_CODEPAGE_950=m +CONFIG_NLS_CODEPAGE_932=m +CONFIG_NLS_CODEPAGE_949=m +CONFIG_NLS_CODEPAGE_874=m +CONFIG_NLS_ISO8859_8=m +CONFIG_NLS_CODEPAGE_1250=m +CONFIG_NLS_CODEPAGE_1251=m +CONFIG_NLS_ISO8859_1=m +CONFIG_NLS_ISO8859_2=m +CONFIG_NLS_ISO8859_3=m +CONFIG_NLS_ISO8859_4=m +CONFIG_NLS_ISO8859_5=m +CONFIG_NLS_ISO8859_6=m +CONFIG_NLS_ISO8859_7=m +CONFIG_NLS_ISO8859_9=m +CONFIG_NLS_ISO8859_13=m +CONFIG_NLS_ISO8859_14=m +CONFIG_NLS_ISO8859_15=m +CONFIG_NLS_KOI8_R=m +CONFIG_NLS_KOI8_U=m +CONFIG_NLS_UTF8=m + +# +# Console drivers +# +CONFIG_VGA_CONSOLE=y +CONFIG_VIDEO_SELECT=y +CONFIG_MDA_CONSOLE=m + +# +# Frame-buffer support +# +CONFIG_FB=y +CONFIG_DUMMY_CONSOLE=y +CONFIG_FB_RIVA=m +CONFIG_FB_CLGEN=m +CONFIG_FB_PM2=m +# CONFIG_FB_PM2_FIFO_DISCONNECT is not set +CONFIG_FB_PM2_PCI=y +CONFIG_FB_PM3=m +# CONFIG_FB_CYBER2000 is not set +CONFIG_FB_VESA=y +CONFIG_FB_VGA16=m +CONFIG_FB_HGA=m +CONFIG_VIDEO_SELECT=y +CONFIG_FB_MATROX=m +CONFIG_FB_MATROX_MILLENIUM=y +CONFIG_FB_MATROX_MYSTIQUE=y +# CONFIG_FB_MATROX_G450 is not set +CONFIG_FB_MATROX_G100A=y +CONFIG_FB_MATROX_G100=y +CONFIG_FB_MATROX_I2C=m +# CONFIG_FB_MATROX_MAVEN is not set +# CONFIG_FB_MATROX_PROC is not set +CONFIG_FB_MATROX_MULTIHEAD=y +CONFIG_FB_ATY=m +CONFIG_FB_ATY_GX=y +CONFIG_FB_ATY_CT=y +CONFIG_FB_RADEON=m +CONFIG_FB_ATY128=m +# CONFIG_FB_INTEL is not set +CONFIG_FB_SIS=m +CONFIG_FB_SIS_300=y +CONFIG_FB_SIS_315=y +CONFIG_FB_NEOMAGIC=m +CONFIG_FB_3DFX=m +CONFIG_FB_VOODOO1=m +# CONFIG_FB_TRIDENT is not set +# CONFIG_FB_VIRTUAL is not set +# CONFIG_FBCON_ADVANCED is not set +CONFIG_FBCON_MFB=m +CONFIG_FBCON_CFB8=y +CONFIG_FBCON_CFB16=y +CONFIG_FBCON_CFB24=y +CONFIG_FBCON_CFB32=y +CONFIG_FBCON_VGA_PLANES=m +CONFIG_FBCON_HGA=m +# CONFIG_FBCON_FONTWIDTH8_ONLY is not set +# CONFIG_FBCON_FONTS is not set +CONFIG_FONT_8x8=y +CONFIG_FONT_8x16=y + +# +# Sound +# +CONFIG_SOUND=m +CONFIG_SOUND_ALI5455=m +CONFIG_SOUND_BT878=m +CONFIG_SOUND_CMPCI=m +CONFIG_SOUND_CMPCI_FM=y +CONFIG_SOUND_CMPCI_FMIO=388 +CONFIG_SOUND_CMPCI_FMIO=388 +CONFIG_SOUND_CMPCI_MIDI=y +CONFIG_SOUND_CMPCI_MPUIO=330 +CONFIG_SOUND_CMPCI_JOYSTICK=y +CONFIG_SOUND_CMPCI_CM8738=y +# CONFIG_SOUND_CMPCI_SPDIFINVERSE is not set +CONFIG_SOUND_CMPCI_SPDIFLOOP=y +CONFIG_SOUND_CMPCI_SPEAKERS=2 +CONFIG_SOUND_EMU10K1=m +CONFIG_MIDI_EMU10K1=y +CONFIG_SOUND_FUSION=m +CONFIG_SOUND_CS4281=m +CONFIG_SOUND_ES1370=m +CONFIG_SOUND_ES1371=m +CONFIG_SOUND_ESSSOLO1=m +CONFIG_SOUND_MAESTRO=m +CONFIG_SOUND_MAESTRO3=m +CONFIG_SOUND_FORTE=m +CONFIG_SOUND_ICH=m +CONFIG_SOUND_RME96XX=m +CONFIG_SOUND_SONICVIBES=m +CONFIG_SOUND_TRIDENT=m +CONFIG_SOUND_MSNDCLAS=m +# CONFIG_MSNDCLAS_HAVE_BOOT is not set +CONFIG_MSNDCLAS_INIT_FILE="/etc/sound/msndinit.bin" +CONFIG_MSNDCLAS_PERM_FILE="/etc/sound/msndperm.bin" +CONFIG_SOUND_MSNDPIN=m +# CONFIG_MSNDPIN_HAVE_BOOT is not set +CONFIG_MSNDPIN_INIT_FILE="/etc/sound/pndspini.bin" +CONFIG_MSNDPIN_PERM_FILE="/etc/sound/pndsperm.bin" +CONFIG_SOUND_VIA82CXXX=m +CONFIG_MIDI_VIA82CXXX=y +CONFIG_SOUND_OSS=m +# CONFIG_SOUND_TRACEINIT is not set +CONFIG_SOUND_DMAP=y +CONFIG_SOUND_AD1816=m +CONFIG_SOUND_AD1889=m +CONFIG_SOUND_SGALAXY=m +CONFIG_SOUND_ADLIB=m +CONFIG_SOUND_ACI_MIXER=m +CONFIG_SOUND_CS4232=m +CONFIG_SOUND_SSCAPE=m +CONFIG_SOUND_GUS=m +CONFIG_SOUND_GUS16=y +CONFIG_SOUND_GUSMAX=y +CONFIG_SOUND_VMIDI=m +CONFIG_SOUND_TRIX=m +CONFIG_SOUND_MSS=m +CONFIG_SOUND_MPU401=m +CONFIG_SOUND_NM256=m +CONFIG_SOUND_MAD16=m +CONFIG_MAD16_OLDCARD=y +CONFIG_SOUND_PAS=m +# CONFIG_PAS_JOYSTICK is not set +CONFIG_SOUND_PSS=m +# CONFIG_PSS_MIXER is not set +# CONFIG_PSS_HAVE_BOOT is not set +CONFIG_SOUND_SB=m +CONFIG_SOUND_AWE32_SYNTH=m +CONFIG_SOUND_KAHLUA=m +CONFIG_SOUND_WAVEFRONT=m +CONFIG_SOUND_MAUI=m +CONFIG_SOUND_YM3812=m +CONFIG_SOUND_OPL3SA1=m +CONFIG_SOUND_OPL3SA2=m +CONFIG_SOUND_YMFPCI=m +CONFIG_SOUND_YMFPCI_LEGACY=y +# CONFIG_SOUND_UART6850 is not set +CONFIG_SOUND_AEDSP16=m +CONFIG_SC6600=y +CONFIG_SC6600_JOY=y +CONFIG_SC6600_CDROM=4 +CONFIG_SC6600_CDROMBASE=0 +CONFIG_AEDSP16_SBPRO=y +CONFIG_AEDSP16_MPU401=y +CONFIG_SOUND_TVMIXER=m + +# +# USB support +# +CONFIG_USB=m +# CONFIG_USB_DEBUG is not set +CONFIG_USB_DEVICEFS=y +# CONFIG_USB_BANDWIDTH is not set +CONFIG_USB_EHCI_HCD=m +# CONFIG_USB_UHCI is not set +CONFIG_USB_UHCI_ALT=m +CONFIG_USB_OHCI=m +CONFIG_USB_AUDIO=m +# CONFIG_USB_EMI26 is not set +CONFIG_USB_MIDI=m +CONFIG_USB_STORAGE=m +# CONFIG_USB_STORAGE_DEBUG is not set +CONFIG_USB_STORAGE_DATAFAB=y +CONFIG_USB_STORAGE_FREECOM=y +CONFIG_USB_STORAGE_ISD200=y +CONFIG_USB_STORAGE_DPCM=y +CONFIG_USB_STORAGE_HP8200e=y +CONFIG_USB_STORAGE_SDDR09=y +CONFIG_USB_STORAGE_SDDR55=y +CONFIG_USB_STORAGE_JUMPSHOT=y +CONFIG_USB_ACM=m +CONFIG_USB_PRINTER=m +CONFIG_USB_HID=m +CONFIG_USB_HIDINPUT=y +CONFIG_USB_HIDDEV=y +# CONFIG_USB_KBD is not set +# CONFIG_USB_MOUSE is not set +CONFIG_USB_AIPTEK=m +CONFIG_USB_WACOM=m +CONFIG_USB_KBTAB=m +CONFIG_USB_POWERMATE=m +# CONFIG_USB_DC2XX is not set +CONFIG_USB_MDC800=m +CONFIG_USB_SCANNER=m +CONFIG_USB_MICROTEK=m +CONFIG_USB_HPUSBSCSI=m +CONFIG_USB_IBMCAM=m +CONFIG_USB_KONICAWC=m +CONFIG_USB_OV511=m +CONFIG_USB_PWC=m +CONFIG_USB_SE401=m +CONFIG_USB_STV680=m +CONFIG_USB_VICAM=m +CONFIG_USB_DSBR=m +CONFIG_USB_DABUSB=m +CONFIG_USB_PEGASUS=m +CONFIG_USB_RTL8150=m +CONFIG_USB_KAWETH=m +CONFIG_USB_CATC=m +CONFIG_USB_AX8817X=m +CONFIG_USB_CDCETHER=m +CONFIG_USB_USBNET=m +CONFIG_USB_USS720=m + +# +# USB Serial Converter support +# +CONFIG_USB_SERIAL=m +# CONFIG_USB_SERIAL_DEBUG is not set +CONFIG_USB_SERIAL_GENERIC=y +CONFIG_USB_SERIAL_BELKIN=m +CONFIG_USB_SERIAL_WHITEHEAT=m +CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m +CONFIG_USB_SERIAL_EMPEG=m +CONFIG_USB_SERIAL_FTDI_SIO=m +CONFIG_USB_SERIAL_VISOR=m +CONFIG_USB_SERIAL_IPAQ=m +CONFIG_USB_SERIAL_IR=m +CONFIG_USB_SERIAL_EDGEPORT=m +CONFIG_USB_SERIAL_EDGEPORT_TI=m +CONFIG_USB_SERIAL_KEYSPAN_PDA=m +CONFIG_USB_SERIAL_KEYSPAN=m +# CONFIG_USB_SERIAL_KEYSPAN_USA28 is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA28X is not set +CONFIG_USB_SERIAL_KEYSPAN_USA28XA=y +CONFIG_USB_SERIAL_KEYSPAN_USA28XB=y +# CONFIG_USB_SERIAL_KEYSPAN_USA19 is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA18X is not set +CONFIG_USB_SERIAL_KEYSPAN_USA19W=y +CONFIG_USB_SERIAL_KEYSPAN_USA19QW=y +CONFIG_USB_SERIAL_KEYSPAN_USA19QI=y +CONFIG_USB_SERIAL_KEYSPAN_MPR=y +CONFIG_USB_SERIAL_KEYSPAN_USA49W=y +CONFIG_USB_SERIAL_KEYSPAN_USA49WLC=y +CONFIG_USB_SERIAL_MCT_U232=m +CONFIG_USB_SERIAL_KLSI=m +CONFIG_USB_SERIAL_KOBIL_SCT=m +CONFIG_USB_SERIAL_PL2303=m +CONFIG_USB_SERIAL_CYBERJACK=m +CONFIG_USB_SERIAL_XIRCOM=m +CONFIG_USB_SERIAL_OMNINET=m +CONFIG_USB_RIO500=m +CONFIG_USB_AUERSWALD=m +CONFIG_USB_TIGL=m +CONFIG_USB_BRLVGER=m +CONFIG_USB_LCD=m +CONFIG_USB_SPEEDTOUCH=m + +# +# Bluetooth support +# +CONFIG_BLUEZ=m +CONFIG_BLUEZ_L2CAP=m +CONFIG_BLUEZ_SCO=m +CONFIG_BLUEZ_RFCOMM=m +CONFIG_BLUEZ_RFCOMM_TTY=y +CONFIG_BLUEZ_BNEP=m +CONFIG_BLUEZ_BNEP_MC_FILTER=y +CONFIG_BLUEZ_BNEP_PROTO_FILTER=y +# CONFIG_BLUEZ_CMTP is not set + +# +# Bluetooth device drivers +# +CONFIG_BLUEZ_HCIUSB=m +CONFIG_BLUEZ_USB_SCO=y +CONFIG_BLUEZ_USB_ZERO_PACKET=y +CONFIG_BLUEZ_HCIUART=m +CONFIG_BLUEZ_HCIUART_H4=y +CONFIG_BLUEZ_HCIUART_BCSP=y +# CONFIG_BLUEZ_HCIUART_BCSP_TXCRC is not set +# CONFIG_BLUEZ_HCIBFUSB is not set +CONFIG_BLUEZ_HCIDTL1=m +CONFIG_BLUEZ_HCIBT3C=m +CONFIG_BLUEZ_HCIBLUECARD=m +CONFIG_BLUEZ_HCIBTUART=m +CONFIG_BLUEZ_HCIVHCI=m + +# +# Kernel hacking +# +CONFIG_DEBUG_KERNEL=y +CONFIG_DEBUG_STACKOVERFLOW=y +# CONFIG_DEBUG_HIGHMEM is not set +# CONFIG_DEBUG_SLAB is not set +# CONFIG_DEBUG_IOVIRT is not set +CONFIG_MAGIC_SYSRQ=y +# CONFIG_DEBUG_SPINLOCK is not set +# CONFIG_FRAME_POINTER is not set + +# +# Cryptographic options +# +# CONFIG_CRYPTO is not set + +# +# Library routines +# +# CONFIG_CRC32 is not set +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=m diff --git a/Makerules/generic-2.4.22-i686-smp.config b/Makerules/generic-2.4.22-i686-smp.config new file mode 100644 index 0000000..e09f51a --- /dev/null +++ b/Makerules/generic-2.4.22-i686-smp.config @@ -0,0 +1,1747 @@ +# +# Automatically generated by make menuconfig: don't edit +# +CONFIG_X86=y +# CONFIG_SBUS is not set +CONFIG_UID16=y + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y + +# +# Loadable module support +# +CONFIG_MODULES=y +CONFIG_MODVERSIONS=y +CONFIG_KMOD=y + +# +# Processor type and features +# +# CONFIG_M386 is not set +# CONFIG_M486 is not set +# CONFIG_M586 is not set +# CONFIG_M586TSC is not set +# CONFIG_M586MMX is not set +CONFIG_M686=y +# CONFIG_MPENTIUMIII is not set +# CONFIG_MPENTIUM4 is not set +# CONFIG_MK6 is not set +# CONFIG_MK7 is not set +# CONFIG_MK8 is not set +# CONFIG_MELAN is not set +# CONFIG_MCRUSOE is not set +# CONFIG_MWINCHIPC6 is not set +# CONFIG_MWINCHIP2 is not set +# CONFIG_MWINCHIP3D is not set +# CONFIG_MCYRIXIII is not set +# CONFIG_MVIAC3_2 is not set +CONFIG_X86_WP_WORKS_OK=y +CONFIG_X86_INVLPG=y +CONFIG_X86_CMPXCHG=y +CONFIG_X86_XADD=y +CONFIG_X86_BSWAP=y +CONFIG_X86_POPAD_OK=y +# CONFIG_RWSEM_GENERIC_SPINLOCK is not set +CONFIG_RWSEM_XCHGADD_ALGORITHM=y +CONFIG_X86_L1_CACHE_SHIFT=5 +CONFIG_X86_HAS_TSC=y +CONFIG_X86_GOOD_APIC=y +CONFIG_X86_PGE=y +CONFIG_X86_USE_PPRO_CHECKSUM=y +CONFIG_X86_PPRO_FENCE=y +CONFIG_X86_F00F_WORKS_OK=y +CONFIG_X86_MCE=y +CONFIG_TOSHIBA=m +CONFIG_I8K=m +CONFIG_MICROCODE=m +CONFIG_X86_MSR=m +CONFIG_X86_CPUID=m +# CONFIG_NOHIGHMEM is not set +CONFIG_HIGHMEM4G=y +# CONFIG_HIGHMEM64G is not set +CONFIG_HIGHMEM=y +CONFIG_HIGHIO=y +# CONFIG_MATH_EMULATION is not set +CONFIG_MTRR=y +CONFIG_SMP=y +# CONFIG_X86_NUMA is not set +# CONFIG_X86_TSC_DISABLE is not set +CONFIG_X86_TSC=y +CONFIG_HAVE_DEC_LOCK=y + +# +# General setup +# +CONFIG_NET=y +CONFIG_X86_IO_APIC=y +CONFIG_X86_LOCAL_APIC=y +CONFIG_PCI=y +# CONFIG_PCI_GOBIOS is not set +# CONFIG_PCI_GODIRECT is not set +CONFIG_PCI_GOANY=y +CONFIG_PCI_BIOS=y +CONFIG_PCI_DIRECT=y +CONFIG_ISA=y +CONFIG_PCI_NAMES=y +CONFIG_EISA=y +# CONFIG_MCA is not set +CONFIG_HOTPLUG=y + +# +# PCMCIA/CardBus support +# +CONFIG_PCMCIA=m +CONFIG_CARDBUS=y +CONFIG_TCIC=y +CONFIG_I82092=y +CONFIG_I82365=y + +# +# PCI Hotplug Support +# +CONFIG_HOTPLUG_PCI=y +# CONFIG_HOTPLUG_PCI_COMPAQ is not set +# CONFIG_HOTPLUG_PCI_COMPAQ_NVRAM is not set +CONFIG_HOTPLUG_PCI_IBM=m +CONFIG_SYSVIPC=y +CONFIG_BSD_PROCESS_ACCT=y +CONFIG_SYSCTL=y +CONFIG_KCORE_ELF=y +# CONFIG_KCORE_AOUT is not set +CONFIG_BINFMT_AOUT=y +CONFIG_BINFMT_ELF=y +CONFIG_BINFMT_MISC=y +CONFIG_PM=y +CONFIG_APM=y +# CONFIG_APM_IGNORE_USER_SUSPEND is not set +# CONFIG_APM_DO_ENABLE is not set +CONFIG_APM_CPU_IDLE=y +# CONFIG_APM_DISPLAY_BLANK is not set +CONFIG_APM_RTC_IS_GMT=y +# CONFIG_APM_ALLOW_INTS is not set +# CONFIG_APM_REAL_MODE_POWER_OFF is not set + +# +# ACPI Support +# +# CONFIG_ACPI is not set + +# +# Memory Technology Devices (MTD) +# +# CONFIG_MTD is not set + +# +# Parallel port support +# +CONFIG_PARPORT=m +CONFIG_PARPORT_PC=m +CONFIG_PARPORT_PC_CML1=m +CONFIG_PARPORT_SERIAL=m +# CONFIG_PARPORT_PC_FIFO is not set +# CONFIG_PARPORT_PC_SUPERIO is not set +CONFIG_PARPORT_PC_PCMCIA=m +# CONFIG_PARPORT_AMIGA is not set +# CONFIG_PARPORT_MFC3 is not set +# CONFIG_PARPORT_ATARI is not set +# CONFIG_PARPORT_GSC is not set +# CONFIG_PARPORT_SUNBPP is not set +# CONFIG_PARPORT_OTHER is not set +CONFIG_PARPORT_1284=y + +# +# Plug and Play configuration +# +CONFIG_PNP=y +CONFIG_ISAPNP=y + +# +# Block devices +# +CONFIG_BLK_DEV_FD=y +CONFIG_BLK_DEV_XD=m +CONFIG_PARIDE=m +CONFIG_PARIDE_PARPORT=m +CONFIG_PARIDE_PD=m +CONFIG_PARIDE_PCD=m +CONFIG_PARIDE_PF=m +CONFIG_PARIDE_PT=m +CONFIG_PARIDE_PG=m +CONFIG_PARIDE_ATEN=m +CONFIG_PARIDE_BPCK=m +CONFIG_PARIDE_BPCK6=m +CONFIG_PARIDE_COMM=m +CONFIG_PARIDE_DSTR=m +CONFIG_PARIDE_FIT2=m +CONFIG_PARIDE_FIT3=m +CONFIG_PARIDE_EPAT=m +CONFIG_PARIDE_EPATC8=y +CONFIG_PARIDE_EPIA=m +CONFIG_PARIDE_FRIQ=m +CONFIG_PARIDE_FRPW=m +CONFIG_PARIDE_KBIC=m +CONFIG_PARIDE_KTTI=m +CONFIG_PARIDE_ON20=m +CONFIG_PARIDE_ON26=m +CONFIG_BLK_CPQ_DA=m +CONFIG_BLK_CPQ_CISS_DA=m +CONFIG_CISS_SCSI_TAPE=y +CONFIG_BLK_DEV_DAC960=m +CONFIG_BLK_DEV_UMEM=m +CONFIG_BLK_DEV_LOOP=m +CONFIG_BLK_DEV_NBD=m +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_SIZE=4096 +CONFIG_BLK_DEV_INITRD=y +CONFIG_BLK_STATS=y + +# +# Multi-device support (RAID and LVM) +# +CONFIG_MD=y +CONFIG_BLK_DEV_MD=y +CONFIG_MD_LINEAR=m +CONFIG_MD_RAID0=m +CONFIG_MD_RAID1=m +CONFIG_MD_RAID5=m +CONFIG_MD_MULTIPATH=m +CONFIG_BLK_DEV_LVM=m + +# +# Networking options +# +CONFIG_PACKET=y +CONFIG_PACKET_MMAP=y +CONFIG_NETLINK_DEV=y +CONFIG_NETFILTER=y +# CONFIG_NETFILTER_DEBUG is not set +CONFIG_FILTER=y +CONFIG_UNIX=y +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +CONFIG_IP_ADVANCED_ROUTER=y +CONFIG_IP_MULTIPLE_TABLES=y +CONFIG_IP_ROUTE_FWMARK=y +CONFIG_IP_ROUTE_NAT=y +CONFIG_IP_ROUTE_MULTIPATH=y +CONFIG_IP_ROUTE_TOS=y +CONFIG_IP_ROUTE_VERBOSE=y +# CONFIG_IP_PNP is not set +CONFIG_NET_IPIP=m +CONFIG_NET_IPGRE=m +CONFIG_NET_IPGRE_BROADCAST=y +CONFIG_IP_MROUTE=y +CONFIG_IP_PIMSM_V1=y +CONFIG_IP_PIMSM_V2=y +# CONFIG_ARPD is not set +# CONFIG_INET_ECN is not set +CONFIG_SYN_COOKIES=y + +# +# IP: Netfilter Configuration +# +CONFIG_IP_NF_CONNTRACK=m +CONFIG_IP_NF_FTP=m +CONFIG_IP_NF_AMANDA=m +CONFIG_IP_NF_TFTP=m +CONFIG_IP_NF_IRC=m +CONFIG_IP_NF_QUEUE=m +CONFIG_IP_NF_IPTABLES=m +CONFIG_IP_NF_MATCH_LIMIT=m +CONFIG_IP_NF_MATCH_MAC=m +CONFIG_IP_NF_MATCH_PKTTYPE=m +CONFIG_IP_NF_MATCH_MARK=m +CONFIG_IP_NF_MATCH_MULTIPORT=m +CONFIG_IP_NF_MATCH_TOS=m +CONFIG_IP_NF_MATCH_RECENT=m +CONFIG_IP_NF_MATCH_ECN=m +CONFIG_IP_NF_MATCH_DSCP=m +CONFIG_IP_NF_MATCH_AH_ESP=m +CONFIG_IP_NF_MATCH_LENGTH=m +CONFIG_IP_NF_MATCH_TTL=m +CONFIG_IP_NF_MATCH_TCPMSS=m +CONFIG_IP_NF_MATCH_HELPER=m +CONFIG_IP_NF_MATCH_STATE=m +CONFIG_IP_NF_MATCH_CONNTRACK=m +CONFIG_IP_NF_MATCH_UNCLEAN=m +CONFIG_IP_NF_MATCH_OWNER=m +CONFIG_IP_NF_FILTER=m +CONFIG_IP_NF_TARGET_REJECT=m +CONFIG_IP_NF_TARGET_MIRROR=m +CONFIG_IP_NF_NAT=m +CONFIG_IP_NF_NAT_NEEDED=y +CONFIG_IP_NF_TARGET_MASQUERADE=m +CONFIG_IP_NF_TARGET_REDIRECT=m +CONFIG_IP_NF_NAT_AMANDA=m +CONFIG_IP_NF_NAT_LOCAL=y +CONFIG_IP_NF_NAT_SNMP_BASIC=m +CONFIG_IP_NF_NAT_IRC=m +CONFIG_IP_NF_NAT_FTP=m +CONFIG_IP_NF_NAT_TFTP=m +CONFIG_IP_NF_MANGLE=m +CONFIG_IP_NF_TARGET_TOS=m +CONFIG_IP_NF_TARGET_ECN=m +CONFIG_IP_NF_TARGET_DSCP=m +CONFIG_IP_NF_TARGET_MARK=m +CONFIG_IP_NF_TARGET_LOG=m +CONFIG_IP_NF_TARGET_ULOG=m +CONFIG_IP_NF_TARGET_TCPMSS=m +CONFIG_IP_NF_ARPTABLES=m +CONFIG_IP_NF_ARPFILTER=m +CONFIG_IP_NF_ARP_MANGLE=m +CONFIG_IP_NF_COMPAT_IPCHAINS=m +CONFIG_IP_NF_NAT_NEEDED=y +CONFIG_IP_NF_COMPAT_IPFWADM=m +CONFIG_IP_NF_NAT_NEEDED=y +CONFIG_IPV6=m + +# +# IPv6: Netfilter Configuration +# +# CONFIG_IP6_NF_QUEUE is not set +CONFIG_IP6_NF_IPTABLES=m +CONFIG_IP6_NF_MATCH_LIMIT=m +CONFIG_IP6_NF_MATCH_MAC=m +CONFIG_IP6_NF_MATCH_RT=m +CONFIG_IP6_NF_MATCH_OPTS=m +CONFIG_IP6_NF_MATCH_FRAG=m +CONFIG_IP6_NF_MATCH_HL=m +CONFIG_IP6_NF_MATCH_MULTIPORT=m +CONFIG_IP6_NF_MATCH_OWNER=m +CONFIG_IP6_NF_MATCH_MARK=m +CONFIG_IP6_NF_MATCH_IPV6HEADER=m +CONFIG_IP6_NF_MATCH_AHESP=m +CONFIG_IP6_NF_MATCH_LENGTH=m +CONFIG_IP6_NF_MATCH_EUI64=m +CONFIG_IP6_NF_FILTER=m +CONFIG_IP6_NF_TARGET_LOG=m +CONFIG_IP6_NF_MANGLE=m +# CONFIG_IP6_NF_TARGET_MARK is not set +# CONFIG_KHTTPD is not set +CONFIG_ATM=m +CONFIG_ATM_CLIP=m +# CONFIG_ATM_CLIP_NO_ICMP is not set +CONFIG_ATM_LANE=m +CONFIG_ATM_MPOA=m +CONFIG_ATM_BR2684=m +CONFIG_ATM_BR2684_IPFILTER=y +CONFIG_VLAN_8021Q=m +CONFIG_IPX=m +# CONFIG_IPX_INTERN is not set +CONFIG_ATALK=m + +# +# Appletalk devices +# +CONFIG_DEV_APPLETALK=y +CONFIG_LTPC=m +CONFIG_COPS=m +CONFIG_COPS_DAYNA=y +CONFIG_COPS_TANGENT=y +CONFIG_IPDDP=m +CONFIG_IPDDP_ENCAP=y +CONFIG_IPDDP_DECAP=y +CONFIG_DECNET=m +CONFIG_DECNET_SIOCGIFCONF=y +CONFIG_DECNET_ROUTER=y +CONFIG_DECNET_ROUTE_FWMARK=y +CONFIG_BRIDGE=m +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_LLC is not set +CONFIG_NET_DIVERT=y +# CONFIG_ECONET is not set +CONFIG_WAN_ROUTER=m +# CONFIG_NET_FASTROUTE is not set +# CONFIG_NET_HW_FLOWCONTROL is not set + +# +# QoS and/or fair queueing +# +CONFIG_NET_SCHED=y +CONFIG_NET_SCH_CBQ=m +CONFIG_NET_SCH_HTB=m +CONFIG_NET_SCH_CSZ=m +# CONFIG_NET_SCH_ATM is not set +CONFIG_NET_SCH_PRIO=m +CONFIG_NET_SCH_RED=m +CONFIG_NET_SCH_SFQ=m +CONFIG_NET_SCH_TEQL=m +CONFIG_NET_SCH_TBF=m +CONFIG_NET_SCH_GRED=m +CONFIG_NET_SCH_DSMARK=m +CONFIG_NET_SCH_INGRESS=m +CONFIG_NET_QOS=y +CONFIG_NET_ESTIMATOR=y +CONFIG_NET_CLS=y +CONFIG_NET_CLS_TCINDEX=m +CONFIG_NET_CLS_ROUTE4=m +CONFIG_NET_CLS_ROUTE=y +CONFIG_NET_CLS_FW=m +CONFIG_NET_CLS_U32=m +CONFIG_NET_CLS_RSVP=m +CONFIG_NET_CLS_RSVP6=m +CONFIG_NET_CLS_POLICE=y + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set + +# +# Telephony Support +# +CONFIG_PHONE=m +CONFIG_PHONE_IXJ=m +CONFIG_PHONE_IXJ_PCMCIA=m + +# +# ATA/IDE/MFM/RLL support +# +CONFIG_IDE=y + +# +# IDE, ATA and ATAPI Block devices +# +CONFIG_BLK_DEV_IDE=y +# CONFIG_BLK_DEV_HD_IDE is not set +# CONFIG_BLK_DEV_HD is not set +CONFIG_BLK_DEV_IDEDISK=y +CONFIG_IDEDISK_MULTI_MODE=y +# CONFIG_IDEDISK_STROKE is not set +CONFIG_BLK_DEV_IDECS=m +CONFIG_BLK_DEV_IDECD=m +CONFIG_BLK_DEV_IDETAPE=m +CONFIG_BLK_DEV_IDEFLOPPY=y +CONFIG_BLK_DEV_IDESCSI=m +# CONFIG_IDE_TASK_IOCTL is not set +CONFIG_BLK_DEV_CMD640=y +# CONFIG_BLK_DEV_CMD640_ENHANCED is not set +# CONFIG_BLK_DEV_ISAPNP is not set +CONFIG_BLK_DEV_IDEPCI=y +CONFIG_BLK_DEV_GENERIC=y +CONFIG_IDEPCI_SHARE_IRQ=y +CONFIG_BLK_DEV_IDEDMA_PCI=y +# CONFIG_BLK_DEV_OFFBOARD is not set +# CONFIG_BLK_DEV_IDEDMA_FORCED is not set +CONFIG_IDEDMA_PCI_AUTO=y +# CONFIG_IDEDMA_ONLYDISK is not set +CONFIG_BLK_DEV_IDEDMA=y +# CONFIG_IDEDMA_PCI_WIP is not set +CONFIG_BLK_DEV_ADMA100=y +CONFIG_BLK_DEV_AEC62XX=y +CONFIG_BLK_DEV_ALI15X3=y +# CONFIG_WDC_ALI15X3 is not set +CONFIG_BLK_DEV_AMD74XX=y +# CONFIG_AMD74XX_OVERRIDE is not set +CONFIG_BLK_DEV_CMD64X=y +CONFIG_BLK_DEV_TRIFLEX=y +CONFIG_BLK_DEV_CY82C693=y +CONFIG_BLK_DEV_CS5530=y +CONFIG_BLK_DEV_HPT34X=y +# CONFIG_HPT34X_AUTODMA is not set +CONFIG_BLK_DEV_HPT366=y +CONFIG_BLK_DEV_PIIX=y +# CONFIG_BLK_DEV_NS87415 is not set +# CONFIG_BLK_DEV_OPTI621 is not set +CONFIG_BLK_DEV_PDC202XX_OLD=y +# CONFIG_PDC202XX_BURST is not set +CONFIG_BLK_DEV_PDC202XX_NEW=y +CONFIG_PDC202XX_FORCE=y +CONFIG_BLK_DEV_RZ1000=y +# CONFIG_BLK_DEV_SC1200 is not set +CONFIG_BLK_DEV_SVWKS=y +CONFIG_BLK_DEV_SIIMAGE=y +# CONFIG_BLK_DEV_SIS5513 is not set +# CONFIG_BLK_DEV_SLC90E66 is not set +# CONFIG_BLK_DEV_TRM290 is not set +# CONFIG_BLK_DEV_VIA82CXXX is not set +# CONFIG_IDE_CHIPSETS is not set +CONFIG_IDEDMA_AUTO=y +# CONFIG_IDEDMA_IVB is not set +# CONFIG_DMA_NONPCI is not set +CONFIG_BLK_DEV_PDC202XX=y +CONFIG_BLK_DEV_IDE_MODES=y +CONFIG_BLK_DEV_ATARAID=m +CONFIG_BLK_DEV_ATARAID_PDC=m +CONFIG_BLK_DEV_ATARAID_HPT=m +CONFIG_BLK_DEV_ATARAID_SII=m + +# +# SCSI support +# +CONFIG_SCSI=m +CONFIG_BLK_DEV_SD=m +CONFIG_SD_EXTRA_DEVS=40 +CONFIG_CHR_DEV_ST=m +CONFIG_CHR_DEV_OSST=m +CONFIG_BLK_DEV_SR=m +CONFIG_BLK_DEV_SR_VENDOR=y +CONFIG_SR_EXTRA_DEVS=2 +CONFIG_CHR_DEV_SG=m +# CONFIG_SCSI_DEBUG_QUEUES is not set +# CONFIG_SCSI_MULTI_LUN is not set +CONFIG_SCSI_CONSTANTS=y +CONFIG_SCSI_LOGGING=y + +# +# SCSI low-level drivers +# +CONFIG_BLK_DEV_3W_XXXX_RAID=m +CONFIG_SCSI_7000FASST=m +CONFIG_SCSI_ACARD=m +CONFIG_SCSI_AHA152X=m +CONFIG_SCSI_AHA1542=m +CONFIG_SCSI_AHA1740=m +CONFIG_SCSI_AACRAID=m +CONFIG_SCSI_AIC7XXX=m +CONFIG_AIC7XXX_CMDS_PER_DEVICE=253 +CONFIG_AIC7XXX_RESET_DELAY_MS=15000 +# CONFIG_AIC7XXX_PROBE_EISA_VL is not set +# CONFIG_AIC7XXX_BUILD_FIRMWARE is not set +# CONFIG_AIC7XXX_DEBUG_ENABLE is not set +CONFIG_AIC7XXX_DEBUG_MASK=0 +# CONFIG_AIC7XXX_REG_PRETTY_PRINT is not set +# CONFIG_SCSI_AIC79XX is not set +# CONFIG_SCSI_AIC7XXX_OLD is not set +CONFIG_SCSI_DPT_I2O=m +CONFIG_SCSI_ADVANSYS=m +CONFIG_SCSI_IN2000=m +CONFIG_SCSI_AM53C974=m +CONFIG_SCSI_MEGARAID=m +CONFIG_SCSI_BUSLOGIC=m +# CONFIG_SCSI_OMIT_FLASHPOINT is not set +CONFIG_SCSI_CPQFCTS=m +CONFIG_SCSI_DMX3191D=m +CONFIG_SCSI_DTC3280=m +CONFIG_SCSI_EATA=m +CONFIG_SCSI_EATA_TAGGED_QUEUE=y +# CONFIG_SCSI_EATA_LINKED_COMMANDS is not set +CONFIG_SCSI_EATA_MAX_TAGS=16 +CONFIG_SCSI_EATA_DMA=m +CONFIG_SCSI_EATA_PIO=m +CONFIG_SCSI_FUTURE_DOMAIN=m +CONFIG_SCSI_GDTH=m +CONFIG_SCSI_GENERIC_NCR5380=m +# CONFIG_SCSI_GENERIC_NCR53C400 is not set +CONFIG_SCSI_G_NCR5380_PORT=y +# CONFIG_SCSI_G_NCR5380_MEM is not set +CONFIG_SCSI_IPS=m +CONFIG_SCSI_INITIO=m +CONFIG_SCSI_INIA100=m +CONFIG_SCSI_PPA=m +CONFIG_SCSI_IMM=m +# CONFIG_SCSI_IZIP_EPP16 is not set +# CONFIG_SCSI_IZIP_SLOW_CTR is not set +CONFIG_SCSI_NCR53C406A=m +CONFIG_SCSI_NCR53C7xx=m +# CONFIG_SCSI_NCR53C7xx_sync is not set +CONFIG_SCSI_NCR53C7xx_FAST=y +CONFIG_SCSI_NCR53C7xx_DISCONNECT=y +CONFIG_SCSI_SYM53C8XX_2=m +CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=1 +CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16 +CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64 +# CONFIG_SCSI_SYM53C8XX_IOMAPPED is not set +CONFIG_SCSI_NCR53C8XX=m +CONFIG_SCSI_SYM53C8XX=m +CONFIG_SCSI_NCR53C8XX_DEFAULT_TAGS=8 +CONFIG_SCSI_NCR53C8XX_MAX_TAGS=32 +CONFIG_SCSI_NCR53C8XX_SYNC=20 +# CONFIG_SCSI_NCR53C8XX_PROFILE is not set +# CONFIG_SCSI_NCR53C8XX_IOMAPPED is not set +# CONFIG_SCSI_NCR53C8XX_PQS_PDS is not set +# CONFIG_SCSI_NCR53C8XX_SYMBIOS_COMPAT is not set +CONFIG_SCSI_PAS16=m +CONFIG_SCSI_PCI2000=m +CONFIG_SCSI_PCI2220I=m +CONFIG_SCSI_PSI240I=m +CONFIG_SCSI_QLOGIC_FAS=m +CONFIG_SCSI_QLOGIC_ISP=m +CONFIG_SCSI_QLOGIC_FC=m +# CONFIG_SCSI_QLOGIC_FC_FIRMWARE is not set +CONFIG_SCSI_QLOGIC_1280=m +CONFIG_SCSI_SEAGATE=m +CONFIG_SCSI_SIM710=m +CONFIG_SCSI_SYM53C416=m +CONFIG_SCSI_DC390T=m +# CONFIG_SCSI_DC390T_NOGENSUPP is not set +CONFIG_SCSI_T128=m +CONFIG_SCSI_U14_34F=m +# CONFIG_SCSI_U14_34F_LINKED_COMMANDS is not set +CONFIG_SCSI_U14_34F_MAX_TAGS=8 +CONFIG_SCSI_ULTRASTOR=m +CONFIG_SCSI_NSP32=m +CONFIG_SCSI_DEBUG=m + +# +# PCMCIA SCSI adapter support +# +CONFIG_SCSI_PCMCIA=y +CONFIG_PCMCIA_AHA152X=m +CONFIG_PCMCIA_FDOMAIN=m +CONFIG_PCMCIA_NINJA_SCSI=m +CONFIG_PCMCIA_QLOGIC=m + +# +# Fusion MPT device support +# +CONFIG_FUSION=m +# CONFIG_FUSION_BOOT is not set +CONFIG_FUSION_MAX_SGE=40 +# CONFIG_FUSION_ISENSE is not set +CONFIG_FUSION_CTL=m +CONFIG_FUSION_LAN=m +CONFIG_NET_FC=y + +# +# IEEE 1394 (FireWire) support (EXPERIMENTAL) +# +CONFIG_IEEE1394=m +# CONFIG_IEEE1394_PCILYNX is not set +CONFIG_IEEE1394_OHCI1394=m +CONFIG_IEEE1394_VIDEO1394=m +CONFIG_IEEE1394_SBP2=m +CONFIG_IEEE1394_SBP2_PHYS_DMA=y +CONFIG_IEEE1394_ETH1394=m +CONFIG_IEEE1394_DV1394=m +CONFIG_IEEE1394_RAWIO=m +CONFIG_IEEE1394_CMP=m +CONFIG_IEEE1394_AMDTP=m +# CONFIG_IEEE1394_VERBOSEDEBUG is not set +# CONFIG_IEEE1394_OUI_DB is not set + +# +# I2O device support +# +CONFIG_I2O=m +CONFIG_I2O_PCI=m +CONFIG_I2O_BLOCK=m +CONFIG_I2O_LAN=m +CONFIG_I2O_SCSI=m +CONFIG_I2O_PROC=m + +# +# Network device support +# +CONFIG_NETDEVICES=y + +# +# ARCnet devices +# +# CONFIG_ARCNET is not set +CONFIG_DUMMY=m +CONFIG_BONDING=m +CONFIG_EQUALIZER=m +CONFIG_TUN=m +CONFIG_ETHERTAP=m +CONFIG_NET_SB1000=m + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +# CONFIG_SUNLANCE is not set +CONFIG_HAPPYMEAL=m +# CONFIG_SUNBMAC is not set +# CONFIG_SUNQE is not set +CONFIG_SUNGEM=m +CONFIG_NET_VENDOR_3COM=y +CONFIG_EL1=m +CONFIG_EL2=m +CONFIG_ELPLUS=m +CONFIG_EL16=m +CONFIG_EL3=m +CONFIG_3C515=m +# CONFIG_ELMC is not set +# CONFIG_ELMC_II is not set +CONFIG_VORTEX=m +CONFIG_TYPHOON=m +CONFIG_LANCE=m +CONFIG_NET_VENDOR_SMC=y +CONFIG_WD80x3=m +# CONFIG_ULTRAMCA is not set +CONFIG_ULTRA=m +CONFIG_ULTRA32=m +CONFIG_SMC9194=m +CONFIG_NET_VENDOR_RACAL=y +CONFIG_NI5010=m +CONFIG_NI52=m +CONFIG_NI65=m +CONFIG_AT1700=m +CONFIG_DEPCA=m +CONFIG_HP100=m +CONFIG_NET_ISA=y +CONFIG_E2100=m +CONFIG_EWRK3=m +CONFIG_EEXPRESS=m +CONFIG_EEXPRESS_PRO=m +CONFIG_HPLAN_PLUS=m +CONFIG_HPLAN=m +CONFIG_LP486E=m +CONFIG_ETH16I=m +CONFIG_NE2000=m +CONFIG_NET_PCI=y +CONFIG_PCNET32=m +CONFIG_AMD8111_ETH=m +CONFIG_ADAPTEC_STARFIRE=m +CONFIG_AC3200=m +CONFIG_APRICOT=m +CONFIG_B44=m +CONFIG_CS89x0=m +CONFIG_TULIP=m +# CONFIG_TULIP_MWI is not set +CONFIG_TULIP_MMIO=y +CONFIG_DE4X5=m +CONFIG_DGRS=m +CONFIG_DM9102=m +CONFIG_EEPRO100=m +# CONFIG_EEPRO100_PIO is not set +CONFIG_E100=m +CONFIG_LNE390=m +CONFIG_FEALNX=m +CONFIG_NATSEMI=m +CONFIG_NE2K_PCI=m +CONFIG_NE3210=m +CONFIG_ES3210=m +CONFIG_8139CP=m +CONFIG_8139TOO=m +# CONFIG_8139TOO_PIO is not set +# CONFIG_8139TOO_TUNE_TWISTER is not set +CONFIG_8139TOO_8129=y +# CONFIG_8139_OLD_RX_RESET is not set +CONFIG_SIS900=m +CONFIG_EPIC100=m +CONFIG_SUNDANCE=m +# CONFIG_SUNDANCE_MMIO is not set +CONFIG_TLAN=m +CONFIG_VIA_RHINE=m +# CONFIG_VIA_RHINE_MMIO is not set +CONFIG_WINBOND_840=m +CONFIG_NET_POCKET=y +CONFIG_ATP=m +CONFIG_DE600=m +CONFIG_DE620=m + +# +# Ethernet (1000 Mbit) +# +CONFIG_ACENIC=m +# CONFIG_ACENIC_OMIT_TIGON_I is not set +CONFIG_DL2K=m +CONFIG_E1000=m +CONFIG_E1000_NAPI=y +# CONFIG_MYRI_SBUS is not set +CONFIG_NS83820=m +CONFIG_HAMACHI=m +CONFIG_YELLOWFIN=m +CONFIG_R8169=m +CONFIG_SK98LIN=m +CONFIG_TIGON3=m +CONFIG_FDDI=y +CONFIG_DEFXX=m +CONFIG_SKFP=m +# CONFIG_HIPPI is not set +CONFIG_PLIP=m +CONFIG_PPP=m +CONFIG_PPP_MULTILINK=y +CONFIG_PPP_FILTER=y +CONFIG_PPP_ASYNC=m +CONFIG_PPP_SYNC_TTY=m +CONFIG_PPP_DEFLATE=m +# CONFIG_PPP_BSDCOMP is not set +CONFIG_PPPOE=m +CONFIG_PPPOATM=m +CONFIG_SLIP=m +CONFIG_SLIP_COMPRESSED=y +CONFIG_SLIP_SMART=y +CONFIG_SLIP_MODE_SLIP6=y + +# +# Wireless LAN (non-hamradio) +# +CONFIG_NET_RADIO=y +CONFIG_STRIP=m +CONFIG_WAVELAN=m +CONFIG_ARLAN=m +CONFIG_AIRONET4500=m +CONFIG_AIRONET4500_NONCS=m +CONFIG_AIRONET4500_PNP=y +CONFIG_AIRONET4500_PCI=y +CONFIG_AIRONET4500_ISA=y +CONFIG_AIRONET4500_I365=y +CONFIG_AIRONET4500_PROC=m +CONFIG_AIRO=m +CONFIG_HERMES=m +CONFIG_PLX_HERMES=m +CONFIG_PCI_HERMES=m +CONFIG_PCMCIA_HERMES=m +CONFIG_AIRO_CS=m +CONFIG_NET_WIRELESS=y + +# +# Token Ring devices +# +CONFIG_TR=y +CONFIG_IBMTR=m +CONFIG_IBMOL=m +CONFIG_IBMLS=m +CONFIG_3C359=m +CONFIG_TMS380TR=m +CONFIG_TMSPCI=m +CONFIG_TMSISA=m +CONFIG_ABYSS=m +# CONFIG_MADGEMC is not set +CONFIG_SMCTR=m +CONFIG_NET_FC=y +CONFIG_IPHASE5526=m +CONFIG_RCPCI=m +CONFIG_SHAPER=m + +# +# Wan interfaces +# +CONFIG_WAN=y +CONFIG_HOSTESS_SV11=m +CONFIG_COSA=m +# CONFIG_COMX is not set +# CONFIG_DSCC4 is not set +# CONFIG_LANMEDIA is not set +CONFIG_ATI_XX20=m +CONFIG_SEALEVEL_4021=m +# CONFIG_SYNCLINK_SYNCPPP is not set +# CONFIG_HDLC is not set +CONFIG_DLCI=m +CONFIG_DLCI_COUNT=24 +CONFIG_DLCI_MAX=8 +CONFIG_SDLA=m +CONFIG_WAN_ROUTER_DRIVERS=y +CONFIG_VENDOR_SANGOMA=m +CONFIG_WANPIPE_CHDLC=y +CONFIG_WANPIPE_FR=y +CONFIG_WANPIPE_X25=y +CONFIG_WANPIPE_PPP=y +CONFIG_WANPIPE_MULTPPP=y +CONFIG_CYCLADES_SYNC=m +CONFIG_CYCLOMX_X25=y +# CONFIG_LAPBETHER is not set +# CONFIG_X25_ASY is not set +CONFIG_SBNI=m +CONFIG_SBNI_MULTILINE=y + +# +# PCMCIA network device support +# +CONFIG_NET_PCMCIA=y +CONFIG_PCMCIA_3C589=m +CONFIG_PCMCIA_3C574=m +CONFIG_PCMCIA_FMVJ18X=m +CONFIG_PCMCIA_PCNET=m +CONFIG_PCMCIA_AXNET=m +CONFIG_PCMCIA_NMCLAN=m +CONFIG_PCMCIA_SMC91C92=m +CONFIG_PCMCIA_XIRC2PS=m +# CONFIG_ARCNET_COM20020_CS is not set +CONFIG_PCMCIA_IBMTR=m +CONFIG_PCMCIA_XIRCOM=m +CONFIG_PCMCIA_XIRTULIP=m +CONFIG_NET_PCMCIA_RADIO=y +CONFIG_PCMCIA_RAYCS=m +CONFIG_PCMCIA_NETWAVE=m +CONFIG_PCMCIA_WAVELAN=m +CONFIG_AIRONET4500_CS=m + +# +# ATM drivers +# +# CONFIG_ATM_TCP is not set +CONFIG_ATM_LANAI=m +CONFIG_ATM_ENI=m +# CONFIG_ATM_ENI_DEBUG is not set +# CONFIG_ATM_ENI_TUNE_BURST is not set +CONFIG_ATM_FIRESTREAM=m +CONFIG_ATM_ZATM=m +# CONFIG_ATM_ZATM_DEBUG is not set +CONFIG_ATM_ZATM_EXACT_TS=y +CONFIG_ATM_NICSTAR=m +CONFIG_ATM_NICSTAR_USE_SUNI=y +CONFIG_ATM_NICSTAR_USE_IDT77105=y +CONFIG_ATM_IDT77252=m +# CONFIG_ATM_IDT77252_DEBUG is not set +# CONFIG_ATM_IDT77252_RCV_ALL is not set +CONFIG_ATM_IDT77252_USE_SUNI=y +CONFIG_ATM_AMBASSADOR=m +# CONFIG_ATM_AMBASSADOR_DEBUG is not set +CONFIG_ATM_HORIZON=m +# CONFIG_ATM_HORIZON_DEBUG is not set +CONFIG_ATM_IA=m +# CONFIG_ATM_IA_DEBUG is not set +CONFIG_ATM_FORE200E_MAYBE=m +CONFIG_ATM_FORE200E_PCA=y +CONFIG_ATM_FORE200E_PCA_DEFAULT_FW=y +CONFIG_ATM_FORE200E_TX_RETRY=16 +CONFIG_ATM_FORE200E_DEBUG=0 +CONFIG_ATM_FORE200E=m +CONFIG_ATM_HE=m +CONFIG_ATM_HE_USE_SUNI=y + +# +# Amateur Radio support +# +CONFIG_HAMRADIO=y +CONFIG_AX25=m +# CONFIG_AX25_DAMA_SLAVE is not set +CONFIG_NETROM=m +CONFIG_ROSE=m + +# +# AX.25 network device drivers +# +# CONFIG_MKISS is not set +# CONFIG_6PACK is not set +# CONFIG_BPQETHER is not set +# CONFIG_DMASCC is not set +# CONFIG_SCC is not set +# CONFIG_BAYCOM_SER_FDX is not set +# CONFIG_BAYCOM_SER_HDX is not set +# CONFIG_BAYCOM_PAR is not set +# CONFIG_BAYCOM_EPP is not set +CONFIG_SOUNDMODEM=m +CONFIG_SOUNDMODEM_SBC=y +CONFIG_SOUNDMODEM_WSS=y +CONFIG_SOUNDMODEM_AFSK1200=y +CONFIG_SOUNDMODEM_AFSK2400_7=y +CONFIG_SOUNDMODEM_AFSK2400_8=y +CONFIG_SOUNDMODEM_AFSK2666=y +CONFIG_SOUNDMODEM_HAPN4800=y +CONFIG_SOUNDMODEM_PSK4800=y +CONFIG_SOUNDMODEM_FSK9600=y +# CONFIG_YAM is not set + +# +# IrDA (infrared) support +# +CONFIG_IRDA=m +CONFIG_IRLAN=m +CONFIG_IRNET=m +CONFIG_IRCOMM=m +CONFIG_IRDA_ULTRA=y +CONFIG_IRDA_CACHE_LAST_LSAP=y +CONFIG_IRDA_FAST_RR=y +# CONFIG_IRDA_DEBUG is not set + +# +# Infrared-port device drivers +# +CONFIG_IRTTY_SIR=m +CONFIG_IRPORT_SIR=m +CONFIG_DONGLE=y +CONFIG_ESI_DONGLE=m +CONFIG_ACTISYS_DONGLE=m +CONFIG_TEKRAM_DONGLE=m +CONFIG_GIRBIL_DONGLE=m +CONFIG_LITELINK_DONGLE=m +CONFIG_MCP2120_DONGLE=m +CONFIG_OLD_BELKIN_DONGLE=m +CONFIG_ACT200L_DONGLE=m +CONFIG_MA600_DONGLE=m +CONFIG_USB_IRDA=m +CONFIG_NSC_FIR=m +CONFIG_WINBOND_FIR=m +CONFIG_TOSHIBA_OLD=m +CONFIG_TOSHIBA_FIR=m +CONFIG_SMC_IRCC_FIR=m +CONFIG_ALI_FIR=m +CONFIG_VLSI_FIR=m + +# +# ISDN subsystem +# +CONFIG_ISDN=m +CONFIG_ISDN_BOOL=y +CONFIG_ISDN_PPP=y +CONFIG_IPPP_FILTER=y +CONFIG_ISDN_PPP_VJ=y +CONFIG_ISDN_MPP=y +CONFIG_ISDN_PPP_BSDCOMP=m +CONFIG_ISDN_AUDIO=y +CONFIG_ISDN_TTY_FAX=y + +# +# ISDN feature submodules +# +CONFIG_ISDN_DRV_LOOP=m +# CONFIG_ISDN_DIVERSION is not set + +# +# Passive ISDN cards +# +CONFIG_ISDN_DRV_HISAX=m +CONFIG_ISDN_HISAX=y +CONFIG_HISAX_EURO=y +CONFIG_DE_AOC=y +# CONFIG_HISAX_NO_SENDCOMPLETE is not set +# CONFIG_HISAX_NO_LLC is not set +# CONFIG_HISAX_NO_KEYPAD is not set +CONFIG_HISAX_1TR6=y +CONFIG_HISAX_NI1=y +CONFIG_HISAX_MAX_CARDS=8 +CONFIG_HISAX_16_0=y +CONFIG_HISAX_16_3=y +CONFIG_HISAX_AVM_A1=y +CONFIG_HISAX_IX1MICROR2=y +CONFIG_HISAX_ASUSCOM=y +CONFIG_HISAX_TELEINT=y +CONFIG_HISAX_HFCS=y +CONFIG_HISAX_SPORTSTER=y +CONFIG_HISAX_MIC=y +CONFIG_HISAX_ISURF=y +CONFIG_HISAX_HSTSAPHIR=y +CONFIG_HISAX_TELESPCI=y +CONFIG_HISAX_S0BOX=y +CONFIG_HISAX_FRITZPCI=y +CONFIG_HISAX_AVM_A1_PCMCIA=y +CONFIG_HISAX_ELSA=y +CONFIG_HISAX_DIEHLDIVA=y +CONFIG_HISAX_SEDLBAUER=y +CONFIG_HISAX_NETJET=y +CONFIG_HISAX_NETJET_U=y +CONFIG_HISAX_NICCY=y +CONFIG_HISAX_BKM_A4T=y +CONFIG_HISAX_SCT_QUADRO=y +CONFIG_HISAX_GAZEL=y +CONFIG_HISAX_HFC_PCI=y +CONFIG_HISAX_W6692=y +CONFIG_HISAX_HFC_SX=y +CONFIG_HISAX_ENTERNOW_PCI=y +CONFIG_HISAX_DEBUG=y +CONFIG_HISAX_SEDLBAUER_CS=m +CONFIG_HISAX_ELSA_CS=m +CONFIG_HISAX_AVM_A1_CS=m +CONFIG_HISAX_ST5481=m +CONFIG_HISAX_FRITZ_PCIPNP=m +CONFIG_USB_AUERISDN=m + +# +# Active ISDN cards +# +CONFIG_ISDN_DRV_ICN=m +CONFIG_ISDN_DRV_PCBIT=m +# CONFIG_ISDN_DRV_SC is not set +# CONFIG_ISDN_DRV_ACT2000 is not set +CONFIG_ISDN_DRV_EICON=y +CONFIG_ISDN_DRV_EICON_DIVAS=m +# CONFIG_ISDN_DRV_EICON_OLD is not set +CONFIG_ISDN_DRV_TPAM=m +CONFIG_ISDN_CAPI=m +CONFIG_ISDN_DRV_AVMB1_VERBOSE_REASON=y +CONFIG_ISDN_CAPI_MIDDLEWARE=y +CONFIG_ISDN_CAPI_CAPI20=m +CONFIG_ISDN_CAPI_CAPIFS_BOOL=y +CONFIG_ISDN_CAPI_CAPIFS=m +CONFIG_ISDN_CAPI_CAPIDRV=m +CONFIG_ISDN_DRV_AVMB1_B1ISA=m +CONFIG_ISDN_DRV_AVMB1_B1PCI=m +CONFIG_ISDN_DRV_AVMB1_B1PCIV4=y +CONFIG_ISDN_DRV_AVMB1_T1ISA=m +CONFIG_ISDN_DRV_AVMB1_B1PCMCIA=m +CONFIG_ISDN_DRV_AVMB1_AVM_CS=m +CONFIG_ISDN_DRV_AVMB1_T1PCI=m +CONFIG_ISDN_DRV_AVMB1_C4=m +CONFIG_HYSDN=m +CONFIG_HYSDN_CAPI=y + +# +# Old CD-ROM drivers (not SCSI, not IDE) +# +# CONFIG_CD_NO_IDESCSI is not set + +# +# Input core support +# +CONFIG_INPUT=m +CONFIG_INPUT_KEYBDEV=m +CONFIG_INPUT_MOUSEDEV=m +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +CONFIG_INPUT_JOYDEV=m +CONFIG_INPUT_EVDEV=m + +# +# Character devices +# +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_SERIAL=y +CONFIG_SERIAL_CONSOLE=y +CONFIG_SERIAL_EXTENDED=y +CONFIG_SERIAL_MANY_PORTS=y +CONFIG_SERIAL_SHARE_IRQ=y +# CONFIG_SERIAL_DETECT_IRQ is not set +CONFIG_SERIAL_MULTIPORT=y +# CONFIG_HUB6 is not set +CONFIG_SERIAL_NONSTANDARD=y +CONFIG_COMPUTONE=m +CONFIG_ROCKETPORT=m +CONFIG_CYCLADES=m +# CONFIG_CYZ_INTR is not set +CONFIG_DIGIEPCA=m +CONFIG_ESPSERIAL=m +CONFIG_MOXA_INTELLIO=m +CONFIG_MOXA_SMARTIO=m +CONFIG_ISI=m +CONFIG_SYNCLINK=m +# CONFIG_SYNCLINKMP is not set +CONFIG_N_HDLC=m +CONFIG_RISCOM8=m +CONFIG_SPECIALIX=m +CONFIG_SPECIALIX_RTSCTS=y +CONFIG_SX=m +# CONFIG_RIO is not set +CONFIG_STALDRV=y +CONFIG_STALLION=m +CONFIG_ISTALLION=m +CONFIG_UNIX98_PTYS=y +CONFIG_UNIX98_PTY_COUNT=2048 +CONFIG_PRINTER=m +CONFIG_LP_CONSOLE=y +CONFIG_PPDEV=m +CONFIG_TIPAR=m + +# +# I2C support +# +CONFIG_I2C=m +CONFIG_I2C_ALGOBIT=m +CONFIG_I2C_PHILIPSPAR=m +CONFIG_I2C_ELV=m +CONFIG_I2C_VELLEMAN=m +# CONFIG_SCx200_I2C is not set +# CONFIG_SCx200_ACB is not set +CONFIG_I2C_ALGOPCF=m +CONFIG_I2C_ELEKTOR=m +CONFIG_I2C_CHARDEV=m +CONFIG_I2C_PROC=m + +# +# Mice +# +CONFIG_BUSMOUSE=m +CONFIG_ATIXL_BUSMOUSE=m +CONFIG_LOGIBUSMOUSE=m +CONFIG_MS_BUSMOUSE=m +CONFIG_MOUSE=y +CONFIG_PSMOUSE=y +CONFIG_82C710_MOUSE=m +CONFIG_PC110_PAD=m +CONFIG_MK712_MOUSE=m + +# +# Joysticks +# +CONFIG_INPUT_GAMEPORT=m +CONFIG_INPUT_NS558=m +CONFIG_INPUT_LIGHTNING=m +CONFIG_INPUT_PCIGAME=m +CONFIG_INPUT_CS461X=m +CONFIG_INPUT_EMU10K1=m +CONFIG_INPUT_SERIO=m +CONFIG_INPUT_SERPORT=m +CONFIG_INPUT_ANALOG=m +CONFIG_INPUT_A3D=m +CONFIG_INPUT_ADI=m +CONFIG_INPUT_COBRA=m +CONFIG_INPUT_GF2K=m +CONFIG_INPUT_GRIP=m +CONFIG_INPUT_INTERACT=m +CONFIG_INPUT_TMDC=m +CONFIG_INPUT_SIDEWINDER=m +CONFIG_INPUT_IFORCE_USB=m +CONFIG_INPUT_IFORCE_232=m +CONFIG_INPUT_WARRIOR=m +CONFIG_INPUT_MAGELLAN=m +CONFIG_INPUT_SPACEORB=m +CONFIG_INPUT_SPACEBALL=m +CONFIG_INPUT_STINGER=m +CONFIG_INPUT_DB9=m +CONFIG_INPUT_GAMECON=m +CONFIG_INPUT_TURBOGRAFX=m +# CONFIG_QIC02_TAPE is not set +CONFIG_IPMI_HANDLER=m +# CONFIG_IPMI_PANIC_EVENT is not set +CONFIG_IPMI_DEVICE_INTERFACE=m +CONFIG_IPMI_KCS=m +CONFIG_IPMI_WATCHDOG=m + +# +# Watchdog Cards +# +CONFIG_WATCHDOG=y +# CONFIG_WATCHDOG_NOWAYOUT is not set +CONFIG_ACQUIRE_WDT=m +CONFIG_ADVANTECH_WDT=m +CONFIG_ALIM1535_WDT=m +CONFIG_ALIM7101_WDT=m +CONFIG_SC520_WDT=m +CONFIG_PCWATCHDOG=m +CONFIG_EUROTECH_WDT=m +CONFIG_IB700_WDT=m +CONFIG_WAFER_WDT=m +CONFIG_I810_TCO=m +# CONFIG_MIXCOMWD is not set +# CONFIG_60XX_WDT is not set +CONFIG_SC1200_WDT=m +# CONFIG_SCx200_WDT is not set +CONFIG_SOFT_WATCHDOG=m +CONFIG_W83877F_WDT=m +CONFIG_WDT=m +CONFIG_WDTPCI=m +# CONFIG_WDT_501 is not set +CONFIG_MACHZ_WDT=m +CONFIG_AMD7XX_TCO=m +# CONFIG_SCx200_GPIO is not set +CONFIG_AMD_RNG=m +CONFIG_INTEL_RNG=m +CONFIG_AMD_PM768=m +CONFIG_NVRAM=m +CONFIG_RTC=y +CONFIG_DTLK=m +CONFIG_R3964=m +# CONFIG_APPLICOM is not set +CONFIG_SONYPI=m + +# +# Ftape, the floppy tape device driver +# +# CONFIG_FTAPE is not set +CONFIG_AGP=y +CONFIG_AGP_INTEL=y +CONFIG_AGP_I810=y +CONFIG_AGP_VIA=y +CONFIG_AGP_AMD=y +CONFIG_AGP_AMD_8151=y +CONFIG_AGP_SIS=y +CONFIG_AGP_ALI=y +CONFIG_AGP_SWORKS=y +CONFIG_AGP_NVIDIA=y +CONFIG_DRM=y +# CONFIG_DRM_OLD is not set +CONFIG_DRM_NEW=y +CONFIG_DRM_TDFX=m +CONFIG_DRM_R128=m +CONFIG_DRM_RADEON=m +CONFIG_DRM_I810=m +# CONFIG_DRM_I810_XFREE_41 is not set +CONFIG_DRM_I830=m +CONFIG_DRM_MGA=m +# CONFIG_DRM_SIS is not set + +# +# PCMCIA character devices +# +CONFIG_PCMCIA_SERIAL_CS=m +CONFIG_SYNCLINK_CS=m +CONFIG_MWAVE=m + +# +# Multimedia devices +# +CONFIG_VIDEO_DEV=m + +# +# Video For Linux +# +CONFIG_VIDEO_PROC_FS=y +CONFIG_I2C_PARPORT=m +CONFIG_VIDEO_BT848=m +CONFIG_VIDEO_PMS=m +CONFIG_VIDEO_BWQCAM=m +CONFIG_VIDEO_CQCAM=m +CONFIG_VIDEO_W9966=m +CONFIG_VIDEO_CPIA=m +CONFIG_VIDEO_CPIA_PP=m +CONFIG_VIDEO_CPIA_USB=m +CONFIG_VIDEO_SAA5249=m +CONFIG_TUNER_3036=m +CONFIG_VIDEO_STRADIS=m +CONFIG_VIDEO_ZORAN=m +CONFIG_VIDEO_ZORAN_BUZ=m +CONFIG_VIDEO_ZORAN_DC10=m +CONFIG_VIDEO_ZORAN_LML33=m +CONFIG_VIDEO_ZR36120=m +CONFIG_VIDEO_MEYE=m + +# +# Radio Adapters +# +CONFIG_RADIO_CADET=m +CONFIG_RADIO_RTRACK=m +CONFIG_RADIO_RTRACK2=m +CONFIG_RADIO_AZTECH=m +CONFIG_RADIO_GEMTEK=m +CONFIG_RADIO_GEMTEK_PCI=m +CONFIG_RADIO_MAXIRADIO=m +CONFIG_RADIO_MAESTRO=m +CONFIG_RADIO_MIROPCM20=m +CONFIG_RADIO_MIROPCM20_RDS=m +CONFIG_RADIO_SF16FMI=m +CONFIG_RADIO_SF16FMR2=m +CONFIG_RADIO_TERRATEC=m +CONFIG_RADIO_TRUST=m +CONFIG_RADIO_TYPHOON=m +CONFIG_RADIO_TYPHOON_PROC_FS=y +CONFIG_RADIO_ZOLTRIX=m + +# +# File systems +# +CONFIG_QUOTA=y +CONFIG_QFMT_V2=y +CONFIG_AUTOFS_FS=m +CONFIG_AUTOFS4_FS=m +CONFIG_REISERFS_FS=m +# CONFIG_REISERFS_CHECK is not set +CONFIG_REISERFS_PROC_INFO=y +# CONFIG_ADFS_FS is not set +# CONFIG_ADFS_FS_RW is not set +# CONFIG_AFFS_FS is not set +CONFIG_HFS_FS=m +# CONFIG_HFSPLUS_FS is not set +CONFIG_BEFS_FS=m +# CONFIG_BEFS_DEBUG is not set +CONFIG_BFS_FS=m +CONFIG_EXT3_FS=m +CONFIG_JBD=m +# CONFIG_JBD_DEBUG is not set +CONFIG_FAT_FS=m +CONFIG_MSDOS_FS=m +CONFIG_UMSDOS_FS=m +CONFIG_VFAT_FS=m +# CONFIG_EFS_FS is not set +# CONFIG_JFFS_FS is not set +# CONFIG_JFFS2_FS is not set +CONFIG_CRAMFS=m +CONFIG_TMPFS=y +CONFIG_RAMFS=y +CONFIG_ISO9660_FS=y +CONFIG_JOLIET=y +CONFIG_ZISOFS=y +CONFIG_JFS_FS=m +# CONFIG_JFS_DEBUG is not set +# CONFIG_JFS_STATISTICS is not set +CONFIG_MINIX_FS=m +CONFIG_VXFS_FS=m +# CONFIG_NTFS_FS is not set +# CONFIG_NTFS_RW is not set +# CONFIG_HPFS_FS is not set +CONFIG_PROC_FS=y +# CONFIG_DEVFS_FS is not set +# CONFIG_DEVFS_MOUNT is not set +# CONFIG_DEVFS_DEBUG is not set +CONFIG_DEVPTS_FS=y +# CONFIG_QNX4FS_FS is not set +# CONFIG_QNX4FS_RW is not set +CONFIG_ROMFS_FS=m +CONFIG_EXT2_FS=y +CONFIG_SYSV_FS=m +CONFIG_UDF_FS=m +CONFIG_UDF_RW=y +CONFIG_UFS_FS=m +# CONFIG_UFS_FS_WRITE is not set + +# +# Network File Systems +# +CONFIG_CODA_FS=m +CONFIG_INTERMEZZO_FS=m +CONFIG_NFS_FS=m +CONFIG_NFS_V3=y +# CONFIG_NFS_DIRECTIO is not set +# CONFIG_ROOT_NFS is not set +CONFIG_NFSD=m +CONFIG_NFSD_V3=y +CONFIG_NFSD_TCP=y +CONFIG_SUNRPC=m +CONFIG_LOCKD=m +CONFIG_LOCKD_V4=y +CONFIG_SMB_FS=m +# CONFIG_SMB_NLS_DEFAULT is not set +CONFIG_NCP_FS=m +# CONFIG_NCPFS_PACKET_SIGNING is not set +# CONFIG_NCPFS_IOCTL_LOCKING is not set +# CONFIG_NCPFS_STRONG is not set +# CONFIG_NCPFS_NFS_NS is not set +# CONFIG_NCPFS_OS2_NS is not set +# CONFIG_NCPFS_SMALLDOS is not set +# CONFIG_NCPFS_NLS is not set +# CONFIG_NCPFS_EXTRAS is not set +CONFIG_ZISOFS_FS=y + +# +# Partition Types +# +CONFIG_PARTITION_ADVANCED=y +# CONFIG_ACORN_PARTITION is not set +CONFIG_OSF_PARTITION=y +# CONFIG_AMIGA_PARTITION is not set +# CONFIG_ATARI_PARTITION is not set +CONFIG_MAC_PARTITION=y +CONFIG_MSDOS_PARTITION=y +CONFIG_BSD_DISKLABEL=y +CONFIG_MINIX_SUBPARTITION=y +CONFIG_SOLARIS_X86_PARTITION=y +CONFIG_UNIXWARE_DISKLABEL=y +# CONFIG_LDM_PARTITION is not set +CONFIG_SGI_PARTITION=y +# CONFIG_ULTRIX_PARTITION is not set +CONFIG_SUN_PARTITION=y +# CONFIG_EFI_PARTITION is not set +CONFIG_SMB_NLS=y +CONFIG_NLS=y + +# +# Native Language Support +# +CONFIG_NLS_DEFAULT="iso8859-1" +CONFIG_NLS_CODEPAGE_437=m +CONFIG_NLS_CODEPAGE_737=m +CONFIG_NLS_CODEPAGE_775=m +CONFIG_NLS_CODEPAGE_850=m +CONFIG_NLS_CODEPAGE_852=m +CONFIG_NLS_CODEPAGE_855=m +CONFIG_NLS_CODEPAGE_857=m +CONFIG_NLS_CODEPAGE_860=m +CONFIG_NLS_CODEPAGE_861=m +CONFIG_NLS_CODEPAGE_862=m +CONFIG_NLS_CODEPAGE_863=m +CONFIG_NLS_CODEPAGE_864=m +CONFIG_NLS_CODEPAGE_865=m +CONFIG_NLS_CODEPAGE_866=m +CONFIG_NLS_CODEPAGE_869=m +CONFIG_NLS_CODEPAGE_936=m +CONFIG_NLS_CODEPAGE_950=m +CONFIG_NLS_CODEPAGE_932=m +CONFIG_NLS_CODEPAGE_949=m +CONFIG_NLS_CODEPAGE_874=m +CONFIG_NLS_ISO8859_8=m +CONFIG_NLS_CODEPAGE_1250=m +CONFIG_NLS_CODEPAGE_1251=m +CONFIG_NLS_ISO8859_1=m +CONFIG_NLS_ISO8859_2=m +CONFIG_NLS_ISO8859_3=m +CONFIG_NLS_ISO8859_4=m +CONFIG_NLS_ISO8859_5=m +CONFIG_NLS_ISO8859_6=m +CONFIG_NLS_ISO8859_7=m +CONFIG_NLS_ISO8859_9=m +CONFIG_NLS_ISO8859_13=m +CONFIG_NLS_ISO8859_14=m +CONFIG_NLS_ISO8859_15=m +CONFIG_NLS_KOI8_R=m +CONFIG_NLS_KOI8_U=m +CONFIG_NLS_UTF8=m + +# +# Console drivers +# +CONFIG_VGA_CONSOLE=y +CONFIG_VIDEO_SELECT=y +CONFIG_MDA_CONSOLE=m + +# +# Frame-buffer support +# +CONFIG_FB=y +CONFIG_DUMMY_CONSOLE=y +CONFIG_FB_RIVA=m +CONFIG_FB_CLGEN=m +CONFIG_FB_PM2=m +# CONFIG_FB_PM2_FIFO_DISCONNECT is not set +CONFIG_FB_PM2_PCI=y +CONFIG_FB_PM3=m +# CONFIG_FB_CYBER2000 is not set +CONFIG_FB_VESA=y +CONFIG_FB_VGA16=m +CONFIG_FB_HGA=m +CONFIG_VIDEO_SELECT=y +CONFIG_FB_MATROX=m +CONFIG_FB_MATROX_MILLENIUM=y +CONFIG_FB_MATROX_MYSTIQUE=y +# CONFIG_FB_MATROX_G450 is not set +CONFIG_FB_MATROX_G100A=y +CONFIG_FB_MATROX_G100=y +CONFIG_FB_MATROX_I2C=m +# CONFIG_FB_MATROX_MAVEN is not set +# CONFIG_FB_MATROX_PROC is not set +CONFIG_FB_MATROX_MULTIHEAD=y +CONFIG_FB_ATY=m +CONFIG_FB_ATY_GX=y +CONFIG_FB_ATY_CT=y +CONFIG_FB_RADEON=m +CONFIG_FB_ATY128=m +# CONFIG_FB_INTEL is not set +CONFIG_FB_SIS=m +CONFIG_FB_SIS_300=y +CONFIG_FB_SIS_315=y +CONFIG_FB_NEOMAGIC=m +CONFIG_FB_3DFX=m +CONFIG_FB_VOODOO1=m +# CONFIG_FB_TRIDENT is not set +# CONFIG_FB_VIRTUAL is not set +# CONFIG_FBCON_ADVANCED is not set +CONFIG_FBCON_MFB=m +CONFIG_FBCON_CFB8=y +CONFIG_FBCON_CFB16=y +CONFIG_FBCON_CFB24=y +CONFIG_FBCON_CFB32=y +CONFIG_FBCON_VGA_PLANES=m +CONFIG_FBCON_HGA=m +# CONFIG_FBCON_FONTWIDTH8_ONLY is not set +# CONFIG_FBCON_FONTS is not set +CONFIG_FONT_8x8=y +CONFIG_FONT_8x16=y + +# +# Sound +# +CONFIG_SOUND=m +CONFIG_SOUND_ALI5455=m +CONFIG_SOUND_BT878=m +CONFIG_SOUND_CMPCI=m +CONFIG_SOUND_CMPCI_FM=y +CONFIG_SOUND_CMPCI_FMIO=388 +CONFIG_SOUND_CMPCI_FMIO=388 +CONFIG_SOUND_CMPCI_MIDI=y +CONFIG_SOUND_CMPCI_MPUIO=330 +CONFIG_SOUND_CMPCI_JOYSTICK=y +CONFIG_SOUND_CMPCI_CM8738=y +# CONFIG_SOUND_CMPCI_SPDIFINVERSE is not set +CONFIG_SOUND_CMPCI_SPDIFLOOP=y +CONFIG_SOUND_CMPCI_SPEAKERS=2 +CONFIG_SOUND_EMU10K1=m +CONFIG_MIDI_EMU10K1=y +CONFIG_SOUND_FUSION=m +CONFIG_SOUND_CS4281=m +CONFIG_SOUND_ES1370=m +CONFIG_SOUND_ES1371=m +CONFIG_SOUND_ESSSOLO1=m +CONFIG_SOUND_MAESTRO=m +CONFIG_SOUND_MAESTRO3=m +CONFIG_SOUND_FORTE=m +CONFIG_SOUND_ICH=m +CONFIG_SOUND_RME96XX=m +CONFIG_SOUND_SONICVIBES=m +CONFIG_SOUND_TRIDENT=m +CONFIG_SOUND_MSNDCLAS=m +# CONFIG_MSNDCLAS_HAVE_BOOT is not set +CONFIG_MSNDCLAS_INIT_FILE="/etc/sound/msndinit.bin" +CONFIG_MSNDCLAS_PERM_FILE="/etc/sound/msndperm.bin" +CONFIG_SOUND_MSNDPIN=m +# CONFIG_MSNDPIN_HAVE_BOOT is not set +CONFIG_MSNDPIN_INIT_FILE="/etc/sound/pndspini.bin" +CONFIG_MSNDPIN_PERM_FILE="/etc/sound/pndsperm.bin" +CONFIG_SOUND_VIA82CXXX=m +CONFIG_MIDI_VIA82CXXX=y +CONFIG_SOUND_OSS=m +# CONFIG_SOUND_TRACEINIT is not set +CONFIG_SOUND_DMAP=y +CONFIG_SOUND_AD1816=m +CONFIG_SOUND_AD1889=m +CONFIG_SOUND_SGALAXY=m +CONFIG_SOUND_ADLIB=m +CONFIG_SOUND_ACI_MIXER=m +CONFIG_SOUND_CS4232=m +CONFIG_SOUND_SSCAPE=m +CONFIG_SOUND_GUS=m +CONFIG_SOUND_GUS16=y +CONFIG_SOUND_GUSMAX=y +CONFIG_SOUND_VMIDI=m +CONFIG_SOUND_TRIX=m +CONFIG_SOUND_MSS=m +CONFIG_SOUND_MPU401=m +CONFIG_SOUND_NM256=m +CONFIG_SOUND_MAD16=m +CONFIG_MAD16_OLDCARD=y +CONFIG_SOUND_PAS=m +# CONFIG_PAS_JOYSTICK is not set +CONFIG_SOUND_PSS=m +# CONFIG_PSS_MIXER is not set +# CONFIG_PSS_HAVE_BOOT is not set +CONFIG_SOUND_SB=m +CONFIG_SOUND_AWE32_SYNTH=m +CONFIG_SOUND_KAHLUA=m +CONFIG_SOUND_WAVEFRONT=m +CONFIG_SOUND_MAUI=m +CONFIG_SOUND_YM3812=m +CONFIG_SOUND_OPL3SA1=m +CONFIG_SOUND_OPL3SA2=m +CONFIG_SOUND_YMFPCI=m +CONFIG_SOUND_YMFPCI_LEGACY=y +# CONFIG_SOUND_UART6850 is not set +CONFIG_SOUND_AEDSP16=m +CONFIG_SC6600=y +CONFIG_SC6600_JOY=y +CONFIG_SC6600_CDROM=4 +CONFIG_SC6600_CDROMBASE=0 +CONFIG_AEDSP16_SBPRO=y +CONFIG_AEDSP16_MPU401=y +CONFIG_SOUND_TVMIXER=m + +# +# USB support +# +CONFIG_USB=m +# CONFIG_USB_DEBUG is not set +CONFIG_USB_DEVICEFS=y +# CONFIG_USB_BANDWIDTH is not set +CONFIG_USB_EHCI_HCD=m +# CONFIG_USB_UHCI is not set +CONFIG_USB_UHCI_ALT=m +CONFIG_USB_OHCI=m +CONFIG_USB_AUDIO=m +# CONFIG_USB_EMI26 is not set +CONFIG_USB_MIDI=m +CONFIG_USB_STORAGE=m +# CONFIG_USB_STORAGE_DEBUG is not set +CONFIG_USB_STORAGE_DATAFAB=y +CONFIG_USB_STORAGE_FREECOM=y +CONFIG_USB_STORAGE_ISD200=y +CONFIG_USB_STORAGE_DPCM=y +CONFIG_USB_STORAGE_HP8200e=y +CONFIG_USB_STORAGE_SDDR09=y +CONFIG_USB_STORAGE_SDDR55=y +CONFIG_USB_STORAGE_JUMPSHOT=y +CONFIG_USB_ACM=m +CONFIG_USB_PRINTER=m +CONFIG_USB_HID=m +CONFIG_USB_HIDINPUT=y +CONFIG_USB_HIDDEV=y +# CONFIG_USB_KBD is not set +# CONFIG_USB_MOUSE is not set +CONFIG_USB_AIPTEK=m +CONFIG_USB_WACOM=m +CONFIG_USB_KBTAB=m +CONFIG_USB_POWERMATE=m +# CONFIG_USB_DC2XX is not set +CONFIG_USB_MDC800=m +CONFIG_USB_SCANNER=m +CONFIG_USB_MICROTEK=m +CONFIG_USB_HPUSBSCSI=m +CONFIG_USB_IBMCAM=m +CONFIG_USB_KONICAWC=m +CONFIG_USB_OV511=m +CONFIG_USB_PWC=m +CONFIG_USB_SE401=m +CONFIG_USB_STV680=m +CONFIG_USB_VICAM=m +CONFIG_USB_DSBR=m +CONFIG_USB_DABUSB=m +CONFIG_USB_PEGASUS=m +CONFIG_USB_RTL8150=m +CONFIG_USB_KAWETH=m +CONFIG_USB_CATC=m +CONFIG_USB_AX8817X=m +CONFIG_USB_CDCETHER=m +CONFIG_USB_USBNET=m +CONFIG_USB_USS720=m + +# +# USB Serial Converter support +# +CONFIG_USB_SERIAL=m +# CONFIG_USB_SERIAL_DEBUG is not set +CONFIG_USB_SERIAL_GENERIC=y +CONFIG_USB_SERIAL_BELKIN=m +CONFIG_USB_SERIAL_WHITEHEAT=m +CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m +CONFIG_USB_SERIAL_EMPEG=m +CONFIG_USB_SERIAL_FTDI_SIO=m +CONFIG_USB_SERIAL_VISOR=m +CONFIG_USB_SERIAL_IPAQ=m +CONFIG_USB_SERIAL_IR=m +CONFIG_USB_SERIAL_EDGEPORT=m +CONFIG_USB_SERIAL_EDGEPORT_TI=m +CONFIG_USB_SERIAL_KEYSPAN_PDA=m +CONFIG_USB_SERIAL_KEYSPAN=m +# CONFIG_USB_SERIAL_KEYSPAN_USA28 is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA28X is not set +CONFIG_USB_SERIAL_KEYSPAN_USA28XA=y +CONFIG_USB_SERIAL_KEYSPAN_USA28XB=y +# CONFIG_USB_SERIAL_KEYSPAN_USA19 is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA18X is not set +CONFIG_USB_SERIAL_KEYSPAN_USA19W=y +CONFIG_USB_SERIAL_KEYSPAN_USA19QW=y +CONFIG_USB_SERIAL_KEYSPAN_USA19QI=y +CONFIG_USB_SERIAL_KEYSPAN_MPR=y +CONFIG_USB_SERIAL_KEYSPAN_USA49W=y +CONFIG_USB_SERIAL_KEYSPAN_USA49WLC=y +CONFIG_USB_SERIAL_MCT_U232=m +CONFIG_USB_SERIAL_KLSI=m +CONFIG_USB_SERIAL_KOBIL_SCT=m +CONFIG_USB_SERIAL_PL2303=m +CONFIG_USB_SERIAL_CYBERJACK=m +CONFIG_USB_SERIAL_XIRCOM=m +CONFIG_USB_SERIAL_OMNINET=m +CONFIG_USB_RIO500=m +CONFIG_USB_AUERSWALD=m +CONFIG_USB_TIGL=m +CONFIG_USB_BRLVGER=m +CONFIG_USB_LCD=m +CONFIG_USB_SPEEDTOUCH=m + +# +# Bluetooth support +# +CONFIG_BLUEZ=m +CONFIG_BLUEZ_L2CAP=m +CONFIG_BLUEZ_SCO=m +CONFIG_BLUEZ_RFCOMM=m +CONFIG_BLUEZ_RFCOMM_TTY=y +CONFIG_BLUEZ_BNEP=m +CONFIG_BLUEZ_BNEP_MC_FILTER=y +CONFIG_BLUEZ_BNEP_PROTO_FILTER=y +# CONFIG_BLUEZ_CMTP is not set + +# +# Bluetooth device drivers +# +CONFIG_BLUEZ_HCIUSB=m +CONFIG_BLUEZ_USB_SCO=y +CONFIG_BLUEZ_USB_ZERO_PACKET=y +CONFIG_BLUEZ_HCIUART=m +CONFIG_BLUEZ_HCIUART_H4=y +CONFIG_BLUEZ_HCIUART_BCSP=y +# CONFIG_BLUEZ_HCIUART_BCSP_TXCRC is not set +# CONFIG_BLUEZ_HCIBFUSB is not set +CONFIG_BLUEZ_HCIDTL1=m +CONFIG_BLUEZ_HCIBT3C=m +CONFIG_BLUEZ_HCIBLUECARD=m +CONFIG_BLUEZ_HCIBTUART=m +CONFIG_BLUEZ_HCIVHCI=m + +# +# Kernel hacking +# +CONFIG_DEBUG_KERNEL=y +CONFIG_DEBUG_STACKOVERFLOW=y +# CONFIG_DEBUG_HIGHMEM is not set +# CONFIG_DEBUG_SLAB is not set +# CONFIG_DEBUG_IOVIRT is not set +CONFIG_MAGIC_SYSRQ=y +# CONFIG_DEBUG_SPINLOCK is not set +# CONFIG_FRAME_POINTER is not set + +# +# Cryptographic options +# +# CONFIG_CRYPTO is not set + +# +# Library routines +# +# CONFIG_CRC32 is not set +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=m diff --git a/Makerules/generic-2.4.22-i686.config b/Makerules/generic-2.4.22-i686.config new file mode 100644 index 0000000..cf6fc97 --- /dev/null +++ b/Makerules/generic-2.4.22-i686.config @@ -0,0 +1,1744 @@ +# +# Automatically generated by make menuconfig: don't edit +# +CONFIG_X86=y +# CONFIG_SBUS is not set +CONFIG_UID16=y + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y + +# +# Loadable module support +# +CONFIG_MODULES=y +CONFIG_MODVERSIONS=y +CONFIG_KMOD=y + +# +# Processor type and features +# +# CONFIG_M386 is not set +# CONFIG_M486 is not set +# CONFIG_M586 is not set +# CONFIG_M586TSC is not set +# CONFIG_M586MMX is not set +CONFIG_M686=y +# CONFIG_MPENTIUMIII is not set +# CONFIG_MPENTIUM4 is not set +# CONFIG_MK6 is not set +# CONFIG_MK7 is not set +# CONFIG_MK8 is not set +# CONFIG_MELAN is not set +# CONFIG_MCRUSOE is not set +# CONFIG_MWINCHIPC6 is not set +# CONFIG_MWINCHIP2 is not set +# CONFIG_MWINCHIP3D is not set +# CONFIG_MCYRIXIII is not set +# CONFIG_MVIAC3_2 is not set +CONFIG_X86_WP_WORKS_OK=y +CONFIG_X86_INVLPG=y +CONFIG_X86_CMPXCHG=y +CONFIG_X86_XADD=y +CONFIG_X86_BSWAP=y +CONFIG_X86_POPAD_OK=y +# CONFIG_RWSEM_GENERIC_SPINLOCK is not set +CONFIG_RWSEM_XCHGADD_ALGORITHM=y +CONFIG_X86_L1_CACHE_SHIFT=5 +CONFIG_X86_HAS_TSC=y +CONFIG_X86_GOOD_APIC=y +CONFIG_X86_PGE=y +CONFIG_X86_USE_PPRO_CHECKSUM=y +CONFIG_X86_PPRO_FENCE=y +CONFIG_X86_F00F_WORKS_OK=y +CONFIG_X86_MCE=y +CONFIG_TOSHIBA=m +CONFIG_I8K=m +CONFIG_MICROCODE=m +CONFIG_X86_MSR=m +CONFIG_X86_CPUID=m +# CONFIG_NOHIGHMEM is not set +CONFIG_HIGHMEM4G=y +# CONFIG_HIGHMEM64G is not set +CONFIG_HIGHMEM=y +CONFIG_HIGHIO=y +# CONFIG_MATH_EMULATION is not set +CONFIG_MTRR=y +# CONFIG_SMP is not set +# CONFIG_X86_UP_APIC is not set +# CONFIG_X86_UP_IOAPIC is not set +# CONFIG_X86_TSC_DISABLE is not set +CONFIG_X86_TSC=y + +# +# General setup +# +CONFIG_NET=y +CONFIG_PCI=y +# CONFIG_PCI_GOBIOS is not set +# CONFIG_PCI_GODIRECT is not set +CONFIG_PCI_GOANY=y +CONFIG_PCI_BIOS=y +CONFIG_PCI_DIRECT=y +CONFIG_ISA=y +CONFIG_PCI_NAMES=y +CONFIG_EISA=y +# CONFIG_MCA is not set +CONFIG_HOTPLUG=y + +# +# PCMCIA/CardBus support +# +CONFIG_PCMCIA=m +CONFIG_CARDBUS=y +CONFIG_TCIC=y +CONFIG_I82092=y +CONFIG_I82365=y + +# +# PCI Hotplug Support +# +# CONFIG_HOTPLUG_PCI is not set +# CONFIG_HOTPLUG_PCI_COMPAQ is not set +# CONFIG_HOTPLUG_PCI_COMPAQ_NVRAM is not set +CONFIG_SYSVIPC=y +CONFIG_BSD_PROCESS_ACCT=y +CONFIG_SYSCTL=y +CONFIG_KCORE_ELF=y +# CONFIG_KCORE_AOUT is not set +CONFIG_BINFMT_AOUT=y +CONFIG_BINFMT_ELF=y +CONFIG_BINFMT_MISC=y +CONFIG_PM=y +CONFIG_APM=y +# CONFIG_APM_IGNORE_USER_SUSPEND is not set +# CONFIG_APM_DO_ENABLE is not set +CONFIG_APM_CPU_IDLE=y +# CONFIG_APM_DISPLAY_BLANK is not set +CONFIG_APM_RTC_IS_GMT=y +# CONFIG_APM_ALLOW_INTS is not set +# CONFIG_APM_REAL_MODE_POWER_OFF is not set + +# +# ACPI Support +# +# CONFIG_ACPI is not set + +# +# Memory Technology Devices (MTD) +# +# CONFIG_MTD is not set + +# +# Parallel port support +# +CONFIG_PARPORT=m +CONFIG_PARPORT_PC=m +CONFIG_PARPORT_PC_CML1=m +CONFIG_PARPORT_SERIAL=m +# CONFIG_PARPORT_PC_FIFO is not set +# CONFIG_PARPORT_PC_SUPERIO is not set +CONFIG_PARPORT_PC_PCMCIA=m +# CONFIG_PARPORT_AMIGA is not set +# CONFIG_PARPORT_MFC3 is not set +# CONFIG_PARPORT_ATARI is not set +# CONFIG_PARPORT_GSC is not set +# CONFIG_PARPORT_SUNBPP is not set +# CONFIG_PARPORT_OTHER is not set +CONFIG_PARPORT_1284=y + +# +# Plug and Play configuration +# +CONFIG_PNP=y +CONFIG_ISAPNP=y + +# +# Block devices +# +CONFIG_BLK_DEV_FD=y +CONFIG_BLK_DEV_XD=m +CONFIG_PARIDE=m +CONFIG_PARIDE_PARPORT=m +CONFIG_PARIDE_PD=m +CONFIG_PARIDE_PCD=m +CONFIG_PARIDE_PF=m +CONFIG_PARIDE_PT=m +CONFIG_PARIDE_PG=m +CONFIG_PARIDE_ATEN=m +CONFIG_PARIDE_BPCK=m +CONFIG_PARIDE_BPCK6=m +CONFIG_PARIDE_COMM=m +CONFIG_PARIDE_DSTR=m +CONFIG_PARIDE_FIT2=m +CONFIG_PARIDE_FIT3=m +CONFIG_PARIDE_EPAT=m +CONFIG_PARIDE_EPATC8=y +CONFIG_PARIDE_EPIA=m +CONFIG_PARIDE_FRIQ=m +CONFIG_PARIDE_FRPW=m +CONFIG_PARIDE_KBIC=m +CONFIG_PARIDE_KTTI=m +CONFIG_PARIDE_ON20=m +CONFIG_PARIDE_ON26=m +CONFIG_BLK_CPQ_DA=m +CONFIG_BLK_CPQ_CISS_DA=m +CONFIG_CISS_SCSI_TAPE=y +CONFIG_BLK_DEV_DAC960=m +CONFIG_BLK_DEV_UMEM=m +CONFIG_BLK_DEV_LOOP=m +CONFIG_BLK_DEV_NBD=m +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_SIZE=4096 +CONFIG_BLK_DEV_INITRD=y +CONFIG_BLK_STATS=y + +# +# Multi-device support (RAID and LVM) +# +CONFIG_MD=y +CONFIG_BLK_DEV_MD=y +CONFIG_MD_LINEAR=m +CONFIG_MD_RAID0=m +CONFIG_MD_RAID1=m +CONFIG_MD_RAID5=m +CONFIG_MD_MULTIPATH=m +CONFIG_BLK_DEV_LVM=m + +# +# Networking options +# +CONFIG_PACKET=y +CONFIG_PACKET_MMAP=y +CONFIG_NETLINK_DEV=y +CONFIG_NETFILTER=y +# CONFIG_NETFILTER_DEBUG is not set +CONFIG_FILTER=y +CONFIG_UNIX=y +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +CONFIG_IP_ADVANCED_ROUTER=y +CONFIG_IP_MULTIPLE_TABLES=y +CONFIG_IP_ROUTE_FWMARK=y +CONFIG_IP_ROUTE_NAT=y +CONFIG_IP_ROUTE_MULTIPATH=y +CONFIG_IP_ROUTE_TOS=y +CONFIG_IP_ROUTE_VERBOSE=y +# CONFIG_IP_PNP is not set +CONFIG_NET_IPIP=m +CONFIG_NET_IPGRE=m +CONFIG_NET_IPGRE_BROADCAST=y +CONFIG_IP_MROUTE=y +CONFIG_IP_PIMSM_V1=y +CONFIG_IP_PIMSM_V2=y +# CONFIG_ARPD is not set +# CONFIG_INET_ECN is not set +CONFIG_SYN_COOKIES=y + +# +# IP: Netfilter Configuration +# +CONFIG_IP_NF_CONNTRACK=m +CONFIG_IP_NF_FTP=m +CONFIG_IP_NF_AMANDA=m +CONFIG_IP_NF_TFTP=m +CONFIG_IP_NF_IRC=m +CONFIG_IP_NF_QUEUE=m +CONFIG_IP_NF_IPTABLES=m +CONFIG_IP_NF_MATCH_LIMIT=m +CONFIG_IP_NF_MATCH_MAC=m +CONFIG_IP_NF_MATCH_PKTTYPE=m +CONFIG_IP_NF_MATCH_MARK=m +CONFIG_IP_NF_MATCH_MULTIPORT=m +CONFIG_IP_NF_MATCH_TOS=m +CONFIG_IP_NF_MATCH_RECENT=m +CONFIG_IP_NF_MATCH_ECN=m +CONFIG_IP_NF_MATCH_DSCP=m +CONFIG_IP_NF_MATCH_AH_ESP=m +CONFIG_IP_NF_MATCH_LENGTH=m +CONFIG_IP_NF_MATCH_TTL=m +CONFIG_IP_NF_MATCH_TCPMSS=m +CONFIG_IP_NF_MATCH_HELPER=m +CONFIG_IP_NF_MATCH_STATE=m +CONFIG_IP_NF_MATCH_CONNTRACK=m +CONFIG_IP_NF_MATCH_UNCLEAN=m +CONFIG_IP_NF_MATCH_OWNER=m +CONFIG_IP_NF_FILTER=m +CONFIG_IP_NF_TARGET_REJECT=m +CONFIG_IP_NF_TARGET_MIRROR=m +CONFIG_IP_NF_NAT=m +CONFIG_IP_NF_NAT_NEEDED=y +CONFIG_IP_NF_TARGET_MASQUERADE=m +CONFIG_IP_NF_TARGET_REDIRECT=m +CONFIG_IP_NF_NAT_AMANDA=m +CONFIG_IP_NF_NAT_LOCAL=y +CONFIG_IP_NF_NAT_SNMP_BASIC=m +CONFIG_IP_NF_NAT_IRC=m +CONFIG_IP_NF_NAT_FTP=m +CONFIG_IP_NF_NAT_TFTP=m +CONFIG_IP_NF_MANGLE=m +CONFIG_IP_NF_TARGET_TOS=m +CONFIG_IP_NF_TARGET_ECN=m +CONFIG_IP_NF_TARGET_DSCP=m +CONFIG_IP_NF_TARGET_MARK=m +CONFIG_IP_NF_TARGET_LOG=m +CONFIG_IP_NF_TARGET_ULOG=m +CONFIG_IP_NF_TARGET_TCPMSS=m +CONFIG_IP_NF_ARPTABLES=m +CONFIG_IP_NF_ARPFILTER=m +CONFIG_IP_NF_ARP_MANGLE=m +CONFIG_IP_NF_COMPAT_IPCHAINS=m +CONFIG_IP_NF_NAT_NEEDED=y +CONFIG_IP_NF_COMPAT_IPFWADM=m +CONFIG_IP_NF_NAT_NEEDED=y +CONFIG_IPV6=m + +# +# IPv6: Netfilter Configuration +# +# CONFIG_IP6_NF_QUEUE is not set +CONFIG_IP6_NF_IPTABLES=m +CONFIG_IP6_NF_MATCH_LIMIT=m +CONFIG_IP6_NF_MATCH_MAC=m +CONFIG_IP6_NF_MATCH_RT=m +CONFIG_IP6_NF_MATCH_OPTS=m +CONFIG_IP6_NF_MATCH_FRAG=m +CONFIG_IP6_NF_MATCH_HL=m +CONFIG_IP6_NF_MATCH_MULTIPORT=m +CONFIG_IP6_NF_MATCH_OWNER=m +CONFIG_IP6_NF_MATCH_MARK=m +CONFIG_IP6_NF_MATCH_IPV6HEADER=m +CONFIG_IP6_NF_MATCH_AHESP=m +CONFIG_IP6_NF_MATCH_LENGTH=m +CONFIG_IP6_NF_MATCH_EUI64=m +CONFIG_IP6_NF_FILTER=m +CONFIG_IP6_NF_TARGET_LOG=m +CONFIG_IP6_NF_MANGLE=m +# CONFIG_IP6_NF_TARGET_MARK is not set +# CONFIG_KHTTPD is not set +CONFIG_ATM=m +CONFIG_ATM_CLIP=m +# CONFIG_ATM_CLIP_NO_ICMP is not set +CONFIG_ATM_LANE=m +CONFIG_ATM_MPOA=m +CONFIG_ATM_BR2684=m +CONFIG_ATM_BR2684_IPFILTER=y +CONFIG_VLAN_8021Q=m +CONFIG_IPX=m +# CONFIG_IPX_INTERN is not set +CONFIG_ATALK=m + +# +# Appletalk devices +# +CONFIG_DEV_APPLETALK=y +CONFIG_LTPC=m +CONFIG_COPS=m +CONFIG_COPS_DAYNA=y +CONFIG_COPS_TANGENT=y +CONFIG_IPDDP=m +CONFIG_IPDDP_ENCAP=y +CONFIG_IPDDP_DECAP=y +CONFIG_DECNET=m +CONFIG_DECNET_SIOCGIFCONF=y +CONFIG_DECNET_ROUTER=y +CONFIG_DECNET_ROUTE_FWMARK=y +CONFIG_BRIDGE=m +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_LLC is not set +CONFIG_NET_DIVERT=y +# CONFIG_ECONET is not set +CONFIG_WAN_ROUTER=m +# CONFIG_NET_FASTROUTE is not set +# CONFIG_NET_HW_FLOWCONTROL is not set + +# +# QoS and/or fair queueing +# +CONFIG_NET_SCHED=y +CONFIG_NET_SCH_CBQ=m +CONFIG_NET_SCH_HTB=m +CONFIG_NET_SCH_CSZ=m +# CONFIG_NET_SCH_ATM is not set +CONFIG_NET_SCH_PRIO=m +CONFIG_NET_SCH_RED=m +CONFIG_NET_SCH_SFQ=m +CONFIG_NET_SCH_TEQL=m +CONFIG_NET_SCH_TBF=m +CONFIG_NET_SCH_GRED=m +CONFIG_NET_SCH_DSMARK=m +CONFIG_NET_SCH_INGRESS=m +CONFIG_NET_QOS=y +CONFIG_NET_ESTIMATOR=y +CONFIG_NET_CLS=y +CONFIG_NET_CLS_TCINDEX=m +CONFIG_NET_CLS_ROUTE4=m +CONFIG_NET_CLS_ROUTE=y +CONFIG_NET_CLS_FW=m +CONFIG_NET_CLS_U32=m +CONFIG_NET_CLS_RSVP=m +CONFIG_NET_CLS_RSVP6=m +CONFIG_NET_CLS_POLICE=y + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set + +# +# Telephony Support +# +CONFIG_PHONE=m +CONFIG_PHONE_IXJ=m +CONFIG_PHONE_IXJ_PCMCIA=m + +# +# ATA/IDE/MFM/RLL support +# +CONFIG_IDE=y + +# +# IDE, ATA and ATAPI Block devices +# +CONFIG_BLK_DEV_IDE=y +# CONFIG_BLK_DEV_HD_IDE is not set +# CONFIG_BLK_DEV_HD is not set +CONFIG_BLK_DEV_IDEDISK=y +CONFIG_IDEDISK_MULTI_MODE=y +# CONFIG_IDEDISK_STROKE is not set +CONFIG_BLK_DEV_IDECS=m +CONFIG_BLK_DEV_IDECD=m +CONFIG_BLK_DEV_IDETAPE=m +CONFIG_BLK_DEV_IDEFLOPPY=y +CONFIG_BLK_DEV_IDESCSI=m +# CONFIG_IDE_TASK_IOCTL is not set +CONFIG_BLK_DEV_CMD640=y +# CONFIG_BLK_DEV_CMD640_ENHANCED is not set +# CONFIG_BLK_DEV_ISAPNP is not set +CONFIG_BLK_DEV_IDEPCI=y +CONFIG_BLK_DEV_GENERIC=y +CONFIG_IDEPCI_SHARE_IRQ=y +CONFIG_BLK_DEV_IDEDMA_PCI=y +# CONFIG_BLK_DEV_OFFBOARD is not set +# CONFIG_BLK_DEV_IDEDMA_FORCED is not set +CONFIG_IDEDMA_PCI_AUTO=y +# CONFIG_IDEDMA_ONLYDISK is not set +CONFIG_BLK_DEV_IDEDMA=y +# CONFIG_IDEDMA_PCI_WIP is not set +CONFIG_BLK_DEV_ADMA100=y +CONFIG_BLK_DEV_AEC62XX=y +CONFIG_BLK_DEV_ALI15X3=y +# CONFIG_WDC_ALI15X3 is not set +CONFIG_BLK_DEV_AMD74XX=y +# CONFIG_AMD74XX_OVERRIDE is not set +CONFIG_BLK_DEV_CMD64X=y +CONFIG_BLK_DEV_TRIFLEX=y +CONFIG_BLK_DEV_CY82C693=y +CONFIG_BLK_DEV_CS5530=y +CONFIG_BLK_DEV_HPT34X=y +# CONFIG_HPT34X_AUTODMA is not set +CONFIG_BLK_DEV_HPT366=y +CONFIG_BLK_DEV_PIIX=y +# CONFIG_BLK_DEV_NS87415 is not set +# CONFIG_BLK_DEV_OPTI621 is not set +CONFIG_BLK_DEV_PDC202XX_OLD=y +# CONFIG_PDC202XX_BURST is not set +CONFIG_BLK_DEV_PDC202XX_NEW=y +CONFIG_PDC202XX_FORCE=y +CONFIG_BLK_DEV_RZ1000=y +# CONFIG_BLK_DEV_SC1200 is not set +CONFIG_BLK_DEV_SVWKS=y +CONFIG_BLK_DEV_SIIMAGE=y +# CONFIG_BLK_DEV_SIS5513 is not set +# CONFIG_BLK_DEV_SLC90E66 is not set +# CONFIG_BLK_DEV_TRM290 is not set +# CONFIG_BLK_DEV_VIA82CXXX is not set +# CONFIG_IDE_CHIPSETS is not set +CONFIG_IDEDMA_AUTO=y +# CONFIG_IDEDMA_IVB is not set +# CONFIG_DMA_NONPCI is not set +CONFIG_BLK_DEV_PDC202XX=y +CONFIG_BLK_DEV_IDE_MODES=y +CONFIG_BLK_DEV_ATARAID=m +CONFIG_BLK_DEV_ATARAID_PDC=m +CONFIG_BLK_DEV_ATARAID_HPT=m +CONFIG_BLK_DEV_ATARAID_SII=m + +# +# SCSI support +# +CONFIG_SCSI=m +CONFIG_BLK_DEV_SD=m +CONFIG_SD_EXTRA_DEVS=40 +CONFIG_CHR_DEV_ST=m +CONFIG_CHR_DEV_OSST=m +CONFIG_BLK_DEV_SR=m +CONFIG_BLK_DEV_SR_VENDOR=y +CONFIG_SR_EXTRA_DEVS=2 +CONFIG_CHR_DEV_SG=m +# CONFIG_SCSI_DEBUG_QUEUES is not set +# CONFIG_SCSI_MULTI_LUN is not set +CONFIG_SCSI_CONSTANTS=y +CONFIG_SCSI_LOGGING=y + +# +# SCSI low-level drivers +# +CONFIG_BLK_DEV_3W_XXXX_RAID=m +CONFIG_SCSI_7000FASST=m +CONFIG_SCSI_ACARD=m +CONFIG_SCSI_AHA152X=m +CONFIG_SCSI_AHA1542=m +CONFIG_SCSI_AHA1740=m +CONFIG_SCSI_AACRAID=m +CONFIG_SCSI_AIC7XXX=m +CONFIG_AIC7XXX_CMDS_PER_DEVICE=253 +CONFIG_AIC7XXX_RESET_DELAY_MS=15000 +# CONFIG_AIC7XXX_PROBE_EISA_VL is not set +# CONFIG_AIC7XXX_BUILD_FIRMWARE is not set +# CONFIG_AIC7XXX_DEBUG_ENABLE is not set +CONFIG_AIC7XXX_DEBUG_MASK=0 +# CONFIG_AIC7XXX_REG_PRETTY_PRINT is not set +# CONFIG_SCSI_AIC79XX is not set +# CONFIG_SCSI_AIC7XXX_OLD is not set +CONFIG_SCSI_DPT_I2O=m +CONFIG_SCSI_ADVANSYS=m +CONFIG_SCSI_IN2000=m +CONFIG_SCSI_AM53C974=m +CONFIG_SCSI_MEGARAID=m +CONFIG_SCSI_BUSLOGIC=m +# CONFIG_SCSI_OMIT_FLASHPOINT is not set +CONFIG_SCSI_CPQFCTS=m +CONFIG_SCSI_DMX3191D=m +CONFIG_SCSI_DTC3280=m +CONFIG_SCSI_EATA=m +CONFIG_SCSI_EATA_TAGGED_QUEUE=y +# CONFIG_SCSI_EATA_LINKED_COMMANDS is not set +CONFIG_SCSI_EATA_MAX_TAGS=16 +CONFIG_SCSI_EATA_DMA=m +CONFIG_SCSI_EATA_PIO=m +CONFIG_SCSI_FUTURE_DOMAIN=m +CONFIG_SCSI_GDTH=m +CONFIG_SCSI_GENERIC_NCR5380=m +# CONFIG_SCSI_GENERIC_NCR53C400 is not set +CONFIG_SCSI_G_NCR5380_PORT=y +# CONFIG_SCSI_G_NCR5380_MEM is not set +CONFIG_SCSI_IPS=m +CONFIG_SCSI_INITIO=m +CONFIG_SCSI_INIA100=m +CONFIG_SCSI_PPA=m +CONFIG_SCSI_IMM=m +# CONFIG_SCSI_IZIP_EPP16 is not set +# CONFIG_SCSI_IZIP_SLOW_CTR is not set +CONFIG_SCSI_NCR53C406A=m +CONFIG_SCSI_NCR53C7xx=m +# CONFIG_SCSI_NCR53C7xx_sync is not set +CONFIG_SCSI_NCR53C7xx_FAST=y +CONFIG_SCSI_NCR53C7xx_DISCONNECT=y +CONFIG_SCSI_SYM53C8XX_2=m +CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=1 +CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16 +CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64 +# CONFIG_SCSI_SYM53C8XX_IOMAPPED is not set +CONFIG_SCSI_NCR53C8XX=m +CONFIG_SCSI_SYM53C8XX=m +CONFIG_SCSI_NCR53C8XX_DEFAULT_TAGS=8 +CONFIG_SCSI_NCR53C8XX_MAX_TAGS=32 +CONFIG_SCSI_NCR53C8XX_SYNC=20 +# CONFIG_SCSI_NCR53C8XX_PROFILE is not set +# CONFIG_SCSI_NCR53C8XX_IOMAPPED is not set +# CONFIG_SCSI_NCR53C8XX_PQS_PDS is not set +# CONFIG_SCSI_NCR53C8XX_SYMBIOS_COMPAT is not set +CONFIG_SCSI_PAS16=m +CONFIG_SCSI_PCI2000=m +CONFIG_SCSI_PCI2220I=m +CONFIG_SCSI_PSI240I=m +CONFIG_SCSI_QLOGIC_FAS=m +CONFIG_SCSI_QLOGIC_ISP=m +CONFIG_SCSI_QLOGIC_FC=m +# CONFIG_SCSI_QLOGIC_FC_FIRMWARE is not set +CONFIG_SCSI_QLOGIC_1280=m +CONFIG_SCSI_SEAGATE=m +CONFIG_SCSI_SIM710=m +CONFIG_SCSI_SYM53C416=m +CONFIG_SCSI_DC390T=m +# CONFIG_SCSI_DC390T_NOGENSUPP is not set +CONFIG_SCSI_T128=m +CONFIG_SCSI_U14_34F=m +# CONFIG_SCSI_U14_34F_LINKED_COMMANDS is not set +CONFIG_SCSI_U14_34F_MAX_TAGS=8 +CONFIG_SCSI_ULTRASTOR=m +CONFIG_SCSI_NSP32=m +CONFIG_SCSI_DEBUG=m + +# +# PCMCIA SCSI adapter support +# +CONFIG_SCSI_PCMCIA=y +CONFIG_PCMCIA_AHA152X=m +CONFIG_PCMCIA_FDOMAIN=m +CONFIG_PCMCIA_NINJA_SCSI=m +CONFIG_PCMCIA_QLOGIC=m + +# +# Fusion MPT device support +# +CONFIG_FUSION=m +# CONFIG_FUSION_BOOT is not set +CONFIG_FUSION_MAX_SGE=40 +# CONFIG_FUSION_ISENSE is not set +CONFIG_FUSION_CTL=m +CONFIG_FUSION_LAN=m +CONFIG_NET_FC=y + +# +# IEEE 1394 (FireWire) support (EXPERIMENTAL) +# +CONFIG_IEEE1394=m +# CONFIG_IEEE1394_PCILYNX is not set +CONFIG_IEEE1394_OHCI1394=m +CONFIG_IEEE1394_VIDEO1394=m +CONFIG_IEEE1394_SBP2=m +CONFIG_IEEE1394_SBP2_PHYS_DMA=y +CONFIG_IEEE1394_ETH1394=m +CONFIG_IEEE1394_DV1394=m +CONFIG_IEEE1394_RAWIO=m +CONFIG_IEEE1394_CMP=m +CONFIG_IEEE1394_AMDTP=m +# CONFIG_IEEE1394_VERBOSEDEBUG is not set +# CONFIG_IEEE1394_OUI_DB is not set + +# +# I2O device support +# +CONFIG_I2O=m +CONFIG_I2O_PCI=m +CONFIG_I2O_BLOCK=m +CONFIG_I2O_LAN=m +CONFIG_I2O_SCSI=m +CONFIG_I2O_PROC=m + +# +# Network device support +# +CONFIG_NETDEVICES=y + +# +# ARCnet devices +# +# CONFIG_ARCNET is not set +CONFIG_DUMMY=m +CONFIG_BONDING=m +CONFIG_EQUALIZER=m +CONFIG_TUN=m +CONFIG_ETHERTAP=m +CONFIG_NET_SB1000=m + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +# CONFIG_SUNLANCE is not set +CONFIG_HAPPYMEAL=m +# CONFIG_SUNBMAC is not set +# CONFIG_SUNQE is not set +CONFIG_SUNGEM=m +CONFIG_NET_VENDOR_3COM=y +CONFIG_EL1=m +CONFIG_EL2=m +CONFIG_ELPLUS=m +CONFIG_EL16=m +CONFIG_EL3=m +CONFIG_3C515=m +# CONFIG_ELMC is not set +# CONFIG_ELMC_II is not set +CONFIG_VORTEX=m +CONFIG_TYPHOON=m +CONFIG_LANCE=m +CONFIG_NET_VENDOR_SMC=y +CONFIG_WD80x3=m +# CONFIG_ULTRAMCA is not set +CONFIG_ULTRA=m +CONFIG_ULTRA32=m +CONFIG_SMC9194=m +CONFIG_NET_VENDOR_RACAL=y +CONFIG_NI5010=m +CONFIG_NI52=m +CONFIG_NI65=m +CONFIG_AT1700=m +CONFIG_DEPCA=m +CONFIG_HP100=m +CONFIG_NET_ISA=y +CONFIG_E2100=m +CONFIG_EWRK3=m +CONFIG_EEXPRESS=m +CONFIG_EEXPRESS_PRO=m +CONFIG_HPLAN_PLUS=m +CONFIG_HPLAN=m +CONFIG_LP486E=m +CONFIG_ETH16I=m +CONFIG_NE2000=m +CONFIG_NET_PCI=y +CONFIG_PCNET32=m +CONFIG_AMD8111_ETH=m +CONFIG_ADAPTEC_STARFIRE=m +CONFIG_AC3200=m +CONFIG_APRICOT=m +CONFIG_B44=m +CONFIG_CS89x0=m +CONFIG_TULIP=m +# CONFIG_TULIP_MWI is not set +CONFIG_TULIP_MMIO=y +CONFIG_DE4X5=m +CONFIG_DGRS=m +CONFIG_DM9102=m +CONFIG_EEPRO100=m +# CONFIG_EEPRO100_PIO is not set +CONFIG_E100=m +CONFIG_LNE390=m +CONFIG_FEALNX=m +CONFIG_NATSEMI=m +CONFIG_NE2K_PCI=m +CONFIG_NE3210=m +CONFIG_ES3210=m +CONFIG_8139CP=m +CONFIG_8139TOO=m +# CONFIG_8139TOO_PIO is not set +# CONFIG_8139TOO_TUNE_TWISTER is not set +CONFIG_8139TOO_8129=y +# CONFIG_8139_OLD_RX_RESET is not set +CONFIG_SIS900=m +CONFIG_EPIC100=m +CONFIG_SUNDANCE=m +# CONFIG_SUNDANCE_MMIO is not set +CONFIG_TLAN=m +CONFIG_VIA_RHINE=m +# CONFIG_VIA_RHINE_MMIO is not set +CONFIG_WINBOND_840=m +CONFIG_NET_POCKET=y +CONFIG_ATP=m +CONFIG_DE600=m +CONFIG_DE620=m + +# +# Ethernet (1000 Mbit) +# +CONFIG_ACENIC=m +# CONFIG_ACENIC_OMIT_TIGON_I is not set +CONFIG_DL2K=m +CONFIG_E1000=m +CONFIG_E1000_NAPI=y +# CONFIG_MYRI_SBUS is not set +CONFIG_NS83820=m +CONFIG_HAMACHI=m +CONFIG_YELLOWFIN=m +CONFIG_R8169=m +CONFIG_SK98LIN=m +CONFIG_TIGON3=m +CONFIG_FDDI=y +CONFIG_DEFXX=m +CONFIG_SKFP=m +# CONFIG_HIPPI is not set +CONFIG_PLIP=m +CONFIG_PPP=m +CONFIG_PPP_MULTILINK=y +CONFIG_PPP_FILTER=y +CONFIG_PPP_ASYNC=m +CONFIG_PPP_SYNC_TTY=m +CONFIG_PPP_DEFLATE=m +# CONFIG_PPP_BSDCOMP is not set +CONFIG_PPPOE=m +CONFIG_PPPOATM=m +CONFIG_SLIP=m +CONFIG_SLIP_COMPRESSED=y +CONFIG_SLIP_SMART=y +CONFIG_SLIP_MODE_SLIP6=y + +# +# Wireless LAN (non-hamradio) +# +CONFIG_NET_RADIO=y +CONFIG_STRIP=m +CONFIG_WAVELAN=m +CONFIG_ARLAN=m +CONFIG_AIRONET4500=m +CONFIG_AIRONET4500_NONCS=m +CONFIG_AIRONET4500_PNP=y +CONFIG_AIRONET4500_PCI=y +CONFIG_AIRONET4500_ISA=y +CONFIG_AIRONET4500_I365=y +CONFIG_AIRONET4500_PROC=m +CONFIG_AIRO=m +CONFIG_HERMES=m +CONFIG_PLX_HERMES=m +CONFIG_PCI_HERMES=m +CONFIG_PCMCIA_HERMES=m +CONFIG_AIRO_CS=m +CONFIG_NET_WIRELESS=y + +# +# Token Ring devices +# +CONFIG_TR=y +CONFIG_IBMTR=m +CONFIG_IBMOL=m +CONFIG_IBMLS=m +CONFIG_3C359=m +CONFIG_TMS380TR=m +CONFIG_TMSPCI=m +CONFIG_TMSISA=m +CONFIG_ABYSS=m +# CONFIG_MADGEMC is not set +CONFIG_SMCTR=m +CONFIG_NET_FC=y +CONFIG_IPHASE5526=m +CONFIG_RCPCI=m +CONFIG_SHAPER=m + +# +# Wan interfaces +# +CONFIG_WAN=y +CONFIG_HOSTESS_SV11=m +CONFIG_COSA=m +# CONFIG_COMX is not set +# CONFIG_DSCC4 is not set +# CONFIG_LANMEDIA is not set +CONFIG_ATI_XX20=m +CONFIG_SEALEVEL_4021=m +# CONFIG_SYNCLINK_SYNCPPP is not set +# CONFIG_HDLC is not set +CONFIG_DLCI=m +CONFIG_DLCI_COUNT=24 +CONFIG_DLCI_MAX=8 +CONFIG_SDLA=m +CONFIG_WAN_ROUTER_DRIVERS=y +CONFIG_VENDOR_SANGOMA=m +CONFIG_WANPIPE_CHDLC=y +CONFIG_WANPIPE_FR=y +CONFIG_WANPIPE_X25=y +CONFIG_WANPIPE_PPP=y +CONFIG_WANPIPE_MULTPPP=y +CONFIG_CYCLADES_SYNC=m +CONFIG_CYCLOMX_X25=y +# CONFIG_LAPBETHER is not set +# CONFIG_X25_ASY is not set +CONFIG_SBNI=m +CONFIG_SBNI_MULTILINE=y + +# +# PCMCIA network device support +# +CONFIG_NET_PCMCIA=y +CONFIG_PCMCIA_3C589=m +CONFIG_PCMCIA_3C574=m +CONFIG_PCMCIA_FMVJ18X=m +CONFIG_PCMCIA_PCNET=m +CONFIG_PCMCIA_AXNET=m +CONFIG_PCMCIA_NMCLAN=m +CONFIG_PCMCIA_SMC91C92=m +CONFIG_PCMCIA_XIRC2PS=m +# CONFIG_ARCNET_COM20020_CS is not set +CONFIG_PCMCIA_IBMTR=m +CONFIG_PCMCIA_XIRCOM=m +CONFIG_PCMCIA_XIRTULIP=m +CONFIG_NET_PCMCIA_RADIO=y +CONFIG_PCMCIA_RAYCS=m +CONFIG_PCMCIA_NETWAVE=m +CONFIG_PCMCIA_WAVELAN=m +CONFIG_AIRONET4500_CS=m + +# +# ATM drivers +# +# CONFIG_ATM_TCP is not set +CONFIG_ATM_LANAI=m +CONFIG_ATM_ENI=m +# CONFIG_ATM_ENI_DEBUG is not set +# CONFIG_ATM_ENI_TUNE_BURST is not set +CONFIG_ATM_FIRESTREAM=m +CONFIG_ATM_ZATM=m +# CONFIG_ATM_ZATM_DEBUG is not set +CONFIG_ATM_ZATM_EXACT_TS=y +CONFIG_ATM_NICSTAR=m +CONFIG_ATM_NICSTAR_USE_SUNI=y +CONFIG_ATM_NICSTAR_USE_IDT77105=y +CONFIG_ATM_IDT77252=m +# CONFIG_ATM_IDT77252_DEBUG is not set +# CONFIG_ATM_IDT77252_RCV_ALL is not set +CONFIG_ATM_IDT77252_USE_SUNI=y +CONFIG_ATM_AMBASSADOR=m +# CONFIG_ATM_AMBASSADOR_DEBUG is not set +CONFIG_ATM_HORIZON=m +# CONFIG_ATM_HORIZON_DEBUG is not set +CONFIG_ATM_IA=m +# CONFIG_ATM_IA_DEBUG is not set +CONFIG_ATM_FORE200E_MAYBE=m +CONFIG_ATM_FORE200E_PCA=y +CONFIG_ATM_FORE200E_PCA_DEFAULT_FW=y +CONFIG_ATM_FORE200E_TX_RETRY=16 +CONFIG_ATM_FORE200E_DEBUG=0 +CONFIG_ATM_FORE200E=m +CONFIG_ATM_HE=m +CONFIG_ATM_HE_USE_SUNI=y + +# +# Amateur Radio support +# +CONFIG_HAMRADIO=y +CONFIG_AX25=m +# CONFIG_AX25_DAMA_SLAVE is not set +CONFIG_NETROM=m +CONFIG_ROSE=m + +# +# AX.25 network device drivers +# +# CONFIG_MKISS is not set +# CONFIG_6PACK is not set +# CONFIG_BPQETHER is not set +# CONFIG_DMASCC is not set +# CONFIG_SCC is not set +# CONFIG_BAYCOM_SER_FDX is not set +# CONFIG_BAYCOM_SER_HDX is not set +# CONFIG_BAYCOM_PAR is not set +# CONFIG_BAYCOM_EPP is not set +CONFIG_SOUNDMODEM=m +CONFIG_SOUNDMODEM_SBC=y +CONFIG_SOUNDMODEM_WSS=y +CONFIG_SOUNDMODEM_AFSK1200=y +CONFIG_SOUNDMODEM_AFSK2400_7=y +CONFIG_SOUNDMODEM_AFSK2400_8=y +CONFIG_SOUNDMODEM_AFSK2666=y +CONFIG_SOUNDMODEM_HAPN4800=y +CONFIG_SOUNDMODEM_PSK4800=y +CONFIG_SOUNDMODEM_FSK9600=y +# CONFIG_YAM is not set + +# +# IrDA (infrared) support +# +CONFIG_IRDA=m +CONFIG_IRLAN=m +CONFIG_IRNET=m +CONFIG_IRCOMM=m +CONFIG_IRDA_ULTRA=y +CONFIG_IRDA_CACHE_LAST_LSAP=y +CONFIG_IRDA_FAST_RR=y +# CONFIG_IRDA_DEBUG is not set + +# +# Infrared-port device drivers +# +CONFIG_IRTTY_SIR=m +CONFIG_IRPORT_SIR=m +CONFIG_DONGLE=y +CONFIG_ESI_DONGLE=m +CONFIG_ACTISYS_DONGLE=m +CONFIG_TEKRAM_DONGLE=m +CONFIG_GIRBIL_DONGLE=m +CONFIG_LITELINK_DONGLE=m +CONFIG_MCP2120_DONGLE=m +CONFIG_OLD_BELKIN_DONGLE=m +CONFIG_ACT200L_DONGLE=m +CONFIG_MA600_DONGLE=m +CONFIG_USB_IRDA=m +CONFIG_NSC_FIR=m +CONFIG_WINBOND_FIR=m +CONFIG_TOSHIBA_OLD=m +CONFIG_TOSHIBA_FIR=m +CONFIG_SMC_IRCC_FIR=m +CONFIG_ALI_FIR=m +CONFIG_VLSI_FIR=m + +# +# ISDN subsystem +# +CONFIG_ISDN=m +CONFIG_ISDN_BOOL=y +CONFIG_ISDN_PPP=y +CONFIG_IPPP_FILTER=y +CONFIG_ISDN_PPP_VJ=y +CONFIG_ISDN_MPP=y +CONFIG_ISDN_PPP_BSDCOMP=m +CONFIG_ISDN_AUDIO=y +CONFIG_ISDN_TTY_FAX=y + +# +# ISDN feature submodules +# +CONFIG_ISDN_DRV_LOOP=m +# CONFIG_ISDN_DIVERSION is not set + +# +# Passive ISDN cards +# +CONFIG_ISDN_DRV_HISAX=m +CONFIG_ISDN_HISAX=y +CONFIG_HISAX_EURO=y +CONFIG_DE_AOC=y +# CONFIG_HISAX_NO_SENDCOMPLETE is not set +# CONFIG_HISAX_NO_LLC is not set +# CONFIG_HISAX_NO_KEYPAD is not set +CONFIG_HISAX_1TR6=y +CONFIG_HISAX_NI1=y +CONFIG_HISAX_MAX_CARDS=8 +CONFIG_HISAX_16_0=y +CONFIG_HISAX_16_3=y +CONFIG_HISAX_AVM_A1=y +CONFIG_HISAX_IX1MICROR2=y +CONFIG_HISAX_ASUSCOM=y +CONFIG_HISAX_TELEINT=y +CONFIG_HISAX_HFCS=y +CONFIG_HISAX_SPORTSTER=y +CONFIG_HISAX_MIC=y +CONFIG_HISAX_ISURF=y +CONFIG_HISAX_HSTSAPHIR=y +CONFIG_HISAX_TELESPCI=y +CONFIG_HISAX_S0BOX=y +CONFIG_HISAX_FRITZPCI=y +CONFIG_HISAX_AVM_A1_PCMCIA=y +CONFIG_HISAX_ELSA=y +CONFIG_HISAX_DIEHLDIVA=y +CONFIG_HISAX_SEDLBAUER=y +CONFIG_HISAX_NETJET=y +CONFIG_HISAX_NETJET_U=y +CONFIG_HISAX_NICCY=y +CONFIG_HISAX_BKM_A4T=y +CONFIG_HISAX_SCT_QUADRO=y +CONFIG_HISAX_GAZEL=y +CONFIG_HISAX_HFC_PCI=y +CONFIG_HISAX_W6692=y +CONFIG_HISAX_HFC_SX=y +CONFIG_HISAX_ENTERNOW_PCI=y +CONFIG_HISAX_DEBUG=y +CONFIG_HISAX_SEDLBAUER_CS=m +CONFIG_HISAX_ELSA_CS=m +CONFIG_HISAX_AVM_A1_CS=m +CONFIG_HISAX_ST5481=m +CONFIG_HISAX_FRITZ_PCIPNP=m +CONFIG_USB_AUERISDN=m + +# +# Active ISDN cards +# +CONFIG_ISDN_DRV_ICN=m +CONFIG_ISDN_DRV_PCBIT=m +# CONFIG_ISDN_DRV_SC is not set +# CONFIG_ISDN_DRV_ACT2000 is not set +CONFIG_ISDN_DRV_EICON=y +CONFIG_ISDN_DRV_EICON_DIVAS=m +# CONFIG_ISDN_DRV_EICON_OLD is not set +CONFIG_ISDN_DRV_TPAM=m +CONFIG_ISDN_CAPI=m +CONFIG_ISDN_DRV_AVMB1_VERBOSE_REASON=y +CONFIG_ISDN_CAPI_MIDDLEWARE=y +CONFIG_ISDN_CAPI_CAPI20=m +CONFIG_ISDN_CAPI_CAPIFS_BOOL=y +CONFIG_ISDN_CAPI_CAPIFS=m +CONFIG_ISDN_CAPI_CAPIDRV=m +CONFIG_ISDN_DRV_AVMB1_B1ISA=m +CONFIG_ISDN_DRV_AVMB1_B1PCI=m +CONFIG_ISDN_DRV_AVMB1_B1PCIV4=y +CONFIG_ISDN_DRV_AVMB1_T1ISA=m +CONFIG_ISDN_DRV_AVMB1_B1PCMCIA=m +CONFIG_ISDN_DRV_AVMB1_AVM_CS=m +CONFIG_ISDN_DRV_AVMB1_T1PCI=m +CONFIG_ISDN_DRV_AVMB1_C4=m +CONFIG_HYSDN=m +CONFIG_HYSDN_CAPI=y + +# +# Old CD-ROM drivers (not SCSI, not IDE) +# +# CONFIG_CD_NO_IDESCSI is not set + +# +# Input core support +# +CONFIG_INPUT=m +CONFIG_INPUT_KEYBDEV=m +CONFIG_INPUT_MOUSEDEV=m +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +CONFIG_INPUT_JOYDEV=m +CONFIG_INPUT_EVDEV=m + +# +# Character devices +# +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_SERIAL=y +CONFIG_SERIAL_CONSOLE=y +CONFIG_SERIAL_EXTENDED=y +CONFIG_SERIAL_MANY_PORTS=y +CONFIG_SERIAL_SHARE_IRQ=y +# CONFIG_SERIAL_DETECT_IRQ is not set +CONFIG_SERIAL_MULTIPORT=y +# CONFIG_HUB6 is not set +CONFIG_SERIAL_NONSTANDARD=y +CONFIG_COMPUTONE=m +CONFIG_ROCKETPORT=m +CONFIG_CYCLADES=m +# CONFIG_CYZ_INTR is not set +CONFIG_DIGIEPCA=m +CONFIG_ESPSERIAL=m +CONFIG_MOXA_INTELLIO=m +CONFIG_MOXA_SMARTIO=m +CONFIG_ISI=m +CONFIG_SYNCLINK=m +# CONFIG_SYNCLINKMP is not set +CONFIG_N_HDLC=m +CONFIG_RISCOM8=m +CONFIG_SPECIALIX=m +CONFIG_SPECIALIX_RTSCTS=y +CONFIG_SX=m +# CONFIG_RIO is not set +CONFIG_STALDRV=y +CONFIG_STALLION=m +CONFIG_ISTALLION=m +CONFIG_UNIX98_PTYS=y +CONFIG_UNIX98_PTY_COUNT=2048 +CONFIG_PRINTER=m +CONFIG_LP_CONSOLE=y +CONFIG_PPDEV=m +CONFIG_TIPAR=m + +# +# I2C support +# +CONFIG_I2C=m +CONFIG_I2C_ALGOBIT=m +CONFIG_I2C_PHILIPSPAR=m +CONFIG_I2C_ELV=m +CONFIG_I2C_VELLEMAN=m +# CONFIG_SCx200_I2C is not set +# CONFIG_SCx200_ACB is not set +CONFIG_I2C_ALGOPCF=m +CONFIG_I2C_ELEKTOR=m +CONFIG_I2C_CHARDEV=m +CONFIG_I2C_PROC=m + +# +# Mice +# +CONFIG_BUSMOUSE=m +CONFIG_ATIXL_BUSMOUSE=m +CONFIG_LOGIBUSMOUSE=m +CONFIG_MS_BUSMOUSE=m +CONFIG_MOUSE=y +CONFIG_PSMOUSE=y +CONFIG_82C710_MOUSE=m +CONFIG_PC110_PAD=m +CONFIG_MK712_MOUSE=m + +# +# Joysticks +# +CONFIG_INPUT_GAMEPORT=m +CONFIG_INPUT_NS558=m +CONFIG_INPUT_LIGHTNING=m +CONFIG_INPUT_PCIGAME=m +CONFIG_INPUT_CS461X=m +CONFIG_INPUT_EMU10K1=m +CONFIG_INPUT_SERIO=m +CONFIG_INPUT_SERPORT=m +CONFIG_INPUT_ANALOG=m +CONFIG_INPUT_A3D=m +CONFIG_INPUT_ADI=m +CONFIG_INPUT_COBRA=m +CONFIG_INPUT_GF2K=m +CONFIG_INPUT_GRIP=m +CONFIG_INPUT_INTERACT=m +CONFIG_INPUT_TMDC=m +CONFIG_INPUT_SIDEWINDER=m +CONFIG_INPUT_IFORCE_USB=m +CONFIG_INPUT_IFORCE_232=m +CONFIG_INPUT_WARRIOR=m +CONFIG_INPUT_MAGELLAN=m +CONFIG_INPUT_SPACEORB=m +CONFIG_INPUT_SPACEBALL=m +CONFIG_INPUT_STINGER=m +CONFIG_INPUT_DB9=m +CONFIG_INPUT_GAMECON=m +CONFIG_INPUT_TURBOGRAFX=m +# CONFIG_QIC02_TAPE is not set +CONFIG_IPMI_HANDLER=m +# CONFIG_IPMI_PANIC_EVENT is not set +CONFIG_IPMI_DEVICE_INTERFACE=m +CONFIG_IPMI_KCS=m +CONFIG_IPMI_WATCHDOG=m + +# +# Watchdog Cards +# +CONFIG_WATCHDOG=y +# CONFIG_WATCHDOG_NOWAYOUT is not set +CONFIG_ACQUIRE_WDT=m +CONFIG_ADVANTECH_WDT=m +CONFIG_ALIM1535_WDT=m +CONFIG_ALIM7101_WDT=m +CONFIG_SC520_WDT=m +CONFIG_PCWATCHDOG=m +CONFIG_EUROTECH_WDT=m +CONFIG_IB700_WDT=m +CONFIG_WAFER_WDT=m +CONFIG_I810_TCO=m +# CONFIG_MIXCOMWD is not set +# CONFIG_60XX_WDT is not set +CONFIG_SC1200_WDT=m +# CONFIG_SCx200_WDT is not set +CONFIG_SOFT_WATCHDOG=m +CONFIG_W83877F_WDT=m +CONFIG_WDT=m +CONFIG_WDTPCI=m +# CONFIG_WDT_501 is not set +CONFIG_MACHZ_WDT=m +CONFIG_AMD7XX_TCO=m +# CONFIG_SCx200_GPIO is not set +CONFIG_AMD_RNG=m +CONFIG_INTEL_RNG=m +CONFIG_AMD_PM768=m +CONFIG_NVRAM=m +CONFIG_RTC=y +CONFIG_DTLK=m +CONFIG_R3964=m +# CONFIG_APPLICOM is not set +CONFIG_SONYPI=m + +# +# Ftape, the floppy tape device driver +# +# CONFIG_FTAPE is not set +CONFIG_AGP=y +CONFIG_AGP_INTEL=y +CONFIG_AGP_I810=y +CONFIG_AGP_VIA=y +CONFIG_AGP_AMD=y +CONFIG_AGP_AMD_8151=y +CONFIG_AGP_SIS=y +CONFIG_AGP_ALI=y +CONFIG_AGP_SWORKS=y +CONFIG_AGP_NVIDIA=y +CONFIG_DRM=y +# CONFIG_DRM_OLD is not set +CONFIG_DRM_NEW=y +CONFIG_DRM_TDFX=m +CONFIG_DRM_R128=m +CONFIG_DRM_RADEON=m +CONFIG_DRM_I810=m +# CONFIG_DRM_I810_XFREE_41 is not set +CONFIG_DRM_I830=m +CONFIG_DRM_MGA=m +# CONFIG_DRM_SIS is not set + +# +# PCMCIA character devices +# +CONFIG_PCMCIA_SERIAL_CS=m +CONFIG_SYNCLINK_CS=m +CONFIG_MWAVE=m + +# +# Multimedia devices +# +CONFIG_VIDEO_DEV=m + +# +# Video For Linux +# +CONFIG_VIDEO_PROC_FS=y +CONFIG_I2C_PARPORT=m +CONFIG_VIDEO_BT848=m +CONFIG_VIDEO_PMS=m +CONFIG_VIDEO_BWQCAM=m +CONFIG_VIDEO_CQCAM=m +CONFIG_VIDEO_W9966=m +CONFIG_VIDEO_CPIA=m +CONFIG_VIDEO_CPIA_PP=m +CONFIG_VIDEO_CPIA_USB=m +CONFIG_VIDEO_SAA5249=m +CONFIG_TUNER_3036=m +CONFIG_VIDEO_STRADIS=m +CONFIG_VIDEO_ZORAN=m +CONFIG_VIDEO_ZORAN_BUZ=m +CONFIG_VIDEO_ZORAN_DC10=m +CONFIG_VIDEO_ZORAN_LML33=m +CONFIG_VIDEO_ZR36120=m +CONFIG_VIDEO_MEYE=m + +# +# Radio Adapters +# +CONFIG_RADIO_CADET=m +CONFIG_RADIO_RTRACK=m +CONFIG_RADIO_RTRACK2=m +CONFIG_RADIO_AZTECH=m +CONFIG_RADIO_GEMTEK=m +CONFIG_RADIO_GEMTEK_PCI=m +CONFIG_RADIO_MAXIRADIO=m +CONFIG_RADIO_MAESTRO=m +CONFIG_RADIO_MIROPCM20=m +CONFIG_RADIO_MIROPCM20_RDS=m +CONFIG_RADIO_SF16FMI=m +CONFIG_RADIO_SF16FMR2=m +CONFIG_RADIO_TERRATEC=m +CONFIG_RADIO_TRUST=m +CONFIG_RADIO_TYPHOON=m +CONFIG_RADIO_TYPHOON_PROC_FS=y +CONFIG_RADIO_ZOLTRIX=m + +# +# File systems +# +CONFIG_QUOTA=y +CONFIG_QFMT_V2=y +CONFIG_AUTOFS_FS=m +CONFIG_AUTOFS4_FS=m +CONFIG_REISERFS_FS=m +# CONFIG_REISERFS_CHECK is not set +CONFIG_REISERFS_PROC_INFO=y +# CONFIG_ADFS_FS is not set +# CONFIG_ADFS_FS_RW is not set +# CONFIG_AFFS_FS is not set +CONFIG_HFS_FS=m +# CONFIG_HFSPLUS_FS is not set +CONFIG_BEFS_FS=m +# CONFIG_BEFS_DEBUG is not set +CONFIG_BFS_FS=m +CONFIG_EXT3_FS=m +CONFIG_JBD=m +# CONFIG_JBD_DEBUG is not set +CONFIG_FAT_FS=m +CONFIG_MSDOS_FS=m +CONFIG_UMSDOS_FS=m +CONFIG_VFAT_FS=m +# CONFIG_EFS_FS is not set +# CONFIG_JFFS_FS is not set +# CONFIG_JFFS2_FS is not set +CONFIG_CRAMFS=m +CONFIG_TMPFS=y +CONFIG_RAMFS=y +CONFIG_ISO9660_FS=y +CONFIG_JOLIET=y +CONFIG_ZISOFS=y +CONFIG_JFS_FS=m +# CONFIG_JFS_DEBUG is not set +# CONFIG_JFS_STATISTICS is not set +CONFIG_MINIX_FS=m +CONFIG_VXFS_FS=m +# CONFIG_NTFS_FS is not set +# CONFIG_NTFS_RW is not set +# CONFIG_HPFS_FS is not set +CONFIG_PROC_FS=y +# CONFIG_DEVFS_FS is not set +# CONFIG_DEVFS_MOUNT is not set +# CONFIG_DEVFS_DEBUG is not set +CONFIG_DEVPTS_FS=y +# CONFIG_QNX4FS_FS is not set +# CONFIG_QNX4FS_RW is not set +CONFIG_ROMFS_FS=m +CONFIG_EXT2_FS=y +CONFIG_SYSV_FS=m +CONFIG_UDF_FS=m +CONFIG_UDF_RW=y +CONFIG_UFS_FS=m +# CONFIG_UFS_FS_WRITE is not set + +# +# Network File Systems +# +CONFIG_CODA_FS=m +CONFIG_INTERMEZZO_FS=m +CONFIG_NFS_FS=m +CONFIG_NFS_V3=y +# CONFIG_NFS_DIRECTIO is not set +# CONFIG_ROOT_NFS is not set +CONFIG_NFSD=m +CONFIG_NFSD_V3=y +CONFIG_NFSD_TCP=y +CONFIG_SUNRPC=m +CONFIG_LOCKD=m +CONFIG_LOCKD_V4=y +CONFIG_SMB_FS=m +# CONFIG_SMB_NLS_DEFAULT is not set +CONFIG_NCP_FS=m +# CONFIG_NCPFS_PACKET_SIGNING is not set +# CONFIG_NCPFS_IOCTL_LOCKING is not set +# CONFIG_NCPFS_STRONG is not set +# CONFIG_NCPFS_NFS_NS is not set +# CONFIG_NCPFS_OS2_NS is not set +# CONFIG_NCPFS_SMALLDOS is not set +# CONFIG_NCPFS_NLS is not set +# CONFIG_NCPFS_EXTRAS is not set +CONFIG_ZISOFS_FS=y + +# +# Partition Types +# +CONFIG_PARTITION_ADVANCED=y +# CONFIG_ACORN_PARTITION is not set +CONFIG_OSF_PARTITION=y +# CONFIG_AMIGA_PARTITION is not set +# CONFIG_ATARI_PARTITION is not set +CONFIG_MAC_PARTITION=y +CONFIG_MSDOS_PARTITION=y +CONFIG_BSD_DISKLABEL=y +CONFIG_MINIX_SUBPARTITION=y +CONFIG_SOLARIS_X86_PARTITION=y +CONFIG_UNIXWARE_DISKLABEL=y +# CONFIG_LDM_PARTITION is not set +CONFIG_SGI_PARTITION=y +# CONFIG_ULTRIX_PARTITION is not set +CONFIG_SUN_PARTITION=y +# CONFIG_EFI_PARTITION is not set +CONFIG_SMB_NLS=y +CONFIG_NLS=y + +# +# Native Language Support +# +CONFIG_NLS_DEFAULT="iso8859-1" +CONFIG_NLS_CODEPAGE_437=m +CONFIG_NLS_CODEPAGE_737=m +CONFIG_NLS_CODEPAGE_775=m +CONFIG_NLS_CODEPAGE_850=m +CONFIG_NLS_CODEPAGE_852=m +CONFIG_NLS_CODEPAGE_855=m +CONFIG_NLS_CODEPAGE_857=m +CONFIG_NLS_CODEPAGE_860=m +CONFIG_NLS_CODEPAGE_861=m +CONFIG_NLS_CODEPAGE_862=m +CONFIG_NLS_CODEPAGE_863=m +CONFIG_NLS_CODEPAGE_864=m +CONFIG_NLS_CODEPAGE_865=m +CONFIG_NLS_CODEPAGE_866=m +CONFIG_NLS_CODEPAGE_869=m +CONFIG_NLS_CODEPAGE_936=m +CONFIG_NLS_CODEPAGE_950=m +CONFIG_NLS_CODEPAGE_932=m +CONFIG_NLS_CODEPAGE_949=m +CONFIG_NLS_CODEPAGE_874=m +CONFIG_NLS_ISO8859_8=m +CONFIG_NLS_CODEPAGE_1250=m +CONFIG_NLS_CODEPAGE_1251=m +CONFIG_NLS_ISO8859_1=m +CONFIG_NLS_ISO8859_2=m +CONFIG_NLS_ISO8859_3=m +CONFIG_NLS_ISO8859_4=m +CONFIG_NLS_ISO8859_5=m +CONFIG_NLS_ISO8859_6=m +CONFIG_NLS_ISO8859_7=m +CONFIG_NLS_ISO8859_9=m +CONFIG_NLS_ISO8859_13=m +CONFIG_NLS_ISO8859_14=m +CONFIG_NLS_ISO8859_15=m +CONFIG_NLS_KOI8_R=m +CONFIG_NLS_KOI8_U=m +CONFIG_NLS_UTF8=m + +# +# Console drivers +# +CONFIG_VGA_CONSOLE=y +CONFIG_VIDEO_SELECT=y +CONFIG_MDA_CONSOLE=m + +# +# Frame-buffer support +# +CONFIG_FB=y +CONFIG_DUMMY_CONSOLE=y +CONFIG_FB_RIVA=m +CONFIG_FB_CLGEN=m +CONFIG_FB_PM2=m +# CONFIG_FB_PM2_FIFO_DISCONNECT is not set +CONFIG_FB_PM2_PCI=y +CONFIG_FB_PM3=m +# CONFIG_FB_CYBER2000 is not set +CONFIG_FB_VESA=y +CONFIG_FB_VGA16=m +CONFIG_FB_HGA=m +CONFIG_VIDEO_SELECT=y +CONFIG_FB_MATROX=m +CONFIG_FB_MATROX_MILLENIUM=y +CONFIG_FB_MATROX_MYSTIQUE=y +# CONFIG_FB_MATROX_G450 is not set +CONFIG_FB_MATROX_G100A=y +CONFIG_FB_MATROX_G100=y +CONFIG_FB_MATROX_I2C=m +# CONFIG_FB_MATROX_MAVEN is not set +# CONFIG_FB_MATROX_PROC is not set +CONFIG_FB_MATROX_MULTIHEAD=y +CONFIG_FB_ATY=m +CONFIG_FB_ATY_GX=y +CONFIG_FB_ATY_CT=y +CONFIG_FB_RADEON=m +CONFIG_FB_ATY128=m +# CONFIG_FB_INTEL is not set +CONFIG_FB_SIS=m +CONFIG_FB_SIS_300=y +CONFIG_FB_SIS_315=y +CONFIG_FB_NEOMAGIC=m +CONFIG_FB_3DFX=m +CONFIG_FB_VOODOO1=m +# CONFIG_FB_TRIDENT is not set +# CONFIG_FB_VIRTUAL is not set +# CONFIG_FBCON_ADVANCED is not set +CONFIG_FBCON_MFB=m +CONFIG_FBCON_CFB8=y +CONFIG_FBCON_CFB16=y +CONFIG_FBCON_CFB24=y +CONFIG_FBCON_CFB32=y +CONFIG_FBCON_VGA_PLANES=m +CONFIG_FBCON_HGA=m +# CONFIG_FBCON_FONTWIDTH8_ONLY is not set +# CONFIG_FBCON_FONTS is not set +CONFIG_FONT_8x8=y +CONFIG_FONT_8x16=y + +# +# Sound +# +CONFIG_SOUND=m +CONFIG_SOUND_ALI5455=m +CONFIG_SOUND_BT878=m +CONFIG_SOUND_CMPCI=m +CONFIG_SOUND_CMPCI_FM=y +CONFIG_SOUND_CMPCI_FMIO=388 +CONFIG_SOUND_CMPCI_FMIO=388 +CONFIG_SOUND_CMPCI_MIDI=y +CONFIG_SOUND_CMPCI_MPUIO=330 +CONFIG_SOUND_CMPCI_JOYSTICK=y +CONFIG_SOUND_CMPCI_CM8738=y +# CONFIG_SOUND_CMPCI_SPDIFINVERSE is not set +CONFIG_SOUND_CMPCI_SPDIFLOOP=y +CONFIG_SOUND_CMPCI_SPEAKERS=2 +CONFIG_SOUND_EMU10K1=m +CONFIG_MIDI_EMU10K1=y +CONFIG_SOUND_FUSION=m +CONFIG_SOUND_CS4281=m +CONFIG_SOUND_ES1370=m +CONFIG_SOUND_ES1371=m +CONFIG_SOUND_ESSSOLO1=m +CONFIG_SOUND_MAESTRO=m +CONFIG_SOUND_MAESTRO3=m +CONFIG_SOUND_FORTE=m +CONFIG_SOUND_ICH=m +CONFIG_SOUND_RME96XX=m +CONFIG_SOUND_SONICVIBES=m +CONFIG_SOUND_TRIDENT=m +CONFIG_SOUND_MSNDCLAS=m +# CONFIG_MSNDCLAS_HAVE_BOOT is not set +CONFIG_MSNDCLAS_INIT_FILE="/etc/sound/msndinit.bin" +CONFIG_MSNDCLAS_PERM_FILE="/etc/sound/msndperm.bin" +CONFIG_SOUND_MSNDPIN=m +# CONFIG_MSNDPIN_HAVE_BOOT is not set +CONFIG_MSNDPIN_INIT_FILE="/etc/sound/pndspini.bin" +CONFIG_MSNDPIN_PERM_FILE="/etc/sound/pndsperm.bin" +CONFIG_SOUND_VIA82CXXX=m +CONFIG_MIDI_VIA82CXXX=y +CONFIG_SOUND_OSS=m +# CONFIG_SOUND_TRACEINIT is not set +CONFIG_SOUND_DMAP=y +CONFIG_SOUND_AD1816=m +CONFIG_SOUND_AD1889=m +CONFIG_SOUND_SGALAXY=m +CONFIG_SOUND_ADLIB=m +CONFIG_SOUND_ACI_MIXER=m +CONFIG_SOUND_CS4232=m +CONFIG_SOUND_SSCAPE=m +CONFIG_SOUND_GUS=m +CONFIG_SOUND_GUS16=y +CONFIG_SOUND_GUSMAX=y +CONFIG_SOUND_VMIDI=m +CONFIG_SOUND_TRIX=m +CONFIG_SOUND_MSS=m +CONFIG_SOUND_MPU401=m +CONFIG_SOUND_NM256=m +CONFIG_SOUND_MAD16=m +CONFIG_MAD16_OLDCARD=y +CONFIG_SOUND_PAS=m +# CONFIG_PAS_JOYSTICK is not set +CONFIG_SOUND_PSS=m +# CONFIG_PSS_MIXER is not set +# CONFIG_PSS_HAVE_BOOT is not set +CONFIG_SOUND_SB=m +CONFIG_SOUND_AWE32_SYNTH=m +CONFIG_SOUND_KAHLUA=m +CONFIG_SOUND_WAVEFRONT=m +CONFIG_SOUND_MAUI=m +CONFIG_SOUND_YM3812=m +CONFIG_SOUND_OPL3SA1=m +CONFIG_SOUND_OPL3SA2=m +CONFIG_SOUND_YMFPCI=m +CONFIG_SOUND_YMFPCI_LEGACY=y +# CONFIG_SOUND_UART6850 is not set +CONFIG_SOUND_AEDSP16=m +CONFIG_SC6600=y +CONFIG_SC6600_JOY=y +CONFIG_SC6600_CDROM=4 +CONFIG_SC6600_CDROMBASE=0 +CONFIG_AEDSP16_SBPRO=y +CONFIG_AEDSP16_MPU401=y +CONFIG_SOUND_TVMIXER=m + +# +# USB support +# +CONFIG_USB=m +# CONFIG_USB_DEBUG is not set +CONFIG_USB_DEVICEFS=y +# CONFIG_USB_BANDWIDTH is not set +CONFIG_USB_EHCI_HCD=m +# CONFIG_USB_UHCI is not set +CONFIG_USB_UHCI_ALT=m +CONFIG_USB_OHCI=m +CONFIG_USB_AUDIO=m +# CONFIG_USB_EMI26 is not set +CONFIG_USB_MIDI=m +CONFIG_USB_STORAGE=m +# CONFIG_USB_STORAGE_DEBUG is not set +CONFIG_USB_STORAGE_DATAFAB=y +CONFIG_USB_STORAGE_FREECOM=y +CONFIG_USB_STORAGE_ISD200=y +CONFIG_USB_STORAGE_DPCM=y +CONFIG_USB_STORAGE_HP8200e=y +CONFIG_USB_STORAGE_SDDR09=y +CONFIG_USB_STORAGE_SDDR55=y +CONFIG_USB_STORAGE_JUMPSHOT=y +CONFIG_USB_ACM=m +CONFIG_USB_PRINTER=m +CONFIG_USB_HID=m +CONFIG_USB_HIDINPUT=y +CONFIG_USB_HIDDEV=y +# CONFIG_USB_KBD is not set +# CONFIG_USB_MOUSE is not set +CONFIG_USB_AIPTEK=m +CONFIG_USB_WACOM=m +CONFIG_USB_KBTAB=m +CONFIG_USB_POWERMATE=m +# CONFIG_USB_DC2XX is not set +CONFIG_USB_MDC800=m +CONFIG_USB_SCANNER=m +CONFIG_USB_MICROTEK=m +CONFIG_USB_HPUSBSCSI=m +CONFIG_USB_IBMCAM=m +CONFIG_USB_KONICAWC=m +CONFIG_USB_OV511=m +CONFIG_USB_PWC=m +CONFIG_USB_SE401=m +CONFIG_USB_STV680=m +CONFIG_USB_VICAM=m +CONFIG_USB_DSBR=m +CONFIG_USB_DABUSB=m +CONFIG_USB_PEGASUS=m +CONFIG_USB_RTL8150=m +CONFIG_USB_KAWETH=m +CONFIG_USB_CATC=m +CONFIG_USB_AX8817X=m +CONFIG_USB_CDCETHER=m +CONFIG_USB_USBNET=m +CONFIG_USB_USS720=m + +# +# USB Serial Converter support +# +CONFIG_USB_SERIAL=m +# CONFIG_USB_SERIAL_DEBUG is not set +CONFIG_USB_SERIAL_GENERIC=y +CONFIG_USB_SERIAL_BELKIN=m +CONFIG_USB_SERIAL_WHITEHEAT=m +CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m +CONFIG_USB_SERIAL_EMPEG=m +CONFIG_USB_SERIAL_FTDI_SIO=m +CONFIG_USB_SERIAL_VISOR=m +CONFIG_USB_SERIAL_IPAQ=m +CONFIG_USB_SERIAL_IR=m +CONFIG_USB_SERIAL_EDGEPORT=m +CONFIG_USB_SERIAL_EDGEPORT_TI=m +CONFIG_USB_SERIAL_KEYSPAN_PDA=m +CONFIG_USB_SERIAL_KEYSPAN=m +# CONFIG_USB_SERIAL_KEYSPAN_USA28 is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA28X is not set +CONFIG_USB_SERIAL_KEYSPAN_USA28XA=y +CONFIG_USB_SERIAL_KEYSPAN_USA28XB=y +# CONFIG_USB_SERIAL_KEYSPAN_USA19 is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA18X is not set +CONFIG_USB_SERIAL_KEYSPAN_USA19W=y +CONFIG_USB_SERIAL_KEYSPAN_USA19QW=y +CONFIG_USB_SERIAL_KEYSPAN_USA19QI=y +CONFIG_USB_SERIAL_KEYSPAN_MPR=y +CONFIG_USB_SERIAL_KEYSPAN_USA49W=y +CONFIG_USB_SERIAL_KEYSPAN_USA49WLC=y +CONFIG_USB_SERIAL_MCT_U232=m +CONFIG_USB_SERIAL_KLSI=m +CONFIG_USB_SERIAL_KOBIL_SCT=m +CONFIG_USB_SERIAL_PL2303=m +CONFIG_USB_SERIAL_CYBERJACK=m +CONFIG_USB_SERIAL_XIRCOM=m +CONFIG_USB_SERIAL_OMNINET=m +CONFIG_USB_RIO500=m +CONFIG_USB_AUERSWALD=m +CONFIG_USB_TIGL=m +CONFIG_USB_BRLVGER=m +CONFIG_USB_LCD=m +CONFIG_USB_SPEEDTOUCH=m + +# +# Bluetooth support +# +CONFIG_BLUEZ=m +CONFIG_BLUEZ_L2CAP=m +CONFIG_BLUEZ_SCO=m +CONFIG_BLUEZ_RFCOMM=m +CONFIG_BLUEZ_RFCOMM_TTY=y +CONFIG_BLUEZ_BNEP=m +CONFIG_BLUEZ_BNEP_MC_FILTER=y +CONFIG_BLUEZ_BNEP_PROTO_FILTER=y +# CONFIG_BLUEZ_CMTP is not set + +# +# Bluetooth device drivers +# +CONFIG_BLUEZ_HCIUSB=m +CONFIG_BLUEZ_USB_SCO=y +CONFIG_BLUEZ_USB_ZERO_PACKET=y +CONFIG_BLUEZ_HCIUART=m +CONFIG_BLUEZ_HCIUART_H4=y +CONFIG_BLUEZ_HCIUART_BCSP=y +# CONFIG_BLUEZ_HCIUART_BCSP_TXCRC is not set +# CONFIG_BLUEZ_HCIBFUSB is not set +CONFIG_BLUEZ_HCIDTL1=m +CONFIG_BLUEZ_HCIBT3C=m +CONFIG_BLUEZ_HCIBLUECARD=m +CONFIG_BLUEZ_HCIBTUART=m +CONFIG_BLUEZ_HCIVHCI=m + +# +# Kernel hacking +# +CONFIG_DEBUG_KERNEL=y +CONFIG_DEBUG_STACKOVERFLOW=y +# CONFIG_DEBUG_HIGHMEM is not set +# CONFIG_DEBUG_SLAB is not set +# CONFIG_DEBUG_IOVIRT is not set +CONFIG_MAGIC_SYSRQ=y +# CONFIG_DEBUG_SPINLOCK is not set +# CONFIG_FRAME_POINTER is not set + +# +# Cryptographic options +# +# CONFIG_CRYPTO is not set + +# +# Library routines +# +# CONFIG_CRC32 is not set +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=m diff --git a/Makerules/template.dsp b/Makerules/template.dsp new file mode 100755 index 0000000..4e9598a --- /dev/null +++ b/Makerules/template.dsp @@ -0,0 +1,108 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** +# Microsoft Developer Studio Project File - Name="ProjectTemplate" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) External Target" 0x0106 + +CFG=ProjectTemplate - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "ProjectTemplate.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "ProjectTemplate.mak" CFG="ProjectTemplate - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "ProjectTemplate - Win32 Release" (based on "Win32 (x86) External Target") +!MESSAGE "ProjectTemplate - Win32 Debug" (based on "Win32 (x86) External Target") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +!MESSAGE disabled PROP Scc_ProjName "ProjectTemplate" +!MESSAGE disabled PROP Scc_LocalPath "." + +!IF "$(CFG)" == "ProjectTemplate - Win32 Release" + +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Cmd_Line "NMAKE /f ProjectTemplate.mak" +# PROP BASE Rebuild_Opt "/a" +# PROP BASE Target_File "ProjectTemplate.exe" +# PROP BASE Bsc_Name "ProjectTemplate.bsc" +# PROP BASE Target_Dir "" +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "" +# PROP Intermediate_Dir "" +# PROP Cmd_Line "ProjectMake "BUILD_CONFIG=release"" +# PROP Rebuild_Opt "clobber stage" +# PROP Target_File "ProjectExecute" +# PROP Bsc_Name "ProjectTemplate.bsc" +# PROP Target_Dir "" + +!ELSEIF "$(CFG)" == "ProjectTemplate - Win32 Debug" + +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Cmd_Line "NMAKE /f ProjectTemplate.mak" +# PROP BASE Rebuild_Opt "/a" +# PROP BASE Target_File "ProjectTemplate.exe" +# PROP BASE Bsc_Name "ProjectTemplate.bsc" +# PROP BASE Target_Dir "" +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "" +# PROP Intermediate_Dir "" +# PROP Cmd_Line "ProjectMake "BUILD_CONFIG=debug"" +# PROP Rebuild_Opt "clobber stage" +# PROP Target_File "ProjectExecute" +# PROP Bsc_Name "ProjectTemplate.bsc" +# PROP Target_Dir "" + +!ENDIF + +# Begin Target + +# Name "ProjectTemplate - Win32 Release" +# Name "ProjectTemplate - Win32 Debug" + +!IF "$(CFG)" == "ProjectTemplate - Win32 Release" + +!ELSEIF "$(CFG)" == "ProjectTemplate - Win32 Debug" + +!ENDIF + + diff --git a/Moab/Makefile b/Moab/Makefile new file mode 100644 index 0000000..7b19009 --- /dev/null +++ b/Moab/Makefile @@ -0,0 +1,162 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** +# Makefile for xedge_swreset + +# Include Make Control Settings +include $(TL_DIR)/$(PROJ_FILE_DIR)/Makesettings.project + +#=============================================================================# +# Definitions: +#-----------------------------------------------------------------------------# + +# Name of SubProjects +DS_SUBPROJECTS = +# name of executable or downloadable image +EXECUTABLE = +# list of sub directories to build +DIRS = +# C files (.c) +CFILES = \ + # Add more c files here +# C++ files (.cpp) +CCFILES = \ + # Add more cpp files here +# lex files (.lex) +LFILES = \ + # Add more lex files here +# archive library files (basename, $ARFILES will add MOD_LIB_DIR/prefix and suffix) +LIBFILES= +# Windows Resource Files (.rc) +RSCFILES = +# Windows IDL File (.idl) +IDLFILE = +# Windows Linker Module Definitions (.def) file for dll's +DEFFILE = +# targets to build during INCLUDES phase (add public includes here) +INCLUDE_TARGETS = \ + # Add more h hpp files here +# Non-compiled files + # Add more files here +MISC_FILES = \ + moab.submit.mvapich2.job \ + moab.submit.mvapich.job \ + moab.submit.openmpi.job \ + moab.mpi.job.wrapper \ + iba_select_mpi \ + README +# all source files +SOURCES = $(CFILES) $(CCFILES) $(LFILES) $(RSCFILES) $(IDLFILE) +# Source files to include in DSP File +DSP_SOURCES = $(INCLUDE_TARGETS) $(SOURCES) $(MISC_FILES) \ + $(RSCFILES) $(DEFFILE) $(MAKEFILE) +# all object files +OBJECTS = $(CFILES:.c=$(OBJ_SUFFIX)) $(CCFILES:.cpp=$(OBJ_SUFFIX)) \ + $(LFILES:.lex=$(OBJ_SUFFIX)) +RSCOBJECTS = $(RSCFILES:.rc=$(RES_SUFFIX)) +# targets to build during LIBS phase +LIB_TARGETS_IMPLIB = +LIB_TARGETS_ARLIB = # $(LIB_PREFIX)ResourceTest$(ARLIB_SUFFIX) +LIB_TARGETS_EXP = $(LIB_TARGETS_IMPLIB:$(ARLIB_SUFFIX)=$(EXP_SUFFIX)) +LIB_TARGETS_MISC = +# targets to build during CMDS phase +CMD_TARGETS_SHLIB = +CMD_TARGETS_EXE = $(EXECUTABLE) +CMD_TARGETS_MISC = +# files to remove during clean phase +CLEAN_TARGETS_MISC = +CLEAN_TARGETS = $(OBJECTS) $(RSCOBJECTS) $(IDL_TARGETS) $(CLEAN_TARGETS_MISC) +# other files to remove during clobber phase +CLOBBER_TARGETS_MISC= +# sub-directory to install to within bin +BIN_SUBDIR = +# sub-directory to install to within include +INCLUDE_SUBDIR = + +# Additional Settings +#CLOCALDEBUG = User defined C debugging compilation flags [Empty] +#CCLOCALDEBUG = User defined C++ debugging compilation flags [Empty] +#CLOCAL = User defined C flags for compiling [Empty] +#CCLOCAL = User defined C++ flags for compiling [Empty] +#BSCLOCAL = User flags for Browse File Builder [Empty] +#DEPENDLOCAL = user defined makedepend flags [Empty] +#LINTLOCAL = User defined lint flags [Empty] +#LOCAL_INCLUDE_DIRS = User include directories to search for C/C++ headers [Empty] +#LDLOCAL = User defined C flags for linking [Empty] +#IMPLIBLOCAL = User flags for Object Lirary Manager [Empty] +#MIDLLOCAL = User flags for IDL compiler [Empty] +#RSCLOCAL = User flags for resource compiler [Empty] +#LOCALDEPLIBS = User libraries to include in dependencies [Empty] +#LOCALLIBS = User libraries to use when linking [Empty] +# (in addition to LOCALDEPLIBS) +#LOCAL_LIB_DIRS = User library directories for libpaths [Empty] + +LOCALDEPLIBS=$(IBACCESS_USER_LIBS) xedge_common opamgt-priv Md5 +LOCAL_INCLUDE_DIRS= +LOCALLIBS=$(OPENIB_USER_LIBS) +LOCAL_LIB_DIRS=$(OPENIB_USER_LIB_DIRS) $(IBACCESS_USER_LIB_DIRS) + +# Include Make Rules definitions and rules +include $(TL_DIR)/IbaTools/Makerules.module + +#=============================================================================# +# Overrides: +#-----------------------------------------------------------------------------# +#CCOPT = # C++ optimization flags, default lets build config decide +#COPT = # C optimization flags, default lets build config decide +#SUBSYSTEM = Subsystem to build for (none, console or windows) [none] +# (Windows Only) +#USEMFC = How Windows MFC should be used (none, static, shared, no_mfc) [none] +# (Windows Only) +#=============================================================================# + +#=============================================================================# +# Rules: +#-----------------------------------------------------------------------------# +# process Sub-directories +include $(TL_DIR)/Makerules/Maketargets.toplevel + +# build cmds and libs +include $(TL_DIR)/Makerules/Maketargets.build + +# install for includes, libs and cmds phases +include $(TL_DIR)/Makerules/Maketargets.install + +# install for stage phase +include $(TL_DIR)/Makerules/Maketargets.stage +STAGE:: + $(VS)$(STAGE_INSTALL) $(STAGE_INSTALL_DIR_OPT) $(PROJ_STAGE_MOAB_DIR) $(MISC_FILES) + +# Unit test execution +#include $(TL_DIR)/Makerules/Maketargets.runtest + +#=============================================================================# + +#=============================================================================# +# DO NOT DELETE THIS LINE -- make depend depends on it. +#=============================================================================# diff --git a/Moab/README b/Moab/README new file mode 100644 index 0000000..bde2f42 --- /dev/null +++ b/Moab/README @@ -0,0 +1,141 @@ +Copyright (c) 2015, Intel Corporation +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: +- Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. +- Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. +- Neither the name of Intel Corporation nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL INTEL, THE COPYRIGHT OWNER OR CONTRIBUTORS +BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. + +EXPORT LAWS: THIS LICENSE ADDS NO RESTRICTIONS TO THE EXPORT LAWS OF YOUR +JURISDICTION. It is licensee's responsibility to comply with any export +regulations applicable in licensee's jurisdiction. Under CURRENT (May 2000) +U.S. export regulations this software is eligible for export from the U.S. +and can be downloaded by or otherwise exported or reexported worldwide EXCEPT +to U.S. embargoed destinations which include Cuba, Iraq, Libya, North Korea, +Iran, Syria, Sudan, Afghanistan and any other country to which the U.S. has +embargoed goods and services. + +[ICS VERSION STRING: unknown] + +README for Moab scripts directory +--------------------------------- + +This directory contains: + +* Three scripts for submitting Moab jobs, one each for OpenMPI, mvapich, and mvapich2 +* A helper script that is used by the three previously mentioned scripts +* This file + + + +Virtual Fabric integration with Moab +------------------------------------ + +The sole intent of the Moab scripts is to act as templates for the administrator, on how to enable +Moab to take advantage of Virtual Fabric (vFabric) functionality. In order to make these scripts +accessible to common users, the administrator must do the following: + + 1. (Optional) If necessary, edit the scripts to meet the configuration and usage criteria + requirements specific to your Moab environment. + 2. Copy the scripts to a shared file system service that provides the appropriate access rights + for common users. + +In order for Moab to take advantage of vFabric functionality, vFabric must be integrated with Moab. +There are several integration methods that could be used, these scripts use the method of Moab based +queues. This method requires that the administrator perform the following steps (for detailed +information on vFabric, reference "Fabric Manager Users Guide"): + + 1. For both Moab and the Resource Manager(s), create a queue for each vFabric defined within the + FM configuration file (/etc/sysconfig/ifs_fm.xml). + 2. Configure each vFabric queue defined within Moab with the compute nodes assigned to it within + the FM configuration file. + 3. (Optional) Configure each vFabric queue defined within Moab with the priorities, policies, QoS, + and attributes that are specific to the needs of the organization and fabric environment. + +Note, depending on the queue support requirements of a Resource Manager, steps 2 and 3 may also have + to be performed upon that Resource Manager (TORQUE does not require these two steps). + + + +Moab Submit Scripts +------------------- + +Moab submit scripts utilize the Moab primitive "msub", encapsulating the arguments and call structure +for ease-of-use. They query the SA for information regarding virtual fabrics, or in the case of PSM +with dist_sa, pass the appropriate arguments to PSM for SA lookup. + +The submit scripts default the MPICH_PREFIX if it is not set in the environment. The openmpi, mvapich +and mvapich2 scripts default to the -qlc versions of MPI. + +The submit scripts utilize a helper script called "moab.mpi.job.wrapper". This helper script is used +to dynamically generate a hosts file required for MPI. This host file is a list of hosts to run MPI +on. The host file created is called ".mpi_hosts_file." and is created in the work directory +on the primary node executing the job. Note, the Moab scripts DO NOT delete the host file; therefore, +clean up of these temporary host files is the responsibility of the user. + + +Here are some examples of how to call the scripts and pass vFabric parameters (Note, these examples +utilize the proprietary MPI applications, which are located in the /usr/src/opa/mpi_apps/ +directory. These MPI applications were provided specifically for administrative use only): + + +Example 1: + + moab.submit.openmpi.job -p 2 -V vf_name -n Compute -d 3 osu2/osu_bibw + +This submits a job with the openmpi-qlc subsystem, i.e. the run file osu_bibw is expected to have been +compiled with the openmpi-qlc compiler under gcc. The number of processes is given as 2, and the virtual +fabric to use is identified by name, and that name is "Compute". Option 3 is given to denote a +dispersive routing option of static_dest. + +Example 2: + + moab.submit.openmpi.job -p 2 -V sid -s 0x0000000000000022 -d 1 osu2/osu_bibw + +This submits a job with the openmpi-qlc subsystem, i.e. the run file osu_bibw is expected to have been +compiled with the openmpi-qlc compiler under gcc. The number of processes is given as 2, and the virtual +fabric to use is identified by service id, and that id is "0x0000000000000022". Option 3 is given +to denote a dispersive routing option of adaptive. + +Example 3: + + moab.submit.openmpi.job -p 2 -V sid_qlc -s 0x1000117500000000 -q night osu2/osu_bibw + +This submits a job with the openmpi-qlc subsystem, i.e. the run file osu_bibw is expected to have been +compiled with the openmpi-qlc compiler under gcc. The number of processes is given as 2. The virtual fabric +to use is identified by service id, and that id is "0x1000117500000000"; it will be passed to the QIB driver +which will perform the vFabric lookup on behalf of the job. No dispersive routing instructions are given. +The job is being requested for submission via the "night" Moab queue. + + + +Moab Script Administration +-------------------------- + +The scripts are intended to be tailored by the Moab administrator in order to structure the msub +parameters appropriately. Any parameters, such as queue name, application profile, work directory, etc. may +be inserted into the script either using script options, accessing environment variables, or by hardcoding. + +Additionally, the scripts use mpirun_rsh or mpirun to start MPI jobs. This method enables the vFabric +parameters to be passed to the MPI jobs so that the appropriate lower level actions can be taken based on +those settings (e.g. inserting Service Level information into data messages). Any MPI job command parameters +should be used on the script command line, and will be passed to the MPI run job. + diff --git a/Moab/iba_select_mpi b/Moab/iba_select_mpi new file mode 100755 index 0000000..561dbe5 --- /dev/null +++ b/Moab/iba_select_mpi @@ -0,0 +1,86 @@ +#!/bin/sh +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] + +# helper script to select MPICH_PREFIX + +# this script should be . included in a run_ script +# Input: +# MPICH_PREFIX - path to MPICH tools (optional) +# Output: +# MPICH_PREFIX - path to MPICH tools + +valid_mpich_prefix() +{ + if [ -z "$MPICH_PREFIX" -o ! -e "$MPICH_PREFIX" -o ! -e "$MPICH_PREFIX"/bin ] + then + return 1 + fi + if [ -e "$MPICH_PREFIX/bin/mpirun" -o -e "$MPICH_PREFIX/bin/mpdtrace" \ + -o -e "$MPICH_PREFIX/bin/mpirun_mpd" -o -e "$MPICH_PREFIX/bin/mpiexec" \ + -o -e "$MPICH_PREFIX/bin/mpirun_rsh" ] + then + return 0 + else + return 1 + fi +} + +# check all MPIs which start with $1 pathname and pick the 1st valid one +find_mpi() +{ + local mpich_prefix + for mpich_prefix in $(ls -d $1/bin 2>/dev/null) + do + MPICH_PREFIX=$(dirname $mpich_prefix 2>/dev/null) + if valid_mpich_prefix + then + break + else + MPICH_PREFIX="" + fi + done +} + +# defaults we use for MPI (QuickSilver, openmpi, mvapich1, mvapich2) +if [ -z "$MPICH_PREFIX" ] +then + if test -f /usr/lib/opa/bin/mpirun_rsh && ! rpm -q kernel-ib >/dev/null 2>&1 + then + # QuickSilver MPI + MPICH_PREFIX=/usr/lib/opa + fi + # by default MPI gets installed using same stack prefix as OFED + prefix=$(/etc/infiniband/info 2>/dev/null|grep '^prefix='|cut -f2 -d=) + prefix=${prefix:-/usr} # in case $prefix not defined or not OFED + MPICH_PREFIX="" +fi +export MPICH_PREFIX diff --git a/Moab/moab.mpi.job.debugger b/Moab/moab.mpi.job.debugger new file mode 100755 index 0000000..f09118a --- /dev/null +++ b/Moab/moab.mpi.job.debugger @@ -0,0 +1,38 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +#[ICS VERSION STRING: unknown] +echo MPIRUNFILE=$mpirunfile +echo VF_SELECTMETHOD=$vfselectmethod +echo VF_SID=$vfsid +echo VF_NAME=$vfname +echo DSPRTG=$dsprtg +echo NUMPROCS=$numprocs +echo QNAME=$qname +echo WRKDIR=$wrkdir diff --git a/Moab/moab.mpi.job.wrapper b/Moab/moab.mpi.job.wrapper new file mode 100755 index 0000000..38a7e51 --- /dev/null +++ b/Moab/moab.mpi.job.wrapper @@ -0,0 +1,55 @@ +#! /bin/bash +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] + + +# initialize + +MPI_TASKMAP=$MOAB_TASKMAP +echo "$MPI_TASKMAP"|tr \& \\n > .mpi_hosts_procs_file.$$ + +if [ -f ".mpi_hosts_file.$$" ] +then + rm .mpi_hosts_file.$$ +fi + +while read line +do + NODE=${line%:*} + PROCS=${line#*:} + for ((i=0; i<$PROCS; i++)) + do + echo $NODE >> .mpi_hosts_file.$$ + done +done <.mpi_hosts_procs_file.$$ + +rm .mpi_hosts_procs_file.$$ + diff --git a/Moab/moab.submit.mvapich.job b/Moab/moab.submit.mvapich.job new file mode 100755 index 0000000..2b97cff --- /dev/null +++ b/Moab/moab.submit.mvapich.job @@ -0,0 +1,240 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] +#! /bin/bash + +# initialize + +# BASE PATH TO MPI EXECUTABLES: To use an alternate location, +# either edit this line or set MPICH_PREFIX in your environment. +# see iba_select_mpi for the set of default MPI selections +# default to MPI used for build +MPICH_PREFIX= + +mpirunfile= +vfselectmethod=sid_qlc +vfname= +vfsid= +dsprtg= +qname= +numprocs=2 +wrkdir=$HOME +mrailmap= + +MPI_CMD_ARGS= + +MOAB_DJOB_QUEUE_ARGS="" +MOAB_DJOB_WRK_DIR_ARGS="" + + + +# Usage - display usage syntax and exit + +Usage() +{ + echo "Usage: submit.mvapich.job [-V vf_select_method] [-s vf_sid] [-n vf_name]" + echo " [-d dsp_rtg] [-q queue_name] [-p num_processes] [-w wrk_dir]" + echo " [-m [,]]" + echo " mpi_run_file [mpi_run_file args]" + echo -e "\n where vf_select_method is one of:" + echo " vf_name: Name of virtual fabric - use -n to define vf name" + echo " sid : ServiceId of virtual fabric - use -s option to define service id" + echo " sid_qlc: ServiceId of virtual fabric - use -s option to define service id," + echo " uses dist_sa (default)" + echo " where dsp_rtg is: 1-adaptive, 2-static_src, 3-static_dest, or 4-static_base" + echo " where queue_name is a valid Moab queue name (default queue is batch)" + echo " where num_processes is the number of processors to run MPI on" + echo " where wrk_dir is the directory the job should execute in (default $""HOME)" + echo " where unit:port is the unit/port pair is used to setup a rail" + exit 2 +} + + + + +# process opts and args + +while getopts r:h:V:s:n:d:p:q:w:m: param +do + case $param in + r) + export mpirunfile=$OPTARG;; + V) + export vfselectmethod=$OPTARG;; + s) + export vfsid=$OPTARG;; + n) + export vfname=$OPTARG;; + d) + export dsprtg=$OPTARG;; + p) + export numprocs=$OPTARG;; + q) + export qname=$OPTARG;; + w) + export wrkdir=$OPTARG;; + m) + export mrailmap=$OPTARG;; + ?) + Usage + esac +done +shift $(($OPTIND -1)) + +mpirunfile=$1 + +# validate args + +if [ "$mpirunfile" = "" ] +then + echo "Must provide an mpi_run_file" + Usage +fi + +if [ ! -f $mpirunfile ] +then + echo "mpi_run_file \"$mpirunfile\" does not exist" + Usage +fi + +if [ "$dsprtg" != "" ] +then + if [ $dsprtg -lt 1 -o $dsprtg -gt 4 ] + then + echo dispersive routing value must be between 1 and 4 + Usage + fi +fi + +# get opagetvf_func definition +. /usr/bin/opagetvf_env + +case $vfselectmethod in + vf_name) + opagetvf_func "-d '$vfname'" VIADEV_DEFAULT_PKEY VIADEV_DEFAULT_SERVICE_LEVEL MTU + if [ $? -ne 0 ] + then + echo "Failed to get environment variables for VF with Name \"$vfname\"" + Usage + fi + export MPI_CMD_ARGS="VIADEV_DEFAULT_PKEY=$VIADEV_DEFAULT_PKEY VIADEV_DEFAULT_SERVICE_LEVEL=$VIADEV_DEFAULT_SERVICE_LEVEL VIADEV_DEFAULT_MTU=MTU$MTU MV_MTU=$MTU PSM_PKEY=$VIADEV_DEFAULT_PKEY IPATH_SL=$VIADEV_DEFAULT_SERVICE_LEVEL PSM_MTU=$MTU";; + sid) + opagetvf_func "-S '$vfsid'" VIADEV_DEFAULT_PKEY VIADEV_DEFAULT_SERVICE_LEVEL MTU + if [ $? -ne 0 ] + then + echo "Failed to get environment variables for VF with SID \"$vfsid\"" + Usage + fi + export MPI_CMD_ARGS="VIADEV_DEFAULT_PKEY=$VIADEV_DEFAULT_PKEY VIADEV_DEFAULT_SERVICE_LEVEL=$VIADEV_DEFAULT_SERVICE_LEVEL VIADEV_DEFAULT_MTU=MTU$MTU MV_MTU=$MTU PSM_PKEY=$VIADEV_DEFAULT_PKEY IPATH_SL=$VIADEV_DEFAULT_SERVICE_LEVEL PSM_MTU=$MTU";; + sid_qlc) + export MPI_CMD_ARGS="PSM_PATH_REC=opp PSM_IB_SERVICE_ID=$vfsid";; + *) + echo Unknown vfselectmethod $vfselectmethod + Usage;; +esac + +if [ "$dsprtg" != "" ] +then + case $dsprtg in + 1) + export routing=adaptive;; + 2) + export routing=static_src;; + 3) + export routing=static_dest;; + 4) + export routing=static_base;; + esac + export MPI_CMD_ARGS="$MPI_CMD_ARGS PSM_PATH_SELECTION=$routing" +fi + +if [ "$MPICH_PREFIX" = "" ] +then + . /usr/bin/iba_select_mpi + if ! valid_mpich_prefix + then + find_mpi $prefix/mpi/gcc/mvapich-1*qlc + fi + if ! valid_mpich_prefix + then + find_mpi $prefix/mpi/gcc/mvapich-1* + fi +fi + +if [ "$qname" != "" ] +then + export MOAB_DJOB_QUEUE_ARGS="-q $qname" +fi + +if [ ! -d $wrkdir ] +then + echo "wrk_dir \"$wrkdir\" does not exist" + Usage +fi + +if [ "$wrkdir" != "" ] +then + export MOAB_DJOB_WRK_DIR_ARGS="-d $wrkdir" +fi + +if [ "$mrailmap" != "" ] +then + . /usr/bin/opagetvf_env + + iba_getpsm_func $mrailmap + if [ $? -ne 0 ] + then + echo "Failed to get environment variable for PSM with value \"$mrailmap\"" + Usage + else + export MPI_CMD_ARGS="$MPI_CMD_ARGS PSM_MULTIRAIL=1 PSM_MULTIRAIL_MAP=$mrailmap" + fi +fi + +# +# submit the job from stdin +# +# parameters: +# -E: Moab adds standard Moab environment variables to the job's environment. +# -l: Defines the resources that are required by the job and establishes a +# limit to the amount of resource that can be consumed. +# + tpn: Tasks per node allowed on allocated hosts, +# + procs: Requests a specific amount of processors for the job. +# -q: Specifies the destination queue (Class) the job should execute in. +# -d: Specifies which directory the job should execute in. +# -V: Declares that all environment variables in the msub environment are +# exported to the batch job. + +cat moab.mpi.job.wrapper > .run.mvapich +echo $MPICH_PREFIX/bin/mpirun_rsh -np $numprocs -hostfile '.mpi_hosts_file.$$' $MPI_CMD_ARGS $* >> .run.mvapich +msub -E -l procs=$numprocs $MOAB_DJOB_WRK_DIR_ARGS $MOAB_DJOB_QUEUE_ARGS -V .run.mvapich +rm .run.mvapich + +exit 0 diff --git a/Moab/moab.submit.mvapich2.job b/Moab/moab.submit.mvapich2.job new file mode 100755 index 0000000..0df2264 --- /dev/null +++ b/Moab/moab.submit.mvapich2.job @@ -0,0 +1,240 @@ +#! /bin/bash +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] + + +# initialize + +# BASE PATH TO MPI EXECUTABLES: To use an alternate location, +# either edit this line or set MPICH_PREFIX in your environment. +# see iba_select_mpi for the set of default MPI selections +# default to MPI used for build +MPICH_PREFIX= + +mpirunfile= +vfselectmethod=sid_qlc +vfname= +vfsid= +dsprtg= +qname= +numprocs=2 +wrkdir=$HOME +mrailmap= + +MPI_CMD_ARGS= + +MOAB_DJOB_QUEUE_ARGS="" +MOAB_DJOB_WRK_DIR_ARGS="" + + +# Usage - display usage syntax and exit + +Usage() +{ + echo "Usage: submit.mvapich2.job [-V vf_select_method] [-s vf_sid] [-n vf_name]" + echo " [-d dsp_rtg] [-q queue_name] [-p num_processes] [-w wrk_dir]" + echo " [-m [,]]" + echo " mpi_run_file [mpi_run_file args]" + echo -e "\n where vf_select_method is one of:" + echo " vf_name: Name of virtual fabric - use -n to define vf name" + echo " sid : ServiceId of virtual fabric - use -s option to define service id" + echo " sid_qlc: ServiceId of virtual fabric - use -s option to define service id," + echo " uses dist_sa (default)" + echo " where dsp_rtg is: 1-adaptive, 2-static_src, 3-static_dest, or 4-static_base" + echo " where queue_name is a valid Moab queue name (default queue is batch)" + echo " where num_processes is the number of processors to run MPI on" + echo " where wrk_dir is the directory the job should execute in (default $""HOME)" + echo " where unit:port is the unit/port pair is used to setup a rail" + exit 2 +} + + + + +# process opts and args + +while getopts r:h:V:s:n:d:p:q:w:m: param +do + case $param in + r) + export mpirunfile=$OPTARG;; + V) + export vfselectmethod=$OPTARG;; + s) + export vfsid=$OPTARG;; + n) + export vfname=$OPTARG;; + d) + export dsprtg=$OPTARG;; + p) + export numprocs=$OPTARG;; + q) + export qname=$OPTARG;; + w) + export wrkdir=$OPTARG;; + m) + export mrailmap=$OPTARG;; + ?) + Usage + esac +done +shift $(($OPTIND -1)) + +mpirunfile=$1 + +# validate args + +if [ "$mpirunfile" = "" ] +then + echo "Must provide an mpi_run_file" + Usage +fi + +if [ ! -f $mpirunfile ] +then + echo "mpi_run_file \"$mpirunfile\" does not exist" + Usage +fi + +if [ "$dsprtg" != "" ] +then + if [ $dsprtg -lt 1 -o $dsprtg -gt 4 ] + then + echo dispersive routing value must be between 1 and 4 + Usage + fi +fi + +# get opagetvf_func definition +. /usr/bin/opagetvf_env + +case $vfselectmethod in + vf_name) + opagetvf_func "-d '$vfname'" MV2_DEFAULT_PKEY MV2_DEFAULT_SERVICE_LEVEL MTU + if [ $? -ne 0 ] + then + echo "Failed to get environment variables for VF with Name \"$vfname\"" + Usage + fi + export MPI_CMD_ARGS="MV2_DEFAULT_PKEY=$MV2_DEFAULT_PKEY MV2_DEFAULT_SERVICE_LEVEL=$MV2_DEFAULT_SERVICE_LEVEL MV2_DEFAULT_MTU=IBV_MTU_$MTU PSM_PKEY=$MV2_DEFAULT_PKEY IPATH_SL=$MV2_DEFAULT_SERVICE_LEVEL PSM_MTU=$MTU";; + sid) + opagetvf_func "-S '$vfsid'" MV2_DEFAULT_PKEY MV2_DEFAULT_SERVICE_LEVEL MTU + if [ $? -ne 0 ] + then + echo "Failed to get environment variables for VF with SID \"$vfsid\"" + Usage + fi + export MPI_CMD_ARGS="MV2_DEFAULT_PKEY=$MV2_DEFAULT_PKEY MV2_DEFAULT_SERVICE_LEVEL=$MV2_DEFAULT_SERVICE_LEVEL MV2_DEFAULT_MTU=IBV_MTU_$MTU PSM_PKEY=$MV2_DEFAULT_PKEY IPATH_SL=$MV2_DEFAULT_SERVICE_LEVEL PSM_MTU=$MTU";; + sid_qlc) + export MPI_CMD_ARGS="PSM_PATH_REC=opp PSM_IB_SERVICE_ID=$vfsid";; + *) + echo Unknown vfselectmethod $vfselectmethod + Usage;; +esac + +if [ "$dsprtg" != "" ] +then + case $dsprtg in + 1) + export routing=adaptive;; + 2) + export routing=static_src;; + 3) + export routing=static_dest;; + 4) + export routing=static_base;; + esac + export MPI_CMD_ARGS="$MPI_CMD_ARGS PSM_PATH_SELECTION=$routing" +fi + +if [ "$MPICH_PREFIX" = "" ] +then + . /usr/bin/iba_select_mpi + if ! valid_mpich_prefix + then + find_mpi $prefix/mpi/gcc/mvapich2*qlc + fi + if ! valid_mpich_prefix + then + find_mpi $prefix/mpi/gcc/mvapich2* + fi +fi + +if [ "$qname" != "" ] +then + export MOAB_DJOB_QUEUE_ARGS="-q $qname" +fi + +if [ ! -d $wrkdir ] +then + echo "wrk_dir \"$wrkdir\" does not exist" + Usage +fi + +if [ "$wrkdir" != "" ] +then + export MOAB_DJOB_WRK_DIR_ARGS="-d $wrkdir" +fi + +if [ "$mrailmap" != "" ] +then + . /usr/bin/opagetvf_env + + iba_getpsm_func $mrailmap + if [ $? -ne 0 ] + then + echo "Failed to get environment variable for PSM with value \"$mrailmap\"" + Usage + else + export MPI_CMD_ARGS="$MPI_CMD_ARGS PSM_MULTIRAIL=1 PSM_MULTIRAIL_MAP=$mrailmap" + fi +fi + +# +# submit the job from stdin +# +# parameters: +# -E: Moab adds standard Moab environment variables to the job's environment. +# -l: Defines the resources that are required by the job and establishes a +# limit to the amount of resource that can be consumed. +# + tpn: Tasks per node allowed on allocated hosts, +# + procs: Requests a specific amount of processors for the job. +# -q: Specifies the destination queue (Class) the job should execute in. +# -d: Specifies which directory the job should execute in. +# -V: Declares that all environment variables in the msub environment are +# exported to the batch job. + +cat moab.mpi.job.wrapper > .run.mvapich2 +echo $MPICH_PREFIX/bin/mpirun_rsh -np $numprocs -hostfile '.mpi_hosts_file.$$' $MPI_CMD_ARGS $* >> .run.mvapich2 +msub -E -l procs=$numprocs $MOAB_DJOB_WRK_DIR_ARGS $MOAB_DJOB_QUEUE_ARGS -V .run.mvapich2 +rm .run.mvapich2 + +exit 0 diff --git a/Moab/moab.submit.openmpi.job b/Moab/moab.submit.openmpi.job new file mode 100755 index 0000000..5d32ff4 --- /dev/null +++ b/Moab/moab.submit.openmpi.job @@ -0,0 +1,251 @@ +#! /bin/bash +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] + + +# initialize + +# BASE PATH TO MPI EXECUTABLES: To use an alternate location, +# either edit this line or set MPICH_PREFIX in your environment. +# see iba_select_mpi for the set of default MPI selections +# default to MPI used for build +MPICH_PREFIX= + +mpirunfile= +vfselectmethod=sid_qlc +vfname= +vfsid= +dsprtg= +qname= +numprocs=2 +wrkdir=$HOME +mrailmap= + +MPI_CMD_ARGS= + +LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$MPICH_PREFIX/lib64/ +MOAB_DJOB_QUEUE_ARGS="" +MOAB_DJOB_WRK_DIR_ARGS="" + + +# Usage - display usage syntax and exit + +Usage() +{ + echo "Usage: submit.openmpi.job [-V vf_select_method] [-s vf_sid] [-n vf_name]" + echo " [-d dsp_rtg] [-q queue_name] [-p num_processes] [-w wrk_dir]" + echo " [-m [,]]" + echo " mpi_run_file [mpi_run_file args]" + echo -e "\n where vf_select_method is one of:" + echo " vf_name: Name of virtual fabric - use -n to define vf name" + echo " sid : ServiceId of virtual fabric - use -s option to define service id" + echo " sid_qlc: ServiceId of virtual fabric - use -s option to define service id," + echo " uses dist_sa (default)" + echo " where dsp_rtg is: 1-adaptive, 2-static_src, 3-static_dest, or 4-static_base" + echo " where queue_name is a valid Moab queue name (default queue is batch)" + echo " where num_processes is the number of processors to run MPI on" + echo " where wrk_dir is the directory the job should execute in (default $""HOME)" + echo " where unit:port is the unit/port pair is used to setup a rail" + exit 2 +} + + + + +# process opts and args + +while getopts r:h:V:s:n:d:p:q:w:m: param +do + case $param in + r) + export mpirunfile=$OPTARG;; + V) + export vfselectmethod=$OPTARG;; + s) + export vfsid=$OPTARG;; + n) + export vfname=$OPTARG;; + d) + export dsprtg=$OPTARG;; + p) + export numprocs=$OPTARG;; + q) + export qname=$OPTARG;; + w) + export wrkdir=$OPTARG;; + m) + export mrailmap=$OPTARG;; + ?) + Usage + esac +done +shift $(($OPTIND -1)) + +mpirunfile=$1 + +# validate args + +if [ "$mpirunfile" = "" ] +then + echo "Must provide a mpi_run_file" + Usage +fi + +if [ ! -f $mpirunfile ] +then + echo "mpi_run_file \"$mpirunfile\" does not exist" + Usage +fi + +if [ "$dsprtg" != "" ] +then + if [ $dsprtg -lt 1 -o $dsprtg -gt 4 ] + then + echo dispersive routing value must be between 1 and 4 + Usage + fi +fi + +# get opagetvf_func definition +. /usr/bin/opagetvf_env + +case $vfselectmethod in + vf_name) + opagetvf2_func "-d '$vfname'" OMPI_MCA_btl_openib_pkey OMPI_MCA_btl_openib_ib_service_level OMPI_MCA_btl_openib_mtu + if [ $? -ne 0 ] + then + echo "Failed to get environment variables for VF with Name \"$vfname\"" + Usage + fi + export OMPI_MCA_mtl_psm_ib_pkey=$OMPI_MCA_btl_openib_pkey + export OMPI_MCA_mtl_psm_ib_service_level=$OMPI_MCA_btl_openib_ib_service_level + export PSM_MTU=$OMPI_MCA_btl_openib_mtu;; + sid) + opagetvf2_func "-S '$vfsid'" OMPI_MCA_btl_openib_pkey OMPI_MCA_btl_openib_ib_service_level OMPI_MCA_btl_openib_mtu + if [ $? -ne 0 ] + then + echo "Failed to get environment variables for VF with SID \"$vfsid\"" + Usage + fi + export OMPI_MCA_mtl_psm_ib_pkey=$OMPI_MCA_btl_openib_pkey + export OMPI_MCA_mtl_psm_ib_service_level=$OMPI_MCA_btl_openib_ib_service_level + export PSM_MTU=$OMPI_MCA_btl_openib_mtu;; + sid_qlc) + export OMPI_MCA_mtl_psm_path_query=opp + export OMPI_MCA_mtl_psm_ib_service_id=$vfsid;; + *) + echo Unknown vfselectmethod $vfselectmethod + Usage;; +esac + +if [ "$dsprtg" != "" ] +then + case $dsprtg in + 1) + export routing=adaptive;; + 2) + export routing=static_src;; + 3) + export routing=static_dest;; + 4) + export routing=static_base;; + esac + export MPI_CMD_ARGS="PSM_PATH_SELECTION=$routing" +fi + +if [ "$MPICH_PREFIX" = "" ] +then + . /usr/bin/iba_select_mpi + if ! valid_mpich_prefix + then + find_mpi $prefix/mpi/gcc/openmpi*qlc + fi + if ! valid_mpich_prefix + then + find_mpi $prefix/mpi/gcc/openmpi* + fi +fi + +if [ "$qname" != "" ] +then + export MOAB_DJOB_QUEUE_ARGS="-q $qname" +fi + +if [ ! -d $wrkdir ] +then + echo "wrk_dir \"$wrkdir\" does not exist" + Usage +fi + +if [ "$wrkdir" != "" ] +then + export MOAB_DJOB_WRK_DIR_ARGS="-d $wrkdir" +fi + +if [ "$mrailmap" != "" ] +then + . /usr/bin/opagetvf_env + + iba_getpsm_func $mrailmap + if [ $? -ne 0 ] + then + echo "Failed to get environment variable for PSM with value \"$mrailmap\"" + Usage + else + export MPI_CMD_ARGS="$MPI_CMD_ARGS PSM_MULTIRAIL=1 PSM_MULTIRAIL_MAP=$mrailmap" + fi +fi + +if [ "$MPI_CMD_ARGS" != "" ] +then + export MPI_CMD_ARGS="-x \"$MPI_CMD_ARGS\"" +fi + +# +# submit the job from stdin +# +# parameters: +# -E: Moab adds standard Moab environment variables to the job's environment. +# -l: Defines the resources that are required by the job and establishes a +# limit to the amount of resource that can be consumed. +# + tpn: Tasks per node allowed on allocated hosts, +# + procs: Requests a specific amount of processors for the job. +# -q: Specifies the destination queue (Class) the job should execute in. +# -d: Specifies which directory the job should execute in. +# -V: Declares that all environment variables in the msub environment are +# exported to the batch job. + +cat moab.mpi.job.wrapper > .run.openmpi +echo $MPICH_PREFIX/bin/mpirun -np $numprocs -hostfile '.mpi_hosts_file.$$' $MPI_CMD_ARGS $* >> .run.openmpi +msub -E -l procs=$numprocs $MOAB_DJOB_WRK_DIR_ARGS $MOAB_DJOB_QUEUE_ARGS -V .run.openmpi +rm .run.openmpi + +exit 0 diff --git a/MpiApps/Makefile b/MpiApps/Makefile new file mode 100644 index 0000000..3cf75be --- /dev/null +++ b/MpiApps/Makefile @@ -0,0 +1,81 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** +# Makefile for MpiApps + +# Include Make Control Settings +include $(TL_DIR)/$(PROJ_FILE_DIR)/Makesettings.project + +DS_SUBPROJECTS = +DSP_SOURCES = Makefile + +DIRS = + +include $(TL_DIR)/$(PROJ_FILE_DIR)/Makerules.project + +MPI_INSTALL_TESTS_DIR = $(PROJ_STAGE_DIR)/Tests/mpi + +INSTALL_TEST_APPS_SRC = $(TL_DIR)/MpiApps/apps/mpi_apps.tgz +INSTALL_TEST_APPS = $(TL_DIR)/MpiApps/apps/run \ + $(INSTALL_TEST_APPS_SRC) + +CLOBBER_EXTRA = \ + .ICSBOOTROMVERSIONSTRING \ + # add additional files here + +.PHONEY: appl +appl $(TL_DIR)/MpiApps/apps/mpi_apps.tgz $(TL_DIR)/MpiApps/apps/for_intel_mpi: + if [ -d apps ]; then \ + cd apps; $(MAKE) -f Makefile.package $(MFLAGS) ALL; \ + fi + + +cleandepend clean:: clobber + +clobber:: + if [ -d apps ]; then \ + cd apps; $(MAKE) -f Makefile.package $(MFLAGS) CLOBBER; \ + fi +depend:: +force:: +ALL:: INCLUDES LIBS CMDS +INCLUDES:: +LIBS:: +# do the real work during CMDS +CMDS:: $(INSTALL_TEST_APPS_SRC) + +STAGE:: + $(VS)if [ -d apps ]; then $(STAGE_INSTALL) $(STAGE_INSTALL_DIR_OPT) $(MPI_INSTALL_TESTS_DIR) $(INSTALL_TEST_APPS); fi + $(VS)if [ -d apps ]; then $(STAGE_INSTALL) $(STAGE_INSTALL_DIR_OPT) $(PROJ_STAGE_SRC_DIR)/mpi/mpi_apps $(INSTALL_TEST_APPS_SRC); fi + +INSTALL:: +RUNTEST:: +build_dsfiles:: +clobber_dsfiles:: +lint:: +cflow:: diff --git a/MpiApps/apps/Makefile b/MpiApps/apps/Makefile new file mode 100644 index 0000000..4435d64 --- /dev/null +++ b/MpiApps/apps/Makefile @@ -0,0 +1,252 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# Makefile for MPI application/benchmark source for end user system +# targets: +# full - build all targets. +# basic - build all applications provivded in opa-fastfabric package +# quick - build commonly used apps. +# all - synonym for quick +# clobber - remove all built files. +# +# The following targets build the matching applications. If the +# application name differs from the target name, it is listed +# in parens. +# +# GROUPSTRESS +# DEVIATION +# LAT (latency) +# BW (bandwidth) +# MULTIBW (multi-pair bandwidth) +# OSU2 (version 2 of osu_latency, osu_bw, osu_bcast, osu_bibw) +# OSU2_MPI2 (version 2 of osu MPI2 benchmarks) +# OSU38 (version 3.8 of the OSU benchmarks) +# IMB/PMB (Pallas) +# XHPL2 (hpl v2) +# + +ifndef MPICH_PREFIX +export MPICH_PREFIX=$(shell . ./select_mpi 2>/dev/null; echo $$MPICH_PREFIX) +endif + +# set MPICC to our own mpicc warpper that will change the real mpicc to use RPATH +# so that our MPI Apps will stick with the mpi we selected during build. +# if you want the default RUNPATH, you can set MPICC before calling the Makefile +ifndef MPICC +export REAL_MPICC=$(MPICH_PREFIX)/bin/mpicc +export MPICC=$(PWD)/mpicc +endif +ifndef MPIF77 +export REAL_MPIF77=$(MPICH_PREFIX)/bin/mpif77 +export MPIF77=$(PWD)/mpif77 +endif +ifndef MPI_INCLUDE_DIR +export MPI_INCLUDE_DIR=$(MPICH_PREFIX)/include +endif +ifndef MPI_LIB_DIR +export MPI_LIB_DIR=/lib +endif + +all:: INCLUDES LIBS CMDS +.PHONY: all + +CHECK: SHOWMPI + @echo "Building MPI Check..." + export HOME_DIR=$(PWD); \ + make -C mpicheck + @echo +.PHONY: CHECK + +GROUPSTRESS: SHOWMPI + @echo "Building groupstress..." + export HOME_DIR=$(PWD); \ + make -C groupstress + @echo +.PHONY: GROUPSTRESS +DEVIATION: SHOWMPI + @echo "Building deviation..." + export HOME_DIR=$(PWD); \ + make -C deviation + @echo +.PHONY: DEVIATION + +NVIDIA: SHOWMPI + @echo "Building nvidia test apps..." + export HOME_DIR=$(PWD); \ + make -C nvidia + @echo +.PHONY: NVIDIA + +LAT: SHOWMPI + @echo "Building OSU latency..." + cd latency;\ + $(MPICC) -I$(MPI_INCLUDE_DIR) -o latency latency.c; + @echo +.PHONY: LAT + +BW: SHOWMPI + @echo "Building OSU bandwidth..." + cd bandwidth;\ + $(MPICC) -I$(MPI_INCLUDE_DIR) -o bw bw.c; + @echo +.PHONY: BW + +MULTIBW: SHOWMPI + @echo "Building multi bandwidth..." + cd mpi_multibw;\ + $(MPICC) -I$(MPI_INCLUDE_DIR) -o mpi_multibw mpi_multibw.c; + @echo +.PHONY: MUTLIBW + +OSU2: SHOWMPI + @echo "Building OSU 2.0 benchmarks..." + cd osu2; $(MPICC) -I$(MPI_INCLUDE_DIR) -o osu_latency osu_latency.c + cd osu2; $(MPICC) -I$(MPI_INCLUDE_DIR) -o osu_bw osu_bw.c + cd osu2; $(MPICC) -I$(MPI_INCLUDE_DIR) -o osu_bcast osu_bcast.c + cd osu2; $(MPICC) -I$(MPI_INCLUDE_DIR) -o osu_bibw osu_bibw.c + @echo +.PHONY: OSU2 + +OSU38: SHOWMPI + @echo "Building OSU 3.8 benchmarks..." + cd osu-micro-benchmarks-3.8-July12; ./configure CC=$(MPICC); make + @echo +.PHONY: OSU38 + +OSU2_MPI2: SHOWMPI + @echo "Building OSU 2.0 benchmarks for MPI2..." + cd osu2; $(MPICC) -I$(MPI_INCLUDE_DIR) -o osu_acc_latency osu_acc_latency.c + cd osu2; $(MPICC) -I$(MPI_INCLUDE_DIR) -o osu_get_latency osu_get_latency.c + cd osu2; $(MPICC) -I$(MPI_INCLUDE_DIR) -o osu_put_latency osu_put_latency.c + cd osu2; $(MPICC) -I$(MPI_INCLUDE_DIR) -o osu_get_bw osu_get_bw.c + cd osu2; $(MPICC) -I$(MPI_INCLUDE_DIR) -o osu_put_bw osu_put_bw.c + cd osu2; $(MPICC) -I$(MPI_INCLUDE_DIR) -o osu_put_bibw osu_put_bibw.c + @echo +.PHONY: OSU2_MPI2 + +IMB: SHOWMPI + @echo "Building Intel Micro Benchmarks 4.0.2..." + cd imb/src; make MPI_HOME=$(MPICH_PREFIX) CC=$(MPICC) -f make_mpich + @echo +.PHONY: IMB + +XHPL2: SHOWMPI + @echo "Building HPL 2.2 (Linpack)..." + export HPL_HOME_DIR=$(PWD)/hpl-2.2;\ + make -C hpl-2.2 arch=ICS.`uname -s`.`./get_mpi_cc.sh` + @echo +.PHONY: XHPL2 + +# PGFILE_TEST is not included in the stock mpi_apps package. +PGFILE: SHOWMPI + @echo "Building pgfile test..." + export HOME_DIR=$(PWD); make -C pgfile_test; + @echo +.PHONY: PGFILE + +# TACHYON is not included in the stock mpi_apps package. +TACHYON: SHOWMPI + @echo "Building Tachyon demo..." + rm -rf tachyon/compile/* + if [ -f $(MPICH_PREFIX)/lib/libmpich.a -o -f $(MPICH_PREFIX)/lib/shared/libmpich.so ] ; then export MPICH_LIB='-lmpich'; fi + make -C tachyon/unix linux-vapi + cp tachyon/compile/linux-vapi/tachyon tachyon/scenes + @echo +.PHONY: TACHYON + +# MANDEL is not included in the stock mpi_apps package. +MANDEL: SHOWMPI + @echo "Building Mandel demo..." + make -C mandel clean + make -C mandel + @echo +.PHONY: MANDEL + +cleandepend clean:: clobber +.PHONY: cleandepend clean + +clobber:: + rm -f latency/*.o latency/*.d latency/latency + rm -f bandwidth/*.o bandwidth/*.d bandwidth/bw + if [ -f "imb/src/make_mpich" ]; then cd imb/src; make MPI_HOME=$(MPICH_PREFIX) -f make_mpich clean; fi + if [ -d hpl-2.2 ]; then find hpl-2.2 -name ICS.`uname -s`.* | xargs rm -rf; rm -rf hpl-2.2/bin hpl-2.2/lib; fi + if [ -d hpl-2.2 ]; then find hpl-2.2 -name xerbla.o | xargs rm -rf; fi + if [ -d pgfile_test ]; then make -C pgfile_test clean; fi + if [ -d tachyon ]; then rm -rf tachyon/compile/*; fi + if [ -d mandel ]; then make -C mandel clean; rm -f mandel/*.d; fi + make -C mpicheck clean; + make -C deviation clean; + make -C groupstress clean; + rm -f mpi_multibw/mpi_multibw mpi_multibw/*.o + rm -f osu2/*.o + rm -f osu2/osu_latency osu2/osu_bw osu2/osu_bcast osu2/osu_bibw + rm -f osu2/osu_acc_latency osu2/osu_get_latency osu2/osu_put_latency + rm -f osu2/osu_get_bw osu2/osu_put_bw osu2/osu_put_bibw + if [ -f "osu-micro-benchmarks-3.8-July12/Makefile" ]; then cd osu-micro-benchmarks-3.8-July12; make clean; fi + rm -f .prefix +.PHONY: clobber + +SHOWMPI: + @echo "Using MPICH_PREFIX=$(MPICH_PREFIX)" + echo "$(MPICH_PREFIX)" > .prefix +.PHONY: SHOWMPI + +depend:: +force:: +INCLUDES:: +# do the real work during LIBS +LIBS:: +.PHONY: depend force INCLUDES LIBS + +opa-base:: DEVIATION CHECK GROUPSTRESS + @echo "build base sample applications" +.PHONY: opa-base + +quick:: BW LAT MULTIBW OSU2 OSU38 IMB XHPL2 opa-base + @echo "Built subset of sample applications" +.PHONY: quick + +CMDS:: quick + @echo "Built sample applications" +.PHONY: CMDS + +full:: CMDS + @echo "Built full set of sample applications" +.PHONY: full + +STAGE:: +INSTALL:: + +RUNTEST:: +build_dsfiles:: +clobber_dsfiles:: +lint:: +cflow:: + +.PHONY: STAGE INSTALL RUNTEST build_dsfiles clobber_dsfiles lint cflow diff --git a/MpiApps/apps/Makefile.package b/MpiApps/apps/Makefile.package new file mode 100644 index 0000000..f4ece74 --- /dev/null +++ b/MpiApps/apps/Makefile.package @@ -0,0 +1,85 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** +# Makefile for Mpi apps + +# Include Make Control Settings +include $(TL_DIR)/$(PROJ_FILE_DIR)/Makesettings.project + +DS_SUBPROJECTS = +DSP_SOURCES = Makefile + +DIRS = + +include $(TL_DIR)/$(PROJ_FILE_DIR)/Makerules.project + + +# files used to create mpi_apps.tgz +INSTALL_TEST_APPS_SRC = mpi_apps.tgz + +CLOBBER_EXTRA = \ + .ICSBOOTROMVERSIONSTRING \ + mpi_apps.tgz \ + # add additional files here + +.PHONEY: appl + +appl mpi_apps.tgz: + tar cvfz mpi_apps.tgz --exclude CVS \ + Makefile mpi_hosts.sample README prepare_run select_mpi run_bw \ + get_selected_mpi.sh get_mpi_cc.sh *.params gen_group_hosts \ + gen_mpi_hosts mpi_cleanup stop_daemons \ + hpl_dat_gen config_hpl2 run_hpl2 run_lat \ + run_imb run_lat2 run_bw2 run_bibw2 run_bcast2 run_app runmyapp \ + mpicheck run_mpicheck deviation run_deviation \ + run_multibw run_mpi_stress run_osu \ + groupstress run_cabletest run_allhfilatency run_nxnlatbw \ + run_alltoall3 run_bcast3 run_bibw3 run_bw3 run_lat3 run_mbw_mr3 \ + run_multi_lat3 run_batch_script run_batch_cabletest \ + hpl-count.diff \ + hpl-config/HPL.dat* hpl-config/README \ + mpicc mpif77; + +cleandepend clean:: clobber +clobber:: CLOBBER +CLOBBER:: + rm -rf $(CLOBBER_EXTRA) +depend:: +force:: +ALL:: INCLUDES LIBS CMDS +INCLUDES:: +LIBS:: +# do the real work during CMDS +CMDS:: $(INSTALL_TEST_APPS_SRC) +STAGE:: +INSTALL:: +RUNTEST:: +build_dsfiles:: +clobber_dsfiles:: +lint:: +cflow:: diff --git a/MpiApps/apps/README b/MpiApps/apps/README new file mode 100644 index 0000000..097a0ed --- /dev/null +++ b/MpiApps/apps/README @@ -0,0 +1,85 @@ +This package contains Mpi applications and packages for testing and +evaluation. + + + +NOTE TO RPM USERS +------------------------------------------------------------------- +If you have installed the opa-fastfabric package through your distro +you likely only have a subset of the applications required for full +testing. Certain run scripts, builds, and functionality will be +limited. To enable full functionality, the opa-mpi-apps package +must be installed. This package is available from Intel and contained +in Intel Fabric Suite (IFS). + + +MPICH_PREFIX ENVIRONMENT VARIABLE: +---------------------------------- + +By default, Make will build these programs with the MPI installed in + /usr/mpi/gcc/openmpi* + +You can override this by setting MPICH_PREFIX in your .bashrc file. For +example, the following will use Intel MPI: + +export MPICH_PREFIX=/opt/intel/impi_latest/intel64 + + +USING THESE TOOLS WITH MPI-SELECTOR: +------------------------------------ + +In OFED (and IFS), the normal method of selecting an MPI is to +use the mpi-selector commands (type "man mpi-selector-menu" and "man +mpi-selector" for details on those commmands). + +To use mpi-selector with these scripts, add this line to your .bashrc +file: + +source /usr/src/opa/mpi_apps/get_selected_mpi.sh + + + +COMPILING THE TEST PROGRAMS: +---------------------------- + +The top level Makefile will build all the applications and benchmarks, +using the default (described above) or the value of MPICH_PREFIX (also +described above). + +Some useful make targets include: + + clean - remove all binaries. Useful when changing MPIs. + all - will build everything, including NPB. + quick - builds only bandwidth, latency, pmb and xhpl. + + + +RUNNING THE TEST PROGRAMS: +-------------------------- + +A top level "run" script is provided to run all the applications as a +regression test. Other scripts will run individual benchmarks. These +scripts assume the existence of a local "mpi_hosts" file [alternate name can be +exported in MPI_HOSTS if desired] (in mpirun mode) +and that mpd is already running (if you're using mvapich2). For example, +to run the bandwith test, simply type: + +# ./run_bw + +The scripts log the output of the MPI programs to the +/usr/src/opa/mpi_apps/logs directory. + + + +TUNING THE TEST PROGRAMS: +------------------------- + +MVAPICH, MVAPICH2 and OpenMPI are all extremely tunable, and a complete +discussion of all their settings is far beyond the scope of this document. +However, these scripts to provide examples of tuning the different MPIs +as a way to get started. + +When using IFS, you can tune any of the MPIs. See the files +mvapich2.params and openmpi.params for details. +Each file describes the syntax of the parameter file, provides a link to +online documentation on how to tune that MPI and several sample parameters. diff --git a/MpiApps/apps/config_hpl2 b/MpiApps/apps/config_hpl2 new file mode 100755 index 0000000..1248708 --- /dev/null +++ b/MpiApps/apps/config_hpl2 @@ -0,0 +1,120 @@ +#!/bin/bash +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] + +# select an HPL.dat file and copy to all hosts +# MPI_HOSTS - mpi_hosts file to use (default is $PWD/mpi_hosts) + +MPI_HOSTS=${MPI_HOSTS:-$PWD/mpi_hosts} + +if [ $(echo $MPI_HOSTS|cut -c1) != '/' ] +then + MPI_HOSTS="$PWD/$MPI_HOSTS" +fi + +arch=ICS.`uname -s`.`./get_mpi_cc.sh` + +TEMP_FILE="$(mktemp)" +trap "rm -rf $TEMP_FILE; exit 1" SIGINT SIGHUP SIGTERM +trap "rm -rf $TEMP_FILE" EXIT + +Usage() +{ + echo " Usage: ./config_hpl2 [-l] config_name [problem_size]" + echo " -l - only configure local file, default is to configure on all mpi_hosts" + echo " For example: ./config_hpl2 32t" + echo " either create hpl-config/HPL.dat-'config_name'" + echo " or select one of:" + cd hpl-config; ls HPL.dat-*[!~] + exit 2 +} + +lopt=n +while getopts l param +do + case $param in + l) lopt="y";; + *) Usage;; + esac +done +shift $((OPTIND-1)) + +if [ -z "$1" ] +then + Usage +else + config_name=$1 +fi +if [ $lopt = n -a ! -f $MPI_HOSTS ] +then + echo " Please create $MPI_HOSTS file with the list of " + echo " hosts in this cluster. One hostname per line." + echo " See mpi_hosts.sample file" + exit 1 +fi + +if [ ! -d hpl-2.2/bin/$arch ] +then + echo " Could not find hpl2 compiled for $arch." + echo " Please compile hpl2 using:" + echo " make XHPL2" + exit 1 +fi +if [ ! -f hpl-config/HPL.dat-$config_name ] +then + echo " HPL.dat file for $config_name is not available" + echo " either create hpl-config/HPL.dat-$config_name" + echo " or select one of:" + cd hpl-config; ls HPL.dat-*[!~] + exit 1 +fi + +file=hpl-config/HPL.dat-$config_name +if [ ! -z "$2" ] +then + # change line 6 to requested problem size + sed -e "6s/^[0-9]*/$2/" < $file > $TEMP_FILE + if [ $lopt = n ] + then + opascpall -p -h "`sort -u $MPI_HOSTS`" $TEMP_FILE $PWD/hpl-2.2/bin/$arch/HPL.dat + else + # avoid any cp alias + /bin/cp -f $TEMP_FILE $PWD/hpl-2.2/bin/$arch/HPL.dat + fi +else + if [ $lopt = n ] + then + opascpall -p -h "`sort -u $MPI_HOSTS`" $file $PWD/hpl-2.2/bin/$arch/HPL.dat + else + # avoid any cp alias + /bin/cp -f $file $PWD/hpl-2.2/bin/$arch/HPL.dat + fi +fi diff --git a/MpiApps/apps/deviation/Makefile b/MpiApps/apps/deviation/Makefile new file mode 100644 index 0000000..2c3b4eb --- /dev/null +++ b/MpiApps/apps/deviation/Makefile @@ -0,0 +1,44 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +ifndef MPICH_PREFIX +export MPICH_PREFIX=/usr/lib/opa +endif +ifndef MPICC +export MPICC=$(MPICH_PREFIX)/bin/mpicc +endif + +all: deviation + +deviation: deviation.c + #$(MPICC) -o deviation -g deviation.c -Idmalloc -Ldmalloc -ldmallocth + $(MPICC) -o deviation -g deviation.c + +clean: + rm -f deviation *.o diff --git a/MpiApps/apps/deviation/deviation.c b/MpiApps/apps/deviation/deviation.c new file mode 100644 index 0000000..f9a3b53 --- /dev/null +++ b/MpiApps/apps/deviation/deviation.c @@ -0,0 +1,1820 @@ +/* BEGIN_ICS_COPYRIGHT7 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT7 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define HOSTNAME_MAXLEN 64 +#define MYBUFSIZE 4*1024*1028 +#define MAX_REQ_NUM 100000 + +/* defaults */ +#define LATENCY_TOLERANCE 50 +#define LATENCY_DELTA 0.8 +#define LATENCY_WARMUP 10 +#define LATENCY_SIZE 0 +#define LATENCY_LOOP 4000 + +#define BANDWIDTH_TOLERANCE 20 +#define BANDWIDTH_DELTA 150 +#define BANDWIDTH_WARMUP 10 +#define BANDWIDTH_SIZE (2 * 1024 * 1024) +#define BANDWIDTH_LOOP 30 + +#define TRIAL_PAIRS 20 /* max pairs to test during trial to select baseline */ + +#define true 1 +#define false 0 + +char sendBuffer[MYBUFSIZE]; +char receiveBuffer[MYBUFSIZE]; + +MPI_Request request[MAX_REQ_NUM]; +MPI_Request request2[MAX_REQ_NUM]; +MPI_Status my_stat[MAX_REQ_NUM]; + +/*#define DEBUG */ +/*#define SECOND_PASS */ + +/* keep track of status per pair for initial test */ +typedef struct pairResults +{ + int sendRank; /* rank of sending hoat */ + int receiveRank; /* rank of receiving host */ + double latency; /* pair latency */ + double bandwidth; /* pair bandwidth */ + double latencyTimeStart; + double latencyTimeEnd; + int latencyFailed; + double bandwidthTimeStart; + double bandwidthTimeEnd; + int bandwidthFailed; + char sendHostname[HOSTNAME_MAXLEN]; /* sending hostname */ + char receiveHostname[HOSTNAME_MAXLEN]; /* receiving hostname */ + int alone; /* is this a single */ + int failed; /* did this pair fail */ + int valid; /* is this a valid pair */ +} pairResults; + +/* host list */ +typedef struct hostListing +{ + char hostname[HOSTNAME_MAXLEN]; +} hostListing; + +/* global variables */ +int verbose = false; /* default to quite mode */ +int debug = false; /* default to no debug statements */ +int concurrent = false; /* default to sequential testing */ +int compare_best = false; /* default to using Avg for comparisons */ +int secondPass = false; /* start with first pass */ +int trialPass = false; /* assume no trial pass */ +int trialPairs = TRIAL_PAIRS;/* num pairs run during trail to pick baseline */ +int compute_lat_thres = true; /* default to computing using tol and delta */ +int compute_bw_thres = true; /* default to computing using tol and delta */ +int use_bwdelta = false; +int use_bwtol = false; +int use_lattol = false; +int use_latdelta = false; + +int latencyTolerance = LATENCY_TOLERANCE; +double latencyDelta = LATENCY_DELTA; +int latencySize = LATENCY_SIZE; /* latency test frame size */ +int latencyLoop = LATENCY_LOOP; /* number of latency frame loops */ +double latencyUpper = 0;/* failure threshold, latency > Upper fails */ + +int bandwidthTolerance = BANDWIDTH_TOLERANCE; +double bandwidthDelta = BANDWIDTH_DELTA; +int bandwidthSize = BANDWIDTH_SIZE; /* bandwidth test frame size */ +int bandwidthLoop = BANDWIDTH_LOOP; /* number of bandwidth frame loops */ +double bandwidthLower = 0; /* failure threshold, bandwidth < Lower fails */ +int bandwidthBiDir = false; /* do a bidirectional BW test */ + +char baselineHost[HOSTNAME_MAXLEN]; +int baselineRank = 0; +hostListing* hostList = NULL; /* list of hosts */ + +double latencyMax = 0; +double latencyMin = 0; +double latencyAvg = 0; +double latencyBase = 0; /* basis for comparison - Avg or Min */ + +double bandwidthMax = 0; +double bandwidthMin = 0; +double bandwidthAvg = 0; +double bandwidthBase = 0; /* basis for comparison - Avg or Max */ + +/* declarations */ +static void initPairs(pairResults *pairData, int pairs); +static void reportTestResults(int pairs, pairResults *pairData); +static int parseInputParameters(int argc, char *argv[]); +static int findBaselineHost(int pairs, int loop, pairResults *pairData); +static void createPairs(int concurrent, pairResults *pairData); +static void runConcurrentLatency(int pairs, int doubles, int size, int loop, + pairResults *pairData); +static void runConcurrentBandwidth(int pairs, int doubles, int size, int loop, + pairResults *pairData); +static void runSequentialLatency(int pairs, int size, int loop, + pairResults *pairData); +static void runSequentialBandwidth(int pairs, int size, int loop, + pairResults *pairData); +static void hostReport(pairResults *pairData, int latency); +static void hostBroadcast(pairResults *pairData); +static void Usage(); +static const char *pairedHostname(); + +/* Entry point */ +int +main(int argc, char **argv) +{ + int myrank; /* what is my rank */ + int ranks; /* how many ranks total */ + int hosts; /* how many hosts */ + int pair; /* pairing iterator - first pass */ + int pair2; /* pairing iterator - second pass */ + int pairs; /* how many pairings */ + int doubles; /* how many unique pairs */ + int newPairs; /* pairs for second round of testing */ + pairResults* pairData; /* paired data info - first pass */ + pairResults* pairData2; /* paired data info - second pass */ + + MPI_Init(&argc, &argv); + + /* how many hosts are there? */ + MPI_Comm_size(MPI_COMM_WORLD, &ranks); + if (ranks < 2) + { + fprintf(stderr, "Must have at least 2 hosts to run deviation test\n"); + MPI_Finalize(); + return 0; + } + + /* set globals */ + newPairs = 0; + + /* parse command line arguments */ + if (parseInputParameters(argc, argv) < 0) + { + MPI_Finalize(); + exit(2); + } + + /* what is my rank */ + MPI_Comm_rank(MPI_COMM_WORLD, &myrank); + + /* space test data down one line to start out with */ + if (myrank == 0) + printf("\n"); + + /* get memory for host names */ + hostList = malloc(sizeof(hostListing) * ranks); + assert(hostList); + + /* calculate how many pairs we need for testing */ + if (concurrent == true) + { + doubles = pairs = ranks / 2; + if (ranks % 2 != 0) + pairs++; + } + else + doubles = pairs = ranks - 1; + + /* get memory for tests */ + pairData = malloc(sizeof(pairResults) * ranks); + assert(pairData); + initPairs(&pairData[0], ranks); + + /* get memory for second round of pair testing */ + if (myrank == 0) + { + pairData2 = malloc(sizeof(pairResults) * ranks); + assert(pairData2); + initPairs(&pairData2[0], ranks); + } + + if (debug == true) + { + printf( + "Rank %u reports ranks %u pairs %u doubles %u hostList %u pairData %u\n", + myrank, ranks, pairs, doubles, (unsigned)sizeof(hostListing) * ranks, + (unsigned)sizeof(pairResults) * pairs); + } + + /* gather the list of hostnames */ + MPI_Allgather((void *)pairedHostname(), HOSTNAME_MAXLEN, MPI_CHAR, + hostList, HOSTNAME_MAXLEN, MPI_CHAR, MPI_COMM_WORLD); + + /* get the list of hosts */ + if (myrank == 0 && debug == true) + { + for (hosts = 0; hosts < ranks; hosts++) + printf("Rank %u: %s\n", hosts, hostList[hosts].hostname); + } + + /* if user supplied a baseline host then use that host in sequential tests */ + if (strlen(baselineHost) > 0) + { + int found = false; + for (hosts = 0; hosts < ranks; hosts++) + { + if (strcmp(hostList[hosts].hostname, baselineHost) == 0) + { + baselineRank = hosts; + found = true; + break; + } + } + if (found == false) + { + if (myrank == 0) + printf("Baseline host not found: %s\n", baselineHost); + strcpy(baselineHost, hostList[0].hostname); + baselineRank = 0; + trialPass = true; + } + } + /* otherwise setup to do a trial run to find the best baseline host */ + else + { + strcpy(baselineHost, hostList[0].hostname); + trialPass = true; + } + + /* if no baseline host then find the best host */ + if (trialPass == true) + { + /* only test the first 20 hosts */ + if (ranks < TRIAL_PAIRS*2) + trialPairs = ranks / 2; + else + trialPairs = TRIAL_PAIRS; + + if (myrank == 0) + { + printf("Trial runs of %u hosts are being performed to find\n" + "the best host since no baseline host was specified.\n", + trialPairs * 2); + } + +#ifdef DEBUG + printf("Pairs %u doubles %u trialPairs %u hosts %u\n", + pairs, doubles, trialPairs, ranks); +#endif + + MPI_Barrier(MPI_COMM_WORLD); + + if (myrank == 0) + createPairs(/* concurrent */ true, pairData); + + MPI_Barrier(MPI_COMM_WORLD); + + hostBroadcast(&pairData[0]); + + MPI_Barrier(MPI_COMM_WORLD); + + /* run quick concurrent latency test on hosts with a larger + packet size than normal so it is indicitive of both best + latency and bandwidth. Bandwidth will be better indicator */ + runConcurrentLatency(trialPairs, trialPairs, BANDWIDTH_SIZE, BANDWIDTH_LOOP, &pairData[0]); + + MPI_Barrier(MPI_COMM_WORLD); + + /* look for the best combo */ + if (myrank == 0) + { + baselineRank = findBaselineHost(trialPairs, BANDWIDTH_LOOP, &pairData[0]); + strcpy(baselineHost, hostList[baselineRank].hostname); + } + /* trial pass is done */ + trialPass = false; + } + if (myrank == 0) + printf("\nBaseline host is %s (%d)\n\n", + hostList[baselineRank].hostname, baselineRank); + + MPI_Barrier(MPI_COMM_WORLD); + + /* now that we have the list of hosts create the initial pairs */ + initPairs(&pairData[0], ranks); + if (myrank == 0) + createPairs(concurrent, pairData); + + MPI_Barrier(MPI_COMM_WORLD); + + /* distribute the pair list to all ranks */ + hostBroadcast(&pairData[0]); + + MPI_Barrier(MPI_COMM_WORLD); + + /* run the latency tests */ + if (concurrent == true) + runConcurrentLatency(pairs, doubles, latencySize, latencyLoop, &pairData[0]); + else + runSequentialLatency(pairs, latencySize, latencyLoop, &pairData[0]); + + /* run the bandwidth tests */ + if (concurrent == true) + runConcurrentBandwidth(pairs, doubles, bandwidthSize, bandwidthLoop, &pairData[0]); + else + runSequentialBandwidth(pairs, bandwidthSize, bandwidthLoop, &pairData[0]); + + MPI_Barrier(MPI_COMM_WORLD); + + /* report latency and bandwidth */ + if (myrank == 0) + { + reportTestResults(pairs, &pairData[0]); + } + + /* if sequential testing then we are done */ + if (concurrent == false) + { + MPI_Finalize(); + return 0; + } + + /* if we are running concurrent tests then find all of the failed ones and + pair them against the baseline rank for a sequential test */ + secondPass = true; + + /* find how many concurrent test failed */ + if (myrank == 0) + { + for (pair = 0; pair < pairs; pair++) + { + /* keep track of the number of failed pairs */ + if (pairData[pair].failed == true) + { + /* if the original send pair was the baselinerank or rank 0 not in the + first pair then we only need one pair for the new one */ + if (pairData[pair].sendRank == baselineRank) + newPairs++; + else if (pairData[pair].receiveRank == baselineRank) + newPairs++; + else if (pair != 0 && pairData[pair].sendRank == 0) + newPairs++; + else + newPairs += 2; + } + } + } + + if (myrank == 0 && newPairs != 0) + { + /* create new sequential pairs for round 2 of testing */ + pair2 = 0; + for (pair = 0; pair < pairs; pair++) + { + if (pairData[pair].failed == true) + { + /* pair the baseline rank against the failed send rank - only + allow rank 0 send rank to occupy the first pair */ + if (pair == 0) + { + if (pairData[pair].sendRank != baselineRank) + { + pairData2[pair2].receiveRank = pairData[pair].sendRank; + strcpy(pairData2[pair2].receiveHostname, + pairData[pair].sendHostname); + pair2++; + } + } + else + { + if (pairData[pair].sendRank != 0 && + pairData[pair].sendRank != baselineRank) + { + pairData2[pair2].receiveRank = pairData[pair].sendRank; + strcpy(pairData2[pair2].receiveHostname, + pairData[pair].sendHostname); + pair2++; + } + } + + /* pair the baseline rank against the failed receive rank */ + if (pairData[pair].receiveRank != baselineRank) + { + pairData2[pair2].receiveRank = pairData[pair].receiveRank; + strcpy(pairData2[pair2].receiveHostname, + pairData[pair].receiveHostname); + pair2++; + } + } + } + + /* all send hosts for round 2 will use the baseline rank */ + for (pair2 = 0; pair2 < newPairs; pair2++) + { + pairData2[pair2].sendRank = baselineRank; + strcpy(pairData2[pair2].sendHostname, baselineHost); + pairData2[pair2].valid = true; + pairData2[pair2].alone = true; +#ifdef DEBUG + printf("Second Round Pair %u send rank %u receive rank %u\n", + pair2, pairData2[pair2].sendRank, pairData2[pair2].receiveRank); +#endif + } + } + + /* clear out the first round of test pairs so we can get ready for the + second round and then copy second round to first round pair array */ + initPairs(&pairData[0], ranks); + if (myrank == 0 && newPairs != 0) + { + for (pair = 0; pair < newPairs; pair++) + { + pairData[pair] = pairData2[pair]; + } + } + +#ifdef DEBUG + if (myrank == 0) + { + for (pair = 0; pair < ranks; pair++) + { + printf( + "Second Round Pair %u send rank %u receive rank %u valid %u\n", + pair, pairData[pair].sendRank, pairData[pair].receiveRank, + pairData[pair].valid); + } + } +#endif + + /* wait for all communications to complete */ + MPI_Barrier(MPI_COMM_WORLD); + + /* broadcast pair data to all hosts */ + hostBroadcast(&pairData[0]); + + /* if there are no second pairs to test then we are done in all processes + - we know this since the receive rank of the first pair will be invalid */ + if (pairData[0].valid == false) + { + MPI_Finalize(); + return 0; + } + + /* run the second round of latency tests */ + runSequentialLatency(ranks, latencySize, latencyLoop, &pairData[0]); + + /* run the second round of bandwidth tests */ + runSequentialBandwidth(ranks, bandwidthSize, bandwidthLoop, &pairData[0]); + + /* report latency and bandwidth */ + concurrent = false; + if (myrank == 0 && newPairs != 0) + { + reportTestResults(newPairs, &pairData[0]); + } + + MPI_Finalize(); + return 0; +} + +/* duration is in sec, returns latency in usec */ +/* each loop is a round trip, so we half it to get 1 way latency */ +double +compute_latency(double duration, int loop) +{ + return (duration * 1.0e6) / (2.0 * loop); +} +double +compute_pair_latency(int pair, int loop, pairResults *pairData) +{ + return compute_latency( pairData[pair].latencyTimeEnd + - pairData[pair].latencyTimeStart, loop); +} + +/* size in bytes, duration in seconds, returns MB/s */ +/* Note we use the OSU definition of 1.0e6=MB */ +double +compute_bandwidth(double duration, int size, int loop) +{ + return (((size/1.0e6) * loop) / duration) * (bandwidthBiDir?2:1); +} + +double +compute_pair_bandwidth(int pair, int size, int loop, pairResults *pairData) +{ + return compute_bandwidth( + pairData[pair].bandwidthTimeEnd - pairData[pair].bandwidthTimeStart, size, loop); +} + +/* initialize pairs */ +static void +initPairs(pairResults *pairData, int pairs) +{ + int pair; + + for (pair = 0; pair < pairs; pair++) + { + pairData[pair].valid = false; + pairData[pair].sendRank = 0; + pairData[pair].receiveRank = 0; + pairData[pair].latency = 0; + pairData[pair].bandwidth = 0; + pairData[pair].latencyTimeStart = 0; + pairData[pair].latencyTimeEnd = 0; + pairData[pair].latencyFailed = false; + pairData[pair].bandwidthTimeStart = 0; + pairData[pair].bandwidthTimeEnd = 0; + pairData[pair].bandwidthFailed = false; + pairData[pair].sendHostname[0] = 0; + pairData[pair].receiveHostname[0] = 0; + pairData[pair].alone = true; + pairData[pair].failed = false; + } +} + +/* find the baseline host for testing */ +static int +findBaselineHost(int pairs, int loop, pairResults *pairData) +{ + int pair; + int bestLatencyPair = 0; + + for (pair = 0; pair < pairs; pair++) + { +#ifdef DEBUG + printf("pair %u valid=%d\n", pair, pairData[pair].valid); +#endif + if (pairData[pair].valid == false) + continue; + + /* calculate latency between pairs */ + pairData[pair].latency = compute_pair_latency(pair, loop, pairData); + + if (debug) + printf("Trial Latency %.2f usec %s (%u) <-> %s (%u)\n", + pairData[pair].latency, + pairData[pair].sendHostname, pairData[pair].sendRank, + pairData[pair].receiveHostname, pairData[pair].receiveRank); + + /* find min latency */ + if (pair == 0) + { + latencyMin = pairData[0].latency; + if (debug) + printf("Best Candidate: %s (%u)\n", + pairData[pair].sendHostname, pairData[pair].sendRank); + } + else + { + if (pairData[pair].latency < latencyMin) + { + latencyMin = pairData[pair].latency; + bestLatencyPair = pair; + if (debug) + printf("Best Candidate: %s (%u)\n", + pairData[pair].sendHostname, pairData[pair].sendRank); + } + } + } + /* return the sender in the best latency pair */ + return pairData[bestLatencyPair].sendRank; +} + +/* report test results */ +static void +reportTestResults(int pairs, pairResults *pairData) +{ + int pair; + double pairPercentage; + double latencyRange; + double latencyWorstPct; + double bandwidthRange; + double bandwidthWorstPct; + int latencyFailed = false; + int bandwidthFailed = false; + + /* report latency and bandwidth */ + /* we only compute average on 1st pass, too few entries on second pass */ + if (! secondPass) { + latencyAvg = 0; + bandwidthAvg = 0; + } + for (pair = 0; pair < pairs; pair++) + { + /* calculate latency between pairs */ + pairData[pair].latency = compute_pair_latency(pair, latencyLoop, pairData); + + /* find max, min and avg latency */ + if (! secondPass) + latencyAvg += pairData[pair].latency / pairs; + if (pair == 0) + { + latencyMax = pairData[0].latency; + latencyMin = pairData[0].latency; + } else { + if (pairData[pair].latency > latencyMax) + latencyMax = pairData[pair].latency; + if (pairData[pair].latency < latencyMin) + latencyMin = pairData[pair].latency; + } + + /* calculate bandwidth between pairs */ + pairData[pair].bandwidth = compute_pair_bandwidth(pair, bandwidthSize, + bandwidthLoop, pairData); + + /* find max, min and avg bandwidth */ + if (! secondPass) + bandwidthAvg += pairData[pair].bandwidth / pairs; + if (pair == 0) + { + bandwidthMax = pairData[0].bandwidth; + bandwidthMin = pairData[0].bandwidth; + } else { + if (pairData[pair].bandwidth > bandwidthMax) + bandwidthMax = pairData[pair].bandwidth; + if (pairData[pair].bandwidth < bandwidthMin) + bandwidthMin = pairData[pair].bandwidth; + } + } + + /* we reuse thresholds from 1st pass, too few entries on 2nd pass */ + if (! secondPass) { + /* calculate upper and lower latency thresholds based on tolerance */ + /* tolerance is expressed as % of Base */ + if (compare_best) + latencyBase = latencyMin; + else + latencyBase = latencyAvg; + if (compute_lat_thres) { + /*if user specifies both delta and tolerance, use the less strict*/ + /*If neither are specified, use least strict of defaults */ + if((!use_latdelta && !use_lattol) || (use_latdelta && use_lattol)) { + latencyUpper = latencyBase * (1 + (latencyTolerance / 100.0)); + if (latencyUpper < latencyBase + latencyDelta) + latencyUpper = latencyBase + latencyDelta; + } + else if(use_lattol) { + latencyUpper = latencyBase * (1 + (latencyTolerance / 100.0)); + } + else if(use_latdelta) { + latencyUpper = latencyBase + latencyDelta; + } + } + + /* calculate upper and lower bandwidth thresholds based on tolerance */ + /* tolerance is expressed as % of Base */ + if (compare_best) + bandwidthBase = bandwidthMax; + else + bandwidthBase = bandwidthAvg; + if (compute_bw_thres) { + /*if user specifies both delta and tolerance, use the less strict*/ + /*If neither are specified, use least strict of defaults */ + if((!use_bwdelta && !use_bwtol) || (use_bwdelta && use_bwtol)) { + bandwidthLower = bandwidthBase * (1 - (bandwidthTolerance / 100.0)); + if (bandwidthLower > bandwidthBase - bandwidthDelta) + bandwidthLower = bandwidthBase - bandwidthDelta; + } + else if(use_bwtol) { + bandwidthLower = bandwidthBase * (1 - (bandwidthTolerance / 100.0)); + } + else if(use_bwdelta) { + bandwidthLower = bandwidthBase - bandwidthDelta; + } + + } + } + + /* calculate the middle of performance range */ + /*latencyMid = latencyMin + ((latencyMax - latencyMin) / 2); */ + /*bandwidthMid = bandwidthMin + ((bandwidthMax - bandwidthMin) / 2); */ + + /* latencyWorstPct could be > 100% when Max is multiple of Min */ + latencyRange = ((latencyMax - latencyMin) / latencyMin) * 100; + latencyWorstPct = ((latencyMax - latencyBase) / latencyBase) * 100; + bandwidthRange = ((bandwidthMax - bandwidthMin) / bandwidthMax) * 100; + bandwidthWorstPct = ((bandwidthMin - bandwidthBase) / bandwidthBase) * 100; + + /* scan through the pairs again and see which ones violate the thresholds */ + for (pair = 0; pair < pairs; pair++) + { + pairData[pair].failed = false; + if (pairData[pair].latency > latencyUpper) + { + pairData[pair].failed = true; + pairData[pair].latencyFailed = true; + latencyFailed = true; + } + if (pairData[pair].bandwidth < bandwidthLower) + { + pairData[pair].failed = true; + pairData[pair].bandwidthFailed = true; + bandwidthFailed = true; + } + } + + /* now output the results */ + printf("\n"); + if (secondPass == false) + { + if (concurrent == true) + printf("Concurrent MPI Performance Test Results\n"); + else + printf("Sequential MPI Performance Test Results\n"); + } else { + printf("Second Pass - Sequential MPI Performance Test Results\n"); + } + + printf(" Latency Summary:\n"); + printf(" Min: %.2f usec, Max: %.2f usec", latencyMin, latencyMax); + if (! secondPass) + printf(", Avg: %.2f usec", latencyAvg); + if (compare_best) { + printf("\n Worst: %+.1f%% of Min\n", latencyWorstPct); + } else { + printf("\n Range: %+.1f%% of Min, Worst: %+.1f%% of Avg\n", + latencyRange, latencyWorstPct); + } + if (! compute_lat_thres) { + printf(" Cfg: Threshold: %.2f usec\n", latencyUpper); + } else if (compare_best) { + printf(" Cfg: Tolerance: +%u%% of Min, Delta: %.2f usec, Threshold: %.2f usec\n", + latencyTolerance, latencyDelta, latencyUpper); + } else if (compute_lat_thres) { + printf(" Cfg: Tolerance: +%u%% of Avg, Delta: %.2f usec, Threshold: %.2f usec\n", + latencyTolerance, latencyDelta, latencyUpper); + } + printf(" Message Size: %d, Loops: %d\n", + latencySize, latencyLoop); + + printf("\n"); + + printf(" Bandwidth Summary:\n"); + printf(" Min: %.1f MB/s, Max: %.1f MB/s", bandwidthMin, bandwidthMax); + if (! secondPass) + printf(", Avg: %.1f MB/s", bandwidthAvg); + if (compare_best) { + printf("\n Worst: %+.1f%% of Max\n", bandwidthWorstPct); + } else { + printf("\n Range: -%.1f%% of Max, Worst: %+.1f%% of Avg\n", + bandwidthRange, bandwidthWorstPct); + } + if (! compute_bw_thres) { + printf(" Cfg: Threshold: %.1f MB/s\n", bandwidthLower); + } else if (compare_best) { + printf(" Cfg: Tolerance: -%u%% of Max, Delta: %.1f MB/s, Threshold: %.1f MB/s\n", + bandwidthTolerance, bandwidthDelta, bandwidthLower); + } else { + printf(" Cfg: Tolerance: -%u%% of Avg, Delta: %.1f MB/s, Threshold: %.1f MB/s\n", + bandwidthTolerance, bandwidthDelta, bandwidthLower); + } + printf(" Message Size: %d, Loops: %d BiDir: %s\n", + bandwidthSize, bandwidthLoop, bandwidthBiDir?"yes":"no"); + + if (verbose || latencyFailed) + { + /* report latency stats for each pair */ + printf("\n Latency Details:\n"); + printf(" Result Lat Dev Host (rank) <-> Host (rank) \n"); + for (pair = 0; pair < pairs; pair++) + { + /* skip tests that passed */ + if (! pairData[pair].latencyFailed && ! verbose) + continue; + + pairPercentage = + ((pairData[pair].latency - latencyBase) / latencyBase) * 100; + printf(" %6s %7.2f %+6.1f%% %s (%d) <-> %s (%d)\n", + pairData[pair].latencyFailed ? + (concurrent? "RETRY " : "FAILED") : "PASSED", + pairData[pair].latency, pairPercentage, + pairData[pair].sendHostname, pairData[pair].sendRank, + pairData[pair].receiveHostname, pairData[pair].receiveRank); + } + } + + if (verbose || bandwidthFailed) + { + /* report bandwidth stats for each pair */ + printf("\n Bandwidth Details:\n"); + printf(" Result BW Dev Host (rank) --> Host (rank) \n"); + /* report bandwidth stats for each pair */ + for (pair = 0; pair < pairs; pair++) + { + /* skip tests that passed */ + if (! pairData[pair].bandwidthFailed && ! verbose) + continue; + + pairPercentage = + ((pairData[pair].bandwidth - bandwidthBase) / bandwidthBase) * 100; + printf(" %6s %7.1f %+6.1f%% %s (%d) --> %s (%d)\n", + pairData[pair].bandwidthFailed ? + (concurrent? "RETRY " : "FAILED") : "PASSED", + pairData[pair].bandwidth, pairPercentage, + pairData[pair].sendHostname, pairData[pair].sendRank, + pairData[pair].receiveHostname, pairData[pair].receiveRank); + } + } + + printf("\n"); + if ((latencyFailed || bandwidthFailed) && concurrent) { + printf("Partial Retry using Sequential with Baseline Host to determine failed host\n"); + printf("\nBaseline host is %s (%d)\n\n", + hostList[baselineRank].hostname, baselineRank); + } else { + printf("Latency: %s\n", latencyFailed ? "FAILED" : "PASSED"); + printf("Bandwidth: %s\n", bandwidthFailed ? "FAILED" : "PASSED"); + } +} + +/* parse bandwidth and latency input parameters */ +static int +parseInputParameters(int argc,char *argv[]) +{ + int myrank; + int opt; + char *p; + + /* what is my rank */ + MPI_Comm_rank(MPI_COMM_WORLD, &myrank); + + /* parse args */ + for (opt = 1; opt < argc; opt++) + { + if (strcasecmp(argv[opt], "-bwtol") == 0) { + use_bwtol = true; + errno = 0; + opt++; + if (argv[opt]) + bandwidthTolerance = (long)strtoul(argv[opt], &p, 10); + /* since bw tolerance is % of Avg or Max, low BW must be 0-100% */ + if (argv[opt] == NULL || argv[opt] == p || errno || *p + || bandwidthTolerance < 0 || bandwidthTolerance > 100) + { + if (myrank == 0) { + fprintf(stderr, "Invalid bandwidth tolerance: %s\n", argv[opt]?argv[opt]:"required parameter missing"); + fprintf(stderr, + "Bandwidth tolerance must be a percentage from 0 to 100\n"); + Usage(); + } + return -1; + } + } else if (strcasecmp(argv[opt], "-bwdelta") == 0) { + use_bwdelta = true; + errno = 0; + opt++; + if (argv[opt]) + bandwidthDelta = strtod(argv[opt], &p); + if (argv[opt] == NULL || argv[opt] == p || errno || *p + || bandwidthDelta < 0) + { + if (myrank == 0) { + fprintf(stderr, "Invalid bandwidth delta: %s\n", argv[opt]?argv[opt]:"required parameter missing"); + fprintf(stderr, "Bandwidth Delta must be number of MB/s\n"); + Usage(); + } + return -1; + } + } else if (strcasecmp(argv[opt], "-bwthres") == 0) { + compute_bw_thres = false; + errno = 0; + opt++; + if (argv[opt]) + bandwidthLower = strtod(argv[opt], &p); + if (argv[opt] == NULL || argv[opt] == p || errno || *p + || bandwidthLower < 0) + { + if (myrank == 0) { + fprintf(stderr, "Invalid bandwidth threshold: %s\n", argv[opt]?argv[opt]:"required parameter missing"); + fprintf(stderr, "Bandwidth Threshold must be number of MB/s\n"); + Usage(); + } + return -1; + } + } else if (strcasecmp(argv[opt], "-bwloop") == 0) { + errno = 0; + opt++; + if (argv[opt]) + bandwidthLoop = (long)strtoul(argv[opt], &p, 10); + if (argv[opt] == NULL || argv[opt] == p || errno || *p + || bandwidthLoop <= 0 ) + { + if (myrank == 0) { + fprintf(stderr, "Invalid bandwidth loop count: %s\n", argv[opt]?argv[opt]:"required parameter missing"); + Usage(); + } + return -1; + } + } else if (strcasecmp(argv[opt], "-bwsize") == 0) { + errno = 0; + opt++; + if (argv[opt]) + bandwidthSize = (long)strtoul(argv[opt], &p, 10); + if (argv[opt] == NULL || argv[opt] == p || errno || *p + || bandwidthSize < 0 ) + { + if (myrank == 0) { + fprintf(stderr, "Invalid bandwidth message size: %s\n", argv[opt]?argv[opt]:"required parameter missing"); + Usage(); + } + return -1; + } + } else if (strcasecmp(argv[opt], "-bwbidir") == 0) { + bandwidthBiDir = true; + } else if (strcasecmp(argv[opt], "-bwunidir") == 0) { + bandwidthBiDir = false; + } else if (strcasecmp(argv[opt], "-lattol") == 0) { + use_lattol = true; + errno = 0; + opt++; + if (argv[opt]) + latencyTolerance = (long)strtoul(argv[opt], &p, 10); + /* Max latency > 2x of Avg or Min is possible, so allow 0-500% */ + if (argv[opt] == NULL || argv[opt] == p || errno || *p + || latencyTolerance < 0 || latencyTolerance > 500) + { + if (myrank == 0) { + fprintf(stderr, "Invalid latency tolerance: %s\n", argv[opt]?argv[opt]:"required parameter missing"); + fprintf(stderr, + "Latency tolerance must be a percentage from 0 to 500\n"); + Usage(); + } + return -1; + } + } else if (strcasecmp(argv[opt], "-latdelta") == 0) { + use_latdelta = true; + errno = 0; + opt++; + if (argv[opt]) + latencyDelta = strtod(argv[opt], &p); + if (argv[opt] == NULL || argv[opt] == p || errno || *p + || latencyDelta < 0) + { + if (myrank == 0) { + fprintf(stderr, "Invalid latency delta: %s\n", argv[opt]?argv[opt]:"required parameter missing"); + fprintf(stderr, "Latency Delta must be number of usec\n"); + Usage(); + } + return -1; + } + } else if (strcasecmp(argv[opt], "-latthres") == 0) { + compute_lat_thres = false; + errno = 0; + opt++; + if (argv[opt]) + latencyUpper = strtod(argv[opt], &p); + if (argv[opt] == NULL || argv[opt] == p || errno || *p + || latencyUpper < 0) + { + if (myrank == 0) { + fprintf(stderr, "Invalid latency threshold: %s\n", argv[opt]?argv[opt]:"required parameter missing"); + fprintf(stderr, "Latency Threshold must be number of usec\n"); + Usage(); + } + return -1; + } + } else if (strcasecmp(argv[opt], "-latloop") == 0) { + errno = 0; + opt++; + if (argv[opt]) + latencyLoop = (long)strtoul(argv[opt], &p, 10); + if (argv[opt] == NULL || argv[opt] == p || errno || *p + || latencyLoop <= 0 ) + { + if (myrank == 0) { + fprintf(stderr, "Invalid latency loop count: %s\n", argv[opt]?argv[opt]:"required parameter missing"); + Usage(); + } + return -1; + } + } else if (strcasecmp(argv[opt], "-latsize") == 0) { + errno = 0; + opt++; + if (argv[opt]) + latencySize = (long)strtoul(argv[opt], &p, 10); + if (argv[opt] == NULL || argv[opt] == p || errno || *p + || latencySize < 0 ) + { + if (myrank == 0) { + fprintf(stderr, "Invalid latency message size: %s\n", argv[opt]?argv[opt]:"required parameter missing"); + Usage(); + } + return -1; + } + } else if (strcasecmp(argv[opt], "-h") == 0) { + if (argv[++opt] != NULL) { + strcpy(baselineHost, argv[opt]); + } else { + if (myrank == 0) { + fprintf(stderr, "-h argument requires hostname\n"); + Usage(); + } + return -1; + } + } else if (strcasecmp(argv[opt], "-v") == 0) + verbose = true; + else if (strcasecmp(argv[opt], "-vv") == 0) + verbose = debug = true; + else if (strcasecmp(argv[opt], "-c") == 0) + concurrent = true; + else if (strcasecmp(argv[opt], "-b") == 0) + compare_best = true; + else { + if (myrank == 0) { + fprintf(stderr, "Invalid Argument: %s\n", argv[opt]); + Usage(); + } + return -1; + } + } + + if (myrank == 0 && debug == true) + printf("Settings - verbose %u concurrent %u debug %u\n", + verbose, concurrent, debug); + + return 0; +} + +/* create pairings */ +static void +createPairs(int parallel, pairResults* pairData) +{ + int pair = 0; + int host = 0; + int hosts; + int ranks; + int myrank; + + /* how many hosts are there? */ + MPI_Comm_size(MPI_COMM_WORLD, &ranks); + + /* what is my rank */ + MPI_Comm_rank(MPI_COMM_WORLD, &myrank); + + hosts = ranks; + + while (hosts > 0) + { + /* if creating trial pairs then only create up to trialPairs of them */ + if (trialPass == true && pair > trialPairs - 1) + return; + + /* if running concurrent tests then pair up each host with one of the + other hosts in the list */ + if (parallel == true) + { + /* if we still have at least 2 hosts then set them both init a pair */ + if (hosts >= 2) + { + pairData[pair].sendRank = host; + strcpy(pairData[pair].sendHostname, hostList[host++].hostname); + pairData[pair].receiveRank = host; + strcpy(pairData[pair].receiveHostname, hostList[host++].hostname); + pairData[pair].alone = false; + hosts -= 2; + } + /* otherwise pair the last one with the first one - but it will + run later */ + else + { + pairData[pair].sendRank = 0; + strcpy(pairData[pair].sendHostname, hostList[0].hostname); + pairData[pair].receiveRank = host; + strcpy(pairData[pair].receiveHostname, hostList[host++].hostname); + pairData[pair].alone = true; + hosts -= 1; + } + } + /* must be running sequential tests from the baseline rank */ + else + { + if (host == baselineRank) + { + host++; + hosts--; + continue; + } + pairData[pair].sendRank = baselineRank; + strcpy(pairData[pair].sendHostname, baselineHost); + pairData[pair].receiveRank = host; + strcpy(pairData[pair].receiveHostname, hostList[host++].hostname); + pairData[pair].alone = true; + hosts -= 1; + } + pairData[pair].valid = true; + if (myrank == 0 && debug == true) + { + printf("createPairs() Pair %u send rank %u receive rank %u\n", + pair, pairData[pair].sendRank, pairData[pair].receiveRank); + } + pair++; + } +} + +/* this is the heart of the latency test */ +/* because the test is a ping-pong type latency test, their is no need for a + * barrier. The first packet (which is part of warmup) will implicitly + * synchronize the sender/receiver pair + */ +void do_latency(int pair, int myrank, int size, int loop, pairResults* pairData) +{ + int iterations; + MPI_Status stat; + + if (pairData[pair].sendRank == myrank) + { + for (iterations = 0; iterations < loop + LATENCY_WARMUP; iterations++) + { + if (iterations == LATENCY_WARMUP) + { + /* snapshot of start time */ + pairData[pair].latencyTimeStart = MPI_Wtime(); + } + + MPI_Send(sendBuffer, size, MPI_CHAR, pairData[pair].receiveRank, + iterations, MPI_COMM_WORLD); + MPI_Recv(receiveBuffer, size, MPI_CHAR, pairData[pair].receiveRank, + iterations + 1000, MPI_COMM_WORLD, &stat); + } + /* snapshot of end time */ + pairData[pair].latencyTimeEnd = MPI_Wtime(); + + if (debug == true) + { + printf( + "Concurrent Latency %.2f usec %s (%u) <-> %s (%u)\n", + compute_pair_latency(pair, loop, pairData), + pairData[pair].sendHostname, pairData[pair].sendRank, + pairData[pair].receiveHostname, pairData[pair].receiveRank); + } + } else if (pairData[pair].receiveRank == myrank) { + for (iterations = 0; iterations < loop + LATENCY_WARMUP; iterations++) + { + MPI_Recv(receiveBuffer, size, MPI_CHAR, pairData[pair].sendRank, + iterations, MPI_COMM_WORLD, &stat); + MPI_Send(sendBuffer, size, MPI_CHAR, pairData[pair].sendRank, + iterations + 1000, MPI_COMM_WORLD); + } + } +} + +/* run concurrent latency test between pairs */ +static void +runConcurrentLatency(int pairs, int doubles, int size, int loop, pairResults* pairData) +{ + int bytes; + int pair; + int validPairs = 0; + int myrank; + + /* what is my rank */ + MPI_Comm_rank(MPI_COMM_WORLD, &myrank); + + /* how many pairs are valid */ + for (pair = 0; pair < pairs; pair++) + { + if (pairData[pair].valid == true) + validPairs++; + } + if (myrank == 0 && secondPass == false && debug == false && trialPass == false) + printf("Running Concurrent MPI Latency Tests - Pairs %u Testing ", + validPairs); + + if (myrank == 0 && debug == true) + printf("\n"); + + /* initialize the buffer data */ + for (bytes = 0; bytes < size; bytes++) + { + sendBuffer[bytes]= 'a'; + receiveBuffer[bytes]= 'b'; + } + + /* now run the latency tests concurrently for all of the complete pairs */ + /* we sync up once at the start, then let each test run independently + * so they all run concurrently + */ + MPI_Barrier(MPI_COMM_WORLD); + for (pair = 0; pair < doubles; pair++) + { + /* skip if not valid */ + if (pairData[pair].valid == false) + continue; + + if (myrank == 0 && debug == false && trialPass == false) + { + printf("%5u", pair + 1); + fflush(stdout); + } + do_latency(pair, myrank, size, loop, pairData); + if (myrank == 0 && debug == false && trialPass == false) + { + printf("\b\b\b\b\b"); + fflush(stdout); + } + } + + MPI_Barrier(MPI_COMM_WORLD); /* just to be safe */ + /* now do the odd pair against rank 0 */ + for (pair = doubles; pair < pairs; pair++) + { + /* skip if not valid */ + if (pairData[pair].valid == false) + continue; + + if (myrank == 0 && debug == false && trialPass == false) + { + printf("%5u", pair + 1); + fflush(stdout); + } + do_latency(pair, myrank, size, loop, pairData); + if (myrank == 0 && debug == false && trialPass == false) + { + printf("\b\b\b\b\b"); + fflush(stdout); + } + } + MPI_Barrier(MPI_COMM_WORLD); + if (myrank == 0 && trialPass == false) + printf("\n"); + + /* report test pair data */ + hostReport(&pairData[0], /* latency */ true); + + /* wait for all communications to complete */ + MPI_Barrier(MPI_COMM_WORLD); +} + +/* run sequential latency test between pairs */ +static void +runSequentialLatency(int pairs, int size, int loop, pairResults* pairData) +{ + int bytes; + int pair; + int validPairs = 0; + int myrank; + + /* what is my rank */ + MPI_Comm_rank(MPI_COMM_WORLD, &myrank); + + /* how many valid pairs */ + for (pair = 0; pair < pairs; pair++) + { + if (pairData[pair].valid == true) + validPairs++; + } + if (myrank == 0 && secondPass == false && debug == false) + printf("Running Sequential MPI Latency Tests - Pairs %u Testing ", + validPairs); + + if (myrank == 0 && secondPass == true && debug == false) + printf("Second Pass - Running Sequential MPI Latency Tests - Pairs %u Testing ", + validPairs); + + if (myrank == 0 && debug == true) + printf("\n"); + + /* initialize the buffer data */ + for (bytes = 0; bytes < size; bytes++) + { + sendBuffer[bytes]= 'a'; + receiveBuffer[bytes]= 'b'; + } + + for (pair = 0; pair < pairs; pair++) + { + /* skip if not valid */ + if (pairData[pair].valid == false) + { + MPI_Barrier(MPI_COMM_WORLD); + continue; + } + + if (myrank == 0 && debug == false) + { + printf("%5u", pair + 1); + fflush(stdout); + } + + MPI_Barrier(MPI_COMM_WORLD); + do_latency(pair, myrank, size, loop, pairData); + if (myrank == 0 && debug == false) + { + printf("\b\b\b\b\b"); + fflush(stdout); + } + } + MPI_Barrier(MPI_COMM_WORLD); + if (myrank == 0) + printf("\n"); + + /* report test pair data */ + hostReport(&pairData[0], /* latency */ true); + + /* wait for all communications to complete */ + MPI_Barrier(MPI_COMM_WORLD); +} + +/* a simple way to synchronize two nodes without using a barrier nor + * collective is to send a round trip packet + */ +void pair_barrier(int pair, int myrank, pairResults* pairData) +{ + MPI_Status stat; + + if (pairData[pair].sendRank == myrank) + { + MPI_Send(sendBuffer, 0, MPI_CHAR, pairData[pair].receiveRank, + 0, MPI_COMM_WORLD); + MPI_Recv(receiveBuffer, 0, MPI_CHAR, pairData[pair].receiveRank, + 1000, MPI_COMM_WORLD, &stat); + } else if (pairData[pair].receiveRank == myrank) { + MPI_Recv(receiveBuffer, 0, MPI_CHAR, pairData[pair].sendRank, + 0, MPI_COMM_WORLD, &stat); + MPI_Send(sendBuffer, 0, MPI_CHAR, pairData[pair].sendRank, + 1000, MPI_COMM_WORLD); + } +} + +/* this is the heart of the bandwidth test */ +void do_bandwidth(int pair, int myrank, int size, int loop, + char *s_buf, char *r_buf, pairResults* pairData) +{ + int iterations; + + /* warmup */ + if (pairData[pair].sendRank == myrank) + { + if (bandwidthBiDir) { + for (iterations = 0; iterations < BANDWIDTH_WARMUP; iterations++) + { + MPI_Irecv(r_buf, size, MPI_CHAR, pairData[pair].receiveRank, + 100, MPI_COMM_WORLD, request2 + iterations); + } + } + for (iterations = 0; iterations < BANDWIDTH_WARMUP; iterations++) + { + MPI_Isend(s_buf, size, MPI_CHAR, pairData[pair].receiveRank, + 100, MPI_COMM_WORLD, request + iterations); + } + MPI_Waitall(BANDWIDTH_WARMUP, request, my_stat); + if (bandwidthBiDir) + MPI_Waitall(BANDWIDTH_WARMUP, request2, my_stat); + MPI_Recv(r_buf, 4, MPI_CHAR, pairData[pair].receiveRank, + 101, MPI_COMM_WORLD, &my_stat[0]); + } + else if (pairData[pair].receiveRank == myrank) + { + for (iterations = 0; iterations < BANDWIDTH_WARMUP; iterations++) + { + MPI_Irecv(r_buf, size, MPI_CHAR, pairData[pair].sendRank, + 100, MPI_COMM_WORLD, request + iterations); + } + if (bandwidthBiDir) { + for (iterations = 0; iterations < BANDWIDTH_WARMUP; iterations++) + { + MPI_Isend(s_buf, size, MPI_CHAR, pairData[pair].sendRank, + 100, MPI_COMM_WORLD, request2 + iterations); + } + } + MPI_Waitall(BANDWIDTH_WARMUP, request, my_stat); + if (bandwidthBiDir) + MPI_Waitall(BANDWIDTH_WARMUP, request2, my_stat); + MPI_Send(s_buf, 4, MPI_CHAR, pairData[pair].sendRank, 101, MPI_COMM_WORLD); + } + + pair_barrier(pair, myrank, pairData); + + if (pairData[pair].sendRank == myrank) + { + /* snapshot of start time */ + pairData[pair].bandwidthTimeStart = MPI_Wtime(); + + if (bandwidthBiDir) { + for (iterations = 0; iterations < loop; iterations++) + { + MPI_Irecv(r_buf, size, MPI_CHAR, pairData[pair].receiveRank, + 100, MPI_COMM_WORLD, request2 + iterations); + } + } + + for (iterations = 0; iterations < loop; iterations++) + { + MPI_Isend(s_buf, size, MPI_CHAR, pairData[pair].receiveRank, + 100, MPI_COMM_WORLD, request + iterations); + } + MPI_Waitall(loop, request, my_stat); + if (bandwidthBiDir) + MPI_Waitall(loop, request2, my_stat); + MPI_Recv(r_buf, 4, MPI_CHAR, pairData[pair].receiveRank, + 101, MPI_COMM_WORLD, &my_stat[0]); + + /* snapshot of end time */ + pairData[pair].bandwidthTimeEnd = MPI_Wtime(); + + if (debug == true) + { + printf( + "Concurrent Bandwidth %.1f MB/s %s (%u) --> %s (%u)\n", + compute_pair_bandwidth(pair, bandwidthSize, + bandwidthLoop, pairData), + pairData[pair].sendHostname, pairData[pair].sendRank, + pairData[pair].receiveHostname, pairData[pair].receiveRank); + } + } + else if (pairData[pair].receiveRank == myrank) + { + for (iterations = 0; iterations < loop; iterations++) + { + MPI_Irecv(r_buf, size, MPI_CHAR, pairData[pair].sendRank, + 100, MPI_COMM_WORLD, request + iterations); + } + if (bandwidthBiDir) { + for (iterations = 0; iterations < loop; iterations++) + { + MPI_Isend(s_buf, size, MPI_CHAR, pairData[pair].sendRank, + 100, MPI_COMM_WORLD, request2 + iterations); + } + } + MPI_Waitall(loop, request, my_stat); + if (bandwidthBiDir) + MPI_Waitall(loop, request2, my_stat); + MPI_Send(s_buf, 4, MPI_CHAR, pairData[pair].sendRank, 101, MPI_COMM_WORLD); + } +} + +/* run concurrent bandwidth test between pairs */ +static void +runConcurrentBandwidth(int pairs, int doubles, int size, int loop, pairResults* + pairData) +{ + int bytes; + int pair; + int validPairs = 0; + int myrank; + int pageSize; + char *s_buf, *r_buf; + + /* what is my rank */ + MPI_Comm_rank(MPI_COMM_WORLD, &myrank); + + /* how many are valid */ + for (pair = 0; pair < pairs; pair++) + { + if (pairData[pair].valid == true) + validPairs++; + } + if (myrank == 0 && secondPass == false && debug == false && trialPass == false) + printf("Running Concurrent MPI Bandwidth Tests - Pairs %u Testing ", + validPairs); + + if (myrank == 0 && debug == true) + printf("\n"); + + /* get memory page size for this host */ + pageSize = getpagesize(); + + /* set send and receive buffer pointers */ + s_buf = (char*)(((unsigned long)sendBuffer + (pageSize -1))/pageSize * pageSize); + r_buf = (char*)(((unsigned long)receiveBuffer + (pageSize -1))/pageSize * pageSize); + assert((s_buf != NULL) && (r_buf != NULL)); + + /* initialize the buffer data */ + for (bytes = 0; bytes < size; bytes++) + { + s_buf[bytes]= 'a'; + r_buf[bytes]= 'b'; + } + + MPI_Barrier(MPI_COMM_WORLD); + + for (pair = 0; pair < doubles; pair++) + { + /* skip if not valid */ + if (pairData[pair].valid == false) + continue; + + if (myrank == 0 && debug == false && trialPass == false) + { + printf("%5u", pair + 1); + fflush(stdout); + } + pair_barrier(pair, myrank, pairData); + do_bandwidth(pair, myrank, size, loop, s_buf, r_buf, pairData); + if (myrank == 0 && debug == false && trialPass == false) + { + printf("\b\b\b\b\b"); + fflush(stdout); + } + } + + MPI_Barrier(MPI_COMM_WORLD); /* just to be safe */ + /* now do the odd pair agains rank 0 */ + for (pair = doubles; pair < pairs; pair++) + { + /* skip if not valid */ + if (pairData[pair].valid == false) + continue; + + if (myrank == 0 && debug == false && trialPass == false) + { + printf("%5u", pair + 1); + fflush(stdout); + } + pair_barrier(pair, myrank, pairData); + do_bandwidth(pair, myrank, size, loop, s_buf, r_buf, pairData); + if (myrank == 0 && debug == false && trialPass == false) + { + printf("\b\b\b\b\b"); + fflush(stdout); + } + } + MPI_Barrier(MPI_COMM_WORLD); + if (myrank == 0 && trialPass == false) + printf("\n"); + + /* report test pair data */ + hostReport(&pairData[0], /* bandwidth */ false); + + /* wait for all communications to complete */ + MPI_Barrier(MPI_COMM_WORLD); +} + +/* run sequential bandwidth test between pairs */ +static void +runSequentialBandwidth(int pairs, int size, int loop, pairResults* pairData) +{ + int bytes; + int pair; + int validPairs = 0; + int myrank; + int pageSize; + char *s_buf, *r_buf; + + /* what is my rank */ + MPI_Comm_rank(MPI_COMM_WORLD, &myrank); + + /* how many pairs are valid */ + for (pair = 0; pair < pairs; pair++) + { + if (pairData[pair].valid == true) + validPairs++; + } + if (myrank == 0 && secondPass == false && debug == false) + printf("Running Sequential MPI Bandwidth Tests - Pairs %u Testing ", + validPairs); + + if (myrank == 0 && secondPass == true && debug == false) + printf("Second Pass - Running Sequential MPI Bandwidth Tests - Pairs %u Testing ", + validPairs); + + if (myrank == 0 && debug == true) + printf("\n"); + + /* get memory page size for this host */ + pageSize = getpagesize(); + + /* set send and receive buffer pointers */ + s_buf = (char*)(((unsigned long)sendBuffer + (pageSize -1))/pageSize * pageSize); + r_buf = (char*)(((unsigned long)receiveBuffer + (pageSize -1))/pageSize * pageSize); + assert((s_buf != NULL) && (r_buf != NULL)); + + /* initialize the buffer data */ + for (bytes = 0; bytes < size; bytes++) + { + s_buf[bytes]= 'a'; + r_buf[bytes]= 'b'; + } + + MPI_Barrier(MPI_COMM_WORLD); + + for (pair = 0; pair < pairs; pair++) + { + /* skip if not valid */ + if (pairData[pair].valid == false) + { + MPI_Barrier(MPI_COMM_WORLD); + continue; + } + + if (myrank == 0 && debug == false) + { + printf("%5u", pair + 1); + fflush(stdout); + } + + MPI_Barrier(MPI_COMM_WORLD); + do_bandwidth(pair, myrank, size, loop, s_buf, r_buf, pairData); + if (myrank == 0 && debug == false) + { + printf("\b\b\b\b\b"); + fflush(stdout); + } + } + MPI_Barrier(MPI_COMM_WORLD); + if (myrank == 0) + printf("\n"); + + /* report test pair data */ + hostReport(&pairData[0], /* bandwidth */ false); + + /* wait for all communications to complete */ + MPI_Barrier(MPI_COMM_WORLD); +} + +/* report results from other ranks to rank 0 */ +static void +hostReport(pairResults* pairData, int latency) +{ + int myrank; + int ranks; + int hosts; + MPI_Status stat; + pairResults receiveResults; + + /* what is my rank */ + MPI_Comm_rank(MPI_COMM_WORLD, &myrank); + + /* how many hosts are there? */ + MPI_Comm_size(MPI_COMM_WORLD, &ranks); + + /* send all reports to rank 0 */ + for (hosts = 0; hosts < ranks; hosts++) + { + /* skip invalid pairs */ + if (pairData[hosts].valid == false) + continue; + + if (myrank != 0 && pairData[hosts].sendRank == myrank) + { + MPI_Send(&pairData[hosts], sizeof(pairResults), MPI_CHAR, 0, 1, MPI_COMM_WORLD); +#ifdef DEBUG + printf("Sending latency report from rank %u\n", myrank); +#endif + } + + if (myrank == 0 && pairData[hosts].sendRank != 0) + { + MPI_Recv(&receiveResults, sizeof(pairResults), MPI_CHAR, + pairData[hosts].sendRank, 1, MPI_COMM_WORLD, &stat); + if (latency == true) + { + pairData[hosts].latencyTimeStart = receiveResults.latencyTimeStart; + pairData[hosts].latencyTimeEnd = receiveResults.latencyTimeEnd; +#ifdef DEBUG + printf("Receiving latency report from rank %u\n", + pairData[hosts].sendRank); +#endif + } + else + { + pairData[hosts].bandwidthTimeStart = receiveResults.bandwidthTimeStart; + pairData[hosts].bandwidthTimeEnd = receiveResults.bandwidthTimeEnd; +#ifdef DEBUG + printf("Receiving bandwidth report from rank %u\n", + pairData[hosts].sendRank); +#endif + } + } + } + + /* wait for all communications to complete */ + MPI_Barrier(MPI_COMM_WORLD); +} + +/* broadcast test pairs to all hosts from rank 0 */ +static void +hostBroadcast(pairResults *pairData) +{ + int myrank; + int ranks; + int hosts; + MPI_Status stat; + + /* what is my rank */ + MPI_Comm_rank(MPI_COMM_WORLD, &myrank); + + /* how many hosts are there? */ + MPI_Comm_size(MPI_COMM_WORLD, &ranks); + + /* broadcast pair list to all ranks */ + for (hosts = 0; hosts < ranks; hosts++) + { + if (myrank == 0 && hosts != 0) + { + MPI_Send(&pairData[0], sizeof(pairResults) * ranks, MPI_CHAR, + hosts, 1, MPI_COMM_WORLD); +#ifdef DEBUG + printf("Broadcasting pair list from rank %u to rank %u\n", + myrank, hosts); +#endif + } + } + + /* receive pair list from rank 0 */ + if (myrank != 0) + { + MPI_Recv(&pairData[0], sizeof(pairResults) * ranks, MPI_CHAR, + 0, 1, MPI_COMM_WORLD, &stat); +#ifdef DEBUG + printf("Rank %u receiving broadcast pair list\n", myrank); +#endif + } + + /* wait for all communications to complete */ + MPI_Barrier(MPI_COMM_WORLD); +} + +/* display usage statement */ +static void +Usage() +{ + fprintf(stderr, "Usage: deviation [-bwtol %%] [-bwdelta MBs] [-bwthres MBs]\n" + " [-bwloop count] [-bwsize size] [-bwbidir|-bwunidir]\n" + " [-lattol %%] [-latdelta usec] [-latthres usec]\n" + " [-latloop count] [-latsize size]\n" + " [-c] [-b] [-v] [-vv] [-h reference_host]\n"); + + fprintf(stderr, " -bwtol Percent of bandwidth degradation allowed below Avg value\n"); + fprintf(stderr, " -bwdelta Limit in MB/s of bandwidth degradation allowed below Avg value\n"); + fprintf(stderr, " -bwthres Lower Limit in MB/s of bandwidth allowed\n"); + fprintf(stderr, " -bwloop Number of loops to execute each bandwidth test\n"); + fprintf(stderr, " -bwsize Size of message to use for bandwidth test\n"); + fprintf(stderr, " -bwbidir Perform a bidirectional bandwidth test\n"); + fprintf(stderr, " -bwunidir Perform a unidirectional bandwidth test (default)\n"); + fprintf(stderr, " -lattol Percent of latency degradation allowed above Avg value\n"); + fprintf(stderr, " -latdelta Limit in usec of latency degradation allowed above Avg value\n"); + fprintf(stderr, " -latthres Upper Limit in usec of latency allowed\n"); + fprintf(stderr, " -latloop Number of loops to execute each latency test\n"); + fprintf(stderr, " -latsize Size of message to use for latency test\n"); + fprintf(stderr, " -c Run test pairs concurrently instead of the default of sequential\n"); + fprintf(stderr, " -b When comparing results against tolerance and delta use best\n" " instead of Avg\n"); + fprintf(stderr, " -v verbose output\n"); + fprintf(stderr, " -vv Very verbose output\n"); + fprintf(stderr, " -h Baseline host to use for sequential pairing\n"); + fprintf(stderr, "Both bwtol and bwdelta must be exceeded to fail bandwidth test when both are supplied\n"); + fprintf(stderr, "When bwthres is supplied, bwtol and bwdelta are ignored\n"); + fprintf(stderr, "Both lattol and latdelta must be exceeded to fail latency test when both are supplied\n"); + fprintf(stderr, "When lathres is supplied, lattol and latdelta are ignored\n"); + fprintf(stderr, "\n"); + fprintf(stderr, "For consistency with OSU benchmarks MB/s is defined as 1000000 bytes/s\n"); + fprintf(stderr, "\n"); + fprintf(stderr, "Example of running a test with bandwidth tolerance set to 20%%\n" + " and latency tolerance set to 30%%, running concurrently, with a known good\n" + " host compute0001, and running in verbose mode\n"); + fprintf(stderr, " deviation -bwtol 20 -lattol 30 -c -h compute0001 -v\n"); + fprintf(stderr, "Examples:\n"); + fprintf(stderr, " deviation -bwthres 1200.5 -latthres 3.5 -c -h compute0001 -v\n"); + fprintf(stderr, " deviation -bwdelta 200 -latdelta 0.5 -bwtol 0 -lattol 0\n"); +} + +/* Get the name of my host */ +static const char* +pairedHostname() +{ + static char *host = NULL; + static char buf[256]; + + if (!host) + { + gethostname(buf, sizeof buf-1); + buf[sizeof buf-1] = '\0'; + host = buf; + } + return host; +} + +/* vi:set ts=4: */ + diff --git a/MpiApps/apps/gen_group_hosts b/MpiApps/apps/gen_group_hosts new file mode 100755 index 0000000..baf5335 --- /dev/null +++ b/MpiApps/apps/gen_group_hosts @@ -0,0 +1,176 @@ +#!/bin/bash +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +#[ICS VERSION STRING: unknown] + +MPI_HOSTS=${MPI_HOSTS:-$PWD/mpi_hosts} +MPI_GROUP_HOSTS=${MPI_GROUP_HOSTS:-$PWD/mpi_group_hosts} +DEFAULT_GROUPSIZE=2 +DEFAULT_NUMPROCS=3 + +hostfile="/baddir/badfile" + +groupsize="NaN" +numprocs="NaN" + +echo +echo "This tool generates an mpi_group_test file for use with" +echo "run_cabletest." +echo +echo "To generate an mpi_group_test file, please answer the" +echo "following questions." + +until [ -f $hostfile ] +do + echo + echo "Please enter the name of your hosts file." + echo "The hosts must be listed in group order, one per line. " + echo "Hosts should not be listed more than once and should be listed" + echo "in their physical order." + echo -n "Hostfile (default is $MPI_HOSTS)> " + read hostfile + + if [ -z "$hostfile" ] + then + hostfile=$MPI_HOSTS + fi + + if [ ! -f $hostfile ] + then + echo "Could not find '$hostfile'". + fi +done + +until [ $groupsize -eq $groupsize 2>/dev/null ] +do + echo + echo "How big are your groups? For example, if you want to test each" + echo "node against the node next to it, use a group size of 2." + echo "(This is the default.)" + echo "If you want to test the nodes connected to one leaf switch against " + echo "nodes on another leaf switch, and you have 16 nodes per leaf," + echo "your group size is 32." + echo "Remember, your hosts must be listed in the order they are connected" + echo "to the switches." + echo -n "Group Size (default is $DEFAULT_GROUPSIZE)> " + read groupsize + + if [ -z "$groupsize" ] + then + groupsize=$DEFAULT_GROUPSIZE + fi + + # Believe it or not, this is how you check to see + # if $groupsize is numeric or not.... + if [ $groupsize -eq $groupsize 2>/dev/null ] + then + if [ $groupsize -le 1 ] + then + echo "Group Size must be at least two." + groupsize="NaN" + fi + else + echo "Group Size must be a number." + fi +done + +until [ $numprocs -eq $numprocs 2>/dev/null ] +do + echo + echo "How many processes per node do you wish to run?" + echo "The higher you make this number, the higher your" + echo "link utilization will be. The number should be between" + echo "1 and the number of processors per node." + echo -n "Number of processes (default is $DEFAULT_NUMPROCS)> " + read numprocs + + if [ -z "$numprocs" ] + then + numprocs=$DEFAULT_NUMPROCS + fi + + # Believe it or not, this is how you check to see + # if $numprocs is numeric or not.... + if [ $numprocs -eq $numprocs 2>/dev/null ] + then + if [ $numprocs -le 0 ] + then + echo "Number of processes must be at least one." + numprocs="NaN" + fi + else + echo "Number of processes must be a number." + fi +done + +# this assignment will implicitly ignore blank lines +host=( `cat $hostfile | grep -v "^#"` ) +hostcount=${#host[*]} + +i=0 +j=$groupsize +groupno=0 + +echo "# DO NOT DELETE THIS LINE: $groupsize $numprocs" >$MPI_GROUP_HOSTS + +while [ $i -lt $hostcount ] +do + if [ $j -eq $groupsize ] + then + groupno=$((groupno + 1)) + (echo "#" + echo "# Group $groupno" + echo "#") >> $MPI_GROUP_HOSTS + j=1 + else + j=$((j + 1)) + fi + + k=0 + while [ $k -lt $numprocs ] + do + k=$((k + 1)) + echo ${host[$i]} >> $MPI_GROUP_HOSTS + done + + i=$((i + 1)) +done + +echo +echo "$MPI_GROUP_HOSTS generated." +if [ $j -ne $groupsize ] +then + echo + echo "WARNING: The number of hosts in $hostfile is not" + echo "an even multiple of the group size $groupsize." + echo "It is highly likely that the new mpi_group_hosts" + echo "file is not correct." +fi +echo diff --git a/MpiApps/apps/gen_mpi_hosts b/MpiApps/apps/gen_mpi_hosts new file mode 100755 index 0000000..5190e49 --- /dev/null +++ b/MpiApps/apps/gen_mpi_hosts @@ -0,0 +1,99 @@ +#!/bin/bash +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +#[ICS VERSION STRING: unknown] + +usage() +{ + echo "Usage: ./gen_mpi_hosts [-s] host_list rank_per_host [num_hosts] > somefile" >&2 + echo >&2 + echo "generate a hosts file using the 1st num_hosts from host_list input file" >&2 + echo "and putting rank_per_host ranks per host. Ranks are listed as:" >&2 + echo " host1 host2 host3 host1 host2 host3 ..." >&2 + echo >&2 + echo "when the -s option is used, the ranks are listed as:" >&2 + echo " host1 host1 host1 host2 host2 host2 ..." >&2 + echo "with the hosts in the exact order given as input" >&2 + echo >&2 + echo "as needed, output can be piped into an appropriate sort routine" >&2 + echo "to convert ordering into:" >&2 + echo " host1 host1 ... host2 host2 ... " >&2 + echo >&2 + echo "This tool can be helpful when generating mpi_hosts files to run" >&2 + echo "a specific number of ranks per host" >&2 + exit 2 +} + +sopt=n +while getopts s param +do + case $param in + s) sopt=y;; + ?) usage;; + esac +done +shift $(( OPTIND-1)) + +if [ $# -lt 2 -o $# -gt 3 ] +then + usage +fi + +infile="$1" +if [ ! -e "$infile" ] +then + echo "Not Found: $infile" + usage +fi +ranks="$2" +if [ ! -z "$3" ] +then + nodes=$3 +else + nodes=$(cat $infile|wc -l) +fi + +if [ "$sopt" = "n" ] +then + for i in $(seq 1 $ranks) + do + head -$nodes < $infile + done +else + head -$nodes < $infile | while read node + do + for i in $(seq 1 $ranks) + do + echo $node + done + done +fi + +exit 0 diff --git a/MpiApps/apps/get_mpi_cc.sh b/MpiApps/apps/get_mpi_cc.sh new file mode 100755 index 0000000..4766ae0 --- /dev/null +++ b/MpiApps/apps/get_mpi_cc.sh @@ -0,0 +1,73 @@ +#!/bin/bash +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +#[ICS VERSION STRING: unknown] +#!/bin/bash +# +# Sets the MPICH_CC_TYPE variable to match the CC compiler being used +# by the current mpicc command. +# +# Usage: +# +# source get_mpi_cc.sh +# +# -- or -- +# +# export MYVAR=`get_mpi_cc.sh` + + + + +if [ -e .prefix ]; then + prefix=`cat .prefix` +elif [ ! -z "$MPICH_PREFIX" ]; then + prefix="$MPICH_PREFIX" +else + prefix=`which mpicc 2>/dev/null | sed 's:bin/mpicc::g'` +fi + +$prefix/bin/mpicc -v 2>&1 | grep -w "icc" | grep -q -v "mpicc"; isintel=$? +$prefix/bin/mpicc -v 2>&1 | grep -w "gcc" | grep -q -v "icc"; isgcc=$? +$prefix/bin/mpicc -v 2>&1 | grep -w "pgi" | grep -q -v "icc"; ispgi=$? + +#echo "intel = $isintel; pgi = $ispgi; gcc = $isgcc" + + +if [ $isgcc -eq 0 ]; then + export MPICH_CC_TYPE="gcc" +elif [ $ispgi -eq 0 ]; then + export MPICH_CC_TYPE="pgi" +elif [ $isintel -eq 0 ]; then + export MPICH_CC_TYPE="intel" +else + export MPICH_CC_TYPE="UNKNOWN_MPI_CC" +fi + +echo $MPICH_CC_TYPE diff --git a/MpiApps/apps/get_selected_mpi.sh b/MpiApps/apps/get_selected_mpi.sh new file mode 100755 index 0000000..b3ac48e --- /dev/null +++ b/MpiApps/apps/get_selected_mpi.sh @@ -0,0 +1,49 @@ +#!/bin/bash +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +#[ICS VERSION STRING: unknown] +#!/bin/bash +# +# Sets MPICH_PREFIX to match the value of your mpi-selector settings. +# +# Usage: +# +# source get_selected_mpi.sh + +testmpi=`mpi-selector --query` +if [ ! -z "$testmpi" ] +then + export MPICH_PREFIX=`which mpicc 2>/dev/null| sed "s#/bin/mpicc##"` +else + export MPICH_PREFIX='NO MPI SELECTED' + echo 'NO MPI SELECTED' +fi + +echo $MPICH_PREFIX diff --git a/MpiApps/apps/groupstress/Makefile b/MpiApps/apps/groupstress/Makefile new file mode 100644 index 0000000..444c614 --- /dev/null +++ b/MpiApps/apps/groupstress/Makefile @@ -0,0 +1,46 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +ifndef MPICH_PREFIX +export MPICH_PREFIX=/usr/lib/opa +endif +ifndef MPICC +export MPICC=$(MPICH_PREFIX)/bin/mpicc +endif + +all: mpi_groupstress mpi_latencystress + +mpi_groupstress: mpi_groupstress.c + $(MPICC) -o mpi_groupstress -g mpi_groupstress.c + +mpi_latencystress: mpi_latencystress.c + $(MPICC) -o mpi_latencystress -g mpi_latencystress.c + +clean: + rm -f mpi_groupstress mpi_latencystress *.o diff --git a/MpiApps/apps/groupstress/README.txt b/MpiApps/apps/groupstress/README.txt new file mode 100644 index 0000000..e9298a5 --- /dev/null +++ b/MpiApps/apps/groupstress/README.txt @@ -0,0 +1,51 @@ +The tools in this directory are intended to stress a fabric in different ways +in order to provide information about how a fabric is running. + +mpi_groupstress: + +USAGE: + -v/--verbose Verbose. + -g/--group Group size. Should be an even number between 2 and 128 + -l/--min Minimum Message Size. Should be between 16384 and + (1<<22) + -u/--max Maximum Message Size. Should be between 16384 and + (1<<22) + -n/--num Number of times to repeat the test. Enter -1 to run + forever. + -h/--help Provides this help text. + +The first tool, mpi_groupstress breaks the nodes into groups and then runs the +osu bandwidth benchmark on pairs of nodes within each group. + +This is useful for stressing the fabric in specific ways. For example, consider +a fabric where all the nodes are connected to the core switch via leaf switches, +with 18 nodes per leaf switch. If you list the nodes in the mpi_hosts file in +topological order and run mpi_groupstress with a group size of 18, you can +stress all the leaf-to-node connections without sending traffic over the core +switch. If you want to test leaf-to-leaf connections, doubling the group size +to 36 will ensure that every single test will pass through an inter-switch link. + +Note that, as mentioned above, adding nodes to the hosts file is very important. +mpi_groupstress has no knowledge of the fabric topology, so that knowledge +must be embedded in the hosts file. + +A third use case might be to stress a single link as hard as possible. For +example, if each node has 16 cores, and you want to stress the path between +two nodes, list each node 16 times in the hostfile, then run mpi_groupstress +with a group size of 32. + + + +mpi_latencystress: + +USAGE: + -v/--verbose Verbose. Outputs some debugging information. + Use multiple times for more detailed information. + -s/--size Message Size. Should be between 0 and (1<<22) + -n/--num Number of times to repeat the test. Enter -1 to + run forever. + -h/--help Provides this help text. + +mpi_latencystress iterates through every possible pair of nodes in the fabric, +looking for slow links. Unlike similar tools, it will do as many pair-wise +tests in parallel as it can, to reduce the total run time of the test. \ No newline at end of file diff --git a/MpiApps/apps/groupstress/mpi_groupstress.c b/MpiApps/apps/groupstress/mpi_groupstress.c new file mode 100644 index 0000000..34defef --- /dev/null +++ b/MpiApps/apps/groupstress/mpi_groupstress.c @@ -0,0 +1,551 @@ +/* BEGIN_ICS_COPYRIGHT7 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT7 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +/* + * OSU MPI Bandwidth test v2.2 + */ +/* + * Copyright (C) 2002-2006 the Network-Based Computing Laboratory + * (NBCL), The Ohio State University. + * + * Contact: Dr. D. K. Panda (panda@cse.ohio-state.edu) + */ + +/* +This program is available under BSD licensing. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +(1) Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + +(2) Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. + +(3) Neither the name of The Ohio State University nor the names of +their contributors may be used to endorse or promote products derived +from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +/* mpi_groupstress + +The purpose of this program is to stress groups of links in a large +IB fabric. While it generates some basic numbers about how the links +are performing, it is not intended as a benchmark. + +*/ + +#include "mpi.h" +#include +#include +#include +#include +#include +#include +#include +#include + +#define stringize(x) #x +#define add_quotes(x) stringize(x) + +#define VERBOSE(X,...) if (verbose) fprintf(stderr,X, ## __VA_ARGS__ ) +#define RANK0(X,...) if (verbose && myid == 0) fprintf(stderr,X, ## __VA_ARGS__ ) + +#define MIN_MSG_SIZE 16384 +#define MAX_ALIGNMENT 16384 +#define MAX_MSG_SIZE (1<<22) +#define N_HALF_ERROR_BOUND 0.2 +#define MY_BUF_SIZE (MAX_MSG_SIZE + MAX_ALIGNMENT) + +char s_buf1[MY_BUF_SIZE]; +char r_buf1[MY_BUF_SIZE]; + +#define TAG_DATA 100 +#define TAG_SKIP 101 +#define TAG_LOOP 102 +#define TAG_DONE 103 + +#define MAX_REQ_NUM 1000 + +MPI_Request send_request[MAX_REQ_NUM]; +MPI_Request recv_request[MAX_REQ_NUM]; +MPI_Status reqstat[MAX_REQ_NUM]; + +MPI_Comm mpi_comm_sender; + +/* + * Ranks are grouped into "groups". During the test, the ranks in the first + * half of each group will pair themselves with matching ranks in the second + * half of each group. + * + * This permits, correct pairing of ranks in multi-processor nodes. + * For example, given a fabric made of 4-processor nodes, a group size of 8 + * will allow all the ranks running on node #1 to be paired + * with ranks running on node #2. + */ +#define MIN_GROUP_SIZE 2 +#define MAX_GROUP_SIZE 128 +#define DEFAULT_GROUP_SIZE 2 + +static int minutes = 60; // how long the test should run. +static int verbose = 0; // noisy output +static int group_size = DEFAULT_GROUP_SIZE; // size of the groups +static int num_groups; // how many groups in the job? +static int num_procs; // how many processes in the job? +static int myid; // my rank. +static int partnerid; // my partner's rank. +static int min_msg_size = MIN_MSG_SIZE; +static int max_msg_size = MAX_MSG_SIZE; + +#if defined(WIDE_PATTERN) +#define PATTERN_SIZE 80 +// This pattern is designed to exercise a pattern of different IB symbols +static u_int32_t pattern[] = { + 0x63636363, // 00 + 0xA3A3A3A3, // 01 + 0x54545454, // 02 + 0x47474747, // 03 + 0x18181818, // 04 + 0x63636363, // 05 + 0xA3A3A3A3, // 06 + 0x54545454, // 07 + 0x47474747, // 08 + 0x18181818, // 09 + 0x63636363, // 10 + 0xA3A3A3A3, // 11 + 0x54545454, // 12 + 0x47474747, // 13 + 0x18181818, // 14 + 0x63636363, // 15 + 0xA3A3A3A3, // 16 + 0x54545454, // 17 + 0x47474747, // 18 + 0x18181818, // 19 +}; +#else +#define PATTERN_SIZE 80 +// By repeating the same word over and over, we can stress signal integrity +// in a different way... +static u_int32_t pattern[] = { + 0xb5b5b5b5, // 00 + 0xb5b5b5b5, // 01 + 0xb5b5b5b5, // 02 + 0xb5b5b5b5, // 03 + 0xb5b5b5b5, // 04 + 0xb5b5b5b5, // 05 + 0xb5b5b5b5, // 06 + 0xb5b5b5b5, // 07 + 0xb5b5b5b5, // 08 + 0xb5b5b5b5, // 09 + 0xb5b5b5b5, // 10 + 0xb5b5b5b5, // 11 + 0xb5b5b5b5, // 12 + 0xb5b5b5b5, // 13 + 0xb5b5b5b5, // 14 + 0xb5b5b5b5, // 15 + 0xb5b5b5b5, // 16 + 0xb5b5b5b5, // 17 + 0xb5b5b5b5, // 18 + 0xb5b5b5b5, // 19 +}; +#endif + + +int window_size_small = 64; +long skip_small = 100; +long min_loops_small = 1000; +long max_loops_small = 60000000000; +double seconds_per_message_size_small = 60.0; + +int window_size_large = 64; +long skip_large = 2; +long min_loops_large = 20; +long max_loops_large = 60000000000; +double seconds_per_message_size_large = 60.0; + +int large_message_size = 8192; + +double +find_bibw(int myid, int target, int size, char *s_buf, char *r_buf) +{ +/*This function is the bandwidth test that was previously part of main in + osu_bibw, with the additional modification of being able to stream multiple + stream multiple processors per node. As of the InfiniPath 1.3 release + the code can also dynamically determine which processes are on which + node and set things up appropriately.*/ + + double t_start = 0.0, t_end = 0.0, t = 0.0, max_time = 0.0, min_time = 0.0; + double seconds_per_message_size, sum_loops, dloops; + int i, j, window_size; + long skip, loops = 0, min_loops, max_loops; + + if (size < large_message_size) + { + skip = skip_small; + min_loops = min_loops_small; + max_loops = max_loops_small; + window_size = window_size_small; + seconds_per_message_size = seconds_per_message_size_small; + } + else + { + skip = skip_large; + min_loops = min_loops_large; + max_loops = max_loops_large; + window_size = window_size_large; + seconds_per_message_size = seconds_per_message_size_large; + } + + MPI_Barrier (MPI_COMM_WORLD); + if (target != -1 && myid < target) + { + for (i = 0; i < max_loops + skip; i++) + { + if (i == skip) + { + MPI_Barrier (MPI_COMM_WORLD); + t_start = MPI_Wtime(); + } + for (j = 0; j < window_size; j++) + { + MPI_Irecv (r_buf, size, MPI_CHAR, target, TAG_DATA, + MPI_COMM_WORLD, recv_request + j); + } + for (j = 0; j < window_size; j++) + { + MPI_Isend (s_buf, size, MPI_CHAR, target, TAG_DATA, + MPI_COMM_WORLD, send_request + j); + } + MPI_Waitall (window_size, send_request, reqstat); + MPI_Waitall (window_size, recv_request, reqstat); + MPI_Recv (r_buf, 4, MPI_CHAR, target, MPI_ANY_TAG, MPI_COMM_WORLD, + &reqstat[0]); + if (reqstat[0].MPI_TAG == TAG_DONE) + { + t_end = MPI_Wtime(); + i++; + break; + } + } + if (t_end == 0.0) + { + t_end = MPI_Wtime(); + } + loops = i - skip; + t = t_end - t_start; + } + else if (target != -1 && myid > target) + { + int tag = TAG_SKIP; + for (i = 0; i < max_loops + skip; i++) + { + if (i == skip) + { + tag = TAG_LOOP; + MPI_Barrier (MPI_COMM_WORLD); + t_start = MPI_Wtime(); + } + for (j = 0; j < window_size; j++) + { + MPI_Isend (s_buf, size, MPI_CHAR, target, TAG_DATA, + MPI_COMM_WORLD, send_request + j); + } + for (j = 0; j < window_size; j++) + { + MPI_Irecv (r_buf, size, MPI_CHAR, target, TAG_DATA, + MPI_COMM_WORLD, recv_request + j); + } + MPI_Waitall (window_size, send_request, reqstat); + MPI_Waitall (window_size, recv_request, reqstat); + if (tag == TAG_LOOP && + (i - skip) >= (min_loops - 1) && + MPI_Wtime() - t_start >= seconds_per_message_size) + { + MPI_Send (s_buf, 4, MPI_CHAR, target, TAG_DONE, MPI_COMM_WORLD); + i++; + break; + } + else { + MPI_Send (s_buf, 4, MPI_CHAR, target, tag, MPI_COMM_WORLD); + } + } + loops = i - skip; + } + else + { + MPI_Barrier(MPI_COMM_WORLD); + } + MPI_Reduce (&t, &max_time, 1, MPI_DOUBLE, MPI_MAX, 0, mpi_comm_sender); + MPI_Reduce (&t, &min_time, 1, MPI_DOUBLE, MPI_MIN, 0, mpi_comm_sender); + MPI_Reduce (&loops, &max_loops, 1, MPI_INTEGER, MPI_MAX, 0, mpi_comm_sender); + MPI_Reduce (&loops, &min_loops, 1, MPI_INTEGER, MPI_MIN, 0, mpi_comm_sender); + dloops = (double) loops; + MPI_Reduce (&dloops, &sum_loops, 1, MPI_DOUBLE, MPI_SUM, 0, mpi_comm_sender); + + if (myid==0) + { + double mbytes = ( (size * 2.0) / (1000 * 1000) ) * sum_loops * window_size; + double bw = (mbytes / num_groups) / max_time; + VERBOSE("%d bytes, %.2f MB/s, %ld to %ld loops (range %.2f%%), " + "%.3f to %.3f secs (range %.2f%%)\n", + size, bw, + min_loops, max_loops, + 100.0 * ((double) max_loops / (double) min_loops - 1), + min_time, max_time, + 100.0 * (max_time / min_time - 1)); + return bw; + } + return 0; +} + +static char *short_options = "g:vl:u:t:h"; +static struct option long_options[] = { + { .name = "verbose", .has_arg = 0, .val = 'v' }, + { .name = "group", .has_arg = 1, .val = 'g' }, + { .name = "min", .has_arg = 1, .val = 'l' }, + { .name = "max", .has_arg = 1, .val = 'u' }, + { .name = "time", .has_arg = 1, .val = 't' }, + { .name = "help", .has_arg = 0, .val = 'h' }, + { 0 } +}; + +static char *usage_text[] = { + "Verbose.", + "Group size. Should be an even number between " add_quotes(MIN_GROUP_SIZE) " and " add_quotes(MAX_GROUP_SIZE), + "Minimum Message Size. Should be between " add_quotes(MIN_MSG_SIZE) " and " add_quotes(MAX_MSG_SIZE), + "Maximum Message Size. Should be between " add_quotes(MIN_MSG_SIZE) " and " add_quotes(MAX_MSG_SIZE), + "The duration of the test, in minutes. Defaults to 60 minutes. -1 to run forever.", + "Provides this help text.", + 0 +}; + +static void +usage() +{ + int i=0; + + if (myid == 0) { + fprintf(stderr,"\nError processing command line arguments.\n\n"); + fprintf(stderr,"USAGE:\n"); + while (long_options[i].name != NULL) { + fprintf(stderr, " -%c/--%-8s %s %s\n", + long_options[i].val, + long_options[i].name, + (long_options[i].has_arg)?"":" ", + usage_text[i]); + i++; + } + fprintf(stderr,"\n\n"); + } +} + +int +main(int argc, char *argv[]) +{ + int done = 0; + int err = 0; + int c; + int align_size = getpagesize(); + int size; + time_t done_time; + + char *s_buf = (char*)(((unsigned long)s_buf1 + (align_size - 1)) / + align_size * align_size); + + char *r_buf = (char*)(((unsigned long)r_buf1 + (align_size - 1)) / + align_size * align_size); + + double bw=0.0; + + memset(r_buf1,'a',MY_BUF_SIZE); + + for(c=0;c<(MAX_MSG_SIZE-PATTERN_SIZE);c+=PATTERN_SIZE) + memcpy(s_buf+c,pattern,PATTERN_SIZE); + + MPI_Init(&argc, &argv); + MPI_Comm_size(MPI_COMM_WORLD, &num_procs); + MPI_Comm_rank(MPI_COMM_WORLD, &myid); + + while ( -1 != (c = getopt_long(argc, argv, short_options, long_options, NULL))) { + switch (c) { + case 'v': + verbose=1; + break; + + case 'g': + group_size = strtol(optarg, NULL, 0); + if (group_size < MIN_GROUP_SIZE || group_size > MAX_GROUP_SIZE || (group_size % 2) != 0) { + usage(); + err = -1; + goto exit; + } + break; + + case 'l': + min_msg_size = strtoul(optarg, NULL, 0); + if (min_msg_size < MIN_MSG_SIZE || min_msg_size > MAX_MSG_SIZE) { + usage(); + err = -1; + goto exit; + } + break; + + case 'u': + max_msg_size = strtoul(optarg, NULL, 0); + if (max_msg_size < MIN_MSG_SIZE || min_msg_size > MAX_MSG_SIZE) { + usage(); + err = -1; + goto exit; + } + break; + + case 't': + minutes = strtol(optarg, NULL, 0); + if (minutes == 0 && strcmp(optarg,"0")) { + usage(); + err = -1; + goto exit; + } + break; + + case 'h': + default: + usage(); + err = -1; + goto exit; + } + } + + num_groups = num_procs / group_size; + + MPI_Barrier(MPI_COMM_WORLD); + + /* Calculate my partner's rank. */ + { + int g; // group # + int q; // rank within group. + + g = myid / group_size; + q = (myid % group_size) + (group_size / 2); + if (q > (group_size-1)) q -= group_size; + + partnerid = g * group_size + q; + if (partnerid >= num_procs) partnerid = -1; + } + + if (partnerid >= 0) + { + VERBOSE("%d is partnered with %d.\n", myid, partnerid); + } + else + { + VERBOSE("%d has no partner.\n", myid); + } + + MPI_Comm_split(MPI_COMM_WORLD, (myid 0) { + printf("%d groups of %d, running for %d minutes.\n", + num_groups, group_size, minutes); + done_time = time(NULL) + minutes*60; + } else { + printf("%d groups of %d, running till interrupted.\n", + num_groups, group_size); + done_time=(time_t)-1; + } + + printf("\n# Size\t\tGroup Agg Bandwidth (MB/s)\tMessages/s\tTime Left\n"); + } + + do { + for (size = min_msg_size; size <= max_msg_size; size *= 2) + { + bw = find_bibw(myid, partnerid, size, s_buf, r_buf); + if (myid == 0) + { + double rate = 1000*1000*bw/size; + int h, m, s; + + if (minutes > 0) { + time_t rt = done_time - time(NULL); + + if (rt<0) rt=0; + + h = rt/3600; + m = rt/60-(h*60); + s = (h>0)?0:(rt-(m*60)); + + printf("%d\t\t%8.2f\t\t\t%8.2f\t%02d:%02d:%02d\n", + size, bw, rate, h, m, s); + fflush(stdout); + } else { + printf("%d\t\t%8.2f\t\t\t%8.2f\t--:--:--\n", + size, bw, rate); + fflush(stdout); + } + } + } + if (myid == 0) { + if (min_msg_size != max_msg_size) { + printf("\n\nMPI_GroupStress BIBW Cable Stress Test\n"); + printf("\n# Size\t\tGroup Agg Bandwidth (MB/s)\tMessages/s\tTime Left\n"); + } + done = (minutes > 0) && (done_time < time(NULL)); + } + MPI_Bcast(&done,1,MPI_INT,0,MPI_COMM_WORLD); + } while (!done); + + VERBOSE("%d at final barrier.\n",myid); + MPI_Barrier(MPI_COMM_WORLD); + +exit: + VERBOSE("%d at finalize.\n",myid); + MPI_Finalize(); + return err; +} diff --git a/MpiApps/apps/groupstress/mpi_latencystress.c b/MpiApps/apps/groupstress/mpi_latencystress.c new file mode 100644 index 0000000..dbefc1e --- /dev/null +++ b/MpiApps/apps/groupstress/mpi_latencystress.c @@ -0,0 +1,694 @@ +/* BEGIN_ICS_COPYRIGHT7 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT7 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +/* + * Copyright (C) 2002-2005 the Network-Based Computing Laboratory + * (NBCL), The Ohio State University. + * + * Contact: Dr. D. K. Panda (panda@cse.ohio-state.edu) + */ + +/* +This program is available under BSD licensing. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +(1) Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + +(2) Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. + +(3) Neither the name of The Ohio State University nor the names of +their contributors may be used to endorse or promote products derived +from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +/* mpi_latencystress + +The purpose of this program is to stress links in a large IB fabric. +While it generates some basic numbers about how the links +are performing, it is not intended as a benchmark. + +*/ + +#include "mpi.h" +#include +#include +#include +#include +#include +#include +#include + +#define stringize(x) #x +#define add_quotes(x) stringize(x) + +#define DEBUG(X,...) if (verbose>2) printf(X, ## __VA_ARGS__ ) +#define VERBOSE(X,...) if (verbose>1) printf(X, ## __VA_ARGS__ ) +#define NORMAL(X,...) if (verbose>0) printf(X, ## __VA_ARGS__ ) +#define RANK0(X,...) if (verbose && my_id == 0) printf(X, ## __VA_ARGS__ ) + +#define MESSAGE_ALIGNMENT 64 +#define MIN_MSG_SIZE 0 +#define MAX_MSG_SIZE (1<<22) +#define MY_BUF_SIZE (MAX_MSG_SIZE + MESSAGE_ALIGNMENT) +#define DEFAULT_MINUTES 5 + +#define TAG_BASIC 1000 +#define TAG_RSLT1 1001 +#define TAG_RSLT2 1002 + +/* + * Command line args. + */ +static int minutes = DEFAULT_MINUTES; // how long the test should run. +static int verbose = 0; // noisy output +static int size = MIN_MSG_SIZE; +static int csv = 0; // generate CSV file + +static int num_procs; // how many processes in the job? +static int my_id; // my rank. + +#define PATTERN_SIZE 80 +static u_int32_t pattern[] = { + 0x63636363, + 0xA3A3A3A3, + 0x54545454, + 0x47474747, + 0x18181818, + 0x63636363, + 0xA3A3A3A3, + 0x54545454, + 0x47474747, + 0x18181818, + 0x63636363, + 0xA3A3A3A3, + 0x54545454, + 0x47474747, + 0x18181818, + 0x63636363, + 0xA3A3A3A3, + 0x54545454, + 0x47474747, + 0x18181818, +}; + +char s_buf1[MY_BUF_SIZE]; +char r_buf1[MY_BUF_SIZE]; + +struct partner { + int inuse; + int sender; + int receiver; +}; + +#define MAX_HOST_LEN 32 +struct host { char name[MAX_HOST_LEN]; }; + +static struct partner *pair_list; +static struct host *host_list; +static short *checked; +static double *latency; +static unsigned long psize; +static unsigned long csize; + +static void +dump_checked(int ranks) +{ + int i, j; + + printf(" "); + for (i = 0; i< ranks; i++) { + printf(":%4d",i); + } + printf("\n"); + + for (j = 0; j < ranks; j++) { + printf("%4d",j); + for (i = 0; i < ranks; i++) { + if (checked[j*ranks+i]) { + printf(": %02u ", checked[j*ranks+i]); + } else { + printf(": "); + } + } + printf("\n"); + } +} + +static int +calculate_pairs(int iteration, int ranks) +{ + int i,j, k, pairs_found, match_found; + + memset(pair_list,0,psize); + + pairs_found = 0; + + if (iteration > ranks) return 0; + + for (i=0; ii-ranks; k--) { + j = (k>=0)?k:(k+ranks); + if (i == j) { + // Can't test against yourself. + break; + } else if ((pair_list[j].inuse == 0) && + (checked[i*ranks+j]==0)) { + pair_list[i].inuse=1; + pair_list[i].sender=i; + pair_list[i].receiver=j; + pair_list[j]=pair_list[i]; + match_found=1; + checked[i*ranks+j]=iteration; + checked[j*ranks+i]=iteration; + break; + } else if ((pair_list[j].inuse != 0)) + DEBUG("collision on [%d,%d] (%d)\n", + i, j, k); + + } + if (!match_found) { + // This will happen if + // ranks is not a power of 2. + pair_list[i].sender=-1; + pair_list[i].receiver=-1; + pair_list[i].inuse=1; + VERBOSE("%d is idle this iteration.\n", i); + } else { + pairs_found++; + } + } + } + + return pairs_found; +} + +/* + * Taken from osu_latency and converted to a function. + */ +int skip = 1000; +int loop = 10000; +int skip_large = 10; +int loop_large = 100; +int large_message_size = 8192; + +static void +find_latency(int ranks, int size, char *s_buf, char *r_buf, + double *min_lat, double *max_lat, double *avg_lat, + int *min_rank, int *max_rank) +{ + int i; + MPI_Status reqstat; + MPI_Comm mpi_comm_sender; + MPI_Request request1, request2; + int partner; + double lat; + double summary_f[3]; + int summary_i[2]; + int sender_id; + + double t_start = 0.0, t_end = 0.0; + + //VERBOSE("%d @ find_latency(%d, %d, %p, %p)\n", + // my_id, ranks, size, s_buf, r_buf); + + if (pair_list[my_id].sender == my_id) { + partner = pair_list[my_id].receiver; + //VERBOSE("%d -> %d\n", my_id, partner); + } else if (pair_list[my_id].receiver == my_id) { + partner = pair_list[my_id].sender; + //VERBOSE("%d <- %d\n", my_id, partner); + } else { + //VERBOSE("%d IDLE\n",my_id); + partner = -1; + } + + //VERBOSE("%d @ buffers loaded.\n",my_id); + + if (size > large_message_size) { + loop = loop_large; + skip = skip_large; + } + +// VERBOSE("%d @ barrier.\n", my_id); + MPI_Barrier(MPI_COMM_WORLD); + + if (pair_list[my_id].sender == my_id) { +// VERBOSE("%d @ sending.\n", my_id); + MPI_Comm_split(MPI_COMM_WORLD, 1, my_id, &mpi_comm_sender); + for (i = 0; i < loop + skip; i++) { + if (i == skip) + t_start = MPI_Wtime(); + MPI_Send(s_buf, + size, + MPI_CHAR, + partner, + TAG_BASIC, + MPI_COMM_WORLD); + MPI_Recv(r_buf, + size, + MPI_CHAR, + partner, + TAG_BASIC, + MPI_COMM_WORLD, + &reqstat); + } + t_end = MPI_Wtime(); + + } else if (pair_list[my_id].receiver == my_id) { +// VERBOSE("%d @ receiving.\n", my_id); + MPI_Comm_split(MPI_COMM_WORLD, 2, my_id, &mpi_comm_sender); + for (i = 0; i < loop + skip; i++) { + MPI_Recv(r_buf, + size, + MPI_CHAR, + partner, + TAG_BASIC, + MPI_COMM_WORLD, + &reqstat); + MPI_Send(s_buf, + size, + MPI_CHAR, + partner, + TAG_BASIC, + MPI_COMM_WORLD); + } + } else { + MPI_Comm_split(MPI_COMM_WORLD, 3, my_id, &mpi_comm_sender); + } + +// VERBOSE("%d @ collectives.\n", my_id); + + if (pair_list[my_id].sender == my_id) { + lat = (t_end - t_start) * 1.0e6 / (2.0 * loop); + + VERBOSE("t_start = %f, t_end = %f, loop = %d, lat = %f\n", t_start, t_end, loop, lat); + + MPI_Reduce(&lat, &summary_f[0], 1, MPI_DOUBLE, MPI_MIN, 0, mpi_comm_sender); + MPI_Reduce(&lat, &summary_f[1], 1, MPI_DOUBLE, MPI_MAX, 0, mpi_comm_sender); + MPI_Reduce(&lat, &summary_f[2], 1, MPI_DOUBLE, MPI_SUM, 0, mpi_comm_sender); + MPI_Gather(&lat, 1, MPI_DOUBLE, latency, 1, MPI_DOUBLE, 0, mpi_comm_sender); + + MPI_Comm_rank(mpi_comm_sender, &sender_id); + } else { + sender_id = -1; + } + + MPI_Barrier(MPI_COMM_WORLD); + + // It is possible for the root of the senders to be different from + // the global rank 0. So, the root of the senders will send + // a summary of the results to rank 0, even though this is usually + // redundant. + if (sender_id == 0) { + int j=0; + + for (i=0;i idle\n", host_list[i].name, i); + } + } + + summary_f[2] = (j)?(summary_f[2] / j):0.0; + + MPI_Isend(summary_f, + 3, + MPI_DOUBLE, + 0, + TAG_RSLT1, + MPI_COMM_WORLD, + &request1); + MPI_Isend(summary_i, + 2, + MPI_INT, + 0, + TAG_RSLT2, + MPI_COMM_WORLD, + &request2); + } + + if (my_id == 0) { + MPI_Recv(summary_f, + 3, + MPI_DOUBLE, + MPI_ANY_SOURCE, + TAG_RSLT1, + MPI_COMM_WORLD, + &reqstat); + MPI_Recv(summary_i, + 2, + MPI_INT, + MPI_ANY_SOURCE, + TAG_RSLT2, + MPI_COMM_WORLD, + &reqstat); + + *min_lat = summary_f[0]; + *max_lat = summary_f[1]; + *avg_lat = summary_f[2]; + *min_rank = summary_i[0]; + *max_rank = summary_i[1]; + } + + MPI_Barrier(MPI_COMM_WORLD); + MPI_Comm_free(&mpi_comm_sender); + + //VERBOSE("%d @ done.\n", my_id); +} + +static char *short_options = "s:vt:ch"; +static struct option long_options[] = { + { .name = "verbose", .has_arg = 0, .val = 'v' }, + { .name = "size", .has_arg = 0, .val = 's' }, + { .name = "time", .has_arg = 1, .val = 't' }, + { .name = "csv", . has_arg = 0, .val = 'c' }, + { .name = "help", .has_arg = 0, .val = 'h' }, + { 0 } +}; + +static char *usage_text[] = { + "Verbose. Outputs some debugging information. Use multiple times for more detailed information.", + "Message Size. Should be between " add_quotes(MIN_MSG_SIZE) " and " add_quotes(MAX_MSG_SIZE), + "The duration of the test, in minutes. Defaults to " + add_quotes(DEFAULT_MINUTES) " minutes or use -1 to run forever.", + "Outputs raw data in a CSV file format, suitable for use in Excel." + "Provides this help text.", + 0 +}; + +static void +usage() +{ + int i=0; + + if (my_id == 0) { + fprintf(stderr,"\nError processing command line arguments.\n\n"); + fprintf(stderr,"USAGE:\n"); + while (long_options[i].name != NULL) { + fprintf(stderr, " -%c/--%-8s %s %s\n", + long_options[i].val, + long_options[i].name, + (long_options[i].has_arg)?"":" ", + usage_text[i]); + i++; + } + fprintf(stderr,"\n\n"); + } +} + +int +main(int argc, char *argv[]) +{ + int done = 0; + int err = 0; + int c, i; + int align_size = MESSAGE_ALIGNMENT; + time_t done_time; + + //int DebugWait = 1; // used to attach gdb. + + char *s_buf = (char*)(((unsigned long)s_buf1 + (align_size - 1)) / + align_size * align_size); + + char *r_buf = (char*)(((unsigned long)s_buf1 + (align_size - 1)) / + align_size * align_size); + + memset(r_buf1,'a',MY_BUF_SIZE); + + for(c=0;c<(MAX_MSG_SIZE-PATTERN_SIZE);c+=PATTERN_SIZE) + memcpy(s_buf+c,pattern,PATTERN_SIZE); + + int min_rank, max_rank, num_pairs; + struct partner round_fastest, round_slowest; + int found_fastest = 0; + int found_slowest = 0; + double min_lat, max_lat; + double avg_lat = 0; + double final_min = 99999999.0, final_max = 0.0; + double round_min, round_max; + + MPI_Init(&argc, &argv); + MPI_Comm_size(MPI_COMM_WORLD, &num_procs); + MPI_Comm_rank(MPI_COMM_WORLD, &my_id); + + //if (my_id == 0) while (DebugWait); // used to attach gdb. + + while ( -1 != (c = getopt_long(argc, argv, short_options, long_options, NULL))) { + switch (c) { + case 'v': + verbose += 1; + break; + + case 's': + size = strtoul(optarg, NULL, 0); + if (size < MIN_MSG_SIZE || size > MAX_MSG_SIZE) { + usage(); + err = -1; + goto exit; + } + break; + + case 't': + minutes = strtol(optarg, NULL, 0); + if (minutes == 0 && strcmp(optarg,"0")) { + usage(); + err = -1; + goto exit; + } + + break; + + case 'c': + csv = 1; + break; + case 'h': + default: + usage(); + err = -1; + goto exit; + } + } + + MPI_Barrier(MPI_COMM_WORLD); + + RANK0("Allocating buffers.\n"); + psize = sizeof (struct partner) * num_procs; + pair_list = malloc(psize); + csize = sizeof(short) * num_procs * num_procs; + checked = malloc(csize); + latency = malloc(sizeof(double)*num_procs); + host_list = malloc(sizeof(struct host)*num_procs); + + if (!pair_list || !checked || !latency || !host_list) { + fprintf(stderr,"malloc failed.\n"); + err = -1; + goto exit; + } + + // Broadcast the hostnames. + { + struct host myname; + gethostname(myname.name, MAX_HOST_LEN-1); + myname.name[MAX_HOST_LEN-1]='\0'; + //VERBOSE("%d hostname: %s\n",my_id,myname.name); + memset(host_list, 0, sizeof(struct host)*num_procs); + MPI_Allgather(&myname, sizeof(myname), MPI_CHAR, host_list, sizeof(myname), MPI_CHAR, MPI_COMM_WORLD); + } + + if (my_id == 0) { + if (minutes > 0) { + done_time = time(NULL) + minutes*60; + } else { + done_time = (time_t)-1; + } + } + + do { + memset(checked,0,csize); + if ((my_id == 0) && !csv) { + printf("\n\nMPI HCA Latency Stress Test\n"); + printf("Msg Size:\t%d\n",size); + if (minutes > 0) { + long rt = done_time-time(NULL); + if (rt > 3600) { + printf("Time Left:\t%ld hours and %ld minutes\n", + rt/3600, + rt/60 - (rt/3600)*60); + } else if (rt > 60) { + printf("Time Left:\t%ld minutes and %ld seconds\n",rt/60, + rt - (rt/60)*60); + } else { + printf("Time Left:\t%ld seconds\n",(rt > 0)?rt:0); + } + } else { + printf("Time Left:\ttil interrupted.\n"); + } + } + + round_max = 0.0; + round_min = 99999999.0; + num_pairs = 1; + + for (i=1; num_pairs > 0; i++) { + if (my_id == 0) { + // Rank 0 calculates the pairs and distributes the + // info to other nodes. + int j; + + for (j=0;j1) dump_checked(num_procs); + } else if (verbose>2) { + dump_checked(num_procs); + } + } + + MPI_Bcast(pair_list, + psize, + MPI_UNSIGNED_CHAR, + 0, + MPI_COMM_WORLD); + + // If rank 0 says there are no pairs to test, + // then it's time to stop. + if (pair_list[0].inuse == -2) { + break; + } + + find_latency(num_procs, + size, + s_buf, + r_buf, + &min_lat, + &max_lat, + &avg_lat, + &min_rank, + &max_rank); + + + if (my_id == 0 && min_lat < round_min) { + round_min = min_lat; + round_fastest = pair_list[min_rank]; + found_fastest=1; + if (round_min < final_min) final_min = round_min; + } + if (my_id == 0 && max_lat > round_max) { + round_max = max_lat; + round_slowest = pair_list[max_rank]; + found_slowest = 1; + if (round_max > final_max) final_max = round_max; + } + } + + MPI_Barrier(MPI_COMM_WORLD); + + if (my_id == 0) { + if (!csv) { + printf("Avg Latency:\t%0.2f\n",avg_lat); + if(found_fastest) { + printf("Fastest Pair:\n%"add_quotes(MAX_HOST_LEN)"s -> %"add_quotes(MAX_HOST_LEN)"s\t%0.2f\n", + host_list[round_fastest.sender].name, + host_list[round_fastest.receiver].name, + round_min); + } + if(found_slowest) { + printf("Slowest Pair:\n%"add_quotes(MAX_HOST_LEN)"s -> %"add_quotes(MAX_HOST_LEN)"s\t%0.2f\n", + host_list[round_slowest.sender].name, + host_list[round_slowest.receiver].name, + round_max); + } + } + done = (minutes > 0) && (done_time < time(NULL)); + } + MPI_Bcast(&done,1,MPI_INT,0,MPI_COMM_WORLD); + } while (!done); + + if (my_id == 0) { + fprintf(stderr,"\n\nMPI HCA Latency Stress Test\n"); + fprintf(stderr,"Msg Size:\t%d\n",size); + fprintf(stderr,"Final Min:\t%0.2f\n",final_min); + fprintf(stderr,"Final Max:\t%0.2f\n",final_max); + } + +exit: + //VERBOSE("%d at finalize.\n",my_id); + MPI_Finalize(); + return err; +} diff --git a/MpiApps/apps/hpl-config/HPL.dat-128l b/MpiApps/apps/hpl-config/HPL.dat-128l new file mode 100644 index 0000000..c77cba1 --- /dev/null +++ b/MpiApps/apps/hpl-config/HPL.dat-128l @@ -0,0 +1,31 @@ +HPLinpack benchmark input file - 128 process, large problem size +Innovative Computing Laboratory, University of Tennessee +HPL.out output file name (if any) +6 device out (6=stdout,7=stderr,file) +1 # of problems sizes (N) +90000 Ns +1 # of NBs +112 NBs +0 PMAP process mapping (0=Row-,1=Column-major) +1 # of process grids (P x Q) +8 Ps +16 Qs +16.0 threshold +1 # of panel fact +1 PFACTs (0=left, 1=Crout, 2=Right) +1 # of recursive stopping criterium +4 NBMINs (>= 1) +1 # of panels in recursion +2 NDIVs +1 # of recursive panel fact. +2 RFACTs (0=left, 1=Crout, 2=Right) +1 # of broadcast +1 BCASTs (0=1rg,1=1rM,2=2rg,3=2rM,4=Lng,5=LnM) +1 # of lookahead depth +1 DEPTHs (>=0) +2 SWAP (0=bin-exch,1=long,2=mix) +112 swapping threshold +0 L1 in (0=transposed,1=no-transposed) form +0 U in (0=transposed,1=no-transposed) form +1 Equilibration (0=no,1=yes) +4 memory alignment in double (> 0) diff --git a/MpiApps/apps/hpl-config/HPL.dat-128m b/MpiApps/apps/hpl-config/HPL.dat-128m new file mode 100644 index 0000000..65be979 --- /dev/null +++ b/MpiApps/apps/hpl-config/HPL.dat-128m @@ -0,0 +1,31 @@ +HPLinpack benchmark input file - 128 process, medium problem size +Innovative Computing Laboratory, University of Tennessee +HPL.out output file name (if any) +6 device out (6=stdout,7=stderr,file) +1 # of problems sizes (N) +87000 Ns +1 # of NBs +112 NBs +0 PMAP process mapping (0=Row-,1=Column-major) +1 # of process grids (P x Q) +8 Ps +16 Qs +16.0 threshold +1 # of panel fact +1 PFACTs (0=left, 1=Crout, 2=Right) +1 # of recursive stopping criterium +4 NBMINs (>= 1) +1 # of panels in recursion +2 NDIVs +1 # of recursive panel fact. +2 RFACTs (0=left, 1=Crout, 2=Right) +1 # of broadcast +1 BCASTs (0=1rg,1=1rM,2=2rg,3=2rM,4=Lng,5=LnM) +1 # of lookahead depth +1 DEPTHs (>=0) +2 SWAP (0=bin-exch,1=long,2=mix) +112 swapping threshold +0 L1 in (0=transposed,1=no-transposed) form +0 U in (0=transposed,1=no-transposed) form +1 Equilibration (0=no,1=yes) +4 memory alignment in double (> 0) diff --git a/MpiApps/apps/hpl-config/HPL.dat-128s b/MpiApps/apps/hpl-config/HPL.dat-128s new file mode 100644 index 0000000..cb3a02f --- /dev/null +++ b/MpiApps/apps/hpl-config/HPL.dat-128s @@ -0,0 +1,31 @@ +HPLinpack benchmark input file - small 128 process, small problem size +Innovative Computing Laboratory, University of Tennessee +HPL.out output file name (if any) +6 device out (6=stdout,7=stderr,file) +1 # of problems sizes (N) +84000 Ns +1 # of NBs +112 NBs +0 PMAP process mapping (0=Row-,1=Column-major) +1 # of process grids (P x Q) +8 Ps +16 Qs +16.0 threshold +1 # of panel fact +1 PFACTs (0=left, 1=Crout, 2=Right) +1 # of recursive stopping criterium +4 NBMINs (>= 1) +1 # of panels in recursion +2 NDIVs +1 # of recursive panel fact. +2 RFACTs (0=left, 1=Crout, 2=Right) +1 # of broadcast +1 BCASTs (0=1rg,1=1rM,2=2rg,3=2rM,4=Lng,5=LnM) +1 # of lookahead depth +1 DEPTHs (>=0) +2 SWAP (0=bin-exch,1=long,2=mix) +112 swapping threshold +0 L1 in (0=transposed,1=no-transposed) form +0 U in (0=transposed,1=no-transposed) form +1 Equilibration (0=no,1=yes) +4 memory alignment in double (> 0) diff --git a/MpiApps/apps/hpl-config/HPL.dat-128t b/MpiApps/apps/hpl-config/HPL.dat-128t new file mode 100644 index 0000000..272dde1 --- /dev/null +++ b/MpiApps/apps/hpl-config/HPL.dat-128t @@ -0,0 +1,31 @@ +HPLinpack benchmark input file - test 128 process, tiny problem size +Innovative Computing Laboratory, University of Tennessee +HPL.out output file name (if any) +6 device out (6=stdout,7=stderr,file) +1 # of problems sizes (N) +5000 Ns +1 # of NBs +112 NBs +0 PMAP process mapping (0=Row-,1=Column-major) +1 # of process grids (P x Q) +8 Ps +16 Qs +16.0 threshold +1 # of panel fact +1 PFACTs (0=left, 1=Crout, 2=Right) +1 # of recursive stopping criterium +4 NBMINs (>= 1) +1 # of panels in recursion +2 NDIVs +1 # of recursive panel fact. +2 RFACTs (0=left, 1=Crout, 2=Right) +1 # of broadcast +1 BCASTs (0=1rg,1=1rM,2=2rg,3=2rM,4=Lng,5=LnM) +1 # of lookahead depth +1 DEPTHs (>=0) +2 SWAP (0=bin-exch,1=long,2=mix) +112 swapping threshold +0 L1 in (0=transposed,1=no-transposed) form +0 U in (0=transposed,1=no-transposed) form +1 Equilibration (0=no,1=yes) +4 memory alignment in double (> 0) diff --git a/MpiApps/apps/hpl-config/HPL.dat-16l b/MpiApps/apps/hpl-config/HPL.dat-16l new file mode 100644 index 0000000..6c95923 --- /dev/null +++ b/MpiApps/apps/hpl-config/HPL.dat-16l @@ -0,0 +1,31 @@ +HPLinpack benchmark input file - 16 process, large problem size +Innovative Computing Laboratory, University of Tennessee +HPL.out output file name (if any) +6 device out (6=stdout,7=stderr,file) +1 # of problems sizes (N) +35000 Ns +1 # of NBs +112 NBs +0 PMAP process mapping (0=Row-,1=Column-major) +1 # of process grids (P x Q) +4 Ps +4 Qs +16.0 threshold +1 # of panel fact +1 PFACTs (0=left, 1=Crout, 2=Right) +1 # of recursive stopping criterium +4 NBMINs (>= 1) +1 # of panels in recursion +2 NDIVs +1 # of recursive panel fact. +2 RFACTs (0=left, 1=Crout, 2=Right) +1 # of broadcast +1 BCASTs (0=1rg,1=1rM,2=2rg,3=2rM,4=Lng,5=LnM) +1 # of lookahead depth +1 DEPTHs (>=0) +2 SWAP (0=bin-exch,1=long,2=mix) +112 swapping threshold +0 L1 in (0=transposed,1=no-transposed) form +0 U in (0=transposed,1=no-transposed) form +1 Equilibration (0=no,1=yes) +4 memory alignment in double (> 0) diff --git a/MpiApps/apps/hpl-config/HPL.dat-16m b/MpiApps/apps/hpl-config/HPL.dat-16m new file mode 100644 index 0000000..10802ad --- /dev/null +++ b/MpiApps/apps/hpl-config/HPL.dat-16m @@ -0,0 +1,31 @@ +HPLinpack benchmark input file - 16 process, medium problem size +Innovative Computing Laboratory, University of Tennessee +HPL.out output file name (if any) +6 device out (6=stdout,7=stderr,file) +1 # of problems sizes (N) +32000 Ns +1 # of NBs +112 NBs +0 PMAP process mapping (0=Row-,1=Column-major) +1 # of process grids (P x Q) +4 Ps +4 Qs +16.0 threshold +1 # of panel fact +1 PFACTs (0=left, 1=Crout, 2=Right) +1 # of recursive stopping criterium +4 NBMINs (>= 1) +1 # of panels in recursion +2 NDIVs +1 # of recursive panel fact. +2 RFACTs (0=left, 1=Crout, 2=Right) +1 # of broadcast +1 BCASTs (0=1rg,1=1rM,2=2rg,3=2rM,4=Lng,5=LnM) +1 # of lookahead depth +1 DEPTHs (>=0) +2 SWAP (0=bin-exch,1=long,2=mix) +112 swapping threshold +0 L1 in (0=transposed,1=no-transposed) form +0 U in (0=transposed,1=no-transposed) form +1 Equilibration (0=no,1=yes) +4 memory alignment in double (> 0) diff --git a/MpiApps/apps/hpl-config/HPL.dat-16s b/MpiApps/apps/hpl-config/HPL.dat-16s new file mode 100644 index 0000000..f939429 --- /dev/null +++ b/MpiApps/apps/hpl-config/HPL.dat-16s @@ -0,0 +1,31 @@ +HPLinpack benchmark input file - small 16 process, small problem size +Innovative Computing Laboratory, University of Tennessee +HPL.out output file name (if any) +6 device out (6=stdout,7=stderr,file) +1 # of problems sizes (N) +30000 Ns +1 # of NBs +112 NBs +0 PMAP process mapping (0=Row-,1=Column-major) +1 # of process grids (P x Q) +4 Ps +4 Qs +16.0 threshold +1 # of panel fact +1 PFACTs (0=left, 1=Crout, 2=Right) +1 # of recursive stopping criterium +4 NBMINs (>= 1) +1 # of panels in recursion +2 NDIVs +1 # of recursive panel fact. +2 RFACTs (0=left, 1=Crout, 2=Right) +1 # of broadcast +1 BCASTs (0=1rg,1=1rM,2=2rg,3=2rM,4=Lng,5=LnM) +1 # of lookahead depth +1 DEPTHs (>=0) +2 SWAP (0=bin-exch,1=long,2=mix) +112 swapping threshold +0 L1 in (0=transposed,1=no-transposed) form +0 U in (0=transposed,1=no-transposed) form +1 Equilibration (0=no,1=yes) +4 memory alignment in double (> 0) diff --git a/MpiApps/apps/hpl-config/HPL.dat-16t b/MpiApps/apps/hpl-config/HPL.dat-16t new file mode 100644 index 0000000..d1b70ed --- /dev/null +++ b/MpiApps/apps/hpl-config/HPL.dat-16t @@ -0,0 +1,31 @@ +HPLinpack benchmark input file - test 16 process, tiny problem size +Innovative Computing Laboratory, University of Tennessee +HPL.out output file name (if any) +6 device out (6=stdout,7=stderr,file) +1 # of problems sizes (N) +5000 Ns +1 # of NBs +112 NBs +0 PMAP process mapping (0=Row-,1=Column-major) +1 # of process grids (P x Q) +4 Ps +4 Qs +16.0 threshold +1 # of panel fact +1 PFACTs (0=left, 1=Crout, 2=Right) +1 # of recursive stopping criterium +4 NBMINs (>= 1) +1 # of panels in recursion +2 NDIVs +1 # of recursive panel fact. +2 RFACTs (0=left, 1=Crout, 2=Right) +1 # of broadcast +1 BCASTs (0=1rg,1=1rM,2=2rg,3=2rM,4=Lng,5=LnM) +1 # of lookahead depth +1 DEPTHs (>=0) +2 SWAP (0=bin-exch,1=long,2=mix) +112 swapping threshold +0 L1 in (0=transposed,1=no-transposed) form +0 U in (0=transposed,1=no-transposed) form +1 Equilibration (0=no,1=yes) +4 memory alignment in double (> 0) diff --git a/MpiApps/apps/hpl-config/HPL.dat-18l b/MpiApps/apps/hpl-config/HPL.dat-18l new file mode 100644 index 0000000..19a1fba --- /dev/null +++ b/MpiApps/apps/hpl-config/HPL.dat-18l @@ -0,0 +1,31 @@ +HPLinpack benchmark input file - 18 processes, large problem +Innovative Computing Laboratory, University of Tennessee +HPL.out output file name (if any) +6 device out (6=stdout,7=stderr,file) +1 # of problems sizes (N) +35000 Ns +1 # of NBs +112 NBs +0 PMAP process mapping (0=Row-,1=Column-major) +1 # of process grids (P x Q) +4 Ps +4 Qs +16.0 threshold +1 # of panel fact +1 PFACTs (0=left, 1=Crout, 2=Right) +1 # of recursive stopping criterium +4 NBMINs (>= 1) +1 # of panels in recursion +2 NDIVs +1 # of recursive panel fact. +2 RFACTs (0=left, 1=Crout, 2=Right) +1 # of broadcast +1 BCASTs (0=1rg,1=1rM,2=2rg,3=2rM,4=Lng,5=LnM) +1 # of lookahead depth +1 DEPTHs (>=0) +2 SWAP (0=bin-exch,1=long,2=mix) +112 swapping threshold +0 L1 in (0=transposed,1=no-transposed) form +0 U in (0=transposed,1=no-transposed) form +1 Equilibration (0=no,1=yes) +4 memory alignment in double (> 0) diff --git a/MpiApps/apps/hpl-config/HPL.dat-18m b/MpiApps/apps/hpl-config/HPL.dat-18m new file mode 100644 index 0000000..d362874 --- /dev/null +++ b/MpiApps/apps/hpl-config/HPL.dat-18m @@ -0,0 +1,31 @@ +HPLinpack benchmark input file - 18 processes, medium problem +Innovative Computing Laboratory, University of Tennessee +HPL.out output file name (if any) +6 device out (6=stdout,7=stderr,file) +1 # of problems sizes (N) +32000 Ns +1 # of NBs +112 NBs +0 PMAP process mapping (0=Row-,1=Column-major) +1 # of process grids (P x Q) +4 Ps +4 Qs +16.0 threshold +1 # of panel fact +1 PFACTs (0=left, 1=Crout, 2=Right) +1 # of recursive stopping criterium +4 NBMINs (>= 1) +1 # of panels in recursion +2 NDIVs +1 # of recursive panel fact. +2 RFACTs (0=left, 1=Crout, 2=Right) +1 # of broadcast +1 BCASTs (0=1rg,1=1rM,2=2rg,3=2rM,4=Lng,5=LnM) +1 # of lookahead depth +1 DEPTHs (>=0) +2 SWAP (0=bin-exch,1=long,2=mix) +112 swapping threshold +0 L1 in (0=transposed,1=no-transposed) form +0 U in (0=transposed,1=no-transposed) form +1 Equilibration (0=no,1=yes) +4 memory alignment in double (> 0) diff --git a/MpiApps/apps/hpl-config/HPL.dat-18s b/MpiApps/apps/hpl-config/HPL.dat-18s new file mode 100644 index 0000000..83cad18 --- /dev/null +++ b/MpiApps/apps/hpl-config/HPL.dat-18s @@ -0,0 +1,31 @@ +HPLinpack benchmark input file - 18 processes, small problem +Innovative Computing Laboratory, University of Tennessee +HPL.out output file name (if any) +6 device out (6=stdout,7=stderr,file) +1 # of problems sizes (N) +30000 Ns +1 # of NBs +112 NBs +0 PMAP process mapping (0=Row-,1=Column-major) +1 # of process grids (P x Q) +4 Ps +4 Qs +16.0 threshold +1 # of panel fact +1 PFACTs (0=left, 1=Crout, 2=Right) +1 # of recursive stopping criterium +4 NBMINs (>= 1) +1 # of panels in recursion +2 NDIVs +1 # of recursive panel fact. +2 RFACTs (0=left, 1=Crout, 2=Right) +1 # of broadcast +1 BCASTs (0=1rg,1=1rM,2=2rg,3=2rM,4=Lng,5=LnM) +1 # of lookahead depth +1 DEPTHs (>=0) +2 SWAP (0=bin-exch,1=long,2=mix) +112 swapping threshold +0 L1 in (0=transposed,1=no-transposed) form +0 U in (0=transposed,1=no-transposed) form +1 Equilibration (0=no,1=yes) +4 memory alignment in double (> 0) diff --git a/MpiApps/apps/hpl-config/HPL.dat-18t b/MpiApps/apps/hpl-config/HPL.dat-18t new file mode 100644 index 0000000..6f57dde --- /dev/null +++ b/MpiApps/apps/hpl-config/HPL.dat-18t @@ -0,0 +1,31 @@ +HPLinpack benchmark input file - 18 processes, very small problem. +Innovative Computing Laboratory, University of Tennessee +HPL.out output file name (if any) +6 device out (6=stdout,7=stderr,file) +1 # of problems sizes (N) +5000 Ns +1 # of NBs +112 NBs +0 PMAP process mapping (0=Row-,1=Column-major) +1 # of process grids (P x Q) +4 Ps +4 Qs +16.0 threshold +1 # of panel fact +1 PFACTs (0=left, 1=Crout, 2=Right) +1 # of recursive stopping criterium +4 NBMINs (>= 1) +1 # of panels in recursion +2 NDIVs +1 # of recursive panel fact. +2 RFACTs (0=left, 1=Crout, 2=Right) +1 # of broadcast +1 BCASTs (0=1rg,1=1rM,2=2rg,3=2rM,4=Lng,5=LnM) +1 # of lookahead depth +1 DEPTHs (>=0) +2 SWAP (0=bin-exch,1=long,2=mix) +112 swapping threshold +0 L1 in (0=transposed,1=no-transposed) form +0 U in (0=transposed,1=no-transposed) form +1 Equilibration (0=no,1=yes) +4 memory alignment in double (> 0) diff --git a/MpiApps/apps/hpl-config/HPL.dat-1l b/MpiApps/apps/hpl-config/HPL.dat-1l new file mode 100644 index 0000000..127eb44 --- /dev/null +++ b/MpiApps/apps/hpl-config/HPL.dat-1l @@ -0,0 +1,31 @@ +HPLinpack benchmark input file - 1 process, large problem size +Innovative Computing Laboratory, University of Tennessee +HPL.out output file name (if any) +6 device out (6=stdout,7=stderr,file) +1 # of problems sizes (N) +9000 Ns +1 # of NBs +112 NBs +0 PMAP process mapping (0=Row-,1=Column-major) +1 # of process grids (P x Q) +1 Ps +1 Qs +16.0 threshold +1 # of panel fact +1 PFACTs (0=left, 1=Crout, 2=Right) +1 # of recursive stopping criterium +4 NBMINs (>= 1) +1 # of panels in recursion +2 NDIVs +1 # of recursive panel fact. +2 RFACTs (0=left, 1=Crout, 2=Right) +1 # of broadcast +1 BCASTs (0=1rg,1=1rM,2=2rg,3=2rM,4=Lng,5=LnM) +1 # of lookahead depth +1 DEPTHs (>=0) +2 SWAP (0=bin-exch,1=long,2=mix) +112 swapping threshold +0 L1 in (0=transposed,1=no-transposed) form +0 U in (0=transposed,1=no-transposed) form +1 Equilibration (0=no,1=yes) +4 memory alignment in double (> 0) diff --git a/MpiApps/apps/hpl-config/HPL.dat-1m b/MpiApps/apps/hpl-config/HPL.dat-1m new file mode 100644 index 0000000..5a2d245 --- /dev/null +++ b/MpiApps/apps/hpl-config/HPL.dat-1m @@ -0,0 +1,31 @@ +HPLinpack benchmark input file - 1 process, medium problem size +Innovative Computing Laboratory, University of Tennessee +HPL.out output file name (if any) +6 device out (6=stdout,7=stderr,file) +1 # of problems sizes (N) +8000 Ns +1 # of NBs +112 NBs +0 PMAP process mapping (0=Row-,1=Column-major) +1 # of process grids (P x Q) +1 Ps +1 Qs +16.0 threshold +1 # of panel fact +1 PFACTs (0=left, 1=Crout, 2=Right) +1 # of recursive stopping criterium +4 NBMINs (>= 1) +1 # of panels in recursion +2 NDIVs +1 # of recursive panel fact. +2 RFACTs (0=left, 1=Crout, 2=Right) +1 # of broadcast +1 BCASTs (0=1rg,1=1rM,2=2rg,3=2rM,4=Lng,5=LnM) +1 # of lookahead depth +1 DEPTHs (>=0) +2 SWAP (0=bin-exch,1=long,2=mix) +112 swapping threshold +0 L1 in (0=transposed,1=no-transposed) form +0 U in (0=transposed,1=no-transposed) form +1 Equilibration (0=no,1=yes) +4 memory alignment in double (> 0) diff --git a/MpiApps/apps/hpl-config/HPL.dat-1s b/MpiApps/apps/hpl-config/HPL.dat-1s new file mode 100644 index 0000000..9e882c6 --- /dev/null +++ b/MpiApps/apps/hpl-config/HPL.dat-1s @@ -0,0 +1,31 @@ +HPLinpack benchmark input file - small 1 process, small problem size +Innovative Computing Laboratory, University of Tennessee +HPL.out output file name (if any) +6 device out (6=stdout,7=stderr,file) +1 # of problems sizes (N) +8000 Ns +1 # of NBs +112 NBs +0 PMAP process mapping (0=Row-,1=Column-major) +1 # of process grids (P x Q) +1 Ps +1 Qs +16.0 threshold +1 # of panel fact +1 PFACTs (0=left, 1=Crout, 2=Right) +1 # of recursive stopping criterium +4 NBMINs (>= 1) +1 # of panels in recursion +2 NDIVs +1 # of recursive panel fact. +2 RFACTs (0=left, 1=Crout, 2=Right) +1 # of broadcast +1 BCASTs (0=1rg,1=1rM,2=2rg,3=2rM,4=Lng,5=LnM) +1 # of lookahead depth +1 DEPTHs (>=0) +2 SWAP (0=bin-exch,1=long,2=mix) +112 swapping threshold +0 L1 in (0=transposed,1=no-transposed) form +0 U in (0=transposed,1=no-transposed) form +1 Equilibration (0=no,1=yes) +4 memory alignment in double (> 0) diff --git a/MpiApps/apps/hpl-config/HPL.dat-1t b/MpiApps/apps/hpl-config/HPL.dat-1t new file mode 100644 index 0000000..9fc3bc6 --- /dev/null +++ b/MpiApps/apps/hpl-config/HPL.dat-1t @@ -0,0 +1,31 @@ +HPLinpack benchmark input file - test 1 process, tiny problem size +Innovative Computing Laboratory, University of Tennessee +HPL.out output file name (if any) +6 device out (6=stdout,7=stderr,file) +1 # of problems sizes (N) +5000 Ns +1 # of NBs +112 NBs +0 PMAP process mapping (0=Row-,1=Column-major) +1 # of process grids (P x Q) +1 Ps +1 Qs +16.0 threshold +1 # of panel fact +1 PFACTs (0=left, 1=Crout, 2=Right) +1 # of recursive stopping criterium +4 NBMINs (>= 1) +1 # of panels in recursion +2 NDIVs +1 # of recursive panel fact. +2 RFACTs (0=left, 1=Crout, 2=Right) +1 # of broadcast +1 BCASTs (0=1rg,1=1rM,2=2rg,3=2rM,4=Lng,5=LnM) +1 # of lookahead depth +1 DEPTHs (>=0) +2 SWAP (0=bin-exch,1=long,2=mix) +112 swapping threshold +0 L1 in (0=transposed,1=no-transposed) form +0 U in (0=transposed,1=no-transposed) form +1 Equilibration (0=no,1=yes) +4 memory alignment in double (> 0) diff --git a/MpiApps/apps/hpl-config/HPL.dat-256l b/MpiApps/apps/hpl-config/HPL.dat-256l new file mode 100644 index 0000000..ddc7b82 --- /dev/null +++ b/MpiApps/apps/hpl-config/HPL.dat-256l @@ -0,0 +1,31 @@ +HPLinpack benchmark input file - 256 process, large problem size +Innovative Computing Laboratory, University of Tennessee +HPL.out output file name (if any) +6 device out (6=stdout,7=stderr,file) +1 # of problems sizes (N) +130000 Ns +1 # of NBs +112 NBs +0 PMAP process mapping (0=Row-,1=Column-major) +1 # of process grids (P x Q) +16 Ps +16 Qs +16.0 threshold +1 # of panel fact +1 PFACTs (0=left, 1=Crout, 2=Right) +1 # of recursive stopping criterium +4 NBMINs (>= 1) +1 # of panels in recursion +2 NDIVs +1 # of recursive panel fact. +2 RFACTs (0=left, 1=Crout, 2=Right) +1 # of broadcast +1 BCASTs (0=1rg,1=1rM,2=2rg,3=2rM,4=Lng,5=LnM) +1 # of lookahead depth +1 DEPTHs (>=0) +2 SWAP (0=bin-exch,1=long,2=mix) +112 swapping threshold +0 L1 in (0=transposed,1=no-transposed) form +0 U in (0=transposed,1=no-transposed) form +1 Equilibration (0=no,1=yes) +4 memory alignment in double (> 0) diff --git a/MpiApps/apps/hpl-config/HPL.dat-256m b/MpiApps/apps/hpl-config/HPL.dat-256m new file mode 100644 index 0000000..87dbad6 --- /dev/null +++ b/MpiApps/apps/hpl-config/HPL.dat-256m @@ -0,0 +1,31 @@ +HPLinpack benchmark input file - 256 process, medium problem size +Innovative Computing Laboratory, University of Tennessee +HPL.out output file name (if any) +6 device out (6=stdout,7=stderr,file) +1 # of problems sizes (N) +125000 Ns +1 # of NBs +112 NBs +0 PMAP process mapping (0=Row-,1=Column-major) +1 # of process grids (P x Q) +16 Ps +16 Qs +16.0 threshold +1 # of panel fact +1 PFACTs (0=left, 1=Crout, 2=Right) +1 # of recursive stopping criterium +4 NBMINs (>= 1) +1 # of panels in recursion +2 NDIVs +1 # of recursive panel fact. +2 RFACTs (0=left, 1=Crout, 2=Right) +1 # of broadcast +1 BCASTs (0=1rg,1=1rM,2=2rg,3=2rM,4=Lng,5=LnM) +1 # of lookahead depth +1 DEPTHs (>=0) +2 SWAP (0=bin-exch,1=long,2=mix) +112 swapping threshold +0 L1 in (0=transposed,1=no-transposed) form +0 U in (0=transposed,1=no-transposed) form +1 Equilibration (0=no,1=yes) +4 memory alignment in double (> 0) diff --git a/MpiApps/apps/hpl-config/HPL.dat-256s b/MpiApps/apps/hpl-config/HPL.dat-256s new file mode 100644 index 0000000..40be5e7 --- /dev/null +++ b/MpiApps/apps/hpl-config/HPL.dat-256s @@ -0,0 +1,31 @@ +HPLinpack benchmark input file - small 256 process, small problem size +Innovative Computing Laboratory, University of Tennessee +HPL.out output file name (if any) +6 device out (6=stdout,7=stderr,file) +1 # of problems sizes (N) +120000 Ns +1 # of NBs +112 NBs +0 PMAP process mapping (0=Row-,1=Column-major) +1 # of process grids (P x Q) +16 Ps +16 Qs +16.0 threshold +1 # of panel fact +1 PFACTs (0=left, 1=Crout, 2=Right) +1 # of recursive stopping criterium +4 NBMINs (>= 1) +1 # of panels in recursion +2 NDIVs +1 # of recursive panel fact. +2 RFACTs (0=left, 1=Crout, 2=Right) +1 # of broadcast +1 BCASTs (0=1rg,1=1rM,2=2rg,3=2rM,4=Lng,5=LnM) +1 # of lookahead depth +1 DEPTHs (>=0) +2 SWAP (0=bin-exch,1=long,2=mix) +112 swapping threshold +0 L1 in (0=transposed,1=no-transposed) form +0 U in (0=transposed,1=no-transposed) form +1 Equilibration (0=no,1=yes) +4 memory alignment in double (> 0) diff --git a/MpiApps/apps/hpl-config/HPL.dat-256t b/MpiApps/apps/hpl-config/HPL.dat-256t new file mode 100644 index 0000000..bf00550 --- /dev/null +++ b/MpiApps/apps/hpl-config/HPL.dat-256t @@ -0,0 +1,31 @@ +HPLinpack benchmark input file - test 256 process, tiny problem size +Innovative Computing Laboratory, University of Tennessee +HPL.out output file name (if any) +6 device out (6=stdout,7=stderr,file) +1 # of problems sizes (N) +5000 Ns +1 # of NBs +112 NBs +0 PMAP process mapping (0=Row-,1=Column-major) +1 # of process grids (P x Q) +16 Ps +16 Qs +16.0 threshold +1 # of panel fact +1 PFACTs (0=left, 1=Crout, 2=Right) +1 # of recursive stopping criterium +4 NBMINs (>= 1) +1 # of panels in recursion +2 NDIVs +1 # of recursive panel fact. +2 RFACTs (0=left, 1=Crout, 2=Right) +1 # of broadcast +1 BCASTs (0=1rg,1=1rM,2=2rg,3=2rM,4=Lng,5=LnM) +1 # of lookahead depth +1 DEPTHs (>=0) +2 SWAP (0=bin-exch,1=long,2=mix) +112 swapping threshold +0 L1 in (0=transposed,1=no-transposed) form +0 U in (0=transposed,1=no-transposed) form +1 Equilibration (0=no,1=yes) +4 memory alignment in double (> 0) diff --git a/MpiApps/apps/hpl-config/HPL.dat-2l b/MpiApps/apps/hpl-config/HPL.dat-2l new file mode 100644 index 0000000..4aab220 --- /dev/null +++ b/MpiApps/apps/hpl-config/HPL.dat-2l @@ -0,0 +1,31 @@ +HPLinpack benchmark input file - 2 process, large problem size +Innovative Computing Laboratory, University of Tennessee +HPL.out output file name (if any) +6 device out (6=stdout,7=stderr,file) +1 # of problems sizes (N) +15000 Ns +1 # of NBs +112 NBs +0 PMAP process mapping (0=Row-,1=Column-major) +1 # of process grids (P x Q) +1 Ps +2 Qs +16.0 threshold +1 # of panel fact +1 PFACTs (0=left, 1=Crout, 2=Right) +1 # of recursive stopping criterium +4 NBMINs (>= 1) +1 # of panels in recursion +2 NDIVs +1 # of recursive panel fact. +2 RFACTs (0=left, 1=Crout, 2=Right) +1 # of broadcast +1 BCASTs (0=1rg,1=1rM,2=2rg,3=2rM,4=Lng,5=LnM) +1 # of lookahead depth +1 DEPTHs (>=0) +2 SWAP (0=bin-exch,1=long,2=mix) +112 swapping threshold +0 L1 in (0=transposed,1=no-transposed) form +0 U in (0=transposed,1=no-transposed) form +1 Equilibration (0=no,1=yes) +4 memory alignment in double (> 0) diff --git a/MpiApps/apps/hpl-config/HPL.dat-2m b/MpiApps/apps/hpl-config/HPL.dat-2m new file mode 100644 index 0000000..d721a5a --- /dev/null +++ b/MpiApps/apps/hpl-config/HPL.dat-2m @@ -0,0 +1,31 @@ +HPLinpack benchmark input file - 2 process, medium problem size +Innovative Computing Laboratory, University of Tennessee +HPL.out output file name (if any) +6 device out (6=stdout,7=stderr,file) +1 # of problems sizes (N) +12000 Ns +1 # of NBs +112 NBs +0 PMAP process mapping (0=Row-,1=Column-major) +1 # of process grids (P x Q) +1 Ps +2 Qs +16.0 threshold +1 # of panel fact +1 PFACTs (0=left, 1=Crout, 2=Right) +1 # of recursive stopping criterium +4 NBMINs (>= 1) +1 # of panels in recursion +2 NDIVs +1 # of recursive panel fact. +2 RFACTs (0=left, 1=Crout, 2=Right) +1 # of broadcast +1 BCASTs (0=1rg,1=1rM,2=2rg,3=2rM,4=Lng,5=LnM) +1 # of lookahead depth +1 DEPTHs (>=0) +2 SWAP (0=bin-exch,1=long,2=mix) +112 swapping threshold +0 L1 in (0=transposed,1=no-transposed) form +0 U in (0=transposed,1=no-transposed) form +1 Equilibration (0=no,1=yes) +4 memory alignment in double (> 0) diff --git a/MpiApps/apps/hpl-config/HPL.dat-2s b/MpiApps/apps/hpl-config/HPL.dat-2s new file mode 100644 index 0000000..08e41b0 --- /dev/null +++ b/MpiApps/apps/hpl-config/HPL.dat-2s @@ -0,0 +1,31 @@ +HPLinpack benchmark input file - 2 process, small problem size +Innovative Computing Laboratory, University of Tennessee +HPL.out output file name (if any) +6 device out (6=stdout,7=stderr,file) +1 # of problems sizes (N) +10000 Ns +1 # of NBs +112 NBs +0 PMAP process mapping (0=Row-,1=Column-major) +1 # of process grids (P x Q) +1 Ps +2 Qs +16.0 threshold +1 # of panel fact +1 PFACTs (0=left, 1=Crout, 2=Right) +1 # of recursive stopping criterium +4 NBMINs (>= 1) +1 # of panels in recursion +2 NDIVs +1 # of recursive panel fact. +2 RFACTs (0=left, 1=Crout, 2=Right) +1 # of broadcast +1 BCASTs (0=1rg,1=1rM,2=2rg,3=2rM,4=Lng,5=LnM) +1 # of lookahead depth +1 DEPTHs (>=0) +2 SWAP (0=bin-exch,1=long,2=mix) +112 swapping threshold +0 L1 in (0=transposed,1=no-transposed) form +0 U in (0=transposed,1=no-transposed) form +1 Equilibration (0=no,1=yes) +4 memory alignment in double (> 0) diff --git a/MpiApps/apps/hpl-config/HPL.dat-2t b/MpiApps/apps/hpl-config/HPL.dat-2t new file mode 100644 index 0000000..54a7e88 --- /dev/null +++ b/MpiApps/apps/hpl-config/HPL.dat-2t @@ -0,0 +1,31 @@ +HPLinpack benchmark input file - test 2 process, tiny problem size +Innovative Computing Laboratory, University of Tennessee +HPL.out output file name (if any) +6 device out (6=stdout,7=stderr,file) +1 # of problems sizes (N) +5000 Ns +1 # of NBs +112 NBs +0 PMAP process mapping (0=Row-,1=Column-major) +1 # of process grids (P x Q) +1 Ps +2 Qs +16.0 threshold +1 # of panel fact +1 PFACTs (0=left, 1=Crout, 2=Right) +1 # of recursive stopping criterium +4 NBMINs (>= 1) +1 # of panels in recursion +2 NDIVs +1 # of recursive panel fact. +2 RFACTs (0=left, 1=Crout, 2=Right) +1 # of broadcast +1 BCASTs (0=1rg,1=1rM,2=2rg,3=2rM,4=Lng,5=LnM) +1 # of lookahead depth +1 DEPTHs (>=0) +2 SWAP (0=bin-exch,1=long,2=mix) +112 swapping threshold +0 L1 in (0=transposed,1=no-transposed) form +0 U in (0=transposed,1=no-transposed) form +1 Equilibration (0=no,1=yes) +4 memory alignment in double (> 0) diff --git a/MpiApps/apps/hpl-config/HPL.dat-300l b/MpiApps/apps/hpl-config/HPL.dat-300l new file mode 100644 index 0000000..6140a5a --- /dev/null +++ b/MpiApps/apps/hpl-config/HPL.dat-300l @@ -0,0 +1,31 @@ +HPLinpack benchmark input file - 300 process, large problem size +Innovative Computing Laboratory, University of Tennessee +HPL.out output file name (if any) +6 device out (6=stdout,7=stderr,file) +1 # of problems sizes (N) +130000 Ns +1 # of NBs +112 NBs +0 PMAP process mapping (0=Row-,1=Column-major) +1 # of process grids (P x Q) +15 Ps +20 Qs +16.0 threshold +1 # of panel fact +1 PFACTs (0=left, 1=Crout, 2=Right) +1 # of recursive stopping criterium +4 NBMINs (>= 1) +1 # of panels in recursion +2 NDIVs +1 # of recursive panel fact. +2 RFACTs (0=left, 1=Crout, 2=Right) +1 # of broadcast +1 BCASTs (0=1rg,1=1rM,2=2rg,3=2rM,4=Lng,5=LnM) +1 # of lookahead depth +1 DEPTHs (>=0) +2 SWAP (0=bin-exch,1=long,2=mix) +112 swapping threshold +0 L1 in (0=transposed,1=no-transposed) form +0 U in (0=transposed,1=no-transposed) form +1 Equilibration (0=no,1=yes) +4 memory alignment in double (> 0) diff --git a/MpiApps/apps/hpl-config/HPL.dat-300m b/MpiApps/apps/hpl-config/HPL.dat-300m new file mode 100644 index 0000000..6b24ae2 --- /dev/null +++ b/MpiApps/apps/hpl-config/HPL.dat-300m @@ -0,0 +1,31 @@ +HPLinpack benchmark input file - 300 process, medium problem size +Innovative Computing Laboratory, University of Tennessee +HPL.out output file name (if any) +6 device out (6=stdout,7=stderr,file) +1 # of problems sizes (N) +130000 Ns +1 # of NBs +112 NBs +0 PMAP process mapping (0=Row-,1=Column-major) +1 # of process grids (P x Q) +15 Ps +20 Qs +16.0 threshold +1 # of panel fact +1 PFACTs (0=left, 1=Crout, 2=Right) +1 # of recursive stopping criterium +4 NBMINs (>= 1) +1 # of panels in recursion +2 NDIVs +1 # of recursive panel fact. +2 RFACTs (0=left, 1=Crout, 2=Right) +1 # of broadcast +1 BCASTs (0=1rg,1=1rM,2=2rg,3=2rM,4=Lng,5=LnM) +1 # of lookahead depth +1 DEPTHs (>=0) +2 SWAP (0=bin-exch,1=long,2=mix) +112 swapping threshold +0 L1 in (0=transposed,1=no-transposed) form +0 U in (0=transposed,1=no-transposed) form +1 Equilibration (0=no,1=yes) +4 memory alignment in double (> 0) diff --git a/MpiApps/apps/hpl-config/HPL.dat-300s b/MpiApps/apps/hpl-config/HPL.dat-300s new file mode 100644 index 0000000..4fa9aa8 --- /dev/null +++ b/MpiApps/apps/hpl-config/HPL.dat-300s @@ -0,0 +1,31 @@ +HPLinpack benchmark input file - 300 process, small problem size +Innovative Computing Laboratory, University of Tennessee +HPL.out output file name (if any) +6 device out (6=stdout,7=stderr,file) +1 # of problems sizes (N) +130000 Ns +1 # of NBs +112 NBs +0 PMAP process mapping (0=Row-,1=Column-major) +1 # of process grids (P x Q) +15 Ps +20 Qs +16.0 threshold +1 # of panel fact +1 PFACTs (0=left, 1=Crout, 2=Right) +1 # of recursive stopping criterium +4 NBMINs (>= 1) +1 # of panels in recursion +2 NDIVs +1 # of recursive panel fact. +2 RFACTs (0=left, 1=Crout, 2=Right) +1 # of broadcast +1 BCASTs (0=1rg,1=1rM,2=2rg,3=2rM,4=Lng,5=LnM) +1 # of lookahead depth +1 DEPTHs (>=0) +2 SWAP (0=bin-exch,1=long,2=mix) +112 swapping threshold +0 L1 in (0=transposed,1=no-transposed) form +0 U in (0=transposed,1=no-transposed) form +1 Equilibration (0=no,1=yes) +4 memory alignment in double (> 0) diff --git a/MpiApps/apps/hpl-config/HPL.dat-300t b/MpiApps/apps/hpl-config/HPL.dat-300t new file mode 100644 index 0000000..20a7902 --- /dev/null +++ b/MpiApps/apps/hpl-config/HPL.dat-300t @@ -0,0 +1,31 @@ +HPLinpack benchmark input file - test 300 process, tiny problem size +Innovative Computing Laboratory, University of Tennessee +HPL.out output file name (if any) +6 device out (6=stdout,7=stderr,file) +1 # of problems sizes (N) +5000 Ns +1 # of NBs +112 NBs +0 PMAP process mapping (0=Row-,1=Column-major) +1 # of process grids (P x Q) +15 Ps +20 Qs +16.0 threshold +1 # of panel fact +1 PFACTs (0=left, 1=Crout, 2=Right) +1 # of recursive stopping criterium +4 NBMINs (>= 1) +1 # of panels in recursion +2 NDIVs +1 # of recursive panel fact. +2 RFACTs (0=left, 1=Crout, 2=Right) +1 # of broadcast +1 BCASTs (0=1rg,1=1rM,2=2rg,3=2rM,4=Lng,5=LnM) +1 # of lookahead depth +1 DEPTHs (>=0) +2 SWAP (0=bin-exch,1=long,2=mix) +112 swapping threshold +0 L1 in (0=transposed,1=no-transposed) form +0 U in (0=transposed,1=no-transposed) form +1 Equilibration (0=no,1=yes) +4 memory alignment in double (> 0) diff --git a/MpiApps/apps/hpl-config/HPL.dat-320l b/MpiApps/apps/hpl-config/HPL.dat-320l new file mode 100644 index 0000000..9645e14 --- /dev/null +++ b/MpiApps/apps/hpl-config/HPL.dat-320l @@ -0,0 +1,31 @@ +HPLinpack benchmark input file - 512 process, large problem size +Innovative Computing Laboratory, University of Tennessee +HPL.out output file name (if any) +6 device out (6=stdout,7=stderr,file) +1 # of problems sizes (N) +145000 Ns +1 # of NBs +112 NBs +0 PMAP process mapping (0=Row-,1=Column-major) +1 # of process grids (P x Q) +16 Ps +20 Qs +16.0 threshold +1 # of panel fact +1 PFACTs (0=left, 1=Crout, 2=Right) +1 # of recursive stopping criterium +4 NBMINs (>= 1) +1 # of panels in recursion +2 NDIVs +1 # of recursive panel fact. +2 RFACTs (0=left, 1=Crout, 2=Right) +1 # of broadcast +1 BCASTs (0=1rg,1=1rM,2=2rg,3=2rM,4=Lng,5=LnM) +1 # of lookahead depth +1 DEPTHs (>=0) +2 SWAP (0=bin-exch,1=long,2=mix) +112 swapping threshold +0 L1 in (0=transposed,1=no-transposed) form +0 U in (0=transposed,1=no-transposed) form +1 Equilibration (0=no,1=yes) +4 memory alignment in double (> 0) diff --git a/MpiApps/apps/hpl-config/HPL.dat-320m b/MpiApps/apps/hpl-config/HPL.dat-320m new file mode 100644 index 0000000..9f5844d --- /dev/null +++ b/MpiApps/apps/hpl-config/HPL.dat-320m @@ -0,0 +1,31 @@ +HPLinpack benchmark input file - 512 process, medium problem size +Innovative Computing Laboratory, University of Tennessee +HPL.out output file name (if any) +6 device out (6=stdout,7=stderr,file) +1 # of problems sizes (N) +140000 Ns +1 # of NBs +112 NBs +0 PMAP process mapping (0=Row-,1=Column-major) +1 # of process grids (P x Q) +16 Ps +20 Qs +16.0 threshold +1 # of panel fact +1 PFACTs (0=left, 1=Crout, 2=Right) +1 # of recursive stopping criterium +4 NBMINs (>= 1) +1 # of panels in recursion +2 NDIVs +1 # of recursive panel fact. +2 RFACTs (0=left, 1=Crout, 2=Right) +1 # of broadcast +1 BCASTs (0=1rg,1=1rM,2=2rg,3=2rM,4=Lng,5=LnM) +1 # of lookahead depth +1 DEPTHs (>=0) +2 SWAP (0=bin-exch,1=long,2=mix) +112 swapping threshold +0 L1 in (0=transposed,1=no-transposed) form +0 U in (0=transposed,1=no-transposed) form +1 Equilibration (0=no,1=yes) +4 memory alignment in double (> 0) diff --git a/MpiApps/apps/hpl-config/HPL.dat-320s b/MpiApps/apps/hpl-config/HPL.dat-320s new file mode 100644 index 0000000..f88add8 --- /dev/null +++ b/MpiApps/apps/hpl-config/HPL.dat-320s @@ -0,0 +1,31 @@ +HPLinpack benchmark input file - 320 process, small problem size +Innovative Computing Laboratory, University of Tennessee +HPL.out output file name (if any) +6 device out (6=stdout,7=stderr,file) +1 # of problems sizes (N) +135000 Ns +1 # of NBs +112 NBs +0 PMAP process mapping (0=Row-,1=Column-major) +1 # of process grids (P x Q) +16 Ps +20 Qs +16.0 threshold +1 # of panel fact +1 PFACTs (0=left, 1=Crout, 2=Right) +1 # of recursive stopping criterium +4 NBMINs (>= 1) +1 # of panels in recursion +2 NDIVs +1 # of recursive panel fact. +2 RFACTs (0=left, 1=Crout, 2=Right) +1 # of broadcast +1 BCASTs (0=1rg,1=1rM,2=2rg,3=2rM,4=Lng,5=LnM) +1 # of lookahead depth +1 DEPTHs (>=0) +2 SWAP (0=bin-exch,1=long,2=mix) +112 swapping threshold +0 L1 in (0=transposed,1=no-transposed) form +0 U in (0=transposed,1=no-transposed) form +1 Equilibration (0=no,1=yes) +4 memory alignment in double (> 0) diff --git a/MpiApps/apps/hpl-config/HPL.dat-320t b/MpiApps/apps/hpl-config/HPL.dat-320t new file mode 100644 index 0000000..5487b5a --- /dev/null +++ b/MpiApps/apps/hpl-config/HPL.dat-320t @@ -0,0 +1,31 @@ +HPLinpack benchmark input file - test 512 process, tiny problem size +Innovative Computing Laboratory, University of Tennessee +HPL.out output file name (if any) +6 device out (6=stdout,7=stderr,file) +1 # of problems sizes (N) +5000 Ns +1 # of NBs +112 NBs +0 PMAP process mapping (0=Row-,1=Column-major) +1 # of process grids (P x Q) +16 Ps +20 Qs +16.0 threshold +1 # of panel fact +1 PFACTs (0=left, 1=Crout, 2=Right) +1 # of recursive stopping criterium +4 NBMINs (>= 1) +1 # of panels in recursion +2 NDIVs +1 # of recursive panel fact. +2 RFACTs (0=left, 1=Crout, 2=Right) +1 # of broadcast +1 BCASTs (0=1rg,1=1rM,2=2rg,3=2rM,4=Lng,5=LnM) +1 # of lookahead depth +1 DEPTHs (>=0) +2 SWAP (0=bin-exch,1=long,2=mix) +112 swapping threshold +0 L1 in (0=transposed,1=no-transposed) form +0 U in (0=transposed,1=no-transposed) form +1 Equilibration (0=no,1=yes) +4 memory alignment in double (> 0) diff --git a/MpiApps/apps/hpl-config/HPL.dat-32l b/MpiApps/apps/hpl-config/HPL.dat-32l new file mode 100644 index 0000000..02e3ed1 --- /dev/null +++ b/MpiApps/apps/hpl-config/HPL.dat-32l @@ -0,0 +1,31 @@ +HPLinpack benchmark input file - 32 process, large problem size +Innovative Computing Laboratory, University of Tennessee +HPL.out output file name (if any) +6 device out (6=stdout,7=stderr,file) +1 # of problems sizes (N) +45000 Ns +1 # of NBs +112 NBs +0 PMAP process mapping (0=Row-,1=Column-major) +1 # of process grids (P x Q) +4 Ps +8 Qs +16.0 threshold +1 # of panel fact +1 PFACTs (0=left, 1=Crout, 2=Right) +1 # of recursive stopping criterium +4 NBMINs (>= 1) +1 # of panels in recursion +2 NDIVs +1 # of recursive panel fact. +2 RFACTs (0=left, 1=Crout, 2=Right) +1 # of broadcast +1 BCASTs (0=1rg,1=1rM,2=2rg,3=2rM,4=Lng,5=LnM) +1 # of lookahead depth +1 DEPTHs (>=0) +2 SWAP (0=bin-exch,1=long,2=mix) +112 swapping threshold +0 L1 in (0=transposed,1=no-transposed) form +0 U in (0=transposed,1=no-transposed) form +1 Equilibration (0=no,1=yes) +4 memory alignment in double (> 0) diff --git a/MpiApps/apps/hpl-config/HPL.dat-32m b/MpiApps/apps/hpl-config/HPL.dat-32m new file mode 100644 index 0000000..24cba0d --- /dev/null +++ b/MpiApps/apps/hpl-config/HPL.dat-32m @@ -0,0 +1,31 @@ +HPLinpack benchmark input file - 32 process, medium problem size +Innovative Computing Laboratory, University of Tennessee +HPL.out output file name (if any) +6 device out (6=stdout,7=stderr,file) +1 # of problems sizes (N) +43000 Ns +1 # of NBs +112 NBs +0 PMAP process mapping (0=Row-,1=Column-major) +1 # of process grids (P x Q) +4 Ps +8 Qs +16.0 threshold +1 # of panel fact +1 PFACTs (0=left, 1=Crout, 2=Right) +1 # of recursive stopping criterium +4 NBMINs (>= 1) +1 # of panels in recursion +2 NDIVs +1 # of recursive panel fact. +2 RFACTs (0=left, 1=Crout, 2=Right) +1 # of broadcast +1 BCASTs (0=1rg,1=1rM,2=2rg,3=2rM,4=Lng,5=LnM) +1 # of lookahead depth +1 DEPTHs (>=0) +2 SWAP (0=bin-exch,1=long,2=mix) +112 swapping threshold +0 L1 in (0=transposed,1=no-transposed) form +0 U in (0=transposed,1=no-transposed) form +1 Equilibration (0=no,1=yes) +4 memory alignment in double (> 0) diff --git a/MpiApps/apps/hpl-config/HPL.dat-32s b/MpiApps/apps/hpl-config/HPL.dat-32s new file mode 100644 index 0000000..9e8c563 --- /dev/null +++ b/MpiApps/apps/hpl-config/HPL.dat-32s @@ -0,0 +1,31 @@ +HPLinpack benchmark input file - 32 process, small problem size +Innovative Computing Laboratory, University of Tennessee +HPL.out output file name (if any) +6 device out (6=stdout,7=stderr,file) +1 # of problems sizes (N) +40000 Ns +1 # of NBs +112 NBs +0 PMAP process mapping (0=Row-,1=Column-major) +1 # of process grids (P x Q) +4 Ps +8 Qs +16.0 threshold +1 # of panel fact +1 PFACTs (0=left, 1=Crout, 2=Right) +1 # of recursive stopping criterium +4 NBMINs (>= 1) +1 # of panels in recursion +2 NDIVs +1 # of recursive panel fact. +2 RFACTs (0=left, 1=Crout, 2=Right) +1 # of broadcast +1 BCASTs (0=1rg,1=1rM,2=2rg,3=2rM,4=Lng,5=LnM) +1 # of lookahead depth +1 DEPTHs (>=0) +2 SWAP (0=bin-exch,1=long,2=mix) +112 swapping threshold +0 L1 in (0=transposed,1=no-transposed) form +0 U in (0=transposed,1=no-transposed) form +1 Equilibration (0=no,1=yes) +4 memory alignment in double (> 0) diff --git a/MpiApps/apps/hpl-config/HPL.dat-32t b/MpiApps/apps/hpl-config/HPL.dat-32t new file mode 100644 index 0000000..20c6a72 --- /dev/null +++ b/MpiApps/apps/hpl-config/HPL.dat-32t @@ -0,0 +1,31 @@ +HPLinpack benchmark input file - test 32 process, tiny problem size +Innovative Computing Laboratory, University of Tennessee +HPL.out output file name (if any) +6 device out (6=stdout,7=stderr,file) +1 # of problems sizes (N) +5000 Ns +1 # of NBs +112 NBs +0 PMAP process mapping (0=Row-,1=Column-major) +1 # of process grids (P x Q) +4 Ps +8 Qs +16.0 threshold +1 # of panel fact +1 PFACTs (0=left, 1=Crout, 2=Right) +1 # of recursive stopping criterium +4 NBMINs (>= 1) +1 # of panels in recursion +2 NDIVs +1 # of recursive panel fact. +2 RFACTs (0=left, 1=Crout, 2=Right) +1 # of broadcast +1 BCASTs (0=1rg,1=1rM,2=2rg,3=2rM,4=Lng,5=LnM) +1 # of lookahead depth +1 DEPTHs (>=0) +2 SWAP (0=bin-exch,1=long,2=mix) +112 swapping threshold +0 L1 in (0=transposed,1=no-transposed) form +0 U in (0=transposed,1=no-transposed) form +1 Equilibration (0=no,1=yes) +4 memory alignment in double (> 0) diff --git a/MpiApps/apps/hpl-config/HPL.dat-4l b/MpiApps/apps/hpl-config/HPL.dat-4l new file mode 100644 index 0000000..beea84d --- /dev/null +++ b/MpiApps/apps/hpl-config/HPL.dat-4l @@ -0,0 +1,31 @@ +HPLinpack benchmark input file - 4 process, large problem size +Innovative Computing Laboratory, University of Tennessee +HPL.out output file name (if any) +6 device out (6=stdout,7=stderr,file) +1 # of problems sizes (N) +20000 Ns +1 # of NBs +112 NBs +0 PMAP process mapping (0=Row-,1=Column-major) +1 # of process grids (P x Q) +2 Ps +2 Qs +16.0 threshold +1 # of panel fact +1 PFACTs (0=left, 1=Crout, 2=Right) +1 # of recursive stopping criterium +4 NBMINs (>= 1) +1 # of panels in recursion +2 NDIVs +1 # of recursive panel fact. +2 RFACTs (0=left, 1=Crout, 2=Right) +1 # of broadcast +1 BCASTs (0=1rg,1=1rM,2=2rg,3=2rM,4=Lng,5=LnM) +1 # of lookahead depth +1 DEPTHs (>=0) +2 SWAP (0=bin-exch,1=long,2=mix) +112 swapping threshold +0 L1 in (0=transposed,1=no-transposed) form +0 U in (0=transposed,1=no-transposed) form +1 Equilibration (0=no,1=yes) +4 memory alignment in double (> 0) diff --git a/MpiApps/apps/hpl-config/HPL.dat-4m b/MpiApps/apps/hpl-config/HPL.dat-4m new file mode 100644 index 0000000..0f73003 --- /dev/null +++ b/MpiApps/apps/hpl-config/HPL.dat-4m @@ -0,0 +1,31 @@ +HPLinpack benchmark input file - 4 process, medium problem size +Innovative Computing Laboratory, University of Tennessee +HPL.out output file name (if any) +6 device out (6=stdout,7=stderr,file) +1 # of problems sizes (N) +17000 Ns +1 # of NBs +112 NBs +0 PMAP process mapping (0=Row-,1=Column-major) +1 # of process grids (P x Q) +2 Ps +2 Qs +16.0 threshold +1 # of panel fact +1 PFACTs (0=left, 1=Crout, 2=Right) +1 # of recursive stopping criterium +4 NBMINs (>= 1) +1 # of panels in recursion +2 NDIVs +1 # of recursive panel fact. +2 RFACTs (0=left, 1=Crout, 2=Right) +1 # of broadcast +1 BCASTs (0=1rg,1=1rM,2=2rg,3=2rM,4=Lng,5=LnM) +1 # of lookahead depth +1 DEPTHs (>=0) +2 SWAP (0=bin-exch,1=long,2=mix) +112 swapping threshold +0 L1 in (0=transposed,1=no-transposed) form +0 U in (0=transposed,1=no-transposed) form +1 Equilibration (0=no,1=yes) +4 memory alignment in double (> 0) diff --git a/MpiApps/apps/hpl-config/HPL.dat-4s b/MpiApps/apps/hpl-config/HPL.dat-4s new file mode 100644 index 0000000..8c9debb --- /dev/null +++ b/MpiApps/apps/hpl-config/HPL.dat-4s @@ -0,0 +1,31 @@ +HPLinpack benchmark input file - 4 process, small problem size +Innovative Computing Laboratory, University of Tennessee +HPL.out output file name (if any) +6 device out (6=stdout,7=stderr,file) +1 # of problems sizes (N) +15000 Ns +1 # of NBs +112 NBs +0 PMAP process mapping (0=Row-,1=Column-major) +1 # of process grids (P x Q) +2 Ps +2 Qs +16.0 threshold +1 # of panel fact +1 PFACTs (0=left, 1=Crout, 2=Right) +1 # of recursive stopping criterium +4 NBMINs (>= 1) +1 # of panels in recursion +2 NDIVs +1 # of recursive panel fact. +2 RFACTs (0=left, 1=Crout, 2=Right) +1 # of broadcast +1 BCASTs (0=1rg,1=1rM,2=2rg,3=2rM,4=Lng,5=LnM) +1 # of lookahead depth +1 DEPTHs (>=0) +2 SWAP (0=bin-exch,1=long,2=mix) +112 swapping threshold +0 L1 in (0=transposed,1=no-transposed) form +0 U in (0=transposed,1=no-transposed) form +1 Equilibration (0=no,1=yes) +4 memory alignment in double (> 0) diff --git a/MpiApps/apps/hpl-config/HPL.dat-4t b/MpiApps/apps/hpl-config/HPL.dat-4t new file mode 100644 index 0000000..3a2e223 --- /dev/null +++ b/MpiApps/apps/hpl-config/HPL.dat-4t @@ -0,0 +1,31 @@ +HPLinpack benchmark input file - test 4 process, tiny problem size +Innovative Computing Laboratory, University of Tennessee +HPL.out output file name (if any) +6 device out (6=stdout,7=stderr,file) +1 # of problems sizes (N) +5000 Ns +1 # of NBs +112 NBs +0 PMAP process mapping (0=Row-,1=Column-major) +1 # of process grids (P x Q) +2 Ps +2 Qs +16.0 threshold +1 # of panel fact +1 PFACTs (0=left, 1=Crout, 2=Right) +1 # of recursive stopping criterium +4 NBMINs (>= 1) +1 # of panels in recursion +2 NDIVs +1 # of recursive panel fact. +2 RFACTs (0=left, 1=Crout, 2=Right) +1 # of broadcast +1 BCASTs (0=1rg,1=1rM,2=2rg,3=2rM,4=Lng,5=LnM) +1 # of lookahead depth +1 DEPTHs (>=0) +2 SWAP (0=bin-exch,1=long,2=mix) +112 swapping threshold +0 L1 in (0=transposed,1=no-transposed) form +0 U in (0=transposed,1=no-transposed) form +1 Equilibration (0=no,1=yes) +4 memory alignment in double (> 0) diff --git a/MpiApps/apps/hpl-config/HPL.dat-512l b/MpiApps/apps/hpl-config/HPL.dat-512l new file mode 100644 index 0000000..f4dc09b --- /dev/null +++ b/MpiApps/apps/hpl-config/HPL.dat-512l @@ -0,0 +1,31 @@ +HPLinpack benchmark input file - 320 process, large problem size +Innovative Computing Laboratory, University of Tennessee +HPL.out output file name (if any) +6 device out (6=stdout,7=stderr,file) +1 # of problems sizes (N) +180000 Ns +1 # of NBs +112 NBs +0 PMAP process mapping (0=Row-,1=Column-major) +1 # of process grids (P x Q) +16 Ps +32 Qs +16.0 threshold +1 # of panel fact +1 PFACTs (0=left, 1=Crout, 2=Right) +1 # of recursive stopping criterium +4 NBMINs (>= 1) +1 # of panels in recursion +2 NDIVs +1 # of recursive panel fact. +2 RFACTs (0=left, 1=Crout, 2=Right) +1 # of broadcast +1 BCASTs (0=1rg,1=1rM,2=2rg,3=2rM,4=Lng,5=LnM) +1 # of lookahead depth +1 DEPTHs (>=0) +2 SWAP (0=bin-exch,1=long,2=mix) +112 swapping threshold +0 L1 in (0=transposed,1=no-transposed) form +0 U in (0=transposed,1=no-transposed) form +1 Equilibration (0=no,1=yes) +4 memory alignment in double (> 0) diff --git a/MpiApps/apps/hpl-config/HPL.dat-512m b/MpiApps/apps/hpl-config/HPL.dat-512m new file mode 100644 index 0000000..0596841 --- /dev/null +++ b/MpiApps/apps/hpl-config/HPL.dat-512m @@ -0,0 +1,31 @@ +HPLinpack benchmark input file - 320 process, medium problem size +Innovative Computing Laboratory, University of Tennessee +HPL.out output file name (if any) +6 device out (6=stdout,7=stderr,file) +1 # of problems sizes (N) +175000 Ns +1 # of NBs +112 NBs +0 PMAP process mapping (0=Row-,1=Column-major) +1 # of process grids (P x Q) +16 Ps +32 Qs +16.0 threshold +1 # of panel fact +1 PFACTs (0=left, 1=Crout, 2=Right) +1 # of recursive stopping criterium +4 NBMINs (>= 1) +1 # of panels in recursion +2 NDIVs +1 # of recursive panel fact. +2 RFACTs (0=left, 1=Crout, 2=Right) +1 # of broadcast +1 BCASTs (0=1rg,1=1rM,2=2rg,3=2rM,4=Lng,5=LnM) +1 # of lookahead depth +1 DEPTHs (>=0) +2 SWAP (0=bin-exch,1=long,2=mix) +112 swapping threshold +0 L1 in (0=transposed,1=no-transposed) form +0 U in (0=transposed,1=no-transposed) form +1 Equilibration (0=no,1=yes) +4 memory alignment in double (> 0) diff --git a/MpiApps/apps/hpl-config/HPL.dat-512s b/MpiApps/apps/hpl-config/HPL.dat-512s new file mode 100644 index 0000000..90b74af --- /dev/null +++ b/MpiApps/apps/hpl-config/HPL.dat-512s @@ -0,0 +1,31 @@ +HPLinpack benchmark input file - 320 process, small problem size +Innovative Computing Laboratory, University of Tennessee +HPL.out output file name (if any) +6 device out (6=stdout,7=stderr,file) +1 # of problems sizes (N) +170000 Ns +1 # of NBs +112 NBs +0 PMAP process mapping (0=Row-,1=Column-major) +1 # of process grids (P x Q) +16 Ps +32 Qs +16.0 threshold +1 # of panel fact +1 PFACTs (0=left, 1=Crout, 2=Right) +1 # of recursive stopping criterium +4 NBMINs (>= 1) +1 # of panels in recursion +2 NDIVs +1 # of recursive panel fact. +2 RFACTs (0=left, 1=Crout, 2=Right) +1 # of broadcast +1 BCASTs (0=1rg,1=1rM,2=2rg,3=2rM,4=Lng,5=LnM) +1 # of lookahead depth +1 DEPTHs (>=0) +2 SWAP (0=bin-exch,1=long,2=mix) +112 swapping threshold +0 L1 in (0=transposed,1=no-transposed) form +0 U in (0=transposed,1=no-transposed) form +1 Equilibration (0=no,1=yes) +4 memory alignment in double (> 0) diff --git a/MpiApps/apps/hpl-config/HPL.dat-512t b/MpiApps/apps/hpl-config/HPL.dat-512t new file mode 100644 index 0000000..60c8db9 --- /dev/null +++ b/MpiApps/apps/hpl-config/HPL.dat-512t @@ -0,0 +1,31 @@ +HPLinpack benchmark input file - test 320 process, tiny problem size +Innovative Computing Laboratory, University of Tennessee +HPL.out output file name (if any) +6 device out (6=stdout,7=stderr,file) +1 # of problems sizes (N) +5000 Ns +1 # of NBs +112 NBs +0 PMAP process mapping (0=Row-,1=Column-major) +1 # of process grids (P x Q) +16 Ps +32 Qs +16.0 threshold +1 # of panel fact +1 PFACTs (0=left, 1=Crout, 2=Right) +1 # of recursive stopping criterium +4 NBMINs (>= 1) +1 # of panels in recursion +2 NDIVs +1 # of recursive panel fact. +2 RFACTs (0=left, 1=Crout, 2=Right) +1 # of broadcast +1 BCASTs (0=1rg,1=1rM,2=2rg,3=2rM,4=Lng,5=LnM) +1 # of lookahead depth +1 DEPTHs (>=0) +2 SWAP (0=bin-exch,1=long,2=mix) +112 swapping threshold +0 L1 in (0=transposed,1=no-transposed) form +0 U in (0=transposed,1=no-transposed) form +1 Equilibration (0=no,1=yes) +4 memory alignment in double (> 0) diff --git a/MpiApps/apps/hpl-config/HPL.dat-64l b/MpiApps/apps/hpl-config/HPL.dat-64l new file mode 100644 index 0000000..254195c --- /dev/null +++ b/MpiApps/apps/hpl-config/HPL.dat-64l @@ -0,0 +1,31 @@ +HPLinpack benchmark input file - 64 process, large problem size +Innovative Computing Laboratory, University of Tennessee +HPL.out output file name (if any) +6 device out (6=stdout,7=stderr,file) +1 # of problems sizes (N) +65000 Ns +1 # of NBs +112 NBs +0 PMAP process mapping (0=Row-,1=Column-major) +1 # of process grids (P x Q) +8 Ps +8 Qs +16.0 threshold +1 # of panel fact +1 PFACTs (0=left, 1=Crout, 2=Right) +1 # of recursive stopping criterium +4 NBMINs (>= 1) +1 # of panels in recursion +2 NDIVs +1 # of recursive panel fact. +2 RFACTs (0=left, 1=Crout, 2=Right) +1 # of broadcast +1 BCASTs (0=1rg,1=1rM,2=2rg,3=2rM,4=Lng,5=LnM) +1 # of lookahead depth +1 DEPTHs (>=0) +2 SWAP (0=bin-exch,1=long,2=mix) +112 swapping threshold +0 L1 in (0=transposed,1=no-transposed) form +0 U in (0=transposed,1=no-transposed) form +1 Equilibration (0=no,1=yes) +4 memory alignment in double (> 0) diff --git a/MpiApps/apps/hpl-config/HPL.dat-64m b/MpiApps/apps/hpl-config/HPL.dat-64m new file mode 100644 index 0000000..17a61d3 --- /dev/null +++ b/MpiApps/apps/hpl-config/HPL.dat-64m @@ -0,0 +1,31 @@ +HPLinpack benchmark input file - 64 process, medium problem size +Innovative Computing Laboratory, University of Tennessee +HPL.out output file name (if any) +6 device out (6=stdout,7=stderr,file) +1 # of problems sizes (N) +63000 Ns +1 # of NBs +112 NBs +0 PMAP process mapping (0=Row-,1=Column-major) +1 # of process grids (P x Q) +8 Ps +8 Qs +16.0 threshold +1 # of panel fact +1 PFACTs (0=left, 1=Crout, 2=Right) +1 # of recursive stopping criterium +4 NBMINs (>= 1) +1 # of panels in recursion +2 NDIVs +1 # of recursive panel fact. +2 RFACTs (0=left, 1=Crout, 2=Right) +1 # of broadcast +1 BCASTs (0=1rg,1=1rM,2=2rg,3=2rM,4=Lng,5=LnM) +1 # of lookahead depth +1 DEPTHs (>=0) +2 SWAP (0=bin-exch,1=long,2=mix) +112 swapping threshold +0 L1 in (0=transposed,1=no-transposed) form +0 U in (0=transposed,1=no-transposed) form +1 Equilibration (0=no,1=yes) +4 memory alignment in double (> 0) diff --git a/MpiApps/apps/hpl-config/HPL.dat-64s b/MpiApps/apps/hpl-config/HPL.dat-64s new file mode 100644 index 0000000..ed8a175 --- /dev/null +++ b/MpiApps/apps/hpl-config/HPL.dat-64s @@ -0,0 +1,31 @@ +HPLinpack benchmark input file - 64 process, small problem size +Innovative Computing Laboratory, University of Tennessee +HPL.out output file name (if any) +6 device out (6=stdout,7=stderr,file) +1 # of problems sizes (N) +60000 Ns +1 # of NBs +112 NBs +0 PMAP process mapping (0=Row-,1=Column-major) +1 # of process grids (P x Q) +8 Ps +8 Qs +16.0 threshold +1 # of panel fact +1 PFACTs (0=left, 1=Crout, 2=Right) +1 # of recursive stopping criterium +4 NBMINs (>= 1) +1 # of panels in recursion +2 NDIVs +1 # of recursive panel fact. +2 RFACTs (0=left, 1=Crout, 2=Right) +1 # of broadcast +1 BCASTs (0=1rg,1=1rM,2=2rg,3=2rM,4=Lng,5=LnM) +1 # of lookahead depth +1 DEPTHs (>=0) +2 SWAP (0=bin-exch,1=long,2=mix) +112 swapping threshold +0 L1 in (0=transposed,1=no-transposed) form +0 U in (0=transposed,1=no-transposed) form +1 Equilibration (0=no,1=yes) +4 memory alignment in double (> 0) diff --git a/MpiApps/apps/hpl-config/HPL.dat-64t b/MpiApps/apps/hpl-config/HPL.dat-64t new file mode 100644 index 0000000..2125820 --- /dev/null +++ b/MpiApps/apps/hpl-config/HPL.dat-64t @@ -0,0 +1,31 @@ +HPLinpack benchmark input file - test 64 process, tiny problem size +Innovative Computing Laboratory, University of Tennessee +HPL.out output file name (if any) +6 device out (6=stdout,7=stderr,file) +1 # of problems sizes (N) +5000 Ns +1 # of NBs +112 NBs +0 PMAP process mapping (0=Row-,1=Column-major) +1 # of process grids (P x Q) +8 Ps +8 Qs +16.0 threshold +1 # of panel fact +1 PFACTs (0=left, 1=Crout, 2=Right) +1 # of recursive stopping criterium +4 NBMINs (>= 1) +1 # of panels in recursion +2 NDIVs +1 # of recursive panel fact. +2 RFACTs (0=left, 1=Crout, 2=Right) +1 # of broadcast +1 BCASTs (0=1rg,1=1rM,2=2rg,3=2rM,4=Lng,5=LnM) +1 # of lookahead depth +1 DEPTHs (>=0) +2 SWAP (0=bin-exch,1=long,2=mix) +112 swapping threshold +0 L1 in (0=transposed,1=no-transposed) form +0 U in (0=transposed,1=no-transposed) form +1 Equilibration (0=no,1=yes) +4 memory alignment in double (> 0) diff --git a/MpiApps/apps/hpl-config/HPL.dat-8l b/MpiApps/apps/hpl-config/HPL.dat-8l new file mode 100644 index 0000000..db631d5 --- /dev/null +++ b/MpiApps/apps/hpl-config/HPL.dat-8l @@ -0,0 +1,31 @@ +HPLinpack benchmark input file - 8 process, large problem size +Innovative Computing Laboratory, University of Tennessee +HPL.out output file name (if any) +6 device out (6=stdout,7=stderr,file) +1 # of problems sizes (N) +25000 Ns +1 # of NBs +112 NBs +0 PMAP process mapping (0=Row-,1=Column-major) +1 # of process grids (P x Q) +2 Ps +4 Qs +16.0 threshold +1 # of panel fact +1 PFACTs (0=left, 1=Crout, 2=Right) +1 # of recursive stopping criterium +4 NBMINs (>= 1) +1 # of panels in recursion +2 NDIVs +1 # of recursive panel fact. +2 RFACTs (0=left, 1=Crout, 2=Right) +1 # of broadcast +1 BCASTs (0=1rg,1=1rM,2=2rg,3=2rM,4=Lng,5=LnM) +1 # of lookahead depth +1 DEPTHs (>=0) +2 SWAP (0=bin-exch,1=long,2=mix) +112 swapping threshold +0 L1 in (0=transposed,1=no-transposed) form +0 U in (0=transposed,1=no-transposed) form +1 Equilibration (0=no,1=yes) +4 memory alignment in double (> 0) diff --git a/MpiApps/apps/hpl-config/HPL.dat-8m b/MpiApps/apps/hpl-config/HPL.dat-8m new file mode 100644 index 0000000..2498d40 --- /dev/null +++ b/MpiApps/apps/hpl-config/HPL.dat-8m @@ -0,0 +1,31 @@ +HPLinpack benchmark input file - 8 process, medium problem size +Innovative Computing Laboratory, University of Tennessee +HPL.out output file name (if any) +6 device out (6=stdout,7=stderr,file) +1 # of problems sizes (N) +22000 Ns +1 # of NBs +112 NBs +0 PMAP process mapping (0=Row-,1=Column-major) +1 # of process grids (P x Q) +2 Ps +4 Qs +16.0 threshold +1 # of panel fact +1 PFACTs (0=left, 1=Crout, 2=Right) +1 # of recursive stopping criterium +4 NBMINs (>= 1) +1 # of panels in recursion +2 NDIVs +1 # of recursive panel fact. +2 RFACTs (0=left, 1=Crout, 2=Right) +1 # of broadcast +1 BCASTs (0=1rg,1=1rM,2=2rg,3=2rM,4=Lng,5=LnM) +1 # of lookahead depth +1 DEPTHs (>=0) +2 SWAP (0=bin-exch,1=long,2=mix) +112 swapping threshold +0 L1 in (0=transposed,1=no-transposed) form +0 U in (0=transposed,1=no-transposed) form +1 Equilibration (0=no,1=yes) +4 memory alignment in double (> 0) diff --git a/MpiApps/apps/hpl-config/HPL.dat-8s b/MpiApps/apps/hpl-config/HPL.dat-8s new file mode 100644 index 0000000..b764d2e --- /dev/null +++ b/MpiApps/apps/hpl-config/HPL.dat-8s @@ -0,0 +1,31 @@ +HPLinpack benchmark input file - 8 process, small problem size +Innovative Computing Laboratory, University of Tennessee +HPL.out output file name (if any) +6 device out (6=stdout,7=stderr,file) +1 # of problems sizes (N) +20000 Ns +1 # of NBs +112 NBs +0 PMAP process mapping (0=Row-,1=Column-major) +1 # of process grids (P x Q) +2 Ps +4 Qs +16.0 threshold +1 # of panel fact +1 PFACTs (0=left, 1=Crout, 2=Right) +1 # of recursive stopping criterium +4 NBMINs (>= 1) +1 # of panels in recursion +2 NDIVs +1 # of recursive panel fact. +2 RFACTs (0=left, 1=Crout, 2=Right) +1 # of broadcast +1 BCASTs (0=1rg,1=1rM,2=2rg,3=2rM,4=Lng,5=LnM) +1 # of lookahead depth +1 DEPTHs (>=0) +2 SWAP (0=bin-exch,1=long,2=mix) +112 swapping threshold +0 L1 in (0=transposed,1=no-transposed) form +0 U in (0=transposed,1=no-transposed) form +1 Equilibration (0=no,1=yes) +4 memory alignment in double (> 0) diff --git a/MpiApps/apps/hpl-config/HPL.dat-8t b/MpiApps/apps/hpl-config/HPL.dat-8t new file mode 100644 index 0000000..10afd55 --- /dev/null +++ b/MpiApps/apps/hpl-config/HPL.dat-8t @@ -0,0 +1,31 @@ +HPLinpack benchmark input file - test 8 process, tiny problem size +Innovative Computing Laboratory, University of Tennessee +HPL.out output file name (if any) +6 device out (6=stdout,7=stderr,file) +1 # of problems sizes (N) +5000 Ns +1 # of NBs +112 NBs +0 PMAP process mapping (0=Row-,1=Column-major) +1 # of process grids (P x Q) +2 Ps +4 Qs +16.0 threshold +1 # of panel fact +1 PFACTs (0=left, 1=Crout, 2=Right) +1 # of recursive stopping criterium +4 NBMINs (>= 1) +1 # of panels in recursion +2 NDIVs +1 # of recursive panel fact. +2 RFACTs (0=left, 1=Crout, 2=Right) +1 # of broadcast +1 BCASTs (0=1rg,1=1rM,2=2rg,3=2rM,4=Lng,5=LnM) +1 # of lookahead depth +1 DEPTHs (>=0) +2 SWAP (0=bin-exch,1=long,2=mix) +112 swapping threshold +0 L1 in (0=transposed,1=no-transposed) form +0 U in (0=transposed,1=no-transposed) form +1 Equilibration (0=no,1=yes) +4 memory alignment in double (> 0) diff --git a/MpiApps/apps/hpl-config/README b/MpiApps/apps/hpl-config/README new file mode 100644 index 0000000..b33b4ec --- /dev/null +++ b/MpiApps/apps/hpl-config/README @@ -0,0 +1,44 @@ +HPL has a large number of tunable parameters. +These configuration files should be considered a starting point +and guideline for the problem size and parameters to start with. +From there additional tuning of HPL and MPI parameters can be done +to get the best performance for a given cluster. + +For each cluster size there are multiple configs: + t = a very small test config + s = on the low side of a 1G/process cluster + m = in the middle of a 1G/process cluster + l = on the high side of a 1G/process cluster +Main difference is problem size (N) + +The config_hpl2 script can be used to transfer the HPL.dat file to all +nodes specified in mpi_hosts + +A very critical HPL parameter is the problem size (N). +These files assume 1G of memory per processor in the cluster +(hence a 2G dual proc box would be typical). For alternate +memory configurations the problem size should be approximated by + SQRT(total Mem/8)*0.80 + Where total mem is the number of bytes of memory in the fabric. + 8 is the size of a double floating point number + and 0.80 allows 80% for application data and 20% for OS, fabric, code, etc + +Another important value is NB. For the goto library supplied an NB value of +104 or 112 is recommended. + +While running hpl monitor a few systems with top. There should be no swapping +if you observe swapping reduce the problem size or reduce the memory +for MPI. + +A few critical parameters in MPI (/etc/sysconfig/mpi.param) to tune: +VIADEV_SQ_SIZE - values in the 100-200 range are best. If too low additional + code overheads occur, if too high excessive memory is used. +VIADEV_MEM_REG_MAX - controls how much memory can be dynamically locked for + RPUT/RDMA Write transfers, a value of 5-10 works best +VIADEV_NUM_RDMA_BUFFER - how many buffers for RDMA fast path, this consumes + extra memory and can hurt scalability, for MPI runs over 16 processes, + set this to 0 +VIADEV_INITIAL_PREPOST_DEPTH - how many receive buffers to prepost on each QP, + since HPL uses very few of the possible paths a value of 15 is best. + +For additional information see hpl/TUNING and hpl/www/faq.html diff --git a/MpiApps/apps/hpl-count.diff b/MpiApps/apps/hpl-count.diff new file mode 100644 index 0000000..a925f75 --- /dev/null +++ b/MpiApps/apps/hpl-count.diff @@ -0,0 +1,67 @@ +This patch can be applied to the HPL program to provide a simple progress output +Every 8 NB values the present progress (0-N) will be displayed by rank 0. +When making large HPL runs this can be useful to get a feeling as to how far the +run has progressed and how fast it is running. + +To apply this patch: + cd /usr/src/opa/mpi_apps + patch -p0 < hpl-count.diff + make clean + make quick +To remove this patch: + cd /usr/src/opa/mpi_apps + patch -R -p0 < hpl-count.diff + make clean + make quick +Note rebuilding HPL will replace the HPL.dat file. Also after rebuilding +HPL you need to copy the new executable to all the nodes (or in the case of this +patch to at least rank 0) + +diff -c -r hpl/src/pgesv/HPL_pdgesv0.c ./HPL_pdgesv0.c +*** hpl/src/pgesv/HPL_pdgesv0.c Tue Jan 13 19:51:40 2004 +--- hpl/src/pgesv/HPL_pdgesv0.c Tue Jan 13 20:03:50 2004 +*************** +*** 118,123 **** + */ + for( j = 0; j < N; j += nb ) + { + n = N - j; jb = Mmin( n, nb ); + /* + * Release panel resources - re-initialize panel data structure +--- 118,125 ---- + */ + for( j = 0; j < N; j += nb ) + { ++ if (GRID->myrow == 0 && GRID->mycol == 0 && (j/nb & 7) == 0) ++ fprintf(stderr, "%d\n", j); + n = N - j; jb = Mmin( n, nb ); + /* + * Release panel resources - re-initialize panel data structure +diff -c -r hpl/src/pgesv/HPL_pdgesvK1.c ./HPL_pdgesvK1.c +*** hpl/src/pgesv/HPL_pdgesvK1.c Tue Jan 13 19:51:40 2004 +--- hpl/src/pgesv/HPL_pdgesvK1.c Tue Jan 13 20:03:56 2004 +*************** +*** 157,162 **** +--- 157,164 ---- + */ + for( j = jstart; j < N; j += nb ) + { ++ if (GRID->myrow == 0 && GRID->mycol == 0 && (j/nb & 7) == 0) ++ fprintf(stderr, "%d\n", j); + n = N - j; jb = Mmin( n, nb ); + /* + * Allocate current panel resources - Finish latest update - Factor and +diff -c -r hpl/src/pgesv/HPL_pdgesvK2.c ./HPL_pdgesvK2.c +*** hpl/src/pgesv/HPL_pdgesvK2.c Tue Jan 13 19:51:40 2004 +--- hpl/src/pgesv/HPL_pdgesvK2.c Tue Jan 13 20:04:00 2004 +*************** +*** 163,168 **** +--- 163,170 ---- + */ + for( j = jstart; j < N; j += nb ) + { ++ if (GRID->myrow == 0 && GRID->mycol == 0 && (j/nb & 7) == 0) ++ fprintf(stderr, "%d\n", j); + n = N - j; jb = Mmin( n, nb ); + /* + * Initialize current panel - Finish latest update, Factor and broadcast diff --git a/MpiApps/apps/hpl_dat_gen b/MpiApps/apps/hpl_dat_gen new file mode 100755 index 0000000..3d21518 --- /dev/null +++ b/MpiApps/apps/hpl_dat_gen @@ -0,0 +1,309 @@ +#!/bin/bash +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] + +# Might want to tune this later. +NBs=168 + +# Generate some reasonable defaults based on the current node. +default_numcores=$(lscpu | grep "^CPU(s):" | awk '{print $2}') +bytesram=$(cat /proc/meminfo | grep MemTotal | awk '{print $2}') +default_megsram=$(( $bytesram / 1024 )) +default_pressure=0.3 + +# If we have an mpi_hosts file, use that for the default # of hosts. +if [ -e /usr/src/opa/mpi_hosts ]; then + default_numnodes=$(sort -u mpi_hosts | wc -l) +else + default_numnodes=1 +fi + +numcores=$default_numcores +megsram=$default_megsram +pressure=$default_pressure +numnodes=$default_numnodes + +USAGE() { + echo >&2 + echo >&2 "Usage:" + echo >&2 " ./hpl_dat_gen.sh [-2|-1][-n ][-c ][-r ][-p ][-d]" + echo >&2 + echo >&2 " This tool generates an HPL.dat file and copies it to the appropriate hpl" + echo >&2 " executable directory (hpl-2.2/bin/ICS.Linux.*)" + echo >&2 + echo >&2 " The HPL.dat file can be tuned for different numbers of nodes, cores per node," + echo >&2 " and the approximate amount of RAM per node to use. The script chooses" + echo >&2 " defaults based on the characteristics of the node the script is run on, but" + echo >&2 " these values can be overridden either by command line options or by" + echo >&2 " prompting the user to enter new values." + echo >&2 + echo >&2 "Options:" + echo >&2 + echo >&2 " --nodes " + echo >&2 " -n # of nodes in the fabric." + echo >&2 + echo >&2 " --cores " + echo >&2 " -c # of cores per node." + echo >&2 + echo >&2 " --ram " + echo >&2 " -r Amount of RAM per node in MB." + echo >&2 + echo >&2 " --pressure

" + echo >&2 " -p

Total memory pressure, expressed as a number" + echo >&2 " between 0.1 and 0.9. This value scales the" + echo >&2 " problem size against the amount of RAM available." + echo >&2 " (For example, a pressure of 0.5 will use about" + echo >&2 " half the available RAM on each node.)" + echo >&2 + echo >&2 " --use-defaults" + echo >&2 " -d Use defaults for unspecified values." + echo >&2 " (otherwise prompt for the missing values.)" + echo >&2 + echo >&2 "Defaults for this system are:" + echo >&2 " -2" + echo >&2 " -n $default_numnodes" + echo >&2 " -c $default_numcores" + echo >&2 " -r $default_megsram" + echo >&2 " -p $default_pressure" +} + +P=0 +Q=0 +HPL_PQ() { + local cores=$1 + local pp + local qq + + # Find values of P and Q that use every available core and are as close + # in value as possible, with Q being slightly larger than P. + # For example, if the # of cores is 36, the optimal (P,Q) is (4,9) rather + # than (6,6). + for pp in $(seq 1 $cores); do + qq=$(( $cores / $pp)) + ll=$(( $pp * $qq)) + if [ $pp -ge $qq ]; then + break + fi + if [ $ll -eq $cores ]; then + P=$pp; + Q=$qq; + fi + done +} + +Ns="" +CALC_NS() { + local numnodes=$1 + local megspernode=$2 + local pressure=$3 + + # This calculation adjusts the size of the HPL problem to a percentage + # of the available RAM. The formula is: + # + # "Take the square root of the total amount of memory in the cluster + # divided by the number of bytes in a double precision number, then + # multiply by the requested memory pressure and round up to a multiple + # of the block size." + Ns=$(echo "sqrt($megspernode * 1024 * 1024 * $numnodes / 8) * $pressure / $NBs * $NBs" | bc) +} + +inputval="" +GET_INPUT() { + local defval="" + local prompt="Input" + local value="" + + if [ $# -ge 1 ]; then + prompt=$1 + fi + + if [ $# -ge 2 ]; then + defval=$2 + fi + + while [ -z $value ]; do + if [ ! -z $defval ]; then + echo -n "$prompt [$defval]? " + else + echo -n "$prompt? " + fi + read value + if [ -z $value ]; then + value=$defval + fi + done + + inputval=$value +} + +TEMP_FILE="$(mktemp)" +trap "rm -rf $TEMP_FILE; exit 1" SIGINT SIGHUP SIGTERM +trap "rm -rf $TEMP_FILE" EXIT + +arch=ICS.`uname -s`.`./get_mpi_cc.sh` + +got_nodes=0 +got_cores=0 +got_ram=0 +got_pressure=0 +use_defaults=0 + +OPTIONS=$(getopt -o "n:c:r:p:hd12" --long "nodes:,cores:,ram:,pressure:,help,use-defaults" -- "$@") + +if [ $? -ne 0 ]; then + USAGE; exit 1 +fi + +eval set -- "$OPTIONS" + +while true; do + case "$1" in + -n | --nodes ) + numnodes=$2; got_nodes=1; + shift; shift;; + -c | --cores ) + numcores=$2; got_cores=1; + shift; shift;; + -r | --ram ) + megsram=$2; got_ram=1; + shift; shift;; + -p | --pressure ) + pressure=$2; got_pressure=1; + shift; shift;; + -d | --use-defaults ) + use_defaults=1; + shift;; + -- ) + # End of arguments list. + break;; + -h | --help ) + USAGE; exit 0;; + * ) + USAGE; exit 1;; + esac +done + +if ! [[ $numnodes =~ ^[0-9]+$ ]]; then + echo >&2 "\"$numnodes\" is not a valid # of nodes" + USAGE; exit 1 +elif ! [[ $numcores =~ ^[0-9]+$ ]]; then + echo >&2 "\"$numcores\" is not a valid # of cores" + USAGE; exit 1 +elif ! [[ $megsram =~ ^[0-9]+$ ]]; then + echo >&2 "\"$megsram\" is not a valid amount of RAM" + USAGE; exit 1 +elif ! [[ $pressure =~ ^0\.[1-9][0-9]*$ ]]; then + echo >&2 "\"$pressure\" is not a valid amount memory pressure." + USAGE; exit 1 +fi + +while [ $got_nodes -eq 0 -a $use_defaults -eq 0 ] +do + GET_INPUT "# of compute nodes" $default_numnodes + numnodes=$inputval + if [[ $numnodes =~ ^[0-9]+$ ]]; then + got_nodes=1 + fi +done + +while [ $got_cores -eq 0 -a $use_defaults -eq 0 ] +do + GET_INPUT "# of cores per node" $default_numcores + numcores=$inputval + if [[ $numcores =~ ^[0-9]+$ ]]; then + got_cores=1 + fi +done + +while [ $got_ram -eq 0 -a $use_defaults -eq 0 ] +do + GET_INPUT "# of RAM per node (in MB)" $default_megsram + megsram=$inputval + if [[ $megsram =~ ^[0-9]+$ ]]; then + got_ram=1 + fi +done + +while [ $got_pressure -eq 0 -a $use_defaults -eq 0 ] +do + GET_INPUT "Memory pressure (range between 0.1 and 0.9)" $default_pressure + pressure=$inputval + if [[ $pressure =~ ^0\.[1-9][0-9]*$ ]]; then + got_pressure=1 + fi +done + +totnumcores=$(( $numcores * $numnodes )) + +HPL_PQ $totnumcores + +CALC_NS $numnodes $megsram $pressure + +echo +echo "Use \"./run_hpl2 $totnumcores\" to use this configuration." +echo +echo + +DATFILE=$PWD/hpl-2.2/bin/$arch/HPL.dat + +cat <= 1) +1 # of panels in recursion +2 NDIVs +1 # of recursive panel fact. +2 RFACTs (0=left, 1=Crout, 2=Right) +1 # of broadcast +1 BCASTs (0=1rg,1=1rM,2=2rg,3=2rM,4=Lng,5=LnM) +1 # of lookahead depth +1 DEPTHs (>=0) +2 SWAP (0=bin-exch,1=long,2=mix) +$NBs swapping threshold +0 L1 in (0=transposed,1=no-transposed) form +0 U in (0=transposed,1=no-transposed) form +1 Equilibration (0=no,1=yes) +8 memory alignment in double (> 0) +EOF diff --git a/MpiApps/apps/intelmpi.params b/MpiApps/apps/intelmpi.params new file mode 100644 index 0000000..a8a5548 --- /dev/null +++ b/MpiApps/apps/intelmpi.params @@ -0,0 +1,117 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +#[ICS VERSION STRING: unknown] +#!/bin/bash + +# PURPOSE: +# +# This file sets environment variables for an IntelMPI job. +# Note that there are many, many such variables. +# +# SYNTAX: +# +# This file must be a valid BASH script. In general, anything that's valid +# in BASH is valid here. To pass variables to IntelMPI, they +# may take either of these forms: +# +# export MPI_CMD_ARGS="$MPI_CMD_ARGS -genv VARIABLE_NAME variablevalue" +# export VARIABLE_NAME=variablevalue +# +# This script generally both exports the variable and provides it via -genv +# As such MPI_CMD_ARGS shown in the log of running the MPI app will explicitly +# show the variables used. + +# SAMPLE Tuning variables: +# +# Uncomment the following lines to enable them. +# +. /usr/sbin/opagetvf_env # defines bash function opagetvf_func +export MPI_CMD_ARGS= + +# It is recommended to use the OFI interface over PSM2 within IntelMPI +export I_MPI_FABRICS=shm:ofi +export I_MPI_OFI_PROVIDER=psm2 + +# These 3 lines select a Virtual Fabric by name and configure PKEY, SL, MTU +# opagetvf_func "-d 'Compute'" PSM2_PKEY HFI_SL PSM2_MTU +# export MPI_CMD_ARGS="-genv PSM2_PKEY $PSM2_PKEY -genv HFI_SL $HFI_SL" +# [ -n "$PSM2_MTU" ] && export MPI_CMD_ARGS="$MPI_CMD_ARGS -genv PSM2_MTU $PSM2_MTU" + +# These 3 lines select a Virtual Fabric by ServiceId and configure PKEY, SL, MTU +# opagetvf_func "-S '0x1000117500000000'" PSM2_PKEY HFI_SL PSM2_MTU +# export MPI_CMD_ARGS="-genv PSM2_PKEY $PSM2_PKEY -genv HFI_SL $HFI_SL" +# [ -n "$PSM2_MTU" ] && export MPI_CMD_ARGS="$MPI_CMD_ARGS -genv PSM2_MTU $PSM2_MTU" + +# These 3 lines select a Virtual Fabric by ServiceId and uses dist_sa +# to directly fetch the PathRecord at job startup. +# This mechanism is only supported for Intel HFIs when using PSM (-hfi MPIs) +#export PSM2_PATH_REC=opp +#export PSM2_IB_SERVICE_ID=0x1000117500000000 +#export MPI_CMD_ARGS="-genv PSM2_PATH_REC $PSM2_PATH_REC -genv PSM2_IB_SERVICE_ID $PSM2_IB_SERVICE_ID" + +# This line can enable dispersive routing. The following choices are allowed: +# adaptive, static_src, static_dest, static_base +# If LMC is enabled in the SM, adaptive will automatically be used. +# This mechanism is only supported for Intel HFIs when using PSM +#export PSM2_PATH_SELECTION=adaptive +#export MPI_CMD_ARGS="$MPI_CMD_ARGS -genv PSM2_PATH_SELECTION $PSM2_PATH_SELECTION" + +# Use this to explicitly specify a pkey (for virtual fabrics) +#export PSM2_PKEY=0x8002 +#export MPI_CMD_ARGS="$MPI_CMD_ARGS -genv PSM2_PKEY $PSM2_PKEY" + +# Use this to explicitly specify a service level (for virtual fabrics) +#export HFI_SL=0 +#export MPI_CMD_ARGS="$MPI_CMD_ARGS -genv HFI_SL $HFI_SL" + +# Use this to explicitly specify a MTU (for virtual fabrics) +#export PSM2_MTU=4096 +#export MPI_CMD_ARGS="$MPI_CMD_ARGS -genv PSM2_MTU $PSM2_MTU" + +# Use this to enable core dumps +# (in addition ulimit and /etc/security/limits must enable core dumps too) +#export HFI_NO_BACKTRACE=1 +#export MPI_CMD_ARGS="$MPI_CMD_ARGS -genv HFI_NO_BACKTRACE $HFI_NO_BACKTRACE" + +# Normally Congestion Control is completely configured in the SM config file. +# However, if desired, the fabric interface settings can be overridden for +# the given job. +#export PSM2_DISABLE_CCA=0 +#export MPI_CMD_ARGS="$MPI_CMD_ARGS -genv PSM2_DISABLE_CCA $PSM2_DISABLE_CCA" + +# These values can enable and control PSM Multi-Rail +# In most cases the default automatic selections will be sufficient +# The sample shown is for Dual HFI server with port 1 per HFI connected +#export PSM2_MULTIRAIL=1 +#export PSM2_MULTIRAIL_MAP="0:1,1:1" +#export MPI_CMD_ARGS="$MPI_CMD_ARGS -genv PSM2_MULTIRAIL $PSM2_MULTIRAIL -genv PSM2_MULTIRAIL_MAP $PSM2_MULTIRAIL_MAP" + +# This can be enabled to force benchmarks to run on selected CPU cores +#export MPI_TASKSET="${MPI_TASKSET:- -c 1-7}" diff --git a/MpiApps/apps/mpi_cleanup b/MpiApps/apps/mpi_cleanup new file mode 100755 index 0000000..3260dda --- /dev/null +++ b/MpiApps/apps/mpi_cleanup @@ -0,0 +1,115 @@ +#!/bin/bash +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +#[ICS VERSION STRING: unknown] + +# This script can help to cleanup manually launched jobs +# the focus is on apps often run during cluster verification or +# microbenchmarking +set -x +# $1 is hosts to cleanup +#hosts=alive +#hosts=good +hosts=${1:-running} + +export FF_MAX_PARALLEL=1700 + +pkill -f mvapich +pkill -f run_cabletest +pkill -9 -f run_many_pmb +pkill -9 -f mvapich +pkill -9 -f deviation +pkill -9 -f mpiBench +pkill -9 -f openmpi +pkill -9 -f xhpl +pkill -9 -f PMB-MPI +pkill -9 -f IMB-MPI +pkill -9 -f mpi_groupstress +pkill -9 -f run_cabletest + +cat > $workdir/cleanup.tmp </dev/null 2>&1 +# opacmdall -p -f $hosts "pkill -9 -f $app; echo -n" >/dev/null 2>&1 +#done +sleep 10 +## use an echo at end so exit status is good +#opacmdall -p -f $hosts 'pkill -9 -f stress; echo -n' +#opacmdall -p -f $hosts 'pkill -9 -f deviation; echo -n' + +opacmdall -p -f $hosts 'bash cleanup.tmp' + +#opacmdall -p -f $hosts 'service ipmi stop' +#opacmdall -p -f $hosts 'service nptd stop' +#opacmdall -p -f $hosts 'service crond stop' +#opacmdall -p -f $hosts 'mount -all' + diff --git a/MpiApps/apps/mpi_hosts.sample b/MpiApps/apps/mpi_hosts.sample new file mode 100644 index 0000000..6f9222d --- /dev/null +++ b/MpiApps/apps/mpi_hosts.sample @@ -0,0 +1,4 @@ +hostname1 +hostname2 +hostname3 +hostname4 diff --git a/MpiApps/apps/mpicc b/MpiApps/apps/mpicc new file mode 100755 index 0000000..db81bd9 --- /dev/null +++ b/MpiApps/apps/mpicc @@ -0,0 +1,25 @@ +#! /bin/bash +# A simple wrapper of mpif77 to force it uses RPATH +#set -x +echo "REAL_MPICC=$REAL_MPICC" +# generate compile string and replace 'enable-new-dtags' with 'disable-new-dtags' +# to force use RPATH. Given we can have space in quoted string that will cause +# wrong word splitting, we split string into arguments by ourselves with ' -'. +# To do it, we replace ' -' with '\n-' and then split the string with customized +# IFS that is set to new line +cmd_str=$($REAL_MPICC -show "$@" | sed -e 's/enable-new-dtags/disable-new-dtags/g' -e 's/[[:space:]]\+-/\n-/g') +OLDIFS=$IFS +IFS=$'\n' +args=() +# for each argument that constains '"', we escape special characters in the argument. +# Please note that an argument only can contain one quoted string, so it's fine +# to do escape in the whole string +for arg in ${cmd_str[@]}; do + if [[ "$arg" == *\"* ]]; then + args+=" $'$arg'" + else + args+=" $arg" + fi +done +IFS=$OLDIFS +eval "${args[*]}" diff --git a/MpiApps/apps/mpicheck/Makefile b/MpiApps/apps/mpicheck/Makefile new file mode 100644 index 0000000..0323d1e --- /dev/null +++ b/MpiApps/apps/mpicheck/Makefile @@ -0,0 +1,44 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +ifndef MPICH_PREFIX +export MPICH_PREFIX=/usr/lib/opa +endif +ifndef MPICC +export MPICC=$(MPICH_PREFIX)/bin/mpicc +endif + +all: mpicheck + +mpicheck: mpicheck.c + #$(MPICC) -o mpicheck -g mpicheck.c -Idmalloc -Ldmalloc -ldmallocth + $(MPICC) -o mpicheck -g mpicheck.c + +clean: + rm -f mpicheck *.o diff --git a/MpiApps/apps/mpicheck/mpicheck.c b/MpiApps/apps/mpicheck/mpicheck.c new file mode 100644 index 0000000..144eca3 --- /dev/null +++ b/MpiApps/apps/mpicheck/mpicheck.c @@ -0,0 +1,946 @@ +/* BEGIN_ICS_COPYRIGHT7 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT7 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ +/* + * The purpose of this application is to do some simple validations of MPI + * communications. Unlike other benchmark apps is is not intended to run + * quickly, but to validate the results of each transfer to ensure the + * correct operation of MPI. + * + * The code is deliberately written to be inefficient; in order to (hopefully) + * expose communication errors and memory corruption issues. + */ + +#include +#include +#include +#include +#include +#include +#include + +/* + * Defines used by randomize test. + */ +#define SHUFFLERATE 64 +#define MINRANDXFER 1024 +#define MAXRANDXFER 32768 +#define NUMRANDXFERS 65536 +#define RANDOMLEN() (MINRANDXFER + (random() % (MAXRANDXFER-MINRANDXFER))) + +#define MAX(a,b) ((a>b)?a:b) +#define MIN(a,b) ((a'}, + {"rounds", required_argument, NULL, 'i'}, + {"buffers", required_argument, NULL, 'b'}, + {"barrier", required_argument, NULL, 'B'}, + {"verbose", no_argument, &verboseMode, 1}, + {"fast", no_argument, &doFast, 1}, + {"nofast", no_argument, &doFast, 0}, + {"slow", no_argument, &doSlow, 1}, + {"noslow", no_argument, &doSlow, 0}, + {"random", no_argument, &doRandom, 1}, + {"norandom", no_argument, &doRandom, 0}, + {"sendoffset", no_argument, &useSendOffset, 1}, + {NULL, 0, NULL, 0} +}; + +void +usage( ) +{ + int i = 0; + + fprintf( stderr, "Usage: mpicheck " ); + for ( i = 0; options[i].name != NULL; i++ ) { + if ( options[i].has_arg == required_argument ) { + fprintf( stderr, "[--%s ###] ", options[i].name ); + } else { + fprintf( stderr, "[--%s] ", options[i].name ); + } + } + fprintf( stderr, "\n" ); +} + +/* + * Writes a transfer buffer to disk for post-mortem analysis. + */ +void +dumpbuffer( int myid, char *name, char *buffer, int size ) +{ + char fname[1024]; + FILE *f; + size_t s; + + sprintf( fname, "%s.%03d", name, myid ); + + f = fopen( fname, "w" ); + + if ( !f ) { + ERRPRINT( "Failed to open %s\n", fname ); + return; + } + + s = fwrite( buffer, 1, size, f ); + if ( s != size ) { + ERRPRINT( "Failed to write %s\n", fname ); + } + + fclose( f ); +} + +typedef struct { + unsigned int start; + unsigned int length; +} RandomRecord; + +static void +initrandom( ) +{ + unsigned int seed; + FILE *f = fopen( "/dev/random", "r" ); + + if ( f ) { + fread( &seed, sizeof( seed ), 1, f ); + } + fclose( f ); + srandom( seed ); +} + +/* + * Randomize mode pairs up the nodes and performs a "drunkards" walk + * between them - it performs a large number of sends and receives + * designed to stress operations when asynchronous messages overlap. + * + * Note that randomize does not use the "rounds" setting that the + * other tests use. + */ +int +randomize( int myid, int numProcs, int minSize, int maxSize, int maxIters ) +{ + int i, size, partner, sendMode, numRecords, iters; + int retCode = MPI_SUCCESS; + RandomRecord records[NUMRANDXFERS]; + MPI_Request request[NUMRANDXFERS]; + MPI_Status status[NUMRANDXFERS]; + unsigned char *rawBuffer = NULL; /* Array of buffer+barrier memory + * regions. */ + unsigned char *buffer = NULL; /* Pointer into rawBuffer. */ + unsigned int totalBufferSize = BARRIERSIZE * 2 + maxSize; + + ROOTPRINT( "Beginning Randomize Test Section\n" ); + ROOTPRINT( "(Node sends random length messages to each other.)\n" ); + + initrandom( ); + + memset( request, 0, sizeof( MPI_Request ) * NUMRANDXFERS ); + memset( status, 0, sizeof( MPI_Status ) * NUMRANDXFERS ); + + sendMode = ( myid % 2 ) == 0; + + if ( sendMode ) { + partner = myid + 1; + } else { + partner = myid - 1; + } + + rawBuffer = malloc( totalBufferSize ); + if ( !rawBuffer ) { + ERRPRINT( "Failed to allocate buffers.\n" ); + retCode = ~MPI_SUCCESS; + goto done; + } + + buffer = rawBuffer + BARRIERSIZE; + size = minSize; + + while ( size <= maxSize ) { + int round = 0; + iters = maxIters; + while ( iters > 0 ) { + /* Initialize the buffer to our rank as a pad value. */ + memset( rawBuffer, myid, totalBufferSize ); + + if ( sendMode ) { + /* Initialize the buffer with some random data. */ + /* Every 4th byte is a check sum of the previous 3. */ + for ( i = 0; i < ( size - 3 ); i += 4 ) { + buffer[i] = random( ) % 256; + buffer[i + 1] = random( ) % 256; + buffer[i + 2] = random( ) % 256; + buffer[i + 3] = + ( buffer[i] + buffer[i + 1] + buffer[i + 2] ) % 256; + } + + /* Build a list of randomly sized messages to send. */ + /* Note that we effectively "null terminate" the list. */ + memset( records, 0, sizeof( RandomRecord ) * NUMRANDXFERS ); + i = 0; + numRecords = 0; + while ( i < size ) { + records[numRecords].start = i; + records[numRecords].length = RANDOMLEN( ); + if ( records[numRecords].length + i > size ) { + records[numRecords].length = size - i; + } + i += records[numRecords].length; + numRecords++; + } + + /* Note that numRecords is now the length of records. */ + + /* Swap a few records, for extra evil. */ + i = random( ) % SHUFFLERATE; + while ( i < NUMRANDXFERS && records[i].length ) { + unsigned int j; + + j = i + ( random( ) % SHUFFLERATE ); + if ( ( j != i ) && ( j < NUMRANDXFERS ) + && ( records[j].length ) ) { + RandomRecord r; + + r.start = records[j].start; + r.length = records[j].length; + records[j].start = records[i].start; + records[j].length = records[i].length; + records[i].start = r.start; + records[i].length = r.length; + } + i = j; + } + + /* Dump a list of the records. */ + if ( verboseMode ) { + for ( i = 0; ( i < NUMRANDXFERS ) && ( records[i].length ); + i++ ) { + NODEPRINT( "X %d - %d\n", records[i].start, + records[i].length ); + } + } + + /* Send the record list to our partner. */ + retCode = MPI_Send( records, + NUMRANDXFERS * sizeof( RandomRecord ), + MPI_BYTE, partner, 0, MPI_COMM_WORLD ); + ERRABORT( retCode ); + + for ( i = 0; ( i < NUMRANDXFERS ) && ( records[i].length ); + i++ ) { + NODEPRINT( "S %d - %x\n", records[i].start, + records[i].length ); + retCode = MPI_Isend( &buffer[records[i].start], + records[i].length, + MPI_BYTE, partner, i, MPI_COMM_WORLD, + &request[i] ); + ERRABORT( retCode ); + round++; + if (!verboseMode && (round % 100) == 0) + ROOTPRINT("."); + } + } else { + /* Get the record list from our partner. */ + retCode = MPI_Recv( records, + NUMRANDXFERS * sizeof( RandomRecord ), + MPI_BYTE, + partner, 0, MPI_COMM_WORLD, &status[0] ); + ERRABORT( retCode ); + + for ( i = 0; ( i < NUMRANDXFERS ) && ( records[i].length ); + i++ ) { + NODEPRINT( "R %d - %x\n", records[i].start, + records[i].length ); + retCode = MPI_Irecv( &buffer[records[i].start], + records[i].length, + MPI_BYTE, partner, i, MPI_COMM_WORLD, + &request[i] ); + ERRABORT( retCode ); + } + numRecords = i; /* Save the # of records. */ + } + + retCode = MPI_Waitall( numRecords, request, status ); + ERRABORT( retCode ); + for ( i = 0; i < numRecords; i++ ) { + ERRABORT( status[i].MPI_ERROR ); + } + + /* Check for corruption. */ + if ( !sendMode ) { + for ( i = 0; i < ( size - 3 ); i += 4 ) { + unsigned char c = + ( buffer[i] + buffer[i + 1] + buffer[i + 2] ) % 256; + if ( c != buffer[i + 3] ) { + ERRPRINT( "Corruption in the buffer @ %d\n", i ); + dumpbuffer( myid, "rawBuffer", (char*)rawBuffer, + size + 2 * BARRIERSIZE ); + retCode = ~MPI_SUCCESS; + goto done; + } + } + } + + iters -= numRecords; + + } + + ROOTPRINT( "\t%8d\n", size ); + size *= 2; + } + + MPI_Barrier( MPI_COMM_WORLD ); + ROOTPRINT( "Completed Randomize Test Section.\n\n" ); + + done: + + if ( rawBuffer ) + free( rawBuffer ); + + return retCode; +} + +/* + * Calculate the average time to complete MPI_Init. + */ +#define HOSTNAMELEN 32 +#define HOSTOFFSET 8 +int +calc_init_time( int myid, int numProcs, time_t t_start, time_t t_end, + time_t * t_avg ) +{ + time_t t_delta, t_min, t_max, t_temp; + int i, retCode = MPI_SUCCESS; + + if ( myid != 0 ) { + /* Send our time to init back to the 0 node. */ + char mydata[HOSTNAMELEN + HOSTOFFSET]; + + /* Build a buffer containing our host name and the elapsed time. */ + t_delta = t_end - t_start; + *( ( time_t * ) mydata ) = t_delta; + gethostname( &mydata[HOSTOFFSET], HOSTNAMELEN ); + + mydata[HOSTOFFSET + HOSTNAMELEN - 1] = 0; + + retCode = MPI_Send( mydata, + HOSTNAMELEN + HOSTOFFSET, MPI_CHAR, 0, 0, + MPI_COMM_WORLD ); + ERRABORT( retCode ); + } else { + /* Collect time to init data. */ + MPI_Status status; + char curdata[HOSTNAMELEN + HOSTOFFSET]; + char min_host[HOSTNAMELEN]; + char max_host[HOSTNAMELEN]; + double avg; + + /* Initially the root is both best and worst. */ + gethostname( min_host, HOSTNAMELEN ); + gethostname( max_host, HOSTNAMELEN ); + + t_delta = t_end - t_start; + t_min = t_delta; + t_max = t_delta; + + /* + * We don't care what order the replies come in, + * as long as we get them all. + */ + for ( i = 0; i < numProcs - 1; i++ ) { + memset( &status, 0, sizeof( status ) ); + retCode = MPI_Recv( curdata, + HOSTNAMELEN + HOSTOFFSET, MPI_CHAR, + MPI_ANY_SOURCE, 0, MPI_COMM_WORLD, &status ); + ERRABORT( retCode ); + t_temp = *( ( time_t * ) curdata ); + t_delta += t_temp; + + if ( t_temp < t_min ) { + t_min = t_temp; + strcpy( min_host, &curdata[HOSTOFFSET] ); + } else if ( t_temp > t_max ) { + t_max = t_temp; + strcpy( max_host, &curdata[HOSTOFFSET] ); + } + } + + avg = ( double ) t_delta / ( double ) numProcs; + ROOTPRINT( "Maximum time to init was: %8ld seconds (%s).\n", + t_max, max_host ); + ROOTPRINT( "Minimum time to init was: %8ld seconds (%s).\n", + t_min, min_host ); + ROOTPRINT( "Average time to init was: %8.2lf seconds.\n", avg ); + } + + return retCode; +} + +/* + * Simple whisper down the lane test. Rank 0 sends a message to rank 1, + * who passes it to 2, etc., till rank N returns it to rank 0. At that + * point, it is compared against what was sent. + * + * This code is made more complicated by the desire to mangle memory + * usage in order to uncover possible corruption issues. If useSendOffset + * is specified, each successive round moves the buffer one byte higher + * in memory. In addition, if rawBufferCount is > 1, the code will use + * multiple buffers in a ring. This is primarily to cause an increase in + * total memory consumption to induce paging operations, which can affect + * memory transfers to/from the HCA. + * + */ +int +slowRing( int myid, int numProcs, int minSize, int maxSize, int maxIters ) +{ + unsigned int i, size, iters, round; + int retCode = MPI_SUCCESS; + + MPI_Request *request = NULL; + MPI_Status *status = NULL; + + char **rawSendBuffer = NULL; + char **rawRecvBuffer = NULL; + char *sendBuffer, *recvBuffer; + + request = malloc( sizeof( MPI_Request ) ); + status = malloc( sizeof( MPI_Status ) ); + if ( !request || !status ) { + ERRPRINT( "Failed to allocate requests and status.\n" ); + retCode = ~MPI_SUCCESS; + goto done; + } + + memset( request, 0, sizeof( MPI_Request ) ); + memset( status, 0, sizeof( MPI_Status ) ); + + rawSendBuffer = malloc( sizeof( char * ) * rawBufferCount ); + rawRecvBuffer = malloc( sizeof( char * ) * rawBufferCount ); + memset( rawSendBuffer, 0, sizeof( char * ) * rawBufferCount ); + memset( rawRecvBuffer, 0, sizeof( char * ) * rawBufferCount ); + + ROOTPRINT( "Beginning Slow Ring Test Section\n" ); + ROOTPRINT( "(This test passes messages from node to node in a ring\n" + "and validates that the end result matches the original\n" + "message.)\n" ); + + size = minSize; + iters = maxIters; + + while ( size <= maxSize ) { + + for ( round = 0; round < iters; round++ ) { + size_t rawBufferSize = + ( barrierSize * 2 ) + ( size + ( useSendOffset ? round : 0 ) ); + char *currentRawSendBuffer; + char *currentRawRecvBuffer; + + /* + * If we already had a buffer here, we free it then + * reallocate it. In a sane world, we will normally + * get the same memory back again, but this could also + * trigger various "optimizations" in malloc's handling + * of the heap and the operating system's handling of + * the page table - and it stresses any malloc management + * magic in MPI itself... + */ + if ( rawSendBuffer[round % rawBufferCount] != NULL ) { + free( rawSendBuffer[round % rawBufferCount] ); + } + rawSendBuffer[round % rawBufferCount] = malloc( rawBufferSize ); + if ( rawRecvBuffer[round % rawBufferCount] != NULL ) { + free( rawRecvBuffer[round % rawBufferCount] ); + } + rawRecvBuffer[round % rawBufferCount] = malloc( rawBufferSize ); + if ( !rawRecvBuffer[round % rawBufferCount] + || !rawSendBuffer[round % rawBufferCount] ) { + ERRPRINT( "Failed to allocate buffers.\n" ); + retCode = ~MPI_SUCCESS; + goto done; + } + + currentRawSendBuffer = rawSendBuffer[round % rawBufferCount]; + currentRawRecvBuffer = rawRecvBuffer[round % rawBufferCount]; + + sendBuffer = + currentRawSendBuffer + barrierSize + + ( useSendOffset ? round : 0 ); + recvBuffer = + currentRawRecvBuffer + barrierSize + + ( useSendOffset ? round : 0 ); + + /* + * Setting up guard areas to check for corruption. + */ + memset( currentRawSendBuffer, myid, rawBufferSize ); + memset( currentRawRecvBuffer, myid, rawBufferSize ); + + /* Create some data to send and validate against. */ + for ( i = 0; i < size; i++ ) + sendBuffer[i] = ( unsigned char ) ( i % 256 ); + + if ( myid == 0 ) { + /* Root initiates the loop and vets the results. */ + NODEPRINT( "S node 1\n" ); + + retCode = + MPI_Send( sendBuffer, size, MPI_CHAR, 1, round, + MPI_COMM_WORLD ); + ERRABORT( retCode ); + + NODEPRINT( "W node %d\n", numProcs - 1 ); + + retCode = MPI_Recv( recvBuffer, + size, + MPI_CHAR, + numProcs - 1, + round, MPI_COMM_WORLD, status ); + ERRABORT( retCode ); + + if ( memcmp( currentRawSendBuffer, + currentRawRecvBuffer, rawBufferSize ) ) { + ERRPRINT( "%d byte messages do not match!\n", size ); + dumpbuffer( myid, "rawSendBuffer", currentRawSendBuffer, + rawBufferSize ); + dumpbuffer( myid, "rawRecvBuffer", currentRawRecvBuffer, + rawBufferSize ); + retCode = ~MPI_SUCCESS; + goto done; + } + } else { + /* Everyone else waits for a message and then repeats it to + * their neighbor. */ + NODEPRINT( "W node %d\n", myid - 1 ); + retCode = MPI_Recv( recvBuffer, + size, + MPI_CHAR, + myid - 1, round, MPI_COMM_WORLD, status ); + ERRABORT( retCode ); + NODEPRINT( "S node %d\n", myid + 1 ); + retCode = MPI_Send( recvBuffer, + size, + MPI_CHAR, + ( myid + 1 ) % numProcs, + round, MPI_COMM_WORLD ); + ERRABORT( retCode ); + + /* + * Note that we never sent SendBuffer but it should still + * be a correct model of what we actually received then + * sent. + */ + if ( memcmp( currentRawSendBuffer, + currentRawRecvBuffer, rawBufferSize ) ) { + ERRPRINT( "%d byte messages do not match!\n", size ); + dumpbuffer( myid, "rawSendBuffer", currentRawSendBuffer, + rawBufferSize ); + dumpbuffer( myid, "rawRecvBuffer", currentRawRecvBuffer, + rawBufferSize ); + retCode = ~MPI_SUCCESS; + goto done; + } + } + + if ( !verboseMode && ( round % 100 ) == 0 ) + ROOTPRINT( "." ); + } + ROOTPRINT( "\t%8d\n", size ); + + size *= 2; + iters = ( iters > 1 ) ? iters / 2 : 1; + } + + ROOTPRINT( "Completed Slow Ring Test Section.\n\n" ); + + done: + if ( rawRecvBuffer ) { + for ( i = 0; i < rawBufferCount; i++ ) { + if ( rawRecvBuffer[i] ) { + free( rawRecvBuffer[i] ); + } + } + + free( rawRecvBuffer ); + } + + if ( rawSendBuffer ) { + for ( i = 0; i < rawBufferCount; i++ ) { + if ( rawSendBuffer[i] ) { + free( rawSendBuffer[i] ); + } + } + + free( rawSendBuffer ); + } + + if ( request ) + free( request ); + if ( status ) + free( status ); + return retCode; +} + +/* + * Fast whisper down the lane test. Rank 0 sends many messages to rank 1, + * who passes them to 2, etc., till rank N returns them to rank 0. At that + * point, the messages are compared against what was sent. + */ +int +fastRing( int myid, int numProcs, int minSize, int maxSize, int maxIters ) +{ + unsigned int i, j, size, iters, round; + int retCode = MPI_SUCCESS; + + MPI_Request *request = NULL; + MPI_Status *status = NULL; + + char **rawSendBuffer = NULL; + char **rawRecvBuffer = NULL; + char *sendBuffer, *recvBuffer; + size_t rawBufferSize = + ( barrierSize * 2 ) + ( maxSize + ( useSendOffset ? maxIters : 0 ) ); + + request = malloc( (rawBufferCount+maxIters) * sizeof( MPI_Request ) ); + status = malloc( (rawBufferCount+maxIters) * sizeof( MPI_Status ) ); + if ( !request || !status ) { + ERRPRINT( "Failed to allocate requests and status.\n" ); + retCode = ~MPI_SUCCESS; + goto done; + } + + memset( request, 0, (rawBufferCount+maxIters) * sizeof( MPI_Request ) ); + memset( status, 0, (rawBufferCount+maxIters) * sizeof( MPI_Status ) ); + + rawSendBuffer = malloc( sizeof( char * ) * rawBufferCount ); + rawRecvBuffer = malloc( sizeof( char * ) * rawBufferCount ); + memset( rawSendBuffer, 0, sizeof( char * ) * rawBufferCount ); + memset( rawRecvBuffer, 0, sizeof( char * ) * rawBufferCount ); + + for ( i = 0; i < rawBufferCount; i++ ) { + rawSendBuffer[i] = malloc( rawBufferSize ); + rawRecvBuffer[i] = malloc( rawBufferSize ); + + if ( !rawRecvBuffer[i] || !rawSendBuffer[i] ) { + ERRPRINT( "Failed to allocate buffers.\n" ); + retCode = ~MPI_SUCCESS; + goto done; + } + } + + ROOTPRINT( "Beginning Fast Ring Test Section\n" ); + ROOTPRINT( "(This test passes multiple messages from node to node in a\n" + "ring and validates that the end result matches the original\n" + "message.)\n" ); + + size = minSize; + iters = maxIters; + + while ( size <= maxSize ) { + + if ( myid == 0 ) { + for ( j = 0; j < rawBufferCount; j++) { + char *currentRawSendBuffer = rawSendBuffer[j]; + char *currentRawRecvBuffer = rawRecvBuffer[j]; + + /* + * Setting up guard areas to check for corruption. + */ + memset( currentRawSendBuffer, myid, rawBufferSize ); + memset( currentRawRecvBuffer, myid, rawBufferSize ); + + sendBuffer = currentRawSendBuffer + barrierSize; + + /* Create some data to send and validate against. */ + for ( i = 0; i < size; i++ ) + sendBuffer[i] = ( unsigned char ) ( i % 256 ); + } + + for ( round = 0; round < iters; round+= rawBufferCount ) { + + /* Fire in the hole! */ + for (j = 0; j 1 ) ? iters / 2 : 1; + } + + ROOTPRINT( "Completed Fast Ring Test Section.\n\n" ); + + done: + if ( rawRecvBuffer ) { + for ( i = 0; i < rawBufferCount; i++ ) { + if ( rawRecvBuffer[i] ) { + free( rawRecvBuffer[i] ); + } + } + + free( rawRecvBuffer ); + } + + if ( rawSendBuffer ) { + for ( i = 0; i < rawBufferCount; i++ ) { + if ( rawSendBuffer[i] ) { + free( rawSendBuffer[i] ); + } + } + + free( rawSendBuffer ); + } + + if ( request ) + free( request ); + if ( status ) + free( status ); + return retCode; +} + +int +main( int argc, char *argv[] ) +{ + int retCode, myid, numProcs, i; + time_t t1, t2, t3; + + t1 = time( NULL ); + MPI_Init( &argc, &argv ); + MPI_Comm_size( MPI_COMM_WORLD, &numProcs ); + MPI_Comm_rank( MPI_COMM_WORLD, &myid ); + t2 = time( NULL ); + + while ( -1 != + ( retCode = getopt_long_only( argc, argv, "", options, &i ) ) ) { + switch ( retCode ) { + case '<': + minSize = strtoul( optarg, NULL, 0 ); + break; + case '>': + maxSize = strtoul( optarg, NULL, 0 ); + break; + case 'i': + maxIters = strtoul( optarg, NULL, 0 ); + break; + case 'b': + rawBufferCount = strtoul( optarg, NULL, 0 ); + break; + case 'B': + barrierSize = strtoul( optarg, NULL, 0 ); + break; + case '?': + usage( ); + goto done; + default: + break; + } + } + + ROOTPRINT( "-----------------------------\n" ); + ROOTPRINT( "-----------------------------\n" ); + ROOTPRINT( "Initialization complete.\n" ); + MPI_Barrier( MPI_COMM_WORLD ); + retCode = calc_init_time( myid, numProcs, t1, t2, &t3 ); + ERRABORT( retCode ); + + ROOTPRINT( "--------------------------\n" ); + ROOTPRINT( "--------------------------\n" ); + ROOTPRINT( "Number of nodes = %d\n", numProcs ); + ROOTPRINT( "Minimum message size = %d\n", minSize ); + ROOTPRINT( "Maximum message size = %d\n", maxSize ); + ROOTPRINT( "Maximum # of rounds = %d\n\n", maxIters ); + ROOTPRINT( "Use Message Send Offset = %s\n", useSendOffset ? "ON" : "OFF" ); + ROOTPRINT( "Message Buffer Count = %d\n", rawBufferCount ); + ROOTPRINT( "Message Barrier Size = %d\n\n", barrierSize ); + + if ( doSlow ) { + MPI_Barrier( MPI_COMM_WORLD ); + retCode = slowRing( myid, numProcs, minSize, maxSize, maxIters ); + ERRABORT( retCode ); + } + if ( doFast ) { + MPI_Barrier( MPI_COMM_WORLD ); + retCode = fastRing( myid, numProcs, minSize, maxSize, maxIters ); + ERRABORT( retCode ); + } + if ( doRandom ) { + MPI_Barrier( MPI_COMM_WORLD ); + retCode = randomize( myid, numProcs, minSize, maxSize, maxIters ); + ERRABORT( retCode ); + } + + ROOTPRINT( "--------------------------\n" ); + ROOTPRINT( "--------------------------\n" ); + + done: + MPI_Finalize( ); + return retCode; +} diff --git a/MpiApps/apps/mpif77 b/MpiApps/apps/mpif77 new file mode 100755 index 0000000..e45a85b --- /dev/null +++ b/MpiApps/apps/mpif77 @@ -0,0 +1,25 @@ +#! /bin/bash +# A simple wrapper of mpif77 to force it uses RPATH +#set -x +echo "REAL_MPIF77=$REAL_MPIF77" +# generate compile string and replace 'enable-new-dtags' with 'disable-new-dtags' +# to force use RPATH. Given we can have space in quoted string that will cause +# wrong word splitting, we split string into arguments by ourselves with ' -'. +# To do it, we replace ' -' with '\n-' and then split the string with customized +# IFS that is set to new line +cmd_str=$($REAL_MPIF77 -show "$@" | sed -e 's/enable-new-dtags/disable-new-dtags/g' -e 's/[[:space:]]\+-/\n-/g') +OLDIFS=$IFS +IFS=$'\n' +args=() +# for each argument that constains '"', we escape special characters in the argument. +# Please note that an argument only can contains one quoted string, so it's fine +# to do escape in the whole string +for arg in ${cmd_str[@]}; do + if [[ "$arg" == *\"* ]]; then + args+=" $'$arg'" + else + args+=" $arg" + fi +done +IFS=$OLDIFS +eval "${args[*]}" diff --git a/MpiApps/apps/mvapich2.params b/MpiApps/apps/mvapich2.params new file mode 100644 index 0000000..43cbe1c --- /dev/null +++ b/MpiApps/apps/mvapich2.params @@ -0,0 +1,112 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +#[ICS VERSION STRING: unknown] +#!/bin/bash + +# PURPOSE: +# +# This file sets environment variables for an mvapich2 job. +# Note that there are many, many such variables. +# See http://mvapich.cse.ohio-state.edu/support/ for details. + +# SYNTAX: +# +# This file must be a valid BASH script. In general, anything that's valid +# in BASH is valid here. To pass variables to mvapich2, however, they +# should take this form: +# +# export MPI_CMD_ARGS="$MPI_CMD_ARGS -genv MV2_VARIABLE_NAME variablevalue" +# + +# SAMPLE Tuning variables: +# +# Uncomment the following lines to enable them. +# +. /usr/sbin/opagetvf_env # defines bash function opagetvf_func +export MPI_CMD_ARGS= + +# These 3 lines select a Virtual Fabric by name and configure PKEY, SL, MTU +# opagetvf_func "-d 'Compute'" MV2_DEFAULT_PKEY MV2_DEFAULT_SERVICE_LEVEL MTU +# export MPI_CMD_ARGS="-genv MV2_DEFAULT_PKEY $MV2_DEFAULT_PKEY -genv MV2_DEFAULT_SERVICE_LEVEL $MV2_DEFAULT_SERVICE_LEVEL -genv PSM2_PKEY $MV2_DEFAULT_PKEY -genv HFI_SL $MV2_DEFAULT_SERVICE_LEVEL" +# [ -n "$MTU" ] && export MPI_CMD_ARGS="$MPI_CMD_ARGS -genv MV2_DEFAULT_MTU IBV_MTU_$MTU -genv PSM2_MTU $MTU" + +# These 3 lines select a Virtual Fabric by ServiceId and configure PKEY, SL, MTU +# opagetvf_func "-S '0x1000117500000000'" MV2_DEFAULT_PKEY MV2_DEFAULT_SERVICE_LEVEL MTU +# export MPI_CMD_ARGS="-genv MV2_DEFAULT_PKEY $MV2_DEFAULT_PKEY -genv MV2_DEFAULT_SERVICE_LEVEL $MV2_DEFAULT_SERVICE_LEVEL -genv PSM2_PKEY $MV2_DEFAULT_PKEY -genv HFI_SL $MV2_DEFAULT_SERVICE_LEVEL" +# [ -n "$MTU" ] && export MPI_CMD_ARGS="$MPI_CMD_ARGS -genv MV2_DEFAULT_MTU IBV_MTU_$MTU -genv PSM2_MTU $MTU" + +# These line selects a Virtual Fabric by ServiceId and uses dist_sa +# to directly fetch the PathRecord at job startup. This approach is +# required when using Mesh/Torus fabrics and optional for other topologies. +# This mechanism is only supported for Intel HFIs when using PSM (-hfi MPIs) +#export MPI_CMD_ARGS="-genv PSM2_PATH_REC opp -genv PSM2_IB_SERVICE_ID 0x1000117500000000" + +# This line can enable dispersive routing. The following choices are allowed: +# adaptive, static_src, static_dest, static_base +# If LMC is enabled in the SM, adaptive will automatically be used. +# This mechanism is only supported for Intel HFIs when using PSM (-hfi MPIs) +#export MPI_CMD_ARGS="$MPI_CMD_ARGS -genv PSM2_PATH_SELECTION adaptive" + +# Use this to explicitly specify a pkey (for virtual fabrics) +#pkey=0x8002 +#export MPI_CMD_ARGS="$MPI_CMD_ARGS -genv MV2_DEFAULT_PKEY $pkey -genv PSM2_PKEY $pkey" + +# Use this to explicitly specify a service level (for virtual fabrics) +#sl=0 +#export MPI_CMD_ARGS="$MPI_CMD_ARGS -genv MV2_DEFAULT_SERVICE_LEVEL $sl -genv HFI_SL $sl" + +# Use this to explicitly specify a MTU (for virtual fabrics) +#mtu=4096 +#export MPI_CMD_ARGS="$MPI_CMD_ARGS -genv MV2_DEFAULT_MTU IBV_MTU_$mtu -genv PSM2_MTU $mtu" + +# Use this to enable core dumps +# (in addition ulimit and /etc/security/limits must enable core dumps too) +#export MPI_CMD_ARGS="$MPI_CMD_ARGS -genv MV2_DEBUG_CORESIZE unlimited -genv HFI_NO_BACKTRACE 1" + +# Note that to use the rdma_cm, support for it must be enabled when mvapich2 +# is compiled. +#export MPI_CMD_ARGS="$MPI_CMD_ARGS -genv MV2_USE_RDMA_CM 1" + +# When using Intel HFIs over Verbs, the following are recommended +#export MPI_CMD_ARGS="$MPI_CMD_ARGS -genv MV2_USE_RDMA_FAST_PATH 0" + +# Normally Congestion Control is completely configured in the SM config file. +# However, if desired, the fabric interface settings can be overridden for +# the given job. +#export MPI_CMD_ARGS="$MPI_CMD_ARGS -genv PSM2_DISABLE_CCA 0" + +# These values can enable and control PSM Multi-Rail +# In most cases the default automatic selections will be sufficient. +# The sample shown is for Dual HFI server with port 1 per HFI connected +#export MPI_CMD_ARGS="$MPI_CMD_ARGS -genv PSM2_MULTIRAIL 1 -genv PSM2_MULTIRAIL_MAP 0:1,1:1" + +# This can be enabled to force benchmarks to run on selected CPU cores +#export MPI_TASKSET="${MPI_TASKSET:- -c 1-7}" + diff --git a/MpiApps/apps/nvidia/Makefile b/MpiApps/apps/nvidia/Makefile new file mode 100644 index 0000000..e90a941 --- /dev/null +++ b/MpiApps/apps/nvidia/Makefile @@ -0,0 +1,55 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +ifndef MPICH_PREFIX +export MPICH_PREFIX=/usr/lib/opa +endif +ifndef MPICC +export MPICC=$(MPICH_PREFIX)/bin/mpicc +endif + +# Adjust path locations as necessary + +INCLUDES = -I/usr/local/cuda/include +LIBPATH = -L/usr/local/cuda/lib64 +LIBS = -lcudart +DEFINES = -DPINNED + +all: mpi_pinned mpi_pageable + +mpi_pinned: mpi_pinned.c + ${MPICC} ${INCLUDES} ${DEFINES} ${LIBPATH} ${LIBS} -o $@ $^ + +mpi_pageable: mpi_pinned.c + ${MPICC} ${INCLUDES} ${LIBPATH} ${LIBS} -o $@ $^ + +.PHONY: clean +clean: + rm -f mpi_pinned mpi_pageable *.o + diff --git a/MpiApps/apps/nvidia/README.txt b/MpiApps/apps/nvidia/README.txt new file mode 100644 index 0000000..fe42e23 --- /dev/null +++ b/MpiApps/apps/nvidia/README.txt @@ -0,0 +1,59 @@ +Interfacing Intel InfiniBand with NVIDIA GPUs + +----------------------------------------------------------------------------- +Introduction +----------------------------------------------------------------------------- + +This directory provides information on how to setup and test that two +drivers -- the Intel InfiniBand driver (qib) and the NVIDIA GPU driver -- +can share pinned memory pages for optimal performance. + +If you are running on any Linux distribution supported by this Intel +InfiniBand software release, then you must use NVIDIA CUDA 4.0 or newer to +have a supported solution from NVIDIA. To get optimal performance with the +qib InfiniBand driver in this software release in applications which CUDA 4.x, +all you need to do is to set the environment variable: + CUDA_NIC_INTEROP=1 +and to propagate that variable to the compute nodes running the application. + +--------------------------------------- +CONTENTS + +- README.txt - This file + +- mpi_pinned.c - A small test program that can verify if the + installation was successful. +- Makefile - File to enable easy build of two test programs + from mpi_pinned.c + +--------------------------------------- + +Note: + +In previous QLogic IFS releases, NVIDIA support required a patch to the CUDA +3.1 or 3.2 driver. This patch is not needed when using IFS 7.1 and CUDA 4.0 +or higher, so the patch is no longer included. + +------------------------------------------------ +CUDA Toolkit and mpi_pinned.c test program +------------------------------------------------ + +To build the test programs, use the following steps: + +1. Download and install the CUDA Toolkit for your Linux distribution. + + - Please make sure your LD_LIBRARY_PATH includes /usr/local/cuda/lib64 + - Please make sure your PATH includes /usr/local/cuda/bin + +2. From the /usr/src/opa/mpi_apps directory, choose your mpi as you + would normally, then type: + + # make NVIDIA + +3. Copy the resulting binaries to all nodes using the fast-fabric tools or + with scp. + +4. From the same directory, type: + + # ./run_nvidia + diff --git a/MpiApps/apps/nvidia/mpi_pinned.c b/MpiApps/apps/nvidia/mpi_pinned.c new file mode 100644 index 0000000..0ab19c2 --- /dev/null +++ b/MpiApps/apps/nvidia/mpi_pinned.c @@ -0,0 +1,144 @@ +/* BEGIN_ICS_COPYRIGHT7 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT7 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ +// mpi_pinned.c +// +// To run with, for example, Open MPI: +// mpirun -x LD_LIBRARY_PATH -np 2 -host host1,host2 ./mpi_pinned +// +////////////////////////////////////////////////////////////////////// +#include +#include +#include +#include +#include +#include + +#define NREPEAT 10 +#define NBYTES 10.e6 + +void usage(const char * name) +{ + printf("Usage: %s -x LD_LIBRARY_PATH \\ \n" + " -np 2 -host computer1,computer2 _out//mpi_pinned\n", + name); +} + +int main (int argc, char *argv[]) +{ + int rank, size, n, len; + int result; + void *a_h, *a_d; + struct timeval time[2]; + double bandwidth; + char hostname[MPI_MAX_PROCESSOR_NAME]; + MPI_Status status; + + MPI_Init (&argc, &argv); + MPI_Comm_rank (MPI_COMM_WORLD, &rank); + MPI_Comm_size (MPI_COMM_WORLD, &size); + + MPI_Get_processor_name(hostname, &len); + printf("Process %d is on %s\n", rank, hostname); + + if (argc > 1 && *argv[1] == 'h') + { + usage(argv[0]); + exit(0); + } + +#ifdef PINNED + cudaMallocHost( (void **) &a_h, NBYTES); +#else + a_h = malloc(NBYTES); +#endif + + result = cudaMalloc( (void **) &a_d, NBYTES); + if (result) + { + printf("ERROR: %s: cudaMalloc failed, error code: %d, which means: %s\n", + hostname, result, cudaGetErrorString(result)); + exit(1); + } + + /* Test host -> device bandwidth. */ + + gettimeofday(&time[0], NULL); + for (n=0; ndevice bandwidth for process %d: %f MB/sec\n",rank,bandwidth); + + /* Test MPI send/recv bandwidth. */ + + MPI_Barrier(MPI_COMM_WORLD); + + gettimeofday(&time[0], NULL); + for (n=0; n +#include + +main(int argc, char *argv[]) +{ + int my_rank; + int n, num_tasks, i, final_n, msgtype; + float data[100], result[100]; + char sbuff[1000], rbuff[1000]; + int position; + MPI_Status status; + + /* Initialize MPI */ + MPI_Init(&argc, &argv); + + /* Get our task id (our rank in the basic group) */ + MPI_Comm_rank(MPI_COMM_WORLD, &my_rank); + + /* Get the number of MPI tasks and slaves */ + MPI_Comm_size(MPI_COMM_WORLD, &num_tasks); + + if (my_rank != 0) { + fprintf(stderr,"%s should only be the first program.\n",argv[0]); + return -1; + } + + fprintf(stderr,"num_tasks = %d\n",num_tasks); + + /* Begin User Program */ + + /* actual argument run from 1 to argc. */ + n = (argc < 100)?argc:100; + for( i=1 ; i +#include +main(int argc, char *argv[]) +{ + int my_rank; + int n, n2, i, min, dest, num_tasks, msgtype; + float args[100], data[100], result[100]; + char rbuff[1000], sbuff[1000]; + int position; + MPI_Status status; + + /* Initialize MPI */ + MPI_Init(&argc, &argv); + + /* Get our task id (our rank in the basic group) */ + MPI_Comm_rank(MPI_COMM_WORLD, &my_rank); + + /* Get the number of MPI tasks */ + MPI_Comm_size(MPI_COMM_WORLD, &num_tasks); + + if (my_rank == 0) { + fprintf(stderr,"%s cannot be the first program.\n",argv[0]); + return -1; + } + + /* Just to make the print outs easier to read. */ + sleep(my_rank); + + /* process arguments, skipping argv[0] */ + n = (argc < 100)?argc:100; + for( i=1 ; i= num_tasks) { + dest = 0; + } + + fprintf(stderr,"Task %d sending to task %d\n",my_rank, dest); + msgtype = 0; + MPI_Send(sbuff, position, MPI_PACKED, dest, msgtype, + MPI_COMM_WORLD); + + /* Program finished. Exit from MPI */ + MPI_Barrier(MPI_COMM_WORLD); + MPI_Finalize(); +} + diff --git a/MpiApps/apps/prepare_run b/MpiApps/apps/prepare_run new file mode 100755 index 0000000..ce4ec21 --- /dev/null +++ b/MpiApps/apps/prepare_run @@ -0,0 +1,201 @@ +#!/bin/sh +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] + +# helper script to handle common setup for the sample application run scripts + +# this script should be . included in a run_ script +# Input: +# MPICH_PREFIX - path to MPICH tools +# MPI_HOSTS - mpi_hosts file to use (default is $PWD/mpi_hosts) +# MPI_TASKSET - arguments to /bin/taskset to control CPU selection +# default is to not use /bin/taskset +# may be set in environment or param file +# SHOW_MPI_HOSTS - set to "y" if MPI_HOSTS contents should be output prior +# to starting job. Set to "n" to disable +# defaults to "y" +# SHOW_MPI_HOSTS_LINES - maximum lines in MPI_HOSTS to show. Default is 128 +# Only lines applicable to job will be shown. +# Note the file might include some comment lines +# NUM_PROCESSES - number of processes in job, if "" no count is specified +# if "all" use wc -l $MPI_HOSTS as the process count +# MIN_PROCESSES - minimum number of processes in job (default of 2) +# MULT_PROCESSES - NUM_PROCESSES must be a multiple of this (default of 1) +# PARAM_FILE - Native IB param file to use, if "" no param file is specified +# APP - application name for use a prefix to LOGFILE name +# LOGFILE - logfile to append results of run to, if "" this script will define +# LOGSUFFIX - suffix to append to logfile name defined by this script +# Output: +# MPI_RUN_CMD - MPI command to start job, actual program name and args can be suffixed +# LOGFILE - logfile to append results of run to + +. ./select_mpi # default MPICH_PREFIX if necessary + +# helper function which can be called by each run_* script to output the +# list of hosts the job is run for. By default the output is enabled. +# This can be especially useful when running many small +# batch jobs, such as cabletest, so that errors in the log can more easily +# be associated to the list of hosts included in the run +show_mpi_hosts() +{ + local lines + + echo "Using hosts list: $MPI_HOSTS" + + if [ "${SHOW_MPI_HOSTS:-y}" = "y" ] + then + show_lines=${SHOW_MPI_HOSTS_LINES:-128} + if [ "z$NUM_PROCESSES" != "z" ] + then + # there may be comments before the last host. So we number the + # lines, filter out the lines with comments and blank lines + # and then get the "NUM_PROCESSES"th line's number + avail_lines=$(nl -s';' -nln -w1 -ba $MPI_HOSTS|egrep -v '^[0-9]*;[[:space:]]*#'|egrep -v '^[0-9]*;[[:space:]]*$'|head -$NUM_PROCESSES|tail -1|cut -f1 -d';' ) + else + # no NUM_PROCESSES, so use whole file + avail_lines=$(cat $MPI_HOSTS|wc -l) + fi + if [ $show_lines -ge $avail_lines ] + then + echo "Hosts in run:" + head -n $avail_lines $MPI_HOSTS + else + echo "First $show_lines lines in host list for run:" + head -n $show_lines $MPI_HOSTS + fi + echo + fi +} + +MPI_HOSTS=${MPI_HOSTS:-$PWD/mpi_hosts} + +if [ $(echo $MPI_HOSTS|cut -c1) != '/' ] +then + MPI_HOSTS="$PWD/$MPI_HOSTS" +fi + +MIN_PROCESSES=${MIN_PROCESSES:-2} +MULT_PROCESSES=${MULT_PROCESSES:-1} +if [ z"$NUM_PROCESSES" = zall ] +then + # skip comment and blank lines + NUM_PROCESSES=$(cat $MPI_HOSTS|egrep -v '^[[:space:]]*#'|egrep -v '^[[:space:]]*$'|wc -l) +fi +if [ z"$NUM_PROCESSES" != z ] +then + if ! [ $NUM_PROCESSES -ge $MIN_PROCESSES ] 2>/dev/null + then + echo " Invalid process count: $NUM_PROCESSES" + echo " This application requires a minimum of $MIN_PROCESSES processes" + exit 2 + fi + if [ $(($NUM_PROCESSES % $MULT_PROCESSES)) -ne 0 ] + then + echo " Invalid process count: $NUM_PROCESSES" + echo " This application requires a multiple of $MULT_PROCESSES processes" + exit 2 + fi +fi + + +if [ ! -f $MPI_HOSTS ] +then + echo " Please create $MPI_HOSTS file with the list of " + echo " processors in this cluster. One hostname per line." + echo " See mpi_hosts.sample file" + exit 1 +fi + +if [ -z "$LOGFILE" ] +then + CURTIME=`date +%d%b%y%H%M%S` + if [ ! -d logs ] + then + mkdir -p logs + fi + LOGFILE=$PWD/logs/$APP.$CURTIME$LOGSUFFIX + echo " Running MPI tests with $NUM_PROCESSES processes" + echo " logfile $LOGFILE" + > $LOGFILE +fi + +# additional arguments can be specified on mpirun command line +MPI_CMD_ARGS= +disable_affinity= +USING_MPD=n #I think we can delete this variable +# Determine which MPI is being used: +if [ -e "$MPICH_PREFIX/bin/tune" ] #IntelMPI +then + echo "IntelMPI Detected, running with mpirun." | tee -i -a $LOGFILE + if [ -e ./intelmpi.params ] + then + . ./intelmpi.params + fi + MPI_RUN_CMD="$MPICH_PREFIX/bin/mpirun ${NUM_PROCESSES:+-np $NUM_PROCESSES} -hostfile $MPI_HOSTS $MPI_CMD_ARGS " +elif [ -e "$MPICH_PREFIX/bin/ompi_info" ] #OpenMPI +then + echo "OpenMPI Detected, running with mpirun." | tee -i -a $LOGFILE + MPI_CMD_ARGS="-mca plm_rsh_no_tree_spawn 1" + if [ -e ./openmpi.params ] + then + . ./openmpi.params + fi + MPI_RUN_CMD="$MPICH_PREFIX/bin/mpirun ${NUM_PROCESSES:+-np $NUM_PROCESSES} -map-by node --allow-run-as-root -machinefile $MPI_HOSTS $MPI_CMD_ARGS " + +elif [ -e "$MPICH_PREFIX/bin/mpichversion" ] #Mvapich2 +then + echo "MVAPICH2 Detected, running with mpirun." | tee -i -a $LOGFILE + if [ -e ./mvapich2.params ] + then + . ./mvapich2.params + fi + disable_affinity="-genv MV2_ENABLE_AFFINITY 0" + MPI_RUN_CMD="$MPICH_PREFIX/bin/mpirun -machinefile $MPI_HOSTS ${NUM_PROCESSES:+-n $NUM_PROCESSES} $MPI_CMD_ARGS " +else + echo "MPI Not Recognized!i exiting" | tee -i -a $LOGFILE + exit 1 +fi + +head -n $NUM_PROCESSES $MPI_HOSTS|sort -u > ff.hosts + + +# add /bin/taskset to MPI_RUN_CMD based on MPI_TASKSET value +if [ x"$MPI_TASKSET" != x ] +then + if [ -x /bin/taskset ] + then + MPI_RUN_CMD="$MPI_RUN_CMD $disable_affinity /bin/taskset $MPI_TASKSET " + elif [ -x /usr/bin/taskset ] + then + MPI_RUN_CMD="$MPI_RUN_CMD $disable_affinity /usr/bin/taskset $MPI_TASKSET " + fi +fi + diff --git a/MpiApps/apps/run b/MpiApps/apps/run new file mode 100755 index 0000000..99efde5 --- /dev/null +++ b/MpiApps/apps/run @@ -0,0 +1,134 @@ +#!/bin/sh +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] + +# BASE PATH TO MPI EXECUTABLES: To use an alternate location, +# either edit this line or set MPICH_PREFIX in your environment. +# default to MPI used for build +MPICH_PREFIX=${MPICH_PREFIX:-`cat .prefix 2>/dev/null`} + +trap "exit 1" SIGHUP SIGTERM SIGINT + +if [ -z "$1" ] +then + echo " Usage: run number_processes [full]." + echo " For example: ./run 2" + exit 1 +fi +full=n +if [ x"$2" = x"full" ] +then + full=y +fi + +NUM_PROCESSES=$1 +PARAM_FILE="" +APP=multi +. ./prepare_run + +LATENCY_CMD="latency/latency 100000 0" +LATENCY_CMD2="latency/latency 100000 4" +BANDWIDTH_CMD="bandwidth/bw 100 100000" +#PMB_CMD="PMB2.2/SRC/PMB-MPI1" +PMB_CMD="PMB2.2.1/SRC_PMB/PMB-MPI1" +NPB_CMD="NPB2.3/bin/$test.$class.$NUM_PROCESSES" +HPL_CMD="./xhpl" +HPL_DIR="$PWD/hpl/bin/ICS.`uname -s`.`./get_mpi_cc.sh`" + +{ +if [ $USING_MPD = y ] +then + MPI_RUN_HPL="$MPI_RUN_CMD -wdir $HPL_DIR" +else + MPI_RUN_HPL="$MPI_RUN_CMD" +fi + +show_mpi_hosts +if [ $NUM_PROCESSES -eq 2 ] +then + echo " Running Latency ..." + date + set -x + $MPI_RUN_CMD $LATENCY_CMD + set +x + date + set -x + $MPI_RUN_CMD $LATENCY_CMD2 + set +x + date + echo "########################################### " + + echo " Running Bandwidth ..." + date + set -x + $MPI_RUN_CMD $BANDWIDTH_CMD + set +x + date +fi +echo "########################################### " + +echo " Running Pallas Benchmarks ..." +date +set -x +$MPI_RUN_CMD $PMB_CMD +set +x +date +echo "########################################### " + +if [ "$full" = y ] +then + echo " Running NASA Parallel Benchmarks ..." + class="B" + for test in cg ep lu is mg + do + echo " Running $test.$class.$NUM_PROCESSES benchmark ..." + date + set -x + $MPI_RUN_CMD NPB3.2.1/NPB3.2-MPI/bin/$test.$class.$NUM_PROCESSES + set +x + date + done + echo "########################################### " +fi + + +if [ "$full" = y -a $NUM_PROCESSES -gt 2 ] +then + echo " Running High Performance Computing Linpack Benchmark (HPL) ..." + date + set -x + # need to cd so HPL.dat in current directory + (cd $HPL_DIR; $MPI_RUN_HPL $HPL_CMD ) + set +x + date + echo "########################################### " +fi +} 2>&1 | tee -a -i $LOGFILE diff --git a/MpiApps/apps/run_allhfilatency b/MpiApps/apps/run_allhfilatency new file mode 100755 index 0000000..5b45941 --- /dev/null +++ b/MpiApps/apps/run_allhfilatency @@ -0,0 +1,160 @@ +#!/bin/sh +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] + +# BASE PATH TO MPI EXECUTABLES: To use an alternate location, +# either edit this line or set MPICH_PREFIX in your environment. +# see select_mpi for the set of default MPI selections +# default to MPI used for build +MPICH_PREFIX=${MPICH_PREFIX:-`cat .prefix 2>/dev/null`} + +trap "exit 1" SIGHUP SIGTERM SIGINT + +APP=mpi_allhfilatency +LOGFILE= + +NUM_PROCESSES=2 +SIZE=0 +MINUTES=1 +VERBOSE= +CSV= + +usage() { + echo + echo "$0 is a specialized stress test for large fabrics. It iterates through" + echo "every possible pairing of HCAs and performs a latency test on each" + echo "pair. At the end of each round of testing, the fastest and slowest" + echo "pairs are reported." + echo + echo "This has no real value as a performance benchmark but is" + echo "extremely useful for checking for cabling problems in the fabric." + echo + echo "$0 requires no arguments, but can take three optional arguments." + echo + echo "$0 nn dd ss" + echo + echo "Where nn is the number of ranks, dd is the duration in minutes and ss" + echo "is the message size, in bytes." + echo + echo "For example, to run a 30 minute test on 64 nodes with 4 kilobyte messages:" + echo + echo "$0 64 30 4096" + echo + echo "Once 30 minutes has elapsed, the test will complete as soon" + echo "as the current round of testing has completed." + echo + echo "If you want the tests to repeat indefinitely, use 'infinite' as" + echo "the duration:" + echo + echo "$0 64 infinite 4096" + echo + echo "The nn argument may be 'all' in which case one rank will be started for" + echo "every process in the mpi_hosts file" + echo + echo "Finally, there are three optional arguments, -c, -h and -v." + echo + echo "-h (--help) provides this help text." + echo "-c (--csv) prints all raw test results in CSV file format, into the" + echo " application logfile. Useful for analyzing the raw results with" + echo " a spreadsheet application." + echo "-v (--verbose) runs the test in a verbose mode that shows more" + echo " information." + echo + echo "To use the results of this, look for nodes that are often listed as" + echo "the slowest at the end of the round. One of those nodes may have" + echo "a cabling problem, or there may be a congested interswitch link" + echo "causing those nodes to experience degraded performance." + exit +} + +ARGS=`getopt --name=$0 -o "hvc" -l "help,verbose,csv" -- $@` +if [ $? -ne 0 ]; then + usage +fi +eval set -- $ARGS +while [ $1 != -- ]; do + case $1 in + -h|--help) + usage + shift;; + -v|--verbose) + VERBOSE="-v" + shift;; + -c|--csv) + CSV="-c" + shift;; + esac +done +shift # remove the -- + +if [ $# -ge 1 ]; then + if [ "$1" = "all" ] || [ $1 -eq $1 ]; then + NUM_PROCESSES=$1 + else + usage + fi +fi +shift +if [ $# -ge 1 ]; then + if [ $1 = "infinite" ]; then + MINUTES=0 + elif [ $1 -eq $1 ]; then + MINUTES=$1 + else + usage + fi +fi +shift +if [ $# -ge 1 ]; then + if [ $1 -eq $1 ]; then + SIZE=$1 + else + usage + fi +fi + +. ./prepare_run + +CMD="groupstress/mpi_latencystress -s $SIZE -t $MINUTES $VERBOSE $CSV" + +if [ ! -z "$CSV" ]; then + echo " CSV output in $LOGFILE" + echo +fi +( + echo " Running All HCA Latency Test..." + show_mpi_hosts + set -x + $MPI_RUN_CMD $CMD + set +x +) 2>&1 | tee -i -a $LOGFILE + +echo "########################################### " >> $LOGFILE diff --git a/MpiApps/apps/run_alltoall3 b/MpiApps/apps/run_alltoall3 new file mode 100755 index 0000000..c8c61fc --- /dev/null +++ b/MpiApps/apps/run_alltoall3 @@ -0,0 +1,64 @@ +#!/bin/sh +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] + +# BASE PATH TO MPI EXECUTABLES: To use an alternate location, +# either edit this line or set MPICH_PREFIX in your environment. +# see select_mpi for the set of default MPI selections +# default to MPI used for build +MPICH_PREFIX=${MPICH_PREFIX:-`cat .prefix 2>/dev/null`} + +trap "exit 1" SIGHUP SIGTERM SIGINT + +if [ -z "$1" ] +then + echo " Usage: run_alltoall3 number_processes" + echo " For example: ./run_alltoall3 2" + echo "number_processes may be 'all' in which case one rank will be started for" + echo "every process in the mpi_hosts file" + exit 1 +fi + +NUM_PROCESSES=$1 +APP=osu_alltoall +LOGFILE= +. ./prepare_run + +CMD="osu-micro-benchmarks-3.8-July12/mpi/collective/osu_alltoall" + +( + echo " Running AlltoAll 3.8 ..." + show_mpi_hosts + set -x + $MPI_RUN_CMD $CMD + set +x +) 2>&1 | tee -i -a $LOGFILE +echo "########################################### " >> $LOGFILE diff --git a/MpiApps/apps/run_app b/MpiApps/apps/run_app new file mode 100755 index 0000000..3d82a2b --- /dev/null +++ b/MpiApps/apps/run_app @@ -0,0 +1,270 @@ +#!/bin/sh +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] + +# This is a template to allow generic applications to be run in a test and tune +# mode where statistics and output is desirable to be collected per run for +# later analysis + +# edit the assignments below as need to define the application to run +# you may also want to use runmyapp (or a similar script) as the actual +# APP_CMD in which case you can put the actual command to run and any setup for +# the command in runmyapp on each compute node see runmyapp for an example +# of running HPL + +# Also you can create a file mpi_chassis listing all the relevant SilverStorm +# chassis IP addresses/names for which switch statistics should be cleared and +# fetched for this run. +# If its not present the default fast fabric chassis file will be used. + +# BASE PATH TO MPI EXECUTABLES: To use an alternate location, +# either edit this line or set MPICH_PREFIX in your environment. +# default to MPI used for build +MPICH_PREFIX=${MPICH_PREFIX:-`cat .prefix 2>/dev/null`} + +# MPI_HOSTS - mpi_hosts file to use (default is $PWD/mpi_hosts) +MPI_HOSTS=${MPI_HOSTS:-$PWD/mpi_hosts} +if [ $(echo $MPI_HOSTS|cut -c1) != '/' ] +then + MPI_HOSTS="$PWD/$MPI_HOSTS" +fi + +# temporary file name to use when collecting statistics +# This file will be created on each node in the job +# and deleted again after the data has been collected. +OPASTATS_FILE="$(mktemp --tmpdir 'opastats.XXXXXXXX')" +trap "rm -f $OPASTATS_FILE; exit 1" SIGHUP SIGTERM SIGINT +trap "rm -f $OPASTATS_FILE" EXIT + +# the application to run along with any necessary arguments +# APP_CMD can be ./runmyapp or the actual application name. +# When using runmyapp, you can edit runmyapp with the +# correct application name and arguments. runmyapp gives you an opportunity to +# control the environment such as library paths, core file options, etc +APP_CMD="./runmyapp" +#APP_CMD="PMB2.2.1/SRC_PMB/PMB-MPI1" + +# Application executable name, used to kill application before each run to +# ensure no remnants from a previous run exist +# also used as part of log directory name and included in runlog +# if this is not set, basename of APP_CMD is used instead +APP=xhpl + +# the param file to use (only applicable to MPICH 1 runs) +PARAM_FILE= + +# any relevant input data files which should be saved per run as part of record +# this should be files which you plan to change between runs as you tune +INPUT_FILES=hpl/bin/ICS.$(uname -s).$(./get_mpi_cc.sh)/HPL.dat + +# any output files generated which should be saved per run as part of record +OUTPUT_FILES= + +# an single output file which should be monitored and displayed when running +# for example: hpccoutf.txt +# the file specified must appear on the head node (possibly in a shared +# filesystem which other ranks in the job will write to) +# leave this blank if application primary progress/status output is to screen +MONITOR_FILE= + +# any relevant code files which should be saved per run as part of record +# this should be files which might change between runs as you tune +# can also include any scripts or Makefiles which might be used to build the +# app or directory of any source code for app which might be changing +#CODE_FILES=hpl/bin/ICS.Linux.gcc/xhpl +CODE_FILES= + +loop=n +if [ x"$1" = "x-l" ] +then + loop=y + shift +fi +if [ -z "$1" ] +then + echo " Usage: run_app [-l] number_processes ['reason for run']" + echo " For example: ./run_app 2 'run with 2t problem size'" + echo "number_processes may be 'all' in which case one rank will be started for" + echo "every process in the mpi_hosts file" + exit 1 +else + NUM_PROCESSES=$1 +fi + +if [ -s mpi_chassis ] +then + chassis_arg="-F mpi_chassis" +else + chassis_arg= +fi + +if [ "x$APP" = "x" ] +then + # get command name part of APP_CMD (eg. remove arguments) + app=`(set $APP_CMD; echo $1)` + APP=`basename $app` +fi +CURTIME=`date +%d%b%y%H%M%S` +dir=$PWD/logs/$APP.$CURTIME$LOGSUFFIX +LOGFILE=$dir/log +mkdir -p $dir + +# keep some temp local files with info about the job +echo "$CURTIME" > curtime +echo "$APP" > app +echo "$APP.$CURTIME$LOGSUFFIX - $2" >> logs/runlog +echo " Running MPI app ($APP_CMD) with $NUM_PROCESSES processes" +echo " logfile $LOGFILE" +> $LOGFILE + +. ./prepare_run + +# clear output +# remove debug output file +echo " Removing debug and core files..." +rm -f MVICH-DBG.* pid core.* $OUTPUT_FILES $MONITOR_FILE +opacmdall -p -f ff.hosts -u `whoami` "cd $PWD;"'rm -f MVICH-DBG.* core.*' > /dev/null 2>&1 +if [ x"$MONITOR_FILE" != x ] +then + > $MONITOR_FILE +fi + +# copy data before we start the run +echo " Copying files to $dir..." +cp -r $PARAM_FILE $INPUT_FILES $CODE_FILES $MPI_HOSTS run_app runmyapp $dir +if [ -f mpi_chassis ] +then + cp mpi_chassis $dir +fi + +# kill any existing instances of app, just to be safe +echo " Killing $APP..." +pkill $APP >/dev/null 2>&1 +opacmdall -p -f ff.hosts -u `whoami` "pkill $APP 2>/dev/null" >/dev/null 2>&1 + +# fetch host stats before +echo " Fetching host stats..." +opacmdall -p -f ff.hosts -u `whoami` "opainfo -o stats > $OPASTATS_FILE 2>/dev/null" > /dev/null +opauploadall -p -f ff.hosts -u `whoami` -d $dir $OPASTATS_FILE opastats-before > /dev/null +opacmdall -p -f ff.hosts -u `whoami` "rm -f $OPASTATS_FILE" > /dev/null + +# fetch switch stats +echo " Fetching switch stats..." +opacmdall -C $chassis_arg "ismPortStats -noprompt" > $dir/switch_stats-before +#iba_report -C -o none + +echo "$msg" | tee -i -a $LOGFILE +if [ $loop = y ] +then + echo " Looping $APP_CMD ..." + echo " Looping $APP_CMD ..." >> $LOGFILE +else + echo " Running $APP_CMD ..." + echo " Running $APP_CMD ..." >> $LOGFILE +fi +show_mpi_hosts | tee -a $LOGFILE +while true +do + date + date >> $LOGFILE + echo "$MPI_RUN_CMD $APP_CMD" >> $LOGFILE + if [ x"$MONITOR_FILE" = x ] + then + # simple run, nothing to monitor + set -x + $MPI_RUN_CMD $APP_CMD 2>&1|tee -i -a $LOGFILE + res=$? + set +x + else + # run both a tail and app so we can see the results while it runs and + # stop the tail when app finishes + ( $MPI_RUN_CMD $APP_CMD 2>&1|tee -i -a $LOGFILE ) & + pid=$! + set +x + echo "$pid" > pid + tail -f $MONITOR_FILE & + tail=$! + while true + do + if kill -s SIGCONT $pid >/dev/null 2>&1 # see if pid still running + then + sleep 10 + else + break + fi + done + kill -9 $tail + wait $pid + res=$? + if [ $res = 127 ] + then + echo "Unable to get exit status of application" + res=0 + fi + wait + fi + # check for both exit status and typical app failure messages + if [ ! $res ] || cat $LOGFILE $MONITOR_FILE| egrep 'ERROR|disconnect|truncated|IRECV|STOP|FAIL' + then + echo " $APP FAILED!! See log file" + break + fi + if [ $loop = y ] + then + echo "########################################### " >> $LOGFILE + # uncomment this if global id is part of MVICH-DBG filename + #rm -f MVICH-DBG.* + #opacmdall -p -f ff.hosts -u `whoami` "cd $PWD;"'rm -f MVICH-DBG.*' > /dev/null 2>&1 + sleep 5 # a little delay so user could cntl-C us + else + break + fi +done + +echo " Copying files to $dir..." +cp MVICH-DBG.* core.* $OUTPUT_FILES $MONITOR_FILE $dir + +# fetch host stats +echo " Fetching host stats..." +opacmdall -p -f ff.hosts -u `whoami` "opainfo -o stats > $OPASTATS_FILE 2>/dev/null" > /dev/null +opauploadall -p -f ff.hosts -u `whoami` -d $dir $OPASTATS_FILE opastats-after > /dev/null +opacmdall -p -f ff.hosts -u `whoami` "rm -f $OPASTATS_FILE" > /dev/null + +# fetch switch stats +echo " Fetching switch stats..." +opacmdall -C $chassis_arg "ismPortStats -noprompt" > $dir/switch_stats-after +#echo " Fetching fabric errors..." +#iba_report -o errors > $dir/iba_report_errors + +echo " Fetching debug and core to $dir..." +opacmdall -p -f ff.hosts -u `whoami` "cd $PWD;"'rm -f debug.tgz; tar cfz debug.tgz MVICH-DBG.* core.*' > /dev/null 2>/dev/null +opauploadall -p -f ff.hosts -u `whoami` -d $dir $PWD/debug.tgz debug.tgz > /dev/null 2>/dev/null +rm -f pid curtime app ff.hosts diff --git a/MpiApps/apps/run_batch_cabletest b/MpiApps/apps/run_batch_cabletest new file mode 100755 index 0000000..e2039e7 --- /dev/null +++ b/MpiApps/apps/run_batch_cabletest @@ -0,0 +1,149 @@ +#!/bin/bash +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2018, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] + +temp1="$(mktemp)" +temp2="$(mktemp)" +tmpdir=$PWD/tmp + +trap "rm -f $temp1 $temp2; exit 1" SIGHUP SIGTERM SIGINT +trap "rm -f $temp1 $temp2" EXIT + +BATCH_SIZE=${BATCH_SIZE:-24} # now many hosts per mpi job + +# build the mpi_group_hosts file and start HCA-SW cable tests as a series +# of small BATCH_SIZE node jobs. This approach limits the impact should a few hosts +# crash and also allows for quicker job startup. + +# jobs are nohup'ed so they can run for long duration in the background + +Usage() { + echo "Usage: ./run_batch_cabletest [-v] [-n numprocs] [duration [minmsg [maxmsg]]]" >&2 + echo " or" >&2 + echo " ./run_batch_cabletest --help" >&2 + echo " -v - verbose mode. Additional output generated to nohup files" >&2 + echo " -n numprocs - number of processes per host (default 3)" >&2 + echo " duration - how many minutes to run. Can be 'infinite'. Default is 60" >&2 + echo " minmsg - smallest message to use. Must be between 16384 and 4194304." >&2 + echo " maxmsg - largest message to use. Must be between 16384 and 4194304." >&2 + echo " Default minmsg and maxmsg is 4 Megabytes" >&2 + echo >&2 + echo " This will build a set of mpi_hosts.# and mpi_group_hosts.# files with no" >&2 + echo " more than BATCH_SIZE hosts each. If an odd number of hosts appear in" >&2 + echo " mpi_hosts, the last one is skipped" >&2 + echo " Each run_cabletest MPI job will have its output saved to a corresponding" >&2 + echo " ./tmp/nohup.#.out file" >&2 + echo "Environment:" >&2 + echo " MPI_HOSTS - mpi_hosts file to use, default is mpi_hosts" >&2 + echo " This should list hosts in topology order, 1 entry per host" >&2 + echo " hosts will be paired sequentially (1st & 2nd, 3rd & 4th, ...)" >&2 + echo " BATCH_SIZE - maximum hosts per MPI job, default is 18, must be even" >&2 + echo "Examples:" >&2 + echo " ./run_batch_cabletest" >&2 + echo " MPI_HOSTS=good ./run_batch_cabletest 1440" >&2 + echo " BATCH_SIZE=16 MPI_HOSTS=good ./run_batch_cabletest infinite" >&2 + exit 2 +} + +if [ x"$1" = x"--help" ] +then + Usage +fi +numprocs= +vopt= +while getopts vn: param +do + case $param in + v) vopt="-v";; + n) numprocs="$OPTARG";; + *) Usage;; + esac +done +shift $((OPTIND-1)) + +export MPI_HOSTS=${MPI_HOSTS:-mpi_hosts} +if [ ! -e $MPI_HOSTS ] +then + echo "MPI_HOSTS='$MPI_HOSTS': Not Found" >&2 + Usage +fi + +if ! [ $BATCH_SIZE -gt 0 ] 2>/dev/null +then + echo "Invalid BATCH_SIZE='$BATCH_SIZE': must be an even number >= 2" >&2 + Usage +fi +if [ $(($BATCH_SIZE % 2)) -eq 1 ] +then + echo "Invalid BATCH_SIZE='$BATCH_SIZE': must be an even number" >&2 + Usage +fi + +# ignore blank and comment lines in mpi_hosts +cat $MPI_HOSTS|egrep -v '^[[:space:]]*#'|egrep -v '^[[:space:]]*$' > $temp1 +echo "Starting HFI-SW cabletests using $MPI_HOSTS: $(cat $temp1|wc -l) hosts" +echo " Max batch size $BATCH_SIZE" + +#set -x +mkdir -p $tmpdir +loop=1 +while [ $(cat $temp1|wc -l) -gt 1 ] +do + head -$BATCH_SIZE $temp1 > $tmpdir/mpi_hosts.$loop + if [ $(($(cat $tmpdir/mpi_hosts.$loop|wc -l) % 2)) -eq 1 ] + then + # need an even number, drop the last one + echo "Skipping odd host:" `tail -1 $temp1` + head -$(($(cat $temp1|wc -l) - 1)) $temp1 > $tmpdir/mpi_hosts.$loop + fi + tail -n +$(($BATCH_SIZE + 1)) $temp1 > $temp2; mv $temp2 $temp1 + echo "starting cabletest $loop on $(cat $tmpdir/mpi_hosts.$loop|wc -l) hosts" + export MPI_HOSTS=$tmpdir/mpi_hosts.$loop + export MPI_GROUP_HOSTS=$tmpdir/mpi_group_hosts.$loop + export LOGSUFFIX=".$loop" + ./gen_group_hosts > /dev/null < $tmpdir/nohup.$loop.out 2>&1 & + loop=$(($loop + 1)) + #echo "Enter to Continue" + #read trash +done + +if [ $(cat $temp1|wc -l) -gt 0 ] +then + echo "Skipping odd host:" `cat $temp1` +fi +rm -f $temp1 $temp2 + +echo "Started $(($loop - 1 )) MPI cabletest jobs" diff --git a/MpiApps/apps/run_batch_script b/MpiApps/apps/run_batch_script new file mode 100755 index 0000000..4653b03 --- /dev/null +++ b/MpiApps/apps/run_batch_script @@ -0,0 +1,179 @@ +#!/bin/bash +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] + +temp1="$(mktemp)" +temp2="$(mktemp)" +tmpdir=$PWD/tmp + +trap "rm -f $temp1 $temp2; exit 1" SIGHUP SIGTERM SIGINT +trap "rm -f $temp1 $temp2" EXIT + +BATCH_SIZE=${BATCH_SIZE:-18} # now many hosts per mpi job +MIN_BATCH_SIZE=${MIN_BATCH_SIZE:-2} # now many hosts per mpi job + +# start the given run_* script as a series of small BATCH_SIZE node jobs. +# This approach limits the impact should a few hosts +# crash and also allows for quicker job startup. + +# jobs are nohup'ed so they can run for long duration in the background + +Usage() { + echo "Usage: ./run_batch_script [-e] run_script [args]" >&2 + echo " or" >&2 + echo " ./run_batch_script --help" >&2 + echo " -e - force an even number of hosts in final batch by skipping the last one" >&2 + echo " run_script - a run_* script from this directory" >&2 + echo " args - arguments for the run_script" >&2 + echo " if the 1st arg is 'NP' it will be replaced with the process count" >&2 + echo >&2 + echo " This will build a set of mpi_hosts.# files with no" >&2 + echo " more than BATCH_SIZE hosts each. If -e is specified and an odd number of" >&2 + echo " hosts appear in mpi_hosts, the last one is skipped" >&2 + echo " Each run_script MPI job will have its output saved to a corresponding" >&2 + echo " ./tmp/nohup.#.out file" >&2 + echo >&2 + echo " This may only used for scripts which do use MPI_HOSTS." >&2 + echo " To run run_cabletest use run_batch_cabletest" >&2 + echo "Environment:" >&2 + echo " MPI_HOSTS - mpi_hosts file to use, default is mpi_hosts" >&2 + echo " BATCH_SIZE - max hosts per MPI job, default is 18, if -e must be even" >&2 + echo " MIN_BATCH_SIZE - min hosts per MPI job, default is 2, if -e must be even" >&2 + echo "Examples:" >&2 + echo " ./run_batch_script run_deviation NP ff" >&2 + echo " BATCH_SIZE=2 MPI_HOSTS=good ./run_batch_script run_lat2" >&2 + echo " BATCH_SIZE=16 MPI_HOSTS=good ./run_batch_script run_deviation ff" >&2 + echo " MIN_BATCH_SIZE=16 BATCH_SIZE=16 ./run_batch_script run_hpl2 16" >&2 + exit 2 +} + +if [ x"$1" = x"--help" ] +then + Usage +fi + +even=n +if [ x"$1" = x"-e" ] +then + even=y + shift +fi + +if [ $# -lt 1 ] +then + Usage +fi +script=$1 +shift + +if [ $(basename $script) = 'run_cabletest' ] +then + echo "To execute run_cabletest use run_batch_cabletest instead" >&2 + exit 1 +fi + +np=n +if [ x"$1" = x"NP" ] +then + np=y + shift +fi + + +export MPI_HOSTS=${MPI_HOSTS:-mpi_hosts} +if [ ! -e $MPI_HOSTS ] +then + echo "MPI_HOSTS='$MPI_HOSTS': Not Found" >&2 + Usage +fi + +if ! [ $BATCH_SIZE -gt 0 ] 2>/dev/null +then + echo "Invalid BATCH_SIZE='$BATCH_SIZE': must be a number > 0" >&2 + Usage +fi +if [ $even = y -a $(($BATCH_SIZE % 2)) -eq 1 ] +then + echo "Invalid BATCH_SIZE='$BATCH_SIZE': must be an even number" >&2 + Usage +fi +if ! [ $MIN_BATCH_SIZE -gt 0 ] 2>/dev/null +then + echo "Invalid MIN_BATCH_SIZE='$MIN_BATCH_SIZE': must be a number > 0" >&2 + Usage +fi +if [ $even = y -a $(($MIN_BATCH_SIZE % 2)) -eq 1 ] +then + echo "Invalid MIN_BATCH_SIZE='$MIN_BATCH_SIZE': must be an even number" >&2 + Usage +fi +if [ $MIN_BATCH_SIZE -gt $BATCH_SIZE ] 2>/dev/null +then + echo "Invalid MIN_BATCH_SIZE='$MIN_BATCH_SIZE': must be < BATCH_SIZE of $BATCH_SIZE" >&2 + Usage +fi + +# ignore blank and comment lines in mpi_hosts +cat $MPI_HOSTS|egrep -v '^[[:space:]]*#'|egrep -v '^[[:space:]]*$' > $temp1 +echo "Starting $script jobs using $MPI_HOSTS: $(cat $temp1|wc -l) hosts" +echo " Max batch size $BATCH_SIZE, Min batch size $MIN_BATCH_SIZE" + +#set -x +mkdir -p $tmpdir +loop=1 +while [ $(cat $temp1|wc -l) -ge $MIN_BATCH_SIZE ] +do + head -$BATCH_SIZE $temp1 > $tmpdir/mpi_hosts.$loop + if [ $even = y -a $(($(cat $tmpdir/mpi_hosts.$loop|wc -l) % 2)) -eq 1 ] + then + # need an even number, drop the last one + echo "Skipping odd host:" `tail -1 $temp1` + head -$(($(cat $temp1|wc -l) - 1)) $temp1 > $tmpdir/mpi_hosts.$loop + fi + tail -n +$(($BATCH_SIZE + 1)) $temp1 > $temp2; mv $temp2 $temp1 + NP=$(cat $tmpdir/mpi_hosts.$loop|wc -l) + echo "starting $script job $loop on $NP hosts" + [ $np = n ] && NP= # don't insert process count + export MPI_HOSTS=$tmpdir/mpi_hosts.$loop + export LOGSUFFIX=".$loop" + nohup ./$script $NP "$@" > $tmpdir/nohup.$loop.out 2>&1 & + loop=$(($loop + 1)) + #echo "Enter to Continue" + #read trash +done + +if [ $(cat $temp1|wc -l) -gt 0 ] +then + echo "Skipping odd hosts:" `cat $temp1` +fi +rm -f $temp1 $temp2 + +echo "Started $(($loop - 1 )) MPI $script jobs" diff --git a/MpiApps/apps/run_bcast2 b/MpiApps/apps/run_bcast2 new file mode 100755 index 0000000..a547adf --- /dev/null +++ b/MpiApps/apps/run_bcast2 @@ -0,0 +1,64 @@ +#!/bin/sh +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] + +# BASE PATH TO MPI EXECUTABLES: To use an alternate location, +# either edit this line or set MPICH_PREFIX in your environment. +# see select_mpi for the set of default MPI selections +# default to MPI used for build +MPICH_PREFIX=${MPICH_PREFIX:-`cat .prefix 2>/dev/null`} + +trap "exit 1" SIGHUP SIGTERM SIGINT + +if [ -z "$1" ] +then + echo " Usage: run_bcast2 number_processes" + echo " For example: ./run_bcast2 2" + echo "number_processes may be 'all' in which case one rank will be started for" + echo "every process in the mpi_hosts file" + exit 1 +fi + +NUM_PROCESSES=$1 +APP=osu_bcast +LOGFILE= +. ./prepare_run + +CMD="osu2/osu_bcast" + +( + echo " Running Broadcast ..." + show_mpi_hosts + set -x + $MPI_RUN_CMD $CMD + set +x +) 2>&1 | tee -i -a $LOGFILE +echo "########################################### " >> $LOGFILE diff --git a/MpiApps/apps/run_bcast3 b/MpiApps/apps/run_bcast3 new file mode 100755 index 0000000..f64a5b6 --- /dev/null +++ b/MpiApps/apps/run_bcast3 @@ -0,0 +1,64 @@ +#!/bin/sh +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] + +# BASE PATH TO MPI EXECUTABLES: To use an alternate location, +# either edit this line or set MPICH_PREFIX in your environment. +# see select_mpi for the set of default MPI selections +# default to MPI used for build +MPICH_PREFIX=${MPICH_PREFIX:-`cat .prefix 2>/dev/null`} + +trap "exit 1" SIGHUP SIGTERM SIGINT + +if [ -z "$1" ] +then + echo " Usage: run_bcast3 number_processes" + echo " For example: ./run_bcast3 2" + echo "number_processes may be 'all' in which case one rank will be started for" + echo "every process in the mpi_hosts file" + exit 1 +fi + +NUM_PROCESSES=$1 +APP=osu_bcast +LOGFILE= +. ./prepare_run + +CMD="osu-micro-benchmarks-3.8-July12/mpi/collective/osu_bcast" + +( + echo " Running Broadcast 3.8 ..." + show_mpi_hosts + set -x + $MPI_RUN_CMD $CMD + set +x +) 2>&1 | tee -i -a $LOGFILE +echo "########################################### " >> $LOGFILE diff --git a/MpiApps/apps/run_bibw2 b/MpiApps/apps/run_bibw2 new file mode 100755 index 0000000..87922ce --- /dev/null +++ b/MpiApps/apps/run_bibw2 @@ -0,0 +1,56 @@ +#!/bin/sh +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] + +# BASE PATH TO MPI EXECUTABLES: To use an alternate location, +# either edit this line or set MPICH_PREFIX in your environment. +# see select_mpi for the set of default MPI selections +# default to MPI used for build +MPICH_PREFIX=${MPICH_PREFIX:-`cat .prefix 2>/dev/null`} + +trap "exit 1" SIGHUP SIGTERM SIGINT + +NUM_PROCESSES=2 +APP=osu_bibw +LOGFILE= +. ./prepare_run + +CMD="osu2/osu_bibw" + +( + echo " Running BiDir Bandwidth 2 ..." + show_mpi_hosts + set -x + $MPI_RUN_CMD $CMD + set +x +) 2>&1 | tee -i -a $LOGFILE + +echo "########################################### " >> $LOGFILE diff --git a/MpiApps/apps/run_bibw3 b/MpiApps/apps/run_bibw3 new file mode 100755 index 0000000..f60c2b2 --- /dev/null +++ b/MpiApps/apps/run_bibw3 @@ -0,0 +1,56 @@ +#!/bin/sh +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] + +# BASE PATH TO MPI EXECUTABLES: To use an alternate location, +# either edit this line or set MPICH_PREFIX in your environment. +# see select_mpi for the set of default MPI selections +# default to MPI used for build +MPICH_PREFIX=${MPICH_PREFIX:-`cat .prefix 2>/dev/null`} + +trap "exit 1" SIGHUP SIGTERM SIGINT + +NUM_PROCESSES=2 +APP=osu_bibw +LOGFILE= +. ./prepare_run + +CMD="osu-micro-benchmarks-3.8-July12/mpi/pt2pt/osu_bibw" + +( + echo " Running BiDir Bandwidth 3.8 ..." + show_mpi_hosts + set -x + $MPI_RUN_CMD $CMD + set +x +) 2>&1 | tee -i -a $LOGFILE + +echo "########################################### " >> $LOGFILE diff --git a/MpiApps/apps/run_bw b/MpiApps/apps/run_bw new file mode 100755 index 0000000..a714380 --- /dev/null +++ b/MpiApps/apps/run_bw @@ -0,0 +1,97 @@ +#!/bin/sh +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] + +# BASE PATH TO MPI EXECUTABLES: To use an alternate location, +# either edit this line or set MPICH_PREFIX in your environment. +# see select_mpi for the set of default MPI selections +# default to MPI used for build +MPICH_PREFIX=${MPICH_PREFIX:-`cat .prefix 2>/dev/null`} + +trap "exit 1" SIGHUP SIGTERM SIGINT + +all=n +if [ -z $1 ] +then + echo " Setting the default Maximum Message Size to 4194304" + MAX_SIZE=4194304 + mult=4 + size=4096 +elif [ "$1" = full ] +then + MAX_SIZE=4194304 + mult=2 + size=1024 +elif [ "$1" = all ] +then + MAX_SIZE=`expr 128 \* 1024` + all=y + mult=0 + size=0 + if [ -z $2 ] + then + inc=10 + else + inc=$2 + fi +else + MAX_SIZE=$1 + mult=4 + size=4096 +fi + +NUM_PROCESSES=2 +APP=bw +LOGFILE= +. ./prepare_run + +BANDWIDTH_CMD="bandwidth/bw 400" + +echo " Running Bandwidth ..." | tee -a $LOGFILE +show_mpi_hosts | tee -a $LOGFILE +echo " Using: $MPI_RUN_CMD $BANDWIDTH_CMD SIZE" >> $LOGFILE +while [ "$size" -le "$MAX_SIZE" ] +do + if [ $all != y ] + then + echo " Running Bandwith for size $size" + fi + set -x + $MPI_RUN_CMD $BANDWIDTH_CMD $size 2>&1|tee -i -a $LOGFILE + set +x + if [ $all = y ] + then + size=`expr $size + $inc` + else + size=`expr $size \* $mult` + fi +done +echo "########################################### " >> $LOGFILE diff --git a/MpiApps/apps/run_bw2 b/MpiApps/apps/run_bw2 new file mode 100755 index 0000000..dd6b821 --- /dev/null +++ b/MpiApps/apps/run_bw2 @@ -0,0 +1,56 @@ +#!/bin/sh +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] + +# BASE PATH TO MPI EXECUTABLES: To use an alternate location, +# either edit this line or set MPICH_PREFIX in your environment. +# see select_mpi for the set of default MPI selections +# default to MPI used for build +MPICH_PREFIX=${MPICH_PREFIX:-`cat .prefix 2>/dev/null`} + +trap "exit 1" SIGHUP SIGTERM SIGINT + +NUM_PROCESSES=2 +APP=osu_bw +LOGFILE= +. ./prepare_run + +CMD="osu2/osu_bw" + +( + echo " Running Bandwidth 2 ..." + show_mpi_hosts + set -x + $MPI_RUN_CMD $CMD + set +x +) 2>&1 | tee -i -a $LOGFILE + +echo "########################################### " >> $LOGFILE diff --git a/MpiApps/apps/run_bw3 b/MpiApps/apps/run_bw3 new file mode 100755 index 0000000..e75927e --- /dev/null +++ b/MpiApps/apps/run_bw3 @@ -0,0 +1,56 @@ +#!/bin/sh +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] + +# BASE PATH TO MPI EXECUTABLES: To use an alternate location, +# either edit this line or set MPICH_PREFIX in your environment. +# see select_mpi for the set of default MPI selections +# default to MPI used for build +MPICH_PREFIX=${MPICH_PREFIX:-`cat .prefix 2>/dev/null`} + +trap "exit 1" SIGHUP SIGTERM SIGINT + +NUM_PROCESSES=2 +APP=osu_bw +LOGFILE= +. ./prepare_run + +CMD="osu-micro-benchmarks-3.8-July12/mpi/pt2pt/osu_bw" + +( + echo " Running Bandwidth 3.8 ..." + show_mpi_hosts + set -x + $MPI_RUN_CMD $CMD + set +x +) 2>&1 | tee -i -a $LOGFILE + +echo "########################################### " >> $LOGFILE diff --git a/MpiApps/apps/run_cabletest b/MpiApps/apps/run_cabletest new file mode 100755 index 0000000..aadd8fd --- /dev/null +++ b/MpiApps/apps/run_cabletest @@ -0,0 +1,179 @@ +#!/bin/sh +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] + +# BASE PATH TO MPI EXECUTABLES: To use an alternate location, +# either edit this line or set MPICH_PREFIX in your environment. +# see select_mpi for the set of default MPI selections +# default to MPI used for build +MPICH_PREFIX=${MPICH_PREFIX:-`cat .prefix 2>/dev/null`} + +trap "exit 1" SIGHUP SIGTERM SIGINT + +APP=mpi_groupstress +LOGFILE= + +MPI_GROUP_HOSTS=${MPI_GROUP_HOSTS:-$PWD/mpi_group_hosts} +if [ $(echo $MPI_GROUP_HOSTS|cut -c1) != '/' ] +then + MPI_GROUP_HOSTS="$PWD/$MPI_GROUP_HOSTS" +fi + +MINUTES=60 +MINSIZE=4194304 +MAXSIZE=4194304 +VERBOSE= + +usage() { + echo + echo "$0 is a specialized stress test for large fabrics. It groups" + echo "MPI ranks into sets which are tested against other members of the set." + echo + echo "This has no real value as a performance benchmark but is" + echo "extremely useful for checking for cabling problems in the fabric." + echo + echo "$0 requires no arguments, but does require the user to generate a" + echo "group hosts file. This is done with the gen_group_hosts script." + echo "The name of the group hosts file is specified by the MPI_GROUP_HOSTS" + echo "variable, and defaults to \"mpi_group_hosts\"." + echo + echo "By default, run_cabletest will run for 60 minutes, and uses 4" + echo "megabyte messages, but these settings can be changed by using the" + echo "three optional arguments: duration, smallest message size, and " + echo "largest message size. The arguments are specified in order:" + echo + echo "$0 dd ss ll" + echo + echo "Where dd is the duration in minutes, ss is the smallest message" + echo "size and ll is the largest message size." + echo + echo "For example, to run a one minute test, with 4 megabyte messages:" + echo + echo "$0 1" + echo + echo "Once 1 minute has elapsed, the test will complete when the current" + echo "round of testing completes." + echo + echo "If you want the tests to repeat indefinitely, use 'infinite' as" + echo "the duration:" + echo + echo "$0 infinite" + echo + echo "In addition to the duration, you can specify" + echo "the smallest and largest messages to send." + echo "Messages must be between 16384 and 4194304 (4 megabytes)." + echo "This example will test message sizes between 1 and 4" + echo "megabytes, and will run for 24 hours:" + echo + echo "$0 1440 1048576 4194304" + echo + echo "Finally, there are two optional arguments, -h and -v." + echo + echo "-h (--help) provides this help text." + echo "-v (--verbose) runs the test in a verbose mode that shows you how" + echo " the nodes were grouped." + exit +} + +ARGS=`getopt --name=$0 -o "hv" -l "help,verbose" -- $@` +if [ $? -ne 0 ]; then + usage +fi +eval set -- $ARGS +while [ $1 != -- ]; do + case $1 in + -h|--help) + usage + shift;; + -v|--verbose) + VERBOSE="-v" + shift;; + esac +done +shift # remove the -- + +if [ ! -f "$MPI_GROUP_HOSTS" ] +then + echo "Could not find the group hosts file \"$MPI_GROUP_HOSTS\"." + echo "Please use ./gen_group_hosts before using this" + echo "application." + exit +fi + +# skip comment and blank lines +NUM_PROCESSES=$(cat $MPI_GROUP_HOSTS|egrep -v '^[[:space:]]*#'|egrep -v '^[[:space:]]*$'|wc -l) +MIN_PROCESSES=2 +MULT_PROCESSES=2 +HEADER=`head -1 $MPI_GROUP_HOSTS | sed -e 's/# DO NOT DELETE THIS LINE: //'` +GROUP_SIZE=`echo $HEADER | cut -d\ -f1` +PROCS_PER_NODE=`echo $HEADER | cut -d\ -f2` +GROUP_SIZE=$((GROUP_SIZE * PROCS_PER_NODE)) +export MPI_HOSTS=$MPI_GROUP_HOSTS + +if [ $# -ge 1 ] ; then + if [ $1 = "infinite" ]; then + MINUTES=0 + elif [ $1 -eq $1 ]; then + MINUTES=$1 + else + usage + fi +fi +shift +if [ $# -ge 1 ]; then + if [ $1 -eq $1 ]; then + MINSIZE=$1 + else + usage + fi +fi +shift +if [ $# -ge 1 ]; then + if [ $1 -eq $1 ]; then + MAXSIZE=$1 + else + usage + fi +fi + +. ./prepare_run + +CMD="groupstress/mpi_groupstress -g $GROUP_SIZE -t $MINUTES -l $MINSIZE -u $MAXSIZE $VERBOSE" + +( + echo " Running $APP ..." + show_mpi_hosts + set -x + $MPI_RUN_CMD $CMD + set +x +) 2>&1 | tee -i -a $LOGFILE + +echo "########################################### " >> $LOGFILE diff --git a/MpiApps/apps/run_deviation b/MpiApps/apps/run_deviation new file mode 100755 index 0000000..61e7003 --- /dev/null +++ b/MpiApps/apps/run_deviation @@ -0,0 +1,154 @@ +#!/bin/sh +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] + +# BASE PATH TO MPI EXECUTABLES: To use an alternate location, +# either edit this line or set MPICH_PREFIX in your environment. +# see select_mpi for the set of default MPI selections +# default to MPI used for build +MPICH_PREFIX=${MPICH_PREFIX:-`cat .prefix 2>/dev/null`} + +trap "exit 1" SIGHUP SIGTERM SIGINT + +bwtol=20 +lattol=50 + +Usage() +{ + echo "Usage: run_deviation number_processes ['ff' | bwtol lattol]" >&2 + echo " [other deviation arguments]" >&2 + echo " number_processes may be 'all' in which case one rank will be started for" + echo " every process in the mpi_hosts file" + echo " 'ff' When specified, the configured FF_DEVIATION_ARGS will be used" >&2 + echo " bwtol Percent of bandwidth degradation allowed below Avg value" >&2 + echo " lattol Percent of latency degradation allowed above Avg value" >&2 + echo >&2 + echo "Other deviation arguments:" >&2 + echo " [-bwdelta MBs] [-bwthres MBs] [-bwloop count] [-bwsize size]" >&2 + echo " [-bwbidir|-bwunidir]" >&2 + echo " [-latdelta usec] [-latthres usec] [-latloop count] [-latsize size]" >&2 + echo " [-c] [-b] [-v] [-vv] [-h reference_host]" >&2 + echo " -bwdelta Limit in MB/s of bandwidth degradation allowed below Avg value" >&2 + echo " -bwthres Lower Limit in MB/s of bandwidth allowed" >&2 + echo " -bwloop Number of loops to execute each bandwidth test" >&2 + echo " -bwsize Size of message to use for bandwidth test" >&2 + echo " -bwbidir Perform a bidirectional bandwidth test" >&2 + echo " -bwunidir Perform a unidirectional bandwidth test (default)" >&2 + echo " -latdelta Limit in usec of latency degradation allowed above Avg value" >&2 + echo " -latthres Upper Limit in usec of latency allowed" >&2 + echo " -latloop Number of loops to execute each latency test" >&2 + echo " -latsize Size of message to use for latency test" >&2 + echo " -c Run test pairs concurrently instead of the default of sequential" >&2 + echo " -b When comparing results against tolerance and delta use best" >&2 + echo " instead of Avg" >&2 + echo " -v verbose output" >&2 + echo " -vv Very verbose output" >&2 + echo " -h Baseline host to use for sequential pairing" >&2 + echo "Both bwtol and bwdelta must be exceeded to fail bandwidth test" >&2 + echo "When bwthres is supplied, bwtol and bwdelta are ignored" >&2 + echo "Both lattol and latdelta must be exceeded to fail latency test" >&2 + echo "When latthres is supplied, lattol and latdelta are ignored" >&2 + echo >&2 + echo "For consistency with OSU benchmarks MB/s is defined as 1000000 bytes/s" >&2 + echo >&2 + echo "Examples:" >&2 + echo " ./run_deviation 20 ff" >&2 + echo " ./run_deviation 20 ff -v" >&2 + echo " ./run_deviation 20 20 50 -c" >&2 + echo " ./run_deviation 20 '' '' -c -v -bwthres 1200.5 -latthres 3.5" >&2 + echo " ./run_deviation 20 20 50 -c -h compute0001" >&2 + echo " ./run_deviation 20 0 0 -bwdelta 200 -latdelta 0.5" >&2 + exit 2 +} + +if [ -z "$1" ] +then + Usage +else + NUM_PROCESSES=$1 + shift +fi + +other_args= +if [ x"$1" = x"ff" ] +then + if [ ! -f /usr/lib/opa/tools/ff_funcs ] + then + echo "run_deviation: 'ff' argument requires that FastFabric is installed on this host" >&2 + Usage + fi + # get other arguments from opafastfabric config + # optional override of defaults + if [ -f /etc/opa/opafastfabric.conf ] + then + . /etc/opa/opafastfabric.conf + fi + + . /usr/lib/opa/tools/opafastfabric.conf.def + + other_args="$FF_DEVIATION_ARGS" + shift +else + if [ -z $1 ] + then + echo " Setting the default bandwidth tolerance to 20%" + bwtol=20 + else + bwtol=$1 + fi + shift + + if [ -z $1 ] + then + echo " Setting the default latency tolerance to 50%" + lattol=50 + else + lattol=$1 + fi + shift + + other_args="-bwtol $bwtol -lattol $lattol" +fi + +CMD="deviation/deviation $other_args $@" + +APP=deviation +LOGFILE= +. ./prepare_run + +( + echo " Running Deviation ..." + show_mpi_hosts + set -x + $MPI_RUN_CMD $CMD + set +x +) 2>&1 | tee -i -a $LOGFILE +echo "########################################### " >> $LOGFILE diff --git a/MpiApps/apps/run_hpl2 b/MpiApps/apps/run_hpl2 new file mode 100755 index 0000000..a238a73 --- /dev/null +++ b/MpiApps/apps/run_hpl2 @@ -0,0 +1,74 @@ +#!/bin/sh +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] + +# BASE PATH TO MPI EXECUTABLES: To use an alternate location, +# either edit this line or set MPICH_PREFIX in your environment. +# see select_mpi for the set of default MPI selections +# default to MPI used for build +MPICH_PREFIX=${MPICH_PREFIX:-`cat .prefix 2>/dev/null`} + +trap "exit 1" SIGHUP SIGTERM SIGINT + +if [ -z "$1" ] +then + echo " Usage: run_hpl number_processes" + echo " For example: ./run_hpl2 2" + echo "number_processes may be 'all' in which case one rank will be started for" + echo "every process in the mpi_hosts file" + exit 1 +fi + +NUM_PROCESSES=$1 +APP=xhpl2 +LOGFILE= +. ./prepare_run + +CC=`./get_mpi_cc.sh` +ARCH=`uname -s` +HPL_DIR="${PWD}/hpl-2.2/bin/ICS.${ARCH}.${CC}" +HPL_CMD="./xhpl" + +if [ $USING_MPD = y ] +then + MPI_RUN_CMD_HPL="$MPI_RUN_CMD -wdir $HPL_DIR" +else + MPI_RUN_CMD_HPL="$MPI_RUN_CMD" +fi + +( + echo " Running High Performance Computing Linkpack Benchmark (HPL) ..." + show_mpi_hosts + set -x + cd $HPL_DIR; $MPI_RUN_CMD_HPL $HPL_CMD + set +x +) 2>&1 | tee -i -a $LOGFILE +echo "########################################### " >> $LOGFILE diff --git a/MpiApps/apps/run_imb b/MpiApps/apps/run_imb new file mode 100755 index 0000000..135122c --- /dev/null +++ b/MpiApps/apps/run_imb @@ -0,0 +1,79 @@ +#!/bin/sh +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] + +# BASE PATH TO MPI EXECUTABLES: To use an alternate location, +# either edit this line or set MPICH_PREFIX in your environment. +# see select_mpi for the set of default MPI selections +# default to MPI used for build +MPICH_PREFIX=${MPICH_PREFIX:-`cat .prefix 2>/dev/null`} + +trap "exit 1" SIGHUP SIGTERM SIGINT + +if [ -z "$1" ] +then + echo " Usage: run_imb number_processes" + echo " For example: ./run_imb 2" + echo "number_processes may be 'all' in which case one rank will be started for" + echo "every process in the mpi_hosts file" + exit 1 +fi + +NUM_PROCESSES=$1 +APP=IMB-MPI1 +LOGFILE= +. ./prepare_run + +IMB_CMD=$MPICH_PREFIX/tests/IMB-4.0/IMB-MPI1 +if [ ! -x $IMB_CMD ] +then + echo " $IMB_CMD: Not Found" + exit 1 +fi + +# to run a reduced suite of tests, uncomment a different one of these lines +# full list of tests +CMD="$IMB_CMD" +#CMD="$IMB_CMD Bcast Barrier AllReduce Reduce exchange reduce_scatter pingping pingpong sendrecv alltoall allgather allgatherv" +# avoid allgather and alltoall, too much memory needed +#CMD="$IMB_CMD Bcast Barrier AllReduce Reduce exchange reduce_scatter pingping pingpong sendrecv" +#CMD="$IMB_CMD Bcast Barrier AllReduce Reduce" +#CMD="$IMB_CMD Bcast Barrier" +#CMD="$IMB_CMD Barrier" + +( + echo " Running Intel MPI Benchmark suite ..." + show_mpi_hosts + set -x + $MPI_RUN_CMD $CMD + set +x +) 2>&1 | tee -i -a $LOGFILE +echo "########################################### " >> $LOGFILE diff --git a/MpiApps/apps/run_lat b/MpiApps/apps/run_lat new file mode 100755 index 0000000..d97c2ae --- /dev/null +++ b/MpiApps/apps/run_lat @@ -0,0 +1,119 @@ +#!/bin/sh +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] + +# BASE PATH TO MPI EXECUTABLES: To use an alternate location, +# either edit this line or set MPICH_PREFIX in your environment. +# see select_mpi for the set of default MPI selections +# default to MPI used for build +MPICH_PREFIX=${MPICH_PREFIX:-`cat .prefix 2>/dev/null`} + +trap "exit 1" SIGHUP SIGTERM SIGINT + +full=n +all=n +size=1 +if [ -z $1 ] +then + echo " Setting the default Maximum Message Size to 1000" + MAX_SIZE=1000 + mult=4 +elif [ "$1" = full ] +then + MAX_SIZE=4194304 + full=y + mult=2 + size=0 +elif [ "$1" = all ] +then + MAX_SIZE=`expr 128 \* 1024` + all=y + mult=0 + size=0 + if [ -z $2 ] + then + inc=10 + else + inc=$2 + fi +else + MAX_SIZE=$1 + mult=4 +fi + +NUM_PROCESSES=2 +APP=latency +LOGFILE= +. ./prepare_run + +loops=10000 +LATENCY_CMD="latency/latency" + +echo " Running Latency ..." | tee -a $LOGFILE +show_mpi_hosts | tee -a $LOGFILE +echo " Using: $MPI_RUN_CMD $LATENCY_CMD LOOPS SIZE" >> $LOGFILE +while [ "$size" -le "$MAX_SIZE" ] +do + if [ $all != y ] + then + echo " Running Latency for size $size" + fi + set -x + $MPI_RUN_CMD $LATENCY_CMD $loops $size 2>&1|tee -i -a $LOGFILE + set +x + + if [ $all = y ] + then + size=`expr $size + $inc` + elif [ $full = y -a $size -lt 8 ] + then + size=`expr $size + 1` + else + size=`expr $size \* $mult` + fi + + if [ $size -lt 100 ] + then + loops=10000 + elif [ $size -lt 1024 ] + then + loops=7000 + elif [ $size -lt 2048 ] + then + loops=5000 + elif [ $size -lt 1000000 ] + then + loops=1000 + else + loops=20 + fi +done +echo "########################################### " >> $LOGFILE diff --git a/MpiApps/apps/run_lat2 b/MpiApps/apps/run_lat2 new file mode 100755 index 0000000..2003bbc --- /dev/null +++ b/MpiApps/apps/run_lat2 @@ -0,0 +1,57 @@ +#!/bin/sh +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] + +# BASE PATH TO MPI EXECUTABLES: To use an alternate location, +# either edit this line or set MPICH_PREFIX in your environment. +# see select_mpi for the set of default MPI selections +# default to MPI used for build +MPICH_PREFIX=${MPICH_PREFIX:-`cat .prefix 2>/dev/null`} + +trap "exit 1" SIGHUP SIGTERM SIGINT + + +NUM_PROCESSES=2 +APP=osu_latency +LOGFILE= +. ./prepare_run + +CMD="osu2/osu_latency" + +( + echo " Running Latency 2 ..." + show_mpi_hosts + set -x + $MPI_RUN_CMD $CMD + set +x +) 2>&1 | tee -i -a $LOGFILE + +echo "########################################### " >> $LOGFILE diff --git a/MpiApps/apps/run_lat3 b/MpiApps/apps/run_lat3 new file mode 100755 index 0000000..1685343 --- /dev/null +++ b/MpiApps/apps/run_lat3 @@ -0,0 +1,57 @@ +#!/bin/sh +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] + +# BASE PATH TO MPI EXECUTABLES: To use an alternate location, +# either edit this line or set MPICH_PREFIX in your environment. +# see select_mpi for the set of default MPI selections +# default to MPI used for build +MPICH_PREFIX=${MPICH_PREFIX:-`cat .prefix 2>/dev/null`} + +trap "exit 1" SIGHUP SIGTERM SIGINT + + +NUM_PROCESSES=2 +APP=osu_latency +LOGFILE= +. ./prepare_run + +CMD="osu-micro-benchmarks-3.8-July12/mpi/pt2pt/osu_latency" + +( + echo " Running Latency 3.8 ..." + show_mpi_hosts + set -x + $MPI_RUN_CMD $CMD + set +x +) 2>&1 | tee -i -a $LOGFILE + +echo "########################################### " >> $LOGFILE diff --git a/MpiApps/apps/run_mandel b/MpiApps/apps/run_mandel new file mode 100755 index 0000000..7793c01 --- /dev/null +++ b/MpiApps/apps/run_mandel @@ -0,0 +1,62 @@ +#!/bin/bash +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] + +# BASE PATH TO MPI EXECUTABLES: To use an alternate location, +# either edit this line or set MPICH_PREFIX in your environment. +# see select_mpi for the set of default MPI selections +# default to MPI used for build +MPICH_PREFIX=${MPICH_PREFIX:-`cat .prefix 2>/dev/null`} + +trap "exit 1" SIGHUP SIGTERM SIGINT + +if [ -z "$1" ] +then + echo " Usage: run_mandel number_processes" + echo " For example: ./run_mandel 2" + echo "number_processes may be 'all' in which case one rank will be started for" + echo "every process in the mpi_hosts file" + echo + echo " Use click-and-drag to zoom into image." + echo " Use CTRL-C to terminate." + exit 1 +fi + +NUM_PROCESSES=$1 +APP=pmandel +LOGFILE= +. ./prepare_run + +MANDEL_CMD="./mandel/pmandel +randomize -colors 256 +zoom" + +echo " Running Mandel..." +show_mpi_hosts +$MPI_RUN_CMD $MANDEL_CMD diff --git a/MpiApps/apps/run_mbw_mr3 b/MpiApps/apps/run_mbw_mr3 new file mode 100755 index 0000000..e2e7504 --- /dev/null +++ b/MpiApps/apps/run_mbw_mr3 @@ -0,0 +1,81 @@ +#!/bin/sh +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] + +# BASE PATH TO MPI EXECUTABLES: To use an alternate location, +# either edit this line or set MPICH_PREFIX in your environment. +# see select_mpi for the set of default MPI selections +# default to MPI used for build +MPICH_PREFIX=${MPICH_PREFIX:-`cat .prefix 2>/dev/null`} + +trap "exit 1" SIGHUP SIGTERM SIGINT + +if [ -z "$1" ] +then + echo "Usage: run_mbw_mr3 number_processes [osu_mbw_mr arguments]]" >&2 + echo "number_processes may be 'all' in which case one rank will be started for" >&2 + echo "every process in the mpi_hosts file" >&2 + echo "This application requires an even number of processes" >&2 + echo >&2 + echo "osu_mbw_mr arguments:" >&2 + echo " -r=<0,1> Print uni-directional message rate (default 1)" >&2 + echo " -p= Number of pairs involved (default np / 2)" >&2 + echo " -w= Number of messages sent before acknowledgement (64, 10)" >&2 + echo " [cannot be used with -v]" >&2 + echo " -v Vary the window size (default no)" >&2 + echo " [cannot be used with -w]" >&2 + echo " -h Print this help" >&2 + echo >&2 + echo " Note: This benchmark relies on block ordering of the ranks. Please see" >&2 + echo " the OSU benchmarks README for more information." >&2 + echo >&2 + exit 2 +else + NUM_PROCESSES=$1 + shift +fi + +MULT_PROCESSES=2 + +CMD="osu-micro-benchmarks-3.8-July12/mpi/pt2pt/osu_mbw_mr $@" + +APP=osu_mbw_mr +LOGFILE= +. ./prepare_run + +( + echo " Running Multi-Bandwidth 3.8 ..." + show_mpi_hosts + set -x + $MPI_RUN_CMD $CMD + set +x +) 2>&1 | tee -i -a $LOGFILE +echo "########################################### " >> $LOGFILE diff --git a/MpiApps/apps/run_mpi_stress b/MpiApps/apps/run_mpi_stress new file mode 100755 index 0000000..b80d3b1 --- /dev/null +++ b/MpiApps/apps/run_mpi_stress @@ -0,0 +1,124 @@ +#!/bin/sh +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] + +# BASE PATH TO MPI EXECUTABLES: To use an alternate location, +# either edit this line or set MPICH_PREFIX in your environment. +# see select_mpi for the set of default MPI selections +# default to MPI used for build +MPICH_PREFIX=${MPICH_PREFIX:-`cat .prefix 2>/dev/null`} + +trap "exit 1" SIGHUP SIGTERM SIGINT + +usage() +{ + echo "Usage: run_mpi_stress number_processes [mpi_stress arguments]" >&2 + echo "number_processes may be 'all' in which case one rank will be started for" >&2 + echo "every process in the mpi_hosts file" >&2 + echo >&2 + echo "mpi_stress arguments:" >&2 + echo " -a INT : desired alignment for buffers (must be power of 2)" >&2 + echo " -b BYTE : byte value to initialize non-random send buffers (otherwise 0)" >&2 + echo " -c : enable CRC checksums" >&2 + echo " -D INT : set max data amount per msg size (default 1073741824)" >&2 + echo " -d : enable data checksums (otherwise headers only)" >&2 + echo " -e : exercise the interconnect with random length messages" >&2 + echo " -g INT : use INT-dimensional grid connectivity (non-periodic)" >&2 + echo " -G INT : use INT-dimensional grid connectivity (periodic)" >&2 + echo " (default is to use all-to-all connectivity)" >&2 + echo " -h : display this help page" >&2 + echo " -i : include local ranks as destinations (only for all-to-all)" >&2 + echo " -I INT : set msg size increment (default power of 2)" >&2 + echo " -l INT : set min msg size (default 0)" >&2 + echo " -L INT : set min msg count (default 100)" >&2 + echo " -m INT : set max msg size (default 4194304)" >&2 + echo " -M INT : set max msg count (default 10000)" >&2 + echo " -n INT : number of times to repeat (default 1)" >&2 + echo " -O : show options and parameters used for the run." >&2 + echo " -p : show progress" >&2 + echo " -P : poison receive buffers at init and after each receive" >&2 + echo " -q : quiet mode (don't show error details)" >&2 + echo " -r : fill send buffers with random data (else 0 or -b byte)" >&2 + echo " -R : round robin destinations (default is random selection)" >&2 + echo " -s : include self as a destination (only for all-to-all)" >&2 + echo " -S : use non-blocking synchronous sends (MPI_Issend)" >&2 + echo " -t INT : run for INT minutes (implictly adds -n BIGNUM)" >&2 + echo " -u : uni-directional traffic (only for grid)" >&2 + echo " -v : enable verbose mode (more -v for more verbose)" >&2 + echo " -w INT : number of send/recv in window (default 20)" >&2 + echo " -x : enable XOR checksums" >&2 + echo " -z : enable typical options for data integrity (-drx)" >&2 + echo " : (for stronger integrity checking try using -drc instead)" >&2 + echo " -Z : zero receive buffers at init and after each receive" >&2 + echo "This an an MPI stress test program designed to load up an MPI" >&2 + echo "interconnect with point-to-point messages while optionally" >&2 + echo "checking for data integrity. By default, it runs with all-to-all" >&2 + echo "traffic patterns, optionally including oneself and one's local" >&2 + echo "shm peers. It can also be set up with multi-dimensional grid" >&2 + echo "traffic patterns, and this can be parameterized to run rings," >&2 + echo "open 2D grids, closed 2D grids, cubic lattices, hypercubes, etc." >&2 + echo "Optionally, the message data can be randomized and checked" >&2 + echo "using CRC checksums (strong but slow) or XOR checksums (weak but" >&2 + echo "fast). The communication kernel is built out of non-blocking" >&2 + echo "point-to-point calls to load up the interconnect. The program is" >&2 + echo "not designed to exhaustively test out different MPI primitives." >&2 + echo "Performance metrics are displayed, but should be carefully" >&2 + echo "interpreted in terms of the features enabled." >&2 + echo >&2 + exit 2 +} + +if [ -z "$1" ] +then + usage +fi +if [ "$1" != "all" ] && ! [ "$1" -gt 0 ] 2>/dev/null +then + usage +fi +NUM_PROCESSES=$1 +MIN_PROCESSES=1 +shift + +CMD="$MPICH_PREFIX/tests/intel/mpi_stress $@" + +APP=mpi_stress +LOGFILE= +. ./prepare_run + +( + echo " Running Mpi Stress ..." + show_mpi_hosts + set -x + $MPI_RUN_CMD $CMD + set +x +) 2>&1 | tee -i -a $LOGFILE +echo "########################################### " >> $LOGFILE diff --git a/MpiApps/apps/run_mpicheck b/MpiApps/apps/run_mpicheck new file mode 100755 index 0000000..857a48f --- /dev/null +++ b/MpiApps/apps/run_mpicheck @@ -0,0 +1,65 @@ +#!/bin/sh +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] + +# BASE PATH TO MPI EXECUTABLES: To use an alternate location, +# either edit this line or set MPICH_PREFIX in your environment. +# see select_mpi for the set of default MPI selections +# default to MPI used for build +MPICH_PREFIX=${MPICH_PREFIX:-`cat .prefix 2>/dev/null`} + +trap "exit 1" SIGHUP SIGTERM SIGINT + +if [ -z "$1" ] +then + echo " Usage: run_mpicheck number_processes" + echo " For example: ./run_mpicheck 2 [options]" + echo "number_processes may be 'all' in which case one rank will be started for" + echo "every process in the mpi_hosts file" + exit 1 +fi + +NUM_PROCESSES=$1 +OPTIONS="$2 $3 $4 $5 $6 $7 $8 $9" +APP=mpicheck +LOGFILE= +. ./prepare_run + +CMD="mpicheck/mpicheck" + +( + echo " Running MpiCheck ..." + show_mpi_hosts + set -x + $MPI_RUN_CMD $CMD $OPTIONS + set +x +) 2>&1 | tee -i -a $LOGFILE +echo "########################################### " >> $LOGFILE diff --git a/MpiApps/apps/run_multi_lat3 b/MpiApps/apps/run_multi_lat3 new file mode 100755 index 0000000..401f6d4 --- /dev/null +++ b/MpiApps/apps/run_multi_lat3 @@ -0,0 +1,66 @@ +#!/bin/sh +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] + +# BASE PATH TO MPI EXECUTABLES: To use an alternate location, +# either edit this line or set MPICH_PREFIX in your environment. +# see select_mpi for the set of default MPI selections +# default to MPI used for build +MPICH_PREFIX=${MPICH_PREFIX:-`cat .prefix 2>/dev/null`} + +trap "exit 1" SIGHUP SIGTERM SIGINT + +if [ -z "$1" ] +then + echo " Usage: run_multi_lat3 number_processes" + echo " For example: ./run_multi_lat3 2" + echo "number_processes may be 'all' in which case one rank will be started for" + echo "every process in the mpi_hosts file" + echo "This application requires an even number of processes" + exit 1 +fi + +NUM_PROCESSES=$1 +MULT_PROCESSES=2 +APP=osu_multi_lat +LOGFILE= +. ./prepare_run + +CMD="osu-micro-benchmarks-3.8-July12/mpi/pt2pt/osu_multi_lat" + +( + echo " Running Multi-Latency 3.8 ..." + show_mpi_hosts + set -x + $MPI_RUN_CMD $CMD + set +x +) 2>&1 | tee -i -a $LOGFILE +echo "########################################### " >> $LOGFILE diff --git a/MpiApps/apps/run_multibw b/MpiApps/apps/run_multibw new file mode 100755 index 0000000..aeac9d9 --- /dev/null +++ b/MpiApps/apps/run_multibw @@ -0,0 +1,67 @@ +#!/bin/sh +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] + +# BASE PATH TO MPI EXECUTABLES: To use an alternate location, +# either edit this line or set MPICH_PREFIX in your environment. +# see select_mpi for the set of default MPI selections +# default to MPI used for build +MPICH_PREFIX=${MPICH_PREFIX:-`cat .prefix 2>/dev/null`} + +trap "exit 1" SIGHUP SIGTERM SIGINT + +if [ -z "$1" ] +then + echo " Usage: run_multibw number_processes [-b] [-m pairs]" + echo " For example: ./run_multibw 4" + echo "number_processes may be 'all' in which case one rank will be started for" + echo "every process in the mpi_hosts file" + echo "This application requires an even number of processes" + exit 1 +fi + +NUM_PROCESSES=$1 +shift +MULT_PROCESSES=2 +APP=mpi_multibw +LOGFILE= +. ./prepare_run + +CMD="mpi_multibw/mpi_multibw $@" + +( + echo " Running Multi-Bandwidth ..." + show_mpi_hosts + set -x + $MPI_RUN_CMD $CMD + set +x +) 2>&1 | tee -i -a $LOGFILE +echo "########################################### " >> $LOGFILE diff --git a/MpiApps/apps/run_nvidia b/MpiApps/apps/run_nvidia new file mode 100755 index 0000000..2ee5e2c --- /dev/null +++ b/MpiApps/apps/run_nvidia @@ -0,0 +1,64 @@ +#!/bin/sh +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] + +# BASE PATH TO MPI EXECUTABLES: To use an alternate location, +# either edit this line or set MPICH_PREFIX in your environment. +# see select_mpi for the set of default MPI selections +# default to MPI used for build +MPICH_PREFIX=${MPICH_PREFIX:-`cat .prefix 2>/dev/null`} + +trap "exit 1" SIGHUP SIGTERM SIGINT + +NUM_PROCESSES=2 +APP=bw +LOGFILE= +. ./prepare_run + +PAGEABLE_CMD="nvidia/mpi_pageable" +PINNED_CMD="nvidia/mpi_pinned" + +echo " Running NVidia pageable/pinned test..." | tee -a $LOGFILE +show_mpi_hosts | tee -a $LOGFILE + +echo " ###########" | tee -a $LOGFILE +echo " Pageable..." | tee -a $LOGFILE +set -x +$MPI_RUN_CMD $PAGEABLE_CMD 2>&1|tee -i -a $LOGFILE +set +x + +echo " ###########" | tee -a $LOGFILE +echo " Pinned....." | tee -a $LOGFILE +set -x +$MPI_RUN_CMD $PINNED_CMD 2>&1|tee -i -a $LOGFILE +set +x + +echo "########################################### " >> $LOGFILE diff --git a/MpiApps/apps/run_nxnlatbw b/MpiApps/apps/run_nxnlatbw new file mode 100755 index 0000000..cdec722 --- /dev/null +++ b/MpiApps/apps/run_nxnlatbw @@ -0,0 +1,70 @@ +#!/bin/sh +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] + +# BASE PATH TO MPI EXECUTABLES: To use an alternate location, +# either edit this line or set MPICH_PREFIX in your environment. +# see select_mpi for the set of default MPI selections +# default to MPI used for build +MPICH_PREFIX=${MPICH_PREFIX:-`cat .prefix 2>/dev/null`} + +trap "exit 1" SIGHUP SIGTERM SIGINT + +if [ -z "$1" ] +then + echo " Usage: run_nxnlatbw number_processes [other arguments]" + echo " For example: ./run_nxnlatbw 2" + echo "number_processes may be 'all' in which case one rank will be started for" + echo "every process in the mpi_hosts file" + exit 1 +fi + +NUM_PROCESSES=$1 +shift +APP=mpi_nxnlatbw +LOGFILE= +. ./prepare_run + +CMD="$MPICH_PREFIX/tests/intel/mpi_nxnlatbw" +if [ ! -x $CMD ] +then + echo " $CMD: Not Found" + exit 1 +fi + +( + echo " Running Intel NxN Latency and Bandwidth Test ..." + show_mpi_hosts + set -x + $MPI_RUN_CMD $CMD "$@" + set +x +) 2>&1 | tee -i -a $LOGFILE +echo "########################################### " >> $LOGFILE diff --git a/MpiApps/apps/run_osu b/MpiApps/apps/run_osu new file mode 100755 index 0000000..85bf0d8 --- /dev/null +++ b/MpiApps/apps/run_osu @@ -0,0 +1,86 @@ +#!/bin/sh +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] + +# BASE PATH TO MPI EXECUTABLES: To use an alternate location, +# either edit this line or set MPICH_PREFIX in your environment. +# see select_mpi for the set of default MPI selections +# default to MPI used for build +MPICH_PREFIX=${MPICH_PREFIX:-`cat .prefix 2>/dev/null`} + +trap "exit 1" SIGHUP SIGTERM SIGINT + +if [ -z "$1" -o "$1" = "-h" ] +then + echo " Usage: run_osu ... " + echo " For example: ./run_osu 2 osu_allgatherv" + echo " number_processes may be 'all' in which case one rank will be" + echo " started for every process in the mpi_hosts file." + echo " The remaining arguments are passed to the target command." + echo + echo " Commands are: osu_allgather, osu_allgatherv, osu_allreduce," + echo " osu_alltoall, osu_alltoallv, osu_barrier, osu_bcast, osu_gather," + echo " osu_gatherv, osu_reduce, osu_reduce_scatter, osu_scatter," + echo " osu_scatterv, osu_acc_latency, osu_get_bw, osu_get_latency," + echo " osu_passive_acc_latency, osu_passive_get_bw, osu_passive_get_latency" + echo " osu_passive_put_bw, osu_passive_put_latency, osu_put_bibw," + echo " osu_put_bw, osu_put_latency, osu_bibw, osu_bw, osu_latency," + echo " osu_latency_mt, osu_mbw_mr, osu_multi_lat" + exit 1 +fi + +BASE_DIR="osu-micro-benchmarks-3.8-July12/mpi/" +NUM_PROCESSES=$1 +shift + +if [ $# -lt 1 ]; then + echo "You must specify an OSU benchmark." + exit 1 +fi + +CMD=`find ${BASE_DIR} -name $1` +if [ -z ${CMD} ]; then + echo "$1 is not a valid OSU benchmark." + exit 1 +fi + +LOGFILE= +. ./prepare_run + + +( + echo " Running $CMD ..." + show_mpi_hosts + set -x + $MPI_RUN_CMD $CMD + set +x +) 2>&1 | tee -i -a $LOGFILE +echo "########################################### " >> $LOGFILE diff --git a/MpiApps/apps/run_pgfile b/MpiApps/apps/run_pgfile new file mode 100755 index 0000000..a74308f --- /dev/null +++ b/MpiApps/apps/run_pgfile @@ -0,0 +1,67 @@ +#!/bin/sh +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] + +trap "exit 1" SIGHUP SIGTERM SIGINT + +CURTIME=`date +%d%b%y%H%M%S` +if [ ! -d logs ] +then + `mkdir logs` +fi +if [ $# -ne 0 ] +then + echo " Usage: run_pgfile" + echo " For example: ./run_pgfile" + exit 1 +fi +if [ ! -f pgfile ] +then + echo " Please create pgfile file with the list of " + echo " processors/commands and arguments in this cluster." + echo " One host per line." + echo " See pgfile.sample file" + exit 1 +fi +LOGFILE=$PWD/logs/pgfile.$CURTIME +echo " Running MPI tests" +echo " logfile $LOGFILE" +> $LOGFILE + +MPI_RUN_CMD="/usr/lib/opa/bin/mpirun -pgfile pgfile " + +( + echo " Running pgfile test ..." + set -x + $MPI_RUN_CMD + set +x +) 2>&1 | tee -i -a $LOGFILE +echo "########################################### " >> $LOGFILE diff --git a/MpiApps/apps/run_tachyon b/MpiApps/apps/run_tachyon new file mode 100755 index 0000000..80678e2 --- /dev/null +++ b/MpiApps/apps/run_tachyon @@ -0,0 +1,68 @@ +#!/bin/bash +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] + +# BASE PATH TO MPI EXECUTABLES: To use an alternate location, +# either edit this line or set MPICH_PREFIX in your environment. +# see select_mpi for the set of default MPI selections +# default to MPI used for build +MPICH_PREFIX=${MPICH_PREFIX:-`cat .prefix 2>/dev/null`} + +trap "exit 1" SIGHUP SIGTERM SIGINT + +if [ -z "$1" ] +then + echo " Usage: run_tachyon number_processes" + echo " For example: ./run_tachyon 2" + echo "number_processes may be 'all' in which case one rank will be started for" + echo "every process in the mpi_hosts file" + echo + echo " Use click-and-drag to zoom into image." + echo " Use CTRL-C to terminate." + exit 1 +fi + +NUM_PROCESSES=$1 +APP=tachyon +LOGFILE= +. ./prepare_run + +RUN_DIR="$PWD/tachyon/scenes" +TACHYON_CMD="$PWD/tachyon/scenes/tachyon $RUN_DIR/$2.dat -camfile $RUN_DIR/$2.cam -numthreads 1" + +if [ $USING_MPD = y ] +then + MPI_RUN_CMD="$MPI_RUN_CMD -wdir $RUN_DIR" +fi + +echo " Running Tachyon..." +show_mpi_hosts +(cd $RUN_DIR; $MPI_RUN_CMD $TACHYON_CMD) diff --git a/MpiApps/apps/runmyapp b/MpiApps/apps/runmyapp new file mode 100755 index 0000000..6a4578b --- /dev/null +++ b/MpiApps/apps/runmyapp @@ -0,0 +1,56 @@ +#!/bin/sh +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] + +# script to perform a single run of an app. +# by having mpirun invoke this script as the app we have a chance to +# carefully control environment variables and check the output from the +# app for indications of errors + +# this is a sample which you should edit to match the application you want to +# to run, the example is provided for HPL + +# edit this if you have an alternate path to MPI libraries +# default to MPI used for build +MPICH_PREFIX=${MPICH_PREFIX:-`cat .prefix 2>/dev/null`} +. ./select_mpi # default MPICH_PREFIX if necessary + +# uncomment if you want to collect any core files +#ulimit -c unlimited + +# uncomment if MPI libraries may be in a non-standard path +#export LD_LIBRARY_PATH=$MPICH_PREFIX/lib64/shared:$MPICH_PREFIX/lib/shared:$LD_LIBRARY_PATH + +# This line can run your real application with appropriate arguments +#PMB2.2.1/SRC_PMB/PMB-MPI1 "$@" +#$MPICH_PREFIX/tests/IMB-4.0/IMB-MPI1 "$@" +cd hpl/bin/ICS.$(uname -s).$(./get_mpi_cc.sh) +./xhpl diff --git a/MpiApps/apps/select_mpi b/MpiApps/apps/select_mpi new file mode 100755 index 0000000..3d10eb7 --- /dev/null +++ b/MpiApps/apps/select_mpi @@ -0,0 +1,104 @@ +#!/bin/sh +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] + +# helper script to select MPICH_PREFIX + +# this script should be . included in a run_ script +# Input: +# MPICH_PREFIX - path to MPICH tools (optional) +# Output: +# MPICH_PREFIX - path to MPICH tools + +valid_mpich_prefix() +{ + if [ -z "$MPICH_PREFIX" -o ! -e "$MPICH_PREFIX" -o ! -e "$MPICH_PREFIX"/bin ] + then + return 1 + fi + if [ -e "$MPICH_PREFIX/bin/mpirun" -o -e "$MPICH_PREFIX/bin/mpdtrace" \ + -o -e "$MPICH_PREFIX/bin/mpirun_mpd" -o -e "$MPICH_PREFIX/bin/mpiexec" \ + -o -e "$MPICH_PREFIX/bin/mpirun_rsh" ] + then + return 0 + else + return 1 + fi +} + +# check all MPIs which start with $1 pathname and pick the 1st valid one +find_mpi() +{ + for MPICH_PREFIX in $(ls -d $* 2>/dev/null) + do + if valid_mpich_prefix + then + break + else + MPICH_PREFIX="" + fi + done +} + +# defaults we use for MPI (intelMPI, openmpi, mvapich2) +if [ -z "$MPICH_PREFIX" ] +then + prefix=${prefix:-/usr} + if ! valid_mpich_prefix + then + find_mpi $(ls -d $prefix/mpi/gcc/openmpi*hfi | grep -v cuda) + fi + if ! valid_mpich_prefix + then + find_mpi $prefix/mpi/gcc/openmpi*cuda*hfi + fi + if ! valid_mpich_prefix + then + find_mpi $prefix/mpi/gcc/mvapich2-*hfi + fi + if ! valid_mpich_prefix + then + find_mpi $prefix/mpi/gcc/openmpi* + fi + if ! valid_mpich_prefix + then + find_mpi $prefix/mpi/gcc/mvapich2-* + fi + if ! valid_mpich_prefix + then + find_mpi $prefix/mpi/gcc/mvapich-2* + fi + if ! valid_mpich_prefix + then + MPICH_PREFIX="" + fi +fi +export MPICH_PREFIX diff --git a/MpiApps/apps/stop_daemons b/MpiApps/apps/stop_daemons new file mode 100755 index 0000000..777afe7 --- /dev/null +++ b/MpiApps/apps/stop_daemons @@ -0,0 +1,48 @@ +#!/bin/bash +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +#[ICS VERSION STRING: unknown] +set -x +# stop daemons which may affect benchmark performancs +# only needed when running true performance benchmarks + +# $1 is hosts to operate on +#hosts=alive +#hosts=good +hosts=${1:-running} + +export FF_MAX_PARALLEL=1700 + +# /etc/init.d approach works for RHEL6 and SLES11 +opacmdall -p -f $hosts '/etc/init.d/dhcpd stop; /etc/init.d/ntpd stop; /etc/init.d/impi stop; /etc/init.d/crond stop' + +# systemctl for RHEL7 and SLES12 +#opacmdall -p -f $hosts 'systemctl stop dhcpd; systemctl stop ntpd; systemctl stop impi; systemctl stop crond' +opacmdall -p -f $hosts 'systemctl stop ntpd; systemctl stop crond' diff --git a/OpenIb_Host/DEFAULT_OPA_FEATURE_SET b/OpenIb_Host/DEFAULT_OPA_FEATURE_SET new file mode 100755 index 0000000..1c2142d --- /dev/null +++ b/OpenIb_Host/DEFAULT_OPA_FEATURE_SET @@ -0,0 +1 @@ +opa10 diff --git a/OpenIb_Host/LINUX/Makefile b/OpenIb_Host/LINUX/Makefile new file mode 100644 index 0000000..482917d --- /dev/null +++ b/OpenIb_Host/LINUX/Makefile @@ -0,0 +1,364 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** +# Makefile for LINUX + +# Include Make Control Settings +include $(TL_DIR)/$(PROJ_FILE_DIR)/Makesettings.project + +#=============================================================================# +# Definitions: +#-----------------------------------------------------------------------------# + +# Name of SubProjects +DS_SUBPROJECTS = +# name of executable or downloadable image +EXECUTABLE = #LINUX$(EXE_SUFFIX) +# list of sub directories to build +DIRS = +# C files (.c) +CFILES = \ + # Add more c files here +# C++ files (.cpp) +CCFILES = \ + # Add more cpp files here +# lex files (.lex) +LFILES = \ + # Add more lex files here +# archive library files (basename, $ARFILES will add MOD_LIB_DIR/prefix and suffix) +LIBFILES = +# Windows Resource Files (.rc) +RSCFILES = +# Windows IDL File (.idl) +IDLFILE = +# Windows Linker Module Definitions (.def) file for dll's +DEFFILE = +# targets to build during INCLUDES phase (add public includes here) +INCLUDE_TARGETS = \ + # Add more h hpp files here +# Non-compiled files +MISC_FILES = \ + README \ + # Add more files here +# all source files +SOURCES = $(CFILES) $(CCFILES) $(LFILES) $(RSCFILES) $(IDLFILE) + +ifeq "$(BUILD_TARGET_OS_VENDOR)" "ubuntu" + UTIL_PKG = $(TL_DIR)/CommonInstall/util_deb.pl +else + UTIL_PKG = $(TL_DIR)/CommonInstall/util_rpm.pl +endif +INSTALL_SOURCES= \ + $(TL_DIR)/CommonInstall/util_init.pl \ + $(TL_DIR)/CommonInstall/util_basicio.pl \ + $(TL_DIR)/CommonInstall/util_basicfile.pl \ + $(TL_DIR)/CommonInstall/util_configfile.pl \ + $(TL_DIR)/CommonInstall/util_startup.pl \ + $(TL_DIR)/CommonInstall/util_driver.pl \ + $(TL_DIR)/CommonInstall/util_components.pl \ + $(TL_DIR)/CommonInstall/util_blacklist.pl \ + $(TL_DIR)/CommonInstall/util_ifcfg.pl \ + $(TL_DIR)/CommonInstall/util_linuxconfig.pl \ + $(TL_DIR)/CommonInstall/util_hosttools.pl \ + $(UTIL_PKG) \ + $(TL_DIR)/CommonInstall/util_build.pl \ + $(TL_DIR)/CommonInstall/ofed_firmware.pl \ + $(TL_DIR)/CommonInstall/comp_oftools.pl \ + $(TL_DIR)/CommonInstall/comp_fastfabric.pl \ + $(TL_DIR)/CommonInstall/overrides_ff.pl \ + $(TL_DIR)/CommonInstall/main_omnipathwrap_delta.pl + +ifeq "$(BUILD_TARGET_OS_VENDOR_VERSION)" "ES72" + PREREQ_SOURCE= $(TL_DIR)/CommonInstall/comp_ff_of_prereq_RHEL72.pl +endif +ifeq "$(BUILD_TARGET_OS_VENDOR_VERSION)" "ES73" + PREREQ_SOURCE= $(TL_DIR)/CommonInstall/comp_ff_of_prereq_RHEL73.pl +endif +ifeq "$(BUILD_TARGET_OS_VENDOR_VERSION)" "ES74" + PREREQ_SOURCE= $(TL_DIR)/CommonInstall/comp_ff_of_prereq_RHEL74.pl +endif +ifeq "$(BUILD_TARGET_OS_VENDOR_VERSION)" "ES75" + PREREQ_SOURCE= $(TL_DIR)/CommonInstall/comp_ff_of_prereq_RHEL75.pl +endif +ifeq "$(BUILD_TARGET_OS_VENDOR_VERSION)" "ES76" + PREREQ_SOURCE= $(TL_DIR)/CommonInstall/comp_ff_of_prereq_RHEL76.pl +endif +ifeq "$(BUILD_TARGET_OS_VENDOR_VERSION)" "ES8" + PREREQ_SOURCE= $(TL_DIR)/CommonInstall/comp_ff_of_prereq_RHEL8.pl +endif +ifeq "$(BUILD_TARGET_OS_VENDOR_VERSION)" "ES81" + PREREQ_SOURCE= $(TL_DIR)/CommonInstall/comp_ff_of_prereq_RHEL81.pl +endif +ifeq "$(BUILD_TARGET_OS_VENDOR_VERSION)" "ES122" + PREREQ_SOURCE= $(TL_DIR)/CommonInstall/comp_ff_of_prereq_SLES122.pl +endif +ifeq "$(BUILD_TARGET_OS_VENDOR_VERSION)" "ES123" + PREREQ_SOURCE= $(TL_DIR)/CommonInstall/comp_ff_of_prereq_SLES123.pl +endif +ifeq "$(BUILD_TARGET_OS_VENDOR_VERSION)" "ES124" + PREREQ_SOURCE= $(TL_DIR)/CommonInstall/comp_ff_of_prereq_SLES124.pl +endif +ifeq "$(BUILD_TARGET_OS_VENDOR_VERSION)" "ES125" + PREREQ_SOURCE= $(TL_DIR)/CommonInstall/comp_ff_of_prereq_SLES125.pl +endif +ifeq "$(BUILD_TARGET_OS_VENDOR_VERSION)" "ES15" + PREREQ_SOURCE= $(TL_DIR)/CommonInstall/comp_ff_of_prereq_SLES15.pl +endif +ifeq "$(BUILD_TARGET_OS_VENDOR_VERSION)" "ES151" + PREREQ_SOURCE= $(TL_DIR)/CommonInstall/comp_ff_of_prereq_SLES151.pl +endif + +COMP_SOURCES= \ + $(TL_DIR)/CommonInstall/comp_oftools.pl \ + $(TL_DIR)/CommonInstall/comp_fastfabric.pl +# Source files to include in DSP File +DSP_SOURCES = $(INCLUDE_TARGETS) $(SOURCES) $(MISC_FILES) \ + $(RSCFILES) $(DEFFILE) $(MAKEFILE) +# all object files +OBJECTS = $(CFILES:.c=$(OBJ_SUFFIX)) $(CCFILES:.cpp=$(OBJ_SUFFIX)) \ + $(LFILES:.lex=$(OBJ_SUFFIX)) +RSCOBJECTS = $(RSCFILES:.rc=$(RES_SUFFIX)) +# targets to build during LIBS phase +LIB_TARGETS_IMPLIB = +LIB_TARGETS_ARLIB = # $(LIB_PREFIX)LINUX$(ARLIB_SUFFIX) +LIB_TARGETS_EXP = $(LIB_TARGETS_IMPLIB:$(ARLIB_SUFFIX)=$(EXP_SUFFIX)) +LIB_TARGETS_MISC = +# targets to build during CMDS phase +CMD_TARGETS_SHLIB = +CMD_TARGETS_EXE = $(EXECUTABLE) +CMD_TARGETS_MISC = opacapture INSTALL.pl comp.pl +# files to remove during clean phase +CLEAN_TARGETS_MISC = +CLEAN_TARGETS = $(OBJECTS) $(RSCOBJECTS) $(IDL_TARGETS) $(CLEAN_TARGETS_MISC) +# other files to remove during clobber phase +CLOBBER_TARGETS_MISC= opacapture.sh +# sub-directory to install to within bin +BIN_SUBDIR = +# sub-directory to install to within include +INCLUDE_SUBDIR = + +# Additional Settings +#CLOCALDEBUG = User defined C debugging compilation flags [Empty] +#CCLOCALDEBUG = User defined C++ debugging compilation flags [Empty] +#CLOCAL = User defined C flags for compiling [Empty] +#CCLOCAL = User defined C++ flags for compiling [Empty] +#BSCLOCAL = User flags for Browse File Builder [Empty] +#DEPENDLOCAL = user defined makedepend flags [Empty] +#LINTLOCAL = User defined lint flags [Empty] +#LOCAL_INCLUDE_DIRS = User include directories to search for C/C++ headers [Empty] +#LDLOCAL = User defined C flags for linking [Empty] +#IMPLIBLOCAL = User flags for Object Lirary Manager [Empty] +#MIDLLOCAL = User flags for IDL compiler [Empty] +#RSCLOCAL = User flags for resource compiler [Empty] +#LOCALDEPLIBS = User libraries to include in dependencies [Empty] +#LOCALLIBS = User libraries to use when linking [Empty] +# (in addition to LOCALDEPLIBS) +#LOCAL_LIB_DIRS = User library directories for libpaths [Empty] + +LOCALDEPLIBS = + +# Include Make Rules definitions and rules +include $(TL_DIR)/$(PROJ_FILE_DIR)/Makerules.project + +#=============================================================================# +# Overrides: +#-----------------------------------------------------------------------------# +#CCOPT = # C++ optimization flags, default lets build config decide +#COPT = # C optimization flags, default lets build config decide +#SUBSYSTEM = Subsystem to build for (none, console or windows) [none] +# (Windows Only) +#USEMFC = How Windows MFC should be used (none, static, shared, no_mfc) [none] +# (Windows Only) +#=============================================================================# + +#=============================================================================# +# Rules: +#-----------------------------------------------------------------------------# +# process Sub-directories +include $(TL_DIR)/Makerules/Maketargets.toplevel + +# build cmds and libs +include $(TL_DIR)/Makerules/Maketargets.build + +# install for includes, libs and cmds phases +include $(TL_DIR)/Makerules/Maketargets.install + +# to avoid conflicts with the INSTALL pseudo target in make system build as .pl +# and rename during STAGE +INSTALL.pl: $(INSTALL_SOURCES) + cat $(INSTALL_SOURCES) > INSTALL.pl + chmod +x INSTALL.pl + +comp.pl: + cat $(PREREQ_SOURCE) $(COMP_SOURCES) > comp.pl + chmod +x comp.pl + +# install for stage phase +#include $(TL_DIR)/Makerules/Maketargets.stage +STAGE: + $(VS)$(STAGE_INSTALL) $(STAGE_INSTALL_DIR_OPT) $(PROJ_STAGE_DIR) INSTALL.pl + cd $(PROJ_STAGE_DIR) ; mv INSTALL.pl INSTALL + $(VS)$(STAGE_INSTALL) $(STAGE_INSTALL_DIR_OPT) $(PROJ_STAGE_DIR) comp.pl + $(VS)$(STAGE_INSTALL) $(STAGE_INSTALL_DIR_OPT) $(PROJ_STAGE_DIR) README + $(VS)$(STAGE_INSTALL) $(STAGE_INSTALL_DIR_OPT) $(PROJ_STAGE_BIN_DIR) opacapture + +# TBD - should build an rpm here +# can't use STAGE_SUB_DIR since RELEASE_TAG may not be set and it is used to +# put version suffix on STAGE_SUB_DIR +# TBD - make this a script, the wildcards for IntelOPA-Tools.* are a problem +# packaging should be filelist based, especially for release media which will +# be a subset of things found in stage +# TBD - make some of these "make variables" so this can be a simple sequence +# of commands and make will test exit codes for us + + +# TBD - make some of these "make variables" so this can be a simple sequence +# of commands and make will test exit codes for us + +DIR_ARCH := $(shell echo $(BUILD_TARGET) | tr '[A-Z]' '[a-z]') + +ifeq "$(BUILD_TARGET_OS_VENDOR)" "ubuntu" + RPM_ARCH := $(subst ia32,i386,$(subst em64t,amd64,$(subst x86_64,amd64,$(DIR_ARCH)))) + RPMDIR := $(TL_DIR)/debbuild + RPM_BUILD_DIR := build + SRPMSDIR := $(RPM_BUILD_DIR) + RPMSDIR := $(RPM_BUILD_DIR) + DEVEL := dev + SEPARATOR := _ + DEBUGINFO := dbgsym + SRPM_EXT := {.tar.xz,.dsc,_$(RPM_ARCH).changes} + RPM_EXT := _$(RPM_ARCH).deb + DEBUG_EXT := _$(RPM_ARCH).ddeb + EXT := deb + pkg_arch = _$(DEB_TARGET_ARCH) + pkg_ver = _$${MKRPM_VER} +else + RPM_ARCH := $(DIR_ARCH) + RPMDIR := $(TL_DIR)/rpmbuild + RPM_BUILD_DIR := BUILD + SRPMSDIR := SRPMS + RPMSDIR := RPMS/$(RPM_ARCH) + DEVEL := devel + SEPARATOR := - + DEBUGINFO := debuginfo + SRPM_EXT := .src.rpm + RPM_EXT := .$(RPM_ARCH).rpm + DEBUG_EXT := $(RPM_EXT) + EXT := rpm + pkg_arch = .`echo $(BUILD_TARGET) | tr '[A-Z]' '[a-z]'` + pkg_ver = -$${MKRPM_VER} +endif + +package: + mkdir -p $(RELEASE_DIR) + rm -f packaged_files dist_files + cd $(STAGE_DIR) ; \ + dir=`echo IntelOPA-Tools-FF.*`; \ + ver=`expr IntelOPA-Tools-FF.* : 'IntelOPA-Tools-FF.\(.*\)$$'`; \ + arch=$(pkg_arch); \ + vers=$(pkg_ver); \ + rm -rf $(RELEASE_DIR)/IntelOPA-Tools-FF.$$ver ; \ + mkdir -p $(RELEASE_DIR)/IntelOPA-Tools-FF.$$ver ; \ + cp -r $$dir/arch $$dir/distro $$dir/distro_version $$dir/os_id $(RELEASE_DIR)/IntelOPA-Tools-FF.$$ver 2>/dev/null; \ + cp -r $$dir/INSTALL $$dir/comp.pl $$dir/README $$dir/version $(RELEASE_DIR)/IntelOPA-Tools-FF.$$ver ; \ + cp -r $$dir/Lsf $(RELEASE_DIR)/IntelOPA-Tools-FF.$$ver 2>/dev/null; \ + cp -r $$dir/Moab $(RELEASE_DIR)/IntelOPA-Tools-FF.$$ver 2>/dev/null; \ + echo "$(RELEASE_DIR)/IntelOPA-Tools-FF.$$ver.tgz" >> $(TL_DIR)/packaged_files; \ + echo "$(RELEASE_DIR)/IntelOPA-Tools-FF.$$ver.tgz" >> $(TL_DIR)/dist_files; \ + echo "$(RELEASE_DIR)/IntelOPA-Tools.$$ver.tgz" >> $(TL_DIR)/packaged_files; \ + echo "$(RELEASE_DIR)/IntelOPA-Tools.$$ver.tgz" >> $(TL_DIR)/dist_files; \ + if [ "$(OPA_FEATURE_SET)" != "opa10" ]; then \ + echo "$(RELEASE_DIR)/opa-snapconfig$${vers}-$${MKRPM_REL}$${arch}.$(EXT)" >> $(TL_DIR)/packaged_files; \ + echo "$(RELEASE_DIR)/opa-snapconfig$${vers}-$${MKRPM_REL}$${arch}.$(EXT)" >> $(TL_DIR)/dist_files; \ + fi; \ + +final_package: + mkdir -p $(RELEASE_DIR) + cd $(RPMDIR); \ + dir=`grep 'IntelOPA-Tools-FF\.' $(RPM_BUILD_DIR)/opa-$${MKRPM_VER}/packaged_files | xargs dirname`; \ + filename=`grep 'IntelOPA-Tools-FF\.' $(RPM_BUILD_DIR)/opa-$${MKRPM_VER}/packaged_files | xargs basename`; \ + subdir=$${filename%.tgz}; \ + srpmdir=$$dir/$$subdir/SRPMS; \ + basicdir=`grep 'IntelOPA-Tools\.' $(RPM_BUILD_DIR)/opa-$${MKRPM_VER}/packaged_files | xargs dirname`; \ + basic=`grep 'IntelOPA-Tools\.' $(RPM_BUILD_DIR)/opa-$${MKRPM_VER}/packaged_files | xargs basename`; \ + rpmdir=$$dir/$$subdir/RPMS/$(DIR_ARCH); \ + basicrpmdir=$$basicdir/$${basic%.tgz}/RPMS/$(DIR_ARCH); \ + basicsrpmdir=$$basicdir/$${basic%.tgz}/SRPMS; \ + mkdir -p $$srpmdir || echo "ERR""OR: mkdir $$srpmdir."; \ + mkdir -p $$rpmdir || echo "ERR""OR: mkdir $$rpmdir."; \ + rm -rf $${basicdir}/$${basic} $${basicdir}/$${basic%.tgz}; \ + cp -rp $${dir}/$${subdir} $${basicdir}/$${basic%.tgz} || echo "ERR""OR: cp $${basicdir}/$${basic%.tgz}."; \ + cp $(SRPMSDIR)/opa-mpi-apps$(SEPARATOR)$${MKRPM_VER}-$${MKRPM_REL}$(SRPM_EXT) $$srpmdir/ || echo "ERR""OR: cp $$srpmdir."; \ + cp $(SRPMSDIR)/opa$(SEPARATOR)$${MKRPM_VER}-$${MKRPM_REL}$(SRPM_EXT) $$srpmdir/ || echo "ERR""OR: cp $$srpmdir."; \ + cp $(SRPMSDIR)/opa$(SEPARATOR)$${MKRPM_VER}-$${MKRPM_REL}$(SRPM_EXT) $$basicsrpmdir/ || echo "ERR""OR: cp $$srpmdir."; \ + cp $(RPMSDIR)/opa-basic-tools$(SEPARATOR)$${MKRPM_VER}-$${MKRPM_REL}$(RPM_EXT) $$rpmdir/ || echo "ERR""OR: cp $$rpmdir."; \ + cp $(RPMSDIR)/opa-address-resolution$(SEPARATOR)$${MKRPM_VER}-$${MKRPM_REL}$(RPM_EXT) $$rpmdir/ || echo "ERR""OR: cp $$rpmdir."; \ + cp $(RPMSDIR)/opa-libopamgt$(SEPARATOR)$${MKRPM_VER}-$${MKRPM_REL}$(RPM_EXT) $$rpmdir/ || echo "ERR""OR: cp $$rpmdir."; \ + cp $(RPMSDIR)/opa-libopamgt-$(DEVEL)$(SEPARATOR)$${MKRPM_VER}-$${MKRPM_REL}$(RPM_EXT) $$rpmdir/ || echo "ERR""OR: cp $$rpmdir."; \ + cp $(RPMSDIR)/opa-fastfabric$(SEPARATOR)$${MKRPM_VER}-$${MKRPM_REL}$(RPM_EXT) $$rpmdir/ || echo "ERR""OR: cp $$rpmdir."; \ + cp $(RPMSDIR)/opa-basic-tools$(SEPARATOR)$${MKRPM_VER}-$${MKRPM_REL}$(RPM_EXT) $$basicrpmdir/ || echo "ERR""OR: cp $$basicrpmdir."; \ + cp $(RPMSDIR)/opa-address-resolution$(SEPARATOR)$${MKRPM_VER}-$${MKRPM_REL}$(RPM_EXT) $$basicrpmdir/ || echo "ERR""OR: cp $$basicrpmdir."; \ + cp $(RPMSDIR)/opa-libopamgt$(SEPARATOR)$${MKRPM_VER}-$${MKRPM_REL}$(RPM_EXT) $$basicrpmdir/ || echo "ERR""OR: cp $$basicrpmdir."; \ + cp $(RPMSDIR)/opa-libopamgt-$(DEVEL)$(SEPARATOR)$${MKRPM_VER}-$${MKRPM_REL}$(RPM_EXT) $$basicrpmdir/ || echo "ERR""OR: cp $$basicrpmdir."; \ + cp $(RPMSDIR)/opa-mpi-apps$(SEPARATOR)$${MKRPM_VER}-$${MKRPM_REL}$(RPM_EXT) $$rpmdir/ || echo "ERR""OR: cp $$rpmdir."; \ + if [ "$(OPA_FEATURE_SET)" != "opa10" ]; then \ + cp $(RPMSDIR)/opa-snapconfig$(SEPARATOR)$${MKRPM_VER}-$${MKRPM_REL}$(RPM_EXT) $$dir/ || echo "ERR""OR: cp $$dir."; \ + cp $(RPMSDIR)/opa-snapconfig$(SEPARATOR)$${MKRPM_VER}-$${MKRPM_REL}$(RPM_EXT) $(RELEASE_DIR)/ || echo "ERR""OR: cp $$dir."; \ + fi; \ + if [ "$(BUILD_TARGET_OS_VENDOR)" = "redhat" ]; then \ + cp $(RPMSDIR)/opa-$(DEBUGINFO)$(SEPARATOR)$${MKRPM_VER}-$${MKRPM_REL}$(DEBUG_EXT) $$rpmdir/; \ + fi; \ + if [ "$(BUILD_TARGET_OS_VENDOR)" = "SuSE" ]; then \ + cp $(RPMSDIR)/opa-debugsource$(SEPARATOR)$${MKRPM_VER}-$${MKRPM_REL}$(RPM_EXT) $$rpmdir/; \ + fi; \ + if [ "$(BUILD_TARGET_OS_VENDOR)" = "SuSE" -o "$(BUILD_TARGET_OS_VENDOR)" = "ubuntu" ]; then \ + cp $(RPMSDIR)/opa-basic-tools-$(DEBUGINFO)$(SEPARATOR)$${MKRPM_VER}-$${MKRPM_REL}$(DEBUG_EXT) $$rpmdir/; \ + cp $(RPMSDIR)/opa-basic-tools-$(DEBUGINFO)$(SEPARATOR)$${MKRPM_VER}-$${MKRPM_REL}$(DEBUG_EXT) $$basicrpmdir/; \ + cp $(RPMSDIR)/opa-address-resolution-$(DEBUGINFO)$(SEPARATOR)$${MKRPM_VER}-$${MKRPM_REL}$(DEBUG_EXT) $$rpmdir/; \ + cp $(RPMSDIR)/opa-address-resolution-$(DEBUGINFO)$(SEPARATOR)$${MKRPM_VER}-$${MKRPM_REL}$(DEBUG_EXT) $$basicrpmdir/; \ + cp $(RPMSDIR)/opa-fastfabric-$(DEBUGINFO)$(SEPARATOR)$${MKRPM_VER}-$${MKRPM_REL}$(DEBUG_EXT) $$rpmdir/; \ + fi; \ + cd $$dir; \ + echo "Packaging $$dir/$$filename ..."; \ + tar cvfz $$filename $$subdir; \ + echo "Packaging $$basicdir/$$basic ..."; \ + tar cvfz $${basic} --exclude mpi --exclude shmem $${basic%.tgz} + cp "$(RPMDIR)/$(RPM_BUILD_DIR)/opa-$${MKRPM_VER}/packaged_files" "$(TL_DIR)/$(PROJ_FILE_DIR)/" + cp "$(RPMDIR)/$(RPM_BUILD_DIR)/opa-$${MKRPM_VER}/dist_files" "$(TL_DIR)/$(PROJ_FILE_DIR)/" + +# Unit test execution +#include $(TL_DIR)/Makerules/Maketargets.runtest + +# Unit test execution +#include $(TL_DIR)/Makerules/Maketargets.runtest + +#=============================================================================# + +#=============================================================================# +# DO NOT DELETE THIS LINE -- make depend depends on it. +#=============================================================================# diff --git a/OpenIb_Host/LINUX/README b/OpenIb_Host/LINUX/README new file mode 100644 index 0000000..8e63eba --- /dev/null +++ b/OpenIb_Host/LINUX/README @@ -0,0 +1,40 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] + +To install the Fast Fabric Tools +cd to this directory +./INSTALL + +The menus will guide you through the installation process. +For usage information on additional arguments to INSTALL, run: ./INSTALL -? + +For additional information, consult the IB Install Guide and User's +Manuals. diff --git a/OpenIb_Host/LINUX/opacapture.sh b/OpenIb_Host/LINUX/opacapture.sh new file mode 100755 index 0000000..59b583d --- /dev/null +++ b/OpenIb_Host/LINUX/opacapture.sh @@ -0,0 +1,576 @@ +#!/bin/bash +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2018, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] + +# Usage: opacapture output_file_name +# captures system information for IntelOPA problem reporting + +Usage_full() +{ + echo "Usage: opacapture [-d detail] output_tgz_file" >&2 + echo " or" >&2 + echo " opacapture --help" >&2 + echo " --help - produce full help text" >&2 + echo " -d detail - level of detail of capture" >&2 + echo " 1-Local 2-Fabric 3-Fabric+FDB 4-Analysis (default=1)" >&2 + echo "This will capture critical system information into a zipped tar file" >&2 + echo "The program will automatically append .tgz to the " >&2 + echo "if it does not already have a .tgz suffix" >&2 + echo "The resulting tar file should be sent to Customer Support along with any" 2>&1 + echo "IntelOPA problem report regarding this system" >&2 +} + +Usage() +{ + Usage_full + exit 2 +} + +if [ `basename $0` = ics_capture ] +then + echo "warning: ics_capture is depricated, use opacapture" >&2 +fi + +if [ x"$1" = "x--help" ] +then + Usage_full + exit 0 +fi + + +if [ -f /usr/lib/opa/tools/ff_funcs ] +then + . /usr/lib/opa/tools/ff_funcs + ff_available=y +else + ff_available=n +fi + +if [ $ff_available = "y" ] +then + if [ -f $CONFIG_DIR/opa/opafastfabric.conf ] + then + . $CONFIG_DIR/opa/opafastfabric.conf + fi + + . /usr/lib/opa/tools/opafastfabric.conf.def +fi + +detail=1 + +while getopts d: param +do + case $param in + d) + detail="$OPTARG";; + ?) + Usage;; + esac +done +shift $((OPTIND -1)) + +if [ $# != 1 ] +then + Usage +fi + +if [ `id -u` -ne 0 ] +then + echo "This must be run as user root" >&2 + Usage +fi + +if [ x`expr "$1" : '\(/\).*'` != x'/' ] +then + # relative path + tar_file=`pwd`/$1 +else + # absolute path + tar_file=$1 +fi + +# append .tgz suffix if not already present +if [ x$(expr "$tar_file" : '.*\(\.tgz\)') != x'.tgz' ] +then + tar_file="$tar_file.tgz" +fi + +dir=tmp/capture$$ +rm -rf /$dir +mkdir /$dir + +echo "Capture Info: Detail: $detail; Date: $(date)" >> /$dir/capture_info + +echo "Getting software and firmware version information ..." +echo "[ICS VERSION STRING: unknown]" > /$dir/sw_version +uname -a > /$dir/os_version +# we use query format so we can get ARCH information +rpm --queryformat '[%{NAME}-%{VERSION}-%{RELEASE}.%{ARCH}\n]' -qa > /$dir/rpms.detailed +# get simple version just to be safe +rpm -qa > /$dir/rpms + +sha256sum /usr/lib/opa-fm/runtime/sm > /$dir/sha256sums +sha256sum /usr/lib/opa-fm/runtime/fe >> /$dir/sha256sums + +echo "Capturing FM binaries and debuginfo if available" +rpm -q opa-fm-debuginfo > /dev/null 2>&1 +if [ $? -eq 0 ]; then + debuginfofiles=$(rpm -ql opa-fm-debuginfo | xargs -I% bash -c "if [ -f % ]; then echo %; fi") + tar -zcf /$dir/opa-fm-debuginfo.tgz $debuginfofiles > /dev/null 2>&1 + unset debuginfofiles +fi +tar -zcf /$dir/opa-fm-bins.tgz /usr/lib/opa-fm/runtime/ > /dev/null 2>&1 + +# Finding the PCI devices +for fw in `lspci -n | grep "8086:24f0"` +do + # Just get the PCI info for now... + echo "$fw" >> /$dir/fw_info +done + +opahfirev > /$dir/opahfirev 2>&1 + +echo "Capturing Firmware info if available" +type hfi1_eprom > /dev/null 2>&1 +if [ $? -eq 0 ]; then + hfi1_eprom -d all -V > /$dir/uefi_version 2>&1 +fi + +type opatmmtool > /dev/null 2>&1 +if [ $? -eq 0 ]; then + opatmmtool 2>/dev/null 1>/dev/null + tmm=$? + if [ $tmm -ne 3 ] + then + echo "Getting TMM information..." + opatmmtool -v status > /$dir/f4status 2>&1 + opatmmtool -f /$dir/f4otpdump dumpotp 2>&1 + fi +fi + +echo "Obtaining OS configuration ..." +# get library config +ldconfig -p > /$dir/ldconfig +# get current runlevel +who -r > /$dir/who_r 2>/dev/null # not available on all OSs +runlevel > /$dir/runlevel # not available on all OSs +# get service startup configuration +if [ $(command -v systemctl) ]; then + systemctl list-unit-files > /$dir/chkconfig.systemd +fi +chkconfig --list > /$dir/chkconfig 2>/dev/null +ulimit -a > /$dir/ulimit +uptime > /$dir/uptime + +echo "Obtaining dmesg logs ..." +dmesg -T > /$dir/dmesg + +echo "Obtaining present process and module list ..." +lsmod > /$dir/lsmod 2>&1 +depmod -a 2>&1 +cp -p /lib/modules/`uname -r`/modules.dep /$dir/modules.dep +ps -welf > /$dir/ps 2>&1 + +echo "Obtaining module info for hfi1 ..." +modinfo hfi1 > /$dir/modinfo_hfi1 2>&1 + +echo "Obtaining PCI device list ..." +lspci -vvv -xxxx > /$dir/lspci 2>&1 +ls -l /dev/ipath* /dev/hfi* /dev/infiniband > /$dir/lsdev + +echo "Obtaining processor information ..." +cpucount=$(grep -c processor /proc/cpuinfo) +cpupower -c 0-$((cpucount - 1)) frequency-info > /$dir/cpu-frequency-info 2>&1 +grep . /sys/devices/system/cpu/cpu*/cpufreq/scaling* > /$dir/cpu-scaling-info 2>&1 +grep . /sys/devices/system/cpu/intel_pstate/* > /$dir/cpu-intel_pstate 2>&1 +unset cpucount + +lscpu > /$dir/lscpu 2>&1 +lscpu --extended=CPU,CORE,SOCKET,NODE,BOOK,DRAWER,CACHE,POLARIZATION,ADDRESS,CONFIGURED > /$dir/lscpu-extended 2>&1 + +echo "Obtaining environment variables ..." +env > /$dir/env 2>&1 + +echo "Obtaining network interfaces ..." +ip addr show > /$dir/ifconfig 2>&1 + +echo "Obtaining DMI information ..." +dmidecode > /$dir/dmidecode 2>&1 + +echo "Obtaining Shared Memory information ..." +sysctl -a > /$dir/sysctl 2>&1 +sysctl -a 2>/dev/null | grep kernel.shm > /$dir/shm 2>&1 +ls -d /dev/shm >> /$dir/shm 2>&1 +ls -lR /dev/shm >> /$dir/shm 2>&1 + +echo "Obtaining OmniPath information ..." + +# concise port statistics +opainfo > /$dir/opainfo 2>&1 +opainfo -o stats > /$dir/opainfo-stats 2>&1 +opainfo -o info > /$dir/opainfo-info 2>&1 + +echo "Obtaining MPI configuration ..." +if type mpi-selector >/dev/null 2>/dev/null +then + mpi-selector --list > /$dir/mpi-selector-list + mpi-selector --system --query > /$dir/mpi-selector-system + mpi-selector --user --query > /$dir/mpi-selector-user +fi + +mkdir /$dir/proc +echo "Copying configuration and statistics for OPA drivers from /proc ..." +for proc_file in cmdline cpuinfo ksyms meminfo mtrr modules net/arp net/dev net/dev_mcast net/route net/rt_cache net/vlan pci interrupts devices filesystems iomem ioports slabinfo version uptime scsi iba driver/ics_dsc driver/ipoib driver/sdp driver/rds irq acpi/processor +do + if [ -e /proc/$proc_file ] + then + cp -p -r /proc/$proc_file /$dir/proc + fi +done +for proc_file in `ps -eo pid` +do + if [ -e /proc/$proc_file/stack ] + then + mkdir -p /$dir/proc/$proc_file + cp -p -r /proc/$proc_file/stack /$dir/proc/$proc_file + fi +done + +echo "Obtaining additional CPU info..." +cpupower frequency-info > /$dir/cpupower-freq-info + +# Check if HFI driver debug data dir) is present; log only if present +HFI_DEBUGDIR="/sys/kernel/debug/hfi1" +if [ -d ${HFI_DEBUGDIR} ] +then + #hfi1stats requires the existance of ${HFI_DEBUGDIR} + echo "Obtaining HFI statistics ..." + hfi1stats > /$dir/hfi1stats 2>&1 + + mkdir -p /${dir}${HFI_DEBUGDIR} + echo "Copying kernel debug information from ${HFI_DEBUGDIR}..." + cp -p -r ${HFI_DEBUGDIR}/* /${dir}/${HFI_DEBUGDIR} 2>/dev/null +fi + +# Check if IPOIB debug data dir is present; log if present +IPOIB_DEBUGDIR="/sys/kernel/debug/ipoib" +if [ -d ${IPOIB_DEBUGDIR} ] +then + echo "Obtaining IPOIB debug information from ${IPOIB_DEBUGDIR}..." + mkdir -p /${dir}${IPOIB_DEBUGDIR} + echo "Copying IPOIB debug information from ${IPOIB_DEBUGDIR}..." + cp -r ${IPOIB_DEBUGDIR}/* /${dir}/${IPOIB_DEBUGDIR} 2>/dev/null +fi + +# Check if side channel security issue mitigation information files are +# present; log if present +SIDE_CHANNEL_MITIGATION_INFO="/sys/devices/system/cpu/vulnerabilities" +if [ -d ${SIDE_CHANNEL_MITIGATION_INFO} ] +then + echo "Obtaining side channel security issue mitigation information from ${SIDE_CHANNEL_MITIGATION_INFO}" + mkdir -p /${dir}${SIDE_CHANNEL_MITIGATION_INFO} + echo "Copying side channel security issue mitigation information from ${SIDE_CHANNEL_MITIGATION_INFO}..." + cp -r ${SIDE_CHANNEL_MITIGATION_INFO}/* /${dir}${SIDE_CHANNEL_MITIGATION_INFO} 2>/dev/null +fi + +# Check if side channel security issue mitigation kernel configuration files are +# present; log if present +KERNEL_CONFIG_LOC=/sys/kernel/debug/x86 +SIDE_CHANNEL_MITIGATION_KERNEL_CONFIG_FILES="ibpb_enabled ibrs_enabled pti_enabled retp_enabled" +for fname in ${SIDE_CHANNEL_MITIGATION_KERNEL_CONFIG_FILES} +do + if [ -e ${KERNEL_CONFIG_LOC}/${fname} ] + then + echo "Obtaining kernel configuration file ${KERNEL_CONFIG_LOC}/${fname}" + if [ ! -d /${dir}${KERNEL_CONFIG_LOC} ] + then + mkdir -p /${dir}${KERNEL_CONFIG_LOC} + fi + echo "Copying kernel configuration file ${KERNEL_CONFIG_LOC}/${fname}..." + cp ${KERNEL_CONFIG_LOC}/${fname} /${dir}${KERNEL_CONFIG_LOC} 2>/dev/null + fi +done + +mkdir -p /$dir/sys/class +if [ -e /sys/class/infiniband ] +then + echo "Copying configuration and statistics for ib_ drivers from /sys ..." + cp -p -r /sys/class/*infiniband* /$dir/sys/class 2>/dev/null + mkdir -p /$dir/sys/class/infiniband + for f in /sys/class/infiniband/* + do + if [ -h $f ] + then + rm -f /$dir/$f + cp -p -r $f/ /$dir/sys/class/infiniband/ 2>/dev/null + if [ -h $f/device ] + then + dev=`basename $f` + unit=`expr $dev : 'hfi1_\(.*\)'` + if [ ! -z "$unit" ] + then + echo " Getting statedump for $dev ..." + echo -e "unit $unit\nstate save hw /$dir/opa${dev}.dump"|hfidiags -s - > /$dir/opa${dev}.dump.res 2>&1 + fi + # rm -f /$dir/$f/device + # mkdir -p /$dir/sys/class/infiniband/$dev/ 2>/dev/null + # cp -p -r $f/device/ /$dir/sys/class/infiniband/$dev/ 2>/dev/null + fi + fi + done +fi + +if [ -e /sys/class/scsi_host ] +then + cp -p -r /sys/class/scsi_host /$dir/sys/class 2>/dev/null +fi +if [ -e /sys/class/scsi_device ] +then + cp -p -r /sys/class/scsi_device /$dir/sys/class 2>/dev/null +fi + +if [ -e /sys/class/net/ ] +then + echo "Copying interface information for ipoib" + mkdir -p /$dir/sys/class/net + cp -r /sys/class/net/ /$dir/sys/class 2>/dev/null + for f in /sys/class/net/* + do + if [ -h $f ] + then + rm -f /$dir/$f + cp -r $f/ /$dir/sys/class/net/ 2>/dev/null + if [ -h $f/device ] + then + iface=`basename $f` + rm -f /$dir/$f/device + mkdir -p /$dir/sys/class/net/$iface/ 2>/dev/null + cp -r $f/device/ /$dir/sys/class/net/$iface/ 2>/dev/null + fi + fi + done +fi + +if [ -e /sys/module ] +then + echo "Copying configuration and statistics for OPA from /sys/module ..." + cp -p -r /sys/module /$dir/sys 2>/dev/null +fi + +if [ -f /usr/lib/opa-fm/bin/fm_capture ] +then + echo "Gathering Host FM Information ..." + (cd /$dir; /usr/lib/opa-fm/bin/fm_capture) +fi + +if [ -f /usr/bin/opa_osd_dump ] +then + echo "Gathering Distributed SA data..." + opa_osd_dump > /$dir/opa_osd_dump 2>&1 +fi + +if [ $detail -ge 2 ] +then + mkdir -p /$dir/fabric + cd /$dir/fabric/ + if [ "$ff_available" = y ] + then + check_ports_args opacapture + else + PORTS='0:0' + if [ $detail -ge 3 ] + then + echo "Warning: opacapture detail=$detail but FastFabric not available" + fi + fi + + if [ $detail -ge 3 -a "$ff_available" = y ] + then + echo "Gathering Fabric-Level Information with FDBs ..." + else + echo "Gathering Fabric-Level Information ..." + fi + + for hfi_port in $PORTS + do + hfi=$(expr $hfi_port : '\([0-9]*\):[0-9]*') + port=$(expr $hfi_port : '[0-9]*:\([0-9]*\)') + if [ "$hfi" = "" -o "$port" = "" ] + then + echo "opacapture: Error: Invalid port specification: $hfi_port" >&2 + continue + fi + ## fixup name so winzip won't complain + hfi_port_dir=${hfi}_${port} + + # make hfi_port directory + mkdir $hfi_port_dir + + # opasaquery doesn't require FF available + /usr/sbin/opasaquery -h $hfi -p $port -o node > $hfi_port_dir/nodes 2>&1 + /usr/sbin/opafabricinfo -p $hfi_port > $hfi_port_dir/opafabricinfo 2>&1 + + if [ "$ff_available" = y ] + then + router_opt="" + + if [ $port -eq 0 ] + then + port_opt="-h $hfi" + else + port_opt="-h $hfi -p $port" + fi + + # determine if port is management enabled + /usr/sbin/opasmaquery $port_opt -o pkey 2>/dev/null|grep -q 0xffff + mgmt_disabled=$? + + # add router table information to snapshot report + if [ $detail -gt 2 ] + then + router_opt="-r" + fi + + if [ $mgmt_disabled -eq 0 ] + then + /usr/sbin/opareport $port_opt -o snapshot -s -V $router_opt > $hfi_port_dir/snapshot.xml 2> $hfi_port_dir/snapshot.xml.err + /usr/sbin/opareport $port_opt -o snapshot -m -M -s -V $router_opt > $hfi_port_dir/snapshot_direct.xml 2> $hfi_port_dir/snapshot_direct.xml.err + /usr/sbin/opareport -o links -X $hfi_port_dir/snapshot.xml > $hfi_port_dir/fabric_links 2>&1 + /usr/sbin/opareport -o comps -X $hfi_port_dir/snapshot.xml > $hfi_port_dir/fabric_comps 2>&1 + /usr/sbin/opareport -o errors -X $hfi_port_dir/snapshot.xml > $hfi_port_dir/fabric_errors 2>&1 + /usr/sbin/opareport -o extlinks -X $hfi_port_dir/snapshot.xml > $hfi_port_dir/fabric_extlinks 2>&1 + /usr/sbin/opareport -o slowlinks -X $hfi_port_dir/snapshot.xml > $hfi_port_dir/fabric_slowlinks 2>&1 + /usr/sbin/opareport -o vfmember -V -d 4 > $hfi_port_dir/fabric_vfmember 2>&1 + fi + + if [ $detail -gt 2 ] + then + echo "Gathering Multicast Membership ..." + /usr/sbin/opashowmc -p $hfi:$port > $hfi_port_dir/fabric_showmc 2>&1 + # create cable health report directory and generate report + if [ $ff_available = "y" ] && [ -e "${FF_CABLE_HEALTH_REPORT_DIR}" ] + then + echo "Gathering Cable Health Report ..." + FF_CABLE_HEALTH_REPORT_DIR_WITH_HFI_PORT="${FF_CABLE_HEALTH_REPORT_DIR}/${hfi_port_dir}/" + mkdir -p ${FF_CABLE_HEALTH_REPORT_DIR_WITH_HFI_PORT} + /usr/sbin/opareport -h $hfi -p $port -o cablehealth 2>/dev/null>${FF_CABLE_HEALTH_REPORT_DIR_WITH_HFI_PORT}/cablehealth$(date "+%Y%m%d%H%M%S").csv + fi + fi + fi + done +fi + +if [ $ff_available = "y" ] && [ -e "${FF_CABLE_HEALTH_REPORT_DIR}" ] +then + echo "Copying all Cable Health Reports" + cp -p -r ${FF_CABLE_HEALTH_REPORT_DIR} /$dir/ 2>/dev/null +fi + +cd / +files="$dir" +for f in var/log/opa* var/log/ics_* var/log/messages* var/log/ksyms.* var/log/boot* etc/*release* etc/sysconfig/ipoib.cfg* etc/opa etc/modules.conf* etc/modprobe.conf* etc/sysconfig/network-scripts/ifcfg* etc/dapl/ibhosts etc/hosts etc/sysconfig/boot etc/sysconfig/firstboot etc/dat.conf etc/sysconfig/network/ifcfg* etc/infiniband etc/sysconfig/*config etc/security etc/opa-fm/opafm.xml etc/sysconfig/iview_fm.config var/log/fm* var/log/sm* var/log/bm* var/log/pm* var/log/fe* var/log/opensm* var/log/ipath* etc/rc.d/rc.local etc/modprobe.d boot/grub/menu.lst boot/grub/grub.conf boot/grub2/grub.cfg boot/grub2/grubenv boot/grub2/device.map etc/grub*.conf etc/udev* etc/opensm etc/sysconfig/opensm etc/rdma/* etc/modprobe.d/* etc/dracut.conf.d/* etc/nsswitch.conf etc/sysconfig/irqbalance +do + if [ -e "$f" ] + then + files="$files $f" + fi +done +if [ -e /usr/bin/opaxmlextract ] +then + for f in $(opaxmlextract -H -e LogFile < /etc/opa-fm/opafm.xml 2>/dev/null) + do + case "$f" in + /var/log/fm*|/var/log/sm*|/var/log/bm*|/var/log/pm*|/var/log/fe*) + >/dev/null;; + *) + if [ -e "$f" ] + then + files="$files $(echo $f|sed -e 's|^/||')" + fi;; + esac + done +fi + +for f in usr/local/src/mpi_apps/core* usr/src/opa/mpi_apps/core* usr/src/opa/shmem_apps/core* +do + if [ -e "$f" ] + then + files="$files $f" + fi +done +if [ "$ff_available" = y -a -d "$FF_MPI_APPS_DIR" ] +then + apps_dir=$(echo $FF_MPI_APPS_DIR|sed -e 's|^/||') # drop leading / + for f in $apps_dir/core* + do + if [ -e "$f" ] + then + files="$files $f" + fi + done +fi + +if [ $detail -ge 4 -a "$ff_available" = y ] +then + if [ ! -d $FF_ANALYSIS_DIR/latest ] + then + rm -f $FF_ANALYSIS_DIR/opaallanalysis + mkdir -p $FF_ANALYSIS_DIR + baseline_opt="" + if [ ! -d $FF_ANALYSIS_DIR/baseline ] + then + echo "Performing Fabric Analysis Baseline ..." + baseline_opt="-b" + else + echo "Performing Fabric Analysis ..." + fi + /usr/sbin/opaallanalysis $baseline_opt > $FF_ANALYSIS_DIR/opaallanalysis 2>&1 + else + echo "Copying Fabric Analysis ..." + fi + files="$files $(echo $FF_ANALYSIS_DIR|sed -e 's|^/||')" +fi + +echo "Creating tar file $tar_file ..." +tar --format=gnu -czf $tar_file $files +retval=$? +rm -rf /$dir + +if [ $retval -ne 0 ] +then + echo "tar encountered an issue while generating the tarball. Please verify the tarball was created successfully, files that have changed are acceptable." >&2 +fi + +echo "Done." +echo +echo "Please include $tar_file with any problem reports to Customer Support" + +exit $retval diff --git a/OpenIb_Host/LINUX/opacapture.sh.base b/OpenIb_Host/LINUX/opacapture.sh.base new file mode 100755 index 0000000..59b583d --- /dev/null +++ b/OpenIb_Host/LINUX/opacapture.sh.base @@ -0,0 +1,576 @@ +#!/bin/bash +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2018, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] + +# Usage: opacapture output_file_name +# captures system information for IntelOPA problem reporting + +Usage_full() +{ + echo "Usage: opacapture [-d detail] output_tgz_file" >&2 + echo " or" >&2 + echo " opacapture --help" >&2 + echo " --help - produce full help text" >&2 + echo " -d detail - level of detail of capture" >&2 + echo " 1-Local 2-Fabric 3-Fabric+FDB 4-Analysis (default=1)" >&2 + echo "This will capture critical system information into a zipped tar file" >&2 + echo "The program will automatically append .tgz to the " >&2 + echo "if it does not already have a .tgz suffix" >&2 + echo "The resulting tar file should be sent to Customer Support along with any" 2>&1 + echo "IntelOPA problem report regarding this system" >&2 +} + +Usage() +{ + Usage_full + exit 2 +} + +if [ `basename $0` = ics_capture ] +then + echo "warning: ics_capture is depricated, use opacapture" >&2 +fi + +if [ x"$1" = "x--help" ] +then + Usage_full + exit 0 +fi + + +if [ -f /usr/lib/opa/tools/ff_funcs ] +then + . /usr/lib/opa/tools/ff_funcs + ff_available=y +else + ff_available=n +fi + +if [ $ff_available = "y" ] +then + if [ -f $CONFIG_DIR/opa/opafastfabric.conf ] + then + . $CONFIG_DIR/opa/opafastfabric.conf + fi + + . /usr/lib/opa/tools/opafastfabric.conf.def +fi + +detail=1 + +while getopts d: param +do + case $param in + d) + detail="$OPTARG";; + ?) + Usage;; + esac +done +shift $((OPTIND -1)) + +if [ $# != 1 ] +then + Usage +fi + +if [ `id -u` -ne 0 ] +then + echo "This must be run as user root" >&2 + Usage +fi + +if [ x`expr "$1" : '\(/\).*'` != x'/' ] +then + # relative path + tar_file=`pwd`/$1 +else + # absolute path + tar_file=$1 +fi + +# append .tgz suffix if not already present +if [ x$(expr "$tar_file" : '.*\(\.tgz\)') != x'.tgz' ] +then + tar_file="$tar_file.tgz" +fi + +dir=tmp/capture$$ +rm -rf /$dir +mkdir /$dir + +echo "Capture Info: Detail: $detail; Date: $(date)" >> /$dir/capture_info + +echo "Getting software and firmware version information ..." +echo "[ICS VERSION STRING: unknown]" > /$dir/sw_version +uname -a > /$dir/os_version +# we use query format so we can get ARCH information +rpm --queryformat '[%{NAME}-%{VERSION}-%{RELEASE}.%{ARCH}\n]' -qa > /$dir/rpms.detailed +# get simple version just to be safe +rpm -qa > /$dir/rpms + +sha256sum /usr/lib/opa-fm/runtime/sm > /$dir/sha256sums +sha256sum /usr/lib/opa-fm/runtime/fe >> /$dir/sha256sums + +echo "Capturing FM binaries and debuginfo if available" +rpm -q opa-fm-debuginfo > /dev/null 2>&1 +if [ $? -eq 0 ]; then + debuginfofiles=$(rpm -ql opa-fm-debuginfo | xargs -I% bash -c "if [ -f % ]; then echo %; fi") + tar -zcf /$dir/opa-fm-debuginfo.tgz $debuginfofiles > /dev/null 2>&1 + unset debuginfofiles +fi +tar -zcf /$dir/opa-fm-bins.tgz /usr/lib/opa-fm/runtime/ > /dev/null 2>&1 + +# Finding the PCI devices +for fw in `lspci -n | grep "8086:24f0"` +do + # Just get the PCI info for now... + echo "$fw" >> /$dir/fw_info +done + +opahfirev > /$dir/opahfirev 2>&1 + +echo "Capturing Firmware info if available" +type hfi1_eprom > /dev/null 2>&1 +if [ $? -eq 0 ]; then + hfi1_eprom -d all -V > /$dir/uefi_version 2>&1 +fi + +type opatmmtool > /dev/null 2>&1 +if [ $? -eq 0 ]; then + opatmmtool 2>/dev/null 1>/dev/null + tmm=$? + if [ $tmm -ne 3 ] + then + echo "Getting TMM information..." + opatmmtool -v status > /$dir/f4status 2>&1 + opatmmtool -f /$dir/f4otpdump dumpotp 2>&1 + fi +fi + +echo "Obtaining OS configuration ..." +# get library config +ldconfig -p > /$dir/ldconfig +# get current runlevel +who -r > /$dir/who_r 2>/dev/null # not available on all OSs +runlevel > /$dir/runlevel # not available on all OSs +# get service startup configuration +if [ $(command -v systemctl) ]; then + systemctl list-unit-files > /$dir/chkconfig.systemd +fi +chkconfig --list > /$dir/chkconfig 2>/dev/null +ulimit -a > /$dir/ulimit +uptime > /$dir/uptime + +echo "Obtaining dmesg logs ..." +dmesg -T > /$dir/dmesg + +echo "Obtaining present process and module list ..." +lsmod > /$dir/lsmod 2>&1 +depmod -a 2>&1 +cp -p /lib/modules/`uname -r`/modules.dep /$dir/modules.dep +ps -welf > /$dir/ps 2>&1 + +echo "Obtaining module info for hfi1 ..." +modinfo hfi1 > /$dir/modinfo_hfi1 2>&1 + +echo "Obtaining PCI device list ..." +lspci -vvv -xxxx > /$dir/lspci 2>&1 +ls -l /dev/ipath* /dev/hfi* /dev/infiniband > /$dir/lsdev + +echo "Obtaining processor information ..." +cpucount=$(grep -c processor /proc/cpuinfo) +cpupower -c 0-$((cpucount - 1)) frequency-info > /$dir/cpu-frequency-info 2>&1 +grep . /sys/devices/system/cpu/cpu*/cpufreq/scaling* > /$dir/cpu-scaling-info 2>&1 +grep . /sys/devices/system/cpu/intel_pstate/* > /$dir/cpu-intel_pstate 2>&1 +unset cpucount + +lscpu > /$dir/lscpu 2>&1 +lscpu --extended=CPU,CORE,SOCKET,NODE,BOOK,DRAWER,CACHE,POLARIZATION,ADDRESS,CONFIGURED > /$dir/lscpu-extended 2>&1 + +echo "Obtaining environment variables ..." +env > /$dir/env 2>&1 + +echo "Obtaining network interfaces ..." +ip addr show > /$dir/ifconfig 2>&1 + +echo "Obtaining DMI information ..." +dmidecode > /$dir/dmidecode 2>&1 + +echo "Obtaining Shared Memory information ..." +sysctl -a > /$dir/sysctl 2>&1 +sysctl -a 2>/dev/null | grep kernel.shm > /$dir/shm 2>&1 +ls -d /dev/shm >> /$dir/shm 2>&1 +ls -lR /dev/shm >> /$dir/shm 2>&1 + +echo "Obtaining OmniPath information ..." + +# concise port statistics +opainfo > /$dir/opainfo 2>&1 +opainfo -o stats > /$dir/opainfo-stats 2>&1 +opainfo -o info > /$dir/opainfo-info 2>&1 + +echo "Obtaining MPI configuration ..." +if type mpi-selector >/dev/null 2>/dev/null +then + mpi-selector --list > /$dir/mpi-selector-list + mpi-selector --system --query > /$dir/mpi-selector-system + mpi-selector --user --query > /$dir/mpi-selector-user +fi + +mkdir /$dir/proc +echo "Copying configuration and statistics for OPA drivers from /proc ..." +for proc_file in cmdline cpuinfo ksyms meminfo mtrr modules net/arp net/dev net/dev_mcast net/route net/rt_cache net/vlan pci interrupts devices filesystems iomem ioports slabinfo version uptime scsi iba driver/ics_dsc driver/ipoib driver/sdp driver/rds irq acpi/processor +do + if [ -e /proc/$proc_file ] + then + cp -p -r /proc/$proc_file /$dir/proc + fi +done +for proc_file in `ps -eo pid` +do + if [ -e /proc/$proc_file/stack ] + then + mkdir -p /$dir/proc/$proc_file + cp -p -r /proc/$proc_file/stack /$dir/proc/$proc_file + fi +done + +echo "Obtaining additional CPU info..." +cpupower frequency-info > /$dir/cpupower-freq-info + +# Check if HFI driver debug data dir) is present; log only if present +HFI_DEBUGDIR="/sys/kernel/debug/hfi1" +if [ -d ${HFI_DEBUGDIR} ] +then + #hfi1stats requires the existance of ${HFI_DEBUGDIR} + echo "Obtaining HFI statistics ..." + hfi1stats > /$dir/hfi1stats 2>&1 + + mkdir -p /${dir}${HFI_DEBUGDIR} + echo "Copying kernel debug information from ${HFI_DEBUGDIR}..." + cp -p -r ${HFI_DEBUGDIR}/* /${dir}/${HFI_DEBUGDIR} 2>/dev/null +fi + +# Check if IPOIB debug data dir is present; log if present +IPOIB_DEBUGDIR="/sys/kernel/debug/ipoib" +if [ -d ${IPOIB_DEBUGDIR} ] +then + echo "Obtaining IPOIB debug information from ${IPOIB_DEBUGDIR}..." + mkdir -p /${dir}${IPOIB_DEBUGDIR} + echo "Copying IPOIB debug information from ${IPOIB_DEBUGDIR}..." + cp -r ${IPOIB_DEBUGDIR}/* /${dir}/${IPOIB_DEBUGDIR} 2>/dev/null +fi + +# Check if side channel security issue mitigation information files are +# present; log if present +SIDE_CHANNEL_MITIGATION_INFO="/sys/devices/system/cpu/vulnerabilities" +if [ -d ${SIDE_CHANNEL_MITIGATION_INFO} ] +then + echo "Obtaining side channel security issue mitigation information from ${SIDE_CHANNEL_MITIGATION_INFO}" + mkdir -p /${dir}${SIDE_CHANNEL_MITIGATION_INFO} + echo "Copying side channel security issue mitigation information from ${SIDE_CHANNEL_MITIGATION_INFO}..." + cp -r ${SIDE_CHANNEL_MITIGATION_INFO}/* /${dir}${SIDE_CHANNEL_MITIGATION_INFO} 2>/dev/null +fi + +# Check if side channel security issue mitigation kernel configuration files are +# present; log if present +KERNEL_CONFIG_LOC=/sys/kernel/debug/x86 +SIDE_CHANNEL_MITIGATION_KERNEL_CONFIG_FILES="ibpb_enabled ibrs_enabled pti_enabled retp_enabled" +for fname in ${SIDE_CHANNEL_MITIGATION_KERNEL_CONFIG_FILES} +do + if [ -e ${KERNEL_CONFIG_LOC}/${fname} ] + then + echo "Obtaining kernel configuration file ${KERNEL_CONFIG_LOC}/${fname}" + if [ ! -d /${dir}${KERNEL_CONFIG_LOC} ] + then + mkdir -p /${dir}${KERNEL_CONFIG_LOC} + fi + echo "Copying kernel configuration file ${KERNEL_CONFIG_LOC}/${fname}..." + cp ${KERNEL_CONFIG_LOC}/${fname} /${dir}${KERNEL_CONFIG_LOC} 2>/dev/null + fi +done + +mkdir -p /$dir/sys/class +if [ -e /sys/class/infiniband ] +then + echo "Copying configuration and statistics for ib_ drivers from /sys ..." + cp -p -r /sys/class/*infiniband* /$dir/sys/class 2>/dev/null + mkdir -p /$dir/sys/class/infiniband + for f in /sys/class/infiniband/* + do + if [ -h $f ] + then + rm -f /$dir/$f + cp -p -r $f/ /$dir/sys/class/infiniband/ 2>/dev/null + if [ -h $f/device ] + then + dev=`basename $f` + unit=`expr $dev : 'hfi1_\(.*\)'` + if [ ! -z "$unit" ] + then + echo " Getting statedump for $dev ..." + echo -e "unit $unit\nstate save hw /$dir/opa${dev}.dump"|hfidiags -s - > /$dir/opa${dev}.dump.res 2>&1 + fi + # rm -f /$dir/$f/device + # mkdir -p /$dir/sys/class/infiniband/$dev/ 2>/dev/null + # cp -p -r $f/device/ /$dir/sys/class/infiniband/$dev/ 2>/dev/null + fi + fi + done +fi + +if [ -e /sys/class/scsi_host ] +then + cp -p -r /sys/class/scsi_host /$dir/sys/class 2>/dev/null +fi +if [ -e /sys/class/scsi_device ] +then + cp -p -r /sys/class/scsi_device /$dir/sys/class 2>/dev/null +fi + +if [ -e /sys/class/net/ ] +then + echo "Copying interface information for ipoib" + mkdir -p /$dir/sys/class/net + cp -r /sys/class/net/ /$dir/sys/class 2>/dev/null + for f in /sys/class/net/* + do + if [ -h $f ] + then + rm -f /$dir/$f + cp -r $f/ /$dir/sys/class/net/ 2>/dev/null + if [ -h $f/device ] + then + iface=`basename $f` + rm -f /$dir/$f/device + mkdir -p /$dir/sys/class/net/$iface/ 2>/dev/null + cp -r $f/device/ /$dir/sys/class/net/$iface/ 2>/dev/null + fi + fi + done +fi + +if [ -e /sys/module ] +then + echo "Copying configuration and statistics for OPA from /sys/module ..." + cp -p -r /sys/module /$dir/sys 2>/dev/null +fi + +if [ -f /usr/lib/opa-fm/bin/fm_capture ] +then + echo "Gathering Host FM Information ..." + (cd /$dir; /usr/lib/opa-fm/bin/fm_capture) +fi + +if [ -f /usr/bin/opa_osd_dump ] +then + echo "Gathering Distributed SA data..." + opa_osd_dump > /$dir/opa_osd_dump 2>&1 +fi + +if [ $detail -ge 2 ] +then + mkdir -p /$dir/fabric + cd /$dir/fabric/ + if [ "$ff_available" = y ] + then + check_ports_args opacapture + else + PORTS='0:0' + if [ $detail -ge 3 ] + then + echo "Warning: opacapture detail=$detail but FastFabric not available" + fi + fi + + if [ $detail -ge 3 -a "$ff_available" = y ] + then + echo "Gathering Fabric-Level Information with FDBs ..." + else + echo "Gathering Fabric-Level Information ..." + fi + + for hfi_port in $PORTS + do + hfi=$(expr $hfi_port : '\([0-9]*\):[0-9]*') + port=$(expr $hfi_port : '[0-9]*:\([0-9]*\)') + if [ "$hfi" = "" -o "$port" = "" ] + then + echo "opacapture: Error: Invalid port specification: $hfi_port" >&2 + continue + fi + ## fixup name so winzip won't complain + hfi_port_dir=${hfi}_${port} + + # make hfi_port directory + mkdir $hfi_port_dir + + # opasaquery doesn't require FF available + /usr/sbin/opasaquery -h $hfi -p $port -o node > $hfi_port_dir/nodes 2>&1 + /usr/sbin/opafabricinfo -p $hfi_port > $hfi_port_dir/opafabricinfo 2>&1 + + if [ "$ff_available" = y ] + then + router_opt="" + + if [ $port -eq 0 ] + then + port_opt="-h $hfi" + else + port_opt="-h $hfi -p $port" + fi + + # determine if port is management enabled + /usr/sbin/opasmaquery $port_opt -o pkey 2>/dev/null|grep -q 0xffff + mgmt_disabled=$? + + # add router table information to snapshot report + if [ $detail -gt 2 ] + then + router_opt="-r" + fi + + if [ $mgmt_disabled -eq 0 ] + then + /usr/sbin/opareport $port_opt -o snapshot -s -V $router_opt > $hfi_port_dir/snapshot.xml 2> $hfi_port_dir/snapshot.xml.err + /usr/sbin/opareport $port_opt -o snapshot -m -M -s -V $router_opt > $hfi_port_dir/snapshot_direct.xml 2> $hfi_port_dir/snapshot_direct.xml.err + /usr/sbin/opareport -o links -X $hfi_port_dir/snapshot.xml > $hfi_port_dir/fabric_links 2>&1 + /usr/sbin/opareport -o comps -X $hfi_port_dir/snapshot.xml > $hfi_port_dir/fabric_comps 2>&1 + /usr/sbin/opareport -o errors -X $hfi_port_dir/snapshot.xml > $hfi_port_dir/fabric_errors 2>&1 + /usr/sbin/opareport -o extlinks -X $hfi_port_dir/snapshot.xml > $hfi_port_dir/fabric_extlinks 2>&1 + /usr/sbin/opareport -o slowlinks -X $hfi_port_dir/snapshot.xml > $hfi_port_dir/fabric_slowlinks 2>&1 + /usr/sbin/opareport -o vfmember -V -d 4 > $hfi_port_dir/fabric_vfmember 2>&1 + fi + + if [ $detail -gt 2 ] + then + echo "Gathering Multicast Membership ..." + /usr/sbin/opashowmc -p $hfi:$port > $hfi_port_dir/fabric_showmc 2>&1 + # create cable health report directory and generate report + if [ $ff_available = "y" ] && [ -e "${FF_CABLE_HEALTH_REPORT_DIR}" ] + then + echo "Gathering Cable Health Report ..." + FF_CABLE_HEALTH_REPORT_DIR_WITH_HFI_PORT="${FF_CABLE_HEALTH_REPORT_DIR}/${hfi_port_dir}/" + mkdir -p ${FF_CABLE_HEALTH_REPORT_DIR_WITH_HFI_PORT} + /usr/sbin/opareport -h $hfi -p $port -o cablehealth 2>/dev/null>${FF_CABLE_HEALTH_REPORT_DIR_WITH_HFI_PORT}/cablehealth$(date "+%Y%m%d%H%M%S").csv + fi + fi + fi + done +fi + +if [ $ff_available = "y" ] && [ -e "${FF_CABLE_HEALTH_REPORT_DIR}" ] +then + echo "Copying all Cable Health Reports" + cp -p -r ${FF_CABLE_HEALTH_REPORT_DIR} /$dir/ 2>/dev/null +fi + +cd / +files="$dir" +for f in var/log/opa* var/log/ics_* var/log/messages* var/log/ksyms.* var/log/boot* etc/*release* etc/sysconfig/ipoib.cfg* etc/opa etc/modules.conf* etc/modprobe.conf* etc/sysconfig/network-scripts/ifcfg* etc/dapl/ibhosts etc/hosts etc/sysconfig/boot etc/sysconfig/firstboot etc/dat.conf etc/sysconfig/network/ifcfg* etc/infiniband etc/sysconfig/*config etc/security etc/opa-fm/opafm.xml etc/sysconfig/iview_fm.config var/log/fm* var/log/sm* var/log/bm* var/log/pm* var/log/fe* var/log/opensm* var/log/ipath* etc/rc.d/rc.local etc/modprobe.d boot/grub/menu.lst boot/grub/grub.conf boot/grub2/grub.cfg boot/grub2/grubenv boot/grub2/device.map etc/grub*.conf etc/udev* etc/opensm etc/sysconfig/opensm etc/rdma/* etc/modprobe.d/* etc/dracut.conf.d/* etc/nsswitch.conf etc/sysconfig/irqbalance +do + if [ -e "$f" ] + then + files="$files $f" + fi +done +if [ -e /usr/bin/opaxmlextract ] +then + for f in $(opaxmlextract -H -e LogFile < /etc/opa-fm/opafm.xml 2>/dev/null) + do + case "$f" in + /var/log/fm*|/var/log/sm*|/var/log/bm*|/var/log/pm*|/var/log/fe*) + >/dev/null;; + *) + if [ -e "$f" ] + then + files="$files $(echo $f|sed -e 's|^/||')" + fi;; + esac + done +fi + +for f in usr/local/src/mpi_apps/core* usr/src/opa/mpi_apps/core* usr/src/opa/shmem_apps/core* +do + if [ -e "$f" ] + then + files="$files $f" + fi +done +if [ "$ff_available" = y -a -d "$FF_MPI_APPS_DIR" ] +then + apps_dir=$(echo $FF_MPI_APPS_DIR|sed -e 's|^/||') # drop leading / + for f in $apps_dir/core* + do + if [ -e "$f" ] + then + files="$files $f" + fi + done +fi + +if [ $detail -ge 4 -a "$ff_available" = y ] +then + if [ ! -d $FF_ANALYSIS_DIR/latest ] + then + rm -f $FF_ANALYSIS_DIR/opaallanalysis + mkdir -p $FF_ANALYSIS_DIR + baseline_opt="" + if [ ! -d $FF_ANALYSIS_DIR/baseline ] + then + echo "Performing Fabric Analysis Baseline ..." + baseline_opt="-b" + else + echo "Performing Fabric Analysis ..." + fi + /usr/sbin/opaallanalysis $baseline_opt > $FF_ANALYSIS_DIR/opaallanalysis 2>&1 + else + echo "Copying Fabric Analysis ..." + fi + files="$files $(echo $FF_ANALYSIS_DIR|sed -e 's|^/||')" +fi + +echo "Creating tar file $tar_file ..." +tar --format=gnu -czf $tar_file $files +retval=$? +rm -rf /$dir + +if [ $retval -ne 0 ] +then + echo "tar encountered an issue while generating the tarball. Please verify the tarball was created successfully, files that have changed are acceptable." >&2 +fi + +echo "Done." +echo +echo "Please include $tar_file with any problem reports to Customer Support" + +exit $retval diff --git a/OpenIb_Host/Makefile b/OpenIb_Host/Makefile new file mode 100644 index 0000000..64047e5 --- /dev/null +++ b/OpenIb_Host/Makefile @@ -0,0 +1,230 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** +# Makefile for OPENIB_HOST Project + +# Include Make Control Settings +include $(TL_DIR)/$(PROJ_FILE_DIR)/Makesettings.project + +# default target for project level makefile is stage +stage:: +#prepfiles:: prepfiles_global +clobber:: clobber_global clobber_tools + +ALL:: tools + +BSP_SPECIFIC_DIRS= + +#=============================================================================# +# Definitions: +#-----------------------------------------------------------------------------# + +# Name of SubProjects +DS_SUBPROJECTS = +# name of executable or downloadable image +EXECUTABLE = # OPENIB_FF$(EXE_SUFFIX) +# list of sub directories to build + + +DIRS = \ + $(TL_DIR)/Makerules \ + $(TL_DIR)/IbAccess \ + $(TL_DIR)/opamgt \ + $(TL_DIR)/Xml \ + $(TL_DIR)/IbaTools \ + $(TL_DIR)/MpiApps \ + $(TL_DIR)/Iih \ + $(TL_DIR)/TestTools \ + $(TL_DIR)/IbPrint \ + $(TL_DIR)/Topology \ + $(TL_DIR)/opasadb \ + $(TL_DIR)/Lsf \ + $(TL_DIR)/Moab \ + $(TL_DIR)/Dsap \ + $(TL_DIR)/Esm/ib/src/linux/log/usr \ + $(TL_DIR)/Esm/ib/src/ibaccess \ + $(TL_DIR)/Esm/ib/src/cs \ + $(TL_DIR)/Esm/ib/src/config \ + $(TL_DIR)/Esm/ib/src/linux/startup/fm_config \ + $(BUILD_TARGET_OS) + + # DISABLED - MWHEINZ + #$(TL_DIR)/L8sim + + +# C files (.c) +CFILES = \ + # Add more c files here +# C++ files (.cpp) +CCFILES = \ + # Add more cpp files here +# lex files (.lex) +LFILES = \ + # Add more lex files here +# archive library files (basename, $ARFILES will add MOD_LIB_DIR/prefix and suffix) +LIBFILES = +# Windows Resource Files (.rc) +RSCFILES = +# Windows IDL File (.idl) +IDLFILE = +# Windows Linker Module Definitions (.def) file for dll's +DEFFILE = +# targets to build during INCLUDES phase (add public includes here) +INCLUDE_TARGETS = \ + # Add more h hpp files here +# Non-compiled files +MISC_FILES = +# all source files +SOURCES = $(CFILES) $(CCFILES) $(LFILES) $(RSCFILES) $(IDLFILE) +# Source files to include in DSP File +DSP_SOURCES = $(INCLUDE_TARGETS) $(SOURCES) $(MISC_FILES) \ + $(RSCFILES) $(DEFFILE) $(MAKEFILE) Makerules.project +# all object files +OBJECTS = $(CFILES:.c=$(OBJ_SUFFIX)) $(CCFILES:.cpp=$(OBJ_SUFFIX)) \ + $(LFILES:.lex=$(OBJ_SUFFIX)) +RSCOBJECTS = $(RSCFILES:.rc=$(RES_SUFFIX)) +# targets to build during LIBS phase +LIB_TARGETS_IMPLIB = +LIB_TARGETS_ARLIB = +LIB_TARGETS_EXP = $(LIB_TARGETS_IMPLIB:$(ARLIB_SUFFIX)=$(EXP_SUFFIX)) +LIB_TARGETS_MISC = +# targets to build during CMDS phase +CMD_TARGETS_SHLIB = +CMD_TARGETS_EXE = $(EXECUTABLE) +CMD_TARGETS_MISC = +# files to remove during clean phase +CLEAN_TARGETS_MISC = +CLEAN_TARGETS = $(OBJECTS) $(RSCOBJECTS) $(IDL_TARGETS) $(CLEAN_TARGETS_MISC) +# other files to remove during clobber phase +CLOBBER_TARGETS_MISC= update_opa_spec.sh ff_build.sh $(TL_DIR)/Fd/buildFeatureDefs +# sub-directory to install to within bin +BIN_SUBDIR = +# sub-directory to install to within include +INCLUDE_SUBDIR = + +# Additional Settings +#CLOCALDEBUG = User defined C debugging compilation flags [Empty] +#CCLOCALDEBUG = User defined C++ debugging compilation flags [Empty] +#CLOCAL = User defined C flags for compiling [Empty] +#CCLOCAL = User defined C++ flags for compiling [Empty] +#BSCLOCAL = User flags for Browse File Builder [Empty] +#DEPENDLOCAL = user defined makedepend flags [Empty] +#LINTLOCAL = User defined lint flags [Empty] +#LOCAL_INCLUDE_DIRS = User include directories to search for C/C++ headers [Empty] +#LDLOCAL = User defined C flags for linking [Empty] +#IMPLIBLOCAL = User flags for Object Lirary Manager [Empty] +#MIDLLOCAL = User flags for IDL compiler [Empty] +#RSCLOCAL = User flags for resource compiler [Empty] +#LOCALDEPLIBS = User libraries to include in dependencies [Empty] +#LOCALLIBS = User libraries to use when linking [Empty] +# (in addition to LOCALDEPLIBS) +#LOCAL_LIB_DIRS = User library directories for libpaths [Empty] + +LOCALDEPLIBS = + +# Include Make Rules definitions and rules +include $(TL_DIR)/$(PROJ_FILE_DIR)/Makerules.project + +#=============================================================================# +# Overrides: +#-----------------------------------------------------------------------------# +#CCOPT = # C++ optimization flags, default lets build config decide +#COPT = # C optimization flags, default lets build config decide +#SUBSYSTEM = Subsystem to build for (none, console or windows) [none] +# (Windows Only) +#USEMFC = How Windows MFC should be used (none, static, shared, no_mfc) [none] +# (Windows Only) +#=============================================================================# + +#=============================================================================# +# Rules: +#-----------------------------------------------------------------------------# +# process Sub-directories +include $(TL_DIR)/Makerules/Maketargets.toplevel + +# build cmds and libs +include $(TL_DIR)/Makerules/Maketargets.build + +# install for includes, libs and cmds phases +include $(TL_DIR)/Makerules/Maketargets.install + +# install for stage phase +include $(TL_DIR)/Makerules/Maketargets.stage +STAGE:: +ifeq "$(RELEASE_TAG)" "" + $(CONVERT_RELEASETAG) $(MODULEVERSION) > $(PROJ_STAGE_DIR)/version +else + $(CONVERT_RELEASETAG) $(RELEASE_TAG) > $(PROJ_STAGE_DIR)/version +endif + echo $(BUILD_TARGET) > $(PROJ_STAGE_DIR)/arch + echo $(BUILD_TARGET_OS_VENDOR) > $(PROJ_STAGE_DIR)/distro + echo $(BUILD_TARGET_OS_VENDOR_VERSION) > $(PROJ_STAGE_DIR)/distro_version + echo $(BUILD_TARGET_OS_ID) > $(PROJ_STAGE_DIR)/os_id + +# put version number into a file to facilitate rpm construction +# presently only INSTALL allows dynamic version patch +prepfiles:: check_env +ifeq "$(RELEASE_TAG)" "" + $(CONVERT_RELEASETAG) $(MODULEVERSION) > $(PROJ_STAGE_DIR)/version +else + $(CONVERT_RELEASETAG) $(RELEASE_TAG) > $(PROJ_STAGE_DIR)/version +endif + cd $(PROJ_STAGE_DIR) && find . -print| $(PREP) + cd $(PROJ_STAGE_DIR) && $(PATCH_VERSION) -m % -n `$(CONVERT_RELEASETAG) $(RELEASE_TAG)` $(RELEASE_TAG) INSTALL + cd $(PROJ_STAGE_DIR) && [ ! -e fastfabric/opafastfabric ] || $(PATCH_VERSION) -m % -n `$(CONVERT_RELEASETAG) $(RELEASE_TAG)` $(RELEASE_TAG) fastfabric/opahostadmin fastfabric/opachassisadmin fastfabric/opaswitchadmin fastfabric/opafastfabric + cd $(PROJ_STAGE_DIR) && $(PATCH_BRAND) -m % "$(BUILD_BRAND)" INSTALL + cd $(PROJ_STAGE_DIR) && [ ! -e fastfabric/opafastfabric ] || $(PATCH_BRAND) -m % "$(BUILD_BRAND)" fastfabric/opafastfabric + +# OS specific packaging step +# package builds standard package +package: + cd $(BUILD_TARGET_OS) && $(MAKE) $(MFLAGS) $@ +.PHONY: package + +vars_include: vars_include_global + +final_package: + cd $(BUILD_TARGET_OS) && $(MAKE) $(MFLAGS) $@ +.PHONY: final_package + +# Unit test execution +#include $(TL_DIR)/Makerules/Maketargets.runtest + +tools: $(TL_DIR)/Fd/buildFeatureDefs + mkdir -p $(COMN_LIB_DIRS) $(GLOBAL_SHLIB_DIR) + cd $(TL_DIR)/MakeTools && $(MAKE) $(MFLAGS) +clobber_tools: + cd $(TL_DIR)/MakeTools && $(MAKE) $(MFLAGS) clobber +CLOBBER:: + rm -f packaged_files dist_files + +#=============================================================================# + +#=============================================================================# +# DO NOT DELETE THIS LINE -- make depend depends on it. +#=============================================================================# diff --git a/OpenIb_Host/Makefile.tests b/OpenIb_Host/Makefile.tests new file mode 100644 index 0000000..aea6544 --- /dev/null +++ b/OpenIb_Host/Makefile.tests @@ -0,0 +1,213 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** +# Makefile for OPENIB_HOST Project - tests portion + +# Include Make Control Settings +include $(TL_DIR)/$(PROJ_FILE_DIR)/Makesettings.project + +# default target for project level makefile is stage +stage:: +#prepfiles:: prepfiles_global +clobber:: clobber_global clobber_tools +ALL:: tools + +BSP_SPECIFIC_DIRS= + +#=============================================================================# +# Definitions: +#-----------------------------------------------------------------------------# + +# Name of SubProjects +DS_SUBPROJECTS = +# name of executable or downloadable image +EXECUTABLE = # OPENIB_FF_TESTS$(EXE_SUFFIX) +# list of sub directories to build +DIRS = \ + $(TL_DIR)/Makerules \ + $(TL_DIR)/IbAccess \ + $(TL_DIR)/opamgt \ + $(TL_DIR)/Xml \ + $(TL_DIR)/Topology \ + $(TL_DIR)/SrpTools \ + $(TL_DIR)/InicTools \ + $(TL_DIR)/Tests \ + $(TL_DIR)/IbaTests \ + $(TL_DIR)/MpiApps + + # DISABLED - MWHEINZ + #$(TL_DIR)/L8sim + + +# C files (.c) +CFILES = \ + # Add more c files here +# C++ files (.cpp) +CCFILES = \ + # Add more cpp files here +# lex files (.lex) +LFILES = \ + # Add more lex files here +# archive library files (basename, $ARFILES will add MOD_LIB_DIR/prefix and suffix) +LIBFILES = +# Windows Resource Files (.rc) +RSCFILES = +# Windows IDL File (.idl) +IDLFILE = +# Windows Linker Module Definitions (.def) file for dll's +DEFFILE = +# targets to build during INCLUDES phase (add public includes here) +INCLUDE_TARGETS = \ + # Add more h hpp files here +# Non-compiled files +MISC_FILES = +# all source files +SOURCES = $(CFILES) $(CCFILES) $(LFILES) $(RSCFILES) $(IDLFILE) +# Source files to include in DSP File +DSP_SOURCES = $(INCLUDE_TARGETS) $(SOURCES) $(MISC_FILES) \ + $(RSCFILES) $(DEFFILE) $(MAKEFILE) Makerules.project +# all object files +OBJECTS = $(CFILES:.c=$(OBJ_SUFFIX)) $(CCFILES:.cpp=$(OBJ_SUFFIX)) \ + $(LFILES:.lex=$(OBJ_SUFFIX)) +RSCOBJECTS = $(RSCFILES:.rc=$(RES_SUFFIX)) +# targets to build during LIBS phase +LIB_TARGETS_IMPLIB = +LIB_TARGETS_ARLIB = +LIB_TARGETS_EXP = $(LIB_TARGETS_IMPLIB:$(ARLIB_SUFFIX)=$(EXP_SUFFIX)) +LIB_TARGETS_MISC = +# targets to build during CMDS phase +CMD_TARGETS_SHLIB = +CMD_TARGETS_EXE = $(EXECUTABLE) +CMD_TARGETS_MISC = +# files to remove during clean phase +CLEAN_TARGETS_MISC = +CLEAN_TARGETS = $(OBJECTS) $(RSCOBJECTS) $(IDL_TARGETS) $(CLEAN_TARGETS_MISC) +# other files to remove during clobber phase +CLOBBER_TARGETS_MISC= +# sub-directory to install to within bin +BIN_SUBDIR = +# sub-directory to install to within include +INCLUDE_SUBDIR = + +# Additional Settings +#CLOCALDEBUG = User defined C debugging compilation flags [Empty] +#CCLOCALDEBUG = User defined C++ debugging compilation flags [Empty] +#CLOCAL = User defined C flags for compiling [Empty] +#CCLOCAL = User defined C++ flags for compiling [Empty] +#BSCLOCAL = User flags for Browse File Builder [Empty] +#DEPENDLOCAL = user defined makedepend flags [Empty] +#LINTLOCAL = User defined lint flags [Empty] +#LOCAL_INCLUDE_DIRS = User include directories to search for C/C++ headers [Empty] +#LDLOCAL = User defined C flags for linking [Empty] +#IMPLIBLOCAL = User flags for Object Lirary Manager [Empty] +#MIDLLOCAL = User flags for IDL compiler [Empty] +#RSCLOCAL = User flags for resource compiler [Empty] +#LOCALDEPLIBS = User libraries to include in dependencies [Empty] +#LOCALLIBS = User libraries to use when linking [Empty] +# (in addition to LOCALDEPLIBS) +#LOCAL_LIB_DIRS = User library directories for libpaths [Empty] + +LOCALDEPLIBS = + +# Include Make Rules definitions and rules +include $(TL_DIR)/Makerules.project + +#=============================================================================# +# Overrides: +#-----------------------------------------------------------------------------# +#CCOPT = # C++ optimization flags, default lets build config decide +#COPT = # C optimization flags, default lets build config decide +#SUBSYSTEM = Subsystem to build for (none, console or windows) [none] +# (Windows Only) +#USEMFC = How Windows MFC should be used (none, static, shared, no_mfc) [none] +# (Windows Only) +#=============================================================================# + +#=============================================================================# +# Rules: +#-----------------------------------------------------------------------------# +# process Sub-directories +include $(TL_DIR)/Makerules/Maketargets.toplevel + +# build cmds and libs +include $(TL_DIR)/Makerules/Maketargets.build + +# install for includes, libs and cmds phases +include $(TL_DIR)/Makerules/Maketargets.install + +# install for stage phase +include $(TL_DIR)/Makerules/Maketargets.stage +STAGE:: +ifeq "$(RELEASE_TAG)" "" + $(CONVERT_RELEASETAG) $(MODULEVERSION) > $(PROJ_STAGE_DIR)/version +else + $(CONVERT_RELEASETAG) $(RELEASE_TAG) > $(PROJ_STAGE_DIR)/version +endif + echo $(BUILD_TARGET) > $(PROJ_STAGE_DIR)/arch + echo $(BUILD_TARGET_OS_VENDOR) > $(PROJ_STAGE_DIR)/distro + echo $(BUILD_TARGET_OS_VENDOR_VERSION) > $(PROJ_STAGE_DIR)/distro_version + echo $(BUILD_TARGET_OS_ID) > $(PROJ_STAGE_DIR)/os_id + +# put version number into a file to facilitate rpm construction +# presently only INSTALL allows dynamic version patch +prepfiles:: check_env +ifeq "$(RELEASE_TAG)" "" + $(CONVERT_RELEASETAG) $(MODULEVERSION) > $(PROJ_STAGE_DIR)/version +else + $(CONVERT_RELEASETAG) $(RELEASE_TAG) > $(PROJ_STAGE_DIR)/version +endif + cd $(PROJ_STAGE_DIR) && find . -print| $(PREP) + cd $(PROJ_STAGE_DIR) && $(PATCH_VERSION) -m % -n `$(CONVERT_RELEASETAG) $(RELEASE_TAG)` $(RELEASE_TAG) INSTALL + cd $(PROJ_STAGE_DIR) && [ ! -e fastfabric/opafastfabric ] || $(PATCH_VERSION) -m % -n `$(CONVERT_RELEASETAG) $(RELEASE_TAG)` $(RELEASE_TAG) fastfabric/opahostadmin fastfabric/opachassisadmin fastfabric/opaswitchadmin fastfabric/opafastfabric + cd $(PROJ_STAGE_DIR) && $(PATCH_BRAND) -m % "$(BUILD_BRAND)" INSTALL + cd $(PROJ_STAGE_DIR) && [ ! -e fastfabric/opafastfabric ] || $(PATCH_BRAND) -m % "$(BUILD_BRAND)" fastfabric/opafastfabric + +# OS specific packaging step +# package builds standard package +package: + cd $(BUILD_TARGET_OS) && $(MAKE) $(MFLAGS) $@ +.PHONY: package + +vars_include: vars_include_global + +# Unit test execution +#include $(TL_DIR)/Makerules/Maketargets.runtest + +tools: + mkdir -p $(COMN_LIB_DIRS) $(GLOBAL_SHLIB_DIR) + cd $(TL_DIR)/MakeTools && $(MAKE) $(MFLAGS) +clobber_tools: + cd $(TL_DIR)/MakeTools && $(MAKE) $(MFLAGS) clobber +CLOBBER:: + rm -f packaged_files dist_files + +#=============================================================================# + +#=============================================================================# +# DO NOT DELETE THIS LINE -- make depend depends on it. +#=============================================================================# diff --git a/OpenIb_Host/Makerules.project b/OpenIb_Host/Makerules.project new file mode 100755 index 0000000..add1f85 --- /dev/null +++ b/OpenIb_Host/Makerules.project @@ -0,0 +1,254 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** +## Rules for ALL_HOST project +#=============================================================================# +## Project Make Rules File +## ----------------------- +## +## All tools local makefiles should include this makerules file after its own +## local definitions section and before the local rules section. Use +## Makefile.template as a base makefile and modify the template according to +## your application needs. The template makefile includes this makerules file +## and this project makerules file includes the global makerules file. Any +## modifications to this makerules file or to local makefiles should be made +## in a portable fashion using 'ifdef' structures where necessary so that the +## same makefile can be used on multiple platforms. The main purpose of this +## include makerules file is for local variable definitions and rules which are +## specific to the project at hand. Global modifications should be made in the +## global makerules file and local items should be in the local makefile, not +## in this makerules file. Any modifications to the source should be made with +## portability in mind and should follow the embedded notations. Documentation +## is automatically generated from this makefile! Use the correct conventions +## for those items which should be documented. +## +## NOTE: This makefile inclusion (the global makerules, and the template +## makefile) depend on using the GNU version of make. GNU make must be +## installed on your system prior to using this makefile. +#=============================================================================# +## +#=============================================================================# +# The following list is the standard list of definitions which will be defined +# for all platforms. It consists of general and machine specific sections that +# contain many system parameters which may be used in a makefile. Please keep +# the list(s) in strictly aphabetical order to facilitate simple searches. +# +# See Makerules.global for the meaning of these flags +#-----------------------------------------------------------------------------# +# Common platform definitions: +#-----------------------------------------------------------------------------# + +# TBD code should be redone so that prepfiles can insert version string instead +# of using MODULEVERSION +ifeq "$(RELEASE_TAG)" "" +MODULEVERSION=$(shell $(PATCH_ENG_VERSION)) +else +MODULEVERSION=$(shell $(CONVERT_RELEASETAG) $(RELEASE_TAG)) +endif + +PROJ_DIR = $(GLOBAL_DIR) +PROJ_BIN_DIR = $(GLOBAL_BIN_DIR) +PROJ_DRIVER_BIN_DIR = $(GLOBAL_BIN_DIR) +PROJ_INCLUDE_DIR = $(GLOBAL_INCLUDE_DIR) +PROJ_LIB_DIR = $(GLOBAL_LIB_DIR) +PROJ_SHLIB_DIR = $(GLOBAL_SHLIB_DIR) +PROJ_SBR_DIR = $(GLOBAL_SBR_DIR) + +ifeq "$(RELEASE_TAG)" "" +# only use engineer's name for directory name (omit timestamp part), +# otherwise each partial build goes to a different place +STAGE_SUB_DIR = IntelOPA-Tools-FF.$(BUILD_TARGET_OS_ID).$(shell $(PATCH_ENG_VERSION)|cut -d"." -f1) +else +STAGE_SUB_DIR = IntelOPA-Tools-FF.$(BUILD_TARGET_OS_ID).$(MODULEVERSION) +endif +PROJ_STAGE_DIR = $(STAGE_DIR)/$(STAGE_SUB_DIR) +PROJ_STAGE_ETC_DIR = $(PROJ_STAGE_DIR)/etc +PROJ_STAGE_BIN_DIR = $(PROJ_STAGE_DIR)/bin +PROJ_STAGE_MAN_DIR = $(PROJ_STAGE_DIR)/man +PROJ_STAGE_INCLUDE_DIR = $(PROJ_STAGE_DIR)/include +PROJ_STAGE_TESTS_DIR = $(PROJ_STAGE_DIR)/Tests +PROJ_STAGE_SRC_DIR = $(PROJ_STAGE_DIR)/src +PROJ_STAGE_TESTS_BIN_DIR= $(PROJ_STAGE_DIR)/Tests/bin +#PROJ_STAGE_LIB_DIR = $(PROJ_STAGE_DIR)/bin/$(BUILD_TARGET)/$(BUILD_TARGET_OS_VERSION)/lib/$(BUILD_CONFIG) +PROJ_STAGE_LIB_DIR = $(PROJ_STAGE_DIR)/bin/$(BUILD_TARGET)/$(BUILD_TARGET_OS_VENDOR).$(BUILD_TARGET_OS_VENDOR_VERSION)/lib/$(BUILD_CONFIG) +PROJ_STAGE_SHLIB_DIR= $(PROJ_STAGE_LIB_DIR) +PROJ_STAGE_SBR_DIR = $(STAGE_SBR_DIR) +#PROJ_STAGE_DRIVER_BIN_DIR= $(PROJ_STAGE_DIR)/bin/$(BUILD_TARGET)/$(BUILD_TARGET_OS_VERSION)/$(BUILD_CONFIG) +#PROJ_STAGE_DRIVER_BIN_DIR= $(PROJ_STAGE_DIR)/bin/$(BUILD_TARGET)/$(BUILD_TARGET_OS_VERSION)/$(BUILD_CONFIG) +PROJ_STAGE_FASTFABRIC_DIR = $(PROJ_STAGE_DIR)/fastfabric +PROJ_STAGE_IBTOOLS_DIR = $(PROJ_STAGE_DIR)/fastfabric/tools +PROJ_STAGE_SAMPLES_DIR = $(PROJ_STAGE_DIR)/iba_samples +PROJ_STAGE_FIRMWARE_DIR = $(PROJ_STAGE_DIR)/Firmware +PROJ_STAGE_OPA_SA_DB_DIR = $(PROJ_STAGE_DIR)/opasadb +PROJ_STAGE_LSF_DIR = $(PROJ_STAGE_DIR)/Lsf +PROJ_STAGE_MOAB_DIR = $(PROJ_STAGE_DIR)/Moab +PROJ_STAGE_OPAMGT_DIR = $(PROJ_STAGE_DIR)/opamgt + +PROJ_INCLUDE_DIRS = $(COMN_INCLUDE_DIRS) +PROJ_LIB_DIRS = $(COMN_LIB_DIRS) +PROJDEPLIBS = +PROJLIBS = $(CCLIBS) + +BSCPROJ = + +# strict-prototypes - treat extern int foo() as function with no args +CPROJ = -DPRODUCT=$(PRODUCT) -DPRODUCT_$(PRODUCT) -DMODULEVERSION=$(MODULEVERSION) -DIB_STACK_OPENIB +# include buildFeatureDefs to let inplace build work for stream consistency +CPROJ += -include $(TL_DIR)/Fd/buildFeatureDefs +ifeq ($(__GNUC__),2) +CPROJ += -fstrict-prototypes +endif +CCPROJ = $(CCNORTTI) $(CCNOEXH) $(CPROJ) +# DBG and _DEBUG_ are primarily used by IbAccess and modules using it +# IB_DEBUG is the prefered define to test +CPROJDEBUG = -DICSDEBUG -DDBG -DIB_DEBUG +DEPENDPROJ = +LDPROJ = +LINTPROJ = +MIDLPROJ = +RSCPROJ = + +# On Windows ACE needs MFC DLL +USEMFC = shared + +# variables for use in modules building against Open IB Stack +ifeq "$(OFED_STACK_PREFIX)" "" +OFED_STACK_PREFIX=/usr +endif +OPENIB_INCLUDE_DIRS= +#OPENIB_USER_INCLUDE_DIRS= $(OFED_STACK_PREFIX)/include $(OFED_STACK_PREFIX)/include/infiniband +OPENIB_USER_INCLUDE_DIRS= $(OFED_STACK_PREFIX)/include/infiniband $(OFED_STACK_PREFIX)/include +ifeq "$(BUILD_TARGET)" "X86_64" +OPENIB_USER_LIB_DIRS= +else +ifeq "$(BUILD_TARGET)" "PPC64" +OPENIB_USER_LIB_DIRS= $(OFED_STACK_PREFIX)/lib64 +else +OPENIB_USER_LIB_DIRS= $(OFED_STACK_PREFIX)/lib +endif +endif +OPENIB_USER_LIBS= ibverbs ibumad ssl crypto +IBACCESS_USER_INCLUDE_DIRS= $(GLOBAL_INCLUDE_DIR)/iba $(GLOBAL_INCLUDE_DIR)/iba/public +IBACCESS_USER_LIB_DIRS= +IBACCESS_USER_LIBS= public + +PROJ_INCLUDE_DIRS+= $(IBACCESS_USER_INCLUDE_DIRS) $(OPENIB_INCLUDE_DIRS) $(OPENIB_USER_INCLUDE_DIRS) + +CPROJKERNEL=$(CKERNEL) + +#-----------------------------------------------------------------------------# +# Platform specific definitions: +#-----------------------------------------------------------------------------# +ifeq "$(BUILD_TARGET_OS)" "VXWORKS" +$(error BUILD_TARGET_OS of VXWORKS not supported) +endif # VXWORKS +ifeq "$(BUILD_TARGET_OS)" "DARWIN" +$(error BUILD_TARGET_OS of DARWIN not supported) +endif # DARWIN +ifeq "$(BUILD_TARGET_OS)" "LINUX" +ifndef BUILD_TARGET_OS_VERSION +$(error BUILD_TARGET_OS_VERSION not defined) +endif +ifndef BUILD_TARGET_OS_VENDOR_VERSION +$(error BUILD_TARGET_OS_VENDOR_VERSION not defined) +endif +ifndef BUILD_TARGET_OS_VENDOR +$(error BUILD_TARGET_OS_VENDOR not defined) +endif +ICS_KERNEL_CONF_FILE:=$(TL_DIR)/Makerules/LINUX/$(BUILD_TARGET).$(BUILD_TARGET_OS_VENDOR).$(BUILD_TARGET_OS_VERSION).h +endif # LINUX +ifeq "$(BUILD_TARGET_OS)" "WIN32" +$(error BUILD_TARGET_OS of WIN32 not supported) +endif # WIN32 +#=============================================================================# +#=============================================================================# +## TL_DIR must be set in the environment for the 'make' to succeed. +## icsmake will do this for you +#-----------------------------------------------------------------------------# +# Include Global makerules definitions and rules +include $(TL_DIR)/Makerules/Makerules.global +ifdef BUILD_26 +ifndef KERNELRELEASE +#parse cflags for KBUILD +#only trick is with -I options +#with relative path directories + +# get an alternate copy of CFLAGS without any compiler options +KBUILD_CFLAGS:=$(filter -D%, $(CMACH)) $(CSYS) $(CENV) $(CPROJ) $(CMOD) $(CLOCAL) $(CINCSRCH) +ifeq "$(BUILD_CONFIG)" "debug" +KBUILD_CFLAGS+=$(filter -D%, $(CDEBUG)) +endif +KBUILD_EXTRA_CFLAGS=$(filter-out -I%,$(KBUILD_CFLAGS)) +# -I options with absolute paths +KBUILD_INCS:=$(filter -I%,$(KBUILD_CFLAGS)) +KBUILD_EXTRA_CFLAGS+=$(filter -I/%,$(KBUILD_INCS)) +# -I options with relative paths +KBUILD_REL_INC_DIRS:=$(patsubst -I%,%,$(filter-out -I/%,$(KBUILD_INCS))) +KBUILD_EXTRA_CFLAGS+=$(addprefix -I${PWD}/,$(KBUILD_REL_INC_DIRS)) +endif +endif +#=============================================================================# + +#=============================================================================# +## The project makerules file also contains the following basic make target +## rules for simplifying application build processes: +## +#=============================================================================# +# The following section contains a list of standard targets which will be used +# by all of the makefiles. The targets are listed in alphabetical order and +# depend on the above definitions section as well as externally defined items +# from the user specific makefile. +#=============================================================================# +# General Rules: +#-----------------------------------------------------------------------------# +#ifeq "$(BUILD_TARGET_OS)" "DARWIN" +#Info.plist: Info.$(BUILD_TARGET_OS_VERSION).plist +# $(SED) -e 's/MODULEVERSION/$(MODULEVERSION)/' < $< > $@ +#endif +#=============================================================================# + +#=============================================================================# +# This section contains a set of targets which override the standard ones +# provided for by GNU make. +#=============================================================================# +# Standard Makefile Rules Overrides: +#-----------------------------------------------------------------------------# +#=============================================================================# + +#=============================================================================# +# Targets to make sure the initial environment is properly configured +#=============================================================================# +#ifndef ENVIRONMENT +#check_env: +# @echo "The ENVIRONMENT environment variable must be set to be valid" +# @exit 1 +#else #ENVIRONMENT +#check_env: +#endif #ENVIRONMENT +#.PHONY: check_env +#=============================================================================# diff --git a/OpenIb_Host/Makesettings.project b/OpenIb_Host/Makesettings.project new file mode 100644 index 0000000..ef3af0e --- /dev/null +++ b/OpenIb_Host/Makesettings.project @@ -0,0 +1,94 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** +## Make Settings at project level +#=============================================================================# +## Project Make Settings File +## ----------------------- +## +## This file allows setting variables which can be used by Makefiles to make +## decisions on which targets or DIRS to build. This allows such controls +## to be placed here as opposed to extending the build system environment +## variable tools like setenv, target, etc. +## +## All tools local makefiles should include this makerules file before its own +## local definitions section. Use +## Makefile.template as a base makefile and modify the template according to +## your application needs. The template makefile includes this file +## and this project makesettings file includes the global makesettings file. +## Any modifications to this makesettings file or to local makefiles should be +## made in a portable fashion using 'ifdef' structures where necessary so that +## the same makefile can be used on multiple platforms. +## The main purpose of this +## include makesettings file is for local variable definitions +## specific to the project at hand. Global modifications should be made in the +## global makesettings file and local items should be in the local makefile, not +## in this makesettings file. +## Any modifications to the source should be made with +## portability in mind and should follow the embedded notations. Documentation +## is automatically generated from this makefile! Use the correct conventions +## for those items which should be documented. +## +## NOTE: This makefile inclusion (the global makesettings, and the template +## makefile) depend on using the GNU version of make. GNU make must be +## installed on your system prior to using this makefile. +#=============================================================================# +## +#=============================================================================# +# The following list is the standard list of settings which will be defined +# for all platforms. It consists of general and machine specific sections that +# contain many system parameters which may be used in a makefile. Please keep +# the list(s) in strictly aphabetical order to facilitate simple searches. +# +# See Makerules.global for the meaning of these flags +#-----------------------------------------------------------------------------# +# Common platform definitions: +#-----------------------------------------------------------------------------# + +IB_STACK=OPENIB +#PROJ_SM_DIR=$(TL_DIR)/Esm/ib + +#-----------------------------------------------------------------------------# +# Platform specific definitions: +#-----------------------------------------------------------------------------# +ifeq "$(BUILD_TARGET_OS)" "VXWORKS" +endif # VXWORKS +#ifeq "$(BUILD_TARGET_OS)" "DARWIN" +#endif # DARWIN +ifeq "$(BUILD_TARGET_OS)" "LINUX" +endif # LINUX +ifeq "$(BUILD_TARGET_OS)" "WIN32" +endif # WIN32 +#=============================================================================# +#=============================================================================# +## TL_DIR must be set in the environment for the 'make' to succeed. +## icsmake will do this for you +#-----------------------------------------------------------------------------# +# Include Global makerules definitions and rules +include $(TL_DIR)/Makerules/Makesettings.global +#=============================================================================# diff --git a/OpenIb_Host/README b/OpenIb_Host/README new file mode 100644 index 0000000..7084aa8 --- /dev/null +++ b/OpenIb_Host/README @@ -0,0 +1,38 @@ +IntelOPA Open Fabrics FastFabric Tools Host Software + +The majority of this source is best viewed with tabstops set at 4 spaces. + +In order to build this source: + cd to this directory + ./do_build + +The build will create installation packages into the release/ tree. +These can be used to install on a destination system. +Typically the IntelOPA-Tools-FF.*.tgz is the only file you will require. +As it contains all the tools including fast fabric. +IntelOPA-Tools.*.tgz will not contain the fast fabric specific items. +IntelOPA-Tests.*.tgz will contain some test programs. + +To build a debug version: + export BUILD_CONFIG=debug +To build a release version + export BUILD_CONFIG=release +default is a release version. +The debug version has additional error checks, and logging. +However performance is slightly less than the release version. +Production systems should run the release version. + +The majority of directories include README files which indicate +what the given directory implements as well as some other information. + +Build options which can be set in CENV: + TBD + +The following command (run as root) allows the GPL source to compile on Suse releases: + + ln -s /usr/src/linux-`uname -r`/drivers /lib/modules/`uname -r`/build/drivers + +The following commands (run as root) allow the GPL source to compile on Fedora releases: + + cd /usr/src/linux-`uname -r`/drivers/scsi + cp scsi.h scsi_obsolete.h scsi_typedefs.h /lib/modules/`uname -r`/build/drivers/scsi diff --git a/OpenIb_Host/build.env b/OpenIb_Host/build.env new file mode 100644 index 0000000..999040f --- /dev/null +++ b/OpenIb_Host/build.env @@ -0,0 +1,6 @@ +# Adjust the environment variables if necessary +export PRODUCT=OPENIB_FF +export RELEASE_TAG=10_10_1_0_35 +export BUILD_CONFIG=${BUILD_CONFIG:-"release"} +export BUILD_WITH_STACK=OPENIB +export LDENVFS= diff --git a/OpenIb_Host/build_label b/OpenIb_Host/build_label new file mode 100644 index 0000000..faf816d --- /dev/null +++ b/OpenIb_Host/build_label @@ -0,0 +1 @@ +Build of OPENIB_FF 12/26/19 23:51 Tag: OPENIB_FF_LINUX_opa-10_10_10_10_1_0_35 diff --git a/OpenIb_Host/build_tests.sh b/OpenIb_Host/build_tests.sh new file mode 100755 index 0000000..deb8196 --- /dev/null +++ b/OpenIb_Host/build_tests.sh @@ -0,0 +1,122 @@ +#!/bin/bash +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +#[ICS VERSION STRING: unknown] + +Usage() +{ + echo "build_tests.sh [-C]" >&2 + exit 2 +} + +Cflag=n +rerun=n +while getopts rC param +do + case $param in + r) rerun=y;; + C) Cflag=y;; + ?) Usage;; + esac +done + +set -x +wd=$PWD +testdir=$wd/tests_build + +# TBD - maybe there can be a better way +# this copies the relevant directories to a place where we can do the +# build, this avoids clutter in the main tree and hence avoids clutter +# in the FF src.rpm, but it is creating extra copies of things which clutter +# any searches from the top of the tree +# perhaps we should rename testsdir to a dot filename or a different tree +if [ "$Cflag" != y ] +then + # clobber old tree + rm -rf $testdir +fi +mkdir -p $testdir +cp Makefile.tests $testdir/Makefile +cp *.project setenv $testdir +cd $TL_DIR +# -p will preserve timestamps (and ownership, etc) so that we will +# not rebuild unless we need to +cp -r -p Makerules MakeTools opamgt Xml Topology SrpTools InicTools Tests IbaTests IbaTools IbAccess MpiApps Fd $testdir +if [ "$Cflag" = y ] +then + # if in-place FF build left builtbin, builtinclude and builtlibs, pick + # them up to accelerate incremental builds + for i in builtbin builtinclude builtlibs + do + if [ -e $i.$PRODUCT.$BUILD_CONFIG ] + then + cp -r -p $i.$PRODUCT.$BUILD_CONFIG $testdir + fi + done +fi + + +cd $testdir +export PROJ_FILE_DIR=. +set +x +. setenv +set -x +showenv +# TBD the code below should be moved back into the LINUX/Makefile as part of a +# package_tests target, then this can run make stage prepfiles package_tests +# and also avoid editing Makerules.project +sed -i 's/IntelOPA-Tools-FF/IntelOPA-Tests/' Makerules.project +make stage 2>&1 | tee make.res +#make prepfiles 2>&1 | tee make.res # TBD should be enabled +if [ "x$RELEASE_TAG" = "x" ] +then + STAGE_SUB_DIR=IntelOPA-Tests.$(MakeTools/patch_engineer_version.sh|cut -d"." -f1) +else + STAGE_SUB_DIR=IntelOPA-Tests.$(format_releasetag $RELEASE_TAG) +fi +tarstage=$PWD/tarStage/$STAGE_SUB_DIR +mkdir -p $tarstage +if [ "x$PRODUCT" = "x" ] +then + stagedir=stage.tests_build.$BUILD_CONFIG +else + stagedir=stage.$PRODUCT.$BUILD_CONFIG +fi +tarbase=$(find $stagedir -name "IntelOPA-Tests*") +cd $tarbase +cd Tests +cp -r * $tarstage +cd .. +cp version $tarstage +cd $tarstage +cd .. +tar cfz $STAGE_SUB_DIR.tgz $STAGE_SUB_DIR +echo $PWD/$STAGE_SUB_DIR.tgz >> $TL_DIR/../dist_files +echo $PWD/$STAGE_SUB_DIR.tgz >> $TL_DIR/../packaged_files diff --git a/OpenIb_Host/check_results b/OpenIb_Host/check_results new file mode 100755 index 0000000..488b44f --- /dev/null +++ b/OpenIb_Host/check_results @@ -0,0 +1,8 @@ +#!/bin/bash + +if [ -d IbAccess ] +then +./MakeTools/check_results "$@" +else +../MakeTools/check_results "$@" +fi diff --git a/OpenIb_Host/debian/changelog.in b/OpenIb_Host/debian/changelog.in new file mode 100644 index 0000000..42969f1 --- /dev/null +++ b/OpenIb_Host/debian/changelog.in @@ -0,0 +1,18 @@ +opa (10.7.0.0-1) UNRELEASED; urgency=medium + + * Import OPA from upstream + + -- Tymoteusz Kielan Wed, 8 Feb 2017 14:02:27 +0100 + +opa (10.1.0.0) UNRELEASED; urgency=medium + + * Import OPA from upstream + + -- Brian T. Smith Fri, 10 Jun 2016 18:28:35 -0500 + +opa (10.0.0.0) UNRELEASED; urgency=medium + + * Initial release + + -- Brian T. Smith Mon, 14 Mar 2016 12:26:35 -0500 + diff --git a/OpenIb_Host/debian/compat b/OpenIb_Host/debian/compat new file mode 100644 index 0000000..ec63514 --- /dev/null +++ b/OpenIb_Host/debian/compat @@ -0,0 +1 @@ +9 diff --git a/OpenIb_Host/debian/control b/OpenIb_Host/debian/control new file mode 100644 index 0000000..3287d3d --- /dev/null +++ b/OpenIb_Host/debian/control @@ -0,0 +1,52 @@ +Source: opa +Maintainer: Breyer, Scott J +Section: admin +Priority: optional +Standards-Version: 3.9.8 +Build-Depends: debhelper (>= 9), libexpat-dev, + dh-systemd (>= 1.5), bash (>= 3), libibverbs-dev, uuid-dev, + libibmad-dev, libibumad-dev, ibacm, libncurses5-dev, texinfo + +Package: opa-basic-tools +Architecture: linux-any +Depends: ${misc:Depends}, ${shlibs:Depends}, ${perl:Depends}, + bc, libhfi1 (>= 0.5) +Description: Management level tools and scripts. + Contains basic tools for fabric managment necessary on all compute nodes. + +Package: opa-address-resolution +Architecture: linux-any +Depends: ${misc:Depends}, ${shlibs:Depends}, + opa-basic-tools (= ${binary:Version}), + ibacm +Description: Contains Address Resolution manager + This is to be filled out more concisely later. + +Package: opa-fastfabric +Architecture: linux-any +Depends: ${misc:Depends}, ${shlibs:Depends}, ${perl:Depends}, + opa-basic-tools (= ${binary:Version}), + opa-mpi-apps (= ${binary:Version}), + tcl-expect, tclsh +Description: Management level tools and scripts. + Contains tools for managing fabric on a management node. + +Package: opa-libopamgt +Architecture: linux-any +Depends: ${misc:Depends}, ${shlibs:Depends} +Description: Omni-Path management API library + This package contains the library necessary to build applications that + interface with an Omni-Path FM. + +Package: opa-libopamgt-dev +Architecture: linux-any +Depends: ${misc:Depends}, ${shlibs:Depends}, + opa-libopamgt +Description: Omni-Path library development headers + This package contains the necessary headers for opamgt development. + +Package: opa-snapconfig +Architecture: linux-any +Depends: ${misc:Depends}, ${shlibs:Depends} +Description: Parse information from snapshot file, issue packets to program + Contains snapconfig tools diff --git a/OpenIb_Host/debian/copyright b/OpenIb_Host/debian/copyright new file mode 100644 index 0000000..d28cf56 --- /dev/null +++ b/OpenIb_Host/debian/copyright @@ -0,0 +1,53 @@ +This file is provided under a dual BSD/GPLv2 license. When using or +redistributing this software, you may do so under either license. + +Copyright(c) 2017 Intel Corporation. +Copyright(c) 2016 System Fabric Works, Inc. All Rights Reserved. + +/usr/share/common-licenses/GPL-2 + +Contact Information: + +Intel Corporation +www.Intel.com + +BSD License: + +Copyright (c) 2017, Intel Corporation +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: +- Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. +- Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. +- Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +EXPORT LAWS: THIS LICENSE ADDS NO RESTRICTIONS TO THE EXPORT LAWS OF YOUR +JURISDICTION. It is licensee's responsibility to comply with any export +regulations applicable in licensee's jurisdiction. Under current U.S. export +regulations this software is eligible for export from the U.S. and can be +downloaded by or otherwise exported or reexported worldwide EXCEPT to U.S. +embargoed destinations which include Cuba, Iraq, Libya, North Korea, Iran, +Syria, Sudan, Afghanistan and any other country to which the U.S. has embargoed +goods and services. + +NOTICE: + +This software distribution may contain software from 3'rd parties. +3'rd party software is licensed as noted in their source files. diff --git a/OpenIb_Host/debian/opa-address-resolution.install b/OpenIb_Host/debian/opa-address-resolution.install new file mode 100644 index 0000000..81817c4 --- /dev/null +++ b/OpenIb_Host/debian/opa-address-resolution.install @@ -0,0 +1,14 @@ +/etc/rdma/dsap.conf +/usr/bin/opa_osd_dump +/usr/bin/opa_osd_exercise +/usr/bin/opa_osd_perf +/usr/bin/opa_osd_query +/usr/include/infiniband/opasadb_path.h +/usr/include/infiniband/opasadb_route.h +/usr/include/infiniband/opasadb_route2.h +/usr/lib/libopasadb.so.1.0.0 +/usr/lib/ibacm/libdsap.so.1.0.0 +/usr/share/man/man1/opa_osd_dump.1* +/usr/share/man/man1/opa_osd_exercise.1* +/usr/share/man/man1/opa_osd_perf.1* +/usr/share/man/man1/opa_osd_query.1* diff --git a/OpenIb_Host/debian/opa-address-resolution.symbols b/OpenIb_Host/debian/opa-address-resolution.symbols new file mode 100644 index 0000000..124a2a9 --- /dev/null +++ b/OpenIb_Host/debian/opa-address-resolution.symbols @@ -0,0 +1,57 @@ +libdsap.so.1.0.0 opa-address-resolution #MINVER# + LIBDSAP_1.0.0@LIBDSAP_1.0.0 10.7.0.0 + provider_query@LIBDSAP_1.0.0 10.7.0.0 +libopasadb.so.1.0.0 opa-address-resolution #MINVER# + OPA_SA_DB_1.0.0@OPA_SA_DB_1.0.0 10.7.0.0 + op_log@OPA_SA_DB_1.0.0 10.7.0.0 + op_log_get_file@OPA_SA_DB_1.0.0 10.7.0.0 + op_log_set_file@OPA_SA_DB_1.0.0 10.7.0.0 + op_log_set_level@OPA_SA_DB_1.0.0 10.7.0.0 + op_log_syslog@OPA_SA_DB_1.0.0 10.7.0.0 + op_path_check_version@OPA_SA_DB_1.0.0 10.7.0.0 + op_path_close@OPA_SA_DB_1.0.0 10.7.0.0 + op_path_compute_timeout@OPA_SA_DB_1.0.0 10.7.0.0 + op_path_find_hfi@OPA_SA_DB_1.0.0 10.7.0.0 + op_path_find_pkey@OPA_SA_DB_1.0.0 10.7.0.0 + op_path_get_path_by_rec@OPA_SA_DB_1.0.0 10.7.0.0 + op_path_get_path_to_dgid@OPA_SA_DB_1.0.0 10.7.0.0 + op_path_open@OPA_SA_DB_1.0.0 10.7.0.0 + op_path_qp_attr@OPA_SA_DB_1.0.0 10.7.0.0 + op_ppath_add_path@OPA_SA_DB_1.0.0 10.7.0.0 + op_ppath_add_port@OPA_SA_DB_1.0.0 10.7.0.0 + op_ppath_add_sid@OPA_SA_DB_1.0.0 10.7.0.0 + op_ppath_add_subnet@OPA_SA_DB_1.0.0 10.7.0.0 + op_ppath_add_vfab@OPA_SA_DB_1.0.0 10.7.0.0 + op_ppath_close_reader@OPA_SA_DB_1.0.0 10.7.0.0 + op_ppath_close_writer@OPA_SA_DB_1.0.0 10.7.0.0 + op_ppath_create_reader@OPA_SA_DB_1.0.0 10.7.0.0 + op_ppath_create_writer@OPA_SA_DB_1.0.0 10.7.0.0 + op_ppath_find_path@OPA_SA_DB_1.0.0 10.7.0.0 + op_ppath_initialize_paths@OPA_SA_DB_1.0.0 10.7.0.0 + op_ppath_initialize_ports@OPA_SA_DB_1.0.0 10.7.0.0 + op_ppath_initialize_subnets@OPA_SA_DB_1.0.0 10.7.0.0 + op_ppath_initialize_vfabrics@OPA_SA_DB_1.0.0 10.7.0.0 + op_ppath_publish@OPA_SA_DB_1.0.0 10.7.0.0 + op_ppath_version@OPA_SA_DB_1.0.0 10.7.0.0 + op_route_alloc_param@OPA_SA_DB_1.0.0 10.7.0.0 + op_route_close@OPA_SA_DB_1.0.0 10.7.0.0 + op_route_complete_job@OPA_SA_DB_1.0.0 10.7.0.0 + op_route_create_job@OPA_SA_DB_1.0.0 10.7.0.0 + op_route_dump@OPA_SA_DB_1.0.0 10.7.0.0 + op_route_dump_param@OPA_SA_DB_1.0.0 10.7.0.0 + op_route_free_param@OPA_SA_DB_1.0.0 10.7.0.0 + op_route_get_cost_matrix@OPA_SA_DB_1.0.0 10.7.0.0 + op_route_get_job_list@OPA_SA_DB_1.0.0 10.7.0.0 + op_route_get_portguid_vec@OPA_SA_DB_1.0.0 10.7.0.0 + op_route_get_status_text@OPA_SA_DB_1.0.0 10.7.0.0 + op_route_get_switch_map@OPA_SA_DB_1.0.0 10.7.0.0 + op_route_get_use_matrix@OPA_SA_DB_1.0.0 10.7.0.0 + op_route_init_param@OPA_SA_DB_1.0.0 10.7.0.0 + op_route_open@OPA_SA_DB_1.0.0 10.7.0.0 + op_route_poll_ready@OPA_SA_DB_1.0.0 10.7.0.0 + op_route_release_cost_matrix@OPA_SA_DB_1.0.0 10.7.0.0 + op_route_release_job_list@OPA_SA_DB_1.0.0 10.7.0.0 + op_route_release_portguid_vec@OPA_SA_DB_1.0.0 10.7.0.0 + op_route_release_switch_map@OPA_SA_DB_1.0.0 10.7.0.0 + op_route_release_use_matrix@OPA_SA_DB_1.0.0 10.7.0.0 + op_route_set_use_matrix@OPA_SA_DB_1.0.0 10.7.0.0 diff --git a/OpenIb_Host/debian/opa-basic-tools.install b/OpenIb_Host/debian/opa-basic-tools.install new file mode 100644 index 0000000..26132cd --- /dev/null +++ b/OpenIb_Host/debian/opa-basic-tools.install @@ -0,0 +1,27 @@ +/etc/opa/opamgt_tls.xml +/usr/lib/opa/tools/opaipcalc +/usr/lib/opa/tools/setup_self_ssh +/usr/lib/opa/tools/usemem +/usr/sbin/opacapture +/usr/sbin/opafabricinfo +/usr/sbin/opagetvf +/usr/sbin/opagetvf_env +/usr/sbin/opahfirev +/usr/sbin/opainfo +/usr/sbin/opapacketcapture +/usr/sbin/opaportinfo +/usr/sbin/oparesolvehfiport +/usr/sbin/opasaquery +/usr/sbin/opasmaquery +/usr/share/man/man1/opafabricinfo.1* +/usr/share/man/man1/opagetvf.1* +/usr/share/man/man1/opagetvf_env.1* +/usr/share/man/man1/opahfirev.1* +/usr/share/man/man1/opainfo.1* +/usr/share/man/man1/opapacketcapture.1* +/usr/share/man/man1/opapmaquery.1* +/usr/share/man/man1/opaportconfig.1* +/usr/share/man/man1/opaportinfo.1* +/usr/share/man/man1/oparesolvehfiport.1* +/usr/share/man/man1/opasaquery.1* +/usr/share/man/man1/opasmaquery.1* diff --git a/OpenIb_Host/debian/opa-basic-tools.links b/OpenIb_Host/debian/opa-basic-tools.links new file mode 100644 index 0000000..2780998 --- /dev/null +++ b/OpenIb_Host/debian/opa-basic-tools.links @@ -0,0 +1,2 @@ +/usr/sbin/opaportinfo /usr/sbin/opaportconfig +/usr/sbin/opasmaquery /usr/sbin/opapmaquery diff --git a/OpenIb_Host/debian/opa-fastfabric.install b/OpenIb_Host/debian/opa-fastfabric.install new file mode 100644 index 0000000..b5031cf --- /dev/null +++ b/OpenIb_Host/debian/opa-fastfabric.install @@ -0,0 +1,137 @@ +/etc/opa/allhosts +/etc/opa/chassis +/etc/opa/esm_chassis +/etc/opa/hosts +/etc/opa/opafastfabric.conf +/etc/opa/opamon.conf +/etc/opa/opamon.si.conf +/etc/opa/ports +/etc/opa/switches +/usr/lib/opa/tools/osid_wrapper +/usr/lib/opa/fm_tools/config_check +/usr/lib/opa/fm_tools/config_convert +/usr/lib/opa/fm_tools/config_diff +/usr/lib/opa/fm_tools/config_generate +/usr/lib/opa/tools/basic.exp +/usr/lib/opa/tools/chassis.exp +/usr/lib/opa/tools/chassis_configure.exp +/usr/lib/opa/tools/chassis_fmconfig.exp +/usr/lib/opa/tools/chassis_fmcontrol.exp +/usr/lib/opa/tools/chassis_fmgetconfig.exp +/usr/lib/opa/tools/chassis_fmgetsecurityfiles.exp +/usr/lib/opa/tools/chassis_fmsecurityfiles.exp +/usr/lib/opa/tools/chassis_getconfig.exp +/usr/lib/opa/tools/chassis_reboot.exp +/usr/lib/opa/tools/chassis_setup +/usr/lib/opa/tools/chassis_upgrade.exp +/usr/lib/opa/tools/comm12 +/usr/lib/opa/tools/common_funcs.exp +/usr/lib/opa/tools/configipoib.exp +/usr/lib/opa/tools/extmng.exp +/usr/lib/opa/tools/ff_funcs +/usr/lib/opa/tools/ff_function.exp +/usr/lib/opa/tools/front +/usr/lib/opa/tools/ib.exp +/usr/lib/opa/tools/ibtools.exp +/usr/lib/opa/tools/install.exp +/usr/lib/opa/tools/ipoibping.exp +/usr/lib/opa/tools/libqlgc_fork.so +/usr/lib/opa/tools/load.exp +/usr/lib/opa/tools/mpi.exp +/usr/lib/opa/tools/mpiperf.exp +/usr/lib/opa/tools/mpiperfdeviation.exp +/usr/lib/opa/tools/network.exp +/usr/lib/opa/tools/opa_to_xml.exp +/usr/lib/opa/tools/opachassisip +/usr/lib/opa/tools/opafastfabric.conf.def +/usr/lib/opa/tools/opagenswitcheshelper +/usr/lib/opa/tools/opagetipaddrtype +/usr/lib/opa/tools/opaswconfigure +/usr/lib/opa/tools/opaswfwconfigure +/usr/lib/opa/tools/opaswfwupdate +/usr/lib/opa/tools/opaswfwverify +/usr/lib/opa/tools/opaswping +/usr/lib/opa/tools/opaswquery +/usr/lib/opa/tools/opaswreset +/usr/lib/opa/tools/osid_wrapper +/usr/lib/opa/tools/proc_mgr.exp +/usr/lib/opa/tools/reboot.exp +/usr/lib/opa/tools/sacache.exp +/usr/lib/opa/tools/show_counts +/usr/lib/opa/tools/sm_control.exp +/usr/lib/opa/tools/switch_capture.exp +/usr/lib/opa/tools/switch_configure.exp +/usr/lib/opa/tools/switch_dump.exp +/usr/lib/opa/tools/switch_fwverify.exp +/usr/lib/opa/tools/switch_getconfig.exp +/usr/lib/opa/tools/switch_hwvpd.exp +/usr/lib/opa/tools/switch_info.exp +/usr/lib/opa/tools/switch_ping.exp +/usr/lib/opa/tools/switch_reboot.exp +/usr/lib/opa/tools/switch_setup +/usr/lib/opa/tools/switch_upgrade.exp +/usr/lib/opa/tools/target.exp +/usr/lib/opa/tools/tclIndex +/usr/lib/opa/tools/tcl_proc +/usr/lib/opa/tools/tools.exp +/usr/lib/opa/tools/upgrade.exp +/usr/sbin/opa2rm +/usr/sbin/opaallanalysis +/usr/sbin/opacabletest +/usr/sbin/opacaptureall +/usr/sbin/opachassisadmin +/usr/sbin/opachassisanalysis +/usr/sbin/opacheckload +/usr/sbin/opacmdall +/usr/sbin/opadisablehosts +/usr/sbin/opadisableports +/usr/sbin/opadownloadall +/usr/sbin/opaenableports +/usr/sbin/opaesmanalysis +/usr/sbin/opaexpandfile +/usr/sbin/opaextractbadlinks +/usr/sbin/opaextracterror +/usr/sbin/opaextractlids +/usr/sbin/opaextractlink +/usr/sbin/opaextractmissinglinks +/usr/sbin/opaextractperf +/usr/sbin/opaextractperf2 +/usr/sbin/opaextractsellinks +/usr/sbin/opaextractstat +/usr/sbin/opaextractstat2 +/usr/sbin/opafabricanalysis +/usr/sbin/opafastfabric +/usr/sbin/opafindgood +/usr/sbin/opafirmware +/usr/sbin/opagenchassis +/usr/sbin/opagenesmchassis +/usr/sbin/opagenswitches +/usr/sbin/opahostadmin +/usr/sbin/opahostsmanalysis +/usr/sbin/opaledports +/usr/sbin/opalinkanalysis +/usr/sbin/opamergeperf2 +/usr/sbin/opapaquery +/usr/sbin/opapingall +/usr/sbin/opareport +/usr/sbin/opareports +/usr/sbin/opascpall +/usr/sbin/opasetupssh +/usr/sbin/opashowallports +/usr/sbin/opashowmc +/usr/sbin/opasorthosts +/usr/sbin/opaswdisableall +/usr/sbin/opaswenableall +/usr/sbin/opaswitchadmin +/usr/sbin/opatop +/usr/sbin/opauploadall +/usr/sbin/opaverifyhosts +/usr/sbin/opaxlattopology +/usr/sbin/opaxmlextract +/usr/sbin/opaxmlfilter +/usr/sbin/opaxmlgenerate +/usr/sbin/opaxmlindent +/usr/share/man/man8/opa*.8* +/usr/share/opa/help/*.hlp +/usr/share/opa/samples/* +/usr/src/opa/shmem_apps/* diff --git a/OpenIb_Host/debian/opa-fastfabric.links b/OpenIb_Host/debian/opa-fastfabric.links new file mode 100644 index 0000000..ef3e6ed --- /dev/null +++ b/OpenIb_Host/debian/opa-fastfabric.links @@ -0,0 +1,2 @@ +/usr/lib/opa/fm_tools/config_check /usr/sbin/opafmconfigcheck +/usr/lib/opa/fm_tools/config_diff /usr/sbin/opafmconfigdiff diff --git a/OpenIb_Host/debian/opa-libopamgt-dev.install b/OpenIb_Host/debian/opa-libopamgt-dev.install new file mode 100644 index 0000000..b5d8601 --- /dev/null +++ b/OpenIb_Host/debian/opa-libopamgt-dev.install @@ -0,0 +1,2 @@ +/usr/include/opamgt/* +/usr/src/opamgt/* diff --git a/OpenIb_Host/debian/opa-libopamgt-dev.links b/OpenIb_Host/debian/opa-libopamgt-dev.links new file mode 100644 index 0000000..10f79f9 --- /dev/null +++ b/OpenIb_Host/debian/opa-libopamgt-dev.links @@ -0,0 +1 @@ +/usr/lib/libopamgt.so.0 /usr/lib/libopamgt.so diff --git a/OpenIb_Host/debian/opa-libopamgt.install b/OpenIb_Host/debian/opa-libopamgt.install new file mode 100644 index 0000000..35f9f27 --- /dev/null +++ b/OpenIb_Host/debian/opa-libopamgt.install @@ -0,0 +1 @@ +/usr/lib/libopamgt.so.* diff --git a/OpenIb_Host/debian/opa-libopamgt.links b/OpenIb_Host/debian/opa-libopamgt.links new file mode 100644 index 0000000..b7ad935 --- /dev/null +++ b/OpenIb_Host/debian/opa-libopamgt.links @@ -0,0 +1 @@ +/usr/lib/libopamgt.so.0.2.0 /usr/lib/libopamgt.so.0 diff --git a/OpenIb_Host/debian/opa-libopamgt.symbols b/OpenIb_Host/debian/opa-libopamgt.symbols new file mode 100644 index 0000000..e6b7128 --- /dev/null +++ b/OpenIb_Host/debian/opa-libopamgt.symbols @@ -0,0 +1,264 @@ +libopamgt.so.0 opa-libopamgt #MINVER# + BackTrace@Base 10.7.0.0 + DumpStack@Base 10.7.0.0 + FCmStatusText@Base 10.7.0.0 + FStatusText@Base 10.7.0.0 + IB2STL_NODE_INFO@Base 10.7.0.0 + IB2STL_PORT_INFO@Base 10.7.0.0 + IB2STL_SWITCH_INFO@Base 10.7.0.0 + IbLogPrintf@Base 10.7.0.0 + MemoryAllocate2AndClearDbg@Base 10.7.0.0 + MemoryAllocate2AndClearRel@Base 10.7.0.0 + MemoryAllocate2Dbg@Base 10.7.0.0 + MemoryAllocate2Rel@Base 10.7.0.0 + MemoryAllocateAndClearDbg@Base 10.7.0.0 + MemoryAllocateAndClearRel@Base 10.7.0.0 + MemoryAllocateDbg@Base 10.7.0.0 + MemoryAllocateObjectArrayDbg@Base 10.7.0.0 + MemoryAllocateObjectArrayRel@Base 10.7.0.0 + MemoryAllocatePriv@Base 10.7.0.0 + MemoryAllocateRel@Base 10.7.0.0 + MemoryClear@Base 10.7.0.0 + MemoryCompare@Base 10.7.0.0 + MemoryCopy@Base 10.7.0.0 + MemoryDeallocate@Base 10.7.0.0 + MemoryDeallocatePriv@Base 10.7.0.0 + MemoryDisplayUsage@Base 10.7.0.0 + MemoryFill@Base 10.7.0.0 + MemoryTrackUsage@Base 10.7.0.0 + PrintUDbg@Base 10.7.0.0 + PrintUMsg@Base 10.7.0.0 + STL2IB_NODE_INFO@Base 10.7.0.0 + STL2IB_PORT_INFO@Base 10.7.0.0 + STL2IB_SWITCH_INFO@Base 10.7.0.0 + StringToDateTime@Base 10.7.0.0 + StringToGid@Base 10.7.0.0 + StringToInt16@Base 10.7.0.0 + StringToInt32@Base 10.7.0.0 + StringToInt64@Base 10.7.0.0 + StringToInt8@Base 10.7.0.0 + StringToMAC@Base 10.7.0.0 + StringToTuple@Base 10.7.0.0 + StringToUint16@Base 10.7.0.0 + StringToUint32@Base 10.7.0.0 + StringToUint64@Base 10.7.0.0 + StringToUint64Bytes@Base 10.7.0.0 + StringToUint8@Base 10.7.0.0 + StringToVeswPort@Base 10.7.0.0 + convert_umad_ca_attribs_to_iba@Base 10.7.0.0 + convert_umad_port_attribs_to_iba@Base 10.7.0.0 + create_sa_qp@Base 10.7.0.0 + flush_rcv@Base 10.7.0.0 + handle_sa_ud_qp@Base 10.7.0.0 + iba_format_get_portguid_error@Base 10.7.0.0 + iba_fstatus_msg@Base 10.7.0.0 + iba_get_caguids_alloc@Base 10.7.0.0 + iba_get_portguid@Base 10.7.0.0 + iba_init@Base 10.7.0.0 + iba_mad_status_msg2@Base 10.7.0.0 + iba_mad_status_msg@Base 10.7.0.0 + iba_pa_mad_status_msg@Base 10.7.0.0 + iba_pa_multi_mad_focus_ports_multiselect_response_query@Base 10.7.0.0 + iba_pa_multi_mad_focus_ports_response_query@Base 10.7.0.0 + iba_pa_multi_mad_get_image_info_response_query@Base 10.7.0.0 + iba_pa_multi_mad_group_config_response_query@Base 10.7.0.0 + iba_pa_multi_mad_group_list_response_query@Base 10.7.0.0 + iba_pa_multi_mad_group_stats_response_query@Base 10.7.0.0 + iba_pa_multi_mad_vf_config_response_query@Base 10.7.0.0 + iba_pa_multi_mad_vf_focus_ports_response_query@Base 10.7.0.0 + iba_pa_multi_mad_vf_info_response_query@Base 10.7.0.0 + iba_pa_multi_mad_vf_list_response_query@Base 10.7.0.0 + iba_pa_query_input_type_msg@Base 10.7.0.0 + iba_pa_query_master_pm_lid@Base 10.7.0.0 + iba_pa_query_result_type_msg@Base 10.7.0.0 + iba_pa_single_mad_clr_all_port_counters_response_query@Base 10.7.0.0 + iba_pa_single_mad_clr_port_counters_response_query@Base 10.7.0.0 + iba_pa_single_mad_clr_vf_port_counters_response_query@Base 10.7.0.0 + iba_pa_single_mad_freeze_image_response_query@Base 10.7.0.0 + iba_pa_single_mad_get_pm_config_response_query@Base 10.7.0.0 + iba_pa_single_mad_move_freeze_response_query@Base 10.7.0.0 + iba_pa_single_mad_port_counters_response_query@Base 10.7.0.0 + iba_pa_single_mad_release_image_response_query@Base 10.7.0.0 + iba_pa_single_mad_renew_image_response_query@Base 10.7.0.0 + iba_pa_single_mad_vf_port_counters_response_query@Base 10.7.0.0 + iba_query_ca_by_guid@Base 10.7.0.0 + iba_query_ca_by_guid_alloc@Base 10.7.0.0 + iba_sd_mad_status_msg@Base 10.7.0.0 + iba_sd_query_input_type_msg@Base 10.7.0.0 + iba_sd_query_result_type_msg@Base 10.7.0.0 + iba_umadt_deregister@Base 10.7.0.0 + iba_umadt_get_sendmad@Base 10.7.0.0 + iba_umadt_poll_recv_compl@Base 10.7.0.0 + iba_umadt_poll_send_compl@Base 10.7.0.0 + iba_umadt_post_send@Base 10.7.0.0 + iba_umadt_release_recvmad@Base 10.7.0.0 + iba_umadt_release_sendmad@Base 10.7.0.0 + iba_umadt_wait_any_compl@Base 10.7.0.0 + ibv_sa_get_field@Base 10.7.0.0 + ibv_sa_set_field@Base 10.7.0.0 + omgt_bind_classes@Base 10.7.0.0 + omgt_close_port@Base 10.7.0.0 + omgt_dump_mad@Base 10.7.0.0 + omgt_find_pkey@Base 10.7.0.0 + omgt_free_query_result_buffer@Base 10.7.0.0 + omgt_get_caguids@Base 10.7.0.0 + omgt_get_hfi_from_portguid@Base 10.7.0.0 + omgt_get_hfi_names@Base 10.7.0.0 + omgt_get_hfi_num@Base 10.7.0.0 + omgt_get_issm_device@Base 10.7.0.0 + omgt_get_mgmt_pkey@Base 10.7.0.0 + omgt_get_pa_mad_status@Base 10.7.0.0 + omgt_get_portguid@Base 10.7.0.0 + omgt_get_sa_mad_status@Base 10.7.0.0 + omgt_input_value_conversion@Base 10.7.0.0 + omgt_lock_sem@Base 10.7.0.0 + omgt_mad_refresh_port_pkey@Base 10.7.0.0 + omgt_oob_adjust_blob_cur_ptr@Base 10.7.0.0 + omgt_oob_connect@Base 10.7.0.0 + omgt_oob_dequeue_net_blob@Base 10.7.0.0 + omgt_oob_disconnect@Base 10.7.0.0 + omgt_oob_enqueue_net_blob@Base 10.7.0.0 + omgt_oob_free_net_blob@Base 10.7.0.0 + omgt_oob_free_net_buf@Base 10.7.0.0 + omgt_oob_init_queue@Base 10.7.0.0 + omgt_oob_net_connect@Base 10.7.0.0 + omgt_oob_net_disconnect@Base 10.7.0.0 + omgt_oob_net_get_next_message@Base 10.7.0.0 + omgt_oob_net_process@Base 10.7.0.0 + omgt_oob_net_send@Base 10.7.0.0 + omgt_oob_new_net_blob@Base 10.7.0.0 + omgt_oob_peek_net_blob@Base 10.7.0.0 + omgt_oob_queue_empty@Base 10.7.0.0 + omgt_oob_receive_response@Base 10.7.0.0 + omgt_oob_send_packet@Base 10.7.0.0 + omgt_oob_ssl_client_open@Base 10.7.0.0 + omgt_oob_ssl_connect@Base 10.7.0.0 + omgt_oob_ssl_init@Base 10.7.0.0 + omgt_oob_ssl_read@Base 10.7.0.0 + omgt_oob_ssl_write@Base 10.7.0.0 + omgt_open_port@Base 10.7.0.0 + omgt_open_port_by_guid@Base 10.7.0.0 + omgt_open_port_by_num@Base 10.7.0.0 + omgt_pa_freeze_image@Base 10.7.0.0 + omgt_pa_get_classportinfo@Base 10.7.0.0 + omgt_pa_get_group_config@Base 10.7.0.0 + omgt_pa_get_group_focus@Base 10.7.0.0 + omgt_pa_get_group_info@Base 10.7.0.0 + omgt_pa_get_group_list@Base 10.7.0.0 + omgt_pa_get_image_info@Base 10.7.0.0 + omgt_pa_get_pm_config@Base 10.7.0.0 + omgt_pa_get_port_stats2@Base 10.7.0.0 + omgt_pa_get_port_stats@Base 10.7.0.0 + omgt_pa_get_vf_config@Base 10.7.0.0 + omgt_pa_get_vf_focus@Base 10.7.0.0 + omgt_pa_get_vf_info@Base 10.7.0.0 + omgt_pa_get_vf_list@Base 10.7.0.0 + omgt_pa_get_vf_port_stats2@Base 10.7.0.0 + omgt_pa_get_vf_port_stats@Base 10.7.0.0 + omgt_pa_move_image_freeze@Base 10.7.0.0 + omgt_pa_release_group_config@Base 10.7.0.0 + omgt_pa_release_group_focus@Base 10.7.0.0 + omgt_pa_release_group_list@Base 10.7.0.0 + omgt_pa_release_image@Base 10.7.0.0 + omgt_pa_release_vf_config@Base 10.7.0.0 + omgt_pa_release_vf_focus@Base 10.7.0.0 + omgt_pa_release_vf_list@Base 10.7.0.0 + omgt_pa_renew_image@Base 10.7.0.0 + omgt_pa_service_connect@Base 10.7.0.0 + omgt_port_get_hfi_name@Base 10.7.0.0 + omgt_port_get_hfi_num@Base 10.7.0.0 + omgt_port_get_hfi_port_num@Base 10.7.0.0 + omgt_port_get_ip_addr_text@Base 10.7.0.0 + omgt_port_get_ip_version@Base 10.7.0.0 + omgt_port_get_ipv4_addr@Base 10.7.0.0 + omgt_port_get_ipv6_addr@Base 10.7.0.0 + omgt_port_get_node_type@Base 10.7.0.0 + omgt_port_get_pa_service_state@Base 10.7.0.0 + omgt_port_get_port_guid@Base 10.7.0.0 + omgt_port_get_port_lid@Base 10.7.0.0 + omgt_port_get_port_lmc@Base 10.7.0.0 + omgt_port_get_port_prefix@Base 10.7.0.0 + omgt_port_get_port_sm_lid@Base 10.7.0.0 + omgt_port_get_port_sm_sl@Base 10.7.0.0 + omgt_port_get_port_state@Base 10.7.0.0 + omgt_port_get_sa_service_state@Base 10.7.0.0 + omgt_query_ca_by_guid@Base 10.7.0.0 + omgt_query_ca_by_guid_alloc@Base 10.7.0.0 + omgt_query_sa@Base 10.7.0.0 + omgt_recv_mad_alloc@Base 10.7.0.0 + omgt_recv_mad_no_alloc@Base 10.7.0.0 + omgt_sa_add_reg_unsafe@Base 10.7.0.0 + omgt_sa_clear_regs_unsafe@Base 10.7.0.0 + omgt_sa_find_reg@Base 10.7.0.0 + omgt_sa_free_records@Base 10.7.0.0 + omgt_sa_get_buffctrl_records@Base 10.7.0.0 + omgt_sa_get_cableinfo_records@Base 10.7.0.0 + omgt_sa_get_classportinfo_records@Base 10.7.0.0 + omgt_sa_get_conginfo_records@Base 10.7.0.0 + omgt_sa_get_devicegroupmember_records@Base 10.7.0.0 + omgt_sa_get_devicegroupname_records@Base 10.7.0.0 + omgt_sa_get_devicetreemember_records@Base 10.7.0.0 + omgt_sa_get_fabric_info_records@Base 10.7.0.0 + omgt_sa_get_hficong_records@Base 10.7.0.0 + omgt_sa_get_hficongctrl_records@Base 10.7.0.0 + omgt_sa_get_ib_mcmember_records@Base 10.7.0.0 + omgt_sa_get_ib_path_records@Base 10.7.0.0 + omgt_sa_get_informinfo_records@Base 10.7.0.0 + omgt_sa_get_lfdb_records@Base 10.7.0.0 + omgt_sa_get_lid_records@Base 10.7.0.0 + omgt_sa_get_link_records@Base 10.7.0.0 + omgt_sa_get_mcfdb_records@Base 10.7.0.0 + omgt_sa_get_node_records@Base 10.7.0.0 + omgt_sa_get_nodedesc_records@Base 10.7.0.0 + omgt_sa_get_nodeguid_records@Base 10.7.0.0 + omgt_sa_get_notice_report@Base 10.7.0.0 + omgt_sa_get_pkey_table_records@Base 10.7.0.0 + omgt_sa_get_portgroup_records@Base 10.7.0.0 + omgt_sa_get_portgroupfwd_records@Base 10.7.0.0 + omgt_sa_get_portguid_records@Base 10.7.0.0 + omgt_sa_get_portinfo_records@Base 10.7.0.0 + omgt_sa_get_quarantinenode_records@Base 10.7.0.0 + omgt_sa_get_scsc_table_records@Base 10.7.0.0 + omgt_sa_get_scsl_table_records@Base 10.7.0.0 + omgt_sa_get_scvlnt_table_records@Base 10.7.0.0 + omgt_sa_get_scvlt_table_records@Base 10.7.0.0 + omgt_sa_get_service_records@Base 10.7.0.0 + omgt_sa_get_slsc_table_records@Base 10.7.0.0 + omgt_sa_get_sminfo_records@Base 10.7.0.0 + omgt_sa_get_swcong_records@Base 10.7.0.0 + omgt_sa_get_switchcost_records@Base 10.7.0.0 + omgt_sa_get_switchinfo_records@Base 10.7.0.0 + omgt_sa_get_swportcong_records@Base 10.7.0.0 + omgt_sa_get_sysimageguid_records@Base 10.7.0.0 + omgt_sa_get_trace_records@Base 10.7.0.0 + omgt_sa_get_vfinfo_records@Base 10.7.0.0 + omgt_sa_get_vlarb_records@Base 10.7.0.0 + omgt_sa_register_trap@Base 10.7.0.0 + omgt_sa_remove_all_pending_reg_msgs@Base 10.7.0.0 + omgt_sa_remove_reg_by_trap_unsafe@Base 10.7.0.0 + omgt_sa_unregister_trap@Base 10.7.0.0 + omgt_send_mad2@Base 10.7.0.0 + omgt_send_recv_mad_alloc@Base 10.7.0.0 + omgt_send_recv_mad_no_alloc@Base 10.7.0.0 + omgt_service_state_totext@Base 10.7.0.0 + omgt_set_dbg@Base 10.7.0.0 + omgt_set_err@Base 10.7.0.0 + omgt_set_retry_count@Base 10.7.0.0 + omgt_set_timeout@Base 10.7.0.0 + omgt_status_totext@Base 10.7.0.0 + omgt_unlock_sem@Base 10.7.0.0 + omgt_xdump@Base 10.7.0.0 + pa_client_clr_port_counters@Base 10.7.0.0 + pgmname@Base 10.7.0.0 + repost_pending_registrations@Base 10.7.0.0 + reregister_traps@Base 10.7.0.0 + set_opapaquery_debug@Base 10.7.0.0 + start_ud_cq_monitor@Base 10.7.0.0 + stl_CopyIbNodeInfo@Base 10.7.0.0 + stl_CopyStlNodeInfo@Base 10.7.0.0 + stl_attribute_str@Base 10.7.0.0 + stl_class_str@Base 10.7.0.0 + stl_mad_status_str@Base 10.7.0.0 + stl_method_str@Base 10.7.0.0 + stop_ud_cq_monitor@Base 10.7.0.0 + userspace_register@Base 10.7.0.0 diff --git a/OpenIb_Host/debian/opa-snapconfig.install b/OpenIb_Host/debian/opa-snapconfig.install new file mode 100644 index 0000000..8790d0e --- /dev/null +++ b/OpenIb_Host/debian/opa-snapconfig.install @@ -0,0 +1 @@ +/usr/lib/opa/tools/opasnapconfig diff --git a/OpenIb_Host/debian/rules b/OpenIb_Host/debian/rules new file mode 100755 index 0000000..3657264 --- /dev/null +++ b/OpenIb_Host/debian/rules @@ -0,0 +1,52 @@ +#!/usr/bin/make -f +# +# Copyright (c) 2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +ifndef RELEASE_TAG + export RELEASE_TAG := $(shell dpkg-parsechangelog -Sversion) +endif + +DESTDIR := debian/tmp + +%: + dh $@ --with systemd --parallel + +override_dh_auto_clean: + rm -rf $(DESTDIR) + +override_dh_auto_build: + # WA for PR139393 + unset LDFLAGS; \ + cd OpenIb_Host; \ + ./ff_build.sh $(CURDIR) $(BUILD_ARGS) + +override_dh_auto_install: + BUILDDIR=$(CURDIR) \ + DESTDIR=$(CURDIR)/$(DESTDIR) \ + LIBDIR=/usr/lib \ + OpenIb_Host/ff_install.sh + diff --git a/OpenIb_Host/debian/source/format b/OpenIb_Host/debian/source/format new file mode 100644 index 0000000..89ae9db --- /dev/null +++ b/OpenIb_Host/debian/source/format @@ -0,0 +1 @@ +3.0 (native) diff --git a/OpenIb_Host/debian/source/options b/OpenIb_Host/debian/source/options new file mode 100644 index 0000000..b7bc1f2 --- /dev/null +++ b/OpenIb_Host/debian/source/options @@ -0,0 +1 @@ +compression = "xz" diff --git a/OpenIb_Host/dobuild b/OpenIb_Host/dobuild new file mode 100755 index 0000000..a8818d6 --- /dev/null +++ b/OpenIb_Host/dobuild @@ -0,0 +1,81 @@ +#!/bin/bash +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +. $ICSBIN/funcs.sh + +# Simple script to perform builds for current system/OS type +export PRODUCT=${PRODUCT:-OPENIB_FF} +export BUILD_TARGET=${BUILD_TARGET:-`uname -m`} + +export BUILD_CONFIG=${BUILD_CONFIG:-"debug"} +export PRODUCT_DIRNAME=${PRODUCT_DIRNAME:-`basename ${PWD}`} + +set -x +{ + echo "Environment:" + env + echo "----------------------------------------------------------------------------" + echo + # Klocwork scan + if [ "$KW_ENABLE" = "yes" ]; then + settl + + # Set Klocwork variables. set_klocwork defines all the Klocwork parameters + # like server url, port number, Klocwork installationpath etc., + source $ICSBIN/set_klocwork -d + + # Check the retrun code of set_klocwork + if [ $? -ne 0 ]; then + echo "Something went wrong" + echo "exiting.." + exit 1 + fi + + # Capture the runmake compilation to kwinject.out using Klocwork's kwinject command + $KW_INJECT ./runmake -B $BUILD_CONFIG $* || exit 1 + + # Execute klocwork_analyze script to run integration analysis and upload + # Klocwork tables to the server + $ICSBIN/klocwork_analyze -p $PRODUCT >> $TL_DIR/$PRODUCT_DIRNAME/build.kw 2>&1 + else + ./runmake -B $BUILD_CONFIG $* || exit 1 + fi +} 2>&1|tee build.res + +# Check Exit Status +exit_status=${PIPESTATUS[0]} +if [ $exit_status -ne 0 ] ; then + echo "FAILED BUILD: A command exited with non-zero status: $exit_status" >> build.res +fi + +set +x + +# Check the results of the build for errors and unexpected warnings. +./check_results -r build.res build.err build.warn diff --git a/OpenIb_Host/expected.err b/OpenIb_Host/expected.err new file mode 100644 index 0000000..cb6629f --- /dev/null +++ b/OpenIb_Host/expected.err @@ -0,0 +1,22 @@ +HostTests/HostTestCases/iv/tools/data/stl1_mpi/wfr_driver/BadICRC.pkt +HostTests/HostTestCases/iv/tools/data/stl1_mpi/wfr_driver/BadJobKey.pkt +HostTests/HostTestCases/iv/tools/data/stl1_mpi/wfr_driver/BadLIDPktA.pkt +HostTests/HostTestCases/iv/tools/data/stl1_mpi/wfr_driver/BadLIDPktB.pkt +HostTests/HostTestCases/iv/tools/data/stl1_mpi/wfr_driver/BadLIDPktC.pkt +HostTests/HostTestCases/iv/tools/data/stl1_mpi/wfr_driver/BadOpcodeA.pkt +HostTests/HostTestCases/iv/tools/data/stl1_mpi/wfr_driver/BadOpcodeB.pkt +HostTests/iv/tools/data/stl1_mpi/wfr_driver/BadICRC.pkt +HostTests/iv/tools/data/stl1_mpi/wfr_driver/BadJobKey.pkt +HostTests/iv/tools/data/stl1_mpi/wfr_driver/BadLIDPktA.pkt +HostTests/iv/tools/data/stl1_mpi/wfr_driver/BadLIDPktB.pkt +HostTests/iv/tools/data/stl1_mpi/wfr_driver/BadLIDPktC.pkt +HostTests/iv/tools/data/stl1_mpi/wfr_driver/BadOpcodeA.pkt +HostTests/iv/tools/data/stl1_mpi/wfr_driver/BadOpcodeB.pkt +U HostTestCases/iv/tools/data/stl1_mpi/wfr_driver/BadICRC.pkt +U HostTestCases/iv/tools/data/stl1_mpi/wfr_driver/BadJobKey.pkt +U HostTestCases/iv/tools/data/stl1_mpi/wfr_driver/BadLIDPktA.pkt +U HostTestCases/iv/tools/data/stl1_mpi/wfr_driver/BadLIDPktB.pkt +U HostTestCases/iv/tools/data/stl1_mpi/wfr_driver/BadLIDPktC.pkt +U HostTestCases/iv/tools/data/stl1_mpi/wfr_driver/BadOpcodeA.pkt +U HostTestCases/iv/tools/data/stl1_mpi/wfr_driver/BadOpcodeB.pkt +HostTests/EoSTL/CV/Tools/data/Host/EM/BadGW_spoofing.pkt diff --git a/OpenIb_Host/expected.warn b/OpenIb_Host/expected.warn new file mode 100644 index 0000000..3f646b1 --- /dev/null +++ b/OpenIb_Host/expected.warn @@ -0,0 +1,65 @@ +getdate.c:28: warning: `%c' yields only last 2 digits of year in some locales +/usr/include/linux/byteorder/swab.h:132: warning: no previous prototype for `__fswab16' +/usr/include/linux/byteorder/swab.h:136: warning: no previous prototype for `__swab16p' +/usr/include/linux/byteorder/swab.h:140: warning: no previous prototype for `__swab16s' +/usr/include/linux/byteorder/swab.h:145: warning: no previous prototype for `__fswab32' +/usr/include/linux/byteorder/swab.h:149: warning: no previous prototype for `__swab32p' +/usr/include/linux/byteorder/swab.h:153: warning: no previous prototype for `__swab32s' +/usr/include/linux/byteorder/swab.h:159: warning: no previous prototype for `__fswab64' +/usr/include/linux/byteorder/swab.h:169: warning: no previous prototype for `__swab64p' +/usr/include/linux/byteorder/swab.h:173: warning: no previous prototype for `__swab64s' +Warning: creating filesystem that does not conform to ISO-9660. +warning: No version string in file: ./bin/opaipcalc +warning: No version string in file: ./arch +warning: No version string in file: ./distro +warning: No version string in file: ./distro_version +warning: No version string in file: ./os_id +warning: No version string in file: ./config/ibhosts +warning: No version string in file: ./include/ics_discovery.h +warning: No version string in file: ./include/ics_portinfo.h +warning: No version string in file: ./include/mtcr.h +warning: No version string in file: ./include/zconf.h +warning: No version string in file: ./include/zlib.h +warning: No version string in file: ./Tests/bin/snapshot_script +warning: No version string in file: ./Tests/bin/tcp_range_script +warning: No version string in file: ./Tests/bin/tcp_rr_script +warning: No version string in file: ./Tests/bin/tcp_stream_script +warning: No version string in file: ./Tests/bin/udp_rr_script +warning: No version string in file: ./Tests/bin/udp_stream_script +warning: No version string in file: ./version +Warning: using transparent compression. This is a nonstandard Rock Ridge +warning: No version string in file: ./fastfabric/samples/iba_topology_1.txt +warning: No version string in file: ./fastfabric/samples/iba_topology_2.txt +warning: No version string in file: ./fastfabric/samples/README.topology +warning: No version string in file: ./fastfabric/samples/iba_topology_CAs.txt +warning: No version string in file: ./fastfabric/samples/iba_topology_SWs.txt +warning: No version string in file: ./fastfabric/samples/iba_topology_links.txt +warning: No version string in file: ./fastfabric/samples/iba_topology_SMs.txt +warning: No version string in file: ./fastfabric/samples/linksum_180.csv +warning: No version string in file: ./fastfabric/samples/linksum_360.csv +warning: No version string in file: ./fastfabric/opatop_group_bw.hlp +warning: No version string in file: ./fastfabric/opatop_group_config.hlp +warning: No version string in file: ./fastfabric/opatop_group_ctg.hlp +warning: No version string in file: ./fastfabric/opatop_group_focus.hlp +warning: No version string in file: ./fastfabric/opatop_group_info_sel.hlp +warning: No version string in file: ./fastfabric/opatop_img_config.hlp +warning: No version string in file: ./fastfabric/opatop_pm_config.hlp +warning: No version string in file: ./fastfabric/opatop_port_stats.hlp +warning: No version string in file: ./fastfabric/opatop_summary.hlp +config.status: WARNING: 'MCONFIG.in' seems to ignore the --datarootdir setting +opapacketcapture.c:870: warning: ignoring return value of 'write', declared with attribute warn_unused_result +opapacketcapture.c:871: warning: ignoring return value of 'write', declared with attribute warn_unused_result +opapacketcapture.c:873: warning: ignoring return value of 'write', declared with attribute warn_unused_result +opapacketcapture.c:876: warning: ignoring return value of 'write', declared with attribute warn_unused_result +opaswfwconfigure.c:1141: warning: ignoring return value of 'chdir', declared with attribute warn_unused_result +opaswfwupdate.c:77: warning: ignoring return value of 'chdir', declared with attribute warn_unused_result +opatop.c:589: warning: ignoring return value of 'system', declared with attribute warn_unused_result +switch_setup.c:135: warning: ignoring return value of 'fgets', declared with attribute warn_unused_result +switch_setup.c:58: warning: ignoring return value of 'fgets', declared with attribute warn_unused_result +switch_setup.c:95: warning: ignoring return value of 'fgets', declared with attribute warn_unused_result +WARNING: `aclocal-1.11' is missing on your system. You should only need it +WARNING: `automake-1.11' is missing on your system. You should only need it +aclocal.m4:16: warning: this file was generated for autoconf 2.67. +configure: WARNING: 'missing' script is too old or missing +nettest_omni.c:94:4: warning: #warning Using our own value for MSG_FASTOPEN [-Wcpp] +stream.c:424:13: warning: variable 'i' set but not used [-Wunused-but-set-variable] diff --git a/OpenIb_Host/ff_build.sh b/OpenIb_Host/ff_build.sh new file mode 100755 index 0000000..dd457e3 --- /dev/null +++ b/OpenIb_Host/ff_build.sh @@ -0,0 +1,81 @@ +#!/bin/bash +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# This is the main build script used within the FF src rpm's %build operation + +# Import the build environment +. ./build.env + +export BUILD_PLATFORM="LINUX" + +source ../MakeTools/funcs-ext.sh + +settarget x86_64 +settl + +# This is a user level file to build the basic project +# One must run target and setver before invoking this script. +# One should set the targeted stack by uncommenting one of the lines below. +export BUILD_WITH_STACK=${BUILD_WITH_STACK:-OPENIB} + +# Simple script to perform builds for current system/OS type +export BUILD_TARGET=${BUILD_TARGET:-`uname -m`} +case $BUILD_TARGET in +i?86) BUILD_TARGET=ia32;; +esac + +export BUILD_CONFIG=${BUILD_CONFIG:-"debug"} +export PRODUCT=${PRODUCT:-OPENIB_FF} + +# for FF the kernel rev is not important. We simply use the kernel rev +# of the running kernel. While BUILD_TARGET_OS_VERSION is needed by Makerules +# it will have no impact on what is actually built for FF +export BUILD_TARGET_OS_VERSION=${BUILD_TARGET_OS_VERSION:-`uname -r`} +setver $BUILD_TARGET_OS_VENDOR $BUILD_TARGET_OS_VERSION +export OPA_FEATURE_SET=opa10 + +MODULEVERSION=`$TL_DIR/MakeTools/format_releasetag.sh $RELEASE_TAG` +RELEASE_STRING=IntelOPA-Tools-FF.$BUILD_TARGET_OS_ID.$MODULEVERSION +echo "stage.OPENIB_FF.$BUILD_CONFIG/$BUILD_TARGET_OS_VENDOR/$BUILD_TARGET/$RELEASE_STRING" > $1/RELEASE_PATH +echo "../bin/$BUILD_TARGET/$BUILD_PLATFORM_OS_VENDOR.$BUILD_PLATFORM_OS_VENDOR_VERSION/lib/$BUILD_CONFIG/" > $1/LIB_PATH +shift + +set -x +{ + echo "Environment:" + env + echo "----------------------------------------------------------------------------" + echo + ./rpm_runmake -B ${BUILD_CONFIG} $* +} 2>&1|tee build.res +set +x + +# Check the results of the build for errors and unexpected warnings. +./check_results -r build.res build.err build.warn diff --git a/OpenIb_Host/ff_build.sh.base b/OpenIb_Host/ff_build.sh.base new file mode 100755 index 0000000..dd457e3 --- /dev/null +++ b/OpenIb_Host/ff_build.sh.base @@ -0,0 +1,81 @@ +#!/bin/bash +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# This is the main build script used within the FF src rpm's %build operation + +# Import the build environment +. ./build.env + +export BUILD_PLATFORM="LINUX" + +source ../MakeTools/funcs-ext.sh + +settarget x86_64 +settl + +# This is a user level file to build the basic project +# One must run target and setver before invoking this script. +# One should set the targeted stack by uncommenting one of the lines below. +export BUILD_WITH_STACK=${BUILD_WITH_STACK:-OPENIB} + +# Simple script to perform builds for current system/OS type +export BUILD_TARGET=${BUILD_TARGET:-`uname -m`} +case $BUILD_TARGET in +i?86) BUILD_TARGET=ia32;; +esac + +export BUILD_CONFIG=${BUILD_CONFIG:-"debug"} +export PRODUCT=${PRODUCT:-OPENIB_FF} + +# for FF the kernel rev is not important. We simply use the kernel rev +# of the running kernel. While BUILD_TARGET_OS_VERSION is needed by Makerules +# it will have no impact on what is actually built for FF +export BUILD_TARGET_OS_VERSION=${BUILD_TARGET_OS_VERSION:-`uname -r`} +setver $BUILD_TARGET_OS_VENDOR $BUILD_TARGET_OS_VERSION +export OPA_FEATURE_SET=opa10 + +MODULEVERSION=`$TL_DIR/MakeTools/format_releasetag.sh $RELEASE_TAG` +RELEASE_STRING=IntelOPA-Tools-FF.$BUILD_TARGET_OS_ID.$MODULEVERSION +echo "stage.OPENIB_FF.$BUILD_CONFIG/$BUILD_TARGET_OS_VENDOR/$BUILD_TARGET/$RELEASE_STRING" > $1/RELEASE_PATH +echo "../bin/$BUILD_TARGET/$BUILD_PLATFORM_OS_VENDOR.$BUILD_PLATFORM_OS_VENDOR_VERSION/lib/$BUILD_CONFIG/" > $1/LIB_PATH +shift + +set -x +{ + echo "Environment:" + env + echo "----------------------------------------------------------------------------" + echo + ./rpm_runmake -B ${BUILD_CONFIG} $* +} 2>&1|tee build.res +set +x + +# Check the results of the build for errors and unexpected warnings. +./check_results -r build.res build.err build.warn diff --git a/OpenIb_Host/ff_filegroups.sh b/OpenIb_Host/ff_filegroups.sh new file mode 100644 index 0000000..e7a0d8f --- /dev/null +++ b/OpenIb_Host/ff_filegroups.sh @@ -0,0 +1,106 @@ +basic_tools_sbin="opacapture opafabricinfo opagetvf opagetvf_env opahfirev + opapacketcapture opaportinfo oparesolvehfiport opasaquery opasmaquery + opainfo" + +basic_tools_sbin_sym="opapmaquery opaportconfig" + +basic_tools_opt="setup_self_ssh usemem opaipcalc stream" + +basic_mans="opacapture.1 opafabricinfo.1 opagetvf.1 + opagetvf_env.1 opahfirev.1 opainfo.1 opapacketcapture.1 opapmaquery.1 + opaportconfig.1 opaportinfo.1 oparesolvehfiport.1 opasaquery.1 + opasmaquery.1" + +basic_configs="opamgt_tls.xml" + +basic_samples="opamgt_tls.xml-sample" + +ff_tools_opt="opaswquery opaswconfigure opaswfwconfigure opaswfwupdate + opaswfwverify opaswping opaswreset" + +ff_tools_exp="basic.exp chassis.exp chassis_configure.exp chassis_fmconfig.exp + chassis_fmcontrol.exp chassis_fmgetconfig.exp chassis_getconfig.exp + chassis_reboot.exp chassis_fmgetsecurityfiles.exp chassis_fmsecurityfiles.exp + chassis_upgrade.exp common_funcs.exp configipoib.exp extmng.exp ff_function.exp + ib.exp opa_to_xml.exp ibtools.exp install.exp ipoibping.exp load.exp mpi.exp + mpiperf.exp mpiperfdeviation.exp network.exp proc_mgr.exp reboot.exp sacache.exp + sm_control.exp switch_capture.exp switch_configure.exp switch_dump.exp + switch_fwverify.exp switch_getconfig.exp switch_hwvpd.exp switch_info.exp + switch_ping.exp switch_reboot.exp switch_upgrade.exp target.exp tools.exp + upgrade.exp tclIndex tcl_proc comm12 front" + +ff_tools_sbin="opacabletest opacheckload opaextracterror opaextractlink + opaextractperf opaextractstat opaextractstat2 opafindgood opafirmware + opagenchassis opagenesmchassis opagenswitches opalinkanalysis opareport + opareports opasorthosts opatop opaxlattopology opaxmlextract + opaxmlfilter opaxmlgenerate opaxmlindent opaallanalysis opacaptureall + opachassisanalysis opacmdall opadownloadall opaesmanalysis opafabricanalysis + opafastfabric opahostsmanalysis opadisablehosts opadisableports opaenableports + opaledports opaexpandfile opaextractbadlinks opaextractlids opaextractsellinks + opaextractmissinglinks opaswenableall opaswdisableall opaverifyhosts opahostadmin + opachassisadmin opaswitchadmin opapingall opascpall opasetupssh opashowallports + opauploadall opapaquery opashowmc opa2rm opaextractperf2 opamergeperf2" + +ff_tools_misc="ff_funcs opachassisip opagenswitcheshelper chassis_setup + switch_setup opagetipaddrtype opafastfabric.conf.def show_counts opacablehealthcron" + +ff_tools_fm="config_generate config_diff config_check config_convert" + +ff_libs_misc="libqlgc_fork.so" + +ff_mans="opaallanalysis.8 opacabletest.8 opacaptureall.8 opachassisadmin.8 + opachassisanalysis.8 opacheckload.8 opacmdall.8 opadisablehosts.8 + opadisableports.8 opadownloadall.8 opaenableports.8 opaledports.8 + opaesmanalysis.8 opaexpandfile.8 opaextractbadlinks.8 opaextracterror.8 + opaextractlids.8 opaextractlink.8 opaextractperf.8 opaextractsellinks.8 + opaextractstat.8 opaextractstat2.8 opafabricanalysis.8 opafastfabric.8 + opafindgood.8 opafmconfigcheck.8 opafmconfigdiff.8 opagenchassis.8 + opagenesmchassis.8 opagenswitches.8 opagentopology.8 opahostadmin.8 + opahostsmanalysis.8 opalinkanalysis.8 opapaquery.8 opapingall.8 opareport.8 + opareports.8 opascpall.8 opasetupssh.8 opashowallports.8 opasorthosts.8 + opaswitchadmin.8 opatop.8 opauploadall.8 opaverifyhosts.8 opaxlattopology.8 + opashowmc.8 opaxmlextract.8 opaxmlfilter.8 opaextractperf2.8 opamergeperf2.8 + opaxmlgenerate.8 opaxmlindent.8 opaswdisableall.8 opaswenableall.8 + opafirmware.8 opaextractmissinglinks.8 opa2rm.8" + +ff_iba_samples="hostverify.sh opatopology_FIs.txt opatopology_links.txt opatopology_SMs.txt + opatopology_SWs.txt linksum_swd06.csv linksum_swd24.csv README.topology + README.xlat_topology minimal_topology.xlsx detailed_topology.xlsx allhosts-sample chassis-sample + hosts-sample switches-sample ports-sample mac_to_dhcp filterFile.txt triggerFile.txt + opamon.conf-sample opamon.si.conf-sample opafastfabric.conf-sample + opa_ca_openssl.cnf-sample opa_comp_openssl.cnf-sample opagentopology esm_chassis-sample" + +help_doc="opatop_group_bw.hlp opatop_group_config.hlp opatop_group_ctg.hlp + opatop_group_focus.hlp opatop_group_info_sel.hlp opatop_img_config.hlp + opatop_pm_config.hlp opatop_port_stats.hlp opatop_summary.hlp opatop_vf_bw.hlp + opatop_vf_info_sel.hlp opatop_vf_config.hlp" + +opasadb_bin="opa_osd_dump opa_osd_exercise opa_osd_perf opa_osd_query opa_osd_query_many opa_osd_load" + +opasadb_header="opasadb.h opasadb_path.h opasadb_route.h opasadb_route2.h" + +opasadb_mans="opa_osd_dump.1 opa_osd_exercise.1 opa_osd_perf.1 opa_osd_query.1" + +opamgt_headers="opamgt.h opamgt_pa.h opamgt_sa.h opamgt_sa_notice.h" + +opamgt_iba_headers="ib_mad.h ib_sa_records.h ib_sd.h ib_sm_types.h + ib_status.h ib_types.h stl_mad_types.h stl_pa_types.h + stl_sa_types.h stl_sd.h stl_sm_types.h stl_types.h" + +opamgt_iba_public_headers="datatypes.h datatypes_osd.h ibyteswap.h ibyteswap_osd.h + ilist.h imath.h imemory.h imemory_osd.h ipackoff.h ipackon.h ispinlock.h + ispinlock_osd.h statustext.h iethernet.h" + +opamgt_examples="paquery.c saquery.c simple_sa_query.c simple_sa_notice.c simple_pa_query.c + job_schedule.c show_switch_cost_matrix.c Makefile README" + +mpi_apps_files="Makefile mpi_hosts.sample README prepare_run select_mpi run_bw + get_selected_mpi.sh get_mpi_cc.sh *.params gen_group_hosts gen_mpi_hosts + mpi_cleanup stop_daemons hpl_dat_gen config_hpl2 run_hpl2 run_lat run_imb run_lat2 + run_bw2 run_bibw2 run_bcast2 run_app runmyapp mpicheck run_mpicheck run_deviation + run_multibw run_mpi_stress run_osu run_cabletest run_allhfilatency run_nxnlatbw + run_alltoall3 run_bcast3 run_bibw3 run_bw3 run_lat3 run_mbw_mr3 run_multi_lat3 + run_batch_script run_batch_cabletest hpl-count.diff groupstress deviation + hpl-config/HPL.dat-* hpl-config/README mpicc mpif77" + +opasnapconfig_bin= diff --git a/OpenIb_Host/ff_filegroups.sh.base b/OpenIb_Host/ff_filegroups.sh.base new file mode 100644 index 0000000..e7a0d8f --- /dev/null +++ b/OpenIb_Host/ff_filegroups.sh.base @@ -0,0 +1,106 @@ +basic_tools_sbin="opacapture opafabricinfo opagetvf opagetvf_env opahfirev + opapacketcapture opaportinfo oparesolvehfiport opasaquery opasmaquery + opainfo" + +basic_tools_sbin_sym="opapmaquery opaportconfig" + +basic_tools_opt="setup_self_ssh usemem opaipcalc stream" + +basic_mans="opacapture.1 opafabricinfo.1 opagetvf.1 + opagetvf_env.1 opahfirev.1 opainfo.1 opapacketcapture.1 opapmaquery.1 + opaportconfig.1 opaportinfo.1 oparesolvehfiport.1 opasaquery.1 + opasmaquery.1" + +basic_configs="opamgt_tls.xml" + +basic_samples="opamgt_tls.xml-sample" + +ff_tools_opt="opaswquery opaswconfigure opaswfwconfigure opaswfwupdate + opaswfwverify opaswping opaswreset" + +ff_tools_exp="basic.exp chassis.exp chassis_configure.exp chassis_fmconfig.exp + chassis_fmcontrol.exp chassis_fmgetconfig.exp chassis_getconfig.exp + chassis_reboot.exp chassis_fmgetsecurityfiles.exp chassis_fmsecurityfiles.exp + chassis_upgrade.exp common_funcs.exp configipoib.exp extmng.exp ff_function.exp + ib.exp opa_to_xml.exp ibtools.exp install.exp ipoibping.exp load.exp mpi.exp + mpiperf.exp mpiperfdeviation.exp network.exp proc_mgr.exp reboot.exp sacache.exp + sm_control.exp switch_capture.exp switch_configure.exp switch_dump.exp + switch_fwverify.exp switch_getconfig.exp switch_hwvpd.exp switch_info.exp + switch_ping.exp switch_reboot.exp switch_upgrade.exp target.exp tools.exp + upgrade.exp tclIndex tcl_proc comm12 front" + +ff_tools_sbin="opacabletest opacheckload opaextracterror opaextractlink + opaextractperf opaextractstat opaextractstat2 opafindgood opafirmware + opagenchassis opagenesmchassis opagenswitches opalinkanalysis opareport + opareports opasorthosts opatop opaxlattopology opaxmlextract + opaxmlfilter opaxmlgenerate opaxmlindent opaallanalysis opacaptureall + opachassisanalysis opacmdall opadownloadall opaesmanalysis opafabricanalysis + opafastfabric opahostsmanalysis opadisablehosts opadisableports opaenableports + opaledports opaexpandfile opaextractbadlinks opaextractlids opaextractsellinks + opaextractmissinglinks opaswenableall opaswdisableall opaverifyhosts opahostadmin + opachassisadmin opaswitchadmin opapingall opascpall opasetupssh opashowallports + opauploadall opapaquery opashowmc opa2rm opaextractperf2 opamergeperf2" + +ff_tools_misc="ff_funcs opachassisip opagenswitcheshelper chassis_setup + switch_setup opagetipaddrtype opafastfabric.conf.def show_counts opacablehealthcron" + +ff_tools_fm="config_generate config_diff config_check config_convert" + +ff_libs_misc="libqlgc_fork.so" + +ff_mans="opaallanalysis.8 opacabletest.8 opacaptureall.8 opachassisadmin.8 + opachassisanalysis.8 opacheckload.8 opacmdall.8 opadisablehosts.8 + opadisableports.8 opadownloadall.8 opaenableports.8 opaledports.8 + opaesmanalysis.8 opaexpandfile.8 opaextractbadlinks.8 opaextracterror.8 + opaextractlids.8 opaextractlink.8 opaextractperf.8 opaextractsellinks.8 + opaextractstat.8 opaextractstat2.8 opafabricanalysis.8 opafastfabric.8 + opafindgood.8 opafmconfigcheck.8 opafmconfigdiff.8 opagenchassis.8 + opagenesmchassis.8 opagenswitches.8 opagentopology.8 opahostadmin.8 + opahostsmanalysis.8 opalinkanalysis.8 opapaquery.8 opapingall.8 opareport.8 + opareports.8 opascpall.8 opasetupssh.8 opashowallports.8 opasorthosts.8 + opaswitchadmin.8 opatop.8 opauploadall.8 opaverifyhosts.8 opaxlattopology.8 + opashowmc.8 opaxmlextract.8 opaxmlfilter.8 opaextractperf2.8 opamergeperf2.8 + opaxmlgenerate.8 opaxmlindent.8 opaswdisableall.8 opaswenableall.8 + opafirmware.8 opaextractmissinglinks.8 opa2rm.8" + +ff_iba_samples="hostverify.sh opatopology_FIs.txt opatopology_links.txt opatopology_SMs.txt + opatopology_SWs.txt linksum_swd06.csv linksum_swd24.csv README.topology + README.xlat_topology minimal_topology.xlsx detailed_topology.xlsx allhosts-sample chassis-sample + hosts-sample switches-sample ports-sample mac_to_dhcp filterFile.txt triggerFile.txt + opamon.conf-sample opamon.si.conf-sample opafastfabric.conf-sample + opa_ca_openssl.cnf-sample opa_comp_openssl.cnf-sample opagentopology esm_chassis-sample" + +help_doc="opatop_group_bw.hlp opatop_group_config.hlp opatop_group_ctg.hlp + opatop_group_focus.hlp opatop_group_info_sel.hlp opatop_img_config.hlp + opatop_pm_config.hlp opatop_port_stats.hlp opatop_summary.hlp opatop_vf_bw.hlp + opatop_vf_info_sel.hlp opatop_vf_config.hlp" + +opasadb_bin="opa_osd_dump opa_osd_exercise opa_osd_perf opa_osd_query opa_osd_query_many opa_osd_load" + +opasadb_header="opasadb.h opasadb_path.h opasadb_route.h opasadb_route2.h" + +opasadb_mans="opa_osd_dump.1 opa_osd_exercise.1 opa_osd_perf.1 opa_osd_query.1" + +opamgt_headers="opamgt.h opamgt_pa.h opamgt_sa.h opamgt_sa_notice.h" + +opamgt_iba_headers="ib_mad.h ib_sa_records.h ib_sd.h ib_sm_types.h + ib_status.h ib_types.h stl_mad_types.h stl_pa_types.h + stl_sa_types.h stl_sd.h stl_sm_types.h stl_types.h" + +opamgt_iba_public_headers="datatypes.h datatypes_osd.h ibyteswap.h ibyteswap_osd.h + ilist.h imath.h imemory.h imemory_osd.h ipackoff.h ipackon.h ispinlock.h + ispinlock_osd.h statustext.h iethernet.h" + +opamgt_examples="paquery.c saquery.c simple_sa_query.c simple_sa_notice.c simple_pa_query.c + job_schedule.c show_switch_cost_matrix.c Makefile README" + +mpi_apps_files="Makefile mpi_hosts.sample README prepare_run select_mpi run_bw + get_selected_mpi.sh get_mpi_cc.sh *.params gen_group_hosts gen_mpi_hosts + mpi_cleanup stop_daemons hpl_dat_gen config_hpl2 run_hpl2 run_lat run_imb run_lat2 + run_bw2 run_bibw2 run_bcast2 run_app runmyapp mpicheck run_mpicheck run_deviation + run_multibw run_mpi_stress run_osu run_cabletest run_allhfilatency run_nxnlatbw + run_alltoall3 run_bcast3 run_bibw3 run_bw3 run_lat3 run_mbw_mr3 run_multi_lat3 + run_batch_script run_batch_cabletest hpl-count.diff groupstress deviation + hpl-config/HPL.dat-* hpl-config/README mpicc mpif77" + +opasnapconfig_bin= diff --git a/OpenIb_Host/ff_install.sh b/OpenIb_Host/ff_install.sh new file mode 100755 index 0000000..9430648 --- /dev/null +++ b/OpenIb_Host/ff_install.sh @@ -0,0 +1,121 @@ +#!/bin/bash +set -x + +[ -z "${BUILDDIR}" ] && BUILDDIR="." +[ -z "${DESTDIR}" ] && DESTDIR="/" +[ -z "${LIBDIR}" ] && LIBDIR=/usr/lib +[ -z "${DSAP_LIBDIR}" ] && DSAP_LIBDIR="$DSAP_LIBDIR" + +if [ -n ${DSAP_LIBDIR}]; then + DSAP_LIBDIR="/usr/lib" +fi + +if [ ! -f "${BUILDDIR}/RELEASE_PATH" ]; then + echo "Wrong BUILDDIR? No such file ${BUILDDIR}/RELEASE_PATH" + exit 1 +fi + +source OpenIb_Host/ff_filegroups.sh + +release_string="IntelOPA-Tools-FF.$BUILD_TARGET_OS_ID.$MODULEVERSION" + +mkdir -p ${DESTDIR}/usr/bin +mkdir -p ${DESTDIR}/usr/sbin +mkdir -p ${DESTDIR}/usr/lib/opa/{tools,fm_tools} +mkdir -p ${DESTDIR}/usr/share/opa/{samples,help} +mkdir -p ${DESTDIR}/${DSAP_LIBDIR}/ibacm +mkdir -p ${DESTDIR}/etc/rdma +mkdir -p ${DESTDIR}/etc/opa +mkdir -p ${DESTDIR}/etc/cron.d +mkdir -p ${DESTDIR}/usr/include/infiniband +mkdir -p ${DESTDIR}/usr/include/opamgt/iba/public +mkdir -p ${DESTDIR}/usr/src/opamgt +mkdir -p ${DESTDIR}/usr/share/man/man1 +mkdir -p ${DESTDIR}/usr/share/man/man8 +mkdir -p ${DESTDIR}/usr/src/opa/mpi_apps + +#Binaries and scripts installing (basic tools) +#cd builtbin.OPENIB_FF.release +cd $(cat ${BUILDDIR}/RELEASE_PATH) + +cd bin +cp -t ${DESTDIR}/usr/sbin $basic_tools_sbin +cp -t ${DESTDIR}/usr/lib/opa/tools/ $basic_tools_opt +ln -s ./opaportinfo ${DESTDIR}/usr/sbin/opaportconfig +ln -s ./opasmaquery ${DESTDIR}/usr/sbin/opapmaquery + +cd ../opasadb +cp -t ${DESTDIR}/usr/bin $opasadb_bin +cp -t ${DESTDIR}/usr/include/infiniband $opasadb_header + +cd ../opamgt +cp -t ${DESTDIR}/usr/include/opamgt $opamgt_headers +cp -t ${DESTDIR}/usr/include/opamgt/iba $opamgt_iba_headers +cp -t ${DESTDIR}/usr/include/opamgt/iba/public $opamgt_iba_public_headers +cp -t ${DESTDIR}/usr/src/opamgt $opamgt_examples + +OPAMGT_VERNO_MAJOR=$(cat version | cut -d . -f 1) + +cd ../bin +cp -t ${DESTDIR}/usr/lib/opa/tools/ $ff_tools_opt +cp -t ${DESTDIR}/usr/lib/opa/tools/ $opasnapconfig_bin + +cd ../fastfabric +cp -t ${DESTDIR}/usr/sbin $ff_tools_sbin +cp -t ${DESTDIR}/usr/lib/opa/tools/ $ff_tools_misc +cp -t ${DESTDIR}/usr/share/opa/help $help_doc +cp -t ${DESTDIR}/etc/opa $basic_configs + +cd ../etc +cp -t ${DESTDIR}/usr/lib/opa/fm_tools/ $ff_tools_fm +ln -s /usr/lib/opa/fm_tools/config_check ${DESTDIR}/usr/sbin/opafmconfigcheck +ln -s /usr/lib/opa/fm_tools/config_diff ${DESTDIR}/usr/sbin/opafmconfigdiff +cd cron.d +cp -t ${DESTDIR}/etc/cron.d opa-cablehealth +cd .. + +cd ../fastfabric/samples +cp -t ${DESTDIR}/usr/share/opa/samples $ff_iba_samples $basic_samples +cd .. + +cd ../fastfabric/tools +cp -t ${DESTDIR}/usr/lib/opa/tools/ $ff_tools_exp +cp -t ${DESTDIR}/usr/lib/opa/tools/ $ff_libs_misc +cp -t ${DESTDIR}/usr/lib/opa/tools/ osid_wrapper +cp -t ${DESTDIR}/etc/opa allhosts chassis esm_chassis hosts ports switches +cd .. + +cd ../man/man1 +cp -t ${DESTDIR}/usr/share/man/man1 $basic_mans +cp -t ${DESTDIR}/usr/share/man/man1 $opasadb_mans +cd ../man8 +cp -t ${DESTDIR}/usr/share/man/man8 $ff_mans +cd .. + +cd ../src/mpi/mpi_apps +tar -xzf mpi_apps.tgz -C ${DESTDIR}/usr/src/opa/mpi_apps/ +cd ../../ + +#Config files +cd ../config +cp -t ${DESTDIR}/etc/rdma dsap.conf +cp -t ${DESTDIR}/etc/rdma op_path_rec.conf +cp -t ${DESTDIR}/etc/rdma opasadb.xml +cp -t ${DESTDIR}/etc/opa opamon.conf opamon.si.conf + +#Libraries installing +#cd ../builtlibs.OPENIB_FF.release +cd $(cat $BUILDDIR/LIB_PATH) +cp -t ${DESTDIR}/${DSAP_LIBDIR} libopasadb.so.* +ln -s libopasadb.so.* ${DESTDIR}/${DSAP_LIBDIR}/libopasadb.so.1 +ln -s libopasadb.so.1 ${DESTDIR}/${DSAP_LIBDIR}/libopasadb.so +cp -t ${DESTDIR}/${DSAP_LIBDIR}/ibacm libdsap.so.* +cp -t ${DESTDIR}/usr/lib libopamgt.so.* +ln -s libopamgt.so.${OPAMGT_VERNO_MAJOR} ${DESTDIR}/usr/lib/libopamgt.so + + +# Now that we've put everything in the buildroot, copy any default config files to their expected location for user +# to edit. To prevent nuking existing user configs, the files section of this spec file will reference these as noreplace +# config files. +cp ${DESTDIR}/usr/lib/opa/tools/opafastfabric.conf.def ${DESTDIR}/etc/opa/opafastfabric.conf + diff --git a/OpenIb_Host/mpi-apps.spec.in b/OpenIb_Host/mpi-apps.spec.in new file mode 100644 index 0000000..2d03021 --- /dev/null +++ b/OpenIb_Host/mpi-apps.spec.in @@ -0,0 +1,54 @@ +Name: opa-mpi-apps +Version: __RPM_VERSION +Release: __RPM_RELEASE +Summary: Intel MPI benchmarks and Applications used by opa-fast-fabric +Group: System Environment/Libraries +License: GPLv2/BSD +Url: http://www.intel.com/ +Source: opa-mpi-apps.tgz + +AutoReq: no +__RPM_REQ + +BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) + +%description +Contains applications and source for testing MPI performance in conjunction with opa-fastfabric or stand alone. +IFSComponent: Tools_FF __RPM_VERSION.__RPM_RELEASE + +__RPM_DBG + +%prep +%setup -q -c + + +%build + + + +%install + +%define mpi_apps_files bandwidth latency osu2 hpl-2.2 imb osu-micro-benchmarks-3.8-July12 mpi_multibw + + +mkdir -p $RPM_BUILD_ROOT/usr/src/opa/mpi_apps + +cd ./MpiApps +cp ./apps/* -r $RPM_BUILD_ROOT/usr/src/opa/mpi_apps/ + +echo "/usr/src/opa/mpi_apps/%{mpi_apps_files}" > %{_builddir}/mpi_apps.list +sed -i 's;[ ];\n/usr/src/opa/mpi_apps/;g' %{_builddir}/mpi_apps.list + + +%clean +rm -rf $RPM_BUILD_ROOT + +%files -f %{_builddir}/mpi_apps.list + +%changelog +* Mon Feb 26 2018 Jijun Wang - 10.8.0.0 +- Added component information in description for all rpms +* Wed Dec 2 2015 Brandon Yates +- Initial Creation + + diff --git a/OpenIb_Host/mpiapps_tar_manifest b/OpenIb_Host/mpiapps_tar_manifest new file mode 100644 index 0000000..058bb0e --- /dev/null +++ b/OpenIb_Host/mpiapps_tar_manifest @@ -0,0 +1,9 @@ +MpiApps/apps/osu-micro-benchmarks-3.8-July12 +MpiApps/apps/osu2 +MpiApps/apps/bandwidth +MpiApps/apps/latency +MpiApps/apps/hpl-2.2 +MpiApps/apps/imb +MpiApps/apps/mpi_multibw +MpiApps/debian +OpenIb_Host/debian diff --git a/OpenIb_Host/opa.spec.in b/OpenIb_Host/opa.spec.in new file mode 100644 index 0000000..c2fd56c --- /dev/null +++ b/OpenIb_Host/opa.spec.in @@ -0,0 +1,173 @@ +Name: opa +Version: __RPM_VERSION +Release: __RPM_RELEASE +Summary: Intel Omni-Path basic tools and libraries for fabric managment. + +Group: System Environment/Libraries +License: BSD +Url: https://github.com/intel/opa-ff +# tarball created by: +# git clone https://github.com/intel/opa-ff.git +# cd opa-ff +# tar czf opa.tgz --exclude-vcs . +Source: opa.tgz +ExclusiveArch: x86_64 +# The Intel(R) OPA product line is only available on x86_64 platforms at this time. + +__RPM_DEBUG_PKG + +%description +This package contains the tools necessary to manage an Intel(R) Omni-Path Architecture fabric. +IFSComponent: Tools_FF __RPM_VERSION.__RPM_RELEASE + +%package basic-tools +Summary: Managment level tools and scripts. +Group: System Environment/Libraries + +Requires: rdma bc + +Requires: __RPM_REQ_BASIC +BuildRequires: __RPM_BLDREQ +__RPM_EPOCH_BASIC + +%description basic-tools +Contains basic tools for fabric managment necessary on all compute nodes. +IFSComponent: Tools_FF __RPM_VERSION.__RPM_RELEASE + +%package fastfabric +Summary: Management level tools and scripts. +Group: System Environment/Libraries +Requires: opa-basic-tools cronie + +__RPM_EPOCH_FF + +%description fastfabric +Contains tools for managing fabric on a managment node. +IFSComponent: Tools_FF __RPM_VERSION.__RPM_RELEASE + +%package address-resolution +Summary: Contains Address Resolution manager +Group: System Environment/Libraries +Requires: __RPM_REQ_ADDR_RES +__RPM_EPOCH_ADDR_RES + +%description address-resolution +This package contains the ibacm distributed SA provider (dsap) for name and address resolution on OPA platform. +It also contains the library and tools to access the shared memory database exported by dsap. +IFSComponent: Tools_FF __RPM_VERSION.__RPM_RELEASE + +#opasnapconfig +%package snapconfig +Summary: Configure fabric with snapshot file +Group: System Environment/Libraries +AutoReq: no +Requires: opa-fastfabric + +%description snapconfig +Parse information from provided snapshot file and issue packets to program +IFSComponent: Tools_FF __RPM_VERSION.__RPM_RELEASE + +%package libopamgt +Summary: Omni-Path management API library +Group: System Environment/Libraries +Requires: __RPM_REQ_OPAMGT +__RPM_EPOCH_LIBOPAMGT + +%description libopamgt +This package contains the library necessary to build applications that interface with an Omni-Path FM. +IFSComponent: Tools_FF __RPM_VERSION.__RPM_RELEASE + +%package libopamgt-devel +Summary: Omni-Path library development headers +Group: System Environment/Libraries +Requires: __RPM_REQ_OPAMGT_DEV +__RPM_EPOCH_LIBOPAMGT + +%description libopamgt-devel +This package contains the necessary headers for opamgt development. +IFSComponent: Tools_FF __RPM_VERSION.__RPM_RELEASE + +%prep +#rm -rf %{_builddir}/* +#tar xzf %_sourcedir/%name.tgz + +%setup -q -c + +%build +cd OpenIb_Host +__RPM_FS ./ff_build.sh %{_builddir} $BUILD_ARGS + +%install +BUILDDIR=%{_builddir} DESTDIR=%{buildroot} LIBDIR=/usr/lib DSAP_LIBDIR=%{_libdir} ./ff_install.sh + +%post address-resolution -p /sbin/ldconfig +%postun address-resolution -p /sbin/ldconfig + +%preun fastfabric +cd /usr/src/opa/mpi_apps >/dev/null 2>&1 +make -k clean >/dev/null 2>&1 || : # suppress all errors and return codes from the make clean. + +%post libopamgt -p /sbin/ldconfig +%postun libopamgt -p /sbin/ldconfig + +%preun libopamgt-devel +cd /usr/src/opamgt >/dev/null 2>&1 +make -k clean >/dev/null 2>&1 || : + +%files basic-tools +__RPM_BASIC_FILES +%config(noreplace) %{_sysconfdir}/opa/opamgt_tls.xml + +%files fastfabric +__RPM_FF_FILES +%{_sysconfdir}/opa/opamon.si.conf +# Replace opamon.si.conf, as it's a template config file. +%config(noreplace) %{_sysconfdir}/opa/opafastfabric.conf +%config(noreplace) %{_sysconfdir}/opa/opamon.conf +%config(noreplace) %{_sysconfdir}/opa/allhosts +%config(noreplace) %{_sysconfdir}/opa/chassis +%config(noreplace) %{_sysconfdir}/opa/esm_chassis +%config(noreplace) %{_sysconfdir}/opa/hosts +%config(noreplace) %{_sysconfdir}/opa/ports +%config(noreplace) %{_sysconfdir}/opa/switches +%config(noreplace) %{_sysconfdir}/cron.d/opa-cablehealth +%config(noreplace) /usr/lib/opa/tools/osid_wrapper + + +%files address-resolution +%{_bindir}/opa_osd_dump +%{_bindir}/opa_osd_exercise +%{_bindir}/opa_osd_perf +%{_bindir}/opa_osd_query +%{_bindir}/opa_osd_query_many +%{_bindir}/opa_osd_load +%{_libdir}/ibacm +%{_libdir}/libopasadb.so* +%{_includedir}/infiniband +%{_mandir}/man1/opa_osd_dump.1* +%{_mandir}/man1/opa_osd_exercise.1* +%{_mandir}/man1/opa_osd_perf.1* +%{_mandir}/man1/opa_osd_query.1* +%config(noreplace) %{_sysconfdir}/rdma/dsap.conf +%config(noreplace) %{_sysconfdir}/rdma/op_path_rec.conf +%{_sysconfdir}/rdma/opasadb.xml + +%files snapconfig +__RPM_SNAP_FILES + +%files libopamgt +/usr/lib/libopamgt.* + + +%files libopamgt-devel +%{_includedir}/opamgt +/usr/src/opamgt + +%changelog +* Mon Feb 26 2018 Jijun Wang - 10.8.0.0 +- Added epoch for RHEL address-resolution, basic-tools and fastfabric +- Added component information in description for all rpms +* Thu Apr 13 2017 Scott Breyer - 10.5.0.0 +- Updates for spec file cleanup +* Fri Oct 10 2014 Erik E. Kahn - 1.0.0-ifs +- Initial version diff --git a/OpenIb_Host/rpm_runmake b/OpenIb_Host/rpm_runmake new file mode 100755 index 0000000..422ead3 --- /dev/null +++ b/OpenIb_Host/rpm_runmake @@ -0,0 +1,180 @@ +#!/bin/bash +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** +## +## rpm_runmake +## ----------- +## Perform a full build +## This is used within the FF src rpm by the ff_build.sh script +## and for in-place builds its invoked directly by runmake +## When this is invoked, the current directory will be the TL_DIR for +## the source tree of FF +## +## Usage: +## rpm_runmake [-B 'build_config'] [-n] +## or +## rpm_runmake -r [-B 'build_config'] [-C] [-n] +## +## Arguments: +## -B build_config release type to build, (debug/release). default is release +## -r rerun the build in place without doing a new checkout/tag +## -C don't clobber prior to the rerun +## -n No build. Useful for checking build machine +## +## In addition, the following environment variables are expected to be set: +## RELEASE_TAG, BRANCH_TAG, BUILD_TARGET, PRODUCT, RELEASE_HOME, BUILD_CONFIG +## The target command is expected to have already been run to set up the +## environment for the specified target +## +## re-run can be used for 2 situations: +## 1. re-run a failed build to correct incorrect weeklybuild arguments +## or other non-source code related problems (out of disk space) +## 2. re-run a build for a different BUILD_TARGET_OS_VERSION while using the same +## source code image/tag +## If the source code needs to be corrected, a full weeklybuild should be run +## after the correction such that the code is properly tagged. +## +## Since weeklybuild and target commands always set BUILD_CONFIG, this +## script ignores BUILD_CONFIG. As such the BuildOptions file +## or the -B argument completely control BUILD_CONFIG for this product. + +# A given release will be targeted for a specific version of ofed +# however we allow build.config to override if needed +export OFED_STACK_PREFIX=${OFED_STACK_PREFIX:-/usr} + +Usage() +{ + # include "ERROR" in message so weeklybuild catches it in error log + echo "ERROR: rpm_runmake failed" >&2 + echo "Usage: rpm_runmake [-B 'build_config'] [-n]" >&2 + echo " OR" >&2 + echo " rpm_runmake -r [-B 'build_config'] [-C] [-n]" >&2 + exit 2 +} + +showbuild() +{ + # output summary of what we are building to stdout + echo "Building for $SUBPRODUCT $BUILD_TARGET $BUILD_CONFIG $(date)..." + #echo "Building for $BUILD_TARGET_OS $BUILD_TARGET $BUILD_TARGET_OS_VERSION $BUILD_CONFIG $(date)..." +} + +build_config= +rerun=n +Cflag=n +while getopts B:rCn param +do + case $param in + r) + rerun=y;; + B) + build_config="$OPTARG";; + C) + Cflag=y;; + n) + nflag=y;; + ?) + Usage + esac +done +shift $(($OPTIND -1)) + +if [ $# != 0 ] +then + Usage +fi + +if [ -z "$build_config" ] +then + # default to release build + export BUILD_CONFIG=release +elif [ "$build_config" != debug -a "$build_config" != release ] +then + Usage +else + export BUILD_CONFIG="$build_config" +fi + +export PROJ_FILE_DIR=OpenIb_Host + +if [ "$BUILD_WITH_STACK" = "OPENIB" ] +then + if [ ! -d $OFED_STACK_PREFIX ] + then + echo "$0: ERROR: OFED stack not found: $OFED_STACK_PREFIX" >&2 + exit 1 + fi + echo "Stack to build for: $BUILD_WITH_STACK ($OFED_STACK_PREFIX)" +else + echo "Stack to build for: $BUILD_WITH_STACK" +fi + +if [ "$nflag" = "y" ] +then + exit 0 +fi + +# when inplace developer builds have been done, the src rpm will include +# prebuilt code. if the -C option is not specified (via BUILD_ARGS) +# clobber any such files if they are present (indicated by builtinplace file). +# The clobber allows a src.rpm packaged with an in-place build to still +# generate normally when -C not given. +# No need to check rerun flag because for rpms we always start fresh from what +# was inside the src rpm and for runmake we can test built* to decide if the +# clobber is needed +clobber_arg= +if [ "$Cflag" != y ] +then + # force full rebuild + if [ -e $TL_DIR/builtinplace.$PRODUCT.$BUILD_CONFIG \ + -o -e $TL_DIR/builtinclude.$PRODUCT.$BUILD_CONFIG \ + -o -e $TL_DIR/builtlibs.$PRODUCT.$BUILD_CONFIG \ + -o -e $TL_DIR/builtbin.$PRODUCT.$BUILD_CONFIG ] + then + export REMOVE_DEPENDS=yes + clobber_arg="clobber clobber_stage clobber_release" + fi +fi +rm -rf packaged_files dist_files + +# export DATE for use by prep so all files get same date/time stamp +DATE=${DATE:-"`date +'%m/%d/%y %H:%M'`"} + +# Do the actual MAKE +showbuild +env +make $clobber_arg stage +echo "Done $BUILD_TARGET_OS $BUILD_TARGET Fast Fabric $SUBPRODUCT $(date)" +echo "==============================================================" + +echo "Preping Files for $BUILD_TARGET_OS $BUILD_TARGET $(date)..." +# run prep and package once at end +# TBD - move package into outer final_package step and remove from here +# consolidate Makefile accordingly to have one package target +make prepfiles package diff --git a/OpenIb_Host/runmake b/OpenIb_Host/runmake new file mode 100755 index 0000000..ccf8456 --- /dev/null +++ b/OpenIb_Host/runmake @@ -0,0 +1,503 @@ +#!/bin/bash +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** +## +## runmake +## ----------- +## Perform a full build +## This is used by the weeklybuild script to provide product specific +## build operations for product's whose build is more complex +## than simply a "make stage prepfiles" +## When this is invoked, the current directory will be the TL_DIR for a +## full checkout of the product to be built +## +## Usage: +## runmake [-B 'build_config'] [-n] +## or +## runmake -r [-B 'build_config'] [-iCRP] [-n] +## +## Arguments: +## -f options_file - depricated, see -B +## -B build_config release types to build, (debug/release). default is release +## -V os_version - depricated, N/A +## -r rerun the build in place without doing a new checkout/tag +## -i allow incremental builds by building in-place before package rpm +## -R skip building rpm, just leave in-place files +## -C don't clobber prior to the rerun +## -P skip building and packaging IntelOPA-Tests +## -O depricated, N/A +## -n No build. Useful for checking build machine +## -T PROJ_FILE_DIR - depricated, PROJ_FILE_DIR always set to OpenIb_Host +## +## In addition, the following environment variables are expected to be set: +## RELEASE_TAG, BRANCH_TAG, BUILD_TARGET, PRODUCT, RELEASE_HOME, BUILD_CONFIG +## The target command is expected to have already been run to set up the +## environment for the specified target +## +## re-run can be used for 2 situations: +## 1. re-run a failed build to correct incorrect weeklybuild arguments +## or other non-source code related problems (out of disk space) +## 2. re-run a build for a different BUILD_TARGET_OS_VERSION while using the same +## source code image/tag +## If the source code needs to be corrected, a full weeklybuild should be run +## after the correction such that the code is properly tagged. +## +## For developer builds (such as via dobuildall), the following combinations +## of the -r, -i, -C and -R options are useful +## -r - existing typical mode for developer builds +## - clobbers any existing built files +## - creates a src.rpm +## - builds in rpmbuild tree +## - creates a resulting binary rpm +## - IntelOpa-Tests built in a tests_build area +## -r -C - for opa FF & mpi_apps, behaves same as -r above except skips clobber +## - IntelOpa-Tests tree is not cleaned, so will do incremental build +## -r -i [-C] - incremental build mode for developer builds +## - clobbers any existing built files (unless -C specified) +## - builds code in place in source tree +## - src rpm contains pre-built code +## - rpmbuild ends up using pre-built code, creates binary rpm +## - IntelOpa-Tests built in a tests_build area using +## pre-built code from FF and previous tests build +## After this build, the developer may do incremental sub-tree builds +## using . setenv and then running make in the subtree +## For subtree builds in tests_build, also export PROJ_FILE_DIR=. +## -r -i [-C] -R - incremental build mode for developer builds with no rpms +## - same as -r -i [-C] except no rpms are created +## none of these options - typical production build +## - expects a fresh un-built checkout of code tree +## - creates a src.rpm +## - builds in rpmbuild tree +## - creates a resulting binary rpm +## - IntelOpa-Tests built in a tests_build area +## if developer does not need an updated build of IntelOPA-Tests, the -P option +## may be used to further speed up the build +## +## Recommended developer sequence of builds when debugging new code +## -r -i -C -R - performs the fastest full build possible, generates no rpms +## It is recommended to omit the -C option on 1st build so the tree +## is clobbered to be sure you start fresh. +## iterate on this and code changes until the basic build works +## and syntax errors and warnings are all resolved +## For unit tests only needing a few binaries, they can also be +## directly tested. +## If IntelOPA-Tests is not needed also use -P option +## after initial attempt, if compile errors are limited to a subtree: +## create a new bash shell, use . setenv and then +## iterate on make in the subtree and code changes until compiles +## -r -i -C - performs a build to generate rpms +## install the rpms and continue testing +## if focused on a few executables: +## create a new bash shell, use . setenv and then +## iterate on make in the subtree and code changes and test of +## the individual binary until works properly +## -r - perform a full build and generate rpms +## install the rpms, confirm clean build, proper install and function +## +## Since weeklybuild and target commands always set BUILD_CONFIG, this +## script ignores BUILD_CONFIG. As such the BuildOptions file +## or the -B argument completely control BUILD_CONFIG for this product. + +. $ICSBIN/funcs.sh + +# A given release will be targeted for a specific version of ofed +# however we allow build.config to override if needed +#export OFED_STACK_PREFIX=${OFED_STACK_PREFIX:-/usr/ofed-1.5.2} +export OFED_STACK_PREFIX=${OFED_STACK_PREFIX:-/usr} + +# typically exported by build.config +export BUILD_WITH_STACK=${BUILD_WITH_STACK:-OPENIB} + +Usage() +{ + # include "ERROR" in message so weeklybuild catches it in error log + echo "ERROR: runmake failed" >&2 + echo "Usage: runmake [-B 'build_config'] [-n]" >&2 + echo " OR" >&2 + echo " runmake -r [-B 'build_config'] [-iCRP] [-n]" >&2 + exit 2 +} + +build_config= +rerun=n +Cflag=n +nflag=n +inplace=n +rpm=y +buildtests=y +while getopts f:B:V:riRPCOnT: param +do + case $param in + V) echo "Depricated -V os_versions ignored." >&2 ;; + f) + echo "Depricated -f options_file ignored." >&2 ;; + r) + rerun=y;; + B) + build_config="$OPTARG";; + i) + inplace=y;; + R) + rpm=n;; + C) + Cflag=y;; + n) + nflag=y;; + P) + buildtests=n;; + O) + echo "Depricated -O ignored." >&2 ;; + T) + echo "Depricated -T PROJ_FILE_DIR ignored." >&2 ;; + ?) + Usage + esac +done +shift $(($OPTIND -1)) + +if [ $# != 0 ] +then + Usage +fi + +if [ -z "$RELEASE_TAG" ] +then + export RELEASE_TAG=`patch_engineer_version|cut -d"." -f1` + echo "Defaulting RELEASE_TAG to $RELEASE_TAG" + # engineers will always forget this flag, since clobber is fast + # default to a rerun which will clobber first unless -C specified + rerun=y +fi + +# these are special cases +if [ "$SUBPRODUCT" = "TESTS" ] +then + # build the IntelOPA-IntTests (aka HostTests) for use by validation and + # DST testing + # This builds so quick there is no need for incremental builds nor packaging + # options like -r -i -C and -R + # simply always clobber any old packaging and start fresh + settl + PRODUCT_DIR=$PWD + cd $TL_DIR + dir=release.$PRODUCT.$SUBPRODUCT + rm -rf $dir + mkdir $dir + cp -R HostTestCases $dir/HostTests + cp -R Makerules MakeTemplates MakeTools TestTools TestOnly CodeTemplates $dir/HostTests + ( cd $dir; tar cvfz IntelOPA-IntTests.$RELEASE_TAG.tgz --exclude CVS --exclude '*.bak' HostTests; [ $? = 0 ] || echo "ERROR: tar command failed" ) + echo "$TL_DIR/$dir/IntelOPA-IntTests.$RELEASE_TAG.tgz" > $PRODUCT_DIR/packaged_files + # this should not be distributed, so create an empty dist_files + > $PRODUCT_DIR/dist_files + exit $? +elif [ "$SUBPRODUCT" = "GPL" -o "$SUBPRODUCT" = "SRC" \ + -o "$SUBPRODUCT" = "MCLX" -o "$SUBPRODUCT" = "OPEN12200" ] +then + echo "ERROR: $SUBPRODUCT build no longer supported for OPENIB_HOST" >&2 + exit 1 +fi +# other values of SUBPRODUCT are ignored in the compilation, however can set +# the destination directory in the Integration and System_Test areas, so we +# allow them, but do nothing special with them + +resetct +resetbsp +if [ "$BUILD_TARGET_TOOLCHAIN" == "INTEL" ] +then + target $BUILD_TARGET_TOOLCHAIN +else + target $BUILD_TARGET +fi + +# the kernel rev is not important. We simply use the kernel rev +# of the running kernel. While BUILD_TARGET_OS_VERSION is needed by Makerules +# it will have no impact on what is actually built +export BUILD_TARGET_OS_VERSION=${BUILD_TARGET_OS_VERSION:-`uname -r`} +setver $BUILD_TARGET_OS_VENDOR $BUILD_TARGET_OS_VERSION + +export PROJ_FILE_DIR=OpenIb_Host +echo "Using PROJ_FILE_DIR=$PROJ_FILE_DIR" + +if [ -z "$build_config" ] +then + # default to release build + export BUILD_CONFIG=release +elif [ "$build_config" != debug -a "$build_config" != release ] +then + Usage +else + export BUILD_CONFIG="$build_config" +fi + +if [ ! -d $OFED_STACK_PREFIX ] +then + echo "$0: ERROR: OFED stack not found: $OFED_STACK_PREFIX" >&2 + exit 1 +fi + +echo "---------------------------------------" +# Import OPA Build feature settings. +export OPA_FEATURE_SET=${OPA_FEATURE_SET:-$(cat $TL_DIR/$PROJ_FILE_DIR/DEFAULT_OPA_FEATURE_SET)} +FEATURE_SETTINGS_FILE=opa_feature_settings.${PRODUCT}.$BUILD_CONFIG +$TL_DIR/OpaBuildFeatureToggles/opa_build_import_feature_settings.sh +if [ -e ./$FEATURE_SETTINGS_FILE ]; then + . ./$FEATURE_SETTINGS_FILE +else + echo "$0: ERROR: OPA BUILD - $FEATURE_SETTINGS_FILE not found" >&2 + exit 1 +fi +showenv +echo "---------------------------------------" + +# To run thew klocwork scans using klocwork_analyze script, it requires OPA_FEATURE_SET and BUILD_TARGET_OS_ID +# Copying the required variables to $TL_DIR/$PRODUCT_DIRNAME/klocwork.env +if [ "$KW_ENABLE" = "yes" ]; then + echo "export OPA_FEATURE_SET=${OPA_FEATURE_SET}" >> $TL_DIR/$PRODUCT_DIRNAME/klocwork.env + echo "export BUILD_TARGET_OS_ID=${BUILD_TARGET_OS_ID}" >> $TL_DIR/$PRODUCT_DIRNAME/klocwork.env +fi + +echo "build for: $BUILD_TARGET" +echo "Stack to build for: $BUILD_WITH_STACK ($OFED_STACK_PREFIX)" + +if [ "$nflag" = "y" ] +then + exit 0 +fi + +if [ "$BUILD_TARGET_OS" = "VXWORKS" ] +then + echo "ERROR: Wrong runmake file" + exit 1 +fi + +MODULEVERSION=`$TL_DIR/MakeTools/format_releasetag.sh $RELEASE_TAG` +RPMVERSION=`$TL_DIR/MakeTools/format_releasetag.sh -f rpm $RELEASE_TAG` +RPM_VER=`echo $RPMVERSION|cut -d"-" -f1` +RPM_REL=`echo $RPMVERSION-999|cut -d"-" -f2` +export MKRPM_VER=$RPM_VER +export MKRPM_REL=$RPM_REL`rpm --eval %{?dist}` + +# even if building rpms, clobber to cleanup any previous in-place builds +# so they don't end up inside the src.rpm when not wanted +# clean up from prior build when rebuilding +if [ "$rerun" = y -a "$Cflag" != y ] +then + # force full rebuild + # Clobber is really only necessary if we have ever built inplace + # but to be safe we always clobber just in case an aborted inplace + # build has previously occurred. + #if [ -e $TL_DIR/builtinplace.$PRODUCT.$BUILD_CONFIG \ + # -o -e $TL_DIR/builtinclude.$PRODUCT.$BUILD_CONFIG \ + # -o -e $TL_DIR/builtlibs.$PRODUCT.$BUILD_CONFIG \ + # -o -e $TL_DIR/builtbin.$PRODUCT.$BUILD_CONFIG ] + #then + export REMOVE_DEPENDS=yes + make clobber clobber_stage clobber_release + (cd $TL_DIR/CommonInstall; make clobber_pl_files) + rm -f $TL_DIR/builtinplace.$PRODUCT.$BUILD_CONFIG + #fi +fi + +rm -rf $TL_DIR/$PROJ_FILE_DIR/packaged_files $TL_DIR/$PROJ_FILE_DIR/dist_files $TL_DIR/Fd/buildFeatureDefs + +# make sure buildFeatureDefs is in place for the build +make $TL_DIR/Fd/buildFeatureDefs || exit 1 + +# make sure detailed_topology.xlsx is in place for the build +(cd $TL_DIR/IbaTools/opaxlattopology; make detailed_topology.xlsx) || exit 1 + +# make sure files from BaseFiles are in place +while read comp fn +do + if ! echo $comp | grep FF > /dev/null + then + continue + fi + dir=$(dirname $fn) + bn=$(basename $fn) + (cd $TL_DIR/$dir;make $bn) || exit 1 +done < $TL_DIR/Fd/BaseFiles + +# make sure CommonInstall files are in place +#(cd $TL_DIR/CommonInstall; make clobber_pl_files ff_files) + +args= +if [ "$inplace" = y ] +then + # Do not use unifdef for inplace build + export USE_UNIFDEF="no" + echo > $TL_DIR/builtinplace.$PRODUCT.$BUILD_CONFIG + ./rpm_runmake -r -C -B $BUILD_CONFIG + args="-r -C" # we pre-built, so skip clobber in rpmbuild +fi + +if [ "$rpm" = y ] +then + USE_UNIFDEF=${USE_UNIFDEF:-"yes"} + set -x + + # Pass env variables to rpmbuild. In integration build, + # most of the rpmbuild environment variables remains the same except + # a few (like TL_DIR). However, when the SRPM is built on another + # different machine, the environment variables may be totally + # different. In that case, we may want to pass (hardcode) some + # environment variables. + echo "# Adjust the environment variables if necessary" > build.env + echo "export PRODUCT=${PRODUCT}" >> build.env + echo "export RELEASE_TAG=${RELEASE_TAG}" >> build.env + echo "export BUILD_CONFIG=\${BUILD_CONFIG:-\"${BUILD_CONFIG}\"}" >> build.env + echo "export BUILD_WITH_STACK=${BUILD_WITH_STACK}" >> build.env + echo "export LDENVFS=${LDENVFS}" >> build.env + + FILES_TO_TAR= + # if in-place build left builtbin, builtinclude and builtlibs, pick them up + # to accelerate incremental builds + for i in builtbin builtinclude builtlibs builtinplace + do + if [ -e $TL_DIR/$i.$PRODUCT.$BUILD_CONFIG ] + then + FILES_TO_TAR="$FILES_TO_TAR $i.$PRODUCT.$BUILD_CONFIG" + fi + done + + FILES_TO_TAR="$FILES_TO_TAR -T tar_manifest" + MPIAPPS_FILES_TO_TAR="-T mpiapps_tar_manifest" + + if [ "$BUILD_PLATFORM_OS_VENDOR" != "ubuntu" ] + then + RPMDIR="$TL_DIR/rpmbuild" + mkdir -p $RPMDIR/{BUILD,SPECS,BUILDROOT,SOURCES,RPMS,SRPMS} + + # Update the spec file + cp opa.spec.in opa.spec + sed -i "s/__RPM_VERSION/${RPM_VER}/g" opa.spec + sed -i "s/__RPM_RELEASE/${RPM_REL}%{?dist}/g" opa.spec + # TBD - this is odd, do we need to edit .spec or should we just change + # the input to always look like this? + sed -i "s/.\/ff_install/OpenIb_Host\/ff_install/g" opa.spec + ./update_opa_spec.sh + mv opa.spec $RPMDIR/SPECS/ + + cp mpi-apps.spec.in mpi-apps.spec + sed -i "s/__RPM_VERSION/${RPM_VER}/g" mpi-apps.spec + sed -i "s/__RPM_RELEASE/${RPM_REL}%{?dist}/g" mpi-apps.spec + ./update_mpi_spec.sh + mv mpi-apps.spec $RPMDIR/SPECS/ + + # Create source tar ball. Update licenses if needed. + $TL_DIR/MakeTools/make_src_tar.sh \ + "${RELEASE_TYPE}" \ + "${TL_DIR}" \ + "$USE_UNIFDEF" \ + "$RPMDIR/SOURCES/opa.tgz" \ + "$FILES_TO_TAR" \ + " -X tar_excludes " \ + " --transform=s,$PROJ_FILE_DIR/debian,debian," \ + || exit 1 + + # Do same for MpiApps + $TL_DIR/MakeTools/make_src_tar.sh \ + "${RELEASE_TYPE}" \ + "${TL_DIR}" \ + "$USE_UNIFDEF" \ + "$RPMDIR/SOURCES/opa-mpi-apps.tgz" \ + "$MPIAPPS_FILES_TO_TAR" \ + || exit 1 + ( + export BUILD_ARGS="$args" + cd $RPMDIR + rpmbuild -ba --define "_topdir $RPMDIR" SPECS/opa.spec + rpmbuild -ba --define "_topdir $RPMDIR" SPECS/mpi-apps.spec + ) || exit 1 + else + RPMDIR="$TL_DIR/debbuild" + RPMVER=${RPM_VER}-${RPM_REL} + mkdir -p $RPMDIR/{build,dists} + + OPA_SOURCE_TARBALL="$RPMDIR/dists/opa.tgz" + # Create source tar ball. Update licenses if needed. + $TL_DIR/MakeTools/make_src_tar.sh \ + "${RELEASE_TYPE}" \ + "${TL_DIR}" \ + "$USE_UNIFDEF" \ + "$OPA_SOURCE_TARBALL" \ + "$FILES_TO_TAR" \ + " -X tar_excludes " \ + " --transform=s,$PROJ_FILE_DIR/debian,debian," \ + || exit 1 + ( + OPA_DIR="$RPMDIR/build/opa-$RPM_VER" + mkdir -p "$OPA_DIR" + cd "$OPA_DIR" + tar xzf "$OPA_SOURCE_TARBALL" + # Prepate manifest from template + mv debian/changelog.in debian/changelog + # Annotate changelog file to get proper version + debchange --newversion=$RPMVER "Bump up version to $RPMVER" + # Pass build variables into package build environment + export BUILD_ARGS="$args" + dpkg-buildpackage -uc -us + ) || exit 1 + + OPA_MPI_APPS_SOURCE_TARBALL="$RPMDIR/dists/opa-mpi-apps.tgz" + # Do same for MpiApps + $TL_DIR/MakeTools/make_src_tar.sh \ + "${RELEASE_TYPE}" \ + "${TL_DIR}" \ + "$USE_UNIFDEF" \ + "$OPA_MPI_APPS_SOURCE_TARBALL" \ + "$MPIAPPS_FILES_TO_TAR" \ + || exit 1 + ( + OPA_MPI_APPS_DIR="$RPMDIR/build/opa-mpi-apps-$RPM_VER" + mkdir -p "$OPA_MPI_APPS_DIR" + cd "$OPA_MPI_APPS_DIR" + tar xzf "$OPA_MPI_APPS_SOURCE_TARBALL" + # Prepate manifest from template + mv debian/changelog.in debian/changelog + # Annotate changelog file to get proper version + debchange --newversion=$RPMVER "Bump up version to $RPMVER" + # Pass build variables into package build environment + export BUILD_ARGS="$args" + dpkg-buildpackage -uc -us + ) || exit 1 + fi + make final_package + echo "$TL_DIR/$PROJ_FILE_DIR/$FEATURE_SETTINGS_FILE" >> packaged_files +fi + +if [ "$buildtests" = y ] +then + echo "Building IntelOPA-Tests $build_config for allkernels for $BUILD_TARGET_OS $BUILD_TARGET ..." + echo "===============================================================================" + ./build_tests.sh $args + echo "Done IntelOPA-Tests $BUILD_TARGET_OS $BUILD_TARGET allkernels $(date)" + echo "===============================================================================" +fi +exit 0 diff --git a/OpenIb_Host/setenv b/OpenIb_Host/setenv new file mode 100755 index 0000000..337468b --- /dev/null +++ b/OpenIb_Host/setenv @@ -0,0 +1,45 @@ +#!/bin/bash +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# Simple script to setup environment for a build for current OS version/type +. $ICSBIN/funcs.sh +settl + +export BUILD_WITH_STACK=${BUILD_WITH_STACK:-OPENIB} +export PRODUCT=${PRODUCT:-OPENIB_FF} +export PROJ_FILE_DIR=${PROJ_FILE_DIR:-OpenIb_Host} + +# Configure OPA_FEATURE_SET +FEATURE_SETTINGS_FILE=$TL_DIR/$PROJ_FILE_DIR/opa_feature_settings.$PRODUCT.$BUILD_CONFIG +if [ -e $FEATURE_SETTINGS_FILE ]; then + . $FEATURE_SETTINGS_FILE +fi + +. $TL_DIR/MakeTools/setenv diff --git a/OpenIb_Host/tar_excludes b/OpenIb_Host/tar_excludes new file mode 100644 index 0000000..3500ba9 --- /dev/null +++ b/OpenIb_Host/tar_excludes @@ -0,0 +1,37 @@ +*VXWORKS* +Xml/XmlParser +MakeTools/zisofs-tools +MakeTools/makeself-header.sh +MakeTools/makeself.sh +MakeTools/regdll.bat +MakeTools/regexe.bat +MakeTools/format_releasetag.py +MakeTools/ltsign +IbAccess/Common/Ibt/ibt.vssscc +MpiApps/apps/osu2 +MpiApps/apps/osu-micro-benchmarks-3.8-July12 +MpiApps/apps/hpl-2.2 +MpiApps/apps/*.tgz +MpiApps/apps/PMB2.2.1 +MpiApps/apps/bandwidth +MpiApps/apps/latency +MpiApps/apps/mpi_multibw +MpiApps/apps/imb +MpiApps/apps/NPB* +OpenIb_Host/build.err +OpenIb_Host/build.res +OpenIb_Host/build.warn +OpenIb_Host/build.kw +OpenIb_Host/dist_files +OpenIb_Host/FFresults +OpenIb_Host/klocwork.env +OpenIb_Host/kwinject.out +OpenIb_Host/kwtables/* +OpenIb_Host/packaged_files +OpenIb_Host/tests_build +OpenIb_Host/TESTSresults +OpenIb_Host/opa_feature_settings* +opasadb/lib/libopasadb.map.base +opasadb/path_tools/load/opasadb.xml.base +opasadb/lib/path/op_path_rec.conf.base +*/opasnapconfig* diff --git a/OpenIb_Host/tar_excludes.base b/OpenIb_Host/tar_excludes.base new file mode 100644 index 0000000..3500ba9 --- /dev/null +++ b/OpenIb_Host/tar_excludes.base @@ -0,0 +1,37 @@ +*VXWORKS* +Xml/XmlParser +MakeTools/zisofs-tools +MakeTools/makeself-header.sh +MakeTools/makeself.sh +MakeTools/regdll.bat +MakeTools/regexe.bat +MakeTools/format_releasetag.py +MakeTools/ltsign +IbAccess/Common/Ibt/ibt.vssscc +MpiApps/apps/osu2 +MpiApps/apps/osu-micro-benchmarks-3.8-July12 +MpiApps/apps/hpl-2.2 +MpiApps/apps/*.tgz +MpiApps/apps/PMB2.2.1 +MpiApps/apps/bandwidth +MpiApps/apps/latency +MpiApps/apps/mpi_multibw +MpiApps/apps/imb +MpiApps/apps/NPB* +OpenIb_Host/build.err +OpenIb_Host/build.res +OpenIb_Host/build.warn +OpenIb_Host/build.kw +OpenIb_Host/dist_files +OpenIb_Host/FFresults +OpenIb_Host/klocwork.env +OpenIb_Host/kwinject.out +OpenIb_Host/kwtables/* +OpenIb_Host/packaged_files +OpenIb_Host/tests_build +OpenIb_Host/TESTSresults +OpenIb_Host/opa_feature_settings* +opasadb/lib/libopasadb.map.base +opasadb/path_tools/load/opasadb.xml.base +opasadb/lib/path/op_path_rec.conf.base +*/opasnapconfig* diff --git a/OpenIb_Host/tar_manifest b/OpenIb_Host/tar_manifest new file mode 100644 index 0000000..4f943e6 --- /dev/null +++ b/OpenIb_Host/tar_manifest @@ -0,0 +1,34 @@ +CommonInstall +IbAccess +IbaTools +IbPrint +Iih +Lsf +Makerules +MakeTools +MakeTemplates +MpiApps/apps +MpiApps/Makefile +Moab +OpenIb_Host +opasadb +opamgt +TestTools +Topology +Xml +Dsap +Esm/ib/include +Esm/ib/Makerules.module +Esm/ib/src/config +Esm/ib/src/cs +Esm/ib/src/ibaccess +Esm/ib/src/linux/log/common +Esm/ib/src/linux/log/include +Esm/ib/src/linux/log/usr +Esm/ib/src/linux/startup/fm_config +Esm/ib/src/pm/include +Esm/ib/src/smi/include +Fd/buildFeatureDefs +Fd/buildFeatureDefs.base +OpenIb_Host/debian +Fd/buildFeatureDefs.base diff --git a/OpenIb_Host/update_mpi_spec.sh b/OpenIb_Host/update_mpi_spec.sh new file mode 100755 index 0000000..77edcb9 --- /dev/null +++ b/OpenIb_Host/update_mpi_spec.sh @@ -0,0 +1,59 @@ +#!/bin/bash +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +#[ICS VERSION STRING: unknown] + +id=$(./get_id_and_versionid.sh | cut -f1 -d' ') +versionid=$(./get_id_and_versionid.sh | cut -f2 -d' ') + +if [ "$id" = "rhel" -o "$id" = "centos" ] +then + GE_8_0=$(echo "$versionid >= 8.0" | bc) + sed -i "s/__RPM_REQ/Requires: atlas/" mpi-apps.spec + if [ $GE_8_0 = 1 ] + then + sed -i "s/__RPM_DBG/%global debug_package %{nil}/" mpi-apps.spec + else + sed -i "/__RPM_DBG/,+1d" mpi-apps.spec + fi +elif [ "$id" = "fedora" ] +then + sed -i "s/__RPM_REQ/Requires: atlas/" mpi-apps.spec + sed -i "s/__RPM_DBG/%global debug_package %{nil}/" mpi-apps.spec +elif [ "$id" = "sles" ] +then + sed -i "/__RPM_REQ/,+1d" mpi-apps.spec + sed -i "/__RPM_DBG/,+1d" mpi-apps.spec +else + echo ERROR: Unsupported distribution: $id $versionid + exit 1 +fi + +exit 0 diff --git a/OpenIb_Host/update_opa_spec.sh.base b/OpenIb_Host/update_opa_spec.sh.base new file mode 100755 index 0000000..ebb07a0 --- /dev/null +++ b/OpenIb_Host/update_opa_spec.sh.base @@ -0,0 +1,225 @@ +#!/bin/bash +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +#[ICS VERSION STRING: unknown] + +id=$(./get_id_and_versionid.sh | cut -f1 -d' ') +versionid=$(./get_id_and_versionid.sh | cut -f2 -d' ') + +sed -i "s/__RPM_FS/OPA_FEATURE_SET=$OPA_FEATURE_SET/g" opa.spec + + +source ./ff_filegroups.sh + +sed -i "/__RPM_OPASNAPCONFIG1/d" opa.spec +sed -i "/__RPM_OPASNAPCONFIG2/d" opa.spec + +if [ "$id" = "rhel" -o "$id" = "centos" ] +then + GE_7_4=$(echo "$versionid >= 7.4" | bc) + GE_7_5=$(echo "$versionid >= 7.5" | bc) + + # __RPM_REQ_BASIC - + sed -i "s/__RPM_REQ_BASIC/expect%{?_isa}, tcl%{?_isa}, openssl%{?_isa}, expat%{?_isa}, libibumad%{?_isa}, libibverbs%{?_isa}/g" opa.spec + + # __RPM_REQ_OPAMGT_DEV - different for RHEL7.4 and greater + if [ $GE_7_4 = 1 ] + then + sed -i "s/__RPM_REQ_OPAMGT_DEV/rdma-core-devel, openssl-devel, opa-libopamgt,/g" opa.spec + else + sed -i "s/__RPM_REQ_OPAMGT_DEV/libibumad-devel, libibverbs-devel, openssl-devel, opa-libopamgt/g" opa.spec + fi + + # __RPM_BLDREQ - different for RHEL 7.5, RHEL7.4, or earlier + if [ $GE_7_4 = 1 ] + then + sed -i "s/__RPM_BLDREQ/expat-devel, gcc-c++, openssl-devel, ncurses-devel, tcl-devel, zlib-devel, rdma-core-devel, ibacm-devel/g" opa.spec + else + sed -i "s/__RPM_BLDREQ/expat-devel, gcc-c++, openssl-devel, ncurses-devel, tcl-devel, zlib-devel, libibumad-devel, libibverbs-devel, ibacm-devel/g" opa.spec + fi + + # __RPM_REQ_ADDR_RES,__RPM_REQ_OPAMGT and __RPM_DEBUG same for all RHEL versions + sed -i "s/__RPM_REQ_ADDR_RES/opa-basic-tools ibacm/g" opa.spec + sed -i "s/__RPM_REQ_OPAMGT/libibumad%{?_isa}, libibverbs%{?_isa}, openssl%{?_isa}/g" opa.spec + sed -i "/__RPM_DEBUG_PKG/,+1d" opa.spec + + #Setup Epoch tags for RHEL rpms + sed -i "s/__RPM_EPOCH_BASIC/Epoch: 1/g" opa.spec + sed -i "s/__RPM_EPOCH_FF/Epoch: 1/g" opa.spec + sed -i "s/__RPM_EPOCH_ADDR_RES/Epoch: 1/g" opa.spec + sed -i "s/__RPM_EPOCH_LIBOPAMGT/Epoch: 1/g" opa.spec + + +elif [ "$id" = "sles" ] +then + GE_11_1=$(echo "$versionid >= 11.1" | bc) + GE_12_2=$(echo "$versionid >= 12.2" | bc) + GE_12_3=$(echo "$versionid >= 12.3" | bc) + + # __RPM_DEBUG_PKG - needed for SLES 11.1 and greater + if [ $GE_11_1 = 1 ] + then + sed -i "s/__RPM_DEBUG_PKG/%debug_package/g" opa.spec + else + sed -i "/__RPM_DEBUG_PKG/,+1d" opa.spec + fi + + # __RPM_REQ_BASIC, __RPM_BLDREQ, and __RPM_REQ_OPAMGT_DEV different for SLES 12.3 and greater + if [ $GE_12_3 = 1 ] + then + sed -i "s/__RPM_REQ_BASIC/libexpat1, libibmad5, libibumad3, libibverbs1, openssl, expect, tcl/g" opa.spec + sed -i "s/__RPM_BLDREQ/libexpat-devel, gcc-c++, libopenssl-devel, ncurses-devel, tcl-devel, zlib-devel, rdma-core-devel, ibacm-devel/g" opa.spec + sed -i "s/__RPM_REQ_OPAMGT_DEV/rdma-core-devel, libopenssl-devel, opa-libopamgt/g" opa.spec + else + sed -i "s/__RPM_REQ_BASIC/libexpat1, libibmad5, libibumad3, libibverbs1, openssl, expect, tcl/g" opa.spec + sed -i "s/__RPM_BLDREQ/libexpat-devel, gcc-c++, libopenssl-devel, ncurses-devel, tcl-devel, zlib-devel, libibumad-devel, libibverbs-devel, ibacm-devel/g" opa.spec + sed -i "s/__RPM_REQ_OPAMGT_DEV/libibumad-devel, libibverbs-devel, libopenssl-devel, opa-libopamgt/g" opa.spec + fi + + # __RPM_REQ_ADDR_RES same for all SLES versions + sed -i "s/__RPM_REQ_ADDR_RES/opa-basic-tools, ibacm/g" opa.spec + # __RPM_REQ_OPAMGT same for all SLES versions + sed -i "s/__RPM_REQ_OPAMGT/libibumad3, libibverbs1, openssl/g" opa.spec + + #Cleanup EPOCH macros from sles spec. + #Note that SUSE discourages and does not use epochs + sed -i "/__RPM_EPOCH_*/d" opa.spec + +elif [ "$id" = "fedora" ] +then + # __RPM_REQ_BASIC1 - + sed -i "s/__RPM_REQ_BASIC1/expect%{?_isa}, tcl%{?_isa}, openssl%{?_isa}, expat%{?_isa}, libibumad%{?_isa}, libibverbs%{?_isa}/g" opa.spec + sed -i "/__RPM_REQ_BASIC2/d" opa.spec + + # __RPM_REQ_OPAMGT_DEV - different for RHEL7.4 and greater + sed -i "s/__RPM_REQ_OPAMGT_DEV/rdma-core-devel, openssl-devel, opa-libopamgt,/g" opa.spec + + # __RPM_BLDREQ1 - different for RHEL 7.5, RHEL7.4, or earlier + sed -i "s/__RPM_BLDREQ1/expat-devel, gcc-c++, openssl-devel, ncurses-devel, tcl-devel, rdma-core-devel, ibacm-devel/g" opa.spec + sed -i "/__RPM_BLDREQ2/d" opa.spec + + # __RPM_REQ_ADDR_RES,__RPM_REQ_OPAMGT and __RPM_DEBUG same for all RHEL versions + sed -i "s/__RPM_REQ_OPAMGT/libibumad%{?_isa}, libibverbs%{?_isa}, openssl%{?_isa}/g" opa.spec + sed -i "s/__RPM_REQ_ADDR_RES/opa-basic-tools ibacm/g" opa.spec + sed -i "/__RPM_DEBUG_PKG/,+1d" opa.spec + + #Setup Epoch tags for RHEL rpms + sed -i "s/__RPM_EPOCH_BASIC/Epoch: 1/g" opa.spec + sed -i "s/__RPM_EPOCH_FF/Epoch: 1/g" opa.spec + sed -i "s/__RPM_EPOCH_ADDR_RES/Epoch: 1/g" opa.spec + sed -i "s/__RPM_EPOCH_LIBOPAMGT/Epoch: 1/g" opa.spec + +else + echo ERROR: Unsupported distribution: $id $versionid + exit 1 +fi + +> .tmpspec +while read line +do + if [ "$line" = "__RPM_BASIC_FILES" ] + then + for i in $basic_tools_sbin $basic_tools_sbin_sym + do + echo "%{_sbindir}/$i" >> .tmpspec + done + for i in $basic_tools_opt + do + echo "/usr/lib/opa/tools/$i" >> .tmpspec + done + for i in $basic_mans + do + echo "%{_mandir}/man1/${i}.gz" >> .tmpspec + done + for i in $basic_samples + do + echo "/usr/share/opa/samples/$i" >> .tmpspec + done + else + echo "$line" >> .tmpspec + fi +done < opa.spec +mv .tmpspec opa.spec + +> .tmpspec +while read line +do + if [ "$line" = "__RPM_FF_FILES" ] + then + for i in $ff_tools_sbin opafmconfigcheck opafmconfigdiff + do + echo "%{_sbindir}/$i" >> .tmpspec + done + for i in $ff_tools_opt $ff_tools_misc $ff_tools_exp $ff_libs_misc + do + echo "/usr/lib/opa/tools/$i" >> .tmpspec + done + for i in $help_doc + do + echo "/usr/share/opa/help/$i" >> .tmpspec + done + for i in $ff_tools_fm + do + echo "/usr/lib/opa/fm_tools/$i" >> .tmpspec + done + for i in $ff_iba_samples + do + echo "/usr/share/opa/samples/$i" >> .tmpspec + done + for i in $ff_mans + do + echo "%{_mandir}/man8/${i}.gz" >> .tmpspec + done + for i in $mpi_apps_files + do + echo "/usr/src/opa/mpi_apps/$i" >> .tmpspec + done + else + echo "$line" >> .tmpspec + fi +done < opa.spec +mv .tmpspec opa.spec + +> .tmpspec +while read line +do + if [ "$line" = "__RPM_SNAP_FILES" ] + then + for i in $opasnapconfig_bin + do + echo "/usr/lib/opa/tools/$i" >> .tmpspec + done + else + echo "$line" >> .tmpspec + fi +done < opa.spec +mv .tmpspec opa.spec + +exit 0 diff --git a/README b/README new file mode 100644 index 0000000..d75101b --- /dev/null +++ b/README @@ -0,0 +1,21 @@ +OPA tools and Fast Fabric +------------------------- + +* To build the RPM and SRPM: + + 1. mkdir -p $HOME/rpmbuild/{SOURCES,RPMS,SRPMS} + 2. ./update_opa_spec.sh opa-ff.spec.in opa-ff.spec + 3. tar czf $HOME/rpmbuild/SOURCES/opa.tgz --exclude-vcs . + 4. rpmbuild -ba ./opa-ff.spec + + This will build the opa-basic-tools, opa-fastfabric, and opa-address-resolution + RPMs in $HOME/rpmbuild/RPMS/(architecture)/ + + This will also create a opa-debuginfo RPM, which by default contains basic symbol + information - see below on how to build with full debugging information. + +* How to include debugging symbols: + + export BUILD_CONFIG=debug + + prior to the aforementioned build procedure. diff --git a/ShmemApps/Makefile b/ShmemApps/Makefile new file mode 100644 index 0000000..fd1fe2c --- /dev/null +++ b/ShmemApps/Makefile @@ -0,0 +1,78 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** +# Makefile for MpiApps + +# Include Make Control Settings +include $(TL_DIR)/$(PROJ_FILE_DIR)/Makesettings.project + +DS_SUBPROJECTS = +DSP_SOURCES = Makefile + +DIRS = + +include $(TL_DIR)/$(PROJ_FILE_DIR)/Makerules.project + +INSTALL_TEST_APPS_SRC = $(TL_DIR)/ShmemApps/apps/shmem_apps.tgz +SHMEM_INSTALL_TESTS_DIR = $(PROJ_STAGE_DIR)/Tests/shmem + +CLOBBER_EXTRA = \ + .ICSBOOTROMVERSIONSTRING \ + # add additional files here + +.PHONEY: appl +appl $(TL_DIR)/ShmemApps/apps/shmem_apps.tgz: + if [ -d apps ]; then \ + cd apps; $(MAKE) -f Makefile.package $(MFLAGS) ALL; \ + fi + + +cleandepend clean:: clobber + +clobber:: + if [ -d apps ]; then \ + cd apps; $(MAKE) -f Makefile.package $(MFLAGS) CLOBBER; \ + fi +depend:: +force:: +ALL:: INCLUDES LIBS CMDS +INCLUDES:: +LIBS:: +# do the real work during CMDS +CMDS:: $(INSTALL_TEST_APPS_SRC) + +STAGE:: + $(VS)if [ -d apps ]; then $(STAGE_INSTALL) $(STAGE_INSTALL_DIR_OPT) $(SHMEM_INSTALL_TESTS_DIR) $(INSTALL_TEST_APPS_SRC); fi + $(VS)if [ -d apps ]; then $(STAGE_INSTALL) $(STAGE_INSTALL_DIR_OPT) $(PROJ_STAGE_SRC_DIR)/shmem/shmem_apps $(INSTALL_TEST_APPS_SRC); fi + +INSTALL:: +RUNTEST:: +build_dsfiles:: +clobber_dsfiles:: +lint:: +cflow:: diff --git a/ShmemApps/README b/ShmemApps/README new file mode 100644 index 0000000..d5222c6 --- /dev/null +++ b/ShmemApps/README @@ -0,0 +1 @@ +SHMEM sample apps diff --git a/ShmemApps/apps/Makefile b/ShmemApps/apps/Makefile new file mode 100644 index 0000000..2070778 --- /dev/null +++ b/ShmemApps/apps/Makefile @@ -0,0 +1,114 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# Makefile for SHMEM application/benchmark source for end user system +# targets: +# full - build all targets. +# quick - build commonly used apps. +# all - synonym for quick +# clobber - remove all built files. +# +# The following targets build the matching applications. If the +# application name differs from the target name, it is listed +# in parens. +# +# HELLO +# + +ifndef SHMEM_PREFIX +SOS_DEVEL_RPM=sandia-openshmem_gcc_hfi-devel +export SHMEM_PREFIX=$(shell rpm -ql $(SOS_DEVEL_RPM) |grep -e "bin/oshcc" |sed -e "s%/bin/oshcc%%") +ifeq ($(SHMEM_PREFIX),) +$(error SHMEM_PREFIX not set) +endif + +endif + + +ifndef SHMEMCC +export SHMEMCC=$(SHMEM_PREFIX)/bin/oshcc +endif +ifndef SHMEM_INCLUDE_DIR +export SHMEM_INCLUDE_DIR=$(SHMEM_PREFIX)/include +endif +ifndef SHMEM_LIB_DIR +export SHMEM_LIB_DIR=$(SHMEM_PREFIX)/lib64 +endif + +all:: INCLUDES LIBS CMDS +.PHONY: all + +HELLO: SHOWSHMEM + @echo "Building SHMEM Hello..." + $(SHMEMCC) -I$(SHMEM_INCLUDE_DIR) -o shmem-hello shmem-hello.c; + @echo +.PHONY: HELLO + +cleandepend clean:: clobber +.PHONY: cleandepend clean + +clobber:: + rm -f shmem-hello shmem-hello.o + rm -f .shmem_prefix +.PHONY: clobber + +SHOWSHMEM: + @echo "Using SHMEM_PREFIX=$(SHMEM_PREFIX)" + echo "$(SHMEM_PREFIX)" > .shmem_prefix +.PHONY: SHOWSHMEM + +depend:: +force:: +INCLUDES:: +# do the real work during LIBS +LIBS:: +.PHONY: depend force INCLUDES LIBS + +quick:: HELLO + @echo "Built subset of sample applications" +.PHONY: quick + +CMDS:: HELLO + @echo "Built sample application" +.PHONY: CMDS + +full:: CMDS + @echo "Built full set of sample applications" +.PHONY: full + +STAGE:: +INSTALL:: + +RUNTEST:: +build_dsfiles:: +clobber_dsfiles:: +lint:: +cflow:: + +.PHONY: STAGE INSTALL RUNTEST build_dsfiles clobber_dsfiles lint cflow diff --git a/ShmemApps/apps/Makefile.package b/ShmemApps/apps/Makefile.package new file mode 100644 index 0000000..5bc0b47 --- /dev/null +++ b/ShmemApps/apps/Makefile.package @@ -0,0 +1,76 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** +# Makefile for Mpi apps + +# Include Make Control Settings +include $(TL_DIR)/$(PROJ_FILE_DIR)/Makesettings.project + +DS_SUBPROJECTS = +DSP_SOURCES = Makefile + +DIRS = + +include $(TL_DIR)/$(PROJ_FILE_DIR)/Makerules.project + +# files used to create mpi_apps.tgz +INSTALL_TEST_APPS_SRC = shmem_apps.tgz + +CLOBBER_EXTRA = \ + .ICSBOOTROMVERSIONSTRING \ + shmem_apps.tgz \ + # add additional files here + +.PHONEY: appl + +appl shmem_apps.tgz: + chmod +x run_* prepare_run select_mpi + tar cvfz shmem_apps.tgz --exclude CVS \ + Makefile mpi_hosts.sample prepare_run README select_mpi \ + run_barrier run_get_bibw run_get_bw run_get_latency run_put_bibw \ + run_put_bw run_put_latency run_reduce run_hello run_alltoall \ + shmem-hello.c + +cleandepend clean:: clobber +clobber:: CLOBBER +CLOBBER:: + rm -rf $(CLOBBER_EXTRA) +depend:: +force:: +ALL:: INCLUDES LIBS CMDS +INCLUDES:: +LIBS:: +# do the real work during CMDS +CMDS:: $(INSTALL_TEST_APPS_SRC) +STAGE:: +INSTALL:: +RUNTEST:: +build_dsfiles:: +clobber_dsfiles:: +lint:: +cflow:: diff --git a/ShmemApps/apps/README b/ShmemApps/apps/README new file mode 100644 index 0000000..dd8da91 --- /dev/null +++ b/ShmemApps/apps/README @@ -0,0 +1,102 @@ +Copyright (c) 2017, Intel Corporation +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: +- Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. +- Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. +- Neither the name of Intel Corporation nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL INTEL, THE COPYRIGHT OWNER OR CONTRIBUTORS +BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. + +EXPORT LAWS: THIS LICENSE ADDS NO RESTRICTIONS TO THE EXPORT LAWS OF YOUR +JURISDICTION. It is licensee's responsibility to comply with any export +regulations applicable in licensee's jurisdiction. Under CURRENT (May 2000) +U.S. export regulations this software is eligible for export from the U.S. +and can be downloaded by or otherwise exported or reexported worldwide EXCEPT +to U.S. embargoed destinations which include Cuba, Iraq, Libya, North Korea, +Iran, Syria, Sudan, Afghanistan and any other country to which the U.S. has +embargoed goods and services. + +This package contains SHMEM applications and packages for testing and +evaluation. + + +MPICH_PREFIX ENVIRONMENT VARIABLE: +---------------------------------- + +The SHMEM samples require an MPI implementation to run. Sandia +OpenSHMEM requires a Hydra* based MPI to run. The select_mpi script +will look for MVAPICH2 directories matching either +mvapich2*hfi (first) or mvapich* (second). + +If desired the MPICH_PREFIX may be exported to control the selection. +Alternatively, a .prefix file can be created in this directory with the +preferred selection. + +SHMEM_PREFIX ENVIRONMENT VARIABLE: +---------------------------------- + +By default, Make will build these programs with Sandia OpenSHMEM installed +by RPM sandia-openshmem_gcc_hfi-devel. SHMEM_PREFIX is also used by the +run_* scripts to define where bin/oshrun is found. + +You can override this by setting SHMEM_PREFIX in your environment. For +example: + +export SHMEM_PREFIX=/my/copy_of_shmem + +The run_* sample runner scripts set SHMEM_PREFIX from a file +.shmem_prefix in the current working directory if that +SHMEM_PREFIX is not already set. + +USING THESE TOOLS WITH MPI-SELECTOR: +------------------------------------ + +SHMEM applications are started using the mpirun from an MPI +implementation such mvapich2. + +In OFED (and Intel IFS), the normal method of selecting an MPI is to +use the mpi-selector commands (type "man mpi-selector-menu" and "man +mpi-selector" for details on those commands). + +To use mpi-selector with these scripts, add this line to your .bashrc +file: + +source /usr/src/opa/mpi_apps/get_selected_mpi.sh + +COMPILING THE TEST PROGRAMS: +---------------------------- + +The top level Makefile will build a simple SHMEM hello_worl application, +using the default (described above) or the value of SHMEM_PREFIX (also +described above). + +RUNNING THE TEST PROGRAMS: +-------------------------- + +A "run_*" script is provided for the applications/benchmark. These +scripts assume the existence of a local "shmem_hosts" file [alternate name can be +exported in MPI_HOSTS if desired] (in mpirun mode) +and that mpd is already running (if you're using mvapich2 in mpd mode). +For example, to run the barrier test, simply type: + +# ./run_barrier 2 + +The scripts log the output of the SHMEM programs to the +/usr/src/opa/shmem_apps/logs directory. diff --git a/ShmemApps/apps/mpi_hosts.sample b/ShmemApps/apps/mpi_hosts.sample new file mode 100644 index 0000000..6f9222d --- /dev/null +++ b/ShmemApps/apps/mpi_hosts.sample @@ -0,0 +1,4 @@ +hostname1 +hostname2 +hostname3 +hostname4 diff --git a/ShmemApps/apps/prepare_run b/ShmemApps/apps/prepare_run new file mode 100755 index 0000000..f298d8d --- /dev/null +++ b/ShmemApps/apps/prepare_run @@ -0,0 +1,153 @@ +#!/bin/sh +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] + +# helper script to handle common setup for the sample application run scripts + +# this script should be . included in a run_ script +# Input: +# MPICH_PREFIX - path to MPICH tools +# MPI_HOSTS - mpi_hosts file to use (default is $PWD/mpi_hosts) +# SHOW_MPI_HOSTS - set to "y" if MPI_HOSTS contents should be output prior +# to starting job. Set to "n" to disable +# defaults to "y" +# SHOW_MPI_HOSTS_LINES - maximum lines in MPI_HOSTS to show. Default is 128 +# Only lines applicable to job will be shown. +# Note the file might include some comment lines +# NUM_PROCESSES - number of processes in job, if "" no count is specified +# if "all" use wc -l $MPI_HOSTS as the process count +# LOGFILE - logfile to append results of run to, if "" +# this script will define +# LOGSUFFIX - suffix to append to logfile name defined by this script +SOS_RPM=sandia-openshmem_gcc_hfi +SOS_TEST_RPM=sandia-openshmem_gcc_hfi-tests + +get_shmem_bench_dir() +{ + + local TEST_NAME=$1 + local instDir=`rpm -ql $SOS_TEST_RPM |grep -e "/$TEST_NAME$" |sed -e "s%/$TEST_NAME%%"` + if [[ $? -ne 0 || $instDir = "(none)" || ! -d $instDir ]] ; then + echo "$TEST_NAME not found" + exit 1 + fi + echo $instDir +} + +show_mpi_hosts() +{ + local lines + + echo "Using hosts list: $MPI_HOSTS" + + if [ "${SHOW_MPI_HOSTS:-y}" = "y" ] + then + show_lines=${SHOW_MPI_HOSTS_LINES:-128} + if [ "z$NUM_PROCESSES" != "z" ] + then + # there may be comments before the last host. So we number the + # lines, filter out the lines with comments and blank lines + # and then get the "NUM_PROCESSES"th line's number + avail_lines=$(nl -s';' -nln -w1 -ba $MPI_HOSTS|egrep -v '^[0-9]*;[[:space:]]*#'|egrep -v '^[0-9]*;[[:space:]]*$'|head -$NUM_PROCESSES|tail -1|cut -f1 -d';' ) + else + # no NUM_PROCESSES, so use whole file + avail_lines=$(cat $MPI_HOSTS|wc -l) + fi + if [ $show_lines -ge $avail_lines ] + then + echo "Hosts in run:" + head -n $avail_lines $MPI_HOSTS + else + echo "First $show_lines lines in host list for run:" + head -n $show_lines $MPI_HOSTS + fi + echo + fi +} + + +if [ -z "$NUM_PROCESSES" ]; then + NUM_PROCESSES=2 + echo " Defaulting to $NUM_PROCESSES processes" +elif [[ ! "$NUM_PROCESSES" =~ [0-9]+ ]]; then + echo " Expected number for and got: $NUM_PROCESSES" + exit 1 +fi + +if [ -z "$LOGFILE" ] +then + CURTIME=`date +%d%b%y%H%M%S` + if [ ! -d logs ] + then + mkdir -p logs + fi + LOGFILE=$PWD/logs/$APP.$CURTIME$LOGSUFFIX + echo " Running MPI tests with $NUM_PROCESSES processes" + echo " logfile $LOGFILE" + > $LOGFILE +fi +SHMEM_PREFIX=${SHMEM_PREFIX:-`rpm -ql $SOS_RPM |grep -e "bin/oshrun" |sed -e "s%/bin/oshrun%%"`} +if [ -z "$SHMEM_PREFIX" ]; then + echo "Environment variale SHMEM_PREFIX Not defined" >&2 +fi + +OSHRUN=$SHMEM_PREFIX/bin/oshrun +if [[ ! -e $OSHRUN ]] ; then + echo "osrun Not found. Expecting it at: $OSHRUN " >&2 + exit 1 +fi + +export MPI_HOSTS=${MPI_HOSTS:-./shmem_hosts} + +if [ ! -f $MPI_HOSTS ] ; then + echo "No MPI hosts file defined. Set MPI_HOSTS variable pointing to the hosts file" + exit 1 +fi + +if [[ -z $MPICH_PREFIX ]] ; then + . ./select_mpi + if [[ -z $MPICH_PREFIX ]] ; then + echo "Error: MPICH_PREFIX not set" >&2 + exit 1 + fi + echo " Using MVAPICH2 at $MPICH_PREFIX (in PATH and LD_LIBRARY_PATH)" >&2 +fi + +rpm -q $SOS_TEST_RPM &>/dev/null +if [ $? -ne 0 ]; then + echo "Error: RPM $SOS_TEST_RPM is expected to be installed with the tests binaries" + exit 1 +fi + +export SHMEM_RUN="$SHMEM_PREFIX/bin/oshrun --hostfile $MPI_HOSTS" +export PATH=${MPICH_PREFIX}/bin:${SHMEM_PREFIX}/bin:${PATH} +export LD_LIBRARY_PATH=${MPICH_PREFIX}/lib64:${SHMEM_PREFIX}/lib64:${LD_LIBRARY_PATH} + diff --git a/ShmemApps/apps/run_alltoall b/ShmemApps/apps/run_alltoall new file mode 100644 index 0000000..9231eb7 --- /dev/null +++ b/ShmemApps/apps/run_alltoall @@ -0,0 +1,71 @@ +#!/bin/sh +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] + +# BASE PATH TO MPI EXECUTABLES: To use an alternate location, +# either edit this line or set MPICH_PREFIX in your environment. +# see select_mpi for the set of default MPI selections +# default to MPI used for build +MPICH_PREFIX=${MPICH_PREFIX:-`cat .prefix 2>/dev/null`} +SHMEM_PREFIX=${SHMEM_PREFIX:-`cat .shmem_prefix 2>/dev/null`} + +trap "exit 1" SIGHUP SIGTERM SIGINT + +if [ -z "$1" ] +then + echo " Usage: run_alltoall " + echo " For example: ./run_alltoall 2" + exit 1 +fi + +NUM_PROCESSES=$1 +shift +APP=alltoall +LOGFILE= +. ./prepare_run + +SAMPLE_DIR=${SAMPLE_DIR:-`get_shmem_bench_dir $APP`} +EXECUTABLE="$SAMPLE_DIR/$APP" +CMD="$EXECUTABLE $@" +if [ ! -x $EXECUTABLE ] +then + echo " $EXECUTABLE: Not Found" + exit 1 +fi + +( + echo " Running SHMEM All to All Benchmark ..." + show_mpi_hosts + set -x + $SHMEM_RUN -np $NUM_PROCESSES $CMD + set +x +) 2>&1 | tee -i -a $LOGFILE +echo "########################################### " >> $LOGFILE diff --git a/ShmemApps/apps/run_barrier b/ShmemApps/apps/run_barrier new file mode 100755 index 0000000..492c01f --- /dev/null +++ b/ShmemApps/apps/run_barrier @@ -0,0 +1,71 @@ +#!/bin/sh +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] + +# BASE PATH TO MPI EXECUTABLES: To use an alternate location, +# either edit this line or set MPICH_PREFIX in your environment. +# see select_mpi for the set of default MPI selections +# default to MPI used for build +MPICH_PREFIX=${MPICH_PREFIX:-`cat .prefix 2>/dev/null`} +SHMEM_PREFIX=${SHMEM_PREFIX:-`cat .shmem_prefix 2>/dev/null`} + +trap "exit 1" SIGHUP SIGTERM SIGINT + +if [ -z "$1" ] +then + echo " Usage: run_barrier " + echo " For example: ./run_barrier 2" + exit 1 +fi + +NUM_PROCESSES=$1 +shift +APP=barrier +LOGFILE= +. ./prepare_run + +SAMPLE_DIR=${SAMPLE_DIR:-`get_shmem_bench_dir $APP`} +EXECUTABLE="$SAMPLE_DIR/$APP" +CMD="$EXECUTABLE $@" +if [ ! -x $EXECUTABLE ] +then + echo " $EXECUTABLE: Not Found" + exit 1 +fi + +( + echo " Running SHMEM Barrier Benchmark ..." + show_mpi_hosts + set -x + $SHMEM_RUN -np $NUM_PROCESSES $CMD + set +x +) 2>&1 | tee -i -a $LOGFILE +echo "########################################### " >> $LOGFILE diff --git a/ShmemApps/apps/run_get_bibw b/ShmemApps/apps/run_get_bibw new file mode 100755 index 0000000..ec417ec --- /dev/null +++ b/ShmemApps/apps/run_get_bibw @@ -0,0 +1,74 @@ +#!/bin/sh +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] + +# BASE PATH TO MPI EXECUTABLES: To use an alternate location, +# either edit this line or set MPICH_PREFIX in your environment. +# see select_mpi for the set of default MPI selections +# default to MPI used for build +MPICH_PREFIX=${MPICH_PREFIX:-`cat .prefix 2>/dev/null`} +SHMEM_PREFIX=${SHMEM_PREFIX:-`cat .shmem_prefix 2>/dev/null`} + +trap "exit 1" SIGHUP SIGTERM SIGINT + +if [ -z "$1" ] +then + echo " Usage: run_get_bibw [args...]" + echo " args - additional test program options, -h will provide help" + echo " For example: ./run_get_bibw 2" + echo "This application requires an even number of processes" + exit 1 +fi + +NUM_PROCESSES=$1 +shift +MULT_PROCESSES=2 +APP=shmem_bibw_get_perf +LOGFILE= +. ./prepare_run + +SAMPLE_DIR=${SAMPLE_DIR:-`get_shmem_bench_dir $APP`} +EXECUTABLE="$SAMPLE_DIR/$APP" +CMD="$EXECUTABLE $@" +if [ -z $EXECUTABLE ] || [ ! -x $EXECUTABLE ] +then + echo " $EXECUTABLE: Not Found" + exit 1 +fi + +( + echo " Running SHMEM Bi-Directional Get Bandwidth Benchmark ..." + show_mpi_hosts + set -x + $SHMEM_RUN -np $NUM_PROCESSES $CMD + set +x +) 2>&1 | tee -i -a $LOGFILE +echo "########################################### " >> $LOGFILE diff --git a/ShmemApps/apps/run_get_bw b/ShmemApps/apps/run_get_bw new file mode 100755 index 0000000..d7945c0 --- /dev/null +++ b/ShmemApps/apps/run_get_bw @@ -0,0 +1,74 @@ +#!/bin/sh +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] + +# BASE PATH TO MPI EXECUTABLES: To use an alternate location, +# either edit this line or set MPICH_PREFIX in your environment. +# see select_mpi for the set of default MPI selections +# default to MPI used for build +MPICH_PREFIX=${MPICH_PREFIX:-`cat .prefix 2>/dev/null`} +SHMEM_PREFIX=${SHMEM_PREFIX:-`cat .shmem_prefix 2>/dev/null`} + +trap "exit 1" SIGHUP SIGTERM SIGINT + +if [ -z "$1" ] +then + echo " Usage: run_get_bw [args ...]" + echo " args - additional test program options, -h will provide help" + echo " For example: ./run_get_bw 2" + echo "This application requires an even number of processes" + exit 1 +fi + +NUM_PROCESSES=$1 +shift +MULT_PROCESSES=2 +APP=shmem_bw_get_perf +LOGFILE= +. ./prepare_run + +SAMPLE_DIR=${SAMPLE_DIR:-`get_shmem_bench_dir $APP`} +EXECUTABLE="$SAMPLE_DIR/$APP" +CMD="$EXECUTABLE $@" +if [ ! -x $EXECUTABLE ] +then + echo " $EXECUTABLE: Not Found" + exit 1 +fi + +( + echo " Running SHMEM Uni-Directional Get Bandwidth Benchmark ..." + show_mpi_hosts + set -x + $SHMEM_RUN -np $NUM_PROCESSES $CMD + set +x +) 2>&1 | tee -i -a $LOGFILE +echo "########################################### " >> $LOGFILE diff --git a/ShmemApps/apps/run_get_latency b/ShmemApps/apps/run_get_latency new file mode 100755 index 0000000..7b1fd3b --- /dev/null +++ b/ShmemApps/apps/run_get_latency @@ -0,0 +1,74 @@ +#!/bin/sh +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] + +# BASE PATH TO MPI EXECUTABLES: To use an alternate location, +# either edit this line or set MPICH_PREFIX in your environment. +# see select_mpi for the set of default MPI selections +# default to MPI used for build +MPICH_PREFIX=${MPICH_PREFIX:-`cat .prefix 2>/dev/null`} +SHMEM_PREFIX=${SHMEM_PREFIX:-`cat .shmem_prefix 2>/dev/null`} + +trap "exit 1" SIGHUP SIGTERM SIGINT + +if [ -z "$1" ] +then + echo " Usage: run_get_latency [args ...]" + echo " args - additional test program options, -h will provide help" + echo " For example: ./run_get_latency 2" + echo "This application requires an even number of processes" + exit 1 +fi + +NUM_PROCESSES=$1 +shift +MULT_PROCESSES=2 +APP=shmem_latency_get_perf +LOGFILE= +. ./prepare_run + +SAMPLE_DIR=${SAMPLE_DIR:-`get_shmem_bench_dir $APP`} +EXECUTABLE="$SAMPLE_DIR/$APP" +CMD="$EXECUTABLE $@" +if [ ! -x $EXECUTABLE ] +then + echo " $EXECUTABLE: Not Found" + exit 1 +fi + +( + echo " Running SHMEM Get Latency Benchmark ..." + show_mpi_hosts + set -x + $SHMEM_RUN -np $NUM_PROCESSES $CMD + set +x +) 2>&1 | tee -i -a $LOGFILE +echo "########################################### " >> $LOGFILE diff --git a/ShmemApps/apps/run_hello b/ShmemApps/apps/run_hello new file mode 100644 index 0000000..905afc4 --- /dev/null +++ b/ShmemApps/apps/run_hello @@ -0,0 +1,69 @@ +#!/bin/sh +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] + +# BASE PATH TO MPI EXECUTABLES: To use an alternate location, +# either edit this line or set MPICH_PREFIX in your environment. +# see select_mpi for the set of default MPI selections +# default to MPI used for build +MPICH_PREFIX=${MPICH_PREFIX:-`cat .prefix 2>/dev/null`} +SHMEM_PREFIX=${SHMEM_PREFIX:-`cat .shmem_prefix 2>/dev/null`} + +trap "exit 1" SIGHUP SIGTERM SIGINT + +if [ -z "$1" ] +then + echo " Usage: run_hello " + echo " For example: ./run_hello 2" + exit 1 +fi + +NUM_PROCESSES=$1 +APP=shmem-hello +LOGFILE= +. ./prepare_run + +EXECUTABLE=./$APP +CMD=$EXECUTABLE +if [ ! -x $EXECUTABLE ] +then + echo " $EXECUTABLE: Not Found" + exit 1 +fi + +( + echo " Running SHMEM Hello Application ..." + show_mpi_hosts + set -x + $SHMEM_RUN -np $NUM_PROCESSES $CMD + set +x +) 2>&1 | tee -i -a $LOGFILE +echo "########################################### " >> $LOGFILE diff --git a/ShmemApps/apps/run_put_bibw b/ShmemApps/apps/run_put_bibw new file mode 100755 index 0000000..0f92794 --- /dev/null +++ b/ShmemApps/apps/run_put_bibw @@ -0,0 +1,74 @@ +#!/bin/sh +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] + +# BASE PATH TO MPI EXECUTABLES: To use an alternate location, +# either edit this line or set MPICH_PREFIX in your environment. +# see select_mpi for the set of default MPI selections +# default to MPI used for build +MPICH_PREFIX=${MPICH_PREFIX:-`cat .prefix 2>/dev/null`} +SHMEM_PREFIX=${SHMEM_PREFIX:-`cat .shmem_prefix 2>/dev/null`} + +trap "exit 1" SIGHUP SIGTERM SIGINT + +if [ -z "$1" ] +then + echo " Usage: run_put_bibw [args ...]" + echo " args - additional test program options, -h will provide help" + echo " For example: ./run_put_bibw 2" + echo "This application requires an even number of processes" + exit 1 +fi + +NUM_PROCESSES=$1 +shift +MULT_PROCESSES=2 +APP=shmem_bibw_put_perf +LOGFILE= +. ./prepare_run + +SAMPLE_DIR=${SAMPLE_DIR:-`get_shmem_bench_dir $APP`} +EXECUTABLE="$SAMPLE_DIR/$APP" +CMD="$EXECUTABLE $@" +if [ ! -x $EXECUTABLE ] +then + echo " $EXECUTABLE: Not Found" + exit 1 +fi + +( + echo " Running SHMEM Bi-Directional Put Bandwidth Benchmark ..." + show_mpi_hosts + set -x + $SHMEM_RUN -np $NUM_PROCESSES $CMD + set +x +) 2>&1 | tee -i -a $LOGFILE +echo "########################################### " >> $LOGFILE diff --git a/ShmemApps/apps/run_put_bw b/ShmemApps/apps/run_put_bw new file mode 100755 index 0000000..665c287 --- /dev/null +++ b/ShmemApps/apps/run_put_bw @@ -0,0 +1,74 @@ +#!/bin/sh +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] + +# BASE PATH TO MPI EXECUTABLES: To use an alternate location, +# either edit this line or set MPICH_PREFIX in your environment. +# see select_mpi for the set of default MPI selections +# default to MPI used for build +MPICH_PREFIX=${MPICH_PREFIX:-`cat .prefix 2>/dev/null`} +SHMEM_PREFIX=${SHMEM_PREFIX:-`cat .shmem_prefix 2>/dev/null`} + +trap "exit 1" SIGHUP SIGTERM SIGINT + +if [ -z "$1" ] +then + echo " Usage: run_put_bw number_processes [args ...]" + echo " args - additional test program options, -h will provide help" + echo " For example: ./run_put_bw 2" + echo "This application requires an even number of processes" + exit 1 +fi + +NUM_PROCESSES=$1 +shift +MULT_PROCESSES=2 +APP=shmem_bw_put_perf +LOGFILE= +. ./prepare_run + +SAMPLE_DIR=${SAMPLE_DIR:-`get_shmem_bench_dir $APP`} +EXECUTABLE="$SAMPLE_DIR/$APP" +CMD="$EXECUTABLE $@" +if [ ! -x $EXECUTABLE ] +then + echo " $EXECUTABLE: Not Found" + exit 1 +fi + +( + echo " Running SHMEM Uni-Directional Put Bandwidth Benchmark ..." + show_mpi_hosts + set -x + $SHMEM_RUN -np $NUM_PROCESSES $CMD + set +x +) 2>&1 | tee -i -a $LOGFILE +echo "########################################### " >> $LOGFILE diff --git a/ShmemApps/apps/run_put_latency b/ShmemApps/apps/run_put_latency new file mode 100755 index 0000000..c4b4cb5 --- /dev/null +++ b/ShmemApps/apps/run_put_latency @@ -0,0 +1,74 @@ +#!/bin/sh +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] + +# BASE PATH TO MPI EXECUTABLES: To use an alternate location, +# either edit this line or set MPICH_PREFIX in your environment. +# see select_mpi for the set of default MPI selections +# default to MPI used for build +MPICH_PREFIX=${MPICH_PREFIX:-`cat .prefix 2>/dev/null`} +SHMEM_PREFIX=${SHMEM_PREFIX:-`cat .shmem_prefix 2>/dev/null`} + +trap "exit 1" SIGHUP SIGTERM SIGINT + +if [ -z "$1" ] +then + echo " Usage: run_put_latency [args ...]" + echo " args - additional test program options, -h will provide help" + echo " For example: ./run_put_latency 2" + echo "This application requires an even number of processes" + exit 1 +fi + +NUM_PROCESSES=$1 +shift +MULT_PROCESSES=2 +APP=shmem_latency_put_perf +LOGFILE= +. ./prepare_run + +SAMPLE_DIR=${SAMPLE_DIR:-`get_shmem_bench_dir $APP`} +EXECUTABLE="$SAMPLE_DIR/$APP" +CMD="$EXECUTABLE $@" +if [ ! -x $EXECUTABLE ] +then + echo " $EXECUTABLE: Not Found" + exit 1 +fi + +( + echo " Running SHMEM Put Latency Benchmark ..." + show_mpi_hosts + set -x + $SHMEM_RUN -np $NUM_PROCESSES $CMD + set +x +) 2>&1 | tee -i -a $LOGFILE +echo "########################################### " >> $LOGFILE diff --git a/ShmemApps/apps/run_reduce b/ShmemApps/apps/run_reduce new file mode 100755 index 0000000..5c255bf --- /dev/null +++ b/ShmemApps/apps/run_reduce @@ -0,0 +1,72 @@ +#!/bin/sh +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] + +# BASE PATH TO MPI EXECUTABLES: To use an alternate location, +# either edit this line or set MPICH_PREFIX in your environment. +# see select_mpi for the set of default MPI selections +# default to MPI used for build +export MPICH_PREFIX=${MPICH_PREFIX:-`cat .prefix 2>/dev/null`} +SHMEM_PREFIX=${SHMEM_PREFIX:-`cat .shmem_prefix 2>/dev/null`} + +trap "exit 1" SIGHUP SIGTERM SIGINT + +if [ -z "$1" ] +then + echo " Usage: run_reduce [args ...]" + echo " args - additional test program options, -h will provide help" + echo " For example: ./run_reduce 2" + exit 1 +fi + +NUM_PROCESSES=$1 +shift +APP=reduce_active_set +LOGFILE= +. ./prepare_run + +SAMPLE_DIR=${SAMPLE_DIR:-`get_shmem_bench_dir $APP`} +EXECUTABLE="$SAMPLE_DIR/$APP" +CMD="$EXECUTABLE $@" +if [ ! -x $EXECUTABLE ] +then + echo " $EXECUTABLE: Not Found" + exit 1 +fi + +( + echo " Running SHMEM Reduce ..." + show_mpi_hosts + set -x + $SHMEM_RUN -np $NUM_PROCESSES $CMD + set +x +) 2>&1 | tee -i -a $LOGFILE +echo "########################################### " >> $LOGFILE diff --git a/ShmemApps/apps/select_mpi b/ShmemApps/apps/select_mpi new file mode 100755 index 0000000..c22c733 --- /dev/null +++ b/ShmemApps/apps/select_mpi @@ -0,0 +1,94 @@ +#!/bin/sh +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] + +# helper script to select MPICH_PREFIX + +# this script should be . included in a run_ script +# Input: +# MPICH_PREFIX - path to MPICH tools (optional) +# Output: +# MPICH_PREFIX - path to MPICH tools + +valid_mpich_prefix() +{ + if [ -z "$MPICH_PREFIX" -o ! -e "$MPICH_PREFIX" -o ! -e "$MPICH_PREFIX"/bin ] + then + return 1 + fi + if [ -e "$MPICH_PREFIX/bin/mpirun" -o -e "$MPICH_PREFIX/bin/mpdtrace" \ + -o -e "$MPICH_PREFIX/bin/mpirun_mpd" -o -e "$MPICH_PREFIX/bin/mpiexec" \ + -o -e "$MPICH_PREFIX/bin/mpirun_rsh" ] + then + return 0 + else + return 1 + fi +} + +# check all MPIs which start with $1 pathname and pick the 1st valid one +find_mpi() +{ + local mpich_prefix + for mpich_prefix in $(ls -d $1/bin 2>/dev/null) + do + MPICH_PREFIX=$(dirname $mpich_prefix 2>/dev/null) + if valid_mpich_prefix + then + break + else + MPICH_PREFIX="" + fi + done +} + +# defaults we use for MPI (openmpi, IntelMPI, mvapich2) +if [ -z "$MPICH_PREFIX" ] +then + + prefix=${prefix:-/usr} + + # OpenMPI is the only supported runner + if ! valid_mpich_prefix + then + find_mpi $(ls -d $prefix/mpi/gcc/mvapich2*hfi) + fi + if ! valid_mpich_prefix + then + find_mpi $prefix/mpi/gcc/mvapich2* + fi + if ! valid_mpich_prefix + then + MPICH_PREFIX="" + fi +fi +export MPICH_PREFIX + diff --git a/ShmemApps/apps/shmem-hello.c b/ShmemApps/apps/shmem-hello.c new file mode 100644 index 0000000..ee28ad8 --- /dev/null +++ b/ShmemApps/apps/shmem-hello.c @@ -0,0 +1,40 @@ +/* BEGIN_ICS_COPYRIGHT7 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT7 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ +#include +#include + +int main(int argc, char ** argv) +{ + shmem_init(); + printf("Hello from PE %d out of %d\n", shmem_my_pe(), shmem_n_pes()); + shmem_finalize(); + return 0; +} diff --git a/TestTools/Loop_Test_Instructions.txt b/TestTools/Loop_Test_Instructions.txt new file mode 100644 index 0000000..0c925ac --- /dev/null +++ b/TestTools/Loop_Test_Instructions.txt @@ -0,0 +1,180 @@ +A) Introduction +B) Basic Loop Test Operation +C) Information in the Logs +D) Advanced Loop Test Options +E) Debug Options + +====================== +A) Introduction +====================== +1. SM must be started manually. + +2. run_hsm_loop_test_fast.sh is a simple wrapper script to start and stop loop test. + (and also for controlling the loop test parameters) + +3. run_hsm_loop_test_fast.sh starts loop test in fast mode. In fast mode, loop test, + by default starts with max loop path length of 4 and is able to + finish setting up the loops faster. At the end the script sets fast mode + back to 0. + +============================ +B) Basic Loop Test Operation +============================ +1. Start SM manually. (Configure FM threshold for Integrity errors to 1 for a strict check. Default is 100.) + +2. Wait till SM reaches a stable state i.e. finishes all initial sweeps. + +3. Start loop test + + ./run_hsm_loop_test_fast.sh -s (By default injects 5 packets into each + loop. See -i option for changing number of packets injected) + +Note: + Side effect of starting loop test is that periodic SM sweeps will stop. + But fabric events can still trigger a sweep. Since loop test is started in + Fast Mode, subsequent sweeps will not inject packets by default. (this + behavior can be controlled by fm_cmd smLoopTestInjectEachSweep option) + +4. Check SM logs to see if loop test is covering all ISLs (see point (C) below for more info on the SM logs) + +5. Use iba_top to monitor SWs group (group 3) for utilization to see if ISLs are getting stressed. + +6. Let loop test run for a few hours. + +7. Use iba_top and/or SM logs to check for integrity errors on ISLs. + +8. Stop loop test + + ./run_hsm_loop_test_fast.sh -e + + This also turns off Loop test Fast mode. + +9. Optional: Reboot all switches. + Stopping loop test will reprogram the fabric without loops, so the loop packets will stop. + If desired, switches can be rebooted to make doubly sure everything returns to a clean state. + +--------- +Example: +--------- + +[root@george ~]# ./run_hsm_loop_test_fast.sh -s +Turning on Loop test Fast Mode... +Connecting to LOCAL FM instance 0 +Successfully sent Loop Test Fast Mode 1 control to local SM instance +Starting Loop test with 4 packets... +Connecting to LOCAL FM instance 0 +Successfully sent Loop Test START control (4 inject packets)to local SM instance + + + +[root@george ~]# ./run_hsm_loop_test_fast.sh -e +Stopping Loop test... +Connecting to LOCAL FM instance 0 +Successfully sent Loop Test STOP control to local SM instance +Turning OFF Loop test Fast Mode... +Connecting to LOCAL FM instance 0 +Successfully sent Loop Test Fast Mode 0 control to local SM instance + + + +================================== +C) Information in the Logs +================================= +Whenever loop test runs, following useful info is logged in the log file which looks like: + + +fm0_sm[20334]: PROGR[topology]: SM: print_LoopCoverage: Total 828 ISL ports (hence 414 ISLs) are in loop paths +fm0_sm[20334]: PROGR[topology]: SM: print_LoopCoverage: Loop Coverage: Full - all ISL ports covered +fm0_sm[20334]: PROGR[topology]: SM: print_LoopCoverage: Total 414 Loop paths of length <= 4 links. MinISLRedundancy is 4. +fm0_sm[20334]: PROGR[topology]: SM: print_LoopCoverage: Total LIDs required for loop paths is 828. +fm0_sm[20334]: PROGR[topology]: SM: topology_loopTest: Packets injected since start of loop test = 4 +fm0_sm[20334]: PROGR[topology]: SM: topology_loopTest: END topology_loopTest + + +If loop coverage is partial - information about all switch ports not covered in the test is logged. + +================================ +D) Advanced Loop Test Options +=============================== + +1. Injecting more packets + + ./run_hsm_loop_test_fast.sh -i will inject num packets in all the loops. + + Steps: + + a) Can be used along with -s to determine how many packets will be injected at start. + + ./run_hsm_loop_test_fast.sh -s -i 2 + + b) Can be used separately after starting the test to inject more packets in the loops. + + ./run_hsm_loop_test_fast.sh -i 1 + + +2. Changing minimum number of loops in which each ISL is included (smLooptestMinISLRedundancy) + + IMPORTANT NOTES: + + a) After changes, parameter value DOES NOT reset to default value automatically after stopping loop test. + Changes are persistent through out the SM run even after stopping the loop test. + + b) This needs updated fm_cmd which is in the build. You can use -d option of + run_hsm_loop_test to run fm_cmd present at a different location. + + + Default value of smLooptestMinISLRedundancy is 4. + + Steps: + + a) Stop loop test (if its running) + ./run_hsm_loop_test_fast.sh -e + + WAIT TILL THE SM SWEEP FINISHES. + + b) Set MinISLRedundancy + + ./run_hsm_loop_test_fast.sh -r -d [if updated fm_cmd is NOT at standard location] + + OR + + ./run_hsm_loop_test_fast.sh -r [if updated fm_cmd is at standard location] + + c) Start loop test + ./run_hsm_loop_test_fast.sh -s + + +3. Changing loop path length (smLooptestPathLength) + + IMPORTANT NOTE: + After changes, parameter value DOES NOT reset to default value automatically after stopping loop test. + Changes are persistent through out the SM run even after stopping the loop test. + + Default value of smLooptestPathLength is 4. + + Steps: + + a) Stop loop test (if its running) + ./run_hsm_loop_test_fast.sh -e + + WAIT TILL THE SM SWEEP FINISHES. + + b) Set path length + ./run_hsm_loop_test_fast.sh -l + + c) Start loop test + ./run_hsm_loop_test_fast.sh -s + +=========================== +E) Debug options +=========================== +To see a list of all loop paths: + +1) Set SmPerfDebug parameter to 1. + +2) Start SM binary directly in the foreground on the terminal. + +3) Start loop test. + +4) SM prints out all the loop paths on the terminal. + diff --git a/TestTools/Makefile b/TestTools/Makefile new file mode 100644 index 0000000..5907911 --- /dev/null +++ b/TestTools/Makefile @@ -0,0 +1,185 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + + +# Makefile for TestTools + +# Include Make Control Settings +include $(TL_DIR)/$(PROJ_FILE_DIR)/Makesettings.project + +# This makefile is an oddball, it is the only test Makefile +# which actually builds code. +# even then it only builds some scripts and a tclIndex file. +# hence for simplicity it is handcoded and does not use any makerules + +#=============================================================================# +# Definitions: +#-----------------------------------------------------------------------------# + +# Name of SubProjects +DS_SUBPROJECTS = +# name of executable or downloadable image +EXECUTABLE = # TestTools$(EXE_SUFFIX) +# list of sub directories to build +DIRS = +# C files (.c) +CFILES = \ + qlgc_fork.c \ + # Add more c files here +# C++ files (.cpp) +CCFILES = \ + # Add more cpp files here +# lex files (.lex) +LFILES = \ + # Add more lex files here +# archive library files (basename, $ARFILES will add MOD_LIB_DIR/prefix and suffix) +LIBFILES = +TCL_SOURCES = proc_mgr.exp tools.exp target.exp chassis.exp basic.exp \ + network.exp install.exp ib.exp extmng.exp mpi.exp opa_to_xml.exp common_funcs.exp sm_control.exp switch_methods.exp +# Windows Resource Files (.rc) +RSCFILES = +# Windows IDL File (.idl) +IDLFILE = +# Windows Linker Module Definitions (.def) file for dll's +DEFFILE = +# targets to build during INCLUDES phase (add public includes here) +INCLUDE_TARGETS = \ + # Add more h hpp files here +# Non-compiled files +MISC_FILES = +# all source files +SOURCES = $(CFILES) $(CCFILES) $(LFILES) $(RSCFILES) $(IDLFILE) +# Source files to include in DSP File +DSP_SOURCES = $(INCLUDE_TARGETS) $(SOURCES) $(MISC_FILES) \ + $(RSCFILES) $(DEFFILE) $(MAKEFILE) +# all object files +OBJECTS = $(CFILES:.c=$(OBJ_SUFFIX)) $(CCFILES:.cpp=$(OBJ_SUFFIX)) \ + $(LFILES:.lex=$(OBJ_SUFFIX)) +RSCOBJECTS = $(RSCFILES:.rc=$(RES_SUFFIX)) +# targets to build during LIBS phase +LIB_TARGETS_IMPLIB = +LIB_TARGETS_ARLIB = +LIB_TARGETS_EXP = $(LIB_TARGETS_IMPLIB:$(ARLIB_SUFFIX)=$(EXP_SUFFIX)) +LIB_TARGETS_MISC = +# targets to build during CMDS phase +CMD_TARGETS_SHLIB = $(LIB_PREFIX)qlgc_fork$(SHLIB_SUFFIX) +CMD_TARGETS_EXE = $(EXECUTABLE) +CMD_TARGETS_MISC = tclIndex front +# files to remove during clean phase +CLEAN_TARGETS_MISC = +CLEAN_TARGETS = $(OBJECTS) $(RSCOBJECTS) $(IDL_TARGETS) $(CLEAN_TARGETS_MISC) +# other files to remove during clobber phase +CLOBBER_TARGETS_MISC=$(CMD_TARGETS_MISC) +# sub-directory to install to within bin +BIN_SUBDIR = +# sub-directory to install to within include +INCLUDE_SUBDIR = + +# Additional Settings +#CLOCALDEBUG = User defined C debugging compilation flags [Empty] +#CCLOCALDEBUG = User defined C++ debugging compilation flags [Empty] +#CLOCAL = User defined C flags for compiling [Empty] +#CCLOCAL = User defined C++ flags for compiling [Empty] +#BSCLOCAL = User flags for Browse File Builder [Empty] +#DEPENDLOCAL = user defined makedepend flags [Empty] +#LINTLOCAL = User defined lint flags [Empty] +#LOCAL_INCLUDE_DIRS = User include directories to search for C/C++ headers [Empty] +#LDLOCAL = User defined C flags for linking [Empty] +#IMPLIBLOCAL = User flags for Object Lirary Manager [Empty] +#MIDLLOCAL = User flags for IDL compiler [Empty] +#RSCLOCAL = User flags for resource compiler [Empty] +#LOCALDEPLIBS = User libraries to include in dependencies [Empty] +#LOCALLIBS = User libraries to use when linking [Empty] +# (in addition to LOCALDEPLIBS) +#LOCAL_LIB_DIRS = User library directories for libpaths [Empty] +CLOCAL=-DUSE_TCL_STUBS $(CPIC) +# tcl.h is located in /usr/include for RedHat and in /usr/include/tcl for Ubuntu +LOCAL_INCLUDE_DIRS = /usr/include/tcl +LOCALLIBS=$(shell if [ -e /usr/lib64/libtclstub.a -o -e /usr/lib/libtclstub.a -o -e /usr/lib/x86_64-linux-gnu/libtclstub.a ]; then echo tclstub; \ + elif [ -e /usr/lib64/libtclstub8.6.a -o -e /usr/lib/libtclstub8.6.a -o -e /usr/lib/x86_64-linux-gnu/libtclstub8.6.a ]; then echo tclstub8.6; \ + elif [ -e /usr/lib64/libtclstub8.5.a -o -e /usr/lib/libtclstub8.5.a -o -e /usr/lib/x86_64-linux-gnu/libtclstub8.5.a ]; then echo tclstub8.5; \ + else echo tclstub8.4; fi) + +# Include Make Rules definitions and rules +include $(TL_DIR)/$(PROJ_FILE_DIR)/Makerules.project + +#=============================================================================# +# Overrides: +#-----------------------------------------------------------------------------# +#CCOPT = # C++ optimization flags, default lets build config decide +#COPT = # C optimization flags, default lets build config decide +#SUBSYSTEM = Subsystem to build for (none, console or windows) [none] +# (Windows Only) +#USEMFC = How Windows MFC should be used (none, static, shared, no_mfc) [none] +# (Windows Only) +#=============================================================================# + +#=============================================================================# +# Rules: +#-----------------------------------------------------------------------------# +# process Sub-directories +include $(TL_DIR)/Makerules/Maketargets.toplevel + +# build cmds and libs +include $(TL_DIR)/Makerules/Maketargets.build + +ifeq "$(BUILD_TARGET)" "PPC64" +# must build for 32 bit on PPC64, 64 bit TCL library not available +LDMACH=-m32 +%.o: %.c + $(VS)$(CC) $(subst -m64,-m32,$(CFLAGS)) -c $< +endif + +# used to copy CMD_TARGETS from this directory to $TL_DIR +$(TL_DIR)/%: % + rm -f $@ + cp $^ $@ +# index for autoloading Tcl procedures, remove first in case a symlink +tclIndex: $(TCL_SOURCES) + rm -f tclIndex + echo auto_mkindex . $^|tclsh + echo '# [ICS VERSION STRING: unknown]' >> tclIndex + cat qlgc_fork.pkgIndex >> tclIndex + +# install for includes, libs and cmds phases +include $(TL_DIR)/Makerules/Maketargets.install + +# install for stage phase +#include $(TL_DIR)/Makerules/Maketargets.stage +STAGE:: + $(VS)$(STAGE_INSTALL) $(STAGE_INSTALL_DIR_OPT) $(PROJ_STAGE_IBTOOLS_DIR) tclIndex $(TCL_SOURCES) front ibtools.exp $(CMD_TARGETS_SHLIB) + +# Unit test execution +#include $(TL_DIR)/Makerules/Maketargets.runtest + +#=============================================================================# + +#=============================================================================# +# DO NOT DELETE THIS LINE -- make depend depends on it. +#=============================================================================# diff --git a/TestTools/README b/TestTools/README new file mode 100644 index 0000000..e2544a2 --- /dev/null +++ b/TestTools/README @@ -0,0 +1,15 @@ +This directory contains all the shell and tcl coded scripts which +add tcl commands to support the test environment and fastfabric. + +The following files are included: +proc_mgr.exp - process management library for expect +tools.exp - generic test tools +extmng.exp - operations on 9024FC +network.exp - network ULP test support library +basic.exp - test basic support +target.exp - login and commands to target host/chassis +chassis.exp - switch chassis support functions +ib.exp - IB basic tools and test cases +ibtools.exp - manual inclusion for MAC (does not support TCL_LIB_PATH) +install.exp - install support functions +mpi.exp - MPI test support diff --git a/TestTools/basic.exp b/TestTools/basic.exp new file mode 100644 index 0000000..4ffe1f5 --- /dev/null +++ b/TestTools/basic.exp @@ -0,0 +1,261 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] + +# This is an expect (tcl) library of procedures to aid integration testing +# These functions provide support for pre-built test cases which can be +# provided arguments to indicate the ulp to be tested + +## tcl procedures to support testing: +## ============================================= + +global os_type +set os_type [ exec uname -s ] + +proc get_num_hosts {} { + global env + + set num_hosts [ llength $env(CFG_HOSTS) ] +} + +proc reboot_host { host } { +## +## reboot_host +## ------------------- +## reboot a host +## +## Usage: +## reboot_host host +## Arguments: +## host - host to reboot +## Returns: +## None +## Additional Information: +## None + + global env + + target_root_sh "$host" + send_unix_cmd "reboot" + + # wait for host login shell to go down + expect_eof 60 1 + sleep 10 + + # now wait for host to come online + log_message "Waiting for Host $host to come online" + set online 0 + for { set i 0 } { $i < 100 } { incr i } { + if { $i != 0 } { + log_message "Retrying: Host $host is not yet up" + # wait before we try again + sleep [ calc_timeout 5 ] + } + if { [ catch { target_root_sh $host } res ] != 0 } { + # send escape sequence to close timed out ssh sessions + catch { exp_send "~.\n" } + } else { + # we got in + target_root_sh_exit + set online 1 + break + } + } + if { ! $online } { + set info "Host did not come online within timeout limit" + return -code error -errorinfo $info $info + } + # network can be up before rest of host, allow a little more time + sleep 20 +} + +proc test_case_reboot { host {iterations 1}} { +## +## test_case_reboot +## ------------------- +## test_case to reboot host +## +## Usage: +## test_case_reboot host [iterations] +## Arguments: +## host - host to reboot +## iterations - number of reboot iterations, default is 1 +## Returns: +## None +## Additional Information: +## must be used within a test_suite's body, performs test_case calls +## uses case_setup and case_cleanup provided by caller +## no item_setup nor item_cleanup used + + global env + + test_case "$host.reboot" "$host reboot" "test reboot of $host +confirm host goes down and comes back up +File: TestTools/basic.exp" case_setup case_cleanup { + upvar host host + upvar iterations iterations + + for { set i 0 } { $i < $iterations } { incr i } { + reboot_host $host + } + } +} + +proc chassis_cmd_reboot_all { } { +## +## chassis_cmd_reboot_all +## ------------------- +## issue reboot command to chassis, support older models which don't support +## "reboot now all" command, in which case "reboot now" is used +## Arguments: +## None +## Returns: +## None +## Additional Information: + global spawn_id expect_out spawn_out timeout + global expecting + + set_timeout 60 + set expecting "reboot command response" + send_chassis_cmd "reboot now all" + # if we get a usage message indicating the command is not supported + # we will try "reboot now" command instead + expect { + "Goodbye" return + "sage" noop + "upported" noop + } + expect_chassis_prompt 60 + send_chassis_cmd "reboot now" + expect_list 60 { "Goodbye" } +} + +proc chassis_wait_reboot_done { chassis } { +## +## chassis_wait_reboot_done +## ------------------- +## wait for the reboot command which was just issued to the chassis to complete +## and for the chassis to come back online +## Arguments: +## chassis - chassis being rebooted +## Returns: +## None +## Additional Information: + global spawn_id expect_out spawn_out timeout + global expecting + global env + + # make sure chassis has time to go down (its usually immediate) + sleep 10 + + # use a local shell for ping to verify chassis comes back + # it reboots too fast for us to observe it go away + local_sh + if { [ auto_execok /usr/lib/opa/tools/opagetipaddrtype ] != "" } { + send_unix_cmd "/usr/lib/opa/tools/opagetipaddrtype $chassis" + set out [expect_any 60 {"ipv6" "ipv4" } {"Error:" "Usage:"}] + regexp {([ip]+)([A-Za-z0-9]+)} $out iptype + } else { + set iptype "ipv4" + } + if { $iptype == "ipv4" } { + send_unix_cmd "ping -i 1 $chassis" + } else { + send_unix_cmd "ping6 -i 1 $chassis" + } + # allow 3 minutes for chassis to complete reboot + expect_list 180 {bytes from} + local_sh_exit + # give it a few seconds to boot + sleep 5 + + # now wait for CLI to come online + # 12800 can take 650 seconds = 130 * 5 + log_message "Waiting for Chassis $chassis CLI to come online" + set online 0 + for { set i 0 } { $i < 130 } { incr i } { + if { $i != 0 } { + log_message "Retrying: Chassis $chassis CLI is not yet up" + # wait before we try again + sleep [ calc_timeout 5 ] + } + if { [ catch { target_chassis_admin_sh $chassis } res ] != 0 } { + # send escape sequence to close timed out ssh sessions + catch { exp_send "~.\n" } + } else { + # we got in + target_chassis_admin_sh_exit + set online 1 + break + } + } + if { ! $online } { + set info "Chassis CLI did not come online within timeout limit" + return -code error -errorinfo $info $info + } +} + +proc test_case_chassis_reboot { chassis {iterations 1}} { +## +## test_case_chassis_reboot +## ------------------- +## test_case to reboot chassis +## +## Usage: +## test_case_chassis_reboot chassis [iterations] +## Arguments: +## chassis - chassis to reboot +## iterations - number of reboot iterations, default is 1 +## Returns: +## None +## Additional Information: +## must be used within a test_suite's body, performs test_case calls +## uses case_setup and case_cleanup provided by caller +## no item_setup nor item_cleanup used + + global env + + test_case "$chassis.reboot" "$chassis reboot" "test reboot of $chassis +use ping to confirm comes back up +File: TestTools/basic.exp" case_setup case_cleanup { + upvar chassis chassis + upvar iterations iterations + + for { set i 0 } { $i < $iterations } { incr i } { + # chassis CLI shell for reboot command + target_chassis_admin_sh $chassis + chassis_cmd_reboot_all + # may not be able to send logout command, so just get out of dodge + expect_eof 60 1 + + chassis_wait_reboot_done $chassis + } + } +} diff --git a/TestTools/chassis.exp b/TestTools/chassis.exp new file mode 100644 index 0000000..152d7d9 --- /dev/null +++ b/TestTools/chassis.exp @@ -0,0 +1,2292 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] + +# assumptions: +# slot numbers are alphanumeric: A-Za-z0-9 (actually are numeric in <=3.1) +# card types are alphanumeric with dot, dash, underscore: A-Za-z0-9._- +# versions are alphanumeric with dot, dash, underscore: A-Za-z0-9._- + +# This is an expect (tcl) library of procedures to aid testing +# These functions provide support for chassis operations +# against a test target chassis + +## tcl procedures to support testing: +## ============================================= + +global os_type + +proc get_chassis_sftp_status { slot {wait_done 1 }} { +## +## get_chassis_sftp_status +## ------------------------- +## return the exit status of the last sftp executed against the given slot +## +## Usage: +## get_chassis_sftp_status slot [wait_done] +## Arguments: +## slot - slot number to get status for +## wait_done - if status is "In Progress", loop until changes to another value +## Returns: +## "success" +## "skipped" - transfer unnecessary +## "invalid" - invalid firmware image for card type +## "inprogress" - transfer still in progress, but wait_done not set +## "error" - other errors or timeouts +## -code error on failure +## Additional Information: +## The global timeout is changed by this routine + + global spawn_id expect_out spawn_out timeout + global expecting + + while { 1 } { + send_chassis_cmd "showLastScpRetCode $slot" + set out [expect_list 60 { "Code: [0-9]+:" } { "usage" "Invalid" "Error" "Failed" "roblem" "roblem" "not found"} ] + regexp {[0-9]+} $out ret + expect_chassis_prompt 60 + + if { $ret == 0 } { + return "success" + } elseif { $ret == 1 } { + # unneeded + return "skipped" + } elseif { $ret == 2 } { + # wrong card type + return "invalid" + } elseif { $ret == 3 } { + if { ! $wait_done } { + # transfer in progress internal to chassis + return "inprogress" + } + # can be a few minutes, so lets be a little patient + sleep 20 + } else { + # other errors + return "error" + } + } +} + +proc check_chassis_capability { capability } { +## +## check_chassis_capability +## ------------------------- +## return level of support for the given capability by the current chassis +## +## Usage: +## check_chassis_capability capability +## Arguments: +## capability - the capability name to check +## Returns: +## 0 - capability not supported +## >0 - version of capability supported +## -code error on failure +## Additional Information: +## The global timeout is changed by this routine + + global spawn_id expect_out spawn_out timeout + global expecting + + send_chassis_cmd "showCapability -key $capability" + # the [:space:] bounds the + so we get all the data on the line + set out [expect_list 60 "{$capability: \[0-9A-Za-z\]+\[\[:space:\]\]}" { "usage" "Invalid" "Error" "Failed" "roblem" "not found"} ] + expect_chassis_prompt 60 + #log_message "out=$out" + + # throw away the \r\n, there may be trailing spaces, TCL lists will ignore + regexp {: ([A-Za-z0-9]+)[[:space:]]} $out line ret + #log_message "ret=$ret" + + if { [ string equal -nocase "$ret" "unavailable" ] } { + set ret 0 + } + + return "$ret" +} + +proc get_chassis_slots { { card_type "" } } { +## +## get_chassis_type_slots +## ------------------------- +## return the list of slots in the given chassis of the given card type +## if no card type is specified, a list of all slots in the chassis is returned +## +## Usage: +## get_chassis_type_slots [card_type] +## Arguments: +## card_type - card type, default is "" (eg. all slots) +## Returns: +## list of slots in chassis +## -code error on failure +## Additional Information: +## The global timeout is changed by this routine + + global spawn_id expect_out spawn_out timeout + global expecting + + if { ! [ string equal "$card_type" "" ] } { + send_chassis_cmd "chassisQuery -ignoreInvalidType -type $card_type" + } else { + send_chassis_cmd "chassisQuery" + } + # this could return no slots, in which case "none" is output + # The \r\n is needed to bound the + so we get all the data on the line + set out [expect_list 60 "{slot\[s\]*: \[0-9A-Za-z \]+\[\r\n\]}" { "usage" "Error" "Failed" "roblem" "not found"} ] + expect_chassis_prompt 60 + #log_message "out=$out" + + # The \r\n is needed to bound the + so we get all the data on the line + # there may be trailing spaces, TCL lists will ignore + regexp {: ([0-9A-Za-z ]+)[\r\n]+} $out line ret + #log_message "ret=$ret" + if { [ regexp -nocase "none" "$ret" ] } { + set ret "" + } + + return "$ret" +} + +proc list_esm_security_files { } { +## +## list_esm_security_files +## ------------------------- +## return the list of FM security files in the given chassis +## +## Usage: +## list_esm_security_files +## Arguments: +## none +## Returns: +## list of .pem files in chassis +## -code error on failure +## Additional Information: +## The global timeout is changed by this routine + + global spawn_id expect_out spawn_out timeout + global expecting + + send_chassis_cmd "smListSecurityFiles -showSingleLine" + + # this could return no *.pem files, in which case "none" is output + # The \r\n is needed to bound the + so we get all the data on the line + set out [expect_list 60 "{files: \[0-9A-Za-z._ \]+\[\r\n\]}" { "usage" "Error" "Failed" "roblem" "not found"} ] + expect_chassis_prompt 60 + #log_message "out=$out" + + # The \r\n is needed to bound the + so we get all the data on the line + # there may be trailing spaces, TCL lists will ignore + regexp {: ([0-9A-Za-z._ ]+)[\r\n]+} $out line ret + #log_message "ret=$ret" + if { [ regexp -nocase "none" "$ret" ] } { + set ret "" + } + + return "$ret" +} + +proc get_chassis_card_type { slot } { +## +## get_chassis_card_type +## ------------------------- +## return the card type of the given slot in the given chassis +## +## Usage: +## get_chassis_card_type slot +## Arguments: +## slot - slot to query +## Returns: +## card type of given slot +## -code error on failure +## Additional Information: +## The global timeout is changed by this routine + + # DONE + global spawn_id expect_out spawn_out timeout + global expecting + + send_chassis_cmd "chassisQuery -showType $slot" + # require trailing whitespace to anchor end of string + set out [expect_list 60 "{type: \[a-zA-Z0-9._-\]+\[\[:space:\]\]+}" { "usage" "Invalid" "Error" "Failed" "roblem" "not found"} ] + # just get the card type field + regexp {: ([a-zA-Z0-9._-]+)[[:space:]]+} $out line ret + + expect_chassis_prompt 60 + + return "$ret" +} + +proc is_management_card_type { card_type } { +## +## is_management_card_type +## ------------------------- +## is the given card_type a management card for the current chassis +## +## Usage: +## is_management_card_type card_type +## Arguments: +## card_type - card type to test +## Returns: +## 0-> this card type is not the management card type for this chassis +## 1-> this card type is the management card type for this chassis +## -code error on failure +## Additional Information: +## The global timeout is changed by this routine +## +## Our best way to do this is to query slot 0 for its card type. Slot 0 +## is always the management card + + set my_slot [ get_this_slot_number ] + return [string equal [ get_chassis_card_type $my_slot] "$card_type" ] +} + +proc get_this_slot_number { } { +## +## get_this_slot_number +## ------------------------- +## return the slot number of the management card we are logged into +## +## Usage: +## get_this_slot_number +## Arguments: +## Returns: +## slot number +## -code error on failure +## Additional Information: +## The global timeout is changed by this routine + + global spawn_id expect_out spawn_out timeout + global expecting + + send_chassis_cmd "chassisQuery -master" + # this could return no slots, in which case "none" is output + # The \r\n is needed to bound the + so we get all the data on the line + set out [expect_list 60 "{master: \[0-9A-Za-z \]+\[\r\n\]}" { "usage" "Error" "Failed" "roblem" "not found"} ] + expect_chassis_prompt 60 + #log_message "out=$out" + + # The \r\n is needed to bound the + so we get all the data on the line + # there may be trailing spaces, TCL lists will ignore + regexp {: ([0-9A-Za-z ]+)[\r\n]+} $out line ret + #log_message "ret=$ret" + if { [ regexp -nocase "none" "$ret" ] } { + set ret "" + } + + return "$ret" +} + +proc get_chassis_active_firmware_version { slot } { +## +## get_chassis_active_firmware_version +## ------------------------- +## return the presently running firmware_version of the given slot +## in the given chassis +## +## Usage: +## get_chassis_active_firmware_version slot +## Arguments: +## slot - slot to query +## Returns: +## firmware version of given slot +## -code error on failure +## Additional Information: +## The global timeout is changed by this routine + + global spawn_id expect_out spawn_out timeout + global expecting + + send_chassis_cmd "fwVersion $slot" + # echo of command + set out [expect_list 60 { "fwVersion" "Firmware Version: [a-zA-Z0-9.]+[[:space:]]" } { "usage" "Invalid" "Error" "Failed" "roblem" "not found"} ] + regexp {: ([a-zA-Z0-9._-]+)[[:space:]]} $out line ret + expect_chassis_prompt 60 + + return "$ret" +} + +proc get_file_firmware_version { fw_file } { +## +## get_file_firmware_version +## ------------------------- +## return the firmware version of the given local file +## +## Usage: +## get_file_firmware_version fw_file +## Arguments: +## fw_file - local pathname of file +## Returns: +## firmware version of given file +## -code error on failure +## Additional Information: +## The global timeout is changed by this routine + + log_message "opafirmware --showVersion $fw_file\n" + set fw_version [exec /usr/sbin/opafirmware --showVersion $fw_file] + log_message "Version: $fw_version\n" + return "$fw_version" +} + +proc get_file_firmware_type { fw_file } { +## +## get_file_firmware_type +## ------------------------- +## return the firmware type of the given local file +## +## Usage: +## get_file_firmware_type fw_file +## Arguments: +## fw_file - local pathname of file +## Returns: +## firmware card type of given file +## -code error on failure +## Additional Information: +## The global timeout is changed by this routine + + log_message "opafirmware --showType $fw_file" + set card_type [exec /usr/sbin/opafirmware --showType $fw_file] + log_message "Card Type: $card_type\n" + return "$card_type" +} + +proc get_chassis_firmware_version { slot {location "act"} } { +## +## get_chassis_firmware_version +## ------------------------- +## return the firmware version of the given slot in the chassis +## +## Usage: +## get_chassis_firmware_version slot [alternate] +## Arguments: +## slot - slot to query +## location - location to query +## "pri" -> primary +## "alt" -> alternate +## "act" -> active (running) (default) +## Returns: +## firmware version of given slot +## -code error on failure +## Additional Information: +## The global timeout is changed by this routine + + global spawn_id expect_out spawn_out timeout + global expecting + + if { [string equal "$location" "act"] } { + return [get_chassis_active_firmware_version $slot] + } + + if { [string equal "$location" "alt"] } { + #set cmd "bootQuery $slot -showVersion -alternate" + set cmd "bootQuery $slot -alternate" + } else { + #set cmd "bootQuery $slot -showVersion" + set cmd "bootQuery $slot" + } + send_chassis_cmd "$cmd" + set out [expect_list 60 "{version: \[a-zA-Z0-9._-\]+\[\[:space:\]\]}" { "usage" "Invalid" "Error" "Failed" "roblem" "not found"} ] + regexp {: ([a-zA-Z0-9._-]+)[[:space:]]} $out line ret + expect_chassis_prompt 60 + + return "$ret" +} + +proc select_chassis_firmware_version { slot fw_version } { +## +## select_chassis_firmware_version +## ------------------------- +## select the given firmware version for the given slot in the chassis +## +## Usage: +## select_chassis_firmware_version slot fw_version +## Arguments: +## slot - slot to act on +## fw_version - firmware version to select +## Returns: +## 0 -> success +## -code error on failure +## Additional Information: +## The global timeout is changed by this routine + + global spawn_id expect_out spawn_out timeout + global expecting + + chassis_cmd 60 0 "bootSelect $slot -version $fw_version" + + return 0 +} + +proc sftp_chassis_firmware { chassis fw_file {select 0} {slot "all"} } { +## +## sftp_chassis_firmware +## ------------------------- +## push the given firmware file to the specified slots in the +## given chassis. +## +## Usage: +## sftp_chassis_firmware chassis fw_file [select [slot]] +## Arguments: +## chassis - IP address/name of chassis to sftp to +## fw_file - local pathname of file to push +## select - should image be selected (0->no (default), 1->yes) +## slot - slot to push to, default is "all" of given card type +## Returns: +## 0 -> success +## -code error on failure +## Additional Information: +## The global timeout is changed by this routine + global spawn_id expect_out spawn_out timeout + global expecting + + if { $select } { + set nopt "" + } else { + set nopt "n" + } + + # Create a basename for the firmware on the server + set base [ exec basename $fw_file ] + + if { [ string equal "$slot" "all" ] } { + chassis_sftp_cmd "sftp admin@\\\[$chassis\\\]:" "put $fw_file A$nopt:/firmware/$base" + } else { + chassis_sftp_cmd "sftp admin@\\\[$chassis\\\]:" "put $fw_file $nopt$slot:/firmware/$base" + } +} + +proc push_chassis_firmware { chassis fw_file fw_version card_type {action "push"} { slots "all" } } { +## +## push_chassis_firmware +## ------------------------- +## push the given firmware file to the specified slots in the +## given chassis. +## +## Usage: +## push_chassis_firmware chassis fw_file fw_version card_type [action [slots]] +## Arguments: +## chassis - IP address/name of chassis to sftp and telnet to +## fw_file - local pathname of file to push +## fw_version - firmware version of fw_file +## card_type - card type of fw_file +## action - action after pushing firmware: +## push - do not reboot, do not change as primary +## is already primary, no change +## select - select as primary, but do not reboot +## run - select as primary and reboot to activate firmware +## slots - list of slot numbers to push to, default is "all" of given card type +## Returns: +## 0 -> success +## -code error on failure +## Additional Information: +## The global timeout is changed by this routine +## +## Any slots which are not of a card type which matches that +## of the firmware file, are quietly skipped. This allows multi-file +## push to work with a slot list. +## +## If the sftp fails for some slots but succeeds for others. The failed slots +## are logged and an exception will be thrown, however the good slots +## are processed to completion [except for the reboot] (if possible) +## so that they are not left in an odd state + + global spawn_id expect_out spawn_out timeout + global expecting + + # caller has already done this + #set fw_version [get_file_firmware_version $fw_file] + #set card_type [get_file_firmware_type $fw_file] + + # variables: + # select - do we want to select the image as primary + # active - do we want to select the image as primary and activate it + if { [ string equal "$action" "push"] } { + set select 0 + set active 0 + } elseif { [string equal "$action" "select"] } { + set select 1 + set active 0 + } elseif { [string equal "$action" "run"] } { + set select 1 + set active 1 + } else { + fail_test "Invalid firmware push action: $action" + } + + log_message "\nTest: Seeing if $chassis present running firmware supports firmware push ...\n" + target_chassis_admin_sh $chassis + if { [ catch { set cap [check_chassis_capability "fwPush"] } res ] != 0 + || $cap < 1 } { + fail_test "Chassis $chassis present running firmware does not support fwPush:\n$res" + } + log_message "\nTest: Getting Slot list from $chassis ...\n" + + if { [string equal "$slots" "all"] } { + # push to all slots of matching card type + set push_slots [get_chassis_slots $card_type] + set num_slots [llength $push_slots] + #set push_all 0 + set push_all 1 + } else { + # push to a specific set of slots + set push_slots "$slots" + set push_all 0 + } + set num_slots [llength $push_slots] + if { $num_slots == 0 } { + target_chassis_admin_sh_exit + skip_case "No cards of type $card_type" + return 0 + } + set is_mgmt [ is_management_card_type $card_type] + set use_rebootall 0 + if { $is_mgmt } { + if { [ catch { set cap [check_chassis_capability "redundantMgmtCapable"] } res ] == 0 + && $cap >= 1 } { + set use_rebootall 1 + } + } + + log_message "\nTest: Getting present installed firmware from $chassis ...\n" + # first get present firmware versions for each of the slots + set act_fw_versions "" + set pri_fw_versions "" + set alt_fw_versions "" + set card_types "" + foreach slot $push_slots { + lappend card_types [get_chassis_card_type $slot] + lappend act_fw_versions [get_chassis_firmware_version $slot "act"] + lappend pri_fw_versions [get_chassis_firmware_version $slot "pri"] + lappend alt_fw_versions [get_chassis_firmware_version $slot "alt"] + } + target_chassis_admin_sh_exit + # DEBUG + #log_message "push_slots: $push_slots" + #log_message "num_slots: $num_slots" + #log_message "card_types: $card_types" + #log_message "act_fw_versions: $act_fw_versions" + #log_message "pri_fw_versions: $pri_fw_versions" + #log_message "alt_fw_versions: $alt_fw_versions" + #log_message "is_mgmt: $is_mgmt" + + log_message "\nTest: Determining operations needed to upgrade to $fw_file for $chassis ..." + # now check that card types match and determine if we need to push firmware + set need_push "" + set need_select "" + set need_reboot "" + set have_card 0 + for { set i 0 } { $i < $num_slots } { incr i } { + set slot [lindex $push_slots $i] + if { ! [ string equal "$card_type" [lindex $card_types $i] ] } { + # if this happens card type is inconsistent with original + # query for slots of given card type (hot swap during update?) + # or user has explicitly specified slots and picked one of + # wrong card type + # quiety ignore this slot + lappend need_push 0 + lappend need_select 0 + lappend need_reboot 0 + log_message "Test: Skipping slot $slot: is of type [lindex $card_types $i], $fw_file is for $card_type" + continue + } + set have_card 1 + set in_pri [ string equal "$fw_version" [lindex $pri_fw_versions $i] ] + set in_alt [ string equal "$fw_version" [lindex $alt_fw_versions $i] ] + set booted [string equal "$fw_version" [lindex $act_fw_versions $i]] + if { ! $in_pri && ! $in_alt } { + # firmware is not in slot, need to push and possibly select/reboot + lappend need_push 1 + set s $select + log_message "Test: Will need to push firmware to slot $slot" + } else { + # firmware is in one of the images + #set push_all 0 + lappend need_push 0 + # only need to select if not already the primary image + set s [ expr $select && ! $in_pri] + log_message "Test: Do Not need to push firmware to slot $slot" + } + # could be running something not on chassis but matching pushed version + # only need to reboot if not the active image + set a [ expr $active && ! $booted] + lappend need_select $s + lappend need_reboot $a + if { $s && $a } { + log_message "Test: Need to select firmware and reboot slot $slot\n" + } elseif { $a } { + log_message "Test: Firmware already selected, Need to reboot slot $slot\n" + } elseif { $s } { + log_message "Test: Firmware already booted, but need to select firmware for slot $slot\n" + } else { + log_message "Test: No need to select firmware nor reboot slot $slot\n" + } + } + # only need do a step if applicable to at least 1 slot + set do_push [ expr [lsearch -exact $need_push 1] != -1 ] + set do_select [ expr [lsearch -exact $need_select 1] != -1 ] + set do_reboot [ expr [lsearch -exact $need_reboot 1] != -1 ] + + # DEBUG + #log_message "push_all: $push_all" + #log_message "do_push: $do_push" + #log_message "do_select: $do_select" + #log_message "do_reboot: $do_reboot" + #log_message "need_push: $need_push" + #log_message "need_select: $need_select" + #log_message "need_reboot: $need_reboot" + + if { ! ( $do_push || $do_select || $do_reboot ) } { + # we are done, everything is already the way we want it + if { $have_card } { + skip_case "No action required" + } else { + skip_case "No selected slots of type $card_type" + } + return 0 + } + + set fail 0 + set pushed 0 + set sftp_failures "" + set sftp_statuses "" + + if { $do_push && $push_all } { + # push to all applicable slots at once + log_message "Test: sftp $fw_file to all applicable slots\n" + sftp_chassis_firmware $chassis $fw_file $select "all" + # will check status of sftp operations for slots we care about below + log_message "\nTest: Verifying firmware was pushed to $chassis ...\n" + target_chassis_admin_sh $chassis + } + + for { set i 0 } { $i < $num_slots } { incr i } { + set slot [lindex $push_slots $i] + if { $do_push && ( $push_all || [lindex $need_push $i] ) } { + if { ! $push_all } { + # push one slot at a time + log_message "\nTest: sftp $fw_file to slot $slot\n" + sftp_chassis_firmware $chassis $fw_file $select $slot + target_chassis_admin_sh $chassis + } + # check status, must do immediately after sftp + set status [get_chassis_sftp_status $slot 1] + if { [ string equal "$status" "success" ] || [ string equal "$status" "skipped" ] } { + set pushed 1 + lappend sftp_failures 0 + lappend sftp_statuses "$status" + } else { + log_message "\nFAILURE: Failed to sftp firmware to chassis $chassis slot $slot\n" + set fail 1 + lappend sftp_failures 1 + lappend sftp_statuses "$status" + } + if { ! $push_all } { + target_chassis_admin_sh_exit + } + } else { + # we never sftp'ed to this slot + lappend sftp_failures 0 + lappend sftp_statuses "skipped" + } + } + # make sure we are logged in for operations below + if { ! ( $do_push && $push_all ) } { + target_chassis_admin_sh $chassis + } + + # DEBUG + #log_message "pushed: $pushed" + #log_message "sftp_statuses: $sftp_statuses" + #log_message "sftp_failures: $sftp_failures" + #log_message "fail: $fail" + + if { $pushed } { + # we pushed firmware to some or all of the requested slots + # now check firmware versions + + for { set i 0 } { $i < $num_slots } { incr i } { + set slot [lindex $push_slots $i] + if { [lindex $sftp_failures $i] } { + # it failed, no further checks necessary + continue + } + if { ! $push_all && ! [lindex $need_push $i] } { + # we never sftp'ed to this slot + continue + } + # if we get here, status was success or skipped + + # check what is in the slot after the sftp + set pri_fw_version [get_chassis_firmware_version $slot "pri"] + set alt_fw_version [get_chassis_firmware_version $slot "alt"] + set in_pri [ string equal "$fw_version" "$pri_fw_version" ] + set in_alt [ string equal "$fw_version" "$alt_fw_version" ] + if { $push_all && ! [lindex $need_push $i] } { + # sftp should have skipped this slot + if { ! [ string equal [lindex $sftp_statuses $i] "skipped" ] } { + set sftp_failures [lreplace $sftp_failures $i $i 1] + set fail 1 + log_message "\nFAILURE: Unexpected sftp transfer for chassis $chassis slot $slot\n" + } elseif { ! $in_pri && ! $in_alt } { + # the version disappeared + set sftp_failures [lreplace $sftp_failures $i $i 1] + set fail 1 + log_message "\nFAILURE: Unexpected removal of $fw_version for chassis $chassis slot $slot\n" + } elseif { $select && ! $in_pri } { + # the primary changed? + # we can recover + log_message "\nWARNING: Unexpected change of primary for chassis $chassis slot $slot\n" + set need_select [lreplace $need_select $i $i 1] + set do_select 1 + } + continue + } + + # if we get here, we needed to push to this slot + # hence the slot should not have been skipped + if { ! [ string equal [lindex $sftp_statuses $i] "success" ] } { + # it was skipped for no reason + set sftp_failures [lreplace $sftp_failures $i $i 1] + set fail 1 + log_message "\nFAILURE: Unexpected skip of sftp transfer for chassis $chassis slot $slot\n" + } elseif { ! $in_pri && ! $in_alt } { + # the version never appeared + set sftp_failures [lreplace $sftp_failures $i $i 1] + set fail 1 + log_message "\nFAILURE: $fw_version did not transfer to chassis $chassis slot $slot\n" + } elseif { $select && ! $in_pri } { + # the image is there but was not selected + # we can recover + log_message "\nWARNING: sftp transfered to wrong image for chassis $chassis slot $slot\n" + set need_select [lreplace $need_select $i $i 1] + set do_select 1 + } + } + } + + # DEBUG + #log_message "sftp_failures: $sftp_failures" + #log_message "do_select: $do_select" + #log_message "need_select: $need_select" + + if { $do_select } { + # now select the firmware as primary for the necessary slots + for { set i 0 } { $i < $num_slots } { incr i } { + if { [lindex $sftp_failures $i] } { + # it failed, no further ops necessary + continue + } + if { ! [lindex $need_select $i] } { + # does not need select + continue + } + set slot [lindex $push_slots $i] + select_chassis_firmware_version $slot $fw_version + } + } + + # if any of the above failed, do not activate or reboot it could + # make things worse + if { $fail } { + fail_test "Unable to sftp firmware to requested slots in $chassis" + } + + # DEBUG + #log_message "do_reboot: $do_reboot" + #log_message "need_reboot: $need_reboot" + #log_message "is_mgmt: $is_mgmt" + + # now activate the firmware for the necessary slots + if { $do_reboot} { + if { $is_mgmt } { + # we can't tell which slot is the active mgmt slot, so just reboot + # the whole chassis + if { $use_rebootall } { + chassis_cmd_reboot_all + } else { + send_chassis_cmd "reboot now" + expect_list 60 { "Goodbye" } + } + # may not be able to send logout command, so just get out of dodge + ignore_rest + + chassis_wait_reboot_done $chassis + return 0 + } else { + for { set i 0 } { $i < $num_slots } { incr i } { + if { [lindex $need_reboot $i] } { + set slot [lindex $push_slots $i] + chassis_cmd 60 0 "resetCard $slot now" + } + } + # TBD - is there a way to poll via CLI if card has finished reboot? + # allow 60 seconds for it to come fully on line + sleep 60 + } + } + + target_chassis_admin_sh_exit + + return 0 +} + +proc test_case_push_chassis_firmware { chassis fw_file fw_version card_type {action "push"} { slots "all" } } { +## +## test_case_push_chassis_firmware +## ------------------------- +## test case to push the given firmware file to the specified slots in the +## given chassis. +## +## Usage: +## test_case_push_chassis_firmware chassis fw_file fw_version card_type [action [slots]] +## Arguments: +## chassis - IP address/name of chassis to sftp and telnet to +## fw_file - local pathname of file to push +## fw_version - firmware version of fw_file +## card_type - card type of fw_file +## action - action after pushing firmware: +## push - do not reboot, do not change as primary +## is already primary, no change +## select - select as primary, but do not reboot +## run - select as primary and reboot to activate firmware +## slots - list of slot numbers to push to, default is "all" of given card type +## Returns: +## 0 -> success +## -code error on failure +## Additional Information: +## The global timeout is changed by this routine +## +## see push_chassis_firmware for error handling summary + + global env + + set base [exec basename $fw_file .pkg] + + test_case "$chassis.$base" "upgrade $chassis $base" "upgrade firmware on $chassis +selected slots: $slots +Firmware File: $fw_file +card type: $card_type +Firmware Version: $fw_version +Action: $action +File: TestTools/chassis.exp" noop noop { + upvar chassis chassis + upvar fw_file fw_file + upvar fw_version fw_version + upvar card_type card_type + upvar action action + upvar slots slots + + push_chassis_firmware "$chassis" "$fw_file" "$fw_version" "$card_type" "$action" "$slots" + } +} + +proc sftp_chassis_security_file { chassis sec_file } { +## +## sftp_chassis_security_file +## ------------------------- +## push the given FM security file to the specified chassis the +# given chassis. +## +## Usage: +## sftp_chassis_security_file chassis sec_file +## Arguments: +## chassis - IP address/name of chassis to sftp to +## sec_file - local pathname of file to push +## Returns: +## 0 -> success +## -code error on failure +## Additional Information: +## The global timeout is changed by this routine + global spawn_id expect_out spawn_out timeout + global expecting + + chassis_sftp_cmd "sftp admin@\\\[$chassis\\\]:" "put $sec_file /firmware" +} + +proc push_chassis_security_file { chassis sec_file {action "push"} { slots "all" } } { +## +## push_chassis_security_file +## ------------------------- +## push the given FM security file to the specified slots in the +## given chassis. +## +## Usage: +## push_chassis_security_file chassis sec_file [action [slots]] +## Arguments: +## chassis - IP address/name of chassis to sftp and telnet to +## sec_file - local pathname of file to push +## action - action after pushing FM security files: +## push - push, do not restart SM +## run - make sure FM running on master, not on slave +## runall - make sure FM running on master and slave +## restart - restart FM on master, make sure not running on slave +## restartall - restart FM on master and slave +## stop - stop FM on master and slave +## slots - list of slot numbers to push to, default is "all" to all +# management cards +## Returns: +## 0 -> success +## -code error on failure +## Additional Information: +## The global timeout is changed by this routine +## +## Any slots which are not of a management card, are quietly skipped. +## This allows multi-file push to work with a slot list. +## +## If the sftp fails for some slots but succeeds for others. The failed slots +## are logged and an exception will be thrown, however the good slots +## are processed to completion. + + global spawn_id expect_out spawn_out timeout + global expecting + + # variables: + # runstate: 0=no change, 1=running, 2=restart, -1=stop + if { "$action" == "push" } { + set push 1 + set master_runstate 0 + set slave_runstate 0 + } elseif { "$action" == "stop" } { + set push 0 + set master_runstate -1 + set slave_runstate -1 + } elseif { "$action" == "run" } { + set push 0 + set master_runstate 1 + set slave_runstate -1 + } elseif { "$action" == "runall" } { + set push 0 + set master_runstate 1 + set slave_runstate 1 + } elseif { "$action" == "restart" } { + set push 0 + set master_runstate 2 + set slave_runstate -1 + } elseif { "$action" == "restartall" } { + set push 0 + set master_runstate 2 + set slave_runstate 2 + } else { + fail_test "Invalid FM security file push action: $action" + } + + log_message "\nTest: Seeing if $chassis present running firmware supports FM security file push ...\n" + target_chassis_admin_sh $chassis + if { [ catch { set cap [check_chassis_capability "fwPush"] } res ] != 0 + || $cap < 1 } { + fail_test "Chassis $chassis present running firmware does not support push:\n$res" + } + + log_message "\nTest: Getting card type of management card from $chassis ...\n" + set my_slot [ get_this_slot_number ] + set mgmt_card_type [get_chassis_card_type $my_slot] + + log_message "\nTest: Getting Slot list from $chassis ...\n" + if { [string equal "$slots" "all"] } { + # push to all slots of matching card type + set push_slots [get_chassis_slots $mgmt_card_type] + set num_slots [llength $push_slots] + #set push_all 0 + set push_all 1 + } else { + # push to a specific set of slots + set push_slots "$slots" + set push_all 0 + } + set num_slots [llength $push_slots] + if { $num_slots == 0 } { + target_chassis_admin_sh_exit + skip_case "No management cards of type $mgmt_card_type" + return 0 + } + + log_message "\nTest: Getting present installed firmware from $chassis ...\n" + # first get present card types for each of the slots + set card_types "" + + foreach slot $push_slots { + lappend card_types [get_chassis_card_type $slot] + } + target_chassis_admin_sh_exit + + # DEBUG + #log_message "push_slots: $push_slots" + #log_message "num_slots: $num_slots" + #log_message "card_types: $card_types" + #log_message "mgmt_card_type: $mgmt_card_type" + #log_message "my_slot: $my_slot" + + log_message "\nTest: Determining operations needed to upgrade to $sec_file for $chassis ..." + # now check that card types match and determine if we need to push security file + set need_push "" + set have_card 0 + set mgmt_slot "" + set fm_running "" + + for { set i 0 } { $i < $num_slots } { incr i } { + set slot [lindex $push_slots $i] + if { ! [ string equal "$mgmt_card_type" [lindex $card_types $i] ] } { + # if this happens card type is inconsistent with original + # query for slots of given card type (hot swap during update?) + # or user has explicitly specified slots and picked one of + # wrong card type + # quiety ignore this slot + lappend need_push 0 + log_message "Test: Skipping slot $slot: is of type [lindex $card_types $i], $sec_file is for $mgmt_card_type" + continue + } + + # check whether the slot support running the ESM + if { [ string equal "$slot" "$my_slot" ] } { + target_chassis_admin_sh $chassis + } else { + target_chassis_admin_sh $chassis $slot + } + if { [ catch { set cap [check_chassis_capability "smConfig"] } res ] != 0 + || $cap < 1 } { + # slot will be skipped, doesn't support smConfig + lappend card_capabilities 0 + lappend fm_running 0 + } else { + lappend card_capabilities 1 + lappend fm_running [ is_esm_running ] + if { [ string equal "$mgmt_slot" ""] || [ string equal "$slot" "$my_slot" ] } { + set mgmt_slot "$slot" + } + } + if { [ string equal "$slot" "$my_slot" ] } { + target_chassis_admin_sh_exit + } else { + target_chassis_admin_sh_exit 1 + } + + set have_card 1 + # valid slot so push security file to this slot + lappend need_push $push + if { $push } { + log_message "Test: Will need to push FM security file to slot $slot" + } else { + log_message "Test: No need to push FM security files slot $slot\n" + } + } + + # only need do a step if applicable to at least 1 slot + set do_push [ expr [lsearch -exact $need_push 1] != -1 ] + + # DEBUG + #log_message "mgmt_slot: $mgmt_slot" + #log_message "card_capabilities: $card_capabilities" + #log_message "fm_running: $fm_running" + + if { [ string equal "$mgmt_slot" "" ] } { + skip_case "chassis does not have an ESM license key or does not support smConfig" + return 0 + } + + # DEBUG + #log_message "push_all: $push_all" + #log_message "do_push: $do_push" + #log_message "need_push: $need_push" + + set fail 0 + set pushed 0 + set sftp_failures "" + set sftp_statuses "" + set need_runstate "" + set do_runstate 0 + + for { set i 0 } { $i < $num_slots } { incr i } { + set slot [lindex $push_slots $i] + if { ! [lindex $card_capabilities $i] } { + # if this happens card is not capable of smConfig ignore this slot + lappend need_runstate 0 + log_message "Test: Skipping slot $slot: does not support smConfig" + continue + } + set running [ lindex $fm_running $i] + if { ! [ string equal "$slot" "$my_slot" ] } { + # slave MM + if { ( $slave_runstate < 0 && $running ) + || ($slave_runstate == 1 && ! $running ) + || $slave_runstate == 2 } { + lappend need_runstate $slave_runstate + set do_runstate 1 + log_message "Test: Need to change runstate for FM in slot $slot" + } else { + lappend need_runstate 0 + log_message "Test: No need to change runstate for FM in slot $slot" + } + } else { + # master MM + if { ( $master_runstate < 0 && $running ) + || ($master_runstate == 1 && ! $running ) + || $master_runstate == 2 } { + lappend need_runstate $master_runstate + set do_runstate 1 + log_message "Test: Need to change runstate for FM in slot $slot" + } else { + lappend need_runstate 0 + log_message "Test: No need to change runstate for FM in slot $slot" + } + } + + if { $do_push && ( $push_all || [lindex $need_push $i] ) } { + # push one slot at a time + log_message "\nTest: sftp $sec_file to slot $slot\n" + sftp_chassis_security_file $chassis $sec_file + target_chassis_admin_sh $chassis + + # check status, must do immediately after sftp + set status [get_chassis_sftp_status $slot 1] + if { [ string equal "$status" "success" ] || [ string equal "$status" "skipped" ] } { + set pushed 1 + lappend sftp_failures 0 + lappend sftp_statuses "$status" + } else { + log_message "\nFAILURE: Failed to sftp FM security file to chassis $chassis slot $slot\n" + set fail 1 + lappend sftp_failures 1 + lappend sftp_statuses "$status" + } + if { ! $push_all } { + target_chassis_admin_sh_exit + } + } else { + # we never sftp'ed to this slot + lappend sftp_failures 0 + lappend sftp_statuses "skipped" + } + } + + # make sure we are logged in for operations below + if { ! ( $do_push && $push_all ) } { + target_chassis_admin_sh $chassis + } + + # DEBUG + #log_message "pushed: $pushed" + #log_message "sftp_statuses: $sftp_statuses" + #log_message "sftp_failures: $sftp_failures" + #log_message "fail: $fail" + + if { $fail } { + fail_test "Unable to sftp FM security file to requested slots in $chassis" + } + + # DEBUG + #log_message "do_runstate: $do_runstate" + #log_message "need_runstate: $need_runstate" + + if { $do_runstate} { + for { set i 0 } { $i < $num_slots } { incr i } { + set slot [lindex $push_slots $i] + set new_runstate [lindex $need_runstate $i] + if { $new_runstate != 0 } { + if { [ string equal "$slot" "$my_slot" ] } { + target_chassis_admin_sh $chassis + } else { + target_chassis_admin_sh $chassis $slot + } + if { $new_runstate > 0 } { + # easier to restart, will start if not already running + chassis_cmd 60 0 "smControl restart" + # don't wait, it would risk having mismatched esm configs + } elseif { $new_runstate < 0 } { + chassis_cmd 60 0 "smControl stop" + } + if { [ string equal "$slot" "$my_slot" ] } { + target_chassis_admin_sh_exit + } else { + target_chassis_admin_sh_exit 1 + } + } + } + } + + if { ! ( $do_push || $do_runstate ) } { + # we are done, everything is already the way we want it + if { $have_card } { + skip_case "No action required" + } else { + skip_case "No selected slots of type $mgmt_card_type" + } + return 0 + } + + return 0 +} + +proc test_case_push_chassis_security_file { chassis sec_file {action "push"} { slots "all" } } { +## +## test_case_push_chassis_security_file +## ------------------------- +## test case to push the given FM security file to the specified slots in the +## given chassis. +## +## Usage: +## test_case_push_chassis_security_file chassis sec_file [action [slots]] +## Arguments: +## chassis - IP address/name of chassis to sftp and telnet to +## sec_file - local pathname of file to push +## action - action after pushing firmware: +## push - do not reboot, do not change as primary +## is already primary, no change +## slots - list of slot numbers to push to, default is "all" of given card type +## Returns: +## 0 -> success +## -code error on failure +## Additional Information: +## The global timeout is changed by this routine +## +## see push_chassis_security_file for error handling summary + + global env + + set base [exec basename $sec_file .pem] + + test_case "$chassis.$base" "upgrade $chassis $base" "upgrade FM security file on $chassis +Selected slots: $slots +Security File: $sec_file +Action: $action +File: TestTools/chassis.exp" noop noop { + upvar chassis chassis + upvar sec_file sec_file + upvar action action + upvar slots slots + + push_chassis_security_file "$chassis" "$sec_file" "$action" "$slots" + } +} + +proc test_case_chassis_configure { chassis chassisIP} { + + global tools_case_status + + test_case "$chassis.emb.configure" "Chassis $chassis configure" "Configure $chassis +File: TestOnly/chassis.exp" case_setup case_cleanup { + upvar chassis chassis + upvar chassisIP chassisIP + global env + + set syslogServer $env(SYSLOG_SERVER) + set syslogPort $env(SYSLOG_PORT) + set syslogFacility $env(SYSLOG_FACILITY) + set ntpServer $env(NTP_SERVER) + set tzOffset $env(TZ_OFFSET) + set dstStart $env(DST_START) + set dstEnd $env(DST_END) + set linkWidthSelection $env(LINKWIDTH_SETTING) + set setname $env(SET_NAME) + set linkCRCMode $env(LINKCRCMODE) + + target_chassis_admin_sh $chassis + + set chassis_cmd_string "logSyslogConfig" + set setSyslog 0 + if { [string equal "$syslogServer" "0.0.0.0"] == 0 } { + append chassis_cmd_string " -h $syslogServer" + set setSyslog 1 + } + if { [string equal "$syslogPort" "-1"] == 0 } { + append chassis_cmd_string " -p $syslogPort" + set setSyslog 1 + } + if { [string equal "$syslogFacility" "-1"] == 0 } { + append chassis_cmd_string " -f $syslogFacility" + set setSyslog 1 + } + if { $setSyslog } { + send_chassis_cmd $chassis_cmd_string + expect_progress 60 {[\r\n]} { "Successfully" "facility" } { "Invalid" "usage" } + check_chassis_exit_status 60 0 + } + + if { [string equal "$ntpServer" "0.0.0.0"] == 0 } { + send_chassis_cmd "time -S $ntpServer" + expect_progress 60 {[\r\n]} { "Configured" "NTP" } { "not" "valid" } + check_chassis_exit_status 60 0 + } + + if { [string equal "$tzOffset" "100"] == 0 } { + send_chassis_cmd "timeZoneConf $tzOffset" + expect_progress 60 {[\r\n]} { "successfully" "configured" } { "invalid" "not found" } + check_chassis_exit_status 60 0 + } + + if { [string equal "$dstStart" "0 0 0"] == 0 } { + send_chassis_cmd "timeDstConf $dstStart $dstEnd" + expect_progress 60 {[\r\n]} { "Timezone" "DST" } { "bounds" "not found" } + check_chassis_exit_status 60 0 + } + + if { [string equal "$linkWidthSelection" "0"] == 0 } { + send_chassis_cmd "ismChassisSetWidth $linkWidthSelection" + send_chassis_cmd "showLastRetCode" + set out [expect_list 60 { "Last Exit Code: [0-9]+" } { "Error" }] + regexp {([0-9]+)} $out ret + if { ! [ string equal "$ret" "0"] } { + if { [ string equal "$ret" "5"] } { + skip_case "\n$chassis: Skipped changing chassis link width: ismChassisSetWidth command not supported" + } else { + fail_test "\n$chassis: Failed changing chassis link width: ismChassisSetWidth command failed with return code $ret" + } + } + } + + if { [string equal "$chassisIP" "0.0.0.0"] == 0 } { + send_chassis_cmd "setChassisIpAddr -h $chassisIP" + expect_progress 60 {[\r\n]} { "reconnect" "updated" } { "valid" "usage" } + check_chassis_exit_status 60 0 + } + + # $setname is y or n + if { [string equal "$setname" "y"] } { + send_chassis_cmd "setNodeDesc \"$chassis\"" + expect_progress 60 {[\r\n]} { "success" "changed" } { "usage:" "not found" } + check_chassis_exit_status 60 0 + } + + if { [string equal "$linkCRCMode" "-1" ] == 0 } { + send_chassis_cmd "ismChassisSetCrcMode $linkCRCMode" + send_chassis_cmd "showLastRetCode" + set out [expect_list 60 { "Last Exit Code: [0-9]+" } { "Error" }] + regexp {([0-9]+)} $out ret + if { ! [ string equal "$ret" "0"] } { + if { [ string equal "$ret" "5" ] } { + skip_case "\n$chassis: Skipped changing chassis link CRC mode: ismChassisSetCrcMode command not supported" + } else { + fail_test "\n$chassis: Failed changing chassis link CRC mode: ismChassisSetCrcMode command failed with return code $ret" + } + } + check_chassis_exit_status 60 0 + } + + target_chassis_admin_sh_exit + } +} + +proc check_esm_config { config_file } { +## +## check_esm_config +## ------------------------- +## check the syntax of the given esm config file +## +## Usage: +## check_esm_config config_file +## Arguments: +## config_file - local pathname of file +## Returns: +## -code error on failure +## Additional Information: +## The global timeout is changed by this routine + + global env + + if { [ file exists "/usr/lib/opa/fm_tools/config_check" ] } { + set env(IFS_FM_BASE) "" + set tooldir "/usr/lib/opa/fm_tools" + } else { + set env(IFS_FM_BASE) "/usr/lib/opa-fm" + set tooldir "$env(IFS_FM_BASE)/bin" + } + log_message "IFS_FM_BASE=$env(IFS_FM_BASE)" + log_message "tooldir=$tooldir" + log_message "" + if { [ file exists "$tooldir/config_check" ] } { + log_message "$tooldir/config_check -c $config_file" + if { [ catch { exec "$tooldir/config_check" -c "$config_file" } err_str ] != 0 } { + puts "$tooldir/config_check -c $config_file" + show_message "$err_str" + error "$tooldir/config_check -c $config_file: failed: $err_str" + } + } else { + skip_case "Unable to pre-check config file, Intel OPA FM not installed on this server" + } + return 0 +} + +proc sftp_esm_config { chassis config_file } { +## +## sftp_esm_config +## ------------------------- +## push the given SM config file to the specified chassis +## +## Usage: +## sftp_esm_config chassis config_file +## Arguments: +## chassis - IP address/name of chassis to scp and telnet to +## config_file - local pathname of file to push +## Returns: +## 0 -> success +## -code error on failure +## Additional Information: +## The global timeout is changed by this routine + + global spawn_id expect_out spawn_out timeout + global expecting + + chassis_sftp_cmd "sftp admin@\\\[$chassis\\\]:" "put $config_file /firmware/opafm.xml" + + return 0 +} + +proc get_esm_config { chassis config_file } { +## +## get_esm_config +## ------------------------- +## get esm config file from the chassis +## +## Usage: +## get_esm_config config_file +## Arguments: +## chassis - IP address/name of chassis to scp and telnet to +## config_file - local pathname of file to get to +## Returns: +## 1 - match, 0 - no match +## -code error on failure +## Additional Information: +## The global timeout is changed by this routine + + global spawn_id expect_out spawn_out timeout + global expecting + + chassis_sftp_cmd "sftp admin@\\\[$chassis\\\]:" "get /firmware/opafm.xml $config_file" 0 + + return 0 +} + +proc compare_esm_config { chassis config_file mgmt_card_type } { +## +## compare_esm_config +## ------------------------- +## return if the config_file matches esm config in the chassis +## +## Usage: +## compare_esm_config chassis config_file +## Arguments: +## chassis - IP address/name of chassis to scp and telnet to +## config_file - local pathname of file to push +## mgmt_card_type - Name of management card type +## Returns: +## 1 - match, 0 - no match +## -code error on failure +## Additional Information: +## The global timeout is changed by this routine + + global spawn_id expect_out spawn_out timeout + global expecting + global test_tmp + + log_message "\nComparing $config_file to FM config...\n" + set temp_file "$test_tmp/get_opafm.xml" + get_esm_config "$chassis" "$test_tmp/get_opafm.xml" + if { [catch { run_cmd "exec cmp -s $config_file $temp_file"} ] == 0 } { + # match + log_message "Test: Matches\n" + return 1 + } else { + log_message "Test: Does not Match\n" + return 0 + } +} + +proc is_esm_running { } { +## +## is_esm_running +## ------------------------- +## check the esm status for the current slot in the current chassis +## +## Usage: +## is_esm_running +## Arguments: +## Returns: +## esm status +## -code error on failure +## Additional Information: +## The global timeout is changed by this routine + + # DONE + global spawn_id expect_out spawn_out timeout + global expecting + + send_chassis_cmd "smControl status" + # require trailing whitespace to anchor end of string + set out [expect_list 60 "{Subnet manager is \[a-zA-Z0-9_ -\]+\\\.}" { "usage" "Invalid" "Error" "Failed" "roblem" "not found"} ] + set ret "" + regexp {is ([a-zA-Z0-9_ -]+)\.} $out line ret + + expect_chassis_prompt 60 + + return [ string equal "$ret" "running"] +} + +proc chassis_get_sm_boot_options { } { +## +## chassis_get_sm_boot_options +## ------------------------- +## return SM boot options +## +## Usage: +## chassis_get_sm_boot_options +## Arguments: +## Returns: +## { startAtBoot startOnSlaveCmu } +## -code error on failure +## Additional Information: +## The global timeout is changed by this routine + + global spawn_id expect_out spawn_out timeout + global expecting + + send_chassis_cmd "smConfig query" + # the [:space:] bounds the + so we get all the data on the line + set out1 [expect_list 60 "{startAtBoot: \[0-9A-Za-z\]+\[\[:space:\]\]}" { "usage" "Invalid" "Error" "Failed" "roblem" "not found"} ] + set out2 [expect_list 60 "{startOnSlaveCmu: \[0-9A-Za-z/\]+\[\[:space:\]\]}" { "usage" "Invalid" "Error" "Failed" "roblem" "not found"} ] + check_chassis_exit_status 60 0 + #log_message "out1=$out1" + #log_message "out2=$out2" + + set ret1 "" + set ret2 "" + # throw away the \r\n, there may be trailing spaces, TCL lists will ignore + regexp {startAtBoot: ([A-Za-z0-9]+)[[:space:]]} $out1 line ret1 + regexp {startOnSlaveCmu: ([A-Za-z0-9/]+)[[:space:]]} $out2 line ret2 + + return "$ret1 $ret2" +} + +proc push_esm_config { chassis config_file {action "push"} {bootstate ""} } { +## +## push_esm_config +## ------------------------- +## push the given ESM config file to all the applicable slots in the +## given chassis. +## +## Usage: +## push_esm_config chassis config_file [action [bootstate]] +## Arguments: +## chassis - IP address/name of chassis to scp and telnet to +## config_file - local pathname of file to push +## if "", no file push will occur +## action - action after pushing config_file: +## push - push, do not restart SM +## select - same as push +## run - make sure FM running on master, not on slave +## runall - make sure FM running on master and slave +## restart - restart FM on master, make sure not running on slave +## restartall - restart FM on master and slave +## stop - stop FM on master and slave +## bootstate - optional selection for FM bootstate +## "" - no change to FM start at boot options +## disable - disable FM start on all MM on boot +## enable - enable FM start on master MM on boot, disable on slave MM +## enableall - enable FM start on all MM on boot +## Returns: +## 0 -> success +## -code error on failure +## Additional Information: +## The global timeout is changed by this routine +## +## If the scp fails for some slots but succeeds for others. The failed slots +## are logged and an exception will be thrown, however the good slots +## are processed to completion [except for the restart] (if possible) +## so that they are not left in an odd state + + global spawn_id expect_out spawn_out timeout + global expecting + + # variables: + # restart_only - no push, just restart FM + set restart_only [string equal "$config_file" ""] + + # runstate: 0=no change, 1=running, 2=restart, -1=stop + if { "$action" == "push" || "$action" == "select" } { + set master_runstate 0 + set slave_runstate 0 + } elseif { "$action" == "stop" } { + set master_runstate -1 + set slave_runstate -1 + } elseif { "$action" == "run" } { + set master_runstate 1 + set slave_runstate -1 + } elseif { "$action" == "runall" } { + set master_runstate 1 + set slave_runstate 1 + } elseif { "$action" == "restart" } { + set master_runstate 2 + set slave_runstate -1 + } elseif { "$action" == "restartall" } { + set master_runstate 2 + set slave_runstate 2 + } else { + fail_test "Invalid FM config file action: $action" + } + if { "$bootstate" != "" && "$bootstate" != "disable" + && "$bootstate" != "enable" && "$bootstate" != "enableall" } { + fail_test "Invalid FM config bootstate: $bootstate" + } + + # DEBUG + #log_message "action: $action" + #log_message "restart_only: $restart_only" + #log_message "bootstate: $bootstate" + + target_chassis_admin_sh $chassis + # check if chassis supports slaveCli, if not then skip chassis, older FW + if { [ catch { set cap [check_chassis_capability "slaveCli"] } res ] != 0 + || $cap < 1 } { + skip_case "chassis does not support FM config via FastFabric" + } + + log_message "\nTest: Getting Slot list from $chassis ...\n" + set my_slot [ get_this_slot_number ] + # get management card type for this chassis model + set mgmt_card_type [ get_chassis_card_type $my_slot ] + # all slots of matching card type (eg. all management cards) + set mgmt_slots [get_chassis_slots $mgmt_card_type] + set num_slots [llength $mgmt_slots] + if { $num_slots == 0 } { + # this should not happen, we should at least find card 0 + target_chassis_admin_sh_exit + fail_test "No cards of type $mgmt_card_type" + } + # lets be paranoid + if { ! [ string equal [get_chassis_card_type $my_slot] "$mgmt_card_type" ] } { + target_chassis_admin_sh_exit + fail_test "IP address given is not for chassis mgmt card $mgmt_card_type" + } + target_chassis_admin_sh_exit + + log_message "\nTest: Checking FM capabilities and status of $chassis ...\n" + # flag per slot indicating if slot has smConfig capability + # may not have smConfig on all cards, esp if ESM license key lacking + set card_capabilities "" + # flag per slot indicating if slot has FM currently running + set fm_running "" + # slot which supports sm CLI. Prefer active mgmt card otherwise its + # secondary mgmt card + set mgmt_slot "" + # see if any slots in chassis support smConfig, if so check FM status + foreach slot $mgmt_slots { + if { [ string equal "$slot" "$my_slot" ] } { + target_chassis_admin_sh $chassis + } else { + target_chassis_admin_sh $chassis $slot + } + if { [ catch { set cap [check_chassis_capability "smConfig"] } res ] != 0 + || $cap < 1 } { + # slot will be skipped, doesn't support smConfig + lappend card_capabilities 0 + lappend fm_running 0 + } else { + lappend card_capabilities 1 + lappend fm_running [ is_esm_running ] + if { [ string equal "$mgmt_slot" ""] || [ string equal "$slot" "$my_slot" ] } { + set mgmt_slot "$slot" + } + } + if { [ string equal "$slot" "$my_slot" ] } { + target_chassis_admin_sh_exit + } else { + target_chassis_admin_sh_exit 1 + } + } + + # DEBUG + #log_message "mgmt_slots: $mgmt_slots" + #log_message "mgmt_slot: $mgmt_slot" + #log_message "num_slots: $num_slots" + #log_message "card_capabilities: $card_capabilities" + #log_message "fm_running: $fm_running" + + if { [ string equal "$mgmt_slot" "" ] } { + skip_case "chassis does not have an ESM license key or does not support smConfig" + } + + set do_push 0 + if { ! $restart_only } { + log_message "\nTest: Checking FM config in $chassis ...\n" + # we trust that secondary management cards will be synced with primary + # so only need to upload this once + set config_matches [compare_esm_config $chassis $config_file $mgmt_card_type ] + + # DEBUG + #log_message "config_matches: $config_matches" + + log_message "\nTest: Determining operations needed to update to $config_file for $chassis ..." + ## now check that card is capable and determine if we need to push config + + if { ! $config_matches } { + # config is not in chassis, need to push and possibly restart + set do_push 1 + log_message "Test: Will need to push config to chassis" + } else { + # config is in chassis, can skip push + set do_push 0 + log_message "Test: No need to push config to chassis" + } + } + + # we are assuming we can trust that primary mgmt card's config files + # match those of secondary. So FM runstate is only card specific aspect. + set need_runstate "" + set do_runstate 0 + for { set i 0 } { $i < $num_slots } { incr i } { + set slot [lindex $mgmt_slots $i] + if { ! [lindex $card_capabilities $i] } { + # if this happens card is not capable of smConfig ignore this slot + lappend need_runstate 0 + log_message "Test: Skipping slot $slot: does not support smConfig" + continue + } + set running [ lindex $fm_running $i] + if { ! [ string equal "$slot" "$my_slot" ] } { + # slave MM + if { ( $slave_runstate < 0 && $running ) + || ($slave_runstate == 1 && ! $running ) + || $slave_runstate == 2 } { + lappend need_runstate $slave_runstate + set do_runstate 1 + log_message "Test: Need to change runstate for FM in slot $slot" + } else { + lappend need_runstate 0 + log_message "Test: No need to change runstate for FM in slot $slot" + } + } else { + # master MM + if { ( $master_runstate < 0 && $running ) + || ($master_runstate == 1 && ! $running ) + || $master_runstate == 2 } { + lappend need_runstate $master_runstate + set do_runstate 1 + log_message "Test: Need to change runstate for FM in slot $slot" + } else { + lappend need_runstate 0 + log_message "Test: No need to change runstate for FM in slot $slot" + } + } + } + log_message "\n" + + # DEBUG + #log_message "do_push: $do_push" + #log_message "do_runstate: $do_runstate" + #log_message "need_runstate: $need_runstate" + + if { $do_push } { + set fail 0 + set scp_statuses "" + + # push is done once to chassis and automatically synced to all + # mgmt cards + log_message "Test: sftp $config_file to all applicable slots\n" + sftp_esm_config $chassis $config_file + + # will check status of scp operations for slots we care about below + log_message "\nTest: Verifying config was pushed to $chassis ...\n" + target_chassis_admin_sh $chassis + + # check status, must do immediately after scp for each slot + for { set i 0 } { $i < $num_slots } { incr i } { + set slot [lindex $mgmt_slots $i] + # do not expect "skipped" status + set status [get_chassis_sftp_status $slot 1] + if { [ string equal "$status" "success" ] } { + lappend scp_statuses "$status" + } else { + log_message "\nFAILURE: Failed to scp config to chassis $chassis slot $slot\n" + set fail 1 + lappend scp_statuses "$status" + } + } + + target_chassis_admin_sh_exit + + # DEBUG + #log_message "scp_statuses: $scp_statuses" + #log_message "fail: $fail" + + if { ! $fail } { + # we trust that secondary management cards will be synced with + # primary so only need to upload this once + if { ! [compare_esm_config $chassis $config_file $mgmt_card_type ] } { + # the config disappeared + set fail 1 + log_message "\nFAILURE: Unexpected mismatch of config for chassis $chassis slot $slot\n" + } + } + + # if any of the above failed, do not change runstate it could make things worse + if { $fail } { + fail_test "Unable to scp config to required slots in $chassis" + } + } + + # DEBUG + #log_message "do_runstate: $do_runstate" + #log_message "need_runstate: $need_runstate" + + if { $do_runstate} { + for { set i 0 } { $i < $num_slots } { incr i } { + set slot [lindex $mgmt_slots $i] + set new_runstate [lindex $need_runstate $i] + if { $new_runstate != 0 } { + if { [ string equal "$slot" "$my_slot" ] } { + target_chassis_admin_sh $chassis + } else { + target_chassis_admin_sh $chassis $slot + } + if { $new_runstate > 0 } { + # easier to restart, will start if not already running + chassis_cmd 60 0 "smControl restart" + # don't wait, it would risk having mismatched esm configs + } elseif { $new_runstate < 0 } { + chassis_cmd 60 0 "smControl stop" + } + if { [ string equal "$slot" "$my_slot" ] } { + target_chassis_admin_sh_exit + } else { + target_chassis_admin_sh_exit 1 + } + } + } + } + + # adjust start at boot options + set do_boot 0 + if { "$bootstate" != "" } { + if { ! [ string equal "$mgmt_slot" "$my_slot" ] } { + fail_test "Master MM does not have SM license key, unable to configure start options in $chassis" + } + log_message "\nTest: Checking FM Start At Boot Options for $chassis ...\n" + target_chassis_admin_sh $chassis + # get present options to old_startAtBootArg and old_startOnSlaveCmuArg + set boot_options [ chassis_get_sm_boot_options ] + set old_startAtBootArg [lindex $boot_options 0 ] + set old_startOnSlaveCmuArg [lindex $boot_options 1 ] + + # determine desired settings + if { "$bootstate" == "disable" } { + set startAtBootArg "no" + set startOnSlaveCmuArg "no" + } elseif { "$bootstate" == "enable" } { + set startAtBootArg "yes" + set startOnSlaveCmuArg "no" + } elseif { "$bootstate" == "enableall" } { + set startAtBootArg "yes" + set startOnSlaveCmuArg "yes" + } + # do what is needed + set arg1 "" + set arg2 "" + if { "$startAtBootArg" != "$old_startAtBootArg" } { + set arg1 "startAtBoot $startAtBootArg" + } + if { "$startOnSlaveCmuArg" != "$old_startOnSlaveCmuArg" + && "$old_startOnSlaveCmuArg" != "N/A" } { + set arg2 "startOnSlaveCmu $startOnSlaveCmuArg" + } + if { "$arg1" != "" || "$arg2" != "" } { + log_message "\nTest: Changing FM Start At Boot Options for $chassis ...\n" + chassis_cmd 60 0 "smConfig $arg1 $arg2" + set do_boot 1 + } else { + log_message "\nTest: No Change to FM Start At Boot Options for $chassis ...\n" + } + target_chassis_admin_sh_exit + } + + if { ! $do_push && ! $do_runstate && ! $do_boot } { + # we are done, everything is already the way we want it + # report skip so user knows we didn't change anything on this chassis + skip_case "No action required" + return 0 + } + + return 0 +} + +proc test_case_push_esm_config { chassis config_file {action "push"} {bootstate ""} } { +## +## test_case_push_esm_config +## ------------------------- +## test case to push the given config file to all applicable slots in +## the given chassis. +## +## Usage: +## test_case_push_esm_config chassis config_file [action [bootstate]] +## Arguments: +## chassis - IP address/name of chassis to scp and telnet to +## config_file - local pathname of file to push +## action - action after pushing firmware: +## push - push, do not restart SM +## select - same as push +## run - restart FM on master, make sure not running on slave +## runall - restart FM on master and slave +## stop - stop FM on master and slave +## bootstate - optional selection for FM bootstate +## "" - no change to FM start at boot options +## disable - disable FM start on all MM on boot +## enable - enable FM start on master MM on boot, disable on slave MM +## enableall - enable FM start on all MM on boot +## Returns: +## 0 -> success +## -code error on failure +## Additional Information: +## The global timeout is changed by this routine +## +## see push_esm_config for error handling summary + + global env + + test_case "$chassis.fmconfig" "update $chassis $config_file" "update FM config file on $chassis +Config File: $config_file +Action: $action +BootState: $bootstate +File: TestTools/chassis.exp" noop noop { + upvar chassis chassis + upvar config_file config_file + upvar action action + upvar bootstate bootstate + + # translate action, when pushing config file we want to use restart + # so that the new file ends up "running" + if { "$action" == "run" } { + set action "restart" + } elseif { "$action" == "runall" } { + set action "restartall" + } + + push_esm_config "$chassis" "$config_file" "$action" "$bootstate" + } +} + +proc test_case_get_esm_config { chassis config_file } { +## +## test_case_get_esm_config +## ------------------------- +## test case to get the given config file from the given chassis. +## +## Usage: +## test_case_get_esm_config chassis config_file +## Arguments: +## chassis - IP address/name of chassis to scp and telnet to +## config_file - local pathname of file to fetch to +## Returns: +## 0 -> success +## -code error on failure +## Additional Information: +## The global timeout is changed by this routine +## +## see push_esm_config for error handling summary + + global env + + test_case "$chassis.fm_get_config" "get $chassis $config_file" "get FM config file from $chassis +To Config File: $config_file +File: TestTools/chassis.exp" noop noop { + upvar chassis chassis + upvar config_file config_file + upvar action action + + # check if chassis supports slaveCli, if not then skip chassis, older FW + target_chassis_admin_sh $chassis + if { [ catch { set cap [check_chassis_capability "slaveCli"] } res ] != 0 + || $cap < 1 } { + skip_case "chassis does not support FM config via FastFabric" + } + + # TBD - make this common code with fmconfig + log_message "\nTest: Getting Slot list from $chassis ...\n" + set my_slot [ get_this_slot_number ] + # get management card type for this chassis model + set mgmt_card_type [ get_chassis_card_type $my_slot] + # all slots of matching card type (eg. all management cards) + set mgmt_slots [get_chassis_slots $mgmt_card_type] + set num_slots [llength $mgmt_slots] + if { $num_slots == 0 } { + # this should not happen, we should at least find card 0 + target_chassis_admin_sh_exit + fail_test "No cards of type $mgmt_card_type" + } + # lets be paranoid + if { ! [ string equal [get_chassis_card_type $my_slot] "$mgmt_card_type" ] } { + target_chassis_admin_sh_exit + fail_test "IP address given is not for chassis mgmt card $mgmt_card_type" + } + target_chassis_admin_sh_exit + + log_message "\nTest: Checking FM capabilities and status of $chassis ...\n" + # slot which supports sm CLI. Prefer active mgmt card otherwise its + # secondary mgmt card + set mgmt_slot "" + # see if any slots in chassis support smConfig + foreach slot $mgmt_slots { + if { [ string equal "$slot" "$my_slot" ] } { + target_chassis_admin_sh $chassis + } else { + target_chassis_admin_sh $chassis $slot + } + if { [ catch { set cap [check_chassis_capability "smConfig"] } res ] != 0 + || $cap < 1 } { + # slot will be skipped, doesn't support smConfig + } else { + if { [ string equal "$mgmt_slot" ""] || [ string equal "$slot" "$my_slot" ] } { + set mgmt_slot "$slot" + } + } + if { [ string equal "$slot" "$my_slot" ] } { + target_chassis_admin_sh_exit + } else { + target_chassis_admin_sh_exit 1 + } + } + + if { [ string equal "$mgmt_slot" "" ] } { + skip_case "chassis does not have an ESM license key or does not support smConfig" + } + + log_message "mkdir -p [exec dirname $config_file]" + exec mkdir -p "[exec dirname $config_file]" + get_esm_config "$chassis" "$config_file" + } +} + + +proc test_case_chassis_getconfig { chassis {fd ""}} { +## +## test_case_chassis_getconfig +## ------------------------- +## test case to get basic config from the given chassis. +## +## Usage: +## test_case_chassis_getconfig chassis [fd] +## Arguments: +## chassis - IP address/name of chassis to scp and telnet to +## fd - file to write config info to +## Returns: +## 0 -> success +## -code error on failure +## Additional Information: +## The global timeout is changed by this routine +## + + global env + + test_case "$chassis.getconfig" "get $chassis" "get basic configuration from $chassis +File: TestTools/chassis.exp" noop noop { + upvar chassis chassis + upvar fd fd + set ntpVal "" + set sysLogVal "" + set timeZone "" + set out "" + set linkWidth "" + set nodeDesc "" + set act_fw_version "" + set pri_fw_version "" + set linkCRCmode "" + + # check if chassis supports slaveCli, if not then skip chassis, older FW + target_chassis_admin_sh $chassis + # slot 0 is alias for mgmt card in all chassis models + set my_slot [ get_this_slot_number ] + set act_fw_version [get_chassis_firmware_version $my_slot "act"] + set pri_fw_version [get_chassis_firmware_version $my_slot "pri"] + send_chassis_cmd "time" + set out [expect_list 240 { "[Cc]onfigured.+\n" } { "Usage" "Invalid" "Error" "Failed" "roblem" "not found"} ] + regexp {([A-Za-z0-9:. ]+)} $out tmp ntpVal + expect_chassis_prompt 60 + send_chassis_cmd "logSyslogConfig" + set out [expect_list 240 { "logSyslogConfig" "[Ss]yslog.+\n" } { "Usage" "Invalid" "Error" "Failed" "roblem" "not found"} ] + regexp {([A-Za-z0-9:. ]+)} $out tmp sysLogVal + expect_chassis_prompt 60 + send_chassis_cmd "timeZoneConf" + set out [expect_list 240 { "timeZoneConf" ".+[tT]ime.+\n" } { "Usage" "Invalid" "Error" "Failed" "roblem" "not found"} ] + regexp {([-A-Za-z0-9:. ]+)} $out tmp timeZone + expect_chassis_prompt 60 + send_chassis_cmd "ismChassisSetWidth" + set out [expect_list 240 { "ismChassisSetWidth" "link width supported: [^\r\n]*[\r\n]" } { "Usage" "Invalid" "Error" "Failed" "roblem" "not found"} ] + # "4X" or "4X/8X" or "UNKNOWN" or similar + regexp {supported: ([^\r\n]+)[\r\n]} $out tmp linkWidth + expect_chassis_prompt 60 + send_chassis_cmd "showNodeDesc" + set out [expect_list 240 { "showNodeDesc" "Node" "\(SMA\)" "Description.+[\r\n]" } { "Usage" "Invalid" "Error" "Failed" "roblem" "not found"} ] + regexp {.+= (.+)[\r\n]} $out tmp nodeDesc + expect_chassis_prompt 60 + send_chassis_cmd "ismChassisSetCrcMode" + set out [expect_list 240 { "ismChassisSetCrcMode" "CRC_MODE: [^\r\n]*[\r\n]" } { "Usage" "Invalid" "Error" "Failed" "roblem" "not found" } ] + regexp {CRC_MODE: ([^\r\n]+)[\r\n]} $out tmp linkCRCmode + expect_chassis_prompt 60 + set out " + Firmware Active : $act_fw_version + Firmware Primary : $pri_fw_version + Syslog Configuration : $sysLogVal + NTP : $ntpVal + Time Zone : $timeZone + LinkWidth Support : $linkWidth + Node Description : $nodeDesc + Link CRC Mode : $linkCRCmode" + show_message "\n$chassis:$out" + if { ! [ string equal "$fd" "" ] } { + puts $fd "$out" + } + target_chassis_admin_sh_exit + } +} + +proc get_esm_security_files { chassis security_files dest_dir } { +## +## get_esm_security_files +## ------------------------- +## get esm security files from the chassis +## +## Usage: +## get_esm_security security_files +## Arguments: +## chassis - IP address/name of chassis to scp and telnet to +## security_files - local pathname of file to get to +## Returns: +## 1 - match, 0 - no match +## -code error on failure +## Additional Information: +## The global timeout is changed by this routine + + global spawn_id expect_out spawn_out timeout + global expecting + + chassis_sftp_cmd "sftp admin@\\\[$chassis\\\]:" "get /firmware/$security_files $dest_dir" 0 + + return 0 +} + +proc test_case_get_esm_security_files { chassis security_files dest_dir } { +## +## test_case_get_esm_security_file +## ------------------------- +## test case to get the given security files from the given chassis. +## +## Usage: +## test_case_get_esm_security_files chassis security_files +## Arguments: +## chassis - IP address/name of chassis to scp and telnet to +## security_files - security files to fetch +## Returns: +## 0 -> success +## -code error on failure +## Additional Information: +## The global timeout is changed by this routine +## +## see push_esm_security_files for error handling summary + + global env + + test_case "$chassis.fm_get_security_files" "get $chassis $security_files $dest_dir" "get FM security files from $chassis +Get Security Files: $security_files +Dest Directory: $dest_dir +File: TestTools/chassis.exp" noop noop { + upvar chassis chassis + upvar security_files security_files + upvar action action + upvar dest_dir dest_dir + + # check if chassis supports slaveCli, if not then skip chassis, older FW + target_chassis_admin_sh $chassis + if { [ catch { set cap [check_chassis_capability "slaveCli"] } res ] != 0 + || $cap < 1 } { + skip_case "chassis does not support FM config via FastFabric" + } + + # TBD - make this common code with fmconfig + log_message "\nTest: Getting Slot list from $chassis ...\n" + set my_slot [ get_this_slot_number ] + # get management card type for this chassis model + set mgmt_card_type [ get_chassis_card_type $my_slot] + # all slots of matching card type (eg. all management cards) + set mgmt_slots [get_chassis_slots $mgmt_card_type] + set num_slots [llength $mgmt_slots] + if { $num_slots == 0 } { + # this should not happen, we should at least find card 0 + target_chassis_admin_sh_exit + fail_test "No cards of type $mgmt_card_type" + } + # lets be paranoid + if { ! [ string equal [get_chassis_card_type $my_slot] "$mgmt_card_type" ] } { + target_chassis_admin_sh_exit + fail_test "IP address given is not for chassis mgmt card $mgmt_card_type" + } + + # all security files on the master management card + set sec_files [ list_esm_security_files ] + set num_sec_files [llength $sec_files] + if { $num_sec_files == 0 } { + target_chassis_admin_sh_exit + fail_test "No FM security files found" + } + + target_chassis_admin_sh_exit + + log_message "\nTest: Checking FM capabilities and status of $chassis ...\n" + # slot which supports sm CLI. Prefer active mgmt card otherwise its + # secondary mgmt card + set mgmt_slot "" + # see if any slots in chassis support smConfig + foreach slot $mgmt_slots { + if { [ string equal "$slot" "$my_slot" ] } { + target_chassis_admin_sh $chassis + } else { + target_chassis_admin_sh $chassis $slot + } + if { [ catch { set cap [check_chassis_capability "smConfig"] } res ] != 0 + || $cap < 1 } { + # slot will be skipped, doesn't support smConfig + } else { + if { [ string equal "$mgmt_slot" ""] || [ string equal "$slot" "$my_slot" ] } { + set mgmt_slot "$slot" + } + } + if { [ string equal "$slot" "$my_slot" ] } { + target_chassis_admin_sh_exit + } else { + target_chassis_admin_sh_exit 1 + } + } + + if { [ string equal "$mgmt_slot" "" ] } { + skip_case "chassis does not have an ESM license key or does not support smConfig" + } + + log_message "mkdir -p $dest_dir" + exec mkdir -p $dest_dir + foreach sec_file $sec_files { + get_esm_security_files "$chassis" "$sec_file" "$dest_dir" + } + } +} + diff --git a/TestTools/checkoutGen2Code.bash b/TestTools/checkoutGen2Code.bash new file mode 100755 index 0000000..25732f2 --- /dev/null +++ b/TestTools/checkoutGen2Code.bash @@ -0,0 +1,95 @@ +#!/bin/bash + +# Multipurpose script for master->stl1-branch code checkout. What it +# does depends on the command (first argument) passed into it: +# * checkout: checkout files from master into stl1-branch, +# limited to certain directories and regexes. Doesn't actually +# switch to stl1-branch, you have to do that. +# * diff: show differences between stl1-branch and master in files that +# should be the same between the two. +# * showSliced: show files that differ between stl1-branch and master and +# that were in commits that had files that were checked-out into master. +# So-called 'sliced' because they were part of a single commit that was +# 'sliced' apart. +set -u + +FromBranch=origin/master +ToBranch=origin/stl1-branch +DirList="Esm/ FabricSim/ IbAccess/ IbaTools/ IbPrint/ Log/ Makerules/ opamgt/ OpenIb_Host/ Sim/ Topology/ Xml/" + +# Limit checkout of master code to a) C/C++ files and b) non-C/C++ +# files where necessary to get code to build (basically just Makefiles) +inclRegex='\.([ch]|cpp|hpp)|Esm/ib/src/(eeph|eepha|eeph_mux|em)/|IbaTools/opaxlattopology/opaxlattopology.sh' +exclRegex="build_label" +function getFilesToCheckout() { + git ls-tree -r --name-only $FromBranch -- $DirList | egrep $inclRegex | egrep -v $exclRegex +} + +# When testing for sliced files (files that were in a commit that +slicedExclRegex="" +for d in $DirList ; do + if [[ -n $slicedExclRegex ]] ; then + slicedExclRegex+="|" + fi + slicedExclRegex+=$d +done + +function getExclFilesForCmt() { + local cmt=$1 ; shift + git diff-tree --no-commit-id --name-only -r $cmt | egrep $inclRegex | egrep -v $slicedExclRegex +} + +cmd=$1; shift + +if [[ $cmd = "checkout" ]] ; then + getFilesToCheckout | egrep $inclRegex | egrep -v $exclRegex | while read f ; do + git checkout $FromBranch -- $f + done +elif [[ $cmd = "diff" ]] ; then + diffOpts=$* + getFilesToCheckout | xargs git diff $ToBranch $FromBranch $diffOpts -- +elif [[ $cmd = "showSliced" ]] ; then + # TODO get 'show files' and 'show commit' options from commandline + # TODO also get additional exclude regexes from command line + showFiles=1 + showCmt=0 + + getFilesToCheckout | xargs git rev-list ${ToBranch}..${FromBranch} -- | while read cmt ; do + slicedFiles=`getExclFilesForCmt $cmt` + if [[ -z $slicedFiles ]] ; then + continue + fi + + # No actual diffs between the two branches concerning files that weren't checked out + # from $FromBranch into $ToBranch - skip this commit + if git diff --quiet $ToBranch $FromBranch -- $slicedFiles ; then + continue + fi + + if [[ $showCmt -ne 0 ]] ; then + git show --quiet $cmt + fi + + if [[ $showFiles -ne 0 ]] ; then + # This will include duplicates; pipe into sort | uniq to get unique file list + git diff-tree --no-commit-id --name-only -r $cmt | egrep $inclRegex | \ + egrep -v $slicedExclRegex | while read file ; do + + # Only show files from this commit if they actually + # differ between $FromBranch and $ToBranch + if ! git diff --quiet $ToBranch $FromBranch -- $file ; then + echo $file + fi + done + fi + + # Neither $showCmt nor $showFiles, just print commit SHA + if [[ $showCmt -eq 0 && $showFiles -eq 0 ]] ; then + echo $cmt + fi + done +else + echo "Error: unrecognized command \"$cmd\"" >&2 + echo "Usage: $0 (checkout|diff []|showSliced [])" >&2 + exit 1 +fi diff --git a/TestTools/common_funcs.exp b/TestTools/common_funcs.exp new file mode 100644 index 0000000..68d55d8 --- /dev/null +++ b/TestTools/common_funcs.exp @@ -0,0 +1,142 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] + +# This is an expect (tcl) library of procedures to aid ib stack testing + +global g_debug + +######################################################################################### +# Name : value_cmp_eq +# Input : value1, value2 +# Return . None. +# Description : Return an error if $value1 != $value2 +######################################################################################### + +proc value_cmp_eq { leftval rightval } { + if { $leftval ne $rightval } { + return -code error "ERROR : $leftval does not equal $rightval." + } + +} + +######################################################################################### +# Name : hextodec +# Input : hex value in the form 0x1234ABCD.... +# Return . decimal value. +# Description : Convert a 16 bit hex value to a decimal value. +######################################################################################### + +proc hextodec { number } { + + set result 0 + foreach hexvalue [split $number {}] { + + # check if hex value is a number + if { [ regexp {^([0-9]+)$} $hexvalue ] || [ regexp {^([a-fA-F]+)$} $hexvalue ] } { + set newhex 0x$hexvalue + set result [expr {16*$result + $newhex}] + } + } + + return $result +} + +######################################################################################### +# Name : dectohex +# Input : decimal value +# Return . hex value in the form 0x0000. +# Description : Convert a decimal value to a 16 bit hex value. +######################################################################################### + +proc dectohex { number } { + + set result [ format 0x%4.4x $number ] + return $result + +} + +######################################################################################### +# Name : normalizedec +# Input : decimal value +# Return . dec value in the form 1234. +# Description : Removes leading zeros in a decimal number +######################################################################################### + +proc normalizedec { number } { + + set result [string trimleft "$number" "0"] + if { $result == "" } { + set result 0 + } + + return $result +} + +######################################################################################### +# Name : dumpvar +# Input : var, fail, isXML +# Return : Failure with var value; if fail = 1, halt proc else dump var contents. +# : if isXML = true, dump var asXML +# Description : Useful for setting breakpoints in tcl test framework. +######################################################################################### + +proc dumpvar { var fail isXML} { + if { $fail == 0 } { + if { $isXML eq "true" } { + puts [$var asXML] + } else { + puts "DEBUG :: |$var|" + puts [ string length $var ] + } + } elseif { $fail == 1 } { + if { $isXML eq "true" } { + return -code error "DEBUG : |$var asXML|." + } else { + return -code error "DEBUG : |$var|." + } + } +} + +######################################################################################### +# Name : debug_message +# Input : msg +# Return : None +# Description : Outputs debug message msg to console +######################################################################################### + +proc debug_message { msg } { + global g_debug + + if { $g_debug == 1 } { + puts "DEBUG: $msg: [clock seconds]" + } +} + diff --git a/TestTools/defs.exp b/TestTools/defs.exp new file mode 100644 index 0000000..8e1a8e6 --- /dev/null +++ b/TestTools/defs.exp @@ -0,0 +1,44 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] + +# This is an expect (tcl) library of procedures to aid ib stack testing + +# Global variables that are used across mulitple suites +global g_xml_file_loc g_default_xml_file g_sample_xml_file_loc g_saved_xml_file_loc ibtools_dir + +set g_xml_file_loc {/etc/opa-fm/opafm.xml} +set g_default_xml_file test_run_default.xml +set ibtools_dir {/opt/iba/ib_tools} + +set g_sample_xml_file_loc {/usr/share/opa-fm/opafm.xml} +#set g_sample_xml_file_loc [ append g_sample_xml_file_loc $g_xml_file_loc -sample ] +set g_saved_xml_file_loc {} +set g_saved_xml_file_loc [ append g_saved_xml_file_loc $g_xml_file_loc .saved ] diff --git a/TestTools/extmng.exp b/TestTools/extmng.exp new file mode 100644 index 0000000..d250d50 --- /dev/null +++ b/TestTools/extmng.exp @@ -0,0 +1,1647 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: @(#) ./fastfabric/tools/extmng.exp 10_4_0_0_168 [03/04/17 07:32] + +# This is an expect (tcl) library of procedures to aid OPASW operations + +## tcl procedures to support testing: +## ============================================= + +proc expect_list_with_punchlist { ibnode issue timelimit list { error_list "" } { out_var "" } } { + if { ! [ string equal "$out_var" "" ] } { + upvar $out_var out + set var "out" + } else { + set var "" + } + + if { [ catch { set res [ expect_list $timelimit $list $error_list $var ] } err_str ] != 0 } { + append_punchlist "$ibnode" "$issue" + error "$err_str" + } + return $res +} + +proc trim_opaswitch_distance { opaswitch } { +## +## trim_opaswitch_distance +## --------------------------- +## remove the ,distance from the opaswitch +## +## Usage: +## trim_opaswitch_distance opaswitch +## Arguments: +## opaswitch - node to resolve, syntax as found in opaswitchs file +## Returns: +## opaswitch with any ,distance field removed +## -code error on failure +## Additional Information: +## Syntax allowed for opaswitch: +## nodeguid +## nodeguid,,distance +## nodeguid:hfi:port +## nodeguid:hfi:port,,distance +## nodeguid,nodename +## nodeguid,nodename,distance +## nodeguid:hfi:port,nodename +## nodeguid:hfi:port,nodename,distance +## + global env + + set index [string first "," "$opaswitch" ] + if { $index != -1 } { + set index [string first "," "$opaswitch" [ expr $index + 1]] + if { $index != -1 } { + # remove ,distance + set opaswitch [string range "$opaswitch" 0 [ expr $index - 1] ] + } + } + return "$opaswitch" +} + +proc get_opaswitch_distance { opaswitch } { +## +## gettrim_opaswitch_distance +## --------------------------- +## get the distance from the opaswitch +## +## Usage: +## get_opaswitch_distance opaswitch +## Arguments: +## opaswitch - node to process, syntax as found in switches file +## Returns: +## distance field from opaswitch or "" +## -code error on failure +## Additional Information: +## Syntax allowed for opaswitch: +## nodeguid +## nodeguid,,distance +## nodeguid:hfi:port +## nodeguid:hfi:port,,distance +## nodeguid,nodename +## nodeguid,nodename,distance +## nodeguid:hfi:port,nodename +## nodeguid:hfi:port,nodename,distance +## + global env + + set index [string first "," "$opaswitch" ] + if { $index != -1 } { + set index [string first "," "$opaswitch" [ expr $index + 1]] + if { $index != -1 } { + # return distance + return [string range "$opaswitch" [expr $index + 1 ] end ] + } + } + return "" +} + +proc trim_opaswitch_hfi_port { opaswitch } { +## +## trim_opaswitch_hfi_port +## --------------------------- +## remove the hfi:port from the opaswitch +## +## Usage: +## trim_opaswitch_hfi_port opaswitch +## Arguments: +## opaswitch - node to resolve, syntax as found in opaswitchs file +## Returns: +## opaswitch with any hfi:port field removed +## -code error on failure +## Additional Information: +## Assumes ,distance was already removed from opaswitch +## Syntax allowed for opaswitch: +## nodeguid +## nodeguid:hfi:port +## nodeguid,nodename +## nodeguid:hfi:port,nodename +## + global env + + # first parse off any nodename + set index [string first "," "$opaswitch" ] + if { $index != -1 } { + # includes , + set nodename [string range "$opaswitch" $index end ] + # excludes , + set nodeguid_hfi_port [string range "$opaswitch" 0 [ expr $index - 1] ] + } else { + set nodename "" + set nodeguid_hfi_port "$opaswitch" + } + # now parse off any hfi_port + set index [string first ":" "$nodeguid_hfi_port" ] + if { $index != -1 } { + # excludes : + set hfi_port [string range "$nodeguid_hfi_port" [expr $index + 1] end ] + # excludes : + set nodeguid [string range "$nodeguid_hfi_port" 0 [ expr $index - 1] ] + } else { + set hfi_port "" + set nodeguid "$nodeguid_hfi_port" + } + return "$nodeguid$nodename" +} + +proc strip_nodename_from_guid { opaswitch } { +## +## strip_nodename_from_guid +## --------------------------- +## remove the nodename from the opaswitch +## +## Usage: +## strip_nodename_from_guid opaswitch +## Arguments: +## opaswitch - node representation guid followed optionally +## by comma and nodename +## Returns: +## opaswitch with comma and nodename removed +## Additional Information: +## Assumes ,distance was already removed from opaswitch +## + global env + + set index [string first "," "$opaswitch" ] + if { $index != -1 } { + set node_guid [string range "$opaswitch" 0 [ expr $index - 1 ] ] + } else { + set node_guid "$opaswitch" + } + return "$node_guid" +} + +proc strip_nodeguid_from_desc { ibnode } { +## +## strip_nodeguid_from_desc +## --------------------------- +## remove the node GUID from the ibnode +## +## Usage: +## strip_nodeguid_from_desc ibnode +## Arguments: +## ibnode - node representation guid followed optionally +## by comma and nodename +## Returns: +## ibnode with node guid and comma removed +## Additional Information: +## Assumes ,distance was already removed from ibnode +## + global env + + set index [string first "," "$ibnode" ] + if { $index != -1 } { + set node_desc [string range "$ibnode" [ expr $index + 1 ] [expr [string length "$ibnode"]] ] + } else { + set node_desc "" + } + return "$node_desc" +} + +proc resolve_ibnode { ibnode } { +## +## resolve_ibnode +## --------------------------- +## resolve the hfi:port by which the given ibnode should be accessed +## +## Usage: +## resolve_ibnode ibnode +## Arguments: +## ibnode - node to resolve, syntax as found in ibnodes file +## Returns: +## hfi:port to access ibnode via -> success +## -code error on failure +## Additional Information: +## Assumes ,distance was already removed from ibnode +## Must be called with a local_sh established +## env(CFG_PORTS) is used to specify local hfi:port(s) to check to +## locate ibnode if ibnode does not have an explicit hfi_port. +## Syntax allowed for ibnode: +## nodeguid +## nodeguid:hfi:port +## nodeguid,nodename +## nodeguid:hfi:port,nodename +## + global env + + set bindir /usr/sbin + + # first parse off any nodename + set index [string first "," "$ibnode" ] + if { $index != -1 } { + # excludes , + set nodeguid_hfi_port [string range "$ibnode" 0 [ expr $index - 1] ] + + } else { + set nodeguid_hfi_port "$ibnode" + } + # now parse off any hfi_port + set index [string first ":" "$nodeguid_hfi_port" ] + if { $index != -1 } { + # excludes : + set hfi_port [string range "$nodeguid_hfi_port" [expr $index + 1] end ] + # excludes : + set nodeguid [string range "$nodeguid_hfi_port" 0 [ expr $index - 1] ] + } else { + set hfi_port "" + set nodeguid "$nodeguid_hfi_port" + } + + if { [ string equal "$hfi_port" "" ] } { + # no hfi_port specified + set found 0 + set llen [ llength $env(CFG_PORTS) ] + if { $llen == 0 } { + # default should have been set in opatest.sh, just be safe + set hfi_port "0:0" + } elseif { $llen == 1 } { + # no use iterating saquery, only 1 choice + set hfi_port [ lindex $env(CFG_PORTS) 0 ] + } else { + # iterate all specified ports, find first with given ibnode + foreach hfi_port $env(CFG_PORTS) { + set hfi_port_args [ get_hfi_port_args "$hfi_port" "-p" ] + # if saquery outputs a Node Record (which includes PortGuid heading) + # the nodeguid was found. Otherwise it will output an error message + if { ! [ string equal "$hfi_port" [ lindex $env(CFG_PORTS) 0] ] } { + log_message("Retrying with HFI port $hfi_port"); + } + if { [ catch { unix_cmd 90 0 "$bindir/opasaquery $hfi_port_args -n $nodeguid 2>&1|grep -i PortGuid > /dev/null 2>&1" } res ] == 0 } { + set found 1 + break + } else { + # kill any stuck saquery command + target_send_intr + expect_unix_prompt 60 + } + } + if { ! $found } { + append_punchlist "$ibnode" "Unable to find via hfi:port(s) $env(CFG_PORTS)" + fail_test "Unable to find $ibnode via hfi:port(s) $env(CFG_PORTS)" + } + } + } + return "$hfi_port" +} + +proc get_hfi_port_args { hfi_port { port_arg "-o" }} { +## +## get_hfi_port_args +## ------------------- +## parse the hfi_port and return proper -h and -o options for commands +## +## Usage: +## get_hfi_port_args hfi_port [port_arg] +## Arguments: +## hfi_port - hfi:port on local system to use to access the switch +## if "", defaults to 1st local port +## port_arg - argument name to specify port (default is p) +## Returns: +## nothing +## Additional Information: +## + + if { [ string equal "$hfi_port" "" ] } { + set hfi_port "0:0" + } + set hfi "" + set port "" + regexp {([0-9]+):([0-9]+)} $hfi_port p1 hfi port + if { [ string equal "$hfi" ""] || [ string equal "$port" ""] } { + fail_test "Invalid hfi:port ($hfi_port)" + } + set hfi_port_args "-h $hfi" + if { ! [ string equal "$port" "0"] } { + set hfi_port_args "$hfi_port_args $port_arg $port" + } + return "$hfi_port_args" +} + +proc get_switch_type { ibnode sa_hfi_port_args node_guid } { +## +## get_switch_type +## ------------------- +## find out if the switch is externally managed or internally managed +## +## Usage: +## ibnode sa_hfi_port_args node_guid +## Arguments: +## ibnode : to verify if it's a switch or not +## sa_hfi_port_args : port on the local system to access switch +## node_guid : to query records and find details about switch +## Returns: +## nothing +## Additional Information: + + global env + + set bindir /usr/sbin + + local_sh + + set type "" + set out "" + set lid "" + set systemimageguid "" + + send_unix_cmd "$bindir/opasaquery $sa_hfi_port_args -n $node_guid" + set out [expect_list_with_punchlist "$ibnode" "Switch not found in SA DB" 120 { "Type: [A-Za-z]+" } { "Error" "No Records Returned"}] + regexp {([Type:]+) ([A-Za-z]+)} $out type2 type1 type + check_exit_status 60 0 + send_unix_cmd "opasaquery $sa_hfi_port_args -n $node_guid -o node" + set out [expect_list_with_punchlist "$ibnode" "Switch not found in SA DB" 120 { "SystemImageGuid: [0x[A-Fa-f0-9]+" } { "Error" "No Records Returned"}] + regexp {(0x[A-Fa-f0-9]+)} $out systemimageguid + check_exit_status 60 0 + send_unix_cmd "opasaquery $sa_hfi_port_args -n $node_guid -o node" + set out [expect_list_with_punchlist "$ibnode" "Switch not found in SA DB" 120 { "LID: [0x[A-Fa-f0-9]+" } { "Error" "No Records Returned"}] + regexp {([LID:]+) ([0x[A-Fa-f0-9]+)} $out lid2 lid1 lid + if { ! [ string equal "$type" "SW"] } { + set type "SW" + log_message "$ibnode: Not a Switch device" + append_punchlist "$ibnode" "Not a Switch device" + fail_test "$ibnode: Not a Switch device" + } else { + check_exit_status 60 0 + # TODO: does this need to be updated, and how so + if { [ catch { unix_cmd 90 0 "echo $node_guid 2>&1 | grep 0x001175 /dev/null 2>&1" } res ] != 0 } { + log_message "It's an Intel switch $node_guid" + } else { + log_message "It's not an Intel switch $node_guid" + } + check_exit_status 60 0 + if { [ catch { unix_cmd 90 0 "$bindir/opasaquery -l $lid -o portinfo 2>&1 | sed -n '/PortNum: *0x00/,/-------/p' 2>&1 | grep Capability: 2>&1 | grep -v VDR > /dev/null 2>&1 " } res ] == 0 } { + log_message "$node_guid is an Internally Managed Switch" + show_message "$node_guid is an Internally Managed Switch" + append_punchlist "$ibnode" "Internally Managed Switch" + fail_test "Not supported: This is not an externally managed switch" + } + } +} + +proc get_switch_brand { ibnode } { +## +## get_switch_brand +## ------------------- +## determine if the switch identified by ibnode is OPA +## +## Usage: +## get_switch_brand hfi_port [port_arg] +## Arguments: +## hfi_port - hfi:port on local system to use to access the switch +## if "", defaults to 1st local port +## port_arg - argument name to specify port (default is p) +## Returns: +## switch brand - "OPA" or "unknown" +## Additional Information: +## + global env + + local_sh + + set out "" + set node_guid "" + set deviceid "" + set vendorid "" + set brand "" + set type "" + set bypass "" + + set hfi_port [ resolve_ibnode $ibnode ] + set hfi_port_args [ get_hfi_port_args "$hfi_port" ] + set trimmed_ibnode [ trim_opaswitch_hfi_port "$ibnode" ] + # use verbose option so we have a predictable output to expect + set node_guid [ strip_nodename_from_guid "$trimmed_ibnode" ] + set sa_hfi_port_args [ regsub -- "-o" "$hfi_port_args" "-p" ] + set bypass $env(CFG_SWITCH_BYPASS_SWITCH_CHECK) + if { [ string equal "$bypass" "n"] } { + set type [ get_switch_type "$ibnode" "$sa_hfi_port_args" "$node_guid" ] + } else { + log_message "" + log_message "Bypassing check for externally managed switch for -B option" + } + send_unix_cmd "opasaquery $sa_hfi_port_args -n $node_guid" + set out [expect_list_with_punchlist "$ibnode" "Switch not found in SA DB" 120 { "VendorID: [A-Fa-fx0-9]+ DeviceId: [A-Fa-fx0-9]+" } { "Error" "No Records Returned" }] + regexp {VendorID: (0x[A-Fa-f0-9]+) DeviceId: (0x[A-Fa-f0-9]+)} $out match vendorid deviceid + if { [ string equal "$deviceid" "0xabc0"] } { + if { [ string equal "$vendorid" "0x8086"] } { + set brand "OPA" + log_message "$ibnode: detected Intel OPA device" + } else { + set brand "unknown" + log_message "$ibnode: detected unknown device" + } + } else { + set brand "unknown" + log_message "$ibnode: detected unknown device" + } + + return "$brand" +} + +proc get_switch_getportconfig { ibnode } { +## +## get_switch_getportconfig +## ------------------- +## execute a test case gathering port info of switch $ibnode +## +## Usage: +## get_switch_getportconfig ibnode +## Arguments: +## ibnode - ib node to get switch port config +## Returns: +## config description +## Additional Information: +## + + global env + + set toolsdir /usr/lib/opa/tools + + set out_msg "" + + local_sh + set out "" + + set hfi_port [ resolve_ibnode $ibnode ] + set hfi_port_args [ get_hfi_port_args "$hfi_port" ] + set trimmed_ibnode [ trim_opaswitch_hfi_port "$ibnode" ] + # use verbose option so we have a predictable output to expect + + set brand [get_switch_brand "$ibnode"] + if { [ string equal "$brand" "OPA"] } { + check_exit_status 60 0 + send_unix_cmd "$toolsdir/opaswquery -t $trimmed_ibnode $hfi_port_args -Q 11 " + set all [expect_list_with_punchlist "$ibnode" "Unable to query switch" 60 { "Switch.+opaswquery completed" } { "Error"}] + regexp {(Switch configuration values)(.+)(opaswquery completed)} $all a b out_msg + show_message "$out_msg" + } else { + append_punchlist "$ibnode" "Not an Intel Device" + fail_test "$ibnode: Not an Intel Device" + } + + local_sh_exit + + return "$out_msg" +} + +proc get_portstate { ibnode } { +## +## get_portstate +## ------------------- +## get state of local HFI port +## +## Usage: +## get_portstate ibnode +## Arguments: +## ibnode - ib node of switch, includes hfi/port +## Returns: +## port state as output in "opaportinfo" command +## Additional Information: +## + global env + set out_msg "" + + local_sh + set out "" + set portstate "" + + set hfi_port [ resolve_ibnode $ibnode ] + set hfi_port_args [ get_hfi_port_args "$hfi_port" ] + + send_unix_cmd "opaportinfo $hfi_port_args" + set out [expect_list_with_punchlist "$ibnode" "Unable to open hfi:port" 30 { "PortState: +[A-Za-z]+" } { "failed"}] + regexp {PortState: +([A-Za-z]+)} $out xx portstate + + local_sh_exit + + return "$portstate" +} + +proc verify_port_active { ibnode {wait_time 30} } { +## +## verify_port_active +## ------------------- +## verify that the local HFI port is active +## +## Usage: +## verify_port_active ibnode +## Arguments: +## ibnode - ib node of switch, includes hfi/port +## wait_time - seconds to wait for the hfi port +## to come active, default 30 +## Returns: +## 0 on success, -1 on failure +## Additional Information: +## + global env + + for {set i 0} {$i < $wait_time} {incr i} { + set portstate [get_portstate "$ibnode"] + set index [ string first "Active" $portstate ] + if { $index == -1 } { + sleep 1 + } else { + return 0 + } + } + return -1 +} + + +proc get_switch_info { ibnode } { +## +## get_switch_info +## ------------------- +## execute a test case gathering switch info from $ibnode +## +## Usage: +## get_switch_info ibnode +## Arguments: +## ibnode - ib node to get switch info +## Returns: +## info description +## Additional Information: +## + + global env + + set toolsdir /usr/lib/opa/tools + + set out_msg "" + + local_sh + + set hfi_port [ resolve_ibnode $ibnode ] + set hfi_port_args [ get_hfi_port_args "$hfi_port" ] + set trimmed_ibnode [ trim_opaswitch_hfi_port "$ibnode" ] + # use verbose option so we have a predictable output to expect + + set brand [get_switch_brand "$ibnode"] + if { [ string equal "$brand" "OPA"] } { + check_exit_status 60 0 + send_unix_cmd "$toolsdir/opaswquery -t $trimmed_ibnode $hfi_port_args -Q 3" + set out [expect_list_with_punchlist "$ibnode" "Unable to query switch" 60 { "FW Version is [0-9.]+" } { "Error"}] + regexp {([0-9.]+)} $out fwversion + } else { + append_punchlist "$ibnode" "Not an Intel OPA device" + fail_test "$ibnode: Not an Intel OPA device" + } + + # use verbose option so we have a predictable output to expect + if { [ string equal "$brand" "OPA"] } { + send_unix_cmd "$toolsdir/opaswquery -t $trimmed_ibnode $hfi_port_args -Q 11" + } else { + append_punchlist "$ibnode" "Not an Intel OPA device" + fail_test "$ibnode: Not an Intel OPA device" + } + set out [expect_list_with_punchlist "$ibnode" "Unable to query switch" 60 { "Switch configuration values" "[[:space:]]+Link Width[[:space:]]+[:][[:space:]][[:print:]]*([0-9]+)" } { "Error"}] + regexp {[[:space:]]+Link Width[[:space:]]+[:][[:space:]]+([[:print:]],)*([0-9]+)} $out line p1 linkWidth + set out [expect_list_with_punchlist "$ibnode" "Unable to query switch" 60 { "[[:space:]]+Link Speed[[:space:]]+[:][[:space:]]+([0-9Gb.,])*([0-9Gb]+)" } { "Error"}] + regexp {[[:space:]]+Link Speed[[:space:]]+[:][[:space:]]+([[:print:]],)*([0-9Gb]+)$} $out line p1 linkSpeed + set capability [format {%sx%s} $linkWidth $linkSpeed] + + # use verbose option so we have a predictable output to expect + if { [ string equal "$brand" "OPA"] } { + send_unix_cmd "$toolsdir/opaswquery -t $trimmed_ibnode $hfi_port_args -Q 4" + } else { + append_punchlist "$ibnode" "Not an Intel OPA device" + fail_test "$ibnode: Not an Intel OPA device" + } + set out [expect_list_with_punchlist "$ibnode" "Unable to query switch" 60 { "VPD \"[[:print:]]*\",\"[[:print:]]*\",\"[[:print:]]*\",\"[[:print:]]*\",\"[[:print:]]+\",\"[[:print:]]+\",\"[[:print:]]*\",\"[[:print:]]*\",\"[[:print:]]*\"" } { "Error"}] + regexp {([VPD]+) "([[:print:]]*)","([[:print:]]*)","([[:print:]]*)","([[:print:]]*)","([[:print:]]*)","([[:print:]]*)","([[:print:]]*)","([[:print:]]*)","([[:print:]]*)"} $out p1 p2 p3 partnumber p4 hwversion + + # use verbose option so we have a predictable output to expect + if { [ string equal "$brand" "OPA"] } { + set index1 [expr [string first "-" $partnumber ] + 1] + set index2 [expr [string last "-" $partnumber ] - 1] + set midNum [string range $partnumber $index1 $index2] + set psIndicator [string range $midNum 1 1] + + set numPS 2 + + check_exit_status 60 0 + send_unix_cmd "$toolsdir/opaswquery -t $trimmed_ibnode $hfi_port_args -Q 7" + set out [expect_list_with_punchlist "$ibnode" "Unable to query switch" 60 { "FAN[A-Z0-9: ]+"} { "Error" }] + regexp {0:([A-Z]+)} $out f1 f2 + if { [ string equal "$f2" "NORMAL"] } { + set fanaStatus "Normal" + } elseif { [ string equal "$f2" "FAST"] } { + set fanaStatus "TooFast" + } elseif { [ string equal "$f2" "SLOW"] } { + set fanaStatus "TooSlow" + } elseif { [ string equal "$f2" "NOTPRESENT"] } { + set fanaStatus "NotPresent" + } elseif { [ string equal "$f2" "NOTAVAIL"] } { + set fanaStatus "NotAvail" + } else { + set fanaStatus "Unknown" + } + regexp {1:([A-Z]+)} $out f1 f2 + if { [ string equal "$f2" "NORMAL"] } { + set fanbStatus "Normal" + } elseif { [ string equal "$f2" "FAST"] } { + set fanbStatus "TooFast" + } elseif { [ string equal "$f2" "SLOW"] } { + set fanbStatus "TooSlow" + } elseif { [ string equal "$f2" "NOTPRESENT"] } { + set fanbStatus "NotPresent" + } elseif { [ string equal "$f2" "NOTAVAIL"] } { + set fanbStatus "NotAvail" + } else { + set fanbStatus "Unknown" + } + regexp {2:([A-Z]+)} $out f1 f2 + if { [ string equal "$f2" "NORMAL"] } { + set fancStatus "Normal" + } elseif { [ string equal "$f2" "FAST"] } { + set fancStatus "TooFast" + } elseif { [ string equal "$f2" "SLOW"] } { + set fancStatus "TooSlow" + } elseif { [ string equal "$f2" "NOTPRESENT"] } { + set fancStatus "NotPresent" + } elseif { [ string equal "$f2" "NOTAVAIL"] } { + set fancStatus "NotAvail" + } else { + set fancStatus "Unknown" + } + regexp {3:([A-Z]+)} $out f1 f2 + if { [ string equal "$f2" "NORMAL"] } { + set fandStatus "Normal" + } elseif { [ string equal "$f2" "FAST"] } { + set fandStatus "TooFast" + } elseif { [ string equal "$f2" "SLOW"] } { + set fandStatus "TooSlow" + } elseif { [ string equal "$f2" "NOTPRESENT"] } { + set fandStatus "NotPresent" + } elseif { [ string equal "$f2" "NOTAVAIL"] } { + set fandStatus "NotAvail" + } else { + set fandStatus "Unknown" + } + regexp {4:([A-Z]+)} $out f1 f2 + if { [ string equal "$f2" "NORMAL"] } { + set faneStatus "Normal" + } elseif { [ string equal "$f2" "FAST"] } { + set faneStatus "TooFast" + } elseif { [ string equal "$f2" "SLOW"] } { + set faneStatus "TooSlow" + } elseif { [ string equal "$f2" "NOTPRESENT"] } { + set faneStatus "NotPresent" + } elseif { [ string equal "$f2" "NOTAVAIL"] } { + set faneStatus "NotAvail" + } else { + set faneStatus "Unknown" + } + regexp {5:([A-Z]+)} $out f1 f2 + if { [ string equal "$f2" "NORMAL"] } { + set fanfStatus "Normal" + } elseif { [ string equal "$f2" "FAST"] } { + set fanfStatus "TooFast" + } elseif { [ string equal "$f2" "SLOW"] } { + set fanfStatus "TooSlow" + } elseif { [ string equal "$f2" "NOTPRESENT"] } { + set fanfStatus "NotPresent" + } elseif { [ string equal "$f2" "NOTAVAIL"] } { + set fanfStatus "NotAvail" + } else { + set fanfStatus "Unknown" + } + if { ! [ string equal "$fanaStatus/$fanbStatus/$fancStatus/$fandStatus/$faneStatus/$fanfStatus" "Normal/Normal/Normal/Normal/Normal/Normal" ] } { + append_punchlist "$ibnode" "Fan: $fanaStatus/$fanbStatus/$fancStatus/$fandStatus/$faneStatus/$fanfStatus" + } + set fanStatus "$fanaStatus/$fanbStatus/$fancStatus/$fandStatus/$faneStatus/$fanfStatus" + } else { + append_punchlist "$ibnode" "Not an Intel OPA device" + fail_test "$ibnode: Not an Intel OPA device" + } + + if { [ string equal "$brand" "OPA"] } { + check_exit_status 60 0 + send_unix_cmd "$toolsdir/opaswquery -t $trimmed_ibnode $hfi_port_args -Q 6" + set out [expect_list_with_punchlist "$ibnode" "Unable to query switch" 60 { "SENSOR[A-Z_0-9/_: ]+" } { "Error" }] + regexp {LTC2974: ([NA0-9\/C]+)} $out f1 f2 + if { [ string equal "N/A" "$f2" ] } { + append_punchlist "$ibnode" "LTC2974: Temperature Not Available" + set tempaStatus "LTC2974:$f2" + } else { + set tempaStatus "LTC2974:$f2" + } + regexp {MAX QSFP: ([NA0-9\/C]+)} $out f1 f2 + if { [ string equal "N/A" "$f2" ] } { + set tempbStatus "MAX_QSFP:$f2" + append_punchlist "$ibnode" "MAX_QSFP: Temperature Not Available" + } else { + set tempbStatus "MAX_QSFP:$f2" + } + regexp {PRR ASIC: ([NA0-9\/C]+)} $out f1 f2 + if { [ string equal "N/A" "$f2" ] } { + set tempcStatus "PRR_ASIC:$f2" + append_punchlist "$ibnode" "PRR_ASIC: Temperature Not Available" + } else { + set tempcStatus "PRR_ASIC:$f2" + } + + set tempStatus "$tempaStatus/$tempbStatus/$tempcStatus" + + } else { + append_punchlist "$ibnode" "Not an Intel OPA device" + fail_test "$ibnode: Not an Intel OPA device" + } + + # use verbose option so we have a predictable output to expect + if { [ string equal "$brand" "OPA"] } { + if { "$numPS" == "2" } { + check_exit_status 60 0 + send_unix_cmd "$toolsdir/opaswquery -t $trimmed_ibnode $hfi_port_args -Q 8 -i 1" + set out [expect_list_with_punchlist "$ibnode" "Unable to query switch" 60 { "PS 1: [A-Z\/ ]+" } { "Error" }] + regexp {([PS 1:]+) ([A-Z\/ ]+)} $out p1 p2 p3 + + if { ! [ string equal "$p3" "ONLINE" ] && + ! [ string equal "$p3" "OFFLINE" ] && + ! [ string equal "$p3" "NOT PRESENT" ] && + ! [ string equal "$p3" "N/A" ] && + ! [ string equal "$p3" "INVALID" ] } { + set ps1Status "ERROR" + } else { + set ps1Status "$p3" + } + } else { + set ps1Status "ERROR" + } + check_exit_status 60 0 + send_unix_cmd "$toolsdir/opaswquery -t $trimmed_ibnode $hfi_port_args -Q 8 -i 2" + set out [expect_list_with_punchlist "$ibnode" "Unable to query switch" 60 { "PS 2: [A-Z\/ ]+" } { "Error" }] + regexp {([PS 2:]+) ([A-Z\/ ]+)} $out p1 p2 p3 + if { ! [ string equal "$p3" "ONLINE" ] && + ! [ string equal "$p3" "OFFLINE" ] && + ! [ string equal "$p3" "NOT PRESENT" ] && + ! [ string equal "$p3" "N/A" ] && + ! [ string equal "$p3" "INVALID" ] } { + set ps2Status "ERROR" + } else { + set ps2Status "$p3" + } + } else { + append_punchlist "$ibnode" "Not an Intel OPA device" + fail_test "$ibnode: Not an Intel OPA device" + } + + # report the results + show_message "" + if { [ string equal "$brand" "OPA"] } { +# show_message "$ibnode: +# F/W ver:$fwversion H/W ver:$hwversion H/W pt num:$partnumber Capability:$capability Fan status:$fanStatus PS1 Status:$ps1Status PS2 Status:$ps2Status" + if { [ string equal "$ps2Status" "INVALID" ] } { + show_message "$ibnode: + F/W ver:$fwversion H/W ver:$hwversion H/W pt num:$partnumber Fan status:$fanStatus PS1 Status:$ps1Status Temperature status:$tempStatus" + set out_msg "F/W ver:$fwversion +H/W ver:$hwversion +H/W pt num:$partnumber +Capability:$capability +Fan status:$fanStatus +PS1 Status:$ps1Status +Temperature status:$tempStatus" + } elseif { [ string equal "$ps1Status" "INVALID" ] } { + show_message "$ibnode: + F/W ver:$fwversion H/W ver:$hwversion H/W pt num:$partnumber Fan status:$fanStatus PS2 Status:$ps2Status Temperature status:$tempStatus" + set out_msg "F/W ver:$fwversion +H/W ver:$hwversion +H/W pt num:$partnumber +Capability:$capability +Fan status:$fanStatus +PS2 Status:$ps2Status +Temperature status:$tempStatus" + } else { + show_message "$ibnode: + F/W ver:$fwversion H/W ver:$hwversion H/W pt num:$partnumber Fan status:$fanStatus PS1 Status:$ps1Status PS2 Status:$ps2Status Temperature status:$tempStatus" + set out_msg "F/W ver:$fwversion +H/W ver:$hwversion +H/W pt num:$partnumber +Capability:$capability +Fan status:$fanStatus +PS1 Status:$ps1Status +PS2 Status:$ps2Status +Temperature status:$tempStatus" + } + } else { + append_punchlist "$ibnode" "Not an Intel OPA device" + fail_test "$ibnode: Not an Intel OPA device" + } + local_sh_exit + + return "$out_msg" +} + +proc get_switch_hwvpd { ibnode } { +## +## get_switch_hwvpd +## ------------------- +## execute a test case gathering switch hwvpd from $ibnode +## +## Usage: +## get_switch_hwvpd ibnode +## Arguments: +## ibnode - ib node to get switch hwvpd +## Returns: +## nothing +## Additional Information: +## + global env + + set toolsdir /usr/lib/opa/tools + + local_sh + + set hfi_port [ resolve_ibnode $ibnode ] + set hfi_port_args [ get_hfi_port_args "$hfi_port" ] + set trimmed_ibnode [ trim_opaswitch_hfi_port "$ibnode" ] + set brand [get_switch_brand "$ibnode"] + # use verbose option so we have a predictable output to expect + if { [ string equal "$brand" "OPA"] } { + check_exit_status 60 0 + send_unix_cmd "$toolsdir/opaswquery -t $trimmed_ibnode $hfi_port_args -Q 4" + } else { + append_punchlist "$ibnode" "Not an OPA series device" + fail_test "$ibnode: Not an Intel OPA device" + } + set out [expect_list_with_punchlist "$ibnode" "Unable to query switch" 60 { "VPD \"[[:print:]]*\",\"[[:print:]]*\",\"[[:print:]]*\",\"[[:print:]]*\",\"[[:print:]]+\",\"[[:print:]]+\",\"[[:print:]]*\",\"[[:print:]]*\",\"[[:print:]]*\"" } { "Error" }] + regexp {([VPD]+) "([[:print:]]*)","([[:print:]]*)","([[:print:]]*)","([[:print:]]*)","([[:print:]]*)","([[:print:]]*)","([[:print:]]*)","([[:print:]]*)","([[:print:]]*)"} $out p1 p2 serialnumber partnumber model hwversion mfgname proddesc mfgid date time + local_sh_exit + + # report the results + show_message " \n + $ibnode: H/W VPD serial number: $serialnumber + $ibnode: H/W VPD part number : $partnumber + $ibnode: H/W VPD model : $model + $ibnode: H/W VPD h/w version : $hwversion + $ibnode: H/W VPD manufacturer : $mfgname + $ibnode: H/W VPD prod desc : $proddesc + $ibnode: H/W VPD mfg id : $mfgid + $ibnode: H/W VPD mfg date : $date + $ibnode: H/W VPD mfg time : $time" + +} + +proc get_switch_ping { ibnode { hfi_port ""} { report "1" } { ignore_pass "0" } } { +## +## get_switch_ping +## ------------------- +## execute a test case gathering switch ping from $ibnode +## +## Usage: +## get_switch_ping ibnode [hfi_port] [report] +## Arguments: +## ibnode - ib node to ping +## hfi_port - hfi:port on local system to use to access the ibnode +## report - if "1", output presence, otherwise be silent +## Returns: +## presence string - "is" or "not" +## Additional Information: +## + global env + + set toolsdir /usr/lib/opa/tools + + local_sh + + set out "" + set node_guid "" + set presence "not" + + if { [ string equal "$hfi_port" "" ] } { + set hfi_port [ resolve_ibnode $ibnode ] + } + set hfi_port_args [ get_hfi_port_args "$hfi_port" ] + set trimmed_ibnode [ trim_opaswitch_hfi_port "$ibnode" ] + # use verbose option so we have a predictable output to expect + set node_guid [ strip_nodename_from_guid "$trimmed_ibnode" ] + set sa_hfi_port_args [ regsub -- "-o" "$hfi_port_args" "-p" ] + send_unix_cmd "opasaquery $sa_hfi_port_args -n $node_guid" + if { [ catch { expect_progress 60 {[\r\n]} { "LID" "SystemImageGuid" } { "No Records Returned" "Failed:" } } res ] != 0 } { + set presence "not" + log_message "$ibnode: unit is not present" + } else { + set brand [get_switch_brand "$ibnode"] + if { [ string equal "$brand" "OPA"] } { + check_exit_status 60 0 + send_unix_cmd "$toolsdir/opaswping -t $trimmed_ibnode $hfi_port_args" + } else { + append_punchlist "$ibnode" "Not an Intel OPA device" + fail_test "$ibnode: Not an Intel OPA device" + } + if { [ catch { expect_progress 60 {[\r\n]} { "is present" } { "No Path Records Returned" "Error" } } res ] != 0 } { + set present not + } else { + set present is + } + if { [ string equal "$present" "is"] } { + set presence "is" + if { [ string equal "$report" "1"] } { + log_message "$ibnode: unit is present" + show_message "" + show_message "$ibnode: unit is present" + } + } + } + local_sh_exit + + return "$presence" +} + +proc get_switch_fwverify { ibnode } { +## +## get_switch_fwverify +## ------------------- +## execute a test case verifying f/w on $ibnode +## +## Usage: +## get_switch_fwverify ibnode +## Arguments: +## ibnode - ib node to verify f/w +## Returns: +## nothing +## Additional Information: +## + global env + + set toolsdir /usr/lib/opa/tools + + local_sh + + set hfi_port [ resolve_ibnode $ibnode ] + set hfi_port_args [ get_hfi_port_args "$hfi_port" ] + set trimmed_ibnode [ trim_opaswitch_hfi_port "$ibnode" ] + set brand [get_switch_brand "$ibnode"] + if { [ string equal "$brand" "OPA"] } { + check_exit_status 60 0 + send_unix_cmd "$toolsdir/opaswfwverify -t $trimmed_ibnode $hfi_port_args -q" + } else { + append_punchlist "$ibnode" "Not an Intel OPA device" + fail_test "$ibnode: Not an Intel OPA device" + } + set out [expect_list_with_punchlist "$ibnode" "Unable to verify FW" 120 { "[A-Za-z]+ primary image" } { "Error" }] + regexp {([A-Za-z]+)} $out pValidity + + set present "is" + + if { [ string equal "$present" "not"] } { + # log_message "$ibnode - no failsafe eeproms" + set fValidity "N/A" + } else { + check_exit_status 60 0 + send_unix_cmd "$toolsdir/opaswfwverify -t $trimmed_ibnode $hfi_port_args -q -F" + set out [expect_list_with_punchlist "$ibnode" "Unable to verify FW" 120 { "[A-Za-z]+ secondary image" } { "Error" }] + regexp {([A-Za-z]+)} $out fValidity + + if { [ string equal "$brand" "OPA"] } { + check_exit_status 60 0 + send_unix_cmd "$toolsdir/opaswquery -t $trimmed_ibnode $hfi_port_args -Q 2" + set out [expect_list_with_punchlist "$ibnode" "Unable to query switch" 120 { "from [A-Za-z]+" } { "Error" }] + regexp {(from) ([A-Za-z]+)} $out from f which + log_message "$ibnode - switch has booted from $which image" + } + } + show_message "" + + show_message "$ibnode - bootable image: $pValidity failsafe image: $fValidity booted from: $which" + local_sh_exit + + if { ! ( [ string equal "$pValidity" "valid" ] || [ string equal "$fValidity" "N/A" ] ) || + ! ( [ string equal "$pValidity" "valid" ] || [ string equal "$fValidity" "N/A" ] ) } { + append_punchlist "$ibnode" "Corrupted FW Image: primary: $pValidity failsafe: $fValidity" + fail_test "$ibnode: Corrupted FW Image: primary: $pValidity failsafe: $fValidity" + } +} + +proc get_switch_capture { ibnode upload_file } { +## +## get_switch_capture +## ------------------- +## execute a test case gathering switch capture from $ibnode to $upload_file +## +## Usage: +## get_switch_capture ibnode upload_file +## Arguments: +## ibnode - ib node to get switch capture +## upload_file - file to save capture to +## Returns: +## nothing +## Additional Information: +## + global env + + set toolsdir /usr/lib/opa/tools + + local_sh + + set hfi_port [ resolve_ibnode $ibnode ] + set hfi_port_args [ get_hfi_port_args "$hfi_port" ] + set trimmed_ibnode [ trim_opaswitch_hfi_port "$ibnode" ] + set node_guid [ strip_nodename_from_guid "$trimmed_ibnode" ] + set brand [get_switch_brand "$ibnode"] + # use verbose option so we have a predictable output to expect + if { [ string equal "$brand" "OPA"] } { + unix_cmd 60 0 "mkdir -p [ exec dirname $upload_file ]" + # use -v so log is easier to analyze and debug failures + # TODO: This needs to be updated with whatever the new capture file is + send_unix_cmd "$toolsdir/xedge_capture -v -t $node_guid $hfi_port_args $upload_file" + check_exit_status 60 0 + } else { + append_punchlist "$ibnode" "Not an Intel OPA device" + fail_test "$ibnode: Not an Intel OPA device" + } + local_sh_exit +} + +proc test_case_i2c_extmgd_eeprom { operation ibnode fwspeed hwversion { args {}} {norecords 0} } { +## +## test_case_i2c_extmgd_eeprom +## --------------------------- +## test case to dump or upgrade the firmware image of externally managed switch +## nodes. +## +## Usage: +## test_case_i2c_extmgd_eeprom operation ibnode [args] +## Arguments: +## operation - dump or upgrade operation +## ibnode - IB switch node +## args - parameters specific to the operation +## Returns: +## 0 -> success +## -code error on failure +## Additional Information: +## The global timeout is changed by this routine +## + + global env + + # TBD - should separate dump and upgrade into different functions + # fwfile, file version and action should be args of this function instead + # of using globals, that way caller can do looping in TCL later + if { [ string equal "$operation" "upgrade"] } { + set info " +Firmware package File: $env(CFG_FWFILE) +Speed: $fwspeed +Firmware Version: $env(CFG_FWRELEASEVERSIONINFO) +Action: $env(CFG_FWACTION)" + } else { + set info "" + } + test_case "$ibnode.i2c.extmgd.eeprom" "$operation firmware of switch $ibnode" "Access EEPROM of switch node $ibnode$info +File: TestTools/extmng.exp" case_setup case_cleanup { + upvar operation operation + upvar ibnode ibnode + upvar fwspeed fwspeed + upvar hwversion hwversion + upvar args args + upvar norecords norecords + + + set fw_override $env(CFG_FWOVERRIDE) + + local_sh + set hfi_port [ resolve_ibnode $ibnode ] + set hfi_port_args [ get_hfi_port_args "$hfi_port" ] + set trimmed_ibnode [ trim_opaswitch_hfi_port "$ibnode" ] + local_sh_exit + + set toolsdir /usr/lib/opa/tools + + set brand [get_switch_brand "$ibnode"] + if { [ string equal "$brand" "OPA"] } { + if { ! [ string equal "$env(CFG_SWITCH_DEVICE)" "OPA"] } { + show_message "" + skip_case "Device type of firmware -$env(CFG_SWITCH_DEVICE)- does not match switch\n" + } + if { [ string equal "$operation" "upgrade"] } { + # retrieve version and asic version of target + local_sh + send_unix_cmd "$toolsdir/opaswquery -t $trimmed_ibnode $hfi_port_args -Q 3" + set out [expect_list_with_punchlist "$ibnode" "Unable to query switch" 60 { "FW Version is [0-9.]+" } { "Error" }] + regexp {([0-9.]+)} $out fwversion + check_exit_status 60 0 + send_unix_cmd "$toolsdir/opaswquery -t $trimmed_ibnode $hfi_port_args -Q 9" + set out [expect_list_with_punchlist "$ibnode" "Unable to query switch" 60 { "ASIC Version: [V0-9]+" } { "Error" }] + regexp {([ASIC Version:]+) ([V0-9]+)} $out p1 p2 asicversion + if { ! [string match "*$asicversion*" "$hwversion"] } { + show_message "" + skip_case "Switch capability of -$asicversion- does not support ASIC version of firmware -$hwversion-\n" + # aborts via skip_case + } elseif { $env(CFG_FWRELEASEVERSIONINFO) == $fwversion && $fw_override == "n" } { + # if the password is not being changed, we will skip below + #skip_case "Switch already has version $fwversion loaded" + check_exit_status 60 0 + send_unix_cmd "$toolsdir/opaswquery -t $trimmed_ibnode $hfi_port_args -Q 2" + set out [expect_list_with_punchlist "$ibnode" "Unable to query switch" 120 { "from [A-Za-z]+" } { "Error" }] + regexp {(from) ([A-Za-z]+)} $out from f which + if { [ string equal "$which" "primary"] } { + set proceed 0 + } else { + set proceed 1 + } + } else { + set proceed 1 + } + local_sh_exit + } else { + set proceed 1 + } + } + + if { ! $proceed } { + show_message "" + skip_case "Switch already has version $fwversion loaded" + } + + # use verbose option so we have a predictable output to expect + local_sh + set brand [get_switch_brand "$ibnode"] + if { [ string equal "$brand" "OPA"] } { + set modifyParam "-z 60 -u 10 -T 15000" + set modifyParamCfg "-T 15000" + set node_desc [ strip_nodeguid_from_desc "$trimmed_ibnode" ] + set length [string length $node_desc] + if { $length > 0 } { + local_sh + send_unix_cmd "$toolsdir/opaswconfigure -t $trimmed_ibnode $hfi_port_args -S -C 1 -s $node_desc" + if { $norecords } { + expect_list_with_punchlist "$ibnode" "Unable to configure switch" 60 { "opaswconfigure completed"} { "Error" } + } else { + expect_list_with_punchlist "$ibnode" "Unable to configure switch" 300 { "opaswconfigure completed"} { "Error"} + } + } + if { [ file exists $env(CFG_FWTEMPDIR)] } { + check_exit_status 60 0 + send_unix_cmd "$toolsdir/opaswfwconfigure -t $trimmed_ibnode $hfi_port_args $modifyParamCfg -d $env(CFG_FWTEMPDIR)" + if { $norecords } { + expect_list_with_punchlist "$ibnode" "Unable to configure switch" 60 { "opaswfwconfigure completed"} { "Error" } + } else { + expect_list_with_punchlist "$ibnode" "Unable to configure switch" 300 { "opaswfwconfigure completed"} { "Error" } + } + } + check_exit_status 60 0 + send_unix_cmd "$toolsdir/opaswquery -t $trimmed_ibnode $hfi_port_args -Q 10" + set out [expect_list_with_punchlist "$ibnode" "Unable to query switch" 120 { "Session ID: [0-9]+" } { "Error" }] + regexp {(Session ID:) ([0-9]+)} $out p1 p2 oldSessID + scan $oldSessID "%d" oldsessionid + check_exit_status 60 0 + send_unix_cmd "$toolsdir/opaswfwupdate $hfi_port_args -q $modifyParam $args; echo DONE" + if { $norecords } { + expect_list_with_punchlist "$ibnode" "Unable to update FW" 60 { "opaswfwupdate completed"} { "Error" } + } else { + expect_list_with_punchlist "$ibnode" "Unable to update FW" 300 { "opaswfwupdate completed"} { "Error" } + } + } else { + append_punchlist "$ibnode" "Not an Intel OPA device" + fail_test "$ibnode: Not an Intel OPA device" + } + local_sh_exit + + + if { [ string equal "$operation" "upgrade"] + && [ string equal "$env(CFG_FWACTION)" "run"] } { + log_message "$ibnode has been reset ... waiting for return" + # wait 30 secs first, then try up to 7.5 minutes at 10 sec intervals + if { [ string equal "$brand" "OPA"] } { + set sleeptime 18 + } else { + set sleeptime 30 + } + for {set i 0} {$i < 51} {incr i} { + # wait for switch to reboot + if { $i!=0 } { + log_message "Retrying: $ibnode not yet back online ... waiting for return" + } + sleep $sleeptime + # first wait for local HFI port to come active - 30 seconds + set active [verify_port_active "$ibnode" 30] + if { $active == -1 } { + append_punchlist "$ibnode" "Can not verify reboot - local HFI port not active" + fail_test "$ibnode - can not verify reboot - local HFI port not active" + } + set presence [get_switch_ping "$ibnode" "$hfi_port" 0 "0"] + if { [ string equal "$presence" "is"] } { + break + } + set sleeptime 10 + } + if { [ string equal "$presence" "not"] } { + append_punchlist "$ibnode" "Failed to come back online after reboot" + fail_test "$ibnode Failed to come back online after reboot" + } elseif { [ string equal "$brand" "OPA"] } { + local_sh + send_unix_cmd "$toolsdir/opaswquery -t $trimmed_ibnode $hfi_port_args -Q 10" + set out [expect_list_with_punchlist "$ibnode" "Unable to query switch" 120 { "Session ID: [0-9]+" } { "Error" }] + regexp {(Session ID:) ([0-9]+)} $out p1 p2 sessID + scan $sessID "%d" sessionid + if { $sessionid > $oldsessionid } { + append_punchlist "$ibnode" "Did not reboot properly" + fail_test "$ibnode did not reboot properly" + } + local_sh_exit + } + } + } +} + +proc test_case_i2c_extmgd_reset { ibnode { args {}} {norecords 0} } { +## +## test_case_i2c_extmgd_reset +## --------------------------- +## test_case to reset externally managed switch +## +## Usage: +## test_case_i2c_extmgd_reset ibnode +## Arguments: +## ibnode - IB switch node +## args - parameters specific to the operation +## Returns: +## None +## Additional Information: +## must be used within a test_suite's body, performs test_case calls +## uses case_setup and case_cleanup provided by caller +## no item_setup nor item_cleanup used + + test_case "$ibnode.i2c.extmgd.reset" "reset switch $ibnode" "Reset switch node $ibnode +File: TestTools/extmng.exp" case_setup case_cleanup { + upvar ibnode ibnode + upvar args args + upvar norecords norecords + + global env + + set toolsdir /usr/lib/opa/tools + + local_sh + + set hfi_port [ resolve_ibnode $ibnode ] + set hfi_port_args [ get_hfi_port_args "$hfi_port" ] + set trimmed_ibnode [ trim_opaswitch_hfi_port "$ibnode" ] + set brand [get_switch_brand "$ibnode"] + # use verbose option so we have a predictable output to expect + if { [ string equal "$brand" "OPA"] } { + check_exit_status 60 0 + send_unix_cmd "$toolsdir/opaswquery -t $trimmed_ibnode $hfi_port_args -Q 10" + set out [expect_list_with_punchlist "$ibnode" "Unable to query switch" 120 { "Session ID: [0-9]+" } { "Error" }] + regexp {(Session ID:) ([0-9]+)} $out p1 p2 oldSessID + scan $oldSessID "%d" oldsessionid + check_exit_status 60 0 + send_unix_cmd "$toolsdir/opaswreset $hfi_port_args $args; echo DONE" + if { $norecords } { + expect_list_with_punchlist "$ibnode" "Unable to reboot switch" 60 { "opaswreset completed"} { "Error" } + } else { + expect_list_with_punchlist "$ibnode" "Unable to reboot switch" 300 { "opaswreset completed"} { "Error" } + } + } else { + fail_test "$ibnode: Not an Intel OPA device" + } + + + local_sh_exit + + log_message "$ibnode has been reset ... waiting for return" + # wait 30 secs first, then try up to 7.5 minutes at 10 sec intervals + if { [ string equal "$brand" "OPA"] } { + set sleeptime 18 + } else { + set sleeptime 30 + } + for {set i 0} {$i < 51} {incr i} { + # wait for switch to reboot + if { $i!= 0 } { + log_message "Retrying: $ibnode not yet back online ... waiting for return" + } + sleep $sleeptime + # first wait for local HFI port to come active - 30 seconds + set active [verify_port_active "$ibnode" 30] + if { $active == -1 } { + append_punchlist "$ibnode" "Can not verify reboot - local HFI port not active" + fail_test "$ibnode - can not verify reboot - local HFI port not active" + } + set presence [get_switch_ping "$ibnode" "$hfi_port" 0 "1"] + if { [ string equal "$presence" "is"] } { + break + } + set sleeptime 10 + } + + if { [ string equal "$presence" "not"] } { + fail_test "$ibnode Failed to come back online after reboot" + } elseif { [ string equal "$brand" "OPA"] } { + local_sh + send_unix_cmd "$toolsdir/opaswquery -t $trimmed_ibnode $hfi_port_args -Q 10" + set out [expect_list_with_punchlist "$ibnode" "Unable to query switch" 120 { "Session ID: [0-9]+" } { "Error" }] + regexp {(Session ID:) ([0-9]+)} $out p1 p2 sessID + scan $sessID "%d" sessionid + if { $sessionid > $oldsessionid } { + fail_test "$ibnode did not reboot properly" + } + local_sh_exit + } + } +} +proc test_case_i2c_extmgd_switchgetportconfig { ibnode {fd ""}} { +## +## test_case_i2c_extmgd_switchgetportconfig +## --------------------------- +## test_case to retrieve info about port configurations of externally managed switches +## +## Usage: +## test_case_i2c_extmgd_switchgetportconfig ibnode [fd] +## Arguments: +## ibnode - IB switch node +## fd - file to write config info to +## Returns: +## None +## Additional Information: +## must be used within a test_suite's body, performs test_case calls +## uses case_setup and case_cleanup provided by caller +## no item_setup nor item_cleanup used + + test_case "$ibnode.i2c.extmgd.switchgetportconfig" "retrieve switch $ibnode" "Retrieve port config info $ibnode +File: TestTools/extmng.exp" case_setup case_cleanup { + upvar ibnode ibnode + upvar fd fd + + # use verbose option so we have a predictable output to expect + set out [ get_switch_getportconfig "$ibnode" ] + if { ! [ string equal "$fd" "" ] } { + puts $fd "\n$out" + } + } +} + + +proc test_case_i2c_extmgd_switchinfo { ibnode {fd ""}} { +## +## test_case_i2c_extmgd_switchinfo +## --------------------------- +## test_case to retrieve info from externally managed switch +## +## Usage: +## test_case_i2c_extmgd_info ibnode [fd] +## Arguments: +## ibnode - IB switch node +## fd - file to write config info to +## Returns: +## None +## Additional Information: +## must be used within a test_suite's body, performs test_case calls +## uses case_setup and case_cleanup provided by caller +## no item_setup nor item_cleanup used + + test_case "$ibnode.i2c.extmgd.switchinfo" "retrieve switch $ibnode" "Retrieve switch info node $ibnode +File: TestTools/extmng.exp" case_setup case_cleanup { + upvar ibnode ibnode + upvar fd fd + + # use verbose option so we have a predictable output to expect + set out [get_switch_info "$ibnode"] + if { ! [ string equal "$fd" "" ] } { + puts $fd "\n$out" + } + } +} + +proc test_case_i2c_extmgd_switchhwinfo { ibnode } { +## +## test_case_i2c_extmgd_switchhwinfo +## --------------------------- +## test_case to retrieve hw info from externally managed switch +## +## Usage: +## test_case_i2c_extmgd_hwinfo ibnode +## Arguments: +## ibnode - IB switch node +## Returns: +## None +## Additional Information: +## must be used within a test_suite's body, performs test_case calls +## uses case_setup and case_cleanup provided by caller +## no item_setup nor item_cleanup used + + test_case "$ibnode.i2c.extmgd.switchhwinfo" "retrieve switch $ibnode" "Retrieve switch hwinfo node $ibnode +File: TestTools/extmng.exp" case_setup case_cleanup { + upvar ibnode ibnode + + # use verbose option so we have a predictable output to expect + set brand [get_switch_brand "$ibnode"] + if { [ string equal "$brand" "OPA"] } { + # are we going to implement this? + puts "Function not yet implemented for Intel OPA" + } else { + append_punchlist "$ibnode" "Not an Intel OPA device" + fail_test "$ibnode: Not an Intel OPA device" + } + } +} + +proc test_case_i2c_extmgd_switchhwvpd { ibnode } { +## +## test_case_i2c_extmgd_switchhwvpd +## --------------------------- +## test_case to retrieve hw vpd from externally managed switch +## +## Usage: +## test_case_i2c_extmgd_hwvpd ibnode +## Arguments: +## ibnode - IB switch node +## Returns: +## None +## Additional Information: +## must be used within a test_suite's body, performs test_case calls +## uses case_setup and case_cleanup provided by caller +## no item_setup nor item_cleanup used + + test_case "$ibnode.i2c.extmgd.switchhwvpd" "retrieve switch $ibnode" "Retrieve switch hwvpd node $ibnode +File: TestTools/extmng.exp" case_setup case_cleanup { + upvar ibnode ibnode + + # use verbose option so we have a predictable output to expect + get_switch_hwvpd "$ibnode" + } +} + +proc test_case_i2c_extmgd_switchping { ibnode } { +## +## test_case_i2c_extmgd_switchping +## --------------------------- +## test_case to retrieve hw vpd from externally managed switch +## +## Usage: +## test_case_i2c_extmgd_ping ibnode +## Arguments: +## ibnode - IB switch node +## Returns: +## None +## Additional Information: +## must be used within a test_suite's body, performs test_case calls +## uses case_setup and case_cleanup provided by caller +## no item_setup nor item_cleanup used + + test_case "$ibnode.i2c.extmgd.switchping" "ping switch $ibnode" "Ping switch node $ibnode +File: TestTools/extmng.exp" case_setup case_cleanup { + upvar ibnode ibnode + + set presence [ get_switch_ping "$ibnode" "" 0 ] + if { [ string equal "$presence" "not"] } { + append_punchlist "$ibnode" "Not responding" + fail_test "$ibnode Not Responding" + } else { + log_message "$ibnode: unit is present" + show_message "" + show_message "$ibnode: unit is present" + } + } +} + +proc test_case_i2c_extmgd_switchfwverify { ibnode } { +## +## test_case_i2c_extmgd_switchfwverify +## --------------------------- +## test_case to verify firmware in externally managed switch +## +## Usage: +## test_case_i2c_extmgd_fwverify ibnode +## Arguments: +## ibnode - IB switch node +## Returns: +## None +## Additional Information: +## must be used within a test_suite's body, performs test_case calls +## uses case_setup and case_cleanup provided by caller +## no item_setup nor item_cleanup used + + test_case "$ibnode.i2c.extmgd.switchfwverify" "retrieve switch $ibnode" "Verify firmware node $ibnode +File: TestTools/extmng.exp" case_setup case_cleanup { + upvar ibnode ibnode + upvar args args + upvar norecords norecords + + # use verbose option so we have a predictable output to expect + get_switch_fwverify "$ibnode" + } +} + +proc test_case_ext_mgmt_sw_config { ibnode } { + + global tools_case_status + global env + + test_case "$ibnode.i2c.extmgd.switchconfigure" "configure switch $ibnode" "Configure node $ibnode +File: TestTools/extmng.exp" case_setup case_cleanup { + upvar ibnode ibnode + upvar args args + upvar norecords norecords + + set toolsdir /usr/lib/opa/tools + + local_sh + + set hfi_port [ resolve_ibnode $ibnode ] + set hfi_port_args [ get_hfi_port_args "$hfi_port" ] + set trimmed_ibnode [ trim_opaswitch_hfi_port "$ibnode" ] + # use verbose option so we have a predictable output to expect + + set brand [get_switch_brand "$ibnode"] + if { [ string equal "$brand" "OPA"] } { + set linkWidthSelection $env(LINKWIDTH_SETTING) + + if { [string equal "$linkWidthSelection" "0"] == 0 } { + check_exit_status 60 0 + send_unix_cmd "$toolsdir/opaswconfigure -t $trimmed_ibnode $hfi_port_args -S -C 5 -i $linkWidthSelection" + expect_list_with_punchlist "$ibnode" "Unable to configure switch link width" 60 { "opaswconfigure completed"} { "Error" } + } + + set nodeDescSelection $env(NODEDESC_SETTING) + + if { [string equal "$nodeDescSelection" "0"] == 0 } { + set node_desc [ strip_nodeguid_from_desc "$trimmed_ibnode" ] + set length [string length $node_desc] + if { $length > 0 } { + local_sh + send_unix_cmd "$toolsdir/opaswconfigure -t $trimmed_ibnode $hfi_port_args -S -C 1 -s $node_desc" + expect_list_with_punchlist "$ibnode" "Unable to configure switch node description" 60 { "opaswconfigure completed"} { "Error" } + } + } + + set FMEnabledSelection $env(FMENABLED_SETTING) + + if { [string equal "$FMEnabledSelection" "-1"] == 0 } { + check_exit_status 60 0 + send_unix_cmd "$toolsdir/opaswconfigure -t $trimmed_ibnode $hfi_port_args -S -C 8 -i $FMEnabledSelection" + expect_list_with_punchlist "$ibnode" "Unable to configure switch FM Enabled" 60 { "opaswconfigure completed" } { "Error" } + } + + set linkCRCModeSelection $env(LINKCRCMODE_SETTING) + + if { [string equal "$linkCRCModeSelection" "-1"] == 0 } { + check_exit_status 60 0 + send_unix_cmd "$toolsdir/opaswconfigure -t $trimmed_ibnode $hfi_port_args -S -C 9 -i $linkCRCModeSelection" + expect_list_with_punchlist "$ibnode" "Unable to configure switch link CRC mode" 60 { "opaswconfigure completed" } { "Error" } + } + + } else { + append_punchlist "$ibnode" "Not an Intel OPA device" + fail_test "$ibnode: Not an Intel OPA device" + } + + local_sh_exit + + } +} + +proc test_case_i2c_extmgd_switchcapture { ibnode upload_file } { +## +## test_case_i2c_extmgd_switchcapture +## --------------------------- +## test_case to retrieve capture from externally managed switch +## +## Usage: +## test_case_i2c_extmgd_switchcapture ibnode upload_file +## Arguments: +## ibnode - IB switch node +## upload_file - file to upload too +## Returns: +## None +## Additional Information: +## must be used within a test_suite's body, performs test_case calls +## uses case_setup and case_cleanup provided by caller +## no item_setup nor item_cleanup used + + test_case "$ibnode.i2c.extmgd.switchcapture" "capture switch $ibnode" "Capture switch state node $ibnode +File: TestTools/extmng.exp" case_setup case_cleanup { + upvar ibnode ibnode + upvar upload_file upload_file + + # use verbose option so we have a predictable output to expect + get_switch_capture "$ibnode" "$upload_file" + } +} diff --git a/TestTools/front.sh b/TestTools/front.sh new file mode 100755 index 0000000..21e0d51 --- /dev/null +++ b/TestTools/front.sh @@ -0,0 +1,105 @@ +#!/usr/bin/expect +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] + +## +## Running Test Commands in Shell +## ------------------------------ +## +## Selected TCL procedures from the automated tests +## have been made available in the shell. When run from the shell, +## the actual TCL procedure is still run, with some setup. +## Arguments for each command are identical to those of the TCL version. +## The result from the given command is returned on stdout, (possibly along +## with additional information preceeding it) +## +## The arguments are identical to those provided within TCL, however because +## of quoting differences, shell " or ' quotes should guard each argument +## For example: +## In TCL: some_proc {{1} {my.file}} +## In Sh: some_proc "{1} {my.file}" +## +## The running of such commands in the shell assumes settl and TEST_CONFIG_FILE +## have been setup +## +## At present the following commands are available in the shell: +## some typical uses: + +# This shell script is a simple interface for shell scripts to run the +# a tcl function from the automated test environment. +# typically it is invoked via tcl_proc, which also sets up common +# environment variables such as TCLLIBPATH + +# This script can be linked to filenames correspnding to what ever TCL commands +# need to be available from the shell. +# alternately a tcl function name can be provided as the first argument to +# this script when this script is invoked as "front" +# such as: +# front get_config CFG_HOSTS + +if { ! [ info exists env(TL_DIR) ] || $env(TL_DIR) == "" } { + puts stderr "$argv0: run settl first" + exit 1 +} + +# This is a workaround for MAC, which does not support TCLLIBPATH +# it doesn't hurt on Linux. ibtools.exp sources all our .exp scripts +if { [ file exists $env(TL_DIR)/TestTools/ibtools.exp ] } { + # HostTests + source $env(TL_DIR)/TestTools/ibtools.exp +} else { + # Fast Fabric, TL_DIR is set to /usr/lib/opa/tools + source $env(TL_DIR)/ibtools.exp +} + +global env spawn_id expecting +if { ! [ info exists env(TEST_SHOW_CONFIG) ] } { + set env(TEST_SHOW_CONFIG) no +} + +set spawn_id "" +set expecting "" +set_timeout 60 + +set cmd [file tail $argv0] +if { "$cmd" != "read_config" && [lindex $argv 0] != "read_config" } { + read_config $env(TEST_CONFIG_FILE) +} + +if { "$cmd" == "front" } { + set res [ eval $argv ] +} else { + set res [ eval $cmd $argv ] +} + +if { "$res" != "" } { + puts $res +} diff --git a/TestTools/ib.exp b/TestTools/ib.exp new file mode 100644 index 0000000..06c4a6e --- /dev/null +++ b/TestTools/ib.exp @@ -0,0 +1,147 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] + +# This is an expect (tcl) library of procedures to aid ib testing + +## tcl procedures to support testing: +## ============================================= + +proc test_case_discovered_hosts { host hosts } { +## +## test_case_discovered_hosts +## ------------------- +## execute a test case to determine if hosts can be seen from discovery on +## given host +## +## Usage: +## test_case_discovered_hosts host hosts +## Arguments: +## host - host to test +## hosts - list of hosts expected to be discovered +## Returns: +## 0 - success +## 1 - failure +## Additional Information: +## must be used within a test_suite's body, performs test_case calls +## uses case_setup and case_cleanup provided by caller +## no item_setup nor item_cleanup used + return [ test_case "$host.dsc" "$host can see $hosts" "Verify host can discover $hosts +via /proc/driver/ics_dsc/gids +File: TestTools/ib.exp" case_setup case_cleanup { + upvar host host + upvar hosts hosts + + target_root_sh $host + + set target_stack [ target_get_stack_type "y" "$host"] + + if { "$target_stack" == "OPENIB" } { + send_unix_cmd {type opasaquery} + if { 0 == [ get_exit_status 60 ] } { + #send_unix_cmd "opasaquery -h 0 -p 0 -t fi -o desc 2>&1 |tr 'A-Z' 'a-z' | sed -e 's/^/Node: /'" + send_unix_cmd {opasaquery -h 0 -p 0 -t fi -o desc 2>&1 |tr 'A-Z' 'a-z' | sed -e 's/^/Node: /'} + } else { + #send_unix_cmd {saquery |egrep '^[[:space:]]*NodeDescription\.*'|tr 'A-Z' 'a-z' | sed -e 's/^[[:space:]]*nodedescription\.*/Node: /'} + send_unix_cmd {opasaquery |egrep '^[[:space:]]*NodeDescription\.*'|tr 'A-Z' 'a-z' | sed -e 's/^[[:space:]]*nodedescription\.*/Node: /'} + } + # wait for echo of command so we don't mistake command for any + # similarly named hosts + expect_list 90 {"sed -e" "Node: /'"} {"not found" "unknown" "Error" "cannot" "usage:" "Usage:"} + set expected_host_list {} + # for each host we expect to see a line with $h + # To support OFED hosts, we need to handle names with HCA-# appended to them. + # Ensure that hostnames in the case insensitive manners are supported. + set hosts [ string tolower $hosts ] + + foreach h "$hosts" { + lappend expected_host_list "Node: $h\n|Node: $h hfi1_\[0-9\]+\n" + } + expect_list_orderless 60 0 "$expected_host_list" { "not found" "unknown" "Error" "cannot" "usage:" "Usage:"} + check_exit_status 60 0 + target_root_sh_exit + } else { + target_root_sh_exit + skip_case "This IB stack is not supported" + } + + } ] +} + + +proc test_case_verify_topology { host local_topology_file remote_topology_dir} { +## +## test_case_verify_topology +## ------------------- +## execute a test case to determine if the topology of the cluster has changed +## +## See README file in dsc directory for more information +## +## Usage: +## test_case_verify_topology +## Arguments: +## host - sm host +## local_topolgy_file - path and name of the saved topology file +## remote_topology_dir - where to scp file on the SM host +## Returns: +## 0 - success, no change in topology +## 1 - failure, topology has changed +## Additional Information: +## must be used within a test_suite's body, performs test_case calls +## uses case_setup and case_cleanup provided by caller +## no item_setup nor item_cleanup used + return [ test_case "verifytopology.dsc" "Verify topology of SM $host" "Verify topology of sm $host with $local_topology_file +File: TestTools/ib.exp" case_setup case_cleanup { + upvar host host + upvar local_topology_file local_topology_file + upvar remote_topology_dir remote_topology_dir + + set path [split "$local_topology_file" /] + set topology_file_name [lindex $path [llength $path]-1] + set remote_topology_file [join "$remote_topology_dir $topology_file_name" "/"] + + if { [file exists $local_topology_file] == 0 } { + error "Error: topology file $local_topology_file could not be found" + } + + if { [ catch { exec scp $local_topology_file root@$host:$remote_topology_dir } msg ] } { + error "Failed to scp $local_topology_file to $host:$remote_topology_dir: $msg" + } + + target_root_sh $host + + send_unix_cmd "opareport -o verifynodes -T $remote_topology_file; echo DONE" + expect_list 60 { "Getting" "DONE" } { "[1-9][0-9]* Missing" "[1-9][0-9]* Unexpected" "[1-9][0-9]* Duplicate" "[1-9][0-9]* Different" } + check_exit_status 60 0 + send_unix_cmd "rm -f $remote_topology_file" + + target_root_sh_exit + } ] +} diff --git a/TestTools/ibtools.exp b/TestTools/ibtools.exp new file mode 100644 index 0000000..36b945c --- /dev/null +++ b/TestTools/ibtools.exp @@ -0,0 +1,57 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] + +## This file replaces the use of the TCLLIBPATH environment variable on Mac +## (since the TCLLIBPATH environment variable doesn't work on Mac) +## This file should be sourced by all expect scripts that need to use +## procedures in the following files (when running on Mac). +## +## It won't have effect on Linux, or to be more precise, it won't break code +## on Linux. + +if { [file exists $env(TL_DIR)/TestTools)] } { + # HostTests environment + set ibtools_dir $env(TL_DIR)/TestTools +} else { + # in fastfabric, TL_DIR is set to /usr/lib/opa/tools + set ibtools_dir $env(TL_DIR) +} + +# basic scripts used by FastFabric and HostTests +foreach file { proc_mgr.exp tools.exp target.exp chassis.exp basic.exp ff_function.exp ib.exp extmng.exp install.exp mpi.exp network.exp } { + if { [file exists $ibtools_dir/$file] } { + source $ibtools_dir/$file + } +} +# HostTests only, picks up additional HostTest scripts +if { [file exists $env(TL_DIR)/TestTools/TestOnly/ibtools.exp)] } { + source $env(TL_DIR)/TestTools/TestOnly/ibtools.exp +} diff --git a/TestTools/install.exp b/TestTools/install.exp new file mode 100644 index 0000000..7736765 --- /dev/null +++ b/TestTools/install.exp @@ -0,0 +1,414 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] + +# This is an expect (tcl) library of procedures to aid install testing + +## tcl procedures to support testing of install: +## ============================================= + +proc install_cleanup { } { +## +## install_cleanup +## ------------------- +## cleanup temp files and logs in preparation for a new install scenario +## during an rlogin session +## +## Usage: +## install_cleanup +## Additional Information: +## Must have run target_rlogin and target_su before this +## Returns: +## 0 - success +## -code error on failure + + unix_cmd 60 0 "rm -f /var/log/ics_ib.log" + unix_cmd 60 0 "rm -f /var/log/opa.log" + unix_cmd 60 0 "rm -f /var/log/opamon" + unix_cmd 200 0 "rm -rf IntelOPA-Basic.*" + unix_cmd 200 0 "rm -rf IntelOPA-IFS.*" + unix_cmd 200 0 "rm -rf IntelOPA-Tools*" + unix_cmd 200 0 "rm -rf IntelOPA-Tests.*" + unix_cmd 60 0 "rm -rf /tmp/opa.log.len /tmp/ics_ib.log.len" + + return 0 +} + +proc install_saveloglen { } { +## +## install_saveloglen +## ------------------- +## save log length for use to verify install results +## +## Usage: +## install_saveloglen +## Additional Information: +## Must have run target_rlogin and target_su before this +## Returns: +## 0 - success +## -code error on failure + + foreach log {/var/log/opa.log /var/log/ics_ib.log} { + set log_len "/tmp/[exec basename $log].len" + # use sed to get rid of white space + unix_cmd 60 0 "cat $log 2>/dev/null|wc -l | sed -e 's/\[ \\t]//g' > $log_len" + } + + return 0 +} + +proc install_rmloglen { } { +## +## install_rmloglen +## ------------------- +## remove log length files created by install_saveloglen +## +## Usage: +## install_rmloglen +## Additional Information: +## Must have run target_rlogin and target_su before this +## Returns: +## 0 - success +## -code error on failure + + unix_cmd 60 0 "rm -f /tmp/opa.log.len" + unix_cmd 60 0 "rm -f /tmp/ics_ib.log.len" + + return 0 +} + +proc install_expect_drivers { driver_list { skip_done 0 }} { +## +## install_expect_drivers +## ---------------------- +## Check the proper drivers are loaded during an rlogin session +## +## Usage: +## install_expect_drivers driver_list [skip_done] +## Arguments: +## driver_list - list of drivers/ULP names +## skip_done - skip wait for 'Done Installing IB' message +## 0=wait for message +## 1=don't wait for message, default is 0 +## Returns: +## 0 - success +## -code error on failure +## Additional Information: +## Does not care what order the drivers are loaded in + + expect_progress 600 { "Preparing" "Building" } { "Installing" {OPA Software} } { + "Unable" + "Error" + "Failure" + "invalid" + "Usage" + } + set list {} + foreach driver $driver_list { + lappend list "Installing $driver" + } + if { "$list" != "" } { + # allow 5 minutes per Driver + expect_progress_orderless 300 { "Preparing" "Building" "installing" "Updating" "Copying" } 0 $list { + "Unable" + "Error" + "Failure" + "invalid" + } + } + if { ! $skip_done } { + # "Unable" message could occur if A0 HCA being installed + # allow some extra time for depmod and firmware update + # firmware update can be slow on MAC or if pciconf1 device is used + expect_progress 300 { {[0-9]} "---" "Updating" "Copying" "installing" } { {Done Installing OPA} } { + "Error" + "Failure" + "invalid" + } + } + + return 0 +} + +proc install_uninstall { {uninstall 1} {remove_config 0} { dir "" } } { +## +## install_uninstall +## ----------------- +## uninstall any existing version of IB software on the system during an rlogin session +## +## Usage: +## install_uninstall [ uninstall [remove_config [dir]] ] +## Arguments: +## uninstall - should existing installation be uninstalled, default is yes +## remove_config - should existing config files be removed, default is no +## dir - directory to find uninstall in (default is to only use +## opaconfig/ics_ib) +## Returns: +## 0 - success +## -code error on failure + + set toolsdir /usr/lib/opa/tools + + if { $uninstall } { + # use ics_ib to remove if possible + unix_cmd 240 "" {if [ -f /sbin/opaconfig ]; then /sbin/opaconfig -u; elif [ -f /sbin/ics_ib ]; then /sbin/ics_ib -u; fi } + } + + if { $uninstall && "$dir" != "" } { + unix_cmd 240 "" "test -d $dir && (cd $dir; ./INSTALL -u )" + } + if { $remove_config } { + set target_os_type [target_get_os_type] + + unix_cmd 60 "" {rm -rf /etc/opa /etc/sysconfig/ipoib.cfg /etc/sysconfig/ics_srp.cfg /etc/sysconfig/ics_inic.cfg /etc/sysconfig/mpi.param /etc/sysconfig/mpi.param.safe /etc/sysconfig/mpi.param.microbench $toolsdir/opafastfabric.conf /etc/dat.conf} + unix_cmd 60 "" {rm -rf /etc/opa-fm/opafm.xml /etc/infiniband/openib.conf /etc/opamon.conf} + unix_cmd 60 "" {rm -rf /etc/sysconfig/network-scripts/ifcfg-eioc[0-9]* /etc/sysconfig/network-scripts/ifcfg-ib[0-9]*} + unix_cmd 60 "" {rm -rf /etc/sysconfig/network/ifcfg-eioc[0-9]* /etc/sysconfig/network/ifcfg-ib[0-9]*} + unix_cmd 60 "" {rm -rf /etc/dapl} + } + + return 0 +} + +proc install_getready { target {uninstall 1} { remove_config 0 } { cleanup 1 } { dir "" }} { +## +## install_getready +## ---------------- +## prepare for an install test by login'ing +## cleaning up from any prior install, uninstalling any prior software +## +## Usage: +## install_getready target [uninstall [remove_config [cleanup [dir] ]]] +## +## Arguments: +## target - hostname to rlogin to +## uninstall - should existing installation be uninstalled, default is yes +## remove_config - should existing config files be removed, default is no +## cleanup - should existing installation files and install logs be removed, default is yes +## dir - directory to find uninstall in (default is to only use +## opaconfig/ics_ib) +## Returns: +## 0 - success +## -code error om failure +## Additional Information: +## setup file is sent to /tmp/mysetup.stp + + global env + + # become root user on target system + target_root_sh $target + + install_uninstall $uninstall $remove_config $dir + + if { $cleanup } { + install_cleanup + } else { + install_saveloglen + } + + return 0 +} + +proc install_all { target drivers {uninstall 1} {remove_config 0 } {cleanup 1} {cd_device ""} {release ""} { install_opt "-a" } { from_dir "." } {product "IntelOPA-Basic"}} { +## +## install_all +## ----------------- +## perform a basic installation of all drivers +## +## Usage: +## install_all target drivers [uninstall [remove_config [cleanup [cd_device [release [install_opt [from_dir]]]]]]] +## Arguments: +## target - hostname to rlogin to +## drivers - list of driver names expected to be installed +## uninstall - should existing installation be uninstalled, default is yes +## remove_config - should existing config files be removed, default is no +## cleanup - should existing installation files and install logs be removed, default is yes +## cd_device - CD device to load from, default is ftp from get_ftp_dir +## release - if ! "", scp $product.$release.tgz to target and install +## install_opt - install options, default is "-a" +## from_dir - where to get $product.*.tgz for scp install +## Returns: +## 0 - success +## -code error on failure +## Additional Information: +## This establishes and closes an rlogin session + + global env + + if { "$cd_device" == "" && "$release" == "" } { + # will untar below into this directory + set dir [get_install_dir "$product"] + } elseif { "$cd_device" != "" } { + set dir $cd_device + } else { + log_message "scp $from_dir/$product.$release.tgz root@\[$target\]:" + if { [ catch { exec scp $from_dir/$product.$release.tgz root@\[$target\]: } err_str2 ] != 0 } { + error "scp $from_dir/$product.$release.tgz root@\[$target\]: failed: $err_str2" + } + set dir $product.$release + # can't cleanup, will remove the file we just copied + set cleanup 0 + } + + install_getready $target $uninstall $remove_config $cleanup $dir + + if { "$cd_device" == "" && "$release" == "" } { + if { ! [ info exists env(CFG_FTP_SERVER) ] + || "$env(CFG_FTP_SERVER)" == ""} { + fail_test "Release version not specified" + } + # Fast Fabric always sets release and sets CFG_FTP_SERVER="" + # hence for fast fabric we never use ftp + set release [get_release] + scp_get_file "$env(CFG_SCP_SERVER)" "$env(CFG_SCP_USERID)" "[get_ftp_dir $target]/$product.$release.tgz" "$product.$release.tgz" + send_unix_cmd "tar xvfz $product.$release.tgz; echo DONE" + expect_progress 120 { "doc" "include" "config" "bin" "lib" } { "echo DONE" "DONE" } { "Error " "No such" } + check_exit_status 360 0 + } elseif { "$cd_device" == "" && "$release" != "" } { + unix_cmd 200 0 "rm -rf $product.$release" + send_unix_cmd "tar xvfz $product.$release.tgz; echo DONE" + expect_progress 120 { "doc" "include" "config" "bin" "lib" } { "echo DONE" "DONE" } { "Error " "No such" } + check_exit_status 360 0 + } + + unix_cmd 60 0 "cd $dir" + send_unix_cmd "./INSTALL $install_opt" + + set_timeout 60 + + install_expect_drivers "$drivers" + + check_exit_status 60 0 + + install_check_logs + + install_rmloglen + + child_cleanup + + return 0 +} + +proc install_check_logs { { log_list { /var/log/ics_ib.log /var/log/opa.log } } { retcode "1" } } { +## +## install_check_logs +## ----------------- +## check there are no errors or warnings in the installation log +## during an rlogin session +## +## Usage: +## install_check_logs [log_list] [retcode] +## Arguments: +## log_list - list of log filenames to get, default is opa.log ics_ib.log +## retcode - expected return code from egrep, 0=errors/warnings in log +## 1=no errors/warnings in log, defaults to 1 +## Returns: +## 0 - success +## -code error on failure + + foreach log $log_list { + send_unix_cmd "\[ -f $log \];" + if { [ get_exit_status 60 ] == 0 } { + set log_len "/tmp/[exec basename $log].len" + send_unix_cmd "\[ -s $log_len \];" + if { [ get_exit_status 60 ] == 0 } { + # allow Unable due to message for A0 HCA + unix_cmd 60 $retcode "tail -n +`cat $log_len` $log|egrep 'Abort|corrupted|Can not'" + } else { + unix_cmd 60 $retcode "egrep 'Abort|corrupted|Can not' $log" + } + } + } + + return 0 +} + +proc install_getready2 { target } { +## +## install_getready2 +## ---------------- +## prepare for an install test by login'ing +## cleaning up from any prior install +## +## Usage: +## install_getready2 target +## +## Arguments: +## target - hostname to rlogin to +## Returns: +## 0 - success +## -code error om failure + + # become root user on target system + target_root_sh $target $usercode $password $root_password + + install_cleanup + + return 0 +} + +proc install_get_logs { target { log_list { ics_ib.log opa.log } } { log_dir /var/log } } { +## +## install_get_logs +## ------------------------ +## Get the various installation log file +## +## Usage: +## install_get_logs target [log_list] [log_dir] +## Arguments: +## target - hostname to rlogin to +## log_list - list of log filenames to get, default is opa.log ics_ib.log +## log_dir - directory to get log files from, default is /var/log +## Additional Information: +## The login session to the target system is terminated to allow an +## ftp to occur to transfer the file +## This is intended for use as a failure_code handler for test cases +## Errors in getting the log files are ignored (in case the logs don't +## exist) +## The log files gotten are of the form: +## $log_dir/$log +## where $log is an individual entry in log_list +## They are transfered to: +## $test_tmp/$log + + global env + global test_tmp + + # ignore errors in case the log doesn't exist + foreach log $log_list { + # cleanup any previous sessions + catch { child_cleanup } + #catch { ftp_mget_files $target $env(CFG_USERNAME) $env(CFG_PASSWORD) $log_dir $log $test_tmp ascii } + catch { exec scp root@\[$target\]:$log_dir/$log $test_tmp/ } + } + # cleanup any previous sessions + catch { child_cleanup } +} + diff --git a/TestTools/line_equivalent.py b/TestTools/line_equivalent.py new file mode 100644 index 0000000..2a161f7 --- /dev/null +++ b/TestTools/line_equivalent.py @@ -0,0 +1,61 @@ +import sys +import os +import tempfile +dict = {0:0} + +# Help Text +def usage(): + print "Usage: python line_equivalent.py \n" + print "The tool is used to find the equivalent line number for stripped file" + print "Input: file name, line number of stripped file (customer copy) and buildFeatureDefs file" + print "Output: line number in the code used by developers" + print "Note: make sure the buildFeatureDefs is the same that was used to create the customer release" + +# Create a hash table line_num_of_stripped_file:line_num_of_orig_file +def create_table(file_name, buildFeatureDefs): + # Create a temporary file, to store unifdef output + temp_file = tempfile.NamedTemporaryFile() + # Use unifdef to strip the file based on buildFeatureDefs, + # This temporary file should look same as the one in RPM + cmd="unifdef -f %s %s > %s"%(buildFeatureDefs, file_name, temp_file.name) + os.system(cmd) + # Create table + line_num_temp_file=0 + line_num_orig_file=0 + with open(file_name) as orig_file, temp_file: + for orig_line in iter(orig_file.readline, ''): + line_num_orig_file += 1 + last_pos = temp_file.tell() + if orig_line != temp_file.readline(): + temp_file.seek(last_pos) + continue + line_num_temp_file += 1 + dict[line_num_temp_file] = line_num_orig_file + +# Query hash_table +def query_table(line_number): + if int(line_number) in dict: + print dict[int(line_number)] + else: + print "Invalid query: Line number do not exist in the stripped file" + +# main +if len(sys.argv) != 4: + usage() + exit() + +# Collect Input +file_name = sys.argv[1] +line_number = sys.argv[2] +buildFeatureDefs=sys.argv[3] + +# Check if file exists +if not os.path.isfile(file_name): + print "Invalid file path - %s\nprovide complete path to the file"%file_name + exit(1) +if not os.path.isfile(buildFeatureDefs): + print "Invalid file path - %s\nprovide complete path to the file"%buildFeatureDefs + exit(1) + +create_table(file_name, buildFeatureDefs) +query_table(line_number) diff --git a/TestTools/mpi.exp b/TestTools/mpi.exp new file mode 100644 index 0000000..4fe36e9 --- /dev/null +++ b/TestTools/mpi.exp @@ -0,0 +1,773 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] + +# This is an expect (tcl) library of procedures to aid mpi testing + +## tcl procedures to support testing: +## ============================================= + +proc build_mpi_hosts { file host_list } { +# create the mpi_hosts file on the present host +# Usage: +# build_mpi_hosts file host_list +# Arguments: +# file - file to build +# host_list - list of hosts to put in file + global env + + set host_names {} + #max number of characters to write to the file over one + #ssh connection. + set buf_size 500 + set current_block_size 0 + + send_unix_cmd "> $file" + expect_unix_prompt 60 + + foreach h $host_list { + # use IPoIB names + # When called by FastFabric, CFG_IPOIB_SUFFIX is set to "" + # and host_list is already translated as needed + set host_entry "[host_basename $h]$env(CFG_IPOIB_SUFFIX)\n" + set host_length [string length $host_entry] + + if { [expr $current_block_size + $host_length ] < $buf_size } { + #adding the current host $h does not exceed the character limit + #append it to the current block of host_names + append host_names $host_entry + set current_block_size [expr $current_block_size + $host_length] + } else { + #adding the current host $h will exceed the character limit, write + #already queued up host_names and reset for the next block + send_unix_cmd "printf \"$host_names\" >> $file" + expect_unix_prompt 60 + set host_names {} + append host_names $host_entry + set current_block_size $host_length + } + } + + #writing the final batch of entries + send_unix_cmd "printf \"$host_names\" >> $file" + expect_unix_prompt 60 +} + +proc build_mpd_hosts { file host host_list } { +# create the mpd_hosts file on the present host +# Usage: +# build_mpd_hosts file host_list +# Arguments: +# file - file to build +# host_list - list of hosts to put in file +# +# Return: +# The length of the mpd file, in lines. + global env + + foreach h $host_list { + set hn [host_basename $h] + if { [info exists mpd($hn)] } { + set mpd($hn) [expr $mpd($hn) + 1] + } else { + set mpd($hn) 1 + } + } + # unwind the mpd array + unix_cmd 10 0 "> $file" + foreach hn [array names mpd] { + if { $hn == "$host" } { + continue + } + unix_cmd 10 0 "echo $hn >> $file" + } + unix_cmd 10 0 "echo $host >> $file" + return [array size mpd] +} + +proc running_mpi_int_tests { } { +# Determine if running MPI Integration tests, in which case +# caller will need to get_mpi_info using $env(MPITYPE) +# +# Returns: +# 0 - in Fastfabric, no need to get_mpi_info, MPICH_PREFIX defined +# 1 - in integration tests, get_mpi_info using $env(MPITYPE) + global env + + if { ! [ info exists env(MPICH_PREFIX) ] + || [ string equal "$env(MPICH_PREFIX)" "" ] + || ( [ info exists env(DEV_INT_TESTS) ] + && [ string equal "$env(DEV_INT_TESTS)" "y" ] ) } { + # only occurs for int tests + # this is a little ugly, MPITYPE is passed in env + if { ! [ info exists env(MPITYPE) ] + || [ string equal "$env(MPITYPE)" "" ] } { + set info "MPITYPE not set" + return -code error -errorinfo $info $info + } + return 1 + } else { + return 0 + } +} + +proc determine_mpitype { appdir } { +# Determine based on MPICH_PREFIX in $appdir/.prefix which MPI type is selected +# Only used in FastFabric since integration tests get this fron MPITYPE env +# must match algorithm used in prepare_run to select MPD_MODE +# +# Usage: +# determine_mpitype appdir +# Arguments: +# appdir - directory where mpi_apps built, .prefix in here will be used +# Returns: +# mpirunner name +# error if unable to determine or unsupported MPI selected + global env + + if { [ catch {set env(MPICH_PREFIX) [exec cat "$appdir/.prefix" 2>/dev/null] } ] != 0 || "$env(MPICH_PREFIX)" == "" } { + return -code error -errorinfo "mpi_apps not built" "mpi_apps not built" + } + if { ! [file exists $env(MPICH_PREFIX)/] } { + return -code error -errorinfo "$env(MPICH_PREFIX) not found, please rebuild mpi_apps against an MPI currently on the system" "$env(MPICH_PREFIX) not found, please rebuild mpi_apps against an MPI currently on the system" + } + if { [file exists $env(MPICH_PREFIX)/bin/tune] } { + set mpitype "intelmpi" + } elseif { [file exists $env(MPICH_PREFIX)/bin/mpichversion] } { + set mpitype "mvapich2_mpirun" + } elseif { [file exists "$env(MPICH_PREFIX)/bin/ompi_info"] } { + set mpitype "openmpi" + } else { + # unknown MPI + return -code error -errorinfo "MPI selected is not supported by this operation: $env(MPICH_PREFIX)" "MPI selected is not supported by this operation: $env(MPICH_PREFIX)" + } + return "$mpitype" +} + +proc test_case_run_mvapich2_mpirun_mpi_app { transport host host_list timelimit dir mpi_cmd mpi_args show_perf case_tag} { +## +## test_case_run_mvapich2_mpirun_mpi_app +## ------------------------- +## run an mpi application initiated by host with host_list processes +## used OFED mvapich2 with mpirun (instead of MPD) +## +## Usage: +## test_case_run_mvapich2_mpirun_mpi_app transport host host_list timelimit dir mpi_cmd mpi_args show_perf case_tag +## Arguments: +## transport - not used for OFED mpich2 +## host - host initiate mpi run +## host_list - hosts/processes to run +## dir - directory (if not absolute assumed relative to tests_dir) with command +## timelimit - time to allow between output by command +## mpi_cmd - MPI appl command +## mpi_args - application args +## show_perf - should results be shown as performance +## case_tag - suffix for test case name +## $env(MPICH_PREFIX) - path to mpi installation +## Returns: +## Additional Information: +## must be used within a test_suite's body, performs test_case calls +## uses case_setup and case_cleanup provided by caller +## no item_setup nor item_cleanup used + + global tools_case_status + + upvar mpitype mpitype + test_case "$host.$case_tag" "$host starts $mpitype $mpi_cmd" "$host starts $mpitype mpi command $mpi_cmd with args: $mpi_args +against hosts: $host_list +File: TestTools/mpi.exp" case_setup case_cleanup { + upvar host host + upvar host_list host_list + upvar dir dir + upvar timelimit timelimit + upvar mpi_cmd mpi_cmd + upvar mpi_args mpi_args + upvar show_perf show_perf + upvar perf perf + upvar transport transport + global env + set paramfile "" + + target_root_sh $host + set target_stack [ target_get_stack_type "y" "$host"] + + if { "$target_stack" != "OPENIB" } { + target_root_sh_exit + skip_case "OFED MVAPICH2 tests not supported for this IB stack" + } + set target_os_type [target_get_os_type] + + #set param_file "/etc/sysconfig/mpi.param" + + if { [ string range $dir 0 0 ] != "/" } { + unix_cmd 60 0 "cd [get_tests_dir]" + } + unix_cmd 60 0 "cd $dir" + + # build it in place, allows other mpi runs to occur for other apps + # at same time as this, provided not same app with same initiator + build_mpi_hosts "mpi_hosts" $host_list + set np [llength $host_list] + + # for now we have one setting which applies to all MPIs + # it typically adds env variables to the command so any not + # applicable to the given MPI will be ignored + if { [ info exists env(CFG_MPI_ENV) ] } { + set add_mpi_env "$env(CFG_MPI_ENV)" + } else { + set add_mpi_env "" + } + + if { [ running_mpi_int_tests ] } { + # this is a little ugly, MPITYPE is passed in env + set mpi_info [get_mpi_info "$env(MPITYPE)"] + set env(MPICH_PREFIX) [lindex "$mpi_info" 1 ] + append add_mpi_env " " [lindex "$mpi_info" 5 ] + } + + if { ! [ info exists env(FF_MPI_APPS_DIR) ] + || [ string equal "$env(FF_MPI_APPS_DIR)" "" ] } { + set env(FF_MPI_APPS_DIR) "/usr/src/opa/mpi_apps" + } + + if { [ catch {unix_cmd 20 0 "test -e $env(FF_MPI_APPS_DIR)/mvapich2.params"} res ] == 0 } { + # mvapich2 1.6 no longer supports the -paramfile option + # we handle it by exporting MPI_CMD_ARGS in our param script + #set paramfile "-paramfile $env(FF_MPI_APPS_DIR)/mvapich2.params" + unix_cmd 20 0 ". $env(FF_MPI_APPS_DIR)/mvapich2.params" + unix_cmd 20 "" {echo MPI_CMD_ARGS="$MPI_CMD_ARGS"} + } else { + unix_cmd 20 0 "export MPI_CMD_ARGS=" + } + send_unix_cmd "$env(MPICH_PREFIX)/bin/mpirun_rsh $paramfile -np $np -hostfile mpi_hosts \$MPI_CMD_ARGS $add_mpi_env ./$mpi_cmd $mpi_args; echo DONE" + if { $show_perf } { + set perf_var perf + } else { + set perf_var "" + } + expect_progress $timelimit {[0-9]} { "echo DONE" {[0-9]} "DONE" } { "FAIL" "DISCONNECT" "[tT]imeout" "ERROR" "usage:" "Usage:" "THH" "No such" "rejected" "Assertion" "Fatal" "Abort:" "No route to host" "Killing" "Abort signal" "egmentation fault" "died unexpectedly" "Error" "unable to launch"} $perf_var + expect_unix_prompt 60 + } + test_execute {} { + if { "$tools_case_status" == "okay" } { + if { $show_perf } { + show_performance "$mpitype $mpi_cmd for $host_list:\n$perf" + } + } elseif { "$tools_case_status" != "skip" } { + sleep 10 + } + } +} + +proc test_case_run_mvapich2_mpi_app { transport host host_list timelimit dir mpi_cmd mpi_args show_perf case_tag} { +## +## test_case_run_mvapich2_mpi_app +## ------------------------- +## run an mpi application initiated by host with host_list processes +## +## Usage: +## test_case_run_mvapich2_mpi_app transport host host_list timelimit dir mpi_cmd mpi_args show_perf case_tag +## Arguments: +## transport - not used for OFED mpich +## host - host initiate mpi run +## host_list - hosts/processes to run +## dir - directory (if not absolute assumed relative to tests_dir) with command +## timelimit - time to allow between output by command +## mpi_cmd - MPI appl command +## mpi_args - application args +## show_perf - should results be shown as performance +## case_tag - suffix for test case name +## $env(MPICH_PREFIX) - path to mpi installation +## Returns: +## Additional Information: +## must be used within a test_suite's body, performs test_case calls +## uses case_setup and case_cleanup provided by caller +## no item_setup nor item_cleanup used + + global tools_case_status + + upvar mpitype mpitype + test_case "$host.$case_tag" "$host starts $mpitype $mpi_cmd" "$host starts $mpitype mpi command $mpi_cmd with args: $mpi_args \nagainst hosts: $host_list \nFile: TestTools/mpi.exp" case_setup case_cleanup { + upvar host host + upvar host_list host_list + upvar dir dir + upvar timelimit timelimit + upvar mpi_cmd mpi_cmd + upvar mpi_args mpi_args + upvar show_perf show_perf + upvar perf perf + upvar transport transport + global env + + target_root_sh $host + set target_stack [ target_get_stack_type "y" "$host"] + + if { "$target_stack" != "OPENIB" } { + target_root_sh_exit + skip_case "OFED MVAPICH2 tests not supported for this IB stack" + } + set target_os_type [target_get_os_type] + + # for now we have one setting which applies to all MPIs + # it typically adds env variables to the command so any not + # applicable to the given MPI will be ignored + if { [ info exists env(CFG_MPI_ENV) ] } { + set add_mpi_env "$env(CFG_MPI_ENV)" + } else { + set add_mpi_env "" + } + + if { [ running_mpi_int_tests ] } { + # this is a little ugly, MPITYPE is passed in env + set mpi_info [get_mpi_info "$env(MPITYPE)"] + set env(MPICH_PREFIX) [lindex "$mpi_info" 1 ] + append add_mpi_env " " [lindex "$mpi_info" 5 ] + } + + + #set param_file "/etc/sysconfig/mpi.param" + + if { [ string range $dir 0 0 ] != "/" } { + unix_cmd 60 0 "cd [get_tests_dir]" + } + unix_cmd 60 0 "cd $dir" + + + # stop mpd is if was running + stop_all_mpds + + foreach h $host_list { + host_unix_cmd 30 0 $h "'rm -f /etc/mpd.conf && echo MPD_SECRETWORD=password > /etc/mpd.conf && chown root:root /etc/mpd.conf && chmod 600 /etc/mpd.conf && cp /etc/mpd.conf /root/.mpd.conf'" + } + + # use mpd hosts toggle the mpd + build_mpd_hosts "/etc/mpd.hosts" $host $host_list + + set np [llength $host_list] + # start mpd + send_unix_cmd "/usr/sbin/opacmdall -f /etc/mpd.hosts \"cat /etc/mpd.hosts | wc -l\"; echo DONE" + expect_list 60 { "echo DONE" "DONE" } { "failed" "error" "fault" } + check_exit_status 20 0 + + send_unix_cmd "$env(MPICH_PREFIX)/bin/mpirun -n $np $add_mpi_env -hostfile /etc/mpd.hosts ./$mpi_cmd $mpi_args;echo DONE" + if { $show_perf } { + set perf_var perf + } else { + set perf_var "" + } + expect_progress $timelimit {[0-9]} { "echo DONE" {[0-9]} "DONE" } { "FAIL" "DISCONNECT" "timeout" "abort" "ERROR" "usage:" "Usage:" "THH" "No such" "rejected" "Assertion" "Fatal" "Abort:" "No route to host" "Killing" "Abort signal" "forked process failed" "open failed for" "egmentation fault" "died unexpectedly" "aborting" "unable to launch"} $perf_var + expect_unix_prompt 60 + } + test_execute {} { + if { "$tools_case_status" == "okay" } { + if { $show_perf } { + show_performance "$mpitype $mpi_cmd for $host_list:\n$perf" + } + } elseif { "$tools_case_status" != "skip" } { + sleep 10 + } + } +} + +proc test_case_run_intelmpi_mpi_app { transport host host_list timelimit dir mpi_cmd mpi_args show_perf case_tag} { +## +## test_case_run_intel_mpi_app +## ------------------------- +## run an mpi application initiated by host with host_list processes +## +## Usage: +## test_case_run_intel_mpi_app transport host host_list timelimit dir mpi_cmd mpi_args show_perf case_tag +## Arguments: +## transport - not used for intelmpi +## host - host initiate mpi run +## host_list - hosts/processes to run +## dir - directory (if not absolute assumed relative to tests_dir) with command +## timelimit - time to allow between output by command +## mpi_cmd - MPI appl command +## mpi_args - application args +## show_perf - should results be shown as performance +## case_tag - suffix for test case name +## $env(MPICH_PREFIX) - path to mpi installation +## Returns: +## Additional Information: +## must be used within a test_suite's body, performs test_case calls +## uses case_setup and case_cleanup provided by caller +## no item_setup nor item_cleanup used + + global tools_case_status + upvar mpitype mpitype + + + test_case "$host.$case_tag" "$host starts $mpitype $mpi_cmd" "$host starts $mpitype mpi command $mpi_cmd with args: $mpi_args \nagainst hosts: $host_list \nFile: TestTools/mpi.exp" case_setup case_cleanup { + upvar host host + upvar host_list host_list + upvar dir dir + upvar timelimit timelimit + upvar mpi_cmd mpi_cmd + upvar mpi_args mpi_args + upvar show_perf show_perf + upvar perf perf + upvar transport transport + global env + + target_root_sh $host + set target_stack [ target_get_stack_type "y" "$host"] + + if { "$target_stack" != "OPENIB" } { + target_root_sh_exit + skip_case "IntelMPI tests not supported for this IB stack" + } + + set target_os_type [target_get_os_type] + + if { [ string range $dir 0 0 ] != "/" } { + unix_cmd 60 0 "cd [get_tests_dir]" + } + unix_cmd 60 0 "cd $dir" + + # build it in place, allows other mpi runs to occur for other apps + # at same time as this, provided not same app with same initiator + build_mpi_hosts "mpi_hosts" $host_list + set np [llength $host_list] + + # for now we have one setting which applies to all MPIs + # it typically adds env variables to the command so any not + # applicable to the given MPI will be ignored + if { [ info exists env(CFG_MPI_ENV) ] } { + set add_mpi_env "$env(CFG_MPI_ENV)" + } else { + set add_mpi_env "" + } + + if { ! [ info exists env(FF_MPI_APPS_DIR) ] + || [ string equal "$env(FF_MPI_APPS_DIR)" "" ] } { + set env(FF_MPI_APPS_DIR) "/usr/src/opa/mpi_apps" + } + + if { [ catch {unix_cmd 20 0 "test -e $env(FF_MPI_APPS_DIR)/intelmpi.params"} res ] == 0 } { + unix_cmd 20 0 ". $env(FF_MPI_APPS_DIR)/intelmpi.params" + unix_cmd 20 "" {echo MPI_CMD_ARGS="$MPI_CMD_ARGS"} + } else { + unix_cmd 20 0 "export MPI_CMD_ARGS=" + } + + send_unix_cmd "$env(MPICH_PREFIX)/bin/mpirun -np $np -hostfile mpi_hosts \$MPI_CMD_ARGS $add_mpi_env ./$mpi_cmd $mpi_args; echo DONE" + if { $show_perf } { + set perf_var perf + } else { + set perf_var "" + } + expect_progress $timelimit {[0-9]} { "echo DONE" {[0-9]} "DONE" } { "FAIL" "DISCONNECT" "[tT]imeout" "ERROR" "usage:" "Usage:" "THH" "No such" "rejected" "Assertion" "Fatal" "Abort:" "No route to host" "Killing" "Abort signal" "egmentation fault" "died unexpectedly" "unable to launch"} $perf_var + expect_unix_prompt 60 + + } + test_execute {} { + if { "$tools_case_status" == "okay" } { + if { $show_perf } { + show_performance "$mpitype $mpi_cmd for $host_list:\n$perf" + } + } elseif { "$tools_case_status" != "skip" } { + sleep 10 + } + } + +} +proc test_case_run_openmpi_mpi_app { transport host host_list timelimit dir mpi_cmd mpi_args show_perf case_tag { mpi_env_args "" } } { +## +## test_case_run_openmpi_mpi_app +## ------------------------- +## run an mpi application initiated by host with host_list processes +## +## Usage: +## test_case_run_openmpi_mpi_app transport host host_list timelimit dir mpi_cmd mpi_args show_perf case_tag +## Arguments: +## transport - not used for openmpi +## host - host initiate mpi run +## host_list - hosts/processes to run +## dir - directory (if not absolute assumed relative to tests_dir) with command +## timelimit - time to allow between output by command +## mpi_cmd - MPI appl command +## mpi_args - application args +## show_perf - should results be shown as performance +## case_tag - suffix for test case name +## $env(MPICH_PREFIX) - path to mpi installation +## Returns: +## Additional Information: +## must be used within a test_suite's body, performs test_case calls +## uses case_setup and case_cleanup provided by caller +## no item_setup nor item_cleanup used + + global tools_case_status + + upvar mpitype mpitype + test_case "$host.$case_tag" "$host starts $mpitype $mpi_cmd" "$host starts $mpitype mpi command $mpi_cmd with args: $mpi_args +against hosts: $host_list +File: TestTools/mpi.exp" case_setup case_cleanup { + upvar host host + upvar host_list host_list + upvar dir dir + upvar timelimit timelimit + upvar mpi_cmd mpi_cmd + upvar mpi_args mpi_args + upvar show_perf show_perf + upvar perf perf + upvar transport transport + upvar mpi_env_args mpi_env_args + global env + + target_root_sh $host + set target_stack [ target_get_stack_type "y" "$host"] + + if { "$target_stack" != "OPENIB" } { + target_root_sh_exit + skip_case "OpenMPI tests not supported for this IB stack" + } + set target_os_type [target_get_os_type] + + if { [ string range $dir 0 0 ] != "/" } { + unix_cmd 60 0 "cd [get_tests_dir]" + } + unix_cmd 60 0 "cd $dir" + + # build it in place, allows other mpi runs to occur for other apps + # at same time as this, provided not same app with same initiator + build_mpi_hosts "mpi_hosts" $host_list + set np [llength $host_list] + + # for now we have one setting which applies to all MPIs + # it typically adds env variables to the command so any not + # applicable to the given MPI will be ignored + if { [ info exists env(CFG_MPI_ENV) ] } { + set add_mpi_env "$env(CFG_MPI_ENV)" + } else { + set add_mpi_env "" + } + + if { [ running_mpi_int_tests ] } { + # this is a little ugly, MPITYPE is passed in env + set mpi_info [get_mpi_info "$env(MPITYPE)"] + set env(MPICH_PREFIX) [lindex "$mpi_info" 1 ] + append add_mpi_env " " [lindex "$mpi_info" 5 ] + set api [lindex "$mpi_info" 4 ] + + if { [string match "$api" "PSM"] } { + if { ! [ info exists env(CFG_PSM_ENV) ] + || [ string equal "$env(CFG_PSM_ENV)" "" ] } { + set mpiapi_env "" + } else { + set mpiapi_env "$env(CFG_PSM_ENV)" + } + } elseif {[string match "$api" "verbs"] } { + if { ! [ info exists env(CFG_VERBS_ENV) ] + || [ string equal "$env(CFG_VERBS_ENV)" "" ] } { + set mpiapi_env "" + } else { + set mpiapi_env "$env(CFG_VERBS_ENV)" + } + } else { + set mpiapi_env "" + } + append add_mpi_env " " $mpi_env_args + } else { + set mpiapi_env "" + } + # change env from var=value to -x var=value + regsub -all {([A-Za-z0-9_]+=[^[:space:]])} "$add_mpi_env" {-x \0} openmpi_env + + if { ! [ info exists env(FF_MPI_APPS_DIR) ] + || [ string equal "$env(FF_MPI_APPS_DIR)" "" ] } { + set env(FF_MPI_APPS_DIR) "/usr/src/opa/mpi_apps" + } + + if { [ catch {unix_cmd 20 0 "test -e $env(FF_MPI_APPS_DIR)/openmpi.params"} res ] == 0 } { + unix_cmd 60 0 ". $env(FF_MPI_APPS_DIR)/openmpi.params" + unix_cmd 20 "" {echo MPI_CMD_ARGS="$MPI_CMD_ARGS"} + } else { + unix_cmd 20 0 "export MPI_CMD_ARGS=" + } + + send_unix_cmd "$env(MPICH_PREFIX)/bin/mpirun $mpiapi_env -np $np -allow-run-as-root --map-by node -machinefile mpi_hosts \$MPI_CMD_ARGS $openmpi_env ./$mpi_cmd $mpi_args; echo DONE" + + if { $show_perf } { + set perf_var perf + } else { + set perf_var "" + } + expect_progress $timelimit {[0-9]} { "echo DONE" {[0-9]} "DONE" } { "FAIL" "DISCONNECT" "[tT]imeout" "ERROR" "usage:" "Usage:" "THH" "No such" "rejected" "Assertion" "Fatal" "Abort:" "No route to host" "Killing" "Abort signal" "Failed to find or execute" "exiting without calling" "egmentation fault" "died unexpectedly" "more processes than the ppr" "revise the conflict and try again" "unable to launch" } $perf_var + expect_unix_prompt 60 + } + test_execute {} { + if { "$tools_case_status" == "okay" } { + if { $show_perf } { + show_performance "$mpitype $mpi_cmd for $host_list:\n$perf" + } + } elseif { "$tools_case_status" != "skip" } { + sleep 10 + } + } +} + +# stop all mpds of any flavor that might be running. +proc stop_all_mpds { } { + + global env + set mpi2dir "/usr/local/mpich2/bin" + set impidir "$env(CFG_INTEL_INSTALL_DIR)/bin" + set mpichdir "$env(MPICH_PREFIX)/bin" + + if { [ catch { unix_cmd 20 0 "$mpi2dir/mpdtrace >/dev/null 2>&1" } res ] == 0 } { + unix_cmd 20 0 "$mpi2dir/mpdallexit" + } + + if { [ catch { unix_cmd 20 0 "$impidir/mpdtrace >/dev/null 2>&1" } res ] == 0 } { + unix_cmd 20 0 "$impidir/mpdallexit" + } + + if { [ catch { unix_cmd 20 0 "$mpichdir/mpdtrace >/dev/null 2>&1" } res ] == 0 } { + unix_cmd 20 0 "$mpichdir/mpdallexit" + } +} + +# Note: not used by FastFabric, only automated tests use +# extract info from an OFED mpitype string +# returns a list: { mpirunner MPICH_PREFIX testdir_prefix compiler API {add_mpi_env}} +# must be logged in to target host to get_mpich_prefix +proc get_mpi_info { mpitype {get_mpich_prefix 1}} { + # mpitype is MPIRUNNER_COMPILER_SUFFIX + # _SUFFIX is optional (_hfi or nothing) + + # first look for _opp suffix + if { [ string match "*_opp" "$mpitype" ] } { + set mpitype [string range $mpitype 0 [ expr [ string length $mpitype ] - 5]] + set add_mpi_env "PSM_PATH_REC=opp" + set api_suffix "_opp" + } else { + set add_mpi_env "" + set api_suffix "" + } + # look for _hfi suffix + if { [ string match "*_hfi" "$mpitype" ] } { + set mpiname_suffix "_hfi" + set mpipath_suffix "-hfi" + set mpitype [string range $mpitype 0 [ expr [ string length $mpitype ] - 5]] + set api "PSM$api_suffix" + } else { + set mpiname_suffix "" + set mpipath_suffix "" + # Path Record query and api_suffix N/A + set api "verbs" + } + # next pull off compiler + if {![regexp "(.*)_(\[^_]+)" "$mpitype" line mpirunner mpicompiler]} { + set info "Cannot parse $mpitype into mpirunner_mpicompiler" + return -code error -errorinfo $info $info + } + + # special: mvapich2_mpirun has same testdir and mpich_prefix as mvapich2 + if { [ string equal "$mpirunner" "mvapich2_mpirun" ] } { + set mpiname "mvapich2" + } else { + set mpiname "$mpirunner" + } + + # mvapich mpirunner is called mvapich1 + if { [ string equal "$mpirunner" "mvapich" ] } { + set mpirunner "mvapich1" + } + + set mpifullname "${mpiname}_${mpicompiler}${mpiname_suffix}" + if { $get_mpich_prefix } { + # determine mpich_prefix + set mpi_version [target_get_registered_mpi_version "$mpifullname" ] + set mpich_prefix "/usr/mpi/$mpicompiler/$mpiname-$mpi_version$mpipath_suffix" + } else { + set mpich_prefix "unknown" + } + + set testdir_prefix "$mpifullname" + + return "$mpirunner $mpich_prefix $testdir_prefix $mpicompiler $api {$add_mpi_env}" +} + +proc test_case_run_mpi_app { mpitype transport host host_list timelimit dir mpi_cmd { mpi_args "" } {show_perf 0 } {case_tag ""} { mpi_env_args "" } } { +## +## test_case_run_mpi_app +## --------------------- +## run an mpi application initiated by host with host_list processes +## +## Usage: +## test_case_run_mpi_app host host_list timelimit dir mpi_cmd [mpi_args] [show_perf] [case_tag] +## Arguments: +## mpitype - mvapich1, mvapich2, openmpi, intel, or variations +## transport - transport layer for MPI, choices are: +## For intel_mpi: sock or rdma +## For others: default +## host - host to initiate mpi run +## host_list - hosts/processes to run +## dir - directory (if not absolute assumed relative to tests_dir) with command +## timelimit - time to allow between output by command +## mpi_cmd - MPI appl command +## mpi_args - application args +## show_perf - should results be shown as performance +## case_tag - suffix for test case name, default is mpi_cmd argument value +## Returns: +## Additional Information: +## must be used within a test_suite's body, performs test_case calls +## uses case_setup and case_cleanup provided by caller +## no item_setup nor item_cleanup used + global env + + if { [ string range $dir 0 0 ] != "/" } { + # Automated Integration tests + set mpi_info [get_mpi_info "$mpitype" 0] + set mpirunner_type [lindex "$mpi_info" 0 ] + set testdir_prefix [lindex "$mpi_info" 2 ] + set compiler [lindex "$mpi_info" 3 ] + set api [lindex "$mpi_info" 4 ] + set case_prefix "${api}_${compiler}_" + + set newdir "${testdir_prefix}_$dir" + set mpirunner "test_case_run_${mpirunner_type}_mpi_app" + # to avoid large changes to existing code, we pass MPITYPE in env + # so test cases can use it to determine MPICH_PREFIX while logged into + # target host + set env(MPITYPE) "$mpitype" + } else { + # Fast Fabric + set newdir "$dir" + set mpirunner "test_case_run_${mpitype}_mpi_app" + set case_prefix "" + } + if { [string equal "$case_tag" "" ] } { + set case_tag "$mpi_cmd" + } + set case_tag "$case_prefix$case_tag" + eval $mpirunner $transport $host [list $host_list] $timelimit "{$newdir}" $mpi_cmd [list $mpi_args] $show_perf $case_tag $mpi_env_args +} diff --git a/TestTools/network.exp b/TestTools/network.exp new file mode 100644 index 0000000..c1b8867 --- /dev/null +++ b/TestTools/network.exp @@ -0,0 +1,115 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] + +# This is an expect (tcl) library of procedures to aid network testing +# These functions provide support for pre-built test cases which can be +# provided arguments to indicate the network to be tested + +## tcl procedures to support testing: +## ============================================= + +proc test_case_ping1 { host desthosts ulp suffix mtu { punchlist 0 } } { +## +## test_case_ping1 +## ------------------- +## execute a test case to perform basic 1 packet pings +## from host to each of desthosts +## +## Usage: +## test_cases_ping1 host desthosts ulp suffix mtu [punchlist] +## Arguments: +## host - host to initiate ping from +## desthosts - list of hosts to send to +## ulp - protocol being used +## suffix - hostname suffix for network ($env(CFG_IPOIB_SUFFIX), +## or $env(CFG_INIC_SUFFIX) or "") +## Only used for integration tests, when used by FastFabric, set to "" +## mtu - MTU for network +## punchlist - should punchlist be updated on failure (default=0=no) +## Returns: +## nothing +## Additional Information: +## must be used within a test_suite's body, performs test_case calls +## uses case_setup and case_cleanup provided by caller +## no item_setup nor item_cleanup used + + global env + + #Substract 28 from the mtu, 20 Byte IP header and 8 Byte ICMP header + # because we dont want to fragment icmp packet.See PR 111259 + set ping_size [ expr $mtu - 28 ] + + test_case "$host\_ping1" "simple ping from $host" "perform simple 1 packet $ping_size byte pings from $host using $ulp +to $desthosts +File: TestTools/network.exp" case_setup case_cleanup { + upvar host host + upvar ulp ulp + upvar suffix suffix + upvar ping_size ping_size + upvar desthosts desthosts + upvar punchlist punchlist + + target_root_sh $host + set target_os_type [target_get_os_type] + + foreach desthost $desthosts { + # allow ping of self + if { [ catch { set res [ + test_item "$desthost" "$host to $desthost" "simple ping from $host to $desthost" noop noop { + set netdest "[ host_basename $desthost ]$suffix" + send_unix_cmd "/usr/lib/opa/tools/opagetipaddrtype $netdest" + set out [expect_any 60 {"ipv6" "ipv4" } {"Error:" "Usage:"}] + regexp {([ip]+)([A-Za-z0-9]+)} $out iptype + if { $iptype == "ipv4" } { + set PING "ping" + } else { + set PING "ping6" + } + + send_unix_cmd "$PING -W 5 -c 1 -s $ping_size $netdest" + + # AS2.1 ping has slightly different output than 7.3 ping + expect_any 60 { "1 packets transmitted" "1 transmitted" } { "unknown" "refused" "error" "timeout" " 0 packets received" " 0 received" "nreachable" "duplicates" } + expect_any 60 { " 1 received" " 1 packets received" } { "unknown" "refused" "error" "timeout" " 0 packets received" " 0 received" "nreachable" "duplicates" } + expect_any 60 { " 0% loss" "0% packet loss" } { "unknown" "refused" "error" "timeout" " 0 packets received" " 0 received" "nreachable" "duplicates" } + expect_any 60 { "time " "round-trip" } { "unknown" "refused" "error" "timeout" " 0 packets received" " 0 received" "nreachable" "duplicates" } + + check_exit_status 60 0 + } ] } err_str2 ] != 0 || $res != 0 } { + if { $punchlist } { + append_punchlist "$desthost" "unable to ping via $ulp" + } + } + } + + target_root_sh_exit + } +} diff --git a/TestTools/opa_to_xml.exp b/TestTools/opa_to_xml.exp new file mode 100644 index 0000000..448bfb4 --- /dev/null +++ b/TestTools/opa_to_xml.exp @@ -0,0 +1,1343 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] + +# This is an expect (tcl) library of procedures to aid opa stack testing + +package require tdom + +######################################################################################### +# Name : createTextElement +# Input : document tagName tagValue +# Return . Text node +# Description : Creates a text node in the form text +######################################################################################### +proc createTextElement { doc tagName text } { + + set textNode [ $doc createTextNode $text ] + set elem [ $doc createElement $tagName ] + $elem appendChild $textNode + + return $elem +} + +######################################################################################### +# Name : createAttributesElement +# Input : document tagName attributeName1 attributeValue1 ... +# Return . Element with attributes +# Description : Creates an element with attributes, i.e. +# Note : If number of values doesn't match the number of tags an error tag will be +# set in the resulting XML. +######################################################################################### +proc createAttributesElement { doc tagName args } { + + set elem [ $doc createElement $tagName ] + set argsCounter 0 + + foreach arg $args { + incr argsCounter + if { [ expr $argsCounter % 2 ] != 0 } { + set attrName $arg + } else { + $elem setAttribute $attrName $arg + } + } + + if { [ expr $argsCounter % 2 ] != 0 } { + set elem [ createTextElement $doc ERROR "Incorrect number of attributes: $args" ] + } + + return $elem +} + + +######################################################################################### +# Name : open_xml_doc +# Input : xml file +# Return . DOM tree. +# Description : Load a well-formed xml file into memory. +######################################################################################### + +proc open_xml_doc { xmldoc } { + + if { ! [ file exists $xmldoc ] } { + return -code error "ERROR : $xmldoc does not exist in the current location." + } + + set doc [dom parse [tDOM::xmlReadFile $xmldoc] ] + set root [$doc documentElement] + + return $root +} + +######################################################################################### +# Name : run_opareport +# Input : host, output_type = { brnodes, vfinfo } +# Return . results from the opareport command as a DOM tree. +# Description : runs opareport and stores results in result. +######################################################################################### + +proc run_opareport { host arguments } { + + set xmldoc [ run_cmd "exec ssh root@$host opareport $arguments -x" ] + set doc [dom parse $xmldoc] + set result [$doc documentElement] + + return $result +} + +######################################################################################### +# Name : run_opasmaquery +# Input : host, lid, output_type = { slsc, scvlt } +# Return . results from the opasmaquery command for a given HFI. +# Description : runs opasmaquery and stores results in result. +######################################################################################### + +proc run_opasmaquery { host arguments } { + + set result [ run_cmd "exec ssh root@$host opasmaquery $arguments" ] + return $result +} + +######################################################################################### +# Name : run_opasaquery +# Input : output_type = { pkey } +# Return . results from the opasmaquery command for a given HFI. +# Description : runs opasmaquery and stores results in result. +######################################################################################### + +proc run_opasaquery { host arguments } { + + set result [ run_cmd "exec ssh root@$host opasaquery $arguments" ] + return $result +} + +######################################################################################### +# Name : run_opasaquery +# Input : output_type = { pkey } +# Return . results from the opasmaquery command for a given HFI. +# Description : runs opasmaquery and stores results in result. +######################################################################################### + +proc run_opapaquery { host arguments } { + + set result [ run_cmd "exec ssh root@$host opapaquery $arguments 2> /dev/null" ] + return $result +} + +######################################################################################### +# Name : ibaSAQuerySwitchltvToXml +# Input : txt generated from opasmaquery -o switchltv +# Return . DOM object. +# Description : Produce a DOM object (xml) from a formatted text. +######################################################################################### + +proc ibaSAQuerySwitchltvToXml { switchltv_content } { + + set lines [ split $switchltv_content "\n"] + + set doc [ dom createDocument SwitchLTV ] + $doc encoding {iso8859-1} + set root [$doc documentElement] + + set doOnce 0 + + foreach line $lines { + # Look for LID + set rc [ regexp {(LID) +([0-9]+)} $line matched text lid ] + if { $rc == 1 } { + if { $doOnce == 0 } { + set lidNode [ $doc createElement LID ] + $lidNode setAttribute id $lid + $root appendChild $lidNode + set portsNode [ $doc createElement Ports ] + $root appendChild $portsNode + + set doOnce 1 + } + } + + # Look for port + set rc [ regexp {(Port) +([0-9]+)} $line matched text port ] + if { $rc == 1 } { + set portNode [ $doc createElement Port ] + $portNode setAttribute id $port + $portsNode appendChild $portNode + set virtualLanesNode [ $doc createElement VirtualLanes ] + } + + # Look for VL and LTV + set rc [ regexp -nocase {(VL) +([0-9]+) +-> +(0x[0-9a-f]+) +(VL) +([0-9]+) +-> +(0x[0-9a-f]+) +(VL) +([0-9]+) +-> +(0x[0-9a-f]+) +(VL) +([0-9]+) +-> +(0x[0-9a-f]+)} $line matched text vl1 ltv1 matched vl2 ltv2 matched vl3 ltv3 matched vl4 ltv4 ] + if { $rc == 1 } { + + # Four VLs per line, do this 4 times + set vlNode [ $doc createElement VL ] + $vlNode setAttribute id $vl1 ltv $ltv1 + $virtualLanesNode appendChild $vlNode + + set vlNode [ $doc createElement VL ] + $vlNode setAttribute id $vl2 ltv $ltv2 + $virtualLanesNode appendChild $vlNode + + set vlNode [ $doc createElement VL ] + $vlNode setAttribute id $vl3 ltv $ltv3 + $virtualLanesNode appendChild $vlNode + + set vlNode [ $doc createElement VL ] + $vlNode setAttribute id $vl4 ltv $ltv4 + $virtualLanesNode appendChild $vlNode + + if { $vl4 == 31 } { + $portNode appendChild $virtualLanesNode + } + } + } + + #puts "[$root asXML]" + + return $root +} + +######################################################################################### +# Name : ibaSAQuerySwitchltvToXml +# Input : txt generated from opasmaquery -o switchltv +# Return . DOM object. +# Description : Produce a DOM object (xml) from a formatted text. +######################################################################################### + +proc ibaPAQueryVFConfigToXml { output } { + + set lines [ split $output "\n"] + + set doc [ dom createDocument VFConfig ] + $doc encoding {iso8859-1} + + set root [$doc documentElement] + + foreach line $lines { + # Look for VF Name + set rc [ regexp -nocase {(VF name:) +([a-zA-Z0-9_-]+)} $line matched text name ] + if { $rc == 1 } { + set node [ $doc createElement VFname ] + $node appendChild [$doc createTextNode $name ] + $root appendChild $node + } + + # Look for VF SID + set rc [ regexp -nocase {(VF SID:) +(0x[a-fA-F0-9]+)} $line matched text sid ] + if { $rc == 1 } { + set node [ $doc createElement VFsid ] + $node appendChild [$doc createTextNode $sid ] + $root appendChild $node + } + + # Look for number of ports + set rc [ regexp -nocase {(Number ports:) +([0-9]+)} $line matched text numports ] + if { $rc == 1 } { + set node [ $doc createElement NumberOfPorts ] + $node appendChild [$doc createTextNode $numports ] + $root appendChild $node + } + + # Look for ports + set rc [ regexp -nocase {([0-9]+):LID:(0x[0-9A-F]+) +Port:([0-9]+) +GUID:(0x[0-9A-F]+) +NodeDesc: +(.+)} $line matched num lid port guid nodeDesc ] + if { $rc == 1 } { + # Create Ports element only once + if { $num == 1 } { + set portsNode [ $doc createElement Ports ] + } + set node [ $doc createElement Port ] + $node setAttribute id $num LID $lid PortNum $port GUID $guid NodeDesc $nodeDesc + $portsNode appendChild $node + + set numPorts [ $root selectNodes /VFConfig/NumberOfPorts/text() ] + set numPorts [ $numPorts nodeValue ] + + # At the last port, attach it to the root + if { $numPorts == $num } { + $root appendChild $portsNode + } + } + + # Look for Image Number + set rc [ regexp {(Image Number:) +(0x[a-fA-F0-9]+) +Offset: +([0-9]+)} $line matched text imageNum offset ] + if { $rc == 1 } { + set node [ $doc createElement ImageNumber ] + $node setAttribute id $imageNum Offset $offset + $root appendChild $node + } + } + + # puts "[$root asXML]" + + return $root +} + + +######################################################################################### +# Name : ibaSAQueryPkeyToXml +# Input : txt file generated from opasmaquery -o pkey +# Return . DOM object. +# Description : Produce a DOM object (xml) from a formatted txt file. +######################################################################################### + +proc ibaSAQueryPkeyToXml { pkey_content } { + + set delimeter "\n-------------------------------------------------------------------------------\n" + set output [ regsub -all "$delimeter" "$pkey_content" "|" ] + set lids [ split $output "|"] + + # determine lid ids. + + set lidIdList {} + set portIdList {} + array set lidToPortMap {} + set lididcount 0 + + set lididlist {} + set portidlist {} + set pkeylist {} + set result "" + + # break down scraped output. + foreach lid $lids { + set lidid [string trim [ getCmdOutputParameter $lid "LID:" "PortNum:" "true" ] ] + set portid [string trim [ getCmdOutputParameter $lid "PortNum:" "BlockNum:" "true" ] ] + set ports0to7 [string trim [ getCmdOutputParameter $lid "0- 7:" "\n" "false" ] ] + set ports8to15 [string trim [ getCmdOutputParameter $lid "8- 15:" "\n" "false" ] ] + set ports16to23 [string trim [ getCmdOutputParameter $lid "16- 23:" "\n" "false" ] ] + set ports24to31 [string trim [ getCmdOutputParameter $lid "24- 31:" "\n" "false" ] ] + set pkey [ concat $ports0to7 $ports8to15 $ports16to23 $ports24to31] + + lappend lididlist $lidid + lappend portidlist $portid + lappend pkeylist $pkey + } + #create unique lid list + set lididlistunique [ lsort -unique $lididlist ] + + #iterate through lists + foreach innerlid $lididlistunique { + + set result "$result" + + foreach innerinnerlid $lididlist innerport $portidlist innerpkey $pkeylist { + + if {$innerinnerlid == $innerlid} { + set result "$result" + set count 0 + foreach pk $innerpkey { + set result "$result" + set count [expr $count + 1] + } + #close port tag + set result "$result" + } + } + # set currLid $innerlid + set result "$result" + + } + + set result "$result" + + # build DOM tree. + set XML "$result" + set doc [dom parse $XML] + set root [$doc documentElement] + + return $root +} + +######################################################################################### +# Name : getCmdOutputParameter +# Input : paramlabel,nextparamlabel, trim { false/true }, content +# Return . param +# Description : Given a paramlabel and the subsequent label, parse and return the param. +######################################################################################### + +proc getCmdOutputParameter { content paramlabel nextparamlabel trim } { + + set param [ regsub -all "^.*$paramlabel" "$content" "" ] + set param [ regsub -all "$nextparamlabel.*" "$param" "" ] + + if { $trim == "true"} { + set param [ regsub -all "\n|^\s+|\;|,|^:| " "$param" "" ] + return $param + } elseif { $trim == "false"} { + return $param + } else { + return -code error "getCmdOutputParameter :: Invalid trim option." + } + +} + + +######################################################################################### +# Name : ibaSAQueryVfInfoToXml +# Input : txt file generated from opasmaquery -o vfinfo +# Return . DOM object. +# Description : Produce a DOM object (xml) from a formatted txt file. +######################################################################################### + +proc ibaSAQueryVfInfoToXml { vfinfo_content } { + + # build DOM tree. + set XML "" + set doc [dom parse $XML] + set root [$doc documentElement] + + set delimeter "\n-------------------------------------------------------------------------------\n" + set output [ regsub -all "$delimeter" "$vfinfo_content" "|" ] + set vfabrics [ split $output "|"] + + foreach vfabric $vfabrics { + + #determine vfabricids + set vfabricindex [ regsub -all "Name.*" "$vfabric" "" ] + set vfabricindex [ regsub -all "^.*:" "$vfabricindex" "" ] + set vfabricindex [ regsub -all " " "$vfabricindex" "" ] + + #determine Name + set vfabricName [ getCmdOutputParameter $vfabric "Name:" "ServiceId:" "true"] + set result "" + + #for each vfabric, collect the child elements. + foreach innervfabric $vfabrics { + + #determine vfabricids + set innervfabricindex [ regsub -all "Name.*" "$innervfabric" "" ] + set innervfabricindex [ regsub -all "^.*:" "$innervfabricindex" "" ] + set innervfabricindex [ regsub -all " " "$innervfabricindex" "" ] + + if {$vfabricindex == $innervfabricindex} { + + #determine SerivceId + set vfabricServiceId [ getCmdOutputParameter $innervfabric "ServiceId:" "MGID:" "true" ] + + # determine MGID + set vfabricmgid [ getCmdOutputParameter $innervfabric "MGID:" "PKey:" "true" ] + + # determine PKey + set vfabricpkey [ getCmdOutputParameter $innervfabric "PKey:" "SL:" "true" ] + + # determine SL + set vfabricsl [ getCmdOutputParameter $innervfabric "SL:" "Select:" "true" ] + + # determine Select + set vfabricsselect [ getCmdOutputParameter $innervfabric "Select:" "PktLifeTimeMult:" "true" ] + + # determine MaxMtu + set vfabricsmaxmtu [ getCmdOutputParameter $innervfabric "MaxMtu:" "MaxRate:" "true" ] + + # determine MaxRate + set vfabricsmaxrate [ getCmdOutputParameter $innervfabric "MaxRate:" "Options:" "true" ] + + # determine options + set vfabricsoptions [ getCmdOutputParameter $innervfabric "Options:" "QOS:" "true" ] + + # determine QOS + set vfabricsqos [ getCmdOutputParameter $innervfabric "QOS:" "\n" "true" ] + + # build xml. + set result "$result$vfabricServiceId" + set result "$result$vfabricmgid" + set result "$result$vfabricpkey" + set result "$result$vfabricsl" + set result "$result" + set result "$result$vfabricsmaxmtu" + set result "$result$vfabricsmaxrate" + set result "$result$vfabricsoptions" + set result "$result$vfabricsqos" + + } + + } + set result "$result" + + $root appendXML $result + + } + + return $root + +} + +######################################################################################### +# Name : ibaSAQueryNodeToXml +# Input : txt generated from opasmaquery -o node +# Return . DOM object. +# Description : Produce a DOM object (xml) from a formatted txt file. +######################################################################################### + +proc ibaSAQueryNodeToXml { lid_content } { + + # build DOM tree. + set XML "" + set doc [dom parse $XML] + set root [$doc documentElement] + + set delimeter "\n-------------------------------------------------------------------------------\n" + set output [ regsub -all "$delimeter" "$lid_content" "|" ] + set lids [ split $output "|"] + + foreach lid $lids { + + #determine lid + set lidId [ getCmdOutputParameter $lid "LID:" "Type:" "true" ] + + #determine Type + set lidType [ getCmdOutputParameter $lid "Type:" "Name:" "true" ] + + #determine Name + set lidName [ getCmdOutputParameter $lid "Name:" "\n" "true" ] + + # determine Lid: + + set result "" + + #for each vfabric, collect the child elements. + foreach innerlid $lids { + + #determine lid + set innerlidId [ getCmdOutputParameter $innerlid "LID:" "Type:" "true" ] + + if {$lidId == $innerlidId} { + + #determine Ports + set lidPort [ getCmdOutputParameter $innerlid "Ports:" "PortNum:" "true" ] + + # determine PortNum + set lidPortNum [ getCmdOutputParameter $innerlid "PortNum:" "PartitionCap:" "true" ] + + # determine PartitionCap + set lidPartitionCap [ getCmdOutputParameter $innerlid "PartitionCap:" "\n" "true" ] + + # determine NodeGuid + set lidNodeGuid [ getCmdOutputParameter $innerlid "NodeGuid:" "PortGuid:" "true" ] + + # determine PortGuid + set lidPortGuid [ getCmdOutputParameter $innerlid "PortGuid:" "\n" "true" ] + + # determine BaseVersion + set lidBaseVersion [ getCmdOutputParameter $innerlid "BaseVersion:" "SmaVersion" "true" ] + + # determine SmaVersion + set lidSmaVersion [ getCmdOutputParameter $innerlid "SmaVersion:" "VendorID:" "true" ] + + # determine VendorID + set lidVendorID [ getCmdOutputParameter $innerlid "VendorID:" "DeviceId:" "true" ] + + # determine Revision + set lidRevision [ getCmdOutputParameter $innerlid "Revision:" "\n" "true" ] + + # build xml. + set result "$result$lidPort" + set result "$result$lidPortNum" + set result "$result$lidPartitionCap" + set result "$result$lidNodeGuid" + set result "$result$lidPortGuid" + set result "$result$lidBaseVersion" + set result "$result$lidSmaVersion" + set result "$result$lidVendorID" + set result "$result$lidRevision" + + } + + } + set result "$result" + + $root appendXML $result + + } + + return $root + +} + +######################################################################################### +# Name : ibaSAQueryLinkToXml +# Input : txt generated from opasmaquery -o link +# Return . DOM object. +# Description : Produce a DOM object (xml) from a formatted txt file. +######################################################################################### + +proc ibaSAQueryLinkToXml { link_content } { + # build DOM tree. + set XML "" + set doc [dom parse $XML] + set root [$doc documentElement] + + set delimeter "\n" + set output [ regsub -all "$delimeter" "$link_content" "|" ] + set links [ split $output "|"] + + foreach link $links { + + #srclid + set srcLid [ getCmdOutputParameter $link "LID:" " -" "true" ] + #dstlid + set dstLid [ getCmdOutputParameter $link "$srcLid ->" "Port:" "true" ] + #srcport + set srcPort [ getCmdOutputParameter $link "Port:" " ->" "true" ] + #dstport + set dstPort [ getCmdOutputParameter $link "$srcPort ->" "\n" "true" ] + + #dumpvar $dstLid 0 false + + set result "" + + $root appendXML $result + + } + + return $root +} + +######################################################################################### +# Name : ibaSAQuerySwinfoToXml +# Input : txt generated from opasaquery -o swinfo +# Return . DOM object. +# Description : Produce a DOM object (xml) from a formatted txt file. +######################################################################################### + +proc ibaSAQuerySwinfoToXml { swinfo_content } { + + # build DOM tree. + set XML "" + set doc [dom parse $XML] + set root [$doc documentElement] + + set delimeter "\n-------------------------------------------------------------------------------\n" + set output [ regsub -all "$delimeter" "$swinfo_content" "|" ] + set swinfo [ split $output "|"] + + foreach sw $swinfo { + + # Determine Switch LID + set lid [ getCmdOutputParameter $swinfo "LID:" "\n" "true"] + + # Determing LinearFDBCap + set linearfdbcap [ getCmdOutputParameter $swinfo "LinearFDBCap:" "LinearFDBTop:" "true"] + # Determing LinearFDBTop + set linearfdbtop [ getCmdOutputParameter $swinfo "LinearFDBTop:" "MCFDBCap:" "true"] + # Determing MCFDBCap + set mcfdbcap [ getCmdOutputParameter $swinfo "MCFDBCap:" "MCFDBTop:" "true"] + # Determing MCFDBTop + set mcfdbtop [ getCmdOutputParameter $swinfo "MCFDBTop:" "\n" "true"] + # Determing Capability + set capability [ getCmdOutputParameter $swinfo "Capability:" ": " "true"] + # Determing PartEnfCap + set partenfcap [ getCmdOutputParameter $swinfo "PartEnfCap:" "PortStateChange:" "true"] + # Determing PortStateChange + set portstatechange [ getCmdOutputParameter $swinfo "PortStateChange:" "SwitchLifeTime:" "true"] + # Determing SwitchLifeTime + set switchlifetime [ getCmdOutputParameter $swinfo "SwitchLifeTime:" "\n" "true"] + # Determing PortGroupCap + set portgroupcap [ getCmdOutputParameter $swinfo "PortGroupCap:" "PortGroupTop:" "true"] + # Determing PortGroupTop + set portgrouptop [ getCmdOutputParameter $swinfo "PortGroupTop:" "\n" "true"] + # Determing IPAddrIPV6 + set ipaddripv6 [ getCmdOutputParameter $swinfo "IPAddrIPV6:" "\n" "true"] + # Determing IPAddrIPV4 + set ipaddripv4 [ getCmdOutputParameter $swinfo "IPAddrIPV4:" "\n" "true"] + # Determing Supported RoutingMode + set routingmode_supported [ getCmdOutputParameter $swinfo "RoutingMode.Supported:" "RoutingMode.Enabled:" "true"] + # Determing RoutingMode Enable + set routingmode_enabled [ getCmdOutputParameter $swinfo "RoutingMode.Enabled:" "\n" "true"] + # Determing AdaptiveRouting Enable + set adaptiverouting_enabled [ getCmdOutputParameter $swinfo "AdaptiveRouting: Enable:" "Pause:" "true"] + # Determing AR Pause + set adaptiverouting_pause [ getCmdOutputParameter $swinfo "Pause:" "Algorithm:" "true"] + # Determing AR Algorithm + set adaptiverouting_algorithm [ getCmdOutputParameter $swinfo "Algorithm:" "Frequency:" "true"] + # Determing AR Frequency + set adaptiverouting_frequency [ getCmdOutputParameter $swinfo "Frequency:" "LostRoutesOnly:" "true"] + # Determing AR LostRoutesOnly + set adaptiverouting_lostroutesonly [ getCmdOutputParameter $swinfo "LostRoutesOnly:" "\n" "true"] + # Determing CapabilityMask + set capabilitymask_addrrangeconfig [ getCmdOutputParameter $swinfo "CapabilityMask: IsAddrRangeConfigSupported:" "IsAdaptiveRoutingSupported:" "true"] + # Determing AR Support + set capabilitymask_adaptiverouting [ getCmdOutputParameter $swinfo "IsAdaptiveRoutingSupported:" "\n" "true"] + + # Build XML + set result "" + + set result "$result$linearfdbcap" + set result "$result$linearfdbtop" + set result "$result$mcfdbcap" + set result "$result$mcfdbtop" + set result "$result$capability" + set result "$result$partenfcap" + set result "$result$portstatechange" + set result "$result$switchlifetime" + set result "$result$portgroupcap" + set result "$result$portgrouptop" + set result "$result$ipaddripv6" + set result "$result$ipaddripv4" + + set result "$result" + set result "$result$routingmode_supported" + set result "$result$routingmode_enabled" + set result "$result" + + set result "$result" + set result "$result$adaptiverouting_enabled" + set result "$result$adaptiverouting_pause" + set result "$result$adaptiverouting_algorithm" + set result "$result$adaptiverouting_frequency" + set result "$result$adaptiverouting_lostroutesonly" + set result "$result" + + set result "$result" + set result "$result$capabilitymask_addrrangeconfig" + set result "$result$capabilitymask_adaptiverouting" + set result "$result" + + set result "$result" + + $root appendXML $result + } + + #puts "[$root asXML]" + return $root + +} + +######################################################################################### +# Name : ibaSAQueryPathRecordToXml +# Input : txt generated from opasaquery -o portinfo +# Return . DOM object. +# Description : Produce a DOM object (xml) from a formatted txt file. +######################################################################################### + +proc ibaSAQueryPathRecordToXml { path_content } { + + # build DOM tree. + set XML "" + set doc [dom parse $XML] + set root [$doc documentElement] + + set delimeter "\n-------------------------------------------------------------------------------\n" + set output [ regsub -all "$delimeter" "$path_content" "|" ] + set pathrecord [ split $output "|"] + set numPaths 0 + + foreach path $pathrecord { + incr numPaths + + #determine source to destination pair + set slid [ getCmdOutputParameter $path "SLID:" "DLID:" "true"] + set dlid [ getCmdOutputParameter $path "DLID:" "Reversible:" "true"] + set pkey [ getCmdOutputParameter $path "PKey:" "\n" "true"] + set result "" + + + # Determine SGID + set sgid [ getCmdOutputParameter $path "SGID:" "\n" "true"] + + # Determine DGID + set dgid [ getCmdOutputParameter $path "DGID:" "\n" "true"] + + # Determine Reversible ("Y" or "N") + set reversible [ getCmdOutputParameter $path "Reversible:" "PKey" "true"] + + # Determine SL + set sl [ getCmdOutputParameter $path "SL:" "Mtu:" "true"] + + # Determine Mtu + set mtu [ getCmdOutputParameter $path "Mtu:" "Rate:" "true"] + + # Determine Rate + set rate [ getCmdOutputParameter $path "Rate:" "PktLifeTime:" "true"] + + # Determine PktLifeTime + set pktlifetime [ getCmdOutputParameter $path "PktLifeTime" "Pref:" "true"] + + # Determine Pref + set pref [ getCmdOutputParameter $path "Pref:" "\n" "true"] + + # build xml. + set result "$result$sgid" + set result "$result$dgid" + set result "$result$reversible" + set result "$result$pkey" + set result "$result$sl" + set result "$result$mtu" + set result "$result$rate" + set result "$result$pktlifetime" + set result "$result$pref" + + set result "$result" + + $root appendXML $result + + } + + $root appendXML "$numPaths" + + return $root +} + + + +######################################################################################### +# Name : ibaSAQueryPortInfoToXml +# Input : txt generated from opasaquery -o portinfo +# Return . DOM object. +# Description : Produce a DOM object (xml) from a formatted txt file. +######################################################################################### + +proc ibaSAQueryPortInfoToXml { port_content } { + set lines [ split $port_content "\n"] + + set doc [ dom createDocument PortInfo ] + $doc encoding {iso8859-1} + + set root [$doc documentElement] + + set generateNewPort 1 + set portNum_dec {} + + foreach line $lines { + # Skip empty lines + set rc [ regexp {^$} $line matched ] + if { $rc == 1 } { + continue + } + + if { $generateNewPort == 1 } { + set portNode [ $doc createElement Port ] + $root appendChild $portNode + set generateNewPort 0 + } + + set rc [ regexp {PortLID: +(0x[0-9a-fA-F]+) +PortNum: +(0x[0-9a-fA-F]+) +\((\s*[0-9]+\s*)\)} $line matched plid portNum portNum_dec] + if { $rc == 1 } { + $portNode appendChild [ createTextElement $doc PortLID $plid ] + $portNode appendChild [ createTextElement $doc PortNum $portNum_dec ] + } + + set rc [ regexp {^Subnet: +([0-9a-fA-F]+$)} $line matched subnet ] + if { $rc == 1 } { + $portNode appendChild [ createTextElement $doc Subnet $subnet ] + } + + set rc [ regexp {LocalPort: +([0-9]+) +PortState: +(.+)} $line matched locPort portState ] + if { $rc == 1 } { + $portNode appendChild [ createTextElement $doc LocalPort $locPort ] + $portNode appendChild [ createTextElement $doc PortState $portState ] + } + + set rc [ regexp {PhysicalState: +(.+)} $line matched physState ] + if { $rc == 1 } { + $portNode appendChild [ createTextElement $doc PhysicalState $physState ] + } + + set rc [ regexp {IsSMConfigurationStarted: +(.+[^ ]) +NeighborNormal: +(.+)} $line matched smStarted neighbor ] + if { $rc == 1 } { + $portNode appendChild [ createTextElement $doc IsSMConfigurationStarted $smStarted ] + $portNode appendChild [ createTextElement $doc NeighborNormal $neighbor ] + } + + set rc [ regexp {BaseLID: +([0-9a-zA-Z]+) +SMLID: +(0x[0-9a-fA-F]+)} $line matched baseLid smLid ] + if { $rc == 1 } { + $portNode appendChild [ createTextElement $doc BaseLID $baseLid ] + $portNode appendChild [ createTextElement $doc SMLID $smLid ] + } + + set rc [ regexp {LMC: +([0-9]+) +SMSL: +([0-9]+)} $line matched lmc smsl ] + if { $rc == 1 } { + $portNode appendChild [ createTextElement $doc LMC $lmc ] + $portNode appendChild [ createTextElement $doc SMSL $smsl ] + } + + set rc [ regexp {PortType: +(.+)[^ ] +LimtRsp/Subnet: +([0-9]+) +([a-zA-Z]+), +([0-9]+) +([a-zA-Z]+)} $line matched portType lmtRsp lmtRspUom subnet subnetUom ] + if { $rc == 1 } { + $portNode appendChild [ createTextElement $doc PortType $portType ] + $portNode appendChild [ createTextElement $doc LimtRsp_Subnet "$lmtRsp$lmtRspUom,$subnet$subnetUom" ] + } + + set rc [ regexp {M_KEY: +(0x[0-9a-fA-F]+) +Lease: +([0-9]+) +([a-zA-Z]+) +Protect: +(.+)} $line matched mkey lease leaseUOM protect ] + if { $rc == 1 } { + $portNode appendChild [ createTextElement $doc M_KEY $mkey ] + $portNode appendChild [ createTextElement $doc Lease $lease$leaseUOM ] + $portNode appendChild [ createTextElement $doc Protect $protect ] + } + + set rc [ regexp {LinkWidth +Act: +([0-9a-zA-Z_-]+) +Sup: +(.+) +En: (.+)} $line matched act sup en ] + if { $rc == 1 } { + $portNode appendChild [ createAttributesElement $doc LinkWidth Act $act Sup [ string trim $sup ] En $en ] + } + + set rc [ regexp {LinkWidthDnGrd +Act: +([0-9a-zA-Z_-]+) +Sup: +(.+) +En: (.+)} $line matched act sup en ] + if { $rc == 1 } { + $portNode appendChild [ createAttributesElement $doc LinkWidthDnGrd Act $act Sup [ string trim $sup ] En $en ] + } + + set rc [ regexp {LinkSpeed +Act: +([0-9a-zA-Z_-]+) +Sup: +(.+) +En: (.+)} $line matched act sup en ] + if { $rc == 1 } { + $portNode appendChild [ createAttributesElement $doc LinkSpeed Act $act Sup [ string trim $sup ] En $en ] + } + + set rc [ regexp {PortLinkMode +Act: +([0-9a-zA-Z_-]+) +Sup: +(.+) +En: (.+)} $line matched act sup en ] + if { $rc == 1 } { + $portNode appendChild [ createAttributesElement $doc PortLinkMode Act $act Sup [ string trim $sup ] En $en ] + } + + set rc [ regexp {PortLTPCRCMode +Act: +([0-9a-zA-Z_-]+) +Sup: +(.+) +En: (.+)} $line matched act sup en ] + if { $rc == 1 } { + $portNode appendChild [ createAttributesElement $doc PortLTPCRCMode Act $act Sup [ string trim $sup ] En $en ] + } + + set rc [ regexp {NeighborMode +MgmtAllowed: +([0-9a-zA-Z_-]+) +FWAuthBypass: +([0-9a-zA-Z_-]+) +NeighborNodeType: +([0-9a-zA-Z_-]+)} $line matched mgmtAllowd authBypass neighborType ] + if { $rc == 1 } { + $portNode appendChild [ createAttributesElement $doc NeighborMode MgmtAllowed $mgmtAllowd FWAuthBypass $authBypass NeighborNodeType $neighborType ] + } + + set rc [ regexp {NeighborNodeGuid: +(0x[0-9a-fA-F]+)} $line matched guid ] + if { $rc == 1 } { + $portNode appendChild [ createTextElement $doc NeighborNodeGuid $guid ] + } + + set rc [ regexp {Capability: +(0x[0-9a-fA-F]+): *(.*)} $line matched number tag ] + if { $rc == 1 } { + $portNode appendChild [ createTextElement $doc Capability $number:$tag ] + } + + set rc [ regexp {Capability3: +(0x[0-9a-fA-F]+): *(.*)} $line matched number tag ] + if { $rc == 1 } { + $portNode appendChild [ createTextElement $doc Capability3 $number:$tag ] + } + + set rc [ regexp {VLs Active: +(0x[0-9a-fA-F]+)} $line matched number ] + if { $rc == 1 } { + $portNode appendChild [ createTextElement $doc VLs_Active $number ] + } + + set rc [ regexp {VL: +Cap +(0x[0-9a-fA-F]+) +HighLimit +(0x[0-9a-fA-F]+) +PreemptLimit +(0x[0-9a-fA-F]+)} $line matched cap highLimit preemptLimit ] + if { $rc == 1 } { + $portNode appendChild [ createAttributesElement $doc VL Cap $cap HighLimit $highLimit PreemptLimit $preemptLimit ] + } + + set rc [ regexp {VLs Active: +(0x[0-9a-fA-F]+)} $line matched number ] + if { $rc == 1 } { + $portNode appendChild [ createTextElement $doc VLs_Active $number ] + } + + set rc [ regexp {MulticastMask: +(0x[0-9a-fA-F]+) +CollectiveMask: +(0x[0-9a-fA-F]+)} $line matched mmask cmask ] + if { $rc == 1 } { + $portNode appendChild [ createTextElement $doc MulticastMask $mmask ] + $portNode appendChild [ createTextElement $doc CollectiveMask $cmask ] + } + + set rc [ regexp {P_Key Enforcement +In: +([a-zA-Z]+) +Out: +([a-zA-Z]+)} $line matched inVal outVal ] + if { $rc == 1 } { + $portNode appendChild [ createAttributesElement $doc P_Key_Enforcement In $inVal Out $outVal ] + } + + set rc [ regexp {MulticastPKeyTrapSuppressionEnabled: +([0-9]+) +ClientReregister +([0-9]+)} $line matched val1 val2 ] + if { $rc == 1 } { + $portNode appendChild [ createTextElement $doc MulticastPKeyTrapSuppressionEnabled $val1 ] + $portNode appendChild [ createTextElement $doc ClientReregister $val2 ] + } + + set rc [ regexp {PortMode +ActiveOptimize: +([a-zA-Z]+) +PassThru: +([a-zA-Z]+) +VLMarker: +([a-zA-Z]+)\s*} $line matched val1 val2 val3 ] + if { $rc == 1 } { + $portNode appendChild [ createAttributesElement $doc PortMode ActiveOptimize $val1 PassThru $val2 VLMarker $val3 ] + } + + # This belongs to the previous element + set rc [ regexp {\s+16BTrapQuery:\s+([a-zA-Z]+)\s*} $line matched val1 ] + if { $rc == 1 } { + set portModeNode [ $doc selectNodes {//PortInfo/Port[PortNum=$portNum_dec and PortLID=$plid]/PortMode }] + $portModeNode setAttribute TrapQuery16BT $val1 + } + + set rc [ regexp {FlitCtrlInterleave +Distance Max: +([0-9]+) +Enabled: +([0-9]+)} $line matched val1 val2 ] + if { $rc == 1 } { + $portNode appendChild [ createAttributesElement $doc FlitCtrlInterleave Distance_Max $val1 Enabled $val2 ] + } + + # This belongs to the previous element + set rc [ regexp {MaxNestLevelTxEnabled: +([0-9]+) +MaxNestLevelRxSupported: +([0-9]+)} $line matched val1 val2 ] + if { $rc == 1 } { + set portModeNode [ $doc selectNodes {//PortInfo/Port[PortNum=$portNum_dec and PortLID=$plid]/FlitCtrlInterleave } ] + $portModeNode setAttribute MaxNestLevelTxEnabled $val1 MaxNestLevelRxSupported $val2 + } + + # PR144729 Change MinInitial and Mintail output format from 0x00 to 0, otherwise can't set variable FlitCtrlPreemption properly. + set rc [ regexp {FlitCtrlPreemption +MinInitial: +([0-9]+) +MinTail: +([0-9]+) +LargePktLim: +(0x[0-9a-fA-F]+)} $line matched val1 val2 val3 ] + if { $rc == 1 } { + $portNode appendChild [ createAttributesElement $doc FlitCtrlPreemption MinInitial $val1 MinTail $val2 LargePktLim $val3 ] + } + + # This belongs to the previous element + set rc [ regexp {SmallPktLimit: +(0x[0-9a-fA-F]+) +MaxSmallPktLimit +(0x[0-9a-fA-F]+) +PreemptionLimit: +(0x[0-9a-fA-F]+)} $line matched val1 val2 val3 ] + if { $rc == 1 } { + set portModeNode [ $doc selectNodes {//PortInfo/Port[PortNum=$portNum_dec and PortLID=$plid]/FlitCtrlPreemption } ] + + $portModeNode setAttribute SmallPktLimit $val1 MaxSmallPktLimit $val2 PreemptionLimit $val3 + } + + set rc [ regexp {PortErrorActions: +(0x[0-9a-fA-F]+): +(.+)} $line matched val1 val2 ] + if { $rc == 1 } { + $portNode appendChild [ createAttributesElement $doc PortErrorActions Value $val1 Fields $val2 ] + } + + set rc [ regexp {BufferUnits:VL15Init +(0x[0-9a-fA-F]+) +VL15CreditRate +(0x[0-9a-fA-F]+) +CreditAck +(0x[0-9a-fA-F]+) +BufferAlloc +(0x[0-9a-fA-F]+)} $line matched val1 val2 val3 val4 ] + if { $rc == 1 } { + $portNode appendChild [ createAttributesElement $doc BufferUnits VL15Init $val1 VL15CreditRate $val2 CreditAck $val3 BufferAlloc $val4 ] + } + + set rc [ regexp {MTU +Supported: +(.+)} $line matched val1 ] + if { $rc == 1 } { + $portNode appendChild [ createAttributesElement $doc MTU Cap $val1 ] + } + + set rc [ regexp {MTU +Active By VL:} $line matched ] + if { $rc == 1 } { + set mtuNode [ $doc createElement NeighborMTUByVL ] + $portNode appendChild $mtuNode + } + + # Build VLtoMTU Map + set rc [ regexp {^00:|^08:|^16:|^24:} $line matched ] + if { $rc == 1 } { + #the regex ": +" eliminates the error for MTU values that are less than 4 characters + #sample line 00>8192 01>4096 02>8192 03>8192 04>256 05>512 06>1024 07>2048 + set VLMTUPair_line [regsub -all ": *" $line >] + + foreach vlMTUPair [split $VLMTUPair_line " "] { + #00>8192 + set vlValue [lindex [split $vlMTUPair ">"] 0] + set value [lindex [split $vlMTUPair ">"] 1] + + set mtuNode [ $doc selectNodes {//PortInfo/Port[PortNum=$portNum_dec and PortLID=$plid]/NeighborMTUByVL } ] + + $mtuNode appendChild [ createAttributesElement $doc VL id $vlValue MTU $value ] + } + } + + set rc [ regexp {StallCnt/VL: } $line matched ] + if { $rc == 1 } { + set values [ split $line ] + set values [ lreplace $values 0 0 ] + set valueCounter 0 + set stallCountsNode [ $doc createElement StallCounts ] + + foreach value $values { + set value [ string trim $value ] + + # Skip empty fields + if { [ string length $value ] != 0 } { + $stallCountsNode appendChild [ createAttributesElement $doc VL id $valueCounter Count $value ] + + incr valueCounter + } + } + + $portNode appendChild $stallCountsNode + } + + set rc [ regexp {^HOQLife VL\[([0-9]+),([0-9])+\]: } $line matched startVL endVL ] + if { $rc == 1 } { + set values [ split $line " "] + + # Getting rid of the first two fields, so two identical calls + set values [ lreplace $values 0 0 ] + set values [ lreplace $values 0 0 ] + + set vlValue [ string trim $startVL "0" ] + if { $vlValue == "" } { + set vlValue 0 + } + + if { $startVL == 0 } { + # Create HOQLife to VL element + set hoqNode [ $doc createElement HOQ ] + $portNode appendChild $hoqNode + } + + foreach value $values { + set Node [ $doc selectNodes {//PortInfo/Port[PortNum=$portNum_dec and PortLID=$plid]/HOQ } ] + + $Node appendChild [ createAttributesElement $doc VL id $vlValue Life $value ] + incr vlValue + } + } + + set rc [ regexp {ReplayDepth Buffer +(0x[0-9a-fA-F]+). +Wire +(0x[0-9a-fA-F]+)} $line matched val1 val2 ] + if { $rc == 1 } { + $portNode appendChild [ createAttributesElement $doc ReplayDepth Buffer $val1 Wire $val2 ] + } + + set rc [ regexp {DiagCode: +(0x[0-9a-fA-F]+) +LinkDownReason: +(.+)} $line matched val1 val2 ] + if { $rc == 1 } { + $portNode appendChild [ createTextElement $doc DiagCode $val1 ] + $portNode appendChild [ createTextElement $doc LinkDownReason $val2 ] + } + + set rc [ regexp {OverallBufferSpace: +(0x[0-9a-fA-F]+)} $line matched val1 ] + if { $rc == 1 } { + $portNode appendChild [ createTextElement $doc OverallBufferSpace $val1 ] + } + + set rc [ regexp {Violations +M_Key: +([0-9]+) +P_Key: +([0-9]+) +Q_Key: +([0-9]+)} $line matched val1 val2 val3 ] + if { $rc == 1 } { + $portNode appendChild [ createAttributesElement $doc Violations M_Key $val1 P_Key $val2 Q_Key $val3 ] + } + + # Last element of a port + set rc [ regexp {LinkDownErrorLog: +(.+$)} $line matched linkDown ] + if { $rc == 1 } { + $portNode appendChild [ createTextElement $doc LinkDownErrorLog $linkDown ] + + # Generate new port tag + set generateNewPort 1 + } + } + + #puts [$root asXML] + return $root +} + + +######################################################################################### +# Name : smaquerytoxml +# Input : txt file generated from opasmaquery,top row label, bottom row label +# Return . DOM tree. +# Description : Produce a DOM object (xml) from a formatted txt file. +######################################################################################### + +proc smaquerytoxml { content toplabel bottomlabel } { + + # determine parsing method based on content size. + # There are 206 characters in a single port output. + + #dumpvar $content 0 false + set singlePortCommandSize 206 + + if { [ string length $content ] < $singlePortCommandSize } { + # Single Port Ouput. + + # Parse + set toprow [ regsub -all "$bottomlabel:.*" "$content" "" ] + set bottomrow [ regsub -all ".+?(?=$bottomlabel)" "$content" "" ] + set toprow_values [ regsub -all "$toplabel:" "$toprow" "" ] + set bottomrow_values [ regsub -all "$bottomlabel:" "$bottomrow" "" ] + + set i 0 + set result "" + set result "$result" + foreach sl_xml $toprow_values { + set sc_xml [ lindex $bottomrow_values $i] + set result "$result<$toplabel id='$sl_xml'><$bottomlabel>$sc_xml" + set i [expr $i + 1] + } + set result "$result" + set result "$result" + + } else { + # Multi Port Ouput: + # puts "this is the multiport ouput." + + # Parse + set rowTop [ getCmdOutputParameter $content $toplabel "Port" "true" ] + + # define port array + array set portArr {} + + # determine size of multiport output + set portcount [ regexp -all {(Port)} $content ] + + # define spacing between Port and # + set singlespace " " + set doublespace " " + + #Build port array. + for {set i 0} {$i < $portcount} {incr i} { + + if {$i < 9 } { + set portArr($i) [ getCmdOutputParameter $content "Port$doublespace$i" "Port$doublespace[expr $i + 1]" "true" ] + set portArr($i) [ getCmdOutputParameter $portArr($i) "$bottomlabel:" "\n" "true" ] + } elseif {$i == 9} { + set portArr($i) [ getCmdOutputParameter $content "Port$doublespace$i" "Port$singlespace[expr $i + 1]" "true" ] + set portArr($i) [ getCmdOutputParameter $portArr($i) "$bottomlabel:" "\n" "true" ] + } else { + set portArr($i) [ getCmdOutputParameter $content "Port$singlespace$i" "Port$singlespace[expr $i + 1]" "true" ] + set portArr($i) [ getCmdOutputParameter $portArr($i) "$bottomlabel:" "\n" "true" ] + } + } + + set result "" + # for each port, determine the toplabel-bottom label mapping + + for {set j 0} {$j < $portcount} {incr j} { + + set result "$result" + + foreach row $portArr($j) column $rowTop { + set result "$result<$toplabel id='$column'><$bottomlabel>$row" + } + set result "$result" + } + set result "$result" + + } + + # build DOM tree. + set XML "$result" + set doc [dom parse $XML] + set root [$doc documentElement] +# puts "[$root asXML]" + return $root +} + + +######################################################################################### +# Name : build_node_list +# Input : DOM node list. +# Return . TCL list of strings. +# Description : dereference xpath node values. +######################################################################################### + +proc build_node_list { list } { + + set nodeList {} + + foreach node $list { + set idx_val [ lindex [$node nodeValue] 0 ] + lappend nodeList $idx_val + } + + return $nodeList +} + +######################################################################################### +# Name : node_lists_cmp_eq +# Input : list1, list2, list1Desc, list2Desc +# Return . None. +# Description : Checks if all values of list1 exist in list2. +######################################################################################### + +proc node_lists_cmp_eq { list1 list2 list1Desc list2Desc} { + + foreach element $list1 { + if {$element ni $list2} { + return -code error "ERROR : $list1Desc $element does not exist in $list2Desc" + } + } +} + +######################################################################################### +# Name : node_lists_cmp_ne +# Input : list1, list2, list1Desc, list2Desc, testState +# Return . None. +# Description : Checks if all values of list1 do not exist in list2. +######################################################################################### + +proc node_lists_cmp_ne { list1 list2 list1Desc list2Desc testState } { + + foreach element $list1 { + if {$element in $list2} { + return -code error "ERROR : $list1Desc $element exists in $list2Desc. \nTest Execution State : $testState" + } + } +} + +######################################################################################### +# Name : node_list_cmp_eq +# Input : list1, list1Desc +# Return . None. +# Description : Compare every element in the list with every other element in the list. +######################################################################################### + +proc node_list_cmp_eq { list1 list1Desc} { + + foreach element1 $list1 { + foreach element2 $list1 { + if {$element1 ne $element2} { + return -code error "ERROR : $element1 does not exist in $list1Desc." + } + } + } +} + +######################################################################################### +# Name : node_list_cmp_ne +# Input : list1, list1Desc +# Return . Return a failure if an element exists in a list more than once. +# Description : Compare every element in the list with every other element in the list. +######################################################################################### + +proc node_list_cmp_ne { list1 list1Desc} { + + foreach element1 $list1 { + set match 0 + foreach element2 $list1 { + if {$element1 eq $element2} { + set count [expr $match + 1] + if {$match > 1} { + return -code error "ERROR : $element1 exists in $list1Desc." + } + } + } + } +} + +######################################################################################### +# Name : arginfoToXml +# Input : None +# Return . outputXml, string containing xml elements and values +# Description : Converts input arguments of any calling proc to xml. Call arginfoToXml +# from a proc with input arguments that need to be converted to Xml +######################################################################################### + +proc arginfoToXml {} { + + #get calling proc name + set proc [lindex [info level -1] 0] + set proc_name [uplevel [list namespace which -command $proc]] + set outputXml {} + #Take each input argument argName and argValue of the calling function and convert + #to a xml line in the form $argValue + foreach arg [info args $proc_name] { + set value [uplevel [list set $arg]] + + if { [info default $proc_name $arg def] && [ string length $value ] ==0 } { + lappend outputXml "<$arg>$def" + } elseif { [ string length $value ] != 0 } { + lappend outputXml "<$arg>$value" + } + } + return $outputXml +} + diff --git a/TestTools/proc_mgr.exp b/TestTools/proc_mgr.exp new file mode 100644 index 0000000..abcb65d --- /dev/null +++ b/TestTools/proc_mgr.exp @@ -0,0 +1,658 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] + +# low level process management routines + +# This is the default stty settings for the pty used by expect +# to have it take effect callers of spawn or test_spawn must +# declare global stty_init in their function +# alternately they could declare a local variable with their own settings +# or take the default settings +global stty_init +# avoid surprise carriages returns in pty due to column wrap +set stty_init "columns 500" + +global os_type +set os_type [ exec uname -s ] + +proc stop_child { spawn_id_list { signal TERM }} { +## +## stop_child +## ---------- +## stop the given set of child processes +## +## Usage: +## stop_child spawn_id_list [signal] +## Arguments: +## spawn_id_list - list of spawn id's from test_spawn +## signal - signal to send to kill child if not already dead. +## default is TERM + + global test_spawn_id_list test_spawn_program + upvar #0 spawn_id global_spawn_id + + foreach spawn_id $spawn_id_list { + # see if child still running + if { [catch {set pid [exp_pid -i $spawn_id]}] == 1 } { + # child must already be dead + log_message "Child exited: $test_spawn_program($spawn_id)" + } else { + + log_message "Stopping $test_spawn_program($spawn_id)" + # terminate child + catch {exp_close -i $spawn_id } + if { "$signal" != "" } { + catch {exec kill -s TERM $pid } + } + } + catch {exp_wait -i $spawn_id } + set index [lsearch -exact $test_spawn_id_list $spawn_id] + if { $index != -1 } { + set test_spawn_id_list [ lreplace $test_spawn_id_list $index $index ] + } + if { $spawn_id == $global_spawn_id } { + # so expect_after in test_suite looks at a valid + # value for spawn_id + set global_spawn_id {} + } + } +} + +proc kill_child { spawn_id_list signal } { +## +## kill_child +## ---------- +## send a signal to the given children +## +## Usage: +## kill_child spawn_id_list [signal] +## Arguments: +## spawn_id_list - list of spawn id's from test_spawn +## signal - signal to send to child + + global test_spawn_program + + foreach spawn_id $spawn_id_list { + if { [catch {set pid [exp_pid -i $spawn_id]}] == 1 } { + # child must already be dead + continue + } + log_message "Sending SIG$signal to $test_spawn_program($spawn_id)" + catch {exec kill -s $signal $pid} + } +} + +proc wait_child { spawn_id_list } { +## +## wait_child +## ---------- +## Wait for child to die, do not send any signals +## +## Usage: +## wait_child spawn_id_list +## Arguments: +## spawn_id_list - list of spawn id's from test_spawn + + stop_child $spawn_id_list "" +} + +proc wait_child_eof { spawn_id_list timelimit { err_msg "timeout: waiting for data or EOF"} } { +## +## wait_child_eof +## -------------- +## Wait for an eof from the given set of children and log all output +## +## Usage: +## wait_child_eof spawn_id_list timelimit [ err_msg ] +## Arguments: +## spawn_id_list - list of spawn ids to operate on +## timelimit - maximum time to wait for eof per child +## This timelimit is restarted each time the child provides output +## err_msg - error to provide if timeout waiting for eof +## default is "timeout: waiting for data or EOF" +## Additional Information: +## The child is unconditionally stopped after the wait, even if +## the wait fails. +## The children are waited for sequentially, not in unison + + global expect_out + + # since our local spawn_id will not match the global one + # expect_after will not get involved + set_timeout $timelimit + foreach spawn_id $spawn_id_list { + set retcode [ catch { expect { + "?*" { exp_continue } + eof noop + timeout { log_message "wait_child_eof: $err_msg"; error "wait_child_eof: $err_msg" } + default { log_message "wait_child_eof: default unexpected" + error "wait_child_eof: default unexpected" + } + } + } res ] + # make sure child terminates + stop_child $spawn_id + if { $retcode != 0 } { + error $res $res + } + } +} + +proc wait_eof { timelimit } \ +{ +## +## wait_eof +## -------- +## utility procedure to wait for eof +## +## Usage: +## wait_eof timelimit +## Arguments: +## timelimit - maximum time to wait +## Returns: +## nothing +## timeout - error exception +## Additional Information: +## This is designed for use within test_case's $code +## It is similar to expect_eof/ignore_rest except that it +## waits for eof from the spawned task and logs all messages +## received until eof. The only way it fails is if the child +## does no output for $timeout and does not eof either. +## +## The child is specified by the global variable spawn_id +## The global timeout is changed + + global timeout + global spawn_id + global expect_out + + set_timeout $timelimit + + wait_child_eof $spawn_id $timeout + return +} + +proc child_cleanup { { show_output 1 } { id "" } } \ +{ +# +# child_cleanup +# ------------- +# cleanup after child after test completion +# +# Usage: +# child_cleanup [show_output] [id] +# Arguments: +# show_output - should additional lines of child output be shown first +# id - spawn_id of child to cleanup, default is global spawn_id +# Returns: +# nothing +# Additional Information: +# This makes sure that the child has exited or been killed +# This routine is for internal use and is not documented for user use +# +# The child is specified by the global variable spawn_id + + global lines_to_show + global expecting + + if { "$id" == "" } { + global spawn_id + set id $spawn_id + # so expect_after in test_suite looks at a valid + # value for spawn_id + set spawn_id {} + } else { + # use a local, expect_after isn't involved anyway + # since we cover eof and default cases in show_more_lines + set spawn_id $id + } + if { $show_output } { + # show the next few lines + if { [info exists lines_to_show] } { + set line_cnt $lines_to_show + } else { + set line_cnt 10; # default value + } + catch { show_more_lines $line_cnt $id } + } + + set expecting "" + + stop_child $id + return +} + +global test_spawn_id_list +set test_spawn_id_list {} + +proc test_spawn { program_name args } { +## +## test_spawn +## ---------- +## spawn a child process for monitoring with send/expect +## +## Usage: +## test_spawn program_name args +## Arguments: +## program_name - name for child in log messages +## args - expect spawn args for child creation, includes command name +## Additional Information: +## spawn in run in callers context and $spawn_id will reflect new task +## global stty_init can be used to accept the default global settings +## if not declared the defaults are used, if local - overrides global default + + global test_spawn_id_list test_spawn_program + global stty_init + + log_message "spawn $args" + uplevel spawn $args + upvar spawn_id new_spawn_id + + lappend test_spawn_id_list $new_spawn_id + set test_spawn_program($new_spawn_id) $program_name +} + + +proc stop_all_children {} { +## +## stop_all_children +## ----------------- +## stop all currently running children +## +## Usage: +## stop_all_children +## Additional Information: +## stop_child is run against all children started with test_spawn + + stop_child $test_spawn_id_list +} + +proc cleanup_all_children { { show_output 1 } } { +## +## cleanup_all_children +## ------------- +## cleanup after all children after test completion +## +## Usage: +## cleanup_all_children [show_output] +## Arguments: +## show_output - should next few lines of child output be logged +## Returns: +## nothing +## Additional Information: +## All children started with test_spawn are sequentially processed + + global test_spawn_id_list + + foreach id $test_spawn_id_list { + child_cleanup $show_output $id + } +} + +#proc command_name { arg_list } { +# # return first non-dash argument, used to parse spawn arg list +# # to get name for program to operate on +# foreach arg $arg_list { +# if { [ string match "-*" $arg ] == 0 } { +# return $arg +# } +# } +# return "unknown_program" +#} + +# later, if test_spawn_id_list has more than 1 element, show the corresponding +# element in the list when operate on it via send/expect + +# fix all other tests to use test_spawn and cleanup_all_children +# instead of spawn and child_cleanup + +# used to be needed for parallel below +# now fork/wait is exp_fork/exp_wait, kill is exec shell's kill +# we ignore errors, FastFabric on opteron sometimes finds 64 bit expect and +# 32 bit tclx library loaded, however on those systems expect seems to +# be able to run the desired fast fabric commands +#catch { +# if { [ file exists /usr/lib/libtclx.so ] } { +# load /usr/lib/libtclx.so +# } elseif { [ file exists /usr/lib64/tclx8.4/libtclx8.4.so ] } { +# load /usr/lib64/tclx8.4/libtclx8.4.so +# } +#} + +set qlgc_fork exp_fork +set qlgc_wait exp_wait +if { ! [ catch { set thread_tcl $tcl_platform(threaded) } result] } { + # Our own TCL extension to work around fork issues + #load /usr/lib/opa/tools/libqlgc_fork.so + package require qlgc_fork + set qlgc_fork qlgc_fork + set qlgc_wait qlgc_wait +} + +proc dump_file_to_output { fd } { +## +## dump_file_to_output +## ------------------- +## Dumps output of file to stdout +## +## Usage: +## dump_file_to_output $fd +## Arguments: +## fd - File discriptor to be use for reading +## Returns: +## nothing +## + if { $fd == 0 } { + return + } + while {1} { + set line [gets $fd] + if {[eof $fd]} { + close $fd + break + } + puts "$line" + } +} + +proc parallel { var list code } { +## +## parallel +## ------------- +## execute code in parallel (one process per entry in list) with var +## set to each item in list +## +## Usage: +## parallel var list code +## Arguments: +## var - name of variable to be assigned a value from list +## list - values for $var, one process per entry +## code - code to execute, will be executed in stack frame of caller +## Returns: +## nothing +## Additional Information: +## Used TclX version of fork/wait, expect version can't wait for non-spawned +## processes +## +## This is intended for use within parallel execution of +## test suites/cases/items +## beware the sub-processes will have the same files/expect sessions open +## generally it is a bad a item to have parallel processes sharing the +## same expect session (reads from session could go to either process) +## hooks with tools_ functions allow counters for run to be maintained +## across the process boundaries and allow failures in sub-processes +## to appropriately propigate up + + global env + upvar $var $var + global os_type + global qlgc_fork + global qlgc_wait + global orig_stdout + + if { [ test_parallel ] } { + tools_clear_tmp_counters + set max_parallel [test_get_env TEST_MAX_PARALLEL] + set first 0 + set last [expr $max_parallel - 1] + set ff_pid [pid] + set test_serialize_output [test_check_yn [test_get_env TEST_SERIALIZE_OUTPUT]] + + while { $first < [llength $list] } { + set processes {} + if { $test_serialize_output } { + set child_counter 1 + array unset fd_list + } + foreach $var [ lrange $list $first $last] { + if { $test_serialize_output } { + set fname "/tmp/qlgc_tmp_${ff_pid}_${child_counter}" + set fd [open $fname w+] + } + set pid [ eval $qlgc_fork ] + if { $pid == 0 } { + # child process + if { $test_serialize_output } { + package require qlgc_fork + if { $orig_stdout == "" } { + set orig_stdout [qlgc_dup stdout] + fconfigure $orig_stdout -buffering line + } + close stdout + set fd [open $fname {WRONLY APPEND TRUNC} ] + close stderr + set fd1 [qlgc_dup stdout ] + fconfigure $fd -buffering line + fconfigure $fd1 -buffering line + file delete $fname + } + tools_clear_saved_counters + set errorcode [ catch { uplevel eval "{" "$code" "}" } errorinfo ] + tools_save_counters $errorcode $errorinfo + if { $test_serialize_output } { + close $fd + close $fd1 + if { $orig_stdout != "" } { + close $orig_stdout + } + } + exit 0 + } elseif { $pid == -1 } { + if { $test_serialize_output } { + close $fd + file delete $fname + } + fail_test "Unable to fork" + } else { + # parent process + lappend processes $pid + if { $test_serialize_output } { + set fd_list($pid) $fd + incr child_counter + } + } + } + if { $test_serialize_output } { + wait_process_list $processes [array get fd_list] + } else { + wait_process_list $processes + } + set first [expr $last + 1] + incr last $max_parallel + } + tools_propigate_process_results + } else { + foreach $var $list { + uplevel eval "{" "$code" "}" + } + } +} + +proc wait_process_list { pid_list {fd_arr "" }} { +## +## wait_process_list +## ------------- +## Internal helper function, waits for a set of processes to exit +## for each the tmp_counters are updated +## intended for use internal to parallel and wait_subprocesses + + global env + global qlgc_fork + global qlgc_wait + + set killed 0 + set test_serialize_output [test_check_yn [test_get_env TEST_SERIALIZE_OUTPUT]] + + if { $fd_arr != "" } { + array set fd_list $fd_arr + } + + foreach pid $pid_list { + while { 1 } { + # wait on x86_64 is broken, does not actually wait + if { [ catch { set wait_status [ eval $qlgc_wait -i -1 ] } errorinfo ] } { + sleep 1 + continue + } + # first element of wait_status list is PID + set pid [lindex $wait_status 0] + # check pid against list, could be a CHILDKILLED status + if { [ lsearch -exact $pid_list $pid ] == -1 } { + # not found + continue + } + # a process in pid_list has exited + break + } + # once we kill processes, we ignore the counters, they will have exited + if { ! $killed } { + tools_update_tmp_counters $pid + } else { + tools_remove_tmp_counters $pid + } + if { $test_serialize_output == 1 && + $fd_arr != "" + } { + + dump_file_to_output $fd_list($pid) + set fd_list($pid) "0" + } + + if { ! [ tools_check_process_results ] } { + # we had a failure which will propigate up + # stop other processes + log_message "Child failure detected: killing $pid_list" + log_message "exec: kill -s TERM $pid_list" + if { $test_serialize_output == 1 && + $fd_arr != "" + } { + foreach {pid fd} [array get fd_list] { + #This check ensures that we don't perform any output for + #already completed children. + if { $fd != 0 } { + dump_file_to_output $fd + set fd_list($pid) "0" + } + } + } + + catch {exec kill -s TERM $pid_list } + sleep 2 + log_message "exec: kill -s KILL $pid_list" + catch {exec kill -s KILL $pid_list } + set killed 1 + } + } +} + +global sub_process_list +set sub_process_list {} + +proc init_subprocesses { } { +## +## init_subprocesses +## ------------- +## prepare to start subprocesses +## +## Usage: +## init_subprocesses +## Returns: +## None +## + global sub_process_list + + tools_clear_tmp_counters +} + +proc subprocess { code } { +## +## subprocess +## ------------- +## start a subprocess +## +## Usage: +## subprocess code +## Arguments: +## code - code to execute, will be executed in stack frame of caller +## Returns: +## nothing +## Additional Information: +## Used TclX version of fork/wait, expect version can't wait for non-spawned +## processes +## +## This is intended for use within tests where 2 or more processes will +## be talking to eachother, such as a client/server application within +## test suites/cases/items +## beware the sub-processes will have the same files/expect sessions open +## generally it is a bad a idea to have parallel processes sharing the +## same expect session (reads from session could go to either process) +## +## hooks with tools_ functions allow counters for run to be maintained +## across the process boundaries and allow failures in sub-processes +## to appropriately propigate up +## +## After starting all subprocesses, parent process must call +## wait_subprocesses (or fail_test) + + global sub_process_list + global os_type + global qlgc_fork + global qlgc_wait + + set pid [ eval $qlgc_fork ] + if { $pid == 0 } { + tools_clear_saved_counters + set errorcode [ catch { uplevel eval "{" "$code" "}" } errorinfo ] + tools_save_counters $errorcode $errorinfo + exit 0 + } elseif { $pid == -1 } { + fail_test "Unable to fork" + } else { + lappend sub_process_list $pid + } +} + +proc wait_subprocesses { } { +## +## wait_subprocesses +## ------------- +## wait for all the subprocesses started since last init_subprocesses +## +## Usage: +## wait_subprocesses + + global sub_process_list + + set list $sub_process_list + set sub_process_list {} + wait_process_list $list + tools_propigate_process_results +} diff --git a/TestTools/qlgc_fork.c b/TestTools/qlgc_fork.c new file mode 100644 index 0000000..4a5d7ef --- /dev/null +++ b/TestTools/qlgc_fork.c @@ -0,0 +1,281 @@ +/* BEGIN_ICS_COPYRIGHT5 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + * ** END_ICS_COPYRIGHT5 ****************************************/ +/* [ICS VERSION STRING: unknown] */ + +/* + * qlgc_fork.c -- TCL extension to workaround problems in exp_fork/exp_wait + * when TCL_THREADS enabled in build + */ +#include +#include +#include +#include +#include + +static int +Qlgc_fork_Cmd(ClientData cdata, Tcl_Interp *interp, int objc, Tcl_Obj * CONST objv[]) +{ + pid_t pid; + char result[20]; + + fflush(stdout); + fflush(stderr); + /* this is a bit of a hack, but seems to solve the problem + * by stopping and starting the notifier we ensure a notifier + * exists for the child process. We must stop it because the + * startup depends on hidden static status variables. + */ + Tcl_FinalizeNotifier(NULL); // arg not used in TCL 8.4 on Linux + pid = fork(); + (void)Tcl_InitNotifier(); + sprintf(result, "%d", pid); + Tcl_SetObjResult(interp, Tcl_NewStringObj(result, -1)); + return TCL_OK; +} + +static int +Qlgc_wait_Cmd(ClientData cdata, Tcl_Interp *interp, int objc, Tcl_Obj * CONST objv[]) +{ + pid_t pid; + int status; + char result[20]; + + /* don't check args, this way the -i -1 arg of exp_wait is simply ignored */ + pid = wait(&status); + + sprintf(result, "%d", pid); + Tcl_SetObjResult(interp, Tcl_NewStringObj(result, -1)); + return TCL_OK; +} + +#if 0 /* this is comparible to TCL's normal exit command, don't need this */ +static int +Qlgc_exit_Cmd(ClientData cdata, Tcl_Interp *interp, int objc, Tcl_Obj * CONST objv[]) +{ + int status; + + + /* + * Check params. + */ + if (objc != 2) { + Tcl_WrongNumArgs(interp, 1, objv, "status"); + return TCL_ERROR; + } + if (Tcl_GetIntFromObj(interp, objv[1], &status) != TCL_OK) { + return TCL_ERROR; + } + Tcl_Exit(status); + //fflush(stdout); + //fflush(stderr); + //exit(status); + + /*NOTREACHED*/ + return TCL_OK; +} +#endif + +/* This is a quick and dirty implementation of dup capability for TCL + * Usage: dup file + * Parameters: + * file - an existing TCL file/channel opened read/write + * Additional Information: + * Implemented and tested for intended usage of: close stderr; dup stdout + * such that stderr can be redirected to the same file used for stdout + */ +static int +Qlgc_dup_Cmd(ClientData cdata, Tcl_Interp *interp, int objc, Tcl_Obj * CONST objv[]) +{ + char *file; + Tcl_Channel channel; + Tcl_Channel newchannel; + ClientData handle; + int fd, newfd; + int mode; + char result[100]; + + /* + * Check params. + */ + if (objc != 2) { + Tcl_WrongNumArgs(interp, 1, objv, "file"); + return TCL_ERROR; + } + + file = Tcl_GetStringFromObj(objv[1], NULL); + channel = Tcl_GetChannel(interp, file, &mode); + if (! channel) + goto failfile; + + if (Tcl_Flush(channel) == TCL_ERROR) { + errno = Tcl_GetErrno(); + goto failerrno; + } + + if (TCL_ERROR == Tcl_GetChannelHandle(channel, TCL_WRITABLE, &handle)) + goto failfile; + fd = (int)(long int)handle; + + newfd = dup(fd); + + newchannel = Tcl_MakeFileChannel((ClientData)(long)newfd, mode); + Tcl_RegisterChannel(interp, newchannel); + Tcl_SetObjResult(interp, Tcl_NewStringObj(Tcl_GetChannelName(newchannel), -1)); + + return TCL_OK; + +failfile: + Tcl_ResetResult(interp); + Tcl_AppendResult(interp, "qlgc_dup failed: invalid file handle: ", file, NULL); + goto fail; + +failerrno: + snprintf(result, sizeof(result), "qlgc_dup failed: %s", Tcl_PosixError(interp)); + Tcl_SetObjResult(interp, Tcl_NewStringObj(result, -1)); + +fail: + return TCL_ERROR; +} + +#if 0 +// this idea was viable and sort of worked. Except that +// the TCL shell did not process the resulting trap handler +// until after the command being executed completed. +// This was intended as a way for opacmdall to set a timeout for +// remote ssh commands +typedef void (*signal_handler_t)(int); + +static int have_old_alarm_handler = 0; +static signal_handler_t old_alarm_handler; + +static void save_alarm_handler(signal_handler_t handler) +{ + if (! have_old_alarm_handler) { + printf("saving alarm handler\n"); + old_alarm_handler = handler; + have_old_alarm_handler = 1; + } +} + +static void restore_alarm_handler() +{ + if (have_old_alarm_handler) { + printf("restoring alarm handler\n"); + signal(SIGALRM, old_alarm_handler); + have_old_alarm_handler = 0; + } +} + + +/* This is a quick and dirty way to get alarms into a "trapable" signal + * for expect code. Expect uses SIGALRM, so it won't allow trap for it + * however, if we are careful not to use the qlgc_alarm code within + * expect {} statements, we should be safe to borrow the alarms as long as + * we restore the handler when we are done. + */ +static void alarm_handler(int x) +{ + int ret; + printf("got alarm\n"); + restore_alarm_handler(); + printf("send SIGUSR1 to %d\n", getpid()); + if (0 != (ret = kill (0 /*getpid()*/, SIGUSR1))) + printf("kill SIGUSR1 failed %s\n", strerror(errno)); + //if (0 != (ret = kill (getpid(), SIGHUP))) + // printf("kill SIGHUP %s\n", strerror(errno)); +} + +/* This is a quick and dirty implementation of alarm capability for TCL + * Usage: alarm seconds + * Parameters: + * seconds - number of seconds til next SIGALRM, 0 to disable + * Returns: + * number of seconds remaining until any previously scheduled alarm was due to + * be delivered. + */ +static int +Qlgc_alarm_Cmd(ClientData cdata, Tcl_Interp *interp, int objc, Tcl_Obj * CONST objv[]) +{ + int seconds; + int secondsleft; + char result[20]; + signal_handler_t ret; + + /* + * Check params. + */ + if (objc != 2) { + Tcl_WrongNumArgs(interp, 1, objv, "seconds"); + return TCL_ERROR; + } + if (Tcl_GetIntFromObj(interp, objv[1], &seconds) != TCL_OK) { + return TCL_ERROR; + } +printf("qlgc_alarm %d\n", seconds); + if (seconds) { + ret = signal(SIGALRM, alarm_handler); + if (ret == SIG_ERR) + goto failerrno; + save_alarm_handler(ret); + } + secondsleft = (int)alarm((unsigned int)seconds); + if (! seconds) + restore_alarm_handler(); + + sprintf(result, "%d", secondsleft); + Tcl_SetObjResult(interp, Tcl_NewStringObj(result, -1)); + return TCL_OK; + +failerrno: + sprintf(result, "qlgc_alarm failed: %s", strerror(errno)); + Tcl_SetObjResult(interp, Tcl_NewStringObj(result, -1)); + return TCL_ERROR; +} +#endif + +/* + * qlgc_fork_Init -- Called when Tcl loads the extension. + */ +int DLLEXPORT +Qlgc_fork_Init(Tcl_Interp *interp) +{ + if (Tcl_InitStubs(interp, TCL_VERSION, 0) == NULL) { + return TCL_ERROR; + } + /* changed this to check for an error - GPS */ + if (Tcl_PkgProvide(interp, "qlgc_fork", "1.0") == TCL_ERROR) { + return TCL_ERROR; + } + Tcl_CreateObjCommand(interp, "qlgc_fork", Qlgc_fork_Cmd, NULL, NULL); + Tcl_CreateObjCommand(interp, "qlgc_wait", Qlgc_wait_Cmd, NULL, NULL); + //Tcl_CreateObjCommand(interp, "qlgc_exit", Qlgc_exit_Cmd, NULL, NULL); + Tcl_CreateObjCommand(interp, "qlgc_dup", Qlgc_dup_Cmd, NULL, NULL); + //Tcl_CreateObjCommand(interp, "qlgc_alarm", Qlgc_alarm_Cmd, NULL, NULL); + return TCL_OK; +} diff --git a/TestTools/qlgc_fork.pkgIndex b/TestTools/qlgc_fork.pkgIndex new file mode 100644 index 0000000..cc4ec62 --- /dev/null +++ b/TestTools/qlgc_fork.pkgIndex @@ -0,0 +1,3 @@ +# qlgc_fork.pkgIndex -- tells Tcl how to load qlgc_fork package. +package ifneeded "qlgc_fork" 1.0 \ + [list load [file join $dir libqlgc_fork[info sharedlibextension]]] diff --git a/TestTools/run_hsm_loop_test_fast.sh b/TestTools/run_hsm_loop_test_fast.sh new file mode 100644 index 0000000..5235ed4 --- /dev/null +++ b/TestTools/run_hsm_loop_test_fast.sh @@ -0,0 +1,157 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +#[ICS VERSION STRING: unknown] +#!/bin/bash + +INJECT_NUM_PKTS=5 +start_test=0 +end_test=0 +inject=0 +redundancy=0 +length=0 +SM_DIAG_PATH=/usr/lib/opa-fm/bin/fm_cmd +MIN_ISL_REDUNDANCY=4 +PATH_LENGTH=4 + +Usage() +{ + + echo "Usage: $0 [-s] [-e] [-i num] [-r num] [-l len] [-d path_to_fm_cmd]" + echo " -s : start loop test in fast mode with default $INJECT_NUM_PKTS packets or -i option can be used to specify number of packets." + echo " -e : end loop test and turn off fast mode" + echo " -i num : inject num packets. Can also be used after starting the test, to inject more packets." + echo " -r num : Set loop test's MinISLRedundancy to num. This will include each ISL in num different loops." + echo " -l len : Set loop test path length to len. Loop paths will be of length <=len" + echo " -d path : Run fm_cmd binary at path, instead of the default $SM_DIAG_PATH" + echo " -h : shows usage" + + exit 1 +} + +if [ $# -eq 0 ]; then + Usage + exit 1 +fi + +while getopts sehi:r:l:d: param +do + case $param in + s) + start_test=1;; + e) + end_test=1;; + i) + inject=1; + INJECT_NUM_PKTS="$OPTARG";; + r) + redundancy=1 + MIN_ISL_REDUNDANCY="$OPTARG";; + l) + length=1 + PATH_LENGTH="$OPTARG";; + d) + SM_DIAG_PATH="$OPTARG";; + h) + Usage;; + + ?) + Usage;; + esac +done + +shift $((OPTIND -1)) + +if [ ! -f $SM_DIAG_PATH ];then + echo "$SM_DIAG_PATH not found. fm_cmd is required for running loop test" + exit 1 +fi + +if [ ! -x $SM_DIAG_PATH ];then + echo "$SM_DIAG_PATH is not an executable. fm_cmd is required for running loop test" + exit 1 +fi + + +if [ $start_test -eq 1 ]; then + echo "Turning on Loop test Fast Mode..." + if ! $SM_DIAG_PATH smLooptestFastMode 1; then + echo "Could not turn ON loop test fast mode. Command used: $SM_DIAG_PATH smLooptestFastMode 1" + exit 1 + fi + + echo "Starting Loop test with $INJECT_NUM_PKTS packets..." + if ! $SM_DIAG_PATH smLooptestStart $INJECT_NUM_PKTS; then + echo "Could not start loop test. Command used: $SM_DIAG_PATH smLooptestStart $INJECT_NUM_PKTS" + exit 1 + fi + exit 0 +fi + +if [ $end_test -eq 1 ]; then + echo "Stopping Loop test..." + if ! $SM_DIAG_PATH smLooptestStop; then + echo "Could not stop loop test. Command used: $SM_DIAG_PATH smLooptestStop" + exit 1 + fi + echo "Turning OFF Loop test Fast Mode..." + if ! $SM_DIAG_PATH smLooptestFastMode 0; then + echo "Could not turn OFF loop test fast mode. Command used: $SM_DIAG_PATH smLooptestFastMode 0" + fi + exit 0 +fi + +if [ $inject -eq 1 ]; then + echo "Injecting $NUM_PKTS to Loop test..." + if ! $SM_DIAG_PATH smLooptestInjectPackets $INJECT_NUM_PKTS; then + echo "Could not inject packets. Command used: $SM_DIAG_PATH smLooptestInjectPackets $INJECT_NUM_PKTS" + exit 1 + fi + exit 0 +fi + +if [ $redundancy -eq 1 ]; then + echo "Setting Loop test MinISLRedundancy to $MIN_ISL_REDUNDANCY..." + if ! $SM_DIAG_PATH smLooptestMinISLRedundancy $MIN_ISL_REDUNDANCY; then + echo "Could not set MinISLRedundancy. Command used: $SM_DIAG_PATH smLooptestMinISLRedundancy $MIN_ISL_REDUNDANCY" + exit 1 + fi + exit 0 +fi + +if [ $length -eq 1 ]; then + echo "Setting Loop test Path Length to $PATH_LENGTH..." + if ! $SM_DIAG_PATH smLooptestPathLength $PATH_LENGTH; then + echo "Could not set path length. Command used: $SM_DIAG_PATH smLooptestPathLength $PATH_LENGTH" + exit 1 + fi + exit 0 +fi + + diff --git a/TestTools/sm_control.exp b/TestTools/sm_control.exp new file mode 100644 index 0000000..7f08ccb --- /dev/null +++ b/TestTools/sm_control.exp @@ -0,0 +1,152 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] + +# This is an expect (tcl) library of procedures to aid ib stack testing + +# manditory setup +log_user 0; # disable detailed logging to stdout + +package require tdom + +######################################################################################### +# Name : stop_sm +# Input : host +# Return . none +# Description : stops the sm, opafm +######################################################################################### +proc stop_sm { host } { + set ret {} + target_root_sh $host + + set host_os_id [get_target_os_id $host] + if { [ string equal "$host_os_id" "RHEL7-x86_64" ] || [ string equal "$host_os_id" "RHEL71-x86_64" ] || [ string equal "$host_os_id" "SLES12-x86_64" ] || [ string equal "$host_os_id" "RHEL72-x86_64" ] || [ string equal "$host_os_id" "SLES121-x86_64" ] } { + send_unix_cmd "systemctl stop opafm" + + send_unix_cmd "systemctl -n 0 status opafm" + catch {expect_any 60 {"dead" "failed"} {"running"} out} ret + } else { + send_unix_cmd "service opafm stop" + catch {expect_any 60 {"Stopping IFS Fabric Manager" "Shutting down IFS Fabric Manager" "shutting down all instances"} {} out} ret + } + + target_root_sh_exit + + return $ret +} + +######################################################################################### +# Name : start_sm +# Input : host +# Return . none +# Description : starts the sm, opafm +######################################################################################### +proc start_sm { host } { + set ret {} + target_root_sh $host + set host_os_id [get_target_os_id $host] + if { [ string equal "$host_os_id" "RHEL7-x86_64" ] || [ string equal "$host_os_id" "RHEL71-x86_64" ] || [ string equal "$host_os_id" "SLES12-x86_64" ] || [ string equal "$host_os_id" "RHEL72-x86_64" ] || [ string equal "$host_os_id" "SLES121-x86_64" ] } { + send_unix_cmd "systemctl start opafm" + + send_unix_cmd "systemctl -n 0 status opafm" + catch {expect_any 60 {"running"} {"failed" "unknown" "dead" } out} ret + } else { + send_unix_cmd "service opafm start" + catch {expect_any 60 {"Starting IFS Fabric Manager"} {"unable to start" "not properly shutdown"} out } ret + sleep 30 + } + + target_root_sh_exit + + return $ret +} + +######################################################################################### +# Name : restart_sm +# Input : host +# Return . none +# Description : restarts the sm, opafm +######################################################################################### +proc restart_sm { host } { + set ret {} + target_root_sh $host + set host_os_id [get_target_os_id $host] + if { [ string equal "$host_os_id" "RHEL7-x86_64" ] || [ string equal "$host_os_id" "RHEL71-x86_64" ] || [ string equal "$host_os_id" "SLES12-x86_64" ] || [ string equal "$host_os_id" "RHEL72-x86_64" ] || [ string equal "$host_os_id" "SLES121-x86_64" ] } { + send_unix_cmd "systemctl restart opafm" + check_exit_status 60 0 + } else { + send_unix_cmd "service opafm restart" + catch {expect_any 60 {"Stopping IFS Fabric Manager" "Shutting down IFS Fabric Manager" "shutting down all instances"} {} out} ret + sleep 25 + } + + target_root_sh_exit + return $ret +} + +######################################################################################### +# Name : save_xml_file +# Input : host +# xml_file_loc - xml source +# xml_file_loc_saved - xml destination +# Return . none +# Description : Saves a backup of an xml file to be restored from later +######################################################################################### +proc save_xml_file { host xml_file_loc xml_file_loc_saved} { + set ret {} + set out {} + target_root_sh $host + send_unix_cmd "/bin/cp -pf $xml_file_loc $xml_file_loc_saved; echo DONE;" + catch {expect_any 60 {"DONE"} {"No such"} out } ret + debug_message "save_xml_file: out=$out" + target_root_sh_exit + + return $ret +} + +######################################################################################### +# Name : restore_xml_file +# Input : host +# xml_file_loc - xml to be overwritten +# xml_file_loc_saved - xml source +# Return . none +# Description : Restores xml from a saved backup (xml_file_loc_saved) +######################################################################################### +proc restore_xml_file { host xml_file_loc_saved xml_file_loc} { + set ret {} + set out {} + target_root_sh $host + send_unix_cmd "/bin/cp -pf $xml_file_loc_saved $xml_file_loc; echo DONE;" + catch {expect_any 60 {"DONE"} {"No such"} out } ret + debug_message "restore_xml_file: out=$out" + target_root_sh_exit + + return $ret +} diff --git a/TestTools/switch_methods.exp b/TestTools/switch_methods.exp new file mode 100644 index 0000000..9f13773 --- /dev/null +++ b/TestTools/switch_methods.exp @@ -0,0 +1,338 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +#[ICS VERSION STRING: unknown] +######################################################################################### +# Name : get_switch_lids_to_ports_map +# Input : cmd_host (where can opa commands be run to query SM) +# Return . A dict mapping LID to list of ports. +# Description : Queries fabric return a dict with all lids of switches and ports that are enabled on them. Only ports with LINK will be returned (no disconnected ports) +######################################################################################### + + +proc get_switch_lids_to_ports_map { cmd_host } { + + # Build DOM from XML + set lids_dom [ run_opareport $cmd_host "-o lids" ] + set links_dom [ run_opareport $cmd_host "-o links" ] + + # Get all switches + set lidsList [ $lids_dom selectNodes {/Report/LIDSummary/LIDs/Value[NodeType='SW']} ] + #puts "found [ llength $lidsList ] switch lids" + + + set lid_port_map [dict create] + + # For each switch node + foreach item $lidsList { + set lid [ $item getAttribute "LID"] + set guid [ [ $item selectNodes NodeGUID/text() ] nodeValue ] + #puts "lid:$lid; guid:$guid" + + # Now, using guid as the key, poke into linksDOM to find the ports for this guid. + set portList [ $links_dom selectNodes /Report/LinkSummary/Link/Port\[NodeGUID='$guid'\]/PortNum/text() ] + # Now you have a list of ports for specific LID/GUID. + #puts "found [ llength $portList ] ports" + + # List of ports per lid + set ports {} + foreach port $portList { + set portNum [ $port nodeValue ] + + # If don't care about port 1 - skip it + #` if { $portNum == 1 } { + # continue + # } + #puts "lid:$lid->port num:$portNum" + + lappend ports $portNum + + # I would have a data structure that is a map of lists, i.e. + # LID1: port1, port2, port3 + # LID2: port5,port6,port7 + # ……. + } + #puts "Added [ llength $ports ] ports" + + dict set lid_port_map $lid $ports + #puts "lid_port_map size: [dict size $lid_port_map]" + } + + # Free memory + $lids_dom delete + $links_dom delete + + return $lid_port_map +} +######################################################################################### +# Name : get_switch_lids_to_hfi_ports_map +# Input : cmd_host (where can opa commands be run to query SM) +# Return . A dict mapping LID to list of ports that are connect to HFIs. +# Description : Queries fabric return a dict with all lids of switches and ports that are enabled and connected to HFIs on them. Only ports with LINK will be returned (no disconnected ports) +######################################################################################### + + +proc get_switch_lids_to_hfi_ports_map { cmd_host } { + # Build DOM from XML + set lids_dom [ run_opareport $cmd_host "-o lids" ] + set links_dom [ run_opareport $cmd_host "-o links" ] + + set lidsList [ $lids_dom selectNodes {/Report/LIDSummary/LIDs/Value[NodeType='SW']} ] +# puts "found [ llength $lidsList ] switch lids" +# puts "[$lidsList selectNodes NodeGUID/text()]" + + set lid_port_map [dict create] + + # For each switch node + foreach item $lidsList { + set lid [ $item getAttribute "LID"] + set guid [ [ $item selectNodes NodeGUID/text() ] nodeValue ] + #puts "lid:$lid; guid:$guid" + + # Now, using guid as the key, poke into linksDOM to find the ports for this guid. + +# set portList [ $links_dom selectNodes /Report/LinkSummary/Link/Port\[NodeGUID='$guid'\]/PortNum/text() ] + set linkList [ $links_dom selectNodes /Report/LinkSummary/Link ] + #puts "found [ llength $linkList ] links" + foreach link $linkList { + set portNodes [ $link getElementsByTagName Port ] + set port1 [lindex $portNodes 0] + set port2 [lindex $portNodes 1] + set port1_NodeType [[$port1 child all NodeType] asText] + set port2_NodeType [[$port2 child all NodeType] asText] + set port1_GUID [[$port1 child all NodeGUID] asText] + set port2_GUID [[$port2 child all NodeGUID] asText] + set port1_PortNum [[$port1 child all PortNum] asText] + set port2_PortNum [[$port2 child all PortNum] asText] + if { ([string compare $port1_GUID $guid]==0) || ([string compare $port2_GUID $guid]==0) } { + if { ([string compare $port1_NodeType SW]==0) && ([string compare $port2_NodeType FI]==0) } { + lappend ports $port1_PortNum + } elseif {([string compare $port1_NodeType FI] == 0) && ([string compare $port2_NodeType SW] == 0)} { + lappend ports $port2_PortNum + } + } + + } + #puts "Added [ llength $ports ] ports" + + dict set lid_port_map $lid $ports + #puts "lid_port_map size: [dict size $lid_port_map]" + } + + # Free memory + $lids_dom delete + $links_dom delete + + return $lid_port_map +} + + + +######################################################################################### +# Name : get_lid_from_guid +# Input : guid +# Return : output of opasaquery -o lid -n $guid +# Description : get lid from guid +######################################################################################### + + +proc get_lid_from_guid { guid } { +## +## get_lid_from_guid +## -------------- +## Obtain my guid +## assumes that target_root_sh has already been called for the host + set cmd "lid=`opasaquery -o lid -n $guid`" + #debug_message "running: $cmd" + unix_cmd 60 "" $cmd + send_unix_cmd { echo "XXX${lid}XXX"; echo DONE } + expect_list 60 { "DONE" "XXX" "DONE" } { "exiting" "No such" "Error" "ERROR" "VAPI" "THH" } tmp + check_exit_status 60 0 + regexp {DONE.*XXX *(.*) *XXX.*DONE} $tmp trash lid + + return "$lid" +} + +######################################################################################### +# Name : get_switchport_from_lid +# Input : cmd_host lid *** LID must be in format 0x0001 (the same format as provided by opareport -o lids) +# Return . A list with element 1 being the SWITCH LID and element 2 being the SWITCH PORT where HFI with that LID is directly connected. If not found the list [ none none ] will be returned +# Description : For the lid of an HFI return the switch lid and port that that HFI is connected to +######################################################################################### +proc get_switchport_from_lid { cmd_host mylid } { + set lids_dom [ run_opareport $cmd_host "-o lids" ] + set links_dom [ run_opareport $cmd_host "-o links" ] + + ################################################# + #debug/dev only + #set lids_file "lids.xml" + #set links_file "links.xml" + ################################################# + # Open lids XML files + #set size [file size $lids_file] + #set fp [open $lids_file r] + #set lidsXML [read $fp $size] + ################################################# + # Open links XML files + #set size [file size $links_file] + #set fp [open $links_file r] + #set linksXML [read $fp $size] + ################################################## + #set lids_dom [dom parse $lidsXML] + #set links_dom [dom parse $linksXML] + + set switchLidsList [ $lids_dom selectNodes {/Report/LIDSummary/LIDs/Value[NodeType='SW']} ] + set hfiLidsList [ $lids_dom selectNodes {/Report/LIDSummary/LIDs/Value[NodeType='FI']} ] + + set myguid "none" + set return_lid "none" + set return_port "none" + + foreach item $hfiLidsList { + set lid [ $item getAttribute "LID"] + set guid [ [ $item selectNodes NodeGUID/text() ] nodeValue ] + if { [string compare $lid $mylid] == 0 } { + set myguid $guid + } + } + + if { [string compare $myguid "none"] == 0 } { + error "Lid $mylid not found" + } + + # For each switch node + foreach item $switchLidsList { + set lid [ $item getAttribute "LID"] + set guid [ [ $item selectNodes NodeGUID/text() ] nodeValue ] + + set linkList [ $links_dom selectNodes /Report/LinkSummary/Link ] + #puts "found [ llength $linkList ] links" + foreach link $linkList { +# puts "processing link [$link asXML] [$link asText]" + set portNodes [ $link getElementsByTagName Port ] + set port1 [lindex $portNodes 0] + set port2 [lindex $portNodes 1] + set port1_NodeType [[$port1 child all NodeType] asText] + set port2_NodeType [[$port2 child all NodeType] asText] + set port1_GUID [[$port1 child all NodeGUID] asText] + set port2_GUID [[$port2 child all NodeGUID] asText] + set port1_PortNum [[$port1 child all PortNum] asText] + set port2_PortNum [[$port2 child all PortNum] asText] + target_root_sh $cmd_host + if { ([string compare $port1_GUID $myguid]==0) } { + #set return_lid $lid + set return_lid [get_lid_from_guid $port2_GUID] + set return_port $port2_PortNum + } elseif { ([string compare $port2_GUID $myguid]==0) } { + #set return_lid $lid + set return_lid [get_lid_from guid $port1_GUID] + set return_port $port1_PortNum + } + + } + + } + $lids_dom delete + $links_dom delete + return [list $return_lid $return_port] +} + + +######################################################################################### +# Name : get_switchport_from_guid +# Input : cmd_host guid +# Return . A list with element 1 being the SWITCH LID and element 2 being the SWITCH PORT where HFI with that LID is directly connected. If not found the list [ none none ] will be returned +# Description : For the lid of an HFI return the switch lid and port that that HFI is connected to +######################################################################################### +proc get_switchport_from_guid { cmd_host myguid } { + set lids_dom [ run_opareport $cmd_host "-o lids" ] + set links_dom [ run_opareport $cmd_host "-o links" ] + + ################################################# + #debug/dev only + #set lids_file "lids.xml" + #set links_file "links.xml" + ################################################# + # Open lids XML files + #set size [file size $lids_file] + #set fp [open $lids_file r] + #set lidsXML [read $fp $size] + ################################################# + # Open links XML files + #set size [file size $links_file] + #set fp [open $links_file r] + #set linksXML [read $fp $size] + ################################################## + #set lids_dom [dom parse $lidsXML] + #set links_dom [dom parse $linksXML] + + set switchLidsList [ $lids_dom selectNodes {/Report/LIDSummary/LIDs/Value[NodeType='SW']} ] + set hfiLidsList [ $lids_dom selectNodes {/Report/LIDSummary/LIDs/Value[NodeType='FI']} ] + + set return_lid "none" + set return_port "none" + + # For each switch node + foreach item $switchLidsList { + set lid [ $item getAttribute "LID"] + set guid [ [ $item selectNodes NodeGUID/text() ] nodeValue ] + + set linkList [ $links_dom selectNodes /Report/LinkSummary/Link ] + #puts "found [ llength $linkList ] links" + foreach link $linkList { + #puts "processing link [$link asXML] [$link asText]" + set portNodes [ $link getElementsByTagName Port ] + set port1 [lindex $portNodes 0] + set port2 [lindex $portNodes 1] + set port1_NodeType [[$port1 child all NodeType] asText] + set port2_NodeType [[$port2 child all NodeType] asText] + set port1_GUID [[$port1 child all NodeGUID] asText] + set port2_GUID [[$port2 child all NodeGUID] asText] + set port1_PortNum [[$port1 child all PortNum] asText] + set port2_PortNum [[$port2 child all PortNum] asText] + #puts "myguid is $myguid port1guid = $port1_GUID port2guid= $port2_GUID lid = $lid" + if { ([string compare $port1_GUID $myguid]==0) } { + set return_lid $lid + set return_lid [get_lid_from_guid $port2_GUID] + + set return_port $port2_PortNum + } elseif { ([string compare $port2_GUID $myguid]==0) } { + set return_lid $lid + set return_lid [get_lid_from_guid $port1_GUID] + + set return_port $port1_PortNum + } + } + } + + $lids_dom delete + $links_dom delete + return [list $return_lid $return_port] +} + diff --git a/TestTools/target.exp b/TestTools/target.exp new file mode 100644 index 0000000..b10d199 --- /dev/null +++ b/TestTools/target.exp @@ -0,0 +1,2390 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] + +# This is an expect (tcl) library of procedures to aid testing +# These functions provide support for remote login and command execution +# against a test target host + +## tcl procedures to support testing: +## ============================================= + +# pattern to match for unix prompts (both local and on target) +global target_unix_prompt +set target_unix_prompt {[$#>][\033 ]} + +# pattern to match for chassis prompts +# since it starts with a -, -gl must be passed to expect +global target_chassis_prompt +set target_chassis_prompt {-> } + +# prompt which comes after login when connect to support shell +global target_chassis_shell_prompt +set target_chassis_shell_prompt {shell-> } + +# limit on login retries +global target_chassis_retry_limit +set target_chassis_retry_limit 3 + +# is the present chassis session a support shell session? +global target_chassis_shell +set target_chassis_shell 0 +# save area for main card when in a rlogin shell +global target_chassis_shell_save +set target_chassis_shell_save 0 + +global os_type +set os_type [ exec uname -s ] + +proc chassis_strip_slots { chassis } { +## +## chassis_strip_slots +## ------------------- +## strip slot specifications from chassis +## +## Usage: +## chassis_strip_slots chassis +## Arguments: +## chassis - chassis name of the form: name[:slot,slot...] +## Returns: +## resulting chassis name +## -code error on failure + + if { [ regexp {.*\[(.*)\].*:.*} "$chassis" full ret] } { + # [chassis]:slot format + return "$ret" + } elseif { [ regexp {.*\[(.*)\].*} "$chassis" full ret] } { + # [chassis] format + return "$ret" + } elseif { [ regexp {.*:.*:.*} "$chassis" full ] } { + # ipv6 without [] nor slot + return "$chassis" + } elseif { [regexp {([^:]+):.*} "$chassis" full ret] } { + # chassis:slot format + return "$ret" + } else { + # chassis without [] nor slot + return "$chassis" + } +} + +proc chassis_get_slots { chassis } { +## +## chassis_get_slots +## ------------------- +## get slot specifications from chassis +## +## Usage: +## chassis_get_slots chassis +## Arguments: +## chassis - chassis name of the form: name[:slot,slot...] +## Returns: +## resulting list of slots as a TCL list : slot nos after colon +## if no slots, returns "all" +## -code error on failure + + if { [ regexp {.*\[.*\].*:(.*)} "$chassis" full slots] } { + # [chassis]:slot format + return [string map {, " "} "$slots"] + } elseif { [ regexp {.*\[.*\].*} "$chassis" full] } { + # [chassis] format + return "all" + } elseif { [ regexp {.*:.*:.*} "$chassis" full ] } { + # ipv6 without [] nor slot + return "all" + } elseif { [regexp {[^:]+:(.*)} "$chassis" full slots] } { + # chassis:slot format + return [string map {, " "} "$slots"] + } else { + # chassis without [] nor slot + return "all" + } +} + +proc local_sh { } { +## +## local_sh +## ------------------- +## start a local shell +## +## Usage: +## local_sh +## Arguments: +## Returns: +## 0 - success +## -code error on failure + + global spawn_id expect_out spawn_out timeout + global expecting + + test_spawn "bash" bash + + expect_unix_prompt 60 + local_set_env + return 0 +} + +proc local_sh_exit { } { +## +## local_sh_exit +## ---------------- +## exit from shell connection created by local_sh +## +## Usage: +## local_sh_exit +## +## Returns: +## 0 - success +## -code error on failure + + send_unix_cmd "exit 0" + ignore_rest + + return 0 +} + +proc local_set_env { } { +## +## local_set_env +## ------------------- +## setup environment for shell session to allow testing +## +## Usage: +## local_set_env +## Arguments: +## None +## Returns: +## 0 - success +## -code error on failure + + # set COLUMNS real large so the Posix shell doesn't enter + # command edit mode and confuse us + #unix_cmd 60 "" "export COLUMNS=500" + #unix_cmd 60 "" "unset EDITOR" + #unix_cmd 60 "" "unset VISUAL" + #unix_cmd 60 "" "umask 0" + #target_set_intr + # get rid of cr and control characters in logs for easier reading + #unix_cmd 60 0 {unset PROMPT_COMMAND; export PS1='[\u@\h]\$ '; stty -onlcr columns 500} + unix_cmd 60 0 {unset PROMPT_COMMAND HISTFILE; set +o history; export PS1='[\u@\h]\$ '} + +} + +proc target_rlogin { target usercode password } { +## +## target_rlogin +## ------------------- +## rlogin to the given target host +## +## Usage: +## target_rlogin target usercode password +## Arguments: +## target - hostname to rlogin to +## usercode - usercode +## password - password +## Returns: +## 0 - success +## -code error on failure + + global spawn_id expect_out spawn_out timeout + global expecting + global stty_init + global target_unix_prompt + + test_spawn "rlogin" rlogin $target -l $usercode + set_timeout 120 + set expecting "rlogin session ($target $usercode)" + expect { + "assword:" { exp_send "$password\r" + exp_continue + } + "incorrect" { set info "Failed to rlogin to $target as $usercode, incorrect usercode" + return -code error -errorinfo $info $info + } + "failure" { set info "Failed to rlogin to $target as $usercode" + return -code error -errorinfo $info $info + } + "refused" { set info "Failed to rlogin to $target as $usercode" + return -code error -errorinfo $info $info + } + "nknown" { set info "Failed to rlogin to $target as $usercode" + return -code error -errorinfo $info $info + } + "$target_unix_prompt" noop + } + + return 0 +} + +proc target_telnet { target usercode password } { +## +## target_telnet +## ------------------- +## telnet to the given target host +## +## Usage: +## target_telnet target usercode password +## Arguments: +## target - hostname to rlogin to +## usercode - usercode +## password - password +## Returns: +## 0 - success +## -code error on failure + + global spawn_id expect_out spawn_out timeout + global expecting + global stty_init + global target_unix_prompt + + test_spawn "telnet" telnet $target -l $usercode + set_timeout 120 + set expecting "telnet session ($target $usercode)" + expect { + "assword:" { exp_send "$password\r" + exp_continue + } + "incorrect" { set info "Failed to telnet to $target as $usercode, incorrect usercode" + return -code error -errorinfo $info $info + } + "failure" { set info "Failed to telnet to $target as $usercode" + return -code error -errorinfo $info $info + } + "refused" { set info "Failed to telnet to $target as $usercode" + return -code error -errorinfo $info $info + } + "nknown" { set info "Failed to telnet to $target as $usercode" + return -code error -errorinfo $info $info + } + "$target_unix_prompt" noop + } + + return 0 +} + +proc target_chassis_telnet {target usercode password} { +## +## target_chassis_telnet +## ------------------- +## telnet to the given target chassis +## +## Usage: +## target_chassis_telnet target usercode password +## Arguments: +## target - chassis name to telnet to +## usercode - usercode +## password - password +## Returns: +## 0 - success +## -code error on failure + global spawn_id expect_out spawn_out timeout + global expecting + global stty_init + global target_chassis_prompt + global target_chassis_shell target_chassis_shell_prompt + global target_chassis_retry_limit + + set target_chassis_shell 0 + test_spawn "telnet" telnet $target + set_timeout 120 + set expecting "telnet session ($target $usercode)" + set retries 0 + expect { + "ogin:" { exp_send "$usercode\r" + set retries [ expr $retries + 1 ] + if { $retries > $target_chassis_retry_limit } { + set info "Failed to telnet to $target as $usercode" + return -code error -errorinfo $info $info + } + exp_continue + } + "sername:" { exp_send "$usercode\r" + set retries [ expr $retries + 1 ] + if { $retries > $target_chassis_retry_limit } { + set info "Failed to telnet to $target as $usercode" + return -code error -errorinfo $info $info + } + exp_continue + } + "sername->" { exp_send "$usercode\r" + set retries [ expr $retries + 1 ] + if { $retries > $target_chassis_retry_limit } { + set info "Failed to telnet to $target as $usercode" + return -code error -errorinfo $info $info + } + exp_continue + } + "assword:" { exp_send "$password\r" + exp_continue + } + "assword->" { exp_send "$password\r" + exp_continue + } + "incorrect" { set info "Failed to telnet to $target as $usercode, incorrect usercode" + return -code error -errorinfo $info $info + } + "failure" { set info "Failed to telnet to $target as $usercode" + return -code error -errorinfo $info $info + } + "refused" { set info "Failed to telnet to $target as $usercode" + return -code error -errorinfo $info $info + } + "nknown" { set info "Failed to telnet to $target as $usercode" + return -code error -errorinfo $info $info + } + -gl "$target_chassis_shell_prompt" { set target_chassis_shell 1 } + -gl "$target_chassis_prompt" noop + } + + return 0 +} + + +proc target_ssh { target usercode password } { +## +## target_ssh +## ------------------- +## ssh to the given target host +## +## Usage: +## target_ssh target usercode password +## Arguments: +## target - hostname to ssh to +## usercode - usercode +## password - password +## Returns: +## 0 - success +## -code error on failure + + global spawn_id expect_out spawn_out timeout + global expecting + global stty_init + global target_unix_prompt + + test_spawn "ssh" ssh -q $usercode@$target + set_timeout 30 + set expecting "ssh session ($target $usercode)" + expect { + "assword:" { exp_send "$password\r" + exp_continue + } + "denied" { set info "Failed to ssh to $target as $usercode, incorrect password" + return -code error -errorinfo $info $info + } + "failure" { set info "Failed to ssh to $target as $usercode" + return -code error -errorinfo $info $info + } + "refused" { set info "Failed to ssh to $target as $usercode" + return -code error -errorinfo $info $info + } + "nknown" { set info "Failed to ssh to $target as $usercode" + return -code error -errorinfo $info $info + } + "ast login" { + noop + } + "$target_unix_prompt" noop + } + + return 0 +} + +proc target_chassis_ssh { target usercode password } { +## +## target_chassis_ssh +## ------------------- +## ssh to the given target chassis +## +## Usage: +## target_chassis_ssh target usercode password +## Arguments: +## target - chassis to ssh to +## usercode - usercode +## password - password +## Returns: +## 0 - success +## -code error on failure + + global spawn_id expect_out spawn_out timeout + global expecting + global stty_init + global target_chassis_prompt + global target_chassis_shell target_chassis_shell_prompt + global target_chassis_retry_limit + + set target_chassis_shell 0 + test_spawn "ssh" ssh -q $usercode@$target + set_timeout 60 + set expecting "ssh session ($target $usercode)" + set retries 0 + expect { + "ogin:" { exp_send "$usercode\r" + set retries [ expr $retries + 1 ] + if { $retries > $target_chassis_retry_limit } { + set info "Failed to telnet to $target as $usercode" + return -code error -errorinfo $info $info + } + exp_continue + } + "sername:" { exp_send "$usercode\r" + set retries [ expr $retries + 1 ] + if { $retries > $target_chassis_retry_limit } { + set info "Failed to telnet to $target as $usercode" + return -code error -errorinfo $info $info + } + exp_continue + } + "sername->" { exp_send "$usercode\r" + set retries [ expr $retries + 1 ] + if { $retries > $target_chassis_retry_limit } { + set info "Failed to telnet to $target as $usercode" + return -code error -errorinfo $info $info + } + exp_continue + } + "assword:" { exp_send "$password\r" + exp_continue + } + "assword->" { exp_send "$password\r" + exp_continue + } + "denied" { set info "Failed to ssh to $target as $usercode, incorrect password" + return -code error -errorinfo $info $info + } + "failure" { set info "Failed to ssh to $target as $usercode" + return -code error -errorinfo $info $info + } + "refused" { set info "Failed to ssh to $target as $usercode" + return -code error -errorinfo $info $info + } + "nknown" { set info "Failed to ssh to $target as $usercode" + return -code error -errorinfo $info $info + } + "continue connecting" { exp_send "yes\n" + exp_continue + } + "ast login" { + noop + } + -gl "$target_chassis_shell_prompt" { set target_chassis_shell 1 } + -gl "$target_chassis_prompt" noop + } + + return 0 +} + +proc target_chassis_rlogin_slot {slot usercode password} { +## +## target_chassis_rlogin_slot +## ------------------- +## rlogin to the given slot within the present chassis +## This should only be called by target_chassis_admin_sh +## otherwise tracking of shell vs cli prompt will be incorrect +## +## Usage: +## target_chassis_rlogin_slot slot usercode password +## Arguments: +## slot - slot to login to +## usercode - usercode +## password - password +## Returns: +## 0 - success +## -code error on failure + global spawn_id expect_out spawn_out timeout + global expecting + global stty_init + global target_chassis_prompt + global target_chassis_shell target_chassis_shell_prompt + global target_chassis_retry_limit + global target_chassis_shell_save + + set target_chassis_shell_save $target_chassis_shell + send_chassis_cmd "rlogin $slot" + set_timeout 60 + set expecting "rlogin session to slot $slot ($usercode)" + set retries 0 + expect { + "sername:" { exp_send "$usercode\r" + set retries [ expr $retries + 1 ] + if { $retries > $target_chassis_retry_limit } { + set info "Failed to rlogin to slot $slot as $usercode" + return -code error -errorinfo $info $info + } + exp_continue + } + "sername->" { exp_send "$usercode\r" + set retries [ expr $retries + 1 ] + if { $retries > $target_chassis_retry_limit } { + set info "Failed to rlogin to slot $slot as $usercode" + return -code error -errorinfo $info $info + } + exp_continue + } + "assword:" { exp_send "$password\r" + exp_continue + } + "assword->" { exp_send "$password\r" + exp_continue + } + "incorrect" { set info "Failed to rlogin to slot $slot as $usercode, incorrect usercode" + return -code error -errorinfo $info $info + } + "failure" { set info "Failed to rlogin to slot $slot as $usercode" + return -code error -errorinfo $info $info + } + "refused" { set info "Failed to rlogin to slot $slot as $usercode" + return -code error -errorinfo $info $info + } + "nknown" { set info "Failed to rlogin to slot $slot as $usercode" + return -code error -errorinfo $info $info + } + "orry" { set info "Failed to rlogin to slot $slot as $usercode" + return -code error -errorinfo $info $info + } + "not responding" { set info "Failed to rlogin to slot $slot as $usercode" + return -code error -errorinfo $info $info + } + -gl "$target_chassis_shell_prompt" { set target_chassis_shell 1 } + -gl "$target_chassis_prompt" { set target_chassis_shell 0 } + } + + return 0 +} + +proc send_unix { text } { +## +## send_unix +## ------------------- +## send a interactive response to a unix command during a login session +## +## Usage: +## send_unix text +## Arguments: +## text - text to send +## Returns: +## nothing +## Additional Information: +## Do NOT use this to send commands. +## send_unix_cmd or unix_cmd should be used for that purpose + + global spawn_id expect_out spawn_out + + exp_send "$text" +} + +proc send_chassis { text } { +## +## send_chassis +## ------------------- +## send a interactive response to a chassis command during a login session +## +## Usage: +## send_chassis text +## Arguments: +## text - text to send +## Returns: +## nothing +## Additional Information: +## Do NOT use this to send commands. +## send_chassis_cmd or chassis_cmd should be used for that purpose + global spawn_id expect_out spawn_out + + exp_send "$text" +} + +proc target_set_intr {} { +## +## target_set_intr +## ---------------- +## set the interrupt character to control-C +## +## Usage: +## target_set_intr +## Returns: +## 0 - success +## -code error on failure + + unix_cmd 60 0 "stty intr ^C" +} + +proc target_send_intr {} { +## +## target_send_intr +## ---------------- +## set the interrupt character (eg. control-C) to a host +## +## Usage: +## target_send_intr +## Returns: +## 0 - success +## -code error on failure + + global spawn_id expect_out spawn_out timeout + + exp_send "\003" +} + +proc chassis_send_intr {} { +## +## chassis_send_intr +## ---------------- +## set the interrupt character (eg. control-C) to a chassis +## +## Usage: +## chassis_send_intr +## Returns: +## 0 - success +## -code error on failure + + global spawn_id expect_out spawn_out timeout + + exp_send "\003" +} + +proc target_set_noecho {} { +## +## target_set_noecho +## ---------------- +## disable echo during a unix login session or sh +## +## Usage: +## target_set_noecho +## Returns: +## 0 - success +## -code error on failure + + unix_cmd 60 0 "stty -echo" +} + +proc target_set_echo {} { +## +## target_set_echo +## ---------------- +## enable echo during a unix login session or sh +## +## Usage: +## target_set_echo +## Returns: +## 0 - success +## -code error on failure + + unix_cmd 60 0 "stty echo" +} + +proc target_su { usercode {password "" }} { +## +## target_su +## ------------------- +## change usercode during a unix login session +## +## Usage: +## target_su usercode [password] +## Arguments: +## usercode - usercode +## password - password, if omitted assumes no password needed +## Returns: +## 0 - success +## -code error on failure + + global spawn_id expect_out spawn_out timeout + global expecting env + global target_unix_prompt + + send_unix_cmd "su - $usercode" + set_timeout 120 + set expecting "su session ($usercode)" + expect { + "assword:" { if { "$password" == "" } { + set info "Failed to su $usercode, password required" + return -code error -errorinfo $info $info + } else { + exp_send "$password\n" + exp_continue + } + } + "Sorry" { set info "Failed to su $usercode, incorrect password" + return -code error -errorinfo $info $info + } + "$target_unix_prompt" noop + } + + #unix_cmd 60 0 "ksh" + target_set_env + + return 0 +} + +proc target_su_exit { } { +## +## target_su_exit +## ------------------- +## exit super user shell created by target_su +## +## Usage: +## target_su_exit +## Returns: +## 0 - success +## -code error on failure + + global env + + # exit ksh + #unix_cmd 60 "" "exit 0" + # exit su + unix_cmd 60 "" "exit 0" +} + +proc target_set_env { } { +## +## target_set_env +## ------------------- +## setup environment for unix shell session to allow testing +## +## Usage: +## target_set_env +## Arguments: +## None +## Returns: +## 0 - success +## -code error on failure + + # set COLUMNS real large so the Posix shell doesn't enter + # command edit mode and confuse us + #unix_cmd 60 "" "export COLUMNS=500" + #unix_cmd 60 "" "unset EDITOR" + #unix_cmd 60 "" "unset VISUAL" + #unix_cmd 60 "" "umask 0" + #target_set_intr + # get rid of cr and control characters in logs for easier reading + unix_cmd 60 0 {unset PROMPT_COMMAND HISTFILE; set +o history; export PS1='[\u@\h]\$ '; stty -onlcr columns 500} +} + +proc target_root_sh { target } { +## +## target_root_sh +## ---------------- +## prepare for a test by login'ing to target host as user root +## +## Usage: +## target_root_sh target +## +## Arguments: +## target - hostname to login to +## Returns: +## 0 - success +## -code error on failure +## Additional Information: +## uses: +## env(CFG_LOGIN_METHOD) to select between rlogin or ssh +## env(CFG_USERNAME) as a non-root user name for rlogin (followed by su) +## env(CFG_PASSWORD) as password for CFG_USERNAME for rlogin +## env(CFG_ROOTPASS) as root password for ssh or su + + global env + + if { "$env(CFG_LOGIN_METHOD)" == "rlogin" } { + target_rlogin $target $env(CFG_USERNAME) $env(CFG_PASSWORD) + target_su root $env(CFG_ROOTPASS) + } elseif { "$env(CFG_LOGIN_METHOD)" == "telnet" } { + target_telnet $target $env(CFG_USERNAME) $env(CFG_PASSWORD) + target_su root $env(CFG_ROOTPASS) + } elseif { "$env(CFG_LOGIN_METHOD)" == "ssh" } { + target_ssh $target root $env(CFG_ROOTPASS) + target_set_env + } else { + set info "CFG_LOGIN_METHOD must be rlogin, telnet or ssh" + return -code error -errorinfo $info $info + } + + return 0 +} + +proc target_root_sh_exit { } { +## +## target_root_sh_exit +## ---------------- +## exit from shell connection created by target_root_sh +## +## Usage: +## target_root_sh_exit +## +## Returns: +## 0 - success +## -code error on failure +## uses: +## env(CFG_LOGIN_METHOD) to select between rlogin or ssh + + global env + + if { "$env(CFG_LOGIN_METHOD)" == "rlogin" } { + target_su_exit + } elseif { "$env(CFG_LOGIN_METHOD)" == "telnet" } { + target_su_exit + } elseif { "$env(CFG_LOGIN_METHOD)" == "ssh" } { + #unix_cmd 60 "" "exit 0" + send_unix_cmd "exit 0" + } else { + set info "CFG_LOGIN_METHOD must be rlogin, telnet or ssh" + return -code error -errorinfo $info $info + } + + ignore_rest + + return 0 +} + +proc target_chassis_admin_sh { target {slot ""} {user "admin"}} { +## +## target_chassis_admin_sh +## ---------------- +## prepare for a test by login'ing to chassis as user admin +## +## Usage: +## target_chassis_admin_sh target [slot] [user] +## +## Arguments: +## target - chassis to login to +## slot - slot to login to, default is "" +## user - user code to login as, default is admin +## Returns: +## 0 - success +## -code error on failure +## Additional Information: +## uses: +## env(CFG_CHASSIS_LOGIN_METHOD) to select between telnet or ssh +## env(CFG_CHASSIS_ADMIN_PASSWORD) as password for admin (if no password-less ssh) + + global env + + if { "$env(CFG_CHASSIS_LOGIN_METHOD)" == "ssh" } { + target_chassis_ssh $target $user $env(CFG_CHASSIS_ADMIN_PASSWORD) + } elseif { "$env(CFG_CHASSIS_LOGIN_METHOD)" == "telnet" } { + target_chassis_telnet $target $user $env(CFG_CHASSIS_ADMIN_PASSWORD) + } else { + set info "CFG_CHASSIS_LOGIN_METHOD must be ssh or telnet" + return -code error -errorinfo $info $info + } + if { "$slot" != "" } { + target_chassis_rlogin_slot $slot $user $env(CFG_CHASSIS_ADMIN_PASSWORD) + } + + return 0 +} + +proc target_chassis_admin_sh_exit { {rlogin 0} } { +## +## target_chassis_admin_sh_exit +## ---------------- +## exit from shell connection created by target_chassis_admin_sh +## +## Usage: +## target_chassis_admin_sh_exit [rlogin] +## Arguments: +## rlogin - are we in an rlogin subshell +## +## Returns: +## 0 - success +## -code error on failure +## uses: + + global target_chassis_shell + global target_chassis_shell_save + + if { $rlogin } { + send_chassis "logout\n" + expect_list 60 "connection closed" + set target_chassis_shell $target_chassis_shell_save + } + send_chassis "logout\n" + set target_chassis_shell 0 + + ignore_rest + + return 0 +} + +proc expect_prompt { timelimit prompt {out_var ""}} { +## +## expect_prompt +## ------------------------- +## wait for prompt during a session +## +## Usage: +## expect_prompt timelimit prompt [out_var] +## Arguments: +## timelimit - maximum wait for shell prompt +## prompt - regular expression for prompt +## out_var - variable in callers context to receive all text which was +## received during during this expect +## Returns: +## 0 - success +## -code error on failure +## Additional Information: + + global spawn_id expect_out spawn_out timeout + + if { "$out_var" != "" } { + upvar $out_var $out_var + } + + expect_list $timelimit "{$prompt}" {} $out_var + + return 0 +} + +proc expect_unix_prompt { timelimit {out_var ""}} { +## +## expect_unix_prompt +## ------------------------- +## wait for a unix/darwin prompt during a session +## +## Usage: +## expect_unix_prompt timelimit [out_var] +## Arguments: +## timelimit - maximum wait for shell prompt +## out_var - variable in callers context to receive all text which was +## received during during this expect +## Returns: +## 0 - success +## -code error on failure +## Additional Information: + global target_unix_prompt + + if { "$out_var" != "" } { + upvar $out_var $out_var + } + return [ expect_prompt $timelimit "$target_unix_prompt" $out_var ] +} + +proc expect_chassis_prompt { timelimit {out_var ""}} { +## +## expect_chassis_prompt +## ------------------------- +## wait for a chassis prompt during a session +## +## Usage: +## expect_chassis_prompt timelimit [out_var] +## Arguments: +## timelimit - maximum wait for shell prompt +## out_var - variable in callers context to receive all text which was +## received during during this expect +## Returns: +## 0 - success +## -code error on failure +## Additional Information: + global target_chassis_prompt + global target_chassis_shell target_chassis_shell_prompt + + if { "$out_var" != "" } { + upvar $out_var $out_var + } + if { $target_chassis_shell } { + set prompt "$target_chassis_shell_prompt" + } else { + set prompt "$target_chassis_prompt" + } + return [ expect_prompt $timelimit "$prompt" $out_var ] +} + +proc target_get_config_stack_type { { host "" } } { +## +## target_get_config_stack_type +## ------------------------- +## get the configured stack type of the specified system. +## +## Usage: +## target_get_config_stack_type host +## Arguments: +## host - host to look for in CFG_OFED_HOSTS +## Returns: +## "OPENIB" or "IBACCESS" +## -code error on failure (eg. unable to identify stack type) +## Additional Information: +## checks for host CFG_OFED_HOSTS and stack type is reported based solely +## on CFG_OFED_HOSTS. If not specified or CFG_OFED_HOSTS is not exported +## then returns an error + global env + + if { "$host" == "" || ! [ info exists env(CFG_OFED_HOSTS) ] } { + set info "Unable to Determine IB Stack Type" + return -code error -errorinfo $info $info + } + set index [ lsearch -exact $env(CFG_OFED_HOSTS) $host ] + if { $index != -1 } { + return "OPENIB" + } else { + return "IBACCESS" + } +} + +proc target_get_stack_type { { checkrun "y"} { host "" } } { +## +## target_get_stack_type +## ------------------------- +## get the stack type of the current target Linux/Unix system. +## +## Usage: +## target_get_stack_type [checkrun [host]] +## Arguments: +## checkrun - if y, the running stack is checked first, otherwise +## just installed stack is checked. Note that during reinstall +## an old stack could be left running until the next reboot +## default is y. Beware, due to newer distros including openib, if it +## appears both are installed and 'n' is used, this reports IBACCESS. +## It is safest to invoke this with 'y'. +## host - if specified and CFG_OFED_HOSTS is exported, then host is looked +## for in CFG_OFED_HOSTS and stack type is reported based solely on +## CFG_OFED_HOSTS. If not specified or CFG_OFED_HOSTS is not exported +## then actual running or installed stack is checked +## Returns: +## "OPENIB" or "IBACCESS" +## -code error on failure (eg. unable to identify stack type) +## Additional Information: +## The global timeout is changed by this routine +## If no IB stack is found running, then checks which stack is installed + + global spawn_id expect_out spawn_out + global env + + # try static lookup first + if { [ catch { target_get_config_stack_type "$host" } res ] == 0 } { + return "$res"; + } + + set target_os_type [target_get_os_type] + + if { "$checkrun" == "y" } { + # ib_umad is a required module for OPEN IB stack + send_unix_cmd {lsmod|egrep '^ib_umad[[:space:]]'} + if { 0 == [ get_exit_status 60 ] } { + return "OPENIB" + } + # ibt is a required module for IbAccess stack + send_unix_cmd {lsmod|egrep '^ibt[[:space:]]'} + if { 0 == [ get_exit_status 60 ] } { + return "IBACCESS" + } + } + + # see if IbAccess installed, 0 -> yes + send_unix_cmd {test -e /etc/init.d/iba -o -e /lib/modules/`uname -r`/iba/ibt.ko} + set iba_not_installed [ get_exit_status 60 ] + + # see if Open IB installed, 0 -> yes + send_unix_cmd {test -e /etc/init.d/openibd -o -e /lib/modules/`uname -r`/kernel/drivers/infiniband/core/ib_umad.ko -o -e /lib/modules/`uname -r`/kernel/drivers/infiniband/core/ib_umad.ko.xz} + set openib_not_installed [ get_exit_status 60 ] + + # newer distros include openib, so if both appear installed also assume iba + # presently this is only called with checkrun=n for automated tests configio + if { ! $iba_not_installed } { + return "IBACCESS" + } + if { $iba_not_installed && ! $openib_not_installed } { + return "OPENIB" + } + set info "Unable to Determine IB Stack Type" + return -code error -errorinfo $info $info +} + +proc target_get_os_type { } { +## +## target_get_os_type +## ------------------------- +## get the os_type of the current target Linux/Darwin/Unix system. +## +## Usage: +## target_get_os_type +## Arguments: +## Returns: +## "Linux" or "Darwin" (eg. uname -s output of target system) +## -code error on failure +## Additional Information: +## The global timeout is changed by this routine + + global spawn_id expect_out spawn_out timeout + global expecting + + set_timeout 60 + # we use SSS around output so we don't mistake other text in output + # (such as in hostname in prompt) for the os_type + send_unix_cmd "echo SSS`uname -s`SSS" + set expecting "target os_type" + expect { + -re {SSS[A-Za-z0-9]+SSS} noop + } + + regexp {SSS([A-Za-z0-9]+)SSS} $expect_out(0,string) line ret + expect_unix_prompt 60 + + return $ret +} + +# TBD - could be moved to TestTools/mpi.exp +# Note: not used by FF, only by Int Tests +proc target_get_registered_mpi_version {mpi_type} { + global spawn_id expect_out spawn_out timeout + global expecting + + # Below cmd to flushing out the out buffet that might contains + # too many lines of screen output, causing the output of a cmd + # not being capture in the output. May be there is other better + # way to clean the out buffet + set out "" + send_unix_cmd "echo SSS`mpi-selector --list`EEE" + expect_list 60 { "mpi-selector" "EEE" "EEE" } {} out + + set out "" + send_unix_cmd "echo SSS`mpi-selector --list`EEE" + expect_list 60 { "mpi-selector" "EEE" "EEE" } {} out + + regexp "EEE.*SSS+(.*)EEE$" $out full_out mpi_list + + check_exit_status 60 0 + + if {![regexp "($mpi_type)-(\[^ ]+)" $mpi_list line mpi_type_match mpi_version]} { + set info "Did not find mpi_type($mpi_type) in mpi_list($mpi_list)" + return -code error -errorinfo $info $info + } + + return $mpi_version +} + +proc get_exit_status { timelimit { wait_prompt 1 } } { +## +## get_exit_status +## ------------------------- +## wait for shell prompt and return the exit status of the last command executed +## during a login session, then wait for shell prompt +## +## Usage: +## get_exit_status timelimit [wait_prompt] +## Arguments: +## timelimit - maximum wait for shell prompt +## wait_prompt - should we wait for prompt before issuing echo of status +## Returns: +## exit code - success +## -code error on failure +## Additional Information: +## The global timeout is changed by this routine + + global spawn_id expect_out spawn_out timeout + global expecting + + if { $wait_prompt } { + expect_unix_prompt $timelimit + } + + set_timeout 60 + # we use SSS around number so we don't mistake other numbers in output + # (such as in hostname in prompt) for the exit code + send_unix_cmd "echo SSS$?SSS" + set expecting "exit code" + expect { + -re {SSS[0-9]+SSS} noop + } + + regexp {[0-9]+} $expect_out(0,string) ret + expect_unix_prompt 60 + + return $ret +} + +proc check_exit_status { timelimit exit_code { wait_prompt 1 } } { +## +## check_exit_status +## ------------------------- +## wait for shell prompt and check the exit status of the last command executed +## during a login session, then wait for shell prompt +## +## Usage: +## check_exit_status timelimit exit_code [wait_prompt] +## Arguments: +## timelimit - maximum wait for shell prompt +## exit_code - expected exit code ([0-9] if don't care) +## wait_prompt - should we wait for prompt before issuing echo of status +## Returns: +## 0 - success +## -code error on failure +## Additional Information: +## The global timeout is changed by this routine + + global spawn_id expect_out spawn_out timeout + global expecting + + if { $wait_prompt } { + expect_unix_prompt $timelimit + } + + set_timeout 60 + # we use SSS around number so we don't mistake other numbers in output + # (such as in hostname in prompt) for the exit code + send_unix_cmd "echo SSS$?SSS" + set expecting "exit code: $exit_code" + expect { + "SSS${exit_code}SSS" noop + -re {SSS[0-9]+SSS} { set info "Incorrect exit code: Expected $exit_code, Got: $expect_out(0,string)" + return -code error -errorinfo $info $info + } + } + + expect_unix_prompt 60 + + return 0 +} + +proc get_chassis_exit_status { timelimit { wait_prompt 1 } } { +## +## get_chassis_exit_status +## ------------------------- +## wait for shell prompt and return the exit status of the last command executed +## during an chassis session, then wait for shell prompt +## +## Usage: +## get_exit_status timelimit [wait_prompt] +## Arguments: +## timelimit - maximum wait for shell prompt +## wait_prompt - should we wait for prompt before issuing echo of status +## Returns: +## 0 - success +## -code error on failure +## Additional Information: +## The global timeout is changed by this routine + + global spawn_id expect_out spawn_out timeout + global expecting + + if { $wait_prompt } { + expect_chassis_prompt $timelimit + } + + set_timeout 60 + send_chassis_cmd "showLastRetCode" + set expecting "exit code" + expect { + -re {Code: [0-9]+:} noop + } + + regexp {[0-9]+} $expect_out(0,string) ret + expect_chassis_prompt 60 + + return $ret +} + +proc check_chassis_exit_status { timelimit exit_code { wait_prompt 1 } } { +## +## check_chassis_exit_status +## ------------------------- +## wait for shell prompt and check the exit status of the last command executed +## during an chassis session, then wait for shell prompt +## +## Usage: +## check_exit_status timelimit exit_code [wait_prompt] +## Arguments: +## timelimit - maximum wait for shell prompt +## exit_code - expected exit code ([0-9] if don't care) +## wait_prompt - should we wait for prompt before issuing echo of status +## Returns: +## 0 - success +## -code error on failure +## Additional Information: +## The global timeout is changed by this routine + + global spawn_id expect_out spawn_out timeout + global expecting + + if { $wait_prompt } { + expect_chassis_prompt $timelimit + } + + set_timeout 60 + send_chassis_cmd "showLastRetCode" + set expecting "exit code: $exit_code" + expect { + "Code: ${exit_code}:" noop + -re {Code: [0-9]+:} { set info "Incorrect exit code: Expected $exit_code, Got: $expect_out(0,string)" + return -code error -errorinfo $info $info + } + } + expect_chassis_prompt 60 + + return 0 +} + +proc longcmd { cmd } { +## +## longcmd +## -------- +## Add newlines and backslashes to a command to avoid command line editor +## +## Usage: +## longcmd cmd +## Arguments: +## cmd - a shell command to break up into multiple lines +## Returns: +## A command to execute +## +## Additional Information: +## On some platforms the command line editor cannot be turned off. On other +## platforms setting COLUMNS=500, unset EDITOR and unset VISUAL would +## cause the command line editor to not affect entry of long command lines +## Unfortunately, the entry of such long +## lines causes the command line editor to re-display the line +## including the # or $ prompt. This makes the expect scripts think the +## command has completed before it has even started. +## + if { [ string length $cmd ] < 70 } { + return $cmd + } + # break up every 70th character + set result {} + while { [ string length $cmd ] > 0 } { + append result [string range $cmd 0 69 ] + append result "\\\n" + set cmd [ string range $cmd 70 end ] + } + return $result +} + +proc send_unix_cmd { cmd { separator "\n"} } { +## +## send_unix_cmd +## ------------------- +## issue a unix command to the target system during a login session +## +## Usage: +## send_unix_cmd cmd [separator] +## Arguments: +## cmd - unix command to issue +## separator - separator at end of command, default is newline +## Returns: +## nothing +## Additional Information: +## This must be used to send any command which could be larger than +## 70 characters and for which the first expect is for a shell prompt +## If there are other expect's before the wait for the shell prompt, +## a simple send can also be used +## +## Do NOT use this to send responses to interactive commands. +## exp_send should be used for that purpose + + global spawn_id expect_out spawn_out timeout + global env + + exp_send "$cmd$separator" + # possible workaround if command line editor gets involved + #exp_send [ longcmd "$cmd$separator" ] +} + +proc send_chassis_cmd { cmd } { +## +## send_chassis_cmd +## ------------------- +## issue a command to the target chassis during a login session +## +## Usage: +## send_chassis_cmd cmd +## Arguments: +## cmd - chassis command to issue +## Returns: +## nothing +## Additional Information: +## This should be used to send all chassis commands. It handles +## the support shell vs cli interface as needed. The decision as to +## type of shell inteface is made per chassis during login. +## +## Do NOT use this to send responses to interactive commands. +## exp_send should be used for that purpose +## +## unlike send_unix_cmd, there is no "separator" argument. This is for a +## few reasons: +## - implementation with target_chassis_shell could be tricky +## - older versions of chassis FW only allowed newline as the separator + + global spawn_id expect_out spawn_out timeout + global env + global target_chassis_shell + + if { $target_chassis_shell } { + exp_send "cli \"$cmd\"\n" + } else { + exp_send "$cmd\n" + } +} + +proc unix_cmd { timelimit exit_code cmd } { +## +## unix_cmd +## ------------------- +## issue a unix command to the target system during a login session +## +## Usage: +## unix_cmd timelimit exit_code cmd +## Arguments: +## timelimit - maximum wait for command to complete (shell prompt) +## exit_code - expected exit code ("" if don't care) +## cmd - unix command to issue +## Returns: +## 0 - success +## -code error on failure +## Additional Information: +## The global timeout is changed by this routine + + global spawn_id expect_out spawn_out timeout + global env + + + if { "$exit_code" != "" } { + send_unix_cmd $cmd ";" + check_exit_status $timelimit $exit_code 0 + } else { + send_unix_cmd $cmd + expect_unix_prompt $timelimit + } + + return 0 +} + +proc chassis_cmd { timelimit exit_code cmd } { +## +## chassis_cmd +## ------------------- +## issue a chassis command to the target system during a login session +## +## Usage: +## chassis_cmd timelimit exit_code cmd +## Arguments: +## timelimit - maximum wait for command to complete (shell prompt) +## exit_code - expected exit code ("" if don't care) +## cmd - chassis command to issue +## Returns: +## 0 - success +## -code error on failure +## Additional Information: +## The global timeout is changed by this routine + + global spawn_id expect_out spawn_out timeout + global env + + if { "$exit_code" != "" } { + send_chassis_cmd $cmd + check_chassis_exit_status $timelimit $exit_code + } else { + send_chassis_cmd $cmd + expect_chassis_prompt $timelimit + } + + return 0 +} + +proc host_send_unix_cmd { host cmd { separator "\n"} } { +## +## host_send_unix_cmd +## ------------------- +## issue a unix command to host via the target system during a login session +## +## Usage: +## host_send_unix_cmd host cmd [separator] +## Arguments: +## host - host to issue command to +## cmd - unix command to issue +## separator - separator at end of command, default is newline +## Returns: +## nothing +## Additional Information: +## This must be used to send any command which could be larger than +## 70 characters and for which the first expect is for a shell prompt +## If there are other expect's before the wait for the shell prompt, +## a simple send can be used + + global spawn_id expect_out spawn_out timeout + global env + + exp_send "ssh -q -o ForwardX11=no -P root@$host $cmd$separator" + # possible workaround if command line editor gets involved + #exp_send [ longcmd "ssh -q -o ForwardX11=no -P root@$host $cmd$separator" ] +} + +proc opacmdall_stop_child { spawn_id } { +## +## opacmdall_stop_child +## ---------- +## stop the given child process +## provided for use by opacmdall only +## This avoids use of the test infrastructure +## +## Usage: +## opacmdall_stop_child spawn_id +## Arguments: +## spawn_id - spawn id's from spawn +## Returns: +## exit status of process +## or -code error if unable to wait for process + + global errorCode + + # see if child still running + if { [catch {set pid [exp_pid -i $spawn_id]}] == 1 } { + # child must already be dead + #puts "Child exited" + } else { + #puts "Stopping $pid" + # terminate child + catch {exp_close -i $spawn_id } + catch {exec kill -s INT $pid } + #catch {exec kill -s TERM $pid } + } + set status {} + catch {set status [exp_wait -i $spawn_id] } + # return the exit status of the process + # exp_wait returns a list: + # { pid spawn_id OS_ret exit_status } + # if OS_ret is 0, status is process exit status + # if OS_ret is -1, status is OS errno and errorCode also set + # if child was killed, there can be 3 more elements in list: + # { pid spawn_id 0 0 CHILDKILLED signal desc} + if { [ llength $status ] < 4 } { + set info "wait for child failed" + return -code error -errorinfo $info $info + } elseif { [ lindex $status 4] == "CHILDKILLED" } { + set info "child killed: [lrange $status 5 end]" + return -code error -errorinfo $info $info + } elseif { [ lindex $status 2 ] == 0 } { + # process exited + set exit_status [ lindex $status 3] + return $exit_status + } else { + # OS error running wait + set info "wait for child failed: $errorCode" + return -code error -errorinfo $info $info + } +} + +proc host_run_cmd { host user cmd {quiet 0} {timelimit -1} {prefix ""} } { +## +## host_run_cmd +## ------------------- +## issue a unix command to host directly via ssh +## provided for use by opacmdall only +## This avoids use of the test infrastructure +## +## Usage: +## host_run_cmd host user cmd [[[quiet] timelimit] prefix] +## Arguments: +## host - host to issue command to +## user - user code to connect to host as +## cmd - unix command to issue +## quiet - if 1 command is not shown +## timelimit - maximum time to allow for command to complete, -1-> unlimited +## prefix - prefix to output at start of every line output by host +## Returns: +## nothing +## Additional Information: +## errors are caught and output to stderr + + global spawn_id expect_out spawn_out timeout errorCode + global env + + if { ! $quiet } { + puts "$prefix\[$user@$host\]# $cmd" + } + if { $timelimit <= 0 } { + set timelimit -1 + } + + if { $timelimit == -1 && [string equal "$prefix" "" ] } { + if { [ catch { exec ssh -q -o ForwardX11=no -P "$user@$host" "$cmd" >@ stdout 2>@ stderr } res ] != 0 } { + set exit_status [concat $errorCode] + if { [ lindex $exit_status 0 ] == "CHILDSTATUS" } { + set res "child exit code: [lindex $exit_status 2]" + } elseif { [ lindex $exit_status 0 ] == "CHILDKILLED" } { + set res "child killed: [lrange $exit_status 2 end]" + } else { + set res "$res: $errorCode" + } + puts stderr "$prefix$user@$host: $cmd: Command execution FAILED: $res" + } + } else { + global spawn_id user_spawn_id expect_out spawn_out timeout + # disable normal output so we can insert prefix + set save_log_user [log_user -info] + if { [ catch { + log_user 0 + spawn -noecho ssh -q -o ForwardX11=no -P "$user@$host" "$cmd" + # do not use TEST_TIMEOUT_MULT + set timeout $timelimit + expect { + \n {puts -nonewline "$prefix$expect_out(buffer)"; exp_continue -continue_timer} + \r {puts -nonewline "$prefix$expect_out(buffer)"; exp_continue -continue_timer} + eof { + # handle output without newline at end + if { ! [ string equal "$expect_out(buffer)" "" ] } { + puts "$prefix$expect_out(buffer)" + + } + } + timeout {return -code error -errorinfo "Timeout" "Timeout" } + } + #interact { + # -input $user_spawn_id + # timeout [ calc_timeout $timelimit ] { + # #puts "Timeout" + # return -code error -errorinfo "Timeout" "Timeout" + # } + # \003 { + # #puts "Interrupted" + # return -code error -errorinfo "Interrupted" "Interrupted" + # } + # -output $spawn_id + # eof return + #} + set ret [opacmdall_stop_child $spawn_id] + if { $ret != 0 } { + set info "child exit code: $ret" + return -code error -errorinfo $info $info + } + } res ] != 0 } { + catch { opacmdall_stop_child $spawn_id } + puts stderr "$prefix$user@$host: $cmd: Command execution FAILED: $res" + } + log_user $save_log_user + } +} + +proc chassis_run_cmd { chassis user cmd {quiet 0} {slot ""} {marker ""} {prefix ""}} { +## +## chassis_run_cmd +## ------------------- +## issue a chassis command to chassis +## provided for use by opacmdall only +## +## Usage: +## chassis_run_cmd host user cmd [quiet [slot [marker]]] +## Arguments: +## chassis - chassis to issue command to +## user - user code to connect to chassis as +## cmd - chassis CLI command to issue +## quiet - if 1 command is not shown +## slot - slot to login to, default is "" +## marker - marker for end of command output, otherwise first instance of +## prompt marks end of data. When marker is supplied, prompts which +## preceed marker are ignored, but a final prompt is still waited for +## after the marker +## prefix - prefix to output at start of every line output by host +## Returns: +## nothing +## Additional Information: +## errors are caught and output to stderr + + global spawn_id expect_out spawn_out timeout + global env + global target_chassis_prompt + global target_chassis_shell target_chassis_shell_prompt + global log_disable + + # disable detailed logging to stdout + log_user 0 + set log_disable 1 + setup_expect_after + if { ! $quiet } { + if { "$slot" != "" } { + puts "$prefix\[$user@$chassis:$slot\]# $cmd" + } else { + puts "$prefix\[$user@$chassis\]# $cmd" + } + } + if { [ catch { target_chassis_admin_sh "$chassis" "$slot" "$user" } res ] != 0 } { + puts stderr "$prefix$user@$chassis: $cmd: Command execution FAILED (Login): $res" + return + } + if { $target_chassis_shell } { + set prompt "$target_chassis_shell_prompt" + } else { + set prompt "$target_chassis_prompt" + } + if { [ catch { + send_chassis_cmd "$cmd" + set out "" + if { "$marker" == "" } { + expect_progress 120 {[\r\n\b]} "{$prompt}" {} out + } else { + expect_progress 120 {[\r\n\b]} "{$marker} {$prompt}" {} out + } + } res ] != 0 } { + puts stderr "$prefix$user@$chassis: $cmd: Command execution FAILED: $res" + } elseif { [ catch { + # filter out $cmd at start + set match [string first "$cmd" "$out"] + set length [string length "$cmd" ] + if { $match != -1 } { + set out [string range "$out" [expr $match + $length] end] + } + # filter out prompt + if { "$marker" == "" } { + regexp "\[\\\r\\\n\]+(.*)${prompt}" "$out" full_out output + } else { + regexp "\[\\\r\\\n\]+(.*$marker.*)${prompt}" "$out" full_out output + } + if { ! [string equal "$prefix" "" ] } { + # insert prefix + regsub -all -line {^.*$} "$output" "$prefix\\0" new_output + # if last character is not newline add one + set lastchar [string index $new_output end ] + if { "$lastchar" != {\n} && "$lastchar" != {\r} } { + puts stdout $new_output + } else { + puts -nonewline stdout $new_output + } + } else { + puts -nonewline stdout $output + } + check_chassis_exit_status 60 0 0 + } res ] != 0 } { + puts stderr "$prefix$user@$chassis: $cmd: Command execution FAILED: $res" + } + catch { target_chassis_admin_sh_exit [expr {"$slot" != ""} ] } +} + +proc hosts_run_cmd { hosts user cmd {quiet 0} {timelimit -1} {output_prefix 0} } { +## +## hosts_run_cmd +## ------------------- +## issue a unix command to hosts directly via ssh +## provided for use by opacmdall only +## This avoids use of the test infrastructure +## +## Usage: +## hosts_run_cmd hosts user cmd [[[quiet] timelimit] output_prefix] +## Arguments: +## hosts - hosts to issue command to, if "" uses $env(CFG_HOSTS) +## user - user code to connect to host as +## cmd - unix command to issue +## quiet - if 1 command is not shown +## timelimit - maximum time to allow for command to complete, -1-> unlimited +## output_prefix - should host: be output as a prefix to each line +## Returns: +## nothing +## Additional Information: +## errors are caught and output to stderr + + global env + if { "$hosts" == "" } { + set hosts $env(CFG_HOSTS) + } + foreach host $hosts { + if { $output_prefix } { + set prefix "$host: " + } else { + set prefix "" + } + host_run_cmd $host $user "$cmd" $quiet $timelimit "$prefix" + } +} + +# pardon my spelling but I need a plural version of chassis +# which has a different spelling so function names are unique +proc chassises_run_cmd { chassises user cmd {quiet 0} {marker ""} {output_prefix 0}} { +## +## chassises_run_cmd +## ------------------- +## issue a chassis command to chassises directly via ssh +## provided for use by opacmdall only +## +## Usage: +## chassises_run_cmd hosts user cmd [[quiet [marker]] output_prefix] +## Arguments: +## chassises - chassises to issue command to, if "" uses $env(CFG_CHASSIS) +## can have slot specifier per chassis entry +## user - user code to connect to host as +## cmd - unix command to issue +## quiet - if 1 command is not shown +## marker - marker for end of command output, otherwise first instance of +## prompt marks end of data. When marker is supplied, prompts which +## preceed marker are ignored, but a final prompt is still waited for +## after the marker +## output_prefix - should host: be output as a prefix to each line +## Returns: +## nothing +## Additional Information: +## errors are caught and output to stderr + + global env + if { "$chassises" == "" } { + set chassises $env(CFG_CHASSIS) + } + foreach chassis $chassises { + set slots [chassis_get_slots "$chassis"] + set chassis [chassis_strip_slots "$chassis"] + foreach slot $slots { + if { "$slot" == "all" } { + set slot "" + } + if { $output_prefix } { + if { "$slot" != "" } { + set prefix "$chassis:$slot: " + } else { + set prefix "$chassis: " + } + } else { + set prefix "" + } + chassis_run_cmd $chassis $user "$cmd" $quiet $slot "$marker" "$prefix" + } + } +} + +proc hosts_parallel_run_cmd { hosts user cmd {quiet 0} {timelimit -1} {output_prefix 0}} { +## +## hosts_parallel_run_cmd +## ------------------- +## issue a unix command to hosts directly via ssh, in parallel on all hosts +## provided for use by opacmdall only +## This avoids use of the test infrastructure +## +## Usage: +## hosts_parallel_run_cmd hosts user cmd [[[quiet] timelimit] output_prefix] +## Arguments: +## hosts - hosts to issue command to, if "" uses $env(CFG_HOSTS) +## user - user code to connect to host as +## cmd - unix command to issue +## quiet - if 1 command is not shown +## timelimit - maximum time to allow for command to complete, -1-> unlimited +## output_prefix - should host: be output as a prefix to each line +## Returns: +## nothing +## Additional Information: +## errors are caught and output to stderr + + global env + global os_type + if { "$hosts" == "" } { + set hosts $env(CFG_HOSTS) + } + parallel host $hosts { + if { $output_prefix } { + set prefix "$host: " + } else { + set prefix "" + } + host_run_cmd "$host" $user "$cmd" $quiet $timelimit "$prefix" + } +} + +# pardon my spelling but I need a plural version of chassis +# which has a different spelling so function names are unique +proc chassises_parallel_run_cmd { chassises user cmd {quiet 0} {marker ""} {output_prefix 0}} { +## +## chassises_parallel_run_cmd +## ------------------- +## issue a chassis command to chassises, in parallel on all chassises +## provided for use by opacmdall only +## +## Usage: +## chassises_parallel_run_cmd chassises user cmd [[quiet [marker]] output_prefix] +## Arguments: +## chassises - chassises to issue command to, if "" uses $env(CFG_HOSTS) +## can have slot specifier per chassis entry +## user - user code to connect to chassis as +## cmd - chassis command to issue +## quiet - if 1 command is not shown +## marker - marker for end of command output, otherwise first instance of +## prompt marks end of data. When marker is supplied, prompts which +## preceed marker are ignored, but a final prompt is still waited for +## after the marker +## output_prefix - should host: be output as a prefix to each line +## Returns: +## nothing +## Additional Information: +## errors are caught and output to stderr + + global env + if { "$chassises" == "" } { + set chassises $env(CFG_CHASSIS) + } + parallel chassis $chassises { + set slots [chassis_get_slots "$chassis"] + set chassis [chassis_strip_slots "$chassis"] + foreach slot $slots { + if { "$slot" == "all" } { + set slot "" + } + if { $output_prefix } { + if { "$slot" != "" } { + set prefix "$chassis:$slot: " + } else { + set prefix "$chassis: " + } + } else { + set prefix "" + } + chassis_run_cmd "$chassis" $user "$cmd" $quiet $slot "$marker" "$prefix" + } + } +} + +proc chassis_scp_cmd { scp_cmd } { +## +## chassis_scp_cmd +## ------------------- +## perform an scp to a chassis +## provided for use by opascpall, opauploadall, opadownloadall only +## +## Usage: +## chassis_scp_cmd scp_cmd +## Arguments: +## scp_cmd - scp unix command to issue +## Returns: +## nothing +## Additional Information: +## errors are caught and output to stderr + + global spawn_id expect_out spawn_out timeout + global env + global log_disable + global expecting + + # disable detailed logging to stdout + log_user 0 + set log_disable 1 + + local_sh + send_unix_cmd "$scp_cmd; echo 'SCP IS DONE'" + # handle password prompts, once we start to see progress indicators + # we can do a normal wait progress + set_timeout 120 + set expecting "scp session ($scp_cmd)" + expect { + "assword:" { exp_send "$env(CFG_CHASSIS_ADMIN_PASSWORD)\r" + exp_continue + } + "assword->" { exp_send "$env(CFG_CHASSIS_ADMIN_PASSWORD)\r" + exp_continue + } + "refused" { set info "Failed to $scp_cmd" + return -code error -errorinfo $info $info + } + "denied" { set info "Failed to $scp_cmd" + return -code error -errorinfo $info $info + } + "Error" { set info "Failed to $scp_cmd" + return -code error -errorinfo $info $info + } + "continue connecting" { exp_send "yes\r" + exp_continue + } + {\*} noop + "%" noop + "No such" { set info "Failed to $scp_cmd" + return -code error -errorinfo $info $info + } + } + expect_progress 200 { "\\\*" "\\\." "=" "-" "%" } { "SCP IS DONE" } {"No such" "Error" "Invalid" "lost" } + check_exit_status 60 0 + local_sh_exit + + return 0 +} + +proc chassis_sftp_cmd { sftp_cmd sftp_action { not_found 1 } } { +## +## chassis_sftp_cmd +## ------------------- +## perform an sftp to a chassis +## provided for use by opachassisadmin +## +## Usage: +## chassis_sftp_cmd sftp_cmd sftp_action +## Arguments: +## sftp_cmd - sftp unix command to issue +## sftp_action - sftp command to issue once sftp connection has +## been established +## Returns: +## nothing +## Additional Information: +## errors are caught and output to stderr + + global spawn_id expect_out spawn_out timeout + global env + global log_disable + global expecting + + # disable detailed logging to stdout + log_user 0 + set log_disable 1 + + local_sh + send_unix_cmd "$sftp_cmd; echo 'SFTP IS DONE'" + + # handle password prompts, once we start to see progress indicators + # we can do a normal wait progress + set_timeout 120 + set expecting "sftp session ($sftp_cmd)" + expect { + "assword:" { exp_send "$env(CFG_CHASSIS_ADMIN_PASSWORD)\r" + exp_continue + } + "assword->" { exp_send "$env(CFG_CHASSIS_ADMIN_PASSWORD)\r" + exp_continue + } + "refused" { set info "Failed to $sftp_cmd" + return -code error -errorinfo $info $info + } + "denied" { set info "Failed to $sftp_cmd" + return -code error -errorinfo $info $info + } + "Error" { set info "Failed to $sftp_cmd" + return -code error -errorinfo $info $info + } + "continue connecting" { exp_send "yes\r" + exp_continue + } + "sftp>" { exp_send "$sftp_action\r" + exp_send "bye\r" + } + {\*} noop + "%" noop + "No such" { set info "Failed to $sftp_cmd" + return -code error -errorinfo $info $info + } + } + if { $not_found } { + expect_progress 200 { "\\\*" "\\\." "=" "-" "%" } { "SFTP IS DONE" } {"No such" "Error" "Invalid" "lost" "not found"} + } else { + expect_progress 200 { "\\\*" "\\\." "=" "-" "%" } { "SFTP IS DONE" } {"No such" "Error" "Invalid" "lost"} + } + check_exit_status 60 0 + local_sh_exit + + return 0 +} + +proc host_unix_cmd { timelimit exit_code host cmd } { +## +## host_unix_cmd +## ------------------- +## issue a unix command to host via the target system during a login session +## +## Usage: +## host_unix_cmd timelimit exit_code host cmd +## Arguments: +## timelimit - maximum wait for command to complete (shell prompt) +## exit_code - expected exit code ("" if don't care) +## host - host to issue command to +## cmd - unix command to issue +## Returns: +## 0 - success +## -code error on failure +## Additional Information: +## The global timeout is changed by this routine + + global spawn_id expect_out spawn_out timeout + global env + + if { "$exit_code" != "" } { + host_send_unix_cmd $host $cmd ";" + check_exit_status $timelimit $exit_code 0 + } else { + host_send_unix_cmd $host $cmd + expect_unix_prompt $timelimit + } + + return 0 +} + +proc host_save_log { hostname } { +## +## host_save_log +## ------------------- +## Save OS log file for hostname for later use by check_log +## +## Usage: +## host_save_log hostname +## Arguments: +## hostname - host to save log on, saved to /tmp/log +## Returns: +## 0 - success +## -code error on failure +## Additional Information: + + global tests_dir + + exec "ssh -q root@$hostname '$tests_dir/bin/save_log /tmp/log'" +} + +proc host_check_log { hostname testname } { +## +## host_check_log +## ------------------- +## Check OS log file for hostname relative to last host_save_log +## +## Usage: +## host_check_log hostname testname +## Arguments: +## hostname - host to check log on +## testname - name of test to be used in log filenames +## Returns: +## 0 - success +## -code error on failure +## Additional Information: +## The global timeout is changed by this routine +## assumes already logged into hostname + + global tests_dir + + send_unix_cmd "cd /root/$tests_dir; ./bin/check_log /tmp/log ./logs/$test/$test. ./logs/$test" + + expect_list 120 "DONE" { "ERROR" "WARN" "kernel" } +} + +proc host_basename { hostname } { +## +## host_basename +## ------------------- +## return hostname with any $env(CFG_IPOIB_SUFFIX) or $env(CFG_INIC_SUFFIX) +## suffix removed +## +## Usage: +## host_basename hostname +## Arguments: +## hostname - host name used by test driver (could be an $env(CFG_IPOIB_SUFFIX) +## or $env(CFG_INIC_SUFFIX) name) +## Returns: +## base of hostname, suitable for an $env(CFG_IPOIB_SUFFIX), +## or $env(CFG_INIC_SUFFIX) suffix to be added +## Additional Information: +## When called by FastFabric, CFG_IPOIB_SUFFIX is "", so this is a noop + global env + + set result $hostname + if { "$env(CFG_IPOIB_SUFFIX)" != "" } { + regsub -- "$env(CFG_IPOIB_SUFFIX)\$" $hostname "" result + } + if { "$env(CFG_INIC_SUFFIX)" != "" } { + regsub -- "$env(CFG_INIC_SUFFIX)\$" $hostname "" result + } + return "$result" +} + +proc get_hostname { number } { +## +## get_hostname +## ------------------- +## return hostname for number'th host in CFG_HOSTS +## +## Usage: +## get_hostname number +## Arguments: +## number - host number, 1 is 1st host +## Returns: +## hostname from CFG_HOSTS, might not be the host_basename + + global env + + return [ lindex $env(CFG_HOSTS) [ expr $number - 1] ] +} + +proc same_host { hostname1 hostname2 } { +## +## same_host +## ------------------- +## determine if hostnames are equivalent basenames +## +## Usage: +## same_host hostname1 hostname2 +## Arguments: +## hostname1 - host name used by test driver (could be an +## $env(CFG_IPOIB_SUFFIX) or $env(CFG_IPOIB_SUFFIX) name) +## hostname2 - host name used by test driver (could be an +## $env(CFG_IPOIB_SUFFIX) or $env(CFG_IPOIB_SUFFIX) name) +## Returns: +## 1 - names are same +## 0 - names are different + + return [ expr {"[ host_basename $hostname1 ]" == "[ host_basename $hostname2 ]"} ] +} + +proc get_hostnumber { name } { +## +## get_hostnumber +## ------------------- +## return host number for host in CFG_HOSTS +## +## Usage: +## get_hostnumber name +## Arguments: +## name - host name +## Returns: +## host number in CFG_HOSTS, 1 is 1st host +## 0 - if name not in CFG_HOSTS + + global env + + set number 1 + foreach host $env(CFG_HOSTS) { + if { [same_host $name $host ] } { + return $number + } + incr number + } + + return 0 +} + +proc have_other_hosts { hostname desthosts } { +## +## have_other_hosts +## ------------------- +## determine if desthosts includes any others other than hostname +## +## Usage: +## have_other_hosts hostname desthosts +## Arguments: +## hostname - host name used by test driver (could be an $env(CFG_IPOIB_SUFFIX) or $env(CFG_IPOIB_SUFFIX) name) +## desthosts - list of hosts to check +## Returns: +## 1 - there is at least 1 host other than hostname in desthosts +## 0 - desthosts has no hosts other than hostname + + foreach host $desthosts { + if { ! [ same_host $hostname $host ] } { + return 1 + } + } + return 0 +} + +proc get_local_stack_type { {checkrun "y"}} { +## +## get_local_stack_type +## -------------------- +## get IB stack type on this host +## +## Arguments: +## checkrun - if y, the running stack is checked first, otherwise +## just installed stack is checked. Note that during reinstall +## an old stack could be left running until the next reboot +## default is y. Beware, due to newer distros including openib, if it +## appears both are installed and 'n' is used, this reports IBACCESS. +## It is safest to invoke this with 'y'. +## + global spawn_id expect_out spawn_out timeout + global env + global log_disable + global expecting + + # disable detailed logging to stdout + log_user 0 + set log_disable 1 + + set hostname [ host_basename [exec hostname | cut -f1 -d.]] + local_sh + set target_stack [target_get_stack_type "$checkrun" "$hostname"] + local_sh_exit + return "$target_stack" +} + +proc add_module_parameter { module_name module_parameter value {conffile ""} } { +## +## add_module_parameter +## -------------------- +## edit modules.conf to add the specified parameter +## +## Arguments: +## module_name - (i.e ics_sdp) +## module_parameter - parameter (i.e. NoTcpFilter) +## value - literal value +## conffile - existing file within /etc/modprobe.d on RHEL6 and newer distros +## + # determine correct file name + if { ! [string equal "$conffile" "" ] && [ catch { unix_cmd 60 0 "[ -e /etc/modprobe.d/$conffile ]" } res ] == 0 } { + set mconf "/etc/modprobe.d/$conffile" + } else { + set mconf "/etc/modprobe.conf" + } + send_unix_cmd "cat > /tmp/add.txt < $mconf-new && mv -f $mconf-new $mconf && rm -f /tmp/add.txt" +} + +proc remove_module_parameter { module_name module_parameter {conffile ""}} { +## +## remove_module_parameter +## -------------------- +## edit modules.conf to remove the specified parameter +## Arguments: +## module_name - (i.e ics_sdp) +## module_parameter - parameter (i.e. NoTcpFilter) +## parameter - literal value +## conffile - existing file within /etc/modprobe.d on RHEL6 and newer distros +## + # determine correct file name + if { ! [string equal "$conffile" "" ] && [ catch { unix_cmd 60 0 "[ -e /etc/modprobe.d/$conffile ]" } res ] == 0 } { + set mconf "/etc/modprobe.d/$conffile" + } elseif { [ catch { unix_cmd 60 0 {[ -e /etc/modprobe.conf ]} } res ] == 0 } { + set mconf "/etc/modprobe.conf" + } else { + # parameter is not in a place we added it, do nothing + return + } + send_unix_cmd "cat > /tmp/remove.txt < $mconf-new && mv -f $mconf-new $mconf && rm -f /tmp/add.txt" +} + +proc scp_local_file { file_name host {directory "."} } { +## +## scp_local_file +## ------------------- +## scp a file from local_sh to remote host/directory +## Arguments: +## file_name - local file name to scp to remote host +## host - remote host to scp file to +## optional: directory - the remote directory to scp to (should end in '/.') + global spawn_id + + set save_spawn_id $spawn_id + local_sh + send_unix_cmd "scp $file_name root@$host:$directory" +# catch {expect_list 10 {"password:"} {"command not found"} out} +# send_unix_cmd "thepassword" + expect_unix_prompt 20 + local_sh_exit + set spawn_id $save_spawn_id +} diff --git a/TestTools/tools.exp b/TestTools/tools.exp new file mode 100644 index 0000000..850e789 --- /dev/null +++ b/TestTools/tools.exp @@ -0,0 +1,3736 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# [ICS VERSION STRING: unknown] + +## The tools.exp expect script file contains various utility routines which can +## be used in the generation of test scripts +## It is auto sourced into expect + +## Future enhancement - provide a spawn_id argument to the expect_ procedures? +## Current handling assumes a single spawned process or the manipulation of +## spawn_id prior to calling them. +## + +## User Controlled Global variables: +## --------------------------------- +## These variables are available to the user for read/write access +## They are used (read only) internally by the tools procedures. +## +## env(TEST_STOP_FAILED) +## none - do not stop on any failure +## suite - abort test suite only on the failure of a test suite +## case - abort test suite on the failure of any test case +## any - abort test suite on the failure of any test item +## default is none +## env(TEST_SAVE_FAILED) +## no - do not save any temporary files in the case of a failure +## yes - save all temporary files in the case of a failure +## default is yes +## env(TEST_SAVE_TEMP) +## no - do not save any temporary files between test cases +## yes - save all temporary files for each test case +## default is no +## env(TEST_SAVE_FIRST) +## when saving temp files for TEST_SAVE_FAILED or TEST_SAVE_TEMP should +## an existing save_tmp be retained in preference to the newer files +## yes - keep existing files, reflecting 1st run or failure of test +## no - replace existing files, reflecting last run or failure of test +## default yes +## env(TEST_PARALLEL) +## no - serialize all tests +## yes - when supported by a test_suite, parallelize test cases +## default is yes +## env(TEST_MAX_PARALLEL) +## maximum processes to concurrently execute in parallel blocks +## default is 20 +## env(TEST_TIMEOUT_MULT) +## multiplier for all timeouts during a test (used to account for slower hosts) +## default is 1 +## env(TEST_SHOW_CONFIG) +## show configuration at start of test suite +## default is yes +## env(TEST_SHOW_START) +## output a message at start of each test case +## default is no +## env(TEST_RESULT_DIR) +## directory to put test.log, test.res, identify.log, save_tmp, and test_tmp +## default is . +## env(CFG_*) +## assorted test target/driver configuration information from config file +## env(TEST_SUITES) +## env(TEST_SKIP_SUITES) +## A space separated list of test suite tags for test suites to run/not run. +## If not exported all the test suites are run +## For example: +## export TEST_SUITES="suite1 suite2" +## will cause only tests within suite1 and suite2 to be executed. All +## other test suites will be completely skipped including their +## initialization and cleanup code. +## The test cases run within the selected test suites can be further +## limited by using the TEST_CASES variable (see below). +## Shell style "glob" patterns can be used +## If a test suite matches both TEST_SUITES and TEST_SKIP_SUITES it is skipped +## env(TEST_CASES) +## env(TEST_SKIP_CASES) +## A space separated list of tags for the test cases to run/not run. The tags +## can be either the tag for a test case or a test_suite_tag.test_case_tag. +## If not exported all the test cases in the selected test suites are +## run. +## For example: +## export TEST_CASES="tag1 tag2" +## will cause test cases tag1 and tag2 to be executed within all the +## selected test suites. +## export TEST_CASES="suite1.tag1 suite2.tag2" +## Will cause test case tag1 within suite1 to be executed and tag2 +## within suite2 to be executed. Note that this will not prevent the +## execution of initialization and cleanup code from any other test suites +## hence it is usually desirable when multiple test suites are potentially +## being run, to limit the test suites by using the TEST_SUITES variable +## (see above). So in the case above: +## export TEST_SUITES="suite1 suite2" +## export TEST_CASES="suite1.tag1 suite2.tag2" +## will make sure that any test suites other than suite1 or suite2 +## are totally skipped. +## Shell style "glob" patterns can be used +## If a test case matches both TEST_CASES and TEST_SKIP_CASES it is skipped +## env(TEST_ITEMS) +## env(TEST_SKIP_ITEMS) +## A space separated list of tags for the test items to run/not run. The tags +## can be either the tag for a test item or a +## test_suite_tag.test_case_tag.test_item_tag. +## If not exported all the test items in the selected test +## cases in the selected test suites are run. +## For example: +## export TEST_ITEMS="tag1 tag2" +## will cause test items tag1 and tag2 to be executed within all the +## selected test cases. +## export TEST_ITEMS="suite1.tag1.item1 suite2.tag2.item2" +## Will cause test item item1 within test case tag1 within suite1 to be +## executed and item2 in test case tag2 within suite2 to be executed. +## Note that this will not prevent the execution of initialization and +## cleanup code from any other test suites hence it is usually desirable +## when multiple test suites are potentially being run, to limit the test +## cases and suites by using the TEST_SUITES and TEST_CASES variables +## (see above). So in the case above: +## export TEST_SUITES="suite1 suite2" +## export TEST_CASES="suite1.tag1 suite2.tag2" +## export TEST_ITEMS="suite1.tag1.item1 suite2.tag2.item2" +## will make sure that any test suites other than suite1 or suite2 +## and any cases other than suite1.tag1 and suite2.tag2 +## are totally skipped. +## Shell style "glob" patterns can be used +## If a test item matches both TEST_ITEMS and TEST_SKIP_ITEMS it is skipped +## env(TEST_NOEXECUTE) +## list of test operations/initializations to skip execution of +## the valid set of entries is defined by the test suite itself. +## This can be used to selectively disable test_execute operations +## within the test suite, typically within the initialization routines. +## env(TEST_IDENTIFY) +## disable test execution, simply identify the tests within the suite +## this is not completely implemented yet. +## env(TEST_DEBUG_LEVEL) +## Enable additional test debug output to the log +## +## Additional global variables (read only in this file, +## but internally set by test scripts): +## spawn_id - expect's spawn id, made global for ease of use +## spawn_out - expect's spawn output information, made global for ease of use +## interact_out - expect's interact output, made global for ease of use +## expect_out - expect's expect output, made global for ease of use +## timeout - expect's timeout value, made global for ease of use +## lines_to_show - number of lines to show from stdout of a child +## when it exits. Default is 10. +## expecting - current message or item being expected. This is output in +## the timeout handler for expect_after to aid debug of failed tests. +## defaults to "" at start of each test case/suite. +## features(au,feature) - feature status for each AU +## +## Files Generated: +## ---------------- +## Any test suite which uses these tools and the associated test automation +## makefiles (to run the tests) will automatically generate +## various files as follows: +## test.res - summary of tests run and brief results +## test.log - detailed summary of test +## save_tmp/test_suite_tag/test_case_tag/* +## - log and data files from running the given test suite and +## test case, the test_suite_tag component will be +## the actual test suite tag as specified in the +## test_suite procedure call, similar for test_case_tag +## The selection as to which cases generate such files +## depends on the env(TEST_SAVE_FAILED) and +## env(TEST_SAVE_TEMP) variables. The default is to +## only save results for failed test cases, but this can +## be altered by the user through these variables. +## The special test_case_tags of "suite_setup" and +## suite_cleanup are used to save log files from the +## suite_setup and suite_cleanup routines +## test_tmp$$ - temporary files, renamed as save_tmp/... or removed +## when test completes +## identify.res - summary of test suites automated within the directory +## This is generated when env(TEST_IDENTIFY)=yes +## as opposed to actually running the test suites +## File Formats: +## ------------- +## Some of these files can be machine parsed or easily greped for various +## patterns. In the messages below, fields bracketed in '' are replaced with +## variables from execution time. Hence ['DATE'] in a message may be +## emitted as [10:05:39 Jul 20, 1996] +## +## test.res +## -------- +## The test.res file contains the following types of messages: +## Executing 'NAME' Test Suite ('TAG') ['DATE'] ... +## - the given test suite is being started +## Executing 'NAME' Test Suite ('TAG') ['DATE'] ... +## SKIPPED +## - the given test suite is being skipped +## Test Configuration File: 'FILENAME' +## - the given configuration file will guide the test suite +## of course the environment may override config file values +## FAILURE during test suite: 'MULTI_LINE_DESCRIPTION' +## - the given error occured during the test suite and caused +## it to prematurely abort. No further messages will be provided +## for the suite other than a multi-line description of the error +## TEST SUITE FAILURE: 'MULTI_LINE_DESCRIPTION' +## TEST SUITE 'NAME' TESTS ABORTED +## - fatal test suite error +## TEST SUITE 'NAME': 'CNT' Cases; 'CNT' PASSED; 'CNT' FAILED; 'CNT' SKIPPED +## TEST SUITE 'NAME': 'CNT' Cases; 'CNT' PASSED; 'CNT' FAILED +## TEST SUITE 'NAME': 'CNT' Cases; 'CNT' PASSED; 'CNT' SKIPPED +## TEST SUITE 'NAME': 'CNT' Cases; 'CNT' PASSED +## - cummulative results for test suite +## - cummulative results for test suite +## TEST SUITE 'NAME' PASSED +## TEST SUITE 'NAME' FAILED +## - overall results of suite (only passes if all cases passed +## excluding those skipped) +## Done 'NAME' Test Suite ['DATE'] +## - test suite completed +## TEST SUITE 'NAME' CASE ('FULL_TAG') 'CASE_NAME': PASSED +## TEST SUITE 'NAME' CASE ('FULL_TAG') 'CASE_NAME': FAILED +## TEST SUITE 'NAME' CASE ('FULL_TAG') 'CASE_NAME': SKIPPED +## - test case results, Note in some cases the PASSED/FAILED +## may not appear on the same line as the TEST CASE name. +## This can be due to configuration errors causing setup errors +## or because the test case includes test items. For the +## passing case, an additional line will be logged. +## TEST CASE FAILURE='MULTI_LINE_ERROR' +## test case failed for given reason +## TEST CASE 'NAME': 'CNT' Items; 'CNT' STARTED; 'CNT' PASSED; 'CNT' FAILED +## TEST CASE 'NAME': 'CNT' Items; 'CNT' STARTED; 'CNT' PASSED +## TEST CASE 'NAME': 'CNT' Items; 'CNT' STARTED; 'CNT' FAILED +## TEST CASE 'NAME': 'CNT' Items; 'CNT' STARTED +## TEST CASE 'NAME': 'CNT' Items; 'CNT' STARTED; 'CNT' PASSED; 'CNT' FAILED; 'CNT' SKIPPED +## TEST CASE 'NAME': 'CNT' Items; 'CNT' STARTED; 'CNT' PASSED; 'CNT' SKIPPED +## TEST CASE 'NAME': 'CNT' Items; 'CNT' STARTED; 'CNT' FAILED; 'CNT' SKIPPED +## TEST CASE 'NAME': 'CNT' Items; 'CNT' STARTED; 'CNT' SKIPPED +## - cummulative results for test case which had test_items +## TEST SUITE 'NAME' ITEM ('FULL_TAG') 'ITEM_NAME': PASSED +## TEST SUITE 'NAME' ITEM ('FULL_TAG') 'ITEM_NAME' PASSED +## TEST SUITE 'NAME' ITEM ('FULL_TAG') 'ITEM_NAME': FAILED +## TEST SUITE 'NAME' ITEM ('FULL_TAG') 'ITEM_NAME' FAILED +## TEST SUITE 'NAME' ITEM ('FULL_TAG') 'ITEM_NAME': SKIPPED +## TEST SUITE 'NAME' ITEM ('FULL_TAG') 'ITEM_NAME': STARTED +## - test case item results, Note in some cases the PASSED/FAILED +## may not appear on the same line as the TEST CASE name. +## This can be due to configuration errors causing setup errors +## or because the test case includes test items. +## For the STARTED case, a subsequent PASSED or FAILED line will +## also be logged. +## PERF performance data +## Performance data reported by test which should be part of performance +## section of final report +## additional messages could appear in the log + +## +## identify.res +## ------------ +## +## *************************** +## Directory: 'DIRECTORY_NAME' +## - the given subdirectory exists which contains additional +## test suites (and an identify.res file) +## the details of those test suites follows this marker +## ============== +## - preceeds data for a new test suite +## Test Suite: 'NAME' ('TAG') +## 'MULTI_LINE_INFORMATION' +## - test suite name, tag and detailed (multi-line) description +## +## configuration variable settings from configuration file +## any messages from test suite setup routines, possibly +## failures +## -------------- +## - preceeds data for a new test case +## Test Case: 'NAME' ('FULL_TAG') +## 'MULTI_LINE_INFORMATION' +## - test suite and test case name, tag and detailed +## (multi-line) description. Description is for the test +## case only, description from test suite (above) may +## provide additional information +## +## +## Internal Global variables: +## -------------------------- +## These variables are used internally by the tools procedures. +## they may be read by the user, but not modified. +## +## tools_suite_name - name of current test suite (user should not change) +## tools_suite_tag - tag of current test suite (user should not change) +## tools_suite_result - PASSED/FAILED overall result for test suite +## tools_suite_status - status of most recent (current if still in progess) +## test_suite: "okay" if normal, "skip" if test cases should be +## skipped, "fail" if failed, and "abort" if the suite was programmatically aborted. +## tools_suite_count - on going count of the number of test suites run +## tools_case_name - name of current test case (user should not change) +## tools_case_tag - tag of current test case (user should not change) +## tools_case_count - on going count of the number of test cases run +## tools_case_passed - on going count of the number of test cases that passed +## tools_case_failed - on going count of the number of test cases that failed +## tools_case_skipped - on going count of the number of test cases skipped +## tools_case_async - flag if test case involves asynchronous test items +## tools_case_status - status of most recent (current if still in progess) +## test_case: "okay" if normal, "skip" if test items should be +## skipped, "fail" if failed, and "abort" if the case was programmatically aborted. +## tools_item_name - name of current test case (user should not change) +## tools_item_tag - tag of current test case (user should not change) +## tools_item_count - on going count of the number of test items run +## tools_item_passed - on going count of the number of test items that passed +## tools_item_started - on going count of the number of test items that started +## tools_item_failed - on going count of the number of test items that failed +## tools_item_skipped - on going count of the number of test items skipped +## tools_item_*_list - lists of test item information for async test cases +## test_tmp - directory for temporary files, renamed as save_tmp/... or removed +## when test completes +## +## Tcl Library Paths +## ----------------- +## When test_expect is run, the Tcl library search path automatically +## is appended to to include $BUILD_DIR/tcl_libs, $RELEASE_DIR/tcl_libs +## and the current working directory. As needed you can create libraries +## of routines for use by you various test suites and build the +## corresponding tclIndex to allow those libraries to be run without +## needing to explicity source the files. + +# defaults +set default_TEST_STOP_FAILED none +set default_TEST_SAVE_FAILED yes +set default_TEST_SAVE_TEMP no +set default_TEST_SAVE_FIRST yes +set default_TEST_PARALLEL yes +set default_TEST_MAX_PARALLEL 20 +set default_TEST_TIMEOUT_MULT 1 +set default_TEST_IDENTIFY no +set default_TEST_SHOW_CONFIG yes +set default_TEST_SHOW_START no +set default_TEST_RESULT_DIR "." +set default_TEST_SERIALIZE_OUTPUT no + +set tools_suite_count 0 +set tools_suite_failed 0 +set log_disable 0 + +# if we redirect stdout as part of serializing parallel output, we save +# the original stdout here so we can still output some interactive messages +set orig_stdout "" + +proc test_suite { tag name information startup cleanup code } { +## +## test_suite +## ----------- +## utility procedure to execute a test suite +## +## Usage: +## test_suite tag name information startup cleanup { +## code for test suite (typically calls to test_case) +## } +## Arguments: +## tag - short tag for test suite, no spaces or special characters allowed +## used to name directory to save results +## name - name of test suite +## information - brief description of test suite +## startup - procedure to execute at start of the test suite +## cleanup - procedure to execute at the end of the test suite +## code = Tcl commands for test suite (typically a list with 1 or +## more invocations of test_case) +## Returns: +## none +## Additional Information: +## Any test_case calls must be made within the code of this +## control structure +## + + global tools_suite_name + global tools_suite_tag + global tools_suite_result + global tools_suite_status + global tools_suite_count + global tools_case_count + global tools_case_passed + global tools_case_failed + global tools_case_skipped + global env + global spawn_id + global spawn_out + global interact_out + global expect_out + global timeout + global expecting + global features + + set tools_suite_name $name + set tools_suite_tag $tag + + if { ! [ identify_mode ] } { + # create test_tmp for use by startup code + make_test_tmp + log_redirect + log_message "Start $name Test Suite ($tag) [date_stamp]" + log_message "==============================================================================" + puts "Executing $name Test Suite ($tag) [date_stamp] ..." + + log_message "$information\n" + log_message "[date_stamp]" + log_message "" + } + + set tools_suite_result "PASSED" + set tools_suite_status "okay" + + clear_case_counters + + incr tools_suite_count + + set spawn_id ""; # create variable + set expecting ""; # create variable + set_timeout 60; # create and initialize variable + + # test for test_suite_tag in TEST_SUITES/TEST_SKIP_SUITES + if { [ check_skip_test TEST_SUITES TEST_SKIP_SUITES "{$tag}" ] } { + show_message "SKIPPED" + log_message "" + remove_test_tmp + return + } + + if { [ info exists env(TEST_CONFIG_FILE) ] != 1 } { + remove_test_tmp + fail_suite "FAILURE during test suite: Environment variable TEST_CONFIG_FILE not set" 1 + } + if { [ catch { read_config $env(TEST_CONFIG_FILE) } res ] != 0 } { + remove_test_tmp + fail_suite "FAILURE during test suite: failed to read $env(TEST_CONFIG_FILE) $res" 1 + } + + # test for test_suite_tag in TEST_SUITES/TEST_SKIP_SUITES + if { [ check_skip_test TEST_SUITES TEST_SKIP_SUITES "{$tag}" ] } { + show_message "TEST SUITE $tools_suite_name ($tag) TESTS SKIPPED" + log_message "" + remove_test_tmp + return + } + + # only identify suites which are not skipped + if { [ identify_mode ] } { + log_file -a [test_get_env TEST_RESULT_DIR]/identify.log + puts "==============================================================================" + puts "Test Suite: $name ($tag)" + puts "$information\n" + } + + test_execute {} { + setup_expect_after + } + set res [ catch { + set expecting "" + set_timeout 60 + if { [ catch { eval $startup } err_str2 ] != 0 } { + cleanup_all_children + test_execute {} { + log_restore + save_test_tmp $tools_suite_tag suite_setup TEST_SAVE_FAILED + } + error "suite_setup failed: $err_str2" + } elseif { "$err_str2" == -1} { + # skip test_suite and do not run cleanup proc + show_message "TEST SUITE $tools_suite_name ($tag) TESTS SKIPPED" + set tools_suite_status "skipped" + log_message "" + set cleanup "noop" + set tools_suite_result "SKIPPED" + test_execute {} { + log_restore + save_test_tmp $tools_suite_tag suite_setup TEST_SAVE_TEMP + } + remove_test_tmp + } else { + test_execute {} { + log_restore + save_test_tmp $tools_suite_tag suite_setup TEST_SAVE_TEMP + } + + set expecting "" + set_timeout 60 + # code is run even in identify mode so that test cases + # can identify themselves + eval $code + } + } err_str ] + if { $res != 0 } { + if { $tools_suite_status == "okay" } { + fail_suite "FAILURE during test suite: $err_str" 0 + } + } + + set expecting "" + set_timeout 60 + if { "$cleanup" != "" && "$cleanup" != "noop" } { + test_execute {} { + make_test_tmp + log_redirect + } + if { [ catch { eval $cleanup [expr { "$tools_suite_result" == "FAILED" }] } err_str2 ] != 0 } { + cleanup_all_children + test_execute {} { + log_restore + save_test_tmp $tools_suite_tag suite_cleanup TEST_SAVE_FAILED + } + if { $tools_suite_status == "okay" } { + fail_suite "FAILURE during test suite $cleanup function: $err_str2" 0 + } + } else { + test_execute {} { + log_restore + save_test_tmp $tools_suite_tag suite_cleanup TEST_SAVE_TEMP + } + } + } + cleanup_all_children + set message "TEST SUITE $tools_suite_name: $tools_case_count Cases; $tools_case_passed PASSED" + if { $tools_case_failed != 0 } { + append message "; $tools_case_failed FAILED" + } + if { $tools_case_skipped != 0 } { + append message "; $tools_case_skipped SKIPPED" + } + show_message "$message" + show_message "TEST SUITE $tools_suite_name $tools_suite_result" + show_message "Done $tools_suite_name Test Suite [date_stamp]\n" + if { [ identify_mode ] } { + puts " " + } + remove_test_tmp + clear_case_counters + + return +} + +proc log_redirect {} { + global test_tmp + + # redirect the log for a test case + log_file + log_file -a $test_tmp/test.log +} + +proc log_restore {} { + # restore the logging and append the test case's log to the + # main log + global test_tmp + set test_log "[test_get_env TEST_RESULT_DIR]/test.log" + + log_file + # RHEL5, SLES10 and newer distros have flock which can correct a race here + # on older distros we could use tclX's flock command, but not worth the + # trouble to fix for RHEL4 at this time + if { [catch { exec which flock > /dev/null 2>/dev/null } ] == 0 } { + exec flock $test_log tee -a $test_log < $test_tmp/test.log > /dev/null + } else { + exec cat $test_tmp/test.log >> $test_log + } + log_file -a $test_log +} + +set punchlist_fd "" +set start_time "" + +proc open_punchlist { fname } { + global start_time punchlist_fd + + if { "$start_time" == "" } { + set start_time [ timestamp -format "%Y/%m/%d %H:%M:%S" ] + } + if { "$punchlist_fd" == "" } { + set punchlist_fd [open "$fname" {WRONLY APPEND CREAT} ] + fconfigure $punchlist_fd -buffering line + } +} + +proc close_punchlist {} { + global start_time punchlist_fd + + if { "$punchlist_fd" != "" } { + close $punchlist_fd + set punchlist_fd "" + } +} + +# open, append and close punchlist +# any errors are logged but will not cause exceptions +proc append_punchlist { device issue } { + global start_time punchlist_fd + + set fname "[test_get_env TEST_RESULT_DIR]/punchlist.csv" + if { [ catch { open_punchlist "$fname" } err_str ] != 0 } { + log_message "\nERROR: Unable to open punchlist: $fname: $err_str" + } else { + if { [ catch { puts $punchlist_fd "$start_time;$device;$issue" } err_str ] != 0 } { + log_message "\nERROR: Unable to write punchlist: $fname: $err_str" + } + } + catch { close_punchlist } +} + +proc setup_expect_after {} { + global spawn_id + + # set up so all subsequent expects fail on unexpected conditions + # Note that since expect_after is used, eof or timeout within + # specific + # test invocations (such as expect_eof) will be evaluated before + # those here + # spawn_id is global and indirect so that as a process is + # spawned, the expect_after will apply to it automatically + expect_after { + -i spawn_id eof { + global expecting + if { "$expecting" != "" } { + log_message "\nERROR: EOF waiting for: $expecting" + } + ignore_rest + fail_test "eof" + } + -i spawn_id timeout { + global spawn_id expecting + + if { "$expecting" != "" } { + log_message "\nERROR: timeout ($timeout) waiting for: $expecting" + } + # get buffered data + expect * + if { "$expect_out(buffer)" != "" } { + log_message "\nERROR: Received data: $expect_out(buffer)" + fail_test "timeout: with data" + } else { + fail_test "timeout: No data" + } + } + } +} + +proc disable_expect_after {} { + expect_after +} + +proc test_case { tag name information startup cleanup code { failure_code "" }} { +## +## test_case +## --------- +## This executes the given test case +## +## Usage: +## test_case tag "test name" "test description" startup cleanup { +## code for test +## } +## Arguments: +## tag - short tag for test case, no spaces or special characters allowed +## used to name directory to save results +## name = test case name +## information = brief description of test +## code = Tcl commands for test case (typically a list) +## startup - procedure to execute at start of the test case +## cleanup - procedure to execute at the end of the test case +## Returns: +## 0 - test success or explicitly skipped or identify mode +## 1 - test failure or skipped due to earlier fail_suite +## Additional Information: +## In general the code should avoid doing output such that the +## output will simply include test cases and PASS/FAIL status +## Any error returns within $code will indicate a test failure. +## In general, fail_test should be invoked to indicate such failures. +## Any detailed logging of test progress should be done using log_message +## +## This routine always removes/mkdir's test_tmp at the start of each +## test case and removes it at the end of each test case. +## +## The failure_code is run before saving test_tmp (if TEST_SAVE_FAILED exported) +## and prior to running any cleanup code (defined for test_suite) +## Its typical use to to extract additional information into test_tmp +## to aid the debug of why the test case failed +## The log during the test case is kept in test_tmp/test.log (and +## saved based on TEST_SAVE_FAILED) and at the end of the test case it is +## appended to the main test.log + + global tools_suite_name + global tools_suite_tag + global tools_suite_result + global tools_suite_count + global tools_suite_status + global tools_case_name + global tools_case_tag + global tools_case_count + global tools_case_passed + global tools_case_failed + global tools_case_skipped + global tools_case_status + global tools_item_name + global tools_item_tag + global tools_item_count + global tools_item_passed + global tools_item_started + global tools_item_failed + global tools_item_skipped + global tools_item_status + global tools_case_async + global tools_item_tag_list + global tools_item_full_tag_list + global tools_item_name_list + global tools_item_status_list + global orig_stdout + + global env + # force spawn_id returned by any spawn's within $code to be global + global spawn_id + global spawn_out + global interact_out + global expect_out + global timeout + global expecting + global features + + set tools_case_status "okay" + incr tools_case_count + + clear_item_counters + set tools_case_async 0 + set tools_item_tag_list {} + set tools_item_full_tag_list {} + set tools_item_name_list {} + set tools_item_status_list {} + + set full_tag "$tools_suite_tag\.$tag" + set tools_case_name "$name" + set tools_case_tag "$full_tag" + + if { ! [ identify_mode ] } { + make_test_tmp + + log_redirect + if { [ show_start ] } { + if { $orig_stdout != "" } { + puts $orig_stdout "Executing TEST SUITE $tools_suite_name CASE ($full_tag) $name ... " + } else { + puts "Executing TEST SUITE $tools_suite_name CASE ($full_tag) $name ... " + } + } + puts -nonewline "TEST SUITE $tools_suite_name CASE ($full_tag) $name " + log_message "TEST SUITE $tools_suite_name CASE ($full_tag) $name:" + log_message "$information\n" + log_message "[date_stamp]" + log_message "" + } + + # test for tag or test_suite_tag.test_case_tag in TEST_CASES/TEST_SKIP_CASES + if { $tools_suite_status == "skip" + || [ check_skip_test TEST_CASES TEST_SKIP_CASES "{$tag} {$full_tag}" ] } { + test_execute {} { + show_message "SKIPPED" + log_message "" + log_restore + } + set tools_case_status "skip" + incr tools_case_skipped + remove_test_tmp + if { $tools_suite_status == "skip" } { + return 1 + } else { + return 0 + } + } + + # only identify cases which are not skipped + if { [ identify_mode ] } { + puts "------------------------------------------------------------------------------" + # puts "Test Suite: $tools_suite_name ($tools_suite_tag)" + puts "Test Case: $name ($full_tag)" + puts "$information\n" + } + + set res [ catch { + set expecting "" + set_timeout 60 + if { [ catch { eval $startup } err_str2 ] != 0 } { + error "case_setup failed: $err_str2" + } elseif { "$err_str2" == -1} { + # skip test_case and do not run cleanup proc + set tools_case_status "skip" + set res 1 + } else { + set expecting "" + set_timeout 60 + # the handling of TEST_IDENTIFY for test_items within + # a test_case is TBD, at this time, they are ignored. + test_execute {} { eval $code } + } + } err_str ] + + set did_cleanup 0 + if { $res != 0 && $tools_case_status == "skip" } { + # clear result, we will run cleanup for skipped + set res 0 + } + if { $res == 0 } { + set expecting "" + set_timeout 60 + if { "$cleanup" != "" && "$cleanup" != "noop" + && [ catch { eval $cleanup 0 } err_str2 ] != 0 } { + set err_str "$cleanup function FAILED: $err_str2" + set res 1 + } + set did_cleanup 1 + } + if { $res == 0 && $tools_item_failed != 0 } { + set err_str "$tools_item_failed test items FAILED" + set res 1 + } + if { $res != 0 && ! [ identify_mode ] } { + # output message immediately after failure to make reading + # log easier, also output immediately before FAILED message + log_message "\nTEST CASE FAILURE=$err_str" + if { ! $did_cleanup && "$failure_code" != "" } { + set expecting "" + set_timeout 60 + if { [ catch { eval $failure_code } err_str2 ] != 0 } { + log_message "failure handling code FAILED: $err_str2" + } + } + set expecting "" + set_timeout 60 + if { ! $did_cleanup && "$cleanup" != "" && "$cleanup" != "noop" + && [ catch { eval $cleanup 1 } err_str2 ] != 0 } { + log_message "$cleanup function FAILED: $err_str2" + } + cleanup_all_children + log_message "\nFAILURE=$err_str" + test_item_totals + clear_item_counters + puts "FAILED" + log_message "\n[date_stamp]\n" + log_message "\nTEST SUITE $tools_suite_name CASE ($full_tag) $name: FAILED\n" + set tools_suite_result "FAILED" + incr tools_case_failed + set tools_case_status "fail" + log_restore + save_test_tmp $tools_suite_tag $tag TEST_SAVE_FAILED + set stop_failed [test_get_env TEST_STOP_FAILED] + if { "$stop_failed" == "case" || "$stop_failed" == "any" } { + fail_suite "test failed with TEST_STOP_FAILED set" $stop_failed + } else { + return 1 + } + } else { + cleanup_all_children + test_execute {} { + test_item_totals + if { $tools_case_status == "skip" } { + incr tools_case_skipped + set status "SKIPPED: $err_str" + } elseif {$tools_item_count && $tools_item_skipped == $tools_item_count } { + # all items were skipped, report case as skipped + incr tools_case_skipped + set status "SKIPPED" + } else { + incr tools_case_passed + set status "PASSED" + } + puts "$status" + log_message "\n[date_stamp]\n" + log_message "\nTEST SUITE $tools_suite_name CASE ($full_tag) $name: $status\n" + log_restore + save_test_tmp $tools_suite_tag $tag TEST_SAVE_TEMP + } + clear_item_counters + return 0 + } +} + +proc test_item_totals { } { +# if there were test_items in this test_case, report the test item +# statuses and the totals +# and re-output the test_case details for the PASSED/FAILED message to come + global tools_item_count + global tools_item_passed + global tools_item_started + global tools_item_failed + global tools_item_skipped + global tools_case_async + global tools_case_name + global tools_case_tag + global tools_suite_name + global tools_item_status_list + + if { $tools_item_count > 0 } { + foreach message $tools_item_status_list { + show_message $message + } + if { $tools_case_async } { + set message "TEST CASE $tools_case_name: $tools_item_count Items; $tools_item_started STARTED" + if { $tools_item_passed != 0 } { + append message "; $tools_item_passed PASSED" + } + if { $tools_item_failed != 0 } { + append message "; $tools_item_failed FAILED" + } + } else { + set message "TEST CASE $tools_case_name: $tools_item_count Items; $tools_item_passed PASSED" + if { $tools_item_failed != 0 } { + append message "; $tools_item_failed FAILED" + } + } + if { $tools_item_skipped != 0 } { + append message "; $tools_item_skipped SKIPPED" + } + show_message "$message" + puts -nonewline "TEST SUITE $tools_suite_name CASE ($tools_case_tag) $tools_case_name " + } +} + +# initialize when first load this module +set test_tmp "test_tmp[pid]" + +proc make_test_tmp { } { +# create the test_tmp directory + + global test_tmp + + # set here in case sub-process in a parallel execution set of tests + set test_tmp "[test_get_env TEST_RESULT_DIR]/test_tmp[pid]" + catch { exec rm -rf $test_tmp } + exec mkdir $test_tmp +} + +proc test_get_env { envvar } { +## +## test_get_env +## -------------- +## get given env var value, if not exported, returns value of default_$envvar +## +## Arguments: +## envvar - variable name to get value for +## Returns: +## value to use for variable + + global env + global default_$envvar + + if { [ info exists env($envvar)] } { + return $env($envvar) + } else { + return [ set default_$envvar ] + } +} + +proc test_check_yn { value } { +## +## test_check_yn +## -------------- +## determine if value is yes (or y) or no +## +## Arguments: +## value - value to check +## Returns: +## 1 - yes +## 0 - no (or invalid value) + + return [ string match {[yY]*} $value ] +} + + +proc test_save_temp { } { +## +## test_save_temp +## -------------- +## return if TEST_SAVE_TEMP behaviour should be performed +## +## Returns: +## 1 - yes +## 0 - no + + return [ test_check_yn [ test_get_env TEST_SAVE_TEMP] ] +} + +proc save_test_tmp { suite_tag case_tag envvar } { +# save the test_tmp directory to save_tmp/$suite_tag/$case_tag +# if $env(envvar) is yes + + global env + global test_tmp + + set save_tmp [test_get_env TEST_RESULT_DIR]/save_tmp + + if { [ test_check_yn [ test_get_env TEST_SAVE_FIRST ] ] + && [ file exists $save_tmp/$suite_tag/$case_tag ] } { + log_message "$test_tmp not saved due to existing $save_tmp/$suite_tag/$case_tag with TEST_SAVE_FIRST enabled" + catch { exec rm -rf $test_tmp } + return + } + catch { exec rm -fr $save_tmp/$suite_tag/$case_tag } + if { [ test_check_yn [ test_get_env $envvar ] ] } { + log_message "$test_tmp saved to $save_tmp/$suite_tag/$case_tag" + if { [ file exists $save_tmp ] != 1 } { + exec mkdir -p $save_tmp + } + if { [ file exists $save_tmp/$suite_tag ] != 1 } { + exec mkdir -p $save_tmp/$suite_tag + } + exec mv $test_tmp $save_tmp/$suite_tag/$case_tag + } else { + catch { exec rm -rf $test_tmp } + # rmdir can fail if directory not empty, thats ok + catch { exec rmdir $save_tmp/$suite_tag } + } +} + +proc remove_test_tmp { } { +# remove the test_tmp directory + + global test_tmp + + catch { exec rm -rf $test_tmp } +} + +proc check_skip_test { envvar skipenvvar match_list } { +# +# check_skip_test +# ------------------- +# determine if the current test should be skipped +# +# Usage: +# check_skip_test +# +# Arguments: +# envvar - environment variable to base tests on (TEST_SUITES, TEST_CASES +# or TEST_ITEMS) +# skipenvvar - environment variable to base skipping tests on +# (TEST_SKIP_SUITES, TEST_SKIP_CASES or TEST_SKIP_ITEMS) +# match_list - list of tags to attempt to match against each entry in +# the environment variable +# Returns: +# 1 - this test should be skipped +# 0 - this test should be executed +# Additional Information: +# If a tag in match_list matches both envvar and skipenvvar, 1 is returned + + global env + + set result 0 + + if { [ info exists env($envvar) ] } { + # limit to those we find in envvar + set result 1 + foreach item $env($envvar) { + foreach tag $match_list { + if { [ string match $item $tag ] } { + set result 0 + } + } + } + } + if { $result == 1 } { + # already decided to skip, no need to test skipenvvar + return $result + } + if { [ info exists env($skipenvvar) ] } { + # skip those we find in skipenvvar + foreach item $env($skipenvvar) { + foreach tag $match_list { + if { [ string match $item $tag ] } { + set result 1 + } + } + } + } + return $result +} + +proc test_parallel { } { +## +## test_parallel +## -------------- +## determine if parallel tests should be run based on TEST_PARALLEL and +## TEST_IDENTIFY +## +## Returns: +## 1 - yes +## 0 - no + +# +# If this version of TCL has thread support enabled, disable +# parallel operations, because thread support causes hangs +# in TCL fork processing. +# + + global tcl_platform + #if { [ catch { set thread_tcl $tcl_platform(threaded) } result] } { + set thread_tcl 0 + #} + + return [ expr ! [identify_mode] \ + && [ test_check_yn [ test_get_env TEST_PARALLEL] ] \ + && [ test_get_env TEST_MAX_PARALLEL ] > 1 \ + && {$thread_tcl == 0 } ] +} + +proc test_item { tag name information startup cleanup code { failure_code "" }} { +## +## test_item +## --------- +## This executes the given test item +## +## Usage: +## test_item tag "test name" "test description" startup cleanup { +## code for test +## } +## Arguments: +## tag - short tag for test case, no spaces or special characters allowed +## used to name directory to save results +## name = test case name +## information = brief description of test +## code = Tcl commands for test item (typically a list) +## startup - procedure to execute at start of the test item +## cleanup - procedure to execute at the end of the test item +## Returns: +## 0 - test success or explicitly skipped +## 1 - test failure or skipped due to earlier fail_suite +## Additional Information: +## In general the code should avoid doing output such that the +## output will simply include test items and PASS/FAIL status +## Any error returns within $code will indicate a test failure. +## In general, fail_test should be invoked to indicate such failures. +## Any detailed logging of test progress should be done using log_message +## +## Its typical use is to extract additional information into test_tmp +## to aid the debug of why the test item failed +## The log during the test item is kept in test_tmp/test.log (and +## saved based on TEST_SAVE_FAILED) and at the end of the test item it is +## appended to the main test.log + + global tools_suite_name + global tools_suite_tag + global tools_suite_result + global tools_suite_count + global tools_suite_status + global tools_case_name + global tools_case_tag + global tools_name_name + global tools_name_tag + global tools_item_count + global tools_item_passed + global tools_item_started + global tools_item_failed + global tools_item_skipped + global tools_item_status + global tools_case_async + global tools_case_status + global tools_item_tag_list + global tools_item_full_tag_list + global tools_item_name_list + + global env + # force spawn_id returned by any spawn's within $code to be global + global spawn_id + global spawn_out + global interact_out + global expect_out + global timeout + global expecting + global features + + if { $tools_item_count == 0 } { + # newline after TEST CASE name line + puts "..." + } + + incr tools_item_count + + set tools_item_result "PASSED" + set tools_item_status "okay" + + set full_tag "$tools_case_tag\.$tag" + set tools_item_name "$name" + set tools_item_tag "$full_tag" + + puts -nonewline "TEST SUITE $tools_suite_name ITEM ($full_tag) $name " + log_message "TEST SUITE $tools_suite_name ITEM ($full_tag) $name:" + log_message "$information\n" + log_message "[date_stamp]" + log_message "" + + # test for tag or test_suite_tag.test_case_tag.test_item_tag + # in TEST_ITEMS + if { $tools_suite_status == "skip" + || [ check_skip_test TEST_ITEMS TEST_SKIP_ITEMS "{$tag} {$full_tag}" ] } { + show_message "SKIPPED" + log_message "" + incr tools_item_skipped + set tools_item_status "skip" + if { $tools_suite_status == "skip" } { + return 1 + } else { + return 0 + } + } + + set res [ catch { + set expecting "" + set_timeout 60 + if { [ catch { uplevel $startup } err_str2 ] != 0 } { + error "item_setup failed: $err_str2" + } elseif { "$err_str2" == -1} { + # skip test_item and do not run cleanup proc + set tools_item_status "skip" + set res 1 + } else { + set expecting "" + set_timeout 60 + uplevel $code + } + } err_str ] + if { $res != 0 && ( $tools_item_status == "skip" || $tools_case_status == "skip" ) } { + # clear result, we will run cleanup for skipped + set res 0 + } + set did_cleanup 0 + if { $res == 0 } { + set expecting "" + set_timeout 60 + if { "$cleanup" != "" && "$cleanup" != "noop" + && [ catch { eval $cleanup 0 } err_str2 ] != 0 } { + set err_str "$cleanup function FAILED: $err_str2" + set res 1 + } + set did_cleanup 1 + } + if { $res != 0 } { + # output message immediately after failure to make reading + # log easier, also output immediately before FAILED message + log_message "\nFAILURE=$err_str" + if { ! $did_cleanup && "$failure_code" != "" } { + set expecting "" + set_timeout 60 + if { [ catch { uplevel $failure_code } err_str2 ] != 0 } { + log_message "failure handling code FAILED: $err_str2" + } + } + set expecting "" + set_timeout 60 + if { ! $did_cleanup && "$cleanup" != "" && "$cleanup" != "noop" + && [ catch { uplevel $cleanup 1 } err_str2 ] != 0 } { + log_message "$cleanup function FAILED: $err_str2" + } + log_message "\nFAILURE=$err_str" + puts "FAILED" + log_message "\n[date_stamp]\n" + log_message "\nTEST SUITE $tools_suite_name ITEM ($full_tag) $name: FAILED\n" + set tools_suite_result "FAILED" + incr tools_item_failed + set tools_item_status "fail" + set stop_failed [test_get_env TEST_STOP_FAILED] + if { "$stop_failed" == "any" } { + fail_suite "test failed with TEST_STOP_FAILED set" $stop_failed + } else { + return 1 + } + } else { + if { $tools_case_async } { + set status "STARTED" + incr tools_item_started + lappend tools_item_tag_list "$tag" + lappend tools_item_name_list "$name" + lappend tools_item_full_tag_list "$full_tag" + } else { + if { $tools_item_status == "skip" || $tools_case_status == "skip" } { + set status "SKIPPED: $err_str" + incr tools_item_skipped + } else { + set status "PASSED" + incr tools_item_passed + } + } + puts "$status" + log_message "\n[date_stamp]\n" + log_message "\nTEST SUITE $tools_suite_name ITEM ($full_tag) $name: $status\n" + if { $tools_case_status == "skip" } { + # pass exception up so rest of test case is skipped + error "$err_str" "$err_str" + } + return 0 + } +} + +proc async_case {} { +## +## async_case +## ---------- +## Indicate that the test_items in the current test case run asynchronously +## +## Usage: +## async_case +## Additional Information: +## This causes the test_item to report FAILED (and but counts) or +## Started. If it expected that later code in the test_case +## (typically the cleanup routine) will invoke the test_item_status +## routine to indicate the pass/fail status for each test item +## for inclusion in the test.res report. + global tools_case_async + + set tools_case_async 1 + log_message "Asynchronously run test items for this test case" +} + +# initialize value when source is first autosourced in +global tools_case_async +set tools_case_async 0 + +proc get_async_case {} { +## +## get_async_case +## ---------- +## return current value for async_case as set via async_case call +## +## Usage: +## get_async_case + + global tools_case_async + + return $tools_case_async +} + +proc test_item_status { item_info } { +## +## test_item_status +## ---------------- +## Report the status for a test item in an asynchronously executed test case +## +## Usage: +## test_item_status item_info +## Arguments: +## info_info: +## test_item_tag status +## test_item_tag - tag provided to test_item call +## status - status of test item (PASSED/FAILED/SKIPPED) +## Additional Information: +## test_item_tags not found in the tools_item_tag_list are assumed to +## have already been reported on. This is maintains the +## list of test_items which have been successfully started +## but not yet reported status for +## + + global tools_item_passed tools_item_failed tools_item_skipped + global tools_item_tag_list + global tools_item_full_tag_list + global tools_item_name_list tools_suite_name + global tools_item_status_list + + set test_item_tag [ lindex $item_info 0 ] + set status [ lindex $item_info 1 ] + + set index [ lsearch -exact $tools_item_tag_list $test_item_tag ] + if { $index == -1 } { + return + } + set name [ lindex $tools_item_name_list $index ] + set full_tag [ lindex $tools_item_full_tag_list $index ] + set tools_item_tag_list [ lreplace $tools_item_tag_list $index $index ] + set tools_item_name_list [ lreplace $tools_item_name_list $index $index ] + set tools_item_full_tag_list [ lreplace $tools_item_full_tag_list $index $index ] + if { "$status" == "PASSED" } { + incr tools_item_passed + } elseif { "$status" == "SKIPPED" } { + incr tools_item_skipped + } else { + incr tools_item_failed + } + lappend tools_item_status_list "TEST SUITE $tools_suite_name ITEM ($full_tag) $name $status" +} + +proc fail_test { info } { +## +## fail_test +## --------- +## abort the current test and indicate a failure to test_case +## +## Usage: +## fail_test info +## Arguments: +## info - a brief comment as to why the test failed, typically what +## was received by expect that wasn't expected ( ie. "eof") +## Returns: +## error exception +## Additional Information: +## This procedure should be called anytime a test case detects a failure +## The error return will cause the stack to unwrap all the way up to +## test_case (which should be the only error trap in the stack) +## Note that an alternative to using this routine is to simply have an +## error return (return -code error or a failed tcl command) within the +## test case code block. +## However this has the advantage of logging "$info" to the test.log + + log_message "\nERROR: $info" + error "$info" "$info" +} + +proc fail_suite { info { abort_now 1 } } { +## +## fail_suite +## --------- +## abort the current test suite and indicate a failure +## +## Usage: +## fail_suite info [abort_now] +## Arguments: +## info - a brief comment as to why the test suite failed +## abort_now - 0/1 should the suite abort immediately or +## simply ignore all test_cases calls until end_suite +## default is 1 +## Returns: +## abort_now = 0 -> nothing +## abort_now = 1 -> error exception +## Additional Information: +## Typically used when global environment requirements are not met +## or when subsequent test cases depend on the success of a prior test case +## +## This routine can only be called within a test_suite code block. +## +## If abort_now is 1, the code block aborts immediately. +## +## However if it is 0, the test_suite code block will continue to be +## executed, however all test_case invocations within the code block will +## be ignored. +## +## In general abort_now should be 1. +## +## Only if there is special cleanup code between tests (which really +## should be done by the cleanup code supplied to test_suite) should +## abort_now be 0. + + global tools_suite_name + global tools_suite_result + global tools_suite_status + global tools_suite_failed + + show_message "\nTEST SUITE FAILURE: $info" + show_message "TEST SUITE $tools_suite_name TESTS ABORTED" + log_message "" + set tools_suite_result "FAILED" + incr tools_suite_failed + if { $abort_now == 1 } { + set tools_suite_status "abort" + error "$info" "$info" + } else { + set tools_suite_status "skip" + return + } +} + +proc skip_case { info } { +## +## skip_case +## --------- +## stop the current test case and indicate it was skipped +## +## Usage: +## skip_case info +## Arguments: +## info - a brief comment as to why the test case was skipped +## Returns: +## does not return, throws and exception +## Additional Information: +## Typically used when global environment requirements are not met +## or when subsequent test cases depend on the success of a prior test case +## +## This routine can only be called within a test_case code block. +## If called within a test_item, the rest of the test case will be skipped +## Of course if the item is within a parallel block, the skip will only +## affect other items within the same subprocess. For example: +## test_case { +## parallel x { a b c } { +## test_item 1$x +## test_item 2$x +## } +## } +## A skip_case within item 1a will only affect item 2a, it will not affect +## 1b, 1c, 2b, 2c. However the final results for the case will be tabulated +## as 2 skipped, 4 passed (or failed) +## + + global tools_case_status + + # test_case (or test_item) will catch exception and report to log and stdout + log_message "" + set tools_case_status "skip" + error "$info" "$info" +} + +proc skip_item { info } { +## +## skip_item +## --------- +## stop the current test item and indicate it was skipped +## +## Usage: +## skip_item info +## Arguments: +## info - a brief comment as to why the test item was skipped +## Returns: +## does not return, throws and exception +## Additional Information: +## Typically used when global environment requirements are not met +## or when subsequent test items depend on the success of a prior test item +## +## This routine can only be called within a test_item code block. +## + + global tools_item_status + + # test_item will catch exception and report to log and stdout + log_message "" + set tools_item_status "skip" + error "$info" "$info" +} + +proc clear_case_counters {} { +# clear counters for cases and items completed within a test suite + global tools_case_count 0 + global tools_case_passed 0 + global tools_case_failed 0 + global tools_case_skipped 0 + + set tools_case_count 0 + set tools_case_passed 0 + set tools_case_failed 0 + set tools_case_skipped 0 + clear_item_counters +} + +proc clear_item_counters {} { +# clear counters for items completed within a test case + global tools_item_count 0 + global tools_item_started 0 + global tools_item_passed 0 + global tools_item_failed 0 + global tools_item_skipped 0 + + set tools_item_count 0 + set tools_item_started 0 + set tools_item_passed 0 + set tools_item_failed 0 + set tools_item_skipped 0 +} + +# set of counters which are saved and passed across process boundary +# during parallel execution on completion of a sub-process +set saved_counters { suite_count suite_failed + case_count case_passed case_failed case_skipped + item_count item_started item_passed item_failed item_skipped} + +proc tools_clear_saved_counters {} { +# clear all counters, utility function to aid counter management during +# parallel execution, by clearing counters we can identify the changes +# which occurred in a sub-process for ultimate tabulations back into +# the parent processes counters +# +# case_status and item_status are text values, not counters + + global saved_counters + global tools_case_status + global tools_item_status + + foreach counter $saved_counters { + global tools_$counter + set tools_$counter 0 + } + set tools_case_status "okay" + set tools_item_status "okay" +} + +proc tools_save_counters { {errorcode 0} {errorinfo ""} } { +# +# output all counters to a [pid] based file +# Used for parallel test execution in sub-processes +# +# Arguments: +# errorcode - 0/1, should an error be propigated back to parent process +# errorinfo - info to pass back to parent in thrown error, only used if +# errorcode is 1 + + global saved_counters + global tools_case_status + global tools_item_status + + set filename "/tmp/testcount.[pid]" + catch { eval exec rm -f $filename } + set fileid [ open $filename "w" ] + if { [ catch { + foreach counter $saved_counters { + global tools_$counter + puts $fileid "$counter [set tools_$counter]" + } + puts $fileid "case_status $tools_case_status" + puts $fileid "item_status $tools_item_status" + puts $fileid "errorcode $errorcode" + # errorinfo must be the last counter, $errorinfo could be multi-line string + puts $fileid "errorinfo $errorinfo" + } res ] != 0 } { + show_message "save_counters failed: $res" + catch { close $fileid } + # remove file so parent recognizes a critical failure in child + catch { eval exec rm -f $filename } + } else { + catch { close $fileid } + } +} + +proc tools_clear_tmp_counters {} { +# +# clear the counters into which tools_update_tmp_counters adds its totals + + global tools_tmp_exit + global saved_counters + global tools_tmp_case_status + global tools_tmp_item_status + global tools_tmp_errorcode + global tools_tmp_errorinfo + + set tools_tmp_exit 0 + foreach counter $saved_counters { + global tools_tmp_$counter + set tools_tmp_$counter 0 + } + set tools_tmp_case_status "okay" + set tools_tmp_item_status "okay" + set tools_tmp_errorcode 0 + set tools_tmp_errorinfo "" +} + +proc tools_update_tmp_counters { pid } { +# +# fetch counters created by tools_save_counters and update tools_tmp_* + global env + global tools_tmp_case_status + global tools_tmp_item_status + global tools_tmp_errorcode + global tools_tmp_errorinfo + global tools_tmp_exit + + set filename "/tmp/testcount.$pid" + if { ! [ file exists "$filename" ] } { + set tools_tmp_exit 1 + return + } + set fileid [ open $filename "r" ] + if { [ catch { + while { [ gets $fileid line ] != -1 } { + set counter [ lindex $line 0 ] + set value [ lreplace $line 0 0 ] + if { "$counter" == "case_status" } { + if { "$value" == "skip"} { + set tools_tmp_case_status $value + } + } elseif { "$counter" == "item_status" } { + if { "$value" == "skip"} { + set tools_tmp_item_status $value + } + } elseif { "$counter" == "errorcode" } { + if { $value } { + set tools_tmp_errorcode $value + } + } elseif { "$counter" == "errorinfo" } { + if { "$value" != "" } { + set tools_tmp_errorinfo "$value" + } + # rest of file could be part of a long error message + while { [ gets $fileid line ] != -1 } { + append tools_tmp_errorinfo "\n$line" + } + } else { + global tools_tmp_$counter + incr tools_tmp_$counter $value + } + } + close $fileid + } res ] != 0 } { + catch { close $fileid } + set tools_tmp_exit 1 + } + catch { eval exec rm -f $filename } +} + +proc tools_remove_tmp_counters { pid } { +# +# remove counters file created by tools_save_counters + set filename "/tmp/testcount.$pid" + catch { eval exec rm -f $filename } +} + +proc add_item_counters { } { +# add tools_tmp_item_* to tools_item_* + global tools_suite_result + global tools_item_count + global tools_item_started + global tools_item_passed + global tools_item_failed + global tools_item_skipped + global tools_tmp_item_count + global tools_tmp_item_started + global tools_tmp_item_passed + global tools_tmp_item_failed + global tools_tmp_item_skipped + + incr tools_item_count $tools_tmp_item_count + incr tools_item_started $tools_tmp_item_started + incr tools_item_passed $tools_tmp_item_passed + incr tools_item_failed $tools_tmp_item_failed + incr tools_item_skipped $tools_tmp_item_skipped + if { $tools_tmp_item_failed > 0 } { + set tools_suite_result "FAILED" + } +} + +proc add_case_counters { } { +# add tools_tmp_case_* to tools_case_* and add_item_counters + global tools_suite_result + global tools_case_count + global tools_case_passed + global tools_case_failed + global tools_case_skipped + global tools_tmp_case_count + global tools_tmp_case_started + global tools_tmp_case_passed + global tools_tmp_case_failed + global tools_tmp_case_skipped + + incr tools_case_count $tools_tmp_case_count + incr tools_case_passed $tools_tmp_case_passed + incr tools_case_failed $tools_tmp_case_failed + incr tools_case_skipped $tools_tmp_case_skipped + add_item_counters + if { $tools_tmp_case_failed > 0 } { + set tools_suite_result "FAILED" + } +} + +proc add_suite_counters { } { +# add tools_tmp_* to tools_* + global tools_suite_count + global tools_suite_failed + + incr tools_suite_count $tools_tmp_suite_count + incr tools_suite_failed $tools_tmp_suite_failed + add_case_counters +} + +proc tools_check_process_results {} { +# check sub process results +# Returns: +# 1 - no failures which would justify a failure of parent +# 0 - failures which will result in failure of parent + + global tools_tmp_exit + global tools_tmp_suite_count + global tools_tmp_suite_failed + global tools_tmp_case_count + global tools_tmp_case_failed + global tools_tmp_item_count + global tools_tmp_item_failed + global tools_tmp_case_status + global tools_tmp_item_status + global tools_tmp_errorcode + global tools_tmp_errorinfo + + # beyond just adding counters, we simulate the effect of failures + # by looking at the _count counters to determine what was started + # within the parallel (to determine our context) and check + + if { $tools_tmp_exit } { + return 0 + } + if { $tools_tmp_suite_count > 0 } { + # must have started test_suites within parallel block + } elseif { $tools_tmp_case_count > 0 } { + # must have started test_case's within an existing test_suite + if { $tools_tmp_suite_failed } { + return 0 + } + } elseif { $tools_tmp_item_count > 0 } { + # must have started test_item's within an existing test_case + if { $tools_tmp_suite_failed || $tools_tmp_case_failed } { + return 0 + } + } else { + # parallel code within an existing item or in a general script + if { $tools_tmp_suite_failed || $tools_tmp_case_failed + || $tools_tmp_item_failed } { + return 0 + } + } + # if we didn't find a failure above, but there was an error from + # the sub-process + if { $tools_tmp_errorcode } { + return 0 + } + return 1 +} + +proc tools_propigate_process_results {} { +# +# Used for parallel test execution, takes tools_tmp_* counters and updates +# tools_* counters and performs fail_test, fail_suite, or error as needed + + global tools_suite_count + global tools_suite_failed + global tools_case_count + global tools_case_failed + global tools_item_count + global tools_item_failed + global tools_tmp_exit + global tools_tmp_suite_count + global tools_tmp_suite_failed + global tools_tmp_case_count + global tools_tmp_case_failed + global tools_tmp_item_count + global tools_tmp_item_failed + global tools_tmp_case_status + global tools_tmp_item_status + global tools_tmp_errorcode + global tools_tmp_errorinfo + + # beyond just adding counters, we simulate the effect of failures + # by looking at the _count counters to determine what was started + # within the parallel (to determine our context) and check + # failures to invoke the proper failure mechanism to cause the + # appropriate global effect in the calling process + if { $tools_tmp_exit } { + # one of the count files was missing, process must have exited + # we should do the same + exit 1 + } + if { $tools_tmp_suite_count > 0 } { + # must have started test_suites within parallel block + add_suite_counters + } elseif { $tools_tmp_case_count > 0 } { + # must have started test_case's within an existing test_suite + add_case_counters + if { $tools_tmp_suite_failed } { + fail_suite "suite failure during parallel execution" + } + } elseif { $tools_tmp_item_count > 0 } { + # must have started test_item's within an existing test_case + add_item_counters + if { $tools_tmp_suite_failed } { + fail_suite "suite failure during parallel execution" + } + if { $tools_tmp_case_failed } { + fail_test "case failure during parallel execution" + } + if { $tools_tmp_case_status == "skip" } { + # case skipped within parallel execution + skip_case "$tools_tmp_errorinfo" + } + } else { + # parallel code within an existing item or in a general script + if { $tools_tmp_suite_failed } { + fail_suite "suite failure during parallel execution" + } + if { $tools_tmp_case_failed } { + fail_test "case failure during parallel execution" + } + if { $tools_tmp_item_failed } { + fail_test "item failure during parallel execution" + } + if { $tools_tmp_case_status == "skip" } { + # case skipped within parallel execution + skip_case "$tools_tmp_errorinfo" + } + if { $tools_tmp_item_status == "skip" } { + # item skipped within parallel execution + skip_item "$tools_tmp_errorinfo" + } + } + # if we didn't find a failure above, but there was an error from + # the sub-process, invoke the general error mechanism + if { $tools_tmp_errorcode } { + error "$tools_tmp_errorinfo" "$tools_tmp_errorinfo" + } +} + +proc show_more_lines { linecnt { id "" } } { +## +## show_more_lines +## --------------- +## show the next few lines from the spawned program's output +## +## Usage: +## show_more_lines line_cnt [id] +## Arguments: +## line_cnt - number of lines to attempt to show +## id - spawn_id of child, default is global spawn_id +## Returns: +## nothing +## Additional Information: +## If a timeout or eof occurs before line_cnt lines are shown, this +## procedure returns without an error + + global expect_out + + if { "$id" == "" } { + global spawn_id + } else { + # use a local, expect_after isn't involved anyway + # since we cover eof and default cases here + set spawn_id $id + } + + # local timeout variable is purposely used so that + # any test_suite global settings are not altered + set timeout 1 + for { set i 0 } { $i < $linecnt } { incr i } { + expect { + "\n" noop + eof return + default break + } + } + log_message "" + return +} + +proc log_message { string } { +## +## log_message +## ----------- +## output an informative message +## +## Usage: +## log_message string +## Arguments: +## string - string to put to log, a newline will be appended +## Returns: +## nothing +## Additional Information: +## This will log the given string to the log_file, if there is +## no current log_file, it is output to stdout +## This should be used for all detailed output routines within +## test scripts or utility procedures. The case were it sends output +## to stdout, allows for interactive execution of commands which use this +## Otherwise, within a typical expect test script, the log_file will get +## the detailed output and stdout will only get brief messages +## +## This adds a newline at the end of string +## +## No output nor logging is generated for identify_mode + + global log_disable + + if { [ identify_mode ] } { + return + } + if { [log_file -info] == "" } { + if { ! $log_disable } { + puts "$string" + } + } else { + send_log "$string\n" + } + return +} + +proc show_message { string } { +## +## show_message +## ----------- +## output an informative message to stdout and the log +## +## Usage: +## show_message string +## Arguments: +## string - string to put to log and stdout, a newline will be appended +## Returns: +## nothing +## Additional Information: +## This will log the given string to the log_file, if there is one, +## and stdout +## +## This adds a newline at the end of string +## +## No output nor logging is generated for identify_mode + + if { [ identify_mode ] } { + return + } + if { [log_file -info] != "" } { + send_log "$string\n" + } + puts "$string" + return +} + +proc show_performance { string } { +## +## show_performance +## ----------- +## output performance results to stdout and the log +## +## Usage: +## show_performance string +## Arguments: +## string - string to put to log and stdout, a newline will be appended +## and each newline will be preceeded with "PERF " +## Returns: +## nothing +## Additional Information: +## This will log the given string to the log_file, if there is one, +## and stdout +## +## This adds a newline at the end of string +## +## No output nor logging is generated for identify_mode + + if { [ identify_mode ] } { + return + } + regsub -all "\n" $string "\nPERF " message + if { [log_file -info] != "" } { + send_log "PERF $message\n" + send_log "PERF ---------------------------------------------------------------------------\n" + } + puts "PERF $message" + puts "PERF ---------------------------------------------------------------------------\n" + return +} + +proc noop {} { +## +## noop +## ---- +## do nothing procedure +## +## Usage: +## noop +## Returns: +## nothing +## Additional Information: +## useful as the body for expect commands when the pattern needs no special +## execution + + return +} + +proc expect_eof { timelimit { ignore_rest 0 } } { +## +## expect_eof +## ---------- +## utility procedure to check for eof +## +## Usage: +## expect_eof timelimit [ignore_rest] +## Arguments: +## timelimit - maximum time to wait +## ignore_rest - ignore any data prior to eof (default 0) +## if 0 any data received before eof is an error +## Returns: +## eof found - nothing +## eof not found - error exception +## Additional Information: +## This is designed for use within test_case's $code +## After getting eof, it makes sure the child is terminated +## by waiting and/or killing child as needed +## The global timeout is saved, changed and restored by this routine + + global spawn_id + global expect_out + global timeout + global expecting + global env + + set save_timeout $timeout + + set_timeout $timelimit + + set expecting "EOF" + if { [ info exists env(TESTDEBUG) ] } { + log_message "DEBUG: expecting EOF" + } + + expect { + eof noop + "?*" { if { ! $ignore_rest } { + log_message "\nERROR: expected: EOF" + log_message "\nERROR: Unexpected data: $expect_out(buffer)" + fail_test "Unexpected data" + } else { + exp_continue + } + } + timeout { + log_message "\nERROR: timeout ($timeout) waiting for: EOF" + # get buffered data + expect * + if { "$expect_out(buffer)" != "" } { + log_message "\nERROR: timeout: Received data: $expect_out(buffer)" + fail_test "timeout: with data" + } else { + fail_test "timeout: No data" + } + } + default { log_message "\nERROR: expected: EOF" + fail_test "default" + } + } + # make sure child terminates + stop_child $spawn_id + + set timeout $save_timeout + + return +} + +proc ignore_rest {} { +## +## ignore_rest +## ----------- +## utility procedure to ignore the rest of the output +## by waiting and/or killing child as needed +## +## Usage: +## ignore_rest +## Returns: +## nothing +## Additional Information: +## This is designed for use within test_case's $code + + # make sure child terminates + child_cleanup + return +} + +proc run_cmd { cmd } { +## +## run_cmd +## ------- +## utility procedure to run a command with error logging +## +## Usage: +## run_cmd cmd +## Typical Usage: +## run_cmd {exec some_shell_command} +## Returns: +## output from command on success +## Additional Information: +## If the given command fails, it is logged along with the output +## from the command and an error is generated +## This is designed for use within test_case's $code + + global spawn_id + global spawn_out + global interact_out + global expect_out + global timeout + global expecting + global env + + if { [ info exists env(TESTDEBUG) ] } { + log_message "DEBUG: run_cmd $cmd" + } + if { [catch { eval $cmd } string] == 1 } { + set info "Command failed: $cmd" + log_message "$info" + log_message "$string" + error "$info" "$info" + } else { + return "$string" + } +} + +proc compare_files { file1 file2 } { +## +## compare_files +## ------------- +## utility procedure to compare 2 ascii files +## +## Usage: +## compare_files file1 file2 +## Returns: +## match - nothing +## mismatch - error exception +## Additional Information: +## This is designed for use within test_case's $code +## It causes an error exception if the files do not match + + log_message "Comparing $file1 to $file2" + run_cmd "exec diff $file1 $file2" + return +} + +proc compare_tdiff_files { file1 file2 } { +## +## compare_tdiff_files +## --------------------- +## utility procedure to compare a file against a pattern/template using tdiff +## +## Usage: +## compare_tdiff_files file1 file2 +## Returns: +## match - nothing +## mismatch - error exception +## Additional Information: +## This is designed for use within test_case's $code +## It causes an error exception if the files do not match + + log_message "Comparing template $file1 to $file2" + run_cmd "exec tdiff $file1 $file2" + return +} + +proc compare_binary_files { file1 file2 } { +## +## compare_binary_files +## -------------------- +## utility procedure to compare 2 binary files +## +## Usage: +## compare_files file1 file2 +## Returns: +## match - nothing +## mismatch - error exception +## Additional Information: +## This is designed for use within test_case's $code +## It causes an error exception if the files do not match + + log_message "Comparing Binary $file1 to $file2" + run_cmd "exec cmp $file1 $file2" + return +} + +proc match_files { range_list template_list file_list } { +## +## match_files +## ----------- +## allow a set of templates and data_files to be matched in any combination +## +## Usage: +## match_files range_list template_list datafile_list +## Arguments: +## range_list - a list of ranges. Each indicates the number of times +## each template must be matched. +## The number of range_list elements can't exceed +## the number of template_list elements. If ranges are not +## provided for all template_list elements, the additional +## template_list elementswill all have the last range provided. +## If the range_list is empty, the default is "1" +## A given range list element cannot include any spaces or tabs. +## Format (X and Y are positive integers): +## X expect exactly this many matches of command +## X-Y Allow up to Y matches, require X matches. +## X- Similar to X-Y, but Y is infinite. +## The special range "m" may be included at the start of the +## list to indicate that every template_list entry which has +## not yet reached its maximum match count should be applied +## against the data_file. +## template_list - a list of tdiff template files to be matched. +## datafile_list - a list of tdiff data files to be matched against the +## templates. +## Returns: +## match - "matched" +## mismatch - error exception +## invalid args - error exception +## Additional Information: +## If the template_files are not each matched the required minimum +## times, this routine returns with an error exception. +## +## For each data file, the template files are processed in the +## order provided. Once a given template file has matched its maximum +## number of occurances (Y), it is no longer executed against +## subsequent data files. +## +## If some of the ranges are not 1, it is valid to have the number of +## elements in the file_list differ from the number of elements in +## the template_list. +## +## The special m range parallels the tdiff %orderless -m option. +## This allows every unmaxed template to be applied against each data_file +## This can be especially useful for protocols such as SMTP which may +## handle multiple recipient distributions by sending 1 distribution with +## all the recipients or multiple distributions with various subsets of +## the recipient list. +## In which case, a template file should exist to match a distribution +## with the given recipient (and possibly others) and that list could +## be applied against the distributions received to verify that +## all the recipients got mail. +# +# local variables: +# scoreboard(#) - count that template_list element # has matched +# range_min(#), range_max(#) - range values for template_list +# element # + + log_message "Matching files { $range_list } { $template_list } { $file_list }" + + set num_data_files [llength $file_list] + set num_template_files [llength $template_list] + set num_ranges [llength $range_list] + set match_many 0 + + if { $num_template_files == 0 } { + set info "match_files: empty template_list" + error "$info" "$info" + } + + if { $num_ranges >= 1 && [lindex $range_list 0] == "m" } { + set match_many 1 + incr num_ranges -1 + if { $num_ranges > 0 } { + set range_list [lrange $range_list 1 $num_ranges] + } else { + set range_list {} + } + } + + if { $num_template_files < $num_ranges } { + set info "match_files: range_list larger than template_list" + error "$info" "$info" + } + + set last_range_min 1 + set last_range_max 1 + + for { set i 0 } { $i < $num_template_files } { incr i } { + if { $i >= $num_ranges } { + set range_min($i) $last_range_min + set range_max($i) $last_range_max + } else { + parse_range [lindex $range_list $i] range_min($i) range_max($i) + set last_range_min $range_min($i) + set last_range_max $range_max($i) + } + set scoreboard($i) 0 + } + foreach data_file $file_list { + set match 0; # has this data_file been matched yet + set allmin 1; # assume all matched at minimum + set allmax 1; # assume all matched at maximum + + for { set i 0 } { $i < $num_template_files } { incr i } { + set template_file [lindex $template_list $i] + if { $range_max($i) != -1 + && $scoreboard($i) >= $range_max($i) } { + # debug output + # puts "match_files: template $template_file reached max ($range_max($i))" + continue + } + if { ! $match || $match_many } { + if { [ catch { exec tdiff $template_file $data_file } ] == 0 } { + # file match + incr scoreboard($i) + set match 1 + log_message "$data_file matched by $template_file" + } + } + if { $allmin && $scoreboard($i) < $range_min($i) } { + set allmin 0 + # values for error message + set not_min $template_file + set not_min_cnt $range_min($i) + } + if { $range_max($i) == -1 + || $scoreboard($i) < $range_max($i) } { + set allmax 0 + } + } + # debug print + # puts "allmin=$allmin allmax=$allmax match=$match" + + if { ! $match } { + # no match found for any template + if { $allmax } { + set info "match_files: unable to match $data_file, all templates at maximum matches" + error "$info" "$info" + } else { + set info "match_files: unable to match $data_file" + error "$info" "$info" + } + } + } + + if { ! $allmin } { + # some template_files not matched minimum number of times + set info "match_files: unable to match $not_min $not_min_cnt times" + error "$info" "$info" + } + return matched +} + +proc parse_range { range min_ref max_ref } { +# parse a range +# Arguments: +# range - range to parse +# min_ref - name of variable to hold min +# max_ref - name of variable to hold max +# Returns: +# nothing +# Additional Information: +# Fatal error on invalid range +# + upvar $min_ref min + upvar $max_ref max + + if { [regexp {[0-9]+-[0-9]+} $range] == 1 } { + scan $range "%d-%d" min max + } elseif { [regexp {[0-9]+-} $range] == 1 } { + scan $range "%d-" min + set max -1 + } elseif { [regexp {[0-9]+} $range] == 1 } { + set min $range + set max $min + if { $min > $max } { + set info "Invalid range: $range" + error "$info" "$info" + } + } else { + set info "Invalid range: $range" + error "$info" "$info" + } + return +} + +proc build_file_list { filename_list } { +## +## build_file_list +## --------------- +## Build a list of filenames from a list of files/directories +## +## Arguments: +## filename_list - list of file/directory names +## Returns: +## list of non-directory files +## +## Additional Information: +## All directory entries within filename_list are recursively searched +## and replaced in the list with a list of all the non-directory files +## found within them. +## +## Note that the entire list is kept in memory. + + set file_list {} + foreach filename $filename_list { + if { [file isdirectory $filename] } { + foreach filen [glob $filename/*] { + set file_list [concat $file_list [build_file_list $filen]] + } + } else { + set file_list [concat $file_list $filename] + } + } + return $file_list +} + +proc clean_file_list { filename_list } { +## +## clean_file_list +## --------------- +## delete the files in the file name list. Used by +## tests that are long running enough +## +## Arguments: +## filename_list - list of file/directory names +## +## Addtional Information: +## Intended for use by tests that are long running enough to build +## up an extreme number of send files. Large directories cause +## performance problems for stress tests that run for a long +## time. +## + set hit_list [ build_file_list $filename_list ] + foreach file $hit_list { + catch { eval exec rm -f $file [ glob -nocomplain $file.* ] } + } +} + +proc repeat_command { command file_list cnt_list } { +## +## repeat_command +## -------------- +## execute a command repeatedly against a set of files +## +## Usage: +## repeat_command command file_list cnt_list +## Arguments: +## command - tcl command to execute (can include arguments if passed as +## a list +## file_list - list of files to supply to each execution of command +## - note this really does not have to be a filelist +## however that is the typical case +## cnt_list - list of counts to apply to command +## if the cnt_list has fewer elements than the file_list, the +## last cnt_list entry is applied to the remaining file_list +## entries. An empty cnt_list is equivalent to { 1 } +## Returns: +## nothing +## Sample: +## repeat_command { /etc/init.d/ics_srp} { restart } { 10} +## +## This does the followingi 10 times: +## /etc/init.d/ics_srp restart +## +## repeat_command { fsck} { /dev/sdb /dev/sdc /dev/sdd } { 2 2 1} +## fsck /dev/sdb /dev/sdc /dev/sdd +## fsck /dev/sdb /dev/sdc +## Note that per the count, /dev/sdd was omitted from the 2nd call +## +## This command is very useful when counts are very large + + log_message "performing repeated operation: $command\n\ton { $file_list }\n\tfor { $cnt_list }" + + set num_files [llength $file_list] + set num_cnt [llength $cnt_list] + + if { $num_files == 0 } { + set info "repeat_command: empty file_list" + error "$info" "$info" + } + + if { $num_files < $num_cnt } { + set info "repeat_command: cnt_list larger than file_list" + error "$info" "$info" + } + + set last_cnt 1 + set max_cnt 1 + + # set up cnt(x) for each file_list entry + for { set i 0 } { $i < $num_files } { incr i } { + if { $i >= $num_cnt } { + set cnt($i) $last_cnt + } else { + set cnt($i) [lindex $cnt_list $i] + set last_cnt $cnt($i) + } + if { $last_cnt > $max_cnt } { + set max_cnt $last_cnt + } + } + + # do the command max_cnt times + for { set i 0 } { $i < $max_cnt } { incr i } { + + # build f_list with list of file_list elements to use + set f_list {} + for { set j 0 } { $j < $num_files } { incr j } { + if { $i < $cnt($j) } { + # [list ...] allows a file_list element to + # be a list, in which case it is kept as + # a list + set f_list [concat $f_list [list [lindex $file_list $j]]] + } + } + + # execute command + log_message "$command [list $f_list]\n" + uplevel 1 $command [list $f_list] + } + return +} + +proc scp_get_file { host usercode target_filename local_filename } { +## +## scp_get_file +## -------- +## scp a file from the target system to the local system +## +## Usage: +## scp_get_file host usercode target_filename local_filename +## Arguments: +## host - host to connect to +## usercode - usercode on that host +## target_filename - file to get +## local_filename - destination file on local system + global env + + if { ! [ info exists env(CFG_SCP_FLAGS) ] } { + set env(CFG_SCP_FLAGS) "" + } + + #randomly wait up to a minute to alleviate many hosts attempting to scp files at once + unix_cmd 150 0 "r=\$(( \$RANDOM % 60 + 1 )); sleep \$r" + + unix_cmd 400 0 "scp $env(CFG_SCP_FLAGS) $usercode@$host:/nfs/site/proj/stlbuilds/$target_filename $local_filename" +} + +proc ftp_connect { host usercode password { do_spawn 1 } } { +## +## ftp_connect +## -------- +## establish an ftp connection +## +## Usage: +## ftp_connect host usercode password [do_spawn] +## Arguments: +## host - host to connect to +## usercode - usercode on that host +## password - password on that host +## do_spawn - should we spawn a expect session (eg. one not in progress already) +## Additional Information: + + global spawn_id + global expect_out + global spawn_out + global timeout + global expecting + global env + global stty_init + + # -i option will avoid y/n prompts in mget + if { $do_spawn } { + test_spawn "ftp -i" ftp -i $host + } else { + send_unix_cmd "ftp -i $host" + } + set timeout 120 + set expecting "ftp login sequence" + expect { + "Name*:" { exp_send "$usercode\n" + exp_continue + } + "assword:" { exp_send "$password\n" + exp_continue + } + "ftp: * +" { + fail_test "ftp login failed" + } + "ftp> " noop + } +} + +proc ftp_send_file { host usercode password local_filename target_filename {type "binary" } {do_spawn 1}} { +## +## ftp_send_file +## -------- +## ftp a file from the local system to the specified target system +## +## Usage: +## ftp_send_file host usercode password local_filename target_filename [type] [do_spawn] +## Arguments: +## host - host to connect to +## usercode - usercode on that host +## password - password on that host +## local_filename - file to send +## target_filename - destination on host for file +## type - type of file (ascii or binary). Default is binary +## do_spawn - should we spawn a expect session (eg. one not in progress already) + + global spawn_id + global expect_out + global spawn_out + global timeout + global expecting + + set save_timeout $timeout + ftp_connect $host $usercode $password $do_spawn + + exp_send "$type\n" + expect_list 60 { "ftp> " } { "Not connected" } + + # allow for large files + exp_send "exp_send $local_filename $target_filename\n" + expect_list 600 { "bytes sent" } { "Error" "Not connected" "No such" } + expect_list 60 { "ftp> " } { "Not connected" "No such" } + exp_send "quit\n" + expect_any 60 { "221" "Goodbye" "So long" } { "ftp> " } + if { $do_spawn } { + wait_eof 60 + } + set timeout $save_timeout +} + +proc ftp_get_file { host usercode password target_filename local_filename {type "binary" } {do_spawn 1} } { +## +## ftp_get_file +## -------- +## ftp a file from the target system to the local system +## +## Usage: +## ftp_get_file host usercode password target_filename local_filename [type] [do_spawn] +## Arguments: +## host - host to connect to +## usercode - usercode on that host +## password - password on that host +## target_filename - file to get +## local_filename - destination file on local system +## type - type of file (ascii or binary). Default is binary +## do_spawn - should we spawn a expect session (eg. one not in progress already) + + global spawn_id + global expect_out + global spawn_out + global timeout + + set save_timeout $timeout + ftp_connect $host $usercode $password $do_spawn + + exp_send "$type\n" + expect_list 60 { "ftp> " } { "Not connected" } + + exp_send "get $target_filename $local_filename\n" + # allow for large files + expect_list 600 { "bytes received" } { "Error" "Not connected" "No such" } + expect_list 60 { "ftp> " } { "Not connected" "No such" } + exp_send "quit\n" + expect_any 60 { "221" "Goodbye" "So long" } { "ftp> " } + if { $do_spawn } { + wait_eof 60 + } + set timeout $save_timeout +} + +proc ftp_mget_files { host usercode password target_directory target_pattern local_directory {type "binary" } {do_spawn 1}} { +## +## ftp_mget_files +## -------- +## ftp a set of files from the target system to the local system +## +## Usage: +## ftp_mget_files host usercode password target_directory target_filename +## local_directory [type] [do_spawn] +## Arguments: +## host - host to connect to +## usercode - usercode on that host +## password - password on that host +## target_directory - directory to get files from +## target_pattern - files to get (can be wildcarded for target system) +## local_directory - destination directory on local system +## type - type of files (ascii or binary). Default is binary +## do_spawn - should we spawn a expect session (eg. one not in progress already) + + global spawn_id + global expect_out + global spawn_out + global timeout + + set save_timeout $timeout + ftp_connect $host $usercode $password $do_spawn + + exp_send "$type\n" + expect_list 60 { "ftp> " } { "Not connected" } + + exp_send "cd $target_directory\n" + expect_list 60 { "ftp> " } { "Not connected" } + exp_send "lcd $local_directory\n" + expect_list 60 { "ftp> " } { "Not connected" } + exp_send "mget $target_pattern\n" + # allow for large files + expect_list 600 { "bytes received" } { "Error" "Not connected" "No such" } + expect_list 60 { "ftp> " } { "Not connected" "No such" } + exp_send "quit\n" + expect_any 60 { "221" "Goodbye" "So long" } { "ftp> " } + if { $do_spawn } { + wait_eof 60 + } + set timeout $save_timeout +} + +proc date_stamp {} { +## +## datestamp +## --------- +## +## Usage: +## date_stamp +## Returns: +## date in an identical format to the date command +## Additional Information: +## should be used in preference to [exec date]. The performance +## difference is 30 vs 175000 microseconds. +## + return [timestamp -format "%a %b %d %X %Z %Y"] +} + +proc tools_mult_timeout { mult } { +## +## tools_mult_timeout +## ------------ +## adjust timeout multiplier by a factor of mult +## +## Usage: +## tools_mult_timeout mult +## Arguments: +## mult - multiply timeout multiplier by mult +## Returns: +## None +## Additional Information: +## updates the environment variable TEST_TIMEOUT_MULT + + global env + set env(TEST_TIMEOUT_MULT) [ expr $mult * [ test_get_env TEST_TIMEOUT_MULT] ] +} + +proc calc_timeout { timelimit } { +## +## calc_timeout +## ------------ +## calculate the timeout value to use by adjusting by TEST_TIMEOUT_MULT +## +## Usage: +## calc_timeout timelimit +## Arguments: +## timelimit - a timeout value in seconds +## Returns: +## timelimit adjusted by TEST_TIMEOUT_MULT +## Additional Information: +## The environment variable TEST_TIMEOUT_MULT is used as an optional +## multiplier for all timeout values. This can be exported by the user +## to adjust all the timeouts in a test to account for slow systems or +## the use of debug tools such as printf or purify which significantly +## affect the performance of the system. + + return [ expr $timelimit * [ test_get_env TEST_TIMEOUT_MULT] ] +} + +proc set_timeout { timelimit } { +## +## set_timeout +## ----------- +## set the expect timeout variable accounting for TEST_TIMEOUT_MULT +## +## Usage: +## set_timeout timelimit +## Arguments: +## timelimit - a timeout value in seconds +## Returns: +## The timeout value set +## Additional Information: +## The timeout variable in the callers stack frame is set. It is up +## to the caller to determine if this is the global or local version +## of timeout. + + # sets the expect timeout variable in the stack frame of the caller + return [ uplevel set timeout [ calc_timeout $timelimit ] ] +} + +proc expect_list { timelimit list { error_list "" } { out_var "" } } { +## +## expect_list +## ----------- +## apply expect sequencially against a list of messages +## +## Usage: +## expect_list timelimit list [error_list [out_var]] +## Arguments: +## timelimit - maximum wait for each message +## list - list of messages to expect, they are regular expressions +## error_list - optional list of messages, fails if any gotten, +## regular expressions +## out_var - variable in callers context to receive all text which was +## received during during this expect +## Returns: +## string in output which matched last regular expression in list +## (this is also held in $expect_out(0,string) ) +## Additional Information: +## the expecting global is set as each item is expect'ed for such that +## any errors are appropriately reported +## an error is automatically reported if any of the error_list messages +## are gotten at any point. Avoid having an error_list message be +## a subset or part of a valid list message +## The global timeout is saved, changed and restored by this routine + + global spawn_id + global expect_out + global spawn_out + global timeout + global expecting + global env + + set save_timeout $timeout + + set_timeout $timelimit + + if { "$out_var" != "" } { + upvar $out_var out + set out "" + } + # match against a 10 screen buffer + match_max 19200 + # expect is real picky about the quoting and braces here + set fail_cmd { + log_message "\nERROR: while waiting for: $expecting" + log_message "\nERROR: Received data: $expect_out(buffer)" + fail_test "Invalid data" + } + foreach item $list { + set arg_list {} + foreach err_item $error_list { + append arg_list " -re {$err_item} { + log_message {\nERROR: invalid data: $err_item} + $fail_cmd + }" + } + append arg_list " -re {$item} noop" + set expecting "$item" + if { [ info exists env(TESTDEBUG) ] } { + log_message "DEBUG: spawn_id: $spawn_id expecting: $expecting" + } + eval expect "{ + $arg_list + }" + if { "$out_var" != "" } { + append out $expect_out(buffer) + } + } + + set timeout $save_timeout + return $expect_out(0,string) +} + +proc expect_any { timelimit list { error_list "" } { out_var ""} } { +## +## expect_any +## ----------- +## apply expect once against a list of messages, succeed if matches any one +## message in list +## +## Usage: +## expect_any timelimit list [error_list [out_var]] +## Arguments: +## timelimit - maximum wait for each message +## list - list of messages to expect, they are regular expressions +## error_list - optional list of messages, fails if any gotten, +## regular expressions +## out_var - variable in callers context to receive all text which was +## received during during this expect +## Returns: +## string in output which matched a regular expression in list +## (this is also held in $expect_out(0,string) ) +## Additional Information: +## accept 1st of list (eg. expects any 1 of list) +## the expecting global is set such that +## any errors are appropriately reported +## an error is reported if any of the error_list messages +## are gotten. Avoid having an error_list message be +## a subset or part of a valid list message +## The global timeout is saved, changed and restored by this routine + + global spawn_id + global expect_out + global spawn_out + global timeout + global expecting + global env + + set save_timeout $timeout + + set_timeout $timelimit + + if { "$out_var" != "" } { + upvar $out_var out + set out "" + } + # expect is real picky about the quoting and braces here + set fail_cmd { + log_message "\nERROR: while waiting for: $expecting" + log_message "\nERROR: Received data: $expect_out(buffer)" + fail_test "Invalid data" + } + set expecting "" + set arg_list {} + foreach err_item $error_list { + append arg_list " -re {$err_item} { + log_message {\nERROR: invalid data: $err_item} + $fail_cmd + }" + } + foreach item $list { + append arg_list " -re {$item} noop" + if { "$expecting" == "" } { + set expecting "$item" + } else { + set expecting "$expecting OR $item" + } + } + if { [ info exists env(TESTDEBUG) ] } { + log_message "DEBUG: spawn_id: $spawn_id expecting: $expecting" + } + eval expect "{ + $arg_list + }" + if { "$out_var" != "" } { + append out $expect_out(buffer) + } + + set timeout $save_timeout + return $expect_out(0,string) +} + +proc expect_progress { timelimit progress_list done_list { error_list "" } { out_var "" } } { +## +## expect_progress +## ----------- +## apply expect against a long running operation which reflects progress +## +## Usage: +## expect_progress timelimit progress_list done_list [error_list [out_var]] +## Arguments: +## timelimit - maximum wait for each message +## progress_list - list of progress messages to expect, +## they are regular expressions +## done_list - list of completion messages to expect, +## they are regular expressions +## error_list - optional list of messages, fails if any gotten, +## regular expressions +## out_var - variable in callers context to receive all text which was +## received during during this expect +## Returns: +## string in output which matched a regular expression in done_list +## (this is also held in $expect_out(0,string) ) +## Additional Information: +## expects to see at least one progress_list or done_list message +## within each timelimit interval. +## progress_list messages reset timelimit and expect is run again +## progress_list messages can be repeated or seen in any order. +## There is no requirement for any nor all of them to occur. +## done_list messages indicate completion and all must appear in the order +## given. +## the expecting global is set as each done item is expect'ed for such that +## any errors are appropriately reported +## an error is automatically reported if any of the error_list messages +## are gotten at any point. Avoid having an error_list message be +## a subset or part of a valid list message +## The global timeout is saved, changed and restored by this routine + + global spawn_id + global expect_out + global spawn_out + global timeout + global expecting + global env + + set save_timeout $timeout + + set_timeout $timelimit + + if { "$out_var" != "" } { + upvar $out_var out + set out "" + } + # expect is real picky about the quoting and braces here + set fail_cmd { + log_message "\nERROR: while waiting for: $expecting" + log_message "\nERROR: Received data: $expect_out(buffer)" + fail_test "Invalid data" + } + foreach item $done_list { + set arg_list {} + foreach err_item $error_list { + append arg_list " -re {$err_item} { + log_message {\nERROR: invalid data: $err_item} + $fail_cmd + }" + } + append arg_list " -re {$item} noop" + set expecting "$item" + foreach prog_item $progress_list { + append arg_list " -re {$prog_item}" + append arg_list { { + if { "$out_var" != "" } { + append out $expect_out(buffer) + } + exp_continue } } + append expecting " OR $prog_item" + } + if { [ info exists env(TESTDEBUG) ] } { + log_message "DEBUG: spawn_id: $spawn_id expecting: $expecting" + } + eval expect "{ + $arg_list + }" + if { "$out_var" != "" } { + append out $expect_out(buffer) + } + } + + set timeout $save_timeout + return $expect_out(0,string) +} + +proc _got_orderless_item { got once listname error_listname indexname } { +# +# _got_orderless_item +# ------------------- +# Process a matched item +# +# Usage: +# _got_orderless_item got once listname error_listname indexname +# +# Arguments: +# got - pattern matched within the list +# once - should got be added to error_list (1=yes, 0=no) +# listname - name of list variable which contains $got +# error_listname - name of error_list variable to update +# indexname - name of variable to hold index of got within list +# Additional Information: +# list is updated to remove got from it +# if once, got is appended to error_list +# fatal error if got not found in list +# list is a list of string match, expect style patterns + + upvar $listname list + upvar $error_listname error_list + upvar $indexname index + + set index [ lsearch -exact $list $got ] + if { $index == -1 } { + fail_test "Bug in expect_list_orderless: got={$got}, list={$list}" + } + set list [ lreplace $list $index $index ] + if { $once } { + lappend error_list "$got" + } +} + +proc expect_list_orderless { timelimit once list { error_list "" } { out_var ""} } { +## +## expect_list_orderless +## ----------- +## apply expect against a list of messages, order independently +## +## Usage: +## expect_list_orderless timelimit once list [error_list [out_var]] +## Arguments: +## timelimit - maximum time to wait for next message +## once - if 1, it is an error for any of the messages in list to +## occur more than once, if 0 they can occur any number of +## times +## list - list of messages to expect, regular expressions +## error_list - optional list of messages, fails if any gotten, +## regular expressions +## out_var - variable in callers context to receive all text which was +## received during during this expect +## Returns: +## string in output which last matched a regular expression in list +## (this is also held in $expect_out(0,string) ) +## Additional Information: +## the expecting global is set as each item set is expect'ed for such that +## any errors are appropriately reported +## an error is automatically reported if any of the error_list messages +## are gotten at any point. Avoid having an error_list message be +## a subset or part of a valid list message +## list messages should not be subsets of eachother +## The messages in list are permitted to occur in any order. +## If you want to permit a given message to occur more than once, +## set once=0 +## The global timeout is saved, changed and restored by this routine + + global spawn_id + global expect_out + global spawn_out + global timeout + global expecting + global env + + set save_timeout $timeout + + set_timeout $timelimit + + if { "$out_var" != "" } { + upvar $out_var out + set out "" + } + # expect is real picky about the quoting and braces here + set fail_cmd { + log_message "\nERROR: while waiting for: $expecting" + log_message "\nERROR: Received data: $expect_out(buffer)" + fail_test "Invalid data" + } + while { [ llength $list ] != 0 } { + # build arg_list with the list of valid items + # expecting indicates all the items remaining + set expecting "" + set arg_list {} + foreach err_item $error_list { + append arg_list " -re {$err_item} { + log_message {\nERROR: invalid data: $err_item} + $fail_cmd + }" + } + foreach item $list { + append arg_list " -re {$item} { set got {$item} }" + if { "$expecting" == "" } { + set expecting "$item" + } else { + set expecting "$expecting OR $item" + } + } + set got "" + if { [ info exists env(TESTDEBUG) ] } { + log_message "DEBUG: expecting $expecting" + } + eval expect "{ + $arg_list + }" + if { "$out_var" != "" } { + append out $expect_out(buffer) + } + # if we did not fail_test by getting an invalid item, + # got will indicate what we did get + # Remove that item from the list of valid messages and + # if once, add it to the list of invalid message + if { "$got" != "" } { + _got_orderless_item $got $once list error_list index + # expect will take a single output buffer and + # apply the patterns in the order given, in the event + # of a large output or multiple patterns which should + # be matched by a single line, expect may match fewer + # patterns than are possible to be matched + # now see if other patterns in the remainder of + # the list are also matched + foreach item [ lrange $list $index end ] { + if { [ regexp ".*$item.*" $expect_out(buffer) ] == 1 } { + _got_orderless_item $item $once list error_list index + } + } + } else { + fail_test "Bug in expect_list_orderless, got={}" + } + } + + set timeout $save_timeout + return $expect_out(0,string) +} + +proc expect_progress_orderless { timelimit progress_list once done_list { error_list "" } { out_var ""} } { +## +## expect_progress_orderless +## ----------- +## apply expect against a long running operation which reflects progress +## and expect a list of messages, order independently +## +## Usage: +## expect_progress_orderless timelimit progress_list once done_list [error_list [out_var]] +## Arguments: +## timelimit - maximum time to wait for next message +## progress_list - list of progress messages to expect, +## they are regular expressions +## once - if 1, it is an error for any of the messages in list to +## occur more than once, if 0 they can occur any number of +## times +## done_list - list of completion messages to expect, regular expressions +## error_list - optional list of messages, fails if any gotten, +## regular expressions +## out_var - variable in callers context to receive all text which was +## received during during this expect +## Returns: +## string in output which last matched a regular expression in done_list +## (this is also held in $expect_out(0,string) ) +## Additional Information: +## expects to see at least one progress_list or done_list message +## within each timelimit interval. +## progress_list messages reset timelimit and expect is run again +## progress_list messages can be repeated or seen in any order. +## There is no requirement for any nor all of them to occur. +## the expecting global is set as each item set is expect'ed for such that +## any errors are appropriately reported +## an error is automatically reported if any of the error_list messages +## are gotten at any point. Avoid having an error_list message be +## a subset or part of a valid list message +## done_list messages should not be subsets of eachother +## The messages in done_list are permitted to occur in any order. +## If you want to permit a given message to occur more than once, +## set once=0 +## The global timeout is saved, changed and restored by this routine + + global spawn_id + global expect_out + global spawn_out + global timeout + global expecting + global env + + set save_timeout $timeout + + set_timeout $timelimit + + if { "$out_var" != "" } { + upvar $out_var out + set out "" + } + # expect is real picky about the quoting and braces here + set fail_cmd { + log_message "\nERROR: while waiting for: $expecting" + log_message "\nERROR: Received data: $expect_out(buffer)" + fail_test "Invalid data" + } + while { [ llength $done_list ] != 0 } { + # build arg_list with the list of valid items + # expecting indicates all the items remaining + set expecting "" + set arg_list {} + foreach err_item $error_list { + append arg_list " -re {$err_item} { + log_message {\nERROR: invalid data: $err_item} + $fail_cmd + }" + } + foreach item $done_list { + append arg_list " -re {$item} { set got {$item} }" + if { "$expecting" == "" } { + set expecting "$item" + } else { + set expecting "$expecting OR $item" + } + } + foreach prog_item $progress_list { + append arg_list " -re {$prog_item}" + append arg_list { { + if { "$out_var" != "" } { + append out $expect_out(buffer) + } + exp_continue } } + append expecting " OR $prog_item" + } + set got "" + if { [ info exists env(TESTDEBUG) ] } { + log_message "DEBUG: spawn_id: $spawn_id expecting: $expecting" + } + eval expect "{ + $arg_list + }" + if { "$out_var" != "" } { + append out $expect_out(buffer) + } + # if we did not fail_test by getting an invalid item, + # got will indicate what we did get + # Remove that item from the list of valid messages and + # if once, add it to the list of invalid message + if { "$got" != "" } { + _got_orderless_item $got $once done_list error_list index + # expect will take a single output buffer and + # apply the patterns in the order given, in the event + # of a large output or multiple patterns which should + # be matched by a single line, expect may match fewer + # patterns than are possible to be matched + # now see if other patterns in the remainder of + # the list are also matched + foreach item [ lrange $done_list $index end ] { + if { [ regexp ".*$item.*" $expect_out(buffer) ] == 1 } { + _got_orderless_item $item $once done_list error_list index + } + } + } else { + fail_test "Bug in expect_list_orderless, got={}" + } + } + + set timeout $save_timeout + return $expect_out(0,string) +} + +proc test_execute {list code} { +## +## test_execute +## ------------ +## Conditionally execute the block of code specified +## +## Usage: +## test_execute { list } { +## conditional code +## } +## Arguments: +## list - a list of conditions under which the code should not be run. The +## items specified in the list are searched for in the +## TEST_NOEXECUTE environment variable and if found, the code is +## not executed. +## code = Tcl commands for execution (typically a list) +## Returns: +## None +## Additional Information: +## This routine will not execute any code if any of the items in the list +## are located in the TEST_NOEXECUTE environment variable list. +## Further, the code is not executed if the TEST_IDENTIFY environment +## variable is defined. +## + global env + + if { ! [ identify_mode ] } { + set skip 0 + if { [ info exists env(TEST_NOEXECUTE) ] } { + foreach item $list { + if { [lsearch -exact "$env(TEST_NOEXECUTE)" $item ] != -1 } { + set skip 1; + break; + } + } + } + if { $skip == 0 } { + uplevel $code + } + } +} + +proc show_config {} { +## +## show_config +## ------------- +## determine if tests are being run with show config enabled +## +## Usage: +## show_config +## Returns: +## 0 - no +## 1 - yes + + return [ test_check_yn [ test_get_env TEST_SHOW_CONFIG ] ] +} + +proc show_start {} { +## +## show_start +## ------------- +## determine if tests are being run with show start enabled +## +## Usage: +## show_start +## Returns: +## 0 - no +## 1 - yes + + return [ test_check_yn [ test_get_env TEST_SHOW_START ] ] +} + +proc identify_mode {} { +## +## identify_mode +## ------------- +## determine if tests are being run in identify mode +## +## Usage: +## identify_mode +## Returns: +## 0 - no +## 1 - yes + + return [ test_check_yn [ test_get_env TEST_IDENTIFY ] ] +} + +proc get_config_path { filename } { +## +## get_config_path +## ----------- +## Return the path to the configuration file specified +## +## Arguments: +## filename - name of a configuration file +## Additional Information: + + global env + + if { ( ! [ file exists $filename ] || [ file isdirectory $filename ] ) + && [ info exists env(TL_DIR) ] } { + set dir1 "$env(TL_DIR)/configs" + set dir2 "$env(TL_DIR)/HostTestCases/configs" + if { [ file isdirectory "$dir1" ] + && [ file exists "$dir1/$filename" ] } { + return "$dir1/$filename" + } elseif { [ file isdirectory "$dir2" ] + && [ file exists "$dir2/$filename" ] } { + return "$dir2/$filename" + } else { + set res "get_config_path: unable to find $filename in ., $dir1 nor $dir2" + log_message "$res" + error "$res" + } + } elseif { [ file exists $filename ] } { + return "$filename" + } +} + +proc read_config { filename } { +## +## read_config +## ----------- +## Read the configuration file specified +## +## Arguments: +## filename - name of a configuration file +## Additional Information: +## The configuration file consists of lines of the form: +## parameter_name value +## OR +## include filename +## If the "parameter_name" is # or the line is blank, +## the given line is ignored +## Otherwise the parameter is set to the supplied value unless +## it is already exported. This allows the configuration to +## be partially overridden by the environment. It also permits the +## setting of any environment variables (such as TEST_FAIL_SAVE) +## An omitted "value" field results in the parameter being set to the +## null string +## If parameter_name is already exported, it overrides the value in the +## config file. Due to use of eval, value for a parameter can include +## references to other parameters and environment variables as $env(name) + + global env + + if { [ show_config ] } { + show_message "Test Configuration File: $filename" + } + set filename [get_config_path $filename ] + set fileid [ open $filename "r" ] + if { [ catch { + while { [ gets $fileid line ] != -1 } { + set parameter [ lindex $line 0 ] + if { "$parameter" == "" + || "[ string index $parameter 0 ]" == "#" } { + # comment or blank line + continue + } + eval set value \[ lreplace \"$line\" 0 0 \] + #set value [ lreplace $line 0 0 ] + if { "$parameter" == "include" } { + read_config "$value" + } else { + if { ! [ info exists env($parameter) ] } { + set env($parameter) "$value" + #eval set env($parameter) \"$value\" + } + # show the parameter values + set message [ format "%-25s %s" $parameter $env($parameter) ] + if { [ show_config ] } { + show_message "$message" + } + } + } + if { [ show_config ] } { + show_message "" + } + close $fileid + } res ] != 0 } { + catch { close $fileid } + if { [ show_config ] } { + show_message "" + } + log_message "read_config: $res in variable \"$parameter\"" + error "read_config: $res in variable \"$parameter\"" + } + + # fixup suffixes, this is a hack, should be put elsewhere + if { [ info exists env(CFG_IPOIB_SUFFX) ] + && [ string equal "$env(CFG_IPOIB_SUFFIX)" "NONE" ] } { + set env(CFG_IPOIB_SUFFIX) "" + } + if { [ info exists env(CFG_IPOIB_PREFIX) ] + && [ string equal "$env(CFG_IPOIB_PREFIX)" "NONE" ] } { + set env(CFG_IPOIB_PREFIX) "" + } + if { [ info exists env(CFG_INIC_SUFFX) ] + && [ string equal "$env(CFG_INIC_SUFFIX)" "NONE" ] } { + set env(CFG_INIC_SUFFIX) "" + } +} + +proc get_config { var } { +## +## get_config +## ------------- +## support function for use by front.sh to get config file values +## out to a calling bash shell + + #global env + + #puts "$env($var)" + puts [test_get_env "$var"] +} + +proc sum_list { list } { +## +## sum_list +## ------------- +## compute the sum of a list of numbers +## +## Usage: +## sum_list list +## Arguments: +## list - a list of numbers +## Returns: +## sum +## Additional Information: +## non-numeric entries in the list are quietly ignored + + set sum 0 + foreach entry $list { + if { [ string is double $entry ] } { + incr sum $entry + } + } + return $sum +} + +proc tools_get_platform {} { + global tcl_platform + return $tcl_platform(machine) +} + +# IPtoHex assumes IP has already been validated +proc IPtoHex { IP } { + binary scan [binary format c4 [split $IP .]] H8 Hex + return $Hex +} + +proc hexToIP { Hex } { + binary scan [binary format H8 $Hex] c4 IPtmp + foreach num $IPtmp { + # binary scan "c" format gives signed int - the following + # [expr]-ology converts to unsigned (from [binary] manpage) + lappend IP [expr ($num + 0x100) % 0x100] + } + set IP [join $IP .] + return $IP +} + +# IP and netmask in Hex, returns hex +proc broadcastAddress { hexIP hexNetmask } { + set tmpBrdAddr [expr 0x$hexIP | ( 0x$hexNetmask ^ 0xffffffff )] + binary scan [binary format I $tmpBrdAddr] H8 broadcastAddress + return $broadcastAddress +} + +# IP and netmask in Hex, returns hex +proc networkAddress { hexIP hexNetmask } { + set compNetmask [expr 0x$hexNetmask ^ 0xffffffff] + set tmpNetAddr [expr ( 0x$hexIP | $compNetmask ) ^ $compNetmask] + binary scan [binary format I $tmpNetAddr] H8 networkAddress + return $networkAddress +} + +proc IPisValid { IP } { + # must contain only dots and digits + # this originally read:- + #if { [regsub -all {[.0-9]} $IP {}] != "" } { + # return 0 + #} + regsub -all {[.0-9]} $IP {} tmpStr + if { $tmpStr != "" } { + return 0 + } + # however this appears to be a 8.4.1-ism which doesn't work with + # earlier versions (e.g. the 8.4a2 version that the PocketPC tcltk + # version is based on. + # + # exactly three dots + regsub -all {[0-9]} $IP {} tmpStr + if { $tmpStr != "..." } { + return 0 + } + # each numerical component is between 0 and 255 + foreach b [split $IP .] { + if { [string length $b] == 0 } { + return 0 + } + set ob $b + scan $b %d b ;# allow for leading zeros which tcl thinks are octal + if { $b < 0 | $b > 255 } { + return 0 + } + } + return 1 +} + + +proc getBroadCast { ip netmask } { +## +## getBroadCast +## ----------- +## Return the broadcast address given IP and netmask +## +## Usage: +## getBroadCast ip netmask +## Arguments: +## ip - valid IP address. can be a network address. +## netmask - the netmask for this IP. +## Returns +## netmask in the form nnn.nnn.nnn.nnn +## + if { ! [IPisValid $ip] } { + error "IP is not valid" + } + if { ! [IPisValid $netmask] } { + error "Netmask is not valid" + } + set hexIP [IPtoHex $ip] + set hexNM [IPtoHex $netmask] + set hexBC [broadcastAddress $hexIP $hexNM] + set broadcastAddress [hexToIP $hexBC] + return $broadcastAddress +} + +proc getNetWork { ip netmask } { +## +## getNetWork +## ----------- +## Return the netowkr address given IP and netmask +## +## Usage: +## getNwtWork ip netmask +## Arguments: +## ip - valid IP address. can be a network address. +## netmask - the netmask for this IP. +## Returns +## network in the form nnn.nnn.nnn.nnn +## + if { ! [IPisValid $ip] } { + error "IP is not valid" + } + if { ! [IPisValid $netmask] } { + error "Netmask is not valid" + } + set hexIP [IPtoHex $ip] + set hexNM [IPtoHex $netmask] + set hexNW [networkAddress $hexIP $hexNM] + set networkAddress [hexToIP $hexNW] + return $networkAddress +} diff --git a/Topology/Makefile b/Topology/Makefile new file mode 100644 index 0000000..c09bc9b --- /dev/null +++ b/Topology/Makefile @@ -0,0 +1,183 @@ +# Makefile for Topology + +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# Include Make Control Settings +include $(TL_DIR)/$(PROJ_FILE_DIR)/Makesettings.project + +#=============================================================================# +# Definitions: +#-----------------------------------------------------------------------------# + +# Name of SubProjects +DS_SUBPROJECTS = +# name of executable or downloadable image +EXECUTABLE = # Topology$(EXE_SUFFIX) +# list of sub directories to build +DIRS = +# C files (.c) +CFILES = \ + getdate.c \ + fabricdata.c \ + focus.c \ + point.c \ + search.c \ + snapshot.c \ + topology.c \ + util.c \ + mad_info.c +ifneq "$(BUILD_TARGET_OS)" "VXWORKS" +CFILES += \ + mad.c \ + route.c \ + sweep.c +endif + +# C++ files (.cpp) +CCFILES = \ + # Add more cpp files here +# lex files (.lex) +LFILES = \ + # Add more lex files here +# archive library files (basename, $ARFILES will add MOD_LIB_DIR/prefix and suffix) +LIBFILES = +# Windows Resource Files (.rc) +RSCFILES = +# Windows IDL File (.idl) +IDLFILE = +# Windows Linker Module Definitions (.def) file for dll's +DEFFILE = +# targets to build during INCLUDES phase (add public includes here) +INCLUDE_TARGETS = \ + topology.h \ + # Add more h hpp files here +# Non-compiled files +MISC_FILES = +# all source files +SOURCES = $(CFILES) $(CCFILES) $(LFILES) $(RSCFILES) $(IDLFILE) +# Source files to include in DSP File +DSP_SOURCES = $(INCLUDE_TARGETS) $(SOURCES) $(MISC_FILES) \ + $(RSCFILES) $(DEFFILE) $(MAKEFILE) +# all object files +OBJECTS = $(CFILES:.c=$(OBJ_SUFFIX)) $(CCFILES:.cpp=$(OBJ_SUFFIX)) \ + $(LFILES:.lex=$(OBJ_SUFFIX)) +RSCOBJECTS = $(RSCFILES:.rc=$(RES_SUFFIX)) +# targets to build during LIBS phase +LIB_TARGETS_IMPLIB = +LIB_TARGETS_ARLIB = $(LIB_PREFIX)Topology$(ARLIB_SUFFIX) +LIB_TARGETS_EXP = $(LIB_TARGETS_IMPLIB:$(ARLIB_SUFFIX)=$(EXP_SUFFIX)) +LIB_TARGETS_MISC = +# targets to build during CMDS phase +SHLIB_VERSION = +CMD_TARGETS_SHLIB = +CMD_TARGETS_EXE = $(EXECUTABLE) +CMD_TARGETS_MISC = +CMD_TARGETS_DRIVER = +CMD_TARGETS_KEXT = +# files to remove during clean phase +CLEAN_TARGETS_MISC = +CLEAN_TARGETS = $(OBJECTS) $(RSCOBJECTS) $(IDL_TARGETS) $(CLEAN_TARGETS_MISC) +# other files to remove during clobber phase +CLOBBER_TARGETS_MISC= +# sub-directory to install to within bin +BIN_SUBDIR = +# sub-directory to install to within include +INCLUDE_SUBDIR = + +# Additional Settings +#CLOCALDEBUG = User defined C debugging compilation flags [Empty] +#CCLOCALDEBUG = User defined C++ debugging compilation flags [Empty] +#CLOCAL = User defined C flags for compiling [Empty] +#CCLOCAL = User defined C++ flags for compiling [Empty] +#BSCLOCAL = User flags for Browse File Builder [Empty] +#DEPENDLOCAL = user defined makedepend flags [Empty] +#LINTLOCAL = User defined lint flags [Empty] +#LOCAL_INCLUDE_DIRS = User include directories to search for C/C++ headers [Empty] +#LDLOCAL = User defined C flags for linking [Empty] +#IMPLIBLOCAL = User flags for Object Lirary Manager [Empty] +#MIDLLOCAL = User flags for IDL compiler [Empty] +#RSCLOCAL = User flags for resource compiler [Empty] +#LOCALDEPLIBS = User libraries to include in dependencies [Empty] +#LOCALLIBS = User libraries to use when linking [Empty] +# (in addition to LOCALDEPLIBS) +#LOCAL_LIB_DIRS = User library directories for libpaths [Empty] + +CLOCAL = $(CPIE) + +LOCALDEPLIBS = ibaccess opamgt-priv +LOCAL_INCLUDE_DIRS = $(TL_DIR)/opamgt/include \ + $(TL_DIR)/opamgt/src \ + $(TL_DIR)/IbAccess/Common/Inc \ + $(TL_DIR)/BSP/bspcommon/h + +ifeq "$(BUILD_TARGET)" "ATOM" +LOCAL_INCLUDE_DIRS += \ + $(TL_DIR)/target/include +endif + + +# Include Make Rules definitions and rules +include $(TL_DIR)/$(PROJ_FILE_DIR)/Makerules.project + +#=============================================================================# +# Overrides: +#-----------------------------------------------------------------------------# +#CCOPT = # C++ optimization flags, default lets build config decide +#COPT = # C optimization flags, default lets build config decide +#SUBSYSTEM = Subsystem to build for (none, console or windows) [none] +# (Windows Only) +#USEMFC = How Windows MFC should be used (none, static, shared, no_mfc) [none] +# (Windows Only) +#=============================================================================# + +#=============================================================================# +# Rules: +#-----------------------------------------------------------------------------# +# process Sub-directories +include $(TL_DIR)/Makerules/Maketargets.toplevel + +# build cmds and libs +include $(TL_DIR)/Makerules/Maketargets.build + +# install for includes, libs and cmds phases +include $(TL_DIR)/Makerules/Maketargets.install + +# install for stage phase +#include $(TL_DIR)/Makerules/Maketargets.stage +STAGE:: + +# Unit test execution +#include $(TL_DIR)/Makerules/Maketargets.runtest + +#=============================================================================# + +#=============================================================================# +# DO NOT DELETE THIS LINE -- make depend depends on it. +#=============================================================================# diff --git a/Topology/README b/Topology/README new file mode 100644 index 0000000..d43ba47 --- /dev/null +++ b/Topology/README @@ -0,0 +1 @@ +Library to do topology discovery from SA or a snapshot input file diff --git a/Topology/fabricdata.c b/Topology/fabricdata.c new file mode 100644 index 0000000..c607cb0 --- /dev/null +++ b/Topology/fabricdata.c @@ -0,0 +1,3965 @@ +/* BEGIN_ICS_COPYRIGHT7 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT7 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +#include "topology.h" +#include "topology_internal.h" +#include +#include + + +#define VTIMER_1S 1000000ull +#define VTIMER_1_MILLISEC 1000ull +#define VTIMER_10_MILLISEC 10000ull +#define VTIMER_100_MILLISEC 100000ull +#define VTIMER_200_MILLISEC 200000ull +#define VTIMER_500_MILLISEC 500000ull +#define RESP_WAIT_TIME 1000 + +#define CL_MAX_THREADS 4 + +typedef struct clListSearchData_s { + cl_map_item_t AllListEntry; // key is numeric id +} clListSearchData_t; + +#ifndef __VXWORKS__ +typedef struct clThreadContext_s { + FabricData_t *fabricp; + clGraphData_t *graphp; + uint32 srcHcaListLength; + LIST_ITEM *srcHcaList; + uint32 threadId; + int verbose; + int quiet; + uint32 numVertices; + uint8 threadExit; + uint64_t sTime, eTime; + FSTATUS threadStatus; + ValidateCLTimeGetCallback_t timeGetCallback; + uint32 usedSLs; +} clThreadContext_t; + +pthread_mutex_t g_cl_lock; + +static uint32 present_routes = 0, missing_routes = 0; +static uint32 hops_histogram_entries = 0, hops_histogram_length = 0; +static uint32 *hops_histogram = NULL; +static cl_qmap_t hopsHistogramLstMap; +static cl_qmap_t *routesLstMap; + +#endif + +PortData *GetMapEntry(FabricData_t *fabricp, STL_LID lid) +{ + if (lid > TOPLM_LID_MAX) return NULL; + if (!fabricp->u.LidMap.LidBlocks[TOPLM_BLOCK_NUM(lid)]) return NULL; + return fabricp->u.LidMap.LidBlocks[TOPLM_BLOCK_NUM(lid)][TOPLM_ENTRY_NUM(lid)]; +} + +FSTATUS SetMapEntry(FabricData_t *fabricp, STL_LID lid, PortData *pd) +{ + if (lid > TOPLM_LID_MAX) return FERROR; + if (!fabricp->u.LidMap.LidBlocks[TOPLM_BLOCK_NUM(lid)]) { + if (!pd) return FSUCCESS; + + fabricp->u.LidMap.LidBlocks[TOPLM_BLOCK_NUM(lid)] = + (PortData **)MemoryAllocate2AndClear(sizeof(PortData *)*(TOPLM_ENTRIES), IBA_MEM_FLAG_PREMPTABLE, MYTAG); + if (!fabricp->u.LidMap.LidBlocks[TOPLM_BLOCK_NUM(lid)]) { + // Failed to allocate + return FERROR; + } + } + fabricp->u.LidMap.LidBlocks[TOPLM_BLOCK_NUM(lid)][TOPLM_ENTRY_NUM(lid)] = pd; + return FSUCCESS; +} + +void FreeLidMap(FabricData_t *fabricp) +{ + int i; + for (i = 0; i < TOPLM_BLOCKS; i++) { + if (fabricp->u.LidMap.LidBlocks[i]) { + MemoryDeallocate(fabricp->u.LidMap.LidBlocks[i]); + fabricp->u.LidMap.LidBlocks[i] = NULL; + } + } +} + +#if !defined(VXWORKS) || defined(BUILD_DMC) +static int CompareIOC(IN const uint64 key1, IN const uint64 key2) +{ + IocData *iocCompare = (IocData *)(key1); + IocData *iocKey = (IocData *)(key2); + if(iocKey->IocProfile.IocGUID == iocCompare->IocProfile.IocGUID) { + if(iocKey->ioup->nodep->NodeInfo.NodeGUID == iocCompare->ioup->nodep->NodeInfo.NodeGUID) + return 0; + else if(iocKey->ioup->nodep->NodeInfo.NodeGUID < iocCompare->ioup->nodep->NodeInfo.NodeGUID) + return 1; + else + return -1; + } + else if(iocKey->IocProfile.IocGUID < iocCompare->IocProfile.IocGUID) + return 1; + else + return -1; +} +#endif + +// only FF_LIDARRAY,FF_PMADIRECT,FF_SMADIRECT,FF_DOWNPORTINFO,FF_CABLELOWPAGE +// flags are used, others ignored +FSTATUS InitFabricData(FabricData_t *fabricp, FabricFlags_t flags) +{ + MemoryClear(fabricp, sizeof(*fabricp)); + cl_qmap_init(&fabricp->AllNodes, NULL); + if (!(flags & FF_LIDARRAY)) { + cl_qmap_init(&fabricp->u.AllLids, NULL); + } + fabricp->ms_timeout = RESP_WAIT_TIME; + fabricp->flags = flags & (FF_LIDARRAY|FF_PMADIRECT|FF_SMADIRECT|FF_DOWNPORTINFO|FF_CABLELOWPAGE); + cl_qmap_init(&fabricp->AllSystems, NULL); + cl_qmap_init(&fabricp->ExpectedNodeGuidMap, NULL); + QListInitState(&fabricp->AllPorts); + if (! QListInit(&fabricp->AllPorts)) { + fprintf(stderr, "%s: Unable to initialize List\n", g_Top_cmdname); + goto fail; + } + QListInitState(&fabricp->ExpectedLinks); + if (! QListInit(&fabricp->ExpectedLinks)) { + fprintf(stderr, "%s: Unable to initialize List\n", g_Top_cmdname); + goto fail; + } + QListInitState(&fabricp->AllFIs); + if (! QListInit(&fabricp->AllFIs)) { + fprintf(stderr, "%s: Unable to initialize List\n", g_Top_cmdname); + goto fail; + } + QListInitState(&fabricp->AllSWs); + if (! QListInit(&fabricp->AllSWs)) { + fprintf(stderr, "%s: Unable to initialize List\n", g_Top_cmdname); + goto fail; + } + QListInitState(&fabricp->AllVFs); + if (! QListInit(&fabricp->AllVFs)) { + fprintf(stderr, "%s: Unable to initialize List\n", g_Top_cmdname); + goto fail; + } +#if !defined(VXWORKS) || defined(BUILD_DMC) + QListInitState(&fabricp->AllIOUs); + if (! QListInit(&fabricp->AllIOUs)) { + fprintf(stderr, "%s: Unable to initialize List\n", g_Top_cmdname); + goto fail; + } +#endif + QListInitState(&fabricp->ExpectedFIs); + if (! QListInit(&fabricp->ExpectedFIs)) { + fprintf(stderr, "%s: Unable to initialize List\n", g_Top_cmdname); + goto fail; + } + QListInitState(&fabricp->ExpectedSWs); + if (! QListInit(&fabricp->ExpectedSWs)) { + fprintf(stderr, "%s: Unable to initialize List\n", g_Top_cmdname); + goto fail; + } + QListInitState(&fabricp->ExpectedSMs); + if (! QListInit(&fabricp->ExpectedSMs)) { + fprintf(stderr, "%s: Unable to initialize List\n", g_Top_cmdname); + goto fail; + } +#if !defined(VXWORKS) || defined(BUILD_DMC) + cl_qmap_init(&fabricp->AllIOCs, CompareIOC); +#endif + cl_qmap_init(&fabricp->AllSMs, NULL); + + // MC routes related structures + QListInitState(&fabricp->AllMcGroups); + if (!QListInit(&fabricp->AllMcGroups)) { + fprintf(stderr, "%s: Unable to initialize List of mcast Members\n", g_Top_cmdname); + goto fail; + } + + // credit-loop related lists + cl_qmap_init(&fabricp->map_guid_to_ib_device, NULL); + QListInitState(&fabricp->FIs); + if (!QListInit(&fabricp->FIs)) { + fprintf(stderr, "%s: Unable to initialize List\n", g_Top_cmdname); + goto fail; + } + QListInitState(&fabricp->Switches); + if (!QListInit(&fabricp->Switches)) { + fprintf(stderr, "%s: Unable to initialize List\n", g_Top_cmdname); + goto fail; + } + cl_qmap_init(&fabricp->Graph.Arcs, NULL); + cl_qmap_init(&fabricp->Graph.map_arc_key_to_arc, NULL); + + return FSUCCESS; + +fail: + if (flags & FF_LIDARRAY) { + FreeLidMap(fabricp); + } + return FERROR; + +} + +// create SystemData as needed +// add this Node to the appropriate System +// This should only be invoked once per node (eg. not per NodeRecord) +FSTATUS AddSystemNode(FabricData_t *fabricp, NodeData *nodep) +{ + SystemData* systemp; + cl_map_item_t *mi; + FSTATUS status; + uint64 key; + + systemp = (SystemData *)MemoryAllocate2AndClear(sizeof(SystemData), IBA_MEM_FLAG_PREMPTABLE, MYTAG); + if (! systemp) { + fprintf(stderr, "%s: Unable to allocate memory\n", g_Top_cmdname); + goto fail; + } + + cl_qmap_init(&systemp->Nodes, NULL); + systemp->SystemImageGUID = nodep->NodeInfo.SystemImageGUID; + key = systemp->SystemImageGUID; + if (! key) + key = nodep->NodeInfo.NodeGUID; + + // There can be more than 1 node per system, only create 1 SystemData + mi = cl_qmap_insert(&fabricp->AllSystems, key, &systemp->AllSystemsEntry); + if (mi != &systemp->AllSystemsEntry) + { + MemoryDeallocate(systemp); + systemp = PARENT_STRUCT(mi, SystemData, AllSystemsEntry); + } + + nodep->systemp = systemp; + if (cl_qmap_insert(&systemp->Nodes, nodep->NodeInfo.NodeGUID, &nodep->SystemNodesEntry) != &nodep->SystemNodesEntry) + { + fprintf(stderr, "%s: Duplicate NodeGuids found in nodeRecords: 0x%"PRIx64"\n", + g_Top_cmdname, nodep->NodeInfo.NodeGUID); + goto fail; + } + status = FSUCCESS; +done: + return status; + +fail: + status = FERROR; + goto done; +} + +/* build the fabricp->AllPorts, ALLFIs, and AllSWs lists such that + * AllPorts is sorted by NodeGUID, PortNum + * AllFIs, ALLSWs, AllIOUs is sorted by NodeGUID + */ +void BuildFabricDataLists(FabricData_t *fabricp) +{ + cl_map_item_t *p; + + // this list may already be filled when parsing Port definitions + boolean AllPortsIsEmpty = QListIsEmpty(&fabricp->AllPorts); + + for (p=cl_qmap_head(&fabricp->AllNodes); p != cl_qmap_end(&fabricp->AllNodes); p = cl_qmap_next(p)) { + NodeData *nodep = PARENT_STRUCT(p, NodeData, AllNodesEntry); + cl_map_item_t *q; + + switch (nodep->NodeInfo.NodeType) { + case STL_NODE_FI: + QListInsertTail(&fabricp->AllFIs, &nodep->AllTypesEntry); + break; + case STL_NODE_SW: + QListInsertTail(&fabricp->AllSWs, &nodep->AllTypesEntry); + break; + default: + fprintf(stderr, "%s: Ignoring Unknown node type: 0x%x\n", + g_Top_cmdname, nodep->NodeInfo.NodeType); + break; + } +#if !defined(VXWORKS) || defined(BUILD_DMC) + if (nodep->ioup) { + QListInsertTail(&fabricp->AllIOUs, &nodep->ioup->AllIOUsEntry); + } +#endif + + if (AllPortsIsEmpty) { + for (q=cl_qmap_head(&nodep->Ports); q != cl_qmap_end(&nodep->Ports); q = cl_qmap_next(q)) { + PortData *portp = PARENT_STRUCT(q, PortData, NodePortsEntry); + QListInsertTail(&fabricp->AllPorts, &portp->AllPortsEntry); + } + } + } +} + +PortSelector* GetPortSelector(PortData *portp) +{ + ExpectedLink *elinkp = portp->elinkp; + if (elinkp) { + if (elinkp->portp1 == portp) + return elinkp->portselp1; + if (elinkp->portp2 == portp) + return elinkp->portselp2; + } + return NULL; +} + +// Determine if portp and its neighbor are an internal link within a single +// system. Note that some 3rd party products report SystemImageGuid of 0 in +// which case we can only consider links between the same node as internal links +boolean isInternalLink(PortData *portp) +{ + PortData *neighbor = portp->neighbor; + + return (neighbor + && portp->nodep->NodeInfo.SystemImageGUID + == neighbor->nodep->NodeInfo.SystemImageGUID + && (portp->nodep->NodeInfo.SystemImageGUID + || portp->nodep->NodeInfo.NodeGUID + == neighbor->nodep->NodeInfo.NodeGUID)); +} + +// Determine if portp and its neighbor are an Inter-switch Link +boolean isISLink(PortData *portp) +{ + PortData *neighbor = portp->neighbor; + + return (neighbor + && portp->nodep->NodeInfo.NodeType == STL_NODE_SW + && neighbor->nodep->NodeInfo.NodeType == STL_NODE_SW); +} + +// Determine if portp or its neighbor is an FI +boolean isFILink(PortData *portp) +{ + PortData *neighbor = portp->neighbor; + + return (neighbor + && (portp->nodep->NodeInfo.NodeType == STL_NODE_FI + || neighbor->nodep->NodeInfo.NodeType == STL_NODE_FI)); +} + +// The routines below are primarily for use when classifying ExpectedLinks +// which did not resolve properly. So we want them to be a little loose +// and select a link which is expected to be of the given type based on input +// or where the port resolved for either side is connected to a real link of +// the given type. + +// Due to this more inclusive definition, oriented toward verification, +// isExternal is not the same as ! isInternal +// Given this definition both isExternal and isInternal could be true for +// the same resolved or vaguely defined link, such as when the elinkp +// has not specified if its internal or external (default is ! internal) +// and the elink is resolved to two disconnected ports where one is an internal +// link and the other is an external link. +// Note: Currently there is no use case for an isInternalExpectedLink function +// and given the defaulting behavior of elinkp->internal such a function would +// not be implementable under this inclusive definition. +// +// Similarly isISExpectedLink is not the same as ! isFIExpectedLink +// isIS will include a link where expected link or either resolved real link +// have at least 1 switch to switch link, even if other expected or real links +// are FI links. Similarly isFIExpectedLink will match any link where an FI is +// expected on either side or is found on either side of a resolved real link. +// As such the case of an expected link which is SW-SW which matches two +// unrelated ports where one port is part of a FI-SW link and the other is +// part of a SW-SW link, will return true for both functions. +// Note portselp*->NodeType is optional (default NONE) and can resolve a port +// without matching NodeType. So it is even possible for an expected link +// of SW-SW to resolve to a FI-SW link (verify reports will report the +// incorrect node types as part of fully verifying the link) + +// Determine if elinkp is an external link within a single system. +boolean isExternalExpectedLink(ExpectedLink *elinkp) +{ + return ( + // elinkp was specified as external (or Internal not specified) + (! elinkp->internal) + // either real port resolved to the elinkp is an external link + || (elinkp->portp1 && ! isInternalLink(elinkp->portp1)) + || (elinkp->portp2 && ! isInternalLink(elinkp->portp2)) + ); +} + +// Determine if elinkp is an inter-switch link +boolean isISExpectedLink(ExpectedLink *elinkp) +{ + return ( + // elinkp was expicitly specified as an ISL + ((elinkp->portselp1 && elinkp->portselp1->NodeType == STL_NODE_SW) + && (elinkp->portselp2 && elinkp->portselp2->NodeType == STL_NODE_SW)) + // either real port resolved to the elinkp is an ISL link + || (elinkp->portp1 && isISLink(elinkp->portp1)) + || (elinkp->portp2 && isISLink(elinkp->portp2)) + ); +} + +// Determine if elinkp is an FI link +boolean isFIExpectedLink(ExpectedLink *elinkp) +{ + return ( + // either side of elinkp was specified as an FI + (elinkp->portselp1 && elinkp->portselp1->NodeType == STL_NODE_FI) + || (elinkp->portselp2 && elinkp->portselp2->NodeType == STL_NODE_FI) + // either real port resolved to a link including an FI + || (elinkp->portp1 && isFILink(elinkp->portp1)) + || (elinkp->portp2 && isFILink(elinkp->portp2)) + ); +} + +// Lookup PKey +// ignores the Full/Limited bit, only checks low 15 bits for a match +// returns index of pkey in overall table or -1 if not found +// if the Partition Table for the port is not available, returns -1 +int FindPKey(PortData *portp, uint16 pkey) +{ + uint16 ix, ix_capacity; + STL_PKEY_ELEMENT *pPartitionTable = portp->pPartitionTable; + + if (! pPartitionTable) + return -1; + ix_capacity = PortPartitionTableSize(portp); + for (ix = 0; ix < ix_capacity; ix++) + { + if ((pPartitionTable[ix].AsReg16 & 0x7FFF) == (pkey & 0x7FFF)) + return ix; + } + return -1; +} + +// Determine if the given port is a member of the given vFabric +// We don't really have all the right data here, especially if the FM has +// combined multiple vFabrics into the same SL and PKey +// but for most cases, we can safely conclude that if the port has the SL and +// PKey configured it is a member of the vFabric. +// This function will return FALSE if QoS data or SL2SCMap is not available +// or if the port is not Armed/Active. +// Given the current FM implementation (and the dependency on SL2SCMap), this +// routine will return FALSE if invoked for non-endpoints +boolean isVFMember(PortData *portp, VFData_t *pVFData) +{ + STL_VFINFO_RECORD *pR = &pVFData->record; + uint8 sl = pR->s1.slBase; + uint8 slResp = (pR->slResponseSpecified? pR->slResponse: sl); + uint8 slMcast = (pR->slMulticastSpecified? pR->slMulticast: sl); + + // VF only valid if port initialized + if (! IsPortInitialized(portp->PortInfo.PortStates)) + return FALSE; + // there is no saquery to find out if a port is a member of a vfabric + // so a port is assumed to be a member of a vfabric if: + // for the base SL of the vfabric, that port has an SC assigned (SC!=15) + // and the port has the VF's pkey + + if (! portp->pQOS || ! portp->pQOS->SL2SCMap) + return FALSE; + + if (portp->pQOS->SL2SCMap->SLSCMap[sl].SC == 15 && + portp->pQOS->SL2SCMap->SLSCMap[slResp].SC == 15 && + portp->pQOS->SL2SCMap->SLSCMap[slMcast].SC == 15) + return FALSE; + + return (-1 != FindPKey(portp, pR->pKey)); +} + +// count the number of armed/active links in the node +uint32 CountInitializedPorts(FabricData_t *fabricp, NodeData *nodep) +{ + cl_map_item_t *p; + uint32 count = 0; + for (p=cl_qmap_head(&nodep->Ports); p != cl_qmap_end(&nodep->Ports); p = cl_qmap_next(p)) + { + PortData *portp = PARENT_STRUCT(p, PortData, NodePortsEntry); + if (IsPortInitialized(portp->PortInfo.PortStates)) + count++; + } + return count; +} + +void PortDataFreeQOSData(FabricData_t *fabricp, PortData *portp) +{ + if (portp->pQOS) { + QOSData *pQOS = portp->pQOS; + + LIST_ITEM *p; + int i; + for (i=0; i< SC2SCMAPLIST_MAX; i++) { + while (!QListIsEmpty(&pQOS->SC2SCMapList[i])) { + p = QListTail(&pQOS->SC2SCMapList[i]); + PortMaskSC2SCMap *pSC2SC = (PortMaskSC2SCMap *)QListObj(p); + QListRemoveTail(&pQOS->SC2SCMapList[i]); + MemoryDeallocate(pSC2SC->SC2SCMap); + pSC2SC->SC2SCMap = NULL; + MemoryDeallocate(pSC2SC); + } + } + + if (pQOS->SL2SCMap) + MemoryDeallocate(pQOS->SL2SCMap); + if (pQOS->SC2SLMap) + MemoryDeallocate(pQOS->SC2SLMap); + + MemoryDeallocate(pQOS); + } + portp->pQOS = NULL; +} + +void PortDataFreeBufCtrlTable(FabricData_t *fabricp, PortData *portp) +{ + if (portp->pBufCtrlTable) { + MemoryDeallocate(portp->pBufCtrlTable); + } + portp->pBufCtrlTable = NULL; +} + + +void PortDataFreePartitionTable(FabricData_t *fabricp, PortData *portp) +{ + if (portp->pPartitionTable) { + MemoryDeallocate(portp->pPartitionTable); + } + portp->pPartitionTable = NULL; +} + + +void PortDataFreeCableInfoData(FabricData_t *fabricp, PortData *portp) +{ + if (portp->pCableInfoData) { + MemoryDeallocate(portp->pCableInfoData); + } + portp->pCableInfoData = NULL; +} + +void PortDataFreeCongestionControlTableEntries(FabricData_t *fabricp, PortData *portp) +{ + if (portp->pCongestionControlTableEntries) { + MemoryDeallocate(portp->pCongestionControlTableEntries); + } + portp->pCongestionControlTableEntries = NULL; +} + +void AllLidsRemove(FabricData_t *fabricp, PortData *portp) +{ + if (! portp->PortGUID) + return; // quietly ignore + switch (portp->PortInfo.PortStates.s.PortState) { + default: + case IB_PORT_DOWN: + case IB_PORT_INIT: + // may be in AllLids + if (FindLid(fabricp, portp->EndPortLID) != portp) + return; + break; + case IB_PORT_ARMED: + case IB_PORT_ACTIVE: + // should be in AllLids + break; + } + if (fabricp->flags & FF_LIDARRAY) { + STL_LID first_lid = portp->EndPortLID; + STL_LID last_lid = portp->EndPortLID | + ((1<PortInfo.s1.LMC)-1); + while (first_lid <= last_lid) { + SetMapEntry(fabricp, first_lid++, NULL); + } + } else { + cl_qmap_remove_item(&fabricp->u.AllLids, &portp->AllLidsEntry); + } + fabricp->lidCount -= (1<PortInfo.s1.LMC); +} + +void PartialLidsRemove(FabricData_t *fabricp, PortData *portp, uint32 count) +{ + STL_LID first_lid = portp->EndPortLID; + STL_LID last_lid = portp->EndPortLID + count; + while (first_lid < last_lid) { + SetMapEntry(fabricp, first_lid++, NULL); + fabricp->lidCount--; + } +} + +// add the LID for a non-down port to the LID lists +// does nothing for ports in DOWN or INIT state +FSTATUS AllLidsAdd(FabricData_t *fabricp, PortData *portp, boolean force) +{ + cl_map_item_t *mi; + + if (! portp->PortGUID) + return FSUCCESS; // quietly ignore + + // we are less strict about switch port 0. We have seen odd state's + // reported and unfortunately SM just passes them along. + // Since Port 0 is in SM DB it must have a trustable LID (note that + // for simulator, PortDataStateChanged will only call this for Armed/Active) + if (IB_PORT_ACTIVE != portp->PortInfo.PortStates.s.PortState + && IB_PORT_ARMED != portp->PortInfo.PortStates.s.PortState + && ! (portp->nodep->NodeInfo.NodeType == STL_NODE_SW + && 0 == portp->PortNum + && IB_PORT_NOP == portp->PortInfo.PortStates.s.PortState)) + return FSUCCESS; // quietly ignore + if (portp->EndPortLID > TOPLM_LID_MAX) + return FERROR; + if (fabricp->flags & FF_LIDARRAY) { + STL_LID perm_first_lid = portp->EndPortLID; + STL_LID first_lid = portp->EndPortLID; + STL_LID last_lid = portp->EndPortLID | + ((1<PortInfo.s1.LMC)-1); + FSTATUS status = FSUCCESS; + + for(;first_lid <= last_lid;first_lid++) { + PortData *testportp = GetMapEntry(fabricp, first_lid); + if(testportp != portp) { + if(testportp != NULL) { + status = FDUPLICATE; + if (! force) { + PartialLidsRemove(fabricp, portp, first_lid - perm_first_lid); + return status; + } else { + AllLidsRemove(fabricp, testportp); + } + } + fabricp->lidCount++; + SetMapEntry(fabricp, first_lid, portp); + } + } + return status; + } else { + // TBD does not verify potential overlap of lid+(1<u.AllLids, portp->EndPortLID, &portp->AllLidsEntry); + if (mi != &portp->AllLidsEntry) { + if (force) { + AllLidsRemove(fabricp, PARENT_STRUCT(mi, PortData, AllLidsEntry)); + mi = cl_qmap_insert(&fabricp->u.AllLids, portp->EndPortLID, &portp->AllLidsEntry); + ASSERT(mi == &portp->AllLidsEntry); + fabricp->lidCount += (1<PortInfo.s1.LMC); + } + return FDUPLICATE; + } else { + fabricp->lidCount += (1<PortInfo.s1.LMC); + return FSUCCESS; + } + } +} + +STL_SCSCMAP * QOSDataLookupSCSCMap(PortData *portp, uint8_t outport, int extended) { + LIST_ITEM *p; + PortMaskSC2SCMap *pSC2SC; + QOSData *pQOS = portp->pQOS; + + if (!pQOS) + return NULL; + if ((extended >= SC2SCMAPLIST_MAX) || (extended < 0)) + return NULL; + + for (p = QListHead(&pQOS->SC2SCMapList[extended]); p != NULL; p = QListNext(&pQOS->SC2SCMapList[extended], p)) { + pSC2SC = (PortMaskSC2SCMap *)QListObj(p); + + if (StlIsPortInPortMask(pSC2SC->outports, outport)) + return (pSC2SC->SC2SCMap); + } + return NULL; +} + +// Add a SCSC table to QOS data +// If a matching SCSC table already exists, add egress to its port mask +// Otherwise, create a new entry in the SCSCMap list for this table +void QOSDataAddSCSCMap(PortData *portp, uint8_t outport, int extended, const STL_SCSCMAP *pSCSC) { + LIST_ITEM *p; + QOSData *pQOS = portp->pQOS; + PortMaskSC2SCMap *pSC2SC2; + PortMaskSC2SCMap *pEmptySC2SC2 = NULL; + int entryFound = 0; + + if (!pQOS) + return; + if ((extended >= SC2SCMAPLIST_MAX) || (extended < 0)) + return; + + for (p = QListHead(&pQOS->SC2SCMapList[extended]); p != NULL; p = QListNext(&pQOS->SC2SCMapList[extended], p)) { + pSC2SC2 = (PortMaskSC2SCMap *)QListObj(p); + + if (!memcmp(pSC2SC2->SC2SCMap, pSCSC, sizeof(STL_SCSCMAP))) { + StlAddPortToPortMask(pSC2SC2->outports, outport); + entryFound = 1; + } else if (StlIsPortInPortMask(pSC2SC2->outports, outport)) { + // the maps don't match but the port does, remove & replace with new map + StlClearPortInPortMask(pSC2SC2->outports, outport); + if (StlNumPortsSetInPortMask(pSC2SC2->outports, portp->nodep->NodeInfo.NumPorts) ==0) { + pEmptySC2SC2 = pSC2SC2; + } + } + } + + if (entryFound) { + if(pEmptySC2SC2) { + QListRemoveItem(&pQOS->SC2SCMapList[extended], &pEmptySC2SC2->SC2SCMapListEntry); + } + return; + } + + pSC2SC2 = pEmptySC2SC2; + if (!pSC2SC2) { + // never found a matching map, create a new one + pSC2SC2 = (PortMaskSC2SCMap *)MemoryAllocate2AndClear(sizeof(PortMaskSC2SCMap), IBA_MEM_FLAG_PREMPTABLE, MYTAG); + if (!pSC2SC2) { + // memory error + fprintf(stderr, "%s: Unable to allocate memory\n", g_Top_cmdname); + return; + } + + ListItemInitState(&pSC2SC2->SC2SCMapListEntry); + QListSetObj(&pSC2SC2->SC2SCMapListEntry, pSC2SC2); + + pSC2SC2->SC2SCMap = (STL_SCSCMAP *)MemoryAllocate2AndClear(sizeof(STL_SCSCMAP), IBA_MEM_FLAG_PREMPTABLE, MYTAG); + if (!pSC2SC2->SC2SCMap) { + // memory error + fprintf(stderr, "%s: Unable to allocate memory\n", g_Top_cmdname); + return; + } + QListInsertTail(&pQOS->SC2SCMapList[extended], &pSC2SC2->SC2SCMapListEntry); + } + + memcpy(pSC2SC2->SC2SCMap, pSCSC, sizeof(STL_SCSCMAP)); + StlAddPortToPortMask(pSC2SC2->outports, outport); +} + +// Set new Port Info based on a Set(PortInfo). For use by fabric simulator +// assumes pInfo already validated and any Noop fields filled in with correct +// values. +// MODIFIED FOR STL +void PortDataStateChanged(FabricData_t *fabricp, PortData *portp) +{ + if (IB_PORT_ACTIVE == portp->PortInfo.PortStates.s.PortState + || IB_PORT_ARMED == portp->PortInfo.PortStates.s.PortState) { + if (FSUCCESS != AllLidsAdd(fabricp, portp, TRUE)) { + fprintf(stderr, "%s: Overwrote Duplicate LID found in portRecords: PortGUID 0x%016"PRIx64" LID 0x%x Port %u Node %.*s\n", + g_Top_cmdname, + portp->PortGUID, portp->EndPortLID, + portp->PortNum, STL_NODE_DESCRIPTION_ARRAY_SIZE, + (char*)portp->nodep->NodeDesc.NodeString); + } + } else { + AllLidsRemove(fabricp, portp); + } + +} + +// Set new Port Info based on a Set(PortInfo). For use by fabric simulator +// assumes pInfo already validated and any Noop fields filled in with correct +// values. +// MODIFIED FOR STL +void PortDataSetPortInfo(FabricData_t *fabricp, PortData *portp, STL_PORT_INFO *pInfo) +{ + portp->PortInfo = *pInfo; + if (portp->PortGUID) { + portp->EndPortLID = pInfo->LID; + /* Only port 0 in a switch has a GUID. It's LID is the switch's LID */ + if (portp->nodep->pSwitchInfo) { + cl_map_item_t *q; + NodeData *nodep = portp->nodep; + + nodep->pSwitchInfo->RID.LID = pInfo->LID; + /* also set EndPortLID in all of switch's PortInfoRecords */ + for (q=cl_qmap_head(&nodep->Ports); q != cl_qmap_end(&nodep->Ports); q = cl_qmap_next(q)) { + PortData *p = PARENT_STRUCT(q, PortData, NodePortsEntry); + p->EndPortLID = pInfo->LID; + } + } + } + PortDataStateChanged(fabricp, portp); +} + +// remove Port from lists and free it +// Only removes from AllLids and NodeData.Ports, caller must remove from +// any other lists if called after BuildFabricLists +void PortDataFree(FabricData_t *fabricp, PortData *portp) +{ + NodeData *nodep = portp->nodep; + + if (portp->context && g_Top_FreeCallbacks.pPortDataFreeCallback) + (*g_Top_FreeCallbacks.pPortDataFreeCallback)(fabricp, portp); + + if (portp->PortGUID) + AllLidsRemove(fabricp, portp); + cl_qmap_remove_item(&nodep->Ports, &portp->NodePortsEntry); + if (portp->pPortCounters) + MemoryDeallocate(portp->pPortCounters); + PortDataFreeQOSData(fabricp, portp); + PortDataFreeBufCtrlTable(fabricp, portp); + PortDataFreePartitionTable(fabricp, portp); + + + PortDataFreeCableInfoData(fabricp, portp); + PortDataFreeCongestionControlTableEntries(fabricp, portp); + MemoryDeallocate(portp); +} + +FSTATUS PortDataAllocateQOSData(FabricData_t *fabricp, PortData *portp) +{ + QOSData *pQOS; + int i; + + ASSERT(! portp->pQOS); // or could free if present + portp->pQOS = (QOSData *)MemoryAllocate2AndClear(sizeof(QOSData), IBA_MEM_FLAG_PREMPTABLE, MYTAG); + if (! portp->pQOS) { + fprintf(stderr, "%s: Unable to allocate memory\n", g_Top_cmdname); + goto fail; + } + pQOS = portp->pQOS; + if (portp->nodep->NodeInfo.NodeType == STL_NODE_SW && portp->PortNum) { + for (i=0; iSC2SCMapList[i]); + if (!QListInit(&pQOS->SC2SCMapList[i])) { + fprintf(stderr, "%s: Unable to initialize SC2SCMaps member list\n", g_Top_cmdname); + goto fail; + } + } + } else { + // HFI and Switch Port 0 get SL2SC and SC2SL + pQOS->SL2SCMap = (STL_SLSCMAP *)MemoryAllocate2AndClear(sizeof(STL_SLSCMAP), IBA_MEM_FLAG_PREMPTABLE, MYTAG); + if (! pQOS->SL2SCMap) { + fprintf(stderr, "%s: Unable to allocate memory\n", g_Top_cmdname); + goto fail; + } + + pQOS->SC2SLMap = (STL_SCSLMAP *)MemoryAllocate2AndClear(sizeof(STL_SCSLMAP), IBA_MEM_FLAG_PREMPTABLE, MYTAG); + if (!pQOS->SC2SLMap) { + goto fail; + } + } + + return FSUCCESS; +fail: + PortDataFreeQOSData(fabricp, portp); + return FINSUFFICIENT_MEMORY; +} + +FSTATUS PortDataAllocateAllQOSData(FabricData_t *fabricp) +{ + LIST_ITEM *p; + FSTATUS status = FSUCCESS; + + for (p=QListHead(&fabricp->AllPorts); p != NULL; p = QListNext(&fabricp->AllPorts, p)) { + PortData *portp = (PortData *)QListObj(p); + FSTATUS s; + s = PortDataAllocateQOSData(fabricp, portp); + if (FSUCCESS != s) + status = s; + } + return status; +} + +FSTATUS PortDataAllocateBufCtrlTable(FabricData_t *fabricp, PortData *portp) +{ + ASSERT(! portp->pBufCtrlTable); // or could free if present + portp->pBufCtrlTable = MemoryAllocate2AndClear(sizeof(STL_BUFFER_CONTROL_TABLE), IBA_MEM_FLAG_PREMPTABLE, MYTAG); + if (! portp->pBufCtrlTable) { + fprintf(stderr, "%s: Unable to allocate memory\n", g_Top_cmdname); + goto fail; + } + + return FSUCCESS; +fail: + //PortDataFreeBufCtrlTable(fabricp, portp); + return FINSUFFICIENT_MEMORY; +} + + +FSTATUS PortDataAllocateAllBufCtrlTable(FabricData_t *fabricp) +{ + LIST_ITEM *p; + FSTATUS status = FSUCCESS; + + for (p=QListHead(&fabricp->AllPorts); p != NULL; p = QListNext(&fabricp->AllPorts, p)) { + PortData *portp = (PortData *)QListObj(p); + FSTATUS s; + s = PortDataAllocateBufCtrlTable(fabricp, portp); + if (FSUCCESS != s) + status = s; + } + return status; +} + +uint16 PortPartitionTableSize(PortData *portp) +{ + NodeData *nodep = portp->nodep; + if (nodep->NodeInfo.NodeType == STL_NODE_SW && portp->PortNum) { + // Switch External Ports table size is defined in SwitchInfo + if (! nodep->pSwitchInfo) { + // guess the limits, we don't have SwitchInfo + // or we haven't yet read it from the snapshot while parsing + return nodep->NodeInfo.PartitionCap; + } else { + return nodep->pSwitchInfo->SwitchInfoData.PartitionEnforcementCap; + } + } else { + // Switch Port 0 and FI table size is defined by NodeInfo + return nodep->NodeInfo.PartitionCap; + } +} + +FSTATUS PortDataAllocatePartitionTable(FabricData_t *fabricp, PortData *portp) +{ + uint16 size; + + ASSERT(! portp->pPartitionTable); // or could free if present + size = PortPartitionTableSize(portp); + portp->pPartitionTable = (STL_PKEY_ELEMENT *)MemoryAllocate2AndClear(sizeof(STL_PKEY_ELEMENT)*size, IBA_MEM_FLAG_PREMPTABLE, MYTAG); + if (! portp->pPartitionTable) { + fprintf(stderr, "%s: Unable to allocate memory\n", g_Top_cmdname); + goto fail; + } + + return FSUCCESS; +fail: + //PortDataFreePartitionTable(fabricp, portp); + return FINSUFFICIENT_MEMORY; +} + +FSTATUS PortDataAllocateAllPartitionTable(FabricData_t *fabricp) +{ + LIST_ITEM *p; + FSTATUS status = FSUCCESS; + + for (p=QListHead(&fabricp->AllPorts); p != NULL; p = QListNext(&fabricp->AllPorts, p)) { + PortData *portp = (PortData *)QListObj(p); + FSTATUS s; + s = PortDataAllocatePartitionTable(fabricp, portp); + if (FSUCCESS != s) + status = s; + } + return status; +} + + +FSTATUS PortDataAllocateCableInfoData(FabricData_t *fabricp, PortData *portp) +{ + uint16 size = STL_CIB_STD_LEN; + ASSERT(! portp->pCableInfoData); // or could free if present + + //Data in Low address space of Cable info is also accesed for Cable Health Report + if (fabricp) { + if (fabricp->flags & FF_CABLELOWPAGE) + size = STL_CABLE_INFO_DATA_SIZE * 4; // 2 blocks of lower page 0 and 2 blocks of upper page 0 + } + + portp->pCableInfoData = MemoryAllocate2AndClear(size, IBA_MEM_FLAG_PREMPTABLE, MYTAG); + if (! portp->pCableInfoData) { + fprintf(stderr, "%s: Unable to allocate memory\n", g_Top_cmdname); + goto fail; + } + + return FSUCCESS; +fail: + //PortDataFreeCableInfoData(fabricp, portp); + return FINSUFFICIENT_MEMORY; +} + +FSTATUS PortDataAllocateAllCableInfo(FabricData_t *fabricp) +{ + LIST_ITEM *p; + FSTATUS status = FSUCCESS; + + for (p=QListHead(&fabricp->AllPorts); p != NULL; p = QListNext(&fabricp->AllPorts, p)) { + PortData *portp = (PortData *)QListObj(p); + FSTATUS s; + // skip switch port 0 + if (! portp->PortNum) + continue; + s = PortDataAllocateCableInfoData(fabricp, portp); + if (FSUCCESS != s) + status = s; + } + return status; +} + +FSTATUS PortDataAllocateCongestionControlTableEntries(FabricData_t *fabricp, PortData *portp) +{ + ASSERT(! portp->pCongestionControlTableEntries); // or could free if present + if (! portp->nodep->CongestionInfo.ControlTableCap) + return FSUCCESS; + portp->pCongestionControlTableEntries = MemoryAllocate2AndClear( + sizeof(STL_HFI_CONGESTION_CONTROL_TABLE_ENTRY) + * STL_NUM_CONGESTION_CONTROL_ELEMENTS_BLOCK_ENTRIES + * portp->nodep->CongestionInfo.ControlTableCap, + IBA_MEM_FLAG_PREMPTABLE, MYTAG); + if (! portp->pCongestionControlTableEntries) { + fprintf(stderr, "%s: Unable to allocate memory\n", g_Top_cmdname); + goto fail; + } + + return FSUCCESS; +fail: + //PortDataFreeCongestionControlTableEntries(fabricp, portp); + return FINSUFFICIENT_MEMORY; +} + +FSTATUS PortDataAllocateAllCongestionControlTableEntries(FabricData_t *fabricp) +{ + LIST_ITEM *p; + FSTATUS status = FSUCCESS; + + for (p=QListHead(&fabricp->AllPorts); p != NULL; p = QListNext(&fabricp->AllPorts, p)) { + PortData *portp = (PortData *)QListObj(p); + FSTATUS s; + // only applicable to HFIs and enhanced switch port 0 + if (portp->nodep->NodeInfo.NodeType == STL_NODE_SW + && portp->PortNum) + continue; + if (! portp->nodep->CongestionInfo.ControlTableCap) + continue; + s = PortDataAllocateCongestionControlTableEntries(fabricp, portp); + if (FSUCCESS != s) + status = s; + } + return status; +} + +// guid is the PortGUID as found in corresponding NodeRecord +// we adjust as needed to account for Switch Ports (only switch port 0 has guid) +PortData* NodeDataAddPort(FabricData_t *fabricp, NodeData *nodep, EUI64 guid, STL_PORTINFO_RECORD *pPortInfo) +{ + PortData *portp; + + portp = (PortData*)MemoryAllocate2AndClear(sizeof(PortData), IBA_MEM_FLAG_PREMPTABLE, MYTAG); + if (! portp) { + fprintf(stderr, "%s: Unable to allocate memory\n", g_Top_cmdname); + goto fail; + } + + ListItemInitState(&portp->AllPortsEntry); + QListSetObj(&portp->AllPortsEntry, portp); + portp->PortInfo = pPortInfo->PortInfo; + portp->EndPortLID = pPortInfo->RID.EndPortLID; + memcpy(portp->LinkDownReasons, pPortInfo->LinkDownReasons, STL_NUM_LINKDOWN_REASONS * sizeof(STL_LINKDOWN_REASON)); + + if (nodep->NodeInfo.NodeType == STL_NODE_SW) { + // a switch only gets 1 port Guid, we save it for switch + // port 0 (the "virtual management port") + portp->PortNum = pPortInfo->RID.PortNum; + portp->PortGUID = portp->PortNum?0:guid; + } else { + portp->PortNum = pPortInfo->PortInfo.LocalPortNum; + portp->PortGUID = guid; + } + portp->rate = StlLinkSpeedWidthToStaticRate( + (portp->PortInfo.LinkSpeed.Active), + (portp->PortInfo.LinkWidth.Active)); + portp->nodep = nodep; + //DisplayPortInfoRecord(&pPortInfoRecords[i], 0); + //printf("process PortNumber: %u\n", portp->PortNum); + + if (cl_qmap_insert(&nodep->Ports, portp->PortNum, &portp->NodePortsEntry) != &portp->NodePortsEntry) + { + fprintf(stderr, "%s: Duplicate PortNums found in portRecords: LID 0x%x Port %u Node: %.*s\n", + g_Top_cmdname, + portp->EndPortLID, + portp->PortNum, STL_NODE_DESCRIPTION_ARRAY_SIZE, + (char*)nodep->NodeDesc.NodeString); + MemoryDeallocate(portp); + goto fail; + } + if (FSUCCESS != AllLidsAdd(fabricp, portp, FALSE)) + { + fprintf(stderr, "%s: Duplicate LIDs found in portRecords: PortGUID 0x%016"PRIx64" LID 0x%x Port %u Node %.*s\n", + g_Top_cmdname, + portp->PortGUID, portp->EndPortLID, + portp->PortNum, STL_NODE_DESCRIPTION_ARRAY_SIZE, + (char*)nodep->NodeDesc.NodeString); + cl_qmap_remove_item(&nodep->Ports, &portp->NodePortsEntry); + MemoryDeallocate(portp); + goto fail; + } + //DisplayPortInfoRecord(pPortInfo, 0); + + return portp; + +fail: + return NULL; +} + +FSTATUS NodeDataSetSwitchInfo(NodeData *nodep, STL_SWITCHINFO_RECORD *pSwitchInfo) +{ + ASSERT(! nodep->pSwitchInfo); + nodep->pSwitchInfo = (STL_SWITCHINFO_RECORD*)MemoryAllocate2AndClear(sizeof(STL_SWITCHINFO_RECORD), IBA_MEM_FLAG_PREMPTABLE, MYTAG); + if (! nodep->pSwitchInfo) { + fprintf(stderr, "%s: Unable to allocate memory\n", g_Top_cmdname); + return FERROR; + } + // leave the extra vendor specific fields zeroed + nodep->pSwitchInfo->RID.LID = pSwitchInfo->RID.LID; + nodep->pSwitchInfo->SwitchInfoData = pSwitchInfo->SwitchInfoData; + return FSUCCESS; +} + +// TBD - routines to add/set IOC and IOU information + +NodeData *FabricDataAddNode(FabricData_t *fabricp, STL_NODE_RECORD *pNodeRecord, boolean *new_nodep) +{ + NodeData *nodep = (NodeData*)MemoryAllocate2AndClear(sizeof(NodeData), IBA_MEM_FLAG_PREMPTABLE, MYTAG); + cl_map_item_t *mi; + boolean new_node = TRUE; + + if (! nodep) { + fprintf(stderr, "%s: Unable to allocate memory\n", g_Top_cmdname); + goto fail; + } + //printf("process NodeRecord LID: 0x%x\n", pNodeRecords->RID.s.LID); + //DisplayNodeRecord(pNodeRecord, 0); + + cl_qmap_init(&nodep->Ports, NULL); + + nodep->NodeInfo = pNodeRecord->NodeInfo; + + nodep->NodeDesc = pNodeRecord->NodeDesc; + + // zero out port specific fields, the PortData will handle these + nodep->NodeInfo.PortGUID=0; + nodep->NodeInfo.u1.s.LocalPortNum=0; + ListItemInitState(&nodep->AllTypesEntry); + QListSetObj(&nodep->AllTypesEntry, nodep); + + // when sweeping we get 1 NodeRecord per port on a node, so only save + // 1 NodeData structure per node and discard the duplicates + mi = cl_qmap_insert(&fabricp->AllNodes, nodep->NodeInfo.NodeGUID, &nodep->AllNodesEntry); + if (mi != &nodep->AllNodesEntry) + { + MemoryDeallocate(nodep); + nodep = PARENT_STRUCT(mi, NodeData, AllNodesEntry); + new_node = FALSE; + } + + if (new_node) { + if (FSUCCESS != AddSystemNode(fabricp, nodep)) { + cl_qmap_remove_item(&fabricp->AllNodes, &nodep->AllNodesEntry); + MemoryDeallocate(nodep); + goto fail; + } + } + + if (new_nodep) + *new_nodep = new_node; + return nodep; + +fail: + return NULL; +} + + +#ifdef PRODUCT_OPENIB_FF + + +McGroupData *FabricDataAddMCGroup(FabricData_t *fabricp, struct omgt_port *port, int quiet, IB_MCMEMBER_RECORD *pMCGRecord, + boolean *new_nodep, FILE *verbose_file) +{ + FSTATUS status; + McGroupData *mcgroupp = (McGroupData*)MemoryAllocate2AndClear(sizeof(McGroupData), IBA_MEM_FLAG_PREMPTABLE, MYTAG); + boolean new_node = TRUE; + + if (! mcgroupp) { + fprintf(stderr, "%s: Unable to allocate memory\n", g_Top_cmdname); + return NULL; + } + + // init list of McGroupMembers + QListInitState(&mcgroupp->AllMcGroupMembers); + if ( !QListInit(&mcgroupp->AllMcGroupMembers)) { + fprintf(stderr, "%s: Unable to initialize MCGroup member list\n", g_Top_cmdname); + MemoryDeallocate(mcgroupp); + return NULL; + } + + // init list of switches in a group + QListInitState(&mcgroupp->EdgeSwitchesInGroup); + if ( !QListInit(&mcgroupp->EdgeSwitchesInGroup)) { + fprintf(stderr, "%s: Unable to initialize list of Switches in a MC group\n", g_Top_cmdname); + MemoryDeallocate(mcgroupp); + return NULL; + } + mcgroupp->MGID = pMCGRecord->RID.MGID; + mcgroupp->MLID = MCAST16_TO_MCAST32(pMCGRecord->MLID); + + + ListItemInitState(&mcgroupp->AllMcGMembersEntry); + QListSetObj(&mcgroupp->AllMcGMembersEntry, mcgroupp); + + // search members of the group using opasaquery -o mcmember -m nodep->MLID + // and add them to the list of group members + status = GetAllMCGroupMember(fabricp, mcgroupp, port, quiet, verbose_file); + + if (status != FSUCCESS) { + fprintf(stderr, "%s: Unable to get MCGroup member list\n", g_Top_cmdname); + MemoryDeallocate(mcgroupp); + if (status == FINSUFFICIENT_MEMORY) + fprintf(stderr, "%s: Insufficient memory to allocate MC Member\n", g_Top_cmdname); + return NULL; + } + + // this part needs to be optimized + LIST_ITEM *p; + boolean found = FALSE; + p=QListHead(&fabricp->AllMcGroups); + +// insert everything in the fabric structure ordered by MGID + while (!found && p != NULL) { + McGroupData *pMCG = (McGroupData *)QListObj(p); + if ( pMCG->MLID > mcgroupp->MLID) + p = QListNext(&fabricp->AllMcGroups, p); + else { + // insert mcmember element + QListInsertNext(&fabricp->AllMcGroups,p, &mcgroupp->AllMcGMembersEntry); + found = TRUE; + } + } //end while + + if (!found) + QListInsertTail(&fabricp->AllMcGroups, &mcgroupp->AllMcGMembersEntry); + + if (new_nodep) + *new_nodep = new_node; + + return mcgroupp; +} + +#endif + + +FSTATUS AddEdgeSwitchToGroup(FabricData_t *fabricp, McGroupData *mcgroupp, NodeData *groupswitch, uint8 SWentryport) +{ + LIST_ITEM *p; + boolean found; + FSTATUS status; + + // this linear insertion needs to be optimized + found = FALSE; + p=QListHead(&mcgroupp->EdgeSwitchesInGroup); + while (!found && (p != NULL)) { + McEdgeSwitchData *pSW = (McEdgeSwitchData *)QListObj(p); + if (pSW->NodeGUID == groupswitch->NodeInfo.NodeGUID) + found = TRUE; + else + p = QListNext(&mcgroupp->EdgeSwitchesInGroup, p); + } + if (!found) { + McEdgeSwitchData *mcsw = (McEdgeSwitchData*)MemoryAllocate2AndClear(sizeof(McEdgeSwitchData), IBA_MEM_FLAG_PREMPTABLE, MYTAG); + if (! mcsw) { + status = FINSUFFICIENT_MEMORY; + return status; + } + mcsw->NodeGUID = groupswitch->NodeInfo.NodeGUID; + mcsw->pPort = FindPortGuid(fabricp, groupswitch->NodeInfo.NodeGUID ); + mcsw->EntryPort = SWentryport; + QListSetObj(&mcsw->McEdgeSwitchEntry, mcsw); + QListInsertTail(&mcgroupp->EdgeSwitchesInGroup, &mcsw->McEdgeSwitchEntry); + } + return FSUCCESS; +} + +FSTATUS FabricDataAddLink(FabricData_t *fabricp, PortData *p1, PortData *p2) +{ + // The Link Records will be reported in both directions + // so discard duplicates + if (p1->neighbor == p2 && p2->neighbor == p1) + goto fail; + if (p1->neighbor) { + fprintf(stderr, "%s: Skipping Duplicate Link Record reference to port: LID 0x%x Port %u Node %.*s\n", + g_Top_cmdname, + p1->EndPortLID, + p1->PortNum, NODE_DESCRIPTION_ARRAY_SIZE, + (char*)p1->nodep->NodeDesc.NodeString); + goto fail; + } + if (p2->neighbor) { + fprintf(stderr, "%s: Skipping Duplicate Link Record reference to port: LID 0x%x Port %u Node %.*s\n", + g_Top_cmdname, + p2->EndPortLID, + p2->PortNum, NODE_DESCRIPTION_ARRAY_SIZE, + (char*)p2->nodep->NodeDesc.NodeString); + goto fail; + } + //DisplayLinkRecord(pLinkRecord, 0); + p1->neighbor = p2; + p2->neighbor = p1; + // for consistency between runs, we always report the "from" port + // as the one with lower numbered NodeGUID/PortNum + if (p1->nodep->NodeInfo.NodeGUID != p2->nodep->NodeInfo.NodeGUID) { + if (p1->nodep->NodeInfo.NodeGUID < p2->nodep->NodeInfo.NodeGUID) { + p1->from = 1; + p2->from = 0; + } else { + p1->from = 0; + p2->from = 1; + } + } else { + if (p1->PortNum < p2->PortNum) { + p1->from = 1; + p2->from = 0; + } else { + p1->from = 0; + p2->from = 1; + } + } + if (p1->rate != p2->rate) { + fprintf(stderr, "\n%s: Warning: Ignoring Inconsistent Active Speed/Width for link between:\n", g_Top_cmdname); + fprintf(stderr, " %4s 0x%016"PRIx64" %3u %s %.*s\n", + StlStaticRateToText(p1->rate), + p1->nodep->NodeInfo.NodeGUID, + p1->PortNum, + StlNodeTypeToText(p1->nodep->NodeInfo.NodeType), + NODE_DESCRIPTION_ARRAY_SIZE, + (char*)p1->nodep->NodeDesc.NodeString); + fprintf(stderr, " %4s 0x%016"PRIx64" %3u %s %.*s\n", + StlStaticRateToText(p2->rate), + p2->nodep->NodeInfo.NodeGUID, + p2->PortNum, + StlNodeTypeToText(p2->nodep->NodeInfo.NodeType), + NODE_DESCRIPTION_ARRAY_SIZE, + (char*)p2->nodep->NodeDesc.NodeString); + } + ++(fabricp->LinkCount); + if (! isInternalLink(p1)) + ++(fabricp->ExtLinkCount); + if (isFILink(p1)) + ++(fabricp->FILinkCount); + if (isISLink(p1)) + ++(fabricp->ISLinkCount); + if (! isInternalLink(p1)&& isISLink(p1)) + ++(fabricp->ExtISLinkCount); + + return FSUCCESS; + +fail: + return FERROR; +} + +FSTATUS FabricDataAddLinkRecord(FabricData_t *fabricp, STL_LINK_RECORD *pLinkRecord) +{ + PortData *p1, *p2; + + //printf("process LinkRecord LID: 0x%x\n", pLinkRecord->RID.s.LID); + p1 = FindLidPort(fabricp, pLinkRecord->RID.FromLID, pLinkRecord->RID.FromPort); + if (! p1) { + fprintf(stderr, "%s: Can't find \"From\" Lid 0x%x Port %u: Skipping\n", + g_Top_cmdname, + pLinkRecord->RID.FromLID, pLinkRecord->RID.FromPort); + return FERROR; + } + p2 = FindLidPort(fabricp, pLinkRecord->ToLID, pLinkRecord->ToPort); + if (! p2) { + fprintf(stderr, "%s: Can't find \"To\" Lid 0x%x Port %u: Skipping\n", + g_Top_cmdname, + pLinkRecord->ToLID, pLinkRecord->ToPort); + return FERROR; + } + return FabricDataAddLink(fabricp, p1, p2); +} + +// This allows a link to be removed, its mainly a helper for manual +// construction of topologies which need to "undo links" they created +FSTATUS FabricDataRemoveLink(FabricData_t *fabricp, PortData *p1) +{ + PortData *p2 = p1->neighbor; + + if (! p1->neighbor) + goto fail; + if (p1 == p2) { + fprintf(stderr, "%s: Corrupted Topology, port linked to self: LID 0x%x Port %u Node %.*s\n", + g_Top_cmdname, + p1->EndPortLID, + p1->PortNum, NODE_DESCRIPTION_ARRAY_SIZE, + (char*)p1->nodep->NodeDesc.NodeString); + goto fail; + } + if (p2->neighbor != p1) { + fprintf(stderr, "%s: Corrupted Topology, port linked inconsistently: LID 0x%x Port %u Node %.*s\n", + g_Top_cmdname, + p1->EndPortLID, + p1->PortNum, NODE_DESCRIPTION_ARRAY_SIZE, + (char*)p1->nodep->NodeDesc.NodeString); + goto fail; + } + --(fabricp->LinkCount); + if (! isInternalLink(p1)) + --(fabricp->ExtLinkCount); + if (isFILink(p1)) + --(fabricp->FILinkCount); + if (isISLink(p1)) + --(fabricp->ISLinkCount); + if (! isInternalLink(p1)&& isISLink(p1)) + --(fabricp->ExtISLinkCount); + p1->rate = 0; + p1->neighbor = NULL; + p1->from = 0; + p2->rate = 0; + p2->neighbor = NULL; + p2->from = 0; + + return FSUCCESS; + +fail: + return FERROR; +} +#if !defined(VXWORKS) || defined(BUILD_DMC) +// remove Ioc from lists and free it +// Only removes from AllIOCs and IouData.Iocs, caller must remove from +// any other lists if called after BuildFabricLists +void IocDataFree(FabricData_t *fabricp, IocData *iocp) +{ + IouData *ioup = iocp->ioup; + + if (iocp->context && g_Top_FreeCallbacks.pIocDataFreeCallback) + (*g_Top_FreeCallbacks.pIocDataFreeCallback)(fabricp, iocp); + + QListRemoveItem(&ioup->Iocs, &iocp->IouIocsEntry); + cl_qmap_remove_item(&fabricp->AllIOCs, &iocp->AllIOCsEntry); + if (iocp->Services) + MemoryDeallocate(iocp->Services); + MemoryDeallocate(iocp); +} + +// Free all parsed Iocs for this Iou +// Only removes Iocs from AllIOCs and IouData.Iocs, caller must remove from +// any other lists if called after BuildFabricLists +void IouDataFreeIocs(FabricData_t *fabricp, IouData *ioup) +{ + LIST_ITEM *p; + + // this list is sorted/keyed by NodeGUID + for (p=QListHead(&ioup->Iocs); p != NULL; p = QListHead(&ioup->Iocs)) { + IocDataFree(fabricp, (IocData*)QListObj(p)); + } +} + +// remove Iou from NodeData.ioup and free it and its IOCs +// Only removes Iocs from AllIOCs and IouData.Iocs, caller must remove from +// any other lists if called after BuildFabricLists +void IouDataFree(FabricData_t *fabricp, IouData *ioup) +{ + if (ioup->context && g_Top_FreeCallbacks.pIouDataFreeCallback) + (*g_Top_FreeCallbacks.pIouDataFreeCallback)(fabricp, ioup); + + IouDataFreeIocs(fabricp, ioup); + if (ioup->nodep && ioup->nodep->ioup) + ioup->nodep->ioup = NULL; + MemoryDeallocate(ioup); +} +#endif +// Free all ports for this node +// Only removes ports from AllLids and NodeData.Ports, caller must remove from +// any other lists if called after BuildFabricLists +void NodeDataFreePorts(FabricData_t *fabricp, NodeData *nodep) +{ + cl_map_item_t *p; + + // this list is sorted/keyed by NodeGUID + for (p=cl_qmap_head(&nodep->Ports); p != cl_qmap_end(&nodep->Ports); p = cl_qmap_head(&nodep->Ports)) { + PortDataFree(fabricp, PARENT_STRUCT(p, PortData, NodePortsEntry)); + } +} + + +void NodeDataFreeSwitchData(FabricData_t *fabricp, NodeData *nodep) +{ + uint8_t i; + + if (nodep->switchp) { + SwitchData *switchp = nodep->switchp; + + if (switchp->LinearFDB) + MemoryDeallocate(switchp->LinearFDB); + if (switchp->PortGroupFDB) + MemoryDeallocate(switchp->PortGroupFDB); + if (switchp->PortGroupElements) + MemoryDeallocate(switchp->PortGroupElements); + for (i = 0; i < STL_NUM_MFT_POSITIONS_MASK; ++i) + if (switchp->MulticastFDB[i]) + MemoryDeallocate(switchp->MulticastFDB[i]); + + + MemoryDeallocate(switchp); + } + nodep->switchp = NULL; +} + + +FSTATUS NodeDataAllocateFDB(FabricData_t *fabricp, NodeData *nodep, + uint32 LinearFDBSize) { + + if (NodeDataSwitchResizeLinearFDB(nodep, LinearFDBSize) != FSUCCESS) { + fprintf(stderr, "%s: Unable to allocate memory\n", g_Top_cmdname); + return FINSUFFICIENT_MEMORY; + } + + + return FSUCCESS; +} + +FSTATUS NodeDataAllocateSwitchData(FabricData_t *fabricp, NodeData *nodep, + uint32 LinearFDBSize, uint32 MulticastFDBSize) +{ + SwitchData *switchp; + + if (nodep->switchp) { + // Free prior switch data + NodeDataFreeSwitchData(fabricp, nodep); + } + + nodep->switchp = (SwitchData *)MemoryAllocate2AndClear(sizeof(SwitchData), IBA_MEM_FLAG_PREMPTABLE, MYTAG); + if (! nodep->switchp) { + fprintf(stderr, "%s: Unable to allocate memory\n", g_Top_cmdname); + goto fail; + } + + switchp = nodep->switchp; + + if (NodeDataAllocateFDB(fabricp, nodep, LinearFDBSize) != FSUCCESS) { + goto fail; + } + + if (NodeDataSwitchResizeMcastFDB(nodep, MulticastFDBSize) != FSUCCESS) { + goto fail; + } + + // These are for the new STL PG Adaptative routing. Note that we allocate + // in multiples of full "blocks" which simplifies sending PG MADs to the + // switches and supports up to 64 ports per port group. Supporting more + // than 64 ports will require a different memory management technique. + switchp->PortGroupSize = ROUNDUP(nodep->pSwitchInfo->SwitchInfoData.PortGroupCap, NUM_PGT_ELEMENTS_BLOCK); + switchp->PortGroupElements = + MemoryAllocate2AndClear(switchp->PortGroupSize * + sizeof(STL_PORTMASK), IBA_MEM_FLAG_PREMPTABLE, MYTAG); + + + + return FSUCCESS; +fail: + NodeDataFreeSwitchData(fabricp, nodep); + return FINSUFFICIENT_MEMORY; +} + + + +//---------------------------------------------------------------------------- + +FSTATUS NodeDataSwitchResizeMcastFDB(NodeData * nodep, uint32 newMfdbSize) +{ + int errStatus = FINSUFFICIENT_MEMORY; + int i; + STL_PORTMASK * newMfdb[STL_NUM_MFT_POSITIONS_MASK] = {NULL}; + assert(nodep->NodeInfo.NodeType == STL_NODE_SW && nodep->switchp && nodep->pSwitchInfo); + + STL_SWITCH_INFO * switchInfo = &nodep->pSwitchInfo->SwitchInfoData; + + STL_LID newMtop = switchInfo->MulticastFDBTop; + + if (newMfdbSize > 0) { + newMfdbSize = MIN(newMfdbSize, switchInfo->MulticastFDBCap); + + for (i = 0; i < STL_NUM_MFT_POSITIONS_MASK; ++i) { + newMfdb[i] = (STL_PORTMASK*) MemoryAllocate2AndClear(newMfdbSize * sizeof(STL_PORTMASK), + IBA_MEM_FLAG_PREMPTABLE, MYTAG); + if (!newMfdb[i]) goto fail; + } + + if (switchInfo->MulticastFDBTop >= STL_LID_MULTICAST_BEGIN) { + size_t size = MIN(newMfdbSize, switchInfo->MulticastFDBTop - STL_LID_MULTICAST_BEGIN + 1); + + for (i = 0; i < STL_NUM_MFT_POSITIONS_MASK; ++i) { + if (!nodep->switchp->MulticastFDB[i]) + continue; + + memcpy(newMfdb[i], nodep->switchp->MulticastFDB[i], size * sizeof(STL_PORTMASK)); + newMtop = MIN((size - 1) + STL_LID_MULTICAST_BEGIN, newMtop); + } + } + } + + if (newMfdbSize) { + for (i = 0; i < STL_NUM_MFT_POSITIONS_MASK; ++i) { + if (nodep->switchp->MulticastFDB[i]) { + MemoryDeallocate(nodep->switchp->MulticastFDB[i]); + nodep->switchp->MulticastFDB[i] = NULL; + } + } + + memcpy(nodep->switchp->MulticastFDB, newMfdb, sizeof(newMfdb)); + switchInfo->MulticastFDBTop = newMtop; + + if (newMtop >= STL_LID_MULTICAST_BEGIN) + nodep->switchp->MulticastFDBSize = newMtop + 1; + else + nodep->switchp->MulticastFDBSize = newMfdbSize + STL_LID_MULTICAST_BEGIN; + + } + + return FSUCCESS; +fail: + for (i = 0; i < STL_NUM_MFT_POSITIONS_MASK; ++i) { + if (newMfdb[i]) { + MemoryDeallocate(newMfdb[i]); + newMfdb[i] = NULL; + } + } + + return errStatus; +} + +FSTATUS NodeDataSwitchResizeLinearFDB(NodeData * nodep, uint32 newLfdbSize) +{ + int errStatus = FINSUFFICIENT_MEMORY; + uint32 newPgdbSize; + STL_LINEAR_FORWARDING_TABLE * newLfdb = NULL; + STL_PORT_GROUP_FORWARDING_TABLE * newPgdb = NULL; + DEBUG_ASSERT(nodep->NodeInfo.NodeType == STL_NODE_SW && nodep->switchp && nodep->pSwitchInfo); + + STL_SWITCH_INFO * switchInfo = &nodep->pSwitchInfo->SwitchInfoData; + + STL_LID newLtop = switchInfo->LinearFDBTop; + + if (newLfdbSize > 0 && + switchInfo->RoutingMode.Enabled == STL_ROUTE_LINEAR) { + newLfdbSize = MIN(newLfdbSize, switchInfo->LinearFDBCap); + newLfdb = (STL_LINEAR_FORWARDING_TABLE*) MemoryAllocate2AndClear( + ROUNDUP(newLfdbSize, MAX_LFT_ELEMENTS_BLOCK), IBA_MEM_FLAG_PREMPTABLE, MYTAG); + + if (!newLfdb) goto fail; + + memset(newLfdb, 0xff, ROUNDUP(newLfdbSize, MAX_LFT_ELEMENTS_BLOCK)); + if (nodep->switchp->LinearFDB) { + size_t size = MIN(newLfdbSize, switchInfo->LinearFDBTop + 1); + memcpy(newLfdb, nodep->switchp->LinearFDB, size * sizeof(PORT)); + newLtop = MIN(size - 1, newLtop); + } + + // Port Group Forwarding table same as Linear FDB but capped + // at PortGroupFDBCap (for early STL1 HW hardcoded cap of 8kb) + newPgdbSize = MIN(newLfdbSize, + switchInfo->PortGroupFDBCap ? switchInfo->PortGroupFDBCap : DEFAULT_MAX_PGFT_LID+1); + newPgdb = (STL_PORT_GROUP_FORWARDING_TABLE*) MemoryAllocate2AndClear( + ROUNDUP(newPgdbSize, NUM_PGFT_ELEMENTS_BLOCK), IBA_MEM_FLAG_PREMPTABLE, MYTAG); + + if (!newPgdb) goto fail; + + memset(newPgdb, 0xff, ROUNDUP(newPgdbSize, NUM_PGFT_ELEMENTS_BLOCK)); + if (nodep->switchp->PortGroupFDB) { + size_t size = MIN(newPgdbSize, switchInfo->LinearFDBTop + 1); + memcpy(newPgdb, nodep->switchp->PortGroupFDB, size * sizeof(PORT)); + } + } + + if (newLfdb) { + STL_LINEAR_FORWARDING_TABLE * oldLfdb = nodep->switchp->LinearFDB; + nodep->switchp->LinearFDB = newLfdb; + nodep->switchp->LinearFDBSize = newLfdbSize; + switchInfo->LinearFDBTop = newLtop; + MemoryDeallocate(oldLfdb); + } + + if (newPgdb) { + STL_PORT_GROUP_FORWARDING_TABLE * oldPgdb = nodep->switchp->PortGroupFDB; + nodep->switchp->PortGroupFDB = newPgdb; + nodep->switchp->PortGroupFDBSize = newPgdbSize; + MemoryDeallocate(oldPgdb); + } + + return FSUCCESS; +fail: + if (newLfdb) { + MemoryDeallocate(newLfdb); + newLfdb = NULL; + } + + if (newPgdb) { + MemoryDeallocate(newPgdb); + newPgdb = NULL; + } + + return errStatus; +} + +FSTATUS NodeDataSwitchResizeFDB(NodeData * nodep, uint32 newLfdbSize, uint32 newMfdbSize) +{ + if ((NodeDataSwitchResizeLinearFDB(nodep, newLfdbSize) != FSUCCESS) || + (NodeDataSwitchResizeMcastFDB(nodep, newMfdbSize) != FSUCCESS)) { + fprintf(stderr, "%s: Unable to allocate memory\n", g_Top_cmdname); + return FINSUFFICIENT_MEMORY; + } + return FSUCCESS; +} + +// remove Node from lists and free it +// Only removes node from AllNodes and SystemData.Nodes +// Only removes ports from AllLids and NodeData.Ports +// Only removes Iou from NodeData.ioup +// Only removes Iocs from AllIOCs and IouData.Iocs, caller must remove from +// any other lists if called after BuildFabricLists +void NodeDataFree(FabricData_t *fabricp, NodeData *nodep) +{ + if (nodep->context && g_Top_FreeCallbacks.pNodeDataFreeCallback) + (*g_Top_FreeCallbacks.pNodeDataFreeCallback)(fabricp, nodep); + + cl_qmap_remove_item(&nodep->systemp->Nodes, &nodep->SystemNodesEntry); + if (cl_qmap_count(&nodep->systemp->Nodes) == 0) { + if (nodep->systemp->context && g_Top_FreeCallbacks.pSystemDataFreeCallback) + (*g_Top_FreeCallbacks.pSystemDataFreeCallback)(fabricp, nodep->systemp); + + cl_qmap_remove_item(&fabricp->AllSystems, &nodep->systemp->AllSystemsEntry); + MemoryDeallocate(nodep->systemp); + } + cl_qmap_remove_item(&fabricp->AllNodes, &nodep->AllNodesEntry); + NodeDataFreePorts(fabricp, nodep); +#if !defined(VXWORKS) || defined(BUILD_DMC) + if (nodep->ioup) + IouDataFree(fabricp, nodep->ioup); +#endif + if (nodep->pSwitchInfo) + MemoryDeallocate(nodep->pSwitchInfo); + NodeDataFreeSwitchData(fabricp, nodep); + MemoryDeallocate(nodep); +} + +// remove all Nodes from lists and free them +// Only removes nodes from AllNodes and SystemData.Nodes +// Only removes ports from AllLids and NodeData.Ports +// Only removes Iou from NodeData.ioup +// Only removes Iocs from AllIOCs and IouData.Iocs, caller must remove from +// any other lists if called after BuildFabricLists +void NodeDataFreeAll(FabricData_t *fabricp) +{ + cl_map_item_t *p; + + // this list is sorted/keyed by NodeGUID + for (p=cl_qmap_head(&fabricp->AllNodes); p != cl_qmap_end(&fabricp->AllNodes); p = cl_qmap_head(&fabricp->AllNodes)) { + NodeDataFree(fabricp, PARENT_STRUCT(p, NodeData, AllNodesEntry)); + } +} + +// remove SM from lists and free it +// Only removes SM from AllSMs, caller must remove from +// any other lists if called after BuildFabricLists +void SMDataFree(FabricData_t *fabricp, SMData *smp) +{ + if (smp->context && g_Top_FreeCallbacks.pSMDataFreeCallback) + (*g_Top_FreeCallbacks.pSMDataFreeCallback)(fabricp, smp); + + cl_qmap_remove_item(&fabricp->AllSMs, &smp->AllSMsEntry); + MemoryDeallocate(smp); +} + +// remove all SMs from lists and free them +// Only removes SMs from AllSMs, caller must remove from +// any other lists if called after BuildFabricLists +void SMDataFreeAll(FabricData_t *fabricp) +{ + cl_map_item_t *p; + + for (p=cl_qmap_head(&fabricp->AllSMs); p != cl_qmap_end(&fabricp->AllSMs); p = cl_qmap_head(&fabricp->AllSMs)) { + SMDataFree(fabricp, PARENT_STRUCT(p, SMData, AllSMsEntry)); + } +} + +void MCGroupFree(FabricData_t *fabricp, McGroupData *mcgroupp) +{ + LIST_ITEM *p; + + while (!QListIsEmpty(&mcgroupp->AllMcGroupMembers)) { + p = QListTail(&mcgroupp->AllMcGroupMembers); + McGroupData *group = (McGroupData *)QListObj(p); + QListRemoveTail(&mcgroupp->AllMcGroupMembers); + MemoryDeallocate(group); + } + + QListRemoveItem(&fabricp->AllMcGroups, &mcgroupp->AllMcGMembersEntry); + MemoryDeallocate(mcgroupp); +} + +void MCDataFreeAll(FabricData_t *fabricp) +{ + LIST_ITEM *p; + while (!QListIsEmpty(&fabricp->AllMcGroups)) { + p = QListTail(&fabricp->AllMcGroups); + MCGroupFree(fabricp, (McGroupData *)QListObj(p)); + } + +} + +void VFDataFreeAll(FabricData_t *fabricp) +{ + LIST_ITEM *i; + for (i = QListHead(&fabricp->AllVFs); i;) { + LIST_ITEM *next = QListNext(&fabricp->AllVFs, i); + MemoryDeallocate(QListObj(i)); + i = next; + } +} + +void CableDataFree(CableData *cablep) +{ + if (cablep->length) + MemoryDeallocate(cablep->length); + if (cablep->label) + MemoryDeallocate(cablep->label); + if (cablep->details) + MemoryDeallocate(cablep->details); + cablep->length = cablep->label = cablep->details = NULL; +} + +void PortSelectorFree(PortSelector *portselp) +{ + if (portselp->NodeDesc) + MemoryDeallocate(portselp->NodeDesc); + if (portselp->details) + MemoryDeallocate(portselp->details); + MemoryDeallocate(portselp); +} + +// remove Link from lists and free it +void ExpectedLinkFree(FabricData_t *fabricp, ExpectedLink *elinkp) +{ + if (elinkp->portp1 && elinkp->portp1->elinkp == elinkp) + elinkp->portp1->elinkp = NULL; + if (elinkp->portp2 && elinkp->portp2->elinkp == elinkp) + elinkp->portp2->elinkp = NULL; + if (ListItemIsInAList(&elinkp->ExpectedLinksEntry)) + QListRemoveItem(&fabricp->ExpectedLinks, &elinkp->ExpectedLinksEntry); + if (elinkp->portselp1) + PortSelectorFree(elinkp->portselp1); + if (elinkp->portselp2) + PortSelectorFree(elinkp->portselp2); + if (elinkp->details) + MemoryDeallocate(elinkp->details); + CableDataFree(&elinkp->CableData); + MemoryDeallocate(elinkp); +} + +// remove all Links from lists and free them +void ExpectedLinkFreeAll(FabricData_t *fabricp) +{ + LIST_ITEM *p; + + // free all link data + for (p=QListHead(&fabricp->ExpectedLinks); p != NULL;) { + LIST_ITEM *nextp = QListNext(&fabricp->ExpectedLinks, p); + ExpectedLinkFree(fabricp, (ExpectedLink *)QListObj(p)); + p = nextp; + } +} + +// remove Expected Node from lists and free it +void ExpectedNodeFree(FabricData_t *fabricp, ExpectedNode *enodep, QUICK_LIST *listp) +{ + if (enodep->nodep && enodep->nodep->enodep == enodep) + enodep->nodep->enodep = NULL; + if (ListItemIsInAList(&enodep->ExpectedNodesEntry)) + QListRemoveItem(listp, &enodep->ExpectedNodesEntry); + if (enodep->NodeGUID) + cl_qmap_remove(&fabricp->ExpectedNodeGuidMap, enodep->NodeGUID); + if (enodep->NodeDesc) + MemoryDeallocate(enodep->NodeDesc); + if (enodep->details) + MemoryDeallocate(enodep->details); + if (enodep->ports) { + int i; + for (i = 0; i < enodep->portsSize; ++i) { + if (enodep->ports[i]) + MemoryDeallocate(enodep->ports[i]); + } + MemoryDeallocate(enodep->ports); + } + MemoryDeallocate(enodep); +} + +// remove all Expected Nodes from lists and maps and free them +void ExpectedNodesFreeAll(FabricData_t *fabricp, QUICK_LIST *listp) +{ + LIST_ITEM *p; + + // free all link data + for (p=QListHead(listp); p != NULL;) { + LIST_ITEM *nextp = QListNext(listp, p); + ExpectedNodeFree(fabricp, (ExpectedNode *)QListObj(p), listp); + p = nextp; + } +} + +// remove Expected SM from lists and free it +void ExpectedSMFree(FabricData_t *fabricp, ExpectedSM *esmp) +{ + if (esmp->smp && esmp->smp->esmp == esmp) + esmp->smp->esmp = NULL; + if (ListItemIsInAList(&esmp->ExpectedSMsEntry)) + QListRemoveItem(&fabricp->ExpectedSMs, &esmp->ExpectedSMsEntry); + if (esmp->NodeDesc) + MemoryDeallocate(esmp->NodeDesc); + if (esmp->details) + MemoryDeallocate(esmp->details); + MemoryDeallocate(esmp); +} + +// remove all Expected SMs from lists and free them +void ExpectedSMsFreeAll(FabricData_t *fabricp) +{ + LIST_ITEM *p; + + // free all link data + for (p=QListHead(&fabricp->ExpectedSMs); p != NULL;) { + LIST_ITEM *nextp = QListNext(&fabricp->ExpectedSMs, p); + ExpectedSMFree(fabricp, (ExpectedSM *)QListObj(p)); + p = nextp; + } +} + +void DestroyFabricData(FabricData_t *fabricp) +{ + if (fabricp->context && g_Top_FreeCallbacks.pFabricDataFreeCallback) + (*g_Top_FreeCallbacks.pFabricDataFreeCallback)(fabricp); + + ExpectedLinkFreeAll(fabricp); // ExpectedLinks + ExpectedNodesFreeAll(fabricp, &fabricp->ExpectedFIs); // ExpectedFIs + ExpectedNodesFreeAll(fabricp, &fabricp->ExpectedSWs); // ExpectedSWs + ExpectedSMsFreeAll(fabricp); // ExpectedSMs + + SMDataFreeAll(fabricp); // SMs + NodeDataFreeAll(fabricp); // Nodes, Ports, IOUs, Systems + VFDataFreeAll(fabricp); + + if (fabricp->flags & FF_LIDARRAY) + FreeLidMap(fabricp); + + // make sure no stale pointers in lists, etc + // also clear counters and flags + MemoryClear(fabricp, sizeof(*fabricp)); +} + +#ifndef __VXWORKS__ + +static uint8 CLListUint32Find(cl_qmap_t *arrayMap, uint32 entry) +{ + uint8 found = 0; + cl_map_item_t *mi; + + mi = cl_qmap_get(arrayMap, entry); + if (mi != cl_qmap_end(arrayMap)) { + found = 1;; + } + return found; +} + +static uint8 CLListIntFind(cl_qmap_t *arrayMap, int entry) +{ + uint8 found = 0; + cl_map_item_t *mi; + + mi = cl_qmap_get(arrayMap, entry); + if (mi != cl_qmap_end(arrayMap)) { + found = 1;; + } + return found; +} + +static FSTATUS CLListUint32Add(cl_qmap_t *arrayMap, uint32 entry) +{ + FSTATUS status = FSUCCESS; + cl_map_item_t *mi; + clListSearchData_t *clListp; + + if (CLListUint32Find(arrayMap, entry)) + return status; + + clListp = (clListSearchData_t *)MemoryAllocate2AndClear(sizeof(clListSearchData_t), IBA_MEM_FLAG_PREMPTABLE, MYTAG); + if (!clListp) { + status = FINSUFFICIENT_MEMORY; + fprintf(stderr, "%s: Unable to allocate memory\n", g_Top_cmdname); + } else { + mi = cl_qmap_insert(arrayMap, entry, &clListp->AllListEntry); + if (mi != &clListp->AllListEntry) { + fprintf(stderr, "%s: Duplicate entry found in numeric list map: %d\n", g_Top_cmdname, entry); + MemoryDeallocate(clListp); + clListp = PARENT_STRUCT(mi, clListSearchData_t, AllListEntry); + } + } + + return status; +} + +static FSTATUS CLListIntAdd(cl_qmap_t *arrayMap, int entry) +{ + FSTATUS status = FSUCCESS; + cl_map_item_t *mi; + clListSearchData_t *clListp; + + if (CLListIntFind(arrayMap, entry)) + return status; + + clListp = (clListSearchData_t *)MemoryAllocate2AndClear(sizeof(clListSearchData_t), IBA_MEM_FLAG_PREMPTABLE, MYTAG); + if (!clListp) { + status = FINSUFFICIENT_MEMORY; + fprintf(stderr, "%s: Unable to allocate memory\n", g_Top_cmdname); + } else { + mi = cl_qmap_insert(arrayMap, entry, &clListp->AllListEntry); + if (mi != &clListp->AllListEntry) { + fprintf(stderr, "%s: Duplicate entry found in numeric list map: %d\n", g_Top_cmdname, entry); + MemoryDeallocate(clListp); + clListp = PARENT_STRUCT(mi, clListSearchData_t, AllListEntry); + } + } + + return status; +} + +//PYTHON: def ib_connection_source_to_str (conn) : +//NOTA BENE: NOTE THAT THIS FUNCTION IS NOT THREAD SAFE! +static char* ib_connection_source_to_str(FabricData_t *fabricp, clConnData_t *connp) +{ + cl_map_item_t *mi; + clDeviceData_t * device1p,*device2p; + static char str[2*NODE_DESCRIPTION_ARRAY_SIZE+11]; + + /* + return '%s port %d' % \ + (fabric.map_guid_to_ib_device[conn.guid1].name, conn.port1) + */ + mi = cl_qmap_get(&fabricp->map_guid_to_ib_device, connp->FromDeviceGUID); + if (mi == cl_qmap_end(&fabricp->map_guid_to_ib_device)) + return NULL; + device1p = PARENT_STRUCT(mi, clDeviceData_t, AllDevicesEntry); + + mi = cl_qmap_get(&fabricp->map_guid_to_ib_device, connp->ToDeviceGUID); + if (mi == cl_qmap_end(&fabricp->map_guid_to_ib_device)) + return NULL; + device2p = PARENT_STRUCT(mi, clDeviceData_t, AllDevicesEntry); + + snprintf(str, 2*NODE_DESCRIPTION_ARRAY_SIZE+10, "%s:%d to %s:%d VL:%d", + device1p->nodep->NodeDesc.NodeString, connp->FromPortNum, + device2p->nodep->NodeDesc.NodeString, connp->ToPortNum, + connp->VL.VL); + return str; +} + +static void CLThreadSleep(uint64_t sleep_time) +{ + struct timespec ts; + struct timespec ts_actual; + long micro_seconds; + + ts.tv_sec = (time_t)(sleep_time / 1000000ULL); + micro_seconds = (long)(sleep_time % 1000000ULL); + ts.tv_nsec = micro_seconds * 1000; + (void)nanosleep(&ts, &ts_actual); + + return; +} + +static clArcData_t* CLGraphFindIdArc(clGraphData_t *graphp, uint32 arcId) +{ + cl_map_item_t *mi; + + mi = cl_qmap_get(&graphp->Arcs, arcId); + if (mi != cl_qmap_end(&graphp->Arcs)) { + clArcData_t *arcp = PARENT_STRUCT(mi, clArcData_t, AllArcIdsEntry); + return arcp; + } + + return NULL; +} + +void CLGraphDataFree(clGraphData_t *graphp, void *context) +{ + #define DEF_MAX_FREE_ENTRY 5000 + int i; + cl_map_item_t *mi; + uint32_t arcListCount, arcCount = 0; + ValidateCreditLoopRoutesContext_t *cp = (ValidateCreditLoopRoutesContext_t *)context; + + + if (!graphp) + return; + + // free all arc entries + arcListCount = cl_qmap_count(&graphp->Arcs); + for (mi = cl_qmap_head(&graphp->Arcs); + mi != cl_qmap_end(&graphp->Arcs); + mi = cl_qmap_head(&graphp->Arcs), arcCount++) { + clArcData_t *arcp; + + if (NULL != (arcp = PARENT_STRUCT(mi, clArcData_t, AllArcIdsEntry))) { + cl_qmap_remove_item(&graphp->Arcs, &arcp->AllArcIdsEntry); + MemoryDeallocate(arcp); + } + if (arcListCount >= DEF_MAX_FREE_ENTRY) { + if (arcCount % PROGRESS_FREQ == 0 || arcCount == 0) { + if (!cp->quiet) + ProgressPrint(FALSE, "Deallocated %6d of %6d Arcs...", arcCount, arcListCount); + } + } + } + + // clear line used to display progress report + if (!cp->quiet && arcListCount >= DEF_MAX_FREE_ENTRY) + ProgressPrint(TRUE, "Done Deallocating All Arcs"); + + // free all vertices associated with the graph + if (graphp->Vertices) { + for (i = 0; i < graphp->NumVertices; i++) { + if (graphp->Vertices[i]) { + if (graphp->Vertices[i]->Inbound) + MemoryDeallocate(graphp->Vertices[i]->Inbound); + if (graphp->Vertices[i]->Outbound) + MemoryDeallocate(graphp->Vertices[i]->Outbound); + MemoryDeallocate(graphp->Vertices[i]); + } + if (graphp->NumVertices >= DEF_MAX_FREE_ENTRY) { + if (i % PROGRESS_FREQ == 0 || i == 0) { + if (!cp->quiet) + ProgressPrint(FALSE, "Deallocated %6d of %6d Vertices...", i, graphp->NumVertices); + } + } + } + + // clear line used to display progress report + if (!cp->quiet && graphp->NumVertices >= DEF_MAX_FREE_ENTRY) + ProgressPrint(TRUE, "Done Deallocating All Vertices"); + MemoryDeallocate(graphp->Vertices); + } +} + +static void CLDeviceDataFreeAll(FabricData_t *fabricp, void *context) +{ + #define DEF_MAX_FREE_DEV 5000 + int i, j; + cl_map_item_t * mi,*ri; + uint32 deviceCount = 0, deviceListCount, routeCount = 0; +// uint32 routeListCount; + ValidateCreditLoopRoutesContext_t *cp = (ValidateCreditLoopRoutesContext_t *)context; + + deviceListCount = cl_qmap_count(&fabricp->map_guid_to_ib_device); + // free all device entries + for (mi = cl_qmap_head(&fabricp->map_guid_to_ib_device); + mi != cl_qmap_end(&fabricp->map_guid_to_ib_device); + mi = cl_qmap_head(&fabricp->map_guid_to_ib_device), deviceCount++) { + clDeviceData_t *ccDevicep; + + if (NULL == (ccDevicep = PARENT_STRUCT(mi, clDeviceData_t, AllDevicesEntry))) + break; + else { + cl_qmap_remove_item(&fabricp->map_guid_to_ib_device, &ccDevicep->AllDevicesEntry); + // free all connections associated with the device + for (i = 0; i < CREDIT_LOOP_DEVICE_MAX_CONNECTIONS; i++) { + for (j = 0; j < STL_MAX_VLS; j++) { + if (ccDevicep->Connections[i][j]) + MemoryDeallocate(ccDevicep->Connections[i][j]); + } + } + +// routeListCount = cl_qmap_count(&ccDevicep->map_dlid_to_route); + // free all routes associated with the device + for (ri = cl_qmap_head(&ccDevicep->map_dlid_to_route), routeCount = 0; + ri != cl_qmap_end(&ccDevicep->map_dlid_to_route); + ri = cl_qmap_head(&ccDevicep->map_dlid_to_route), routeCount++) { + clRouteData_t *ccRoutep; + + if (NULL == (ccRoutep = PARENT_STRUCT(ri, clRouteData_t, AllRoutesEntry))) + break; + else { + cl_qmap_remove_item(&ccDevicep->map_dlid_to_route, &ccRoutep->AllRoutesEntry); + MemoryDeallocate(ccRoutep); + } + + /* + if (routeCount % PROGRESS_FREQ == 0 || routeCount == 0) { + if (!cp->quiet) + ProgressPrint(FALSE, "Deallocated %6d of %6d Routes...", routeCount, routeListCount); + } + */ + } + + if (deviceListCount >= DEF_MAX_FREE_DEV) { + if (deviceCount % PROGRESS_FREQ == 0 || deviceCount == 0) { + if (!cp->quiet) + ProgressPrint(FALSE, "Deallocated %6d of %6d Devices...", deviceCount, deviceListCount); + } + } + + // free device + MemoryDeallocate(ccDevicep); + } + } + + // clear line used to display progress report + if (!cp->quiet && deviceListCount >= DEF_MAX_FREE_DEV) + ProgressPrint(TRUE, "Done Deallocating All Routes"); +} + +static FSTATUS CLGetDynamicArray(void **array, uint32 *arrayEntries, uint32 entryLength, uint32 newEntryIndice, int verbose) +{ + #define ARRAY_INCR_NUM_ENTRIES 1000 + + FSTATUS status = FERROR; + + uint32 newEntries; + void *newBufferp; + + + if (array && arrayEntries) { + status = FSUCCESS; + if (!*array || newEntryIndice >= *arrayEntries) { + if (verbose >= 6) + printf("Old size: array=%p, *array=%p, arrayEntries=%d, entryLength=%d , newEntryIndice=%d\n", + array, *array, *arrayEntries, entryLength, newEntryIndice); + + // array has not been initialized, set entries to default values + if (!*array) { + //printf("\tALLOC:\n"); + *arrayEntries = 0; + } + + // extend the buffer by an addition fixed number of entries + newEntries = *arrayEntries + ARRAY_INCR_NUM_ENTRIES; + newBufferp = MemoryAllocate2AndClear(newEntries * entryLength, IBA_MEM_FLAG_PREMPTABLE, MYTAG); + if (!newBufferp) { + status = FINSUFFICIENT_MEMORY; + fprintf(stderr, "%s: Unable to resize the buffer\n", g_Top_cmdname); + } else { + // replicate the old array into the new array + if (*array) { + //printf("\tRESIZE:\n"); + memcpy(newBufferp, *array, (*arrayEntries * entryLength)); + MemoryDeallocate(*array); + } + // point to new array + *array = newBufferp; + *arrayEntries = newEntries; + //status = FSUCCESS; + } + if (verbose >= 6) + printf("New size: array=%p, arrayEntries=%d, array size=%d\n", *array, *arrayEntries, (*arrayEntries * entryLength)); + } + } + + return status; +} + +static clDeviceData_t* CLFindGuidDevice(FabricData_t *fabricp, uint64 guid) +{ + cl_map_item_t *mi; + + mi = cl_qmap_get(&fabricp->map_guid_to_ib_device, guid); + if (mi != cl_qmap_end(&fabricp->map_guid_to_ib_device)) { + clDeviceData_t *ccDevicep = PARENT_STRUCT(mi, clDeviceData_t, AllDevicesEntry); + return ccDevicep; + } + return NULL; +} + +//PYTHON: def lookup_vertex (self, ref) : +static clVertixData_t* CLGraphFindConnVertex(clGraphData_t *graphp, clConnData_t *ccConnp) +{ + cl_map_item_t *mi; + clVertixData_t *ccVertexp = NULL; + + if (graphp->Vertices) { + mi = cl_qmap_get(&graphp->map_conn_to_vertex_conn, (uint64)ccConnp); + if (mi != cl_qmap_end(&graphp->map_conn_to_vertex_conn)) { + ccVertexp = PARENT_STRUCT(mi, clVertixData_t, AllVerticesEntry); + } + } + return ccVertexp; +} + +//PYTHON: def add_vertex (self, ref) : +static int CLGraphDataAddVertex(clGraphData_t *graphp, clConnData_t *ccConnp, int verbose) +{ + cl_map_item_t *mi; + + //PYTHON: vertex = self.map_ref_to_vertex.get(ref) + /* CJKING: Addtional thought required on how to map a connection + * to a Vertex. Currently, doing linear search via CLGraphFindConnVertex() + */ + clVertixData_t *ccVertexp = CLGraphFindConnVertex(graphp, ccConnp); + + //PYTHON: if vertex : + if (ccVertexp) { + if (verbose >= 5) + fprintf(stderr, "Warning, Vector Id %d already exist\n", ccVertexp->Id); + return ccVertexp->Id; + } else { + ccVertexp = (clVertixData_t *)MemoryAllocate2AndClear(sizeof(clVertixData_t), IBA_MEM_FLAG_PREMPTABLE, MYTAG); + if (!ccVertexp) { + fprintf(stderr, "%s: Unable to allocate memory\n", g_Top_cmdname); + } else { + //PYTHON: id = len(self.vertices) + //PYTHON: vertex = Vertex(id, ref) + ccVertexp->Id = graphp->NumVertices; + ccVertexp->Connection = ccConnp; + if (!graphp->Vertices) + cl_qmap_init(&graphp->map_conn_to_vertex_conn, NULL); + if (!CLGetDynamicArray((void **)&graphp->Vertices, &graphp->VerticesLength, + sizeof(graphp->Vertices[0]), ccVertexp->Id, verbose)) { + //PYTHON: self.vertices.append(vertex) + graphp->Vertices[ccVertexp->Id] = ccVertexp; + //PYTHON: self.map_ref_to_vertex[ref] = vertex + mi = cl_qmap_insert(&graphp->map_conn_to_vertex_conn, (uint64)ccConnp, &ccVertexp->AllVerticesEntry); + if (mi != &ccVertexp->AllVerticesEntry) { + //if (verbose >= 4) { + fprintf(stderr, "%s: Duplicate connection found in vertix map: %p\n", g_Top_cmdname, ccVertexp->Connection); + //} + MemoryDeallocate(ccVertexp); + ccVertexp = PARENT_STRUCT(mi, clVertixData_t, AllVerticesEntry); + } + //PYTHON: self.num_vertices += 1 + graphp->NumVertices++; + graphp->NumActiveVertices++; + if (verbose >= 4) + printf("Adding vector Id %d\n", ccVertexp->Id); + return ccVertexp->Id; + } else { + MemoryDeallocate(ccVertexp); + } + } + } + + return -1; +} + +//PYTHON: def get_arc_key (source, sink) : +static clArcData_t* CLGraphFindSrcSinkArc(clGraphData_t *graphp, uint32 source, uint32 sink) +{ + cl_map_item_t *mi; + clArcData_t *arcp = NULL; + + if (cl_qmap_count(&graphp->map_arc_key_to_arc)) { + clArcData_t arc; + + arc.u1.s.Source = source; + arc.u1.s.Sink = sink; + mi = cl_qmap_get(&graphp->map_arc_key_to_arc, arc.u1.AsReg64); + if (mi != cl_qmap_end(&graphp->map_arc_key_to_arc)) { + arcp = PARENT_STRUCT(mi, clArcData_t, AllArcsEntry); + } + } + return arcp; +} + +//PYTHON: def del_arc (self, id) : +static void CLGraphDataDelArc(clGraphData_t *graphp, int arcId) +{ + uint32 i; + //LIST_ITEM *p; + cl_map_item_t *mi; + clArcData_t *ccArcp = NULL; + + + if (arcId < 0) + return; + + + //PYTHON: arc = self.arcs[id] + mi = cl_qmap_get(&graphp->Arcs, arcId); + if (mi != cl_qmap_end(&graphp->Arcs)) { + ccArcp = PARENT_STRUCT(mi, clArcData_t, AllArcIdsEntry); + if (ccArcp) { + clArcData_t *ssArcp; + + // remove arc entry from arc IDs map + cl_qmap_remove_item(&graphp->Arcs, &ccArcp->AllArcIdsEntry); + // remove arc entry from arc Source/Sink map + if ((ssArcp = CLGraphFindSrcSinkArc(graphp, ccArcp->Source, ccArcp->Sink))) + cl_qmap_remove_item(&graphp->map_arc_key_to_arc, &ssArcp->AllArcsEntry); + } + } + + if (!ccArcp) { + fprintf(stderr, "Warning, failed to find arc with id %d\n", arcId); + exit(0); + } else { + /* + * process up-link references + */ + //PYTHON: self.vertices[arc.source].outbound.remove(id) + for (i = 0; i < graphp->Vertices[ccArcp->Source]->OutboundCount; i++) { + if (arcId == graphp->Vertices[ccArcp->Source]->Outbound[i]) { + graphp->Vertices[ccArcp->Source]->Outbound[i] = -1; + //PYTHON: self.vertices[arc.source].refcount -= 1 + graphp->Vertices[ccArcp->Source]->RefCount--; + graphp->Vertices[ccArcp->Source]->OutboundInuseCount--; + } + } + //PYTHON: if self.vertices[arc.source].refcount == 0 : + if (graphp->Vertices[ccArcp->Source]->RefCount == 0) + graphp->NumActiveVertices--; //PYTHON: self.num_vertices -= 1 + + /* + * remove down-link references + */ + //PYTHON: self.vertices[arc.sink].inbound.remove(id) + for (i = 0; i < graphp->Vertices[ccArcp->Sink]->InboundCount; i++) { + if (arcId == graphp->Vertices[ccArcp->Sink]->Inbound[i]) { + graphp->Vertices[ccArcp->Sink]->Inbound[i] = -1; + //PYTHON: self.vertices[arc.sink].refcount -= 1 + graphp->Vertices[ccArcp->Sink]->RefCount--; + graphp->Vertices[ccArcp->Sink]->InboundInuseCount--; + } + } + //PYTHON: if self.vertices[arc.sink].refcount == 0 : + if (graphp->Vertices[ccArcp->Sink]->RefCount == 0) + graphp->NumActiveVertices--; //PYTHON: self.num_vertices -= 1 + + //PYTHON: self.num_arcs -= 1 + graphp->NumArcs--; + MemoryDeallocate(ccArcp); + } +} + +//PYTHON: def add_arc (self, source, sink) : +static int CLGraphDataAddArc(clGraphData_t *graphp, uint32 source, uint32 sink, int verbose) +{ + int arcId = -1; + cl_map_item_t *mi; + + + //PYTHON: if source == sink : + if (source == sink) + fprintf(stderr, "Warning, Ignoring arc with same source and sink of %d\n", source); + else if (source >= graphp->NumVertices) //PYTHON: if source < 0 or source >= len(self.vertices) : + fprintf(stderr, "Warning, Ignoring out of range source vertex %d\n", source); + else if (sink >= graphp->NumVertices) //PYTHON: if sink < 0 or sink >= len(self.vertices) : + fprintf(stderr, "Warning, Ignoring out of range sink vertex %d\n", sink); + else { + //PYTHON: arc_key = get_arc_key(source, sink) + clArcData_t *ccArcp = CLGraphFindSrcSinkArc(graphp, source, sink); + + if (ccArcp) { + //PYTHON: id = self.map_arc_key_to_arc[arc_key] + arcId = ccArcp->Id; + if (verbose >= 6) + fprintf(stderr, "Warning, arc %d from %d to %d already exists\n", arcId, source, sink); + } else { + ccArcp = (clArcData_t *)MemoryAllocate2AndClear(sizeof(clArcData_t), IBA_MEM_FLAG_PREMPTABLE, MYTAG); + if (!ccArcp) { + fprintf(stderr, "%s: Unable to allocate memory\n", g_Top_cmdname); + } else { + FSTATUS status; + + //PYTHON: id = len(self.arcs) + ccArcp->Id = cl_qmap_count(&graphp->Arcs); + //PYTHON: self.arcs.append(Arc(self, source, sink)) + ccArcp->Source = source; + ccArcp->Sink = sink; + mi = cl_qmap_insert(&graphp->Arcs, ccArcp->Id, &ccArcp->AllArcIdsEntry); + if (mi != &ccArcp->AllArcIdsEntry) { + //if (verbose >= 4) { + fprintf(stderr, "%s: Duplicate connection found in arc ID map: %d\n", g_Top_cmdname, ccArcp->Id); + //} + //MemoryDeallocate(ccArcp); + //ccArcp = PARENT_STRUCT(mi, clArcData_t, AllArcsEntry); + } + //PYTHON: self.map_arc_key_to_arc[arc_key] = id + ccArcp->u1.s.Source = source; + ccArcp->u1.s.Sink = sink; + mi = cl_qmap_insert(&graphp->map_arc_key_to_arc, ccArcp->u1.AsReg64, &ccArcp->AllArcsEntry); + if (mi != &ccArcp->AllArcsEntry) { + //if (verbose >= 4) { + fprintf(stderr, "%s: Duplicate connection found in arc source-sink map: 0x%016"PRIx64"\n", g_Top_cmdname, ccArcp->u1.AsReg64); + //} + MemoryDeallocate(ccArcp); + ccArcp = PARENT_STRUCT(mi, clArcData_t, AllArcsEntry); + } + + if (!(status = CLGetDynamicArray((void **)&graphp->Vertices[source]->Outbound, + &graphp->Vertices[source]->OutboundLength, + sizeof(int), graphp->Vertices[source]->OutboundCount, verbose))) { + //PYTHON: self.vertices[source].outbound.append(id) + graphp->Vertices[source]->Outbound[graphp->Vertices[source]->OutboundCount] = ccArcp->Id; + graphp->Vertices[source]->OutboundCount++; + graphp->Vertices[source]->OutboundInuseCount++; + //PYTHON: self.vertices[source].refcount += 1 + graphp->Vertices[source]->RefCount++; + } + + if (!status) { + if (!(status = CLGetDynamicArray((void **)&graphp->Vertices[sink]->Inbound, + &graphp->Vertices[sink]->InboundLength, + sizeof(int), graphp->Vertices[sink]->InboundCount, verbose))) { + //PYTHON: self.vertices[sink].inbound.append(id) + graphp->Vertices[sink]->Inbound[graphp->Vertices[sink]->InboundCount] = ccArcp->Id; + graphp->Vertices[sink]->InboundCount++; + graphp->Vertices[sink]->InboundInuseCount++; + //PYTHON: self.vertices[sink].refcount += 1 + graphp->Vertices[sink]->RefCount++; + } + } + + if (status) + (void)CLGraphDataDelArc(graphp, ccArcp->Id); + else { + arcId = ccArcp->Id; + //PYTHON: self.num_arcs += 1 + graphp->NumArcs++; + if (verbose >= 4) + printf("Add arc from %d to %d\n", source, sink); + } + } + } + } + + return arcId; +} + +//PYTHON: def build_routing_graph (fabric) : +static void* CLFabricDataBuildRouteGraphThread(void *context) +{ + FabricData_t *fabricp = ((clThreadContext_t *)context)->fabricp; + int verbose = ((clThreadContext_t *)context)->verbose; + FSTATUS status = FSUCCESS; + uint32 hops = 0, l = 0; + LIST_ITEM *dstHcaLstp; + LIST_ITEM *srcHcaLstp; + uint32 thrdId = ((clThreadContext_t *)context)->threadId; + ValidateCLTimeGetCallback_t timeGetCallback = ((clThreadContext_t *)context)->timeGetCallback; + uint32 usedSLs = ((clThreadContext_t*)context)->usedSLs; + //PYTHON: for src_hfi in fabric.hfis : + for (srcHcaLstp = ((clThreadContext_t *)context)->srcHcaList; + l < ((clThreadContext_t *)context)->srcHcaListLength; + srcHcaLstp = QListNext(&fabricp->FIs, srcHcaLstp), l++) { + clDeviceData_t *src_hfip = (clDeviceData_t *)QListObj(srcHcaLstp); + + if (verbose >= 3) { + timeGetCallback(&((clThreadContext_t *)context)->sTime, &g_cl_lock); + printf("[%d] START build all routes from %s (SLID 0x%08x)\n", + (int)thrdId, src_hfip->nodep->NodeDesc.NodeString, src_hfip->Lid); + } + + //PYTHON: for dst_hfi in fabric.hfis : + for (dstHcaLstp = QListHead(&fabricp->FIs); dstHcaLstp != NULL; dstHcaLstp = QListNext(&fabricp->FIs, dstHcaLstp)) { + clDeviceData_t *dst_hfip = (clDeviceData_t *)QListObj(dstHcaLstp); + + if (srcHcaLstp != dstHcaLstp) { + uint8 sl; + for (sl = 0; sl < STL_MAX_SLS; sl++) { // loop over SLs + if (usedSLs != 0) { + if (!((usedSLs >> sl) & 1)) { + continue; + } + } else { + if (sl != 0) continue; + } + uint32 links; + uint16 slid, dlid; + int this_vertex_id; + uint32 previous_vertex_id = 0; //PYTHON: previous_vertex_id = None + clDeviceData_t *hfip = src_hfip; //PYTHON: hfi = src_hfip; + clConnData_t *this_connection = NULL; + clConnData_t *previous_connection = NULL; //PYTHON: previous_connection = None + uint8 sc = 0, previous_sc = 0; + + //PYTHON: slid = src_hfi.lid + //PYTHON: dlid = dst_hfi.lid + //PYTHON: links = 0 + slid = src_hfip->Lid; + dlid = dst_hfip->Lid; + links = 0; + if (verbose >= 4) + printf("[%d]Build route from %s to %s (SLID 0x%04x to DLID 0x%04x):\n", + (int)thrdId, src_hfip->nodep->NodeDesc.NodeString, dst_hfip->nodep->NodeDesc.NodeString, slid, dlid); + + // get global lock + pthread_mutex_lock(&g_cl_lock); + + //PYTHON: while hfi != dst_hfi : + while (hfip != dst_hfip) { + cl_map_item_t *mi; + PortData *portp = NULL; + clRouteData_t *ccRoutep = NULL; + //PYTHON: if dlid in hfi.routes : + mi = cl_qmap_get(&hfip->map_dlid_to_route, dlid); + if (mi != cl_qmap_end(&hfip->map_dlid_to_route)) + ccRoutep = PARENT_STRUCT(mi, clRouteData_t, AllRoutesEntry); + + if (ccRoutep) { + //PYTHON: port = hfi.routes[dlid] + portp = ccRoutep->portp; + if (verbose >= 4) + printf(" [%d] GUID 0x%016"PRIx64": use port %3.3u\n", (int)thrdId, hfip->nodep->NodeInfo.NodeGUID, portp->PortNum); + } else { + if (verbose >= 4) + printf(" [%d] GUID 0x%016"PRIx64": no route to DLID 0x%04x\n", (int)thrdId, hfip->nodep->NodeInfo.NodeGUID, dlid); + break; + } + // look up the sc + if (usedSLs) { + // if this is the 1st hop, use the SL2SC table + if (hfip == src_hfip) { + if (portp->pQOS && portp->pQOS->SL2SCMap) { + sc = portp->pQOS->SL2SCMap->SLSCMap[sl].SC; + } + } else if (previous_connection) { + // SC to SC' transition + if (!hfip->nodep) { + fprintf(stderr, "[%d] Error, no node data found for GUID 0x%016"PRIx64"\n", (int)thrdId, previous_connection->ToDeviceGUID); + status = FERROR; + break; + } + if (hfip->nodep->NodeInfo.NodeType == STL_NODE_SW) { // should always be a switch + mi = cl_qmap_get(&hfip->nodep->Ports, previous_connection->ToPortNum); + if (mi == cl_qmap_end(&hfip->nodep->Ports)) { + fprintf(stderr, "[%d] Error, unable to find port %d for GUID 0x%016"PRIx64"\n", (int)thrdId, previous_connection->ToPortNum, previous_connection->ToDeviceGUID); + status = FERROR; + break; + } + PortData *prev_port = PARENT_STRUCT(mi, PortData, NodePortsEntry); + if (prev_port && prev_port->pQOS && !(QListIsEmpty(&prev_port->pQOS->SC2SCMapList[0]))){ + STL_SCSCMAP *pSCSC = QOSDataLookupSCSCMap(prev_port, portp->PortNum, 0); + if (pSCSC) { + sc = pSCSC->SCSCMap[previous_sc].SC; + } + } + } + } + } + //PYTHON: this_connection = hfi.connections[port] + this_connection = hfip->Connections[portp->PortNum][sc]; + if (!this_connection){ // no connection found for this port/vl, broken route + fprintf(stderr, "[%d] Warning, broken route for GUID 0x%016"PRIx64" port %3.3u\n", (int)thrdId, hfip->nodep->NodeInfo.NodeGUID, portp->PortNum); + break; + } + + //PYTHON: graph.add_vertex(this_connection) + if (-1 == (this_vertex_id = CLGraphDataAddVertex(&fabricp->Graph, this_connection, verbose))) { + break; + } + //PYTHON: if previous_connection : + if (previous_connection) { + //PYTHON: graph.add_arc(previous_vertex_id, this_vertex_id) + if (-1 == CLGraphDataAddArc(&fabricp->Graph, previous_vertex_id, this_vertex_id, verbose)) { + status = FERROR; + break; + } + } + + //PYTHON: guid = this_connection.guid2 + //PYTHON: hfi = fabric.map_guid_to_ib_device[guid] + if (!(hfip = CLFindGuidDevice(fabricp, this_connection->ToDeviceGUID))) { + fprintf(stderr, "[%d] Error, no device found for GUID 0x%016"PRIx64" to DLID 0x%04x\n", (int)thrdId, this_connection->ToDeviceGUID, dlid); + status = FERROR; + break; + } + + //PYTHON: links += 1 + //PYTHON: previous_connection = this_connection + //PYTHON: previous_vertex_id = this_vertex_id + links++; + previous_connection = this_connection; + previous_vertex_id = this_vertex_id; + previous_sc = sc; + } // end while loop + + // release global lock + pthread_mutex_unlock(&g_cl_lock); + + //PYTHON: if hfi == dst_hfi : + if (hfip == dst_hfip) { + //PYTHON: present_routes += 1 + //PYTHON: hops = links - 1 + present_routes++; + hops = links - 1; + + if (verbose >= 4) + printf(" [%d] %d links traversed, %d hops\n", (int)thrdId, links, hops); + + // get global lock + pthread_mutex_lock(&g_cl_lock); + + if (!CLGetDynamicArray((void **)&hops_histogram, &hops_histogram_length, sizeof(uint32), hops, verbose)) { + //PYTHON: if hops in hops_histogram + //CJKING: if (CLListUint32Find(hops, hops_histogram, hops_histogram_entries, verbose)) + if (CLListUint32Find(&hopsHistogramLstMap, hops)) + hops_histogram[hops]++; //PYTHON: hops_histogram[hops] += 1 + else { + //CJKING: Add entry to search list for hops_histogram array + if (!CLListUint32Add(&hopsHistogramLstMap, hops)) + hops_histogram[hops] = 1; //PYTHON: histogram[hops] = 1 + else { + status = FERROR; + pthread_mutex_unlock(&g_cl_lock); + break; + } + } + hops_histogram_entries = MAX(hops_histogram_entries, hops); + } + + // release global lock + pthread_mutex_unlock(&g_cl_lock); + } else { + missing_routes += 1; //PYTHON: missing_routes += 1 + } + } + } + } + + if (verbose >= 3) { + timeGetCallback(&((clThreadContext_t *)context)->eTime, &g_cl_lock); + printf("[%d] END build all routes from %s (SLID 0x%08x); elapsed time(usec)=%d, (sec)=%d\n", + (int)thrdId, src_hfip->nodep->NodeDesc.NodeString, src_hfip->Lid, + (int)(((clThreadContext_t *)context)->eTime - ((clThreadContext_t *)context)->sTime), + ((int)(((clThreadContext_t *)context)->eTime - ((clThreadContext_t *)context)->sTime)) / CL_TIME_DIVISOR); + + printf("[%d] %d of %d nodes completed\n", + (int)thrdId, l+1, ((clThreadContext_t *)context)->srcHcaListLength); + } else { + if (l%PROGRESS_FREQ == 0 || l == 0) { + // get global lock + pthread_mutex_lock(&g_cl_lock); + if (!((clThreadContext_t *)context)->quiet) + ProgressPrint(FALSE, "[%d]Processed %6d of %6d Routes...", + (int)thrdId, l+1, ((clThreadContext_t *)context)->srcHcaListLength); + // release global lock + pthread_mutex_unlock(&g_cl_lock); + } + } + + (void)CLThreadSleep(VTIMER_1_MILLISEC); + } + + ((clThreadContext_t *)context)->threadExit = 1; + ((clThreadContext_t *)context)->threadStatus = status; + + return NULL; +} + +//PYTHON: def split_out_vertex (self, new_graph, vertex) : +static FSTATUS CLGraphDataSplitOutVertex(clGraphData_t *graphp, clGraphData_t *newGraphp, clVertixData_t *vertexp, int verbose) +{ + FSTATUS status = FSUCCESS; + int ii, nn, new_vertex_id, new_sink_id, new_source_id; + uint32 neighborsLength = 0, neighborsCount = 0; + clVertixData_t * sink,*source; + clArcData_t *arcp; + clVertixData_t **neighbors = NULL; + + + //PYTHON: if vertex.refcount : + if (vertexp->RefCount) { + //PYTHON: new_vertex_id = new_graph.add_vertex(vertex.ref) + new_vertex_id = CLGraphDataAddVertex(newGraphp, vertexp->Connection, verbose); + + //PYTHON: neighbors = [] + /* initialization of neighbors array handled via CLGetDynamicArray() */ + + //PYTHON: for arc_id in vertex.outbound : + for (ii = 0; ii < vertexp->OutboundCount; ii++) { + if (vertexp->Outbound[ii] >= 0 && (arcp = CLGraphFindIdArc(graphp, vertexp->Outbound[ii]))) { + //PYTHON: sink = self.vertices[self.arcs[arc_id].sink] + sink = graphp->Vertices[arcp->Sink]; + + if (CLGetDynamicArray((void **)&neighbors, &neighborsLength, sizeof(neighbors), neighborsCount, verbose)) { + status = FERROR; + break; + } + + //PYTHON: neighbors.append(sink) + neighbors[neighborsCount++] = sink; + + //PYTHON: new_sink_id = new_graph.add_vertex(sink.ref) + if (-1 == (new_sink_id = CLGraphDataAddVertex(newGraphp, sink->Connection, verbose))) { + status = FERROR; + break; + } + //PYTHON: new_graph.add_arc(new_vertex_id, new_sink_id) + if (-1 == CLGraphDataAddArc(newGraphp, new_vertex_id, new_sink_id, verbose)) { + status = FERROR; + break; + } + } + } + + //PYTHON: for arc_id in vertex.outbound : + for (ii = 0; ii < vertexp->OutboundCount; ii++) { + //PYTHON: self.del_arc(arc_id) + if (vertexp->Outbound[ii] >= 0) + (void)CLGraphDataDelArc(graphp, vertexp->Outbound[ii]); + } + + //PYTHON: for arc_id in vertex.inbound : + for (ii = 0; ii < vertexp->InboundCount; ii++) { + if (vertexp->Inbound[ii] >= 0 && (arcp = CLGraphFindIdArc(graphp, vertexp->Inbound[ii]))) { + //PYTHON: source = self.vertices[self.arcs[arc_id].source] + source = graphp->Vertices[arcp->Source]; + if (CLGetDynamicArray((void **)&neighbors, &neighborsLength, sizeof(neighbors), neighborsCount, verbose)) { + status = FERROR; + break; + } + //PYTHON: neighbors.append(source) + neighbors[neighborsCount++] = source; + + //PYTHON: new_source_id = new_graph.add_vertex(source.ref) + if (-1 == (new_source_id = CLGraphDataAddVertex(newGraphp, source->Connection, verbose))) { + status = FERROR; + break; + } + + //PYTHON: new_graph.add_arc(new_source_id, new_vertex_id) + if (-1 == CLGraphDataAddArc(newGraphp, new_source_id, new_vertex_id, verbose)) { + status = FERROR; + break; + } + } + } + + //PYTHON: for arc_id in vertex.inbound : + for (ii = 0; ii < vertexp->InboundCount; ii++) { + //PYTHON: self.del_arc(arc_id) + if (vertexp->Inbound[ii] >= 0) + (void)CLGraphDataDelArc(graphp, vertexp->Inbound[ii]); + } + + //PYTHON: for n in neighbors : + for (nn = 0; nn < neighborsCount; nn++) { + //PYTHON: self.split_out_vertex(new_graph, n) + CLGraphDataSplitOutVertex(graphp, newGraphp, neighbors[nn], verbose); + } + } + + // deallocate dynamic array + MemoryDeallocate(neighbors); + + return status; +} + +static void CLDijkstraFreeArray(void **array, uint32 nRows) +{ + int i; + + if (array) { + for (i = 0; i < nRows; i++) { + if (array[i]) + MemoryDeallocate(array[i]); + } + MemoryDeallocate(array); + } +} + +static void** CLDijkstraAllocArray(uint32 nRows, uint32 nCols, uint32 entryLenth) +{ + int i; + void **array; + + array = MemoryAllocate2AndClear(nRows * sizeof(void *), IBA_MEM_FLAG_PREMPTABLE, MYTAG); + if (!array) + fprintf(stderr, "%s: Unable to allocate memory\n", g_Top_cmdname); + else { + for (i = 0; i < nRows; i++) { + array[i] = MemoryAllocate2AndClear(nCols * entryLenth, IBA_MEM_FLAG_PREMPTABLE, MYTAG); + if (!array[i]) { + fprintf(stderr, "%s: Unable to allocate memory\n", g_Top_cmdname); + (void)CLDijkstraFreeArray(array, i); + return NULL; + } + } + } + + return array; +} + +static clVertixDataDistance_t* CLDijkstraAddVertexDistance(cl_qmap_t *mapp, clVertixData_t *vertixp, int verbose) +{ + cl_map_item_t *mi; + clVertixDataDistance_t *entryp = NULL; + + if (mapp && vertixp) { + entryp = (clVertixDataDistance_t *)MemoryAllocate2AndClear(sizeof(clVertixDataDistance_t), IBA_MEM_FLAG_PREMPTABLE, MYTAG); + if (!entryp) + fprintf(stderr, "%s: Unable to allocate memory\n", g_Top_cmdname); + else { + entryp->vertixp = vertixp; + mi = cl_qmap_insert(mapp, vertixp->Id, &entryp->AllVerticesEntry); + if (verbose >= 4) + printf("Add distance vertix Id %d\n", vertixp->Id); + if (mi != &entryp->AllVerticesEntry) { + MemoryDeallocate(entryp); + entryp = NULL; + fprintf(stderr, "Error, failed to add vertix Id %d\n", vertixp->Id); + } + } + } + + return entryp; +} + +static int CLDijkstraVertexPopDistance(cl_qmap_t *mapp) +{ + uint32 id = -1; + cl_map_item_t *mi; + clVertixDataDistance_t *entryp; + + mi = cl_qmap_head(mapp); + if (mi != cl_qmap_end(mapp)) { + if (NULL != (entryp = PARENT_STRUCT(mi, clVertixDataDistance_t, AllVerticesEntry))) { + id = entryp->vertixp->Id; + cl_qmap_remove_item(mapp, &entryp->AllVerticesEntry); + MemoryDeallocate(entryp); + } + } + + return id; +} + +//PYTHON: def get_distance (distances, src, dst) : +static FSTATUS CLDijkstraGetDistance(uint32 **distances, uint32 nRows, uint32 nCols, uint32 src, uint32 dst, uint32 *value) +{ + FSTATUS status = FSUCCESS; + + //PYTHON: if distances.get(src) == None : + //PYTHON: return infinity + *value = DIJKSTRA_INFINITY; + if (distances == NULL) + status = FERROR; + else if (src >= nRows || dst >= nCols) { + status = FINVALID_PARAMETER; + fprintf(stderr, "Warning, invalid distance parameters: src %d, dst %d\n", src, dst); + } else { + //PYTHON: return distances.get(src).get(dst) + *value = distances[src][dst]; + } + + return status; +} + +//PYTHON: def check_distances_and_routes (graph, distances, routes) : +static int CLDijkstraCheckDistancesAndRoutes(clGraphData_t *graphp, uint32 **distances, uint32 **routes, uint32 nRows, uint32 nCols, uint32 verbose) +{ + uint32 ii, jj, errors = 0; //PYTHON: errors = 0 + clVertixData_t * i,*j; + + //PYTHON: for i in graph.vertices : + for (ii = 0; ii < graphp->VerticesLength; ii++) { + //PYTHON: if i.refcount : + if ((i = graphp->Vertices[ii]) && i->RefCount) { + //PYTHON: for j in graph.vertices : + for (jj = 0; jj < graphp->VerticesLength; jj++) { + uint32 d, distance; + + //PYTHON: if j.refcount : + if ((j = graphp->Vertices[jj]) && j->RefCount) { + uint32 k, found; + + d = 0; //PYTHON: d = 0 + k = i->Id; //PYTHON: k = i.id + + //PYTHON: while j.id in routes[k] : + //CJKING: while ((found = CLListUint32Find(j->Id, routes[k], nCols, verbose))) { + while ((found = CLListUint32Find(routesLstMap, j->Id))) { + uint32 l; + + l = routes[k][j->Id]; //PYTHON: l = routes[k][j.id] + d++; //PYTHON: d += 1 + //PYTHON: if l == j.id : + if (l == j->Id) + break; + k = l; //PYTHON: k = l + } + //PYTHON: else : + //PYTHON: d = infinity + if (!found) + d = DIJKSTRA_INFINITY; + + //PYTHON: distance = get_distance(distances, i.id, j.id) + if (FERROR == CLDijkstraGetDistance(distances, nRows, nCols, i->Id, j->Id, &distance)) + return -1; + if (distance == d) { //if distance == d : + if (verbose >= 4) + printf("Check route from %d to %d of %d hops: OK\n", i->Id, j->Id, distance); + } else { + errors++; //PYTHON: errors += 1 + if (verbose >= 4) + fprintf(stderr, "Warning, check route from %d to %d of %d hops: failed, got %d hops\n", + i->Id, j->Id, distance, d); + } + } + } + } + } + + if (verbose >= 3) + printf("Check route summary : %d dependency graph routes have errors\n", errors); + + return errors; +} + +FSTATUS CLFabricDataDestroy(FabricData_t *fabricp, void *context) +{ + (void)CLDeviceDataFreeAll(fabricp, context); + (void)CLGraphDataFree(&fabricp->Graph, context); + memset(&fabricp->Graph, 0, sizeof(fabricp->Graph)); + + cl_qmap_init(&fabricp->map_guid_to_ib_device, NULL); + QListInitState(&fabricp->FIs); + if (!QListInit(&fabricp->FIs)) { + fprintf(stderr, "%s: Unable to initialize List\n", g_Top_cmdname); + goto fail; + } + QListInitState(&fabricp->Switches); + if (!QListInit(&fabricp->Switches)) { + fprintf(stderr, "%s: Unable to initialize List\n", g_Top_cmdname); + goto fail; + } + cl_qmap_init(&fabricp->Graph.Arcs, NULL); + cl_qmap_init(&fabricp->Graph.map_arc_key_to_arc, NULL); + cl_qmap_init(&fabricp->Graph.map_conn_to_vertex_conn, NULL); + + return FSUCCESS; + +fail: + return FERROR; +} + +//PYTHON: def add_device (fabric, guid, lid, hfi, name) : +NodeData* CLDataAddDevice(FabricData_t *fabricp, NodeData *nodep, STL_LID lid, int verbose, int quiet) +{ + cl_map_item_t *mi; + clDeviceData_t *ccDevicep; + + if (nodep) { + NodeData *p; + + //PYTHON: device = fabric.map_guid_to_ib_device.get(guid) + mi = cl_qmap_get(&fabricp->map_guid_to_ib_device, nodep->NodeInfo.NodeGUID); + if (mi != cl_qmap_end(&fabricp->map_guid_to_ib_device)) { + ccDevicep = PARENT_STRUCT(mi, clDeviceData_t, AllDevicesEntry); + if (verbose >= 5) + fprintf(stderr, "%s: Duplicate NodeGuids found in nodeRecords: 0x%"PRIx64"\n", + g_Top_cmdname, nodep->NodeInfo.NodeGUID); + + p = ccDevicep->nodep; + //PYTHON: if device.guid != guid or device.lid != lid or + //PYTHON: device.hfi != hfi or device.name != name : + if (ccDevicep->Lid != lid || + p->NodeInfo.NodeGUID != nodep->NodeInfo.NodeGUID || + p->NodeInfo.NodeType != nodep->NodeInfo.NodeType || + strcmp((char *)p->NodeDesc.NodeString, (char *)nodep->NodeDesc.NodeString)) { + if (verbose >= 5) + fprintf(stderr, "Warning, Duplicate device (%s, 0x%016"PRIx64", LID 0x%08x, %s) differs from (%s, 0x%016"PRIx64", LID 0x%04x, %s) with same GUID\n", + (char *)nodep->NodeDesc.NodeString, nodep->NodeInfo.NodeGUID, lid, StlNodeTypeToText(nodep->NodeInfo.NodeType), + (char *)p->NodeDesc.NodeString, p->NodeInfo.NodeGUID, ccDevicep->Lid, StlNodeTypeToText(p->NodeInfo.NodeType)); + } + return nodep; + } + + //PYTHON: device = IbDevice(fabric, guid, lid, hfi, name) + ccDevicep = (clDeviceData_t *)MemoryAllocate2AndClear(sizeof(clDeviceData_t), IBA_MEM_FLAG_PREMPTABLE, MYTAG); + if (!ccDevicep) { + fprintf(stderr, "%s: Unable to allocate memory\n", g_Top_cmdname); + return NULL; + } + + ccDevicep->nodep = nodep; + ccDevicep->Lid = lid; + cl_qmap_init(&ccDevicep->map_dlid_to_route, NULL); + //PYTHON: fabric.devices.append(device) + //PYTHON: fabric.map_guid_to_ib_device[guid] = device + mi = cl_qmap_insert(&fabricp->map_guid_to_ib_device, nodep->NodeInfo.NodeGUID, &ccDevicep->AllDevicesEntry); + if (mi != &ccDevicep->AllDevicesEntry) { + MemoryDeallocate(ccDevicep); + ccDevicep = PARENT_STRUCT(mi, clDeviceData_t, AllDevicesEntry); + fprintf(stderr, "Error, failed to add %s %s with GUID 0x%016"PRIx64" and LID 0x%08x\n", + StlNodeTypeToText(nodep->NodeInfo.NodeType), + (char *)nodep->NodeDesc.NodeString, + nodep->NodeInfo.NodeGUID, + lid); + return NULL; + } else { + ListItemInitState(&ccDevicep->AllDeviceTypesEntry); + QListSetObj(&ccDevicep->AllDeviceTypesEntry, ccDevicep); + + if (nodep->NodeInfo.NodeType == STL_NODE_FI) + QListInsertTail(&fabricp->FIs, &ccDevicep->AllDeviceTypesEntry); //PYTHON: fabric.hfis.append(device) + else + QListInsertTail(&fabricp->Switches, &ccDevicep->AllDeviceTypesEntry); //PYTHON: fabric.switches.append(device) + if (verbose >= 4 && !quiet) + ProgressPrint(TRUE, "Add %s %s with GUID 0x%016"PRIx64" and LID 0x%08x", + StlNodeTypeToText(nodep->NodeInfo.NodeType), + (char *)nodep->NodeDesc.NodeString, + nodep->NodeInfo.NodeGUID, + lid); + } + return nodep; + } + + return NULL; +} + +//PYTHON: def add_connection (fabric, guid1, port1, guid2, port2, rate) : +FSTATUS CLDataAddConnection(FabricData_t *fabricp, PortData *portp1, PortData *portp2, clConnPathData_t *pathInfo, uint8 sc, int verbose, int quiet) +{ + FSTATUS status = FSUCCESS; + cl_map_item_t *mi; + clConnData_t *ccConnp; + clDeviceData_t *ccDevicep; + + + //PYTHON: ib_device1 = fabric.map_guid_to_ib_device.get(guid1) + mi = cl_qmap_get(&fabricp->map_guid_to_ib_device, portp1->nodep->NodeInfo.NodeGUID); + if (mi == cl_qmap_end(&fabricp->map_guid_to_ib_device)) { + fprintf(stderr, "Error, add connection for missing device GUID 0x%016"PRIx64"\n", portp1->nodep->NodeInfo.NodeGUID); + return FINVALID_PARAMETER; + } + ccDevicep = PARENT_STRUCT(mi, clDeviceData_t, AllDevicesEntry); + + if (portp1->PortNum >= CREDIT_LOOP_DEVICE_MAX_CONNECTIONS) { + fprintf(stderr, "Error, port number %d exceeds maximum ports supported by a device\n", portp1->PortNum); + return FINVALID_PARAMETER; + } + + //PYTHON: connection = ib_device1.connections.get(port1) + ccConnp = ccDevicep->Connections[portp1->PortNum][sc]; + if (ccConnp) { + //PYTHON: if connection.guid1 != guid1 or connection.port1 != port1 or + //PYTHON: connection.guid2 != guid2 or connection.port2 != port2 or + //PYTHON: connection.rate != rate : + if ((ccConnp->FromDeviceGUID != portp1->nodep->NodeInfo.NodeGUID || ccConnp->FromPortNum != portp1->PortNum) || + (ccConnp->ToDeviceGUID != portp2->nodep->NodeInfo.NodeGUID || ccConnp->ToPortNum != portp2->PortNum) || + ((ccConnp->Rate && portp1->rate) && (ccConnp->Rate != portp1->rate))) { + status = FERROR; + fprintf(stderr, "Error, new connection (0x%016"PRIx64":%3.3u to 0x%016"PRIx64":%3.3u at rate %s) differs from (0x%016"PRIx64":%3.3u to 0x%016"PRIx64":%3.3u at rate %s)\n", + ccConnp->FromDeviceGUID, ccConnp->FromPortNum, ccConnp->ToDeviceGUID, ccConnp->ToPortNum, StlStaticRateToText(ccConnp->Rate), + portp1->nodep->NodeInfo.NodeGUID, portp1->PortNum, portp2->nodep->NodeInfo.NodeGUID, portp2->PortNum, StlStaticRateToText(portp1->rate)); + } + } else { + //PYTHON: ib_device1.connections[port1] = IbConnection(fabric, guid1, port1, guid2, port2, rate) + ccConnp = ccDevicep->Connections[portp1->PortNum][sc] = + (clConnData_t *)MemoryAllocate2AndClear(sizeof(clConnData_t), IBA_MEM_FLAG_PREMPTABLE, MYTAG); + + if (!ccConnp) { + status = FINSUFFICIENT_MEMORY; + fprintf(stderr, "%s: Unable to allocate memory\n", g_Top_cmdname); + } else { + //PYTHON: fabric.connections += 1 + fabricp->ConnectionCount++; + ccConnp->FromDeviceGUID = portp1->nodep->NodeInfo.NodeGUID; // GUID of the HFI, TFI, switch + ccConnp->FromPortNum = portp1->PortNum; + ccConnp->ToDeviceGUID = portp2->nodep->NodeInfo.NodeGUID; // GUID of the HFI, TFI, switch + ccConnp->ToPortNum = portp2->PortNum; + ccConnp->PathInfo = *pathInfo; + if (portp1->pQOS) + ccConnp->VL = portp1->pQOS->SC2VLMaps[Enum_SCVLt].SCVLMap[sc]; + + if (verbose >= 4 && !quiet) + ProgressPrint(TRUE, "Add connection 0x%016"PRIx64":%3.3u to 0x%016"PRIx64":%3.3u at rate %s", + portp1->nodep->NodeInfo.NodeGUID, portp1->PortNum, portp2->nodep->NodeInfo.NodeGUID, + portp2->PortNum, StlStaticRateToText(portp1->rate)); + } + } + + return status; +} + +//PYTHON: add_route(fabric, slid, dlid, route_sguid, route_sport) +FSTATUS CLDataAddRoute(FabricData_t *fabricp, STL_LID slid, STL_LID dlid, PortData *sportp, int verbose, int quiet) +{ + FSTATUS status = FSUCCESS; + cl_map_item_t *mi; + clDeviceData_t *ccDevicep; + clRouteData_t *ccRoutep = NULL; + + + //PYTHON: ib_device = fabric.map_guid_to_ib_device.get(guid) + //PYTHON: if not ib_device : + mi = cl_qmap_get(&fabricp->map_guid_to_ib_device, sportp->nodep->NodeInfo.NodeGUID); + if (mi == cl_qmap_end(&fabricp->map_guid_to_ib_device)) { + fprintf(stderr, "Warning, add connection for missing device GUID 0x%016"PRIx64"\n", sportp->nodep->NodeInfo.NodeGUID); + return FNOT_FOUND; + } + ccDevicep = PARENT_STRUCT(mi, clDeviceData_t, AllDevicesEntry); + + //PYTHON: route = ib_device.routes.get(dlid) + mi = cl_qmap_get(&ccDevicep->map_dlid_to_route, dlid); + if (mi != cl_qmap_end(&ccDevicep->map_dlid_to_route)) + ccRoutep = PARENT_STRUCT(mi, clRouteData_t, AllRoutesEntry); + + if (ccRoutep){ + if (ccRoutep->portp != sportp) { + status = FERROR; + fprintf(stderr, "Error, new route entry from SLID 0x%08x to DLID 0x%08x at 0x%016"PRIx64" has port %3.3u not expected port %3.3u\n", + slid, dlid, sportp->nodep->NodeInfo.NodeGUID, sportp->PortNum, ccRoutep->portp->PortNum); + } + } else { + ccRoutep = (clRouteData_t *)MemoryAllocate2AndClear(sizeof(clRouteData_t), IBA_MEM_FLAG_PREMPTABLE, MYTAG); + + if (!ccRoutep) { + status = FINSUFFICIENT_MEMORY; + fprintf(stderr, "%s: Unable to allocate memory\n", g_Top_cmdname); + } else { + //PYTHON: ib_device.routes[dlid] = port + ccRoutep->portp = sportp; + mi = cl_qmap_insert(&ccDevicep->map_dlid_to_route, dlid, &ccRoutep->AllRoutesEntry); + if (mi != &ccRoutep->AllRoutesEntry) { + if (verbose >= 4) { + fprintf(stderr, "%s: Duplicate DLID found in routes map: 0x%08x\n", g_Top_cmdname, dlid); + } + MemoryDeallocate(ccRoutep); + ccRoutep = PARENT_STRUCT(mi, clRouteData_t, AllRoutesEntry); + } else { + //PYTHON: fabric.routes += 1 + fabricp->RouteCount++; + if (verbose >= 4 && !quiet) + ProgressPrint(TRUE, "Add route SLID 0x%08x to DLID 0x%08x at GUID 0x%016"PRIx64" using port %3.3u", + slid, dlid, sportp->nodep->NodeInfo.NodeGUID, sportp->PortNum); + } + } + } + + return status; +} + +//PYTHON: def IbFabric.summary (self, name) : +void CLFabricSummary(FabricData_t *fabricp, const char *name, + ValidateCLFabricSummaryCallback_t callback, + uint32 totalPaths, uint32 totalBadPaths, + void *context) +{ + callback(fabricp, name, totalPaths, totalBadPaths, context); +} + +//PYTHON: def Graph.summary (self, name) : +void CLGraphDataSummary(clGraphData_t *graphp, const char *name, ValidateCLDataSummaryCallback_t callback, void *context) +{ + callback(graphp, name, context); +} + +FSTATUS CLFabricDataBuildRouteGraph(FabricData_t *fabricp, ValidateCLRouteSummaryCallback_t routeSummaryCallback, ValidateCLTimeGetCallback_t timeGetCallback, void *context, uint32 usedSLs) +{ + FSTATUS status = FSUCCESS; + uint32 i = 0, l = 0, t, threadsActive = 0; + LIST_ITEM *srcHcaLstp; + pthread_t threadId; + uint64_t sTime = 0, eTime = 0; + ValidateCreditLoopRoutesContext_t *cp = (ValidateCreditLoopRoutesContext_t *)context; + int xmlFmt = (cp->format == 1) ? 1 : 0; + int verbose = (xmlFmt) ? 0 : cp->detail; + uint32 maxHcaListEntry = QListCount(&fabricp->FIs) / CL_MAX_THREADS; + clThreadContext_t *threadContexts; + + + cl_qmap_init(&hopsHistogramLstMap, NULL); + if (hops_histogram != NULL) + memset(hops_histogram, 0, hops_histogram_length); + + threadContexts = + (clThreadContext_t *)MemoryAllocate2AndClear(sizeof(clThreadContext_t) * CL_MAX_THREADS, IBA_MEM_FLAG_PREMPTABLE, MYTAG); + + if (!threadContexts) { + status = FINSUFFICIENT_MEMORY; + fprintf(stderr, "%s: Unable to allocate thread contexts\n", g_Top_cmdname); + return status; + } + + if (!xmlFmt && verbose >= 3) { + timeGetCallback(&sTime, &g_cl_lock); + printf("START build graphical layout of all the routes\n"); + } + + pthread_mutex_init(&g_cl_lock, NULL); + + //PYTHON: for src_hfi in fabric.hfis : + if (QListCount(&fabricp->FIs) < 100) { + threadContexts[0].srcHcaList = QListHead(&fabricp->FIs); + + // determine whether to start worker thread + threadContexts[0].fabricp = fabricp; + threadContexts[0].verbose = verbose; + threadContexts[0].quiet = cp->quiet; + threadContexts[0].threadId = 0; + threadContexts[0].srcHcaListLength = QListCount(&fabricp->FIs); + threadContexts[0].timeGetCallback = timeGetCallback; + threadContexts[0].usedSLs = usedSLs; + threadsActive++; + pthread_create(&threadId, NULL, CLFabricDataBuildRouteGraphThread, &threadContexts[0]); + } else { + for (srcHcaLstp = QListHead(&fabricp->FIs); srcHcaLstp != NULL; srcHcaLstp = QListNext(&fabricp->FIs, srcHcaLstp)) { + // set first hfi entry to hfi list + if (l == 0) + threadContexts[i].srcHcaList = srcHcaLstp; + l++; + + // determine whether to start worker thread + if (i < CL_MAX_THREADS - 1 && l >= maxHcaListEntry) { + l = 0; + threadContexts[i].fabricp = fabricp; + threadContexts[i].verbose = verbose; + threadContexts[i].quiet = cp->quiet; + threadContexts[i].threadId = i; + threadContexts[i].srcHcaListLength = maxHcaListEntry; + threadContexts[i].timeGetCallback = timeGetCallback; + threadContexts[i].usedSLs = usedSLs; + threadsActive++; + pthread_create(&threadId, NULL, CLFabricDataBuildRouteGraphThread, &threadContexts[i++]); + } + } + + // start last worker thread + threadContexts[i].fabricp = fabricp; + threadContexts[i].verbose = verbose; + threadContexts[i].quiet = cp->quiet; + threadContexts[i].threadId = i; + threadContexts[i].srcHcaListLength = maxHcaListEntry + (QListCount(&fabricp->FIs) % CL_MAX_THREADS); + threadContexts[i].timeGetCallback = timeGetCallback; + threadContexts[i].usedSLs = usedSLs; + threadsActive++; + pthread_create(&threadId, NULL, CLFabricDataBuildRouteGraphThread, &threadContexts[i]); + } + + // + // wait for worker threads to complete processing + while (threadsActive > 0) { + (void)CLThreadSleep(VTIMER_1_MILLISEC); + for (t = 0; t < CL_MAX_THREADS; t++) { + if (threadContexts[t].threadExit) { + threadContexts[t].threadExit = 0; + threadsActive--; + } + } + } + + // clear line used to display progress report + if (!cp->quiet) + ProgressPrint(TRUE, "Done Building Graphical Layout of All Routes"); + + if (!xmlFmt && verbose >= 3) { + timeGetCallback(&eTime, &g_cl_lock); + printf("END build graphical layout of all the routes; elapsed time(usec)=%d, (sec)=%d\n", + (int)(eTime - sTime), ((int)(eTime - sTime)) / CL_TIME_DIVISOR); + } + + // + // report routes summary + if (hops_histogram != NULL) { + if (verbose >= 3) + routeSummaryCallback(present_routes, missing_routes, hops_histogram_entries, hops_histogram, context); + MemoryDeallocate(hops_histogram); + } + MemoryDeallocate(threadContexts); + + return status; +} + +//PYTHON: Graph.def split (self) : +clGraphData_t* CLGraphDataSplit(clGraphData_t *graphp, int verbose) +{ + uint32 vv; + clGraphData_t *newGraphp; + clVertixData_t *rootVertexp = NULL; //PYTHON: root = None + + + //PYTHON: for vertex in self.vertices : + for (vv = 0; vv < graphp->NumVertices; vv++) { + clVertixData_t *vertexp = graphp->Vertices[vv]; + + //PYTHON: if vertex.refcount : + if (vertexp->RefCount) { + rootVertexp = vertexp; //PYTHON: root = vertex + break; + } + } + + //PYTHON: if not root : + if (!rootVertexp) + return NULL; + + //PYTHON: new_graph = Graph() + newGraphp = (clGraphData_t *)MemoryAllocate2AndClear(sizeof(clGraphData_t), IBA_MEM_FLAG_PREMPTABLE, MYTAG); + if (!newGraphp) { + fprintf(stderr, "%s: Unable to allocate memory\n", g_Top_cmdname); + } else { + cl_qmap_init(&newGraphp->Arcs, NULL); + cl_qmap_init(&newGraphp->map_arc_key_to_arc, NULL); + //PYTHON: self.split_out_vertex(new_graph, root); + CLGraphDataSplitOutVertex(graphp, newGraphp, rootVertexp, verbose); + } + return newGraphp; +} + +void CLGraphDataPrune(clGraphData_t *graphp, ValidateCLTimeGetCallback_t timeGetCallback, int verbose, int quiet) +{ + uint32 ii, vv, progress = 1, round = 0; + uint64_t sTime = 0, eTime = 0; + + if (verbose >= 3 && !quiet) { + timeGetCallback(&sTime, &g_cl_lock); + ProgressPrint(TRUE, "START pruning of graphical layout of all the routes"); + } + + //PYTHON: progress = 1; + //PYTHON: round = 0; + //PYTHON: while progress : + while (progress) { // DEBUG_CODE --- Possible infinite loop, look into later???? + progress = 0; + //PYTHON: for vertex in self.vertices : + for (vv = 0; vv < graphp->NumVertices; vv++) { + clVertixData_t *vertexp = graphp->Vertices[vv]; + + //PYTHON: if vertex.refcount : + if (vertexp->RefCount) { + //PYTHON: if len(vertexp->outbound) == 0 : + if (vertexp->OutboundInuseCount == 0) { + //PYTHON: for arc_id in vertexp->inbound : + for (ii = 0; ii < vertexp->InboundCount; ii++) { + if (vertexp->Inbound[ii] >= 0) { + if (verbose >= 4 && !quiet) + ProgressPrint(TRUE, "Remove arc id %d since vertex id %d is pure sink", + vertexp->Inbound[ii], vertexp->Id); + //PYTHON: self.del_arc(arc_id); + CLGraphDataDelArc(graphp, vertexp->Inbound[ii]); + //PYTHON: progress += 1 + progress++; + } + } + } + + //PYTHON: if len(vertexp->inbound) == 0 : + if (vertexp->InboundInuseCount == 0) { + //PYTHON: for arc_id in vertex.outbound : + for (ii = 0; ii < vertexp->OutboundCount; ii++) { + if (vertexp->Outbound[ii] >= 0) { + if (verbose >= 4 && !quiet) + ProgressPrint(TRUE, "Remove arc id %d since vertex id %d is pure source", + vertexp->Outbound[ii], vertexp->Id); + //PYTHON: self.del_arc(arc_id); + CLGraphDataDelArc(graphp, vertexp->Outbound[ii]); + //PYTHON: progress += 1 + progress++; + } + } + } + } + } + + //PYTHON: round += 1 + round++; + if (verbose >= 4 && !quiet) + ProgressPrint(TRUE, "Graph pruning round %d : deleted %d arcs", round, progress); + } + + if (verbose >= 3 && !quiet) { + timeGetCallback(&eTime, &g_cl_lock); + ProgressPrint(TRUE, "END pruning of graphical layout of all the routes; elapsed time(usec)=%d, (sec)=%d", + (int)(eTime - sTime), ((int)(eTime - sTime)) / CL_TIME_DIVISOR); + } +} + +void CLDijkstraFreeDistancesAndRoutes(clDijkstraDistancesAndRoutes_t *drp) +{ + if (drp->distances) + (void)CLDijkstraFreeArray((void **)drp->distances, drp->nRows); + if (drp->routes) + (void)CLDijkstraFreeArray((void **)drp->routes, drp->nRows); + memset(drp, 0, sizeof(clDijkstraDistancesAndRoutes_t)); +} + +//PYTHON: def find_distances_and_routes_dijkstra (graph) : +FSTATUS CLDijkstraFindDistancesAndRoutes(clGraphData_t *graphp, clDijkstraDistancesAndRoutes_t *respData, int verbose) +{ + FSTATUS status = FERROR; + int c; + uint32 nRows, nCols; + uint32 ii, jj, d, current = 0; + uint32 next, numVertices, maxDistance; + uint32 **distances = NULL,**routes = NULL; + clVertixData_t *i = NULL,*j = NULL; + uint32 *dist = NULL,*route = NULL,*previous = NULL; + cl_qmap_t previousLstMap; + + + // allocate persistant multidimensional arrays and temporary buffers + if (!graphp || !respData) + return FINVALID_PARAMETER; + nRows = graphp->VerticesLength; + nCols = graphp->VerticesLength; + if (!(distances = (uint32 **)CLDijkstraAllocArray(nRows, nCols, sizeof(uint32))) || //PYTHON: distances = {} + !(routes = (uint32 **)CLDijkstraAllocArray(nRows, nCols, sizeof(uint32))) || //PYTHON: routes = {} + !(dist = MemoryAllocate2AndClear(nCols * sizeof(uint32), IBA_MEM_FLAG_PREMPTABLE, MYTAG)) || + !(route = MemoryAllocate2AndClear(nCols * sizeof(uint32), IBA_MEM_FLAG_PREMPTABLE, MYTAG)) || + !(previous = MemoryAllocate2AndClear(nCols * sizeof(uint32), IBA_MEM_FLAG_PREMPTABLE, MYTAG)) || + !(routesLstMap = MemoryAllocate2AndClear(nRows * sizeof(cl_qmap_t), IBA_MEM_FLAG_PREMPTABLE, MYTAG))) { + status = FINSUFFICIENT_MEMORY; + fprintf(stderr, "%s: Unable to allocate memory\n", g_Top_cmdname); + goto fail; + } + + //PYTHON: num_vertices = graph.num_vertices + numVertices = graphp->NumVertices; + if (verbose >= 3) + printf("Calculating distances for %d vertices in graph\n", numVertices); + + //PYTHON: for i in graph.vertices : + for (ii = 0; ii < graphp->VerticesLength; ii++) { + cl_qmap_t todo; + + //PYTHON: if i.refcount : + if ((i = graphp->Vertices[ii]) && i->RefCount) { + //PYTHON: dist = {} + memset(dist, 0, sizeof(nCols * sizeof(uint32))); + //PYTHON: previous = {} + memset(previous, 0, sizeof(nCols * sizeof(uint32))); + //PYTHON: todo = [] + cl_qmap_init(&todo, NULL); + cl_qmap_init(&routesLstMap[i->Id], NULL); + // CJKING: Note, in order to save time, purposely not deallocating memory + // allocated for each list entry. May need to visit this later for extremely + // large fabrics. + cl_qmap_init(&previousLstMap, NULL); + + //PYTHON: for j in graph.vertices : + for (jj = 0; jj < graphp->VerticesLength; jj++) { + if ((j = graphp->Vertices[jj]) && j->RefCount) { + dist[j->Id] = DIJKSTRA_INFINITY; + //PYTHON: todo.append(j.id) + if (!CLDijkstraAddVertexDistance(&todo, j, verbose)) + goto fail; + //PYTHON: previous[j.id] = None + previous[j->Id] = 0; + } + } + + //PYTHON: dist[i.id] = 0 + dist[i->Id] = 0; + //PYTHON: previous[i.id] = i.id + previous[i->Id] = i->Id; + //CJKING: Add entry to search list for previous array + if (CLListUint32Add(&previousLstMap, i->Id)) + goto fail; + + //current = i + current = ii; + + //while todo : + while (cl_qmap_count(&todo)) { + /*CJKING: Not certain of the purpose of this code in the script. + + PYTHON: global vertex_dist + PYTHON: vertex_dist = dist + PYTHON: todo.sort(vertex_distance_compare) + PYTHON: vertex_dist = {} + */ + + //PYTHON: current = todo.pop(0) + if (-1 == (current = CLDijkstraVertexPopDistance(&todo))) { + if (verbose >= 3) + fprintf(stderr, "Warning, pop of vertices list failed\n"); + break; + } + + //PYTHON: if dist[current] == infinity : + if (verbose >= 4 && dist[current] == DIJKSTRA_INFINITY) { + fprintf(stderr, "Warning, distance of current id %d should not be infinite for fully connected graph\n", current); + } + + //PYTHON: for c in graph.vertices[current].outbound : + for (c = 0; c < graphp->Vertices[current]->OutboundCount; c++) { + clVertixData_t *j; + clArcData_t *arcp; + + if (graphp->Vertices[current]->Outbound[c] >= 0 && (arcp = CLGraphFindIdArc(graphp, graphp->Vertices[current]->Outbound[c]))) { + //PYTHON: j = graph.vertices[graph.arcs[c].sink] + j = graphp->Vertices[arcp->Sink]; + + //PYTHON: if not j : + if (!j) + fprintf(stderr, "Warning, cannot follow connection for vertex %d\n", current); + else { //PYTHON: elif j.id in todo : /* CJKING: Unclear about this elif. Might use the following */ + /* else if (CLDijkstraIsVertexDistance(&todo, j->Id)) */ + //PYTHON: d = dist[current] + 1 + d = dist[current] + 1; + //PYTHON: if d < dist[j.id] : + if (d < dist[j->Id]) { + if (verbose >= 4) + printf("Distance from %d to %d reduces from %d to %d (via %d)\n", + i->Id, j->Id, dist[j->Id], d, current); + //PYTHON: dist[j.id] = d + dist[j->Id] = d; + //PYTHON: previous[j.id] = current + previous[j->Id] = current; + //CJKING: Add entry to search list for previous array + if (CLListUint32Add(&previousLstMap, current)) + goto fail; + } + } + } + } + } + + //PYTHON: route = {} + memset(route, 0, sizeof(nCols * sizeof(uint32))); + //PYTHON: for j in graph.vertices : + for (jj = 0; jj < graphp->VerticesLength; jj++) { + //PYTHON: if j.refcount and dist[j.id] != infinity : + if ((j = graphp->Vertices[jj]) && j->RefCount && (dist[j->Id] != DIJKSTRA_INFINITY)) { + if (verbose >= 4) + printf("Route backwards from vertex %d\n", j->Id); + + //PYTHON: current = j.id + current = j->Id; + //PYTHON: next = current + next = current; + + //PYTHON: while current != i.id : + while (current != i->Id) { + //next = current + next = current; + //PYTHON: if not current in previous : + //CJKING: if (!CLListUint32Find(current, previous, nCols, verbose)) { + if (!CLListUint32Find(&previousLstMap, current)) { + if (verbose >= 5) + fprintf(stderr, "Warning, cannot route backwards from vertex %d to %d at %d\n", + j->Id, i->Id, current); + } + + //PYTHON: current = previous[current] + current = previous[current]; + if (verbose >= 4 && next != j->Id) + printf("\tvia %d\n", next); + } + + if (verbose >= 4) + printf("\tto %d (next is %d)\n", i->Id, next); + //PYTHON: route[j.id] = next + route[j->Id] = next; + //CJKING: Add entry to search list for route array + if (CLListUint32Add(&routesLstMap[i->Id], next)) + goto fail; + } + } + + //PYTHON: routes[i.id] = route + //PYTHON: distances[i.id] = dist + memcpy(routes[i->Id], route, nCols); + memcpy(distances[i->Id], dist, nCols); + } + } + + // recompute distance to self for shortest loop (instead of 0) + //PYTHON: for i in graph.vertices : + for (ii = 0; ii < graphp->VerticesLength; ii++) { + //PYTHON: if i.refcount : + if ((i = graphp->Vertices[ii]) && i->RefCount) { + uint32 route = 0; //PYTHON: route = None + + //PYTHON: d = infinity + d = DIJKSTRA_INFINITY; + + //PYTHON: for c in graph.vertices[i.id].outbound : + for (c = 0; c < graphp->Vertices[i->Id]->OutboundCount; c++) { + clVertixData_t *j; + clArcData_t *arcp; + + if (graphp->Vertices[i->Id]->Outbound[c] >= 0 && (arcp = CLGraphFindIdArc(graphp, graphp->Vertices[i->Id]->Outbound[c]))) { + //PYTHON: j = graph.vertices[graph.arcs[c].sink] + j = graphp->Vertices[arcp->Sink]; + //PYTHON: if not j : + if (!j) + fprintf(stderr, "Warning, cannot follow connection for vertex %d\n", i->Id); + else if (distances[j->Id][i->Id] < d) { //PYTHON: elif distances[j.id][i.id] < d : + //PYTHON: d = distances[j.id][i.id] + 1 + d = distances[j->Id][i->Id] + 1; + //PYTHON: route = j.id + route = j->Id; + } + } + } + + //PYTHON: if d == infinity : + if (d == DIJKSTRA_INFINITY) { + if (verbose >= 5) + printf("Self-distance for %d is infinite (no routes to self)\n", i->Id); + } else { + //PYTHON: distances[i.id][i.id] = d + distances[i->Id][i->Id] = d; + //PYTHON: routes[i.id][i.id] = route + routes[i->Id][i->Id] = route; + if (verbose >= 4) + printf("Self-distance for %d is %d via %d\n", i->Id, d, route); + } + } + } + + //PYTHON: max_distance = 0 + maxDistance = 0; + //PYTHON: for i in graph.vertices : + for (ii = 0; ii < graphp->VerticesLength; ii++) { + if ((i = graphp->Vertices[ii])) { + //PYTHON: for j in graph.vertices : + for (jj = 0; jj < graphp->VerticesLength; jj++) { + //PYTHON: if i.refcount and j.refcount : + if (i->RefCount && ((j = graphp->Vertices[jj]) && j->RefCount)) { + //PYTHON: d = get_distance(distances, i.id, j.id) + if (FERROR == (status = CLDijkstraGetDistance(distances, nRows, nCols, i->Id, j->Id, &d))) { + fprintf(stderr, "Error, unable to get distance from vertex %d to vertex %d\n", i->Id, j->Id); + goto fail; + } + + if (verbose >= 5 && d == DIJKSTRA_INFINITY) + fprintf(stderr, "Warning, no path from %d to %d\n", i->Id, j->Id); + else if (verbose >= 4 && d != DIJKSTRA_INFINITY) + printf("Distance from vertex %d to vertex %d is %d arcs\n", + i->Id, j->Id, d); + + //PYTHON: if d > max_distance and d != infinity : + if (d > maxDistance && d != DIJKSTRA_INFINITY) + maxDistance = d; //PYTHON: max_distance = d + } + } + } + } + + if (verbose >= 3) + printf("Maximum distance is %d\n", maxDistance); + + // deallocate temporary buffers + if (dist) + MemoryDeallocate(dist); + if (route) + MemoryDeallocate(route); + if (previous) + MemoryDeallocate(previous); + + //PYTHON: check_distances_and_routes(graph, distances, routes) + CLDijkstraCheckDistancesAndRoutes(graphp, distances, routes, nRows, nCols, verbose); + + // initialize response data + respData->distances = distances; + respData->routes = routes; + respData->nRows = nRows; + respData->nCols = nCols; + + return FSUCCESS; + +fail: + + // deallocate multidimensional arrays + (void)CLDijkstraFreeArray((void **)distances, nRows); + (void)CLDijkstraFreeArray((void **)routes, nRows); + + // deallocate temporary buffers + if (dist) + MemoryDeallocate(dist); + if (route) + MemoryDeallocate(route); + if (previous) + MemoryDeallocate(previous); + + return status; +} + +//PYTHON: def find_cycles (graph, distances, routes, fn) : +void CLDijkstraFindCycles(FabricData_t *fabricp, + clGraphData_t *graphp, + clDijkstraDistancesAndRoutes_t *drp, + ValidateCLLinkSummaryCallback_t linkSummaryCallback, + ValidateCLLinkStepSummaryCallback_t linkStepSummaryCallback, + ValidateCLPathSummaryCallback_t pathSummaryCallback, + void *context) +{ + uint32 ii, dii, next_id, cycles = 0; //PYTHON: cycles = 0 + int done_vertices_entries = 0, *done_vertices = NULL; + uint32 cycle_histogram_entries = 0, *cycle_histogram = NULL, *distance_list = NULL; + clVertixData_t *i = NULL; + ValidateCreditLoopRoutesContext_t *cp = (ValidateCreditLoopRoutesContext_t *)context; + int xmlFmt = (cp->format == 1) ? 1 : 0; + int verbose = (xmlFmt) ? 0 : cp->detail; + cl_qmap_t cycleHistogramLstMap, doneVerticesLstMap; + + + if (!(done_vertices = MemoryAllocate2AndClear(drp->nCols * sizeof(int), IBA_MEM_FLAG_PREMPTABLE, MYTAG)) || //PYTHON: done_vertices = [] + !(cycle_histogram = MemoryAllocate2AndClear(drp->nCols * sizeof(uint32), IBA_MEM_FLAG_PREMPTABLE, MYTAG)) || //PYTHON: cycle_histogram = {} + !(distance_list = MemoryAllocate2AndClear(drp->nCols * sizeof(uint32), IBA_MEM_FLAG_PREMPTABLE, MYTAG))) { + fprintf(stderr, "%s: Unable to allocate memory\n", g_Top_cmdname); + goto done; + } + + cl_qmap_init(&doneVerticesLstMap, NULL); + cl_qmap_init(&cycleHistogramLstMap, NULL); + memset(done_vertices, -1, sizeof(*done_vertices) * drp->nCols); + + //PYTHON: for i in graph.vertices : + for (ii = 0; ii < graphp->VerticesLength; ii++) { + //PYTHON: if i.refcount and not i.id in done_vertices : + if ((i = graphp->Vertices[ii]) && + (i->RefCount && !CLListIntFind(&doneVerticesLstMap, i->Id))) { //CJKING: (i->RefCount && !ListIntFind(i->Id, done_vertices, done_vertices_entries, verbose))) { + //PYTHON: dii = get_distance(distances, i.id, i.id) + if (FERROR == CLDijkstraGetDistance(drp->distances, drp->nRows, drp->nCols, i->Id, i->Id, &dii)) { + fprintf(stderr, "Error, unable to find cycles: distances not specified\n"); + goto done; + } + + //PYTHON: if dii != infinity : + if (dii != DIJKSTRA_INFINITY) { + int indent = cp->indent; //4; + uint32 step; + clVertixData_t *j; + + if (dii || verbose >= 3) { + (void)linkSummaryCallback(i->Id, ib_connection_source_to_str(fabricp, i->Connection), dii, 1, indent, context); + if (verbose >= 4) + (void)pathSummaryCallback(fabricp, i->Connection, indent + 4, context); + } + + j = i; //PYTHON: j = i + cycles++; //PYTHON: cycles += 1 + + //PYTHON: if dii in cycle_histogram : + //CJKING: if (CLListUint32Find(dii, cycle_histogram, drp->nCols, verbose)) + if (CLListUint32Find(&cycleHistogramLstMap, dii)) + cycle_histogram[dii]++; //PYTHON: cycle_histogram[dii] += 1 + else { + //CJKING: Add entry to search list for cycle_histogram array + if (CLListUint32Add(&cycleHistogramLstMap, dii)) + goto done; + else + cycle_histogram[dii] = 1; //PYTHON: cycle_histogram[dii] = 1 + } + cycle_histogram_entries = MAX(cycle_histogram_entries, dii); + + //PYTHON: if routes : + if (drp->routes) { + //PYTHON: for step in range(0, dii) : + for (step = 0; step < dii; step++) { + (void)linkStepSummaryCallback(j->Id, ib_connection_source_to_str(fabricp, j->Connection), step, 1, indent + 4, context); + if (verbose >= 4) + (void)pathSummaryCallback(fabricp, j->Connection, indent + 8, context); + // insert XML token to indicate the end of link step summary section + if (xmlFmt) + (void)linkStepSummaryCallback(0, 0, 0, 0, indent + 4, context); + + done_vertices[done_vertices_entries++] = j->Id; //PYTHON: done_vertices.append(j.id) + //CJKING: Add entry to search list for done_vertices array + if (CLListIntAdd(&doneVerticesLstMap, j->Id)) + goto done; + next_id = drp->routes[j->Id][i->Id]; //PYTHON: next_id = routes[j.id][i.id] + j = graphp->Vertices[next_id]; //PYTHON: j = graph.vertices[next_id] + } + } else { + uint8 found = 0; + + //PYTHON: for step in range(0, dii) : + for (step = 0; step < dii; step++) { + uint32 jj; + + (void)linkStepSummaryCallback(j->Id, ib_connection_source_to_str(fabricp, j->Connection), step, 1, indent + 4, context); + if (verbose >= 4) + (void)pathSummaryCallback(fabricp, j->Connection, indent + 8, context); + // insert XML token to indicate the end of link step summary section + if (xmlFmt) + (void)linkStepSummaryCallback(0, 0, 0, 0, indent + 4/*indent*/, context); + + done_vertices[done_vertices_entries++] = j->Id; //PYTHON: done_vertices.append(j.id) + //CJKING: Add entry to search list for done_vertices array + if (CLListIntAdd(&doneVerticesLstMap, j->Id)) + goto done; + found = 0; + memset(distance_list, 0, sizeof(drp->nCols * sizeof(uint32))); //PYTHON: distance_list = [] + + //PYTHON: for arc_id in j.outbound : + for (jj = 0; jj < j->OutboundCount; jj++) { + clVertixData_t *k; + clArcData_t *arcp; + + if (!(j->Outbound[jj] >= 0 && (arcp = CLGraphFindIdArc(graphp, j->Outbound[jj])))) { + fprintf(stderr, "Warning, arc not available cannot follow connection for vertex %d\n", jj); + continue; + } + + //PYTHON: k = graph.vertices[graph.arcs[arc_id].sink] + k = graphp->Vertices[arcp->Sink]; + //PYTHON: if k.refcount : + if (k->RefCount) { + uint32 dki; + + //PYTHON: dki = get_distance(distances, k.id, i.id) + if (FERROR == CLDijkstraGetDistance(drp->distances, drp->nRows, drp->nCols, k->Id, i->Id, &dki)) { + fprintf(stderr, "Error, unable to find cycles: distances not specified\n"); + goto done; + } + /* + #print ' %d: vertex %d via arc %d to vertex %d' % \ + # (step, j.id, arc_id, k.id) + found = 1 + j = k + */ + //PYTHON: if dki != infinity : + if (dki != DIJKSTRA_INFINITY) + distance_list[dki] = dki; //PYTHON: distance_list.append(dki) + + if (dki != DIJKSTRA_INFINITY && //PYTHON: if dki != infinity and + ((dki == dii - step - 1) || //PYTHON: ((dki == dii - step - 1) or + (k->Id == i->Id && step == dii - 1))) { //PYTHON: (k.id == i.id and step == dii - 1)) + //printf(" %d: vertex %d via arc %d to vertex %d\N", step, j->Id, arc_id, k->Id); + found = 1; //PYTHON: found = 1 + j = k; //PYTHON: j = k + } + break; + } + } + //PYTHON: if not found : + if (!found) { + char *s = ib_connection_source_to_str(fabricp, i->Connection); + printf(" %d: could not find cycle for vertex %d (%s) on step %d of %d (warning), looking for distance %d\n", + step, i->Id, (s)?(s):"", step, dii, dii - step - 1); + break; + } + } + } + + // insert XML token to indicate the end of link summary section + if (xmlFmt) + (void)linkSummaryCallback(0, 0, 0, 0, cp->indent/*0*/, context); + } + } + } + + if (verbose >= 3) { + if (!cycles) + printf("Routes are deadlock free!\n"); + else { + uint32 c; + + printf("Deadlock - dependency graph routes contain %d cycle(s):\n", cycles); + //PYTHON: for c in cycle_histogram : + for (c = 0; c < cycle_histogram_entries; c++) printf(" %d cycle(s) of circumference %d\n", cycle_histogram[c], c); + } + } + +done: + + if (done_vertices) + MemoryDeallocate(done_vertices); + if (cycle_histogram) + MemoryDeallocate(cycle_histogram); + if (distance_list) + MemoryDeallocate(distance_list); +} + +#endif diff --git a/Topology/focus.c b/Topology/focus.c new file mode 100644 index 0000000..d992fdd --- /dev/null +++ b/Topology/focus.c @@ -0,0 +1,2273 @@ +/* BEGIN_ICS_COPYRIGHT7 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT7 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +#include "topology.h" +#include "topology_internal.h" + +#ifndef __VXWORKS__ +#include +#include +#else +#include "icsBspUtil.h" +#endif + +#define FILENAME 256 //Length of file name +#define MIN_LIST_ITEMS 100 // minimum items for ListInit to allocate for +#define NODE_PAIR_DELIMITER_SIZE 1 //Length of delimiter while parsing for node pairs + + + +// Functions to Parse Focus arguments and build POINTs for matches +typedef boolean (PointPortElinkCompareCallback_t)(ExpectedLink *elinkp, void *nodecmp, uint8 portnum); +static FSTATUS ParsePointPort(FabricData_t *fabricp, char *arg, Point *pPoint, uint8 find_flag, PointPortElinkCompareCallback_t *callback, void *nodecmp, char **pp); + +/* check arg to see if 1st characters match prefix, if so return pointer + * into arg just after prefix, otherwise return NULL + */ +char* ComparePrefix(char *arg, const char *prefix) +{ + int len = strlen(prefix); + if (strncmp(arg, prefix, len) == 0) + return arg+len; + else + return NULL; +} + +static FSTATUS ParseGidPoint(FabricData_t *fabricp, char *arg, Point *pPoint, uint8 find_flag, char **pp) +{ + IB_GID gid; + + ASSERT(! PointValid(pPoint)); + if (FSUCCESS != StringToGid(&gid.AsReg64s.H, &gid.AsReg64s.L, arg, pp, TRUE)) { + fprintf(stderr, "%s: Invalid GID format: '%s'\n", g_Top_cmdname, arg); + return FINVALID_PARAMETER; + } + if (! gid.AsReg64s.H || ! gid.AsReg64s.L) { + fprintf(stderr, "%s: Invalid GID: 0x%016"PRIx64":0x%016"PRIx64"\n", + g_Top_cmdname, gid.AsReg64s.H, gid.AsReg64s.L); + return FINVALID_PARAMETER; + } +#if 0 + /* This could be an optimization of the error case, testing SubnetPrefix + * below should be sufficient until we encounter IB routers + */ + /* TBD - if we allow for MC GIDs, this test is inappropriate */ + /* TBD - cleanup use of g_portAttrib global */ + if (g_portAttrib + && gid.Type.Global.SubnetPrefix != g_portAttrib->GIDTable[0].Type.Global.SubnetPrefix) { + fprintf(stderr, "%s: Invalid GID: 0x%016"PRIx64":0x%016"PRIx64"\n", + g_Top_cmdname, + gid.Type.Global.SubnetPrefix, gid.Type.Global.InterfaceID); + fprintf(stderr, "%s: Subnet Prefix: 0x%016"PRIx64" does not match local port: 0x%016"PRIx64"\n", + g_Top_cmdname, gid.Type.Global.SubnetPrefix, + g_portAttrib->GIDTable[0].Type.Global.SubnetPrefix); + return FNOT_FOUND; + } +#endif + return FindGidPoint(fabricp, gid, pPoint, find_flag, 0); +} + +static FSTATUS ParseLidPoint(FabricData_t *fabricp, char *arg, Point *pPoint, uint8 find_flag, char **pp) +{ + STL_LID lid; + PortData *portp = NULL; + char *param; + + ASSERT(! PointValid(pPoint)); + if (FSUCCESS != StringToUint32(&lid, arg, pp, 0, TRUE)) { + fprintf(stderr, "%s: Invalid LID format: '%s'\n", g_Top_cmdname, arg); + return FINVALID_PARAMETER; + } + if (! lid) { + fprintf(stderr, "%s: Invalid LID: 0x%x\n", g_Top_cmdname, lid); + return FINVALID_PARAMETER; + } + + if (0 == (find_flag & FIND_FLAG_FABRIC)) + return FINVALID_OPERATION; + if (find_flag & FIND_FLAG_FABRIC) { + portp = FindLid(fabricp, lid); + if (portp) { + pPoint->u.portp = portp; + pPoint->Type = POINT_TYPE_PORT; + } + } + // N/A for FIND_FLAG_ENODE, FIND_FLAG_ESM and FIND_FLAG_ELINK + if (PointValid(pPoint)) { + ASSERT(portp); // since we only handle FIND_FLAG_FABRIC + if (NULL != (param = ComparePrefix(*pp, ":node"))) { + *pp = param; + pPoint->u.nodep = portp->nodep; + pPoint->Type = POINT_TYPE_NODE; + } else if (NULL != (param = ComparePrefix(*pp, ":port:"))) { + pPoint->u.nodep = portp->nodep; + pPoint->Type = POINT_TYPE_NODE; + return ParsePointPort(fabricp, param, pPoint, find_flag, NULL, NULL, pp); + } + return FSUCCESS; + } else { + fprintf(stderr, "%s: LID Not Found: 0x%x\n", g_Top_cmdname, lid); + return FNOT_FOUND; + } +} + +static FSTATUS ParsePortGuidPoint(FabricData_t *fabricp, char *arg, Point *pPoint, uint8 find_flag, char **pp) +{ + EUI64 guid; + + ASSERT(! PointValid(pPoint)); + if (FSUCCESS != StringToUint64(&guid, arg, pp, 0, TRUE)) { + fprintf(stderr, "%s: Invalid Port GUID format: '%s'\n", + g_Top_cmdname, arg); + return FINVALID_PARAMETER; + } + if (! guid) { + fprintf(stderr, "%s: Invalid Port GUID: 0x%016"PRIx64"\n", + g_Top_cmdname, guid); + return FINVALID_PARAMETER; + } + return FindPortGuidPoint(fabricp, guid, pPoint, find_flag, 0); +} + +/* Parse a :port:# suffix, this will limit the Point to the list of ports + * with the given number + */ +static FSTATUS ParsePointPort(FabricData_t *fabricp, char *arg, Point *pPoint, uint8 find_flag, PointPortElinkCompareCallback_t *callback, void *nodecmp, char **pp) +{ + uint8 portnum; + FSTATUS status; + Point newPoint; + boolean fabric_fail = FALSE; + + ASSERT(PointValid(pPoint)); + PointInit(&newPoint); + if (FSUCCESS != StringToUint8(&portnum, arg, pp, 0, TRUE)) { + fprintf(stderr, "%s: Invalid Port Number format: '%s'\n", + g_Top_cmdname, arg); + status = FINVALID_PARAMETER; + goto fail; + } + // for fabric we try to provide a more detailed message using the + // fabric_fail flag and leaving some of the information in the pPoint + if (find_flag & FIND_FLAG_FABRIC) { + switch (pPoint->Type) { + case POINT_TYPE_NONE: + break; + case POINT_TYPE_PORT: + ASSERT(0); // should not be called for this type of point + status = FINVALID_PARAMETER; + goto fail; + case POINT_TYPE_PORT_LIST: + ASSERT(0); // should not be called for this type of point + status = FINVALID_PARAMETER; + goto fail; + case POINT_TYPE_NODE_PAIR_LIST: + ASSERT(0); // should not be called for this type of point + status = FINVALID_PARAMETER; + goto fail; + case POINT_TYPE_NODE: + { + PortData *portp = FindNodePort(pPoint->u.nodep, portnum); + if (! portp) { + fabric_fail = TRUE; + } else { + pPoint->Type = POINT_TYPE_PORT; + pPoint->u.portp = portp; + } + } + break; + case POINT_TYPE_NODE_LIST: + { + LIST_ITERATOR i; + DLIST *pNodeList = &pPoint->u.nodeList; + + for (i=ListHead(pNodeList); i != NULL; i = ListNext(pNodeList, i)) { + NodeData *nodep = (NodeData*)ListObj(i); + PortData *portp = FindNodePort(nodep, portnum); + if (portp) { + status = PointListAppend(&newPoint, POINT_TYPE_PORT_LIST, portp); + if (FSUCCESS != status) + goto fail; + } + } + if (! PointValid(&newPoint)) { + fabric_fail = TRUE; + } else { + PointFabricCompress(&newPoint); + status = PointFabricCopy(pPoint, &newPoint); + PointDestroy(&newPoint); + if (FSUCCESS != status) + goto fail; + } + } + break; +#if !defined(VXWORKS) || defined(BUILD_DMC) + case POINT_TYPE_IOC: + { + PortData *portp = FindNodePort(pPoint->u.iocp->ioup->nodep, portnum); + if (! portp) { + fabric_fail = TRUE; + } else { + pPoint->Type = POINT_TYPE_PORT; + pPoint->u.portp = portp; + } + } + break; + case POINT_TYPE_IOC_LIST: + { + LIST_ITERATOR i; + DLIST *pIocList = &pPoint->u.iocList; + + for (i=ListHead(pIocList); i != NULL; i = ListNext(pIocList, i)) { + IocData *iocp = (IocData*)ListObj(i); + PortData *portp = FindNodePort(iocp->ioup->nodep, portnum); + if (portp) { + status = PointListAppend(&newPoint, POINT_TYPE_PORT_LIST, portp); + if (FSUCCESS != status) + goto fail; + } + } + if (! PointValid(&newPoint)) { + fabric_fail = TRUE; + } else { + PointFabricCompress(&newPoint); + status = PointFabricCopy(pPoint, &newPoint); + PointDestroy(&newPoint); + if (FSUCCESS != status) + goto fail; + } + } + break; +#endif + case POINT_TYPE_SYSTEM: + { + cl_map_item_t *p; + SystemData *systemp = pPoint->u.systemp; + + for (p=cl_qmap_head(&systemp->Nodes); p != cl_qmap_end(&systemp->Nodes); p = cl_qmap_next(p)) { + NodeData *nodep = PARENT_STRUCT(p, NodeData, SystemNodesEntry); + PortData *portp = FindNodePort(nodep, portnum); + if (portp) { + status = PointListAppend(&newPoint, POINT_TYPE_PORT_LIST, portp); + if (FSUCCESS != status) + goto fail; + } + } + if (! PointValid(&newPoint)) { + fabric_fail = TRUE; + } else { + PointFabricCompress(&newPoint); + status = PointFabricCopy(pPoint, &newPoint); + PointDestroy(&newPoint); + if (FSUCCESS != status) + goto fail; + } + } + break; + } + } + + // for FIND_FLAG_ENODE leave any selected ExpectedNodes as is + + if (find_flag & FIND_FLAG_ESM) { + switch (pPoint->EsmType) { + case POINT_ESM_TYPE_NONE: + break; + case POINT_ESM_TYPE_SM: + if (! (pPoint->u3.esmp->gotPortNum + && pPoint->u3.esmp->PortNum == portnum)) { + PointEsmDestroy(pPoint); + } + break; + case POINT_ESM_TYPE_SM_LIST: + { + LIST_ITERATOR i; + DLIST *pEsmList = &pPoint->u3.esmList; + + for (i=ListHead(pEsmList); i != NULL; i = ListNext(pEsmList, i)) { + ExpectedSM *esmp = (ExpectedSM*)ListObj(i); + if (esmp->gotPortNum && esmp->PortNum == portnum) { + status = PointEsmListAppend(&newPoint, POINT_ESM_TYPE_SM_LIST, esmp); + if (FSUCCESS != status) + goto fail; + } + } + if (! PointValid(&newPoint)) { + PointEsmDestroy(pPoint); + } else { + PointEsmCompress(&newPoint); + status = PointEsmCopy(pPoint, &newPoint); + PointDestroy(&newPoint); + if (FSUCCESS != status) + goto fail; + } + } + break; + } + } + + if ((find_flag & FIND_FLAG_ELINK) && callback) { + // rather than retain extra information to indicate which side of + // the ELINK matched the original search criteria (nodeguid, nodedesc, + // nodedescpat, nodetype) we use a callback to + // recompare with the original criteria and also check against portnum + // N/A search critieria: nodedetpat, iocname, ioctype, iocnamepat + switch (pPoint->ElinkType) { + case POINT_ELINK_TYPE_NONE: + break; + case POINT_ELINK_TYPE_LINK: + if (! (*callback)(pPoint->u4.elinkp, nodecmp, portnum)){ + PointElinkDestroy(pPoint); + } + break; + case POINT_ELINK_TYPE_LINK_LIST: + { + LIST_ITERATOR i; + DLIST *pElinkList = &pPoint->u4.elinkList; + + for (i=ListHead(pElinkList); i != NULL; i = ListNext(pElinkList, i)) { + ExpectedLink *elinkp = (ExpectedLink*)ListObj(i); + if ((*callback)(elinkp, nodecmp, portnum)){ + status = PointElinkListAppend(&newPoint, POINT_ELINK_TYPE_LINK_LIST, elinkp); + if (FSUCCESS != status) + goto fail; + } + } + if (! PointValid(&newPoint)) { + PointElinkDestroy(pPoint); + } else { + PointElinkCompress(&newPoint); + status = PointElinkCopy(pPoint, &newPoint); + PointDestroy(&newPoint); + if (FSUCCESS != status) + goto fail; + } + } + break; + } + } else { + DEBUG_ASSERT(pPoint->ElinkType == POINT_ELINK_TYPE_NONE); + } + + if (fabric_fail && pPoint->EnodeType == POINT_ENODE_TYPE_NONE + && pPoint->EsmType == POINT_ESM_TYPE_NONE + && pPoint->ElinkType == POINT_ELINK_TYPE_NONE) { + // we failed fabric and had no enode, esm, nor elink, so output a good + // message specific to the fabric point we must have started with + switch (pPoint->Type) { + case POINT_TYPE_NONE: + case POINT_TYPE_PORT: + case POINT_TYPE_PORT_LIST: + case POINT_TYPE_NODE_PAIR_LIST: + ASSERT(0); // should not get here + break; + case POINT_TYPE_NODE: + fprintf(stderr, "%s: Node %.*s GUID 0x%016"PRIx64" Port %u Not Found\n", + g_Top_cmdname, STL_NODE_DESCRIPTION_ARRAY_SIZE, + (char*)pPoint->u.nodep->NodeDesc.NodeString, + pPoint->u.nodep->NodeInfo.NodeGUID, portnum); + break; + case POINT_TYPE_NODE_LIST: +#if !defined(VXWORKS) || defined(BUILD_DMC) + case POINT_TYPE_IOC_LIST: +#endif + case POINT_TYPE_SYSTEM: + fprintf(stderr, "%s: Port %u Not Found\n", g_Top_cmdname, portnum); + break; +#if !defined(VXWORKS) || defined(BUILD_DMC) + case POINT_TYPE_IOC: + fprintf(stderr, "%s: IOC %.*s GUID 0x%016"PRIx64" Port %u Not Found\n", + g_Top_cmdname, IOC_IDSTRING_SIZE, + (char*)pPoint->u.iocp->IocProfile.IDString, + pPoint->u.iocp->IocProfile.IocGUID, portnum); + break; +#endif + } + status = FNOT_FOUND; + } else if (! PointValid(pPoint)) { + fprintf(stderr, "%s: Port %u Not Found\n", g_Top_cmdname, portnum); + status = FNOT_FOUND; + } else { + return FSUCCESS; + } + +fail: + PointDestroy(&newPoint); + PointDestroy(pPoint); + return status; +} + +static boolean PointPortElinkCompareNodeGuid(ExpectedLink *elinkp, void *nodecmp, uint8 portnum) +{ + EUI64 guid = *(EUI64*)nodecmp; + + return ((elinkp->portselp1 && elinkp->portselp1->NodeGUID == guid + && elinkp->portselp1->gotPortNum + && elinkp->portselp1->PortNum == portnum) + || (elinkp->portselp2 && elinkp->portselp2->NodeGUID == guid + && elinkp->portselp2->gotPortNum + && elinkp->portselp2->PortNum == portnum)); +} + +static FSTATUS ParseNodeGuidPoint(FabricData_t *fabricp, char *arg, Point *pPoint, uint8 find_flag, char **pp) +{ + char *param; + EUI64 guid; + FSTATUS status; + + ASSERT(! PointValid(pPoint)); + if (FSUCCESS != StringToUint64(&guid, arg, pp, 0, TRUE)) { + fprintf(stderr, "%s: Invalid Node GUID format: '%s'\n", + g_Top_cmdname, arg); + return FINVALID_PARAMETER; + } + if (! guid) { + fprintf(stderr, "%s: Invalid Node GUID: 0x%016"PRIx64"\n", + g_Top_cmdname, guid); + return FINVALID_PARAMETER; + } + status = FindNodeGuidPoint(fabricp, guid, pPoint, find_flag, 0); + if (FSUCCESS != status) + return status; + + if (NULL != (param = ComparePrefix(*pp, ":port:"))) { + return ParsePointPort(fabricp, param, pPoint, find_flag, + PointPortElinkCompareNodeGuid, &guid, pp); + } else { + return FSUCCESS; + } +} + +#if !defined(VXWORKS) || defined(BUILD_DMC) +static FSTATUS ParseIocGuidPoint(FabricData_t *fabricp, char *arg, Point *pPoint, uint8 find_flag, char **pp) +{ + char *param; + EUI64 guid; + FSTATUS status; + + ASSERT(! PointValid(pPoint)); + if (FSUCCESS != StringToUint64(&guid, arg, pp, 0, TRUE)) { + fprintf(stderr, "%s: Invalid IOC GUID format: '%s'\n", + g_Top_cmdname, arg); + return FINVALID_PARAMETER; + } + if (! guid) { + fprintf(stderr, "%s: Invalid IOC GUID: 0x%016"PRIx64"\n", + g_Top_cmdname, guid); + return FINVALID_PARAMETER; + } + if (0 == (find_flag & FIND_FLAG_FABRIC)) + return FINVALID_OPERATION; + if (find_flag & FIND_FLAG_FABRIC) { + status = FindIocGuid(fabricp, guid, pPoint); + } + // N/A for FIND_FLAG_ENODE, FIND_FLAG_ESM and FIND_FLAG_ELINK + if (status == FSUCCESS) { + if (NULL != (param = ComparePrefix(*pp, ":port:"))) { + return ParsePointPort(fabricp, param, pPoint, find_flag, NULL, NULL, pp); + } + return FSUCCESS; + } else { + fprintf(stderr, "%s: IOC GUID Not Found: 0x%016"PRIx64"\n", + g_Top_cmdname, guid); + return status; + } +} +#endif + +static FSTATUS ParseSystemGuidPoint(FabricData_t *fabricp, char *arg, Point *pPoint, uint8 find_flag, char **pp) +{ + EUI64 guid; + char *param; + + ASSERT(! PointValid(pPoint)); + if (FSUCCESS != StringToUint64(&guid, arg, pp, 0, TRUE)) { + fprintf(stderr, "%s: Invalid System Image GUID format: '%s'\n", + g_Top_cmdname, arg); + return FINVALID_PARAMETER; + } + if (! guid) { + fprintf(stderr, "%s: Invalid System Image GUID: 0x%016"PRIx64"\n", + g_Top_cmdname, guid); + return FINVALID_PARAMETER; + } + if (0 == (find_flag & FIND_FLAG_FABRIC)) + return FINVALID_OPERATION; + if (find_flag & FIND_FLAG_FABRIC) { + pPoint->u.systemp = FindSystemGuid(fabricp, guid); + if (pPoint->u.systemp) + pPoint->Type = POINT_TYPE_SYSTEM; + } + // N/A for FIND_FLAG_ENODE, FIND_FLAG_ESM and FIND_FLAG_ELINK + if (PointValid(pPoint)) { + if (NULL != (param = ComparePrefix(*pp, ":port:"))) { + return ParsePointPort(fabricp, param, pPoint, find_flag, NULL, NULL, pp); + } + return FSUCCESS; + } else { + fprintf(stderr, "%s: System Image GUID Not Found: 0x%016"PRIx64"\n", + g_Top_cmdname, guid); + return FNOT_FOUND; + } +} + +static boolean PointPortElinkCompareNodeName(ExpectedLink *elinkp, void *nodecmp, uint8 portnum) +{ + char *name = (char*)nodecmp; + + return ((elinkp->portselp1 && elinkp->portselp1->NodeDesc + && elinkp->portselp1->gotPortNum + && elinkp->portselp1->PortNum == portnum + && 0 == strncmp(elinkp->portselp1->NodeDesc, + name, STL_NODE_DESCRIPTION_ARRAY_SIZE)) + || (elinkp->portselp2 && elinkp->portselp2->NodeDesc + && elinkp->portselp2->gotPortNum + && elinkp->portselp2->PortNum == portnum + && 0 == strncmp(elinkp->portselp2->NodeDesc, + name, STL_NODE_DESCRIPTION_ARRAY_SIZE))); +} + +static FSTATUS ParseNodeNamePoint(FabricData_t *fabricp, char *arg, Point *pPoint, uint8 find_flag, char **pp) +{ + char *p; + char Name[STL_NODE_DESCRIPTION_ARRAY_SIZE+1]; + char *param; + FSTATUS status; + + ASSERT(! PointValid(pPoint)); + p = strchr(arg, ':'); + if (p) { + if (p == arg) { + fprintf(stderr, "%s: Invalid Node name format: '%s'\n", + g_Top_cmdname, arg); + return FINVALID_PARAMETER; + } + if (p - arg > STL_NODE_DESCRIPTION_ARRAY_SIZE) { + fprintf(stderr, "%s: Node name Not Found (too long): %.*s\n", + g_Top_cmdname, (int)(p-arg), arg); + return FINVALID_PARAMETER; + } + StringCopy(Name, arg, sizeof(Name)); + Name[p-arg] = '\0'; + *pp = p; + arg = Name; + } else { + *pp = arg + strlen(arg); + } + + status = FindNodeNamePoint(fabricp, arg, pPoint, find_flag, 0); + if (FSUCCESS != status) + return status; + + if (NULL != (param = ComparePrefix(*pp, ":port:"))) { + return ParsePointPort(fabricp, param, pPoint, find_flag, + PointPortElinkCompareNodeName, arg, pp); + } else { + return FSUCCESS; + } +} + +#ifndef __VXWORKS__ +static boolean PointPortElinkCompareNodeNamePat(ExpectedLink *elinkp, void *nodecmp, uint8 portnum) +{ + char *pattern = (char*)nodecmp; + + return ( (elinkp->portselp1 && elinkp->portselp1->NodeDesc + && elinkp->portselp1->gotPortNum + && elinkp->portselp1->PortNum == portnum + && 0 == fnmatch(pattern, elinkp->portselp1->NodeDesc, 0)) + || (elinkp->portselp2 && elinkp->portselp2->NodeDesc + && elinkp->portselp2->gotPortNum + && elinkp->portselp2->PortNum == portnum + && 0 == fnmatch(pattern, elinkp->portselp2->NodeDesc, 0))); +} + +/* Initialize the nodepatPairs list*/ +static FSTATUS InitNodePatPairs(NodePairList_t *nodePatPairs) +{ + //Initialize the left side of the list here. + ListInitState(&nodePatPairs->nodePairList1); + if (! ListInit(&nodePatPairs->nodePairList1, MIN_LIST_ITEMS)) { + fprintf(stderr, "%s: unable to allocate memory\n", g_Top_cmdname); + return FINSUFFICIENT_MEMORY; + } + + //Initialize the right side of the list here. + ListInitState(&nodePatPairs->nodePairList2); + if (! ListInit(&nodePatPairs->nodePairList2, MIN_LIST_ITEMS)) { + fprintf(stderr, "%s: unable to allocate memory\n", g_Top_cmdname); + if(&nodePatPairs->nodePairList1) + ListDestroy(&nodePatPairs->nodePairList1); + return FINSUFFICIENT_MEMORY; + } + return FSUCCESS; +} + +/* Delete the nodepatpairs list*/ +FSTATUS DeleteNodePatPairs(NodePairList_t *nodePatPairs) +{ + if(nodePatPairs) { + //delete the left side of the list. + ListDestroy(&nodePatPairs->nodePairList1); + //delete the right side of the list. + ListDestroy(&nodePatPairs->nodePairList2); + } + return FSUCCESS; +} + +/* Parse the node pairs/nodes file */ +static FSTATUS ParseNodePairPatFilePoint(FabricData_t *fabricp, char *arg, Point *pPoint, uint8 find_flag, uint8 pair_flag, char **pp) +{ + char *p, *pEol; + char patternLine[STL_NODE_DESCRIPTION_ARRAY_SIZE*2+NODE_PAIR_DELIMITER_SIZE+1]; + char pattern[STL_NODE_DESCRIPTION_ARRAY_SIZE+1]; + FSTATUS status; + char nodePatFileName[FILENAME] = {0}; + struct stat fileStat; + FILE *fp; + NodePairList_t nodePatPairs; + + ASSERT(PointIsInInit(pPoint)); + + if (0 == pair_flag) + return FINVALID_OPERATION; + + if (NULL == arg) { + fprintf(stderr, "%s: Node pattern Filename missing\n", g_Top_cmdname); + return FINVALID_PARAMETER; + } + + if (strlen(arg) > FILENAME - 1) { + fprintf(stderr, "%s: Node pattern Filename too long: %.*s\n", + g_Top_cmdname, (int)strlen(arg), arg); + return FINVALID_PARAMETER; + } + + if ((PAIR_FLAG_NODE != pair_flag) && (PAIR_FLAG_NONE != pair_flag) ) { + fprintf(stderr, "%s: Pair flag argument is invalid: %d\n", + g_Top_cmdname, pair_flag); + return FINVALID_PARAMETER; + } + //Get file name + StringCopy(nodePatFileName, arg, (int)sizeof(nodePatFileName)); + nodePatFileName[strlen(arg)] = '\0'; + + //There are no further focus to evaluate for node pair list + *pp = arg + strlen(arg); + + // Check if file is present + if (stat(nodePatFileName, &fileStat) < 0) { + fprintf(stderr, "Error taking stat of file {%s}: %s\n", + nodePatFileName, strerror(errno)); + return FINVALID_PARAMETER; + } + + //Open file + if ((fp = fopen(nodePatFileName, "r")) == NULL) { + fprintf(stderr, "Error opening file %s for input: %s\n", nodePatFileName, strerror(errno)); + return FINVALID_PARAMETER; + } + + memset(patternLine, 0, sizeof(patternLine)); + + //Get one line at a time + while(fgets(patternLine, sizeof(patternLine), fp) != NULL){ + //remove newline + if ((pEol = strrchr(patternLine, '\n')) != NULL) { + *pEol= '\0'; + } + //When node pairs are given + if (PAIR_FLAG_NODE == pair_flag ) { + p = strchr(patternLine, ':'); + if (p) { + memset(pattern, 0, sizeof(pattern)); + //just log the error meesage + if (p - patternLine > STL_NODE_DESCRIPTION_ARRAY_SIZE) { + fprintf(stderr, "%s: Left side node name Not Found (too long): %.*s\n", + g_Top_cmdname, (int)(p - patternLine), patternLine); + } + // copy the Left side of node pair. +1 for '\0' + StringCopy(pattern, patternLine, (p - patternLine + 1)); + pattern[(p - patternLine) + 1] = '\0'; + status = InitNodePatPairs(&nodePatPairs); + if(FSUCCESS != status){ + fprintf(stderr, "%s: Insufficient Memory\n",g_Top_cmdname ); + goto fail; + } + // Find all the nodes that match the pattern for the left side + status = FindNodePatPairs(fabricp, pattern, &nodePatPairs, find_flag, LSIDE_PAIR); + // When there is invalid entry in the Left side of each line, the entire line is skipped + if ((FSUCCESS != status)){ + DeleteNodePatPairs(&nodePatPairs); + continue; + } + memset(pattern, 0, sizeof(pattern)); + //When there is invalid entry in the right side don't mark error as corresponding left side entry could be a Switch + if (pEol - p <= STL_NODE_DESCRIPTION_ARRAY_SIZE) { + // copy the Right side of node pair. +1 is for ':' + StringCopy(pattern, patternLine + (p - patternLine + 1), (pEol - p + 1)); + // Find all the nodes that match the pattern for the right side + status = FindNodePatPairs(fabricp, pattern, &nodePatPairs, find_flag, RSIDE_PAIR); + // Only when there is insufficient memory error mark as error and return + if ((FSUCCESS != status) && (FINVALID_OPERATION != status) && + (FNOT_FOUND != status)){ + DeleteNodePatPairs(&nodePatPairs); + goto fail; + } + } else { + //just log the error meesage + fprintf(stderr, "%s: Right side node name (too long): %.*s\n", + g_Top_cmdname, (int)(pEol - p), p); + } + }else { + //just log error message + fprintf(stderr, "%s: Node pair is missing: %.*s\n", + g_Top_cmdname, (int)sizeof(patternLine), patternLine); + } + // The complete node pair List N*M is populated for a single line in file + status = PointPopulateNodePairList(pPoint, &nodePatPairs); + if (FSUCCESS != status) { + //Log error and return if it fails to fom N*M list + fprintf(stderr, "%s: Error creating node pairs\n", g_Top_cmdname); + DeleteNodePatPairs(&nodePatPairs); + goto fail; + } + // Now the line is parsed and nadepat pairs are created, so free nodePatPairs + DeleteNodePatPairs(&nodePatPairs); + //When only one node is given + } else { + if (strlen(patternLine) <= STL_NODE_DESCRIPTION_ARRAY_SIZE) { + // Only when there is insufficient memory error or invalid operation error mark as error and return + // else proceed with next node in list + status = FindNodeNamePatPointUncompress(fabricp, patternLine, pPoint, find_flag); + if ((FSUCCESS != status) && (FNOT_FOUND != status)) + goto fail; + } else { + //just log the error message and parse next line + fprintf(stderr, "%s: Node name (too long): %.*s\n", + g_Top_cmdname, (int)sizeof(patternLine), patternLine); + } + } + memset(patternLine, 0, sizeof(patternLine)); + } + PointCompress(pPoint); + fclose(fp); + return FSUCCESS; + +fail: + fclose(fp); + return status; +} + +static FSTATUS ParseNodeNamePatPoint(FabricData_t *fabricp, char *arg, Point *pPoint, uint8 find_flag, char **pp) +{ + char *p; + char Pattern[STL_NODE_DESCRIPTION_ARRAY_SIZE*5+1]; + char *param; + FSTATUS status; + + ASSERT(! PointValid(pPoint)); + p = strchr(arg, ':'); + if (p) { + if (p == arg) { + fprintf(stderr, "%s: Invalid Node name pattern format: '%s'\n", + g_Top_cmdname, arg); + return FINVALID_PARAMETER; + } + if (p - arg > sizeof(Pattern)-1) { + fprintf(stderr, "%s: Node name pattern too long: %.*s\n", + g_Top_cmdname, (int)(p-arg), arg); + return FINVALID_PARAMETER; + } + StringCopy(Pattern, arg, sizeof(Pattern)); + Pattern[p-arg] = '\0'; + *pp = p; + arg = Pattern; + } else { + *pp = arg + strlen(arg); + } + + status = FindNodeNamePatPoint(fabricp, arg, pPoint, find_flag); + if (FSUCCESS != status) + return status; + + if (NULL != (param = ComparePrefix(*pp, ":port:"))) { + return ParsePointPort(fabricp, param, pPoint, find_flag, + PointPortElinkCompareNodeNamePat, arg, pp); + } else { + return FSUCCESS; + } +} + +static FSTATUS ParseNodeDetPatPoint(FabricData_t *fabricp, char *arg, Point *pPoint, uint8 find_flag, char **pp) +{ + char *p; + char Pattern[NODE_DETAILS_STRLEN*5+1]; + char *param; + FSTATUS status; + + ASSERT(! PointValid(pPoint)); + p = strchr(arg, ':'); + if (p) { + if (p == arg) { + fprintf(stderr, "%s: Invalid Node Details pattern format: '%s'\n", + g_Top_cmdname, arg); + return FINVALID_PARAMETER; + } + if (p - arg > sizeof(Pattern)-1) { + fprintf(stderr, "%s: Node Details pattern too long: %.*s\n", + g_Top_cmdname, (int)(p-arg), arg); + return FINVALID_PARAMETER; + } + StringCopy(Pattern, arg, sizeof(Pattern)); + Pattern[p-arg] = '\0'; + *pp = p; + arg = Pattern; + } else { + *pp = arg + strlen(arg); + } + + if (0 == (find_flag & (FIND_FLAG_FABRIC|FIND_FLAG_ENODE)) + && ! QListCount(&fabricp->ExpectedFIs) + && ! QListCount(&fabricp->ExpectedSWs)) + fprintf(stderr, "%s: Warning: No Node Details supplied via topology_input\n", g_Top_cmdname); + status = FindNodeDetailsPatPoint(fabricp, arg, pPoint, find_flag); + if (FSUCCESS != status) + return status; + + if (NULL != (param = ComparePrefix(*pp, ":port:"))) { + return ParsePointPort(fabricp, param, pPoint, find_flag, NULL, NULL, pp); + } else { + return FSUCCESS; + } +} +#endif /* __VXWORKS__ */ + +static boolean PointPortElinkCompareNodeType(ExpectedLink *elinkp, void *nodecmp, uint8 portnum) +{ + NODE_TYPE type = *(NODE_TYPE*)nodecmp; + + return ((elinkp->portselp1 && elinkp->portselp1->NodeType == type + && elinkp->portselp1->gotPortNum + && elinkp->portselp1->PortNum == portnum) + || (elinkp->portselp2 && elinkp->portselp2->NodeType == type + && elinkp->portselp2->gotPortNum + && elinkp->portselp2->PortNum == portnum)); +} + +static FSTATUS ParseNodeTypePoint(FabricData_t *fabricp, char *arg, Point *pPoint, uint8 find_flag, char **pp) +{ + char *p; + char *param; + FSTATUS status; + NODE_TYPE type; + + ASSERT(! PointValid(pPoint)); + p = strchr(arg, ':'); + if (p) { + if (p == arg) { + fprintf(stderr, "%s: Invalid Node type format: '%s'\n", + g_Top_cmdname, arg); + return FINVALID_PARAMETER; + } + if (p - arg != 2) { + fprintf(stderr, "%s: Invalid Node type: %.*s\n", + g_Top_cmdname, (int)(p-arg), arg); + return FINVALID_PARAMETER; + } + *pp = p; + } else { + if (strlen(arg) != 2) { + fprintf(stderr, "%s: Invalid Node type: %s\n", g_Top_cmdname, arg); + return FINVALID_PARAMETER; + } + *pp = arg + strlen(arg); + } + if (strncasecmp(arg, "FI", 2) == 0) + type = STL_NODE_FI; + else if (strncasecmp(arg, "SW", 2) == 0) + type = STL_NODE_SW; + else { + fprintf(stderr, "%s: Invalid Node type: %.*s\n", g_Top_cmdname, 2, arg); + *pp = arg; /* back up to start of type for syntax error */ + return FINVALID_PARAMETER; + } + + status = FindNodeTypePoint(fabricp, type, pPoint, find_flag); + if (FSUCCESS != status) + return status; + + if (NULL != (param = ComparePrefix(*pp, ":port:"))) { + return ParsePointPort(fabricp, param, pPoint, find_flag, + PointPortElinkCompareNodeType, &type, pp); + } else { + return FSUCCESS; + } +} + +#if !defined(VXWORKS) || defined(BUILD_DMC) +static FSTATUS ParseIocNamePoint(FabricData_t *fabricp, char *arg, Point *pPoint, uint8 find_flag, char **pp) +{ + char *p; + char Name[IOC_IDSTRING_SIZE+1]; + char *param; + FSTATUS status; + + ASSERT(! PointValid(pPoint)); + p = strchr(arg, ':'); + if (p) { + if (p == arg) { + fprintf(stderr, "%s: Invalid IOC name format: '%s'\n", + g_Top_cmdname, arg); + return FINVALID_PARAMETER; + } + if (p - arg > IOC_IDSTRING_SIZE) { + fprintf(stderr, "%s: IOC name Not Found (too long): %.*s\n", + g_Top_cmdname, (int)(p-arg), arg); + return FINVALID_PARAMETER; + } + StringCopy(Name, arg, sizeof(Name)); + Name[p-arg] = '\0'; + *pp = p; + arg = Name; + } else { + *pp = arg + strlen(arg); + } + + status = FindIocNamePoint(fabricp, arg, pPoint, find_flag); + if (FSUCCESS != status) + return status; + + if (NULL != (param = ComparePrefix(*pp, ":port:"))) { + return ParsePointPort(fabricp, param, pPoint, find_flag, NULL, NULL, pp); + } else { + return FSUCCESS; + } +} + +static FSTATUS ParseIocNamePatPoint(FabricData_t *fabricp, char *arg, Point *pPoint, uint8 find_flag, char **pp) +{ + char *p; + char Pattern[IOC_IDSTRING_SIZE*5+1]; + char *param; + FSTATUS status; + + ASSERT(! PointValid(pPoint)); + p = strchr(arg, ':'); + if (p) { + if (p == arg) { + fprintf(stderr, "%s: Invalid IOC name pattern format: '%s'\n", + g_Top_cmdname, arg); + return FINVALID_PARAMETER; + } + if (p - arg > sizeof(Pattern)-1) { + fprintf(stderr, "%s: IOC name pattern too long: %.*s\n", + g_Top_cmdname, (int)(p-arg), arg); + return FINVALID_PARAMETER; + } + StringCopy(Pattern, arg, sizeof(Pattern)); + Pattern[p-arg] = '\0'; + *pp = p; + arg = Pattern; + } else { + *pp = arg + strlen(arg); + } + + status = FindIocNamePatPoint(fabricp, arg, pPoint, find_flag); + if (FSUCCESS != status) + return status; + + if (NULL != (param = ComparePrefix(*pp, ":port:"))) { + return ParsePointPort(fabricp, param, pPoint, find_flag, NULL, NULL, pp); + } else { + return FSUCCESS; + } +} + +static FSTATUS ParseIocTypePoint(FabricData_t *fabricp, char *arg, Point *pPoint, uint8 find_flag, char **pp) +{ + char *p; + char Type[5+1]; //"OTHER" is longest valid type name + char *param; + FSTATUS status; + int len; + IocType type; + + ASSERT(! PointValid(pPoint)); + p = strchr(arg, ':'); + if (p) { + if (p == arg) { + fprintf(stderr, "%s: Invalid IOC type format: '%s'\n", + g_Top_cmdname, arg); + return FINVALID_PARAMETER; + } + if (p - arg > sizeof(Type)-1) { + fprintf(stderr, "%s: Invalid IOC type: %.*s\n", + g_Top_cmdname, (int)(p-arg), arg); + return FINVALID_PARAMETER; + } + len = (int)(p-arg); + StringCopy(Type, arg, sizeof(Type)); + Type[len] = '\0'; + *pp = p; + arg = Type; + } else { + len = strlen(arg); + *pp = arg + len; + } + if (strncasecmp(arg, "SRP", len) == 0) + type = IOC_TYPE_SRP; + else if (strncasecmp(arg, "OTHER", len) == 0){ + type = IOC_TYPE_OTHER; + } + else { + fprintf(stderr, "%s: Invalid IOC type: %.*s\n", g_Top_cmdname, len, arg); + *pp -= len; /* back up for syntax error report */ + return FINVALID_PARAMETER; + } + + status = FindIocTypePoint(fabricp, type, pPoint, find_flag); + if (FSUCCESS != status) + return status; + + if (NULL != (param = ComparePrefix(*pp, ":port:"))) { + return ParsePointPort(fabricp, param, pPoint, find_flag, NULL, NULL, pp); + } else { + return FSUCCESS; + } +} +#endif + +static FSTATUS ParseRatePoint(FabricData_t *fabricp, char *arg, Point *pPoint, uint8 find_flag, char **pp) +{ + char *p; + char Rate[8]; // 37_5g is largest valid rate name, but lets use a couple more chars for future expansion + FSTATUS status; + int len; + uint32 rate; + ASSERT(! PointValid(pPoint)); + p = strchr(arg, ':'); + if (p) { + if (p == arg) { + fprintf(stderr, "%s: Invalid Rate format: '%s'\n", + g_Top_cmdname, arg); + return FINVALID_PARAMETER; + } + if (p - arg > sizeof(Rate)-1) { + fprintf(stderr, "%s: Invalid Rate: %.*s\n", + g_Top_cmdname, (int)(p-arg), arg); + return FINVALID_PARAMETER; + } + len = (int)(p-arg); + StringCopy(Rate, arg, sizeof(Rate)); + Rate[len] = '\0'; + *pp = p; + arg = Rate; + } else { + len = strlen(arg); + *pp = arg + len; + } + if (strncmp(arg, "12.5g", len) == 0) + rate = IB_STATIC_RATE_14G; + else if (strncmp(arg, "25g", len) == 0) + rate = IB_STATIC_RATE_25G; + else if (strncmp(arg, "37.5", len) == 0) + rate = IB_STATIC_RATE_40G; + else if (strncmp(arg, "50g", len) == 0) + rate = IB_STATIC_RATE_56G; + else if (strncmp(arg, "75g", len) == 0) + rate = IB_STATIC_RATE_80G; + else if (strncmp(arg, "100g", len) == 0) + rate = IB_STATIC_RATE_100G; + else if (strncmp(arg, "150g", len) == 0) + rate = IB_STATIC_RATE_168G; + else if (strncmp(arg, "200g", len) == 0) + rate = IB_STATIC_RATE_200G; + else { + fprintf(stderr, "%s: Invalid Rate: %.*s\n", g_Top_cmdname, len, arg); + *pp -= len; /* back up for syntax error report */ + return FINVALID_PARAMETER; + } + + status = FindRatePoint(fabricp, rate, pPoint, find_flag); + return status; +} + +static FSTATUS ParseLedPoint(FabricData_t *fabricp, char *arg, Point *pPoint, uint8 find_flag, char **pp) +{ + FSTATUS status; + char *p; + char LedState[3+1]; // "off" is largest valid state name + int len; + boolean ledon; + + ASSERT(! PointValid(pPoint)); + p = strchr(arg, ':'); + if (p) { + if (p == arg) { + fprintf(stderr, "%s: Invalid Led State format: '%s'\n", + g_Top_cmdname, arg); + return FINVALID_PARAMETER; + } + if (p - arg > sizeof(LedState)-1) { + fprintf(stderr, "%s: Invalid Led State: %.*s\n", + g_Top_cmdname, (int)(p-arg), arg); + return FINVALID_PARAMETER; + } + len = (int)(p-arg); + StringCopy(LedState, arg, sizeof(LedState)); + LedState[len] = '\0'; + *pp = p; + arg = LedState; + } else { + len = strlen(arg); + *pp = arg + len; + } + + if (strncasecmp(arg, "off", len) == 0) + ledon = FALSE; + else if (strncasecmp(arg, "on", len) == 0) + ledon = TRUE; + else { + fprintf(stderr, "%s: Invalid Led State: %.*s\n", g_Top_cmdname, len, arg); + *pp -= len; /* back up for syntax error report */ + return FINVALID_PARAMETER; + } + + status = FindLedStatePoint(fabricp, ledon, pPoint, find_flag); + return status; +} + + +static FSTATUS ParsePortStatePoint(FabricData_t *fabricp, char *arg, Point *pPoint, uint8 find_flag, char **pp) +{ + char *p; + char State[6+1]; // active is largest valid state name + FSTATUS status; + int len; + IB_PORT_STATE state; + + ASSERT(! PointValid(pPoint)); + p = strchr(arg, ':'); + if (p) { + if (p == arg) { + fprintf(stderr, "%s: Invalid Port State format: '%s'\n", + g_Top_cmdname, arg); + return FINVALID_PARAMETER; + } + if (p - arg > sizeof(State)-1) { + fprintf(stderr, "%s: Invalid Port State: %.*s\n", + g_Top_cmdname, (int)(p-arg), arg); + return FINVALID_PARAMETER; + } + len = (int)(p-arg); + StringCopy(State, arg, sizeof(State)); + State[len] = '\0'; + *pp = p; + arg = State; + } else { + len = strlen(arg); + *pp = arg + len; + } + if (strncasecmp(arg, "down", len) == 0) + state = IB_PORT_DOWN; + else if (strncasecmp(arg, "init", len) == 0) + state = IB_PORT_INIT; + else if (strncasecmp(arg, "armed", len) == 0) + state = IB_PORT_ARMED; + else if (strncasecmp(arg, "active", len) == 0) + state = IB_PORT_ACTIVE; + else if (strncasecmp(arg, "notactive", len) == 0) + state = PORT_STATE_SEARCH_NOTACTIVE; + else if (strncasecmp(arg, "initarmed", len) == 0) + state = PORT_STATE_SEARCH_INITARMED; + else { + fprintf(stderr, "%s: Invalid Port State: %.*s\n", g_Top_cmdname, len, arg); + *pp -= len; /* back up for syntax error report */ + return FINVALID_PARAMETER; + } + + status = FindPortStatePoint(fabricp, state, pPoint, find_flag); + return status; +} + +static FSTATUS ParsePortPhysStatePoint(FabricData_t *fabricp, char *arg, Point *pPoint, uint8 find_flag, char **pp) +{ + char *p; + char PhysState[8+1]; // recovery is largest valid state name + FSTATUS status; + int len; + IB_PORT_PHYS_STATE physstate; + + ASSERT(! PointValid(pPoint)); + p = strchr(arg, ':'); + if (p) { + if (p == arg) { + fprintf(stderr, "%s: Invalid Port Phys State format: '%s'\n", + g_Top_cmdname, arg); + return FINVALID_PARAMETER; + } + if (p - arg > sizeof(PhysState)-1) { + fprintf(stderr, "%s: Invalid Port Phys State: %.*s\n", + g_Top_cmdname, (int)(p-arg), arg); + return FINVALID_PARAMETER; + } + len = (int)(p-arg); + StringCopy(PhysState, arg, sizeof(PhysState)); + PhysState[len] = '\0'; + *pp = p; + arg = PhysState; + } else { + len = strlen(arg); + *pp = arg + len; + } + // SLEEP is N/A to OPA + if (strncasecmp(arg, "polling", len) == 0) + physstate = IB_PORT_PHYS_POLLING; + else if (strncasecmp(arg, "disabled", len) == 0) + physstate = IB_PORT_PHYS_DISABLED; + else if (strncasecmp(arg, "training", len) == 0) + physstate = IB_PORT_PHYS_TRAINING; + else if (strncasecmp(arg, "linkup", len) == 0) + physstate = IB_PORT_PHYS_LINKUP; + else if (strncasecmp(arg, "recovery", len) == 0) + physstate = IB_PORT_PHYS_LINK_ERROR_RECOVERY; + else if (strncasecmp(arg, "offline", len) == 0) + physstate = STL_PORT_PHYS_OFFLINE; + else if (strncasecmp(arg, "test", len) == 0) + physstate = STL_PORT_PHYS_TEST; + else { + fprintf(stderr, "%s: Invalid Port Phys State: %.*s\n", g_Top_cmdname, len, arg); + *pp -= len; /* back up for syntax error report */ + return FINVALID_PARAMETER; + } + + status = FindPortPhysStatePoint(fabricp, physstate, pPoint, find_flag); + return status; +} + +static FSTATUS ParseMtuPoint(FabricData_t *fabricp, char *arg, Point *pPoint, uint8 find_flag, char **pp) +{ + uint16 mtu_int; + IB_MTU mtu; + + ASSERT(! PointValid(pPoint)); + if (FSUCCESS != StringToUint16(&mtu_int, arg, pp, 0, TRUE)) { + fprintf(stderr, "%s: Invalid MTU format: '%s'\n", g_Top_cmdname, arg); + return FINVALID_PARAMETER; + } + if (! mtu_int) { + fprintf(stderr, "%s: Invalid MTU: %u\n", + g_Top_cmdname, (unsigned)mtu_int); + return FINVALID_PARAMETER; + } + mtu = GetMtuFromBytes(mtu_int); + + return FindMtuPoint(fabricp, mtu, pPoint, find_flag); +} + +static FSTATUS ParseCableLabelPatPoint(FabricData_t *fabricp, char *arg, Point *pPoint, uint8 find_flag, char **pp) +{ + char *p; + char Pattern[CABLE_LABEL_STRLEN*5+1]; + + ASSERT(! PointValid(pPoint)); + p = strchr(arg, ':'); + if (p) { + if (p == arg) { + fprintf(stderr, "%s: Invalid Cable Label pattern format: '%s'\n", + g_Top_cmdname, arg); + return FINVALID_PARAMETER; + } + if (p - arg > sizeof(Pattern)-1) { + fprintf(stderr, "%s: Cable Label pattern too long: %.*s\n", + g_Top_cmdname, (int)(p-arg), arg); + return FINVALID_PARAMETER; + } + StringCopy(Pattern, arg, sizeof(Pattern)); + Pattern[p-arg] = '\0'; + *pp = p; + arg = Pattern; + } else { + *pp = arg + strlen(arg); + } + + if (0 == (find_flag & (FIND_FLAG_FABRIC|FIND_FLAG_ELINK)) + && ! (fabricp->flags & FF_CABLEDATA)) + fprintf(stderr, "%s: Warning: No Cable Data supplied via topology_input\n", g_Top_cmdname); + return FindCableLabelPatPoint(fabricp, arg, pPoint, find_flag); +} + +static FSTATUS ParseCableLenPatPoint(FabricData_t *fabricp, char *arg, Point *pPoint, uint8 find_flag, char **pp) +{ + char *p; + char Pattern[CABLE_LENGTH_STRLEN*5+1]; + + ASSERT(! PointValid(pPoint)); + p = strchr(arg, ':'); + if (p) { + if (p == arg) { + fprintf(stderr, "%s: Invalid Cable Length pattern format: '%s'\n", + g_Top_cmdname, arg); + return FINVALID_PARAMETER; + } + if (p - arg > sizeof(Pattern)-1) { + fprintf(stderr, "%s: Cable Length pattern too long: %.*s\n", + g_Top_cmdname, (int)(p-arg), arg); + return FINVALID_PARAMETER; + } + StringCopy(Pattern, arg, sizeof(Pattern)); + Pattern[p-arg] = '\0'; + *pp = p; + arg = Pattern; + } else { + *pp = arg + strlen(arg); + } + + if (0 == (find_flag & (FIND_FLAG_FABRIC|FIND_FLAG_ELINK)) + && ! (fabricp->flags & FF_CABLEDATA)) + fprintf(stderr, "%s: Warning: No Cable Data supplied via topology_input\n", g_Top_cmdname); + return FindCableLenPatPoint(fabricp, arg, pPoint, find_flag); +} + +static FSTATUS ParseCableDetailsPatPoint(FabricData_t *fabricp, char *arg, Point *pPoint, uint8 find_flag, char **pp) +{ + char *p; + char Pattern[CABLE_DETAILS_STRLEN*5+1]; + + ASSERT(! PointValid(pPoint)); + p = strchr(arg, ':'); + if (p) { + if (p == arg) { + fprintf(stderr, "%s: Invalid Cable Details pattern format: '%s'\n", + g_Top_cmdname, arg); + return FINVALID_PARAMETER; + } + if (p - arg > sizeof(Pattern)-1) { + fprintf(stderr, "%s: Cable Details pattern too long: %.*s\n", + g_Top_cmdname, (int)(p-arg), arg); + return FINVALID_PARAMETER; + } + StringCopy(Pattern, arg, sizeof(Pattern)); + Pattern[p-arg] = '\0'; + *pp = p; + arg = Pattern; + } else { + *pp = arg + strlen(arg); + } + + if (0 == (find_flag & (FIND_FLAG_FABRIC|FIND_FLAG_ELINK)) + && ! (fabricp->flags & FF_CABLEDATA)) + fprintf(stderr, "%s: Warning: No Cable Data supplied via topology_input\n", g_Top_cmdname); + return FindCableDetailsPatPoint(fabricp, arg, pPoint, find_flag); +} + +static FSTATUS ParseCabinfLenPatPoint(FabricData_t *fabricp, char *arg, Point *pPoint, uint8 find_flag, char **pp) +{ + char *p; + char Pattern[STL_CIB_STD_MAX_STRING + 1]; + + ASSERT(! PointValid(pPoint)); + p = strchr(arg, ':'); + if (p) { + if (p == arg) { + fprintf(stderr, "%s: Invalid CableInfo Cable Length pattern format: '%s'\n", + g_Top_cmdname, arg); + return FINVALID_PARAMETER; + } + if (p - arg > sizeof(Pattern)-1) { + fprintf(stderr, "%s: CableInfo Cable Length pattern too long: %.*s\n", + g_Top_cmdname, (int)(p-arg), arg); + return FINVALID_PARAMETER; + } + StringCopy(Pattern, arg, sizeof(Pattern)); + Pattern[p-arg] = '\0'; + *pp = p; + arg = Pattern; + } else { + *pp = arg + strlen(arg); + } + + return FindCabinfLenPatPoint(fabricp, arg, pPoint, find_flag); + +} // End of ParseCabinfLenPatPoint() + +static FSTATUS ParseCabinfVendNamePatPoint(FabricData_t *fabricp, char *arg, Point *pPoint, uint8 find_flag, char **pp) +{ + char *p; + char Pattern[STL_CIB_STD_MAX_STRING + 1]; + + ASSERT(! PointValid(pPoint)); + p = strchr(arg, ':'); + if (p) { + if (p == arg) { + fprintf(stderr, "%s: Invalid Vendor Name pattern format: '%s'\n", + g_Top_cmdname, arg); + return FINVALID_PARAMETER; + } + if (p - arg > sizeof(Pattern)-1) { + fprintf(stderr, "%s: Vendor Name pattern too long: %.*s\n", + g_Top_cmdname, (int)(p-arg), arg); + return FINVALID_PARAMETER; + } + StringCopy(Pattern, arg, sizeof(Pattern)); + Pattern[p-arg] = '\0'; + *pp = p; + arg = Pattern; + } else { + *pp = arg + strlen(arg); + } + + return FindCabinfVendNamePatPoint(fabricp, arg, pPoint, find_flag); + +} // End of ParseCabinfVendNamePatPoint() + +static FSTATUS ParseCabinfVendPNPatPoint(FabricData_t *fabricp, char *arg, Point *pPoint, uint8 find_flag, char **pp) +{ + char *p; + char Pattern[STL_CIB_STD_MAX_STRING + 1]; + + ASSERT(! PointValid(pPoint)); + p = strchr(arg, ':'); + if (p) { + if (p == arg) { + fprintf(stderr, "%s: Invalid Vendor PN pattern format: '%s'\n", + g_Top_cmdname, arg); + return FINVALID_PARAMETER; + } + if (p - arg > sizeof(Pattern)-1) { + fprintf(stderr, "%s: Vendor PN pattern too long: %.*s\n", + g_Top_cmdname, (int)(p-arg), arg); + return FINVALID_PARAMETER; + } + StringCopy(Pattern, arg, sizeof(Pattern)); + Pattern[p-arg] = '\0'; + *pp = p; + arg = Pattern; + } else { + *pp = arg + strlen(arg); + } + + return FindCabinfVendPNPatPoint(fabricp, arg, pPoint, find_flag); + +} // End of ParseCabinfVendPNPatPoint() + +static FSTATUS ParseCabinfVendRevPatPoint(FabricData_t *fabricp, char *arg, Point *pPoint, uint8 find_flag, char **pp) +{ + char *p; + char Pattern[STL_CIB_STD_MAX_STRING + 1]; + + ASSERT(! PointValid(pPoint)); + p = strchr(arg, ':'); + if (p) { + if (p == arg) { + fprintf(stderr, "%s: Invalid Vendor Rev pattern format: '%s'\n", + g_Top_cmdname, arg); + return FINVALID_PARAMETER; + } + if (p - arg > sizeof(Pattern)-1) { + fprintf(stderr, "%s: Vendor Rev pattern too long: %.*s\n", + g_Top_cmdname, (int)(p-arg), arg); + return FINVALID_PARAMETER; + } + StringCopy(Pattern, arg, sizeof(Pattern)); + Pattern[p-arg] = '\0'; + *pp = p; + arg = Pattern; + } else { + *pp = arg + strlen(arg); + } + + return FindCabinfVendRevPatPoint(fabricp, arg, pPoint, find_flag); + +} // End of ParseCabinfVendRevPatPoint() + +static FSTATUS ParseCabinfVendSNPatPoint(FabricData_t *fabricp, char *arg, Point *pPoint, uint8 find_flag, char **pp) +{ + char *p; + char Pattern[STL_CIB_STD_MAX_STRING + 1]; + + ASSERT(! PointValid(pPoint)); + p = strchr(arg, ':'); + if (p) { + if (p == arg) { + fprintf(stderr, "%s: Invalid Vendor SN pattern format: '%s'\n", + g_Top_cmdname, arg); + return FINVALID_PARAMETER; + } + if (p - arg > sizeof(Pattern)-1) { + fprintf(stderr, "%s: Vendor SN pattern too long: %.*s\n", + g_Top_cmdname, (int)(p-arg), arg); + return FINVALID_PARAMETER; + } + StringCopy(Pattern, arg, sizeof(Pattern)); + Pattern[p-arg] = '\0'; + *pp = p; + arg = Pattern; + } else { + *pp = arg + strlen(arg); + } + + return FindCabinfVendSNPatPoint(fabricp, arg, pPoint, find_flag); + +} // End of ParseCabinfVendSNPatPoint() + + +static FSTATUS ParseCabinfCableTypePoint(FabricData_t *fabricp, char *arg, Point *pPoint, uint8 find_flag, char **pp) +{ + char *p; + char cabletype[STL_CIB_STD_MAX_STRING + 1]; // 'optical' is largest valid cable type name, but we use some more chars for future expansion + int len; + FSTATUS status; + + + ASSERT(! PointValid(pPoint)); + p = strchr(arg, ':'); + if (p) { + if (p == arg) { + fprintf(stderr, "%s: Invalid Cable Type format: '%s'\n", g_Top_cmdname, arg); + return FINVALID_PARAMETER; + } + if (p - arg > sizeof(cabletype)-1) { + fprintf(stderr, "%s: Invalid Cable Type: %.*s\n", g_Top_cmdname, (int)(p-arg), arg); + fprintf(stderr, "%s: Available Cable Types are: optical, passive_copper, active_copper and unknown.\n",g_Top_cmdname); + return FINVALID_PARAMETER; + } + StringCopy(cabletype, arg, sizeof(cabletype)); + cabletype[p-arg] = '\0'; + *pp = p; + arg = cabletype; + } else { + *pp = arg + strlen(arg); + } + + len = strlen(arg); + + if (!((strncmp(arg, "unknown", len) == 0) || (strncmp(arg, "optical", len) == 0) + || (strncmp(arg, "active_copper", len) == 0) || (strncmp(arg, "passive_copper", len) == 0))) + { + fprintf(stderr, "%s: Invalid Cable Type: %.*s\n", g_Top_cmdname, len, arg); + fprintf(stderr, "%s: Available Cable Types are: optical, passive_copper, active_copper and unknown.\n",g_Top_cmdname); + *pp -= len; /* back up for syntax error report */ + return FINVALID_PARAMETER; + } + + status = FindCabinfCableTypePoint(fabricp, arg, pPoint, find_flag); + return status; + +} // End of ParseCabinCableTypePoint() + +static FSTATUS ParseLinkDetailsPatPoint(FabricData_t *fabricp, char *arg, Point *pPoint, uint8 find_flag, char **pp) +{ + char *p; + char Pattern[LINK_DETAILS_STRLEN*5+1]; + + ASSERT(! PointValid(pPoint)); + p = strchr(arg, ':'); + if (p) { + if (p == arg) { + fprintf(stderr, "%s: Invalid Link Details pattern format: '%s'\n", + g_Top_cmdname, arg); + return FINVALID_PARAMETER; + } + if (p - arg > sizeof(Pattern)-1) { + fprintf(stderr, "%s: Link Details pattern too long: %.*s\n", + g_Top_cmdname, (int)(p-arg), arg); + return FINVALID_PARAMETER; + } + StringCopy(Pattern, arg, sizeof(Pattern)); + Pattern[p-arg] = '\0'; + *pp = p; + arg = Pattern; + } else { + *pp = arg + strlen(arg); + } + + if (0 == (find_flag & (FIND_FLAG_FABRIC|FIND_FLAG_ELINK)) + && ! QListCount(&fabricp->ExpectedLinks)) + fprintf(stderr, "%s: Warning: No Link Details supplied via topology_input\n", g_Top_cmdname); + return FindLinkDetailsPatPoint(fabricp, arg, pPoint, find_flag); +} + +static FSTATUS ParsePortDetailsPatPoint(FabricData_t *fabricp, char *arg, Point *pPoint, uint8 find_flag, char **pp) +{ + char *p; + char Pattern[PORT_DETAILS_STRLEN*5+1]; + + ASSERT(! PointValid(pPoint)); + p = strchr(arg, ':'); + if (p) { + if (p == arg) { + fprintf(stderr, "%s: Invalid Port Details pattern format: '%s'\n", + g_Top_cmdname, arg); + return FINVALID_PARAMETER; + } + if (p - arg > sizeof(Pattern)-1) { + fprintf(stderr, "%s: Port Details pattern too long: %.*s\n", + g_Top_cmdname, (int)(p-arg), arg); + return FINVALID_PARAMETER; + } + StringCopy(Pattern, arg, sizeof(Pattern)); + Pattern[p-arg] = '\0'; + *pp = p; + arg = Pattern; + } else { + *pp = arg + strlen(arg); + } + + if (0 == (find_flag & (FIND_FLAG_FABRIC|FIND_FLAG_ELINK)) + && ! QListCount(&fabricp->ExpectedLinks)) + fprintf(stderr, "%s: Warning: No Port Details supplied via topology_input\n", g_Top_cmdname); + return FindPortDetailsPatPoint(fabricp, arg, pPoint, find_flag); +} + +static FSTATUS ParseSmPoint(FabricData_t *fabricp, char *arg, Point *pPoint, uint8 find_flag, char **pp) +{ + + *pp = arg; + ASSERT(! PointValid(pPoint)); + if (0 == (find_flag & FIND_FLAG_FABRIC)) + return FINVALID_OPERATION; + if (find_flag & FIND_FLAG_FABRIC) { + pPoint->u.portp = FindMasterSm(fabricp); + if (pPoint->u.portp) { + pPoint->Type = POINT_TYPE_PORT; + } + } + // N/A for FIND_FLAG_ENODE, FIND_FLAG_ESM and FIND_FLAG_ELINK + // while FIND_FLAG_ESM may seem applicable, we can't identify a master SM + // from what is in topology.xml + if (! PointValid(pPoint)) { + fprintf(stderr, "%s: Master SM Not Found\n", g_Top_cmdname); + return FNOT_FOUND; + } + return FSUCCESS; +} + +static FSTATUS ParseSmDetailsPatPoint(FabricData_t *fabricp, char *arg, Point *pPoint, uint8 find_flag, char **pp) +{ + char *p; + char Pattern[SM_DETAILS_STRLEN*5+1]; + + ASSERT(! PointValid(pPoint)); + p = strchr(arg, ':'); + if (p) { + if (p == arg) { + fprintf(stderr, "%s: Invalid SM Details pattern format: '%s'\n", + g_Top_cmdname, arg); + return FINVALID_PARAMETER; + } + if (p - arg > sizeof(Pattern)-1) { + fprintf(stderr, "%s: SM Details pattern too long: %.*s\n", + g_Top_cmdname, (int)(p-arg), arg); + return FINVALID_PARAMETER; + } + StringCopy(Pattern, arg, sizeof(Pattern)); + Pattern[p-arg] = '\0'; + *pp = p; + arg = Pattern; + } else { + *pp = arg + strlen(arg); + } + + if (0 == (find_flag & (FIND_FLAG_FABRIC|FIND_FLAG_ESM)) + && ! QListCount(&fabricp->ExpectedSMs)) + fprintf(stderr, "%s: Warning: No SM Details supplied via topology_input\n", g_Top_cmdname); + return FindSmDetailsPatPoint(fabricp, arg, pPoint, find_flag); +} + +static FSTATUS ParseLinkQualityPoint(FabricData_t *fabricp, char *arg, Point *pPoint, uint8 find_flag, char **pp) +{ + LinkQualityCompare comp; + uint16 quality; + char *Quality; + + ASSERT(! PointValid(pPoint)); + *pp = arg; + if (NULL != (Quality = ComparePrefix(arg, "LE:"))) { + comp = QUAL_LE; // below means get all qualities less than given quality + } else if (NULL != (Quality = ComparePrefix(arg, "GE:"))) { + comp = QUAL_GE; // above means get all qualities greater than the given quality + } else if (NULL != (Quality = ComparePrefix(arg, ":"))) { + comp = QUAL_EQ; // get exact quality + } else { + fprintf(stderr, "%s: Invalid Link Quality format: '%s'\n", + g_Top_cmdname, arg); + return FINVALID_PARAMETER; + } + + *pp = Quality; + if (FSUCCESS != StringToUint16(&quality, Quality, pp, 0, TRUE)) { + fprintf(stderr, "%s: Invalid Link Quality format: '%s'\n", g_Top_cmdname, arg); + return FINVALID_PARAMETER; + } + + if (quality > STL_LINKQUALITY_EXCELLENT) { // 5 (excellent) is the max value for link quality, anything greater is invalid + fprintf(stderr, "%s: Link Quality Too Large: %d\n", g_Top_cmdname, quality); + return FINVALID_PARAMETER; + } + + return FindLinkQualityPoint(fabricp, quality, comp, pPoint, find_flag); +} + +static FSTATUS ParseLinkDownReasonPoint(FabricData_t *fabricp, char *arg, Point *pPoint, uint8 find_flag, char **pp) +{ + uint8 ldr = IB_UINT8_MAX; + char *ldrp; + + ASSERT(! PointValid(pPoint)); + *pp = arg; + if (NULL != (ldrp = ComparePrefix(arg, ":"))) { + *pp = ldrp; + if (FSUCCESS != StringToUint8(&ldr, ldrp, pp, 0, TRUE)) { + fprintf(stderr, "%s: Invalid Link Quality format: '%s'\n", g_Top_cmdname, arg); + return FINVALID_PARAMETER; + } + } + + return FindLinkDownReasonPoint(fabricp, ldr, pPoint, find_flag); +} +/* parse the arg string and find the mentioned Point + * arg string formats: + * gid:subnet:guid + * lid:lid + * lid:lid:node + * lid:lid:port:# + * lid:lid:veswport:# + * portguid:guid + * nodeguid:guid + * nodeguid:guid:port:# + * iocguid:guid + * iocguid:guid:port:# + * systemguid:guid + * systemguid:guid:port:# + * node:node name + * node:node name:port:# + * nodepat:node name pattern + * nodepat:node name pattern:port:# + * nodedetpat:node details pattern + * nodedetpat:node details pattern:port:# + * nodetype:node type + * nodetype:node type:port:# + * ioc:ioc name + * ioc:ioc name:port:# + * iocpat:ioc name pattern + * iocpat:ioc name pattern:port:# + * ioctype:ioc type + * ioctype:ioc type:port:# + * rate:rate string + * portstate:state string + * portphysstate:phys state string + * mtu:# + * cableinftype:cable type + * labelpat:cable label pattern + * led:on/off + * lengthpat:cable length pattern + * cabledetpat:cable details pattern + * cabinflenpat:cable info cable length pattern + * cabinfvendnamepat:cable info vendor name pattern + * cabinfvendpnpat:cable info vendor part number pattern + * cabinfvendrevpat:cable info vendor rev pattern + * cabinfvendsnpat:cable info vendor serial number pattern + * linkdetpat:cable details pattern + * portdetpat:port details pattern + * sm + * smdetpat:sm details pattern + * linkqual:link quality level + * linkqualLE:link quality level + * linkqualGE:link quality level + */ +FSTATUS ParsePoint(FabricData_t *fabricp, char* arg, Point* pPoint, uint8 find_flag, char **pp) +{ + char* param; + FSTATUS status; + + *pp = arg; + PointInit(pPoint); + if (NULL != (param = ComparePrefix(arg, "gid:"))) { + status = ParseGidPoint(fabricp, param, pPoint, find_flag, pp); + } else if (NULL != (param = ComparePrefix(arg, "lid:"))) { + status = ParseLidPoint(fabricp, param, pPoint, find_flag, pp); + } else if (NULL != (param = ComparePrefix(arg, "portguid:"))) { + status = ParsePortGuidPoint(fabricp, param, pPoint, find_flag, pp); + } else if (NULL != (param = ComparePrefix(arg, "nodeguid:"))) { + status = ParseNodeGuidPoint(fabricp, param, pPoint, find_flag, pp); +#if !defined(VXWORKS) || defined(BUILD_DMC) + } else if (NULL != (param = ComparePrefix(arg, "iocguid:"))) { + status = ParseIocGuidPoint(fabricp, param, pPoint, find_flag, pp); +#endif + } else if (NULL != (param = ComparePrefix(arg, "systemguid:"))) { + status = ParseSystemGuidPoint(fabricp, param, pPoint, find_flag, pp); + } else if (NULL != (param = ComparePrefix(arg, "node:"))) { + status = ParseNodeNamePoint(fabricp, param, pPoint, find_flag, pp); + } else if (NULL != (param = ComparePrefix(arg, "led:"))) { + status = ParseLedPoint(fabricp, param, pPoint, find_flag, pp); +#ifndef __VXWORKS__ + } else if (NULL != (param = ComparePrefix(arg, "nodepat:"))) { + status = ParseNodeNamePatPoint(fabricp, param, pPoint, find_flag, pp); + } else if (NULL != (param = ComparePrefix(arg, "nodedetpat:"))) { + status = ParseNodeDetPatPoint(fabricp, param, pPoint, find_flag, pp); + } else if (NULL != (param = ComparePrefix(arg, "nodepatfile:"))) { + status = ParseNodePairPatFilePoint(fabricp, param, pPoint, find_flag, PAIR_FLAG_NONE, pp); + } else if (NULL != (param = ComparePrefix(arg, "nodepairpatfile:"))) { + status = ParseNodePairPatFilePoint(fabricp, param, pPoint, find_flag, PAIR_FLAG_NODE, pp); +#endif + } else if (NULL != (param = ComparePrefix(arg, "nodetype:"))) { + status = ParseNodeTypePoint(fabricp, param, pPoint, find_flag, pp); +#if !defined(VXWORKS) || defined(BUILD_DMC) + } else if (NULL != (param = ComparePrefix(arg, "ioc:"))) { + status = ParseIocNamePoint(fabricp, param, pPoint, find_flag, pp); + } else if (NULL != (param = ComparePrefix(arg, "iocpat:"))) { + status = ParseIocNamePatPoint(fabricp, param, pPoint, find_flag, pp); + } else if (NULL != (param = ComparePrefix(arg, "ioctype:"))) { + status = ParseIocTypePoint(fabricp, param, pPoint, find_flag, pp); +#endif + } else if (NULL != (param = ComparePrefix(arg, "rate:"))) { + status = ParseRatePoint(fabricp, param, pPoint, find_flag, pp); + } else if (NULL != (param = ComparePrefix(arg, "portstate:"))) { + status = ParsePortStatePoint(fabricp, param, pPoint, find_flag, pp); + } else if (NULL != (param = ComparePrefix(arg, "portphysstate:"))) { + status = ParsePortPhysStatePoint(fabricp, param, pPoint, find_flag, pp); + } else if (NULL != (param = ComparePrefix(arg, "mtucap:"))) { + status = ParseMtuPoint(fabricp, param, pPoint, find_flag, pp); + } else if (NULL != (param = ComparePrefix(arg, "labelpat:"))) { + status = ParseCableLabelPatPoint(fabricp, param, pPoint, find_flag, pp); + } else if (NULL != (param = ComparePrefix(arg, "lengthpat:"))) { + status = ParseCableLenPatPoint(fabricp, param, pPoint, find_flag, pp); + } else if (NULL != (param = ComparePrefix(arg, "cabledetpat:"))) { + status = ParseCableDetailsPatPoint(fabricp, param, pPoint, find_flag, pp); + } else if (NULL != (param = ComparePrefix(arg, "cabinflenpat:"))) { + status = ParseCabinfLenPatPoint(fabricp, param, pPoint, find_flag, pp); + } else if (NULL != (param = ComparePrefix(arg, "cabinfvendnamepat:"))) { + status = ParseCabinfVendNamePatPoint(fabricp, param, pPoint, find_flag, pp); + } else if (NULL != (param = ComparePrefix(arg, "cabinfvendpnpat:"))) { + status = ParseCabinfVendPNPatPoint(fabricp, param, pPoint, find_flag, pp); + } else if (NULL != (param = ComparePrefix(arg, "cabinfvendrevpat:"))) { + status = ParseCabinfVendRevPatPoint(fabricp, param, pPoint, find_flag, pp); + } else if (NULL != (param = ComparePrefix(arg, "cabinfvendsnpat:"))) { + status = ParseCabinfVendSNPatPoint(fabricp, param, pPoint, find_flag, pp); + } else if (NULL != (param = ComparePrefix(arg, "cabinftype:"))) { + status = ParseCabinfCableTypePoint(fabricp, param, pPoint, find_flag, pp); + } else if (NULL != (param = ComparePrefix(arg, "linkdetpat:"))) { + status = ParseLinkDetailsPatPoint(fabricp, param, pPoint, find_flag, pp); + } else if (NULL != (param = ComparePrefix(arg, "portdetpat:"))) { + status = ParsePortDetailsPatPoint(fabricp, param, pPoint, find_flag, pp); + } else if (NULL != (param = ComparePrefix(arg, "smdetpat:"))) { + status = ParseSmDetailsPatPoint(fabricp, param, pPoint, find_flag, pp); + } else if (NULL != (param = ComparePrefix(arg, "sm"))) { + status = ParseSmPoint(fabricp, param, pPoint, find_flag, pp); + } else if (NULL != (param = ComparePrefix(arg, "linkqual"))) { + status = ParseLinkQualityPoint(fabricp, param, pPoint, find_flag, pp); + } else if (NULL != (param = ComparePrefix(arg, "ldr"))) { + status = ParseLinkDownReasonPoint(fabricp, param, pPoint, find_flag, pp); + } else { + fprintf(stderr, "%s: Invalid format: '%s'\n", g_Top_cmdname, arg); + return FINVALID_PARAMETER; + } + if (status == FINVALID_OPERATION) { + fprintf(stderr, "%s: Format Not Allowed: '%s'\n", g_Top_cmdname, arg); + return FINVALID_PARAMETER; + } + return status; +} + +/////////////////////////////////////////////////////////////////////////////// +// FIPortIteratorHead +// +// Description: +// Finds the first non-SW port for each type in the point. +// +// Inputs: +// pFIPortIterator - Pointer to FIPortIterator object +// pFocus - Pointer to user's compare function +// +// Outputs: +// None +// +// Returns: +// Pointer to port data. +// +/////////////////////////////////////////////////////////////////////////////// +PortData *FIPortIteratorHead(FIPortIterator *pFIPortIterator, Point *pFocus) +{ + pFIPortIterator->pPoint = pFocus; + + switch(pFocus->Type) + { + case POINT_TYPE_PORT: + { + //return NULL if port belongs to a switch else return the port + if( STL_NODE_SW != pFocus->u.portp->nodep->NodeInfo.NodeType) { + //Flag to indicate the port is the only port and it is already returned + pFIPortIterator->u.PortIter.lastPortFlag = TRUE; + return pFocus->u.portp; + } + return NULL; + } + break; + case POINT_TYPE_PORT_LIST: + { + LIST_ITERATOR i; + //Go through the port list to find the first FI port. Skip all SW ports + for (i = ListHead(&pFocus->u.portList); + i != NULL; i = ListNext(&pFocus->u.portList, i)) { + PortData *portp = (PortData *)ListObj(i); + if(STL_NODE_SW == portp->nodep->NodeInfo.NodeType) + continue; + else { + //Store where in the point the current iterator is. + pFIPortIterator->u.PortListIter.currentPort = i; + return portp; + } + } + return NULL; + } + break; + case POINT_TYPE_NODE: + { + NodeData *nodep = pFocus->u.nodep; + // Get the first port only if it is a FI node. Return NULL for switch nodes. + if(STL_NODE_SW != nodep->NodeInfo.NodeType) { + cl_map_item_t * p = cl_qmap_head(&nodep->Ports); + if(p != cl_qmap_end(&nodep->Ports)) { + PortData *portp = PARENT_STRUCT(p, PortData, NodePortsEntry); + //Store where in the point the current iterator is. + pFIPortIterator->u.NodeIter.pCurrentPort = p; + pFIPortIterator->u.NodeIter.lastNodeFlag = TRUE; + return portp; + } + } + return NULL; + } + break; + case POINT_TYPE_NODE_LIST: + { + LIST_ITERATOR i; + //Iterate over the node list to get the first FI node. + for (i = ListHead(&pFocus->u.nodeList); + i != NULL; i = ListNext(&pFocus->u.nodeList, i)) { + NodeData *nodep = (NodeData*)ListObj(i); + + //skip switches + if(nodep->NodeInfo.NodeType == STL_NODE_SW) + continue; + else { + cl_map_item_t *p = cl_qmap_head(&nodep->Ports); + if(p != cl_qmap_end(&nodep->Ports)){ + PortData *portp = PARENT_STRUCT(p, PortData, NodePortsEntry); + //Store where in the point the current iterator is. + pFIPortIterator->u.NodeListIter.currentNode = i; + pFIPortIterator->u.NodeListIter.pCurrentPort = p; + return portp; + } + } + } + return NULL; + } + break; +#if !defined(VXWORKS) || defined(BUILD_DMC) + case POINT_TYPE_IOC: + { + NodeData *nodep = pFocus->u.iocp->ioup->nodep; + //Get the first port for a FI node. + if(STL_NODE_SW != nodep->NodeInfo.NodeType) { + cl_map_item_t *p = cl_qmap_head(&nodep->Ports); + if(p != cl_qmap_end(&nodep->Ports)) + { + PortData *portp = PARENT_STRUCT(p, PortData, NodePortsEntry); + //Store where in the point the current iterator is. + pFIPortIterator->u.IocIter.pCurrentPort = p; + pFIPortIterator->u.IocIter.lastIocFlag = TRUE; + return portp; + } + } + return NULL; + } + break; + case POINT_TYPE_IOC_LIST: + { + LIST_ITERATOR i; + //Iterate over the Ioc list to get the first FI node. + for (i = ListHead(&pFocus->u.iocList); + i != NULL; i = ListNext(&pFocus->u.iocList, i)) { + IocData *iocp = (IocData*)ListObj(i); + NodeData *nodep = iocp->ioup->nodep; + //skip switches + if(nodep->NodeInfo.NodeType == STL_NODE_SW) + continue; + else { + cl_map_item_t *p = cl_qmap_head(&nodep->Ports); + if (p != cl_qmap_end(&nodep->Ports)) + { + PortData *portp = PARENT_STRUCT(p, PortData, NodePortsEntry); + //Store where in the point the current iterator is. + pFIPortIterator->u.IocListIter.currentNode = i; + pFIPortIterator->u.IocListIter.pCurrentPort = p; + return portp; + } + } + } + return NULL; + } + break; +#endif + case POINT_TYPE_SYSTEM: + { + cl_map_item_t *s; + //Iterate over the nodes in the system to get the first FI node. + for (s = cl_qmap_head(&pFocus->u.systemp->Nodes); + s != cl_qmap_end(&pFocus->u.systemp->Nodes); s = cl_qmap_next(s)){ + NodeData *nodep = PARENT_STRUCT(s, NodeData, SystemNodesEntry); + if(nodep->NodeInfo.NodeType == STL_NODE_SW) + continue; + else { + cl_map_item_t *p = cl_qmap_head(&nodep->Ports); + if (p != cl_qmap_end(&nodep->Ports)) + { + PortData *portp = PARENT_STRUCT(p, PortData, NodePortsEntry); + //Store where in the point the current iterator is. + pFIPortIterator->u.SystemIter.pCurrentNode = s; + pFIPortIterator->u.SystemIter.pCurrentPort = p; + pFIPortIterator->u.SystemIter.lastSystemFlag = TRUE; + return portp; + } + } + } + return NULL; + } + break; + case POINT_TYPE_NONE: + case POINT_TYPE_NODE_PAIR_LIST: + default: + return NULL; + break; + } + return NULL; +} + +/////////////////////////////////////////////////////////////////////////////// +// FIPortIteratorNext +// +// Description: +// Finds the next non-SW port for each type in the point +// +// Inputs: +// pFIPortIterator - Pointer to FIPortIterator object +// +// Outputs: +// None +// +// Returns: +// Pointer to port data. +// +/////////////////////////////////////////////////////////////////////////////// +PortData *FIPortIteratorNext(FIPortIterator *pFIPortIterator) +{ + Point *pFocus = pFIPortIterator->pPoint; + + switch(pFocus->Type) + { + case POINT_TYPE_PORT: + { + //Check if port is iterated over + if(pFIPortIterator->u.PortIter.lastPortFlag) + pFIPortIterator->u.PortIter.lastPortFlag = FALSE; + return NULL; + } + break; + case POINT_TYPE_PORT_LIST: + { + LIST_ITERATOR i; + //Get the next FI port using the stored position of the iterator in the point + for (i = ListNext(&pFocus->u.portList, pFIPortIterator->u.PortListIter.currentPort); + i != NULL; i = ListNext(&pFocus->u.portList,i)) { + PortData *portp = (PortData *)ListObj(i); + if(STL_NODE_SW == portp->nodep->NodeInfo.NodeType) + continue; + else { + //Store where in the point the current iterator is. + pFIPortIterator->u.PortListIter.currentPort = i; + return portp; + } + } + return NULL; + } + break; + case POINT_TYPE_NODE: + { + if (pFIPortIterator->u.NodeIter.lastNodeFlag){ + //Get the next port using the stored position of the iterator in the point. It is an FI port. + cl_map_item_t *p = cl_qmap_next(pFIPortIterator->u.NodeIter.pCurrentPort); + if(p != cl_qmap_end(&pFocus->u.nodep->Ports)){ + PortData *portp = PARENT_STRUCT(p, PortData, NodePortsEntry); + //Store where in the point the current iterator is. + pFIPortIterator->u.NodeIter.pCurrentPort = p; + return portp; + } else + pFIPortIterator->u.NodeIter.lastNodeFlag = FALSE; + } + return NULL; + } + break; + case POINT_TYPE_NODE_LIST: + { + LIST_ITERATOR i; + //Get the next port of the node using the stored position of the iterator in the point. It is an FI port. + NodeData *nodep = (NodeData*)ListObj(pFIPortIterator->u.NodeListIter.currentNode); + cl_map_item_t *p = cl_qmap_next(pFIPortIterator->u.NodeListIter.pCurrentPort); + if(p != cl_qmap_end(&nodep->Ports)){ + PortData *portp = PARENT_STRUCT(p, PortData, NodePortsEntry); + //Store where in the point the current iterator is. + pFIPortIterator->u.NodeIter.pCurrentPort = p; + return portp; + } else { + //Iterate over the next node of the list + for (i = ListNext(&pFocus->u.nodeList, pFIPortIterator->u.NodeListIter.currentNode); + i != NULL; i = ListNext(&pFocus->u.nodeList, i)) { + nodep = (NodeData*)ListObj(i); + //skip switches + if(nodep->NodeInfo.NodeType == STL_NODE_SW) + continue; + else { + p = cl_qmap_head(&nodep->Ports); + if(p != cl_qmap_end(&nodep->Ports)){ + PortData *portp = PARENT_STRUCT(p, PortData, NodePortsEntry); + //Store where in the point the current iterator is. + pFIPortIterator->u.NodeListIter.currentNode = i; + pFIPortIterator->u.NodeListIter.pCurrentPort = p; + return portp; + } + } + } + } + return NULL; + } + break; +#if !defined(VXWORKS) || defined(BUILD_DMC) + case POINT_TYPE_IOC: + { + if (pFIPortIterator->u.IocIter.lastIocFlag){ + //Get the next port using the stored position of the iterator in the point. It is an FI port. + cl_map_item_t *p = cl_qmap_next(pFIPortIterator->u.IocIter.pCurrentPort); + NodeData *nodep = pFocus->u.iocp->ioup->nodep; + if(p != cl_qmap_end(&nodep->Ports)){ + PortData *portp = PARENT_STRUCT(p, PortData, NodePortsEntry); + //Store where in the point the current iterator is. + pFIPortIterator->u.IocIter.pCurrentPort = p; + return portp; + } else + pFIPortIterator->u.IocIter.lastIocFlag = FALSE; + } + return NULL; + } + break; + case POINT_TYPE_IOC_LIST: + { + LIST_ITERATOR i; + //Get the next port of the node using the stored position of the iterator in the point. It is an FI port. + IocData *iocp = (IocData*)ListObj(pFIPortIterator->u.IocListIter.currentNode); + NodeData *nodep = iocp->ioup->nodep; + cl_map_item_t *p = cl_qmap_next(pFIPortIterator->u.IocListIter.pCurrentPort); + if(p != cl_qmap_end(&nodep->Ports)){ + PortData *portp = PARENT_STRUCT(p, PortData, NodePortsEntry); + //Store where in the point the current iterator is. + pFIPortIterator->u.IocListIter.pCurrentPort = p; + return portp; + } else { + //Iterate over the next Ioc of the list + for (i = ListNext(&pFocus->u.iocList, pFIPortIterator->u.IocListIter.currentNode); + i != NULL; i = ListNext(&pFocus->u.iocList, i)) { + iocp = (IocData*)ListObj(i); + nodep = iocp->ioup->nodep; + //skip switches + if(nodep->NodeInfo.NodeType == STL_NODE_SW) + continue; + else { + p = cl_qmap_head(&nodep->Ports); + if(p != cl_qmap_end(&nodep->Ports)){ + PortData *portp = PARENT_STRUCT(p, PortData, NodePortsEntry); + //Store where in the point the current iterator is. + pFIPortIterator->u.IocListIter.currentNode = i; + pFIPortIterator->u.IocListIter.pCurrentPort = p; + return portp; + } + } + } + } + return NULL; + } + break; +#endif + case POINT_TYPE_SYSTEM: + { + cl_map_item_t *s; + if (pFIPortIterator->u.SystemIter.lastSystemFlag){ + //Get the next port using the stored position of the iterator in the point. It is an FI port. + NodeData *nodep = PARENT_STRUCT(pFIPortIterator->u.SystemIter.pCurrentNode, NodeData, SystemNodesEntry); + cl_map_item_t *p = cl_qmap_next(pFIPortIterator->u.SystemIter.pCurrentPort); + if(p != cl_qmap_end(&nodep->Ports)){ + PortData *portp = PARENT_STRUCT(p, PortData, NodePortsEntry); + //Store where in the point the current iterator is. + pFIPortIterator->u.SystemIter.pCurrentPort = p; + return portp; + } else { + //Iterate over the next node of the list + for (s = cl_qmap_next(pFIPortIterator->u.SystemIter.pCurrentNode); + s != cl_qmap_end(&pFocus->u.systemp->Nodes); s = cl_qmap_next(s)) { + nodep = PARENT_STRUCT(s, NodeData, SystemNodesEntry); + //skip switches + if(nodep->NodeInfo.NodeType == STL_NODE_SW) + continue; + else { + p = cl_qmap_head(&nodep->Ports); + if(p != cl_qmap_end(&nodep->Ports)){ + PortData *portp = PARENT_STRUCT(p, PortData, NodePortsEntry); + //Store where in the point the current iterator is. + pFIPortIterator->u.SystemIter.pCurrentNode = s; + pFIPortIterator->u.SystemIter.pCurrentPort = p; + return portp; + } + } + } + pFIPortIterator->u.SystemIter.lastSystemFlag = FALSE; + } + } + return NULL; + } + break; + case POINT_TYPE_NONE: + case POINT_TYPE_NODE_PAIR_LIST: + default: + return NULL; + break; + } + return NULL; +} diff --git a/Topology/getdate.c b/Topology/getdate.c new file mode 100644 index 0000000..8579d22 --- /dev/null +++ b/Topology/getdate.c @@ -0,0 +1,42 @@ +/* BEGIN_ICS_COPYRIGHT7 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT7 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +#include "time.h" + +// put this in a separate file because %c generates a warning +// this simplifies maintenance of expected.warn for the build +void Top_formattime(char *dest, size_t max, time_t t) +{ + struct tm stTime; + + localtime_r(&t, &stTime); + strftime(dest, max, "%c", &stTime);// %+ or %c or %x %X +} diff --git a/Topology/mad.c b/Topology/mad.c new file mode 100644 index 0000000..26cca67 --- /dev/null +++ b/Topology/mad.c @@ -0,0 +1,2003 @@ +/* BEGIN_ICS_COPYRIGHT7 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT7 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +// mad queries to PMA and DMA + + +#include "topology.h" +#include "topology_internal.h" +// TBD - fix conflict with ib_utils_openib.h +#define DBGPRINT(format, args...) if (g_verbose_file) { fprintf(g_verbose_file, format, ##args); } +#include +#include + +// umadt timeouts for DMA and PMA operations +#define SEND_WAIT_TIME (100) // 100 milliseconds for sends +#define FLUSH_WAIT_TIME (100) // 100 milliseconds for sends/recv during flush +#define RESP_WAIT_TIME (100) // 100 milliseconds for response recv + +#if defined(IB_STACK_IBACCESS) || defined(CAL_IBACCESS) +static IB_HANDLE g_umadtHandle = NULL; /* umadt handle for DM interface queries */ +#endif + +static uint64 g_transId = 1234; // transaction id +static FILE *g_verbose_file = NULL; // file for verbose output +static uint64 g_mkey = 0; // m_Key for SMA operations +static int g_smaRetries = 8; // number of request/response attempts + +FSTATUS send_recv_mad(MADT_HANDLE umadtHandle, IB_PATH_RECORD *pathp, + uint32 qpn, uint32 qkey, MAD* mad, + int timeout, int retries); + +void setTopologyMadVerboseFile(FILE* verbose_file) { + g_verbose_file = verbose_file; +} + +void setTopologyMadRetryCount(int retries) { + g_smaRetries = retries; +} + +#ifdef IB_DEBUG +void DumpMad(void *addr) +{ + uint32 i; + for (i=0; i<256; i++) + { + if ((i & 15) == 0) { + if (i != 0) { + DBGPRINT("\n"); + } + DBGPRINT("%4.4x:", i); + } + DBGPRINT(" %2.2x", (uint32)((uint8*)addr)[i]); + } + if (i != 0) { + DBGPRINT("\n"); + } +} + +void StlDumpMad(void *addr) +{ + uint32 i; + for (i=0; i<2048; i++) + { + if ((i & 15) == 0) { + if (i != 0) { + DBGPRINT("\n"); + } + DBGPRINT("%4.4x:", i); + } + DBGPRINT(" %2.2x", (uint32)((uint8*)addr)[i]); + } + if (i != 0) { + DBGPRINT("\n"); + } +} +#endif /* IB_DEBUG */ + +#if defined(IB_STACK_IBACCESS) || defined(CAL_IBACCESS) +static FSTATUS registerUmadt(EUI64 portGuid, MADT_HANDLE *handle) +{ + RegisterClassStruct Reg; + FSTATUS fstatus; + + DBGPRINT("registerUmadt: Port 0x%016"PRIx64"\n", portGuid); + + Reg.PortGuid = portGuid; + Reg.ClassId = 0; /* only client, don't need to specify */ + Reg.ClassVersion = 0; /* only client, don't need to specify */ + Reg.isResponder = FALSE; + Reg.isTrapProcessor = FALSE; + Reg.isReportProcessor = FALSE; + Reg.SendQueueSize = 5; // TBD + Reg.RecvQueueSize = 5; // TBD + Reg.NotifySendCompletion = FALSE; + + DBGPRINT("register uMadt\n"); + fstatus = iba_umadt_register(&Reg, handle); + if (fstatus != FSUCCESS) { + fprintf(stderr, "%s: Failed to register Port 0x%016"PRIx64" with uMadt: (fstatus=0x%x): %s\n", + g_Top_cmdname, portGuid, fstatus, FSTATUS_MSG(fstatus)); + } + return fstatus; +} + +static FSTATUS send_mad(MADT_HANDLE umadtHandle, IB_PATH_RECORD *pathp, + uint32 qpn, uint32 qkey, MAD* mad) +{ + FSTATUS status; + MadtStruct *Mad; + MadAddrStruct Addr; + uint32 count = 1; + MadWorkCompletion *Wc; + + DBGPRINT("getting buffer to send Mad\n"); + status = iba_umadt_get_sendmad(umadtHandle, &count, &Mad); + if (status != FSUCCESS) { + return status; + } + + DBGPRINT("sending Mad\n"); + Mad->Context = 0; // TBD - for async in future + MemoryClear(&Mad->Grh, sizeof(Mad->Grh)); /* only in recv */ + MemoryCopy(&Mad->IBMad, mad, sizeof(*mad)); + GetGsiAddrFromPath(pathp, qpn, qkey, &Addr); + + status = iba_umadt_post_send(umadtHandle, Mad, &Addr); + if (status != FSUCCESS) { + fprintf(stderr, "%s: Failed to send mad: (status=0x%x): %s\n", + g_Top_cmdname, status, FSTATUS_MSG(status)); + (void)iba_umadt_release_sendmad(umadtHandle, Mad); + return status; + } + status = iba_umadt_wait_any_compl(umadtHandle, SEND_COMPLETION, SEND_WAIT_TIME); + if (status == FSUCCESS) { + status = iba_umadt_poll_send_compl(umadtHandle, &Mad, &Wc); + if (status == FSUCCESS) { + DBGPRINT("MAD Sent\n"); + (void)iba_umadt_release_sendmad(umadtHandle, Mad); + } + } + return status; +} + +static FSTATUS recv_mad(MADT_HANDLE umadtHandle, MAD* mad, int timeout) +{ + FSTATUS status; + MadtStruct *Mad; + MadWorkCompletion *Wc; + + status = iba_umadt_wait_any_compl(umadtHandle, RECV_COMPLETION, timeout); + if (status == FTIMEOUT) { + DBGPRINT("Timeout waiting for MAD Recv. timeout= %d ms\n", timeout); + return status; + } + // cleanup any send completions while here + do { + status = iba_umadt_poll_send_compl(umadtHandle, &Mad, &Wc); + if (status == FSUCCESS) { + (void)iba_umadt_release_sendmad(umadtHandle, Mad); + } + } while (status == FSUCCESS); + // get next recv from the Q + status = iba_umadt_poll_recv_compl(umadtHandle, &Mad, &Wc); + if (status != FSUCCESS) { + DBGPRINT("Poll Recv failed: %s\n", iba_fstatus_msg(status)); + return status; + } + MemoryCopy(mad, &Mad->IBMad, sizeof(*mad)); // caller must byte swap + // for now ignore Work completion, only handling responses + DBGPRINT("Received a MAD\n"); + status = iba_umadt_release_recvmad(umadtHandle, Mad); + if (status != FSUCCESS) { + fprintf(stderr, "%s: ReleaseRecvMad: (status=0x%x): %s\n", + g_Top_cmdname, status, FSTATUS_MSG(status)); + } + return status; +} + +static void flush_rcv(MADT_HANDLE umadtHandle, int timeout) +{ + FSTATUS status; + MadtStruct *Mad; + MadWorkCompletion *Wc; + + if (timeout) { + status = iba_umadt_wait_any_compl(umadtHandle, RECV_COMPLETION, timeout); + if (status == FTIMEOUT) { + return; + } + } + do { + status = iba_umadt_poll_send_compl(umadtHandle, &Mad, &Wc); + if (status == FSUCCESS) { + (void)iba_umadt_release_sendmad(umadtHandle, Mad); + } + } while (status == FSUCCESS); + do { + // get all the recv's from the Q + status = iba_umadt_poll_recv_compl(umadtHandle, &Mad, &Wc); + if (status != FSUCCESS) { + return; + } + DBGPRINT("Received a MAD\n"); + status = iba_umadt_release_recvmad(umadtHandle, Mad); + if (status != FSUCCESS) { + fprintf(stderr, "%s: ReleaseRecvMad: (status=0x%x): %s\n", + g_Top_cmdname, status, FSTATUS_MSG(status)); + } + } while (1); +} + +FSTATUS send_recv_mad(MADT_HANDLE umadtHandle, IB_PATH_RECORD *pathp, + uint32 qpn, uint32 qkey, MAD* mad, + int timeout, int retries) +{ + FSTATUS fstatus; + int attempts = retries+1; + MAD req = *mad; + + do { + fstatus = send_mad(g_umadtHandle, pathp, qpn, qkey, &req); + if (fstatus == FSUCCESS) { + do { + fstatus = recv_mad(g_umadtHandle, (MAD*)mad, timeout); + if (fstatus != FSUCCESS) + { + DBGPRINT("Failed to get MAD response: %s DLID: %u\n", iba_fstatus_msg(fstatus), pathp->DLID); + break; + } + BSWAP_MAD_HEADER((MAD*)mad); + if (mad->common.TransactionID != (g_transId<<24)) + DBGPRINT("Recv unexpected trans id: expected 0x%"PRIx64" got 0x%"PRIx64"\n", (g_transId<<24), mad->common.TransactionID); + } while (mad->common.TransactionID != (g_transId<<24)); + } + } while (FSUCCESS != fstatus && --attempts); + BSWAP_MAD_HEADER((MAD*)mad); + return fstatus; +} +#endif + +#ifdef PRODUCT_OPENIB_FF + +static __inline__ void debugLogSmaRequest(const char* requestName, uint8_t* path, STL_LID dlid, STL_LID slid) { + int i; + + if(path) { + DBGPRINT("Sending DR SMA %s to ", requestName); + if(slid) + DBGPRINT("slid: 0x%08x, ", slid); + + DBGPRINT("path:"); + for(i = 1; i <= path[0]; i++) { + DBGPRINT(" %02d", path[i]); + } + DBGPRINT("\n"); + } else { + DBGPRINT("Sending SMA %s to LID 0x%x\n", requestName, dlid); + } +} + +/** + * Issue a single SMA mad and get the response. + * Retry as needed if unable to send or don't get a response + * + * @param port The omgt_port to communicate with the fabric + * @param dlid Destination LID to send packet to + * @param slid Source LID of mixed LRDR packet. Path describes hops after reaching this LID + * @param path Directed route path to destination + * @param method Request method, likely either get or set + * @param attr Attribute type being issued for this request + * @param modifier Attribute modifier for the specified attribute + * @param buffer Pointer to attribute data + * @param bufferLen The Length of the attribute data in the buffer + * @return FSTATUS return code + */ +static FSTATUS stl_sma_send_recv_mad(struct omgt_port *port, + STL_LID dlid, + STL_LID slid, + uint8_t* path, + uint8_t method, + uint32_t attr, + uint32_t modifier, + uint8_t* buffer, + uint32_t bufferLength) +{ + FSTATUS fstatus; + STL_SMP smp; + struct omgt_mad_addr addr; + size_t send_size; + size_t recv_size; + + memset(&smp, 0, sizeof(smp)); + memset(&addr, 0, sizeof(addr)); + + if(dlid && path == NULL) { + // LID routed only + smp.common.MgmtClass = MCLASS_SM_LID_ROUTED; + smp.common.u.NS.Status.AsReg16 = 0; + addr.lid = dlid; + } else if (!dlid && !slid && path) { + // Directed route only + addr.lid = STL_LID_PERMISSIVE; + smp.common.MgmtClass = MCLASS_SM_DIRECTED_ROUTE; + smp.common.u.DR.s.D = 0; + smp.common.u.DR.s.Status = 0; + smp.common.u.DR.HopPointer = 0; + smp.common.u.DR.HopCount = path[0]; + smp.SmpExt.DirectedRoute.DrSLID = STL_LID_PERMISSIVE; + smp.SmpExt.DirectedRoute.DrDLID = STL_LID_PERMISSIVE; + memcpy(smp.SmpExt.DirectedRoute.InitPath, path, sizeof(smp.SmpExt.DirectedRoute.InitPath)); + } else if (!dlid && slid && path) { + // Mixed LR-DR (initial LID route, then DR) + addr.lid = STL_LID_PERMISSIVE; + smp.common.MgmtClass = MCLASS_SM_DIRECTED_ROUTE; + smp.common.u.DR.s.D = 0; + smp.common.u.DR.s.Status = 0; + smp.common.u.DR.HopPointer = 0; + smp.common.u.DR.HopCount = path[0]; + smp.SmpExt.DirectedRoute.DrSLID = slid; + smp.SmpExt.DirectedRoute.DrDLID = STL_LID_PERMISSIVE; + memcpy(smp.SmpExt.DirectedRoute.InitPath, path, sizeof(smp.SmpExt.DirectedRoute.InitPath)); + } else { + DBGPRINT("ERROR: unable to route packet: slid, dlid, or path not properly specified\n"); + return (FINVALID_PARAMETER); + } + + smp.common.BaseVersion = STL_BASE_VERSION; + smp.common.ClassVersion = STL_SM_CLASS_VERSION; + smp.common.mr.AsReg8 = 0; + smp.common.mr.s.Method = method; +#if defined(IB_STACK_IBACCESS) || defined(CAL_IBACCESS) + smp.common.TransactionID = (++g_transId)<<24; +#else + smp.common.TransactionID = (++g_transId) & 0xffffffff; +#endif + smp.common.AttributeID = attr; + smp.common.AttributeModifier = modifier; + smp.M_Key = g_mkey; + + // Copy the attribute information into the SMP + memcpy(stl_get_smp_data(&smp), buffer, bufferLength); + + // Determine which pkey to use (full or limited) + // Attempt to use full at all times, otherwise, can + // use the limited for queries of the local port. + uint16_t pkey = omgt_get_mgmt_pkey(port, dlid, 0); + if (pkey==0) { + DBGPRINT("ERROR: Local port does not have management privileges\n"); + return (FPROTECTION); + } + + addr.qpn = 0; + addr.qkey = 0; + addr.pkey = pkey; + + send_size = bufferLength; + send_size += stl_get_smp_header_size(&smp); + send_size = ROUNDUP_TYPE(size_t, send_size, 8); + STL_BSWAP_SMP_HEADER(&smp); + +#ifdef IB_DEBUG + DBGPRINT("Sending STL MAD:\n"); + DumpMad(&smp); +#endif + + recv_size = sizeof(smp); + fstatus = omgt_send_recv_mad_no_alloc(port, + (uint8_t *)&smp, send_size, + &addr, + (uint8_t *)&smp, &recv_size, + RESP_WAIT_TIME, + g_smaRetries-1); +#ifdef IB_DEBUG + if (fstatus == FSUCCESS) { + DBGPRINT("Received STL MAD:\n"); + StlDumpMad(&smp); + } +#endif + STL_BSWAP_SMP_HEADER(&smp); + + if (smp.common.MgmtClass == MCLASS_SM_DIRECTED_ROUTE && path && memcmp(path, smp.SmpExt.DirectedRoute.InitPath, sizeof(smp.SmpExt.DirectedRoute.InitPath)) != 0) { + int i; + + DBGPRINT("Response failed directed route validation, received packet with path: "); + for(i = 1; i < 64; i++) { + if(smp.SmpExt.DirectedRoute.InitPath[i] != 0) { + DBGPRINT("%d ", smp.SmpExt.DirectedRoute.InitPath[i]); + } else { + break; + } + } + DBGPRINT("\n"); + + fstatus = FERROR; + } + + if (smp.common.u.DR.s.Status != MAD_STATUS_SUCCESS) { + DBGPRINT("SMA response with bad status: 0x%x\n", smp.common.u.DR.s.Status); + fstatus = FERROR; + } else { + memcpy(buffer, stl_get_smp_data(&smp), bufferLength); + } + + return fstatus; +} + +/** + * Get the NodeDesc from the requested LID/path + * Retry as needed if unable to send or don't get a response + * + * @param port The omgt_port to communicate with the fabric + * @param dlid Destination LID to send packet to + * @param slid Source LID of mixed LRDR packet. Path describes hops after reaching this LID + * @param path Directed route path to destination + * @param pNodeDesc Pointer to allocated space to store the returned NodeDesc + * @return FSTATUS return code + */ +FSTATUS SmaGetNodeDesc(struct omgt_port *port, + STL_LID dlid, + STL_LID slid, + uint8_t* path, + STL_NODE_DESCRIPTION *pNodeDesc) +{ + FSTATUS fstatus; + uint32_t bufferLength = sizeof(STL_NODE_DESCRIPTION); + uint8_t buffer[bufferLength]; + memset(buffer, 0, bufferLength); + + debugLogSmaRequest("Get(NodeDesc)", path, dlid, slid); + + fstatus = stl_sma_send_recv_mad(port, dlid, slid, path, MMTHD_GET, STL_MCLASS_ATTRIB_ID_NODE_DESCRIPTION, 0, buffer, bufferLength); + + if (fstatus == FSUCCESS) { + BSWAP_STL_NODE_DESCRIPTION((STL_NODE_DESCRIPTION*)buffer); + memcpy(pNodeDesc, buffer, bufferLength); + } + return fstatus; +} + +/** + * Get the NodeInfo from the requested LID/path + * Retry as needed if unable to send or don't get a response + * + * @param port The omgt_port to communicate with the fabric + * @param dlid Destination LID to send packet to + * @param slid Source LID of mixed LRDR packet. Path describes hops after reaching this LID + * @param path Directed route path to destination + * @param pNodeInfo Pointer to allocated space to store the returned NodeInfo + * @return FSTATUS return code + */ +FSTATUS SmaGetNodeInfo(struct omgt_port *port, + STL_LID dlid, + STL_LID slid, + uint8_t* path, + STL_NODE_INFO *pNodeInfo) +{ + FSTATUS fstatus; + uint32_t bufferLength = sizeof(STL_NODE_INFO); + uint8_t buffer[bufferLength]; + memset(buffer, 0, bufferLength); + + debugLogSmaRequest("Get(NodeInfo)", path, dlid, slid); + + fstatus = stl_sma_send_recv_mad(port, dlid, slid, path, MMTHD_GET, STL_MCLASS_ATTRIB_ID_NODE_INFO, 0, buffer, bufferLength); + + if (fstatus == FSUCCESS) { + BSWAP_STL_NODE_INFO((STL_NODE_INFO*)buffer); + memcpy(pNodeInfo, buffer, bufferLength); + } + return fstatus; +} + +/** + * Get the SwitchInfo from the requested LID/path + * Retry as needed if unable to send or don't get a response + * + * @param port The omgt_port to communicate with the fabric + * @param dlid Destination LID to send packet to + * @param slid Source LID of mixed LRDR packet. Path describes hops after reaching this LID + * @param path Directed route path to destination + * @param pSwitchInfo Pointer to allocated space to store the returned SwitchInfo + * @return FSTATUS return code + */ +FSTATUS SmaGetSwitchInfo(struct omgt_port *port, + STL_LID dlid, + STL_LID slid, + uint8_t* path, + STL_SWITCH_INFO *pSwitchInfo) +{ + FSTATUS fstatus; + uint32_t bufferLength = sizeof(STL_SWITCH_INFO); + uint8_t buffer[bufferLength]; + memset(buffer, 0, bufferLength); + + debugLogSmaRequest("Get(SwitchInfo)", path, dlid, slid); + + fstatus = stl_sma_send_recv_mad(port, dlid, slid, path, MMTHD_GET, STL_MCLASS_ATTRIB_ID_SWITCH_INFO, 0, buffer, bufferLength); + + if (fstatus == FSUCCESS) { + BSWAP_STL_SWITCH_INFO((STL_SWITCH_INFO*)buffer); + memcpy(pSwitchInfo, buffer, bufferLength); + } + return fstatus; +} + +/** + * Get the PortInfo from the requested LID/path and portNum + * Retry as needed if unable to send or don't get a response + * + * @param port The omgt_port to communicate with the fabric + * @param dlid Destination LID to send packet to + * @param slid Source LID of mixed LRDR packet. Path describes hops after reaching this LID + * @param path Directed route path to destination + * @param portNum Port number for desired port information + * @param pPortInfo Pointer to allocated space to store the returned PortInfo + * @return FSTATUS return code + */ +FSTATUS SmaGetPortInfo(struct omgt_port *port, + STL_LID dlid, + STL_LID slid, + uint8_t* path, + uint8_t portNum, + uint8_t smConfigStarted, + STL_PORT_INFO *pPortInfo) +{ + FSTATUS fstatus; + uint32 amod = 0x01000000 | portNum | (smConfigStarted ? 0x00000200 : 0x0); + char attributeName[64]; + uint32_t bufferLength = sizeof(STL_PORT_INFO); + uint8_t buffer[bufferLength]; + memset(buffer, 0, bufferLength); + + snprintf(attributeName, sizeof(attributeName), "Get(PortInfo %u)", portNum); + debugLogSmaRequest(attributeName, path, dlid, slid); + + fstatus = stl_sma_send_recv_mad(port, dlid, slid, path, MMTHD_GET, STL_MCLASS_ATTRIB_ID_PORT_INFO, amod, buffer, bufferLength); + + if (fstatus == FSUCCESS) { + BSWAP_STL_PORT_INFO((STL_PORT_INFO*)buffer); + memcpy(pPortInfo, buffer, bufferLength); + } + return fstatus; +} + +/** + * Get the CableInfo from the requested LID/path starting at address addr with length len + * Retry as needed if unable to send or don't get a response + * + * @param port The omgt_port to communicate with the fabric + * @param dlid Destination LID to send packet to + * @param slid Source LID of mixed LRDR packet. Path describes hops after reaching this LID + * @param path Directed route path to destination + * @param portNum Port number for desired port information + * @param addr Starting address for CableInfo + * @param len Length of requested CableInfo data + * @param data Pointer to allocated space to store the returned CableInfo data + * @return FSTATUS return code + */ +FSTATUS SmaGetCableInfo(struct omgt_port *port, + STL_LID dlid, + STL_LID slid, + uint8_t* path, + uint8_t portNum, + uint16_t addr, + uint8_t len, + uint8_t *data) +{ + FSTATUS fstatus; + uint32_t amod = (addr & 0x07ff)<<19 | (len & 0x3f)<<13 | (portNum & 0xff); + STL_CABLE_INFO *pCableInfo; + char attributeName[64]; + uint32_t bufferLength = sizeof(STL_CABLE_INFO); + uint8_t buffer[bufferLength]; + memset(buffer, 0, bufferLength); + + snprintf(attributeName, sizeof(attributeName), "Get(CableInfo %u)", portNum); + debugLogSmaRequest(attributeName, path, dlid, slid); + + fstatus = stl_sma_send_recv_mad(port, dlid, slid, path, MMTHD_GET, STL_MCLASS_ATTRIB_ID_CABLE_INFO, amod, buffer, bufferLength); + + if (fstatus == FSUCCESS) { + pCableInfo = (STL_CABLE_INFO*)buffer; + BSWAP_STL_CABLE_INFO(pCableInfo); + memcpy(data, pCableInfo->Data, len+1); + } + return fstatus; +} + +/** + * Get the Partition Table from the requested LID/path + * Retry as needed if unable to send or don't get a response + * + * @param port The omgt_port to communicate with the fabric + * @param dlid Destination LID to send packet to + * @param slid Source LID of mixed LRDR packet. Path describes hops after reaching this LID + * @param path Directed route path to destination + * @param portNum Port number for desired port information + * @param block PKey table block number + * @param pPartTable Pointer to allocated space to store the returned Partition Table information + * @return FSTATUS return code + */ +FSTATUS SmaGetPartTable(struct omgt_port *port, + STL_LID dlid, + STL_LID slid, + uint8_t* path, + uint8_t portNum, + uint16_t block, + STL_PARTITION_TABLE *pPartTable) +{ + FSTATUS fstatus; + uint32 attrmod = (1<<24) | (portNum<<16) | block; + char attributeName[64]; + uint32_t bufferLength = sizeof(STL_PARTITION_TABLE); + uint8_t buffer[bufferLength]; + memset(buffer, 0, bufferLength); + + snprintf(attributeName, sizeof(attributeName), "Get(P_KeyTable %u %u)", portNum, block); + debugLogSmaRequest(attributeName, path, dlid, slid); + + fstatus = stl_sma_send_recv_mad(port, dlid, slid, path, MMTHD_GET, STL_MCLASS_ATTRIB_ID_PART_TABLE, attrmod, buffer, bufferLength); + + if (fstatus == FSUCCESS) { + BSWAP_STL_PARTITION_TABLE((STL_PARTITION_TABLE*)buffer); + memcpy(pPartTable, buffer, bufferLength); + } + return fstatus; +} + +/** + * Get the VLArb Table from the requested LID/path + * Retry as needed if unable to send or don't get a response + * + * @param port The omgt_port to communicate with the fabric + * @param dlid Destination LID to send packet to + * @param slid Source LID of mixed LRDR packet. Path describes hops after reaching this LID + * @param path Directed route path to destination + * @param portNum Port number for desired port information + * @param part Which part of the VLArb table to retrieve + * @param pVLArbTable Pointer to allocated space to store the returned VLArb Table information + * @return FSTATUS return code + */ +FSTATUS SmaGetVLArbTable(struct omgt_port *port, + STL_LID dlid, + STL_LID slid, + uint8_t* path, + uint8_t portNum, + uint8_t part, + STL_VLARB_TABLE *pVLArbTable) +{ + FSTATUS fstatus; + uint32 attrmod = (1<<24) | (part<<16) | portNum; + char attributeName[64]; + uint32_t bufferLength = sizeof(STL_VLARB_TABLE); + uint8_t buffer[bufferLength]; + memset(buffer, 0, bufferLength); + + snprintf(attributeName, sizeof(attributeName), "Get(VLArb %u %u)", part, portNum); + debugLogSmaRequest(attributeName, path, dlid, slid); + + fstatus = stl_sma_send_recv_mad(port, dlid, slid, path, MMTHD_GET, STL_MCLASS_ATTRIB_ID_VL_ARBITRATION, attrmod, buffer, bufferLength); + + if (fstatus == FSUCCESS) { + BSWAP_STL_VLARB_TABLE((STL_VLARB_TABLE*)buffer, part); + memcpy(pVLArbTable, buffer, bufferLength); + } + return fstatus; +} + + +/** + * Get the SLSC Mapping Table from the requested LID/path + * Retry as needed if unable to send or don't get a response + * + * @param port The omgt_port to communicate with the fabric + * @param dlid Destination LID to send packet to + * @param slid Source LID of mixed LRDR packet. Path describes hops after reaching this LID + * @param path Directed route path to destination + * @param pSLSCMap Pointer to allocated space to store the returned SLSC Mapping Table + * @return FSTATUS return code + */ +FSTATUS SmaGetSLSCMappingTable(struct omgt_port *port, + STL_LID dlid, + STL_LID slid, + uint8_t* path, + STL_SLSCMAP *pSLSCMap) +{ + FSTATUS fstatus; + uint32 attrmod = 0; + uint32_t bufferLength = sizeof(STL_SLSCMAP); + uint8_t buffer[bufferLength]; + memset(buffer, 0, bufferLength); + + debugLogSmaRequest("Get(SLSCMap)", path, dlid, slid); + + fstatus = stl_sma_send_recv_mad(port, dlid, slid, path, MMTHD_GET, STL_MCLASS_ATTRIB_ID_SL_SC_MAPPING_TABLE, attrmod, buffer, bufferLength); + + if (fstatus == FSUCCESS) { + BSWAP_STL_SLSCMAP((STL_SLSCMAP*)buffer); + memcpy(pSLSCMap, buffer, bufferLength); + } + return fstatus; +} + +/** + * Get the SCSL Mapping Table from the requested LID/path + * Retry as needed if unable to send or don't get a response + * + * @param port The omgt_port to communicate with the fabric + * @param dlid Destination LID to send packet to + * @param slid Source LID of mixed LRDR packet. Path describes hops after reaching this LID + * @param path Directed route path to destination + * @param pSCSLMap Pointer to allocated space to store the returned SCSL Mapping Table + * @return FSTATUS return code + */ +FSTATUS SmaGetSCSLMappingTable(struct omgt_port *port, + STL_LID dlid, + STL_LID slid, + uint8_t* path, + STL_SCSLMAP *pSCSLMap) +{ + FSTATUS fstatus; + uint32 attrmod = 0; + uint32_t bufferLength = sizeof(STL_SCSLMAP); + uint8_t buffer[bufferLength]; + memset(buffer, 0, bufferLength); + + debugLogSmaRequest("Get(SCSLMap)", path, dlid, slid); + + fstatus = stl_sma_send_recv_mad(port, dlid, slid, path, MMTHD_GET, STL_MCLASS_ATTRIB_ID_SC_SL_MAPPING_TABLE, attrmod, buffer, bufferLength); + + if (fstatus == FSUCCESS) { + BSWAP_STL_SCSLMAP((STL_SCSLMAP*)buffer); + memcpy(pSCSLMap, buffer, bufferLength); + } + return fstatus; +} + +/** + * Get the SCSC Mapping Table from the requested LID/path + * Retry as needed if unable to send or don't get a response + * + * @param port The omgt_port to communicate with the fabric + * @param dlid Destination LID to send packet to + * @param slid Source LID of mixed LRDR packet. Path describes hops after reaching this LID + * @param path Directed route path to destination + * @param in_port Ingress port number for SCSC Mapping Table + * @param out_port Egress port number for SCSC Mapping Table + * @param pSCSCMap Pointer to allocated space to store the returned SCSC Mapping Table + * @return FSTATUS return code + */ +FSTATUS SmaGetSCSCMappingTable(struct omgt_port *port, + STL_LID dlid, + STL_LID slid, + uint8_t* path, + uint8_t in_port, + uint8_t out_port, + STL_SCSCMAP *pSCSCMap) +{ + FSTATUS fstatus; + uint32 attrmod = (1 << 24) | (in_port<<8) | out_port; + char attributeName[64]; + uint32_t bufferLength = sizeof(STL_SCSCMAP); + uint8_t buffer[bufferLength]; + memset(buffer, 0, bufferLength); + + snprintf(attributeName, sizeof(attributeName), "Get(SCSCMap %u %u)", in_port, out_port); + debugLogSmaRequest(attributeName, path, dlid, slid); + + fstatus = stl_sma_send_recv_mad(port, dlid, slid, path, MMTHD_GET, STL_MCLASS_ATTRIB_ID_SC_SC_MAPPING_TABLE, attrmod, buffer, bufferLength); + + if (fstatus == FSUCCESS) { + BSWAP_STL_SCSCMAP((STL_SCSCMAP*)buffer); + memcpy(pSCSCMap, buffer, bufferLength); + } + return fstatus; +} + +/** + * Get the SCVL Mapping Table from the requested LID/path + * Retry as needed if unable to send or don't get a response + * + * @param port The omgt_port to communicate with the fabric + * @param dlid Destination LID to send packet to + * @param slid Source LID of mixed LRDR packet. Path describes hops after reaching this LID + * @param path Directed route path to destination + * @param portNum Port number for desired port information + * @param pSCVLMap Pointer to allocated space to store the returned SCVL Mapping Table + * @param attr SMP Attribute value - used to select between different SCVL Mapping Tables + * @return FSTATUS return code + */ +FSTATUS SmaGetSCVLMappingTable(struct omgt_port *port, + STL_LID dlid, + STL_LID slid, + uint8_t* path, + uint8_t port_num, + STL_SCVLMAP *pSCVLMap, + uint16_t attr) +{ + FSTATUS fstatus; + uint32 attrmod = (1<<24) | port_num; + char attributeName[64]; + uint32_t bufferLength = sizeof(STL_SCVLMAP); + uint8_t buffer[bufferLength]; + memset(buffer, 0, bufferLength); + + snprintf(attributeName, sizeof(attributeName), "Get(SCVLMap %u)", port_num); + debugLogSmaRequest(attributeName, path, dlid, slid); + + fstatus = stl_sma_send_recv_mad(port, dlid, slid, path, MMTHD_GET, attr, attrmod, buffer, bufferLength); + + if (fstatus == FSUCCESS) { + BSWAP_STL_SCVLMAP((STL_SCVLMAP*)buffer); + memcpy(pSCVLMap, buffer, bufferLength); + } + return fstatus; +} + +/** + * Get the Buffer Control Table from the requested LID/path + * Retry as needed if unable to send or don't get a response + * pBCT must be large enough to hold all BufferControlTables + * + * @param port The omgt_port to communicate with the fabric + * @param dlid Destination LID to send packet to + * @param slid Source LID of mixed LRDR packet. Path describes hops after reaching this LID + * @param path Directed route path to destination + * @param startPort Beginning of port range for returned Buffer Control Tables + * @param endPort End of port range for returned Buffer Control Tables + * @param pBCT[] Array to store the returned Buffer Control Table(s) + * @return FSTATUS return code + */ +FSTATUS SmaGetBufferControlTable(struct omgt_port *port, + STL_LID dlid, + STL_LID slid, + uint8_t* path, + uint8_t startPort, + uint8_t endPort, + STL_BUFFER_CONTROL_TABLE pBCT[]) +{ + FSTATUS fstatus = FERROR; + uint8_t maxCount = path == NULL ? STL_NUM_BFRCTLTAB_BLOCKS_PER_LID_SMP : STL_NUM_BFRCTLTAB_BLOCKS_PER_DRSMP; + uint8_t block; + char attributeName[64]; + const size_t bufferLength = STL_BFRCTRLTAB_PAD_SIZE * maxCount; + uint8_t buffer[bufferLength]; + memset(buffer, 0, bufferLength); + + snprintf(attributeName, sizeof(attributeName), "Get(BufferControlTable %u %u)", startPort, endPort); + debugLogSmaRequest(attributeName, path, dlid, slid); + + for (block = startPort; block <= endPort; block += maxCount) { + uint8_t numPorts = MIN(maxCount, (endPort - block)+1); + uint32_t amod = (numPorts << 24) | block; + + fstatus = stl_sma_send_recv_mad(port, dlid, slid, path, MMTHD_GET, STL_MCLASS_ATTRIB_ID_BUFFER_CONTROL_TABLE, amod, buffer, bufferLength); + + if (fstatus == FSUCCESS) { + int i; + STL_BUFFER_CONTROL_TABLE *table = (STL_BUFFER_CONTROL_TABLE *)buffer; + + for (i = 0; i < numPorts; i++) { + BSWAP_STL_BUFFER_CONTROL_TABLE(table); + pBCT[block-startPort+i] = *table; + // Handle the dissimilar sizes of Buffer Table and 8-byte pad alignment + table = (STL_BUFFER_CONTROL_TABLE *)((uint8_t *)table + STL_BFRCTRLTAB_PAD_SIZE); + } + } + } + + return fstatus; +} + +/** + * Get the Linear Forwarding Table from the requested LID/path + * Retry as needed if unable to send or don't get a response + * + * @param port The omgt_port to communicate with the fabric + * @param dlid Destination LID to send packet to + * @param slid Source LID of mixed LRDR packet. Path describes hops after reaching this LID + * @param path Directed route path to destination + * @param block Linear Forwarding Table block number + * @param pFDB Pointer to allocated space to store the returned Linear Forwarding Table + * @return FSTATUS return code + */ +FSTATUS SmaGetLinearFDBTable(struct omgt_port *port, + STL_LID dlid, + STL_LID slid, + uint8_t* path, + uint16_t block, + STL_LINEAR_FORWARDING_TABLE *pFDB) +{ + FSTATUS fstatus; + uint32_t modifier; + char attributeName[64]; + uint32_t bufferLength = sizeof(STL_LINEAR_FORWARDING_TABLE); + uint8_t buffer[bufferLength]; + memset(buffer, 0, bufferLength); + + snprintf(attributeName, sizeof(attributeName), "Get(LFT %u)", block); + debugLogSmaRequest(attributeName, path, dlid, slid); + + modifier = 0x01000000 + (uint32_t)block; + + fstatus = stl_sma_send_recv_mad(port, dlid, slid, path, MMTHD_GET, STL_MCLASS_ATTRIB_ID_LINEAR_FWD_TABLE, modifier, buffer, bufferLength); + + if (fstatus == FSUCCESS) { + BSWAP_STL_LINEAR_FORWARDING_TABLE((STL_LINEAR_FORWARDING_TABLE*)buffer); + memcpy(pFDB, buffer, bufferLength); + } + return fstatus; +} + +/** + * Get the Multicast Forwarding Table from the requested LID/path + * Retry as needed if unable to send or don't get a response + * + * @param port The omgt_port to communicate with the fabric + * @param dlid Destination LID to send packet to + * @param slid Source LID of mixed LRDR packet. Path describes hops after reaching this LID + * @param path Directed route path to destination + * @param block Multicast Forwarding Table block number + * @param position Desired port mask for selected block (0-3) + * @param pFDB Pointer to allocated space to store the returned Multicast Forwarding Table + * @return FSTATUS return code + */ +FSTATUS SmaGetMulticastFDBTable(struct omgt_port *port, + STL_LID dlid, + STL_LID slid, + uint8_t* path, + uint32_t block, + uint8_t position, + STL_MULTICAST_FORWARDING_TABLE *pFDB) +{ + FSTATUS fstatus; + char attributeName[64]; + uint32_t bufferLength = sizeof(STL_MULTICAST_FORWARDING_TABLE); + uint8_t buffer[bufferLength]; + memset(buffer, 0, bufferLength); + + snprintf(attributeName, sizeof(attributeName), "Get(MFT %u %u)", block, position); + debugLogSmaRequest(attributeName, path, dlid, slid); + + //@TODO: Enable multi-block requests from just a single block request + fstatus = stl_sma_send_recv_mad(port, dlid, slid, path, MMTHD_GET, STL_MCLASS_ATTRIB_ID_MCAST_FWD_TABLE, + (0x1<<24) | (0x3 & position)<<22 | (block & 0xfffff), buffer, bufferLength); + + if (fstatus == FSUCCESS) { + BSWAP_STL_MULTICAST_FORWARDING_TABLE((STL_MULTICAST_FORWARDING_TABLE*)buffer); + memcpy(pFDB, buffer, bufferLength); + } + return fstatus; +} + +/* Get PortGroup Table from SMA at lid + * Retry as needed + * + * @param port The omgt_port to communicate with the fabric + * @param dlid Destination LID to send packet to + * @param slid Source LID of mixed LRDR packet. Path describes hops after reaching this LID + * @param path Directed route path to destination + * @param block Port Group Table block number + * @param pPGT Pointer to allocated space to store the returned Port Group Table + * @return FSTATUS return code + */ +FSTATUS SmaGetPortGroupTable(struct omgt_port *port, + STL_LID dlid, + STL_LID slid, + uint8_t* path, + uint16 block, + STL_PORT_GROUP_TABLE *pPGT) +{ + FSTATUS fstatus; + uint32_t modifier; + char attributeName[64]; + uint32_t bufferLength = sizeof(STL_PORT_GROUP_TABLE); + uint8_t buffer[bufferLength]; + memset(buffer, 0, bufferLength); + + snprintf(attributeName, sizeof(attributeName), "Get(PGT %u)", block); + debugLogSmaRequest(attributeName, path, dlid, slid); + + modifier = 0x01000000 + (uint32_t)block; + + fstatus = stl_sma_send_recv_mad(port, dlid, slid, path, MMTHD_GET, STL_MCLASS_ATTRIB_ID_PORT_GROUP_TABLE, + modifier, buffer, bufferLength); + if (FSUCCESS == fstatus) { + BSWAP_STL_PORT_GROUP_TABLE((STL_PORT_GROUP_TABLE*)buffer); + memcpy(pPGT, buffer, bufferLength); + } + return fstatus; +} + +/* Get PortGroup FDB Table from SMA at lid + * Retry as needed + * + * @param port The omgt_port to communicate with the fabric + * @param dlid Destination LID to send packet to + * @param slid Source LID of mixed LRDR packet. Path describes hops after reaching this LID + * @param path Directed route path to destination + * @param block Port Group FDB Table block number + * @param pFDB Pointer to allocated space to store the returned Port Group FDB Table + * @return FSTATUS return code + */ +FSTATUS SmaGetPortGroupFDBTable(struct omgt_port *port, + STL_LID dlid, + STL_LID slid, + uint8_t* path, + uint16 block, + STL_PORT_GROUP_FORWARDING_TABLE *pFDB) +{ + FSTATUS fstatus; + uint32_t modifier; + char attributeName[64]; + uint32_t bufferLength = sizeof(STL_PORT_GROUP_TABLE); + uint8_t buffer[bufferLength]; + memset(buffer, 0, bufferLength); + + snprintf(attributeName, sizeof(attributeName), "Get(PGFDB %u)", block); + debugLogSmaRequest(attributeName, path, dlid, slid); + + modifier = 0x01000000 + (uint32_t)block; + fstatus = stl_sma_send_recv_mad(port, dlid, slid, path, MMTHD_GET, STL_MCLASS_ATTRIB_ID_PORT_GROUP_FWD_TABLE, + modifier, buffer, bufferLength); + if (FSUCCESS == fstatus) { + BSWAP_STL_PORT_GROUP_FORWARDING_TABLE((STL_PORT_GROUP_FORWARDING_TABLE*)buffer); + memcpy(pFDB, buffer, bufferLength); + } + return fstatus; +} + + + +/** + * Set the SwitchInfo of the requested LID/path + * Retry as needed if unable to send or don't get a response + * + * @param port The omgt_port to communicate with the fabric + * @param dlid Destination LID to send packet to + * @param slid Source LID of mixed LRDR packet. Path describes hops after reaching this LID + * @param path Directed route path to destination + * @param pSwitchInfo Pointer to SwitchInfo to set. Will be overwritten with response + * @return FSTATUS return code + */ +FSTATUS SmaSetSwitchInfo(struct omgt_port *port, + STL_LID dlid, + STL_LID slid, + uint8_t* path, + STL_SWITCH_INFO *pSwitchInfo) +{ + FSTATUS fstatus; + uint32_t bufferLength = sizeof(STL_SWITCH_INFO); + uint8_t buffer[bufferLength]; + memset(buffer, 0, bufferLength); + + debugLogSmaRequest("Set(SwitchInfo)", path, dlid, slid); + + memcpy(buffer, pSwitchInfo, bufferLength); + BSWAP_STL_SWITCH_INFO((STL_SWITCH_INFO*)buffer); + + fstatus = stl_sma_send_recv_mad(port, dlid, slid, path, MMTHD_SET, STL_MCLASS_ATTRIB_ID_SWITCH_INFO, 0, buffer, bufferLength); + + if (fstatus == FSUCCESS) { + BSWAP_STL_SWITCH_INFO((STL_SWITCH_INFO*)buffer); + memcpy(pSwitchInfo, buffer, bufferLength); + } + return fstatus; +} + +/** + * Set the PortInfo of the requested LID/path and portNum + * Retry as needed if unable to send or don't get a response + * + * @param port The omgt_port to communicate with the fabric + * @param dlid Destination LID to send packet to + * @param slid Source LID of mixed LRDR packet. Path describes hops after reaching this LID + * @param path Directed route path to destination + * @param portNum Port number for desired port information + * @param pPortInfo Pointer to PortInfo to set. Will be overwritten with response + * @return FSTATUS return code + */ +FSTATUS SmaSetPortInfo(struct omgt_port *port, + STL_LID dlid, + STL_LID slid, + uint8_t* path, + uint8_t portNum, + STL_PORT_INFO *pPortInfo) +{ + FSTATUS fstatus; + uint32 amod = 0x01000000 | portNum; + char attributeName[64]; + uint32_t bufferLength = sizeof(STL_PORT_INFO); + uint8_t buffer[bufferLength]; + + snprintf(attributeName, sizeof(attributeName), "Set(PortInfo %u)", portNum); + debugLogSmaRequest(attributeName, path, dlid, slid); + + memcpy(buffer, pPortInfo, bufferLength); + BSWAP_STL_PORT_INFO((STL_PORT_INFO*)buffer); + + fstatus = stl_sma_send_recv_mad(port, dlid, slid, path, MMTHD_SET, STL_MCLASS_ATTRIB_ID_PORT_INFO, amod, buffer, bufferLength); + + if (fstatus == FSUCCESS) { + BSWAP_STL_PORT_INFO((STL_PORT_INFO*)buffer); + memcpy(pPortInfo, buffer, bufferLength); + } + return fstatus; +} + +/** + * Set the Partition Table of the requested LID/path + * Retry as needed if unable to send or don't get a response + * + * @param port The omgt_port to communicate with the fabric + * @param dlid Destination LID to send packet to + * @param slid Source LID of mixed LRDR packet. Path describes hops after reaching this LID + * @param path Directed route path to destination + * @param portNum Port number for desired port information + * @param block PKey table block number + * @param pPartTable Pointer to Partition table to set. Will be overwritten with response + * @return FSTATUS return code + */ +FSTATUS SmaSetPartTable(struct omgt_port *port, + STL_LID dlid, + STL_LID slid, + uint8_t* path, + uint8_t portNum, + uint16_t block, + STL_PARTITION_TABLE *pPartTable) +{ + FSTATUS fstatus; + uint32 attrmod = (1<<24) | (portNum<<16) | block; + char attributeName[64]; + uint32_t bufferLength = sizeof(STL_PARTITION_TABLE); + uint8_t buffer[bufferLength]; + memset(buffer, 0, bufferLength); + + snprintf(attributeName, sizeof(attributeName), "Set(P_KeyTable %u %u)", portNum, block); + debugLogSmaRequest(attributeName, path, dlid, slid); + + memcpy(buffer, pPartTable, bufferLength); + BSWAP_STL_PARTITION_TABLE((STL_PARTITION_TABLE*)buffer); + + fstatus = stl_sma_send_recv_mad(port, dlid, slid, path, MMTHD_SET, STL_MCLASS_ATTRIB_ID_PART_TABLE, attrmod, buffer, bufferLength); + + if (fstatus == FSUCCESS) { + BSWAP_STL_PARTITION_TABLE((STL_PARTITION_TABLE*)buffer); + memcpy(pPartTable, buffer, bufferLength); + } + return fstatus; +} + +/** + * Set the VLArb Table of the requested LID/path + * Retry as needed if unable to send or don't get a response + * + * @param port The omgt_port to communicate with the fabric + * @param dlid Destination LID to send packet to + * @param slid Source LID of mixed LRDR packet. Path describes hops after reaching this LID + * @param path Directed route path to destination + * @param portNum Port number for desired port information + * @param part Which part of the VLArb table to write to + * @param pVLArbTable Pointer to VLArb table to set. Will be overwritten with response + * @return FSTATUS return code + */ +FSTATUS SmaSetVLArbTable(struct omgt_port *port, + STL_LID dlid, + STL_LID slid, + uint8_t* path, + uint8_t portNum, + uint8_t part, + STL_VLARB_TABLE *pVLArbTable) +{ + FSTATUS fstatus; + uint32 attrmod = (1<<24) | (part<<16) | portNum; + char attributeName[64]; + uint32_t bufferLength = sizeof(STL_VLARB_TABLE); + uint8_t buffer[bufferLength]; + memset(buffer, 0, bufferLength); + + snprintf(attributeName, sizeof(attributeName), "Set(VLArb %u %u)", part, portNum); + debugLogSmaRequest(attributeName, path, dlid, slid); + + memcpy(buffer, pVLArbTable, bufferLength); + BSWAP_STL_VLARB_TABLE((STL_VLARB_TABLE*)buffer, part); + + fstatus = stl_sma_send_recv_mad(port, dlid, slid, path, MMTHD_SET, STL_MCLASS_ATTRIB_ID_VL_ARBITRATION, attrmod, buffer, bufferLength); + + if (fstatus == FSUCCESS) { + BSWAP_STL_VLARB_TABLE((STL_VLARB_TABLE*)buffer, part); + memcpy(pVLArbTable, buffer, bufferLength); + } + return fstatus; +} + + +/** + * Set the SLSC Mapping Table of the requested LID/path + * Retry as needed if unable to send or don't get a response + * + * @param port The omgt_port to communicate with the fabric + * @param dlid Destination LID to send packet to + * @param slid Source LID of mixed LRDR packet. Path describes hops after reaching this LID + * @param path Directed route path to destination + * @param pSLSCMap Pointer to SLSC Mapping Table to set. Will be overwritten with response + * @return FSTATUS return code + */ +FSTATUS SmaSetSLSCMappingTable(struct omgt_port *port, + STL_LID dlid, + STL_LID slid, + uint8_t* path, + STL_SLSCMAP *pSLSCMap) +{ + FSTATUS fstatus; + uint32 attrmod = 0; + uint32_t bufferLength = sizeof(STL_SLSCMAP); + uint8_t buffer[bufferLength]; + memset(buffer, 0, bufferLength); + + debugLogSmaRequest("Set(SLSCMap)", path, dlid, slid); + + memcpy(buffer, pSLSCMap, bufferLength); + BSWAP_STL_SLSCMAP((STL_SLSCMAP*)buffer); + + fstatus = stl_sma_send_recv_mad(port, dlid, slid, path, MMTHD_SET, STL_MCLASS_ATTRIB_ID_SL_SC_MAPPING_TABLE, attrmod, buffer, bufferLength); + + if (fstatus == FSUCCESS) { + BSWAP_STL_SLSCMAP((STL_SLSCMAP*)buffer); + memcpy(pSLSCMap, buffer, bufferLength); + } + return fstatus; +} + +/** + * Set the SCSL Mapping Table of the requested LID/path + * Retry as needed if unable to send or don't get a response + * + * @param port The omgt_port to communicate with the fabric + * @param dlid Destination LID to send packet to + * @param slid Source LID of mixed LRDR packet. Path describes hops after reaching this LID + * @param path Directed route path to destination + * @param pSCSLMap Pointer to SCSL Mapping Table to set. Will be overwritten with response + * @return FSTATUS return code + */ +FSTATUS SmaSetSCSLMappingTable(struct omgt_port *port, + STL_LID dlid, + STL_LID slid, + uint8_t* path, + STL_SCSLMAP *pSCSLMap) +{ + FSTATUS fstatus; + uint32 attrmod = 0; + uint32_t bufferLength = sizeof(STL_SCSLMAP); + uint8_t buffer[bufferLength]; + memset(buffer, 0, bufferLength); + + debugLogSmaRequest("Set(SCSLMap)", path, dlid, slid); + + memcpy(buffer, pSCSLMap, bufferLength); + BSWAP_STL_SCSLMAP((STL_SCSLMAP*)buffer); + + fstatus = stl_sma_send_recv_mad(port, dlid, slid, path, MMTHD_SET, STL_MCLASS_ATTRIB_ID_SC_SL_MAPPING_TABLE, attrmod, buffer, bufferLength); + + if (fstatus == FSUCCESS) { + BSWAP_STL_SCSLMAP((STL_SCSLMAP*)buffer); + memcpy(pSCSLMap, buffer, bufferLength); + } + return fstatus; +} + +/** + * Set the SCSC Mapping Table of the requested LID/path + * Retry as needed if unable to send or don't get a response + * + * @param port The omgt_port to communicate with the fabric + * @param dlid Destination LID to send packet to + * @param slid Source LID of mixed LRDR packet. Path describes hops after reaching this LID + * @param path Directed route path to destination + * @param in_port Ingress port number for SCSC Mapping Table + * @param out_port Egress port number for SCSC Mapping Table + * @param pSCSCMap Pointer to SCSC Mapping Table to set. Will be overwritten with response + * @return FSTATUS return code + */ +FSTATUS SmaSetSCSCMappingTable(struct omgt_port *port, + STL_LID dlid, + STL_LID slid, + uint8_t* path, + uint8_t in_port, + uint8_t out_port, + STL_SCSCMAP *pSCSCMap) +{ + FSTATUS fstatus; + uint32 attrmod = (1 << 24) | (in_port<<8) | out_port; + char attributeName[64]; + uint32_t bufferLength = sizeof(STL_SCSCMAP); + uint8_t buffer[bufferLength]; + memset(buffer, 0, bufferLength); + + snprintf(attributeName, sizeof(attributeName), "Set(SCSCMap %u %u)", in_port, out_port); + debugLogSmaRequest(attributeName, path, dlid, slid); + + memcpy(buffer, pSCSCMap, bufferLength); + BSWAP_STL_SCSCMAP((STL_SCSCMAP*)buffer); + + fstatus = stl_sma_send_recv_mad(port, dlid, slid, path, MMTHD_SET, STL_MCLASS_ATTRIB_ID_SC_SC_MAPPING_TABLE, attrmod, buffer, bufferLength); + + if (fstatus == FSUCCESS) { + BSWAP_STL_SCSCMAP((STL_SCSCMAP*)buffer); + memcpy(pSCSCMap, buffer, bufferLength); + } + return fstatus; +} + +/** + * Set the SCVL Mapping Table of the requested LID/path + * Retry as needed if unable to send or don't get a response + * + * @param port The omgt_port to communicate with the fabric + * @param dlid Destination LID to send packet to + * @param slid Source LID of mixed LRDR packet. Path describes hops after reaching this LID + * @param path Directed route path to destination + * @param asyncUpdate Asynchronous update + * @param allPorts All ports starting at portNum + * @param portNum Port number for desired port information + * @param pSCVLMap Pointer to SCVL Mapping Table to set. Will be overwritten with response + * @param attr SMP Attribute value - used to select between different SCVL Mapping Tables + * @return FSTATUS return code + */ +FSTATUS SmaSetSCVLMappingTable(struct omgt_port *port, + STL_LID dlid, + STL_LID slid, + uint8_t* path, + boolean asyncUpdate, + boolean allPorts, + uint8_t portNum, + STL_SCVLMAP *pSCVLMap, + uint16_t attr) +{ + FSTATUS fstatus; + uint32 attrmod = (1<<24) | portNum; + char attributeName[64]; + uint32_t bufferLength = sizeof(STL_SCVLMAP); + uint8_t buffer[bufferLength]; + memset(buffer, 0, bufferLength); + + if (allPorts) + attrmod |= 1 << 8; + + if (asyncUpdate) + attrmod |= 1 << 12; + + snprintf(attributeName, sizeof(attributeName), "Set(SCVLMap %u)", portNum); + debugLogSmaRequest(attributeName, path, dlid, slid); + + memcpy(buffer, pSCVLMap, bufferLength); + BSWAP_STL_SCVLMAP((STL_SCVLMAP*)buffer); + + fstatus = stl_sma_send_recv_mad(port, dlid, slid, path, MMTHD_SET, attr, attrmod, buffer, bufferLength); + + if (fstatus == FSUCCESS) { + BSWAP_STL_SCVLMAP((STL_SCVLMAP*)buffer); + memcpy(pSCVLMap, buffer, bufferLength); + } + return fstatus; +} + +/** + * Set the Buffer Control Table from the requested LID/path + * Retry as needed if unable to send or don't get a response + * pBCT must be large enough to hold all BufferControlTables + * + * @param port The omgt_port to communicate with the fabric + * @param dlid Destination LID to send packet to + * @param slid Source LID of mixed LRDR packet. Path describes hops after reaching this LID + * @param path Directed route path to destination + * @param startPort Beginning of port range for returned Buffer Control Tables + * @param endPort End of port range for returned Buffer Control Tables + * @param pBCT[] Array of Buffer Control Table(s) to set. Will be overwritten with response + * @return FSTATUS return code + */ +FSTATUS SmaSetBufferControlTable(struct omgt_port *port, + STL_LID dlid, + STL_LID slid, + uint8_t* path, + uint8_t startPort, + uint8_t endPort, + STL_BUFFER_CONTROL_TABLE pBCT[]) +{ + FSTATUS fstatus = FERROR; + uint8_t maxCount = (path == NULL ? STL_NUM_BFRCTLTAB_BLOCKS_PER_LID_SMP : STL_NUM_BFRCTLTAB_BLOCKS_PER_DRSMP); + uint8_t block; + int i; + char attributeName[64]; + uint32_t bufferLength = sizeof(STL_BUFFER_CONTROL_TABLE) * maxCount; + uint8_t buffer[bufferLength]; + uint8_t* data = buffer; + STL_BUFFER_CONTROL_TABLE *table = (STL_BUFFER_CONTROL_TABLE *)data; + memset(buffer, 0, bufferLength); + + snprintf(attributeName, sizeof(attributeName), "Set(BufferControlTable %u %u)", startPort, endPort); + debugLogSmaRequest(attributeName, path, dlid, slid); + + for (block = startPort; block <= endPort; block += maxCount) { + uint8_t numPorts = MIN(maxCount, (endPort - block)+1); + uint32_t amod = (numPorts << 24) | block; + + for (i = 0; i < numPorts; i++) { + memcpy(table, &pBCT[block-startPort+i], sizeof(STL_BUFFER_CONTROL_TABLE)); + BSWAP_STL_BUFFER_CONTROL_TABLE(table); + // Handle the dissimilar sizes of Buffer Table and 8-byte pad alignment + data += STL_BFRCTRLTAB_PAD_SIZE; + table = (STL_BUFFER_CONTROL_TABLE *)(data); + } + + fstatus = stl_sma_send_recv_mad(port, dlid, slid, path, MMTHD_SET, STL_MCLASS_ATTRIB_ID_BUFFER_CONTROL_TABLE, amod, buffer, sizeof(STL_BUFFER_CONTROL_TABLE)); + + if (fstatus == FSUCCESS) { + data = buffer; + table = (STL_BUFFER_CONTROL_TABLE*)data; + + for (i = 0; i < numPorts; i++) { + BSWAP_STL_BUFFER_CONTROL_TABLE(table); + memcpy(&pBCT[block-startPort+i], table, sizeof(STL_BUFFER_CONTROL_TABLE)); + // Handle the dissimilar sizes of Buffer Table and 8-byte pad alignment + data += STL_BFRCTRLTAB_PAD_SIZE; + table = (STL_BUFFER_CONTROL_TABLE *)(data); + } + } + } + + return fstatus; +} + +/** + * Set the Linear Forwarding Table of the requested LID/path + * Retry as needed if unable to send or don't get a response + * + * @param port The omgt_port to communicate with the fabric + * @param dlid Destination LID to send packet to + * @param slid Source LID of mixed LRDR packet. Path describes hops after reaching this LID + * @param path Directed route path to destination + * @param block Linear Forwarding Table block number + * @param pFDB Pointer to Linear Forwarding Table to set. Will be overwritten with response + * @return FSTATUS return code + */ +FSTATUS SmaSetLinearFDBTable(struct omgt_port *port, + STL_LID dlid, + STL_LID slid, + uint8_t* path, + uint16_t block, + STL_LINEAR_FORWARDING_TABLE *pFDB) +{ + FSTATUS fstatus; + uint32_t modifier; + char attributeName[64]; + uint32_t bufferLength = sizeof(STL_LINEAR_FORWARDING_TABLE); + uint8_t buffer[bufferLength]; + memset(buffer, 0, bufferLength); + + snprintf(attributeName, sizeof(attributeName), "Set(LFT %u)", block); + debugLogSmaRequest(attributeName, path, dlid, slid); + + modifier = 0x01000000 + (uint32_t)block; + + memcpy(buffer, pFDB, bufferLength); + BSWAP_STL_LINEAR_FORWARDING_TABLE((STL_LINEAR_FORWARDING_TABLE*)buffer); + + fstatus = stl_sma_send_recv_mad(port, dlid, slid, path, MMTHD_SET, STL_MCLASS_ATTRIB_ID_LINEAR_FWD_TABLE, modifier, buffer, bufferLength); + + if (fstatus == FSUCCESS) { + BSWAP_STL_LINEAR_FORWARDING_TABLE((STL_LINEAR_FORWARDING_TABLE*)buffer); + memcpy(pFDB, buffer, bufferLength); + } + return fstatus; +} + +/** + * Set the Multicast Forwarding Table of the requested LID/path + * Retry as needed if unable to send or don't get a response + * + * @param port The omgt_port to communicate with the fabric + * @param dlid Destination LID to send packet to + * @param slid Source LID of mixed LRDR packet. Path describes hops after reaching this LID + * @param path Directed route path to destination + * @param block Multicast Forwarding Table block number + * @param position Desired port mask for selected block (0-3) + * @param pFDB Pointer to Multicast Forwarding Table to set. Will be overwritten with response + * @return FSTATUS return code + */ +FSTATUS SmaSetMulticastFDBTable(struct omgt_port *port, + STL_LID dlid, + STL_LID slid, + uint8_t* path, + uint32_t block, + uint8_t position, + STL_MULTICAST_FORWARDING_TABLE *pFDB) +{ + FSTATUS fstatus; + char attributeName[64]; + uint32_t bufferLength = sizeof(STL_MULTICAST_FORWARDING_TABLE); + uint8_t buffer[bufferLength]; + memset(buffer, 0, bufferLength); + + snprintf(attributeName, sizeof(attributeName), "Set(MFT %u %u)", block, position); + debugLogSmaRequest(attributeName, path, dlid, slid); + + memcpy(buffer, pFDB, bufferLength); + BSWAP_STL_MULTICAST_FORWARDING_TABLE((STL_MULTICAST_FORWARDING_TABLE*)buffer); + + //@TODO: Enable multi-block requests from just a single block request + fstatus = stl_sma_send_recv_mad(port, dlid, slid, path, MMTHD_SET, STL_MCLASS_ATTRIB_ID_MCAST_FWD_TABLE, + (0x1<<24) | (0x3 & position)<<22 | (block & 0xfffff), buffer, bufferLength); + + if (fstatus == FSUCCESS) { + BSWAP_STL_MULTICAST_FORWARDING_TABLE((STL_MULTICAST_FORWARDING_TABLE*)buffer); + memcpy(pFDB, buffer, bufferLength); + } + return fstatus; +} + +/** + * Get the SmaGetCongestionInfo from the requested LID/path + * + * @param port The omgt_port to communicate with the fabric + * @param dlid Destination LID to send packet to + * @param slid Source LID of mixed LRDR packet. Path describes hops after reaching this LID + * @param path Directed route path to destination + * @param pCongestionInfo Pointer to allocated space to store the returned CongestionInfo + * @return FSTATUS return code + */ +FSTATUS SmaGetCongestionInfo(struct omgt_port *port, + STL_LID dlid, + STL_LID slid, + uint8_t* path, + STL_CONGESTION_INFO *pCongestionInfo) +{ + FSTATUS fstatus; + uint32_t bufferLength = sizeof(STL_CONGESTION_INFO); + uint8_t buffer[bufferLength]; + memset(buffer, 0, bufferLength); + + debugLogSmaRequest("Get(CongestionInfo)", path, dlid, slid); + + fstatus = stl_sma_send_recv_mad(port, dlid, slid, path, MMTHD_GET, STL_MCLASS_ATTRIB_ID_CONGESTION_INFO, 0, buffer, bufferLength); + + if (fstatus == FSUCCESS) { + BSWAP_STL_CONGESTION_INFO((STL_CONGESTION_INFO*)buffer); + memcpy(pCongestionInfo, buffer, bufferLength); + } + return fstatus; +} + +/** + * Get the SmaGetHFICongestionControlTable from the requested LID/path + * + * @param port The omgt_port to communicate with the fabric + * @param dlid Destination LID to send packet to + * @param slid Source LID of mixed LRDR packet. Path describes hops after reaching this LID + * @param path Directed route path to destination + * @param block Starting block value + * @param numBlocks Number of blocks in table + * @return FSTATUS return code + */ + +/* Maximum HFICCT size that can fit in a MAD packet */ +#define HFICCTI_MAX_BLOCK 14 +FSTATUS SmaGetHFICongestionControlTable(struct omgt_port *port, + STL_LID dlid, + STL_LID slid, + uint8_t* path, + uint16_t block, + uint16_t numBlocks, + STL_HFI_CONGESTION_CONTROL_TABLE *pHfiCongestionControl) +{ + FSTATUS fstatus; + + if (numBlocks < 1 || numBlocks > HFICCTI_MAX_BLOCK) + return FERROR; + + uint32_t bufferLength = sizeof(STL_HFI_CONGESTION_CONTROL_TABLE) + + sizeof(STL_HFI_CONGESTION_CONTROL_TABLE_BLOCK) * (numBlocks - 1); + + uint8_t buffer[bufferLength]; + uint32_t amod = (numBlocks<<24) | (block & 0xff); + + memset(buffer, 0, bufferLength); + + debugLogSmaRequest("Get(HFICongestionControlTable)", path, dlid, slid); + + fstatus = stl_sma_send_recv_mad(port, dlid, slid, path, MMTHD_GET, STL_MCLASS_ATTRIB_ID_HFI_CONGESTION_CONTROL_TABLE, amod, buffer, bufferLength); + + if (fstatus != FSUCCESS) + return fstatus; + + BSWAP_STL_HFI_CONGESTION_CONTROL_TABLE((STL_HFI_CONGESTION_CONTROL_TABLE*)buffer, numBlocks); + memcpy(pHfiCongestionControl, buffer, bufferLength); + + return FSUCCESS; +} + +#endif // PRODUCT_OPENIB_FF + +/* process a PMA class port info or redirection required response + * save capability mask and update redirectp as needed + */ +static FSTATUS ProcessPmaClassPortInfo(PortData* portp, STL_CLASS_PORT_INFO *classp, + IB_PATH_RECORD *orig_pathp) +{ + portp->PmaGotClassPortInfo = 1; + BSWAP_STL_CLASS_PORT_INFO(classp); + + DBGPRINT("PMA ClassPortInfo.CapMask = 0x%x\n", classp->CapMask); + return FSUCCESS; +} + +/* issue a single PMA mad and get the response. + * Retry as needed if unable to send or don't get a response + */ +static FSTATUS stl_pm_send_recv_mad(struct omgt_port *port, IB_PATH_RECORD *pathp, + uint32 qpn, uint32 qkey, uint8 method, uint32 attr, uint32 modifier, STL_PERF_MAD *mad) +{ + FSTATUS fstatus; + struct omgt_mad_addr addr; + size_t recv_size; + + memset(&addr, 0, sizeof(addr)); + addr.lid = pathp->DLID; + addr.qpn = qpn; + addr.qkey = qkey; + addr.pkey = pathp->P_Key; + addr.sl = pathp->u2.s.SL; + + mad->common.BaseVersion = STL_BASE_VERSION; + mad->common.MgmtClass = MCLASS_PERF; + mad->common.ClassVersion = STL_PM_CLASS_VERSION; + mad->common.mr.AsReg8 = 0; + mad->common.mr.s.Method = method; + mad->common.u.NS.Status.AsReg16 = 0; +#if defined(IB_STACK_IBACCESS) || defined(CAL_IBACCESS) + mad->common.TransactionID = (++g_transId)<<24; +#else + mad->common.TransactionID = (++g_transId) & 0xffffffff; +#endif + mad->common.AttributeID = attr; + mad->common.AttributeModifier = modifier; + // rest of fields should be ignored for a Get, zero'ed above + BSWAP_MAD_HEADER((MAD*)mad); +#ifdef IB_DEBUG + DBGPRINT("Sending MAD:\n"); + DumpMad(mad); +#endif + + ASSERT(pathp->DLID); + + recv_size = sizeof(*mad); + fstatus = omgt_send_recv_mad_no_alloc(port, + (uint8_t *)mad, sizeof(*mad), + &addr, + (uint8_t *)mad, &recv_size, + RESP_WAIT_TIME, + g_smaRetries-1); + +#ifdef IB_DEBUG + if (fstatus == FSUCCESS) { + DBGPRINT("Received MAD:\n"); + DumpMad(mad); + } +#endif + BSWAP_MAD_HEADER((MAD*)mad); + //DBGPRINT("send_recv_mad fstatus=%s\n", iba_fstatus_msg(fstatus)); + return fstatus; +} + +/* issue a single PMA request and get the response. + * Retry as needed if unable to send or don't get a response + * portp is the port to issue PMA request to (can be port 0 of switch), it need + * not match portNum. + * Handle PMA redirection (currently not supported) here. + */ +static FSTATUS stl_pm_send_recv(struct omgt_port *port, PortData *portp, uint8 method, + uint32 attr, uint32 modifier, STL_PERF_MAD *req, STL_PERF_MAD *resp) +{ + FSTATUS fstatus; + int attempts = 2; // only a single 2nd attempt with redirection + + do { + IB_PATH_RECORD *pathp; + uint32 qpn; + uint32 qkey; + + pathp = portp->pathp; + qpn = 1; + qkey = QP1_WELL_KNOWN_Q_KEY; + + *resp = *req; + //DBGPRINT("LID=0x%x SL=%d PKey=0x%x\n", pathp->DLID, pathp->u2.s.SL, pathp->P_Key); + fstatus = stl_pm_send_recv_mad(port, pathp, qpn, qkey, method, attr, modifier, resp); + if (FSUCCESS != fstatus) { + //DBGPRINT("pm_send_recv_mad fstatus=%s\n", iba_fstatus_msg(fstatus)); + goto fail; + } + if (resp->common.u.NS.Status.AsReg16 != MAD_STATUS_SUCCESS) { + DBGPRINT("PMA response with bad status: 0x%x\n", resp->common.u.NS.Status.AsReg16); + fstatus = FERROR; + goto fail; + } + } while (FSUCCESS != fstatus && --attempts); +fail: + return fstatus; +} + +/* Get STL Class Port Info from PMA at portp + * Retry and handle redirection as needed + * portp is the port to issue PMA request to (can be port 0 of switch) + * The portp is updated with the CLASS_PORT_INFO redirect and PMA CapMask + */ +FSTATUS STLPmGetClassPortInfo(struct omgt_port *port, PortData *portp) +{ + STL_PERF_MAD req; + STL_PERF_MAD resp; + FSTATUS fstatus; + + if (portp->PmaGotClassPortInfo) + return FSUCCESS; // if we already have, no use asking again + MemoryClear(&req, sizeof(req)); + + DBGPRINT("Sending PM Get(ClassPortInfo) to LID 0x%08x Node 0x%016"PRIx64"\n", + portp->pathp->DLID, + portp->nodep->NodeInfo.NodeGUID); + DBGPRINT(" Name: %.*s\n", + NODE_DESCRIPTION_ARRAY_SIZE, + (char*)portp->nodep->NodeDesc.NodeString); + fstatus = stl_pm_send_recv(port, portp, MMTHD_GET, STL_PM_ATTRIB_ID_CLASS_PORTINFO, + 0, &req, &resp); + if (FSUCCESS != fstatus) + goto fail; + fstatus = ProcessPmaClassPortInfo(portp, (STL_CLASS_PORT_INFO*)&(resp.PerfData), + portp->pathp); +fail: + return fstatus; +} + +/* Get Port counters from PMA at portp for given PortNum + * Retry and handle redirection as needed + * portp is the port to issue PMA request to (can be port 0 of switch), it need + */ +FSTATUS STLPmGetPortStatus(struct omgt_port *port, PortData *portp, uint8 portNum, + STL_PORT_STATUS_RSP *pPortStatus) +{ + STL_PERF_MAD req; + STL_PERF_MAD resp; + STL_PORT_STATUS_REQ* p = (STL_PORT_STATUS_REQ *)&(req.PerfData); + FSTATUS fstatus; + + MemoryClear(&req, sizeof(req)); + // rest of fields should be ignored for a Get, zero'ed above + p->PortNumber = portNum; + p->VLSelectMask = 0x8001; // only do VLs 15 and 0 for now, we will ignore VL counters for now + BSWAP_STL_PORT_STATUS_REQ(p); + + DBGPRINT("Sending STL PM Get(PortStatus %d) to LID 0x%04x Node 0x%016"PRIx64"\n", + portNum, portp->pathp->DLID, + portp->nodep->NodeInfo.NodeGUID); + DBGPRINT(" Name: %.*s\n", + NODE_DESCRIPTION_ARRAY_SIZE, + (char*)portp->nodep->NodeDesc.NodeString); + fstatus = stl_pm_send_recv(port, portp, MMTHD_GET, STL_PM_ATTRIB_ID_PORT_STATUS, + 0x01000000, &req, &resp); + if (FSUCCESS != fstatus) + goto fail; + BSWAP_STL_PORT_STATUS_RSP((STL_PORT_STATUS_RSP *)resp.PerfData); + *pPortStatus = *(STL_PORT_STATUS_RSP *)resp.PerfData; + DBGPRINT("SendPkts=0x%16"PRIx64"\n", pPortStatus->PortXmitPkts); +fail: + return fstatus; +} + +/* Clear port counters issued to PMA at portp. + * portp is the port to issue the PMA request to (can be port 0, + * thought lastPortIndex MUST be 0 in this case - see below). + * + * If lastPortIndex > 0, then it's assumed portp is + * switch port 0, and send a ClearPortCounters for all ports up to lastPortIndex. + * Otherwise assume this is an HFI, and only clear the port at portp. + * Retry and handle redirection as needed + * If thresholds is non-NULL, only counters with non-zero threshold are cleared + * otherwise all counters are cleared + */ +FSTATUS STLPmClearPortCounters(struct omgt_port *port, PortData *portp, uint8 lastPortIndex, + uint32 counterselect) +{ + STL_PERF_MAD req; + STL_PERF_MAD resp; + STL_CLEAR_PORT_STATUS* p = (STL_CLEAR_PORT_STATUS *)&(req.PerfData); + FSTATUS fstatus; + uint8_t i; + char debugStr[64] = {'\0'}; + + MemoryClear(&req, sizeof(req)); + + for (i = 0; i < (lastPortIndex / 64); ++i) + p->PortSelectMask[3 - i] = ~(0ULL); + + if (lastPortIndex) + p->PortSelectMask[3 - i] = (1ULL<<(lastPortIndex + 1)) - 1; // All ports up to lastPortIndex masked. + else + p->PortSelectMask[3] = 1<PortNum; // HFI Case. + + p->CounterSelectMask.AsReg32 = counterselect; + + if (g_verbose_file) { + if (lastPortIndex) + sprintf(debugStr, "port range [%d-%d]", portp->PortNum, lastPortIndex); + else + sprintf(debugStr, "port %d", portp->PortNum); + } + DBGPRINT("Sending PM Set(PortStatus %s, Sel=0x%04x) to LID 0x%04x Node 0x%016"PRIx64"\n", + debugStr, p->CounterSelectMask.AsReg32, portp->pathp->DLID, + portp->nodep->NodeInfo.NodeGUID); + DBGPRINT(" Name: %.*s\n", + NODE_DESCRIPTION_ARRAY_SIZE, + (char*)portp->nodep->NodeDesc.NodeString); + BSWAP_STL_CLEAR_PORT_STATUS_REQ(p); + fstatus = stl_pm_send_recv(port, portp, MMTHD_SET, STL_PM_ATTRIB_ID_CLEAR_PORT_STATUS, + 1<<24, &req, &resp); + if (FSUCCESS != fstatus) { + //DBGPRINT("stl_pm_send_recv fstatus=%s\n", iba_fstatus_msg(fstatus)); + goto fail; + } +fail: + return fstatus; +} + + +#if !defined(VXWORKS) || defined(BUILD_DMC) +static FSTATUS dm_send_recv(struct omgt_port *port, + IB_PATH_RECORD *pathp, + uint32 attr, + uint32 modifier, + DM_MAD *mad) +{ + FSTATUS fstatus; + struct omgt_mad_addr addr; + size_t recv_size; + + memset(&addr, 0, sizeof(addr)); + addr.lid = pathp->DLID; + if (pathp->u1.s.HopLimit == 1) { + if ((pathp->DGID.Type.Global.InterfaceID >> 40) == OUI_TRUESCALE) + addr.lid = pathp->DGID.Type.Global.InterfaceID & 0xFFFFFFFF; + } + addr.qpn = 1; + addr.qkey = QP1_WELL_KNOWN_Q_KEY; + addr.pkey = pathp->P_Key; + + mad->common.BaseVersion = IB_BASE_VERSION; + mad->common.MgmtClass = MCLASS_DEV_MGT; + mad->common.ClassVersion = IB_DEV_MGT_CLASS_VERSION; + mad->common.mr.AsReg8 = 0; + mad->common.mr.s.Method = MMTHD_GET; +#if defined(IB_STACK_IBACCESS) || defined(CAL_IBACCESS) + mad->common.TransactionID = (++g_transId) << 24; +#else + mad->common.TransactionID = (++g_transId) & 0xffffffff; +#endif + mad->common.AttributeID = attr; + mad->common.AttributeModifier = modifier; + // rest of fields should be ignored for a Get, zero'ed above + BSWAP_MAD_HEADER((MAD*)mad); + + ASSERT(addr.lid); + recv_size = sizeof(*mad); + fstatus = omgt_send_recv_mad_no_alloc(port, + (uint8_t *)mad, sizeof(*mad), + &addr, + (uint8_t *)mad, &recv_size, + RESP_WAIT_TIME, + g_smaRetries-1); + + BSWAP_MAD_HEADER((MAD*)mad); + if (FSUCCESS == fstatus && mad->common.u.NS.Status.AsReg16 != MAD_STATUS_SUCCESS) { + DBGPRINT("DMA response with bad status: 0x%x\n", mad->common.u.NS.Status.AsReg16); + fstatus = FERROR; + } + return fstatus; +} + +FSTATUS DmGetIouInfo(struct omgt_port *port, IB_PATH_RECORD *pathp, IOUnitInfo *pIouInfo) +{ + DM_MAD mad; + FSTATUS fstatus; + + MemoryClear(&mad, sizeof(mad)); + DBGPRINT("Sending DM Get(IouInfo) to LID 0x%04x\n", pathp->DLID); + fstatus = dm_send_recv(port, pathp, DM_ATTRIB_ID_IOUNIT_INFO, 0, &mad); + if (FSUCCESS != fstatus) + goto fail; + *pIouInfo = *(IOUnitInfo*)mad.DMData; + BSWAP_DM_IOUNIT_INFO(pIouInfo); +fail: + return fstatus; +} + +FSTATUS DmGetIocProfile(struct omgt_port *port, + IB_PATH_RECORD *pathp, + uint8 slot, + IOC_PROFILE *pIocProfile) +{ + DM_MAD mad; + FSTATUS fstatus; + + MemoryClear(&mad, sizeof(mad)); + DBGPRINT("Sending DM Get(IocProfile, %u) to LID 0x%04x\n", slot, pathp->DLID); + fstatus = dm_send_recv(port, pathp, DM_ATTRIB_ID_IOCONTROLLER_PROFILE, slot, &mad); + if (FSUCCESS != fstatus) + goto fail; + *pIocProfile = *(IOC_PROFILE*)mad.DMData; + BSWAP_DM_IOC_PROFILE(pIocProfile); +fail: + return fstatus; +} + +/* last - first must be <= 3 */ +FSTATUS DmGetServiceEntries(struct omgt_port *port, + IB_PATH_RECORD *pathp, + uint8 slot, + uint8 first, + uint8 last, + IOC_SERVICE *pIocServices) +{ + DM_MAD mad; + FSTATUS fstatus; + IOC_SERVICE *p; + + MemoryClear(&mad, sizeof(mad)); + DBGPRINT("Sending DM Get(ServiceEntries, %u, %u-%u) to LID 0x%04x\n", + slot, first, last, pathp->DLID); + fstatus = dm_send_recv(port, pathp, DM_ATTRIB_ID_SERVICE_ENTRIES, + DM_ATTRIB_MODIFIER_SERVICE_ENTRIES(slot, first, last), &mad); + if (FSUCCESS != fstatus) + goto fail; + p = (IOC_SERVICE*)mad.DMData; + for (; first <= last; first++, pIocServices++,p++) { + *pIocServices = *p; + BSWAP_DM_IOC_SERVICE(pIocServices); + } +fail: + return fstatus; +} +#endif + +FSTATUS InitSmaMkey(uint64 mkey) +{ + g_mkey = mkey; + return FSUCCESS; +} + +FSTATUS InitMad(EUI64 portguid, FILE *verbose_file) +{ + g_verbose_file = verbose_file; +#if defined(IB_STACK_IBACCESS) || defined(CAL_IBACCESS) + return registerUmadt(portguid, &g_umadtHandle); +#else + return FSUCCESS; +#endif +} + +void DestroyMad(void) +{ +#if defined(IB_STACK_IBACCESS) || defined(CAL_IBACCESS) + if (g_umadtHandle) { + flush_rcv(g_umadtHandle, FLUSH_WAIT_TIME); + (void)iba_umadt_deregister(g_umadtHandle); + } +#endif +} diff --git a/Topology/mad_info.c b/Topology/mad_info.c new file mode 100644 index 0000000..7b82c16 --- /dev/null +++ b/Topology/mad_info.c @@ -0,0 +1,56 @@ +/* BEGIN_ICS_COPYRIGHT7 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT7 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +#include "topology.h" +#include "topology_internal.h" +#include + +/* indicate if the given port supports a PMA */ +boolean NodeHasPma(NodeData *nodep) +{ + if (nodep->PmaAvoid) + return FALSE; + + return TRUE; +} + +/* indicate if the given port supports a PMA */ +boolean PortHasPma(PortData *portp) +{ + + return NodeHasPma(portp->nodep); +} + +/* Based on Node, determine PMA capabilities and limitations */ +/* this does not issue any packets on wire */ +void UpdateNodePmaCapabilities(NodeData *nodep, boolean ProcessHFICounters) +{ +} diff --git a/Topology/point.c b/Topology/point.c new file mode 100644 index 0000000..7012bb4 --- /dev/null +++ b/Topology/point.c @@ -0,0 +1,1463 @@ +/* BEGIN_ICS_COPYRIGHT7 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT7 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +#include "topology.h" +#include "topology_internal.h" + +// functions to build and compare POINTs + +#define MIN_LIST_ITEMS 100 // minimum items for ListInit to allocate for + +void PointInit(Point *point) +{ + point->Type = POINT_TYPE_NONE; + point->haveSW = FALSE; + point->haveFI = FALSE; + point->EnodeType = POINT_ENODE_TYPE_NONE; + point->EsmType = POINT_ESM_TYPE_NONE; + point->ElinkType = POINT_ELINK_TYPE_NONE; +} + +/* initialize a non-list point */ +static void PointInitSimple(Point *point, PointType type, void *object) +{ + point->Type = type; + + switch (type) { + case POINT_TYPE_NONE: + ASSERT(object == NULL); + return; + case POINT_TYPE_PORT: + ASSERT(object); + point->u.portp = (PortData*)object; + return; + case POINT_TYPE_NODE: + ASSERT(object); + point->u.nodep = (NodeData*)object; + return; +#if !defined(VXWORKS) || defined(BUILD_DMC) + case POINT_TYPE_IOC: + ASSERT(object); + point->u.iocp = (IocData*)object; + return; +#endif + case POINT_TYPE_SYSTEM: + ASSERT(object); + point->u.systemp = (SystemData*)object; + return; + case POINT_TYPE_PORT_LIST: + case POINT_TYPE_NODE_LIST: + case POINT_TYPE_NODE_PAIR_LIST: +#if !defined(VXWORKS) || defined(BUILD_DMC) + case POINT_TYPE_IOC_LIST: +#endif + default: + ASSERT(0); + point->Type = POINT_TYPE_NONE; + return; + } +} + +/* initialize a non-list ExpectedNode point */ +static void PointInitEnodeSimple(Point *point, PointEnodeType type, void *object) +{ + point->EnodeType = type; + + switch (type) { + case POINT_ENODE_TYPE_NONE: + ASSERT(object == NULL); + return; + case POINT_ENODE_TYPE_NODE: + ASSERT(object); + point->u2.enodep = (ExpectedNode*)object; + return; + case POINT_ENODE_TYPE_NODE_LIST: + default: + ASSERT(0); + point->EnodeType = POINT_ENODE_TYPE_NONE; + return; + } +} + +/* initialize a non-list ExpectedSM point */ +static void PointInitEsmSimple(Point *point, PointEsmType type, void *object) +{ + point->EsmType = type; + + switch (type) { + case POINT_ESM_TYPE_NONE: + ASSERT(object == NULL); + return; + case POINT_ESM_TYPE_SM: + ASSERT(object); + point->u3.esmp = (ExpectedSM*)object; + return; + case POINT_ESM_TYPE_SM_LIST: + default: + ASSERT(0); + point->EsmType = POINT_ESM_TYPE_NONE; + return; + } +} + +/* initialize a non-list ExpectedLink point */ +static void PointInitElinkSimple(Point *point, PointElinkType type, void *object) +{ + point->ElinkType = type; + + switch (type) { + case POINT_ELINK_TYPE_NONE: + ASSERT(object == NULL); + return; + case POINT_ELINK_TYPE_LINK: + ASSERT(object); + point->u4.elinkp = (ExpectedLink*)object; + return; + case POINT_ELINK_TYPE_LINK_LIST: + default: + ASSERT(0); + point->ElinkType = POINT_ELINK_TYPE_NONE; + return; + } +} + +/* initialize a list point - sets it as an empty list */ +static FSTATUS PointInitList(Point *point, PointType type) +{ + DLIST *pList = NULL; + DLIST *pList2 = NULL; + + point->Type = POINT_TYPE_NONE; + switch (type) { + case POINT_TYPE_PORT_LIST: + pList = &point->u.portList; + break; + case POINT_TYPE_NODE_LIST: + pList = &point->u.nodeList; + break; +#if !defined(VXWORKS) || defined(BUILD_DMC) + case POINT_TYPE_IOC_LIST: + pList = &point->u.iocList; + break; +#endif + case POINT_TYPE_NODE_PAIR_LIST: + pList = &point->u.nodePairList.nodePairList1; + pList2 = &point->u.nodePairList.nodePairList2; + //Initialize the Right of the list here. The Left side is done with the rest. + ListInitState(pList2); + if (! ListInit(pList2, MIN_LIST_ITEMS)) { + fprintf(stderr, "%s: unable to allocate memory\n", g_Top_cmdname); + return FINSUFFICIENT_MEMORY; + } + break; + default: + ASSERT(0); + return FINVALID_OPERATION; + } + ListInitState(pList); + if (! ListInit(pList, MIN_LIST_ITEMS)) { + fprintf(stderr, "%s: unable to allocate memory\n", g_Top_cmdname); + if(pList2) + ListDestroy(pList2); + return FINSUFFICIENT_MEMORY; + } + point->Type = type; + return FSUCCESS; +} + +/* initialize an ExpectedNode list point - sets it as an empty list */ +static FSTATUS PointInitEnodeList(Point *point, PointEnodeType type) +{ + DLIST *pList; + + point->EnodeType = POINT_ENODE_TYPE_NONE; + switch (type) { + case POINT_ENODE_TYPE_NODE_LIST: + pList = &point->u2.enodeList; + break; + default: + ASSERT(0); + return FINVALID_OPERATION; + } + ListInitState(pList); + if (! ListInit(pList, MIN_LIST_ITEMS)) { + fprintf(stderr, "%s: unable to allocate memory\n", g_Top_cmdname); + return FINSUFFICIENT_MEMORY; + } + point->EnodeType = type; + return FSUCCESS; +} + +/* initialize an ExpectedSM list point - sets it as an empty list */ +static FSTATUS PointInitEsmList(Point *point, PointEsmType type) +{ + DLIST *pList; + + point->EsmType = POINT_ESM_TYPE_NONE; + switch (type) { + case POINT_ESM_TYPE_SM_LIST: + pList = &point->u3.esmList; + break; + default: + ASSERT(0); + return FINVALID_OPERATION; + } + ListInitState(pList); + if (! ListInit(pList, MIN_LIST_ITEMS)) { + fprintf(stderr, "%s: unable to allocate memory\n", g_Top_cmdname); + return FINSUFFICIENT_MEMORY; + } + point->EsmType = type; + return FSUCCESS; +} + +/* initialize an ExpectedLink list point - sets it as an empty list */ +static FSTATUS PointInitElinkList(Point *point, PointElinkType type) +{ + DLIST *pList; + + point->ElinkType = POINT_ELINK_TYPE_NONE; + switch (type) { + case POINT_ELINK_TYPE_LINK_LIST: + pList = &point->u4.elinkList; + break; + default: + ASSERT(0); + return FINVALID_OPERATION; + } + ListInitState(pList); + if (! ListInit(pList, MIN_LIST_ITEMS)) { + fprintf(stderr, "%s: unable to allocate memory\n", g_Top_cmdname); + return FINSUFFICIENT_MEMORY; + } + point->ElinkType = type; + return FSUCCESS; +} + +void PointFabricDestroy(Point *point) +{ + switch (point->Type) { + case POINT_TYPE_PORT_LIST: + ListDestroy(&point->u.portList); + break; + case POINT_TYPE_NODE_LIST: + ListDestroy(&point->u.nodeList); + break; +#if !defined(VXWORKS) || defined(BUILD_DMC) + case POINT_TYPE_IOC_LIST: + ListDestroy(&point->u.iocList); + break; +#endif + case POINT_TYPE_NODE_PAIR_LIST: + ListDestroy(&point->u.nodePairList.nodePairList1); + ListDestroy(&point->u.nodePairList.nodePairList2); + default: + break; + } + point->Type = POINT_TYPE_NONE; +} + +void PointEnodeDestroy(Point *point) +{ + switch (point->EnodeType) { + case POINT_ENODE_TYPE_NODE_LIST: + ListDestroy(&point->u2.enodeList); + break; + default: + break; + } + point->EnodeType = POINT_ENODE_TYPE_NONE; +} + +void PointEsmDestroy(Point *point) +{ + switch (point->EsmType) { + case POINT_ESM_TYPE_SM_LIST: + ListDestroy(&point->u3.esmList); + break; + default: + break; + } + point->EsmType = POINT_ESM_TYPE_NONE; +} + +void PointElinkDestroy(Point *point) +{ + switch (point->ElinkType) { + case POINT_ELINK_TYPE_LINK_LIST: + ListDestroy(&point->u4.elinkList); + break; + default: + break; + } + point->ElinkType = POINT_ELINK_TYPE_NONE; +} + +void PointDestroy(Point *point) +{ + PointFabricDestroy(point); + PointEnodeDestroy(point); + PointEsmDestroy(point); + PointElinkDestroy(point); +} + +/* is the point valid (eg. successfully parsed and/or populated) + * PointInit and PointDestroy will return a point to an invalid state + * PointParseFocus if sucessful will leave a point in a valid state + */ +boolean PointValid(Point *point) +{ + return (point && (point->Type != POINT_TYPE_NONE + || point->EnodeType != POINT_ENODE_TYPE_NONE + || point->EsmType != POINT_ESM_TYPE_NONE + || point->ElinkType != POINT_ELINK_TYPE_NONE)); +} + +/* Checks the point is in Init state */ +boolean PointIsInInit(Point *point) +{ + return (point && (point->Type == POINT_TYPE_NONE + && point->EnodeType == POINT_ENODE_TYPE_NONE + && point->EsmType == POINT_ESM_TYPE_NONE + && point->ElinkType == POINT_ELINK_TYPE_NONE)); +} + +/* append object to the list + * if this is the 1st insert to a "None" Point, it will initialize the + * list and set the point type. + * On failure, the point is destroyed by this routine + */ +FSTATUS PointListAppend(Point *point, PointType type, void *object) +{ + FSTATUS status; + DLIST *pList; + + if (point->Type == POINT_TYPE_NONE) { + status = PointInitList(point, type); + if (FSUCCESS != status) { + PointDestroy(point); + return status; + } + } else if (type != point->Type) { + ASSERT(0); + PointDestroy(point); + return FINVALID_OPERATION; + } + switch (type) { + case POINT_TYPE_PORT_LIST: + pList = &point->u.portList; + break; + case POINT_TYPE_NODE_LIST: + pList = &point->u.nodeList; + break; +#if !defined(VXWORKS) || defined(BUILD_DMC) + case POINT_TYPE_IOC_LIST: + pList = &point->u.iocList; + break; +#endif + default: + ASSERT(0); + PointDestroy(point); + return FINVALID_OPERATION; + } + if (! ListInsertTail(pList, object)) { + fprintf(stderr, "%s: unable to allocate memory\n", g_Top_cmdname); + PointDestroy(point); + return FINSUFFICIENT_MEMORY; + } + return FSUCCESS; +} + +/* append object to the ExpectedNode list + * if this is the 1st insert to a "None" Point, it will initialize the + * list and set the point enode type. + * Failures imply a caller bug or a failure to allocate memory + * On failure, the point is destroyed by this routine + */ +FSTATUS PointEnodeListAppend(Point *point, PointEnodeType type, void *object) +{ + FSTATUS status; + DLIST *pList; + + if (point->EnodeType == POINT_ENODE_TYPE_NONE) { + status = PointInitEnodeList(point, type); + if (FSUCCESS != status) { + PointDestroy(point); + return status; + } + } else if (type != point->EnodeType) { + ASSERT(0); + PointDestroy(point); + return FINVALID_OPERATION; + } + switch (type) { + case POINT_ENODE_TYPE_NODE_LIST: + pList = &point->u2.enodeList; + break; + default: + ASSERT(0); + PointDestroy(point); + return FINVALID_OPERATION; + } + if (! ListInsertTail(pList, object)) { + fprintf(stderr, "%s: unable to allocate memory\n", g_Top_cmdname); + PointDestroy(point); + return FINSUFFICIENT_MEMORY; + } + return FSUCCESS; +} + +/* append object to the ExpectedSM list + * if this is the 1st insert to a "None" Point, it will initialize the + * list and set the point enode type. + * Failures imply a caller bug or a failure to allocate memory + * On failure, the point is destroyed by this routine + */ +FSTATUS PointEsmListAppend(Point *point, PointEsmType type, void *object) +{ + FSTATUS status; + DLIST *pList; + + if (point->EsmType == POINT_ESM_TYPE_NONE) { + status = PointInitEsmList(point, type); + if (FSUCCESS != status) { + PointDestroy(point); + return status; + } + } else if (type != point->EsmType) { + ASSERT(0); + PointDestroy(point); + return FINVALID_OPERATION; + } + switch (type) { + case POINT_ESM_TYPE_SM_LIST: + pList = &point->u3.esmList; + break; + default: + ASSERT(0); + PointDestroy(point); + return FINVALID_OPERATION; + } + if (! ListInsertTail(pList, object)) { + fprintf(stderr, "%s: unable to allocate memory\n", g_Top_cmdname); + PointDestroy(point); + return FINSUFFICIENT_MEMORY; + } + return FSUCCESS; +} + +/* append object to the ExpectedLink list + * if this is the 1st insert to a "None" Point, it will initialize the + * list and set the point enode type. + * Failures imply a caller bug or a failure to allocate memory + * On failure, the point is destroyed by this routine + */ +FSTATUS PointElinkListAppend(Point *point, PointElinkType type, void *object) +{ + FSTATUS status; + DLIST *pList; + + if (point->ElinkType == POINT_ELINK_TYPE_NONE) { + status = PointInitElinkList(point, type); + if (FSUCCESS != status) { + PointDestroy(point); + return status; + } + } else if (type != point->ElinkType) { + ASSERT(0); + PointDestroy(point); + return FINVALID_OPERATION; + } + switch (type) { + case POINT_ELINK_TYPE_LINK_LIST: + pList = &point->u4.elinkList; + break; + default: + ASSERT(0); + PointDestroy(point); + return FINVALID_OPERATION; + } + if (! ListInsertTail(pList, object)) { + fprintf(stderr, "%s: unable to allocate memory\n", g_Top_cmdname); + PointDestroy(point); + return FINSUFFICIENT_MEMORY; + } + return FSUCCESS; +} + +/* append object to the list + * if this is the 1st insert to a "None" Point, it will initialize the + * list and set the point type. + * On failure, the point is destroyed by this routine + */ +FSTATUS PointNodePairListAppend(Point *point, uint8 side, void *object) +{ + FSTATUS status; + DLIST *pList; + + if (point->Type == POINT_TYPE_NONE) { + status = PointInitList(point, POINT_TYPE_NODE_PAIR_LIST); + if (FSUCCESS != status) { + PointDestroy(point); + return status; + } + } else if (POINT_TYPE_NODE_PAIR_LIST != point->Type) { + ASSERT(0); + PointDestroy(point); + return FINVALID_OPERATION; + } + + if (side == LSIDE_PAIR){ + pList = &point->u.nodePairList.nodePairList1; + } else if(side == RSIDE_PAIR) { + pList = &point->u.nodePairList.nodePairList2; + } else { + ASSERT(0); + PointDestroy(point); + return FINVALID_OPERATION; + } + + if (!ListInsertTail(pList, object)) { + fprintf(stderr, "%s: unable to allocate memory\n", g_Top_cmdname); + PointDestroy(point); + return FINSUFFICIENT_MEMORY; + } + + return FSUCCESS; +} + +/* Failures imply a caller bug or a failure to allocate memory */ +/* On failure will Destroy the whole dest point leaving it !PointValid */ +FSTATUS PointFabricCopy(Point *dest, Point *src) +{ + FSTATUS status; + LIST_ITERATOR i; + DLIST *pSrcList; + + PointFabricDestroy(dest); + + pSrcList = NULL; + switch (src->Type) { + case POINT_TYPE_PORT: + case POINT_TYPE_NODE: +#if !defined(VXWORKS) || defined(BUILD_DMC) + case POINT_TYPE_IOC: +#endif + case POINT_TYPE_SYSTEM: + default: + *dest = *src; + break; + case POINT_TYPE_PORT_LIST: + pSrcList = &src->u.portList; + break; + case POINT_TYPE_NODE_LIST: + pSrcList = &src->u.nodeList; + break; +#if !defined(VXWORKS) || defined(BUILD_DMC) + case POINT_TYPE_IOC_LIST: + pSrcList = &src->u.iocList; + break; +#endif + case POINT_TYPE_NODE_PAIR_LIST: + ASSERT(0); //don't come here + break; + } + if (pSrcList) { + for (i=ListHead(pSrcList); i != NULL; i = ListNext(pSrcList, i)) { + /* on failure Append will Destroy the whole point */ + status = PointListAppend(dest, src->Type, ListObj(i)); + if (FSUCCESS != status) + return status; + } + } + return FSUCCESS; +} + + +/* Failures imply a caller bug or a failure to allocate memory */ +/* On failure will Destroy the whole dest point leaving it !PointValid */ +FSTATUS PointEnodeCopy(Point *dest, Point *src) +{ + FSTATUS status; + LIST_ITERATOR i; + DLIST *pSrcList; + + PointEnodeDestroy(dest); + pSrcList = NULL; + switch (src->EnodeType) { + case POINT_ENODE_TYPE_NONE: + case POINT_ENODE_TYPE_NODE: + *dest = *src; + break; + case POINT_ENODE_TYPE_NODE_LIST: + pSrcList = &src->u2.enodeList; + break; + } + + if (pSrcList) { + for (i=ListHead(pSrcList); i != NULL; i = ListNext(pSrcList, i)) { + /* on failure Append will Destroy the whole point */ + status = PointEnodeListAppend(dest, src->EnodeType, ListObj(i)); + if (FSUCCESS != status) + return status; + } + } + return FSUCCESS; +} + +/* Failures imply a caller bug or a failure to allocate memory */ +/* On failure will Destroy the whole dest point leaving it !PointValid */ +FSTATUS PointEsmCopy(Point *dest, Point *src) +{ + FSTATUS status; + LIST_ITERATOR i; + DLIST *pSrcList; + + PointEsmDestroy(dest); + pSrcList = NULL; + switch (src->EsmType) { + case POINT_ESM_TYPE_NONE: + case POINT_ESM_TYPE_SM: + *dest = *src; + break; + case POINT_ESM_TYPE_SM_LIST: + pSrcList = &src->u3.esmList; + break; + } + + if (pSrcList) { + for (i=ListHead(pSrcList); i != NULL; i = ListNext(pSrcList, i)) { + /* on failure Append will Destroy the whole point */ + status = PointEsmListAppend(dest, src->EsmType, ListObj(i)); + if (FSUCCESS != status) + return status; + } + } + return FSUCCESS; +} + +/* Failures imply a caller bug or a failure to allocate memory */ +/* On failure will Destroy the whole dest point leaving it !PointValid */ +FSTATUS PointElinkCopy(Point *dest, Point *src) +{ + FSTATUS status; + LIST_ITERATOR i; + DLIST *pSrcList; + + PointElinkDestroy(dest); + pSrcList = NULL; + switch (src->ElinkType) { + case POINT_ELINK_TYPE_NONE: + case POINT_ELINK_TYPE_LINK: + *dest = *src; + break; + case POINT_ELINK_TYPE_LINK_LIST: + pSrcList = &src->u4.elinkList; + break; + } + + if (pSrcList) { + for (i=ListHead(pSrcList); i != NULL; i = ListNext(pSrcList, i)) { + /* on failure Append will Destroy the whole point */ + status = PointElinkListAppend(dest, src->ElinkType, ListObj(i)); + if (FSUCCESS != status) + return status; + } + } + return FSUCCESS; +} + +/* Failures imply a caller bug or a failure to allocate memory */ +/* On failure will Destroy the whole dest point leaving it !PointValid */ +FSTATUS PointCopy(Point *dest, Point *src) +{ + FSTATUS status; + + status = PointFabricCopy(dest, src); + if (FSUCCESS != status) + return status; + status = PointEnodeCopy(dest, src); + if (FSUCCESS != status) + return status; + status = PointEsmCopy(dest, src); + if (FSUCCESS != status) + return status; + return PointElinkCopy(dest, src); +} + +/* populate rest of node pairs from the list of nodes provided */ +/* nodePairList1 of NodePairList_t contains N entries and nodePairList2 of NodePairList_t contains M entries*/ +/* N x M nodes are populated in the point */ +FSTATUS PointPopulateNodePairList(Point *pPoint, NodePairList_t *nodePatPairs) +{ + FSTATUS status; + int leftSideCount, rightSideCount; + int n, m; + LIST_ITERATOR i; + + leftSideCount = ListCount(&nodePatPairs->nodePairList1); + rightSideCount = ListCount(&nodePatPairs->nodePairList2); + + //Populate N * M entries + DLIST *pList1 = &nodePatPairs->nodePairList1; + for(n = 0, i = ListHead(pList1); n < leftSideCount && i != NULL; n++, i = ListNext(pList1, i)) { + NodeData *nodep1 = (NodeData*)ListObj(i); + LIST_ITERATOR j; + DLIST *pList2 = &nodePatPairs->nodePairList2; + for (m = 0, j = ListHead(pList2); m < rightSideCount && j != NULL; m++, j = ListNext(pList2, j)) { + NodeData *nodep2 = (NodeData*)ListObj(j); + status = PointNodePairListAppend(pPoint, LSIDE_PAIR, nodep1); + if (FSUCCESS != status) + return status; + if (!pPoint->haveSW && (nodep1->NodeInfo.NodeType == STL_NODE_SW)) + pPoint->haveSW = TRUE; + if (!pPoint->haveFI && (nodep1->NodeInfo.NodeType == STL_NODE_FI)) + pPoint->haveFI = TRUE; + + status = PointNodePairListAppend(pPoint, RSIDE_PAIR, nodep2); + if (FSUCCESS != status) + return status; + if (!pPoint->haveSW && (nodep2->NodeInfo.NodeType == STL_NODE_SW)) + pPoint->haveSW = TRUE; + if (!pPoint->haveFI && (nodep1->NodeInfo.NodeType == STL_NODE_FI)) + pPoint->haveFI = TRUE; + + } + } + return FSUCCESS; +} + +/* check if point is of Type NodePairList */ +boolean PointTypeIsNodePairList(Point *pPoint) +{ + if (pPoint){ + if (POINT_TYPE_NODE_PAIR_LIST == pPoint->Type) + return TRUE; + } + return FALSE; +} + +/* check if point is of Type NodeList */ +boolean PointIsTypeNodeList(Point *pPoint) +{ + if (pPoint){ + if (POINT_TYPE_NODE_LIST == pPoint->Type) + return TRUE; + } + return FALSE; +} + +/* check if haveSW flag is set */ +boolean PointHaveSw(Point *pPoint) +{ + if (pPoint){ + if (pPoint->haveSW) + return TRUE; + } + return FALSE; +} + +/* check if haveFI flag is set */ +boolean PointHaveFI(Point *pPoint) +{ + if (pPoint){ + if (pPoint->haveFI) + return TRUE; + } + return FALSE; +} + +/* These compare functions will compare the supplied object to the + * specific relevant portion of the point. Callers who wish to consider + * both expected and fabric objects should call all the relevant routines + * for the fabric and linked expected objects + * This approach provides greater flexibility for callers, and removes the need + * for the Point construction and parsing routines to check all the linked + * fabric and expected objects. + */ + +/* compare the supplied port to the given point + * this is used to identify focus for reports + * if !PointValid will report TRUE for all ports + */ +boolean ComparePortPoint(PortData *portp, Point *point) +{ + if (!PointValid(point)) + return TRUE; + switch (point->Type) { + case POINT_TYPE_NONE: + return FALSE; + case POINT_TYPE_PORT: + return (portp == point->u.portp); + case POINT_TYPE_PORT_LIST: + { + LIST_ITERATOR i; + DLIST *pList = &point->u.portList; + + for (i=ListHead(pList); i != NULL; i = ListNext(pList, i)) { + PortData *portp2 = (PortData*)ListObj(i); + if (portp == portp2) + return TRUE; + } + } + return FALSE; + case POINT_TYPE_NODE: + return (portp->nodep == point->u.nodep); + case POINT_TYPE_NODE_LIST: + { + LIST_ITERATOR i; + DLIST *pList = &point->u.nodeList; + + for (i=ListHead(pList); i != NULL; i = ListNext(pList, i)) { + NodeData *nodep = (NodeData*)ListObj(i); + if (portp->nodep == nodep) + return TRUE; + } + } + return FALSE; +#if !defined(VXWORKS) || defined(BUILD_DMC) + case POINT_TYPE_IOC: + return (portp->nodep == point->u.iocp->ioup->nodep); + case POINT_TYPE_IOC_LIST: + { + LIST_ITERATOR i; + DLIST *pList = &point->u.nodeList; + + for (i=ListHead(pList); i != NULL; i = ListNext(pList, i)) { + IocData *iocp = (IocData*)ListObj(i); + if (portp->nodep == iocp->ioup->nodep) + return TRUE; + } + } + return FALSE; +#endif + case POINT_TYPE_SYSTEM: + return (portp->nodep->systemp == point->u.systemp); + case POINT_TYPE_NODE_PAIR_LIST: + { + LIST_ITERATOR i; + DLIST *pList1 = &point->u.nodePairList.nodePairList1; + DLIST *pList2 = &point->u.nodePairList.nodePairList2; + + for (i=ListHead(pList1); i != NULL; i = ListNext(pList1, i)) { + NodeData *nodep1 = (NodeData*)ListObj(i); + if (portp->nodep == nodep1) + return TRUE; + } + for (i=ListHead(pList2); i != NULL; i = ListNext(pList2, i)) { + NodeData *nodep2 = (NodeData*)ListObj(i); + if (portp->nodep== nodep2) + return TRUE; + } + return FALSE; + } + } + return TRUE; // should not get here +} + +/* compare the supplied node to the given point + * this is used to identify focus for reports + * if !PointValid will report TRUE for all nodes + */ +boolean CompareNodePoint(NodeData *nodep, Point *point) +{ + if (!PointValid(point)) + return TRUE; + switch (point->Type) { + case POINT_TYPE_NONE: + return FALSE; + case POINT_TYPE_PORT: + return (nodep == point->u.portp->nodep); + case POINT_TYPE_PORT_LIST: + { + LIST_ITERATOR i; + DLIST *pList = &point->u.portList; + + for (i=ListHead(pList); i != NULL; i = ListNext(pList, i)) { + PortData *portp = (PortData*)ListObj(i); + if (nodep == portp->nodep) + return TRUE; + } + } + return FALSE; + case POINT_TYPE_NODE: + return (nodep == point->u.nodep); + case POINT_TYPE_NODE_LIST: + { + LIST_ITERATOR i; + DLIST *pList = &point->u.nodeList; + + for (i=ListHead(pList); i != NULL; i = ListNext(pList, i)) { + NodeData *nodep2 = (NodeData*)ListObj(i); + if (nodep == nodep2) + return TRUE; + } + } + return FALSE; +#if !defined(VXWORKS) || defined(BUILD_DMC) + case POINT_TYPE_IOC: + return (nodep == point->u.iocp->ioup->nodep); + case POINT_TYPE_IOC_LIST: + { + LIST_ITERATOR i; + DLIST *pList = &point->u.nodeList; + + for (i=ListHead(pList); i != NULL; i = ListNext(pList, i)) { + IocData *iocp = (IocData*)ListObj(i); + if (nodep == iocp->ioup->nodep) + return TRUE; + } + } + return FALSE; +#endif + case POINT_TYPE_SYSTEM: + return (nodep->systemp == point->u.systemp); + case POINT_TYPE_NODE_PAIR_LIST: + { + LIST_ITERATOR i; + DLIST *pList1 = &point->u.nodePairList.nodePairList1; + DLIST *pList2 = &point->u.nodePairList.nodePairList2; + + for (i=ListHead(pList1); i != NULL; i = ListNext(pList1, i)) { + NodeData *nodep1 = (NodeData*)ListObj(i); + if (nodep == nodep1) + return TRUE; + } + for (i=ListHead(pList2); i != NULL; i = ListNext(pList2, i)) { + NodeData *nodep2 = (NodeData*)ListObj(i); + if (nodep== nodep2) + return TRUE; + } + return FALSE; + } + + } + return TRUE; // should not get here +} + +#if !defined(VXWORKS) || defined(BUILD_DMC) +/* compare the supplied iou to the given point + * this is used to identify focus for reports + * if !PointValid will report TRUE for all ious + */ +boolean CompareIouPoint(IouData *ioup, Point *point) +{ + /* each IOU is associated with a single node, and a given node is + * associated with 0 or 1 IOUs. So we can simply use a Node compare + * for all point->Type values, even if the point is an IOC or IOC_LIST + */ + return CompareNodePoint(ioup->nodep, point); +} + +/* compare the supplied ioc to the given point + * this is used to identify focus for reports + * if !PointValid will report TRUE for all iocs + */ +boolean CompareIocPoint(IocData *iocp, Point *point) +{ + if (!PointValid(point)) + return TRUE; + switch (point->Type) { + case POINT_TYPE_IOC: + return (iocp == point->u.iocp); + case POINT_TYPE_IOC_LIST: + { + LIST_ITERATOR i; + DLIST *pList = &point->u.nodeList; + + for (i=ListHead(pList); i != NULL; i = ListNext(pList, i)) { + IocData *iocp2 = (IocData*)ListObj(i); + if (iocp == iocp2) + return TRUE; + } + } + return FALSE; + default: + return CompareNodePoint(iocp->ioup->nodep, point); + } +} +#endif + +/* compare the supplied SM to the given point + * this is used to identify focus for reports + * if !PointValid will report TRUE for all SMs + */ +boolean CompareSmPoint(SMData *smp, Point *point) +{ + return ComparePortPoint(smp->portp, point); +} + +/* compare the supplied system to the given point + * this is used to identify focus for reports + * if !PointValid will report TRUE for all systems + */ +boolean CompareSystemPoint(SystemData *systemp, Point *point) +{ + if (!PointValid(point)) + return TRUE; + switch (point->Type) { + case POINT_TYPE_NONE: + return FALSE; + case POINT_TYPE_PORT: + return (systemp == point->u.portp->nodep->systemp); + case POINT_TYPE_PORT_LIST: + { + LIST_ITERATOR i; + DLIST *pList = &point->u.portList; + + for (i=ListHead(pList); i != NULL; i = ListNext(pList, i)) { + PortData *portp = (PortData*)ListObj(i); + if (systemp == portp->nodep->systemp) + return TRUE; + } + } + return FALSE; + case POINT_TYPE_NODE: + return (systemp == point->u.nodep->systemp); + case POINT_TYPE_NODE_LIST: + { + LIST_ITERATOR i; + DLIST *pList = &point->u.nodeList; + + for (i=ListHead(pList); i != NULL; i = ListNext(pList, i)) { + NodeData *nodep = (NodeData*)ListObj(i); + if (systemp == nodep->systemp) + return TRUE; + } + } + return FALSE; +#if !defined(VXWORKS) || defined(BUILD_DMC) + case POINT_TYPE_IOC: + return (systemp == point->u.iocp->ioup->nodep->systemp); + case POINT_TYPE_IOC_LIST: + { + LIST_ITERATOR i; + DLIST *pList = &point->u.nodeList; + + for (i=ListHead(pList); i != NULL; i = ListNext(pList, i)) { + IocData *iocp = (IocData*)ListObj(i); + if (systemp == iocp->ioup->nodep->systemp) + return TRUE; + } + } + return FALSE; +#endif + case POINT_TYPE_SYSTEM: + return (systemp == point->u.systemp); + case POINT_TYPE_NODE_PAIR_LIST: + { + LIST_ITERATOR i; + DLIST *pList1 = &point->u.nodePairList.nodePairList1; + DLIST *pList2 = &point->u.nodePairList.nodePairList2; + + for (i=ListHead(pList1); i != NULL; i = ListNext(pList1, i)) { + NodeData *nodep1 = (NodeData*)ListObj(i); + if (systemp == nodep1->systemp) + return TRUE; + } + for (i=ListHead(pList2); i != NULL; i = ListNext(pList2, i)) { + NodeData *nodep2 = (NodeData*)ListObj(i); + if (systemp == nodep2->systemp) + return TRUE; + } + return FALSE; + } + + } + return TRUE; // should not get here +} + +/* compare the supplied ExpectedNode to the given point + * this is used to identify focus for reports + * if !PointValid will report TRUE for all ExpectedNodes + */ +boolean CompareExpectedNodePoint(ExpectedNode *enodep, Point *point) +{ + if (!PointValid(point)) + return TRUE; + switch (point->EnodeType) { + case POINT_ENODE_TYPE_NONE: + return FALSE; + case POINT_ENODE_TYPE_NODE: + return (enodep == point->u2.enodep); + case POINT_ENODE_TYPE_NODE_LIST: + { + LIST_ITERATOR i; + DLIST *pList = &point->u2.enodeList; + + for (i=ListHead(pList); i != NULL; i = ListNext(pList, i)) { + ExpectedNode *enodep2 = (ExpectedNode*)ListObj(i); + if (enodep == enodep2) + return TRUE; + } + } + return FALSE; + } + return TRUE; // should not get here +} + +/* compare the supplied ExpectedSM to the given point + * this is used to identify focus for reports + * if !PointValid will report TRUE for all ExpectedSM + */ +boolean CompareExpectedSMPoint(ExpectedSM *esmp, Point *point) +{ + if (!PointValid(point)) + return TRUE; + switch (point->EsmType) { + case POINT_ESM_TYPE_NONE: + return FALSE; + case POINT_ESM_TYPE_SM: + return (esmp == point->u3.esmp); + case POINT_ESM_TYPE_SM_LIST: + { + LIST_ITERATOR i; + DLIST *pList = &point->u3.esmList; + + for (i=ListHead(pList); i != NULL; i = ListNext(pList, i)) { + ExpectedSM *esmp2 = (ExpectedSM*)ListObj(i); + if (esmp == esmp2) + return TRUE; + } + } + return FALSE; + } + return TRUE; // should not get here +} + +/* compare the supplied ExpectedLink to the given point + * this is used to identify focus for reports + * if !PointValid will report TRUE for all ExpectedLink + */ +boolean CompareExpectedLinkPoint(ExpectedLink *elinkp, Point *point) +{ + if (!PointValid(point)) + return TRUE; + switch (point->ElinkType) { + case POINT_ELINK_TYPE_NONE: + return FALSE; + case POINT_ELINK_TYPE_LINK: + return (elinkp == point->u4.elinkp); + case POINT_ELINK_TYPE_LINK_LIST: + { + LIST_ITERATOR i; + DLIST *pList = &point->u4.elinkList; + + for (i=ListHead(pList); i != NULL; i = ListNext(pList, i)) { + ExpectedLink *elinkp2 = (ExpectedLink*)ListObj(i); + if (elinkp == elinkp2) + return TRUE; + } + } + return FALSE; + } + return TRUE; // should not get here +} + +/* append the given port to the PORT_LIST point, if its already + * in the list, do nothing + */ +FSTATUS PointListAppendUniquePort(Point *point, PortData *portp) +{ + if (point->Type == POINT_TYPE_PORT_LIST && ComparePortPoint(portp, point)) + return FSUCCESS; + return PointListAppend(point, POINT_TYPE_PORT_LIST, portp); +} + +/* If possible compress a point into a simpler format + * This looks for lists which consist of a single entry or + * lists which include all the components of a higher level type + */ +void PointFabricCompress(Point *point) +{ + switch (point->Type) { + case POINT_TYPE_NONE: + break; + case POINT_TYPE_PORT: + break; + case POINT_TYPE_PORT_LIST: + { + PortData *portp; + LIST_ITERATOR head = ListHead(&point->u.portList); + ASSERT(head); + + ASSERT(ListCount(&point->u.portList) >= 1); + + portp = (PortData*)ListObj(head); + if (ListCount(&point->u.portList) == 1) { + /* degenerate case, simplify as a single port */ + PointFabricDestroy(point); + PointInitSimple(point, POINT_TYPE_PORT, portp); + } else if (ListCount(&point->u.portList) == cl_qmap_count(&portp->nodep->Ports)) { + /* maybe we can consolidate to a single node */ + LIST_ITERATOR i; + DLIST *pList = &point->u.portList; + + for (i=ListHead(pList); portp && i != NULL; i = ListNext(pList, i)) { + if (portp->nodep != ((PortData*)ListObj(i))->nodep) + portp = NULL; /* not in same node, flag for below */ + } + if (portp) { + /* degenerate case, simplify as a single node */ + PointFabricDestroy(point); + PointInitSimple(point, POINT_TYPE_NODE, portp->nodep); + } +#if 0 + } else { + // the likelihood of this is low for port oriented searches + // and it would present just the system image guide in the summary + // and may be less obvious to the user than a list of ports + /* maybe we can consolidate to a single system */ + LIST_ITERATOR i; + DLIST *pList = &point->u.portList; + + for (i=ListHead(pList); portp && i != NULL; i = ListNext(pList, i)) { + if (portp->nodep->systemp != ((PortData*)ListObj(i))->nodep->systemp) + portp = NULL; /* not in same system, flag for below */ + } + if (portp) { + /* all ports are in same system. is it a complete list? */ + /* count ports in the system */ + uint32 count = 0; + cl_map_item_t *p; + + for (p=cl_qmap_head(&portp->nodep->systemp->Nodes); p != cl_qmap_end(&portp->nodep->systemp->Nodes); p = cl_qmap_next(p)) { + NodeData *nodep = PARENT_STRUCT(p, NodeData, SystemNodesEntry); + count += cl_qmap_count(&nodep->Ports); + } + if (ListCount(&point->u.portList) != count) + portp = NULL; /* incomplete list, flag for below */ + } + if (portp) { + /* degenerate case, simplify as a single system */ + PointFabricDestroy(point); + PointInitSimple(point, POINT_TYPE_SYSTEM, portp->nodep->systemp); + } +#endif + } + break; + } + case POINT_TYPE_NODE: + break; + case POINT_TYPE_NODE_LIST: + { + NodeData *nodep; + LIST_ITERATOR head = ListHead(&point->u.nodeList); + ASSERT(head); + + ASSERT(ListCount(&point->u.nodeList) >= 1); + nodep = (NodeData*)ListObj(head); + if (ListCount(&point->u.nodeList) == 1) { + /* degenerate case, simplify as a single node */ + PointFabricDestroy(point); + PointInitSimple(point, POINT_TYPE_NODE, nodep); + } else if (ListCount(&point->u.nodeList) == cl_qmap_count(&nodep->systemp->Nodes)) { + /* maybe we can consolidate to a single system */ + LIST_ITERATOR i; + DLIST *pList = &point->u.nodeList; + + for (i=ListHead(pList); nodep && i != NULL; i = ListNext(pList, i)) { + if (nodep->systemp != ((NodeData*)ListObj(i))->systemp) + nodep = NULL; /* not in same system, flag for below */ + } + if (nodep) { + /* degenerate case, simplify as a single system */ + PointFabricDestroy(point); + PointInitSimple(point, POINT_TYPE_SYSTEM, nodep->systemp); + } + } + break; + } +#if !defined(VXWORKS) || defined(BUILD_DMC) + case POINT_TYPE_IOC: + break; + case POINT_TYPE_IOC_LIST: + { + IocData *iocp; + LIST_ITERATOR head = ListHead(&point->u.iocList); + ASSERT(head); + + ASSERT(ListCount(&point->u.iocList) >= 1); + iocp = (IocData*)ListObj(head); + if (ListCount(&point->u.iocList) == 1) { + /* degenerate case, simplify as a single IOC */ + PointFabricDestroy(point); + PointInitSimple(point, POINT_TYPE_IOC, iocp); + } else if (ListCount(&point->u.iocList) == QListCount(&iocp->ioup->Iocs)) { + /* maybe we can consolidate to a single node */ + LIST_ITERATOR i; + DLIST *pList = &point->u.iocList; + + for (i=ListHead(pList); iocp && i != NULL; i = ListNext(pList, i)) { + if (iocp->ioup != ((IocData*)ListObj(i))->ioup) + iocp = NULL; /* not in same iou, flag for below */ + } + if (iocp) { + /* degenerate case, simplify as a single node */ + PointFabricDestroy(point); + PointInitSimple(point, POINT_TYPE_NODE, iocp->ioup->nodep); + } +#if 0 + } else { + // the likelihood of this is low for ioc oriented searches + // and it would present just the system image guide in the summary + // and may be less obvious to the user than a list of iocs + /* maybe we can consolidate to a single system */ + LIST_ITERATOR i; + DLIST *pList = &point->u.iocList; + + for (i=ListHead(pList); iocp && i != NULL; i = ListNext(pList, i)) { + if (iocp->ioup->nodep->systemp != ((IocData*)ListObj(i))->ioup->nodep->systemp) + iocp = NULL; /* not in same system, flag for below */ + } + if (iocp) { + /* all IOCs are in same system. is it a complete list? */ + /* count IOCs in the system */ + uint32 count = 0; + cl_map_item_t *p; + + for (p=cl_qmap_head(&iocp->ioup->nodep->systemp->Nodes); p != cl_qmap_end(&iocp->ioup->nodep->systemp->Nodes); p = cl_qmap_next(p)) { + NodeData *nodep = PARENT_STRUCT(p, NodeData, SystemNodesEntry); + if (nodep->ioup) + count += QListCount(&nodep->ioup->Iocs); + } + if (ListCount(&point->u.iocList) != count) + iocp = NULL; /* incomplete list, flag for below */ + } + if (iocp) { + /* degenerate case, simplify as a single system */ + PointFabricDestroy(point); + PointInitSimple(point, POINT_TYPE_SYSTEM, iocp->ioup->nodep->systemp); + } +#endif + } + break; + } +#endif + case POINT_TYPE_SYSTEM: + break; + case POINT_TYPE_NODE_PAIR_LIST: + break; + } +} + +/* If possible compress a point into a simpler format + * This looks for lists which consist of a single entry + */ +void PointEnodeCompress(Point *point) +{ + switch (point->EnodeType) { + case POINT_ENODE_TYPE_NONE: + break; + case POINT_ENODE_TYPE_NODE: + break; + case POINT_ENODE_TYPE_NODE_LIST: + { + ASSERT(ListCount(&point->u2.enodeList) >= 1); + if (ListCount(&point->u2.enodeList) == 1) { + /* degenerate case, simplify as a single ExpectedNode */ + LIST_ITERATOR head = ListHead(&point->u2.enodeList); + ExpectedNode *enodep; + ASSERT(head); + enodep = (ExpectedNode*)ListObj(head); + PointEnodeDestroy(point); + PointInitEnodeSimple(point, POINT_ENODE_TYPE_NODE, enodep); + } + break; + } + } +} + +/* If possible compress a point into a simpler format + * This looks for lists which consist of a single entry + */ +void PointEsmCompress(Point *point) +{ + switch (point->EsmType) { + case POINT_ESM_TYPE_NONE: + break; + case POINT_ESM_TYPE_SM: + break; + case POINT_ESM_TYPE_SM_LIST: + { + ASSERT(ListCount(&point->u3.esmList) >= 1); + if (ListCount(&point->u3.esmList) == 1) { + /* degenerate case, simplify as a single ExpectedSM */ + LIST_ITERATOR head = ListHead(&point->u3.esmList); + ExpectedSM *esmp; + ASSERT(head); + esmp = (ExpectedSM*)ListObj(head); + PointEsmDestroy(point); + PointInitEsmSimple(point, POINT_ESM_TYPE_SM, esmp); + } + break; + } + } +} + +/* If possible compress a point into a simpler format + * This looks for lists which consist of a single entry + */ +void PointElinkCompress(Point *point) +{ + switch (point->ElinkType) { + case POINT_ELINK_TYPE_NONE: + break; + case POINT_ELINK_TYPE_LINK: + break; + case POINT_ELINK_TYPE_LINK_LIST: + { + ASSERT(ListCount(&point->u4.elinkList) >= 1); + if (ListCount(&point->u4.elinkList) == 1) { + /* degenerate case, simplify as a single ExpectedLink */ + LIST_ITERATOR head = ListHead(&point->u4.elinkList); + ExpectedLink *elinkp; + ASSERT(head); + elinkp = (ExpectedLink*)ListObj(head); + PointElinkDestroy(point); + PointInitElinkSimple(point, POINT_ELINK_TYPE_LINK, elinkp); + } + break; + } + } +} + +/* If possible compress a point into a simpler format + * This looks for lists which consist of a single entry or + * lists which include all the components of a higher level type + */ +void PointCompress(Point *point) +{ + PointFabricCompress(point); + PointEnodeCompress(point); + PointEsmCompress(point); + PointElinkCompress(point); +} diff --git a/Topology/route.c b/Topology/route.c new file mode 100644 index 0000000..e2d9f57 --- /dev/null +++ b/Topology/route.c @@ -0,0 +1,1867 @@ +/* BEGIN_ICS_COPYRIGHT7 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT7 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +// functions to perform routing analysis using LFT tables in FabricData + +#include + +#include "topology.h" +#include "topology_internal.h" + +// For each device along the path, entry and exit port of device is provided +// For the FI at the start of the route, only an exit port is provided +// For the FI at the end of the route, only a entry port is provided +// For switches along the route, both entry and exit ports are provided +// When a switch Port 0 is the start of the route, it will be the entry port +// along with the physical exit port +// When a switch Port 0 is the end of the route, it will be the exit port +// along with the physical entry port +// The above approach parallels how TraceRoute records are reported by the +// SM, so if desired a callback could build a SM TraceRoute style response +// for use in other routines. +//typedef FSTATUS (RouteCallback_t)(PortData *entryPortp, PortData *exitPortp, void *context); + + +// lookup dlid in routing table of switch and return portp to exit switch +static PortData *LookupRoute(NodeData *nodep, STL_LID dlid, PortData* inportp, int vl, int sc, int rc) +{ + uint8 portNum = 0xff; + PortData *portp; + + DEBUG_ASSERT(nodep->switchp); //caller checks + if (!dlid) + return NULL; + + if (nodep->pSwitchInfo->SwitchInfoData.RoutingMode.Enabled == STL_ROUTE_LINEAR) { + DEBUG_ASSERT(nodep->switchp->LinearFDB); + + if (dlid >= nodep->switchp->LinearFDBSize) + return NULL; + + portNum = STL_LFT_PORT_BLOCK(nodep->switchp->LinearFDB, dlid); + } + + if (portNum == 0xff) + return NULL; // invalid table entry, no route + + portp = FindNodePort(nodep, portNum); + // Analysis is focused on datapath routes. While VL15 can route through an + // Init port, that analysis is atypical. Prior to FF_DOWNPORTINFO + // we would tend not to have ports Down or Init in our DB so + // search above would fail. + if (! portp || ! IsPortInitialized(portp->PortInfo.PortStates) + || (portNum != 0 && ! portp->neighbor)) + return NULL; // Non viable route + return portp; +} + +// Walk route from portp to dlid. +// returns status of callback (if not FSUCCESS) +// FUNAVAILABLE - no routing tables in FabricData given +// FNOT_FOUND - unable to find starting port +// FNOT_DONE - unable to trace route, dlid is a dead end +FSTATUS WalkRoutePort(FabricData_t *fabricp, PortData *portp, STL_LID dlid, uint8 SL, uint8 rc, + RouteCallback_t *callback, void *context) +{ + PortData *portp2; // next port in route + FSTATUS status; + PortData *hops[64]; + uint8 numhops = 0; + uint8 sc = 0, vl = 0; + if (portp->pQOS) { + sc = portp->pQOS->SL2SCMap->SLSCMap[SL].SC; + if (sc == 15) { + return FNOT_DONE; // invalid SC + } + vl = portp->pQOS->SC2VLMaps[Enum_SCVLt].SCVLMap[sc].VL; + if (vl == 15) { + return FNOT_DONE; + } + } + + if (portp->nodep->NodeInfo.NodeType != STL_NODE_SW) { + // first device in route + status = (*callback)(NULL, portp, vl, context); + if (status != FSUCCESS) + return status; + portp = portp->neighbor; // entry port to next device + } + + // 1st loop we can start at port 0 of a switch. If we arrive at port 0 + // of a switch any other loop, it must be our destination. + while (portp->nodep->NodeInfo.NodeType == STL_NODE_SW + && (numhops == 0 || portp->PortNum != 0)) { + SwitchData *switchp; + uint8 i; + + if (numhops >= 64) + return FNOT_DONE; // too long a path + for (i=0; i< numhops; i++) { + if (hops[i] == portp) + return FNOT_DONE; // looping path + } + hops[numhops++] = portp; + + // portp is entry port to a switch + switchp = portp->nodep->switchp; + if (!switchp || (!switchp->LinearFDB && + (portp->nodep->pSwitchInfo->SwitchInfoData.RoutingMode.Enabled == STL_ROUTE_NOP || + portp->nodep->pSwitchInfo->SwitchInfoData.RoutingMode.Enabled == STL_ROUTE_LINEAR))) + // TBD - way to check this before start + return FUNAVAILABLE; // no routing tables in snapshot + + portp2 = LookupRoute(portp->nodep, dlid, portp, vl, sc, rc); + if (! portp2) + return FNOT_DONE; // no route from slid to dlid + + if (portp->pQOS && portp->PortNum != 0 && portp2->PortNum != 0) { + STL_SCSCMAP *pSCSC = QOSDataLookupSCSCMap(portp, portp2->PortNum, 0); + if (pSCSC) { + uint8 newsc = pSCSC->SCSCMap[sc].SC; + if (newsc == 15) { + return FNOT_DONE; // invalid SC + } + vl = portp->pQOS->SC2VLMaps[Enum_SCVLt].SCVLMap[newsc].VL; + if (vl == 15) { + return FNOT_DONE; // invalid VL + } + sc = newsc; + } + } + + // hop through a switch + status = (*callback)(portp, portp2, vl, context); + if (status != FSUCCESS) + return status; + + // find next device + if (portp2->nodep->NodeInfo.NodeType == STL_NODE_SW + && portp2->PortNum == 0) + portp = portp2; + else + portp = portp2->neighbor; // entry port to next device + } + + // at destination of dlid: FI or Port 0 of SW + if (dlid < portp->PortInfo.LID + || dlid > (portp->PortInfo.LID + | ((1<PortInfo.s1.LMC)-1)) ) + return FNOT_DONE; // arrived at wrong destination + + if (portp->nodep->NodeInfo.NodeType != STL_NODE_SW) { + // last device in route + status = (*callback)(portp, NULL, vl, context); + if (status != FSUCCESS) + return status; + } + return FSUCCESS; +} + +// walk route from slid to dlid +FSTATUS WalkRoute(FabricData_t *fabricp, STL_LID slid, STL_LID dlid, + RouteCallback_t *callback, void *context) +{ + PortData *portp; + + portp = FindLid(fabricp, slid); + if (! portp) + return FNOT_FOUND; + + return WalkRoutePort(fabricp, portp, dlid, 0, 0, callback, context); +} + +struct GenTraceRouteContext_s { + uint32 NumTraceRecords; + STL_TRACE_RECORD *pTraceRecords; +}; + +static FSTATUS GenTraceRouteCallback(PortData *entryPortp, PortData *exitPortp, uint8 vl, void *context) +{ + struct GenTraceRouteContext_s *TraceContext = (struct GenTraceRouteContext_s *)context; + STL_TRACE_RECORD *p; + NodeData *nodep; + + ASSERT(entryPortp || exitPortp); + ASSERT(! (entryPortp && exitPortp) ||entryPortp->nodep == exitPortp->nodep); + + // add 1 more trace record + TraceContext->NumTraceRecords++; + p = TraceContext->pTraceRecords; + TraceContext->pTraceRecords = (STL_TRACE_RECORD*)MemoryAllocate2AndClear(sizeof(STL_TRACE_RECORD)*TraceContext->NumTraceRecords, IBA_MEM_FLAG_PREMPTABLE, MYTAG); + if (! TraceContext->pTraceRecords) { + if (p) + MemoryDeallocate(p); + return FINSUFFICIENT_MEMORY; + } + + if (p) { + MemoryCopy(TraceContext->pTraceRecords, p, sizeof(STL_TRACE_RECORD)*(TraceContext->NumTraceRecords-1)); + MemoryDeallocate(p); + } + p = &TraceContext->pTraceRecords[TraceContext->NumTraceRecords-1]; + + nodep = (entryPortp?entryPortp->nodep:exitPortp->nodep); + + p->IDGeneration = 0xff; // should be same for all records in a route + p->NodeType = nodep->NodeInfo.NodeType; + p->NodeID = nodep->NodeInfo.NodeGUID; + p->ChassisID = nodep->NodeInfo.SystemImageGUID; + + if(p->NodeType == STL_NODE_SW) { + p->EntryPort = entryPortp?entryPortp->PortNum : 0; + p->ExitPort = exitPortp?exitPortp->PortNum : 0; + p->EntryPortID = 0; + + } else { + + //entry and exit port should be 0 if not a switch + p->EntryPort = 0; + p->ExitPort = 0; + p->EntryPortID = entryPortp? entryPortp->PortGUID : 0; + if(p->EntryPortID == 0) p->EntryPortID = exitPortp? exitPortp->PortGUID : 0; + } + + //Exit port ID should be 0 if not a router + p->ExitPortID = 0; + + + return FSUCCESS; +} + + +// caller must free *ppTraceRecords +FSTATUS GenTraceRoutePort(FabricData_t *fabricp, PortData *portp, STL_LID dlid, uint8 rc, + STL_TRACE_RECORD **ppTraceRecords, uint32 *pNumTraceRecords) +{ + struct GenTraceRouteContext_s context = { 0, NULL}; + FSTATUS status; + + status = WalkRoutePort(fabricp, portp, dlid, 0, rc, GenTraceRouteCallback, &context); + + if (status != FSUCCESS) { + if (context.pTraceRecords) + MemoryDeallocate(context.pTraceRecords); + *ppTraceRecords = NULL; + *pNumTraceRecords = 0; + return status; + } + + *ppTraceRecords = context.pTraceRecords; + *pNumTraceRecords = context.NumTraceRecords; + return FSUCCESS; +} + +// caller must free *ppTraceRecords +FSTATUS GenTraceRoute(FabricData_t *fabricp, STL_LID slid, STL_LID dlid, uint8 rc, + STL_TRACE_RECORD **ppTraceRecords, uint32 *pNumTraceRecords) +{ + PortData *portp; + + portp = FindLid(fabricp, slid); + if (! portp) { + *ppTraceRecords = NULL; + *pNumTraceRecords = 0; + return FNOT_FOUND; + } + + return GenTraceRoutePort(fabricp, portp, dlid, rc, ppTraceRecords, pNumTraceRecords); +} + +// caller must free *ppTraceRecords +FSTATUS GenTraceRoutePath(FabricData_t *fabricp, IB_PATH_RECORD *pathp, uint8 rc, + STL_TRACE_RECORD **ppTraceRecords, uint32 *pNumTraceRecords) +{ + return GenTraceRoute(fabricp, pathp->SLID, pathp->DLID, rc, + ppTraceRecords, pNumTraceRecords); +} + +static FSTATUS GenPath(PortData *portp1, PortData *portp2, + STL_LID slid, STL_LID dlid, + IB_PATH_RECORD **ppPathRecords, uint32 *pNumPathRecords) +{ + IB_PATH_RECORD *p; + + ASSERT(portp1 && portp2); + + // add 1 more path record + (*pNumPathRecords)++; + p = *ppPathRecords; + *ppPathRecords = (IB_PATH_RECORD*)MemoryAllocate2AndClear(sizeof(IB_PATH_RECORD)* *pNumPathRecords, IBA_MEM_FLAG_PREMPTABLE, MYTAG); + if (! *ppPathRecords) { + if (p) + MemoryDeallocate(p); + return FINSUFFICIENT_MEMORY; + } + + if (p) { + MemoryCopy(*ppPathRecords, p, sizeof(IB_PATH_RECORD)*(*pNumPathRecords-1)); + MemoryDeallocate(p); + } + p = &(*ppPathRecords)[*pNumPathRecords-1]; + + p->SGID.Type.Global.SubnetPrefix = portp1->PortInfo.SubnetPrefix; + p->SGID.Type.Global.InterfaceID = portp1->PortGUID; + p->DGID.Type.Global.SubnetPrefix = portp2->PortInfo.SubnetPrefix; + p->DGID.Type.Global.InterfaceID = portp2->PortGUID; + p->SLID = slid; + p->DLID = dlid; + p->Reversible = 1; + p->u1.s.RawTraffic = 0; + p->u1.s.FlowLabel = 0; + p->u1.s.HopLimit = 0; + p->TClass = 0; + p->P_Key = 0; // invalid value to show we don't know + p->PktLifeTime = 0; // invalid value to show we don't know + p->u2.s.SL = 0; // best guess, could be wrong for Torus + p->Mtu = 0; // invalid value to show we don't know + p->Rate = 0; // invalid value to show we don't know + p->Preference = 0; + // other fields zeroed above when allocate w/clear + + return FSUCCESS; +} + +// Generate possible Path records from portp1 to portp2 +// We don't know SM config, so we just guess and generate paths of the form +// 0-0, 1-1, .... +// This corresponds to the PathSelection=Minimal FM config option +// when LMC doesn't match we start back at base lid for other port +// These may not be accurate for Torus, however the dlid is all that really +// matters for route analysis, so this should be fine +FSTATUS GenPaths(FabricData_t *fabricp, PortData *portp1, PortData *portp2, + IB_PATH_RECORD **ppPathRecords, uint32 *pNumPathRecords) +{ + STL_LID slid_base, slid_mask, slid_offset, dlid_base, dlid_mask, dlid_offset; + FSTATUS status; + + *ppPathRecords = NULL; + *pNumPathRecords = 0; + + slid_base = portp1->PortInfo.LID; + slid_mask = (1<PortInfo.s1.LMC)-1; + + dlid_base = portp2->PortInfo.LID; + dlid_mask = (1<PortInfo.s1.LMC)-1; + + if (! slid_base || ! dlid_base) + return FSUCCESS; // no path, probably a non port 0 on a switch + + for (slid_offset=0, dlid_offset=0; + slid_offset <= slid_mask && dlid_offset <= dlid_mask; + slid_offset++, dlid_offset++) { + status = GenPath(portp1, portp2, + slid_base | (slid_offset & slid_mask), + dlid_base | (dlid_offset & dlid_mask), + ppPathRecords, pNumPathRecords); + if (status != FSUCCESS) { + if (*ppPathRecords) + MemoryDeallocate(*ppPathRecords); + *ppPathRecords = NULL; + *pNumPathRecords = 0; + return status; + } + } + return FSUCCESS; +} + + +// clear holding areas for analysis data +void ClearAnalysisData(FabricData_t *fabricp) +{ + cl_map_item_t *n; + cl_map_item_t *p; + + for (n=cl_qmap_head(&fabricp->AllNodes); n != cl_qmap_end(&fabricp->AllNodes); n = cl_qmap_next(n)) { + NodeData *nodep = PARENT_STRUCT(n, NodeData, AllNodesEntry); + nodep->analysis = 0; + for (p=cl_qmap_head(&nodep->Ports); p != cl_qmap_end(&nodep->Ports); p = cl_qmap_next(p)) { + PortData *portp = PARENT_STRUCT(p, PortData, NodePortsEntry); + MemoryClear(&portp->analysisData, sizeof(portp->analysisData)); + } + } +} + +// for Fat Tree analysis +void DetermineSwitchTiers(FabricData_t *fabricp) +{ + LIST_ITEM *n; + cl_map_item_t *p; + boolean found; + unsigned tier; + + // switches connected to FIs are tier 1 + for (n=QListHead(&fabricp->AllFIs); n != NULL; n = QListNext(&fabricp->AllFIs, n)) { + NodeData *nodep = (NodeData *)QListObj(n); + for (p=cl_qmap_head(&nodep->Ports); p != cl_qmap_end(&nodep->Ports); p = cl_qmap_next(p)) { + PortData *portp = PARENT_STRUCT(p, PortData, NodePortsEntry); + if (portp->neighbor && portp->neighbor->nodep->NodeInfo.NodeType == STL_NODE_SW) + portp->neighbor->nodep->analysis = 1; + } + } + + // switches connected to tier1 switches are tier 2, etc + tier=2; + do { + found = FALSE; + for (n=QListHead(&fabricp->AllSWs); n != NULL; n = QListNext(&fabricp->AllSWs, n)) { + NodeData *nodep = (NodeData *)QListObj(n); + if (nodep->analysis != tier-1) + continue; + for (p=cl_qmap_head(&nodep->Ports); p != cl_qmap_end(&nodep->Ports); p = cl_qmap_next(p)) { + PortData *portp = PARENT_STRUCT(p, PortData, NodePortsEntry); + if (portp->neighbor + && portp->nodep->NodeInfo.NodeType == STL_NODE_SW + && ! portp->neighbor->nodep->analysis) { + portp->neighbor->nodep->analysis = tier; + found = TRUE; + } + } + } + tier++; + } while (found); +} + +// tabulate a device along a route in a fat tree +// called for each device in each route +// context != NULL => non-base LID path +static FSTATUS TabulateRouteCallbackFatTree(PortData *entryPortp, PortData *exitPortp, uint8 vl, void *context) +{ + if (exitPortp) { + if (exitPortp->neighbor && exitPortp->nodep->analysis < exitPortp->neighbor->nodep->analysis) { + exitPortp->analysisData.fatTreeRoutes.uplinkAllPaths++; + if (! context) + exitPortp->analysisData.fatTreeRoutes.uplinkBasePaths++; + } else { + // for now == tier or no neighbor unexpected, but treat as downlink + exitPortp->analysisData.fatTreeRoutes.downlinkAllPaths++; + if (! context) + exitPortp->analysisData.fatTreeRoutes.downlinkBasePaths++; + } + } + return FSUCCESS; +} + +// tabulate a device along a route +// called for each device in each route +// context != NULL => non-base LID path +static FSTATUS TabulateRouteCallback(PortData *entryPortp, PortData *exitPortp, uint8 vl, void *context) +{ + if (entryPortp) { + // increment a counter in entryPortp, maybe context indicates which + entryPortp->analysisData.routes.recvAllPaths++; + if (! context) + entryPortp->analysisData.routes.recvBasePaths++; + } + + if (exitPortp) { + // increment a counter in exitPortp, maybe context indicates which + exitPortp->analysisData.routes.xmitAllPaths++; + if (! context) + exitPortp->analysisData.routes.xmitBasePaths++; + } + return FSUCCESS; +} + +// tabulate all the ports along the route from slid to dlid +FSTATUS TabulateRoute(FabricData_t *fabricp, STL_LID slid, STL_LID dlid, + boolean fatTree) +{ + return WalkRoute(fabricp, slid, dlid, + fatTree?TabulateRouteCallbackFatTree:TabulateRouteCallback, + NULL); +} + +// tabulate all routes from portp1 to portp2 +FSTATUS TabulateRoutes(FabricData_t *fabricp, PortData *portp1, + PortData *portp2, uint32 *totalPaths, + uint32 *badPaths, boolean fatTree) +{ + int offset; + int count = (1<PortInfo.s1.LMC); + FSTATUS status; + + *totalPaths = 0; + *badPaths = 0; + + // IB is destination routed, so just need starting port, no need to + // iterate on all SLIDs for that port + status = WalkRoutePort(fabricp, portp1, + portp2->PortInfo.LID, 0, 0, + fatTree?TabulateRouteCallbackFatTree:TabulateRouteCallback, + NULL); // Base LID + if (status == FUNAVAILABLE) + return status; + (*totalPaths)++; + if (status == FNOT_DONE) + (*badPaths)++; + + for (offset = 1; offset < count; offset++) { + status = WalkRoutePort(fabricp, portp1, + portp2->PortInfo.LID|offset, 0, 0, + fatTree?TabulateRouteCallbackFatTree:TabulateRouteCallback, + (void*)1); // LMC LID + if (status == FUNAVAILABLE) + return status; + (*totalPaths)++; + if (status == FNOT_DONE) + (*badPaths)++; + } + return FSUCCESS; +} + +// tabulate all the routes between FIs +FSTATUS TabulateCARoutes(FabricData_t *fabricp, Point *focus, uint32 *totalPaths, + uint32 *badPaths, boolean fatTree) +{ + LIST_ITERATOR i, j; + cl_map_item_t *p1, *p2; + LIST_ITEM *n1, *n2; + FSTATUS status; + uint32 pathCount, badPathCount; + int noOfLeftNodes, noOfRightNodes; + + *totalPaths = 0; + *badPaths = 0; + + ClearAnalysisData(fabricp); + + if (fatTree) + DetermineSwitchTiers(fabricp); + + /* If there is FI in the node pair list only tabulate routes for the specified pairs*/ + if(PointHaveFI(focus) && PointTypeIsNodePairList(focus)){ + + DLIST *pList1 = &focus->u.nodePairList.nodePairList1; + DLIST *pList2 = &focus->u.nodePairList.nodePairList2; + + noOfLeftNodes = ListCount(pList1); + noOfRightNodes = ListCount(pList2); + + if (noOfLeftNodes != noOfRightNodes) { + fprintf(stderr, "%s: Pairs are not complete \n", g_Top_cmdname); + return FINVALID_PARAMETER; + } + + for (i = ListHead(pList1), j = ListHead(pList2); (i != NULL && j != NULL); + i = ListNext(pList1, i), j = ListNext(pList2, j) ) { + NodeData *nodepFromList1 = (NodeData*)ListObj(i); + NodeData *nodepFromList2 = (NodeData*)ListObj(j); + + //skip switches + if ((nodepFromList1->NodeInfo.NodeType == STL_NODE_SW) || (nodepFromList2->NodeInfo.NodeType == STL_NODE_SW)) + continue; + + for (p1=cl_qmap_head(&nodepFromList1->Ports); p1 != cl_qmap_end(&nodepFromList1->Ports); p1 = cl_qmap_next(p1)) { + PortData *portp1 = PARENT_STRUCT(p1, PortData, NodePortsEntry); + + for (p2=cl_qmap_head(&nodepFromList2->Ports); p2 != cl_qmap_end(&nodepFromList2->Ports); p2 = cl_qmap_next(p2)) { + PortData *portp2 = PARENT_STRUCT(p2, PortData, NodePortsEntry); + + // skip loopback paths + if (portp1 == portp2) continue; + status = TabulateRoutes(fabricp, portp1, portp2, &pathCount, &badPathCount, fatTree); + if (status == FUNAVAILABLE) + return status; + *totalPaths += pathCount; + *badPaths += badPathCount; + } + } + } + /* If there is FI in the list, make N x N pairs and tabulate routes for the formed pairs*/ + }else if(PointHaveFI(focus)){ + FIPortIterator a, b; + PortData *portp1, *portp2; + //point type which haveFI and only matches 1 node is invalid and should return error + if((POINT_TYPE_PORT == focus->Type) || (POINT_TYPE_NODE == focus->Type) || +#if !defined(VXWORKS) || defined(BUILD_DMC) + (POINT_TYPE_IOC == focus->Type) || + ((POINT_TYPE_IOC_LIST == focus->Type) && (1 == ListCount(&focus->u.iocList)))|| +#endif + ((POINT_TYPE_PORT_LIST == focus->Type) && (1 == ListCount(&focus->u.portList)))|| + ((POINT_TYPE_NODE_LIST == focus->Type) && (1 == ListCount(&focus->u.nodeList)))|| + ((POINT_TYPE_SYSTEM == focus->Type) && (1 == cl_qmap_count(&focus->u.systemp->Nodes)))){ + status = FINVALID_PARAMETER; + return status; + } + for(portp1 = FIPortIteratorHead(&a, focus); portp1 != NULL; portp1 = FIPortIteratorNext(&a) ) { + for(portp2 = FIPortIteratorHead(&b, focus); portp2 != NULL; portp2 = FIPortIteratorNext(&b) ) { + // skip loopback paths + if (portp1 == portp2) + continue; + status = TabulateRoutes(fabricp, portp1, portp2, &pathCount, &badPathCount, fatTree); + if (status == FUNAVAILABLE) + return status; + *totalPaths += pathCount; + *badPaths += badPathCount; + } + } + } else { + // TBD - because IB is DLID routed, can save effort by getting routes from + // 1 FI per switch to all other FIs (or all FIs on other switches) and + // then multiply the result for that FI by the number of FIs on that switch + // In a pure fattree such an approach would reduce N*N to (N/18)*(N/18) + // so it would have a 18*18 reduction in effort, provided the cost of + // finding FIs is not to high, maybe we can loop here based on all switches? + for (n1=QListHead(&fabricp->AllFIs); n1 != NULL; n1 = QListNext(&fabricp->AllFIs, n1)) { + NodeData *nodep1 = (NodeData *)QListObj(n1); + for (p1=cl_qmap_head(&nodep1->Ports); p1 != cl_qmap_end(&nodep1->Ports); p1 = cl_qmap_next(p1)) { + PortData *portp1 = PARENT_STRUCT(p1, PortData, NodePortsEntry); + + for (n2=QListHead(&fabricp->AllFIs); n2 != NULL; n2 = QListNext(&fabricp->AllFIs, n2)) { + NodeData *nodep2 = (NodeData *)QListObj(n2); + + // enable this if we want to skip node to self paths + //if (nodep1 == nodep2) continue; + + for (p2=cl_qmap_head(&nodep2->Ports); p2 != cl_qmap_end(&nodep2->Ports); p2 = cl_qmap_next(p2)) { + PortData *portp2 = PARENT_STRUCT(p2, PortData, NodePortsEntry); + // skip loopback paths + if (portp1 == portp2) continue; + status = TabulateRoutes(fabricp, portp1, portp2, &pathCount, &badPathCount, fatTree); + if (status == FUNAVAILABLE) + return status; + *totalPaths += pathCount; + *badPaths += badPathCount; + } + } + } + } + } + return FSUCCESS; +} + +typedef struct ReportContext_s { + PortData *portp1; + PortData *portp2; + STL_LID dlid; + boolean isBaseLid; + PortData *reportPort; + ReportCallback_t callback; + void *context; +} ReportContext_t; + +// report a device along a route in a fat tree +// called for each device in each route +static FSTATUS ReportRouteCallbackFatTree(PortData *entryPortp, PortData *exitPortp, uint8 vl, void *context) +{ + ReportContext_t *ReportContext = (ReportContext_t*)context; + + if (exitPortp == ReportContext->reportPort) { + if (exitPortp->neighbor && exitPortp->nodep->analysis < exitPortp->neighbor->nodep->analysis) { + (*ReportContext->callback)(ReportContext->portp1, ReportContext->portp2, ReportContext->dlid, ReportContext->isBaseLid, TRUE, ReportContext->context); + } else { + // for now == tier or no neighbor unexpected, but treat as downlink + (*ReportContext->callback)(ReportContext->portp1, ReportContext->portp2, ReportContext->dlid, ReportContext->isBaseLid, FALSE, ReportContext->context); + } + } + return FSUCCESS; +} + +// report a device along a route +// called for each device in each route +static FSTATUS ReportRouteCallback(PortData *entryPortp, PortData *exitPortp, uint8 vl, void *context) +{ + ReportContext_t *ReportContext = (ReportContext_t*)context; + if (entryPortp == ReportContext->reportPort) { + (*ReportContext->callback)(ReportContext->portp1, ReportContext->portp2, ReportContext->dlid, ReportContext->isBaseLid, TRUE, ReportContext->context); + } + + if (exitPortp == ReportContext->reportPort) { + (*ReportContext->callback)(ReportContext->portp1, ReportContext->portp2, ReportContext->dlid, ReportContext->isBaseLid, FALSE, ReportContext->context); + } + return FSUCCESS; +} + +// report all routes from portp1 to portp2 that cross reportPort +FSTATUS ReportRoutes(FabricData_t *fabricp, + PortData *portp1, PortData *portp2, + PortData *reportPort, ReportCallback_t callback, + void *context, boolean fatTree) +{ + int offset; + int count = (1<PortInfo.s1.LMC); + FSTATUS status; + ReportContext_t ReportContext; + + ReportContext.portp1 = portp1; + ReportContext.portp2 = portp2; + ReportContext.reportPort = reportPort; + ReportContext.callback = callback; + ReportContext.context = context; + + // IB is destination routed, so just need starting port, no need to + // iterate on all SLIDs for that port + ReportContext.dlid = portp2->PortInfo.LID; + ReportContext.isBaseLid = TRUE; + status = WalkRoutePort(fabricp, portp1, + portp2->PortInfo.LID, 0, 0, + fatTree?ReportRouteCallbackFatTree:ReportRouteCallback, + &ReportContext); // Base LID + if (status == FUNAVAILABLE) + return status; + // TabulateRoutes reports bad paths and will have been used + // prior to this, so no need to report FNOT_DONE routes + + for (offset = 1; offset < count; offset++) { + ReportContext.dlid = portp2->PortInfo.LID|offset; + ReportContext.isBaseLid = FALSE; + status = WalkRoutePort(fabricp, portp1, + portp2->PortInfo.LID|offset, 0, 0, + fatTree?ReportRouteCallbackFatTree:ReportRouteCallback, + &ReportContext); // LMC LID + if (status == FUNAVAILABLE) + return status; + // TabulateRoutes reports bad paths and will have been used + // prior to this, so no need to report FNOT_DONE routes + } + return FSUCCESS; +} + + +// report all the routes between FIs that cross reportPort, +// exclude loopback routes +FSTATUS ReportCARoutes(FabricData_t *fabricp, + PortData *reportPort, ReportCallback_t callback, + void *context, boolean fatTree) +{ + LIST_ITEM *n1, *n2; + cl_map_item_t *p1, *p2; + FSTATUS status; + + // TBD - because IB is DLID routed, can save effort by getting routes from + // 1 FI per switch to all other FIs (or all FIs on other switches) and + // then multiply the result for that FI by the number of FIs on that switch + // In a pure fattree such an approach would reduce N*N to (N/18)*(N/18) + // so it would have a 18*18 reduction in effort, provided the cost of + // finding FIs is not to high, maybe we can loop here based on all switches? + for (n1=QListHead(&fabricp->AllFIs); n1 != NULL; n1 = QListNext(&fabricp->AllFIs, n1)) { + NodeData *nodep1 = (NodeData *)QListObj(n1); + for (p1=cl_qmap_head(&nodep1->Ports); p1 != cl_qmap_end(&nodep1->Ports); p1 = cl_qmap_next(p1)) { + PortData *portp1 = PARENT_STRUCT(p1, PortData, NodePortsEntry); + + for (n2=QListHead(&fabricp->AllFIs); n2 != NULL; n2 = QListNext(&fabricp->AllFIs, n2)) { + NodeData *nodep2 = (NodeData *)QListObj(n2); + + // enable this if we want to skip node to self paths + //if (nodep1 == nodep2) continue; + + for (p2=cl_qmap_head(&nodep2->Ports); p2 != cl_qmap_end(&nodep2->Ports); p2 = cl_qmap_next(p2)) { + PortData *portp2 = PARENT_STRUCT(p2, PortData, NodePortsEntry); + // skip loopback paths + if (portp1 == portp2) continue; + status = ReportRoutes(fabricp, portp1, portp2, reportPort, callback, context, fatTree); + if (status == FUNAVAILABLE) + return status; + // TabulateRoutes reports bad paths and will have been used + // prior to this, so no need to report FNOT_DONE routes + } + } + } + } + return FSUCCESS; +} + + + + +// callback for all the ports along a route +static FSTATUS ValidateRouteCallback(PortData *entryPortp, PortData *exitPortp, uint8 vl, void *context) +{ + // nothing special to be done while walking routes + return FSUCCESS; +} + +typedef struct ValidateContext2_s { + ValidateCallback2_t callback; + void *context; +} ValidateContext2_t; + + +// callback for all the ports along an incomplete route +static FSTATUS ValidateRouteCallback2(PortData *entryPortp, PortData *exitPortp, uint8 vl, void *context) +{ + ValidateContext2_t *ValidateContext2 = (ValidateContext2_t*)context; + + if (entryPortp) + (*ValidateContext2->callback)(entryPortp, vl, ValidateContext2->context); + + if (exitPortp) + (*ValidateContext2->callback)(exitPortp, vl, ValidateContext2->context); + + return FSUCCESS; +} + +static FSTATUS getSLSCInfo(FabricData_t *fabricp, EUI64 portGuid, int quiet, uint32 *usedSLs, uint32 *usedSCs) { + uint32 usedSCsSave = 0; + LIST_ITEM *i; + + for (i = QListHead(&fabricp->AllVFs); i; i = QListNext(&fabricp->AllVFs, i)) { + STL_VFINFO_RECORD *vfr = &((VFData_t*)QListObj(i))->record; + (*usedSLs) |= 1 << vfr->s1.slBase; + if (vfr->slResponseSpecified) + (*usedSLs) |= 1 << vfr->slResponse; + } + + if (!usedSCs) { + return FSUCCESS; + } + + cl_map_item_t *n; + for (n = cl_qmap_head(&fabricp->AllNodes); n != cl_qmap_end(&fabricp->AllNodes) && (*usedSCs) != 0xff7f; n = cl_qmap_next(n)) { + NodeData *nodep = PARENT_STRUCT(n, NodeData, AllNodesEntry); + cl_map_item_t *p; + for (p = cl_qmap_head(&nodep->Ports); p != cl_qmap_end(&nodep->Ports); p = cl_qmap_next(p)) { + PortData *portp = PARENT_STRUCT(p, PortData, NodePortsEntry); + + // for each host and switch port 0 + if (nodep->NodeInfo.NodeType == STL_NODE_SW && portp->PortNum != 0) { + continue; + } + + // for each SL + int sl; + for (sl = 0; sl < STL_MAX_SLS; sl++) { + if (((*usedSLs) >> sl) & 1) { + STL_SC sc = portp->pQOS->SL2SCMap->SLSCMap[sl]; + // if SL2SC is a valid SC + if (sc.SC != 15) { + // add SC to used SCs + (*usedSCs) |= (1 << sc.SC); + } + } + } + } + } + + do { + usedSCsSave = (*usedSCs); + // for each switch in fabric + LIST_ITEM *sw; + for (sw = QListHead(&fabricp->AllSWs); sw != NULL; sw = QListNext(&fabricp->AllSWs, sw)) { + NodeData *nodep = (NodeData *)QListObj(sw); + cl_map_item_t *p; + // for each ingress/egress port pair + for (p = cl_qmap_head(&nodep->Ports); p != cl_qmap_end(&nodep->Ports); p = cl_qmap_next(p)) { + PortData *portp = PARENT_STRUCT(p, PortData, NodePortsEntry); + + if (portp->PortNum == 0) { + continue; + } + + int e; + for (e = 0; e < nodep->NodeInfo.NumPorts; e++) { + uint8 sc; + // for each used SC + for (sc = 0; ((*usedSCs) >> sc); sc++) { + if (((*usedSCs) >> sc) & 1) { + // add SC2SC[ingress,egress,inputSC] to used SCs + STL_SCSCMAP *pSCSC = QOSDataLookupSCSCMap(portp, e, 0); + if (!pSCSC) continue; + STL_SC newSC = pSCSC->SCSCMap[sc]; + if (newSC.SC != 15) { + (*usedSCs) |= (1 << newSC.SC); + } + } + } + } + } + } + } while ((*usedSCs) != usedSCsSave); + + return FSUCCESS; +} + +// report all routes from portp1 to portp2 +FSTATUS ValidateRoutes(FabricData_t *fabricp, + PortData *portp1, PortData *portp2, + uint32 *totalPaths, uint32 *badPaths, + uint32 usedSLs, uint8 rc, + ValidateCallback_t callback, void *context, + ValidateCallback2_t callback2, void *context2) +{ + int offset; + int count = (1<PortInfo.s1.LMC); + FSTATUS status = FSUCCESS; + ValidateContext2_t ValidateContext2 ={callback:callback2, context:context2}; + + *totalPaths = 0; + *badPaths = 0; + + // IB is destination routed, so just need starting port, no need to + // iterate on all SLIDs for that port + // loop over the used SLs + uint8 sl; + for (sl = 0; sl < STL_MAX_SLS; sl++) { + if ((usedSLs == 0 && sl == 0) || (usedSLs >> sl) & 1) { + status = WalkRoutePort(fabricp, portp1, + portp2->PortInfo.LID, sl, rc, + ValidateRouteCallback, NULL); // Base LID + } else { + continue; + } + if (status == FUNAVAILABLE) { + return status; + } + (*totalPaths)++; + if (status != FSUCCESS) { + (*badPaths)++; + (*callback)(portp1, portp2, portp2->PortInfo.LID, + TRUE, sl, context); + if (callback2) { + // re-walk route and output details of each hop + (void)WalkRoutePort(fabricp, portp1, + portp2->PortInfo.LID, 0, rc, + ValidateRouteCallback2, &ValidateContext2); + (*callback2)(NULL, 0, context2); // close out path + } + } + + for (offset = 1; offset < count; offset++) { + status = WalkRoutePort(fabricp, portp1, + portp2->PortInfo.LID|offset, sl, rc, + ValidateRouteCallback, NULL); // LMC LID + if (status == FUNAVAILABLE) + return status; + (*totalPaths)++; + if (status != FSUCCESS) { + (*badPaths)++; + (*callback)(portp1, portp2, portp2->PortInfo.LID|offset, + FALSE, sl, context); + if (callback2) { + // re-walk route and output details of each hop + (void)WalkRoutePort(fabricp, portp1, + portp2->PortInfo.LID, 0, rc, + ValidateRouteCallback2, &ValidateContext2); + (*callback2)(NULL, 0, context2); // close out path + } + } + } + if (usedSLs == 0) break; + } + return FSUCCESS; +} + + +// validate all the routes between all LIDs, exclude loopback routes +FSTATUS ValidateAllRoutes(FabricData_t *fabricp, EUI64 portGuid, uint8 rc, + uint32 *totalPaths, uint32 *badPaths, + ValidateCallback_t callback, void *context, + ValidateCallback2_t callback2, void *context2, + uint8 useSCSC) +{ + cl_map_item_t *n1, *n2; + cl_map_item_t *p1, *p2; + FSTATUS status; + uint32 pathCount, badPathCount; + uint32 usedSLs = 0; + + *totalPaths = 0; + *badPaths = 0; + + if (useSCSC) { + // get the SL information, SCs not needed + if ((status = getSLSCInfo(fabricp, portGuid, 1, &usedSLs, NULL)) != FSUCCESS) { + return status; + } + } + + for (n1=cl_qmap_head(&fabricp->AllNodes); n1 != cl_qmap_end(&fabricp->AllNodes); n1 = cl_qmap_next(n1)) { + NodeData *nodep1 = PARENT_STRUCT(n1, NodeData, AllNodesEntry); + for (p1=cl_qmap_head(&nodep1->Ports); p1 != cl_qmap_end(&nodep1->Ports); p1 = cl_qmap_next(p1)) { + PortData *portp1 = PARENT_STRUCT(p1, PortData, NodePortsEntry); + if (nodep1->NodeInfo.NodeType == STL_NODE_SW && portp1->PortNum != 0) { + // only port 0 of a switch has a LID + continue; + } + + for (n2=cl_qmap_head(&fabricp->AllNodes); n2 != cl_qmap_end(&fabricp->AllNodes); n2 = cl_qmap_next(n2)) { + NodeData *nodep2 = PARENT_STRUCT(n2, NodeData, AllNodesEntry); + + // enable this if we want to skip node to self paths + //if (nodep1 == nodep2) continue; + + for (p2=cl_qmap_head(&nodep2->Ports); p2 != cl_qmap_end(&nodep2->Ports); p2 = cl_qmap_next(p2)) { + PortData *portp2 = PARENT_STRUCT(p2, PortData, NodePortsEntry); + if (nodep2->NodeInfo.NodeType == STL_NODE_SW && portp2->PortNum != 0) { + // only port 0 of a switch has a LID + continue; + } + // skip loopback paths + if (portp1 == portp2) continue; + status = ValidateRoutes(fabricp, portp1, portp2, &pathCount, &badPathCount, usedSLs, rc, callback, context, callback2, context2); + if (status == FUNAVAILABLE) + return status; + (*totalPaths) += pathCount; + (*badPaths) += badPathCount; + } + } + } + } + return FSUCCESS; +} + + +////////////////////////////////////////////////////// +// multicast routes functions // +////////////////////////////////////////////////////// + +static STL_PORTMASK *LookupMFT(PortData *portp, STL_LID mlid, uint8 pos) +{ + STL_PORTMASK *PortMask; + uint32 entry; + uint32 MCFDBSize; + + DEBUG_ASSERT(portp->nodep->switchp && portp->nodep->switchp->MulticastFDB[0]); //caller checks + + // Get index independent of mlid format (16-bit or 32-bit) + entry = GetMulticastOffset((uint32)mlid); + MCFDBSize = portp->nodep->switchp->MulticastFDBSize & MULTICAST_LID_OFFSET_MASK; + if (entry >=MCFDBSize) + return NULL; + + if (pos >= STL_NUM_MFT_POSITIONS_MASK) + return NULL; + + PortMask= GetMulticastFDBEntry(portp->nodep, entry, pos); + + return PortMask; +} + +// copying the route with problems to main list for later display. +static FSTATUS CopyAndInsertMcLoopInc(FabricData_t *fabricp, MCROUTESTATUS MCRouteStatus, McLoopInc *pMcLoopInc) +{ + LIST_ITEM *p; + + McLoopInc *pMcLoopIncR = (McLoopInc*)MemoryAllocate2AndClear(sizeof(McLoopInc), IBA_MEM_FLAG_PREMPTABLE, MYTAG); + if (! pMcLoopIncR) { + fprintf(stderr, "Unable to allocate memory to init a list of MC loop and incomplete routes\n"); + return FINSUFFICIENT_MEMORY; + } + //copying contents of pMcLoopInc to the new record. + pMcLoopIncR->status = MCRouteStatus; + pMcLoopIncR->mlid = pMcLoopInc->mlid; + + + QListInitState(&pMcLoopIncR->AllMcNodeLoopIncR); + if (!QListInit(&pMcLoopIncR->AllMcNodeLoopIncR)) { + fprintf(stderr, "Unable to initialize List of nodes with not found MC routes\n"); + //deallocate mem + MemoryDeallocate(pMcLoopIncR); + return FINSUFFICIENT_MEMORY; + } + + // copying list of nodes + for (p = QListHead(&pMcLoopInc->AllMcNodeLoopIncR); p!= NULL; p = QListNext( &pMcLoopInc->AllMcNodeLoopIncR,p) ){ + // retrieve current node + McNodeLoopInc *pmcnode = (McNodeLoopInc *) QListObj(p); + // create new node + McNodeLoopInc *pMcNodeLoopIncR = (McNodeLoopInc*)MemoryAllocate2AndClear(sizeof(McNodeLoopInc), IBA_MEM_FLAG_PREMPTABLE, MYTAG); + if (! pMcNodeLoopIncR) { + fprintf(stderr, "Unable to allocate memory to init a list of MC loop and incomplete routes\n"); + MemoryDeallocate(pMcLoopIncR); + return FINSUFFICIENT_MEMORY; + } + // copy node to node + pMcNodeLoopIncR->pPort = pmcnode->pPort; + pMcNodeLoopIncR->entryPort = pmcnode->entryPort; + pMcNodeLoopIncR->exitPort = pmcnode->exitPort; + //insert new node + QListSetObj(&pMcNodeLoopIncR->McNodeEntry, pMcNodeLoopIncR); + QListInsertTail(&pMcLoopIncR->AllMcNodeLoopIncR , &pMcNodeLoopIncR->McNodeEntry); + } // end for + + + //When all nodes were copied add route item to the main list + QListSetObj(&pMcLoopIncR->LoopIncEntry, pMcLoopIncR); + QListInsertTail(&fabricp->AllMcLoopIncRoutes[MCRouteStatus].AllMcRouteStatus, &pMcLoopIncR->LoopIncEntry); + + return FSUCCESS; +} + +static FSTATUS IsMemberMcGroup(McGroupData *mcgroupp, PortData *portp) +{ + LIST_ITEM *p; + + for (p=QListHead(&mcgroupp->AllMcGroupMembers); p!= NULL; p = QListNext(&mcgroupp->AllMcGroupMembers,p)) { + McMemberData *mcmp = (McMemberData *)QListObj(p); + if (mcmp->MemberInfo.RID.PortGID.AsReg64s.L == portp->nodep->NodeInfo.NodeGUID) { + /*if (!mcmp->MemberInfo.JoinFullMember) + return FNOT_FOUND; + else */return FSUCCESS; + } + } + return FNOT_FOUND; +} + +// Walk MC route from portp for mlid group. +// +// returns status of MC route (if not FSUCCESS) +// FUNAVAILABLE - no routing tables in FabricData given +// FNOT_FOUND - unable to find starting port +// FNOT_DONE - unable to trace route, mlid is a dead end +// FDUPLICATE - loop detected in mc routes + +FSTATUS WalkMCRoute(FabricData_t *fabricp, McGroupData *mcgroupp, PortData *portp, int hop, + uint8 EntryPort, McLoopInc *pMcLoopInc, uint32 *pathCount) +{ + PortData *portp2, *portn; // next port in route + STL_PORTMASK *pp; + FSTATUS status=FSUCCESS; + uint64 Port_res; + SwitchData *switchp; + MCROUTESTATUS mcroutestat; + McNodeLoopInc McNodeLoopIncR, *pMcNodeLoopIncR; + + pMcNodeLoopIncR = &McNodeLoopIncR; + + ListItemInitState(&pMcNodeLoopIncR->McNodeEntry); + pMcNodeLoopIncR->pPort = portp; + pMcNodeLoopIncR->entryPort = EntryPort; + pMcNodeLoopIncR->exitPort = 0; + + QListSetObj(&pMcNodeLoopIncR->McNodeEntry, pMcNodeLoopIncR); + QListInsertTail(&pMcLoopInc->AllMcNodeLoopIncR , &pMcNodeLoopIncR->McNodeEntry); + + if ((hop) >= 64) { + // add list to NOT_DONE + mcroutestat=MC_NO_TRACE; + status = CopyAndInsertMcLoopInc(fabricp, mcroutestat, pMcLoopInc); + if (status== FINSUFFICIENT_MEMORY) { + fprintf(stderr, "Unable to allocate memory\n"); + return FERROR; + } + QListRemoveTail(&pMcLoopInc->AllMcNodeLoopIncR); + (*pathCount)++; + return FNOT_DONE; // too long a path + } +// if port is FI them check membership, if OK then reach end-of-route +// if port is SW; Port0 then check membership, if OK then reach end-of-route + if (( (hop > 1) && (portp->nodep->NodeInfo.NodeType == STL_NODE_SW) + && (EntryPort == 0) && portp->nodep->pSwitchInfo->SwitchInfoData.u2.s.EnhancedPort0) // this is a enhanced Port0; + || (portp->nodep->NodeInfo.NodeType == STL_NODE_FI)) { // these are end-nodes + status = IsMemberMcGroup(mcgroupp, portp); + (*pathCount)++; + if (status != FSUCCESS) { + mcroutestat=MC_NOGROUP; + status = CopyAndInsertMcLoopInc(fabricp, mcroutestat, pMcLoopInc); + if (status == FINSUFFICIENT_MEMORY) { + fprintf(stderr, "Unable to allocate memory\n"); + return FERROR; + } + QListRemoveTail(&pMcLoopInc->AllMcNodeLoopIncR); + return FUNAVAILABLE; // not a member + } + else { + QListRemoveTail(&pMcLoopInc->AllMcNodeLoopIncR); + } + return FSUCCESS; + } + if ((EntryPort == 0) && (hop > 1)){ // Port 0 cannot be switch external port + mcroutestat=MC_NOGROUP; + status = CopyAndInsertMcLoopInc(fabricp,mcroutestat, pMcLoopInc); + if (status== FINSUFFICIENT_MEMORY) { + fprintf(stderr, "Unable to allocate memory\n"); + return FERROR; + } + QListRemoveTail(&pMcLoopInc->AllMcNodeLoopIncR); + return FNOT_DONE; + } +// if we are here, port can be a switch + switchp = portp->nodep->switchp; + +// //test if there is a switch + if (!switchp) { + mcroutestat=MC_NO_TRACE; + status = CopyAndInsertMcLoopInc(fabricp,mcroutestat, pMcLoopInc); + if (status== FINSUFFICIENT_MEMORY) { + fprintf(stderr, "Unable to allocate memory\n"); + return FERROR; + } + QListRemoveTail(&pMcLoopInc->AllMcNodeLoopIncR); + (*pathCount)++; + return FNOT_DONE; + } + +//test if there is a routing table + if (!switchp->MulticastFDB) { + mcroutestat=MC_UNAVAILABLE; + status = CopyAndInsertMcLoopInc(fabricp,mcroutestat, pMcLoopInc); + if (status== FINSUFFICIENT_MEMORY) { + fprintf(stderr, "Unable to allocate memory\n"); + return FERROR; + } + QListRemoveTail(&pMcLoopInc->AllMcNodeLoopIncR); + (*pathCount)++; + return FUNAVAILABLE; + } + +// check if the size of the table is enough +// check if MulticastFDBTop <= MulticastFDBCap + uint32 MCTableSize; +// lower 14 bits of top + MCTableSize = portp->nodep->pSwitchInfo->SwitchInfoData.MulticastFDBTop & MULTICAST_LID_OFFSET_MASK; + if (MCTableSize > portp->nodep->pSwitchInfo->SwitchInfoData.MulticastFDBCap){ + mcroutestat=MC_UNAVAILABLE; + status = CopyAndInsertMcLoopInc(fabricp,mcroutestat, pMcLoopInc); + if (status== FINSUFFICIENT_MEMORY) { + fprintf(stderr, "Unable to allocate memory\n"); + return FERROR; + } + QListRemoveTail(&pMcLoopInc->AllMcNodeLoopIncR); + (*pathCount)++; + return FUNAVAILABLE; + } + +// get index to retrieve routing ports for MC from the MC table + int ix_lid = GetMulticastOffset((uint32)pMcLoopInc->mlid); + //verify that index lies within the table size + if ( ix_lid > MCTableSize) { + mcroutestat=MC_UNAVAILABLE; + status = CopyAndInsertMcLoopInc(fabricp,mcroutestat, pMcLoopInc); + if (status== FINSUFFICIENT_MEMORY) { + fprintf(stderr, "Unable to allocate memory\n"); + return FERROR; + } + QListRemoveTail(&pMcLoopInc->AllMcNodeLoopIncR); + (*pathCount)++; + return FUNAVAILABLE; + } + + + // is this my first visit here? + if (!portp->nodep->switchp->HasBeenVisited) + portp->nodep->switchp->HasBeenVisited = 1; + else { //if not... there is a loop. + mcroutestat=MC_LOOP; + status = CopyAndInsertMcLoopInc(fabricp,mcroutestat, pMcLoopInc); + if (status== FINSUFFICIENT_MEMORY) { + fprintf(stderr, "Unable to allocate memory\n"); + return FERROR; + } + QListRemoveTail(&pMcLoopInc->AllMcNodeLoopIncR); + (*pathCount)++; + return FDUPLICATE; + } + + // getting information of number of ports for the current switch to run the loop only for those values + // limiting max. num of ports to 256 + uint8 swmaxnumport = portp->nodep->NodeInfo.NumPorts; + if (swmaxnumport > STL_MAX_PORTS) { + fprintf(stderr, "Cannot handle more than %d different ports\n", STL_MAX_PORTS); + return FERROR; + } + + uint8 pos=0; + int ix_port; + for (ix_port=0; ix_port <= swmaxnumport; ix_port ++) { + if (EntryPort != ix_port) { + //select correct mask to test given 256 max ports + pos = ix_port / STL_PORT_MASK_WIDTH; + pp = LookupMFT(portp, (uint32)pMcLoopInc->mlid, pos); + if (pp==NULL) { + mcroutestat=MC_UNAVAILABLE; + status = CopyAndInsertMcLoopInc(fabricp,mcroutestat, pMcLoopInc); + if (status== FINSUFFICIENT_MEMORY) { + fprintf(stderr, "Unable to allocate memory\n"); + return FERROR; + } + QListRemoveTail(&pMcLoopInc->AllMcNodeLoopIncR); + (*pathCount)++; + return FUNAVAILABLE; + } + Port_res = ((uint64_t)1<< (ix_port % STL_PORT_MASK_WIDTH)) & *pp;/// this must be compatible with 4 columns of 64 bits each + if (Port_res != 0) { //matching port + pMcNodeLoopIncR->exitPort = ix_port; // save exit port + if (ix_port == 0) { + status = WalkMCRoute( fabricp, mcgroupp, portp, (hop+1), 0, pMcLoopInc, pathCount); + if (status == FERROR) + return FERROR; + } + else { + portp2 = FindNodePort(portp->nodep, ix_port); + if (! portp2 || ! IsPortInitialized(portp2->PortInfo.PortStates) + || (!portp2->neighbor)) { + mcroutestat=MC_NO_TRACE; + status = CopyAndInsertMcLoopInc(fabricp,mcroutestat, pMcLoopInc); + if (status== FINSUFFICIENT_MEMORY) { + fprintf(stderr, "Unable to allocate memory\n"); + return FERROR; + } + (*pathCount)++; + status = FNOT_DONE; + } // Non viable route + else { + portn = portp2->neighbor; // mist be the entry port of the next switch + status = WalkMCRoute( fabricp, mcgroupp, portn, (hop+1), portn->PortNum, pMcLoopInc, pathCount); + if (status == FERROR) + // just return all the way + return FERROR; + } //end else + } //end else + } // end of there is a match + }// end of entry port != exit port + } // end for looking for next port + QListRemoveTail(&pMcLoopInc->AllMcNodeLoopIncR); + + return status; +} + +// report all MC routes +FSTATUS ValidateMCRoutes(FabricData_t *fabricp, McGroupData *mcgroupp, + McEdgeSwitchData *swp, uint32 *pathCount) +{ + FSTATUS status; + + SwitchData *switchp; + PortData *portp1; + LIST_ITEM *n1; + portp1 = swp->pPort; + + switchp = portp1->nodep->switchp; + if (!switchp) { + printf("No switch connected to HFI \n"); + return FNOT_DONE; + } + + McLoopInc mcLoop; + QListInitState(&mcLoop.AllMcNodeLoopIncR); + if (!QListInit(&mcLoop.AllMcNodeLoopIncR)) { + fprintf(stderr, "Unable to initialize List of nodes for loops and incomplete MC routes\n"); + return FERROR; + } + + mcLoop.mlid = mcgroupp->MLID; // identifies the route to analyze + + /* clear visited flag set in previous call to WalkMCRoute for every node */ + for (n1 = QListHead(&fabricp->AllSWs ); n1 != NULL; n1= QListNext(&fabricp->AllSWs, n1)) { + NodeData * node = (NodeData*)QListObj(n1); + node->switchp->HasBeenVisited=0; + } + status = WalkMCRoute( fabricp, mcgroupp, portp1, 1, swp->EntryPort, &mcLoop, pathCount); + + return status; +} + +FSTATUS InitListofLoopAndIncMCRoutes(FabricData_t *fabricp) + +{ int i; + + // init list of loops and incomplete MC routes + + fabricp->AllMcLoopIncRoutes[0].status=MC_NO_TRACE; + fabricp->AllMcLoopIncRoutes[1].status=MC_NOT_FOUND; + fabricp->AllMcLoopIncRoutes[2].status=MC_UNAVAILABLE; + fabricp->AllMcLoopIncRoutes[3].status=MC_LOOP; + fabricp->AllMcLoopIncRoutes[4].status=MC_NOGROUP; + + + for (i=0; iAllMcLoopIncRoutes[i].AllMcRouteStatus); + if (!QListInit(&fabricp->AllMcLoopIncRoutes[i].AllMcRouteStatus)) { + fprintf(stderr, "Unable to initialize List of MC loops and incomplete routes\n"); + return FERROR; + } + } + return FSUCCESS; +} + + +FSTATUS ValidateAllMCRoutes(FabricData_t *fabricp, uint32 *totalPaths ) + +{ LIST_ITEM *n1, *p1, *q1; + FSTATUS status; + McMemberData *pMCM1; + uint32 pathCount; + + *totalPaths = 0; + + status = InitListofLoopAndIncMCRoutes(fabricp); + if (status!=FSUCCESS) + return FERROR; + + // init all switches as never been visited + for (n1 = QListHead(&fabricp->AllSWs ); n1 != NULL; n1= QListNext(&fabricp->AllSWs, n1)) { + NodeData * node = (NodeData*)QListObj(n1); + node->switchp->HasBeenVisited=0; + } + + for (n1 = QListHead(&fabricp->AllMcGroups); n1 != NULL; n1= QListNext(&fabricp->AllMcGroups, n1)) { + McGroupData *pmcgmember = (McGroupData *)QListObj(n1); + //for this group get all member information + p1 = QListHead(&pmcgmember->AllMcGroupMembers); + pMCM1 = (McMemberData *)QListObj(p1); + // do not validate routes empty groups or groups with 1 member + if ((pMCM1->MemberInfo.RID.PortGID.AsReg64s.H != 0) || (pMCM1->MemberInfo.RID.PortGID.AsReg64s.L!=0)) { + if (pmcgmember->NumOfMembers > 1) { + for (q1 = QListHead(&pmcgmember->EdgeSwitchesInGroup); q1 != NULL; q1= QListNext(&pmcgmember->EdgeSwitchesInGroup, q1)) { + pathCount=0; + McEdgeSwitchData *swp = (McEdgeSwitchData *)QListObj(q1); + status = ValidateMCRoutes(fabricp, pmcgmember, swp, &pathCount); + if (status ==FERROR) { + fprintf(stderr, "Unable to validate MC routes\n"); + return FERROR; + } + (*totalPaths) += pathCount; + } + } // end if num members >1 +// }// end evaluating groups with non-zero members*/ + } // end evaluating one MC group + } // end for all MC groups + + return FSUCCESS; +} // End of ValidateAllMCRoutes + +void FreeValidateMCRoutes(FabricData_t *fabricp) +{ int i; + LIST_ITEM *p, *q; + + for (i=0;iAllMcLoopIncRoutes[i].AllMcRouteStatus) ){ + p = QListTail(&fabricp->AllMcLoopIncRoutes[i].AllMcRouteStatus); + McLoopInc *pmcloop = (McLoopInc *) QListObj(p); + //remove members in each mc route + while (!QListIsEmpty(&pmcloop->AllMcNodeLoopIncR)) { + q = QListTail(&pmcloop->AllMcNodeLoopIncR); + McNodeLoopInc *pmcnodeloop = (McNodeLoopInc *) QListObj(q); + QListRemoveTail(&pmcloop->AllMcNodeLoopIncR); + MemoryDeallocate (pmcnodeloop); + } // end while q + QListRemoveTail(&fabricp->AllMcLoopIncRoutes[i].AllMcRouteStatus); + MemoryDeallocate (pmcloop); + }// end while p + }// end for 0..4 + return; + +} + +////////// /////////// end of MC-related functions + + + +#ifndef __VXWORKS__ + +static FSTATUS CLGetRoute(FabricData_t *fabricp, EUI64 portGuid, uint8 rc, + PortData *portp1, PortData *portp2, + IB_PATH_RECORD *pathp, uint32 *totalPaths, uint32 *totalBadPaths, + ValidateCLRouteCallback_t callback, void *context, uint8 snapshotInFile, + uint32 usedSCs) +{ + FSTATUS status; + STL_TRACE_RECORD *pTraceRecords = NULL; + uint32 NumTraceRecords = 0; + int i = -1, detail = 0, quiet = 0; + uint32 links = 0; + PortData *p = portp1,*fromPortp = portp1; + int p_shown = 0; + clConnPathData_t pathInfo; + PQUERY_RESULT_VALUES pQueryResults = NULL; + ValidateCreditLoopRoutesContext_t *cp = (ValidateCreditLoopRoutesContext_t *)context; + + + if (cp) detail = cp->detail; + if (cp) quiet = (cp->quiet == 1) ? 1 : 0; + + // add source and destination HFIs endnodes to device list + if (portp1->nodep->NodeInfo.NodeType != STL_NODE_FI || portp2->nodep->NodeInfo.NodeType != STL_NODE_FI) { + status = FINVALID_PARAMETER; + goto done; + } else if (!CLDataAddDevice(fabricp, portp1->nodep, pathp->SLID, detail, quiet) || + !CLDataAddDevice(fabricp, portp2->nodep, pathp->DLID, detail, quiet)) { + status = FINSUFFICIENT_MEMORY; + goto done; + } + + if (portp1 == portp2) { + /* special case, internal loopback */ + status = FSUCCESS; + goto done; + } + if (portp1->neighbor == portp2) { + /* special case, single link traversed */ + // Since portp1 has a neighbor, neither port is SW Port 0 + status = FSUCCESS; + goto done; + } + + // get trace route for path + status = GenTraceRoutePath(fabricp, pathp, rc, &pTraceRecords, &NumTraceRecords); + + if (NumTraceRecords <= 0) + goto badroute; + //ASSERT(NumTraceRecords > 0); + + /* the first Trace record should be the exit from portp1, however + * not all versions of the SM report this record + */ + if (pTraceRecords[0].NodeType != portp1->nodep->NodeInfo.NodeType) { + /* workaround SM bug, did not report initial exit port */ + // assume portp1 is not a Switch Port 0 + p = portp1->neighbor; + if (!p) { + goto badroute; + } + } + + // replicate path record for later use + MemoryCopy(&pathInfo.path, pathp, sizeof(IB_PATH_RECORD)); + + for (i = 0; i < NumTraceRecords; i++) { + // add switches to device list + if (!CLDataAddDevice(fabricp, p->nodep, 0, detail, quiet)) { + status = FINSUFFICIENT_MEMORY; + goto done; + } + if (p != portp1) { + // add up-link and down-link connections to connection list + + if (usedSCs && fromPortp->pQOS) { + uint8 sc; + for (sc = 0; (usedSCs >> sc); sc++) { + if ((usedSCs >> sc) & 1) { + if ((status = CLDataAddConnection(fabricp, fromPortp, p, &pathInfo, sc, detail, quiet)) || + (status = CLDataAddConnection(fabricp, p, fromPortp, &pathInfo, sc, detail, quiet))) { + if (status == FINSUFFICIENT_MEMORY) goto done; + goto badroute; + } + links++; + p_shown = 1; + } + } + if ((status = CLDataAddRoute(fabricp, pathp->SLID, pathp->DLID, fromPortp, detail, quiet))) { + if (status == FINSUFFICIENT_MEMORY) goto done; + goto badroute; + } + } else { + if ((status = CLDataAddConnection(fabricp, fromPortp, p, &pathInfo, 0, detail, quiet)) || + (status = CLDataAddConnection(fabricp, p, fromPortp, &pathInfo, 0, detail, quiet)) || + (status = CLDataAddRoute(fabricp, pathp->SLID, pathp->DLID, fromPortp, detail, quiet))) { + if (status == FINSUFFICIENT_MEMORY) goto done; + goto badroute; + } + links++; + p_shown = 1; + } + } + if (pTraceRecords[i].NodeType != STL_NODE_FI) { + p = FindNodePort(p->nodep, pTraceRecords[i].ExitPort); + if (!p) { + goto badroute; + } + if (0 == p->PortNum) { + /* Switch Port 0 thus must be final port */ + if (i + 1 != NumTraceRecords) { + goto badroute; + } + break; + } + + fromPortp = p; + if (p == portp2) { + // this should not happen. If we reach portp2 as the exit + // port of a switch, that implies portp2 must be port 0 of + // the switch which the test above should have caught + // but it doesn't hurt to have this redundant test here to be + // safe. + /* final port must be Switch Port 0 */ + if (i + 1 != NumTraceRecords) { + goto badroute; + } + } else { + p = p->neighbor; + if (!p) { + goto badroute; + } + p_shown = 0; + } + } else if (i == 0) { + /* since we caught FI to FI case above, SM must have given us + * initial Node in path + */ + /* unfortunately spec says Exit and Entry Port are 0 for CA, so + * can't verify consistency with portp1 + */ + p = portp1->neighbor; + if (!p) { + goto badroute; + } + p_shown = 0; + } else if (i + 1 != NumTraceRecords) { + goto badroute; + } + } + if (!p_shown) { + /* workaround SM bug, did not report final hop in route */ + // add up-link and down-link connections to connection list + if ((status = CLDataAddConnection(fabricp, fromPortp, portp2, &pathInfo, 0, detail, quiet)) || + (status = CLDataAddConnection(fabricp, portp2, fromPortp, &pathInfo, 0, detail, quiet)) || + (status = CLDataAddRoute(fabricp, pathp->SLID, pathp->DLID, fromPortp, detail, quiet))) { + if (status == FINSUFFICIENT_MEMORY) goto done; + goto badroute; + *totalPaths += 1; + } + } + if (p != portp2) { + goto badroute; + } + + *totalPaths += 1; + +done: + if (pQueryResults) + omgt_free_query_result_buffer(pQueryResults); + if (pTraceRecords) + MemoryDeallocate(pTraceRecords); + return status; + +badroute: + *totalBadPaths += 1; + status = FSUCCESS; // might as well process what we can + (void)callback(portp1, portp2, context); + + goto done; +} + +static FSTATUS CLGetRoutes(FabricData_t *fabricp, EUI64 portGuid, uint8 rc, + PortData *portp1, PortData *portp2, + uint32 *totalPaths, uint32 *totalBadPaths, + ValidateCLRouteCallback_t callback, void *context, + uint8 snapshotInFile, uint32 usedSCs) +{ + FSTATUS status; + int i; + uint32 NumPathRecords; + IB_PATH_RECORD *pPathRecords = NULL; + + + status = GenPaths(fabricp, portp1, portp2, &pPathRecords, &NumPathRecords); + + for (i = 0; i < NumPathRecords; i++) { + CLGetRoute(fabricp, portGuid, rc, portp1, portp2, &pPathRecords[i], + totalPaths, totalBadPaths, callback, context, snapshotInFile, + usedSCs); + } + + if (pPathRecords) + MemoryDeallocate(pPathRecords); + + return status; +} + +FSTATUS ValidateAllCreditLoopRoutes(FabricData_t *fabricp, EUI64 portGuid, uint8 rc, + ValidateCLRouteCallback_t routeCallback, + ValidateCLFabricSummaryCallback_t fabricSummaryCallback, + ValidateCLDataSummaryCallback_t dataSummaryCallback, + ValidateCLRouteSummaryCallback_t routeSummaryCallback, + ValidateCLLinkSummaryCallback_t linkSummaryCallback, + ValidateCLLinkStepSummaryCallback_t linkStepSummaryCallback, + ValidateCLPathSummaryCallback_t pathSummaryCallback, + ValidateCLTimeGetCallback_t timeGetCallback, + void *context, + uint8 snapshotInFile, + uint8 useSCSC) +{ + FSTATUS status; + int detail = 0, xmlFmt; + uint32 nodeCount = 1, totalPaths = 0, totalBadPaths = 0; + LIST_ITEM * n1,*n2; + cl_map_item_t * p1,*p2; + uint64_t sTime = 0, eTime = 0; + uint64_t sTotalTime = 0, eTotalTime = 0; + ValidateCreditLoopRoutesContext_t *cp = (ValidateCreditLoopRoutesContext_t *)context; + uint32 usedSCs = 0, usedSLs = 0; + + if (!cp) + return FNOT_DONE; + + detail = cp->detail; + xmlFmt = (cp->format == 1) ? 1 : 0; + + if (!xmlFmt && cp->detail >= 3) { + timeGetCallback(&sTotalTime, &g_cl_lock); + timeGetCallback(&sTime, &g_cl_lock); + printf("START build all the routes\n"); + } + + // find the used SCs + if (useSCSC) { + if ((status = getSLSCInfo(fabricp, portGuid, cp->quiet, &usedSLs, &usedSCs)) != FSUCCESS) { + return status; + } + } + + // + // collect routing information between all endnodes within the fabric + for (n1 = QListHead(&fabricp->AllFIs); n1 != NULL; n1 = QListNext(&fabricp->AllFIs, n1)) { + NodeData *nodep1 = (NodeData *)QListObj(n1); + if (!xmlFmt && cp->detail >= 3) { + printf("START build all routes from %s\n", nodep1->NodeDesc.NodeString); + } + + for (p1 = cl_qmap_head(&nodep1->Ports); p1 != cl_qmap_end(&nodep1->Ports); p1 = cl_qmap_next(p1), nodeCount++) { + PortData *portp1 = PARENT_STRUCT(p1, PortData, NodePortsEntry); + + if (nodep1->NodeInfo.NodeType == STL_NODE_SW && portp1->PortNum != 0) { + continue; + } + + for (n2 = QListHead(&fabricp->AllFIs); n2 != NULL; n2 = QListNext(&fabricp->AllFIs, n2)) { + NodeData *nodep2 = (NodeData *)QListObj(n2); + + // enable this if we want to skip node to self paths + //if (nodep1 == nodep2) continue; + + for (p2 = cl_qmap_head(&nodep2->Ports); p2 != cl_qmap_end(&nodep2->Ports); p2 = cl_qmap_next(p2)) { + PortData *portp2 = PARENT_STRUCT(p2, PortData, NodePortsEntry); + if (nodep2->NodeInfo.NodeType == STL_NODE_SW && portp2->PortNum != 0) { + continue; + } + // skip loopback paths + if (portp1 == portp2) + continue; + + if (FUNAVAILABLE == (status = CLGetRoutes(fabricp, portGuid, rc, portp1, portp2, + &totalPaths, &totalBadPaths, + routeCallback, context, snapshotInFile, + usedSCs))) + return status; + } + } + } + if (!xmlFmt && cp->detail >= 3) { + printf("END build all routes from %s\n", nodep1->NodeDesc.NodeString); + printf("%d of %d HFI nodes completed\n", ++nodeCount, QListCount(&fabricp->AllFIs)); + } else { + if (nodeCount % PROGRESS_FREQ == 0 || nodeCount == 1) + if (!cp->quiet) + ProgressPrint(FALSE, "Processed %6d of %6d Nodes...", nodeCount, QListCount(&fabricp->AllFIs)); + } + } + + if (!xmlFmt && cp->detail >= 3) { + timeGetCallback(&eTime, &g_cl_lock); + printf("END build all the routes; elapsed time(usec)=%d, (sec)=%d\n", + (int)(eTime - sTime), ((int)(eTime - sTime)) / CL_TIME_DIVISOR); + } + + // clear line used to display progress report + if (!cp->quiet) + ProgressPrint(TRUE, "Done Building All Routes"); + + //PYTHON: fabric.summary('Fabric') + (void)CLFabricSummary(fabricp, "Fabric", fabricSummaryCallback, totalPaths, totalBadPaths, cp); + + if (!cl_qmap_count(&fabricp->map_guid_to_ib_device) || !fabricp->ConnectionCount || !fabricp->RouteCount) + return FNOT_DONE; + + /* build graphical layout of all the routes */ + //PYTHON: full_graph = build_routing_graph(fabric) + if (!CLFabricDataBuildRouteGraph(fabricp, routeSummaryCallback, timeGetCallback, cp, usedSLs)) { + clGraphData_t *graphp; + + if (detail >= 3) { + //PYTHON: full_graph.summary('Full graph') + (void)CLGraphDataSummary(&fabricp->Graph, (xmlFmt) ? "FullGraph" : "Full graph", dataSummaryCallback, cp); + } + + /* prune the graph data */ + //PYTHON: pruned_graph.prune() + (void)CLGraphDataPrune(&fabricp->Graph, timeGetCallback, detail, cp->quiet); + + if (detail >= 3) { + //PYTHON: pruned_graph.summary('Pruned graph') + (void)CLGraphDataSummary(&fabricp->Graph, (xmlFmt) ? "PrunedGraph" : "Pruned graph", dataSummaryCallback, cp); + } + + /* split the graph data */ + //PYTHON: split_graph = pruned_graph.split() + if (!(graphp = CLGraphDataSplit(&fabricp->Graph, detail))) { + if (!xmlFmt) + printf("Routes are deadlock free (No credit loops detected)\n"); + } else { + int count = 0; + char title[100]; + clDijkstraDistancesAndRoutes_t dijkstraInfo; + + if (!xmlFmt) + printf("Deadlock detected in routes (Credit loops detected)\n"); + memset(&dijkstraInfo, 0, sizeof(dijkstraInfo)); + + //PYTHON: while split_graph : + while (graphp) { + if (detail >= 3) { + if (xmlFmt) + sprintf(title, "SplitGraph%d", count); + else + sprintf(title, "Split graph %d", count); + //PYTHON: split_graph.summary('Split graph %d' % count) + (void)CLGraphDataSummary(graphp, title, dataSummaryCallback, cp); + } + + /* find route distances via Dijkstra algorithm */ + //PYTHON: (distances, routes) = find_distances_and_routes_dijkstra(split_graph) + if (CLDijkstraFindDistancesAndRoutes(graphp, &dijkstraInfo, detail)) + break; + else { + //PYTHON: find_cycles(split_graph, distances, routes, ib_connection_source_to_str) + (void)CLDijkstraFindCycles(fabricp, graphp, &dijkstraInfo, + linkSummaryCallback, linkStepSummaryCallback, + pathSummaryCallback, cp); + /* free existing distances and routes relaed data */ + (void)CLDijkstraFreeDistancesAndRoutes(&dijkstraInfo); + //PYTHON: split_graph = pruned_graph.split() + CLGraphDataFree(graphp, cp); + MemoryDeallocate(graphp); // graphp was allocated by CLGraphDataSplit + graphp = CLGraphDataSplit(&fabricp->Graph, detail); + } + count += 1; + } + + if (detail >= 3 && count > 1) + printf("Dependencies split into %d disconnected graphs\n", count); + } + + // free all credit loop related data + if (graphp) MemoryDeallocate(graphp); + if (CLFabricDataDestroy(fabricp, cp)) + fprintf(stderr, "Warning, failed to deallocate route credit loop data\n"); + } + + if (!xmlFmt && cp->detail >= 3) { + timeGetCallback(&eTotalTime, &g_cl_lock); + printf("END Credit loop validation; elapsed time(usec)=%12"PRIu64", (sec)=%12"PRIu64"\n", + (eTotalTime - sTotalTime), ((eTotalTime - sTotalTime)) / CL_TIME_DIVISOR); + } + + return FSUCCESS; +} + +#endif diff --git a/Topology/search.c b/Topology/search.c new file mode 100644 index 0000000..d0c43dc --- /dev/null +++ b/Topology/search.c @@ -0,0 +1,2247 @@ +/* BEGIN_ICS_COPYRIGHT7 **************************************** + +Copyright (c) 2015-2018, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT7 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +#include "topology.h" +#include "topology_internal.h" +#include + +#ifndef __VXWORKS__ +#include +#endif + +// Functions to search the topology + + +// The search routines involving Points tend to limit the search to the +// specific objects indicated by find_flag and expect later caller use of +// Compare functions to invoke the necessary Compare functions to cover the +// fabric vs expected objects of interest. One exception is the comparison +// for Details and Cable information which is only available in topology.xml +// In this case, the fabric seach will check the resolved expected object +// This permits the majority of fabric related operations, such as opareport, +// to make use of Details and Cable information from topology.xml while +// only considering fabric objects. + +// search for the PortData corresponding to the given node and port number +PortData * FindNodePort(NodeData *nodep, uint8 port) +{ + cl_map_item_t *mi; + + mi = cl_qmap_get(&nodep->Ports, port); + if (mi == cl_qmap_end(&nodep->Ports)) + return NULL; + return PARENT_STRUCT(mi, PortData, NodePortsEntry); +} + +// a cl_pfm_qmap_item_compare_t function +// compare a LID (in key) against the range of Lids assigned to the +// given PortData item +// each PortData has LIDs from LID to LID|((1< 1), PortData has exactly 1 LID +// When LMC=1, PortData has 2 LIDs [LID to LID+1] +// When LMC=2, PortData has 4 LIDs [LID to LID+3] +// etc. +// Since non-zero LMC requires low "LMC" bits of LID to be 0 we use | +// however so we could also use an + instead of a | +static int CompareLid(const cl_map_item_t *mi, const uint64 key) +{ + PortData *portp = PARENT_STRUCT(mi, PortData, AllLidsEntry); + + if ((portp->PortInfo.LID | + ((1<PortInfo.s1.LMC)-1)) < key) + return -1; + else if (portp->PortInfo.LID > key) + return 1; + else + return 0; +} + +// search for the PortData corresponding to the given lid +// accounts for LMC giving a port a range of lids +PortData * FindLid(FabricData_t *fabricp, STL_LID lid) +{ + if (fabricp->flags & FF_LIDARRAY) { + return GetMapEntry(fabricp, lid); + } else { + cl_map_item_t *mi; + + mi = cl_qmap_get_item_compare(&fabricp->u.AllLids, lid, CompareLid); + if (mi == cl_qmap_end(&fabricp->u.AllLids)) + return NULL; + return PARENT_STRUCT(mi, PortData, AllLidsEntry); + } +} + +// search for the PortData corresponding to the given port Guid +PortData * FindPortGuid(FabricData_t *fabricp, EUI64 guid) +{ + LIST_ITEM *p; + + for (p=QListHead(&fabricp->AllPorts); p != NULL; p = QListNext(&fabricp->AllPorts, p)) { + PortData *portp = (PortData *)QListObj(p); + + if (portp->PortGUID == guid) + return portp; + } + return NULL; +} + +// search for the PortData, ExpectedNode, ExpectedSM and ExpectedLink +// corresponding to the given port guid +// and update the point with all those which match +// FNOT_FOUND - no instances found +// FINVALID_OPERATION - find_flag contains no applicable searches +// other - error allocating memory or initializing structures +FSTATUS FindPortGuidPoint(FabricData_t *fabricp, EUI64 guid, Point *pPoint, uint8 find_flag, int silent) +{ + FSTATUS status; + + ASSERT(! PointValid(pPoint)); + ASSERT(guid); + if (0 == find_flag) + return FINVALID_OPERATION; + if (find_flag & FIND_FLAG_FABRIC) { + pPoint->u.portp = FindPortGuid(fabricp, guid); + if (pPoint->u.portp) + pPoint->Type = POINT_TYPE_PORT; + } + if (find_flag & FIND_FLAG_ENODE) { + EUI64 nodeGUID = PortGUIDtoNodeGUID(guid); + LIST_ITEM *p; + QUICK_LIST *pList = &fabricp->ExpectedFIs; + // while there should be no duplicates, be safe and assume there might + while (pList != NULL) { + for (p=QListHead(pList); p != NULL; p = QListNext(pList, p)) { + ExpectedNode *enodep = (ExpectedNode *)QListObj(p); + if (enodep->NodeGUID == nodeGUID) + { + status = PointEnodeListAppend(pPoint, POINT_ENODE_TYPE_NODE_LIST, enodep); + if (FSUCCESS != status) + return status; + } + } + if (pList == &fabricp->ExpectedFIs) + pList = &fabricp->ExpectedSWs; + else + pList = NULL; + } + } + if (find_flag & FIND_FLAG_ESM) { + LIST_ITEM *p; + // while there should be no duplicates, be safe and assume there might + for (p=QListHead(&fabricp->ExpectedSMs); p != NULL; p = QListNext(&fabricp->ExpectedSMs, p)) { + ExpectedSM *esmp = (ExpectedSM *)QListObj(p); + if (esmp->PortGUID == guid) + { + status = PointEsmListAppend(pPoint, POINT_ESM_TYPE_SM_LIST, esmp); + if (FSUCCESS != status) + return status; + } + } + } + if (find_flag & FIND_FLAG_ELINK) { + LIST_ITEM *p; + for (p=QListHead(&fabricp->ExpectedLinks); p != NULL; p = QListNext(&fabricp->ExpectedLinks, p)) { + ExpectedLink *elinkp = (ExpectedLink *)QListObj(p); + if ((elinkp->portselp1 && elinkp->portselp1->PortGUID == guid) + || (elinkp->portselp2 && elinkp->portselp2->PortGUID == guid)) + { + status = PointElinkListAppend(pPoint, POINT_ELINK_TYPE_LINK_LIST, elinkp); + if (FSUCCESS != status) + return status; + } + } + } + if (! PointValid(pPoint)) { + if(!silent) + fprintf(stderr, "%s: Port GUID Not Found: 0x%016"PRIx64"\n", g_Top_cmdname, guid); + return FNOT_FOUND; + } + PointCompress(pPoint); + return FSUCCESS; +} + +// search for the PortData, ExpectedNode, ExpectedSM and ExpectedLink +// corresponding to the given GID +// and update the point with all those which match +// FNOT_FOUND - no instances found +// FINVALID_OPERATION - find_flag contains no applicable searches +// other - error allocating memory or initializing structures +FSTATUS FindGidPoint(FabricData_t *fabricp, IB_GID gid, Point *pPoint, uint8 find_flag, int silent) +{ + FSTATUS status; + + ASSERT(! PointValid(pPoint)); + ASSERT(gid.AsReg64s.H && gid.AsReg64s.L); + if (0 == (find_flag & (FIND_FLAG_FABRIC|FIND_FLAG_ENODE|FIND_FLAG_ESM|FIND_FLAG_ELINK))) + return FINVALID_OPERATION; + if (find_flag & FIND_FLAG_FABRIC) { + pPoint->u.portp = FindPortGuid(fabricp, gid.Type.Global.InterfaceID); + if (pPoint->u.portp && + pPoint->u.portp->PortInfo.SubnetPrefix + == gid.Type.Global.SubnetPrefix) { + pPoint->Type = POINT_TYPE_PORT; + } + } + if (find_flag & FIND_FLAG_ENODE) { + EUI64 nodeGUID = PortGUIDtoNodeGUID(gid.Type.Global.InterfaceID); + LIST_ITEM *p; + QUICK_LIST *pList = &fabricp->ExpectedFIs; + // while there should be no duplicates, be safe and assume there might + while (pList != NULL) { + for (p=QListHead(pList); p != NULL; p = QListNext(pList, p)) { + ExpectedNode *enodep = (ExpectedNode *)QListObj(p); + if (enodep->NodeGUID == nodeGUID) + { + status = PointEnodeListAppend(pPoint, POINT_ENODE_TYPE_NODE_LIST, enodep); + if (FSUCCESS != status) + return status; + } + } + if (pList == &fabricp->ExpectedFIs) + pList = &fabricp->ExpectedSWs; + else + pList = NULL; + } + } + if (find_flag & FIND_FLAG_ESM) { + LIST_ITEM *p; + // while there should be no duplicates, be safe and assume there might + for (p=QListHead(&fabricp->ExpectedSMs); p != NULL; p = QListNext(&fabricp->ExpectedSMs, p)) { + ExpectedSM *esmp = (ExpectedSM *)QListObj(p); + /* we should also check SubnetPrefix, but its not in ExpectedSM, + * so just check PortGuid + */ + if (esmp->PortGUID == gid.Type.Global.InterfaceID) + { + status = PointEsmListAppend(pPoint, POINT_ESM_TYPE_SM_LIST, esmp); + if (FSUCCESS != status) + return status; + } + } + } + if (find_flag & FIND_FLAG_ELINK) { + LIST_ITEM *p; + for (p=QListHead(&fabricp->ExpectedLinks); p != NULL; p = QListNext(&fabricp->ExpectedLinks, p)) { + ExpectedLink *elinkp = (ExpectedLink *)QListObj(p); + /* we should also check SubnetPrefix, but its not in ExpectedLink, + * so just check PortGuid + */ + if ((elinkp->portselp1 && elinkp->portselp1->PortGUID == gid.Type.Global.InterfaceID) + || (elinkp->portselp2 && elinkp->portselp2->PortGUID == gid.Type.Global.InterfaceID)) + { + status = PointElinkListAppend(pPoint, POINT_ELINK_TYPE_LINK_LIST, elinkp); + if (FSUCCESS != status) + return status; + } + } + } + if (! PointValid(pPoint)) { + if(!silent) { + fprintf(stderr, "%s: GID Not Found: 0x%016"PRIx64":0x%016"PRIx64"\n", + g_Top_cmdname, + gid.Type.Global.SubnetPrefix, gid.Type.Global.InterfaceID); + } + if ((find_flag & FIND_FLAG_FABRIC) && pPoint->u.portp + && pPoint->u.portp->PortInfo.SubnetPrefix + != gid.Type.Global.SubnetPrefix) { + if (! silent) { + fprintf(stderr, "%s: Subnet Prefix: 0x%016"PRIx64" does not match selected port: 0x%016"PRIx64"\n", + g_Top_cmdname, gid.Type.Global.SubnetPrefix, + pPoint->u.portp->PortInfo.SubnetPrefix); + } + pPoint->u.portp = NULL; + pPoint->Type = POINT_TYPE_NONE; + } + return FNOT_FOUND; + } + PointCompress(pPoint); + return FSUCCESS; +} + +// search for the NodeData corresponding to the given node Guid +NodeData * FindNodeGuid(const FabricData_t *fabricp, EUI64 guid) +{ + cl_map_item_t *mi; + + mi = cl_qmap_get(&fabricp->AllNodes, guid); + if (mi == cl_qmap_end(&fabricp->AllNodes)) + return NULL; + return PARENT_STRUCT(mi, NodeData, AllNodesEntry); +} + +// search for the NodeData, ExpectedNode, ExpectedSM and ExpectedLink +// corresponding to the given node guid +// and update the point with all those which match +// FNOT_FOUND - no instances found +// FINVALID_OPERATION - find_flag contains no applicable searches +// other - error allocating memory or initializing structures +FSTATUS FindNodeGuidPoint(FabricData_t *fabricp, EUI64 guid, Point *pPoint, uint8 find_flag, int silent) +{ + FSTATUS status; + + ASSERT(! PointValid(pPoint)); + ASSERT(guid); + if (0 == find_flag) + return FINVALID_OPERATION; + if (find_flag & FIND_FLAG_FABRIC) { + pPoint->u.nodep = FindNodeGuid(fabricp, guid); + if (pPoint->u.nodep) + pPoint->Type = POINT_TYPE_NODE; + } + if (find_flag & FIND_FLAG_ENODE) { + LIST_ITEM *p; + QUICK_LIST *pList = &fabricp->ExpectedFIs; + // while there should be no duplicates, be safe and assume there might + while (pList != NULL) { + for (p=QListHead(pList); p != NULL; p = QListNext(pList, p)) { + ExpectedNode *enodep = (ExpectedNode *)QListObj(p); + if (enodep->NodeGUID == guid) + { + status = PointEnodeListAppend(pPoint, POINT_ENODE_TYPE_NODE_LIST, enodep); + if (FSUCCESS != status) + return status; + } + } + if (pList == &fabricp->ExpectedFIs) + pList = &fabricp->ExpectedSWs; + else + pList = NULL; + } + } + if (find_flag & FIND_FLAG_ESM) { + LIST_ITEM *p; + // if an SM runs on multiple ports of a device, could validly be + // multiple matches of the same NodeGUID + for (p=QListHead(&fabricp->ExpectedSMs); p != NULL; p = QListNext(&fabricp->ExpectedSMs, p)) { + ExpectedSM *esmp = (ExpectedSM *)QListObj(p); + if (esmp->NodeGUID == guid) + { + status = PointEsmListAppend(pPoint, POINT_ESM_TYPE_SM_LIST, esmp); + if (FSUCCESS != status) + return status; + } + } + } + if (find_flag & FIND_FLAG_ELINK) { + LIST_ITEM *p; + for (p=QListHead(&fabricp->ExpectedLinks); p != NULL; p = QListNext(&fabricp->ExpectedLinks, p)) { + ExpectedLink *elinkp = (ExpectedLink *)QListObj(p); + if ((elinkp->portselp1 && elinkp->portselp1->NodeGUID == guid) + || (elinkp->portselp2 && elinkp->portselp2->NodeGUID == guid)) + { + status = PointElinkListAppend(pPoint, POINT_ELINK_TYPE_LINK_LIST, elinkp); + if (FSUCCESS != status) + return status; + } + } + } + if (! PointValid(pPoint)) { + if(!silent) + fprintf(stderr, "%s: Node GUID Not Found: 0x%016"PRIx64"\n", g_Top_cmdname, guid); + return FNOT_FOUND; + } + PointCompress(pPoint); + return FSUCCESS; +} + +// search for the NodeData, ExpectedNode, ExpectedSM and ExpectedLink +// corresponding to the given node name +// and update the point with all those which match +// FNOT_FOUND - no instances found +// FINVALID_OPERATION - find_flag contains no applicable searches +// other - error allocating memory or initializing structures +FSTATUS FindNodeNamePoint(FabricData_t *fabricp, char *name, Point *pPoint, uint8 find_flag, int silent) +{ + FSTATUS status; + + ASSERT(! PointValid(pPoint)); + if (0 == find_flag) + return FINVALID_OPERATION; + if (find_flag & FIND_FLAG_FABRIC) { + cl_map_item_t *p; + for (p=cl_qmap_head(&fabricp->AllNodes); p != cl_qmap_end(&fabricp->AllNodes); p = cl_qmap_next(p)) { + NodeData *nodep = PARENT_STRUCT(p, NodeData, AllNodesEntry); + if (strncmp((char*)nodep->NodeDesc.NodeString, + name, STL_NODE_DESCRIPTION_ARRAY_SIZE) == 0) + { + status = PointListAppend(pPoint, POINT_TYPE_NODE_LIST, nodep); + if (FSUCCESS != status) + return status; + } + } + } + if (find_flag & FIND_FLAG_ENODE) { + LIST_ITEM *p; + QUICK_LIST *pList = &fabricp->ExpectedFIs; + while (pList != NULL) { + for (p=QListHead(pList); p != NULL; p = QListNext(pList, p)) { + ExpectedNode *enodep = (ExpectedNode *)QListObj(p); + if (enodep->NodeDesc && strncmp(enodep->NodeDesc, + name, STL_NODE_DESCRIPTION_ARRAY_SIZE) == 0) + { + status = PointEnodeListAppend(pPoint, POINT_ENODE_TYPE_NODE_LIST, enodep); + if (FSUCCESS != status) + return status; + } + } + if (pList == &fabricp->ExpectedFIs) + pList = &fabricp->ExpectedSWs; + else + pList = NULL; + } + } + if (find_flag & FIND_FLAG_ESM) { + LIST_ITEM *p; + for (p=QListHead(&fabricp->ExpectedSMs); p != NULL; p = QListNext(&fabricp->ExpectedSMs, p)) { + ExpectedSM *esmp = (ExpectedSM *)QListObj(p); + if (esmp->NodeDesc && strncmp(esmp->NodeDesc, + name, STL_NODE_DESCRIPTION_ARRAY_SIZE) == 0) + { + status = PointEsmListAppend(pPoint, POINT_ESM_TYPE_SM_LIST, esmp); + if (FSUCCESS != status) + return status; + } + } + } + if (find_flag & FIND_FLAG_ELINK) { + LIST_ITEM *p; + for (p=QListHead(&fabricp->ExpectedLinks); p != NULL; p = QListNext(&fabricp->ExpectedLinks, p)) { + ExpectedLink *elinkp = (ExpectedLink *)QListObj(p); + if ((elinkp->portselp1 && elinkp->portselp1->NodeDesc + && strncmp(elinkp->portselp1->NodeDesc, + name, STL_NODE_DESCRIPTION_ARRAY_SIZE) == 0) + || (elinkp->portselp2 && elinkp->portselp2->NodeDesc + && strncmp(elinkp->portselp2->NodeDesc, + name, STL_NODE_DESCRIPTION_ARRAY_SIZE) == 0)) + { + status = PointElinkListAppend(pPoint, POINT_ELINK_TYPE_LINK_LIST, elinkp); + if (FSUCCESS != status) + return status; + } + } + } + if (! PointValid(pPoint)) { + if(!silent) + fprintf(stderr, "%s: Node name Not Found: %s\n", g_Top_cmdname, name); + return FNOT_FOUND; + } + PointCompress(pPoint); + return FSUCCESS; +} + +#ifndef __VXWORKS__ + +/* append searched objects that match the pattern */ +FSTATUS PopoulateNodePatPairs(NodePairList_t *nodePatPairs, uint8 side, void *object) +{ + DLIST *pList; + + if (side == LSIDE_PAIR){ + pList = &nodePatPairs->nodePairList1; + } else if(side == RSIDE_PAIR) { + pList = &nodePatPairs->nodePairList2; + } else { + return FINVALID_OPERATION; + } + + if (!ListInsertTail(pList, object)) { + fprintf(stderr, "%s: unable to allocate memory\n", g_Top_cmdname); + return FINSUFFICIENT_MEMORY; + } + return FSUCCESS; +} + +// search for the NodeData +// corresponding to the given node name pattern for the given Node Pair +// FNOT_FOUND - no instances found +// FINVALID_OPERATION - find_flag or side contains no applicable searches +// other - error allocating memory or initializing structures +FSTATUS FindNodePatPairs(FabricData_t *fabricp, char *pattern, NodePairList_t *nodePatPairs, + uint8 find_flag, uint8 side) +{ + FSTATUS status; + + if (0 == find_flag) + return FINVALID_OPERATION; + + if (0 == side) + return FINVALID_OPERATION; + + if (find_flag & FIND_FLAG_FABRIC){ + cl_map_item_t *p; + /* the node can be of type FI or SW */ + for (p = cl_qmap_head(&fabricp->AllNodes); p != cl_qmap_end(&fabricp->AllNodes); p = cl_qmap_next(p)){ + NodeData *nodep = PARENT_STRUCT(p, NodeData, AllNodesEntry); + /* find all SWs and FIs that match the pattern */ + if (fnmatch(pattern, (char*)nodep->NodeDesc.NodeString, 0) == 0){ + status = PopoulateNodePatPairs(nodePatPairs, side, nodep); + if (FSUCCESS != status) + return status; + } + } + return FSUCCESS; + } + return FNOT_FOUND; +} + +// search for the NodeData, ExpectedNode and ExpectedSM +// corresponding to the given node name pattern +// FNOT_FOUND - no instances found +// FINVALID_OPERATION - find_flag contains no applicable searches +// other - error allocating memory or initializing structures +FSTATUS FindNodeNamePatPoint(FabricData_t *fabricp, char *pattern, Point *pPoint, uint8 find_flag) +{ + FSTATUS status; + + ASSERT(pPoint); + status = FindNodeNamePatPointUncompress(fabricp, pattern, pPoint, find_flag); + if (FSUCCESS == status) + PointCompress(pPoint); + + return status; +} + +// search for the NodeData, ExpectedNode and ExpectedSM +// corresponding to the given node name pattern +// FNOT_FOUND - no instances found +// FINVALID_OPERATION - find_flag contains no applicable searches +// other - error allocating memory or initializing structures +FSTATUS FindNodeNamePatPointUncompress(FabricData_t *fabricp, char *pattern, Point *pPoint, uint8 find_flag) +{ + FSTATUS status; + + ASSERT(pPoint); + if (0 == find_flag) + return FINVALID_OPERATION; + if (find_flag & FIND_FLAG_FABRIC) { + cl_map_item_t *p; + for (p=cl_qmap_head(&fabricp->AllNodes); p != cl_qmap_end(&fabricp->AllNodes); p = cl_qmap_next(p)) { + NodeData *nodep = PARENT_STRUCT(p, NodeData, AllNodesEntry); + if (fnmatch(pattern, (char*)nodep->NodeDesc.NodeString, 0) == 0) + { + status = PointListAppend(pPoint, POINT_TYPE_NODE_LIST, nodep); + if (FSUCCESS != status) + return status; + //Set flag if the node is a switch or FI + if (nodep->NodeInfo.NodeType == STL_NODE_SW) + pPoint->haveSW = TRUE; + else if (nodep->NodeInfo.NodeType == STL_NODE_FI) + pPoint->haveFI = TRUE; + } + } + } + if (find_flag & FIND_FLAG_ENODE) { + LIST_ITEM *p; + QUICK_LIST *pList = &fabricp->ExpectedFIs; + while (pList != NULL) { + for (p=QListHead(pList); p != NULL; p = QListNext(pList, p)) { + ExpectedNode *enodep = (ExpectedNode *)QListObj(p); + if (enodep->NodeDesc + && 0 == fnmatch(pattern, enodep->NodeDesc, 0)) + { + status = PointEnodeListAppend(pPoint, POINT_ENODE_TYPE_NODE_LIST, enodep); + if (FSUCCESS != status) + return status; + } + } + if (pList == &fabricp->ExpectedFIs) + pList = &fabricp->ExpectedSWs; + else + pList = NULL; + } + } + if (find_flag & FIND_FLAG_ESM) { + LIST_ITEM *p; + for (p=QListHead(&fabricp->ExpectedSMs); p != NULL; p = QListNext(&fabricp->ExpectedSMs, p)) { + ExpectedSM *esmp = (ExpectedSM *)QListObj(p); + if (esmp->NodeDesc + && 0 == fnmatch(pattern, esmp->NodeDesc, 0)) + { + status = PointEsmListAppend(pPoint, POINT_ESM_TYPE_SM_LIST, esmp); + if (FSUCCESS != status) + return status; + } + } + } + if (find_flag & FIND_FLAG_ELINK) { + LIST_ITEM *p; + for (p=QListHead(&fabricp->ExpectedLinks); p != NULL; p = QListNext(&fabricp->ExpectedLinks, p)) { + ExpectedLink *elinkp = (ExpectedLink *)QListObj(p); + if ((elinkp->portselp1 && elinkp->portselp1->NodeDesc + && 0 == fnmatch(pattern, elinkp->portselp1->NodeDesc, 0)) + || (elinkp->portselp2 && elinkp->portselp2->NodeDesc + && 0 == fnmatch(pattern, elinkp->portselp2->NodeDesc, 0))) + { + status = PointElinkListAppend(pPoint, POINT_ELINK_TYPE_LINK_LIST, elinkp); + if (FSUCCESS != status) + return status; + } + } + } + if (! PointValid(pPoint)) { + fprintf(stderr, "%s: Node name pattern Not Found: %s\n", + g_Top_cmdname, pattern); + return FNOT_FOUND; + } + return FSUCCESS; +} + +// search for nodes whose ExpectedNode has the given node details +// FNOT_FOUND - no instances found +// FINVALID_OPERATION - find_flag contains no applicable searches +// other - error allocating memory or initializing structures +FSTATUS FindNodeDetailsPatPoint(FabricData_t *fabricp, const char* pattern, Point *pPoint, uint8 find_flag) +{ + FSTATUS status; + + ASSERT(! PointValid(pPoint)); + if (0 == (find_flag & (FIND_FLAG_FABRIC|FIND_FLAG_ENODE))) + return FINVALID_OPERATION; + if (find_flag & FIND_FLAG_FABRIC) { + cl_map_item_t *p; + for (p=cl_qmap_head(&fabricp->AllNodes); p != cl_qmap_end(&fabricp->AllNodes); p = cl_qmap_next(p)) { + NodeData *nodep = PARENT_STRUCT(p, NodeData, AllNodesEntry); + if (nodep->enodep && nodep->enodep->details + && fnmatch(pattern, nodep->enodep->details, 0) == 0) + { + status = PointListAppend(pPoint, POINT_TYPE_NODE_LIST, nodep); + if (FSUCCESS != status) + return status; + } + } + } + if (find_flag & FIND_FLAG_ENODE) { + LIST_ITEM *p; + QUICK_LIST *pList = &fabricp->ExpectedFIs; + while (pList != NULL) { + for (p=QListHead(pList); p != NULL; p = QListNext(pList, p)) { + ExpectedNode *enodep = (ExpectedNode *)QListObj(p); + if (enodep->details + && fnmatch(pattern, enodep->details, 0) == 0) + { + status = PointEnodeListAppend(pPoint, POINT_ENODE_TYPE_NODE_LIST, enodep); + if (FSUCCESS != status) + return status; + } + } + if (pList == &fabricp->ExpectedFIs) + pList = &fabricp->ExpectedSWs; + else + pList = NULL; + } + } + + // N/A for FIND_FLAG_ESM and FIND_FLAG_ELINK + + if (! PointValid(pPoint)) { + fprintf(stderr, "%s: Node Details Not Found: %s\n", + g_Top_cmdname, pattern); + return FNOT_FOUND; + } + PointCompress(pPoint); + return FSUCCESS; +} +#endif + +// search for the NodeData corresponding to the given node type +// FNOT_FOUND - no instances found +// FINVALID_OPERATION - find_flag contains no applicable searches +// other - error allocating memory or initializing structures +FSTATUS FindNodeTypePoint(FabricData_t *fabricp, NODE_TYPE type, Point *pPoint, uint8 find_flag) +{ + FSTATUS status; + + ASSERT(! PointValid(pPoint)); + if (0 == find_flag) + return FINVALID_OPERATION; + if (find_flag & FIND_FLAG_FABRIC) { + cl_map_item_t *p; + for (p=cl_qmap_head(&fabricp->AllNodes); p != cl_qmap_end(&fabricp->AllNodes); p = cl_qmap_next(p)) { + NodeData *nodep = PARENT_STRUCT(p, NodeData, AllNodesEntry); + if (nodep->NodeInfo.NodeType == type) + { + status = PointListAppend(pPoint, POINT_TYPE_NODE_LIST, nodep); + if (FSUCCESS != status) + return status; + } + } + } + if (find_flag & FIND_FLAG_ENODE) { + LIST_ITEM *p; + QUICK_LIST *pList = &fabricp->ExpectedFIs; + while (pList != NULL) { + for (p=QListHead(pList); p != NULL; p = QListNext(pList, p)) { + ExpectedNode *enodep = (ExpectedNode *)QListObj(p); + if (enodep->NodeType == type) + { + status = PointEnodeListAppend(pPoint, POINT_ENODE_TYPE_NODE_LIST, enodep); + if (FSUCCESS != status) + return status; + } + } + if (pList == &fabricp->ExpectedFIs) + pList = &fabricp->ExpectedSWs; + else + pList = NULL; + } + } + if (find_flag & FIND_FLAG_ESM) { + LIST_ITEM *p; + for (p=QListHead(&fabricp->ExpectedSMs); p != NULL; p = QListNext(&fabricp->ExpectedSMs, p)) { + ExpectedSM *esmp = (ExpectedSM *)QListObj(p); + if (esmp->NodeType == type) + { + status = PointEsmListAppend(pPoint, POINT_ESM_TYPE_SM_LIST, esmp); + if (FSUCCESS != status) + return status; + } + } + } + if (find_flag & FIND_FLAG_ELINK) { + LIST_ITEM *p; + for (p=QListHead(&fabricp->ExpectedLinks); p != NULL; p = QListNext(&fabricp->ExpectedLinks, p)) { + ExpectedLink *elinkp = (ExpectedLink *)QListObj(p); + if ( (elinkp->portselp1 && elinkp->portselp1->NodeType == type) + || (elinkp->portselp2 && elinkp->portselp2->NodeType == type)) + { + status = PointElinkListAppend(pPoint, POINT_ELINK_TYPE_LINK_LIST, elinkp); + if (FSUCCESS != status) + return status; + } + } + } + if (! PointValid(pPoint)) { + fprintf(stderr, "%s: No nodes of type %s found\n", + g_Top_cmdname, StlNodeTypeToText(type)); + return FNOT_FOUND; + } + PointCompress(pPoint); + return FSUCCESS; +} + +#if !defined(VXWORKS) || defined(BUILD_DMC) +// search for the Ioc corresponding to the given ioc name +// FNOT_FOUND - no instances found +// FINVALID_OPERATION - find_flag contains no applicable searches +// other - error allocating memory or initializing structures +FSTATUS FindIocNamePoint(FabricData_t *fabricp, char *name, Point *pPoint, uint8 find_flag) +{ + FSTATUS status; + + ASSERT(! PointValid(pPoint)); + if (0 == (find_flag & FIND_FLAG_FABRIC)) + return FINVALID_OPERATION; + if (find_flag & FIND_FLAG_FABRIC) { + cl_map_item_t *p; + for (p=cl_qmap_head(&fabricp->AllIOCs); p != cl_qmap_end(&fabricp->AllIOCs); p = cl_qmap_next(p)) { + IocData *iocp = PARENT_STRUCT(p, IocData, AllIOCsEntry); + + if (strncmp((char*)iocp->IocProfile.IDString, name, IOC_IDSTRING_SIZE) == 0) + { + status = PointListAppend(pPoint, POINT_TYPE_IOC_LIST, iocp); + if (FSUCCESS != status) + return status; + } + } + } + + // N/A for FIND_FLAG_ENODE, FIND_FLAG_ESM and FIND_FLAG_ELINK + + if (! PointValid(pPoint)) { + fprintf(stderr, "%s: IOC name Not Found: %s\n", g_Top_cmdname, name); + return FNOT_FOUND; + } + PointCompress(pPoint); + return FSUCCESS; +} + +#ifndef __VXWORKS__ +// search for the Ioc corresponding to the given ioc name pattern +// FNOT_FOUND - no instances found +// FINVALID_OPERATION - find_flag contains no applicable searches +// other - error allocating memory or initializing structures +FSTATUS FindIocNamePatPoint(FabricData_t *fabricp, char *pattern, Point *pPoint, uint8 find_flag) +{ + FSTATUS status; + + ASSERT(! PointValid(pPoint)); + if (0 == (find_flag & FIND_FLAG_FABRIC)) + return FINVALID_OPERATION; + if (find_flag & FIND_FLAG_FABRIC) { + cl_map_item_t *p; + for (p=cl_qmap_head(&fabricp->AllIOCs); p != cl_qmap_end(&fabricp->AllIOCs); p = cl_qmap_next(p)) { + IocData *iocp = PARENT_STRUCT(p, IocData, AllIOCsEntry); + char Name[IOC_IDSTRING_SIZE+1]; + + strncpy(Name, (char*)iocp->IocProfile.IDString, IOC_IDSTRING_SIZE); + Name[IOC_IDSTRING_SIZE] = '\0'; + if (fnmatch(pattern, Name, 0) == 0) + { + status = PointListAppend(pPoint, POINT_TYPE_IOC_LIST, iocp); + if (FSUCCESS != status) + return status; + } + } + } + + // N/A for FIND_FLAG_ENODE, FIND_FLAG_ESM and FIND_FLAG_ELINK + + if (! PointValid(pPoint)) { + fprintf(stderr, "%s: IOC name pattern Not Found: %s\n", + g_Top_cmdname, pattern); + return FNOT_FOUND; + } + PointCompress(pPoint); + return FSUCCESS; +} +#endif + +/** + * Determine IocType of an IocData object + * @param iocp IocData profile data to determine type from + * @return The IocType of this IOC + */ +IocType GetIocType(IocData *iocp) +{ + if ((iocp->IocProfile.IOClass == 0xff00 + || iocp->IocProfile.IOClass == 0x0100) + && iocp->IocProfile.IOSubClass == 0x609e + && iocp->IocProfile.Protocol == 0x108 + && iocp->IocProfile.ProtocolVer == 1) + { + return IOC_TYPE_SRP; + } + //add cases for new IocTypes here + + return IOC_TYPE_OTHER; +} + +const char * GetIocTypeName(IocType type) +{ + switch(type){ + case IOC_TYPE_SRP: + return "SRP"; + break; + case IOC_TYPE_OTHER: + return "OTHER"; + break; + default: + return ""; + break; + } +} + +// search for the Ioc corresponding to the given ioc type +// FNOT_FOUND - no instances found +// FINVALID_OPERATION - find_flag contains no applicable searches +// other - error allocating memory or initializing structures +FSTATUS FindIocTypePoint(FabricData_t *fabricp, IocType type, Point *pPoint, uint8 find_flag) +{ + FSTATUS status; + + ASSERT(! PointValid(pPoint)); + if (0 == (find_flag & FIND_FLAG_FABRIC)) + return FINVALID_OPERATION; + if (find_flag & FIND_FLAG_FABRIC) { + cl_map_item_t *p; + for (p=cl_qmap_head(&fabricp->AllIOCs); p != cl_qmap_end(&fabricp->AllIOCs); p = cl_qmap_next(p)) { + IocData *iocp = PARENT_STRUCT(p, IocData, AllIOCsEntry); + if (type == GetIocType(iocp)) + { + status = PointListAppend(pPoint, POINT_TYPE_IOC_LIST, iocp); + if (FSUCCESS != status) + return status; + } + } + } + + // N/A for FIND_FLAG_ENODE, FIND_FLAG_ESM and FIND_FLAG_ELINK + + if (! PointValid(pPoint)) { + fprintf(stderr, "%s: IOC type Not Found: %s\n", + g_Top_cmdname, GetIocTypeName(type)); + return FNOT_FOUND; + } + PointCompress(pPoint); + return FSUCCESS; +} + +static int CompareGuid(const cl_map_item_t *p_item, const uint64 key) +{ + IocData *iocp = PARENT_STRUCT(p_item, IocData, AllIOCsEntry); + if( key == iocp->IocProfile.IocGUID) { + return 0; + } else if(key < iocp->IocProfile.IocGUID) { + return 1; + } else { + return -1; + } + +} + +static cl_map_item_t *GetLowestIocGuid(cl_map_item_t *p, EUI64 guid, cl_qmap_t* IocMap) +{ + cl_map_item_t *returnItem = NULL; + while(p != cl_qmap_end(IocMap)) + { + IocData *iocp = PARENT_STRUCT(p, IocData, AllIOCsEntry); + if(iocp->IocProfile.IocGUID != guid) + break; + returnItem = p; + p = cl_qmap_prev(p); + } + return returnItem; +} + +static FSTATUS IocAppend(cl_map_item_t *p, EUI64 guid, Point *pPoint, cl_qmap_t* IocMap) +{ + FSTATUS status; + while(p != cl_qmap_end(IocMap)) { + IocData *iocp = PARENT_STRUCT(p, IocData, AllIOCsEntry); + if(iocp->IocProfile.IocGUID != guid) + break; + status = PointListAppend(pPoint, POINT_TYPE_IOC_LIST, iocp); + if (FSUCCESS != status) + return status; + p = cl_qmap_next(p); + } + if (! PointValid(pPoint)) { + return FNOT_FOUND; + } + PointCompress(pPoint); + return FSUCCESS; +} + +// search for the Ioc corresponding to the given Ioc Guid +FSTATUS FindIocGuid(FabricData_t *fabricp, EUI64 guid, Point *pPoint) +{ + FSTATUS status = FNOT_FOUND; + cl_map_item_t *p, *lowestItem; + p = cl_qmap_get_item_compare(&fabricp->AllIOCs, guid, CompareGuid); + if(p == cl_qmap_end(&fabricp->AllIOCs)) + return status; + lowestItem = GetLowestIocGuid(p, guid, &fabricp->AllIOCs); + if(lowestItem) + status = IocAppend(lowestItem, guid, pPoint, &fabricp->AllIOCs); + return status; + + +} +#endif + +// search for the SystemData corresponding to the given system image Guid +SystemData * FindSystemGuid(FabricData_t *fabricp, EUI64 guid) +{ + cl_map_item_t *mi; + + mi = cl_qmap_get(&fabricp->AllSystems, guid); + if (mi == cl_qmap_end(&fabricp->AllSystems)) + return NULL; + return PARENT_STRUCT(mi, SystemData, AllSystemsEntry); +} + +// search for the PortData corresponding to the given port rate +// FNOT_FOUND - no instances found +// FINVALID_OPERATION - find_flag contains no applicable searches +// other - error allocating memory or initializing structures +FSTATUS FindRatePoint(FabricData_t *fabricp, uint32 rate, Point *pPoint, uint8 find_flag) +{ + FSTATUS status; + + ASSERT(! PointValid(pPoint)); + ASSERT(rate); + if (0 == (find_flag & (FIND_FLAG_FABRIC|FIND_FLAG_ELINK))) + return FINVALID_OPERATION; + if (find_flag & FIND_FLAG_FABRIC) { + LIST_ITEM *p; + for (p=QListHead(&fabricp->AllPorts); p != NULL; p = QListNext(&fabricp->AllPorts, p)) { + PortData *portp = (PortData *)QListObj(p); + + /* omit switch port 0, rate is often odd */ + if (portp->PortNum == 0) + continue; + if (portp->rate == rate) { + status = PointListAppend(pPoint, POINT_TYPE_PORT_LIST, portp); + if (FSUCCESS != status) + return status; + } + } + } + + // N/A for FIND_FLAG_ENODE and FIND_FLAG_ESM + + if (find_flag & FIND_FLAG_ELINK) { + LIST_ITEM *p; + for (p=QListHead(&fabricp->ExpectedLinks); p != NULL; p = QListNext(&fabricp->ExpectedLinks, p)) { + ExpectedLink *elinkp = (ExpectedLink *)QListObj(p); + if (elinkp->expected_rate == rate) + { + status = PointElinkListAppend(pPoint, POINT_ELINK_TYPE_LINK_LIST, elinkp); + if (FSUCCESS != status) + return status; + } + } + } + if (! PointValid(pPoint)) { + fprintf(stderr, "%s: Rate Not Found: %s\n", + g_Top_cmdname, StlStaticRateToText(rate)); + return FNOT_FOUND; + } + PointCompress(pPoint); + return FSUCCESS; +} + + +// search for the PortData corresponding to the given LED state +// FNOT_FOUND - no instances found +// FINVALID_OPERATION - find_flag contains no applicable searches +// other - error allocating memory or initializing structures +FSTATUS FindLedStatePoint(FabricData_t *fabricp, uint8 state, Point *pPoint, uint8 find_flag) +{ + FSTATUS status; + + ASSERT(! PointValid(pPoint)); + if (0 == (find_flag & FIND_FLAG_FABRIC)) + return FINVALID_OPERATION; + if (find_flag & FIND_FLAG_FABRIC) { + LIST_ITEM *p; + for (p=QListHead(&fabricp->AllPorts); p != NULL; p = QListNext(&fabricp->AllPorts, p)) { + PortData *portp = (PortData *)QListObj(p); + + if ( (state == 1 && + portp->PortInfo.PortStates.s.LEDEnabled == 1 ) + || (state == 0 && + portp->PortInfo.PortStates.s.LEDEnabled == 0 ) ) { + status = PointListAppend(pPoint, POINT_TYPE_PORT_LIST, portp); + if (FSUCCESS != status) + return status; + } + } + } + + // N/A for FIND_FLAG_ENODE, FIND_FLAG_ESM and FIND_FLAG_ELINK + + if (! PointValid(pPoint)) { + fprintf(stderr, "%s: LED State Not Found: %d\n", + g_Top_cmdname, + state); + return FNOT_FOUND; + } + PointCompress(pPoint); + return FSUCCESS; +} + +// search for the PortData corresponding to the given port state +// FNOT_FOUND - no instances found +// FINVALID_OPERATION - find_flag contains no applicable searches +// other - error allocating memory or initializing structures +FSTATUS FindPortStatePoint(FabricData_t *fabricp, uint8 state, Point *pPoint, uint8 find_flag) +{ + FSTATUS status; + + ASSERT(! PointValid(pPoint)); + if (0 == (find_flag & FIND_FLAG_FABRIC)) + return FINVALID_OPERATION; + if (find_flag & FIND_FLAG_FABRIC) { + LIST_ITEM *p; + for (p=QListHead(&fabricp->AllPorts); p != NULL; p = QListNext(&fabricp->AllPorts, p)) { + PortData *portp = (PortData *)QListObj(p); + + ///* omit switch port 0, state can be odd */ + //if (portp->PortNum == 0) + // continue; + if ((state == PORT_STATE_SEARCH_NOTACTIVE + && portp->PortInfo.PortStates.s.PortState != IB_PORT_ACTIVE) + || (state == PORT_STATE_SEARCH_INITARMED + && (portp->PortInfo.PortStates.s.PortState == IB_PORT_INIT + || portp->PortInfo.PortStates.s.PortState == IB_PORT_ARMED)) + || (portp->PortInfo.PortStates.s.PortState == state)) { + status = PointListAppend(pPoint, POINT_TYPE_PORT_LIST, portp); + if (FSUCCESS != status) + return status; + } + } + } + + // N/A for FIND_FLAG_ENODE, FIND_FLAG_ESM and FIND_FLAG_ELINK + + if (! PointValid(pPoint)) { + fprintf(stderr, "%s: Port State Not Found: %s\n", + g_Top_cmdname, + (state==PORT_STATE_SEARCH_NOTACTIVE)?"Not Active": + (state==PORT_STATE_SEARCH_INITARMED)?"Init Armed": + StlPortStateToText(state)); + return FNOT_FOUND; + } + PointCompress(pPoint); + return FSUCCESS; +} + +// search for the PortData corresponding to the given port phys state +// FNOT_FOUND - no instances found +// FINVALID_OPERATION - find_flag contains no applicable searches +// other - error allocating memory or initializing structures +FSTATUS FindPortPhysStatePoint(FabricData_t *fabricp, IB_PORT_PHYS_STATE physstate, Point *pPoint, uint8 find_flag) +{ + FSTATUS status; + + ASSERT(! PointValid(pPoint)); + if (0 == (find_flag & FIND_FLAG_FABRIC)) + return FINVALID_OPERATION; + if (find_flag & FIND_FLAG_FABRIC) { + LIST_ITEM *p; + for (p=QListHead(&fabricp->AllPorts); p != NULL; p = QListNext(&fabricp->AllPorts, p)) { + PortData *portp = (PortData *)QListObj(p); + + ///* omit switch port 0, state can be odd */ + //if (portp->PortNum == 0) + // continue; + if (portp->PortInfo.PortStates.s.PortPhysicalState == physstate) { + status = PointListAppend(pPoint, POINT_TYPE_PORT_LIST, portp); + if (FSUCCESS != status) + return status; + } + } + } + + // N/A for FIND_FLAG_ENODE, FIND_FLAG_ESM and FIND_FLAG_ELINK + + if (! PointValid(pPoint)) { + fprintf(stderr, "%s: Port Phys State Not Found: %s\n", + g_Top_cmdname, StlPortPhysStateToText(physstate)); + return FNOT_FOUND; + } + PointCompress(pPoint); + return FSUCCESS; +} + +#ifndef __VXWORKS__ +// search for ports whose ExpectedLink has the given cable label +// FNOT_FOUND - no instances found +// FINVALID_OPERATION - find_flag contains no applicable searches +// other - error allocating memory or initializing structures +FSTATUS FindCableLabelPatPoint(FabricData_t *fabricp, const char* pattern, Point *pPoint, uint8 find_flag) +{ + FSTATUS status; + + ASSERT(! PointValid(pPoint)); + if (0 == (find_flag & (FIND_FLAG_FABRIC|FIND_FLAG_ELINK))) + return FINVALID_OPERATION; + if (find_flag & FIND_FLAG_FABRIC) { + LIST_ITEM *p; + for (p=QListHead(&fabricp->AllPorts); p != NULL; p = QListNext(&fabricp->AllPorts, p)) { + PortData *portp = (PortData *)QListObj(p); + + if (! portp->elinkp || ! portp->elinkp->CableData.label) + continue; // no cable information + if (fnmatch(pattern, portp->elinkp->CableData.label, 0) == 0) + { + status = PointListAppend(pPoint, POINT_TYPE_PORT_LIST, portp); + if (FSUCCESS != status) + return status; + } + } + } + + // N/A for FIND_FLAG_ENODE and FIND_FLAG_ESM + if (find_flag & FIND_FLAG_ELINK) { + LIST_ITEM *p; + for (p=QListHead(&fabricp->ExpectedLinks); p != NULL; p = QListNext(&fabricp->ExpectedLinks, p)) { + ExpectedLink *elinkp = (ExpectedLink *)QListObj(p); + if (! elinkp->CableData.label) + continue; // no cable information + if (fnmatch(pattern, elinkp->CableData.label, 0) == 0) + { + status = PointElinkListAppend(pPoint, POINT_ELINK_TYPE_LINK_LIST, elinkp); + if (FSUCCESS != status) + return status; + } + } + } + + if (! PointValid(pPoint)) { + fprintf(stderr, "%s: Cable Label Not Found: %s\n", + g_Top_cmdname, pattern); + return FNOT_FOUND; + } + PointCompress(pPoint); + return FSUCCESS; +} + +// search for ports whose ExpectedLink has the given cable length +// FNOT_FOUND - no instances found +// FINVALID_OPERATION - find_flag contains no applicable searches +// other - error allocating memory or initializing structures +FSTATUS FindCableLenPatPoint(FabricData_t *fabricp, const char* pattern, Point *pPoint, uint8 find_flag) +{ + FSTATUS status; + + ASSERT(! PointValid(pPoint)); + if (0 == (find_flag & (FIND_FLAG_FABRIC|FIND_FLAG_ELINK))) + return FINVALID_OPERATION; + if (find_flag & FIND_FLAG_FABRIC) { + LIST_ITEM *p; + for (p=QListHead(&fabricp->AllPorts); p != NULL; p = QListNext(&fabricp->AllPorts, p)) { + PortData *portp = (PortData *)QListObj(p); + + if (! portp->elinkp || ! portp->elinkp->CableData.length) + continue; // no cable information + if (fnmatch(pattern, portp->elinkp->CableData.length, 0) == 0) + { + status = PointListAppend(pPoint, POINT_TYPE_PORT_LIST, portp); + if (FSUCCESS != status) + return status; + } + } + } + + // N/A for FIND_FLAG_ENODE and FIND_FLAG_ESM + + if (find_flag & FIND_FLAG_ELINK) { + LIST_ITEM *p; + for (p=QListHead(&fabricp->ExpectedLinks); p != NULL; p = QListNext(&fabricp->ExpectedLinks, p)) { + ExpectedLink *elinkp = (ExpectedLink *)QListObj(p); + if (! elinkp->CableData.length) + continue; // no cable information + if (fnmatch(pattern, elinkp->CableData.length, 0) == 0) + { + status = PointElinkListAppend(pPoint, POINT_ELINK_TYPE_LINK_LIST, elinkp); + if (FSUCCESS != status) + return status; + } + } + } + if (! PointValid(pPoint)) { + fprintf(stderr, "%s: Cable Length Not Found: %s\n", + g_Top_cmdname, pattern); + return FNOT_FOUND; + } + PointCompress(pPoint); + return FSUCCESS; +} + +// search for ports whose ExpectedLink has the given cable details +// FNOT_FOUND - no instances found +// FINVALID_OPERATION - find_flag contains no applicable searches +// other - error allocating memory or initializing structures +FSTATUS FindCableDetailsPatPoint(FabricData_t *fabricp, const char* pattern, Point *pPoint, uint8 find_flag) +{ + FSTATUS status; + + ASSERT(! PointValid(pPoint)); + if (0 == (find_flag & (FIND_FLAG_FABRIC|FIND_FLAG_ELINK))) + return FINVALID_OPERATION; + if (find_flag & FIND_FLAG_FABRIC) { + LIST_ITEM *p; + for (p=QListHead(&fabricp->AllPorts); p != NULL; p = QListNext(&fabricp->AllPorts, p)) { + PortData *portp = (PortData *)QListObj(p); + + if (portp->elinkp && portp->elinkp->CableData.details + && fnmatch(pattern, portp->elinkp->CableData.details, 0) == 0) + { + status = PointListAppend(pPoint, POINT_TYPE_PORT_LIST, portp); + if (FSUCCESS != status) + return status; + } + } + } + + // N/A for FIND_FLAG_ENODE and FIND_FLAG_ESM + + if (find_flag & FIND_FLAG_ELINK) { + LIST_ITEM *p; + for (p=QListHead(&fabricp->ExpectedLinks); p != NULL; p = QListNext(&fabricp->ExpectedLinks, p)) { + ExpectedLink *elinkp = (ExpectedLink *)QListObj(p); + if (elinkp->CableData.details + && fnmatch(pattern, elinkp->CableData.details, 0) == 0) + { + status = PointElinkListAppend(pPoint, POINT_ELINK_TYPE_LINK_LIST, elinkp); + if (FSUCCESS != status) + return status; + } + } + } + if (! PointValid(pPoint)) { + fprintf(stderr, "%s: Cable Details Not Found: %s\n", + g_Top_cmdname, pattern); + return FNOT_FOUND; + } + PointCompress(pPoint); + return FSUCCESS; +} + +// search for ports whose CABLE_INFO has the given length +// FNOT_FOUND - no instances found +// FINVALID_OPERATION - find_flag contains no applicable searches +// other - error allocating memory or initializing structures +FSTATUS FindCabinfLenPatPoint(FabricData_t *fabricp, const char* pattern, Point *pPoint, uint8 find_flag) +{ + FSTATUS status; + char *cur, scrubbed_pat[strlen(pattern) + 1]; + char cablen_str[10] = {0}; // strlen("255") + 1 = 4 + int cableInfoHighPageAddressOffset; + + ASSERT(! PointValid(pPoint)); + if (0 == (find_flag & FIND_FLAG_FABRIC)) + return FINVALID_OPERATION; + + // User may suffix pattern with 'm'. Scrub it as to not intefere with later calls + // to fnmatch(). + snprintf(scrubbed_pat, sizeof(scrubbed_pat), "%s", pattern); + if (NULL != (cur = strchr(scrubbed_pat, 'm'))) + *cur = '\0'; + + if (find_flag & FIND_FLAG_FABRIC) { + LIST_ITEM *p; + //For CableHealth Report the Low Addr page and High address page are accessed, so got to specify the offset. + if(fabricp->flags & FF_CABLELOWPAGE) + cableInfoHighPageAddressOffset = STL_CIB_STD_HIGH_PAGE_ADDR; + else + cableInfoHighPageAddressOffset = 0; + + for (p=QListHead(&fabricp->AllPorts); p != NULL; p = QListNext(&fabricp->AllPorts, p)) { + PortData *portp = (PortData *)QListObj(p); + STL_CABLE_INFO_STD *pCableInfo; + STL_CABLE_INFO_UP0_DD *pCableInfoDD; + CableTypeInfoType cableTypeInfo; + boolean qsfp_dd; + boolean cableLenValid; + + if (!portp->pCableInfoData) + continue; + + pCableInfo = (STL_CABLE_INFO_STD *)(portp->pCableInfoData + cableInfoHighPageAddressOffset); + pCableInfoDD = (STL_CABLE_INFO_UP0_DD *)(portp->pCableInfoData + cableInfoHighPageAddressOffset); + qsfp_dd = (portp->pCableInfoData[0] == STL_CIB_STD_QSFP_DD); + + if (!qsfp_dd) { + StlCableInfoDecodeCableType(pCableInfo->dev_tech.s.xmit_tech, pCableInfo->connector, pCableInfo->ident, &cableTypeInfo); + cableLenValid = cableTypeInfo.cableLengthValid; + + StlCableInfoOM4LengthToText(pCableInfo->len_om4, cableLenValid, sizeof(cablen_str), cablen_str); + if (NULL != (cur = strchr(cablen_str, 'm'))) + *cur = '\0'; + if (fnmatch(scrubbed_pat, cablen_str, 0) != 0) + continue; + + status = PointListAppend(pPoint, POINT_TYPE_PORT_LIST, portp); + if (FSUCCESS != status) + return status; + } else { + StlCableInfoDecodeCableType(pCableInfoDD->cable_type, pCableInfoDD->connector, pCableInfoDD->ident, &cableTypeInfo); + cableLenValid = cableTypeInfo.cableLengthValid; + + StlCableInfoDDCableLengthToText(pCableInfoDD->cableLengthEnc, cableLenValid, sizeof(cablen_str), cablen_str); + if (NULL != (cur = strchr(cablen_str, 'm'))) + *cur = '\0'; + if (fnmatch(scrubbed_pat, cablen_str, 0) != 0) + continue; + + status = PointListAppend(pPoint, POINT_TYPE_PORT_LIST, portp); + if (FSUCCESS != status) + return status; + } + } + } + + // N/A for FIND_FLAG_ENODE, FIND_FLAG_ESM and FIND_FLAG_ELINK + if (! PointValid(pPoint)) { + fprintf(stderr, "%s: CABLE_INFO length Not Found: %s\n", + g_Top_cmdname, pattern); + return FNOT_FOUND; + } + + PointCompress(pPoint); + return FSUCCESS; + +} // End of FindCabinfLenPatPoint() + +// search for ports whose CABLE_INFO has the given vendor name +// FNOT_FOUND - no instances found +// FINVALID_OPERATION - find_flag contains no applicable searches +// other - error allocating memory or initializing structures +FSTATUS FindCabinfVendNamePatPoint(FabricData_t *fabricp, const char* pattern, Point *pPoint, uint8 find_flag) +{ + FSTATUS status; + uint32 len_pattern; + STL_CABLE_INFO_STD *pCableInfo; + STL_CABLE_INFO_UP0_DD *pCableInfoDD; + char bf_pattern[sizeof(pCableInfo->vendor_name) + 1]; + boolean qsfp_dd; + int cableInfoHighPageAddressOffset; + + ASSERT(! PointValid(pPoint)); + if (0 == (find_flag & FIND_FLAG_FABRIC)) + return FINVALID_OPERATION; + len_pattern = strnlen(pattern, sizeof(pCableInfo->vendor_name)); + memset (bf_pattern, ' ', sizeof(bf_pattern)); + memcpy (bf_pattern, pattern, len_pattern); + if (! len_pattern || (bf_pattern[len_pattern-1] != ' ' && bf_pattern[len_pattern-1] != '*')) + bf_pattern[sizeof(pCableInfo->vendor_name)] = '\0'; + else + bf_pattern[len_pattern] = '\0'; + + if (find_flag & FIND_FLAG_FABRIC) { + LIST_ITEM *p; + //For CableHealth Report the Low Addr page and High address page are accessed, so got to specify the offset. + if(fabricp->flags & FF_CABLELOWPAGE) + cableInfoHighPageAddressOffset = STL_CIB_STD_HIGH_PAGE_ADDR; + else + cableInfoHighPageAddressOffset = 0; + + for (p=QListHead(&fabricp->AllPorts); p != NULL; p = QListNext(&fabricp->AllPorts, p)) { + PortData *portp = (PortData *)QListObj(p); + char tempStr[sizeof(pCableInfo->vendor_name) + 1]; + + if (!portp->pCableInfoData) + continue; + + pCableInfo = (STL_CABLE_INFO_STD *)(portp->pCableInfoData + cableInfoHighPageAddressOffset); + pCableInfoDD = (STL_CABLE_INFO_UP0_DD *)(portp->pCableInfoData + cableInfoHighPageAddressOffset); + qsfp_dd = (portp->pCableInfoData[0] == STL_CIB_STD_QSFP_DD); + if (!qsfp_dd) { + memcpy(tempStr, pCableInfo->vendor_name, sizeof(pCableInfo->vendor_name)); + tempStr[sizeof(pCableInfo->vendor_name)] = '\0'; + } else { + memcpy(tempStr, pCableInfoDD->vendor_name, sizeof(pCableInfoDD->vendor_name)); + tempStr[sizeof(pCableInfoDD->vendor_name)] = '\0'; + } + if (fnmatch(bf_pattern, (const char *)tempStr, 0) == 0) + { + status = PointListAppend(pPoint, POINT_TYPE_PORT_LIST, portp); + if (FSUCCESS != status) + return status; + } + } + } + + // N/A for FIND_FLAG_ENODE, FIND_FLAG_ESM and FIND_FLAG_ELINK + + if (! PointValid(pPoint)) { + fprintf(stderr, "%s: CABLE_INFO vendor name Not Found: %s\n", + g_Top_cmdname, pattern); + return FNOT_FOUND; + } + PointCompress(pPoint); + return FSUCCESS; + +} // End of FindCabinfVendNamePatPoint() + +// search for ports whose CABLE_INFO has the given vendor part number +// FNOT_FOUND - no instances found +// FINVALID_OPERATION - find_flag contains no applicable searches +// other - error allocating memory or initializing structures +FSTATUS FindCabinfVendPNPatPoint(FabricData_t *fabricp, const char* pattern, Point *pPoint, uint8 find_flag) +{ + FSTATUS status; + uint32 len_pattern; + STL_CABLE_INFO_STD *pCableInfo; + STL_CABLE_INFO_UP0_DD *pCableInfoDD; + char bf_pattern[sizeof(pCableInfo->vendor_pn) + 1]; + boolean qsfp_dd; + int cableInfoHighPageAddressOffset; + + ASSERT(! PointValid(pPoint)); + if (0 == (find_flag & FIND_FLAG_FABRIC)) + return FINVALID_OPERATION; + len_pattern = strnlen(pattern, sizeof(pCableInfo->vendor_pn)); + memset (bf_pattern, ' ', sizeof(bf_pattern)); + memcpy (bf_pattern, pattern, len_pattern); + if (! len_pattern || (bf_pattern[len_pattern-1] != ' ' && bf_pattern[len_pattern-1] != '*')) + bf_pattern[sizeof(pCableInfo->vendor_pn)] = '\0'; + else + bf_pattern[len_pattern] = '\0'; + + if (find_flag & FIND_FLAG_FABRIC) { + LIST_ITEM *p; + //For CableHealth Report the Low Addr page and High address page are accessed, so got to specify the offset. + if(fabricp->flags & FF_CABLELOWPAGE) + cableInfoHighPageAddressOffset = STL_CIB_STD_HIGH_PAGE_ADDR; + else + cableInfoHighPageAddressOffset = 0; + + for (p=QListHead(&fabricp->AllPorts); p != NULL; p = QListNext(&fabricp->AllPorts, p)) { + PortData *portp = (PortData *)QListObj(p); + char tempStr[sizeof(pCableInfo->vendor_pn) + 1]; + + if (!portp->pCableInfoData) + continue; + + pCableInfo = (STL_CABLE_INFO_STD *)(portp->pCableInfoData + cableInfoHighPageAddressOffset); + pCableInfoDD = (STL_CABLE_INFO_UP0_DD *)(portp->pCableInfoData + cableInfoHighPageAddressOffset); + qsfp_dd = (portp->pCableInfoData[0] == STL_CIB_STD_QSFP_DD); + if (!qsfp_dd) { + memcpy(tempStr, pCableInfo->vendor_pn, sizeof(pCableInfo->vendor_pn)); + tempStr[sizeof(pCableInfo->vendor_pn)] = '\0'; + } else { + memcpy(tempStr, pCableInfoDD->vendor_pn, sizeof(pCableInfoDD->vendor_pn)); + tempStr[sizeof(pCableInfoDD->vendor_pn)] = '\0'; + } + if (fnmatch(bf_pattern, (const char *)tempStr, 0) == 0) + { + status = PointListAppend(pPoint, POINT_TYPE_PORT_LIST, portp); + if (FSUCCESS != status) + return status; + } + } + } + + // N/A for FIND_FLAG_ENODE, FIND_FLAG_ESM and FIND_FLAG_ELINK + + if (! PointValid(pPoint)) { + fprintf(stderr, "%s: CABLE_INFO vendor PN Not Found: %s\n", + g_Top_cmdname, pattern); + return FNOT_FOUND; + } + PointCompress(pPoint); + return FSUCCESS; + +} // End of FindCabinfVendPNPatPoint() + +// search for ports whose CABLE_INFO has the given vendor rev +// FNOT_FOUND - no instances found +// FINVALID_OPERATION - find_flag contains no applicable searches +// other - error allocating memory or initializing structures +FSTATUS FindCabinfVendRevPatPoint(FabricData_t *fabricp, const char* pattern, Point *pPoint, uint8 find_flag) +{ + FSTATUS status; + uint32 len_pattern; + STL_CABLE_INFO_STD *pCableInfo; + STL_CABLE_INFO_UP0_DD *pCableInfoDD; + char bf_pattern[sizeof(pCableInfo->vendor_rev) + 1]; + boolean qsfp_dd; + int cableInfoHighPageAddressOffset; + + ASSERT(! PointValid(pPoint)); + if (0 == (find_flag & FIND_FLAG_FABRIC)) + return FINVALID_OPERATION; + len_pattern = strnlen(pattern, sizeof(pCableInfo->vendor_rev)); + memset (bf_pattern, ' ', sizeof(bf_pattern)); + memcpy (bf_pattern, pattern, len_pattern); + if (! len_pattern || (bf_pattern[len_pattern-1] != ' ' && bf_pattern[len_pattern-1] != '*')) + bf_pattern[sizeof(pCableInfo->vendor_rev)] = '\0'; + else + bf_pattern[len_pattern] = '\0'; + + if (find_flag & FIND_FLAG_FABRIC) { + LIST_ITEM *p; + //For CableHealth Report the Low Addr page and High address page are accessed, so got to specify the offset. + if(fabricp->flags & FF_CABLELOWPAGE) + cableInfoHighPageAddressOffset = STL_CIB_STD_HIGH_PAGE_ADDR; + else + cableInfoHighPageAddressOffset = 0; + + for (p=QListHead(&fabricp->AllPorts); p != NULL; p = QListNext(&fabricp->AllPorts, p)) { + PortData *portp = (PortData *)QListObj(p); + char tempStr[sizeof(pCableInfo->vendor_rev) + 1]; + + if (!portp->pCableInfoData) + continue; + + pCableInfo = (STL_CABLE_INFO_STD *)(portp->pCableInfoData + cableInfoHighPageAddressOffset); + pCableInfoDD = (STL_CABLE_INFO_UP0_DD *)(portp->pCableInfoData + cableInfoHighPageAddressOffset); + qsfp_dd = (portp->pCableInfoData[0] == STL_CIB_STD_QSFP_DD); + if (!qsfp_dd) { + memcpy(tempStr, pCableInfo->vendor_rev, sizeof(pCableInfo->vendor_rev)); + tempStr[sizeof(pCableInfo->vendor_rev)] = '\0'; + } else { + memcpy(tempStr, pCableInfoDD->vendor_rev, sizeof(pCableInfoDD->vendor_rev)); + tempStr[sizeof(pCableInfoDD->vendor_rev)] = '\0'; + } + if (fnmatch(bf_pattern, (const char *)tempStr, 0) == 0) + { + status = PointListAppend(pPoint, POINT_TYPE_PORT_LIST, portp); + if (FSUCCESS != status) + return status; + } + } + } + + // N/A for FIND_FLAG_ENODE, FIND_FLAG_ESM and FIND_FLAG_ELINK + + if (! PointValid(pPoint)) { + fprintf(stderr, "%s: CABLE_INFO vendor rev Not Found: %s\n", + g_Top_cmdname, pattern); + return FNOT_FOUND; + } + PointCompress(pPoint); + return FSUCCESS; + +} // End of FindCabinfVendRevPatPoint() + +// search for ports whose CABLE_INFO has the given vendor serial number +// FNOT_FOUND - no instances found +// FINVALID_OPERATION - find_flag contains no applicable searches +// other - error allocating memory or initializing structures +FSTATUS FindCabinfVendSNPatPoint(FabricData_t *fabricp, const char* pattern, Point *pPoint, uint8 find_flag) +{ + FSTATUS status; + uint32 len_pattern; + STL_CABLE_INFO_STD *pCableInfo; + STL_CABLE_INFO_UP0_DD *pCableInfoDD; + char bf_pattern[sizeof(pCableInfo->vendor_sn) + 1]; + boolean qsfp_dd; + int cableInfoHighPageAddressOffset; + + ASSERT(! PointValid(pPoint)); + if (0 == (find_flag & FIND_FLAG_FABRIC)) + return FINVALID_OPERATION; + len_pattern = strnlen(pattern, sizeof(pCableInfo->vendor_sn)); + memset (bf_pattern, ' ', sizeof(bf_pattern)); + memcpy (bf_pattern, pattern, len_pattern); + if (! len_pattern || (bf_pattern[len_pattern-1] != ' ' && bf_pattern[len_pattern-1] != '*')) + bf_pattern[sizeof(pCableInfo->vendor_sn)] = '\0'; + else + bf_pattern[len_pattern] = '\0'; + + if (find_flag & FIND_FLAG_FABRIC) { + LIST_ITEM *p; + //For CableHealth Report the Low Addr page and High address page are accessed, so got to specify the offset. + if(fabricp->flags & FF_CABLELOWPAGE) + cableInfoHighPageAddressOffset = STL_CIB_STD_HIGH_PAGE_ADDR; + else + cableInfoHighPageAddressOffset = 0; + + for (p=QListHead(&fabricp->AllPorts); p != NULL; p = QListNext(&fabricp->AllPorts, p)) { + PortData *portp = (PortData *)QListObj(p); + char tempStr[sizeof(pCableInfo->vendor_sn) + 1]; + + if (!portp->pCableInfoData) + continue; + + pCableInfo = (STL_CABLE_INFO_STD *)(portp->pCableInfoData + cableInfoHighPageAddressOffset); + pCableInfoDD = (STL_CABLE_INFO_UP0_DD *)(portp->pCableInfoData + cableInfoHighPageAddressOffset); + qsfp_dd = (portp->pCableInfoData[0] == STL_CIB_STD_QSFP_DD); + if (!qsfp_dd) { + memcpy(tempStr, pCableInfo->vendor_sn, sizeof(pCableInfo->vendor_sn)); + tempStr[sizeof(pCableInfo->vendor_sn)] = '\0'; + } else { + memcpy(tempStr, pCableInfoDD->vendor_sn, sizeof(pCableInfoDD->vendor_sn)); + tempStr[sizeof(pCableInfoDD->vendor_sn)] = '\0'; + } + if (fnmatch(bf_pattern, (const char *)tempStr, 0) == 0) + { + status = PointListAppend(pPoint, POINT_TYPE_PORT_LIST, portp); + if (FSUCCESS != status) + return status; + } + } + } + + // N/A for FIND_FLAG_ENODE, FIND_FLAG_ESM and FIND_FLAG_ELINK + + if (! PointValid(pPoint)) { + fprintf(stderr, "%s: CABLE_INFO vendor SN Not Found: %s\n", + g_Top_cmdname, pattern); + return FNOT_FOUND; + } + PointCompress(pPoint); + return FSUCCESS; + +} // End of FindCabinfVendSNPatPoint() + +// search for the PortData corresponding to the given cable type +// FNOT_FOUND - no instances found +// FINVALID_OPERATION - find_flag contains no applicable searches +// other - error allocating memory or initializing structures +FSTATUS FindCabinfCableTypePoint(FabricData_t *fabricp, char *pattern, Point *pPoint, uint8 find_flag) +{ + FSTATUS status; + int len; + int cableInfoHighPageAddressOffset; + + len = strlen(pattern); + + ASSERT(! PointValid(pPoint)); + if (0 == (find_flag & FIND_FLAG_FABRIC)) + return FINVALID_OPERATION; + if (find_flag & FIND_FLAG_FABRIC) { + LIST_ITEM *p; + //For CableHealth Report the Low Addr page and High address page are accessed, so got to specify the offset. + if(fabricp->flags & FF_CABLELOWPAGE) + cableInfoHighPageAddressOffset = STL_CIB_STD_HIGH_PAGE_ADDR; + else + cableInfoHighPageAddressOffset = 0; + + for (p=QListHead(&fabricp->AllPorts); p != NULL; p = QListNext(&fabricp->AllPorts, p)) { + PortData *portp = (PortData *)QListObj(p); + STL_CABLE_INFO_STD *pCableInfo; + STL_CABLE_INFO_UP0_DD *pCableInfoDD; + uint8 xmit_tech; + boolean qsfp_dd; + + /* omit switch port 0, no cable connected to port0 */ + if (portp->PortNum == 0) + continue; + + if (!portp->pCableInfoData) + continue; + + pCableInfo = (STL_CABLE_INFO_STD *)(portp->pCableInfoData + cableInfoHighPageAddressOffset); + pCableInfoDD = (STL_CABLE_INFO_UP0_DD *)(portp->pCableInfoData + cableInfoHighPageAddressOffset); + qsfp_dd = (portp->pCableInfoData[0] == STL_CIB_STD_QSFP_DD); + if (!qsfp_dd) + xmit_tech = pCableInfo->dev_tech.s.xmit_tech; + else + xmit_tech = pCableInfoDD->cable_type; + if (strncmp(pattern, "optical", len) == 0) // this includes AOL and Optical Transceiver + if (xmit_tech <= STL_CIB_STD_TXTECH_1490_DFB && (xmit_tech >= STL_CIB_STD_TXTECH_850_VCSEL) + && (xmit_tech != STL_CIB_STD_TXTECH_OTHER)) { + status = PointListAppend(pPoint, POINT_TYPE_PORT_LIST, portp); + if (FSUCCESS != status) + return status; + } + if (strncmp(pattern, "unknown", len) == 0) + if (xmit_tech == STL_CIB_STD_TXTECH_OTHER) { + status = PointListAppend(pPoint, POINT_TYPE_PORT_LIST, portp); + if (FSUCCESS != status) + return status; + } + if (strncmp(pattern, "passive_copper", len) == 0) + if (xmit_tech == STL_CIB_STD_TXTECH_CU_UNEQ || (xmit_tech == STL_CIB_STD_TXTECH_CU_PASSIVEQ)) { + status = PointListAppend(pPoint, POINT_TYPE_PORT_LIST, portp); + if (FSUCCESS != status) + return status; + } + if (strncmp(pattern, "active_copper", len) == 0) + if (xmit_tech <= STL_CIB_STD_TXTECH_CU_LINACTEQ && (xmit_tech >= STL_CIB_STD_TXTECH_CU_NFELIMACTEQ)) { + status = PointListAppend(pPoint, POINT_TYPE_PORT_LIST, portp); + if (FSUCCESS != status) + return status; + } + } + } + + // N/A for FIND_FLAG_ENODE, FIND_FLAG_ESM and FIND_FLAG_ELINK + + if (! PointValid(pPoint)) { + fprintf(stderr, "%s: CABLE_INFO: No %s cables found\n", + g_Top_cmdname, pattern); + return FNOT_FOUND; + } + PointCompress(pPoint); + return FSUCCESS; + +} // End of FindCabinfCableTypePoint() + +// search for ports whose ExpectedLink has the given link details +// FNOT_FOUND - no instances found +// FINVALID_OPERATION - find_flag contains no applicable searches +// other - error allocating memory or initializing structures +FSTATUS FindLinkDetailsPatPoint(FabricData_t *fabricp, const char* pattern, Point *pPoint, uint8 find_flag) +{ + FSTATUS status; + ASSERT(! PointValid(pPoint)); + if (0 == (find_flag & (FIND_FLAG_FABRIC|FIND_FLAG_ELINK))) + return FINVALID_OPERATION; + if (find_flag & FIND_FLAG_FABRIC) { + LIST_ITEM *p; + for (p=QListHead(&fabricp->AllPorts); p != NULL; p = QListNext(&fabricp->AllPorts, p)) { + PortData *portp = (PortData *)QListObj(p); + if (portp->elinkp && portp->elinkp->details + && fnmatch(pattern, portp->elinkp->details, 0) == 0) + { + status = PointListAppend(pPoint, POINT_TYPE_PORT_LIST, portp); + if (FSUCCESS != status) + return status; + } + } + } + + // N/A for FIND_FLAG_ENODE and FIND_FLAG_ESM + + if (find_flag & FIND_FLAG_ELINK) { + LIST_ITEM *p; + for (p=QListHead(&fabricp->ExpectedLinks); p != NULL; p = QListNext(&fabricp->ExpectedLinks, p)) { + ExpectedLink *elinkp = (ExpectedLink *)QListObj(p); + if (elinkp->details && fnmatch(pattern, elinkp->details, 0) == 0) + { + status = PointElinkListAppend(pPoint, POINT_ELINK_TYPE_LINK_LIST, elinkp); + if (FSUCCESS != status) + return status; + } + } + } + if (! PointValid(pPoint)) { + fprintf(stderr, "%s: Link Details Not Found: %s\n", + g_Top_cmdname, pattern); + return FNOT_FOUND; + } + PointCompress(pPoint); + return FSUCCESS; +} + +// search for ports whose ExpectedLink has the given port details +// FNOT_FOUND - no instances found +// FINVALID_OPERATION - find_flag contains no applicable searches +// other - error allocating memory or initializing structures +FSTATUS FindPortDetailsPatPoint(FabricData_t *fabricp, const char* pattern, Point *pPoint, uint8 find_flag) +{ + FSTATUS status; + + ASSERT(! PointValid(pPoint)); + if (0 == (find_flag & (FIND_FLAG_FABRIC|FIND_FLAG_ELINK))) + return FINVALID_OPERATION; + if (find_flag & FIND_FLAG_FABRIC) { + LIST_ITEM *p; + for (p=QListHead(&fabricp->AllPorts); p != NULL; p = QListNext(&fabricp->AllPorts, p)) { + PortData *portp = (PortData *)QListObj(p); + PortSelector *portselp = GetPortSelector(portp); + + if (portselp && portselp->details + && fnmatch(pattern, portselp->details, 0) == 0) + { + status = PointListAppend(pPoint, POINT_TYPE_PORT_LIST, portp); + if (FSUCCESS != status) + return status; + } + } + } + + // N/A for FIND_FLAG_ENODE and FIND_FLAG_ESM + + if (find_flag & FIND_FLAG_ELINK) { + LIST_ITEM *p; + for (p=QListHead(&fabricp->ExpectedLinks); p != NULL; p = QListNext(&fabricp->ExpectedLinks, p)) { + ExpectedLink *elinkp = (ExpectedLink *)QListObj(p); + if ((elinkp->portselp1 && elinkp->portselp1->details + && fnmatch(pattern, elinkp->portselp1->details, 0) == 0) + || (elinkp->portselp2 && elinkp->portselp2->details + && fnmatch(pattern, elinkp->portselp2->details, 0) == 0)) + { + status = PointElinkListAppend(pPoint, POINT_ELINK_TYPE_LINK_LIST, elinkp); + if (FSUCCESS != status) + return status; + } + } + } + if (! PointValid(pPoint)) { + fprintf(stderr, "%s: Port Details Not Found: %s\n", + g_Top_cmdname, pattern); + return FNOT_FOUND; + } + PointCompress(pPoint); + return FSUCCESS; +} +#endif + +// search for the PortData corresponding to the given port MTU capability +// FNOT_FOUND - no instances found +// FINVALID_OPERATION - find_flag contains no applicable searches +// other - error allocating memory or initializing structures +FSTATUS FindMtuPoint(FabricData_t *fabricp, IB_MTU mtu, Point *pPoint, uint8 find_flag) +{ + FSTATUS status; + + ASSERT(! PointValid(pPoint)); + ASSERT(mtu); + if (0 == (find_flag & (FIND_FLAG_FABRIC|FIND_FLAG_ELINK))) + return FINVALID_OPERATION; + if (find_flag & FIND_FLAG_FABRIC) { + LIST_ITEM *p; + for (p=QListHead(&fabricp->AllPorts); p != NULL; p = QListNext(&fabricp->AllPorts, p)) { + PortData *portp = (PortData *)QListObj(p); + + /* omit switch port 0, mtu is often odd */ + if (portp->PortNum == 0) + continue; + if(MIN(portp->PortInfo.MTU.Cap, portp->neighbor->PortInfo.MTU.Cap) == mtu){ + status = PointListAppend(pPoint, POINT_TYPE_PORT_LIST, portp); + if (FSUCCESS != status) + return status; + } + } + } + + // N/A for FIND_FLAG_ENODE and FIND_FLAG_ESM + + if (find_flag & FIND_FLAG_ELINK) { + LIST_ITEM *p; + for (p=QListHead(&fabricp->ExpectedLinks); p != NULL; p = QListNext(&fabricp->ExpectedLinks, p)) { + ExpectedLink *elinkp = (ExpectedLink *)QListObj(p); + if(elinkp->expected_mtu == mtu) + { + status = PointElinkListAppend(pPoint, POINT_ELINK_TYPE_LINK_LIST, elinkp); + if (FSUCCESS != status) + return status; + } + } + } + if (! PointValid(pPoint)) { + fprintf(stderr, "%s: MTU Not Found: %s\n", + g_Top_cmdname, IbMTUToText(mtu)); + return FNOT_FOUND; + } + PointCompress(pPoint); + return FSUCCESS; +} + +// search for the master SM (should be only 1, so we return 1st master found) +PortData * FindMasterSm(FabricData_t *fabricp) +{ + cl_map_item_t *p; + + for (p=cl_qmap_head(&fabricp->AllSMs); p != cl_qmap_end(&fabricp->AllSMs); p = cl_qmap_next(p)) { + SMData *smp = PARENT_STRUCT(p, SMData, AllSMsEntry); + if (smp->SMInfoRecord.SMInfo.u.s.SMStateCurrent == SM_MASTER) + return smp->portp; + } + return NULL; +} + +#ifndef __VXWORKS__ +// search for SMData whose ExpectedSM has the given SM details +// FNOT_FOUND - no instances found +// FINVALID_OPERATION - find_flag contains no applicable searches +// other - error allocating memory or initializing structures +FSTATUS FindSmDetailsPatPoint(FabricData_t *fabricp, const char* pattern, Point *pPoint, uint8 find_flag) +{ + FSTATUS status; + + ASSERT(! PointValid(pPoint)); + if (0 == (find_flag & (FIND_FLAG_FABRIC|FIND_FLAG_ESM))) + return FINVALID_OPERATION; + if (find_flag & FIND_FLAG_FABRIC) { + cl_map_item_t *p; + for (p=cl_qmap_head(&fabricp->AllSMs); p != cl_qmap_end(&fabricp->AllSMs); p = cl_qmap_next(p)) { + SMData *smp = PARENT_STRUCT(p, SMData, AllSMsEntry); + if (! smp->esmp || ! smp->esmp->details) + continue; // no SM details information + if (fnmatch(pattern, smp->esmp->details, 0) == 0) + { + status = PointListAppend(pPoint, POINT_TYPE_PORT_LIST, smp->portp); + if (FSUCCESS != status) + return status; + } + } + } + + // N/A for FIND_FLAG_ENODE + + if (find_flag & FIND_FLAG_ESM) { + LIST_ITEM *p; + for (p=QListHead(&fabricp->ExpectedSMs); p != NULL; p = QListNext(&fabricp->ExpectedSMs, p)) { + ExpectedSM *esmp = (ExpectedSM *)QListObj(p); + if (! esmp->details) + continue; // no SM details information + if (fnmatch(pattern, esmp->details, 0) == 0) + { + status = PointEsmListAppend(pPoint, POINT_ESM_TYPE_SM_LIST, esmp); + if (FSUCCESS != status) + return status; + } + } + } + + // N/A for FIND_FLAG_ELINK + + if (! PointValid(pPoint)) { + fprintf(stderr, "%s: SM Details Not Found: %s\n", + g_Top_cmdname, pattern); + return FNOT_FOUND; + } + PointCompress(pPoint); + return FSUCCESS; +} +#endif + +// search for the SMData corresponding to the given PortGuid +SMData * FindSMPort(FabricData_t *fabricp, EUI64 PortGUID) +{ + cl_map_item_t *mi; + + mi = cl_qmap_get(&fabricp->AllSMs, PortGUID); + if (mi == cl_qmap_end(&fabricp->AllSMs)) + return NULL; + return PARENT_STRUCT(mi, SMData, AllSMsEntry); +} + +// search for the PortData corresponding to the given lid and port number +// For FIs lid completely defines the port +// For Switches, lid will identify the switch and port is used to select port +PortData * FindLidPort(FabricData_t *fabricp, STL_LID lid, uint8 port) +{ + PortData *portp; + + portp = FindLid(fabricp, lid); + if (! portp) + return NULL; + /* lid is only valid for port 0 on switches + * ignore port for non-switches, in which case LID is all we need + */ + if (portp->PortNum == port + || portp->nodep->NodeInfo.NodeType != STL_NODE_SW) + return portp; + /* must be a port w/o a LID on a switch */ + return FindNodePort(portp->nodep, port); +} + +// search for the PortData corresponding to the given nodeguid and port number +PortData *FindNodeGuidPort(FabricData_t *fabricp, EUI64 nodeguid, uint8 port) +{ + NodeData *nodep = FindNodeGuid(fabricp, nodeguid); + if (! nodep) + return NULL; + return FindNodePort(nodep, port); +} + +// search ExpectedNodeGuidMap for GUID +// Search the ExpectedNodeGuidMap for an ExpectedNode with the given nodeGuid +// This will cover all ExpectedFIs and ExpectedSWs which have Guids specified. +ExpectedNode* FindExpectedNodeByNodeGuid(const FabricData_t *fabricp, EUI64 nodeGuid) +{ + cl_map_item_t *mi; + ExpectedNode *enodep; + + if(fabricp == NULL) + return NULL; + + mi = cl_qmap_get(&fabricp->ExpectedNodeGuidMap, nodeGuid); + if (mi == cl_qmap_end(&fabricp->ExpectedNodeGuidMap)) + return NULL; + + enodep = PARENT_STRUCT(mi, ExpectedNode, ExpectedNodeGuidMapEntry); + return enodep; +} + +// Search through the ExpectedFIs and ExpectedSWs for an ExpectedNode with the +// given node description +// NodeType is optional and may limit scope of search +ExpectedNode* FindExpectedNodeByNodeDesc(const FabricData_t* fabricp, const char* nodeDesc, uint8 NodeType) +{ + LIST_ITEM *p; + + if(fabricp == NULL) + return NULL; + + if (nodeDesc == NULL) + return NULL; + + // Since switches have multiple ports, when this is called as part of + // topology analysis or ExpectedLink analysis we have a better chance + // of finding switch, plus there are often less switches than FIs in a + // fabric, so we check switches first to improve performance on many use + // cases + + // First check through the switches + if(NodeType != STL_NODE_FI && QListHead(&fabricp->ExpectedSWs) != NULL) { + for(p = QListHead(&fabricp->ExpectedSWs); p != NULL; p = QListNext(&fabricp->ExpectedSWs, p)) { + ExpectedNode* enodep = PARENT_STRUCT(p, ExpectedNode, ExpectedNodesEntry); + + if (enodep->NodeDesc && 0 == strncmp(enodep->NodeDesc, + nodeDesc, STL_NODE_DESCRIPTION_ARRAY_SIZE)) + return enodep; + } + } + + // Check through FIs if it wasn't a switch + if(NodeType != STL_NODE_SW && QListHead(&fabricp->ExpectedFIs) != NULL) { + for(p = QListHead(&fabricp->ExpectedFIs); p != NULL; p = QListNext(&fabricp->ExpectedFIs, p)) { + ExpectedNode* enodep = PARENT_STRUCT(p, ExpectedNode, ExpectedNodesEntry); + + if (enodep->NodeDesc && 0 == strncmp(enodep->NodeDesc, + nodeDesc, STL_NODE_DESCRIPTION_ARRAY_SIZE)) + return enodep; + } + } + + return NULL; +} + +// Search for the ExpectedLink by one side of the link with nodeGuid & portNum. +// (OPTIONAL) Side is which portsel in the ExpectedLink that was the one given. +ExpectedLink* FindExpectedLinkByOneSide(const FabricData_t *fabricp, EUI64 nodeGuid, uint8 portNum, uint8* side) +{ + ExpectedLink *elinkp; + ExpectedNode *enodep = FindExpectedNodeByNodeGuid(fabricp, nodeGuid); + if(!enodep) + return NULL; + + if(portNum >= enodep->portsSize || enodep->ports[portNum] == NULL) { + return NULL; + } + elinkp = enodep->ports[portNum]->elinkp; + + if(!elinkp) + return NULL; + + if(elinkp->portselp1->NodeGUID == nodeGuid && elinkp->portselp1->PortNum == portNum) { + if(side) + *side = 1; + } else if (elinkp->portselp2->NodeGUID == nodeGuid && elinkp->portselp2->PortNum == portNum) { + if(side) + *side = 2; + } + + return elinkp; + +} + +// FNOT_FOUND - no instances found +// FINVALID_OPERATION - find_flag contains no applicable searches +// other - error allocating memory or initializing structures +FSTATUS FindLinkQualityPoint(FabricData_t *fabricp, uint16 quality, LinkQualityCompare comp, Point *pPoint, uint8 find_flag) +{ + FSTATUS status; + + ASSERT(! PointValid(pPoint)); + if (0 == (find_flag & FIND_FLAG_FABRIC)) + return FINVALID_OPERATION; + if (find_flag & FIND_FLAG_FABRIC) { + LIST_ITEM *p; + for (p=QListHead(&fabricp->AllPorts); p != NULL; p = QListNext(&fabricp->AllPorts, p)) { + PortData *portp = (PortData *)QListObj(p); + + boolean match = FALSE; + if (!portp->pPortCounters) + continue; + switch (comp) { + case QUAL_EQ: + match = (uint16)(portp->pPortCounters->lq.s.linkQualityIndicator) == quality; + break; + case QUAL_GE: + match = (uint16)(portp->pPortCounters->lq.s.linkQualityIndicator) >= quality; + break; + case QUAL_LE: + match = (uint16)(portp->pPortCounters->lq.s.linkQualityIndicator) <= quality; + break; + default: + break; + } + if (match) { + status = PointListAppend(pPoint, POINT_TYPE_PORT_LIST, portp); + if (FSUCCESS != status) + return status; + } + } + } + + // N/A for FIND_FLAG_ENODE, FIND_FLAG_ESM and FIND_FLAG_ELINK + + if (! PointValid(pPoint)) { + fprintf(stderr, "%s: Link Quality Not Found: %d\n", + g_Top_cmdname, quality); + return FNOT_FOUND; + } + PointCompress(pPoint); + return FSUCCESS; +} + +FSTATUS FindLinkDownReasonPoint(FabricData_t *fabricp, uint8 ldr, Point *pPoint, uint8 find_flag) +{ + FSTATUS status; + + ASSERT(PointIsInInit(pPoint)); + if (0 == (find_flag & FIND_FLAG_FABRIC)) + return FINVALID_OPERATION; + + if (find_flag & FIND_FLAG_FABRIC) { + LIST_ITEM *p; + for (p=QListHead(&fabricp->AllPorts); p != NULL; p = QListNext(&fabricp->AllPorts, p)) { + PortData *portp = (PortData *)QListObj(p); + + boolean match = FALSE; + int i; + if (fabricp->flags & FF_SMADIRECT) { // SMA only + match = ldr == IB_UINT8_MAX + ? portp->PortInfo.LinkDownReason != STL_LINKDOWN_REASON_NONE + : portp->PortInfo.LinkDownReason == ldr; + match |= ldr == IB_UINT8_MAX + ? portp->PortInfo.NeighborLinkDownReason != STL_LINKDOWN_REASON_NONE + : portp->PortInfo.NeighborLinkDownReason == ldr; + } else { // SA + for (i = 0; i < STL_NUM_LINKDOWN_REASONS; ++i) { + STL_LINKDOWN_REASON *ldrp = &portp->LinkDownReasons[i]; + if (ldrp->Timestamp != 0) { + match = ldr == IB_UINT8_MAX + ? ldrp->LinkDownReason != STL_LINKDOWN_REASON_NONE + : ldrp->LinkDownReason == ldr; + match |= ldr == IB_UINT8_MAX + ? ldrp->NeighborLinkDownReason != STL_LINKDOWN_REASON_NONE + : ldrp->NeighborLinkDownReason == ldr; + } + if (match) break; + } + } + if (match) { + status = PointListAppend(pPoint, POINT_TYPE_PORT_LIST, portp); + if (FSUCCESS != status) + return status; + } + } + } + if (! PointValid(pPoint)) { + fprintf(stderr, "%s: Link Down Reason Not Found: %d\n", g_Top_cmdname, ldr); + return FNOT_FOUND; + } + PointCompress(pPoint); + return FSUCCESS; +} + + +// Search through the ExpectedSMs for matching portGuid +// FNOT_FOUND - no instances found +// FINVALID_PARAMETER - input parameter not valid +// FSUCCESS - when a match is found +FSTATUS FindExpectedSMByPortGuid(FabricData_t *fabricp, EUI64 portGuid) { + LIST_ITEM *p; + + if(fabricp == NULL) + return FINVALID_PARAMETER; + + // check through the SMs + for(p = QListHead(&fabricp->ExpectedSMs); p != NULL; p = QListNext(&fabricp->ExpectedSMs, p)) { + ExpectedSM *esmp = (ExpectedSM *)QListObj(p); + if (esmp->PortGUID == portGuid) + return FSUCCESS; + } + return FNOT_FOUND; +} + +// Search through the ExpectedSMs for matching nodeGuid +// FNOT_FOUND - no instances found +// FINVALID_PARAMETER - input parameter not valid +// FSUCCESS - when a match is found +FSTATUS FindExpectedSMByNodeGuid(FabricData_t *fabricp, EUI64 nodeGuid) { + LIST_ITEM *p; + + if(fabricp == NULL) + return FINVALID_PARAMETER; + + // check through the SMs + for(p = QListHead(&fabricp->ExpectedSMs); p != NULL; p = QListNext(&fabricp->ExpectedSMs, p)) { + ExpectedSM *esmp = (ExpectedSM *)QListObj(p); + if (esmp->NodeGUID == nodeGuid) + return FSUCCESS; + } + return FNOT_FOUND; +} diff --git a/Topology/snapshot.c b/Topology/snapshot.c new file mode 100644 index 0000000..3244200 --- /dev/null +++ b/Topology/snapshot.c @@ -0,0 +1,5065 @@ +/* BEGIN_ICS_COPYRIGHT7 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT7 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +#include "topology.h" +#include "topology_internal.h" +#include + +/* this file supports fabric snapshot generation and parsing */ + +/****************************************************************************/ +/* PortStatusData Input/Output functions */ + +/* bitfields needs special handling: LinkQualityIndicator */ +static void PortStatusDataXmlOutputLinkQualityIndicator(IXmlOutputState_t *state, const char *tag, void *data) +{ + IXmlOutputUint(state, tag, ((STL_PORT_COUNTERS_DATA *)data)->lq.s.linkQualityIndicator); +} + +static void PortStatusDataXmlParserEndLinkQualityIndicator(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + uint8 value; + + if (IXmlParseUint8(state, content, len, &value)) + ((STL_PORT_COUNTERS_DATA *)object)->lq.s.linkQualityIndicator = value; +} + +IXML_FIELD PortStatusDataFields[] = { + { tag:"XmitData", format:'U', IXML_FIELD_INFO(STL_PORT_COUNTERS_DATA, portXmitData) }, + { tag:"RcvData", format:'U', IXML_FIELD_INFO(STL_PORT_COUNTERS_DATA, portRcvData) }, + { tag:"XmitPkts", format:'U', IXML_FIELD_INFO(STL_PORT_COUNTERS_DATA, portXmitPkts) }, + { tag:"RcvPkts", format:'U', IXML_FIELD_INFO(STL_PORT_COUNTERS_DATA, portRcvPkts) }, + { tag:"MulticastXmitPkts", format:'U', IXML_FIELD_INFO(STL_PORT_COUNTERS_DATA, portMulticastXmitPkts) }, + { tag:"MulticastRcvPkts", format:'U', IXML_FIELD_INFO(STL_PORT_COUNTERS_DATA, portMulticastRcvPkts) }, + { tag:"XmitWait", format:'U', IXML_FIELD_INFO(STL_PORT_COUNTERS_DATA, portXmitWait) }, + { tag:"CongDiscards", format:'U', IXML_FIELD_INFO(STL_PORT_COUNTERS_DATA, swPortCongestion) }, + { tag:"RcvFECN", format:'U', IXML_FIELD_INFO(STL_PORT_COUNTERS_DATA, portRcvFECN) }, + { tag:"RcvBECN", format:'U', IXML_FIELD_INFO(STL_PORT_COUNTERS_DATA, portRcvBECN) }, + { tag:"XmitTimeCong", format:'U', IXML_FIELD_INFO(STL_PORT_COUNTERS_DATA, portXmitTimeCong) }, + { tag:"XmitWastedBW", format:'U', IXML_FIELD_INFO(STL_PORT_COUNTERS_DATA, portXmitWastedBW) }, + { tag:"XmitWaitData", format:'U', IXML_FIELD_INFO(STL_PORT_COUNTERS_DATA, portXmitWaitData) }, + { tag:"RcvBubble", format:'U', IXML_FIELD_INFO(STL_PORT_COUNTERS_DATA, portRcvBubble) }, + { tag:"MarkFECN", format:'U', IXML_FIELD_INFO(STL_PORT_COUNTERS_DATA, portMarkFECN) }, + { tag:"RcvConstraintErrors", format:'U', IXML_FIELD_INFO(STL_PORT_COUNTERS_DATA, portRcvConstraintErrors) }, + { tag:"RcvSwitchRelayErrors", format:'U', IXML_FIELD_INFO(STL_PORT_COUNTERS_DATA, portRcvSwitchRelayErrors) }, + { tag:"XmitDiscards", format:'U', IXML_FIELD_INFO(STL_PORT_COUNTERS_DATA, portXmitDiscards) }, + { tag:"XmitConstraintErrors", format:'U', IXML_FIELD_INFO(STL_PORT_COUNTERS_DATA, portXmitConstraintErrors) }, + { tag:"RcvRemotePhysicalErrors", format:'U', IXML_FIELD_INFO(STL_PORT_COUNTERS_DATA, portRcvRemotePhysicalErrors) }, + { tag:"LocalLinkIntegrityErrors", format:'U', IXML_FIELD_INFO(STL_PORT_COUNTERS_DATA, localLinkIntegrityErrors) }, + { tag:"RcvErrors", format:'U', IXML_FIELD_INFO(STL_PORT_COUNTERS_DATA, portRcvErrors) }, + { tag:"ExcessiveBufferOverruns", format:'U', IXML_FIELD_INFO(STL_PORT_COUNTERS_DATA, excessiveBufferOverruns) }, + { tag:"FMConfigErrors", format:'U', IXML_FIELD_INFO(STL_PORT_COUNTERS_DATA, fmConfigErrors) }, + { tag:"LinkErrorRecovery", format:'U', IXML_FIELD_INFO(STL_PORT_COUNTERS_DATA, linkErrorRecovery) }, + { tag:"LinkDowned", format:'U', IXML_FIELD_INFO(STL_PORT_COUNTERS_DATA, linkDowned) }, + { tag:"UncorrectableErrors", format:'U', IXML_FIELD_INFO(STL_PORT_COUNTERS_DATA, uncorrectableErrors) }, + { tag:"LinkQualityIndicator", format:'K', format_func:PortStatusDataXmlOutputLinkQualityIndicator, end_func:PortStatusDataXmlParserEndLinkQualityIndicator }, // bitfield + { NULL } +}; + +void PortStatusDataXmlOutput(IXmlOutputState_t *state, const char *tag, void *data) +{ + IXmlOutputStruct(state, tag, (STL_PORT_COUNTERS_DATA *)data, NULL, PortStatusDataFields); +} + +// only output if value != NULL +void PortStatusDataXmlOutputOptional(IXmlOutputState_t *state, const char *tag, void *data) +{ + IXmlOutputOptionalStruct(state, tag, (STL_PORT_COUNTERS_DATA *)data, NULL, PortStatusDataFields); +} + +static void PortStatusDataXmlParserEnd(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + STL_PORT_COUNTERS_DATA *pPortCountersData = (STL_PORT_COUNTERS_DATA *)object; + PortData *portp = (PortData*)parent; + + if (! valid) // missing mandatory fields + goto failvalidate; + + if (portp->pPortCounters) { + IXmlParserPrintError(state, "More than 1 PortStatus for Port"); + goto failinsert; + } + portp->pPortCounters = pPortCountersData; + // NumLanesDown is set in PortDataXmlParserEnd() + + return; + +failinsert: +failvalidate: + MemoryDeallocate(pPortCountersData); +} + +/****************************************************************************/ +/* QOS (SL2SCMap, SC2SLMap, SC2SCMap, VLArb Table) and PKey Table + * Input/Output functions + */ + +uint8 ixVLArb; // Index for VLArb entry being parsed +uint8 vlVLArb; // VL for VLArb entry being parsed +uint8 ixPKey; // Index for P_Key entry being parsed + +/****************************************************************************/ +/* PortData SLtoSC Input/Output functions */ + +static void *SLtoSCMapXmlParserStart(IXmlParserState_t *state, void *parent, const char **attr) +{ + PortData *portp = (PortData *)parent; // parent points to PortData + QOSData *pQOS = portp->pQOS; + + if (portp->nodep->NodeInfo.NodeType == STL_NODE_SW + && portp->PortNum != 0) { + IXmlParserPrintError(state, "SLtoSCMap not valid for switch external ports"); + return (NULL); + } + + if (!pQOS) { + if ( !( pQOS = portp->pQOS = (QOSData *)MemoryAllocate2AndClear( + sizeof(QOSData), IBA_MEM_FLAG_PREMPTABLE, MYTAG ) ) ) { + IXmlParserPrintError(state, "Unable to allocate memory"); + return (NULL); + } + } + + if (pQOS->SL2SCMap) { + IXmlParserPrintError(state, "SLtoSCMap improperly allocated"); + return (NULL); + } + + if ( !( pQOS->SL2SCMap = (STL_SLSCMAP *)MemoryAllocate2( + sizeof(STL_SLSCMAP), IBA_MEM_FLAG_PREMPTABLE, MYTAG ) ) ) { + IXmlParserPrintError(state, "Unable to allocate memory"); + return (NULL); + } + memset(pQOS->SL2SCMap, 0xff, sizeof(STL_SLSCMAP)); + + return (pQOS->SL2SCMap); + +} // End of SLtoSCMapXmlParserStart + +static void SLtoSCMapXmlParserEnd(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + // parent points to PortData + if (! valid) + goto failvalidate; + return; + +failvalidate: + PortDataFreeQOSData(IXmlParserGetContext(state), (PortData *)parent); + return; + +} // End of SLtoSCMapXmlParserEnd + +static void *SLtoSCMapXmlParserStartSC(IXmlParserState_t *state, void *parent, const char **attr) +{ + STL_SLSCMAP *pSLSC = (STL_SLSCMAP *)parent; // parent points to STL_SLSCMAP + uint8 sl; + + if ( !attr || !attr[0] || (0 != strcmp(attr[0], "SL"))) { + IXmlParserPrintError(state, "Missing SL attribute for SLtoSCMap.SC"); + return (NULL); + } + + if (FSUCCESS != StringToUint8(&sl, attr[1], NULL, 0, TRUE)) { + IXmlParserPrintError(state, "Invalid SL attribute in SLtoSCMap.SC SL: %s", attr[1]); + return (NULL); + } + if (sl >= STL_MAX_SLS) { + IXmlParserPrintError(state, "SL attribute Out-of-Range in SLtoSCMap.SC SL: %s", attr[1]); + return (NULL); + } + + return &(pSLSC->SLSCMap[sl]); + +} // End of SLtoSCMapXmlParserStartSC + +static void SLtoSCMapXmlParserEndSC(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + STL_SLSCMAP *pSLSC = (STL_SLSCMAP *)parent; // parent points to STL_SLSCMAP + STL_SC *pSC = (STL_SC*)object; // object points to specific SLs entry + uint8 sl = pSC - pSLSC->SLSCMap; + uint8 sc; + + if (! valid) + goto failvalidate; + + if (!content || !len) { + IXmlParserPrintError(state, "No SC Value in SLtoSCMap.SC for SL %u", sl); + return; + } + + if (FSUCCESS != StringToUint8(&sc, content, NULL, 0, TRUE)) { + IXmlParserPrintError(state, "Invalid SC Value in SLtoSCMap.SC for SL %u SC: %s", sl, content); + return; + } + + if (sc >= STL_MAX_SCS) { + IXmlParserPrintError(state, "SC Out-of-range in SLtoSCMap.SC for SL:%u SC:%u", sl, sc); + return; + } + + *((uint8 *)pSC) = sc; + + return; + +failvalidate: + // SLtoSCMapXmlParserEnd will free as needed + return; + +} // End of SLtoSCMapXmlParserEndSC + +IXML_FIELD SLtoSCMapSCFields[] = { + { tag:"SC", format:'k', start_func:SLtoSCMapXmlParserStartSC, end_func:SLtoSCMapXmlParserEndSC }, + { NULL } +}; + +static void SLtoSCMapXmlOutputSLAttr(IXmlOutputState_t *state, void *data) +{ + IXmlOutputPrint(state, " SL=\"%u\"", *(uint8 *)data); +} + +void SLtoSCMapXmlOutput(IXmlOutputState_t *state, const char *tag, void *data) +{ + PortData *portp = (PortData *)data; // data points to PortData + NodeData *nodep = portp->nodep; + STL_SLSCMAP *pSLSC = portp->pQOS->SL2SCMap; + uint8 sl; + + // SL2SC only applicable to HFIs and switch port 0 + ASSERT(nodep->NodeInfo.NodeType != STL_NODE_SW || portp->PortNum == 0); + + IXmlOutputStartTag(state, tag); + + for(sl = 0; sl < STL_MAX_SLS; sl++) + { + IXmlOutputStartAttrTag(state, "SC", &sl, SLtoSCMapXmlOutputSLAttr); + IXmlOutputPrint(state, "%u", pSLSC->SLSCMap[sl].SC); + IXmlOutputEndTag(state, "SC"); + } + + IXmlOutputEndTag(state, tag); + +} // End of SLtoSCMapXmlOutput + +/****************************************************************************/ +/* PortData SCtoSL Input/Output functions */ + +static void *SCtoSLMapXmlParserStart(IXmlParserState_t *state, void *parent, const char **attr) +{ + PortData *portp = (PortData *)parent; // parent points to PortData + QOSData *pQOS = portp->pQOS; + + if (portp->nodep->NodeInfo.NodeType == STL_NODE_SW + && portp->PortNum != 0) { + IXmlParserPrintError(state, "SCtoSLMap not valid for switch external ports"); + return (NULL); + } + + if (!pQOS) { + if ( !( pQOS = portp->pQOS = (QOSData *)MemoryAllocate2AndClear( + sizeof(QOSData), IBA_MEM_FLAG_PREMPTABLE, MYTAG ) ) ) { + IXmlParserPrintError(state, "Unable to allocate memory"); + return (NULL); + } + } + + if (pQOS->SC2SLMap) { + IXmlParserPrintError(state, "SCtoSLMap improperly allocated"); + return (NULL); + } + + if ( !( pQOS->SC2SLMap = (STL_SCSLMAP *)MemoryAllocate2AndClear( + sizeof(STL_SCSLMAP), IBA_MEM_FLAG_PREMPTABLE, MYTAG ) ) ) { + IXmlParserPrintError(state, "Unable to allocate memory"); + return (NULL); + } + + return (pQOS->SC2SLMap); + +} // End of SCtoSLMapXmlParserStart + +static void SCtoSLMapXmlParserEnd(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + // parent points to PortData + if (! valid) + goto failvalidate; + return; + +failvalidate: + PortDataFreeQOSData(IXmlParserGetContext(state), (PortData *)parent); + return; + +} // End of SCtoSLMapXmlParserEnd + +static void *SCtoSLMapXmlParserStartSL(IXmlParserState_t *state, void *parent, const char **attr) +{ + STL_SCSLMAP *pSCSL = (STL_SCSLMAP *)parent; // parent points to STL_SCSLMAP + uint8 sc; + + if ( !attr || !attr[0] || (0 != strcmp(attr[0], "SC"))) { + IXmlParserPrintError(state, "Missing SC attribute for SCtoSLMap.SL"); + return (NULL); + } + + if (FSUCCESS != StringToUint8(&sc, attr[1], NULL, 0, TRUE)) { + IXmlParserPrintError(state, "Invalid SC attribute in SCtoSLMap.SL SC: %s", attr[1]); + return (NULL); + } + if (sc >= STL_MAX_SCS) { + IXmlParserPrintError(state, "SC attribute Out-of-Range in SCtoSLMap.SL SC: %s", attr[1]); + return (NULL); + } + + return &(pSCSL->SCSLMap[sc]); + +} // End of SCtoSLMapXmlParserStartSL + +static void SCtoSLMapXmlParserEndSL(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + STL_SCSLMAP *pSCSL = (STL_SCSLMAP *)parent; // parent points to STL_SCSLMAP + STL_SL *pSL = (STL_SL*)object; // object points to specific SCs entry + uint8 sc = pSL - pSCSL->SCSLMap; + uint8 sl; + + if (! valid) + goto failvalidate; + + if (!content || !len) { + IXmlParserPrintError(state, "No SL Value in SCtoSLMap.SL for SC %u", sc); + return; + } + + if (FSUCCESS != StringToUint8(&sl, content, NULL, 0, TRUE)) { + IXmlParserPrintError(state, "Invalid SL Value in SCtoSLMap.SL for SC %u SL: %s", sc, content); + return; + } + + if (sl >= STL_MAX_SLS) { + IXmlParserPrintError(state, "SL Out-of-range in SCtoSLMap.SL for SC:%u SL:%u", sc, sl); + return; + } + + pSL->SL = sl; + + return; + +failvalidate: + // SCtoSLMapXmlParserEnd will free as needed + return; + +} // End of SCtoSLMapXmlParserEndSL + +IXML_FIELD SCtoSLMapSLFields[] = { + { tag:"SL", format:'k', start_func:SCtoSLMapXmlParserStartSL, end_func:SCtoSLMapXmlParserEndSL }, + { NULL } +}; + +static void SCtoSLMapXmlOutputSCAttr(IXmlOutputState_t *state, void *data) +{ + IXmlOutputPrint(state, " SC=\"%u\"", *(uint8 *)data); +} + +void SCtoSLMapXmlOutput(IXmlOutputState_t *state, const char *tag, void *data) +{ + PortData *portp = (PortData *)data; // data points to PortData + NodeData *nodep = portp->nodep; + STL_SCSLMAP *pSCSL = portp->pQOS->SC2SLMap; + uint8 sc; + + // SC2SL only applicable to HFIs and switch port 0 + ASSERT(nodep->NodeInfo.NodeType != STL_NODE_SW || portp->PortNum == 0); + + IXmlOutputStartTag(state, tag); + + for(sc = 0; sc < STL_MAX_SCS; sc++) + { + IXmlOutputStartAttrTag(state, "SL", &sc, SCtoSLMapXmlOutputSCAttr); + IXmlOutputPrint(state, "%u", pSCSL->SCSLMap[sc].SL); + IXmlOutputEndTag(state, "SL"); + } + + IXmlOutputEndTag(state, tag); + +} // End of SCtoSLMapXmlOutput + +/****************************************************************************/ +/* PortData SCtoSC Input/Output functions */ + +static void *SCtoSCMapXmlParserStart(IXmlParserState_t *state, void *parent, const char **attr) +{ + PortData *portp = (PortData *)parent; // parent points to PortData + NodeData *nodep = portp->nodep; + QOSData *pQOS = portp->pQOS; + + if (nodep->NodeInfo.NodeType != STL_NODE_SW) { + IXmlParserPrintError(state, "SCtoSCMap only valid for switches"); + return (NULL); + } + + if (portp->PortNum == 0) { + IXmlParserPrintError(state, "SCtoSCMap only valid for switch external ports"); + return (NULL); + } + + if (!pQOS) { + if ( !( pQOS = portp->pQOS = (QOSData *)MemoryAllocate2AndClear( + sizeof(QOSData), IBA_MEM_FLAG_PREMPTABLE, MYTAG ) ) ) { + IXmlParserPrintError(state, "Unable to allocate memory"); + return (NULL); + } + } + + QListInitState(&pQOS->SC2SCMapList[0]); + if (!QListInit(&pQOS->SC2SCMapList[0])) { + IXmlParserPrintError(state, "Unable to initialize SC2SCMaps list"); + MemoryDeallocate(pQOS); + return (NULL); + } + + return (parent); + +} // End of SCtoSCMapXmlParserStart + +static void SCtoSCMapXmlParserEnd(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + if (! valid) + goto failvalidate; + + return; + +failvalidate: + PortDataFreeQOSData(IXmlParserGetContext(state), (PortData *)parent); + return; + +} // End of SCtoSCMapXmlParserEnd + +static void *SCtoSCMapXmlParserStartOutPort(IXmlParserState_t *state, void *parent, const char **attr) +{ + PortMaskSC2SCMap *pSC2SC; + uint8_t outport; + + if ( !attr || !attr[0] || ((0 != strcmp(attr[0], "ports")) && (0 != strcmp(attr[0], "port")))) { + IXmlParserPrintError(state, "Missing port attribute for SCtoSCMap.OutputPort"); + return (NULL); + } + + if (!(pSC2SC = (PortMaskSC2SCMap *)MemoryAllocate2AndClear(sizeof(PortMaskSC2SCMap), IBA_MEM_FLAG_PREMPTABLE, MYTAG))) { + IXmlParserPrintError(state, "Unable to allocate memory"); + return (NULL); + } + + if (!(pSC2SC->SC2SCMap = (STL_SCSCMAP *)MemoryAllocate2AndClear(sizeof(STL_SCSCMAP), IBA_MEM_FLAG_PREMPTABLE, MYTAG))) { + IXmlParserPrintError(state, "Unable to allocate memory"); + MemoryDeallocate(pSC2SC); + return (NULL); + } + + if (0 == strcmp(attr[0], "ports")) { // new format, parse the ports + if (FSUCCESS != StringToStlPortMask(pSC2SC->outports, attr[1])) { + IXmlParserPrintError(state, "Invalid ports list attribute in SCtoSCMap.OutputPorts: %s", attr[1]); + MemoryDeallocate(pSC2SC->SC2SCMap); + pSC2SC->SC2SCMap = NULL; + MemoryDeallocate(pSC2SC); + return NULL; + } + } else { // old format + if (FSUCCESS != StringToUint8(&outport, attr[1], NULL, 0, TRUE)) { + IXmlParserPrintError(state, "Invalid port list attribute in SCtoSCMap.OutputPort: %s", attr[1]); + MemoryDeallocate(pSC2SC->SC2SCMap); + pSC2SC->SC2SCMap = NULL; + MemoryDeallocate(pSC2SC); + return (NULL); + } // parser end function will combine single ports with the same tables + StlAddPortToPortMask(pSC2SC->outports, outport); + } + + // Initialize the list entry + ListItemInitState(&pSC2SC->SC2SCMapListEntry); + QListSetObj(&pSC2SC->SC2SCMapListEntry, pSC2SC); + // Initialize all SCs to 15 + memset(&pSC2SC->SC2SCMap->SCSCMap, 15, STL_MAX_SCS); + + return (pSC2SC); + +} // End of SCtoSCMapXmlParserStartOutPort + +static void SCtoSCMapXmlParserEndOutPort(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + PortData *portp = (PortData *)parent; // parent points to PortData + PortMaskSC2SCMap *pSC2SC = (PortMaskSC2SCMap *)object; // object points to PortMaskSCSCMap + uint8_t numports, outport; + + numports = StlNumPortsSetInPortMask(pSC2SC->outports, portp->nodep->NodeInfo.NumPorts); + // Insert into the maps list + if (numports == 1) { + // only one port + outport = StlGetFirstPortInPortMask(pSC2SC->outports); + QOSDataAddSCSCMap(portp, outport, 0, pSC2SC->SC2SCMap); + + // clear out the unneeded stuff created in parser start + MemoryDeallocate(pSC2SC->SC2SCMap); + pSC2SC->SC2SCMap = NULL; + MemoryDeallocate(pSC2SC); + } else { + QListInsertTail(&portp->pQOS->SC2SCMapList[0], &pSC2SC->SC2SCMapListEntry); + } + + if (! valid) + goto failvalidate; + return; + +failvalidate: + // SCtoSCMapXmlParserEnd will free as needed + return; + +} // End of SCtoSCMapXmlParserEndOutPort + +static void *SCtoSCMapXmlParserStartOutPortSC(IXmlParserState_t *state, void *parent, const char **attr) +{ + PortMaskSC2SCMap *pSC2SC = (PortMaskSC2SCMap *)parent; // parent points to PortMaskSCSCMap for given port mask + uint8 sc; + + if ( !attr || !attr[0] || (0 != strcmp(attr[0], "SC"))) { + IXmlParserPrintError(state, "Missing SC attribute for SCtoSCMap.OutputPort.SC"); + return (NULL); + } + + if (FSUCCESS != StringToUint8(&sc, attr[1], NULL, 0, TRUE)) { + IXmlParserPrintError(state, "Invalid SC attribute in SCtoSCMap.OutputPort.SC SC: %s", attr[1]); + return (NULL); + } + if (sc >= STL_MAX_SCS) { + IXmlParserPrintError(state, "SC attribute Out-of-Range in SCtoSCMap.outputPort.SC SC: %s", attr[1]); + return (NULL); + } + + return &(pSC2SC->SC2SCMap->SCSCMap[sc]); + +} // End of SCtoSCMapXmlParserStartOutPortSC + +static void SCtoSCMapXmlParserEndOutPortSC(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + // parent points to STL_SCSCMAP for given output port + PortMaskSC2SCMap *pSC2SC = (PortMaskSC2SCMap *)parent; // parent points to PortMaskSCSCMap for given port mask + STL_SC *pSC = (STL_SC*)object; // object points to specific SCs entry + uint8 isc = pSC - pSC2SC->SC2SCMap->SCSCMap; // input SC + uint8 sc; // output SC + + if (! valid) + goto failvalidate; + + if (!content || !len) { + IXmlParserPrintError(state, "No SC Value in SCtoSCMap.OutputPort.SC for SC %u", isc); + return; + } + + if (FSUCCESS != StringToUint8(&sc, content, NULL, 0, TRUE)) { + IXmlParserPrintError(state, "Invalid SC' Value in SCtoSCMap.OutputPort.SC for SC %u SC': %s", isc, content); + return; + } + + if (sc >= STL_MAX_SCS) { + IXmlParserPrintError(state, "SC Out-of-range in SCtoSCMap.OutputPort.SC for SC %u SC':%u", isc, sc); + return; + } + + pSC->SC = sc; + + return; + +failvalidate: + // SCtoSCMapXmlParserEnd will free as needed + return; + +} // End of SCtoSCMapXmlParserEndOutPortSC + +IXML_FIELD SCtoSCMapOutPortSCFields[] = { + { tag:"SC", format:'k', start_func:SCtoSCMapXmlParserStartOutPortSC, end_func:SCtoSCMapXmlParserEndOutPortSC }, + { NULL } +}; + +IXML_FIELD SCtoSCMapOutPortFields[] = { + { tag:"OutputPort", format:'C', subfields:SCtoSCMapOutPortSCFields, start_func:SCtoSCMapXmlParserStartOutPort, end_func:SCtoSCMapXmlParserEndOutPort}, + { NULL } +}; + +static void SCtoSCMapXmlOutputPortAttr(IXmlOutputState_t *state, void *data) +{ + IXmlOutputPrint(state, " ports=\"%s\"", (char *)data); +} + +static void SCtoSCMapXmlOutputSCAttr(IXmlOutputState_t *state, void *data) +{ + IXmlOutputPrint(state, " SC=\"%u\"", *(uint8 *)data); +} + +void SCtoSCMapXmlOutput(IXmlOutputState_t *state, const char *tag, void *data) +{ + PortData *portp = (PortData *)data; // data points to PortData + NodeData *nodep = portp->nodep; + LIST_ITEM *p; + uint8 sc; + + // SC2SC only applicable to switch external ports + ASSERT(nodep->NodeInfo.NodeType == STL_NODE_SW && portp->PortNum != 0); + + if (QListHead(&portp->pQOS->SC2SCMapList[0]) != NULL) { + IXmlOutputStartTag(state, tag); + + for (p = QListHead(&portp->pQOS->SC2SCMapList[0]); p != NULL; p = QListNext(&portp->pQOS->SC2SCMapList[0], p)) { + PortMaskSC2SCMap *pSC2SC = (PortMaskSC2SCMap *)QListObj(p); + int buflen = portp->nodep->NodeInfo.NumPorts*3; + char buf[buflen]; + + FormatStlPortMask(buf, pSC2SC->outports, portp->nodep->NodeInfo.NumPorts, buflen); + + IXmlOutputStartAttrTag(state, "OutputPort", &buf[7], + SCtoSCMapXmlOutputPortAttr); + + for (sc = 0; sc < STL_MAX_SCS; sc++) { + // don't output mappings to SC15 + if (sc == 0 || pSC2SC->SC2SCMap->SCSCMap[sc].SC != 15) { + IXmlOutputStartAttrTag(state, "SC", &sc, SCtoSCMapXmlOutputSCAttr); + IXmlOutputPrint(state, "%u", pSC2SC->SC2SCMap->SCSCMap[sc].SC); + IXmlOutputEndTag(state, "SC"); + } + } + + IXmlOutputEndTag(state, "OutputPort"); + } + + IXmlOutputEndTag(state, tag); + } + +} // End of SCtoSCMapXmlOutput + +/****************************************************************************/ +/* PortData SCtoVLx Input/Output functions */ + +static void *SCtoVLxMapXmlParserStart(IXmlParserState_t *state, void *parent, const char **attr, ScvlEnum_t scvlx) +{ + PortData *portp = (PortData *)parent; // parent points to PortData + NodeData *nodep = (NodeData *)portp->nodep; + QOSData *pQOS = portp->pQOS; + + if (scvlx == Enum_SCVLnt && nodep->NodeInfo.NodeType == STL_NODE_SW && portp->PortNum == 0) { + IXmlParserPrintError(state, "SCtoVLtMap not valid for Switch port 0"); + return (NULL); + } + + if (scvlx == Enum_SCVLr && !getIsVLrSupported(nodep, portp)) { + IXmlParserPrintError(state, "SCtoVLrMap not supported"); + return (NULL); + } + + if (!pQOS) { + if (!(pQOS = portp->pQOS = (QOSData*)MemoryAllocate2AndClear( + sizeof(QOSData), IBA_MEM_FLAG_PREMPTABLE, MYTAG ))) { + IXmlParserPrintError(state, "Unable to allocate memory"); + return (NULL); + } + } + + return (&pQOS->SC2VLMaps[scvlx]); + +} // End of SCtoVLxMapXmlParserStart + +static void *SCtoVLrMapXmlParserStart(IXmlParserState_t *state, void *parent, const char **attr) +{ + return SCtoVLxMapXmlParserStart(state, parent, attr, Enum_SCVLr); +} + +static void *SCtoVLtMapXmlParserStart(IXmlParserState_t *state, void *parent, const char **attr) +{ + return SCtoVLxMapXmlParserStart(state, parent, attr, Enum_SCVLt); +} + +static void *SCtoVLntMapXmlParserStart(IXmlParserState_t *state, void *parent, const char **attr) +{ + return SCtoVLxMapXmlParserStart(state, parent, attr, Enum_SCVLnt); +} + +static void SCtoVLxMapXmlParserEnd(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + // parent points to PortData + if (!valid) + goto failvalidate; + return; + +failvalidate: + PortDataFreeQOSData(IXmlParserGetContext(state), (PortData *)parent); + return; +} // End of SCtoVLxMapXmlParserEnd + +static void *SCtoVLxMapXmlParserStartVLx(IXmlParserState_t *state, void *parent, const char **attr) +{ + STL_SCVLMAP *pSCVL = (STL_SCVLMAP *)parent; // parent points to STL_SCVLMAP + uint8 sc; + + if (!attr || !attr[0] || (0 != strcmp(attr[0], "SC"))) { + IXmlParserPrintError(state, "Missing SC attribute for SCtoVLMAp.VL"); + return (NULL); + } + + if (StringToUint8(&sc, attr[1], NULL, 0, TRUE) != FSUCCESS) { + IXmlParserPrintError(state, "Invalid SC attribute in SCtoVLMap.VL SC: %s", attr[1]); + return (NULL); + } + if (sc >= STL_MAX_SCS) { + IXmlParserPrintError(state, "SC attribute Out-of-Range in SCtoVLMap.VL SC: %s", attr[1]); + return (NULL); + } + + return &(pSCVL->SCVLMap[sc]); +} // End of SCtoVLxMapXmlParserStartVLx + +static void SCtoVLxMapXmlParserEndVLx(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + STL_SCVLMAP *pSCVL = (STL_SCVLMAP *)parent; // parent points to STL_SCVLMAP + STL_VL *pVL = (STL_VL*)object; // object points to specific VLs entry + uint8 sc = pVL - pSCVL->SCVLMap; + uint8 vl; + + if (!valid) + goto failvalidate; + + if (!content || !len) { + IXmlParserPrintError(state, "No VL Value in SCtoVLMap.VL for SC %u", sc); + return; + } + + if (StringToUint8(&vl, content, NULL, 0, TRUE) != FSUCCESS) { + IXmlParserPrintError(state, "Invalid VL Value in SCtoVLMap.VL for SC: %u VL: %s", sc, content); + return; + } + + if (vl >= STL_MAX_VLS) { + IXmlParserPrintError(state, "VL Out-of-range in SCtoVLMap.VL for SC: %u VL: %u", sc, vl); + return; + } + + pVL->VL = vl; + + return; + +failvalidate: + // SCtoVLMapXmlParserEnd will free as needed + return; +} + + +IXML_FIELD SCtoVLrMapVLrFields[] = { + { tag:"VLr", format:'k', start_func:SCtoVLxMapXmlParserStartVLx, end_func:SCtoVLxMapXmlParserEndVLx }, + { NULL } +}; + +IXML_FIELD SCtoVLtMapVLtFields[] = { + { tag:"VLt", format:'k', start_func:SCtoVLxMapXmlParserStartVLx, end_func:SCtoVLxMapXmlParserEndVLx }, + { NULL } +}; + +IXML_FIELD SCtoVLntMapVLntFields[] = { + { tag:"VLnt", format:'k', start_func:SCtoVLxMapXmlParserStartVLx, end_func:SCtoVLxMapXmlParserEndVLx }, + { NULL } +}; + +static void SCtoVLxMapXmlOutputSCAttr(IXmlOutputState_t *state, void *data) +{ + IXmlOutputPrint(state, " SC=\"%u\"", *(uint8 *)data); +} + +void SCtoVLxMapXmlOutput(IXmlOutputState_t *state, const char *tag, void *data, ScvlEnum_t scvlx) +{ + PortData *portp = (PortData *)data; // data points to PortData + NodeData *nodep = portp->nodep; + STL_SCVLMAP *pSCVL = &(portp->pQOS->SC2VLMaps[scvlx]); + uint8 sc; + char *vlname = "VL"; + switch (scvlx) { + case Enum_SCVLr: vlname = "VLr"; + break; + case Enum_SCVLt: vlname = "VLt"; + break; + case Enum_SCVLnt: vlname = "VLnt"; + break; + } + + // SC2VLnt doesn't apply to switch port 0 + ASSERT(!(scvlx == Enum_SCVLnt && nodep->NodeInfo.NodeType == STL_NODE_SW && portp->PortNum == 0)); + ASSERT(!(scvlx == Enum_SCVLr && !getIsVLrSupported(nodep, portp))); + + IXmlOutputStartTag(state, tag); + + for(sc = 0; sc < STL_MAX_SCS; sc++) + { + IXmlOutputStartAttrTag(state, vlname, &sc, SCtoVLxMapXmlOutputSCAttr); + IXmlOutputPrint(state, "%u", pSCVL->SCVLMap[sc].VL); + IXmlOutputEndTag(state, vlname); + } + + IXmlOutputEndTag(state, tag); + +} // End of SCtoVLxMapXmlOutput + +/****************************************************************************/ +/* PortData VLArbitration Weight Input/Output functions */ + +static void *VLArbXmlParserStartWeight(IXmlParserState_t *state, void *parent, const char **attr) +{ + // parent points to STL_VLARB_TABLE + + if ( !attr || !attr[0] || (0 != strcmp(attr[0], "VL"))) { + IXmlParserPrintError(state, "Missing VL attribute for VLArbitration Weight"); + return (NULL); + } + + if (FSUCCESS != StringToUint8(&vlVLArb, attr[1], NULL, 0, TRUE)) { + IXmlParserPrintError(state, "Invalid VL attribute in VLArbitration Weight VL: %s", attr[1]); + return (NULL); + } + + if (vlVLArb >= STL_MAX_VLS) { + IXmlParserPrintError( state, + "VL attribute Out-of-range in VLArbitration Weight VL: %s", attr[1] ); + return (NULL); + } + + // ideally we could return &pVLArbTable->Elements[ixVLArb] + // and even save vVLArb in the entry here. + // but we need to keep ixVLArb so we can increment it + // so we simply keep ixVLArb and vlVLArb in globals and don't really use + // "object" as our return + return (parent); + +} // End of VLArbXmlParserStartWeight + +static void VLArbXmlParserEndWeight(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + // parent points to STL_VLARB_TABLE + STL_VLARB_TABLE *pVLArb = (STL_VLARB_TABLE *)parent; + uint8 weight; + + if (! valid) + goto failvalidate; + + // Assign VLArbTable->ArbTable[ixVLArb] = vl,weight + if (!content || !len) { + IXmlParserPrintError(state, "No Weight Value in VLArbitration Weight for VL %u", vlVLArb); + return; + } + + if (FSUCCESS != StringToUint8(&weight, content, NULL, 0, TRUE)) { + IXmlParserPrintError(state, "Invalid Weight Value in VLArbitration Weight for VL %u Weight: %s", vlVLArb, content); + return; + } + + pVLArb->Elements[ixVLArb].s.VL = vlVLArb; + pVLArb->Elements[ixVLArb].Weight = weight; + ixVLArb++; + return; + +failvalidate: + // VLArb*XmlParserEnd will free as needed + return; + +} // End of VLArbXmlParserEndWeight + +IXML_FIELD VLArbFields[] = { + { tag:"Weight", format:'k', start_func:VLArbXmlParserStartWeight, end_func:VLArbXmlParserEndWeight}, + { NULL } +}; + +static void VLArbXmlOutputVLAttr(IXmlOutputState_t *state, void *data) +{ + IXmlOutputPrint(state, " VL=\"%u\"", *(uint8 *)data); +} + +void VLArbXmlOutput(IXmlOutputState_t *state, const char *tag, void *data, int capacity) +{ + int ix; + uint8 vl; + STL_VLARB_TABLE *pVLArb = (STL_VLARB_TABLE*)data; + + IXmlOutputStartTag(state, tag); + for(ix = 0; ix < capacity; ix++) + { + vl = pVLArb->Elements[ix].s.VL; + IXmlOutputStartAttrTag(state, "Weight", &vl, VLArbXmlOutputVLAttr); + IXmlOutputPrint(state, "%u", pVLArb->Elements[ix].Weight); + IXmlOutputEndTag(state, "Weight"); + } + IXmlOutputEndTag(state, tag); + +} // End of VLArbXmlOutput + +/****************************************************************************/ +/* PortData VLArbitrationLow Input/Output functions */ + +static void *VLArbLowXmlParserStart(IXmlParserState_t *state, void *parent, const char **attr) +{ + PortData *portp = (PortData *)parent; // parent points to PortData + QOSData *pQOS = portp->pQOS; + + if (!pQOS) { + if ( !( pQOS = portp->pQOS = (QOSData *)MemoryAllocate2AndClear( + sizeof(QOSData), IBA_MEM_FLAG_PREMPTABLE, MYTAG ) ) ) { + IXmlParserPrintError(state, "Unable to allocate memory"); + return (NULL); + } + } + + ixVLArb = 0; + return ((void *)&(pQOS->u.VLArbTable[STL_VLARB_LOW_ELEMENTS])); + +} // End of VLArbLowXmlParserStart + +static void VLArbLowXmlParserEnd(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + // parent points to PortData + if (! valid) + goto failvalidate; + return; + +failvalidate: + PortDataFreeQOSData(IXmlParserGetContext(state), (PortData *)parent); + return; + +} // End of VLArbLowXmlParserEnd + + +void VLArbLowXmlOutput(IXmlOutputState_t *state, const char *tag, void *data) +{ + PortData *portp = (PortData *)data; // data points to PortData + STL_VLARB_TABLE *pVLArb = portp->pQOS->u.VLArbTable; + + VLArbXmlOutput(state, tag, &pVLArb[STL_VLARB_LOW_ELEMENTS], + portp->PortInfo.VL.ArbitrationLowCap); +} // End of VLArbLowXmlOutput + +/****************************************************************************/ +/* PortData VLArbitrationHigh Input/Output functions */ + +static void *VLArbHighXmlParserStart(IXmlParserState_t *state, void *parent, const char **attr) +{ + PortData *portp = (PortData *)parent; // parent points to PortData + QOSData *pQOS = portp->pQOS; + + if (!pQOS) { + if ( !( pQOS = portp->pQOS = (QOSData *)MemoryAllocate2AndClear( + sizeof(QOSData), IBA_MEM_FLAG_PREMPTABLE, MYTAG ) ) ) { + IXmlParserPrintError(state, "Unable to allocate memory"); + return (NULL); + } + } + + ixVLArb = 0; + return ((void *)&(pQOS->u.VLArbTable[STL_VLARB_HIGH_ELEMENTS])); + +} // End of VLArbHighXmlParserStart + +static void VLArbHighXmlParserEnd(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + // parent points to PortData + if (! valid) + goto failvalidate; + return; + +failvalidate: + PortDataFreeQOSData(IXmlParserGetContext(state), (PortData *)parent); + return; + +} // End of VLArbHighXmlParserEnd + +void VLArbHighXmlOutput(IXmlOutputState_t *state, const char *tag, void *data) +{ + PortData *portp = (PortData *)data; // data points to PortData + STL_VLARB_TABLE *pVLArb = portp->pQOS->u.VLArbTable; + + VLArbXmlOutput(state, tag, &pVLArb[STL_VLARB_HIGH_ELEMENTS], + portp->PortInfo.VL.ArbitrationHighCap); + +} // End of VLArbHighXmlOutput + +/****************************************************************************/ +/* PortData VLArbitrationPreemptElements Input/Output functions */ + +static void *VLArbPreemptElementsXmlParserStart(IXmlParserState_t *state, void *parent, const char **attr) +{ + PortData *portp = (PortData *)parent; // parent points to PortData + QOSData *pQOS = portp->pQOS; + + if (!pQOS) { + if ( !( pQOS = portp->pQOS = (QOSData *)MemoryAllocate2AndClear( + sizeof(QOSData), IBA_MEM_FLAG_PREMPTABLE, MYTAG ) ) ) { + IXmlParserPrintError(state, "Unable to allocate memory"); + return (NULL); + } + } + + ixVLArb = 0; + return ((void *)&(pQOS->u.VLArbTable[STL_VLARB_PREEMPT_ELEMENTS])); + +} // End of VLArbPreemptElementsXmlParserStart + +static void VLArbPreemptElementsXmlParserEnd(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + // parent points to PortData + if (! valid) + goto failvalidate; + return; + +failvalidate: + PortDataFreeQOSData(IXmlParserGetContext(state), (PortData *)parent); + return; + +} // End of VLArbPreemptElementsXmlParserEnd + +void VLArbPreemptElementsXmlOutput(IXmlOutputState_t *state, const char *tag, void *data) +{ + PortData *portp = (PortData *)data; // data points to PortData + STL_VLARB_TABLE *pVLArb = portp->pQOS->u.VLArbTable; + + VLArbXmlOutput(state, tag, &pVLArb[STL_VLARB_PREEMPT_ELEMENTS], + STL_MAX_PREEMPT_CAP); +} // End of VLArbPreemptElementsXmlOutput + +/****************************************************************************/ +/* PortData VLArbitrationPreemptMatrix Input/Output functions */ + +static void *VLArbPreemptMatrixXmlParserStart(IXmlParserState_t *state, void *parent, const char **attr) +{ + PortData *portp = (PortData *)parent; // parent points to PortData + QOSData *pQOS = portp->pQOS; + + if (!pQOS) { + if ( !( pQOS = portp->pQOS = (QOSData *)MemoryAllocate2AndClear( + sizeof(QOSData), IBA_MEM_FLAG_PREMPTABLE, MYTAG ) ) ) { + IXmlParserPrintError(state, "Unable to allocate memory"); + return (NULL); + } + } + + return ((void *)&(pQOS->u.VLArbTable[STL_VLARB_PREEMPT_MATRIX])); + +} // End of VLArbPreemptMatrixXmlParserStart + +static void VLArbPreemptMatrixXmlParserEnd(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + // parent points to PortData + if (! valid) + goto failvalidate; + return; + +failvalidate: + PortDataFreeQOSData(IXmlParserGetContext(state), (PortData *)parent); + return; + +} // End of VLArbPreemptMatrixXmlParserEnd + +static void *VLArbPreemptMatrixXmlParserStartEntry(IXmlParserState_t *state, void *parent, const char **attr) +{ + // parent points to VLARBTABLE for PreemptMatrix + STL_VLARB_TABLE *pVLArb = (STL_VLARB_TABLE *)parent; + uint8 vl; + + if ( !attr || !attr[0] || (0 != strcmp(attr[0], "VL"))) { + IXmlParserPrintError(state, "Missing VL attribute for VLArbitrationPreemptMatrix.MatrixEntry"); + return (NULL); + } + + if (FSUCCESS != StringToUint8(&vl, attr[1], NULL, 0, TRUE)) { + IXmlParserPrintError(state, "Invalid VL attribute in VLArbitrationPreemptMatrix.MatrixEntry VL: %s", attr[1]); + return (NULL); + } + + if (vl >= STL_MAX_VLS) { + IXmlParserPrintError( state, + "VL attribute Out-of-range in VLArbitrationPreemptMatrix.MatrixEntry VL:%u", vl ); + return (NULL); + } + + return &(pVLArb->Matrix[vl]); + +} // End of VLArbPreemptMatrixXmlParserStartEntry + +static void VLArbPreemptMatrixXmlParserEndEntry(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + // parent points to VLARBTABLE for PreemptMatrix + STL_VLARB_TABLE *pVLArb = (STL_VLARB_TABLE *)parent; + // object points to PreemptMatrix entry for specific VL + uint32 *pEntry = (uint32 *)object; + uint32 vl = pEntry - pVLArb->Matrix; + uint32 value; + + if (! valid) + goto failvalidate; + + if (!content || !len) { + IXmlParserPrintError(state, "No entry in VLArbitrationPreemptMatrix.MatrixEntry for VL %u", vl); + return; + } + + if (FSUCCESS != StringToUint32(&value, content, NULL, 0, TRUE)) { + IXmlParserPrintError(state, "Invalid entry in VLArbitrationPreemptMatrix.MatrixEntry for VL %u MatrixEntry: %s", vl, content); + return; + } + + *pEntry = value; + return; + +failvalidate: + // VLArbPreemptMatrixXmlParserEnd will free as needed + return; + +} + +IXML_FIELD VLArbPreemptMatrixFields[] = { + { tag:"MatrixEntry", format:'k', start_func:VLArbPreemptMatrixXmlParserStartEntry, end_func:VLArbPreemptMatrixXmlParserEndEntry }, + { NULL } +}; + +void VLArbPreemptMatrixXmlOutput(IXmlOutputState_t *state, const char *tag, void *data) +{ + uint8 ix; + PortData *portp = (PortData *)data; // data points to PortData + STL_VLARB_TABLE *pVLArb = portp->pQOS->u.VLArbTable; + + IXmlOutputStartTag(state, tag); + + for(ix = 0; ix < STL_MAX_VLS; ix++) + { + IXmlOutputStartAttrTag(state, "MatrixEntry", &ix, VLArbXmlOutputVLAttr); + IXmlOutputPrint(state, "%u", pVLArb[STL_VLARB_PREEMPT_MATRIX].Matrix[ix]); + IXmlOutputEndTag(state, "MatrixEntry"); + } + + IXmlOutputEndTag(state, tag); +} // end of VLArbPreemptMatrixXmlOutput + +/****************************************************************************/ +/* PortData PKeyTable Input/Output functions */ + +static void *PKeyTableXmlParserStart(IXmlParserState_t *state, void *parent, const char **attr) +{ + PortData *portp = (PortData *)parent; // parent points to PortData + STL_PKEY_ELEMENT *pPartitionTable; + uint32 num_pkeys; + + if (portp->pPartitionTable) { + IXmlParserPrintError(state, "PKeyTable improperly allocated"); + return (NULL); + } + num_pkeys = PortPartitionTableSize(portp); + + if ( !( pPartitionTable = portp->pPartitionTable = (STL_PKEY_ELEMENT *)MemoryAllocate2AndClear( + sizeof(STL_PKEY_ELEMENT) * num_pkeys, IBA_MEM_FLAG_PREMPTABLE, MYTAG ) ) ) { + IXmlParserPrintError(state, "Unable to allocate memory"); + return (NULL); + } + + ixPKey = 0; + return ((void *)pPartitionTable); + +} // End of PKeyTableXmlParserStart + +static void PKeyTableXmlParserEnd(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + // parent points to PortData + if (! valid) + goto failvalidate; + return; + +failvalidate: + PortDataFreePartitionTable(IXmlParserGetContext(state), (PortData *)parent); + return; + +} // End of PKeyTableXmlParserEnd + +static void *PKeyTableXmlParserStartPKey(IXmlParserState_t *state, void *parent, const char **attr) +{ + // parent points to PKeyTable + + return (parent); + +} // End of PKeyTableXmlParserStartPKey + +static void PKeyTableXmlParserEndPKey(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + // parent points to PKeyTable + STL_PKEY_ELEMENT *pPartitionTable = (STL_PKEY_ELEMENT *)parent; + uint16 pkey; + + if (! valid) + goto failvalidate; + + // Assign pPartitionTable[ixPKey] = pkey + if (!content || !len) { + IXmlParserPrintError(state, "No PKey Value in PKeyTable.PKey"); + return; + } + + if (FSUCCESS != StringToUint16(&pkey, content, NULL, 0, TRUE)) { + IXmlParserPrintError(state, "Invalid PKey Value in PKeyTable.PKey: %s", content); + return; + } + + pPartitionTable[ixPKey].AsReg16 = pkey; + ixPKey++; + return; + +failvalidate: + // PKeyTableXmlParserEnd will free as needed + return; + +} // End of PKeyTableXmlParserEndPKey + +IXML_FIELD PKeyTableFields[] = { + { tag:"PKey", format:'k', start_func:PKeyTableXmlParserStartPKey, end_func:PKeyTableXmlParserEndPKey }, + { NULL } +}; + +void PKeyTableXmlOutput(IXmlOutputState_t *state, const char *tag, void *data) +{ + int ix, last=0; + PortData *portp = (PortData *)data; // data points to PortData + STL_PKEY_ELEMENT *pPKey = portp->pPartitionTable; + int ix_capacity = PortPartitionTableSize(portp); + + IXmlOutputStartTag(state, tag); + + // find the last non-zero pkey in the table + // we will output all pkeys, even if zero, up to the last + // so that we properly retain the pkey indexes + for (ix = 0; ix < ix_capacity; ix++) + { + if (pPKey[ix].AsReg16 & 0x7FFF) + last = ix; + } + for (ix = 0; ix <= last; ix++) + { + IXmlOutputHexPad16(state, "PKey", pPKey[ix].AsReg16); + } + + IXmlOutputEndTag(state, tag); + +} // End of PKeyTableXmlOutput + +/****************************************************************************/ +/* PortData Input/Output functions */ + +static void PortDataXmlFormatAttr(IXmlOutputState_t *state, void *data) +{ + PortData *portp = (PortData *)data; + + IXmlOutputPrint(state, " id=\"0x%016"PRIx64":%u\"", portp->nodep->NodeInfo.NodeGUID, portp->PortNum); +} + +/* bitfields needs special handling: LID */ +static void PortDataXmlOutputEndPortLID(IXmlOutputState_t *state, const char *tag, void *data) +{ + IXmlOutputLIDValue(state, tag, ((PortData *)data)->EndPortLID); +} + +static void PortDataXmlParserEndEndPortLID(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + uint32 value; + + if (IXmlParseUint32(state, content, len, &value)) + ((PortData *)object)->EndPortLID = value; +} + +/* bitfields needs special handling: PortState */ +static void PortDataXmlOutputPortState(IXmlOutputState_t *state, const char *tag, void *data) +{ + IXmlOutputPortStateValue(state, tag, ((PortData *)data)->PortInfo.PortStates.s.PortState); +} + +static void PortDataXmlParserEndPortState(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + uint8 value; + + if (IXmlParseUint8(state, content, len, &value)) + ((PortData *)object)->PortInfo.PortStates.s.PortState = value; +} + +/* bitfields needs special handling: InitReason */ +static void PortDataXmlOutputInitReason(IXmlOutputState_t *state, const char *tag, void *data) +{ + IXmlOutputInitReasonValue(state, tag, ((PortData *)data)->PortInfo.s3.LinkInitReason); +} + +static void PortDataXmlParserEndInitReason(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + uint8 value; + + if (IXmlParseUint8(state, content, len, &value)) + ((PortData *)object)->PortInfo.s3.LinkInitReason = value; +} + + +/* bitfields needs special handling: PortPhysicalState */ +static void PortDataXmlOutputPhysState(IXmlOutputState_t *state, const char *tag, void *data) +{ + IXmlOutputPortPhysStateValue(state, tag, ((PortData *)data)->PortInfo.PortStates.s.PortPhysicalState); +} + +static void PortDataXmlOutputPortPhysConfig(IXmlOutputState_t *state, const char *tag, void *data) +{ + const uint8_t pt = ((PortData *)data)->PortInfo.PortPhysConfig.s.PortType; + IXmlOutputStr(state, tag, StlPortTypeToText(pt)); +} + +static void PortDataXmlParserEndPhysState(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + uint8 value; + + if (IXmlParseUint8(state, content, len, &value)) + ((PortData *)object)->PortInfo.PortStates.s.PortPhysicalState = value; +} + +/* bitfields needs special handling: LMC */ +static void PortDataXmlOutputLMC(IXmlOutputState_t *state, const char *tag, void *data) +{ + IXmlOutputUint(state, tag, ((PortData *)data)->PortInfo.s1.LMC); +} + +static void PortDataXmlParserEndLMC(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + uint8 value; + + if (IXmlParseUint8(state, content, len, &value)) + ((PortData *)object)->PortInfo.s1.LMC = value; +} + +/* bitfields needs special handling: M_KeyProtectBits */ +static void PortDataXmlOutputMKeyProtect(IXmlOutputState_t *state, const char *tag, void *data) +{ + IXmlOutputMKeyProtectValue(state, tag, ((PortData *)data)->PortInfo.s1.M_KeyProtectBits); +} + +static void PortDataXmlParserEndMKeyProtect(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + uint8 value; + + if (IXmlParseUint8(state, content, len, &value)) + ((PortData *)object)->PortInfo.s1.M_KeyProtectBits = value; +} + +/* special handling: LinkWidthEnabled */ +static void PortDataXmlOutputLinkWidthEnabled(IXmlOutputState_t *state, const char *tag, void *data) +{ + IXmlOutputLinkWidthValue(state, tag, + ((PortData*)data)->PortInfo.LinkWidth.Enabled); +} + +/* special handling: LinkWidthSupportedd */ +static void PortDataXmlOutputLinkWidthSupported(IXmlOutputState_t *state, const char *tag, void *data) +{ + IXmlOutputLinkWidthValue(state, tag, + ((PortData*)data)->PortInfo.LinkWidth.Supported); +} + +/* special handling: LinkWidthActive */ +static void PortDataXmlOutputLinkWidthActive(IXmlOutputState_t *state, const char *tag, void *data) +{ + IXmlOutputLinkWidthValue(state, tag, + ((PortData*)data)->PortInfo.LinkWidth.Active); +} + +/* special handling: LinkWidthEnabled */ +static void PortDataXmlOutputLinkWidthDowngradeEnabled(IXmlOutputState_t *state, const char *tag, void *data) +{ + IXmlOutputLinkWidthValue(state, tag, + ((PortData*)data)->PortInfo.LinkWidthDowngrade.Enabled); +} + +/* special handling: LinkWidthSupportedd */ +static void PortDataXmlOutputLinkWidthDowngradeSupported(IXmlOutputState_t *state, const char *tag, void *data) +{ + IXmlOutputLinkWidthValue(state, tag, + ((PortData*)data)->PortInfo.LinkWidthDowngrade.Supported); +} + +/* special handling: LinkWidthTxActive */ +static void PortDataXmlOutputLinkWidthDowngradeTxActive(IXmlOutputState_t *state, const char *tag, void *data) +{ + IXmlOutputLinkWidthValue(state, tag, + ((PortData*)data)->PortInfo.LinkWidthDowngrade.TxActive); +} + +/* special handling: LinkWidthRxActive */ +static void PortDataXmlOutputLinkWidthDowngradeRxActive(IXmlOutputState_t *state, const char *tag, void *data) +{ + IXmlOutputLinkWidthValue(state, tag, + ((PortData*)data)->PortInfo.LinkWidthDowngrade.RxActive); +} + +/* bitfields needs special handling: LinkSpeedSupported */ +static void PortDataXmlOutputLinkSpeedSupported(IXmlOutputState_t *state, const char *tag, void *data) +{ + IXmlOutputLinkSpeedValue( state, tag, ((PortData*)data)->PortInfo.LinkSpeed.Supported); +} + +static void PortDataXmlParserEndLinkSpeedSupported(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + uint16 value; + + if (IXmlParseUint16(state, content, len, &value)) + ((PortData*)object)->PortInfo.LinkSpeed.Supported = value; +} + +/* bitfields needs special handling: LinkSpeedEnabled */ +static void PortDataXmlOutputLinkSpeedEnabled(IXmlOutputState_t *state, const char *tag, void *data) +{ + IXmlOutputLinkSpeedValue( state, tag, ((PortData*)data)->PortInfo.LinkSpeed.Enabled); +} + +static void PortDataXmlParserEndLinkSpeedEnabled(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + uint16 value; + + if (IXmlParseUint16(state, content, len, &value)) + ((PortData*)object)->PortInfo.LinkSpeed.Enabled = value; +} + +/* bitfields needs special handling: LinkSpeedActive */ +static void PortDataXmlOutputLinkSpeedActive(IXmlOutputState_t *state, const char *tag, void *data) +{ + IXmlOutputLinkSpeedValue( state, tag, ((PortData*)data)->PortInfo.LinkSpeed.Active); +} + +static void PortDataXmlParserEndLinkSpeedActive(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + uint16 value; + + if (IXmlParseUint16(state, content, len, &value)) + ((PortData*)object)->PortInfo.LinkSpeed.Active = value; +} + +static void PortDataXmlOutputMTUActiveVLAttr(IXmlOutputState_t *state, void *data) +{ + IXmlOutputPrint(state, " VL=\"%02u\"", *(uint8 *) data); +} + +static void PortDataXmlOutputMTUs(IXmlOutputState_t *state, const char *tag, void *data) +{ + int outputVL; + + IXmlOutputStartTag(state, tag); + + for(outputVL = 0; outputVL < STL_MAX_VLS; outputVL++) + { + IXmlOutputStartAttrTag(state, "MTUActive", &outputVL, PortDataXmlOutputMTUActiveVLAttr); + IXmlOutputPrint(state, "%04u", GetBytesFromMtu(GET_STL_PORT_INFO_NeighborMTU(&(((PortData*)data)->PortInfo), outputVL))); + IXmlOutputEndTag(state, "MTUActive"); + } + + IXmlOutputEndTag(state, tag); + +} // End of PortDataXmlOutputMTUs + +static void *PortDataXmlParserStartMTUActive(IXmlParserState_t *state, void *parent, const char **attr) +{ + // parent points to PortData + /* since MTUActives don't nest, we can get away with a single static */ + /* since VL is selector for a packed array of 4 bits fields, can't return + * pointer to actual field + */ + static uint8 mtuVL; + + if( !attr | !attr[0] || (0 != strcmp(attr[0], "VL"))) { + IXmlParserPrintError(state, "Missing VL attribute for MTUActive"); + return NULL; + } + + if (FSUCCESS != StringToUint8(&mtuVL, attr[1], NULL, 0, TRUE)) { + IXmlParserPrintError(state, "Invalid VL attribute in MTUActive: %s", attr[1]); + return NULL; + } + + if (mtuVL >= STL_MAX_VLS) { + IXmlParserPrintError(state, "VL attribute Out-of-Range in MTUActive: %s", attr[1]); + return (NULL); + } + + return &mtuVL; + +} // End of PortDataXmlParserStartMTUActive + +static void PortDataXmlParserEndMTUActive(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + PortData *portp = (PortData *)parent; // parent points to PortData + uint8 mtuVL = *(uint8*)object; + uint16 value; + + if(IXmlParseUint16(state, content, len, &value)) + PUT_STL_PORT_INFO_NeighborMTU(&(portp->PortInfo), mtuVL, GetMtuFromBytes(value)); +} // End of PortDataXmlParserEndMTUActive + +IXML_FIELD PortDataMTUActiveXmlFields[] = { + { tag:"MTUActive", format:'k', start_func:PortDataXmlParserStartMTUActive, end_func:PortDataXmlParserEndMTUActive }, + { NULL } +}; + +/* bitfields needs special handling: MTUSupported */ +static void PortDataXmlOutputMTUSupported(IXmlOutputState_t *state, const char *tag, void *data) +{ + IXmlOutputMtuValue(state, tag, + ((PortData*)data)->PortInfo.MTU.Cap); +} + +static void PortDataXmlParserEndMTUSupported(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + uint16 value; + + if (IXmlParseUint16(state, content, len, &value)) + ((PortData*)object)->PortInfo.MTU.Cap = GetMtuFromBytes(value); +} + +/* bitfields needs special handling: SMSL */ +static void PortDataXmlOutputSMSL(IXmlOutputState_t *state, const char *tag, void *data) +{ + IXmlOutputUint(state, tag, + ((PortData*)data)->PortInfo.s2.MasterSMSL); +} + +static void PortDataXmlParserEndSMSL(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + uint8 value; + + if (IXmlParseUint8(state, content, len, &value)) + ((PortData*)object)->PortInfo.s2.MasterSMSL = value; +} + +/* bitfields needs special handling: VLsActive */ +static void PortDataXmlOutputVLsActive(IXmlOutputState_t *state, const char *tag, void *data) +{ + IXmlOutputVLsValue(state, tag, + ((PortData*)data)->PortInfo.s4.OperationalVL); +} + +static void PortDataXmlParserEndVLsActive(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + uint8 value; + + if (IXmlParseUint8(state, content, len, &value)) + ((PortData*)object)->PortInfo.s4.OperationalVL = value; +} + +/* bitfields needs special handling: VLsSupported */ +static void PortDataXmlOutputVLsSupported(IXmlOutputState_t *state, const char *tag, void *data) +{ + IXmlOutputVLsValue(state, tag, + ((PortData*)data)->PortInfo.VL.s2.Cap); +} + +static void PortDataXmlParserEndVLsSupported(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + uint8 value; + + if (IXmlParseUint8(state, content, len, &value)) + ((PortData*)object)->PortInfo.VL.s2.Cap = value; +} + +/* VLStall */ +static void PortDataXmlOutputVLStallVLAttr(IXmlOutputState_t *state, void *data) +{ + IXmlOutputPrint(state, " VL=\"%02u\"", *(uint8 *) data); +} + +static void PortDataXmlOutputVLStalls(IXmlOutputState_t *state, const char *tag, void *data) +{ + uint8 vl; + + IXmlOutputStartTag(state, tag); + for(vl = 0; vl < STL_MAX_VLS; vl++) + { + IXmlOutputStartAttrTag(state, "VLStall", &vl, PortDataXmlOutputVLStallVLAttr); + IXmlOutputPrint(state, "%u", ((PortData*)data)->PortInfo.XmitQ[vl].VLStallCount); + IXmlOutputEndTag(state, "VLStall"); + } + IXmlOutputEndTag(state, tag); +} + +static void *PortDataXmlParserStartVLStall(IXmlParserState_t *state, void *parent, const char **attr) +{ + // parent points to PortData + uint8 vl; + + if( !attr | !attr[0] || (0 != strcmp(attr[0], "VL"))) { + IXmlParserPrintError(state, "Missing VL attribute for VLStall"); + return NULL; + } + + if (FSUCCESS != StringToUint8(&vl, attr[1], NULL, 0, TRUE)) { + IXmlParserPrintError(state, "Invalid VL attribute in VLStall: %s", attr[1]); + return NULL; + } + + if (vl >= STL_MAX_VLS) { + IXmlParserPrintError(state, "VL attribute Out-of-Range in VLStall: %s", attr[1]); + return (NULL); + } + + return &((PortData *)parent)->PortInfo.XmitQ[vl]; + +} // End of PortDataXmlParserStartVLStall + +static void PortDataXmlParserEndVLStall(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + // parent points to PortData, object points to VL specific XmitQ_s + struct XmitQ_s *xmitQ = (struct XmitQ_s*)object; + uint8 value; + + if(IXmlParseUint8(state, content, len, &value)) + xmitQ->VLStallCount = value; +} // End of PortDataXmlParserEndVLStall + +IXML_FIELD PortDataVLStallXmlFields[] = { + { tag:"VLStall", format:'k', start_func:PortDataXmlParserStartVLStall, end_func:PortDataXmlParserEndVLStall }, + { NULL } +}; + +/* bitfields needs special handling: MulticastMask */ +static void PortDataXmlOutputMulticastMask(IXmlOutputState_t *state, const char *tag, void *data) +{ + IXmlOutputHex(state, tag, + ((PortData*)data)->PortInfo.MultiCollectMask.MulticastMask); +} + +static void PortDataXmlParserEndMulticastMask(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + uint8 value; + + if (IXmlParseUint8(state, content, len, &value)) + ((PortData*)object)->PortInfo.MultiCollectMask.MulticastMask = value; +} + +/* bitfields needs special handling: CollectiveMask */ +static void PortDataXmlOutputCollectiveMask(IXmlOutputState_t *state, const char *tag, void *data) +{ + IXmlOutputHex(state, tag, + ((PortData*)data)->PortInfo.MultiCollectMask.CollectiveMask); +} + +static void PortDataXmlParserEndCollectiveMask(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + uint8 value; + + if (IXmlParseUint8(state, content, len, &value)) + ((PortData*)object)->PortInfo.MultiCollectMask.CollectiveMask = value; +} + +/* HoQLife */ +static void PortDataXmlOutputHoQLifeVLAttr(IXmlOutputState_t *state, void *data) +{ + IXmlOutputPrint(state, " VL=\"%02u\"", *(uint8 *) data); +} + +static void PortDataXmlOutputHoQLifes(IXmlOutputState_t *state, const char *tag, void *data) +{ + uint8 vl; + + IXmlOutputStartTag(state, tag); + for(vl = 0; vl < STL_MAX_VLS; vl++) + { + IXmlOutputStartAttrTag(state, "HoQLife_Int", &vl, PortDataXmlOutputHoQLifeVLAttr); + IXmlOutputPrint(state, "%u", ((PortData*)data)->PortInfo.XmitQ[vl].HOQLife); + IXmlOutputEndTag(state, "HoQLife_Int"); + } + IXmlOutputEndTag(state, tag); +} + +static void *PortDataXmlParserStartHoQLife(IXmlParserState_t *state, void *parent, const char **attr) +{ + // parent points to PortData + uint8 vl; + + if( !attr | !attr[0] || (0 != strcmp(attr[0], "VL"))) { + IXmlParserPrintError(state, "Missing VL attribute for HoQLife"); + return NULL; + } + + if (FSUCCESS != StringToUint8(&vl, attr[1], NULL, 0, TRUE)) { + IXmlParserPrintError(state, "Invalid VL attribute in HoQLife: %s", attr[1]); + return NULL; + } + + if (vl >= STL_MAX_VLS) { + IXmlParserPrintError(state, "VL attribute Out-of-Range in HoQLife: %s", attr[1]); + return (NULL); + } + + return &((PortData *)parent)->PortInfo.XmitQ[vl]; + +} // End of PortDataXmlParserStartHoQLife + +static void PortDataXmlParserEndHoQLife(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + // parent points to PortData, object points to VL specific XmitQ_s + struct XmitQ_s *xmitQ = (struct XmitQ_s*)object; + uint8 value; + + if(IXmlParseUint8(state, content, len, &value)) + xmitQ->HOQLife = value; +} // End of PortDataXmlParserEndHoQLife + +IXML_FIELD PortDataHoQLifeXmlFields[] = { + //{ tag:"HoQLife", format:'k', format_func: PortDataXmlOutputHoQLife, end_func:IXmlParserEndNoop }, // output only bitfield + { tag:"HoQLife_Int", format:'K', format_func: IXmlOutputNoop, start_func:PortDataXmlParserStartHoQLife, end_func:PortDataXmlParserEndHoQLife }, // input only bitfield + { NULL } +}; + +static void PortDataXmlOutputNeighborMTU(IXmlOutputState_t *state, const char *tag, void *data) +{ + PortData * portp = (PortData *)data; + STL_VL_TO_MTU * table = portp->PortInfo.NeighborMTU; + uint8_t len = sizeof(portp->PortInfo.NeighborMTU) / sizeof(portp->PortInfo.NeighborMTU[0]); + uint8_t i; + + for(i = 0; i < len; i++) + { + IXmlOutputStartTag(state, "NeighborMTU"); + IXmlOutputAttrFmt(state, "VL", "%u", i); + IXmlOutputPrint(state, "0x%02x", table[i].AsReg8); + IXmlOutputEndTag( state, "NeighborMTU"); + } +} + +static void * PortDataXmlParserStartNeighborMtu(IXmlParserState_t *state, void *parent, const char **attr) +{ + PortData * portp = (PortData *)parent; + uint8_t len = sizeof(portp->PortInfo.NeighborMTU) / sizeof(portp->PortInfo.NeighborMTU[0]); + uint8_t i = 0; + if (!attr || !attr[0] || 0 != strcmp(attr[0], "VL")) { + IXmlParserPrintError(state, "Missing VL attribute for delay element"); + return NULL; + } + if (FSUCCESS != StringToUint8(&i, attr[1], NULL, 0, TRUE)) { + IXmlParserPrintError(state, "Invalid VL in Neighbor MTU element: index:%s", attr[1]); + return NULL; + } + if (i >= len) { + IXmlParserPrintError(state, "VL value is out of range: index:%u len:%u", i, len); + return NULL; + } + return (void *)(portp->PortInfo.NeighborMTU + i); +} + +static void PortDataXmlParserEndNeighborMtu(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + uint8_t value; + if (IXmlParseUint8(state, content, len, &value)) + ((STL_VL_TO_MTU *)object)->AsReg8 = value; +} + +IXML_FIELD FlitControlPreemptionXmlFields[] = { + { tag:"MinInitial", format:'U', IXML_FIELD_INFO(PortData, PortInfo.FlitControl.Preemption.MinInitial) }, + { tag:"MinTail", format:'U', IXML_FIELD_INFO(PortData, PortInfo.FlitControl.Preemption.MinTail) }, + { tag:"LargePktLimit", format:'U', IXML_FIELD_INFO(PortData, PortInfo.FlitControl.Preemption.LargePktLimit) }, + { tag:"SmallPktLimit", format:'U', IXML_FIELD_INFO(PortData, PortInfo.FlitControl.Preemption.SmallPktLimit) }, + { tag:"MaxSmallPktLimit", format:'U', IXML_FIELD_INFO(PortData, PortInfo.FlitControl.Preemption.MaxSmallPktLimit) }, + { tag:"PreemptionLimit", format:'U', IXML_FIELD_INFO(PortData, PortInfo.FlitControl.Preemption.PreemptionLimit) }, + { NULL } +}; + +static void FlitControlXmlOutputPreemption(IXmlOutputState_t *state, const char *tag, void *data) +{ + IXmlOutputStruct(state, tag, data, NULL, FlitControlPreemptionXmlFields); +} + +static void * FlitControlXmlParserStartPreemption(IXmlParserState_t *state, void *parent, const char **attr) +{ + return parent; +} + +IXML_FIELD PortDataFlitControlXmlFields[] = { + { tag:"Interleave", format:'H', IXML_FIELD_INFO(PortData, PortInfo.FlitControl.Interleave.AsReg16) }, + { tag:"Preemption", format:'K', format_func:FlitControlXmlOutputPreemption, subfields:FlitControlPreemptionXmlFields, start_func:FlitControlXmlParserStartPreemption, end_func:IXmlParserEndNoop }, + { NULL } +}; + +static void PortDataXmlOutputFlitControl(IXmlOutputState_t *state, const char *tag, void *data) +{ + IXmlOutputStruct(state, tag, data, NULL, PortDataFlitControlXmlFields); +} + +static void * PortDataXmlParserStartFlitControl(IXmlParserState_t *state, void *parent, const char **attr) +{ + return parent; +} + +/* bitfields needs special handling: P_KeyEnforcementInbound */ +static void PortDataXmlOutputP_KeyEnforcementInbound(IXmlOutputState_t *state, const char *tag, void *data) +{ + IXmlOutputOnOffValue(state, tag, + ((PortData*)data)->PortInfo.s3.PartitionEnforcementInbound); +} + +static void PortDataXmlParserEndP_KeyEnforcementInbound(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + uint8 value; + + if (IXmlParseUint8(state, content, len, &value)) + ((PortData*)object)->PortInfo.s3.PartitionEnforcementInbound = value; +} + +/* bitfields needs special handling: P_KeyEnforcementOutbound */ +static void PortDataXmlOutputP_KeyEnforcementOutbound(IXmlOutputState_t *state, const char *tag, void *data) +{ + IXmlOutputOnOffValue(state, tag, + ((PortData*)data)->PortInfo.s3.PartitionEnforcementOutbound); +} + +static void PortDataXmlParserEndP_KeyEnforcementOutbound(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + uint8 value; + + if (IXmlParseUint8(state, content, len, &value)) + ((PortData*)object)->PortInfo.s3.PartitionEnforcementOutbound = value; +} + +/* bitfields needs special handling: SubnetTimeout */ +static void PortDataXmlOutputSubnetTimeout(IXmlOutputState_t *state, const char *tag, void *data) +{ + IXmlOutputTimeoutMultValue(state, tag, + ((PortData*)data)->PortInfo.Subnet.Timeout); +} + +static void PortDataXmlParserEndSubnetTimeout(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + uint8 value; + + if (IXmlParseUint8(state, content, len, &value)) + ((PortData*)object)->PortInfo.Subnet.Timeout = value; +} + +/* bitfields needs special handling: RespTimeout */ +static void PortDataXmlOutputRespTimeout(IXmlOutputState_t *state, const char *tag, void *data) +{ + IXmlOutputTimeoutMultValue(state, tag, + ((PortData*)data)->PortInfo.Resp.TimeValue); +} + +static void PortDataXmlParserEndRespTimeout(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + uint8 value; + + if (IXmlParseUint8(state, content, len, &value)) + ((PortData*)object)->PortInfo.Resp.TimeValue = value; +} + +static void PortDataXmlOutputSLtoSCMap(IXmlOutputState_t *state, const char *tag, void *data) +{ + if ( ((PortData*)data)->nodep && ((PortData*)data)->pQOS && + ((PortData*)data)->pQOS->SL2SCMap ) + SLtoSCMapXmlOutput(state, tag, data); + +} // End of PortDataXmlOutputSLtoSCMap + +static void PortDataXmlOutputSCtoSLMap(IXmlOutputState_t *state, const char *tag, void *data) +{ + if ( ((PortData*)data)->nodep && ((PortData*)data)->pQOS && + ((PortData*)data)->pQOS->SC2SLMap ) + SCtoSLMapXmlOutput(state, tag, data); + +} // End of PortDataXmlOutputSCtoSLMap + +static void PortDataXmlOutputSCtoSCMap(IXmlOutputState_t *state, const char *tag, void *data) +{ + if ( ((PortData*)data)->nodep && ((PortData*)data)->pQOS && + ((PortData*)data)->nodep->NodeInfo.NodeType == STL_NODE_SW && + ((PortData*)data)->PortNum != 0) + SCtoSCMapXmlOutput(state, tag, data); + +} // End of PortDataXmlOutputSCtoSLMap + +static void PortDataXmlOutputSCtoVLxMap(IXmlOutputState_t *state, const char *tag, void *data, ScvlEnum_t scvlx) +{ + if( ((PortData*)data)->nodep && ((PortData*)data)->pQOS) + SCtoVLxMapXmlOutput(state, tag, data, scvlx); +} + +static void PortDataXmlOutputSCtoVLrMap(IXmlOutputState_t *state, const char *tag, void *data) +{ + PortData *portp = (PortData *)data; + NodeData *nodep = portp->nodep; + if(getIsVLrSupported(nodep, portp)) + PortDataXmlOutputSCtoVLxMap(state, tag, data, Enum_SCVLr); +} + +static void PortDataXmlOutputSCtoVLtMap(IXmlOutputState_t *state, const char *tag, void *data) +{ + PortDataXmlOutputSCtoVLxMap(state, tag, data, Enum_SCVLt); +} + +static void PortDataXmlOutputSCtoVLntMap(IXmlOutputState_t *state, const char *tag, void *data) +{ + if( !(((PortData*)data)->nodep->NodeInfo.NodeType == STL_NODE_SW && + ((PortData*)data)->PortNum == 0)) + PortDataXmlOutputSCtoVLxMap(state, tag, data, Enum_SCVLnt); +} + +/** ========================================================================= + * Buffer Control Table I/O functions + */ +void BCTXmlOutputVLLimitAttr(struct IXmlOutputState *state, void *data) +{ + IXmlOutputPrint(state, " VL=\"%u\"", *(uint8 *)data); +} + +static void *BCTXmlParserStart(IXmlParserState_t *state, void *parent, const char **atr) +{ + PortData *portp = (PortData *)parent; // parent points to PortData + + if (portp->pBufCtrlTable) { + IXmlParserPrintError(state, "BufCtrlTable improperly allocated"); + return (NULL); + } + + if ( !( portp->pBufCtrlTable = (STL_BUFFER_CONTROL_TABLE*)MemoryAllocate2AndClear( + sizeof(STL_BUFFER_CONTROL_TABLE), IBA_MEM_FLAG_PREMPTABLE, MYTAG ) ) ) { + IXmlParserPrintError(state, "Unable to allocate memory"); + return (NULL); + } + + return ((void *)portp->pBufCtrlTable); + +} + +static void PortDataXmlOutputBCT(IXmlOutputState_t *state, const char *tag, void *data) +{ + PortData *portp = (PortData *)data; // data points to PortData + STL_BUFFER_CONTROL_TABLE *bct = portp->pBufCtrlTable; + uint8_t vl; + + if (! bct) + return; + + IXmlOutputStartTag(state, tag); + + IXmlOutputStartTag(state, "TxOverallSharedLimit"); + IXmlOutputPrint(state, "%u", bct->TxOverallSharedLimit); + IXmlOutputEndTag(state, "TxOverallSharedLimit"); + + for (vl = 0; vl < STL_MAX_VLS; vl++) + { + IXmlOutputStartAttrTag( state, "VLLimit", &vl, BCTXmlOutputVLLimitAttr ); + IXmlOutputStartTag(state, "TxDedicatedLimit"); + IXmlOutputPrint(state, "%u", bct->VL[vl].TxDedicatedLimit); + IXmlOutputEndTag(state, "TxDedicatedLimit"); + IXmlOutputStartTag(state, "TxSharedLimit"); + IXmlOutputPrint(state, "%u", bct->VL[vl].TxSharedLimit); + IXmlOutputEndTag(state, "TxSharedLimit"); + IXmlOutputEndTag( state, "VLLimit"); + } + IXmlOutputEndTag(state, tag); +} + +static void *BCTVLLimitStartFunc(IXmlParserState_t *state, void *parent, const char **attr) +{ + STL_BUFFER_CONTROL_TABLE *bct = (STL_BUFFER_CONTROL_TABLE *)parent; // parent points to BufCtrlTable + uint8_t vl; + + if ( !attr || !attr[0] || (0 != strcmp(attr[0], "VL"))) { + IXmlParserPrintError(state, "Missing VL attribute in BufferControlTable.VLLimit"); + return (NULL); + } + + if (FSUCCESS != StringToUint8(&vl, attr[1], NULL, 0, TRUE)) { + IXmlParserPrintError(state, "Invalid VL attribute in BufferControlTable.VLLimit VL %s", attr[1]); + return (NULL); + } + + if (vl >= STL_MAX_VLS) { + IXmlParserPrintError(state, "VL attribute Out-of-Range in BufferControlTable.VLLimit VL: %s", attr[1]); + return (NULL); + } + + return ((void *)&bct->VL[vl]); +} + +/** ========================================================================= + * Buffer Control Table Feild Definitions + */ +// parent is STL_BUFFER_CONTROL_TABLE_VL_s +static IXML_FIELD BCTVLLimitFields[] = { + { tag:"TxDedicatedLimit", format:'U', IXML_FIELD_INFO(struct STL_BUFFER_CONTROL_TABLE_VL_s, TxDedicatedLimit) }, + { tag:"TxSharedLimit", format:'U', IXML_FIELD_INFO(struct STL_BUFFER_CONTROL_TABLE_VL_s, TxSharedLimit) }, + { NULL } +}; + +// parent is BufCtrlTable +static IXML_FIELD BufferControlTableFields[] = { + { tag:"TxOverallSharedLimit", format:'U', IXML_FIELD_INFO(STL_BUFFER_CONTROL_TABLE, TxOverallSharedLimit) }, + { tag:"VLLimit", format:'k', subfields:BCTVLLimitFields, start_func:BCTVLLimitStartFunc }, + { NULL } +}; + +/* End Buffer Control Table Definitions */ +/* ========================================================================= */ + + +static void PortDataXmlOutputVLArbLow(IXmlOutputState_t *state, const char *tag, void *data) +{ + int vlarb; + int res = getVLArb((PortData*)data, &vlarb); + DEBUG_ASSERT(!res); + if (res) { + fprintf(stderr, "Error-%s: failed to determine " + "Failed to determine if vlarb is supported. Not outputting VLArbLow\n", __func__); + return; + } + + if (((PortData*)data)->pQOS && vlarb) + VLArbLowXmlOutput(state, tag, data); + +} // End of PortDataXmlOutputVLArbLow + +static void PortDataXmlOutputVLArbHigh(IXmlOutputState_t *state, const char *tag, void *data) +{ + int vlarb; + int res = getVLArb((PortData*)data, &vlarb); + DEBUG_ASSERT(!res); + if (res) { + fprintf(stderr, "Error-%s: failed to determine " + "Failed to determine if vlarb is supported. Not outputting VLArbHigh\n", __func__); + return; + } + + if (((PortData*)data)->pQOS && vlarb) + VLArbHighXmlOutput(state, tag, data); + +} // End of PortDataXmlOutputVLArbHigh + +static void PortDataXmlOutputVLArbPreemptElements(IXmlOutputState_t *state, const char *tag, void *data) +{ + int vlarb; + int res = getVLArb((PortData*)data, &vlarb); + DEBUG_ASSERT(!res); + if (res) { + fprintf(stderr, "Error-%s: failed to determine " + "Failed to determine if vlarb is supported. Not outputting VLArbPreempt\n", __func__); + return; + } + + if (((PortData*)data)->pQOS && vlarb) + VLArbPreemptElementsXmlOutput(state, tag, data); + +} // End of PortDataXmlOutputVLArbPreemptElements + +static void PortDataXmlOutputVLArbPreemptMatrix(IXmlOutputState_t *state, const char *tag, void *data) +{ + int vlarb; + int res = getVLArb((PortData*)data, &vlarb); + DEBUG_ASSERT(!res); + if (res) { + fprintf(stderr, "Error-%s: failed to determine " + "Failed to determine if vlarb is supported. Not outputting VLArbPreemptMatrix\n", __func__); + return; + } + + if (((PortData*)data)->pQOS && vlarb) + VLArbPreemptMatrixXmlOutput(state, tag, data); +} + +static void PortDataXmlOutputPKeyTable(IXmlOutputState_t *state, const char *tag, void *data) +{ + if (((PortData*)data)->nodep && ((PortData*)data)->pPartitionTable) + PKeyTableXmlOutput(state, tag, data); + +} // End of PortDataXmlOutputPKeyTable + +static void PortDataXmlOutputPortStatusData(IXmlOutputState_t *state, const char *tag, void *data) +{ + PortData *portp = (PortData*)data; + + PortStatusDataXmlOutputOptional(state, "PortStatus", portp->pPortCounters); +} + +/* bitfields needs special handling: PassThroughControlDRControl */ +static void PortDataXmlOutputPassThroughControlDRControl(IXmlOutputState_t *state, const char *tag, void *data) +{ + IXmlOutputUint(state, tag, ((PortData*)data)->PortInfo.PassThroughControl.DRControl); +} + +static void PortDataXmlParserEndPassThroughControlDRControl(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + uint8 value; + + if (IXmlParseUint8(state, content, len, &value)) + ((PortData*)object)->PortInfo.PassThroughControl.DRControl = value; +} + +/* bitfields needs special handling: SubnetMulticastPKeyTrapSuppressionEnabled */ +static void PortDataXmlOutputSubnetMulticastPKeyTrapSuppressionEnabled(IXmlOutputState_t *state, const char *tag, void *data) +{ + IXmlOutputUint(state, tag, ((PortData*)data)->PortInfo.Subnet.MulticastPKeyTrapSuppressionEnabled); +} + +static void PortDataXmlParserEndSubnetMulticastPKeyTrapSuppressionEnabled(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + uint8 value; + + if (IXmlParseUint8(state, content, len, &value)) + ((PortData*)object)->PortInfo.Subnet.MulticastPKeyTrapSuppressionEnabled = value; +} + +/* bitfields needs special handling: Subnet.ClientReregister */ +static void PortDataXmlOutputSubnetClientReregister(IXmlOutputState_t *state, const char *tag, void *data) +{ + IXmlOutputUint(state, tag, ((PortData*)data)->PortInfo.Subnet.ClientReregister); +} + +static void PortDataXmlParserEndSubnetClientReregister(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + uint8 value; + + if (IXmlParseUint8(state, content, len, &value)) + ((PortData*)object)->PortInfo.Subnet.ClientReregister = value; +} + +/** ========================================================================= + * CableInfo definitions + */ + +static void *CableInfoXmlParserStartSegValue(IXmlParserState_t *state, void *parent, const char **attr) +{ + // parent points to CableInfoData + uint32 seg; + + if ( !attr || !attr[0] || 0 != strcmp(attr[0], "Seg")) { + IXmlParserPrintError(state, "Missing Seg attribute for CableInfo.Value"); + return NULL; + } + if (FSUCCESS != StringToUint32(&seg, attr[1], NULL, 0, TRUE)) { + IXmlParserPrintError(state, "Invalid Seg attribute for CableInfo.Value Seg: %s", attr[1]); + return NULL; + } + if (seg >= STL_CIB_STD_LEN / sizeof(uint64) ) { + IXmlParserPrintError(state, "Seg attribute Out-of-Range in CableInfo: %s", attr[1]); + return NULL; + } + + return (&((uint8 *)parent)[seg * sizeof(uint64)]); + +} // End of CableInfoXmlParserStartSegValue() + +static void CableInfoXmlParserEndSegValue(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + // parent points to CableInfoData; object points to segment-specific CableInfoData + uint8 *pCableInfoData = (uint8 *)parent; + uint8 *pCableInfoSegData = (uint8 *)object; + uint64 value; + + if (! valid) + return; + if ( !pCableInfoData || !pCableInfoSegData || !content || !len || + (pCableInfoSegData < pCableInfoData) || + (pCableInfoSegData > pCableInfoData + STL_CIB_STD_LEN) ) { + IXmlParserPrintError(state, "CableInfo improperly allocated"); + return; + } + + if(IXmlParseUint64(state, content, len, &value)) { +#if CPU_LE + value = ntoh64(value); +#endif + *(uint64*)pCableInfoSegData = value; + } + +} // End of CableInfoXmlParserEndSegValue() + +const IXML_FIELD CableInfoFields[] = { + { tag:"Value", start_func:CableInfoXmlParserStartSegValue, end_func:CableInfoXmlParserEndSegValue }, + { NULL } +}; + +static void *CableInfoXmlParserStart(IXmlParserState_t *state, void *parent, const char **atr) +{ + PortData *portp = (PortData *)parent; // parent points to PortData + + if (portp->pCableInfoData) { + IXmlParserPrintError(state, "CableInfo improperly allocated"); + return (NULL); + } + + if ( !( portp->pCableInfoData = MemoryAllocate2AndClear( + STL_CABLE_INFO_PAGESZ, IBA_MEM_FLAG_PREMPTABLE, MYTAG ) ) ) { + IXmlParserPrintError(state, "Unable to allocate memory"); + return (NULL); + } + + return ((void *)portp->pCableInfoData); +} + +static void CableInfoOutputSegAttr(IXmlOutputState_t *state, void *data) +{ + IXmlOutputPrint(state, " Seg=\"0x%x\"", *(unsigned int *)data); +} + +static void PortDataXmlOutputCableInfo(IXmlOutputState_t *state, const char *tag, void *data) +{ + unsigned int ix_seg; + PortData *portp = (PortData*)data; + uint64 *pData = (uint64 *)portp->pCableInfoData; + uint64 temp; + + if (! pData) + return; + + IXmlOutputStartTag(state, tag); + + for ( ix_seg = 0; ix_seg < STL_CABLE_INFO_PAGESZ / sizeof(uint64); + pData++, ix_seg++ ) { + temp = *pData; +#if CPU_LE + temp = ntoh64(temp); +#endif + IXmlOutputStartAttrTag(state, "Value", &ix_seg, CableInfoOutputSegAttr); + IXmlOutputPrint(state, "0x%016lx", temp); + IXmlOutputEndTag(state, "Value"); + } + + IXmlOutputEndTag(state, tag); +} + + +/** ========================================================================= + * HFI Congestion Control Table definitions + */ + +static void *HFICCTXmlParserStartSegValue(IXmlParserState_t *state, void *parent, const char **attr) +{ + uint32 seg = 0; + + if (parent == NULL) + return NULL; + + const uint32 seg_max = ((STL_CONGESTION_CONTROL_ENTRY_MAX_VALUE * sizeof(STL_HFI_CONGESTION_CONTROL_TABLE_ENTRY)) / + sizeof(uint64)); + + if ( !attr || !attr[0] || 0 != strcmp(attr[0], "Seg")) { + IXmlParserPrintError(state, "Missing Seg attribute for HFICCT.Value"); + return NULL; + } + if (FSUCCESS != StringToUint32(&seg, attr[1], NULL, 0, TRUE)) { + IXmlParserPrintError(state, "Invalid Seg attribute for HFICCT.Value Seg: %s", attr[1]); + return NULL; + } + if (seg >= seg_max) { + IXmlParserPrintError(state, "Seg attribute Out-of-Range in HFICCT: %s", attr[1]); + return NULL; + } + + return &(((uint8 *)parent)[seg * sizeof(uint64)]); +} + +static void HFICCTXmlParserEndSegValue(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + // parent points to HFICCTData; object points to segment-specific HFICCTData + uint8 *pHFICCTData = (uint8 *)parent; + uint8 *pHFICCTSegData = (uint8 *)object; + uint64 value; + + const uint32 seg_max = ((STL_CONGESTION_CONTROL_ENTRY_MAX_VALUE * sizeof(STL_HFI_CONGESTION_CONTROL_TABLE_ENTRY)) / + sizeof(uint64)); + + if (!valid) + return; + + if (!pHFICCTData) + return; + + if (!pHFICCTSegData || !content || !len || + (pHFICCTSegData < pHFICCTData) || + (pHFICCTSegData > pHFICCTData + seg_max)) { + IXmlParserPrintError(state, "HFICCT improperly allocated"); + return; + } + + if(IXmlParseUint64(state, content, len, &value)) { +#if CPU_LE + value = ntoh64(value); +#endif + *(uint64*)pHFICCTSegData = value; + } + +} // End of HFICCTXmlParserEndSegValue() + +static void *HFICCTXmlParserStart(IXmlParserState_t *state, void *parent, const char **atr) +{ + PortData *portp = (PortData *)parent; // parent points to PortData + unsigned int adjust = 0; + + if (portp->CCTI_Limit == 0) + return (NULL); + + if (portp->CCTI_Limit >= STL_CONGESTION_CONTROL_ENTRY_MAX_VALUE) { + IXmlParserPrintError(state, "HFI Congestion Control Table Limit Index (CCTI_Limit) is invalid"); + return (NULL); + } + + if (portp->pCongestionControlTableEntries) { + IXmlParserPrintError(state, "HFI Congestion Control Table improperly allocated"); + return (NULL); + } + + // Minimum allocation is 128 entries + if (portp->CCTI_Limit < (STL_NUM_CONGESTION_CONTROL_ELEMENTS_BLOCK_ENTRIES * 2)) + adjust = STL_NUM_CONGESTION_CONTROL_ELEMENTS_BLOCK_ENTRIES * 2; + else + adjust = portp->CCTI_Limit + 1; + + // allocation must be adjusted to a multiple of blocks entries + if (adjust % STL_NUM_CONGESTION_CONTROL_ELEMENTS_BLOCK_ENTRIES) { + adjust = ((adjust/STL_NUM_CONGESTION_CONTROL_ELEMENTS_BLOCK_ENTRIES) + 1) * + STL_NUM_CONGESTION_CONTROL_ELEMENTS_BLOCK_ENTRIES; + } + + if (!(portp->pCongestionControlTableEntries = MemoryAllocate2AndClear( + adjust * sizeof(STL_HFI_CONGESTION_CONTROL_TABLE_ENTRY), + IBA_MEM_FLAG_PREMPTABLE, MYTAG))) { + IXmlParserPrintError(state, "Unable to allocate memory"); + return (NULL); + } + + return ((void *)portp->pCongestionControlTableEntries); +} + +static void HFICCTOutputSegAttr(IXmlOutputState_t *state, void *data) +{ + IXmlOutputPrint(state, " Seg=\"0x%x\"", *(unsigned int *)data); +} + +static void PortDataXmlOutputHFICCT(IXmlOutputState_t *state, const char *tag, void *data) +{ + unsigned int ix_seg; + PortData *portp = (PortData*)data; + uint64 *pData = (uint64 *)portp->pCongestionControlTableEntries; + uint64 temp; + uint32 len = 0; + + if (!pData) + return; + + if (portp->CCTI_Limit == 0 || portp->CCTI_Limit >= STL_CONGESTION_CONTROL_ENTRY_MAX_VALUE) + return; + + len = (portp->CCTI_Limit + 1) * sizeof(STL_HFI_CONGESTION_CONTROL_TABLE_ENTRY); + + IXmlOutputStartTag(state, tag); + + for (ix_seg = 0; ix_seg < len / sizeof(uint64); pData++, ix_seg++) { + temp = *pData; +#if CPU_LE + temp = ntoh64(temp); +#endif + IXmlOutputStartAttrTag(state, "Value", &ix_seg, HFICCTOutputSegAttr); + IXmlOutputPrint(state, "0x%016lx", temp); + IXmlOutputEndTag(state, "Value"); + } + + IXmlOutputEndTag(state, tag); +} + +const IXML_FIELD HFICCTFields[] = { + { tag:"Value", start_func:HFICCTXmlParserStartSegValue, end_func:HFICCTXmlParserEndSegValue }, + { NULL } +}; + +// parse Rate_Int into a uint8 field and validate value +void McgMCRateXmlParserEnd_Int(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + uint16 value; + McGroupData *mcgmemberp = (McGroupData*) object; + + if (IXmlParseUint16(state, content, len, &value)) { + if (value <= IB_STATIC_RATE_LAST) + mcgmemberp->GroupInfo.Rate = value; + else + IXmlParserPrintError(state, "Invalid Rate: %u\n", value); + } + else + IXmlParserPrintError(state, "Invalid Rate: %s\n", content); +} + +static void McgMLIDXmlParserEnd(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + uint32 value; + McGroupData *mcgmemberp = (McGroupData *)object; + + if (IXmlParseUint32(state, content, len, &value)) { + // MLID must be either 16-bit format (0xCXXX) or 32-bit format (0xFXXXXXXX) + if (IS_MCAST16(value)) + mcgmemberp->MLID = MCAST16_TO_MCAST32(value); + else if (IS_MCAST32(value)) + mcgmemberp->MLID = value; + else IXmlParserPrintError(state, "Invalid MLID value: 0x%04x\n", value); + } + else + IXmlParserPrintError(state, "Cannot parse \"%s\" as MLID\n", content); +} + +static void McgMGIDXmlParserEnd(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + McGroupData *mcgmemberp = (McGroupData *)object; + uint64 mgid[2]; + + if (FSUCCESS != StringToGid(&mgid[0], &mgid[1], content, NULL, TRUE)) { + IXmlParserPrintError(state, "Cannot parse \"%s\" as MGID\n", content); + return; + } + + mcgmemberp->MGID.AsReg64s.H=mgid[0]; + mcgmemberp->MGID.AsReg64s.L=mgid[1]; + + return; +} + +static void McgMtuXmlParserEnd(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + uint16 value; + + if (IXmlParseUint16(state, content, len, &value)) + ((McGroupData *)object)->GroupInfo.Mtu = GetMtuFromBytes(value); + else IXmlParserPrintError(state, "Invalid Mtu: %s\n", content); + +} + +static void McgPktLifeTimeXmlParserEnd(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + uint8 value; + + if (IXmlParseUint8(state, content, len, &value)) + ((McGroupData *)object)->GroupInfo.PktLifeTime = value; + else IXmlParserPrintError(state, "Invalid PktLifeTime: %s\n", content); + +} + +static void McgSLXmlParserEnd(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + uint32 value; + + if (IXmlParseUint32(state, content, len, &value)) + ((McGroupData *)object)->GroupInfo.u1.s.SL = value; + else IXmlParserPrintError(state, "Invalid SL: %s\n", content); + +} + +static void McgHopLimitXmlParserEnd(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid){ + uint32 value; + + if (IXmlParseUint32(state, content, len, &value)) + ((McGroupData *)object)->GroupInfo.u1.s.HopLimit = value; + else IXmlParserPrintError(state, "Invalid HopLimit: %s\n", content); + +} + +static void McgFlowLabelXmlParserEnd(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + uint32 value; + + if (IXmlParseUint32(state, content, len, &value)) + ((McGroupData *)object)->GroupInfo.u1.s.FlowLabel = value; + else IXmlParserPrintError(state, "Invalid Flow Level: %s\n", content); + +} + +static void *McPortGIDXmlParserStart(IXmlParserState_t *state, void *parent, const char **attr) +{ + McMemberData *mcmemberp = (McMemberData*)MemoryAllocate2AndClear(sizeof(McMemberData), IBA_MEM_FLAG_PREMPTABLE, MYTAG); + + + if (!mcmemberp) { + IXmlParserPrintError(state, "Unable to allocate memory"); + return NULL; + } + + if ( (!attr | !attr[0]) || (0 != strcmp(attr[0], "id"))) { + IXmlParserPrintError(state, "Missing PortGID id"); + MemoryDeallocate(mcmemberp); + return NULL; + } + + // basic initialization of the MCG structure + ListItemInitState(&mcmemberp->McMembersEntry); + QListSetObj(&mcmemberp->McMembersEntry,mcmemberp); + + // no preexisting membership info + mcmemberp->MemberInfo.JoinFullMember=0; + mcmemberp->MemberInfo.JoinNonMember=0; + mcmemberp->MemberInfo.JoinSendOnlyMember=0; + + return mcmemberp; +} + +static void McPortGIDXmlParserEnd(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + FabricData_t *fabricp = IXmlParserGetContext(state); + McMemberData *mcmemberp = (McMemberData *)object; + McGroupData *mcgmemberp = (McGroupData*)parent; + + if (!valid) { + MemoryDeallocate(mcmemberp); + return; + } + + mcmemberp->MemberInfo.RID.MGID = mcgmemberp->MGID; + mcmemberp->MemberInfo.MLID = mcgmemberp->MLID; + mcmemberp->MemberInfo.P_Key = mcgmemberp->GroupInfo.P_Key; + mcmemberp->MemberInfo.Q_Key = mcgmemberp->GroupInfo.Q_Key; + mcmemberp->MemberInfo.Mtu = mcgmemberp->GroupInfo.Mtu; + mcmemberp->MemberInfo.Rate = mcgmemberp->GroupInfo.Rate; + mcmemberp->MemberInfo.PktLifeTime = mcgmemberp->GroupInfo.PktLifeTime; + mcmemberp->MemberInfo.u1.s.SL = mcgmemberp->GroupInfo.u1.s.SL; + mcmemberp->MemberInfo.u1.s.HopLimit = mcgmemberp->GroupInfo.u1.s.HopLimit; + mcmemberp->MemberInfo.u1.s.FlowLabel = mcgmemberp->GroupInfo.u1.s.FlowLabel; + mcmemberp->MemberInfo.TClass = mcgmemberp->GroupInfo.TClass; + + // inset mcmember in the groups structure + QListInsertTail(&mcgmemberp->AllMcGroupMembers, &mcmemberp->McMembersEntry); + + mcmemberp->pPort = NULL; + + if ((mcmemberp->MemberInfo.RID.PortGID.AsReg64s.H != 0) && (mcmemberp->MemberInfo.RID.PortGID.AsReg64s.L != 0)) { + // attach port to the PortGID + mcmemberp->pPort = FindPortGuid(fabricp, mcmemberp->MemberInfo.RID.PortGID.AsReg64s.L); + //verify there is a port and that there is a neighbor + if (mcmemberp->pPort && mcmemberp->pPort->neighbor) { + // add switches that belong to this group + if (mcmemberp->pPort->neighbor->nodep->NodeInfo.NodeType == STL_NODE_SW) { + NodeData *groupswitch = mcmemberp->pPort->neighbor->nodep; + uint8 switchentryport = mcmemberp->pPort->neighbor->PortNum; + if (FSUCCESS != AddEdgeSwitchToGroup(fabricp, mcgmemberp, groupswitch, switchentryport)) { + IXmlParserPrintError(state, "No switch found for MC Group\n"); + return; + } + } + } + mcgmemberp->NumOfMembers++; + } + + return; +} + +static void McPGIDXmlParserEnd(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + McMemberData *mcmemberp = (McMemberData*)object; + uint64 pgid[2]; + + if (! valid) //missing mandatory fields + return; + + if (FSUCCESS != StringToGid(&pgid[0], &pgid[1], content, NULL, TRUE)) { + IXmlParserPrintError(state, "Invalid PortGID found in hex string %s\n", content); + return; + } + + mcmemberp->MemberInfo.RID.PortGID.AsReg64s.H=pgid[0]; + mcmemberp->MemberInfo.RID.PortGID.AsReg64s.L=pgid[1]; + + return; +} + +static void McMembershipXmlParserEnd(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + McMemberData *mcmemberp = (McMemberData*)object; + uint8 value; + + if (! IXmlParseUint8(state, content, len, &value)) { + IXmlParserPrintError(state, "Illegal Member type found: (%s)\n", content); + return; + } + + if (value != 0) { + mcmemberp->MemberInfo.JoinFullMember = value & 1; + value = value >> 1; + mcmemberp->MemberInfo.JoinNonMember = value & 1; + value = value >> 1; + mcmemberp->MemberInfo.JoinSendOnlyMember = value & 1; + } + + return; +} + +static void *McgXmlParserStart(IXmlParserState_t *state, void *parent, const char **attr) +{ + McGroupData *mcgmemberp = (McGroupData*)MemoryAllocate2AndClear(sizeof(McGroupData), IBA_MEM_FLAG_PREMPTABLE, MYTAG); + + if (! mcgmemberp) { + IXmlParserPrintError(state, "Unable to allocate memory"); + return NULL; + } + + if ( (!attr | !attr[0]) || (0 != strcmp(attr[0], "id"))) { + IXmlParserPrintError(state, "Missing MGID id"); + MemoryDeallocate(mcgmemberp); + return NULL; + } + ListItemInitState(&mcgmemberp->AllMcGMembersEntry); + QListSetObj(&mcgmemberp->AllMcGMembersEntry, mcgmemberp); + // init LIST of Group members to NULL + QListInitState(&mcgmemberp->AllMcGroupMembers); + if ( !QListInit(&mcgmemberp->AllMcGroupMembers)) { + IXmlParserPrintError(state, "Unable to initialize MCGroup member list"); + MemoryDeallocate(mcgmemberp); + return NULL; + } + + //init list of switches in a group + QListInitState(&mcgmemberp->EdgeSwitchesInGroup); + if ( !QListInit(&mcgmemberp->EdgeSwitchesInGroup)) { + IXmlParserPrintError(state, "Unable to initialize list of switches for the current MC group"); + MemoryDeallocate(mcgmemberp); + return NULL; + } + + //init number of member counters for groups and group members + mcgmemberp->NumOfMembers = 0; + return mcgmemberp; +} + +static void McgXmlParserEnd(IXmlParserState_t *state, const IXML_FIELD *field, + void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + McGroupData *mcgmemberp = (McGroupData*)object; + FabricData_t *fabricp = IXmlParserGetContext(state); + + if (!valid) { // missing mandatory fields + MemoryDeallocate(mcgmemberp); + return; + } + + // TODO is this correct? Should NumOfMcGroups be incremented only if the head McMemberData + // object GID != 0? Should NumOfMcGroups be incremented if there's at least one McMemberData + // object whose GID != 0 in AllMcGroupMembers? + McMemberData *pMCH = (McMemberData *)QListObj(QListHead(&mcgmemberp->AllMcGroupMembers)); + if ((pMCH->MemberInfo.RID.PortGID.AsReg64s.H !=0) || (pMCH->MemberInfo.RID.PortGID.AsReg64s.L != 0)) + fabricp->NumOfMcGroups++; + // insert mcmember in the fabric structure + QListInsertTail(&fabricp->AllMcGroups, &mcgmemberp->AllMcGMembersEntry); + return; +} + +static void GIDXmlOutput(IXmlOutputState_t *state, void *data) +{ + IXmlOutputPrint(state, " id=\"0x%016"PRIx64":0x%016"PRIx64"\"", + ((IB_GID*)data)->AsReg64s.H, + ((IB_GID*)data)->AsReg64s.L); +} + +static void McMembershipXmlOutput(IXmlOutputState_t *state, const char* tag, void *data) +{ + McMemberData *pMcMemberRecord = (McMemberData *)data; + uint8 Memberstatus; + + Memberstatus = (pMcMemberRecord->MemberInfo.JoinSendOnlyMember<<2 | + pMcMemberRecord->MemberInfo.JoinNonMember<<1 | + pMcMemberRecord->MemberInfo.JoinFullMember); + + IXmlOutputUint(state, tag, Memberstatus); +} + + +static void McGroupDataXmlOutput(IXmlOutputState_t *state, McGroupData *pMcGroupRecord) +{ + IXmlOutputGID(state, "MGID", &pMcGroupRecord->MGID ); + IXmlOutputLIDValue(state, "MLID", pMcGroupRecord->MLID); + IXmlOutputPKey(state, "P_Key", &pMcGroupRecord->GroupInfo.P_Key); + IXmlOutputUint(state, "Mtu", GetBytesFromMtu(pMcGroupRecord->GroupInfo.Mtu)); + IXmlOutputRateValue(state, "Rate", pMcGroupRecord->GroupInfo.Rate); + IXmlOutputTimeoutMultValue(state, "PktLifeTime", pMcGroupRecord->GroupInfo.PktLifeTime); + IXmlOutputHexPad32(state, "Q_Key", pMcGroupRecord->GroupInfo.Q_Key); + IXmlOutputHex(state, "SL", pMcGroupRecord->GroupInfo.u1.s.SL); + IXmlOutputHex(state, "HopLimit", pMcGroupRecord->GroupInfo.u1.s.HopLimit); + IXmlOutputHex(state, "FlowLabel", pMcGroupRecord->GroupInfo.u1.s.FlowLabel); + IXmlOutputHexPad8(state, "TClass", pMcGroupRecord->GroupInfo.TClass); +} + +static void McGroupMemberXmlOutput(IXmlOutputState_t *state, const char *tag, void *data) +{ + McGroupData *pMcGroupRecord = (McGroupData *)data; + McMemberData *mcmemberp; + LIST_ITEM *p; + + IXmlOutputStartAttrTag(state, tag, &pMcGroupRecord->MGID, GIDXmlOutput); + p=QListHead(&pMcGroupRecord->AllMcGroupMembers); + McGroupDataXmlOutput(state, pMcGroupRecord); + + for (p=QListHead(&pMcGroupRecord->AllMcGroupMembers); p != NULL; p = QListNext(&pMcGroupRecord->AllMcGroupMembers, p)) { + mcmemberp = (McMemberData *)QListObj(p); + IXmlOutputStartAttrTag(state, "PortGID", &mcmemberp->MemberInfo.RID.PortGID, GIDXmlOutput); + IXmlOutputGID(state,"GID",&mcmemberp->MemberInfo.RID.PortGID ); + McMembershipXmlOutput(state, "Membership_Int", mcmemberp); + IXmlOutputEndTag(state,"PortGID"); + } + IXmlOutputEndTag(state,tag); +} + +static IXML_FIELD McPortGIDFields[] = { + { tag:"GID", format:'k', end_func:McPGIDXmlParserEnd }, + { tag:"Membership_Int", format:'k', end_func:McMembershipXmlParserEnd}, + { NULL}, +}; + +static IXML_FIELD McgFields[] = { +{ tag:"MGID", format:'k', end_func: McgMGIDXmlParserEnd }, +{ tag:"MLID", format:'h', end_func: McgMLIDXmlParserEnd }, +{ tag:"P_Key", format:'h', IXML_FIELD_INFO(McGroupData, GroupInfo.P_Key), format_func:IXmlOutputPKey}, +{ tag:"Rate_Int", format:'k', end_func: McgMCRateXmlParserEnd_Int }, +{ tag:"Mtu", format: 'h', end_func:McgMtuXmlParserEnd }, +{ tag:"PktLifeTime_Int", format:'h', end_func:McgPktLifeTimeXmlParserEnd }, +{ tag:"Q_Key", format:'h', IXML_FIELD_INFO(McGroupData, GroupInfo.Q_Key) }, +{ tag:"SL", format:'h', end_func: McgSLXmlParserEnd }, +{ tag:"HopLimit", format:'h', end_func: McgHopLimitXmlParserEnd }, +{ tag:"FlowLabel", format:'h', end_func: McgFlowLabelXmlParserEnd }, +{ tag:"TClass", format:'h', IXML_FIELD_INFO(McGroupData, GroupInfo.TClass) }, +{ tag:"PortGID", format:'k', subfields:McPortGIDFields, start_func:McPortGIDXmlParserStart, end_func:McPortGIDXmlParserEnd }, +{ NULL } +}; + + +static IXML_FIELD MulticastFields[] = { + { tag:"MulticastGroup", format:'k', subfields:McgFields, start_func:McgXmlParserStart, end_func:McgXmlParserEnd }, // structure + { NULL } +}; + + +static void PortDataXmlOutputDownReason(IXmlOutputState_t *state, const char *tag, void *data) +{ + IXmlOutputDownReasonValue(state, tag, ((STL_LINKDOWN_REASON *)data)->LinkDownReason); +} +static void PortDataXmlParserEndDownReason(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + uint8 value; + + if (IXmlParseUint8(state, content, len, &value)) + ((STL_LINKDOWN_REASON *)object)->LinkDownReason = value; +} +static void PortDataXmlOutputNeighborDownReason(IXmlOutputState_t *state, const char *tag, void *data) +{ + IXmlOutputDownReasonValue(state, tag, ((STL_LINKDOWN_REASON *)data)->NeighborLinkDownReason); +} +static void PortDataXmlParserEndNeighborDownReason(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + uint8 value; + + if (IXmlParseUint8(state, content, len, &value)) + ((STL_LINKDOWN_REASON *)object)->NeighborLinkDownReason = value; +} + +// LinkDownReasonLog +static IXML_FIELD LDRLogFields[] = { + { tag:"LinkDownReason", format:'k', format_func:PortDataXmlOutputDownReason, end_func:IXmlParserEndNoop }, + { tag:"LinkDownReason_Int", format:'K', format_func:IXmlOutputNoop, end_func:PortDataXmlParserEndDownReason }, + { tag:"NeighborLinkDownReason", format:'k', format_func:PortDataXmlOutputNeighborDownReason, end_func:IXmlParserEndNoop }, + { tag:"NeighborLinkDownReason_Int", format:'K', format_func:IXmlOutputNoop, end_func:PortDataXmlParserEndNeighborDownReason }, + { tag:"Timestamp", format:'U', IXML_FIELD_INFO(STL_LINKDOWN_REASON, Timestamp) }, + { NULL } +}; + +static void LDRLogEntryXmlFormatAttr(IXmlOutputState_t *state, void *data) +{ + IXmlOutputPrint(state, " idx=\"%d\"", *(int *)data); +} +static void PortDataXmlOutputLDRLog(IXmlOutputState_t *state, const char *tag, void *data) +{ + PortData *portp = (PortData *)data; // data points to PortData + + int i; + for (i = 0; i < STL_NUM_LINKDOWN_REASONS; ++i) { + STL_LINKDOWN_REASON *ldr = &portp->LinkDownReasons[i]; + + if (ldr->Timestamp) { + IXmlOutputStartAttrTag(state, tag, &i, LDRLogEntryXmlFormatAttr); + + IXmlOutputStrUint(state, "LinkDownReason", + StlLinkDownReasonToText(ldr->LinkDownReason), ldr->LinkDownReason); + IXmlOutputStrUint(state, "NeighborLinkDownReason", + StlLinkDownReasonToText(ldr->NeighborLinkDownReason), ldr->NeighborLinkDownReason); + + IXmlOutputUint64(state, "Timestamp", ldr->Timestamp); + + IXmlOutputEndTag(state, tag); + } + } +} + +static void *LDRLogXmlParserStart(IXmlParserState_t *state, void *parent, const char **attr) +{ + PortData *pdata = (PortData *)parent; + int idx = -1; + + if (attr == NULL) { + IXmlParserPrintError(state, "Failed to parse idx Attribute"); + return NULL; + } + + int i = 0; + while (attr[i]) { + if (!strcmp("idx", attr[i]) && attr[i+1] != NULL) { + if (attr[i + 1][1] == '\0') { + idx = attr[i + 1][0] - '0'; + if (idx >= 0 && idx < STL_NUM_LINKDOWN_REASONS) { + return &pdata->LinkDownReasons[idx]; + } + } + } + i++; + } + + IXmlParserPrintError(state, "Failed to parse idx Attribute: %d", idx); + return NULL; +} +static void LDRLogXmlParserEnd(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + return; +} +/** ========================================================================= + * PortData definitions + */ +static IXML_FIELD PortDataFields[] = { + { tag:"PortNum", format:'U', IXML_FIELD_INFO(PortData, PortNum) }, + { tag:"GUID", format:'H', IXML_FIELD_INFO(PortData, PortGUID) }, + { tag:"EndPortLID", format:'K', format_func:PortDataXmlOutputEndPortLID, end_func:PortDataXmlParserEndEndPortLID }, // bitfield + { tag:"M_Key", format:'H', IXML_FIELD_INFO(PortData, PortInfo.M_Key) }, + { tag:"SubnetPrefix", format:'H', IXML_FIELD_INFO(PortData, PortInfo.SubnetPrefix) }, + { tag:"LID", format:'H', IXML_FIELD_INFO(PortData, PortInfo.LID) }, + { tag:"SMLID", format:'H', IXML_FIELD_INFO(PortData, PortInfo.MasterSMLID) }, + { tag:"IPAddrIPV6", format:'k', format_func:IXmlOutputIPAddrIPV6, IXML_FIELD_INFO(PortData, PortInfo.IPAddrIPV6.addr), end_func:IXmlParserEndIPAddrIPV6}, + { tag:"IPAddrIPV4", format:'k', format_func:IXmlOutputIPAddrIPV4, IXML_FIELD_INFO(PortData, PortInfo.IPAddrIPV4.addr), end_func:IXmlParserEndIPAddrIPV4}, + { tag:"CapabilityMask", format:'H', IXML_FIELD_INFO(PortData, PortInfo.CapabilityMask.AsReg32) }, + { tag:"CapabilityMask3", format:'H', IXML_FIELD_INFO(PortData, PortInfo.CapabilityMask3.AsReg16) }, + { tag:"DiagCode", format:'H', IXML_FIELD_INFO(PortData, PortInfo.DiagCode.AsReg16) }, + { tag:"Lease", format:'U', IXML_FIELD_INFO(PortData, PortInfo.M_KeyLeasePeriod) }, + { tag:"PortState", format:'k', format_func: PortDataXmlOutputPortState, end_func:IXmlParserEndNoop }, // output only bitfield + { tag:"PortState_Int", format:'K', format_func: IXmlOutputNoop, end_func:PortDataXmlParserEndPortState }, // input only bitfield + { tag:"InitReason", format:'k', format_func: PortDataXmlOutputInitReason, end_func:IXmlParserEndNoop }, + { tag:"InitReason_Int", format:'K', format_func: IXmlOutputNoop, end_func:PortDataXmlParserEndInitReason }, + { tag:"PhysState", format:'k', format_func: PortDataXmlOutputPhysState, end_func:IXmlParserEndNoop }, // output only bitfield + { tag:"PhysState_Int", format:'K', format_func: IXmlOutputNoop, end_func:PortDataXmlParserEndPhysState }, // input only bitfield + { tag:"PortType", format:'k', format_func:PortDataXmlOutputPortPhysConfig, end_func:IXmlParserEndNoop }, + { tag:"PortType_Int", format:'H', IXML_FIELD_INFO(PortData, PortInfo.PortPhysConfig.AsReg8)}, + { tag:"LMC", format:'K', format_func:PortDataXmlOutputLMC, end_func:PortDataXmlParserEndLMC }, // bitfield + { tag:"Protect", format:'k', format_func: PortDataXmlOutputMKeyProtect, end_func:IXmlParserEndNoop }, // output only bitfield + { tag:"Protect_Int", format:'K', format_func: IXmlOutputNoop, end_func:PortDataXmlParserEndMKeyProtect }, // input only bitfield + { tag:"LinkWidthEnabled", format:'k', format_func: PortDataXmlOutputLinkWidthEnabled, end_func:IXmlParserEndNoop }, // output only + { tag:"LinkWidthEnabled_Int", format:'U', format_func: IXmlOutputNoop, IXML_FIELD_INFO(PortData, PortInfo.LinkWidth.Enabled) }, // input only + { tag:"LinkWidthSupported", format:'k', format_func: PortDataXmlOutputLinkWidthSupported, end_func:IXmlParserEndNoop }, // output only bitfield + { tag:"LinkWidthSupported_Int", format:'U', format_func: IXmlOutputNoop, IXML_FIELD_INFO(PortData, PortInfo.LinkWidth.Supported) }, // input only + { tag:"LinkWidthActive", format:'k', format_func: PortDataXmlOutputLinkWidthActive, end_func:IXmlParserEndNoop }, // output only bitfield + { tag:"LinkWidthActive_Int", format:'U', format_func: IXmlOutputNoop, IXML_FIELD_INFO(PortData, PortInfo.LinkWidth.Active) }, // input only + { tag:"LinkWidthDowngradeEnabled", format:'k', format_func: PortDataXmlOutputLinkWidthDowngradeEnabled, end_func:IXmlParserEndNoop }, // output only + { tag:"LinkWidthDowngradeEnabled_Int", format:'U', format_func: IXmlOutputNoop, IXML_FIELD_INFO(PortData, PortInfo.LinkWidthDowngrade.Enabled) }, // input only + { tag:"LinkWidthDowngradeSupported", format:'k', format_func: PortDataXmlOutputLinkWidthDowngradeSupported, end_func:IXmlParserEndNoop }, // output only bitfield + { tag:"LinkWidthDowngradeSupported_Int", format:'U', format_func: IXmlOutputNoop, IXML_FIELD_INFO(PortData, PortInfo.LinkWidthDowngrade.Supported) }, // input only + { tag:"LinkWidthDowngradeTxActive", format:'k', format_func: PortDataXmlOutputLinkWidthDowngradeTxActive, end_func:IXmlParserEndNoop }, // output only bitfield + { tag:"LinkWidthDowngradeTxActive_Int", format:'U', format_func: IXmlOutputNoop, IXML_FIELD_INFO(PortData, PortInfo.LinkWidthDowngrade.TxActive) }, // input only + { tag:"LinkWidthDowngradeRxActive", format:'k', format_func: PortDataXmlOutputLinkWidthDowngradeRxActive, end_func:IXmlParserEndNoop }, // output only bitfield + { tag:"LinkWidthDowngradeRxActive_Int", format:'U', format_func: IXmlOutputNoop, IXML_FIELD_INFO(PortData, PortInfo.LinkWidthDowngrade.RxActive) }, // input only + + { tag:"PortPacketFormatsSupported", format:'u', IXML_FIELD_INFO(PortData, PortInfo.PortPacketFormats.Supported) }, + { tag:"PortPacketFormatsEnabled", format:'u', IXML_FIELD_INFO(PortData, PortInfo.PortPacketFormats.Enabled) }, + + // PortLinkMode is a union of sub-byte fields; if more than one way of inputting PortLinkMode is provided, code should check that only one is used + { tag:"PortLinkMode_Int", format:'U', IXML_FIELD_INFO(PortData, PortInfo.PortLinkMode.AsReg16) }, + { tag:"LinkSpeedEnabled", format:'k', format_func: PortDataXmlOutputLinkSpeedEnabled, end_func:IXmlParserEndNoop }, // output only bitfield + { tag:"LinkSpeedEnabled_Int", format:'K', format_func: IXmlOutputNoop, end_func:PortDataXmlParserEndLinkSpeedEnabled }, // input only bitfield + { tag:"LinkSpeedSupported", format:'k', format_func: PortDataXmlOutputLinkSpeedSupported, end_func:IXmlParserEndNoop }, // output only bitfield + { tag:"LinkSpeedSupported_Int", format:'K', format_func: IXmlOutputNoop, end_func:PortDataXmlParserEndLinkSpeedSupported }, // input only bitfield + { tag:"LinkSpeedActive", format:'k', format_func: PortDataXmlOutputLinkSpeedActive, end_func:IXmlParserEndNoop }, // output only bitfield + { tag:"LinkSpeedActive_Int", format:'K', format_func: IXmlOutputNoop, end_func:PortDataXmlParserEndLinkSpeedActive }, // input only bitfield + { tag:"MTUs", format:'K', format_func:PortDataXmlOutputMTUs, subfields:PortDataMTUActiveXmlFields }, // bitfield(s) + { tag:"MTUSupported", format:'K', format_func:PortDataXmlOutputMTUSupported, end_func:PortDataXmlParserEndMTUSupported }, // bitfield + { tag:"SMSL", format:'K', format_func:PortDataXmlOutputSMSL, end_func:PortDataXmlParserEndSMSL }, // bitfield + { tag:"VLsActive", format:'k', format_func: PortDataXmlOutputVLsActive, end_func:IXmlParserEndNoop }, // output only bitfield + { tag:"VLsActive_Int", format:'K', format_func: IXmlOutputNoop, end_func:PortDataXmlParserEndVLsActive }, // input only bitfield + { tag:"VLsSupported", format:'k', format_func: PortDataXmlOutputVLsSupported, end_func:IXmlParserEndNoop }, // output only bitfield + { tag:"VLsSupported_Int", format:'K', format_func: IXmlOutputNoop, end_func:PortDataXmlParserEndVLsSupported }, // input only bitfield + { tag:"VLArbHighLimit", format:'U', IXML_FIELD_INFO(PortData, PortInfo.VL.HighLimit) }, + { tag:"VLArbHighCap", format:'U', IXML_FIELD_INFO(PortData, PortInfo.VL.ArbitrationHighCap) }, + { tag:"VLArbLowCap", format:'U', IXML_FIELD_INFO(PortData, PortInfo.VL.ArbitrationLowCap) }, + { tag:"VLPreemptingLimit", format:'u', IXML_FIELD_INFO(PortData, PortInfo.VL.PreemptingLimit) }, + { tag:"VLPreemptCap", format:'u', IXML_FIELD_INFO(PortData, PortInfo.VL.PreemptCap) }, + { tag:"VLStalls", format:'K', format_func:PortDataXmlOutputVLStalls, subfields:PortDataVLStallXmlFields }, + { tag:"VLFlowControlDisabledMask", format:'H', IXML_FIELD_INFO(PortData,PortInfo.FlowControlMask) }, + { tag:"MulticastMask", format:'k', format_func:PortDataXmlOutputMulticastMask, end_func:PortDataXmlParserEndMulticastMask }, // bitfield + { tag:"CollectiveMask", format:'k', format_func:PortDataXmlOutputCollectiveMask, end_func:PortDataXmlParserEndCollectiveMask }, // bitfield + { tag:"HoQLifes", format:'K', format_func:PortDataXmlOutputHoQLifes, subfields:PortDataHoQLifeXmlFields }, + { tag:"P_KeyEnforcementInbound", format:'k', format_func: PortDataXmlOutputP_KeyEnforcementInbound, end_func:IXmlParserEndNoop }, // output only bitfield + { tag:"P_KeyEnforcementInbound_Int", format:'K', format_func: IXmlOutputNoop, end_func:PortDataXmlParserEndP_KeyEnforcementInbound }, // input only bitfield + { tag:"P_KeyEnforcementOutbound", format:'k', format_func: PortDataXmlOutputP_KeyEnforcementOutbound, end_func:IXmlParserEndNoop }, // output only bitfield + { tag:"P_KeyEnforcementOutbound_Int", format:'K', format_func: IXmlOutputNoop, end_func:PortDataXmlParserEndP_KeyEnforcementOutbound }, // input only bitfield + { tag:"ViolationsM_Key", format:'U', IXML_FIELD_INFO(PortData, PortInfo.Violations.M_Key) }, + { tag:"ViolationsP_Key", format:'U', IXML_FIELD_INFO(PortData, PortInfo.Violations.P_Key) }, + { tag:"ViolationsQ_Key", format:'U', IXML_FIELD_INFO(PortData, PortInfo.Violations.Q_Key) }, + { tag:"BufferUnits", format:'x', IXML_FIELD_INFO(PortData, PortInfo.BufferUnits.AsReg32) }, // bitfield + { tag:"OverallBufferSpace", format:'U', IXML_FIELD_INFO(PortData, PortInfo.OverallBufferSpace) }, + { tag:"ReplayDepthBufferH", format:'u', IXML_FIELD_INFO(PortData, PortInfo.ReplayDepthH.BufferDepthH) }, + { tag:"ReplayDepthWireH", format:'u', IXML_FIELD_INFO(PortData, PortInfo.ReplayDepthH.WireDepthH) }, + { tag:"ReplayDepthBuffer", format:'U', IXML_FIELD_INFO(PortData, PortInfo.ReplayDepth.BufferDepth) }, + { tag:"ReplayDepthWire", format:'U', IXML_FIELD_INFO(PortData, PortInfo.ReplayDepth.WireDepth) }, + { tag:"SubnetTimeout", format:'k', format_func: PortDataXmlOutputSubnetTimeout, end_func:IXmlParserEndNoop }, // output only bitfield + { tag:"SubnetTimeout_Int", format:'K', format_func: IXmlOutputNoop, end_func:PortDataXmlParserEndSubnetTimeout }, // input only bitfield + { tag:"RespTimeout", format:'k', format_func: PortDataXmlOutputRespTimeout, end_func:IXmlParserEndNoop }, // output only bitfield + { tag:"RespTimeout_Int", format:'K', format_func: IXmlOutputNoop, end_func:PortDataXmlParserEndRespTimeout }, // input only bitfield + { tag:"SLtoSCMap", format:'k', format_func:PortDataXmlOutputSLtoSCMap, subfields:SLtoSCMapSCFields, start_func:SLtoSCMapXmlParserStart, end_func:SLtoSCMapXmlParserEnd }, // structure + { tag:"SCtoSLMap", format:'k', format_func:PortDataXmlOutputSCtoSLMap, subfields:SCtoSLMapSLFields, start_func:SCtoSLMapXmlParserStart, end_func:SCtoSLMapXmlParserEnd }, // structure + { tag:"SCtoSCMap", format:'k', format_func:PortDataXmlOutputSCtoSCMap, subfields:SCtoSCMapOutPortFields, start_func:SCtoSCMapXmlParserStart, end_func:SCtoSCMapXmlParserEnd }, // structure + { tag:"SCtoVLrMap", format:'k', format_func:PortDataXmlOutputSCtoVLrMap, subfields:SCtoVLrMapVLrFields, start_func:SCtoVLrMapXmlParserStart, end_func:SCtoVLxMapXmlParserEnd }, // structure + { tag:"SCtoVLtMap", format:'k', format_func:PortDataXmlOutputSCtoVLtMap, subfields:SCtoVLtMapVLtFields, start_func:SCtoVLtMapXmlParserStart, end_func:SCtoVLxMapXmlParserEnd }, // structure + { tag:"SCtoVLntMap", format:'k', format_func:PortDataXmlOutputSCtoVLntMap, subfields:SCtoVLntMapVLntFields, start_func:SCtoVLntMapXmlParserStart, end_func:SCtoVLxMapXmlParserEnd }, // structure + { tag:"BufferControlTable", format:'k', format_func:PortDataXmlOutputBCT, subfields:BufferControlTableFields, start_func:BCTXmlParserStart }, // structure + { tag:"VLArbitrationLow", format:'k', format_func:PortDataXmlOutputVLArbLow, subfields:VLArbFields, start_func:VLArbLowXmlParserStart, end_func:VLArbLowXmlParserEnd }, // structure + { tag:"VLArbitrationHigh", format:'k', format_func:PortDataXmlOutputVLArbHigh, subfields:VLArbFields, start_func:VLArbHighXmlParserStart, end_func:VLArbHighXmlParserEnd }, // structure + { tag:"VLArbitrationPreemptElements", format:'k', format_func:PortDataXmlOutputVLArbPreemptElements, subfields:VLArbFields, start_func:VLArbPreemptElementsXmlParserStart, end_func:VLArbPreemptElementsXmlParserEnd }, + { tag:"VLArbitrationPreemptMatrix", format:'k', format_func:PortDataXmlOutputVLArbPreemptMatrix, subfields:VLArbPreemptMatrixFields, start_func:VLArbPreemptMatrixXmlParserStart, end_func:VLArbPreemptMatrixXmlParserEnd }, + { tag:"PKeyTable", format:'k', format_func:PortDataXmlOutputPKeyTable, subfields:PKeyTableFields, start_func:PKeyTableXmlParserStart, end_func:PKeyTableXmlParserEnd }, // structure + { tag:"PortStatus", format:'k', size:sizeof(STL_PORT_COUNTERS_DATA), format_func:PortDataXmlOutputPortStatusData, subfields:PortStatusDataFields, start_func:IXmlParserStartStruct, end_func:PortStatusDataXmlParserEnd }, // structure + { tag:"CableInfo", format:'k', size:128, format_func:PortDataXmlOutputCableInfo, subfields:(IXML_FIELD*)CableInfoFields, start_func:CableInfoXmlParserStart}, + { tag:"LocalPortNum", format:'u', IXML_FIELD_INFO(PortData, PortInfo.LocalPortNum) }, + { tag:"PortStates", format:'h', IXML_FIELD_INFO(PortData, PortInfo.PortStates.AsReg32) }, + { tag:"SMTrapQP", format:'h', IXML_FIELD_INFO(PortData, PortInfo.SM_TrapQP.AsReg32) }, + { tag:"SAQP", format:'h', IXML_FIELD_INFO(PortData, PortInfo.SA_QP.AsReg32) }, + { tag:"PortNeighborMode", format:'h', IXML_FIELD_INFO(PortData, PortInfo.PortNeighborMode) }, + { tag:"PortMode", format:'h', IXML_FIELD_INFO(PortData, PortInfo.PortMode.AsReg16) }, + { tag:"PortErrorAction", format:'h', IXML_FIELD_INFO(PortData, PortInfo.PortErrorAction.AsReg32) }, + { tag:"FlitControl", format:'k', format_func:PortDataXmlOutputFlitControl, subfields:PortDataFlitControlXmlFields, start_func:PortDataXmlParserStartFlitControl, end_func:IXmlParserEndNoop }, + { tag:"NeighborNodeGUID", format:'h', IXML_FIELD_INFO(PortData, PortInfo.NeighborNodeGUID) }, + { tag:"NeighborMTU", format:'k', format_func:PortDataXmlOutputNeighborMTU, start_func:PortDataXmlParserStartNeighborMtu, end_func:PortDataXmlParserEndNeighborMtu }, + { tag:"PKey_8B", format:'h', IXML_FIELD_INFO(PortData, PortInfo.P_Keys.P_Key_8B) }, + { tag:"PKey_10B", format:'h', IXML_FIELD_INFO(PortData, PortInfo.P_Keys.P_Key_10B) }, + { tag:"PortLTPCRCMode_Int", format:'u', IXML_FIELD_INFO(PortData, PortInfo.PortLTPCRCMode.AsReg16) }, + { tag:"VLArbCap_Int", format:'u', IXML_FIELD_INFO(PortData, PortInfo.VL.ArbitrationHighCap) }, + { tag:"NeighborPortNum", format:'u', IXML_FIELD_INFO(PortData, PortInfo.NeighborPortNum) }, + { tag:"LinkDownReason_Int", format:'u', IXML_FIELD_INFO(PortData, PortInfo.LinkDownReason) }, + { tag:"NeighborLinkDownReason_Int", format:'u', IXML_FIELD_INFO(PortData, PortInfo.NeighborLinkDownReason) }, + { tag:"PassThroughControlEgressPort", format:'u', IXML_FIELD_INFO(PortData, PortInfo.PassThroughControl.EgressPort) }, + { tag:"SubnetClientReregister_Int", format:'k', format_func:PortDataXmlOutputSubnetClientReregister, end_func:PortDataXmlParserEndSubnetClientReregister }, + { tag:"SubnetMulticastPKeyTrapSuppressionEnabled_Int", format:'u', format_func:PortDataXmlOutputSubnetMulticastPKeyTrapSuppressionEnabled, end_func:PortDataXmlParserEndSubnetMulticastPKeyTrapSuppressionEnabled }, + { tag:"PassThroughControlDRControl_Int", format:'k', format_func:PortDataXmlOutputPassThroughControlDRControl, end_func:PortDataXmlParserEndPassThroughControlDRControl }, + { tag:"HFICongestionControlTableIndexLimit", format:'h', IXML_FIELD_INFO(PortData, CCTI_Limit) }, + { tag:"HFICongestionControlTable", format:'k', format_func:PortDataXmlOutputHFICCT, subfields:(IXML_FIELD*)HFICCTFields, start_func:HFICCTXmlParserStart}, + { tag:"BundleNextPort", format:'u', IXML_FIELD_INFO(PortData, PortInfo.BundleNextPort) }, + { tag:"BundleLane", format:'u', IXML_FIELD_INFO(PortData, PortInfo.BundleLane) }, + { tag:"LinkDownReasonLog", format:'k', format_func:PortDataXmlOutputLDRLog, subfields:LDRLogFields, start_func:LDRLogXmlParserStart, end_func:LDRLogXmlParserEnd }, // structure + { NULL } +}; + +static void PortDataXmlOutput(IXmlOutputState_t *state, const char *tag, void *data) +{ + IXmlOutputStruct(state, tag, (PortData*)data, PortDataXmlFormatAttr, PortDataFields); +} + +static void *PortDataXmlParserStart(IXmlParserState_t *state, void *parent, const char **attr) +{ + PortData *portp = (PortData*)MemoryAllocate2AndClear(sizeof(PortData), IBA_MEM_FLAG_PREMPTABLE, MYTAG); + + if (! portp) { + IXmlParserPrintError(state, "Unable to allocate memory"); + return NULL; + } + + ListItemInitState(&portp->AllPortsEntry); + QListSetObj(&portp->AllPortsEntry, portp); + portp->nodep = (NodeData *)parent; + //printf("portp=%p, nodep=%p\n", portp, portp->nodep); + + return portp; +} + +static int Snapshot_PortDataComplete(IXmlParserState_t * state, void * object, void * parent); +static ParseCompleteFn portDataCompleteFn = Snapshot_PortDataComplete; + +void SetPortDataComplete(ParseCompleteFn fn) +{ + portDataCompleteFn = fn; +} + +static ParseCompleteFn GetPortDataComplete() +{ + return portDataCompleteFn; +} + +/** + "Destructors" for some topology structs. + + They do not free the targets, only their members. +*/ +void Snapshot_PortDataFree(PortData * portp, FabricData_t * fabricp); +void Snapshot_NodeDataFree(NodeData * nodep, FabricData_t * fabricp); + +/** + Completion handler for PortData inside a snapshot. +*/ +static int Snapshot_PortDataComplete(IXmlParserState_t * state, void * object, void * parent) +{ + const IXML_FIELD *p; + unsigned int i; + PortData *portp = (PortData*)object; + NodeData *nodep = portp->nodep; + FabricData_t *fabricp = IXmlParserGetContext(state); + + ASSERT(nodep == (NodeData*)parent); + + // technically could preceed within + if (nodep->NodeInfo.NodeType == STL_NODE_SW) { + // a switch only gets 1 port Guid, we save it for switch + // port 0 (the "virtual management port") + // should not have PortGUID if PortNum != 0 + if (portp->PortGUID && portp->PortNum != 0) { + IXmlParserPrintError(state, "Invalid fields in Port: PortGUID not allowed for Switch port!=0"); + return FERROR; + } + } else { + portp->PortInfo.LocalPortNum = portp->PortNum ; + // should have PortGUID + if (portp->PortGUID == 0 || portp->PortNum == 0) { + IXmlParserPrintError(state, "Invalid/missing fields in Port, PortGUID required for non-Switch"); + return FERROR; + } + } + + if (cl_qmap_insert(&nodep->Ports, portp->PortNum, &portp->NodePortsEntry) != &portp->NodePortsEntry) + { + IXmlParserPrintError(state, "Duplicate PortNum: %u", portp->PortNum); + goto failinsert2; + } + if (FSUCCESS != AllLidsAdd(fabricp, portp, FALSE)) + { + IXmlParserPrintError(state, "Duplicate LIDs found in portRecords: LID 0x%x Port %u Node: %.*s\n", + portp->EndPortLID, + portp->PortNum, STL_NODE_DESCRIPTION_ARRAY_SIZE, + (char*)nodep->NodeDesc.NodeString); + goto failinsert2; + } + + // Handling to deal with fields not defined in STL Gen 1, but required in Gen 2. Allows forward compatability + // of snapshots. + for (p=state->current.subfields,i=0; p->tag != NULL; ++i,++p) { + if (strcmp(p->tag, "PortPacketFormatsSupported") == 0) { + if (! (state->current.fields_found & ((uint64_t)1)<PortInfo.PortPacketFormats.Supported = STL_PORT_PACKET_FORMAT_9B; + portp->PortInfo.PortPacketFormats.Enabled = STL_PORT_PACKET_FORMAT_9B; + } + } else if (strcmp(p->tag, "MaxLID") == 0) { + if (! (state->current.fields_found & ((uint64_t)1)<PortInfo.CapabilityMask3.s.IsMAXLIDSupported) { + IXmlParserPrintError(state, "Missing fields in Port, MaxLID required for Gen2 HFI"); + return FERROR; + } + } + } + + return FSUCCESS; + +failinsert2: + cl_qmap_remove_item(&nodep->Ports, &portp->NodePortsEntry); + return FERROR; +} + +static void PortDataXmlParserEnd(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + PortData *portp = (PortData*)object; + FabricData_t *fabricp = IXmlParserGetContext(state); + + ParseCompleteFn parseCompleteFn = GetPortDataComplete(); + + if (! valid) // missing mandatory fields + goto failvalidate; + + portp->rate = StlLinkSpeedWidthToStaticRate( + portp->PortInfo.LinkSpeed.Active, + portp->PortInfo.LinkWidth.Active); + + if (portp->pPortCounters) { + portp->pPortCounters->lq.s.numLanesDown = StlGetNumLanesDown(&portp->PortInfo); + } + + if (parseCompleteFn) { + if (parseCompleteFn(state, object, parent) != FSUCCESS) { + goto failvalidate; + } + } + + QListInsertTail(&fabricp->AllPorts, &portp->AllPortsEntry); + + return; + +failvalidate: + Snapshot_PortDataFree(portp, fabricp); + MemoryDeallocate(portp); +} + +/** + Destructor for @c PortData inside parser. + + Frees members but not port data itself. +*/ +void Snapshot_PortDataFree(PortData * portp, FabricData_t * fabricp) +{ + if (portp->pPortCounters) + MemoryDeallocate(portp->pPortCounters); + PortDataFreeQOSData(fabricp, portp); + PortDataFreePartitionTable(fabricp, portp); +} + +#if !defined(VXWORKS) || defined(BUILD_DMC) +/****************************************************************************/ +/* IocService Input/Output functions */ + +/* most are in ixml_ib */ + +// a better approach would be to allocate a "super structure which includes +// IocData and an extra field after it to count service entries as they +// arrive +static unsigned g_service_index = 0; // this is a hack, not Thread safe + +static void *IocServiceXmlParserStart(IXmlParserState_t *state, void *parent, const char **attr) +{ + IocData *iocp = (IocData*)parent; + + if (! iocp->Services) { + IXmlParserPrintError(state, "Services must follow ServicesCount"); + return NULL; + } + if (g_service_index >= iocp->IocProfile.ServiceEntries) { + IXmlParserPrintError(state, "Number of Services inconsistent with ServicesCount"); + return NULL; + } + return (&iocp->Services[g_service_index]); +} + +static void IocServiceXmlParserEnd(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + if (! valid) // missing mandatory fields + goto failvalidate; + g_service_index++; + return; + +failvalidate: + /* nothing to free, Iocp will take care of Services array */ + return; +} + +/****************************************************************************/ +/* IocData Input/Output functions */ + +static void IocDataXmlFormatAttr(IXmlOutputState_t *state, void *data) +{ + IXmlOutputPrint(state, " id=\"0x%016"PRIx64"\"", ((IocData*)data)->IocProfile.IocGUID); +} + +/* bitfields needs special handling: VendorId */ +static void IocDataXmlOutputVendorId(IXmlOutputState_t *state, const char *tag, void *data) +{ + IXmlOutputHex(state, tag, ((IocData *)data)->IocProfile.ven.v.VendorId); +} + +static void IocDataXmlParserEndVendorId(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + uint32 value; + + if (IXmlParseUint32(state, content, len, &value)) + ((IocData *)object)->IocProfile.ven.v.VendorId = value; +} + +/* bitfields needs special handling: SubSystemVendorId */ +static void IocDataXmlOutputSubSystemVendorId(IXmlOutputState_t *state, const char *tag, void *data) +{ + IXmlOutputHex(state, tag, ((IocData *)data)->IocProfile.sub.s.SubSystemVendorID); +} + +static void IocDataXmlParserEndSubSystemVendorId(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + uint32 value; + + if (IXmlParseUint32(state, content, len, &value)) + ((IocData *)object)->IocProfile.sub.s.SubSystemVendorID = value; +} + +/* this is a cheat, we need to allocate IocData.Services array. + * we depend on ServicesCount preceeding 1st Service entry in XML input + */ +static void IocDataXmlParserEndServicesCount(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + IocData * iocp = (IocData *)object; + + if (IXmlParseUint8(state, content, len, &iocp->IocProfile.ServiceEntries)) { + iocp->Services = (IOC_SERVICE*)MemoryAllocate2AndClear(sizeof(IOC_SERVICE)*iocp->IocProfile.ServiceEntries, IBA_MEM_FLAG_PREMPTABLE, MYTAG); + if (! iocp->Services) { + IXmlParserPrintError(state, "Unable to allocate memory"); + } + } +} + +static void IocDataXmlOutputServices(IXmlOutputState_t *state, const char *tag, void *data) +{ + IocData *iocp = (IocData*)data; + unsigned i; + + IXmlOutputStartAttrTag(state, "Services", NULL, NULL); + for (i=0; i < iocp->IocProfile.ServiceEntries; i++) + IocServiceXmlOutput(state, "Service", &iocp->Services[i]); + IXmlOutputEndTag(state, "Services"); +} + +static IXML_FIELD ServicesFields[] = { + { tag:"Service", format:'k', subfields:IocServiceFields, start_func:IocServiceXmlParserStart, end_func:IocServiceXmlParserEnd }, // structure, only used on input + { NULL } +}; + +static IXML_FIELD IocDataFields[] = { + { tag:"IocSlot", format:'U', IXML_FIELD_INFO(IocData, IocSlot) }, + { tag:"IocGUID", format:'H', IXML_FIELD_INFO(IocData, IocProfile.IocGUID) }, + { tag:"VendorId", format:'K', format_func:IocDataXmlOutputVendorId, end_func:IocDataXmlParserEndVendorId }, // bitfield + { tag:"DeviceId", format:'X', IXML_FIELD_INFO(IocData, IocProfile.DeviceId) }, + { tag:"DeviceVersion", format:'X', IXML_FIELD_INFO(IocData, IocProfile.DeviceVersion) }, + { tag:"SubSystemVendorID", format:'K', format_func:IocDataXmlOutputSubSystemVendorId, end_func:IocDataXmlParserEndSubSystemVendorId }, // bitfield + { tag:"SubSystemID", format:'X', IXML_FIELD_INFO(IocData, IocProfile.SubSystemID) }, + { tag:"IOClass", format:'X', IXML_FIELD_INFO(IocData, IocProfile.IOClass) }, + { tag:"IOSubClass", format:'X', IXML_FIELD_INFO(IocData, IocProfile.IOSubClass) }, + { tag:"Protocol", format:'X', IXML_FIELD_INFO(IocData, IocProfile.Protocol) }, + { tag:"ProtocolVer", format:'X', IXML_FIELD_INFO(IocData, IocProfile.ProtocolVer) }, + { tag:"SendMsgDepth", format:'U', IXML_FIELD_INFO(IocData, IocProfile.SendMsgDepth) }, + { tag:"SendMsgSize", format:'U', IXML_FIELD_INFO(IocData, IocProfile.SendMsgSize) }, + { tag:"RDMAReadDepth", format:'U', IXML_FIELD_INFO(IocData, IocProfile.RDMAReadDepth) }, + { tag:"RDMASize", format:'U', IXML_FIELD_INFO(IocData, IocProfile.RDMASize) }, + { tag:"CapabilityMask", format:'X', IXML_FIELD_INFO(IocData, IocProfile.ccm.CntlCapMask) }, + { tag:"ServicesCount", format:'U', IXML_FIELD_INFO(IocData, IocProfile.ServiceEntries), end_func:IocDataXmlParserEndServicesCount }, + { tag:"IDString", format:'C', IXML_FIELD_INFO(IocData, IocProfile.IDString) }, + { tag:"Services", format:'k', format_func:IocDataXmlOutputServices, subfields:ServicesFields }, // list + { NULL } +}; + +static void IocDataXmlOutput(IXmlOutputState_t *state, const char *tag, void *data) +{ + IXmlOutputStruct(state, tag, (IocData*)data, IocDataXmlFormatAttr, IocDataFields); +} + +static void *IocDataXmlParserStart(IXmlParserState_t *state, void *parent, const char **attr) +{ + IocData *iocp = (IocData*)MemoryAllocate2AndClear(sizeof(IocData), IBA_MEM_FLAG_PREMPTABLE, MYTAG); + + if (! iocp) { + IXmlParserPrintError(state, "Unable to allocate memory"); + return NULL; + } + iocp->ioup = (IouData *)parent; + ListItemInitState(&iocp->IouIocsEntry); + QListSetObj(&iocp->IouIocsEntry, iocp); + + g_service_index = 0; + return iocp; +} + +static void IocDataXmlParserEnd(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + IocData *iocp = (IocData*)object; + IouData *ioup = iocp->ioup; + FabricData_t *fabricp = IXmlParserGetContext(state); + + ASSERT(ioup == (IouData*)parent); + + if (! valid) // missing mandatory fields + goto failvalidate; + + if (cl_qmap_insert(&fabricp->AllIOCs, (uint64_t)iocp, &iocp->AllIOCsEntry) != &iocp->AllIOCsEntry) + { + IXmlParserPrintError(state, "Duplicate IOC Guids found: 0x%016"PRIx64, iocp->IocProfile.IocGUID); + goto failinsert; + } + QListInsertTail(&ioup->Iocs, &iocp->IouIocsEntry); + return; + +failinsert: +failvalidate: + if (iocp->Services) + MemoryDeallocate(iocp->Services); + MemoryDeallocate(iocp); +} + +/****************************************************************************/ +/* IouData Input/Output functions */ + +static void IouDataXmlFormatAttr(IXmlOutputState_t *state, void *data) +{ + IXmlOutputPrint(state, " id=\"0x%016"PRIx64"\"", ((IouData*)data)->nodep->NodeInfo.NodeGUID); +} + +/* bitfields needs special handling: DiagDeviceId */ +static void IouDataXmlOutputDiagDeviceId(IXmlOutputState_t *state, const char *tag, void *data) +{ + IXmlOutputUint(state, tag, ((IouData *)data)->IouInfo.DiagDeviceId); +} + +static void IouDataXmlParserEndDiagDeviceId(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + uint8 value; + + if (IXmlParseUint8(state, content, len, &value)) + ((IouData *)object)->IouInfo.DiagDeviceId = value; +} + +/* bitfields needs special handling: OptionRom */ +static void IouDataXmlOutputOptionRom(IXmlOutputState_t *state, const char *tag, void *data) +{ + IXmlOutputUint(state, tag, ((IouData *)data)->IouInfo.OptionRom); +} + +static void IouDataXmlParserEndOptionRom(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + uint8 value; + + if (IXmlParseUint8(state, content, len, &value)) + ((IouData *)object)->IouInfo.OptionRom = value; +} + +static void IouDataXmlOutputIocs(IXmlOutputState_t *state, const char *tag, void *data) +{ + IouData *ioup = (IouData*)data; + LIST_ITEM *p; + + for (p=QListHead(&ioup->Iocs); p != NULL; p = QListNext(&ioup->Iocs, p)) { + IocDataXmlOutput(state, "Ioc", QListObj(p)); + } +} + +static IXML_FIELD IouDataFields[] = { + { tag:"ChangeID", format:'U', IXML_FIELD_INFO(IouData, IouInfo.Change_ID) }, + { tag:"MaxControllers", format:'U', IXML_FIELD_INFO(IouData, IouInfo.MaxControllers) }, + { tag:"DiagDeviceId", format:'K', format_func:IouDataXmlOutputDiagDeviceId, end_func:IouDataXmlParserEndDiagDeviceId }, // bitfield + { tag:"OptionRom", format:'K', format_func:IouDataXmlOutputOptionRom, end_func:IouDataXmlParserEndOptionRom }, // bitfield + { tag:"Ioc", format:'k', format_func:IouDataXmlOutputIocs, subfields:IocDataFields, start_func:IocDataXmlParserStart, end_func:IocDataXmlParserEnd }, // structures + { NULL } +}; + +static void IouDataXmlOutput(IXmlOutputState_t *state, const char *tag, void *data) +{ + IXmlOutputStruct(state, tag, (IouData*)data, IouDataXmlFormatAttr, IouDataFields); +} + +static void *IouDataXmlParserStart(IXmlParserState_t *state, void *parent, const char **attr) +{ + IouData *ioup = (IouData*)MemoryAllocate2AndClear(sizeof(IouData), IBA_MEM_FLAG_PREMPTABLE, MYTAG); + + if (! ioup) { + IXmlParserPrintError(state, "Unable to allocate memory"); + return NULL; + } + ListItemInitState(&ioup->AllIOUsEntry); + QListSetObj(&ioup->AllIOUsEntry, ioup); + ioup->nodep = (NodeData *)parent; + QListInitState(&ioup->Iocs); + if (! QListInit(&ioup->Iocs)) + { + MemoryDeallocate(ioup); + IXmlParserPrintError(state, "Unable to initialize object"); + return NULL; + } + + return ioup; +} + +static void IouDataXmlParserEnd(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + IouData *ioup = (IouData*)object; + NodeData *nodep = ioup->nodep; + FabricData_t *fabricp = IXmlParserGetContext(state); + + ASSERT(nodep == (NodeData*)parent); + + if (! valid) // missing mandatory fields + goto failvalidate; + + if (nodep->ioup) { + IXmlParserPrintError(state, "More than 1 IOU for Node"); + goto failinsert; + } + nodep->ioup = ioup; + return; + +failinsert: +failvalidate: + IouDataFreeIocs(fabricp, ioup); + MemoryDeallocate(ioup); +} +#endif + +/****************************************************************************/ +/* SwitchInfo Input/Output functions */ + +/* most are in ixml_ib */ + +static void *SwitchInfoXmlParserStart(IXmlParserState_t *state, + void *parent, const char **attr) +{ + void *p = IXmlParserStartStruct(state, parent, attr); + + if (!p) return p; + + STL_SWITCHINFO_RECORD *pSwitchInfo = (STL_SWITCHINFO_RECORD*)p; + // For compatibility with snapshots from older versions of OPA, + // provide default values for optional fields. + pSwitchInfo->SwitchInfoData.PortGroupFDBCap = DEFAULT_MAX_PGFT_LID + 1; + return p; +} + +static void SwitchInfoXmlParserEnd(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + STL_SWITCHINFO_RECORD *pSwitchInfo = (STL_SWITCHINFO_RECORD*)object; + NodeData *nodep = (NodeData*)parent; + + if (! valid) // missing mandatory fields + goto failvalidate; + + if (nodep->pSwitchInfo) { + IXmlParserPrintError(state, "More than 1 SwitchInfo for Node"); + goto failinsert; + } + nodep->pSwitchInfo = pSwitchInfo; + return; + +failinsert: +failvalidate: + MemoryDeallocate(pSwitchInfo); +} + +/****************************************************************************/ +/* SwitchData Input/Output functions */ + +boolean fbFDB = FALSE; // Flag for LinearFDB or MulticastFDB parsed +static uint32 lidFDB = 0xFFFFFFFF; // LID for Linear and PortGroup FDB entries +static uint32 portPGT = 0xFFFFFFFF; // PortGroupNumber for PortGroup Element entry + +// Multicast FDB Value parsing context data +static struct McvParseCtx { + uint32 lid; + uint8 pos; +} mcvParseCtx; + +static void *SwitchDataXmlParserStart(IXmlParserState_t *state, + void *parent, const char **attr) +{ + void *p = IXmlParserStartStruct(state, parent, attr); + if (!p) return p; + + SwitchData *switchp = (SwitchData*)p; + + // For compatibility with snapshots from older versions of OPA, + // provide default values for optional fields. + switchp->PortGroupFDBSize = DEFAULT_MAX_PGFT_LID + 1; + + return p; +} + +static void SwitchDataXmlParserEnd(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + SwitchData *switchp = (SwitchData*)object; + NodeData *nodep = (NodeData*)parent; + + if (! valid) // missing mandatory fields + goto failvalidate; + + if (nodep->switchp) { + IXmlParserPrintError(state, "More than 1 SwitchData for Node"); + goto failinsert; + } + + nodep->switchp = switchp; + + + return; + +failinsert: +failvalidate: + MemoryDeallocate(switchp); +} + +static void SwitchDataOutputLIDAttr(IXmlOutputState_t *state, void *data) +{ + IXmlOutputPrint(state, " LID=\"0x%x\"", *(unsigned int *)data); +} + +static void SwitchDataOutputPortGroupNumberAttr(IXmlOutputState_t *state, void *data) +{ + IXmlOutputPrint(state, " PortGroupNumber=\"%d\"", *(unsigned int *)data); +} + +static void *SwitchDataXmlParserStartLinearValue(IXmlParserState_t *state, void *parent, const char **attr) +{ + SwitchData *switchp = (SwitchData *)parent; // parent points to SwitchData + + // Save Value attribute LID value for use in SwitchDataXmlParserEndLinearValue() + if ( !attr || !attr[0] || 0 != strcmp(attr[0], "LID")) { + IXmlParserPrintError(state, "Missing LID attribute for LinearFDB.Value"); + return NULL; + } + if ( FSUCCESS != StringToUint32(&lidFDB, attr[1], NULL, 0, TRUE) + || lidFDB >= switchp->LinearFDBSize ) { + IXmlParserPrintError(state, "Invalid LID attribute for LinearFDB.Value LID: %s", attr[1]); + return NULL; + } + return ((void *)&lidFDB); +} + +static void SwitchDataXmlParserEndLinearValue(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + uint32 *pLID = (uint32 *)object; // object points to LID + SwitchData *switchp = (SwitchData *)parent; // parent points to SwitchData + uint8 temp; + + if (! valid) + return; + // Assign LinearFDB[LID] = port + if ( !switchp || !switchp->LinearFDB || !pLID || !content || + !len || (*pLID >= switchp->LinearFDBSize) ) { + IXmlParserPrintError(state, "LinearFDB improperly allocated"); + return; + } + + if (FSUCCESS != StringToUint8(&temp, content, NULL, 0, TRUE)) { + IXmlParserPrintError(state, "Invalid Port number in LinearFDB.Value for LID %u Value: %s", *pLID, content); + return; + } + STL_LFT_PORT_BLOCK(switchp->LinearFDB, *pLID) = (PORT)temp; +} + +IXML_FIELD LinearFDBFields[] = { + { tag:"Value", start_func:SwitchDataXmlParserStartLinearValue, end_func:SwitchDataXmlParserEndLinearValue }, + { NULL } +}; + +/** + arrays need special handling: LinearFDB +*/ +static void SwitchDataOutputLinearFDB(IXmlOutputState_t *state, const char *tag, void *data) +{ + unsigned int ix_lid; + SwitchData *switchp = (SwitchData *)data; + PORT *pPort = (PORT *)switchp->LinearFDB; + + IXmlOutputStartTag(state, tag); + + for ( ix_lid = 0; ix_lid < switchp->LinearFDBSize; + pPort++, ix_lid++ ) { + if (*pPort == 0xFF) + continue; + IXmlOutputStartAttrTag(state, "Value", &ix_lid, SwitchDataOutputLIDAttr); + IXmlOutputPrint(state, "%u", *pPort); + IXmlOutputEndTag(state, "Value"); + } + + IXmlOutputEndTag(state, tag); +} + +static void *SwitchDataXmlParserStartLinearFDB(IXmlParserState_t *state, void *parent, const char **attr) +{ + SwitchData *switchp = (SwitchData *)parent; // parent points to SwitchData + STL_LINEAR_FORWARDING_TABLE *pPort; + + // Allocate LinearFDB + if (!switchp || switchp->LinearFDB) { + IXmlParserPrintError(state, "SwitchData improperly allocated"); + return NULL; + } + if ( !( pPort = (STL_LINEAR_FORWARDING_TABLE *)MemoryAllocate2AndClear( //Make sure to allocate a full block of LftBLOCK not just PORTs + ROUNDUP(switchp->LinearFDBSize, MAX_LFT_ELEMENTS_BLOCK), IBA_MEM_FLAG_PREMPTABLE, MYTAG ) ) ) { + IXmlParserPrintError(state, "Unable to allocate memory"); + return NULL; + } + + memset(pPort, 255, ROUNDUP(switchp->LinearFDBSize, MAX_LFT_ELEMENTS_BLOCK) ); //Make sure to memset a full block not just whats used + switchp->LinearFDB = pPort; + fbFDB = TRUE; + return (switchp); +} + +static void SwitchDataXmlParserEndLinearFDB(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + SwitchData *switchp = (SwitchData *)object; + + if (! valid) + goto fail; + + return; + +fail: + if (switchp && switchp->LinearFDB) { + MemoryDeallocate(switchp->LinearFDB); + switchp->LinearFDB = NULL; + } +} + + +static void *SwitchDataXmlParserStartMulticastValue(IXmlParserState_t *state, void *parent, const char **attrs) +{ + SwitchData *switchp = (SwitchData *)parent; // parent points to SwitchData + int i; + int lidParsed = 0; + memset(&mcvParseCtx, 0, sizeof(mcvParseCtx)); + + for (i = 0; attrs && attrs[i] != NULL;) { + uint32 temp; + // Save Value attribute LID value for use in SwitchDataXmlParserEndMulticastValue() + if (strcmp(attrs[i], "LID") == 0) { + if (!attrs[i+1]) { + IXmlParserPrintError(state, "No LID specified for MulticastFDB.Value"); + return NULL; + } + + if (StringToUint32(&temp, attrs[i+1], NULL, 0, TRUE) != FSUCCESS) { + IXmlParserPrintError(state, "Invalid LID attribute for MulticastFDB.Value LID: %s", attrs[i+1]); + return NULL; + } + + if (IS_MCAST16(temp)) + temp = MCAST16_TO_MCAST32(temp); + + if ((temp < STL_LID_MULTICAST_BEGIN) || (temp >= switchp->MulticastFDBSize)) { + IXmlParserPrintError(state, "Invalid LID attribute for MulticastFDB.Value LID: %s", attrs[i+1]); + return NULL; + } + + mcvParseCtx.lid = temp - STL_LID_MULTICAST_BEGIN; + lidParsed = 1; + i += 2; + } else if (strcmp(attrs[i], "pos") == 0) { + if (!attrs[i+1]) { + IXmlParserPrintError(state, "No pos specified for MulticastFDB.Value"); + return NULL; + } + + if (StringToUint32(&temp, attrs[i+1], NULL, 0, TRUE) != FSUCCESS || + temp >= STL_NUM_MFT_POSITIONS_MASK) { + IXmlParserPrintError(state, "Invalid pos attribute for MulticastFDB.Value pos: %s", attrs[i+1]); + return NULL; + } + mcvParseCtx.pos = (uint8)temp; + i += 2; + } else + i++; // TODO print unrecognized attr warning? + } + + if (!lidParsed) { + IXmlParserPrintError(state, "Missing LID attribute for MulticastFDB.Value"); + return NULL; + } + + + return ((void *)&mcvParseCtx); +} + +static void SwitchDataXmlParserEndMulticastValue(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + struct McvParseCtx *ctx = (struct McvParseCtx*) object; + SwitchData *switchp = (SwitchData *)parent; // parent points to SwitchData + STL_PORTMASK *pPortMask; + uint64 portMask; // Port masks up to 64 bits can be input + + if (! valid) + return; + + assert(switchp && switchp->MulticastFDB[0]); + + if (!ctx || !content || !len) { + IXmlParserPrintError(state, "Empty multicast FDB value"); + return; + } + + if (ctx->lid >= switchp->MulticastFDBSize) { + IXmlParserPrintError(state, "Multicast LID exceeds multicast FDB range"); + return; + } + + if (ctx->pos >= STL_NUM_MFT_POSITIONS_MASK) { + IXmlParserPrintError(state, "Unsupported MulticastFDB pos: %u", + ctx->pos); + return; + } + + pPortMask = switchp->MulticastFDB[ctx->pos] + ctx->lid; + + if (FSUCCESS != StringToUint64(&portMask, content, NULL, 0, TRUE)) { + IXmlParserPrintError(state, "Invalid PortMask in MulticastFDB: %s", content); + return; + } + + *pPortMask = (STL_PORTMASK)portMask; +} + +IXML_FIELD MulticastFDBFields[] = { + { tag:"Value", start_func:SwitchDataXmlParserStartMulticastValue, end_func:SwitchDataXmlParserEndMulticastValue }, + { NULL } +}; + +/** + Arrays need special handling: MulticastFDB. + + @param data @c SwitchData * to node of interest. + Assumes that ((SwitchData*)data)->parent is not NULL. +*/ +static void SwitchDataOutputMulticastFDB(IXmlOutputState_t *state, const char *tag, void *data) +{ + STL_LID mcastLid; + SwitchData *switchp = (SwitchData *)data; + uint64 portMask; + + // MulticastFDBTop can be less than STL_LID_MULTICAST_BEGIN at POD. + // May not be an error but then there aren't any Mcast entries to be + // output either. + if ((switchp->MulticastFDBSize <= STL_LID_MULTICAST_BEGIN) || (switchp->MulticastFDBSize > STL_LID_MULTICAST_END + 1)) { + return; + } + + IXmlOutputStartTag(state, tag); + + uint32 i; + for (i = 0; i < STL_NUM_MFT_POSITIONS_MASK; ++i) { + uint32 j; + for (j = 0; j < (switchp->MulticastFDBSize - STL_LID_MULTICAST_BEGIN); ++j) { + portMask = (uint64)switchp->MulticastFDB[i][j]; + + if (!portMask) + continue; + + mcastLid = STL_LID_MULTICAST_BEGIN + j; + + IXmlOutputStartTag(state, "Value"); + IXmlOutputAttrFmt(state, "pos", "%d", i); + IXmlOutputAttrFmt(state, "LID", "0x%x", mcastLid); + IXmlOutputPrint(state, "0x%"PRIx64, portMask); + IXmlOutputEndTag(state, "Value"); + } + } + IXmlOutputEndTag(state, tag); +} + +static void *SwitchDataXmlParserStartMulticastFDB(IXmlParserState_t *state, void *parent, const char **attr) +{ + SwitchData *switchp = (SwitchData *)parent; // parent points to SwitchData + STL_PORTMASK *pPortMask; + size_t allocSize; + uint8_t i; + + // Allocate MulticastFDB + if (!switchp || switchp->MulticastFDB[0]) { + IXmlParserPrintError(state, "SwitchData improperly allocated"); + return NULL; + } + allocSize = switchp->MulticastFDBSize - STL_LID_MULTICAST_BEGIN; + + if ((switchp->MulticastFDBSize <= STL_LID_MULTICAST_BEGIN) || (switchp->MulticastFDBSize > STL_LID_MULTICAST_END + 1)) { + IXmlParserPrintError(state, "Invalid MulticastFDBSize, cannot allocate MulticastFDB"); + return NULL; + } + + for (i = 0; i < STL_NUM_MFT_POSITIONS_MASK; ++i) { + + if ( !( pPortMask = (STL_PORTMASK *)MemoryAllocate2AndClear( + allocSize * sizeof(STL_PORTMASK), IBA_MEM_FLAG_PREMPTABLE, + MYTAG ) ) ) { + IXmlParserPrintError(state, "Unable to allocate memory"); + return NULL; + } + + switchp->MulticastFDB[i] = pPortMask; + } + + + fbFDB = TRUE; + return (switchp); +} + +static void SwitchDataXmlParserEndMulticastFDB(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + SwitchData *switchp = (SwitchData *)object; + + if (! valid) + goto fail; + + return; + +fail: + if (switchp) { + uint8_t i; + for (i = 0; i < STL_NUM_MFT_POSITIONS_MASK; ++i) { + if (switchp->MulticastFDB[i]) { + MemoryDeallocate(switchp->MulticastFDB[i]); + switchp->MulticastFDB[i] = NULL; + } + } + } +} + + +static void *SwitchDataXmlParserStartPortGroupElementsValue(IXmlParserState_t *state, void *parent, const char **attr) +{ + SwitchData *switchp = (SwitchData *)parent; + uint32 temp; + + if (!attr || !attr[0] || 0 != strcmp(attr[0], "PortGroupNumber")) { + IXmlParserPrintError(state, "Missing PortGroupNumber attribute for PortGroupElements.Value"); + return NULL; + } + + // we depend on PortGroupSize preceeding this tag in XML + if (FSUCCESS != StringToUint32(&temp, attr[1], NULL, 0, TRUE) + || temp >= switchp->PortGroupSize) { + + IXmlParserPrintError(state, "Invalid PortGroupNumber attribute for PortGroupElements.Value PortGroupNumber: %s", attr[1]); + return NULL; + } + portPGT = temp; + + return ((void *)&portPGT); +} + +static void SwitchDataXmlParserEndPortGroupElementsValue(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + uint32 portGroupNum = *(uint32 *)object; + SwitchData *switchp = (SwitchData *)parent; + STL_PORTMASK *pPortMask; + uint64 portMask; + + if (!valid) { + return; + } + + assert (switchp && switchp->PortGroupElements); + + if (!content || !len) { + IXmlParserPrintError(state, "Empty PortGroupElements.Value"); + return; + } + + pPortMask = switchp->PortGroupElements + portGroupNum; + + if (FSUCCESS != StringToUint64(&portMask, content, NULL, 0, TRUE)) { + IXmlParserPrintError(state, "invalid PortMask in PortGroupElements.Value for PortGroupNumber %u Value: %s", portGroupNum, content); + return; + } + *pPortMask = (STL_PORTMASK)portMask; +} + +IXML_FIELD PortGroupElementsFields[] = { + { tag:"Value", start_func:SwitchDataXmlParserStartPortGroupElementsValue, end_func:SwitchDataXmlParserEndPortGroupElementsValue }, + { NULL } +}; + +static void SwitchDataOutputPortGroupElements(IXmlOutputState_t *state, const char *tag, void *data) +{ + uint32 pgPortGroupNum; + SwitchData *switchp = (SwitchData *)data; + uint64 portMask; + + IXmlOutputStartTag(state, tag); + uint32 i; + for (i = 0; i < switchp->PortGroupSize; i++) { + portMask = (uint64)switchp->PortGroupElements[i]; + if (!portMask) { + continue; + } + + pgPortGroupNum = i; + IXmlOutputStartAttrTag(state, "Value", &pgPortGroupNum, SwitchDataOutputPortGroupNumberAttr); + IXmlOutputPrint(state, "0x%"PRIx64, portMask); + IXmlOutputEndTag(state, "Value"); + } + IXmlOutputEndTag(state, tag); +} + +static void *SwitchDataXmlParserStartPortGroupElements(IXmlParserState_t *state, void *parent, const char **attr) +{ + SwitchData *switchp = (SwitchData *)parent; + STL_PORTMASK *pPortMask; + + if (!switchp || switchp->PortGroupElements) { + IXmlParserPrintError(state, "SwitchData improperly allocated"); + return NULL; + } + + size_t allocSize = switchp->PortGroupSize; + + if (!(pPortMask = (STL_PORTMASK *)MemoryAllocate2AndClear( + allocSize * sizeof(STL_PORTMASK), + IBA_MEM_FLAG_PREMPTABLE, MYTAG))) { + IXmlParserPrintError(state, "Unable to allocate memory"); + return NULL; + } + + switchp->PortGroupElements = pPortMask; + + return (switchp); +} + +static void SwitchDataXmlParserEndPortGroupElements(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + SwitchData *switchp = (SwitchData *)object; + + if (! valid) { + goto fail; + } + return; + +fail: + if (switchp && switchp->PortGroupElements) { + MemoryDeallocate(switchp->PortGroupElements); + switchp->PortGroupElements = NULL; + } +} +// end of port group + +static void *SwitchDataXmlParserStartPortGroupFDBValue(IXmlParserState_t *state, void *parent, const char **attr) +{ + SwitchData *switchp = (SwitchData *)parent; + + if ( !attr || !attr[0] || 0!= strcmp(attr[0], "LID")) { + IXmlParserPrintError(state, "Missing LID attribute for PortGroupFDB.Value"); + return NULL; + } + + if (FSUCCESS != StringToUint32(&lidFDB, attr[1], NULL, 0, TRUE) + || lidFDB >= switchp->PortGroupFDBSize) { + IXmlParserPrintError(state, "Invalid LID attribute for PortGroupFDB.Value LID: %s", attr[1]); + return NULL; + } + return ((void *)&lidFDB); +} + +static void SwitchDataXmlParserEndPortGroupFDBValue(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + uint32 *pLID = (uint32 *)object; //points to LID + SwitchData *switchp = (SwitchData *)parent; + uint8 temp; + + if (!valid) { + return; + } + + if (!switchp || !switchp->PortGroupFDB || !pLID || !content || + !len || (*pLID >= switchp->PortGroupFDBSize)) { + IXmlParserPrintError(state, "PortGroupFDB improperly allocated"); + return; + } + + if (FSUCCESS != StringToUint8(&temp, content, NULL, 0, TRUE)) { + IXmlParserPrintError(state, "Invalid Port Group number in PortGroupFDB.Value for LID %u Value: %s", *pLID, content); + return; + } + STL_PGFT_PORT_BLOCK(switchp->PortGroupFDB, *pLID) = (PORT)temp; +} + +IXML_FIELD PortGroupFDBFields[] = { + { tag:"Value", start_func:SwitchDataXmlParserStartPortGroupFDBValue, end_func:SwitchDataXmlParserEndPortGroupFDBValue}, + { NULL } + +}; + +static void SwitchDataOutputPortGroupFDB(IXmlOutputState_t *state, const char *tag, void *data) +{ + unsigned int ix_lid; + SwitchData *switchp = (SwitchData *)data; + PORT *pPortGroup = (PORT *)switchp->PortGroupFDB; + + IXmlOutputStartTag(state, tag); + + for (ix_lid = 0; ix_lid < switchp->PortGroupFDBSize; + pPortGroup++, ix_lid++) { + if (*pPortGroup == 0xFF) { + continue; + } + IXmlOutputStartAttrTag(state, "Value", &ix_lid, SwitchDataOutputLIDAttr); + IXmlOutputPrint(state, "%u", *pPortGroup); + IXmlOutputEndTag(state, "Value"); + } + + IXmlOutputEndTag(state, tag); +} + +static void *SwitchDataXmlParserStartPortGroupFDB(IXmlParserState_t *state, void *parent, const char **attr) +{ + SwitchData *switchp = (SwitchData *)parent; + STL_PORT_GROUP_FORWARDING_TABLE *pPortGroup; + + if (!switchp || switchp->PortGroupFDB) { + IXmlParserPrintError(state, "SwitchData improperly allocated"); + return NULL; + } + + if (!switchp->PortGroupFDBSize) { + // PortGroupFDB is not in snapshot. For earlier + // versions of STL1, use LinearFDB but cap at 8k + switchp->PortGroupFDBSize = MIN(switchp->LinearFDBSize, DEFAULT_MAX_PGFT_LID+1); + } + + if ( !(pPortGroup = (STL_PORT_GROUP_FORWARDING_TABLE *)MemoryAllocate2AndClear( + ROUNDUP(switchp->PortGroupFDBSize, MAX_LFT_ELEMENTS_BLOCK), IBA_MEM_FLAG_PREMPTABLE, MYTAG))) { + IXmlParserPrintError(state, "Unable to allocate memory"); + return NULL; + } + + memset(pPortGroup, 255, ROUNDUP(switchp->PortGroupFDBSize, MAX_LFT_ELEMENTS_BLOCK)); + switchp->PortGroupFDB = pPortGroup; + + return (switchp); +} + +static void SwitchDataXmlParserEndPortGroupFDB(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + SwitchData *switchp = (SwitchData *)object; + + if (!valid) { + goto fail; + } + return; + +fail: + if (switchp && switchp->PortGroupFDB) { + MemoryDeallocate(switchp->PortGroupFDB); + switchp->PortGroupFDB = NULL; + } +} + + +static void IXmlParserEndMulticastFDBSize(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + uint32 value; + SwitchData *switchp = (SwitchData *)object; + + if (IXmlParseUint32(state, content, len, &value)) { + if (IS_MCAST16(value)) + value = MCAST16_TO_MCAST32(value); + if (value && ((value <= STL_LID_MULTICAST_BEGIN) || (value > STL_LID_MULTICAST_END + 1))) + IXmlParserPrintError(state, "MulticastFDBSize value 0x%08x out of range. Must be 0 or in the range 0x%08x through 0x%08x\n", value, STL_LID_MULTICAST_BEGIN + 1, STL_LID_MULTICAST_END + 1); + else + switchp->MulticastFDBSize = value; + } +} + + +IXML_FIELD SwitchDataFields[] = { + { tag:"LinearFDBSize", format:'U', IXML_FIELD_INFO(SwitchData, LinearFDBSize) }, + { tag:"MulticastFDBSize", format:'U', IXML_FIELD_INFO(SwitchData, MulticastFDBSize), end_func:IXmlParserEndMulticastFDBSize}, + { tag:"PortGroupFDBSize", format:'u', IXML_FIELD_INFO(SwitchData, PortGroupFDBSize) }, + { tag:"PortGroupSize", format:'U', IXML_FIELD_INFO(SwitchData, PortGroupSize) }, + { tag:"LinearFDB", format:'k', format_func:SwitchDataOutputLinearFDB, subfields:LinearFDBFields, start_func:SwitchDataXmlParserStartLinearFDB, end_func:SwitchDataXmlParserEndLinearFDB }, + { tag:"MulticastFDB", format:'k', format_func:SwitchDataOutputMulticastFDB, subfields:MulticastFDBFields, start_func:SwitchDataXmlParserStartMulticastFDB, end_func:SwitchDataXmlParserEndMulticastFDB }, + { tag:"PortGroupElements", format:'k', format_func:SwitchDataOutputPortGroupElements, subfields:PortGroupElementsFields, start_func:SwitchDataXmlParserStartPortGroupElements, end_func:SwitchDataXmlParserEndPortGroupElements }, + { tag:"PortGroupFDB", format:'k', format_func:SwitchDataOutputPortGroupFDB, subfields:PortGroupFDBFields, start_func:SwitchDataXmlParserStartPortGroupFDB, end_func:SwitchDataXmlParserEndPortGroupFDB }, + { NULL } +}; + +void SwitchDataXmlOutput(IXmlOutputState_t *state, const char *tag, void *data) +{ + IXmlOutputStruct(state, tag, (SwitchData*)data, NULL, SwitchDataFields); +} + +// only output if value != NULL +void SwitchDataXmlOutputOptional(IXmlOutputState_t *state, const char *tag, void *data) +{ + IXmlOutputOptionalStruct(state, tag, (SwitchData*)data, NULL, SwitchDataFields); +} + +/****************************************************************************/ +/* NodeData Input/Output functions */ + +static void NodeDataXmlOutputPorts(IXmlOutputState_t *state, const char *tag, void *data) +{ + NodeData *nodep = (NodeData*)data; + cl_map_item_t *p; + + for (p=cl_qmap_head(&nodep->Ports); p != cl_qmap_end(&nodep->Ports); p = cl_qmap_next(p)) { + PortDataXmlOutput(state, "PortInfo", PARENT_STRUCT(p, PortData, NodePortsEntry)); + } +} + +#if !defined(VXWORKS) || defined(BUILD_DMC) +static void NodeDataXmlOutputIou(IXmlOutputState_t *state, const char *tag, void *data) +{ + NodeData *nodep = (NodeData*)data; + + if (nodep->ioup) + IouDataXmlOutput(state, "Iou", nodep->ioup); +} +#endif + +static void NodeDataXmlOutputSwitchInfo(IXmlOutputState_t *state, const char *tag, void *data) +{ + NodeData *nodep = (NodeData*)data; + + if (nodep->pSwitchInfo) + SwitchInfoXmlOutput(state, "SwitchInfo", nodep->pSwitchInfo); +} + +static void NodeDataXmlOutputSwitchData(IXmlOutputState_t *state, const char *tag, void *data) +{ + NodeData *nodep = (NodeData*)data; + + if (nodep->switchp) + SwitchDataXmlOutput(state, "SwitchData", nodep->switchp); +} + +/* bitfields needs special handling: VendorID */ +static void NodeDataXmlOutputVendorID(IXmlOutputState_t *state, const char *tag, void *data) +{ + IXmlOutputUint(state, tag, ((NodeData *)data)->NodeInfo.u1.s.VendorID); +} + +static void NodeDataXmlParserEndVendorID(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + uint32 value; + + if (IXmlParseUint32(state, content, len, &value)) + ((NodeData *)object)->NodeInfo.u1.s.VendorID = value; +} + +IXML_FIELD CongestionInfoFields[] = { + { tag:"IBACongestionInfo", format:'X', IXML_FIELD_INFO(STL_CONGESTION_INFO, CongestionInfo) }, + { tag:"ControlTableCap", format:'U', IXML_FIELD_INFO(STL_CONGESTION_INFO, ControlTableCap) }, + { tag:"CongestionLogLength", format:'U', IXML_FIELD_INFO(STL_CONGESTION_INFO, CongestionLogLength) }, + { NULL } +}; + +static void NodeDataXmlOutputCongestionInfo(IXmlOutputState_t *state, const char *tag, void *data) +{ + NodeData *nodep = (NodeData*)data; + IXmlOutputStruct(state, tag, (STL_CONGESTION_INFO *)&nodep->CongestionInfo, NULL, CongestionInfoFields); +} + +static void CongestionInfoXmlParserEnd(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + STL_CONGESTION_INFO *pci = (STL_CONGESTION_INFO*)object; + NodeData *nodep = (NodeData*)parent; + + if (! valid) // missing mandatory fields + goto failvalidate; + + memcpy(&nodep->CongestionInfo, pci, sizeof(STL_CONGESTION_INFO)); + +failvalidate: + MemoryDeallocate(pci); + return; +} + +const IXML_FIELD NodeDataFields[] = { + { tag:"NodeDesc", format:'C', IXML_FIELD_INFO(NodeData, NodeDesc.NodeString) }, + { tag:"NodeGUID", format:'H', IXML_FIELD_INFO(NodeData, NodeInfo.NodeGUID) }, + { tag:"NodeType", format:'k', IXML_FIELD_INFO(NodeData, NodeInfo.NodeType), format_func:IXmlOutputNodeType, end_func:IXmlParserEndNoop }, // output only + { tag:"NodeType_Int", format:'U', IXML_FIELD_INFO(NodeData, NodeInfo.NodeType), format_func:IXmlOutputNoop }, // input only + { tag:"BaseVersion", format:'U', IXML_FIELD_INFO(NodeData, NodeInfo.BaseVersion) }, + { tag:"ClassVersion", format:'U', IXML_FIELD_INFO(NodeData, NodeInfo.ClassVersion) }, + { tag:"NumPorts", format:'U', IXML_FIELD_INFO(NodeData, NodeInfo.NumPorts) }, + { tag:"SystemImageGUID", format:'H', IXML_FIELD_INFO(NodeData, NodeInfo.SystemImageGUID) }, + // NodeData.NodeInfo.PortGUID is not used + { tag:"PartitionCap", format:'U', IXML_FIELD_INFO(NodeData, NodeInfo.PartitionCap) }, + { tag:"DeviceID", format:'H', IXML_FIELD_INFO(NodeData, NodeInfo.DeviceID) }, + { tag:"Revision", format:'H', IXML_FIELD_INFO(NodeData, NodeInfo.Revision) }, + // NodeData.NodeInfo.u1.s.LocalPortNum is not used + { tag:"VendorID", format:'H', format_func:NodeDataXmlOutputVendorID, end_func:NodeDataXmlParserEndVendorID }, + { tag:"PortInfo", format:'k', format_func:NodeDataXmlOutputPorts, subfields:PortDataFields, start_func:PortDataXmlParserStart, end_func:PortDataXmlParserEnd }, // structures +#if !defined(VXWORKS) || defined(BUILD_DMC) + { tag:"Iou", format:'k', format_func:NodeDataXmlOutputIou, subfields:IouDataFields, start_func:IouDataXmlParserStart, end_func:IouDataXmlParserEnd }, // structure +#endif + { tag:"SwitchInfo", format:'k', size:sizeof(STL_SWITCHINFO_RECORD), format_func:NodeDataXmlOutputSwitchInfo, subfields:SwitchInfoFields, start_func:SwitchInfoXmlParserStart, end_func:SwitchInfoXmlParserEnd }, // structure + { tag:"SwitchData", format:'k', size:sizeof(SwitchData), format_func:NodeDataXmlOutputSwitchData, subfields:SwitchDataFields, start_func:SwitchDataXmlParserStart, end_func:SwitchDataXmlParserEnd }, // structure + { tag:"CongestionInfo", format:'k', size:sizeof(STL_CONGESTION_INFO), format_func:NodeDataXmlOutputCongestionInfo, subfields:CongestionInfoFields, start_func:IXmlParserStartStruct, end_func:CongestionInfoXmlParserEnd }, // structure + { NULL } +}; + +static void NodeDataXmlFormatAttr(IXmlOutputState_t *state, void *data) +{ + IXmlOutputPrint(state, " id=\"0x%016"PRIx64"\"", ((NodeData*)data)->NodeInfo.NodeGUID); +} + +static void NodeDataXmlOutput(IXmlOutputState_t *state, const char *tag, void *data) +{ + IXmlOutputStruct(state, tag, (NodeData*)data, NodeDataXmlFormatAttr, NodeDataFields); +} + +static void *NodeDataXmlParserStart(IXmlParserState_t *state, void *parent, const char **attr) +{ + NodeData *nodep = (NodeData*)MemoryAllocate2AndClear(sizeof(NodeData), IBA_MEM_FLAG_PREMPTABLE, MYTAG); + + // TBD - if enable then need quiet arg in a static global + //if (i%PROGRESS_FREQ == 0) + //ProgressPrint(FALSE, "Processed %6d of %6d Nodes...", i, p->NumNodeRecords); + if (! nodep) { + IXmlParserPrintError(state, "Unable to allocate memory"); + return NULL; + } + + cl_qmap_init(&nodep->Ports, NULL); + ListItemInitState(&nodep->AllTypesEntry); + QListSetObj(&nodep->AllTypesEntry, nodep); + + return nodep; +} + +static void NodeDataXmlParserEnd(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + cl_map_item_t *mi; + NodeData *nodep = (NodeData*)object; + FabricData_t *fabricp = IXmlParserGetContext(state); + //FSTATUS status; + + if (! valid) // missing mandatory fields + goto failvalidate; + + // TODO should this enforce if NodeType == NI_TYPE_SWITCH that + // SwitchData has been parsed (nodep->switchp != NULL)? + + mi = cl_qmap_insert(&fabricp->AllNodes, nodep->NodeInfo.NodeGUID, &nodep->AllNodesEntry); + if (mi != &nodep->AllNodesEntry) + { + IXmlParserPrintError(state, "Duplicate NodeGuid: 0x%"PRIx64"\n", nodep->NodeInfo.NodeGUID); + goto failinsert; + } + + //printf("processed NodeRecord GUID: 0x%"PRIx64"\n", nodep->NodeInfo.NodeGUID); + if (FSUCCESS != AddSystemNode(fabricp, nodep)) { + IXmlParserPrintError(state, "Unable to track systems for NodeGuid: 0x%"PRIx64"\n", nodep->NodeInfo.NodeGUID); + goto failsystem; + } + + // Set FF_ROUTES for cases (older opareport) where it was not set at + // snapshot generation time + if (fbFDB) + fabricp->flags |= FF_ROUTES; + return; + +failsystem: + cl_qmap_remove_item(&fabricp->AllNodes, &nodep->AllNodesEntry); +failinsert: +failvalidate: + MemoryDeallocate(nodep); +} + +static IXML_FIELD NodesFields[] = { + { tag:"Node", format:'K', subfields:(IXML_FIELD*)NodeDataFields, start_func:NodeDataXmlParserStart, end_func:NodeDataXmlParserEnd }, // structure + { NULL } +}; + +void Snapshot_NodeDataFree(NodeData * nodep, FabricData_t * fabricp) +{ + NodeDataFreePorts(fabricp, nodep); +#if !defined(VXWORKS) || defined(BUILD_DMC) + if (nodep->ioup) + IouDataFree(fabricp, nodep->ioup); +#endif + if (nodep->pSwitchInfo) + MemoryDeallocate(nodep->pSwitchInfo); + NodeDataFreeSwitchData(fabricp, nodep); +} + +/****************************************************************************/ +/* SM Data Input/Output functions */ + +static void SMDataXmlFormatAttr(IXmlOutputState_t *state, void *data) +{ + PortDataXmlFormatAttr(state, ((SMData *)data)->portp); +} + +#if 0 +static void SMDataXmlOutputNodeGUID(IXmlOutputState_t *state, const char *tag, void *data) +{ + IXmlOutputHexPad64(state, tag, ((SMData *)data)->portp->nodep->NodeInfo.NodeGUID); +} +#endif + +#if 0 +// since SM's don't nest, we can use a simple global +static struct { + EUI64 NodeGUID; + uint8 PortNum; +} TempSMData; + +static void SMDataXmlParserEndNodeGUID(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + IXmlParseUint64(state, content, len, &TempSMData.NodeGUID); +} + +static void SMDataXmlParserEndPortNum(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + IXmlParseUint8(state, content, len, &TempSMData.PortNum); +} +#endif + +#if 0 +static void SMDataXmlOutputPortNum(IXmlOutputState_t *state, const char *tag, void *data) +{ + IXmlOutputUint(state, tag, ((SMData *)data)->portp->PortNum); +} +#endif + +/* bitfields needs special handling: LID */ +static void SMDataXmlOutputLID(IXmlOutputState_t *state, const char *tag, void *data) +{ + IXmlOutputLIDValue(state, tag, ((SMData *)data)->SMInfoRecord.RID.LID); +} + +static void SMDataXmlParserEndLID(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + STL_LID value; + + if (IXmlParseUint32(state, content, len, &value)) + ((SMData *)object)->SMInfoRecord.RID.LID = value; +} + + +/* bitfields needs special handling: SMState */ +static void SMDataXmlOutputSMState(IXmlOutputState_t *state, const char *tag, void *data) +{ + IXmlOutputSMStateValue(state, tag, ((SMData *)data)->SMInfoRecord.SMInfo.u.s.SMStateCurrent); +} + +static void SMDataXmlParserEndSMState(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + uint8 value; + + if (IXmlParseUint8(state, content, len, &value)) + ((SMData *)object)->SMInfoRecord.SMInfo.u.s.SMStateCurrent = value; +} + +/* bitfields needs special handling: Priority */ +static void SMDataXmlOutputPriority(IXmlOutputState_t *state, const char *tag, void *data) +{ + IXmlOutputUint(state, tag, ((SMData *)data)->SMInfoRecord.SMInfo.u.s.Priority); +} + +static void SMDataXmlParserEndPriority(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + uint8 value; + + if (IXmlParseUint8(state, content, len, &value)) + ((SMData *)object)->SMInfoRecord.SMInfo.u.s.Priority = value; +} + +static IXML_FIELD SMDataFields[] = { + //{ tag:"NodeGUID", format:'k', format_func:SMDataXmlOutputNodeGUID, end_func:IXmlParserEndNoop }, // output only + //{ tag:"PortNum", format:'k', format_func:SMDataXmlOutputPortNum, end_func:IXmlParserEndNoop }, // output only + { tag:"LID", format:'K', format_func:SMDataXmlOutputLID, end_func:SMDataXmlParserEndLID }, // bitfield + { tag:"PortGUID", format:'H', IXML_FIELD_INFO(SMData, SMInfoRecord.SMInfo.PortGUID) }, + { tag:"State", format:'k', format_func:SMDataXmlOutputSMState, end_func:IXmlParserEndNoop },// output only bitfield + { tag:"State_Int", format:'K', format_func:IXmlOutputNoop, end_func:SMDataXmlParserEndSMState }, // input only bitfield + { tag:"Priority", format:'K', format_func:SMDataXmlOutputPriority, end_func:SMDataXmlParserEndPriority }, // bitfield + { tag:"SM_Key", format:'H', IXML_FIELD_INFO(SMData, SMInfoRecord.SMInfo.SM_Key) }, + { tag:"ActCount", format:'X', IXML_FIELD_INFO(SMData, SMInfoRecord.SMInfo.ActCount) }, + { NULL } +}; + +static void SMDataXmlOutput(IXmlOutputState_t *state, const char *tag, void *data) +{ + IXmlOutputStruct(state, tag, (SMData*)data, SMDataXmlFormatAttr, SMDataFields); +} + +static void SMDataXmlParserEnd(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + SMData *smp = (SMData*)object; + FabricData_t *fabricp = IXmlParserGetContext(state); + + if (! valid) + goto invalid; + smp->portp = FindLidPort(fabricp, smp->SMInfoRecord.RID.LID, 0); + if (! smp->portp) { + IXmlParserPrintError(state, "SM LID not found: 0x%x\n", smp->SMInfoRecord.RID.LID); + goto badport; + } + if (&smp->AllSMsEntry != cl_qmap_insert(&fabricp->AllSMs, smp->SMInfoRecord.SMInfo.PortGUID, &smp->AllSMsEntry)) { + IXmlParserPrintError(state, "Duplicate SM Port Guids: 0x%016"PRIx64"\n", smp->SMInfoRecord.SMInfo.PortGUID); + goto failinsert; + } + return; + +failinsert: +badport: +invalid: + MemoryDeallocate(smp); +} + +static IXML_FIELD SMsFields[] = { + { tag:"SM", format:'k', size:sizeof(SMData), subfields:SMDataFields, start_func:IXmlParserStartStruct, end_func:SMDataXmlParserEnd }, // structure + { NULL } +}; + +/****************************************************************************/ +/* Link Input/Output functions */ +static void LinkXmlOutputNodeGUID(IXmlOutputState_t *state, const char *tag, void *data) +{ + IXmlOutputHexPad64(state, tag, ((PortData*)data)->nodep->NodeInfo.NodeGUID); +} + +/* Output fields for PortData to include in To and From Link */ +static IXML_FIELD LinkPortFields[] = { + { tag:"NodeGUID", format:'K', format_func:LinkXmlOutputNodeGUID }, + { tag:"PortNum", format:'U', IXML_FIELD_INFO(PortData, PortNum) }, + { NULL } +}; + +#ifndef JFORMAT +static void LinkXmlOutputFrom(IXmlOutputState_t *state, const char *tag, void *data) +{ + IXmlOutputStruct(state, tag, (PortData*)data, NULL /*PortDataXmlFormatAttr*/, LinkPortFields); +} +#endif + +static void LinkXmlOutputTo(IXmlOutputState_t *state, const char *tag, void *data) +{ + IXmlOutputStruct(state, tag, ((PortData*)data)->neighbor, NULL /*PortDataXmlFormatAttr*/, LinkPortFields); +} + +struct portref { + EUI64 NodeGUID; + uint8 PortNum; +}; + +typedef struct TempLinkData { + struct portref from; + struct portref to; +} TempLinkData_t; + +/* Input fields for TempLinkData */ +static IXML_FIELD TempLinkDataFromFields[] = { + { tag:"NodeGUID", format:'H', IXML_FIELD_INFO(TempLinkData_t, from.NodeGUID)}, + { tag:"PortNum", format:'U', IXML_FIELD_INFO(TempLinkData_t, from.PortNum) }, + { NULL } +}; +static IXML_FIELD TempLinkDataToFields[] = { + { tag:"NodeGUID", format:'H', IXML_FIELD_INFO(TempLinkData_t, to.NodeGUID)}, + { tag:"PortNum", format:'U', IXML_FIELD_INFO(TempLinkData_t, to.PortNum) }, + { NULL } +}; + +static void *LinkFromXmlParserStart(IXmlParserState_t *state, void *parent, const char **attr) +{ + return parent; +} + +static void *LinkToXmlParserStart(IXmlParserState_t *state, void *parent, const char **attr) +{ + return parent; +} + + +/* description */ +static IXML_FIELD LinkFields[] = { +#ifdef JFORMAT + { tag:"From", format:'J', subfields: LinkPortFields, format_attr:PortDataXmlFormatAttr }, + { tag:"To", format:'K', subfields: LinkPortFields, format_func:LinkXmlOutputTo }, +#else + { tag:"From", format:'K', subfields: TempLinkDataFromFields, format_func:LinkXmlOutputFrom, start_func:LinkFromXmlParserStart, end_func:IXmlParserEndNoop }, // special handling + { tag:"To", format:'K', subfields: TempLinkDataToFields, format_func:LinkXmlOutputTo, start_func:LinkToXmlParserStart, end_func:IXmlParserEndNoop }, // special handling +#endif + { NULL } +}; + + + +static void LinkXmlOutput(IXmlOutputState_t *state, const char *tag, void *data) +{ + IXmlOutputStruct(state, tag, (PortData*)data, PortDataXmlFormatAttr, LinkFields); +} + + +static void *LinkXmlParserStart(IXmlParserState_t *state, void *parent, const char **attr) +{ + /* since links don't nest, we can get away with a single static */ + /* if we ever use this multi-threaded, will need to allocate */ + static TempLinkData_t link; + + MemoryClear(&link, sizeof(link)); + return &link; +} + +static void LinkXmlParserEnd(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + TempLinkData_t *link = (TempLinkData_t*)object; + PortData *p1, *p2; + FabricData_t *fabricp = IXmlParserGetContext(state); + + if (! valid) + goto invalid; + p1 = FindNodeGuidPort(fabricp, link->from.NodeGUID, link->from.PortNum); + if (! p1) { + IXmlParserPrintError(state, "Port not found: 0x%016"PRIx64":%u\n", + link->from.NodeGUID, link->from.PortNum); + goto badport; + } + if (p1->neighbor) { + IXmlParserPrintError(state, "Duplicate Port found: 0x%016"PRIx64":%u\n", + link->from.NodeGUID, link->from.PortNum); + goto badport; + } + p2 = FindNodeGuidPort(fabricp, link->to.NodeGUID, link->to.PortNum); + if (! p2) { + IXmlParserPrintError(state, "Port not found: 0x%016"PRIx64":%u\n", + link->to.NodeGUID, link->to.PortNum); + goto badport; + } + if (p2->neighbor) { + IXmlParserPrintError(state, "Duplicate Port found: 0x%016"PRIx64":%u\n", + link->to.NodeGUID, link->to.PortNum); + goto badport; + } + p1->neighbor = p2; + p2->neighbor = p1; + p1->from = 1; + if (p1->rate != p2->rate) { + fprintf(stderr, "%s: Warning: Ignoring Inconsistent Active Speed/Width for link between:\n", g_Top_cmdname); + fprintf(stderr, " %4s 0x%016"PRIx64" %3u %s %.*s\n", + StlStaticRateToText(p1->rate), + p1->nodep->NodeInfo.NodeGUID, + p1->PortNum, + StlNodeTypeToText(p1->nodep->NodeInfo.NodeType), + STL_NODE_DESCRIPTION_ARRAY_SIZE, + (char*)p1->nodep->NodeDesc.NodeString); + fprintf(stderr, " %4s 0x%016"PRIx64" %3u %s %.*s\n", + StlStaticRateToText(p2->rate), + p2->nodep->NodeInfo.NodeGUID, + p2->PortNum, + StlNodeTypeToText(p2->nodep->NodeInfo.NodeType), + STL_NODE_DESCRIPTION_ARRAY_SIZE, + (char*)p2->nodep->NodeDesc.NodeString); + } + ++(fabricp->LinkCount); + if (! isInternalLink(p1)) + ++(fabricp->ExtLinkCount); + if (isFILink(p1)) + ++(fabricp->FILinkCount); + if (isISLink(p1)) + ++(fabricp->ISLinkCount); + if (! isInternalLink(p1)&& isISLink(p1)) + ++(fabricp->ExtISLinkCount); + +badport: +invalid: + /* nothing to free */ + return; +} + + +static IXML_FIELD LinksFields[] = { + { tag:"Link", format:'K', subfields:LinkFields, start_func:LinkXmlParserStart, end_func:LinkXmlParserEnd }, // structure + { NULL } +}; + +/****************************************************************************/ +/* Virtual Fabrics Input/Output functions */ + +static void VFInfoXmlOutputSelectFlags(IXmlOutputState_t *state, const char *tag, void *data) { + IXmlOutputUint(state, tag, ((STL_VFINFO_RECORD *)data)->s1.selectFlags); +} +static void VFInfoXmlParserEndSelectFlags(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) { + uint8 value; + if (IXmlParseUint8(state, content, len, &value)) + ((STL_VFINFO_RECORD *)object)->s1.selectFlags = value; +} + +static void VFInfoXmlOutputSL(IXmlOutputState_t *state, const char *tag, void *data) { + IXmlOutputUint(state, tag, ((STL_VFINFO_RECORD *)data)->s1.slBase); +} + +static void VFInfoXmlParserEndSL(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) { + uint8 value; + if (IXmlParseUint8(state, content, len, &value)) + ((STL_VFINFO_RECORD *)object)->s1.slBase = value; +} + +static void VFInfoXmlOutputRespSL(IXmlOutputState_t *state, const char *tag, void *data) { + if (((STL_VFINFO_RECORD*)data)->slResponseSpecified) + IXmlOutputUint(state, tag, ((STL_VFINFO_RECORD *)data)->slResponse); +} + +static void VFInfoXmlParserEndRespSL(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) { + uint8 value; + if (IXmlParseUint8(state, content, len, &value)) { + ((STL_VFINFO_RECORD*)object)->slResponse = value; + ((STL_VFINFO_RECORD*)object)->slResponseSpecified = 1; + } +} + +static void VFInfoXmlOutputMulticastSL(IXmlOutputState_t *state, const char *tag, void *data) { + if (((STL_VFINFO_RECORD*)data)->slMulticastSpecified) + IXmlOutputUint(state, tag, ((STL_VFINFO_RECORD *)data)->slMulticast); +} + +static void VFInfoXmlParserEndMulticastSL(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) { + uint8 value; + if (IXmlParseUint8(state, content, len, &value)) { + ((STL_VFINFO_RECORD*)object)->slMulticast = value; + ((STL_VFINFO_RECORD*)object)->slMulticastSpecified = 1; + } +} + +static void VFInfoXmlOutputMTUSpecified(IXmlOutputState_t *state, const char *tag, void *data) { + IXmlOutputUint(state, tag, ((STL_VFINFO_RECORD *)data)->s1.mtuSpecified); +} +static void VFInfoXmlParserEndMTUSpecified(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) { + uint8 value; + if (IXmlParseUint8(state, content, len, &value)) + ((STL_VFINFO_RECORD *)object)->s1.mtuSpecified = value; +} + +static void VFInfoXmlOutputMTU(IXmlOutputState_t *state, const char *tag, void *data) { + IXmlOutputUint(state, tag, ((STL_VFINFO_RECORD *)data)->s1.mtu); +} +static void VFInfoXmlParserEndMTU(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) { + uint8 value; + if (IXmlParseUint8(state, content, len, &value)) + ((STL_VFINFO_RECORD *)object)->s1.mtu = value; +} + +static void VFInfoXmlOutputRateSpecified(IXmlOutputState_t *state, const char *tag, void *data) { + IXmlOutputUint(state, tag, ((STL_VFINFO_RECORD *)data)->s1.rateSpecified); +} +static void VFInfoXmlParserEndRateSpecified(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) { + uint8 value; + if (IXmlParseUint8(state, content, len, &value)) + ((STL_VFINFO_RECORD *)object)->s1.rateSpecified = value; +} + +static void VFInfoXmlOutputRate(IXmlOutputState_t *state, const char *tag, void *data) { + IXmlOutputUint(state, tag, ((STL_VFINFO_RECORD *)data)->s1.rate); +} +static void VFInfoXmlParserEndRate(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) { + uint8 value; + if (IXmlParseUint8(state, content, len, &value)) + ((STL_VFINFO_RECORD *)object)->s1.rate = value; +} + +static void VFInfoXmlOutputPacketLifeSpecified(IXmlOutputState_t *state, const char *tag, void *data) { + IXmlOutputUint(state, tag, ((STL_VFINFO_RECORD *)data)->s1.pktLifeSpecified); +} +static void VFInfoXmlParserEndPacketLifeSpecified(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) { + uint8 value; + if (IXmlParseUint8(state, content, len, &value)) + ((STL_VFINFO_RECORD *)object)->s1.pktLifeSpecified = value; +} + +static void VFInfoXmlOutputPacketLifeTimeInc(IXmlOutputState_t *state, const char *tag, void *data) { + IXmlOutputUint(state, tag, ((STL_VFINFO_RECORD *)data)->s1.pktLifeTimeInc); +} +static void VFInfoXmlParserEndPacketLifeTimeInc(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) { + uint8 value; + if (IXmlParseUint8(state, content, len, &value)) + ((STL_VFINFO_RECORD *)object)->s1.pktLifeTimeInc = value; +} + +static void VFInfoXmlOutputSlResponse(IXmlOutputState_t *state, const char *tag, void *data) { + IXmlOutputUint(state, tag, ((STL_VFINFO_RECORD *)data)->slResponse); +} +static void VFInfoXmlParserEndSlResponse(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) { + uint8 value; + if (IXmlParseUint8(state, content, len, &value)) + ((STL_VFINFO_RECORD *)object)->slResponse = value; +} + +static void VFInfoXmlOutputPriority(IXmlOutputState_t *state, const char *tag, void *data) { + IXmlOutputUint(state, tag, ((STL_VFINFO_RECORD *)data)->priority); +} +static void VFInfoXmlParserEndPriority(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) { + uint8 value; + if (IXmlParseUint8(state, content, len, &value)) + ((STL_VFINFO_RECORD *)object)->priority = value; +} + +static void VFInfoXmlOutputPreemptionRank(IXmlOutputState_t *state, const char *tag, void *data) { + IXmlOutputUint(state, tag, ((STL_VFINFO_RECORD *)data)->preemptionRank); +} +static void VFInfoXmlParserEndPreemptionRank(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) { + uint8 value; + if (IXmlParseUint8(state, content, len, &value)) + ((STL_VFINFO_RECORD *)object)->preemptionRank = value; +} + +static void VFInfoXmlOutputHoqLife(IXmlOutputState_t *state, const char *tag, void *data) { + IXmlOutputUint(state, tag, ((STL_VFINFO_RECORD *)data)->hoqLife); +} +static void VFInfoXmlParserEndHoqLife(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) { + uint8 value; + if (IXmlParseUint8(state, content, len, &value)) + ((STL_VFINFO_RECORD *)object)->hoqLife = value; +} + +static IXML_FIELD VFFields[] = { + { tag:"Index", format:'U', IXML_FIELD_INFO(STL_VFINFO_RECORD, vfIndex) }, + { tag:"PKey", format:'u', IXML_FIELD_INFO(STL_VFINFO_RECORD, pKey) }, + { tag:"Name", format:'S', IXML_FIELD_INFO(STL_VFINFO_RECORD, vfName) }, + { tag:"ServiceID", format:'h', IXML_FIELD_INFO(STL_VFINFO_RECORD, ServiceID) }, + { tag:"MGIDHigh", format:'h', IXML_FIELD_INFO(STL_VFINFO_RECORD, MGID.AsReg64s.H) }, + { tag:"MGIDLow", format:'h', IXML_FIELD_INFO(STL_VFINFO_RECORD, MGID.AsReg64s.L) }, + { tag:"SelectFlags", format:'k', format_func:VFInfoXmlOutputSelectFlags, end_func:VFInfoXmlParserEndSelectFlags }, + { tag:"SL", format:'k', format_func:VFInfoXmlOutputSL, end_func:VFInfoXmlParserEndSL }, + { tag:"RespSL", format:'k', format_func:VFInfoXmlOutputRespSL, end_func:VFInfoXmlParserEndRespSL }, + { tag:"MulticastSL", format:'k', format_func:VFInfoXmlOutputMulticastSL, end_func:VFInfoXmlParserEndMulticastSL }, + { tag:"MTUSpecified", format:'k', format_func:VFInfoXmlOutputMTUSpecified, end_func:VFInfoXmlParserEndMTUSpecified }, + { tag:"MTU", format:'k', format_func:VFInfoXmlOutputMTU, end_func:VFInfoXmlParserEndMTU }, + { tag:"RateSpecified", format:'k', format_func:VFInfoXmlOutputRateSpecified, end_func:VFInfoXmlParserEndRateSpecified }, + { tag:"Rate", format:'k', format_func:VFInfoXmlOutputRate, end_func:VFInfoXmlParserEndRate }, + { tag:"PacketLifeSpecified", format:'k', format_func:VFInfoXmlOutputPacketLifeSpecified, end_func:VFInfoXmlParserEndPacketLifeSpecified }, + { tag:"PacketLifeTimeInc", format:'k', format_func:VFInfoXmlOutputPacketLifeTimeInc, end_func:VFInfoXmlParserEndPacketLifeTimeInc }, + { tag:"OptionFlags", format:'h', IXML_FIELD_INFO(STL_VFINFO_RECORD, optionFlags) }, + { tag:"BandwidthPercent", format:'u', IXML_FIELD_INFO(STL_VFINFO_RECORD, bandwidthPercent) }, + { tag:"SLResponse", format:'k', format_func:VFInfoXmlOutputSlResponse, end_func:VFInfoXmlParserEndSlResponse }, + { tag:"Priority", format:'k', format_func:VFInfoXmlOutputPriority, end_func:VFInfoXmlParserEndPriority }, + { tag:"PreemptionRank", format:'k', format_func:VFInfoXmlOutputPreemptionRank, end_func:VFInfoXmlParserEndPreemptionRank }, + { tag:"HOQLife", format:'k', format_func:VFInfoXmlOutputHoqLife, end_func:VFInfoXmlParserEndHoqLife }, + { NULL } +}; + +static void *VFDataXmlParserStartVF(IXmlParserState_t *state, void *parent, const char **attr) +{ + VFData_t *vf = MemoryAllocate2AndClear(sizeof(VFData_t), IBA_MEM_FLAG_PREMPTABLE, MYTAG); + if (!vf) { + IXmlParserPrintError(state, "Unable to allocate memory"); + return NULL; + } + + return &vf->record; +} + +static void VFDataXmlParserEndVF(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + FabricData_t *fabricp = IXmlParserGetContext(state); + STL_VFINFO_RECORD *vfinfo = object; + VFData_t *vf = PARENT_STRUCT(vfinfo, VFData_t, record); + + if (valid) { + QListSetObj(&vf->AllVFsEntry, vf); + QListInsertTail(&fabricp->AllVFs, &vf->AllVFsEntry); + } else if (vf) { + MemoryDeallocate(vf); + } +} + +static IXML_FIELD VFsFields[] = { + { tag:"VF", format:'K', subfields:VFFields, start_func:VFDataXmlParserStartVF, end_func:VFDataXmlParserEndVF }, + { NULL } +}; + +/****************************************************************************/ +/* Overall Serialization Input/Output functions */ + +/* only used for input parsing */ +static IXML_FIELD SnapshotFields[] = { + { tag:"Nodes", format:'K', subfields:NodesFields }, // list + { tag:"SMs", format:'K', subfields:SMsFields }, // list + { tag:"Links", format:'K', subfields:LinksFields }, // list + { tag:"McMembers", format:'k', subfields:MulticastFields }, // list + { tag:"VirtualFabrics", format:'k', subfields:VFsFields }, + { NULL } +}; + +static void *SnapshotXmlParserStart(IXmlParserState_t *state, void *parent, const char **attr) +{ + int i; + boolean gottime = FALSE; + boolean gotstats = FALSE; + FabricData_t *fabricp = IXmlParserGetContext(state); + uint64 temp; + + // process unixtime attribute and update fabricp->time + for (i = 0; attr[i]; i += 2) { + if (strcmp(attr[i], "unixtime") == 0) { + gottime = TRUE; + // typically time_t is 32 bits, but allow 64 bits + if (FSUCCESS != StringToUint64(&temp, attr[i+1], NULL, 0, TRUE)) + IXmlParserPrintError(state, "Invalid unixtime attribute: %s", attr[i+1]); + else + fabricp->time = (time_t)temp; + } else if (strcmp(attr[i], "stats") == 0) { + gotstats = TRUE; + if (FSUCCESS != StringToUint64(&temp, attr[i+1], NULL, 0, TRUE)) + IXmlParserPrintError(state, "Invalid stats attribute: %s", attr[i+1]); + else + fabricp->flags |= temp?FF_STATS:FF_NONE; + } else if (strcmp(attr[i], "routes") == 0) { + if (FSUCCESS != StringToUint64(&temp, attr[i+1], NULL, 0, TRUE)) + IXmlParserPrintError(state, "Invalid routes attribute: %s", attr[i+1]); + else + fabricp->flags |= temp?FF_ROUTES:FF_NONE; + } else if (strcmp(attr[i], "qosdata") == 0) { + if (FSUCCESS != StringToUint64(&temp, attr[i+1], NULL, 0, TRUE)) + IXmlParserPrintError(state, "Invalid qosdata attribute: %s", attr[i+1]); + else + fabricp->flags |= temp?FF_QOSDATA:FF_NONE; + } else if (strcmp(attr[i], "bfrctrl") == 0) { + if (FSUCCESS != StringToUint64(&temp, attr[i+1], NULL, 0, TRUE)) + IXmlParserPrintError(state, "Invalid bfrctrl attribute: %s", attr[i+1]); + else + fabricp->flags |= temp?FF_BUFCTRLTABLE:FF_NONE; + } else if (strcmp(attr[i], "downports") == 0) { + if (FSUCCESS != StringToUint64(&temp, attr[i+1], NULL, 0, TRUE)) + IXmlParserPrintError(state, "Invalid downports attribute: %s", attr[i+1]); + else + fabricp->flags |= temp?FF_DOWNPORTINFO:FF_NONE; + } + } + if (! gottime) { + IXmlParserPrintError(state, "Missing unixtime attribute"); + } + if (! gotstats) { + IXmlParserPrintError(state, "Missing stats attribute"); + } + fabricp->NumOfMcGroups = 0; + return NULL; +} + +static void SnapshotXmlParserEnd(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + FabricData_t *fabricp = IXmlParserGetContext(state); + + if (! valid) { + // This free's everything we built while parsing, leaving empty lists + SMDataFreeAll(fabricp); + NodeDataFreeAll(fabricp); + MCDataFreeAll(fabricp); + VFDataFreeAll(fabricp); + fabricp->LinkCount = 0; + fabricp->ExtLinkCount = 0; + } +} + +static IXML_FIELD TopLevelFields[] = { + { tag:"Snapshot", format:'K', subfields:SnapshotFields, start_func:SnapshotXmlParserStart, end_func:SnapshotXmlParserEnd }, // structure + { NULL } +}; +#if 0 +static IXML_FIELD TopLevelFields[] = { + { tag:"Report", format:'K', subfields:ReportFields }, // structure + { NULL } +}; +#endif + +static void SnapshotInfoXmlFormatAttr(IXmlOutputState_t *state, void *data) +{ + SnapshotOutputInfo_t *info = (SnapshotOutputInfo_t *)IXmlOutputGetContext(state); + char datestr[80] = ""; + int i; + + Top_formattime(datestr, sizeof(datestr), info->fabricp->time); + IXmlOutputPrint( state, " date=\"%s\" unixtime=\"%ld\" stats=\"%d\"" + " routes=\"%d\" qosdata=\"%d\" bfrctrl=\"%d\" downports=\"%d\" options=\"", + datestr, info->fabricp->time, (info->fabricp->flags & FF_STATS) ? 1:0, + (info->fabricp->flags & FF_ROUTES) ? 1:0, + (info->fabricp->flags & FF_QOSDATA) ? 1:0, + (info->fabricp->flags & FF_BUFCTRLTABLE) ? 1:0, + (info->fabricp->flags & FF_DOWNPORTINFO) ? 1:0 ); + for (i=1; iargc; i++) + IXmlOutputPrint(state, "%s%s", i>1?" ":"", info->argv[i]); + IXmlOutputPrint(state, "\""); +} + +static void Xml2PrintAll(IXmlOutputState_t *state, const char *tag, void *data) +{ + SnapshotOutputInfo_t *info = (SnapshotOutputInfo_t *)IXmlOutputGetContext(state); + FabricData_t *fabricp = info->fabricp; + + IXmlOutputStartAttrTag(state, tag, NULL, SnapshotInfoXmlFormatAttr); + + { + cl_map_item_t *p; + + IXmlOutputStartAttrTag(state, "Nodes", NULL, NULL); + for (p=cl_qmap_head(&fabricp->AllNodes); p != cl_qmap_end(&fabricp->AllNodes); p = cl_qmap_next(p)) { + NodeData *nodep = PARENT_STRUCT(p, NodeData, AllNodesEntry); +#if 0 + if (! CompareNodePoint(nodep, info->focus)) + continue; +#endif + NodeDataXmlOutput(state, "Node", nodep); + } + IXmlOutputEndTag(state, "Nodes"); + } + + { + cl_map_item_t *p; + + IXmlOutputStartAttrTag(state, "SMs", NULL, NULL); + for (p=cl_qmap_head(&fabricp->AllSMs); p != cl_qmap_end(&fabricp->AllSMs); p = cl_qmap_next(p)) { + SMDataXmlOutput(state, "SM", PARENT_STRUCT(p, SMData, AllSMsEntry)); + } + IXmlOutputEndTag(state, "SMs"); + } + + { + LIST_ITEM *p; + + IXmlOutputStartAttrTag(state, "Links", NULL, NULL); + for (p=QListHead(&fabricp->AllPorts); p != NULL; p = QListNext(&fabricp->AllPorts, p)) { + PortData *portp = (PortData *)QListObj(p); + // to avoid duplicated processing, only process "from" ports in link + if (! portp->from) + continue; + LinkXmlOutput(state, "Link", portp); + } + IXmlOutputEndTag(state, "Links"); + } + + { + LIST_ITEM *p; + + IXmlOutputStartAttrTag(state, "McMembers", NULL, NULL); + for (p=QListHead(&fabricp->AllMcGroups); p != NULL; p = QListNext(&fabricp->AllMcGroups, p)) { + McGroupData *mcgroupp = (McGroupData *)QListObj(p); + McGroupMemberXmlOutput(state, "MulticastGroup", mcgroupp); + } + IXmlOutputEndTag(state, "McMembers"); + } + + { + LIST_ITEM *p; + + IXmlOutputStartTag(state, "VirtualFabrics"); + for (p=QListHead(&fabricp->AllVFs); p != NULL; p = QListNext(&fabricp->AllVFs, p)) { + VFData_t *vf = (VFData_t *)QListObj(p); + IXmlOutputStruct(state, "VF", &vf->record, NULL, VFFields); + } + IXmlOutputEndTag(state, "VirtualFabrics"); + } + + IXmlOutputEndTag(state, tag); +} + +void Xml2PrintSnapshot(FILE *file, SnapshotOutputInfo_t *info) +{ + IXmlOutputState_t state; + + /* using SERIALIZE with no indent makes output less pretty but 1/2 the size */ + if (FSUCCESS != IXmlOutputInit(&state, file, 0, IXML_OUTPUT_FLAG_SERIALIZE, info)) + //if (FSUCCESS != IXmlOutputInit(&state, file, 4, IXML_OUTPUT_FLAG_NONE, info)) + goto fail; + + //IXmlOutputStartAttrTag(&state, "Report", NULL, NULL); + Xml2PrintAll(&state, "Snapshot", NULL); + //IXmlOutputEndTag(&state, "Report"); + + IXmlOutputDestroy(&state); + + return; + +fail: + return; +} + + + +#ifndef __VXWORKS__ +FSTATUS Xml2ParseSnapshot(const char *input_file, int quiet, FabricData_t *fabricp, FabricFlags_t flags, boolean allocFull) +{ + unsigned tags_found, fields_found; + const char *filename=input_file; + + if (FSUCCESS != InitFabricData(fabricp, flags)) { + fprintf(stderr, "%s: Unable to initialize fabric data memory\n", g_Top_cmdname); + return FERROR; + } + if (strcmp(input_file, "-") == 0) { + filename="stdin"; + if (! quiet) ProgressPrint(TRUE, "Parsing stdin..."); + if (FSUCCESS != IXmlParseFile(stdin, "stdin", IXML_PARSER_FLAG_NONE, TopLevelFields, NULL, fabricp, NULL, NULL, &tags_found, &fields_found)) { + return FERROR; + } + } else { + if (! quiet) ProgressPrint(TRUE, "Parsing %s...", Top_truncate_str(input_file)); + if (FSUCCESS != IXmlParseInputFile(input_file, IXML_PARSER_FLAG_NONE, TopLevelFields, NULL, fabricp, NULL, NULL, &tags_found, &fields_found)) { + return FERROR; + } + } + if (tags_found != 1 || fields_found != 1) { + fprintf(stderr, "Warning: potentially inaccurate input '%s': found %u recognized top level tags, expected 1\n", filename, tags_found); + } + BuildFabricDataLists(fabricp); + + /* + Resize the switch FDB tables to their full capacity. + */ + if (allocFull) { + LIST_ITEM * n; + for (n = QListHead(&fabricp->AllSWs); n != NULL; n = QListNext(&fabricp->AllSWs, n)) { + NodeData * node = (NodeData*)QListObj(n); + STL_SWITCH_INFO * swInfo = &node->pSwitchInfo->SwitchInfoData; + + // The snapshot may not have SwitchData in it. Tables will have to be provided by application (e.g. + // fabric_sim). + if (!node->switchp) continue; + assert(NodeDataSwitchResizeFDB(node, swInfo->LinearFDBCap, swInfo->MulticastFDBCap) == FSUCCESS); + } + } + + return FSUCCESS; +} +#else +FSTATUS Xml2ParseSnapshot(const char *input_file, int quiet, FabricData_t *fabricp, FabricFlags_t flags, boolean allocFull, XML_Memory_Handling_Suite* memsuite) +{ + unsigned tags_found, fields_found; + const char *filename=input_file; + + if (FSUCCESS != InitFabricData(fabricp, flags)) { + fprintf(stderr, "%s: Unable to initialize fabric data memory\n", g_Top_cmdname); + return FERROR; + } + if (strcmp(input_file, "-") == 0) { + filename="stdin"; + if (! quiet) ProgressPrint(TRUE, "Parsing stdin..."); + if (FSUCCESS != IXmlParseFile(stdin, "stdin", IXML_PARSER_FLAG_NONE, TopLevelFields, NULL, fabricp, NULL, NULL, &tags_found, &fields_found, memsuite)) { + return FERROR; + } + } else { + if (! quiet) ProgressPrint(TRUE, "Parsing %s...", Top_truncate_str(input_file)); + if (FSUCCESS != IXmlParseInputFile(input_file, IXML_PARSER_FLAG_NONE, TopLevelFields, NULL, fabricp, NULL, NULL, &tags_found, &fields_found, memsuite)) { + return FERROR; + } + } + if (tags_found != 1 || fields_found != 1) { + fprintf(stderr, "Warning: potentially inaccurate input '%s': found %u recognized top level tags, expected 1\n", filename, tags_found); + } + BuildFabricDataLists(fabricp); + + /* + Resize the switch FDB tables to their full capacity. + */ + if (allocFull) { + LIST_ITEM * n; + for (n = QListHead(&fabricp->AllSWs); n != NULL; n = QListNext(&fabricp->AllSWs, n)) { + NodeData * node = (NodeData*)QListObj(n); + STL_SWITCH_INFO * swInfo = &node->pSwitchInfo->SwitchInfoData; + + // The snapshot may not have SwitchData in it. Tables will have to be provided by application (e.g. + // fabric_sim). + if (!node->switchp) continue; + assert(NodeDataSwitchResizeFDB(node, swInfo->LinearFDBCap, swInfo->MulticastFDBCap) == FSUCCESS); + } + } + + return FSUCCESS; +} +#endif diff --git a/Topology/sweep.c b/Topology/sweep.c new file mode 100644 index 0000000..1283130 --- /dev/null +++ b/Topology/sweep.c @@ -0,0 +1,4759 @@ +/* BEGIN_ICS_COPYRIGHT7 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT7 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +#include "topology.h" +#include "topology_internal.h" +#include +#include "stl_helper.h" +#include +#include +#include +#include +#include +#include + +#ifdef DBGPRINT +#undef DBGPRINT +#endif +#define DBGPRINT(format, args...) if (g_verbose_file) {fflush(stdout); fprintf(stderr, format, ##args); } + + +static int g_skipswitchinfo= 0; // workaround for open SM +static int g_paclient_state = OMGT_SERVICE_STATE_UNKNOWN; // PaClient/PaServer communications +static FILE *g_verbose_file = NULL; // file for verbose output +static struct omgt_port *g_portHandle = NULL; + + +/* get path from our portGuid to destination portp + * cache path in portp, if called again report from cached value + */ +FSTATUS GetPathToPort(struct omgt_port *port, EUI64 portGuid, PortData *portp) +{ + + OMGT_QUERY query; + FSTATUS status; + PQUERY_RESULT_VALUES pQueryResults = NULL; + IB_PATH_RECORD *pPR = &query.InputValue.IbPathRecord.PathRecord.PathRecord; + + if (portp->pathp) + return FSUCCESS; // already have path record + + if (! portp->PortGUID) + return FINVALID_PARAMETER; // not a directly accessible port + + + memset(&query, 0, sizeof(query)); // initialize reserved fields + query.InputType = InputTypePathRecord; + query.InputValue.IbPathRecord.PathRecord.ComponentMask = + IB_PATH_RECORD_COMP_DGID | IB_PATH_RECORD_COMP_SGID | + IB_PATH_RECORD_COMP_PKEY | IB_PATH_RECORD_COMP_REVERSIBLE | + IB_PATH_RECORD_COMP_NUMBPATH; + (void)omgt_port_get_port_prefix(port, &pPR->SGID.Type.Global.SubnetPrefix); + pPR->DGID.Type.Global.SubnetPrefix = pPR->SGID.Type.Global.SubnetPrefix; + pPR->SGID.Type.Global.InterfaceID = portGuid; + pPR->DGID.Type.Global.InterfaceID = portp->PortGUID; + pPR->Reversible = 1; + pPR->NumbPath = 1; + pPR->P_Key = 0x7fff; + + query.OutputType = OutputTypePathRecord; + + DBGPRINT("Query: Input=%s, Output=%s\n", + iba_sd_query_input_type_msg(query.InputType), + iba_sd_query_result_type_msg(query.OutputType)); + + // this call is synchronous + status = omgt_query_sa(port, &query, &pQueryResults); + if (! pQueryResults) + { + fprintf(stderr, "%*sSA PathRecord query Failed: %s\n", 0, "", iba_fstatus_msg(status)); + goto fail; + } else if (pQueryResults->Status != FSUCCESS) { + fprintf(stderr, "%*sSA PathRecord query Failed: %s MadStatus 0x%x: %s\n", 0, "", + iba_fstatus_msg(pQueryResults->Status), + pQueryResults->MadStatus, iba_sd_mad_status_msg(pQueryResults->MadStatus)); + goto fail; + } else if (pQueryResults->ResultDataSize == 0) { + fprintf(stderr, "%*sNo Path Records Returned\n", 0, ""); + status = FNOT_FOUND; + } else { + PATH_RESULTS *p = (PATH_RESULTS*)pQueryResults->QueryResult; + + DBGPRINT("MadStatus 0x%x: %s\n", pQueryResults->MadStatus, + iba_sd_mad_status_msg(pQueryResults->MadStatus)); + DBGPRINT("%d Bytes Returned\n", pQueryResults->ResultDataSize); + if (p->NumPathRecords == 0) { + fprintf(stderr, "%*sNo Path Records Returned\n", 0, ""); + status = FNOT_FOUND; + } + + //DisplayPathRecord(&(p->PathRecords[0]), 0); + /* we save just the 1st path record */ + portp->pathp = (IB_PATH_RECORD*)MemoryAllocate2AndClear(sizeof(IB_PATH_RECORD), IBA_MEM_FLAG_PREMPTABLE, MYTAG); + if (! portp->pathp) { + fprintf(stderr, "%s: Unable to allocate memory\n", g_Top_cmdname); + goto fail; + } + *(portp->pathp) = p->PathRecords[0]; + status = FSUCCESS; + } + +done: + // omgt_query_sa will have allocated a result buffer + // we must free the buffer when we are done with it + if (pQueryResults) + omgt_free_query_result_buffer(pQueryResults); + return status; + +fail: + // TBD verify this error always results in bad exit status g_exitstatus = 1; + status = FERROR; + goto done; + +} + + + + +/* get path records between 2 ports + * caller must omgt_free_query_result_buffer(*ppQueryResults); + */ +FSTATUS GetPaths(struct omgt_port *port, + PortData *portp1, + PortData *portp2, + PQUERY_RESULT_VALUES *ppQueryResults) +{ + OMGT_QUERY query; + FSTATUS status; + + *ppQueryResults = NULL; + + if (! portp1->PortGUID || ! portp2->PortGUID) + return FINVALID_PARAMETER; // not directly accessible ports + + memset(&query, 0, sizeof(query)); // initialize reserved fields + query.InputType = InputTypePortGuidPair; + query.InputValue.IbPathRecord.PortGuidPair.SourcePortGuid = portp1->PortGUID; + query.InputValue.IbPathRecord.PortGuidPair.SharedSubnetPrefix = portp1->PortInfo.SubnetPrefix; + query.InputValue.IbPathRecord.PortGuidPair.DestPortGuid = portp2->PortGUID; + query.OutputType = OutputTypePathRecord; + + DBGPRINT("Query: Input=%s, Output=%s\n", + iba_sd_query_input_type_msg(query.InputType), + iba_sd_query_result_type_msg(query.OutputType)); + + // this call is synchronous + status = omgt_query_sa(port, &query, ppQueryResults); + + if (! *ppQueryResults) + { + fprintf(stderr, "%*sSA PathRecord query Failed: %s\n", 0, "", iba_fstatus_msg(status)); + goto fail; + } else if ((*ppQueryResults)->Status != FSUCCESS) { + fprintf(stderr, "%*sSA PathRecord query Failed: %s MadStatus 0x%x: %s\n", 0, "", + iba_fstatus_msg((*ppQueryResults)->Status), + (*ppQueryResults)->MadStatus, iba_sd_mad_status_msg((*ppQueryResults)->MadStatus)); + goto fail; + } else if ((*ppQueryResults)->ResultDataSize == 0) { + fprintf(stderr, "%*sNo Path Records Returned\n", 0, ""); + status = FNOT_FOUND; + goto fail; + } else { + PATH_RESULTS *p = (PATH_RESULTS*)(*ppQueryResults)->QueryResult; + + DBGPRINT("MadStatus 0x%x: %s\n", (*ppQueryResults)->MadStatus, + iba_sd_mad_status_msg((*ppQueryResults)->MadStatus)); + DBGPRINT("%d Bytes Returned\n", (*ppQueryResults)->ResultDataSize); + if (p->NumPathRecords == 0) { + fprintf(stderr, "%*sNo Path Records Returned\n", 0, ""); + status = FNOT_FOUND; + goto fail; + } + //DisplayPathRecord(&(p->PathRecords[0]), 0); + + /* caller can process *ppQueryResults */ + status = FSUCCESS; + } + +done: + return status; + +fail: + // TBD verify this error always results in bad exit status g_exitstatus = 1; + status = FERROR; + // omgt_query_sa will have allocated a result buffer + // we must free the buffer when we are done with it + if (*ppQueryResults) { + omgt_free_query_result_buffer(*ppQueryResults); + *ppQueryResults = NULL; + } + goto done; +} + +static void DisplayTraceRecord(STL_TRACE_RECORD *pTraceRecord, int indent) +{ + fprintf(g_verbose_file, "%*sIDGeneration: 0x%04x\n", + indent, "", pTraceRecord->IDGeneration); + fprintf(g_verbose_file, "%*sNodeType: 0x%02x\n", + indent, "", pTraceRecord->NodeType); + fprintf(g_verbose_file, "%*sNodeID: 0x%016"PRIx64" ChassisID: %016"PRIx64"\n", + indent, "", pTraceRecord->NodeID, pTraceRecord->ChassisID); + fprintf(g_verbose_file, "%*sEntryPortID: 0x%016"PRIx64" ExitPortID: %016"PRIx64"\n", + indent, "", pTraceRecord->EntryPortID, pTraceRecord->ExitPortID); + fprintf(g_verbose_file, "%*sEntryPort: 0x%02x ExitPort: 0x%02x\n", + indent, "", pTraceRecord->EntryPort, pTraceRecord->ExitPort); +} + + +FSTATUS GetTraceRoute(struct omgt_port *port, + IB_PATH_RECORD *pathp, + PQUERY_RESULT_VALUES *ppQueryResults) +{ + OMGT_QUERY query; + FSTATUS status; + + *ppQueryResults = NULL; + + memset(&query, 0, sizeof(query)); // initialize reserved fields + query.InputType = InputTypePathRecord; + query.InputValue.TraceRecord.PathRecord.PathRecord = *pathp; + query.InputValue.TraceRecord.PathRecord.PathRecord.NumbPath = 1; + query.InputValue.TraceRecord.PathRecord.ComponentMask = IB_PATH_RECORD_COMP_SERVICEID + | IB_PATH_RECORD_COMP_DGID | IB_PATH_RECORD_COMP_SGID + | IB_PATH_RECORD_COMP_DLID | IB_PATH_RECORD_COMP_SLID + | IB_PATH_RECORD_COMP_REVERSIBLE | IB_PATH_RECORD_COMP_NUMBPATH; + query.OutputType = OutputTypeStlTraceRecord; + + DBGPRINT("Query: Input=%s, Output=%s\n", + iba_sd_query_input_type_msg(query.InputType), + iba_sd_query_result_type_msg(query.OutputType)); + + // this call is synchronous + status = omgt_query_sa(port, &query, ppQueryResults); + + if (! *ppQueryResults) + { + fprintf(stderr, "%*sSA TraceRecord query Failed: %s\n", 0, "", iba_fstatus_msg(status)); + goto fail; + } else if ((*ppQueryResults)->Status != FSUCCESS) { + fprintf(stderr, "%*sSA TraceRecord query Failed: %s MadStatus 0x%x: %s\n", 0, "", + iba_fstatus_msg((*ppQueryResults)->Status), + (*ppQueryResults)->MadStatus, iba_sd_mad_status_msg((*ppQueryResults)->MadStatus)); + goto fail; + } else if ((*ppQueryResults)->ResultDataSize == 0) { + fprintf(stderr, "%*sNo Trace Records Data Returned\n", 0, ""); + status = FNOT_FOUND; + goto fail; + } else { + STL_TRACE_RECORD_RESULTS *p = (STL_TRACE_RECORD_RESULTS*)(*ppQueryResults)->QueryResult; + + DBGPRINT("MadStatus 0x%x: %s\n", (*ppQueryResults)->MadStatus, + iba_sd_mad_status_msg((*ppQueryResults)->MadStatus)); + DBGPRINT("%d Bytes Returned\n", (*ppQueryResults)->ResultDataSize); + if (p->NumTraceRecords == 0) { + fprintf(stderr, "%*sNo Trace Records Found\n", 0, ""); + status = FNOT_FOUND; + goto fail; + } + + //DisplayTraceRecord(&p->TraceRecords[0],0); + + /* caller can process *ppQueryResults */ + status = FSUCCESS; + } + +done: + return status; + +fail: + status = FERROR; + // omgt_query_sa will have allocated a result buffer + // we must free the buffer when we are done with it + if (*ppQueryResults) { + omgt_free_query_result_buffer(*ppQueryResults); + *ppQueryResults = NULL; + } + goto done; +} + +/* + * There are 6 cases for routes: + * 1. CA - CA + * 2. CA to self + * 3. SW Port 0 to CA + * 4. CA to SW Port 0 + * 5. SW Port 0 to SW Port 0 + * 6. SW Port 0 to self + * + * Two self consistent Perspectives of these cases: + * + * Perspective 1: Show all "Links" along the route + * - every Link is a connection between 2 devices + * - every Link involves 2 Ports on different devices + * - never show SW Port 0 in a route + * - never show any ports for a "talk to self" route + * - similarly -F route:... would only select ports which -o route would show + * + * Perspective 2: Show all "Ports" along the route + * - route is a list of Ports (not Links) + * - show every port, including port 0 at start and/or end + * - for "talk to self" routes, show just the 1 port involved + * - similarly -F route:... would select all ports involved in the route + * + * The code below implements Perspective 1. Some code in #if 0 and some + * comments discuss possible approaches to implement perspective 2. + * If the future, perspective 2 could become runtime if flags based on a + * new parameter to this function. + */ + +/* obtain and append to pPoint the trace route information for the given path + * between the given pair of ports. + * The ports are provided to aid in tranversing + * the PortData and NodeData records and as an easy way to verify the + * concistency of the trace route query results against our previous + * port, node and link record queries. + */ +FSTATUS FindTraceRoute(struct omgt_port *port, + EUI64 portGuid, + FabricData_t *fabricp, + PortData *portp1, + PortData *portp2, + IB_PATH_RECORD *pathp, + Point *pPoint) +{ + FSTATUS status; + + PQUERY_RESULT_VALUES pQueryResults = NULL; + STL_TRACE_RECORD *pTraceRecords = NULL; + uint32 NumTraceRecords; + int i = -1; + PortData *p = portp1; + int p_shown = 0; + + if (portp1 == portp2) { + /* special case, internal loopback */ +#if 0 // enable for perspective 2 + status = PointListAppendUniquePort(pPoint, portp1); +#else + status = FSUCCESS; +#endif + goto done; + } + if (portp1->neighbor == portp2) { + /* special case, single link traversed */ + // Since portp1 has a neighbor, neither port is SW Port 0 + // same behavior for perspective 1 and 2 + status = PointListAppendUniquePort(pPoint, portp1); + if (FSUCCESS == status) + status = PointListAppendUniquePort(pPoint, portp2); + goto done; + } + + if (portGuid && !(fabricp->flags & FF_SMADIRECT)) { + status = GetTraceRoute(port, pathp, &pQueryResults); + if (FSUCCESS != status) { + // this error results in bad exit status g_exitstatus = 1; + goto done; + } + NumTraceRecords = ((STL_TRACE_RECORD_RESULTS*)pQueryResults->QueryResult)->NumTraceRecords; + pTraceRecords = ((STL_TRACE_RECORD_RESULTS*)pQueryResults->QueryResult)->TraceRecords; + } else { + status = GenTraceRoutePath(fabricp, pathp, 0, &pTraceRecords, &NumTraceRecords); + if (FSUCCESS != status) { + if (status == FUNAVAILABLE) { + fprintf(stderr, "%s: Routing Tables not available\n", + g_Top_cmdname); + // this error results in bad exit status g_exitstatus = 1; + } else if (status == FNOT_DONE) { + DBGPRINT("Route Incomplete\n"); + // fprintf(stderr, "%s: Route Incomplete\n", g_Top_cmdname); + // don't fail just because some routes are incomplete + status = FSUCCESS; + } else { + DBGPRINT("Unable to determine route: (status=0x%x): %s\n", status, iba_fstatus_msg(status)); + // fprintf(stderr, "opareport: Unable to determine route: (status=0x%x): %s\n", status, iba_fstatus_msg(status)); + // don't fail just because some routes are unavailable + // caller will fail if we match no devices for any of the routes + // tried + status = FSUCCESS; + } + goto done; + } + } + + //printf("%*s%d Hops\n", indent, "", pTrace->NumTraceRecords-1); + + ASSERT(NumTraceRecords > 0); + + /* the first Trace record should be the exit from portp1, however + * not all versions of the SM report this record + */ + if (pTraceRecords[0].NodeType != portp1->nodep->NodeInfo.NodeType) { + /* workaround SM bug, did not report initial exit port */ + // assume portp1 is not a Switch Port 0 + p = portp1->neighbor; + if (! p) { + DBGPRINT("incorrect 1st trace record\n"); + goto badroute; + } + // same behavior for perspective 1 and 2 + status = PointListAppendUniquePort(pPoint, portp1); + if (FSUCCESS != status) + goto done; + } + for (i=0; i< NumTraceRecords; i++) { + if (g_verbose_file) + DisplayTraceRecord(&pTraceRecords[i], 0); + if (p != portp1) { + // same behavior for perspective 1 and 2 + status = PointListAppendUniquePort(pPoint, p); + if (FSUCCESS != status) + goto done; + p_shown = 1; + } + if (pTraceRecords[i].NodeType != STL_NODE_FI) { +#if 0 // enable for perspective 2 + if (i == 0 && p == portp1) { // must be starting at switch Port 0 + status = PointListAppendUniquePort(pPoint, portp1); + if (FSUCCESS != status) + goto done; + } +#endif + p = FindNodePort(p->nodep, pTraceRecords[i].ExitPort); + if (! p) { + DBGPRINT("SW port not found\n"); + goto badroute; + } + if (0 == p->PortNum) { + /* Switch Port 0 thus must be final port */ + if (i+1 != NumTraceRecords) { + DBGPRINT("final switch port 0 error\n"); + goto badroute; + } +#if 0 // enable for perspective 2 + status = PointListAppendUniquePort(pPoint, portp1); + if (FSUCCESS != status) + goto done; +#endif + break; + } + // same behavior for perspective 1 and 2 + status = PointListAppendUniquePort(pPoint, p); + if (FSUCCESS != status) + goto done; + if (p == portp2) { + // this should not happen. If we reach portp2 as the exit + // port of a switch, that implies portp2 must be port 0 of + // the switch which the test above should have caught + // but it doesn't hurt to have this redundant test here to be + // safe. + /* final port must be Switch Port 0 */ + if (i+1 != NumTraceRecords) { + DBGPRINT("final switch port 0 error\n"); + goto badroute; + } + } else { + p = p->neighbor; + if (! p) { + DBGPRINT("incorrect neighbor port\n"); + goto badroute; + } + p_shown = 0; + } + } else if (i == 0) { + /* since we caught CA to CA case above, SM must have given us + * initial Node in path + */ + // same behavior for perspective 1 and 2 + status = PointListAppendUniquePort(pPoint, portp1); + if (FSUCCESS != status) + goto done; + /* unfortunately spec says Exit and Entry Port are 0 for CA, so + * can't verify consistency with portp1 + */ + p = portp1->neighbor; + if (! p) { + DBGPRINT("1st port with no neighbor\n"); + goto badroute; + } + p_shown = 0; + } else if (i+1 != NumTraceRecords) { + DBGPRINT("extra unexpected trace records\n"); + goto badroute; + } + } + if (! p_shown) { + /* workaround SM bug, did not report final hop in route */ + // same behavior for perspective 1 and 2 + status = PointListAppendUniquePort(pPoint, p); + if (FSUCCESS != status) + goto done; + } + if (p != portp2) { + DBGPRINT("ended at wrong port\n"); + goto badroute; + } + +done: + + if (pQueryResults) + omgt_free_query_result_buffer(pQueryResults); + if (! portGuid && pTraceRecords) + MemoryDeallocate(pTraceRecords); + + return status; + +badroute: + status = FSUCCESS; // might as well process what we can + fprintf(stderr, "%*sRoute reported by SM inconsistent with Trace Route\n", 0, ""); + if (g_verbose_file && i+1 < NumTraceRecords) { + fprintf(g_verbose_file, "%*sRemainder of Route:\n", 0, ""); + // Don't repeat records we already output above + for (i=i+1; i< NumTraceRecords; i++) + DisplayTraceRecord(&pTraceRecords[i], 4); + } + goto done; +} + +/* find trace routes for all paths between 2 given ports */ +FSTATUS FindPortsTraceRoutes(struct omgt_port *port, + EUI64 portGuid, + FabricData_t *fabricp, + PortData *portp1, + PortData *portp2, + Point *pPoint) +{ + + PQUERY_RESULT_VALUES pQueryResults = NULL; + uint32 NumPathRecords; + IB_PATH_RECORD *pPathRecords = NULL; + FSTATUS status; + int i; + + if (portGuid) { + status = GetPaths(port, portp1, portp2, &pQueryResults); + if (FSUCCESS != status) + goto done; + NumPathRecords = ((PATH_RESULTS*)pQueryResults->QueryResult)->NumPathRecords; + pPathRecords = ((PATH_RESULTS*)pQueryResults->QueryResult)->PathRecords; + } else { + status = GenPaths(fabricp, portp1, portp2, &pPathRecords, &NumPathRecords); + if (FSUCCESS != status) + goto done; + } + + + for (i=0; i< NumPathRecords; i++) { + status = FindTraceRoute(port, portGuid, fabricp, portp1, portp2, &pPathRecords[i], pPoint); + if (FSUCCESS != status) + return status; + } + +done: + if (pQueryResults) + omgt_free_query_result_buffer(pQueryResults); + if (! portGuid && pPathRecords) + MemoryDeallocate(pPathRecords); + + return status; +} + +/* find trace routes for all paths between given node and point */ +FSTATUS FindPortNodeTraceRoutes(struct omgt_port *port, + EUI64 portGuid, + FabricData_t *fabricp, + PortData *portp1, + NodeData *nodep2, + Point *pPoint) +{ + cl_map_item_t *p; + FSTATUS status; + + for (p=cl_qmap_head(&nodep2->Ports); p != cl_qmap_end(&nodep2->Ports); p = cl_qmap_next(p)) { + PortData *portp2= PARENT_STRUCT(p, PortData, NodePortsEntry); + status = FindPortsTraceRoutes(port, portGuid, fabricp, portp1, portp2, pPoint); + if (FSUCCESS != status) + return status; + } + return FSUCCESS; +} + +/* find trace routes for all paths between given port and point */ +FSTATUS FindPortPointTraceRoutes(struct omgt_port *port, + EUI64 portGuid, + FabricData_t *fabricp, + PortData *portp1, + Point *point2, + Point *pPoint) +{ + FSTATUS status; + + switch (point2->Type) { + case POINT_TYPE_PORT: + return FindPortsTraceRoutes(port, portGuid, fabricp, portp1, point2->u.portp, pPoint); + case POINT_TYPE_PORT_LIST: + { + LIST_ITERATOR i; + DLIST *pList = &point2->u.portList; + + for (i=ListHead(pList); i != NULL; i = ListNext(pList, i)) { + PortData *portp = (PortData*)ListObj(i); + status = FindPortsTraceRoutes(port, portGuid, fabricp, portp1, portp, pPoint); + if (FSUCCESS != status) + return status; + } + } + return FSUCCESS; + case POINT_TYPE_NODE: + return FindPortNodeTraceRoutes(port, portGuid, fabricp, portp1, point2->u.nodep, pPoint); + case POINT_TYPE_NODE_LIST: + { + LIST_ITERATOR i; + DLIST *pList = &point2->u.nodeList; + + for (i=ListHead(pList); i != NULL; i = ListNext(pList, i)) { + NodeData *nodep = (NodeData*)ListObj(i); + status = FindPortNodeTraceRoutes(port, portGuid, fabricp, portp1, nodep, pPoint); + if (FSUCCESS != status) + return status; + } + } + return FSUCCESS; +#if !defined(VXWORKS) || defined(BUILD_DMC) + case POINT_TYPE_IOC: + return FindPortNodeTraceRoutes(port, portGuid, fabricp, portp1, point2->u.iocp->ioup->nodep, pPoint); + case POINT_TYPE_IOC_LIST: + { + LIST_ITERATOR i; + DLIST *pList = &point2->u.nodeList; + + for (i=ListHead(pList); i != NULL; i = ListNext(pList, i)) { + IocData *iocp = (IocData*)ListObj(i); + status = FindPortNodeTraceRoutes(port, portGuid, fabricp, portp1, iocp->ioup->nodep, pPoint); + if (FSUCCESS != status) + return status; + } + } + return FSUCCESS; +#endif + case POINT_TYPE_SYSTEM: + { + cl_map_item_t *p; + SystemData *systemp = point2->u.systemp; + + for (p=cl_qmap_head(&systemp->Nodes); p != cl_qmap_end(&systemp->Nodes); p = cl_qmap_next(p)) { + NodeData *nodep = PARENT_STRUCT(p, NodeData, SystemNodesEntry); + status = FindPortNodeTraceRoutes(port, portGuid, fabricp, portp1, nodep, pPoint); + if (FSUCCESS != status) + return status; + } + return FSUCCESS; + } + default: + return FINVALID_PARAMETER; + } +} + +/* find trace routes for all paths between given node and point */ +FSTATUS FindNodePointTraceRoutes(struct omgt_port *port, + EUI64 portGuid, + FabricData_t *fabricp, + NodeData *nodep1, + Point *point2, + Point *pPoint) +{ + cl_map_item_t *p; + FSTATUS status; + + for (p=cl_qmap_head(&nodep1->Ports); p != cl_qmap_end(&nodep1->Ports); p = cl_qmap_next(p)) { + PortData *portp1 = PARENT_STRUCT(p, PortData, NodePortsEntry); + status = FindPortPointTraceRoutes(port, portGuid, fabricp, portp1, point2, pPoint); + if (FSUCCESS != status) + return status; + } + return FSUCCESS; +} + +/* find all ports in trace routes for all paths between 2 given points */ +FSTATUS FindPointsTraceRoutes(struct omgt_port *port, + EUI64 portGuid, + FabricData_t *fabricp, + Point *point1, + Point *point2, + Point *pPoint) +{ + FSTATUS status; + + switch (point1->Type) { + case POINT_TYPE_PORT: + return FindPortPointTraceRoutes(port, portGuid, fabricp, point1->u.portp, point2, pPoint); + case POINT_TYPE_PORT_LIST: + { + LIST_ITERATOR i; + DLIST *pList = &point1->u.portList; + + for (i=ListHead(pList); i != NULL; i = ListNext(pList, i)) { + PortData *portp = (PortData*)ListObj(i); + status = FindPortPointTraceRoutes(port, portGuid, fabricp, portp, point2, pPoint); + if (FSUCCESS != status) + return status; + } + } + return FSUCCESS; + case POINT_TYPE_NODE: + return FindNodePointTraceRoutes(port, portGuid, fabricp, point1->u.nodep, point2, pPoint); + case POINT_TYPE_NODE_LIST: + { + LIST_ITERATOR i; + DLIST *pList = &point1->u.nodeList; + + for (i=ListHead(pList); i != NULL; i = ListNext(pList, i)) { + NodeData *nodep = (NodeData*)ListObj(i); + status = FindNodePointTraceRoutes(port, portGuid, fabricp, nodep, point2, pPoint); + if (FSUCCESS != status) + return status; + } + } + return FSUCCESS; +#if !defined(VXWORKS) || defined(BUILD_DMC) + case POINT_TYPE_IOC: + return FindNodePointTraceRoutes(port, portGuid, fabricp, point1->u.iocp->ioup->nodep, point2, pPoint); + case POINT_TYPE_IOC_LIST: + { + LIST_ITERATOR i; + DLIST *pList = &point1->u.iocList; + + for (i=ListHead(pList); i != NULL; i = ListNext(pList, i)) { + IocData *iocp = (IocData*)ListObj(i); + status = FindNodePointTraceRoutes(port, portGuid, fabricp, iocp->ioup->nodep, point2, pPoint); + if (FSUCCESS != status) + return status; + } + } + return FSUCCESS; +#endif + case POINT_TYPE_SYSTEM: + { + cl_map_item_t *p; + SystemData *systemp = point1->u.systemp; + + for (p=cl_qmap_head(&systemp->Nodes); p != cl_qmap_end(&systemp->Nodes); p = cl_qmap_next(p)) { + NodeData *nodep = PARENT_STRUCT(p, NodeData, SystemNodesEntry); + status = FindNodePointTraceRoutes(port, portGuid, fabricp, nodep, point2, pPoint); + if (FSUCCESS != status) + return status; + } + return FSUCCESS; + } + default: + return FINVALID_PARAMETER; + } +} + +static FSTATUS ParseRoutePoint(struct omgt_port *port, + EUI64 portGuid, + FabricData_t *fabricp, + char* arg, + Point* pPoint, + char **pp) +{ + Point SrcPoint; + Point DestPoint; + FSTATUS status; + + ASSERT(! PointValid(pPoint)); + PointInit(&SrcPoint); + PointInit(&DestPoint); + + if (arg == *pp) { + fprintf(stderr, "%s: Invalid route format: '%s'\n", g_Top_cmdname, arg); + return FINVALID_PARAMETER; + } + status = ParsePoint(fabricp, arg, &SrcPoint, FIND_FLAG_FABRIC, pp); + if (FSUCCESS != status) + return status; + if (**pp != ':') { + fprintf(stderr, "%s: Invalid route format: '%s'\n", g_Top_cmdname, arg); + return FINVALID_PARAMETER; + } + (*pp)++; + status = ParsePoint(fabricp, *pp, &DestPoint, FIND_FLAG_FABRIC, pp); + if (FSUCCESS != status) + return status; + + // now we have 2 valid points, add to pPoint all the Ports in all routes + // between those points + /* TBD - cleanup use of global */ + status = FindPointsTraceRoutes(port, portGuid, fabricp, &SrcPoint, &DestPoint, pPoint); + PointDestroy(&SrcPoint); + PointDestroy(&DestPoint); + if (FSUCCESS != status) + return status; + if (! PointValid(pPoint)) { + fprintf(stderr, "%s: Unable to resolve route: '%s'\n", + g_Top_cmdname, arg); + return FNOT_FOUND; + } + PointCompress(pPoint); + return FSUCCESS; +} + +// focus point syntax also allows route: format +FSTATUS ParseFocusPoint(EUI64 portGuid, + FabricData_t *fabricp, + char* arg, + Point* pPoint, + uint8 find_flag, + char **pp, + boolean allow_route) +{ + char* param; + struct omgt_port *omgt_port_session = NULL; + FSTATUS fstatus = FSUCCESS; + + *pp = arg; + PointInit(pPoint); + if (NULL != (param = ComparePrefix(arg, "route:"))) { + if (! allow_route || ! (find_flag & FIND_FLAG_FABRIC)) { + fprintf(stderr, "%s: Format Not Allowed: '%s'\n", g_Top_cmdname, arg); + fstatus = FINVALID_PARAMETER; + } else { + fstatus = omgt_open_port_by_guid(&omgt_port_session, portGuid, NULL); + if (fstatus != FSUCCESS) { + fprintf(stderr, "%s: Unable to open fabric interface.\n", + g_Top_cmdname); + } else { + omgt_set_timeout(omgt_port_session, fabricp->ms_timeout); + fstatus = ParseRoutePoint(omgt_port_session, portGuid, fabricp, + param, pPoint, pp); + omgt_close_port(omgt_port_session); + } + } + } else { + fstatus = ParsePoint(fabricp, arg, pPoint, find_flag, pp); + } + + return fstatus; +} + +/* get master SM data from SM service record (if available) */ +FSTATUS GetMasterSMData(struct omgt_port *port, + EUI64 portGuid, + FabricData_t *fabricp, + SweepFlags_t flags, + int quiet) +{ + int ix; + FSTATUS status; + OMGT_QUERY query; + PQUERY_RESULT_VALUES pQueryResults = NULL; + uint32 NumServiceRecords; + IB_SERVICE_RECORD *pServiceRecords; + + memset(&fabricp->MasterSMData, 0, sizeof(MasterSMData_t)); // clear master SM data + memset(&query, 0, sizeof(query)); // initialize reserved fields + query.InputType = InputTypeNoInput; + query.OutputType = OutputTypeServiceRecord; + + DBGPRINT("Query: Input=%s, Output=%s\n", + iba_sd_query_input_type_msg(query.InputType), + iba_sd_query_result_type_msg(query.OutputType)); + + // this call is synchronous + status = omgt_query_sa(port, &query, &pQueryResults); + + if (! pQueryResults) + { + fprintf(stderr, "%*sSA ServiceRecord query Failed: %s\n", 0, "", iba_fstatus_msg(status)); + goto fail; + } else if (pQueryResults->Status != FSUCCESS) { + fprintf(stderr, "%*sSA ServiceRecord query Failed: %s MadStatus 0x%x: %s\n", 0, "", + iba_fstatus_msg(pQueryResults->Status), + pQueryResults->MadStatus, iba_sd_mad_status_msg(pQueryResults->MadStatus)); + goto fail; + } else if (pQueryResults->ResultDataSize == 0) { + fprintf(stderr, "%*sNo Service Records Returned\n", 0, ""); + status = FUNAVAILABLE; + } else { + DBGPRINT("MadStatus 0x%x: %s\n", pQueryResults->MadStatus, + iba_sd_mad_status_msg(pQueryResults->MadStatus)); + DBGPRINT("%d Bytes Returned\n", pQueryResults->ResultDataSize); + NumServiceRecords = ((SERVICE_RECORD_RESULTS*)pQueryResults->QueryResult)->NumServiceRecords; + pServiceRecords = ((SERVICE_RECORD_RESULTS*)pQueryResults->QueryResult)->ServiceRecords; + + for (ix = 0; ix < NumServiceRecords; ++ix) + { + if (pServiceRecords[ix].RID.ServiceID == SM_SERVICE_ID) + { + fabricp->MasterSMData.serviceID = pServiceRecords[ix].RID.ServiceID; + fabricp->MasterSMData.version = pServiceRecords[ix].ServiceData8[0]; + fabricp->MasterSMData.capabilityMask = pServiceRecords[ix].ServiceData32[3]; + status = FSUCCESS; + break; + } + } + status = FUNAVAILABLE; + } + +done: + // omgt_query_sa will have allocated a result buffer + // we must free the buffer when we are done with it + if (pQueryResults) + omgt_free_query_result_buffer(pQueryResults); + + return status; + +fail: + status = FERROR; + goto done; + +} // End of GetMasterSMData() + +/* query SMA directly for Node Records for given LID + * on fabric connected to + * given HFI port and put results into pPorts + */ +static FSTATUS GetNodeRecordDirect(struct omgt_port *port, + EUI64 portGuid, + FabricData_t *fabricp, + NodeData *nodep, + STL_LID lid) +{ + FSTATUS status; + STL_NODE_DESCRIPTION NodeDesc; + STL_NODE_INFO NodeInfo; + + status= SmaGetNodeDesc(port, lid, 0, NULL, &NodeDesc); + if (status != FSUCCESS) + { + fprintf(stderr, "%*sSMA Get(NodeDesc) Failed to LID 0x%x Node 0x%016"PRIx64" Name: %.*s: %s\n", 0, "", lid, + nodep->NodeInfo.NodeGUID, + STL_NODE_DESCRIPTION_ARRAY_SIZE, + (char*)nodep->NodeDesc.NodeString, iba_fstatus_msg(status)); + goto fail; + } + + status= SmaGetNodeInfo(port, lid, 0, NULL, &NodeInfo); + if (status != FSUCCESS) + { + fprintf(stderr, "%*sSMA Get(NodeInfo) Failed to LID 0x%x Node 0x%016"PRIx64" Name: %.*s: %s\n", 0, "", lid, + nodep->NodeInfo.NodeGUID, + STL_NODE_DESCRIPTION_ARRAY_SIZE, + (char*)nodep->NodeDesc.NodeString, iba_fstatus_msg(status)); + goto fail; + } + + nodep->NodeDesc = NodeDesc; + nodep->NodeInfo = NodeInfo; + return FSUCCESS; + +fail: + return FERROR; +} + +static FSTATUS GetAllBCTDirect(struct omgt_port *port, + FabricData_t *fabricp, + Point *focus, + int quiet) +{ + cl_map_item_t *p; + FSTATUS status = FSUCCESS; + int ix_node; + int numNodes = cl_qmap_count(&fabricp->AllNodes); + + if (! quiet) ProgressPrint(TRUE, "Getting All Buffer Control Tables..."); + + for ( p = cl_qmap_head(&fabricp->AllNodes), ix_node = 0; p != cl_qmap_end(&fabricp->AllNodes); + p = cl_qmap_next(p), ix_node++ ) + { + NodeData *nodep = PARENT_STRUCT(p, NodeData, AllNodesEntry); + uint8_t numPorts = nodep->NodeInfo.NumPorts; + + if (ix_node%PROGRESS_FREQ == 0) + if (! quiet) ProgressPrint(FALSE, "Processed %6d of %6d Nodes...", ix_node, numNodes); + if (focus && ! CompareNodePoint(nodep, focus)) + continue; + + if (nodep->NodeInfo.NodeType == STL_NODE_SW) + { + // skip port 0 + uint8_t p; + STL_BUFFER_CONTROL_TABLE *pBCT = malloc((numPorts) * sizeof(*pBCT)); + PortData *portp = FindNodePort(nodep, 0); + + if (!portp) { + fprintf(stderr, "%*sSMA Get(BufferControlTable %u %u) Failed to Find Port Data" + "for Node 0x%016"PRIx64" Name: %.*s: %s\n", 0, "", + 0, numPorts, nodep->NodeInfo.NodeGUID, + STL_NODE_DESCRIPTION_ARRAY_SIZE, + (char*)nodep->NodeDesc.NodeString, iba_fstatus_msg(status)); + free(pBCT); + goto done; + } else { + status = SmaGetBufferControlTable(port, portp->EndPortLID, 0, NULL, 1, numPorts, pBCT); + } + if (status != FSUCCESS) + { + fprintf(stderr, "%*sSMA Get(BufferControlTable %u %u) Failed to LID 0x%x " + "Node 0x%016"PRIx64" Name: %.*s: %s\n", 0, "", + 0, numPorts, portp->EndPortLID, nodep->NodeInfo.NodeGUID, + STL_NODE_DESCRIPTION_ARRAY_SIZE, + (char*)nodep->NodeDesc.NodeString, iba_fstatus_msg(status)); + free(pBCT); + goto done; + } else { + for (p = 1; p <= numPorts; p++) { + portp = FindNodePort(nodep, p); + if (!portp) + continue; + // data is undefined for down ports + if (portp->PortInfo.PortStates.s.PortState == IB_PORT_DOWN) + continue; + if (! portp->pBufCtrlTable) { + if ((status = PortDataAllocateBufCtrlTable(fabricp, portp)) != FSUCCESS) + continue; + } + + memcpy(portp->pBufCtrlTable, &pBCT[p-1], sizeof(*portp->pBufCtrlTable)); + } + } + free(pBCT); + } else { + uint8_t p; + STL_BUFFER_CONTROL_TABLE bct; + for (p = 1; p <= numPorts; p++) { + PortData *portp = FindNodePort(nodep, p); + if (!portp) + continue; + + status = SmaGetBufferControlTable(port, portp->EndPortLID, 0, NULL, p, p, &bct); + if (status != FSUCCESS) + { + fprintf(stderr, "%*sSMA Get(BufferControlTable %u) Failed to LID 0x%x " + "Node 0x%016"PRIx64" Name: %.*s: %s\n", 0, "", + p, portp->EndPortLID, nodep->NodeInfo.NodeGUID, + STL_NODE_DESCRIPTION_ARRAY_SIZE, + (char*)nodep->NodeDesc.NodeString, iba_fstatus_msg(status)); + goto done; + } else { + if (! portp->pBufCtrlTable) { + if ((status = PortDataAllocateBufCtrlTable(fabricp, portp)) != FSUCCESS) + continue; + } + memcpy(portp->pBufCtrlTable, &bct, sizeof(*portp->pBufCtrlTable)); + } + } + } + } + +done: + if (! quiet) ProgressPrint(TRUE, "Done Getting Buffer Control Tables"); + + return status; +} + +static FSTATUS GetAllBCTSA(struct omgt_port *port, + FabricData_t *fabricp, + Point *focus, + int quiet) +{ + OMGT_QUERY query; + PQUERY_RESULT_VALUES pQueryResults = NULL; + FSTATUS status = FSUCCESS; + + if (! quiet) ProgressPrint(FALSE, "Getting All Buffer Control Tables..."); + + /* Query all BCT records... */ + memset(&query, 0, sizeof(query)); + query.InputType = InputTypeNoInput; + query.OutputType = OutputTypeStlBufCtrlTabRecord; + + DBGPRINT("Query: Input=%s, Output=%s\n", + iba_sd_query_input_type_msg(query.InputType), + iba_sd_query_result_type_msg(query.OutputType)); + + status = omgt_query_sa(port, &query, &pQueryResults); + if (! pQueryResults) + { + fprintf(stderr, "%*sSA BufferControlTableRecord query Failed: %s\n", 0, "", + iba_fstatus_msg(status)); + status = FERROR; + } else if (pQueryResults->Status != FSUCCESS) { + fprintf(stderr, "%*sSA BufferControlTableRecord query Failed: %s MadStatus 0x%x: %s\n", 0, "", + iba_fstatus_msg(pQueryResults->Status), + pQueryResults->MadStatus, iba_sd_mad_status_msg(pQueryResults->MadStatus)); + status = FERROR; + } else if (pQueryResults->ResultDataSize == 0) { + fprintf(stderr, "%*sNo BufferControlTableRecord Records Returned\n", 0, ""); + } else { + int i; + STL_BUFFER_CONTROL_TABLE_RECORD_RESULTS *result = + ((STL_BUFFER_CONTROL_TABLE_RECORD_RESULTS*)pQueryResults->QueryResult); + STL_BUFFER_CONTROL_TABLE_RECORD *pBCTRecords; + uint32_t numRecords; + + DBGPRINT("MadStatus 0x%x: %s\n", pQueryResults->MadStatus, + iba_sd_mad_status_msg(pQueryResults->MadStatus)); + DBGPRINT("%d Bytes Returned\n", pQueryResults->ResultDataSize); + + numRecords = result->NumBufferControlRecords; + pBCTRecords = result->BufferControlRecords; + + /* ... and place them within the fabric structure */ + for (i=0; inodep->NodeInfo.NodeType == STL_NODE_SW) + port = FindNodePort(port->nodep, pBCTRecords[i].RID.Port); + + if (!port) + continue; + + if (focus && !ComparePortPoint(port, focus)) + continue; + if (! port->pBufCtrlTable) { + if ((status = PortDataAllocateBufCtrlTable(fabricp, port)) != FSUCCESS) + continue; + } + + memcpy(port->pBufCtrlTable, &pBCTRecords[i].BufferControlTable, + sizeof(*port->pBufCtrlTable)); + } + } + + // omgt_query_port_fabric will have allocated a result buffer + // we must free the buffer when we are done with it + if (pQueryResults) + omgt_free_query_result_buffer(pQueryResults); + + if (! quiet) ProgressPrint(TRUE, "Done Getting Buffer Control Tables"); + return status; +} + +FSTATUS GetAllBCTs(EUI64 portGuid, FabricData_t *fabricp, Point *focus, int quiet) +{ + struct omgt_port *omgt_port_session = NULL; + FSTATUS fstatus = FSUCCESS; + + fstatus = omgt_open_port_by_guid(&omgt_port_session, portGuid, NULL); + if (fstatus != FSUCCESS) { + fprintf(stderr, "%s: Unable to open fabric interface.\n", + g_Top_cmdname); + } else { + omgt_set_timeout(omgt_port_session, fabricp->ms_timeout); + if (fabricp->flags & FF_SMADIRECT) { + fstatus = GetAllBCTDirect(omgt_port_session, fabricp, focus, quiet); + } else { + fstatus = GetAllBCTSA(omgt_port_session, fabricp, focus, quiet); + } + omgt_close_port(omgt_port_session); + } + + if (fstatus == FSUCCESS) + fabricp->flags |= FF_BUFCTRLTABLE; + + return fstatus; +} + +/* query all PortInfo Records for given LID on fabric connected to + * given HFI port and put results into pPorts + */ +static FSTATUS GetNodePorts(struct omgt_port *port, + FabricData_t *fabricp, + NodeData *nodep, + cl_qmap_t *pPorts, + EUI64 guid, + STL_LID lid) +{ + OMGT_QUERY query; + PQUERY_RESULT_VALUES pQueryResults = NULL; + uint32 NumPortInfoRecords; + STL_PORTINFO_RECORD *pPortInfoRecords; + FSTATUS status; + int i; + + memset(&query, 0, sizeof(query)); // initialize reserved fields + query.InputType = InputTypeLid; + query.InputValue.PortInfoRecord.Lid = lid; + query.OutputType = OutputTypeStlPortInfoRecord; + + DBGPRINT("Query: Input=%s, Output=%s\n", + iba_sd_query_input_type_msg(query.InputType), + iba_sd_query_result_type_msg(query.OutputType)); + + // this call is synchronous + status = omgt_query_sa(port, &query, &pQueryResults); + if (! pQueryResults) + { + fprintf(stderr, "%*sSA PortInfo query Failed: %s\n", 0, "", iba_fstatus_msg(status)); + goto fail; + } else if (pQueryResults->Status != FSUCCESS) { + fprintf(stderr, "%*sSA PortInfo query Failed: %s MadStatus 0x%x: %s\n", 0, "", + iba_fstatus_msg(pQueryResults->Status), + pQueryResults->MadStatus, iba_sd_mad_status_msg(pQueryResults->MadStatus)); + goto fail; + } else if (pQueryResults->ResultDataSize == 0) { + fprintf(stderr, "%*sNo PortInfo Records Returned\n", 0, ""); + } else { + DBGPRINT("MadStatus 0x%x: %s\n", pQueryResults->MadStatus, + iba_sd_mad_status_msg(pQueryResults->MadStatus)); + DBGPRINT("%d Bytes Returned\n", pQueryResults->ResultDataSize); + NumPortInfoRecords = ((STL_PORTINFO_RECORD_RESULTS*)pQueryResults->QueryResult)->NumPortInfoRecords; + pPortInfoRecords = ((STL_PORTINFO_RECORD_RESULTS*)pQueryResults->QueryResult)->PortInfoRecords; + + for (i=0; iNodeInfo.NodeType == STL_NODE_SW) + { + unsigned i; + for (i=0; i<= nodep->NodeInfo.NumPorts; i++) + { + status= SmaGetPortInfo(port, lid, 0, NULL, i, 0, &PortInfoRecord.PortInfo); + if (status != FSUCCESS) + { + fprintf(stderr, "%*sSMA Get(PortInfo %u) Failed to LID 0x%x Node 0x%016"PRIx64" Name: %.*s: %s\n", 0, "", i, lid, + nodep->NodeInfo.NodeGUID, + STL_NODE_DESCRIPTION_ARRAY_SIZE, + (char*)nodep->NodeDesc.NodeString, iba_fstatus_msg(status)); + goto fail; + } + if (! (fabricp->flags & FF_DOWNPORTINFO) + && PortInfoRecord.PortInfo.PortStates.s.PortState == IB_PORT_DOWN) + { + DBGPRINT("skip down port\n"); + continue; + } + PortInfoRecord.RID.EndPortLID = lid; + PortInfoRecord.RID.PortNum = i; + if (NULL == NodeDataAddPort(fabricp, nodep, guid, &PortInfoRecord)) + goto fail; + //DisplayPortInfoRecord(&PortInfo, 0); + } + } else { + /* router or channel adapter */ + status= SmaGetPortInfo(port, lid, 0, NULL, 0, 0, &PortInfoRecord.PortInfo); + if (status != FSUCCESS) + { + fprintf(stderr, "%*sSMA Get(PortInfo %u) Failed to LID 0x%x Node 0x%016"PRIx64" Name: %.*s: %s\n", 0, "", 0, lid, + nodep->NodeInfo.NodeGUID, + STL_NODE_DESCRIPTION_ARRAY_SIZE, + (char*)nodep->NodeDesc.NodeString, iba_fstatus_msg(status)); + goto fail; + } + PortInfoRecord.RID.EndPortLID = lid; + PortInfoRecord.RID.PortNum = PortInfoRecord.PortInfo.LocalPortNum; + if (NULL == NodeDataAddPort(fabricp, nodep, guid, &PortInfoRecord)) + goto fail; + //DisplayPortInfoRecord(&PortInfo, 0); + } + return FSUCCESS; + +fail: + return FERROR; +} + +/* query all down ports on switch nodes in fabric directly from SMA + * Note: It would have been wonderful if we could have used focus to limit the + * scope of this scan. However many of the focus formats have options to select + * individual ports and that is performed once after Sweep and before reports. + * The focus selection occurs by using the FabricData and searching it for + * matching points. As such there is a catch 22 so when we are asked to report + * all down ports, we must scan them all, even if a focus was specified. + */ +static FSTATUS GetAllDownPortsDirect(struct omgt_port *port, + FabricData_t *fabricp, + int quiet) +{ + FSTATUS status = FSUCCESS; + int ix_node; + + cl_map_item_t *p; + + int num_nodes = cl_qmap_count(&fabricp->AllNodes); + + if (! quiet) ProgressPrint(TRUE, "Getting All Down Switch Ports..."); + for ( p=cl_qmap_head(&fabricp->AllNodes), ix_node = 0; p != cl_qmap_end(&fabricp->AllNodes); + p = cl_qmap_next(p), ix_node++ ) + { + NodeData *nodep = PARENT_STRUCT(p, NodeData, AllNodesEntry); + + if (ix_node%PROGRESS_FREQ == 0) + if (! quiet) ProgressPrint(FALSE, "Processed %6d of %6d Nodes...", ix_node, num_nodes); + + // Process switch nodes + if (nodep->NodeInfo.NodeType == STL_NODE_SW) { + STL_LID lid = nodep->pSwitchInfo->RID.LID; + uint64 guid = nodep->NodeInfo.PortGUID; // SW only used on port 0 + STL_PORTINFO_RECORD PortInfoRecord = {{0}}; + unsigned i; + cl_map_item_t *q; + + // Switch Port 0 should always have been found so start at 1 + for (i=1, q=cl_qmap_head(&nodep->Ports); i<= nodep->NodeInfo.NumPorts; ) { + PortData *portp; + if (q != cl_qmap_end(&nodep->Ports)) { + portp = PARENT_STRUCT(q, PortData, NodePortsEntry); + if (portp->PortNum <= i) + { + q = cl_qmap_next(q); + if (portp->PortNum == i) + i++; + continue; /* skip already found switch ports */ + } + } + // port i not in DB + status= SmaGetPortInfo(port, lid, 0, NULL, i, 0, &PortInfoRecord.PortInfo); + if (status != FSUCCESS) + { + fprintf(stderr, "%*sSMA Get(PortInfo %u) Failed to LID 0x%x Node 0x%016"PRIx64" Name: %.*s: %s\n", 0, "", i, lid, + nodep->NodeInfo.NodeGUID, + STL_NODE_DESCRIPTION_ARRAY_SIZE, + (char*)nodep->NodeDesc.NodeString, iba_fstatus_msg(status)); + goto fail; + } + PortInfoRecord.RID.EndPortLID = lid; + PortInfoRecord.RID.PortNum = i; + // only switch port 0 have a guid + portp = NodeDataAddPort(fabricp, nodep, guid, &PortInfoRecord); + if (NULL == portp) + goto fail; + //DisplayPortInfoRecord(&PortInfo, 0); +fail: + i++; + } + } // End of if (nodep->NodeInfo.NodeType == STL_NODE_SW + + } // End of for ( p=cl_qmap_head(&fabricp->AllNodes) + status = FSUCCESS; // don't let failure to get some devices stop everything + + if (! quiet) ProgressPrint(TRUE, "Done Getting All Down Switch Ports"); + + return (status); + +} // End of GetAllDownPorts() + +/* query all down ports on switch nodes in fabric + */ +static FSTATUS GetAllDownPorts(struct omgt_port *port, + EUI64 portGuid, + FabricData_t *fabricp, + int quiet) +{ + // We must get direct from SMA, SA only tracks Active ports + return GetAllDownPortsDirect(port, fabricp, quiet); +} + +/* if applicable, get the Switch information for the given node */ +static FSTATUS GetNodeSwitchInfo(struct omgt_port *port, + NodeData *nodep, + STL_LID lid) +{ + OMGT_QUERY query; + FSTATUS status; + PQUERY_RESULT_VALUES pQueryResults = NULL; + + if (nodep->NodeInfo.NodeType != STL_NODE_SW + || g_skipswitchinfo) + return FSUCCESS; + + memset(&query, 0, sizeof(query)); // initialize reserved fields + query.InputType = InputTypeLid; + query.InputValue.SwitchInfoRecord.Lid = lid; + query.OutputType = OutputTypeStlSwitchInfoRecord; + + DBGPRINT("Query: Input=%s, Output=%s\n", + iba_sd_query_input_type_msg(query.InputType), + iba_sd_query_result_type_msg(query.OutputType)); + + // this call is synchronous + status = omgt_query_sa(port, &query, &pQueryResults); + if (! pQueryResults) + { + fprintf(stderr, "%*sSA SwitchInfo query Failed: %s\n", 0, "", iba_fstatus_msg(status)); + goto fail; + } else if (pQueryResults->Status != FSUCCESS) { + fprintf(stderr, "%*sSA SwitchInfo query Failed: %s MadStatus 0x%x: %s\n", 0, "", + iba_fstatus_msg(pQueryResults->Status), + pQueryResults->MadStatus, iba_sd_mad_status_msg(pQueryResults->MadStatus)); + goto fail; + } else if (pQueryResults->ResultDataSize == 0) { + fprintf(stderr, "%*sNo SwitchInfo Records Returned\n", 0, ""); + status = FNOT_FOUND; + } else { + STL_SWITCHINFO_RECORD_RESULTS *p = (STL_SWITCHINFO_RECORD_RESULTS*)pQueryResults->QueryResult; + + DBGPRINT("MadStatus 0x%x: %s\n", pQueryResults->MadStatus, + iba_sd_mad_status_msg(pQueryResults->MadStatus)); + DBGPRINT("%d Bytes Returned\n", pQueryResults->ResultDataSize); + if (p->NumSwitchInfoRecords != 1) { + status = FNOT_FOUND; + goto fail; + } + status = NodeDataSetSwitchInfo(nodep, &p->SwitchInfoRecords[0]); + } + +done: + // omgt_query_sa will have allocated a result buffer + // we must free the buffer when we are done with it + if (pQueryResults) + omgt_free_query_result_buffer(pQueryResults); + return status; + +fail: + g_skipswitchinfo= 1; // workaround for open SM + status = FERROR; + goto done; + +} + +/* if applicable, get the Switch information for the given node */ +/* query SMA directly for Switch Info for given LID + * on fabric connected to + * given HFI port and put results into pPorts + */ +static FSTATUS GetNodeSwitchInfoDirect(struct omgt_port *port, NodeData *nodep, STL_LID lid) +{ + FSTATUS status; + STL_SWITCHINFO_RECORD SwitchInfoRecord; + + if (nodep->NodeInfo.NodeType != STL_NODE_SW) + return FSUCCESS; + + status= SmaGetSwitchInfo(port, lid, 0, NULL, &SwitchInfoRecord.SwitchInfoData); + if (status != FSUCCESS) + { + fprintf(stderr, "%*sSMA Get(SwitchInfo) Failed to LID 0x%x Node 0x%016"PRIx64" Name: %.*s: %s\n", 0, "", lid, + nodep->NodeInfo.NodeGUID, + STL_NODE_DESCRIPTION_ARRAY_SIZE, + (char*)nodep->NodeDesc.NodeString, iba_fstatus_msg(status)); + goto fail; + } + SwitchInfoRecord.RID.LID = lid; + + status = NodeDataSetSwitchInfo(nodep, &SwitchInfoRecord); + return FSUCCESS; + +fail: + return FERROR; +} + +#if !defined(VXWORKS) || defined(BUILD_DMC) +static FSTATUS GetIocServices(struct omgt_port *port, IocData *iocp, PortData *portp) +{ + FSTATUS status = FSUCCESS; + uint32 first; + + if (! iocp->IocProfile.ServiceEntries) + goto done; + + iocp->Services = (IOC_SERVICE*)MemoryAllocate2AndClear(sizeof(IOC_SERVICE)*iocp->IocProfile.ServiceEntries, IBA_MEM_FLAG_PREMPTABLE, MYTAG); + if (! iocp->Services) { + status = FINSUFFICIENT_MEMORY; + goto done; + } + for (first=0; first < iocp->IocProfile.ServiceEntries; first+=4) { + uint8 last = MIN(first+3, iocp->IocProfile.ServiceEntries-1); + + /* ignore errors */ + (void)DmGetServiceEntries(port, portp->pathp, + iocp->IocSlot, first, last, &iocp->Services[first]); + } + +done: + return status; +} + +/* get the IOC information for the given IOU */ +static FSTATUS GetIouIocs(struct omgt_port *port, FabricData_t *fabricp, IouData *ioup, PortData *portp) +{ + uint8 slot; + FSTATUS status; + + for (slot=1; slot <= ioup->IouInfo.MaxControllers; slot++) { + IocData *iocp; + uint8 ioc_status = IOC_AT_SLOT(&ioup->IouInfo, slot); + + if (ioc_status != IOC_INSTALLED) + continue; + + iocp = (IocData*)MemoryAllocate2AndClear(sizeof(IocData), IBA_MEM_FLAG_PREMPTABLE, MYTAG); + if (! iocp) { + status = FINSUFFICIENT_MEMORY; + goto done; + } + + iocp->IocSlot = slot; + iocp->ioup = ioup; + ListItemInitState(&iocp->IouIocsEntry); + QListSetObj(&iocp->IouIocsEntry, iocp); + + status = DmGetIocProfile(port, portp->pathp, slot, &iocp->IocProfile); + if (FSUCCESS != status) { + /* skip that IOC */ + MemoryDeallocate(iocp); + continue; + } + if (cl_qmap_insert(&fabricp->AllIOCs, (uint64_t)iocp, &iocp->AllIOCsEntry) != &iocp->AllIOCsEntry) + { + fprintf(stderr, "%s: Duplicate IOC Guids found in IocProfiles: 0x%016"PRIx64", skipping\n", + g_Top_cmdname, iocp->IocProfile.IocGUID); + MemoryDeallocate(iocp); + continue; + } + (void)GetIocServices(port, iocp, portp); + QListInsertTail(&ioup->Iocs, &iocp->IouIocsEntry); + } +done: + return FSUCCESS; +} + +/* if applicable, get the IOU and IOC information for the given node */ +static FSTATUS GetNodeIous(struct omgt_port *port, + EUI64 portGuid, + FabricData_t *fabricp, + NodeData *nodep) +{ + FSTATUS status = FSUCCESS; + PortData *portp; + IouData *ioup; + + /* all ports should report same IOU and IOC info, just use 1st port */ + if (cl_qmap_head(&nodep->Ports) == cl_qmap_end(&nodep->Ports)) + goto done; /* no ports */ + + portp = PARENT_STRUCT(cl_qmap_head(&nodep->Ports), PortData, NodePortsEntry); + if (! portp->PortInfo.CapabilityMask.s.IsDeviceManagementSupported) + goto done; /* no Device Mgmt Agent */ + + status = GetPathToPort(port, portGuid, portp); + if (FSUCCESS != status) + goto done; + + ioup = (IouData*)MemoryAllocate2AndClear(sizeof(IouData), IBA_MEM_FLAG_PREMPTABLE, MYTAG); + if (! ioup) { + status = FINSUFFICIENT_MEMORY; + goto done; + } + + status = DmGetIouInfo(port, portp->pathp, &ioup->IouInfo); + if (FSUCCESS != status) { + MemoryDeallocate(ioup); + goto done; + } + ListItemInitState(&ioup->AllIOUsEntry); + QListSetObj(&ioup->AllIOUsEntry, ioup); + ioup->nodep = nodep; + QListInitState(&ioup->Iocs); + if (! QListInit(&ioup->Iocs)) + { + MemoryDeallocate(ioup); + status = FINSUFFICIENT_RESOURCES; + goto done; + } + nodep->ioup = ioup; + status = GetIouIocs(port, fabricp, ioup, portp); +done: + return status; +} +#endif + +static FSTATUS GetPortCableInfoDirect(struct omgt_port *port, + FabricData_t *fabricp, + PortData *portp, + int quiet) +{ + FSTATUS status = FSUCCESS; + uint8_t cableInfo[STL_CABLE_INFO_DATA_SIZE * 4]; // 2 blocks of lower page 0 and 2 blocks of upper page 0 + uint16_t addr, startAddr; + uint8_t *data; + + if (! IsCableInfoAvailable(&portp->PortInfo)) + return FSUCCESS; + + //Data in Low address space of Cable info is also accesed for Cable Health Report + if(fabricp->flags & FF_CABLELOWPAGE) + startAddr = STL_CIB_STD_LOW_PAGE_ADDR; + else + startAddr = STL_CIB_STD_HIGH_PAGE_ADDR; + + for (addr = startAddr, data=cableInfo; + addr + STL_CABLE_INFO_MAXLEN <= STL_CIB_STD_END_ADDR; addr += STL_CABLE_INFO_DATA_SIZE, data += STL_CABLE_INFO_DATA_SIZE) + { + status = SmaGetCableInfo(port, portp->EndPortLID, 0, NULL, portp->PortNum, addr, STL_CABLE_INFO_MAXLEN, data); + if (status != FSUCCESS) { + fprintf(stderr, "%s: SMA Get(CableInfo) Failed to LID 0x%x Node 0x%016"PRIx64" for port %u. Name: %.*s: %s\n", + g_Top_cmdname, portp->EndPortLID, portp->nodep->NodeInfo.NodeGUID, portp->PortNum, + STL_NODE_DESCRIPTION_ARRAY_SIZE, (char*)portp->nodep->NodeDesc.NodeString, + iba_fstatus_msg(status)); + break; + } + } + + if (status != FSUCCESS) + return status; + + if (! portp->pCableInfoData) { + if ((status = PortDataAllocateCableInfoData(fabricp, portp)) != FSUCCESS) + return status; + } + + //Data in Low address space of Cable info is also copied for Cable Health Report + if(fabricp->flags & FF_CABLELOWPAGE) + memcpy(portp->pCableInfoData, cableInfo, sizeof(cableInfo)); + else + memcpy(portp->pCableInfoData, cableInfo, STL_CIB_STD_LEN); + + return FSUCCESS; +} + +static FSTATUS GetAllCablesDirect(struct omgt_port *port, + FabricData_t *fabricp, + int skip_init_ports, + int quiet) +{ + cl_map_item_t *p; + FSTATUS status = FSUCCESS; + int ix_node; + int numNodes = cl_qmap_count(&fabricp->AllNodes); + + if (! quiet) ProgressPrint(TRUE, "Getting All Cable Info..."); + + for ( p = cl_qmap_head(&fabricp->AllNodes), ix_node = 0; p != cl_qmap_end(&fabricp->AllNodes); + p = cl_qmap_next(p), ix_node++ ) + { + NodeData *nodep = PARENT_STRUCT(p, NodeData, AllNodesEntry); + uint8_t numPorts = nodep->NodeInfo.NumPorts; + uint8_t portNum; + + if (ix_node%PROGRESS_FREQ == 0) + if (! quiet) ProgressPrint(FALSE, "Processed %6d of %6d Nodes...", ix_node, numNodes); + + // switch port 0 has no cable, so just do external ports on switch + // or all ports on HFI + for (portNum = 1; portNum <= numPorts; portNum++) { + PortData *portp = FindNodePort(nodep, portNum); + if (!portp) + continue; + + if (skip_init_ports && IsPortInitialized(portp->PortInfo.PortStates)) + continue; + (void)GetPortCableInfoDirect(port, fabricp, portp, quiet); + } + } + status = FSUCCESS; + + if (! quiet) ProgressPrint(TRUE, "Done Getting Cable Info"); + + return status; +} + +/* query all CableInfo Records on fabric connected to given HFI port + * and put results into PortData's CableInfo. + */ +static FSTATUS GetAllCablesSA(struct omgt_port *port, + FabricData_t *fabricp, + int quiet) +{ + FSTATUS status; + OMGT_QUERY query = {0}; + PQUERY_RESULT_VALUES pQueryResults = NULL; + + query.InputType = InputTypeNoInput; + query.OutputType = OutputTypeStlCableInfoRecord; + + if (!quiet) ProgressPrint(FALSE, "Getting All Cable Info Records..."); + + DBGPRINT("Query: Input=%s, Output=%s\n", + iba_sd_query_input_type_msg(query.InputType), + iba_sd_query_result_type_msg(query.OutputType)); + + // this call is synchronous + status = omgt_query_sa(port, &query, &pQueryResults); + + if (!pQueryResults) { + fprintf(stderr, "%*sSA CableInfo Record query Failed: %s\n", 0, "", iba_fstatus_msg(status)); + goto fail; + } else if (pQueryResults->Status != FSUCCESS) { + fprintf(stderr, "%*sSA CableInfo Record query Failed: %s MadStatus 0x%x: %s\n", 0, "", + iba_fstatus_msg(pQueryResults->Status), + pQueryResults->MadStatus, iba_sd_mad_status_msg(pQueryResults->MadStatus)); + goto fail; + } else if (pQueryResults->ResultDataSize == 0) { + fprintf(stderr, "%*sNo Cable Info Records Returned\n", 0, ""); + } else { + STL_CABLE_INFO_RECORD_RESULTS *p = (STL_CABLE_INFO_RECORD_RESULTS*)pQueryResults->QueryResult; + unsigned int i; + + DBGPRINT("MadStatus 0x%x: %s\n", pQueryResults->MadStatus, + iba_sd_mad_status_msg(pQueryResults->MadStatus)); + DBGPRINT("%d Bytes Returned\n", pQueryResults->ResultDataSize); + + for (i=0; i < p->NumCableInfoRecords; ++i) { + STL_CABLE_INFO_RECORD *pCableInfoRecord = &p->CableInfoRecords[i]; + PortData *portp; + + portp = FindLidPort(fabricp, pCableInfoRecord->LID, pCableInfoRecord->Port); + if (!portp) { + fprintf(stderr, "%s: Can't find Lid 0x%x Port %u: Skipping\n", + g_Top_cmdname, pCableInfoRecord->LID, pCableInfoRecord->Port); + continue; + } + + if (pCableInfoRecord->u1.s.Address < STL_CIB_STD_HIGH_PAGE_ADDR + || pCableInfoRecord->u1.s.Address > STL_CIB_STD_END_ADDR) { + fprintf(stderr, "%s: Cable Info Data Address 0x%x is outside of utilities range on node with" + " Lid 0x%x Port %u: Ignoring\n", + g_Top_cmdname, pCableInfoRecord->u1.s.Address, pCableInfoRecord->LID, + pCableInfoRecord->Port); + continue; + } + + if (! portp->pCableInfoData) { + if ((status = PortDataAllocateCableInfoData(fabricp, portp)) != FSUCCESS) + continue; + } + + memcpy(portp->pCableInfoData + + pCableInfoRecord->u1.s.Address-STL_CIB_STD_HIGH_PAGE_ADDR, + pCableInfoRecord->Data, + MIN(sizeof(pCableInfoRecord->Data), + MIN(pCableInfoRecord->Length + 1, + STL_CIB_STD_LEN - (pCableInfoRecord->u1.s.Address-STL_CIB_STD_HIGH_PAGE_ADDR)))); + } + } + status = FSUCCESS; + if (!quiet) ProgressPrint(TRUE, "Done Getting All Cable Info Records"); + +done: + if (pQueryResults) + omgt_free_query_result_buffer(pQueryResults); + return status; + +fail: + status = FERROR; + goto done; +} + +FSTATUS GetAllCables(struct omgt_port *port, + EUI64 portGuid, + FabricData_t *fabricp, + int quiet) +{ + FSTATUS fstatus = FSUCCESS; + + if (fabricp->flags & FF_SMADIRECT) { + fstatus = GetAllCablesDirect(port, fabricp, FALSE, quiet); + } else { + fstatus = GetAllCablesSA(port, fabricp, quiet); + if (fabricp->flags & FF_DOWNPORTINFO) { + fstatus = GetAllCablesDirect(port, fabricp, TRUE, quiet); + } + } + + return fstatus; +} + +/* query all multicast groups Records on fabric connected to given HFI port + * for a given MGID an dput results into AllMcGroupMember + */ + +FSTATUS GetAllMCGroupMember(FabricData_t *fabricp, McGroupData *mcgroupp, + struct omgt_port *portp, + int quiet, + FILE *g_verbose_file) +{ + + OMGT_QUERY query; + FSTATUS status; + PQUERY_RESULT_VALUES pQueryResults = NULL; + LIST_ITEM *p; + + memset(&query, 0, sizeof(query)); // initialize reserved fields + query.InputType = InputTypeMcGid; + query.InputValue.IbMcMemberRecord.McGid = mcgroupp->MGID; + query.OutputType = OutputTypeMcMemberRecord; + + DBGPRINT("Query: Input=%s, Output=%s\n", + iba_sd_query_input_type_msg(query.InputType), + iba_sd_query_result_type_msg(query.OutputType)); + + // this call is synchronous + status = omgt_query_sa(portp, &query, &pQueryResults); + + if (! pQueryResults) { + fprintf(stderr, "%*sSA McmemberRecord query Failed: %s\n", 0, "", iba_fstatus_msg(status)); + status = FERROR; + // omgt_query_sa will have allocated a result buffer + // we must free the buffer when we are done with it + return status; + } else if (pQueryResults->Status != FSUCCESS) { + fprintf(stderr, "%*sSA McMemberRecord query Failed: %s MadStatus 0x%x: %s\n", 0, "", + iba_fstatus_msg(pQueryResults->Status), + pQueryResults->MadStatus, iba_sd_mad_status_msg(pQueryResults->MadStatus)); + status = FERROR; + // omgt_query_sa will have allocated a result buffer + // we must free the buffer when we are done with it + if (pQueryResults) + omgt_free_query_result_buffer(pQueryResults); + return status; + } else if (pQueryResults->ResultDataSize == 0) { + fprintf(stderr, "%*sNo multicast group Records Returned\n", 0, ""); + //release result buffer + if (pQueryResults) + omgt_free_query_result_buffer(pQueryResults); + status = FUNAVAILABLE; + return status; + + } else { + + MCMEMBER_RECORD_RESULTS *pIbMCRR = (MCMEMBER_RECORD_RESULTS*)pQueryResults->QueryResult; + + DBGPRINT("MadStatus 0x%x: %s\n", pQueryResults->MadStatus, + iba_sd_mad_status_msg(pQueryResults->MadStatus)); + DBGPRINT("%d Bytes Returned\n", pQueryResults->ResultDataSize); + + mcgroupp->NumOfMembers=pIbMCRR->NumMcMemberRecords; + + int i; + for (i=0; iNumMcMemberRecords; ++i) { + + McMemberData *mcmemberp = (McMemberData*)MemoryAllocate2AndClear(sizeof(McMemberData), IBA_MEM_FLAG_PREMPTABLE, MYTAG); + if (!mcmemberp) + return FINSUFFICIENT_MEMORY; + + mcmemberp->MemberInfo = pIbMCRR->McMemberRecords[i]; + mcmemberp->pPort = FindPortGuid(fabricp,pIbMCRR->McMemberRecords[i].RID.PortGID.AsReg64s.L); + + if (mcmemberp->pPort && mcmemberp->pPort->neighbor) { + if (mcmemberp->pPort->neighbor->nodep->NodeInfo.NodeType == STL_NODE_SW) { + NodeData *groupswitch = mcmemberp->pPort->neighbor->nodep; + uint16 switchentryport = mcmemberp->pPort->neighbor->PortNum; + AddEdgeSwitchToGroup(fabricp, mcgroupp, groupswitch, switchentryport); + } + } + + if ((mcmemberp->MemberInfo.RID.PortGID.AsReg64s.H == 0) && (mcmemberp->MemberInfo.RID.PortGID.AsReg64s.L ==0 )) + mcgroupp->NumOfMembers--; // do count as valid member if PortGID is zero + QListSetObj(&mcmemberp->McMembersEntry,mcmemberp); + + // this linear insertion needs to be optimized + boolean found = FALSE; + p=QListHead(&mcgroupp->AllMcGroupMembers); + // insert everything in the fabric structure ordered by PortGID + while (!found && (p != NULL)) { + McMemberData *pMGM = (McMemberData *)QListObj(p); + if (pMGM->MemberInfo.RID.PortGID.AsReg64s.H > mcmemberp->MemberInfo.RID.PortGID.AsReg64s.H) + p = QListNext(&mcgroupp->AllMcGroupMembers, p); + else if (pMGM->MemberInfo.RID.PortGID.AsReg64s.H == mcmemberp->MemberInfo.RID.PortGID.AsReg64s.H) { + if (pMGM->MemberInfo.RID.PortGID.AsReg64s.L > mcmemberp->MemberInfo.RID.PortGID.AsReg64s.L) + p = QListNext(&mcgroupp->AllMcGroupMembers, p); + else { + // insert mc-group-member element + QListInsertNext(&mcgroupp->AllMcGroupMembers,p, &mcmemberp->McMembersEntry); + found = TRUE; + } + } + else { + QListInsertNext(&mcgroupp->AllMcGroupMembers,p, &mcmemberp->McMembersEntry); + found = TRUE; + } + } // end while + if (!found) + QListInsertTail(&mcgroupp->AllMcGroupMembers, &mcmemberp->McMembersEntry); + + } // for end + // set group properties + p=QListHead(&mcgroupp->AllMcGroupMembers); + + McMemberData *pmcmem = (McMemberData *)QListObj(p); + mcgroupp->GroupInfo = pmcmem->MemberInfo; + + } // end else + status = FSUCCESS; + return status; +} + +FSTATUS GetMCGroups(struct omgt_port *port, + EUI64 portGuid, + FabricData_t *fabricp, + int quiet, FILE *m_verbose_file) +{ + + OMGT_QUERY query; + FSTATUS status; + PQUERY_RESULT_VALUES pQueryResults = NULL; + + memset(&query, 0, sizeof(query)); // initialize reserved fields + query.InputType = InputTypeNoInput; + query.OutputType = OutputTypeMcMemberRecord; + + + if (! quiet) ProgressPrint(TRUE, "Getting All MC Records..."); + + DBGPRINT("Query: Input=%s, Output=%s\n", + iba_sd_query_input_type_msg(query.InputType), + iba_sd_query_result_type_msg(query.OutputType)); + + // this call is synchronous + status = omgt_query_sa(port, &query, &pQueryResults); + + if (! pQueryResults) { + fprintf(stderr, "%*sSA McmemberRecord query Failed: %s\n", 0, "", iba_fstatus_msg(status)); + status = FERROR; + // omgt_query_sa will have allocated a result buffer + // we must free the buffer when we are done with it + if (pQueryResults) + omgt_free_query_result_buffer(pQueryResults); + return status; + } else if (pQueryResults->Status != FSUCCESS) { + fprintf(stderr, "%*sSA McMemberRecord query Failed: %s MadStatus 0x%x: %s\n", 0, "", + iba_fstatus_msg(pQueryResults->Status), + pQueryResults->MadStatus, iba_sd_mad_status_msg(pQueryResults->MadStatus)); + status = FERROR; + // omgt_query_sa will have allocated a result buffer + // we must free the buffer when we are done with it + if (pQueryResults) + omgt_free_query_result_buffer(pQueryResults); + return status; + } else if (pQueryResults->ResultDataSize == 0) { + fprintf(stderr, "%*sNo multicast group Records Returned\n", 0, ""); + } else { //// add different mcmember record + MCMEMBER_RECORD_RESULTS *pIbMCRR = (MCMEMBER_RECORD_RESULTS*)pQueryResults->QueryResult; + DBGPRINT("MadStatus 0x%x: %s\n", pQueryResults->MadStatus, + iba_sd_mad_status_msg(pQueryResults->MadStatus)); + DBGPRINT("%d Bytes Returned\n", pQueryResults->ResultDataSize); + + + fabricp->NumOfMcGroups = pIbMCRR->NumMcMemberRecords; + + int i; + for (i=0; i< pIbMCRR->NumMcMemberRecords; ++i) + { + McGroupData *mcgroupp; + boolean new_node; + + if (i%PROGRESS_FREQ == 0) + if (! quiet) ProgressPrint(FALSE, "Processed %6d of %6d MC Records...", i, pIbMCRR->NumMcMemberRecords); + + // collect member info for each McRecord, create the corresponding group and add it to the fabric structure + mcgroupp = FabricDataAddMCGroup(fabricp, port, quiet, &pIbMCRR->McMemberRecords[i], &new_node, m_verbose_file); + if (!mcgroupp) { + // omgt_query_sa will have allocated a result buffer + // we must free the buffer when we are done with it + if (pQueryResults) + omgt_free_query_result_buffer(pQueryResults); + return FERROR; + } + + //do not count as groups in the fabric those with no members + McMemberData *pMCGH = (McMemberData *)QListObj(QListHead(&mcgroupp->AllMcGroupMembers)); + if ((pMCGH->MemberInfo.RID.PortGID.AsReg64s.H ==0) && (pMCGH->MemberInfo.RID.PortGID.AsReg64s.L==0)) + fabricp->NumOfMcGroups--; + } // for end + + } // end else + if (! quiet) ProgressPrint(TRUE, "Done Getting All MC Records"); + + if (pQueryResults) + omgt_free_query_result_buffer(pQueryResults); + return FSUCCESS; + +} + +FSTATUS GetAllMCGroups(EUI64 portGuid, FabricData_t *fabricp, Point *focus, int quiet) +{ + struct omgt_port *omgt_port_session = NULL; + FSTATUS fstatus = FSUCCESS; + + fstatus = omgt_open_port_by_guid(&omgt_port_session, portGuid, NULL); + if (fstatus != FSUCCESS) + fprintf(stderr, "%s: Unable to open fabric interface.\n", g_Top_cmdname); + else { + omgt_set_timeout(omgt_port_session, fabricp->ms_timeout); + fstatus = GetMCGroups(omgt_port_session, portGuid, fabricp, quiet, g_verbose_file); + omgt_close_port(omgt_port_session); + } + + return fstatus; +} + +/* + * Query SMA directly for all Congestion Info Records for given LID + */ +static FSTATUS GetCongestionInfoDirect(struct omgt_port *port, + FabricData_t *fabricp, + NodeData *nodep, + STL_LID lid) +{ + FSTATUS status; + status = SmaGetCongestionInfo(port, lid, 0, NULL, &nodep->CongestionInfo); + if (status != FSUCCESS) + { + fprintf(stderr, "%*sSMA Get(CongestionInfo %u) Failed to LID 0x%x Node 0x%016"PRIx64" Name: %.*s: %s\n", 0, "", 0, lid, + nodep->NodeInfo.NodeGUID, + STL_NODE_DESCRIPTION_ARRAY_SIZE, + (char*)nodep->NodeDesc.NodeString, iba_fstatus_msg(status)); + goto fail; + } + return FSUCCESS; + +fail: + return FERROR; +} + +/* + * Query SA directly for all Congestion Info Records for given LID + */ +static FSTATUS GetCongestionInfo(struct omgt_port *port, + FabricData_t *fabricp, + NodeData *nodep, + STL_LID lid) +{ + OMGT_QUERY query; + FSTATUS status; + PQUERY_RESULT_VALUES pQueryResults = NULL; + STL_CONGESTION_INFO_RECORD *pCongestionRecord = NULL; + + memset(&query, 0, sizeof(query)); // initialize reserved fields + query.InputType = InputTypeLid; + query.InputValue.CongInfoRecord.Lid = lid; + query.OutputType = OutputTypeStlCongInfoRecord; + + DBGPRINT("Query: Input=%s, Output=%s\n", + iba_sd_query_input_type_msg(query.InputType), + iba_sd_query_result_type_msg(query.OutputType)); + + // this call is synchronous + status = omgt_query_sa(port, &query, &pQueryResults); + if (! pQueryResults) + { + fprintf(stderr, "%*sSA CongestionInfo query Failed: %s\n", 0, "", iba_fstatus_msg(status)); + goto fail; + } else if (pQueryResults->Status != FSUCCESS) { + fprintf(stderr, "%*sSA CongestionInfo query Failed: %s MadStatus 0x%x: %s\n", 0, "", + iba_fstatus_msg(pQueryResults->Status), + pQueryResults->MadStatus, iba_sd_mad_status_msg(pQueryResults->MadStatus)); + goto fail; + } else if (pQueryResults->ResultDataSize == 0) { + /* Congestion control might not be enabled so DBGPRINT */ + DBGPRINT("%*sNo CongestionInfo Records Returned\n", 0, ""); + status = FNOT_FOUND; + } else { + STL_CONGESTION_INFO_RECORD_RESULTS *p = (STL_CONGESTION_INFO_RECORD_RESULTS*)pQueryResults->QueryResult; + + DBGPRINT("MadStatus 0x%x: %s\n", pQueryResults->MadStatus, + iba_sd_mad_status_msg(pQueryResults->MadStatus)); + DBGPRINT("%d Bytes Returned\n", pQueryResults->ResultDataSize); + if (p->NumRecords != 1) { + status = FNOT_FOUND; + goto fail; + } + + pCongestionRecord = &p->Records[0]; + memcpy(&nodep->CongestionInfo, &pCongestionRecord->CongestionInfo, sizeof(STL_CONGESTION_INFO)); + } + +done: + // omgt_query_sa will have allocated a result buffer + // we must free the buffer when we are done with it + if (pQueryResults) + omgt_free_query_result_buffer(pQueryResults); + return status; + +fail: + status = FERROR; + goto done; +} + +/* + * Query SA directly for all HFI Congestion Table Records for given LID + */ +static FSTATUS GetHFICongestionControlTable(struct omgt_port *port, + FabricData_t *fabricp, + PortData *portp, + STL_LID lid) +{ + OMGT_QUERY query; + FSTATUS status; + PQUERY_RESULT_VALUES pQueryResults = NULL; + STL_HFI_CONGESTION_CONTROL_TABLE_RECORD *pHFICongestionControlRecord = NULL; + int i = 0; + int entry = 0; + int offset = 0; + + memset(&query, 0, sizeof(query)); // initialize reserved fields + query.InputType = InputTypeLid; + query.InputValue.HFICongCtrlRecord.Lid = lid; + query.OutputType = OutputTypeStlHFICongCtrlRecord; + + DBGPRINT("Query: Input=%s, Output=%s\n", + iba_sd_query_input_type_msg(query.InputType), + iba_sd_query_result_type_msg(query.OutputType)); + + // this call is synchronous + status = omgt_query_sa(port, &query, &pQueryResults); + if (! pQueryResults) + { + fprintf(stderr, "%*sSA HFI Congestion Control Table query Failed: %s\n", 0, "", iba_fstatus_msg(status)); + goto fail; + } else if (pQueryResults->Status != FSUCCESS) { + fprintf(stderr, "%*sSA HFI Congestion Control Table query Failed: %s MadStatus 0x%x: %s\n", 0, "", + iba_fstatus_msg(pQueryResults->Status), + pQueryResults->MadStatus, iba_sd_mad_status_msg(pQueryResults->MadStatus)); + goto fail; + } else if (pQueryResults->ResultDataSize == 0) { + /* Congestion control might not be enabled so DBGPRINT */ + DBGPRINT("%*sNo SA HFI Congestion Control Table Records Returned\n", 0, ""); + status = FNOT_FOUND; + goto done; + } else { + DBGPRINT("MadStatus 0x%x: %s\n", pQueryResults->MadStatus, + iba_sd_mad_status_msg(pQueryResults->MadStatus)); + DBGPRINT("%d Bytes Returned\n", pQueryResults->ResultDataSize); + } + + STL_HFI_CONGESTION_CONTROL_TABLE_RECORD_RESULTS *p = (STL_HFI_CONGESTION_CONTROL_TABLE_RECORD_RESULTS*)pQueryResults->QueryResult; + + /* get CCTI Limit from first record */ + pHFICongestionControlRecord = &p->Records[0]; + portp->CCTI_Limit = pHFICongestionControlRecord->HFICongestionControlTable.CCTI_Limit; + + if (portp->CCTI_Limit >= portp->nodep->CongestionInfo.ControlTableCap * + STL_NUM_CONGESTION_CONTROL_ELEMENTS_BLOCK_ENTRIES) { + fprintf(stderr, "%s Error CCTI_Limit %d >= Congestion Info ControlTableCap %d for LID 0x%x\n", + __func__, + portp->CCTI_Limit, + portp->nodep->CongestionInfo.ControlTableCap * STL_NUM_CONGESTION_CONTROL_ELEMENTS_BLOCK_ENTRIES, + lid); + goto fail; + } + + offset = 0; + + for (i = 0; i < p->NumRecords; i++) { + pHFICongestionControlRecord = &p->Records[i]; + STL_HFI_CONGESTION_CONTROL_TABLE_ENTRY *pHCCTRecordEntries = + (STL_HFI_CONGESTION_CONTROL_TABLE_ENTRY *)pHFICongestionControlRecord->HFICongestionControlTable.CCT_Block_List; + for (entry = 0; entry < STL_NUM_CONGESTION_CONTROL_ELEMENTS_BLOCK_ENTRIES; entry++, offset++) { + if (offset > portp->CCTI_Limit) break; + portp->pCongestionControlTableEntries[offset] = pHCCTRecordEntries[entry]; + } + } +done: + // omgt_query_sa will have allocated a result buffer + // we must free the buffer when we are done with it + if (pQueryResults) + omgt_free_query_result_buffer(pQueryResults); + return status; + +fail: + status = FERROR; + goto done; +} +/* + * Query SMA directly for all HFI Congestion Control Table Records for given LID + */ + +/* Maximum HFICCT size that can fit in a MAD packet */ +#define HFICCTI_MAX_BLOCK 14 + +/* default CCTI limit is 127 or 2 blocks */ +#define DEFAULT_CCTI_BLOCKCNT 2 +static FSTATUS GetHFICongestionControlTableDirect(struct omgt_port *port, + FabricData_t *fabricp, + PortData *portp, + STL_LID lid) +{ + FSTATUS status = FERROR; + uint16_t blocks = DEFAULT_CCTI_BLOCKCNT; + uint16_t start_block = 0; + uint32_t size = 0; + int32_t remainder = 0; + NodeData *nodep = portp->nodep; + STL_HFI_CONGESTION_CONTROL_TABLE *pHFICongestionControl = NULL; + + size = sizeof(STL_HFI_CONGESTION_CONTROL_TABLE) + + (sizeof(STL_HFI_CONGESTION_CONTROL_TABLE_ENTRY) + * STL_NUM_CONGESTION_CONTROL_ELEMENTS_BLOCK_ENTRIES + * (HFICCTI_MAX_BLOCK - 1)); + + if (portp->pCongestionControlTableEntries == NULL) { + goto fail; + } + + pHFICongestionControl = (STL_HFI_CONGESTION_CONTROL_TABLE*)MemoryAllocate2AndClear(size, IBA_MEM_FLAG_PREMPTABLE, MYTAG); + + if (pHFICongestionControl == NULL) { + fprintf(stderr, "SMA Get(HFICongestionControlTable) failed to allocate memory size = %d\n", size); + goto fail; + } + + do { + status = SmaGetHFICongestionControlTable(port, lid, 0, NULL, start_block, blocks, pHFICongestionControl); + + if (status != FSUCCESS) { + fprintf(stderr, "%*sSMA Get(HFICongestionControlTable %u)" + " Failed to LID 0x%x Node 0x%016"PRIx64 + " Name: %.*s: %s\n", 0, "", 0, lid, + nodep->NodeInfo.NodeGUID, + STL_NODE_DESCRIPTION_ARRAY_SIZE, + (char*)nodep->NodeDesc.NodeString, iba_fstatus_msg(status)); + goto fail; + } + + if (start_block == 0) { + portp->CCTI_Limit = pHFICongestionControl->CCTI_Limit; + + if (portp->CCTI_Limit >= portp->nodep->CongestionInfo.ControlTableCap * + STL_NUM_CONGESTION_CONTROL_ELEMENTS_BLOCK_ENTRIES) { + fprintf(stderr, "%s Error CCTI_Limit %d >= Congestion Info ControlTableCap %d for LID 0x%x\n", + __func__, + portp->CCTI_Limit, + portp->nodep->CongestionInfo.ControlTableCap * STL_NUM_CONGESTION_CONTROL_ELEMENTS_BLOCK_ENTRIES, + lid); + goto fail; + } + + remainder = (portp->CCTI_Limit + 1) / STL_NUM_CONGESTION_CONTROL_ELEMENTS_BLOCK_ENTRIES; + } + + if (remainder < blocks) break; + remainder -= blocks; + start_block += blocks; + blocks = (remainder > HFICCTI_MAX_BLOCK) ? HFICCTI_MAX_BLOCK : remainder; + + } while (remainder > 0); + + /* copy CCT entries into portp */ + memcpy(portp->pCongestionControlTableEntries, (STL_HFI_CONGESTION_CONTROL_TABLE_ENTRY *)pHFICongestionControl->CCT_Block_List, + (portp->CCTI_Limit + 1) * (sizeof(STL_HFI_CONGESTION_CONTROL_TABLE_ENTRY))); + + MemoryDeallocate(pHFICongestionControl); + + return FSUCCESS; + +fail: + if (pHFICongestionControl) + MemoryDeallocate(pHFICongestionControl); + + return FERROR; +} + + +/* query all NodeInfo Records on fabric connected to given HFI port + * and put results into fabricp->AllNodes + */ +static FSTATUS GetAllNodes(struct omgt_port *port, + EUI64 portGuid, + FabricData_t *fabricp, + SweepFlags_t flags, + int quiet) +{ + OMGT_QUERY query; + FSTATUS status; + PQUERY_RESULT_VALUES pQueryResults = NULL; + + memset(&query, 0, sizeof(query)); // initialize reserved fields + query.InputType = InputTypeNoInput; + query.OutputType = OutputTypeStlNodeRecord; + + if (! quiet) ProgressPrint(TRUE, "Getting All Node Records..."); + DBGPRINT("Query: Input=%s, Output=%s\n", + iba_sd_query_input_type_msg(query.InputType), + iba_sd_query_result_type_msg(query.OutputType)); + + // this call is synchronous + status = omgt_query_sa(port, &query, &pQueryResults); + + if (! pQueryResults) + { + fprintf(stderr, "%*sSA NodeRecord query Failed: %s\n", 0, "", iba_fstatus_msg(status)); + goto fail; + } else if (pQueryResults->Status != FSUCCESS) { + fprintf(stderr, "%*sSA NodeRecord query Failed: %s MadStatus 0x%x: %s\n", 0, "", + iba_fstatus_msg(pQueryResults->Status), + pQueryResults->MadStatus, iba_sd_mad_status_msg(pQueryResults->MadStatus)); + goto fail; + } else if (pQueryResults->ResultDataSize == 0) { + fprintf(stderr, "%*sNo Node Records Returned\n", 0, ""); + } else { + STL_NODE_RECORD_RESULTS *p = (STL_NODE_RECORD_RESULTS*)pQueryResults->QueryResult; + int i; + + DBGPRINT("MadStatus 0x%x: %s\n", pQueryResults->MadStatus, + iba_sd_mad_status_msg(pQueryResults->MadStatus)); + DBGPRINT("%d Bytes Returned\n", pQueryResults->ResultDataSize); + for (i=0; iNumNodeRecords; ++i) + { + NodeData *nodep; + boolean new_node; + cl_map_item_t *q; + + if (i%PROGRESS_FREQ == 0) + if (! quiet) ProgressPrint(FALSE, "Processed %6d of %6d Nodes...", i, p->NumNodeRecords); + nodep = FabricDataAddNode(fabricp, &p->NodeRecords[i], &new_node); + if (!nodep) { + goto fail; + } + if (new_node && fabricp->flags & FF_SMADIRECT) { + // replace node record data with actual SMA data + (void)GetNodeRecordDirect(port, portGuid, fabricp, nodep, p->NodeRecords[i].RID.LID); + } + //printf("process NodeRecord LID: 0x%x\n", p->NodeRecords[i].RID.LID); + //DisplayNodeRecord(&p->NodeRecords[i], 0); + + // we get 1 NodeRecord per port on a node, AddNode will only save + // 1 NodeData structure per node and discard the duplicates + // (but we need to process their corresponding ports) + if (fabricp->flags & FF_SMADIRECT) + status = GetNodePortsDirect(port, fabricp, nodep, &nodep->Ports, p->NodeRecords[i].NodeInfo.PortGUID, p->NodeRecords[i].RID.LID); + else + status = GetNodePorts(port, fabricp, nodep, &nodep->Ports, p->NodeRecords[i].NodeInfo.PortGUID, p->NodeRecords[i].RID.LID); + if (status != FSUCCESS) + { + // TBD - better handling cleanup of all previous Ports for node + cl_qmap_remove_item(&fabricp->AllNodes, &nodep->AllNodesEntry); + MemoryDeallocate(nodep); + goto fail; + } + + /* Get Congestion Info */ + if (fabricp->flags & FF_SMADIRECT) + GetCongestionInfoDirect(port, fabricp, nodep, p->NodeRecords[i].RID.LID); + else + GetCongestionInfo(port, fabricp, nodep, p->NodeRecords[i].RID.LID); + + /* Get HFI Congestion Control Table */ + for (q = cl_qmap_head(&nodep->Ports); q != cl_qmap_end(&nodep->Ports); q = cl_qmap_next(q)) { + PortData *portp = PARENT_STRUCT(q, PortData, NodePortsEntry); + /* For switches only address switch port 0 */ + if (nodep->NodeInfo.NodeType == STL_NODE_SW && portp->PortNum) continue; + if (!portp->nodep->CongestionInfo.ControlTableCap) continue; + if (PortDataAllocateCongestionControlTableEntries(fabricp, portp)) goto fail; + + if (fabricp->flags & FF_SMADIRECT) + GetHFICongestionControlTableDirect(port, fabricp, portp, p->NodeRecords[i].RID.LID); + else + GetHFICongestionControlTable(port, fabricp, portp, p->NodeRecords[i].RID.LID); + } + + + + // if this was the 1st time we saw the node + if (new_node) { + UpdateNodePmaCapabilities(nodep, TRUE); +#if !defined(VXWORKS) || defined(BUILD_DMC) + if (flags & SWEEP_IOUS) + (void)GetNodeIous(port, portGuid, fabricp, nodep); +#endif + if (flags & SWEEP_SWITCHINFO) { + if (fabricp->flags & FF_SMADIRECT) { + (void)GetNodeSwitchInfoDirect(port, nodep, p->NodeRecords[i].RID.LID); + } else { + (void)GetNodeSwitchInfo(port, nodep, p->NodeRecords[i].RID.LID); + } + } + } + } + } + if (! quiet) ProgressPrint(TRUE, "Done Getting All Node Records"); + if (fabricp->flags & FF_DOWNPORTINFO) { + if (FSUCCESS != (status = GetAllDownPorts(port, portGuid, fabricp, quiet))) + goto done; + } + BuildFabricDataLists(fabricp); + status = FSUCCESS; + +done: + // omgt_query_sa will have allocated a result buffer + // we must free the buffer when we are done with it + if (pQueryResults) + omgt_free_query_result_buffer(pQueryResults); + return status; + +fail: + status = FERROR; + goto done; +} + +/* query all Link Records on fabric connected to given HFI port + * and put results into PortData entries + */ +static FSTATUS GetAllLinks(struct omgt_port *port, + EUI64 portGuid, + FabricData_t *fabricp, + int quiet) +{ + OMGT_QUERY query; + FSTATUS status; + PQUERY_RESULT_VALUES pQueryResults = NULL; + + memset(&query, 0, sizeof(query)); // initialize reserved fields + query.InputType = InputTypeNoInput; + query.OutputType = OutputTypeStlLinkRecord; + + if (! quiet) ProgressPrint(FALSE, "Getting All Link Records..."); + DBGPRINT("Query: Input=%s, Output=%s\n", + iba_sd_query_input_type_msg(query.InputType), + iba_sd_query_result_type_msg(query.OutputType)); + + // this call is synchronous + status = omgt_query_sa(port, &query, &pQueryResults); + + if (! pQueryResults) + { + fprintf(stderr, "%*sSA LinkRecord query Failed: %s\n", 0, "", iba_fstatus_msg(status)); + goto fail; + } else if (pQueryResults->Status != FSUCCESS) { + fprintf(stderr, "%*sSA LinkRecord query Failed: %s MadStatus 0x%x: %s\n", 0, "", + iba_fstatus_msg(pQueryResults->Status), + pQueryResults->MadStatus, iba_sd_mad_status_msg(pQueryResults->MadStatus)); + goto fail; + } else if (pQueryResults->ResultDataSize == 0) { + fprintf(stderr, "%*sNo Link Records Returned\n", 0, ""); + } else { + STL_LINK_RECORD_RESULTS *p = (STL_LINK_RECORD_RESULTS*)pQueryResults->QueryResult; + int i; + + DBGPRINT("MadStatus 0x%x: %s\n", pQueryResults->MadStatus, + iba_sd_mad_status_msg(pQueryResults->MadStatus)); + DBGPRINT("%d Bytes Returned\n", pQueryResults->ResultDataSize); + for (i=0; iNumLinkRecords; ++i) + { + STL_LINK_RECORD *pLinkRecord = &p->LinkRecords[i]; + + // ignore errors + (void)FabricDataAddLinkRecord(fabricp, pLinkRecord); + + //printf("process LinkRecord LID: 0x%x\n", p->LinkRecords[i].RID.LID); + //DisplayLinkRecord(&p->LinkRecords[i], 0); + } + } + status = FSUCCESS; + if (! quiet) ProgressPrint(TRUE, "Done Getting All Link Records"); + +done: + // omgt_query_sa will have allocated a result buffer + // we must free the buffer when we are done with it + if (pQueryResults) + omgt_free_query_result_buffer(pQueryResults); + return status; + +fail: + status = FERROR; + goto done; +} + +/* query all SMInfo Records on fabric connected to given HFI port + * and put results into fabricp->AllSMs + * We always perform this via an SA query. Note that an SMA SMInfo query + * can trigger an SM to resweep in order to find the potentially new + * SM in the fabric which is querying it. + */ +static FSTATUS GetAllSMs(struct omgt_port *port, + EUI64 portGuid, + FabricData_t *fabricp, + int quiet) +{ + OMGT_QUERY query; + FSTATUS status; + PQUERY_RESULT_VALUES pQueryResults = NULL; + + memset(&query, 0, sizeof(query)); // initialize reserved fields + query.InputType = InputTypeNoInput; + query.OutputType = OutputTypeStlSMInfoRecord; + + if (! quiet) ProgressPrint(FALSE, "Getting All SM Info Records..."); + DBGPRINT("Query: Input=%s, Output=%s\n", + iba_sd_query_input_type_msg(query.InputType), + iba_sd_query_result_type_msg(query.OutputType)); + + // this call is synchronous + status = omgt_query_sa(port, &query, &pQueryResults); + + if (! pQueryResults) + { + fprintf(stderr, "%*sSA SmInfoRecord query Failed: %s\n", 0, "", iba_fstatus_msg(status)); + goto fail; + } else if (pQueryResults->Status != FSUCCESS) { + fprintf(stderr, "%*sSA SmInfoRecord query Failed: %s MadStatus 0x%x: %s\n", 0, "", + iba_fstatus_msg(pQueryResults->Status), + pQueryResults->MadStatus, iba_sd_mad_status_msg(pQueryResults->MadStatus)); + goto fail; + } else if (pQueryResults->ResultDataSize == 0) { + fprintf(stderr, "%*sNo SmInfo Records Returned\n", 0, ""); + } else { + STL_SMINFO_RECORD_RESULTS *p = (STL_SMINFO_RECORD_RESULTS*)pQueryResults->QueryResult; + int i; + + DBGPRINT("MadStatus 0x%x: %s\n", pQueryResults->MadStatus, + iba_sd_mad_status_msg(pQueryResults->MadStatus)); + DBGPRINT("%d Bytes Returned\n", pQueryResults->ResultDataSize); + for (i=0; iNumSMInfoRecords; ++i) + { + SMData *smp = (SMData*)MemoryAllocate2AndClear(sizeof(SMData), IBA_MEM_FLAG_PREMPTABLE, MYTAG); + if (! smp) { + fprintf(stderr, "%s: Unable to allocate memory\n", g_Top_cmdname); + goto fail; + } + //printf("process SMInfoRecord LID: 0x%x\n", p->SMInfoRecords[i].RID.LID); + //DisplaySMInfoRecord(&p->SMInfoRecords[i], 0); + + smp->SMInfoRecord = p->SMInfoRecords[i]; + smp->portp = FindLidPort(fabricp, smp->SMInfoRecord.RID.LID, 0); + if (! smp->portp) { + fprintf(stderr, "%s: SM LID not found: 0x%x\n", + g_Top_cmdname, p->SMInfoRecords[i].RID.LID); + MemoryDeallocate(smp); + goto fail; + } + if (&smp->AllSMsEntry != cl_qmap_insert(&fabricp->AllSMs, smp->SMInfoRecord.SMInfo.PortGUID, &smp->AllSMsEntry)) { + fprintf(stderr, "%s: Duplicate SM Port Guids: 0x%016"PRIx64"\n", + g_Top_cmdname, + smp->SMInfoRecord.SMInfo.PortGUID); + MemoryDeallocate(smp); + goto fail; + } + } + } + status = FSUCCESS; + if (! quiet) ProgressPrint(TRUE, "Done Getting All SM Info Records"); + +done: + // omgt_query_sa will have allocated a result buffer + // we must free the buffer when we are done with it + if (pQueryResults) + omgt_free_query_result_buffer(pQueryResults); + return status; + +fail: + status = FERROR; + goto done; +} + +/* query all PortCounters on all ports in fabric; + use PaClient if available, else issue direct PMA query + */ +FSTATUS GetAllPortCounters(EUI64 portGuid, IB_GID localGid, FabricData_t *fabricp, + Point *focus, boolean limitstats, boolean quiet, uint32 begin, uint32 end) +{ + FSTATUS status; + cl_map_item_t *p; +#ifdef PRODUCT_OPENIB_FF + STL_LID lid = 0; + STL_PA_IMAGE_ID_DATA img_id_end = {0}; + STL_PA_IMAGE_ID_DATA img_id_begin = {0}; +#endif + int i=0; + int num_nodes = cl_qmap_count(&fabricp->AllNodes); + uint32 node_count = 0; + uint32 nrsp_node_count = 0; + uint32 nrsp_port_count = 0; + STL_PORT_COUNTERS_DATA PortCountersData = { 0 }; + + if (! quiet) ProgressPrint(TRUE, "Getting All Port Counters..."); + + struct omgt_params params = {.debug_file = g_verbose_file}; + status = omgt_open_port_by_guid(&g_portHandle, portGuid, ¶ms); + if (status != FSUCCESS) { + return status; + } + omgt_set_timeout(g_portHandle, fabricp->ms_timeout); +#ifdef PRODUCT_OPENIB_FF + if ((g_paclient_state == OMGT_SERVICE_STATE_UNKNOWN) && !(fabricp->flags & FF_PMADIRECT)){ + g_paclient_state = omgt_pa_service_connect(g_portHandle); + if (g_paclient_state < 0) { + fprintf(stderr, "GetAllPortCounters: PM/PA Client Unavailable\n"); + return FERROR; + } + } + + //verify pa has necessary capabilities + if (!(fabricp->flags & FF_PMADIRECT)) { + STL_CLASS_PORT_INFO *cpi; + + if (omgt_pa_get_classportinfo(g_portHandle, &cpi) == FSUCCESS) { + STL_PA_CLASS_PORT_INFO_CAPABILITY_MASK paCap; + + memcpy(&paCap, &cpi->CapMask, sizeof(STL_PA_CLASS_PORT_INFO_CAPABILITY_MASK)); + MemoryDeallocate(cpi); + //if trying to query by time, check if feature available + if (begin || end) { + if (!(paCap.s.IsAbsTimeQuerySupported)) { + fprintf(stderr, "%s: PA does not support time queries\n", __func__); + return FERROR; + } + } + } else { + fprintf(stderr, "%s: failed to determine PA capabilities\n", __func__); + return FERROR; + } + + // Verify Images exist before querying + if (end || begin) { + STL_PA_IMAGE_INFO_DATA img_info_end = {{0}}; + + img_id_end.imageNumber = PACLIENT_IMAGE_TIMED; + img_id_end.imageTime.absoluteTime = end ? end : begin; + status = omgt_pa_get_image_info(g_portHandle, img_id_end, &img_info_end); + if (status != FSUCCESS) { + fprintf(stderr, "%s: failed to get image info at %s\n", __func__, ctime((time_t *)&img_id_end.imageTime.absoluteTime)); + return status; + } + img_id_end = img_info_end.imageId; + + status = omgt_pa_freeze_image(g_portHandle, img_id_end, &img_id_end); + if (status != FSUCCESS) { + fprintf(stderr, "%s: failed to freeze image at %s\n", __func__, ctime((time_t *)&img_id_end.imageTime.absoluteTime)); + return status; + } + } + } else if (begin || end) { + DBGPRINT("%s: Ignoring begin and/or end as we are getting counters direct from PMA", __func__); + } +#endif + for (p=cl_qmap_head(&fabricp->AllNodes); p != cl_qmap_end(&fabricp->AllNodes); p = cl_qmap_next(p),i++) { + NodeData *nodep = PARENT_STRUCT(p, NodeData, AllNodesEntry); + PortData *first_portp; + cl_map_item_t *q; + boolean got = FALSE; + boolean fail = FALSE; + + if (i%PROGRESS_FREQ == 0 || node_count == 1) + if (! quiet) ProgressPrint(FALSE, "Processed %6d of %6d Nodes...", node_count, num_nodes); + if (limitstats && focus && ! CompareNodePoint(nodep, focus)) + continue; + if (i%PROGRESS_FREQ == 0) + if (! quiet) ProgressPrint(FALSE, "Processed %6d of %6d Nodes...", i, num_nodes); + if (cl_qmap_head(&nodep->Ports) == cl_qmap_end(&nodep->Ports)) + continue; /* no ports */ + /* issue all switch PMA requests to port 0, its only one with a LID */ + if (nodep->NodeInfo.NodeType == STL_NODE_SW) { + first_portp = PARENT_STRUCT(cl_qmap_head(&nodep->Ports), PortData, NodePortsEntry); +#ifdef PRODUCT_OPENIB_FF + lid = first_portp->PortInfo.LID; +#endif + if (g_paclient_state != OMGT_SERVICE_STATE_OPERATIONAL) { + status = GetPathToPort(g_portHandle, portGuid, first_portp); + if (FSUCCESS != status) { + DBGPRINT("Unable to get Path to Port %d LID 0x%08x Node 0x%016"PRIx64"\n", + first_portp->PortNum, + first_portp->EndPortLID, + first_portp->nodep->NodeInfo.NodeGUID); + DBGPRINT(" Name: %.*s\n", + STL_NODE_DESCRIPTION_ARRAY_SIZE, + (char*)nodep->NodeDesc.NodeString); + //nrsp_port_count+= nodep->NodeInfo.NumPorts; // wrong + nrsp_port_count+= cl_qmap_count(&nodep->Ports); // better + nrsp_node_count++; + continue; + } + } + } else { + first_portp = NULL; + } + + for (q=cl_qmap_head(&nodep->Ports); q != cl_qmap_end(&nodep->Ports); q = cl_qmap_next(q)) { + PortData *portp = PARENT_STRUCT(q, PortData, NodePortsEntry); + + if (focus && ! ComparePortPoint(portp, focus) + && (limitstats || ! portp->neighbor || ! ComparePortPoint(portp->neighbor, focus))) + continue; + +#ifdef PRODUCT_OPENIB_FF + /* use PaClient if available */ + if (g_paclient_state == OMGT_SERVICE_STATE_OPERATIONAL) { + if (!first_portp) lid = portp->PortInfo.LID; + + //if getting port counters by time, get latest counters first + STL_PORT_COUNTERS_DATA portCounters1 = {0}; + + status = omgt_pa_get_port_stats2(g_portHandle, img_id_end, lid, portp->PortNum, + NULL, &portCounters1, NULL, 0, !(end || begin)); //last param is user_counters flag, + //if begin or end set we want raw counters + if (FSUCCESS == status) { + PortCountersData = portCounters1; + } + } +#endif + else { /* issue direct PMA query */ + STL_PORT_STATUS_RSP PortStatus; + + if (! PortHasPma(portp)) + continue; + if (first_portp) { + /* switch, issue query to port 0 */ + if (! nodep->PmaAvoidClassPortInfo) + (void)STLPmGetClassPortInfo(g_portHandle, first_portp); + status = STLPmGetPortStatus(g_portHandle, first_portp, portp->PortNum, &PortStatus); + } else { + /* CA and router, issue query to specific port */ + status = GetPathToPort(g_portHandle, portGuid, portp); + if (FSUCCESS == status) { + if (! nodep->PmaAvoidClassPortInfo) + (void)STLPmGetClassPortInfo(g_portHandle, portp); + status = STLPmGetPortStatus(g_portHandle, portp, portp->PortNum, &PortStatus); + } else { + DBGPRINT("Unable to get Path to Port %d LID 0x%08x Node 0x%016"PRIx64"\n", + portp->PortNum, portp->EndPortLID, + portp->nodep->NodeInfo.NodeGUID); + DBGPRINT(" Name: %.*s\n", + STL_NODE_DESCRIPTION_ARRAY_SIZE, + (char*)portp->nodep->NodeDesc.NodeString); + } + } + if (FSUCCESS == status) { + StlPortStatusToPortCounters(&PortStatus, &PortCountersData, &portp->PortInfo); + } + } + + if (FSUCCESS != status) { + DBGPRINT("Unable to get Port Counters for Port %d LID 0x%08x Node 0x%016"PRIx64"\n", + portp->PortNum, portp->EndPortLID, + portp->nodep->NodeInfo.NodeGUID); + DBGPRINT(" Name: %.*s\n", + STL_NODE_DESCRIPTION_ARRAY_SIZE, + (char*)portp->nodep->NodeDesc.NodeString); + nrsp_port_count++; + fail = TRUE; + continue; + } + + portp->pPortCounters = (STL_PORT_COUNTERS_DATA *)MemoryAllocate2AndClear(sizeof(STL_PORT_COUNTERS_DATA), + IBA_MEM_FLAG_PREMPTABLE, MYTAG); + if (! portp->pPortCounters) { + DBGPRINT("Unable to allocate memory for Port Counters for Port %d LID 0x%08x Node 0x%016"PRIx64"\n", + portp->PortNum, portp->EndPortLID, + portp->nodep->NodeInfo.NodeGUID); + DBGPRINT(" Name: %.*s\n", + STL_NODE_DESCRIPTION_ARRAY_SIZE, + (char*)portp->nodep->NodeDesc.NodeString); + nrsp_port_count++; + fail = TRUE; + continue; + } + + *(portp->pPortCounters) = PortCountersData; + got = TRUE; + } + if (got) + node_count++; + if (fail) + nrsp_node_count++; + } +#ifdef PRODUCT_OPENIB_FF + if ((begin || end) && (g_paclient_state == OMGT_SERVICE_STATE_OPERATIONAL)) { + status = omgt_pa_release_image(g_portHandle, img_id_end); + if (status != FSUCCESS) { + fprintf(stderr, "%s: failed to release frozen image at %s\n", __func__, ctime((time_t *)&img_id_end.imageTime.absoluteTime)); + return status; + } + } + if (begin && end && (g_paclient_state == OMGT_SERVICE_STATE_OPERATIONAL)) { + STL_PA_IMAGE_INFO_DATA img_info_begin = {{0}}; + // Verify Image exists + img_id_begin.imageNumber = PACLIENT_IMAGE_TIMED; + img_id_begin.imageTime.absoluteTime = begin; + status = omgt_pa_get_image_info(g_portHandle, img_id_begin, &img_info_begin); + if (status != FSUCCESS) { + fprintf(stderr, "%s: failed to get image info at %s\n", __func__, ctime((time_t *)&img_id_begin.imageTime.absoluteTime)); + return status; + } + img_id_begin = img_info_begin.imageId; + + status = omgt_pa_freeze_image(g_portHandle, img_id_begin, &img_id_begin); + if (status == FSUCCESS) { + for (i = 0, p = cl_qmap_head(&fabricp->AllNodes); p != cl_qmap_end(&fabricp->AllNodes); p = cl_qmap_next(p), i++) + { + NodeData *nodep = PARENT_STRUCT(p, NodeData, AllNodesEntry); + PortData *first_portp; + cl_map_item_t *q; + + if (limitstats && focus && ! CompareNodePoint(nodep, focus)) + continue; + if (i%PROGRESS_FREQ == 0) + if (! quiet) ProgressPrint(FALSE, "Processed %6d of %6d Nodes...", i, num_nodes); + if (cl_qmap_head(&nodep->Ports) == cl_qmap_end(&nodep->Ports)) + continue; /* no ports */ + /* issue all switch PMA requests to port 0, its only one with a LID */ + if (nodep->NodeInfo.NodeType == STL_NODE_SW) { + first_portp = PARENT_STRUCT(cl_qmap_head(&nodep->Ports), PortData, NodePortsEntry); + lid = first_portp->PortInfo.LID; + } else { + first_portp = NULL; + } + + for (q=cl_qmap_head(&nodep->Ports); q != cl_qmap_end(&nodep->Ports); q = cl_qmap_next(q)) { + PortData *portp = PARENT_STRUCT(q, PortData, NodePortsEntry); + + if (focus && ! ComparePortPoint(portp, focus) + && (limitstats || ! portp->neighbor || ! ComparePortPoint(portp->neighbor, focus))) + continue; + if (!portp->pPortCounters) continue; + + if (!first_portp) lid = portp->PortInfo.LID; + + STL_PORT_COUNTERS_DATA portCounters2 = {0}; + + status = omgt_pa_get_port_stats2(g_portHandle, img_id_begin, lid, portp->PortNum, + NULL, &portCounters2, NULL, 0, 0); + if (FSUCCESS == status) { + + CounterSelectMask_t clearedCounters = DiffPACounters( + portp->pPortCounters, &portCounters2, portp->pPortCounters); + + if (clearedCounters.AsReg32) { + char counterBuf[128]; + + FormatStlCounterSelectMask(counterBuf, clearedCounters); + fprintf(stderr, "Counters reset on LID 0x%x port %u Node 0x%016"PRIx64" Name: %.*s, reporting latest count: %s\n", + lid, portp->PortNum, portp->nodep->NodeInfo.NodeGUID, + STL_NODE_DESCRIPTION_ARRAY_SIZE, (char *)portp->nodep->NodeDesc.NodeString, + counterBuf); + } + } + } + } // END: for all nodes + status = omgt_pa_release_image(g_portHandle, img_id_begin); + if (status != FSUCCESS) { + fprintf(stderr, "%s: failed to release frozen image at %s\n", __func__, ctime((time_t *)&img_id_begin.imageTime.absoluteTime)); + return status; + } + } else if (status != FSUCCESS) { + fprintf(stderr, "%s: failed to freeze image at %s\n", __func__, ctime((time_t *)&img_id_begin.imageTime.absoluteTime)); + return status; + } + } +#endif + + + //Close the opamgt port handle + if (g_portHandle) { + omgt_close_port(g_portHandle); + g_portHandle = NULL; +#ifdef PRODUCT_OPENIB_FF + g_paclient_state = OMGT_SERVICE_STATE_UNKNOWN; +#endif + } + + if (! quiet) ProgressPrint(TRUE, "Done Getting All Port Counters"); + if (nrsp_port_count) + if (! quiet) ProgressPrint(TRUE, "Unable to get %u Ports on %u Nodes", nrsp_port_count, nrsp_node_count); + fabricp->flags |= FF_STATS; + return FSUCCESS; // TBD +} + +static FSTATUS GetAllVFs(struct omgt_port *port, EUI64 portGuid, FabricData_t *fabricp, int quiet) +{ + FSTATUS status = FERROR; + OMGT_QUERY query; + PQUERY_RESULT_VALUES pQueryResults; + STL_VFINFO_RECORD_RESULTS * pinfos; + STL_VFINFO_RECORD * pinfo; + int i; + + if (! quiet) ProgressPrint(FALSE, "Getting vFabric Records..."); + + memset(&query, 0, sizeof(query)); // initialize reserved fields + query.InputType = InputTypeNoInput; + query.OutputType = OutputTypeStlVfInfoRecord; + pQueryResults = NULL; + + DBGPRINT("Query: Input=%s, Output=%s\n", + iba_sd_query_input_type_msg(query.InputType), + iba_sd_query_result_type_msg(query.OutputType)); + + // this call is synchronous + status = omgt_query_sa(port, &query, &pQueryResults); + if (!pQueryResults) + { + fprintf( stderr, "%*sSA VFInfo query Failed: %s\n", 0, "", + iba_fstatus_msg(status) ); + return FERROR; + } + + if (pQueryResults->Status != FSUCCESS) { + fprintf( stderr, + "%*sSA VFInfo query Failed: %s MadStatus 0x%x: %s\n", 0, "", + iba_fstatus_msg(pQueryResults->Status), pQueryResults->MadStatus, + iba_sd_mad_status_msg(pQueryResults->MadStatus) ); + goto free; + } + + if (!pQueryResults->ResultDataSize) { + fprintf(stderr, "%*sSA VFInfo query Returned Invalid Data Size:%u\n", + 0, "", pQueryResults->ResultDataSize ); + goto free; + } + + DBGPRINT("MadStatus 0x%x: %s\n", pQueryResults->MadStatus, + iba_sd_mad_status_msg(pQueryResults->MadStatus)); + DBGPRINT("%d Bytes Returned\n", pQueryResults->ResultDataSize); + + pinfos = (STL_VFINFO_RECORD_RESULTS *)pQueryResults->QueryResult; + pinfo = pinfos->VfInfoRecords; + + for (i = 0; i < pinfos->NumVfInfoRecords; ++i, ++pinfo) { + VFData_t *vf = (VFData_t *)MemoryAllocate2AndClear(sizeof(VFData_t), IBA_MEM_FLAG_PREMPTABLE, MYTAG); + if (!vf) { + fprintf(stderr, "%s: Unable to allocate memory\n", g_Top_cmdname); + goto free; + } + vf->record = *pinfo; + QListSetObj(&vf->AllVFsEntry, vf); + QListInsertTail(&fabricp->AllVFs, &vf->AllVFsEntry); + } + + status = FSUCCESS; + if (! quiet) ProgressPrint(TRUE, "Done Getting vFabric Records"); + +free: + omgt_free_query_result_buffer(pQueryResults); + return status; +} + +void copySCSCTable(int *ix_rec_scsc, STL_SC_MAPPING_TABLE_RECORD_RESULTS *pSCSCRR, STL_SC_MAPPING_TABLE_RECORD **pSCSCR_2, PortData *portp, int tab) +{ + for ( ; ((*ix_rec_scsc) < pSCSCRR->NumSCSCTableRecords) && + ((*pSCSCR_2)->RID.LID == portp->EndPortLID) && + ((*pSCSCR_2)->RID.InputPort == portp->PortNum); + (*ix_rec_scsc)++, (*pSCSCR_2)++ ) + { + uint8 outport; + outport = (*pSCSCR_2)->RID.OutputPort; + QOSDataAddSCSCMap(portp, outport, tab, (STL_SCSCMAP *)&((*pSCSCR_2)->Map)); + } +} + +void copyVLArbTable(int *ix_rec_vla, STL_VLARB_TABLE *pQOSVLARB, STL_VLARBTABLE_RECORD_RESULTS *pVLATRR, STL_VLARBTABLE_RECORD **pVLATR_2, PortData *portp) +{ + int ix, ix_2; + for ( ix = 0; ((*ix_rec_vla) < pVLATRR->NumVLArbTableRecords) && + (ix < STL_VLARB_NUM_SECTIONS) && + ((*pVLATR_2)->RID.LID == portp->EndPortLID) && + ((*pVLATR_2)->RID.OutputPortNum == portp->PortNum); + (*ix_rec_vla)++, ix++, (*pVLATR_2)++ ) + { + for (ix_2 = 0; ix_2 < VLARB_TABLE_LENGTH; ix_2++) + { + pQOSVLARB[ix].Elements[ix_2] = (*pVLATR_2)->VLArbTable.Elements[ix_2]; + } + } +} + + +void copyPKeyTable(int *ix_rec_pk, STL_PKEY_ELEMENT **pPKEY, STL_PKEYTABLE_RECORD_RESULTS *pPKTRR, STL_P_KEY_TABLE_RECORD **pPKTR_2, PortData *portp, uint16 pkey_cap) +{ + int ix; + for ( ; ((*ix_rec_pk) < pPKTRR->NumPKeyTableRecords) && + ((*pPKTR_2)->RID.LID == portp->EndPortLID) && + ((*pPKTR_2)->RID.PortNum == portp->PortNum); + (*pPKTR_2)++, (*ix_rec_pk)++) + { + uint32 ix_base = (*pPKTR_2)->RID.Blocknum * NUM_PKEY_ELEMENTS_BLOCK; + + for ( ix = 0; (ix < NUM_PKEY_ELEMENTS_BLOCK) && + ( (ix_base + ix) < pkey_cap); ix++, (*pPKEY)++ ) + { + (*pPKEY)->AsReg16 = (*pPKTR_2)->PKeyTblData.PartitionTableBlock[ix].AsReg16; + } + } +} + +// TBD - should we do whole fabric queries (which will be large responses) +// or per port queries +/* query all Port VL info from SA + */ +static FSTATUS GetAllPortVLInfoSA(struct omgt_port *port, + FabricData_t *fabricp, + Point *focus, + int quiet, + int *use_scsc) +{ + FSTATUS status = FSUCCESS; + int ix_node, ix_port; + int ix_rec_scsc = 0, ix_rec_slsc = 0, ix_rec_scsl = 0, ix_rec_scvlr = 0, ix_rec_scvlt = 0, + ix_rec_scvlnt = 0, ix_rec_vla = 0, ix_rec_pk = 0; + + cl_map_item_t *p, *p2; + NodeData *nodep; + PortData *portp; + STL_SLSCMAP *pQOSSLSC; + STL_SCSLMAP *pQOSSCSL; + STL_SCVLMAP *pQOSSCVLr; + STL_SCVLMAP *pQOSSCVLt; + STL_SCVLMAP *pQOSSCVLnt; + STL_VLARB_TABLE *pQOSVLARB; + STL_PKEY_ELEMENT *pPKEY; + int num_nodes = cl_qmap_count(&fabricp->AllNodes); + + OMGT_QUERY query; + PQUERY_RESULT_VALUES pQueryResultsSLSCMap = NULL; + PQUERY_RESULT_VALUES pQueryResultsSCSLMap = NULL; + PQUERY_RESULT_VALUES pQueryResultsSCVLrMap = NULL; + PQUERY_RESULT_VALUES pQueryResultsSCVLtMap = NULL; + PQUERY_RESULT_VALUES pQueryResultsSCVLntMap = NULL; + PQUERY_RESULT_VALUES pQueryResultsVLArb = NULL; + PQUERY_RESULT_VALUES pQueryResultsPKey = NULL; + STL_SC_MAPPING_TABLE_RECORD_RESULTS *pSCSCRR = NULL; + STL_SC_MAPPING_TABLE_RECORD *pSCSCR = NULL, *pSCSCR_2 = NULL; + STL_SL2SC_MAPPING_TABLE_RECORD_RESULTS *pSLSCRR = NULL; + STL_SL2SC_MAPPING_TABLE_RECORD *pSLSCR, *pSLSCR_2 = NULL; + STL_SC2SL_MAPPING_TABLE_RECORD_RESULTS *pSCSLRR = NULL; + STL_SC2SL_MAPPING_TABLE_RECORD *pSCSLR, *pSCSLR_2 = NULL; + STL_SC2PVL_R_MAPPING_TABLE_RECORD_RESULTS *pSCVLrRR = NULL; + STL_SC2PVL_R_MAPPING_TABLE_RECORD *pSCVLrR = NULL, *pSCVLrR_2 = NULL; + STL_SC2PVL_T_MAPPING_TABLE_RECORD_RESULTS *pSCVLtRR = NULL; + STL_SC2PVL_T_MAPPING_TABLE_RECORD *pSCVLtR = NULL, *pSCVLtR_2 = NULL; + STL_SC2PVL_NT_MAPPING_TABLE_RECORD_RESULTS *pSCVLntRR = NULL; + STL_SC2PVL_NT_MAPPING_TABLE_RECORD *pSCVLntR = NULL, *pSCVLntR_2 = NULL; + STL_VLARBTABLE_RECORD_RESULTS *pVLATRR = NULL; + STL_VLARBTABLE_RECORD *pVLATR = NULL, *pVLATR_2 = NULL; + STL_PKEYTABLE_RECORD_RESULTS *pPKTRR = NULL; + STL_P_KEY_TABLE_RECORD *pPKTR = NULL, *pPKTR_2 = NULL; + + if (! quiet) ProgressPrint(TRUE, "Getting All Port VL Tables..."); + + // Query all SLSC Map records + memset(&query, 0, sizeof(query)); // initialize reserved fields + query.InputType = InputTypeNoInput; + query.OutputType = OutputTypeStlSLSCTableRecord; + pQueryResultsSLSCMap = NULL; + pSLSCRR = NULL; + + DBGPRINT("Query: Input=%s, Output=%s\n", + iba_sd_query_input_type_msg(query.InputType), + iba_sd_query_result_type_msg(query.OutputType)); + + // this call is synchronous + status = omgt_query_sa(port, &query, &pQueryResultsSLSCMap); + if (! pQueryResultsSLSCMap) + { + fprintf( stderr, "%*sSA SLSCMap query Failed: %s\n", 0, "", + iba_fstatus_msg(status) ); + goto fail; + + } else if (pQueryResultsSLSCMap->Status != FSUCCESS) { + fprintf( stderr, + "%*sSA SLSCMap query Failed: %s MadStatus 0x%x: %s\n", 0, "", + iba_fstatus_msg(pQueryResultsSLSCMap->Status), + pQueryResultsSLSCMap->MadStatus, + iba_sd_mad_status_msg(pQueryResultsSLSCMap->MadStatus) ); + goto fail; + } + + pSLSCRR = (STL_SL2SC_MAPPING_TABLE_RECORD_RESULTS*)pQueryResultsSLSCMap->QueryResult; + if (!pQueryResultsSLSCMap->ResultDataSize) { + pSLSCR = NULL; + } else { + pSLSCR = pSLSCRR->SLSCRecords; + } + + DBGPRINT("MadStatus 0x%x: %s\n", pQueryResultsSLSCMap->MadStatus, + iba_sd_mad_status_msg(pQueryResultsSLSCMap->MadStatus)); + DBGPRINT("%d Bytes Returned\n", pQueryResultsSLSCMap->ResultDataSize); + + // Query all SCSL Map records + memset(&query, 0, sizeof(query)); // initialize reserved fields + query.InputType = InputTypeNoInput; + query.OutputType = OutputTypeStlSCSLTableRecord; + pQueryResultsSCSLMap = NULL; + pSCSLRR = NULL; + + DBGPRINT("Query: Input=%s, Output=%s\n", + iba_sd_query_input_type_msg(query.InputType), + iba_sd_query_result_type_msg(query.OutputType)); + + // this call is synchronous + status = omgt_query_sa(port, &query, &pQueryResultsSCSLMap); + if (! pQueryResultsSCSLMap) + { + fprintf( stderr, "%*sSA SCSLMap query Failed: %s\n", 0, "", + iba_fstatus_msg(status) ); + goto fail; + + } else if (pQueryResultsSCSLMap->Status != FSUCCESS) { + fprintf( stderr, + "%*sSA SCSLMap query Failed: %s MadStatus 0x%x: %s\n", 0, "", + iba_fstatus_msg(pQueryResultsSCSLMap->Status), + pQueryResultsSCSLMap->MadStatus, + iba_sd_mad_status_msg(pQueryResultsSCSLMap->MadStatus) ); + goto fail; + } + + pSCSLRR = (STL_SC2SL_MAPPING_TABLE_RECORD_RESULTS*)pQueryResultsSCSLMap->QueryResult; + if (!pQueryResultsSCSLMap->ResultDataSize) { + pSCSLR = NULL; + } else { + pSCSLR = pSCSLRR->SCSLRecords; + } + + DBGPRINT("MadStatus 0x%x: %s\n", pQueryResultsSCSLMap->MadStatus, + iba_sd_mad_status_msg(pQueryResultsSCSLMap->MadStatus)); + DBGPRINT("%d Bytes Returned\n", pQueryResultsSCSLMap->ResultDataSize); + + // Query all SCVLr Table records + memset(&query, 0, sizeof(query)); // initialize reserved fields + query.InputType = InputTypeNoInput; + query.OutputType = OutputTypeStlSCVLrTableRecord; + pQueryResultsSCVLrMap = NULL; + pSCVLrRR = NULL; + + DBGPRINT("Query: Input=%s, Output=%s\n", + iba_sd_query_input_type_msg(query.InputType), + iba_sd_query_result_type_msg(query.OutputType)); + + // this call is synchronous + status = omgt_query_sa(port, &query, &pQueryResultsSCVLrMap); + if (! pQueryResultsSCVLrMap) + { + fprintf( stderr, "%*sSA SCVLr query Failed: %s\n", 0, "", + iba_fstatus_msg(status) ); + goto fail; + } else if (pQueryResultsSCVLrMap->Status != FSUCCESS) { + fprintf( stderr, + "%*sSA SCVLr query Failed: %s MadStatus 0x%x: %s\n", 0, "", + iba_fstatus_msg(pQueryResultsSCVLrMap->Status), + pQueryResultsSCVLrMap->MadStatus, + iba_sd_mad_status_msg(pQueryResultsSCVLrMap->MadStatus) ); + goto fail; + } + + pSCVLrRR = (STL_SC2PVL_R_MAPPING_TABLE_RECORD_RESULTS*)pQueryResultsSCVLrMap->QueryResult; + if (!pQueryResultsSCVLrMap->ResultDataSize) { + pSCVLrR = NULL; + } else { + pSCVLrR = pSCVLrRR->SCVLrRecords; + } + + DBGPRINT("MadStatus 0x%x: %s\n", pQueryResultsSCVLrMap->MadStatus, + iba_sd_mad_status_msg(pQueryResultsSCVLrMap->MadStatus)); + DBGPRINT("%d Bytes Returned\n", pQueryResultsSCVLrMap->ResultDataSize); + + // Query all SCVLt Table records + memset(&query, 0, sizeof(query)); // initialize reserved fields + query.InputType = InputTypeNoInput; + query.OutputType = OutputTypeStlSCVLtTableRecord; + pQueryResultsSCVLtMap = NULL; + pSCVLtRR = NULL; + + DBGPRINT("Query: Input=%s, Output=%s\n", + iba_sd_query_input_type_msg(query.InputType), + iba_sd_query_result_type_msg(query.OutputType)); + + // this call is synchronous + status = omgt_query_sa(port, &query, &pQueryResultsSCVLtMap); + if (! pQueryResultsSCVLtMap) + { + fprintf( stderr, "%*sSA SCVLt query Failed: %s\n", 0, "", + iba_fstatus_msg(status) ); + goto fail; + } else if (pQueryResultsSCVLtMap->Status != FSUCCESS) { + fprintf( stderr, + "%*sSA SCVLt query Failed: %s MadStatus 0x%x: %s\n", 0, "", + iba_fstatus_msg(pQueryResultsSCVLtMap->Status), + pQueryResultsSCVLtMap->MadStatus, + iba_sd_mad_status_msg(pQueryResultsSCVLtMap->MadStatus) ); + goto fail; + } + + pSCVLtRR = (STL_SC2PVL_T_MAPPING_TABLE_RECORD_RESULTS*)pQueryResultsSCVLtMap->QueryResult; + if (!pQueryResultsSCVLtMap->ResultDataSize) { + pSCVLtR = NULL; + } else { + pSCVLtR = pSCVLtRR->SCVLtRecords; + } + + DBGPRINT("MadStatus 0x%x: %s\n", pQueryResultsSCVLtMap->MadStatus, + iba_sd_mad_status_msg(pQueryResultsSCVLtMap->MadStatus)); + DBGPRINT("%d Bytes Returned\n", pQueryResultsSCVLtMap->ResultDataSize); + + // Query all SCVLnt Table records + memset(&query, 0, sizeof(query)); + query.InputType = InputTypeNoInput; + query.OutputType = OutputTypeStlSCVLntTableRecord; + pQueryResultsSCVLntMap = NULL; + pSCVLntRR = NULL; + + DBGPRINT("Query: Input=%s, Output=%s\n", + iba_sd_query_input_type_msg(query.InputType), + iba_sd_query_result_type_msg(query.OutputType)); + + status = omgt_query_sa(port, &query, &pQueryResultsSCVLntMap); + if (! pQueryResultsSCVLntMap) { + fprintf(stderr, "%*sSA SCVLnt query Failed: %s\n", 0, "", + iba_fstatus_msg(status)); + goto fail; + } else if (pQueryResultsSCVLntMap->Status != FSUCCESS) { + fprintf(stderr, "%*sSA SCVLnt query Failed: %s MadStatus 0x%x: %s\n", 0, "", + iba_fstatus_msg(pQueryResultsSCVLntMap->Status), + pQueryResultsSCVLntMap->MadStatus, + iba_sd_mad_status_msg(pQueryResultsSCVLntMap->MadStatus)); + goto fail; + } + + pSCVLntRR = (STL_SC2PVL_NT_MAPPING_TABLE_RECORD_RESULTS*)pQueryResultsSCVLntMap->QueryResult; + if (!pQueryResultsSCVLntMap->ResultDataSize) { + pSCVLntR = NULL; + } else { + pSCVLntR = pSCVLntRR->SCVLntRecords; + } + + DBGPRINT("MadStatus 0x%x: %s\n", pQueryResultsSCVLntMap->MadStatus, + iba_sd_mad_status_msg(pQueryResultsSCVLntMap->MadStatus)); + DBGPRINT("%d Bytes Returned\n", pQueryResultsSCVLntMap->ResultDataSize); + + // Query all VLArb Table records + memset(&query, 0, sizeof(query)); // initialize reserved fields + query.InputType = InputTypeNoInput; + query.OutputType = OutputTypeStlVLArbTableRecord; + pQueryResultsVLArb = NULL; + pVLATRR = NULL; + + DBGPRINT("Query: Input=%s, Output=%s\n", + iba_sd_query_input_type_msg(query.InputType), + iba_sd_query_result_type_msg(query.OutputType)); + + // this call is synchronous + status = omgt_query_sa(port, &query, &pQueryResultsVLArb); + if (! pQueryResultsVLArb) + { + fprintf( stderr, "%*sSA VLArb query Failed: %s\n", 0, "", + iba_fstatus_msg(status) ); + goto fail; + + } else if (pQueryResultsVLArb->Status != FSUCCESS) { + fprintf( stderr, + "%*sSA VLArb query Failed: %s MadStatus 0x%x: %s\n", 0, "", + iba_fstatus_msg(pQueryResultsVLArb->Status), + pQueryResultsVLArb->MadStatus, + iba_sd_mad_status_msg(pQueryResultsVLArb->MadStatus) ); + goto fail; + } + + pVLATRR = (STL_VLARBTABLE_RECORD_RESULTS*)pQueryResultsVLArb->QueryResult; + if (!pQueryResultsVLArb->ResultDataSize) { + pVLATR = NULL; + + } else { + pVLATR = pVLATRR->VLArbTableRecords; + } + + DBGPRINT("MadStatus 0x%x: %s\n", pQueryResultsVLArb->MadStatus, + iba_sd_mad_status_msg(pQueryResultsVLArb->MadStatus)); + DBGPRINT("%d Bytes Returned\n", pQueryResultsVLArb->ResultDataSize); + + + // Query all PKey Table records + memset(&query, 0, sizeof(query)); // initialize reserved fields + query.InputType = InputTypeNoInput; + query.OutputType = OutputTypeStlPKeyTableRecord; + pQueryResultsPKey = NULL; + pPKTRR = NULL; + + DBGPRINT("Query: Input=%s, Output=%s\n", + iba_sd_query_input_type_msg(query.InputType), + iba_sd_query_result_type_msg(query.OutputType)); + + // this call is synchronous + status = omgt_query_sa(port, &query, &pQueryResultsPKey); + if (! pQueryResultsPKey) + { + fprintf( stderr, "%*sSA P_Key query Failed: %s\n", 0, "", + iba_fstatus_msg(status) ); + goto fail; + + } else if (pQueryResultsPKey->Status != FSUCCESS) { + fprintf( stderr, + "%*sSA P_Key query Failed: %s MadStatus 0x%x: %s\n", 0, "", + iba_fstatus_msg(pQueryResultsPKey->Status), + pQueryResultsPKey->MadStatus, + iba_sd_mad_status_msg(pQueryResultsPKey->MadStatus) ); + goto fail; + } + + pPKTRR = (STL_PKEYTABLE_RECORD_RESULTS*)pQueryResultsPKey->QueryResult; + if (!pQueryResultsPKey->ResultDataSize) { + pPKTR = NULL; + + } else { + pPKTR = pPKTRR->PKeyTableRecords; + } + + DBGPRINT("MadStatus 0x%x: %s\n", pQueryResultsPKey->MadStatus, + iba_sd_mad_status_msg(pQueryResultsPKey->MadStatus)); + DBGPRINT("%d Bytes Returned\n", pQueryResultsPKey->ResultDataSize); + + STL_SCSCMAP basescsc; + uint8 i; + int found_scsc =0; + for (i = 0; i < STL_MAX_SCS; i++) { + basescsc.SCSCMap[i].SC = i; + basescsc.SCSCMap[i].Reserved = 0; + } + + for ( p = cl_qmap_head(&fabricp->AllNodes), ix_node = 0; p != cl_qmap_end(&fabricp->AllNodes); + p = cl_qmap_next(p), ix_node++ ) + { + nodep = PARENT_STRUCT(p, NodeData, AllNodesEntry); + PQUERY_RESULT_VALUES pQueryResultsSCSCMap = NULL; + + if (ix_node%PROGRESS_FREQ == 0) + if (! quiet) ProgressPrint(FALSE, "Processed %6d of %6d Nodes...", ix_node, num_nodes); + if (focus && ! CompareNodePoint(nodep, focus)) + continue; + + if (nodep->NodeInfo.NodeType == STL_NODE_SW) { + // Query all SCSC Map records + memset(&query, 0, sizeof(query)); + query.InputType = InputTypeLid; + query.OutputType = OutputTypeStlSCSCTableRecord; + query.InputValue.ScScTableRecord.Lid = nodep->pSwitchInfo->RID.LID; + pQueryResultsSCSCMap = NULL; + pSCSCRR = NULL; + + DBGPRINT("Query: Input=%s, Output=%s\n", + iba_sd_query_input_type_msg(query.InputType), + iba_sd_query_result_type_msg(query.OutputType)); + + // this call is synchronous + status = omgt_query_sa(port, &query, &pQueryResultsSCSCMap); + if (!pQueryResultsSCSCMap) + { + fprintf(stderr, "%*sSA SCSC Map query for LID 0x%X Failed: %s\n", 0, "", + query.InputValue.ScScTableRecord.Lid, iba_fstatus_msg(status)); + goto fail; + } else if (pQueryResultsSCSCMap->Status != FSUCCESS) { + fprintf(stderr, + "%*sSA SCSCMap query for LID 0x%X Failed: %s MadStatus 0x%x: %s\n", 0, "", + query.InputValue.ScScTableRecord.Lid, + iba_fstatus_msg(pQueryResultsSCSCMap->Status), + pQueryResultsSCSCMap->MadStatus, + iba_sd_mad_status_msg(pQueryResultsSCSCMap->MadStatus)); + goto fail; + } + pSCSCRR = (STL_SC_MAPPING_TABLE_RECORD_RESULTS*)pQueryResultsSCSCMap->QueryResult; + if (pQueryResultsSCSCMap->ResultDataSize == 0) { + fprintf(stderr, "%*sNo SCSC Records returned for LID 0x%X\n", 0, "", + query.InputValue.ScScTableRecord.Lid); + pSCSCR = NULL; + } else { + pSCSCR = pSCSCRR->SCSCRecords; + } + + } + + // Process all ports on node + for ( p2 = cl_qmap_head(&nodep->Ports), ix_port = 0; + p2 != cl_qmap_end(&nodep->Ports); + p2 = cl_qmap_next(p2), ix_port++ ) + { + uint16 pkey_cap; + portp = PARENT_STRUCT(p2, PortData, NodePortsEntry); + + // QOS and PKey data is undefined for down ports + if (portp->PortInfo.PortStates.s.PortState == IB_PORT_DOWN) + { + DBGPRINT("skip down port\n"); + continue; + } + + if ((status = PortDataAllocateQOSData(fabricp, portp)) != FSUCCESS) + break; + if (nodep->NodeInfo.NodeType == STL_NODE_SW && portp->PortNum) { + // switch external ports have SC2SC tables + if ( (pSCSCR_2) && (pSCSCR_2->RID.LID == portp->EndPortLID) && (pSCSCR_2->RID.InputPort == portp->PortNum) ) + { + copySCSCTable(&ix_rec_scsc, pSCSCRR, &pSCSCR_2, portp, 0); + } else { + for ( ix_rec_scsc = 0, pSCSCR_2 = pSCSCR; + (ix_rec_scsc < pSCSCRR->NumSCSCTableRecords) && pSCSCR_2; + ix_rec_scsc++, pSCSCR_2++ ) + { + if ( (pSCSCR_2->RID.LID == portp->EndPortLID) && + (pSCSCR_2->RID.InputPort == portp->PortNum) ) + { + // assume all the records for a given port are + // contiguous + // Add SCSC Table data to PortData + copySCSCTable(&ix_rec_scsc, pSCSCRR, &pSCSCR_2, portp, 0); + // check for SCSC transitions if needed + if ((*use_scsc) && (!found_scsc) && (memcmp(&(pSCSCR_2->Map), &(basescsc), sizeof(STL_SCSCMAP))!=0)) + found_scsc = 1; + break; + } + } + } // End of for ( ix_rec = 0, pQOSSCSC = portp->pQOS->SC2SCMap + } else { + // HFIs and switch port 0 have SL2SC and SC2SL tables + // Find first SLSC record + pQOSSLSC = portp->pQOS->SL2SCMap; + if ( pSLSCR_2 && pSLSCR_2->RID.LID == portp->EndPortLID) + { + memcpy(pQOSSLSC, &(pSLSCR_2->SLSCMap), sizeof(STL_SLSCMAP)); + pSLSCR_2++; + } else { + // HFIs and switch port 0 have SL2SC and SC2SL tables + // Find first SLSC record + for ( ix_rec_slsc = 0, pSLSCR_2 = pSLSCR; + (ix_rec_slsc < pSLSCRR->NumSLSCTableRecords) && pSLSCR_2; + ix_rec_slsc++, pSLSCR_2++ ) + { + if ( pSLSCR_2->RID.LID == portp->EndPortLID) + { + // Add SLSC Table data to PortData + memcpy(pQOSSLSC, &(pSLSCR_2->SLSCMap), sizeof(STL_SLSCMAP)); + pSLSCR_2++; + break; + } + } + } + // Find first SCSL record + pQOSSCSL = portp->pQOS->SC2SLMap; + if (pSCSLR_2 && pSCSLR_2->RID.LID == portp->EndPortLID) + { + memcpy(pQOSSCSL, &(pSCSLR_2->SCSLMap), sizeof(STL_SCSLMAP)); + pSCSLR_2++; + } else { + // Find first SCSL record + for ( ix_rec_scsl = 0, pSCSLR_2 = pSCSLR; + (ix_rec_scsl < pSCSLRR->NumSCSLTableRecords) && pSCSLR_2; + ix_rec_scsl++, pSCSLR_2++ ) + { + if ( pSCSLR_2->RID.LID == portp->EndPortLID) + { + // Add SCSL Table data to PortData + memcpy(pQOSSCSL, &(pSCSLR_2->SCSLMap), sizeof(STL_SCSLMAP)); + pSCSLR_2++; + break; + } + } + } + } + + // Process SCVL Table Data + if(getIsVLrSupported(nodep, portp)) + { + pQOSSCVLr = portp->pQOS->SC2VLMaps; + if ( pSCVLrR_2 && (pSCVLrR_2->RID.LID == portp->EndPortLID) && + (pSCVLrR_2->RID.Port == portp->PortNum) ) + { + memcpy(&(pQOSSCVLr[Enum_SCVLr].SCVLMap), &(pSCVLrR_2->SCVLMap), sizeof(STL_SCVLMAP)); + pSCVLrR_2++; + } else { + for ( ix_rec_scvlr = 0, pSCVLrR_2 = pSCVLrR; + (ix_rec_scvlr < pSCVLrRR->NumSCVLrTableRecords) && pSCVLrR_2; + ix_rec_scvlr++, pSCVLrR_2++ ) + { + if ( (pSCVLrR_2->RID.LID == portp->EndPortLID) && + (pSCVLrR_2->RID.Port == portp->PortNum) ) + { + // Add SCVLr Table data to PortData + memcpy(&(pQOSSCVLr[Enum_SCVLr].SCVLMap), &(pSCVLrR_2->SCVLMap), sizeof(STL_SCVLMAP)); + pSCVLrR_2++; + break; + } + } + } + } + pQOSSCVLt = portp->pQOS->SC2VLMaps; + if ( pSCVLtR_2 && (pSCVLtR_2->RID.LID == portp->EndPortLID) && + (pSCVLtR_2->RID.Port == portp->PortNum) ) + { + memcpy(&(pQOSSCVLt[Enum_SCVLt].SCVLMap), &(pSCVLtR_2->SCVLMap), sizeof(STL_SCVLMAP)); + pSCVLtR_2++; + } else { + // Find first SCVLt record + for ( ix_rec_scvlt = 0, pSCVLtR_2 = pSCVLtR; + (ix_rec_scvlt < pSCVLtRR->NumSCVLtTableRecords) && pSCVLtR_2; + ix_rec_scvlt++, pSCVLtR_2++ ) + { + if ( (pSCVLtR_2->RID.LID == portp->EndPortLID) && + (pSCVLtR_2->RID.Port == portp->PortNum) ) + { + // Add SCVLt Table data to PortData + memcpy(&(pQOSSCVLt[Enum_SCVLt].SCVLMap), &(pSCVLtR_2->SCVLMap), sizeof(STL_SCVLMAP)); + pSCVLtR_2++; + break; + } + } + } + if (nodep->NodeInfo.NodeType != STL_NODE_SW || portp->PortNum != 0) + { + pQOSSCVLnt = portp->pQOS->SC2VLMaps; + if ( pSCVLntR_2 && (pSCVLntR_2->RID.LID == portp->EndPortLID) && + (pSCVLntR_2->RID.Port == portp->PortNum)) { + memcpy(&(pQOSSCVLnt[Enum_SCVLnt].SCVLMap), &(pSCVLntR_2->SCVLMap), sizeof(STL_SCVLMAP)); + pSCVLntR_2++; + } else { + // SCVLnt + for ( ix_rec_scvlnt = 0, pSCVLntR_2 = pSCVLntR; + (ix_rec_scvlnt < pSCVLntRR->NumSCVLntTableRecords) && pSCVLntR_2; + ix_rec_scvlnt++, pSCVLntR_2++) { + if ( (pSCVLntR_2->RID.LID == portp->EndPortLID) && + (pSCVLntR_2->RID.Port == portp->PortNum)) { + // Add SCVLnt table data to PortData + memcpy(&(pQOSSCVLnt[Enum_SCVLnt].SCVLMap), &(pSCVLntR_2->SCVLMap), sizeof(STL_SCVLMAP)); + pSCVLntR_2++; + break; + } + } + } + + int vlArb; + if (getVLArb(portp, &vlArb)) + goto fail; + + if (vlArb) { + // Process VL Arb Table data + pQOSVLARB = portp->pQOS->u.VLArbTable; + if( pVLATR_2 && (pVLATR_2->RID.LID == portp->EndPortLID) && + (pVLATR_2->RID.OutputPortNum == portp->PortNum) ) + { + copyVLArbTable(&ix_rec_vla, pQOSVLARB, pVLATRR, &pVLATR_2, portp); + } else { + // Find first VL Arb record + for ( ix_rec_vla = 0, pVLATR_2 = pVLATR; + (ix_rec_vla < pVLATRR->NumVLArbTableRecords) && pVLATR_2; + ix_rec_vla++, pVLATR_2++ ) + { + if ( (pVLATR_2->RID.LID == portp->EndPortLID) && + (pVLATR_2->RID.OutputPortNum == portp->PortNum) ) + { + copyVLArbTable(&ix_rec_vla, pQOSVLARB, pVLATRR, &pVLATR_2, portp); + break; + } + } // End of for ( ix_rec = 0, pQOSVLARB = portp->pQOS->u.VLArbTable + } + } + } + // Process P_Key data + if ((status = PortDataAllocatePartitionTable(fabricp, portp)) != FSUCCESS) + break; + pkey_cap = PortPartitionTableSize(portp); + + pPKEY = portp->pPartitionTable; + if ( pPKTR_2 && (pPKTR_2->RID.LID == portp->EndPortLID) && + (pPKTR_2->RID.PortNum == portp->PortNum) ) + { + copyPKeyTable(&ix_rec_pk, &pPKEY, pPKTRR, &pPKTR_2, portp, pkey_cap); + } else { + // Find P_Key record + for ( ix_rec_pk = 0, pPKTR_2 = pPKTR; + (ix_rec_pk < pPKTRR->NumPKeyTableRecords) && pPKTR_2; + ix_rec_pk++, pPKTR_2++ ) + { + if ( (pPKTR_2->RID.LID == portp->EndPortLID) && + (pPKTR_2->RID.PortNum == portp->PortNum) ) + + { + copyPKeyTable(&ix_rec_pk, &pPKEY, pPKTRR, &pPKTR_2, portp, pkey_cap); + break; + } + + } // End of for ( ix_rec = 0, pPKEY = portp->pPartitionTable + } + } // End of for ( p2 = cl_qmap_head(&nodep->Ports) + if (pQueryResultsSCSCMap) + omgt_free_query_result_buffer(pQueryResultsSCSCMap); + + } // End of for ( p=cl_qmap_head(&fabricp->AllNodes) + + fabricp->flags |= FF_QOSDATA; + (*use_scsc) &= found_scsc; + +done: + // Free query results buffers + if (pQueryResultsSLSCMap) + omgt_free_query_result_buffer(pQueryResultsSLSCMap); + if (pQueryResultsSCSLMap) + omgt_free_query_result_buffer(pQueryResultsSCSLMap); + if (pQueryResultsSCVLtMap) + omgt_free_query_result_buffer(pQueryResultsSCVLtMap); + if (pQueryResultsSCVLntMap) + omgt_free_query_result_buffer(pQueryResultsSCVLntMap); + if (pQueryResultsVLArb) + omgt_free_query_result_buffer(pQueryResultsVLArb); + if (pQueryResultsPKey) + omgt_free_query_result_buffer(pQueryResultsPKey); + + if (! quiet) ProgressPrint(TRUE, "Done Getting All Port VL Tables"); + return (status); + +fail: + status = FERROR; + goto done; +} // End of GetAllPortVLInfoSA() + +/* query all Port VL info directly from SMA + */ +static FSTATUS GetAllPortVLInfoDirect(struct omgt_port *port, + FabricData_t *fabricp, + Point *focus, + int quiet, + int *use_scsc) +{ + FSTATUS status = FSUCCESS; + int ix_node, ix_port, block; + + cl_map_item_t *p, *p2; + NodeData *nodep; + PortData *portp; + STL_VLARB_TABLE *pQOSVLARB; + STL_PKEY_ELEMENT *pPKEY; + int num_nodes = cl_qmap_count(&fabricp->AllNodes); + uint8 in_port; + uint8 out_port; + + if (! quiet) ProgressPrint(TRUE, "Getting All Port VL Tables..."); + + STL_SCSCMAP basescsc; + int found_scsc = 0; + uint8 i; + for (i = 0; i < STL_MAX_SCS; i++) { + basescsc.SCSCMap[i].SC = i; + basescsc.SCSCMap[i].Reserved = 0; + } + + for ( p = cl_qmap_head(&fabricp->AllNodes), ix_node = 0; p != cl_qmap_end(&fabricp->AllNodes); + p = cl_qmap_next(p), ix_node++ ) + { + nodep = PARENT_STRUCT(p, NodeData, AllNodesEntry); + //boolean enhancedp0 = ( nodep->pSwitchInfo + // && nodep->pSwitchInfo->SwitchInfoData.u2.s.EnhancedPort0); + + if (ix_node%PROGRESS_FREQ == 0) + if (! quiet) ProgressPrint(FALSE, "Processed %6d of %6d Nodes...", ix_node, num_nodes); + if (focus && ! CompareNodePoint(nodep, focus)) + continue; + + // Process all ports on node + for ( p2 = cl_qmap_head(&nodep->Ports), ix_port = 0; + p2 != cl_qmap_end(&nodep->Ports); + p2 = cl_qmap_next(p2), ix_port++ ) + { + int pkey_cap; + portp = PARENT_STRUCT(p2, PortData, NodePortsEntry); + + if (portp->PortInfo.PortStates.s.PortState == IB_PORT_DOWN) + { + DBGPRINT("skip down port\n"); + continue; + } + if ((status = PortDataAllocateQOSData(fabricp, portp)) != FSUCCESS) + break; + + if (nodep->NodeInfo.NodeType == STL_NODE_SW && portp->PortNum) { + // switch external ports have SC2SC tables + cl_map_item_t *p3; + + in_port = portp->PortNum; + // just visit active ports + for ( p3 = cl_qmap_head(&nodep->Ports); + p3 != cl_qmap_end(&nodep->Ports); + p3 = cl_qmap_next(p3) ) + { + PortData *outportp = PARENT_STRUCT(p3, PortData, NodePortsEntry); + STL_SCSCMAP SCSCMap; + + out_port = outportp->PortNum; + if (out_port == 0) + continue; + status = SmaGetSCSCMappingTable(port, portp->EndPortLID, 0, NULL, in_port, out_port, &SCSCMap); + if (status != FSUCCESS) + { + fprintf(stderr, "%*sSMA Get(SCSCMap %u %u) Failed to LID 0x%x Node 0x%016"PRIx64" Name: %.*s: %s\n", 0, "", in_port, out_port, portp->EndPortLID, + nodep->NodeInfo.NodeGUID, + STL_NODE_DESCRIPTION_ARRAY_SIZE, + (char*)nodep->NodeDesc.NodeString, iba_fstatus_msg(status)); + } else { + // Copy the SCSC map to the QOS data + QOSDataAddSCSCMap(portp, out_port, 0, &SCSCMap); + // check for SCSC transitions if needed + if((*use_scsc) && (!found_scsc) && (memcmp(&SCSCMap, &(basescsc), sizeof(STL_SCSCMAP))!=0)) + found_scsc = 1; + } + } + } else { + // HFIs and switch port 0 have SC2SC and SC2SL tables + + STL_SLSCMAP SLSCMap; + STL_SCSLMAP SCSLMap; + + // Process SLSC Mapping Table data + status = SmaGetSLSCMappingTable(port, portp->EndPortLID, 0, NULL, &SLSCMap); + if (status != FSUCCESS) + { + fprintf(stderr, "%*sSMA Get(SLSCMap) Failed to LID 0x%x Node 0x%016"PRIx64" Name: %.*s: %s\n", 0, "", portp->EndPortLID, + nodep->NodeInfo.NodeGUID, + STL_NODE_DESCRIPTION_ARRAY_SIZE, + (char*)nodep->NodeDesc.NodeString, iba_fstatus_msg(status)); + } else { + // Copy the SLSCMap to the pQOS data + memcpy(portp->pQOS->SL2SCMap, &SLSCMap, sizeof(STL_SLSCMAP)); + } + // Process SCSL Mapping Table data + status = SmaGetSCSLMappingTable(port, portp->EndPortLID, 0, NULL, &SCSLMap); + if (status != FSUCCESS) + { + fprintf(stderr, "%*sSMA Get(SCSLMap) Failed to LID 0x%x Node 0x%016"PRIx64" Name: %.*s: %s\n", 0, "", portp->EndPortLID, + nodep->NodeInfo.NodeGUID, + STL_NODE_DESCRIPTION_ARRAY_SIZE, + (char*)nodep->NodeDesc.NodeString, iba_fstatus_msg(status)); + } else { + // Copy the SCSLMap to the pQOS data + memcpy(portp->pQOS->SC2SLMap, &SCSLMap, sizeof(STL_SCSLMAP)); + } + } + + // process scvl_r table data + if (getIsVLrSupported(nodep, portp)) + { + STL_SCVLMAP SCVLrMap; + + status = SmaGetSCVLMappingTable(port, portp->EndPortLID, 0, NULL, portp->PortNum, &SCVLrMap, STL_MCLASS_ATTRIB_ID_SC_VLR_MAPPING_TABLE); + if (status != FSUCCESS) + { + fprintf(stderr, "%*sSMA Get(SCVLrMap: %u) Failed to LID 0x%x Node 0x%016"PRIx64" Name: %.*s: %s\n", 0, "", portp->PortNum, portp->EndPortLID, + nodep->NodeInfo.NodeGUID, + STL_NODE_DESCRIPTION_ARRAY_SIZE, + (char *)nodep->NodeDesc.NodeString, iba_fstatus_msg(status)); + } else { + memcpy(&(portp->pQOS->SC2VLMaps[Enum_SCVLr]), &SCVLrMap, sizeof(STL_SCVLMAP)); + } + } + + // process scvl_t table data + { + STL_SCVLMAP SCVLtMap; + + status = SmaGetSCVLMappingTable(port, portp->EndPortLID, 0, NULL, portp->PortNum, &SCVLtMap, STL_MCLASS_ATTRIB_ID_SC_VLT_MAPPING_TABLE); + if (status != FSUCCESS) + { + fprintf(stderr, "%*sSMA Get(SCVLtMap: %u) Failed to LID 0x%x Node 0x%016"PRIx64" Name: %.*s: %s\n", 0, "", portp->PortNum, portp->EndPortLID, + nodep->NodeInfo.NodeGUID, + STL_NODE_DESCRIPTION_ARRAY_SIZE, + (char *)nodep->NodeDesc.NodeString, iba_fstatus_msg(status)); + } else { + memcpy(&(portp->pQOS->SC2VLMaps[Enum_SCVLt]), &SCVLtMap, sizeof(STL_SCVLMAP)); + } + } + + // process scvl_nt table data (not valid on switch port 0) + if (nodep->NodeInfo.NodeType != STL_NODE_SW || portp->PortNum) + { + STL_SCVLMAP SCVLntMap; + + status = SmaGetSCVLMappingTable(port, portp->EndPortLID, 0, NULL, portp->PortNum, &SCVLntMap, STL_MCLASS_ATTRIB_ID_SC_VLNT_MAPPING_TABLE); + if (status != FSUCCESS) + { + fprintf(stderr, "%*sSMA Get(SCVLntMap: %u) Failed to LID 0x%x Node 0x%016"PRIx64" Name: %.*s: %s\n", 0, "", portp->PortNum, portp->EndPortLID, + nodep->NodeInfo.NodeGUID, + STL_NODE_DESCRIPTION_ARRAY_SIZE, + (char *)nodep->NodeDesc.NodeString, iba_fstatus_msg(status)); + } else { + memcpy(&(portp->pQOS->SC2VLMaps[Enum_SCVLnt]), &SCVLntMap, sizeof(STL_SCVLMAP)); + } + } + + // Process VL Arb Table data, only valid on ports which + // support > 1 VL. Not valid on non-enhanced port 0 + // SA does not report this port any switch port 0, so skip + if (portp->PortInfo.VL.s2.Cap != 1 + && (nodep->NodeInfo.NodeType != STL_NODE_SW + || portp->PortNum != 0 /*|| enhancedp0*/)) { + out_port = portp->PortNum; + + int vlArb; + if (getVLArb(portp, &vlArb)) + return FERROR; + + if (vlArb) { + for ( block = 0, pQOSVLARB = portp->pQOS->u.VLArbTable; + block < STL_VLARB_NUM_SECTIONS; + block++ ) + { + STL_VLARB_TABLE VLArbTable; + status = SmaGetVLArbTable(port, portp->EndPortLID, 0, NULL, out_port, block, &VLArbTable); + if (status != FSUCCESS) { + fprintf(stderr, "%*sSMA Get(VLArbTable %u %u) Failed to LID 0x%x Node 0x%016"PRIx64" Name: %.*s: %s\n", 0, "", block, out_port, portp->EndPortLID, + nodep->NodeInfo.NodeGUID, + STL_NODE_DESCRIPTION_ARRAY_SIZE, + (char*)nodep->NodeDesc.NodeString, iba_fstatus_msg(status)); + } else { + // Add VLArb data to PortData + pQOSVLARB[block] = VLArbTable; + } + } + } + } + + // Get P_Key data + if ((status = PortDataAllocatePartitionTable(fabricp, portp)) != FSUCCESS) + break; + pkey_cap = (int)(unsigned)PortPartitionTableSize(portp); + if (nodep->NodeInfo.NodeType == STL_NODE_SW) + out_port = portp->PortNum; + else + out_port = 0; + + for ( block = 0, pPKEY = portp->pPartitionTable; + pkey_cap > 0; + block++, pPKEY += NUM_PKEY_ELEMENTS_BLOCK, pkey_cap -= NUM_PKEY_ELEMENTS_BLOCK) + { + STL_PARTITION_TABLE PartTable; + status = SmaGetPartTable(port, portp->EndPortLID, 0, NULL, out_port, block, &PartTable); + if (status != FSUCCESS) + { + fprintf(stderr, "%*sSMA Get(P_KeyTable %u %u) Failed to LID 0x%x Node 0x%016"PRIx64" Name: %.*s: %s\n", 0, "", out_port, block, portp->EndPortLID, + nodep->NodeInfo.NodeGUID, + STL_NODE_DESCRIPTION_ARRAY_SIZE, + (char*)nodep->NodeDesc.NodeString, iba_fstatus_msg(status)); + } else { + // Add P_Key data to PortData + memcpy(pPKEY, &PartTable.PartitionTableBlock[0], sizeof(STL_PKEY_ELEMENT)*MIN(pkey_cap, NUM_PKEY_ELEMENTS_BLOCK)); + } + + } // End of for ( block = 0, pPKEY = portp->pPartitionTable + + } // End of for ( p2 = cl_qmap_head(&nodep->Ports) + + } // End of for ( p=cl_qmap_head(&fabricp->AllNodes) + + fabricp->flags |= FF_QOSDATA; + (*use_scsc) &= found_scsc; + + if (! quiet) ProgressPrint(TRUE, "Done Getting All Port VL Tables"); + return (status); + +} // End of GetAllPortVLInfoDirect() + +/* query all Port VL info + */ +FSTATUS GetAllPortVLInfo(EUI64 portGuid, FabricData_t *fabricp, Point *focus, int quiet, int *use_scsc) +{ + struct omgt_port *omgt_port_session = NULL; + FSTATUS fstatus = FSUCCESS; + + fstatus = omgt_open_port_by_guid(&omgt_port_session, portGuid, NULL); + if (fstatus != FSUCCESS) { + fprintf(stderr, "%s: Unable to open fabric interface.\n", + g_Top_cmdname); + } else { + omgt_set_timeout(omgt_port_session, fabricp->ms_timeout); + if (fabricp->flags & FF_SMADIRECT) { + fstatus = GetAllPortVLInfoDirect(omgt_port_session, fabricp, focus, quiet, use_scsc); + } else { + fstatus = GetAllPortVLInfoSA(omgt_port_session, fabricp, focus, quiet, use_scsc); + } + omgt_close_port(omgt_port_session); + } + + return fstatus; +} + +/* copy linear FDB block + */ +static FSTATUS CopyLinearFDBBlock(STL_LINEAR_FORWARDING_TABLE *pDestFwdTbl, PORT *pSrcFDBData, uint16 blockSize) +{ + if (!pDestFwdTbl || !pSrcFDBData || !blockSize) + return (FINVALID_PARAMETER); + + memcpy(pDestFwdTbl, pSrcFDBData, blockSize); + return (FSUCCESS); +} + +/* copy port group FDB block + */ +static FSTATUS CopyPortGroupFDBBlock(STL_PORT_GROUP_FORWARDING_TABLE *pDestFwdTbl, PORT *pSrcFDBData, uint16 blockSize) +{ + if (!pDestFwdTbl || !pSrcFDBData || !blockSize) + return (FINVALID_PARAMETER); + + memcpy(pDestFwdTbl, pSrcFDBData, blockSize); + return (FSUCCESS); +} + +/* copy port group block + */ +static FSTATUS CopyPortGroupBlock(STL_PORTMASK *pDestTbl, STL_PORTMASK *pSrcData, uint16 blockSize) +{ + if (!pDestTbl || !pSrcData || !blockSize) + return (FINVALID_PARAMETER); + + memcpy(pDestTbl, pSrcData, blockSize); + return (FSUCCESS); +} + +/* copy multicast FDB block + */ +static FSTATUS CopyMulticastFDBBlock( NodeData *pNode, STL_PORTMASK *pDestFwdTbl, + STL_PORTMASK *pSrcFDBData, uint16 blockSize) +{ + if ( !pNode || !pNode->switchp || !pDestFwdTbl || !pSrcFDBData || + !blockSize) + return (FINVALID_PARAMETER); + + memcpy(pDestFwdTbl, pSrcFDBData, blockSize * sizeof(STL_PORTMASK)); + return (FSUCCESS); +} + +/* query all forwarding DBs on switch nodes in fabric from SA + */ +static FSTATUS GetAllFDBsSA(struct omgt_port *port, FabricData_t *fabricp, Point *focus, int quiet) +{ + FSTATUS status = FSUCCESS; + int ix, ix_node; + + cl_map_item_t *p; + + OMGT_QUERY query; + PQUERY_RESULT_VALUES pQueryResultsLinearFDB = NULL; + PQUERY_RESULT_VALUES pQueryResultsMulticastFDB = NULL; + PQUERY_RESULT_VALUES pQueryResultsPGT = NULL; + PQUERY_RESULT_VALUES pQueryResultsPGFT = NULL; + + STL_MULTICAST_FORWARDING_TABLE_RECORD *pMFR; + STL_LINEAR_FDB_RECORD_RESULTS *pLFRR=NULL; + STL_MCAST_FDB_RECORD_RESULTS *pMFRR; + STL_PORT_GROUP_TABLE_RECORD_RESULTS *pPGTRR = NULL; + STL_PORT_GROUP_FORWARDING_TABLE_RECORD_RESULTS *pPGFTRR = NULL; + uint32 linearFDBSize = 0; + uint32 multicastFDBSize = 0; + uint16 portGroupSize = 0; + uint32 pgftSize = 0; + + int num_nodes = cl_qmap_count(&fabricp->AllNodes); + + if (! quiet) ProgressPrint(TRUE, "Getting All FDB Tables..."); + for ( p=cl_qmap_head(&fabricp->AllNodes), ix_node = 0; p != cl_qmap_end(&fabricp->AllNodes); + p = cl_qmap_next(p), ix_node++ ) + { + NodeData *nodep = PARENT_STRUCT(p, NodeData, AllNodesEntry); + + if (ix_node%PROGRESS_FREQ == 0) + if (! quiet) ProgressPrint(FALSE, "Processed %6d of %6d Nodes...", ix_node, num_nodes); + if(focus && ! CompareNodePoint(nodep, focus)) + continue; + + // Process switch nodes + if (nodep->NodeInfo.NodeType == STL_NODE_SW) { + + if (nodep->pSwitchInfo->SwitchInfoData.RoutingMode.Enabled == STL_ROUTE_LINEAR) + { + // Query LinearFDB records + memset(&query, 0, sizeof(query)); // initialize reserved fields + query.InputType = InputTypeLid; + query.InputValue.LinFdbTableRecord.Lid = nodep->pSwitchInfo->RID.LID; + query.OutputType = OutputTypeStlLinearFDBRecord; + pQueryResultsLinearFDB = NULL; + pLFRR = NULL; + linearFDBSize = 0; + + DBGPRINT("Query: Input=%s, Output=%s\n", + iba_sd_query_input_type_msg(query.InputType), + iba_sd_query_result_type_msg(query.OutputType)); + + // this call is synchronous + status = omgt_query_sa(port, &query, &pQueryResultsLinearFDB); + if (! pQueryResultsLinearFDB) + { + fprintf( stderr, "%*sSA LinearFDB query for LID 0x%X Failed: %s\n", 0, "", + query.InputValue.LinFdbTableRecord.Lid, iba_fstatus_msg(status) ); + } else if (pQueryResultsLinearFDB->Status != FSUCCESS) { + fprintf( stderr, + "%*sSA LinearFDB query for LID 0x%X Failed: %s MadStatus 0x%x: %s\n", + 0, "", query.InputValue.LinFdbTableRecord.Lid, + iba_fstatus_msg(pQueryResultsLinearFDB->Status), + pQueryResultsLinearFDB->MadStatus, + iba_sd_mad_status_msg(pQueryResultsLinearFDB->MadStatus) ); + } else if (pQueryResultsLinearFDB->ResultDataSize == 0) { + fprintf(stderr, "%*sNo LinearFDB Records Returned\n", 0, ""); + } else { + pLFRR = (STL_LINEAR_FDB_RECORD_RESULTS*)pQueryResultsLinearFDB->QueryResult; + linearFDBSize = pLFRR->NumLinearFDBRecords * MAX_LFT_ELEMENTS_BLOCK; + + if ( linearFDBSize > + nodep->pSwitchInfo->SwitchInfoData.LinearFDBTop + 1 ) + linearFDBSize = + nodep->pSwitchInfo->SwitchInfoData.LinearFDBTop + 1; + + DBGPRINT("MadStatus 0x%x: %s\n", pQueryResultsLinearFDB->MadStatus, + iba_sd_mad_status_msg(pQueryResultsLinearFDB->MadStatus)); + DBGPRINT("%d Bytes Returned\n", pQueryResultsLinearFDB->ResultDataSize); + + } // End of else + } + + if(nodep->pSwitchInfo->SwitchInfoData.AdaptiveRouting.s.Enable) { + // Query Port Group records + memset(&query, 0, sizeof(query)); // initialize reserved fields + query.InputType = InputTypeLid; + query.InputValue.PortGroupRecord.Lid = nodep->pSwitchInfo->RID.LID; + query.OutputType = OutputTypeStlPortGroupRecord; + pQueryResultsPGT = NULL; + pPGTRR = NULL; + portGroupSize = 0; + + DBGPRINT("Query: Input=%s, Output=%s\n", + iba_sd_query_input_type_msg(query.InputType), + iba_sd_query_result_type_msg(query.OutputType)); + + // this call is synchronous + status = omgt_query_sa(port, &query, &pQueryResultsPGT); + if (! pQueryResultsPGT) + { + fprintf( stderr, "%*sSA PortGroup query for LID 0x%X Failed: %s\n", 0, "", + query.InputValue.PortGroupRecord.Lid, iba_fstatus_msg(status) ); + } else if (pQueryResultsPGT->Status != FSUCCESS) { + fprintf( stderr, + "%*sSA PortGroup query for LID 0x%X Failed: %s MadStatus 0x%x: %s\n", + 0, "", query.InputValue.PortGroupRecord.Lid, + iba_fstatus_msg(pQueryResultsPGT->Status), + pQueryResultsPGT->MadStatus, + iba_sd_mad_status_msg(pQueryResultsPGT->MadStatus) ); + } else if (pQueryResultsPGT->ResultDataSize == 0) { + fprintf(stderr, "%*sNo Port Group Records Returned\n", 0, ""); + } else { + pPGTRR = (STL_PORT_GROUP_TABLE_RECORD_RESULTS*)pQueryResultsPGT->QueryResult; + portGroupSize = pPGTRR->NumRecords * NUM_PGT_ELEMENTS_BLOCK; + + DBGPRINT("MadStatus 0x%x: %s\n", pQueryResultsPGT->MadStatus, + iba_sd_mad_status_msg(pQueryResultsPGT->MadStatus)); + DBGPRINT("%d Bytes Returned\n", pQueryResultsPGT->ResultDataSize); + } + + // Query Port Group FDB records + memset(&query, 0, sizeof(query)); // initialize reserved fields + query.InputType = InputTypeLid; + query.InputValue.PortGroupFwdRecord.Lid = nodep->pSwitchInfo->RID.LID; + query.OutputType = OutputTypeStlPortGroupFwdRecord; + pQueryResultsPGFT = NULL; + pPGFTRR = NULL; + pgftSize = 0; + + DBGPRINT("Query: Input=%s, Output=%s\n", + iba_sd_query_input_type_msg(query.InputType), + iba_sd_query_result_type_msg(query.OutputType)); + + // this call is synchronous + status = omgt_query_sa(port, &query, &pQueryResultsPGFT); + if (! pQueryResultsPGFT) + { + fprintf( stderr, "%*sSA PGFT query for LID 0x%X Failed: %s\n", 0, "", + query.InputValue.PortGroupFwdRecord.Lid, iba_fstatus_msg(status) ); + } else if (pQueryResultsPGFT->Status != FSUCCESS) { + fprintf( stderr, + "%*sSA PGFT query for LID 0x%X Failed: %s MadStatus 0x%x: %s\n", + 0, "", query.InputValue.PortGroupFwdRecord.Lid, + iba_fstatus_msg(pQueryResultsPGFT->Status), + pQueryResultsPGFT->MadStatus, + iba_sd_mad_status_msg(pQueryResultsPGFT->MadStatus) ); + } else if (pQueryResultsPGFT->ResultDataSize == 0) { + fprintf(stderr, "%*sNo PGFT Records Returned\n", 0, ""); + } else { + pPGFTRR = (STL_PORT_GROUP_FORWARDING_TABLE_RECORD_RESULTS*)pQueryResultsPGFT->QueryResult; + DBGPRINT("MadStatus 0x%x: %s\n", pQueryResultsPGFT->MadStatus, + iba_sd_mad_status_msg(pQueryResultsPGFT->MadStatus)); + DBGPRINT("%d Bytes Returned\n", pQueryResultsPGFT->ResultDataSize); + pgftSize = pPGFTRR->NumRecords * MAX_LFT_ELEMENTS_BLOCK; + uint32 pgftCap = nodep->pSwitchInfo->SwitchInfoData.PortGroupFDBCap ? + nodep->pSwitchInfo->SwitchInfoData.PortGroupFDBCap : + DEFAULT_MAX_PGFT_LID + 1; + if (pgftSize < MIN(linearFDBSize, pgftCap) && pgftSize != 0) { + fprintf(stderr, "%*sIncorrect # of PGFT Records Returned " + "(LFT(%d) versus PGFT(%d)\n", + 0, "", linearFDBSize, pgftSize); + } + } + } + + + // Query MulticastFDB records + memset(&query, 0, sizeof(query)); // initialize reserved fields + query.InputType = InputTypeLid; + query.InputValue.McFdbTableRecord.Lid = nodep->pSwitchInfo->RID.LID; + query.OutputType = OutputTypeStlMCastFDBRecord; + pQueryResultsMulticastFDB = NULL; + pMFRR = NULL; + multicastFDBSize = 0; + + DBGPRINT("Query: Input=%s, Output=%s\n", + iba_sd_query_input_type_msg(query.InputType), + iba_sd_query_result_type_msg(query.OutputType)); + + // this call is synchronous + status = omgt_query_sa(port, &query, &pQueryResultsMulticastFDB); + if (! pQueryResultsMulticastFDB) + { + fprintf( stderr, "%*sSA MulticastFDB query for LID 0x%X Failed: %s\n", 0, "", + query.InputValue.McFdbTableRecord.Lid, iba_fstatus_msg(status) ); + } else if (pQueryResultsMulticastFDB->Status != FSUCCESS) { + fprintf( stderr, + "%*sSA MulticastFDB query for LID 0x%X Failed: %s MadStatus 0x%x: %s\n", + 0, "", query.InputValue.McFdbTableRecord.Lid, + iba_fstatus_msg(pQueryResultsMulticastFDB->Status), + pQueryResultsMulticastFDB->MadStatus, + iba_sd_mad_status_msg(pQueryResultsMulticastFDB->MadStatus) ); + } else if (pQueryResultsMulticastFDB->ResultDataSize == 0) { + fprintf(stderr, "%*sNo MulticastFDB Records Returned\n", 0, ""); + } else { + + pMFRR = + (STL_MCAST_FDB_RECORD_RESULTS*)pQueryResultsMulticastFDB->QueryResult; + multicastFDBSize = (pMFRR->NumMCastFDBRecords * STL_NUM_MFT_ELEMENTS_BLOCK); + + DBGPRINT("MadStatus 0x%x: %s\n", pQueryResultsMulticastFDB->MadStatus, + iba_sd_mad_status_msg(pQueryResultsMulticastFDB->MadStatus)); + DBGPRINT("%d Bytes Returned\n", pQueryResultsMulticastFDB->ResultDataSize); + + } // End of else + + + + // + // Add forwarding tables to SwitchData + // + status = NodeDataAllocateSwitchData( fabricp, nodep, linearFDBSize, + multicastFDBSize); + + if ((status == FSUCCESS) && linearFDBSize) { + uint32_t limit = ROUNDUP(linearFDBSize,MAX_LFT_ELEMENTS_BLOCK)/MAX_LFT_ELEMENTS_BLOCK; + STL_LINEAR_FORWARDING_TABLE_RECORD *pLFR; + + for ( ix = 0, pLFR = pLFRR->LinearFDBRecords; + ix < limit; ix++, pLFR++ ) { + CopyLinearFDBBlock( &nodep->switchp->LinearFDB[ix], + pLFR->LinearFdbData, + MIN(linearFDBSize - ix, MAX_LFT_ELEMENTS_BLOCK)); + } // End of for ( ix = 0, pLFR = pLFRR->LinearFDBRecords + } + + if ((status == FSUCCESS) && portGroupSize) { + STL_PORT_GROUP_TABLE_RECORD *pPGT = pPGTRR->Records; + for ( ix = 0; ix < pPGTRR->NumRecords; ix++) { + memcpy(&nodep->switchp->PortGroupElements[ix*NUM_PGT_ELEMENTS_BLOCK], + pPGT[ix].GroupBlock, + NUM_PGT_ELEMENTS_BLOCK*sizeof(STL_PORTMASK)); + } + } + + if ((status == FSUCCESS) && pgftSize) { + STL_PORT_GROUP_FORWARDING_TABLE_RECORD *pPGFTR; + unsigned int pgfdbcap = nodep->pSwitchInfo->SwitchInfoData.PortGroupFDBCap ? + nodep->pSwitchInfo->SwitchInfoData.PortGroupFDBCap : + DEFAULT_MAX_PGFT_LID+1; + unsigned int pgfdbsize = ROUNDUP(MIN(nodep->switchp->LinearFDBSize, pgfdbcap), + NUM_PGFT_ELEMENTS_BLOCK)/NUM_PGFT_ELEMENTS_BLOCK; + + // Don't core dump if you received more data than you expected. + pgfdbsize=MIN(pgfdbsize, pPGFTRR->NumRecords); + memset(nodep->switchp->PortGroupFDB,0xff,pgfdbsize); + + for ( ix = 0, + pPGFTR = &pPGFTRR->Records[ix]; + ix < pgfdbsize; ix++, pPGFTR++) { + memcpy(&nodep->switchp->PortGroupFDB[ix], + pPGFTR->PGFdbData, + NUM_PGFT_ELEMENTS_BLOCK*sizeof(PORT)); + } + } + + + if ((status == FSUCCESS) && multicastFDBSize) { + uint32 blockNum; + uint8 position; + + // multicastFDBSize is always a multiple of MFT_BLOCK_SIZE + for ( ix = 0, pMFR = pMFRR->MCastFDBRecords; + ix < pMFRR->NumMCastFDBRecords; ix ++, pMFR++ ) { + + blockNum = pMFR->RID.u1.s.BlockNum; + position = pMFR->RID.u1.s.Position; + + CopyMulticastFDBBlock( nodep, + GetMulticastFDBEntry(nodep, blockNum * STL_NUM_MFT_ELEMENTS_BLOCK, position), + pMFR->MftTable.MftBlock, STL_NUM_MFT_ELEMENTS_BLOCK); + + } // End of for ( ix = 0, pMFR = pMFRR->MCastFDBRecords + } + + + + // Free query results buffers + if (pQueryResultsMulticastFDB) { + omgt_free_query_result_buffer(pQueryResultsMulticastFDB); + pQueryResultsMulticastFDB = NULL; + } + + + if (pQueryResultsLinearFDB) { + omgt_free_query_result_buffer(pQueryResultsLinearFDB); + pQueryResultsLinearFDB = NULL; + } + + if (pQueryResultsPGT) { + omgt_free_query_result_buffer(pQueryResultsPGT); + pQueryResultsPGT = NULL; + } + + if (pQueryResultsPGFT) { + omgt_free_query_result_buffer(pQueryResultsPGFT); + pQueryResultsPGFT = NULL; + } + + + + } // End of if (nodep->NodeInfo.NodeType == STL_NODE_SW + + } // End of for ( p=cl_qmap_head(&fabricp->AllNodes) + + fabricp->flags |= FF_ROUTES; + + if (! quiet) ProgressPrint(TRUE, "Done Getting All FDB Tables"); + + return (status); + +} // End of GetAllFDBsSA() + +/* query all forwarding DBs on switch nodes in fabric directly from SMA + */ +static FSTATUS GetAllFDBsDirect(struct omgt_port *port, FabricData_t *fabricp, Point *focus, int quiet) +{ + FSTATUS status = FSUCCESS; + int ix, ix_node; + unsigned block, position; + + cl_map_item_t *p; + + STL_LINEAR_FORWARDING_TABLE linearFDB; + STL_MULTICAST_FORWARDING_TABLE multicastFDB; + STL_PORT_GROUP_TABLE pgt; + STL_PORT_GROUP_FORWARDING_TABLE pgFDB; + + uint32 linearFDBSize; // Size increased in STL + uint32 multicastFDBSize; + uint32 pgSize; + uint32 pgFDBSize; + + int num_nodes = cl_qmap_count(&fabricp->AllNodes); + + if (! quiet) ProgressPrint(TRUE, "Getting All FDB Tables..."); + for ( p=cl_qmap_head(&fabricp->AllNodes), ix_node = 0; p != cl_qmap_end(&fabricp->AllNodes); + p = cl_qmap_next(p), ix_node++ ) + { + NodeData *nodep = PARENT_STRUCT(p, NodeData, AllNodesEntry); + + if (ix_node%PROGRESS_FREQ == 0) + if (! quiet) ProgressPrint(FALSE, "Processed %6d of %6d Nodes...", ix_node, num_nodes); + if(focus && ! CompareNodePoint(nodep, focus)) + continue; + + // Process switch nodes + if (nodep->NodeInfo.NodeType == STL_NODE_SW) { + STL_LID lid = nodep->pSwitchInfo->RID.LID; + uint32_t limit; + + linearFDBSize = nodep->pSwitchInfo->SwitchInfoData.LinearFDBTop+1; + multicastFDBSize = ComputeMulticastFDBSize(&nodep->pSwitchInfo->SwitchInfoData); + limit = ROUNDUP(linearFDBSize,MAX_LFT_ELEMENTS_BLOCK)/MAX_LFT_ELEMENTS_BLOCK; + + // Add LinearFDB and MulticastFDB data to SwitchData + status = NodeDataAllocateSwitchData( fabricp, nodep, linearFDBSize, + multicastFDBSize); + if (status != FSUCCESS) + break; + + if (nodep->pSwitchInfo->SwitchInfoData.RoutingMode.Enabled == STL_ROUTE_LINEAR) { + for (ix = 0; ix < limit; ix++) { + status = SmaGetLinearFDBTable(port, lid, 0, NULL, ix, &linearFDB); + if (status != FSUCCESS) + { + fprintf(stderr, "%*sSMA Get(LFT %u) Failed to LID 0x%x Node 0x%016"PRIx64" Name: %.*s: %s\n", 0, "", ix, lid, + nodep->NodeInfo.NodeGUID, + STL_NODE_DESCRIPTION_ARRAY_SIZE, + (char*)nodep->NodeDesc.NodeString, iba_fstatus_msg(status)); + } else { + CopyLinearFDBBlock( &nodep->switchp->LinearFDB[ix], + linearFDB.LftBlock, + MIN(linearFDBSize - ix, (int)MAX_LFT_ELEMENTS_BLOCK)); + } + } + } + + int maxPosition = (nodep->NodeInfo.NumPorts) / STL_PORT_MASK_WIDTH; + for (ix = 0, block=0; ix < multicastFDBSize; ix += STL_NUM_MFT_ELEMENTS_BLOCK, block++) { + for (position=0; position <= maxPosition; position++) { + status = SmaGetMulticastFDBTable(port, lid, 0, NULL, block, position, &multicastFDB); + if (status != FSUCCESS) + { + fprintf(stderr, "%*sSMA Get(MFT %u %u) Failed to LID 0x%08x Node 0x%016"PRIx64" Name: %.*s: %s\n", 0, "", block, position, lid, + nodep->NodeInfo.NodeGUID, + STL_NODE_DESCRIPTION_ARRAY_SIZE, + (char*)nodep->NodeDesc.NodeString, iba_fstatus_msg(status)); + } else { + CopyMulticastFDBBlock( nodep, + GetMulticastFDBEntry(nodep, block * STL_NUM_MFT_ELEMENTS_BLOCK, position), + multicastFDB.MftBlock, MIN(multicastFDBSize-ix,STL_NUM_MFT_ELEMENTS_BLOCK)); + } + } + } + + if (nodep->pSwitchInfo->SwitchInfoData.AdaptiveRouting.s.Enable) { + // Query Port Group FDB records + pgFDBSize = MIN(nodep->pSwitchInfo->SwitchInfoData.LinearFDBTop+1, + nodep->pSwitchInfo->SwitchInfoData.PortGroupFDBCap ? + nodep->pSwitchInfo->SwitchInfoData.PortGroupFDBCap : + DEFAULT_MAX_PGFT_LID+1); + + limit = ROUNDUP(pgFDBSize, NUM_PGFT_ELEMENTS_BLOCK)/NUM_PGFT_ELEMENTS_BLOCK; + for (ix = 0; ix < limit; ix++) { + status = SmaGetPortGroupFDBTable(port, lid, 0, NULL, ix, &pgFDB); + if (status != FSUCCESS) + { + fprintf(stderr, "%*sSMA Get(PortGroupFDB %u) Failed to LID 0x%x Node 0x%016"PRIx64" Name: %.*s: %s\n", 0, "", ix, lid, + nodep->NodeInfo.NodeGUID, + STL_NODE_DESCRIPTION_ARRAY_SIZE, + (char*)nodep->NodeDesc.NodeString, iba_fstatus_msg(status)); + } else { + CopyPortGroupFDBBlock(&nodep->switchp->PortGroupFDB[ix], + pgFDB.PgftBlock, + MIN(pgFDBSize - ix, (int)NUM_PGFT_ELEMENTS_BLOCK)); + } + } + + pgSize = nodep->pSwitchInfo->SwitchInfoData.PortGroupTop; + limit = ROUNDUP(pgSize, NUM_PGT_ELEMENTS_BLOCK)/NUM_PGT_ELEMENTS_BLOCK; + for (ix = 0; ix < limit; ix++) { + status = SmaGetPortGroupTable(port, lid, 0, NULL, ix, &pgt); + if (status != FSUCCESS) + { + fprintf(stderr, "%*sSMA Get(PortGroupTable %u) Failed to LID 0x%x Node 0x%016"PRIx64" Name: %.*s: %s\n", 0, "", ix, lid, + nodep->NodeInfo.NodeGUID, + STL_NODE_DESCRIPTION_ARRAY_SIZE, + (char*)nodep->NodeDesc.NodeString, iba_fstatus_msg(status)); + } else { + CopyPortGroupBlock(&nodep->switchp->PortGroupElements[ix*NUM_PGT_ELEMENTS_BLOCK], + pgt.PgtBlock, + (MIN(pgSize - (ix*NUM_PGT_ELEMENTS_BLOCK), (int)NUM_PGT_ELEMENTS_BLOCK)) * sizeof(STL_PORTMASK)); + } + } + } + + + + + } // End of if (nodep->NodeInfo.NodeType == STL_NODE_SW + + } // End of for ( p=cl_qmap_head(&fabricp->AllNodes) + + fabricp->flags |= FF_ROUTES; + + if (! quiet) ProgressPrint(TRUE, "Done Getting All FDB Tables"); + + return (status); + +} // End of GetAllFDBsDirect() + +/* query all forwarding DBs on switch nodes in fabric + */ +FSTATUS GetAllFDBs(EUI64 portGuid, FabricData_t *fabricp, Point *focus, int quiet) +{ + struct omgt_port *omgt_port_session = NULL; + FSTATUS fstatus = FSUCCESS; + + fstatus = omgt_open_port_by_guid(&omgt_port_session, portGuid, NULL); + if (fstatus != FSUCCESS) { + fprintf(stderr, "%s: Unable to open fabric interface.\n", + g_Top_cmdname); + } else { + omgt_set_timeout(omgt_port_session, fabricp->ms_timeout); + if (fabricp->flags & FF_SMADIRECT) { + fstatus = GetAllFDBsDirect(omgt_port_session, fabricp, focus, quiet); + } else { + fstatus = GetAllFDBsSA(omgt_port_session, fabricp, focus, quiet); + } + omgt_close_port(omgt_port_session); + } + return fstatus; +} // End of GetAllFDBs + +/* clear all PortCounters on all ports in fabric + */ +FSTATUS ClearAllPortCounters(EUI64 portGuid, IB_GID localGid, FabricData_t *fabricp, + Point *focus, uint32 counterselect, + boolean limitstats, boolean quiet, + uint32 *node_countp, uint32 *port_countp, + uint32 *fail_node_countp, uint32 *fail_port_countp) +{ + FSTATUS status; + cl_map_item_t *p; + int i; + int num_nodes = cl_qmap_count(&fabricp->AllNodes); + + *node_countp=0; + *port_countp=0; + *fail_node_countp=0; + *fail_port_countp=0; + if (! quiet) ProgressPrint(TRUE, "Clearing Port Counters..."); + + struct omgt_params params = {.debug_file = g_verbose_file}; + status = omgt_open_port_by_guid(&g_portHandle, portGuid, ¶ms); + if (status != FSUCCESS) { + return status; + } + omgt_set_timeout(g_portHandle, fabricp->ms_timeout); +#ifdef PRODUCT_OPENIB_FF + if ((g_paclient_state == OMGT_SERVICE_STATE_UNKNOWN) && !(fabricp->flags & FF_PMADIRECT)) { + g_paclient_state = omgt_pa_service_connect(g_portHandle); + if (g_paclient_state < 0) { + return FERROR; + } + } +#endif + for (i=0, p=cl_qmap_head(&fabricp->AllNodes); p != cl_qmap_end(&fabricp->AllNodes); + p = cl_qmap_next(p),i++) + { + NodeData *nodep = PARENT_STRUCT(p, NodeData, AllNodesEntry); + PortData *first_portp; + cl_map_item_t *q; +#ifdef PRODUCT_OPENIB_FF + STL_LID lid = 0; +#endif + boolean cleared = FALSE; + boolean fail = FALSE; + + if (i%PROGRESS_FREQ == 0 || *node_countp == 1) + if (! quiet) ProgressPrint(FALSE, "Processed %6d of %6d Nodes...", *node_countp, num_nodes); + if (limitstats && focus && ! CompareNodePoint(nodep, focus)) + continue; + if (cl_qmap_head(&nodep->Ports) == cl_qmap_end(&nodep->Ports)) + continue; /* no ports */ + /* issue all switch PMA requests to port 0, its only one with a LID */ + if (nodep->NodeInfo.NodeType == STL_NODE_SW) { + first_portp = PARENT_STRUCT(cl_qmap_head(&nodep->Ports), PortData, NodePortsEntry); +#ifdef PRODUCT_OPENIB_FF + lid = first_portp->PortInfo.LID; +#endif + if (g_paclient_state != OMGT_SERVICE_STATE_OPERATIONAL) { + status = GetPathToPort(g_portHandle, portGuid, first_portp); + if (FSUCCESS != status) { + DBGPRINT("Unable to get Path to Port %d LID 0x%08x Node 0x%016"PRIx64"\n", + first_portp->PortNum, + first_portp->EndPortLID, + first_portp->nodep->NodeInfo.NodeGUID); + DBGPRINT(" Name: %.*s\n", + STL_NODE_DESCRIPTION_ARRAY_SIZE, + (char*)nodep->NodeDesc.NodeString); + //(*fail_port_countp)+= nodep->NodeInfo.NumPorts; // wrong + (*fail_port_countp)+= cl_qmap_count(&nodep->Ports); // better + (*fail_node_countp)++; + continue; + } + } + } else { + first_portp = NULL; + } + + /* to be safe and keep it simple, we issue a clear per port. + * ALL_PORT_SELECT is an optional capability not worth the effort to + * fetch and check + */ + for (q=cl_qmap_head(&nodep->Ports); q != cl_qmap_end(&nodep->Ports); q = cl_qmap_next(q)) { + PortData *portp = PARENT_STRUCT(q, PortData, NodePortsEntry); + uint8 ports = 1; // how many we are doing at a time + + if (focus && ! ComparePortPoint(portp, focus) + && (limitstats || ! portp->neighbor || ! ComparePortPoint(portp->neighbor, focus))) + continue; + +#ifdef PRODUCT_OPENIB_FF + /* use PaClient if available */ + if (g_paclient_state == OMGT_SERVICE_STATE_OPERATIONAL) + { + STL_PA_IMAGE_ID_DATA imageIdQuery = {PACLIENT_IMAGE_CURRENT, 0}; + + if (!first_portp) + lid = portp->PortInfo.LID; + status = pa_client_clr_port_counters( g_portHandle, imageIdQuery, lid, + portp->PortNum, counterselect ); + } +#endif + /* issue direct PMA query */ + else { + if (! PortHasPma(portp)) + continue; + if (first_portp) { + /* switch, issue clear to port 0 */ + // AllPortSelect availability can help out, so ask + if (! focus && ! nodep->PmaAvoidClassPortInfo) + (void)STLPmGetClassPortInfo(g_portHandle, first_portp); + + ports = cl_qmap_count(&nodep->Ports); + status = STLPmClearPortCounters(g_portHandle, first_portp, nodep->NodeInfo.NumPorts, counterselect); + } else { + /* CA and router, issue clear to specific port */ + status = GetPathToPort(g_portHandle, portGuid, portp); + if (FSUCCESS == status) { + status = STLPmClearPortCounters(g_portHandle, portp, 0, counterselect); + } else { + DBGPRINT("Unable to get Path to Port %d LID 0x%08x Node 0x%016"PRIx64"\n", + portp->PortNum, portp->EndPortLID, + portp->nodep->NodeInfo.NodeGUID); + DBGPRINT(" Name: %.*s\n", + STL_NODE_DESCRIPTION_ARRAY_SIZE, + (char*)portp->nodep->NodeDesc.NodeString); + } + } + } + + if (FSUCCESS != status) { + DBGPRINT("Unable to clear Port Counters for Port %d LID 0x%08x Node 0x%016"PRIx64"\n", + portp->PortNum, portp->EndPortLID, + portp->nodep->NodeInfo.NodeGUID); + DBGPRINT(" Name: %.*s\n", + STL_NODE_DESCRIPTION_ARRAY_SIZE, + (char*)portp->nodep->NodeDesc.NodeString); + (*fail_port_countp)+=ports; + fail = TRUE; + if (ports > 1) + break; + continue; + } + (*port_countp)+=ports; + cleared = TRUE; + if (ports > 1) + break; + } + if (cleared) + (*node_countp)++; + if (fail) + (*fail_node_countp)++; + } + + //Close the opamgt port handle + if (g_portHandle) { + omgt_close_port(g_portHandle); + g_portHandle = NULL; +#ifdef PRODUCT_OPENIB_FF + g_paclient_state = OMGT_SERVICE_STATE_UNKNOWN; +#endif + } + + if (! quiet) ProgressPrint(TRUE, "Done Clearing Port Counters"); + return FSUCCESS; // TBD +} + +FSTATUS InitSweepVerbose(FILE *verbose_file) +{ + g_verbose_file = verbose_file; + return FSUCCESS; +} + +// only FF_LIDARRAY fflag is used, others ignored +FSTATUS Sweep(EUI64 portGuid, FabricData_t *fabricp, FabricFlags_t fflags, SweepFlags_t flags, int quiet, int ms_timeout) +{ + FSTATUS fstatus; + struct omgt_port *omgt_port_session = NULL; + + if (FSUCCESS != InitFabricData(fabricp, fflags)) { + fprintf(stderr, "%s: Unable to initialize fabric storage area\n", + g_Top_cmdname); + return FERROR; + } + fabricp->ms_timeout = ms_timeout; + fstatus = omgt_open_port_by_guid(&omgt_port_session, portGuid, NULL); + if (fstatus != FSUCCESS) { + fprintf(stderr, "%s: Unable to open fabric interface.\n", + g_Top_cmdname); + return fstatus; + } + omgt_set_timeout(omgt_port_session, fabricp->ms_timeout); + time(&fabricp->time); +#ifdef IB_STACK_OPENIB +// omgt_mad_refresh_pkey_glob(); +#endif + // get QLogic master SM data if available + if ( (FSUCCESS != (fstatus = GetMasterSMData(omgt_port_session, portGuid, fabricp, flags, quiet))) && + (FUNAVAILABLE != fstatus) ) + goto done; + + // get the data from the SA + if (FSUCCESS != (fstatus = GetAllNodes(omgt_port_session, portGuid, fabricp, flags, quiet))) + goto done; + if (FSUCCESS != (fstatus = GetAllLinks(omgt_port_session, portGuid, fabricp, quiet))) + goto done; + if (FSUCCESS != (fstatus = GetAllCables(omgt_port_session, portGuid, fabricp, quiet))) + goto done; + if (flags & SWEEP_SM) { + if (FSUCCESS != (fstatus = GetAllSMs(omgt_port_session, portGuid, fabricp, quiet))) + goto done; + } + if (FSUCCESS != (fstatus = GetAllVFs(omgt_port_session, portGuid, fabricp, quiet))) + goto done; +done: + omgt_close_port(omgt_port_session); + return fstatus; +} + +/* Get all quarantined node records. + * Note that caller must free QueryResults. + */ +PQUERY_RESULT_VALUES GetAllQuarantinedNodes(struct omgt_port *port, + FabricData_t *fabricp, + Point *focus, + int quiet) +{ + OMGT_QUERY query; + FSTATUS status; + PQUERY_RESULT_VALUES pQueryResults = NULL; + + memset(&query, 0, sizeof(query)); // initialize reserved fields + query.InputType = InputTypeNoInput; + query.OutputType = OutputTypeStlQuarantinedNodeRecord; + + if (! quiet) ProgressPrint(FALSE, "Getting All Quarantined Node Records..."); + DBGPRINT("Query: Input=%s, Output=%s\n", + iba_sd_query_input_type_msg(query.InputType), + iba_sd_query_result_type_msg(query.OutputType)); + + // this call is synchronous + status = omgt_query_sa(port, &query, &pQueryResults); + + if (! pQueryResults) + { + fprintf(stderr, "%*sSA QuarantineNodeRecord query Failed: %s\n", 0, "", iba_fstatus_msg(status)); + return (NULL); + } else if (pQueryResults->Status != FSUCCESS) { + fprintf(stderr, "%*sSA QuarantineNodeRecord query Failed: %s MadStatus 0x%x: %s\n", 0, "", + iba_fstatus_msg(pQueryResults->Status), + pQueryResults->MadStatus, iba_sd_mad_status_msg(pQueryResults->MadStatus)); + } else if (pQueryResults->ResultDataSize == 0) { + fprintf(stderr, "%*sNo Quarantine Node Records Returned\n", 0, ""); + } else { + DBGPRINT("MadStatus 0x%x: %s\n", pQueryResults->MadStatus, + iba_sd_mad_status_msg(pQueryResults->MadStatus)); + DBGPRINT("%d Bytes Returned\n", pQueryResults->ResultDataSize); + } + if (! quiet) ProgressPrint(TRUE, "Done Getting All Quarantined Node Records"); + + // Note that caller must free QueryResults + return (pQueryResults); +} + +/* Get all device group member records. + * Note that caller must free QueryResults. + */ +PQUERY_RESULT_VALUES GetAllDeviceGroupMemberRecords(struct omgt_port *port, + FabricData_t *fabricp, + Point *focus, + int quiet) +{ + + OMGT_QUERY query; + FSTATUS status; + PQUERY_RESULT_VALUES pQueryResults = NULL; + + memset(&query, 0, sizeof(query)); // initialize reserved fields + query.InputType = InputTypeNoInput; + query.OutputType = OutputTypeStlDeviceGroupMemberRecord; + + if (! quiet) ProgressPrint(FALSE, "Getting All Device Group Member Records..."); + + DBGPRINT("Query: Input=%s, Output=%s\n", + iba_sd_query_input_type_msg(query.InputType), + iba_sd_query_result_type_msg(query.OutputType)); + + // this call is synchronous + status = omgt_query_sa(port, &query, &pQueryResults); + + if (! pQueryResults) { + fprintf(stderr, "%*sSA DeviceGroupMemberRecord query Failed: %s\n", 0, "", iba_fstatus_msg(status)); + return NULL; + } else if (pQueryResults->Status != FSUCCESS) { + fprintf(stderr, "%*sSA DeviceGroupMemberRecord query Failed: %s MadStatus 0x%x: %s\n", 0, "", + iba_fstatus_msg(pQueryResults->Status), + pQueryResults->MadStatus, iba_sd_mad_status_msg(pQueryResults->MadStatus)); + } else if (pQueryResults->ResultDataSize == 0) { + fprintf(stderr, "%*sNo DeviceGroupMember Records Returned\n", 0, ""); + } else { + DBGPRINT("MadStatus 0x%x: %s\n", pQueryResults->MadStatus, + iba_sd_mad_status_msg(pQueryResults->MadStatus)); + DBGPRINT("%d Bytes Returned\n", pQueryResults->ResultDataSize); + } + if (! quiet) ProgressPrint(TRUE, "Done Getting All Device Group Member Records"); + + // Note that caller must free QueryResults + return (pQueryResults); +} + diff --git a/Topology/topology.c b/Topology/topology.c new file mode 100644 index 0000000..6bed156 --- /dev/null +++ b/Topology/topology.c @@ -0,0 +1,1481 @@ +/* BEGIN_ICS_COPYRIGHT7 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT7 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +#include "topology.h" +#include "topology_internal.h" + +typedef enum { + MATCH_NONE=0, // worst - nothing matched + MATCH_NODE=1, // better - exact match on Node + MATCH_PORT=2 // best - exact match on Port +} PortSelMatchLevel_t; + +/* this file supports fabric topology input file parsing and output */ + +/****************************************************************************/ +/* Cable Data Input/Output functions */ + +IXML_FIELD CableDataFields[] = { + { tag:"CableLength", format:'p', IXML_P_FIELD_INFO(CableData, length, CABLE_LENGTH_STRLEN) }, + { tag:"CableLabel", format:'p', IXML_P_FIELD_INFO(CableData, label, CABLE_LABEL_STRLEN) }, + { tag:"CableDetails", format:'p', IXML_P_FIELD_INFO(CableData, details, CABLE_DETAILS_STRLEN) }, + { NULL } +}; + +static void CableDataXmlOutput(IXmlOutputState_t *state, const char *tag, void *data) +{ + IXmlOutputStruct(state, tag, (CableData*)data, NULL, CableDataFields); +} + +static void *CableDataXmlParserStart(IXmlParserState_t *state, void *parent, const char **attr) +{ + ExpectedLink *elinkp = (ExpectedLink*)parent; + + return &(elinkp->CableData); +} + +static void CableDataXmlParserEnd(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + CableData *cablep = (CableData*)object; + FabricData_t *fabricp = IXmlParserGetContext(state); + + if (! valid) + goto invalid; + if (cablep->length || cablep->label || cablep->details) + fabricp->flags |= FF_CABLEDATA; + return; + +invalid: + CableDataFree(cablep); + return; +} + +/****************************************************************************/ +/* PortSelector Input/Output functions */ + +// for use in error messages, returns pointer to static string +// Beware, can't call this more than twice in a single function argument list +// (such as printf) +// This is also not thread safe +static const char *FormatPortSelector(PortSelector *portselp) +{ + static char format1[256]; + static char format2[256]; + static int f_num = 0; + int offset = 0; + char *format; + + // This trick allows us to alternate which static char we use and return + // hence two calls in the same function argument list (eg. printf) work + // correctly + if (f_num) { + format=format2; + f_num=0; + } else { + format=format1; + f_num=1; + } + + if (! portselp) { + offset += sprintf(&format[offset], "%*sunspecified", offset?1:0, ""); + return format; + } + if (portselp->NodeDesc) { + offset += sprintf(&format[offset], "%*sNodeDesc: %s", offset?1:0, "", portselp->NodeDesc); + } + if (portselp->NodeGUID) { + offset += sprintf(&format[offset], "%*sNodeGUID: 0x%016"PRIx64, offset?1:0, "", portselp->NodeGUID); + } + if (portselp->gotPortNum) { + offset += sprintf(&format[offset], "%*sPortNum: %u", offset?1:0, "", portselp->PortNum); + } + if (portselp->PortGUID) { + offset += sprintf(&format[offset], "%*sPortGUID: 0x%016"PRIx64, offset?1:0, "", portselp->PortGUID); + } + if (portselp->NodeType) { + offset += sprintf(&format[offset], "%*sNodeType: %s", offset?1:0, "", + StlNodeTypeToText(portselp->NodeType)); + } + if (portselp->details) { + offset += sprintf(&format[offset], "%*sPortDetails: %s", offset?1:0, "", + portselp->details); + } + if (! offset) + offset += sprintf(&format[offset], "%*sunspecified", offset?1:0, ""); + return format; +} + +/* PortNum needs special handling since have gotPortNum flag to maintain */ +static void PortSelectorXmlOutputPortNum(IXmlOutputState_t *state, const char *tag, void *data) +{ + PortSelector *portselp = (PortSelector*)data; + if (portselp->gotPortNum) + IXmlOutputUint(state, tag, portselp->PortNum); +} + +static void PortSelectorXmlParserEndPortNum(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + uint8 value; + + if (IXmlParseUint8(state, content, len, &value)) { + if (value > 254) { + IXmlParserPrintError(state, "PortNum must be in range [0,254]"); + } else { + ((PortSelector *)object)->PortNum = value; + ((PortSelector *)object)->gotPortNum = 1; + } + } +} + +// returns 1st matching node name found +static NodeData* LookupNodeName(FabricData_t *fabricp, char *name) +{ + cl_map_item_t *p; + + for (p=cl_qmap_head(&fabricp->AllNodes); p != cl_qmap_end(&fabricp->AllNodes); p = cl_qmap_next(p)) { + NodeData *nodep = PARENT_STRUCT(p, NodeData, AllNodesEntry); + if (strncmp((char*)nodep->NodeDesc.NodeString, + name, STL_NODE_DESCRIPTION_ARRAY_SIZE) == 0) + { + return nodep; + } + } + return NULL; +} + +// resolve as much as we can about the given Port Selector +static void ResolvePortSelector(FabricData_t *fabricp, PortSelector *portselp, NodeData **nodepp, PortData **portpp, PortSelMatchLevel_t *matchLevel) +{ + *nodepp = NULL; + *portpp = NULL; + *matchLevel=MATCH_NONE; + + if (! portselp) + return; + // order of preference if all specified is: NodeGUID, PortGUID, Desc + // This way if Node Descriptions have not been fully setup and there + // are duplicates, a "opareport -o links -x" can still be used + // as basic template for topology input + // Valid combos in order of consideration: + // NodeGUID, PortNum + // NodeGUID, PortGUID - only if PortGUID on same node as NodeGUID + // NodeGUID (fully resolves to port if only 1 port on node) + // NodeDesc, PortNum + // NodeDesc, PortGUID - only if PortGUID on same node as NodeDesc + // NodeDesc (fully resolves to port if only 1 port on node) + // PortGUID, PortNum (useful if PortGUID is switch port 0) + // PortGUID + // presently: + // NodeGuid, NodeDesc - NodeDesc is ignored + // NodeGuid/Desc, PortNum, PortGUID - PortGUID is ignored + // NodeType is ignored + if (portselp->NodeGUID) { + *nodepp = FindNodeGuid(fabricp, portselp->NodeGUID); + if (*nodepp) + *matchLevel=MATCH_NODE; + } + if (! *nodepp && portselp->NodeDesc) { + *nodepp = LookupNodeName(fabricp, portselp->NodeDesc); + if (*nodepp) + *matchLevel=MATCH_NODE; + } + if (! *nodepp && portselp->PortGUID) { + *portpp = FindPortGuid(fabricp, portselp->PortGUID); + if (*portpp) { + *nodepp = (*portpp)->nodep; + *matchLevel=MATCH_PORT; + } + } + if (*nodepp && portselp->gotPortNum) { + PortData *portp = FindNodePort(*nodepp, portselp->PortNum); + if (portp) { + *portpp = portp; // overrides PortGUID + *matchLevel=MATCH_PORT; + } + } + if (*nodepp && ! *portpp && portselp->PortGUID) { + PortData *portp = FindPortGuid(fabricp, portselp->PortGUID); + if (portp && portp->nodep == *nodepp) { + *portpp = portp; + *matchLevel=MATCH_PORT; + } + } + if (*nodepp && ! *portpp) { + // node matched, if only 1 active port, resolve to it + // we are purposely soft about PortGUID and PortNum in this case + // as such we can better report links which were Changed + if (cl_qmap_count(&(*nodepp)->Ports) == 1) { + *portpp = PARENT_STRUCT(cl_qmap_head(&(*nodepp)->Ports), PortData, NodePortsEntry); + // fuzzy match, so do not update matchLevel + } + } +} + +// table to translate from per PortSelector matchLevel into overall rank +// of ExpectedLink match level. This is used to compare in case of conflicts +// to decide which expected link matched "best" with an actual link +static int g_linkMatchLevel[3][3] = { + { // Table is + 0, // None, None // 5 = Port,Port + 1, // None, Node // 4 = Port,Node; Node,Port + 2, // None, Port // 3 = Node,Node + }, // 2 = Port,None; None,Port + { // 1 = Node,None; None,Node + 1, // Node, None // 0 = None, None + 3, // Node, Node + 4, // Node, Port + }, + { + 2, // Port, None + 4, // Port, Node + 5, // Port, Port + } +}; + +static boolean isCompletePortSelector(PortSelector *portselp) +{ + if (! portselp) + return FALSE; + return ((portselp->NodeGUID && portselp->gotPortNum) + || (portselp->PortGUID) + || (portselp->NodeDesc && portselp->gotPortNum)); + // the two below are indeterminate + // NodeGUID (fully resolves to port if only 1 port on node) + // NodeDesc (fully resolves to port if only 1 port on node) +} + + +IXML_FIELD PortSelectorFields[] = { + { tag:"NodeGUID", format:'h', IXML_FIELD_INFO(PortSelector, NodeGUID) }, + { tag:"PortGUID", format:'h', IXML_FIELD_INFO(PortSelector, PortGUID) }, + { tag:"PortNum", format:'k', format_func: PortSelectorXmlOutputPortNum, end_func:PortSelectorXmlParserEndPortNum }, + { tag:"NodeDesc", format:'p', IXML_P_FIELD_INFO(PortSelector, NodeDesc, STL_NODE_DESCRIPTION_ARRAY_SIZE) }, + { tag:"PortDetails", format:'p', IXML_P_FIELD_INFO(PortSelector, details, PORT_DETAILS_STRLEN) }, + { tag:"NodeType", format:'k', IXML_FIELD_INFO(PortSelector, NodeType), format_func:IXmlOutputOptionalNodeType, end_func:IXmlParserEndNodeType }, // input str output both + { tag:"NodeType_Int", format:'k', IXML_FIELD_INFO(PortSelector, NodeType), format_func:IXmlOutputNoop, end_func:IXmlParserEndNodeType_Int}, // input Int, output none (above does both) + { NULL } +}; + +static void PortSelectorXmlFormatAttr(IXmlOutputState_t *state, void *data) +{ + PortSelector *portselp = (PortSelector *)data; + + // perl and other tools need unique id + IXmlOutputPrint(state, " id=\"0x%016"PRIx64"\"", (uint64)(uintn)portselp); +} + +static void PortSelectorXmlOutput(IXmlOutputState_t *state, const char *tag, void *data) +{ + IXmlOutputOptionalStruct(state, tag, (PortSelector*)data, PortSelectorXmlFormatAttr, PortSelectorFields); +} + + +static void PortSelectorXmlParserEnd(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + PortSelector *portselp = (PortSelector*)object; + ExpectedLink *elinkp = (ExpectedLink*)parent; + + if (! valid) + goto invalid; + if (! elinkp->portselp1) + elinkp->portselp1 = portselp; + else if (! elinkp->portselp2) + elinkp->portselp2 = portselp; + else { + IXmlParserPrintError(state, "Too many Ports specified for Link, ignoring: %s\n", + FormatPortSelector(portselp)); + goto badport; + } + return; + +badport: +invalid: + PortSelectorFree(portselp); + return; +} + +/****************************************************************************/ +/* Link Input/Output functions */ + +static void LinkXmlOutputCableData(IXmlOutputState_t *state, const char *tag, void *data) +{ + CableDataXmlOutput(state, tag, &((ExpectedLink*)data)->CableData); +} + +static void LinkXmlOutputPortSelectors(IXmlOutputState_t *state, const char *tag, void *data) +{ + PortSelectorXmlOutput(state, tag, ((ExpectedLink*)data)->portselp1); + PortSelectorXmlOutput(state, tag, ((ExpectedLink*)data)->portselp2); +} + +/* description */ +static IXML_FIELD LinkFields[] = { + { tag:"Rate", format:'k', IXML_FIELD_INFO(ExpectedLink, expected_rate), format_func:IXmlOutputOptionalRate, end_func:IXmlParserEndRate }, // input str output both + { tag:"Rate_Int", format:'k', IXML_FIELD_INFO(ExpectedLink, expected_rate), format_func:IXmlOutputNoop, end_func:IXmlParserEndRate_Int}, // input Int, output none (above does both) + { tag:"MTU", format:'k', IXML_FIELD_INFO(ExpectedLink, expected_mtu), format_func:IXmlOutputOptionalMtu, end_func:IXmlParserEndMtu }, + { tag:"Internal", format:'u', IXML_FIELD_INFO(ExpectedLink, internal) }, + { tag:"LinkDetails", format:'p', IXML_P_FIELD_INFO(ExpectedLink, details, LINK_DETAILS_STRLEN) }, + { tag:"Cable", format:'k', size:sizeof(CableData), format_func:LinkXmlOutputCableData, subfields:CableDataFields, start_func:CableDataXmlParserStart, end_func:CableDataXmlParserEnd }, // structure + { tag:"Port", format:'K', size:sizeof(PortSelector), format_func:LinkXmlOutputPortSelectors, subfields:PortSelectorFields, start_func:IXmlParserStartStruct, end_func:PortSelectorXmlParserEnd }, // structure + { NULL } +}; + +static void LinkXmlOutput(IXmlOutputState_t *state, const char *tag, void *data) +{ + IXmlOutputStruct(state, tag, (ExpectedLink*)data, NULL /*ExpectedLinkXmlFormatAttr*/ , LinkFields); +} + +static void *LinkXmlParserStart(IXmlParserState_t *state, void *parent, const char **attr) +{ + ExpectedLink *elinkp = (ExpectedLink*)MemoryAllocate2AndClear(sizeof(ExpectedLink), IBA_MEM_FLAG_PREMPTABLE, MYTAG); + + if (! elinkp) { + IXmlParserPrintError(state, "Unable to allocate memory"); + return NULL; + } + + ListItemInitState(&elinkp->ExpectedLinksEntry); + QListSetObj(&elinkp->ExpectedLinksEntry, elinkp); + + elinkp->lineno = (uint64)XML_GetCurrentLineNumber(state->parser); + + return elinkp; +} + +static void ResolvePorts(FabricData_t *fabricp, ExpectedLink *elinkp) +{ + NodeData *nodep1, *nodep2; + PortData *portp1, *portp2; + PortSelMatchLevel_t matchLevel1, matchLevel2; + uint8 linkMatchLevel; + + // First resolve the two Port Selectors in elinkp to ports in the fabric + ResolvePortSelector(fabricp, elinkp->portselp1, &nodep1, &portp1, &matchLevel1); + ResolvePortSelector(fabricp, elinkp->portselp2, &nodep2, &portp2, &matchLevel2); + linkMatchLevel = g_linkMatchLevel[matchLevel1][matchLevel2]; + + if (! portp1 && ! portp2) { + // we can't resolve either side + // will report as missing link during verification + return; + } + + // we purposely have some fuzzy logic here. This attempts to associate + // the link with some link in the fabric. This permits the verification + // to better report links which are changed by moving one end of a cable. + // if only 1 side of link is specified, we assume any neighbor is acceptable + // we will check other details (NodeType, etc) during verification + if (portp1 && ! isCompletePortSelector(elinkp->portselp2)) { + portp2 = portp1->neighbor; + } else if (portp2 && ! isCompletePortSelector(elinkp->portselp1)) { + portp1 = portp2->neighbor; + } + + // if one side resolved to a port and other resolved to neighbor node + // we treat this as a match. Hence we can identify changed links + // and also can handle incomplete specification of selector for "other side" + if (portp1 && ! portp2 && nodep2 && portp1->neighbor && portp1->neighbor->nodep == nodep2) { + portp2 = portp1->neighbor; + } + if (portp2 && ! portp1 && nodep1 && portp2->neighbor && portp2->neighbor->nodep == nodep1) { + portp1 = portp2->neighbor; + } + + // If portp1 and/or portp2 already have a good elinkp, evaluate completeness + // of match and associate ports with the "better" matching elinkp. + if (portp1 && portp1->elinkp && portp2 && portp2->elinkp + && portp1->elinkp == portp2->elinkp) { + + ExpectedLink *elinkp2 = portp1->elinkp; + // we have a potentially duplicate match. This elinkp or elinkp2 + // match could be due to fuzzy logic or a duplicate in input. + // if one elinkp is due to fuzzy logic and other is due to exact match + // the exact match wins. Hence preventing incorrect reporting of + // a missing link such as when a CA has both ports connected and 1 port + // goes down. + // Hence we compare the quality of the match and pick the better one. + // If both are at the same level of match, associate both links with + // same ports and leave ports as is and we will report duplicate/changed + if (elinkp2->matchLevel > linkMatchLevel) { + // elinkp2 is a better match, leave elinkp unassociated so + // reported as a missing link + return; + } else if (elinkp2->matchLevel < linkMatchLevel) { + // new match is better, unlink old from elinkp2 + // will associate ports below + portp1->elinkp = portp2->elinkp = NULL; + elinkp2->portp1 = elinkp2->portp2 = NULL; + elinkp2->matchLevel = 0; + } else { + // equal quality of match, associate ports below and will report as + // a potential duplicate in input + } + } + elinkp->portp1 = portp1; + elinkp->portp2 = portp2; + elinkp->matchLevel = linkMatchLevel; + + // if we have properly resolved both ports, we update PortData + // if this resolves to ports which already have a PortData->elinkp, we do + // report that during verification and leave elinkp pointing to port + // but Port will not point to the duplicate elinkp + // during verify we will check for each link that + // elinkp->portp1->elinkp==elinkp && elinkp->portp2->elinkp==elinkp + // those which do not (or have NULL portp1/2) are dup, missing, etc + if (portp1 && portp2 && portp1->neighbor == portp2 + && ! portp1->elinkp && ! portp2->elinkp) { + // we resolved properly to both sides of a link */ + ASSERT(portp2->neighbor == portp1); + elinkp->portp1->elinkp = elinkp; + elinkp->portp2->elinkp = elinkp; + } +} + +static void LinkXmlParserEnd(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + ExpectedLink *elinkp = (ExpectedLink*)object; + FabricData_t *fabricp = IXmlParserGetContext(state); + + if (! valid) + goto invalid; + ResolvePorts(fabricp, elinkp); + QListInsertTail(&fabricp->ExpectedLinks, &elinkp->ExpectedLinksEntry); + return; + +invalid: + ExpectedLinkFree(fabricp, elinkp); + return; +} + + +static IXML_FIELD LinksFields[] = { + { tag:"Link", format:'K', format_func: LinkXmlOutput, subfields:LinkFields, start_func:LinkXmlParserStart, end_func:LinkXmlParserEnd }, // structure + { NULL } +}; + +/****************************************************************************/ +/* Overall Links lists Input/Output functions */ + +static void Xml2PrintAllLinks(IXmlOutputState_t *state, const char *tag, void *data) +{ + LIST_ITEM *p; + FabricData_t *fabricp = (FabricData_t *)IXmlOutputGetContext(state); + + IXmlOutputStartAttrTag(state, tag, NULL, NULL); + for (p=QListHead(&fabricp->ExpectedLinks); p != NULL; p = QListNext(&fabricp->ExpectedLinks, p)) { + ExpectedLink *elinkp = (ExpectedLink *)QListObj(p); +#if 0 + if (! CompareLinkPoint(elinkp, info->focus)) + continue; +#endif + LinkXmlOutput(state, "Link", elinkp); + } + IXmlOutputEndTag(state, tag); +} + +static void *LinkSummaryXmlParserStart(IXmlParserState_t *state, void *parent, const char **attr) +{ + FabricData_t *fabricp = IXmlParserGetContext(state); + + if (fabricp->flags & (FF_EXPECTED_LINKS|FF_EXPECTED_EXTLINKS)) { + IXmlParserPrintError(state, "Only one of or can be supplied\n"); + return NULL; + } + return parent; +} + +static void LinkSummaryXmlParserEnd(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + FabricData_t *fabricp = IXmlParserGetContext(state); + + if (! valid) + goto invalid; + fabricp->flags |= FF_EXPECTED_LINKS; + return; + +invalid: + return; +} + +static void *ExternalLinkSummaryXmlParserStart(IXmlParserState_t *state, void *parent, const char **attr) +{ + FabricData_t *fabricp = IXmlParserGetContext(state); + + if (fabricp->flags & (FF_EXPECTED_LINKS|FF_EXPECTED_EXTLINKS)) { + IXmlParserPrintError(state, "Only one of or can be supplied\n"); + return NULL; + } + return NULL; +} + +static void ExternalLinkSummaryXmlParserEnd(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + FabricData_t *fabricp = IXmlParserGetContext(state); + + if (! valid) + goto invalid; + fabricp->flags |= FF_EXPECTED_EXTLINKS; + return; + +invalid: + return; +} + +static void ExpectedPortXmlParserEndPortNum(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + uint8 value; + + if (IXmlParseUint8(state, content, len, &value)) { + if (value > 254) { + IXmlParserPrintError(state, "PortNum must be in range [0,254]"); + } else { + ((ExpectedPort *)object)->PortNum = value; + } + } +} + +static void ExpectedPortXmlParserEndLmc(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + uint8 value; + + if (IXmlParseUint8(state, content, len, &value)) + ((ExpectedPort *)object)->lmc = value; +} + +static IXML_FIELD ExpectedPortFields[] = { + { tag:"PortNum", format:'u', end_func:ExpectedPortXmlParserEndPortNum }, + { tag:"LID", format:'h', IXML_FIELD_INFO(ExpectedPort, lid) }, + { tag:"LMC", format:'u', end_func:ExpectedPortXmlParserEndLmc }, + { tag:"PortGUID", format:'h', IXML_FIELD_INFO(ExpectedPort, PortGuid) }, + { NULL } +}; + + +/****************************************************************************/ +/* Node Input/Output functions */ + +// for use in error messages, returns pointer to static string +// Beware, can't call this more than twice in a single function argument list +// (such as printf) +// This is also not thread safe +static const char *FormatExpectedNode(ExpectedNode *enodep) +{ + static char format1[256]; + static char format2[256]; + static int f_num = 0; + int offset = 0; + char *format; + + // This trick allows us to alternate which static char we use and return + // hence two calls in the same function argument list (eg. printf) work + // correctly + if (f_num) { + format=format2; + f_num=0; + } else { + format=format1; + f_num=1; + } + + + if (! enodep) { + offset += sprintf(&format[offset], "%*sunspecified", offset?1:0, ""); + return format; + } + if (enodep->NodeDesc) { + offset += sprintf(&format[offset], "%*sNodeDesc: %s", offset?1:0, "", enodep->NodeDesc); + } + if (enodep->NodeGUID) { + offset += sprintf(&format[offset], "%*sNodeGUID: 0x%016"PRIx64, offset?1:0, "", enodep->NodeGUID); + } + if (enodep->NodeType) { + offset += sprintf(&format[offset], "%*sNodeType: %s", offset?1:0, "", + StlNodeTypeToText(enodep->NodeType)); + } + if (enodep->details) { + offset += sprintf(&format[offset], "%*sNodeDetails: %s", offset?1:0, "", + enodep->details); + } + if (! offset) + offset += sprintf(&format[offset], "%*sunspecified", offset?1:0, ""); + return format; +} + +/* fields */ + +static void *ExpectedPortXmlParserStart(IXmlParserState_t *state, void *parent, const char **attr) +{ + ExpectedPort *eportp = MemoryAllocate2AndClear(sizeof(ExpectedPort), + IBA_MEM_FLAG_PREMPTABLE, MYTAG); + + if (!eportp) { + IXmlParserPrintError(state, "Unable to allocate memory"); + return NULL; + } + + return eportp; +} + +// check enodep->ports size and grow as needed to accomidate adding portNum +static FSTATUS ExpectedNodePrepareSize(ExpectedNode *enodep, uint8 portNum) +{ + if ((portNum + 1) > enodep->portsSize) { + int allocCount = MAX((enodep->portsSize == 0 ? 1 : 2 * enodep->portsSize), + portNum + 1); + ExpectedPort **newMem = MemoryAllocate2AndClear(allocCount * sizeof(ExpectedPort*), + IBA_MEM_FLAG_PREMPTABLE, MYTAG); + if (!newMem) { + return FINSUFFICIENT_MEMORY; + } + + if (enodep->ports) { + memcpy(newMem, enodep->ports, enodep->portsSize * sizeof(ExpectedPort*)); + MemoryDeallocate(enodep->ports); + } + enodep->ports = newMem; + enodep->portsSize = allocCount; + } + return FSUCCESS; +} + +static FSTATUS ExpectedNodeAddPort(ExpectedNode *enodep, ExpectedPort *eportp) +{ + if (FSUCCESS != ExpectedNodePrepareSize(enodep, eportp->PortNum)) + return FINSUFFICIENT_MEMORY; + + if (enodep->ports[eportp->PortNum] != NULL) + return FDUPLICATE; + + enodep->ports[eportp->PortNum] = eportp; + return FSUCCESS; +} + +static ExpectedPort *ExpectedNodeGetPort(ExpectedNode *enodep, uint8 portNum) +{ + if(portNum >= enodep->portsSize) + return NULL; + else + return enodep->ports[portNum]; +} + +static void ExpectedPortXmlParserEnd(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + ExpectedNode *enodep = (ExpectedNode*)parent; + ExpectedPort *eportp = (ExpectedPort*)object; + + if (!valid) + goto invalid; + + switch (ExpectedNodeAddPort(enodep, eportp)) { + case FSUCCESS: + break; + case FINVALID_PARAMETER: + break; + case FINSUFFICIENT_MEMORY: + IXmlParserPrintError(state, "Unable to allocate memory"); + goto invalid; + break; + case FDUPLICATE: + // depending on order of tags, we may not yet know the complete enodep + IXmlParserPrintError(state, "Duplicate PortNums (%u) found in Node: %s\n", eportp->PortNum, FormatExpectedNode(enodep)); + goto invalid; + break; + default: // unexpected + // depending on order of tags, we may not yet know the complete enodep + IXmlParserPrintError(state, "Unable to add port %u to Node: %s\n", eportp->PortNum, FormatExpectedNode(enodep)); + goto invalid; + break; + } + + enodep->ports[eportp->PortNum] = eportp; + return; + +invalid: + MemoryDeallocate(eportp); +} + +static IXML_FIELD ExpectedNodeFields[] = { + { tag:"NodeGUID", format:'h', IXML_FIELD_INFO(ExpectedNode, NodeGUID) }, + { tag:"NodeDesc", format:'p', IXML_P_FIELD_INFO(ExpectedNode, NodeDesc, STL_NODE_DESCRIPTION_ARRAY_SIZE) }, + { tag:"NodeDetails", format:'p', IXML_P_FIELD_INFO(ExpectedNode, details, NODE_DETAILS_STRLEN) }, + { tag:"Port", format:'k', subfields:ExpectedPortFields, start_func:ExpectedPortXmlParserStart, end_func:ExpectedPortXmlParserEnd }, + { NULL } +}; + +static void ExpectedNodeXmlOutput(IXmlOutputState_t *state, const char *tag, void *data) +{ + IXmlOutputStruct(state, tag, (ExpectedNode*)data, NULL /*ExpectedNodeXmlFormatAttr*/ , ExpectedNodeFields); +} + +static void *ExpectedNodeXmlParserStart(IXmlParserState_t *state, void *parent, const char **attr) +{ + ExpectedNode *enodep = (ExpectedNode*)MemoryAllocate2AndClear(sizeof(ExpectedNode), IBA_MEM_FLAG_PREMPTABLE, MYTAG); + + if (! enodep) { + IXmlParserPrintError(state, "Unable to allocate memory"); + return NULL; + } + + ListItemInitState(&enodep->ExpectedNodesEntry); + QListSetObj(&enodep->ExpectedNodesEntry, enodep); + + enodep->lineno = (uint64)XML_GetCurrentLineNumber(state->parser); + + return enodep; +} + +// resolve the Expected Node to a node in fabric +static void ResolveNode(FabricData_t *fabricp, ExpectedNode *enodep) +{ + NodeData *nodep = NULL; + + if (! enodep) + return; + // order of preference if all specified is: NodeGUID, Desc + // This way if Node Descriptions have not been fully setup and there + // are duplicates, a "opareport -o brnodes -x" can still be used + // as basic template for topology input + // Valid combos in order of consideration: + // NodeGUID + // NodeDesc + // presently: + // NodeGuid, NodeDesc - NodeDesc is ignored + // NodeType is ignored + if (enodep->NodeGUID) { + nodep = FindNodeGuid(fabricp, enodep->NodeGUID); + } + if (! nodep && enodep->NodeDesc) { + nodep = LookupNodeName(fabricp, enodep->NodeDesc); + } + + enodep->nodep = nodep; + // if we have properly resolved the node, we update NodeData + // if this resolves to a node which already have a NodeData->enodep, we do + // report that during verification and leave enodep pointing to node + // but Node will not point to the duplicate enodep + // during verify we will check for each node that + // enodep->nodep->enodep==enodep + // those which do not (or have NULL nodep) are dup, missing, etc + if (nodep && ! nodep->enodep) { + nodep->enodep = enodep; + } +} + +static void ExpectedFIXmlParserEnd(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + ExpectedNode *enodep = (ExpectedNode*)object; + FabricData_t *fabricp = IXmlParserGetContext(state); + + + enodep->NodeType = STL_NODE_FI; + if (! valid) + goto invalid; + ResolveNode(fabricp, enodep); + QListInsertTail(&fabricp->ExpectedFIs, &enodep->ExpectedNodesEntry); + + + if(enodep->NodeGUID) { + //Attempts to insert duplicates will not be detected here. Duplicates can be detected later if topology + //file validation is enabled + cl_qmap_insert(&fabricp->ExpectedNodeGuidMap, enodep->NodeGUID, &enodep->ExpectedNodeGuidMapEntry); + } + + return; + +invalid: + ExpectedNodeFree(fabricp, enodep, &fabricp->ExpectedFIs); + return; +} + +static void ExpectedSWXmlParserEnd(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + ExpectedNode *enodep = (ExpectedNode*)object; + FabricData_t *fabricp = IXmlParserGetContext(state); + + enodep->NodeType = STL_NODE_SW; + if (! valid) + goto invalid; + ResolveNode(fabricp, enodep); + QListInsertTail(&fabricp->ExpectedSWs, &enodep->ExpectedNodesEntry); + + if(enodep->NodeGUID) { + //Attempts to insert duplicates will not be detected here. Duplicates can be detected later if topology + //file validation is enabled + cl_qmap_insert(&fabricp->ExpectedNodeGuidMap, enodep->NodeGUID, &enodep->ExpectedNodeGuidMapEntry); + } + return; + +invalid: + ExpectedNodeFree(fabricp, enodep, &fabricp->ExpectedSWs); + return; +} + +static IXML_FIELD FIsFields[] = { + { tag:"Node", format:'k', format_func: ExpectedNodeXmlOutput, subfields:ExpectedNodeFields, start_func:ExpectedNodeXmlParserStart, end_func:ExpectedFIXmlParserEnd }, // structure + { NULL } +}; + +static IXML_FIELD SWsFields[] = { + { tag:"Node", format:'k', format_func: ExpectedNodeXmlOutput, subfields:ExpectedNodeFields, start_func:ExpectedNodeXmlParserStart, end_func:ExpectedSWXmlParserEnd }, // structure + { NULL } +}; + +/****************************************************************************/ +/* SM Input/Output functions */ + +/* PortNum needs special handling since have gotPortNum flag to maintain */ +static void ExpectedSMXmlOutputPortNum(IXmlOutputState_t *state, const char *tag, void *data) +{ + ExpectedSM *esmp = (ExpectedSM*)data; + if (esmp->gotPortNum) + IXmlOutputUint(state, tag, esmp->PortNum); +} + +static void ExpectedSMXmlParserEndPortNum(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + uint8 value; + + if (IXmlParseUint8(state, content, len, &value)) { + ((ExpectedSM *)object)->PortNum = value; + ((ExpectedSM *)object)->gotPortNum = 1; + } +} + +/* fields */ +static IXML_FIELD ExpectedSMFields[] = { + { tag:"NodeGUID", format:'h', IXML_FIELD_INFO(ExpectedSM, NodeGUID) }, + { tag:"PortGUID", format:'h', IXML_FIELD_INFO(ExpectedSM, PortGUID) }, + { tag:"PortNum", format:'k', format_func: ExpectedSMXmlOutputPortNum, end_func:ExpectedSMXmlParserEndPortNum }, + { tag:"NodeDesc", format:'p', IXML_P_FIELD_INFO(ExpectedSM, NodeDesc, STL_NODE_DESCRIPTION_ARRAY_SIZE) }, + { tag:"SMDetails", format:'p', IXML_P_FIELD_INFO(ExpectedSM, details, SM_DETAILS_STRLEN) }, + { tag:"NodeType", format:'k', IXML_FIELD_INFO(ExpectedSM, NodeType), format_func:IXmlOutputOptionalNodeType, end_func:IXmlParserEndNodeType }, // input str output both + { tag:"NodeType_Int", format:'k', IXML_FIELD_INFO(ExpectedSM, NodeType), format_func:IXmlOutputNoop, end_func:IXmlParserEndNodeType_Int}, // input Int, output none (above does both) + { NULL } +}; + +static void ExpectedSMXmlOutput(IXmlOutputState_t *state, const char *tag, void *data) +{ + IXmlOutputStruct(state, tag, (ExpectedSM*)data, NULL /*ExpectedSMXmlFormatAttr*/ , ExpectedSMFields); +} + +static void *ExpectedSMXmlParserStart(IXmlParserState_t *state, void *parent, const char **attr) +{ + ExpectedSM *esmp = (ExpectedSM*)MemoryAllocate2AndClear(sizeof(ExpectedSM), IBA_MEM_FLAG_PREMPTABLE, MYTAG); + + if (! esmp) { + IXmlParserPrintError(state, "Unable to allocate memory"); + return NULL; + } + + ListItemInitState(&esmp->ExpectedSMsEntry); + QListSetObj(&esmp->ExpectedSMsEntry, esmp); + + return esmp; +} + +// resolve the Expected SM to a node in fabric +static void ResolveSM(FabricData_t *fabricp, ExpectedSM *esmp) +{ + SMData *smp = NULL; + NodeData *nodep = NULL; + PortData *portp = NULL; + + if (! esmp) + return; + // order of preference if all specified is: NodeGUID, PortGUID, Desc + // This way if Node Descriptions have not been fully setup and there + // are duplicates, a "opareport -o brnodes -x" can still be used + // as basic template for topology input + // Valid combos in order of consideration: + // NodeGUID, PortNum + // NodeGUID, PortGUID - only if PortGUID on same node as NodeGUID + // NodeGUID (fully resolves to port if only 1 active port on node or port 0 on a Switch) + // NodeDesc, PortNum + // NodeDesc, PortGUID - only if PortGUID on same node as NodeDesc + // NodeDesc (fully resolves to port if only 1 active port on node or port 0 on a Switch) + // PortGUID, PortNum (limited use) + // PortGUID + // presently: + // NodeGuid, NodeDesc - NodeDesc is ignored + // NodeGuid/Desc, PortNum, PortGUID - PortGUID is ignored + // NodeType is ignored + if (esmp->NodeGUID) { + nodep = FindNodeGuid(fabricp, esmp->NodeGUID); + } + if (! nodep && esmp->NodeDesc) { + nodep = LookupNodeName(fabricp, esmp->NodeDesc); + } + if (! nodep && esmp->PortGUID) { + portp = FindPortGuid(fabricp, esmp->PortGUID); + if (portp) + nodep = portp->nodep; + } + if (nodep && esmp->gotPortNum) { + PortData *p = FindNodePort(nodep, esmp->PortNum); + if (p) + portp = p; // overrides PortGUID + } + if (nodep && ! portp && esmp->PortGUID) { + PortData *p = FindPortGuid(fabricp, esmp->PortGUID); + if (p && p->nodep == nodep) + portp = p; + } + if (nodep && ! portp) { + // if switch, default to port 0 + if (nodep->NodeInfo.NodeType == STL_NODE_SW) + portp = FindNodePort(nodep, 0); + // if only 1 active port, default to it + if (! portp && cl_qmap_count(&nodep->Ports) == 1) { + portp = PARENT_STRUCT(cl_qmap_head(&nodep->Ports), PortData, NodePortsEntry); + } + } + + if (! portp) + return; + smp = FindSMPort(fabricp, portp->PortGUID); + + esmp->smp = smp; + // if we have properly resolved the SM, we update SMData + // if this resolves to a SM which already have a SMData->esmp, we do + // report that during verification and leave esmp pointing to SM + // but SM will not point to the duplicate esmp + // during verify we will check for each SM that + // esmp->smp->esmp==esmp + // those which do not (or have NULL smp) are dup, missing, etc + if (smp && ! smp->esmp) { + smp->esmp = esmp; + } +} + +static void ExpectedSMXmlParserEnd(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + ExpectedSM *esmp = (ExpectedSM*)object; + FabricData_t *fabricp = IXmlParserGetContext(state); + + if (! valid) + goto invalid; + ResolveSM(fabricp, esmp); + QListInsertTail(&fabricp->ExpectedSMs, &esmp->ExpectedSMsEntry); + return; + +invalid: + ExpectedSMFree(fabricp, esmp); + return; +} + +static IXML_FIELD SMsFields[] = { + { tag:"SM", format:'k', format_func: ExpectedSMXmlOutput, subfields:ExpectedSMFields, start_func:ExpectedSMXmlParserStart, end_func:ExpectedSMXmlParserEnd }, // structure + { NULL } +}; + +/****************************************************************************/ +/* Overall Nodes lists Input/Output functions */ + +static void Xml2PrintAllType(IXmlOutputState_t *state, const char *listtag, const char *itemtag, QUICK_LIST *listp) +{ + LIST_ITEM *p; + + IXmlOutputStartAttrTag(state, listtag, NULL, NULL); + for (p=QListHead(listp); p != NULL; p = QListNext(listp, p)) { + ExpectedNode *enodep = (ExpectedNode *)QListObj(p); +#if 0 + if (! CompareNodePoint(nodep, info->focus)) + continue; +#endif + ExpectedNodeXmlOutput(state, itemtag, enodep); + } + IXmlOutputEndTag(state, listtag); +} + +static void Xml2PrintAllSMs(IXmlOutputState_t *state, const char *tag, void *data) +{ + LIST_ITEM *p; + FabricData_t *fabricp = (FabricData_t *)IXmlOutputGetContext(state); + + IXmlOutputStartAttrTag(state, tag, NULL, NULL); + for (p=QListHead(&fabricp->ExpectedSMs); p != NULL; p = QListNext(&fabricp->ExpectedSMs, p)) { + ExpectedSM *esmp = (ExpectedSM *)QListObj(p); +#if 0 + if (! CompareSmPoint(smp, info->focus)) + continue; +#endif + ExpectedSMXmlOutput(state, "SM", esmp); + } + IXmlOutputEndTag(state, tag); +} + +static void Xml2PrintAllNodes(IXmlOutputState_t *state, const char *tag, void *data) +{ + FabricData_t *fabricp = (FabricData_t *)IXmlOutputGetContext(state); + + IXmlOutputStartAttrTag(state, tag, NULL, NULL); + + Xml2PrintAllType(state, "FIs", "Node", &fabricp->ExpectedFIs); + Xml2PrintAllType(state, "Switches", "Node", &fabricp->ExpectedSWs); + Xml2PrintAllSMs(state, "SMs", &fabricp->ExpectedSMs); + + IXmlOutputEndTag(state, tag); +} + +static IXML_FIELD NodesFields[] = { + { tag:"FIs", format:'k', subfields:FIsFields, }, // list + { tag:"Switches", format:'k', subfields:SWsFields, }, // list + { tag:"SMs", format:'k', subfields:SMsFields, }, // list + { NULL } +}; + +static void *NodesXmlParserStart(IXmlParserState_t *state, void *parent, const char **attr) +{ + FabricData_t *fabricp = IXmlParserGetContext(state); + + if (fabricp->flags & FF_EXPECTED_NODES) + IXmlParserPrintError(state, "Only one list can be supplied\n"); + return NULL; +} + +static void NodesXmlParserEnd(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + FabricData_t *fabricp = IXmlParserGetContext(state); + + if (! valid) + goto invalid; + fabricp->flags |= FF_EXPECTED_NODES; + return; + +invalid: + return; +} + +/****************************************************************************/ +/* Overall topology Input/Output functions */ + +/* only used for input parsing */ +static IXML_FIELD TopologyFields[] = { + // allow opareport -o brnodes -x -d 1 style input for Nodes and SMs + { tag:"LinkSummary", format:'k', subfields:LinksFields, start_func:LinkSummaryXmlParserStart, end_func:LinkSummaryXmlParserEnd }, // list + { tag:"ExternalLinkSummary", format:'k', subfields:LinksFields, start_func:ExternalLinkSummaryXmlParserStart, end_func:ExternalLinkSummaryXmlParserEnd }, // list + { tag:"Nodes", format:'k', subfields:NodesFields, start_func:NodesXmlParserStart, end_func:NodesXmlParserEnd }, // list +//TBD - IOCs? + { NULL } +}; + +static void *TopologyXmlParserStart(IXmlParserState_t *state, void *parent, const char **attr) +{ + // we generate unixtime attribute on output, but ignore it on input + return NULL; +} + +static void TopologyXmlParserEnd(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + FabricData_t *fabricp = IXmlParserGetContext(state); + + if (! valid) + goto invalid; + // only ExtLinks or Links is allowed, ParserStart for these tags checks + ASSERT(! ((fabricp->flags & (FF_EXPECTED_LINKS|FF_EXPECTED_EXTLINKS)) + == (FF_EXPECTED_LINKS|FF_EXPECTED_EXTLINKS))); + return; + +invalid: + // free parsed data + ExpectedLinkFreeAll(fabricp); + ExpectedNodesFreeAll(fabricp, &fabricp->ExpectedFIs); + ExpectedNodesFreeAll(fabricp, &fabricp->ExpectedSWs); + ExpectedSMsFreeAll(fabricp); +} + +static IXML_FIELD TopLevelFields[] = { + // "Topology" is the prefered input main tag + // however we also allow Report, this permits a -o links and/or -o brnodes + // report to be edited and used as input as the topology + { tag:"Topology", format:'k', subfields:TopologyFields, start_func:TopologyXmlParserStart, end_func:TopologyXmlParserEnd }, // structure + { tag:"Report", format:'k', subfields:TopologyFields, start_func:TopologyXmlParserStart, end_func:TopologyXmlParserEnd }, // structure + { NULL } +}; + +#if TBD +static void TopologyInfoXmlFormatAttr(IXmlOutputState_t *state, void *data) +{ + TopologyOutputInfo_t *info = (TopologyOutputInfo_t *)IXmlOutputGetContext(state); + char datestr[80] = ""; + int i; + + strftime(datestr, sizeof(datestr), "%c", localtime(&info->time));// %+ or %c or %x %X + IXmlOutputPrint(state, " date=\"%s\" unixtime=\"%ld\" options=\"", datestr, info->time); + for (i=1; iargc; i++) + IXmlOutputPrint(state, "%s%s", i>1?" ":"", info->argv[i]); + IXmlOutputPrint(state, "\""); +} +#endif + +static void Xml2PrintAll(IXmlOutputState_t *state, const char *tag, void *data) +{ +#if 0 + TopologyOutputInfo_t *info = (TopologyOutputInfo_t *)IXmlOutputGetContext(state); +#endif + + IXmlOutputStartAttrTag(state, tag, NULL, NULL /*TopologyInfoXmlFormatAttr*/); + + Xml2PrintAllLinks(state, "LinkSummary", NULL); + Xml2PrintAllNodes(state, "Nodes", NULL); + + + IXmlOutputEndTag(state, tag); +} + +void Xml2PrintTopology(FILE *file, FabricData_t *fabricp) +{ + IXmlOutputState_t state; + + /* using SERIALIZE with no indent makes output less pretty but 1/2 the size */ + //if (FSUCCESS != IXmlOutputInit(&state, file, 0, IXML_OUTPUT_FLAG_SERIALIZE, info)) + if (FSUCCESS != IXmlOutputInit(&state, file, 4, IXML_OUTPUT_FLAG_NONE, fabricp)) + goto fail; + + Xml2PrintAll(&state, "Topology", NULL); + + IXmlOutputDestroy(&state); + + return; + +fail: + return; +} + +static FSTATUS TopologyValidateLinkPort(FabricData_t *fabricp, ExpectedLink *elinkp, PortSelector *portselp, TopoVal_t validation) +{ + ExpectedNode *enodep; + + if(!portselp){ + // only 1 side will be found, we'll show that side + fprintf(stderr, "Topology file line %"PRIu64": incomplete link specification, only 1 port provided: %s\n", elinkp->lineno, + elinkp->portselp1? + FormatPortSelector(elinkp->portselp1) + : elinkp->portselp2? + FormatPortSelector(elinkp->portselp2) + :"" + ); + return FINVALID_PARAMETER; + } + + if(portselp->NodeGUID) { + enodep = FindExpectedNodeByNodeGuid(fabricp, portselp->NodeGUID); + if(!enodep){ + fprintf(stderr, "Topology file line %"PRIu64": No node found with matching NodeGUID for link port: %s\n", elinkp->lineno, FormatPortSelector(portselp)); + return FNOT_FOUND; + } + if(portselp->NodeDesc){ + if(enodep->NodeDesc && strcmp(portselp->NodeDesc, enodep->NodeDesc) != 0) { + fprintf(stderr, "Topology file line %"PRIu64": Node GUIDs match, but inconsistent NodeDesc for Node: %.*s link port: %s\n", + elinkp->lineno, NODE_DESCRIPTION_ARRAY_SIZE, enodep->NodeDesc, FormatPortSelector(portselp)); + return FERROR; + } + } + } else if (portselp->NodeDesc) { + enodep = FindExpectedNodeByNodeDesc(fabricp,portselp->NodeDesc, portselp->NodeType); + if(!enodep){ + fprintf(stderr, "Topology file line %"PRIu64": No node found with matching NodeDesc for link port: %s\n", + elinkp->lineno, FormatPortSelector(portselp)); + return FNOT_FOUND; + } + } else { + fprintf(stderr, "Topology file line %"PRIu64": Link port specification with no NodeGUID or NodeDesc: %s; other side of link: %s\n", + elinkp->lineno, FormatPortSelector(portselp), + elinkp->portselp1 == portselp? + FormatPortSelector(elinkp->portselp2) + : FormatPortSelector(elinkp->portselp1)); + return FINVALID_PARAMETER; + } + + if ((enodep->NodeType && portselp->NodeType) + && enodep->NodeType != portselp->NodeType) { + fprintf(stderr, "Topology file line %"PRIu64": Nodes match but inconsistent NodeType for Node: %s link port: %s\n", + elinkp->lineno, StlNodeTypeToText(portselp->NodeType), + FormatPortSelector(portselp)); + return FERROR; + } + + if (! portselp->gotPortNum) { + fprintf(stderr, "Topology file line %"PRIu64": Link port specification with no PortNum: %s\n", elinkp->lineno, FormatPortSelector(portselp)); + return FINVALID_PARAMETER; + } else { + // store a pointer to the ExpectedLink in the ExpectedNode to allow + // for constant time lookup later + ExpectedPort *eportp = ExpectedNodeGetPort(enodep, portselp->PortNum); + if (TOPOVAL_STRICT == validation) { + if(NULL == eportp ) { + fprintf(stderr, "Topology file line %"PRIu64": Referenced port %u not specified in Node (line %"PRIu64"): %s\n", + elinkp->lineno, portselp->PortNum, + enodep->lineno, FormatExpectedNode(enodep)); + return FERROR; + } + } else if (NULL == eportp) { + // did not have port in enode section, we'll add it here + eportp = (ExpectedPort*)MemoryAllocate2AndClear(sizeof(ExpectedPort), IBA_MEM_FLAG_PREMPTABLE, MYTAG); + if (NULL == eportp) + goto unable2add; + eportp->PortNum = portselp->PortNum; + if (FSUCCESS != ExpectedNodeAddPort(enodep, eportp)) { + MemoryDeallocate(eportp); + // Can't be FDUPLICATE, so must be out of memory + goto unable2add; + } + } + // found a matching port on enodep + if(enodep->ports[portselp->PortNum]->elinkp != NULL) { + fprintf(stderr, "Topology file line %"PRIu64": More than one link to port %u on Node: %s\n", elinkp->lineno, portselp->PortNum, FormatExpectedNode(enodep)); + return FDUPLICATE; + } + enodep->ports[portselp->PortNum]->elinkp = elinkp; + } + portselp->enodep = enodep; + + return FSUCCESS; + +unable2add: + fprintf(stderr, "Topology file line %"PRIu64": Unable to add port %u on Node: %s\n", elinkp->lineno, portselp->PortNum, FormatExpectedNode(enodep)); + return FINSUFFICIENT_MEMORY; +} + + +//Do graph search over ExpectedNodes for a given root note, +//and mark all found as "connected" to the graph +void TopologyValidateLinkHelper(ExpectedNode *enodep) +{ + int i; + if(!enodep) + return; + if(enodep->connected) + return; //already processsed this node + enodep->connected = 1; + + //recurse on all nodes with links from this node + for(i=0; iportsSize; i++){ + if(enodep->ports[i] && enodep->ports[i]->elinkp){ + TopologyValidateLinkHelper(enodep->ports[i]->elinkp->portselp1->enodep); + TopologyValidateLinkHelper(enodep->ports[i]->elinkp->portselp2->enodep); + } + } + + return; +} + + +FSTATUS TopologyValidateNoLinksDisjoint(FabricData_t *fabricp) +{ + FSTATUS status = FSUCCESS; + LIST_ITEM *it; + //Algorithm: + //1) Pick any node N in ExpectedSWs + //2) Do a graph search from N + // 2a)For each unique node found mark it as found + //3) Iterate over all nodes in ExpectedSWs and ExpectedSWs + // and if any were not found they are disjoint + + + ExpectedNode* erootnodep = PARENT_STRUCT(QListHead(&fabricp->ExpectedSWs), ExpectedNode, ExpectedNodesEntry); + + //Handle b2b case + if(!erootnodep){ + erootnodep = PARENT_STRUCT(QListHead(&fabricp->ExpectedFIs), ExpectedNode, ExpectedNodesEntry); + if(!erootnodep) + return FSUCCESS; + } + + // if we happen to pick a erootnodep which is disconnected from rest of + // fabric, we will report everything else as disjoint from it + TopologyValidateLinkHelper(erootnodep); + + for(it = QListHead(&fabricp->ExpectedSWs); it != NULL; it = QListNext(&fabricp->ExpectedSWs, it)) { + ExpectedNode *enodep = PARENT_STRUCT(it, ExpectedNode, ExpectedNodesEntry); + if(!enodep->connected){ + fprintf(stderr, "Switch: %s is disjoint from Node: %s\n", + FormatExpectedNode(enodep), FormatExpectedNode(erootnodep)); + status = FERROR; + } + } + + for(it = QListHead(&fabricp->ExpectedFIs); it != NULL; it = QListNext(&fabricp->ExpectedFIs, it)) { + ExpectedNode *enodep = PARENT_STRUCT(it, ExpectedNode, ExpectedNodesEntry); + if(!enodep->connected){ + fprintf(stderr, "FI: %s is disjoint from Node: %s\n", + FormatExpectedNode(enodep), FormatExpectedNode(erootnodep)); + status = FERROR; + } + } + + return status; +} + +static FSTATUS TopologyValidate(FabricData_t *fabricp, int quiet, TopoVal_t validation) +{ + FSTATUS status = FSUCCESS; + LIST_ITEM *it; + int ix=0; + int resolved = 0; + int bad_input = 0; + int input_checked = 0; + + //make sure input file contains at least one link + if(QListHead(&fabricp->ExpectedLinks) == NULL) { + fprintf(stderr, "Topology file does not have link definitions\n"); + return FERROR; + } + + // Validate that all SW0's have matching Node and Port GUIDs. + // This is meant to catch hand-edited topologies with errorneous switch + // GUIDs as SW0 is not checked by pre-defined topology. + for(it = QListHead(&fabricp->ExpectedSWs); it != NULL; it = QListNext(&fabricp->ExpectedSWs, it)) { + ExpectedNode *enodep = PARENT_STRUCT(it, ExpectedNode, ExpectedNodesEntry); + if (enodep->portsSize > 0 && enodep->ports[0] != NULL + && enodep->ports[0]->PortGuid && enodep->NodeGUID + && enodep->ports[0]->PortGuid != NodeGUIDtoPortGUID(enodep->NodeGUID, 0)) { + fprintf(stderr, "Topology file line %"PRIu64": mismatched NodeGUID and PortGUID for switch port 0: %s\n", enodep->lineno, FormatExpectedNode(enodep)); + if (TOPOVAL_SOMEWHAT_STRICT <= validation) + status = FERROR; + } + } + + //Validate each link has a matching node entry, and ensure + //node descriptions and port numbers match + //This also validates that there is not more than one link to a given + //(Node,Port) pair + //Each (ExpectedNode,port) pair that matches a link will have a pointer + //to that link stored in its ExpectedPort struct, and a pointer to the + //node stored in the ExpectedLink portselp + if (! quiet) ProgressPrint(TRUE, "Resolving Links against Nodes..."); + for(it = QListHead(&fabricp->ExpectedLinks); it != NULL; it = QListNext(&fabricp->ExpectedLinks, it)) { + ExpectedLink* elinkp = PARENT_STRUCT(it, ExpectedLink, ExpectedLinksEntry); + int ends = 0; + int bad_end = 0; + + if (! quiet && (ix++ % PROGRESS_FREQ) == 0) { + ProgressPrint(FALSE, "Resolved %6d of %6d Links...", + ix, QListCount(&fabricp->ExpectedLinks)); + } + if (! elinkp->portselp1 && ! elinkp->portselp2) { + fprintf(stderr, "Topology file line %"PRIu64": empty link specification\n", elinkp->lineno); + bad_input++; + continue; + } + switch (TopologyValidateLinkPort(fabricp, elinkp, elinkp->portselp1, validation)) { + case FSUCCESS: + ends++; + break; + case FINVALID_PARAMETER: + if (TOPOVAL_SOMEWHAT_STRICT <= validation) + status = FERROR; + bad_end++; + break; + default: + status = FERROR; + break; + } + switch (TopologyValidateLinkPort(fabricp, elinkp, elinkp->portselp2, validation)) { + case FSUCCESS: + ends++; + break; + case FINVALID_PARAMETER: + bad_end++; + if (TOPOVAL_SOMEWHAT_STRICT <= validation) + status = FERROR; + break; + default: + status = FERROR; + break; + } + if (bad_end) + bad_input++; + else + input_checked++; + if (ends >= 2) + resolved++; + } + if (! quiet) ProgressPrint(TRUE, "Done Resolving Links"); + if (! quiet || bad_input) + fprintf(stderr, "%u of %u Input Links Checked, %u Resolved, %u Bad Input Skipped\n", + input_checked, QListCount(&fabricp->ExpectedLinks), + resolved, bad_input); + + // If successful to this point, Validate all nodes are reachable + if(FSUCCESS == status && TOPOVAL_SOMEWHAT_STRICT <= validation) { + if(TopologyValidateNoLinksDisjoint(fabricp) != FSUCCESS) + status = FERROR; + } + + if (TOPOVAL_SOMEWHAT_STRICT <= validation) + return status; + else + return FSUCCESS; +} + +FSTATUS Xml2ParseTopology(const char *input_file, int quiet, FabricData_t *fabricp, +#ifdef __VXWORKS__ + XML_Memory_Handling_Suite* memsuite, +#endif + TopoVal_t validation) +{ + unsigned tags_found, fields_found; + const char *filename=input_file; + + if(fabricp == NULL || fabricp->AllNodes.state != CL_INITIALIZED) { + if (!quiet) ProgressPrint(TRUE, "Error: input FabricData_t was null or uninitialized!"); + return FERROR; + } + + if (strcmp(input_file, "-") == 0) { + if (! quiet) ProgressPrint(TRUE, "Parsing stdin..."); + filename = "stdin"; + if (FSUCCESS != IXmlParseFile(stdin, "stdin", IXML_PARSER_FLAG_NONE, TopLevelFields, NULL, fabricp, NULL, NULL, &tags_found, &fields_found +#ifdef __VXWORKS__ + , memsuite +#endif + )) { + return FERROR; + } + } else { + if (! quiet) ProgressPrint(TRUE, "Parsing %s...", Top_truncate_str(input_file)); + if (FSUCCESS != IXmlParseInputFile(input_file, IXML_PARSER_FLAG_NONE, TopLevelFields, NULL, fabricp, NULL, NULL, &tags_found, &fields_found +#ifdef __VXWORKS__ + , memsuite +#endif + )) { + return FERROR; + } + } + if (tags_found != 1 || fields_found != 1) { + fprintf(stderr, "Warning: potentially inaccurate input '%s': found %u recognized top level tags, expected 1\n", filename, tags_found); + } + if(TOPOVAL_NONE != validation) + return TopologyValidate(fabricp, quiet, validation); + else + return FSUCCESS; +} diff --git a/Topology/topology.h b/Topology/topology.h new file mode 100644 index 0000000..38d8449 --- /dev/null +++ b/Topology/topology.h @@ -0,0 +1,1645 @@ +/* BEGIN_ICS_COPYRIGHT7 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT7 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +#ifndef _TOPOLOGY_H +#define _TOPOLOGY_H + +#include + +#include +#if !defined(VXWORKS) || defined(BUILD_DMC) +#include +#endif +#include +#include +#include +#include +#include + + +#include +#include +#include +#include +#include + +#if !defined(_GNU_SOURCE) +#define _GNU_SOURCE +#endif + +#include + +#ifdef __cplusplus +extern "C" { +#endif + + +#define CL_TIME_DIVISOR 1000000 + +struct ExpectedLink_s; +struct ExpectedNode_s; +struct ExpectedSM_s; +struct NodeData_s; +struct SystemData_s; +struct omgt_port; + +// Selection indicies for SCVL* tables +typedef enum { Enum_SCVLt, Enum_SCVLnt, Enum_SCVLr } ScvlEnum_t; + +// selection of PortState for FindPortStatePoint, includes all of IB_PORT_STATE +// plus these additional special searches +#define PORT_STATE_SEARCH_NOTACTIVE (IB_PORT_STATE_MAX+1) // != active +#define PORT_STATE_SEARCH_INITARMED (IB_PORT_STATE_MAX+2) // init or armed + +typedef struct PortMaskSC2SCMap_s { + LIST_ITEM SC2SCMapListEntry; // QOSData.SC2SCMapList + STL_PORTMASK outports[STL_MAX_PORTMASK]; // egress ports for this map + STL_SCSCMAP *SC2SCMap; +} PortMaskSC2SCMap; + +#define SC2SCMAPLIST_MAX 1 +// QOS information for a Port in the fabric +typedef struct QOSData_s { + union { + STL_VLARB_TABLE VLArbTable[4]; // One table per type, low, high, preempt, preempt matrix + } u; + + QUICK_LIST SC2SCMapList[SC2SCMAPLIST_MAX]; // PortMaskSC2SCMap + STL_SLSCMAP *SL2SCMap; // only defined for HFI and SW port 0 + STL_SCSLMAP *SC2SLMap; // only defined for HFI and SW port 0 + STL_SCVLMAP SC2VLMaps[3]; // VL_t, _nt, and _r; indicies given by ScvlEnum_t +} QOSData; + + +// How many STL_CABLE_INFO structs to store per port +#define PORTDATA_CABLEINFO_SIZE 4 +#define IFACE_MACLIST_SIZE 512 + +// information about an IB Port in the fabric +// for switches a GUID and LID are only available for Port 0 of the switch +// for all other switch ports, LID is port 0 LID (LID for whole switch) +// and port GUID is NA and hence 0. +typedef struct PortData_s { + cl_map_item_t NodePortsEntry; // NodeData.Ports, key is PortNum + cl_map_item_t AllLidsEntry; // g_AllLids, key is LID (if GUID non-zero) + LIST_ITEM AllPortsEntry; // g_AllPorts + EUI64 PortGUID; // 0 for all but port 0 of a switch + struct PortData_s *neighbor; // adjacent port this is cabled to + struct NodeData_s *nodep; // parent node + uint8 PortNum; // port number within Node + uint8 from:1; // is this the from port in link record + // (avoids double reporting of links) + uint8 PmaGotClassPortInfo:1; // have issued a ClassPortInfo + uint8 spare:6; + uint32 rate; // Active rate for this port + STL_LID EndPortLID; // LID to get to device with this port + STL_PORT_INFO PortInfo; // do not use LocalPortNum,use PortNum above + STL_LINKDOWN_REASON LinkDownReasons[STL_NUM_LINKDOWN_REASONS]; + + + STL_LED_INFO LedInfo; //Led Info for this port + IB_PATH_RECORD *pathp; // Path Record to send to this port + STL_PORT_COUNTERS_DATA *pPortCounters; + struct ExpectedLink_s *elinkp; // if supplied in topology input + QOSData *pQOS; // optional QOS + STL_PKEY_ELEMENT *pPartitionTable; // optional Partition Table + + union { + struct { + uint32 downlinkBasePaths; + uint32 uplinkBasePaths; + uint32 downlinkAllPaths; + uint32 uplinkAllPaths; + } fatTreeRoutes; // for TabulateRoutes of fattree + struct { + uint32 recvBasePaths; + uint32 xmitBasePaths; + uint32 recvAllPaths; + uint32 xmitAllPaths; + } routes; // for TabulateRoutes of any topology + } analysisData; // per port holding space for transient analysis data + STL_BUFFER_CONTROL_TABLE *pBufCtrlTable; + // 128 table entries allocate when needed + STL_HFI_CONGESTION_CONTROL_TABLE_ENTRY *pCongestionControlTableEntries; + uint16_t CCTI_Limit; + + // CableInfo is organized in 128-byte pages but is stored in + // 64-byte half-pages + // We only store STL_CIB_STD_HIGH_PAGE_ADDR to STL_CIB_STD_END_ADDR with + // STL_CIB_STD_HIGH_PAGE_ADDR stored starting at pCableInfoData[0] + uint8_t *pCableInfoData; + void *context; // application specific field +} PortData; + +// additional information about cable for a link, from topology input +// we limit sizes to make output formatting easier +#define CABLE_LENGTH_STRLEN 10 +#define CABLE_LABEL_STRLEN 57 +#define CABLE_DETAILS_STRLEN 64 +typedef struct CableData_s { + char *length; // user specified length + char *label; // user label on cable + char *details; // user description of cable +} CableData; + +typedef struct ExpectedNode_s ExpectedNode; +#define PORT_DETAILS_STRLEN 64 +// port selector from topology input +typedef struct PortSelector_s { + EUI64 PortGUID; // 0 if not specified + EUI64 NodeGUID; // 0 if not specified + uint8 PortNum; // 0-255 are valid port numbers + uint8 gotPortNum; // 0 if PortNum not specified + uint8 NodeType; // 0 if not specified + char *NodeDesc; // NULL if not specified + char *details; // user description of port + ExpectedNode *enodep; // associated ExpectedNode, set by + // TopologyValidate if match is found +} PortSelector; + +#define LINK_DETAILS_STRLEN 64 +// additional information about a link, from topology input +typedef struct ExpectedLink_s { + LIST_ITEM ExpectedLinksEntry; // g_ExpectedLinks + PortSelector *portselp1; // input selector + PortSelector *portselp2; // input selector + PortData *portp1; // NULL if not found + PortData *portp2; // NULL if not found + // the 4 fields below could become bit fields to save space if necessary + // MTU=4 bits, rate=6 bits, internal=1 bit, matchLevel = 3 bits + uint8 expected_rate; // Expected Active rate for this link, IB_STATIC_RATE enum + uint8 expected_mtu; // Expected Active MTU for this link, an IB_MTU enum + uint8 internal; // Is link an internal link + uint8 matchLevel; // degree of match with portp1 and 2, higher is better + // used internally when matching ports to links to pick best + // matches + char *details; // user description of link + CableData CableData; // user supplied info about cable + uint64 lineno; // line number in XML of starting tag, for error messages +} ExpectedLink; + +/* + * Limited port information possibly produced originally from + * full PortData. + */ +typedef struct ExpectedPort_s { + uint8 PortNum; + STL_LID lid; + uint8 lmc; + EUI64 PortGuid; + ExpectedLink *elinkp; +} ExpectedPort; + +#define NODE_DETAILS_STRLEN 64 +// additional information about a node, from topology input +struct ExpectedNode_s { + LIST_ITEM ExpectedNodesEntry; // g_ExpectedFIs, g_ExpectedSWs + cl_map_item_t ExpectedNodeGuidMapEntry; // key is NodeGuid + struct NodeData_s *nodep; // NULL if not found + EUI64 NodeGUID; // 0 if not specified + EUI64 SystemImageGUID; // 0 if not specified + uint8 NodeType; // 0 if not specified + char *NodeDesc; // NULL if not specified + char *details; // user description of node + uint8 portsSize; + ExpectedPort **ports; + uint8 connected; //internally used to validate node is reachable, set by TopologyValidate + void *context; // application specific field + uint64 lineno; // line number in XML of starting tag, for error messages +}; + +#define SM_DETAILS_STRLEN 64 +// additional information about a SM, from topology input +typedef struct ExpectedSM_s { + LIST_ITEM ExpectedSMsEntry; // g_ExpectedSMs + struct SMData_s *smp; // NULL if not found + EUI64 PortGUID; // 0 if not specified + EUI64 NodeGUID; // 0 if not specified + uint8 PortNum; // 0-255 are valid port numbers + uint8 gotPortNum; // 0 if PortNum not specified + uint8 NodeType; // 0 if not specified + char *NodeDesc; // NULL if not specified + char *details; // user description of SM +} ExpectedSM; + +#if !defined(VXWORKS) || defined(BUILD_DMC) +struct IouData_s; + +typedef struct IocData_s { + LIST_ITEM IouIocsEntry; // IouData.Iocs, sorted by IOC slot # + cl_map_item_t AllIOCsEntry; // g_AllIOCs, key is IOC GUID + IOC_PROFILE IocProfile; + uint8 IocSlot; + struct IouData_s *ioup; // parent IOU + IOC_SERVICE *Services; // IO Services indexed by service num + void *context; // application specific field +} IocData; + +typedef struct IouData_s { + LIST_ITEM AllIOUsEntry; // g_AllIOUs + struct NodeData_s *nodep; // parent node + IOUnitInfo IouInfo; + QUICK_LIST Iocs; // Iocs, IocData sorted by IOC slot # + void *context; // application specific field +} IouData; +#endif + + + +// detailed information specific to an IB Switch in the fabric +typedef struct SwitchData_s { + /** + Lower upper-bound on number of entries allocated. + + Should be set to LinearFDBTop + 1. Should be set to 0 when LinearFDBTop is invalid. + + Prefer LinearFDBTop & LinearFDBCap from NodeData when available. + */ + uint32 LinearFDBSize; + STL_LINEAR_FORWARDING_TABLE *LinearFDB; + + + /** + Lower upper-bound on number of entries allocated. + + Should be set to MulticastFDBTop + 1. Should be set to 0 when + MulticastFDBTop is invalid. Users are responsible for knowing where + the multicast address space starts. + + Prefer MulticastFDBTop & MulticastFDBCap from NodeData when available. + */ + uint32 MulticastFDBSize; + STL_PORTMASK *MulticastFDB[STL_NUM_MFT_POSITIONS_MASK]; + uint8 HasBeenVisited; //indicates 0: no; 1: yes when searching for MC routes + + /** + Lower upper-bound on number of entries allocated. + + Should be set to PortGroupTop + 1. Should be set to 0 when + PortGroupTop is invalid. + + Prefer PortGroupTop & PortGroupCap from NodeData when available. + */ + uint16 PortGroupSize; + STL_PORTMASK* PortGroupElements; + + uint32 PortGroupFDBSize; + STL_PORT_GROUP_FORWARDING_TABLE *PortGroupFDB; + +} SwitchData; + +/* + Information about a Node in the fabric. + The SA reports a NodeRecord per port, we coallese all nodes with + the same GUID into a single structure. + As such the Port specific fields in the NodeInfo (PortGUID + and LocalPortNumber) are zeroed and should not be used. + @c NodeInfo.(Base|Class)Version should have the same values as the data + that was used to create this record. +*/ +typedef struct NodeData_s { + cl_map_item_t AllNodesEntry; // g_AllNodes, key is NodeGuid + cl_map_item_t SystemNodesEntry; // SystemData.Nodes, key is NodeGuid + LIST_ITEM AllTypesEntry; // g_AllFIs, g_AllSWs + struct SystemData_s *systemp; // parent system + STL_NODE_INFO NodeInfo; // port specific fields are 0 + STL_NODE_DESCRIPTION NodeDesc; + cl_qmap_t Ports; // items are PortData, key is PortNum +#if !defined(VXWORKS) || defined(BUILD_DMC) + IouData *ioup; // optional IOU +#endif + STL_SWITCHINFO_RECORD *pSwitchInfo; // optional SwitchInfo + // also holds LID for accessing switch + // for devices without vendor specific + // capabilities, extra fields and capability + // mask is zeroed + SwitchData *switchp; // optional Switch specific data + struct ExpectedNode_s *enodep; // if supplied in topology input + void *context; // application specific field + uint8 PmaAvoid:1; // node PMA has instability + uint8 PmaAvoidClassPortInfo:1; // node has instability in ClassPortInfo + uint8 PmaValidateRedirectQP:1; // validate QP in response + uint8 analysis:5; // for TabulateRoutes, tier in fabric + + STL_CONGESTION_INFO CongestionInfo; + /* CCA CongestionSetting */ + union { + STL_SWITCH_CONGESTION_SETTING Switch; + STL_HFI_CONGESTION_SETTING Hfi; + } CongestionSetting; + union { + STL_SWITCH_CONGESTION_LOG Switch; + STL_HFI_CONGESTION_LOG Hfi; + } CongestionLog; + + uint8_t coreSwitch; // (fabric_sim) fat tree non-edge switch + uint8_t visited; // (opasnapconfig) has this node been visited + uint8_t valid; // (opasnapconfig) whether node exists in proper location from snapshot + uint8_t path[64]; // (opasnapconfig) path we traversed to get to this node +} NodeData; + + +typedef uint8 MCROUTESTATUS; +#define MAXMCROUTESTATUS 5 // 5 different status for MC routes +#define MC_NO_TRACE 0x00 +#define MC_NOT_FOUND 0x01 +#define MC_UNAVAILABLE 0x02 +#define MC_LOOP 0x03 +#define MC_NOGROUP 0x04 + +typedef struct McGroupData_s { // entry to AllMcGroups + // holds info of McGroup Members as well as switches that + // belong to the group + LIST_ITEM AllMcGMembersEntry; + QUICK_LIST AllMcGroupMembers; //datatype: McMemberData + int NumOfMembers; + STL_LID MLID; + IB_GID MGID; + IB_MCMEMBER_RECORD GroupInfo; //Fields corresponding to individual members should not be used + QUICK_LIST EdgeSwitchesInGroup;//datatype:McHFISwitchData +} McGroupData; + +typedef struct McEdgeSwitchData_s { // entry in McGroupData + LIST_ITEM McEdgeSwitchEntry; + uint8 EntryPort; + PortData *pPort; + uint64 NodeGUID; +} McEdgeSwitchData; + +typedef struct McMemberData_s { // entry in McGroupData + LIST_ITEM McMembersEntry; + + // Do not use 16-bit MemberInfo.MLID; use 32-bit MLID of containing McGroupData + IB_MCMEMBER_RECORD MemberInfo; + + PortData *pPort; +} McMemberData; + +typedef struct McNodeLoopInc_s { + LIST_ITEM McNodeEntry; + PortData *pPort; + uint16 entryPort; + uint16 exitPort; +} McNodeLoopInc; + +typedef struct McLoopInc_s { + QUICK_LIST AllMcNodeLoopIncR; //datatype: McNodeLoopInc + LIST_ITEM LoopIncEntry; + MCROUTESTATUS status; + STL_LID mlid; +} McLoopInc; + +typedef struct McRouteStatus_s { + QUICK_LIST AllMcRouteStatus; + MCROUTESTATUS status; +} McRouteStatus; + +typedef struct clConnPathData_s { + IB_PATH_RECORD path; +} clConnPathData_t; + +typedef struct clConnData_s { + LIST_ITEM AllConnectionEntry; + uint64 FromDeviceGUID; // GUID of the HFI, TFI, switch + uint8 FromPortNum; + uint64 ToDeviceGUID; // GUID of the HFI, TFI, switch + uint8 ToPortNum; + uint32 Rate; // active rate for this port + STL_VL VL; + clConnPathData_t PathInfo; +} clConnData_t; + +#define CREDIT_LOOP_DEVICE_MAX_CONNECTIONS 66 +#define DIJKSTRA_INFINITY 0xffff + +typedef struct clDeviceData_s { + cl_map_item_t AllDevicesEntry; // key is NodeGuid + LIST_ITEM AllDeviceTypesEntry; + STL_LID Lid; + NodeData *nodep; + clConnData_t *Connections[CREDIT_LOOP_DEVICE_MAX_CONNECTIONS][STL_MAX_SCS]; // 36 port switch + 1 for port zero + cl_qmap_t map_dlid_to_route; +} clDeviceData_t; + +typedef struct clRouteData_s { + cl_map_item_t AllRoutesEntry; // key is DLID + PortData *portp; +} clRouteData_t; + +typedef struct clVertixData_s { + cl_map_item_t AllVerticesEntry; // key is connection memory address + clConnData_t *Connection; + uint32 Id; + uint32 RefCount; + uint32 OutboundCount; + uint32 OutboundInuseCount; + uint32 OutboundLength; + int *Outbound; + uint32 InboundCount; + uint32 InboundInuseCount; + uint32 InboundLength; + int *Inbound; +} clVertixData_t; + +typedef struct clArcData_s { + cl_map_item_t AllArcsEntry; // key is combination of source & sink ids + cl_map_item_t AllArcIdsEntry; // key is arc list id + uint32 Id; + uint32 Source; + uint32 Sink; + union { + uint64 AsReg64; + + struct { + uint32 Source; + uint32 Sink; + } s; + } u1; +} clArcData_t; + +typedef struct clGraphData_s { + uint32 NumVertices; + uint32 NumActiveVertices; + uint32 VerticesLength; + clVertixData_t **Vertices; + uint32 NumArcs; + //QUICK_LIST Arcs; + cl_qmap_t Arcs; + cl_qmap_t map_arc_key_to_arc; + QUICK_LIST map_conn_to_vertex; + cl_qmap_t map_conn_to_vertex_conn; +} clGraphData_t; + +typedef struct clVertixDataDistance_s { + cl_map_item_t AllVerticesEntry; // key is Vertix Id + clVertixData_t *vertixp; +} clVertixDataDistance_t; + +typedef struct clDijkstraDistancesAndRoutes_s { + uint32 **distances; + uint32 **routes; + uint32 nRows; + uint32 nCols; +} clDijkstraDistancesAndRoutes_t; + +/** + * Get start of an entry in MulticastFDB. Should use bits MLID[13:0]. + * @c pos is the portmask position; each position is 64 bits (ports) wide. + */ +static inline +STL_PORTMASK *GetMulticastFDBEntry(NodeData *nodep, uint32 entry, uint8 pos) +{ + if (! nodep->switchp || !nodep->switchp->MulticastFDB[pos]) + return NULL; + + return (&nodep->switchp->MulticastFDB[pos][entry]); +} + +// information about an IB enabled system in the fabric +// Each system is a set of nodes with the same SystemImageGUID +// Some 3rd party devices report a SystemImageGUID of 0, in which case +// the node GUID (which should still be unique among systems with +// SystemImageGUIDs of 0) is used as the key for g_AllSystems +typedef struct SystemData_s { + cl_map_item_t AllSystemsEntry; // g_AllSystems, key is SystemImageGUID + EUI64 SystemImageGUID; + cl_qmap_t Nodes; // items are NodeData, key is NodeGuid + void *context; // application specific field +} SystemData; + +typedef struct SMData_s { + cl_map_item_t AllSMsEntry; // g_AllSMs, key is PortGUID in SMInfo + STL_SMINFO_RECORD SMInfoRecord; // also holds LID for accessing SM + struct PortData_s *portp; // port SM is running on + ExpectedSM *esmp; // if supplied in topology input + void *context; // application specific field +} SMData; + +typedef struct MasterSMData_s { + uint64 serviceID; // Service ID of QLogic master SM (else 0) + uint32 capabilityMask; // Capability mask of QLogic master SM + uint8 version; // SM Version +} MasterSMData_t; + +typedef struct { + LIST_ITEM AllVFsEntry; + STL_VFINFO_RECORD record; +} VFData_t; + +typedef enum { + FF_NONE =0, + FF_STATS =0x000000001, // PortCounters fetched + // flags for topology_input which was provided + FF_EXPECTED_NODES =0x000000002, // topology_input w/ + FF_EXPECTED_LINKS =0x000000004, // topology_input w/ + FF_EXPECTED_EXTLINKS=0x000000008, // topology_input w/ + FF_CABLEDATA =0x000000010, // topology_input w/ some + FF_LIDARRAY =0x000000020, // Keep AllLids as array instead of qmap + // allows faster FindLid, but takes + // approx 300K more memory + FF_PMADIRECT =0x000000080, // Force direct PMA access of port counters + FF_ROUTES =0x000000100, // Routing tables (linear/mcast) fetched + FF_QOSDATA =0x000000200, // QOS data fetched + FF_SMADIRECT =0x000000400, // Force direct SMA access + FF_BUFCTRLTABLE =0x000000800, // BufferControlData collected + FF_DOWNPORTINFO =0x000001000, // Get PortInfo for Down switch ports + FF_CABLELOWPAGE =0x000004000, //Get Lower memory of Cable Info +} FabricFlags_t; + +// Handling for LIDs up to 24 bits +#define TOPLM_BLOCK_BITS 10 +#define TOPLM_ENTRY_BITS 14 +#define TOPLM_BLOCKS (1 << TOPLM_BLOCK_BITS) /* There are 2^10 blocks in the map */ +#define TOPLM_ENTRIES (1 << TOPLM_ENTRY_BITS) /* Each block contains 2^14 pointers to PortData */ +#define TOPLM_BLOCK_NUM(lid) ((lid) >> TOPLM_ENTRY_BITS) +#define TOPLM_ENTRY_NUM(lid) ((lid) & (TOPLM_ENTRIES -1)) +#define TOPLM_LID_MAX ((1 << (TOPLM_BLOCK_BITS + TOPLM_ENTRY_BITS)) - 1) // Map can handle 2^24 lids + +typedef struct TopLidMap_s { + PortData **LidBlocks[TOPLM_BLOCKS]; +} TopLidMap_t; + +typedef struct FabricData_s { + time_t time; // when fabric data was obtained from a real fabric + FabricFlags_t flags; // what data is available in FabricData + + // data from live fabric or snapshot + cl_qmap_t AllNodes; // items are NodeData, key is node guid + union { + cl_qmap_t AllLids; // items are PortData, key is LID + TopLidMap_t LidMap; + } u; + uint32 lidCount; + cl_qmap_t AllSystems; // items are SystemData, key is system image guid + QUICK_LIST AllPorts; // sorted by NodeGUID+PortNum + QUICK_LIST AllFIs; // sorted by NodeGUID + QUICK_LIST AllSWs; // sorted by NodeGUID + QUICK_LIST AllVFs; // list of VFData_t +#if !defined(VXWORKS) || defined(BUILD_DMC) + QUICK_LIST AllIOUs; // sorted by NodeGUID + // AllIOCs uses IOCGUID as the primary key and NodeGUID as secodary key + cl_qmap_t AllIOCs; // items are IocData +#endif + cl_qmap_t AllSMs; // items are SMData, key is PortGuid + + // Multicast related structures + QUICK_LIST AllMcGroups; // items are MCGroups, Key is MGID + McRouteStatus AllMcLoopIncRoutes[MAXMCROUTESTATUS]; // items are list of loop and incomplete MC routes. + uint32 NumOfMcGroups; + + MasterSMData_t MasterSMData; // Master SM data + uint32 LinkCount; // number of links in fabric + uint32 ExtLinkCount; // number of external links in fabric + uint32 FILinkCount; // number of FI links in fabric + uint32 ISLinkCount; // number of inter-switch links in fabric + uint32 ExtISLinkCount; // number of external inter-switch links in fabric + + // additional information for credit loop + uint32 ConnectionCount; + uint32 RouteCount; + QUICK_LIST FIs; + QUICK_LIST Switches; + cl_qmap_t map_guid_to_ib_device; // items are devices, ky is node guid + clGraphData_t Graph; + + // additional information from topology input file + QUICK_LIST ExpectedLinks; // in order read from topology input file + QUICK_LIST ExpectedFIs; // in order read from topology input file + QUICK_LIST ExpectedSWs; // in order read from topology input file + QUICK_LIST ExpectedSMs; // in order read from topology input file + //topology input data optimized for search + cl_qmap_t ExpectedNodeGuidMap; //all expected FIs/SWs mapped by NodeGuid + + void *context; // application specific field + int ms_timeout; +} FabricData_t; + +// these callbacks are called when an object with a non-null application +// specific context field is freed. They should free the object pointed to by +// the context field and remove any other application references to the object +// being freed +typedef void (PortDataFreeCallback)(FabricData_t *fabricp, PortData *portp); +#if !defined(VXWORKS) || defined(BUILD_DMC) +typedef void (IocDataFreeCallback)(FabricData_t *fabricp, IocData *iocp); +typedef void (IouDataFreeCallback)(FabricData_t *fabricp, IouData *ioup); +#endif +typedef void (NodeDataFreeCallback)(FabricData_t *fabricp, NodeData *nodep); +typedef void (SystemDataFreeCallback)(FabricData_t *fabricp, SystemData *systemp); +typedef void (SMDataFreeCallback)(FabricData_t *fabricp, SMData *smp); +typedef void (FabricDataFreeCallback)(FabricData_t *fabricp); + +typedef struct Top_FreeCallbacks_s { + PortDataFreeCallback *pPortDataFreeCallback; +#if !defined(VXWORKS) || defined(BUILD_DMC) + IocDataFreeCallback *pIocDataFreeCallback; + IouDataFreeCallback *pIouDataFreeCallback; +#endif + NodeDataFreeCallback *pNodeDataFreeCallback; + SystemDataFreeCallback *pSystemDataFreeCallback; + SMDataFreeCallback *pSMDataFreeCallback; + FabricDataFreeCallback *pFabricDataFreeCallback; +} Top_FreeCallbacks; + +// For functions which generate Points, is it node pair or just node +#define PAIR_FLAG_NONE 0x01 /* no pair exists */ +#define PAIR_FLAG_NODE 0x02 /* pair exists */ + +// Identifies side of pair +#define LSIDE_PAIR 0x01 /* left side of pair */ +#define RSIDE_PAIR 0x02 /* right side of pair */ + +typedef struct NodePairList_s { + DLIST nodePairList1; //members of left side of pair + DLIST nodePairList2; //members of right side of pair +} NodePairList_t; + +/* struct Point_s identifies a particular point in the fabric and + * topology.xml. + * Used for trace route and other "focused" reports + * Presently coded in C, but a good candidate for a C++ abstract class + * with a subclass for each point type + */ +typedef enum { + POINT_TYPE_NONE, + POINT_TYPE_PORT, + POINT_TYPE_PORT_LIST, + POINT_TYPE_NODE, + POINT_TYPE_NODE_LIST, +#if !defined(VXWORKS) || defined(BUILD_DMC) + POINT_TYPE_IOC, + POINT_TYPE_IOC_LIST, +#endif + POINT_TYPE_SYSTEM, + POINT_TYPE_NODE_PAIR_LIST, +} PointType; + +typedef enum { + POINT_ENODE_TYPE_NONE, + POINT_ENODE_TYPE_NODE, + POINT_ENODE_TYPE_NODE_LIST, +} PointEnodeType; + +typedef enum { + POINT_ESM_TYPE_NONE, + POINT_ESM_TYPE_SM, + POINT_ESM_TYPE_SM_LIST, +} PointEsmType; + +typedef enum { + POINT_ELINK_TYPE_NONE, + POINT_ELINK_TYPE_LINK, + POINT_ELINK_TYPE_LINK_LIST, +} PointElinkType; + + +typedef struct Point_s { + + /* object(s) matched in the fabric */ + PointType Type; /* if POINT_TYPE_NONE, u undefined */ + boolean haveSW; /* indicates the point has SW*/ + boolean haveFI; /* indicates the point has FI*/ + union { + PortData *portp; + NodeData *nodep; +#if !defined(VXWORKS) || defined(BUILD_DMC) + IocData *iocp; +#endif + SystemData *systemp; + DLIST nodeList; + DLIST portList; + DLIST iocList; + NodePairList_t nodePairList; + } u; + + /* ExpectedNode(s) matched in topology file */ + PointEnodeType EnodeType; /* if POINT_ENODE_TYPE_NONE, u2 undefined */ + union { + ExpectedNode *enodep; + DLIST enodeList; + } u2; + + /* ExpectedSM(s) matched in topology file */ + PointEsmType EsmType; /* if POINT_ESM_TYPE_NONE, u3 undefined */ + union { + ExpectedSM *esmp; + DLIST esmList; + } u3; + + /* ExpectedLink(s) matched in topology file */ + PointElinkType ElinkType; /* if POINT_ELINK_TYPE_NONE, u4 undefined */ + union { + ExpectedLink *elinkp; + DLIST elinkList; + } u4; +} Point; + +#if !defined(VXWORKS) || defined(BUILD_DMC) +/* IOC types we can focus on */ +typedef enum { + IOC_TYPE_SRP, + IOC_TYPE_OTHER +} IocType; +#endif + +// used for output of snapshot +typedef struct { + FabricData_t *fabricp; // fabric to dump to snapshot file + int argc; // args to program ran + char **argv; // args to program ran + // Point *focus; +} SnapshotOutputInfo_t; + +// used for output of ValidateAllCreditLoopRoutes +typedef struct ValidateCreditLoopRoutesContext_s { + uint8 format; + int indent; + int detail; + int quiet; +} ValidateCreditLoopRoutesContext_t; + +typedef enum { + QUAL_EQ, + QUAL_GE, + QUAL_LE +} LinkQualityCompare; + +// simple way to convert time_t to a localtime date string in dest +// (from Topology/getdate.c) +extern void Top_formattime(char *dest, size_t max, time_t t); + +// FabricData_t handling (Topology/fabricdata.c) +extern FSTATUS InitFabricData( FabricData_t *pFabric, FabricFlags_t flags); +extern PortSelector* GetPortSelector(PortData *portp); +// Determine if portp and its neighbor are an internal link within a single +// system. Note that some 3rd party products report SystemImageGuid of 0 in +// which case we can only consider links between the same node as internal links +extern boolean isInternalLink(PortData *portp); +// Determine if portp and its neighbor are an Inter-switch Link +extern boolean isISLink(PortData *portp); +// Determine if portp or its neighbor is an FI +extern boolean isFILink(PortData *portp); +// Determine if elinkp is an external link within a single system. +// To make sure verification is thorough, this will return true when +// either the expected or resolved link(s) are external or when the +// expected link is not specific as to whether it is internal or external. +extern boolean isExternalExpectedLink(ExpectedLink *elinkp); +// Determine if elinkp is an inter-switch link +// To make sure verification is thorough, this will return true when +// either the expected or resolved link(s) are SW-SW +extern boolean isISExpectedLink(ExpectedLink *elinkp); +// Determine if elinkp is an FI link +// To make sure verification is thorough, this will return true when +// either the expected or resolved link(s) include an FI +extern boolean isFIExpectedLink(ExpectedLink *elinkp); +extern void PortDataFreePartitionTable(FabricData_t *fabricp, PortData *portp); +extern FSTATUS PortDataAllocatePartitionTable(FabricData_t *fabricp, PortData *portp); +// capacity of Partition Table for the given port +extern uint16 PortPartitionTableSize(PortData *portp); +// Lookup PKey +// ignores the Full/Limited bit, only checks low 15 bits for a match +// returns index of pkey in overall table or -1 if not found +// if the Partition Table for the port is not available, returns -1 +extern int FindPKey(PortData *portp, uint16 pkey); +// Determine if the given port is a member of the given vFabric +// We don't really have all the right data here, especially if the FM has +// combined multiple vFabrics into the same SL and PKey +// but for most cases, we can safely conclude that if the port has the SL and +// PKey configured it is a member of the vFabric. +// This function will return FALSE if QoS data or SL2SCMap is not available +// or if the port is not Armed/Active. +// Given the current FM implementation (and the dependency on SL2SCMap), this +// routine will return FALSE if invoked for non-endpoints +extern boolean isVFMember(PortData *portp, VFData_t *pVFData); +// count the number of armed/active links in the node +extern uint32 CountInitializedPorts(FabricData_t *fabricp, NodeData *nodep); +extern FSTATUS NodeDataAllocateSwitchData(FabricData_t *fabricp, NodeData *nodep, + uint32 LinearFDBSize, uint32 MulticastFDBSize); +extern FSTATUS NodeDataAllocateFDB(FabricData_t *fabricp, NodeData *nodep, + uint32 LinearFDBSize); +extern FSTATUS SwitchDataAllocateQOS(SwitchData *sw); + +/** + Adjust amount of memory allocated for Linear and Multicast FDB tables. + + Copies existing values into new memory, adjusts FDB Top values, and frees existing memory. When resizing MulticastFDB, the new entry size (entries per LID) must be the same as the old size. + + If the multicast FDB table is to be resized and there is already a multicast FDB table and the existing MulticastFDBTop is less than LID_MCAST_START then no values will be copied from the old table to the new table, though the table will still be resized. + In this case, the value of @c nodep->switchp->MulticastFDBSize will be LID_MCAST_START + @c newMfdbSize rather than MulticastFDBTop + 1. + + @param newLfdbSize If 0, don't change. Otherwise, realloc to min(newLfdbSize, LinearFDBCap). + @param newMfdbSize If 0, don't change. Otherwise, realloc to min(newMfdbSize, MulticastFDBCap). + + @return FSUCCESS on success, non-FSUCCESS on failure. Existing memory is not destroyed until after new tables are successfully allocated and copied. +*/ +FSTATUS NodeDataSwitchResizeFDB(NodeData * nodep, uint32 newLfdbSize, uint32 newMfdbSize); +FSTATUS NodeDataSwitchResizeLinearFDB(NodeData * nodep, uint32 newLfdbSize); +FSTATUS NodeDataSwitchResizeMcastFDB(NodeData * nodep, uint32 newMfdbSize); + +extern FSTATUS PortDataAllocateAllQOSData(FabricData_t *fabricp); +extern FSTATUS PortDataAllocateAllBufCtrlTable(FabricData_t *fabricp); +extern FSTATUS PortDataAllocateAllPartitionTable(FabricData_t *fabricp); +extern FSTATUS PortDataAllocateAllCableInfo(FabricData_t *fabricp); +extern FSTATUS PortDataAllocateAllCongestionControlTableEntries(FabricData_t *fabricp); +extern FSTATUS PortDataAllocateAllGuidTable(FabricData_t *fabricp); + + +/// @param fabricp optional, can be NULL +extern void PortDataFreeQOSData(FabricData_t *fabricp, PortData *portp); +/// @param fabricp optional, can be NULL +extern FSTATUS PortDataAllocateQOSData(FabricData_t *fabricp, PortData *portp); + +/// @param fabricp optional, can be NULL +extern void PortDataFreeBufCtrlTable(FabricData_t *fabricp, PortData *portp); +/// @param fabricp optional, can be NULL +extern FSTATUS PortDataAllocateBufCtrlTable(FabricData_t *fabricp, PortData *portp); + +/// @param fabricp optional, can be NULL +extern void PortDataFreeCableInfoData(FabricData_t *fabricp, PortData *portp); +/// @param fabricp optional, can be NULL +extern FSTATUS PortDataAllocateCableInfoData(FabricData_t *fabricp, PortData *portp); + +/// @param fabricp optional, can be NULL +extern void PortDataFreeCongestionControlTableEntries(FabricData_t *fabricp, PortData *portp); +/// @param fabricp optional, can be NULL +extern FSTATUS PortDataAllocateCongestionControlTableEntries(FabricData_t *fabricp, PortData *portp); + + +// these routines can be used to manually build FabricData. Use as follows: +// for each node +// FabricDataAddNode (can be any state, including down) +// if switch node +// NodeDataSetSwitchInfo +// for each port of Node +// NodeDataAddPort +// BuildFabricDataLists +// for each physical link +// FabricDataAddLink or FabricDataAllLinkRecord +// (FabricDataAddLink may be called before BuildFabricDataLists if desired) +// if desired, after building the basic topology, can build empty SMA tables: +// NodeDataAllocateAllSwitchData +// PortDataAllocateAllQOSData +// PortDataAllocateAllBufCtrlTable +// PortDataAllocateAllPartitionTable +// PortDataAllocateAllGuidTable +// when process Set(PortInfo) +// validate PortInfo given +// fill in empty/noop/readonly fields with previous PortInfo +// PortDataSetPortInfo +extern PortData* NodeDataAddPort(FabricData_t *fabricp, NodeData *nodep, EUI64 guid, STL_PORTINFO_RECORD *pPortInfo); +extern FSTATUS NodeDataSetSwitchInfo(NodeData *nodep, STL_SWITCHINFO_RECORD *pSwitchInfo); +extern NodeData *FabricDataAddNode(FabricData_t *fabricp, STL_NODE_RECORD *pNodeRecord, boolean *new_nodep); + +extern FSTATUS AddEdgeSwitchToGroup(FabricData_t *fabricp, McGroupData *mcgroupp, NodeData *groupswitch, uint8 SWentryport); +extern McGroupData *FabricDataAddMCGroup(FabricData_t *fabricp, struct omgt_port *port, int quiet, IB_MCMEMBER_RECORD *pMCGRecord, + boolean *new_nodep, FILE *verbose_file); + +extern FSTATUS GetAllMCGroups(EUI64 portGuid, FabricData_t *fabricp, Point *focus, int quiet); +extern FSTATUS GetAllMCGroupMember(FabricData_t *fabricp, McGroupData *mcgroupp,struct omgt_port *portp,int quiet, FILE *g_verbose_file); + +extern boolean SupportsVendorPortCounters(NodeData *nodep, + IB_CLASS_PORT_INFO *classPortInfop); +extern boolean SupportsVendorPortCounters2(NodeData *nodep, + IB_CLASS_PORT_INFO *classPortInfop); + +/* build the Fabric.AllPorts, ALLFIs, and AllSWs lists such that + * AllPorts is sorted by NodeGUID, PortNum + * AllFIs, ALLSWs, AllIOUs is sorted by NodeGUID + */ +extern void BuildFabricDataLists(FabricData_t *fabricp); + +extern FSTATUS FabricDataAddLink(FabricData_t *fabricp, PortData *p1, PortData *p2); +extern FSTATUS FabricDataAddLinkRecord(FabricData_t *fabricp, STL_LINK_RECORD *pLinkRecord); +extern FSTATUS FabricDataRemoveLink(FabricData_t *fabricp, PortData *p1); + +extern void QOSDataAddSCSCMap(PortData *portp, uint8_t outport, int extended, const STL_SCSCMAP *pSCSC); +extern STL_SCSCMAP * QOSDataLookupSCSCMap(PortData *portp, uint8_t outport, int extended); + +// Set update lookup tables due to PortState, LID or LMC change for port. +// Typical use is when a SetPortInfo on neighbor causes a link state change +// For use by fabric simulator. +extern void PortDataStateChanged(FabricData_t *fabricp, PortData *portp); +// Set new Port Info based on a Set(PortInfo). For use by fabric simulator +// assumes pInfo already validated and any Noop fields filled in with correct +// values. +extern void PortDataSetPortInfo(FabricData_t *fabricp, PortData *portp, STL_PORT_INFO *pInfo); + +extern void DestroyFabricData(FabricData_t *fabricp); + +extern NodeData * CLDataAddDevice(FabricData_t *fabricp, NodeData *nodep, STL_LID lid, int verbose, int quiet); +extern FSTATUS CLDataAddConnection(FabricData_t *fabricp, PortData *portp1, PortData *portp2, clConnPathData_t *pathInfo, uint8 sc, int verbose, int quiet); +extern FSTATUS CLDataAddRoute(FabricData_t *fabricp, STL_LID slid, STL_LID dlid, PortData *sportp, int verbose, int quiet); +extern clGraphData_t * CLGraphDataSplit(clGraphData_t *graphp, int verbose); +extern FSTATUS CLFabricDataDestroy(FabricData_t *fabricp, void *context); +extern void CLGraphDataFree(clGraphData_t *graphp, void *context); +extern FSTATUS CLDijkstraFindDistancesAndRoutes(clGraphData_t *graphp, clDijkstraDistancesAndRoutes_t *respData, int verbose); +extern void CLDijkstraFreeDistancesAndRoutes(clDijkstraDistancesAndRoutes_t *drp); + +// search routines (Topology/search.c) +// For functions which generate Points, indicate what is needed +#define FIND_FLAG_FABRIC 0x01 /* find in live fabric */ +#define FIND_FLAG_ENODE 0x02 /* find in ExpectedNodes */ +#define FIND_FLAG_ESM 0x04 /* find in ExpectedSMs */ +#define FIND_FLAG_ELINK 0x08 /* find in ExpectedLinks */ + +// The search routines involving Points tend to limit the search to the +// specific objects indicated by find_flag and expect later caller use of +// Compare functions to invoke the necessary Compare functions to cover the +// fabric vs expected objects of interest. One exception is the comparison +// for Details and Cable information which is only available in topology.xml +// In this case, the fabric seach will check the resolved expected object +// This permits the majority of fabric related operations, such as opareport, +// to make use of Details and Cable information from topology.xml while +// only considering fabric objects. + +// search for the PortData corresponding to the given node and port number +extern PortData * FindNodePort(NodeData *nodep, uint8 port); +// search for the PortData corresponding to the given lid +extern PortData * FindLid(FabricData_t* fabricp, STL_LID lid); +// search for the PortData corresponding to the given port Guid +extern PortData * FindPortGuid(FabricData_t* fabricp, EUI64 guid); +extern FSTATUS FindPortGuidPoint(FabricData_t *fabricp, EUI64 guid, Point *pPoint, uint8 find_flag, int silent); +extern FSTATUS FindGidPoint(FabricData_t *fabricp, IB_GID gid, Point *pPoint, uint8 find_flag, int silent); +// search for the NodeData corresponding to the given node Guid +extern NodeData * FindNodeGuid(const FabricData_t* fabricp, EUI64 guid); +extern FSTATUS FindNodeGuidPoint(FabricData_t *fabricp, EUI64 guid, Point *pPoint, uint8 find_flag, int silent); +extern FSTATUS FindNodeNamePoint(FabricData_t* fabricp, char *name, Point *pPoint, uint8 find_flag, int silent); +extern FSTATUS FindNodeNamePatPoint(FabricData_t* fabricp, char *pattern, Point *pPoint, uint8 find_flag); +extern FSTATUS FindNodeNamePatPointUncompress(FabricData_t *fabricp, char *pattern, Point *pPoint, uint8 find_flag); + +extern FSTATUS FindNodePatPairs(FabricData_t *fabricp, char *pattern, NodePairList_t *nodePatPairs, uint8 find_flag, uint8 side); +extern FSTATUS FindNodeDetailsPatPoint(FabricData_t* fabricp, const char* pattern, Point *pPoint, uint8 find_flag); +extern FSTATUS FindNodeTypePoint(FabricData_t* fabricp, NODE_TYPE type, Point *pPoint, uint8 find_flag); +#if !defined(VXWORKS) || defined(BUILD_DMC) +extern FSTATUS FindIocNamePoint(FabricData_t* fabricp, char *name, Point *pPoint, uint8 find_flag); +extern FSTATUS FindIocNamePatPoint(FabricData_t* fabricp, char *pattern, Point *pPoint, uint8 find_flag); +extern FSTATUS FindIocTypePoint(FabricData_t* fabricp, IocType type, Point *pPoint, uint8 find_flag); +extern FSTATUS FindIocGuid(FabricData_t* fabricp, EUI64 guid, Point *pPoint); +#endif +extern SystemData * FindSystemGuid(FabricData_t* fabricp, EUI64 guid); +extern FSTATUS FindRatePoint(FabricData_t* fabricp, uint32 rate, Point *pPoint, uint8 find_flag); +extern FSTATUS FindPortStatePoint(FabricData_t* fabricp, uint8 state, Point *pPoint, uint8 find_flag); +extern FSTATUS FindLedStatePoint(FabricData_t* fabricp, uint8 state, Point *pPoint, uint8 find_flag); +extern FSTATUS FindPortPhysStatePoint(FabricData_t* fabricp, IB_PORT_PHYS_STATE state, Point *pPoint, uint8 find_flag); +extern FSTATUS FindCableLabelPatPoint(FabricData_t* fabricp, const char* pattern, Point *pPoint, uint8 find_flag); +extern FSTATUS FindCableLenPatPoint(FabricData_t* fabricp, const char* pattern, Point *pPoint, uint8 find_flag); +extern FSTATUS FindCableDetailsPatPoint(FabricData_t* fabricp, const char* pattern, Point *pPoint, uint8 find_flag); +extern FSTATUS FindCabinfLenPatPoint(FabricData_t *fabricp, const char* pattern, Point *pPoint, uint8 find_flag); +extern FSTATUS FindCabinfVendNamePatPoint(FabricData_t *fabricp, const char* pattern, Point *pPoint, uint8 find_flag); +extern FSTATUS FindCabinfVendPNPatPoint(FabricData_t *fabricp, const char* pattern, Point *pPoint, uint8 find_flag); +extern FSTATUS FindCabinfVendRevPatPoint(FabricData_t *fabricp, const char* pattern, Point *pPoint, uint8 find_flag); +extern FSTATUS FindCabinfVendSNPatPoint(FabricData_t *fabricp, const char* pattern, Point *pPoint, uint8 find_flag); +extern FSTATUS FindCabinfCableTypePoint(FabricData_t *fabricp, char *cablearg, Point *pPoint, uint8 find_flag); +extern FSTATUS FindLinkDetailsPatPoint(FabricData_t* fabricp, const char* pattern, Point *pPoint, uint8 find_flag); +extern FSTATUS FindPortDetailsPatPoint(FabricData_t* fabricp, const char* pattern, Point *pPoint, uint8 find_flag); +extern FSTATUS FindMtuPoint(FabricData_t* fabricp, IB_MTU mtu, Point *pPoint, uint8 find_flag); +extern PortData * FindMasterSm(FabricData_t* fabricp); +extern FSTATUS FindSmDetailsPatPoint(FabricData_t *fabricp,const char* pattern, Point *pPoint, uint8 find_flag); +// search for the SMData corresponding to the given PortGuid +extern SMData * FindSMPort(FabricData_t *fabricp,EUI64 PortGUID); +// search for the PortData corresponding to the given lid and port number +// For FIs lid completely defines the port +// For Switches, lid will identify the switch and port is used to select port +extern PortData * FindLidPort(FabricData_t *fabricp, STL_LID lid, uint8 port); +extern PortData * FindNodeGuidPort(FabricData_t *fabricp,EUI64 nodeguid, uint8 port); +extern ExpectedNode* FindExpectedNodeByNodeGuid(const FabricData_t* fabricp, EUI64 nodeGuid); +extern ExpectedNode* FindExpectedNodeByNodeDesc(const FabricData_t* fabricp, const char* nodeDesc, uint8 NodeType); +extern ExpectedLink* FindExpectedLinkByOneSide(const FabricData_t* fabricp, EUI64 nodeGuid, uint8 portNum, uint8* side); +extern FSTATUS FindLinkQualityPoint(FabricData_t *fabricp, uint16 quality, LinkQualityCompare comp, Point *pPoint, uint8 find_flag); +extern FSTATUS FindLinkDownReasonPoint(FabricData_t *fabricp, uint8 ldr, Point *pPoint, uint8 find_flag); +extern FSTATUS FindExpectedSMByPortGuid(FabricData_t *fabricp, EUI64 portGuid); +extern FSTATUS FindExpectedSMByNodeGuid(FabricData_t *fabricp, EUI64 nodeGuid); + +extern void setTopologyMadVerboseFile(FILE* verbose_file); +extern void setTopologyMadRetryCount(int retries); +// mad queries to SMA (from Topology/mad.c) +extern FSTATUS SmaGetNodeDesc(struct omgt_port *port, STL_LID dlid, STL_LID slid, uint8_t* path, STL_NODE_DESCRIPTION *pNodeDesc); +extern FSTATUS SmaGetNodeInfo(struct omgt_port *port, STL_LID dlid, STL_LID slid, uint8_t* path, STL_NODE_INFO *pNodeInfo); +extern FSTATUS SmaGetSwitchInfo(struct omgt_port *port, STL_LID dlid, STL_LID slid, uint8_t* path, STL_SWITCH_INFO *pSwitchInfo); +extern FSTATUS SmaGetPortInfo(struct omgt_port *port, STL_LID dlid, STL_LID slid, uint8_t* path, uint8_t portNum, uint8_t smConfigStarted, STL_PORT_INFO *pPortInfo); +extern FSTATUS SmaGetPartTable(struct omgt_port *port, STL_LID dlid, STL_LID slid, uint8_t* path, uint8_t portNum, uint16_t block, STL_PARTITION_TABLE *pPartTable); +extern FSTATUS SmaGetVLArbTable(struct omgt_port *port, STL_LID dlid, STL_LID slid, uint8_t* path, uint8_t portNum, uint8_t part, STL_VLARB_TABLE *pVLArbTable); +extern FSTATUS SmaGetSLSCMappingTable(struct omgt_port *port, STL_LID dlid, STL_LID slid, uint8_t* path, STL_SLSCMAP *pSLSCMap); +extern FSTATUS SmaGetSCSLMappingTable(struct omgt_port *port, STL_LID dlid, STL_LID slid, uint8_t* path, STL_SCSLMAP *pSCSLMap); +extern FSTATUS SmaGetSCSCMappingTable(struct omgt_port *port, STL_LID dlid, STL_LID slid, uint8_t* path, uint8_t in_port, uint8_t out_port, STL_SCSCMAP *pSCSCMap); +extern FSTATUS SmaGetSCVLMappingTable(struct omgt_port *port, STL_LID dlid, STL_LID slid, uint8_t* path, uint8_t port_num, STL_SCVLMAP *pSCVLMap, uint16_t attr); +extern FSTATUS SmaGetLinearFDBTable(struct omgt_port *port, STL_LID dlid, STL_LID slid, uint8_t* path, uint16_t block, STL_LINEAR_FORWARDING_TABLE *pFDB); +extern FSTATUS SmaGetMulticastFDBTable(struct omgt_port *port, STL_LID dlid, STL_LID slid, uint8_t* path, uint32_t block, uint8_t position, STL_MULTICAST_FORWARDING_TABLE *pFDB); +extern FSTATUS SmaGetPortGroupFDBTable(struct omgt_port *port, STL_LID dlid, STL_LID slid, uint8_t* path, uint16 block, STL_PORT_GROUP_FORWARDING_TABLE *pFDB); +extern FSTATUS SmaGetPortGroupTable(struct omgt_port *port, STL_LID dlid, STL_LID slid, uint8_t* path, uint16 block, STL_PORT_GROUP_TABLE *pPGT); + +extern FSTATUS SmaGetBufferControlTable(struct omgt_port *port, STL_LID dlid, STL_LID slid, uint8_t* path, uint8_t startPort, uint8_t endPort, STL_BUFFER_CONTROL_TABLE pBCT[]); +extern FSTATUS SmaGetCableInfo(struct omgt_port *port, STL_LID dlid, STL_LID slid, uint8_t* path, uint8_t portNum, uint16_t addr, uint8_t len, uint8_t *data); + +extern FSTATUS SmaSetSwitchInfo(struct omgt_port *port, STL_LID dlid, STL_LID slid, uint8_t* path, STL_SWITCH_INFO *pSwitchInfo); +extern FSTATUS SmaSetPortInfo(struct omgt_port *port, STL_LID dlid, STL_LID slid, uint8_t* path, uint8_t portNum, STL_PORT_INFO *pPortInfo); +extern FSTATUS SmaSetPartTable(struct omgt_port *port, STL_LID dlid, STL_LID slid, uint8_t* path, uint8_t portNum, uint16_t block, STL_PARTITION_TABLE *pPartTable); +extern FSTATUS SmaSetVLArbTable(struct omgt_port *port, STL_LID dlid, STL_LID slid, uint8_t* path, uint8_t portNum, uint8_t part, STL_VLARB_TABLE *pVLArbTable); +extern FSTATUS SmaSetSLSCMappingTable(struct omgt_port *port, STL_LID dlid, STL_LID slid, uint8_t* path, STL_SLSCMAP *pSLSCMap); +extern FSTATUS SmaSetSCSLMappingTable(struct omgt_port *port, STL_LID dlid, STL_LID slid, uint8_t* path, STL_SCSLMAP *pSCSLMap); +extern FSTATUS SmaSetSCSCMappingTable(struct omgt_port *port, STL_LID dlid, STL_LID slid, uint8_t* path, uint8_t in_port, uint8_t out_port, STL_SCSCMAP *pSCSCMap); +extern FSTATUS SmaSetSCVLMappingTable(struct omgt_port *port, STL_LID dlid, STL_LID slid, uint8_t* path, boolean asyncUpdate, boolean allPorts, uint8_t portNum, STL_SCVLMAP *pSCVLMap, uint16_t attr); +extern FSTATUS SmaSetBufferControlTable(struct omgt_port *port, STL_LID dlid, STL_LID slid, uint8_t* path, uint8_t startPort, uint8_t endPort, STL_BUFFER_CONTROL_TABLE pBCT[]); +extern FSTATUS SmaSetLinearFDBTable(struct omgt_port *port, STL_LID dlid, STL_LID slid, uint8_t* path, uint16_t block, STL_LINEAR_FORWARDING_TABLE *pFDB); +extern FSTATUS SmaSetMulticastFDBTable(struct omgt_port *port, STL_LID dlid, STL_LID slid, uint8_t* path, uint32_t block, uint8_t position, STL_MULTICAST_FORWARDING_TABLE *pFDB); + +extern FSTATUS SmaGetCongestionInfo(struct omgt_port *port, STL_LID dlid, STL_LID slid, uint8_t* path, STL_CONGESTION_INFO *pCongestionInfo); +extern FSTATUS SmaGetHFICongestionControlTable(struct omgt_port *port, STL_LID dlid, STL_LID slid, uint8_t* path, uint16_t block, uint16_t numBlocks, STL_HFI_CONGESTION_CONTROL_TABLE *pHfiCongestionControl); + +// mad queries to PMA and DMA (from Topology/mad.c) +extern FSTATUS InitMad(EUI64 portguid, FILE *verbose_file); +extern void DestroyMad(void); +extern FSTATUS InitSmaMkey(uint64 mkey); +extern boolean NodeHasPma(NodeData *nodep); +extern boolean PortHasPma(PortData *portp); +extern void UpdateNodePmaCapabilities(NodeData *nodep, boolean ProcessHFICounters); +extern FSTATUS STLPmGetClassPortInfo(struct omgt_port *port, PortData *portp); +extern FSTATUS STLPmGetPortStatus(struct omgt_port *port, PortData *portp, uint8 portNum, STL_PORT_STATUS_RSP *pPortStatus); +extern FSTATUS STLPmClearPortCounters(struct omgt_port *port, PortData *portp, uint8 lastPortIndex, uint32 counterselect); +#if !defined(VXWORKS) || defined(BUILD_DMC) +extern FSTATUS DmGetIouInfo(struct omgt_port *port, IB_PATH_RECORD *pathp, IOUnitInfo *pIouInfo); +extern FSTATUS DmGetIocProfile(struct omgt_port *port, IB_PATH_RECORD *pathp, uint8 slot, + IOC_PROFILE *pIocProfile); +extern FSTATUS DmGetServiceEntries(struct omgt_port *port, IB_PATH_RECORD *pathp, uint8 slot, + uint8 first, uint8 last, IOC_SERVICE *pIocServices); +#endif + +// POINT routines (from Topology/point.c) +extern void PointInit(Point *point); +extern boolean PointIsInInit(Point *point); +extern void PointFabricDestroy(Point *point); +extern void PointEnodeDestroy(Point *point); +extern void PointEsmDestroy(Point *point); +extern void PointElinkDestroy(Point *point); +extern void PointDestroy(Point *point); +extern boolean PointValid(Point *point); +extern FSTATUS PointFabricCopy(Point *dest, Point *src); +extern FSTATUS PointEnodeCopy(Point *dest, Point *src); +extern FSTATUS PointEsmCopy(Point *dest, Point *src); +extern FSTATUS PointElinkCopy(Point *dest, Point *src); +extern FSTATUS PointCopy(Point *dest, Point *src); +extern FSTATUS PointListAppend(Point *point, PointType type, void *object); +extern FSTATUS PointEnodeListAppend(Point *point, PointEnodeType type, void *object); +extern FSTATUS PointEsmListAppend(Point *point, PointEsmType type, void *object); +extern FSTATUS PointElinkListAppend(Point *point, PointElinkType type, void *object); +extern FSTATUS PointNodePairListAppend(Point *point, uint8 side, void *object); +extern FSTATUS PointPopulateNodePairList(Point *pPoint, NodePairList_t *nodePatPairs); +extern void PointFabricCompress(Point *point); +extern void PointEnodeCompress(Point *point); +extern void PointEsmCompress(Point *point); +extern void PointElinkCompress(Point *point); +extern void PointCompress(Point *point); +extern FSTATUS PointListAppendUniquePort(Point *point, PortData *portp); +/* These compare functions will compare the supplied object to the + * specific relevant portion of the point. Callers who wish to consider + * both expected and fabric objects should call all the relevant routines + * for the fabric and linked expected objects + * This approach provides greater flexibility for callers, and removes the need + * for the Point construction and parsing routines to check all the linked + * fabric and expected objects. + */ + +/* compare the supplied port to the given point + * this is used to identify focus for reports + * if ! PointValid will report TRUE for all ports + */ +extern boolean ComparePortPoint(PortData *portp, Point *point); +/* compare the supplied node to the given point + * this is used to identify focus for reports + * if ! PointValid will report TRUE for all nodes + */ +extern boolean CompareNodePoint(NodeData *nodep, Point *point); +/* compare the supplied ExpectedNode to the given point + * this is used to identify focus for reports + * if !PointValid will report TRUE for all ExpectedNodes + */ +extern boolean CompareExpectedNodePoint(ExpectedNode *enodep, Point *point); +/* compare the supplied ExpectedSM to the given point + * this is used to identify focus for reports + * if !PointValid will report TRUE for all ExpectedSMs + */ +extern boolean CompareExpectedSMPoint(ExpectedSM *esmp, Point *point); +/* compare the supplied ExpectedLink to the given point + * this is used to identify focus for reports + * if !PointValid will report TRUE for all ExpectedLinks + */ +extern boolean CompareExpectedLinkPoint(ExpectedLink *elinkp, Point *point); +#if !defined(VXWORKS) || defined(BUILD_DMC) +extern boolean CompareIouPoint(IouData *ioup, Point *point); +extern boolean CompareIocPoint(IocData *iocp, Point *point); +#endif +/* compare the supplied SM to the given point + * this is used to identify focus for reports + * if ! PointValid will report TRUE for all SMs + */ +extern boolean CompareSmPoint(SMData *smp, Point *point); +extern boolean CompareSystemPoint(SystemData *systemp, Point *point); + +/* check arg to see if 1st characters match prefix, if so return pointer + * into arg just after prefix, otherwise return NULL + */ +extern char* ComparePrefix(char *arg, const char *prefix); +extern FSTATUS ParsePoint(FabricData_t *fabricp, char* arg, Point* pPoint, uint8 find_flag, char **pp); + +/* check if point is of Type NodePairList */ +extern boolean PointTypeIsNodePairList(Point *pPoint); +/* check if point is of Type NodeList */ +extern boolean PointIsTypeNodeList(Point *pPoint); +/* check if haveSW flag is set */ +extern boolean PointHaveSw(Point *pPoint); +/* check if haveFI flag is set */ +extern boolean PointHaveFI(Point *pPoint); + +// snapshot input/output routines (from Topology/snapshot.c) +extern void Xml2PrintSnapshot(FILE *file, SnapshotOutputInfo_t *info); + +struct IXmlParserState; + +/** + Completion callback manipulators. These get called inside custom end_func + definitions and typically do things like insert the completed + structure into a broader data structure. + + The basic idea is to separate how the entity is parsed from how it is used by the parent. +*/ +typedef int (*ParseCompleteFn)(struct IXmlParserState * state, void * object, void * parent); + +void SetPortDataComplete(ParseCompleteFn fn); + +/** + only FF_LIDARRAY flag is used, others set based on file read + @param allocFull When true, adjust allocated memory for linear and multicast forwarding tables to their cap values after reading in all data. +*/ +#ifndef __VXWORKS__ +extern FSTATUS Xml2ParseSnapshot(const char *input_file, int quiet, FabricData_t *fabricp, FabricFlags_t flags, boolean allocFull); +#else +extern FSTATUS Xml2ParseSnapshot(const char *input_file, int quiet, FabricData_t *fabricp, FabricFlags_t flags, boolean allocFull, XML_Memory_Handling_Suite* memsuite); +#endif + +// expected topology input/output routines (from Topology/topology.c) + +// validation options for Xml2ParseTopology +// None - no attempt to cross reference ExpectedLinks to ExpectedNodes +// the ExpectedLink.portselp1 may be NULL +// the ExpectedLink.portselp1->enodep will be NULL +// the ExpectedLink.portselp2 may be NULL +// the ExpectedLink.portselp2->enodep will be NULL +// the ExpectedNode.ports[] may be empty +// the ExpectedNode.ports[]->elinkp will be NULL +// Loose - do a best attempt to resolve (eg. cross reference) ExpectedLinks +// to ExpectedNodes filling in the elinkp and enodep pointers mentioned +// above where possible. Also checks that when Node and Port GUIDs are +// supplied in ExpectedNodes, that switch port 0's GUIDs are consistent. +// However no error return reported by Xml2ParseTopology when unable +// to resolve some links. Does not require ExpectedNodes to +// explicitly list ports in topology file. Will auto-create +// ExpectedNode.ports[] entries if a ExpectedLink references the given +// node's port. +// Somewhat strict - cross references all ExpectedLinks to ExpectedNodes as +// in Loose. Also checks that all nodes are connected to the same fabric. +// Any errors in resolution or checks are reported as an error by +// Xml2ParseTopology. +// Strict - performs all checks in Somewhat strict. Also requires that all +// ExpectedLinks explicitly list PortNum in topology file and +// all ExpectedNodes explicitly list ports in topology file. +// In all cases its valid for a ExpectedNode to list a port which is not +// connected to the fabric (eg. not referenced by an ExpectedLink). +// +typedef enum { + TOPOVAL_NONE =0, + TOPOVAL_LOOSE =1, // resolve what we can, no graph closure checks + TOPOVAL_SOMEWHAT_STRICT =2, // same as strict but don't require under + TOPOVAL_STRICT =3 +} TopoVal_t; + // in ExpectedNode in topology file +#ifndef __VXWORKS__ +extern FSTATUS Xml2ParseTopology(const char *input_file, int quiet, FabricData_t *fabricp, TopoVal_t validation); +#else +extern FSTATUS Xml2ParseTopology(const char *input_file, int quiet, FabricData_t *fabricp, XML_Memory_Handling_Suite* memsuite, TopoVal_t validation); +#endif +extern void Xml2PrintTopology(FILE *file, FabricData_t *fabricp); + +// live fabric analysis routines (from Topology/sweep.c) +extern FSTATUS InitSweepVerbose(FILE *verbose_file); +/* flags for Sweep */ +typedef enum { + SWEEP_BASIC =0, // Systems, Nodes, Ports, Links +#if !defined(VXWORKS) || defined(BUILD_DMC) + SWEEP_IOUS =0x000000001, // IOU and IOC Info +#endif + SWEEP_SWITCHINFO =0x000000002, // Switch Info + SWEEP_SM =0x000000003, // SM Info + SWEEP_ALL =0x000000003 +} SweepFlags_t; + +extern FSTATUS Sweep(EUI64 portGuid, FabricData_t *fabricp, FabricFlags_t fflags, SweepFlags_t flags, int quiet, int ms_timeout); + +//extern FSTATUS GetPathToPort(EUI64 portGuid, PortData *portp, uint16 pkey); +extern FSTATUS GetPaths(struct omgt_port *port, PortData *portp1, PortData *portp2, + PQUERY_RESULT_VALUES *ppQueryResults); +extern FSTATUS GetTraceRoute(struct omgt_port *port, IB_PATH_RECORD *pathp, + PQUERY_RESULT_VALUES *ppQueryResults); +extern FSTATUS GetAllPortCounters(EUI64 portGuid, IB_GID localGid, FabricData_t *fabricp, + Point *focus, boolean limitstats, boolean quiet, uint32 begin, uint32 end); +extern FSTATUS GetAllFDBs( EUI64 portGuid, FabricData_t *fabricp, Point *focus, + int quiet ); +extern FSTATUS GetAllPortVLInfo(EUI64 portGuid, FabricData_t *fabricp, Point *focus, int quieti, int *use_scsc); +extern PQUERY_RESULT_VALUES GetAllQuarantinedNodes(struct omgt_port *port, FabricData_t *fabricp, + Point *focus, int quiet); +extern FSTATUS GetAllBCTs(EUI64 portGuid, FabricData_t *fabricp, Point *focus, int quiet); + +extern FSTATUS ClearAllPortCounters(EUI64 portGuid, IB_GID localGid, FabricData_t *fabricp, + Point *focus, uint32 counterselect, boolean limitstats, + boolean quiet, uint32 *node_countp, uint32 *port_countp, + uint32 *fail_node_countp, uint32 *fail_port_countp); + +extern PQUERY_RESULT_VALUES GetAllDeviceGroupMemberRecords(struct omgt_port *port, FabricData_t *fabricp, + Point *focus, int quiet); +extern void XmlPrintHex64(const char *tag, uint64 value, int indent); +extern FSTATUS ParseFocusPoint(EUI64 portGuid, FabricData_t *fabricp, char* arg, Point* pPoint, uint8 find_flag, char **pp, boolean allow_route); + +// utility routines (from Topology/util.c) +extern void Top_setcmdname(const char *name); // for error messages +extern void Top_setFreeCallbacks(Top_FreeCallbacks *callbacks); +extern void ProgressPrint(boolean newline, const char *format, ...); +extern const char* Top_truncate_str(const char *name); +//#define PROGRESS_PRINT(newline, format, args...) if (! g_quiet) { ProgressPrint(newline, format, ##args); } + + +// functions to perform routing analysis using LFT tables in FabricData +//(from Topology/route.c) + +// For each device along the path, entry and exit port of device is provided +// For the CA at the start of the route, only an exit port is provided +// For the CA at the end of the route, only a entry port is provided +// For switches along the route, both entry and exit ports are provided +// When a switch Port 0 is the start of the route, it will be the entry port +// along with the physical exit port +// When a switch Port 0 is the end of the route, it will be the exit port +// along with the physical entry port +// The above approach parallels how TraceRoute records are reported by the +// SM, so if desired a callback could build a SM TraceRoute style response +// for use in other routines. +typedef FSTATUS (RouteCallback_t)(PortData *entryPortp, PortData *exitPortp, uint8 vl, + void *context); + +// returns status of callback (if not FSUCCESS) +// FUNAVAILABLE - no routing tables in FabricData given +// FNOT_FOUND - unable to find starting port +// FNOT_DONE - unable to trace route, dlid is a dead end +extern FSTATUS WalkRoutePort(FabricData_t *fabricp, + PortData *portp, STL_LID dlid, uint8 SL, uint8 rc, + RouteCallback_t *callback, void *context); +// walk by slid to dlid +extern FSTATUS WalkRoute(FabricData_t *fabricp, STL_LID slid, STL_LID dlid, + RouteCallback_t *callback, void *context); + +// caller must free *ppTraceRecords +extern FSTATUS GenTraceRoutePort(FabricData_t *fabricp, + PortData *portp, STL_LID dlid, uint8 rc, + STL_TRACE_RECORD **ppTraceRecords, uint32 *pNumTraceRecords); +extern FSTATUS GenTraceRoute(FabricData_t *fabricp, STL_LID slid, STL_LID dlid, uint8 rc, + STL_TRACE_RECORD **ppTraceRecords, uint32 *pNumTraceRecords); +extern FSTATUS GenTraceRoutePath(FabricData_t *fabricp, IB_PATH_RECORD *pathp, uint8 rc, + STL_TRACE_RECORD **ppTraceRecords, uint32 *pNumTraceRecords); + +// Generate possible Path records from portp1 to portp2 +// We don't know SM config, so we just guess and generate paths of the form +// 0-0, 1-1, .... +// This corresponds to the PathSelection=Minimal FM config option +// when LMC doesn't match we start back at base lid for other port +// These may not be accurate for Torus, however the dlid is all that really +// matters for route analysis, so this should be fine +extern FSTATUS GenPaths(FabricData_t *fabricp, + PortData *portp1, PortData *portp2, + IB_PATH_RECORD **ppPathRecords, uint32 *pNumPathRecords); + +// tabulate all the ports along the route from slid to dlid +extern FSTATUS TabulateRoute(FabricData_t *fabricp, STL_LID slid, STL_LID dlid, + boolean fatTree); +// tabulate all routes from portp1 to portp2 +extern FSTATUS TabulateRoutes(FabricData_t *fabricp, + PortData *portp1, PortData *portp2, uint32 *totalPaths, + uint32 *badPaths, boolean fatTree); +// tabulate all the routes between FIs, exclude loopback routes +extern FSTATUS TabulateCARoutes(FabricData_t *fabricp, Point *focus, uint32 *totalPaths, + uint32 *badPaths, boolean fatTree); + +typedef void (*ReportCallback_t)(PortData *portp1, PortData *portp2, + STL_LID dlid, boolean isBaseLid, + boolean flag /* TRUE=uplink or Recv */, void *context); + +// report all routes from portp1 to portp2 that cross reportPort +extern FSTATUS ReportRoutes(FabricData_t *fabricp, + PortData *portp1, PortData *portp2, + PortData *reportPort, + ReportCallback_t callback, void *context, boolean fatTree); +// report all the routes between FIs that cross reportPort, +// exclude loopback routes +extern FSTATUS ReportCARoutes(FabricData_t *fabricp, + PortData *reportPort, + ReportCallback_t callback, void *context, boolean fatTree); + +// callback used to indicate that an incomplete route exists between p1 and p2 +typedef void (*ValidateCallback_t)(PortData *portp1, PortData *portp2, + STL_LID dlid, boolean isBaseLid, uint8 sl, void *context); + +// callback used to indicate a port along an incomplete route +typedef void (*ValidateCallback2_t)(PortData *portp, uint8 vl, void *context); + +// validate all routes from portp1 to portp2 +extern FSTATUS ValidateRoutes(FabricData_t *fabricp, + PortData *portp1, PortData *portp2, + uint32 *totalPaths, uint32 *badPaths, + uint32 usedSLs, uint8, + ValidateCallback_t callback, void *context, + ValidateCallback2_t callback2, void *context2); +// validate all the routes between all LIDs +// exclude loopback routes +extern FSTATUS ValidateAllRoutes(FabricData_t *fabricp, EUI64 portGuid, + uint8 rc, uint32 *totalPaths, uint32 *badPaths, + ValidateCallback_t callback, void *context, + ValidateCallback2_t callback2, void *context2, + uint8 useSCSC); + +// validate all MC routes between all members +// exclude loopback routes +extern FSTATUS ValidateAllMCRoutes(FabricData_t *fabricp, + uint32 *totalPaths); +extern FSTATUS ValidateMCRoutes(FabricData_t *fabricp, McGroupData *mcgroupp, + McEdgeSwitchData *swp, uint32 *pathCount); +extern FSTATUS WalkMCRoute(FabricData_t *fabricp, McGroupData *mcgroupp, PortData *portp, int hop, + uint8 EntryPort, McLoopInc *pMcLoopInc, uint32 *pathCount); +extern FSTATUS AddSwtichToGroup(FabricData_t *fabricp, McGroupData *mcgroupp, NodeData *groupswitch); +extern void FreeValidateMCRoutes(FabricData_t *fabricp); + + +typedef void (*ValidateCLRouteCallback_t)(PortData *portp1, PortData *portp2, void *context); +typedef void (*ValidateCLFabricSummaryCallback_t)(FabricData_t *fabricp, const char *name, + uint32 totalPaths, uint32 totalBadPaths, + void *context); +typedef void (*ValidateCLDataSummaryCallback_t)(clGraphData_t *graphp, const char *name, void *context); +typedef void (*ValidateCLRouteSummaryCallback_t)(uint32 routesPresent, + uint32 routesMissing, + uint32 hopsHistogramEntries, + uint32 *hopsHistogram, + void *context); +typedef void (*ValidateCLPathSummaryCallback_t)(FabricData_t *fabricp, clConnData_t *connp, int indent, void *context); +typedef void (*ValidateCLLinkSummaryCallback_t)(uint32 id, const char *name, uint32 cycle, uint8 header, int indent, void *context); +typedef void (*ValidateCLLinkStepSummaryCallback_t)(uint32 id, const char *name, uint32 step, uint8 header, int indent, void *context); + +#ifndef __VXWORKS__ +typedef FSTATUS (*ValidateCLTimeGetCallback_t)(uint64_t *address, pthread_mutex_t *lock); + +extern pthread_mutex_t g_cl_lock; +extern FSTATUS ValidateAllCreditLoopRoutes(FabricData_t *fabricp, EUI64 portGuid, uint8 rc, + ValidateCLRouteCallback_t routeCallback, + ValidateCLFabricSummaryCallback_t fabricSummaryCallback, + ValidateCLDataSummaryCallback_t dataSummaryCallback, + ValidateCLRouteSummaryCallback_t routeSummaryCallback, + ValidateCLLinkSummaryCallback_t linkSummaryCallback, + ValidateCLLinkStepSummaryCallback_t linkStepSummaryCallback, + ValidateCLPathSummaryCallback_t pathSummaryCallback, + ValidateCLTimeGetCallback_t timeGetCallback, + void *context, + uint8 snapshotInFile, + uint8 useSCSC); +extern void CLFabricSummary(FabricData_t *fabricp, const char *name, ValidateCLFabricSummaryCallback_t callback, + uint32 totalPaths, uint32 totalBadPaths, void *context); +extern void CLGraphDataSummary(clGraphData_t *graphp, const char *name, ValidateCLDataSummaryCallback_t callback, void *context); +extern FSTATUS CLFabricDataBuildRouteGraph(FabricData_t *fabricp, + ValidateCLRouteSummaryCallback_t routeSummaryCallback, + ValidateCLTimeGetCallback_t timeGetCallback, + void *context, + uint32 usedSLs); +extern void CLGraphDataPrune(clGraphData_t *graphp, ValidateCLTimeGetCallback_t timeGetCallback, int verbose, int quiet); +extern void CLDijkstraFindCycles(FabricData_t *fabricp, + clGraphData_t *graphp, + clDijkstraDistancesAndRoutes_t *drp, + ValidateCLLinkSummaryCallback_t linkSummaryCallback, + ValidateCLLinkStepSummaryCallback_t linkStepSummaryCallback, + ValidateCLPathSummaryCallback_t pathSummaryCallback, + void *context); +extern FSTATUS CLTimeGet(uint64_t *address); +#endif + +extern PortData *GetMapEntry(FabricData_t *fabricp, STL_LID lid); +extern FSTATUS SetMapEntry(FabricData_t *fabricp, STL_LID lid, PortData *pd); +extern void FreeLidMap(FabricData_t *fabricp); + +static __inline uint32 ComputeMulticastFDBSize(const STL_SWITCH_INFO *pSwitchInfo) +{ + //STL Volg1 20.2.2.6.5 + return (pSwitchInfo->MulticastFDBTop >= STL_LID_MULTICAST_BEGIN) ? + pSwitchInfo->MulticastFDBTop-STL_LID_MULTICAST_BEGIN+1 : 0; +} + + +static __inline int getVLArb(PortData *p, int *res) +{ + NodeData *n = p->nodep; + + if (n->NodeInfo.NodeType == STL_NODE_SW && p->PortNum != 0) { + cl_map_item_t *it = cl_qmap_get(&n->Ports, 0); + if (it == cl_qmap_end(&n->Ports)) + return 1; + + p = PARENT_STRUCT(it, PortData, NodePortsEntry); + } + + *res = p->PortInfo.CapabilityMask3.s.VLSchedulingConfig == STL_VL_SCHED_MODE_VLARB; + return 0; +} + +// TODO MLID offset mask should be derived from MulticastMask in +// SwitchInfo or PortInfo, not hardcoded to lower 14 bits +#define MULTICAST_LID_OFFSET_MASK 0x3FFF + +/** + * Use this function to get offset in multicast FDB without + * having to know multicast LID format. + */ +static inline uint32 GetMulticastOffset(STL_LID mlid) +{ + // TODO should use MulticastMask and CollectiveMask from PortInfo + // or SwitchInfo to determine a) if mlid is a multicast LID and b) + // how many bits in mlid are offset bits + return (mlid & MULTICAST_LID_OFFSET_MASK); +} + +static inline PortData* getCapabilityPortData(NodeData *nodep, PortData *portp) +{ + if (nodep->NodeInfo.NodeType == STL_NODE_SW && portp->PortNum != 0) + return FindNodePort(nodep, 0); + + return portp; +} + +static inline int getIsVLrSupported(NodeData *nodep, PortData *portp) +{ + PortData* port = getCapabilityPortData(nodep, portp); + if (port && port->PortInfo.CapabilityMask3.s.IsVLrSupported) + return 1; + return 0; +} + +static inline int getIsAsyncSC2VLSupported(NodeData *nodep, PortData *portp) +{ + PortData* port = getCapabilityPortData(nodep, portp); + if (port && port->PortInfo.CapabilityMask3.s.IsAsyncSC2VLSupported) + return 1; + return 0; +} + +typedef enum { + SC2VL_UPDATE_TYPE_NONE = 0, + SC2VL_UPDATE_TYPE_SYNC, + SC2VL_UPDATE_TYPE_ASYNC +} SC2VLUpdateType; + +static inline SC2VLUpdateType getSC2VLUpdateType(NodeData *nodep, PortData *portp, ScvlEnum_t scvlx) +{ + uint8_t currentPortState = portp->PortInfo.PortStates.s.PortState; + boolean currentPortAsyncSC2VL = getIsAsyncSC2VLSupported(nodep, portp); + + // port must be at least in the Init state + if (currentPortState < IB_PORT_INIT) + return SC2VL_UPDATE_TYPE_NONE; + + // switch port 0 - special case + if (nodep->NodeInfo.NodeType == STL_NODE_SW && portp->PortNum == 0) { + if (scvlx == Enum_SCVLt) + return SC2VL_UPDATE_TYPE_SYNC; + + if (scvlx == Enum_SCVLr) { + if (currentPortState == IB_PORT_INIT) + return SC2VL_UPDATE_TYPE_SYNC; + if (currentPortAsyncSC2VL) + return SC2VL_UPDATE_TYPE_ASYNC; + } + + return SC2VL_UPDATE_TYPE_NONE; + } + + // in link state Init only sync update is allowed + if (currentPortState == IB_PORT_INIT) + return SC2VL_UPDATE_TYPE_SYNC; + + // async update is allowed only when the link state is Armed or Active and both ports support async update + if (currentPortAsyncSC2VL) { + boolean neighborPortAsyncSC2VL = FALSE; + + if (portp->neighbor && portp->neighbor->nodep->valid) + neighborPortAsyncSC2VL = getIsAsyncSC2VLSupported(portp->neighbor->nodep, portp->neighbor); + + if (neighborPortAsyncSC2VL) + return SC2VL_UPDATE_TYPE_ASYNC; + } + + return SC2VL_UPDATE_TYPE_NONE; +} + +/* Port Iterator structure to hold information of the port being iterated */ +typedef struct _PortIteratorData +{ + boolean lastPortFlag; +}PortIteratorData; + +/* Port List Iterator structure to hold information of the port List being iterated */ +typedef struct _PortListIteratorData +{ + LIST_ITERATOR currentPort; +}PortListIteratorData; + +/* Node Iterator structure to hold information of the node being iterated */ +typedef struct _NodeIteratorData +{ + boolean lastNodeFlag; + cl_map_item_t *pCurrentPort; +}NodeIteratorData; + +/* Node List Iterator structure to hold information of the node list being iterated */ +typedef struct _NodeListIteratorData +{ + LIST_ITERATOR currentNode; + cl_map_item_t *pCurrentPort; +}NodeListIteratorData; + +/* Ioc Iterator structure to hold information of the Ioc being iterated */ +#if !defined(VXWORKS) || defined(BUILD_DMC) +typedef struct _IocIteratorData +{ + boolean lastIocFlag; + cl_map_item_t *pCurrentPort; +}IocIteratorData; + +/* Ioc List Iterator structure to hold information of the Ioc Lst being iterated */ +typedef struct _IocListIteratorData +{ + LIST_ITERATOR currentNode; + cl_map_item_t *pCurrentPort; +}IocListIteratorData; +#endif + +/* System Iterator structure to hold information of the system being iterated */ +typedef struct _SystemListIteratorData +{ + boolean lastSystemFlag; + cl_map_item_t *pCurrentNode; + cl_map_item_t *pCurrentPort; +}SystemListIteratorData; + +/* Iterator structure to hold information of the point being iterated */ +typedef struct _FIPortIterator +{ + Point *pPoint; + union { + PortIteratorData PortIter; + NodeIteratorData NodeIter; +#if !defined(VXWORKS) || defined(BUILD_DMC) + IocIteratorData IocIter; + IocListIteratorData IocListIter; +#endif + SystemListIteratorData SystemIter; + NodeListIteratorData NodeListIter; + PortListIteratorData PortListIter; + } u; +}FIPortIterator; + +/*Finds the next non-SW port for each type in the point*/ +extern PortData *FIPortIteratorHead(FIPortIterator *pFIPortIterator, Point *pFocus); +/* Finds the first non-SW port for each type in the point.*/ +extern PortData *FIPortIteratorNext(FIPortIterator *pFIPortIterator); + +#ifdef __cplusplus +}; +#endif + +#endif /* _TOPOLOGY_H */ diff --git a/Topology/topology_internal.h b/Topology/topology_internal.h new file mode 100644 index 0000000..88105ee --- /dev/null +++ b/Topology/topology_internal.h @@ -0,0 +1,85 @@ +/* BEGIN_ICS_COPYRIGHT7 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT7 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +#ifndef _TOPOLOGY_INTERNAL_H +#define _TOPOLOGY_INTERNAL_H + +#include + +// unpublished interfaces internal to topology library +#ifdef __cplusplus +extern "C" { +#endif + +#define MYTAG MAKE_MEM_TAG('T','o', 'p', 'o') + +#define PROGRESS_FREQ 25 // how many nodes between progress reports + +extern const char *g_Top_cmdname; +extern Top_FreeCallbacks g_Top_FreeCallbacks; + +extern void PortDataFree(FabricData_t *fabricp, PortData *portp); +extern FSTATUS AllLidsAdd(FabricData_t *fabricp, PortData *portp, boolean force); +extern void AllLidsRemove(FabricData_t *fabricp, PortData *portp); +#if !defined(VXWORKS) || defined(BUILD_DMC) +extern void IocDataFree(FabricData_t *fabricp, IocData *iocp); +extern void IouDataFreeIocs(FabricData_t *fabricp, IouData *ioup); +extern void IouDataFree(FabricData_t *fabricp, IouData *ioup); +#endif +extern void NodeDataFreePorts(FabricData_t *fabricp, NodeData *nodep); +extern void NodeDataFreeSwitchData(FabricData_t *fabricp, NodeData *nodep); +extern void NodeDataFree(FabricData_t *fabricp, NodeData *nodep); +extern void NodeDataFreeAll(FabricData_t *fabricp); +extern void SMDataFree(FabricData_t *fabricp, SMData *smp); +extern void SMDataFreeAll(FabricData_t *fabricp); +extern void MCDataFreeAll(FabricData_t *fabricp); +extern void MCMemberFree(FabricData_t *fabricp, McMemberData *mcmemberp); +extern void VFDataFreeAll(FabricData_t *fabricp); +extern void MCGroupFree(FabricData_t *fabricp, McGroupData *mcgroupp); +extern void CableDataFree(CableData *cablep); +extern void PortSelectorFree(PortSelector *portselp); +extern void ExpectedLinkFree(FabricData_t *fabricp, ExpectedLink *elinkp); +extern void ExpectedLinkFreeAll(FabricData_t *fabricp); +extern void ExpectedNodeFree(FabricData_t *fabricp, ExpectedNode *enodep, QUICK_LIST *listp); +extern void ExpectedNodesFreeAll(FabricData_t *fabricp, QUICK_LIST *listp); +extern void ExpectedSMFree(FabricData_t *fabricp, ExpectedSM *esmp); +extern void ExpectedSMsFreeAll(FabricData_t *fabricp); + +// create SystemData as needed +// add this Node to the appropriate System +// This should only be invoked once per node (eg. not per NodeRecord) +extern FSTATUS AddSystemNode(FabricData_t *fabricp, NodeData *nodep); + +#ifdef __cplusplus +}; +#endif + +#endif /* _TOPOLOGY_INTERNAL_H */ diff --git a/Topology/util.c b/Topology/util.c new file mode 100644 index 0000000..3df7e97 --- /dev/null +++ b/Topology/util.c @@ -0,0 +1,97 @@ +/* BEGIN_ICS_COPYRIGHT7 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT7 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +#include "topology.h" +#include "topology_internal.h" + +extern int vsnprintf (char *, size_t, const char *, va_list); + +#define ESC "\033[" +#define LINE_LEN 80 + +const char *g_Top_cmdname = "Topology"; // our default +Top_FreeCallbacks g_Top_FreeCallbacks = {}; + +/* output a progress message. The message should not include a newline + * This is intended to allow for overlapping progress messages + * those without a newline will be written by the next message + * if a newline is desired after the message pass newline=TRUE + */ +void ProgressPrint(boolean newline, const char *format, ...) +{ + va_list args; + static char buffer[LINE_LEN]; + static int first_progress = 1; // has 1st progress been output yet + + va_start(args, format); + vsnprintf(buffer, sizeof(buffer), format, args); + va_end(args); + if (first_progress) { + first_progress = 0; + } else { + fprintf(stderr, ESC "%dD", LINE_LEN); + } + fprintf(stderr, "%-*s", LINE_LEN, buffer); + if (newline) { + first_progress = 1; + fprintf(stderr, "\n"); + } + fflush(stderr); +} + +// truncate a str to fit within LINE_LEN-20 characters +// useful for inclusion of strings and filenames in otherwise +// brief ProgressPrint output +// uses statics, so not thread safe and can't be used multiple times in one +// function call's arguments +const char* Top_truncate_str(const char *name) +{ + int len = strlen(name); + if (len <= (LINE_LEN-20)) { + return name; + } else { + static char buf[LINE_LEN-19]; + + snprintf(buf, sizeof(buf), "...%s", name+len-(LINE_LEN-23)); + return buf; + } +} + +// set command name to be used for error messages +void Top_setcmdname(const char *name) +{ + g_Top_cmdname = name; +} + +void Top_setFreeCallbacks(Top_FreeCallbacks *callbacks) +{ + g_Top_FreeCallbacks = *callbacks; +} diff --git a/Xml/Makefile b/Xml/Makefile new file mode 100644 index 0000000..23876f0 --- /dev/null +++ b/Xml/Makefile @@ -0,0 +1,194 @@ +# Makefile for Xml + +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# Include Make Control Settings +include $(TL_DIR)/$(PROJ_FILE_DIR)/Makesettings.project + +#=============================================================================# +# Definitions: +#-----------------------------------------------------------------------------# + +# Name of SubProjects +DS_SUBPROJECTS = +# name of executable or downloadable image +EXECUTABLE = # Xml$(EXE_SUFFIX) + +# list of sub directories to build +# Roll our own build of expat for VxWorks +ifeq "$(BUILD_TARGET_OS)" "VXWORKS" +DIRS = \ + XmlParser +endif +ifneq "$(BUILD_TARGET_OS)" "VXWORKS" +DIRS += \ + xml_sample \ + xml_sample2 \ + opaxmlindent +endif + +# C files (.c) +CFILES = \ + ixml.c \ + ixml_err.c \ + ixml_ib.c \ + # Add more c files here + +# NOTE: for old MIPS config_compression is with ssecure/sshield; for new, +# it is in Xml directory itself +ifeq (ATOM,$(BUILD_TARGET)) +CFILES += \ + config_compression.c \ + # Add more c files here +endif + +# C++ files (.cpp) +CCFILES = \ + # Add more cpp files here +# lex files (.lex) +LFILES = \ + # Add more lex files here +# archive library files (basename, $ARFILES will add MOD_LIB_DIR/prefix and suffix) +ifeq "$(BUILD_TARGET_OS)" "VXWORKS" +LIBFILES = XmlParser +endif +# Windows Resource Files (.rc) +RSCFILES = +# Windows IDL File (.idl) +IDLFILE = +# Windows Linker Module Definitions (.def) file for dll's +DEFFILE = +# targets to build during INCLUDES phase (add public includes here) +INCLUDE_TARGETS = \ + ixml.h \ + ixml_ib.h \ + # Add more h hpp files here +# NOTE: for old MIPS config_compression is with ssecure/sshield; for new, +# it is in Xml directory itself +ifeq (ATOM,$(BUILD_TARGET)) +INCLUDE_TARGETS += \ + config_compression.h +endif +# Non-compiled files +MISC_FILES = +# all source files +SOURCES = $(CFILES) $(CCFILES) $(LFILES) $(RSCFILES) $(IDLFILE) +# Source files to include in DSP File +DSP_SOURCES = $(INCLUDE_TARGETS) $(SOURCES) $(MISC_FILES) \ + $(RSCFILES) $(DEFFILE) $(MAKEFILE) +# all object files +OBJECTS = $(CFILES:.c=$(OBJ_SUFFIX)) $(CCFILES:.cpp=$(OBJ_SUFFIX)) \ + $(LFILES:.lex=$(OBJ_SUFFIX)) +RSCOBJECTS = $(RSCFILES:.rc=$(RES_SUFFIX)) +# targets to build during LIBS phase +LIB_TARGETS_IMPLIB = +LIB_TARGETS_ARLIB = $(LIB_PREFIX)Xml$(ARLIB_SUFFIX) +LIB_TARGETS_EXP = $(LIB_TARGETS_IMPLIB:$(ARLIB_SUFFIX)=$(EXP_SUFFIX)) +LIB_TARGETS_MISC = +# targets to build during CMDS phase +SHLIB_VERSION = +CMD_TARGETS_SHLIB = +CMD_TARGETS_EXE = $(EXECUTABLE) +CMD_TARGETS_MISC = +CMD_TARGETS_DRIVER = +CMD_TARGETS_KEXT = +# files to remove during clean phase +CLEAN_TARGETS_MISC = +CLEAN_TARGETS = $(OBJECTS) $(RSCOBJECTS) $(IDL_TARGETS) $(CLEAN_TARGETS_MISC) +# other files to remove during clobber phase +CLOBBER_TARGETS_MISC= +# sub-directory to install to within bin +BIN_SUBDIR = +# sub-directory to install to within include +INCLUDE_SUBDIR = + +# Additional Settings +#CLOCALDEBUG = User defined C debugging compilation flags [Empty] +#CCLOCALDEBUG = User defined C++ debugging compilation flags [Empty] +#CLOCAL = User defined C flags for compiling [Empty] +#CCLOCAL = User defined C++ flags for compiling [Empty] +#BSCLOCAL = User flags for Browse File Builder [Empty] +#DEPENDLOCAL = user defined makedepend flags [Empty] +#LINTLOCAL = User defined lint flags [Empty] +#LOCAL_INCLUDE_DIRS = User include directories to search for C/C++ headers [Empty] +#LDLOCAL = User defined C flags for linking [Empty] +#IMPLIBLOCAL = User flags for Object Lirary Manager [Empty] +#MIDLLOCAL = User flags for IDL compiler [Empty] +#RSCLOCAL = User flags for resource compiler [Empty] +#LOCALDEPLIBS = User libraries to include in dependencies [Empty] +#LOCALLIBS = User libraries to use when linking [Empty] +# (in addition to LOCALDEPLIBS) +#LOCAL_LIB_DIRS = User library directories for libpaths [Empty] + +CLOCAL = $(CPIE) + +LOCALDEPLIBS = +ifneq (ATOM,$(BUILD_TARGET)) +CLOCAL += -I$(TL_DIR)/tmsTarget/src/ssecure/sshield/include +endif + +# Include Make Rules definitions and rules +include $(TL_DIR)/$(PROJ_FILE_DIR)/Makerules.project + +#=============================================================================# +# Overrides: +#-----------------------------------------------------------------------------# +#CCOPT = # C++ optimization flags, default lets build config decide +#COPT = # C optimization flags, default lets build config decide +#SUBSYSTEM = Subsystem to build for (none, console or windows) [none] +# (Windows Only) +#USEMFC = How Windows MFC should be used (none, static, shared, no_mfc) [none] +# (Windows Only) +#=============================================================================# + +#=============================================================================# +# Rules: +#-----------------------------------------------------------------------------# +# process Sub-directories +include $(TL_DIR)/Makerules/Maketargets.toplevel + +# build cmds and libs +include $(TL_DIR)/Makerules/Maketargets.build + +# install for includes, libs and cmds phases +include $(TL_DIR)/Makerules/Maketargets.install + +# install for stage phase +#include $(TL_DIR)/Makerules/Maketargets.stage +STAGE:: + +# Unit test execution +#include $(TL_DIR)/Makerules/Maketargets.runtest + +#=============================================================================# + +#=============================================================================# +# DO NOT DELETE THIS LINE -- make depend depends on it. +#=============================================================================# diff --git a/Xml/README b/Xml/README new file mode 100644 index 0000000..0a1d49e --- /dev/null +++ b/Xml/README @@ -0,0 +1 @@ +Xml parser and generation library diff --git a/Xml/config_compression.c b/Xml/config_compression.c new file mode 100755 index 0000000..bc1da1b --- /dev/null +++ b/Xml/config_compression.c @@ -0,0 +1,422 @@ +/* BEGIN_ICS_COPYRIGHT5 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + * ** END_ICS_COPYRIGHT5 ****************************************/ +/* [ICS VERSION STRING: unknown] */ + +/* THIS IS USED ONLY IN STL1 AND LATER */ + +#include "vxWorks.h" +#include "stdio.h" +#include "stdlib.h" +#include "string.h" +#include "taskLib.h" +#include "time.h" +#include "tms/common/rdHelper.h" +#include "tms/idb/icsUiConfigMib.h" +#include "tms/common/usrSecLib.h" +#include "bspcommon/h/sysPrintf.h" +#include "bspcommon/h/icsBspUtil.h" +#include "bspcommon/h/sysFlash.h" + +#include "config_compression.h" + +extern int UiUtil_GetLocalTime (); + +static int debug_comp; + +#define COPYBUFFER_SIZE 2048 +#define UNCOMPRESSED_ARRAY_SIZE 2048 +#define COMPRESSED_ARRAY_SIZE 2048 + +#define SCP_LOG( fmt, func, args... ) \ + do{ \ + if( debug_comp ) { \ + sysPrintf("task=%s %s : " fmt "\n", taskName(taskIdSelf()), func, ## args ); \ + } \ + } while(0) + +// unfortunately we can't #include zlib.h or we have multiple definitions for crc32 +#undef compress +extern int compress(char *dest, int *destLen, char *src, int sourceLen); + +typedef struct compBlockHeader { + int compressedBytes; + int uncompressedBytes; +} compBlockHeader_t; + +#define COMP_VERSION 0 + +typedef struct compFileHeader { + int version; + time_t creationTime; +} compFileHeader_t; + +typedef struct { + FILE *fdin; + int leftOverBytes; + int endOfCompressedFile; + char uncompressedBytesArray[UNCOMPRESSED_ARRAY_SIZE]; + char compressedBytesArray[COMPRESSED_ARRAY_SIZE]; +} compFile_t; + +// TEST CODE START +//SCP_LOG("ATTEMPTING TEST TO TEST.XML", __FUNCTION__); +// FILE *fileIn = openUncompressedFile(outfilename); +// FILE *fileOut = fopen("/firmware/test.xml", "wb"); +// int totalBytes = 0; +// while (!feof(fileIn)) { +// char testBuffer[2049]; +// int bytesRead = readUncompressedBytes(fileIn, testBuffer, sizeof(testBuffer)); +// totalBytes += bytesRead; +// SCP_LOG("READ %d BYTES UNCOMPRESSED", bytesRead, __FUNCTION__); +// fwrite((void*)testBuffer, 1, bytesRead, fileOut); +// if (bytesRead < sizeof(testBuffer)) +// break; +// }; +// SCP_LOG("TOTAL BYTES %d", totalBytes, __FUNCTION__); +// fclose(fileOut); +// closeUncompressedFile(fileIn); +// TES TCODE END + + +int copyFile(char *src, char*dst, int compressFlag, long *compressedFileSize) { + // compress = 1 means inflate + // compress = 0 means just copy + // compress = -1 means deflate + time_t timeStamp; + char *copyBuffer1 = NULL; + char *copyBuffer2 = NULL; + char *uncompressedBytesArray = NULL; + char *compressedBytesArray = NULL; + + copyBuffer1 = malloc(COPYBUFFER_SIZE); + copyBuffer2 = malloc(COPYBUFFER_SIZE); + uncompressedBytesArray = malloc(UNCOMPRESSED_ARRAY_SIZE); + compressedBytesArray = malloc(COMPRESSED_ARRAY_SIZE); + + if ((copyBuffer1 == NULL) || (copyBuffer2 == NULL) || + (uncompressedBytesArray == NULL) || (compressedBytesArray == NULL)) { + if (copyBuffer1 != NULL) + free(copyBuffer1); + if (copyBuffer2 != NULL) + free(copyBuffer2); + if (uncompressedBytesArray != NULL) + free(uncompressedBytesArray); + if (compressedBytesArray != NULL) + free(compressedBytesArray); + SCP_LOG("out of memory in copyFile", __FUNCTION__); + } + SCP_LOG("CopyFile src:%s, dst:%s, compressFlag:%d", __FUNCTION__, src, dst, compressFlag); + size_t bufsize = COPYBUFFER_SIZE; + + int retVal = 0; + int didFileHeader = 0; + + FILE *fdout; + + if (compressedFileSize != NULL) + *compressedFileSize = 0; + + fdout = fopen(dst, "w"); + // if we are out of space, try removing the original first and reopening the file + if (fdout == NULL) { + FileRemove(dst); + fdout = fopen(dst, "w"); + } + if (fdout != NULL) { + SCP_LOG("OPENED! output file %s", __FUNCTION__, dst); + FILE *fdin; + if (NULL != (fdin = fopen(src, "r"))) { + SCP_LOG("OPENED! input %s", __FUNCTION__, src); + while (!feof(fdin)) { + int bytes = 0; + if (compressFlag == 0) { + bytes = fread((void*)copyBuffer1, 1, bufsize, fdin); + SCP_LOG("READ %d bytes when tried %d bytes", __FUNCTION__, bytes, bufsize); + } + if (compressFlag < 0) { + if (!didFileHeader) { + compFileHeader_t header; + if(UiUtil_GetLocalTime( &timeStamp) == 0){ + header.creationTime = timeStamp; + } + else { + header.creationTime = time(NULL); + } + header.version = COMP_VERSION; + int bout = fwrite((void*)&header, 1, sizeof(compFileHeader_t), fdout); + if (bout != sizeof(compFileHeader_t)) { + SCP_LOG("Tried to write %d bytes to %s and only wrote %d", __FUNCTION__, sizeof(compFileHeader_t), dst, bout); + retVal = -1; + break; + } else { + SCP_LOG("Wrote file header to %s", __FUNCTION__, dst); + } + didFileHeader = 1; + } + + bytes = fread((void*)copyBuffer1, 1, bufsize, fdin); + SCP_LOG("READ %d bytes when tried %d bytes", __FUNCTION__, bytes, bufsize); + int compLen = bytes; + compress(copyBuffer2, &compLen, copyBuffer1, bytes); + SCP_LOG("Compressed %d bytes into %d bytes", __FUNCTION__, bytes, compLen); + if (bytes == compLen) { + SCP_LOG("No compression needed for this block.", __FUNCTION__); + memcpy(copyBuffer2, copyBuffer1, bytes); + } + compBlockHeader_t *header = (compBlockHeader_t*)copyBuffer1; + header->compressedBytes = compLen; + header->uncompressedBytes = bytes; + char *startOfData = copyBuffer1+sizeof(compBlockHeader_t); + memcpy(startOfData, copyBuffer2, compLen); + bytes = sizeof(compBlockHeader_t)+compLen; + if (compressedFileSize != NULL) { + *compressedFileSize += (long)bytes;; + } + } + if (compressFlag > 0) { + if (!didFileHeader) { + compFileHeader_t header; + if (fread((void*)&header, 1, sizeof(compFileHeader_t), fdin) != sizeof(compFileHeader_t)) { + SCP_LOG("Tried to READ %d bytes of header and didn't", __FUNCTION__, sizeof(compFileHeader_t)); + break; + } + if (header.version != COMP_VERSION) { + SCP_LOG("Unsuported compress file verison %d", __FUNCTION__, header.version); + retVal = -1; + break; + } + didFileHeader = 1; + } + compBlockHeader_t header; + if (fread((void*)&header, 1, sizeof(compBlockHeader_t), fdin) != sizeof(compBlockHeader_t)) { + SCP_LOG("Tried to READ %d bytes of header and didn't", __FUNCTION__, sizeof(compBlockHeader_t)); + break; + } + SCP_LOG("READ %d bytes of header. %d compressed bytes and %d uncompressed bytes", __FUNCTION__, sizeof(compBlockHeader_t), header.compressedBytes, header.uncompressedBytes); + if ((header.compressedBytes == 0) && (header.uncompressedBytes == 0)) { + SCP_LOG("Tail header read. EOF!", __FUNCTION__); + break; + } + if ((header.compressedBytes > COMPRESSED_ARRAY_SIZE) || (header.compressedBytes <= 0)) { + SCP_LOG("Compressed bytes should be 0-%d and it's %d", __FUNCTION__, COMPRESSED_ARRAY_SIZE, header.compressedBytes); + retVal = -1; + break; + } + if ((header.uncompressedBytes > UNCOMPRESSED_ARRAY_SIZE) || (header.uncompressedBytes <= 0)) { + SCP_LOG("Uncompressed bytes should be 1-%d and it's %d", __FUNCTION__, UNCOMPRESSED_ARRAY_SIZE, header.uncompressedBytes); + retVal = -1; + break; + } + if (fread(copyBuffer1, 1, header.compressedBytes, fdin) != header.compressedBytes) { + SCP_LOG("Tried to READ %d bytes of data and didn't", __FUNCTION__, header.compressedBytes); + retVal = -1; + break; + } + SCP_LOG("READ %d bytes of data.", __FUNCTION__, header.compressedBytes); + if (header.uncompressedBytes > header.compressedBytes) { + SCP_LOG("About to decompress %d bytes", __FUNCTION__, header.compressedBytes); + int uncompBytes = inflater(copyBuffer2, COPYBUFFER_SIZE, copyBuffer1, header.compressedBytes); + SCP_LOG("Decompressed %d bytes into %d bytes", __FUNCTION__, header.compressedBytes, uncompBytes); + memcpy(copyBuffer1, copyBuffer2, uncompBytes); + SCP_LOG("DECOMP:%2048s", __FUNCTION__, dst); + bytes = uncompBytes; + } else { + SCP_LOG("NO DECOMP NEEDED.", __FUNCTION__); + bytes = header.compressedBytes; + } + } + if (bytes > 0) { + SCP_LOG("Writing %d bytes to %s", __FUNCTION__, bytes, dst); + int bout = fwrite((void*)copyBuffer1, 1, bytes, fdout); + if (bout != bytes) { + SCP_LOG("Tried to write %d bytes to %s and only wrote %d", __FUNCTION__, bytes, dst, bout); + retVal = -1; + break; + } else { + SCP_LOG("Wrote %d bytes to %s", __FUNCTION__, bytes, dst); + } + } else {break;} + } + if (compressFlag < 0) { + compBlockHeader_t tailHeader; + tailHeader.compressedBytes = 0; + tailHeader.uncompressedBytes = 0; + int bout = fwrite((void*)&tailHeader, 1, sizeof(compBlockHeader_t), fdout); + if (bout != sizeof(compBlockHeader_t)) { + SCP_LOG("Tried to write tail header to %s and only wrote %d", __FUNCTION__, dst, bout); + retVal = -1; + } else { + if (compressedFileSize != NULL) { + *compressedFileSize += (long)bout; + } + SCP_LOG("Wrote tail header to %s", __FUNCTION__, dst); + } + } + fclose(fdin); + SCP_LOG("Closed fdin", __FUNCTION__); + } else { + SCP_LOG("Unable to fopen input file %s", __FUNCTION__, src); + retVal = -1; + } + + fclose(fdout); + SCP_LOG("Closed fdout", __FUNCTION__); + } else { + SCP_LOG("Unable to fopen %s as writeable.", __FUNCTION__, dst); + retVal = -1; + } + SCP_LOG("CopyFile returning %d", __FUNCTION__, retVal); + free(compressedBytesArray); + free(uncompressedBytesArray); + free(copyBuffer2); + free(copyBuffer1); + + return retVal; +} + +FILE* openUncompressedFile(char *filename, time_t *time) { + compFile_t *cf; + SCP_LOG("openUncompressedFile:%s", __FUNCTION__, filename); + + cf = (compFile_t *)calloc(1, sizeof(compFile_t)); + if (cf == NULL) + return NULL; + + cf->fdin = fopen(filename, "r"); + if (cf->fdin != NULL) { + compFileHeader_t header; + if (fread(&header, 1, sizeof(compFileHeader_t), cf->fdin) == sizeof(compFileHeader_t)) { + if (time != NULL) + *time = header.creationTime; + return (FILE *)cf; + } + fclose(cf->fdin); + SCP_LOG("openUncompressedFile: Unable to read file header for %s.", __FUNCTION__, filename); + } + free(cf); + return NULL; +} + +void closeUncompressedFile(FILE *fileIn) { + compFile_t *cf = (compFile_t *)fileIn; + SCP_LOG("closeUncompressedFile", __FUNCTION__); + fclose(cf->fdin); + free(cf); +} + +int readUncompressedBytes(FILE *fileIn, char *buffer, int bufsize) { + compFile_t *cf = (compFile_t *)fileIn; + compBlockHeader_t header; + int bufferIndex = 0; + + SCP_LOG("readUncompressedBytes bufsize:%d", __FUNCTION__, bufsize); + if (cf->leftOverBytes > 0) { + SCP_LOG("LEFT OVER BYTES: %d bytes", __FUNCTION__, cf->leftOverBytes); + if (cf->leftOverBytes >= bufsize) { + SCP_LOG("COPYING %d BYTES TO BUFFER", __FUNCTION__, bufsize); + memcpy(buffer, cf->uncompressedBytesArray, bufsize); + cf->leftOverBytes -= bufsize; + SCP_LOG("SLIDDING UP uncompressedBytesArray buffer from %d to 0.", __FUNCTION__, bufsize); + memcpy(cf->uncompressedBytesArray, &cf->uncompressedBytesArray[bufsize], cf->leftOverBytes); + SCP_LOG("RETURNING %d BYTES READ", __FUNCTION__, bufsize); + return bufsize; + } else { + SCP_LOG("COPYING %d BYTES TO BUFFER", __FUNCTION__, cf->leftOverBytes); + memcpy(buffer, cf->uncompressedBytesArray, cf->leftOverBytes); + bufferIndex = cf->leftOverBytes; + SCP_LOG("bufferIndex=%d", __FUNCTION__, bufferIndex); + cf->leftOverBytes = 0; + } + } + + while((bufferIndex < bufsize) && !feof(cf->fdin) && !cf->endOfCompressedFile) { + SCP_LOG("bufferIndex=%d", __FUNCTION__, bufferIndex); + int bread = fread(&header, 1, sizeof(compBlockHeader_t), cf->fdin); + if (bread != sizeof(compBlockHeader_t)) { + SCP_LOG("Tried to read header of %d bytes and read %d!", __FUNCTION__, sizeof(compBlockHeader_t), bread); + // should have got a tail header! + return -1; + } + SCP_LOG("header.uncompressedBytes=%d header.compressedBytes=%d", __FUNCTION__, header.uncompressedBytes, header.compressedBytes); + if ((header.uncompressedBytes == 0) && (header.compressedBytes == 0)) { + // no more blocks + cf->endOfCompressedFile = 1; + SCP_LOG("Read tail header. EOF!", __FUNCTION__); + break; + } + if ((header.uncompressedBytes > UNCOMPRESSED_ARRAY_SIZE) || (header.uncompressedBytes <= 0)) { + SCP_LOG("Uncompressed bytes should be 1-%d and it's %d", __FUNCTION__, UNCOMPRESSED_ARRAY_SIZE, header.uncompressedBytes); + return -1; + } + if ((header.compressedBytes > COMPRESSED_ARRAY_SIZE) || (header.compressedBytes <= 0)) { + SCP_LOG("Compressed bytes should be 1-%d and it's %d", __FUNCTION__, COMPRESSED_ARRAY_SIZE, header.compressedBytes); + return -1; + } + if (fread(cf->compressedBytesArray, 1, header.compressedBytes, cf->fdin) != header.compressedBytes) { + SCP_LOG("Unable to read %d compressed bytes", __FUNCTION__, header.compressedBytes); + return -1; + } + SCP_LOG("READ %d COMPRESSED BYTES", __FUNCTION__, header.compressedBytes); + int bytesToCopy = 0; + int uncompBytes = header.compressedBytes; + if (header.compressedBytes < header.uncompressedBytes) { + uncompBytes = inflater(cf->uncompressedBytesArray, UNCOMPRESSED_ARRAY_SIZE, + cf->compressedBytesArray, header.compressedBytes); + SCP_LOG("DECOMPRESSED %d BYTES INTO %d BYTES", __FUNCTION__, header.compressedBytes, uncompBytes); + if (uncompBytes < 0) + return -1; + bytesToCopy = uncompBytes; + } else { + // this block is not compressed, just copy it + memcpy(cf->uncompressedBytesArray, cf->compressedBytesArray, header.compressedBytes); + bytesToCopy = header.compressedBytes; + } + if (uncompBytes + bufferIndex > bufsize) { + // we have extra bytes. Save them for the next call. + bytesToCopy = bufsize - bufferIndex; + cf->leftOverBytes = uncompBytes - bytesToCopy; + } + SCP_LOG("COPYING %d BYTES FROM uncompressedBytesArray TO BUFFER[%d]", __FUNCTION__, bytesToCopy, bufferIndex); + memcpy(&buffer[bufferIndex], cf->uncompressedBytesArray, bytesToCopy); + if (cf->leftOverBytes > 0) { + SCP_LOG("LEFT OVER BYTES. COPYING %d BYTES FROM %d TO 0.", __FUNCTION__, cf->leftOverBytes, bytesToCopy); + memcpy(cf->uncompressedBytesArray, &cf->uncompressedBytesArray[bytesToCopy], cf->leftOverBytes); + } + bufferIndex += bytesToCopy; + SCP_LOG("bufferIndex is now:%d", __FUNCTION__, bufferIndex); + } + SCP_LOG("EXIT: bufferIndex is now:%d", __FUNCTION__, bufferIndex); + if (bufferIndex > 0 ) { + if (bufferIndex < bufsize) { + buffer[bufferIndex] = 0; + } + SCP_LOG("RETURNING: %s", __FUNCTION__, buffer); + } + return bufferIndex; +} diff --git a/Xml/config_compression.h b/Xml/config_compression.h new file mode 100755 index 0000000..c990e5b --- /dev/null +++ b/Xml/config_compression.h @@ -0,0 +1,40 @@ +/* BEGIN_ICS_COPYRIGHT5 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + * ** END_ICS_COPYRIGHT5 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +/* THIS IS USED ONLY IN STL1 AND LATER */ + +int copyFile(char *src, char*dst, int compressFlag,long *fileSize); +FILE* openUncompressedFile(char *filename, time_t *time); +void closeUncompressedFile(FILE *fileIn); +int readUncompressedBytes(FILE *fileIn,char *buffer, int bufsize); + +/* scpFastFabricRetCode_t is now in sftp.h */ + diff --git a/Xml/ixml.c b/Xml/ixml.c new file mode 100644 index 0000000..17110df --- /dev/null +++ b/Xml/ixml.c @@ -0,0 +1,1669 @@ +/* BEGIN_ICS_COPYRIGHT5 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + * ** END_ICS_COPYRIGHT5 ****************************************/ +/* [ICS VERSION STRING: unknown] */ + +#include +#include +#if !defined(VXWORKS) || defined(BUILD_DMC) +#include +#endif +#include +#include +#include +#include +#include +#define _GNU_SOURCE + +#include "ixml.h" +#ifdef VXWORKS +#include "config_compression.h" +int snprintf(char *str, size_t count, const char *fmt, ...); +int vsnprintf(char *str, size_t count, const char *fmt, + va_list arg); +#endif + +#define MYTAG MAKE_MEM_TAG('l','x', 'm', 'l') + +/* should be defined in ib_dm.h */ +#ifndef IOC_IDSTRING_SIZE +#define IOC_IDSTRING_SIZE 64 +#endif +#ifndef IOC_SERVICE_NAME_SIZE +#define IOC_SERVICE_NAME_SIZE 40 +#endif + +extern void IXmlPrintFileError(const char *input_file, IXmlParserPrintMessage printError); + +/****************************************************************************/ +/* XML Init */ + +/* indent is additional indent per level */ +void +IXmlInit(IXmlOutputState_t *state, FILE *file, unsigned indent, + IXmlOutputFlags_t flags, void *context) +{ + state->file = file; + state->indent = indent; + state->flags = flags; + state->cur_indent = 0; + state->context = context; +} + +/****************************************************************************/ +/* XML Output */ + +/* indent is additional indent per level */ +FSTATUS +IXmlOutputInit(IXmlOutputState_t *state, FILE *file, unsigned indent, + IXmlOutputFlags_t flags, void *context) +{ + IXmlInit(state, file, indent, flags, context); + IXmlOutputPrint(state, "\n"); + state->flags &= ~IXML_OUTPUT_FLAG_HAD_CONTENT; // should not be content + return (IXmlOutputFailed(state)?FERROR:FSUCCESS); +} + +void +IXmlOutputDestroy(IXmlOutputState_t *state) +{ + state->file = NULL; // make sure can't be used by mistake + state->context = NULL; // make sure can't be used by mistake +} + +// output to output file +void IXmlOutputPrint(IXmlOutputState_t *state, const char *format, ...) +{ + va_list args; + + if (state->flags & IXML_OUTPUT_FLAG_IN_START_TAG) { + fprintf(state->file, ">"); + state->flags &= ~IXML_OUTPUT_FLAG_IN_START_TAG; + } + + va_start(args, format); + + state->flags &= ~IXML_OUTPUT_FLAG_START_NEED_NL; + state->flags |= IXML_OUTPUT_FLAG_HAD_CONTENT; // could be content + vfprintf(state->file, format, args); + va_end(args); +} + +// output to output file with present indent preceeding output +void IXmlOutputPrintIndent(IXmlOutputState_t *state, const char *format, ...) +{ + va_list args; + + va_start(args, format); + + if (state->flags & IXML_OUTPUT_FLAG_IN_START_TAG) { + fprintf(state->file, ">"); + state->flags &= ~IXML_OUTPUT_FLAG_IN_START_TAG; + } + + if (state->flags & IXML_OUTPUT_FLAG_START_NEED_NL) { + fprintf(state->file, "\n"); + state->flags &= ~IXML_OUTPUT_FLAG_START_NEED_NL; + } + state->flags &= ~IXML_OUTPUT_FLAG_HAD_CONTENT; // should not be content + fprintf(state->file, "%*s", state->cur_indent, ""); + vfprintf(state->file, format, args); + va_end(args); +} + +void IXmlOutputNoop(IXmlOutputState_t *state, const char *tag, void *data) +{ +} + +void IXmlOutputStartTag(IXmlOutputState_t *state, const char *tag) +{ + IXmlOutputPrintIndent(state, "<%s", tag); + state->flags |= IXML_OUTPUT_FLAG_IN_START_TAG; + state->flags |= IXML_OUTPUT_FLAG_START_NEED_NL; + state->flags &= ~IXML_OUTPUT_FLAG_HAD_CONTENT; // no content yet + state->cur_indent += state->indent; +} + +void IXmlOutputStartAttrTag(IXmlOutputState_t *state, const char *tag, void *data, IXML_FORMAT_ATTR_FUNC attr_func) +{ + if (attr_func) { + IXmlOutputPrintIndent(state, "<%s", tag); + (*attr_func)(state, data); + IXmlOutputPrint(state, ">"); + // clear flags after attr_func in case attr_func calls OutputPrint + state->flags |= IXML_OUTPUT_FLAG_START_NEED_NL; + state->flags &= ~IXML_OUTPUT_FLAG_HAD_CONTENT; // no content yet + state->cur_indent += state->indent; + } else { + IXmlOutputStartTag(state, tag); + } +} + +FSTATUS IXmlOutputAttr(IXmlOutputState_t *state, const char *attr, + const char *val) +{ + return IXmlOutputAttrFmt(state, attr, "%s", val); +} + +FSTATUS IXmlOutputAttrFmt(IXmlOutputState_t *state, const char *attr, + const char *format, ...) +{ + va_list args; + + if (!(state->flags & IXML_OUTPUT_FLAG_IN_START_TAG)) + return FERROR; + + va_start(args, format); + + fprintf(state->file, " %s=\"", attr); + vfprintf(state->file, format, args); + fprintf(state->file, "\""); + va_end(args); + + return FSUCCESS; +} + +void IXmlOutputEndTag(IXmlOutputState_t *state, const char *tag) +{ + if (state->cur_indent > state->indent) + state->cur_indent -= state->indent; + else + state->cur_indent = 0; + // if there was content output we can close + // tag on same line as the content, otherwise it was a list + // and we output end tag on a new line with indent + // Note: output of "empty content tags" should do an IXmlOutputPrint + // or IXmlOutputPrintStr with an empty string so flags indicate intent for + // tag to have content + if (state->flags & IXML_OUTPUT_FLAG_HAD_CONTENT) + IXmlOutputPrint(state, "\n", tag); + else + IXmlOutputPrintIndent(state, "\n", tag); + state->flags &= ~IXML_OUTPUT_FLAG_HAD_CONTENT; // closed tag +} + +void IXmlOutputEndTagWithLineno(IXmlOutputState_t *state, const char *tag, unsigned long lineno) +{ + if (state->cur_indent > state->indent) + state->cur_indent -= state->indent; + else + state->cur_indent = 0; + // if there was content output we can close + // tag on same line as the content, otherwise it was a list + // and we output end tag on a new line with indent + // Note: output of "empty content tags" should do an IXmlOutputPrint + // or IXmlOutputPrintStr with an empty string so flags indicate intent for + // tag to have content + if (state->flags & IXML_OUTPUT_FLAG_HAD_CONTENT) + IXmlOutputPrint(state, "\n", tag, lineno); + else + IXmlOutputPrintIndent(state, "\n", tag, lineno); + state->flags &= ~IXML_OUTPUT_FLAG_HAD_CONTENT; // closed tag +} + +void IXmlOutputHexPad8(IXmlOutputState_t *state, const char *tag, uint8 value) +{ + IXmlOutputPrintIndent(state, "<%s>0x%02x\n", tag, value, tag); +} + +// only output if value != 0 +void IXmlOutputOptionalHexPad8(IXmlOutputState_t *state, const char *tag, uint8 value) +{ + if (value) + IXmlOutputHexPad8(state, tag, value); +} + +void IXmlOutputHexPad16(IXmlOutputState_t *state, const char *tag, uint16 value) +{ + IXmlOutputPrintIndent(state, "<%s>0x%04x\n", tag, value, tag); +} + +// only output if value != 0 +void IXmlOutputOptionalHexPad16(IXmlOutputState_t *state, const char *tag, uint16 value) +{ + if (value) + IXmlOutputHexPad16(state, tag, value); +} + +void IXmlOutputHexPad32(IXmlOutputState_t *state, const char *tag, uint32 value) +{ + IXmlOutputPrintIndent(state, "<%s>0x%08x\n", tag, value, tag); +} + +// only output if value != 0 +void IXmlOutputOptionalHexPad32(IXmlOutputState_t *state, const char *tag, uint32 value) +{ + if (value) + IXmlOutputHexPad32(state, tag, value); +} + +void IXmlOutputHexPad64(IXmlOutputState_t *state, const char *tag, uint64 value) +{ + IXmlOutputPrintIndent(state, "<%s>0x%016"PRIx64"\n", tag, value, tag); +} + +// only output if value != 0 +void IXmlOutputOptionalHexPad64(IXmlOutputState_t *state, const char *tag, uint64 value) +{ + if (value) + IXmlOutputHexPad64(state, tag, value); +} + +void IXmlOutputInt(IXmlOutputState_t *state, const char *tag, int value) +{ + IXmlOutputPrintIndent(state, "<%s>%d\n", tag, value, tag); +} + +// only output if value != 0 +void IXmlOutputOptionalInt(IXmlOutputState_t *state, const char *tag, int value) +{ + if (value) + IXmlOutputInt(state, tag, value); +} + +void IXmlOutputInt64(IXmlOutputState_t *state, const char *tag, int64 value) +{ + IXmlOutputPrintIndent(state, "<%s>%"PRId64"\n", tag, value, tag); +} + +// only output if value != 0 +void IXmlOutputOptionalInt64(IXmlOutputState_t *state, const char *tag, int64 value) +{ + if (value) + IXmlOutputInt64(state, tag, value); +} + +static void IXmlOutputIntValue(IXmlOutputState_t *state, const char *tag, int value) +{ + IXmlOutputPrintIndent(state, "<%s_Int>%d\n", tag, value, tag); +} + +void IXmlOutputUint(IXmlOutputState_t *state, const char *tag, unsigned value) +{ + IXmlOutputPrintIndent(state, "<%s>%u\n", tag, value, tag); +} + +// only output if value != 0 +void IXmlOutputOptionalUint(IXmlOutputState_t *state, const char *tag, unsigned value) +{ + if (value) + IXmlOutputUint(state, tag, value); +} + +void IXmlOutputUint64(IXmlOutputState_t *state, const char *tag, uint64 value) +{ + IXmlOutputPrintIndent(state, "<%s>%"PRIu64"\n", tag, value, tag); +} + +// only output if value != 0 +void IXmlOutputOptionalUint64(IXmlOutputState_t *state, const char *tag, uint64 value) +{ + if (value) + IXmlOutputUint64(state, tag, value); +} + +static void IXmlOutputUintValue(IXmlOutputState_t *state, const char *tag, int value) +{ + IXmlOutputPrintIndent(state, "<%s_Int>%u\n", tag, value, tag); +} + +void IXmlOutputHex(IXmlOutputState_t *state, const char *tag, unsigned value) +{ + IXmlOutputPrintIndent(state, "<%s>0x%x\n", tag, value, tag); +} + +// only output if value != 0 +void IXmlOutputOptionalHex(IXmlOutputState_t *state, const char *tag, unsigned value) +{ + if (value) + IXmlOutputHex(state, tag, value); +} + +void IXmlOutputHex64(IXmlOutputState_t *state, const char *tag, uint64 value) +{ + IXmlOutputPrintIndent(state, "<%s>0x%"PRIx64"\n", tag, value, tag); +} + +// only output if value != 0 +void IXmlOutputOptionalHex64(IXmlOutputState_t *state, const char *tag, uint64 value) +{ + if (value) + IXmlOutputHex64(state, tag, value); +} + +void IXmlOutputPrintStrLen(IXmlOutputState_t *state, const char* value, int len) +{ + state->flags &= ~IXML_OUTPUT_FLAG_START_NEED_NL; + state->flags |= IXML_OUTPUT_FLAG_HAD_CONTENT; // should be content + /* print string taking care to translate special XML characters */ + for (;len && *value; --len, ++value) { + if (*value == '&') + IXmlOutputPrint(state, "&"); + else if (*value == '<') + IXmlOutputPrint(state, "<"); + else if (*value == '>') + IXmlOutputPrint(state, ">"); + else if (*value == '\'') + IXmlOutputPrint(state, "'"); + else if (*value == '"') + IXmlOutputPrint(state, """); + else if (*value != '\n' && iscntrl(*value)) { + //table in asciitab.h indiciates character codes permitted in XML strings + //Only 3 control characters below 0x1f are permitted: + //0x9 (BT_S), 0xa (BT_LRF), and 0xd (BT_CR) + if ((unsigned char)*value <= 0x08 + || ((unsigned char)*value >= 0x0b + && (unsigned char)*value <= 0x0c) + || ((unsigned char)*value >= 0x0e + && (unsigned char)*value <= 0x1f)) { + // characters which XML does not permit in character fields + IXmlOutputPrint(state, "!"); + } else { + IXmlOutputPrint(state, "&#x%x;", (unsigned)(unsigned char)*value); + } + } else if ((unsigned char)*value > 0x7f) + // permitted but generate 2 characters back after parsing, so omit + IXmlOutputPrint(state, "!"); + else + fputc((int)(unsigned)(unsigned char)*value, state->file); + } +} + +void IXmlOutputPrintStr(IXmlOutputState_t *state, const char* value) +{ + IXmlOutputPrintStrLen(state, value, IB_INT32_MAX); +} + +void IXmlOutputStrLen(IXmlOutputState_t *state, const char *tag, const char* value, int len) +{ + IXmlOutputPrintIndent(state, "<%s>", tag); + IXmlOutputPrintStrLen(state, value, len); + IXmlOutputPrint(state, "\n", tag); + state->flags &= ~IXML_OUTPUT_FLAG_HAD_CONTENT; // should not be content +} + +// only output if value != "" +void IXmlOutputOptionalStrLen(IXmlOutputState_t *state, const char *tag, const char* value, int len) +{ + if (*value) + IXmlOutputStrLen(state, tag, value, len); +} + +void IXmlOutputStr(IXmlOutputState_t *state, const char *tag, const char* value) +{ + IXmlOutputStrLen(state, tag, value, IB_INT32_MAX); +} + +// only output if value != "" +void IXmlOutputOptionalStr(IXmlOutputState_t *state, const char *tag, const char* value) +{ + if (*value) + IXmlOutputStrLen(state, tag, value, IB_INT32_MAX); +} + +void IXmlOutputStrUint(IXmlOutputState_t *state, const char *tag, const char* str, unsigned value) +{ + /* when serializing, we omit the string output tag */ + if (! (state->flags & IXML_OUTPUT_FLAG_SERIALIZE)) { + IXmlOutputStr(state, tag, str); + } + IXmlOutputUintValue(state, tag, value); +} + +// only output if value != 0 +void IXmlOutputOptionalStrUint(IXmlOutputState_t *state, const char *tag, const char* str, unsigned value) +{ + if (value) + IXmlOutputStrUint(state, tag, str, value); +} + +void IXmlOutputStrUint64(IXmlOutputState_t *state, const char *tag, const char* str, uint64 value) +{ + /* when serializing, we omit the string output tag */ + if (! (state->flags & IXML_OUTPUT_FLAG_SERIALIZE)) { + IXmlOutputStr(state, tag, str); + } + IXmlOutputUint64(state, tag, value); +} +// only output if value != 0 +void IXmlOutputOptionalStrUint64(IXmlOutputState_t *state, const char *tag, const char* str, uint64 value) +{ + if (value) + IXmlOutputStrUint64(state, tag, str, value); +} + +void IXmlOutputStrInt(IXmlOutputState_t *state, const char *tag, const char* str, int value) +{ + /* when serializing, we omit the string output and the _Int tag */ + if (! (state->flags & IXML_OUTPUT_FLAG_SERIALIZE)) { + IXmlOutputStr(state, tag, str); + } + IXmlOutputIntValue(state, tag, value); +} + +// only output if value != 0 +void IXmlOutputOptionalStrInt(IXmlOutputState_t *state, const char *tag, const char* str, int value) +{ + if (value) + IXmlOutputStrInt(state, tag, str, value); +} + + + +void IXmlOutputStruct(IXmlOutputState_t *state, const char *tag, void *data, + IXML_FORMAT_ATTR_FUNC attr_func, const IXML_FIELD *fields) +{ + void *p; + + /* early out test so we don't waste time traversing heirarchy */ + if (IXmlOutputFailed(state)) + return; + IXmlOutputStartAttrTag(state, tag, data, attr_func); + for (;fields->tag; ++fields) { + p = (void *)((uintn)data + fields->offset); + if (fields->format_func) { + (*fields->format_func)(state, fields->tag, p); + } else { + switch (fields->format) { + case 'D': + switch (fields->size) { + case 1: + IXmlOutputInt(state, fields->tag, *(int8*)p); + break; + case 2: + IXmlOutputInt(state, fields->tag, *(int16*)p); + break; + case 4: + IXmlOutputInt(state, fields->tag, *(int32*)p); + break; + case 8: + IXmlOutputInt64(state, fields->tag, *(int64*)p); + break; + default: + ASSERT(0); + break; + } + break; + case 'd': + switch (fields->size) { + case 1: + IXmlOutputOptionalInt(state, fields->tag, *(int8*)p); + break; + case 2: + IXmlOutputOptionalInt(state, fields->tag, *(int16*)p); + break; + case 4: + IXmlOutputOptionalInt(state, fields->tag, *(int32*)p); + break; + case 8: + IXmlOutputOptionalInt64(state, fields->tag, *(int64*)p); + break; + default: + ASSERT(0); + break; + } + break; + case 'U': + switch (fields->size) { + case 1: + IXmlOutputUint(state, fields->tag, *(uint8*)p); + break; + case 2: + IXmlOutputUint(state, fields->tag, *(uint16*)p); + break; + case 4: + IXmlOutputUint(state, fields->tag, *(uint32*)p); + break; + case 8: + IXmlOutputUint64(state, fields->tag, *(uint64*)p); + break; + default: + ASSERT(0); + break; + } + break; + case 'u': + switch (fields->size) { + case 1: + IXmlOutputOptionalUint(state, fields->tag, *(uint8*)p); + break; + case 2: + IXmlOutputOptionalUint(state, fields->tag, *(uint16*)p); + break; + case 4: + IXmlOutputOptionalUint(state, fields->tag, *(uint32*)p); + break; + case 8: + IXmlOutputOptionalUint64(state, fields->tag, *(uint64*)p); + break; + default: + ASSERT(0); + break; + } + break; + case 'X': + switch (fields->size) { + case 1: + IXmlOutputHex(state, fields->tag, *(uint8*)p); + break; + case 2: + IXmlOutputHex(state, fields->tag, *(uint16*)p); + break; + case 4: + IXmlOutputHex(state, fields->tag, *(uint32*)p); + break; + case 8: + IXmlOutputHex64(state, fields->tag, *(uint64*)p); + break; + default: + ASSERT(0); + break; + } + break; + case 'x': + switch (fields->size) { + case 1: + IXmlOutputOptionalHex(state, fields->tag, *(uint8*)p); + break; + case 2: + IXmlOutputOptionalHex(state, fields->tag, *(uint16*)p); + break; + case 4: + IXmlOutputOptionalHex(state, fields->tag, *(uint32*)p); + break; + case 8: + IXmlOutputOptionalHex64(state, fields->tag, *(uint64*)p); + break; + default: + ASSERT(0); + break; + } + break; + case 'H': + switch (fields->size) { + case 1: + IXmlOutputHexPad8(state, fields->tag, *(uint8*)p); + break; + case 2: + IXmlOutputHexPad16(state, fields->tag, *(uint16*)p); + break; + case 4: + IXmlOutputHexPad32(state, fields->tag, *(uint32*)p); + break; + case 8: + IXmlOutputHexPad64(state, fields->tag, *(uint64*)p); + break; + default: + ASSERT(0); + break; + } + break; + case 'h': + switch (fields->size) { + case 1: + IXmlOutputOptionalHexPad8(state, fields->tag, *(uint8*)p); + break; + case 2: + IXmlOutputOptionalHexPad16(state, fields->tag, *(uint16*)p); + break; + case 4: + IXmlOutputOptionalHexPad32(state, fields->tag, *(uint32*)p); + break; + case 8: + IXmlOutputOptionalHexPad64(state, fields->tag, *(uint64*)p); + break; + default: + ASSERT(0); + break; + } + break; + case 'S': + IXmlOutputStr(state, fields->tag, (const char*)p); + break; + case 's': + IXmlOutputOptionalStr(state, fields->tag, (const char*)p); + break; + case 'P': + ASSERT(*(const char**)p); + IXmlOutputStrLen(state, fields->tag, *(const char**)p, fields->size); + case 'p': + // skip output of NULL string + if (*(const char**)p) { + IXmlOutputStrLen(state, fields->tag, *(const char**)p, fields->size); + } + break; + case 'C': + IXmlOutputStrLen(state, fields->tag, (const char*)p, fields->size); + break; + case 'c': + IXmlOutputOptionalStrLen(state, fields->tag, (const char*)p, fields->size); + break; + case 'k': + case 'K': + case 't': + case 'T': + case 'w': + case 'W': + case 'y': + case 'Y': + ASSERT(! fields->format_func); // tested above + break; + default: + ASSERT(0); + break; + } + } + } + IXmlOutputEndTag(state, tag); +} + +// only output if data != NULL +void IXmlOutputOptionalStruct(IXmlOutputState_t *state, const char *tag, void *data, IXML_FORMAT_ATTR_FUNC attr_func, IXML_FIELD *fields) +{ + if (data) + IXmlOutputStruct(state, tag, data, attr_func, fields); +} + +/****************************************************************************/ +/* XML parser. This uses expat to parse an XML file. The format of the XML + * has some limitations and is intended for serializing/deserializing + * structures and configuration information + */ +#define BUFFSIZE 8192 + +/* default callback by the parser to output errors and warnings */ +void IXmlPrintMessage(const char *message) +{ + fprintf(stderr, "%s\n", message); +} + +// output an error message and increment error_cnt and stop parser +void IXmlParserPrintError(IXmlParserState_t *state, const char *format, ...) +{ + va_list args; + char buf[1024]; + char buf2[1024]; + + va_start(args, format); + + vsnprintf(buf, sizeof(buf), format, args); + va_end(args); + + if (state->current.tag) + snprintf(buf2, sizeof(buf2), + "Parse error at line %"PRIu64" in tag '%s': %s", + (uint64)XML_GetCurrentLineNumber(state->parser), + state->current.tag, buf); + else + snprintf(buf2, sizeof(buf2), "Parse error at line %"PRIu64": %s", + (uint64)XML_GetCurrentLineNumber(state->parser), buf); + (state->printError)(buf2); + // future: could use XML_GetInputContext to get line which failed and + // use offset into line to display line with a ^ underit + ++state->error_cnt; + + // fatally abort parser + XML_StopParser(state->parser, 0); +} + +void IXmlParserPrintErrorString(IXmlParserState_t *state) +{ + char buf[1024]; + const char *errMsg = XML_ErrorString(XML_GetErrorCode(state->parser)); + + snprintf(buf, sizeof(buf), "Parse error at line %"PRIu64": %s", + (uint64)XML_GetCurrentLineNumber(state->parser), + errMsg?errMsg:""); + (state->printError)(buf); + // future: could use XML_GetInputContext to get line which failed and + // use offset into line to display line with a ^ underit +} + +/* for use internally to identify when end_func call is needed */ +static _inline boolean IXmlParserFailed(IXmlParserState_t *state) +{ + return (state->error_cnt > 0); +} + +// output a warning message and increment warning_cnt +void IXmlParserPrintWarning(IXmlParserState_t *state, const char *format, ...) +{ + va_list args; + char buf[1024]; + char buf2[1024]; + + va_start(args, format); + + vsnprintf(buf, sizeof(buf), format, args); + va_end(args); + + snprintf(buf2, sizeof(buf2), + "Parse warning at line %"PRIu64" in tag '%s': %s", + (uint64)XML_GetCurrentLineNumber(state->parser), + state->current.tag, buf); + (state->printWarning)(buf2); + // future: could use XML_GetInputContext to get line which failed and + // use offset into line to display line with a ^ underit + ++state->warning_cnt; +} + +static void IXmlParserPush(IXmlParserState_t *state) +{ + ASSERT(state->stack.sp < STACK_DEPTH-1); + state->stack.entries[state->stack.sp] = state->current; + state->stack.sp++; + state->current.tag = NULL; // be paranoid and ensure no double reference +} + +static void IXmlParserPop(IXmlParserState_t *state) +{ + ASSERT(state->stack.sp >= 1); + state->stack.sp--; + if (state->current.tag) + free(state->current.tag); + state->current = state->stack.entries[state->stack.sp]; +} + +// peek parent object +static void *IXmlParserPeek(IXmlParserState_t *state) +{ + ASSERT(state->stack.sp >= 1); + return state->stack.entries[state->stack.sp-1].object; +} + +/* get parser option flags */ +extern int IXmlParserGetFlags(IXmlParserState_t *state) +{ + return state->flags; +} + +/* get current tag name, returns NULL if no current tag */ +const char* IXmlParserGetCurrentTag(IXmlParserState_t *state) +{ + if (state->stack.sp == 0) + return NULL; + return state->current.tag; +} + +/* get parent tag name, returns NULL if no parent tag */ +const char* IXmlParserGetParentTag(IXmlParserState_t *state) +{ + // 0-> no current tag + // 1-> no parent tag + // >=2 -> parent and current tag + if (state->stack.sp <= 1) + return NULL; + return state->stack.entries[state->stack.sp-1].tag; +} + +/* get current Full dotted tag name, returns NULL if no current tag, + * returns pointer to a static buffer which is invalid after next call + * to this function + * In the event of overflow, the string "overflow" is returned + */ +const char* IXmlParserGetCurrentFullTag(IXmlParserState_t *state) +{ + static char fulltag[STACK_DEPTH*50]; + char *p = fulltag; + size_t len; + unsigned i; + + if (state->stack.sp == 0) + return NULL; + /* start at 1, entry 0 is invalid */ + for (i=1; i< state->stack.sp; i++) { + len = strlen(state->stack.entries[i].tag); + if ((p-fulltag) + len + 2 > sizeof(fulltag)) + return "overflow"; + strcpy(p, state->stack.entries[i].tag); + p += len; + *p++='.'; + } + len = strlen(state->current.tag); + if ((p-fulltag) + len + 1 > sizeof(fulltag)) + return "overflow"; + strcpy(p, state->current.tag); + + return fulltag; +} + +/* get count of child tags to current tag, typically called in ParserEnd */ +extern unsigned IXmlParserGetChildTagCount(IXmlParserState_t *state) +{ + return state->current.tags_found; +} + +// set subfields for present tag, only valid to call within ParserStart +// callback. This will override the subfields which were specified for +// the current IXML_FIELD structure +void IXmlParserSetSubfields(IXmlParserState_t *state, const IXML_FIELD *subfields) +{ + state->current.subfields = subfields; +} + +// set field for present tag, only valid to call within ParserStart +// callback. This will override the field which was specified for +// the matching IXML_FIELD structure +// Beware the ParserEndFunc in field will be called instead of the one in +// the original subfields list which matched this tag +// The current subfields are also set to field->subfields +void IXmlParserSetField(IXmlParserState_t *state, const IXML_FIELD *field) +{ + state->current.field = field; + state->current.subfields = field->subfields; +} + +/* return TRUE if current field's contents are empty or all whitespace */ +boolean IXmlIsWhitespace(const XML_Char *str, boolean *hasNewline) +{ + *hasNewline = FALSE; + // str is NULL when tag is empty (has subfields but no text) + if (str != NULL) { + for (;*str;str++) { + if (! isspace(*str)) + return FALSE; + if (*str == '\n' || *str == '\r') + *hasNewline = TRUE; + } + } + return TRUE; +} + +/* discard leading and trailing whitespace in str, return new length + * str modified in place + */ +unsigned IXmlTrimWhitespace(XML_Char *str, unsigned len) +{ + unsigned i; + + // trim trailing whitespace + while (len && isspace(str[len-1])) + len--; + str[len] = 0; + + // trim leading whitespace + for (i=0; ilen = IXmlTrimWhitespace(state->content, state->len); +} + +/* start_func for a simple structure. Allocates and zeros the structure using + * size specified in XML_FIELD + */ +void *IXmlParserStartStruct(IXmlParserState_t *state, void *parent, const char **attr) +{ + void *p = MemoryAllocate2AndClear(state->current.field->size, IBA_MEM_FLAG_PREMPTABLE, MYTAG); + if (! p) { + IXmlParserPrintError(state, "Unable to allocate memory"); + return NULL; + } + return p; +} + +/* end tag function which is a noop. Use this with start_func=NULL + * to define XML_FIELDs which are output only + */ +void IXmlParserEndNoop(struct IXmlParserState *state, + const IXML_FIELD *field, + void *object, void *parent, XML_Char *content, unsigned len, + boolean valid) +{ +} + +/* helper functions to aid parsing of unsigned hex or decimal fields */ +/* return TRUE on success, FALSE on failure + * on failure IXmlParserPrintError called to describe error and move + * parser to Failed state + */ +boolean IXmlParseUint8(IXmlParserState_t *state, XML_Char *content, unsigned len, uint8 *value) +{ + uint64 temp; + + if (! IXmlParseUint64(state, content, len, &temp)) + return FALSE; + + if (temp > IB_UINT8_MAX) { + IXmlParserPrintError(state, "Value out of range"); + return FALSE; + } + *value = (uint8)temp; + return TRUE; +} + +boolean IXmlParseUint16(IXmlParserState_t *state, XML_Char *content, unsigned len, uint16 *value) +{ + uint64 temp; + + if (! IXmlParseUint64(state, content, len, &temp)) + return FALSE; + + if (temp > IB_UINT16_MAX) { + IXmlParserPrintError(state, "Value out of range"); + return FALSE; + } + *value = (uint16)temp; + return TRUE; +} + +boolean IXmlParseUint32(IXmlParserState_t *state, XML_Char *content, unsigned len, uint32 *value) +{ + uint64 temp; + + if (! IXmlParseUint64(state, content, len, &temp)) + return FALSE; + + if (temp > IB_UINT32_MAX) { + IXmlParserPrintError(state, "Value out of range"); + return FALSE; + } + *value = (uint32)temp; + return TRUE; +} + +boolean IXmlParseUint64(IXmlParserState_t *state, XML_Char *content, unsigned len, uint64 *value) +{ + FSTATUS status; + + if (! len) { + IXmlParserPrintError(state, "Empty contents"); + return FALSE; + } + status = StringToUint64(value, content, NULL, 0, TRUE /*skip_trail_whitespace */); + if (status == FINVALID_SETTING) { + IXmlParserPrintError(state, "Value out of range"); + return FALSE; + } else if (status != FSUCCESS) { + IXmlParserPrintError(state, "Invalid contents"); + return FALSE; + } + return TRUE; +} + +/* helper functions to aid parsing of signed decimal fields */ +boolean IXmlParseInt8(IXmlParserState_t *state, XML_Char *content, unsigned len, int8 *value) +{ + int64 temp; + + if (! IXmlParseInt64(state, content, len, &temp)) + return FALSE; + + if (temp < IB_INT8_MIN || temp > IB_INT8_MAX) { + IXmlParserPrintError(state, "Value out of range"); + return FALSE; + } + *value = (int8)temp; + return TRUE; +} + +boolean IXmlParseInt16(IXmlParserState_t *state, XML_Char *content, unsigned len, int16 *value) +{ + int64 temp; + + if (! IXmlParseInt64(state, content, len, &temp)) + return FALSE; + + if (temp < IB_INT16_MIN || temp > IB_INT16_MAX) { + IXmlParserPrintError(state, "Value out of range"); + return FALSE; + } + *value = (int16)temp; + return TRUE; +} + +boolean IXmlParseInt32(IXmlParserState_t *state, XML_Char *content, unsigned len, int32 *value) +{ + int64 temp; + + if (! IXmlParseInt64(state, content, len, &temp)) + return FALSE; + + if (temp < IB_INT32_MIN || temp > IB_INT32_MAX) { + IXmlParserPrintError(state, "Value out of range"); + return FALSE; + } + *value = (int32)temp; + return TRUE; +} + +boolean IXmlParseInt64(IXmlParserState_t *state, XML_Char *content, unsigned len, int64 *value) +{ + FSTATUS status; + + if (! len) { + IXmlParserPrintError(state, "Empty contents"); + return FALSE; + } + status = StringToInt64(value, content, NULL, 0, TRUE /*skip_trail_whitespace */); + if (status == FINVALID_SETTING) { + IXmlParserPrintError(state, "Value out of range"); + return FALSE; + } else if (status != FSUCCESS) { + IXmlParserPrintError(state, "Invalid contents"); + return FALSE; + } + return TRUE; +} + +/* process field into object based on state->current.field->format, etc */ +static void IXmlParseField(IXmlParserState_t *state) +{ + const IXML_FIELD *field = state->current.field; + void *p = IXmlParserGetField(field, state->current.object); + + // a custom or wildcard format without an end_func ends up being an output + // only field which is ignored on input or a field with subfields and no + // special processing at end of all subfields + if (tolower(field->format) == 'k' + || tolower(field->format) == 't' + || tolower(field->format) == 'w' + || tolower(field->format) == 'y') + return; + + DEBUG_ASSERT(! IXmlParserFailed(state)); + + ASSERT(! field->start_func); + + switch (tolower(field->format)) { + case 'd': + switch (field->size) { + case 1: + (void)IXmlParseInt8(state, state->content, state->len, (int8 *)p); + break; + case 2: + (void)IXmlParseInt16(state, state->content, state->len, (int16 *)p); + break; + case 4: + (void)IXmlParseInt32(state, state->content, state->len, (int32 *)p); + break; + case 8: + (void)IXmlParseInt64(state, state->content, state->len, (int64 *)p); + break; + default: + //ASSERT(0); + break; + } + break; + case 'u': + case 'x': + case 'h': + switch (field->size) { + case 1: + (void)IXmlParseUint8(state, state->content, state->len, (uint8 *)p); + break; + case 2: + (void)IXmlParseUint16(state, state->content, state->len, (uint16 *)p); + break; + case 4: + (void)IXmlParseUint32(state, state->content, state->len, (uint32 *)p); + break; + case 8: + (void)IXmlParseUint64(state, state->content, state->len, (uint64 *)p); + break; + default: + //ASSERT(0); + break; + } + break; + case 's': + // Presently empty s, p and c formats are allowed. To make an error: + //if (! state->len) { + // IXmlParserPrintError(state, "Empty contents"); + // return; + //} + if (state->len > field->size-1) { + IXmlParserPrintWarning(state, "String too long, truncated"); + } + if (state->len) + MemoryCopy((char*)p, state->content, MIN(field->size, state->len+1)); + else + *(char*)p = '\0'; + ((char*)p)[field->size-1] = '\0'; + break; + case 'p': + { + int len = MIN(field->size, state->len); + // Presently empty s, p and c formats are allowed. To make an error: + //if (! state->len) { + // IXmlParserPrintError(state, "Empty contents"); + // return; + //} + if (state->len > field->size) { + IXmlParserPrintWarning(state, "String too long, truncated"); + } + *(char**)p = MemoryAllocate2(len+1, IBA_MEM_FLAG_PREMPTABLE, MYTAG); + if (*(char**)p) { + if (len) + MemoryCopy(*(char**)p, state->content, len); + (*(char**)p)[len] = '\0'; + } else { + IXmlParserPrintError(state, "Unable to allocate memory"); + } + } + break; + case 'c': + // Presently empty s, p and c formats are allowed. To make an error: + //if (! state->len) { + // IXmlParserPrintError(state, "Empty contents"); + // return; + //} + if (state->len > field->size) { + IXmlParserPrintWarning(state, "String too long, truncated"); + } + if (state->len) + MemoryCopy((char*)p, state->content, MIN(field->size, state->len)); + else + *(char*)p = '\0'; + break; + case 'k': + case 't': + case 'w': + case 'y': + ASSERT(0); // tested above should not get here + break; + default: + ASSERT(0); + break; + } +} + +static void XMLCALL +IXmlParserStartTag(void *data, const char *el, const char **attr) +{ + IXmlParserState_t *state = (IXmlParserState_t *) data; + +#if DEBUG_IXML_PARSER + { + int i; + /* show tag and attributes */ + for (i = 0; i < state->depth; i++) + printf(" "); + printf("%s", el); + for (i = 0; attr[i]; i += 2) { + printf(" %s='%s'", attr[i], attr[i + 1]); + } + printf("\n"); + } +#endif + + ASSERT(! IXmlParserFailed(state)); + + /* process start of tag */ + if (state->current.field->start_func) { + state->current.object = (*state->current.field->start_func)(state, state->current.object, attr); + // if a simple tag needed a start func it can return parent object + } else { + /* start of a simple tag */ + // ASSERT(state->current.object != NULL) + // processing is done in end for contents of tag + } +} + +// verify manditory subfields (and don't permit contents on tags with subfields) +// tags_found and fields_found optionally return counts (0 if no subfields) +static FSTATUS +IXmlParserCheckSubfields(IXmlParserState_t *state, + unsigned *tags_found, unsigned *fields_found) +{ + FSTATUS ret = FSUCCESS; + + if (state->current.subfields && ! IXmlParserFailed(state)) { + const IXML_FIELD *p; + unsigned i; + unsigned field_count; + + // presently we don't permit content on "containers" + // and we require the toplevel document (field==NULL) to have a tag + // When format of field is 'w' or 'y' (wildcard) we allow container to + // have content or subfields and expect EndTag function to sort it out + // In future if content on containers is needed, we could test other + // aspects of state->current.field such as format, end_func and/or size. + // Perhaps existance of field->size != 0 would indicate content was allowed + if (state->len + && (state->current.tags_found /* found child tags */ + || state->current.field == NULL /* top level tag */ + || (state->current.field->format != 'w' + && state->current.field->format != 'y'))) { + IXmlParserPrintWarning(state, "Unexpected contents ignored: %s", state->content); + ret = FERROR; + } + + // check for manditory subfields +#if DEBUG_IXML_PARSER + printf("fields_found=0x%"PRIx64"\n", state->current.fields_found); +#endif + for (i=0,p=state->current.subfields,field_count=0; p && p->tag && i < 64; p++,i++) { + if (state->current.fields_found & ((uint64)1<format)) { + /* manditory field not found */ + IXmlParserPrintError(state, "Mandatory Tag Not Found: %s", p->tag); + ret = FERROR; + } + } + if (tags_found) + *tags_found = state->current.tags_found; + if (fields_found) + *fields_found = field_count; + } else { + /* subfields not applicable */ + if (tags_found) + *tags_found = 0; + if (fields_found) + *fields_found = 0; + } + return ret; +} + +static void XMLCALL +IXmlParserEndTag(void *data, const char *el) +{ + IXmlParserState_t *state = (IXmlParserState_t *) data; + + // for c, p, s, t and w formats we keep leading and trailing spaces + // we know we output these tags without any extra spaces + // if tag had child tags, we also discard whitespace + if (state->len + && (state->current.tags_found + || (tolower(state->current.field->format) != 'c' + && tolower(state->current.field->format) != 'p' + && tolower(state->current.field->format) != 's' + && tolower(state->current.field->format) != 't' + && tolower(state->current.field->format) != 'w'))) { + IXmlParserTrimWhitespace(state); + } + +#if DEBUG_IXML_PARSER + // show content to aid debug + if (state->len) + printf("End %s: '%s'\n", el, state->content); + else + printf("End %s\n", el); +#endif + + (void)IXmlParserCheckSubfields(state, NULL, NULL); + + /* if there is no start function, we assume its a simple end_func and + * does not need to be called to cleanup if IXmlParserFailed + * also if object is NULL and we have failed, we don't call end_func + */ + if ((state->current.field->start_func && state->current.object != NULL) + || ! IXmlParserFailed(state)) { + // real end processing + if (state->current.field->end_func) { + (*state->current.field->end_func)(state, state->current.field, state->current.object, IXmlParserPeek(state), state->content, state->len, ! IXmlParserFailed(state)); + } else { + IXmlParseField(state); + } + } + + if (state->content) { + free(state->content); + state->content = NULL; + state->len = 0; + } +} + +static void +IXmlParserRawStart(void *data, const char *el, const char **attr) { + IXmlParserState_t *state = (IXmlParserState_t *) data; + const IXML_FIELD *p; + unsigned i; + +#if DEBUG_IXML_PARSER + printf("start field %s\n", el); +#endif + // trim whitespace in parent tag's content + // we do not permit container tags to have text contents as well + // generic XML would permit, but it can get confusing especially for + // embedded whitespace. + // If we later decide we need this, could include in StackEntry + if (state->len) + IXmlParserTrimWhitespace(state); // remove indentation and newlines + if (state->len) { + if (state->current.subfields) + IXmlParserPrintError(state, "Tag is a container and can't have a value"); + else + IXmlParserPrintError(state, "Tag has a value and contains %s Tag", el); + return; + } + if (! state->skip && state->current.subfields) { + for (i=0,p=state->current.subfields; p->tag; p++,i++) { + if (strcmp(el, p->tag) == 0 || strcmp("*", p->tag) == 0) { + char *tagname; + if (i < 64) + state->current.fields_found |= ((uint64)1)<current.tags_found++; +#if DEBUG_IXML_PARSER + printf("tags_found=%u fields_found=0x%"PRIx64"\n", state->current.tags_found, state->current.fields_found); +#endif + tagname = strdup(el); + if (! tagname) { + IXmlParserPrintError(state, "Unable to allocate memory"); + return; + } + IXmlParserPush(state); + state->current.tag = tagname; + state->current.field = p; + state->current.subfields = p->subfields; + state->current.fields_found = 0; + state->current.tags_found = 0; + IXmlParserStartTag(state, state->current.tag, attr); /* rest of start handling */ + break; + } + } + if (! (p && p->tag)) { + /* unknown tag, skip it and child tags */ + if (state->flags & IXML_PARSER_FLAG_STRICT) { + IXmlParserPrintWarning(state, "Unexpected tag ignored: %s", el); + } + state->skip = state->depth; + } + } + + state->depth++; +} + +static void +IXmlParserRawEnd(void *data, const char *el) { + IXmlParserState_t *state = (IXmlParserState_t *) data; + + ASSERT(state->depth > 1); + state->depth--; + + if (! state->skip) { + IXmlParserEndTag(state, el); /* do rest of end handling */ + IXmlParserPop(state); + } + + if (state->skip == state->depth) + state->skip = 0; +} + +static void +IXmlParserCharHandler(void *data, const XML_Char *buf, int len) +{ + IXmlParserState_t *state = (IXmlParserState_t *) data; + + // for c, p, s, t and w formats we keep leading and trailing spaces + // we know we output these tags without any extra spaces + if (! state->content + && tolower(state->current.field->format) != 'c' + && tolower(state->current.field->format) != 'p' + && tolower(state->current.field->format) != 's' + && tolower(state->current.field->format) != 't' + && tolower(state->current.field->format) != 'w') { + /* skip leading spaces */ + while (len && isspace(*buf)) { + buf++; len--; + } + } + if (len) { + state->content = realloc(state->content, (state->len + len + 1)*sizeof(XML_Char)); + if (state->content) { + MemoryCopy(state->content+state->len, buf, len); + state->len += len; + state->content[state->len] = 0; + } else { + (state->printError)("Couldn't allocate memory for content."); + } + } +} + +static void +IXmlParserRawCharHandler(void *data, const XML_Char *buf, int len) +{ + IXmlParserState_t *state = (IXmlParserState_t *) data; + + if (! state->skip) { + IXmlParserCharHandler(data, buf, len); + } +} + +FSTATUS +IXmlParserInit(IXmlParserState_t *state, IXmlParserFlags_t flags, const IXML_FIELD *subfields, void *object, void *context, IXmlParserPrintMessage printError, IXmlParserPrintMessage printWarning, XML_Memory_Handling_Suite *memsuite) +{ + MemoryClear(state, sizeof(*state)); + state->flags = flags; + state->skip = 0; + state->depth = 1; + state->content = NULL; + state->len = 0; + state->current.tag = NULL; + state->current.field = NULL; + state->current.subfields = subfields; + state->current.object = object; + state->current.fields_found = 0; + state->current.tags_found = 0; + state->stack.sp = 0; + state->error_cnt = 0; + state->warning_cnt = 0; + state->context = context; + if (printError) + state->printError = printError; + else + state->printError = IXmlPrintMessage; + if (printWarning) + state->printWarning = printWarning; + else + state->printWarning = IXmlPrintMessage; + + if (memsuite == NULL) + state->parser = XML_ParserCreate(NULL); + else + state->parser = XML_ParserCreate_MM(NULL, memsuite, NULL); + + if (! state->parser) { + (state->printError)("Couldn't allocate memory for parser"); + return FINSUFFICIENT_MEMORY; + } + + XML_SetElementHandler(state->parser, IXmlParserRawStart, IXmlParserRawEnd); + XML_SetCharacterDataHandler(state->parser, IXmlParserRawCharHandler); + XML_SetUserData(state->parser, state); + + return FSUCCESS; +} + +FSTATUS IXmlParserReadFile(IXmlParserState_t *state, FILE *file) +{ + for (;;) { + int n; + int done; + void *buf = XML_GetBuffer(state->parser, BUFFSIZE); + if (buf == NULL) { + /* handle error */ + (state->printError)("GetBuffer error"); + return FINSUFFICIENT_MEMORY; + } + +#ifndef VXWORKS + n = (int)fread(buf, 1, BUFFSIZE, file); +#else + n = (int)readUncompressedBytes(file, buf, BUFFSIZE); +#endif + + if (ferror(file) || (n<0)) { + (state->printError)("Read error"); + return FERROR; + } + done = feof(file) || (n==0); + + if (XML_ParseBuffer(state->parser, n, done) == XML_STATUS_ERROR) { + /* if IXmlParserFailed, we already output an error */ + if (! IXmlParserFailed(state)) + IXmlParserPrintErrorString(state); + return FINVALID_STATE; + } + + if (done) + break; + } + return FSUCCESS; +} + +void +IXmlParserDestroy(IXmlParserState_t *state) { + + // unwind any "open" tags in progress + while (state->depth > 1) { + if (state->current.field) + IXmlParserRawEnd(state, state->current.tag); // also pops stack + else { + state->depth--; + + if (! state->skip) + IXmlParserPop(state); + + if (state->skip == state->depth) + state->skip = 0; + } + } + XML_ParserFree(state->parser); + state->parser = NULL; // make sure not used by mistake after destroy + state->context = NULL; // make sure not used by mistake after destroy + if (state->current.tag) + free(state->current.tag); + state->current.tag = NULL; // make sure not used by mistake after destroy +} + +#ifndef VXWORKS + +// parse supplied file. filename is only used in error messages +FSTATUS +IXmlParseFile(FILE *file, const char* filename, IXmlParserFlags_t flags, const IXML_FIELD *subfields, void *object, void *context, IXmlParserPrintMessage printError, IXmlParserPrintMessage printWarning, unsigned* tags_found, unsigned* fields_found) +{ + IXmlParserState_t state; + + if (FSUCCESS != IXmlParserInit(&state, flags, subfields, object, context, printError, printWarning, NULL)) { + (printError?printError:IXmlPrintMessage)("Couldn't initialize parser"); + goto failinit; + } + if (FSUCCESS != IXmlParserReadFile(&state, file) + || FSUCCESS != IXmlParserCheckSubfields(&state, tags_found, fields_found)) { + IXmlParserPrintError(&state, "Fatal error parsing file '%s'", filename); + goto failread; + } + IXmlParserDestroy(&state); + + return FSUCCESS; + +failread: + IXmlParserDestroy(&state); +failinit: + return FERROR; +} + +// open and parse input_file +FSTATUS +IXmlParseInputFile(const char *input_file, IXmlParserFlags_t flags, const IXML_FIELD *subfields, void *object, void *context, IXmlParserPrintMessage printError, IXmlParserPrintMessage printWarning, unsigned* tags_found, unsigned* fields_found) +{ + FILE *input; + + input = fopen(input_file, "r"); + if (! input) { + IXmlPrintFileError(input_file, printError); + goto failopen; + } + + if (FSUCCESS != IXmlParseFile(input, input_file, flags, subfields, object, context, printError, printWarning, tags_found, fields_found)) { + goto failread; + } + fclose(input); + + return FSUCCESS; + +failread: + fclose(input); +failopen: + return FERROR; +} + +#else + +// parse supplied file. filename is only used in error messages +FSTATUS +IXmlParseFile(FILE *file, const char* filename, IXmlParserFlags_t flags, const IXML_FIELD *subfields, void *object, void *context, IXmlParserPrintMessage printError, IXmlParserPrintMessage printWarning, unsigned* tags_found, unsigned* fields_found, XML_Memory_Handling_Suite* memsuite) +{ + IXmlParserState_t state; + + if (FSUCCESS != IXmlParserInit(&state, flags, subfields, object, context, printError, printWarning, memsuite)) { + (printError?printError:IXmlPrintMessage)("Couldn't initialize parser"); + goto failinit; + } + if (FSUCCESS != IXmlParserReadFile(&state, file) + || FSUCCESS != IXmlParserCheckSubfields(&state, tags_found, fields_found)) { + IXmlParserPrintError(&state, "Fatal error parsing file '%s'", filename); + goto failread; + } + IXmlParserDestroy(&state); + + return FSUCCESS; + +failread: + IXmlParserDestroy(&state); +failinit: + return FERROR; +} + +// open and parse input_file +FSTATUS +IXmlParseInputFile(const char *input_file, IXmlParserFlags_t flags, const IXML_FIELD *subfields, void *object, void *context, IXmlParserPrintMessage printError, IXmlParserPrintMessage printWarning, unsigned* tags_found, unsigned* fields_found, XML_Memory_Handling_Suite* memsuite) +{ + FILE *input; + + input = openUncompressedFile((char*)input_file,NULL); + if (! input) { + IXmlPrintFileError(input_file, printError); + goto failopen; + } + + if (FSUCCESS != IXmlParseFile(input, input_file, flags, subfields, object, context, printError, printWarning, tags_found, fields_found, memsuite)) { + goto failread; + } + closeUncompressedFile(input); + + return FSUCCESS; + +failread: + closeUncompressedFile(input); +failopen: + return FERROR; +} + +#endif diff --git a/Xml/ixml.h b/Xml/ixml.h new file mode 100644 index 0000000..7e3d6b3 --- /dev/null +++ b/Xml/ixml.h @@ -0,0 +1,549 @@ +/* BEGIN_ICS_COPYRIGHT2 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT2 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +#ifndef _IBA_PUBLIC_IXML_H_ +#define _IBA_PUBLIC_IXML_H_ + +#include +#include +#include +#if !defined(_GNU_SOURCE) +#define _GNU_SOURCE +#endif + +#ifdef VXWORKS +#include +#else +#include +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#define DEBUG_IXML_PARSER 0 /* set to 1 to enable DbgOuts in Xml Parser */ + +/*****************************************************************************/ +/* XML declarations common to parser and output */ +struct IXmlOutputState; +struct IXmlParserState; +struct _IXML_FIELD; + +typedef void (*IXML_FORMAT_FIELD_FUNC)(struct IXmlOutputState *state, + const char *tag, void *data); +/* ATTR_FUNC should output a leading space before 1st attribute + * if there are no attributes to output it can simply do nothing + */ +typedef void (*IXML_FORMAT_ATTR_FUNC)(struct IXmlOutputState *state, + void *data); +typedef void *(*IXML_START_TAG_FUNC)(struct IXmlParserState *state, + void *parent, const char **attr); +typedef void (*IXML_END_TAG_FUNC)(struct IXmlParserState *state, + const struct _IXML_FIELD *field, + void *object, void *parent, XML_Char *content, unsigned len, + boolean valid); + +typedef struct _IXML_FIELD { + const char *tag; /* tag name in XML file or "*" */ + char format; /* format for tag, see below for choices */ + int offset; /* offset in C structure for tag's value */ + int size; /* size of field in C structure */ + IXML_FORMAT_FIELD_FUNC format_func; /* custom function to format output */ + struct _IXML_FIELD *subfields; /* fields within a container tag */ + IXML_START_TAG_FUNC start_func; /* function when input */ + IXML_END_TAG_FUNC end_func; /* function when input */ +} IXML_FIELD; + +// helper macro, given a structure datatype and a member in structure +// this provides initializers for IXML_FIELD offset and size +#define IXML_FIELD_INFO(TYPE, MEMBER) offset:offsetof(TYPE, MEMBER), size:sizeof(((TYPE*)0)->MEMBER) +// similar helper for 'p' formats, here the size can be specified as upper bound +// for the string. Use IB_INT32_MAX if there is no practical limit +#define IXML_P_FIELD_INFO(TYPE, MEMBER, SIZE) offset:offsetof(TYPE, MEMBER), size:SIZE + +/* formats: + * d - %d format for given field size (1, 2, 4, 8) + * Leading and trailing whitespace ignored. + * Undefined if also specify subfields + * u - %u format for given field size (1, 2, 4, 8) + * Leading and trailing whitespace ignored. + * Undefined if also specify subfields + * x - 0x%x format for given field size (1, 2, 4, 8) w/o 0 pad + * Leading and trailing whitespace ignored. + * Undefined if also specify subfields + * h - 0x%x format for given field size (1, 2, 4, 8) with 0 pad + * Leading and trailing whitespace ignored. + * Undefined if also specify subfields + * s - '\0' terminated array of chars, %s format, output until '\0' encountered + * use this for arrays of characters directly in the parent structure + * which are to be '\0' terminated. size indicates size of array + * including space for the '\0' terminator (eg. string is limited to + * size-1 characters). + * Leading and trailing whitespace not trimmed. + * Undefined if also specify subfields + * p - pointer to string, %s format, output until '\0' encountered + * use this for pointers to strings in the parent structure. On input + * the pointer will be allocated. Caller must use MemoryDeallocate + * to free the string when done with it. size indicates upper bound for + * string (not including '\0'). strings longer than this will be truncated + * on input and output, but still '\0' terminated. NULL pointers will + * be skipped on output and not output the tag at all. For optional input + * fields when field is not found will default to value set in structure + * StartTag function, typically NULL. + * Leading and trailing whitespace not trimmed. + * Undefined if also specify subfields + * c - fixed length string input/output until size characters or '\0' + * use this for arrays of characters directly in the parent structure + * which need not be '\0' terminated (such as in IB SA Records). + * size indicates size of array. A '\0' terminator is added only if the + * input string is less than size. + * Leading and trailing whitespace not trimmed. + * Undefined if also specify subfields + * k - invoke 'kustom' format_func for output, can use subfields for input + * Leading and trailing whitespace trimmed. + * Enforces that if subfields are specified, no content is allowed + * It is expected that fields without subfields will have explicit + * end_func to process them. + * t - invoke 'kustom' format_func for output, can use subfields for input + * Leading and trailing whitespace not trimmed. + * Enforces that if subfields are specified, no content is allowed + * It is expected that fields without subfields will have explicit + * end_func to process them. + * w - wildcarded tag format. + * Leading and trailing whitespace not trimmed. + * Enforces that if subfields are encountered, no content is allowed + * An end_func should be supplied to handle input, especially when + * no subfields. + * Typically used in conjunction with tag name of '*' to permit IXml + * parser to implement a stack but manually do tag processing in Start + * and End functions. + * y - trimmed wildcarded tag format. + * Leading and trailing whitespace trimmed. + * Enforces that if subfields are encountered, no content is allowed + * An end_func should be supplied to handle input, especially when + * no subfields. + * Typically used in conjunction with tag name of '*' to permit IXml + * parser to implement a stack but manually do tag processing in Start + * and End functions. + * + * The IXmlParserState and IXmlOutputState structures should be treated + * as opaque structures. format_func, end_func and start_func should not + * use fields in these structures. The necessary information from the state + * is supplied as explicit arguments. + * + * Output: + * each field is processed in order. + * If format_func is specified it will be called (regardless of format) + * with data pointer pointing to present object + offset. + * If no format_func is specified, the offset and size will be used along + * with the format to automatically fetch the field and generate output + * 'k', 't', 'w' and 'y' formats must supply a format_func. + * + * Input Parsing: + * On input parsing, capital letters for format indicate manditory fields + * Present implementation is limited to no more than 64 manditory fields + * per object + * + * On input parsing, if a start_func is supplied an end_func must also + * be supplied. If a end_func is supplied, format is not used to parse + * data but affects whitespace and subfield processing. + * An end_func should be supplied for 'k'/'t'/'w'/'y' formats, otherwise + * the input field will be ignored (recommend use of IXmlParserEndNoop + * rather than NULL for future compatibility). + * + * On output processing, capital letters for format indicate manditory fields + * which are always output regardless of value. lower case leters for format + * are optional fields which will only be output if non-zero/non-NULL. + * For 'k', 't', 'w' and 'y' fields, its up to the supplied format_func to + * decide. + * There are "Optional" variations of most generic format functions which may + * be used by format_func if desired. + * + * For an output only field: + * type/format_func define output + * start_func=NULL, end_func=IXmlParserEndNoop + * For an input only field: + * type/start_func/end_func define input + * format_func=IXmlOutputNoop + * For an input/output field: + * type/start_func/end_func define input + * type/format_func define output + * + * Error handling: + * Failures in XML syntax or calls to IXmlParserPrintError will stop + * the parser with an error. For such parsing failures, the parser + * will unwind and invoke the end_func's for all objects whose start_func + * had been called. Such calls will have valid=FALSE. In this case + * the end_func should undo any operations which the start_func did + * (free object, remove object from lists in parent to which start func added it + * etc). + * + * If a start_func or end_func encounters a fatal error, it should call + * IXmlParserPrintError with an appropriate message. This will output + * a message including input file line, present tag and the message + * provided by the caller. It will also start the parser error and unwind + * sequence. + * + * Once a parser error is detected, no further start_func's will be called. + * + * Object handling: + * The parser assists in tracking object heirachies and provides objects + * to the start_func and end_func. The start_func is expected to return an + * object pointer. This pointer is typically an object/structure allocated + * by the start function to hold the subsequent tags. The pointer returned by + * the start_func will be provided to the end_func as the "object" argument. + * Also if there are nested tags (eg. subfields), the object returned by + * the start_func will also be provided to the nested tags' start_func and + * end_func as the "parent". + * + * Typical operation would be for the start_func to allocate and initialize + * the empty object. For simple structures which simply need to be + * allocated and zeroed, the IXmlParserStartStruct function is provided. + * Then the end_func would verify the consistency of the fields and link the + * object into its parent (add to a list or pointer). If the end_func discovers + * an error it should call IXmlParserPrintError (or Warning if its non-fatal) + * and free the object. + * + * For simple fields (bitfields, needing special handling, etc). The + * start_func can be NULL and the end_func will be given the object and + * parent applicable to the preceeding tag. + * + * The code in ixml_ib.c is a good example of use of the parser. + * + * xml_sample provides a simple example of a parser which uses the + * wildcards to parse and dump any XML file given. + * + * opaxmlindent expands on xml_sample by dumping the XML with nice indentation + */ + +/*****************************************************************************/ +/* XML Output Declarations */ +typedef enum { + /* flags which can be passed to IXmlInit and IXmlOutputInit */ + IXML_OUTPUT_FLAG_NONE = 0, + IXML_OUTPUT_FLAG_SERIALIZE = 1, /* compact serialized format */ + /* these flags are for internal use only */ + IXML_OUTPUT_FLAG_START_NEED_NL = 0x10000, /* start tag output without newline */ + IXML_OUTPUT_FLAG_HAD_CONTENT = 0x20000, /* tag had content output */ + IXML_OUTPUT_FLAG_IN_START_TAG = 0x40000, /* For printing multiple attrs */ +} IXmlOutputFlags_t; + +/* these structures should not be directly used by callers */ +typedef struct IXmlOutputState { +// TBD - later support output to a memory buffer + FILE *file; /* output file */ + unsigned indent; /* level of indent */ + unsigned cur_indent; /* level of indent */ + int flags; + void *context; /* caller supplied context */ +} IXmlOutputState_t; + +/* for use in output calls so can early exit */ +/* note that IXmlOutputStruct tests this, so in general it does not need to + * be called in other functions + */ +static _inline boolean IXmlOutputFailed(IXmlOutputState_t *state) +{ + return (ferror(state->file) != 0); +} + +/* get access to caller supplied context for output */ +static _inline void* IXmlOutputGetContext(IXmlOutputState_t *state) +{ + return state->context; +} + +/* indent is additional indent per level */ +extern void IXmlInit(IXmlOutputState_t *state, FILE *file, + unsigned indent, IXmlOutputFlags_t flags, void *context); +extern FSTATUS IXmlOutputInit(IXmlOutputState_t *state, FILE *file, + unsigned indent, IXmlOutputFlags_t flags, void *context); +extern void IXmlOutputDestroy(IXmlOutputState_t *state); +extern void IXmlOutputPrint(IXmlOutputState_t *state, const char *format, ...); +extern void IXmlOutputPrintIndent(IXmlOutputState_t *state, const char *format, ...); +extern void IXmlOutputNoop(IXmlOutputState_t *state, const char *tag, void *data); +extern void IXmlOutputStartTag(IXmlOutputState_t *state, const char *tag); + +/* + * Print start tag with single attribute and value. Use + * IXmlOutputStartTag() and IXmlOutputAttr*() if you need to print + * multiple attributes. + */ +extern void IXmlOutputStartAttrTag(IXmlOutputState_t *state, const char *tag, void *data, IXML_FORMAT_ATTR_FUNC attr_func); + +/* + * Add @attr with @val to current element tag definition. + * This doesn't do any sanitizing on @attr or @val so be careful + * what you put in. Should be called after a call to IXmlOutputStartTag(). + * Any call (direct or indirect) to IXmlOutputPrint() or + * IXmlOutputPrintIndent() closes the start tag. + * + * @return FSUCCESS on success, FERROR if not in the start of a tag + */ +extern FSTATUS IXmlOutputAttr(IXmlOutputState_t *state, const char *attr, const char *val); + +/* + * Like IXmlOutputAttr() but takes a format string and variable args. + * As with IXmlOutputAttr(), does not sanitize inputs. + * + * @return FSUCCESS on success, FERROR if not in the start of a tag + */ +extern FSTATUS IXmlOutputAttrFmt(IXmlOutputState_t *state, const char *attr, const char *format, ...); +extern void IXmlOutputEndTag(IXmlOutputState_t *state, const char *tag); +extern void IXmlOutputEndTagWithLineno(IXmlOutputState_t *state, const char *tag, unsigned long lineno); +extern void IXmlOutputHexPad8(IXmlOutputState_t *state, const char *tag, uint8 value); +extern void IXmlOutputOptionalHexPad8(IXmlOutputState_t *state, const char *tag, uint8 value); +extern void IXmlOutputHexPad16(IXmlOutputState_t *state, const char *tag, uint16 value); +extern void IXmlOutputOptionalHexPad16(IXmlOutputState_t *state, const char *tag, uint16 value); +extern void IXmlOutputHexPad32(IXmlOutputState_t *state, const char *tag, uint32 value); +extern void IXmlOutputOptionalHexPad32(IXmlOutputState_t *state, const char *tag, uint32 value); +extern void IXmlOutputHexPad64(IXmlOutputState_t *state, const char *tag, uint64 value); +extern void IXmlOutputOptionalHexPad64(IXmlOutputState_t *state, const char *tag, uint64 value); +extern void IXmlOutputInt(IXmlOutputState_t *state, const char *tag, int value); +extern void IXmlOutputOptionalInt(IXmlOutputState_t *state, const char *tag, int value); +extern void IXmlOutputInt64(IXmlOutputState_t *state, const char *tag, int64 value); +extern void IXmlOutputOptionalInt64(IXmlOutputState_t *state, const char *tag, int64 value); +extern void IXmlOutputUint(IXmlOutputState_t *state, const char *tag, unsigned value); +extern void IXmlOutputOptionalUint(IXmlOutputState_t *state, const char *tag, unsigned value); +extern void IXmlOutputUint64(IXmlOutputState_t *state, const char *tag, uint64 value); +extern void IXmlOutputOptionalUint64(IXmlOutputState_t *state, const char *tag, uint64 value); +extern void IXmlOutputHex(IXmlOutputState_t *state, const char *tag, unsigned value); +extern void IXmlOutputOptionalHex(IXmlOutputState_t *state, const char *tag, unsigned value); +extern void IXmlOutputHex64(IXmlOutputState_t *state, const char *tag, uint64 value); +extern void IXmlOutputOptionalHex64(IXmlOutputState_t *state, const char *tag, uint64 value); +extern void IXmlOutputPrintStrLen(IXmlOutputState_t *state, const char* value, int len); +extern void IXmlOutputPrintStr(IXmlOutputState_t *state, const char* value); +extern void IXmlOutputStrLen(IXmlOutputState_t *state, const char *tag, const char* value, int len); +extern void IXmlOutputOptionalStrLen(IXmlOutputState_t *state, const char *tag, const char* value, int len); +extern void IXmlOutputStr(IXmlOutputState_t *state, const char *tag, const char* value); +extern void IXmlOutputOptionalStr(IXmlOutputState_t *state, const char *tag, const char* value); +extern void IXmlOutputStrUint(IXmlOutputState_t *state, const char *tag, const char* str, unsigned value); +extern void IXmlOutputOptionalStrUint(IXmlOutputState_t *state, const char *tag, const char* str, unsigned value); +extern void IXmlOutputStrUint64(IXmlOutputState_t *state, const char *tag, const char* str, uint64 value); +extern void IXmlOutputOptionalStrUint64(IXmlOutputState_t *state, const char *tag, const char* str, uint64 value); +extern void IXmlOutputStrInt(IXmlOutputState_t *state, const char *tag, const char* str, int value); +extern void IXmlOutputOptionalStrInt(IXmlOutputState_t *state, const char *tag, const char* str, int value); +extern void IXmlOutputStruct(IXmlOutputState_t *state, const char *tag, void *data, + IXML_FORMAT_ATTR_FUNC attr_func, const IXML_FIELD *fields); +extern void IXmlOutputOptionalStruct(IXmlOutputState_t *state, const char *tag, void *data, IXML_FORMAT_ATTR_FUNC attr_func, IXML_FIELD *fields); + +/*****************************************************************************/ +/* XML Parser declarations */ +/* these structures should not be directly used by callers */ +typedef struct IXmlParserStackEntry { + char *tag; // locally allocated copy + const IXML_FIELD *field; + const IXML_FIELD *subfields; + void *object; + unsigned tags_found; // total subfield tags encountered including dups + uint64 fields_found; // bit mask of indexes into subfields +} IXmlParserStackEntry_t; + +#define STACK_DEPTH 100 + +typedef struct IXmlParserStack { + /* TOS is kept in state->current instead */ + unsigned sp; /* if 0, stack is empty */ + IXmlParserStackEntry_t entries[STACK_DEPTH]; /* entry 0 is unused */ +} IXmlParserStack_t; + +/* callbacks by the parser to output errors and warnings */ +typedef void (*IXmlParserPrintMessage)(const char *message); + +typedef struct IXmlParserState { +// TBD - later support input from a memory buffer + XML_Parser parser; + int flags; /* parser option flags */ + unsigned depth; /* how many nested elements deep >= 1 */ + unsigned skip; /* skip all elements until we return to this depth */ + IXmlParserStackEntry_t current; /* state of current element being parsed */ + XML_Char *content; /* text contents of current element */ + unsigned len; /* number of characters in content */ + IXmlParserStack_t stack; /* stack of parent elements' states */ + unsigned error_cnt; + unsigned warning_cnt; + void *context; /* caller supplied context */ + IXmlParserPrintMessage printError; + IXmlParserPrintMessage printWarning; +} IXmlParserState_t; + +/* get access to caller supplied context for input */ +static _inline void* IXmlParserGetContext(IXmlParserState_t *state) +{ + return state->context; +} + +typedef enum { + /* flags which can be passed to IXmlInit and IXmlOutputInit */ + IXML_PARSER_FLAG_NONE = 0, + IXML_PARSER_FLAG_STRICT = 1, /* provide warnings for unknown tags, etc */ +} IXmlParserFlags_t; + +/* get parser option flags */ +extern int IXmlParserGetFlags(IXmlParserState_t *state); + +/* get current tag name, returns NULL if no current tag */ +extern const char* IXmlParserGetCurrentTag(IXmlParserState_t *state); + +/* get parent tag name, returns NULL if no parent tag */ +extern const char* IXmlParserGetParentTag(IXmlParserState_t *state); + +/* get current Full dotted tag name, returns NULL if no current tag, + * returns pointer to a static buffer which is invalid after next call + * to this function + * In the event of overflow, the string "overflow" is returned + */ +extern const char* IXmlParserGetCurrentFullTag(IXmlParserState_t *state); + +/* get count of child tags to current tag, typically called in ParserEnd */ +extern unsigned IXmlParserGetChildTagCount(IXmlParserState_t *state); + +// set subfields for present tag, only valid to call within ParserStart +// callback. This will override the subfields which were specified for +// the current IXML_FIELD structure +extern void IXmlParserSetSubfields(IXmlParserState_t *state, const IXML_FIELD *subfields); + +// set field for present tag, only valid to call within ParserStart +// callback. This will override the field which was specified for +// the matching IXML_FIELD structure +// Beware the ParserEndFunc in field will be called instead of the one in +// the original subfields list which matched this tag +// The current subfields are also set to field->subfields +extern void IXmlParserSetField(IXmlParserState_t *state, const IXML_FIELD *field); + +// output an error message and increment error_cnt +extern void IXmlParserPrintError(IXmlParserState_t *state, const char *format, ...); + +// output a warning message and increment warning_cnt +extern void IXmlParserPrintWarning(IXmlParserState_t *state, const char *format, ...); + +/* helper functions to aid getting field pointer in end_func callbacks */ +/* this is useful when implementing reusable end_func's which don't know exact + * datatype of object + */ +static _inline void* IXmlParserGetField(const IXML_FIELD* field, void *object) +{ + return (void*)((uintn)object + field->offset); +} + +/* helper functions to aid parsing of unsigned hex or decimal fields */ +/* return TRUE on success, FALSE on failure + * on failure IXmlParserPrintError called to describe error and move + * parser to Failed state + */ +extern boolean IXmlParseUint8(IXmlParserState_t *state, + XML_Char *content, unsigned len, uint8 *value); +extern boolean IXmlParseUint16(IXmlParserState_t *state, + XML_Char *content, unsigned len, uint16 *value); +extern boolean IXmlParseUint32(IXmlParserState_t *state, + XML_Char *content, unsigned len, uint32 *value); +extern boolean IXmlParseUint64(IXmlParserState_t *state, + XML_Char *content, unsigned len, uint64 *value); + +/* helper functions to aid parsing of signed decimal fields */ +extern boolean IXmlParseInt8(IXmlParserState_t *state, + XML_Char *content, unsigned len, int8 *value); +extern boolean IXmlParseInt16(IXmlParserState_t *state, + XML_Char *content, unsigned len, int16 *value); +extern boolean IXmlParseInt32(IXmlParserState_t *state, + XML_Char *content, unsigned len, int32 *value); +extern boolean IXmlParseInt64(IXmlParserState_t *state, + XML_Char *content, unsigned len, int64 *value); + +/* start_func for a simple structure. Allocates and zeros the structure using + * size specified in XML_FIELD + */ +extern void *IXmlParserStartStruct(IXmlParserState_t *state, void *parent, const char **attr); + +/* end tag function which is a noop. Use this with start_func=NULL + * to define XML_FIELDs which are output only + */ +extern void IXmlParserEndNoop(struct IXmlParserState *state, + const IXML_FIELD *field, + void *object, void *parent, XML_Char *content, unsigned len, + boolean valid); + +/* return TRUE if current field's contents are empty or all whitespace */ +boolean IXmlIsWhitespace(const XML_Char *str, boolean *hasNewline); + +/* discard leading and trailing whitespace in str, return new length + * str modified in place + */ +unsigned IXmlTrimWhitespace(XML_Char *str, unsigned len); + +extern FSTATUS IXmlParserInit(IXmlParserState_t *state, IXmlParserFlags_t flags, + const IXML_FIELD *subfields, void *object, void *context, + IXmlParserPrintMessage printError, + IXmlParserPrintMessage printWarning, + XML_Memory_Handling_Suite* memsuite); + +extern FSTATUS IXmlParserReadFile(IXmlParserState_t *state, FILE *file); +extern void IXmlParserDestroy(IXmlParserState_t *state); + +#ifndef VXWORKS +// parse supplied file. filename is only used in error messages +extern FSTATUS IXmlParseFile(FILE *file, const char* filename, + IXmlParserFlags_t flags, + const IXML_FIELD *subfields, void *object, void *context, + IXmlParserPrintMessage printError, + IXmlParserPrintMessage printWarning, + unsigned* tags_found, unsigned *fields_found); +// open and parse input_file +extern FSTATUS IXmlParseInputFile(const char *input_file, + IXmlParserFlags_t flags, + const IXML_FIELD *subfields, void *object, void *context, + IXmlParserPrintMessage printError, + IXmlParserPrintMessage printWarning, + unsigned* tags_found, unsigned *fields_found); +#else +// parse supplied file. filename is only used in error messages +extern FSTATUS IXmlParseFile(FILE *file, const char* filename, + IXmlParserFlags_t flags, + const IXML_FIELD *subfields, void *object, void *context, + IXmlParserPrintMessage printError, + IXmlParserPrintMessage printWarning, + unsigned* tags_found, unsigned *fields_found, + XML_Memory_Handling_Suite* memsuite); +// open and parse input_file +extern FSTATUS IXmlParseInputFile(const char *input_file, + IXmlParserFlags_t flags, + const IXML_FIELD *subfields, void *object, void *context, + IXmlParserPrintMessage printError, + IXmlParserPrintMessage printWarning, + unsigned* tags_found, unsigned *fields_found, + XML_Memory_Handling_Suite* memsuite); +#endif + +#ifdef __cplusplus +}; +#endif + +#endif /* _IBA_PUBLIC_IXML_H_ */ diff --git a/Xml/ixml_err.c b/Xml/ixml_err.c new file mode 100644 index 0000000..313b383 --- /dev/null +++ b/Xml/ixml_err.c @@ -0,0 +1,62 @@ +/* BEGIN_ICS_COPYRIGHT5 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + * ** END_ICS_COPYRIGHT5 ****************************************/ +/* [ICS VERSION STRING: unknown] */ + +/* this is a separate file because _XOPEN_SOURCE define breaks ib_sm.h */ + +#include +#include +#include +#include +#include +#include +#include +#define _GNU_SOURCE + +#ifdef VXWORKS +int snprintf(char *str, size_t count, const char *fmt, ...); +int vsnprintf(char *str, size_t count, const char *fmt, + va_list arg); +#endif + +typedef void (*IXmlParserPrintMessage)(const char *message); +extern void IXmlPrintMessage(const char *message); + +void IXmlPrintFileError(const char *input_file, IXmlParserPrintMessage printError) +{ + char buf[1024]; + char buf2[200] = "Unknown"; +#ifndef VXWORKS + (void)strerror_r(errno, buf2 ,sizeof(buf2)); +#else + (void)strerror_r(errno, buf2 /*,sizeof(buf2)*/); +#endif + snprintf(buf, sizeof(buf), "Unable to open input file: %s: %s", input_file, buf2); + (printError?printError:IXmlPrintMessage)(buf); +} diff --git a/Xml/ixml_ib.c b/Xml/ixml_ib.c new file mode 100644 index 0000000..f2b93c2 --- /dev/null +++ b/Xml/ixml_ib.c @@ -0,0 +1,1048 @@ +/* BEGIN_ICS_COPYRIGHT5 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + * ** END_ICS_COPYRIGHT5 ****************************************/ +/* [ICS VERSION STRING: unknown] */ + +#include +#if !defined(VXWORKS) || defined(BUILD_DMC) +#include +#endif +#include +#include +#include "iba/stl_sa_priv.h" +#include "iba/stl_pm.h" +#if defined(USE_NETF1_IP_STACK) +/* add this to avoid implicit declaration warning in mips/netf1 build */ +extern int snprintf (char *str, size_t count, const char *fmt, ...); +#endif +#include "iba/stl_helper.h" +#include +#include +#include +#include +#include +#include +#define _GNU_SOURCE + +#include "ixml_ib.h" + +#ifdef VXWORKS +#include "bspcommon/h/icsBspUtil.h" +#endif + +/* should be defined in ib_dm.h */ +#ifndef IOC_IDSTRING_SIZE +#define IOC_IDSTRING_SIZE 64 +#endif +#ifndef IOC_SERVICE_NAME_SIZE +#define IOC_SERVICE_NAME_SIZE 40 +#endif + +#ifndef SCNx8 +#define SCNx8 "x" +#endif + +/* sometimes a bitfield, so need to call with value instead of ptr */ +void IXmlOutputLIDValue(IXmlOutputState_t *state, const char *tag, STL_LID value) +{ + IXmlOutputHexPad32(state, tag, value); +} + +// only output if value != 0 +void IXmlOutputOptionalLIDValue(IXmlOutputState_t *state, const char *tag, STL_LID value) +{ + if (value) + IXmlOutputLIDValue(state, tag, value); +} + +void IXmlOutputLID(IXmlOutputState_t *state, const char *tag, void *data) +{ + IXmlOutputHexPad32(state, tag, *(STL_LID*)data); +} + +// only output if value != 0 +void IXmlOutputOptionalLID(IXmlOutputState_t *state, const char *tag, void *data) +{ + IXmlOutputOptionalHexPad32(state, tag, *(STL_LID*)data); +} + + +void IXmlOutputPKey(IXmlOutputState_t *state, const char *tag, void *data) +{ + IXmlOutputHexPad16(state, tag, (*(STL_PKEY_ELEMENT*)data).AsReg16); +} + +// only output if value != 0 +void IXmlOutputOptionalPKey(IXmlOutputState_t *state, const char *tag, void *data) +{ + IXmlOutputOptionalHexPad16(state, tag, (*(STL_PKEY_ELEMENT*)data).AsReg16); +} + + +void IXmlOutputGID(IXmlOutputState_t *state, const char *tag, void *data) +{ + IXmlOutputPrintIndent(state, "<%s>0x%016"PRIx64":0x%016"PRIx64"\n", tag, + ((IB_GID*)data)->AsReg64s.H, + ((IB_GID*)data)->AsReg64s.L, tag); +} + +// only output if value != 0 +void IXmlOutputOptionalGID(IXmlOutputState_t *state, const char *tag, void *data) +{ + if (0ULL != ((IB_GID*)data)->AsReg64s.H || 0ULL != ((IB_GID*)data)->AsReg64s.L) + IXmlOutputGID(state, tag, data); +} + +void IXmlOutputNodeType(IXmlOutputState_t *state, const char *tag, void *data) +{ + IXmlOutputStrUint(state, tag, StlNodeTypeToText(*(uint8*)data), *(uint8*)data); +} + +void IXmlOutputOptionalNodeType(IXmlOutputState_t *state, const char *tag, void *data) +{ + IXmlOutputOptionalStrUint(state, tag, StlNodeTypeToText(*(uint8*)data), *(uint8*)data); +} + +// parse NodeType string into a uint8 field and validate value +void IXmlParserEndNodeType(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + uint8 value; + + if (0 == strcasecmp(content, "FI")) { + value = STL_NODE_FI; + } else if (0 == strcasecmp(content, "SW")) { + value = STL_NODE_SW; + } else { + IXmlParserPrintError(state, "Invalid Node type: '%s' Must be FI or SW", content); + goto fail; + } + ASSERT(field->size == 1); + *(uint8 *)IXmlParserGetField(field, object) = value; +fail: + return; +} + +// parse NodeType_Int into a uint8 field and validate value +void IXmlParserEndNodeType_Int(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + uint8 value; + + if (IXmlParseUint8(state, content, len, &value)) { + if (value != STL_NODE_FI + && value != STL_NODE_SW) { + IXmlParserPrintError(state, "Invalid Node type: %u Must be (FI or SW): %u or %u", value, STL_NODE_FI, STL_NODE_SW); + } else { + ASSERT(field->size == 1); + *(uint8 *)IXmlParserGetField(field, object) = value; + } + } +} + + +void IXmlOutputNodeDesc(IXmlOutputState_t *state, const char *tag, void *data) +{ + IXmlOutputStrLen(state, tag, (const char*)data, NODE_DESCRIPTION_ARRAY_SIZE); +} + +// only output if value != "" +void IXmlOutputOptionalNodeDesc(IXmlOutputState_t *state, const char *tag, void *data) +{ + IXmlOutputOptionalStrLen(state, tag, (const char*)data, NODE_DESCRIPTION_ARRAY_SIZE); +} + +void IXmlOutputIocIDString(IXmlOutputState_t *state, const char *tag, void *data) +{ + IXmlOutputStrLen(state, tag, (const char*)data, IOC_IDSTRING_SIZE); +} + +// only output if value != "" +void IXmlOutputOptionalIocIDString(IXmlOutputState_t *state, const char *tag, void *data) +{ + IXmlOutputOptionalStrLen(state, tag, (const char*)data, IOC_IDSTRING_SIZE); +} + +void IXmlOutputServiceName(IXmlOutputState_t *state, const char *tag, void *data) +{ + IXmlOutputStrLen(state, tag, (const char*)data, IOC_SERVICE_NAME_SIZE); +} + +// only output if value != "" +void IXmlOutputOptionalServiceName(IXmlOutputState_t *state, const char *tag, void *data) +{ + IXmlOutputOptionalStrLen(state, tag, (const char*)data, IOC_SERVICE_NAME_SIZE); +} + +/* typically a bitfield, so need to call with value instead of ptr */ +void IXmlOutputPortStateValue(IXmlOutputState_t *state, const char *tag, uint8 value) +{ + IXmlOutputStrUint(state, tag, StlPortStateToText(value), value); +} + +// only output if value != 0 +void IXmlOutputOptionalPortStateValue(IXmlOutputState_t *state, const char *tag, uint8 value) +{ + IXmlOutputOptionalStrUint(state, tag, IbPortStateToText(value), value); +} + +void IXmlOutputPortState(IXmlOutputState_t *state, const char *tag, void *data) +{ + IXmlOutputPortStateValue(state, tag, *(uint8 *)data); +} + +// only output if value != 0 +void IXmlOutputOptionalPortState(IXmlOutputState_t *state, const char *tag, void *data) +{ + IXmlOutputOptionalPortStateValue(state, tag, *(uint8 *)data); +} + +/* link init reason */ +void IXmlOutputInitReasonValue(IXmlOutputState_t *state, const char *tag, uint8 value) +{ + IXmlOutputStrUint(state, tag, StlLinkInitReasonToText(value), value); +} + +void IXmlOutputOptionalInitReasonValue(IXmlOutputState_t *state, const char *tag, uint8 value) +{ + IXmlOutputOptionalStrUint(state, tag, StlLinkInitReasonToText(value), value); +} + +void IXmlOutputInitReason(IXmlOutputState_t *state, const char *tag, void *data) +{ + IXmlOutputInitReasonValue(state, tag, *(uint8 *)data); +} + +void IXmlOutputOptionalInitReason(IXmlOutputState_t *state, const char *tag, void *data) +{ + IXmlOutputOptionalInitReasonValue(state, tag, *(uint8 *)data); +} + +/* link down reason */ +void IXmlOutputDownReasonValue(IXmlOutputState_t *state, const char *tag, uint8 value) +{ + IXmlOutputStrUint(state, tag, StlLinkDownReasonToText(value), value); +} +void IXmlOutputOptionalDownReasonValue(IXmlOutputState_t *state, const char *tag, uint8 value) +{ + IXmlOutputOptionalStrUint(state, tag, StlLinkDownReasonToText(value), value); +} +void IXmlOutputDownReason(IXmlOutputState_t *state, const char *tag, void *data) +{ + IXmlOutputDownReasonValue(state, tag, *(uint8 *)data); +} +void IXmlOutputOptionalDownReason(IXmlOutputState_t *state, const char *tag, void *data) +{ + IXmlOutputOptionalDownReasonValue(state, tag, *(uint8 *)data); +} + +/* typically a bitfield, so need to call with value instead of ptr */ +void IXmlOutputPortPhysStateValue(IXmlOutputState_t *state, const char *tag, uint8 value) +{ + IXmlOutputStrUint(state, tag, StlPortPhysStateToText(value), value); +} + +// only output if value != 0 +void IXmlOutputOptionalPortPhysStateValue(IXmlOutputState_t *state, const char *tag, uint8 value) +{ + IXmlOutputOptionalStrUint(state, tag, StlPortPhysStateToText(value), value); +} + +void IXmlOutputPortPhysState(IXmlOutputState_t *state, const char *tag, void *data) +{ + IXmlOutputPortPhysStateValue(state, tag, *(uint8 *)data); +} + +// only output if value != 0 +void IXmlOutputOptionalPortPhysState(IXmlOutputState_t *state, const char *tag, void *data) +{ + IXmlOutputOptionalPortPhysStateValue(state, tag, *(uint8 *)data); +} + +/* typically a bitfield, so need to call with value instead of ptr */ +void IXmlOutputPortDownDefaultValue(IXmlOutputState_t *state, const char *tag, uint8 value) +{ + IXmlOutputStrUint(state, tag, IbPortDownDefaultToText(value), value); +} + +// only output if value != 0 +void IXmlOutputOptionalPortDownDefaultValue(IXmlOutputState_t *state, const char *tag, uint8 value) +{ + IXmlOutputOptionalStrUint(state, tag, IbPortDownDefaultToText(value), value); +} + +void IXmlOutputPortDownDefault(IXmlOutputState_t *state, const char *tag, void *data) +{ + IXmlOutputPortDownDefaultValue(state, tag, *(uint8 *)data); +} + +// only output if value != 0 +void IXmlOutputOptionalPortDownDefault(IXmlOutputState_t *state, const char *tag, void *data) +{ + IXmlOutputOptionalPortDownDefaultValue(state, tag, *(uint8 *)data); +} + + +/* typically a bitfield, so need to call with value instead of ptr */ +/* 0 has meaning, so no 'Optional' variations of this function */ +void IXmlOutputMKeyProtectValue(IXmlOutputState_t *state, const char *tag, uint8 value) +{ + IXmlOutputStrUint(state, tag, IbMKeyProtectToText(value), value); +} + +void IXmlOutputMKeyProtect(IXmlOutputState_t *state, const char *tag, void *data) +{ + IXmlOutputMKeyProtectValue(state, tag, *(uint8 *)data); +} +/* typically a bitfield, so need to call with value instead of ptr */ +void IXmlOutputRateValue(IXmlOutputState_t *state, const char *tag, uint8 value) +{ + IXmlOutputStrUint(state, tag, StlStaticRateToText(value), value); +} + +// only output if value != 0 +void IXmlOutputOptionalRateValue(IXmlOutputState_t *state, const char *tag, uint8 value) +{ + IXmlOutputOptionalStrUint(state, tag, StlStaticRateToText(value), value); +} + +void IXmlOutputRate(IXmlOutputState_t *state, const char *tag, void *data) +{ + IXmlOutputRateValue(state, tag, *(uint8 *)data); +} + +// only output if value != 0 +void IXmlOutputOptionalRate(IXmlOutputState_t *state, const char *tag, void *data) +{ + IXmlOutputOptionalRateValue(state, tag, *(uint8 *)data); +} + +// parse rates to uint8 multiplier string - validate rate inputs +boolean IXmlParseRateMult_Str(IXmlParserState_t *state, XML_Char *content, uint8 *value) +{ + if (!content || strlen(content) == 0) { + IXmlParserPrintError(state, "Empty contents"); + return FALSE; + } + + // skip whitespace + while (isspace(*content)) { + content++; + } + + if (0 == strcasecmp(content, "25g") || 0 == strcasecmp(content, "25")) { + *value = IB_STATIC_RATE_25G; + } else if (0 == strcasecmp(content, "50g") || 0 == strcasecmp(content, "50")) { + *value = IB_STATIC_RATE_56G; // STL_STATIC_RATE_50G + } else if (0 == strcasecmp(content, "12.5g") || 0 == strcasecmp(content, "12.5")) { + *value = IB_STATIC_RATE_14G; // STL_STATIC_RATE_12_5G + } else if (0 == strcasecmp(content, "37.5g") || 0 == strcasecmp(content, "37.5")) { + *value = IB_STATIC_RATE_40G; // STL_STATIC_RATE_37_5G + } else if (0 == strcasecmp(content, "75g") || 0 == strcasecmp(content, "75")) { + *value = IB_STATIC_RATE_80G; // STL_STATIC_RATE_75G + } else if (0 == strcasecmp(content, "100g") || 0 == strcasecmp(content, "100")) { + *value = IB_STATIC_RATE_100G; +#if 0 + // future + } else if (0 == strcasecmp(content, "225g") || 0 == strcasecmp(content, "250")) { + *value = STL_STATIC_RATE_225G; + } else if (0 == strcasecmp(content, "300g") || 0 == strcasecmp(content, "300")) { + *value = IB_STATIC_RATE_300G; + } else if (0 == strcasecmp(content, "400g") || 0 == strcasecmp(content, "400")) { + *value = STL_STATIC_RATE_400G; +#endif + } else { + IXmlParserPrintError(state, "Invalid Rate: '%s' Must be 25g, 50g, 75g, 100g", content); + return FALSE; + } + return TRUE; +} + +// parse Rate string into a uint8 field and validate value +void IXmlParserEndRate(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + uint8 value; + + if (0 == strcasecmp(content, "12.5g") || 0 == strcasecmp(content, "12.5")) { + value = IB_STATIC_RATE_14G; // STL_STATIC_RATE_12_5G + } else if (0 == strcasecmp(content, "25g") || 0 == strcasecmp(content, "25")) { + value = IB_STATIC_RATE_25G; + } else if (0 == strcasecmp(content, "37.5g") || 0 == strcasecmp(content, "37.5")) { + value = IB_STATIC_RATE_40G; // STL_STATIC_RATE_37_5G + } else if (0 == strcasecmp(content, "50g") || 0 == strcasecmp(content, "50")) { + value = IB_STATIC_RATE_56G; // STL_STATIC_RATE_50G + } else if (0 == strcasecmp(content, "75g") || 0 == strcasecmp(content, "75")) { + value = IB_STATIC_RATE_80G; // STL_STATIC_RATE_75G + } else if (0 == strcasecmp(content, "100g") || 0 == strcasecmp(content, "100")) { + value = IB_STATIC_RATE_100G; +#if 0 + // future + } else if (0 == strcasecmp(content, "200g") || 0 == strcasecmp(content, "200")) { + value = IB_STATIC_RATE_200G; + } else if (0 == strcasecmp(content, "225g") || 0 == strcasecmp(content, "225")) { + value = STL_STATIC_RATE_225G; + } else if (0 == strcasecmp(content, "300g") || 0 == strcasecmp(content, "300")) { + value = IB_STATIC_RATE_300G; + } else if (0 == strcasecmp(content, "400g") || 0 == strcasecmp(content, "400")) { + value = STL_STATIC_RATE_400G; +#endif + } else { + IXmlParserPrintError(state, "Invalid Rate: '%s' Must be 12.5g, 25g, 37.5g, 50g, 75g, 100g", content); + goto fail; + } + ASSERT(field->size == 1); + *(uint8 *)IXmlParserGetField(field, object) = value; +fail: + return; +} + +// parse Rate_Int into a uint8 field and validate value +void IXmlParserEndRate_Int(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + uint8 value; + + if (IXmlParseUint8(state, content, len, &value)) { + if (value != IB_STATIC_RATE_14G && value != IB_STATIC_RATE_25G + && value != IB_STATIC_RATE_40G && value != IB_STATIC_RATE_80G + && value != IB_STATIC_RATE_56G && value != IB_STATIC_RATE_100G ) { + IXmlParserPrintError(state, "Invalid Rate: %u Must be (12.5g, 25g, 37.5g, 50g, 75g, 100g): %u, %u, %u, %u, %u, %u", value, + IB_STATIC_RATE_14G, IB_STATIC_RATE_25G, + IB_STATIC_RATE_40G, IB_STATIC_RATE_56G, + IB_STATIC_RATE_80G, IB_STATIC_RATE_100G ); + } else { + ASSERT(field->size == 1); + *(uint8 *)IXmlParserGetField(field, object) = value; + } + } +} + +/* typically a bitfield, so need to call with value instead of ptr */ +/* 0 has meaning, so no 'Optional' variations of this function */ +void IXmlOutputLinkWidthValue(IXmlOutputState_t *state, const char* tag, uint16 value) +{ + char tempBuf[64]; + IXmlOutputStrUint(state, tag, StlLinkWidthToText(value, tempBuf, sizeof(tempBuf)), value); +} + +void IXmlOutputLinkWidth(IXmlOutputState_t *state, const char* tag, void *data) +{ + char tempBuf[64]; + IXmlOutputStrUint(state, tag, StlLinkWidthToText(*(uint16*)data, tempBuf, sizeof(tempBuf)), *(uint16*)data); +} + +/* typically a bitfield, so need to call with value instead of ptr */ +/* 0 has meaning, so no 'Optional' variations of this function */ +void IXmlOutputLinkSpeedValue(IXmlOutputState_t *state, const char* tag, uint16 value) +{ + char tempBuf[64]; + IXmlOutputStrUint(state, tag, StlLinkSpeedToText(value, tempBuf, sizeof(tempBuf)), value); +} + +void IXmlOutputLinkSpeed(IXmlOutputState_t *state, const char* tag, void *data) +{ + char tempBuf[64]; + IXmlOutputStrUint(state, tag, StlLinkSpeedToText(*(uint16*)data, tempBuf, sizeof(tempBuf)), *(uint16*)data); +} + +/* typically a bitfield, so need to call with value instead of ptr */ +void IXmlOutputMtuValue(IXmlOutputState_t *state, const char* tag, uint16 value) +{ + IXmlOutputUint(state, tag, GetBytesFromMtu(value)); +} + +// only output if value != 0 +void IXmlOutputOptionalMtuValue(IXmlOutputState_t *state, const char* tag, uint16 value) +{ + IXmlOutputOptionalUint(state, tag, GetBytesFromMtu(value)); +} + +void IXmlOutputMtu(IXmlOutputState_t *state, const char* tag, void *data) +{ + IXmlOutputUint(state, tag, GetBytesFromMtu(*(uint8*)data)); +} + +// only output if value != 0 +void IXmlOutputOptionalMtu(IXmlOutputState_t *state, const char* tag, void *data) +{ + IXmlOutputOptionalUint(state, tag, GetBytesFromMtu(*(uint8*)data)); +} + +// parse Mtu field, validate value and store as an IB_MTU +void IXmlParserEndMtu(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + uint16 value; + + if (IXmlParseUint16(state, content, len, &value)) { + if (value != 256 && value != 512 && value != 1024 + && value != 2048 && value != 4096 && value != 8192 && value != 10240) { + IXmlParserPrintError(state, "Invalid Mtu: %u Must be (256, 512, 1024, 2048, 4096, 8192, or 10240)", value); + } else { + ASSERT(field->size == 1); + *(uint8 *)IXmlParserGetField(field, object) = GetMtuFromBytes(value); + } + } +} + +/* typically a bitfield, so need to call with value instead of ptr */ +void IXmlOutputVLsValue(IXmlOutputState_t *state, const char* tag, uint8 value) +{ + char buf[8]; + + snprintf(buf, sizeof(buf), "%u+1", value); + IXmlOutputStrUint(state, tag, buf, value); +} + +// only output if value != 0 +void IXmlOutputOptionalVLsValue(IXmlOutputState_t *state, const char* tag, uint8 value) +{ + if (value) + IXmlOutputVLsValue(state, tag, value); +} + +void IXmlOutputVLs(IXmlOutputState_t *state, const char* tag, void *data) +{ + IXmlOutputVLsValue(state, tag, *(uint8*)data); +} + +// only output if value != 0 +void IXmlOutputOptionalVLs(IXmlOutputState_t *state, const char* tag, void *data) +{ + IXmlOutputOptionalVLsValue(state, tag, *(uint8*)data); +} + +/* typically a bitfield, so need to call with value instead of ptr */ +/* 0 has meaning, so no 'Optional' variations of this function */ +void IXmlOutputInitTypeValue(IXmlOutputState_t *state, const char* tag, uint8 value) +{ + char buf[80]; + + snprintf(buf, 80, "%s%s%s%s", + value & PORT_INIT_TYPE_NOLOAD?"NL ": "", + value & PORT_INIT_TYPE_PRESERVE_CONTENT?"PC ": "", + value & PORT_INIT_TYPE_PRESERVE_PRESENCE?"PP ": "", + value & PORT_INIT_TYPE_DO_NOT_RESUSCITATE?"NR ": ""); + + IXmlOutputStrUint(state, tag, buf, value); +} + +void IXmlOutputInitType(IXmlOutputState_t *state, const char* tag, void *data) +{ + IXmlOutputInitTypeValue(state, tag, *(uint8*)data); +} + +/* typically a bitfield, so need to call with value instead of ptr */ +/* 0 has meaning, so no 'Optional' variations of this function */ +void IXmlOutputTimeoutMultValue(IXmlOutputState_t *state, const char* tag, uint8 value) +{ + char buf[8]; + FormatTimeoutMult(buf, value); + IXmlOutputStrUint(state, tag, buf, value); +} + +void IXmlOutputTimeoutMult(IXmlOutputState_t *state, const char* tag, void *data) +{ + IXmlOutputTimeoutMultValue(state, tag, *(uint8*)data); +} + +/* typically a bitfield, so need to call with value instead of ptr */ +/* 0 has meaning, so no 'Optional' variations of this function */ +void IXmlOutputHOQLifeValue(IXmlOutputState_t *state, const char* tag, uint8 value) +{ + char buf[9]; + if (value > IB_LIFETIME_MAX) { + memcpy(buf, "Infinite", 9); + } else { + FormatTimeoutMult(buf, value); + } + IXmlOutputStrUint(state, tag, buf, value); +} + +void IXmlOutputHOQLife(IXmlOutputState_t *state, const char* tag, void *data) +{ + IXmlOutputHOQLifeValue(state, tag, *(uint8*)data); +} + +void IXmlOutputIPAddrIPV6(IXmlOutputState_t *state, const char *tag, void *data) +{ + int i; + IXmlOutputStartTag(state, tag); + for (i = 0; i < 16; ++i){ + IXmlOutputPrint(state, "%02x", ((STL_IPV6_IP_ADDR *)data)->addr[i]); + } + IXmlOutputEndTag(state, tag); +} + +void IXmlOutputIPAddrIPV4(IXmlOutputState_t *state, const char *tag, void *data) +{ + int i; + IXmlOutputStartTag(state, tag); + for (i = 0; i < 4; ++i){ + IXmlOutputPrint(state, "%02x", ((STL_IPV4_IP_ADDR *)data)->addr[i]); + } + IXmlOutputEndTag(state, tag); +} + +void IXmlParserEndIPAddrIPV6(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + int i, ret; + for (i = 0; i < 16; ++i){//read in hexadecimal address 2 digits at a time + ret = sscanf((char *)(content + 2*i), "%2"SCNx8, &(((STL_IPV6_IP_ADDR *)IXmlParserGetField(field, object))->addr[i])); + if (ret != 1){ + IXmlParserPrintError(state, "Error parsing IPV6 address:%s", strerror(errno)); + break; + } + } +} + +void IXmlParserEndIPAddrIPV4(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + int i, ret; + for (i = 0; i < 4; ++i){ //read in hexadecimal address 2 digits at a time + ret = sscanf((char *)(content + 2*i), "%2"SCNx8, &(((STL_IPV4_IP_ADDR *)IXmlParserGetField(field, object))->addr[i])); + if (ret != 1){ + IXmlParserPrintError(state, "Error parsing IPV4 address:%s", strerror(errno)); + break; + } + } +} + +// parse TimeoutMult string into a uint8 field and validate value +// does not handle "infinite". Returns value between 0 and 31 inclusive +boolean IXmlParseTimeoutMult_Str(IXmlParserState_t *state, XML_Char *content, unsigned len, uint8 *value) +{ + char *endptr = NULL; + uint64 temp; + FSTATUS status; + + if (! len) { + IXmlParserPrintError(state, "Empty contents"); + return FALSE; + } + status = StringToUint64(&temp, content, &endptr, 0, TRUE /*skip_trail_whitespace */); + if (status == FINVALID_SETTING) { + IXmlParserPrintError(state, "Numeric Value too large for field: %s", content); + return FALSE; + } else if (status != FSUCCESS) { + IXmlParserPrintError(state, "Invalid contents: %s", content); + return FALSE; + } else if (*endptr == '\0') { + IXmlParserPrintError(state, "Invalid contents, no units: %s", content); + return FALSE; + } + + // now parse units + content = endptr; + // we round up to next valid multiplier + // values over 2.4 hours get the max multiplier + if (strncasecmp(content,"ns",2) == 0) { + content += 2; + temp = TimeoutTimeToMult(temp/1000); + } else if (strncasecmp(content,"us",2) == 0) { + content += 2; + temp = TimeoutTimeToMult(temp); + } else if (strncasecmp(content,"ms",2) == 0) { + content += 2; + if (temp >= IB_MAX_TIMEOUT_MULT_MS) + temp = 31; + else + temp = TimeoutTimeMsToMult((uint32)temp); + } else if (strncasecmp(content,"s",1) == 0) { + content++; + if (temp >= IB_MAX_TIMEOUT_MULT_MS/1000) + temp = 31; + else + temp = TimeoutTimeMsToMult(temp*1000); + } else if (strncasecmp(content,"m",1) == 0) { + content++; + if (temp >= IB_MAX_TIMEOUT_MULT_MS/(60*1000)) + temp = 31; + else + temp = TimeoutTimeMsToMult(temp*60*1000); + } else if (strncasecmp(content,"h",1) == 0) { + content++; + if (temp >= IB_MAX_TIMEOUT_MULT_MS/(60*60*1000)) + temp = 31; + else + temp = TimeoutTimeMsToMult(temp*60*60*1000); + } else { + IXmlParserPrintError(state, "Invalid contents, invalid units: %s", content); + return FALSE; + } + + // make sure rest is trailing whitespace + while (isspace(*content)) + content++; + if (*content != '\0') + goto fail; + *value = (uint8)temp; + return TRUE; +fail: + IXmlParserPrintError(state, "Invalid contents, invalid text after units: %s", content); + return FALSE; +} + +// parse TimeoutMult string into a uint8 field and validate value +// does not handle "infinite". Returns value between 0 and 31 inclusive +void IXmlParserEndTimeoutMult_Str(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + uint8 value; + + if (! IXmlParseTimeoutMult_Str(state, content, len, &value)) + goto fail; + ASSERT(field->size == 1); + *(uint8 *)IXmlParserGetField(field, object) = value; +fail: + return; +} + +// parse TimeoutMult string into a uint32 field and validate value +// does not handle "infinite". Returns value between 0 and 31 inclusive +void IXmlParserEndTimeoutMult32_Str(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + uint8 value; + + if (! IXmlParseTimeoutMult_Str(state, content, len, &value)) + goto fail; + ASSERT(field->size == 4); + *(uint32 *)IXmlParserGetField(field, object) = value; +fail: + return; +} + +// parse TimeoutMult string into a uint8 field and validate value +// treat "infinite" or multipliers > IB_LIFETIME_MAX as IB_LIFETIME_MAX+1 +boolean IXmlParseTimeoutMultInf_Str(IXmlParserState_t *state, XML_Char *content, unsigned len, uint8 *value) +{ + XML_Char *p = content; + + if (! len) { + IXmlParserPrintError(state, "Empty contents"); + return FALSE; + } + // ignore leading whitespace + while (isspace(*content)) { + content++; + } + if (strncasecmp(content,"infinite",8) == 0) { + content += 8; + // make sure rest is trailing whitespace + while (isspace(*content)) + content++; + if (*content != '\0') + goto fail; + *value = IB_LIFETIME_MAX+1; + return TRUE; + } else { + uint8 temp; + if (! IXmlParseTimeoutMult_Str(state, content, len, &temp)) + return FALSE; + if (temp > IB_LIFETIME_MAX) + temp = IB_LIFETIME_MAX+1; + *value = temp; + return TRUE; + } +fail: + IXmlParserPrintError(state, "Invalid contents: %s", p); + return FALSE; +} + +void IXmlParserEndHoqTimeout_Str(IXmlParserState_t *state, + const IXML_FIELD *field, void *object, void *parent, XML_Char *content, + unsigned int len, boolean valid) +{ + uint8_t value; + if (!IXmlParseTimeoutMultInf_Str(state, content, len, &value)) { + return; + } + + if (value > IB_LIFETIME_MAX) { + char minBuf[8]; + char maxBuf[8]; + FormatTimeoutMult(minBuf, 0); + FormatTimeoutMult(maxBuf, IB_LIFETIME_MAX); + IXmlParserPrintWarning(state, "%s is outside allowed range %s-%s. Setting to %s.", + content, minBuf, maxBuf, maxBuf); + value = IB_LIFETIME_MAX; + } + + *(uint32_t *)IXmlParserGetField(field, object) = value; +} + +void IXmlParserEndHoqTimeout_Int(IXmlParserState_t *state, + const IXML_FIELD *field, void *object, void *parent, XML_Char *content, + unsigned int len, boolean valid) +{ + uint32_t value; + if (!IXmlParseUint32(state, content, len, &value)) { + return; + } + + if (value > IB_LIFETIME_MAX) { + IXmlParserPrintWarning(state, "%u is outside allowed range 0-%u. Setting to %u.", + value, IB_LIFETIME_MAX, IB_LIFETIME_MAX); + value = IB_LIFETIME_MAX; + } + + *(uint32_t *)IXmlParserGetField(field, object) = value; +} + + +/* typically a bitfield, so need to call with value instead of ptr */ +/* 0 has meaning, so no 'Optional' variations of this function */ +void IXmlOutputSMStateValue(IXmlOutputState_t *state, const char* tag, uint8 value) +{ + IXmlOutputStrUint(state, tag, IbSMStateToText(value), value); +} + +void IXmlOutputSMState(IXmlOutputState_t *state, const char* tag, void *data) +{ + IXmlOutputSMStateValue(state, tag, *(uint8*) data); +} + +/* typically a bitfield, so need to call with value instead of ptr */ +/* 0 has meaning, so no 'Optional' variations of this function */ +void IXmlOutputOnOffValue(IXmlOutputState_t *state, const char* tag, uint8 value) +{ + IXmlOutputStrUint(state, tag, value?"On":"Off", value); +} + +void IXmlOutputOnOff(IXmlOutputState_t *state, const char* tag, void *data) +{ + IXmlOutputOnOffValue(state, tag, *(uint8*)data); +} + +/****************************************************************************/ +void IXmlOutputPathRecord(IXmlOutputState_t *state, const char* tag, void *data) +{ + IB_PATH_RECORD *pPathRecord = (IB_PATH_RECORD*)data; + + IXmlOutputStartTag(state, tag); + IXmlOutputGID(state, "SGID", &pPathRecord->SGID); + IXmlOutputGID(state, "DGID", &pPathRecord->DGID); + IXmlOutputLID(state, "SLID", &pPathRecord->SLID); + IXmlOutputLID(state, "DLID", &pPathRecord->DLID); + IXmlOutputStrUint(state, "Reversible", pPathRecord->Reversible?"Y":"N", pPathRecord->Reversible); + IXmlOutputPKey(state, "PKey", &pPathRecord->P_Key); + IXmlOutputStrUint(state, "Raw", pPathRecord->u1.s.RawTraffic?"Y":"N", pPathRecord->u1.s.RawTraffic); + IXmlOutputHex(state, "FlowLabel", pPathRecord->u1.s.FlowLabel); + IXmlOutputHex(state, "HopLimit", pPathRecord->u1.s.HopLimit); + IXmlOutputHex(state, "TClass", pPathRecord->TClass); + IXmlOutputUint(state, "SL", pPathRecord->u2.s.SL); + IXmlOutputUint(state, "Mtu", GetBytesFromMtu(pPathRecord->Mtu)); + IXmlOutputRateValue(state, "Rate", pPathRecord->Rate); + IXmlOutputTimeoutMultValue(state, "PktLifeTime", pPathRecord->PktLifeTime); + IXmlOutputUint(state, "Preference", pPathRecord->Preference); + IXmlOutputEndTag(state, tag); +} + +// only output if value != NULL +void IXmlOutputOptionalPathRecord(IXmlOutputState_t *state, const char* tag, void *data) +{ + if (data) + IXmlOutputPathRecord(state, tag, data); +} + +/****************************************************************************/ +IXML_FIELD XmlTraceRecordFields[] = { + { tag:"IDGeneration", format:'H', IXML_FIELD_INFO(STL_TRACE_RECORD, IDGeneration) }, + { tag:"NodeType", format:'k', IXML_FIELD_INFO(STL_TRACE_RECORD, NodeType), format_func:IXmlOutputNodeType, end_func:IXmlParserEndNoop }, // outputs both + { tag:"NodeType_Int", format:'K', IXML_FIELD_INFO(STL_TRACE_RECORD, NodeType), format_func:IXmlOutputNoop, end_func:IXmlParserEndNodeType_Int }, // inputs Int, ignore string on input + { tag:"NodeID", format:'H', IXML_FIELD_INFO(STL_TRACE_RECORD, NodeID) }, + { tag:"ChassisID", format:'H', IXML_FIELD_INFO(STL_TRACE_RECORD, ChassisID) }, + { tag:"EntryPortID", format:'H', IXML_FIELD_INFO(STL_TRACE_RECORD, EntryPortID) }, + { tag:"ExitPortID", format:'H', IXML_FIELD_INFO(STL_TRACE_RECORD, ExitPortID) }, + { tag:"EntryPort", format:'D', IXML_FIELD_INFO(STL_TRACE_RECORD, EntryPort) }, + { tag:"ExitPort", format:'D', IXML_FIELD_INFO(STL_TRACE_RECORD, ExitPort) }, + { NULL } +}; + +void IXmlOutputTraceRecord(IXmlOutputState_t *state, const char* tag, void *data) +{ + IXmlOutputStruct(state, tag, data, NULL, XmlTraceRecordFields); +} + +// only output if value != NULL +void IXmlOutputOptionalTraceRecord(IXmlOutputState_t *state, const char* tag, void *data) +{ + IXmlOutputOptionalStruct(state, tag, data, NULL, XmlTraceRecordFields); +} + +#if !defined(VXWORKS) || defined(BUILD_DMC) +/****************************************************************************/ +/* IocService Input/Output functions */ + +static void IocServiceXmlFormatAttr(IXmlOutputState_t *state, void *data) +{ + IXmlOutputPrint(state, " id=\""); + IXmlOutputPrintStrLen(state, (char*)((IOC_SERVICE*)data)->Name, IOC_SERVICE_NAME_SIZE); + IXmlOutputPrint(state, "\""); +} + +IXML_FIELD IocServiceFields[] = { + { tag:"Name", format:'C', IXML_FIELD_INFO(IOC_SERVICE, Name) }, + { tag:"Id", format:'H', IXML_FIELD_INFO(IOC_SERVICE, Id) }, + { NULL } +}; + +void IocServiceXmlOutput(IXmlOutputState_t *state, const char *tag, void *data) +{ + IXmlOutputStruct(state, tag, (IOC_SERVICE*)data, IocServiceXmlFormatAttr, IocServiceFields); +} + +// only output if value != NULL +void IocServiceXmlOutputOptional(IXmlOutputState_t *state, const char *tag, void *data) +{ + IXmlOutputOptionalStruct(state, tag, (IOC_SERVICE*)data, IocServiceXmlFormatAttr, IocServiceFields); +} +#endif + +/* caller must supply IocServiceXmlParserStart and IocServiceXmlParserEnd */ + +/****************************************************************************/ +/* SwitchInfo Input/Output functions */ + +/* bitfields needs special handling: LID */ +static void SwitchInfoXmlOutputLID(IXmlOutputState_t *state, const char *tag, void *data) +{ + IXmlOutputLIDValue(state, tag, ((STL_SWITCHINFO_RECORD *)data)->RID.LID); +} + +static void SwitchInfoXmlParserEndLID(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + uint32 value; + + if (IXmlParseUint32(state, content, len, &value)) + ((STL_SWITCHINFO_RECORD *)object)->RID.LID = value; +} + +static void IXmlParserEndMulticastFDBTop(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + uint32 value; + + if (IXmlParseUint32(state, content, len, &value)) { + if (IS_MCAST16(value)) + value = MCAST16_TO_MCAST32(value); + if (value && ((value < STL_LID_MULTICAST_BEGIN) || (value > STL_LID_MULTICAST_END))) + IXmlParserPrintError(state, "MulticastFDBTop value 0x%08x out of range. Must be 0 or in the range 0x%08x through 0x%08x\n", value, STL_LID_MULTICAST_BEGIN, STL_LID_MULTICAST_END); + else + ((STL_SWITCHINFO_RECORD *)object)->SwitchInfoData.MulticastFDBTop = value; + } +} + +/* bitfields needs special handling: LifeTimeValue */ +static void SwitchInfoXmlOutputLifeTimeValue(IXmlOutputState_t *state, const char *tag, void *data) +{ + IXmlOutputTimeoutMultValue(state, tag, + ((STL_SWITCHINFO_RECORD*)data)->SwitchInfoData.u1.s.LifeTimeValue); +} + +static void SwitchInfoXmlParserEndLifeTimeValue(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + uint8 value; + + if (IXmlParseUint8(state, content, len, &value)) + ((STL_SWITCHINFO_RECORD*)object)->SwitchInfoData.u1.s.LifeTimeValue = value; +} + +/* bitfields needs special handling: PortStateChange */ +static void SwitchInfoXmlOutputPortStateChange(IXmlOutputState_t *state, const char *tag, void *data) +{ + IXmlOutputUint(state, tag, ((STL_SWITCHINFO_RECORD *)data)->SwitchInfoData.u1.s.PortStateChange); +} + +static void SwitchInfoXmlParserEndPortStateChange(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + uint8 value; + + if (IXmlParseUint8(state, content, len, &value)) + ((STL_SWITCHINFO_RECORD *)object)->SwitchInfoData.u1.s.PortStateChange = value; +} + +/* bitfields needs special handling: MulticastMask */ +static void SwitchInfoXmlOutputMulticastMask(IXmlOutputState_t *state, const char *tag, void *data) +{ + IXmlOutputHex(state, tag, ((STL_SWITCHINFO_RECORD *)data)->SwitchInfoData.MultiCollectMask.MulticastMask); +} + +static void SwitchInfoXmlParserEndMulticastMask(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + uint8 value; + + if (IXmlParseUint8(state, content, len, &value)) + ((STL_SWITCHINFO_RECORD *)object)->SwitchInfoData.MultiCollectMask.MulticastMask = value; +} + +/* bitfields needs special handling: CollectiveMask */ +static void SwitchInfoXmlOutputCollectiveMask(IXmlOutputState_t *state, const char *tag, void *data) +{ + IXmlOutputHex(state, tag, ((STL_SWITCHINFO_RECORD *)data)->SwitchInfoData.MultiCollectMask.CollectiveMask); +} + +static void SwitchInfoXmlParserEndCollectiveMask(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + uint8 value; + + if (IXmlParseUint8(state, content, len, &value)) + ((STL_SWITCHINFO_RECORD *)object)->SwitchInfoData.MultiCollectMask.CollectiveMask = value; +} + +IXML_FIELD SwitchInfoFields[] = { + { tag:"LID", format:'K', format_func:SwitchInfoXmlOutputLID, end_func:SwitchInfoXmlParserEndLID }, // bitfield + { tag:"LinearFDBCap", format:'U', IXML_FIELD_INFO(STL_SWITCHINFO_RECORD, SwitchInfoData.LinearFDBCap) }, + { tag:"MulticastFDBCap", format:'U', IXML_FIELD_INFO(STL_SWITCHINFO_RECORD, SwitchInfoData.MulticastFDBCap) }, + { tag:"LinearFDBTop", format:'U', IXML_FIELD_INFO(STL_SWITCHINFO_RECORD, SwitchInfoData.LinearFDBTop) }, + { tag:"MulticastFDBTop", format:'U', IXML_FIELD_INFO(STL_SWITCHINFO_RECORD, SwitchInfoData.MulticastFDBTop), end_func:IXmlParserEndMulticastFDBTop}, + { tag:"IPAddrIPV6", format:'k', format_func:IXmlOutputIPAddrIPV6, IXML_FIELD_INFO(STL_SWITCHINFO_RECORD, SwitchInfoData.IPAddrIPV6.addr), end_func:IXmlParserEndIPAddrIPV6}, + { tag:"IPAddrIPV4", format:'k', format_func:IXmlOutputIPAddrIPV4, IXML_FIELD_INFO(STL_SWITCHINFO_RECORD, SwitchInfoData.IPAddrIPV4.addr), end_func:IXmlParserEndIPAddrIPV4}, + { tag:"LifeTimeValue", format:'k', format_func:SwitchInfoXmlOutputLifeTimeValue, end_func:IXmlParserEndNoop }, // output only bitfield + { tag:"LifeTimeValue_Int", format:'K', format_func:IXmlOutputNoop, end_func:SwitchInfoXmlParserEndLifeTimeValue }, // input only bitfield + { tag:"PortStateChange", format:'K', format_func:SwitchInfoXmlOutputPortStateChange, end_func:SwitchInfoXmlParserEndPortStateChange }, // bitfield + { tag:"PartitionEnforcementCap", format:'U', IXML_FIELD_INFO(STL_SWITCHINFO_RECORD, SwitchInfoData.PartitionEnforcementCap) }, + { tag:"U2", format:'X', IXML_FIELD_INFO(STL_SWITCHINFO_RECORD, SwitchInfoData.u2.AsReg8) }, + { tag:"CapabilityMask", format:'X', IXML_FIELD_INFO(STL_SWITCHINFO_RECORD, SwitchInfoData.CapabilityMask) }, + { tag:"MulticastMask", format:'k', format_func:SwitchInfoXmlOutputMulticastMask, end_func:SwitchInfoXmlParserEndMulticastMask }, // bitfield + { tag:"CollectiveMask", format:'k', format_func:SwitchInfoXmlOutputCollectiveMask, end_func:SwitchInfoXmlParserEndCollectiveMask }, // bitfield + { tag:"RoutingModeSupported", format:'X', IXML_FIELD_INFO(STL_SWITCHINFO_RECORD, SwitchInfoData.RoutingMode.Supported) }, + { tag:"RoutingModeEnabled", format:'X', IXML_FIELD_INFO(STL_SWITCHINFO_RECORD, SwitchInfoData.RoutingMode.Enabled) }, + { tag:"PortGroupFDBCap", format:'u', IXML_FIELD_INFO(STL_SWITCHINFO_RECORD, SwitchInfoData.PortGroupFDBCap) }, // optional to retain compatibility with snapshots made by older versions of OPA. + { tag:"PortGroupCap", format:'U', IXML_FIELD_INFO(STL_SWITCHINFO_RECORD, SwitchInfoData.PortGroupCap) }, + { tag:"PortGroupTop", format:'U', IXML_FIELD_INFO(STL_SWITCHINFO_RECORD, SwitchInfoData.PortGroupTop) }, + { tag:"AdaptiveRouting", format:'x', IXML_FIELD_INFO(STL_SWITCHINFO_RECORD, SwitchInfoData.AdaptiveRouting.AsReg16) }, + { NULL } +}; + +void SwitchInfoXmlOutput(IXmlOutputState_t *state, const char *tag, void *data) +{ + IXmlOutputStruct(state, tag, (STL_SWITCHINFO_RECORD*)data, NULL, SwitchInfoFields); +} + +// only output if value != NULL +void SwitchInfoXmlOutputOptional(IXmlOutputState_t *state, const char *tag, void *data) +{ + IXmlOutputOptionalStruct(state, tag, (STL_SWITCHINFO_RECORD*)data, NULL, SwitchInfoFields); +} + +/* caller must supply SwitchInfoXmlParserStart and SwitchInfoXmlParserEnd */ diff --git a/Xml/ixml_ib.h b/Xml/ixml_ib.h new file mode 100644 index 0000000..ebfa4a3 --- /dev/null +++ b/Xml/ixml_ib.h @@ -0,0 +1,160 @@ +/* BEGIN_ICS_COPYRIGHT2 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT2 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +#ifndef _IBA_PUBLIC_IXML_IB_H_ +#define _IBA_PUBLIC_IXML_IB_H_ + +#include +#include +#include "ixml.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* sometimes a bitfield, so need to call with value instead of ptr */ +extern void IXmlOutputLIDValue(IXmlOutputState_t *state, const char *tag, STL_LID value); +extern void IXmlOutputOptionalLIDValue(IXmlOutputState_t *state, const char *tag, STL_LID value); +extern void IXmlOutputLID(IXmlOutputState_t *state, const char *tag, void *data); +extern void IXmlOutputOptionalLID(IXmlOutputState_t *state, const char *tag, void *data); +extern void IXmlOutputPKey(IXmlOutputState_t *state, const char *tag, void *data); +extern void IXmlOutputOptionalPKey(IXmlOutputState_t *state, const char *tag, void *data); +extern void IXmlOutputGID(IXmlOutputState_t *state, const char *tag, void *data); +extern void IXmlOutputOptionalGID(IXmlOutputState_t *state, const char *tag, void *data); +extern void IXmlOutputNodeType(IXmlOutputState_t *state, const char *tag, void *data); +extern void IXmlOutputOptionalNodeType(IXmlOutputState_t *state, const char *tag, void *data); +extern void IXmlParserEndNodeType(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid); +extern void IXmlParserEndNodeType_Int(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid); +extern void IXmlOutputNodeDesc(IXmlOutputState_t *state, const char *tag, void *data); +extern void IXmlOutputOptionalNodeDesc(IXmlOutputState_t *state, const char *tag, void *data); +extern void IXmlOutputIocIDString(IXmlOutputState_t *state, const char *tag, void *data); +extern void IXmlOutputOptionalIocIDString(IXmlOutputState_t *state, const char *tag, void *data); +extern void IXmlOutputServiceName(IXmlOutputState_t *state, const char *tag, void *data); +extern void IXmlOutputOptionalServiceName(IXmlOutputState_t *state, const char *tag, void *data); +/* typically a bitfield, so need to call with value instead of ptr */ +extern void IXmlOutputPortStateValue(IXmlOutputState_t *state, const char *tag, uint8 value); +extern void IXmlOutputOptionalPortStateValue(IXmlOutputState_t *state, const char *tag, uint8 value); +extern void IXmlOutputPortState(IXmlOutputState_t *state, const char *tag, void *data); +extern void IXmlOutputOptionalPortState(IXmlOutputState_t *state, const char *tag, void *data); +extern void IXmlOutputInitReasonValue(IXmlOutputState_t *state, const char *tag, uint8 value); +extern void IXmlOutputOptionalInitReasonValue(IXmlOutputState_t *state, const char *tag, uint8 value); +extern void IXmlOutputInitReason(IXmlOutputState_t *state, const char *tag, void *data); +extern void IXmlOutputOptionalInitReason(IXmlOutputState_t *state, const char *tag, void *data); +extern void IXmlOutputDownReasonValue(IXmlOutputState_t *state, const char *tag, uint8 value); +extern void IXmlOutputOptionalDownReasonValue(IXmlOutputState_t *state, const char *tag, uint8 value); +extern void IXmlOutputDownReason(IXmlOutputState_t *state, const char *tag, void *data); +extern void IXmlOutputOptionalDownReason(IXmlOutputState_t *state, const char *tag, void *data); +/* typically a bitfield, so need to call with value instead of ptr */ +extern void IXmlOutputPortPhysStateValue(IXmlOutputState_t *state, const char *tag, uint8 value); +extern void IXmlOutputPortOptionalPhysStateValue(IXmlOutputState_t *state, const char *tag, uint8 value); +extern void IXmlOutputPortPhysState(IXmlOutputState_t *state, const char *tag, void *data); +extern void IXmlOutputPortOptionalPhysState(IXmlOutputState_t *state, const char *tag, void *data); +/* typically a bitfield, so need to call with value instead of ptr */ +extern void IXmlOutputPortDownDefaultValue(IXmlOutputState_t *state, const char *tag, uint8 value); +extern void IXmlOutputOptionalPortDownDefaultValue(IXmlOutputState_t *state, const char *tag, uint8 value); +extern void IXmlOutputPortDownDefault(IXmlOutputState_t *state, const char *tag, void *data); +extern void IXmlOutputOptionalPortDownDefault(IXmlOutputState_t *state, const char *tag, void *data); +/* typically a bitfield, so need to call with value instead of ptr */ +extern void IXmlOutputMKeyProtectValue(IXmlOutputState_t *state, const char *tag, uint8 value); +extern void IXmlOutputMKeyProtect(IXmlOutputState_t *state, const char *tag, void *data); +/* typically a bitfield, so need to call with value instead of ptr */ +extern void IXmlOutputRateValue(IXmlOutputState_t *state, const char *tag, uint8 value); +extern void IXmlOutputOptionalRateValue(IXmlOutputState_t *state, const char *tag, uint8 value); +extern void IXmlOutputRate(IXmlOutputState_t *state, const char *tag, void *data); +extern void IXmlOutputOptionalRate(IXmlOutputState_t *state, const char *tag, void *data); +extern boolean IXmlParseRateMult_Str(IXmlParserState_t *state, XML_Char *content, uint8 *value); +extern void IXmlParserEndRate(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid); +extern void IXmlParserEndRate_Int(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid); +/* typically a bitfield, so need to call with value instead of ptr */ +extern void IXmlOutputLinkWidthValue(IXmlOutputState_t *state, const char* tag, uint16 value); +extern void IXmlOutputLinkWidth(IXmlOutputState_t *state, const char* tag, void *data); +/* typically a bitfield, so need to call with value instead of ptr */ +extern void IXmlOutputLinkSpeedValue(IXmlOutputState_t *state, const char* tag, uint16 value); +extern void IXmlOutputLinkSpeed(IXmlOutputState_t *state, const char* tag, void *data); +/* typically a bitfield, so need to call with value instead of ptr */ +extern void IXmlOutputMtuValue(IXmlOutputState_t *state, const char* tag, uint16 value); +extern void IXmlOutputOptionalMtuValue(IXmlOutputState_t *state, const char* tag, uint16 value); +extern void IXmlOutputMtu(IXmlOutputState_t *state, const char* tag, void *data); +extern void IXmlOutputOptionalMtu(IXmlOutputState_t *state, const char* tag, void *data); +extern void IXmlParserEndMtu(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid); +/* typically a bitfield, so need to call with value instead of ptr */ +extern void IXmlOutputVLsValue(IXmlOutputState_t *state, const char* tag, uint8 value); +extern void IXmlOutputOptionalVLsValue(IXmlOutputState_t *state, const char* tag, uint8 value); +extern void IXmlOutputVLs(IXmlOutputState_t *state, const char* tag, void *data); +extern void IXmlOutputOptionalVLs(IXmlOutputState_t *state, const char* tag, void *data); +/* typically a bitfield, so need to call with value instead of ptr */ +extern void IXmlOutputInitTypeValue(IXmlOutputState_t *state, const char* tag, uint8 value); +extern void IXmlOutputInitType(IXmlOutputState_t *state, const char* tag, void *data); +/* typically a bitfield, so need to call with value instead of ptr */ +extern void IXmlOutputTimeoutMultValue(IXmlOutputState_t *state, const char* tag, uint8 value); +extern void IXmlOutputTimeoutMult(IXmlOutputState_t *state, const char* tag, void *data); +/* typically a bitfield, so need to call with value instead of ptr */ +extern void IXmlOutputHOQLifeValue(IXmlOutputState_t *state, const char* tag, uint8 value); +extern void IXmlOutputHOQLife(IXmlOutputState_t *state, const char* tag, void *data); +extern void IXmlOutputIPAddrIPV6(IXmlOutputState_t *state, const char* tag, void *data); +extern void IXmlOutputIPAddrIPV4(IXmlOutputState_t *state, const char* tag, void *data); +extern void IXmlParserEndIPAddrIPV6(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid); +extern void IXmlParserEndIPAddrIPV4(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid); +extern boolean IXmlParseTimeoutMult_Str(IXmlParserState_t *state, XML_Char *content, unsigned len, uint8 *value); +extern void IXmlParserEndTimeoutMult_Str(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid); +extern void IXmlParserEndTimeoutMult32_Str(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid); +extern boolean IXmlParseTimeoutMultInf_Str(IXmlParserState_t *state, XML_Char *content, unsigned len, uint8 *value); + +/* Specialized timeout parsing for SwitchLifetime and HoQLife elements. Parse infinite but map any values > IB_LIFETIME_MAX to IB_LIFETIME_MAX. */ +extern void IXmlParserEndHoqTimeout_Int(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned int len, boolean valid); +extern void IXmlParserEndHoqTimeout_Str(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned int len, boolean valid); + +/* typically a bitfield, so need to call with value instead of ptr */ +extern void IXmlOutputSMStateValue(IXmlOutputState_t *state, const char* tag, uint8 value); +extern void IXmlOutputSMState(IXmlOutputState_t *state, const char* tag, void *data); +/* typically a bitfield, so need to call with value instead of ptr */ +extern void IXmlOutputOnOffValue(IXmlOutputState_t *state, const char* tag, uint8 value); +extern void IXmlOutputOnOff(IXmlOutputState_t *state, const char* tag, void *data); +extern void IXmlOutputPathRecord(IXmlOutputState_t *state, const char* tag, void *data); +extern void IXmlOutputOptionalPathRecord(IXmlOutputState_t *state, const char* tag, void *data); +extern void IXmlOutputTraceRecord(IXmlOutputState_t *state, const char* tag, void *data); +extern void IXmlOutputOptionalTraceRecord(IXmlOutputState_t *state, const char* tag, void *data); + +extern IXML_FIELD IocServiceFields[]; +extern void IocServiceXmlOutput(IXmlOutputState_t *state, const char *tag, void *data/*IOC_SERVICE*/); +extern void IocServiceXmlOutputOptional(IXmlOutputState_t *state, const char *tag, void *data/*IOC_SERVICE*/); +/* caller must supply IocServiceXmlParserStart and IocServiceXmlParserEnd */ + +extern IXML_FIELD SwitchInfoFields[]; +extern void SwitchInfoXmlOutput(IXmlOutputState_t *state, const char *tag, void *data /*STL_SWITCHINFO_RECORD*/); +extern void SwitchInfoXmlOutputOptional(IXmlOutputState_t *state, const char *tag, void *data /*STL_SWITCHINFO_RECORD*/); +/* caller must supply SwitchInfoXmlParserStart and SwitchInfoXmlParserEnd */ + +#ifdef __cplusplus +}; +#endif + +#endif /* _IBA_PUBLIC_IXML_IB_H_ */ diff --git a/Xml/opaxmlindent/Makefile b/Xml/opaxmlindent/Makefile new file mode 100644 index 0000000..359e200 --- /dev/null +++ b/Xml/opaxmlindent/Makefile @@ -0,0 +1,159 @@ +# Makefile for opaxmlindent + +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# Include Make Control Settings +include $(TL_DIR)/$(PROJ_FILE_DIR)/Makesettings.project + +#=============================================================================# +# Definitions: +#-----------------------------------------------------------------------------# + +# Name of SubProjects +DS_SUBPROJECTS = +# name of executable or downloadable image +EXECUTABLE = $(BUILDDIR)/opaxmlindent$(EXE_SUFFIX) +# list of sub directories to build +DIRS = +# C files (.c) +CFILES = \ + opaxmlindent.c \ + # Add more c files here +# C++ files (.cpp) +CCFILES = \ + # Add more cpp files here +# lex files (.lex) +LFILES = \ + # Add more lex files here +# archive library files (basename, $ARFILES will add MOD_LIB_DIR/prefix and suffix) +LIBFILES = +# Windows Resource Files (.rc) +RSCFILES = +# Windows IDL File (.idl) +IDLFILE = +# Windows Linker Module Definitions (.def) file for dll's +DEFFILE = +# targets to build during INCLUDES phase (add public includes here) +INCLUDE_TARGETS = \ + # Add more h hpp files here +# Non-compiled files +MISC_FILES = +# all source files +SOURCES = $(CFILES) $(CCFILES) $(LFILES) $(RSCFILES) $(IDLFILE) +# Source files to include in DSP File +DSP_SOURCES = $(INCLUDE_TARGETS) $(SOURCES) $(MISC_FILES) \ + $(RSCFILES) $(DEFFILE) $(MAKEFILE) +# all object files +OBJECTS = $(CFILES:.c=$(OBJ_SUFFIX)) $(CCFILES:.cpp=$(OBJ_SUFFIX)) \ + $(LFILES:.lex=$(OBJ_SUFFIX)) +RSCOBJECTS = $(RSCFILES:.rc=$(RES_SUFFIX)) +# targets to build during LIBS phase +LIB_TARGETS_IMPLIB = +LIB_TARGETS_ARLIB = +LIB_TARGETS_EXP = $(LIB_TARGETS_IMPLIB:$(ARLIB_SUFFIX)=$(EXP_SUFFIX)) +LIB_TARGETS_MISC = +# targets to build during CMDS phase +SHLIB_VERSION = +CMD_TARGETS_SHLIB = +CMD_TARGETS_EXE = $(EXECUTABLE) +CMD_TARGETS_MISC = +CMD_TARGETS_DRIVER = +CMD_TARGETS_KEXT = +# files to remove during clean phase +CLEAN_TARGETS_MISC = +CLEAN_TARGETS = $(OBJECTS) $(RSCOBJECTS) $(IDL_TARGETS) $(CLEAN_TARGETS_MISC) +# other files to remove during clobber phase +CLOBBER_TARGETS_MISC= +# sub-directory to install to within bin +BIN_SUBDIR = +# sub-directory to install to within include +INCLUDE_SUBDIR = + +# Additional Settings +#CLOCALDEBUG = User defined C debugging compilation flags [Empty] +#CCLOCALDEBUG = User defined C++ debugging compilation flags [Empty] +#CLOCAL = User defined C flags for compiling [Empty] +#CCLOCAL = User defined C++ flags for compiling [Empty] +#BSCLOCAL = User flags for Browse File Builder [Empty] +#DEPENDLOCAL = user defined makedepend flags [Empty] +#LINTLOCAL = User defined lint flags [Empty] +#LOCAL_INCLUDE_DIRS = User include directories to search for C/C++ headers [Empty] +#LDLOCAL = User defined C flags for linking [Empty] +#IMPLIBLOCAL = User flags for Object Lirary Manager [Empty] +#MIDLLOCAL = User flags for IDL compiler [Empty] +#RSCLOCAL = User flags for resource compiler [Empty] +#LOCALDEPLIBS = User libraries to include in dependencies [Empty] +#LOCALLIBS = User libraries to use when linking [Empty] +# (in addition to LOCALDEPLIBS) +#LOCAL_LIB_DIRS = User library directories for libpaths [Empty] + +LOCALDEPLIBS=$(IBACCESS_USER_LIBS) Xml +LOCALLIBS = expat +LOCAL_LIB_DIRS= $(IBACCESS_USER_LIB_DIRS) + +# Include Make Rules definitions and rules +include $(TL_DIR)/$(PROJ_FILE_DIR)/Makerules.project + +#=============================================================================# +# Overrides: +#-----------------------------------------------------------------------------# +#CCOPT = # C++ optimization flags, default lets build config decide +#COPT = # C optimization flags, default lets build config decide +#SUBSYSTEM = Subsystem to build for (none, console or windows) [none] +# (Windows Only) +#USEMFC = How Windows MFC should be used (none, static, shared, no_mfc) [none] +# (Windows Only) +#=============================================================================# + +#=============================================================================# +# Rules: +#-----------------------------------------------------------------------------# +# process Sub-directories +include $(TL_DIR)/Makerules/Maketargets.toplevel + +# build cmds and libs +include $(TL_DIR)/Makerules/Maketargets.build + +# install for includes, libs and cmds phases +include $(TL_DIR)/Makerules/Maketargets.install + +# install for stage phase +#include $(TL_DIR)/Makerules/Maketargets.stage +STAGE:: + $(VS)$(STAGE_INSTALL) $(STAGE_INSTALL_DIR_OPT) $(PROJ_STAGE_FASTFABRIC_DIR) $(EXECUTABLE) + +# Unit test execution +#include $(TL_DIR)/Makerules/Maketargets.runtest + +#=============================================================================# + +#=============================================================================# +# DO NOT DELETE THIS LINE -- make depend depends on it. +#=============================================================================# diff --git a/Xml/opaxmlindent/README b/Xml/opaxmlindent/README new file mode 100644 index 0000000..ffbd09a --- /dev/null +++ b/Xml/opaxmlindent/README @@ -0,0 +1 @@ +sample XML application to parse a file and reoutput it with nice indentation diff --git a/Xml/opaxmlindent/opaxmlindent.c b/Xml/opaxmlindent/opaxmlindent.c new file mode 100644 index 0000000..245994e --- /dev/null +++ b/Xml/opaxmlindent/opaxmlindent.c @@ -0,0 +1,203 @@ +/* BEGIN_ICS_COPYRIGHT7 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT7 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +#include +#include +#include +#include +#include +#include +#include +#define _GNU_SOURCE + +#include + +boolean g_trim = FALSE; +boolean g_keep_newline = FALSE; + +/* example of simple non-predefined parser */ +/* for an example of a predefined parser, see opareport/topology.c */ + +static void *FieldXmlParserStart(IXmlParserState_t *input_state, void *parent, const char **attr); +static void FieldXmlParserEnd(IXmlParserState_t *input_state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid); + +static IXML_FIELD UntrimmedFields[] = { + { tag:"*", format:'w', subfields:UntrimmedFields, start_func:FieldXmlParserStart, end_func:FieldXmlParserEnd }, // wildcard to traverse xml tree, keep all whitespace + { NULL } +}; + +#if 0 +static IXML_FIELD TrimmedFields[] = { + { tag:"*", format:'y', subfields:TrimmedFields, start_func:FieldXmlParserStart, end_func:FieldXmlParserEnd }, // wildcard to traverse xml tree, trim whitespace + { NULL } +}; +#endif + +static void FieldXmlFormatAttr(IXmlOutputState_t *output_state, void *data) +{ + const char **attr = (const char **)data; + int i; + + for (i = 0; attr[i]; i += 2) { + IXmlOutputPrint(output_state, " %s=\"", attr[i]); + IXmlOutputPrintStr(output_state, attr[i+1]); + IXmlOutputPrint(output_state, "\""); + } +} + +static void *FieldXmlParserStart(IXmlParserState_t *input_state, void *parent, const char **attr) +{ + IXmlOutputState_t *output_state = (IXmlOutputState_t*)IXmlParserGetContext(input_state); + + // if no attr, could use: + // IXmlOutputStartTag(output_state, IXmlParserGetCurrentTag(input_state)); + IXmlOutputStartAttrTag(output_state, IXmlParserGetCurrentTag(input_state), (void*)attr, FieldXmlFormatAttr); + // all tags processed via Fields which uses wildcard format + // and hence will keep lead/trail whitespace or permit a container + return NULL; // pointer returned here will be passed as object to ParserEnd function below +} + +static void FieldXmlParserEnd(IXmlParserState_t *input_state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + IXmlOutputState_t *output_state = (IXmlOutputState_t*)IXmlParserGetContext(input_state); + + if (! valid) { + // syntax error during tag (or its children tags), cleanup + //fprintf(stderr, "Cleanup %s", IXmlParserGetCurrentFullTag(input_state)); + } else { + // depending on tag and information from Start (object), process content + boolean hasNewline; + boolean white = IXmlIsWhitespace(content, &hasNewline); + if (len && g_trim) + len = IXmlTrimWhitespace(content, len); + if (white && ! g_keep_newline && hasNewline) { + // no real content, but has a newline, probably an empty list + // no output here, and EndTag will be on a fresh line + } else if (len) { + // tag had content, output it with appropriate XML escapes for + // special characters + IXmlOutputPrintStr(output_state, content); + } else if (! IXmlParserGetChildTagCount(input_state)) { + // if there were no child tags and no content, + // we output this as an empty tag + // this way tags with no content stay that way + // if g_trim && ! g_keep_newline, empty lists get listed on one line + IXmlOutputPrintStr(output_state, ""); + } + // close out the StartTag + IXmlOutputEndTag(output_state, IXmlParserGetCurrentTag(input_state)); + } +} + +FSTATUS Xml2ParseInputFile(const char *input_file, void *context, IXML_FIELD *fields) +{ + if (strcmp(input_file, "-") == 0) { + fprintf(stderr, "Parsing stdin...\n"); + if (FSUCCESS != IXmlParseFile(stdin, "stdin", IXML_PARSER_FLAG_NONE, fields, NULL, context, NULL, NULL, NULL, NULL)) { + return FERROR; + } + } else { + fprintf(stderr, "Parsing %s...\n", input_file); + if (FSUCCESS != IXmlParseInputFile(input_file, IXML_PARSER_FLAG_NONE, fields, NULL, context, NULL, NULL, NULL, NULL)) { + return FERROR; + } + } + return FSUCCESS; +} + +void Usage(int exitcode) +{ + fprintf(stderr, "Usage: opaxmlindent [-t|-k] [-i indent] [input_file]\n"); + fprintf(stderr, " or\n"); + fprintf(stderr, " opaxmlindent --help\n"); + fprintf(stderr, " --help - produce full help text\n"); + fprintf(stderr, " -t - trim leading and trailing whitespace in tag contents\n"); + fprintf(stderr, " -k - in tags with purely whitespace which contain newlines,\n"); + fprintf(stderr, " keep newlines as is (default is to format as an empty list)\n"); + fprintf(stderr, " -i indent - set indentation to use per level (default 4)\n"); + fprintf(stderr, " input_file - xml file to read. default is stdin\n"); + exit(exitcode); +} + +int main(int argc, char **argv) +{ + IXmlOutputState_t output_state; + int exit_code = 0; + uint32 indent = 4; + const struct option longopts[] = {{"help", 0, 0, '$'}, + {0, 0, 0, 0}}; + char *filename = "-"; // default to stdin + IXML_FIELD *fields = UntrimmedFields; + int c; + + while (-1 != (c = getopt_long(argc, argv, "tki:", longopts, NULL))) { + switch (c) { + case '$': + Usage(0); + case 't': + // TrimmedFields treats empty list as tag with no content + //fields = TrimmedFields; + g_trim = TRUE; + break; + case 'i': + if (FSUCCESS != StringToUint32(&indent, optarg, NULL, 0, TRUE)) { + fprintf(stderr, "opaxmlindent: Invalid indent: %s\n", optarg); + Usage(2); + } + break; + case 'k': + g_keep_newline = TRUE; + break; + default: + Usage(2); + } + } + if (g_trim && g_keep_newline) { + fprintf(stderr, "opaxmlindent: Can't use -k and -t together\n"); + Usage(2); + } + if (argc > optind){ + filename = argv[optind++]; + if (!filename) { + fprintf(stderr, "opaxmlindent: Error: null input filename\n"); + exit(1); + } + } + if (argc > optind) { + Usage(2); + } + if (FSUCCESS != IXmlOutputInit(&output_state, stdout, indent, IXML_OUTPUT_FLAG_NONE, NULL)) + exit(1); + if (FSUCCESS != Xml2ParseInputFile(filename, &output_state, fields)) + exit_code = 1; + IXmlOutputDestroy(&output_state); + exit(exit_code); +} diff --git a/Xml/xml_sample/Makefile b/Xml/xml_sample/Makefile new file mode 100644 index 0000000..d6c6b87 --- /dev/null +++ b/Xml/xml_sample/Makefile @@ -0,0 +1,158 @@ +# Makefile for xml_sample + +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# Include Make Control Settings +include $(TL_DIR)/$(PROJ_FILE_DIR)/Makesettings.project + +#=============================================================================# +# Definitions: +#-----------------------------------------------------------------------------# + +# Name of SubProjects +DS_SUBPROJECTS = +# name of executable or downloadable image +EXECUTABLE = $(BUILDDIR)/xml_sample$(EXE_SUFFIX) +# list of sub directories to build +DIRS = +# C files (.c) +CFILES = \ + xml_sample.c \ + # Add more c files here +# C++ files (.cpp) +CCFILES = \ + # Add more cpp files here +# lex files (.lex) +LFILES = \ + # Add more lex files here +# archive library files (basename, $ARFILES will add MOD_LIB_DIR/prefix and suffix) +LIBFILES = +# Windows Resource Files (.rc) +RSCFILES = +# Windows IDL File (.idl) +IDLFILE = +# Windows Linker Module Definitions (.def) file for dll's +DEFFILE = +# targets to build during INCLUDES phase (add public includes here) +INCLUDE_TARGETS = \ + # Add more h hpp files here +# Non-compiled files +MISC_FILES = +# all source files +SOURCES = $(CFILES) $(CCFILES) $(LFILES) $(RSCFILES) $(IDLFILE) +# Source files to include in DSP File +DSP_SOURCES = $(INCLUDE_TARGETS) $(SOURCES) $(MISC_FILES) \ + $(RSCFILES) $(DEFFILE) $(MAKEFILE) +# all object files +OBJECTS = $(CFILES:.c=$(OBJ_SUFFIX)) $(CCFILES:.cpp=$(OBJ_SUFFIX)) \ + $(LFILES:.lex=$(OBJ_SUFFIX)) +RSCOBJECTS = $(RSCFILES:.rc=$(RES_SUFFIX)) +# targets to build during LIBS phase +LIB_TARGETS_IMPLIB = +LIB_TARGETS_ARLIB = +LIB_TARGETS_EXP = $(LIB_TARGETS_IMPLIB:$(ARLIB_SUFFIX)=$(EXP_SUFFIX)) +LIB_TARGETS_MISC = +# targets to build during CMDS phase +SHLIB_VERSION = +CMD_TARGETS_SHLIB = +CMD_TARGETS_EXE = $(EXECUTABLE) +CMD_TARGETS_MISC = +CMD_TARGETS_DRIVER = +CMD_TARGETS_KEXT = +# files to remove during clean phase +CLEAN_TARGETS_MISC = +CLEAN_TARGETS = $(OBJECTS) $(RSCOBJECTS) $(IDL_TARGETS) $(CLEAN_TARGETS_MISC) +# other files to remove during clobber phase +CLOBBER_TARGETS_MISC= +# sub-directory to install to within bin +BIN_SUBDIR = +# sub-directory to install to within include +INCLUDE_SUBDIR = + +# Additional Settings +#CLOCALDEBUG = User defined C debugging compilation flags [Empty] +#CCLOCALDEBUG = User defined C++ debugging compilation flags [Empty] +#CLOCAL = User defined C flags for compiling [Empty] +#CCLOCAL = User defined C++ flags for compiling [Empty] +#BSCLOCAL = User flags for Browse File Builder [Empty] +#DEPENDLOCAL = user defined makedepend flags [Empty] +#LINTLOCAL = User defined lint flags [Empty] +#LOCAL_INCLUDE_DIRS = User include directories to search for C/C++ headers [Empty] +#LDLOCAL = User defined C flags for linking [Empty] +#IMPLIBLOCAL = User flags for Object Lirary Manager [Empty] +#MIDLLOCAL = User flags for IDL compiler [Empty] +#RSCLOCAL = User flags for resource compiler [Empty] +#LOCALDEPLIBS = User libraries to include in dependencies [Empty] +#LOCALLIBS = User libraries to use when linking [Empty] +# (in addition to LOCALDEPLIBS) +#LOCAL_LIB_DIRS = User library directories for libpaths [Empty] + +LOCALDEPLIBS=$(IBACCESS_USER_LIBS) Xml +LOCALLIBS = expat +LOCAL_LIB_DIRS= $(IBACCESS_USER_LIB_DIRS) + +# Include Make Rules definitions and rules +include $(TL_DIR)/$(PROJ_FILE_DIR)/Makerules.project + +#=============================================================================# +# Overrides: +#-----------------------------------------------------------------------------# +#CCOPT = # C++ optimization flags, default lets build config decide +#COPT = # C optimization flags, default lets build config decide +#SUBSYSTEM = Subsystem to build for (none, console or windows) [none] +# (Windows Only) +#USEMFC = How Windows MFC should be used (none, static, shared, no_mfc) [none] +# (Windows Only) +#=============================================================================# + +#=============================================================================# +# Rules: +#-----------------------------------------------------------------------------# +# process Sub-directories +include $(TL_DIR)/Makerules/Maketargets.toplevel + +# build cmds and libs +include $(TL_DIR)/Makerules/Maketargets.build + +# install for includes, libs and cmds phases +include $(TL_DIR)/Makerules/Maketargets.install + +# install for stage phase +#include $(TL_DIR)/Makerules/Maketargets.stage +STAGE:: + +# Unit test execution +#include $(TL_DIR)/Makerules/Maketargets.runtest + +#=============================================================================# + +#=============================================================================# +# DO NOT DELETE THIS LINE -- make depend depends on it. +#=============================================================================# diff --git a/Xml/xml_sample/README b/Xml/xml_sample/README new file mode 100644 index 0000000..d973f5f --- /dev/null +++ b/Xml/xml_sample/README @@ -0,0 +1 @@ +sample XML application to parse an XML file and dump what is read diff --git a/Xml/xml_sample/xml_sample.c b/Xml/xml_sample/xml_sample.c new file mode 100644 index 0000000..4cfb187 --- /dev/null +++ b/Xml/xml_sample/xml_sample.c @@ -0,0 +1,141 @@ +/* BEGIN_ICS_COPYRIGHT7 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT7 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +#include +#include +#include +#include +#include +#include +#define _GNU_SOURCE + +#include + +/* example of simple non-predefined parser */ +/* for an example of a predefined parser, see opareport/topology.c */ + +static void *FieldXmlParserStart(IXmlParserState_t *state, void *parent, const char **attr); +static void FieldXmlParserEnd(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid); + +static IXML_FIELD Fields[] = { + { tag:"*", format:'w', subfields:Fields, start_func:FieldXmlParserStart, end_func:FieldXmlParserEnd }, // wildcard to traverse xml tree, keep all whitespace + { NULL } +}; + +static IXML_FIELD StrField = + { tag:"*", format:'s', start_func:FieldXmlParserStart, end_func:FieldXmlParserEnd }; // keep all whitespace + +static IXML_FIELD OtherField = + { tag:"*", format:'k', start_func:FieldXmlParserStart, end_func:FieldXmlParserEnd }; // trim leading/trailing whitespace + + +static void *FieldXmlParserStart(IXmlParserState_t *state, void *parent, const char **attr) +{ + int i; + const char *tag=IXmlParserGetCurrentTag(state); + const char *parent_tag=IXmlParserGetParentTag(state); // can be NULL at top level tag + const char *full_tag = IXmlParserGetCurrentFullTag(state); + + if (!tag) { + fprintf(stderr, "tag pointer is null.\n"); + return NULL; + } + + // process attributes as needed + printf("Start %s in %s", full_tag?full_tag:"NONE", parent_tag?parent_tag:"NONE"); + for (i = 0; attr[i]; i += 2) { + printf(" %s='%s'", attr[i], attr[i+1]); + } + printf("\n"); + if (strcmp("NodeGUID", tag) == 0) { + // example of changing parsing format + // here is a tag we want lead/trail whitespace trimmed for + IXmlParserSetField(state, &OtherField); + } else if (strcmp("NodeDesc", tag) == 0) { + // example of changing parsing format + // here is a tag we want to keep lead/trail whitespace + IXmlParserSetField(state, &StrField); + } else { + // all other tags processed via Fields which uses 'w' format + // and hence will keep lead/trail whitespace or permit a container + } + return NULL; // pointer returned here will be passed as object to ParserEnd function below +} + +static void FieldXmlParserEnd(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + const char *full_tag = IXmlParserGetCurrentFullTag(state); + if (! valid) { + // syntax error during tag (or its children tags), cleanup + printf("Cleanup %s", full_tag?full_tag:""); + } else { + // depending on tag and information from Start (object), process content + printf("End %s: '%s'\n", full_tag?full_tag:"", content?content:""); + } +} + +FSTATUS Xml2ParseInputFile(const char *input_file) +{ + if (strcmp(input_file, "-") == 0) { + printf("Parsing stdin...\n"); + if (FSUCCESS != IXmlParseFile(stdin, "stdin", IXML_PARSER_FLAG_NONE, Fields, NULL, NULL, NULL, NULL, NULL, NULL)) { + return FERROR; + } + } else { + printf("Parsing %s...\n", input_file); + if (FSUCCESS != IXmlParseInputFile(input_file, IXML_PARSER_FLAG_NONE, Fields, NULL, NULL, NULL, NULL, NULL, NULL)) { + return FERROR; + } + } + return FSUCCESS; +} + +void Usage(void) +{ + fprintf(stderr, "Usage: xml_sample input_file\n"); + exit(2); +} + +int main(int argc, char **argv) +{ + char *filename; + if (argc != 2) + Usage(); + filename = argv[1]; + if (!filename) { + fprintf(stderr, "Error: null input filename\n"); + exit(2); + } + if (FSUCCESS == Xml2ParseInputFile(filename)) + exit(0); + else + exit(1); +} diff --git a/Xml/xml_sample2/Makefile b/Xml/xml_sample2/Makefile new file mode 100644 index 0000000..dacc3a9 --- /dev/null +++ b/Xml/xml_sample2/Makefile @@ -0,0 +1,158 @@ +# Makefile for xml_sample2 + +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +# Include Make Control Settings +include $(TL_DIR)/$(PROJ_FILE_DIR)/Makesettings.project + +#=============================================================================# +# Definitions: +#-----------------------------------------------------------------------------# + +# Name of SubProjects +DS_SUBPROJECTS = +# name of executable or downloadable image +EXECUTABLE = $(BUILDDIR)/xml_sample2$(EXE_SUFFIX) +# list of sub directories to build +DIRS = +# C files (.c) +CFILES = \ + xml_sample2.c \ + # Add more c files here +# C++ files (.cpp) +CCFILES = \ + # Add more cpp files here +# lex files (.lex) +LFILES = \ + # Add more lex files here +# archive library files (basename, $ARFILES will add MOD_LIB_DIR/prefix and suffix) +LIBFILES = +# Windows Resource Files (.rc) +RSCFILES = +# Windows IDL File (.idl) +IDLFILE = +# Windows Linker Module Definitions (.def) file for dll's +DEFFILE = +# targets to build during INCLUDES phase (add public includes here) +INCLUDE_TARGETS = \ + # Add more h hpp files here +# Non-compiled files +MISC_FILES = +# all source files +SOURCES = $(CFILES) $(CCFILES) $(LFILES) $(RSCFILES) $(IDLFILE) +# Source files to include in DSP File +DSP_SOURCES = $(INCLUDE_TARGETS) $(SOURCES) $(MISC_FILES) \ + $(RSCFILES) $(DEFFILE) $(MAKEFILE) +# all object files +OBJECTS = $(CFILES:.c=$(OBJ_SUFFIX)) $(CCFILES:.cpp=$(OBJ_SUFFIX)) \ + $(LFILES:.lex=$(OBJ_SUFFIX)) +RSCOBJECTS = $(RSCFILES:.rc=$(RES_SUFFIX)) +# targets to build during LIBS phase +LIB_TARGETS_IMPLIB = +LIB_TARGETS_ARLIB = +LIB_TARGETS_EXP = $(LIB_TARGETS_IMPLIB:$(ARLIB_SUFFIX)=$(EXP_SUFFIX)) +LIB_TARGETS_MISC = +# targets to build during CMDS phase +SHLIB_VERSION = +CMD_TARGETS_SHLIB = +CMD_TARGETS_EXE = $(EXECUTABLE) +CMD_TARGETS_MISC = +CMD_TARGETS_DRIVER = +CMD_TARGETS_KEXT = +# files to remove during clean phase +CLEAN_TARGETS_MISC = +CLEAN_TARGETS = $(OBJECTS) $(RSCOBJECTS) $(IDL_TARGETS) $(CLEAN_TARGETS_MISC) +# other files to remove during clobber phase +CLOBBER_TARGETS_MISC= +# sub-directory to install to within bin +BIN_SUBDIR = +# sub-directory to install to within include +INCLUDE_SUBDIR = + +# Additional Settings +#CLOCALDEBUG = User defined C debugging compilation flags [Empty] +#CCLOCALDEBUG = User defined C++ debugging compilation flags [Empty] +#CLOCAL = User defined C flags for compiling [Empty] +#CCLOCAL = User defined C++ flags for compiling [Empty] +#BSCLOCAL = User flags for Browse File Builder [Empty] +#DEPENDLOCAL = user defined makedepend flags [Empty] +#LINTLOCAL = User defined lint flags [Empty] +#LOCAL_INCLUDE_DIRS = User include directories to search for C/C++ headers [Empty] +#LDLOCAL = User defined C flags for linking [Empty] +#IMPLIBLOCAL = User flags for Object Lirary Manager [Empty] +#MIDLLOCAL = User flags for IDL compiler [Empty] +#RSCLOCAL = User flags for resource compiler [Empty] +#LOCALDEPLIBS = User libraries to include in dependencies [Empty] +#LOCALLIBS = User libraries to use when linking [Empty] +# (in addition to LOCALDEPLIBS) +#LOCAL_LIB_DIRS = User library directories for libpaths [Empty] + +LOCALDEPLIBS=$(IBACCESS_USER_LIBS) Xml +LOCALLIBS = expat +LOCAL_LIB_DIRS= $(IBACCESS_USER_LIB_DIRS) + +# Include Make Rules definitions and rules +include $(TL_DIR)/$(PROJ_FILE_DIR)/Makerules.project + +#=============================================================================# +# Overrides: +#-----------------------------------------------------------------------------# +#CCOPT = # C++ optimization flags, default lets build config decide +#COPT = # C optimization flags, default lets build config decide +#SUBSYSTEM = Subsystem to build for (none, console or windows) [none] +# (Windows Only) +#USEMFC = How Windows MFC should be used (none, static, shared, no_mfc) [none] +# (Windows Only) +#=============================================================================# + +#=============================================================================# +# Rules: +#-----------------------------------------------------------------------------# +# process Sub-directories +include $(TL_DIR)/Makerules/Maketargets.toplevel + +# build cmds and libs +include $(TL_DIR)/Makerules/Maketargets.build + +# install for includes, libs and cmds phases +include $(TL_DIR)/Makerules/Maketargets.install + +# install for stage phase +#include $(TL_DIR)/Makerules/Maketargets.stage +STAGE:: + +# Unit test execution +#include $(TL_DIR)/Makerules/Maketargets.runtest + +#=============================================================================# + +#=============================================================================# +# DO NOT DELETE THIS LINE -- make depend depends on it. +#=============================================================================# diff --git a/Xml/xml_sample2/README b/Xml/xml_sample2/README new file mode 100644 index 0000000..bc6f516 --- /dev/null +++ b/Xml/xml_sample2/README @@ -0,0 +1 @@ +sample XML application to parse an XML file to/from C structures diff --git a/Xml/xml_sample2/sample.xml b/Xml/xml_sample2/sample.xml new file mode 100644 index 0000000..a9a96a6 --- /dev/null +++ b/Xml/xml_sample2/sample.xml @@ -0,0 +1,18 @@ + + + + 1 + 0xf567 + 0xf568 + 67 + + 0 + 0 + 0x12345 + + + 1 + 0 + 0x12345 + + diff --git a/Xml/xml_sample2/xml_sample2.c b/Xml/xml_sample2/xml_sample2.c new file mode 100644 index 0000000..6ecbbfb --- /dev/null +++ b/Xml/xml_sample2/xml_sample2.c @@ -0,0 +1,323 @@ +/* BEGIN_ICS_COPYRIGHT7 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT7 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +#include +#include +#include +#include +#include +#include +#define _GNU_SOURCE + +#include + +#define MYTAG MAKE_MEM_TAG('s','a', 'm', 'p') + +/* This sample uses the parser to parse a specific file format + * sample.xml is an example of the file format + */ + +/* here is our internal structure for the sample config file + * notice how it maps very well to the xml format. The closer it maps, + * the easier it is to implement the parser and output + */ +typedef struct MySmInstance_s { + LIST_ITEM SmInstancesEntry; + uint8 Instance; + uint8 Port; + uint64 MKey; +} MySmInstance_t; + +typedef struct MyConfig_s { + unsigned Mode; + unsigned LogMask; + QUICK_LIST SmInstances; +} MyConfig_t; + +// in this example this is a simple global. Could just as easily be +// dynamically allocated +MyConfig_t g_config; + +void InitConfig(void) +{ + QListInit(&g_config.SmInstances); +} + +// fields within "SM" tag +// In this example, MKey is optional and others are manditory +static IXML_FIELD SMFields[] = { + { tag:"Instance", format:'U', IXML_FIELD_INFO(MySmInstance_t, Instance) }, + { tag:"Port", format:'U', IXML_FIELD_INFO(MySmInstance_t, Port) }, + { tag:"MKey", format:'x', IXML_FIELD_INFO(MySmInstance_t, MKey) }, + { NULL } +}; + +// Output the SmInstance pointed to by data +// caller will specify the tag (typically "SM") +static void SmXmlOutput(IXmlOutputState_t *state, const char *tag, void *data) +{ + IXmlOutputStruct(state, tag, (MySmInstance_t*)data, NULL, SMFields); +} + +void SmFree(MyConfig_t *configp, MySmInstance_t *smp) +{ + if (ListItemIsInAList(&smp->SmInstancesEntry)) + QListRemoveItem(&configp->SmInstances, &smp->SmInstancesEntry); + MemoryDeallocate(smp); +} + +// This function will be called each time we encounter an SM start tag +// we can allocate an Sm Instance and process/validate any attributes +// in the start tag +static void *SmXmlParserStart(IXmlParserState_t *state, void *parent, const char **attr) +{ + int i; + //boolean gotattr = FALSE; + + // Dynamically allocate the SM instance + MySmInstance_t *smp = (MySmInstance_t*)MemoryAllocate2AndClear(sizeof(MySmInstance_t), IBA_MEM_FLAG_PREMPTABLE, MYTAG); + + if (! smp) { + IXmlParserPrintError(state, "Unable to allocate memory"); + return NULL; + } + + // if desired we could process attributes of SM here. + // even indexes are attribute names and odd indexes are their values + // attr[0] = name, attr[1] = value, etc + // process unixtime attribute and update g_time + // In this example, perhaps Instance could be an attribute instead of a tag + for (i = 0; attr[i]; i += 2) { + if (strcmp(attr[i], "Instance") == 0) { + // process string in attr[i+1] + //if (invalid) + // IXmlParserPrintError(state, "Invalid Instance attribute"); + //else + // gotattr=TRUE; + } + // silently ignore unrecognized attributes + } + // as needed check for manditory attributes being found + //if (! gotattr) { + // IXmlParserPrintError(state, "Missing Instance attribute"); + //} + + // basic initialization of the structure + ListItemInitState(&smp->SmInstancesEntry); + QListSetObj(&smp->SmInstancesEntry, smp); + + // fill in any default values for optional fields here + // MKey is optional, we could set a non-zero default here if desired + + return smp; // will be passed to SmXmlParserEnd as object +} + +// this function is called when we encounter a SM end tag +// it will validate the object if self consistent and put it into +// the parent's list. Note that we do not add it to the list +// until the end tag, this way incomplete or inaccurate SmInstances +// are never placed in the parent's list +static void SmXmlParserEnd(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + MySmInstance_t *smp = (MySmInstance_t*)object; + MyConfig_t *configp = (MyConfig_t*)parent; + + if (! valid) // missing manditory fields or parse error in child + goto fail; + + // validate smp, for example make sure smp->Instance is unique + // Note Xml parser has ensured all manditory fields were supplied + QListInsertTail(&configp->SmInstances, &smp->SmInstancesEntry); + + return; + +fail: + SmFree(configp, smp); +} + +// for output, this outputs all the SMs in the MyConfig +static void ConfigXmlOutputSms(IXmlOutputState_t *state, const char *tag, void *data) +{ + MyConfig_t *configp = (MyConfig_t*)data; + LIST_ITEM *p; + + // free all link data + for (p=QListHead(&configp->SmInstances); p != NULL; p = QListNext(&configp->SmInstances, p)) { + SmXmlOutput(state, "SM", QListObj(p)); + } +} + +// The set of fields permitted within the Config tag +// in this example Mode is optional but LogMask is manditory +// SM is an example of a more complex tag which can occur multiple +// times and will become part of a list of SMs +static IXML_FIELD ConfigFields[] = { + { tag:"Mode", format:'u', IXML_FIELD_INFO(MyConfig_t, Mode) }, + { tag:"LogMask", format:'X', IXML_FIELD_INFO(MyConfig_t, LogMask) }, + { tag:"SM", format:'k', subfields:SMFields, format_func:ConfigXmlOutputSms, start_func:SmXmlParserStart, end_func:SmXmlParserEnd }, // zero or more structures + { NULL } +}; + +// output the Config, will be typically called with tag=="Config" +static void ConfigXmlOutput(IXmlOutputState_t *state, const char *tag, void *data) +{ + IXmlOutputStruct(state, tag, (MyConfig_t*)data, NULL, ConfigFields); +} + +void SMFreeAll(MyConfig_t *configp) +{ + LIST_ITEM *p; + + for (p=QListHead(&configp->SmInstances); p != NULL; p = QListHead(&configp->SmInstances)) { + SmFree(configp, (MySmInstance_t*)QListObj(p)); + } +} + +// Config start tag +static void *ConfigXmlParserStart(IXmlParserState_t *state, void *parent, const char **attr) +{ + int i; + //boolean gotattr = FALSE; + + // if desired we could process attributes of Config here. + // even indexes are attribute names and odd indexes are their values + // attr[0] = name, attr[1] = value, etc + // process unixtime attribute and update g_time + for (i = 0; attr[i]; i += 2) { + if (strcmp(attr[i], "myattrname") == 0) { + // process string in attr[i+1] + //if (invalid) + // IXmlParserPrintError(state, "Invalid myattrname attribute"); + //else + // gotattr=TRUE; + } + // silently ignore unrecognized attributes + } + // as needed check for manditory attributes being found + //if (! gotattr) { + // IXmlParserPrintError(state, "Missing myattrname attribute"); + //} + return &g_config; // will be parent for our child tags +} + +// Config end tag +static void ConfigXmlParserEnd(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) +{ + MyConfig_t *configp = (MyConfig_t*)object; + + if (! valid) { + SMFreeAll(configp); // make sure we cleanup completely + } else { + // as needed process or validate self consistency of config + } +} + +// top level tag +static IXML_FIELD TopLevelFields[] = { + { tag:"Config", format:'K', subfields:ConfigFields, start_func:ConfigXmlParserStart, end_func:ConfigXmlParserEnd }, + { NULL } +}; + +// main output function, this will iterate down the heirarchy 1 level at a time +// If desired we could pass a context into the parser which would +// be available to all the parse functions above via IXmlOutputGetContext +// for example the context might set the scope or style of output +FSTATUS Xml2PrintConfig(FILE *file) +{ + IXmlOutputState_t state; + + if (FSUCCESS != IXmlOutputInit(&state, file, 4, IXML_OUTPUT_FLAG_NONE, NULL )) + goto fail; + + ConfigXmlOutput(&state, "Config", &g_config); + + IXmlOutputDestroy(&state); + + return FSUCCESS; + +fail: + return FERROR; +} + +// main parser. If desired we could pass a context into the parser which would +// be available to all the parse functions above via IXmlParserGetContext +// for example we may have global settings which control how tags are processed +// or we could have dynamically allocated MyConfig_t and passed the pointer +// in as the context +FSTATUS Xml2ParseConfig(const char *input_file) +{ + return IXmlParseInputFile(input_file, IXML_PARSER_FLAG_NONE, TopLevelFields, NULL, NULL, NULL, NULL, NULL, NULL); +} + +void Usage(void) +{ + fprintf(stderr, "Usage: xml_sample2 input_file\n"); + fprintf(stderr, " input_file - xml file to read.\n"); + exit(2); +} + +int main(int argc, char **argv) +{ + int exit_code = 0; + char *input_file; + int c; + + while (-1 != (c = getopt(argc, argv, ""))) { + switch (c) { + } + } + if (argc == optind) + Usage(); // require input_file argument + input_file = argv[optind++]; + if (!input_file) { + fprintf(stderr, "Error: null input filename\n"); + exit_code = 1; + goto fail; + } + if (argc > optind) + Usage(); + + InitConfig(); // initialize g_config + + // parse input_file + fprintf(stderr, "Parsing %s...\n", input_file); + if (FSUCCESS != Xml2ParseConfig(input_file)) { + exit_code = 1; + goto fail; + } + + // spit it back out to prove we parsed it + if (FSUCCESS != Xml2PrintConfig(stdout)) + exit_code = 1; + +fail: + exit(exit_code); +} diff --git a/get_id_and_versionid.sh b/get_id_and_versionid.sh new file mode 100755 index 0000000..81d2c51 --- /dev/null +++ b/get_id_and_versionid.sh @@ -0,0 +1,87 @@ +#!/bin/bash + +if [ -f /etc/os-release ] +then + id=$(grep ^ID= /etc/os-release | cut -f2 -d= | cut -f2 -d\") + versionid=$(grep ^VERSION_ID= /etc/os-release | cut -f2 -d\") +else + if [ `uname -s` == "Darwin" ] + then + # Apple Mac + rval=apple + else + filelist=`'ls' /etc/*-release | egrep -v lsb | egrep -v os` + rval="" + for file in $filelist + do + if [ -f $file ] + then + rval=`basename $file -release` + if [ $rval = 'SuSE' ] + then + if [ -f /etc/UnitedLinux-release ] + then + rval=UnitedLinux + fi + elif [ $rval = 'centos' ] + then + rval=redhat + elif [ $rval != 'os' ] + then + break + fi + fi + done + fi + case $rval in + redhat) + id=rhel + ;; + SuSE) + id=sles + ;; + *) + id="" + ;; + esac + + case $id in + rhel) + if grep -qi advanced /etc/redhat-release + then + rval=`cat /etc/redhat-release | cut -d' ' -f7` + elif grep -qi enterprise /etc/redhat-release + then + # /etc/redhat-release = "Red Hat Enterprise Linux Server release $a.$b ($c)" + rval=`cat /etc/redhat-release | cut -d' ' -f7 | cut -d. -f1` + major=`cat /etc/redhat-release | cut -d' ' -f7 | cut -d. -f1` + minor=`cat /etc/redhat-release | cut -d' ' -f7 | cut -d. -f2` + if [ \( $major -ge 7 -a $minor -ne 0 \) -o \( $major -eq 6 -a $minor -ge 7 \) ] + then + rval=$rval.$minor + fi + elif grep -qi centos /etc/redhat-release + then + # CentOS + rval=`cat /etc/redhat-release | sed -r 's/^.+([[:digit:]])\.([[:digit:]]).+$/\1.\2/'` + elif grep -qi scientific /etc/redhat-release + then + # Scientific Linux. + rval=`cat /etc/redhat-release | sed -r 's/^.+([[:digit:]])\.([[:digit:]]).+$/\1.\2/'` + else + rval=`cat /etc/redhat-release | cut -d' ' -f5` + fi + ;; + sles) + v1=$(grep VERSION /etc/SuSE-release | cut -d' ' -f3) + v2=$(grep PATCHLEVEL /etc/SuSE-release | cut -d' ' -f3) + rval=${v1}.$v2 + ;; + *) + rval="" + esac + versionid=$rval +fi + +echo $id $versionid +exit 0 diff --git a/opa-ff.spec.in b/opa-ff.spec.in new file mode 100644 index 0000000..381b9e0 --- /dev/null +++ b/opa-ff.spec.in @@ -0,0 +1,166 @@ +Name: opa +Version: 10.10.1.0 +Release: 35%{?dist} +Summary: Intel Omni-Path basic tools and libraries for fabric managment. + +Group: System Environment/Libraries +License: GPLv2/BSD +Url: https://github.com/intel/opa-ff +# tarball created by: +# git clone https://github.com/intel/opa-ff.git +# cd opa-ff +# tar czf opa.tgz --exclude-vcs . +Source: opa.tgz +ExclusiveArch: x86_64 +# The Intel(R) OPA product line is only available on x86_64 platforms at this time. + +__RPM_DEBUG_PKG + +%description +This package contains the tools necessary to manage an Intel(R) Omni-Path Architecture fabric. +IFSComponent: Tools_FF 10.10.1.0.35%{?dist} + +%package basic-tools +Summary: Managment level tools and scripts. +Group: System Environment/Libraries + +Requires: rdma bc + +Requires: __RPM_REQ_BASIC +BuildRequires: __RPM_BLDREQ + +%if 0%{?rhel} +Epoch: 1 +%endif + +%description basic-tools +Contains basic tools for fabric managment necessary on all compute nodes. +IFSComponent: Tools_FF 10.10.1.0.35%{?dist} + +%package fastfabric +Summary: Management level tools and scripts. +Group: System Environment/Libraries +Requires: opa-basic-tools cronie + +%if 0%{?rhel} +Epoch: 1 +%endif + +%description fastfabric +Contains tools for managing fabric on a managment node. +IFSComponent: Tools_FF 10.10.1.0.35%{?dist} + +%package address-resolution +Summary: Contains Address Resolution manager +Group: System Environment/Libraries +Requires: __RPM_REQ_ADDR_RES + +%if 0%{?rhel} +Epoch: 1 +%endif + +%description address-resolution +This package contains the ibacm distributed SA provider (dsap) for name and address resolution on OPA platform. +It also contains the library and tools to access the shared memory database exported by dsap. +IFSComponent: Tools_FF 10.10.1.0.35%{?dist} + +%package libopamgt +Summary: Omni-Path management API library +Group: System Environment/Libraries +Requires: __RPM_REQ_OPAMGT + +%description libopamgt +This package contains the library necessary to build applications that interface with an Omni-Path FM. +IFSComponent: Tools_FF 10.10.1.0.35%{?dist} + + +%package libopamgt-devel +Summary: Omni-Path library development headers +Group: System Environment/Libraries +Requires: __RPM_REQ_OPAMGT_DEV + +%description libopamgt-devel +This package contains the necessary headers for opamgt development. +IFSComponent: Tools_FF 10.10.1.0.35%{?dist} + +%prep +#rm -rf %{_builddir}/* +#tar xzf %_sourcedir/%name.tgz +%setup -q -c + +%build +cd OpenIb_Host + __RPM_FS ./ff_build.sh %{_builddir} $BUILD_ARGS + + +%install +BUILDDIR=%{_builddir} DESTDIR=%{buildroot} LIBDIR=/usr/lib DSAP_LIBDIR=%{_libdir} ./OpenIb_Host/ff_install.sh + +%post address-resolution -p /sbin/ldconfig +%postun address-resolution -p /sbin/ldconfig + +%preun fastfabric +cd /usr/src/opa/mpi_apps >/dev/null 2>&1 +make -k clean >/dev/null 2>&1 || : # suppress all errors and return codes from the make clean. + +%post libopamgt -p /sbin/ldconfig +%postun libopamgt -p /sbin/ldconfig + +%preun libopamgt-devel +cd /usr/src/opamgt >/dev/null 2>&1 +make -k clean >/dev/null 2>&1 || : + +%files basic-tools +__RPM_BASIC_FILES +%config(noreplace) %{_sysconfdir}/opa/opamgt_tls.xml + +%files fastfabric +__RPM_FF_FILES +%{_sysconfdir}/opa/opamon.si.conf +# Replace opamon.si.conf, as it's a template config file. +%config(noreplace) %{_sysconfdir}/opa/opafastfabric.conf +%config(noreplace) %{_sysconfdir}/opa/opamon.conf +%config(noreplace) %{_sysconfdir}/opa/allhosts +%config(noreplace) %{_sysconfdir}/opa/chassis +%config(noreplace) %{_sysconfdir}/opa/esm_chassis +%config(noreplace) %{_sysconfdir}/opa/hosts +%config(noreplace) %{_sysconfdir}/opa/ports +%config(noreplace) %{_sysconfdir}/opa/switches +%config(noreplace) %{_sysconfdir}/cron.d/opa-cablehealth +%config(noreplace) /usr/lib/opa/tools/osid_wrapper + + +%files address-resolution +%{_bindir}/opa_osd_dump +%{_bindir}/opa_osd_exercise +%{_bindir}/opa_osd_perf +%{_bindir}/opa_osd_query +%{_bindir}/opa_osd_query_many +%{_bindir}/opa_osd_load +%{_libdir}/ibacm +%{_libdir}/libopasadb.so* +%{_includedir}/infiniband +%{_mandir}/man1/opa_osd_dump.1* +%{_mandir}/man1/opa_osd_exercise.1* +%{_mandir}/man1/opa_osd_perf.1* +%{_mandir}/man1/opa_osd_query.1* +%config(noreplace) %{_sysconfdir}/rdma/dsap.conf +%config(noreplace) %{_sysconfdir}/rdma/op_path_rec.conf +%{_sysconfdir}/rdma/opasadb.xml + +%files libopamgt +/usr/lib/libopamgt.* + + +%files libopamgt-devel +%{_includedir}/opamgt +/usr/src/opamgt + +%changelog +* Mon Feb 26 2018 Jijun Wang - 10.8.0.0 +- Added epoch for RHEL address-resolution, basic-tools and fastfabric +- Added component information in description for all rpms +* Thu Apr 13 2017 Scott Breyer - 10.5.0.0 +- Updates for spec file cleanup +* Fri Oct 10 2014 Erik E. Kahn - 1.0.0-ifs +- Initial version diff --git a/opamgt/Makefile b/opamgt/Makefile new file mode 100644 index 0000000..aba3de6 --- /dev/null +++ b/opamgt/Makefile @@ -0,0 +1,212 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** +# Makefile for opamgt + +# Include Make Control Settings +include $(TL_DIR)/$(PROJ_FILE_DIR)/Makesettings.project + +#=============================================================================# +# Definitions: +#-----------------------------------------------------------------------------# + +# Name of SubProjects +DS_SUBPROJECTS = +# name of executable or downloadable image +EXECUTABLE = #omgt_tils$(EXE_SUFFIX) +# list of sub directories to build +DIRS = +# C files (.c) +CFILES = \ + src/ib_utils_openib.c \ + src/iba2ibo_util_helper.c \ + src/ib_notice.c \ + src/ib_notice_net.c \ + src/opamgt_dump_mad.c \ + src/stl_convertfuncs.c \ + src/opamgt.c \ + src/opamgt_pa.c \ + src/opamgt_sa.c \ + src/opamgt_sa_notice.c \ + src/opamgt_sa_query.c \ + src/omgt_oob_connections.c \ + src/omgt_oob_net.c \ + src/omgt_oob_net_blob.c \ + src/omgt_oob_net_queue.c \ + src/omgt_oob_ssl.c \ + src/opamgt_ea.c + + # Add more c files here +# C++ files (.cpp) +CCFILES = \ + # Add more cpp files here +# lex files (.lex) +LFILES = \ + # Add more lex files here +# archive library files (basename, $ARFILES will add MOD_LIB_DIR/prefix and suffix) +LIBFILES= +# Windows Resource Files (.rc) +RSCFILES = +# Windows IDL File (.idl) +IDLFILE = +# Windows Linker Module Definitions (.def) file for dll's +DEFFILE = +# targets to build during INCLUDES phase (add public includes here) +INCLUDE_TARGETS = \ + src/ib_utils_openib.h \ + src/ib_notice_net.h \ + src/stl_convertfuncs.h \ + include/public/opamgt.h \ + include/public/opamgt_pa.h \ + include/public/opamgt_sa.h \ + include/public/opamgt_sa_notice.h \ + include/opamgt_dump_mad.h \ + include/opamgt_priv.h \ + include/opamgt_pa_priv.h \ + include/opamgt_sa_priv.h \ + include/opamgt_ea_priv.h \ + src/omgt_oob_ssl.h + # Add more h hpp files here +# Library example files, to be include during staging +SAMPLE_TARGETS = \ + samples/README \ + samples/Makefile \ + samples/saquery.c \ + samples/paquery.c \ + samples/simple_sa_query.c \ + samples/simple_sa_notice.c \ + samples/simple_pa_query.c \ + samples/job_schedule.c \ + samples/show_switch_cost_matrix.c + +# Non-compiled files +MISC_FILES = version +# all source files +SOURCES = $(CFILES) $(CCFILES) $(LFILES) $(RSCFILES) $(IDLFILE) +# Source files to include in DSP File +DSP_SOURCES = $(INCLUDE_TARGETS) $(SOURCES) $(MISC_FILES) \ + $(RSCFILES) $(DEFFILE) $(MAKEFILE) +# all object files +OBJECTS = $(CFILES:.c=$(OBJ_SUFFIX)) $(CCFILES:.cpp=$(OBJ_SUFFIX)) \ + $(LFILES:.lex=$(OBJ_SUFFIX)) +RSCOBJECTS = $(RSCFILES:.rc=$(RES_SUFFIX)) +# targets to build during LIBS phase +LIB_TARGETS_IMPLIB = +LIB_TARGETS_ARLIB = $(LIB_PREFIX)opamgt-priv$(ARLIB_SUFFIX) +LIB_TARGETS_EXP = $(LIB_TARGETS_IMPLIB:$(ARLIB_SUFFIX)=$(EXP_SUFFIX)) +LIB_TARGETS_MISC = +# targets to build during CMDS phase +SHLIB_VERSION = $(shell cat ./version) +CMD_TARGETS_SHLIB = $(LIB_PREFIX)opamgt$(SHLIB_VERSION_SUFFIX) +vals = $(subst ., ,$(notdir $(CMD_TARGETS_SHLIB))) +override SHLIB_SONAME = $(word 1,$(vals)).$(word 2,$(vals)).$(word 3,$(vals)) +CMD_TARGETS_EXE = $(EXECUTABLE) +CMD_TARGETS_MISC = +# files to remove during clean phase +CLEAN_TARGETS_MISC = +CLEAN_TARGETS = $(OBJECTS) $(RSCOBJECTS) $(IDL_TARGETS) $(CLEAN_TARGETS_MISC) +# other files to remove during clobber phase +CLOBBER_TARGETS_MISC= +# sub-directory to install to within bin +BIN_SUBDIR = +# sub-directory to install to within include +INCLUDE_SUBDIR = + +# Additional Settings +#CLOCALDEBUG = User defined C debugging compilation flags [Empty] +#CCLOCALDEBUG = User defined C++ debugging compilation flags [Empty] +#CLOCAL = User defined C flags for compiling [Empty] +#CCLOCAL = User defined C++ flags for compiling [Empty] +#BSCLOCAL = User flags for Browse File Builder [Empty] +#DEPENDLOCAL = user defined makedepend flags [Empty] +#LINTLOCAL = User defined lint flags [Empty] +#LOCAL_INCLUDE_DIRS = User include directories to search for C/C++ headers [Empty] +#LDLOCAL = User defined C flags for linking [Empty] +#IMPLIBLOCAL = User flags for Object Lirary Manager [Empty] +#MIDLLOCAL = User flags for IDL compiler [Empty] +#RSCLOCAL = User flags for resource compiler [Empty] +#LOCALDEPLIBS = User libraries to include in dependencies [Empty] +#LOCALLIBS = User libraries to use when linking [Empty] +# (in addition to LOCALDEPLIBS) +#LOCAL_LIB_DIRS = User library directories for libpaths [Empty] + +CLOCAL=$(CIBACCESS) $(CPIC) +CLOCALDEBUG=-Og +LOCALDEPLIBS = +LOCALDEPLIBS=$(IBACCESS_USER_LIBS) +LOCAL_INCLUDE_DIRS=include . src +LOCALLIBS=$(OPENIB_USER_LIBS) +LOCAL_LIB_DIRS=$(OPENIB_USER_LIB_DIRS) $(IBACCESS_USER_LIB_DIRS) + +# Include Make Rules definitions and rules +include $(TL_DIR)/$(PROJ_FILE_DIR)/Makerules.project + + +#=============================================================================# +# Overrides: +#-----------------------------------------------------------------------------# +#CCOPT = # C++ optimization flags, default lets build config decide +#COPT = # C optimization flags, default lets build config decide +#SUBSYSTEM = Subsystem to build for (none, console or windows) [none] +# (Windows Only) +#USEMFC = How Windows MFC should be used (none, static, shared, no_mfc) [none] +# (Windows Only) +#=============================================================================# + +#=============================================================================# +# Rules: +#-----------------------------------------------------------------------------# +# process Sub-directories +include $(TL_DIR)/Makerules/Maketargets.toplevel + +# build cmds and libs +include $(TL_DIR)/Makerules/Maketargets.build + +# install for includes, libs and cmds phases +include $(TL_DIR)/Makerules/Maketargets.install + +# install for stage phase +#include $(TL_DIR)/Makerules/Maketargets.stage +STAGE:: +ifeq "$(PRODUCT)" "OPENIB_FF" + $(VS)$(STAGE_INSTALL) $(STAGE_INSTALL_DIR_OPT) $(PROJ_STAGE_LIB_DIR) $(CMD_TARGETS_SHLIB) + $(VS)$(STAGE_INSTALL) $(STAGE_INSTALL_DIR_OPT) $(PROJ_STAGE_OPAMGT_DIR) \ + $(INCLUDE_TARGETS) \ + $(SAMPLE_TARGETS) \ + $(MISC_FILES) +endif + +# Unit test execution +#include $(TL_DIR)/Makerules/Maketargets.runtest + +#=============================================================================# + +#=============================================================================# +# DO NOT DELETE THIS LINE -- make depend depends on it. +#=============================================================================# + diff --git a/opamgt/README b/opamgt/README new file mode 100644 index 0000000..0ef3955 --- /dev/null +++ b/opamgt/README @@ -0,0 +1,3 @@ +adapter library to support IbAccess style management APIs on top of Open Fabrics +This also contains some common utility functions to facilitate development +of various tools for in-band and out-of-band management. diff --git a/opamgt/include/README b/opamgt/include/README new file mode 100644 index 0000000..a0100ae --- /dev/null +++ b/opamgt/include/README @@ -0,0 +1 @@ +Contains external interface to opamgt. Headers in the "Public" directory are included in the external library API. Headers in top level include directory expose opamgt interface to internal IFS build components but are not included in public library API. diff --git a/opamgt/include/opamgt_dump_mad.h b/opamgt/include/opamgt_dump_mad.h new file mode 100644 index 0000000..8d63b48 --- /dev/null +++ b/opamgt/include/opamgt_dump_mad.h @@ -0,0 +1,57 @@ +/* BEGIN_ICS_COPYRIGHT7 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT7 ****************************************/ + +#ifndef __OMGT_UTIL_DUMP_MAD__ +#define __OMGT_UTIL_DUMP_MAD__ + +#include +#include + +/** + * dump MAD HEX data with minimal header decoding + */ +void omgt_dump_mad(FILE * file, uint8_t *buf, size_t size, const char *msg, ...); + +/** + * dump RAW HEX data + */ +void omgt_xdump(FILE *file, uint8_t *p, size_t size, int width); + + +/* Extends umad_class_str(). + * Extends umad_method_str(). + * Extends umad_attribute_str(). + * + * Checks BaseVersion == 128 (STL) else IB + */ +const char *stl_class_str(uint8_t BaseVersion, uint8_t class); +const char *stl_method_str(uint8_t BaseVersion, uint8_t class, uint8_t method); +const char *stl_mad_status_str(uint8_t BaseVersion, uint8_t class, uint16_t Status); +const char *stl_attribute_str(uint8_t BaseVersion, uint8_t class, uint16_t attr); +#endif /* __OMGT_UTIL_DUMP_MAD__ */ diff --git a/opamgt/include/opamgt_ea_priv.h b/opamgt/include/opamgt_ea_priv.h new file mode 100644 index 0000000..2d8d787 --- /dev/null +++ b/opamgt/include/opamgt_ea_priv.h @@ -0,0 +1,84 @@ +/* BEGIN_ICS_COPYRIGHT2 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT2 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +#ifndef __OPAMGT_PRIV_EA_H__ +#define __OPAMGT_PRIV_EA_H__ + +#include "stl_mad_priv.h" +#include +#include +#include +#include + +/** ========================================================================= + * OPAMGT EA interface + */ + +/** + * @brief Initialize EA connection on existing omgt_port session + * + * @param port omgt_port session to start EA interface on + * + * @return + * OMGT_SERVICE_STATE_OPERATIONAL - initialization successful + * OMGT_SERVICE_STATE_DOWN - initialization not successful/EaServer not + * available + * OMGT_SERVICE_STATE_UNAVAILABLE - ES Service not found + */ +int +omgt_ea_service_connect(struct omgt_port *port); + +/** + * @brief Get LID and SL of master EM service + * + * This function will query the SA service records to get the EM's GID. It will + * then construct a PATH record query (using the ServiceGID as the DGID for the + * request) to get the EM's LID and SL for sending PA queries. + * + * @param port port object to to store master EM LID and SL. + * + * @return FSTATUS + */ +FSTATUS +iba_ea_query_master_em_lid(struct omgt_port *port); + +/** + * Pose a query to the fabric, expect a response. + * + * @param port - port opened by omgt_open_port_* + * @param pQuery - pointer to the query structure + * @param ppQueryResult - pointer where the response will go + * + * @return - 0 if success, else error code + */ +FSTATUS omgt_query_ea(struct omgt_port *port, OMGT_QUERY *pQuery, struct _QUERY_RESULT_VALUES **ppQueryResult); + +#endif /* __OPAMGT_PRIV_EA_H__ */ diff --git a/opamgt/include/opamgt_oob.h b/opamgt/include/opamgt_oob.h new file mode 100644 index 0000000..8e88a8d --- /dev/null +++ b/opamgt/include/opamgt_oob.h @@ -0,0 +1,28 @@ +/* BEGIN_ICS_COPYRIGHT2 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT2 ****************************************/ diff --git a/opamgt/include/opamgt_pa_priv.h b/opamgt/include/opamgt_pa_priv.h new file mode 100644 index 0000000..0676ecd --- /dev/null +++ b/opamgt/include/opamgt_pa_priv.h @@ -0,0 +1,598 @@ +/* BEGIN_ICS_COPYRIGHT2 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT2 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + + +#ifndef __OPAMGT_PRIV_PA_H__ +#define __OPAMGT_PRIV_PA_H__ + +#include +#include +#include +#include +#include +#include "opamgt_priv.h" +#include +#include + +#define PA_REQ_HEADER_SIZE (sizeof(MAD_COMMON) + sizeof(SA_MAD_HDR)) + +/** + * @brief PA query input type to string + * @param code Input type code value + * @return + * Input type static string + */ +const char* +iba_pa_query_input_type_msg( + QUERY_INPUT_TYPE code + ); + +/** + * @brief PA query output type to string + * @param code Output type code value + * @return + * Output type static string + */ +const char* +iba_pa_query_result_type_msg( + QUERY_RESULT_TYPE code + ); + +/** + * @brief Initialize PA connection on existing omgt_port session + * + * @param port omgt_port session to start PA interface on + * + * @return + * PACLIENT_OPERATIONAL - initialization successful + * PACLIENT_DOWN - initialization not successful/PaServer not available + */ +int +omgt_pa_service_connect( + struct omgt_port *port + ); + +/** + * Clear specified port counters for specified port + * + * @param port Port to operate on. + * @param pm_image_id_query Image ID of port counters to clear. + * @param lid LID of port. + * @param port_num Port number. + * @param selct_flags Port's counters to clear. + * + * @return + * FSUCCESS - Clear successful + * FERROR - Error + */ +FSTATUS +pa_client_clr_port_counters( + struct omgt_port *port, + STL_PA_IMAGE_ID_DATA pm_image_id_query, + STL_LID lid, + uint8 port_num, + uint32 select_flag + ); + +/************************************************************ + * The following come from iba2ibo_paquery_helper.h + * Mainly called by opapaquery tool and PA client above. + ************************************************************/ + +/** + * Enable debugging output in the opamgt library. + * + * @param port The local port to operate on. + * + * @return + * None + */ +void +set_opapaquery_debug ( + IN struct omgt_port *port + ); + +/** + * Get port statistics (counters) + * + * @param port Local port to operate on. + * @param node_lid Remote node LID. + * @param port_num Remote port number. + * @param port_counters Pointer to port counters to fill. + * @param delta_flag 1 for delta counters, 0 for raw image counters. + * @param user_cntrs_flag 1 for running counters, 0 for image counters. (delta must be 0) + * @param image_id Pointer to image ID of port counters to get. + * + * @return + * Valid Pointer - A pointer to the memory for the counters data. The caller must free it. + * NULL - Error + */ +STL_PORT_COUNTERS_DATA * +iba_pa_single_mad_port_counters_response_query( + IN struct omgt_port *port, + IN STL_LID node_lid, + IN uint8_t port_number, + IN uint32_t delta_flag, + IN uint32_t user_cntrs_flag, + IN STL_PA_IMAGE_ID_DATA *image_id + ); +/** + * Clear port statistics (counters) + * + * @param port Local Port to operate on. + * @param node_lid Remote node LID. + * @param port_num Remote port number. + * @param select Port's counters to clear. + * + * @return + * Valid Pointer - A pointer to the memory for the clear port counters data (containing the + * info as which counters have been cleared). The caller must free it. + * NULL - Error + */ +STL_CLR_PORT_COUNTERS_DATA * +iba_pa_single_mad_clr_port_counters_response_query( + IN struct omgt_port *port, + IN uint32_t node_lid, + IN uint8_t port_number, + IN uint32_t select + ); + +/** + * Clear all ports, statistics (counters) + * + * @param port Local port to operate on. + * @param select Port's counters to clear. + * + * @return + * Valid Pointer - A pointer to the memory for the clear all port counters data (containing the + * info as which counters have been cleared). The caller must free it. + * NULL - Error + */ +STL_CLR_ALL_PORT_COUNTERS_DATA * +iba_pa_single_mad_clr_all_port_counters_response_query( + IN struct omgt_port *port, + IN uint32_t select + ); + + +/** + * Get the PM config data. + * + * @param port Local port to operate on. + * + * @return + * Valid Pointer - A pointer to the memory for pm config data. The caller must free it. + * NULL - Error + */ +STL_PA_PM_CFG_DATA * +iba_pa_single_mad_get_pm_config_response_query( + IN struct omgt_port *port + ); + +/** + * Free a sweep image. + * + * @param port Local port to operate on. + * @param image_id ID of image to freeze. + * + * @return + * Valid Pointer - A pointer to the memory for the frozen image id data. The caller must free it. + * NULL - Error + */ +STL_PA_IMAGE_ID_DATA * +iba_pa_single_mad_freeze_image_response_query( + IN struct omgt_port *port, + IN STL_PA_IMAGE_ID_DATA *image_id + ); + +/** + * Release a sweep image. + * + * @param port Local port to operate on. + * @param image_id Ponter to id of image to release. + * + * @return + * Valid Pointer - A pointer to the memory for the released image id data. The caller must free it. + * NULL - Error + */ +STL_PA_IMAGE_ID_DATA * +iba_pa_single_mad_release_image_response_query( + IN struct omgt_port *port, + IN STL_PA_IMAGE_ID_DATA *image_id + ); + +/** + * Renew a sweep image. + * + * @param port Local port to operate on. + * @param image_id Ponter to id of image to renew. + * + * @return + * Valid Pointer - A pointer to the memory for the renewed image id data. The caller must free it. + * NULL - Error + */ +STL_PA_IMAGE_ID_DATA * +iba_pa_single_mad_renew_image_response_query( + IN struct omgt_port *port, + IN STL_PA_IMAGE_ID_DATA *image_id + ); + +/** + * Move a frozen image 1 to image 2. + * + * @param port Local port to operate on. + * @param move_info Ponter to move info (src and dest image ID). + * + * @return + * Valid Pointer - A pointer to the memory for the image move info. The caller must free it. + * NULL - Error + */ +STL_MOVE_FREEZE_DATA * +iba_pa_single_mad_move_freeze_response_query( + IN struct omgt_port *port, + IN STL_MOVE_FREEZE_DATA *move_info + ); + +/** + * Get image info + * + * @param port Local port to operate on. + * @param image_info Ponter to image info (containing valid image ID). + * + * @return + * Valid Pointer - A pointer to the memory for the image info data. The caller must free it. + * NULL - Error + */ +STL_PA_IMAGE_INFO_DATA * +iba_pa_multi_mad_get_image_info_response_query ( + IN struct omgt_port *port, + IN STL_PA_IMAGE_INFO_DATA *image_info + ); + +/** + * @brief Get LID and SL of master PM service + * + * This function will query the SA service records to get the PM's GID. It will + * then construct a PATH record query (using the ServiceGID as the DGID for the + * request) to get the PM's LID and SL for sending PA queries. + * + * @param port port object to to store master PM LID and SL. + * + * @return FSTATUS + */ +FSTATUS +iba_pa_query_master_pm_lid(struct omgt_port *port); + +/** + * Get multi-record response for pa group data (group list). + * + * @param port Local port to operate on. + * @param query Pointer to the query + * @param pquery_result Pointer to query result to be filled. The caller has + * to free the buffer. + * + * @return + * FSUCCESS - Get successfully + * FERROR - Error + */ +FSTATUS +iba_pa_multi_mad_group_list_response_query( + IN struct omgt_port *port, + IN POMGT_QUERY query, + OUT PQUERY_RESULT_VALUES *pquery_result + ); +FSTATUS +iba_pa_multi_mad_group_list2_response_query( + IN struct omgt_port *port, + IN POMGT_QUERY query, + IN STL_PA_IMAGE_ID_DATA *image_id, + OUT PQUERY_RESULT_VALUES *pquery_result + ); + +/** + * Get multi-record response for pa group info (stats). + * + * @param port Local port to operate on. + * @param query Pointer to the query + * @param group_name Group name + * @param pquery_result Pointer to query result to be filled. The caller has + * to free the buffer. + * @param image_id Pointer to the image ID. + * + * @return + * FSUCCESS - Get successfully + * FERROR - Error + */ +FSTATUS +iba_pa_multi_mad_group_stats_response_query( + IN struct omgt_port *port, + IN POMGT_QUERY query, + IN char *group_name, + OUT PQUERY_RESULT_VALUES *pquery_result, + IN STL_PA_IMAGE_ID_DATA *image_id + ); + +/** + * Get multi-record response for pa group config. + * + * @param port Local port to operate on. + * @param query Pointer to the query + * @param group_name Group name + * @param pquery_result Pointer to query result to be filled. The caller has + * to free the buffer. + * @param imageID Pointer to the image ID. + * + * @return + * FSUCCESS - Get successfully + * FERROR - Error + */ +FSTATUS +iba_pa_multi_mad_group_config_response_query( + IN struct omgt_port *port, + IN POMGT_QUERY query, + IN char *group_name, + OUT PQUERY_RESULT_VALUES *pquery_result, + IN STL_PA_IMAGE_ID_DATA *image_id + ); +/** + * Get multi-record response for pa group node Info. + * + * @param port Local port to operate on. + * @param query Pointer to the query + * @param group_name Group name + * @param nodeLid node LID + * @param nodeGuid node GUID + * @param nodeDesc node Description + * @param pquery_result Pointer to query result to be filled. The caller has + * to free the buffer. + * @param imageID Pointer to the image ID. + * + * @return + * FSUCCESS - Get successfully + * FERROR - Error + */ +FSTATUS +iba_pa_multi_mad_group_nodeinfo_response_query( + IN struct omgt_port *port, + IN POMGT_QUERY query, + IN char *group_name, + IN STL_LID nodeLid, + IN uint64 nodeGuid, + IN char *nodeDesc, + OUT PQUERY_RESULT_VALUES *pquery_result, + IN STL_PA_IMAGE_ID_DATA *image_id + ); + +/** + * Get multi-record response for pa group link Info. + * + * @param port Local port to operate on. + * @param query Pointer to the query + * @param group_name Group name + * @param inputLid input LID + * @param inputPort input port + * @param pquery_result Pointer to query result to be filled. The caller has + * to free the buffer. + * @param imageID Pointer to the image ID. + * + * @return + * FSUCCESS - Get successfully + * FERROR - Error + */ +FSTATUS +iba_pa_multi_mad_group_linkinfo_response_query( + IN struct omgt_port *port, + IN POMGT_QUERY query, + IN char *group_name, + IN STL_LID inputLid, + IN uint8 inputPort, + OUT PQUERY_RESULT_VALUES *pquery_result, + IN STL_PA_IMAGE_ID_DATA *image_id + ); + +/** + * Get multi-record response for pa group focus portlist. + * + * @param port Local port to operate on. + * @param query Pointer to the query + * @param group_name Group name + * @param select Select value for focus portlist. + * @param start Start index value of portlist + * @param range Index range of portlist. + * @param pquery_result Pointer to query result to be filled. The caller has + * to fill the buffer. + * @param imageID Pointer to the image ID. + * + * @return + * FSUCCESS - Get successfully + * FERROR - Error + */ +FSTATUS +iba_pa_multi_mad_focus_ports_response_query ( + IN struct omgt_port *port, + IN POMGT_QUERY query, + IN char *group_name, + IN uint32 select, + IN uint32 start, + IN uint32 range, + OUT PQUERY_RESULT_VALUES *pquery_result, + IN STL_PA_IMAGE_ID_DATA *image_id + ); + + +/** + * Get multi-record response for pa group focus portlist. + * + * @param port Local port to operate on. + * @param query Pointer to the query. + * @param group_name Group name. + * @param select Select value for focus portlist. + * @param start Start index value of portlist. + * @param range Index range of portlist. + * @param pquery_result Pointer to query result to be filled. The caller has + * to fill the buffer. + * @param imageID Pointer to the image ID. + * + * @return + * FSUCCESS - Get successfully + * FERROR - Error + */ +FSTATUS +iba_pa_multi_mad_focus_ports_multiselect_response_query ( + IN struct omgt_port *port, + IN POMGT_QUERY query, + IN char *group_name, + IN uint32 start, + IN uint32 range, + OUT PQUERY_RESULT_VALUES *pquery_result, + IN STL_PA_IMAGE_ID_DATA *image_id, + IN STL_FOCUS_PORT_TUPLE *tuple, + IN uint8 logical_operator + ); + +/** + * Get multi-record response for pa vf data (vf list). + * + * @param port Local port to operate on. + * @param query Pointer to the query + * @param pquery_result Pointer to query result to be filled. The caller has + * to free the buffer. + * + * @return + * FSUCCESS - Get successfully + * FERROR - Error + */ +FSTATUS +iba_pa_multi_mad_vf_list_response_query( + IN struct omgt_port *port, + IN POMGT_QUERY query, + OUT PQUERY_RESULT_VALUES *pquery_result + ); +FSTATUS +iba_pa_multi_mad_vf_list2_response_query( + IN struct omgt_port *port, + IN POMGT_QUERY query, + IN STL_PA_IMAGE_ID_DATA *image_id, + OUT PQUERY_RESULT_VALUES *pquery_result + ); + +/** + * Get multi-record response for pa vf info (vf info). + * + * @param port Local port to operate on. + * @param query Pointer to the query + * @param pquery_result Pointer to query result to be filled. The caller has + * to free the buffer. + * + * @return + * FSUCCESS - Get successfully + * FERROR - Error + */ +FSTATUS +iba_pa_multi_mad_vf_info_response_query( + IN struct omgt_port *port, + IN POMGT_QUERY query, + IN char *vf_name, + OUT PQUERY_RESULT_VALUES *pquery_result, + IN STL_PA_IMAGE_ID_DATA *image_id + ); + +/** + * Get vf config info + * + * @param port Port to operate on. + * @param pm_image_id_query Image ID of vf config to get. + * @param vf_name Pointer to vf name + * @param pm_image_id_resp Pointer to image ID of vf info returned. + * @param pm_vf_config Pointer to vf config to fill. Upon successful return, a memory to + * contain the vf config is allocated. The caller must call + * omgt_pa_release_vf_config to free the memory later. + * + * @return + * FSUCCESS - Get successful + * FERROR - Error + */ +FSTATUS +iba_pa_multi_mad_vf_config_response_query( + IN struct omgt_port *port, + IN POMGT_QUERY query, + IN char *vf_name, + OUT PQUERY_RESULT_VALUES *pquery_result, + IN STL_PA_IMAGE_ID_DATA *image_id + ); + +STL_PA_VF_PORT_COUNTERS_DATA * +iba_pa_single_mad_vf_port_counters_response_query( + IN struct omgt_port *port, + IN uint32_t node_lid, + IN uint8_t port_number, + IN uint32_t delta_flag, + IN uint32_t user_cntrs_flag, + IN char *vfName, + IN STL_PA_IMAGE_ID_DATA *image_id + ); + +STL_PA_CLEAR_VF_PORT_COUNTERS_DATA * +iba_pa_single_mad_clr_vf_port_counters_response_query( + IN struct omgt_port *port, + IN uint32_t node_lid, + IN uint8_t port_number, + IN uint32_t select, + IN char *vfName + ); + +FSTATUS +iba_pa_multi_mad_vf_focus_ports_response_query ( + IN struct omgt_port *port, + IN POMGT_QUERY query, + IN char *vf_name, + IN uint32 select, + IN uint32 start, + IN uint32 range, + OUT PQUERY_RESULT_VALUES *pquery_result, + IN STL_PA_IMAGE_ID_DATA *image_id + ); + + +/** + * Get and Convert a MAD status code into string. + * + * @param port Local port to operate on. + * + * @return + * The corresponding status string. + */ +const char* +iba_pa_mad_status_msg( + IN struct omgt_port *port + ); + +#endif //__OPAMGT_PRIV_PA_H__ diff --git a/opamgt/include/opamgt_priv.h b/opamgt/include/opamgt_priv.h new file mode 100644 index 0000000..5865000 --- /dev/null +++ b/opamgt/include/opamgt_priv.h @@ -0,0 +1,489 @@ +/* BEGIN_ICS_COPYRIGHT2 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT2 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +#ifndef __OPAMGT_PRIV_H__ +#define __OPAMGT_PRIV_H__ + +#include +/* Needed for getpid() */ +#include +#include +#include "opamgt.h" + +#include "iba/ib_types.h" + +#define OMGT_STL_OUI (0x66A) + +#include "iba/ib_generalServices.h" + +#ifndef OMGT_OUTPUT_ERROR +#define OMGT_OUTPUT_ERROR(port, format, args...) \ + do { \ + FILE *current_log_file = port ? port->error_file : stderr; \ + if (port && current_log_file) { \ + if (current_log_file == OMGT_DBG_FILE_SYSLOG) { \ + syslog(LOG_ERR, "opamgt ERROR: [%d] %s: " format, \ + (int)getpid(), __func__, ##args); \ + } else { \ + fprintf(current_log_file, "opamgt ERROR: [%d] %s: " format, \ + (int)getpid(), __func__, ##args); \ + } \ + } \ + } while(0) +#endif + +/* NOTE we keep this at LOG_INFO and reserve LOG_DEBUG for packet dump */ +#ifndef OMGT_DBGPRINT +#define OMGT_DBGPRINT(port, format, args...) \ + do { \ + FILE *current_log_file = port ? port->dbg_file : NULL; \ + if (port && current_log_file) { \ + if (current_log_file == OMGT_DBG_FILE_SYSLOG) { \ + syslog(LOG_INFO, "opamgt: [%d] %s: " format, \ + (int)getpid(), __func__, ##args); \ + } else { \ + fflush(current_log_file); fprintf(current_log_file, "opamgt: [%d] %s: " format, \ + (int)getpid(), __func__, ##args); \ + } \ + } \ + } while(0) +#endif + +#ifndef OMGT_OUTPUT_INFO +#define OMGT_OUTPUT_INFO(port, format, args...) \ + do { \ + FILE *current_log_file = port ? port->dbg_file : NULL; \ + if (port && current_log_file) { \ + if (current_log_file == OMGT_DBG_FILE_SYSLOG) { \ + syslog(LOG_INFO, "opamgt: [%d] %s: " format, \ + (int)getpid(), __func__, ##args); \ + } else { \ + fprintf(current_log_file, "opamgt: [%d] %s: " format, \ + (int)getpid(), __func__, ##args); \ + } \ + } \ + } while(0) +#endif + + +#ifndef DBG_ENTER_FUNC +#define DBG_ENTER_FUNC(port) OMGT_DBGPRINT(port, "Entering %s\n",__func__) +#endif + +#ifndef DBG_EXIT_FUNC +#define DBG_EXIT_FUNC(port) OMGT_DBGPRINT(port, "Exiting %s\n",__func__) +#endif + + +/** + * OMGT Port Accessor functions + * Data is valid once port is opened and until port object is closed. + */ + +/** + * @brief Gets Port's SM LID for the given port. + * Retrieves port's SM lid for an open in-band port. + * @param port previously initialized port object for an in-band + * connection + * @param sm_lid SM lid to be retruned + * @return OMGT_STATUS_T + */ +OMGT_STATUS_T omgt_port_get_port_sm_lid(struct omgt_port *port, uint32_t *sm_lid); +/** + * @brief Gets Port's LMC for the given port. + * Retrieves port's LMC for an open in-band port. + * @param port previously initialized port object for an in-band + * connection + * @param port_lmc LMC to be retruned + * @return OMGT_STATUS_T + */ +OMGT_STATUS_T omgt_port_get_port_lmc(struct omgt_port *port, uint32_t *port_lmc); +/** + * @brief Gets Port's SM SL for the given port. + * Retrieves port's SM sl for an open in-band port. + * @param port previously initialized port object for an in-band + * connection + * @param sm_sl SM sl to be retruned + * @return OMGT_STATUS_T + */ +OMGT_STATUS_T omgt_port_get_port_sm_sl(struct omgt_port *port, uint8_t *sm_sl); + +/** + * @brief Gets Port's NodeType for the given port. + * Retrieves port's NodeType for an open in-band port. + * @param port previously initialized port object for an in-band + * connection + * @param node_type Node Type of the omgt_port + * @return OMGT_STATUS_T + */ +OMGT_STATUS_T omgt_port_get_node_type(struct omgt_port *port, uint8_t *node_type); + +/* Create OPA GID from 32 bit LID */ +static inline uint64_t omgt_create_gid(STL_LID lid) +{ + return (uint64_t) OMGT_STL_OUI << 40 | lid; +} + +/* Check if lid is beyond the IB Unicast LID range */ +static inline int omgt_is_ext_lid(STL_LID lid) +{ + return !!((lid > LID_UCAST_END) && lid != STL_LID_PERMISSIVE); +} + +/** + * Gets the ISSM device corresponding to the specified port. + * + * @param port Pointer to the opened local port object. + * @param path Buffer in which to place the device path + * @param path_max Maximum length of the output buffer + * + * @return FSUCCESS on success, or UMad error code on failure + */ +FSTATUS omgt_get_issm_device(struct omgt_port *port, char *path, int path_max); + +/** + * Function to refresh the pkey table for the MAD interface + * for a given hfi name and port. + * To use with omgt_xxx_mad, and the umad OFED library. + * + * @param *port pointer to port object + * + * @return 0 success + * -1 Failure + */ +extern int omgt_mad_refresh_port_pkey(struct omgt_port *port); + +/** + * Given a port and a pkey return if this pkey is in the ports local + * pkey_table + * + * @param *port pointer to port object + * @param pkey pkey to search for + * + * @return pkey_idx success + * -1 Failure + */ +extern int omgt_find_pkey(struct omgt_port *port, uint16_t pkey); + + +/** + * Given a port, destination lid, hopcount, return the most + * appropriate management pkey to use. + * + * @param *port pointer to port object + * @param dlid destination lid + * @param hopCnt hop count + * + * @return pkey success + * 0 Failure (Not mgmt allowed for request) + */ +extern uint16_t omgt_get_mgmt_pkey(struct omgt_port *port, STL_LID dlid, uint8_t hopCnt); + + +/** ========================================================================= + * Send Recv interface + */ + +/** + * bind a list of managment classes/methods with the omgt_port object + * + * "bind" must be done if a client wants to respond to unsolicited MAD's + * + * User may call this fn multiple times to register for different class/method + * combinations. + * + * However, registering the same class/method combination twice will result in + * an error. + * + * 3 special flags are used to ease registration for a simple responding + * client, trap processing client or report processing client. If these bits + * are set, methods are set automatically as documented for the client. + * + * @param port port opened by omgt_open_port_* + * @param *mgmt_classes pointer to a list of managment classes to be registered. + * The list is terminated by a record that has 0 for the + * base_version. + * + * Returns 0 if successful, +errno status + */ +#define OMGT_CLASS_ARG_MAX_METHODS 64 +struct omgt_class_args { + uint8_t base_version; // IB_BASE_VERSION or STL_BASE_VERSION + uint8_t mgmt_class; // MCLASS_SUBN_ADM, STL_SA_CLASS, etc... + uint8_t class_version; // IB_BM_CLASS_VERSION, STL_SA_CLASS_VERSION, etc... + int is_responding_client; // client responds to get's and sets + // GET && SET + // if (SA class) + // GET && SET && GET_TABLE && DELETE && GET_TRACE_TABLE + int is_trap_client; // client processes traps + // TRAP && TRAP_REPRESS + int is_report_client; // client processes report + // REPORT + int kernel_rmpp; // nonzero if kernel rmpp coalescing support is desired. + uint8_t *oui; // vendor-specific OUI for vendor classes. + int use_methods; // use the method list instead of default + uint8_t methods[OMGT_CLASS_ARG_MAX_METHODS]; // list of methods. + uint8_t res[64]; +}; +int omgt_bind_classes(struct omgt_port *port, struct omgt_class_args *mgmt_classes); + + +/** + * Address vector for sending MAD's + * Also used to return address information on received MAD's + */ +struct omgt_mad_addr { + STL_LID lid; + uint32_t qpn; + uint32_t qkey; + uint16_t pkey; + uint8_t sl; + uint8_t age; + uint32_t flags; + uint16_t entropy; + uint8_t res[18]; +}; +enum omgt_mad_addr_flags { + OMGT_MAD_ADDR_SM = (1 << 0), /* use SM addr values defined in PortInfo (SMLID/SMSL)*/ + OMGT_MAD_ADDR_16B = (1 << 1), /* Force L2 layer to use 16B packets */ +}; +#define OMGT_DEFAULT_PKEY 0xffff +/** + * Send and wait for response MAD + * (response is allocated and returned to user) + * + * @param port port opened by omgt_open_port_* + * @param *send_mad pointer to outbound MAD + * @param send_size size of send_mad buffer + * @param *addr destination address information + * @param **recv_mad pointer to inbound MAD (Allocated based on inbound size) + * @param *recv_size size of recv_mad buffer returned + * @param timeout_ms OFED send timeout in ms (if timeout_ms < 0 wait forever) + * @param retries number of retries to attempt for MAD + * + * NOTE: function will wait up to timeout_ms * retries for a response + * + * @return 0 (SUCCESS) or error code + * [Error codes are as specified in omgt_recv_mad_alloc] + */ +FSTATUS omgt_send_recv_mad_alloc(struct omgt_port *port, + uint8_t *send_mad, size_t send_size, + struct omgt_mad_addr *addr, + uint8_t **recv_mad, size_t *recv_size, + int timeout_ms, int retries); + +/** + * Send and wait for response MAD + * (response is allocated by user) + * + * @param port port opened by omgt_open_port_* + * @param *send_mad pointer to outbound mad + * @param send_size size of send_mad buffer + * @param *addr destination address information + * @param *recv_mad pointer to buffer to hold response MAD + * @param *recv_size IN size of recv_mad buffer + * OUT sizeof actual data received. + * @param timeout_ms OFED send timeout in ms (if timeout_ms < 0 wait forever) + * @param retries number of retries to attempt for MAD + * + * NOTE: function will wait up to timeout_ms * retries for a response + * + * @return 0 (SUCCESS) or error code + * [Error codes are as specified in omgt_recv_mad_no_alloc] + */ +FSTATUS omgt_send_recv_mad_no_alloc(struct omgt_port *port, + uint8_t *send_mad, size_t send_size, + struct omgt_mad_addr *addr, + uint8_t *recv_mad, size_t *recv_size, + int timeout_ms, int retries); + +/** + * Send a MAD + * + * @param port port opened by omgt_open_port_* + * @param *send_mad pointer to mad to send + * @param send_size Length of buffer to send + * @param addr destination address information + * @param timeout_ms OFED send timeout in ms (if timeout_ms < 0 wait forever) + * @param retries number of retries to attempt for MAD + * + * @return FSTATUS (0 if successful, else error code) + */ +FSTATUS omgt_send_mad2(struct omgt_port *port, uint8_t *send_mad, size_t send_size, + struct omgt_mad_addr *addr, int timeout_ms, int retries); + +/** + * Receive a packet from the specified port + * (response is allocated by user) + * + * Function will allocate an appropriately sized MAD to hold the status. + * The entire MAD is returned, including all headers. + * recv_size is initialized with the size of the returned buffer. + * + * @param port port opened by omgt_open_port_* + * @param **recv_mad pointer to inbound MAD (Allocated based on inbound size) + * @param *recv_size size of recv_mad buffer returned + * @param timeout_ms OFED send timeout in ms (if timeout_ms < 0 wait forever) + * @param addr if supplied recv'd MAD address information is filled in + * here. + * + * @return 0 if success, else error code + * + * FINVALID_PARAMETER - incorrect or missing arguments to function + * FERROR - other atypical errors + * FNOT_DONE - no packet available within timeout + * FOVERRUN - error receiving a large rmpp MAD. *recv_size indicates length + * reported by the failed umad_recv. + * FINSUFFICIENT_MEMORY - unable to allocate memory (*recv_size is length of + * MAD attempting to be allocated), but no MAD is returned + * + * For the FTIMEOUT, FREJECT and FSUCCESS return cases, *recv_mad will be + * updated with pointer to the MAD (coallesced RMPP if applicable). Caller + * must free() this buffer. *recv_size will indicate the length of the MAD. + * + * FTIMEOUT - a previous send's response exceeded timeout/retry, the sent MAD + * is returned + * FREJECT - unexpected error processing a previous send or its response, the + * sent MAD is returned + * FSUCCESS - mad successfully received + */ +FSTATUS omgt_recv_mad_alloc(struct omgt_port *port, uint8_t **recv_mad, size_t *recv_size, + int timeout_ms, struct omgt_mad_addr *addr); +/** + * Free a mad received from omgt_* + * + * @param port port opened by omgt_open_port_* + * @param **recv_mad Pointer to rcv buffer + */ +void omgt_free_recv_mad(struct omgt_port *port, uint8_t *recv_mad); + +/** + * Receive a MAD into an allocated buffer + * (response is allocated by user) + * + * @param port port opened by omgt_open_port_* + * @param *recv_mad Allocated buffer to place MAD in + * @param *recv_size IN size of recv_mad buffer + * OUT sizeof actual data received. + * @param timeout_ms OFED send timeout in ms (if timeout_ms < 0 wait forever) + * @param addr if supplied recv'd MAD address information is filled in + * here. + * + * @return 0 if success, else error code + * + * FINVALID_PARAMETER - incorrect or missing arguments to function + * FERROR - other atypical errors + * FNOT_DONE - no packet available within timeout + * FOVERRUN - large MAD (rmpp) found and discarded, 1st MAD in sequence + * returned + * FINSUFFICIENT_MEMORY - unable to allocate memory, no MAD returned + * + * For the FTIMEOUT, FREJECT and FSUCCESS return cases, recv_mad will be + * filled in with MAD data. + * + * FTIMEOUT - a previous send's response exceeded timeout/retry, the sent MAD + * is returned + * FREJECT - unexpected error processing a previous send or its response, the + * sent MAD is returned + * FSUCCESS - MAD successfully received + */ +FSTATUS omgt_recv_mad_no_alloc(struct omgt_port *port, uint8_t *recv_mad, size_t *recv_size, + int timeout_ms, struct omgt_mad_addr *addr); + +/** ========================================================================= + * Need TBD... Right now the global port has cached data for things like + * pkey, smlid, smsl, portstate... + * It is up to the user of the lib to "refresh" this data. + * It would be nice if the lib could do that on it's own. + * Regardless we could have a call to update this information if the user + * feels the need. + * +FSTATUS omgt_mad_refresh_port_details(struct omgt_port *port); + */ + + +/** ========================================================================= + * Generic HELPER FUNCTIONs + */ + +/** + * @brief Get the HFI number + * + * @param hfi_name Name of the HFI device + * + * @return + * On Success the HFI Number + * On Error -1 + */ +int omgt_get_hfi_num(char *hfi_name); + +/** + * MACRO used to get the specific record in a multi-record response + * @param p pointer to SA_MAD struct that contains the response + * @param i index of record + */ +#define GET_RESULT_OFFSET(p,i) (p->Data+(p->SaHdr.AttributeOffset*sizeof (uint64_t)*i)) + +/* translate ca/port number into a port Guid. Also return other useful structs + * if non-null pointer passed-in. + * Warning: Endian conversion not done + * + * INPUTS: + * ca - system wide CA number 1-n, if 0 port is a system wide port # + * port - 1-n, if ca is 0, system wide port number, otherwise port within CA + * if 0, 1st active port + * *pCaName - ca name for specified port + * *omgtport - optional omgt_port, will use log targets set up for this port + * + * OUTPUTS: + * *pCaGuid - ca guid for specified port + * *pPortGuid - port guid for specified port (Warning: Endian conversion not done) + * *pCaAttributes - attributes for CA, + * If PortAttributesList not null, caller must MemoryDeallocate pCaAttributes->PortAttributesList + * *ppPortAtributes - attributes for port, if ppPortAtributes not null, caller must MemoryDeallocate ppPortAtributes + * *pCaCount - number of CA in system + * *pPortCount - number of ports in system or CA (depends on ca input) + * + * RETURNS: + * FNOT_FOUND - *pCaCount and *pPortCount still output + * if ca == 0, *pPortCount = number of ports in system + * if ca < *pCaCount, *pPortCount = number of ports in CA + * otherwise *pPortCount will be 0 + * + */ +FSTATUS omgt_get_portguid(uint32 ca, uint32 port, char *pCaName, struct omgt_port *omgtport, + EUI64 *pCaGuid, EUI64 *pPortGuid, IB_CA_ATTRIBUTES *pCaAttributes, + IB_PORT_ATTRIBUTES **ppPortAttributes, uint32 *pCaCount, uint32 *pPortCount, + char *pRetCaName, int *pRetPortNum, uint64 *pRetGIDPrefix); + + + +#endif /* __OPAMGT_PRIV_H__ */ diff --git a/opamgt/include/opamgt_sa_priv.h b/opamgt/include/opamgt_sa_priv.h new file mode 100644 index 0000000..d786350 --- /dev/null +++ b/opamgt/include/opamgt_sa_priv.h @@ -0,0 +1,76 @@ +/* BEGIN_ICS_COPYRIGHT2 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT2 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +#ifndef __OPAMGT_PRIV_SA_H__ +#define __OPAMGT_PRIV_SA_H__ + +#include "opamgt_priv.h" +#include + +/* + * Convert old QUERY_INPUT_VALUE to new OMGT_QUERY_INPUT_VALUE + * + * @param output_query Query structure to be passed to omgt_query_sa + * @param old_query old query InputValue holder + * @param source_gid local gid for in-band queries or a source gid for + * out-of-band queries. Queries like path and trace + * record require a SourceGid. + * + * @return FSTATUS: FNOT_FOUND (Type Failure), FERROR (source_gid Failure) + */ +FSTATUS omgt_input_value_conversion(OMGT_QUERY *output_query, QUERY_INPUT_VALUE *old_query, IB_GID source_gid); + +/** + * Pose a query to the fabric, expect a response. + * + * @param port port opened by omgt_open_port_* + * @param pQuery pointer to the query structure + * @param ppQueryResult pointer where the response will go + * + * @return 0 if success, else error code + */ +FSTATUS omgt_query_sa(struct omgt_port *port, + OMGT_QUERY *pQuery, + QUERY_RESULT_VALUES **ppQueryResult); + +/** + * Free the memory used in the query result + * + * @param pQueryResult pointer to the SA query result buffer + * + * @return none + */ +void omgt_free_query_result_buffer(IN void * pQueryResult); + + + +#endif // __OPAMGT_PRIV_SA_H__ + diff --git a/opamgt/include/public/opamgt.h b/opamgt/include/public/opamgt.h new file mode 100644 index 0000000..8727c31 --- /dev/null +++ b/opamgt/include/public/opamgt.h @@ -0,0 +1,524 @@ +/* BEGIN_ICS_COPYRIGHT2 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT2 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +#ifndef __OPAMGT_H__ +#define __OPAMGT_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include +#include +#include + +typedef uint32_t OMGT_STATUS_T; + +#define OMGT_STATUS_SUCCESS 0x00 +#define OMGT_STATUS_ERROR 0x01 +#define OMGT_STATUS_INVALID_STATE 0x02 +#define OMGT_STATUS_INVALID_OPERATION 0x03 +#define OMGT_STATUS_INVALID_SETTING 0x04 +#define OMGT_STATUS_INVALID_PARAMETER 0x05 +#define OMGT_STATUS_INSUFFICIENT_RESOURCES 0x06 +#define OMGT_STATUS_INSUFFICIENT_MEMORY 0x07 +#define OMGT_STATUS_COMPLETED 0x08 +#define OMGT_STATUS_NOT_DONE 0x09 +#define OMGT_STATUS_PENDING 0x0A +#define OMGT_STATUS_TIMEOUT 0x0B +#define OMGT_STATUS_CANCELED 0x0C +#define OMGT_STATUS_REJECT 0x0D +#define OMGT_STATUS_OVERRUN 0x0E +#define OMGT_STATUS_PROTECTION 0x0F +#define OMGT_STATUS_NOT_FOUND 0x10 +#define OMGT_STATUS_UNAVAILABLE 0x11 +#define OMGT_STATUS_BUSY 0x12 +#define OMGT_STATUS_DISCONNECT 0x13 +#define OMGT_STATUS_DUPLICATE 0x14 +#define OMGT_STATUS_POLL_NEEDED 0x15 + +#define OMGT_STATUS_COUNT 0x16 /* should be the last value */ + + +/* opaque data defined internally */ +struct omgt_port; + +#define OMGT_DBG_FILE_SYSLOG ((FILE *)-1) +#define OMGT_DEF_TIMEOUT_MS 1000 +#define OMGT_DEF_RETRY_CNT 3 +/** + * @brief Configuration settings used when opening an omgt_port + * + * Optional advanced configuration options than can be passed to omgt_port open + * functions. + * + * Current default values when NULL pointer is passed to open functions is NULL, + * meaning error and debug logging are disabled. + * + * error_file and debug_file can be specified as either an open linux FILE, or + * can use the following special values: + * NULL: Disable output of this class of log messages + * OMGT_DBG_FILE_SYSLOG: Send this class of messages to syslog. + * Note: It is advisable, but not required, to call "openlog" prior to + * setting this option + * + * @note Enabling debug_file logging will generate a lot of data and may + * overwhelm syslog. error_file logging with syslog will use the LOG_ERR + * facility. debug_file logging with syslog will use the LOG_INFO facility. + * + */ +struct omgt_params { + FILE *error_file; /**File to send ERROR log messages to. */ + FILE *debug_file; /**File to send DEBUG log messages to. */ +}; + + +#define OMGT_OOB_SSL_DIR_SIZE 256 +#define OMGT_OOB_SSL_FILENAME_SIZE 256 +#define OMGT_OOB_SSL_PATH_SIZE (OMGT_OOB_SSL_DIR_SIZE + OMGT_OOB_SSL_FILENAME_SIZE) +/** + * @brief SSL configuration options and locations of files. + * + * A structure to contain the SSL parameters used during setup. An enable flag + * can be set to turn off SSL. + */ +struct omgt_ssl_params { + uint32_t enable; /* To enable/disable this feature */ + char directory[OMGT_OOB_SSL_DIR_SIZE]; /* Directory location of OpenSSL-related files */ + char certificate[OMGT_OOB_SSL_FILENAME_SIZE]; /* Certificate PEM file */ + char private_key[OMGT_OOB_SSL_FILENAME_SIZE]; /* Private key PEM file */ + char ca_certificate[OMGT_OOB_SSL_FILENAME_SIZE]; /* Certificate Authority (CA) certificate PEM file */ + uint32_t cert_chain_depth; /* Limit up to which depth certificates in a chain are used during the + * verification procedure. If the certificate chain is longer than + * allowed, the certificates above the limit are ignored. */ + char dh_params[OMGT_OOB_SSL_FILENAME_SIZE]; /* Diffie-Hellman parameters PEM file */ + uint32_t ca_crl_enable; /* To enable/disable the usage of the CRL PEM file */ + char ca_crl[OMGT_OOB_SSL_FILENAME_SIZE]; /* CA CRL PEM file */ +}; + +/** + * @brief OOB conection info + * + * A structure to contain all input parameters to connect to the FE through an + * out-of-band connection. + */ +struct omgt_oob_input { + char *host; /* ipv4, ipv6, or hostname */ + uint16_t port; /* TCP port of the FE */ + struct omgt_ssl_params ssl_params; /* SSL parameters */ + int is_esm_fe; /* is the FE an ESM */ +}; + + +/** + * @brief Open an in-band opamgt port using the name of the hfi device. + * + * This function will allocate and initilize a connection to the local HFI using + * the HFI device's name and port number. Additionally, per port object logging + * can be setup using session_params. + * + * @param port port object is allocated and returned + * @param hfi_name HFI device name (e.g. "hfi1_0") + * @param port_num port number of the hfi starting at 1 (0 is a + * wildcard meaning first active) + * @param session_params Optional advanced parameters to open port with (e.g. + * Logging streams). + * + * @return OMGT_STATUS_T + * + * @see omgt_params session_params + * @see omgt_close_port + */ +OMGT_STATUS_T omgt_open_port(struct omgt_port **port, char *hfi_name, uint8_t port_num, struct omgt_params *session_params); + +/** + * @brief Open an in-band opamgt port by HFI and port number + * + * This function will allocate and initilize a connection to the local HFI using + * the HFI device's number and port's number. Additionally, per port object + * logging can be setup using session_params. + * + * @param port port object is allocated and returned + * @param hfi_num HFI number based on the order of the cards starting + * at 1 (0 is a wildcard meaning first active) + * @param port_num port number of the hfi starting at 1 (0 is a + * wildcard meaning first active) + * @param session_params Optional advanced parameters to open port with (e.g. + * Logging streams). + * + * @return OMGT_STATUS_T + * + * @see omgt_params session_params + * @see omgt_close_port + */ +OMGT_STATUS_T omgt_open_port_by_num(struct omgt_port **port, int32_t hfi_num, uint8_t port_num, struct omgt_params *session_params); + +/** + * @brief Open an in-band opamgt port by port GUID + * + * This function will allocate and initilize a connection to the local HFI using + * the HFI device's Port GUID. Additionally, per port object logging can be + * setup using session_params. + * + * @param port port object is allocated and returned + * @param port_guid port GUID of the port + * @param session_params Optional advanced parameters to open port with (e.g. + * Logging streams). + * + * @return OMGT_STATUS_T + * + * @see omgt_params session_params + * @see omgt_close_port + */ +OMGT_STATUS_T omgt_open_port_by_guid(struct omgt_port **port, uint64_t port_guid, struct omgt_params *session_params); + +/** + * @brief Open a out-of-band opamgt port + * + * This function will allocate and initilize a connection to the FE through an + * out-of-band interface. Additionally, per port object logging can be setup + * using session_params. + * + * @param port port object is allocated and returned + * @param oob_input OOB conection info + * @param session_params Optional advanced parameters to open port with (e.g. + * Logging streams). + * + * @return OMGT_STATUS_T + * + * @see omgt_oob_input oob_input + * @see omgt_params session_params + * @see omgt_close_port + */ +OMGT_STATUS_T omgt_oob_connect(struct omgt_port **port, struct omgt_oob_input *oob_input, struct omgt_params *session_params); + +/** + * @brief Close and free port object + * + * This function will close, disconnect, and free any previously allocated and + * opened connections for both in-band and out-of-band port objects. + * + * @param port port object to close and free. + * + * @see omgt_open_port + * @see omgt_open_port_by_num + * @see omgt_open_port_by_guid + * @see omgt_oob_connect + */ +void omgt_close_port(struct omgt_port *port); + + +/** ============================================================================ + * omgt_port accessor functions for use while in either in-band or out-of-band + * mode + */ + +/** + * @brief Set debug logging output for an opamgt port + * + * Allows Dynamic modification of the debug log target file. Log Settings are + * initially configured during port open and can be changed at any time with + * this function. Target file can either be a standard linux flat FILE, NULL to + * disable, or OMGT_DBG_FILE_SYSLOG to send debug logging to syslog. + * + * @param port port instance to modify logging configuration + * @param file Target file for debug logging output + * + * @see omgt_params + */ +void omgt_set_dbg(struct omgt_port *port, FILE *file); + +/** + * @brief Set error logging output for an opamgt port + * + * Allows Dynamic modification of the error log target file. Log Settings are + * initially configured during port open and can be changed at any time with + * this function. Target file can either be a standard Linux flat FILE, NULL to + * disable, or OMGT_DBG_FILE_SYSLOG to send error logging to syslog. + * + * @param port port instance to modify logging configuration + * @param file Target file for error logging + * + * @see omgt_params + */ +void omgt_set_err(struct omgt_port *port, FILE *file); + +/** + * @brief Set query timeout for an opamgt port + * + * Allows Dynamic modification of the query timeout value. Timeout value is + * initially set to OMGT_DEF_TIMEOUT_MS during port open and can be changed + * at any time with this function. + * + * @param port port instance to modify configuration. + * @param ms_timeout timeout value in milliseconds (ms). An invalid timeout + * value will reset timeout to default. Default timeout is + * 1000 ms or 1 second. + * + * @see omgt_params + * @see OMGT_DEF_TIMEOUT_MS + */ +void omgt_set_timeout(struct omgt_port *port, int ms_timeout); + +/** + * @brief Set query retry count for an opamgt port + * + * Allows Dynamic modification of the query retry value. Retry value is + * initially set to OMGT_DEF_RETRY_CNT during port open and can be changed + * at any time with this function. + * + * @param port port instance to modify configuration. + * @param retry_count Number of times to retry query. An invalid retry count + * will reset to default. Default is 3. + * + * @see omgt_params + * @see OMGT_DEF_RETRY_CNT + */ +void omgt_set_retry_count(struct omgt_port *port, int retry_count); + +/** ============================================================================ + * omgt_port accessor functions for use while in in-band mode + * + * OMGT_STATUS_INVALID_STATE will be returned for calling this function on an + * out-of-band port + */ + +/** + * @brief Gets Port Prefix for the given port. + * Retrieves port prefix for an open in-band port. + * @param port previously initialized port object for an in-band + * connection + * @param prefix port prefix to be returned + * @return OMGT_STATUS_T + */ +OMGT_STATUS_T omgt_port_get_port_prefix(struct omgt_port *port, uint64_t *prefix); +/** + * @brief Gets Port GUID for the given port. + * Retrieves port GUID for an open in-band port. + * @param port previously initialized port object for an in-band + * connection + * @param port_guid port guid to be returned + * @return OMGT_STATUS_T + */ +OMGT_STATUS_T omgt_port_get_port_guid(struct omgt_port *port, uint64_t *port_guid); +/** + * @brief Gets Port's LID for the given port. + * Retrieves port's lid for an open in-band port. + * @param port previously initialized port object for an in-band + * connection + * @param port_lid lid to be returned + * @return OMGT_STATUS_T + */ +OMGT_STATUS_T omgt_port_get_port_lid(struct omgt_port *port, uint32_t *port_lid); +/** + * @brief Gets HFI's port number for the given port. + * Retrieves HFI's port number for an open in-band port. + * @param port previously initialized port object for an in-band + * connection + * @param port_num port number to be returned (indexed starting at 1) + * @return OMGT_STATUS_T + */ +OMGT_STATUS_T omgt_port_get_hfi_port_num(struct omgt_port *port, uint8_t *port_num); +/** + * @brief Gets HFI's number for the given port. + * Retrieves HFI's number for an open in-band port. + * @param port previously initialized port object for an in-band + * connection + * @param hfi_num hfi number to be returned (indexed starting at 1) + * @return OMGT_STATUS_T + */ +OMGT_STATUS_T omgt_port_get_hfi_num(struct omgt_port *port, int32_t *hfi_num); +/** + * @brief Gets Port's State for the given port. + * Retrieves Port's State for an open in-band port. + * @param port previously initialized port object for an in-band + * connection + * @param port_state Port state to be returned + * @return OMGT_STATUS_T + */ +OMGT_STATUS_T omgt_port_get_port_state(struct omgt_port *port, uint8_t *port_state); +/** + * @brief Gets HFI's Name for the given port. + * Retrieves HFI's Name for an open in-band port. + * @param port previously initialized port object for an in-band + * connection + * @param hfi_name buffer to be filled with HFI's name + * @return OMGT_STATUS_T + */ +OMGT_STATUS_T omgt_port_get_hfi_name(struct omgt_port *port, char hfi_name[IBV_SYSFS_NAME_MAX]); + + +/* OMGT Service State Values */ +#define OMGT_SERVICE_STATE_UNKNOWN 0 +#define OMGT_SERVICE_STATE_OPERATIONAL 1 +#define OMGT_SERVICE_STATE_DOWN (-1) +#define OMGT_SERVICE_STATE_UNAVAILABLE (-2) + +/* OMGT refresh values for how to get or update a service's state */ +#define OMGT_REFRESH_SERVICE_NOP 0x00000000 /* Do not refresh */ +#define OMGT_REFRESH_SERVICE_BAD_STATE 0x00000001 /* Only Refresh if state is not Operational */ +#define OMGT_REFRESH_SERVICE_ANY_STATE 0x00000002 /* Refresh on any state */ + +/** + * @brief Gets port's SA Service's State. + * + * Get the Port's SA Service State. If refresh is triggered, this function will + * send an SA ClassPortInfo query with a small timeout value to quickly check + * the responsiveness of the SA. This get function is an alternative way to + * initialize the port's SA Service State. The SA Service State is also updated + * or initialized before an SA query when the state is not operational. + * + * @param port previously initialized port object for an in-band + * connection + * @param sa_service_state SA Service State to be returned + * @param refresh value to possibly trigger a refresh + * @return OMGT_STATUS_T + */ +OMGT_STATUS_T omgt_port_get_sa_service_state(struct omgt_port *port, int *sa_service_state, uint32_t refresh); +/** + * @brief Gets port's PA Client State. + * + * Get the Port's PA Service State. If refresh is triggered, this function will + * attempt to find the PA's Service record using an SA query to quickly check + * the responsiveness and presence of the PA. An Additional SA Path Record query + * will be issued to determine how to route to the PA. This get function is an + * alternative way to initialize the port's PA Service State. The PA Service + * State is also updated or initialized before a PA query when the state is not + * operational. + * + * @param port previously initialized port object for an in-band + * connection + * @param pa_service_state PA Service State to be returned + * @param refresh value to possibly trigger a refresh + * + * @return OMGT_STATUS_T + */ +OMGT_STATUS_T omgt_port_get_pa_service_state(struct omgt_port *port, int *pa_service_state, uint32_t refresh); + +/** ============================================================================ + * omgt_port accessor functions for use while in out-of-band mode + * + * OMGT_STATUS_INVALID_STATE will be returned for calling this function on an + * in-band port + */ + +/** + * @brief Gets IP Version for the given port. + * Retrieves the IP version currently in use for the open out-of-band port. + * @param port previously initialized port object for an out-of-band + * connection + * @param ip_version version of the ip protocal currently in use. Possible + * output either 4 or 6 + * @return OMGT_STATUS_T + * @see omgt_port_get_ipv6_addr + * @see omgt_port_get_ipv4_addr + */ +OMGT_STATUS_T omgt_port_get_ip_version(struct omgt_port *port, uint8_t *ip_version); +/** + * @brief Gets IPv4 Address for the given port. + * Retrieves the IPv4 Address currently in use for the open out-of-band port. + * @param port previously initialized port object for an out-of-band + * connection + * @param ipv4_addr IPv4 address of the connection currently in use + * @return OMGT_STATUS_T + * @see omgt_port_get_ip_version + * @see omgt_port_get_ipv6_addr + */ +OMGT_STATUS_T omgt_port_get_ipv4_addr(struct omgt_port *port, struct in_addr *ipv4_addr); +/** + * @brief Gets IPv6 Address for the given port. + * Retrieves the IPv6 Address currently in use for the open out-of-band port. + * @param port previously initialized port object for an out-of-band + * connection + * @param ipv6_addr IPv6 address of the connection currently in use + * @return OMGT_STATUS_T + * @see omgt_port_get_ip_version + * @see omgt_port_get_ipv4_addr + */ +OMGT_STATUS_T omgt_port_get_ipv6_addr(struct omgt_port *port, struct in6_addr *ipv6_addr); +/** + * @brief Gets IP Address for the given port in text. + * Retrieves the IP Address currently in use for the open out-of-band port and + * returns it in text format in a text buffer. + * @param port previously initialized port object for an out-of-band + * connection + * @param buf buffer to store the ip address of the connection + * currently in use + * @param buf_len size of the buffer + * @return OMGT_STATUS_T + * @see omgt_port_get_ip_version + * @see omgt_port_get_ipv4_addr + * @see omgt_port_get_ipv6_addr + */ +OMGT_STATUS_T omgt_port_get_ip_addr_text(struct omgt_port *port, char buf[], size_t buf_len); + + +/** ============================================================================ + * general functions that do not require an omgt_port + */ + +/** + * @brief Gets an array of all HFI names available on system + * + * This function preforms the same as umad_get_cas_names(), but is restricted to + * OPA ports only. HFIs will be in HFI num order. + * + * @param hfis Pointer to array of size char [max][UMAD_CA_NAME_LEN] + * @param max Maximum number of names to return + * @param hfi_count The number of valid entries in hfis + * + * @see umad_get_cas_names + */ +OMGT_STATUS_T omgt_get_hfi_names(char hfis[][UMAD_CA_NAME_LEN], int32_t max, int32_t *hfi_count); + +/** + * @brief Converts the service state to text + * + * @param service_state value to convert to text + * + * @return const char* + */ +const char* omgt_service_state_totext(int service_state); +/** + * @brief Converts the status value to text + * + * @param status OMGT_STATUS_T value to convert to text + * + * @return const char* + */ +const char* omgt_status_totext(OMGT_STATUS_T status); +#ifdef __cplusplus +} +#endif + +#endif /* __OPAMGT_H__ */ diff --git a/opamgt/include/public/opamgt_pa.h b/opamgt/include/public/opamgt_pa.h new file mode 100644 index 0000000..bca10d4 --- /dev/null +++ b/opamgt/include/public/opamgt_pa.h @@ -0,0 +1,747 @@ +/* BEGIN_ICS_COPYRIGHT2 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT2 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +#ifndef __OPAMGT_PA_H__ +#define __OPAMGT_PA_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +//opamgt includes +#include +#include "opamgt.h" + + +/** + * @brief Get PM configuration data + * + * @param port Port to operate on. + * @param pm_config Pointer to PM config data to fill + * + * @return + * OMGT_STATUS_SUCCESS - Get successful + * OMGT_STATUS_ERROR - Error + */ +OMGT_STATUS_T +omgt_pa_get_pm_config( + struct omgt_port *port, + STL_PA_PM_CFG_DATA *pm_config + ); + +/** + * @brief Get image info + * + * @param port Port to operate on. + * @param pm_image_Id Image ID of image info to get + * @param pm_image_info Pointer to image info to fill + * + * @return + * OMGT_STATUS_SUCCESS - Get successful + * OMGT_STATUS_ERROR - Error + */ +OMGT_STATUS_T +omgt_pa_get_image_info( + struct omgt_port *port, + STL_PA_IMAGE_ID_DATA pm_image_id, + STL_PA_IMAGE_INFO_DATA *pm_image_info + ); + +/** + * @brief Get list of group names from the current (live) image + * + * @deprecated This function is deprecated and will be removed in a future release. + * @see omgt_pa_get_group_list2 + * + * @param port Port to operate on. + * @param pm_group_list Pointer to group list to fill + * + * @return + * OMGT_STATUS_SUCCESS - Get successful + * OMGT_STATUS_ERROR - Error + */ +OMGT_STATUS_T +omgt_pa_get_group_list( + struct omgt_port *port, + uint32_t *pNum_Groups, + STL_PA_GROUP_LIST **pm_group_list + ); + +/** + * @brief Release group list + * + * @param pm_group_list Pointer to pointer to the group list to free. + * + * @return + * None + */ +void +omgt_pa_release_group_list( + STL_PA_GROUP_LIST **pm_group_list + ); + +/** + * @brief Get list of group names from any image + * + * @param port Port to operate on. + * @param pm_image_id_query ImageID to request + * @oaram pNum_Groups Pointer to Number of records + * @param pm_group_list Pointer to group list to fill + * + * @return + * OMGT_STATUS_SUCCESS - Get successful + * OMGT_STATUS_ERROR - Error + */ +OMGT_STATUS_T +omgt_pa_get_group_list2( + struct omgt_port *port, + STL_PA_IMAGE_ID_DATA pm_image_id_query, + uint32_t *pNum_Groups, + STL_PA_GROUP_LIST2 **pm_group_list + ); + +/** + * @brief Release group list2 + * + * @param pm_group_list Pointer to pointer to the group list2 to free. + * + * @return + * None + */ +void +omgt_pa_release_group_list2( + STL_PA_GROUP_LIST2 **pm_group_list + ); + +/** + * @brief Get list of vf names from the current (live) image + * + * @deprecated This function is deprecated and will be removed in a future release. + * @see omgt_pa_get_vf_list2 + * + * @param port Port to operate on. + * @param pm_vf_list Pointer to vf list to fill + * + * @return + * OMGT_STATUS_SUCCESS - Get successful + * OMGT_STATUS_ERROR - Error + */ +OMGT_STATUS_T +omgt_pa_get_vf_list( + struct omgt_port *port, + uint32_t *pNum_VFs, + STL_PA_VF_LIST **pm_vf_list + ); + +/** + * @brief Release vf list + * + * @param pm_vf_list Pointer to pointer to the vf list to free. + * + * @return + * None + */ +void +omgt_pa_release_vf_list( + STL_PA_VF_LIST **pm_vf_list + ); + +/** + * @brief Get list of vf names from any image + * + * @param port Port to operate on. + * @param pm_image_id_query ImageId + * @param pNum_VFs Pointer to Number of records + * @param pm_vf_list Pointer to vf list to fill + * + * @return + * OMGT_STATUS_SUCCESS - Get successful + * OMGT_STATUS_ERROR - Error + */ +OMGT_STATUS_T +omgt_pa_get_vf_list2( + struct omgt_port *port, + STL_PA_IMAGE_ID_DATA pm_image_id_query, + uint32_t *pNum_VFs, + STL_PA_VF_LIST2 **pm_vf_list + ); + +/** + * @brief Release vf list2 + * + * @param pm_vf_list Pointer to pointer to the vf list2 to free. + * + * @return + * None + */ +void +omgt_pa_release_vf_list2( + STL_PA_VF_LIST2 **pm_vf_list + ); + +/** + * @brief Get group info + * + * @param port Port to operate on. + * @param pm_image_id_query Image ID of group info to get. + * @param group_name Pointer to group name + * @param pm_image_id_resp Pointer to image ID of group info returned. + * @param pm_group_info Pointer to group info to fill. + * + * @return + * OMGT_STATUS_SUCCESS - Get successful + * OMGT_STATUS_ERROR - Error + */ +OMGT_STATUS_T +omgt_pa_get_group_info( + struct omgt_port *port, + STL_PA_IMAGE_ID_DATA pm_image_id_query, + char *group_name, + STL_PA_IMAGE_ID_DATA *pm_image_id_resp, + STL_PA_PM_GROUP_INFO_DATA *pm_group_info + ); + +/** + * @brief Get vf info + * + * @param port Port to operate on. + * @param pm_image_id_query Image ID of vf info to get. + * @param vf_name Pointer to vf name + * @param pm_image_id_resp Pointer to image ID of vf info returned. + * @param pm_vf_info Pointer to vf info to fill. + * + * @return + * OMGT_STATUS_SUCCESS - Get successful + * OMGT_STATUS_ERROR - Error + */ +OMGT_STATUS_T +omgt_pa_get_vf_info( + struct omgt_port *port, + STL_PA_IMAGE_ID_DATA pm_image_id_query, + char *vf_name, + STL_PA_IMAGE_ID_DATA *pm_image_id_resp, + STL_PA_VF_INFO_DATA *pm_vf_info + ); + +/** + * @brief Get group config info + * + * @param port Port to operate on. + * @param pm_image_id_query Image ID of group config to get. + * @param group_name Pointer to group name + * @param pm_image_id_resp Pointer to image ID of group info returned. + * @param pm_group_config Pointer to group config to fill. Upon successful return, a memory to + * contain the group config is allocated. The caller must call + * omgt_pa_release_group_config to free the memory later. + * + * @return + * OMGT_STATUS_SUCCESS - Get successful + * OMGT_STATUS_ERROR - Error + */ +OMGT_STATUS_T +omgt_pa_get_group_config( + struct omgt_port *port, + STL_PA_IMAGE_ID_DATA pm_image_id_query, + char *group_name, + STL_PA_IMAGE_ID_DATA *pm_image_id_resp, + uint32_t *pNum_ports, + STL_PA_PM_GROUP_CFG_RSP * *pm_group_config + ); + +/** + * @brief Release group config info + * + * @param pm_group_config Pointer to pointer to the group config to free. + * + * @return + * None + */ +void +omgt_pa_release_group_config( + STL_PA_PM_GROUP_CFG_RSP **pm_group_config + ); + +/** + * Get group node info + * + * @param port Port to operate on. + * @param pm_image_id_query Image ID of group config to get. + * @param group_name Pointer to group name + * @param nodeLid node LID + * @param nodeGuid node GUID + * @param nodeDesc node Description + * @param pm_image_id_resp Pointer to image ID of group info returned. + * @param pm_group_config Pointer to group config to fill. Upon successful return, a memory to + * contain the group config is allocated. The caller must call + * omgt_pa_release_group_config to free the memory later. + * + * @return + * OMGT_STATUS_SUCCESS - Get successful + * OMGT_STATUS_ERROR - Error + */ +OMGT_STATUS_T +omgt_pa_get_group_nodeinfo( + struct omgt_port *port, + STL_PA_IMAGE_ID_DATA pm_image_id_query, + char *group_name, + STL_LID nodeLid, + uint64 nodeGuid, + char *nodeDesc, + STL_PA_IMAGE_ID_DATA *pm_image_id_resp, + uint32 *pNum_nodes, + STL_PA_GROUP_NODEINFO_RSP **pm_group_nodeinfo + ); + +/** + * Release group node info + * + * @param pm_group_nodeinfo Pointer to pointer to the group nodeinfo to free. + * + * @return + * None + */ +void +omgt_pa_release_group_nodeinfo( + STL_PA_GROUP_NODEINFO_RSP **pm_group_nodeinfo + ); + +/** + * Get group link info + * + * @param port Port to operate on. + * @param pm_image_id_query Image ID of group config to get. + * @param group_name Pointer to group name + * @param inputLid input LID + * @param inputPort input Port + * @param pm_image_id_resp Pointer to image ID of group info returned. + * @param pm_group_config Pointer to group config to fill. Upon successful return, a memory to + * contain the group config is allocated. The caller must call + * omgt_pa_release_group_config to free the memory later. + * + * @return + * OMGT_STATUS_SUCCESS - Get successful + * OMGT_STATUS_ERROR - Error + */ +OMGT_STATUS_T +omgt_pa_get_group_linkinfo( + struct omgt_port *port, + STL_PA_IMAGE_ID_DATA pm_image_id_query, + char *group_name, + STL_LID inputLid, + uint8 inputPort, + STL_PA_IMAGE_ID_DATA *pm_image_id_resp, + uint32 *pNum_links, + STL_PA_GROUP_LINKINFO_RSP **pm_group_linkinfo + ); + +/** + * Release group link info + * + * @param port Port to operate on. + * @param pm_group_nodeinfo Pointer to pointer to the group nodeinfo to free. + * + * @return + * None + */ +void +omgt_pa_release_group_linkinfo( + STL_PA_GROUP_LINKINFO_RSP **pm_group_linkinfo + ); + +/* @brief Get VF config info + * + * @param port Port to operate on + * @param pm_image_id_query Image ID of VF config to get. + * @param vf_name Pointer to VF name. + * @param pm_image_id_resp Pointer to image ID of VF info returned. + * @param pm_vf_config Pointer to VF config to fill. Upon successful return, a memory to + * contain the VF config is allocated. The caller must call + * omgt_pa_release_vf_config to free the memory later. + * + * @return + * OMGT_STATUS_SUCCESS - Get successful + * OMGT_STATUS_ERROR - Error + */ +OMGT_STATUS_T +omgt_pa_get_vf_config( + struct omgt_port *port, + STL_PA_IMAGE_ID_DATA pm_image_id_query, + char *vf_name, + STL_PA_IMAGE_ID_DATA *pm_image_id_resp, + uint32_t *pNum_ports, + STL_PA_VF_CFG_RSP **pm_vf_config + ); + +/* @brief Release VF config info + * + * @param pm_vf_config Pointer to pointer to the VF config to free + * + * @return + * None + */ +void +omgt_pa_release_vf_config( + STL_PA_VF_CFG_RSP **pm_vf_config + ); + +/** + * @brief Get group focus portlist + * + * @param port Port to operate on. + * @param pm_image_id_query Image ID of group focus portlist to get. + * @param group_name Pointer to group name. + * @param select Select value for focus portlist. + * @param start Start index value of portlist + * @param range Index range of portlist. + * @param pm_image_id_resp Pointer to image ID of group focus portlist returned. + * @param pm_group_focus Pointer to pointer to focus portlist to fill. Upon + * successful return, a memory to contain the group focus + * portlist is allocated. The caller must call + * omgt_pa_release_group_focus to free the memory later. + * + * @return + * OMGT_STATUS_SUCCESS - Get successful + * OMGT_STATUS_ERROR - Error + */ + +OMGT_STATUS_T +omgt_pa_get_group_focus( + struct omgt_port *port, + STL_PA_IMAGE_ID_DATA pm_image_id_query, + char *group_name, + uint32_t select, + uint32_t start, + uint32_t range, + STL_PA_IMAGE_ID_DATA *pm_image_id_resp, + uint32_t *pNum_ports, + STL_FOCUS_PORTS_RSP **pm_group_focus + ); + +/** + * @brief Release group focus portlist + * + * @param pm_group_config Pointer to pointer to the group focus portlist to free. + * + * @return + * None + */ +void +omgt_pa_release_group_focus( + STL_FOCUS_PORTS_RSP **pm_group_focus + ); + +/* + * @brief Get VF focus portlist + * + * @param port Port to operate on. + * @param pm_image_id_query Image ID of vf focus portlist to get. + * @param vf_name Pointer to vf name. + * @param select Select value for focus portlist. + * @param start Start index value of portlist + * @param range Index range of portlist. + * @param pm_image_id_resp Pointer to image ID of group focus portlist returned. + * @param pm_vf_focus Pointer to pointer to focus portlist to fill. Upon + * successful return, a memory to contain the group focus + * portlist is allocated. The caller must call + * omgt_pa_release_vf_focus to free the memory later. + * + * @return + * OMGT_STATUS_SUCCESS - Get successful + * OMGT_STATUS_ERROR - Error + */ + +OMGT_STATUS_T +omgt_pa_get_vf_focus( + struct omgt_port *port, + STL_PA_IMAGE_ID_DATA pm_image_id_query, + char *vf_name, + uint32_t select, + uint32_t start, + uint32_t range, + STL_PA_IMAGE_ID_DATA *pm_image_id_resp, + uint32_t *pNum_ports, + STL_PA_VF_FOCUS_PORTS_RSP **pm_vf_focus + ); + + +/* + * @brief Release vf focus portlist + * + * @param pm_vf_config Pointer to pointer to the vf focus portlist to free. + * + * @return + * None + */ +void +omgt_pa_release_vf_focus( + STL_PA_VF_FOCUS_PORTS_RSP **pm_group_focus + ); + +/** + * @brief Get port statistics (counters). Supports 32 bit LIDs + * + * @param port Port to operate on. + * @param pm_image_id_query Image ID of port counters to get. + * @param lid LID of node. + * @param port_num Port number. + * @param pm_image_id_resp Pointer to image ID of port counters returned. + * @param port_counters Pointer to port counters to fill. + * @param flags Pointer to flags + * @param delta 1 for delta counters, 0 for raw image counters. + * @param user_cntrs 1 for running counters, 0 for image counters. (delta must be 0) + * + * @return + * OMGT_STATUS_SUCCESS - Get successful + * OMGT_STATUS_ERROR - Error + */ +OMGT_STATUS_T +omgt_pa_get_port_stats2( + struct omgt_port *port, + STL_PA_IMAGE_ID_DATA pm_image_id_query, + STL_LID lid, + uint8_t port_num, + STL_PA_IMAGE_ID_DATA *pm_image_id_resp, + STL_PORT_COUNTERS_DATA *port_counters, + uint32_t *flags, + uint32_t delta, + uint32_t user_cntrs + ); + + + +/** + * @brief Get vf port statistics (counters). Supports 32 bit LIDs + * + * @param port Port to operate on. + * @param pm_image_id_query Image ID of port counters to get. + * @param vf_name Pointer to VF name. + * @param lid LID of node. + * @param port_num Port number. + * @param pm_image_id_resp Pointer to image ID of port counters returned. + * @param vf_port_counters Pointer to vf port counters to fill. + * @param flags Pointer to flags + * @param delta 1 for delta counters, 0 for raw image counters. + * @param user_cntrs 1 for running counters, 0 for image counters. (delta must be 0) + * + * @return + * OMGT_STATUS_SUCCESS - Get successful + * OMGT_STATUS_ERROR - Error + */ +OMGT_STATUS_T +omgt_pa_get_vf_port_stats2( + struct omgt_port *port, + STL_PA_IMAGE_ID_DATA pm_image_id_query, + char *vf_name, + STL_LID lid, + uint8_t port_num, + STL_PA_IMAGE_ID_DATA *pm_image_id_resp, + STL_PA_VF_PORT_COUNTERS_DATA *vf_port_counters, + uint32_t *flags, + uint32_t delta, + uint32_t user_cntrs + ); + + +/** + * @brief Get port statistics (counters). + * + * @deprecated This function is deprecated and will be removed in a future release. + * @see omgt_pa_get_port_stats2 + * + * @param port Port to operate on. + * @param pm_image_id_query Image ID of port counters to get. + * @param lid LID of node. + * @param port_num Port number. + * @param pm_image_id_resp Pointer to image ID of port counters returned. + * @param port_counters Pointer to port counters to fill. + * @param flags Pointer to flags + * @param delta 1 for delta counters, 0 for raw image counters. + * @param user_cntrs 1 for running counters, 0 for image counters. (delta must be 0) + * + * @return + * OMGT_STATUS_SUCCESS - Get successful + * OMGT_STATUS_ERROR - Error + */ +OMGT_STATUS_T +omgt_pa_get_port_stats( + struct omgt_port *port, + STL_PA_IMAGE_ID_DATA pm_image_id_query, + uint16_t lid, + uint8_t port_num, + STL_PA_IMAGE_ID_DATA *pm_image_id_resp, + STL_PORT_COUNTERS_DATA *port_counters, + uint32_t *flags, + uint32_t delta, + uint32_t user_cntrs + ) __attribute__ ((deprecated)); + + + +/** + * @brief Get vf port statistics (counters) + * + * @deprecated This function is deprecated and will be removed in a future release. + * @see omgt_pa_get_vf_port_stats2 + * + * @param port Port to operate on. + * @param pm_image_id_query Image ID of port counters to get. + * @param vf_name Pointer to VF name. + * @param lid LID of node. + * @param port_num Port number. + * @param pm_image_id_resp Pointer to image ID of port counters returned. + * @param vf_port_counters Pointer to vf port counters to fill. + * @param flags Pointer to flags + * @param delta 1 for delta counters, 0 for raw image counters. + * @param user_cntrs 1 for running counters, 0 for image counters. (delta must be 0) + * + * @return + * OMGT_STATUS_SUCCESS - Get successful + * OMGT_STATUS_ERROR - Error + */ +OMGT_STATUS_T +omgt_pa_get_vf_port_stats( + struct omgt_port *port, + STL_PA_IMAGE_ID_DATA pm_image_id_query, + char *vf_name, + uint16_t lid, + uint8_t port_num, + STL_PA_IMAGE_ID_DATA *pm_image_id_resp, + STL_PA_VF_PORT_COUNTERS_DATA *vf_port_counters, + uint32_t *flags, + uint32_t delta, + uint32_t user_cntrs + ) __attribute__ ((deprecated)); + +/** + * @brief Freeze specified image + * + * @param port Port to operate on. + * @param pm_image_id_query Image ID of image to freeze. + * @param pm_image_id_resp Pointer to image ID of image frozen. + * + * @return + * OMGT_STATUS_SUCCESS - Freeze successful + * OMGT_STATUS_ERROR - Error + */ +OMGT_STATUS_T +omgt_pa_freeze_image( + struct omgt_port *port, + STL_PA_IMAGE_ID_DATA pm_image_id_query, + STL_PA_IMAGE_ID_DATA *pm_image_id_resp + ); + +/** + * @brief Move freeze of image 1 to image 2 + * + * @param port Port to operate on. + * @param pm_image_id_query Image ID of frozen image 1. + * @param pm_image_id_resp Pointer to image ID of image2. + * + * @return + * OMGT_STATUS_SUCCESS - Move image Freeze successful + * OMGT_STATUS_UNAVAILABLE - Image 2 unavailable freeze + * OMGT_STATUS_ERROR - Error + */ +OMGT_STATUS_T +omgt_pa_move_image_freeze( + struct omgt_port *port, + STL_PA_IMAGE_ID_DATA pm_image_id1, + STL_PA_IMAGE_ID_DATA *pm_image_Id2 + ); + +/** + * @brief Release specified image. + * + * @param port Port to operate on. + * @param pm_image_id_query Image ID of image to release. + * + * @return + * OMGT_STATUS_SUCCESS - Release successful + * OMGT_STATUS_ERROR - Error + */ +OMGT_STATUS_T +omgt_pa_release_image( + struct omgt_port *port, + STL_PA_IMAGE_ID_DATA pm_image_id_query + ); + +/** + * @brief Renew lease of specified image. + * + * @param port Port to operate on. + * @param pm_image_id_query Image ID of image to renew. + * + * @return + * OMGT_STATUS_SUCCESS - Renew successful + * OMGT_STATUS_ERROR - Error + */ +OMGT_STATUS_T +omgt_pa_renew_image( + struct omgt_port *port, + STL_PA_IMAGE_ID_DATA pm_image_id_query + ); + + +/** + * @brief Get the classportinfo from the given port. + * + * @param port Local port to operate on. + * @param cpi A pointer to the ClassPortInfo. The caller must free it after use. + * + * @return + * OMGT_STATUS_SUCCESS - Renew successful + * OMGT_STATUS_ERROR - Error + */ +OMGT_STATUS_T +omgt_pa_get_classportinfo( + struct omgt_port *port, + STL_CLASS_PORT_INFO **cpi + ); + + +/* + * @brief Get MAD status code from most recent PA operation + * + * @param port Local port to operate on. + * + * @return + * The corresponding status code. + */ +uint16_t +omgt_get_pa_mad_status( + struct omgt_port *port + ); + +#ifdef __cplusplus +} +#endif + +#endif /* __OPAMGT_PA_H__ */ diff --git a/opamgt/include/public/opamgt_sa.h b/opamgt/include/public/opamgt_sa.h new file mode 100644 index 0000000..22f6edd --- /dev/null +++ b/opamgt/include/public/opamgt_sa.h @@ -0,0 +1,1021 @@ +/* BEGIN_ICS_COPYRIGHT2 **************************************** + +Copyright (c) 2015-2018, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT2 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +#ifndef __OPAMGT_SA_H__ +#define __OPAMGT_SA_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +//opamgt includes +#include "opamgt.h" +#include + +typedef struct omgt_sa_selector { + QUERY_INPUT_TYPE InputType; /* Type of input (i.e. query based on) */ + OMGT_QUERY_INPUT_VALUE InputValue; /* input record selection value input query */ +} omgt_sa_selector_t; + +/* + * @brief Get MAD status code from most recent SA operation + * + * @param port Local port to operate on. + * + * @return + * The corresponding status code. + */ +uint16_t +omgt_get_sa_mad_status(struct omgt_port *port); + + +/** + * @brief Free memory associated with an SA query result + * + * @param record pointer to records returned from omgt_sa_get_* call + * + */ +void +omgt_sa_free_records(void *record); + +/** + * @brief Query SA for Node Records + * + * @param port port opened by omgt_open_port_* + * @param selector Criteria to select records. + * Valid InputType values: + * NoInput, Lid, PortGuid, NodeGuid, SystemImageGuid, + * NodeType, NodeDesc + * (e.g. InputTypeNoInput) + * @param num_records Output: The number of records returned in query + * @param records Output: Pointer to records. + * Must be freed by calling omgt_sa_free_records + * + *@return OMGT_STATUS_SUCCESS if success, else error code + */ + +OMGT_STATUS_T +omgt_sa_get_node_records( + struct omgt_port *port, + omgt_sa_selector_t *selector, + int32_t *num_records, + STL_NODE_RECORD **records + ); +/** + * @brief Query SA for PortInfo Records + * + * @param port port opened by omgt_open_port_* + * @param selector Criteria to select records. + * Valid InputType values: + * NoInput, Lid + * @param num_records Output: The number of records returned in query + * @param records Output: Pointer to records. + * Must be freed by calling omgt_sa_free_records + * + *@return OMGT_STATUS_SUCCESS if success, else error code + */ + +OMGT_STATUS_T +omgt_sa_get_portinfo_records( + struct omgt_port *port, + omgt_sa_selector_t *selector, + int32_t *num_records, + STL_PORTINFO_RECORD **records + ); + + +/** + * @brief Query SA for System Image GUIDs + * + * @param port port opened by omgt_open_port_* + * @param selector Criteria to select GUIDs. Valid InputType values: + * NoInput, NodeType, SystemImageGuid, NodeGuid, + * PortGuid, Lid, NodeDesc + * @param num_records Output: The number of GUIDs returned in query + * @param guids Output: Pointer to array of GUIDs + * Must be freed by calling omgt_sa_free_records + * + *@return OMGT_STATUS_SUCCESS if success, else error code + */ + +OMGT_STATUS_T +omgt_sa_get_sysimageguid_records( + struct omgt_port *port, + omgt_sa_selector_t *selector, + int32_t *num_records, + uint64_t **guids + ); + +/** + * @brief Query SA for Node GUIDs + * + * @param port port opened by omgt_open_port_* + * @param selector Criteria to select GUIDs. Valid InputType values: + * NoInput, NodeType, SystemImageGuid, NodeGuid, + * PortGuid, Lid, NodeDesc + * @param num_records Output: The number of GUIDs returned in query + * @param guids Output: Pointer to array of GUIDs + * Must be freed by calling omgt_sa_free_records + * + *@return OMGT_STATUS_SUCCESS if success, else error code + */ + +OMGT_STATUS_T +omgt_sa_get_nodeguid_records( + struct omgt_port *port, + omgt_sa_selector_t *selector, + int32_t *num_records, + uint64_t **guids + ); + +/** + * @brief Query SA for Port GUIDs + * + * @param port port opened by omgt_open_port_* + * @param selector Criteria to select GUIDs. Valid InputType values: + * NoInput, NodeType, SystemImageGuid, NodeGuid, + * PortGuid, Lid, NodeDesc + * @param num_records Output: The number of GUIDs returned in query + * @param guids Output: Pointer to array of GUIDs + * Must be freed by calling omgt_sa_free_records + * + *@return OMGT_STATUS_SUCCESS if success, else error code + */ + +OMGT_STATUS_T +omgt_sa_get_portguid_records( + struct omgt_port *port, + omgt_sa_selector_t *selector, + int32_t *num_records, + uint64_t **guids + ); + +/** + * @brief Query SA for ClassPortInfo Records + * + * @param port port opened by omgt_open_port_* + * @param selector Criteria to select records. + * Valid InputType values: + * NoInput + * @param num_records Output: The number of records returned in query + * Will either be 0 or 1 + * @param records Output: Pointer to records. + * Must be freed by calling omgt_sa_free_records + * + *@return OMGT_STATUS_SUCCESS if success, else error code + */ +OMGT_STATUS_T +omgt_sa_get_classportinfo_records( + struct omgt_port *port, + omgt_sa_selector_t *selector, + int32_t *num_records, + STL_CLASS_PORT_INFO **records + ); + + +/** + * @brief Query SA for Lid Records + * + * @param port port opened by omgt_open_port_* + * @param selector Criteria to select records. + * Valid InputType values: + * NoInput, NodeType, SystemImageGuid, NodeGuid, + * PortGuid, Lid, NodeDesc + * @param num_records Output: The number of records returned in query + * @param lids Output: Pointer to lids. + * Must be freed by calling omgt_sa_free_records + * + *@return OMGT_STATUS_SUCCESS if success, else error code + */ +OMGT_STATUS_T +omgt_sa_get_lid_records( + struct omgt_port *port, + omgt_sa_selector_t *selector, + int32_t *num_records, + uint32 **lids + ); + + +/** + * @brief Query SA for Node Description Records + * + * @param port port opened by omgt_open_port_* + * @param selector Criteria to select records. + * Valid InputType values: + * NoInput, NodeType, SystemImageGuid, NodeGuid, + * PortGuid, Lid, NodeDesc + * @param num_records Output: The number of records returned in query + * @param records Output: Pointer to records. + * Must be freed by calling omgt_sa_free_records + * + *@return OMGT_STATUS_SUCCESS if success, else error code + */ +OMGT_STATUS_T +omgt_sa_get_nodedesc_records( + struct omgt_port *port, + omgt_sa_selector_t *selector, + int32_t *num_records, + STL_NODE_DESCRIPTION **records + ); + + + +/** + * @brief Query SA for IB Path Records + * + * @param port port opened by omgt_open_port_* + * @param selector Criteria to select records. + * Valid InputType values: + * NoInput, PortGuid, PortGid, PortGuidPair, GidPair, + * PathRecord, Lid, PKey, SL, ServiceId + * @note + * A sourcegid is always required with this query + * + * @param num_records Output: The number of records returned in query + * @param records Output: Pointer to records. + * Must be freed by calling omgt_sa_free_records + * + *@return OMGT_STATUS_SUCCESS if success, else error code + */ +OMGT_STATUS_T +omgt_sa_get_ib_path_records( + struct omgt_port *port, + omgt_sa_selector_t *selector, + int32_t *num_records, + IB_PATH_RECORD **records + ); + + +/** +* @brief Query SA for SM Info Records +* +* @param port port opened by omgt_open_port_* +* @param selector Criteria to select records. +* Valid Input Types: +* NoInput +* @param num_records Output: The number of records returned in query +* @param records Output: Pointer to records. +* Must be freed by calling omgt_sa_free_records +* +*@return OMGT_STATUS_SUCCESS if success, else error code +*/ +OMGT_STATUS_T +omgt_sa_get_sminfo_records( + struct omgt_port *port, + omgt_sa_selector_t *selector, + int32_t *num_records, + STL_SMINFO_RECORD **records + ); + + +/** + * @brief Query SA for Link Records + * + * @param port port opened by omgt_open_port_* + * @param selector Criteria to select records. + * Valid InputType values: + * NoInput, Lid + * @param num_records Output: The number of records returned in query + * @param records Output: Pointer to records. + * Must be freed by calling omgt_sa_free_records + * + *@return OMGT_STATUS_SUCCESS if success, else error code + */ +OMGT_STATUS_T +omgt_sa_get_link_records( + struct omgt_port *port, + omgt_sa_selector_t *selector, + int32_t *num_records, + STL_LINK_RECORD **records + ); + + +/** + * @brief Query SA for Service Records + * + * @param port port opened by omgt_open_port_* + * @param selector Criteria to select records. + * Valid InputType values: + * NoInput, PortGid + * @param num_records Output: The number of records returned in query + * @param records Output: Pointer to records. + * Must be freed by calling omgt_sa_free_records + * + *@return OMGT_STATUS_SUCCESS if success, else error code + */ +OMGT_STATUS_T +omgt_sa_get_service_records( + struct omgt_port *port, + omgt_sa_selector_t *selector, + int32_t *num_records, + IB_SERVICE_RECORD **records + ); + + +/** + * @brief Query SA for Multicast Member Records + * + * @param port port opened by omgt_open_port_* + * @param selector Criteria to select records. + * Valid InputType values: + * NoInput, PortGid, McGid, Lid, PKey + * @param num_records Output: The number of records returned in query + * @param records Output: Pointer to records. + * Must be freed by calling omgt_sa_free_records + * + *@return OMGT_STATUS_SUCCESS if success, else error code + */ +OMGT_STATUS_T +omgt_sa_get_ib_mcmember_records( + struct omgt_port *port, + omgt_sa_selector_t *selector, + int32_t *num_records, + IB_MCMEMBER_RECORD **records + ); + + +/** + * @brief Query SA for Inform Info Records + * + * @param port port opened by omgt_open_port_* + * @param selector Criteria to select records. + * Valid InputType values: + * NoInput, PortGid + * @param num_records Output: The number of records returned in query + * @param records Output: Pointer to records. + * Must be freed by calling omgt_sa_free_records + * + *@return OMGT_STATUS_SUCCESS if success, else error code + */ +OMGT_STATUS_T +omgt_sa_get_informinfo_records( + struct omgt_port *port, + omgt_sa_selector_t *selector, + int32_t *num_records, + STL_INFORM_INFO_RECORD **records + ); + +/** + * @brief Query SA for Trace Records + * + * @param port port opened by omgt_open_port_* + * @param selector Criteria to select records. + * Valid InputType values: + * PathRecord, PortGuid, GidPair, PortGid + * @note + * A sourcegid is always required with this query + * + * @param num_records Output: The number of records returned in query + * @param records Output: Pointer to records. + * Must be freed by calling omgt_sa_free_records + * + *@return OMGT_STATUS_SUCCESS if success, else error code + */ +OMGT_STATUS_T +omgt_sa_get_trace_records( + struct omgt_port *port, + omgt_sa_selector_t *selector, + int32_t *num_records, + STL_TRACE_RECORD **records + ); + +/** + * @brief Query SA for SCSC Table Records + * + * @param port port opened by omgt_open_port_* + * @param selector Criteria to select records. + * Valid InputType values: + * NoInput, Lid + * @param num_records Output: The number of records returned in query + * @param records Output: Pointer to records. + * Must be freed by calling omgt_sa_free_records + * + *@return OMGT_STATUS_SUCCESS if success, else error code + */ +OMGT_STATUS_T +omgt_sa_get_scsc_table_records( + struct omgt_port *port, + omgt_sa_selector_t *selector, + int32_t *num_records, + STL_SC_MAPPING_TABLE_RECORD **records + ); + + +/** + * @brief Query SA for SLSC Table Records + * + * @param port port opened by omgt_open_port_* + * @param selector Criteria to select records. + * Valid InputType values: + * NoInput, Lid + * @param num_records Output: The number of records returned in query + * @param records Output: Pointer to records. + * Must be freed by calling omgt_sa_free_records + * + *@return OMGT_STATUS_SUCCESS if success, else error code + */ +OMGT_STATUS_T +omgt_sa_get_slsc_table_records( + struct omgt_port *port, + omgt_sa_selector_t *selector, + int32_t *num_records, + STL_SL2SC_MAPPING_TABLE_RECORD **records + ); + + +/** + * @brief Query SA for SCSL Table Records + * + * @param port port opened by omgt_open_port_* + * @param selector Criteria to select records. + * Valid InputType values: + * NoInput, Lid + * @param num_records Output: The number of records returned in query + * @param records Output: Pointer to records. + * Must be freed by calling omgt_sa_free_records + * + *@return OMGT_STATUS_SUCCESS if success, else error code + */ +OMGT_STATUS_T +omgt_sa_get_scsl_table_records( + struct omgt_port *port, + omgt_sa_selector_t *selector, + int32_t *num_records, + STL_SC2SL_MAPPING_TABLE_RECORD **records + ); + + +/** + * @brief Query SA for SCVLt Table Records + * + * @param port port opened by omgt_open_port_* + * @param selector Criteria to select records. + * Valid InputType values: + * NoInput, Lid + * @param num_records Output: The number of records returned in query + * @param records Output: Pointer to records. + * Must be freed by calling omgt_sa_free_records + * + *@return OMGT_STATUS_SUCCESS if success, else error code + */ +OMGT_STATUS_T +omgt_sa_get_scvlt_table_records( + struct omgt_port *port, + omgt_sa_selector_t *selector, + int32_t *num_records, + STL_SC2PVL_T_MAPPING_TABLE_RECORD **records + ); + + +/** + * @brief Query SA for SCVLr Table Records + * + * @param port port opened by omgt_open_port_* + * @param selector Criteria to select records. + * Valid InputType values: + * NoInput, Lid + * @param num_records Output: The number of records returned in query + * @param records Output: Pointer to records. + * Must be freed by calling omgt_sa_free_records + * + *@return OMGT_STATUS_SUCCESS if success, else error code + */ +OMGT_STATUS_T +omgt_sa_get_scvlr_table_records( + struct omgt_port *port, + omgt_sa_selector_t *selector, + int32_t *num_records, + STL_SC2PVL_R_MAPPING_TABLE_RECORD **records + ); + + +/** + * @brief Query SA for SCVLnt Table Records + * + * @param port port opened by omgt_open_port_* + * @param selector Criteria to select records. + * Valid InputType values: + * NoInput, Lid + * @param num_records Output: The number of records returned in query + * @param records Output: Pointer to records. + * Must be freed by calling omgt_sa_free_records + * + *@return OMGT_STATUS_SUCCESS if success, else error code + */ +OMGT_STATUS_T +omgt_sa_get_scvlnt_table_records( + struct omgt_port *port, + omgt_sa_selector_t *selector, + int32_t *num_records, + STL_SC2PVL_NT_MAPPING_TABLE_RECORD **records + ); + + +/** + * @brief Query SA for DeviceGroupName Records + * + * @param port port opened by omgt_open_port_* + * @param selector Criteria to select records. + * Valid InputType values: + * NoInput + * @param num_records Output: The number of records returned in query + * @param records Output: Pointer to records. + * Must be freed by calling omgt_sa_free_records + * + * @return OMGT_STATUS_SUCCESS if success, else error code + */ +OMGT_STATUS_T +omgt_sa_get_devicegroupname_records( + struct omgt_port *port, + omgt_sa_selector_t *selector, + int32_t *num_records, + STL_DEVICE_GROUP_NAME_RECORD **records + ); + + + +/** + * @brief Query SA for DeviceGroupMember Records + * + * @param port port opened by omgt_open_port_* + * @param selector Criteria to select records. + * Valid InputType values: + * NoInput, Lid, PortGuid, NodeDesc, DeviceGroup + * @param num_records Output: The number of records returned in query + * @param records Output: Pointer to records. + * Must be freed by calling omgt_sa_free_records + * + * @return OMGT_STATUS_SUCCESS if success, else error code + */ +OMGT_STATUS_T +omgt_sa_get_devicegroupmember_records( + struct omgt_port *port, + omgt_sa_selector_t *selector, + int32_t *num_records, + STL_DEVICE_GROUP_MEMBER_RECORD **records + ); + + + +/** + * @brief Query SA for DeviceTreeMember Records + * + * @param port port opened by omgt_open_port_* + * @param selector Criteria to select records. + * Valid InputType values: + * NoInput, Lid + * @param num_records Output: The number of records returned in query + * @param records Output: Pointer to records. + * Must be freed by calling omgt_sa_free_records + * + * @return OMGT_STATUS_SUCCESS if success, else error code + */ +OMGT_STATUS_T +omgt_sa_get_devicetreemember_records( + struct omgt_port *port, + omgt_sa_selector_t *selector, + int32_t *num_records, + STL_DEVICE_TREE_MEMBER_RECORD **records + ); + + + +/** + * @brief Query SA for SwitchInfo Records + * + * @param port port opened by omgt_open_port_* + * @param selector Criteria to select records. + * Valid InputType values: + * NoInput, Lid + * @param num_records Output: The number of records returned in query + * @param records Output: Pointer to records. + * Must be freed by calling omgt_sa_free_records + * + *@return OMGT_STATUS_SUCCESS if success, else error code + */ +OMGT_STATUS_T +omgt_sa_get_switchinfo_records( + struct omgt_port *port, + omgt_sa_selector_t *selector, + int32_t *num_records, + STL_SWITCHINFO_RECORD **records + ); + + +/** + * @brief Query SA for Linear Forwarding Database Records + * + * @param port port opened by omgt_open_port_* + * @param selector Criteria to select records. + * Valid InputType values: + * NoInput, Lid + * @param num_records Output: The number of records returned in query + * @param records Output: Pointer to records. + * Must be freed by calling omgt_sa_free_records + * + *@return OMGT_STATUS_SUCCESS if success, else error code + */ +OMGT_STATUS_T +omgt_sa_get_lfdb_records( + struct omgt_port *port, + omgt_sa_selector_t *selector, + int32_t *num_records, + STL_LINEAR_FORWARDING_TABLE_RECORD **records + ); + + +/** + * @brief Query SA for Multicast Forwarding Database Records + * + * @param port port opened by omgt_open_port_* + * @param selector Criteria to select records. + * Valid InputType values: + * NoInput, Lid + * @param num_records Output: The number of records returned in query + * @param records Output: Pointer to records. + * Must be freed by calling omgt_sa_free_records + * + *@return OMGT_STATUS_SUCCESS if success, else error code + */ +OMGT_STATUS_T +omgt_sa_get_mcfdb_records( + struct omgt_port *port, + omgt_sa_selector_t *selector, + int32_t *num_records, + STL_MULTICAST_FORWARDING_TABLE_RECORD **records + ); + + +/** + * @brief Query SA for VL Arbitration Table Records + * + * @param port port opened by omgt_open_port_* + * @param selector Criteria to select records. + * Valid InputType values: + * NoInput, Lid + * @param num_records Output: The number of records returned in query + * @param records Output: Pointer to records. + * Must be freed by calling omgt_sa_free_records + * + *@return OMGT_STATUS_SUCCESS if success, else error code + */ +OMGT_STATUS_T +omgt_sa_get_vlarb_records( + struct omgt_port *port, + omgt_sa_selector_t *selector, + int32_t *num_records, + STL_VLARBTABLE_RECORD **records + ); + + + + +/** + * @brief Query SA for PKEY Table Records + * + * @param port port opened by omgt_open_port_* + * @param selector Criteria to select records. + * Valid Input Types: + * NoInput, Lid + * @param num_records Output: The number of records returned in query + * @param records Output: Pointer to records. + * Must be freed by calling omgt_sa_free_records + * + *@return OMGT_STATUS_SUCCESS if success, else error code + */ +OMGT_STATUS_T +omgt_sa_get_pkey_table_records( + struct omgt_port *port, + omgt_sa_selector_t *selector, + int32_t *num_records, + STL_P_KEY_TABLE_RECORD **records + ); + + +/** + * @brief Query SA for VFInfo Records + * + * @param port port opened by omgt_open_port_* + * @param selector Criteria to select records. + * Valid InputType values: + * NoInput, PKey, SL, ServiceId, McGid, Index, NodeDesc + * @param num_records Output: The number of records returned in query + * @param records Output: Pointer to records. + * Must be freed by calling omgt_sa_free_records + * + *@return OMGT_STATUS_SUCCESS if success, else error code + */ +OMGT_STATUS_T +omgt_sa_get_vfinfo_records( + struct omgt_port *port, + omgt_sa_selector_t *selector, + int32_t *num_records, + STL_VFINFO_RECORD **records + ); + + +/** + * @brief Query SA for FabricInfo Records + * + * @param port port opened by omgt_open_port_* + * @param selector Criteria to select records. + * Valid InputType values: + * NoInput + * @param num_records Output: The number of records returned in query + * @param records Output: Pointer to records. + * Must be freed by calling omgt_sa_free_records + * + *@return OMGT_STATUS_SUCCESS if success, else error code + */ +OMGT_STATUS_T +omgt_sa_get_fabric_info_records( + struct omgt_port *port, + omgt_sa_selector_t *selector, + int32_t *num_records, + STL_FABRICINFO_RECORD **records + ); + + +/** + * @brief Query SA for Quarantine Node Records + * + * @param port port opened by omgt_open_port_* + * @param selector Criteria to select records. + * Valid InputType values: + * NoInput + * @param num_records Output: The number of records returned in query + * @param records Output: Pointer to records. + * Must be freed by calling omgt_sa_free_records + * + *@return OMGT_STATUS_SUCCESS if success, else error code + */ +OMGT_STATUS_T +omgt_sa_get_quarantinenode_records( + struct omgt_port *port, + omgt_sa_selector_t *selector, + int32_t *num_records, + STL_QUARANTINED_NODE_RECORD **records + ); + + +/** + * @brief Query SA for Congestion Info Records + * + * @param port port opened by omgt_open_port_* + * @param selector Criteria to select records. + * Valid InputType values: + * NoInput, Lid + * @param num_records Output: The number of records returned in query + * @param records Output: Pointer to records. + * Must be freed by calling omgt_sa_free_records + * + *@return OMGT_STATUS_SUCCESS if success, else error code + */ +OMGT_STATUS_T +omgt_sa_get_conginfo_records( + struct omgt_port *port, + omgt_sa_selector_t *selector, + int32_t *num_records, + STL_CONGESTION_INFO_RECORD **records + ); + + +/** + * @brief Query SA for Switch Congestion Records + * + * @param port port opened by omgt_open_port_* + * @param selector Criteria to select records. + * Valid InputType values: + * NoInput, Lid + * @param num_records Output: The number of records returned in query + * @param records Output: Pointer to records. + * Must be freed by calling omgt_sa_free_records + * + *@return OMGT_STATUS_SUCCESS if success, else error code + */ +OMGT_STATUS_T +omgt_sa_get_swcong_records( + struct omgt_port *port, + omgt_sa_selector_t *selector, + int32_t *num_records, + STL_SWITCH_CONGESTION_SETTING_RECORD **records + ); + + + +/** + * @brief Query SA for Switch Port Congestion Records + * + * @param port port opened by omgt_open_port_* + * @param selector Criteria to select records. + * Valid InputType values: + * NoInput, Lid + * @param num_records Output: The number of records returned in query + * @param records Output: Pointer to records. + * Must be freed by calling omgt_sa_free_records + * + *@return OMGT_STATUS_SUCCESS if success, else error code + */ +OMGT_STATUS_T +omgt_sa_get_swportcong_records( + struct omgt_port *port, + omgt_sa_selector_t *selector, + int32_t *num_records, + STL_SWITCH_PORT_CONGESTION_SETTING_RECORD **records + ); + + + +/** + * @brief Query SA for HFI Congestion Records + * + * @param port port opened by omgt_open_port_* + * @param selector Criteria to select records. + * Valid InputType values: + * NoInput, Lid + * @param num_records Output: The number of records returned in query + * @param records Output: Pointer to records. + * Must be freed by calling omgt_sa_free_records + * + *@return OMGT_STATUS_SUCCESS if success, else error code + */ +OMGT_STATUS_T +omgt_sa_get_hficong_records( + struct omgt_port *port, + omgt_sa_selector_t *selector, + int32_t *num_records, + STL_HFI_CONGESTION_SETTING_RECORD **records + ); + + + +/** + * @brief Query SA for HFI Congestion Control Records + * + * @param port port opened by omgt_open_port_* + * @param selector Criteria to select records. + * Valid InputType values: + * NoInput, Lid + * @param num_records Output: The number of records returned in query + * @param records Output: Pointer to records. + * Must be freed by calling omgt_sa_free_records + * + *@return OMGT_STATUS_SUCCESS if success, else error code + */ +OMGT_STATUS_T +omgt_sa_get_hficongctrl_records( + struct omgt_port *port, + omgt_sa_selector_t *selector, + int32_t *num_records, + STL_HFI_CONGESTION_CONTROL_TABLE_RECORD **records + ); + + + +/** + * @brief Query SA for Buffer Control Table Records + * + * @param port port opened by omgt_open_port_* + * @param selector Criteria to select records. + * Valid InputType values: + * NoInput, Lid + * @param num_records Output: The number of records returned in query + * @param records Output: Pointer to records. + * Must be freed by calling omgt_sa_free_records + * + *@return OMGT_STATUS_SUCCESS if success, else error code + */ +OMGT_STATUS_T +omgt_sa_get_buffctrl_records( + struct omgt_port *port, + omgt_sa_selector_t *selector, + int32_t *num_records, + STL_BUFFER_CONTROL_TABLE_RECORD **records + ); + + + +/** + * @brief Query SA for Cable Info Records + * + * @param port port opened by omgt_open_port_* + * @param selector Criteria to select records. + * Valid InputType values: + * NoInput, Lid + * @param num_records Output: The number of records returned in query + * @param records Output: Pointer to records. + * Must be freed by calling omgt_sa_free_records + * + *@return OMGT_STATUS_SUCCESS if success, else error code + */ +OMGT_STATUS_T +omgt_sa_get_cableinfo_records( + struct omgt_port *port, + omgt_sa_selector_t *selector, + int32_t *num_records, + STL_CABLE_INFO_RECORD **records + ); + + + +/** + * @brief Query SA for PortGroup Records + * + * @param port port opened by omgt_open_port_* + * @param selector Criteria to select records. + * Valid InputType values: + * NoInput, Lid + * @param num_records Output: The number of records returned in query + * @param records Output: Pointer to records. + * Must be freed by calling omgt_sa_free_records + * + *@return OMGT_STATUS_SUCCESS if success, else error code + */ +OMGT_STATUS_T +omgt_sa_get_portgroup_records( + struct omgt_port *port, + omgt_sa_selector_t *selector, + int32_t *num_records, + STL_PORT_GROUP_TABLE_RECORD **records + ); + + + +/** + * @brief Query SA for PortGroup forwarding table Records + * + * @param port port opened by omgt_open_port_* + * @param selector Criteria to select records. + * Valid InputType values: + * NoInput, Lid + * @param num_records Output: The number of records returned in query + * @param records Output: Pointer to records. + * Must be freed by calling omgt_sa_free_records + * + *@return OMGT_STATUS_SUCCESS if success, else error code + */ +OMGT_STATUS_T +omgt_sa_get_portgroupfwd_records( + struct omgt_port *port, + omgt_sa_selector_t *selector, + int32_t *num_records, + STL_PORT_GROUP_FORWARDING_TABLE_RECORD **records + ); + + + +/** + * @brief Query SA for SwitchCost Records + * + * @param port port opened by omgt_open_port_* + * @param selector Criteria to select records. + * Valid InputType values: + * NoInput, Lid + * @param num_records Output: The number of records returned in query + * @param records Output: Pointer to records. + * Must be freed by calling omgt_sa_free_records + * + * @return OMGT_STATUS_SUCCESS if success, else error code + */ +OMGT_STATUS_T +omgt_sa_get_switchcost_records( + struct omgt_port *port, + omgt_sa_selector_t *selector, + int32_t *num_records, + STL_SWITCH_COST_RECORD **records + ); + + +#ifdef __cplusplus +} +#endif + +#endif /* __OPAMGT_SA_H__ */ diff --git a/opamgt/include/public/opamgt_sa_notice.h b/opamgt/include/public/opamgt_sa_notice.h new file mode 100644 index 0000000..1e64d60 --- /dev/null +++ b/opamgt/include/public/opamgt_sa_notice.h @@ -0,0 +1,92 @@ +/* BEGIN_ICS_COPYRIGHT2 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT2 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +#ifndef __OPAMGT_NOTICE_H__ +#define __OPAMGT_NOTICE_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +/** + * @brief Initiates a registration for the specified trap. + * + * @param port Previously initialized port object for an in-band + * connection. + * @param trap_num Trap Number to resgister for. + * @param context optional opaque info to be retruned when trap is recieved. + * + * @return OMGT_STATUS_T + */ +OMGT_STATUS_T omgt_sa_register_trap(struct omgt_port *port, uint16_t trap_num, + void *context); + +/** + * @brief Unregisters for the specified trap. + * + * @param port Previously initialized port object for an in-band + * connection. + * @param trap_num Trap Number to unresgister. + * + * @return OMGT_STATUS_T + */ +OMGT_STATUS_T omgt_sa_unregister_trap(struct omgt_port *port, uint16_t trap_num); + +/** + * @brief Gets the Notice Report forwarded from the SM + * + * @param port Previously initialized port object for an in-band + * connection. + * @param notice Pointer to Notice structure that is allocate and + * returned. Must be freed by user. + * @param notice_len pointer to length of Notice structure to be returned. + * Length should always be greater than or equal to the + * sizeof(STL_NOTICE). All bytes that exist greather + * than sizeof(STL_NOTICE) are for ClassData (i.e. + * ClassData Length = notice_len - sizeof(STL_NOTICE)). + * @param context pointer to registration context value returned. + * @param poll_timeout_ms Length of time this function will poll (wait) for a + * Notice Report to be received in milliseconds (-1 will + * block indefinitely, 0 will not block, and X > 0 will + * block for X). + * + * @return OMGT_STATUS_T + */ +OMGT_STATUS_T omgt_sa_get_notice_report(struct omgt_port *port, STL_NOTICE **notice, + size_t *notice_len, void **context, int poll_timeout_ms); + +#ifdef __cplusplus +} +#endif +#endif /* __OPAMGT_NOTICE_H__ */ diff --git a/opamgt/samples/Makefile b/opamgt/samples/Makefile new file mode 100644 index 0000000..b3a1480 --- /dev/null +++ b/opamgt/samples/Makefile @@ -0,0 +1,22 @@ +CC=gcc +CFLAGS=-D__X86_64__ -DCPU_LE -DLINUX -DIB_STACK_OPENIB -I/usr/include/opamgt -Wall -g + +LIBS=-lopamgt \ + -libverbs \ + -libumad \ + -lssl + +SOURCES := $(shell ls *.c) + +APPS := $(SOURCES:%.c=%) + +.PHONY: all +all: $(APPS) + +#default rule for all apps +% : %.c + $(CC) $(CFLAGS) $^ -o $@ $(LIBS) + +.PHONY: clean +clean: + rm -rf $(APPS) diff --git a/opamgt/samples/README b/opamgt/samples/README new file mode 100644 index 0000000..ac676c5 --- /dev/null +++ b/opamgt/samples/README @@ -0,0 +1,22 @@ +This directory contains sample applications built using the opamgt API + +Use 'make' to build all examples +Use 'make ' to just build a single application where is one + of the sources in this directory without a '.c' suffix, e.g. saquery + +Use 'make clean' to remove all compiled applications + +applications: +simple_sa_query - A 'hello world' of how to query an OPA SA +saquery - A sample showing all requests for subnet management information stored in an OPA SA + +simple_pa_query - A 'hello world' of how to query an OPA PA +paquery - A sample showing all requests for performance management information stored in an OPA PA + +simple_sa_notice - A 'hello world' of how to subscribe to fabric notifications + +show_switch_cost_matrix - A sample showing how to request the cost data an OPA FM uses to make routing decisions +job_schedule - A sample showing how to determine fabric topology and schedule a 'job' or request a number of + nodes based on that topology. + + diff --git a/opamgt/samples/job_schedule.c b/opamgt/samples/job_schedule.c new file mode 100644 index 0000000..a4c8dcf --- /dev/null +++ b/opamgt/samples/job_schedule.c @@ -0,0 +1,316 @@ +/* This sample demonstrates the use of the SA swcost query + * to select a set of nodes/switches for a job + * + */ +// core API +#include +// swcost query +#include + +// "Edge" Switch +typedef struct { + STL_LID lid; // identify switches by LID. Easiest when using cost records + STL_NODE_RECORD *nodes [48]; // list of hosts attached to this switch + int last_host_index; // index in previous list of last host +} opa_switch; + + +/* Helper function to retrieve the LID + * of the neighbor of the supplied node + * Used to determine edge switches, those with hosts attached + */ +STL_LID get_neighbor (STL_NODE_RECORD *node_record, STL_LINK_RECORD *link_records, int num_link_records) +{ + STL_LID lid1, lid2; + int i; + for (i = 0; i < num_link_records; ++i) { + STL_LINK_RECORD *link_record = &link_records[i]; + lid1 = link_record->RID.FromLID; + lid2 = link_record->ToLID; + + if (node_record->RID.LID == lid1) { + return lid2; + } else if (node_record->RID.LID == lid2) { + return lid1; + } + } + + return -1; +} + +/* Helper function to determine if list of lids contains + * a specific lid + * */ +int contains (STL_LID * array, STL_LID lid, int array_size) +{ + int i; + for (i = 0; i < array_size; ++i){ + if (array[i] == lid) return 1; + } + return 0; +} + +int main(int argc, char **argv) +{ + OMGT_STATUS_T status = OMGT_STATUS_SUCCESS; + int exitcode = 0; + + struct omgt_port *port = NULL; + int num_host_records, num_link_records, num_cost_records, num_fabricinfo_records, num_classportinfo_records; + + STL_LINK_RECORD *link_records = NULL; + STL_NODE_RECORD *host_records = NULL; + STL_FABRICINFO_RECORD *fabricinfo_records = NULL; + STL_SWITCH_COST_RECORD *cost_records = NULL; + STL_CLASS_PORT_INFO *classportinfo_records = NULL; + + opa_switch *edge_switches = NULL; + opa_switch **used_switches = NULL; + STL_LID *visited_switch_lids = NULL; + + + int last_switch_index = 0; + int i, j; + int requested_hosts = 0, hosts_needed = 0; + int DEBUG = 0; //set to turn on some additional output + + if (argc > 1) { + requested_hosts = strtoul(argv[1], NULL, 0); + if (DEBUG) printf("Requested Hosts: %u\n", requested_hosts); + } else { + fprintf(stderr, "Usage: %s \n", argv[0]); + exitcode = 1; + goto done; + } + + // create a session + status = omgt_open_port_by_num(&port, 1, 1, NULL); + if (OMGT_STATUS_SUCCESS != status) { + fprintf(stderr, "failed to open port\n"); + exitcode = 1; + goto done; + } + + omgt_sa_selector_t selector; + selector.InputType = InputTypeNoInput; + + /* Initial set-up, request topology information from SA + * + * We request FabricInfo, Link, and (HFI) Node records. + */ + status = omgt_sa_get_fabric_info_records(port, &selector, &num_fabricinfo_records, &fabricinfo_records); + if (OMGT_STATUS_SUCCESS != status || num_fabricinfo_records < 1) { + fprintf(stderr, "failed to get fabricinfo. MADStatus=0x%x\n", omgt_get_sa_mad_status(port)); + exitcode = 1; + goto cleanup; + } + + if (fabricinfo_records[0].NumSwitches < 1) { + fprintf(stderr, "No switches in fabric\n"); + exitcode = 1; + goto cleanup; + } + + edge_switches = malloc(sizeof(opa_switch) * fabricinfo_records[0].NumSwitches); // list of switches with hosts + used_switches = malloc(sizeof(opa_switch *) * fabricinfo_records[0].NumSwitches); // list of switches used in job + visited_switch_lids = malloc(sizeof(STL_LID) * fabricinfo_records[0].NumSwitches); // list of switch lids visited during cost decisions + + if (!edge_switches || !used_switches || ! visited_switch_lids){ + fprintf(stderr, "failed to allocate memory.\n"); + exitcode = 1; + goto cleanup; + } + + status = omgt_sa_get_link_records(port, &selector, &num_link_records, &link_records); + if (OMGT_STATUS_SUCCESS != status) { + fprintf(stderr, "failed to execute link record query. MADStatus=0x%x\n", omgt_get_sa_mad_status(port)); + exitcode = 1; + goto cleanup; + } + + selector.InputType = InputTypeNodeType; // select records by type + selector.InputValue.NodeRecord.NodeType = IBA_NODE_CHANNEL_ADAPTER; // select only HFIs (Channel Adapter) + status = omgt_sa_get_node_records(port, &selector, &num_host_records, &host_records); + if (OMGT_STATUS_SUCCESS != status) { + fprintf(stderr, "failed to execute node record query. MADStatus=0x%x\n", omgt_get_sa_mad_status(port)); + exitcode = 1; + goto cleanup; + } + + if (DEBUG) printf("hosts: %u sws: %u\n", fabricinfo_records[0].NumHFIs, fabricinfo_records[0].NumSwitches); + if (requested_hosts > fabricinfo_records[0].NumHFIs) { + fprintf(stderr, "Error: Requested number of hosts exceeds number of hosts available\n"); + exitcode = 1; + goto cleanup; + } + + /* Determine the edge switches in the fabric along with associated hosts*/ + for (i = 0; i < num_host_records; ++i) { + STL_NODE_RECORD *host_record = &host_records[i]; + + STL_LID neighbor_lid = get_neighbor(host_record, link_records, num_link_records); + if (-1 == neighbor_lid){ + fprintf(stderr, "Node missing neighbor\n"); + exitcode = 1; + goto cleanup; + } + int in_list = 0; + int swIndex = 0; + //check if switch in list already + for (j = 0; j < last_switch_index; ++j) { + if (neighbor_lid == edge_switches[j].lid) { + in_list = 1; + swIndex = j; + break; + } + } + if (!in_list) { + edge_switches[last_switch_index++].lid = neighbor_lid; + edge_switches[last_switch_index - 1].nodes[0] = host_record; + + } else { + //add this host to switch's host list + edge_switches[swIndex].nodes[++edge_switches[swIndex].last_host_index] = host_record; + } + } + + if (DEBUG) { + printf("Edge Switches:\n"); + for (i = 0; i < last_switch_index; ++i) { + printf("0x%x\n", edge_switches[i].lid); + for (j = 0; j <= edge_switches[i].last_host_index; ++j) { + printf("---Host %s\n", edge_switches[i].nodes[j]->NodeDesc.NodeString); + } + } + printf("\n\n"); + } + + + /* Determine which hosts to use, attempt to use hosts on a single switch*/ + int max_hosts_switch_index = 0, max_hosts = 0; + for (i = 0; i < last_switch_index; ++i) { + // Save the switch with the max number of hosts for later + // use if we need hosts on multiple switches + if (edge_switches[i].last_host_index > max_hosts) { + max_hosts = edge_switches[i].last_host_index; + max_hosts_switch_index = i; + } + if (edge_switches[i].last_host_index >= requested_hosts - 1) { + printf("Job Plan: \nSwitch %u\n", edge_switches[i].lid); + printf("-----------------------\n"); + for (j = 0; j < requested_hosts; ++j) { + printf("---Host %s\n", edge_switches[i].nodes[j]->NodeDesc.NodeString); + } + goto cleanup; + } + } + + //===================PATH COSTS============================ + /* There were no switches with the requisite number of hosts, + * so use Switch Cost Records to use hosts on least cost + * paths. We must check the capability of the SA before using + * this feature + * + * + * We can request the "full" cost matrix which includes costs + * among all switches (actually only the upper half of the matrix) + * OR + * We can request one row of the cost matrix. In the following we + * request the row corresponding to our previously saved switch. This + * gets us the costs from the saved switch to every other switch + */ + + selector.InputType = InputTypeNoInput; + status = omgt_sa_get_classportinfo_records(port, &selector, &num_classportinfo_records, &classportinfo_records); + if (OMGT_STATUS_SUCCESS != status || num_classportinfo_records != 1) { + fprintf(stderr, "failed to execute classportinfo record query. MADStatus=0x%x\n", omgt_get_sa_mad_status(port)); + exitcode = 1; + goto cleanup; + } + + if (! (classportinfo_records[0].CapMask && STL_SA_CAPABILITY2_SWCOSTRECORD_SUPPORT)) { + fprintf(stderr, "SA does not support switchcost records\n"); + exitcode = 1; + goto cleanup; + } + + selector.InputType = InputTypeLid; // Costs can be looked up by LID + selector.InputValue.SwitchCostRecord.Lid = edge_switches[max_hosts_switch_index].lid; + + status = omgt_sa_get_switchcost_records(port, &selector, &num_cost_records, &cost_records); + if (OMGT_STATUS_SUCCESS != status) { + fprintf(stderr, "failed to execute cost record query. MADStatus=0x%x\n", omgt_get_sa_mad_status(port)); + exitcode = 1; + goto cleanup; + } + + hosts_needed = requested_hosts - (max_hosts + 1); + used_switches[0] = &edge_switches[max_hosts_switch_index]; // keep track of edge switches we're using + STL_LID switch_lid; + visited_switch_lids[0] = used_switches[0]->lid; // keep track of switches we've already considered + int num_switches = 1, num_lids = 1; + while(hosts_needed > 0 && num_switches < last_switch_index) { + int min_cost = -1; + for (i = 0; i < num_cost_records; ++i) { + for (j = 0; j < STL_SWITCH_COST_NUM_ENTRIES; ++j) { + if (((min_cost < 0) || (cost_records[i].Cost[j].value < min_cost)) && + !contains(visited_switch_lids, cost_records[i].Cost[j].DLID, num_lids) && + (cost_records[i].Cost[j].DLID > 0)) { + //we should also check that this is an edge switch, this is done below + min_cost = cost_records[i].Cost[j].value; + switch_lid = cost_records[i].Cost[j].DLID; + } + } + } + + if (min_cost > 0){ + // look up next switch, only include edge switches + for (i = 0; i < last_switch_index; ++i) { + if (edge_switches[i].lid == switch_lid) { + used_switches[num_switches] = &edge_switches[i]; + num_switches++; + + hosts_needed -= (edge_switches[i].last_host_index + 1); + break; + } + } + visited_switch_lids[num_lids] = switch_lid; //mark this switch as visited + num_lids++; + } + } + + if (hosts_needed > 0) { + fprintf(stderr, "Error: Could not allocate job hosts\n"); + exitcode = 1; + goto cleanup; + } + + hosts_needed = requested_hosts; + printf("Job Plan: \n"); + printf("-----------------------\n"); + for (i = 0; i < num_switches; ++i){ + printf("Switch %u\n", used_switches[i]->lid); + for (j = 0; j <= used_switches[i]->last_host_index; ++j) { + printf("---Host %s\n", used_switches[i]->nodes[j]->NodeDesc.NodeString); + if (--hosts_needed <= 0) goto cleanup; + } + } + + +cleanup: + if (edge_switches) free(edge_switches); + if (used_switches) free(used_switches); + if (visited_switch_lids) free(visited_switch_lids); + + // free our result buffers + if (fabricinfo_records) omgt_sa_free_records(fabricinfo_records); + if (classportinfo_records) omgt_sa_free_records(classportinfo_records); + if (cost_records) omgt_sa_free_records(cost_records); + if (host_records) omgt_sa_free_records(host_records); + + // close our session + omgt_close_port(port); + +done: + return exitcode; +} diff --git a/opamgt/samples/paquery.c b/opamgt/samples/paquery.c new file mode 100644 index 0000000..40f0b80 --- /dev/null +++ b/opamgt/samples/paquery.c @@ -0,0 +1,674 @@ +/* A query application for OPA PA data similar to opapaquery + * bundled in IFS distribution + * + */ + +//core API +#include +//extensions for PA queries +#include + +#include +#include + +void Usage(void) +{ + fprintf(stderr, "Usage:paquery [-v] [-h hfi] [-p port] [-t ms] [-b oob_host] -o type\n"); + fprintf(stderr, " [-g groupName] [-l nodeLid] [-P portNumber] [-d] [-U]\n"); + fprintf(stderr, " [-G nodeGuid] [-D nodeDesc] [-f focus] [-S start] [-r range]\n"); + fprintf(stderr, " [-n imgNum] [-O imgOff] [-y imgTime] [-m moveImgNum]\n"); + fprintf(stderr, " [-M moveImgOff] [-V vfName]\n"); + fprintf(stderr, " --help - display this help text\n"); + fprintf(stderr, " -v/--verbose - verbose output\n"); + fprintf(stderr, " -h/--hfi hfi - hfi, numbered 1..n, 0= -p port will be a system wide\n"); + fprintf(stderr, " port num (default is 0)\n"); + fprintf(stderr, " -p/--port port - port, numbered 1..n, 0=1st active (default is 1st\n"); + fprintf(stderr, " active)\n"); + fprintf(stderr, " -t/--timeout - timeout in ms\n"); + fprintf(stderr, " -b oob_host - perform out of band query. For this example, oob_host\n"); + fprintf(stderr, " should have format hostname[:port] or a.b.c.d[:port]\n"); + fprintf(stderr, " -o/--output - output type, default is groupList\n"); + fprintf(stderr, " -g/--groupName - group name for groupInfo query\n"); + fprintf(stderr, " -l/--lid - lid of node\n"); + fprintf(stderr, " -P/--portNumber - port number\n"); + fprintf(stderr, " -G/--nodeGuid - node GUID\n"); + fprintf(stderr, " -D/--nodeDesc - node Description\n"); + fprintf(stderr, " -d/--delta - delta flag for portCounters query\n"); + fprintf(stderr, " -U/--userCntrs - user controlled counters flag for portCounters query\n"); + fprintf(stderr, " -f/--focus - focus select value for getting focus ports\n"); + fprintf(stderr, " focus select values:\n"); + fprintf(stderr, " unexpclrport - list of unexpectedly cleared ports - LID ordered\n"); + fprintf(stderr, " failedport - list of failed ports - LID ordered\n"); + fprintf(stderr, " skippedport - list of skipped ports - LID ordered\n"); + fprintf(stderr, " utilhigh - sorted by utilization - highest first\n"); + fprintf(stderr, " pktrate - sorted by packet rate - highest first\n"); + fprintf(stderr, " utillow - sorted by utilization - lowest first\n"); + fprintf(stderr, " integrity - sorted by integrity category - highest first\n"); + fprintf(stderr, " congestion - sorted by congestion category - highest first\n"); + fprintf(stderr, " smacongestion - sorted by sma congestion category - highest first\n"); + fprintf(stderr, " bubbles - sorted by bubble category - highest first\n"); + fprintf(stderr, " security - sorted by security category - highest first\n"); + fprintf(stderr, " routing - sorted by routing category - highest first\n"); + fprintf(stderr, " vfutilhigh - sorted by utilization - highest first\n"); + fprintf(stderr, " vfpktrate - sorted by packet rate - highest first\n"); + fprintf(stderr, " vfutillow - sorted by utilization - lowest first\n"); + fprintf(stderr, " vfcongestion - sorted by congestion category - highest first\n"); + fprintf(stderr, " vfbubbles - sorted by bubble category - highest first\n"); + fprintf(stderr, " -S/--start - start of window for focus ports - should always be 0\n"); + fprintf(stderr, " for now\n"); + fprintf(stderr, " -r/--range - size of window for focus ports list\n"); + fprintf(stderr, " -n/--imgNum - 64-bit image number \n"); + fprintf(stderr, " -O/--imgOff - image offset \n"); + fprintf(stderr, " -y/--imgTime - image time - may be used with imageinfo, groupInfo,\n"); + fprintf(stderr, " groupInfo, groupConfig, freezeImage, focusPorts,\n"); + fprintf(stderr, " vfInfo, vfConfig, and vfFocusPorts. Will return\n"); + fprintf(stderr, " closest image within image interval if possible.\n"); + fprintf(stderr, " Input should be seconds since 1970-01-01 00:00:00.\n"); + fprintf(stderr, " -m/--moveImgNum - 64-bit image number - used with moveFreeze to move a\n"); + fprintf(stderr, " freeze image\n"); + fprintf(stderr, " -M/--moveImgOff - image offset - may be used with moveFreeze to move a\n"); + fprintf(stderr, " freeze image\n"); + fprintf(stderr, " -V/--vfName - VF name for vfInfo query\n"); + fprintf(stderr, "\n"); + fprintf(stderr, "The -h and -p options permit a variety of selections:\n"); + fprintf(stderr, " -h 0 - 1st active port in system (this is the default)\n"); + fprintf(stderr, " -h 0 -p 0 - 1st active port in system\n"); + fprintf(stderr, " -h x - 1st active port on HFI x\n"); + fprintf(stderr, " -h x -p 0 - 1st active port on HFI x\n"); + fprintf(stderr, " -h 0 -p y - port y within system (irrespective of which ports are active)\n"); + fprintf(stderr, " -h x -p y - HFI x, port y\n"); + fprintf(stderr, "\n"); + fprintf(stderr, "Output types:\n"); + fprintf(stderr, " classPortInfo - class port info\n"); + fprintf(stderr, " groupList - list of PA groups (default)\n"); + fprintf(stderr, " groupInfo - summary statistics of a PA group - requires -g option\n"); + fprintf(stderr, " for groupName\n"); + fprintf(stderr, " groupConfig - configuration of a PA group - requires -g option for\n"); + fprintf(stderr, " groupName\n"); + fprintf(stderr, " groupNodeInfo - Node Information of a PA group - requires -g option for\n"); + fprintf(stderr, " groupName, options -l (lid), -G (nodeGuid) and\n"); + fprintf(stderr, " -D (node description) are optional\n"); + fprintf(stderr, " groupLinkInfo - Link Information of a PA group - requires -g option for\n"); + fprintf(stderr, " groupName, options -l (lid) and -P (port) are optional\n"); + fprintf(stderr, " -P 255 is for all ports\n"); + fprintf(stderr, " portCounters - port counters of fabric port - requires -l (lid) and\n"); + fprintf(stderr, " -P (port) options, -d (delta) is optional\n"); + fprintf(stderr, " pmConfig - retrieve PM configuration information\n"); + fprintf(stderr, " freezeImage - create freeze frame for image ID - requires -n (imgNum)\n"); + fprintf(stderr, " releaseImage - release freeze frame for image ID - requires -n\n"); + fprintf(stderr, " (imgNum)\n"); + fprintf(stderr, " renewImage - renew lease for freeze frame for image ID - requires -n\n"); + fprintf(stderr, " (imgNum)\n"); + fprintf(stderr, " moveFreeze - move freeze frame from image ID to new image ID -\n"); + fprintf(stderr, " requires -n (imgNum) and -m (moveImgNum)\n"); + fprintf(stderr, " focusPorts - get sorted list of ports using utilization or error\n"); + fprintf(stderr, " values (from group buckets)\n"); + fprintf(stderr, " imageInfo - get information about a PA image (timestamps, etc.) -\n"); + fprintf(stderr, " requires -n (imgNum)\n"); + fprintf(stderr, " vfList - list of virtual fabrics\n"); + fprintf(stderr, " vfInfo - summary statistics of a virtual fabric - requires -V\n"); + fprintf(stderr, " option for vfName\n"); + fprintf(stderr, " vfConfig - configuration of a virtual fabric - requires -V option\n"); + fprintf(stderr, " for vfName\n"); + fprintf(stderr, " vfPortCounters - port counters of fabric port - requires -V (vfName), -l\n"); + fprintf(stderr, " (lid) and -P (port) options, -d (delta) is optional\n"); + fprintf(stderr, " vfFocusPorts - get sorted list of virtual fabric ports using\n"); + fprintf(stderr, " utilization or error values (from VF buckets) -\n"); + fprintf(stderr, " requires -V (vfname)\n"); + fprintf(stderr, "\n"); + fprintf(stderr, "Usage examples:\n"); + fprintf(stderr, " paquery -o classPortInfo\n"); + fprintf(stderr, " paquery -o groupList\n"); + fprintf(stderr, " paquery -o groupInfo -g All\n"); + fprintf(stderr, " paquery -o groupConfig -g All\n"); + fprintf(stderr, " paquery -o groupNodeInfo -g All -G \n"); + fprintf(stderr, " paquery -o groupNodeInfo -g All -D \n"); + fprintf(stderr, " paquery -o groupNodeInfo -g All -l 1 \n"); + fprintf(stderr, " paquery -o groupNodeInfo -g All -l 1 -G \n"); + fprintf(stderr, " paquery -o groupLinkInfo -g All\n"); + fprintf(stderr, " paquery -o groupLinkInfo -g All -l 1 -P 1\n"); + fprintf(stderr, " paquery -o groupLinkInfo -g All -l 1 -P 255\n"); + fprintf(stderr, " paquery -o portCounters -l 1 -P 1 -d 1\n"); + fprintf(stderr, " paquery -o portCounters -l 1 -P 1 -d 1 -n 0x20000000d02 -O 1\n"); + fprintf(stderr, " paquery -o portCounters -l 1 -P 1 -y 1494873266 \n"); + fprintf(stderr, " paquery -o pmConfig\n"); + fprintf(stderr, " paquery -o freezeImage -n 0x20000000d02\n"); + fprintf(stderr, " paquery -o releaseImage -n 0xd01\n"); + fprintf(stderr, " paquery -o renewImage -n 0xd01\n"); + fprintf(stderr, " paquery -o moveFreeze -n 0xd01 -m 0x20000000d02 -M -2\n"); + fprintf(stderr, " paquery -o focusPorts -g All -f integrity -S 0 -r 20\n"); + fprintf(stderr, " paquery -o imageInfo -n 0x20000000d02\n"); + fprintf(stderr, " paquery -o vfList\n"); + fprintf(stderr, " paquery -o vfInfo -V Default\n"); + fprintf(stderr, " paquery -o vfConfig -V Default\n"); + fprintf(stderr, " paquery -o vfPortCounters -l 1 -P 1 -d 1 -V Default\n"); + fprintf(stderr, " paquery -o vfFocusPorts -V Default -f integrity -S 0 -r 20\n"); + + exit(2); +} + +typedef struct OutputFocusMap { + char *string; + int32 focus; +} OutputFocusMap_t; + +OutputFocusMap_t OutputFocusTable[]= { + {"unexpclrport", 0x00010101}, + {"failedport", 0x00010102}, + {"skippedport", 0x00010103}, + {"utilhigh", 0x00020001}, + {"pktrate", 0x00020082}, + {"utillow", 0x00020101}, + {"integrity", 0x00030001}, + {"congestion", 0x00030002}, + {"smacongestion", 0x00030003}, + {"bubbles", 0x00030004}, + {"security" , 0x00030005}, + {"routing", 0x00030006}, + {"vfutilhigh", 0x00020083}, + {"vfpktrate", 0x00020084}, + {"vfutillow", 0x00020102}, + {"vfcongestion", 0x00030007}, + {"vfbubbles", 0x00030008}, + { NULL, 0}, +}; + +int StringToFocus (int32 *value, const char* str) +{ + int i; + + i=0; + while (OutputFocusTable[i].string!=NULL) { + if (0 == strcmp(str,OutputFocusTable[i].string) ){ + *value = OutputFocusTable[i].focus; + return 0; + } + else i++; + } + return 1; +} + +// command line options +struct option options[] = { + { "verbose", required_argument, NULL, 'v' }, + { "hfi", required_argument, NULL, 'h' }, + { "port", required_argument, NULL, 'p' }, + { "timeout", required_argument, NULL, 't' }, + { "lid", required_argument, NULL, 'l' }, + + { "groupName", required_argument, NULL, 'g' }, + { "portNumber", required_argument, NULL, 'P' }, + { "nodeGuid", required_argument, NULL, 'G' }, + { "nodeDesc", required_argument, NULL, 'D' }, + { "delta", no_argument, NULL, 'd' }, + { "userCntrs", no_argument, NULL, 'U' }, + { "focus", required_argument, NULL, 'f' }, + { "start", required_argument, NULL, 'S' }, + { "range", required_argument, NULL, 'r' }, + { "imgNum", required_argument, NULL, 'n' }, + { "imgOff", required_argument, NULL, 'O' }, + { "imgTime", required_argument, NULL, 'y' }, + { "moveImgNum", required_argument, NULL, 'm' }, + { "moveImgOff", required_argument, NULL, 'M' }, + { "vfName", required_argument, NULL, 'V' }, + + // output type + { "output", required_argument, NULL, 'o' }, + { "help", no_argument, NULL, '$' }, // use an invalid option character + { 0 } +}; + +int main(int argc, char **argv) +{ + OMGT_STATUS_T status = OMGT_STATUS_SUCCESS; + int exitcode = 0; + struct omgt_port * port = NULL; + int i,c,index; + int pa_service_state = OMGT_SERVICE_STATE_UNKNOWN; + uint32_t num_data; + + int debug = 0; + + char * type = "groupList"; + int hfi_num = 1; + int port_num = 1; + int ms_timeout = OMGT_DEF_TIMEOUT_MS; + char * oob_addr = NULL; + + int select = 0; + int start = 0; + int range = 0; + + char name_data[256]; + char nodeDesc[64] = ""; + + int lid = 1, counters_port = 1; + int nodeGuid = 1; + + int delta = 0; + int user_counters = 0; + int got_imageTime = 0, got_imageNum = 0, got_imageOffset = 0; + + //where applicable, get current data by default + STL_PA_IMAGE_ID_DATA image_id_query = {.imageNumber = PACLIENT_IMAGE_CURRENT}; + STL_PA_IMAGE_ID_DATA response_id; + + STL_PA_IMAGE_ID_DATA image_id_move = {0}; + while (-1 != (c = getopt_long(argc, argv, "h:p:t:o:l:P:n:g:G:dUO:y:m:M:f:S:r:V:b:v$", options, &index))){ + switch (c) + { + case '$': + Usage(); + break; + case 'h': + hfi_num = strtol(optarg, NULL, 0); + break; + case 'p': + port_num = strtol(optarg, NULL, 0); + break; + case 't': + ms_timeout = strtol(optarg, NULL, 0); + break; + case 'o': + type = optarg; + break; + case 'l': + lid = strtoul(optarg, NULL, 0); + break; + case 'P': + counters_port = strtoul(optarg, NULL, 0); + break; + case 'G': + nodeGuid = strtoul(optarg, NULL, 0); + break; + case 'D': + snprintf(nodeDesc, 64, "%s", optarg); + break; + case 'n': + image_id_query.imageNumber = strtoul(optarg, NULL, 0); + got_imageNum = 1; + break; + case 'g': + snprintf(name_data, 256, "%s", optarg); + break; + case 'd': + delta = 1; + break; + case 'U': + user_counters = 1; + break; + case 'O': + image_id_query.imageOffset = strtol(optarg, NULL, 0); + got_imageOffset = 1; + break; + case 'y': + image_id_query.imageNumber = PACLIENT_IMAGE_TIMED; + image_id_query.imageTime.absoluteTime = strtoul(optarg, NULL, 0); + got_imageTime = 1; + break; + case 'm': + image_id_move.imageNumber = strtoul(optarg, NULL, 0); + break; + case 'M': + image_id_move.imageOffset = strtol(optarg, NULL, 0); + break; + case 'f': + if (StringToFocus (&select, optarg)) { + fprintf(stderr, "opapaquery: Invalid Focus: %s\n", optarg); + Usage(); + } + break; + case 'S': + start = strtoul(optarg, NULL, 0); + break; + case 'r': + range = strtoul(optarg, NULL, 0); + break; + case 'V': + snprintf(name_data, 256, "%s", optarg); + break; + case 'v': + debug = 1; + break; + case 'b': + oob_addr = optarg; + break; + default: + fprintf(stderr, "opasaquery: Invalid option -%c\n", c); + Usage(); + break; + } + } + + // create a session + struct omgt_params session_params = { + .debug_file = debug ? stderr : NULL, + .error_file = stderr + }; + if (oob_addr){ + char *tmp = strchr(oob_addr, ':'); + if (tmp) *tmp = 0; + struct omgt_oob_input oob_input = { + /* host can be specified by name or as either IPv4 of IPv6 + * but this example only considers IPv4 for simplicity*/ + .host = oob_addr, + .port = (tmp ? strtol(++tmp, NULL, 0) : 3245) + }; + + status = omgt_oob_connect(&port, &oob_input, &session_params); + } else { + status = omgt_open_port_by_num(&port, hfi_num, port_num, &session_params); + + /* (Optional) Check if the PA Service is Operational + * All PA queries will do an initial pa service state check if not already + * operational, so this is more of a verbose sanity check. + */ + if (status == OMGT_STATUS_SUCCESS) { + status = omgt_port_get_pa_service_state(port, &pa_service_state, OMGT_REFRESH_SERVICE_ANY_STATE); + if (status == OMGT_STATUS_SUCCESS) { + if (pa_service_state != OMGT_SERVICE_STATE_OPERATIONAL) { + fprintf(stderr, "failed to connect, PA service state is Not Operational: %s (%d)\n", + omgt_service_state_totext(pa_service_state), pa_service_state); + exitcode = 1; + goto fail2; + } + } else { + fprintf(stderr, "failed to get and refresh PA service state: %s (%u)\n", + omgt_status_totext(status), status); + exitcode = 1; + goto fail2; + } + } + } + + if (OMGT_STATUS_SUCCESS != status){ + fprintf(stderr, "failed to open port: %s (%u)\n", + omgt_status_totext(status), status); + exitcode=1; + goto fail1; + } + + //set timeout for PA operations + omgt_set_timeout(port, ms_timeout); + + // verify PA has necessary capabilities + STL_CLASS_PORT_INFO *portInfo; + status = omgt_pa_get_classportinfo(port, &portInfo); + if(OMGT_STATUS_SUCCESS != status){ + fprintf(stderr, "failed to get ClassPortInfo\n"); + exitcode=1; + goto fail2; + } + STL_PA_CLASS_PORT_INFO_CAPABILITY_MASK paCap; + memcpy(&paCap, &portInfo->CapMask, sizeof(STL_PA_CLASS_PORT_INFO_CAPABILITY_MASK)); + //if trying to query by time, check if feature available + if (got_imageTime ){ + if (!(paCap.s.IsAbsTimeQuerySupported)){ + fprintf(stderr, "PA does not support time queries\n"); + exitcode=1; + free(portInfo); + goto fail2; + } + } + //if trying to query extended focus port selects, check if feature is available + if (select == STL_PA_SELECT_UNEXP_CLR_PORT || select == STL_PA_SELECT_NO_RESP_PORT || + select == STL_PA_SELECT_SKIPPED_PORT){ + if (!(paCap.s.IsExtFocusTypesSupported)){ + fprintf(stderr, "PA does not support extended focus ports\n"); + exitcode=1; + free(portInfo); + goto fail2; + } + } + //if querying for nodeinfo and linkinfo check if feature is available + if ((!strcasecmp(type, "groupNodeInfo")) || (!strcasecmp(type, "groupLinkInfo"))){ + if (!(paCap.s.IsTopologyInfoSupported)){ + fprintf(stderr, "PA does not support Topology Information from PM\n"); + exitcode=1; + free(portInfo); + goto fail2; + } + } + //Check if VF level Focus selects are supported + if (IS_VF_FOCUS_SELECT(select)){ + if (!(paCap.s.IsVFFocusTypesSupported)){ + fprintf(stderr, "PA does not support VF Focus selects\n"); + exitcode=1; + free(portInfo); + goto fail2; + } + } + + + //perform the requested operation + if (!strcasecmp(type, "pmconfig")){ + STL_PA_PM_CFG_DATA pa_data; + + status = omgt_pa_get_pm_config(port, &pa_data); + if (OMGT_STATUS_SUCCESS != status){ + fprintf(stderr, "failed to execute query. MadStatus=0x%x\n", omgt_get_pa_mad_status(port)); + } else { + printf("Sweep interval: %d seconds\n", pa_data.sweepInterval); + } + } else if (!strcasecmp(type, "imageInfo")){ + STL_PA_IMAGE_INFO_DATA pa_data; + + status = omgt_pa_get_image_info(port, image_id_query, &pa_data); + if (OMGT_STATUS_SUCCESS != status){ + fprintf(stderr, "failed to execute query. MadStatus=0x%x\n", omgt_get_pa_mad_status(port)); + } else { + printf("Image ID: 0x%"PRIx64"\n", pa_data.imageId.imageNumber); + } + } else if (!strcasecmp(type, "groupList")) { + if (paCap.s.IsPerImageListsSupported) { + STL_PA_GROUP_LIST2 *pa_data = NULL; + + status = omgt_pa_get_group_list2(port, image_id_query, &num_data, &pa_data); + if (OMGT_STATUS_SUCCESS != status){ + fprintf(stderr, "failed to execute query. MadStatus=0x%x\n", omgt_get_pa_mad_status(port)); + } else { + for (i = 0; i < num_data; ++i){ + printf("Group Name: %s\n", pa_data[i].groupName); + } + printf("Image ID: 0x%"PRIx64"\n", pa_data[0].imageId.imageNumber); + // Some calls allocate memory and have associated release functions to free that memory + omgt_pa_release_group_list2(&pa_data); + } + } else { + if (got_imageTime || got_imageNum || got_imageOffset) { + fprintf(stderr, "PA does not support Per Image Lists"); + } + STL_PA_GROUP_LIST *pa_data = NULL; + + status = omgt_pa_get_group_list(port, &num_data, &pa_data); + if (OMGT_STATUS_SUCCESS != status){ + fprintf(stderr, "failed to execute query. MadStatus=0x%x\n", omgt_get_pa_mad_status(port)); + } else { + for (i = 0; i < num_data; ++i){ + printf("Group Name: %s\n", pa_data[i].groupName); + } + // Some calls allocate memory and have associated release functions to free that memory + omgt_pa_release_group_list(&pa_data); + } + } + } else if (!strcasecmp(type, "vfList")){ + if (paCap.s.IsPerImageListsSupported) { + STL_PA_VF_LIST2 *pa_data = NULL; + + status = omgt_pa_get_vf_list2(port, image_id_query, &num_data, &pa_data); + if (OMGT_STATUS_SUCCESS != status){ + fprintf(stderr, "failed to execute query. MadStatus=0x%x\n", omgt_get_pa_mad_status(port)); + } else { + for (i = 0; i < num_data; ++i){ + printf("VF Name: %s\n", pa_data[i].vfName); + } + printf("Image ID: 0x%"PRIx64"\n", pa_data[0].imageId.imageNumber); + // Some calls allocate memory and have associated release functions to free that memory + omgt_pa_release_vf_list2(&pa_data); + } + } else { + if (got_imageTime || got_imageNum || got_imageOffset) { + fprintf(stderr, "PA does not support Per Image Lists"); + } + STL_PA_VF_LIST *pa_data = NULL; + + status = omgt_pa_get_vf_list(port, &num_data, &pa_data); + if (OMGT_STATUS_SUCCESS != status){ + fprintf(stderr, "failed to execute query. MadStatus=0x%x\n", omgt_get_pa_mad_status(port)); + } else { + for(i = 0; i < num_data; ++i){ + printf("VF: %s\n", pa_data[i].vfName); + } + omgt_pa_release_vf_list(&pa_data); + } + } + } else if (!strcasecmp(type, "groupInfo")){ + STL_PA_PM_GROUP_INFO_DATA pa_data; + + status = omgt_pa_get_group_info(port, image_id_query, name_data, &response_id, &pa_data); + if (OMGT_STATUS_SUCCESS != status){ + fprintf(stderr, "failed to execute query. MadStatus=0x%x\n", omgt_get_pa_mad_status(port)); + } else { + printf("Group internal ports: %d\n", pa_data.numInternalPorts); + } + } else if (!strcasecmp(type, "vfInfo")){ + STL_PA_VF_INFO_DATA pa_data; + + status = omgt_pa_get_vf_info(port, image_id_query, name_data, &response_id, &pa_data); + if (OMGT_STATUS_SUCCESS != status){ + fprintf(stderr, "failed to execute query. MadStatus=0x%x\n", omgt_get_pa_mad_status(port)); + } else { + printf("VF ports: %d\n", pa_data.numPorts); + } + } else if (!strcasecmp(type, "groupConfig")){ + STL_PA_PM_GROUP_CFG_RSP * pa_data = NULL; + + status = omgt_pa_get_group_config(port, image_id_query, name_data, &response_id, &num_data, &pa_data); + if (OMGT_STATUS_SUCCESS != status){ + fprintf(stderr, "failed to execute query. MadStatus=0x%x\n", omgt_get_pa_mad_status(port)); + } else { + for(i = 0; i < num_data; ++i){ + printf("Group Member: %s\n", pa_data[i].nodeDesc); + } + omgt_pa_release_group_config(&pa_data); + } + } else if (!strcasecmp(type, "groupNodeInfo")){ + STL_PA_GROUP_NODEINFO_RSP *pa_data = NULL; + + status = omgt_pa_get_group_nodeinfo(port, image_id_query, name_data, lid, nodeGuid, nodeDesc, &response_id, &num_data, &pa_data); + if (OMGT_STATUS_SUCCESS != status){ + fprintf(stderr, "failed to execute query. MadStatus=0x%x\n", omgt_get_pa_mad_status(port)); + } else { + for(i = 0; i < num_data; ++i){ + printf("Group Member: %s\n", pa_data[i].nodeDesc); + } + omgt_pa_release_group_nodeinfo(&pa_data); + } + } else if (!strcasecmp(type, "groupLinkInfo")){ + STL_PA_GROUP_LINKINFO_RSP *pa_data = NULL; + + status = omgt_pa_get_group_linkinfo(port, image_id_query, name_data, lid, port_num, &response_id, &num_data, &pa_data); + if (OMGT_STATUS_SUCCESS != status){ + fprintf(stderr, "failed to execute query. MadStatus=0x%x\n", omgt_get_pa_mad_status(port)); + } else { + for(i = 0; i < num_data; ++i){ + printf("To LID: 0x%08X\n", pa_data[i].toLID); + } + omgt_pa_release_group_linkinfo(&pa_data); + } + } else if (!strcasecmp(type, "vfConfig")){ + STL_PA_VF_CFG_RSP *pa_data = NULL; + + status = omgt_pa_get_vf_config(port, image_id_query, name_data, &response_id, &num_data, &pa_data); + if (OMGT_STATUS_SUCCESS != status){ + fprintf(stderr, "failed to execute query. MadStatus=0x%x\n", omgt_get_pa_mad_status(port)); + } else { + for(i = 0; i < num_data; ++i){ + printf("VF Member: %s\n", pa_data[i].nodeDesc); + } + omgt_pa_release_vf_config(&pa_data); + } + } else if (!strcasecmp(type, "focusPorts")){ + STL_FOCUS_PORTS_RSP *pa_data = NULL; + + status = omgt_pa_get_group_focus(port, image_id_query, name_data, select, start, range, &response_id, &num_data, &pa_data); + if (OMGT_STATUS_SUCCESS != status){ + fprintf(stderr, "failed to execute query. MadStatus=0x%x\n", omgt_get_pa_mad_status(port)); + } else { + for (i = 0; i < num_data; ++i){ + printf("Port: %s Value %"PRIu64"\n", pa_data[i].nodeDesc, pa_data[i].value); + } + omgt_pa_release_group_focus(&pa_data); + } + } else if (!strcasecmp(type, "vfFocusPorts")){ + STL_PA_VF_FOCUS_PORTS_RSP *pa_data = NULL; + + status = omgt_pa_get_vf_focus(port, image_id_query, name_data, select, start, range, &response_id, &num_data, &pa_data); + if (OMGT_STATUS_SUCCESS != status){ + fprintf(stderr, "failed to execute query. MadStatus=0x%x\n", omgt_get_pa_mad_status(port)); + } else { + for(i = 0; i < num_data; ++i){ + printf("Port: %s Value %"PRIu64"\n", pa_data[i].nodeDesc, pa_data[i].value); + } + omgt_pa_release_vf_focus(&pa_data); + } + } else if (!strcasecmp(type, "portCounters")){ + STL_PORT_COUNTERS_DATA pa_data; + + status = omgt_pa_get_port_stats2(port, image_id_query, lid, counters_port, &response_id, &pa_data, NULL, delta, user_counters); + if (OMGT_STATUS_SUCCESS != status){ + fprintf(stderr, "failed to execute query. MadStatus=0x%x\n", omgt_get_pa_mad_status(port)); + } else { + printf("Port Xmit Data: %"PRIu64"\n", pa_data.portXmitData); + } + } else if (!strcasecmp(type, "vfPortCounters")){ + STL_PA_VF_PORT_COUNTERS_DATA pa_data; + + status = omgt_pa_get_vf_port_stats2(port, image_id_query, name_data, lid, counters_port, &response_id, &pa_data, NULL, delta, user_counters); + if (OMGT_STATUS_SUCCESS != status){ + fprintf(stderr, "failed to execute query. MadStatus=0x%x\n", omgt_get_pa_mad_status(port)); + } else { + printf("Port Xmit Data: %"PRIu64"\n", pa_data.portVFXmitData); + } + } else if (!strcasecmp(type, "freezeImage")){ + STL_PA_IMAGE_ID_DATA pa_data; + + status = omgt_pa_freeze_image(port, image_id_query, &pa_data); + if (OMGT_STATUS_SUCCESS != status){ + fprintf(stderr, "failed to execute query. MadStatus=0x%x\n", omgt_get_pa_mad_status(port)); + } else { + printf("Successfully froze image 0x%"PRIx64"\n", pa_data.imageNumber); + } + } else if (!strcasecmp(type, "moveFreeze")){ + status = omgt_pa_move_image_freeze(port, image_id_query, &image_id_move); + if (OMGT_STATUS_SUCCESS != status){ + fprintf(stderr, "failed to execute query. MadStatus=0x%x\n", omgt_get_pa_mad_status(port)); + } else { + printf("Success\n"); + } + + } else if (!strcasecmp(type, "releaseImage")){ + status = omgt_pa_release_image(port, image_id_query); + if (OMGT_STATUS_SUCCESS != status){ + fprintf(stderr, "failed to execute query. MadStatus=0x%x\n", omgt_get_pa_mad_status(port)); + } else { + printf("Success\n"); + } + } else if (!strcasecmp(type, "renewImage")){ + status = omgt_pa_renew_image(port, image_id_query); + if (OMGT_STATUS_SUCCESS != status){ + fprintf(stderr, "failed to execute query. MadStatus=0x%x\n", omgt_get_pa_mad_status(port)); + } else { + printf("Success\n"); + } + } else if (!strcasecmp(type, "classPortInfo")){ + printf("PA Capability Mask: 0x%x\n", portInfo->CapMask); + } + //Frees the portInfo structure + if(portInfo) + free(portInfo); +fail2: + omgt_close_port(port); +fail1: + return exitcode; +} diff --git a/opamgt/samples/saquery.c b/opamgt/samples/saquery.c new file mode 100644 index 0000000..7eda06a --- /dev/null +++ b/opamgt/samples/saquery.c @@ -0,0 +1,486 @@ +/* A query application for OPA SA records similar to opasaquery + * bundled in IFS distribution + * + */ + +// core API +#include +// extensions for SA queries +#include + +#include + +void Usage() +{ + fprintf(stdout, "Usage: saquery [-v] [-h hfi] [-p port] [-t ms] [-b oob_host] [-l lid] -o type \n"); + fprintf(stdout, " or\n"); + fprintf(stdout, " saquery --help\n"); + fprintf(stdout, " --help - produce full help text\n"); + fprintf(stdout, "\n"); + fprintf(stderr, " -v/--verbose - verbose output\n"); + fprintf(stderr, " -h/--hfi hfi - hfi, numbered 1..n, 0= -p port will be a system wide\n"); + fprintf(stderr, " port num (default is 0)\n"); + fprintf(stderr, " -p/--port port - port, numbered 1..n, 0=1st active (default is 1st\n"); + fprintf(stderr, " active)\n"); + fprintf(stderr, " -t/--timeout - timeout in ms\n"); + fprintf(stderr, " -l/--lid - filter query results for specific lid\n"); + fprintf(stderr, " -g/--guid - filter query results for specific guid\n"); + fprintf(stderr, " -b oob_host - perform out of band query. For this example, oob_host\n"); + fprintf(stderr, " should have format hostname[:port] or a.b.c.d[:port]\n"); + fprintf(stderr, " -o/--output type - output type\n"); + fprintf(stderr, " -x local_gid - local gid for out-of-band queryies that need a local gid\n"); + fprintf(stdout, "type: (default is node)\n"); + fprintf(stdout, " classportinfo - classportinfo of the SA\n"); + fprintf(stdout, " systemguid - list of system image guids\n"); + fprintf(stdout, " nodeguid - list of node guids\n"); + fprintf(stdout, " portguid - list of port guids\n"); + fprintf(stdout, " lid - list of lids\n"); + fprintf(stdout, " desc - list of node descriptions/names\n"); + fprintf(stdout, " path - list of path records\n"); + fprintf(stdout, " node - list of node records\n"); + fprintf(stdout, " portinfo - list of port info records\n"); + fprintf(stdout, " sminfo - list of SM info records\n"); + fprintf(stdout, " swinfo - list of switch info records\n"); + fprintf(stdout, " link - list of link records\n"); + fprintf(stdout, " scsc - list of SC to SC mapping table records\n"); + fprintf(stdout, " slsc - list of SL to SC mapping table records\n"); + fprintf(stdout, " scsl - list of SC to SL mapping table records\n"); + fprintf(stdout, " scvlt - list of SC to VLt table records\n"); + fprintf(stdout, " scvlr - list of SC to VLr table records\n"); + fprintf(stdout, " scvlnt - list of SC to VLnt table records\n"); + fprintf(stdout, " vlarb - list of VL arbitration table records\n"); + fprintf(stdout, " pkey - list of P-Key table records\n"); + fprintf(stdout, " service - list of service records\n"); + fprintf(stdout, " mcmember - list of multicast member records\n"); + fprintf(stdout, " inform - list of inform info records\n"); + fprintf(stdout, " linfdb - list of switch linear FDB records\n"); + fprintf(stdout, " mcfdb - list of switch multicast FDB records\n"); + fprintf(stdout, " trace - list of trace records\n"); + fprintf(stdout, " vfinfo - list of vFabrics\n"); + fprintf(stdout, " fabricinfo - summary of fabric devices\n"); + fprintf(stdout, " quarantine - list of quarantined nodes\n"); + fprintf(stdout, " conginfo - list of Congestion Info Records\n"); + fprintf(stdout, " swcongset - list of Switch Congestion Settings\n"); + fprintf(stdout, " swportcong - list of Switch Port Congestion Settings\n"); + fprintf(stdout, " hficongset - list of HFI Congestion Settings\n"); + fprintf(stdout, " hficongcon - list of HFI Congesting Control Settings\n"); + fprintf(stdout, " bfrctrl - list of buffer control tables\n"); + fprintf(stdout ," cableinfo - list of Cable Info records\n"); + fprintf(stdout ," portgroup - list of AR Port Group records\n"); + fprintf(stdout ," portgroupfdb - list of AR Port Group FWD records\n"); + fprintf(stdout ," dglist - list of Device Group Names\n"); + fprintf(stdout ," dgmember - list of Device Group records\n"); + fprintf(stdout ," dtree - list of Device Tree records\n"); + fprintf(stdout ," swcost - list of switch cost records\n"); + fprintf(stdout, "\n"); + fprintf(stdout, "Usage examples:\n"); + fprintf(stdout, " saquery -o desc\n"); + fprintf(stdout, " saquery -o portinfo\n"); + fprintf(stdout, " saquery -o sminfo\n"); + fprintf(stdout, " saquery -o pkey\n"); + + exit(0); +} + +// command line options +struct option options[] = { + { "verbose", required_argument, NULL, 'v' }, + { "hfi", required_argument, NULL, 'h' }, + { "port", required_argument, NULL, 'p' }, + { "timeout", required_argument, NULL, 't' }, + + // input types (small subset) + { "lid", required_argument, NULL, 'l' }, + { "guid", required_argument, NULL, 'g' }, + + // output type + { "output", required_argument, NULL, 'o' }, + { "help", no_argument, NULL, '$' }, // use an invalid option character + { 0 } +}; + +int main(int argc, char ** argv) +{ + + OMGT_STATUS_T status = OMGT_STATUS_SUCCESS; + int exitcode = 0; + struct omgt_port * port = NULL; + int num_records = 0; + int c, index, debug = 0; + int sa_service_state = OMGT_SERVICE_STATE_UNKNOWN; + void *sa_records = NULL; + omgt_sa_selector_t selector; + + char * type = "node"; + int hfi_num = 1; + int port_num = 1; + int ms_timeout = OMGT_DEF_TIMEOUT_MS; + uint32_t lid = 0; + uint64_t guid = 0; + uint64_t local_prefix = 0; + char *tmp = NULL, *gid = NULL; + uint64_t local_guid = 0; + + char * oob_addr = NULL; + + //default to requesting all records + selector.InputType = InputTypeNoInput; + + while (-1 != (c = getopt_long(argc, argv, "h:p:t:o:l:b:g:x:v$", options, &index))){ + switch (c) + { + case '$': + Usage(); + break; + case 'h': // hfi to issue query from + hfi_num = strtol(optarg, NULL, 0); + break; + case 'p': // port to issue query from + port_num = strtol(optarg, NULL, 0); + break; + case 't': + ms_timeout = strtol(optarg, NULL, 0); + break; + case 'o': // select output record desired + type = optarg; + break; + case 'l': + selector.InputType = InputTypeLid; + lid = strtoul(optarg, NULL, 0); + break; + case 'g': + selector.InputType = InputTypePortGuid; + guid = strtoul(optarg, NULL, 0); + break; + case 'x': + gid = optarg; + if (gid[0] == '0' && gid[1] == 'x') gid += 2; + local_prefix = strtoul(gid, &tmp, 16); + local_guid = strtoul(++tmp, NULL, 16); + break; + case 'b': + oob_addr = optarg; + break; + case 'v': + debug = 1; + break; + default: + fprintf(stderr, "opasaquery: Invalid option -%c\n", c); + Usage(); + break; + } + } + + // create a session + struct omgt_params session_params = { + .debug_file = debug ? stderr : NULL, + .error_file = stderr + }; + if (oob_addr){ + tmp = strchr(oob_addr, ':'); + if (tmp) *tmp = 0; + struct omgt_oob_input oob_input = { + /* host can be specified by name or as either IPv4 of IPv6 + * but this example only considers IPv4 for simplicity*/ + .host = oob_addr, + .port = (tmp ? strtol(++tmp, NULL, 0) : 3245) + }; + + status = omgt_oob_connect(&port, &oob_input, &session_params); + } else { + status = omgt_open_port_by_num(&port, hfi_num, port_num, &session_params); + (void)omgt_port_get_port_guid(port, &local_guid); + (void)omgt_port_get_port_prefix(port, &local_prefix); + + /* (Optional) Check if the SA Service is Operational + * All SA queries will do an initial sa service state check if not already + * operational, so this is more of a verbose sanity check. + */ + if (status == OMGT_STATUS_SUCCESS) { + status = omgt_port_get_sa_service_state(port, &sa_service_state, OMGT_REFRESH_SERVICE_ANY_STATE); + if (status == OMGT_STATUS_SUCCESS) { + if (sa_service_state != OMGT_SERVICE_STATE_OPERATIONAL) { + fprintf(stderr, "failed to connect, SA service state is Not Operational: %s (%d)\n", + omgt_service_state_totext(sa_service_state), sa_service_state); + exitcode = 1; + goto fail2; + } + } else { + fprintf(stderr, "failed to get and refresh SA service state: %s (%u)\n", + omgt_status_totext(status), status); + exitcode = 1; + goto fail2; + } + } + } + + if (OMGT_STATUS_SUCCESS != status){ + fprintf(stderr, "failed to open port: %s (%u)\n", + omgt_status_totext(status), status); + exitcode=1; + goto fail1; + } + + /* Set timeout for SA operation */ + omgt_set_timeout(port, ms_timeout); + + /* Perform the requested operation. + * Some records are are not always supported, + * and in those cases an additional omgt_sa_get_classportinfo + * call must be performed to determine the management capabilities + */ + if (!strcmp(type, "node")){ + /* Valid Input Types: + * NoInput, Lid, PortGuid, NodeGuid, SystemImageGuid, NodeType, NodeDesc + */ + if (selector.InputType == InputTypePortGuid) selector.InputValue.NodeRecord.NodeGUID = guid; + if (selector.InputType == InputTypeLid) selector.InputValue.NodeRecord.Lid = lid; + status = omgt_sa_get_node_records(port, &selector, &num_records, (STL_NODE_RECORD **)&sa_records); + } else if (!strcmp(type, "portinfo")){ + /* Valid Input Types: NoInput, Lid */ + if (selector.InputType == InputTypeLid) selector.InputValue.PortInfoRecord.Lid = lid; + status = omgt_sa_get_portinfo_records(port, &selector, &num_records, (STL_PORTINFO_RECORD **)&sa_records); + } else if (!strcmp(type, "systemguid")){ + /* Valid Input Types: + * NoInput, NodeType, SystemImageGuid, NodeGuid, PortGuid, Lid, NodeDesc + */ + if (selector.InputType == InputTypePortGuid) selector.InputValue.NodeRecord.NodeGUID = guid; + if (selector.InputType == InputTypeLid) selector.InputValue.NodeRecord.Lid = lid; + status = omgt_sa_get_sysimageguid_records(port, &selector, &num_records, (uint64_t **)&sa_records); + } else if (!strcmp(type, "nodeguid")){ + /* Valid Input Types: + * NoInput, NodeType, SystemImageGuid, NodeGuid, PortGuid, Lid, NodeDesc + */ + if (selector.InputType == InputTypePortGuid) selector.InputValue.NodeRecord.NodeGUID = guid; + if (selector.InputType == InputTypeLid) selector.InputValue.NodeRecord.Lid = lid; + status = omgt_sa_get_nodeguid_records(port, &selector, &num_records, (uint64_t **)&sa_records); + } else if (!strcmp(type, "portguid")){ + /* Valid Input Types: + * NoInput, NodeType, SystemImageGuid, NodeGuid, PortGuid, Lid, NodeDesc + */ + if (selector.InputType == InputTypePortGuid) selector.InputValue.NodeRecord.NodeGUID = guid; + if (selector.InputType == InputTypeLid) selector.InputValue.NodeRecord.Lid = lid; + status = omgt_sa_get_portguid_records(port, &selector, &num_records, (uint64_t **)&sa_records); + } else if (!strcmp(type, "classportinfo")){ + /*Valid Input Types: NoInput*/ + status = omgt_sa_get_classportinfo_records(port, &selector, &num_records, (STL_CLASS_PORT_INFO **)&sa_records); + } else if (!strcmp(type, "lid")){ + /* Valid Input Types: + * NoInput, NodeType, SystemImageGuid, NodeGuid, PortGuid, Lid, NodeDesc + */ + if (selector.InputType == InputTypePortGuid) selector.InputValue.NodeRecord.NodeGUID = guid; + if (selector.InputType == InputTypeLid) selector.InputValue.NodeRecord.Lid = lid; + status = omgt_sa_get_lid_records(port, &selector, &num_records, (uint32 **)&sa_records); + } else if (!strcmp(type, "desc")){ + /* Valid Input Types: + * NoInput, NodeType, SystemImageGuid, NodeGuid, PortGuid, Lid, NodeDesc + */ + if (selector.InputType == InputTypePortGuid) selector.InputValue.NodeRecord.NodeGUID = guid; + if (selector.InputType == InputTypeLid) selector.InputValue.NodeRecord.Lid = lid; + status = omgt_sa_get_nodedesc_records(port, &selector, &num_records, (STL_NODE_DESCRIPTION **)&sa_records); + } else if (!strcmp(type, "path")){ + /* Valid Input Types: + * NoInput, PortGuid, PortGid, PortGuidPair, GidPair, PathRecord, + * Lid, PKey, SL, ServiceId + * + * SourceGid is not treated as an InputType but is ALWAYS required when querying path/trace records + */ + if (selector.InputType == InputTypePortGuid) { + selector.InputValue.IbPathRecord.PortGuid.DestPortGuid = guid; + selector.InputValue.IbPathRecord.PortGuid.SourcePortGuid = local_guid; + selector.InputValue.IbPathRecord.PortGuid.SharedSubnetPrefix = local_prefix; + } else if (selector.InputType == InputTypeLid) { + selector.InputValue.IbPathRecord.Lid.DLid = lid; + selector.InputValue.IbPathRecord.Lid.SourceGid.Type.Global.InterfaceID = local_guid; + selector.InputValue.IbPathRecord.Lid.SourceGid.Type.Global.SubnetPrefix = local_prefix; + } else { + selector.InputValue.IbPathRecord.SourceGid.Type.Global.InterfaceID = local_guid; + selector.InputValue.IbPathRecord.SourceGid.Type.Global.SubnetPrefix = local_prefix; + } + status = omgt_sa_get_ib_path_records(port, &selector, &num_records, (IB_PATH_RECORD **)&sa_records); + } else if (!strcmp(type, "sminfo")){ + /* Valid Input Types: NoInput */ + status = omgt_sa_get_sminfo_records(port, &selector, &num_records, (STL_SMINFO_RECORD **)&sa_records); + } else if (!strcmp(type, "link")){ + /* Valid Input Types: NoInput, Lid */ + if (selector.InputType == InputTypeLid) selector.InputValue.LinkRecord.Lid = lid; + status = omgt_sa_get_link_records(port, &selector, &num_records, (STL_LINK_RECORD **)&sa_records); + } else if (!strcmp(type, "service")){ + /* Valid Input Types: NoInput, PortGid */ + status = omgt_sa_get_service_records(port, &selector, &num_records, (IB_SERVICE_RECORD **)&sa_records); + } else if (!strcmp(type, "mcmember")){ + // must check if SA supports these records + omgt_sa_selector_t pre_select = {.InputType = InputTypeNoInput}; + status = omgt_sa_get_classportinfo_records(port, &pre_select, &num_records, (STL_CLASS_PORT_INFO **)&sa_records); + + if (OMGT_STATUS_SUCCESS != status || num_records != 1){ + fprintf(stderr, "Failed to determine SA capabilities for mcmember query\n"); + goto fail2; + }else if (! (((STL_CLASS_PORT_INFO **)&sa_records)[0]->CapMask & STL_SA_CAPABILITY_MULTICAST_SUPPORT )){ + fprintf(stderr, "mcmember records not supported by SA\n"); + goto fail2; + } + + if (selector.InputType == InputTypeLid) selector.InputValue.IbMcMemberRecord.Lid = lid; + status = omgt_sa_get_ib_mcmember_records(port, &selector, &num_records, (IB_MCMEMBER_RECORD **)&sa_records); + } else if (!strcmp(type, "inform")){ + /* Valid Input Types: NoInput, PortGid */ + if (selector.InputType == InputTypeLid) selector.InputValue.StlInformInfoRecord.SubscriberLID = lid; + status = omgt_sa_get_informinfo_records(port, &selector, &num_records, (STL_INFORM_INFO_RECORD **)&sa_records); + } else if (!strcmp(type, "trace")){ + /* Valid Input Types: PathRecord, PortGuid, GidPair, PortGid */ + /* SourceGid is not treated as an InputType but is ALWAYS required when querying path/trace records */ + if (selector.InputType == InputTypePortGuid) { + selector.InputValue.TraceRecord.PortGuid.DestPortGuid = guid; + selector.InputValue.TraceRecord.PortGuid.SourcePortGuid = local_guid; + selector.InputValue.TraceRecord.PortGuid.SharedSubnetPrefix = local_prefix; + } else if (selector.InputType == InputTypeLid) { + selector.InputValue.TraceRecord.Lid.DLid = lid; + selector.InputValue.TraceRecord.Lid.SourceGid.Type.Global.InterfaceID = local_guid; + selector.InputValue.TraceRecord.Lid.SourceGid.Type.Global.SubnetPrefix = local_prefix; + } + status = omgt_sa_get_trace_records(port, &selector, &num_records, (STL_TRACE_RECORD **)&sa_records); + } else if (!strcmp(type, "scsc")){ + /* Valid Input Types: NoInput, Lid */ + if (selector.InputType == InputTypeLid) selector.InputValue.ScScTableRecord.Lid = lid; + status = omgt_sa_get_scsc_table_records(port, &selector, &num_records, (STL_SC_MAPPING_TABLE_RECORD **)&sa_records); + } else if (!strcmp(type, "slsc")){ + /* Valid Input Types: NoInput, Lid */ + if (selector.InputType == InputTypeLid) selector.InputValue.SlScTableRecord.Lid = lid; + status = omgt_sa_get_slsc_table_records(port, &selector, &num_records, (STL_SL2SC_MAPPING_TABLE_RECORD **)&sa_records); + } else if (!strcmp(type, "scsl")){ + /* Valid Input Types: NoInput, Lid */ + if (selector.InputType == InputTypeLid) selector.InputValue.ScSlTableRecord.Lid = lid; + status = omgt_sa_get_scsl_table_records(port, &selector, &num_records, (STL_SC2SL_MAPPING_TABLE_RECORD **)&sa_records); + } else if (!strcmp(type, "scvlt")){ + /* Valid Input Types: NoInput, Lid */ + if (selector.InputType == InputTypeLid) selector.InputValue.ScVlxTableRecord.Lid = lid; + status = omgt_sa_get_scvlt_table_records(port, &selector, &num_records, (STL_SC2PVL_T_MAPPING_TABLE_RECORD **)&sa_records); + } else if (!strcmp(type, "scvlr")){ + /* Valid Input Types: NoInput, Lid */ + if (selector.InputType == InputTypeLid) selector.InputValue.ScVlxTableRecord.Lid = lid; + status = omgt_sa_get_scvlr_table_records(port, &selector, &num_records, (STL_SC2PVL_R_MAPPING_TABLE_RECORD **)&sa_records); + } else if (!strcmp(type, "scvlnt")){ + /* Valid Input Types: NoInput, Lid */ + if (selector.InputType == InputTypeLid) selector.InputValue.ScVlxTableRecord.Lid = lid; + status = omgt_sa_get_scvlnt_table_records(port, &selector, &num_records, (STL_SC2PVL_NT_MAPPING_TABLE_RECORD **)&sa_records); + } else if (!strcmp(type, "swinfo")){ + /* Valid Input Types: NoInput, Lid */ + if (selector.InputType == InputTypeLid) selector.InputValue.SwitchInfoRecord.Lid = lid; + status = omgt_sa_get_switchinfo_records(port, &selector, &num_records, (STL_SWITCHINFO_RECORD **)&sa_records); + } else if (!strcmp(type, "linfdb")){ + /* Valid Input Types: NoInput, Lid*/ + if (selector.InputType == InputTypeLid) selector.InputValue.LinFdbTableRecord.Lid = lid; + status = omgt_sa_get_lfdb_records(port, &selector, &num_records, (STL_LINEAR_FORWARDING_TABLE_RECORD **)&sa_records); + } else if (!strcmp(type, "mcfdb")){ + /* Valid Input Types: NoInput, Lid */ + if (selector.InputType == InputTypeLid) selector.InputValue.McFdbTableRecord.Lid = lid; + status = omgt_sa_get_mcfdb_records(port, &selector, &num_records, (STL_MULTICAST_FORWARDING_TABLE_RECORD **)&sa_records); + } else if (!strcmp(type, "vlarb")){ + /* Valid Input Types: NoInput, Lid */ + if (selector.InputType == InputTypeLid) selector.InputValue.VlArbTableRecord.Lid = lid; + status = omgt_sa_get_vlarb_records(port, &selector, &num_records, (STL_VLARBTABLE_RECORD **)&sa_records); + } else if (!strcmp(type, "pkey")){ + /* Valid Input Types: NoInput, Lid */ + if (selector.InputType == InputTypeLid) selector.InputValue.PKeyTableRecord.Lid = lid; + status = omgt_sa_get_pkey_table_records(port, &selector, &num_records, (STL_P_KEY_TABLE_RECORD **)&sa_records); + } else if (!strcmp(type, "vfinfo")){ + /* Valid Input Types: + * NoInput, PKey, SL, ServiceID, McGid, Index, NodeDesc + */ + status = omgt_sa_get_vfinfo_records(port, &selector, &num_records, (STL_VFINFO_RECORD **)&sa_records); + } else if (!strcmp(type, "fabricinfo")){ + /* Valid Input Types: NoInput */ + status = omgt_sa_get_fabric_info_records(port, &selector, &num_records, (STL_FABRICINFO_RECORD **)&sa_records); + } else if (!strcmp(type, "quarantine")){ + /* Valid Input Types: NoInput */ + status = omgt_sa_get_quarantinenode_records(port, &selector, &num_records, (STL_QUARANTINED_NODE_RECORD **)&sa_records); + } else if (!strcmp(type, "conginfo")){ + /* Valid Input Types: NoInput, Lid */ + if (selector.InputType == InputTypeLid) selector.InputValue.CongInfoRecord.Lid = lid; + status = omgt_sa_get_conginfo_records(port, &selector, &num_records, (STL_CONGESTION_INFO_RECORD **)&sa_records); + } else if (!strcmp(type, "swcongset")){ + /* Valid Input Types: NoInput, Lid */ + if (selector.InputType == InputTypeLid) selector.InputValue.SwCongRecord.Lid = lid; + status = omgt_sa_get_swcong_records(port, &selector, &num_records, (STL_SWITCH_CONGESTION_SETTING_RECORD **)&sa_records); + } else if (!strcmp(type, "swportcong")){ + /* Valid Input Types: NoInput, Lid */ + if (selector.InputType == InputTypeLid) selector.InputValue.SwPortCongRecord.Lid = lid; + status = omgt_sa_get_swportcong_records(port, &selector, &num_records, (STL_SWITCH_PORT_CONGESTION_SETTING_RECORD **)&sa_records); + } else if (!strcmp(type, "hficongset")){ + /* Valid Input Types: NoInput, Lid */ + if (selector.InputType == InputTypeLid) selector.InputValue.HFICongRecord.Lid = lid; + status = omgt_sa_get_hficong_records(port, &selector, &num_records, (STL_HFI_CONGESTION_SETTING_RECORD **)&sa_records); + } else if (!strcmp(type, "hficongcon")){ + /* Valid Input Types: NoInput, Lid */ + if (selector.InputType == InputTypeLid) selector.InputValue.HFICongCtrlRecord.Lid = lid; + status = omgt_sa_get_hficongctrl_records(port, &selector, &num_records, (STL_HFI_CONGESTION_CONTROL_TABLE_RECORD **)&sa_records); + } else if (!strcmp(type, "bfrctrl")){ + /* Valid Input Types: NoInput, Lid */ + if (selector.InputType == InputTypeLid) selector.InputValue.BufCtrlTableRecord.Lid = lid; + status = omgt_sa_get_buffctrl_records(port, &selector, &num_records, (STL_BUFFER_CONTROL_TABLE_RECORD **)&sa_records); + } else if (!strcmp(type, "cableinfo")){ + /* Valid Input Types: NoInput, Lid */ + if (selector.InputType == InputTypeLid) selector.InputValue.CableInfoRecord.Lid = lid; + status = omgt_sa_get_cableinfo_records(port, &selector, &num_records, (STL_CABLE_INFO_RECORD **)&sa_records); + } else if (!strcmp(type, "portgroup")){ + /* Valid Input Types: NoInput, Lid */ + if (selector.InputType == InputTypeLid) selector.InputValue.PortGroupRecord.Lid = lid; + status = omgt_sa_get_portgroup_records(port, &selector, &num_records, (STL_PORT_GROUP_TABLE_RECORD **)&sa_records); + } else if (!strcmp(type, "portgroupfdb")){ + /* Valid Input Types: NoInput, Lid */ + if (selector.InputType == InputTypeLid) selector.InputValue.PortGroupFwdRecord.Lid = lid; + status = omgt_sa_get_portgroupfwd_records(port, &selector, &num_records, (STL_PORT_GROUP_FORWARDING_TABLE_RECORD **)&sa_records); + } else if (!strcmp(type, "dglist")){ + /* Valid Input Types: NoInput */ + status = omgt_sa_get_devicegroupname_records(port, &selector, &num_records, (STL_DEVICE_GROUP_NAME_RECORD **)&sa_records); + } else if (!strcmp(type, "dgmember")){ + /* Valid Input Types: NoInput, Lid, PortGuid, NodeDesc, DeviceGroup */ + if (selector.InputType == InputTypeLid) selector.InputValue.DgGrpMemberRecord.Lid = lid; + if (selector.InputType == InputTypePortGuid) selector.InputValue.DgGrpMemberRecord.Guid = guid; + status = omgt_sa_get_devicegroupmember_records(port, &selector, &num_records, (STL_DEVICE_GROUP_MEMBER_RECORD **)&sa_records); + } else if (!strcmp(type, "dtree")){ + /* Valid Input Types: NoInput, Lid */ + if (selector.InputType == InputTypeLid) selector.InputValue.DgTreeMemberRecord.Lid = lid; + status = omgt_sa_get_devicetreemember_records(port, &selector, &num_records, (STL_DEVICE_TREE_MEMBER_RECORD **)&sa_records); + } else if (!strcmp(type, "swcost")){ + /* Valid Input Types: NoInput, Lid */ + if (selector.InputType == InputTypeLid) selector.InputValue.SwitchCostRecord.Lid = lid; + status = omgt_sa_get_switchcost_records(port, &selector, &num_records, (STL_SWITCH_COST_RECORD **)&sa_records); + } + + + if (OMGT_STATUS_SUCCESS != status) { + fprintf(stderr, "failed to execute query. MadStatus=0x%x\n", omgt_get_sa_mad_status(port)); + exitcode = 2; + + /* Not used in oob mode */ + if (!oob_addr) { + /* Check if failure was related to SA service state */ + status = omgt_port_get_sa_service_state(port, &sa_service_state, OMGT_REFRESH_SERVICE_NOP); + if (status == OMGT_STATUS_SUCCESS) { + if (sa_service_state != OMGT_SERVICE_STATE_OPERATIONAL) { + fprintf(stderr, "SA service state is Not Operational: %s (%d)\n", + omgt_service_state_totext(sa_service_state), sa_service_state); + exitcode = 1; + goto fail2; + } + } else { + fprintf(stderr, "failed to get SA service state: %s (%u)\n", + omgt_status_totext(status), status); + exitcode = 1; + goto fail2; + } + } + } else { + printf("Number of records returned: %d\n", num_records); + } + +fail2: + // free our result buffer... + if (sa_records) omgt_sa_free_records(sa_records); + // ...and close our session + omgt_close_port(port); +fail1: + return exitcode; +} diff --git a/opamgt/samples/show_switch_cost_matrix.c b/opamgt/samples/show_switch_cost_matrix.c new file mode 100644 index 0000000..3aac237 --- /dev/null +++ b/opamgt/samples/show_switch_cost_matrix.c @@ -0,0 +1,326 @@ +/* Query SA for Switch Cost Matrix data + * and print it to a file. Monitor for any + * changes and update. + * + */ +// core API +#include +// swcost query +#include +// fabric change notice +#include + +#include + +typedef struct opa_switch{ + STL_LID lid; + const char * name; + struct opa_switch *next; +}opa_switch; + +FILE * matrix_file; + +void free_cost(uint16_t ***cost, int num_rows){ + int i; + + if (!*cost) return; + + for(i = 0; i < num_rows; ++i) { + if ((*cost)[i]) { + free((*cost)[i]); + (*cost)[i] = NULL; + } + } + free(*cost); + *cost = NULL; +} + +void free_switch_list(opa_switch **switchlist_head) +{ + if (!*switchlist_head) return; + opa_switch * temp = *switchlist_head, *temp2; + while(temp){ + temp2 = temp->next; + free(temp); + temp = temp2; + } + *switchlist_head = NULL; +} + +/* Helper function to get the associated name for a particular lid + */ +const char * get_name(STL_LID lid, STL_NODE_RECORD *node_records, int num_node_records) +{ + int i; + for (i = 0; i < num_node_records; ++i) { + if (node_records[i].RID.LID == lid) + return (const char*) node_records[i].NodeDesc.NodeString; + } + return ""; +} + +/* Print Cost Matrix using the Switch Names + */ +void print_matrix(uint16_t **cost, opa_switch *switchlist_head) +{ + fprintf(matrix_file, "%64s", ""); + opa_switch * iter = switchlist_head; + while(iter){ + // Node Descriptions are up to 64 bytes + fprintf(matrix_file, "%64s", iter->name); + iter = iter->next; + } + fprintf(matrix_file, "\n"); + + iter = switchlist_head; + opa_switch * iter2; + while(iter) { + fprintf(matrix_file, "%-64s", iter->name); + iter2 = switchlist_head; + while(iter2) { + if(cost[iter->lid]) + fprintf(matrix_file, "%64d" , cost[iter->lid][iter2->lid]); + iter2 = iter2->next; + } + iter = iter->next; + fprintf(matrix_file, "\n"); + } + fprintf(matrix_file, "\n\n\n"); +} + + +int main(int argc, char **argv) +{ + OMGT_STATUS_T status = OMGT_STATUS_SUCCESS; + int exitcode = 0; + + struct omgt_port *port = NULL; + omgt_sa_selector_t selector; + + int num_classportinfo_records, num_fabricinfo_records, num_cost_records, num_switch_records; + int num_nodes = 0; + + STL_CLASS_PORT_INFO *classportinfo_records = NULL; + STL_FABRICINFO_RECORD *fabricinfo_records = NULL; + STL_SWITCH_COST_RECORD *cost_records = NULL; + STL_NODE_RECORD *switch_records = NULL; + + STL_NOTICE *notice = NULL; + size_t notice_len = 0; + struct omgt_port *context = NULL; + + uint16_t **cost = NULL; + int i,j; + + if (argc < 2) { + fprintf(stderr, "Usage: %s \n", argv[0]); + exitcode = 1; + goto done; + } + + matrix_file = fopen(argv[1], "w"); + if (!matrix_file) { + fprintf(stderr, "could not open output file for writing\n"); + exitcode = 1; + goto done; + } + + // create a session + status = omgt_open_port_by_num(&port, 1, 1, NULL); + if (OMGT_STATUS_SUCCESS != status) { + fprintf(stderr, "failed to open port\n"); + exitcode = 1; + goto close_file; + } + + // Determine if SA has Switch Cost Record capabiility + selector.InputType = InputTypeNoInput; + status = omgt_sa_get_classportinfo_records(port, &selector, &num_classportinfo_records, &classportinfo_records); + if (OMGT_STATUS_SUCCESS != status || num_classportinfo_records != 1) { + fprintf(stderr, "failed to execute classportinfo record query. MADStatus=0x%x\n", omgt_get_sa_mad_status(port)); + exitcode = 1; + goto close_port; + } + + if (! (classportinfo_records[0].CapMask && STL_SA_CAPABILITY2_SWCOSTRECORD_SUPPORT)) { + fprintf(stderr, "SA does not support switchcost records\n"); + exitcode = 1; + goto close_port; + } + + // Register for Cost Matrix Change Trap + if ((status = omgt_sa_register_trap(port, STL_TRAP_COST_MATRIX_CHANGE, port)) != OMGT_STATUS_SUCCESS) { + fprintf(stderr, " Error: Could not register for Trap %u: %s (%u)\n", + STL_TRAP_COST_MATRIX_CHANGE, omgt_status_totext(status), status); + exitcode = 1; + goto close_port; + } + + opa_switch *head_switch = NULL, *temp_switch = NULL; + while(!exitcode){ + selector.InputType = InputTypeNoInput; + + /* Query SA for fabric information to determine how big to make + * our own cost matrix storage + */ + status = omgt_sa_get_fabric_info_records(port, &selector, &num_fabricinfo_records, &fabricinfo_records); + if (OMGT_STATUS_SUCCESS != status || num_fabricinfo_records < 1) { + fprintf(stderr, "failed to get fabricinfo. MADStatus=0x%x\n", omgt_get_sa_mad_status(port)); + exitcode = 1; + goto cleanup; + } + + /* Using total number of nodes will allocate more space than necessary, + * but allows simpler processing of cost data + */ + num_nodes = fabricinfo_records[0].NumSwitches + fabricinfo_records[0].NumHFIs; + if ((cost = calloc(1, num_nodes * sizeof(uint16_t*))) == NULL) { + fprintf(stderr, "failed to allocate memory\n"); + exitcode = 1; + goto cleanup; + } + + /* Query SA for switch records so we can have the names of the switches + * as the cost records are defined with LIDs + */ + selector.InputType = InputTypeNodeType; // select records by type + selector.InputValue.NodeRecord.NodeType = IBA_NODE_SWITCH; // select only Switches + status = omgt_sa_get_node_records(port, &selector, &num_switch_records, &switch_records); + if (OMGT_STATUS_SUCCESS != status) { + fprintf(stderr, "failed to execute node record query. MADStatus=0x%x\n", omgt_get_sa_mad_status(port)); + exitcode = 1; + goto cleanup; + } + + /* Create a linked list of switches in this fabric + */ + for (i = 0; i < num_switch_records; ++i) { + opa_switch * next_switch; + if ((next_switch = malloc(sizeof(opa_switch))) == NULL) { + fprintf(stderr, "failed to allocate memory\n"); + exitcode = 1; + goto cleanup; + } + + next_switch->lid = switch_records[i].RID.LID; + next_switch->name = get_name(switch_records[i].RID.LID, switch_records, num_switch_records); + next_switch->next = NULL; + + if (temp_switch) + temp_switch->next = next_switch; + else + head_switch = next_switch; + + temp_switch = next_switch; + } + temp_switch = NULL; + + // reset selector to appropriate type for cost query + selector.InputType = InputTypeNoInput; + status = omgt_sa_get_switchcost_records(port, &selector, &num_cost_records, &cost_records); + if (OMGT_STATUS_SUCCESS != status) { + fprintf(stderr, "failed to execute cost record query. MADStatus=0x%x\n", omgt_get_sa_mad_status(port)); + exitcode = 1; + goto cleanup; + } + + /* Copy returned Cost matrix data into our own format + * When requesting the entire matrix, only the lower + * diagonal is returned as it is symmetric + */ + int slid, dlid; + STL_SWITCH_COST_RECORD cost_record; + for (i = 0; i < num_cost_records; ++i) { + cost_record = cost_records[i]; + slid = cost_record.SLID; + /* Cost records contain 64 entries, but all may not be filled + * Checking the DLID is > 0 ensures the entry is valid + */ + for (j = 0; j < STL_SWITCH_COST_NUM_ENTRIES && cost_record.Cost[j].DLID > 0; ++j) { + dlid = cost_record.Cost[j].DLID; + + // Initialize all entries in cost to zero. + // The entries of interest will be overwritten with + // actual cost values from the SA + if (!cost[slid]) { + if ((cost[slid] = calloc(1, num_nodes * sizeof(uint16_t))) == NULL) { + fprintf(stderr, "failed to allocate memory\n"); + exitcode = 1; + goto cleanup; + } + } + if (!cost[dlid]) { + if ((cost[dlid] = calloc(1, num_nodes * sizeof(uint16_t))) == NULL) { + fprintf(stderr, "failed to allocate memory\n"); + exitcode = 1; + goto cleanup; + } + } + // add this cost to matrix for slid/dlid + cost[slid][dlid] = cost[dlid][slid] = cost_record.Cost[j].value; + } + } + + print_matrix(cost, head_switch); + + printf("\nMonitoring for any changes...\n"); + fflush(matrix_file); + + // monitor cluster for changes, -1 = indefinite wait time + if ((status = omgt_sa_get_notice_report(port, ¬ice, ¬ice_len, (void **)&context, -1)) != OMGT_STATUS_SUCCESS) { + fprintf(stderr, "Error: Could not wait for Notice: %s (%u)\n", + omgt_status_totext(status), status); + exitcode = 1; + goto cleanup; + } + + // we only registered for Cost Matrix Change notice, if we got something else it's an error + if (notice->Attributes.Generic.TrapNumber != STL_TRAP_COST_MATRIX_CHANGE) { + fprintf(stderr, "Unhandled Trap Received: %u\n", notice->Attributes.Generic.TrapNumber); + exitcode = 1; + goto cleanup; + } + +cleanup: + if (notice) { + free(notice); + notice = NULL; + } + + if (fabricinfo_records) { + omgt_sa_free_records(fabricinfo_records); + fabricinfo_records = NULL; + } + if (cost_records) { + omgt_sa_free_records(cost_records); + cost_records = NULL; + } + if (switch_records) { + omgt_sa_free_records(switch_records); + switch_records = NULL; + } + + free_switch_list(&head_switch); + free_cost(&cost, num_nodes); + + } //end while + + + if ((status = omgt_sa_unregister_trap(port, STL_TRAP_COST_MATRIX_CHANGE)) != OMGT_STATUS_SUCCESS) { + fprintf(stderr, "Error: Could not unregister for Trap %u: %s (%u)\n", + STL_TRAP_COST_MATRIX_CHANGE, omgt_status_totext(status), status); + if (!exitcode) exitcode = 1; + } + +close_port: + if (classportinfo_records) omgt_sa_free_records(classportinfo_records); + + //close our session + omgt_close_port(port); + +close_file: + fclose(matrix_file); + +done: + return exitcode; +} diff --git a/opamgt/samples/simple_pa_query.c b/opamgt/samples/simple_pa_query.c new file mode 100644 index 0000000..8e3229e --- /dev/null +++ b/opamgt/samples/simple_pa_query.c @@ -0,0 +1,58 @@ +/* This file shows a simple example of requesting and printing OPA + * port counters data + * + */ + +//core API +#include +//extensions for PA queries +#include +#include + + +int main() +{ + struct omgt_port * port = NULL; + OMGT_STATUS_T status; + int exitcode = 0; + + STL_PA_IMAGE_ID_DATA image_ID = {0}; + STL_PA_IMAGE_INFO_DATA image_info; + + status = omgt_open_port_by_num(&port, 1, 1, NULL); + if(OMGT_STATUS_SUCCESS != status) { + fprintf(stderr, "Failed to open port or initialize PA connection\n"); + exitcode=1; + goto fail1; + } + + if (omgt_pa_get_image_info(port, image_ID, &image_info)){ + fprintf(stderr, "Failed to get PA image\n"); + exitcode=1; + goto fail2; + } + + printf("Sweep start: %s", ctime((time_t *)&image_info.sweepStart)); + + STL_PORT_COUNTERS_DATA port_counters; + /*loop here, collecting counters and storing or displaying*/ + /*maybe show capability to get specific images*/ + if (omgt_pa_get_port_stats2(port, image_ID, 1, 1, &image_ID, &port_counters, NULL, 0, 1)){ + fprintf(stderr, "Failed to get port counters\n"); + exitcode=1; + goto fail2; + } + + printf("Port Counters Data:\n"); + printf("portXmitData: %"PRIu64"\n", port_counters.portXmitData); + printf("portRcvData: %"PRIu64"\n", port_counters.portRcvData); + printf("portXmitPkts: %"PRIu64"\n", port_counters.portXmitPkts); + printf("portRcvPkts: %"PRIu64"\n", port_counters.portRcvPkts); + printf("localLinkIntegrityErrors: %"PRIu64"\n", port_counters.localLinkIntegrityErrors); + printf("linkDowned: %u\n", port_counters.linkDowned); + +fail2: + omgt_close_port(port); +fail1: + return exitcode; +} diff --git a/opamgt/samples/simple_sa_notice.c b/opamgt/samples/simple_sa_notice.c new file mode 100644 index 0000000..c7e7d43 --- /dev/null +++ b/opamgt/samples/simple_sa_notice.c @@ -0,0 +1,117 @@ +// core API +#include +// extensions for SA Notices +#include + +// extension to print gid using inet_ntop() +#include + + +int main(void) +{ + int exit_code = 0; + struct omgt_port *port = NULL; + OMGT_STATUS_T status; + + STL_NOTICE *notice = NULL; + size_t notice_len = 0; + struct omgt_port *context = NULL; + + /* Set Init Params */ + struct omgt_params params = {0}; + params.error_file = stderr; + params.debug_file = NULL; + /* Open in-band port */ + if ((status = omgt_open_port(&port, "hfi1_0", 1, ¶ms)) != OMGT_STATUS_SUCCESS) { + fprintf(stderr, "Error: Could not open port: %s (%u)\n", + omgt_status_totext(status), status); + return 1; + } + + /* Register for Traps (Node Appear | Node Disappear) */ + if ((status = omgt_sa_register_trap(port, STL_TRAP_GID_NOW_IN_SERVICE, port)) != OMGT_STATUS_SUCCESS) { + fprintf(stderr, "Error: Could not register for Trap %u: %s (%u)\n", + STL_TRAP_GID_NOW_IN_SERVICE, omgt_status_totext(status), status); + exit_code = 1; + goto close_port; + } + if ((status = omgt_sa_register_trap(port, STL_TRAP_GID_OUT_OF_SERVICE, port)) != OMGT_STATUS_SUCCESS) { + fprintf(stderr, "Error: Could not register for Trap %u: %s (%u)\n", + STL_TRAP_GID_OUT_OF_SERVICE, omgt_status_totext(status), status); + exit_code = 1; + goto unreg_trap1; + } + + /* Wait for Trap (-1 = indefinite wait time) */ + if ((status = omgt_sa_get_notice_report(port, ¬ice, ¬ice_len, (void **)&context, -1)) != OMGT_STATUS_SUCCESS) { + fprintf(stderr, "Error: Could not wait for Notice: %s (%u)\n", + omgt_status_totext(status), status); + exit_code = 1; + goto unreg_trap2; + } + if (notice_len < sizeof(STL_NOTICE)) { + fprintf(stderr, "Error: Could not get Notice: Returned Length is less than expected: %zu < %zu\n", + notice_len, sizeof(STL_NOTICE)); + exit_code = 2; + goto free_notice; + } + if (port != context) { + fprintf(stderr, "Error: Could not get Notice: Returned context (%p) is not port (%p)\n", + context, port); + exit_code = 2; + goto free_notice; + } + + /* Check Trap Number */ + switch (notice->Attributes.Generic.TrapNumber) { + case STL_TRAP_GID_NOW_IN_SERVICE: + /* New Node Appears */ + { + char gid_buf[46] = {0}; + STL_TRAP_GID *new_gid = (STL_TRAP_GID *)¬ice->Data[0]; + fprintf(stderr, "New Node: %s\n", + inet_ntop(AF_INET6, new_gid, gid_buf, sizeof(gid_buf))); + } + break; + case STL_TRAP_GID_OUT_OF_SERVICE: + /* Node Disapears */ + { + char gid_buf[46] = {0}; + STL_TRAP_GID *new_gid = (STL_TRAP_GID *)¬ice->Data[0]; + fprintf(stderr, "Node Disappears: %s\n", + inet_ntop(AF_INET6, new_gid, gid_buf, sizeof(gid_buf))); + } + break; + default: + fprintf(stderr, "Unhandled Trap Received: %u\n", notice->Attributes.Generic.TrapNumber); + exit_code = 3; + } + + /* Clean Up Notice */ +free_notice: + if (notice) { + free(notice); + notice = NULL; + } + + /* Unregister Traps */ +unreg_trap2: + if ((status = omgt_sa_unregister_trap(port, STL_TRAP_GID_OUT_OF_SERVICE)) != OMGT_STATUS_SUCCESS) { + fprintf(stderr, "Error: Could not unregister for Trap %u: %s (%u)\n", + STL_TRAP_GID_OUT_OF_SERVICE, omgt_status_totext(status), status); + if (!exit_code) exit_code = 1; + } +unreg_trap1: + if ((status = omgt_sa_unregister_trap(port, STL_TRAP_GID_NOW_IN_SERVICE)) != OMGT_STATUS_SUCCESS) { + fprintf(stderr, "Error: Could not unregister for Trap %u: %s (%u)\n", + STL_TRAP_GID_NOW_IN_SERVICE, omgt_status_totext(status), status); + if (!exit_code) exit_code = 1; + } + + /* Close port */ +close_port: + omgt_close_port(port); + port = NULL; + + return exit_code; +} diff --git a/opamgt/samples/simple_sa_query.c b/opamgt/samples/simple_sa_query.c new file mode 100644 index 0000000..a4a2432 --- /dev/null +++ b/opamgt/samples/simple_sa_query.c @@ -0,0 +1,63 @@ +// core API +#include +// extensions for SA queries +#include + +int main(int argc, char ** argv) +{ + OMGT_STATUS_T status = OMGT_STATUS_SUCCESS; + int exitcode = 0; + int i; + struct omgt_port * port = NULL; + int num_records; + STL_PORTINFO_RECORD *pi_records = NULL; + + + // create a session + status = omgt_open_port_by_num(&port, 1 /* hfi */, 1 /* port */, NULL); + if (OMGT_STATUS_SUCCESS != status) { + fprintf(stderr, "failed to open port\n"); + exitcode=1; + goto fail1; + } + + + // specify how and what we want to query by + omgt_sa_selector_t selector; + selector.InputType = InputTypeLid; + selector.InputValue.PortInfoRecord.Lid = 1; + + // execute query synchronously + status = omgt_sa_get_portinfo_records(port, &selector, &num_records, &pi_records); + if (status != OMGT_STATUS_SUCCESS) { + exitcode=1; + fprintf(stderr, "failed to execute query. MadStatus=0x%x\n", omgt_get_sa_mad_status(port)); + goto fail2; + } + + if (!num_records) { + // we can check result count independent of result type + printf("No records found.\n"); + } else { + for (i = 0; i < num_records; ++i) { + // the result is a set of SA records, which often follow a pattern + // of including a RID section containing top-level identification of + // the record, and an encapsulated SM payload. + // + // in this case: + // r->RID: contains the LID and port number as record identifiers + // r->PortInfo: the encapsulated subnet management structure (STL_PORT_INFO) + STL_PORTINFO_RECORD * r = &pi_records[i]; // sa + printf("PortNum: %2u PortLID: 0x%08x\n", r->RID.PortNum, r->RID.EndPortLID); + } + } + +fail2: + // free our result buffer... + if (pi_records) omgt_sa_free_records(pi_records); + // ...and close our session + omgt_close_port(port); +fail1: + return exitcode; +} + diff --git a/opamgt/src/ib_notice.c b/opamgt/src/ib_notice.c new file mode 100644 index 0000000..dd11cc8 --- /dev/null +++ b/opamgt/src/ib_notice.c @@ -0,0 +1,952 @@ +/* BEGIN_ICS_COPYRIGHT5 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + * ** END_ICS_COPYRIGHT5 ****************************************/ +/* [ICS VERSION STRING: unknown] */ + +/* + * OFED "User SA" support. + * + * This module provides userspace access to the "User SA" components, which + * exposes SA Notice multiplexing functionality to userspace. + * + * Note that this implementation follows the opamgt model using the omgt_port + * object to track the connection. It creates the kernel channel on + * initialization and holds it open. Explicit deregistration and shutdown is + * not required, as libibsa and the kernel will automatically clear + * registrations when a channel is closed. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define OPAMGT_PRIVATE 1 + +#include "ib_utils_openib.h" +#include "ib_notice_net.h" +#include "iba/public/ibyteswap.h" +#include "iba/stl_sa_types.h" +#include "iba/stl_mad_priv.h" + +#define OMGT_SA_MAX_REGISTRANTS 10 + +#define OMGT_SA_DEVICE_NAME_LEN_MAX 32 + +#define OMGT_SA_DEFAULT_LOCK_TIMEOUT 5 // seconds + +#ifndef container_of +#define container_of(ptr, type, field) \ + ((type *) ((void *) ptr - offsetof(type, field))) +#endif + +struct ibv_sa_event { + void *context; + int status; + int attr_count; + int attr_size; + int attr_offset; + uint16_t attr_id; + void *attr; +}; +struct omgt_sa_event { + struct ibv_sa_event event; + struct ibv_sa_event_channel *channel; + void *data; +}; + +int omgt_lock_sem(SEMAPHORE* const pSema) +{ + struct timespec ts; + clock_gettime(CLOCK_REALTIME, &ts); + ts.tv_sec += OMGT_SA_DEFAULT_LOCK_TIMEOUT; + int ret; + while ((ret = sem_timedwait(pSema, &ts)) && errno == EINTR) continue; + return ret ? errno : 0; +} + +void omgt_unlock_sem(SEMAPHORE * const pSema) +{ + sem_post(pSema); +} + +/** + * port->lock must be held + */ +static int reg_sa_msg_mr(struct omgt_port *port, struct omgt_sa_msg *msg, + enum ibv_wr_opcode opcode, + uint32_t rem_qpn, uint32_t rem_qkey) +{ + msg->mr = ibv_reg_mr(port->sa_qp_pd, msg->data, sizeof(msg->data), + IBV_ACCESS_LOCAL_WRITE); + if (!msg->mr) { + OMGT_OUTPUT_ERROR(port, "Notice: sa msg register memory region failed\n"); + return (-EIO); + } + + msg->sge.addr = (uint64_t)msg->data; + msg->sge.length = sizeof(msg->data); + msg->sge.lkey = msg->mr->lkey; + msg->in_q = 0; + + if (opcode == IBV_WR_SEND) { + msg->wr.send.wr_id = (uint64_t)msg; + msg->wr.send.next = NULL; + msg->wr.send.sg_list = &msg->sge; + msg->wr.send.num_sge = 1; + msg->wr.send.opcode = IBV_WR_SEND; + msg->wr.send.send_flags = IBV_SEND_SIGNALED; + msg->wr.send.wr.ud.ah = port->sa_ah; + msg->wr.send.wr.ud.remote_qpn = rem_qpn; + msg->wr.send.wr.ud.remote_qkey = rem_qkey; + } else { + msg->wr.recv.wr_id = (uint64_t)msg; + msg->wr.recv.next = NULL; + msg->wr.recv.sg_list = &msg->sge; + msg->wr.recv.num_sge = 1; + } + + return (0); +} + +/** + * port->lock must be held + */ +static struct omgt_sa_msg * alloc_send_sa_msg(struct omgt_port *port) +{ + struct omgt_sa_msg *msg; + + if (!port->sa_ah) { + struct ibv_ah_attr attr; + int err = 0; + memset(&attr, 0, sizeof(attr)); + + attr.dlid = (uint16_t)port->umad_port_cache.sm_lid; + if (omgt_is_ext_lid(port->umad_port_cache.base_lid) || + omgt_is_ext_lid(port->umad_port_cache.sm_lid)) { + attr.is_global = 1; + attr.grh.hop_limit = 1; + attr.grh.sgid_index = 0; + attr.grh.dgid.global.subnet_prefix = + port->umad_port_cache.gid_prefix; + /* Not too sure why ntoh64 is required */ + attr.grh.dgid.global.interface_id = + ntoh64(omgt_create_gid(port->umad_port_cache.sm_lid)); + } + + if ((err = omgt_lock_sem(&port->umad_port_cache_lock)) != 0) { + OMGT_OUTPUT_ERROR(port, "failed to acquire lock (err: %d)\n", err); + return (NULL); + } + attr.sl = port->umad_port_cache.sm_sl; + omgt_unlock_sem(&port->umad_port_cache_lock); + + attr.port_num = port->hfi_port_num; + port->sa_ah = ibv_create_ah(port->sa_qp_pd, &attr); + if (!port->sa_ah) { + OMGT_OUTPUT_ERROR(port, "failed to create SA AH (err: %d)\n", errno); + return (NULL); + } + } + + msg = calloc(1, sizeof(*msg)); + if (!msg) + return (NULL); + + if (reg_sa_msg_mr(port, msg, IBV_WR_SEND, 1, UMAD_QKEY)) { + free(msg); + return (NULL); + } + + msg->prev = msg; + msg->next = msg; + + return (msg); +} + +/** + * port->lock must be held + */ +static void free_sa_msg(struct omgt_sa_msg *msg) +{ + if (msg->mr) + ibv_dereg_mr(msg->mr); + free(msg); +} + + +/** + * Adds a registration to the list. + * NOTE: Caller must hold the lock. + * + * @param port port opened by omgt_open_port_ + * @param reg Pointer to the registration structure. + * + * @return none + */ +void omgt_sa_add_reg_unsafe(struct omgt_port *port, omgt_sa_registration_t *reg) +{ + reg->next = port->regs_list; + port->regs_list = reg; +} + +static void set_sa_msg_tid(struct omgt_port *port, struct umad_sa_packet *sa_pkt) +{ + port->next_tid++; + if (port->next_tid == 0) + port->next_tid++; + sa_pkt->mad_hdr.tid = hton64((uint64_t)port->next_tid); +} + +static void set_sa_common_stl_inform_info(struct omgt_port *port, struct umad_sa_packet *sa_pkt) +{ + STL_INFORM_INFO *informinfo; + + sa_pkt->mad_hdr.base_version = STL_BASE_VERSION; + sa_pkt->mad_hdr.mgmt_class = MCLASS_SUBN_ADM; + sa_pkt->mad_hdr.class_version = STL_SA_CLASS_VERSION; + sa_pkt->mad_hdr.method = MMTHD_SET; + sa_pkt->mad_hdr.attr_id = hton16(STL_MCLASS_ATTRIB_ID_INFORM_INFO); + + sa_pkt->rmpp_hdr.rmpp_version = UMAD_RMPP_VERSION; + sa_pkt->rmpp_hdr.rmpp_type = 0; + + informinfo = (STL_INFORM_INFO *)sa_pkt->data; + + informinfo->LIDRangeBegin = UINT32_MAX; + informinfo->IsGeneric = 1; + informinfo->Type = UINT16_MAX; + informinfo->u.Generic.u2.s.ProducerType = 0xFFFFFF; +} + +static void set_sa_common_stl_response_notice(struct omgt_port *port, struct umad_sa_packet *sa_pkt) +{ + STL_NOTICE *notice; + + sa_pkt->mad_hdr.base_version = STL_BASE_VERSION; + sa_pkt->mad_hdr.mgmt_class = MCLASS_SUBN_ADM; + sa_pkt->mad_hdr.class_version = STL_SA_CLASS_VERSION; + sa_pkt->mad_hdr.method = MMTHD_REPORT_RESP; + sa_pkt->mad_hdr.attr_id = hton16(STL_MCLASS_ATTRIB_ID_NOTICE); + + sa_pkt->rmpp_hdr.rmpp_version = UMAD_RMPP_VERSION; + sa_pkt->rmpp_hdr.rmpp_type = 0; + + notice = (STL_NOTICE *)sa_pkt->data; + + // if the Type is set to 0x7f (empty) all other fields are unused + notice->Attributes.Generic.u.AsReg32 = 0; + notice->Attributes.Generic.u.s.Type = 0x7f; +} + +static void post_send_sa_msg(struct omgt_port *port, + struct omgt_sa_msg *msg, + enum omgt_reg_retry_state resend) +{ + int rc; + struct ibv_send_wr *bad_wr = NULL; + + if (msg->in_q) { + OMGT_OUTPUT_ERROR(port, "msg (%p) is already in the send Q!!!\n", msg); + return; + } + + if (!msg->retries) { + OMGT_OUTPUT_ERROR(port, "msg (%p) has timed out!!!\n", msg); + return; + } + + if (port->outstanding_sends_cnt >= port->num_userspace_send_buf) { + OMGT_OUTPUT_ERROR(port, "no send buffers\n"); + return; + } + + if (OMGT_RRS_SEND_RETRY == resend) { + msg->retries--; + if (!msg->retries) { + OMGT_DBGPRINT(port, "Timeout sending SA msg.\n"); + return; + } + } + set_sa_msg_tid(port, (struct umad_sa_packet *)msg->data); + if ((rc = ibv_post_send(port->sa_qp, &(msg->wr.send), &bad_wr)) == 0) { + port->outstanding_sends_cnt++; + msg->in_q = 1; + } else { + OMGT_OUTPUT_ERROR(port, "Notice: post send WR failed: %s: Aborting send.\n", + strerror(rc)); + } +} + +static int omgt_post_notice_recvs(struct omgt_port *port) +{ + int i = 0; + int post_count = 0; + + /* post recv msgs */ + for (i = 0; i < port->num_userspace_recv_buf; i++) { + if (reg_sa_msg_mr(port, &port->recv_bufs[i], 0, 0, 0)) + goto init_error; + } + for (i = 0; i < port->num_userspace_recv_buf; i++) { + if (ibv_post_recv(port->sa_qp, &port->recv_bufs[i].wr.recv, NULL)) { + port->recv_bufs[i].in_q = 0; + } else { + post_count++; + port->recv_bufs[i].in_q = 1; + } + } + if (!post_count) + goto init_error; + + return (0); + +init_error: + for (/* */; i >= 0; i--) { + ibv_dereg_mr(port->recv_bufs[i].mr); + } + return (-EIO); +} + +static struct omgt_sa_msg * +find_req_by_tid(struct omgt_port *port, uint32_t tid) +{ + struct omgt_sa_msg *rc = NULL; + struct omgt_sa_msg *msg; + + OMGT_DBGPRINT(port, "find req tid 0x%x\n", tid); + + LIST_FOR_EACH(&port->pending_reg_msg_head, msg) { + struct umad_sa_packet *sa_pkt = (struct umad_sa_packet *)msg->data; + uint32_t mtid = ntoh64(sa_pkt->mad_hdr.tid) & 0xffffffff; + OMGT_DBGPRINT(port, "found tid 0x%x\n", mtid); + if (mtid == tid) { + rc = msg; + break; + } + } + + return rc; +} + +static void process_sa_get_resp(struct omgt_port *port, struct umad_sa_packet *sa_pkt) +{ + struct omgt_sa_msg *req; + STL_INFORM_INFO *informinfo = (STL_INFORM_INFO *)sa_pkt->data; + uint16_t trap_num = ntoh16(informinfo->u.Generic.TrapNumber); + + omgt_lock_sem(&port->lock); + + /* find the registration for this response */ + req = find_req_by_tid(port, ntoh64(sa_pkt->mad_hdr.tid) & 0xffffffff); + if (req) { + if (informinfo->Subscribe == 1) { + OMGT_DBGPRINT(port, "registration complete for trap %d; req %p\n", trap_num, req); + } else { + OMGT_DBGPRINT(port, "UN-registration complete for trap %d; req %p\n", trap_num, req); + } + /* Check if the registration has been freed */ + if (req->reg) + req->reg->reg_msg = NULL; + LIST_DEL(req); + free_sa_msg(req); + } else { + OMGT_OUTPUT_ERROR(port, "Unknown get response; 'trap num' %d\n", trap_num); + } + omgt_unlock_sem(&port->lock); +} + +/* Recv'ed messages will a GRH on them or at least space (40 bytes) */ +/* for a GRH which we need to remove. */ +static struct umad_sa_packet * +sa_pkt_from_recv_msg(struct omgt_sa_msg *msg) +{ + return (struct umad_sa_packet *)&msg->data[sizeof(struct ibv_grh)]; +} + +static void process_sa_report(struct omgt_port *port, struct umad_sa_packet *sa_pkt) +{ + struct omgt_sa_msg *response_msg = NULL; + struct umad_sa_packet *response_pkt = NULL; + struct ibv_send_wr *bad_wr = NULL; + + STL_NOTICE *notice = (STL_NOTICE *)sa_pkt->data; + STL_TRAP_GID *notice_gid = (STL_TRAP_GID *)¬ice->Data[0]; + struct omgt_thread_msg thread_msg; + struct iovec iov[2]; + size_t write_count, write_size; + uint16_t trap_num = ntoh16(notice->Attributes.Generic.TrapNumber); + + // create and send ReportResp to trap notify + if (omgt_lock_sem(&port->lock)) { + OMGT_OUTPUT_ERROR(port, "failed to acquire lock (status: %d)\n", FTIMEOUT); + return; + } + + response_msg = alloc_send_sa_msg(port); + if (response_msg) + { + STL_NOTICE *notice_resp; + int rc; + memset(response_msg->data, 0, sizeof(response_msg->data)); + response_pkt = (struct umad_sa_packet *)response_msg->data; + set_sa_common_stl_response_notice(port, response_pkt); + notice_resp = (STL_NOTICE *)response_pkt->data; + BSWAP_STL_NOTICE(notice_resp); + response_pkt->mad_hdr.tid = sa_pkt->mad_hdr.tid; + + if ((rc = ibv_post_send(port->sa_qp, &(response_msg->wr.send), &bad_wr)) != 0) { + OMGT_OUTPUT_ERROR(port, "Notice: post send WR failed: %s: Aborting send.\n", + strerror(rc)); + } + + free_sa_msg(response_msg); + } + omgt_unlock_sem(&port->lock); + + thread_msg.size = sizeof *notice; + thread_msg.evt = OMGT_TH_EVT_TRAP_MSG; + + iov[0].iov_base = &thread_msg; + iov[0].iov_len = sizeof thread_msg; + iov[1].iov_base = notice; + iov[1].iov_len = sizeof *notice; + write_size = iov[0].iov_len + iov[1].iov_len; + + if ( write_size != + (write_count = writev(port->umad_port_sv[1], iov, 2)) ) + OMGT_OUTPUT_ERROR(port, "bad write count %d\n", (int)write_count); + + OMGT_DBGPRINT(port, "process_sa_report: msg queued - trap %d gid %02x%02x%02x%02x%02x%02x%02x%02x\n", + trap_num, notice_gid->Gid.Raw[8], notice_gid->Gid.Raw[9], notice_gid->Gid.Raw[10], notice_gid->Gid.Raw[11], + notice_gid->Gid.Raw[12], notice_gid->Gid.Raw[13], notice_gid->Gid.Raw[14], notice_gid->Gid.Raw[15]); +} + +static void process_sa_rcv_msg(struct omgt_port *port, struct omgt_sa_msg *msg) +{ + struct umad_sa_packet *sa_pkt = sa_pkt_from_recv_msg(msg); + + switch (sa_pkt->mad_hdr.method) { + case UMAD_METHOD_GET_RESP: + process_sa_get_resp(port, sa_pkt); + break; + case UMAD_METHOD_REPORT: + process_sa_report(port, sa_pkt); + break; + default: + OMGT_OUTPUT_ERROR(port, "unknown 'message' received : method 0x%x\n", sa_pkt->mad_hdr.method); + break; + } +} + +int repost_pending_registrations(struct omgt_port *port) +{ + int new_timeout_ms = -1; + struct omgt_sa_msg *msg; + struct omgt_sa_msg *del_msg; + struct omgt_thread_msg thread_msg; + omgt_sa_registration_t *reg; + struct iovec iov[2]; + size_t write_size, write_count; + + omgt_lock_sem(&port->lock); + + LIST_FOR_EACH(&port->pending_reg_msg_head, msg) { + if (msg->retries) { + new_timeout_ms = NOTICE_REG_TIMEOUT_MS; + post_send_sa_msg(port, msg, OMGT_RRS_SEND_RETRY); + } else { + /* + * When the registration is unregistered (in + * userspace_unregister()), msg->reg is NULL and we could not + * send the timeout event anymore (the caller is not waiting + * for notification anymore). + */ + if (msg->reg) { + reg = msg->reg; + thread_msg.size = sizeof *reg; + thread_msg.evt = OMGT_TH_EVT_TRAP_REG_ERR_TIMEOUT; + + iov[0].iov_base = &thread_msg; + iov[0].iov_len = sizeof thread_msg; + iov[1].iov_base = reg; + iov[1].iov_len = sizeof *reg; + write_size = iov[0].iov_len + iov[1].iov_len; + + write_count = writev(port->umad_port_sv[1], iov, 2); + if ( write_size != write_count) + OMGT_OUTPUT_ERROR(port, "bad write count %d\n", + (int)write_count); + } + + // detach the msg to be deleted from the list first + del_msg = msg; + msg = msg->prev; + if (del_msg->reg) { + OMGT_DBGPRINT(port, "registration timeout on trap %d : req %p\n", + del_msg->reg->trap_num, del_msg->reg); + } else { + OMGT_DBGPRINT(port, "registration timeout on trap: No information available.\n"); + } + if (del_msg->reg) + del_msg->reg->reg_msg = NULL; + LIST_DEL(del_msg); + free_sa_msg(del_msg); + } + } + + omgt_unlock_sem(&port->lock); + + return new_timeout_ms; +} + +/* This function is only called after all registrations have been + freed and the port thread has terminated. It is called to free + all pending registration/unregistration messages */ +void omgt_sa_remove_all_pending_reg_msgs(struct omgt_port *port) +{ + struct omgt_sa_msg *msg; + struct omgt_sa_msg *del_msg; + + omgt_lock_sem(&port->lock); + + LIST_FOR_EACH(&port->pending_reg_msg_head, msg) { + /* detach the msg to be deleted from the list first */ + del_msg = msg; + msg = msg->prev; + LIST_DEL(del_msg); + free_sa_msg(del_msg); + } + + omgt_unlock_sem(&port->lock); +} + +static void process_wc(struct omgt_port *port, struct ibv_wc *wc) +{ + struct omgt_sa_msg *msg = (struct omgt_sa_msg *)wc->wr_id; + int i; + if (wc->opcode == IBV_WC_SEND) { + OMGT_DBGPRINT(port, "Notice Send Completion %p : %s\n", + msg, + ibv_wc_status_str(wc->status)); + + omgt_lock_sem(&port->lock); + port->outstanding_sends_cnt--; + msg->in_q = 0; + omgt_unlock_sem(&port->lock); + if (wc->status != IBV_WC_SUCCESS) { + /* Thread will handle reposting */ + OMGT_OUTPUT_ERROR(port, "Notice Send Completion not success : %s... ", + ibv_wc_status_str(wc->status)); + } + } else if (wc->opcode == IBV_WC_RECV) { + OMGT_DBGPRINT(port, "Notice Recv Completion %p flags %d: %s\n", msg, wc->wc_flags, ibv_wc_status_str(wc->status)); + process_sa_rcv_msg(port, msg); + if (ibv_post_recv(port->sa_qp, &msg->wr.recv, NULL)) { + OMGT_OUTPUT_ERROR(port, "Failed to repost recv buffer - mark as unqueued\n"); + msg->in_q = 0; + } else { + msg->in_q = 1; + } + + // If any receive buffers failed to repost cycle through the list here + // and retry the post to keep the buffer queue full. + for (i = 0; i < port->num_userspace_recv_buf; i++) + if (!port->recv_bufs[i].in_q) + if (0 == ibv_post_recv(port->sa_qp, &port->recv_bufs[i].wr.recv, NULL)) { + port->recv_bufs[i].in_q = 1; + } + } else { + OMGT_OUTPUT_ERROR(port, "Unknown work completion event: 0x%x\n", wc->opcode); + } +} + +void handle_sa_ud_qp(struct omgt_port *port) +{ + struct ibv_wc wc; + struct ibv_cq *ev_cq = port->sa_qp_cq; + struct omgt_port *ev_port; + + if (ibv_get_cq_event(port->sa_qp_comp_channel, &ev_cq, (void **)&ev_port)) + goto request_notify; + + ibv_ack_cq_events(ev_cq, 1); + + if (port != ev_port || ev_cq != port->sa_qp_cq) { + OMGT_OUTPUT_ERROR(port, "ibv_get_cq_event failed to get event for our notice/CQ\n"); + goto request_notify; + } + + while (ibv_poll_cq(port->sa_qp_cq, 1, &wc) > 0) { + process_wc(port, &wc); + } + +request_notify: + if (ibv_req_notify_cq(port->sa_qp_cq, 0)) + OMGT_OUTPUT_ERROR(port, "ibv_req_notify_cq failed\n"); +} + +int start_ud_cq_monitor(struct omgt_port *port) +{ + int rc; + struct omgt_thread_msg msg = {0}; + + msg.size = sizeof(msg); + msg.evt = OMGT_TH_EVT_UD_MONITOR_ON; + + rc = write(port->umad_port_sv[0], &msg, sizeof(msg)); + if (rc <= 0) { + OMGT_OUTPUT_ERROR(port, "Failed to start CQ Monitoring...\n"); + return 1; + } + return 0; +} + +int stop_ud_cq_monitor(struct omgt_port *port) +{ + int rc; + struct omgt_thread_msg msg = {0}; + + msg.size = sizeof(msg); + msg.evt = OMGT_TH_EVT_UD_MONITOR_OFF; + + rc = write(port->umad_port_sv[0], &msg, sizeof(msg)); + if (rc <= 0) { + OMGT_OUTPUT_ERROR(port, "Failed to stop CQ Monitoring...\n"); + return 1; + } + return 0; +} + +int create_sa_qp(struct omgt_port *port) +{ + int i; + int flags, rc; + int buf_cnt; + struct ibv_qp_init_attr init_attr = {0}; + struct ibv_qp_attr attr = {0}; + + if (port->sa_qp) { + return 0; + } + + port->sa_qp_comp_channel = ibv_create_comp_channel(port->verbs_ctx); + if (!port->sa_qp_comp_channel) { + OMGT_OUTPUT_ERROR(port, "Notice: create comp_channel failed\n"); + return -EIO; + } + + flags = fcntl(port->sa_qp_comp_channel->fd, F_GETFL); + rc = fcntl(port->sa_qp_comp_channel->fd, F_SETFL, flags | O_NONBLOCK); + if (rc < 0) { + OMGT_OUTPUT_ERROR(port, "Notice: create QP failed\n"); + goto cq_fail; + } + + port->recv_bufs = calloc(port->num_userspace_recv_buf, + sizeof *port->recv_bufs); + if (!port->recv_bufs){ + OMGT_OUTPUT_ERROR(port, "Notice: recv message buffer allocation failed\n"); + goto cq_fail; + } + + buf_cnt = port->num_userspace_recv_buf + port->num_userspace_send_buf + 10; + port->sa_qp_cq = ibv_create_cq(port->verbs_ctx, buf_cnt, (void *)port, + port->sa_qp_comp_channel, 0); + if (!port->sa_qp_cq) { + OMGT_OUTPUT_ERROR(port, "Notice: create QP failed\n"); + goto buf_fail; + } + + if (ibv_req_notify_cq(port->sa_qp_cq, 0)) { + OMGT_OUTPUT_ERROR(port, "Notice: req_notifiy_cq: failed\n"); + goto pd_fail; + } + + port->sa_qp_pd = ibv_alloc_pd(port->verbs_ctx); + if (!port->sa_qp_pd) { + OMGT_OUTPUT_ERROR(port, "Notice: Alloc PD failed\n"); + goto pd_fail; + } + + memset(&init_attr, 0, sizeof(init_attr)); + init_attr.qp_context = (void *)port; + init_attr.send_cq = port->sa_qp_cq; + init_attr.recv_cq = port->sa_qp_cq; + init_attr.cap.max_send_wr = port->num_userspace_send_buf +1; + init_attr.cap.max_recv_wr = port->num_userspace_recv_buf +1; + init_attr.cap.max_send_sge = 1; + init_attr.cap.max_recv_sge = 1; + init_attr.qp_type = IBV_QPT_UD; + init_attr.sq_sig_all = 1; + + port->sa_qp = ibv_create_qp(port->sa_qp_pd, &init_attr); + if (!port->sa_qp) { + OMGT_OUTPUT_ERROR(port, "Notice: create QP failed\n"); + goto qp_fail; + } + + attr.qp_state = IBV_QPS_INIT; + attr.port_num = port->hfi_port_num; + attr.qkey = UMAD_QKEY; + if ( 0xffff == (attr.pkey_index = omgt_find_pkey(port, 0xffff)) ) + attr.pkey_index = omgt_find_pkey(port, 0x7fff); + if (ibv_modify_qp(port->sa_qp, &attr, IBV_QP_STATE | IBV_QP_PKEY_INDEX | + IBV_QP_PORT | IBV_QP_QKEY)) { + OMGT_OUTPUT_ERROR(port, "Notice: failed to modify QP to init\n"); + goto destroy_qp; + } + + attr.qp_state = IBV_QPS_RTR; + if (ibv_modify_qp(port->sa_qp, &attr, IBV_QP_STATE)) { + OMGT_OUTPUT_ERROR(port, "Notice: failed to modify QP to rtr\n"); + goto destroy_qp; + } + + attr.qp_state = IBV_QPS_RTS; + attr.sq_psn = 0; + if (ibv_modify_qp(port->sa_qp, &attr, IBV_QP_STATE | IBV_QP_SQ_PSN)) { + OMGT_OUTPUT_ERROR(port, "Notice: failed to modify QP to rts\n"); + goto destroy_qp; + } + + if (omgt_post_notice_recvs(port)) { + OMGT_OUTPUT_ERROR(port, "Notice: post recv buffers failed\n"); + goto destroy_qp; + } + + if (start_ud_cq_monitor(port)) + goto unreg_recv; + + return (0); + +unreg_recv: + OMGT_DBGPRINT(port, "create_sa_qp: unreg_recv\n"); + for (i = 0; inum_userspace_recv_buf; i++) + ibv_dereg_mr(port->recv_bufs[i].mr); +destroy_qp: + OMGT_DBGPRINT(port, "create_sa_qp: destroy_qp\n"); + ibv_destroy_qp(port->sa_qp); + port->sa_qp = NULL; +qp_fail: + OMGT_DBGPRINT(port, "create_sa_qp: qp_fail\n"); + ibv_dealloc_pd(port->sa_qp_pd); +pd_fail: + OMGT_DBGPRINT(port, "create_sa_qp: pd_fail\n"); + ibv_destroy_cq(port->sa_qp_cq); +buf_fail: + OMGT_DBGPRINT(port, "create_sa_qp: buf_fail\n"); + free(port->recv_bufs); +cq_fail: + OMGT_DBGPRINT(port, "create_sa_qp: cq_fail\n"); + ibv_destroy_comp_channel(port->sa_qp_comp_channel); + return (-EIO); +} + +static int start_outstanding_req_timer(struct omgt_port *port) +{ + int rc; + struct omgt_thread_msg msg = {0}; + + msg.size = sizeof(msg); + msg.evt = OMGT_TH_EVT_START_OUTSTANDING_REQ_TIME; + + rc = write(port->umad_port_sv[0], &msg, sizeof(msg)); + if (rc <= 0) { + OMGT_OUTPUT_ERROR(port, "Failed to start outstanding request timer...\n"); + return 1; + } + return 0; +} + +/** + * port->lock must be held + */ +int userspace_register(struct omgt_port *port, uint16_t trap_num, omgt_sa_registration_t *reg) +{ + struct omgt_sa_msg *sa_msg; + struct umad_sa_packet *sa_pkt; + STL_INFORM_INFO *informinfo; + + sa_msg = alloc_send_sa_msg(port); + if (!sa_msg) + return (-EIO); + + memset(sa_msg->data, 0, sizeof(sa_msg->data)); + sa_pkt = (struct umad_sa_packet *)sa_msg->data; + set_sa_common_stl_inform_info(port, sa_pkt); + informinfo = (STL_INFORM_INFO *)sa_pkt->data; + informinfo->Subscribe = 1; + informinfo->u.Generic.TrapNumber = trap_num; + informinfo->u.Generic.u1.s.RespTimeValue = 19; + BSWAP_STL_INFORM_INFO(informinfo); + + LIST_ADD(&port->pending_reg_msg_head, sa_msg); + + reg->reg_msg = sa_msg; + sa_msg->reg = reg; + sa_msg->retries = NOTICE_REG_RETRY_COUNT; + sa_msg->status = 0; + post_send_sa_msg(port, sa_msg, OMGT_RRS_SEND_INITIAL); + + OMGT_DBGPRINT(port, "starting timer to register %d\n", trap_num); + start_outstanding_req_timer(port); + + return (0); +} + +/** + * port->lock must be held + */ +static int userspace_unregister(struct omgt_port *port, omgt_sa_registration_t *reg) +{ + struct omgt_sa_msg *sa_msg; + struct umad_sa_packet *sa_pkt; + STL_INFORM_INFO *informinfo; + uint16_t trap_num; + + if (reg->reg_msg) { + LIST_DEL(reg->reg_msg); + /* Registration never completed just free the oustanding mad */ + free_sa_msg(reg->reg_msg); + return 0; + } + + sa_msg = alloc_send_sa_msg(port); + if (!sa_msg) { + OMGT_OUTPUT_ERROR(port, "Notice: failed to allocate SA message\n"); + return (-EIO); + } + + trap_num = reg->trap_num; + memset(sa_msg->data, 0, sizeof(sa_msg->data)); + sa_pkt = (struct umad_sa_packet *)sa_msg->data; + set_sa_common_stl_inform_info(port, sa_pkt); + informinfo = (STL_INFORM_INFO *)sa_pkt->data; + informinfo->Subscribe = 0; + informinfo->u.Generic.TrapNumber = trap_num; + informinfo->u.Generic.u1.s.RespTimeValue = 19; + informinfo->u.Generic.u1.s.QPNumber = port->sa_qp->qp_num; + BSWAP_STL_INFORM_INFO(informinfo); + + LIST_ADD(&port->pending_reg_msg_head, sa_msg); + + /* By the time the response comes back, the variable "reg" is already + freed by omgt_sa_remove_gre_by_trap (the caller), and we should not + set it here to avoid segfault in process_sa_gret_resp() */ + sa_msg->reg = NULL; + sa_msg->retries = NOTICE_REG_RETRY_COUNT; + sa_msg->status = 0; + post_send_sa_msg(port, sa_msg, OMGT_RRS_SEND_INITIAL); + + OMGT_DBGPRINT(port, "starting timer to un-register %d\n", trap_num); + start_outstanding_req_timer(port); + + return 0; +} + +/** + * Removes a registration based on its trap number. + * NOTE: Caller must hold the lock. + * + * @param port port opened by omgt_open_port_* + * @param trap_num The trap number to search for + * + * @return 0 if success, else error code + */ +FSTATUS omgt_sa_remove_reg_by_trap_unsafe(struct omgt_port *port, uint16_t trap_num) +{ + omgt_sa_registration_t *curr = port->regs_list, *prev = NULL; + while (curr != NULL) { + if (curr->trap_num == trap_num) { + if (prev != NULL) + prev->next = curr->next; + else + port->regs_list = curr->next; + + userspace_unregister(port, curr); + free(curr); + return FSUCCESS; + } + prev = curr; + curr = curr->next; + } + + return FERROR; +} + +/** + * Clear all registrations from the port. + */ +void omgt_sa_clear_regs_unsafe(struct omgt_port *port) +{ + FSTATUS status = FTIMEOUT; + if (omgt_lock_sem(&port->lock)) { + OMGT_OUTPUT_ERROR(port, "failed to acquire lock (status: %d)\n", status); + return; + } + + while (port->regs_list != NULL) { + /* The called function takes care of adjusting the head pointer + and freeing the entry*/ + omgt_sa_remove_reg_by_trap_unsafe(port, port->regs_list->trap_num); + } + + omgt_unlock_sem(&port->lock); +} + +/** + * Re-register all current registrations for the port. + */ +int reregister_traps(struct omgt_port *port) +{ + int ret; + int status = -1; + if (omgt_lock_sem(&port->lock)) { + OMGT_OUTPUT_ERROR(port, "failed to acquire lock (status: %d)\n", status); + return status; + } + + omgt_sa_registration_t *curr = port->regs_list; + while (curr != NULL) { + if ((ret = userspace_register(port, curr->trap_num, curr)) != 0) { + OMGT_OUTPUT_ERROR(port, "omgt_sa_reregister_trap_regs: failed to register for trap (%u) (status: %d)\n", + curr->trap_num, ret); + } + curr = curr->next; + } + + omgt_unlock_sem(&port->lock); + return 0; +} diff --git a/opamgt/src/ib_notice_net.c b/opamgt/src/ib_notice_net.c new file mode 100644 index 0000000..95cc80f --- /dev/null +++ b/opamgt/src/ib_notice_net.c @@ -0,0 +1,91 @@ +/* BEGIN_ICS_COPYRIGHT5 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + * ** END_ICS_COPYRIGHT5 ****************************************/ +/* [ICS VERSION STRING: unknown] */ + +#if HAVE_CONFIG_H +# include +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include + +#include + +#include "ib_notice_net.h" + +uint32_t ibv_sa_get_field(void *data, int offset, int size) +{ + uint32_t value, left_offset; + + left_offset = offset & 0x07; + if (size <= 8) { + value = ((uint8_t *) data)[offset / 8]; + value = ((value << left_offset) & 0xFF) >> (8 - size); + } else if (size <= 16) { + value = ntohs(((uint16_t *) data)[offset / 16]); + value = ((value << left_offset) & 0xFFFF) >> (16 - size); + } else { + value = ntohl(((uint32_t *) data)[offset / 32]); + value = (value << left_offset) >> (32 - size); + } + return value; +} + +void ibv_sa_set_field(void *data, uint32_t value, int offset, int size) +{ + uint32_t left_value, right_value; + uint32_t left_offset, right_offset; + uint32_t field_size; + + if (size <= 8) + field_size = 8; + else if (size <= 16) + field_size = 16; + else + field_size = 32; + + left_offset = offset & 0x07; + right_offset = field_size - left_offset - size; + + left_value = left_offset ? ibv_sa_get_field(data, offset - left_offset, + left_offset) : 0; + right_value = right_offset ? ibv_sa_get_field(data, offset + size, + right_offset) : 0; + + value = (left_value << (size + right_offset)) | + (value << right_offset) | right_value; + + if (field_size == 8) + ((uint8_t *) data)[offset / 8] = (uint8_t) value; + else if (field_size == 16) + ((uint16_t *) data)[offset / 16] = htons((uint16_t) value); + else + ((uint32_t *) data)[offset / 32] = htonl((uint32_t) value); +} diff --git a/opamgt/src/ib_notice_net.h b/opamgt/src/ib_notice_net.h new file mode 100644 index 0000000..21a01cc --- /dev/null +++ b/opamgt/src/ib_notice_net.h @@ -0,0 +1,282 @@ +/* BEGIN_ICS_COPYRIGHT5 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + * ** END_ICS_COPYRIGHT5 ****************************************/ +/* [ICS VERSION STRING: unknown] */ + +#if !defined(SA_NET_H) +#define SA_NET_H + +#include + +#include + +enum { + IBV_SA_ATTR_NOTICE = __constant_cpu_to_be16(0x02), + IBV_SA_ATTR_INFORM_INFO = __constant_cpu_to_be16(0x03), + IBV_SA_ATTR_MC_MEMBER_REC = __constant_cpu_to_be16(0x38), + IBV_SA_ATTR_INFORM_INFO_REC = __constant_cpu_to_be16(0xf3) +}; + +enum { + IBV_SA_METHOD_GET = 0x01, + IBV_SA_METHOD_SET = 0x02, + IBV_SA_METHOD_DELETE = 0x15 +}; + +/* Length of SA attributes on the wire */ +enum { + IBV_SA_ATTR_NOTICE_LEN = 80, + IBV_SA_ATTR_INFORM_INFO_LEN = 36, + IBV_SA_ATTR_MC_MEMBER_REC_LEN = 52, + IBV_SA_ATTR_INFORM_INFO_REC_LEN = 60 +}; + +#define IBV_SA_COMP_MASK(n) __constant_cpu_to_be64(1ull << n) + +struct ibv_sa_net_mcmember_rec { + uint8_t mgid[16]; + uint8_t port_gid[16]; + uint32_t qkey; + uint16_t mlid; + /* MtuSelector: 2:304, MTU: 6:306 */ + uint8_t mtu_info; + uint8_t tclass; + uint16_t pkey; + /* RateSelector: 2:336, Rate: 6:338 */ + uint8_t rate_info; + /* PacketLifeTimeSelector: 2:344, PacketLifeTime: 6:346 */ + uint8_t packetlifetime_info; + /* SL: 4:352, FlowLabel: 20:356, HopLimit: 8:376 */ + uint32_t sl_flow_hop; + /* Scope: 4:384, JoinState: 4:388 */ + uint8_t scope_join; + /* ProxyJoin: 1:392, rsvd: 7:393 */ + uint8_t proxy_join; + uint8_t rsvd[2]; +}; + +enum { + IBV_SA_MCMEMBER_REC_MTU_SELECTOR_OFFSET = 304, + IBV_SA_MCMEMBER_REC_MTU_SELECTOR_LENGTH = 2, + IBV_SA_MCMEMBER_REC_MTU_OFFSET = 306, + IBV_SA_MCMEMBER_REC_MTU_LENGTH = 6, + IBV_SA_MCMEMBER_REC_RATE_SELECTOR_OFFSET = 336, + IBV_SA_MCMEMBER_REC_RATE_SELECTOR_LENGTH = 2, + IBV_SA_MCMEMBER_REC_RATE_OFFSET = 338, + IBV_SA_MCMEMBER_REC_RATE_LENGTH = 6, + IBV_SA_MCMEMBER_REC_PACKETLIFE_SELECTOR_OFFSET = 344, + IBV_SA_MCMEMBER_REC_PACKETLIFE_SELECTOR_LENGTH = 2, + IBV_SA_MCMEMBER_REC_PACKETLIFE_OFFSET = 346, + IBV_SA_MCMEMBER_REC_PACKETLIFE_LENGTH = 6, + IBV_SA_MCMEMBER_REC_SL_OFFSET = 352, + IBV_SA_MCMEMBER_REC_SL_LENGTH = 4, + IBV_SA_MCMEMBER_REC_FLOW_LABEL_OFFSET = 356, + IBV_SA_MCMEMBER_REC_FLOW_LABEL_LENGTH = 20, + IBV_SA_MCMEMBER_REC_HOP_LIMIT_OFFSET = 376, + IBV_SA_MCMEMBER_REC_HOP_LIMIT_LENGTH = 8, + IBV_SA_MCMEMBER_REC_SCOPE_OFFSET = 384, + IBV_SA_MCMEMBER_REC_SCOPE_LENGTH = 4, + IBV_SA_MCMEMBER_REC_JOIN_STATE_OFFSET = 388, + IBV_SA_MCMEMBER_REC_JOIN_STATE_LENGTH = 4, + IBV_SA_MCMEMBER_REC_PROXY_JOIN_OFFSET = 392, + IBV_SA_MCMEMBER_REC_PROXY_JOIN_LENGTH = 1 +}; + +enum { + IBV_SA_MCMEMBER_REC_MGID = IBV_SA_COMP_MASK(0), + IBV_SA_MCMEMBER_REC_PORT_GID = IBV_SA_COMP_MASK(1), + IBV_SA_MCMEMBER_REC_QKEY = IBV_SA_COMP_MASK(2), + IBV_SA_MCMEMBER_REC_MLID = IBV_SA_COMP_MASK(3), + IBV_SA_MCMEMBER_REC_MTU_SELECTOR = IBV_SA_COMP_MASK(4), + IBV_SA_MCMEMBER_REC_MTU = IBV_SA_COMP_MASK(5), + IBV_SA_MCMEMBER_REC_TRAFFIC_CLASS = IBV_SA_COMP_MASK(6), + IBV_SA_MCMEMBER_REC_PKEY = IBV_SA_COMP_MASK(7), + IBV_SA_MCMEMBER_REC_RATE_SELECTOR = IBV_SA_COMP_MASK(8), + IBV_SA_MCMEMBER_REC_RATE = IBV_SA_COMP_MASK(9), + IBV_SA_MCMEMBER_REC_PACKET_LIFE_TIME_SELECTOR = IBV_SA_COMP_MASK(10), + IBV_SA_MCMEMBER_REC_PACKET_LIFE_TIME = IBV_SA_COMP_MASK(11), + IBV_SA_MCMEMBER_REC_SL = IBV_SA_COMP_MASK(12), + IBV_SA_MCMEMBER_REC_FLOW_LABEL = IBV_SA_COMP_MASK(13), + IBV_SA_MCMEMBER_REC_HOP_LIMIT = IBV_SA_COMP_MASK(14), + IBV_SA_MCMEMBER_REC_SCOPE = IBV_SA_COMP_MASK(15), + IBV_SA_MCMEMBER_REC_JOIN_STATE = IBV_SA_COMP_MASK(16), + IBV_SA_MCMEMBER_REC_PROXY_JOIN = IBV_SA_COMP_MASK(17) +}; + +/* InformInfo:Type */ +enum { + IBV_SA_EVENT_TYPE_FATAL = __constant_cpu_to_be16(0x0), + IBV_SA_EVENT_TYPE_URGENT = __constant_cpu_to_be16(0x1), + IBV_SA_EVENT_TYPE_SECURITY = __constant_cpu_to_be16(0x2), + IBV_SA_EVENT_TYPE_SM = __constant_cpu_to_be16(0x3), + IBV_SA_EVENT_TYPE_INFO = __constant_cpu_to_be16(0x4), + IBV_SA_EVENT_TYPE_EMPTY = __constant_cpu_to_be16(0x7F), + IBV_SA_EVENT_TYPE_ALL = __constant_cpu_to_be16(0xFFFF) +}; + +/* InformInfo:TrapNumber */ +enum { + IBV_SA_SM_TRAP_GID_IN_SERVICE = __constant_cpu_to_be16(64), + IBV_SA_SM_TRAP_GID_OUT_OF_SERVICE = __constant_cpu_to_be16(65), + IBV_SA_SM_TRAP_CREATE_MC_GROUP = __constant_cpu_to_be16(66), + IBV_SA_SM_TRAP_DELETE_MC_GROUP = __constant_cpu_to_be16(67), + IBV_SA_SM_TRAP_PORT_CHANGE_STATE = __constant_cpu_to_be16(128), + IBV_SA_SM_TRAP_LINK_INTEGRITY = __constant_cpu_to_be16(129), + IBV_SA_SM_TRAP_EXCESSIVE_BUFFER_OVERRUN = __constant_cpu_to_be16(130), + IBV_SA_SM_TRAP_FLOW_CONTROL_UPDATE_EXPIRED = __constant_cpu_to_be16(131), + IBV_SA_SM_TRAP_BAD_M_KEY = __constant_cpu_to_be16(256), + IBV_SA_SM_TRAP_BAD_P_KEY = __constant_cpu_to_be16(257), + IBV_SA_SM_TRAP_BAD_Q_KEY = __constant_cpu_to_be16(258), + IBV_SA_SM_TRAP_ALL = __constant_cpu_to_be16(0xFFFF) +}; + +/* InformInfo:ProducerType */ +enum { + IBV_SA_EVENT_PRODUCER_TYPE_CA = __constant_cpu_to_be32(0x1), + IBV_SA_EVENT_PRODUCER_TYPE_SWITCH = __constant_cpu_to_be32(0x2), + IBV_SA_EVENT_PRODUCER_TYPE_ROUTER = __constant_cpu_to_be32(0x3), + IBV_SA_EVENT_PRODUCER_TYPE_CLASS_MANAGER = __constant_cpu_to_be32(0x4), + IBV_SA_EVENT_PRODUCER_TYPE_ALL = __constant_cpu_to_be32(0xFFFFFF) +}; + +struct ibv_sa_net_inform_info { + uint8_t gid[16]; + uint16_t lid_range_begin; + uint16_t lid_range_end; + uint16_t rsvd; + uint8_t is_generic; + uint8_t subscribe; + uint16_t type; + /* TrapNumber/DeviceID */ + uint16_t trap_num_device_id; + /* QPN: 24:224, rsvd: 3:248, RespTimeValue: 5:251 */ + uint32_t qpn_resptime; + /* rsvd: 8:256, ProducerType/VendorID: 24:264 */ + uint32_t producer_type_vendor_id; +}; + +enum { + IBV_SA_INFORM_INFO_QPN_OFFSET = 224, + IBV_SA_INFORM_INFO_QPN_LENGTH = 24, + IBV_SA_INFORM_INFO_RESP_TIME_OFFSET = 251, + IBV_SA_INFORM_INFO_RESP_TIME_LENGTH = 5, + IBV_SA_INFORM_INFO_PRODUCER_TYPE_OFFSET = 264, + IBV_SA_INFORM_INFO_PRODUCER_TYPE_LENGTH = 24, + IBV_SA_INFORM_INFO_VENDOR_ID_OFFSET = 264, + IBV_SA_INFORM_INFO_VENDOR_ID_LENGTH = 24 +}; + +struct ibv_sa_net_notice { + /* IsGeneric: 1:0, Type: 7:1, ProducerType/VendorID: 24:8 */ + uint32_t generic_type_producer; + /* TrapNumber/DeviceID */ + uint16_t trap_num_device_id; + uint16_t issuer_lid; + /* NoticeToggle: 1:64, NoticeCount: 15:65 */ + uint16_t toggle_count; + uint8_t data_details[54]; + uint8_t issuer_gid[16]; +}; + +enum { + IBV_SA_NOTICE_IS_GENERIC_OFFSET = 0, + IBV_SA_NOTICE_IS_GENERIC_LENGTH = 1, + IBV_SA_NOTICE_TYPE_OFFSET = 1, + IBV_SA_NOTICE_TYPE_LENGTH = 7, + IBV_SA_NOTICE_PRODUCER_TYPE_OFFSET = 8, + IBV_SA_NOTICE_PRODUCER_TYPE_LENGTH = 24, + IBV_SA_NOTICE_VENDOR_ID_OFFSET = 8, + IBV_SA_NOTICE_VENDOR_IF_LENGTH = 24, + IBV_SA_NOTICE_TOGGLE_OFFSET = 64, + IBV_SA_NOTICE_TOGGLE_LENGTH = 1, + IBV_SA_NOTICE_COUNT_OFFSET = 65, + IBV_SA_NOTICE_COUNT_LENGTH = 15, +}; + +/* + * SM notice data details for: + * + * IB_SA_SM_TRAP_GID_IN_SERVICE = 64 + * IB_SA_SM_TRAP_GID_OUT_OF_SERVICE = 65 + * IB_SA_SM_TRAP_CREATE_MC_GROUP = 66 + * IB_SA_SM_TRAP_DELETE_MC_GROUP = 67 + */ +struct ibv_sa_net_notice_data_gid { + uint8_t reserved[6]; + uint8_t gid[16]; + uint8_t padding[32]; +}; + +/* + * SM notice data details for: + * + * IB_SA_SM_TRAP_PORT_CHANGE_STATE = 128 + */ +struct ibv_sa_net_notice_data_port_change { + uint16_t lid; + uint8_t padding[52]; +}; + +/* + * SM notice data details for: + * + * IB_SA_SM_TRAP_LINK_INTEGRITY = 129 + * IB_SA_SM_TRAP_EXCESSIVE_BUFFER_OVERRUN = 130 + * IB_SA_SM_TRAP_FLOW_CONTROL_UPDATE_EXPIRED = 131 + */ +struct ibv_sa_net_notice_data_port_error { + uint8_t reserved[2]; + uint16_t lid; + uint8_t port_num; + uint8_t padding[49]; +}; + +/** + * ibv_sa_get_field - Extract a bit field value from a structure. + * @data: Pointer to the start of the structure. + * @offset: Bit offset of field from start of structure. + * @size: Size of field, in bits. + * + * The structure must be in network-byte order. The returned value is in + * host-byte order. + */ +uint32_t ibv_sa_get_field(void *data, int offset, int size); + +/** + * ibv_sa_set_field - Set a bit field value in a structure. + * @data: Pointer to the start of the structure. + * @value: Value to assign to field. + * @offset: Bit offset of field from start of structure. + * @size: Size of field, in bits. + * + * The structure must be in network-byte order. The value to set is in + * host-byte order. + */ +void ibv_sa_set_field(void *data, uint32_t value, int offset, int size); + +#endif /* SA_NET_H */ diff --git a/opamgt/src/ib_utils_openib.c b/opamgt/src/ib_utils_openib.c new file mode 100644 index 0000000..cd14de3 --- /dev/null +++ b/opamgt/src/ib_utils_openib.c @@ -0,0 +1,773 @@ +/* BEGIN_ICS_COPYRIGHT3 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT3 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +#ifdef IB_STACK_OPENIB + +#include +#include +#include +#include +#include +#define _GNU_SOURCE +#include +#include +#include +#include +#include + +#define OPAMGT_PRIVATE 1 + +#include "ibt.h" + +#include "infiniband/umad.h" +#include "ib_utils_openib.h" +#include + +#define MAX_NUM_CAS 20 + +FSTATUS convert_umad_ca_attribs_to_iba( IN void *pumad_ca_attribs, + OUT IB_CA_ATTRIBUTES *pCaAttributes ); +FSTATUS convert_umad_port_attribs_to_iba( IN void *pumad_port_attribs, + OUT IB_PORT_ATTRIBUTES *pPortAttributes ); + +/** + * @brief Get the HFI number + * + * @param hfi_name Name of the HFI device + * + * @return + * On Success the HFI Number + * On Error -1 + */ +int omgt_get_hfi_num(char *hfi_name) +{ + char ca_names[MAX_NUM_CAS][UMAD_CA_NAME_LEN]; + int i; + + // Always clear the count. + int caCount = 0; + + // get ca count and names + if (omgt_get_hfi_names((void *)ca_names, MAX_NUM_CAS, &caCount) != OMGT_STATUS_SUCCESS) { + return -1; + } + + for (i = 0; i < caCount; i++) { + if (0 == strcmp(ca_names[i], hfi_name)) + return i + 1; + } + return -1; +} // int omgt_get_hfiNum + +/******************************************************************************/ +/******************************************************************************/ + +/** + * Return the GUIDs for the FIs. The GUID array pointer must be null and + * will always get filled-in, sets the number of FIs in the system + * regardless of the initial value of the + * count. + * + * @param pCaCount + * @param pCaGuidArray, If pCaGuidArray not null, Caller must call MemoryDeallocate() + * + * @return FSTATUS + */ +FSTATUS omgt_get_caguids(OUT uint32 *pCaCount, OUT uint64 **pCaGuidArray) +{ + FSTATUS fstatus = FSUCCESS; + int i, c; + char ca_names[MAX_NUM_CAS][UMAD_CA_NAME_LEN]; + + // Check that a valid pointer was provided for the CA count. + if( !pCaCount ) + { + return FINVALID_PARAMETER; + } + if( !pCaGuidArray ) + { + return FINVALID_PARAMETER; + } + + // Always clear the count. + *pCaCount = 0; + + // get ca count and names + (void)omgt_get_hfi_names((void *)ca_names, MAX_NUM_CAS, &c); + if (c <= 0) + { + // _DBG_LEAVE_FUNC(); + *pCaCount = 0; + return FNOT_FOUND; + } + + *pCaCount = 0; + + + *pCaGuidArray = (EUI64*)MemoryAllocateAndClear( sizeof(EUI64)*(*pCaCount), FALSE, OMGT_MEMORY_TAG); + + + if ( *pCaGuidArray==NULL ) + { + return FINSUFFICIENT_MEMORY; + } + + umad_ca_t ca; + uint64 *pCaGuid; + + for (i=0, pCaGuid=*pCaGuidArray; i<*pCaCount; ++i,++pCaGuid) + { + + + fstatus = umad_get_ca(ca_names[i], &ca); + if (fstatus != FSUCCESS) { + break; + } + + + *pCaGuid = ca.node_guid; + umad_release_ca(&ca); + // *pCaGuid = ca.system_guid; + + } // for (i=0, pCaGuid=g_caMon; i<*pCaCount; ++i,++pCaGuid) + + if (fstatus != FSUCCESS) { + if (pCaGuidArray != NULL) + MemoryDeallocate(pCaGuidArray); + } + + return fstatus; + + +} // omgt_get_caguids() + + +/** + * Return the the hfi name and hfi port for the given port guid. + * Return value is success / failure. + * + * @param portGuid + * @param pointer to hfiName + * @param pointer to hfi number (1=1st CA) + * @param pointer to port number (1=1st port) + * @param pointer to port gid prefix + * + * @return 0 for success, else error code + */ +FSTATUS omgt_get_hfi_from_portguid(uint64_t portGuid, struct omgt_port *port, char *pCaName, + int *caNum, int *portNum, uint64_t *pPrefix, uint16 *pSMLid, uint8 *pSMSL, uint8 *pPortState) +{ + FSTATUS fstatus = FSUCCESS; + char ca_names[MAX_NUM_CAS][UMAD_CA_NAME_LEN]; + umad_ca_t Ca; + umad_port_t port_attr; + int i, j; + int found = 0; + + // Always clear the count, and output parameters + int caCount = 0; + + // Default the return values to error cases. + if (pCaName) *pCaName = '\0'; + if (caNum) *caNum = -1; + if (portNum) *portNum = -1; + if (pPrefix) *pPrefix = 0; + if (pSMLid) *pSMLid = -1; + if (pSMSL) *pSMSL = 0; + if (pPortState) *pPortState = PortStateNop; + + // get ca count and names + if (omgt_get_hfi_names((void *)ca_names, MAX_NUM_CAS, &caCount) != OMGT_STATUS_SUCCESS || caCount <= 0) { + OMGT_OUTPUT_ERROR(port, "No hfi names found, no data to be found.\n"); + return FERROR; + } + + for (i = 0; i < caCount; i++) { + fstatus = umad_get_ca(ca_names[i], &Ca); + + if (0 != fstatus) { + OMGT_OUTPUT_ERROR(port, "Cannot query CA %s: %s\n", ca_names[i], FSTATUS_MSG(fstatus)); + return FERROR; + } + + for (j = 1; j <= Ca.numports; j++) { + fstatus = umad_get_port(ca_names[i], j, &port_attr); + OMGT_OUTPUT_INFO(port, "returned umad_get_port (%s,%u)...Status=%u \n", ca_names[i], j, fstatus); + if (FSUCCESS != fstatus) { + OMGT_OUTPUT_ERROR(port, "Failed. Returned umad_get_port (%s,%u)...Status=%u \n", ca_names[i], j, fstatus); + umad_release_ca(&Ca); + return FERROR; + } + + // Check for the port + if (portGuid == ntoh64(port_attr.port_guid)) { + found = 1; + if (pCaName) strncpy(pCaName, ca_names[i], UMAD_CA_NAME_LEN); + if (caNum) *caNum = i + 1; + if (portNum) *portNum = j; + if (pPrefix) *pPrefix = ntoh64(port_attr.gid_prefix); + if (pSMLid) *pSMLid = port_attr.sm_lid; + if (pSMSL) *pSMSL = port_attr.sm_sl; + if (pPortState) *pPortState = port_attr.state; + } else { + OMGT_OUTPUT_INFO(port, "Given Port guid (0x%016"PRIx64") not matched for hfi port %u guid (0x%016"PRIx64")\n", + portGuid, j, ntoh64(port_attr.port_guid)); + } + umad_release_port(&port_attr); + } + umad_release_ca(&Ca); + } + + if (found == 1) { + return FSUCCESS; + } else { + return FNOT_FOUND; + } +} // FSTATUS omgt_get_hfi_from_portguid + +/* translate ca/port number into a port Guid. Also return other useful structs + * if non-null pointer passed-in. + * Warning: Endian conversion not done + * + * INPUTS: + * ca - system wide CA number 1-n + * port - 1-n, + * *pCaName - ca name for specified port + * port - if provided, logging parameters will be extracted from this port. + * + * -h and -p options for assorted utilities (opareport, opasaquery, etc) should + * behave as follows: + * -h 0 = 1st active port in system (p defaults to 0 or -1) + * -h 0 -p 0 = 1st active port in system (same as above) + * -h x = 1st active port on HFI x (p defaults to 0 or -1) + * -h x -p 0 = 1st active port on HFI x (same as above) + * + * -h 0 -p y = port y within system (inrespective of which ports are active) + * -h x -p y = HFI x, port y + * + * OUTPUTS: + * *pCaGuid - ca guid for specified port + * *pPortGuid - port guid for specified port (Warning: Endian conversion not done) + * *pCaAttributes - attributes for CA, + * If PortAttributesList not null, caller must MemoryDeallocate pCaAttributes->PortAttributesList + * *ppPortAtributes - attributes for port, if ppPortAtributes not null, caller must MemoryDeallocate ppPortAtributes + * *pCaCount - number of CA in system + * *pPortCount - number of ports in system or CA (depends on ca input) + * *pRetCaName - pointer to CA name to return. + * *pRetPortNum - pointer to port number that was selected (useful in wildcard searches) + * + * RETURNS: + * FNOT_FOUND - *pCaCount and *pPortCount still output + * if ca == 0, *pPortCount = number of ports in system + * if ca < *pCaCount, *pPortCount = number of ports in CA + * otherwise *pPortCount will be 0 + * + */ +FSTATUS omgt_get_portguid(uint32 ca, uint32 port, char *pCaName, struct omgt_port *omgtport, + EUI64 *pCaGuid, EUI64 *pPortGuid, IB_CA_ATTRIBUTES *pCaAttributes, + IB_PORT_ATTRIBUTES **ppPortAttributes, uint32 *pCaCount, uint32 *pPortCount, + char *pRetCaName, int *pRetPortNum, uint64 *pRetGIDPrefix) +{ + + FSTATUS fstatus = FSUCCESS; + char ca_names[MAX_NUM_CAS][UMAD_CA_NAME_LEN]; + umad_ca_t umad_ca_attribs; + umad_port_t umad_port_attribs; + int caCount ; + int found = 0; + int i,j,k; + int total_ports = 0; + + OMGT_OUTPUT_INFO(omgtport, "omgt_get_portguid(%u,%u,...)... \n",ca,port ); + + // Ensure proper defaults (-1 is equivalent to 0) + if (port==-1) + port = 0; + if (ca==-1) + ca = 0; + + // Default the input parameters now just in case we exit with an error. + if (pCaCount) *pCaCount = 0; + if (pPortCount) *pPortCount = 0; + + // get ca count and names + OMGT_OUTPUT_INFO(omgtport, "omgt_get_portguid calling omgt_get_hfi_names()... \n" ); + if (omgt_get_hfi_names((void *)ca_names, MAX_NUM_CAS, &caCount) != OMGT_STATUS_SUCCESS || caCount <= 0) { + OMGT_OUTPUT_ERROR(omgtport,"No hfi names found, no port GUID to find.\n" ); + return FNOT_FOUND; + } + OMGT_OUTPUT_INFO(omgtport, "returned omgt_get_hfi_names (%s,)...caCount=%u \n", ca_names[0], caCount); + + if (caCount > MAX_NUM_CAS) { + OMGT_OUTPUT_ERROR(omgtport, "OFED'S omgt_get_hfi_names returned more CA's than max allowed." + "Cas:%d, Max:%d\n",caCount, MAX_NUM_CAS); + } + + if (pCaCount) + *pCaCount = (uint32)caCount; + + // Set default number if CA requested by name... + // Check bounds of ca requested if requested by number.... + if ((pCaName) && (*pCaName!='\0') ) { + ca = MAX_NUM_CAS; + } + else if (ca > caCount ) + { + OMGT_OUTPUT_INFO(omgtport, "Ca %u not found. Max Cas are %u\n", ca, caCount); + return FNOT_FOUND; + } + + // CA's and ports are numbered 1 to n where n is max num of FIs in system / ports on CA + for (k=1, i=1; i<=caCount; i++) { + + // if ca name is supplied, determine if this ca name matches the requested + // and set the ca number. + if ( (pCaName) && (strncmp(pCaName, ca_names[i-1], UMAD_CA_NAME_LEN)==0) ) + ca = i; + + // Is this the CA we want (value of 0 means wildcard CA (used for first ACTIVE port)) + if ((ca==i) || (ca==0)) { + + // Get CA Info. + OMGT_OUTPUT_INFO(omgtport,"omgt_get_portguid calling umad_get_ca(%s,)... \n", ca_names[i-1]); + fstatus = umad_get_ca(ca_names[i-1], &umad_ca_attribs); + OMGT_OUTPUT_INFO(omgtport,"returned omgt_get_portguid umad_get_ca(%s,) fstatus=%u \n", ca_names[i-1], fstatus); + + if (fstatus != FSUCCESS) { + OMGT_OUTPUT_ERROR(omgtport,"Cannot query CA %s: %d\n",ca_names[i-1], fstatus); + return fstatus; + } + OMGT_OUTPUT_INFO(omgtport,"returned omgt_get_portguid umad_get_ca(%s,), numports=%u \n", ca_names[i-1], umad_ca_attribs.numports); + + // Initialize port count + if (ca != 0 && pPortCount) *pPortCount = umad_ca_attribs.numports; + + // If this request for a specific CA - update the ca structs. + if (ca==i) { + if (pCaGuid) *pCaGuid = umad_ca_attribs.node_guid; + if (pRetCaName) strcpy (pRetCaName,ca_names[i-1]); + + if (pCaAttributes) + { + OMGT_OUTPUT_INFO(omgtport,"omgt_get_portguid setting pCaAttributes...\n"); + + fstatus = convert_umad_ca_attribs_to_iba( &umad_ca_attribs, pCaAttributes ); + if (FSUCCESS != fstatus) { + umad_release_ca(&umad_ca_attribs); + return fstatus; + } + } + + // check bounds of port requested. + if (port > umad_ca_attribs.numports) { + OMGT_OUTPUT_INFO(omgtport,"Port %u does not exist for Ca %u(%s). Max ports are %u.\n", + port, ca, ca_names[i-1], umad_ca_attribs.numports); + umad_release_ca(&umad_ca_attribs); + return (FNOT_FOUND); + } + } + + + // Update the running system count of ports + total_ports += umad_ca_attribs.numports; + if (found) // already found, just counting total_ports + continue; + + // Evaluate the ports on this CA... + for (j=1; j <= umad_ca_attribs.numports; j++, k++) { + + // Is this a specific requested port + if ( + ((ca==0) && (port==k)) || // Specific System port request + ((ca==i) && (port==j)) || // Specific HFI / Port request + (port==0) // Wildcard - first ACTIVE port (in system or HFI) + ) + { + OMGT_OUTPUT_INFO(omgtport, "Calling umad_get_port (%s,%u)... \n", ca_names[i-1], j); + fstatus = umad_get_port( ca_names[i-1], j, &umad_port_attribs); + OMGT_OUTPUT_INFO(omgtport, "returned umad_get_port (%s,%u)...Status=%u \n", ca_names[i-1], j, fstatus); + if (FSUCCESS != fstatus) + { + OMGT_OUTPUT_ERROR(omgtport,"returned umad_get_port (%s,%u)...Status=%u \n",ca_names[i-1], j, fstatus); + umad_release_ca(&umad_ca_attribs); + return fstatus; + } + + // If this is a request for an active wildcard port - + // Check if we are active ... continue to next port if we are not active. + if ((port==0) && (umad_port_attribs.state!=PortStateActive)) + { + umad_release_port(&umad_port_attribs); + continue; + } + + // Otherwise - we are either specifying THIS port OR + // this is the first ACTIVE port (on system or HFI) + // Initialized the pointer values. + found = 1; + + // Wildcard HFI. Found first active port. Initialize CA stuff. + if (ca==0) { + if (pCaGuid) *pCaGuid = umad_ca_attribs.node_guid; + if (pRetCaName) strcpy (pRetCaName,ca_names[i-1]); + + if (pCaAttributes) + { + OMGT_OUTPUT_INFO(omgtport, "omgt_get_portguid setting pCaAttributes...\n"); + + fstatus = convert_umad_ca_attribs_to_iba( &umad_ca_attribs, pCaAttributes ); + if (FSUCCESS != fstatus) + { + umad_release_port(&umad_port_attribs); + umad_release_ca(&umad_ca_attribs); + return fstatus; + } + } + } + + // Port Stuff + if (pPortGuid) *pPortGuid = ntoh64(umad_port_attribs.port_guid); + if (pRetPortNum) *pRetPortNum = j; + if (pRetGIDPrefix) * pRetGIDPrefix = ntoh64(umad_port_attribs.gid_prefix); + if (ppPortAttributes) + { + OMGT_OUTPUT_INFO(omgtport, "omgt_get_portguid setting ppPortAttributes...\n"); + + *ppPortAttributes = (IB_PORT_ATTRIBUTES*) + MemoryAllocateAndClear((ROUNDUPP2(sizeof(IB_PORT_ATTRIBUTES), 8)+sizeof(IB_GID)), + FALSE, OMGT_MEMORY_TAG); + + if (*ppPortAttributes == NULL) + { + umad_release_port(&umad_port_attribs); + umad_release_ca(&umad_ca_attribs); + return (FINSUFFICIENT_MEMORY); + } + (*ppPortAttributes)->GIDTable = (IB_GID*) ((char *)(*ppPortAttributes) + + ROUNDUPP2(sizeof(IB_PORT_ATTRIBUTES), 8)); + fstatus = convert_umad_port_attribs_to_iba( &umad_port_attribs, *ppPortAttributes ); + if (FSUCCESS != fstatus) + { + umad_release_port(&umad_port_attribs); + umad_release_ca(&umad_ca_attribs); + return fstatus; + } + } + + umad_release_port(&umad_port_attribs); + break; + } + } + + umad_release_ca(&umad_ca_attribs); + + // If the query was for specific CA, we are done. + if (ca==i) break; + } + } + + if (ca==0 && pPortCount) { + *pPortCount = total_ports; + OMGT_OUTPUT_INFO(omgtport, "total_ports = %u\n", total_ports); + } + + // We found what we are looking for. + if (found == 1) + return (FSUCCESS); + + // Error cases. We did not find the port. + // Remaining possibilites are: + // No active port in system + // No active port on HFI requested + // System port number out of range. + + if (port==0) + if (ca==0) + OMGT_OUTPUT_INFO(omgtport, "No active ports found on any CA.\n"); + else + OMGT_OUTPUT_INFO(omgtport, "No active port found on CA %d(%s).\n", ca, ca_names[ca-1]); + else + if (ca==0) { + OMGT_OUTPUT_INFO(omgtport, "System Port %d does not exist. Max system port is %d.\n",port, k-1); + } else + OMGT_OUTPUT_INFO(omgtport, "Port not found for parameters port:%d ca:%d.\n",port, ca); + + return (FNOT_FOUND); +} // FSTATUS omgt_get_portguid + +/* Find the ca indicated by the passed in CA guid, then allocate + * and fill in the ca attributes. + * + * INPUTS: + * caGuid - guid of the desired ca + * + * OUTPUTS: + * *pCaAttributes - attributes for CA, + * If PortAttributesList not null, caller must + * MemoryDeallocate pCaAttributes->PortAttributesList + * + * RETURNS: + * FNOT_FOUND + * + */ + +FSTATUS omgt_query_ca_by_guid_alloc(IN EUI64 CaGuid,OUT IB_CA_ATTRIBUTES *CaAttributes ) +{ + FSTATUS fstatus = FSUCCESS; + int i, j, count; + char ca_names[MAX_NUM_CAS][UMAD_CA_NAME_LEN]; + umad_ca_t ca; + umad_port_t uport; + IB_PORT_ATTRIBUTES *cur, *prev; + + // get ca count and names + if (omgt_get_hfi_names((void *)ca_names, MAX_NUM_CAS, &count) != OMGT_STATUS_SUCCESS || count <= 0) { + return FNOT_FOUND; + } + + + for (i=0;i0) { + CaAttributes->PortAttributesListSize = + (ROUNDUPP2(sizeof(IB_PORT_ATTRIBUTES), 8) + sizeof(IB_GID))*ca.numports; + CaAttributes->PortAttributesList = MemoryAllocateAndClear(CaAttributes->PortAttributesListSize, + FALSE, OMGT_MEMORY_TAG); + if (CaAttributes->PortAttributesList == NULL) + { + umad_release_ca(&ca); + return FINSUFFICIENT_MEMORY; + } + cur = CaAttributes->PortAttributesList; + prev = NULL; + for (j=0; j< ca.numports;j++) { + cur->GIDTable = (IB_GID*) ((char *)cur + + ROUNDUPP2(sizeof(IB_PORT_ATTRIBUTES), 8)); + cur->Next = (IB_PORT_ATTRIBUTES *)((char *)cur->GIDTable + sizeof(IB_GID)); + prev = cur; + cur = cur->Next; + fstatus = umad_get_port( ca.ca_name, j+1, &uport); + if (fstatus != FSUCCESS) { + continue; //skip to next port + } + convert_umad_port_attribs_to_iba(&uport, prev); + umad_release_port(&uport); + } + prev->Next = NULL; + } + umad_release_ca(&ca); + break; + } + umad_release_ca(&ca); + } + + return fstatus; +} // FSTATUS omgt_query_ca_by_guid_alloc + + +/* Find the ca indicated by the passed in CA guid, then + * fill in the ca attributes. + * + * Note: It is assumed that the CaAttributes is already populated with + * allocated memory for pCaAttributes->PortAttributesList + * + * INPUTS: + * caGuid - guid of the desired ca + * + * OUTPUTS: + * *pCaAttributes - attributes for CA, + * caller responsible for allocating/deallocating memory for + * pCaAttributes->PortAttributesList + * + * RETURNS: + * FNOT_FOUND + * + */ + +FSTATUS omgt_query_ca_by_guid(IN EUI64 CaGuid, OUT IB_CA_ATTRIBUTES *CaAttributes ) +{ + FSTATUS fstatus = FSUCCESS; + int i, j, count; + char ca_names[MAX_NUM_CAS][UMAD_CA_NAME_LEN]; + umad_ca_t ca; + umad_port_t uport; + IB_PORT_ATTRIBUTES *cur, *prev; + + // get ca count and names + if (omgt_get_hfi_names((void *)ca_names, MAX_NUM_CAS, &count) != OMGT_STATUS_SUCCESS || count <= 0) { + return FNOT_FOUND; + } + + + for (i=0;iPortAttributesListSize)/(ROUNDUPP2(sizeof(IB_PORT_ATTRIBUTES), 8)+sizeof(IB_GID))) + < ca.numports ) { + umad_release_ca(&ca); + return FINSUFFICIENT_MEMORY; + } + + convert_umad_ca_attribs_to_iba (&ca, CaAttributes); + if (ca.numports >0) { + + // ensure that list is valid + if (CaAttributes->PortAttributesList == NULL) + { + umad_release_ca(&ca); + return FINVALID_PARAMETER; + } + cur = CaAttributes->PortAttributesList; + prev = NULL; + for (j=0; j< ca.numports;j++) { + cur->GIDTable = (IB_GID*) ((char *)cur + + ROUNDUPP2(sizeof(IB_PORT_ATTRIBUTES), 8)); + cur->Next = (IB_PORT_ATTRIBUTES *)((char *)cur->GIDTable + sizeof(IB_GID)); + prev = cur; + cur = cur->Next; + fstatus = umad_get_port( ca.ca_name, j+1, &uport); + if (fstatus != FSUCCESS) { + continue; //skip to next port + } + convert_umad_port_attribs_to_iba(&uport, prev); + umad_release_port(&uport); + } // for (j=0; j< ca.numports;j++) + prev->Next = NULL; + } // if (ca.numports >0) + umad_release_ca(&ca); + break; + } // if (ca.node_guid == CaGuid) + umad_release_ca(&ca); + } // for (i=0;iGIDTable must be pointing to valid memory to get the GIDTable + * + * @param pumad_port_attribs (expect pointer to type umad_port_t) + * @param pPortAttributes + * + * @return FSTATUS + */ +FSTATUS convert_umad_port_attribs_to_iba(IN void * p, OUT IB_PORT_ATTRIBUTES *pPortAttributes) +{ + FSTATUS fstatus = FSUCCESS; + umad_port_t *pumad_port_attribs = p; + + + if (!pPortAttributes || !pumad_port_attribs) + { + return FINVALID_PARAMETER; + } + + pPortAttributes->GUID = ntoh64(pumad_port_attribs->port_guid); + pPortAttributes->Address.BaseLID = pumad_port_attribs->base_lid; + pPortAttributes->Address.LMC = pumad_port_attribs->lmc; + + pPortAttributes->SMAddress.LID= pumad_port_attribs->sm_lid; + pPortAttributes->SMAddress.ServiceLevel = pumad_port_attribs->sm_sl; + pPortAttributes->PortState = pumad_port_attribs->state; + // pPortAttributes->PortState = pumad_port_attribs->phys_state; + // pPortAttributes->PortState = pumad_port_attribs->rate; + + if (pPortAttributes->GIDTable) { + pPortAttributes->GIDTable[0].Type.Global.SubnetPrefix = ntoh64(pumad_port_attribs->gid_prefix); + pPortAttributes->GIDTable[0].Type.Global.InterfaceID = pPortAttributes->GUID; + } + + // what about other attributes? TBD + + return fstatus; + +} // convert_umad_port_attribs_to_iba() + + +/** + * Convert openib/umad ca attribs to ibaccess ca attributes. + * Warning: Only very few (common) attributes are being copied. + * + * @param pumad_ca_attribs (expects pointer to type umad_ca_t) + * @param pCaAttributes + * + * @return FSTATUS + */ +FSTATUS convert_umad_ca_attribs_to_iba(IN void *p, OUT IB_CA_ATTRIBUTES *pCaAttributes) +{ + FSTATUS fstatus = FSUCCESS; + umad_ca_t *pumad_ca_attribs = p; + + if (!pCaAttributes || !pumad_ca_attribs) + { + + return FINVALID_PARAMETER; + + } + + pCaAttributes->GUID = pumad_ca_attribs->node_guid; + pCaAttributes->SystemImageGuid = pumad_ca_attribs->system_guid; + pCaAttributes->Ports = pumad_ca_attribs->numports; + + // what about other attributes? TBD + + return fstatus; + +} // convert_umad_ca_attribs_to_iba() + + +//////////////////////////////////////////////////////// +#endif diff --git a/opamgt/src/ib_utils_openib.h b/opamgt/src/ib_utils_openib.h new file mode 100644 index 0000000..ecb0dc0 --- /dev/null +++ b/opamgt/src/ib_utils_openib.h @@ -0,0 +1,414 @@ +/* BEGIN_ICS_COPYRIGHT3 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT3 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +#ifndef _IB_UTILS_OPENIB_H_ +#define _IB_UTILS_OPENIB_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "iba/public/datatypes.h" +#include "iba/public/isemaphore.h" +#include "iba/ib_types.h" +#include "iba/stl_types.h" + +#define OMGT_MEMORY_TAG ((uint32)0x4F50454E) /* OPEN */ + +#ifndef min +#define min(a,b) (((a)<(b))?(a):(b)) +#endif +#ifndef max +#define max(a,b) (((a)>(b))?(a):(b)) +#endif + + /* filled in in C code so we don't need opamgt headers here */ +#define OMGT_SEND_TIMEOUT_DEFAULT -1 + +/* compute max timeout value to use in umad_recv based on + * timeout and retries specified in corresponding umad_send + * we add 1000ms (1 second) to allow for delays in local HFI and stack + * in issuing retries, etc. + */ +#define COMPUTE_MAX_TIMEOUT(timeout, retries) (((timeout)*((retries)+1))+1000) + +#define OUI_TRUESCALE_0 (0x00) /* 3-byte InfiniCon (now Intel) OUI */ +#define OUI_TRUESCALE_1 (0x06) +#define OUI_TRUESCALE_2 (0x6a) + + +/** + * Initailize global elements to be used for queries and access to OFED stack. + * + * There are 3 different ways to call init, all 3 have the same effect - + * they initialize all the global vars to be used later for oib + * (ofed to ib access) utilities. + * They also initialize the umad interface. + * + * The three ways to initialize are + * initialize via port guid, [hfi / port specific, no wildcards] + * initialize via hfi name and port num [hfi specific, port can be wildcard (0)] + * initialize via hfi num and port num [hfi / port specific, or wildcards (0)] + * + * Wildcards for hfi num or port num look for ACTIVE ports. + * Specific ports may be inactive, although not all globals may be initialized + * in that case. + * + * @param hfiName - pointer to name of HFI + * @param hfi - number of HFI to initialize globals + * @param port - number of port to initialize globals + * @param port_guid - guid to initialize globals (can be invalid (-1)) + * + * @return FSTATUS - error if could not find the port (or any active port for wildcards) + */ + +#define OMGT_GLOBAL_PORTID -1 + + +/** + * Return the the hfi name and hfi port for the given port guid. + * Return value is success / failure. + * + * @param portGuid + * @param pointer to hfiName + * @param pointer to ca number (1=1st CA) + * @param pointer to port number (1=1st port) + * @param pointer to port gid prefix + * + * @return 0 for success, else error code + */ +extern FSTATUS omgt_get_hfi_from_portguid(uint64_t portGuid, struct omgt_port *port, char *pCaName, + int *caNum, int *portNum, uint64_t *pPrefix, uint16 *pSMLid, uint8 *pSMSL, uint8 *pPortState); + + +/** + * Return the GUIDs for the FIs. The GUID array pointer must be null and + * will always get filled-in, sets the number of FIs in the system + * regardless of the initial value of the + * count. + * + * @param pCaCount + * @param pCaGuidArray + * + * @return FSTATUS + */ +extern FSTATUS omgt_get_caguids( OUT uint32 *pCaCount, OUT uint64 **pCaGuidArray ); + + +/* Find the ca indicated by the passed in CA guid, then allocate + * and fill in the ca attributes. + * * + * INPUTS: + * caGuid - guid of the desired ca + * + * OUTPUTS: + * *pCaAttributes - attributes for CA, + * If PortAttributesList not null, caller must MemoryDeallocate + * pCaAttributes->PortAttributesList + * Meant to be equivalent for iba_get_caguids. + * + * RETURNS: + * FNOT_FOUND + * + */ +extern FSTATUS omgt_query_ca_by_guid_alloc(IN EUI64 CaGuid,OUT IB_CA_ATTRIBUTES *CaAttributes ); + +/* Find the ca indicated by the passed in CA guid, then + * fill in the ca attributes. + * + * Note: It is assumed that the CaAttributes is already populated with + * allocated memory for pCaAttributes->PortAttributesList + * + * INPUTS: + * caGuid - guid of the desired ca + * + * OUTPUTS: + * *pCaAttributes - attributes for CA, + * caller responsible for allocating/deallocating memory for + * pCaAttributes->PortAttributesList + * + * RETURNS: + * FNOT_FOUND + * + */ + +extern FSTATUS omgt_query_ca_by_guid(IN EUI64 CaGuid, OUT IB_CA_ATTRIBUTES *CaAttributes ); + +/** + * Function to register a list of managment classes with the umad OFED + * library. + * + * To use with omgt_send_rcv_mad, and the umad OFED library. + * + * User must have called omgt_mad_init first. Otherwise - call fails + * + * User may call this fn multiple times to register for different classes. + * If the class is already registered, a warning is printed, but the + * call succeeds. + * + * @param *mgmt_classes pointer to a list of managment classes to be registered. + * The list is terminated by a record that has 0 for the + * base_version. + * + * Returns 0 if successful, else error code. + */ +#define OMGT_CLASS_MAX_METHODS 8 + +typedef struct { + int base_version; // IB_BASE_VERSION or STL_BASE_VERSION + int class; // MCLASS_SUBN_ADM, STL_SA_CLASS, etc... + int classVersion; // IB_BM_CLASS_VERSION, STL_SA_CLASS_VERSION, etc... + int useMethods; // if Nonzero, use the methods list instead of the defaults. + int isResp; // nonzero if registering for rx respones + int isTrap; // nonzero if registering for rx Traps + int isReport; // nonzero if registering for rx reports + int stackRMPP; // nonzero if OFED-style rmpp support is desired. + uint8_t *oui; // vendor-specific OUI for vendor classes. + int methods[OMGT_CLASS_MAX_METHODS]; // 0 terminated list of methods. +} OMGT_CLASS_ARGS; + +/* + * ib_utils_user_sa.c + */ + + +/** ========================================================================= + * As we remove the above functionality from the external interface we will + * want this functionality to remain available via internal header file. + * Move that functionaltiy here to protect against further ussage and we can + * rename this file after the conversion. + */ + +#ifdef OPAMGT_PRIVATE + +#include + +#define OMGT_MAX_CLASS 256 +#define OMGT_MAX_CLASS_VERSION 256 +#define OMGT_MAX_PKEYS 256 +#define OMGT_DEFAULT_PKEY 0xffff +#define OMGT_PKEY_MASK 0x7fff +#define OMGT_PKEY_FULL_BIT 0x8000 +#define OMGT_INVALID_AGENTID -1 +#define DEFAULT_USERSPACE_RECV_BUF 512 +#define DEFAULT_USERSPACE_SEND_BUF 128 +#define NOTICE_REG_TIMEOUT_MS 1000 /* 1sec */ +#define NOTICE_REG_RETRY_COUNT 15 + +enum omgt_reg_retry_state +{ + OMGT_RRS_SEND_INITIAL = 0, + OMGT_RRS_SEND_RETRY, +}; + +enum omgt_th_event +{ + OMGT_TH_EVT_NONE = 0, + OMGT_TH_EVT_SHUTDOWN, + OMGT_TH_EVT_UD_MONITOR_ON, + OMGT_TH_EVT_UD_MONITOR_OFF, + OMGT_TH_EVT_START_OUTSTANDING_REQ_TIME, + OMGT_TH_EVT_TRAP_MSG, + OMGT_TH_EVT_TRAP_REG_ERR_TIMEOUT, +}; + +struct omgt_thread_msg +{ + size_t size; + enum omgt_th_event evt; + uint8_t data[0]; +}; + +#define IBUSA_NOTICE_SUP_ENV "OMGT_IBUSA_NOTICE" + +struct ibv_sa_id; +struct omgt_sa_msg; + +typedef struct _omgt_sa_registration +{ + uint16_t trap_num; + struct ibv_sa_id *id; + void *user_context; /* for userspace notice, id == NULL */ + struct omgt_sa_msg *reg_msg; + struct _omgt_sa_registration *next; +} omgt_sa_registration_t; + +struct omgt_sa_msg { + struct omgt_sa_msg *prev; + struct omgt_sa_msg *next; + struct ibv_mr *mr; + struct ibv_sge sge; + union { + struct ibv_send_wr send; + struct ibv_recv_wr recv; + } wr; + int retries; + int status; + int in_q; + omgt_sa_registration_t *reg; + uint8_t data[2048]; +}; + +/** ========================================================================= */ +struct omgt_port { + int hfi_num; + char hfi_name[IBV_SYSFS_NAME_MAX]; + uint8_t hfi_port_num; + int umad_fd; + int umad_agents[OMGT_MAX_CLASS_VERSION][OMGT_MAX_CLASS]; + struct ibv_context *verbs_ctx; + + /* from omgt_sa_registry_t object */ + struct ibv_sa_event_channel *channel; + omgt_sa_registration_t *regs_list; + SEMAPHORE lock; + + /* cache of "port details" */ + SEMAPHORE umad_port_cache_lock; + umad_port_t umad_port_cache; + int umad_port_cache_valid; + pthread_t umad_port_thread; + int umad_port_sv[2]; + + /* Logging */ + FILE *dbg_file; + FILE *error_file; + + /* Timeout & Retries */ + int ms_timeout; + int retry_count; + + /* SA interaction for userspace Notice registration */ + struct ibv_comp_channel *sa_qp_comp_channel; + struct ibv_cq *sa_qp_cq; + struct ibv_pd *sa_qp_pd; + struct ibv_qp *sa_qp; + struct ibv_ah *sa_ah; + uint32_t next_tid; /* 32 bits only */ + int run_sa_cq_poll; + int poll_timeout_ms; + + int num_userspace_recv_buf; + int num_userspace_send_buf; + int outstanding_sends_cnt; + struct omgt_sa_msg pending_reg_msg_head; + struct omgt_sa_msg *recv_bufs; + + /* For SA Client interface */ + uint16_t sa_mad_status; + int sa_service_state; + uint32_t sa_capmask2; + + /* For PA/EA client interface */ + IB_GID local_gid; + FILE *verbose_file; + int pa_verbose; + int pa_service_state; + STL_LID primary_pm_lid; + uint8_t primary_pm_sl; + uint16_t pa_mad_status; + + int ea_service_state; + STL_LID primary_em_lid; + uint8_t primary_em_sl; + + /* For OOB client interface */ + boolean is_oob_enabled; /* Is port in FE OOB mode */ + struct net_connection *conn; + struct omgt_oob_input oob_input; + /* For OOB Notice interface */ + boolean is_oob_notice_setup; + struct net_connection *notice_conn; + /* For OOB SSL */ + boolean is_ssl_enabled; /* Is SSL enabled */ + boolean is_ssl_initialized; + void *ssl_context; + const SSL_METHOD *ssl_client_method; + boolean is_x509_store_initialized; + X509_STORE *x509_store; + boolean is_dh_params_initialized; + DH *dh_params; +}; + +/** + * Clears registration structures + * + * @param port port opened by omgt_open_port_* + * + * @return none + **/ +void omgt_sa_clear_regs_unsafe(struct omgt_port *port); + +int omgt_lock_sem(SEMAPHORE* const pSema); +void omgt_unlock_sem(SEMAPHORE * const pSema); +void omgt_sa_unreg_all(struct omgt_port *port); + +void handle_sa_ud_qp(struct omgt_port *port); +int stop_ud_cq_monitor(struct omgt_port *port); +int repost_pending_registrations(struct omgt_port *port); +int reregister_traps(struct omgt_port *port); +void omgt_sa_remove_all_pending_reg_msgs(struct omgt_port *port); + +int create_sa_qp(struct omgt_port *port); +int userspace_register(struct omgt_port *port, uint16_t trap_num, omgt_sa_registration_t *reg); +void omgt_sa_add_reg_unsafe(struct omgt_port *port, omgt_sa_registration_t *reg); +FSTATUS omgt_sa_remove_reg_by_trap_unsafe(struct omgt_port *port, uint16_t trap_num); + +#define LIST_INIT(obj) \ + (obj)->next = obj; \ + (obj)->prev = obj; + +#define LIST_ADD(head, new_obj) \ + (head)->prev->next = (new_obj); \ + (new_obj)->next = (head); \ + (new_obj)->prev = (head)->prev; \ + (head)->prev = (new_obj); + +#define LIST_DEL(obj) \ + (obj)->prev->next = (obj)->next; \ + (obj)->next->prev = (obj)->prev; \ + LIST_INIT(obj); + +#define LIST_FOR_EACH(head, item) \ + for (item = (head)->next; item != (head); item = item->next) + +#define LIST_EMPTY(head) \ + ((head) == (head)->next) + +#endif /* OPAMGT_PRIVATE */ + +#endif /* _IB_UTILS_OPENIB_H_ */ diff --git a/opamgt/src/iba2ibo_util_helper.c b/opamgt/src/iba2ibo_util_helper.c new file mode 100644 index 0000000..c7eb4e6 --- /dev/null +++ b/opamgt/src/iba2ibo_util_helper.c @@ -0,0 +1,191 @@ +/* BEGIN_ICS_COPYRIGHT7 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT7 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +#ifdef IB_STACK_OPENIB + + +#include +#include +#include +#include +#include +#include + +#define OPAMGT_PRIVATE 1 +#include "ibt.h" + +#include "ib_utils_openib.h" + +static FSTATUS unimplemented_fn (const char * fn) +{ + return(FSUCCESS); +} + +FSTATUS iba_init(void) +{ + return (unimplemented_fn (__func__)); +} + +FSTATUS iba_umadt_deregister( MADT_HANDLE serviceHandle) +{ + return (unimplemented_fn (__func__)); +} + +FSTATUS iba_umadt_get_sendmad(MADT_HANDLE serviceHandle, uint32 *madCount, MadtStruct** mad) +{ + return (unimplemented_fn (__func__)); +} + +FSTATUS iba_umadt_release_sendmad(MADT_HANDLE serviceHandle, MadtStruct *mad) +{ + //return (unimplemented_fn (__func__)); // Removed due to too many prints + return FSUCCESS; +} + +FSTATUS iba_umadt_release_recvmad(MADT_HANDLE serviceHandle, MadtStruct *mad) +{ + return (unimplemented_fn (__func__)); +} + +FSTATUS iba_umadt_post_send(MADT_HANDLE serviceHandle, MadtStruct *mad, MadAddrStruct *DestAddr) +{ + return (unimplemented_fn (__func__)); +} + +FSTATUS iba_umadt_wait_any_compl(MADT_HANDLE serviceHandle, uint32 completionType, uint32 timeout) +{ + return (unimplemented_fn (__func__)); +} + +FSTATUS iba_umadt_poll_recv_compl(MADT_HANDLE serviceHandle, MadtStruct **mad, MadWorkCompletion **ppWorkCmpletion) +{ + return (unimplemented_fn (__func__)); +} + +FSTATUS iba_umadt_poll_send_compl(MADT_HANDLE serviceHandle, MadtStruct **mad, MadWorkCompletion **ppWorkCmpletion) +{ + //return (unimplemented_fn (__func__)); // Removed due to too many prints + return 0; +} + +void flush_rcv(MADT_HANDLE umadtHandle, int timeout) +{ + unimplemented_fn (__func__); +} + +/////////////////////////////////////////////////////////// +// // +// IMPLEMENTED FUNCTIONS WITH OFED EQUIVALENTS // +// // +/////////////////////////////////////////////////////////// + +FSTATUS iba_get_caguids_alloc(uint32 *CaCount,EUI64 **CaGuidList) +{ + // Call OFED equivalent + return (omgt_get_caguids(CaCount, CaGuidList)); +} + +FSTATUS iba_query_ca_by_guid_alloc(IN EUI64 CaGuid,OUT IB_CA_ATTRIBUTES *CaAttributes ) +{ + // Call OFED equivalent + return (omgt_query_ca_by_guid_alloc(CaGuid, CaAttributes)); +} + +FSTATUS iba_query_ca_by_guid(IN EUI64 CaGuid,OUT IB_CA_ATTRIBUTES *CaAttributes ) +{ + // Call OFED equivalent + return (omgt_query_ca_by_guid(CaGuid, CaAttributes)); +} + + +FSTATUS iba_get_portguid( + IN uint32 ca, + IN uint32 port, + OUT EUI64 *pCaGuid OPTIONAL, + OUT EUI64 *pPortGuid OPTIONAL, + OUT IB_CA_ATTRIBUTES *pCaAttributes OPTIONAL, + OUT IB_PORT_ATTRIBUTES **ppPortAttributes OPTIONAL, + OUT uint32 *pCaCount OPTIONAL, + OUT uint32 *pPortCount OPTIONAL + ) +{ + return (omgt_get_portguid(ca, port, NULL, NULL, pCaGuid, pPortGuid, pCaAttributes, ppPortAttributes, + pCaCount, pPortCount, NULL, NULL, NULL)); + +} + +/* format an error message when iba_get_portguid returns FNOT_FOUND + * + * INPUTS: + * ca, port - inputs provided to failed call to iba_get_portguid + * CaCount, PortCount - outputs returned by failed call to iba_get_portguid + * + * RETURNS: + * string formatted with error message. This is a pointer into a static + * string which will be invalidated upon next call to this function. + */ +const char* +iba_format_get_portguid_error( + IN uint32 ca, + IN uint32 port, + IN uint32 caCount, + IN uint32 portCount + ) +{ + static char errstr[80]; + + if (ca) { + if (portCount) { + if (port) { + sprintf(errstr, "Invalid port number: %u, FI %u only has %u Ports", + port, ca, portCount); + } else { + sprintf(errstr, "No Active Ports found on FI %u", ca); + } + } else { + sprintf(errstr,"Invalid FI number: %u, only have %u FIs", + ca, caCount); + } + } else { + if (portCount) { + if (port) { + sprintf(errstr, "Invalid port number: %u, System only has %u Ports", + port, portCount); + } else { + sprintf(errstr, "No Active ports found in System"); + } + } else { + sprintf(errstr,"No FIs found in System"); + } + } + return errstr; +} +#endif diff --git a/opamgt/src/omgt_oob_connections.c b/opamgt/src/omgt_oob_connections.c new file mode 100644 index 0000000..9f65c3c --- /dev/null +++ b/opamgt/src/omgt_oob_connections.c @@ -0,0 +1,206 @@ +/* BEGIN_ICS_COPYRIGHT5 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT5 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +#include +#include + +#define OPAMGT_PRIVATE 1 +#include "ib_utils_openib.h" +#include "omgt_oob_net.h" +#include "omgt_oob_protocol.h" +#include "opamgt_dump_mad.h" + +OMGT_STATUS_T omgt_oob_connect(struct omgt_port **port, struct omgt_oob_input *oob_input, struct omgt_params *session_params) +{ + struct omgt_port *prt = calloc(1, sizeof(struct omgt_port)); + struct net_connection *conn = NULL; + FSTATUS status = FSUCCESS; + + if (prt == NULL) { + return OMGT_STATUS_INSUFFICIENT_MEMORY; + } + + /* Copy session_params into port struct */ + if (session_params) { + prt->dbg_file = session_params->debug_file; + prt->error_file = session_params->error_file; + } else { + prt->dbg_file = NULL; + prt->error_file = NULL; + } + + prt->ms_timeout = OMGT_DEF_TIMEOUT_MS; + prt->retry_count = OMGT_DEF_RETRY_CNT; + + /* copy login info into port struct */ + prt->oob_input = *oob_input; + + prt->is_oob_enabled = TRUE; + /* Establish a connection to the host */ + OMGT_DBGPRINT(prt, "establish a connection to host\n"); + if ((status = omgt_oob_net_connect(prt, &conn)) != FSUCCESS) { + OMGT_OUTPUT_ERROR(prt, "failed to establish a connection to the host: %u\n", status); + if (prt->is_ssl_enabled && prt->is_ssl_initialized) { + if (prt->x509_store) { + X509_STORE_free(prt->x509_store); + prt->x509_store = NULL; + prt->is_x509_store_initialized = 0; + } + if (prt->dh_params) { + DH_free(prt->dh_params); + prt->dh_params = NULL; + prt->is_dh_params_initialized = 0; + } + if (prt->ssl_context) { + SSL_CTX_free(prt->ssl_context); + prt->ssl_context = NULL; + } + + ERR_free_strings(); + prt->is_ssl_initialized = 0; + } + free(prt); + return OMGT_STATUS_UNAVAILABLE; + } + prt->conn = conn; + prt->is_oob_notice_setup = FALSE; + *port = prt; + return OMGT_STATUS_SUCCESS; +} + +FSTATUS omgt_oob_disconnect(struct omgt_port *port, struct net_connection *conn) +{ + FSTATUS status = FSUCCESS; + + if (conn) { + if (port->is_ssl_enabled) { + if (conn->ssl_session) { + (void)SSL_shutdown(conn->ssl_session); + SSL_free(conn->ssl_session); + conn->ssl_session = NULL; + } + } + if ((status = omgt_oob_net_disconnect(port, conn)) != FSUCCESS) { + OMGT_OUTPUT_ERROR(port, "failed to disconnect from socket: %u\n", status); + } + } + return status; +} + +FSTATUS omgt_oob_send_packet(struct omgt_port *port, uint8_t *data, size_t len) +{ + OOB_PACKET packet; + + memset(&packet, 0, sizeof(OOB_PACKET)); + packet.MadData = *((MAD_RMPP *)data); + packet.Header.HeaderVersion = STL_BASE_VERSION; + + /* Update length of payload in header */ + packet.Header.Length = len; + BSWAP_OOB_HEADER(&(packet.Header)); + + len += sizeof(OOB_HEADER) + sizeof(RMPP_HEADER); + + /* Do nothing if no conn */ + if (!port || !port->conn) + return FINVALID_PARAMETER; + + /* Send the header and payload */ + return omgt_oob_net_send(port, (uint8_t *)&packet, len); +} + +FSTATUS omgt_oob_receive_response(struct omgt_port *port, uint8_t **data, uint32_t *len) +{ + OOB_PACKET *packet = NULL; + FSTATUS e; + + boolean data_null; + boolean response_acquired; + struct timeval start, current; + uint64_t delta_ms, total_timeout; + + /* Do nothing if no conn */ + if (!port || !port->conn) + return FINVALID_PARAMETER; + + /* Get response from server */ + response_acquired = FALSE; + while (response_acquired != TRUE) { + e = FSUCCESS; + data_null = TRUE; + (void)gettimeofday(&start, NULL); + (void)gettimeofday(¤t, NULL); + delta_ms = 0; + total_timeout = port->ms_timeout * (port->retry_count + 1); + while (delta_ms < total_timeout && data_null) { + omgt_oob_net_process(port, port->conn, 100, 1); + omgt_oob_net_get_next_message(port->conn, (uint8_t **)&packet, (int *)len); + if (packet != NULL) { + data_null = FALSE; + } else { + if (port->conn->err) { + return FERROR; + } + (void)gettimeofday(¤t, NULL); + /* Get Delta in ms */ + delta_ms = ((current.tv_sec - start.tv_sec) * 1000) + ((current.tv_usec - start.tv_usec) / 1000); + } + } + if (data_null == TRUE) { + e = FTIMEOUT; + response_acquired = TRUE; + } else { + *len = 0; + BSWAP_OOB_HEADER(&(packet->Header)); + *len = packet->Header.Length; + + if (port->dbg_file) { + OMGT_DBGPRINT(port, "Received MAD: socket %d, length=%u\n", port->conn->sock, *len); + omgt_dump_mad(port->dbg_file, (uint8_t *)&(packet->MadData), *len, "rcv mad\n"); + } + + // Allocate and copy to new buffer + *data = calloc(1, *len); + if (*data == NULL) { + OMGT_OUTPUT_ERROR(port, "can't alloc return buffer length %u\n", *len); + return FINSUFFICIENT_MEMORY; + } + memcpy(*data, (uint8_t *)&(packet->MadData), *len); + + response_acquired = TRUE; + } + } + if (packet != NULL) { + free(packet); + } + return e; +} + diff --git a/opamgt/src/omgt_oob_net.c b/opamgt/src/omgt_oob_net.c new file mode 100644 index 0000000..a2079d5 --- /dev/null +++ b/opamgt/src/omgt_oob_net.c @@ -0,0 +1,585 @@ +/* BEGIN_ICS_COPYRIGHT5 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT5 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "imath.h" + +#define OPAMGT_PRIVATE 1 + +#include "ib_utils_openib.h" +#include "omgt_oob_net.h" +#include "omgt_oob_ssl.h" +#include "opamgt_dump_mad.h" + +#define CONNECTION_BACKLOG 10 + +#define SET_ERROR(x,y) if (x) { *(x)=(y); } +#define NET_MAGIC 0x31E0CC01 + +static FSTATUS omgt_oob_read_from_socket(struct omgt_port *port, struct net_connection *conn); +static FSTATUS omgt_oob_write_to_socket(struct omgt_port *port, struct net_connection *conn); +static struct net_connection* omgt_oob_new_connection(); +static FSTATUS omgt_oob_print_addrinfo(struct omgt_port *port, char *hostname, uint16_t conn_port); + + +/** + * @brief Establish a connection to the given host. + * @param port port object with connection info + * @return FSTATUS + */ +FSTATUS omgt_oob_net_connect(struct omgt_port *port, struct net_connection **cnn) +{ + struct net_connection *conn = NULL; + struct sockaddr_in v4_addr; + struct sockaddr_in6 v6_addr; + struct in_addr ipv4addr; + struct in6_addr ipv6addr; + struct hostent *hp = NULL; + int inaddr = 0; + int ipv6 = 0; + + /* Set Timeout to default value if incorrect value */ + if (port->ms_timeout <= 0) { + port->ms_timeout = OMGT_DEF_TIMEOUT_MS; + } + if (port->retry_count < 0) { + port->retry_count = OMGT_DEF_RETRY_CNT; + } + /* First resolve the hostname and fill in the sockaddr */ + inaddr = inet_pton(AF_INET6, port->oob_input.host, &ipv6addr); + + if ((ipv6 = (inaddr == 1) ? 1 : 0)) { + memset((void *)&v6_addr, 0, sizeof(v6_addr)); + v6_addr.sin6_family = AF_INET6; + v6_addr.sin6_port = htons((short)port->oob_input.port); + memcpy((void *)&v6_addr.sin6_addr, (void *)&ipv6addr, sizeof(ipv6addr)); + + if (port->dbg_file) { + (void)omgt_oob_print_addrinfo(port, port->oob_input.host, port->oob_input.port); + } + } else { + memset((void *)&v4_addr, 0, sizeof(v4_addr)); + v4_addr.sin_family = AF_INET; + v4_addr.sin_port = htons((short)port->oob_input.port); + inaddr = inet_pton(AF_INET, port->oob_input.host, &ipv4addr); + + if (inaddr == 1) { + memcpy((void *)&v4_addr.sin_addr, (void *)&ipv4addr, sizeof(ipv4addr)); + } else { + hp = gethostbyname(port->oob_input.host); + if (hp == NULL) { + OMGT_OUTPUT_ERROR(port, "invalid hostname (%s).\n", port->oob_input.host); + return FINVALID_PARAMETER; + } + memcpy((void *)&v4_addr.sin_addr, hp->h_addr, hp->h_length); + } + } + + /* Next, create a socket and attempt the connection */ + conn = omgt_oob_new_connection(); + if (conn == NULL) { + OMGT_OUTPUT_ERROR(port, "no memory for connection.\n"); + return FINSUFFICIENT_MEMORY; + } + conn->ipv6 = ipv6; + conn->sock = socket((conn->ipv6) ? AF_INET6 : AF_INET, SOCK_STREAM, 0); + if (conn->sock == INVALID_SOCKET) { + OMGT_OUTPUT_ERROR(port, "invalid socket.\n"); + free(conn); + return FINVALID_STATE; + } + + if (connect(conn->sock, + (conn->ipv6) ? (struct sockaddr *)&v6_addr : (struct sockaddr *)&v4_addr, + (conn->ipv6) ? sizeof(v6_addr) : sizeof(v4_addr)) == SOCKET_ERROR) { + + OMGT_OUTPUT_ERROR(port, "cannot connect to socket.\n"); + goto bail; + } + + if (conn->ipv6) { + conn->v6_addr = v6_addr; + } else { + conn->v4_addr = v4_addr; + } + + OMGT_DBGPRINT(port, "Out-bound connection to %s port %d (conn #%d) established.\n", + port->oob_input.host, port->oob_input.port, conn->sock); + + // Should we setup SSL/TLS + if (port->oob_input.ssl_params.enable) { + port->is_ssl_enabled = TRUE; + if (omgt_oob_ssl_init(port)) { + OMGT_OUTPUT_ERROR(port, "cannot initialize SSL/TLS\n"); + goto bail; + } + + if (port->ssl_context == NULL) { + // open SSL/TLS connection + if (!(port->ssl_context = omgt_oob_ssl_client_open(port, + port->oob_input.ssl_params.directory, + port->oob_input.ssl_params.certificate, + port->oob_input.ssl_params.private_key, + port->oob_input.ssl_params.ca_certificate, + port->oob_input.ssl_params.cert_chain_depth, + port->oob_input.ssl_params.dh_params, + port->oob_input.ssl_params.ca_crl_enable, + port->oob_input.ssl_params.ca_crl))) { + OMGT_OUTPUT_ERROR(port, "cannot open SSL/TLS connection\n"); + goto bail; + } + } + + // establish SSL/TLS session + conn->ssl_session = omgt_oob_ssl_connect(port, port->ssl_context, conn->sock); + if (!conn->ssl_session) { + OMGT_OUTPUT_ERROR(port, "cannot establish SSL/TLS session\n"); + goto bail; + } + } + + *cnn = conn; + return FSUCCESS; + +bail: + close(conn->sock); + conn->sock = INVALID_SOCKET; + free(conn); + return FERROR; +} + +FSTATUS omgt_oob_net_disconnect(struct omgt_port *port, struct net_connection *conn) +{ + struct net_blob *blob; + int nr, ns; + + if (!conn || conn->sock == INVALID_SOCKET) { + return FINVALID_PARAMETER; + } + + close(conn->sock); + conn->sock = INVALID_SOCKET; + + /* + * Delete all enqueued blobs + */ + ns = 0; + while (!omgt_oob_queue_empty(&conn->send_queue)) { + blob = omgt_oob_dequeue_net_blob(&conn->send_queue); + if (blob) omgt_oob_free_net_blob(blob); + ++ns; + } + nr = 0; + while (!omgt_oob_queue_empty(&conn->recv_queue)) { + blob = omgt_oob_dequeue_net_blob(&conn->recv_queue); + if (blob) omgt_oob_free_net_blob(blob); + ++nr; + } + + OMGT_DBGPRINT(port, "closed connection %d, deleted %d send %d recv blobs\n", + conn->sock, ns, nr); + + free(conn); + + return FSUCCESS; +} + +/* + * Pack up the given data into a struct net_blob to be sent over the given + * connection. Simply enqueue the blob here. omgt_oob_net_sleep() will take + * care of the actual sending. + */ +FSTATUS omgt_oob_net_send(struct omgt_port *port, uint8_t *data, int len) +{ + int magic; + int tot_len; + struct net_blob *blob; + + if (!port || !port->conn) { + return FINVALID_PARAMETER; + } + if (port->conn->sock == INVALID_SOCKET) { + return FINVALID_PARAMETER; + } + + /* + * Copy the given data, prepended by a magic # and the tot msg len, + * into the blob. + */ + tot_len = len + 2 * sizeof(int); + blob = omgt_oob_new_net_blob(tot_len); + if (blob == NULL || blob->data == NULL) { + if (blob) omgt_oob_free_net_blob(blob); + return FINSUFFICIENT_MEMORY; + } + magic = htonl(NET_MAGIC); + memcpy((void *)blob->data, (void *)&magic, sizeof(int)); + tot_len = htonl(tot_len); + memcpy((void *)(blob->data + sizeof(int)), (void *)&tot_len, sizeof(int)); + memcpy((void *)(blob->data + 2 * sizeof(int)), (void *)data, len); + + if (port->dbg_file) { + OMGT_DBGPRINT(port, ">>> sending: len %d pktsz %d\n", len, tot_len); + omgt_dump_mad(port->dbg_file, data, len, "send mad\n"); + } + + omgt_oob_enqueue_net_blob(&port->conn->send_queue, blob); + + OMGT_DBGPRINT(port, "sent %d bytes at %p over conn %d\n", len, (void *)data, port->conn->sock); + + return FSUCCESS; +} + +/* + * Return the next message in the given connection's receive queue, NULL if none. + */ +void omgt_oob_net_get_next_message(struct net_connection *conn, uint8_t **data, int *len) +{ + struct net_blob *blob; + + if (conn == NULL) { + if (data) { + *data = NULL; + } + if (len) { + *len = 0; + } + return; + } + + blob = omgt_oob_dequeue_net_blob(&conn->recv_queue); + if (blob == NULL) { + if (data) { + *data = NULL; + } + if (len) { + *len = 0; + } + return; + } else { + if (data) { + *data = blob->data; + } + if (len) { + *len = blob->len; + } + blob->data = NULL; /* so omgt_oob_free_net_blob() won't free the data */ + omgt_oob_free_net_blob(blob); + return; + } +} + +static FSTATUS omgt_oob_read_from_socket(struct omgt_port *port, struct net_connection *conn) +{ + ssize_t bytes_read; + struct net_blob *blob; + + /* + * If we're in the middle of a message, pick up where we left off. + * Otherwise, start reading a new message. + */ + if (conn->blob_in_progress == NULL) { + blob = omgt_oob_new_net_blob(0); + if (blob) { + blob->data = NULL; /* this flags that we haven't read the msg size yet */ + blob->cur_ptr = (uint8_t *)blob->magic; + blob->bytes_left = 2 * sizeof(int); + conn->blob_in_progress = blob; + } else { + OMGT_DBGPRINT(port, "Received NULL blob from socket."); + return FERROR; + } + } else { + blob = conn->blob_in_progress; + } + + if (port->is_ssl_enabled && port->is_ssl_initialized) { + bytes_read = omgt_oob_ssl_read(port, conn->ssl_session, blob->cur_ptr, blob->bytes_left); + } else { + bytes_read = recv(conn->sock, blob->cur_ptr, blob->bytes_left, 0); + } + + if (bytes_read == 0) { /* graceful shutdown */ + OMGT_DBGPRINT(port, "conn %d shut down gracefully\n", conn->sock); + return FERROR; + } else if (bytes_read == SOCKET_ERROR) { + OMGT_DBGPRINT(port, "err %zd, %d over connection %d\n", bytes_read, errno, conn->sock); + return FERROR; + } else { + if (bytes_read < blob->bytes_left) { /* still more to read */ + omgt_oob_adjust_blob_cur_ptr(blob, bytes_read); + OMGT_DBGPRINT(port, "read %zu bytes over conn %d, %zu bytes to go\n", + bytes_read, conn->sock, blob->bytes_left); + return FSUCCESS; + } else { + if (blob->data == NULL) { /* NULL means we just finished reading msg size */ + /* if we didn't get the magic, DISCONNECT this connection */ + if (ntohl(blob->magic[0]) != NET_MAGIC) { + OMGT_OUTPUT_ERROR(port, "Read/write error over connection %d\n", conn->sock); + omgt_oob_free_net_blob(blob); + return FERROR; + } + + blob->len = ntohl(blob->magic[1]) - 2 * sizeof(int); + blob->data = malloc(blob->len); + if (blob->data == NULL) { + /* No memory! Bail out and disconnect, since we have to lose this msg */ + omgt_oob_free_net_blob(blob); + return FERROR; + } + blob->cur_ptr = blob->data; + blob->bytes_left = blob->len; + OMGT_DBGPRINT(port, "read %zd bytes over conn %d, start reading size %zu\n", + bytes_read, conn->sock, blob->len); + return FSUCCESS; + } else { /* we just finished reading the user data -- enqueue blob */ + blob->bytes_left = 0; + blob->cur_ptr = NULL; + omgt_oob_enqueue_net_blob(&conn->recv_queue, blob); + conn->blob_in_progress = NULL; + OMGT_DBGPRINT(port, "read %zd bytes over conn %d, finish reading msg of size %zu\n", + bytes_read, conn->sock, blob->len); + return FSUCCESS; + } + } + } +} + +static FSTATUS omgt_oob_write_to_socket(struct omgt_port *port, struct net_connection *conn) +{ + ssize_t bytes_sent; + struct net_blob *blob; + + if (omgt_oob_queue_empty(&conn->send_queue)) { + return FSUCCESS; + } + + blob = omgt_oob_peek_net_blob(&conn->send_queue); + + /* + * #define TEST if you want to stress test message fragmentation. + * Leave undefined for release build. + */ +#ifdef TEST + xxx = blob->bytes_left / 2; + if (xxx == 0) { + xxx = blob->bytes_left; + } + if (port->is_ssl_enabled && port->is_ssl_initialized) { + bytes_sent = omgt_oob_ssl_write(port, conn->ssl_session, blob->cur_ptr, xxx); + } else { + bytes_sent = send(conn->sock, blob->cur_ptr, xxx, 0); + } +#else + if (port->is_ssl_enabled && port->is_ssl_initialized) { + bytes_sent = omgt_oob_ssl_write(port, conn->ssl_session, blob->cur_ptr, blob->bytes_left); + } else { + bytes_sent = send(conn->sock, blob->cur_ptr, blob->bytes_left, 0); + } +#endif + + OMGT_DBGPRINT(port, "wrote %zd bytes over conn %d\n", bytes_sent, conn->sock); + + if (bytes_sent == SOCKET_ERROR) { + /* + * If we couldn't send because the send() would block, then just + * return. We'll try again next time. + */ + if (errno == EWOULDBLOCK) { + return FSUCCESS; + } else { + return FERROR; + } + } else { + /* + * If we sent the entire message, destroy it and go on to the next one + * in the queue. Otherwise, return; we'll continue were we left off + * next time. + */ + if (bytes_sent == blob->bytes_left) { + blob = omgt_oob_dequeue_net_blob(&conn->send_queue); + if (blob) omgt_oob_free_net_blob(blob); + return FSUCCESS; + } else { + omgt_oob_adjust_blob_cur_ptr(blob, bytes_sent); + return FSUCCESS; + } + } +} + +static struct net_connection* omgt_oob_new_connection() +/* + * Return a new struct net_connection object. + */ +{ + struct net_connection *conn = malloc(sizeof(struct net_connection)); + if (conn == NULL) { + return NULL; + } + + conn->sock = INVALID_SOCKET; + omgt_oob_init_queue(&conn->send_queue); + omgt_oob_init_queue(&conn->recv_queue); + conn->blob_in_progress = NULL; + conn->err = 0; + return conn; +} + +/** + * @brief Listen on connection for data + * + * Put the connection to sleep and wait for the specified time to awake. Listens + * for data to be sent and received and calls the appropriate read/write socket + * function. + * + * @param port port object + * @param conn connection to listen on + * @param msec_to_wait number of milliseconds to wait + * @param blocking specifies whether to block while sleeping + * + * @return None + */ +void omgt_oob_net_process(struct omgt_port *port, struct net_connection *conn, int msec_to_wait, int blocking) +{ + int n, nfds; + fd_set readfds, writefds, errorfds; + int queued_data = 0, inprogress_data = 0; + struct timeval timeout = {0}; + + /* Do nothing if no conn */ + if (!port || !conn) + return; + + /* + * Do a select on the listen socket (to catch new connections), + * on all in-bound sockets, and on those out-bound sockets for + * which we have traffic enqueued. If blocking!=0, do the select + * even if there's nothing to listen for (so we will wait msec_to_wait + * always). + */ + FD_ZERO(&errorfds); + FD_ZERO(&readfds); + FD_ZERO(&writefds); + nfds = 0; + + FD_SET(conn->sock, &readfds); + nfds = MAX(nfds, (int)conn->sock); + if (!omgt_oob_queue_empty(&conn->send_queue)) { + queued_data++; + nfds = MAX(nfds, (int)conn->sock); + FD_SET(conn->sock, &writefds); + } + if (conn->blob_in_progress) { + inprogress_data++; + } + + if ((nfds == 0) && !blocking) { + return; + } + ++nfds; + + if (msec_to_wait > 0) { + timeout.tv_sec = msec_to_wait / 1000; + timeout.tv_usec = (msec_to_wait % 1000) * 1000; + } + n = select(nfds, &readfds, &writefds, &errorfds, (msec_to_wait < 0 ? NULL : &timeout)); + + if (n == SOCKET_ERROR) { + return; + } + if (n == 0 && inprogress_data == 0) { + return; + } + + if (FD_ISSET(conn->sock, &writefds) || !omgt_oob_queue_empty(&conn->send_queue)) { + conn->err = omgt_oob_write_to_socket(port, conn); + } + if (conn->err == 0 && + (FD_ISSET(conn->sock, &readfds) || conn->blob_in_progress)) + { + conn->err = omgt_oob_read_from_socket(port, conn); + } + + if (conn->err) { + OMGT_OUTPUT_ERROR(port, "Read/write error over connection %d\n", conn->sock); + } + + return; +} + +static FSTATUS omgt_oob_print_addrinfo(struct omgt_port *port, char *hostname, uint16_t conn_port) +{ + int erc; + struct addrinfo hints; + struct addrinfo *res = NULL; + struct addrinfo *ai; + char host_bfr[NI_MAXHOST]; + char serv_bfr[NI_MAXSERV]; + char port_bfr[NI_MAXSERV]; + + memset(&hints, 0, sizeof(hints)); + hints.ai_family = PF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + hints.ai_flags |= AI_CANONNAME; + snprintf(port_bfr, NI_MAXSERV, "%u", conn_port); + erc = getaddrinfo(hostname, port_bfr, &hints, &res); + + if (erc != 0 || !res) { + OMGT_DBGPRINT(port, "Unable to get addressing information on IP address\n"); + return FERROR; + } + + for (ai = res; ai != NULL; ai = ai->ai_next) { + OMGT_DBGPRINT(port, + "Setting up a socket connection based on the following address info:\n" + " IP Version: %s\n IP Proto: %s\n", + (ai->ai_family == PF_INET ? "IPv4" : "IPv6"), + (ai->ai_protocol == IPPROTO_TCP ? "TCP" : "UDP")); + + getnameinfo(ai->ai_addr, ai->ai_addrlen, host_bfr, sizeof(host_bfr), serv_bfr, + sizeof(serv_bfr), NI_NUMERICHOST | NI_NUMERICSERV); + + OMGT_DBGPRINT(port, + " IP Address: %s\n Port: %s\n", + host_bfr, serv_bfr); + } + if (res) + freeaddrinfo(res); + return FSUCCESS; +} diff --git a/opamgt/src/omgt_oob_net.h b/opamgt/src/omgt_oob_net.h new file mode 100644 index 0000000..d417db7 --- /dev/null +++ b/opamgt/src/omgt_oob_net.h @@ -0,0 +1,86 @@ +/* BEGIN_ICS_COPYRIGHT2 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT2 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +#ifndef _OMGT_OOB_NET_H_ +#define _OMGT_OOB_NET_H_ + +#include +#include +#include +#include +#include +#include +#include "ibyteswap.h" + +#include "ib_utils_openib.h" +#include "omgt_oob_net_blob.h" +#include "omgt_oob_net_queue.h" + +/************************************************************************** +* struct net_connection Structures +**************************************************************************/ + +/* + * A net_connection encapsulates a logical network connection between + * client and server. More than one net_connection can exist between + * two given machines. Here we store the blobs queued up for send but + * not yet sent, and the blobs received and ready to be processed. + */ +struct net_connection { + int sock; + net_queue_t send_queue; + net_queue_t recv_queue; + struct net_blob *blob_in_progress; + int err; /* to indicate err on this connection */ + struct sockaddr_in v4_addr; /* socket IPv4 address of peer */ + struct sockaddr_in6 v6_addr; /* socket IPv6 address of peer */ + int ipv6; /* specify ipv6 or ipv4 as domain family */ + /* SSL */ + void *ssl_session; +}; + +/* Error defines */ +#define INVALID_SOCKET -1 +#define SOCKET_ERROR -1 + +/* Net connection functions */ +FSTATUS omgt_oob_net_connect(struct omgt_port *port, struct net_connection **conn); +FSTATUS omgt_oob_net_disconnect(struct omgt_port *port, struct net_connection *conn); +void omgt_oob_net_process(struct omgt_port *port, struct net_connection *conn, int msec_to_wait, int blocking); +FSTATUS omgt_oob_net_send(struct omgt_port *port, uint8_t *data, int len); +void omgt_oob_net_get_next_message(struct net_connection *conn, uint8_t **data, int *len); + +/* Connection functions */ +FSTATUS omgt_oob_send_packet(struct omgt_port *port, uint8_t *buf, size_t len); +FSTATUS omgt_oob_receive_response(struct omgt_port *port, uint8_t **data, uint32_t *len); +FSTATUS omgt_oob_disconnect(struct omgt_port *port, struct net_connection *conn); + +#endif /* _OMGT_OOB_NET_H_ */ diff --git a/opamgt/src/omgt_oob_net_blob.c b/opamgt/src/omgt_oob_net_blob.c new file mode 100644 index 0000000..9046de8 --- /dev/null +++ b/opamgt/src/omgt_oob_net_blob.c @@ -0,0 +1,83 @@ +/* BEGIN_ICS_COPYRIGHT5 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT5 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +#include +#include +#include +#include "omgt_oob_net.h" + +/* + * Return a new net_blob object with an allocated buffer of size len bytes. + */ +struct net_blob *omgt_oob_new_net_blob(size_t len) +{ + struct net_blob *blob = (struct net_blob *)malloc(sizeof(struct net_blob)); + if (blob == NULL) { + return NULL; + } + if (len) { + blob->data = malloc(len); + if (blob->data == NULL) { + free(blob); + return NULL; + } + } else { + blob->data = NULL; + } + blob->len = len; + blob->bytes_left = len; + blob->cur_ptr = blob->data; + blob->next = NULL; + return blob; +} + +void omgt_oob_free_net_blob(struct net_blob *blob) +{ + free(blob->data); + free(blob); +} + +void omgt_oob_free_net_buf(char *buf) +{ + free(buf); +} + +void omgt_oob_adjust_blob_cur_ptr(struct net_blob *blob, int bytes_sent) +{ + ASSERT(blob); + ASSERT(blob->cur_ptr); + ASSERT(blob->cur_ptr >= blob->data); + ASSERT(blob->bytes_left <= blob->len); + ASSERT(bytes_sent <= blob->bytes_left); + + blob->bytes_left -= bytes_sent; + blob->cur_ptr += bytes_sent; +} diff --git a/opamgt/src/omgt_oob_net_blob.h b/opamgt/src/omgt_oob_net_blob.h new file mode 100644 index 0000000..0c8744c --- /dev/null +++ b/opamgt/src/omgt_oob_net_blob.h @@ -0,0 +1,58 @@ +/* BEGIN_ICS_COPYRIGHT2 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT2 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +#ifndef _OMGT_OOB_NET_BLOB_H_ +#define _OMGT_OOB_NET_BLOB_H_ + +/* + * A net_blob encapsulates the raw data of a message along with state + * information needed to retrieve the message. + * + * On send, we pack a magic#,len in front of the user data. + * On recv, we read magic#,len into magic[] then put user data into data. + * Be careful about this difference! + */ +struct net_blob { + size_t len; /* length of what data points to */ + uint8_t *data; /* ptr to user data (recv) or magic#,len,userdata (send) */ + ssize_t bytes_left; /* # bytes of this msg left to send/recv */ + uint8_t *cur_ptr; /* ptr into buffer where next byte sent/recvd will go */ + uint32_t magic[2]; /* buffer for reading magic#, message len */ + struct net_blob *next; /* next blob in the queue */ +}; + +/* Function prototypes */ +struct net_blob *omgt_oob_new_net_blob(size_t len); +void omgt_oob_free_net_buf(char *buf); +void omgt_oob_free_net_blob(struct net_blob *blob); +void omgt_oob_adjust_blob_cur_ptr(struct net_blob *blob, int bytes_sent); + +#endif /* _OMGT_OOB_NET_BLOB_H_ */ diff --git a/opamgt/src/omgt_oob_net_queue.c b/opamgt/src/omgt_oob_net_queue.c new file mode 100644 index 0000000..0d261d9 --- /dev/null +++ b/opamgt/src/omgt_oob_net_queue.c @@ -0,0 +1,74 @@ +/* BEGIN_ICS_COPYRIGHT5 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT5 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +#include "omgt_oob_net.h" + +void omgt_oob_init_queue(net_queue_t *q) +{ + q->head = q->tail = NULL; +} + +void omgt_oob_enqueue_net_blob(net_queue_t *q, struct net_blob *blob) +{ + if (q->head == NULL) { + q->head = blob; + q->tail = blob; + blob->next = NULL; + } else { + q->tail->next = blob; + q->tail = blob; + blob->next = NULL; + } +} + +struct net_blob *omgt_oob_dequeue_net_blob(net_queue_t *q) +{ + struct net_blob *retval = NULL; + + if (q->head) { + retval = q->head; + q->head = q->head->next; + /* Note: q->tail won't be NULL once q->head advances to NULL, */ + /* but omgt_oob_enqueue_net_blob only tests q->head to determine emptiness */ + } + + return retval; +} + +struct net_blob *omgt_oob_peek_net_blob(net_queue_t *q) +{ + return q->head; +} + +int omgt_oob_queue_empty(net_queue_t *q) +{ + return q->head == NULL; +} diff --git a/opamgt/src/omgt_oob_net_queue.h b/opamgt/src/omgt_oob_net_queue.h new file mode 100644 index 0000000..2c024b1 --- /dev/null +++ b/opamgt/src/omgt_oob_net_queue.h @@ -0,0 +1,51 @@ +/* BEGIN_ICS_COPYRIGHT2 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT2 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +#ifndef _OMGT_OOB_NET_QUEUE_H_ +#define _OMGT_OOB_NET_QUEUE_H_ + +/* + * A net_queue is simply a queue of net_blobs. + */ +struct net_queue { + struct net_blob *head; + struct net_blob *tail; +}; +typedef struct net_queue net_queue_t; + +/* Function prototypes */ +void omgt_oob_init_queue(net_queue_t *q); +void omgt_oob_enqueue_net_blob(net_queue_t *q, struct net_blob *blob); +struct net_blob *omgt_oob_dequeue_net_blob(net_queue_t *q); +struct net_blob *omgt_oob_peek_net_blob(net_queue_t *q); +int omgt_oob_queue_empty(net_queue_t *q); + +#endif /* _OMGT_OOB_NET_QUEUE_H_ */ diff --git a/opamgt/src/omgt_oob_protocol.h b/opamgt/src/omgt_oob_protocol.h new file mode 100644 index 0000000..6719460 --- /dev/null +++ b/opamgt/src/omgt_oob_protocol.h @@ -0,0 +1,61 @@ +/* BEGIN_ICS_COPYRIGHT2 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT2 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +#ifndef _OMGT_OOB_PROTOCOL_H_ +#define _OMGT_OOB_PROTOCOL_H_ + +#include "iba/ib_generalServices.h" + +/************************************************************************** +* OOB PROTOCOL STRUCTURES +**************************************************************************/ +typedef struct __OOB_HEADER { + uint32_t HeaderVersion; /* Version of the FE protocol header */ + uint32_t Length; /* Length of the message data payload */ + uint32_t Reserved[2]; /* Reserved */ +} OOB_HEADER; + +/* Header byte swap for OOB network transmission */ +static __inline +void BSWAP_OOB_HEADER(OOB_HEADER *header) +{ + header->HeaderVersion = ntoh32(header->HeaderVersion); + header->Length = ntoh32(header->Length); + header->Reserved[0] = 0; + header->Reserved[1] = 0; +} + +typedef struct _OOB_PACKET { + OOB_HEADER Header; + MAD_RMPP MadData; +} OOB_PACKET; + +#endif /* _OMGT_OOB_PROTOCOL_H_ */ diff --git a/opamgt/src/omgt_oob_ssl.c b/opamgt/src/omgt_oob_ssl.c new file mode 100644 index 0000000..3d53170 --- /dev/null +++ b/opamgt/src/omgt_oob_ssl.c @@ -0,0 +1,480 @@ +/* BEGIN_ICS_COPYRIGHT5 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + * ** END_ICS_COPYRIGHT5 ****************************************/ +/* [ICS VERSION STRING: unknown] */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#define OPAMGT_PRIVATE 1 +#include "ib_utils_openib.h" +#include "omgt_oob_ssl.h" + +#define DNS_NAME_MAX_LENGTH 256 +#define FE_SSL_FM_DNS_NAME ".com" + +#define FE_SSL_CIPHER_LIST "ECDHE-ECDSA-AES128-GCM-SHA256:DHE-DSS-AES256-SHA" + +// Include all workaround patches. Exclude versions SSLv2, SSLv3, and lower. +// Include Diffie-Hellman protocol for Ephemeral Keying, in order to take +// advantage of Forward Secrecy property of TLS +#define FE_SSL_OPTIONS SSL_OP_ALL | SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_SINGLE_DH_USE + +#define FE_SSL_IS_VALID_FN(d, f, b) ((strlen(d) + strlen(f) + 1) < (sizeof(b) - 1)) +#define FE_SSL_GET_FN(d, f, b) { \ + if (d[strlen(d)] == '/') \ + snprintf(b, sizeof(b), "%s%s", d, f); \ + else \ + snprintf(b, sizeof(b), "%s/%s", d, f); \ +} + +#if (OPENSSL_VERSION_NUMBER >= 0x10100000L) && !defined(__VXWORKS__) +#define TLSv1_client_method() TLS_client_method() +#define TLSv1_server_method() TLS_server_method() +#define TLSv1_2_server_method() TLS_server_method() +#define TLSv1_2_client_method() TLS_client_method() +#endif + +static void omgt_oob_ssl_print_ciphers(struct omgt_port *port, SSL *ssl) +{ + int index = 0; + const char *next = NULL; + do { + next = SSL_get_cipher_list(ssl, index); + if (next != NULL) { + OMGT_DBGPRINT(port, "CIPHER[%d] %s\n", index, next); + index++; + } + }while (next != NULL); +} + +static void omgt_oob_ssl_print_error_stack(struct omgt_port *port) +{ + unsigned long error, i; + + for (i = 0; i < 5; i++) { + if ((error = ERR_get_error())) { + OMGT_OUTPUT_ERROR(port, "\tStackErr[%d] %s\n", (int)i, ERR_error_string(error, NULL)); + } + } +} + +static int omgt_oob_ssl_ctx_pem_password_cb(char *buf, int size, int rwflag, void *userdata) +{ + int len = 0; + + if (buf && userdata) { + memset(buf, 0, size); + strncpy(buf, userdata, size - 1); + buf[size - 1] = 0; + len = strlen(buf); + } + + return (len); +} + +static OMGT_STATUS_T omgt_oob_ssl_post_connection_cert_check(struct omgt_port *port, X509 *cert) +{ + X509_STORE_CTX *x509StoreContext; + int err = 0; + + if (!cert) + return OMGT_STATUS_ERROR; + + if (port->is_x509_store_initialized) { + // create the X509 store context + if (!(x509StoreContext = X509_STORE_CTX_new())) { + OMGT_OUTPUT_ERROR(port, "Failed to allocate x509 store context\n"); + return OMGT_STATUS_INSUFFICIENT_MEMORY; + } + + // initialize the X509 store context with the global X509 store and certificate + // of the peer. + if (X509_STORE_CTX_init(x509StoreContext, port->x509_store, cert, NULL) != 1) { + OMGT_OUTPUT_ERROR(port, "Failed to initialize x509 store context\n"); + return OMGT_STATUS_ERROR; + } + + // validate the certificate of the peer against the CRLs in the global X509 store + if (X509_verify_cert(x509StoreContext) != 1) { + err = X509_STORE_CTX_get_error(x509StoreContext); + OMGT_OUTPUT_ERROR(port, "Failed to verify certificate: %s (%d)\n", + X509_verify_cert_error_string((long)err), err); + return OMGT_STATUS_REJECT; + } + + X509_STORE_CTX_cleanup(x509StoreContext); + } + + return OMGT_STATUS_SUCCESS; +} + +OMGT_STATUS_T omgt_oob_ssl_init(struct omgt_port *port) +{ + OMGT_STATUS_T status = OMGT_STATUS_SUCCESS; + + if (!port->is_ssl_initialized) { + port->is_ssl_initialized = 1; + // initialize the OpenSSL library and error strings. + SSL_library_init(); + SSL_load_error_strings(); + + // allocate the method that will be used to create a SSL/TLS connection. + // The method defines which protocol version to be used by the connection. + port->ssl_client_method = port->oob_input.is_esm_fe ? + (SSL_METHOD *)TLSv1_client_method() : (SSL_METHOD *)TLSv1_2_client_method(); + + if (!port->ssl_client_method) { + port->is_ssl_initialized = 0; + status = OMGT_STATUS_INSUFFICIENT_MEMORY; + OMGT_OUTPUT_ERROR(port, "failed to allocate SSL method\n"); + } + } + + return status; +} + +void* omgt_oob_ssl_client_open(struct omgt_port *port, const char *ffDir, + const char *ffCertificate, const char *ffPrivateKey, + const char *ffCaCertificate, uint32_t ffCertChainDepth, + const char *ffDHParameters, uint32_t ffCaCrlEnabled, const char *ffCaCrl) +{ + SSL_CTX *context = NULL; + X509_LOOKUP *x509StoreLookup; + EC_KEY *ecdhPrime256v1 = NULL; + char fileName[OMGT_OOB_SSL_PATH_SIZE], ffCertificateFn[OMGT_OOB_SSL_PATH_SIZE], + ffCaCertificateFn[OMGT_OOB_SSL_PATH_SIZE]; + const char *bogusPassword = "boguspswd"; + + if (!port->is_ssl_initialized) { + OMGT_OUTPUT_ERROR(port, "TLS/SSL is not initialized\n"); + return (void *)context; + } + + if (!ffDir || !ffCertificate || !ffPrivateKey || !ffCaCertificate || !ffCaCrl) { + OMGT_OUTPUT_ERROR(port, "invalid parameter\n"); + return (void *)context; + } + + if (!FE_SSL_IS_VALID_FN(ffDir, ffCertificate, fileName) || + !FE_SSL_IS_VALID_FN(ffDir, ffPrivateKey, fileName) || + !FE_SSL_IS_VALID_FN(ffDir, ffCaCertificate, fileName) || + !FE_SSL_IS_VALID_FN(ffDir, ffCaCrl, fileName)) { + OMGT_OUTPUT_ERROR(port, "invalid file name\n"); + return (void *)context; + } + + // allocate a new SSL/TLS connection context + context = SSL_CTX_new(port->ssl_client_method); + if (!context) { + OMGT_OUTPUT_ERROR(port, "failed to allocate SSL context\n"); + return (void *)context; + } + + // Usage of the passphrase would require the admin to manual enter + // a password each time a FF utility is ran, so set the context + // callback to override the passphrases prompt stage of SSL/TLS by + // specifying a bogus password. + SSL_CTX_set_default_passwd_cb(context, omgt_oob_ssl_ctx_pem_password_cb); + SSL_CTX_set_default_passwd_cb_userdata(context, (void *)bogusPassword); + + // set the location and name of certificate file to be used by the context. + FE_SSL_GET_FN(ffDir, ffCertificate, ffCertificateFn); + if (SSL_CTX_use_certificate_file(context, ffCertificateFn, SSL_FILETYPE_PEM) <= 0) { + OMGT_OUTPUT_ERROR(port, "failed to set up the certificate file: %s\n", ffCertificateFn); + omgt_oob_ssl_print_error_stack(port); + goto bail; + } + + // set the location and name of the private key file to be used by the context. + FE_SSL_GET_FN(ffDir, ffPrivateKey, fileName); + if (SSL_CTX_use_PrivateKey_file(context, fileName, SSL_FILETYPE_PEM) <= 0) { + OMGT_OUTPUT_ERROR(port, "failed to set up the private key file: %s\n", fileName); + omgt_oob_ssl_print_error_stack(port); + goto bail; + } + + // check the consistency of the private key with the certificate + if (SSL_CTX_check_private_key(context) != 1) { + OMGT_OUTPUT_ERROR(port, "private key and certificate do not match\n"); + omgt_oob_ssl_print_error_stack(port); + goto bail; + } + + // set the location and name of the trusted CA certificates file to be used + // by the context. + FE_SSL_GET_FN(ffDir, ffCaCertificate, ffCaCertificateFn); + if (!SSL_CTX_load_verify_locations(context, ffCaCertificateFn, NULL)) { + OMGT_OUTPUT_ERROR(port, "failed to set up the CA certificates file: %s\n", ffCaCertificateFn); + omgt_oob_ssl_print_error_stack(port); + goto bail; + } + + // Certificate Revocation Lists (CRL). CRLs are an addtional mechanism + // used to verify certificates, in order to ensure that they have not + // expired or been revoked. + if (ffCaCrlEnabled && !port->is_x509_store_initialized) { + if (!(port->x509_store = X509_STORE_new())) { + OMGT_OUTPUT_ERROR(port, "Failed to allocate X509 store for CRLs\n"); + goto bail; + } + + if (X509_STORE_load_locations(port->x509_store, ffCaCertificateFn, ffDir) != 1) { + OMGT_OUTPUT_ERROR(port, "Failed to load FF CA certificate file into X509 store\n"); + goto bail; + } + + if (X509_STORE_set_default_paths(port->x509_store) != 1) { + OMGT_OUTPUT_ERROR(port, "Failed to set the default paths for X509 store\n"); + goto bail; + } + + if (!(x509StoreLookup = X509_STORE_add_lookup(port->x509_store, X509_LOOKUP_file()))) { + OMGT_OUTPUT_ERROR(port, "Failed add file lookup object to X509 store\n"); + goto bail; + } + + FE_SSL_GET_FN(ffDir, ffCaCrl, fileName); + if (X509_load_crl_file(x509StoreLookup, fileName, X509_FILETYPE_PEM) != 1) { + OMGT_OUTPUT_ERROR(port, "Failed to load the FF CRL file into X509 store: file %s\n", fileName); + goto bail; + } + + X509_STORE_set_flags(port->x509_store, X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL); + + if (!(x509StoreLookup = X509_STORE_add_lookup(port->x509_store, X509_LOOKUP_hash_dir()))) { + OMGT_OUTPUT_ERROR(port, "Failed add hash directory lookup object to X509 store\n"); + goto bail; + } + + if (!X509_LOOKUP_add_dir(x509StoreLookup, ffDir, X509_FILETYPE_PEM)) { + OMGT_OUTPUT_ERROR(port, "Failed add FF CRL directory to X509 store\n"); + goto bail; + } + + port->is_x509_store_initialized = 1; + } + + // set options to be enforced upon the SSL/TLS connection. + SSL_CTX_set_verify(context, SSL_VERIFY_PEER, NULL); + SSL_CTX_set_verify_depth(context, ffCertChainDepth); + SSL_CTX_set_options(context, FE_SSL_OPTIONS); + + // initialize Diffie-Hillmen parameters + if (!port->is_dh_params_initialized) { + FILE *dhParmsFile; + + // set the location and name of the Diffie-Hillmen parameters file to be used + // by the context. + FE_SSL_GET_FN(ffDir, ffDHParameters, fileName); + + dhParmsFile = fopen(fileName, "r"); + if (!dhParmsFile) { + OMGT_OUTPUT_ERROR(port, "failed to open Diffie-Hillmen parameters PEM file: %s\n", fileName); + goto bail; + } else { + port->dh_params = PEM_read_DHparams(dhParmsFile, NULL, NULL, NULL); + fclose(dhParmsFile); + if (!port->dh_params) { + OMGT_OUTPUT_ERROR(port, "failed to read Diffie-Hillmen parameters PEM file: %s\n", fileName); + goto bail; + } else { + port->is_dh_params_initialized = 1; + // set DH for all SSL sesions in this context (should only be one per port) + SSL_CTX_set_tmp_dh(context, port->dh_params); + } + } + } + + // set up the cipher list with the cipher suites that are allowed + // to be used in establishing the connection. + if (!SSL_CTX_set_cipher_list(context, FE_SSL_CIPHER_LIST)) { + OMGT_OUTPUT_ERROR(port, "failed to set up the cipher list\n"); + goto bail; + } + + // set up the elliptic curve to be used in establishing the connection. + ecdhPrime256v1 = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1); + if (ecdhPrime256v1 == NULL) { + OMGT_OUTPUT_ERROR(port, "Failed to to create curve: prime256v1\n"); + goto bail; + } + + SSL_CTX_set_tmp_ecdh(context, ecdhPrime256v1); + EC_KEY_free(ecdhPrime256v1); + + return (void *)context; + +bail: + + if (context) { + SSL_CTX_free(context); + } + + return NULL; +} + +void* omgt_oob_ssl_connect(struct omgt_port *port, void *context, int serverfd) +{ + OMGT_STATUS_T status = OMGT_STATUS_SUCCESS; + int rc; + SSL *session = NULL; + X509 *cert = NULL; + + if (!port || !context) { + OMGT_OUTPUT_ERROR(port, "invalid context parameter\n"); + return (void *)session; + } + + // allocate a new session to be associated with the SSL/TLS connection + if (!(session = SSL_new((SSL_CTX *)context))) { + OMGT_OUTPUT_ERROR(port, "Failed to allocate new SSL/TLS session for socket fd %d\n", serverfd); + return (void *)session; + } + + // assign peer file descriptor to the SSL/TLS session + SSL_set_fd(session, serverfd); + if (port->dbg_file) { + omgt_oob_ssl_print_ciphers(port, session); + } + + // attempt to establish SSL/TLS connection to the server + if ((rc = SSL_connect(session)) != 1) { + OMGT_OUTPUT_ERROR(port, "SSL/TLS handshake failed for connect: err %d, rc %d, %s\n", SSL_get_error(session, rc), rc, strerror(errno)); + omgt_oob_ssl_print_error_stack(port); + } else { + OMGT_DBGPRINT(port, "ACTIVE cipher suite: %s\n", SSL_CIPHER_get_name(SSL_get_current_cipher(session))); + + // request and verify the certificate of the server. Typically, it is + // required for a server to present a certificate. Strict security + // enforcement is to be done for the STL FM, so if a certificate + // is not presented by the server the connection will be rejected. + if (!(cert = SSL_get_peer_certificate(session))) { + status = OMGT_STATUS_NOT_FOUND; + OMGT_OUTPUT_ERROR(port, "server has no certifcate to verfiy\n"); + } else { + long result; + + // post-connection verification is very important, because it allows for + // much finer grained control over the certificate that is presented by + // the server, beyond the basic certificate verification that is done by + // the SSL/TLS protocol proper during the connect operation. + if (!(status = omgt_oob_ssl_post_connection_cert_check(port, cert))) { + // do the final phase of post-connection verification of the + // certificate presented by the server. + result = SSL_get_verify_result(session); + if (result != X509_V_OK) { + status = OMGT_STATUS_REJECT; + OMGT_OUTPUT_ERROR(port, "verification of server certificate failed: err %ld\n", result); + } + } + + // deallocate the cert + X509_free(cert); + } + } + if (status && session) { + SSL_free(session); + session = NULL; + } + + return (void *)session; +} + +int omgt_oob_ssl_read(struct omgt_port *port, void *session, unsigned char *buffer, int bufferLength) +{ + int erc, bytesRead = -1; + + if (buffer) { + bytesRead = SSL_read((SSL *)session, (void *)buffer, bufferLength); + OMGT_DBGPRINT(port, "Received %d bytes from SSL/TLS server\n", bytesRead); + + // FIXME: cjking - Implement retry logic code for certain return error conditions + erc = SSL_get_error((SSL *)session, bytesRead); + switch (erc) { + case SSL_ERROR_NONE: + break; + case SSL_ERROR_ZERO_RETURN: + OMGT_DBGPRINT(port, "Warning, SSL read failed with SSL_ERROR_ZERO_RETURN error, retrying read\n"); + break; + case SSL_ERROR_WANT_READ: + OMGT_DBGPRINT(port, "Warning, SSL read failed with SSL_ERROR_WANT_READ error, retrying read\n"); + break; + case SSL_ERROR_WANT_WRITE: + OMGT_DBGPRINT(port, "Warning, SSL read failed with SSL_ERROR_WANT_WRITE error, retrying read\n"); + break; + default: + OMGT_OUTPUT_ERROR(port, "SSL read failed with rc %d: %s\n", erc, strerror(errno)); + break; + } + } + + return bytesRead; +} + +int omgt_oob_ssl_write(struct omgt_port *port, void *session, unsigned char *buffer, int bufferLength) +{ + int erc, bytesWritten = -1; + + if (buffer) { + bytesWritten = SSL_write((SSL *)session, (void *)buffer, bufferLength); + OMGT_DBGPRINT(port, "Sent %d bytes to SSL/TLS server\n", bytesWritten); + + // FIXME: cjking - Implement retry logic code for certain return error conditions + erc = SSL_get_error((SSL *)session, bytesWritten); + switch (erc) { + case SSL_ERROR_NONE: + break; + case SSL_ERROR_ZERO_RETURN: + OMGT_DBGPRINT(port, "Warning, SSL read failed with SSL_ERROR_ZERO_RETURN error, retrying read\n"); + break; + case SSL_ERROR_WANT_READ: + OMGT_DBGPRINT(port, "Warning, SSL read failed with SSL_ERROR_WANT_READ error, retrying read\n"); + break; + case SSL_ERROR_WANT_WRITE: + OMGT_DBGPRINT(port, "Warning, SSL read failed with SSL_ERROR_WANT_WRITE error, retrying read\n"); + break; + default: + OMGT_OUTPUT_ERROR(port, "SSL read failed with rc %d: %s\n", erc, strerror(errno)); + break; + } + } + + return bytesWritten; +} + diff --git a/opamgt/src/omgt_oob_ssl.h b/opamgt/src/omgt_oob_ssl.h new file mode 100644 index 0000000..c6d29f5 --- /dev/null +++ b/opamgt/src/omgt_oob_ssl.h @@ -0,0 +1,47 @@ +/* BEGIN_ICS_COPYRIGHT5 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT5 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +#ifndef __OMGT_OOB_SSL_H +#define __OMGT_OOB_SSL_H + +extern OMGT_STATUS_T omgt_oob_ssl_init(struct omgt_port *port); +extern void *omgt_oob_ssl_client_open(struct omgt_port *port, const char *ffDir, + const char *ffCertificate, const char *ffPrivateKey, + const char *ffCaCertificate, uint32_t ffCertChainDepth, + const char *ffDHParameters, uint32_t ffCaCrlEnabled, const char *ffCaCrl); +extern void *omgt_oob_ssl_connect(struct omgt_port *port, void *context, int serverfd); +extern int omgt_oob_ssl_read(struct omgt_port *port, void *session, + unsigned char *buffer, int bufferLength); +extern int omgt_oob_ssl_write(struct omgt_port *port, void *session, + unsigned char *buffer, int bufferLength); + +#endif + diff --git a/opamgt/src/opamgt.c b/opamgt/src/opamgt.c new file mode 100644 index 0000000..4942f2b --- /dev/null +++ b/opamgt/src/opamgt.c @@ -0,0 +1,2191 @@ +/* BEGIN_ICS_COPYRIGHT2 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT2 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define OPAMGT_PRIVATE 1 +#include "ib_utils_openib.h" +#include "omgt_oob_net.h" +#include "opamgt_dump_mad.h" +#include "opamgt_sa_priv.h" +#include "opamgt_pa_priv.h" +#include "stl_convertfuncs.h" +#include "iba/ib_sm_priv.h" +#include "iba/ib_generalServices.h" + + +/** ========================================================================= */ +void omgt_set_dbg(struct omgt_port *port, FILE *file) +{ + if (port) port->dbg_file = file; +} +/** ========================================================================= */ +void omgt_set_err(struct omgt_port *port, FILE *file) +{ + if (port) port->error_file = file; +} +/** ========================================================================= */ +void omgt_set_timeout(struct omgt_port *port, int ms_timeout) +{ + if (port) { + port->ms_timeout = (ms_timeout > 0 ? ms_timeout : OMGT_DEF_TIMEOUT_MS); + } +} +/** ========================================================================= */ +void omgt_set_retry_count(struct omgt_port *port, int retry_count) +{ + if (port) { + port->retry_count = (retry_count >= 0 ? retry_count : OMGT_DEF_RETRY_CNT); + } +} +/** ========================================================================= */ +const char* omgt_status_totext(OMGT_STATUS_T status) +{ + switch (status) { + case OMGT_STATUS_SUCCESS: return "Success"; + case OMGT_STATUS_ERROR: return "Error"; + case OMGT_STATUS_INVALID_STATE: return "Invalid State"; + case OMGT_STATUS_INVALID_OPERATION: return "Invalid Operation"; + case OMGT_STATUS_INVALID_SETTING: return "Invalid Setting"; + case OMGT_STATUS_INVALID_PARAMETER: return "Invalid Parameter"; + case OMGT_STATUS_INSUFFICIENT_RESOURCES: return "Insufficient Resources"; + case OMGT_STATUS_INSUFFICIENT_MEMORY: return "Insufficient Memory"; + case OMGT_STATUS_COMPLETED: return "Completed"; + case OMGT_STATUS_NOT_DONE: return "Not Done"; + case OMGT_STATUS_PENDING: return "Pending"; + case OMGT_STATUS_TIMEOUT: return "Timeout"; + case OMGT_STATUS_CANCELED: return "Canceled"; + case OMGT_STATUS_REJECT: return "Reject"; + case OMGT_STATUS_OVERRUN: return "Overrun"; + case OMGT_STATUS_PROTECTION: return "Protection"; + case OMGT_STATUS_NOT_FOUND: return "Not Found"; + case OMGT_STATUS_UNAVAILABLE: return "Unavailable"; + case OMGT_STATUS_BUSY: return "Busy"; + case OMGT_STATUS_DISCONNECT: return "Disconnect"; + case OMGT_STATUS_DUPLICATE: return "Duplicate"; + case OMGT_STATUS_POLL_NEEDED: return "Poll Needed"; + default: return "Unknown"; + } +} +/** ========================================================================= */ +const char* omgt_service_state_totext(int service_state) +{ + switch (service_state) { + case OMGT_SERVICE_STATE_OPERATIONAL: return "Operational"; + case OMGT_SERVICE_STATE_DOWN: return "Down"; + case OMGT_SERVICE_STATE_UNAVAILABLE: return "Unavailable"; + case OMGT_SERVICE_STATE_UNKNOWN: + default: + return "Unknown"; + } +} +/** ========================================================================= + * Init sub libraries like umad here + * */ +static int init_sub_lib(struct omgt_port *port) +{ + static int done = 0; + + if (done) + return 0; + + if (umad_init() < 0) { + OMGT_OUTPUT_ERROR(port, "can't init UMAD library\n"); + return EIO; + } + + done = 1; + return (0); +} + +/** ========================================================================= + * Cache the pkeys associated with the port passed into the port object. + * + * @param port + * @return 0 on success +ERRNO on failure + */ +static int cache_port_details(struct omgt_port *port) +{ + int err = 0; + + if ((err = omgt_lock_sem(&port->umad_port_cache_lock)) != 0) { + OMGT_OUTPUT_ERROR(port, "Cannot cache pkeys, failed to acquire lock (err: %d)\n", err); + return EIO; + } + + if (port->umad_port_cache_valid) { + umad_release_port(&port->umad_port_cache); + } + port->umad_port_cache.pkeys_size = 0; + port->umad_port_cache_valid = 0; + + if (umad_get_port(port->hfi_name, port->hfi_port_num, &port->umad_port_cache) < 0) { + OMGT_OUTPUT_ERROR(port, "can't get UMAD port information (%s:%d)\n", + port->hfi_name, port->hfi_port_num); + err = EIO; + goto fail; + } + + if (!port->umad_port_cache.pkeys) { + OMGT_OUTPUT_ERROR(port, "no UMAD pkeys for (%s:%d)\n", + port->hfi_name, port->hfi_port_num); + err = EIO; + goto fail2; + } + + /* NOTE the umad interface returns network byte order here; fix it */ + port->umad_port_cache.port_guid = ntoh64(port->umad_port_cache.port_guid); + port->umad_port_cache.gid_prefix = ntoh64(port->umad_port_cache.gid_prefix); + + port->umad_port_cache_valid = 1; + omgt_unlock_sem(&port->umad_port_cache_lock); + + return 0; + +fail2: + umad_release_port(&port->umad_port_cache); + port->umad_port_cache.pkeys_size = 0; + port->umad_port_cache_valid = 0; +fail: + omgt_unlock_sem(&port->umad_port_cache_lock); + return err; +} + +/** ========================================================================= */ +static int open_verbs_ctx(struct omgt_port *port) +{ + int i; + int num_devices; + struct ibv_device **dev_list; + + dev_list = ibv_get_device_list(&num_devices); + for (i = 0; i < num_devices; ++i) + if (dev_list[i] != NULL + && (strncmp(dev_list[i]->name, port->hfi_name, sizeof(dev_list[i]->name)) == 0) ) + break; + + if (i >= num_devices) { + ibv_free_device_list(dev_list); + OMGT_OUTPUT_ERROR(port, "failed to find verbs device\n"); + return EIO; + } + + port->verbs_ctx = ibv_open_device(dev_list[i]); + + ibv_free_device_list(dev_list); + + if (port->verbs_ctx == NULL) + { + OMGT_OUTPUT_ERROR(port, "failed to open verbs device\n"); + return EIO; + } + + if (sem_init(&port->lock,0,1) != 0) + { + ibv_close_device(port->verbs_ctx); + OMGT_OUTPUT_ERROR(port, "failed to init registry lock\n"); + return EIO; + } + + return 0; +} + +/** ========================================================================= */ +static void close_verbs_ctx(struct omgt_port *port) +{ + sem_destroy(&port->lock); + ibv_close_device(port->verbs_ctx); +} + +static void update_umad_port_cache(struct omgt_port *port) +{ + int rc; + struct ibv_async_event event; + + ibv_get_async_event(port->verbs_ctx, &event); + ibv_ack_async_event(&event); + switch (event.event_type) { + case IBV_EVENT_PORT_ACTIVE: + case IBV_EVENT_PORT_ERR: + case IBV_EVENT_LID_CHANGE: + case IBV_EVENT_PKEY_CHANGE: + case IBV_EVENT_GID_CHANGE: + rc = cache_port_details(port); + if (rc != 0) + OMGT_OUTPUT_ERROR(port, "umad port cache data invalid!\n"); + break; + + case IBV_EVENT_SM_CHANGE: + case IBV_EVENT_CLIENT_REREGISTER: + if (reregister_traps(port)) + OMGT_OUTPUT_ERROR(port, "failed to reregister traps.\n"); + rc = cache_port_details(port); + if (rc != 0) + OMGT_OUTPUT_ERROR(port, "umad port cache data invalid!\n"); + break; + case IBV_EVENT_CQ_ERR: + OMGT_OUTPUT_ERROR(port, "got IBV_EVENT_CQ_ERR\n"); + break; + default: + break; + } +} + + +static enum omgt_th_event handle_th_msg(struct omgt_port *port) +{ + struct omgt_thread_msg msg; + int s; + + memset(&msg, 0, sizeof(msg)); + + s = read(port->umad_port_sv[1], &msg, sizeof(msg)); + if (s <= 0 || s != sizeof(msg)) { + OMGT_OUTPUT_ERROR(port, "th event read failed : %s\n", strerror(errno)); + return OMGT_TH_EVT_NONE; + } + + switch (msg.evt) { + case OMGT_TH_EVT_SHUTDOWN: + break; + case OMGT_TH_EVT_UD_MONITOR_ON: + port->run_sa_cq_poll = 1; + break; + case OMGT_TH_EVT_UD_MONITOR_OFF: + port->run_sa_cq_poll = 0; + break; + case OMGT_TH_EVT_START_OUTSTANDING_REQ_TIME: + port->poll_timeout_ms = NOTICE_REG_TIMEOUT_MS; + break; + default: + OMGT_OUTPUT_ERROR(port, "Unknown msg : %d\n", msg.evt); + break; + } + + return msg.evt; +} + +static void *umad_port_thread(void *arg) +{ + struct omgt_port *port = (struct omgt_port *)arg; + int err; + + port->poll_timeout_ms = -1; + while (1) { + int nfds = 0; + int rc; + struct pollfd pollfd[3]; + + /* Verbs event */ + pollfd[0].fd = port->verbs_ctx->async_fd; + pollfd[0].events = POLLIN; + pollfd[0].revents = 0; + nfds++; + + /* thread message */ + pollfd[1].fd = port->umad_port_sv[1]; + pollfd[1].events = POLLIN; + pollfd[1].revents = 0; + nfds++; + + /* Notice QP event */ + if (port->run_sa_cq_poll && port->sa_qp_comp_channel) { + pollfd[2].fd = port->sa_qp_comp_channel->fd; + pollfd[2].events = POLLIN; + nfds++; + } + pollfd[2].revents = 0; /* this always needs to be cleared */ + + if ((rc = poll(pollfd, nfds, port->poll_timeout_ms)) < 0) { + if (rc < 0) + OMGT_OUTPUT_ERROR(port, "event poll failed : %s\n", strerror(errno)); + continue; + } + + if (rc == 0) { + /* Timed out means we have periodic work to do */ + port->poll_timeout_ms = repost_pending_registrations(port); + continue; + } + + if (pollfd[1].revents & POLLIN) { + if (handle_th_msg(port) == OMGT_TH_EVT_SHUTDOWN) + goto quit_thread; + } else if (pollfd[0].revents & POLLNVAL) { + goto quit_thread; + } else if (pollfd[0].revents & POLLIN) { + update_umad_port_cache(port); + } else if (pollfd[2].revents & POLLIN) { + handle_sa_ud_qp(port); + } else { + OMGT_DBGPRINT(port, "poll returned but no ready file desc: %d - %d, %d - %d, %d - %d\n", + pollfd[0].revents, port->verbs_ctx->async_fd, + pollfd[1].revents, port->umad_port_sv[1], + port->sa_qp_comp_channel? pollfd[2].revents : 0, + port->sa_qp_comp_channel? port->sa_qp_comp_channel->fd : -1); + } + } + +quit_thread: + err = close(port->umad_port_sv[1]); + if (err != 0) { + OMGT_OUTPUT_ERROR(port, "Failed to close thread sock pair(1) : %s\n", strerror(errno)); + } + return NULL; +} + +/** ========================================================================= */ +static int start_port_thread(struct omgt_port *port) +{ + int err, flags; + pthread_attr_t attr; + + err = socketpair(AF_UNIX, SOCK_DGRAM, 0, port->umad_port_sv); + if (err != 0) { + OMGT_OUTPUT_ERROR(port, "Failed to open thread sock pair : %s\n", strerror(errno)); + return EIO; + } + + /* change the blocking mode of the async event queue */ + flags = fcntl(port->verbs_ctx->async_fd, F_GETFL); + err = fcntl(port->verbs_ctx->async_fd, F_SETFL, flags | O_NONBLOCK); + if (err < 0) { + OMGT_OUTPUT_ERROR(port, "Failed to change file descriptor of async event queue\n"); + return EIO; + } + + pthread_attr_init(&attr); + err = pthread_create(&port->umad_port_thread, &attr, umad_port_thread, (void *)port); + pthread_attr_destroy(&attr); + return err; +} + +static int find_pkey_from_umad_port(umad_port_t *umad_port, uint16_t pkey) +{ + int i = -1; + + if (pkey == 0xffff || pkey == 0x7fff) { + /* Mgmt P_Keys are to be an exact match */ + for (i = 0; i < umad_port->pkeys_size; i++) { + if (umad_port->pkeys[i] == pkey) + goto done; + } + i = -1; + goto done; + } + + for (i = 0; i < umad_port->pkeys_size; i++) { + if ((umad_port->pkeys[i] & OMGT_PKEY_MASK) == (pkey & OMGT_PKEY_MASK)) + goto done; + } + + i = -1; + +done: + return i; +} + +/* + * Register to send IB DR SMAs + * This is used only to send DR Packets to the local ports to determine OPA + * support + */ +static int register_ib_smi_dr(int fd, uint32_t *aid) +{ + struct umad_reg_attr reg_attr; + int err; + + memset(®_attr, 0, sizeof(reg_attr)); + reg_attr.mgmt_class = UMAD_CLASS_SUBN_DIRECTED_ROUTE; + reg_attr.mgmt_class_version = 0x01; + + err = umad_register2(fd, ®_attr, aid); + + return err; +} + +/* Returns 0 (invalid base version) on error */ +static uint8_t get_base_version_from_ni(int fd, uint32_t aid, int pkey_index) +{ + uint8_t rc; + void *umad_p = NULL; + struct umad_smp *send_mad; + size_t length; + + umad_p = umad_alloc(1, sizeof(*send_mad) + umad_size()); + if (!umad_p) { + return 0; + } + memset(umad_p, 0, sizeof(*send_mad) + umad_size()); + umad_set_grh(umad_p, 0); + + send_mad = umad_get_mad(umad_p); + send_mad->base_version = UMAD_BASE_VERSION; + send_mad->mgmt_class = UMAD_CLASS_SUBN_DIRECTED_ROUTE; + send_mad->class_version = 0x01; + send_mad->method = UMAD_METHOD_GET; + send_mad->tid = htonl(0xDEADBEEF); + send_mad->attr_id = htons(UMAD_SM_ATTR_NODE_INFO); + send_mad->dr_slid = LID_PERMISSIVE; + send_mad->dr_dlid = LID_PERMISSIVE; + + umad_set_pkey(umad_p, pkey_index); + umad_set_addr(umad_p, LID_PERMISSIVE, 0, 0, 0); + + rc = 0; + if (umad_send(fd, aid, umad_p, sizeof(*send_mad), 100, 1) < 0) + goto free_mad; + + length = sizeof(*send_mad); + if (umad_recv(fd, umad_p, (int *)&length, 100) < 0) + goto free_mad; + + if (length < sizeof(*send_mad)) + goto free_mad; + + if (umad_status(umad_p) != 0) + goto free_mad; + + rc = ((NODE_INFO *)(send_mad->data))->BaseVersion; + +free_mad: + free(umad_p); + return rc; +} + +static int port_is_opa(char *hfi_name, int port_num) +{ + int fd; + int rc; + int pkey_index; + uint32_t aid; + uint8_t base_version; + umad_port_t umad_port; + + if (umad_get_port(hfi_name, port_num, &umad_port) != 0) + return 0; + + pkey_index = find_pkey_from_umad_port(&umad_port, 0x7fff); + umad_release_port(&umad_port); + + if (pkey_index < 0) + return 0; + + if ((fd = umad_open_port(hfi_name, port_num)) < 0) + return 0; + + if (register_ib_smi_dr(fd, &aid) != 0) { + rc = 0; + goto close; + } + + base_version = get_base_version_from_ni(fd, aid, pkey_index); + + umad_unregister(fd, (int)aid); + + rc = (base_version == 0x80); + +close: + umad_close_port(fd); + return rc; +} + +static int hfi_is_opa(char *hfi_name) +{ + return port_is_opa(hfi_name, 1); +} +/** ========================================================================= */ +OMGT_STATUS_T omgt_get_hfi_names(char hfis[][UMAD_CA_NAME_LEN], int32_t max, int32_t *hfi_count) +{ + OMGT_STATUS_T status = OMGT_STATUS_SUCCESS; + int i; + int caCount; + int hfiCount = 0; + char (*ca_names)[UMAD_CA_NAME_LEN]; + + if (hfi_count) *hfi_count = -1; + ca_names = calloc(max, UMAD_CA_NAME_LEN * sizeof(char)); + if (!ca_names) { + return OMGT_STATUS_INSUFFICIENT_MEMORY; + } + + if ((caCount = umad_get_cas_names((void *)ca_names, max)) <= 0) { + hfiCount = caCount; + status = OMGT_STATUS_NOT_FOUND; + goto out; + } + + for (i = 0; i < caCount; i++) { + if (hfi_is_opa(ca_names[i])) { + memcpy(hfis[hfiCount], ca_names[i], UMAD_CA_NAME_LEN); + hfiCount++; + } + } + +out: + free(ca_names); + + if (hfi_count) *hfi_count = hfiCount; + return status; +} +/** ========================================================================= */ +static int open_first_opa_hfi(int port_num, char *hfi_name, size_t name_len) +{ + int ca_cnt; + char hfis[UMAD_MAX_DEVICES][UMAD_CA_NAME_LEN]; + + (void)omgt_get_hfi_names(hfis, UMAD_MAX_DEVICES, &ca_cnt); + if (ca_cnt < 0) + return ca_cnt; + + ca_cnt = umad_open_port(hfis[0], port_num); + + if (ca_cnt >= 0) { + strncpy(hfi_name, hfis[0], name_len); + hfi_name[name_len-1] = '\0'; + } + + return ca_cnt; +} + +/** ========================================================================= */ +static OMGT_STATUS_T omgt_open_port_internal(struct omgt_port *port, char *hfi_name, uint8_t port_num) +{ + int i,j; + OMGT_STATUS_T err; + + if (init_sub_lib(port)) { + err = OMGT_STATUS_UNAVAILABLE; + goto free_port; + } + + /* Set Timeout and retry to default values */ + port->ms_timeout = OMGT_DEF_TIMEOUT_MS; + port->retry_count = OMGT_DEF_RETRY_CNT; + + if ((port->umad_fd = umad_open_port(hfi_name, port_num)) < 0) { + OMGT_OUTPUT_ERROR(port, "can't open UMAD port (%s:%d)\n", hfi_name, port_num); + err = OMGT_STATUS_INVALID_PARAMETER; + goto free_port; + } + + if (!port_is_opa(hfi_name, port_num)) { + umad_close_port(port->umad_fd); + + if (hfi_name) { + OMGT_OUTPUT_ERROR(port, "Port is not OPA (%s:%d)\n", hfi_name, port_num); + err = OMGT_STATUS_INVALID_PARAMETER; + goto free_port; + } + + /* hfi was wild carded, attempt to open the first OPA HFI */ + port->umad_fd = open_first_opa_hfi(port_num, port->hfi_name, sizeof(port->hfi_name)); + if (port->umad_fd < 0) { + OMGT_OUTPUT_ERROR (port, "OPA port not found (%d)\n", port_num); + err = OMGT_STATUS_NOT_FOUND; + goto free_port; + } + } else if (!hfi_name) { + /* get the actual name from a null hfi_name */ + umad_port_t umad_port; + + if (umad_get_port(NULL, port_num, &umad_port) < 0) { + OMGT_OUTPUT_ERROR (port ,"Failed to get umad port name (:%d)\n", port_num); + err = OMGT_STATUS_INVALID_PARAMETER; + goto close_port; + } + + snprintf(port->hfi_name, sizeof(port->hfi_name), "%s", umad_port.ca_name); + + umad_release_port(&umad_port); + } else { + snprintf(port->hfi_name, sizeof(port->hfi_name), "%s", hfi_name); + } + + port->hfi_port_num = port_num; + port->num_userspace_recv_buf = DEFAULT_USERSPACE_RECV_BUF; + port->num_userspace_send_buf = DEFAULT_USERSPACE_SEND_BUF; + + for (i = 0; i < OMGT_MAX_CLASS_VERSION; i++) { + for (j = 0; j < OMGT_MAX_CLASS; j++) { + port->umad_agents[i][j] = OMGT_INVALID_AGENTID; + } + } + + if (sem_init(&port->umad_port_cache_lock,0,1) != 0) { + OMGT_OUTPUT_ERROR(port, "failed to init umad_port_cache_lock\n"); + err = OMGT_STATUS_INVALID_STATE; + goto close_port; + } + + if (open_verbs_ctx(port) != 0) { + err = OMGT_STATUS_ERROR; + goto destroy_cache_lock; + } + + if (cache_port_details(port) != 0) { + err = OMGT_STATUS_ERROR; + goto close_verbs; + } + + if (start_port_thread(port) != 0) { + err = OMGT_STATUS_ERROR; + goto release_cache; + } + + port->hfi_num = omgt_get_hfi_num(port->hfi_name); + + LIST_INIT(&port->pending_reg_msg_head); + return (OMGT_STATUS_SUCCESS); + +release_cache: + umad_release_port(&port->umad_port_cache); +close_verbs: + close_verbs_ctx(port); +destroy_cache_lock: + sem_destroy(&port->umad_port_cache_lock); +close_port: + umad_close_port(port->umad_fd); +free_port: + return (err); +} + +/** ========================================================================= */ +OMGT_STATUS_T omgt_open_port(struct omgt_port **port, char *hfi_name, uint8_t port_num, struct omgt_params *session_params) +{ + OMGT_STATUS_T status; + struct omgt_port *rc; + + if ((rc = calloc(1, sizeof(*rc))) == NULL) + return (OMGT_STATUS_INSUFFICIENT_MEMORY); + + if (session_params) { + rc->dbg_file = session_params->debug_file; + rc->error_file = session_params->error_file; + } else { + rc->dbg_file = NULL; + rc->error_file = NULL; + } + + status = omgt_open_port_internal(rc, hfi_name, port_num); + if (status == OMGT_STATUS_SUCCESS) { + rc->is_oob_enabled = FALSE; + *port = rc; + } else { + free(rc); + *port = NULL; + } + + return status; +} + +/** ========================================================================= */ +OMGT_STATUS_T omgt_open_port_by_num(struct omgt_port **port, int32_t hfi_num, uint8_t port_num, struct omgt_params *session_params) +{ + OMGT_STATUS_T status; + char name[IBV_SYSFS_NAME_MAX]; + int num = -1; + uint32_t hfi_count = 0, port_count = 0; + struct omgt_port *rc = NULL; + + if ((rc = calloc(1, sizeof(*rc))) == NULL) + return (OMGT_STATUS_INSUFFICIENT_MEMORY); + + if (session_params) { + rc->dbg_file = session_params->debug_file; + rc->error_file = session_params->error_file; + } else { + rc->dbg_file = NULL; + rc->error_file = NULL; + } + + status = omgt_get_portguid(hfi_num, port_num, NULL, rc, NULL, NULL, NULL, + NULL, &hfi_count, &port_count, name, &num, NULL); + if (status != OMGT_STATUS_SUCCESS) { + if (status != OMGT_STATUS_NOT_FOUND || + (hfi_count == 0 || port_count == 0) || + hfi_num > hfi_count || port_num > port_count) { + goto done; + } + /* No active port was found for wildcard hfi/port. + * return NOT_DONE so caller could query specific hfi/port + */ + status = OMGT_STATUS_NOT_DONE; + goto done; + } + + status = omgt_open_port_internal(rc, name, num); + +done: + if (status == OMGT_STATUS_SUCCESS) { + rc->is_oob_enabled = FALSE; + *port = rc; + } else if (rc) { + free(rc); + rc = NULL; + } + + return status; +} + +/** ========================================================================= */ +OMGT_STATUS_T omgt_open_port_by_guid(struct omgt_port **port, uint64_t port_guid, struct omgt_params *session_params) +{ + OMGT_STATUS_T status; + char name[IBV_SYSFS_NAME_MAX]; + int num = -1; + struct omgt_port *rc; + + if ((rc = calloc(1, sizeof(*rc))) == NULL) + return (OMGT_STATUS_INSUFFICIENT_MEMORY); + + if (session_params) { + rc->dbg_file = session_params->debug_file; + rc->error_file = session_params->error_file; + } else { + rc->dbg_file = NULL; + rc->error_file = NULL; + } + + status = omgt_get_hfi_from_portguid(port_guid, rc, name, NULL, &num, + NULL, NULL, NULL, NULL); + if (status != OMGT_STATUS_SUCCESS) { + goto done; + } + + status = omgt_open_port_internal(rc, name, num); + +done: + if (status == OMGT_STATUS_SUCCESS) { + rc->is_oob_enabled = FALSE; + *port = rc; + } else { + free(rc); + rc = NULL; + } + return status; +} + +static void join_port_thread(struct omgt_port *port) +{ + struct omgt_thread_msg msg; + int rc, err; + int retries = 3; + + msg.size = sizeof(msg); + msg.evt = OMGT_TH_EVT_SHUTDOWN; + + do { + rc = write(port->umad_port_sv[0], &msg, sizeof(msg)); + if (rc <= 0) + OMGT_OUTPUT_ERROR(port, "failed to send Thread shutdown to cache thread\n"); + /* I don't think we need to wait for a response */ + } while (rc <= 0 && retries--); + + if (rc <= 0) { + OMGT_OUTPUT_ERROR(port, "Thread NOT SHUTDOWN aborting join...\n"); + return; + } + + pthread_join(port->umad_port_thread, NULL); + + // close the sockets + err = close(port->umad_port_sv[0]); + if (err != 0) { + OMGT_OUTPUT_ERROR(port, "Failed to close thread sock pair(0) : %s\n", strerror(errno)); + } +} + +/** ========================================================================= */ +static void destroy_sa_qp(struct omgt_port *port) +{ + int i; + + // if the user just unregistered trap messages those messages may still + // be on this list, wait 5 seconds for the thread to handle the response. + for (i = 0; i < 5000; i++) { + if (!LIST_EMPTY(&port->pending_reg_msg_head)) { + usleep(1000); + } + else { + OMGT_DBGPRINT(port, "destroy_sa_qp: wait %d ms for LIST_EMPTY\n", i); + break; + } + } + + stop_ud_cq_monitor(port); + + join_port_thread(port); + + /* Free any remaining unregistration messages */ + if (!LIST_EMPTY(&port->pending_reg_msg_head)) { + OMGT_OUTPUT_ERROR(port, "Ignoring Pending Notice un-registation requests\n"); + omgt_sa_remove_all_pending_reg_msgs(port); + } + + if (port->sa_ah) + ibv_destroy_ah(port->sa_ah); + + if (port->sa_qp) + ibv_destroy_qp(port->sa_qp); + + for (i = 0; inum_userspace_recv_buf; i++) + if (port->recv_bufs) + ibv_dereg_mr(port->recv_bufs[i].mr); + + if (port->sa_qp_pd) + ibv_dealloc_pd(port->sa_qp_pd); + + if (port->sa_qp_cq) + ibv_destroy_cq(port->sa_qp_cq); + + if (port->recv_bufs) { + free(port->recv_bufs); + port->recv_bufs = NULL; + } + + if (port->sa_qp_comp_channel) + ibv_destroy_comp_channel(port->sa_qp_comp_channel); +} + +/** ========================================================================= */ +void omgt_close_port(struct omgt_port *port) +{ + int i, j; + FSTATUS status = FSUCCESS; + + /* If port is in OOB mode just close connction */ + if (port->is_oob_enabled) { + if (port->is_ssl_enabled && port->is_ssl_initialized) { + if (port->x509_store) { + X509_STORE_free(port->x509_store); + port->x509_store = NULL; + port->is_x509_store_initialized = 0; + } + if (port->dh_params) { + DH_free(port->dh_params); + port->dh_params = NULL; + port->is_dh_params_initialized = 0; + } + if (port->ssl_context) { + SSL_CTX_free(port->ssl_context); + port->ssl_context = NULL; + } + /* Clean up SSL_load_error_strings() from omgt_oob_ssl_init() */ + ERR_free_strings(); + port->is_ssl_initialized = 0; + } + if ((status = omgt_oob_disconnect(port, port->conn)) != FSUCCESS) { + OMGT_OUTPUT_ERROR(port, "Failed to disconnect from OOB connection: %u\n", status); + } + port->conn = NULL; + if (port->is_oob_notice_setup && + (status = omgt_oob_disconnect(port, port->notice_conn)) != FSUCCESS) + { + OMGT_OUTPUT_ERROR(port, "Failed to disconnect from OOB Notice connection: %u\n", status); + } + port->notice_conn = NULL; + free(port); + return; + } + + omgt_sa_clear_regs_unsafe(port); + + destroy_sa_qp(port); + + close_verbs_ctx(port); + + for (i = 0; i < OMGT_MAX_CLASS_VERSION; i++) { + for (j = 0; j < OMGT_MAX_CLASS; j++) { + if (port->umad_agents[i][j] != OMGT_INVALID_AGENTID) { + umad_unregister(port->umad_fd, port->umad_agents[i][j]); + } + } + } + + umad_close_port(port->umad_fd); + sem_destroy(&port->umad_port_cache_lock); + free(port); + +} + +/** ========================================================================= */ +uint16_t omgt_get_mgmt_pkey(struct omgt_port *port, STL_LID dlid, uint8_t hopCnt) +{ + uint16_t mgmt = 0; + int err = 0; + int i = 0; + + if (port->is_oob_enabled) { + OMGT_OUTPUT_ERROR(port, "Port in Out-of-Band Mode, no pkey\n"); + return 0; + } + if ((err = omgt_lock_sem(&port->umad_port_cache_lock)) != 0) { + OMGT_OUTPUT_ERROR(port, "Cannot get port LID, failed to acquire lock (err: %d)\n", err); + return mgmt; + } + + // Look for full mgmt pkey first. + for (i=0; iumad_port_cache.pkeys_size; i++) { + if (port->umad_port_cache.pkeys[i] == 0xffff) { + mgmt = 0xffff; + goto unlock; + } + } + + // If there is a hop count, is not local access, + // requires a full pkey, and there is no full mgmt pkey in the table, + if (hopCnt != 0) + goto unlock; + + // Look for limited mgmt pkey only if local query + if ((dlid == 0) || (dlid == port->umad_port_cache.base_lid) || (dlid == STL_LID_PERMISSIVE)) { + for (i=0; iumad_port_cache.pkeys_size; i++) { + if (port->umad_port_cache.pkeys[i] == 0x7fff) { + mgmt = 0x7fff; + goto unlock; + } + } + } +unlock: + omgt_unlock_sem(&port->umad_port_cache_lock); + return mgmt; +} + +/** ========================================================================= */ +OMGT_STATUS_T omgt_port_get_port_lid(struct omgt_port *port, uint32_t *port_lid) +{ + int err = 0; + + if (port->is_oob_enabled) { + OMGT_OUTPUT_ERROR(port, "Port in Out-of-Band Mode, no LID\n"); + return OMGT_STATUS_INVALID_STATE; + } + if ((err = omgt_lock_sem(&port->umad_port_cache_lock)) != 0) { + OMGT_OUTPUT_ERROR(port, "Cannot get port LID, failed to acquire lock (err: %d)\n", err); + return OMGT_STATUS_PROTECTION; + } + + *port_lid = port->umad_port_cache.base_lid; + + omgt_unlock_sem(&port->umad_port_cache_lock); + return OMGT_STATUS_SUCCESS; +} + +/** ========================================================================= */ +OMGT_STATUS_T omgt_port_get_port_lmc(struct omgt_port *port, uint32_t *port_lmc) +{ + int err = 0; + + if (port->is_oob_enabled) { + OMGT_OUTPUT_ERROR(port, "Port in Out-of-Band Mode, no LMC\n"); + return OMGT_STATUS_INVALID_STATE; + } + if ((err = omgt_lock_sem(&port->umad_port_cache_lock)) != 0) { + OMGT_OUTPUT_ERROR(port, "Cannot get port LMC, failed to acquire lock (err: %d)\n", err); + return OMGT_STATUS_PROTECTION; + } + *port_lmc = port->umad_port_cache.lmc; + + omgt_unlock_sem(&port->umad_port_cache_lock); + return OMGT_STATUS_SUCCESS; +} + +/** ========================================================================= */ +OMGT_STATUS_T omgt_port_get_port_sm_lid(struct omgt_port *port, uint32_t *sm_lid) +{ + int err = 0; + + if (port->is_oob_enabled) { + OMGT_OUTPUT_ERROR(port, "Port in Out-of-Band Mode, no SM LID\n"); + return OMGT_STATUS_INVALID_STATE; + } + if ((err = omgt_lock_sem(&port->umad_port_cache_lock)) != 0) { + OMGT_OUTPUT_ERROR(port, "Cannot get port SM LID, failed to acquire lock (err: %d)\n", err); + return OMGT_STATUS_PROTECTION; + } + + *sm_lid = port->umad_port_cache.sm_lid; + + omgt_unlock_sem(&port->umad_port_cache_lock); + return OMGT_STATUS_SUCCESS; +} +/** ========================================================================= */ +OMGT_STATUS_T omgt_port_get_port_sm_sl(struct omgt_port *port, uint8_t *sm_sl) +{ + int err = 0; + + if (port->is_oob_enabled) { + OMGT_OUTPUT_ERROR(port, "Port in Out-of-Band Mode, no SM SL\n"); + return OMGT_STATUS_INVALID_STATE; + } + if ((err = omgt_lock_sem(&port->umad_port_cache_lock)) != 0) { + OMGT_OUTPUT_ERROR(port, "Cannot get port SM SL, failed to acquire lock (err: %d)\n", err); + return OMGT_STATUS_PROTECTION; + } + + *sm_sl = port->umad_port_cache.sm_sl; + + omgt_unlock_sem(&port->umad_port_cache_lock); + return OMGT_STATUS_SUCCESS; +} +/** ========================================================================= */ +OMGT_STATUS_T omgt_port_get_port_prefix(struct omgt_port *port, uint64_t *prefix) +{ + int err = 0; + + if (port->is_oob_enabled) { + OMGT_OUTPUT_ERROR(port, "Port in Out-of-Band Mode, no Port Prefix\n"); + return OMGT_STATUS_INVALID_STATE; + } + if ((err = omgt_lock_sem(&port->umad_port_cache_lock)) != 0) { + OMGT_OUTPUT_ERROR(port, "Cannot get Port Prefix, failed to acquire lock (err: %d)\n", err); + return OMGT_STATUS_PROTECTION; + } + + *prefix = port->umad_port_cache.gid_prefix; + + omgt_unlock_sem(&port->umad_port_cache_lock); + return OMGT_STATUS_SUCCESS; +} +/** ========================================================================= */ +OMGT_STATUS_T omgt_port_get_port_guid(struct omgt_port *port, uint64_t *port_guid) +{ + int err = 0; + + if (port->is_oob_enabled) { + OMGT_OUTPUT_ERROR(port, "Port in Out-of-Band Mode, no Port GUID\n"); + return OMGT_STATUS_INVALID_STATE; + } + if ((err = omgt_lock_sem(&port->umad_port_cache_lock)) != 0) { + OMGT_OUTPUT_ERROR(port, "Cannot get Port GUID, failed to acquire lock (err: %d)\n", err); + return OMGT_STATUS_PROTECTION; + } + + *port_guid = port->umad_port_cache.port_guid; + + omgt_unlock_sem(&port->umad_port_cache_lock); + return OMGT_STATUS_SUCCESS; +} +/** ========================================================================= */ +OMGT_STATUS_T omgt_port_get_hfi_port_num(struct omgt_port *port, uint8_t *port_num) +{ + if (port->is_oob_enabled) { + OMGT_OUTPUT_ERROR(port, "Port in Out-of-Band Mode, no HFI Port number\n"); + return OMGT_STATUS_INVALID_STATE; + } + + *port_num = port->hfi_port_num; + + if (port->hfi_port_num <= 0) { + OMGT_OUTPUT_ERROR(port, "HFI Port Number not properly initialized: %d\n", port->hfi_port_num); + return OMGT_STATUS_ERROR; + } + + return OMGT_STATUS_SUCCESS; +} +/** ========================================================================= */ +OMGT_STATUS_T omgt_port_get_hfi_num(struct omgt_port *port, int32_t *hfi_num) +{ + if (port->is_oob_enabled) { + OMGT_OUTPUT_ERROR(port, "Port in Out-of-Band Mode, no HFI number\n"); + return OMGT_STATUS_INVALID_STATE; + } + + *hfi_num = port->hfi_num; + + if (port->hfi_num <= 0) { + OMGT_OUTPUT_ERROR(port, "HFI Number not properly initialized: %d\n", port->hfi_num); + return OMGT_STATUS_ERROR; + } + + return OMGT_STATUS_SUCCESS; +} + +/** ========================================================================= */ +OMGT_STATUS_T omgt_port_get_hfi_name(struct omgt_port *port, char hfi_name[IBV_SYSFS_NAME_MAX]) +{ + if (port->is_oob_enabled) { + OMGT_OUTPUT_ERROR(port, "Port in Out-of-Band Mode, no HFI name\n"); + return OMGT_STATUS_INVALID_STATE; + } + + snprintf(hfi_name, IBV_SYSFS_NAME_MAX, "%s", port->hfi_name); + + if (strnlen(port->hfi_name, IBV_SYSFS_NAME_MAX) <= 0) { + OMGT_OUTPUT_ERROR(port, "HFI name not properly initialized\n"); + return OMGT_STATUS_ERROR; + } + + return OMGT_STATUS_SUCCESS; +} + +/** ========================================================================= */ +OMGT_STATUS_T omgt_port_get_port_state(struct omgt_port *port, uint8_t *port_state) +{ + int err = 0; + + if (port->is_oob_enabled) { + OMGT_OUTPUT_ERROR(port, "Port in Out-of-Band Mode, no HFI number\n"); + return OMGT_STATUS_INVALID_STATE; + } + if ((err = omgt_lock_sem(&port->umad_port_cache_lock)) != 0) { + OMGT_OUTPUT_ERROR(port, "Cannot get Port State, failed to acquire lock (err: %d)\n", err); + return OMGT_STATUS_PROTECTION; + } + + *port_state = (uint8_t)port->umad_port_cache.state; + + omgt_unlock_sem(&port->umad_port_cache_lock); + return OMGT_STATUS_SUCCESS; +} +/** ========================================================================= */ +OMGT_STATUS_T omgt_port_get_node_type(struct omgt_port *port, uint8_t *node_type) +{ + if (port->is_oob_enabled) { + OMGT_OUTPUT_ERROR(port, "Port in Out-of-Band Mode, no NodeType\n"); + return OMGT_STATUS_INVALID_STATE; + } + + *node_type = STL_NODE_FI; + return OMGT_STATUS_SUCCESS; +} +OMGT_STATUS_T omgt_port_get_sa_service_state(struct omgt_port *port, int *sa_service_state, uint32_t refresh) +{ + int need_refresh = 0; + OMGT_STATUS_T query_status = OMGT_STATUS_SUCCESS; + + if (port->is_oob_enabled) { + OMGT_OUTPUT_ERROR(port, "Port in Out-of-Band Mode, no SA Service State\n"); + return OMGT_STATUS_INVALID_STATE; + } + + /* Check if we should attempt to refresh */ + switch (refresh) { + case OMGT_REFRESH_SERVICE_NOP: + break; + case OMGT_REFRESH_SERVICE_BAD_STATE: + if (port->sa_service_state != OMGT_SERVICE_STATE_OPERATIONAL) { + need_refresh = 1; + } + break; + case OMGT_REFRESH_SERVICE_ANY_STATE: + need_refresh = 1; + break; + default: + OMGT_OUTPUT_ERROR(port, "Invalid Refresh Flags: 0x%x\n", refresh); + return OMGT_STATUS_INVALID_PARAMETER; + } + if (need_refresh == 1) { + /* Refresh SA Client */ + query_status = omgt_query_sa(port, NULL, NULL); + if (query_status != OMGT_STATUS_SUCCESS) { + OMGT_OUTPUT_ERROR(port, "Failed to refresh SA Service State: %u\n", query_status); + return query_status; + } + } + + *sa_service_state = port->sa_service_state; + return OMGT_STATUS_SUCCESS; +} + +OMGT_STATUS_T omgt_port_get_pa_service_state(struct omgt_port *port, int *pa_service_state, uint32_t refresh) +{ + int need_refresh = 0; + + if (port->is_oob_enabled) { + OMGT_OUTPUT_ERROR(port, "Port in Out-of-Band Mode, no PA Service State\n"); + return OMGT_STATUS_INVALID_STATE; + } + + /* Check if we should attempt to refresh */ + switch (refresh) { + case OMGT_REFRESH_SERVICE_NOP: + break; + case OMGT_REFRESH_SERVICE_BAD_STATE: + if (port->pa_service_state != OMGT_SERVICE_STATE_OPERATIONAL) { + need_refresh = 1; + } + break; + case OMGT_REFRESH_SERVICE_ANY_STATE: + need_refresh = 1; + break; + default: + OMGT_OUTPUT_ERROR(port, "Invalid Refresh Flags: 0x%x\n", refresh); + return OMGT_STATUS_INVALID_PARAMETER; + } + if (need_refresh == 1) { + /* Refresh PA Client */ + (void)omgt_pa_service_connect(port); + } + + *pa_service_state = port->pa_service_state; + return OMGT_STATUS_SUCCESS; +} +/** ========================================================================= */ +OMGT_STATUS_T omgt_port_get_ip_version(struct omgt_port *port, uint8_t *ip_version) +{ + if (!port->is_oob_enabled) { + OMGT_OUTPUT_ERROR(port, "Port in In-Band Mode, no IP Version\n"); + return OMGT_STATUS_INVALID_STATE; + } + if (port->conn == NULL || port->conn->sock == INVALID_SOCKET) { + OMGT_OUTPUT_ERROR(port, "Net Connection not initialized\n"); + return OMGT_STATUS_INVALID_STATE; + } + if (port->conn->err) { + OMGT_DBGPRINT(port, "Net Connection has the Error Flag set: %d\n", port->conn->err); + } + + *ip_version = (port->conn->ipv6 ? 6 : 4); + + return OMGT_STATUS_SUCCESS; +} +/** ========================================================================= */ +OMGT_STATUS_T omgt_port_get_ipv4_addr(struct omgt_port *port, struct in_addr *ipv4_addr) +{ + if (!port->is_oob_enabled) { + OMGT_OUTPUT_ERROR(port, "Port in In-Band Mode, no IPv4 Address\n"); + return OMGT_STATUS_INVALID_STATE; + } + if (port->conn == NULL || port->conn->sock == INVALID_SOCKET) { + OMGT_OUTPUT_ERROR(port, "Net Connection not initialized\n"); + return OMGT_STATUS_INVALID_STATE; + } + if (port->conn->ipv6) { + OMGT_OUTPUT_ERROR(port, "Net Connection is using IPv6, no IPv4 Address\n"); + return OMGT_STATUS_INVALID_STATE; + } + if (port->conn->err) { + OMGT_DBGPRINT(port, "Net Connection has the Error Flag set: %d\n", port->conn->err); + } + + *ipv4_addr = port->conn->v4_addr.sin_addr; + + return OMGT_STATUS_SUCCESS; +} +/** ========================================================================= */ +OMGT_STATUS_T omgt_port_get_ipv6_addr(struct omgt_port *port, struct in6_addr *ipv6_addr) +{ + if (!port->is_oob_enabled) { + OMGT_OUTPUT_ERROR(port, "Port in In-Band Mode, no IPv4 Address\n"); + return OMGT_STATUS_INVALID_STATE; + } + if (port->conn == NULL || port->conn->sock == INVALID_SOCKET) { + OMGT_OUTPUT_ERROR(port, "Net Connection not initialized\n"); + return OMGT_STATUS_INVALID_STATE; + } + if (!port->conn->ipv6) { + OMGT_OUTPUT_ERROR(port, "Net Connection is using IPv4, no IPv6 Address\n"); + return OMGT_STATUS_INVALID_STATE; + } + if (port->conn->err) { + OMGT_DBGPRINT(port, "Net Connection has the Error Flag set: %d\n", port->conn->err); + } + + *ipv6_addr = port->conn->v6_addr.sin6_addr; + + return OMGT_STATUS_SUCCESS; +} +/** ========================================================================= */ +OMGT_STATUS_T omgt_port_get_ip_addr_text(struct omgt_port *port, char buf[], size_t buf_len) +{ + if (!port->is_oob_enabled) { + OMGT_OUTPUT_ERROR(port, "Port in In-Band Mode, no IP Address\n"); + return OMGT_STATUS_INVALID_STATE; + } + if (port->conn == NULL || port->conn->sock == INVALID_SOCKET) { + OMGT_OUTPUT_ERROR(port, "Net Connection not initialized\n"); + return OMGT_STATUS_INVALID_STATE; + } + if (port->conn->err) { + OMGT_DBGPRINT(port, "Net Connection has the Error Flag set: %d\n", port->conn->err); + } + + if (port->conn->ipv6) { + inet_ntop(AF_INET6, &(port->conn->v6_addr.sin6_addr), buf, buf_len); + } else { + inet_ntop(AF_INET, &(port->conn->v4_addr.sin_addr), buf, buf_len); + } + + return OMGT_STATUS_SUCCESS; +} +/** + * Gets the ISSM device corresponding to the specified port. + * + * @param port Pointer to the opened local port object. + * @param path Buffer in which to place the device path + * @param path_max Maximum length of the output buffer + * + * @return OMGT_STATUS_SUCCESS on success, or (umad) error code on failure + */ +OMGT_STATUS_T omgt_get_issm_device(struct omgt_port *port, char *path, int32_t path_max) +{ + int status; + + if (port == NULL) + { + OMGT_OUTPUT_ERROR(port, "port must be specified.\n"); + return OMGT_STATUS_INVALID_PARAMETER; + } + else if (path == NULL) + { + OMGT_OUTPUT_ERROR(port, "Invalid output path buffer.\n"); + return OMGT_STATUS_INVALID_PARAMETER; + } + if (port->is_oob_enabled) { + OMGT_DBGPRINT(port, "Port in Out-of-Band Mode, no NodeType\n"); + return FINVALID_STATE; + } + + status = umad_get_issm_path(port->hfi_name, port->hfi_port_num, path, path_max); + if (status) { + OMGT_OUTPUT_ERROR(port, "Failed to resolve ISSM device name (status: %d)\n", status); + return status; + } + + return OMGT_STATUS_SUCCESS; +} + +/** + * Function to refresh the pkey table for the MAD interface + * for a given hfi name and port. + * To use with omgt_xxx_mad, and the umad OFED library. + * + * @param *port pointer to port object + * + * @return 0 success + * -1 Failure + */ +int32_t omgt_mad_refresh_port_pkey(struct omgt_port *port) +{ + if (!port) + { + OMGT_OUTPUT_ERROR(port, "%s: Port must be specified\n", __func__); + return (-1); + } + + // The local function takes care of everything. + return cache_port_details(port); +} + +/** ========================================================================= */ +static int bind_single_class(struct omgt_port *port, + struct omgt_class_args *mgmt_class, uint64_t *mask) +{ + int rereg = 0; + int err; + uint32_t aid; + struct umad_reg_attr reg_attr; + uint8_t mclass = mgmt_class->mgmt_class; + uint8_t class_ver = mgmt_class->class_version; + + if (mclass >= OMGT_MAX_CLASS ) { + OMGT_OUTPUT_ERROR(port, "bad mgmt class : 0x%x\n", mclass); + return EINVAL; + } + if (class_ver >= OMGT_MAX_CLASS_VERSION ) { + OMGT_OUTPUT_ERROR(port, "bad mgmt class version : 0x%x\n", class_ver); + return EINVAL; + } + + memset(®_attr, 0, sizeof(reg_attr)); + reg_attr.mgmt_class = mclass; + reg_attr.mgmt_class_version = class_ver; + reg_attr.flags = 0; + memcpy(reg_attr.method_mask, mask, sizeof(reg_attr.method_mask)); + reg_attr.rmpp_version = 0; + if (mgmt_class->oui) { + //memcpy(®_attr.oui, mgmt_class->oui, sizeof(reg_attr.oui)); + reg_attr.oui = ((uint32_t)mgmt_class->oui[0]) << 16; + reg_attr.oui |= ((uint32_t)mgmt_class->oui[1]) << 8; + reg_attr.oui |= (uint32_t)(mgmt_class->oui[2]); + } + + // Exceptions to default values. + switch (mgmt_class->mgmt_class) { + case UMAD_CLASS_SUBN_ADM: + if (!mgmt_class->kernel_rmpp) { + reg_attr.flags = UMAD_USER_RMPP; + } + reg_attr.rmpp_version = 1; + break; + default: + { + /* Check for all RMPP based vendor classes */ + if (mgmt_class->mgmt_class >= 0x30 && mgmt_class->mgmt_class <= 0x4F) + { + if (!mgmt_class->kernel_rmpp) { + reg_attr.flags = UMAD_USER_RMPP; + } + reg_attr.rmpp_version = 1; + } + break; + } + } + + if (port->umad_agents[class_ver][mclass] != OMGT_INVALID_AGENTID) { + OMGT_OUTPUT_ERROR(port, "WARNINIG re-register of class 0x%x; version 0x%x; was %d\n", + mclass, class_ver, port->umad_agents[class_ver][mclass]); + umad_unregister(port->umad_fd, port->umad_agents[class_ver][mclass]); + rereg = 1; + } + + if ((err = umad_register2(port->umad_fd, ®_attr, &aid)) !=0) { + OMGT_OUTPUT_ERROR(port, "Can't register agent for class 0x%x; version 0x%x; %s\n", + mclass, class_ver, strerror(err)); + return err; + } + + if (rereg) + OMGT_OUTPUT_ERROR(port, "WARNINIG re-register new %d\n", aid); + + // Store the agent id; be able to correlate it to mgmt class/version. + port->umad_agents[class_ver][mclass] = (int)aid; + + return 0; +} + +static void set_bit64(int b, uint64_t *buf) +{ + uint64_t mask; + uint64_t *addr = buf; + + addr += b >> 6; + mask = 1ULL << (b & 0x3f); + *addr |= mask; +} + +/** ========================================================================= */ +int omgt_bind_classes(struct omgt_port *port, struct omgt_class_args *mgmt_classes) +{ + int rc; + int i = 1; + + if (!port || port->umad_fd < 0) { + OMGT_OUTPUT_ERROR(port, "Mad port is not initialized / opened\n"); + return EINVAL; + } + + while (mgmt_classes && mgmt_classes->base_version != 0) { + uint64_t method_mask[2]; + + OMGT_DBGPRINT(port, "Registering 0x%x/0x%x with umad layer\n", + mgmt_classes->mgmt_class, mgmt_classes->class_version); + + if (i >= OMGT_MAX_CLASS) { + OMGT_OUTPUT_ERROR(port, "too many classes %d requested\n", i); + return EIO; + } + + // Initialize method mask. + memset(method_mask, 0, sizeof (method_mask)); + if (mgmt_classes->use_methods) { + int j=0; + + for (j = 0; j < OMGT_CLASS_ARG_MAX_METHODS; j++) { + if (mgmt_classes->methods[j]) + set_bit64(mgmt_classes->methods[j], method_mask); + } + } else { + if (mgmt_classes->is_responding_client) { + set_bit64(UMAD_METHOD_GET, method_mask); + set_bit64(UMAD_METHOD_SET, method_mask); + } + if (mgmt_classes->is_trap_client) { + set_bit64(UMAD_METHOD_TRAP, method_mask); + set_bit64(UMAD_METHOD_TRAP_REPRESS, method_mask); + } + + if (mgmt_classes->is_report_client) { + set_bit64(UMAD_METHOD_REPORT, method_mask); + } + + if (mgmt_classes->is_responding_client && mgmt_classes->mgmt_class == UMAD_CLASS_SUBN_ADM) { + set_bit64(UMAD_SA_METHOD_GET_TABLE, method_mask); + set_bit64(UMAD_SA_METHOD_DELETE, method_mask); + set_bit64(UMAD_SA_METHOD_GET_TRACE_TABLE, method_mask); + } + } + + rc = bind_single_class(port, mgmt_classes, method_mask); + if (rc != 0) + return rc; + + mgmt_classes++; + i++; + } + + return 0; +} + +/** ========================================================================= */ +FSTATUS omgt_send_recv_mad_alloc(struct omgt_port *port, + uint8_t *send_mad, size_t send_size, struct omgt_mad_addr *addr, + uint8_t **recv_mad, size_t *recv_size, int timeout_ms, int retries) +{ + FSTATUS rc = FNOT_DONE; + if (port->is_oob_enabled) { + rc = omgt_oob_send_packet(port, send_mad, send_size); + if (rc) return rc; + + return (omgt_oob_receive_response(port, recv_mad, (uint32_t *)recv_size)); + } else { + rc = omgt_send_mad2(port, send_mad, send_size, addr, timeout_ms, retries); + if (rc) return (rc); + + return (omgt_recv_mad_alloc(port, recv_mad, recv_size, timeout_ms * (retries + 2), addr)); + } +} + +/** ========================================================================= */ +FSTATUS omgt_send_recv_mad_no_alloc(struct omgt_port *port, + uint8_t *send_mad, size_t send_size, struct omgt_mad_addr *addr, + uint8_t *recv_mad, size_t *recv_size, int timeout_ms, int retries) +{ + FSTATUS rc = FNOT_DONE; + if (port->is_oob_enabled) { + return FINVALID_PARAMETER; + } else { + rc = omgt_send_mad2(port, send_mad, send_size, addr, timeout_ms, retries); + if (rc) return (rc); + + return (omgt_recv_mad_no_alloc(port, recv_mad, recv_size, timeout_ms * (retries + 2), addr)); + } +} + +static uint16_t omgt_find_pkey_from_idx(struct omgt_port *port, unsigned idx) +{ + uint16_t rc; + int err; + + if ((err = omgt_lock_sem(&port->umad_port_cache_lock)) != 0) { + OMGT_OUTPUT_ERROR(port, "Cannot locate pKey, failed to acquire lock (err: %d)\n", err); + return 0x0000; + } + + if (idx < port->umad_port_cache.pkeys_size) + rc = port->umad_port_cache.pkeys[idx]; + else + rc = 0x0000; + + omgt_unlock_sem(&port->umad_port_cache_lock); + + return rc; +} + +/** ========================================================================= */ +int32_t omgt_find_pkey(struct omgt_port *port, uint16_t pkey) +{ + int err; + int i = -1; + + if (pkey == 0) + return -1; + + if ((err = omgt_lock_sem(&port->umad_port_cache_lock)) != 0) { + OMGT_OUTPUT_ERROR(port, "Cannot find pKey, failed to acquire lock (err: %d)\n", err); + return -1; + } + + i = find_pkey_from_umad_port(&port->umad_port_cache, pkey); + + omgt_unlock_sem(&port->umad_port_cache_lock); + return i; +} + +/** ========================================================================= */ +static inline int is_my_lid_port(struct omgt_port *port, uint32_t lid) +{ + int rc; + int err = 0; + unsigned last_lid; + + if ((err = omgt_lock_sem(&port->umad_port_cache_lock)) != 0) { + OMGT_OUTPUT_ERROR(port, "Cannot check LID information, failed to acquire lock (err: %d)\n", err); + return 0; + } + + last_lid = port->umad_port_cache.base_lid + (1<umad_port_cache.lmc)-1; + + if (lid >= port->umad_port_cache.base_lid && lid <= last_lid) + rc = 1; + else + rc = 0; + + omgt_unlock_sem(&port->umad_port_cache_lock); + return rc; +} + +static int omgt_extract_lid(ib_user_mad_t *umad) +{ + uint64_t dest_if_id; + + if (umad->addr.grh_present) { + memcpy(&dest_if_id, umad->addr.gid + 8, sizeof(dest_if_id)); + dest_if_id = ntoh64(dest_if_id); + if ((dest_if_id >> 40) == OMGT_STL_OUI) + return dest_if_id & 0xFFFFFFFF; + } + return IB2STL_LID(ntoh16(umad->addr.lid)); +} + +/** ========================================================================= */ +FSTATUS omgt_send_mad2(struct omgt_port *port, uint8_t *send_mad, size_t send_size, + struct omgt_mad_addr *addr, int timeout_ms, int retries) +{ + FSTATUS status = FSUCCESS; + void *umad_p = NULL; + int response; + uint8_t mclass, class_ver; + int aid; + int correctedTimeout; + struct umad_hdr *mad_hdr = (struct umad_hdr *)send_mad; + uint16_t ib_lid; + int pkey_idx; + size_t padded_size; + struct ib_mad_addr *mad_addr; + int slid_is_permissive = 0; + int dlid_is_permissive = 0; + IB_GID gid; + struct umad_smp *ib_mad; + STL_SMP *stl_mad; + + if (!port || !send_mad || !send_size || !addr) + return FINVALID_PARAMETER; + + // Make sure we are registered for this class/version... + mclass = mad_hdr->mgmt_class; + class_ver = mad_hdr->class_version; + response = (mad_hdr->method & 0x80) + || (mad_hdr->method == UMAD_METHOD_TRAP_REPRESS) + || (mclass == UMAD_CLASS_BM && + ntohl(mad_hdr->attr_mod) & BM_ATTRIB_MOD_RESPONSE); + aid = port->umad_agents[class_ver][mclass]; + OMGT_DBGPRINT(port, " Management Class 0x%x method 0x%x attrId 0x%x attrM 0x%x\n",mclass, mad_hdr->method, + ntohs(mad_hdr->attr_id), ntohl(mad_hdr->attr_mod)); + OMGT_DBGPRINT(port, " base_version 0x%x class_version 0x%x\n",mad_hdr->base_version, mad_hdr->class_version); + + if (aid == OMGT_INVALID_AGENTID) { + // automatically register for "send" only + int err = 0; + struct omgt_class_args mgmt_class[2]; + + memset(mgmt_class, 0, sizeof(mgmt_class)); + + mgmt_class[0].base_version = mad_hdr->base_version; + mgmt_class[0].mgmt_class = mad_hdr->mgmt_class; + mgmt_class[0].class_version = mad_hdr->class_version; + mgmt_class[0].is_responding_client = 0; + mgmt_class[0].is_trap_client = 0; + mgmt_class[0].is_report_client = 0; + mgmt_class[0].kernel_rmpp = 1; + mgmt_class[0].use_methods = 0; + + OMGT_DBGPRINT(port, "auto registering class 0x%02x; version 0x%x for send only\n", + mclass, class_ver); + if ((err = omgt_bind_classes(port, mgmt_class)) != 0) { + OMGT_OUTPUT_ERROR(port, "Failed to auto register for class 0x%02x: %s\n", + mclass, strerror(err)); + status = FERROR; + goto done; + } + aid = port->umad_agents[class_ver][mclass]; + } + + // Initialize the user mad. + // umad has limititation that outgoing packets must be > 36 bytes. + padded_size = ( MAX(send_size,36) + 7) & ~0x7; + OMGT_DBGPRINT (port, "dlid %d qpn %d qkey %x sl %d\n", addr->lid, addr->qpn, addr->qkey, addr->sl); + + umad_p = umad_alloc(1, padded_size + umad_size()); + if (!umad_p) { + OMGT_OUTPUT_ERROR(port, "can't alloc umad send_size %ld\n", padded_size + umad_size()); + status = FINSUFFICIENT_MEMORY; + goto done; + } + memset(umad_p, 0, padded_size + umad_size()); + + memcpy (umad_get_mad(umad_p), send_mad, send_size); /* Copy mad to umad */ + + /** + * If incoming dlid is 0, set it to a permissive LID. + * If slid is an extended LID, set it to 0xFFFFFFFF. + * If not, set it to 0xFFFF + */ + if (addr->lid == 0) { + if (omgt_is_ext_lid(port->umad_port_cache.base_lid)) + addr->lid = STL_LID_PERMISSIVE; + else + addr->lid = LID_PERMISSIVE; + } + + ib_lid = addr->lid & 0xffff; + + /* Pure Directed Route packets dont need GRH */ + if (mad_hdr->mgmt_class == UMAD_CLASS_SUBN_DIRECTED_ROUTE) { + if (mad_hdr->base_version == UMAD_BASE_VERSION) { + /* IB MAD */ + ib_mad = (struct umad_smp *)send_mad; + slid_is_permissive = (ib_mad->dr_slid == LID_PERMISSIVE); + dlid_is_permissive = (ib_mad->dr_dlid == LID_PERMISSIVE); + } else { + /* OPA MAD */ + stl_mad = (STL_SMP *)send_mad; + slid_is_permissive = (stl_mad->SmpExt.DirectedRoute.DrSLID + == STL_LID_PERMISSIVE); + dlid_is_permissive = (stl_mad->SmpExt.DirectedRoute.DrDLID + == STL_LID_PERMISSIVE); + } + } + OMGT_DBGPRINT(port, "dlid: 0x%x, slid: 0x%x\n", + addr->lid, port->umad_port_cache.base_lid); + if ((!slid_is_permissive) || (!dlid_is_permissive)) { + /* Not a pure DR packet */ + if ((omgt_is_ext_lid(addr->lid)) || + omgt_is_ext_lid(port->umad_port_cache.base_lid) || + addr->flags & OMGT_MAD_ADDR_16B) { + mad_addr = umad_get_mad_addr(umad_p); + mad_addr->gid_index = 0; + mad_addr->grh_present = 1; + mad_addr->hop_limit = 1; + gid.Type.Global.SubnetPrefix = port->umad_port_cache.gid_prefix; + gid.Type.Global.InterfaceID = omgt_create_gid(addr->lid); + BSWAP_IB_GID(&gid); + OMGT_DBGPRINT(port, "Assigned DGID: 0x%lx:0x%lx\n", + ntoh64(gid.Type.Global.InterfaceID), + ntoh64(gid.Type.Global.SubnetPrefix)); + memcpy(mad_addr->gid, &gid, sizeof(gid)); + } else { + umad_set_grh(umad_p, 0); + } + } else { + umad_set_grh(umad_p, 0); + } + + pkey_idx = omgt_find_pkey(port, addr->pkey); + if (pkey_idx < 0) { + OMGT_DBGPRINT(port, "P_Key 0x%x not found in pkey table\n", addr->pkey); + if (addr->pkey == 0xffff) { + pkey_idx = omgt_find_pkey(port, 0x7fff); + if (pkey_idx < 0) { + OMGT_OUTPUT_ERROR(port, "Failed to find 0x7fff pkey defaulting to index 1\n"); + pkey_idx = 1; + } else { + OMGT_DBGPRINT(port, "... using 0x7fff found at index %d\n", pkey_idx); + } + } else { + // Previously, this code would try to find the limited management pkey + // if it could not find the requested pkey, and use that pkey instead. + // This would often "work" because all nodes should have the limited + // management pkey, but b/c it was a limited member, this would result + // in potential timeouts - especially where the full management pkey was + // required. + // Changed this code fail immediately without retrying a new pkey. + OMGT_OUTPUT_ERROR(port, "Failed to find requested pkey:0x%x, class 0x%x aid:0x%x \n", + addr->pkey, mclass, ntohs(mad_hdr->attr_id)); + status = FPROTECTION; + goto done; + } + } + umad_set_pkey(umad_p, pkey_idx); + + umad_set_addr(umad_p, ib_lid, addr->qpn, addr->sl, addr->qkey); + + correctedTimeout = (timeout_ms == OMGT_SEND_TIMEOUT_DEFAULT) + ? OMGT_DEF_TIMEOUT_MS : timeout_ms; + + if (port->dbg_file) { + OMGT_DBGPRINT(port, ">>> sending: len %ld pktsz %zu\n", send_size, umad_size() + padded_size); + umad_dump(umad_p); + omgt_dump_mad(port->dbg_file, umad_get_mad(umad_p), send_size, "send mad\n"); + } + + if (umad_send(port->umad_fd, aid, umad_p, padded_size, (response ? 0 : correctedTimeout), retries) < 0) { + OMGT_OUTPUT_ERROR(port, "send failed; %s, agent id %u MClass 0x%x method 0x%x attrId 0x%x attrM 0x%x\n", + strerror(errno), aid, mclass, mad_hdr->method, + ntohs(mad_hdr->attr_id), ntohl(mad_hdr->attr_mod)); + status = FNOT_DONE; + goto done; + } +done: + // Free umad if allocated. + if (umad_p != NULL) { + umad_free(umad_p); + } + return status; +} + +/** ========================================================================= */ +FSTATUS omgt_recv_mad_alloc(struct omgt_port *port, uint8_t **recv_mad, size_t *recv_size, + int timeout_ms, struct omgt_mad_addr *addr) +{ + #define STL_MAD_SIZE 2048 // Note, hack should reference size value OFED standard header file + FSTATUS status = FSUCCESS; + ib_user_mad_t *umad = NULL; + int mad_agent; + uint32_t my_umad_status = 0; + size_t length; + + if (!port || !recv_mad || !recv_size) + return FINVALID_PARAMETER; + + length = STL_MAD_SIZE; + umad = umad_alloc(1, umad_size() + length); + if (!umad) { + OMGT_OUTPUT_ERROR(port, "can't alloc MAD sized umad\n"); + status = FINSUFFICIENT_MEMORY; + goto done; + } + +retry: + + mad_agent = umad_recv(port->umad_fd, umad, (int *)&length, timeout_ms); + // There are 4 combinations: + // assorted errors: mad_agent < 0, length <= MAD_SIZE + // large RMPP response: mad_agent < 0, length > MAD_SIZE, umad_status==0 + // got response: mad_agent >= 0, length <= MAD_SIZE, umad_status==0 + // no response: mad_agent >= 0, length <= MAD_SIZE, umad_status == error + if (mad_agent < 0) { + if (length <= STL_MAD_SIZE) { + // no MAD returned. None available. + OMGT_DBGPRINT(port, "recv error on MAD sized umad (%s) length=%ld\n", + strerror(errno), length); + if (errno == EINTR) + goto retry; + + status = (errno == ETIMEDOUT) ? FNOT_DONE : FERROR; + goto done; + } else { + /* Need a larger buffer for RMPP */ + OMGT_DBGPRINT(port, "Received 1st MAD length=%ld\n", length); + umad_free(umad); + + umad = umad_alloc(1, umad_size() + length); + if (!umad) { + OMGT_OUTPUT_ERROR(port, "can't alloc umad length %ld\n", length); + status = FINSUFFICIENT_MEMORY; + goto done; + } + + // just to be safe, we supply a timeout. However it + // should be unnecessary since we know we have a packet +retry2: + if ((mad_agent = umad_recv(port->umad_fd, umad, (int *)&length, OMGT_DEF_TIMEOUT_MS)) < 0) { + OMGT_OUTPUT_ERROR(port, "recv error on umad length %ld (%s)\n", length, strerror(errno)); + if (errno == EINTR) + goto retry2; + + status = FOVERRUN; + *recv_size = length; + goto done; + } + + /* + * PA RMPP MADs need to be handled differently as the Kernel + * RMPP module reassembles the PA MADs believing the header to + * only be 40 bytes (MAD[24] + RMPP[12] + OUI[4]). However, OPA uses + * 56 bytes (MAD[24] + RMPP[12] + PA_HEADER[20]), like the SA Class. + * + * As a result the extra 16 bytes ends up in the payload returned by + * umad_recv() before every segment (packet). Here is where we + * remove the extra 16 bytes per packet segment. + */ + uint8_t mgmt_class = ((SA_MAD *)umad_get_mad(umad))->common.MgmtClass; + if (mgmt_class == MCLASS_VFI_PM) { +#define RMPP_VENDOR_HDR_LEN 40 +#define RMPP_PA_HDR_LEN 56 +#define RMPP_PA_DATA_OFFSET (RMPP_PA_HDR_LEN - RMPP_VENDOR_HDR_LEN) + + SA_MAD *rcv_mad = (SA_MAD *)umad_get_mad(umad); + size_t final_len, len = length; + /* Get the number of full packet segments in the response */ + int i, full_segments = (len - RMPP_VENDOR_HDR_LEN) / (STL_SUBN_ADM_DATASIZE + RMPP_PA_DATA_OFFSET); + /* Get Size of Final Segment if it is not a full segment (size != 1992 + 16) */ + size_t last_seg = + ((len - RMPP_VENDOR_HDR_LEN) % + (STL_SUBN_ADM_DATASIZE + RMPP_PA_DATA_OFFSET)) <= RMPP_PA_DATA_OFFSET ? 0 : + ((len - RMPP_VENDOR_HDR_LEN) % + (STL_SUBN_ADM_DATASIZE + RMPP_PA_DATA_OFFSET)) - RMPP_PA_DATA_OFFSET; + + /* Using Segments find the size of what the real payload should be */ + final_len = RMPP_PA_HDR_LEN + (full_segments * STL_SUBN_ADM_DATASIZE) + last_seg; + + OMGT_DBGPRINT(port, "PA Mad RMPP Adjustment:\n"); + OMGT_DBGPRINT(port, " Length: Before %zu v. After %zu\n", len, final_len); + OMGT_DBGPRINT(port, " Segments: %u%s\n", full_segments, (last_seg ? " + 1" : "")); + + uint8_t *new_data = (uint8_t *)umad_alloc(1, umad_size() + final_len); + if (new_data == NULL) { + OMGT_OUTPUT_ERROR(port, "error allocating query result buffer\n"); + status = FINSUFFICIENT_MEMORY; + goto done; + } + /* Copy UMAD and Class Header Data */ + memcpy(new_data, (uint8_t *)umad, umad_size() + RMPP_PA_HDR_LEN); + /* Move old_ptr to start of data past the first Header */ + uint8_t *old_ptr = ((uint8_t *)rcv_mad) + RMPP_PA_HDR_LEN; + uint8_t *new_ptr = new_data + umad_size() + RMPP_PA_HDR_LEN; + + for (i = 0; i < full_segments; i++) { + /* Copy Full Segments */ + memcpy(new_ptr, old_ptr, STL_SUBN_ADM_DATASIZE); + /* Remove 16 byte offset from old segement */ + old_ptr += RMPP_PA_DATA_OFFSET; + /* Move Pointers */ + old_ptr += STL_SUBN_ADM_DATASIZE; + new_ptr += STL_SUBN_ADM_DATASIZE; + } + /* Copy Last Segment if not full. old_ptr updated above */ + if (last_seg) { + memcpy(new_ptr, old_ptr, last_seg); + } + /* Clean up Old Data*/ + free(umad); + /* Copy New_Data to umad pointer */ + umad = (ib_user_mad_t *)new_data; + /* Update Length */ + length = final_len; + umad->length = final_len + umad_size(); + } + } + } + + if (mad_agent >= UMAD_CA_MAX_AGENTS) { + OMGT_OUTPUT_ERROR(port, "invalid mad agent %d - dropping\n", mad_agent); + status = FERROR; + goto done; + } + + my_umad_status = umad_status(umad); + OMGT_DBGPRINT(port, "UMAD Status: %s (%d)\n", strerror(my_umad_status), my_umad_status); + if (my_umad_status != 0) { + status = (my_umad_status == ETIMEDOUT) ? FTIMEOUT : FREJECT; + } + + OMGT_DBGPRINT(port, "Received MAD length=%ld, total umad size=%ld\n",length, length + umad_size()); + + if (port->dbg_file) { + struct umad_hdr * umad_hdr = (struct umad_hdr *)umad_get_mad(umad); + OMGT_DBGPRINT(port, " Base_Version 0x%x Class 0x%x Method 0x%x attrId 0x%x attr_mod 0x%x status 0x%x\n", + umad_hdr->base_version, umad_hdr->mgmt_class, umad_hdr->method, + umad_hdr->attr_id, umad_hdr->attr_mod, umad_hdr->status); + umad_dump(umad); + omgt_dump_mad(port->dbg_file, umad_get_mad(umad), length, "rcv mad\n"); + + } + + // Allocate and copy to new buffer. + *recv_mad = calloc (1, length); + + if (*recv_mad == NULL) { + OMGT_OUTPUT_ERROR(port, "can't alloc return buffer length %ld\n", length); + status = FINSUFFICIENT_MEMORY; + goto done; + } + + memcpy (*recv_mad, umad_get_mad(umad), length); + *recv_size = length; + + if (addr != NULL) { + addr->lid = omgt_extract_lid(umad); + addr->sl = umad->addr.sl; + addr->qkey = ntoh32(umad->addr.qkey); + addr->qpn = ntoh32(umad->addr.qpn); + addr->pkey = omgt_find_pkey_from_idx(port, umad_get_pkey(umad)); + } + +done: + if (umad != NULL) { + umad_free(umad); + } + return status; +} + +/** ========================================================================= */ +FSTATUS omgt_recv_mad_no_alloc(struct omgt_port *port, uint8_t *recv_mad, size_t *recv_size, + int timeout_ms, struct omgt_mad_addr *addr) +{ + size_t length = *recv_size; + ib_user_mad_t *umad = NULL; + int mad_agent; + uint32_t my_umad_status = 0; + FSTATUS status = FSUCCESS; + + if (!port || !recv_mad || !*recv_size) + return FINVALID_PARAMETER; + + umad = umad_alloc(1, length + umad_size()); + if (!umad) { + OMGT_OUTPUT_ERROR(port, "can't alloc umad length %ld\n", length); + status = FINSUFFICIENT_MEMORY; + goto done; + } + +retry: + mad_agent = umad_recv(port->umad_fd, umad, (int *)&length, timeout_ms); + // There are 4 combinations: + // assorted errors: mad_agent < 0, length <= MAD_SIZE + // large RMPP response: mad_agent < 0, length > MAD_SIZE, umad_status==0 + // got response: mad_agent >= 0, length <= MAD_SIZE, umad_status==0 + // no response: mad_agent >= 0, length <= MAD_SIZE, umad_status == error + if (mad_agent < 0) { + if (length <= *recv_size) { + // no MAD returned. None available. + OMGT_DBGPRINT(port, "recv error on umad (size %zu) (%s)\n", *recv_size, + strerror(errno)); + if (errno == EINTR) + goto retry; + + status = (errno == ETIMEDOUT) ? FNOT_DONE:FERROR; + goto done; + } else { + // this routine is not expecting large responses + OMGT_OUTPUT_ERROR(port, "Rx Packet size %zu larger than mad-size %zu\n", + length, *recv_size); + status = FOVERRUN; + if (recv_mad) + memcpy(recv_mad, umad_get_mad(umad), *recv_size); + + // Clean out Rx packet 'cause it will never go away.. + umad_free(umad); + umad = umad_alloc(1, umad_size() + length); + if (!umad) { + OMGT_OUTPUT_ERROR(port, "can't alloc umad for rx cleanup, length %ld\n", length); + status = FINSUFFICIENT_MEMORY; + goto done; + } + + // just to be safe, we supply a timeout. However it + // should be unnecessary since we know we have a packet +retry2: + if (umad_recv(port->umad_fd, umad, (int *)&length, OMGT_DEF_TIMEOUT_MS) < 0) { + OMGT_OUTPUT_ERROR(port, "recv error on cleanup, length %ld (%s)\n", length, + strerror(errno)); + if (errno == EINTR) + goto retry2; + + goto done; + } + + if (port->dbg_file) { + umad_dump(umad); + omgt_dump_mad(port->dbg_file, umad_get_mad(umad), length, "rcv mad discarded\n"); + } + goto done; + } + } + if (mad_agent >= UMAD_CA_MAX_AGENTS) { + OMGT_OUTPUT_ERROR(port, "invalid mad agent %d\n", mad_agent); + status = FERROR; + goto done; + } + + my_umad_status = umad_status(umad); + OMGT_DBGPRINT(port, "UMAD Status: %s (%d)\n", strerror(my_umad_status), my_umad_status); + if (my_umad_status != 0) { + status = (my_umad_status == ETIMEDOUT) ? FTIMEOUT : FREJECT; + } + + OMGT_DBGPRINT(port, "Received MAD: Agent %d, length=%ld\n", mad_agent, length); + if (port->dbg_file) { + umad_dump(umad); + omgt_dump_mad(port->dbg_file, umad_get_mad(umad), length, "rcv mad\n"); + } + + // Copy the data + if (recv_mad && length > 0) { + *recv_size = length; + memcpy(recv_mad, umad_get_mad(umad), length); + } + + if (addr != NULL) { + addr->lid = omgt_extract_lid(umad); + addr->sl = umad->addr.sl; + addr->qkey = ntoh32(umad->addr.qkey); + addr->qpn = ntoh32(umad->addr.qpn); + addr->pkey = omgt_find_pkey_from_idx(port, umad_get_pkey(umad)); + } + +done: + if (umad != NULL) { + umad_free(umad); + } + return status; +} + +/** ========================================================================= +FSTATUS omgt_get_portguid( + uint32_t ca, + uint32_t port, + char *pCaName, + uint64_t *pCaGuid, + uint64_t *pPortGuid, + IB_CA_ATTRIBUTES *pCaAttributes, + IB_PORT_ATTRIBUTES **ppPortAttributes, + uint32_t *pCaCount, + uint32_t *pPortCount, + char *pRetCaName, + int *pRetPortNum, + uint64_t *pRetGIDPrefix) +{ + +} +*/ + +/* + * Get MAD status code from most recent PA operation + * + * @param port Local port to operate on. + * + * @return + * The corresponding status code. + */ +uint16_t +omgt_get_pa_mad_status( + IN struct omgt_port *port + ) +{ + return port->pa_mad_status; +} diff --git a/opamgt/src/opamgt_dump_mad.c b/opamgt/src/opamgt_dump_mad.c new file mode 100644 index 0000000..279aa9e --- /dev/null +++ b/opamgt/src/opamgt_dump_mad.c @@ -0,0 +1,480 @@ +/* BEGIN_ICS_COPYRIGHT7 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT7 ****************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#include +#include + +#define OMGT_STACK_BUF_SIZE 128 + +/* + * Extends umad_class_str(). + */ +const char *stl_class_str(uint8_t BaseVersion, uint8_t class) +{ + if (BaseVersion != STL_BASE_VERSION) { + return umad_class_str(class); + } + switch (class) { + case MCLASS_VFI_PM: return("PerfAdm"); + } + return umad_class_str(class); +} +/* + * Extends umad_method_str(). + * + * Added All Methods defined in IB spec which STL spec links to. + * Numbers were used because There is no central definition for all methods used in STL or IB code that makes sense. + */ +const char *stl_method_str(uint8_t BaseVersion, uint8_t class, uint8_t method) +{ + if (BaseVersion != STL_BASE_VERSION) { + return umad_method_str(class, method); + } + switch (method) { + case 0x01: return("Get"); + case 0x02: return("Set"); + case 0x03: return("Send"); + case 0x05: return("Trap"); + case 0x06: return("Report"); + case 0x07: return("TrapRepress"); + case 0x12: return("GetTable"); + case 0x13: return("GetTraceTable"); + case 0x14: return("GetMulti"); + case 0x15: return("Delete"); + case 0x81: return("GetResp"); + case 0x86: return("ReportResp"); + case 0x92: return("GetTableResp"); + case 0x94: return("GetMultiResp"); + case 0x95: return("DeleteResp"); + } + return umad_method_str(class, method); +} +/* + * Extends umad_common_mad_status_str(). + * + * Added all common status options because they have higher priority over class-specific statuses. + * Could not include definitions from Esm/ib/include/ib_mad.h + */ +const char *stl_mad_status_str(uint8_t BaseVersion, uint8_t class, uint16_t Status) +{ + if (BaseVersion != STL_BASE_VERSION) + return umad_common_mad_status_str(Status); + + uint16 status = ntohs(Status); + if (!(status & 0x7FFF)) return("Success"); + if (status & 0x0001) return("Busy"); // MAD_STATUS_BUSY + if (status & 0x0002) return("Redirection required"); // MAD_STATUS_REDIRECT + if (status & 0x001C) { //7 = 0x001C = 0000 0000 0001 1100 = MAD_STATUS_BAD_FIELD + switch (status) { + case 0x0004: return("Bad Class and/or Base Version"); //1 = 0x0004 = 0000 0000 0000 0100 = MAD_STATUS_BAD_CLASS + case 0x0008: return("Method not supported"); //2 = 0x0008 = 0000 0000 0000 1000 = MAD_STATUS_BAD_METHOD + case 0x000C: return("Method/Attribute combination not supported"); //3 = 0x000C = 0000 0000 0000 1100 = MAD_STATUS_BAD_ATTR + case 0x0010: //4 = 0x0010 = 0000 0000 0001 0000 = MAD_STATUS_RSVD1 + case 0x0014: //5 = 0x0014 = 0000 0000 0001 0100 = MAD_STATUS_RSVD2 + case 0x0018: //6 = 0x0018 = 0000 0000 0001 1000 = MAD_STATUS_RSVD3 + default: return("Invalid Attribute/Modifier"); + } + } + // Check Class Specific Status Bits 8-14 = 0x7F00 + if (status & 0x7F00) { + switch (class) { + case MCLASS_SM_LID_ROUTED: //SM + case MCLASS_SM_DIRECTED_ROUTE: + break; + case MCLASS_SUBN_ADM: return umad_sa_mad_status_str(Status); + case MCLASS_PERF: //PM + switch (status) { + case STL_PM_STATUS_REQUEST_TOO_LARGE: return("Request too large"); + case STL_PM_STATUS_NUMBLOCKS_INCONSISTENT: return("Request too large"); + case STL_PM_STATUS_OPERATION_FAILED: return("Request too large"); + } + break; + case MCLASS_VFI_PM: //PA + switch (status) { + case STL_MAD_STATUS_STL_PA_UNAVAILABLE: return("Engine unavailable"); + case STL_MAD_STATUS_STL_PA_NO_GROUP: return("No such group"); + case STL_MAD_STATUS_STL_PA_NO_PORT: return("Port not found"); + case STL_MAD_STATUS_STL_PA_NO_VF: return("VF not found"); + case STL_MAD_STATUS_STL_PA_INVALID_PARAMETER: return("Invalid parameter"); + case STL_MAD_STATUS_STL_PA_NO_IMAGE: return("Image not found"); + case STL_MAD_STATUS_STL_PA_NO_DATA: return("No Counter Data"); + case STL_MAD_STATUS_STL_PA_BAD_DATA: return("Bad Counter Data"); + default: return umad_sa_mad_status_str(Status); + } + break; + } + } + return umad_common_mad_status_str(Status); +} +/* + * Extends umad_attribute_str(). + * + * Added All AttrIDs because they were redefined with STL_... + */ +const char *stl_attribute_str(uint8_t BaseVersion, uint8_t class, uint16_t attr) +{ + if (BaseVersion != STL_BASE_VERSION) + return umad_attribute_str(class, attr); + + switch (class) { + case MCLASS_SM_LID_ROUTED: //SM //0x01 + case MCLASS_SM_DIRECTED_ROUTE: //0x81 + switch (ntoh16(attr)) { + case STL_MCLASS_ATTRIB_ID_NODE_DESCRIPTION: return("NodeDesc"); + case STL_MCLASS_ATTRIB_ID_NODE_INFO: return("NodeInfo"); + case STL_MCLASS_ATTRIB_ID_SWITCH_INFO: return("SwitchInfo"); + case STL_MCLASS_ATTRIB_ID_PORT_INFO: return("PortInfo"); + case STL_MCLASS_ATTRIB_ID_PART_TABLE: return("PKey"); + case STL_MCLASS_ATTRIB_ID_SL_SC_MAPPING_TABLE: return("SLtoSC"); + case STL_MCLASS_ATTRIB_ID_SC_SC_MULTI_SET: return("SLtoSCMulti"); + case STL_MCLASS_ATTRIB_ID_VL_ARBITRATION: return("VLArb"); + case STL_MCLASS_ATTRIB_ID_LINEAR_FWD_TABLE: return("LinerFwdTable"); + case STL_MCLASS_ATTRIB_ID_MCAST_FWD_TABLE: return("MulticastFwdTable"); + case STL_MCLASS_ATTRIB_ID_SM_INFO: return("SMInfo"); + case STL_MCLASS_ATTRIB_ID_LED_INFO: return("LEDInfo"); + case STL_MCLASS_ATTRIB_ID_CABLE_INFO: return("CableInfo"); + case STL_MCLASS_ATTRIB_ID_AGGREGATE: return("Aggregate"); + case STL_MCLASS_ATTRIB_ID_SC_SC_MAPPING_TABLE: return("SCtoSC"); + case STL_MCLASS_ATTRIB_ID_SC_SL_MAPPING_TABLE: return("SCtoSL"); + case STL_MCLASS_ATTRIB_ID_SC_VLR_MAPPING_TABLE: return("SCtoVLr"); + case STL_MCLASS_ATTRIB_ID_SC_VLT_MAPPING_TABLE: return("SCtoVLt"); + case STL_MCLASS_ATTRIB_ID_SC_VLNT_MAPPING_TABLE: return("SCtoVLnt"); + case STL_MCLASS_ATTRIB_ID_PORT_STATE_INFO: return("PortStateInfo"); + case STL_MCLASS_ATTRIB_ID_PORT_GROUP_FWD_TABLE: return("PortGroupFwdTable"); + case STL_MCLASS_ATTRIB_ID_PORT_GROUP_TABLE: return("PortGroupTable"); + case STL_MCLASS_ATTRIB_ID_BUFFER_CONTROL_TABLE: return("BufferCtrlTable"); + case STL_MCLASS_ATTRIB_ID_CONGESTION_INFO: return("CongestionInfo"); + case STL_MCLASS_ATTRIB_ID_SWITCH_CONGESTION_LOG: return("SwitchCongLog"); + case STL_MCLASS_ATTRIB_ID_SWITCH_CONGESTION_SETTING: return("SwitchCongSetting"); + case STL_MCLASS_ATTRIB_ID_SWITCH_PORT_CONGESTION_SETTING: return("SwitchPortCongSetting"); + case STL_MCLASS_ATTRIB_ID_HFI_CONGESTION_LOG: return("HFICongLog"); + case STL_MCLASS_ATTRIB_ID_HFI_CONGESTION_SETTING: return("HFICongSetting"); + case STL_MCLASS_ATTRIB_ID_HFI_CONGESTION_CONTROL_TABLE: return("HFICongCtrlTable"); + } + break; + case MCLASS_SUBN_ADM: //SA //0x03 + switch (ntoh16(attr)) { + case STL_SA_ATTR_CLASS_PORT_INFO: return("ClassPortInfo"); + case STL_SA_ATTR_NOTICE: return("Notice"); + case STL_SA_ATTR_INFORM_INFO: return("InformInfo"); + case STL_SA_ATTR_NODE_RECORD: return("NodeRecord"); + case STL_SA_ATTR_PORTINFO_RECORD: return("PortInfoRecord"); + case STL_SA_ATTR_SC_MAPTBL_RECORD: return("SCMappingTableRecord"); + case STL_SA_ATTR_SWITCHINFO_RECORD: return("SwitchInfoRecord"); + case STL_SA_ATTR_LINEAR_FWDTBL_RECORD: return("LinerFwdTableRecord"); + case STL_SA_ATTR_MCAST_FWDTBL_RECORD: return("MulticastFwdTableRecord"); + case STL_SA_ATTR_SMINFO_RECORD: return("SMInfoRecord"); + case STL_SA_ATTR_LINK_SPD_WDTH_PAIRS_RECORD: return("LinkSpeedWithPairsRecord"); + case STL_SA_ATTR_LINK_RECORD: return("LinkRecord"); + case STL_SA_ATTR_SERVICE_RECORD: return("ServiceRecord"); + case STL_SA_ATTR_P_KEY_TABLE_RECORD: return("PKeyTableRecord"); + case STL_SA_ATTR_PATH_RECORD: return("PathRecord"); + case STL_SA_ATTR_VLARBTABLE_RECORD: return("VLArbitrationRecord"); + case STL_SA_ATTR_MCMEMBER_RECORD: return("MulticastMemberRecord"); + case STL_SA_ATTR_TRACE_RECORD: return("TraceRecord"); + case STL_SA_ATTR_MULTIPATH_GID_RECORD: return("MultipathGIDRecord"); + case STL_SA_ATTR_SERVICEASSOCIATION_RECORD: return("ServiceAssociationRecord"); + case STL_SA_ATTR_INFORM_INFO_RECORD: return("InformInfoRecord"); + case STL_SA_ATTR_SC2SL_MAPTBL_RECORD: return("SCtoSLMappingTableRecord"); + case STL_SA_ATTR_SC2VL_NT_MAPTBL_RECORD: return("SCtoVLntMappingTableRecord"); + case STL_SA_ATTR_SC2VL_T_MAPTBL_RECORD: return("SCtoVLtMappingTableRecord"); + case STL_SA_ATTR_SC2VL_R_MAPTBL_RECORD: return("SCtoVLrMappingTableRecord"); + case STL_SA_ATTR_PGROUP_FWDTBL_RECORD: return("PortGroupFwdTableRecord"); + case STL_SA_ATTR_MULTIPATH_GUID_RECORD: return("MultipathGUIDRecord"); + case STL_SA_ATTR_MULTIPATH_LID_RECORD: return("MultipathLIDRecord"); + case STL_SA_ATTR_CABLE_INFO_RECORD: return("CableInfoRecord"); + case STL_SA_ATTR_VF_INFO_RECORD: return("VFInfoRecord"); + case STL_SA_ATTR_PORT_STATE_INFO_RECORD: return("PortStateInfoRecord"); + case STL_SA_ATTR_PORTGROUP_TABLE_RECORD: return("PortGroupTableRecord"); + case STL_SA_ATTR_BUFF_CTRL_TAB_RECORD: return("BufferCtrlTableRecord"); + case STL_SA_ATTR_FABRICINFO_RECORD: return("FabricInfoRecord"); + case STL_SA_ATTR_QUARANTINED_NODE_RECORD: return("QuarantinedNodeRecord"); + case STL_SA_ATTR_CONGESTION_INFO_RECORD: return("CongestionInfoRecord"); + case STL_SA_ATTR_SWITCH_CONG_RECORD: return("SwitchCongestionRecord"); + case STL_SA_ATTR_SWITCH_PORT_CONG_RECORD: return("SwitchPortCongestionRecord"); + case STL_SA_ATTR_HFI_CONG_RECORD: return("HFICongestionRecord"); + case STL_SA_ATTR_HFI_CONG_CTRL_RECORD: return("HFICongestionCtrlRecord"); + case STL_SA_ATTR_SWITCH_COST_RECORD: return("SwitchCostRecord"); + } + break; + case MCLASS_PERF: //PM //0x04 + switch (ntoh16(attr)) { + case STL_PM_ATTRIB_ID_CLASS_PORTINFO: return("ClassPortInfo"); + case STL_PM_ATTRIB_ID_PORT_STATUS: return("PortStatus"); + case STL_PM_ATTRIB_ID_CLEAR_PORT_STATUS: return("ClearPortStatus"); + case STL_PM_ATTRIB_ID_DATA_PORT_COUNTERS: return("DataPortCounters"); + case STL_PM_ATTRIB_ID_ERROR_PORT_COUNTERS: return("ErrorPortCounters"); + case STL_PM_ATTRIB_ID_ERROR_INFO: return("ErrorInfo"); + } + break; + case MCLASS_VFI_PM: //PA //0x32 + switch (ntoh16(attr)) { + case STL_PA_ATTRID_GET_CLASSPORTINFO: return("ClassPortInfo"); + case STL_PA_ATTRID_GET_GRP_LIST: return("GroupList"); + case STL_PA_ATTRID_GET_GRP_INFO: return("GroupInfo"); + case STL_PA_ATTRID_GET_GRP_CFG: return("GroupConfig"); + case STL_PA_ATTRID_GET_PORT_CTRS: return("PortCounters"); + case STL_PA_ATTRID_CLR_PORT_CTRS: return("ClearPortCounters"); + case STL_PA_ATTRID_CLR_ALL_PORT_CTRS: return("ClearAllPortCounters"); + case STL_PA_ATTRID_GET_PM_CONFIG: return("PmConfig"); + case STL_PA_ATTRID_FREEZE_IMAGE: return("FreezeImage"); + case STL_PA_ATTRID_RELEASE_IMAGE: return("ReleaseImage"); + case STL_PA_ATTRID_RENEW_IMAGE: return("RenewImage"); + case STL_PA_ATTRID_GET_FOCUS_PORTS: return("FocusPorts"); + case STL_PA_ATTRID_GET_IMAGE_INFO: return("ImageInfo"); + case STL_PA_ATTRID_MOVE_FREEZE_FRAME: return("MoveFreezeFrame"); + case STL_PA_ATTRID_GET_VF_LIST: return("VFList"); + case STL_PA_ATTRID_GET_VF_INFO: return("VFInfo"); + case STL_PA_ATTRID_GET_VF_CONFIG: return("VFConfig"); + case STL_PA_ATTRID_GET_VF_PORT_CTRS: return("VFPortCounters"); + case STL_PA_ATTRID_CLR_VF_PORT_CTRS: return("ClearVFPortCounters"); + case STL_PA_ATTRID_GET_VF_FOCUS_PORTS: return("VFFocusPorts"); + case STL_PA_ATTRID_GET_FOCUS_PORTS_MULTISELECT: return("MultiSelectFocusPorts"); + case STL_PA_ATTRID_GET_GRP_NODE_INFO: return("GroupNodeInfo"); + case STL_PA_ATTRID_GET_GRP_LINK_INFO: return("GroupLinkInfo"); + case STL_PA_ATTRID_GET_GRP_LIST2: return("GroupList2"); + case STL_PA_ATTRID_GET_VF_LIST2: return("VFList2"); + } + break; + + } + + return umad_attribute_str(class, attr); +} + +static void print_mad_hdr_syslog(uint8_t *buf, size_t size) +{ + struct umad_hdr * umad_hdr = (struct umad_hdr *)buf; + int i; + + int n = 0; + char tmp[OMGT_STACK_BUF_SIZE]; + + n += snprintf(tmp+n, OMGT_STACK_BUF_SIZE - n, "%06d: ", 0); + for (i = 0; i < size;) { + n += snprintf(tmp+n, OMGT_STACK_BUF_SIZE - n, "%02x", buf[0]); + if (++i >= size) + break; + n += snprintf(tmp+n, OMGT_STACK_BUF_SIZE - n, "%02x", buf[1]); + if ((++i) % 4) + n += snprintf(tmp+n, OMGT_STACK_BUF_SIZE - n, " "); + else { + switch(i) { + case 4: + n += snprintf(tmp+n, OMGT_STACK_BUF_SIZE - n, " %02d | %s | %02d | %s", + umad_hdr->base_version, + stl_class_str(umad_hdr->base_version, umad_hdr->mgmt_class), + umad_hdr->class_version, + stl_method_str(umad_hdr->base_version, umad_hdr->mgmt_class, umad_hdr->method)); + break; + case 8: + n += snprintf(tmp+n, OMGT_STACK_BUF_SIZE - n, " %s", + stl_mad_status_str(umad_hdr->base_version, umad_hdr->mgmt_class, umad_hdr->status)); + break; + case 20: + n += snprintf(tmp+n, OMGT_STACK_BUF_SIZE - n, " %s | ", + stl_attribute_str(umad_hdr->base_version, umad_hdr->mgmt_class, umad_hdr->attr_id)); + break; + case 24: + n += snprintf(tmp+n, OMGT_STACK_BUF_SIZE - n, " (AttributeModifier)"); + break; + default: + break; + } + syslog(LOG_DEBUG, "%s", tmp); + n = 0; + n += snprintf(tmp+n, OMGT_STACK_BUF_SIZE - n, "%06d: ", i); + } + buf += 2; + } + syslog(LOG_DEBUG, "%s", tmp); +} + +static void print_mad_hdr(FILE *file, uint8_t *buf, size_t size) +{ + struct umad_hdr * umad_hdr = (struct umad_hdr *)buf; + int i; + + if (file == OMGT_DBG_FILE_SYSLOG) { + print_mad_hdr_syslog(buf, size); + return; + } + + fprintf(file, "%06d: ", 0); + for (i = 0; i < size;) { + fprintf(file, "%02x", buf[0]); + if (++i >= size) + break; + fprintf(file, "%02x", buf[1]); + if ((++i) % 4) + fprintf(file, " "); + else { + switch(i) { + case 4: + fprintf(file, " %02d | %s | %02d | %s", + umad_hdr->base_version, + stl_class_str(umad_hdr->base_version, umad_hdr->mgmt_class), + umad_hdr->class_version, + stl_method_str(umad_hdr->base_version, umad_hdr->mgmt_class, umad_hdr->method)); + break; + case 8: + fprintf(file, " %s", + stl_mad_status_str(umad_hdr->base_version, umad_hdr->mgmt_class, umad_hdr->status)); + break; + case 20: + fprintf(file, " %s | ", + stl_attribute_str(umad_hdr->base_version, umad_hdr->mgmt_class, umad_hdr->attr_id)); + break; + case 24: + fprintf(file, " (AttributeModifier)"); + break; + default: + break; + } + fprintf(file, "\n%06d: ", i); + } + buf += 2; + } + fprintf(file, "\n"); +} + +static void omgt_xdump_syslog(uint8_t *buf, size_t size, int width) +{ + int i; + int n = 0; + char tmp[OMGT_STACK_BUF_SIZE]; + + n += snprintf(tmp+n, OMGT_STACK_BUF_SIZE - n, "%06d: ", 0); + for (i = 0; i < size;) { + n += snprintf(tmp+n, OMGT_STACK_BUF_SIZE - n, "%02x", buf[0]); + if (++i >= size) + break; + n += snprintf(tmp+n, OMGT_STACK_BUF_SIZE - n, "%02x", buf[1]); + if ((++i) % width) + n += snprintf(tmp+n, OMGT_STACK_BUF_SIZE - n, " "); + else { + syslog(LOG_DEBUG, "%s", tmp); + n = 0; + n += snprintf(tmp+n, OMGT_STACK_BUF_SIZE - n, "%06d: ", i); + } + buf += 2; + } + syslog(LOG_DEBUG, "%s", tmp); +} + +void omgt_xdump(FILE *file, uint8_t *buf, size_t size, int width) +{ + int i; + + if (file == OMGT_DBG_FILE_SYSLOG) { + omgt_xdump_syslog(buf, size, width); + return; + } + + fprintf(file, "%06d: ", 0); + for (i = 0; i < size;) { + fprintf(file, "%02x", buf[0]); + if (++i >= size) + break; + fprintf(file, "%02x", buf[1]); + if ((++i) % width) + fprintf(file, " "); + else { + fprintf(file, "\n"); + fprintf(file, "%06d: ", i); + } + buf += 2; + } + fprintf(file, "\n"); +} + +static size_t get_data_offset(uint8_t mgmt_class) +{ + switch (mgmt_class) { + case MCLASS_SM_LID_ROUTED: return(24+8); //MAD+MKey + case MCLASS_SM_DIRECTED_ROUTE: return(24+8+4+4+64+64+8); //MAD+Mkey+SLID+DLID+InitPath+RetPath+Rsvd2 + case MCLASS_SUBN_ADM: return(24+12+8+2+2+8); //MAD+RMPP+SMKey+AttrOff+Rsvd+CompMask + case MCLASS_PERF: return(24); //MAD + case MCLASS_VFI_PM: return(24+12+8+2+2+8); //MAD+RMPP+SMKey+AttrOff+Rsvd+CompMask + case MCLASS_BM: + case MCLASS_DEV_MGT: + case MCLASS_COMM_MGT: + case MCLASS_SNMP: + case MCLASS_DEV_CONF_MGT: + case MCLASS_DTA: + case MCLASS_CC: + default: return(24); + } +} + +void omgt_dump_mad(FILE * file, uint8_t *buf, size_t size, const char *msg, ...) +{ + char b[512]; + va_list va; + size_t hdr_size; + uint8_t class = buf[1]; + size_t data_off = 24; + + if (msg) { + va_start(va, msg); + vsnprintf(b, 511, msg, va); + va_end(va); + b[511] = '\0'; + if (file == OMGT_DBG_FILE_SYSLOG) + syslog(LOG_DEBUG, "%s", b); + else + fputs(b, file); + } + + data_off = get_data_offset(class); + hdr_size = (size < data_off) ? size : data_off; + + print_mad_hdr(file, buf, hdr_size); + + if (file == OMGT_DBG_FILE_SYSLOG) + syslog(LOG_DEBUG, "Data:\n"); + else + fprintf(file, "Data:\n"); + + if ((size - hdr_size) > 0) { + omgt_xdump(file, buf+hdr_size, size - hdr_size, 8); + } +} diff --git a/opamgt/src/opamgt_ea.c b/opamgt/src/opamgt_ea.c new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/opamgt/src/opamgt_ea.c diff --git a/opamgt/src/opamgt_oob.c b/opamgt/src/opamgt_oob.c new file mode 100644 index 0000000..8e88a8d --- /dev/null +++ b/opamgt/src/opamgt_oob.c @@ -0,0 +1,28 @@ +/* BEGIN_ICS_COPYRIGHT2 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT2 ****************************************/ diff --git a/opamgt/src/opamgt_pa.c b/opamgt/src/opamgt_pa.c new file mode 100644 index 0000000..29841bd --- /dev/null +++ b/opamgt/src/opamgt_pa.c @@ -0,0 +1,4602 @@ +/* BEGIN_ICS_COPYRIGHT7 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT7 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +#ifdef IB_STACK_OPENIB + + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#define OPAMGT_PRIVATE 1 + +// Includes / Defines from IBACCESS +#include "ibt.h" +#include "opamgt_priv.h" +#include "ib_utils_openib.h" +#include "stl_pa_priv.h" +#include "ib_mad.h" +#include "opamgt_dump_mad.h" +#include "stl_sd.h" +#include "stl_pm.h" +#include "opamgt_pa_priv.h" +#include "opamgt_sa_priv.h" + +/************************************** + * Defines and global variables + **************************************/ + +#define IB_SA_DATA_OFFS 56 + +#define MAX_PORTS_LIST 300000 // Max number of ports in port list + +#define OPAMGT_MAD_SIZE 256 +#define OPAMGT_DEF_RETRIES 3 +#define MAD_STATUS_PA_MINIMUM 0x0A00 + +// from ib_sa.h +#define PR_COMPONENTMASK_SRV_ID 0x0000000000000001ull +#define PR_COMPONENTMASK_DGID 0x0000000000000004ull +#define PR_COMPONENTMASK_SGID 0x0000000000000008ull + +//from ib_sa_records.h +#define IB_MULTIPATH_RECORD_COMP_NUMBPATH 0x00000040 + +static uint8_t ib_truescale_oui[] = {OUI_TRUESCALE_0, OUI_TRUESCALE_1, OUI_TRUESCALE_2}; + +static const char* const pa_query_input_type_text[] = +{ + "InputTypeNoInput", +}; + +static const char* const pa_query_result_type_text[] = +{ + "OutputTypePaTableRecord", /* PA_TABLE_PACKET_RESULTS complete PA MultiPacketRespRecords */ +}; + +static const char* const pa_sa_status_text[] = +{ + "Success", // not used by code below + "PA: Insufficient Resources", // 0x0100 NO_RESOURCES + "PA: Invalid Request", // 0x0200 REQ_INVALID + "PA: No Records", // 0x0300 NO_RECORDS + "PA: Too Many Records", // 0x0400 TOO_MANY_RECORDS + "PA: Invalid GID in Request", // 0x0500 REQ_INVALID_GID + "PA: Insufficient Components in Request", // 0x0600 REQ_INSUFFICIENT_COMPONENT +}; +static const char* const pa_status_text[] = +{ + "Success", // not used by code below + "PA: PM Engine Unavailable", //0x0A00 - Engine unavailable + "PA: Group Not Found", //0x0B00 - No such group + "PA: Port Not Found", //0x0C00 - Port not found + "PA: Virtual Fabric Not Found", //0x0D00 - VF not found + "PA: Invalid Parameter", //0x0E00 - Invalid parameter + "PA: Image Not Found", //0x0F00 - Image not found + "PA: No Data", //0x1000 - no data skipped port + "PA: Bad Data", //0x1100 - query fail or clear fail +}; + +/**************************************** + * Prototypes + ****************************************/ + + +/******************************************************** + * Local file functions + *******************************************************/ + +/** + * Send a PA query and get the result. + * + * @param port The port from which we access the fabric. + * @param method PA method identifier. + * @param attr_id PA attribute identifier + * @param attr_mod PA attribute modifier + * @param snd_data Outbound request data. + * @param snd_data_len Outbound request data length. + * @param rcv_buf_len Max rcv buffer length (required for OFED driver) + * @param rsp_mad Response MAD packet. The caller should free it after use. + * @param query_result Query return result (pointer to pointer to the query result). Allocated + * here if successful and the caller must free it. + * + * @return + * FSUCCESS - Query successful + * FERROR - Error + */ +static FSTATUS +pa_query_common( + struct omgt_port *port, + uint8_t method, + uint32_t attr_id, + uint32_t attr_mod, + uint8_t *snd_data, + size_t snd_data_len, + size_t *rcv_buf_len, + SA_MAD **rsp_mad, + PQUERY_RESULT_VALUES *query_result + ) +{ + FSTATUS fstatus = FSUCCESS; + uint32_t rec_sz = 0; + uint32_t rec_cnt = 0; + uint32_t mem_size; + SA_MAD *send_mad = (SA_MAD *)snd_data; + SA_MAD *rcv_mad = NULL; + struct omgt_mad_addr addr = {0}; + MAD_STATUS madStatus = {0}; + static uint32_t mad_tid = 1; + + // do some common stuff for each command / query. + DBG_ENTER_FUNC(port); + + /* If port is In-Band, set up addr */ + if (!port->is_oob_enabled) { + uint8_t port_state; + (void)omgt_port_get_port_state(port, &port_state); + if (port_state != PortStateActive) { + OMGT_OUTPUT_ERROR(port, "Local port not Active!\n"); + return FINVALID_STATE; + } + if ((port->pa_service_state != OMGT_SERVICE_STATE_OPERATIONAL) + && (omgt_pa_service_connect(port) != OMGT_SERVICE_STATE_OPERATIONAL)) { + + OMGT_OUTPUT_ERROR(port, "Query PA failed: PA Service Not Operational: %s (%d)\n", + omgt_service_state_totext(port->pa_service_state), port->pa_service_state); + return FUNAVAILABLE; + } + addr.lid = port->primary_pm_lid; + addr.sl = port->primary_pm_sl; + addr.qpn = 1; + addr.qkey = QP1_WELL_KNOWN_Q_KEY; + addr.pkey = OMGT_DEFAULT_PKEY; + if (omgt_find_pkey(port, OMGT_DEFAULT_PKEY) < 0) { + OMGT_OUTPUT_ERROR(port, "Query PA failed: requires full management node. Status:(%u)\n", FPROTECTION); + return FPROTECTION; + } + } + + OMGT_DBGPRINT(port, "Request MAD method: 0x%x\n", method); + OMGT_DBGPRINT(port, "\taid: 0x%x\n", attr_id); + OMGT_DBGPRINT(port, "\tamod: 0x%x\n", attr_mod); + + // default the parameters to failed state. + *query_result = NULL; + *rsp_mad = NULL; + + /* Setup MAD Header */ + MAD_SET_VERSION_INFO(send_mad, STL_BASE_VERSION, MCLASS_VFI_PM, STL_PA_CLASS_VERSION); + MAD_SET_METHOD_TYPE(send_mad, method); + MAD_SET_ATTRIB_ID(send_mad, attr_id); + MAD_SET_ATTRIB_MOD(send_mad, attr_mod); /* should be zero */ + MAD_SET_TRANSACTION_ID(send_mad, mad_tid++); + + BSWAP_SA_HDR(&send_mad->SaHdr); + BSWAP_MAD_HEADER((MAD *)&send_mad->common); + + /* Add OUI to MAD after BSWAP */ + struct umad_vendor_packet *pkt = (struct umad_vendor_packet *)send_mad; + memcpy(&pkt->oui, ib_truescale_oui, 3); + + // submit RMPP MAD request + fstatus = omgt_send_recv_mad_alloc(port, snd_data, (size_t)snd_data_len, &addr, + (uint8_t **)rsp_mad, rcv_buf_len, port->ms_timeout, port->retry_count); + + if (fstatus != FSUCCESS) { + if (fstatus == FPROTECTION) { + // PKEY lookup error. + OMGT_OUTPUT_ERROR(port, "Query Failed: requires full management node.\n"); + } else { + OMGT_DBGPRINT(port, "Query Failed: %u.\n", (unsigned int)fstatus); + port->pa_service_state = OMGT_SERVICE_STATE_DOWN; + } + goto done; + } + + if (*rcv_buf_len < PA_REQ_HEADER_SIZE) { + OMGT_DBGPRINT(port, "Query PA: Failed to receive packet\n"); + fstatus = FNOT_FOUND; + goto done; + } + + rcv_mad = *rsp_mad; + BSWAP_MAD_HEADER((MAD *)&rcv_mad->common); + BSWAP_SA_HDR(&rcv_mad->SaHdr); + MAD_GET_STATUS(rcv_mad, &madStatus); + + // dump of PA header for debug + OMGT_DBGPRINT(port, " PA Header\n"); + OMGT_DBGPRINT(port, " length %zu (0x%zx) vs Header length %d\n", + *rcv_buf_len, *rcv_buf_len, (int)PA_REQ_HEADER_SIZE); + //OMGT_DBGPRINT(port, " SmKey (0x%016"PRIx64")\n", rcv_mad->SaHdr.SmKey); + OMGT_DBGPRINT(port, " AttributeOffset %u (0x%x) : in bytes: %u\n", + rcv_mad->SaHdr.AttributeOffset, rcv_mad->SaHdr.AttributeOffset, + (rcv_mad->SaHdr.AttributeOffset * 8)); + OMGT_DBGPRINT(port, " Reserved (0x%x)\n", rcv_mad->SaHdr.Reserved); + //OMGT_DBGPRINT(port, " ComponetMask (0x%016"PRIx64")\n", rcv_mad->SaHdr.ComponentMask); + + rec_sz = rcv_mad->SaHdr.AttributeOffset * 8; + if (rcv_mad->common.mr.AsReg8 == STL_PA_CMD_GET_RESP) { + /* Attribute Offset is 0 on GetResp() as there is only one record */ + rec_sz = *rcv_buf_len - PA_REQ_HEADER_SIZE; + rec_cnt = 1; + } else if (rcv_mad->SaHdr.AttributeOffset) { + rec_cnt = (int)((*rcv_buf_len - PA_REQ_HEADER_SIZE) / + (rcv_mad->SaHdr.AttributeOffset * 8)); + } else { + rec_cnt = 0; + } + OMGT_DBGPRINT(port, "Record count is %d\n", rec_cnt); + + // If the command was not successful (mad status is not 0) + // Change overall return status to failed. + // Fill in the result pointer so the caller can evaluate the return mad status. + port->pa_mad_status = madStatus.AsReg16; + if (madStatus.AsReg16 != 0) { + OMGT_DBGPRINT(port, "Query PA failed: Mad status is 0x%x: %s\n", + madStatus.AsReg16, iba_pa_mad_status_msg(port)); + + switch (madStatus.AsReg16) { + case STL_MAD_STATUS_STL_PA_NO_GROUP: + case STL_MAD_STATUS_STL_PA_NO_PORT: + case STL_MAD_STATUS_STL_PA_NO_VF: + case STL_MAD_STATUS_STL_PA_NO_IMAGE: + case STL_MAD_STATUS_STL_PA_NO_DATA: + fstatus = FNOT_FOUND; + break; + case STL_MAD_STATUS_STL_PA_INVALID_PARAMETER: + fstatus = FINVALID_PARAMETER; + break; + case STL_MAD_STATUS_STL_PA_UNAVAILABLE: + fstatus = FINVALID_STATE; + break; + case STL_MAD_STATUS_STL_PA_BAD_DATA: + default: + fstatus = FERROR; + break; + } + } + + mem_size = rec_sz * rec_cnt; + mem_size += sizeof(uint32_t); + mem_size += sizeof(QUERY_RESULT_VALUES); + + // resultDataSize should be 0 when status is not successful and no data is returned + *query_result = MemoryAllocate2AndClear(mem_size, IBA_MEM_FLAG_PREMPTABLE, OMGT_MEMORY_TAG); + if (*query_result == NULL) { + OMGT_OUTPUT_ERROR(port, "error allocating query result buffer\n"); + fstatus = FINSUFFICIENT_MEMORY; + goto done; + } + (*query_result)->Status = fstatus; + (*query_result)->MadStatus = port->pa_mad_status; + (*query_result)->ResultDataSize = rec_sz * rec_cnt; + *((uint32_t *)((*query_result)->QueryResult)) = rec_cnt; + +done: + if (fstatus != FSUCCESS) { + if (*rsp_mad != NULL) { + free(*rsp_mad); + *rsp_mad = NULL; + } + } + + DBG_EXIT_FUNC(port); + return (fstatus); +} // End of pa_query_common() + +const char* +iba_pa_query_input_type_msg( + QUERY_INPUT_TYPE code + ) +{ + if (code < 0 || code >= (int)(sizeof(pa_query_input_type_text)/sizeof(char*))) + return "Unknown PA Query Input Type"; + else + return pa_query_input_type_text[code]; +} + +const char* +iba_pa_query_result_type_msg( + QUERY_RESULT_TYPE code + ) +{ + if (code < 0 || code >= (int)(sizeof(pa_query_result_type_text)/sizeof(char*))) + return "Unknown PA Query Result Type"; + else + return pa_query_result_type_text[code]; +} + + +/******************************************************* + * Public functions + *******************************************************/ +/** + * Enable debugging output in the opamgt library. + * + * @param port The local port to operate on. + * + * @return + * None + */ +void +set_opapaquery_debug ( + IN struct omgt_port *port + ) +{ + port->pa_verbose = 1; + + // Should we pass along the debug info + //_openib_debug_ = 1; // enable general debugging + + return; +} + +/** + * Get the classportinfo from the given port. + * + * @param port Local port to operate on. + * + * @return + * Valid pointer - A pointer to the ClassPortInfo. The caller must free it after use. + * NULL - Error. + */ +OMGT_STATUS_T +omgt_pa_get_classportinfo( + IN struct omgt_port *port, + STL_CLASS_PORT_INFO **cpi + ) +{ + FSTATUS fstatus = FSUCCESS; + QUERY_RESULT_VALUES *query_result = NULL; + STL_CLASS_PORT_INFO *response = NULL; + SA_MAD *rsp_mad = NULL; + size_t rcv_buf_len = 0; + uint8_t request_data[PA_REQ_HEADER_SIZE] = {0}; + + DBG_ENTER_FUNC(port); + // Check the incoming port parameter + if (port == NULL) return FERROR; + + // submit request + fstatus = pa_query_common(port, STL_PA_CMD_GET, STL_PA_ATTRID_GET_CLASSPORTINFO, 0, + request_data, sizeof(request_data), &rcv_buf_len, &rsp_mad, &query_result); + if (fstatus != FSUCCESS) { + if (port->pa_verbose) + OMGT_OUTPUT_ERROR(port, "Error, requeset failed: status=%u\n", (unsigned int)fstatus); + goto done; + } else if (rsp_mad->SaHdr.AttributeOffset) { + if (port->pa_verbose) + OMGT_OUTPUT_ERROR(port, "Error, unexpected multiple MAD response\n"); + fstatus = FERROR; + goto done; + } else { + if (port->pa_verbose) { + OMGT_DBGPRINT(port, "Completed request: OK\n"); + } + } + + response = MemoryAllocate2AndClear(sizeof(STL_CLASS_PORT_INFO), IBA_MEM_FLAG_PREMPTABLE, OMGT_MEMORY_TAG); + if (response == NULL) { + OMGT_OUTPUT_ERROR(port, "error allocating response buffer\n"); + fstatus = FINSUFFICIENT_RESOURCES; + goto done; + } + memcpy((uint8 *)response, rsp_mad->Data, min(sizeof(STL_CLASS_PORT_INFO), rcv_buf_len - IB_SA_DATA_OFFS)); + + // translate the data. + BSWAP_STL_CLASS_PORT_INFO(response); +done: + omgt_free_query_result_buffer(query_result); + if (rsp_mad) + free(rsp_mad); + *cpi = response; + DBG_EXIT_FUNC(port); + return fstatus; + +} // End of omgt_pa_get_classportinfo() + +/** + * Get port statistics (counters) + * + * @param port Local port to operate on. + * @param node_lid Remote node LID. + * @param port_num Remote port number. + * @param port_counters Pointer to port counters to fill. + * @param delta_flag 1 for delta counters, 0 for raw image counters. + * @param user_ctrs_flag 1 for running counters, 0 for image counters. (delta must be 0) + * @param image_id Pointer to image ID of port counters to get. + * + * @return + * Valid Pointer - A pointer to the memory for the counters data. The caller must free it. + * NULL - Error + */ +STL_PORT_COUNTERS_DATA * +iba_pa_single_mad_port_counters_response_query( + IN struct omgt_port *port, + IN STL_LID node_lid, + IN uint8_t port_number, + IN uint32_t delta_flag, + IN uint32_t user_cntrs_flag, + IN STL_PA_IMAGE_ID_DATA *image_id + ) +{ + FSTATUS fstatus = FSUCCESS; + QUERY_RESULT_VALUES *query_result = NULL; + STL_PORT_COUNTERS_DATA *response = NULL, *p; + SA_MAD *rsp_mad = NULL; + size_t rcv_buf_len = 0; + uint8_t request_data[PA_REQ_HEADER_SIZE + sizeof(STL_PORT_COUNTERS_DATA)] = {0}; + + DBG_ENTER_FUNC(port); + // Check the incoming port parameter + if (port == NULL) return response; + + // Build Request + p = (STL_PORT_COUNTERS_DATA *)(((SA_MAD *)request_data)->Data); + p->nodeLid = node_lid; + p->portNumber = port_number; + p->flags = (delta_flag ? STL_PA_PC_FLAG_DELTA : 0) | + (user_cntrs_flag ? STL_PA_PC_FLAG_USER_COUNTERS : 0); + + p->imageId.imageNumber = image_id->imageNumber; + p->imageId.imageOffset = image_id->imageOffset; + p->imageId.imageTime.absoluteTime = image_id->imageTime.absoluteTime; + memset(p->reserved, 0, sizeof(p->reserved)); + memset(p->reserved2, 0, sizeof(p->reserved2)); + p->lq.s.reserved = 0; + BSWAP_STL_PA_PORT_COUNTERS(p); + + // submit request + fstatus = pa_query_common(port, STL_PA_CMD_GET, STL_PA_ATTRID_GET_PORT_CTRS, 0, + request_data, sizeof(request_data), &rcv_buf_len, &rsp_mad, &query_result); + if (fstatus != FSUCCESS) { + if (port->pa_verbose) + OMGT_OUTPUT_ERROR(port, "Error, requeset failed: status=%u\n", (unsigned int)fstatus); + goto done; + } else if (rsp_mad->SaHdr.AttributeOffset) { + if (port->pa_verbose) + OMGT_OUTPUT_ERROR(port, "Error, unexpected multiple MAD response\n"); + goto done; + } else { + if (port->pa_verbose) { + OMGT_DBGPRINT(port, "Completed request: OK\n"); + } + } + + response = MemoryAllocate2AndClear(sizeof(STL_PORT_COUNTERS_DATA), IBA_MEM_FLAG_PREMPTABLE, OMGT_MEMORY_TAG); + if (response == NULL) { + OMGT_OUTPUT_ERROR(port, "error allocating response buffer\n"); + goto done; + } + memcpy((uint8 *)response, rsp_mad->Data, min(sizeof(STL_PORT_COUNTERS_DATA), rcv_buf_len - IB_SA_DATA_OFFS)); + + // translate the data. + BSWAP_STL_PA_PORT_COUNTERS(response); +done: + omgt_free_query_result_buffer(query_result); + if (rsp_mad) + free(rsp_mad); + + DBG_EXIT_FUNC(port); + return response; +} + + +/** + * Clear port statistics (counters) + * + * @param port Local Port to operate on. + * @param node_lid Remote node LID. + * @param port_num Remote port number. + * @param select Port's counters to clear. + * + * @return + * Valid Pointer - A pointer to the memory for the clear port counters data (containing the + * info as which counters have been cleared). The caller must free it. + * NULL - Error + */ +STL_CLR_PORT_COUNTERS_DATA * +iba_pa_single_mad_clr_port_counters_response_query( + IN struct omgt_port *port, + IN uint32_t node_lid, + IN uint8_t port_number, + IN uint32_t select + ) +{ + FSTATUS fstatus = FSUCCESS; + QUERY_RESULT_VALUES *query_result = NULL; + STL_CLR_PORT_COUNTERS_DATA *response = NULL, *p; + SA_MAD *rsp_mad = NULL; + size_t rcv_buf_len = 0; + uint8_t request_data[PA_REQ_HEADER_SIZE + sizeof(STL_CLR_PORT_COUNTERS_DATA)] = {0}; + + DBG_ENTER_FUNC(port); + // Check the incoming port parameter + if (port == NULL) return response; + + p = (STL_CLR_PORT_COUNTERS_DATA *)(((SA_MAD *)request_data)->Data); + p->NodeLid = node_lid; + p->PortNumber = port_number; + p->CounterSelectMask.AsReg32 = select; + p->CounterSelectMask.s.Reserved = 0; + memset(p->Reserved, 0, sizeof(p->Reserved)); + BSWAP_STL_PA_CLR_PORT_COUNTERS(p); + + // submit request + fstatus = pa_query_common(port, STL_PA_CMD_SET, STL_PA_ATTRID_CLR_PORT_CTRS, 0, + request_data, sizeof(request_data), &rcv_buf_len, &rsp_mad, &query_result); + if (fstatus != FSUCCESS) { + if (port->pa_verbose) + OMGT_OUTPUT_ERROR(port, "Error, requeset failed: status=%u\n", (unsigned int)fstatus); + goto done; + } else if (rsp_mad->SaHdr.AttributeOffset) { + if (port->pa_verbose) + OMGT_OUTPUT_ERROR(port, "Error, unexpected multiple MAD response\n"); + goto done; + } else { + if (port->pa_verbose) { + OMGT_DBGPRINT(port, "Completed request: OK\n"); + } + } + + response = MemoryAllocate2AndClear(sizeof(STL_CLR_PORT_COUNTERS_DATA), IBA_MEM_FLAG_PREMPTABLE, OMGT_MEMORY_TAG); + if (response == NULL) { + OMGT_OUTPUT_ERROR(port, "error allocating response buffer\n"); + goto done; + } + memcpy((uint8 *)response, rsp_mad->Data, min(sizeof(STL_CLR_PORT_COUNTERS_DATA), rcv_buf_len - IB_SA_DATA_OFFS)); + + // translate the data. + BSWAP_STL_PA_CLR_PORT_COUNTERS(response); +done: + omgt_free_query_result_buffer(query_result); + if (rsp_mad) + free(rsp_mad); + + DBG_EXIT_FUNC(port); + return response; +} + +/** + * Clear all ports, statistics (counters) + * + * @param port Local port to operate on. + * @param select Port's counters to clear. + * + * @return + * Valid Pointer - A pointer to the memory for the clear all port counters data (containing the + * info as which counters have been cleared). The caller must free it. + * NULL - Error + */ +STL_CLR_ALL_PORT_COUNTERS_DATA * +iba_pa_single_mad_clr_all_port_counters_response_query( + IN struct omgt_port *port, + IN uint32_t select + ) +{ + FSTATUS fstatus = FSUCCESS; + QUERY_RESULT_VALUES *query_result = NULL; + STL_CLR_ALL_PORT_COUNTERS_DATA *response = NULL, *p; + SA_MAD *rsp_mad = NULL; + size_t rcv_buf_len = 0; + uint8_t request_data[PA_REQ_HEADER_SIZE + sizeof(STL_CLR_ALL_PORT_COUNTERS_DATA)] = {0}; + + DBG_ENTER_FUNC(port); + // Check the incoming port parameter + if (port == NULL) return response; + + p = (STL_CLR_ALL_PORT_COUNTERS_DATA *)(((SA_MAD *)request_data)->Data); + p->CounterSelectMask.AsReg32 = select; + p->CounterSelectMask.s.Reserved = 0; + BSWAP_STL_PA_CLR_ALL_PORT_COUNTERS(p); + + // submit request + fstatus = pa_query_common(port, STL_PA_CMD_SET, STL_PA_ATTRID_CLR_ALL_PORT_CTRS, 0, + request_data, sizeof(request_data), &rcv_buf_len, &rsp_mad, &query_result); + if (fstatus != FSUCCESS) { + if (port->pa_verbose) + OMGT_OUTPUT_ERROR(port, "Error, requeset failed: status=%u\n", (unsigned int)fstatus); + goto done; + } else if (rsp_mad->SaHdr.AttributeOffset) { + if (port->pa_verbose) + OMGT_OUTPUT_ERROR(port, "Error, unexpected multiple MAD response\n"); + goto done; + } else { + if (port->pa_verbose) { + OMGT_DBGPRINT(port, "Completed request: OK\n"); + } + } + + response = MemoryAllocate2AndClear(sizeof(STL_CLR_ALL_PORT_COUNTERS_DATA), IBA_MEM_FLAG_PREMPTABLE, OMGT_MEMORY_TAG); + if (response == NULL) { + OMGT_OUTPUT_ERROR(port, "error allocating response buffer\n"); + goto done; + } + memcpy((uint8 *)response, rsp_mad->Data, min(sizeof(STL_CLR_ALL_PORT_COUNTERS_DATA), rcv_buf_len - IB_SA_DATA_OFFS)); + + // translate the data. + BSWAP_STL_PA_CLR_ALL_PORT_COUNTERS(response); +done: + omgt_free_query_result_buffer(query_result); + if (rsp_mad) + free(rsp_mad); + + DBG_EXIT_FUNC(port); + return response; +} + +/** + * Get the PM config data. + * + * @param port Local port to operate on. + * + * @return + * Valid Pointer - A pointer to the memory for pm config data. The caller must free it. + * NULL - Error + */ +STL_PA_PM_CFG_DATA * +iba_pa_single_mad_get_pm_config_response_query( + IN struct omgt_port *port + ) +{ + FSTATUS fstatus = FSUCCESS; + QUERY_RESULT_VALUES *query_result = NULL; + STL_PA_PM_CFG_DATA *response = NULL; + SA_MAD *rsp_mad = NULL; + size_t rcv_buf_len = 0; + uint8_t request_data[PA_REQ_HEADER_SIZE + sizeof(STL_PA_PM_CFG_DATA)] = {0}; + + DBG_ENTER_FUNC(port); + // Check the incoming port parameter + if (port == NULL) return response; + + // submit request + fstatus = pa_query_common(port, STL_PA_CMD_GET, STL_PA_ATTRID_GET_PM_CONFIG, 0, + request_data, sizeof(request_data), &rcv_buf_len, &rsp_mad, &query_result); + if (fstatus != FSUCCESS) { + if (port->pa_verbose) + OMGT_OUTPUT_ERROR(port, "Error, requeset failed: status=%u\n", (unsigned int)fstatus); + goto done; + } else if (rsp_mad->SaHdr.AttributeOffset) { + if (port->pa_verbose) + OMGT_OUTPUT_ERROR(port, "Error, unexpected multiple MAD response\n"); + goto done; + } else { + if (port->pa_verbose) { + OMGT_DBGPRINT(port, "Completed request: OK\n"); + } + } + + response = MemoryAllocate2AndClear(sizeof(STL_PA_PM_CFG_DATA), IBA_MEM_FLAG_PREMPTABLE, OMGT_MEMORY_TAG); + if (response == NULL) { + OMGT_OUTPUT_ERROR(port, "error allocating response buffer\n"); + goto done; + } + memcpy((uint8 *)response, rsp_mad->Data, min(sizeof(STL_PA_PM_CFG_DATA), rcv_buf_len - IB_SA_DATA_OFFS)); + + // translate the data. + BSWAP_STL_PA_PM_CFG(response); +done: + omgt_free_query_result_buffer(query_result); + if (rsp_mad) + free(rsp_mad); + + DBG_EXIT_FUNC(port); + return response; +} + +/** + * Free a sweep image. + * + * @param port Local port to operate on. + * @param image_id ID of image to freeze. + * + * @return + * Valid Pointer - A pointer to the memory for the frozen image id data. The caller must free it. + * NULL - Error + */ +STL_PA_IMAGE_ID_DATA * +iba_pa_single_mad_freeze_image_response_query( + IN struct omgt_port *port, + IN STL_PA_IMAGE_ID_DATA *image_id + ) +{ + FSTATUS fstatus = FSUCCESS; + QUERY_RESULT_VALUES *query_result = NULL; + STL_PA_IMAGE_ID_DATA *response = NULL, *p; + SA_MAD *rsp_mad = NULL; + size_t rcv_buf_len = 0; + uint8_t request_data[PA_REQ_HEADER_SIZE + sizeof(STL_PA_IMAGE_ID_DATA)] = {0}; + + DBG_ENTER_FUNC(port); + // Check the incoming port parameter + if (port == NULL) return response; + + p = (STL_PA_IMAGE_ID_DATA *)(((SA_MAD *)request_data)->Data); + p->imageNumber = hton64(image_id->imageNumber); + p->imageOffset = hton32(image_id->imageOffset); + p->imageTime.absoluteTime = hton32(image_id->imageTime.absoluteTime); + + // submit request + fstatus = pa_query_common(port, STL_PA_CMD_SET, STL_PA_ATTRID_FREEZE_IMAGE, 0, + request_data, sizeof(request_data), &rcv_buf_len, &rsp_mad, &query_result); + if (fstatus != FSUCCESS) { + if (port->pa_verbose) + OMGT_OUTPUT_ERROR(port, "Error, requeset failed: status=%u\n", (unsigned int)fstatus); + goto done; + } else if (rsp_mad->SaHdr.AttributeOffset) { + if (port->pa_verbose) + OMGT_OUTPUT_ERROR(port, "Error, unexpected multiple MAD response\n"); + goto done; + } else { + if (port->pa_verbose) { + OMGT_DBGPRINT(port, "Completed request: OK\n"); + } + } + + response = MemoryAllocate2AndClear(sizeof(STL_PA_IMAGE_ID_DATA), IBA_MEM_FLAG_PREMPTABLE, OMGT_MEMORY_TAG); + if (response == NULL) { + OMGT_OUTPUT_ERROR(port, "error allocating response buffer\n"); + goto done; + } + memcpy((uint8 *)response, rsp_mad->Data, min(sizeof(STL_PA_IMAGE_ID_DATA), rcv_buf_len - IB_SA_DATA_OFFS)); + + // translate the data. + BSWAP_STL_PA_IMAGE_ID(response); +done: + omgt_free_query_result_buffer(query_result); + if (rsp_mad) + free(rsp_mad); + + DBG_EXIT_FUNC(port); + return response; +} + +/** + * Release a sweep image. + * + * @param port Local port to operate on. + * @param image_id Ponter to id of image to release. + * + * @return + * Valid Pointer - A pointer to the memory for the released image id data. The caller must free it. + * NULL - Error + */ +STL_PA_IMAGE_ID_DATA * +iba_pa_single_mad_release_image_response_query( + IN struct omgt_port *port, + IN STL_PA_IMAGE_ID_DATA *image_id + ) +{ + FSTATUS fstatus = FSUCCESS; + QUERY_RESULT_VALUES *query_result = NULL; + STL_PA_IMAGE_ID_DATA *response = NULL, *p; + SA_MAD *rsp_mad = NULL; + size_t rcv_buf_len = 0; + uint8_t request_data[PA_REQ_HEADER_SIZE + sizeof(STL_PA_IMAGE_ID_DATA)] = {0}; + + DBG_ENTER_FUNC(port); + // Check the incoming port parameter + if (port == NULL) return response; + + p = (STL_PA_IMAGE_ID_DATA *)(((SA_MAD *)request_data)->Data); + p->imageNumber = hton64(image_id->imageNumber); + p->imageOffset = hton32(image_id->imageOffset); + p->imageTime.absoluteTime = hton32(image_id->imageTime.absoluteTime); + + // submit request + fstatus = pa_query_common(port, STL_PA_CMD_SET, STL_PA_ATTRID_RELEASE_IMAGE, 0, + request_data, sizeof(request_data), &rcv_buf_len, &rsp_mad, &query_result); + if (fstatus != FSUCCESS) { + if (port->pa_verbose) + OMGT_OUTPUT_ERROR(port, "Error, requeset failed: status=%u\n", (unsigned int)fstatus); + goto done; + } else if (rsp_mad->SaHdr.AttributeOffset) { + if (port->pa_verbose) + OMGT_OUTPUT_ERROR(port, "Error, unexpected multiple MAD response\n"); + goto done; + } else { + if (port->pa_verbose) { + OMGT_DBGPRINT(port, "Completed request: OK\n"); + } + } + + response = MemoryAllocate2AndClear(sizeof(STL_PA_IMAGE_ID_DATA), IBA_MEM_FLAG_PREMPTABLE, OMGT_MEMORY_TAG); + if (response == NULL) { + OMGT_OUTPUT_ERROR(port, "error allocating response buffer\n"); + goto done; + } + memcpy((uint8 *)response, rsp_mad->Data, min(sizeof(STL_PA_IMAGE_ID_DATA), rcv_buf_len - IB_SA_DATA_OFFS)); + + // translate the data. + BSWAP_STL_PA_IMAGE_ID(response); +done: + omgt_free_query_result_buffer(query_result); + if (rsp_mad) + free(rsp_mad); + + DBG_EXIT_FUNC(port); + return response; +} + +/** + * Renew a sweep image. + * + * @param port Local port to operate on. + * @param image_id Ponter to id of image to renew. + * + * @return + * Valid Pointer - A pointer to the memory for the renewed image id data. The caller must free it. + * NULL - Error + */ +STL_PA_IMAGE_ID_DATA * +iba_pa_single_mad_renew_image_response_query( + IN struct omgt_port *port, + IN STL_PA_IMAGE_ID_DATA *image_id + ) +{ + FSTATUS fstatus = FSUCCESS; + QUERY_RESULT_VALUES *query_result = NULL; + STL_PA_IMAGE_ID_DATA *response = NULL, *p; + SA_MAD *rsp_mad = NULL; + size_t rcv_buf_len = 0; + uint8_t request_data[PA_REQ_HEADER_SIZE + sizeof(STL_PA_IMAGE_ID_DATA)] = {0}; + + DBG_ENTER_FUNC(port); + // Check the incoming port parameter + if (port == NULL) return response; + + p = (STL_PA_IMAGE_ID_DATA *)(((SA_MAD *)request_data)->Data); + p->imageNumber = hton64(image_id->imageNumber); + p->imageOffset = hton32(image_id->imageOffset); + p->imageTime.absoluteTime = hton32(image_id->imageTime.absoluteTime); + + // submit request + fstatus = pa_query_common(port, STL_PA_CMD_SET, STL_PA_ATTRID_RENEW_IMAGE, 0, + request_data, sizeof(request_data), &rcv_buf_len, &rsp_mad, &query_result); + if (fstatus != FSUCCESS) { + if (port->pa_verbose) + OMGT_OUTPUT_ERROR(port, "Error, requeset failed: status=%u\n", (unsigned int)fstatus); + goto done; + } else if (rsp_mad->SaHdr.AttributeOffset) { + if (port->pa_verbose) + OMGT_OUTPUT_ERROR(port, "Error, unexpected multiple MAD response\n"); + goto done; + } else { + if (port->pa_verbose) { + OMGT_DBGPRINT(port, "Completed request: OK\n"); + } + } + + response = MemoryAllocate2AndClear(sizeof(STL_PA_IMAGE_ID_DATA), IBA_MEM_FLAG_PREMPTABLE, OMGT_MEMORY_TAG); + if (response == NULL) { + OMGT_OUTPUT_ERROR(port, "error allocating response buffer\n"); + goto done; + } + memcpy((uint8 *)response, rsp_mad->Data, min(sizeof(STL_PA_IMAGE_ID_DATA), rcv_buf_len - IB_SA_DATA_OFFS)); + + // translate the data. + BSWAP_STL_PA_IMAGE_ID(response); +done: + omgt_free_query_result_buffer(query_result); + if (rsp_mad) + free(rsp_mad); + + DBG_EXIT_FUNC(port); + return response; +} + +/** + * Move a frozen image 1 to image 2. + * + * @param port Local port to operate on. + * @param move_info Ponter to move info (src and dest image ID). + * + * @return + * Valid Pointer - A pointer to the memory for the image move info. The caller must free it. + * NULL - Error + */ +STL_MOVE_FREEZE_DATA * +iba_pa_single_mad_move_freeze_response_query( + IN struct omgt_port *port, + IN STL_MOVE_FREEZE_DATA *move_info + ) +{ + FSTATUS fstatus = FSUCCESS; + QUERY_RESULT_VALUES *query_result = NULL; + STL_MOVE_FREEZE_DATA *response = NULL, *p; + SA_MAD *rsp_mad = NULL; + size_t rcv_buf_len = 0; + uint8_t request_data[PA_REQ_HEADER_SIZE + sizeof(STL_MOVE_FREEZE_DATA)] = {0}; + + DBG_ENTER_FUNC(port); + // Check the incoming port parameter + if (port == NULL) return response; + + p = (STL_MOVE_FREEZE_DATA *)(((SA_MAD *)request_data)->Data); + *p = *move_info; + BSWAP_STL_PA_MOVE_FREEZE(p); + + // submit request + fstatus = pa_query_common(port, STL_PA_CMD_SET, STL_PA_ATTRID_MOVE_FREEZE_FRAME, 0, + request_data, sizeof(request_data), &rcv_buf_len, &rsp_mad, &query_result); + if (fstatus != FSUCCESS) { + if (port->pa_verbose) + OMGT_OUTPUT_ERROR(port, "Error, requeset failed: status=%u\n", (unsigned int)fstatus); + goto done; + } else if (rsp_mad->SaHdr.AttributeOffset) { + if (port->pa_verbose) + OMGT_OUTPUT_ERROR(port, "Error, unexpected multiple MAD response\n"); + goto done; + } else { + if (port->pa_verbose) { + OMGT_DBGPRINT(port, "Completed request: OK\n"); + } + } + + response = MemoryAllocate2AndClear(sizeof(STL_MOVE_FREEZE_DATA), IBA_MEM_FLAG_PREMPTABLE, OMGT_MEMORY_TAG); + if (response == NULL) { + OMGT_OUTPUT_ERROR(port, "error allocating response buffer\n"); + goto done; + } + memcpy((uint8 *)response, rsp_mad->Data, min(sizeof(STL_MOVE_FREEZE_DATA), rcv_buf_len - IB_SA_DATA_OFFS)); + + // translate the data. + BSWAP_STL_PA_MOVE_FREEZE(response); +done: + omgt_free_query_result_buffer(query_result); + if (rsp_mad) + free(rsp_mad); + + DBG_EXIT_FUNC(port); + return response; +} + +/** + * Get image info + * + * @param port Local port to operate on. + * @param image_info Ponter to image info (containing valid image ID). + * + * @return + * Valid Pointer - A pointer to the memory for the image info data. The caller must free it. + * NULL - Error + */ +STL_PA_IMAGE_INFO_DATA * +iba_pa_multi_mad_get_image_info_response_query ( + IN struct omgt_port *port, + IN STL_PA_IMAGE_INFO_DATA *image_info + ) +{ + FSTATUS fstatus = FSUCCESS; + QUERY_RESULT_VALUES *query_result = NULL; + STL_PA_IMAGE_INFO_DATA *response = NULL, *p; + SA_MAD *rsp_mad = NULL; + size_t rcv_buf_len = 0; + uint8_t request_data[PA_REQ_HEADER_SIZE + sizeof(STL_PA_IMAGE_INFO_DATA)] = {0}; + + DBG_ENTER_FUNC(port); + // Check the incoming port parameter + if (port == NULL) return response; + + p = (STL_PA_IMAGE_INFO_DATA *)(((SA_MAD *)request_data)->Data); + p->imageId.imageNumber = hton64(image_info->imageId.imageNumber); + p->imageId.imageOffset = hton32(image_info->imageId.imageOffset); + p->imageId.imageTime.absoluteTime = hton32(image_info->imageId.imageTime.absoluteTime); + p->reserved = 0; + + // submit request + fstatus = pa_query_common(port, STL_PA_CMD_GETTABLE, STL_PA_ATTRID_GET_IMAGE_INFO, 0, + request_data, sizeof(request_data), &rcv_buf_len, &rsp_mad, &query_result); + if (fstatus != FSUCCESS) { + if (port->pa_verbose) + OMGT_OUTPUT_ERROR(port, "Error, requeset failed: status=%u\n", (unsigned int)fstatus); + goto done; + } else { + if (port->pa_verbose) { + OMGT_DBGPRINT(port, "Completed request: OK\n"); + } + } + + response = MemoryAllocate2AndClear(sizeof(STL_PA_IMAGE_INFO_DATA), IBA_MEM_FLAG_PREMPTABLE, OMGT_MEMORY_TAG); + if (response == NULL) { + OMGT_OUTPUT_ERROR(port, "error allocating response buffer\n"); + goto done; + } + memcpy((uint8 *)response, rsp_mad->Data, min(sizeof(STL_PA_IMAGE_INFO_DATA), rcv_buf_len - IB_SA_DATA_OFFS)); + + // translate the data. + BSWAP_STL_PA_IMAGE_INFO(response); +done: + omgt_free_query_result_buffer(query_result); + if (rsp_mad) + free(rsp_mad); + + DBG_EXIT_FUNC(port); + return response; +} + +/** + * Get multi-record response for pa group data (group list). + * + * @param port Local port to operate on. + * @param query Pointer to the query + * @param pquery_result Pointer to query result to be filled. The caller + * has to free the buffer. + * + * @return + * FSUCCESS - Get successfully + * FERROR - Error + */ +FSTATUS +iba_pa_multi_mad_group_list_response_query( + IN struct omgt_port *port, + IN POMGT_QUERY query, + OUT PQUERY_RESULT_VALUES *pquery_result + ) +{ + FSTATUS fstatus = FSUCCESS; + QUERY_RESULT_VALUES *query_result = NULL; + SA_MAD *rsp_mad = NULL; + size_t rcv_buf_len = 0; + uint8_t request_data[PA_REQ_HEADER_SIZE] = { 0 }; + STL_PA_GROUP_LIST *pa_data; + STL_PA_GROUP_LIST_RESULTS *pa_result; + int i; + + DBG_ENTER_FUNC(port); + // Check the incoming port parameter + if (port == NULL) return FERROR; + + // process the command. + switch (query->OutputType) { + case OutputTypePaTableRecord: + // submit request + fstatus = pa_query_common(port, STL_PA_CMD_GETTABLE, STL_PA_ATTRID_GET_GRP_LIST, 0, + request_data, sizeof(request_data), &rcv_buf_len, &rsp_mad, &query_result); + if (fstatus != FSUCCESS) { + if (port->pa_verbose) + OMGT_OUTPUT_ERROR(port, "Error, requeset failed: status=%u\n", (unsigned int)fstatus); + goto done; + } else { + if (port->pa_verbose) { + OMGT_DBGPRINT(port, "Completed request: OK\n"); + } + } + + // translate the data. + pa_result = (STL_PA_GROUP_LIST_RESULTS *)query_result->QueryResult; + pa_data = pa_result->GroupListRecords; + for (i = 0; i < pa_result->NumGroupListRecords; i++) { + STL_PA_GROUP_LIST *groupname = (STL_PA_GROUP_LIST *)GET_RESULT_OFFSET(rsp_mad, i); + pa_data[i] = *groupname; + } + break; + + default: + OMGT_OUTPUT_ERROR(port, "Query Not supported in OPAMGT: Input=%s, Output=%s\n", + iba_pa_query_input_type_msg(query->InputType), + iba_pa_query_result_type_msg(query->OutputType)); + fstatus = FERROR; + goto done; + break; + } + +done: + if (rsp_mad) + free(rsp_mad); + + *pquery_result = query_result; + + DBG_EXIT_FUNC(port); + return fstatus; +} +FSTATUS +iba_pa_multi_mad_group_list2_response_query( + IN struct omgt_port *port, + IN POMGT_QUERY query, + IN STL_PA_IMAGE_ID_DATA *imageId, + OUT PQUERY_RESULT_VALUES *pquery_result + ) +{ + FSTATUS fstatus = FSUCCESS; + QUERY_RESULT_VALUES *query_result = NULL; + SA_MAD *rsp_mad = NULL; + size_t rcv_buf_len = 0; + uint8_t request_data[PA_REQ_HEADER_SIZE + sizeof(STL_PA_IMAGE_ID_DATA)] = { 0 }; + STL_PA_GROUP_LIST2 *pa_data; + STL_PA_GROUP_LIST2_RESULTS *pa_result; + STL_PA_IMAGE_ID_DATA *p; + int i; + + DBG_ENTER_FUNC(port); + // Check the incoming port parameter + if (port == NULL) return FERROR; + + p = (STL_PA_IMAGE_ID_DATA *)(((SA_MAD *)request_data)->Data); + *p = *imageId; + BSWAP_STL_PA_IMAGE_ID(p); + + // process the command. + switch (query->OutputType) { + case OutputTypePaTableRecord: + // submit request + fstatus = pa_query_common(port, STL_PA_CMD_GETTABLE, STL_PA_ATTRID_GET_GRP_LIST2, 0, + request_data, sizeof(request_data), &rcv_buf_len, &rsp_mad, &query_result); + if (fstatus != FSUCCESS) { + if (port->pa_verbose) + OMGT_OUTPUT_ERROR(port, "Error, requeset failed: status=%u\n", (unsigned int)fstatus); + goto done; + } else { + if (port->pa_verbose) { + OMGT_DBGPRINT(port, "Completed request: OK\n"); + } + } + + // translate the data. + pa_result = (STL_PA_GROUP_LIST2_RESULTS *)query_result->QueryResult; + pa_data = pa_result->GroupList2Records; + for (i = 0; i < pa_result->NumGroupList2Records; i++) { + STL_PA_GROUP_LIST2 *group = (STL_PA_GROUP_LIST2 *)GET_RESULT_OFFSET(rsp_mad, i); + BSWAP_STL_PA_IMAGE_ID(&group->imageId); + pa_data[i] = *group; + } + break; + + default: + OMGT_OUTPUT_ERROR(port, "Query Not supported in OPAMGT: Input=%s, Output=%s\n", + iba_pa_query_input_type_msg(query->InputType), + iba_pa_query_result_type_msg(query->OutputType)); + fstatus = FERROR; + goto done; + break; + } + +done: + if (rsp_mad) + free(rsp_mad); + + *pquery_result = query_result; + + DBG_EXIT_FUNC(port); + return fstatus; +} +/** + * Get multi-record response for pa group info (stats). + * + * @param port Local port to operate on. + * @param query Pointer to the query + * @param group_name Group name + * @param pquery_result Pointer to query result to be filled. The caller has to + * to free the buffer. + * @param image_id Pointer to the image ID. + * + * @return + * FSUCCESS - Get successfully + * FERROR - Error + */ +FSTATUS +iba_pa_multi_mad_group_stats_response_query( + IN struct omgt_port *port, + IN POMGT_QUERY query, + IN char *group_name, + OUT PQUERY_RESULT_VALUES *pquery_result, + IN STL_PA_IMAGE_ID_DATA *image_id + ) +{ + FSTATUS fstatus = FSUCCESS; + QUERY_RESULT_VALUES *query_result = NULL; + SA_MAD *rsp_mad = NULL; + size_t rcv_buf_len = 0; + uint8_t request_data[PA_REQ_HEADER_SIZE + 80] = {0}; // 80 = GroupName + ImageId (Request) + STL_PA_PM_GROUP_INFO_DATA *pa_data, *p; + STL_PA_GROUP_INFO_RESULTS *pa_result; + int i; + + DBG_ENTER_FUNC(port); + // Check the incoming port parameter + if (port == NULL) return FERROR; + + p = (STL_PA_PM_GROUP_INFO_DATA *)(((SA_MAD *)request_data)->Data); + snprintf(p->groupName, sizeof(p->groupName), "%s", group_name); + p->imageId.imageNumber = image_id->imageNumber; + p->imageId.imageOffset = image_id->imageOffset; + p->imageId.imageTime.absoluteTime = image_id->imageTime.absoluteTime; + BSWAP_STL_PA_PM_GROUP_INFO(p, 1); + + // process the command. + switch (query->OutputType) { + case OutputTypePaTableRecord: + // submit request + fstatus = pa_query_common(port, STL_PA_CMD_GETTABLE, STL_PA_ATTRID_GET_GRP_INFO, 0, + request_data, sizeof(request_data), &rcv_buf_len, &rsp_mad, &query_result); + if (fstatus != FSUCCESS){ + if (port->pa_verbose) + OMGT_OUTPUT_ERROR(port, "Error, requeset failed: status=%u\n",(unsigned int)fstatus); + goto done; + } else { + if (port->pa_verbose){ + OMGT_DBGPRINT(port, "Completed request: OK\n"); + } + } + + // translate the data. + pa_result = (STL_PA_GROUP_INFO_RESULTS *)query_result->QueryResult; + pa_data = pa_result->GroupInfoRecords; + for (i = 0; i < pa_result->NumGroupInfoRecords; i++) { + STL_PA_PM_GROUP_INFO_DATA *group = (STL_PA_PM_GROUP_INFO_DATA *)GET_RESULT_OFFSET(rsp_mad, i); + pa_data[i] = *group; + BSWAP_STL_PA_PM_GROUP_INFO(&pa_data[i], 0); + } + break; + + default: + OMGT_OUTPUT_ERROR(port, "Query Not supported in OPAMGT: Input=%s, Output=%s\n", + iba_pa_query_input_type_msg(query->InputType), + iba_pa_query_result_type_msg(query->OutputType)); + fstatus = FERROR; + goto done; + break; + } + +done: + if (rsp_mad) + free(rsp_mad); + + *pquery_result = query_result; + + DBG_EXIT_FUNC(port); + return fstatus; +} + +/** + * Get multi-record response for pa group config. + * + * @param port Local port to operate on. + * @param query Pointer to the query + * @param group_name Group name + * @param pquery_result Pointer to query result to be filled. The caller has + * to free the buffer. + * @param imageID Pointer to the image ID. + * + * @return + * FSUCCESS - Get successfully + * FERROR - Error + */ +FSTATUS +iba_pa_multi_mad_group_config_response_query( + IN struct omgt_port *port, + IN POMGT_QUERY query, + IN char *group_name, + OUT PQUERY_RESULT_VALUES *pquery_result, + IN STL_PA_IMAGE_ID_DATA *image_id + ) +{ + FSTATUS fstatus = FSUCCESS; + QUERY_RESULT_VALUES *query_result = NULL; + SA_MAD *rsp_mad = NULL; + size_t rcv_buf_len = 0; + uint8_t request_data[PA_REQ_HEADER_SIZE + sizeof(STL_PA_PM_GROUP_CFG_REQ)] = {0}; + STL_PA_PM_GROUP_CFG_RSP *pa_data; + STL_PA_PM_GROUP_CFG_REQ *p; + STL_PA_GROUP_CONFIG_RESULTS *pa_result; + int i; + + DBG_ENTER_FUNC(port); + // Check the incoming port parameter + if (port == NULL) return FERROR; + + p = (STL_PA_PM_GROUP_CFG_REQ *)(((SA_MAD *)request_data)->Data); + snprintf(p->groupName, sizeof(p->groupName), "%s", group_name); + + p->imageId.imageNumber = hton64(image_id->imageNumber); + p->imageId.imageOffset = hton32(image_id->imageOffset); + p->imageId.imageTime.absoluteTime = hton32(image_id->imageTime.absoluteTime); + + // process the command. + switch (query->OutputType) { + case OutputTypePaTableRecord: + // submit request + fstatus = pa_query_common(port, STL_PA_CMD_GETTABLE, STL_PA_ATTRID_GET_GRP_CFG, 0, + request_data, sizeof(request_data), &rcv_buf_len, &rsp_mad, &query_result); + if (fstatus != FSUCCESS){ + if (port->pa_verbose) + OMGT_OUTPUT_ERROR(port, "Error, requeset failed: status=%u\n",(unsigned int)fstatus); + goto done; + } else { + if (port->pa_verbose){ + OMGT_DBGPRINT(port, "Completed request: OK\n"); + } + } + + // translate the data. + pa_result = (STL_PA_GROUP_CONFIG_RESULTS *)query_result->QueryResult; + pa_data = pa_result->GroupConfigRecords; + for (i = 0; i < pa_result->NumGroupConfigRecords; i++) { + STL_PA_PM_GROUP_CFG_RSP *group_cfg = (STL_PA_PM_GROUP_CFG_RSP *)GET_RESULT_OFFSET(rsp_mad, i); + pa_data[i] = *group_cfg; + BSWAP_STL_PA_GROUP_CONFIG_RSP(&pa_data[i]); + } + break; + + default: + OMGT_OUTPUT_ERROR(port, "Query Not supported in OPAMGT: Input=%s, Output=%s\n", + iba_pa_query_input_type_msg(query->InputType), + iba_pa_query_result_type_msg(query->OutputType)); + fstatus = FERROR; + goto done; + break; + } + +done: + if (rsp_mad) + free(rsp_mad); + + *pquery_result = query_result; + + DBG_EXIT_FUNC(port); + return fstatus; +} // End of iba_pa_multi_mad_group_config_response_query() + +/** + * Get multi-record response for pa group node Info. + * + * @param port Local port to operate on. + * @param query Pointer to the query + * @param group_name Group name + * @param nodeLid node LID + * @param nodeGuid node GUID + * @param nodeDesc node Description + * @param pquery_result Pointer to query result to be filled. The caller has + * to free the buffer. + * @param imageID Pointer to the image ID. + * + * @return + * FSUCCESS - Get successfully + * FERROR - Error + */ +FSTATUS +iba_pa_multi_mad_group_nodeinfo_response_query( + IN struct omgt_port *port, + IN POMGT_QUERY query, + IN char *group_name, + IN STL_LID nodeLid, + IN uint64 nodeGuid, + IN char *nodeDesc, + OUT PQUERY_RESULT_VALUES *pquery_result, + IN STL_PA_IMAGE_ID_DATA *image_id + ) +{ + FSTATUS fstatus = FSUCCESS; + QUERY_RESULT_VALUES *query_result = NULL; + SA_MAD *rsp_mad = NULL; + size_t rcv_buf_len = 0; + uint8_t request_data[PA_REQ_HEADER_SIZE + sizeof(STL_PA_GROUP_NODEINFO_REQ)] = {0}; + STL_PA_GROUP_NODEINFO_RSP *pa_data; + STL_PA_GROUP_NODEINFO_REQ *p; + STL_PA_GROUP_NODEINFO_RESULTS *pa_result; + int i; + + DBG_ENTER_FUNC(port); + // Check the incoming port parameter + if (port == NULL) return FERROR; + + p = (STL_PA_GROUP_NODEINFO_REQ *)(((SA_MAD *)request_data)->Data); + snprintf(p->groupName, sizeof(p->groupName), "%s", group_name); + p->nodeLID = nodeLid; + p->nodeGUID = nodeGuid; + if(nodeDesc) + snprintf(p->nodeDesc, sizeof(p->nodeDesc), "%s", nodeDesc); + p->imageId.imageNumber = image_id->imageNumber; + p->imageId.imageOffset = image_id->imageOffset; + p->imageId.imageTime.absoluteTime = image_id->imageTime.absoluteTime; + BSWAP_STL_PA_GROUP_NODE_INFO_REQ(p); + + // process the command. + switch (query->OutputType) { + case OutputTypePaTableRecord: + // submit request + fstatus = pa_query_common(port, STL_PA_CMD_GETTABLE, STL_PA_ATTRID_GET_GRP_NODE_INFO, 0, + request_data, sizeof(request_data), &rcv_buf_len, &rsp_mad, &query_result); + if (fstatus != FSUCCESS){ + if (port->pa_verbose) + OMGT_OUTPUT_ERROR(port, "Error, requeset failed: status=%u\n",(unsigned int)fstatus); + goto done; + } else { + if (port->pa_verbose){ + OMGT_DBGPRINT(port, "Completed request: OK\n"); + } + } + + // translate the data. + pa_result = (STL_PA_GROUP_NODEINFO_RESULTS *)query_result->QueryResult; + pa_data = pa_result->GroupNodeInfoRecords; + for (i = 0; i < pa_result->NumGroupNodeInfoRecords; i++) { + STL_PA_GROUP_NODEINFO_RSP *group_node_info = (STL_PA_GROUP_NODEINFO_RSP *)GET_RESULT_OFFSET(rsp_mad, i); + pa_data[i] = *group_node_info; + BSWAP_STL_PA_GROUP_NODE_INFO_RSP(&pa_data[i]); + } + break; + + default: + OMGT_OUTPUT_ERROR(port, "Query Not supported in OPAMGT: Input=%s, Output=%s\n", + iba_pa_query_input_type_msg(query->InputType), + iba_pa_query_result_type_msg(query->OutputType)); + fstatus = FERROR; + goto done; + break; + } + +done: + if (rsp_mad) + free(rsp_mad); + + *pquery_result = query_result; + + DBG_EXIT_FUNC(port); + return fstatus; +} // End of iba_pa_multi_mad_group_nodeinfo_response_query() + +/** + * Get multi-record response for pa group link Info. + * + * @param port Local port to operate on. + * @param query Pointer to the query + * @param group_name Group name + * @param inputLid input LID + * @param inputPort input port + * @param pquery_result Pointer to query result to be filled. The caller has + * to free the buffer. + * @param imageID Pointer to the image ID. + * + * @return + * FSUCCESS - Get successfully + * FERROR - Error + */ +FSTATUS +iba_pa_multi_mad_group_linkinfo_response_query( + IN struct omgt_port *port, + IN POMGT_QUERY query, + IN char *group_name, + IN STL_LID inputLid, + IN uint8 inputPort, + OUT PQUERY_RESULT_VALUES *pquery_result, + IN STL_PA_IMAGE_ID_DATA *image_id + ) +{ + FSTATUS fstatus = FSUCCESS; + QUERY_RESULT_VALUES *query_result = NULL; + SA_MAD *rsp_mad = NULL; + size_t rcv_buf_len = 0; + uint8_t request_data[PA_REQ_HEADER_SIZE + sizeof(STL_PA_GROUP_LINKINFO_REQ)] = {0}; + STL_PA_GROUP_LINKINFO_RSP *pa_data; + STL_PA_GROUP_LINKINFO_REQ *p; + STL_PA_GROUP_LINKINFO_RESULTS *pa_result; + int i; + + DBG_ENTER_FUNC(port); + // Check the incoming port parameter + if (port == NULL) return FERROR; + + p = (STL_PA_GROUP_LINKINFO_REQ *)(((SA_MAD *)request_data)->Data); + snprintf(p->groupName, sizeof(p->groupName), "%s", group_name); + p->lid = inputLid; + p->port = inputPort; + p->imageId.imageNumber = image_id->imageNumber; + p->imageId.imageOffset = image_id->imageOffset; + p->imageId.imageTime.absoluteTime = image_id->imageTime.absoluteTime; + BSWAP_STL_PA_GROUP_LINK_INFO_REQ(p); + + // process the command. + switch (query->OutputType) { + case OutputTypePaTableRecord: + // submit request + fstatus = pa_query_common(port, STL_PA_CMD_GETTABLE, STL_PA_ATTRID_GET_GRP_LINK_INFO, 0, + request_data, sizeof(request_data), &rcv_buf_len, &rsp_mad, &query_result); + if (fstatus != FSUCCESS){ + if (port->pa_verbose) + OMGT_OUTPUT_ERROR(port, "Error, requeset failed: status=%u\n",(unsigned int)fstatus); + goto done; + } else { + if (port->pa_verbose){ + OMGT_DBGPRINT(port, "Completed request: OK\n"); + } + } + + // translate the data. + pa_result = (STL_PA_GROUP_LINKINFO_RESULTS *)query_result->QueryResult; + pa_data = pa_result->GroupLinkInfoRecords; + for (i = 0; i < pa_result->NumGroupLinkInfoRecords; i++) { + STL_PA_GROUP_LINKINFO_RSP *group_link_info = (STL_PA_GROUP_LINKINFO_RSP *)GET_RESULT_OFFSET(rsp_mad, i); + pa_data[i] = *group_link_info; + BSWAP_STL_PA_GROUP_LINK_INFO_RSP(&pa_data[i]); + } + break; + + default: + OMGT_OUTPUT_ERROR(port, "Query Not supported in OPAMGT: Input=%s, Output=%s\n", + iba_pa_query_input_type_msg(query->InputType), + iba_pa_query_result_type_msg(query->OutputType)); + fstatus = FERROR; + goto done; + break; + } + +done: + if (rsp_mad) + free(rsp_mad); + + *pquery_result = query_result; + + DBG_EXIT_FUNC(port); + return fstatus; +} + + +/** + * Get multi-record response for pa group focus portlist. + * + * @param port Local port to operate on. + * @param query Pointer to the query + * @param group_name Group name + * @param select Select value for focus portlist. + * @param start Start index value of portlist + * @param range Index range of portlist. + * @param pquery_result Pointer to query result to be filled. The caller has + * to fill the buffer. + * @param imageID Pointer to the image ID. + * + * @return + * FSUCCESS - Get successfully + * FERROR - Error + */ +FSTATUS +iba_pa_multi_mad_focus_ports_response_query ( + IN struct omgt_port *port, + IN POMGT_QUERY query, + IN char *group_name, + IN uint32 select, + IN uint32 start, + IN uint32 range, + OUT PQUERY_RESULT_VALUES *pquery_result, + IN STL_PA_IMAGE_ID_DATA *image_id + ) +{ + FSTATUS fstatus = FSUCCESS; + QUERY_RESULT_VALUES *query_result = NULL; + SA_MAD *rsp_mad = NULL; + size_t rcv_buf_len = 0; + uint8_t request_data[PA_REQ_HEADER_SIZE + sizeof(STL_FOCUS_PORTS_REQ)] = {0}; + STL_FOCUS_PORTS_RSP *pa_data; + STL_FOCUS_PORTS_REQ *p; + STL_PA_FOCUS_PORTS_RESULTS *pa_result; + int i; + + DBG_ENTER_FUNC(port); + // Check the incoming port parameter + if (port == NULL) return FERROR; + + p = (STL_FOCUS_PORTS_REQ *)(((SA_MAD *)request_data)->Data); + snprintf(p->groupName, sizeof(p->groupName), "%s", group_name); + p->select = hton32(select); + p->start = hton32(start); + p->range = hton32(range); + + p->imageId.imageNumber = hton64(image_id->imageNumber); + p->imageId.imageOffset = hton32(image_id->imageOffset); + p->imageId.imageTime.absoluteTime = hton32(image_id->imageTime.absoluteTime); + + // process the command. + switch (query->OutputType) { + case OutputTypePaTableRecord: + // submit request + fstatus = pa_query_common(port, STL_PA_CMD_GETTABLE, STL_PA_ATTRID_GET_FOCUS_PORTS, 0, + request_data, sizeof(request_data), &rcv_buf_len, &rsp_mad, &query_result); + if (fstatus != FSUCCESS) { + if (port->pa_verbose) + OMGT_OUTPUT_ERROR(port, "Error, requeset failed: status=%u\n", (unsigned int)fstatus); + goto done; + } else { + if (port->pa_verbose) { + OMGT_DBGPRINT(port, "Completed request: OK\n"); + } + } + + // translate the data. + pa_result = (STL_PA_FOCUS_PORTS_RESULTS *)query_result->QueryResult; + pa_data = pa_result->FocusPortsRecords; + for (i = 0; i < pa_result->NumFocusPortsRecords; i++) { + STL_FOCUS_PORTS_RSP *focus_port = (STL_FOCUS_PORTS_RSP *)GET_RESULT_OFFSET(rsp_mad, i); + pa_data[i] = *focus_port; + BSWAP_STL_PA_FOCUS_PORTS_RSP(&pa_data[i]); + } + break; + + default: + OMGT_OUTPUT_ERROR(port, "Query Not supported in OPAMGT: Input=%s, Output=%s\n", + iba_pa_query_input_type_msg(query->InputType), + iba_pa_query_result_type_msg(query->OutputType)); + fstatus = FERROR; + goto done; + break; + } + +done: + if (rsp_mad) + free(rsp_mad); + + *pquery_result = query_result; + + DBG_EXIT_FUNC(port); + return fstatus; +} + + +/** + * Get multi-record response for pa group focus portlist. + * + * @param port Local port to operate on. + * @param query Pointer to the query. + * @param group_name Group name. + * @param select Select value for focus portlist. + * @param start Start index value of portlist. + * @param range Index range of portlist. + * @param pquery_result Pointer to query result to be filled. The caller has + * to fill the buffer. + * @param imageID Pointer to the image ID. + * + * @return + * FSUCCESS - Get successfully + * FERROR - Error + */ +FSTATUS +iba_pa_multi_mad_focus_ports_multiselect_response_query ( + IN struct omgt_port *port, + IN POMGT_QUERY query, + IN char *group_name, + IN uint32 start, + IN uint32 range, + OUT PQUERY_RESULT_VALUES *pquery_result, + IN STL_PA_IMAGE_ID_DATA *image_id, + IN STL_FOCUS_PORT_TUPLE *tuple, + IN uint8 logical_operator + ) +{ + FSTATUS fstatus = FSUCCESS; + QUERY_RESULT_VALUES *query_result = NULL; + SA_MAD *rsp_mad = NULL; + size_t rcv_buf_len = 0; + uint8_t request_data[PA_REQ_HEADER_SIZE + sizeof(STL_FOCUS_PORTS_MULTISELECT_REQ)] = {0}; + STL_FOCUS_PORTS_MULTISELECT_RSP *pa_data; + STL_FOCUS_PORTS_MULTISELECT_REQ *p; + STL_PA_FOCUS_PORTS_MULTISELECT_RESULTS *pa_result; + int i; + + DBG_ENTER_FUNC(port); + // Check the incoming port parameter + if (port == NULL) return FERROR; + + p = (STL_FOCUS_PORTS_MULTISELECT_REQ *)(((SA_MAD *)request_data)->Data); + snprintf(p->groupName, STL_PM_GROUPNAMELEN, "%s", group_name); + p->start = hton32(start); + p->range = hton32(range); + + for (i = 0; i < MAX_NUM_FOCUS_PORT_TUPLES; i++) { + p->tuple[i].select = hton32(tuple[i].select); + p->tuple[i].comparator = tuple[i].comparator; + p->tuple[i].argument = hton64(tuple[i].argument); + } + + p->logical_operator = logical_operator; + + p->imageId.imageNumber = hton64(image_id->imageNumber); + p->imageId.imageOffset = hton32(image_id->imageOffset); + p->imageId.imageTime.absoluteTime = hton32(image_id->imageTime.absoluteTime); + + // process the command. + switch (query->OutputType) { + case OutputTypePaTableRecord: + // submit request + fstatus = pa_query_common(port, STL_PA_CMD_GETTABLE, STL_PA_ATTRID_GET_FOCUS_PORTS_MULTISELECT, 0, + request_data, sizeof(request_data), &rcv_buf_len, &rsp_mad, &query_result); + if (fstatus != FSUCCESS) { + if (port->pa_verbose) + OMGT_OUTPUT_ERROR(port, "Error, requeset failed: status=%u\n", (unsigned int)fstatus); + goto done; + } else { + if (port->pa_verbose) { + OMGT_DBGPRINT(port, "Completed request: OK\n"); + } + } + + // translate the data. + pa_result = (STL_PA_FOCUS_PORTS_MULTISELECT_RESULTS *)query_result->QueryResult; + pa_data = pa_result->FocusPortsRecords; + for (i = 0; i < pa_result->NumFocusPortsRecords; i++) { + STL_FOCUS_PORTS_MULTISELECT_RSP *focus_port = (STL_FOCUS_PORTS_MULTISELECT_RSP *)GET_RESULT_OFFSET(rsp_mad, i); + pa_data[i] = *focus_port; + BSWAP_STL_PA_FOCUS_PORTS_MULTISELECT_RSP(&pa_data[i]); + } + break; + + default: + OMGT_OUTPUT_ERROR(port, "Query Not supported in OPAMGT: Input=%s, Output=%s\n", + iba_pa_query_input_type_msg(query->InputType), + iba_pa_query_result_type_msg(query->OutputType)); + fstatus = FERROR; + goto done; + break; + } + +done: + if (rsp_mad) + free(rsp_mad); + + *pquery_result = query_result; + + DBG_EXIT_FUNC(port); + return fstatus; +} + +/** + * Get multi-record response for pa vf data (vf list). + * + * @param port Local port to operate on. + * @param query Pointer to the query + * @param pquery_result Pointer to query result to be filled. The caller + * has to free the buffer. + * + * @return + * FSUCCESS - Get successfully + * FERROR - Error + */ +FSTATUS +iba_pa_multi_mad_vf_list_response_query( + IN struct omgt_port *port, + IN POMGT_QUERY query, + OUT PQUERY_RESULT_VALUES *pquery_result + ) +{ + FSTATUS fstatus = FSUCCESS; + QUERY_RESULT_VALUES *query_result = NULL; + SA_MAD *rsp_mad = NULL; + size_t rcv_buf_len = 0; + uint8_t request_data[PA_REQ_HEADER_SIZE] = {0}; + STL_PA_VF_LIST *pa_data; + STL_PA_VF_LIST_RESULTS *pa_result; + int i; + + DBG_ENTER_FUNC(port); + // Check the incoming port parameter + if (port == NULL) return FERROR; + + // process the command. + switch (query->OutputType){ + case OutputTypePaTableRecord: + // submit request + fstatus = pa_query_common(port, STL_PA_CMD_GETTABLE, STL_PA_ATTRID_GET_VF_LIST, 0, + request_data, sizeof(request_data), &rcv_buf_len, &rsp_mad, &query_result); + if (fstatus != FSUCCESS){ + if (port->pa_verbose) + OMGT_OUTPUT_ERROR(port, "Error, requeset failed: status=%u\n",(unsigned int)fstatus); + goto done; + } else { + if (port->pa_verbose){ + OMGT_DBGPRINT(port, "Completed request: OK\n"); + } + } + + // translate the data. + pa_result = (STL_PA_VF_LIST_RESULTS *)query_result->QueryResult; + pa_data = pa_result->VFListRecords; + for (i = 0; i < pa_result->NumVFListRecords; i++) { + STL_PA_VF_LIST *vfname = (STL_PA_VF_LIST *)GET_RESULT_OFFSET(rsp_mad, i); + pa_data[i] = *vfname; + } + break; + + default: + OMGT_OUTPUT_ERROR(port, "Query Not supported in OPAMGT: Input=%s, Output=%s\n", + iba_pa_query_input_type_msg(query->InputType), + iba_pa_query_result_type_msg(query->OutputType)); + fstatus = FERROR; + goto done; + break; + } + +done: + if (rsp_mad) + free(rsp_mad); + + *pquery_result = query_result; + + DBG_EXIT_FUNC(port); + return fstatus; +} +FSTATUS +iba_pa_multi_mad_vf_list2_response_query( + IN struct omgt_port *port, + IN POMGT_QUERY query, + IN STL_PA_IMAGE_ID_DATA *imageId, + OUT PQUERY_RESULT_VALUES *pquery_result + ) +{ + FSTATUS fstatus = FSUCCESS; + QUERY_RESULT_VALUES *query_result = NULL; + SA_MAD *rsp_mad = NULL; + size_t rcv_buf_len = 0; + uint8_t request_data[PA_REQ_HEADER_SIZE + sizeof(STL_PA_IMAGE_ID_DATA)] = { 0 }; + STL_PA_VF_LIST2 *pa_data; + STL_PA_VF_LIST2_RESULTS *pa_result; + STL_PA_IMAGE_ID_DATA *p; + + DBG_ENTER_FUNC(port); + // Check the incoming port parameter + if (port == NULL) return FERROR; + + p = (STL_PA_IMAGE_ID_DATA *)(((SA_MAD *)request_data)->Data); + *p = *imageId; + BSWAP_STL_PA_IMAGE_ID(p); + + // process the command. + switch (query->OutputType) { + case OutputTypePaTableRecord: + // submit request + fstatus = pa_query_common(port, STL_PA_CMD_GETTABLE, STL_PA_ATTRID_GET_VF_LIST2, 0, + request_data, sizeof(request_data), &rcv_buf_len, &rsp_mad, &query_result); + if (fstatus != FSUCCESS) { + if (port->pa_verbose) + OMGT_OUTPUT_ERROR(port, "Error, requeset failed: status=%u\n", (unsigned int)fstatus); + goto done; + } else { + if (port->pa_verbose) { + OMGT_DBGPRINT(port, "Completed request: OK\n"); + } + } + + int i; + // translate the data. + pa_result = (STL_PA_VF_LIST2_RESULTS *)query_result->QueryResult; + pa_data = pa_result->VFList2Records; + for (i = 0; i < pa_result->NumVFList2Records; i++) { + STL_PA_VF_LIST2 *vf = (STL_PA_VF_LIST2 *)GET_RESULT_OFFSET(rsp_mad, i); + BSWAP_STL_PA_IMAGE_ID(&vf->imageId); + pa_data[i] = *vf; + } + break; + + default: + OMGT_OUTPUT_ERROR(port, "Query Not supported in OPAMGT: Input=%s, Output=%s\n", + iba_pa_query_input_type_msg(query->InputType), + iba_pa_query_result_type_msg(query->OutputType)); + fstatus = FERROR; + goto done; + break; + } + +done: + if (rsp_mad) + free(rsp_mad); + + *pquery_result = query_result; + + DBG_EXIT_FUNC(port); + return fstatus; +} +/** + * Get multi-record response for pa vf info (stats). + * + * @param port Local port to operate on. + * @param query Pointer to the query + * @param vf_name VF name + * @param pquery_result Pointer to query result to be filled. The caller has to + * to free the buffer. + * @param image_id Pointer to the image ID. + * + * @return + * FSUCCESS - Get successfully + * FERROR - Error + */ +FSTATUS +iba_pa_multi_mad_vf_info_response_query( + IN struct omgt_port *port, + IN POMGT_QUERY query, + IN char *vf_name, + OUT PQUERY_RESULT_VALUES *pquery_result, + IN STL_PA_IMAGE_ID_DATA *image_id + ) +{ + FSTATUS fstatus = FSUCCESS; + QUERY_RESULT_VALUES *query_result = NULL; + SA_MAD *rsp_mad = NULL; + size_t rcv_buf_len = 0; + uint8_t request_data[PA_REQ_HEADER_SIZE + 88] = {0}; //80 = VFName + reserved + ImageID + STL_PA_VF_INFO_DATA *pa_data, *p; + STL_PA_VF_INFO_RESULTS *pa_result; + int i; + + DBG_ENTER_FUNC(port); + // Check the incoming port parameter + if (port == NULL) return FERROR; + + p = (STL_PA_VF_INFO_DATA *)(((SA_MAD *)request_data)->Data); + snprintf(p->vfName, sizeof(p->vfName), "%s", vf_name); + p->imageId.imageNumber = image_id->imageNumber; + p->imageId.imageOffset = image_id->imageOffset; + p->imageId.imageTime.absoluteTime = image_id->imageTime.absoluteTime; + BSWAP_STL_PA_VF_INFO(p, 1); + + // process the command. + switch (query->OutputType) { + case OutputTypePaTableRecord: + // submit request + fstatus = pa_query_common(port, STL_PA_CMD_GETTABLE, STL_PA_ATTRID_GET_VF_INFO, 0, + request_data, sizeof(request_data), &rcv_buf_len, &rsp_mad, &query_result); + if (fstatus != FSUCCESS){ + if (port->pa_verbose) + OMGT_OUTPUT_ERROR(port, "Error, requeset failed: status=%u\n",(unsigned int)fstatus); + goto done; + } else { + if (port->pa_verbose){ + OMGT_DBGPRINT(port, "Completed request: OK\n"); + } + } + + // translate the data. + pa_result = (STL_PA_VF_INFO_RESULTS *)query_result->QueryResult; + pa_data = pa_result->VFInfoRecords; + for (i = 0; i < pa_result->NumVFInfoRecords; i++) { + STL_PA_VF_INFO_DATA *vfinfo = (STL_PA_VF_INFO_DATA *)GET_RESULT_OFFSET(rsp_mad, i); + pa_data[i] = *vfinfo; + BSWAP_STL_PA_VF_INFO(&pa_data[i], 0); + } + break; + + default: + OMGT_OUTPUT_ERROR(port, "Query Not supported in OPAMGT: Input=%s, Output=%s\n", + iba_pa_query_input_type_msg(query->InputType), + iba_pa_query_result_type_msg(query->OutputType)); + fstatus = FERROR; + goto done; + break; + } + +done: + if (rsp_mad) + free(rsp_mad); + + *pquery_result = query_result; + + DBG_EXIT_FUNC(port); + return fstatus; +} + +/** + * Get multi-record response for pa vf config. + * + * @param port Local port to operate on. + * @param query Pointer to the query + * @param vf_name VF Name + * @param pquery_result Pointer to query result to be filled. The + * caller has to free the buffer. + * @param image_id Pointer to the image ID. + * + * @return + * FSUCCESS - Get successfully + * FERROR - Error + */ +FSTATUS +iba_pa_multi_mad_vf_config_response_query( + IN struct omgt_port *port, + IN POMGT_QUERY query, + IN char *vf_name, + OUT PQUERY_RESULT_VALUES *pquery_result, + IN STL_PA_IMAGE_ID_DATA *image_id + ) +{ + FSTATUS fstatus = FSUCCESS; + QUERY_RESULT_VALUES *query_result = NULL; + SA_MAD *rsp_mad = NULL; + size_t rcv_buf_len = 0; + uint8_t request_data[PA_REQ_HEADER_SIZE + sizeof(STL_PA_VF_CFG_REQ)] = {0}; + STL_PA_VF_CFG_RSP *pa_data; + STL_PA_VF_CFG_REQ *p; + STL_PA_VF_CONFIG_RESULTS *pa_result; + int i; + + DBG_ENTER_FUNC(port); + // Check the incoming port parameter + if (port == NULL) return FERROR; + + p = (STL_PA_VF_CFG_REQ *)(((SA_MAD *)request_data)->Data); + snprintf(p->vfName, sizeof(p->vfName), "%s", vf_name); + + p->imageId.imageNumber = hton64(image_id->imageNumber); + p->imageId.imageOffset = hton32(image_id->imageOffset); + p->imageId.imageTime.absoluteTime = hton32(image_id->imageTime.absoluteTime); + + // process the command. + switch (query->OutputType) { + case OutputTypePaTableRecord: + // submit request + fstatus = pa_query_common(port, STL_PA_CMD_GETTABLE, STL_PA_ATTRID_GET_VF_CONFIG, 0, + request_data, sizeof(request_data), &rcv_buf_len, &rsp_mad, &query_result); + if (fstatus != FSUCCESS) { + if (port->pa_verbose) + OMGT_OUTPUT_ERROR(port, "Error, requeset failed: status=%u\n", (unsigned int)fstatus); + goto done; + } else { + if (port->pa_verbose) { + OMGT_DBGPRINT(port, "Completed request: OK\n"); + } + } + + // translate the data. + pa_result = (STL_PA_VF_CONFIG_RESULTS *)query_result->QueryResult; + pa_data = pa_result->VFConfigRecords; + for (i = 0; i < pa_result->NumVFConfigRecords; i++) { + STL_PA_VF_CFG_RSP *vf_cfg = (STL_PA_VF_CFG_RSP *)GET_RESULT_OFFSET(rsp_mad, i); + pa_data[i] = *vf_cfg; + BSWAP_STL_PA_VF_CFG_RSP(&pa_data[i]); + } + break; + + default: + OMGT_OUTPUT_ERROR(port, "Query Not supported in OPAMGT: Input=%s, Output=%s\n", + iba_pa_query_input_type_msg(query->InputType), + iba_pa_query_result_type_msg(query->OutputType)); + fstatus = FERROR; + goto done; + break; + } + +done: + if (rsp_mad) + free(rsp_mad); + + *pquery_result = query_result; + + DBG_EXIT_FUNC(port); + return fstatus; +} + +STL_PA_VF_PORT_COUNTERS_DATA * +iba_pa_single_mad_vf_port_counters_response_query( + IN struct omgt_port *port, + IN STL_LID node_lid, + IN uint8_t port_number, + IN uint32_t delta_flag, + IN uint32_t user_cntrs_flag, + IN char *vfName, + IN STL_PA_IMAGE_ID_DATA *image_id + ) +{ + FSTATUS fstatus = FSUCCESS; + QUERY_RESULT_VALUES *query_result = NULL; + STL_PA_VF_PORT_COUNTERS_DATA *response = NULL, *p; + SA_MAD *rsp_mad = NULL; + size_t rcv_buf_len = 0; + uint8_t request_data[PA_REQ_HEADER_SIZE + sizeof(STL_PA_VF_PORT_COUNTERS_DATA)] = {0}; + + DBG_ENTER_FUNC(port); + // Check the incoming port parameter + if (port == NULL) return response; + + p = (STL_PA_VF_PORT_COUNTERS_DATA *)(((SA_MAD *)request_data)->Data); + p->nodeLid = node_lid; + p->portNumber = port_number; + p->flags = (delta_flag ? STL_PA_PC_FLAG_DELTA : 0) | + (user_cntrs_flag ? STL_PA_PC_FLAG_USER_COUNTERS : 0); + snprintf(p->vfName, STL_PM_VFNAMELEN, "%s", vfName); + + p->imageId.imageNumber = image_id->imageNumber; + p->imageId.imageOffset = image_id->imageOffset; + p->imageId.imageTime.absoluteTime = image_id->imageTime.absoluteTime; + memset(p->reserved, 0, sizeof(p->reserved)); + p->reserved1 = 0; + BSWAP_STL_PA_VF_PORT_COUNTERS(p); + + // submit request + fstatus = pa_query_common(port, STL_PA_CMD_GET, STL_PA_ATTRID_GET_VF_PORT_CTRS, 0, + request_data, sizeof(request_data), &rcv_buf_len, &rsp_mad, &query_result); + if (fstatus != FSUCCESS) { + if (port->pa_verbose) + OMGT_OUTPUT_ERROR(port, "Error, requeset failed: status=%u\n", (unsigned int)fstatus); + goto done; + } else if (rsp_mad->SaHdr.AttributeOffset) { + if (port->pa_verbose) + OMGT_OUTPUT_ERROR(port, "Error, unexpected multiple MAD response\n"); + goto done; + } else { + if (port->pa_verbose) { + OMGT_DBGPRINT(port, "Completed request: OK\n"); + } + } + + response = MemoryAllocate2AndClear(sizeof(STL_PA_VF_PORT_COUNTERS_DATA), IBA_MEM_FLAG_PREMPTABLE, OMGT_MEMORY_TAG); + if (response == NULL) { + OMGT_OUTPUT_ERROR(port, "error allocating response buffer\n"); + goto done; + } + memcpy((uint8 *)response, rsp_mad->Data, min(sizeof(STL_PA_VF_PORT_COUNTERS_DATA), rcv_buf_len - IB_SA_DATA_OFFS)); + + // translate the data. + BSWAP_STL_PA_VF_PORT_COUNTERS(response); +done: + omgt_free_query_result_buffer(query_result); + if (rsp_mad) + free(rsp_mad); + + DBG_EXIT_FUNC(port); + return response; +} + +STL_PA_CLEAR_VF_PORT_COUNTERS_DATA * +iba_pa_single_mad_clr_vf_port_counters_response_query( + IN struct omgt_port *port, + IN uint32_t node_lid, + IN uint8_t port_number, + IN uint32_t select, + IN char *vfName + ) +{ + FSTATUS fstatus = FSUCCESS; + QUERY_RESULT_VALUES *query_result = NULL; + STL_PA_CLEAR_VF_PORT_COUNTERS_DATA *response = NULL, *p; + SA_MAD *rsp_mad = NULL; + size_t rcv_buf_len = 0; + uint8_t request_data[PA_REQ_HEADER_SIZE + sizeof(STL_PA_CLEAR_VF_PORT_COUNTERS_DATA)] = {0}; + + DBG_ENTER_FUNC(port); + // Check the incoming port parameter + if (port == NULL) return response; + + p = (STL_PA_CLEAR_VF_PORT_COUNTERS_DATA *)(((SA_MAD *)request_data)->Data); + p->nodeLid = hton32(node_lid); + p->portNumber = port_number; + p->vfCounterSelectMask.AsReg32 = hton32(select); + snprintf(p->vfName, STL_PM_VFNAMELEN, "%s", vfName); + memset(p->reserved, 0, sizeof(p->reserved)); + p->reserved2 = 0; + + // submit request + fstatus = pa_query_common(port, STL_PA_CMD_SET, STL_PA_ATTRID_CLR_VF_PORT_CTRS, 0, + request_data, sizeof(request_data), &rcv_buf_len, &rsp_mad, &query_result); + if (fstatus != FSUCCESS) { + if (port->pa_verbose) + OMGT_OUTPUT_ERROR(port, "Error, requeset failed: status=%u\n", (unsigned int)fstatus); + goto done; + } else if (rsp_mad->SaHdr.AttributeOffset) { + if (port->pa_verbose) + OMGT_OUTPUT_ERROR(port, "Error, unexpected multiple MAD response\n"); + goto done; + } else { + if (port->pa_verbose) { + OMGT_DBGPRINT(port, "Completed request: OK\n"); + } + } + + response = MemoryAllocate2AndClear(sizeof(STL_PA_CLEAR_VF_PORT_COUNTERS_DATA), IBA_MEM_FLAG_PREMPTABLE, OMGT_MEMORY_TAG); + if (response == NULL) { + OMGT_OUTPUT_ERROR(port, "error allocating response buffer\n"); + goto done; + } + memcpy((uint8 *)response, rsp_mad->Data, min(sizeof(STL_PA_CLEAR_VF_PORT_COUNTERS_DATA), rcv_buf_len - IB_SA_DATA_OFFS)); + + // translate the data. + BSWAP_STL_PA_CLEAR_VF_PORT_COUNTERS(response); +done: + omgt_free_query_result_buffer(query_result); + if (rsp_mad) + free(rsp_mad); + + DBG_EXIT_FUNC(port); + return response; +} + +FSTATUS +iba_pa_multi_mad_vf_focus_ports_response_query ( + IN struct omgt_port *port, + IN POMGT_QUERY query, + IN char *vf_name, + IN uint32 select, + IN uint32 start, + IN uint32 range, + OUT PQUERY_RESULT_VALUES *pquery_result, + IN STL_PA_IMAGE_ID_DATA *image_id + ) +{ + FSTATUS fstatus = FSUCCESS; + QUERY_RESULT_VALUES *query_result = NULL; + SA_MAD *rsp_mad = NULL; + size_t rcv_buf_len = 0; + uint8 request_data[PA_REQ_HEADER_SIZE + sizeof(STL_PA_VF_FOCUS_PORTS_REQ)] = {0}; + STL_PA_VF_FOCUS_PORTS_RSP *pa_data; + STL_PA_VF_FOCUS_PORTS_REQ *p; + STL_PA_VF_FOCUS_PORTS_RESULTS *pa_result; + int i; + + DBG_ENTER_FUNC(port); + // Check the incoming port parameter + if (port == NULL) return FERROR; + + p = (STL_PA_VF_FOCUS_PORTS_REQ *)(((SA_MAD *)request_data)->Data); + snprintf(p->vfName, sizeof(p->vfName), "%s", vf_name); + p->select = hton32(select); + p->start = hton32(start); + p->range = hton32(range); + + p->imageId.imageNumber = hton64(image_id->imageNumber); + p->imageId.imageOffset = hton32(image_id->imageOffset); + p->imageId.imageTime.absoluteTime = hton32(image_id->imageTime.absoluteTime); + + // process the command. + switch (query->OutputType) { + case OutputTypePaTableRecord: + // submit request + fstatus = pa_query_common(port, STL_PA_CMD_GETTABLE, STL_PA_ATTRID_GET_VF_FOCUS_PORTS, 0, + request_data, sizeof(request_data), &rcv_buf_len, &rsp_mad, &query_result); + if (fstatus != FSUCCESS){ + if (port->pa_verbose) + OMGT_OUTPUT_ERROR(port, "Error, requeset failed: status=%u\n",(unsigned int)fstatus); + goto done; + } else { + if (port->pa_verbose){ + OMGT_DBGPRINT(port, "Completed request: OK\n"); + } + } + + // translate the data. + pa_result = (STL_PA_VF_FOCUS_PORTS_RESULTS *)query_result->QueryResult; + pa_data = pa_result->FocusPortsRecords; + for (i = 0; i < pa_result->NumVFFocusPortsRecords; i++) { + STL_PA_VF_FOCUS_PORTS_RSP *vf_focus = (STL_PA_VF_FOCUS_PORTS_RSP *)GET_RESULT_OFFSET(rsp_mad, i); + pa_data[i] = *vf_focus; + BSWAP_STL_PA_VF_FOCUS_PORTS_RSP(&pa_data[i]); + } + break; + + default: + OMGT_OUTPUT_ERROR(port, "Query Not supported in OPAMGT: Input=%s, Output=%s\n", + iba_pa_query_input_type_msg(query->InputType), + iba_pa_query_result_type_msg(query->OutputType)); + fstatus = FERROR; + goto done; + break; + } + +done: + if (rsp_mad) + free(rsp_mad); + + *pquery_result = query_result; + + DBG_EXIT_FUNC(port); + return fstatus; +} + +/** + * @brief Get LID and SL of master PM service + * + * This function will query the SA service records to get the PM's GID. It will + * then construct a PATH record query (using the ServiceGID as the DGID for the + * request) to get the PM's LID and SL for sending PA queries. + * + * @param port port object to to store master PM LID and SL. + * + * @return FSTATUS + */ +FSTATUS +iba_pa_query_master_pm_lid(struct omgt_port *port) +{ + FSTATUS status; + OMGT_QUERY query; + PQUERY_RESULT_VALUES query_results = NULL; + PQUERY_RESULT_VALUES query_path_results = NULL; + SERVICE_RECORD_RESULTS *service_record_results; + + // Check the incoming port parameter + if (NULL == port) { + return (FERROR); + } + + // query SA for Service Records to all PMs within the fabric + memset(&query, 0, sizeof(query)); + query.InputType = InputTypeNoInput; + query.OutputType = OutputTypeServiceRecord; + + status = omgt_query_sa(port, &query, &query_results); + if (status != FSUCCESS) { + OMGT_OUTPUT_ERROR(port, "Error, failed to get service records (status=0x%x) query_results=%p: %s\n", + (unsigned int)status, (void *)query_results, FSTATUS_MSG(status)); + } else if ((query_results == NULL) || (query_results->ResultDataSize == 0)) { + status = FUNAVAILABLE; + } else { + int i, ix, pmCount = 0; + + status = FUNAVAILABLE; + service_record_results = (SERVICE_RECORD_RESULTS *)query_results->QueryResult; + if (service_record_results->NumServiceRecords) { + OMGT_DBGPRINT(port, "Got Service Records: records=%d\n", service_record_results->NumServiceRecords); + for (i = 0; i < service_record_results->NumServiceRecords; ++i) { + if (STL_PM_SERVICE_ID == service_record_results->ServiceRecords[i].RID.ServiceID) { + pmCount++; + if ((service_record_results->ServiceRecords[i].ServiceData8[0] >= STL_PM_VERSION) && + (service_record_results->ServiceRecords[i].ServiceData8[1] == STL_PM_MASTER)) { + OMGT_DBGPRINT(port, "This is the Primary PM.\n"); + + // + // query SA for Path Record to the primary PM + memset(&query, 0, sizeof(query)); + { + query.InputType = InputTypePathRecord; + query.OutputType = OutputTypePathRecord; + query.InputValue.IbPathRecord.PathRecord.PathRecord.DGID = + service_record_results->ServiceRecords[i].RID.ServiceGID; + omgt_port_get_port_prefix(port, + &query.InputValue.IbPathRecord.PathRecord.PathRecord.SGID.Type.Global.SubnetPrefix); + omgt_port_get_port_guid(port, + &query.InputValue.IbPathRecord.PathRecord.PathRecord.SGID.Type.Global.InterfaceID); + query.InputValue.IbPathRecord.PathRecord.PathRecord.ServiceID = STL_PM_SERVICE_ID; + + query.InputValue.IbPathRecord.PathRecord.ComponentMask = + IB_PATH_RECORD_COMP_NUMBPATH | IB_PATH_RECORD_COMP_SERVICEID | + IB_PATH_RECORD_COMP_DGID | IB_PATH_RECORD_COMP_SGID; + query.InputValue.IbPathRecord.PathRecord.PathRecord.NumbPath = 32; + } + + status = omgt_query_sa(port, &query, &query_path_results); + if ((status != FSUCCESS) || (query_path_results == NULL) || (query_path_results->ResultDataSize == 0)) { + OMGT_OUTPUT_ERROR(port, "Error, failed to get path record (status=0x%x) query_path_results=%p: %s\n", + (unsigned int)status, (void *)query_path_results, FSTATUS_MSG(status)); + status = FERROR; + break; + } + else { + PATH_RESULTS *path_record_results = (PATH_RESULTS *)query_path_results->QueryResult; + OMGT_DBGPRINT(port, "Got Path Records: records=%d\n", path_record_results->NumPathRecords); + if (path_record_results->NumPathRecords >= 1) { + // Find PathRecord with default P_Key or use PathRecords[0] + for (ix = path_record_results->NumPathRecords - 1; ix > 0; ix--) { + if ((path_record_results->PathRecords[ix].P_Key & 0x7FFF) == + (DEFAULT_P_KEY & 0x7FFF)) + break; + } + OMGT_DBGPRINT(port, "DGID in path record: 0x%lx:0x%lx\n", + path_record_results->PathRecords[ix].DGID.Type.Global.SubnetPrefix, + path_record_results->PathRecords[ix].DGID.Type.Global.InterfaceID); + /* Check for Extended LID in the OPA GID */ + if ((path_record_results->PathRecords[ix].DGID.Type.Global.InterfaceID >> 40) + == OMGT_STL_OUI) { + port->primary_pm_lid = + path_record_results->PathRecords[ix].DGID.Type.Global.InterfaceID & 0xFFFFFFFF; + } else { + port->primary_pm_lid = path_record_results->PathRecords[ix].DLID; + } + // Remember that for our own use + port->primary_pm_sl = path_record_results->PathRecords[ix].u2.s.SL; + OMGT_DBGPRINT(port, "Found Master PM LID 0x%x SL %u\n", + port->primary_pm_lid, port->primary_pm_sl); + } else { + status = FERROR; + OMGT_OUTPUT_ERROR(port, "Error, received no path records\n"); + break; + } + } + } + } + } + OMGT_DBGPRINT(port, "Number of PMs found %d\n", pmCount); + } + } + // deallocate results buffers + if (query_results) + omgt_free_query_result_buffer(query_results); + if (query_path_results) + omgt_free_query_result_buffer(query_path_results); + + return status; +} + +/** + * Get and Convert a MAD status code into string. + * + * @param port Local port to operate on. + * + * @return + * The corresponding status string. + */ +const char* +iba_pa_mad_status_msg( + IN struct omgt_port *port + ) +{ + // this is a little more complex than most due to bitfields and reserved + // values + MAD_STATUS mad_status; + uint16_t code = port->pa_mad_status; + + mad_status.AsReg16 = port->pa_mad_status; // ignore reserved bits in mad_status + if (code == MAD_STATUS_SUCCESS || (code & 0xff)) + return iba_mad_status_msg(mad_status); // standard mad status fields + else + { + // SA specific status code field 0-6 + code = mad_status.S.ClassSpecific; + if (code >= (unsigned)(sizeof(pa_sa_status_text)/sizeof(char*))) { + // PA specific status code field - codes start at 'A' (10) + code = mad_status.S.ClassSpecific - 9; + if (code >= (unsigned)(sizeof(pa_status_text)/sizeof(char*))) + return "Unknown PA Mad Status"; + else + return pa_status_text[code]; + } else + return pa_sa_status_text[code]; + } +} + +/* + * @brief Initialize PA connection on existing omgt_port session + * + * @param port omgt_port session to start PA interface on + * + * @return + * PACLIENT_OPERATIONAL - initialization successful + * PACLIENT_DOWN - initialization not successful/PaServer not available + */ +int +omgt_pa_service_connect(struct omgt_port *port) +{ + FSTATUS fstatus; + uint8_t mclass = MCLASS_VFI_PM; + struct omgt_class_args mgmt_class[2]; + int err = 0; + IB_PORT_ATTRIBUTES *attrib = NULL; + int pa_service_state = OMGT_SERVICE_STATE_DOWN; + + fstatus = omgt_get_portguid(port->hfi_num, port->hfi_port_num, NULL, port, NULL, NULL, NULL, &attrib, NULL, NULL, NULL, NULL, NULL); + + if (FSUCCESS == fstatus && attrib) { + port->local_gid = attrib->GIDTable[0]; + } else { + OMGT_OUTPUT_ERROR(port, "Could not get port guid: %s\n", iba_fstatus_msg(fstatus)); + goto done; + } + + if ((fstatus = iba_pa_query_master_pm_lid(port)) != FSUCCESS) { + OMGT_OUTPUT_ERROR(port, "Can't query primary PM LID!\n"); + if (fstatus == FUNAVAILABLE) { + pa_service_state = OMGT_SERVICE_STATE_UNAVAILABLE; + } + goto done; + } + + // register PA methods with OFED + memset(mgmt_class, 0, sizeof(mgmt_class)); + mgmt_class[0].base_version = STL_BASE_VERSION; + mgmt_class[0].mgmt_class = mclass; + mgmt_class[0].class_version = STL_PM_CLASS_VERSION; + mgmt_class[0].is_responding_client = 0; + mgmt_class[0].is_trap_client = 0; + mgmt_class[0].is_report_client = 0; + mgmt_class[0].kernel_rmpp = 1; + mgmt_class[0].use_methods = 0; + mgmt_class[0].oui = ib_truescale_oui; + + if ((err = omgt_bind_classes(port, mgmt_class)) != 0) { + OMGT_OUTPUT_ERROR(port, "Failed to register management class 0x%02x: %s\n", + mclass, strerror(err)); + goto done; + } + + pa_service_state = OMGT_SERVICE_STATE_OPERATIONAL; +done: + if (attrib) + MemoryDeallocate(attrib); + + return (port->pa_service_state = pa_service_state); +} + +/** + * Get PM configuration data + * + * @param port Port to operate on. + * @param pm_config Pointer to PM config data to fill + * + * @return + * OMGT_STATUS_SUCCESS - Get successful + * OMGT_STATUS_ERROR - Error + */ +OMGT_STATUS_T +omgt_pa_get_pm_config( + struct omgt_port *port, + STL_PA_PM_CFG_DATA *pm_config + ) +{ + OMGT_STATUS_T fstatus = OMGT_STATUS_ERROR; + STL_PA_PM_CFG_DATA * response; + + // Validate parameters + if (NULL == port || !pm_config) + { + OMGT_OUTPUT_ERROR(port, "invalid params or state\n"); + return (fstatus); + } + + OMGT_DBGPRINT(port, "Getting PM Configuration...\n"); + + if ( ( response = + iba_pa_single_mad_get_pm_config_response_query(port) ) != NULL ) + { +#if 0 +TODO STL COMPILE! + // TBD remove some of these after additional MAD testing + OMGT_DBGPRINT(port, "Interval = %u\n", response->sweepInterval); + OMGT_DBGPRINT(port, "Max Clients = %u\n", response->MaxClients); + OMGT_DBGPRINT(port, "History Size = %u\n", response->sizeHistory); + OMGT_DBGPRINT(port, "Freeze Size = %u\n", response->sizeFreeze); + OMGT_DBGPRINT(port, "Freeze Lease = %u\n", response->lease); + OMGT_DBGPRINT(port, "Flags = 0x%X\n", response->pmFlags); + OMGT_DBGPRINT(port, "Memory Footprint = 0x%" PRIX64 "\n", + response->memoryFootprint ); +#endif + memcpy(pm_config, response, sizeof(*pm_config)); + + MemoryDeallocate(response); + fstatus = OMGT_STATUS_SUCCESS; + } + else + OMGT_DBGPRINT(port, "Got NULL response - FAILED\n"); + + return (fstatus); +} + +/** + * Get image info + * + * @param port Port to operate on. + * @param pm_image_Id Image ID of image info to get + * @param pm_image_info Pointer to image info to fill + * + * @return + * OMGT_STATUS_SUCCESS - Get successful + * OMGT_STATUS_ERROR - Error + */ +OMGT_STATUS_T +omgt_pa_get_image_info( + struct omgt_port *port, + STL_PA_IMAGE_ID_DATA pm_image_id, + STL_PA_IMAGE_INFO_DATA *pm_image_info + ) +{ + OMGT_STATUS_T fstatus = OMGT_STATUS_ERROR; + uint32 ix; + STL_PA_IMAGE_INFO_DATA query = {{0}}; + STL_PA_IMAGE_INFO_DATA *response;; + + if (NULL == port || !pm_image_info) + { + OMGT_OUTPUT_ERROR(port, "invalid params or state\n"); + return (fstatus); + } + + query.imageId = pm_image_id; + + OMGT_DBGPRINT(port, "Getting Image Info...\n"); + + if ( ( response = iba_pa_multi_mad_get_image_info_response_query( + port, &query ) ) != NULL ) + { +#if 0 // TBD remove some of these after additional MAD testing + OMGT_DBGPRINT(port, "RespImageNum = 0x%" PRIX64 " Offset = %d\n", + response->imageId.imageNumber, response->imageId.imageOffset ); + OMGT_DBGPRINT(port, "sweepStart = 0x%" PRIX64 "\n", + response->sweepStart ); + OMGT_DBGPRINT(port, "sweepDuration = %u\n", + response->sweepDuration ); + OMGT_DBGPRINT(port, "numHFIPorts = %u\n", + response->numHFIPorts ); + OMGT_DBGPRINT(port, "numSwNodes = %u\n", + response->numSwitchNodes ); + OMGT_DBGPRINT(port, "numSwPorts = %u\n", + response->numSwitchPorts ); + OMGT_DBGPRINT(port, "numLinks = %u\n", + response->numLinks ); + OMGT_DBGPRINT(port, "numSMs = %u\n", + response->numSMs ); + OMGT_DBGPRINT(port, "numFailedNodes = %u\n", + response->numFailedNodes ); + OMGT_DBGPRINT(port, "numFailedPorts = %u\n", + response->numFailedPorts ); + OMGT_DBGPRINT(port, "numSkippedPorts = %u\n", + response->numSkippedPorts ); + OMGT_DBGPRINT(port, "numUnexpectedClearPorts = %u\n", + response->numUnexpectedClearPorts ); +#endif + memcpy(pm_image_info, response, sizeof(*pm_image_info)); + + for (ix = pm_image_info->numSMs; ix < 2; ix++) + memset(&pm_image_info->SMInfo[ix], 0, sizeof(STL_SMINFO_DATA)); + + MemoryDeallocate(response); + fstatus = OMGT_STATUS_SUCCESS; + } + else + OMGT_DBGPRINT(port, "Got NULL response - FAILED\n"); + + return (fstatus); +} + +/** + * Get list of group names + * + * @param port Port to operate on. + * @param pm_group_list Pointer to group list to fill + * + * @return + * OMGT_STATUS_SUCCESS - Get successful + * OMGT_STATUS_ERROR - Error + */ +OMGT_STATUS_T +omgt_pa_get_group_list( + struct omgt_port *port, + uint32 *pNum_Groups, + STL_PA_GROUP_LIST **pm_group_list + ) +{ + OMGT_STATUS_T fstatus = OMGT_STATUS_ERROR; + uint32 size_group_list; + OMGT_QUERY query; + PQUERY_RESULT_VALUES query_results = NULL; + STL_PA_GROUP_LIST_RESULTS *p; + + // Validate the parameters and state + if (!port || !pNum_Groups || !pm_group_list || *pm_group_list) + { + OMGT_OUTPUT_ERROR(port, "invalid params or state\n"); + return (fstatus); + } + + memset(&query, 0, sizeof(query)); // initialize reserved fields + query.InputType = InputTypeNoInput; + query.OutputType = OutputTypePaTableRecord; + + OMGT_DBGPRINT(port, "Getting Multi Record Response For Group Data...\n"); + OMGT_DBGPRINT(port, "Query: Input=%s, Output=%s\n", + iba_pa_query_input_type_msg(query.InputType), + iba_pa_query_result_type_msg(query.OutputType) ); + + fstatus = iba_pa_multi_mad_group_list_response_query( port, &query, &query_results ); + + if (!query_results) + { + OMGT_DBGPRINT(port, "PA Group List query Failed: %s\n", + iba_fstatus_msg(fstatus) ); + goto fail; + } + else if (query_results->Status != FSUCCESS) + { + OMGT_DBGPRINT(port, "PA Group List query Failed: %s MadStatus 0x%X: %s\n", + iba_fstatus_msg(query_results->Status), + port->pa_mad_status, iba_pa_mad_status_msg(port) ); + goto fail; + } + + else if (query_results->ResultDataSize == 0) + { + OMGT_DBGPRINT(port, "No Records Returned\n"); + *pNum_Groups = 0; + fstatus = OMGT_STATUS_SUCCESS; + goto done; + } + else + { + p = (STL_PA_GROUP_LIST_RESULTS*)query_results->QueryResult; + + // TBD remove some of these after additional MAD testing + OMGT_DBGPRINT(port, "MadStatus 0x%X: %s\n", port->pa_mad_status, + iba_pa_mad_status_msg(port)); + OMGT_DBGPRINT(port, "%d Bytes Returned\n", query_results->ResultDataSize); + OMGT_DBGPRINT(port, "PA Multiple MAD Response for Group Data:\n"); + OMGT_DBGPRINT(port, "NumGroupListRecords = %d\n", + (int)p->NumGroupListRecords ); + + *pNum_Groups = p->NumGroupListRecords; + size_group_list = sizeof(STL_PA_GROUP_LIST) * *pNum_Groups; + + if ( !( *pm_group_list = MemoryAllocate2AndClear( size_group_list, IBA_MEM_FLAG_PREMPTABLE, OMGT_MEMORY_TAG ) ) ) + { + OMGT_OUTPUT_ERROR(port, "can not allocate memory\n"); + goto fail; + } + + memcpy(*pm_group_list, p->GroupListRecords, size_group_list); + fstatus = OMGT_STATUS_SUCCESS; + } + +done: + // omgt_query_port_fabric will have allocated a result buffer + // we must free the buffer when we are done with it + if (query_results) + omgt_free_query_result_buffer(query_results); + return (fstatus); + +fail: + fstatus = OMGT_STATUS_ERROR; + goto done; + +} + +void omgt_pa_release_group_list(STL_PA_GROUP_LIST **pm_group_list) +{ + if (pm_group_list && *pm_group_list) { + MemoryDeallocate(*pm_group_list); + *pm_group_list = NULL; + } +} +OMGT_STATUS_T +omgt_pa_get_group_list2( + struct omgt_port *port, + STL_PA_IMAGE_ID_DATA pm_image_id_query, + uint32 *pNum_Groups, + STL_PA_GROUP_LIST2 **pm_group_list + ) +{ + OMGT_STATUS_T fstatus = OMGT_STATUS_ERROR; + uint32 size_group_list; + OMGT_QUERY query; + PQUERY_RESULT_VALUES query_results = NULL; + STL_PA_IMAGE_ID_DATA image_id = pm_image_id_query; + STL_PA_GROUP_LIST2_RESULTS *p; + + // Validate the parameters and state + if (!port || !pNum_Groups || !pm_group_list || *pm_group_list) { + OMGT_OUTPUT_ERROR(port, "invalid params or state\n"); + return (fstatus); + } + + memset(&query, 0, sizeof(query)); // initialize reserved fields + query.InputType = InputTypeNoInput; + query.OutputType = OutputTypePaTableRecord; + + OMGT_DBGPRINT(port, "Getting Multi Record Response For Group List...\n"); + OMGT_DBGPRINT(port, "Query: Input=%s, Output=%s\n", + iba_pa_query_input_type_msg(query.InputType), + iba_pa_query_result_type_msg(query.OutputType)); + + fstatus = iba_pa_multi_mad_group_list2_response_query(port, &query, &image_id, &query_results); + + if (!query_results) { + OMGT_DBGPRINT(port, "PA Group List2 query Failed: %s\n", + iba_fstatus_msg(fstatus)); + goto fail; + } else if (query_results->Status != FSUCCESS) { + OMGT_DBGPRINT(port, "PA Group List2 query Failed: %s MadStatus 0x%X: %s\n", + iba_fstatus_msg(query_results->Status), + port->pa_mad_status, iba_pa_mad_status_msg(port)); + goto fail; + } else if (query_results->ResultDataSize == 0) { + OMGT_DBGPRINT(port, "No Records Returned\n"); + *pNum_Groups = 0; + fstatus = OMGT_STATUS_SUCCESS; + goto done; + } else { + p = (STL_PA_GROUP_LIST2_RESULTS *)query_results->QueryResult; + + // TBD remove some of these after additional MAD testing + OMGT_DBGPRINT(port, "MadStatus 0x%X: %s\n", port->pa_mad_status, + iba_pa_mad_status_msg(port)); + OMGT_DBGPRINT(port, "%d Bytes Returned\n", query_results->ResultDataSize); + OMGT_DBGPRINT(port, "PA Multiple MAD Response for Group Data:\n"); + OMGT_DBGPRINT(port, "NumGroupList2Records = %d\n", + (int)p->NumGroupList2Records); + + *pNum_Groups = p->NumGroupList2Records; + size_group_list = sizeof(STL_PA_GROUP_LIST2) * *pNum_Groups; + + if (!(*pm_group_list = MemoryAllocate2AndClear(size_group_list, IBA_MEM_FLAG_PREMPTABLE, OMGT_MEMORY_TAG))) { + OMGT_OUTPUT_ERROR(port, "can not allocate memory\n"); + goto fail; + } + memcpy(*pm_group_list, p->GroupList2Records, size_group_list); + fstatus = OMGT_STATUS_SUCCESS; + } + +done: + // omgt_query_port_fabric will have allocated a result buffer + // we must free the buffer when we are done with it + if (query_results) + omgt_free_query_result_buffer(query_results); + return (fstatus); +fail: + fstatus = OMGT_STATUS_ERROR; + goto done; +} + +void omgt_pa_release_group_list2(STL_PA_GROUP_LIST2 **pm_group_list) +{ + if (pm_group_list && *pm_group_list) { + MemoryDeallocate(*pm_group_list); + *pm_group_list = NULL; + } +} +/** + * Get list of vf names + * + * @param port Port to operate on. + * @param pm_vf_list Pointer to vf list to fill + * + * @return + * OMGT_STATUS_SUCCESS - Get successful + * OMGT_STATUS_ERROR - Error + */ +OMGT_STATUS_T +omgt_pa_get_vf_list( + struct omgt_port *port, + uint32 *pNum_VFs, + STL_PA_VF_LIST **pm_vf_list + ) +{ + OMGT_STATUS_T fstatus = OMGT_STATUS_ERROR; + uint32 size_vf_list; + OMGT_QUERY query; + PQUERY_RESULT_VALUES query_results = NULL; + STL_PA_VF_LIST_RESULTS *p; + + // Validate the parameters and state + if (!port || !pNum_VFs || !pm_vf_list || *pm_vf_list) + { + OMGT_OUTPUT_ERROR(port, "invalid params or state\n"); + return (fstatus); + } + + memset(&query, 0, sizeof(query)); // initialize reserved fields + query.InputType = InputTypeNoInput; + query.OutputType = OutputTypePaTableRecord; + + OMGT_DBGPRINT(port, "Getting Multi Record Response For VF Data...\n"); + OMGT_DBGPRINT(port, "Query: Input=%s, Output=%s\n", + iba_pa_query_input_type_msg(query.InputType), + iba_pa_query_result_type_msg(query.OutputType) ); + + fstatus = iba_pa_multi_mad_vf_list_response_query( port, &query, &query_results ); + + if (!query_results) + { + OMGT_DBGPRINT(port, "PA VF List query Failed: %s\n", + iba_fstatus_msg(fstatus) ); + goto fail; + } + else if (query_results->Status != FSUCCESS) + { + OMGT_DBGPRINT(port, "PA VF List query Failed: %s MadStatus 0x%X: %s\n", + iba_fstatus_msg(query_results->Status), + port->pa_mad_status, iba_pa_mad_status_msg(port) ); + goto fail; + } + + else if (query_results->ResultDataSize == 0) + { + OMGT_DBGPRINT(port, "No Records Returned\n"); + *pNum_VFs = 0; + fstatus = OMGT_STATUS_SUCCESS; + goto done; + } + else + { + p = (STL_PA_VF_LIST_RESULTS*)query_results->QueryResult; + + // TBD remove some of these after additional MAD testing + OMGT_DBGPRINT(port, "MadStatus 0x%X: %s\n", port->pa_mad_status, + iba_pa_mad_status_msg(port)); + OMGT_DBGPRINT(port, "%d Bytes Returned\n", query_results->ResultDataSize); + OMGT_DBGPRINT(port, "PA Multiple MAD Response for VF Data:\n"); + OMGT_DBGPRINT(port, "NumVFListRecords = %d\n", + (int)p->NumVFListRecords ); + + *pNum_VFs = p->NumVFListRecords; + size_vf_list = sizeof(STL_PA_VF_LIST) * *pNum_VFs; + + if ( !( *pm_vf_list = MemoryAllocate2AndClear( size_vf_list, IBA_MEM_FLAG_PREMPTABLE, OMGT_MEMORY_TAG ) ) ) + { + OMGT_OUTPUT_ERROR(port, "can not allocate memory\n"); + goto fail; + } + + memcpy(*pm_vf_list, p->VFListRecords, size_vf_list); + fstatus = OMGT_STATUS_SUCCESS; + } + +done: + // omgt_query_port_fabric will have allocated a result buffer + // we must free the buffer when we are done with it + if (query_results) + omgt_free_query_result_buffer(query_results); + return (fstatus); + +fail: + fstatus = OMGT_STATUS_ERROR; + goto done; + +} + +void omgt_pa_release_vf_list(STL_PA_VF_LIST **pm_vf_list) +{ + if (pm_vf_list && *pm_vf_list) { + MemoryDeallocate(*pm_vf_list); + *pm_vf_list = NULL; + } +} +OMGT_STATUS_T +omgt_pa_get_vf_list2( + struct omgt_port *port, + STL_PA_IMAGE_ID_DATA pm_image_id_query, + uint32 *pNum_VFs, + STL_PA_VF_LIST2 **pm_vf_list + ) +{ + OMGT_STATUS_T fstatus = OMGT_STATUS_ERROR; + uint32 size_vf_list; + OMGT_QUERY query; + PQUERY_RESULT_VALUES query_results = NULL; + STL_PA_IMAGE_ID_DATA image_id = pm_image_id_query; + STL_PA_VF_LIST2_RESULTS *p; + + // Validate the parameters and state + if (!port || !pNum_VFs || !pm_vf_list || *pm_vf_list) { + OMGT_OUTPUT_ERROR(port, "invalid params or state\n"); + return (fstatus); + } + + memset(&query, 0, sizeof(query)); // initialize reserved fields + query.InputType = InputTypeNoInput; + query.OutputType = OutputTypePaTableRecord; + + OMGT_DBGPRINT(port, "Getting Multi Record Response For VF Data...\n"); + OMGT_DBGPRINT(port, "Query: Input=%s, Output=%s\n", + iba_pa_query_input_type_msg(query.InputType), + iba_pa_query_result_type_msg(query.OutputType)); + + fstatus = iba_pa_multi_mad_vf_list2_response_query(port, &query, &image_id, &query_results); + if (!query_results) { + OMGT_DBGPRINT(port, "PA VF List2 query Failed: %s\n", + iba_fstatus_msg(fstatus)); + goto fail; + } else if (query_results->Status != FSUCCESS) { + OMGT_DBGPRINT(port, "PA VF List2 query Failed: %s MadStatus 0x%X: %s\n", + iba_fstatus_msg(query_results->Status), + port->pa_mad_status, iba_pa_mad_status_msg(port)); + goto fail; + } else if (query_results->ResultDataSize == 0) { + OMGT_DBGPRINT(port, "No Records Returned\n"); + *pNum_VFs = 0; + fstatus = OMGT_STATUS_SUCCESS; + goto done; + } else { + p = (STL_PA_VF_LIST2_RESULTS *)query_results->QueryResult; + + // TBD remove some of these after additional MAD testing + OMGT_DBGPRINT(port, "MadStatus 0x%X: %s\n", port->pa_mad_status, + iba_pa_mad_status_msg(port)); + OMGT_DBGPRINT(port, "%d Bytes Returned\n", query_results->ResultDataSize); + OMGT_DBGPRINT(port, "PA Multiple MAD Response for VF Data:\n"); + OMGT_DBGPRINT(port, "NumVFList2Records = %d\n", + (int)p->NumVFList2Records); + + *pNum_VFs = p->NumVFList2Records; + size_vf_list = sizeof(STL_PA_VF_LIST2) * *pNum_VFs; + + if (!(*pm_vf_list = MemoryAllocate2AndClear(size_vf_list, IBA_MEM_FLAG_PREMPTABLE, OMGT_MEMORY_TAG))) { + OMGT_OUTPUT_ERROR(port, "can not allocate memory\n"); + goto fail; + } + + memcpy(*pm_vf_list, p->VFList2Records, size_vf_list); + fstatus = OMGT_STATUS_SUCCESS; + } + +done: + // omgt_query_port_fabric will have allocated a result buffer + // we must free the buffer when we are done with it + if (query_results) + omgt_free_query_result_buffer(query_results); + return (fstatus); +fail: + fstatus = OMGT_STATUS_ERROR; + goto done; + +} +void omgt_pa_release_vf_list2(STL_PA_VF_LIST2 **pm_vf_list) +{ + if (pm_vf_list && *pm_vf_list) { + MemoryDeallocate(*pm_vf_list); + *pm_vf_list = NULL; + } +} +/** + * Get group info + * + * @param port Port to operate on. + * @param pm_image_id_query Image ID of group info to get. + * @param group_name Pointer to group name + * @param pm_image_id_resp Pointer to image ID of group info returned. + * @param pm_group_info Pointer to group info to fill. + * + * @return + * OMGT_STATUS_SUCCESS - Get successful + * OMGT_STATUS_ERROR - Error + */ +OMGT_STATUS_T +omgt_pa_get_group_info( + struct omgt_port *port, + STL_PA_IMAGE_ID_DATA pm_image_id_query, + char *group_name, + STL_PA_IMAGE_ID_DATA *pm_image_id_resp, + STL_PA_PM_GROUP_INFO_DATA *pm_group_info + ) +{ + OMGT_STATUS_T fstatus = OMGT_STATUS_ERROR; + STL_PA_IMAGE_ID_DATA image_id = pm_image_id_query; + OMGT_QUERY query; + PQUERY_RESULT_VALUES query_results = NULL; + STL_PA_GROUP_INFO_RESULTS *p; + + // Validate the parameters and state + if (!port || !group_name || !pm_group_info) + { + OMGT_OUTPUT_ERROR(port, "invalid params or state\n"); + return (fstatus); + } + + memset(&query, 0, sizeof(query)); // initialize reserved fields + query.InputType = InputTypeNoInput; + query.OutputType = OutputTypePaTableRecord; + + OMGT_DBGPRINT(port, "Getting Multi Record Response For Group Info...\n"); + OMGT_DBGPRINT(port, "Query: Input=%s, Output=%s\n", + iba_pa_query_input_type_msg(query.InputType), + iba_pa_query_result_type_msg(query.OutputType)); + + fstatus = iba_pa_multi_mad_group_stats_response_query( + port, &query, group_name, &query_results, &image_id ); + + if (!query_results) + { + OMGT_DBGPRINT(port, "PA GroupInfo query Failed: %s\n", + iba_fstatus_msg(fstatus) ); + goto fail; + } + else if (query_results->Status != FSUCCESS) + { + OMGT_DBGPRINT(port, "PA GroupInfo query Failed: %s MadStatus 0x%X: %s\n", + iba_fstatus_msg(query_results->Status), port->pa_mad_status, + iba_pa_mad_status_msg(port) ); + goto fail; + } + else if (query_results->ResultDataSize == 0) + { + OMGT_DBGPRINT(port, "No Records Returned\n"); + fstatus = OMGT_STATUS_SUCCESS; + goto done; + } + else + { + p = (STL_PA_GROUP_INFO_RESULTS*)query_results->QueryResult; +#if 0 + // TBD remove some of these after additional MAD testing + OMGT_DBGPRINT(port, "MadStatus 0x%X: %s\n", port->pa_mad_status, + iba_pa_mad_status_msg(port->pa_mad_status ); + OMGT_DBGPRINT(port, "%d Bytes Returned\n", query_results->ResultDataSize); + OMGT_DBGPRINT(port, "PA Multiple MAD Response for Group Info group %s:\n", + group_name ); + OMGT_DBGPRINT(port, "NumGroupInfoRecords = %d\n", + (int)p->NumGroupInfoRecords ); + + // TBD should this allow multiple records of group info ? + // TBD remove some of these after additional MAD testing + OMGT_DBGPRINT(port, "\tgroup name: %s\n", p->GroupInfoRecords[0].groupName); + OMGT_DBGPRINT(port, "\tinternal ports: %d\n", p->GroupInfoRecords[0].numInternalPorts); + OMGT_DBGPRINT(port, "\tinternal rate min: %d\n", p->GroupInfoRecords[0].minInternalRate); + OMGT_DBGPRINT(port, "\tinternal rate max: %d\n", p->GroupInfoRecords[0].maxInternalRate); + OMGT_DBGPRINT(port, "\tinternal MBps max: %d\n", p->GroupInfoRecords[0].maxInternalMBps); + OMGT_DBGPRINT(port, "\texternal ports: %d\n", p->GroupInfoRecords[0].numExternalPorts); + OMGT_DBGPRINT(port, "\texternal rate min: %d\n", p->GroupInfoRecords[0].minExternalRate); + OMGT_DBGPRINT(port, "\texternal rate max: %d\n", p->GroupInfoRecords[0].maxExternalRate); + OMGT_DBGPRINT(port, "\texternal MBps max: %d\n", p->GroupInfoRecords[0].maxExternalMBps); + OMGT_DBGPRINT(port, "\tinternal util totalMBps: %" PRIu64 "\n", + p->GroupInfoRecords[0].internalUtilStats.totalMBps ); + OMGT_DBGPRINT(port, "\tinternal util avgMBps: %u\n", + p->GroupInfoRecords[0].internalUtilStats.avgMBps ); + OMGT_DBGPRINT(port, "\tinternal util maxMBps: %u\n", + p->GroupInfoRecords[0].internalUtilStats.maxMBps ); + OMGT_DBGPRINT(port, "\tinternal util totalKPps: %" PRIu64 "\n", + p->GroupInfoRecords[0].internalUtilStats.totalKPps ); + OMGT_DBGPRINT(port, "\tinternal util avgKPps: %u\n", + p->GroupInfoRecords[0].internalUtilStats.avgKPps ); + OMGT_DBGPRINT(port, "\tinternal util maxKPps: %u\n", + p->GroupInfoRecords[0].internalUtilStats.maxKPps ); + OMGT_DBGPRINT(port, "\tsend util stats: %" PRIu64 "\n", + p->GroupInfoRecords[0].sendUtilStats.totalMBps ); + OMGT_DBGPRINT(port, "\trecv util stats: %" PRIu64 "\n", + p->GroupInfoRecords[0].recvUtilStats.totalMBps ); + OMGT_DBGPRINT(port, "\tinternal max integrity errors: %u\n", + p->GroupInfoRecords[0].internalCategoryStats.categoryMaximums.integrityErrors ); + OMGT_DBGPRINT(port, "\texternal max integrity errors: %u\n", + p->GroupInfoRecords[0].externalCategoryStats.categoryMaximums.integrityErrors ); + OMGT_DBGPRINT(port, "\tinternal integrity bucket[4]: %u\n", + p->GroupInfoRecords[0].internalCategoryStats.ports[4].integrityErrors ); + OMGT_DBGPRINT(port, "\texternal integrity bucket[4]: %u\n", + p->GroupInfoRecords[0].externalCategoryStats.ports[4].integrityErrors ); +#endif + memcpy(pm_group_info, p->GroupInfoRecords, sizeof(*pm_group_info)); + if (pm_image_id_resp) + *pm_image_id_resp = p->GroupInfoRecords[0].imageId; + + fstatus = OMGT_STATUS_SUCCESS; + } + +done: + // iba_pa_query_port_fabric_info will have allocated a result buffer + // we must free the buffer when we are done with it + if (query_results) + omgt_free_query_result_buffer(query_results); + return (fstatus); + +fail: + fstatus = OMGT_STATUS_ERROR; + goto done; +} + +/** + * Get vf info + * + * @param port Port to operate on. + * @param pm_image_id_query Image ID of vf info to get. + * @param vf_name Pointer to vf name + * @param pm_image_id_resp Pointer to image ID of vf info returned. + * @param pm_vf_info Pointer to vf info to fill. + * + * @return + * OMGT_STATUS_SUCCESS - Get successful + * OMGT_STATUS_ERROR - Error + */ +OMGT_STATUS_T +omgt_pa_get_vf_info( + struct omgt_port *port, + STL_PA_IMAGE_ID_DATA pm_image_id_query, + char *vf_name, + STL_PA_IMAGE_ID_DATA *pm_image_id_resp, + STL_PA_VF_INFO_DATA *pm_vf_info + ) +{ + OMGT_STATUS_T status = OMGT_STATUS_ERROR; + STL_PA_IMAGE_ID_DATA image_id = pm_image_id_query; + OMGT_QUERY query; + PQUERY_RESULT_VALUES query_results = NULL; + STL_PA_VF_INFO_RESULTS *p; + + // Validate the parameters and state + if (!port || !vf_name || !pm_vf_info){ + OMGT_OUTPUT_ERROR(port, "invalid params or state\n"); + return status; + } + + memset(&query, 0, sizeof(query)); + query.InputType = InputTypeNoInput; + query.OutputType = OutputTypePaTableRecord; + + OMGT_DBGPRINT(port, "Getting Multi Record Response for VF Info...\n"); + OMGT_DBGPRINT(port, "Query: Input=%s, Output=%s\n", iba_pa_query_input_type_msg(query.InputType), + iba_pa_query_result_type_msg(query.OutputType)); + + status = iba_pa_multi_mad_vf_info_response_query(port, &query, vf_name, &query_results, &image_id); + + if (!query_results) + { + OMGT_DBGPRINT(port, "PA VFInfo query Failed: %s\n", iba_fstatus_msg(status)); + goto fail; + } + else if (query_results->Status != FSUCCESS) + { + OMGT_DBGPRINT(port, "PA VFInfo query Failed: %s MadStatus 0x%X: %s\n", + iba_fstatus_msg(query_results->Status), port->pa_mad_status, + iba_pa_mad_status_msg(port) ); + goto fail; + } + else if (query_results->ResultDataSize == 0) + { + OMGT_DBGPRINT(port, "No Records Returned\n"); + status = OMGT_STATUS_SUCCESS; + goto done; + } + else + { + p = (STL_PA_VF_INFO_RESULTS*)query_results->QueryResult; + + memcpy(pm_vf_info, p->VFInfoRecords, sizeof(*pm_vf_info)); + if (pm_image_id_resp) + *pm_image_id_resp = p->VFInfoRecords[0].imageId; + + status = OMGT_STATUS_SUCCESS; + } + +done: + if (query_results) + omgt_free_query_result_buffer(query_results); + return (status); + +fail: + status = OMGT_STATUS_ERROR; + goto done; +} + +/** + * Get group config info + * + * @param port Port to operate on. + * @param pm_image_id_query Image ID of group config to get. + * @param group_name Pointer to group name + * @param pm_image_id_resp Pointer to image ID of group info returned. + * @param pm_group_config Pointer to group config to fill. Upon successful return, a memory to + * contain the group config is allocated. The caller must call + * omgt_pa_release_group_config to free the memory later. + * + * @return + * OMGT_STATUS_SUCCESS - Get successful + * OMGT_STATUS_ERROR - Error + */ +OMGT_STATUS_T +omgt_pa_get_group_config( + struct omgt_port *port, + STL_PA_IMAGE_ID_DATA pm_image_id_query, + char *group_name, + STL_PA_IMAGE_ID_DATA *pm_image_id_resp, + uint32 *pNum_ports, + STL_PA_PM_GROUP_CFG_RSP **pm_group_config + ) +{ + OMGT_STATUS_T fstatus = OMGT_STATUS_ERROR; + uint32 num_ports; + uint32 size_group_config; + STL_PA_IMAGE_ID_DATA image_id = pm_image_id_query; + OMGT_QUERY query; + PQUERY_RESULT_VALUES query_results = NULL; + STL_PA_GROUP_CONFIG_RESULTS *p; + + // Validate the parameters and state + if (!port || !group_name || !pm_group_config || *pm_group_config) + { + OMGT_OUTPUT_ERROR(port, "invalid params or state\n"); + return (fstatus); + } + + memset(&query, 0, sizeof(query)); // initialize reserved fields + query.InputType = InputTypeNoInput; + query.OutputType = OutputTypePaTableRecord; + + OMGT_DBGPRINT(port, "Getting Group Config...\n"); + OMGT_DBGPRINT(port, "Query: Input=%s, Output=%s\n", + iba_pa_query_input_type_msg(query.InputType), + iba_pa_query_result_type_msg(query.OutputType)); + + fstatus = iba_pa_multi_mad_group_config_response_query( + port, &query, group_name, &query_results, &image_id ); + + if (!query_results) + { + OMGT_DBGPRINT(port, "PA GroupConfig query Failed: %s\n", + iba_fstatus_msg(fstatus) ); + goto fail; + } + else if (query_results->Status != FSUCCESS) + { + OMGT_DBGPRINT(port, "PA GroupConfig query Failed: %s MadStatus 0x%X: %s\n", + iba_fstatus_msg(query_results->Status), port->pa_mad_status, + iba_pa_mad_status_msg(port) ); + goto fail; + } + else if (query_results->ResultDataSize == 0) + { + OMGT_DBGPRINT(port, "No Records Returned\n"); + *pNum_ports = 0; + fstatus = OMGT_STATUS_SUCCESS; + goto done; + } + else + { + p = (STL_PA_GROUP_CONFIG_RESULTS*)query_results->QueryResult; + + // TBD remove some of these after additional MAD testing + OMGT_DBGPRINT(port, "MadStatus 0x%X: %s\n", port->pa_mad_status, + iba_pa_mad_status_msg(port) ); + OMGT_DBGPRINT(port, "%d Bytes Returned\n", query_results->ResultDataSize); + OMGT_DBGPRINT(port, "PA Multiple MAD Response for GroupConfig group %s:\n", + group_name ); + OMGT_DBGPRINT(port, "NumGroupConfigRecords = %d\n", + (int)p->NumGroupConfigRecords ); + + num_ports = p->NumGroupConfigRecords < MAX_PORTS_LIST ? + p->NumGroupConfigRecords : MAX_PORTS_LIST; + *pNum_ports = num_ports; + size_group_config = sizeof(STL_PA_PM_GROUP_CFG_RSP) * num_ports; + + if ( !( *pm_group_config = MemoryAllocate2AndClear( size_group_config, + IBA_MEM_FLAG_PREMPTABLE, OMGT_MEMORY_TAG ) ) ) + { + OMGT_OUTPUT_ERROR(port, "can not allocate memory\n"); + goto fail; + } + + OMGT_DBGPRINT(port, "\tname:%s, ports:%u\n", + group_name, + (unsigned int)num_ports ); + + memcpy(*pm_group_config, p->GroupConfigRecords, size_group_config); + fstatus = OMGT_STATUS_SUCCESS; + } + +done: + // iba_pa_query_port_fabric_info will have allocated a result buffer + // we must free the buffer when we are done with it + omgt_free_query_result_buffer(query_results); + return (fstatus); + +fail: + fstatus = OMGT_STATUS_ERROR; + goto done; +} + +/** + * Release group config info + * + * @param port Port to operate on. + * @param pm_group_config Pointer to pointer to the group config to free. + * + * @return + * None + */ +void +omgt_pa_release_group_config( + STL_PA_PM_GROUP_CFG_RSP **pm_group_config + ) +{ + if (pm_group_config && *pm_group_config) + { + MemoryDeallocate(*pm_group_config); + *pm_group_config = NULL; + } + +} + +/** + * Get group node info + * + * @param port Port to operate on. + * @param pm_image_id_query Image ID of group config to get. + * @param group_name Pointer to group name + * @param nodeLid node LID + * @param nodeGuid node GUID + * @param nodeDesc node Description + * @param pm_image_id_resp Pointer to image ID of group info returned. + * @param pm_group_config Pointer to group config to fill. Upon successful return, a memory to + * contain the group config is allocated. The caller must call + * omgt_pa_release_group_config to free the memory later. + * + * @return + * OMGT_STATUS_SUCCESS - Get successful + * OMGT_STATUS_ERROR - Error + */ +OMGT_STATUS_T +omgt_pa_get_group_nodeinfo( + struct omgt_port *port, + STL_PA_IMAGE_ID_DATA pm_image_id_query, + char *group_name, + STL_LID nodeLid, + uint64 nodeGuid, + char *nodeDesc, + STL_PA_IMAGE_ID_DATA *pm_image_id_resp, + uint32 *pNum_nodes, + STL_PA_GROUP_NODEINFO_RSP **pm_group_nodeinfo + ) +{ + OMGT_STATUS_T fstatus = OMGT_STATUS_ERROR; + uint32 num_nodes; + uint32 size_group_nodeinfo; + STL_PA_IMAGE_ID_DATA image_id = pm_image_id_query; + OMGT_QUERY query; + PQUERY_RESULT_VALUES query_results = NULL; + STL_PA_GROUP_NODEINFO_RESULTS *p; + + // Validate the parameters and state + if (!port || !group_name || !pm_group_nodeinfo || *pm_group_nodeinfo) + { + OMGT_OUTPUT_ERROR(port, "invalid params or state\n"); + return (fstatus); + } + + memset(&query, 0, sizeof(query)); // initialize reserved fields + query.InputType = InputTypeNoInput; + query.OutputType = OutputTypePaTableRecord; + + OMGT_DBGPRINT(port, "Getting Group Node Info...\n"); + OMGT_DBGPRINT(port, "Query: Input=%s, Output=%s\n", + iba_pa_query_input_type_msg(query.InputType), + iba_pa_query_result_type_msg(query.OutputType)); + + fstatus = iba_pa_multi_mad_group_nodeinfo_response_query( + port, &query, group_name, nodeLid, nodeGuid, nodeDesc, &query_results, &image_id ); + + if (!query_results) + { + OMGT_DBGPRINT(port, "PA GroupNodeInfo query Failed: %s\n", + iba_fstatus_msg(fstatus) ); + goto fail; + } + else if (query_results->Status != FSUCCESS) + { + OMGT_DBGPRINT(port, "PA GroupNodeInfo query Failed: %s MadStatus 0x%X: %s\n", + iba_fstatus_msg(query_results->Status), port->pa_mad_status, + iba_pa_mad_status_msg(port) ); + goto fail; + } + else if (query_results->ResultDataSize == 0) + { + OMGT_DBGPRINT(port, "No Records Returned\n"); + *pNum_nodes = 0; + fstatus = OMGT_STATUS_SUCCESS; + goto done; + } + else + { + p = (STL_PA_GROUP_NODEINFO_RESULTS*)query_results->QueryResult; + + // TBD remove some of these after additional MAD testing + OMGT_DBGPRINT(port, "MadStatus 0x%X: %s\n", port->pa_mad_status, + iba_pa_mad_status_msg(port) ); + OMGT_DBGPRINT(port, "%d Bytes Returned\n", query_results->ResultDataSize); + OMGT_DBGPRINT(port, "PA Multiple MAD Response for GroupNodeInfo group %s:\n", + group_name ); + OMGT_DBGPRINT(port, "NumGroupNodeInfoRecords = %d\n", + (int)p->NumGroupNodeInfoRecords ); + + num_nodes = p->NumGroupNodeInfoRecords; + *pNum_nodes = num_nodes; + size_group_nodeinfo = sizeof(STL_PA_GROUP_NODEINFO_RSP) * num_nodes; + + if ( !( *pm_group_nodeinfo = MemoryAllocate2AndClear( size_group_nodeinfo, + IBA_MEM_FLAG_PREMPTABLE, OMGT_MEMORY_TAG ) ) ) + { + OMGT_OUTPUT_ERROR(port, "can not allocate memory\n"); + goto fail; + } + + OMGT_DBGPRINT(port, "\tname:%s, nodes:%u\n", + group_name, + (unsigned int)num_nodes ); + + memcpy(*pm_group_nodeinfo, p->GroupNodeInfoRecords, size_group_nodeinfo); + fstatus = OMGT_STATUS_SUCCESS; + } + +done: + // iba_pa_query_port_fabric_info will have allocated a result buffer + // we must free the buffer when we are done with it + omgt_free_query_result_buffer(query_results); + return (fstatus); + +fail: + fstatus = OMGT_STATUS_ERROR; + goto done; +} + +/** + * Release group node info + * + * @param pm_group_nodeinfo Pointer to pointer to the group nodeinfo to free. + * + * @return + * None + */ +void +omgt_pa_release_group_nodeinfo( + STL_PA_GROUP_NODEINFO_RSP **pm_group_nodeinfo + ) +{ + if (pm_group_nodeinfo && *pm_group_nodeinfo) + { + MemoryDeallocate(*pm_group_nodeinfo); + *pm_group_nodeinfo = NULL; + } +} + +/** + * Get group link info + * + * @param port Port to operate on. + * @param pm_image_id_query Image ID of group config to get. + * @param group_name Pointer to group name + * @param inputLid input LID + * @param inputPort input Port + * @param pm_image_id_resp Pointer to image ID of group info returned. + * @param pm_group_config Pointer to group config to fill. Upon successful return, a memory to + * contain the group config is allocated. The caller must call + * omgt_pa_release_group_config to free the memory later. + * + * @return + * OMGT_STATUS_SUCCESS - Get successful + * OMGT_STATUS_ERROR - Error + */ +OMGT_STATUS_T +omgt_pa_get_group_linkinfo( + struct omgt_port *port, + STL_PA_IMAGE_ID_DATA pm_image_id_query, + char *group_name, + STL_LID inputLid, + uint8 inputPort, + STL_PA_IMAGE_ID_DATA *pm_image_id_resp, + uint32 *pNum_links, + STL_PA_GROUP_LINKINFO_RSP **pm_group_linkinfo + ) +{ + OMGT_STATUS_T fstatus = OMGT_STATUS_ERROR; + uint32 num_links; + uint32 size_group_linkinfo; + STL_PA_IMAGE_ID_DATA image_id = pm_image_id_query; + OMGT_QUERY query; + PQUERY_RESULT_VALUES query_results = NULL; + STL_PA_GROUP_LINKINFO_RESULTS *p; + + // Validate the parameters and state + if (!port || !group_name || !pm_group_linkinfo || *pm_group_linkinfo) + { + OMGT_OUTPUT_ERROR(port, "invalid params or state\n"); + return (fstatus); + } + + memset(&query, 0, sizeof(query)); // initialize reserved fields + query.InputType = InputTypeNoInput; + query.OutputType = OutputTypePaTableRecord; + + OMGT_DBGPRINT(port, "Getting Group Link Info...\n"); + OMGT_DBGPRINT(port, "Query: Input=%s, Output=%s\n", + iba_pa_query_input_type_msg(query.InputType), + iba_pa_query_result_type_msg(query.OutputType)); + + fstatus = iba_pa_multi_mad_group_linkinfo_response_query( + port, &query, group_name, inputLid, inputPort, &query_results, &image_id ); + + if (!query_results) + { + OMGT_DBGPRINT(port, "PA GroupLinkInfo query Failed: %s\n", + iba_fstatus_msg(fstatus) ); + goto fail; + } + else if (query_results->Status != FSUCCESS) + { + OMGT_DBGPRINT(port, "PA GroupLinkInfo query Failed: %s MadStatus 0x%X: %s\n", + iba_fstatus_msg(query_results->Status), port->pa_mad_status, + iba_pa_mad_status_msg(port) ); + goto fail; + } + else if (query_results->ResultDataSize == 0) + { + OMGT_DBGPRINT(port, "No Records Returned\n"); + *pNum_links = 0; + fstatus = OMGT_STATUS_SUCCESS; + goto done; + } + else + { + p = (STL_PA_GROUP_LINKINFO_RESULTS*)query_results->QueryResult; + + // TBD remove some of these after additional MAD testing + OMGT_DBGPRINT(port, "MadStatus 0x%X: %s\n", port->pa_mad_status, + iba_pa_mad_status_msg(port) ); + OMGT_DBGPRINT(port, "%d Bytes Returned\n", query_results->ResultDataSize); + OMGT_DBGPRINT(port, "PA Multiple MAD Response for GroupLinkInfo group %s:\n", + group_name ); + OMGT_DBGPRINT(port, "NumGroupLinkInfoRecords = %d\n", + (int)p->NumGroupLinkInfoRecords ); + + num_links = p->NumGroupLinkInfoRecords; + *pNum_links = num_links; + size_group_linkinfo = sizeof(STL_PA_GROUP_LINKINFO_RSP) * num_links; + + if ( !( *pm_group_linkinfo = MemoryAllocate2AndClear( size_group_linkinfo, + IBA_MEM_FLAG_PREMPTABLE, OMGT_MEMORY_TAG ) ) ) + { + OMGT_OUTPUT_ERROR(port, "can not allocate memory\n"); + goto fail; + } + + OMGT_DBGPRINT(port, "\tname:%s, links:%u\n", + group_name, + (unsigned int)num_links ); + + memcpy(*pm_group_linkinfo, p->GroupLinkInfoRecords, size_group_linkinfo); + fstatus = OMGT_STATUS_SUCCESS; + } + +done: + // iba_pa_query_port_fabric_info will have allocated a result buffer + // we must free the buffer when we are done with it + omgt_free_query_result_buffer(query_results); + return (fstatus); + +fail: + fstatus = OMGT_STATUS_ERROR; + goto done; +} + +/** + * Release group link info + * + * @param port Port to operate on. + * @param pm_group_nodeinfo Pointer to pointer to the group nodeinfo to free. + * + * @return + * None + */ +void +omgt_pa_release_group_linkinfo( + STL_PA_GROUP_LINKINFO_RSP **pm_group_linkinfo + ) +{ + if (pm_group_linkinfo && *pm_group_linkinfo) + { + MemoryDeallocate(*pm_group_linkinfo); + *pm_group_linkinfo = NULL; + } +} + +/* Get VF config info + * + * @param port Port to operate on + * @param pm_image_id_query Image ID of VF config to get. + * @param vf_name Pointer to VF name. + * @param pm_image_id_resp Pointer to image ID of VF info returned. + * @param pm_vf_config Pointer to VF config to fill. Upon successful return, a memory to + * contain the VF config is allocated. The caller must call + * omgt_pa_release_vf_config to free the memory later. + * + * @return + * OMGT_STATUS_SUCCESS - Get successful + * OMGT_STATUS_ERROR - Error + */ +OMGT_STATUS_T +omgt_pa_get_vf_config( + struct omgt_port *port, + STL_PA_IMAGE_ID_DATA pm_image_id_query, + char *vf_name, + STL_PA_IMAGE_ID_DATA *pm_image_id_resp, + uint32 *pNum_ports, + STL_PA_VF_CFG_RSP **pm_vf_config + ) +{ + OMGT_STATUS_T fstatus = OMGT_STATUS_ERROR; + uint32 num_ports; + uint32 size_vf_config; + STL_PA_IMAGE_ID_DATA image_id = pm_image_id_query; + OMGT_QUERY query; + PQUERY_RESULT_VALUES query_results = NULL; + STL_PA_VF_CONFIG_RESULTS *p; + + // Validate the parameters and state + if (!port || !vf_name || !pm_vf_config || *pm_vf_config) + { + OMGT_OUTPUT_ERROR(port, "invalid params or state\n"); + return (fstatus); + } + + memset(&query, 0, sizeof(query)); // initialize reserved fields + query.InputType = InputTypeNoInput; + query.OutputType = OutputTypePaTableRecord; + + OMGT_DBGPRINT(port, "Getting Group Config...\n"); + OMGT_DBGPRINT(port, "Query: Input=%s, Output=%s\n", + iba_pa_query_input_type_msg(query.InputType), + iba_pa_query_result_type_msg(query.OutputType)); + + fstatus = iba_pa_multi_mad_vf_config_response_query( + port, &query, vf_name, &query_results, &image_id ); + + if (!query_results) + { + OMGT_DBGPRINT(port, "PA VFConfig query Failed: %s\n", + iba_fstatus_msg(fstatus) ); + goto fail; + } + else if (query_results->Status != FSUCCESS) + { + OMGT_DBGPRINT(port, "PA VFConfig query Failed: %s MadStatus 0x%X: %s\n", + iba_fstatus_msg(query_results->Status), port->pa_mad_status, + iba_pa_mad_status_msg(port) ); + goto fail; + } + else if (query_results->ResultDataSize == 0) + { + OMGT_DBGPRINT(port, "No Records Returned\n"); + *pNum_ports = 0; + fstatus = OMGT_STATUS_SUCCESS; + goto done; + } + else + { + p = (STL_PA_VF_CONFIG_RESULTS*)query_results->QueryResult; + + // TBD remove some of these after additional MAD testing + OMGT_DBGPRINT(port, "MadStatus 0x%X: %s\n", port->pa_mad_status, + iba_pa_mad_status_msg(port) ); + OMGT_DBGPRINT(port, "%d Bytes Returned\n", query_results->ResultDataSize); + OMGT_DBGPRINT(port, "PA Multiple MAD Response for VFConfig group %s:\n", + vf_name ); + OMGT_DBGPRINT(port, "NumVFConfigRecords = %d\n", + (int)p->NumVFConfigRecords ); + + num_ports = p->NumVFConfigRecords < MAX_PORTS_LIST ? + p->NumVFConfigRecords : MAX_PORTS_LIST; + *pNum_ports = num_ports; + size_vf_config = sizeof(STL_PA_VF_CFG_RSP) * num_ports; + + if ( !( *pm_vf_config = MemoryAllocate2AndClear( size_vf_config, + IBA_MEM_FLAG_PREMPTABLE, OMGT_MEMORY_TAG ) ) ) + { + OMGT_OUTPUT_ERROR(port, "can not allocate memory\n"); + goto fail; + } + + OMGT_DBGPRINT(port, "\tname:%s, ports:%u\n", + vf_name, + (unsigned int)num_ports ); + + memcpy(*pm_vf_config, p->VFConfigRecords, size_vf_config); + fstatus = OMGT_STATUS_SUCCESS; + } + +done: + // iba_pa_query_port_fabric_info will have allocated a result buffer + // we must free the buffer when we are done with it + omgt_free_query_result_buffer(query_results); + return (fstatus); + +fail: + fstatus = OMGT_STATUS_ERROR; + goto done; +} + + +/* Release VF config info + * + * @param port Port to operate on. + * @param pm_vf_config Pointer to pointer to the VF config to free + * + * @return + * None + */ +void +omgt_pa_release_vf_config( + STL_PA_VF_CFG_RSP **pm_vf_config + ) +{ + if (pm_vf_config && *pm_vf_config) + { + MemoryDeallocate(*pm_vf_config); + *pm_vf_config = NULL; + } +} + +/** + * Get group focus portlist + * + * @param port Port to operate on. + * @param pm_image_id_query Image ID of group focus portlist to get. + * @param group_name Pointer to group name. + * @param select Select value for focus portlist. + * @param start Start index value of portlist + * @param range Index range of portlist. + * @param pm_image_id_resp Pointer to image ID of group focus portlist returned. + * @param pm_group_focus Pointer to pointer to focus portlist to fill. Upon + * successful return, a memory to contain the group focus + * portlist is allocated. The caller must call + * omgt_pa_release_group_focus to free the memory later. + * + * @return + * OMGT_STATUS_SUCCESS - Get successful + * OMGT_STATUS_ERROR - Error + */ + +OMGT_STATUS_T +omgt_pa_get_group_focus( + struct omgt_port *port, + STL_PA_IMAGE_ID_DATA pm_image_id_query, + char *group_name, + uint32 select, + uint32 start, + uint32 range, + STL_PA_IMAGE_ID_DATA *pm_image_id_resp, + uint32 *pNum_ports, + STL_FOCUS_PORTS_RSP **pm_group_focus + ) +{ + OMGT_STATUS_T fstatus = OMGT_STATUS_ERROR; + uint32 num_ports; + uint32 size_group_focus; + STL_PA_IMAGE_ID_DATA image_id = pm_image_id_query; + OMGT_QUERY query; + PQUERY_RESULT_VALUES query_results = NULL; + STL_PA_FOCUS_PORTS_RESULTS *p; + + // Validate the parameters and state + if (!port || + !group_name || + (range > MAX_PORTS_LIST) || + !pm_group_focus || *pm_group_focus) + { + OMGT_OUTPUT_ERROR(port, "invalid params or state\n"); + return (fstatus); + } + + memset(&query, 0, sizeof(query)); // initialize reserved fields + query.InputType = InputTypeNoInput; + query.OutputType = OutputTypePaTableRecord; + + OMGT_DBGPRINT(port, "Getting Group Focus...\n"); + OMGT_DBGPRINT(port, "Query: Input=%s, Output=%s\n", + iba_pa_query_input_type_msg(query.InputType), + iba_pa_query_result_type_msg(query.OutputType)); + + fstatus = iba_pa_multi_mad_focus_ports_response_query(port, &query, + group_name, select, start, range, &query_results, &image_id ); + + if (!query_results) + { + OMGT_DBGPRINT(port, "PA Group Focus query Failed: %s\n", + iba_fstatus_msg(fstatus) ); + goto fail; + } + else if (query_results->Status != FSUCCESS) + { + OMGT_DBGPRINT(port, "PA Group Focus query Failed: %s MadStatus 0x%X: %s\n", + iba_fstatus_msg(query_results->Status), port->pa_mad_status, + iba_pa_mad_status_msg(port) ); + goto fail; + } + else if (query_results->ResultDataSize == 0) + { + OMGT_DBGPRINT(port, "No Records Returned\n"); + *pNum_ports = 0; + fstatus = OMGT_STATUS_SUCCESS; + goto done; + } + else + { + p = (STL_PA_FOCUS_PORTS_RESULTS*)query_results->QueryResult; + + // TBD remove some of these after additional MAD testing + OMGT_DBGPRINT(port, "MadStatus 0x%X: %s\n", port->pa_mad_status, + iba_pa_mad_status_msg(port) ); + OMGT_DBGPRINT(port, "%d Bytes Returned\n", query_results->ResultDataSize); + OMGT_DBGPRINT(port, "PA Multiple MAD Response for Focus portlist group %s:\n", + group_name ); + OMGT_DBGPRINT(port, "NumFocusPortsRecords = %d\n", + (int)p->NumFocusPortsRecords ); + + num_ports = p->NumFocusPortsRecords < range ? + p->NumFocusPortsRecords : range; + + *pNum_ports = num_ports; + size_group_focus = sizeof(STL_FOCUS_PORTS_RSP) * num_ports; + + if ( !( *pm_group_focus = MemoryAllocate2AndClear( size_group_focus, + IBA_MEM_FLAG_PREMPTABLE, OMGT_MEMORY_TAG ) ) ) + { + OMGT_OUTPUT_ERROR(port, "can not allocate memory\n"); + goto fail; + } + + OMGT_DBGPRINT(port, "\tname:%s, ports:%u\n", + group_name, + (unsigned int)num_ports ); + + memcpy(*pm_group_focus, p->FocusPortsRecords, size_group_focus); + fstatus = OMGT_STATUS_SUCCESS; + } + +done: + // iba_pa_query_port_fabric_info will have allocated a result buffer + // we must free the buffer when we are done with it + omgt_free_query_result_buffer(query_results); + return (fstatus); + +fail: + fstatus = OMGT_STATUS_ERROR; + goto done; +} + +/** + * Release group focus portlist + * + * @param port Port to operate on. + * @param pm_group_config Pointer to pointer to the group focus portlist to free. + * + * @return + * None + */ +void +omgt_pa_release_group_focus( + STL_FOCUS_PORTS_RSP **pm_group_focus + ) +{ + if (pm_group_focus && *pm_group_focus) + { + MemoryDeallocate(*pm_group_focus); + *pm_group_focus = NULL; + } +} + + +/* + * Get VF focus portlist + * + * @param port Port to operate on. + * @param pm_image_id_query Image ID of vf focus portlist to get. + * @param vf_name Pointer to vf name. + * @param select Select value for focus portlist. + * @param start Start index value of portlist + * @param range Index range of portlist. + * @param pm_image_id_resp Pointer to image ID of group focus portlist returned. + * @param pm_vf_focus Pointer to pointer to focus portlist to fill. Upon + * successful return, a memory to contain the group focus + * portlist is allocated. The caller must call + * omgt_pa_release_vf_focus to free the memory later. + * + * @return + * OMGT_STATUS_SUCCESS - Get successful + * OMGT_STATUS_ERROR - Error + */ + +OMGT_STATUS_T +omgt_pa_get_vf_focus( + struct omgt_port *port, + STL_PA_IMAGE_ID_DATA pm_image_id_query, + char *vf_name, + uint32 select, + uint32 start, + uint32 range, + STL_PA_IMAGE_ID_DATA *pm_image_id_resp, + uint32 *pNum_ports, + STL_PA_VF_FOCUS_PORTS_RSP **pm_vf_focus + ) +{ + OMGT_STATUS_T fstatus = OMGT_STATUS_ERROR; + uint32 num_ports; + uint32 size_vf_focus; + STL_PA_IMAGE_ID_DATA image_id = pm_image_id_query; + OMGT_QUERY query; + PQUERY_RESULT_VALUES query_results = NULL; + STL_PA_VF_FOCUS_PORTS_RESULTS *p; + + // Validate the parameters and state + if (!port || + !vf_name || + (range > MAX_PORTS_LIST) || + !pm_vf_focus || *pm_vf_focus) + { + OMGT_OUTPUT_ERROR(port, "invalid params or state\n"); + return (fstatus); + } + + memset(&query, 0, sizeof(query)); // initialize reserved fields + query.InputType = InputTypeNoInput; + query.OutputType = OutputTypePaTableRecord; + + OMGT_DBGPRINT(port, "Getting VF Focus...\n"); + OMGT_DBGPRINT(port, "Query: Input=%s, Output=%s\n", + iba_pa_query_input_type_msg(query.InputType), + iba_pa_query_result_type_msg(query.OutputType)); + + fstatus = iba_pa_multi_mad_vf_focus_ports_response_query(port, &query, + vf_name, select, start, range, &query_results, &image_id); + + if (!query_results) + { + OMGT_DBGPRINT(port, "PA VF Focus query Failed: %s\n", + iba_fstatus_msg(fstatus) ); + goto fail; + } + else if (query_results->Status != FSUCCESS) + { + OMGT_DBGPRINT(port, "PA VF Focus query Failed: %s MadStatus 0x%X: %s\n", + iba_fstatus_msg(query_results->Status), port->pa_mad_status, + iba_pa_mad_status_msg(port) ); + goto fail; + } + else if (query_results->ResultDataSize == 0) + { + OMGT_DBGPRINT(port, "No Records Returned\n"); + *pNum_ports = 0; + fstatus = OMGT_STATUS_SUCCESS; + goto done; + } + else + { + p = (STL_PA_VF_FOCUS_PORTS_RESULTS*)query_results->QueryResult; + + // TBD remove some of these after additional MAD testing + OMGT_DBGPRINT(port, " MadStatus 0x%X: %s\n", port->pa_mad_status, + iba_pa_mad_status_msg(port) ); + OMGT_DBGPRINT(port, "%d Bytes Returned\n", query_results->ResultDataSize); + OMGT_DBGPRINT(port, "PA Multiple MAD Response for Focus portlist vf %s:\n", + vf_name ); + OMGT_DBGPRINT(port, "NumVFFocusPortsRecords = %d\n", + (int)p->NumVFFocusPortsRecords ); + + num_ports = p->NumVFFocusPortsRecords < range ? + p->NumVFFocusPortsRecords : range; + *pNum_ports = num_ports; + size_vf_focus = sizeof(STL_PA_VF_FOCUS_PORTS_RSP) * num_ports; + + if ( !( *pm_vf_focus = MemoryAllocate2AndClear( size_vf_focus, + IBA_MEM_FLAG_PREMPTABLE, OMGT_MEMORY_TAG ) ) ) + { + OMGT_OUTPUT_ERROR(port, "can not allocate memory\n"); + goto fail; + } + + OMGT_DBGPRINT(port, "\tname:%s, ports:%u\n", + vf_name, + (unsigned int)num_ports ); + + memcpy(*pm_vf_focus, p->FocusPortsRecords, size_vf_focus); + fstatus = OMGT_STATUS_SUCCESS; + } + +done: + // iba_pa_query_port_fabric_info will have allocated a result buffer + // we must free the buffer when we are done with it + omgt_free_query_result_buffer(query_results); + return (fstatus); + +fail: + fstatus = OMGT_STATUS_ERROR; + goto done; +} + + +/* + * Release vf focus portlist + * + * @param port Port to operate on. + * @param pm_vf_focus Pointer to pointer to the vf focus portlist to free. + * + * @return + * None + */ +void +omgt_pa_release_vf_focus( + STL_PA_VF_FOCUS_PORTS_RSP **pm_vf_focus + ) +{ + if (pm_vf_focus && *pm_vf_focus) + { + MemoryDeallocate(*pm_vf_focus); + *pm_vf_focus = NULL; + } +} + +/** + * Get port statistics (counters). Supports 32 bit lids + * + * @param port Port to operate on. + * @param pm_image_id_query Image ID of port counters to get. + * @param lid LID of node. + * @param port_num Port number. + * @param pm_image_id_resp Pointer to image ID of port counters returned. + * @param port_counters Pointer to port counters to fill. + * @param flags Pointer to flags + * @param delta 1 for delta counters, 0 for raw image counters. + * @param user_cntrs 1 for running counters, 0 for image counters. (delta must be 0) + * + * @return + * OMGT_STATUS_SUCCESS - Get successful + * OMGT_STATUS_ERROR - Error + */ +OMGT_STATUS_T +omgt_pa_get_port_stats2( + struct omgt_port *port, + STL_PA_IMAGE_ID_DATA pm_image_id_query, + STL_LID lid, + uint8 port_num, + STL_PA_IMAGE_ID_DATA *pm_image_id_resp, + STL_PORT_COUNTERS_DATA *port_counters, + uint32 *flags, + uint32 delta, + uint32 user_cntrs + ) +{ + OMGT_STATUS_T fstatus = OMGT_STATUS_ERROR; + STL_PA_IMAGE_ID_DATA image_id = pm_image_id_query; + STL_PORT_COUNTERS_DATA *response; + + // Validate the parameters and state + if (!port || !port_counters) + { + OMGT_OUTPUT_ERROR(port, "invalid params or state\n"); + return (fstatus); + } + + OMGT_DBGPRINT(port, "Getting Port Counters...\n"); + + if ( ( response = iba_pa_single_mad_port_counters_response_query( + port, lid, port_num, delta, user_cntrs, &image_id ) ) != NULL ) + { + // TBD remove some of these after additional MAD testing + OMGT_DBGPRINT(port, "%s Controlled Port Counters (%s) Response for nodeLid 0x%X portNumber %d%s%s:\n", + (user_cntrs?"User":"PM"), (delta?"Delta":"Total"), lid, port_num, + response->flags & STL_PA_PC_FLAG_UNEXPECTED_CLEAR?" (Unexpected Clear)":"", + response->flags & STL_PA_PC_FLAG_CLEAR_FAIL?" (Clear Unsuccessful)":"" ); + OMGT_DBGPRINT(port, "\tXmitData = %" PRIu64 "\n", response->portXmitData); + OMGT_DBGPRINT(port, "\tRcvData = %" PRIu64 "\n", response->portRcvData); + OMGT_DBGPRINT(port, "\tXmitPkts = %" PRIu64 "\n", response->portXmitPkts); + OMGT_DBGPRINT(port, "\tRcvPkts = %" PRIu64 "\n", response->portRcvPkts); + OMGT_DBGPRINT(port, "\tMulticastXmitPkts = %" PRIu64 "\n", response->portMulticastXmitPkts); + OMGT_DBGPRINT(port, "\tMulticastRcvPkts = %" PRIu64 "\n", response->portMulticastRcvPkts); + + OMGT_DBGPRINT(port, "\tLinkQualityIndicator = %u\n", response->lq.s.linkQualityIndicator); + OMGT_DBGPRINT(port, "\tUncorrectableErrors = %u\n", response->uncorrectableErrors); // 8 bit + OMGT_DBGPRINT(port, "\tLinkDowned = %u\n", response->linkDowned); // 32 bit + OMGT_DBGPRINT(port, "\tNumLanesDown = %u\n", response->lq.s.numLanesDown); + OMGT_DBGPRINT(port, "\tRcvErrors = %"PRIu64"\n", response->portRcvErrors); + OMGT_DBGPRINT(port, "\tExcessiveBufferOverruns = %"PRIu64"\n", + response->excessiveBufferOverruns ); + OMGT_DBGPRINT(port, "\tFMConfigErrors = %"PRIu64"\n", + response->fmConfigErrors ); + OMGT_DBGPRINT(port, "\tLinkErrorRecovery = %u\n", response->linkErrorRecovery); // 32 bit + OMGT_DBGPRINT(port, "\tLocalLinkIntegrityErrors = %"PRIu64"\n", + response->localLinkIntegrityErrors ); + OMGT_DBGPRINT(port, "\tRcvRemotePhysicalErrors = %"PRIu64"\n", + response->portRcvRemotePhysicalErrors); + OMGT_DBGPRINT(port, "\tXmitConstraintErrors = %"PRIu64"\n", + response->portXmitConstraintErrors ); + OMGT_DBGPRINT(port, "\tRcvConstraintErrors = %"PRIu64"\n", + response->portRcvConstraintErrors ); + OMGT_DBGPRINT(port, "\tRcvSwitchRelayErrors = %"PRIu64"\n", + response->portRcvSwitchRelayErrors); + OMGT_DBGPRINT(port, "\tXmitDiscards = %"PRIu64"\n", response->portXmitDiscards); + OMGT_DBGPRINT(port, "\tCongDiscards = %"PRIu64"\n", + response->swPortCongestion); + OMGT_DBGPRINT(port, "\tRcvFECN = %"PRIu64"\n", response->portRcvFECN); + OMGT_DBGPRINT(port, "\tRcvBECN = %"PRIu64"\n", response->portRcvBECN); + OMGT_DBGPRINT(port, "\tMarkFECN = %"PRIu64"\n", response->portMarkFECN); + OMGT_DBGPRINT(port, "\tXmitTimeCong = %"PRIu64"\n", response->portXmitTimeCong); + OMGT_DBGPRINT(port, "\tXmitWait = %"PRIu64"\n", response->portXmitWait); + OMGT_DBGPRINT(port, "\tXmitWastedBW = %"PRIu64"\n", response->portXmitWastedBW); + OMGT_DBGPRINT(port, "\tXmitWaitData = %"PRIu64"\n", response->portXmitWaitData); + OMGT_DBGPRINT(port, "\tRcvBubble = %"PRIu64"\n", response->portRcvBubble); + if (pm_image_id_resp) + *pm_image_id_resp = response->imageId; + if (flags) + *flags = response->flags; + + memcpy(port_counters, response, sizeof(*port_counters)); + MemoryDeallocate(response); + fstatus = OMGT_STATUS_SUCCESS; + } + else + OMGT_DBGPRINT(port, "Got NULL response - FAILED\n"); + + return (fstatus); +} + +/* Deprecated. Use omgt_get_vf_port_stats2 +* This Should be removed in favor of the version that supports 32bit lids +* when opamgt public library decides breaking compatibility is acceptable. +*/ +OMGT_STATUS_T +omgt_pa_get_port_stats( + struct omgt_port *port, + STL_PA_IMAGE_ID_DATA pm_image_id_query, + uint16_t lid, + uint8 port_num, + STL_PA_IMAGE_ID_DATA *pm_image_id_resp, + STL_PORT_COUNTERS_DATA *port_counters, + uint32 *flags, + uint32 delta, + uint32 user_cntrs + ) +{ + OMGT_DBGPRINT(port, "omgt_pa_get_port_stats is deprecated. Please use omgt_pa_get_port_stats2\n"); + return omgt_pa_get_port_stats2(port, pm_image_id_query, lid, port_num, pm_image_id_resp, port_counters, flags, delta, user_cntrs); +} + + + +/** + * Clear specified port counters for specified port + * + * @param port Port to operate on. + * @param pm_image_id_query Image ID of port counters to clear. + * @param lid LID of port. + * @param port_num Port number. + * @param selct_flags Port's counters to clear. + * + * @return + * FSUCCESS - Clear successful + * FERROR - Error + */ +FSTATUS +pa_client_clr_port_counters( + struct omgt_port *port, + STL_PA_IMAGE_ID_DATA pm_image_id_query, + STL_LID lid, + uint8 port_num, + uint32 select_flag + ) +{ + FSTATUS fstatus = FERROR; + STL_CLR_PORT_COUNTERS_DATA *response; + + // Validate the parameters and state + if (!port) + { + OMGT_OUTPUT_ERROR(port, "invalid params or state\n"); + return (fstatus); + } + + if ( ( response = + iba_pa_single_mad_clr_port_counters_response_query( + port, lid, port_num, select_flag ) ) ) + { + MemoryDeallocate(response); + fstatus = FSUCCESS; + } + + return (fstatus); +} + +/** + * Get vf port statistics (counters). Supports 32 bit lids. + * + * @param port Port to operate on. + * @param pm_image_id_query Image ID of port counters to get. + * @param vf_name Pointer to VF name. + * @param lid LID of node. + * @param port_num Port number. + * @param pm_image_id_resp Pointer to image ID of port counters returned. + * @param vf_port_counters Pointer to vf port counters to fill. + * @param flags Pointer to flags + * @param delta 1 for delta counters, 0 for raw image counters. + * @param user_cntrs 1 for running counters, 0 for image counters. (delta must be 0) + * + * @return + * OMGT_STATUS_SUCCESS - Get successful + * OMGT_STATUS_ERROR - Error + */ +OMGT_STATUS_T +omgt_pa_get_vf_port_stats2( + struct omgt_port *port, + STL_PA_IMAGE_ID_DATA pm_image_id_query, + char *vf_name, + STL_LID lid, + uint8 port_num, + STL_PA_IMAGE_ID_DATA *pm_image_id_resp, + STL_PA_VF_PORT_COUNTERS_DATA *vf_port_counters, + uint32 *flags, + uint32 delta, + uint32 user_cntrs + ) +{ + OMGT_STATUS_T fstatus = OMGT_STATUS_ERROR; + STL_PA_IMAGE_ID_DATA image_id = pm_image_id_query; + STL_PA_VF_PORT_COUNTERS_DATA *response; + + // Validate the parameters and state + if (!port || !vf_port_counters) + { + OMGT_OUTPUT_ERROR(port, "invalid params or state\n"); + return (fstatus); + } + + OMGT_DBGPRINT(port, "Getting Port Counters...\n"); + + if ( ( response = iba_pa_single_mad_vf_port_counters_response_query( + port, lid, port_num, delta, user_cntrs, vf_name, &image_id ) ) != NULL ) + { + // TBD remove some of these after additional MAD testing + OMGT_DBGPRINT(port, "%s Controlled VF Port Counters (%s) Response for nodeLid 0x%X portNumber %d%s%s:\n", + (user_cntrs?"User":"PM"), (delta?"Delta":"Total"), lid, port_num, + response->flags & STL_PA_PC_FLAG_UNEXPECTED_CLEAR?" (Unexpected Clear)":"", + response->flags & STL_PA_PC_FLAG_CLEAR_FAIL?" (Clear Unsuccessful)":"" ); + OMGT_DBGPRINT(port, "\tvfName = %s\n", response->vfName); + OMGT_DBGPRINT(port, "\tXmitData = %" PRIu64 "\n", response->portVFXmitData); + OMGT_DBGPRINT(port, "\tRcvData = %" PRIu64 "\n", response->portVFRcvData); + OMGT_DBGPRINT(port, "\tXmitPkts = %" PRIu64 "\n", response->portVFXmitPkts); + OMGT_DBGPRINT(port, "\tRcvPkts = %" PRIu64 "\n", response->portVFRcvPkts); + OMGT_DBGPRINT(port, "\tXmitDiscards = %"PRIu64"\n", response->portVFXmitDiscards); + OMGT_DBGPRINT(port, "\tCongDiscards = %"PRIu64"\n", response->swPortVFCongestion); + OMGT_DBGPRINT(port, "\tRcvFECN = %"PRIu64"\n", response->portVFRcvFECN); + OMGT_DBGPRINT(port, "\tRcvBECN = %"PRIu64"\n", response->portVFRcvBECN); + OMGT_DBGPRINT(port, "\tMarkFECN = %"PRIu64"\n", response->portVFMarkFECN); + OMGT_DBGPRINT(port, "\tXmitTimeCong = %"PRIu64"\n", response->portVFXmitTimeCong); + OMGT_DBGPRINT(port, "\tXmitWait = %"PRIu64"\n", response->portVFXmitWait); + OMGT_DBGPRINT(port, "\tXmitWastedBW = %"PRIu64"\n", response->portVFXmitWastedBW); + OMGT_DBGPRINT(port, "\tXmitWaitData = %"PRIu64"\n", response->portVFXmitWaitData); + OMGT_DBGPRINT(port, "\tRcvBubble = %"PRIu64"\n", response->portVFRcvBubble); + if (pm_image_id_resp) + *pm_image_id_resp = response->imageId; + if (flags) + *flags = response->flags; + + memcpy(vf_port_counters, response, sizeof(*vf_port_counters)); + MemoryDeallocate(response); + fstatus = OMGT_STATUS_SUCCESS; + } + else + OMGT_DBGPRINT(port, "Got NULL response - FAILED\n"); + + return (fstatus); +} + +/* Deprecated. Use omgt_get_vf_port_stats2 +* This Should be removed in favor of the version that supports 32bit lids +* when opamgt public library decides breaking compatibility is acceptable. +*/ + +OMGT_STATUS_T +omgt_pa_get_vf_port_stats( + struct omgt_port *port, + STL_PA_IMAGE_ID_DATA pm_image_id_query, + char *vf_name, + uint16_t lid, + uint8 port_num, + STL_PA_IMAGE_ID_DATA *pm_image_id_resp, + STL_PA_VF_PORT_COUNTERS_DATA *vf_port_counters, + uint32 *flags, + uint32 delta, + uint32 user_cntrs + ) +{ + OMGT_DBGPRINT(port, "omgt_pa_get_vf_port_stats is deprecated. Please use omgt_pa_get_vf_port_stats2\n"); + return omgt_pa_get_vf_port_stats2(port, pm_image_id_query, vf_name, lid, port_num, pm_image_id_resp, vf_port_counters, flags, delta, user_cntrs); +} + +/** + * Freeze specified image + * + * @param port Port to operate on. + * @param pm_image_id_query Image ID of image to free. + * @param pm_image_id_resp Pointer to image ID of image frozen. + * + * @return + * OMGT_STATUS_SUCCESS - Freeze successful + * OMGT_STATUS_ERROR - Error + */ +OMGT_STATUS_T +omgt_pa_freeze_image( + struct omgt_port *port, + STL_PA_IMAGE_ID_DATA pm_image_id_query, + STL_PA_IMAGE_ID_DATA *pm_image_id_resp + ) +{ + OMGT_STATUS_T fstatus = OMGT_STATUS_ERROR; + STL_PA_IMAGE_ID_DATA image_id = pm_image_id_query; + STL_PA_IMAGE_ID_DATA *response; + + // Validate the parameters and state + if (!port) + { + OMGT_OUTPUT_ERROR(port, "invalid params or state\n"); + return (fstatus); + } + + OMGT_DBGPRINT(port, "QueryImageNum = 0x%" PRIX64 " Offset = %d\n", + pm_image_id_query.imageNumber, (int)pm_image_id_query.imageOffset ); + + if ( ( response = + iba_pa_single_mad_freeze_image_response_query( + port, &image_id ) ) != NULL ) + { + OMGT_DBGPRINT(port, "RespImageNum = 0x%" PRIX64 " Offset = %d\n", + response->imageNumber, (int)response->imageOffset ); + + if (pm_image_id_resp) + *pm_image_id_resp = *response; + + MemoryDeallocate(response); + fstatus = OMGT_STATUS_SUCCESS; + } + else + OMGT_DBGPRINT(port, "Got NULL response - FAILED\n"); + + return (fstatus); +} + +/** + * Move freeze of image 1 to image 2 + * + * @param port Port to operate on. + * @param pm_image_id_query Image ID of frozen image 1. + * @param pm_image_id_resp Pointer to image ID of image2. + * + * @return + * OMGT_STATUS_SUCCESS - Move image Freeze successful + * OMGT_STATUS_UNAVAILABLE - Image 2 unavailable freeze + * OMGT_STATUS_ERROR - Error + */ +OMGT_STATUS_T +omgt_pa_move_image_freeze( + struct omgt_port *port, + STL_PA_IMAGE_ID_DATA pm_image_id1, + STL_PA_IMAGE_ID_DATA *pm_image_id2 + ) +{ + FSTATUS fstatus = OMGT_STATUS_ERROR; + STL_MOVE_FREEZE_DATA request; + STL_MOVE_FREEZE_DATA *response; + + // Validate the parameters and state + if (!port || !pm_image_id2) + { + OMGT_OUTPUT_ERROR(port, "invalid params or state\n"); + return (fstatus); + } + + OMGT_DBGPRINT(port, "Img1ImageNum = 0x%" PRIX64 " Offset = %d\n", + pm_image_id1.imageNumber, (int)pm_image_id1.imageOffset ); + OMGT_DBGPRINT(port, "Img2ImageNum = 0x%" PRIX64 " Offset = %d\n", + pm_image_id2->imageNumber, (int)pm_image_id2->imageOffset ); + request.oldFreezeImage = pm_image_id1; + request.newFreezeImage = *pm_image_id2; + + if ( ( response = + iba_pa_single_mad_move_freeze_response_query( + port, &request ) ) != NULL ) + { + OMGT_DBGPRINT(port, "RespOldImageNum = 0x%" PRIX64 " Offset = %d\n", + response->oldFreezeImage.imageNumber, response->oldFreezeImage.imageOffset ); + OMGT_DBGPRINT(port, "RespNewImageNum = 0x%" PRIX64 " Offset = %d\n", + response->newFreezeImage.imageNumber, response->newFreezeImage.imageOffset ); + + *pm_image_id2 = response->newFreezeImage; + fstatus = OMGT_STATUS_SUCCESS; + MemoryDeallocate(response); + } + else + { + OMGT_DBGPRINT(port, "Got NULL response - UNAVAILABLE\n"); + fstatus = OMGT_STATUS_UNAVAILABLE; + } + + return (fstatus); +} + +/** + * Release specified image. + * + * @param port Port to operate on. + * @param pm_image_id_query Image ID of image to release. + * + * @return + * OMGT_STATUS_SUCCESS - Release successful + * OMGT_STATUS_ERROR - Error + */ +OMGT_STATUS_T +omgt_pa_release_image( + struct omgt_port *port, + STL_PA_IMAGE_ID_DATA pm_image_id_query + ) +{ + OMGT_STATUS_T fstatus = OMGT_STATUS_ERROR; + STL_PA_IMAGE_ID_DATA image_id = pm_image_id_query; + STL_PA_IMAGE_ID_DATA *response; + + // Validate the parameters and state + if (!port) + { + OMGT_OUTPUT_ERROR(port, "invalid params or state\n"); + return (fstatus); + } + + if ( ( response = iba_pa_single_mad_release_image_response_query( + port, &image_id ) ) != NULL ) + { + // TBD remove some of these after additional MAD testing + OMGT_DBGPRINT(port, "QueryImageNum = 0x%" PRIX64 " Offset = %d\n", + pm_image_id_query.imageNumber, (int)pm_image_id_query.imageOffset ); + OMGT_DBGPRINT(port, "RespImageNum = 0x%" PRIX64 " Offset = %d\n", + response->imageNumber, (int)response->imageOffset ); + + MemoryDeallocate(response); + fstatus = OMGT_STATUS_SUCCESS; + } + else + OMGT_DBGPRINT(port, "Got NULL response - FAILED\n"); + + return (fstatus); +} + +/** + * Renew lease of specified image. + * + * @param port Port to operate on. + * @param pm_image_id_query Image ID of image to renew. + * + * @return + * OMGT_STATUS_SUCCESS - Renew successful + * OMGT_STATUS_ERROR - Error + */ +OMGT_STATUS_T +omgt_pa_renew_image( + struct omgt_port *port, + STL_PA_IMAGE_ID_DATA pm_image_id_query + ) +{ + OMGT_STATUS_T fstatus = OMGT_STATUS_ERROR; + STL_PA_IMAGE_ID_DATA image_id = pm_image_id_query; + STL_PA_IMAGE_ID_DATA *response; + + // Validate the parameters and state + if (!port) + { + OMGT_OUTPUT_ERROR(port, "invalid params or state\n"); + return (fstatus); + } + + if ( ( response = iba_pa_single_mad_renew_image_response_query( + port, &image_id ) ) != NULL ) + { + // TBD remove some of these after additional MAD testing + OMGT_DBGPRINT(port, "QueryImageNum = 0x%" PRIX64 " Offset = %d\n", + pm_image_id_query.imageNumber, (int)pm_image_id_query.imageOffset ); + OMGT_DBGPRINT(port, "RespImageNum = 0x%" PRIX64 " Offset = %d\n", + response->imageNumber, (int)response->imageOffset ); + + MemoryDeallocate(response); + fstatus = OMGT_STATUS_SUCCESS; + } + else + OMGT_DBGPRINT(port, "Got NULL response - FAILED\n"); + + return (fstatus); +} + +#endif diff --git a/opamgt/src/opamgt_sa.c b/opamgt/src/opamgt_sa.c new file mode 100644 index 0000000..c5dd907 --- /dev/null +++ b/opamgt/src/opamgt_sa.c @@ -0,0 +1,2998 @@ +/* BEGIN_ICS_COPYRIGHT2 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT2 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +#include +#include +#include +#include +#include + +#define OPAMGT_PRIVATE 1 + +#include "iba/stl_sd.h" +#include "iba/stl_sa_priv.h" +#include "ib_mad.h" +#include "ib_sm_priv.h" +#include "ib_generalServices.h" +#include "ib_utils_openib.h" +#include "opamgt_sa_priv.h" +#include + + +#define STL_TRACE_RECORD_COMP_ENCRYPT_MASK 0x55555555 +#define PATHRECORD_NUMBPATH 32 // max to request given 2 guids + +#define OMGT_NUM_MGMT_CLASSES 4 + +/* TBD get from libibt? */ +static const char * const MadInvalidFieldText[] = { + "Valid Field", // should not be used below + "Unsupported Class or Version", + "Unsupported Method", + "Unsupported Method/Attribute Combination", + "Reserved Invalid Field 4", + "Reserved Invalid Field 5", + "Reserved Invalid Field 6", + "Invalid Attribute or Attribute Modifier" +}; + +/* upper 8 bits of MAD_STATUS_SA_* fields from ib_sa_records.h */ +static const char* const SdSAStatusText[] = { + "Success", // not used by code below + "Insufficient SA Resources", + "Invalid SA Request", + "No SA Records", + "Too Many SA Records", + "Invalid GID in SA Request", + "Insufficient Components in SA Request" +}; + +static const QueryInputString_t InputTypeStringValuePair[] = { + { InputTypeNoInput, "InputTypeNoInput" }, + { InputTypeNodeType, "InputTypeNodeType" }, + { InputTypeSystemImageGuid, "InputTypeSystemImageGuid" }, + { InputTypeNodeGuid, "InputTypeNodeGuid" }, + { InputTypePortGuid, "InputTypePortGuid" }, + { InputTypePortGid, "InputTypePortGid" }, + { InputTypeMcGid, "InputTypeMcGid" }, + { InputTypePortGuidPair, "InputTypePortGuidPair" }, + { InputTypeGidPair, "InputTypeGidPair" }, + { InputTypePathRecord, "InputTypePathRecord" }, + { InputTypePathRecordNetworkOrder, "InputTypePathRecordNetworkOrder" }, + { InputTypeLid, "InputTypeLid" }, + { InputTypePKey, "InputTypePKey" }, + { InputTypeSL, "InputTypeSL" }, + { InputTypeIndex, "InputTypeIndex" }, + { InputTypeServiceId, "InputTypeServiceId" }, + { InputTypeNodeDesc, "InputTypeNodeDesc" }, + { InputTypeServiceRecord, "InputTypeServiceRecord" }, + { InputTypeMcMemberRecord, "InputTypeMcMemberRecord" }, + { InputTypePortGuidList, "InputTypePortGuidList" }, + { InputTypeGidList, "InputTypeGidList" }, + { InputTypeMultiPathRecord, "InputTypeMultiPathRecord" }, + { InputTypeSourceGid, "InputTypeSourceGid" }, + + { InputTypeDeviceGroup, "InputTypeDeviceGroup" }, + { InputTypeNoInput, NULL } // {0, NULL} Must be the last element to terminate the Map +}; +const char* iba_sd_query_input_type_msg(QUERY_INPUT_TYPE code) +{ + int i; + for (i = 0; InputTypeStringValuePair[i].inputTypeStr != NULL; i++) { + if (InputTypeStringValuePair[i].inputType == code) + return InputTypeStringValuePair[i].inputTypeStr; + } + return "Unknown Query Input Type"; +} + +static const QueryOutputString_t OutputTypeStringValuePair[] = { + /* SA query results */ + { OutputTypeSystemImageGuid, "OutputTypeSystemImageGuid" }, + { OutputTypeNodeGuid, "OutputTypeNodeGuid" }, + { OutputTypePortGuid, "OutputTypePortGuid" }, + { OutputTypeLid, "OutputTypeLid" }, + { OutputTypeGid, "OutputTypeGid" }, + { OutputTypeNodeDesc, "OutputTypeNodeDesc" }, + { OutputTypePathRecord, "OutputTypePathRecord" }, + { OutputTypePathRecordNetworkOrder, "OutputTypePathRecordNetworkOrder" }, + { OutputTypeNodeRecord, "OutputTypeNodeRecord" }, + { OutputTypePortInfoRecord, "OutputTypePortInfoRecord" }, + { OutputTypeSMInfoRecord, "OutputTypeSMInfoRecord" }, + { OutputTypeLinkRecord, "OutputTypeLinkRecord" }, + { OutputTypeServiceRecord, "OutputTypeServiceRecord" }, + { OutputTypeMcMemberRecord, "OutputTypeMcMemberRecord" }, + { OutputTypeInformInfoRecord, "OutputTypeInformInfoRecord" }, + { OutputTypeTraceRecord, "OutputTypeTraceRecord" }, + { OutputTypeSwitchInfoRecord, "OutputTypeSwitchInfoRecord" }, + { OutputTypeLinearFDBRecord, "OutputTypeLinearFDBRecord" }, + { OutputTypeRandomFDBRecord, "OutputTypeRandomFDBRecord" }, + { OutputTypeMCastFDBRecord, "OutputTypeMCastFDBRecord" }, + { OutputTypeVLArbTableRecord, "OutputTypeVLArbTableRecord" }, + { OutputTypePKeyTableRecord, "OutputTypePKeyTableRecord" }, + { OutputTypeVfInfoRecord, "OutputTypeVfInfoRecord" }, + { OutputTypeClassPortInfo, "OutputTypeClassPortInfo" }, + + /* PA query results */ + { OutputTypePaRecord, "OutputTypePaRecord" }, + { OutputTypePaTableRecord, "OutputTypePaTableRecord" }, + + /* New STL SA Types */ + { OutputTypeStlNodeRecord, "OutputTypeStlNodeRecord" }, + { OutputTypeStlNodeDesc, "OutputTypeStlNodeDesc" }, + { OutputTypeStlPortInfoRecord, "OutputTypeStlPortInfoRecord" }, + { OutputTypeStlSwitchInfoRecord, "OutputTypeStlSwitchInfoRecord" }, + { OutputTypeStlPKeyTableRecord, "OutputTypeStlPKeyTableRecord" }, + { OutputTypeStlSLSCTableRecord, "OutputTypeStlSLSCTableRecord" }, + { OutputTypeStlSMInfoRecord, "OutputTypeStlSMInfoRecord" }, + { OutputTypeStlLinearFDBRecord, "OutputTypeStlLinearFDBRecord" }, + { OutputTypeStlVLArbTableRecord, "OutputTypeStlVLArbTableRecord" }, + { OutputTypeStlLid, "OutputTypeStlLid" }, + { OutputTypeStlMCastFDBRecord, "OutputTypeStlMCastFDBRecord" }, + { OutputTypeStlLinkRecord, "OutputTypeStlLinkRecord" }, + { OutputTypeStlSystemImageGuid, "OutputTypeStlSystemImageGuid" }, + { OutputTypeStlPortGuid, "OutputTypeStlPortGuid" }, + { OutputTypeStlNodeGuid, "OutputTypeStlNodeGuid" }, + { OutputTypeStlInformInfoRecord, "OutputTypeStlInformInfoRecord" }, + { OutputTypeStlVfInfoRecord, "OutputTypeStlVfInfoRecord" }, + { OutputTypeStlTraceRecord, "OutputTypeStlTraceRecord" }, + { OutputTypeStlQuarantinedNodeRecord, "OutputTypeStlQuarantinedNodeRecord" }, + { OutputTypeStlCongInfoRecord, "OutputTypeStlCongInfoRecord" }, + { OutputTypeStlSwitchCongRecord, "OutputTypeStlSwitchCongRecord" }, + { OutputTypeStlSwitchPortCongRecord, "OutputTypeStlSwitchPortCongRecord" }, + { OutputTypeStlHFICongRecord, "OutputTypeStlHFICongRecord" }, + { OutputTypeStlHFICongCtrlRecord, "OutputTypeStlHFICongCtrlRecord" }, + { OutputTypeStlBufCtrlTabRecord, "OutputTypeStlBufCtrlTabRecord" }, + { OutputTypeStlCableInfoRecord, "OutputTypeStlCableInfoRecord" }, + { OutputTypeStlPortGroupRecord, "OutputTypeStlPortGroupRecord" }, + { OutputTypeStlPortGroupFwdRecord, "OutputTypeStlPortGroupFwdRecord" }, + { OutputTypeStlSCSLTableRecord, "OutputTypeStlSCSLTableRecord" }, + { OutputTypeStlSCVLtTableRecord, "OutputTypeStlSCVLtTableRecord" }, + { OutputTypeStlSCVLntTableRecord, "OutputTypeStlSCVLntTableRecord" }, + { OutputTypeStlSCSCTableRecord, "OutputTypeStlSCSCTableRecord" }, + { OutputTypeStlClassPortInfo, "OutputTypeStlClassPortInfo" }, + { OutputTypeStlFabricInfoRecord, "OutputTypeStlFabricInfoRecord" }, + { OutputTypeStlSCVLrTableRecord, "OutputTypeStlSCVLrTableRecord" }, + { OutputTypeStlDeviceGroupNameRecord, "OutputTypeStlDeviceGroupNameRecord" }, + { OutputTypeStlDeviceGroupMemberRecord, "OutputTypeStlDeviceGroupMemberRecord" }, + { OutputTypeStlDeviceTreeMemberRecord, "OutputTypeStlDeviceTreeMemberRecord" }, + { OutputTypeStlSwitchCostRecord, "OutputTypeStlSwitchCostRecord" }, + + { OutputTypeSystemImageGuid, NULL } // {0, NULL} Must be the last element to terminate the Map +}; +const char* iba_sd_query_result_type_msg(QUERY_RESULT_TYPE code) +{ + int i; + for (i = 0; OutputTypeStringValuePair[i].outputTypeStr != NULL; i++) { + if (OutputTypeStringValuePair[i].outputType == code) + return OutputTypeStringValuePair[i].outputTypeStr; + } + return "Unknown Query Result Type"; +} + +const char* iba_mad_status_msg(MAD_STATUS madStatus) +{ + if (madStatus.AsReg16 == MAD_STATUS_SUCCESS) + return "Success"; + else if (madStatus.S.Busy) + return "Busy"; + else if (madStatus.S.RedirectRqrd) + return "Redirection Required"; + else if (madStatus.S.InvalidField) + return MadInvalidFieldText[madStatus.S.InvalidField]; + else if (madStatus.S.ClassSpecific) + return "Class Specific Status"; + else + return "Unknown Mad Status"; +} + +// this function is useful when we have DR.s.Status which is a 15 bit bitfield +const char* iba_mad_status_msg2(uint16 madStatus) +{ + MAD_STATUS mad_status; + + mad_status.AsReg16 = madStatus; + return iba_mad_status_msg(mad_status); +} + +const char* iba_sd_mad_status_msg(uint32 code) +{ + // this is a little more complex than most due to bitfields and reserved + // values + MAD_STATUS madStatus; + + madStatus.AsReg16 = code; // ignore reserved bits in Sd MadStatus + if (code == MAD_STATUS_SUCCESS || (code & 0xff)) + return iba_mad_status_msg(madStatus); // standard mad status fields + else { + code = madStatus.S.ClassSpecific; // SA specific status code field + if (code >= (unsigned)(sizeof(SdSAStatusText)/sizeof(char*))) + return "Unknown SA Mad Status"; + else + return SdSAStatusText[code]; + } +} + +/** + * Common actions related to the query of the SA + * + * @param pSA pointer to the SA query message + * @param ppRsp pointer to the address of the SA query + * response + * @param record_size Size of the record being queried. + * @param ppQR pointer to the address of the response + * values + * @param port port opened by omgt_open_port_* + * + * @return 0 if success, else error code (FSTATUS) + */ +static FSTATUS sa_query_common(SA_MAD * pSA, SA_MAD **ppRsp, uint32_t record_size, + PQUERY_RESULT_VALUES *ppQR, struct omgt_port *port) +{ + FSTATUS fstatus = FSUCCESS; + MAD_STATUS madStatus = {0}; + size_t length = 0; + uint32_t cnt = 0; + uint32_t memsize; + struct omgt_mad_addr addr = {0}; + + DBG_ENTER_FUNC(port); + + /* If port is In-Band, set up addr */ + if (!port->is_oob_enabled) { + uint8_t port_state; + (void)omgt_port_get_port_state(port, &port_state); + if (port_state != PortStateActive) { + OMGT_OUTPUT_ERROR(port, "Local port not Active!\n"); + return FINVALID_STATE; + } + (void)omgt_port_get_port_sm_lid(port, &addr.lid); + (void)omgt_port_get_port_sm_sl(port, &addr.sl); + addr.qpn = 1; + addr.qkey = QP1_WELL_KNOWN_Q_KEY; + addr.pkey = OMGT_DEFAULT_PKEY; + } + + // Default the parameters to failed state. + *ppQR = NULL; + *ppRsp= NULL; + + // If the port is In-Band, use the correct PKEY. + // Should attempt to use full mgmt if available, + // which is default case above. + if (!port->is_oob_enabled && omgt_find_pkey(port, 0xffff) < 0) { + // No full mgmt pkey available on this node. + switch (pSA->common.AttributeID) { + case SA_ATTRIB_PORTINFO_RECORD: + if (pSA->common.BaseVersion != IB_BASE_VERSION) { + fstatus = FPROTECTION; + goto done; + } + // fall through + case SA_ATTRIB_PATH_RECORD: + case SA_ATTRIB_MULTIPATH_RECORD: + case SA_ATTRIB_NODE_RECORD: + case SA_ATTRIB_INFORM_INFO: + case SA_ATTRIB_INFORM_INFO_RECORD: + case SA_ATTRIB_NOTICE: + case SA_ATTRIB_SERVICE_RECORD: + case SA_ATTRIB_MCMEMBER_RECORD: + case SA_ATTRIB_CLASS_PORT_INFO: + case STL_SA_ATTR_VF_INFO_RECORD: + // These attributes can use limited mgmt pkey, if available. + if (omgt_find_pkey(port, 0x7fff) >= 0) { + addr.pkey = 0x7fff; + break; + } + // fall through + default: + // Unable to make such a query. + // Must be full or limited mgmt, and we do not have proper pkey in our tables. + fstatus = FPROTECTION; + goto done; + } + } + + /* Set a short timeout for class port info as these queries will always be + * a small constant size. + */ + int timeout; + if (pSA->common.AttributeID == SA_ATTRIB_CLASS_PORT_INFO && port->sa_service_state != OMGT_SERVICE_STATE_OPERATIONAL) { + timeout = 250; //250 ms + } else { + timeout = port->ms_timeout; + } + + BSWAP_SA_HDR (&pSA->SaHdr); + BSWAP_MAD_HEADER((MAD*)pSA); + + fstatus = omgt_send_recv_mad_alloc(port, (uint8_t *)pSA, record_size + sizeof(MAD_COMMON) + sizeof(SA_MAD_HDR), + &addr, (uint8_t **)ppRsp, &length, timeout, port->retry_count); + + if (fstatus != FSUCCESS) { + OMGT_DBGPRINT(port, "Query SA failed to send: %d\n", fstatus); + goto done; + } + /* Check if MAD header is present */ + if (length < sizeof(MAD_COMMON)) { + OMGT_DBGPRINT(port, "Query SA: Failed to receive packet: length (%zu) less than sizeof(MAD_COMMON) (%zu)\n", + length, sizeof(MAD_COMMON)); + fstatus = FNOT_FOUND; + goto done; + } + BSWAP_MAD_HEADER((MAD*)(*ppRsp)); + MAD_GET_STATUS((*ppRsp), &madStatus); + port->sa_mad_status = madStatus.AsReg16; + + /* Check if SA Header is present */ + if (length < IBA_SUBN_ADM_HDRSIZE) { + OMGT_DBGPRINT(port, "Query SA: Failed to receive packet: length (%zu) less than IBA_SUBN_ADM_HDRSIZE (%u)\n", + length, IBA_SUBN_ADM_HDRSIZE); + fstatus = FNOT_FOUND; + goto done; + } + BSWAP_SA_HDR (&(*ppRsp)->SaHdr); + + // dump of SA header for debug + OMGT_DBGPRINT(port, " SA Header\n"); + OMGT_DBGPRINT(port, " length %zu (0x%zx) vs IBA_SUBN_ADM_HDRSIZE %d\n", + length, length, IBA_SUBN_ADM_HDRSIZE); + OMGT_DBGPRINT(port, " SmKey (0x%016"PRIx64")\n", (*ppRsp)->SaHdr.SmKey); + OMGT_DBGPRINT(port, " AttributeOffset %u (0x%x) : in bytes: %u\n", + (*ppRsp)->SaHdr.AttributeOffset, (*ppRsp)->SaHdr.AttributeOffset, + ((*ppRsp)->SaHdr.AttributeOffset * 8)); + OMGT_DBGPRINT(port, " Reserved (0x%x)\n", (*ppRsp)->SaHdr.Reserved); + OMGT_DBGPRINT(port, " ComponetMask (0x%016"PRIx64")\n", (*ppRsp)->SaHdr.ComponentMask); + + // if no records IBTA 1.2.1 says AttributeOffset should be 0 + if ((*ppRsp)->common.mr.AsReg8 == SUBN_ADM_GET_RESP) { + cnt = 1; /* Count is always 1 for a GET(). */ + } else if ((*ppRsp)->SaHdr.AttributeOffset) { + /* Count is data length / attribute offset. */ + cnt = (int)((length - IBA_SUBN_ADM_HDRSIZE) / + ((*ppRsp)->SaHdr.AttributeOffset * sizeof(uint64))); + } else { + cnt = 0; + } + + OMGT_DBGPRINT(port, "Record count is %d\n", cnt); + + // If the command was not successful (mad status is not 0) + // Change overall return status to failed. + // Fill in the result pointer so the caller can evaluate the return mad status. + if (madStatus.AsReg16!=0) { + OMGT_DBGPRINT(port, "Query SA failed: Mad status is 0x%x: %s\n", + madStatus.AsReg16, iba_sd_mad_status_msg(madStatus.AsReg16)); + } + + // Query result is the size of one of the IBACCESS expected data types. + // Multiply that size by the count of records we got back. + // Add to that size, the size of the size of the query response struct. + memsize = record_size * cnt; + memsize += sizeof (uint32_t); + memsize += sizeof (QUERY_RESULT_VALUES); + + // ResultDataSize should be 0 when status is not successful and no data is returned + *ppQR = MemoryAllocate2AndClear(memsize, IBA_MEM_FLAG_PREMPTABLE, OMGT_MEMORY_TAG); + if (!(*ppQR)) { + fstatus = FINSUFFICIENT_MEMORY; + OMGT_DBGPRINT(port, "Query SA failed to allocate result: %d\n", fstatus); + goto done; + } + + (*ppQR)->Status = fstatus; + (*ppQR)->MadStatus = madStatus.AsReg16; + (*ppQR)->ResultDataSize = record_size * cnt; + *((uint32_t*)((*ppQR)->QueryResult)) = cnt; + +done: + if (fstatus != FSUCCESS) { + if (*ppRsp!=NULL) { + free (*ppRsp); + *ppRsp = NULL; + } + } + + DBG_EXIT_FUNC(port); + return (fstatus); +} + +/** + * Fill in the query node info + * + * @param pSA pointer to the MAD header + * @param pQuery pointer to the query message + * + * @return 0 if success, else error code (FSTATUS) + */ +static FSTATUS fillInNodeRecord(SA_MAD * pSA, POMGT_QUERY pQuery) +{ + STL_NODE_RECORD *pNR = NULL; + + if ((pSA==NULL) || (pQuery==NULL)) { + return (FERROR); + } + + MAD_SET_ATTRIB_ID(pSA, STL_SA_ATTR_NODE_RECORD); + pNR = (STL_NODE_RECORD *)pSA->Data; + pNR->Reserved = 0; + + switch (pQuery->InputType) { + case InputTypeNoInput: + pSA->SaHdr.ComponentMask = 0; + break; + case InputTypeLid: + pSA->SaHdr.ComponentMask = STL_NODE_RECORD_COMP_LID; + pNR->RID.LID = pQuery->InputValue.NodeRecord.Lid; + break; + case InputTypePortGuid: + pSA->SaHdr.ComponentMask = STL_NODE_RECORD_COMP_PORTGUID; + pNR->NodeInfo.PortGUID = pQuery->InputValue.NodeRecord.PortGUID; + break; + case InputTypeNodeType: + pSA->SaHdr.ComponentMask = STL_NODE_RECORD_COMP_NODETYPE; + pNR->NodeInfo.NodeType = pQuery->InputValue.NodeRecord.NodeType; + break; + case InputTypeSystemImageGuid: + pSA->SaHdr.ComponentMask = STL_NODE_RECORD_COMP_SYSIMAGEGUID; + pNR->NodeInfo.SystemImageGUID = pQuery->InputValue.NodeRecord.SystemImageGUID; + break; + case InputTypeNodeGuid: + pSA->SaHdr.ComponentMask = STL_NODE_RECORD_COMP_NODEGUID; + pNR->NodeInfo.NodeGUID = pQuery->InputValue.NodeRecord.SystemImageGUID; + break; + case InputTypeNodeDesc: + pSA->SaHdr.ComponentMask = STL_NODE_RECORD_COMP_NODEDESC; + memcpy(pNR->NodeDesc.NodeString, pQuery->InputValue.NodeRecord.NodeDesc, + STL_NODE_DESCRIPTION_ARRAY_SIZE); + break; + default: + fprintf(stderr, "Query not supported in OFED: Input=%s(%d), Output=%s(%d)\n", + iba_sd_query_input_type_msg(pQuery->InputType), + pQuery->InputType, + iba_sd_query_result_type_msg(pQuery->OutputType), + pQuery->OutputType); + return(FINVALID_PARAMETER); + } + + BSWAP_STL_NODE_RECORD(pNR); + + return(FSUCCESS); +} + +/** + * Fill in node IB info + * + * @param pSA pointer to the mad header + * @param pQuery pointer to the query message + * + * @return 0 if success, else error code (FSTATUS) + */ +static FSTATUS fillInIbNodeRecord(SA_MAD * pSA, POMGT_QUERY pQuery) +{ + IB_NODE_RECORD *pNR = NULL; + + if ((pSA==NULL) || (pQuery==NULL)) { + return (FERROR); + } + + MAD_SET_ATTRIB_ID(pSA, SA_ATTRIB_NODE_RECORD); + pNR = (IB_NODE_RECORD *)pSA->Data; + + switch (pQuery->InputType) { + case InputTypeNoInput: + pSA->SaHdr.ComponentMask = 0; + break; + case InputTypeLid: + pSA->SaHdr.ComponentMask = IB_NODE_RECORD_COMP_LID; + pNR->RID.s.LID = pQuery->InputValue.IbNodeRecord.Lid; + break; + case InputTypePortGuid: + pSA->SaHdr.ComponentMask = IB_NODE_RECORD_COMP_PORTGUID; + pNR->NodeInfoData.PortGUID = pQuery->InputValue.IbNodeRecord.PortGUID; + break; + case InputTypeNodeType: + pSA->SaHdr.ComponentMask = IB_NODE_RECORD_COMP_NODETYPE; + pNR->NodeInfoData.NodeType = pQuery->InputValue.IbNodeRecord.NodeType; + break; + case InputTypeSystemImageGuid: + pSA->SaHdr.ComponentMask = IB_NODE_RECORD_COMP_SYSIMAGEGUID; + pNR->NodeInfoData.SystemImageGUID = pQuery->InputValue.IbNodeRecord.SystemImageGUID; + break; + case InputTypeNodeGuid: + pSA->SaHdr.ComponentMask = IB_NODE_RECORD_COMP_NODEGUID; + pNR->NodeInfoData.NodeGUID = pQuery->InputValue.IbNodeRecord.NodeGUID; + break; + case InputTypeNodeDesc: + pSA->SaHdr.ComponentMask = IB_NODE_RECORD_COMP_NODEDESC; + memcpy(pNR->NodeDescData.NodeString, pQuery->InputValue.IbNodeRecord.NodeDesc, + STL_NODE_DESCRIPTION_ARRAY_SIZE); + break; + default: + fprintf(stderr, "Query not supported in OFED: Input=%s(%d), Output=%s(%d)\n", + iba_sd_query_input_type_msg(pQuery->InputType), + pQuery->InputType, + iba_sd_query_result_type_msg(pQuery->OutputType), + pQuery->OutputType); + return(FINVALID_PARAMETER); + } + + BSWAP_IB_NODE_RECORD(pNR); + + return(FSUCCESS); +} + +/** + * Free the memory used in the query result + * + * @param pQueryResult pointer to the SA query result buffer + * + * @return none + */ +void omgt_free_query_result_buffer(IN void * pQueryResult) +{ + MemoryDeallocate(pQueryResult); +} + + +FSTATUS omgt_input_value_conversion(OMGT_QUERY *output_query, QUERY_INPUT_VALUE *old_query, IB_GID source_gid) +{ + switch ((int)output_query->OutputType) { + /* InputTypeNoInput Only */ + case OutputTypeClassPortInfo: + case OutputTypeStlClassPortInfo: + case OutputTypeStlSMInfoRecord: + case OutputTypeStlFabricInfoRecord: + case OutputTypeStlQuarantinedNodeRecord: + case OutputTypeStlDeviceGroupNameRecord: + switch (output_query->InputType) { + case InputTypeNoInput: break; + default: return FNOT_FOUND; + } + break; + case OutputTypeNodeRecord: + switch (output_query->InputType) { + case InputTypeNoInput: break; + case InputTypeLid: + output_query->InputValue.IbNodeRecord.Lid = old_query->Lid; + break; + case InputTypePortGuid: + output_query->InputValue.IbNodeRecord.PortGUID = old_query->Guid; + break; + case InputTypeNodeGuid: + output_query->InputValue.IbNodeRecord.NodeGUID = old_query->Guid; + break; + case InputTypeSystemImageGuid: + output_query->InputValue.IbNodeRecord.SystemImageGUID = old_query->Guid; + break; + case InputTypeNodeType: + output_query->InputValue.IbNodeRecord.NodeType = old_query->TypeOfNode; + break; + case InputTypeNodeDesc: + memcpy(output_query->InputValue.IbNodeRecord.NodeDesc, + old_query->NodeDesc.Name, STL_NODE_DESCRIPTION_ARRAY_SIZE); + break; + default: return FNOT_FOUND; + } + break; + case OutputTypeStlNodeRecord: + case OutputTypeStlNodeDesc: + case OutputTypeStlLid: + case OutputTypeStlSystemImageGuid: + case OutputTypeStlPortGuid: + case OutputTypeStlNodeGuid: + switch (output_query->InputType) { + case InputTypeNoInput: break; + case InputTypeLid: + output_query->InputValue.NodeRecord.Lid = old_query->Lid; + break; + case InputTypePortGuid: + output_query->InputValue.NodeRecord.PortGUID = old_query->Guid; + break; + case InputTypeNodeGuid: + output_query->InputValue.NodeRecord.NodeGUID = old_query->Guid; + break; + case InputTypeSystemImageGuid: + output_query->InputValue.NodeRecord.SystemImageGUID = old_query->Guid; + break; + case InputTypeNodeType: + output_query->InputValue.NodeRecord.NodeType = old_query->TypeOfNode; + break; + case InputTypeNodeDesc: + memcpy(output_query->InputValue.NodeRecord.NodeDesc, + old_query->NodeDesc.Name, STL_NODE_DESCRIPTION_ARRAY_SIZE); + break; + default: return FNOT_FOUND; + } + break; + case OutputTypePortInfoRecord: + switch (output_query->InputType) { + case InputTypeNoInput: break; + case InputTypeLid: + output_query->InputValue.IbPortInfoRecord.Lid = old_query->Lid; + break; + default: return FNOT_FOUND; + } + break; + case OutputTypeStlPortInfoRecord: + switch (output_query->InputType) { + case InputTypeNoInput: break; + case InputTypeLid: + output_query->InputValue.PortInfoRecord.Lid = old_query->Lid; + break; + default: return FNOT_FOUND; + } + break; + case OutputTypeStlLinkRecord: + switch (output_query->InputType) { + case InputTypeNoInput: break; + case InputTypeLid: + output_query->InputValue.LinkRecord.Lid = old_query->Lid; + break; + default: return FNOT_FOUND; + } + break; + case OutputTypeStlSwitchInfoRecord: + switch (output_query->InputType) { + case InputTypeNoInput: break; + case InputTypeLid: + output_query->InputValue.SwitchInfoRecord.Lid = old_query->Lid; + break; + default: return FNOT_FOUND; + } + break; + case OutputTypePathRecord: + case OutputTypePathRecordNetworkOrder: + switch (output_query->InputType) { + case InputTypeNoInput: + /* SourceGid is a new field for this InputType */ + if (source_gid.AsReg64s.H == 0 || source_gid.AsReg64s.L == 0) return FERROR; + output_query->InputValue.IbPathRecord.SourceGid = source_gid; + break; + case InputTypePKey: + output_query->InputValue.IbPathRecord.PKey.PKey = old_query->PKey; + /* SourceGid is a new field for this InputType */ + if (source_gid.AsReg64s.H == 0 || source_gid.AsReg64s.L == 0) return FERROR; + output_query->InputValue.IbPathRecord.PKey.SourceGid = source_gid; + break; + case InputTypeSL: + output_query->InputValue.IbPathRecord.SL.SL = old_query->SL; + /* SourceGid is a new field for this InputType */ + if (source_gid.AsReg64s.H == 0 || source_gid.AsReg64s.L == 0) return FERROR; + output_query->InputValue.IbPathRecord.SL.SourceGid = source_gid; + break; + case InputTypeServiceId: + output_query->InputValue.IbPathRecord.ServiceId.ServiceId = old_query->ServiceId; + /* SourceGid is a new field for this InputType */ + if (source_gid.AsReg64s.H == 0 || source_gid.AsReg64s.L == 0) return FERROR; + output_query->InputValue.IbPathRecord.ServiceId.SourceGid = source_gid; + break; + case InputTypePortGuid: + output_query->InputValue.IbPathRecord.PortGuid.DestPortGuid = + old_query->Guid; + /* SourcePortGuid is a new field for this InputType */ + if (source_gid.Type.Global.InterfaceID == 0) return FERROR; + output_query->InputValue.IbPathRecord.PortGuid.SourcePortGuid = + source_gid.Type.Global.InterfaceID; + /* SharedSubnetPrefix is new field for this InputType */ + if (source_gid.Type.Global.SubnetPrefix == 0) return FERROR; + output_query->InputValue.IbPathRecord.PortGuid.SharedSubnetPrefix = + source_gid.Type.Global.SubnetPrefix; + break; + case InputTypePortGuidPair: + output_query->InputValue.IbPathRecord.PortGuidPair.SourcePortGuid = + old_query->PortGuidPair.SourcePortGuid; + output_query->InputValue.IbPathRecord.PortGuidPair.DestPortGuid = + old_query->PortGuidPair.DestPortGuid; + /* SharedSubnetPrefix is new field for this InputType */ + if (source_gid.Type.Global.SubnetPrefix == 0) return FERROR; + output_query->InputValue.IbPathRecord.PortGuidPair.SharedSubnetPrefix = + source_gid.Type.Global.SubnetPrefix; + break; + case InputTypePortGid: + output_query->InputValue.IbPathRecord.PortGid.DestGid = + old_query->Gid; + /* SourceGid is a new field for this InputType */ + if (source_gid.AsReg64s.H == 0 || source_gid.AsReg64s.L == 0) return FERROR; + output_query->InputValue.IbPathRecord.PortGid.SourceGid = source_gid; + break; + case InputTypeGidPair: + output_query->InputValue.IbPathRecord.GidPair.DestGid = + old_query->GidPair.DestGid; + output_query->InputValue.IbPathRecord.GidPair.SourceGid = + old_query->GidPair.SourceGid; + break; + case InputTypeLid: + output_query->InputValue.IbPathRecord.Lid.DLid = + old_query->Lid; + /* SourceGid is a new field for this InputType */ + if (source_gid.AsReg64s.H == 0 || source_gid.AsReg64s.L == 0) return FERROR; + output_query->InputValue.IbPathRecord.Lid.SourceGid = source_gid; + break; + case InputTypePathRecord: + case InputTypePathRecordNetworkOrder: + output_query->InputValue.IbPathRecord.PathRecord.ComponentMask = + old_query->PathRecordValue.ComponentMask; + output_query->InputValue.IbPathRecord.PathRecord.PathRecord = + old_query->PathRecordValue.PathRecord; + break; + default: return FNOT_FOUND; + } + break; + case OutputTypeStlTraceRecord: + switch (output_query->InputType) { + case InputTypePathRecord: + output_query->InputValue.TraceRecord.PathRecord.ComponentMask = + old_query->PathRecordValue.ComponentMask; + output_query->InputValue.TraceRecord.PathRecord.PathRecord = + old_query->PathRecordValue.PathRecord; + break; + case InputTypePortGuid: + output_query->InputValue.TraceRecord.PortGuid.DestPortGuid = + old_query->Guid; + /* SourcePortGuid is a new field for this InputType */ + if (source_gid.Type.Global.InterfaceID == 0) return FERROR; + output_query->InputValue.TraceRecord.PortGuid.SourcePortGuid = + source_gid.Type.Global.InterfaceID; + /* SharedSubnetPrefix is new field for this InputType */ + if (source_gid.Type.Global.SubnetPrefix == 0) return FERROR; + output_query->InputValue.TraceRecord.PortGuid.SharedSubnetPrefix = + source_gid.Type.Global.SubnetPrefix; + break; + case InputTypePortGuidPair: + output_query->InputValue.TraceRecord.PortGuidPair.SourcePortGuid = + old_query->PortGuidPair.SourcePortGuid; + output_query->InputValue.TraceRecord.PortGuidPair.DestPortGuid = + old_query->PortGuidPair.DestPortGuid; + /* SharedSubnetPrefix is new field for this InputType */ + if (source_gid.Type.Global.SubnetPrefix == 0) return FERROR; + output_query->InputValue.TraceRecord.PortGuidPair.SharedSubnetPrefix = + source_gid.Type.Global.SubnetPrefix; + break; + case InputTypePortGid: + output_query->InputValue.TraceRecord.PortGid.DestGid = + old_query->Gid; + /* SourceGid is new field for this InputType */ + if (source_gid.AsReg64s.H == 0 || source_gid.AsReg64s.L == 0) return FERROR; + output_query->InputValue.TraceRecord.PortGid.SourceGid = source_gid; + break; + case InputTypeGidPair: + output_query->InputValue.TraceRecord.GidPair.DestGid = + old_query->GidPair.DestGid; + output_query->InputValue.TraceRecord.GidPair.SourceGid = + old_query->GidPair.SourceGid; + break; + case InputTypeLid: + output_query->InputValue.TraceRecord.Lid.DLid = + old_query->Lid; + /* SourceGid is a new field for this InputType */ + if (source_gid.AsReg64s.H == 0 || source_gid.AsReg64s.L == 0) return FERROR; + output_query->InputValue.TraceRecord.Lid.SourceGid = source_gid; + break; + default: return FNOT_FOUND; + } + break; + case OutputTypeServiceRecord: + switch (output_query->InputType) { + case InputTypeNoInput: break; + case InputTypePortGid: + output_query->InputValue.IbServiceRecord.ServiceGid = old_query->Gid; + break; + case InputTypeServiceId: + output_query->InputValue.IbServiceRecord.ServiceId = old_query->ServiceId; + break; + default: return FNOT_FOUND; + } + break; + case OutputTypeMcMemberRecord: + switch (output_query->InputType) { + case InputTypeNoInput: break; + case InputTypePortGid: + output_query->InputValue.IbMcMemberRecord.PortGid = old_query->Gid; + break; + case InputTypeMcGid: + output_query->InputValue.IbMcMemberRecord.McGid = old_query->Gid; + break; + case InputTypeLid: + output_query->InputValue.IbMcMemberRecord.Lid = old_query->Lid; + break; + case InputTypePKey: + output_query->InputValue.IbMcMemberRecord.PKey = old_query->PKey; + break; + case InputTypeSL: + output_query->InputValue.IbMcMemberRecord.SL = old_query->SL; + break; + default: return FNOT_FOUND; + } + break; + case OutputTypeInformInfoRecord: + switch (output_query->InputType) { + case InputTypeNoInput: break; + case InputTypePortGid: + output_query->InputValue.IbInformInfoRecord.SubscriberGID = old_query->Gid; + break; + default: return FNOT_FOUND; + } + break; + case OutputTypeStlInformInfoRecord: + switch (output_query->InputType) { + case InputTypeNoInput: break; + case InputTypeLid: + output_query->InputValue.StlInformInfoRecord.SubscriberLID = old_query->Lid; + break; + default: return FNOT_FOUND; + } + break; + case OutputTypeStlSCSCTableRecord: + switch (output_query->InputType) { + case InputTypeNoInput: break; + case InputTypeLid: + output_query->InputValue.ScScTableRecord.Lid = old_query->Lid; + break; + default: return FNOT_FOUND; + } + break; + case OutputTypeStlSLSCTableRecord: + switch (output_query->InputType) { + case InputTypeNoInput: break; + case InputTypeLid: + output_query->InputValue.SlScTableRecord.Lid = old_query->Lid; + break; + default: return FNOT_FOUND; + } + break; + case OutputTypeStlSCSLTableRecord: + switch (output_query->InputType) { + case InputTypeNoInput: break; + case InputTypeLid: + output_query->InputValue.ScSlTableRecord.Lid = old_query->Lid; + break; + default: return FNOT_FOUND; + } + break; + case OutputTypeStlSCVLtTableRecord: + case OutputTypeStlSCVLntTableRecord: + case OutputTypeStlSCVLrTableRecord: + switch (output_query->InputType) { + case InputTypeNoInput: break; + case InputTypeLid: + output_query->InputValue.ScVlxTableRecord.Lid = old_query->Lid; + break; + default: return FNOT_FOUND; + } + break; + case OutputTypeStlVLArbTableRecord: + switch (output_query->InputType) { + case InputTypeNoInput: break; + case InputTypeLid: + output_query->InputValue.VlArbTableRecord.Lid = old_query->Lid; + break; + default: return FNOT_FOUND; + } + break; + case OutputTypeStlPKeyTableRecord: + switch (output_query->InputType) { + case InputTypeNoInput: break; + case InputTypeLid: + output_query->InputValue.PKeyTableRecord.Lid = old_query->Lid; + break; + default: return FNOT_FOUND; + } + break; + case OutputTypeStlLinearFDBRecord: + switch (output_query->InputType) { + case InputTypeNoInput: break; + case InputTypeLid: + output_query->InputValue.LinFdbTableRecord.Lid = old_query->Lid; + break; + default: return FNOT_FOUND; + } + break; + case OutputTypeStlMCastFDBRecord: + switch (output_query->InputType) { + case InputTypeNoInput: break; + case InputTypeLid: + output_query->InputValue.McFdbTableRecord.Lid = old_query->Lid; + break; + default: return FNOT_FOUND; + } + break; + case OutputTypeStlVfInfoRecord: + switch (output_query->InputType) { + case InputTypeNoInput: break; + case InputTypePKey: + output_query->InputValue.VfInfoRecord.PKey = old_query->PKey; + break; + case InputTypeSL: + output_query->InputValue.VfInfoRecord.SL = old_query->SL; + break; + case InputTypeServiceId: + output_query->InputValue.VfInfoRecord.ServiceId = old_query->ServiceId; + break; + case InputTypeMcGid: + output_query->InputValue.VfInfoRecord.McGid = old_query->Gid; + break; + case InputTypeIndex: + output_query->InputValue.VfInfoRecord.vfIndex = old_query->vfIndex; + break; + case InputTypeNodeDesc: + snprintf(output_query->InputValue.VfInfoRecord.vfName, + STL_VFABRIC_NAME_LEN, "%s", old_query->NodeDesc.Name); + break; + default: return FNOT_FOUND; + } + break; + case OutputTypeStlCongInfoRecord: + switch (output_query->InputType) { + case InputTypeNoInput: break; + case InputTypeLid: + output_query->InputValue.CongInfoRecord.Lid = old_query->Lid; + break; + default: return FNOT_FOUND; + } + break; + case OutputTypeStlSwitchCongRecord: + switch (output_query->InputType) { + case InputTypeNoInput: break; + case InputTypeLid: + output_query->InputValue.SwCongRecord.Lid = old_query->Lid; + break; + default: return FNOT_FOUND; + } + break; + case OutputTypeStlSwitchPortCongRecord: + switch (output_query->InputType) { + case InputTypeNoInput: break; + case InputTypeLid: + output_query->InputValue.SwPortCongRecord.Lid = old_query->Lid; + break; + default: return FNOT_FOUND; + } + break; + case OutputTypeStlHFICongRecord: + switch (output_query->InputType) { + case InputTypeNoInput: break; + case InputTypeLid: + output_query->InputValue.HFICongRecord.Lid = old_query->Lid; + break; + default: return FNOT_FOUND; + } + break; + case OutputTypeStlHFICongCtrlRecord: + switch (output_query->InputType) { + case InputTypeNoInput: break; + case InputTypeLid: + output_query->InputValue.HFICongCtrlRecord.Lid = old_query->Lid; + break; + default: return FNOT_FOUND; + } + break; + case OutputTypeStlBufCtrlTabRecord: + switch (output_query->InputType) { + case InputTypeNoInput: break; + case InputTypeLid: + output_query->InputValue.BufCtrlTableRecord.Lid = old_query->Lid; + break; + default: return FNOT_FOUND; + } + break; + case OutputTypeStlCableInfoRecord: + switch (output_query->InputType) { + case InputTypeNoInput: break; + case InputTypeLid: + output_query->InputValue.CableInfoRecord.Lid = old_query->Lid; + break; + default: return FNOT_FOUND; + } + break; + case OutputTypeStlPortGroupRecord: + switch (output_query->InputType) { + case InputTypeNoInput: break; + case InputTypeLid: + output_query->InputValue.PortGroupRecord.Lid = old_query->Lid; + break; + default: return FNOT_FOUND; + } + break; + case OutputTypeStlPortGroupFwdRecord: + switch (output_query->InputType) { + case InputTypeNoInput: break; + case InputTypeLid: + output_query->InputValue.PortGroupFwdRecord.Lid = old_query->Lid; + break; + default: return FNOT_FOUND; + } + break; + case OutputTypeStlDeviceGroupMemberRecord: + switch (output_query->InputType) { + case InputTypeNoInput: break; + case InputTypeLid: + output_query->InputValue.DgGrpMemberRecord.Lid = old_query->Lid; + break; + case InputTypePortGuid: + output_query->InputValue.DgGrpMemberRecord.Guid = old_query->Guid; + break; + case InputTypeNodeDesc: + snprintf(output_query->InputValue.DgGrpMemberRecord.NodeDesc, + STL_NODE_DESCRIPTION_ARRAY_SIZE, "%s", old_query->NodeDesc.Name); + break; + case InputTypeDeviceGroup: + snprintf(output_query->InputValue.DgGrpMemberRecord.DeviceGroup, + MAX_DG_NAME, "%s", old_query->NodeDesc.Name); + break; + default: return FNOT_FOUND; + } + break; + case OutputTypeStlDeviceTreeMemberRecord: + switch (output_query->InputType) { + case InputTypeNoInput: break; + case InputTypeLid: + output_query->InputValue.DgTreeMemberRecord.Lid = old_query->Lid; + break; + default: return FNOT_FOUND; + } + break; + case OutputTypeStlSwitchCostRecord: + switch (output_query->InputType) { + case InputTypeNoInput: break; + case InputTypeLid: + output_query->InputValue.SwitchCostRecord.Lid = old_query->Lid; + break; + default: return FNOT_FOUND; + } + break; + default: return FNOT_FOUND; + } + return FSUCCESS; +} + + + +/** + * Pose a query to the fabric, expect a response. + * + * @param port port opened by omgt_open_port_* + * @param pQuery pointer to the query structure + * @param ppQueryResult pointer where the response will go + * + * @return 0 if success, else error code + */ +static FSTATUS omgt_query_sa_internal(struct omgt_port *port, OMGT_QUERY *pQuery, + struct _QUERY_RESULT_VALUES **ppQueryResult) +{ + FSTATUS fstatus = FSUCCESS; + QUERY_RESULT_VALUES *pQR = NULL; + SA_MAD mad; + SA_MAD *pRsp = NULL; + static uint32_t trans_id = 1; + int i; + + DBG_ENTER_FUNC(port); + + /* All fields are supposed to be zeroed out if they are not used. */ + memset(&mad,0,sizeof(mad)); + + // Setup defaults + memset( &mad, 0, sizeof(mad)); + MAD_SET_METHOD_TYPE (&mad, SUBN_ADM_GETTABLE); + MAD_SET_VERSION_INFO(&mad, STL_BASE_VERSION, MCLASS_SUBN_ADM, STL_SA_CLASS_VERSION); + MAD_SET_TRANSACTION_ID(&mad, trans_id++); //<<16??? + + // Process the command. + switch ((int)pQuery->OutputType) { + case OutputTypeClassPortInfo: + { + IB_CLASS_PORT_INFO_RESULTS *pCPIR; + IB_CLASS_PORT_INFO *pCPI; + + if (pQuery->InputType != InputTypeNoInput) { + OMGT_OUTPUT_ERROR(port, "Query not supported by opamgt: Input=%s, Output=%s\n", + iba_sd_query_input_type_msg(pQuery->InputType), + iba_sd_query_result_type_msg(pQuery->OutputType)); + + fstatus = FINVALID_PARAMETER; goto done; + } + + MAD_SET_VERSION_INFO(&mad, IB_BASE_VERSION, MCLASS_SUBN_ADM, + IB_SUBN_ADM_CLASS_VERSION); + MAD_SET_ATTRIB_ID(&mad, SA_ATTRIB_CLASS_PORT_INFO); + MAD_SET_METHOD_TYPE(&mad, SUBN_ADM_GET); + + fstatus = sa_query_common(&mad, &pRsp, sizeof(IB_CLASS_PORT_INFO), &pQR, port); + if (fstatus != FSUCCESS) break; + + pCPIR = (IB_CLASS_PORT_INFO_RESULTS*)pQR->QueryResult; + pCPI = &pCPIR->ClassPortInfo[0]; + + // There should only be one ClassPortInfo result. + if (pCPIR->NumClassPortInfo > 0) { + *pCPI = *((IB_CLASS_PORT_INFO*)(GET_RESULT_OFFSET(pRsp, 0))); + BSWAP_IB_CLASS_PORT_INFO(pCPI); + } + } + break; + case OutputTypeStlClassPortInfo: + { + STL_CLASS_PORT_INFO_RESULT *pCPIR; + STL_CLASS_PORT_INFO *pCPI; + + if (pQuery->InputType != InputTypeNoInput) { + OMGT_OUTPUT_ERROR(port, "Query not supported by opamgt: Input=%s, Output=%s\n", + iba_sd_query_input_type_msg(pQuery->InputType), + iba_sd_query_result_type_msg(pQuery->OutputType)); + + fstatus = FINVALID_PARAMETER; goto done; + } + + MAD_SET_ATTRIB_ID(&mad, STL_SA_ATTR_CLASS_PORT_INFO); + MAD_SET_METHOD_TYPE(&mad, SUBN_ADM_GET); + + fstatus = sa_query_common(&mad, &pRsp, sizeof(STL_CLASS_PORT_INFO), &pQR, port); + if (fstatus != FSUCCESS) break; + + pCPIR = (STL_CLASS_PORT_INFO_RESULT*)pQR->QueryResult; + pCPI = &pCPIR->ClassPortInfo; + + // There should only be one ClassPortInfo result. + if (pCPIR->NumClassPortInfo > 0) { + *pCPI = *((STL_CLASS_PORT_INFO*)(GET_RESULT_OFFSET(pRsp, 0))); + BSWAP_STL_CLASS_PORT_INFO(pCPI); + } + } + break; + case OutputTypeNodeRecord: // Legacy, IB query + { + NODE_RECORD_RESULTS *pNRR; + IB_NODE_RECORD *pNR; + + MAD_SET_VERSION_INFO(&mad, IB_BASE_VERSION, MCLASS_SUBN_ADM, IB_SUBN_ADM_CLASS_VERSION); + + // Take care of input types in fillIn... + if (fillInIbNodeRecord(&mad, pQuery) != FSUCCESS) break; + + fstatus = sa_query_common(&mad, &pRsp, sizeof (IB_NODE_RECORD), &pQR, port); + if (fstatus != FSUCCESS) break; + + // Translate the data. + pNRR = (NODE_RECORD_RESULTS*)pQR->QueryResult; + pNR = pNRR->NodeRecords; + for (i=0; i< pNRR->NumNodeRecords; i++, pNR++) { + *pNR = * ((IB_NODE_RECORD*)(GET_RESULT_OFFSET(pRsp, i))); + BSWAP_IB_NODE_RECORD(pNR); + } + } + break; + + /* Group All STL NodeInfo Record based OutputTypes */ + case OutputTypeStlNodeRecord: + case OutputTypeStlSystemImageGuid: + case OutputTypeStlNodeGuid: + case OutputTypeStlPortGuid: + case OutputTypeStlLid: + case OutputTypeStlNodeDesc: + { + STL_NODE_RECORD *pNR; + + fstatus = fillInNodeRecord(&mad, pQuery); + if (fstatus != FSUCCESS) break; + + fstatus = sa_query_common(&mad, &pRsp, sizeof(STL_NODE_RECORD), &pQR, port); + if (fstatus != FSUCCESS) break; + + // Translate the data. + switch ((int)pQuery->OutputType) { + case OutputTypeStlNodeRecord: + { + STL_NODE_RECORD_RESULTS *pNRR = (STL_NODE_RECORD_RESULTS *)pQR->QueryResult; + pNR = pNRR->NodeRecords; + for (i=0; i< pNRR->NumNodeRecords; i++, pNR++) { + *pNR = *((STL_NODE_RECORD *)(GET_RESULT_OFFSET(pRsp, i))); + BSWAP_STL_NODE_RECORD(pNR); + } + } + break; + case OutputTypeStlSystemImageGuid: + { + GUID_RESULTS *pGR = (GUID_RESULTS*)pQR->QueryResult; + EUI64 *pGuid = pGR->Guids; + for (i=0; i< pGR->NumGuids; i++, pGuid++) { + pNR = ((STL_NODE_RECORD *)(GET_RESULT_OFFSET(pRsp, i))); + *pGuid = ntoh64(pNR->NodeInfo.SystemImageGUID); + } + } + break; + case OutputTypeStlNodeGuid: + { + GUID_RESULTS *pGR = (GUID_RESULTS*)pQR->QueryResult; + EUI64 *pGuid = pGR->Guids; + for (i=0; i< pGR->NumGuids; i++, pGuid++) { + pNR = ((STL_NODE_RECORD *)(GET_RESULT_OFFSET(pRsp, i))); + *pGuid = ntoh64(pNR->NodeInfo.NodeGUID); + } + } + break; + case OutputTypeStlPortGuid: + { + GUID_RESULTS *pGR = (GUID_RESULTS*)pQR->QueryResult; + EUI64 *pGuid = pGR->Guids; + for (i=0; i< pGR->NumGuids; i++, pGuid++) { + pNR = ((STL_NODE_RECORD *)(GET_RESULT_OFFSET(pRsp, i))); + *pGuid = ntoh64(pNR->NodeInfo.PortGUID); + } + } + break; + case OutputTypeStlLid: + { + STL_LID_RESULTS *pLR = (STL_LID_RESULTS *)pQR->QueryResult; + STL_LID *pLid = pLR->Lids; + for (i=0; i< pLR->NumLids; i++, pLid++) { + pNR = ((STL_NODE_RECORD *)(GET_RESULT_OFFSET(pRsp, i))); + *pLid = ntoh32(pNR->RID.LID); + } + } + break; + case OutputTypeStlNodeDesc: + { + STL_NODEDESC_RESULTS *pNDR = (STL_NODEDESC_RESULTS *)pQR->QueryResult; + STL_NODE_DESCRIPTION *pDesc = pNDR->NodeDescs; + for (i=0; i< pNDR->NumDescs; i++, pDesc++) { + pNR = ((STL_NODE_RECORD *)(GET_RESULT_OFFSET(pRsp, i))); + *pDesc = pNR->NodeDesc; + } + } + break; + } + } + break; + + case OutputTypePortInfoRecord: + { + PORTINFO_RECORD_RESULTS *pPIR; + IB_PORTINFO_RECORD *pPI = (IB_PORTINFO_RECORD *)mad.Data; + int extended_data; + + switch (pQuery->InputType) { + case InputTypeNoInput: + break; + case InputTypeLid: + mad.SaHdr.ComponentMask = IB_PORTINFO_RECORD_COMP_ENDPORTLID; + pPI->RID.s.EndPortLID = pQuery->InputValue.IbPortInfoRecord.Lid; + break; + default: + OMGT_OUTPUT_ERROR(port,"Query not supported by opamgt: Input=%s, Output=%s\n", + iba_sd_query_input_type_msg(pQuery->InputType), + iba_sd_query_result_type_msg(pQuery->OutputType)); + fstatus = FINVALID_PARAMETER; goto done; + } + + BSWAP_IB_PORTINFO_RECORD(pPI, TRUE); + MAD_SET_ATTRIB_ID(&mad, SA_ATTRIB_PORTINFO_RECORD); + MAD_SET_VERSION_INFO(&mad, IB_BASE_VERSION, MCLASS_SUBN_ADM, + IB_SUBN_ADM_CLASS_VERSION); + + fstatus = sa_query_common(&mad, &pRsp, sizeof (IB_PORTINFO_RECORD), &pQR, port); + if (fstatus != FSUCCESS) break; + + // Translate the data. + pPIR = (PORTINFO_RECORD_RESULTS*)pQR->QueryResult; + pPI = pPIR->PortInfoRecords; + extended_data = ( (pRsp->SaHdr.AttributeOffset * 8) >= + sizeof(IB_PORTINFO_RECORD) ); + + for (i=0; i< pPIR->NumPortInfoRecords; i++, pPI++) { + *pPI = * ((IB_PORTINFO_RECORD*)(GET_RESULT_OFFSET(pRsp, i))); + BSWAP_IB_PORTINFO_RECORD(pPI, extended_data); + // Clear IB_LINK_SPEED_10G if QDR is overloaded + if (extended_data) { + if ( pPI->PortInfoData.CapabilityMask.s.IsExtendedSpeedsSupported && + !( pPI->RID.s.Options & + IB_PORTINFO_RECORD_OPTIONS_QDRNOTOVERLOADED ) ) { + if (pPI->PortInfoData.LinkSpeedExt.Active) + pPI->PortInfoData.LinkSpeed.Active &= ~IB_LINK_SPEED_10G; + if (pPI->PortInfoData.LinkSpeedExt.Supported) + pPI->PortInfoData.Link.SpeedSupported &= ~IB_LINK_SPEED_10G; + if (pPI->PortInfoData.LinkSpeedExt.Enabled) + pPI->PortInfoData.LinkSpeed.Enabled &= ~IB_LINK_SPEED_10G; + } + } + else { + pPI->PortInfoData.LinkSpeedExt.Active = 0; + pPI->PortInfoData.LinkSpeedExt.Supported = 0; + pPI->PortInfoData.LinkSpeedExt.Enabled = 0; + } + } + } + break; + + case OutputTypeStlPortInfoRecord: + { + STL_PORTINFO_RECORD_RESULTS *pPIR; + STL_PORTINFO_RECORD *pPI = (STL_PORTINFO_RECORD *)mad.Data; + + switch (pQuery->InputType) { + case InputTypeNoInput: + break; + case InputTypeLid: + mad.SaHdr.ComponentMask = STL_PORTINFO_RECORD_COMP_ENDPORTLID; + pPI->RID.EndPortLID = pQuery->InputValue.PortInfoRecord.Lid; + break; + default: + OMGT_OUTPUT_ERROR(port,"Query not supported by opamgt: Input=%s, Output=%s\n", + iba_sd_query_input_type_msg(pQuery->InputType), + iba_sd_query_result_type_msg(pQuery->OutputType)); + fstatus = FINVALID_PARAMETER; goto done; + } + + BSWAP_STL_PORTINFO_RECORD(pPI); + MAD_SET_ATTRIB_ID(&mad, STL_SA_ATTR_PORTINFO_RECORD); + + fstatus = sa_query_common(&mad, &pRsp, sizeof (STL_PORTINFO_RECORD), &pQR, port); + if (fstatus != FSUCCESS) break; + + // Translate the data. + pPIR = (STL_PORTINFO_RECORD_RESULTS*)pQR->QueryResult; + pPI = pPIR->PortInfoRecords; + + for (i=0; i< pPIR->NumPortInfoRecords; i++, pPI++) { + *pPI = * ((STL_PORTINFO_RECORD*)(GET_RESULT_OFFSET(pRsp, i))); + BSWAP_STL_PORTINFO_RECORD(pPI); + } + } + break; + + case OutputTypeStlLinkRecord: + { + STL_LINK_RECORD_RESULTS *pLRR; + STL_LINK_RECORD *pLR = (STL_LINK_RECORD*)mad.Data; + + + switch (pQuery->InputType) { + case InputTypeNoInput: + break; + case InputTypeLid: + mad.SaHdr.ComponentMask = IB_LINK_RECORD_COMP_FROMLID; + pLR->RID.FromLID = pQuery->InputValue.LinkRecord.Lid; + break; + default: + OMGT_OUTPUT_ERROR(port, "Query not supported: Input=%s, Output=%s\n", + iba_sd_query_input_type_msg(pQuery->InputType), + iba_sd_query_result_type_msg(pQuery->OutputType)); + fstatus = FINVALID_PARAMETER; goto done; + } + + BSWAP_STL_LINK_RECORD(pLR); + MAD_SET_ATTRIB_ID(&mad, STL_SA_ATTR_LINK_RECORD); + + fstatus = sa_query_common(&mad, &pRsp, sizeof (STL_LINK_RECORD), &pQR, port); + if (fstatus != FSUCCESS) break; + + // Translate the data. + pLRR = (STL_LINK_RECORD_RESULTS*)pQR->QueryResult; + pLR = pLRR->LinkRecords; + for (i=0; i< pLRR->NumLinkRecords; i++, pLR++) { + *pLR = * ((STL_LINK_RECORD*)(GET_RESULT_OFFSET(pRsp, i))); + BSWAP_STL_LINK_RECORD(pLR); + } + } + break; + + case OutputTypeStlSwitchInfoRecord: + { + STL_SWITCHINFO_RECORD_RESULTS *pSIR = 0; + STL_SWITCHINFO_RECORD *pSI = (STL_SWITCHINFO_RECORD*)mad.Data; + + switch (pQuery->InputType) { + case InputTypeNoInput: + break; + case InputTypeLid: + mad.SaHdr.ComponentMask = STL_SWITCHINFO_RECORD_COMP_LID; + pSI->RID.LID = pQuery->InputValue.SwitchInfoRecord.Lid; + break; + default: + OMGT_OUTPUT_ERROR(port, "Query not supported by opamgt: Input=%s, Output=%s\n", + iba_sd_query_input_type_msg(pQuery->InputType), + iba_sd_query_result_type_msg(pQuery->OutputType)); + fstatus = FINVALID_PARAMETER; goto done; + } + + pSI->Reserved = 0; + + BSWAP_STL_SWITCHINFO_RECORD(pSI); + MAD_SET_ATTRIB_ID(&mad, STL_SA_ATTR_SWITCHINFO_RECORD); + + fstatus = sa_query_common(&mad, &pRsp, sizeof(STL_SWITCHINFO_RECORD), &pQR, port); + if (fstatus != FSUCCESS) break; + + pSIR = (STL_SWITCHINFO_RECORD_RESULTS*)pQR->QueryResult; + pSI = pSIR->SwitchInfoRecords; + + for (i = 0; i < pSIR->NumSwitchInfoRecords; ++i, ++pSI) { + *pSI = *((STL_SWITCHINFO_RECORD*)(GET_RESULT_OFFSET(pRsp, i))); + BSWAP_STL_SWITCHINFO_RECORD(pSI); + } + } + break; + + case OutputTypeStlSMInfoRecord: + { + STL_SMINFO_RECORD_RESULTS *pSMIR = 0; + STL_SMINFO_RECORD *pSMI = (STL_SMINFO_RECORD*)mad.Data; + + switch (pQuery->InputType) { + case InputTypeNoInput: + break; + default: + OMGT_OUTPUT_ERROR(port, "Query not supported by opamgt: Input=%s, Output=%s\n", + iba_sd_query_input_type_msg(pQuery->InputType), + iba_sd_query_result_type_msg(pQuery->OutputType)); + fstatus = FINVALID_PARAMETER; goto done; + } + + pSMI->Reserved = 0; + + BSWAP_STL_SMINFO_RECORD(pSMI); + MAD_SET_ATTRIB_ID(&mad, STL_SA_ATTR_SMINFO_RECORD); + + fstatus = sa_query_common(&mad, &pRsp, sizeof (STL_SMINFO_RECORD), &pQR, port); + if (fstatus != FSUCCESS) break; + + // Translate the data. + pSMIR = (STL_SMINFO_RECORD_RESULTS*)pQR->QueryResult; + pSMI = pSMIR->SMInfoRecords; + for (i=0; i< pSMIR->NumSMInfoRecords; i++, pSMI++) { + *pSMI = * ((STL_SMINFO_RECORD*)(GET_RESULT_OFFSET(pRsp, i))); + BSWAP_STL_SMINFO_RECORD(pSMI); + } + } + break; + + case OutputTypePathRecord: + case OutputTypePathRecordNetworkOrder: + { + // Nota Bene: Path Records are different from other SA Queries + // because there are two different queries that can result + // in a list of Path Records. The first is an IB_PATH_RECORD + // the second is an IB_MULTIPATH_RECORD. + // + // This slightly complicates the code in that the mad.Data + // buffer may get cast as either record type, depending on + // the input arguments that were provided. + + PATH_RESULTS *pPRR = 0; + IB_PATH_RECORD *pPR = 0; + IB_MULTIPATH_RECORD *pMPR = 0; + uint16_t length = sizeof(IB_PATH_RECORD); + int i; + + switch (pQuery->InputType) { + case InputTypeNoInput: + pPR = (IB_PATH_RECORD *)mad.Data; + MAD_SET_ATTRIB_ID(&mad, SA_ATTRIB_PATH_RECORD); + /* node record query??? */ + mad.SaHdr.ComponentMask = IB_PATH_RECORD_COMP_SGID | + IB_PATH_RECORD_COMP_REVERSIBLE | + IB_PATH_RECORD_COMP_NUMBPATH; + pPR->SGID = pQuery->InputValue.IbPathRecord.SourceGid; + pPR->Reversible = 1; + pPR->NumbPath = PATHRECORD_NUMBPATH; + BSWAP_IB_PATH_RECORD(pPR); + break; + + + case InputTypePKey: + pPR = (IB_PATH_RECORD *)mad.Data; + MAD_SET_ATTRIB_ID(&mad, SA_ATTRIB_PATH_RECORD); + mad.SaHdr.ComponentMask = IB_PATH_RECORD_COMP_SGID | + IB_PATH_RECORD_COMP_PKEY | + IB_PATH_RECORD_COMP_REVERSIBLE | + IB_PATH_RECORD_COMP_NUMBPATH; + pPR->SGID = pQuery->InputValue.IbPathRecord.PKey.SourceGid; + pPR->Reversible = 1; + pPR->P_Key = pQuery->InputValue.IbPathRecord.PKey.PKey; + pPR->NumbPath = PATHRECORD_NUMBPATH; + BSWAP_IB_PATH_RECORD(pPR); + break; + + case InputTypeSL: + pPR = (IB_PATH_RECORD *)mad.Data; + MAD_SET_ATTRIB_ID(&mad, SA_ATTRIB_PATH_RECORD); + mad.SaHdr.ComponentMask = IB_PATH_RECORD_COMP_SGID | + IB_PATH_RECORD_COMP_SL | + IB_PATH_RECORD_COMP_REVERSIBLE | + IB_PATH_RECORD_COMP_NUMBPATH; + pPR->SGID = pQuery->InputValue.IbPathRecord.SL.SourceGid; + pPR->Reversible = 1; + pPR->u2.s.SL = pQuery->InputValue.IbPathRecord.SL.SL; + pPR->NumbPath = PATHRECORD_NUMBPATH; + BSWAP_IB_PATH_RECORD(pPR); + break; + + case InputTypeServiceId: + pPR = (IB_PATH_RECORD *)mad.Data; + MAD_SET_ATTRIB_ID(&mad, SA_ATTRIB_PATH_RECORD); + mad.SaHdr.ComponentMask = IB_PATH_RECORD_COMP_SGID | + IB_PATH_RECORD_COMP_SERVICEID | + IB_PATH_RECORD_COMP_REVERSIBLE | + IB_PATH_RECORD_COMP_NUMBPATH; + pPR->SGID = pQuery->InputValue.IbPathRecord.ServiceId.SourceGid; + pPR->Reversible = 1; + pPR->ServiceID = pQuery->InputValue.IbPathRecord.ServiceId.ServiceId; + pPR->NumbPath = PATHRECORD_NUMBPATH; + BSWAP_IB_PATH_RECORD(pPR); + break; + + case InputTypePortGuid: + case InputTypePortGuidPair: + pPR = (IB_PATH_RECORD *)mad.Data; + MAD_SET_ATTRIB_ID(&mad, SA_ATTRIB_PATH_RECORD); + mad.SaHdr.ComponentMask = IB_PATH_RECORD_COMP_DGID | + IB_PATH_RECORD_COMP_SGID | + IB_PATH_RECORD_COMP_REVERSIBLE | + IB_PATH_RECORD_COMP_NUMBPATH; + pPR->SGID.Type.Global.SubnetPrefix = pQuery->InputValue.IbPathRecord.PortGuid.SharedSubnetPrefix; + pPR->DGID.Type.Global.SubnetPrefix = pQuery->InputValue.IbPathRecord.PortGuid.SharedSubnetPrefix; + pPR->SGID.Type.Global.InterfaceID = pQuery->InputValue.IbPathRecord.PortGuid.SourcePortGuid; + pPR->DGID.Type.Global.InterfaceID = pQuery->InputValue.IbPathRecord.PortGuid.DestPortGuid; + pPR->Reversible = 1; + pPR->NumbPath = PATHRECORD_NUMBPATH; + BSWAP_IB_PATH_RECORD(pPR); + break; + + case InputTypePortGid: + case InputTypeGidPair: + pPR = (IB_PATH_RECORD *)mad.Data; + MAD_SET_ATTRIB_ID(&mad, SA_ATTRIB_PATH_RECORD); + mad.SaHdr.ComponentMask = IB_PATH_RECORD_COMP_DGID | + IB_PATH_RECORD_COMP_SGID | + IB_PATH_RECORD_COMP_REVERSIBLE | + IB_PATH_RECORD_COMP_NUMBPATH; + pPR->DGID = pQuery->InputValue.IbPathRecord.PortGid.DestGid; + pPR->SGID = pQuery->InputValue.IbPathRecord.PortGid.SourceGid; + pPR->Reversible = 1; + pPR->NumbPath = PATHRECORD_NUMBPATH; + BSWAP_IB_PATH_RECORD(pPR); + break; + case InputTypeLid: + pPR = (IB_PATH_RECORD *)mad.Data; + MAD_SET_ATTRIB_ID(&mad, SA_ATTRIB_PATH_RECORD); + // This is going to be tricky. + // I need to specify a source and destination for a path to be valid. + // In this case - I have a dest lid, but my src lid is unknown to me. + // BUT - I have my port lid and can create my port GID. + // So - I'll use a gid for the source and a lid for dest.... + mad.SaHdr.ComponentMask = IB_PATH_RECORD_COMP_DLID | + IB_PATH_RECORD_COMP_SGID | + IB_PATH_RECORD_COMP_REVERSIBLE | + IB_PATH_RECORD_COMP_NUMBPATH; + pPR->SGID = pQuery->InputValue.IbPathRecord.Lid.SourceGid; + pPR->DLID = pQuery->InputValue.IbPathRecord.Lid.DLid; + pPR->Reversible = 1; + pPR->NumbPath = PATHRECORD_NUMBPATH; + BSWAP_IB_PATH_RECORD(pPR); + break; + + case InputTypePathRecord: + case InputTypePathRecordNetworkOrder: + pPR = (IB_PATH_RECORD *)mad.Data; + MAD_SET_ATTRIB_ID(&mad, SA_ATTRIB_PATH_RECORD); + mad.SaHdr.ComponentMask = pQuery->InputValue.IbPathRecord.PathRecord.ComponentMask; + *pPR = pQuery->InputValue.IbPathRecord.PathRecord.PathRecord; + + if (pQuery->InputType == InputTypePathRecord) { + BSWAP_IB_PATH_RECORD(pPR); + } + break; + + default: + OMGT_OUTPUT_ERROR(port, "Query not supported by opamgt: Input=%s, Output=%s\n", + iba_sd_query_input_type_msg(pQuery->InputType), + iba_sd_query_result_type_msg(pQuery->OutputType)); + fstatus = FINVALID_PARAMETER; goto done; + } + + if(pPR){ + pPR->u2.s.Reserved2 = 0; + memset(pPR->Reserved2, 0, sizeof(pPR->Reserved2)); + } + if(pMPR){ + pMPR->u2.s.Reserved2 = 0; + pMPR->Reserved4= 0; + } + + MAD_SET_VERSION_INFO(&mad, + IB_BASE_VERSION, + MCLASS_SUBN_ADM, + IB_SUBN_ADM_CLASS_VERSION); + + fstatus = sa_query_common(&mad, &pRsp, length, &pQR, port); + if (fstatus != FSUCCESS) break; + + // Translate the data. + pPRR = (PATH_RESULTS*)pQR->QueryResult; + pPR = pPRR->PathRecords; + for (i=0; i< pPRR->NumPathRecords; i++, pPR++) { + *pPR = * ((IB_PATH_RECORD*)(GET_RESULT_OFFSET(pRsp, i))); + /* We do not want to swap the OutputTypePathRecordNetworkOrder type */ + if (pQuery->OutputType == OutputTypePathRecord) { + BSWAP_IB_PATH_RECORD(pPR); + } + } + } + break; + + case OutputTypeStlTraceRecord: + { + IB_PATH_RECORD *pPR = (IB_PATH_RECORD*)mad.Data; + STL_TRACE_RECORD_RESULTS *pTRR; + STL_TRACE_RECORD *pTR; + + switch (pQuery->InputType) { + case InputTypePathRecord: + mad.SaHdr.ComponentMask = pQuery->InputValue.TraceRecord.PathRecord.ComponentMask; + *pPR = pQuery->InputValue.TraceRecord.PathRecord.PathRecord; + break; + case InputTypePortGuid: + case InputTypePortGuidPair: + mad.SaHdr.ComponentMask = IB_PATH_RECORD_COMP_DGID | + IB_PATH_RECORD_COMP_SGID | + IB_PATH_RECORD_COMP_REVERSIBLE | + IB_PATH_RECORD_COMP_NUMBPATH; + pPR->SGID.Type.Global.SubnetPrefix = pQuery->InputValue.TraceRecord.PortGuid.SharedSubnetPrefix; + pPR->DGID.Type.Global.SubnetPrefix = pQuery->InputValue.TraceRecord.PortGuid.SharedSubnetPrefix; + pPR->SGID.Type.Global.InterfaceID = pQuery->InputValue.TraceRecord.PortGuid.SourcePortGuid; + pPR->DGID.Type.Global.InterfaceID = pQuery->InputValue.TraceRecord.PortGuid.DestPortGuid; + pPR->Reversible = 1; + pPR->NumbPath = PATHRECORD_NUMBPATH; + break; + case InputTypeGidPair: + case InputTypePortGid: + mad.SaHdr.ComponentMask = IB_PATH_RECORD_COMP_DGID | + IB_PATH_RECORD_COMP_SGID | + IB_PATH_RECORD_COMP_REVERSIBLE | + IB_PATH_RECORD_COMP_NUMBPATH; + pPR->SGID = pQuery->InputValue.TraceRecord.PortGid.SourceGid; + pPR->DGID = pQuery->InputValue.TraceRecord.PortGid.DestGid; + pPR->Reversible = 1; + pPR->NumbPath = PATHRECORD_NUMBPATH; + break; + case InputTypeLid: + mad.SaHdr.ComponentMask = IB_PATH_RECORD_COMP_DLID | + IB_PATH_RECORD_COMP_SLID | + IB_PATH_RECORD_COMP_REVERSIBLE | + IB_PATH_RECORD_COMP_NUMBPATH; + (void)omgt_port_get_port_lid(port, (uint32_t *)&pPR->SLID); + pPR->DLID = pQuery->InputValue.TraceRecord.Lid.DLid; + pPR->Reversible = 1; + pPR->NumbPath = PATHRECORD_NUMBPATH; + break; + + default: + OMGT_OUTPUT_ERROR(port, "Query not supported by opamgt: Input=%s, Output=%s\n", + iba_sd_query_input_type_msg(pQuery->InputType), + iba_sd_query_result_type_msg(pQuery->OutputType)); + fstatus = FINVALID_PARAMETER; goto done; + } + + BSWAP_IB_PATH_RECORD(pPR); + MAD_SET_METHOD_TYPE (&mad, SUBN_ADM_GETTRACETABLE); + MAD_SET_ATTRIB_ID(&mad, STL_SA_ATTR_TRACE_RECORD); + + fstatus = sa_query_common(&mad, &pRsp, sizeof(IB_PATH_RECORD), &pQR, port); + if (fstatus != FSUCCESS) break; + + // Translate the data. + pTRR = (STL_TRACE_RECORD_RESULTS*)pQR->QueryResult; + pTR = pTRR->TraceRecords; + for (i=0; i< pTRR->NumTraceRecords; i++, pTR++) { + *pTR = * ((STL_TRACE_RECORD*)(GET_RESULT_OFFSET(pRsp, i))); + pTR->Reserved = 0; + pTR->Reserved2 = 0; + BSWAP_STL_TRACE_RECORD(pTR); + pTR->NodeID ^= STL_TRACE_RECORD_COMP_ENCRYPT_MASK; + pTR->ChassisID ^= STL_TRACE_RECORD_COMP_ENCRYPT_MASK; + pTR->EntryPortID ^= STL_TRACE_RECORD_COMP_ENCRYPT_MASK; + pTR->ExitPortID ^= STL_TRACE_RECORD_COMP_ENCRYPT_MASK; + } + } + break; + + case OutputTypeServiceRecord: + { + SERVICE_RECORD_RESULTS *pSRR; + IB_SERVICE_RECORD *pSR = (IB_SERVICE_RECORD*)mad.Data; + + switch (pQuery->InputType) { + case InputTypeNoInput: + break; + case InputTypePortGid: + mad.SaHdr.ComponentMask = IB_SERVICE_RECORD_COMP_SERVICEGID; + pSR->RID.ServiceGID = pQuery->InputValue.IbServiceRecord.ServiceGid; + break; + case InputTypeServiceId: + mad.SaHdr.ComponentMask = IB_SERVICE_RECORD_COMP_SERVICEID; + pSR->RID.ServiceID = pQuery->InputValue.IbServiceRecord.ServiceId; + break; + default: + OMGT_OUTPUT_ERROR(port, "Query not supported by opamgt: Input=%s, Output=%s\n", + iba_sd_query_input_type_msg(pQuery->InputType), + iba_sd_query_result_type_msg(pQuery->OutputType)); + fstatus = FINVALID_PARAMETER; goto done; + } + + BSWAP_IB_SERVICE_RECORD(pSR); + MAD_SET_ATTRIB_ID(&mad, SA_ATTRIB_SERVICE_RECORD); + MAD_SET_VERSION_INFO(&mad, IB_BASE_VERSION, MCLASS_SUBN_ADM, + IB_SUBN_ADM_CLASS_VERSION); + + fstatus = sa_query_common(&mad, &pRsp, sizeof (IB_SERVICE_RECORD), &pQR, port); + if (fstatus != FSUCCESS) break; + + // Translate the data. + pSRR = (SERVICE_RECORD_RESULTS*)pQR->QueryResult; + pSR = pSRR->ServiceRecords; + for (i=0; i< pSRR->NumServiceRecords; i++, pSR++) { + *pSR = * ((IB_SERVICE_RECORD*)(GET_RESULT_OFFSET(pRsp, i))); + BSWAP_IB_SERVICE_RECORD(pSR); + } + } + break; + + + case OutputTypeMcMemberRecord: + { + MCMEMBER_RECORD_RESULTS *pIbMCRR; + IB_MCMEMBER_RECORD *pIbMCR = (IB_MCMEMBER_RECORD*)mad.Data; + + switch (pQuery->InputType) { + case InputTypeNoInput: + break; + case InputTypePortGid: + mad.SaHdr.ComponentMask = IB_MCMEMBER_RECORD_COMP_PORTGID; + pIbMCR->RID.PortGID = pQuery->InputValue.IbMcMemberRecord.PortGid; + break; + case InputTypeMcGid: + mad.SaHdr.ComponentMask = IB_MCMEMBER_RECORD_COMP_MGID; + pIbMCR->RID.MGID = pQuery->InputValue.IbMcMemberRecord.McGid; + break; + case InputTypeLid: + mad.SaHdr.ComponentMask = IB_MCMEMBER_RECORD_COMP_MLID; + pIbMCR->MLID = MCAST32_TO_MCAST16(pQuery->InputValue.IbMcMemberRecord.Lid); + break; + case InputTypePKey: + mad.SaHdr.ComponentMask = IB_MCMEMBER_RECORD_COMP_PKEY; + pIbMCR->P_Key = pQuery->InputValue.IbMcMemberRecord.PKey; + break; + case InputTypeSL: + mad.SaHdr.ComponentMask = IB_MCMEMBER_RECORD_COMP_SL; + pIbMCR->u1.s.SL = pQuery->InputValue.IbMcMemberRecord.SL; + break; + default: + OMGT_OUTPUT_ERROR(port, "Query not supported by opamgt: Input=%s, Output=%s\n", + iba_sd_query_input_type_msg(pQuery->InputType), + iba_sd_query_result_type_msg(pQuery->OutputType)); + fstatus = FINVALID_PARAMETER; goto done; + } + + BSWAP_IB_MCMEMBER_RECORD(pIbMCR); + MAD_SET_ATTRIB_ID(&mad, SA_ATTRIB_MCMEMBER_RECORD); + + MAD_SET_VERSION_INFO(&mad, IB_BASE_VERSION, MCLASS_SUBN_ADM, + IB_SUBN_ADM_CLASS_VERSION); + + fstatus = sa_query_common(&mad, &pRsp, sizeof (IB_MCMEMBER_RECORD), &pQR, port); + if (fstatus != FSUCCESS) break; + + // Translate the data. + pIbMCRR = (MCMEMBER_RECORD_RESULTS*)pQR->QueryResult; + pIbMCR = pIbMCRR->McMemberRecords; + for (i=0; i< pIbMCRR->NumMcMemberRecords; i++, pIbMCR++) { + *pIbMCR = * ((IB_MCMEMBER_RECORD*)(GET_RESULT_OFFSET(pRsp, i))); + BSWAP_IB_MCMEMBER_RECORD(pIbMCR); + } + } + break; + + case OutputTypeInformInfoRecord: + { + INFORM_INFO_RECORD_RESULTS *pIIRR; + IB_INFORM_INFO_RECORD *pIIR = (IB_INFORM_INFO_RECORD*)mad.Data; + + switch (pQuery->InputType) { + case InputTypeNoInput: + break; + case InputTypePortGid: + mad.SaHdr.ComponentMask = IB_INFORMINFO_RECORD_COMP_SUBSCRIBERGID; + pIIR->RID.SubscriberGID = pQuery->InputValue.IbInformInfoRecord.SubscriberGID; + break; + default: + OMGT_OUTPUT_ERROR(port, "Query not supported by opamgt: Input=%s, Output=%s\n", + iba_sd_query_input_type_msg(pQuery->InputType), + iba_sd_query_result_type_msg(pQuery->OutputType)); + fstatus = FINVALID_PARAMETER; goto done; + } + + BSWAP_IB_INFORM_INFO_RECORD(pIIR); + MAD_SET_ATTRIB_ID(&mad, SA_ATTRIB_INFORM_INFO_RECORD); + MAD_SET_VERSION_INFO(&mad, IB_BASE_VERSION, MCLASS_SUBN_ADM, + IB_SUBN_ADM_CLASS_VERSION); + + fstatus = sa_query_common(&mad, &pRsp, sizeof (IB_INFORM_INFO_RECORD), &pQR, port); + if (fstatus != FSUCCESS) break; + + // Translate the data. + pIIRR = (INFORM_INFO_RECORD_RESULTS*)pQR->QueryResult; + pIIR = pIIRR->InformInfoRecords; + for (i=0; i< pIIRR->NumInformInfoRecords; i++, pIIR++) { + *pIIR = * ((IB_INFORM_INFO_RECORD*)(GET_RESULT_OFFSET(pRsp, i))); + BSWAP_IB_INFORM_INFO_RECORD(pIIR); + } + } + break; + + case OutputTypeStlInformInfoRecord: + { + STL_INFORM_INFO_RECORD_RESULTS *pIIRR; + STL_INFORM_INFO_RECORD *pIIR = (STL_INFORM_INFO_RECORD*)mad.Data; + + switch (pQuery->InputType) { + case InputTypeNoInput: + break; + case InputTypeLid: + mad.SaHdr.ComponentMask = STL_INFORM_INFO_REC_COMP_SUBSCRIBER_LID; + pIIR->RID.SubscriberLID = pQuery->InputValue.StlInformInfoRecord.SubscriberLID; + break; + default: + OMGT_OUTPUT_ERROR(port, "Query not supported by opamgt: Input=%s, Output=%s\n", + iba_sd_query_input_type_msg(pQuery->InputType), + iba_sd_query_result_type_msg(pQuery->OutputType)); + fstatus = FINVALID_PARAMETER; goto done; + } + + pIIR->Reserved = 0; + + BSWAP_STL_INFORM_INFO_RECORD(pIIR); + MAD_SET_ATTRIB_ID(&mad, STL_SA_ATTR_INFORM_INFO_RECORD); + + fstatus = sa_query_common(&mad, &pRsp, sizeof (STL_INFORM_INFO_RECORD), &pQR, port); + if (fstatus != FSUCCESS) break; + + // Translate the data. + pIIRR = (STL_INFORM_INFO_RECORD_RESULTS*)pQR->QueryResult; + pIIR = pIIRR->InformInfoRecords; + for (i=0; i< pIIRR->NumInformInfoRecords; i++, pIIR++) { + *pIIR = * ((STL_INFORM_INFO_RECORD*)(GET_RESULT_OFFSET(pRsp, i))); + BSWAP_STL_INFORM_INFO_RECORD(pIIR); + } + } + break; + case OutputTypeStlSCSCTableRecord: + { + STL_SC_MAPPING_TABLE_RECORD_RESULTS *pSCSCRR; + STL_SC_MAPPING_TABLE_RECORD *pSCSCR = (STL_SC_MAPPING_TABLE_RECORD*)mad.Data; + + pSCSCR->Reserved = 0; + + switch (pQuery->InputType) { + case InputTypeNoInput: + break; + case InputTypeLid: + mad.SaHdr.ComponentMask = STL_SC2SC_RECORD_COMP_LID; + pSCSCR->RID.LID = pQuery->InputValue.ScScTableRecord.Lid; + break; + default: + OMGT_OUTPUT_ERROR(port, "Query not supported by opamgt: Input=%s, Output=%s\n", + iba_sd_query_input_type_msg(pQuery->InputType), + iba_sd_query_result_type_msg(pQuery->OutputType)); + fstatus = FINVALID_PARAMETER; goto done; + } + + BSWAP_STL_SC_MAPPING_TABLE_RECORD(pSCSCR); + MAD_SET_ATTRIB_ID(&mad, STL_SA_ATTR_SC_MAPTBL_RECORD); + + fstatus = sa_query_common(&mad, &pRsp, sizeof(STL_SC_MAPPING_TABLE_RECORD), &pQR, port); + if (fstatus != FSUCCESS) break; + + pSCSCRR = (STL_SC_MAPPING_TABLE_RECORD_RESULTS*)pQR->QueryResult; + pSCSCR = pSCSCRR->SCSCRecords; + for (i=0; i < pSCSCRR->NumSCSCTableRecords; i++, pSCSCR++) { + *pSCSCR = *((STL_SC_MAPPING_TABLE_RECORD*)(GET_RESULT_OFFSET(pRsp, i))); + BSWAP_STL_SC_MAPPING_TABLE_RECORD(pSCSCR); + } + } + break; + + case OutputTypeStlSLSCTableRecord: + { + STL_SL2SC_MAPPING_TABLE_RECORD_RESULTS *pSLSCRR; + STL_SL2SC_MAPPING_TABLE_RECORD *pSLSCR = (STL_SL2SC_MAPPING_TABLE_RECORD*)mad.Data; + + pSLSCR->RID.Reserved = 0; + pSLSCR->Reserved2 = 0; + + switch (pQuery->InputType) { + case InputTypeNoInput: + break; + case InputTypeLid: + mad.SaHdr.ComponentMask = STL_SL2SC_RECORD_COMP_LID; + pSLSCR->RID.LID = pQuery->InputValue.SlScTableRecord.Lid; + break; + default: + OMGT_OUTPUT_ERROR(port, "Query not supported by opamgt: Input=%s, Output=%s\n", + iba_sd_query_input_type_msg(pQuery->InputType), + iba_sd_query_result_type_msg(pQuery->OutputType)); + fstatus = FINVALID_PARAMETER; + goto done; + } + BSWAP_STL_SL2SC_MAPPING_TABLE_RECORD(pSLSCR); + MAD_SET_ATTRIB_ID(&mad, STL_SA_ATTR_SL2SC_MAPTBL_RECORD); + + fstatus = sa_query_common(&mad, &pRsp, sizeof(STL_SL2SC_MAPPING_TABLE_RECORD), &pQR, port); + if (fstatus != FSUCCESS) { + break; + } + + pSLSCRR = (STL_SL2SC_MAPPING_TABLE_RECORD_RESULTS*)pQR->QueryResult; + pSLSCR = pSLSCRR->SLSCRecords; + for (i=0; i < pSLSCRR->NumSLSCTableRecords; i++, pSLSCR++) { + *pSLSCR = *((STL_SL2SC_MAPPING_TABLE_RECORD*)(GET_RESULT_OFFSET(pRsp, i))); + BSWAP_STL_SL2SC_MAPPING_TABLE_RECORD(pSLSCR); + } + } + break; + + case OutputTypeStlSCSLTableRecord: + { + STL_SC2SL_MAPPING_TABLE_RECORD_RESULTS *pSCSLRR; + STL_SC2SL_MAPPING_TABLE_RECORD *pSCSLR = (STL_SC2SL_MAPPING_TABLE_RECORD*)mad.Data; + + pSCSLR->RID.Reserved = 0; + pSCSLR->Reserved2 = 0; + + switch (pQuery->InputType) { + case InputTypeNoInput: + break; + case InputTypeLid: + mad.SaHdr.ComponentMask = STL_SC2SL_RECORD_COMP_LID; + pSCSLR->RID.LID = pQuery->InputValue.ScSlTableRecord.Lid; + break; + default: + OMGT_OUTPUT_ERROR(port, "Query not supported by opamgt: Input=%s, Output=%s\n", + iba_sd_query_input_type_msg(pQuery->InputType), + iba_sd_query_result_type_msg(pQuery->OutputType)); + fstatus = FINVALID_PARAMETER; + goto done; + } + BSWAP_STL_SC2SL_MAPPING_TABLE_RECORD(pSCSLR); + MAD_SET_ATTRIB_ID(&mad, STL_SA_ATTR_SC2SL_MAPTBL_RECORD); + + fstatus = sa_query_common(&mad, &pRsp, sizeof(STL_SC2SL_MAPPING_TABLE_RECORD), &pQR, port); + if (fstatus != FSUCCESS) { + break; + } + + pSCSLRR = (STL_SC2SL_MAPPING_TABLE_RECORD_RESULTS*)pQR->QueryResult; + pSCSLR = pSCSLRR->SCSLRecords; + for (i=0; i < pSCSLRR->NumSCSLTableRecords; i++, pSCSLR++) { + *pSCSLR = *((STL_SC2SL_MAPPING_TABLE_RECORD*)(GET_RESULT_OFFSET(pRsp, i))); + BSWAP_STL_SC2SL_MAPPING_TABLE_RECORD(pSCSLR); + } + } + break; + case OutputTypeStlSCVLtTableRecord: + { + STL_SC2PVL_T_MAPPING_TABLE_RECORD_RESULTS *pSCVLtRR; + STL_SC2PVL_T_MAPPING_TABLE_RECORD *pSCVLtR = (STL_SC2PVL_T_MAPPING_TABLE_RECORD*)mad.Data; + + switch (pQuery->InputType) { + case InputTypeNoInput: + break; + case InputTypeLid: + mad.SaHdr.ComponentMask = STL_SC2VL_R_RECORD_COMP_LID; + pSCVLtR->RID.LID = pQuery->InputValue.ScVlxTableRecord.Lid; + break; + default: + OMGT_OUTPUT_ERROR(port, "Query not supported by opamgt: Input=%s, Output=%s\n", + iba_sd_query_input_type_msg(pQuery->InputType), + iba_sd_query_result_type_msg(pQuery->OutputType)); + fstatus = FINVALID_PARAMETER; + goto done; + } + BSWAP_STL_SC2VL_R_MAPPING_TABLE_RECORD(pSCVLtR); + MAD_SET_ATTRIB_ID(&mad, STL_SA_ATTR_SC2VL_T_MAPTBL_RECORD); + + fstatus = sa_query_common(&mad, &pRsp, sizeof(STL_SC2PVL_T_MAPPING_TABLE_RECORD), &pQR, port); + if (fstatus != FSUCCESS) { + break; + } + + pSCVLtRR = (STL_SC2PVL_T_MAPPING_TABLE_RECORD_RESULTS*)pQR->QueryResult; + pSCVLtR = pSCVLtRR->SCVLtRecords; + for (i=0; i < pSCVLtRR->NumSCVLtTableRecords; i++, pSCVLtR++) { + *pSCVLtR = *((STL_SC2PVL_T_MAPPING_TABLE_RECORD*)(GET_RESULT_OFFSET(pRsp, i))); + BSWAP_STL_SC2VL_R_MAPPING_TABLE_RECORD(pSCVLtR); + } + } + break; + case OutputTypeStlSCVLntTableRecord: + { + STL_SC2PVL_NT_MAPPING_TABLE_RECORD_RESULTS *pSCVLntRR; + STL_SC2PVL_NT_MAPPING_TABLE_RECORD *pSCVLntR = (STL_SC2PVL_NT_MAPPING_TABLE_RECORD*)mad.Data; + + switch (pQuery->InputType) { + case InputTypeNoInput: + break; + case InputTypeLid: + mad.SaHdr.ComponentMask = STL_SC2VL_R_RECORD_COMP_LID; + pSCVLntR->RID.LID = pQuery->InputValue.ScVlxTableRecord.Lid; + break; + default: + OMGT_OUTPUT_ERROR(port, "Query not supported by opamgt: Input=%s, Output=%s\n", + iba_sd_query_input_type_msg(pQuery->InputType), + iba_sd_query_result_type_msg(pQuery->OutputType)); + fstatus = FINVALID_PARAMETER; + goto done; + } + BSWAP_STL_SC2VL_R_MAPPING_TABLE_RECORD(pSCVLntR); + MAD_SET_ATTRIB_ID(&mad, STL_SA_ATTR_SC2VL_NT_MAPTBL_RECORD); + + fstatus = sa_query_common(&mad, &pRsp, sizeof(STL_SC2PVL_NT_MAPPING_TABLE_RECORD), &pQR, port); + if (fstatus != FSUCCESS) { + break; + } + + pSCVLntRR = (STL_SC2PVL_NT_MAPPING_TABLE_RECORD_RESULTS*)pQR->QueryResult; + pSCVLntR = pSCVLntRR->SCVLntRecords; + for (i=0; i < pSCVLntRR->NumSCVLntTableRecords; i++, pSCVLntR++) { + *pSCVLntR = *((STL_SC2PVL_NT_MAPPING_TABLE_RECORD*)(GET_RESULT_OFFSET(pRsp, i))); + BSWAP_STL_SC2VL_R_MAPPING_TABLE_RECORD(pSCVLntR); + } + } + break; + case OutputTypeStlSCVLrTableRecord: + { + STL_SC2PVL_R_MAPPING_TABLE_RECORD_RESULTS *pSCVLrRR; + STL_SC2PVL_R_MAPPING_TABLE_RECORD *pSCVLrR = (STL_SC2PVL_R_MAPPING_TABLE_RECORD*)mad.Data; + + switch (pQuery->InputType) { + case InputTypeNoInput: + break; + case InputTypeLid: + mad.SaHdr.ComponentMask = STL_SC2VL_R_RECORD_COMP_LID; + pSCVLrR->RID.LID = pQuery->InputValue.ScVlxTableRecord.Lid; + break; + default: + fprintf(stderr, "Query not supported by opamgt: Input=%s, Output=%s\n", + iba_sd_query_input_type_msg(pQuery->InputType), + iba_sd_query_result_type_msg(pQuery->OutputType)); + fstatus = FINVALID_PARAMETER; + goto done; + } + BSWAP_STL_SC2VL_R_MAPPING_TABLE_RECORD(pSCVLrR); + MAD_SET_ATTRIB_ID(&mad, STL_SA_ATTR_SC2VL_R_MAPTBL_RECORD); + + fstatus = sa_query_common(&mad, &pRsp, sizeof(STL_SC2PVL_R_MAPPING_TABLE_RECORD), &pQR, port); + if (fstatus != FSUCCESS) { + break; + } + + pSCVLrRR = (STL_SC2PVL_R_MAPPING_TABLE_RECORD_RESULTS*)pQR->QueryResult; + pSCVLrR = pSCVLrRR->SCVLrRecords; + for (i=0; i < pSCVLrRR->NumSCVLrTableRecords; i++, pSCVLrR++) { + *pSCVLrR = *((STL_SC2PVL_R_MAPPING_TABLE_RECORD*)(GET_RESULT_OFFSET(pRsp, i))); + BSWAP_STL_SC2VL_R_MAPPING_TABLE_RECORD(pSCVLrR); + } + } + break; + case OutputTypeStlVLArbTableRecord: + { + STL_VLARBTABLE_RECORD_RESULTS *pVLRR; + STL_VLARBTABLE_RECORD *pVLR = (STL_VLARBTABLE_RECORD*)mad.Data; + + switch (pQuery->InputType) { + case InputTypeNoInput: + break; + case InputTypeLid: + mad.SaHdr.ComponentMask = STL_VLARB_COMPONENTMASK_LID; + pVLR->RID.LID = pQuery->InputValue.VlArbTableRecord.Lid; + break; + default: + OMGT_OUTPUT_ERROR(port, "Query not supported by opamgt: Input=%s, Output=%s\n", + iba_sd_query_input_type_msg(pQuery->InputType), + iba_sd_query_result_type_msg(pQuery->OutputType)); + fstatus = FINVALID_PARAMETER; goto done; + } + + pVLR->Reserved = 0; + + BSWAP_STL_VLARBTABLE_RECORD(pVLR); + + MAD_SET_ATTRIB_ID(&mad, STL_SA_ATTR_VLARBTABLE_RECORD); + + fstatus = sa_query_common(&mad, &pRsp, sizeof (STL_VLARBTABLE_RECORD), &pQR, port); + if (fstatus != FSUCCESS) break; + + // Translate the data. + pVLRR = (STL_VLARBTABLE_RECORD_RESULTS*)pQR->QueryResult; + pVLR = pVLRR->VLArbTableRecords; + for (i=0; i< pVLRR->NumVLArbTableRecords; i++, pVLR++) { + *pVLR = * ((STL_VLARBTABLE_RECORD*)(GET_RESULT_OFFSET(pRsp, i))); + BSWAP_STL_VLARBTABLE_RECORD(pVLR); + } + } + break; + + + case OutputTypeStlPKeyTableRecord: + { + STL_PKEYTABLE_RECORD_RESULTS *pPKRR; + STL_P_KEY_TABLE_RECORD *pPKR = (STL_P_KEY_TABLE_RECORD*)mad.Data; + + MAD_SET_ATTRIB_ID(&mad, STL_SA_ATTR_P_KEY_TABLE_RECORD); + + switch (pQuery->InputType) { + case InputTypeNoInput: + break; + case InputTypeLid: + mad.SaHdr.ComponentMask = STL_PKEYTABLE_RECORD_COMP_LID; + pPKR->RID.LID = pQuery->InputValue.PKeyTableRecord.Lid; + break; + default: + OMGT_OUTPUT_ERROR(port, "Query not supported by opamgt: Input=%s, Output=%s\n", + iba_sd_query_input_type_msg(pQuery->InputType), + iba_sd_query_result_type_msg(pQuery->OutputType)); + fstatus = FINVALID_PARAMETER; goto done; + } + + pPKR->Reserved = 0; + BSWAP_STL_PARTITION_TABLE_RECORD(pPKR); + + fstatus = sa_query_common(&mad, &pRsp, sizeof (STL_P_KEY_TABLE_RECORD), &pQR, port); + if (fstatus != FSUCCESS) break; + + // Translate the data. + pPKRR = (STL_PKEYTABLE_RECORD_RESULTS*)pQR->QueryResult; + pPKR = pPKRR->PKeyTableRecords; + for (i=0; i< pPKRR->NumPKeyTableRecords; i++, pPKR++) { + *pPKR = * ((STL_P_KEY_TABLE_RECORD*)(GET_RESULT_OFFSET(pRsp, i))); + BSWAP_STL_PARTITION_TABLE_RECORD(pPKR); + } + } + break; + + case OutputTypeStlLinearFDBRecord: + { + STL_LINEAR_FDB_RECORD_RESULTS *pLFRR; + STL_LINEAR_FORWARDING_TABLE_RECORD *pLFR = (STL_LINEAR_FORWARDING_TABLE_RECORD*)mad.Data; + + switch (pQuery->InputType) { + case InputTypeNoInput: + break; + case InputTypeLid: + mad.SaHdr.ComponentMask = STL_LFT_RECORD_COMP_LID; + pLFR->RID.LID = pQuery->InputValue.LinFdbTableRecord.Lid; + break; + default: + OMGT_OUTPUT_ERROR(port, "Query not supported by opamgt: Input=%s, Output=%s\n", + iba_sd_query_input_type_msg(pQuery->InputType), + iba_sd_query_result_type_msg(pQuery->OutputType)); + fstatus = FINVALID_PARAMETER; goto done; + } + + pLFR->RID.Reserved = 0; + + BSWAP_STL_LINEAR_FORWARDING_TABLE_RECORD(pLFR); + MAD_SET_ATTRIB_ID(&mad, STL_SA_ATTR_LINEAR_FWDTBL_RECORD); + + fstatus = sa_query_common(&mad, &pRsp, sizeof (STL_LINEAR_FORWARDING_TABLE_RECORD), &pQR, port); + if (fstatus != FSUCCESS) break; + + // Translate the data. + pLFRR = (STL_LINEAR_FDB_RECORD_RESULTS*)pQR->QueryResult; + pLFR = pLFRR->LinearFDBRecords; + for (i=0; i< pLFRR->NumLinearFDBRecords; i++, pLFR++) { + *pLFR = * ((STL_LINEAR_FORWARDING_TABLE_RECORD*)(GET_RESULT_OFFSET(pRsp, i))); + BSWAP_STL_LINEAR_FORWARDING_TABLE_RECORD(pLFR); + } + } + break; + + + case OutputTypeStlMCastFDBRecord: + { + STL_MCAST_FDB_RECORD_RESULTS *pMFRR; + STL_MULTICAST_FORWARDING_TABLE_RECORD *pMFR = (STL_MULTICAST_FORWARDING_TABLE_RECORD*)mad.Data; + + switch (pQuery->InputType) { + case InputTypeNoInput: + break; + case InputTypeLid: + mad.SaHdr.ComponentMask = STL_MFTB_RECORD_COMP_LID; + pMFR->RID.LID = pQuery->InputValue.McFdbTableRecord.Lid; + break; + default: + OMGT_OUTPUT_ERROR(port, "Query not supported by opamgt: Input=%s, Output=%s\n", + iba_sd_query_input_type_msg(pQuery->InputType), + iba_sd_query_result_type_msg(pQuery->OutputType)); + fstatus = FINVALID_PARAMETER; goto done; + } + + pMFR->RID.u1.s.Reserved = 0; + + BSWAP_STL_MCFTB_RECORD(pMFR); + MAD_SET_ATTRIB_ID(&mad, SA_ATTRIB_MCAST_FWDTBL_RECORD); + + fstatus = sa_query_common(&mad, &pRsp, sizeof (STL_MULTICAST_FORWARDING_TABLE_RECORD), &pQR, port); + if (fstatus != FSUCCESS) break; + + // Translate the data. + pMFRR = (STL_MCAST_FDB_RECORD_RESULTS*)pQR->QueryResult; + pMFR = pMFRR->MCastFDBRecords; + for (i=0; i< pMFRR->NumMCastFDBRecords; i++, pMFR++) { + *pMFR = * ((STL_MULTICAST_FORWARDING_TABLE_RECORD*)(GET_RESULT_OFFSET(pRsp, i))); + BSWAP_STL_MCFTB_RECORD(pMFR); + } + } + break; + + case OutputTypeStlVfInfoRecord: + { + STL_VFINFO_RECORD_RESULTS *pVFRR; + STL_VFINFO_RECORD *pVFR = (STL_VFINFO_RECORD*)mad.Data; + + switch (pQuery->InputType) { + case InputTypeNoInput: + break; + case InputTypePKey: + mad.SaHdr.ComponentMask = STL_VFINFO_REC_COMP_PKEY; + pVFR->pKey = pQuery->InputValue.VfInfoRecord.PKey; + break; + case InputTypeSL: + mad.SaHdr.ComponentMask = STL_VFINFO_REC_COMP_SL; + pVFR->s1.slBase = pQuery->InputValue.VfInfoRecord.SL; + break; + case InputTypeServiceId: + mad.SaHdr.ComponentMask = STL_VFINFO_REC_COMP_SERVICEID; + pVFR->ServiceID = pQuery->InputValue.VfInfoRecord.ServiceId; + break; + case InputTypeMcGid: + mad.SaHdr.ComponentMask = STL_VFINFO_REC_COMP_MGID; + pVFR->MGID = pQuery->InputValue.VfInfoRecord.McGid; + break; + case InputTypeIndex: + mad.SaHdr.ComponentMask = STL_VFINFO_REC_COMP_INDEX; + pVFR->vfIndex = pQuery->InputValue.VfInfoRecord.vfIndex; + break; + case InputTypeNodeDesc: + mad.SaHdr.ComponentMask = STL_VFINFO_REC_COMP_NAME; + memcpy(pVFR->vfName, pQuery->InputValue.VfInfoRecord.vfName, + STL_VFABRIC_NAME_LEN); + break; + default: + OMGT_OUTPUT_ERROR(port, "Query not supported by opamgt: Input=%s, Output=%s\n", + iba_sd_query_input_type_msg(pQuery->InputType), + iba_sd_query_result_type_msg(pQuery->OutputType)); + fstatus = FINVALID_PARAMETER; goto done; + } + + pVFR->rsvd1 = 0; + pVFR->s1.rsvd2 = 0; + pVFR->s1.rsvd3 = 0; + pVFR->s1.rsvd4 = 0; + pVFR->s1.rsvd5 = 0; + pVFR->rsvd6 = 0; + pVFR->rsvd7 = 0; + pVFR->rsvd8 = 0; + pVFR->rsvd9 = 0; + pVFR->rsvd10 = 0; + memset(pVFR->rsvd11, 0, sizeof(pVFR->rsvd11)); + + BSWAP_STL_VFINFO_RECORD(pVFR); + MAD_SET_ATTRIB_ID(&mad, STL_SA_ATTR_VF_INFO_RECORD); + + fstatus = sa_query_common(&mad, &pRsp, sizeof(STL_VFINFO_RECORD), &pQR, port); + if (fstatus != FSUCCESS) break; + + // Translate the data. + pVFRR = (STL_VFINFO_RECORD_RESULTS*)pQR->QueryResult; + pVFR = pVFRR->VfInfoRecords; + for (i=0; i< pVFRR->NumVfInfoRecords; i++, pVFR++) { + *pVFR = * ((STL_VFINFO_RECORD*)(GET_RESULT_OFFSET(pRsp, i))); + BSWAP_STL_VFINFO_RECORD(pVFR); + } + } + break; + + case OutputTypeStlFabricInfoRecord: + { + STL_FABRICINFO_RECORD_RESULT *pFIR; + STL_FABRICINFO_RECORD *pFI; + + if (pQuery->InputType != InputTypeNoInput) { + OMGT_OUTPUT_ERROR(port, "Query not supported by opamgt: Input=%s, Output=%s\n", + iba_sd_query_input_type_msg(pQuery->InputType), + iba_sd_query_result_type_msg(pQuery->OutputType)); + + fstatus = FINVALID_PARAMETER; goto done; + } + + MAD_SET_ATTRIB_ID(&mad, STL_SA_ATTR_FABRICINFO_RECORD); + MAD_SET_METHOD_TYPE(&mad, SUBN_ADM_GET); + + fstatus = sa_query_common(&mad, &pRsp, sizeof(STL_FABRICINFO_RECORD), &pQR, port); + if (fstatus != FSUCCESS) break; + + pFIR = (STL_FABRICINFO_RECORD_RESULT*)pQR->QueryResult; + pFI = &pFIR->FabricInfoRecord; + + // There should only be one FabricInfoRecord result. + if (pFIR->NumFabricInfoRecords > 0) { + *pFI = *((STL_FABRICINFO_RECORD*)(GET_RESULT_OFFSET(pRsp, 0))); + BSWAP_STL_FABRICINFO_RECORD(pFI); + } + } + break; + + case OutputTypeStlQuarantinedNodeRecord: + { + STL_QUARANTINED_NODE_RECORD_RESULTS *pQNRR; + STL_QUARANTINED_NODE_RECORD *pQNR = (STL_QUARANTINED_NODE_RECORD*)mad.Data; + + if(pQuery->InputType != InputTypeNoInput) + { + OMGT_OUTPUT_ERROR(port, "Query not supported by opamgt: Input=%s, Output=%s\n", + iba_sd_query_input_type_msg(pQuery->InputType), + iba_sd_query_result_type_msg(pQuery->OutputType)); + fstatus = FINVALID_PARAMETER; goto done; + } + + BSWAP_STL_QUARANTINED_NODE_RECORD(pQNR); + MAD_SET_ATTRIB_ID(&mad, STL_SA_ATTR_QUARANTINED_NODE_RECORD); + + fstatus = sa_query_common(&mad, &pRsp, sizeof(STL_QUARANTINED_NODE_RECORD), &pQR, port); + if(fstatus != FSUCCESS) break; + + // Translate the data + pQNRR = (STL_QUARANTINED_NODE_RECORD_RESULTS*) pQR->QueryResult; + pQNR = pQNRR->QuarantinedNodeRecords; + + for(i = 0; i < pQNRR->NumQuarantinedNodeRecords; i++, pQNR++) + { + *pQNR = * ((STL_QUARANTINED_NODE_RECORD*)(GET_RESULT_OFFSET(pRsp, i))); + + BSWAP_STL_QUARANTINED_NODE_RECORD(pQNR); + } + break; + } + + case OutputTypeStlCongInfoRecord: + { + STL_CONGESTION_INFO_RECORD_RESULTS *pRecResults; + STL_CONGESTION_INFO_RECORD *pRec = (STL_CONGESTION_INFO_RECORD*)mad.Data; + + switch (pQuery->InputType) { + case InputTypeNoInput: + break; + case InputTypeLid: + mad.SaHdr.ComponentMask = CIR_COMPONENTMASK_COMP_LID; + pRec->LID = pQuery->InputValue.CongInfoRecord.Lid; + break; + default: + OMGT_OUTPUT_ERROR(port, "Query not supported by opamgt: Input=%s, Output=%s\n", + iba_sd_query_input_type_msg(pQuery->InputType), + iba_sd_query_result_type_msg(pQuery->OutputType)); + fstatus = FINVALID_PARAMETER; goto done; + } + + pRec->reserved = 0; + + BSWAP_STL_CONGESTION_INFO_RECORD(pRec); + MAD_SET_ATTRIB_ID(&mad, STL_SA_ATTR_CONGESTION_INFO_RECORD); + + fstatus = sa_query_common(&mad, &pRsp, sizeof(STL_CONGESTION_INFO_RECORD), &pQR, port); + if(fstatus != FSUCCESS) break; + + // Translate the data + pRecResults = (STL_CONGESTION_INFO_RECORD_RESULTS*)pQR->QueryResult; + pRec = pRecResults->Records; + + for(i = 0; i < pRecResults->NumRecords; i++, pRec++) + { + *pRec = * ((STL_CONGESTION_INFO_RECORD*)(GET_RESULT_OFFSET(pRsp, i))); + BSWAP_STL_CONGESTION_INFO_RECORD(pRec); + } + break; + } + case OutputTypeStlSwitchCongRecord: + { + STL_SWITCH_CONGESTION_SETTING_RECORD_RESULTS *pRecResults; + STL_SWITCH_CONGESTION_SETTING_RECORD *pRec = (STL_SWITCH_CONGESTION_SETTING_RECORD*)mad.Data; + + switch (pQuery->InputType) { + case InputTypeNoInput: + break; + case InputTypeLid: + mad.SaHdr.ComponentMask = SWCSR_COMPONENTMASK_COMP_LID; + pRec->LID = pQuery->InputValue.SwCongRecord.Lid; + break; + default: + OMGT_OUTPUT_ERROR(port, "Query not supported by opamgt: Input=%s, Output=%s\n", + iba_sd_query_input_type_msg(pQuery->InputType), + iba_sd_query_result_type_msg(pQuery->OutputType)); + fstatus = FINVALID_PARAMETER; goto done; + } + + pRec->reserved = 0; + + BSWAP_STL_SWITCH_CONGESTION_SETTING_RECORD(pRec); + MAD_SET_ATTRIB_ID(&mad, STL_SA_ATTR_SWITCH_CONG_RECORD); + + fstatus = sa_query_common(&mad, &pRsp, sizeof(STL_SWITCH_CONGESTION_SETTING_RECORD), &pQR, port); + if(fstatus != FSUCCESS) break; + + // Translate the data + pRecResults = (STL_SWITCH_CONGESTION_SETTING_RECORD_RESULTS*)pQR->QueryResult; + pRec = pRecResults->Records; + + for(i = 0; i < pRecResults->NumRecords; i++, pRec++) + { + *pRec = * ((STL_SWITCH_CONGESTION_SETTING_RECORD*)(GET_RESULT_OFFSET(pRsp, i))); + BSWAP_STL_SWITCH_CONGESTION_SETTING_RECORD(pRec); + } + break; + } + + case OutputTypeStlSwitchPortCongRecord: + { + STL_SWITCH_PORT_CONGESTION_SETTING_RECORD_RESULTS *pRecResults; + STL_SWITCH_PORT_CONGESTION_SETTING_RECORD *pRec = (STL_SWITCH_PORT_CONGESTION_SETTING_RECORD*)mad.Data; + + switch (pQuery->InputType) { + case InputTypeNoInput: + break; + case InputTypeLid: + mad.SaHdr.ComponentMask = SWPCSR_COMPONENTMASK_COMP_LID; + pRec->RID.LID = pQuery->InputValue.SwPortCongRecord.Lid; + break; + default: + OMGT_OUTPUT_ERROR(port, "Query not supported by opamgt: Input=%s, Output=%s\n", + iba_sd_query_input_type_msg(pQuery->InputType), + iba_sd_query_result_type_msg(pQuery->OutputType)); + fstatus = FINVALID_PARAMETER; goto done; + } + + memset(pRec->Reserved, 0, sizeof(pRec->Reserved)); + + BSWAP_STL_SWITCH_PORT_CONGESTION_SETTING_RECORD(pRec); + MAD_SET_ATTRIB_ID(&mad, STL_SA_ATTR_SWITCH_PORT_CONG_RECORD); + + fstatus = sa_query_common(&mad, &pRsp, sizeof(STL_SWITCH_PORT_CONGESTION_SETTING_RECORD), &pQR, port); + if(fstatus != FSUCCESS) break; + + // Translate the data + pRecResults = (STL_SWITCH_PORT_CONGESTION_SETTING_RECORD_RESULTS*)pQR->QueryResult; + pRec = pRecResults->Records; + + for(i = 0; i < pRecResults->NumRecords; i++, pRec++) + { + *pRec = * ((STL_SWITCH_PORT_CONGESTION_SETTING_RECORD*)(GET_RESULT_OFFSET(pRsp, i))); + BSWAP_STL_SWITCH_PORT_CONGESTION_SETTING_RECORD(pRec); + } + break; + } + + case OutputTypeStlHFICongRecord: + { + STL_HFI_CONGESTION_SETTING_RECORD_RESULTS *pRecResults; + STL_HFI_CONGESTION_SETTING_RECORD *pRec = (STL_HFI_CONGESTION_SETTING_RECORD*)mad.Data; + + switch (pQuery->InputType) { + case InputTypeNoInput: + break; + case InputTypeLid: + mad.SaHdr.ComponentMask = HCSR_COMPONENTMASK_COMP_LID; + pRec->LID = pQuery->InputValue.HFICongRecord.Lid; + break; + default: + OMGT_OUTPUT_ERROR(port, "Query not supported by opamgt: Input=%s, Output=%s\n", + iba_sd_query_input_type_msg(pQuery->InputType), + iba_sd_query_result_type_msg(pQuery->OutputType)); + fstatus = FINVALID_PARAMETER; goto done; + } + + pRec->reserved = 0; + + BSWAP_STL_HFI_CONGESTION_SETTING_RECORD(pRec); + MAD_SET_ATTRIB_ID(&mad, STL_SA_ATTR_HFI_CONG_RECORD); + + fstatus = sa_query_common(&mad, &pRsp, sizeof(STL_HFI_CONGESTION_SETTING_RECORD), &pQR, port); + if(fstatus != FSUCCESS) break; + + // Translate the data + pRecResults = (STL_HFI_CONGESTION_SETTING_RECORD_RESULTS*)pQR->QueryResult; + pRec = pRecResults->Records; + + for(i = 0; i < pRecResults->NumRecords; i++, pRec++) + { + *pRec = * ((STL_HFI_CONGESTION_SETTING_RECORD*)(GET_RESULT_OFFSET(pRsp, i))); + BSWAP_STL_HFI_CONGESTION_SETTING_RECORD(pRec); + } + break; + } + + case OutputTypeStlHFICongCtrlRecord: + { + STL_HFI_CONGESTION_CONTROL_TABLE_RECORD_RESULTS *pRecResults; + STL_HFI_CONGESTION_CONTROL_TABLE_RECORD *pRec = (STL_HFI_CONGESTION_CONTROL_TABLE_RECORD*)mad.Data; + + switch (pQuery->InputType) { + case InputTypeNoInput: + break; + case InputTypeLid: + mad.SaHdr.ComponentMask = HCCTR_COMPONENTMASK_COMP_LID; + pRec->RID.LID = pQuery->InputValue.HFICongCtrlRecord.Lid; + break; + default: + OMGT_OUTPUT_ERROR(port, "Query not supported by opamgt: Input=%s, Output=%s\n", + iba_sd_query_input_type_msg(pQuery->InputType), + iba_sd_query_result_type_msg(pQuery->OutputType)); + fstatus = FINVALID_PARAMETER; goto done; + } + + pRec->reserved = 0; + + BSWAP_STL_HFI_CONGESTION_CONTROL_TABLE_RECORD(pRec); + MAD_SET_ATTRIB_ID(&mad, STL_SA_ATTR_HFI_CONG_CTRL_RECORD); + + fstatus = sa_query_common(&mad, &pRsp, sizeof(STL_HFI_CONGESTION_CONTROL_TABLE_RECORD), &pQR, port); + if(fstatus != FSUCCESS) break; + + // Translate the data + pRecResults = (STL_HFI_CONGESTION_CONTROL_TABLE_RECORD_RESULTS*)pQR->QueryResult; + pRec = pRecResults->Records; + + for(i = 0; i < pRecResults->NumRecords; i++, pRec++) + { + *pRec = * ((STL_HFI_CONGESTION_CONTROL_TABLE_RECORD*)(GET_RESULT_OFFSET(pRsp, i))); + BSWAP_STL_HFI_CONGESTION_CONTROL_TABLE_RECORD(pRec); + } + break; + } + + case OutputTypeStlBufCtrlTabRecord: + { + STL_BUFFER_CONTROL_TABLE_RECORD_RESULTS *pBCTRR; + STL_BUFFER_CONTROL_TABLE_RECORD *pBCTR = (STL_BUFFER_CONTROL_TABLE_RECORD *)mad.Data; + + switch (pQuery->InputType) { + case InputTypeNoInput: + break; + case InputTypeLid: + mad.SaHdr.ComponentMask = BFCTRL_COMPONENTMASK_COMP_LID; + pBCTR->RID.LID = pQuery->InputValue.BufCtrlTableRecord.Lid; + break; + default: + OMGT_OUTPUT_ERROR(port, "Query not supported by opamgt: Input=%s, Output=%s\n", + iba_sd_query_input_type_msg(pQuery->InputType), + iba_sd_query_result_type_msg(pQuery->OutputType)); + fstatus = FINVALID_PARAMETER; goto done; + } + + memset(pBCTR->Reserved, 0, sizeof(pBCTR->Reserved)); + + BSWAP_STL_BUFFER_CONTROL_TABLE_RECORD(pBCTR); + MAD_SET_ATTRIB_ID(&mad, STL_SA_ATTR_BUFF_CTRL_TAB_RECORD); + + fstatus = sa_query_common(&mad, &pRsp, sizeof (STL_BUFFER_CONTROL_TABLE_RECORD), &pQR, port); + if (fstatus != FSUCCESS) goto done; + + // Translate the data. + pBCTRR = (STL_BUFFER_CONTROL_TABLE_RECORD_RESULTS*)pQR->QueryResult; + pBCTR = pBCTRR->BufferControlRecords; + for (i=0; i< pBCTRR->NumBufferControlRecords; i++, pBCTR++) { + *pBCTR = * ((STL_BUFFER_CONTROL_TABLE_RECORD*)(GET_RESULT_OFFSET(pRsp, i))); + BSWAP_STL_BUFFER_CONTROL_TABLE_RECORD(pBCTR); + } + break; + } + case OutputTypeStlCableInfoRecord: + { + STL_CABLE_INFO_RECORD_RESULTS *pCIRR; + STL_CABLE_INFO_RECORD *pCIR = (STL_CABLE_INFO_RECORD *)mad.Data; + + switch (pQuery->InputType) { + case InputTypeNoInput: + break; + case InputTypeLid: + mad.SaHdr.ComponentMask |= STL_CIR_COMP_LID; + pCIR->LID = pQuery->InputValue.CableInfoRecord.Lid; + break; + default: + OMGT_OUTPUT_ERROR(port, "Query not supported by opamgt: Input=%s, Output=%s\n", + iba_sd_query_input_type_msg(pQuery->InputType), + iba_sd_query_result_type_msg(pQuery->OutputType)); + fstatus = FINVALID_PARAMETER; goto done; + break; + } + + pCIR->Reserved = 0; + + // Default values. + mad.SaHdr.ComponentMask |= STL_CIR_COMP_LEN | STL_CIR_COMP_ADDR; + pCIR->Length = STL_CABLE_INFO_PAGESZ - 1; + pCIR->u1.s.Address = STL_CIB_STD_HIGH_PAGE_ADDR; + + BSWAP_STL_CABLE_INFO_RECORD(pCIR); + MAD_SET_ATTRIB_ID(&mad, STL_SA_ATTR_CABLE_INFO_RECORD); + + fstatus = sa_query_common(&mad, &pRsp, sizeof(STL_CABLE_INFO_RECORD), &pQR, port); + if (fstatus != FSUCCESS) goto done; + + pCIRR = (STL_CABLE_INFO_RECORD_RESULTS *)pQR->QueryResult; + pCIR = pCIRR->CableInfoRecords; + for (i=0; i < pCIRR->NumCableInfoRecords; ++i, pCIR++) { + *pCIR = *((STL_CABLE_INFO_RECORD*)(GET_RESULT_OFFSET(pRsp, i))); + BSWAP_STL_CABLE_INFO_RECORD(pCIR); + } + break; + } + case OutputTypeStlPortGroupRecord: + { + STL_PORT_GROUP_TABLE_RECORD_RESULTS *pRecResults; + STL_PORT_GROUP_TABLE_RECORD *pRec = (STL_PORT_GROUP_TABLE_RECORD*)mad.Data; + + switch (pQuery->InputType) { + case InputTypeNoInput: + break; + case InputTypeLid: + mad.SaHdr.ComponentMask = STL_PGTB_RECORD_COMP_LID; + pRec->RID.LID = pQuery->InputValue.PortGroupRecord.Lid; + break; + default: + OMGT_OUTPUT_ERROR(port, "Query not supported by opamgt: Input=%s, Output=%s\n", + iba_sd_query_input_type_msg(pQuery->InputType), + iba_sd_query_result_type_msg(pQuery->OutputType)); + fstatus = FINVALID_PARAMETER; goto done; + } + pRec->RID.Reserved = 0; + pRec->Reserved2 = 0; + + BSWAP_STL_PORT_GROUP_TABLE_RECORD(pRec); + MAD_SET_ATTRIB_ID(&mad, STL_SA_ATTR_PORTGROUP_TABLE_RECORD); + + fstatus = sa_query_common(&mad, &pRsp, sizeof(STL_PORT_GROUP_TABLE_RECORD), &pQR, port); + if(fstatus != FSUCCESS) break; + + // Translate the data + pRecResults = (STL_PORT_GROUP_TABLE_RECORD_RESULTS*)pQR->QueryResult; + pRec = pRecResults->Records; + + for(i = 0; i < pRecResults->NumRecords; i++, pRec++) + { + *pRec = * ((STL_PORT_GROUP_TABLE_RECORD*)(GET_RESULT_OFFSET(pRsp, i))); + BSWAP_STL_PORT_GROUP_TABLE_RECORD(pRec); + } + break; + } + case OutputTypeStlPortGroupFwdRecord: + { + STL_PORT_GROUP_FORWARDING_TABLE_RECORD_RESULTS *pRecResults; + STL_PORT_GROUP_FORWARDING_TABLE_RECORD *pRec = (STL_PORT_GROUP_FORWARDING_TABLE_RECORD*)mad.Data; + + switch (pQuery->InputType) { + case InputTypeNoInput: + break; + case InputTypeLid: + mad.SaHdr.ComponentMask = STL_PGFWDTB_RECORD_COMP_LID; + pRec->RID.LID = pQuery->InputValue.PortGroupFwdRecord.Lid; + break; + default: + OMGT_OUTPUT_ERROR(port, "Query not supported by opamgt: Input=%s, Output=%s\n", + iba_sd_query_input_type_msg(pQuery->InputType), + iba_sd_query_result_type_msg(pQuery->OutputType)); + fstatus = FINVALID_PARAMETER; goto done; + } + + pRec->RID.u1.s.Reserved = 0; + + BSWAP_STL_PORT_GROUP_FORWARDING_TABLE_RECORD(pRec); + MAD_SET_ATTRIB_ID(&mad, STL_SA_ATTR_PGROUP_FWDTBL_RECORD); + + fstatus = sa_query_common(&mad, &pRsp, sizeof(STL_PORT_GROUP_FORWARDING_TABLE_RECORD), &pQR, port); + if(fstatus != FSUCCESS) break; + + // Translate the data + pRecResults = (STL_PORT_GROUP_FORWARDING_TABLE_RECORD_RESULTS*)pQR->QueryResult; + pRec = pRecResults->Records; + + for(i = 0; i < pRecResults->NumRecords; i++, pRec++) + { + *pRec = * ((STL_PORT_GROUP_FORWARDING_TABLE_RECORD*)(GET_RESULT_OFFSET(pRsp, i))); + BSWAP_STL_PORT_GROUP_FORWARDING_TABLE_RECORD(pRec); + } + break; + } + + case OutputTypeStlDeviceGroupMemberRecord: + { + STL_DEVICE_GROUP_MEMBER_RECORD_RESULTS *pRecResults; + STL_DEVICE_GROUP_MEMBER_RECORD *pRec = (STL_DEVICE_GROUP_MEMBER_RECORD*)mad.Data; + + switch (pQuery->InputType) { + + case InputTypeNoInput: + mad.SaHdr.ComponentMask = 0; + break; + case InputTypeLid: + mad.SaHdr.ComponentMask = STL_DEVICE_GROUP_COMPONENTMASK_LID; + pRec->LID = pQuery->InputValue.DgGrpMemberRecord.Lid; + break; + case InputTypePortGuid: + mad.SaHdr.ComponentMask = STL_DEVICE_GROUP_COMPONENTMASK_GUID; + pRec->GUID = pQuery->InputValue.DgGrpMemberRecord.Guid; + break; + case InputTypeNodeDesc: + mad.SaHdr.ComponentMask = STL_DEVICE_GROUP_COMPONENTMASK_NODEDESC; + memcpy(pRec->NodeDescription.NodeString, pQuery->InputValue.DgGrpMemberRecord.NodeDesc, + STL_NODE_DESCRIPTION_ARRAY_SIZE); + break; + case InputTypeDeviceGroup: + mad.SaHdr.ComponentMask = STL_DEVICE_GROUP_COMPONENTMASK_DGNAME; + memcpy(pRec->DeviceGroupName, pQuery->InputValue.DgGrpMemberRecord.DeviceGroup, + MAX_DG_NAME); + break; + default: + fprintf(stderr, "Query not supported by opamgt: Input=%s, Output=%s\n", + iba_sd_query_input_type_msg(pQuery->InputType), + iba_sd_query_result_type_msg(pQuery->OutputType)); + fstatus = FINVALID_PARAMETER; + goto done; + } + + BSWAP_STL_DEVICE_GROUP_MEMBER_RECORD(pRec); + MAD_SET_ATTRIB_ID(&mad, STL_SA_ATTR_DG_MEMBER_RECORD); + + fstatus = sa_query_common(&mad, &pRsp, sizeof(STL_DEVICE_GROUP_MEMBER_RECORD), &pQR, port); + if(fstatus != FSUCCESS) break; + + // Translate the data + pRecResults = (STL_DEVICE_GROUP_MEMBER_RECORD_RESULTS*)pQR->QueryResult; + pRec = pRecResults->Records; + + for(i = 0; i < pRecResults->NumRecords; i++, pRec++) + { + *pRec = * ((STL_DEVICE_GROUP_MEMBER_RECORD*)(GET_RESULT_OFFSET(pRsp, i))); + BSWAP_STL_DEVICE_GROUP_MEMBER_RECORD(pRec); + } + break; + } + + case OutputTypeStlDeviceGroupNameRecord: + { + STL_DEVICE_GROUP_NAME_RECORD_RESULTS *pRecResults; + STL_DEVICE_GROUP_NAME_RECORD *pRec = (STL_DEVICE_GROUP_NAME_RECORD*)mad.Data; + + switch (pQuery->InputType) { + case InputTypeNoInput: + mad.SaHdr.ComponentMask = 0; + break; + default: + fprintf(stderr, "Query not supported by opamgt: Input=%s, Output=%s\n", + iba_sd_query_input_type_msg(pQuery->InputType), + iba_sd_query_result_type_msg(pQuery->OutputType)); + fstatus = FINVALID_PARAMETER; + goto done; + } + + BSWAP_STL_DEVICE_GROUP_NAME_RECORD(pRec); + MAD_SET_ATTRIB_ID(&mad, STL_SA_ATTR_DG_NAME_RECORD); + + fstatus = sa_query_common(&mad, &pRsp, sizeof(STL_DEVICE_GROUP_NAME_RECORD), &pQR, port); + if(fstatus != FSUCCESS) break; + + // Translate the data + pRecResults = (STL_DEVICE_GROUP_NAME_RECORD_RESULTS*)pQR->QueryResult; + pRec = pRecResults->Records; + + for(i = 0; i < pRecResults->NumRecords; i++, pRec++) + { + *pRec = * ((STL_DEVICE_GROUP_NAME_RECORD*)(GET_RESULT_OFFSET(pRsp, i))); + BSWAP_STL_DEVICE_GROUP_NAME_RECORD(pRec); + } + break; + } + + case OutputTypeStlDeviceTreeMemberRecord: + { + STL_DEVICE_TREE_MEMBER_RECORD_RESULTS *pRecResults; + STL_DEVICE_TREE_MEMBER_RECORD *pRec = (STL_DEVICE_TREE_MEMBER_RECORD*)mad.Data; + + switch (pQuery->InputType) { + + case InputTypeNoInput: + mad.SaHdr.ComponentMask = 0; + break; + + case InputTypeLid: + mad.SaHdr.ComponentMask = STL_DEVICE_TREE_COMPONENTMASK_LID; + pRec->LID = pQuery->InputValue.DgTreeMemberRecord.Lid; + break; + default: + fprintf(stderr, "Query not supported by opamgt: Input=%s, Output=%s\n", + iba_sd_query_input_type_msg(pQuery->InputType), + iba_sd_query_result_type_msg(pQuery->OutputType)); + fstatus = FINVALID_PARAMETER; + goto done; + } + + BSWAP_STL_DEVICE_TREE_MEMBER_RECORD(pRec); + MAD_SET_ATTRIB_ID(&mad, STL_SA_ATTR_DT_MEMBER_RECORD); + + fstatus = sa_query_common(&mad, &pRsp, sizeof(STL_DEVICE_TREE_MEMBER_RECORD), &pQR, port); + if(fstatus != FSUCCESS) break; + + // Translate the data + pRecResults = (STL_DEVICE_TREE_MEMBER_RECORD_RESULTS*)pQR->QueryResult; + pRec = pRecResults->Records; + + for(i = 0; i < pRecResults->NumRecords; i++, pRec++) + { + *pRec = * ((STL_DEVICE_TREE_MEMBER_RECORD*)(GET_RESULT_OFFSET(pRsp, i))); + BSWAP_STL_DEVICE_TREE_MEMBER_RECORD(pRec); + } + break; + } + case OutputTypeStlSwitchCostRecord: + { + STL_SWITCH_COST_RECORD_RESULTS *pSCR; + STL_SWITCH_COST_RECORD *pSC = (STL_SWITCH_COST_RECORD *)mad.Data; + + switch(pQuery->InputType) { + case InputTypeNoInput: + break; + case InputTypeLid: + mad.SaHdr.ComponentMask = STL_SWITCH_COST_REC_COMP_SLID; + pSC->SLID = pQuery->InputValue.SwitchCostRecord.Lid; + break; + default: + OMGT_OUTPUT_ERROR(port, "Query not supported by opamgt: Input=%s, Output=%s\n", + iba_sd_query_input_type_msg(pQuery->InputType), + iba_sd_query_result_type_msg(pQuery->OutputType)); + fstatus = FINVALID_PARAMETER; goto done; + } + + BSWAP_STL_SWITCH_COST_RECORD(pSC); + MAD_SET_ATTRIB_ID(&mad, STL_SA_ATTR_SWITCH_COST_RECORD); + + fstatus = sa_query_common(&mad, &pRsp, sizeof(STL_SWITCH_COST_RECORD), &pQR, port); + if(fstatus != FSUCCESS) break; + + pSCR = (STL_SWITCH_COST_RECORD_RESULTS*)pQR->QueryResult; + pSC = pSCR->Records; + + for(i = 0; i < pSCR->NumRecords; ++i, ++pSC) + { + *pSC = *((STL_SWITCH_COST_RECORD*)(GET_RESULT_OFFSET(pRsp, i))); + BSWAP_STL_SWITCH_COST_RECORD(pSC); + } + break; + } + + default: + OMGT_OUTPUT_ERROR(port, "Query not supported by opamgt: Input=%s, Output=%s\n", + iba_sd_query_input_type_msg(pQuery->InputType), + iba_sd_query_result_type_msg(pQuery->OutputType)); + fstatus = FINVALID_PARAMETER; goto done; + break; + } + +done: + // Common place to print error for PKEY mismatch + if (fstatus == FPROTECTION) { + OMGT_OUTPUT_ERROR(port, "Unable to send query, requires full management PKEY\n"); + } + if (pRsp!=NULL) { + free (pRsp); + } + pRsp = NULL; + *ppQueryResult = pQR; + + DBG_EXIT_FUNC(port); + + return fstatus; +} + +/* omgt_query_sa + * + * All SA queries are sent through this path. This function performs a test of + * SA reachability before sending the main query. If the FM's reachability is + * not operational, a request for a ClassPortInfo with a small timeout + * (defaulted to 250ms in lower layer) is sent. Only after determining the SA + * is reachable is the main query sent. All other queries currently default to + * a timeout of 20s with 3 retires. Sending the CPI first allows us to do a + * quick ping and avoid long timeouts when SA is unreachable. + * + * if pQuery and ppQueryResult are input NULL, only a reachability test will be + * performed with no main query. + * + */ +FSTATUS omgt_query_sa(struct omgt_port *port, OMGT_QUERY *pQuery, + struct _QUERY_RESULT_VALUES **ppQueryResult) +{ + FSTATUS fstatus = FSUCCESS; + + if (port == NULL) + return FINVALID_PARAMETER; + + if (port->sa_service_state != OMGT_SERVICE_STATE_OPERATIONAL && !port->is_oob_enabled) { + QUERY_RESULT_VALUES *cpi_query_result = NULL; + OMGT_QUERY cpi_query; + cpi_query.InputType = InputTypeNoInput; + cpi_query.OutputType = OutputTypeStlClassPortInfo; + fstatus = omgt_query_sa_internal(port, &cpi_query, &cpi_query_result); + + if (fstatus == FSUCCESS) { + port->sa_service_state = OMGT_SERVICE_STATE_OPERATIONAL; + STL_CLASS_PORT_INFO *pClassPortInfo = NULL; + pClassPortInfo = &((STL_CLASS_PORT_INFO_RESULT *)cpi_query_result->QueryResult)->ClassPortInfo; + port->sa_capmask2 = pClassPortInfo->u1.s.CapMask2; + if (pQuery != NULL && ppQueryResult != NULL && + pQuery->OutputType == OutputTypeStlClassPortInfo && + pQuery->InputType == InputTypeNoInput && cpi_query_result != NULL) { + /* If request is a ClassPortInfo Query, then just return with results */ + *ppQueryResult = cpi_query_result; + return FSUCCESS; + } + } else if (fstatus == FTIMEOUT || fstatus == FNOT_DONE){ + OMGT_OUTPUT_ERROR(port, "SA nonresponsive. SA Service State refresh failed: %s.\n", omgt_status_totext(fstatus)); + port->sa_service_state = OMGT_SERVICE_STATE_DOWN; + /* If SA is down assume PA is down */ + port->pa_service_state = OMGT_SERVICE_STATE_DOWN; + } else { + OMGT_OUTPUT_ERROR(port, "SA nonresponsive. SA Service State refresh failed: %s.\n", omgt_status_totext(fstatus)); + port->sa_service_state = OMGT_SERVICE_STATE_UNKNOWN; + port->pa_service_state = OMGT_SERVICE_STATE_UNKNOWN; + } + omgt_free_query_result_buffer(cpi_query_result); + } + + if (fstatus == FSUCCESS && pQuery != NULL && ppQueryResult != NULL) { + fstatus = omgt_query_sa_internal(port, pQuery, ppQueryResult); + if (fstatus == FTIMEOUT || fstatus == FNOT_DONE) { + OMGT_OUTPUT_ERROR(port, "Query Failed on response: %s.\n", omgt_status_totext(fstatus)); + port->sa_service_state = OMGT_SERVICE_STATE_DOWN; + /* If SA is down assume PA is down */ + port->pa_service_state = OMGT_SERVICE_STATE_DOWN; + } else if (fstatus != FSUCCESS) { + OMGT_OUTPUT_ERROR(port, "Query Failed: %s. \n", omgt_status_totext(fstatus)); + } + } + + return fstatus; +} diff --git a/opamgt/src/opamgt_sa_notice.c b/opamgt/src/opamgt_sa_notice.c new file mode 100644 index 0000000..44357a0 --- /dev/null +++ b/opamgt/src/opamgt_sa_notice.c @@ -0,0 +1,303 @@ +/* BEGIN_ICS_COPYRIGHT2 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT2 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +#include +#include +#include /* strerror() */ + + +#define OPAMGT_PRIVATE 1 +#include "ib_utils_openib.h" +#include "opamgt_dump_mad.h" +#include "omgt_oob_net.h" +#include "omgt_oob_protocol.h" + +#include +#include +#include +#include + + +/**===========================================================================*/ +omgt_sa_registration_t* omgt_sa_find_reg(struct omgt_port *port, uint16_t trap_num) +{ + omgt_sa_registration_t *curr = port->regs_list; + while (curr != NULL) { + if (curr->trap_num == trap_num) { + return curr; + } + curr = curr->next; + } + return NULL; +} +/**===========================================================================*/ +OMGT_STATUS_T omgt_sa_register_trap(struct omgt_port *port, uint16_t trap_num, + void *context) +{ + OMGT_STATUS_T status; + int ret; + omgt_sa_registration_t *reg; + + if (port->is_oob_enabled) { + OMGT_OUTPUT_ERROR(port, "Port in Out-of-Band Mode, Trap registration not Supported\n"); + return OMGT_STATUS_INVALID_STATE; + } + + reg = (omgt_sa_registration_t *)calloc(1, sizeof*reg); + if (reg == NULL) { + OMGT_OUTPUT_ERROR(port, "failed to allocate reg structure\n"); + return OMGT_STATUS_ERROR; + } + + status = FTIMEOUT; + if (omgt_lock_sem(&port->lock)) { + OMGT_OUTPUT_ERROR(port, "failed to acquire lock (status: %d)\n", status); + free(reg); + return OMGT_STATUS_ERROR; + } + + if (omgt_sa_find_reg(port, trap_num)) { + omgt_unlock_sem(&port->lock); + free(reg); + return OMGT_STATUS_SUCCESS; + } + + if ((ret = create_sa_qp(port)) != 0) { + omgt_unlock_sem(&port->lock); + OMGT_OUTPUT_ERROR(port, "failed to create notice QP for trap (%u) registration (status: %d)\n", + trap_num, ret); + } else if ((ret = userspace_register(port, trap_num, reg)) != 0) { + omgt_unlock_sem(&port->lock); + OMGT_OUTPUT_ERROR(port, "failed to register for trap (%u) (status: %d)\n", + trap_num, ret); + } + + if (ret) { + free(reg); + return OMGT_STATUS_ERROR; + } + + reg->user_context = context; + reg->trap_num = trap_num; + omgt_sa_add_reg_unsafe(port, reg); + + omgt_unlock_sem(&port->lock); + return OMGT_STATUS_SUCCESS; +} +/**===========================================================================*/ +OMGT_STATUS_T omgt_sa_unregister_trap(struct omgt_port *port, uint16_t trap_num) +{ + OMGT_STATUS_T status; + + if (port->is_oob_enabled) { + OMGT_OUTPUT_ERROR(port, "Port in Out-of-Band Mode, Trap (un)registration not Supported\n"); + return OMGT_STATUS_INVALID_STATE; + } + + if (omgt_lock_sem(&port->lock)) + return OMGT_STATUS_ERROR; + + status = omgt_sa_remove_reg_by_trap_unsafe(port, trap_num); + + omgt_unlock_sem(&port->lock); + return status; +} +/**===========================================================================*/ +OMGT_STATUS_T omgt_sa_get_notice_report(struct omgt_port *port, STL_NOTICE **notice, + size_t *notice_len, void **context, int poll_timeout_ms) +{ + int rc; + int bytes_read; + struct pollfd pollfd[1]; + uint8_t rcv_buf[2048]; + struct omgt_thread_msg *msg; + STL_NOTICE *notice_buf = NULL; + omgt_sa_registration_t *reg; + uint16_t trap_num; + + if (port->is_oob_enabled) { + uint32_t oob_recv_len = 0; + OOB_PACKET *packet = NULL; + + if (!port->is_oob_notice_setup) { + OMGT_STATUS_T status; + if ((status = omgt_oob_net_connect(port, &port->notice_conn)) != FSUCCESS) { + OMGT_OUTPUT_ERROR(port, "failed to establish a connection to the host: %u\n", status); + return status; + } + port->is_oob_notice_setup = TRUE; + } + + do { + /* Process IP 'blobs' (TCP Segments) */ + omgt_oob_net_process(port, port->notice_conn, poll_timeout_ms, 1); + /* If failure return error */ + if (port->notice_conn->err) { + return OMGT_STATUS_ERROR; + } + } while (port->notice_conn->blob_in_progress); + + /* Check if we are done getting all the 'blobs' */ + omgt_oob_net_get_next_message(port->notice_conn, (uint8_t **)&packet, (int *)&oob_recv_len); + /* Handle Timeout Case */ + if (packet == NULL) { + return OMGT_STATUS_TIMEOUT; + } + + /* Handle packet */ + oob_recv_len = 0; + BSWAP_OOB_HEADER(&(packet->Header)); + oob_recv_len = packet->Header.Length; + BSWAP_MAD_HEADER((MAD *)&packet->MadData.common); + + /* Handle Trap/Notice Report */ + if (packet->MadData.common.AttributeID == STL_MCLASS_ATTRIB_ID_NOTICE) { + /* Remove Header Bytes */ + oob_recv_len -= (sizeof(MAD_COMMON) - sizeof(RMPP_HEADER) - sizeof(SA_HDR)); + + /* Allocate the Notice */ + notice_buf = (STL_NOTICE *)calloc(1, oob_recv_len); + if (notice_buf == NULL) { + OMGT_OUTPUT_ERROR(port, "failed to allocate notice buffer\n"); + return OMGT_STATUS_INSUFFICIENT_MEMORY; + } + + /* Copy and allocate the Data */ + SA_MAD *samad = (SA_MAD *)&packet->MadData.common; + memcpy(notice_buf, samad->Data, oob_recv_len); + BSWAP_STL_NOTICE(notice_buf); + trap_num = notice_buf->Attributes.Generic.TrapNumber; + OMGT_DBGPRINT(port, "trap message %u: %d bytes\n", trap_num, oob_recv_len); + + /* Find Context (Not in OOB) */ + if (context) { + *context = NULL; + } + /* Set Notice struct and length */ + *notice = notice_buf; + *notice_len = oob_recv_len; + return OMGT_STATUS_SUCCESS; + /* Handle Inform Info */ + } else if (packet->MadData.common.AttributeID == STL_MCLASS_ATTRIB_ID_INFORM_INFO) { + SA_MAD *samad = (SA_MAD *)&packet->MadData.common; + STL_INFORM_INFO *informinfo = (STL_INFORM_INFO *)samad->Data; + trap_num = ntoh16(informinfo->u.Generic.TrapNumber); + + /* Free Packet */ + free(packet); + + OMGT_OUTPUT_ERROR(port, "Registration of Trap message timed out: Trap %u\n", trap_num); + return OMGT_STATUS_DISCONNECT; + /* Otherwise error */ + } else { + SA_MAD *samad = (SA_MAD *)&packet->MadData.common; + OMGT_OUTPUT_ERROR(port, "Unexpected OOB MAD recieved: %s %s(%s)\n", + stl_class_str(samad->common.BaseVersion, samad->common.MgmtClass), + stl_method_str(samad->common.BaseVersion, samad->common.MgmtClass, samad->common.mr.AsReg8), + stl_attribute_str(samad->common.BaseVersion, samad->common.MgmtClass, hton16(samad->common.AttributeID))); + + /* Free Packet */ + free(packet); + return OMGT_STATUS_ERROR; + } + } + pollfd[0].fd = port->umad_port_sv[0]; + pollfd[0].events = POLLIN; + pollfd[0].revents = 0; + + /* Poll for event */ + if ((rc = poll(pollfd, 1, poll_timeout_ms)) < 0) { + OMGT_OUTPUT_ERROR(port, "trap poll failed : %s\n", strerror(errno)); + return FERROR; + + } else if (rc == 0) { + /* Handle Timeout Case */ + return OMGT_STATUS_TIMEOUT; + } else if (pollfd[0].revents & POLLIN) { + /* Read from Stream */ + bytes_read = read(port->umad_port_sv[0], rcv_buf, sizeof(rcv_buf)); + if (bytes_read <= 0) { + OMGT_OUTPUT_ERROR(port, "user event read failed : %s\n", strerror(errno)); + return OMGT_STATUS_ERROR; + } + + /* Determine Message Type */ + msg = (struct omgt_thread_msg *)rcv_buf; + if (OMGT_TH_EVT_TRAP_MSG == msg->evt) { + int bufSize = MIN(msg->size,sizeof(rcv_buf)-sizeof(*msg)); + /* Thread Event Type : Trap Message */ + + /* Allocate the Notice */ + notice_buf = (STL_NOTICE *)calloc(1, bufSize); + if (notice_buf == NULL) { + OMGT_OUTPUT_ERROR(port, "failed to allocate notice buffer\n"); + return OMGT_STATUS_INSUFFICIENT_MEMORY; + } + /* Copy and allocate the Data */ + memcpy(notice_buf, rcv_buf + sizeof(*msg), bufSize); + BSWAP_STL_NOTICE(notice_buf); + trap_num = notice_buf->Attributes.Generic.TrapNumber; + OMGT_DBGPRINT(port, "trap message %u: %d bytes\n", trap_num, (int)(msg->size)); + + /* Find Context */ + if (context) { + reg = omgt_sa_find_reg(port, trap_num); + if (reg == NULL) { + OMGT_OUTPUT_ERROR(port, "failed to retrieve registration: trap %u\n", trap_num); + *context = NULL; + } else { + /* Set context */ + *context = reg->user_context; + } + } + + /* Set Notice struct and length */ + *notice = notice_buf; + *notice_len = msg->size; + return OMGT_STATUS_SUCCESS; + + } else if (OMGT_TH_EVT_TRAP_REG_ERR_TIMEOUT == msg->evt) { + /* Thread Event Type : Registration Timeout */ + STL_INFORM_INFO *informinfo = (STL_INFORM_INFO *)msg->data; + trap_num = ntoh16(informinfo->u.Generic.TrapNumber); + OMGT_OUTPUT_ERROR(port, "Registration of Trap message timed out: Trap %u\n", trap_num); + + return OMGT_STATUS_DISCONNECT; + } else { + OMGT_OUTPUT_ERROR(port, "user event read invalid message: %u\n", msg->evt); + return OMGT_STATUS_ERROR; + } + } else { + OMGT_OUTPUT_ERROR(port, "trap poll unexpected result : %d\n", pollfd[0].revents); + return OMGT_STATUS_ERROR; + } + return OMGT_STATUS_SUCCESS; +} diff --git a/opamgt/src/opamgt_sa_query.c b/opamgt/src/opamgt_sa_query.c new file mode 100644 index 0000000..6025a3c --- /dev/null +++ b/opamgt/src/opamgt_sa_query.c @@ -0,0 +1,2195 @@ +/* BEGIN_ICS_COPYRIGHT2 **************************************** + +Copyright (c) 2015-2018, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT2 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + + +#include +#include +#include +#include + + +#include +#include + +#define OPAMGT_PRIVATE 1 + + +#include "ib_utils_openib.h" +#include "opamgt_sa_priv.h" +#include "opamgt_sa.h" + +/* + * @brief Get MAD status code from most recent SA operation + * + * @param port Local port to operate on. + * + * @return + * The corresponding status code. + */ +uint16_t +omgt_get_sa_mad_status(struct omgt_port *port) +{ + return port->sa_mad_status; +} + + + +static OMGT_STATUS_T +omgt_sa_query_helper( + struct omgt_port *port, + omgt_sa_selector_t *selector, + QUERY_RESULT_TYPE output_type, + QUERY_RESULT_VALUES **query_result) +{ + OMGT_QUERY query; + OMGT_STATUS_T status; + + query.InputType = selector->InputType; + query.OutputType = output_type; + query.InputValue = selector->InputValue; + + status = omgt_query_sa(port, &query, query_result); + + if(OMGT_STATUS_SUCCESS != status) + return status; + + if(!*query_result) + return OMGT_STATUS_ERROR; + + if(OMGT_STATUS_SUCCESS != port->sa_mad_status) + return OMGT_STATUS_ERROR; + + return status; +} + +void +omgt_sa_free_records(void *record) +{ + free(record); + return; +} + + +/** + * @brief Query SA for Node Records + * + * @param port port opened by omgt_open_port_* + * @param selector Criteria to select records. NULL == all records + * @param num_records Output: The number of records returned in query + * @param ni_records Output: Pointer to records. + * Must be freed by calling omgt_free_query_result_buffer + * + *@return OMGT_STATUS_SUCCESS if success, else error code + */ +OMGT_STATUS_T +omgt_sa_get_node_records( + struct omgt_port *port, + omgt_sa_selector_t *selector, + int32_t *num_records, + STL_NODE_RECORD **records + ) +{ + + OMGT_STATUS_T status; + QUERY_RESULT_VALUES *query_result; + STL_NODE_RECORD_RESULTS *record_results = NULL; + + status = omgt_sa_query_helper(port, selector, OutputTypeStlNodeRecord, &query_result); + + if(OMGT_STATUS_SUCCESS != status) + return status; + + record_results = (STL_NODE_RECORD_RESULTS*)query_result->QueryResult; + *num_records = record_results->NumNodeRecords; + + if(*num_records == 0) { + *records = NULL; + goto exit; + } + + int buf_size = sizeof(**records) * (*num_records); + *records = malloc(buf_size); + if(*records == NULL){ + status = OMGT_STATUS_INSUFFICIENT_MEMORY; + goto exit; + } + + memcpy(*records, record_results->NodeRecords, buf_size); +exit: + omgt_free_query_result_buffer(query_result); + return status; +} +/** + * @brief Query SA for PortInfo Records + * + * @param port port opened by omgt_open_port_* + * @param selector Criteria to select records. NULL == all records + * @param num_records Output: The number of records returned in query + * @param ni_records Output: Pointer to records. + * Must be freed by calling omgt_free_query_result_buffer + * + *@return OMGT_STATUS_SUCCESS if success, else error code + */ +OMGT_STATUS_T +omgt_sa_get_portinfo_records( + struct omgt_port *port, + omgt_sa_selector_t *selector, + int32_t *num_records, + STL_PORTINFO_RECORD **records + ) +{ + + OMGT_STATUS_T status; + QUERY_RESULT_VALUES *query_result; + STL_PORTINFO_RECORD_RESULTS *record_results = NULL; + + status = omgt_sa_query_helper(port, selector, OutputTypeStlPortInfoRecord, &query_result); + + if(OMGT_STATUS_SUCCESS != status) + return status; + + record_results = (STL_PORTINFO_RECORD_RESULTS*)query_result->QueryResult; + *num_records = record_results->NumPortInfoRecords; + + if(*num_records == 0) { + *records = NULL; + goto exit; + } + + int buf_size = sizeof(**records) * (*num_records); + *records = malloc(buf_size); + if(*records == NULL){ + status = OMGT_STATUS_INSUFFICIENT_MEMORY; + goto exit; + } + + memcpy(*records, record_results->PortInfoRecords, buf_size); +exit: + omgt_free_query_result_buffer(query_result); + return status; +} + + + +/** + * @brief Query SA for System Image GUIDs + * + * @param port port opened by omgt_open_port_* + * @param selector Criteria to select GUIDs. + * @param num_records Output: The number of GUIDs returned in query + * @param guids Output: Pointer to array of GUIDs + * Must be freed by calling omgt_free_query_result_buffer + * + *@return OMGT_STATUS_SUCCESS if success, else error code + */ +OMGT_STATUS_T +omgt_sa_get_sysimageguid_records( + struct omgt_port *port, + omgt_sa_selector_t *selector, + int32_t *num_records, + uint64_t **guids + ) +{ + + OMGT_STATUS_T status; + QUERY_RESULT_VALUES *query_result; + GUID_RESULTS *record_results = NULL; + + status = omgt_sa_query_helper(port, selector, OutputTypeStlSystemImageGuid, &query_result); + + if(OMGT_STATUS_SUCCESS != status) + return status; + + record_results = (GUID_RESULTS*)query_result->QueryResult; + *num_records = record_results->NumGuids; + if(*num_records == 0) { + *guids = NULL; + goto exit; + } + + int buf_size = sizeof(**guids) * (*num_records); + *guids = malloc(buf_size); + if(*guids == NULL){ + status = OMGT_STATUS_INSUFFICIENT_MEMORY; + goto exit; + } + + memcpy(*guids, record_results->Guids, buf_size); +exit: + omgt_free_query_result_buffer(query_result); + return status; +} + +/** + * @brief Query SA for Node GUIDs + * + * @param port port opened by omgt_open_port_* + * @param selector Criteria to select GUIDs. + * @param num_records Output: The number of GUIDs returned in query + * @param guids Output: Pointer to array of GUIDs + * Must be freed by calling omgt_free_query_result_buffer + * + *@return OMGT_STATUS_SUCCESS if success, else error code + */ +OMGT_STATUS_T +omgt_sa_get_nodeguid_records( + struct omgt_port *port, + omgt_sa_selector_t *selector, + int32_t *num_records, + uint64_t **guids + ) +{ + + OMGT_STATUS_T status; + QUERY_RESULT_VALUES *query_result; + GUID_RESULTS *record_results = NULL; + + status = omgt_sa_query_helper(port, selector, OutputTypeStlNodeGuid, &query_result); + + if(OMGT_STATUS_SUCCESS != status) + return status; + + record_results = (GUID_RESULTS*)query_result->QueryResult; + *num_records = record_results->NumGuids; + if(*num_records == 0) { + *guids = NULL; + goto exit; + } + + int buf_size = sizeof(**guids) * (*num_records); + *guids = malloc(buf_size); + if(*guids == NULL){ + status = OMGT_STATUS_INSUFFICIENT_MEMORY; + goto exit; + } + + memcpy(*guids, record_results->Guids, buf_size); +exit: + omgt_free_query_result_buffer(query_result); + return status; +} + + +/** + * @brief Query SA for Port GUIDs + * + * @param port port opened by omgt_open_port_* + * @param selector Criteria to select GUIDs. + * @param num_records Output: The number of GUIDs returned in query + * @param guids Output: Pointer to array of GUIDs + * Must be freed by calling omgt_free_query_result_buffer + * + *@return OMGT_STATUS_SUCCESS if success, else error code + */OMGT_STATUS_T +omgt_sa_get_portguid_records( + struct omgt_port *port, + omgt_sa_selector_t *selector, + int32_t *num_records, + uint64_t **guids + ) +{ + + OMGT_STATUS_T status; + QUERY_RESULT_VALUES *query_result; + GUID_RESULTS *record_results = NULL; + + status = omgt_sa_query_helper(port, selector, OutputTypeStlPortGuid, &query_result); + + if(OMGT_STATUS_SUCCESS != status) + return status; + + record_results = (GUID_RESULTS*)query_result->QueryResult; + *num_records = record_results->NumGuids; + if(*num_records == 0) { + *guids = NULL; + goto exit; + } + + int buf_size = sizeof(**guids) * (*num_records); + *guids = malloc(buf_size); + if(*guids == NULL){ + status = OMGT_STATUS_INSUFFICIENT_MEMORY; + goto exit; + } + + memcpy(*guids, record_results->Guids, buf_size); +exit: + omgt_free_query_result_buffer(query_result); + return status; +} + +/** + * @brief Query SA for ClassPortInfo Records + * + * @param port port opened by omgt_open_port_* + * @param selector Criteria to select records. NULL == all records + * @param num_records Output: The number of records returned in query + * @param records Output: Pointer to records. + * Must be freed by calling omgt_free_query_result_buffer + * + *@return OMGT_STATUS_SUCCESS if success, else error code + */ +OMGT_STATUS_T +omgt_sa_get_classportinfo_records( + struct omgt_port *port, + omgt_sa_selector_t *selector, + int32_t *num_records, + STL_CLASS_PORT_INFO **records + ) +{ + + OMGT_STATUS_T status; + QUERY_RESULT_VALUES *query_result; + STL_CLASS_PORT_INFO_RESULT *record_results = NULL; + + status = omgt_sa_query_helper(port, selector, OutputTypeStlClassPortInfo, &query_result); + + if(OMGT_STATUS_SUCCESS != status) + return status; + + record_results = (STL_CLASS_PORT_INFO_RESULT*)query_result->QueryResult; + *num_records = record_results->NumClassPortInfo; + if(*num_records == 0) { + *records = NULL; + goto exit; + } + + int buf_size = sizeof(**records) * (*num_records); + *records = malloc(buf_size); + if(*records == NULL){ + status = OMGT_STATUS_INSUFFICIENT_MEMORY; + goto exit; + } + + + memcpy(*records, &record_results->ClassPortInfo, buf_size); +exit: + omgt_free_query_result_buffer(query_result); + return status; +} + +/** + * @brief Query SA for Lid Records + * + * @param port port opened by omgt_open_port_* + * @param selector Criteria to select records. NULL == all records + * @param num_records Output: The number of records returned in query + * @param lids Output: Pointer to lids. + * Must be freed by calling omgt_free_query_result_buffer + * + *@return OMGT_STATUS_SUCCESS if success, else error code + */ +OMGT_STATUS_T +omgt_sa_get_lid_records( + struct omgt_port *port, + omgt_sa_selector_t *selector, + int32_t *num_records, + uint32 **lids + ) +{ + + OMGT_STATUS_T status; + QUERY_RESULT_VALUES *query_result; + STL_LID_RESULTS *record_results = NULL; + + status = omgt_sa_query_helper(port, selector, OutputTypeStlLid, &query_result); + + if(OMGT_STATUS_SUCCESS != status) + return status; + + record_results = (STL_LID_RESULTS*)query_result->QueryResult; + *num_records = record_results->NumLids; + if(*num_records == 0) { + *lids = NULL; + goto exit; + } + + int buf_size = sizeof(**lids) * (*num_records); + *lids = malloc(buf_size); + if(*lids == NULL){ + status = OMGT_STATUS_INSUFFICIENT_MEMORY; + goto exit; + } + + + memcpy(*lids, record_results->Lids, buf_size); +exit: + omgt_free_query_result_buffer(query_result); + return status; +} + + +/** + * @brief Query SA for Node Description Records + * + * @param port port opened by omgt_open_port_* + * @param selector Criteria to select records. NULL == all records + * @param num_records Output: The number of records returned in query + * @param records Output: Pointer to records. + * Must be freed by calling omgt_free_query_result_buffer + * + *@return OMGT_STATUS_SUCCESS if success, else error code + */ +OMGT_STATUS_T +omgt_sa_get_nodedesc_records( + struct omgt_port *port, + omgt_sa_selector_t *selector, + int32_t *num_records, + STL_NODE_DESCRIPTION **records + ) +{ + + OMGT_STATUS_T status; + QUERY_RESULT_VALUES *query_result; + STL_NODEDESC_RESULTS *record_results = NULL; + + status = omgt_sa_query_helper(port, selector, OutputTypeStlNodeDesc, &query_result); + + if(OMGT_STATUS_SUCCESS != status) + return status; + + record_results = (STL_NODEDESC_RESULTS*)query_result->QueryResult; + *num_records = record_results->NumDescs; + if(*num_records == 0) { + *records = NULL; + goto exit; + } + + int buf_size = sizeof(**records) * (*num_records); + *records = malloc(buf_size); + if(*records == NULL){ + status = OMGT_STATUS_INSUFFICIENT_MEMORY; + goto exit; + } + + memcpy(*records, record_results->NodeDescs, buf_size); +exit: + omgt_free_query_result_buffer(query_result); + return status; +} + + +/** + * @brief Query SA for IB Path Records + * + * @param port port opened by omgt_open_port_* + * @param selector Criteria to select records. NULL == all records + * @param num_records Output: The number of records returned in query + * @param records Output: Pointer to records. + * Must be freed by calling omgt_free_query_result_buffer + * + *@return OMGT_STATUS_SUCCESS if success, else error code + */ +OMGT_STATUS_T +omgt_sa_get_ib_path_records( + struct omgt_port *port, + omgt_sa_selector_t *selector, + int32_t *num_records, + IB_PATH_RECORD **records + ) +{ + + OMGT_STATUS_T status; + QUERY_RESULT_VALUES *query_result; + PATH_RESULTS *record_results = NULL; + + status = omgt_sa_query_helper(port, selector, OutputTypePathRecord, &query_result); + + if(OMGT_STATUS_SUCCESS != status) + return status; + + record_results = (PATH_RESULTS*)query_result->QueryResult; + *num_records = record_results->NumPathRecords; + if(*num_records == 0) { + *records = NULL; + goto exit; + } + + int buf_size = sizeof(**records) * (*num_records); + *records = malloc(buf_size); + if(*records == NULL){ + status = OMGT_STATUS_INSUFFICIENT_MEMORY; + goto exit; + } + + + memcpy(*records, record_results->PathRecords, buf_size); +exit: + omgt_free_query_result_buffer(query_result); + return status; +} + +/** +* @brief Query SA for SM Info Records +* +* @param port port opened by omgt_open_port_* +* @param selector Criteria to select records. NULL == all records +* @param num_records Output: The number of records returned in query +* @param records Output: Pointer to records. +* Must be freed by calling omgt_free_query_result_buffer +* +*@return OMGT_STATUS_SUCCESS if success, else error code +*/ +OMGT_STATUS_T +omgt_sa_get_sminfo_records( + struct omgt_port *port, + omgt_sa_selector_t *selector, + int32_t *num_records, + STL_SMINFO_RECORD **records + ) +{ + + OMGT_STATUS_T status; + QUERY_RESULT_VALUES *query_result; + STL_SMINFO_RECORD_RESULTS *record_results = NULL; + + status = omgt_sa_query_helper(port, selector, OutputTypeStlSMInfoRecord, &query_result); + + if(OMGT_STATUS_SUCCESS != status) + return status; + + record_results = (STL_SMINFO_RECORD_RESULTS*)query_result->QueryResult; + *num_records = record_results->NumSMInfoRecords; + + int buf_size = sizeof(**records) * (*num_records); + if(*num_records == 0) { + *records = NULL; + return status; + } + + *records = malloc(buf_size); + if(*records == NULL){ + status = OMGT_STATUS_INSUFFICIENT_MEMORY; + goto exit; + } + + + memcpy(*records, record_results->SMInfoRecords, buf_size); +exit: + omgt_free_query_result_buffer(query_result); + return status; +} + + +/** + * @brief Query SA for Link Records + * + * @param port port opened by omgt_open_port_* + * @param selector Criteria to select records. NULL == all records + * @param num_records Output: The number of records returned in query + * @param records Output: Pointer to records. + * Must be freed by calling omgt_free_query_result_buffer + * + *@return OMGT_STATUS_SUCCESS if success, else error code + */ +OMGT_STATUS_T +omgt_sa_get_link_records( + struct omgt_port *port, + omgt_sa_selector_t *selector, + int32_t *num_records, + STL_LINK_RECORD **records + ) +{ + + OMGT_STATUS_T status; + QUERY_RESULT_VALUES *query_result; + STL_LINK_RECORD_RESULTS *record_results = NULL; + + status = omgt_sa_query_helper(port, selector, OutputTypeStlLinkRecord, &query_result); + + if(OMGT_STATUS_SUCCESS != status) + return status; + + record_results = (STL_LINK_RECORD_RESULTS*)query_result->QueryResult; + *num_records = record_results->NumLinkRecords; + + int buf_size = sizeof(**records) * (*num_records); + if(*num_records == 0) { + *records = NULL; + goto exit; + } + + *records = malloc(buf_size); + if(*records == NULL){ + status = OMGT_STATUS_INSUFFICIENT_MEMORY; + goto exit; + } + + + memcpy(*records, record_results->LinkRecords, buf_size); +exit: + omgt_free_query_result_buffer(query_result); + return status; +} + +/** + * @brief Query SA for Service Records + * + * @param port port opened by omgt_open_port_* + * @param selector Criteria to select records. NULL == all records + * @param num_records Output: The number of records returned in query + * @param records Output: Pointer to records. + * Must be freed by calling omgt_free_query_result_buffer + * + *@return OMGT_STATUS_SUCCESS if success, else error code + */ +OMGT_STATUS_T +omgt_sa_get_service_records( + struct omgt_port *port, + omgt_sa_selector_t *selector, + int32_t *num_records, + IB_SERVICE_RECORD **records + ) +{ + + OMGT_STATUS_T status; + QUERY_RESULT_VALUES *query_result; + SERVICE_RECORD_RESULTS *record_results = NULL; + + status = omgt_sa_query_helper(port, selector, OutputTypeServiceRecord, &query_result); + + if(OMGT_STATUS_SUCCESS != status) + return status; + + record_results = (SERVICE_RECORD_RESULTS*)query_result->QueryResult; + *num_records = record_results->NumServiceRecords; + + int buf_size = sizeof(**records) * (*num_records); + if(*num_records == 0) { + *records = NULL; + goto exit; + } + + *records = malloc(buf_size); + if(*records == NULL){ + status = OMGT_STATUS_INSUFFICIENT_MEMORY; + goto exit; + } + + + memcpy(*records, record_results->ServiceRecords, buf_size); +exit: + omgt_free_query_result_buffer(query_result); + return status; +} + +/** + * @brief Query SA for Multicast Member Records + * + * @param port port opened by omgt_open_port_* + * @param selector Criteria to select records. NULL == all records + * @param num_records Output: The number of records returned in query + * @param records Output: Pointer to records. + * Must be freed by calling omgt_free_query_result_buffer + * + *@return OMGT_STATUS_SUCCESS if success, else error code + */ +OMGT_STATUS_T +omgt_sa_get_ib_mcmember_records( + struct omgt_port *port, + omgt_sa_selector_t *selector, + int32_t *num_records, + IB_MCMEMBER_RECORD **records + ) +{ + + OMGT_STATUS_T status; + QUERY_RESULT_VALUES *query_result; + MCMEMBER_RECORD_RESULTS *record_results = NULL; + + status = omgt_sa_query_helper(port, selector, OutputTypeMcMemberRecord, &query_result); + + if(OMGT_STATUS_SUCCESS != status) + return status; + + record_results = (MCMEMBER_RECORD_RESULTS*)query_result->QueryResult; + *num_records = record_results->NumMcMemberRecords; + if(*num_records == 0) { + *records = NULL; + goto exit; + } + + int buf_size = sizeof(**records) * (*num_records); + *records = malloc(buf_size); + if(*records == NULL){ + status = OMGT_STATUS_INSUFFICIENT_MEMORY; + goto exit; + } + + memcpy(*records, record_results->McMemberRecords, buf_size); +exit: + omgt_free_query_result_buffer(query_result); + return status; +} + +/** + * @brief Query SA for Inform Info Records + * + * @param port port opened by omgt_open_port_* + * @param selector Criteria to select records. NULL == all records + * @param num_records Output: The number of records returned in query + * @param records Output: Pointer to records. + * Must be freed by calling omgt_free_query_result_buffer + * + *@return OMGT_STATUS_SUCCESS if success, else error code + */ +OMGT_STATUS_T +omgt_sa_get_informinfo_records( + struct omgt_port *port, + omgt_sa_selector_t *selector, + int32_t *num_records, + STL_INFORM_INFO_RECORD **records + ) +{ + + OMGT_STATUS_T status; + QUERY_RESULT_VALUES *query_result; + STL_INFORM_INFO_RECORD_RESULTS *record_results = NULL; + + status = omgt_sa_query_helper(port, selector, OutputTypeStlInformInfoRecord, &query_result); + + if(OMGT_STATUS_SUCCESS != status) + return status; + + record_results = (STL_INFORM_INFO_RECORD_RESULTS*)query_result->QueryResult; + *num_records = record_results->NumInformInfoRecords; + if(*num_records == 0) { + *records = NULL; + goto exit; + } + + int buf_size = sizeof(**records) * (*num_records); + *records = malloc(buf_size); + if(*records == NULL){ + status = OMGT_STATUS_INSUFFICIENT_MEMORY; + goto exit; + } + + memcpy(*records, record_results->InformInfoRecords, buf_size); +exit: + omgt_free_query_result_buffer(query_result); + return status; +} +/** + * @brief Query SA for Trace Records + * + * @param port port opened by omgt_open_port_* + * @param selector Criteria to select records. NULL == all records + * @param num_records Output: The number of records returned in query + * @param records Output: Pointer to records. + * Must be freed by calling omgt_free_query_result_buffer + * + *@return OMGT_STATUS_SUCCESS if success, else error code + */ +OMGT_STATUS_T +omgt_sa_get_trace_records( + struct omgt_port *port, + omgt_sa_selector_t *selector, + int32_t *num_records, + STL_TRACE_RECORD **records + ) +{ + + OMGT_STATUS_T status; + QUERY_RESULT_VALUES *query_result; + STL_TRACE_RECORD_RESULTS *record_results = NULL; + + status = omgt_sa_query_helper(port, selector, OutputTypeStlTraceRecord, &query_result); + + if(OMGT_STATUS_SUCCESS != status) + return status; + + record_results = (STL_TRACE_RECORD_RESULTS*)query_result->QueryResult; + *num_records = record_results->NumTraceRecords; + if(*num_records == 0) { + *records = NULL; + goto exit; + } + + int buf_size = sizeof(**records) * (*num_records); + *records = malloc(buf_size); + if(*records == NULL){ + status = OMGT_STATUS_INSUFFICIENT_MEMORY; + goto exit; + } + + memcpy(*records, record_results->TraceRecords, buf_size); +exit: + omgt_free_query_result_buffer(query_result); + return status; +} +/** + * @brief Query SA for SCSC Table Records + * + * @param port port opened by omgt_open_port_* + * @param selector Criteria to select records. NULL == all records + * @param num_records Output: The number of records returned in query + * @param records Output: Pointer to records. + * Must be freed by calling omgt_free_query_result_buffer + * + *@return OMGT_STATUS_SUCCESS if success, else error code + */ +OMGT_STATUS_T +omgt_sa_get_scsc_table_records( + struct omgt_port *port, + omgt_sa_selector_t *selector, + int32_t *num_records, + STL_SC_MAPPING_TABLE_RECORD **records + ) +{ + + OMGT_STATUS_T status; + QUERY_RESULT_VALUES *query_result; + STL_SC_MAPPING_TABLE_RECORD_RESULTS *record_results = NULL; + + status = omgt_sa_query_helper(port, selector, OutputTypeStlSCSCTableRecord, &query_result); + + if(OMGT_STATUS_SUCCESS != status) + return status; + + record_results = (STL_SC_MAPPING_TABLE_RECORD_RESULTS*)query_result->QueryResult; + *num_records = record_results->NumSCSCTableRecords; + if(*num_records == 0) { + *records = NULL; + goto exit; + } + + int buf_size = sizeof(**records) * (*num_records); + *records = malloc(buf_size); + if(*records == NULL){ + status = OMGT_STATUS_INSUFFICIENT_MEMORY; + goto exit; + } + + memcpy(*records, record_results->SCSCRecords, buf_size); +exit: + omgt_free_query_result_buffer(query_result); + return status; +} + +/** + * @brief Query SA for SLSC Table Records + * + * @param port port opened by omgt_open_port_* + * @param selector Criteria to select records. NULL == all records + * @param num_records Output: The number of records returned in query + * @param records Output: Pointer to records. + * Must be freed by calling omgt_free_query_result_buffer + * + *@return OMGT_STATUS_SUCCESS if success, else error code + */ +OMGT_STATUS_T +omgt_sa_get_slsc_table_records( + struct omgt_port *port, + omgt_sa_selector_t *selector, + int32_t *num_records, + STL_SL2SC_MAPPING_TABLE_RECORD **records + ) +{ + + OMGT_STATUS_T status; + QUERY_RESULT_VALUES *query_result; + STL_SL2SC_MAPPING_TABLE_RECORD_RESULTS *record_results = NULL; + + status = omgt_sa_query_helper(port, selector, OutputTypeStlSLSCTableRecord, &query_result); + + if(OMGT_STATUS_SUCCESS != status) + return status; + + record_results = (STL_SL2SC_MAPPING_TABLE_RECORD_RESULTS*)query_result->QueryResult; + *num_records = record_results->NumSLSCTableRecords; + if(*num_records == 0) { + *records = NULL; + goto exit; + } + + int buf_size = sizeof(**records) * (*num_records); + *records = malloc(buf_size); + if(*records == NULL){ + status = OMGT_STATUS_INSUFFICIENT_MEMORY; + goto exit; + } + + memcpy(*records, record_results->SLSCRecords, buf_size); +exit: + omgt_free_query_result_buffer(query_result); + return status; +} + +/** + * @brief Query SA for SCSL Table Records + * + * @param port port opened by omgt_open_port_* + * @param selector Criteria to select records. NULL == all records + * @param num_records Output: The number of records returned in query + * @param records Output: Pointer to records. + * Must be freed by calling omgt_free_query_result_buffer + * + *@return OMGT_STATUS_SUCCESS if success, else error code + */ +OMGT_STATUS_T +omgt_sa_get_scsl_table_records( + struct omgt_port *port, + omgt_sa_selector_t *selector, + int32_t *num_records, + STL_SC2SL_MAPPING_TABLE_RECORD **records + ) +{ + + OMGT_STATUS_T status; + QUERY_RESULT_VALUES *query_result; + STL_SC2SL_MAPPING_TABLE_RECORD_RESULTS *record_results = NULL; + + status = omgt_sa_query_helper(port, selector, OutputTypeStlSCSLTableRecord, &query_result); + + if(OMGT_STATUS_SUCCESS != status) + return status; + + record_results = (STL_SC2SL_MAPPING_TABLE_RECORD_RESULTS*)query_result->QueryResult; + *num_records = record_results->NumSCSLTableRecords; + if(*num_records == 0) { + *records = NULL; + goto exit; + } + + int buf_size = sizeof(**records) * (*num_records); + *records = malloc(buf_size); + if(*records == NULL){ + status = OMGT_STATUS_INSUFFICIENT_MEMORY; + goto exit; + } + + memcpy(*records, record_results->SCSLRecords, buf_size); +exit: + omgt_free_query_result_buffer(query_result); + return status; +} + +/** + * @brief Query SA for SCVLt Table Records + * + * @param port port opened by omgt_open_port_* + * @param selector Criteria to select records. NULL == all records + * @param num_records Output: The number of records returned in query + * @param records Output: Pointer to records. + * Must be freed by calling omgt_free_query_result_buffer + * + *@return OMGT_STATUS_SUCCESS if success, else error code + */ +OMGT_STATUS_T +omgt_sa_get_scvlt_table_records( + struct omgt_port *port, + omgt_sa_selector_t *selector, + int32_t *num_records, + STL_SC2PVL_T_MAPPING_TABLE_RECORD **records + ) +{ + + OMGT_STATUS_T status; + QUERY_RESULT_VALUES *query_result; + STL_SC2PVL_T_MAPPING_TABLE_RECORD_RESULTS *record_results = NULL; + + status = omgt_sa_query_helper(port, selector, OutputTypeStlSCVLtTableRecord, &query_result); + + if(OMGT_STATUS_SUCCESS != status) + return status; + + record_results = (STL_SC2PVL_T_MAPPING_TABLE_RECORD_RESULTS*)query_result->QueryResult; + *num_records = record_results->NumSCVLtTableRecords; + if(*num_records == 0) { + *records = NULL; + goto exit; + } + + int buf_size = sizeof(**records) * (*num_records); + *records = malloc(buf_size); + if(*records == NULL){ + status = OMGT_STATUS_INSUFFICIENT_MEMORY; + goto exit; + } + + memcpy(*records, record_results->SCVLtRecords, buf_size); +exit: + omgt_free_query_result_buffer(query_result); + return status; +} + +/** + * @brief Query SA for SCVLr Table Records + * + * @param port port opened by omgt_open_port_* + * @param selector Criteria to select records. NULL == all records + * @param num_records Output: The number of records returned in query + * @param records Output: Pointer to records. + * Must be freed by calling omgt_free_query_result_buffer + * + *@return OMGT_STATUS_SUCCESS if success, else error code + */ +OMGT_STATUS_T +omgt_sa_get_scvlr_table_records( + struct omgt_port *port, + omgt_sa_selector_t *selector, + int32_t *num_records, + STL_SC2PVL_R_MAPPING_TABLE_RECORD **records + ) +{ + + OMGT_STATUS_T status; + QUERY_RESULT_VALUES *query_result; + STL_SC2PVL_R_MAPPING_TABLE_RECORD_RESULTS *record_results = NULL; + + status = omgt_sa_query_helper(port, selector, OutputTypeStlSCVLrTableRecord, &query_result); + + if(OMGT_STATUS_SUCCESS != status) + return status; + + record_results = (STL_SC2PVL_R_MAPPING_TABLE_RECORD_RESULTS*)query_result->QueryResult; + *num_records = record_results->NumSCVLrTableRecords; + if(*num_records == 0) { + *records = NULL; + goto exit; + } + + int buf_size = sizeof(**records) * (*num_records); + *records = malloc(buf_size); + if(*records == NULL){ + status = OMGT_STATUS_INSUFFICIENT_MEMORY; + goto exit; + } + + memcpy(*records, record_results->SCVLrRecords, buf_size); +exit: + omgt_free_query_result_buffer(query_result); + return status; +} + +/** + * @brief Query SA for SCVLnt Table Records + * + * @param port port opened by omgt_open_port_* + * @param selector Criteria to select records. NULL == all records + * @param num_records Output: The number of records returned in query + * @param records Output: Pointer to records. + * Must be freed by calling omgt_free_query_result_buffer + * + *@return OMGT_STATUS_SUCCESS if success, else error code + */ +OMGT_STATUS_T +omgt_sa_get_scvlnt_table_records( + struct omgt_port *port, + omgt_sa_selector_t *selector, + int32_t *num_records, + STL_SC2PVL_NT_MAPPING_TABLE_RECORD **records + ) +{ + + OMGT_STATUS_T status; + QUERY_RESULT_VALUES *query_result; + STL_SC2PVL_NT_MAPPING_TABLE_RECORD_RESULTS *record_results = NULL; + + status = omgt_sa_query_helper(port, selector, OutputTypeStlSCVLntTableRecord, &query_result); + + if(OMGT_STATUS_SUCCESS != status) + return status; + + record_results = (STL_SC2PVL_NT_MAPPING_TABLE_RECORD_RESULTS*)query_result->QueryResult; + *num_records = record_results->NumSCVLntTableRecords; + if(*num_records == 0) { + *records = NULL; + goto exit; + } + + int buf_size = sizeof(**records) * (*num_records); + *records = malloc(buf_size); + if(*records == NULL){ + status = OMGT_STATUS_INSUFFICIENT_MEMORY; + goto exit; + } + + memcpy(*records, record_results->SCVLntRecords, buf_size); +exit: + omgt_free_query_result_buffer(query_result); + return status; +} + +/** + * @brief Query SA for SwitchInfo Records + * + * @param port port opened by omgt_open_port_* + * @param selector Criteria to select records. NULL == all records + * @param num_records Output: The number of records returned in query + * @param records Output: Pointer to records. + * Must be freed by calling omgt_free_query_result_buffer + * + *@return OMGT_STATUS_SUCCESS if success, else error code + */ +OMGT_STATUS_T +omgt_sa_get_switchinfo_records( + struct omgt_port *port, + omgt_sa_selector_t *selector, + int32_t *num_records, + STL_SWITCHINFO_RECORD **records + ) +{ + + OMGT_STATUS_T status; + QUERY_RESULT_VALUES *query_result; + STL_SWITCHINFO_RECORD_RESULTS *record_results = NULL; + + status = omgt_sa_query_helper(port, selector, OutputTypeStlSwitchInfoRecord, &query_result); + + if(OMGT_STATUS_SUCCESS != status) + return status; + + record_results = (STL_SWITCHINFO_RECORD_RESULTS*)query_result->QueryResult; + *num_records = record_results->NumSwitchInfoRecords; + if(*num_records == 0) { + *records = NULL; + goto exit; + } + + int buf_size = sizeof(**records) * (*num_records); + *records = malloc(buf_size); + if(*records == NULL){ + status = OMGT_STATUS_INSUFFICIENT_MEMORY; + goto exit; + } + + memcpy(*records, record_results->SwitchInfoRecords, buf_size); +exit: + omgt_free_query_result_buffer(query_result); + return status; +} + +/** + * @brief Query SA for Linear Forwarding Database Records + * + * @param port port opened by omgt_open_port_* + * @param selector Criteria to select records. NULL == all records + * @param num_records Output: The number of records returned in query + * @param records Output: Pointer to records. + * Must be freed by calling omgt_free_query_result_buffer + * + *@return OMGT_STATUS_SUCCESS if success, else error code + */ +OMGT_STATUS_T +omgt_sa_get_lfdb_records( + struct omgt_port *port, + omgt_sa_selector_t *selector, + int32_t *num_records, + STL_LINEAR_FORWARDING_TABLE_RECORD **records + ) +{ + + OMGT_STATUS_T status; + QUERY_RESULT_VALUES *query_result; + STL_LINEAR_FDB_RECORD_RESULTS *record_results = NULL; + + status = omgt_sa_query_helper(port, selector, OutputTypeStlLinearFDBRecord, &query_result); + + if(OMGT_STATUS_SUCCESS != status) + return status; + + record_results = (STL_LINEAR_FDB_RECORD_RESULTS*)query_result->QueryResult; + *num_records = record_results->NumLinearFDBRecords; + if(*num_records == 0) { + *records = NULL; + goto exit; + } + + int buf_size = sizeof(**records) * (*num_records); + *records = malloc(buf_size); + if(*records == NULL){ + status = OMGT_STATUS_INSUFFICIENT_MEMORY; + goto exit; + } + + memcpy(*records, record_results->LinearFDBRecords, buf_size); +exit: + omgt_free_query_result_buffer(query_result); + return status; +} + +/** + * @brief Query SA for Multicast Forwarding Database Records + * + * @param port port opened by omgt_open_port_* + * @param selector Criteria to select records. NULL == all records + * @param num_records Output: The number of records returned in query + * @param records Output: Pointer to records. + * Must be freed by calling omgt_free_query_result_buffer + * + *@return OMGT_STATUS_SUCCESS if success, else error code + */ +OMGT_STATUS_T +omgt_sa_get_mcfdb_records( + struct omgt_port *port, + omgt_sa_selector_t *selector, + int32_t *num_records, + STL_MULTICAST_FORWARDING_TABLE_RECORD **records + ) +{ + + OMGT_STATUS_T status; + QUERY_RESULT_VALUES *query_result; + STL_MCAST_FDB_RECORD_RESULTS *record_results = NULL; + + status = omgt_sa_query_helper(port, selector, OutputTypeStlMCastFDBRecord, &query_result); + + if(OMGT_STATUS_SUCCESS != status) + return status; + + record_results = (STL_MCAST_FDB_RECORD_RESULTS*)query_result->QueryResult; + *num_records = record_results->NumMCastFDBRecords; + if(*num_records == 0) { + *records = NULL; + goto exit; + } + + int buf_size = sizeof(**records) * (*num_records); + *records = malloc(buf_size); + if(*records == NULL){ + status = OMGT_STATUS_INSUFFICIENT_MEMORY; + goto exit; + } + + memcpy(*records, record_results->MCastFDBRecords, buf_size); +exit: + omgt_free_query_result_buffer(query_result); + return status; +} + +/** + * @brief Query SA for VL Arbitration Table Records + * + * @param port port opened by omgt_open_port_* + * @param selector Criteria to select records. NULL == all records + * @param num_records Output: The number of records returned in query + * @param records Output: Pointer to records. + * Must be freed by calling omgt_free_query_result_buffer + * + *@return OMGT_STATUS_SUCCESS if success, else error code + */ +OMGT_STATUS_T +omgt_sa_get_vlarb_records( + struct omgt_port *port, + omgt_sa_selector_t *selector, + int32_t *num_records, + STL_VLARBTABLE_RECORD **records + ) +{ + + OMGT_STATUS_T status; + QUERY_RESULT_VALUES *query_result; + STL_VLARBTABLE_RECORD_RESULTS *record_results = NULL; + + status = omgt_sa_query_helper(port, selector, OutputTypeStlVLArbTableRecord, &query_result); + + if(OMGT_STATUS_SUCCESS != status) + return status; + + record_results = (STL_VLARBTABLE_RECORD_RESULTS*)query_result->QueryResult; + *num_records = record_results->NumVLArbTableRecords; + if(*num_records == 0) { + *records = NULL; + goto exit; + } + + int buf_size = sizeof(**records) * (*num_records); + *records = malloc(buf_size); + if(*records == NULL){ + status = OMGT_STATUS_INSUFFICIENT_MEMORY; + goto exit; + } + + memcpy(*records, record_results->VLArbTableRecords, buf_size); +exit: + omgt_free_query_result_buffer(query_result); + return status; +} + + +/** + * @brief Query SA for PKEY Table Records + * + * @param port port opened by omgt_open_port_* + * @param selector Criteria to select records. NULL == all records + * @param num_records Output: The number of records returned in query + * @param records Output: Pointer to records. + * Must be freed by calling omgt_free_query_result_buffer + * + *@return OMGT_STATUS_SUCCESS if success, else error code + */ +OMGT_STATUS_T +omgt_sa_get_pkey_table_records( + struct omgt_port *port, + omgt_sa_selector_t *selector, + int32_t *num_records, + STL_P_KEY_TABLE_RECORD **records + ) +{ + + OMGT_STATUS_T status; + QUERY_RESULT_VALUES *query_result; + STL_PKEYTABLE_RECORD_RESULTS *record_results = NULL; + + status = omgt_sa_query_helper(port, selector, OutputTypeStlPKeyTableRecord, &query_result); + + if(OMGT_STATUS_SUCCESS != status) + return status; + + record_results = (STL_PKEYTABLE_RECORD_RESULTS*)query_result->QueryResult; + *num_records = record_results->NumPKeyTableRecords; + if(*num_records == 0) { + *records = NULL; + goto exit; + } + + int buf_size = sizeof(**records) * (*num_records); + *records = malloc(buf_size); + if(*records == NULL){ + status = OMGT_STATUS_INSUFFICIENT_MEMORY; + goto exit; + } + + memcpy(*records, record_results->PKeyTableRecords, buf_size); +exit: + omgt_free_query_result_buffer(query_result); + return status; +} + +/** + * @brief Query SA for VFInfo Records + * + * @param port port opened by omgt_open_port_* + * @param selector Criteria to select records. NULL == all records + * @param num_records Output: The number of records returned in query + * @param records Output: Pointer to records. + * Must be freed by calling omgt_free_query_result_buffer + * + *@return OMGT_STATUS_SUCCESS if success, else error code + */ +OMGT_STATUS_T +omgt_sa_get_vfinfo_records( + struct omgt_port *port, + omgt_sa_selector_t *selector, + int32_t *num_records, + STL_VFINFO_RECORD **records + ) +{ + + OMGT_STATUS_T status; + QUERY_RESULT_VALUES *query_result; + STL_VFINFO_RECORD_RESULTS *record_results = NULL; + + status = omgt_sa_query_helper(port, selector, OutputTypeStlVfInfoRecord, &query_result); + + if(OMGT_STATUS_SUCCESS != status) + return status; + + record_results = (STL_VFINFO_RECORD_RESULTS*)query_result->QueryResult; + *num_records = record_results->NumVfInfoRecords; + if(*num_records == 0) { + *records = NULL; + goto exit; + } + + int buf_size = sizeof(**records) * (*num_records); + *records = malloc(buf_size); + if(*records == NULL){ + status = OMGT_STATUS_INSUFFICIENT_MEMORY; + goto exit; + } + + memcpy(*records, record_results->VfInfoRecords, buf_size); +exit: + omgt_free_query_result_buffer(query_result); + return status; +} + +/** + * @brief Query SA for FabricInfo Records + * + * @param port port opened by omgt_open_port_* + * @param selector Criteria to select records. NULL == all records + * @param num_records Output: The number of records returned in query + * @param records Output: Pointer to records. + * Must be freed by calling omgt_free_query_result_buffer + * + *@return OMGT_STATUS_SUCCESS if success, else error code + */ +OMGT_STATUS_T +omgt_sa_get_fabric_info_records( + struct omgt_port *port, + omgt_sa_selector_t *selector, + int32_t *num_records, + STL_FABRICINFO_RECORD **records + ) +{ + + OMGT_STATUS_T status; + QUERY_RESULT_VALUES *query_result; + STL_FABRICINFO_RECORD_RESULT *record_results = NULL; + + status = omgt_sa_query_helper(port, selector, OutputTypeStlFabricInfoRecord, &query_result); + + if(OMGT_STATUS_SUCCESS != status) + return status; + + record_results = (STL_FABRICINFO_RECORD_RESULT*)query_result->QueryResult; + *num_records = record_results->NumFabricInfoRecords; + if(*num_records == 0) { + *records = NULL; + goto exit; + } + + int buf_size = sizeof(**records) * (*num_records); + *records = malloc(buf_size); + if(*records == NULL){ + status = OMGT_STATUS_INSUFFICIENT_MEMORY; + goto exit; + } + + memcpy(*records, &record_results->FabricInfoRecord, buf_size); +exit: + omgt_free_query_result_buffer(query_result); + return status; +} + +/** + * @brief Query SA for Quarantine Node Records + * + * @param port port opened by omgt_open_port_* + * @param selector Criteria to select records. NULL == all records + * @param num_records Output: The number of records returned in query + * @param records Output: Pointer to records. + * Must be freed by calling omgt_free_query_result_buffer + * + *@return OMGT_STATUS_SUCCESS if success, else error code + */ +OMGT_STATUS_T +omgt_sa_get_quarantinenode_records( + struct omgt_port *port, + omgt_sa_selector_t *selector, + int32_t *num_records, + STL_QUARANTINED_NODE_RECORD **records + ) +{ + + OMGT_STATUS_T status; + QUERY_RESULT_VALUES *query_result; + STL_QUARANTINED_NODE_RECORD_RESULTS *record_results = NULL; + + status = omgt_sa_query_helper(port, selector, OutputTypeStlQuarantinedNodeRecord, &query_result); + + if(OMGT_STATUS_SUCCESS != status) + return status; + + record_results = (STL_QUARANTINED_NODE_RECORD_RESULTS*)query_result->QueryResult; + *num_records = record_results->NumQuarantinedNodeRecords; + if(*num_records == 0) { + *records = NULL; + goto exit; + } + + int buf_size = sizeof(**records) * (*num_records); + *records = malloc(buf_size); + if(*records == NULL){ + status = OMGT_STATUS_INSUFFICIENT_MEMORY; + goto exit; + } + + memcpy(*records, record_results->QuarantinedNodeRecords, buf_size); +exit: + omgt_free_query_result_buffer(query_result); + return status; +} + +/** + * @brief Query SA for Congestion Info Records + * + * @param port port opened by omgt_open_port_* + * @param selector Criteria to select records. NULL == all records + * @param num_records Output: The number of records returned in query + * @param records Output: Pointer to records. + * Must be freed by calling omgt_free_query_result_buffer + * + *@return OMGT_STATUS_SUCCESS if success, else error code + */ +OMGT_STATUS_T +omgt_sa_get_conginfo_records( + struct omgt_port *port, + omgt_sa_selector_t *selector, + int32_t *num_records, + STL_CONGESTION_INFO_RECORD **records + ) +{ + + OMGT_STATUS_T status; + QUERY_RESULT_VALUES *query_result; + STL_CONGESTION_INFO_RECORD_RESULTS *record_results = NULL; + + status = omgt_sa_query_helper(port, selector, OutputTypeStlCongInfoRecord, &query_result); + + if(OMGT_STATUS_SUCCESS != status) + return status; + + record_results = (STL_CONGESTION_INFO_RECORD_RESULTS*)query_result->QueryResult; + *num_records = record_results->NumRecords; + if(*num_records == 0) { + *records = NULL; + goto exit; + } + + int buf_size = sizeof(**records) * (*num_records); + *records = malloc(buf_size); + if(*records == NULL){ + status = OMGT_STATUS_INSUFFICIENT_MEMORY; + goto exit; + } + + memcpy(*records, record_results->Records, buf_size); +exit: + omgt_free_query_result_buffer(query_result); + return status; +} + +/** + * @brief Query SA for Switch Congestion Records + * + * @param port port opened by omgt_open_port_* + * @param selector Criteria to select records. NULL == all records + * @param num_records Output: The number of records returned in query + * @param records Output: Pointer to records. + * Must be freed by calling omgt_free_query_result_buffer + * + *@return OMGT_STATUS_SUCCESS if success, else error code + */ +OMGT_STATUS_T +omgt_sa_get_swcong_records( + struct omgt_port *port, + omgt_sa_selector_t *selector, + int32_t *num_records, + STL_SWITCH_CONGESTION_SETTING_RECORD **records + ) +{ + + OMGT_STATUS_T status; + QUERY_RESULT_VALUES *query_result; + STL_SWITCH_CONGESTION_SETTING_RECORD_RESULTS *record_results = NULL; + + status = omgt_sa_query_helper(port, selector, OutputTypeStlSwitchCongRecord, &query_result); + + if(OMGT_STATUS_SUCCESS != status) + return status; + + record_results = (STL_SWITCH_CONGESTION_SETTING_RECORD_RESULTS*)query_result->QueryResult; + *num_records = record_results->NumRecords; + if(*num_records == 0) { + *records = NULL; + goto exit; + } + + int buf_size = sizeof(**records) * (*num_records); + *records = malloc(buf_size); + if(*records == NULL){ + status = OMGT_STATUS_INSUFFICIENT_MEMORY; + goto exit; + } + + memcpy(*records, record_results->Records, buf_size); +exit: + omgt_free_query_result_buffer(query_result); + return status; +} + + +/** + * @brief Query SA for Switch Port Congestion Records + * + * @param port port opened by omgt_open_port_* + * @param selector Criteria to select records. NULL == all records + * @param num_records Output: The number of records returned in query + * @param records Output: Pointer to records. + * Must be freed by calling omgt_free_query_result_buffer + * + *@return OMGT_STATUS_SUCCESS if success, else error code + */ +OMGT_STATUS_T +omgt_sa_get_swportcong_records( + struct omgt_port *port, + omgt_sa_selector_t *selector, + int32_t *num_records, + STL_SWITCH_PORT_CONGESTION_SETTING_RECORD **records + ) +{ + + OMGT_STATUS_T status; + QUERY_RESULT_VALUES *query_result; + STL_SWITCH_PORT_CONGESTION_SETTING_RECORD_RESULTS *record_results = NULL; + + status = omgt_sa_query_helper(port, selector, OutputTypeStlSwitchPortCongRecord, &query_result); + + if(OMGT_STATUS_SUCCESS != status) + return status; + + record_results = (STL_SWITCH_PORT_CONGESTION_SETTING_RECORD_RESULTS*)query_result->QueryResult; + *num_records = record_results->NumRecords; + if(*num_records == 0) { + *records = NULL; + goto exit; + } + + int buf_size = sizeof(**records) * (*num_records); + *records = malloc(buf_size); + if(*records == NULL){ + status = OMGT_STATUS_INSUFFICIENT_MEMORY; + goto exit; + } + + memcpy(*records, record_results->Records, buf_size); +exit: + omgt_free_query_result_buffer(query_result); + return status; +} + + +/** + * @brief Query SA for HFI Congestion Records + * + * @param port port opened by omgt_open_port_* + * @param selector Criteria to select records. NULL == all records + * @param num_records Output: The number of records returned in query + * @param records Output: Pointer to records. + * Must be freed by calling omgt_free_query_result_buffer + * + *@return OMGT_STATUS_SUCCESS if success, else error code + */ +OMGT_STATUS_T +omgt_sa_get_hficong_records( + struct omgt_port *port, + omgt_sa_selector_t *selector, + int32_t *num_records, + STL_HFI_CONGESTION_SETTING_RECORD **records + ) +{ + + OMGT_STATUS_T status; + QUERY_RESULT_VALUES *query_result; + STL_HFI_CONGESTION_SETTING_RECORD_RESULTS *record_results = NULL; + + status = omgt_sa_query_helper(port, selector, OutputTypeStlHFICongRecord, &query_result); + + if(OMGT_STATUS_SUCCESS != status) + return status; + + record_results = (STL_HFI_CONGESTION_SETTING_RECORD_RESULTS*)query_result->QueryResult; + *num_records = record_results->NumRecords; + if(*num_records == 0) { + *records = NULL; + goto exit; + } + + int buf_size = sizeof(**records) * (*num_records); + *records = malloc(buf_size); + if(*records == NULL){ + status = OMGT_STATUS_INSUFFICIENT_MEMORY; + goto exit; + } + + memcpy(*records, record_results->Records, buf_size); +exit: + omgt_free_query_result_buffer(query_result); + return status; +} + + +/** + * @brief Query SA for HFI Congestion Control Records + * + * @param port port opened by omgt_open_port_* + * @param selector Criteria to select records. NULL == all records + * @param num_records Output: The number of records returned in query + * @param records Output: Pointer to records. + * Must be freed by calling omgt_free_query_result_buffer + * + *@return OMGT_STATUS_SUCCESS if success, else error code + */ +OMGT_STATUS_T +omgt_sa_get_hficongctrl_records( + struct omgt_port *port, + omgt_sa_selector_t *selector, + int32_t *num_records, + STL_HFI_CONGESTION_CONTROL_TABLE_RECORD **records + ) +{ + + OMGT_STATUS_T status; + QUERY_RESULT_VALUES *query_result; + STL_HFI_CONGESTION_CONTROL_TABLE_RECORD_RESULTS *record_results = NULL; + + status = omgt_sa_query_helper(port, selector, OutputTypeStlHFICongCtrlRecord, &query_result); + + if(OMGT_STATUS_SUCCESS != status) + return status; + + record_results = (STL_HFI_CONGESTION_CONTROL_TABLE_RECORD_RESULTS*)query_result->QueryResult; + *num_records = record_results->NumRecords; + if(*num_records == 0) { + *records = NULL; + goto exit; + } + + int buf_size = sizeof(**records) * (*num_records); + *records = malloc(buf_size); + if(*records == NULL){ + status = OMGT_STATUS_INSUFFICIENT_MEMORY; + goto exit; + } + + memcpy(*records, record_results->Records, buf_size); +exit: + omgt_free_query_result_buffer(query_result); + return status; +} + + +/** + * @brief Query SA for Buffer Control Table Records + * + * @param port port opened by omgt_open_port_* + * @param selector Criteria to select records. NULL == all records + * @param num_records Output: The number of records returned in query + * @param records Output: Pointer to records. + * Must be freed by calling omgt_free_query_result_buffer + * + *@return OMGT_STATUS_SUCCESS if success, else error code + */ +OMGT_STATUS_T +omgt_sa_get_buffctrl_records( + struct omgt_port *port, + omgt_sa_selector_t *selector, + int32_t *num_records, + STL_BUFFER_CONTROL_TABLE_RECORD **records + ) +{ + + OMGT_STATUS_T status; + QUERY_RESULT_VALUES *query_result; + STL_BUFFER_CONTROL_TABLE_RECORD_RESULTS *record_results = NULL; + + status = omgt_sa_query_helper(port, selector, OutputTypeStlBufCtrlTabRecord, &query_result); + + if(OMGT_STATUS_SUCCESS != status) + return status; + + record_results = (STL_BUFFER_CONTROL_TABLE_RECORD_RESULTS*)query_result->QueryResult; + *num_records = record_results->NumBufferControlRecords; + if(*num_records == 0) { + *records = NULL; + goto exit; + } + + int buf_size = sizeof(**records) * (*num_records); + *records = malloc(buf_size); + if(*records == NULL){ + status = OMGT_STATUS_INSUFFICIENT_MEMORY; + goto exit; + } + + memcpy(*records, record_results->BufferControlRecords, buf_size); +exit: + omgt_free_query_result_buffer(query_result); + return status; +} + + +/** + * @brief Query SA for Cable Info Records + * + * @param port port opened by omgt_open_port_* + * @param selector Criteria to select records. NULL == all records + * @param num_records Output: The number of records returned in query + * @param records Output: Pointer to records. + * Must be freed by calling omgt_free_query_result_buffer + * + *@return OMGT_STATUS_SUCCESS if success, else error code + */ +OMGT_STATUS_T +omgt_sa_get_cableinfo_records( + struct omgt_port *port, + omgt_sa_selector_t *selector, + int32_t *num_records, + STL_CABLE_INFO_RECORD **records + ) +{ + + OMGT_STATUS_T status; + QUERY_RESULT_VALUES *query_result; + STL_CABLE_INFO_RECORD_RESULTS *record_results = NULL; + + status = omgt_sa_query_helper(port, selector, OutputTypeStlCableInfoRecord, &query_result); + + if(OMGT_STATUS_SUCCESS != status) + return status; + + record_results = (STL_CABLE_INFO_RECORD_RESULTS*)query_result->QueryResult; + *num_records = record_results->NumCableInfoRecords; + if(*num_records == 0) { + *records = NULL; + goto exit; + } + + int buf_size = sizeof(**records) * (*num_records); + *records = malloc(buf_size); + if(*records == NULL){ + status = OMGT_STATUS_INSUFFICIENT_MEMORY; + goto exit; + } + + memcpy(*records, record_results->CableInfoRecords, buf_size); +exit: + omgt_free_query_result_buffer(query_result); + return status; +} + + +/** + * @brief Query SA for PortGroup Records + * + * @param port port opened by omgt_open_port_* + * @param selector Criteria to select records. NULL == all records + * @param num_records Output: The number of records returned in query + * @param records Output: Pointer to records. + * Must be freed by calling omgt_free_query_result_buffer + * + *@return OMGT_STATUS_SUCCESS if success, else error code + */ +OMGT_STATUS_T +omgt_sa_get_portgroup_records( + struct omgt_port *port, + omgt_sa_selector_t *selector, + int32_t *num_records, + STL_PORT_GROUP_TABLE_RECORD **records + ) +{ + + OMGT_STATUS_T status; + QUERY_RESULT_VALUES *query_result; + STL_PORT_GROUP_TABLE_RECORD_RESULTS *record_results = NULL; + + status = omgt_sa_query_helper(port, selector, OutputTypeStlPortGroupRecord, &query_result); + + if(OMGT_STATUS_SUCCESS != status) + return status; + + record_results = (STL_PORT_GROUP_TABLE_RECORD_RESULTS*)query_result->QueryResult; + *num_records = record_results->NumRecords; + if(*num_records == 0) { + *records = NULL; + goto exit; + } + + int buf_size = sizeof(**records) * (*num_records); + *records = malloc(buf_size); + if(*records == NULL){ + status = OMGT_STATUS_INSUFFICIENT_MEMORY; + goto exit; + } + + memcpy(*records, record_results->Records, buf_size); +exit: + omgt_free_query_result_buffer(query_result); + return status; +} + + +/** + * @brief Query SA for PortGroup forwarding table Records + * + * @param port port opened by omgt_open_port_* + * @param selector Criteria to select records. NULL == all records + * @param num_records Output: The number of records returned in query + * @param records Output: Pointer to records. + * Must be freed by calling omgt_free_query_result_buffer + * + *@return OMGT_STATUS_SUCCESS if success, else error code + */ +OMGT_STATUS_T +omgt_sa_get_portgroupfwd_records( + struct omgt_port *port, + omgt_sa_selector_t *selector, + int32_t *num_records, + STL_PORT_GROUP_FORWARDING_TABLE_RECORD **records + ) +{ + + OMGT_STATUS_T status; + QUERY_RESULT_VALUES *query_result; + STL_PORT_GROUP_FORWARDING_TABLE_RECORD_RESULTS *record_results = NULL; + + status = omgt_sa_query_helper(port, selector, OutputTypeStlPortGroupFwdRecord, &query_result); + + if(OMGT_STATUS_SUCCESS != status) + return status; + + record_results = (STL_PORT_GROUP_FORWARDING_TABLE_RECORD_RESULTS*)query_result->QueryResult; + *num_records = record_results->NumRecords; + if(*num_records == 0) { + *records = NULL; + goto exit; + } + + int buf_size = sizeof(**records) * (*num_records); + *records = malloc(buf_size); + if(*records == NULL){ + status = OMGT_STATUS_INSUFFICIENT_MEMORY; + goto exit; + } + + memcpy(*records, record_results->Records, buf_size); +exit: + omgt_free_query_result_buffer(query_result); + return status; +} + + +/** + * @brief Query SA for DeviceGroupName Records + * + * @param port port opened by omgt_open_port_* + * @param selector Criteria to select records. + * Valid InputType values: + * NoInput + * @param num_records Output: The number of records returned in query + * @param records Output: Pointer to records. + * Must be freed by calling omgt_sa_free_records + * + * @return OMGT_STATUS_SUCCESS if success, else error code + */ +OMGT_STATUS_T +omgt_sa_get_devicegroupname_records( + struct omgt_port *port, + omgt_sa_selector_t *selector, + int32_t *num_records, + STL_DEVICE_GROUP_NAME_RECORD **records + ) +{ + + OMGT_STATUS_T status; + QUERY_RESULT_VALUES *query_result; + STL_DEVICE_GROUP_NAME_RECORD_RESULTS *record_results = NULL; + + status = omgt_sa_query_helper(port, selector, OutputTypeStlDeviceGroupNameRecord, &query_result); + + if (OMGT_STATUS_SUCCESS != status) + return status; + + record_results = (STL_DEVICE_GROUP_NAME_RECORD_RESULTS*)query_result->QueryResult; + *num_records = record_results->NumRecords; + if(*num_records == 0) { + *records = NULL; + goto exit; + } + + int buf_size = sizeof(**records) * (*num_records); + *records = malloc(buf_size); + if(*records == NULL){ + status = OMGT_STATUS_INSUFFICIENT_MEMORY; + goto exit; + } + + memcpy(*records, record_results->Records, buf_size); + +exit: + omgt_free_query_result_buffer(query_result); + return status; +} + + +/** + * @brief Query SA for DeviceGroupMember Records + * + * @param port port opened by omgt_open_port_* + * @param selector Criteria to select records. + * Valid InputType values: + * NoInput, Lid, PortGuid, NodeDesc, DeviceGroup + * @param num_records Output: The number of records returned in query + * @param records Output: Pointer to records. + * Must be freed by calling omgt_sa_free_records + * + * @return OMGT_STATUS_SUCCESS if success, else error code + */ +OMGT_STATUS_T +omgt_sa_get_devicegroupmember_records( + struct omgt_port *port, + omgt_sa_selector_t *selector, + int32_t *num_records, + STL_DEVICE_GROUP_MEMBER_RECORD **records + ) +{ + + OMGT_STATUS_T status; + QUERY_RESULT_VALUES *query_result; + STL_DEVICE_GROUP_MEMBER_RECORD_RESULTS *record_results = NULL; + + status = omgt_sa_query_helper(port, selector, OutputTypeStlDeviceGroupMemberRecord, &query_result); + + if (OMGT_STATUS_SUCCESS != status) + return status; + + record_results = (STL_DEVICE_GROUP_MEMBER_RECORD_RESULTS*)query_result->QueryResult; + *num_records = record_results->NumRecords; + if(*num_records == 0) { + *records = NULL; + goto exit; + } + + int buf_size = sizeof(**records) * (*num_records); + *records = malloc(buf_size); + if(*records == NULL){ + status = OMGT_STATUS_INSUFFICIENT_MEMORY; + goto exit; + } + + memcpy(*records, record_results->Records, buf_size); + +exit: + omgt_free_query_result_buffer(query_result); + return status; +} + + +/** + * @brief Query SA for DeviceTreeMember Records + * + * @param port port opened by omgt_open_port_* + * @param selector Criteria to select records. + * Valid InputType values: + * NoInput, Lid + * @param num_records Output: The number of records returned in query + * @param records Output: Pointer to records. + * Must be freed by calling omgt_sa_free_records + * + * @return OMGT_STATUS_SUCCESS if success, else error code + */ +OMGT_STATUS_T +omgt_sa_get_devicetreemember_records( + struct omgt_port *port, + omgt_sa_selector_t *selector, + int32_t *num_records, + STL_DEVICE_TREE_MEMBER_RECORD **records + ) +{ + + OMGT_STATUS_T status; + QUERY_RESULT_VALUES *query_result; + STL_DEVICE_TREE_MEMBER_RECORD_RESULTS *record_results = NULL; + + status = omgt_sa_query_helper(port, selector, OutputTypeStlDeviceTreeMemberRecord, &query_result); + + if (OMGT_STATUS_SUCCESS != status) + return status; + + record_results = (STL_DEVICE_TREE_MEMBER_RECORD_RESULTS*)query_result->QueryResult; + *num_records = record_results->NumRecords; + if(*num_records == 0) { + *records = NULL; + goto exit; + } + + int buf_size = sizeof(**records) * (*num_records); + *records = malloc(buf_size); + if(*records == NULL){ + status = OMGT_STATUS_INSUFFICIENT_MEMORY; + goto exit; + } + + memcpy(*records, record_results->Records, buf_size); + +exit: + omgt_free_query_result_buffer(query_result); + return status; +} + + +/** + * @brief Query SA for SwitchCost Records + * + * @param port port opened by omgt_open_port_* + * @param selector Criteria to select records. + * Valid InputType values: + * NoInput, Lid + * @param num_records Output: The number of records returned in query + * @param records Output: Pointer to records. + * Must be freed by calling omgt_sa_free_records + * + * @return OMGT_STATUS_SUCCESS if success, else error code + */ +OMGT_STATUS_T +omgt_sa_get_switchcost_records( + struct omgt_port *port, + omgt_sa_selector_t *selector, + int32_t *num_records, + STL_SWITCH_COST_RECORD **records + ) +{ + + OMGT_STATUS_T status; + QUERY_RESULT_VALUES *query_result; + STL_SWITCH_COST_RECORD_RESULTS *record_results = NULL; + + status = omgt_sa_query_helper(port, selector, OutputTypeStlSwitchCostRecord, &query_result); + + if (OMGT_STATUS_SUCCESS != status) + return status; + + record_results = (STL_SWITCH_COST_RECORD_RESULTS*)query_result->QueryResult; + *num_records = record_results->NumRecords; + if(*num_records == 0) { + *records = NULL; + goto exit; + } + + int buf_size = sizeof(**records) * (*num_records); + *records = malloc(buf_size); + if(*records == NULL){ + status = OMGT_STATUS_INSUFFICIENT_MEMORY; + goto exit; + } + + memcpy(*records, record_results->Records, buf_size); + +exit: + omgt_free_query_result_buffer(query_result); + return status; +} + diff --git a/opamgt/src/stl_convertfuncs.c b/opamgt/src/stl_convertfuncs.c new file mode 100644 index 0000000..bcccafe --- /dev/null +++ b/opamgt/src/stl_convertfuncs.c @@ -0,0 +1,366 @@ +/* BEGIN_ICS_COPYRIGHT5 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + * ** END_ICS_COPYRIGHT5 ****************************************/ +/* [ICS VERSION STRING: unknown] */ + +#include "iba/stl_mad_priv.h" +#include "stl_convertfuncs.h" + +int stl_CopyIbNodeInfo(STL_NODE_INFO * dest, NODE_INFO * src, int cpyVerInfo) +{ + if (cpyVerInfo) { + dest->BaseVersion = src->BaseVersion; + dest->ClassVersion = src->ClassVersion; + } + else { + dest->BaseVersion = STL_BASE_VERSION; + dest->ClassVersion = STL_SM_CLASS_VERSION; + } + + dest->NodeType = src->NodeType; + dest->NumPorts = src->NumPorts; + + dest->SystemImageGUID = src->SystemImageGUID; + + dest->NodeGUID = src->NodeGUID; + dest->PortGUID = src->PortGUID; + + dest->PartitionCap = src->PartitionCap; + + dest->DeviceID = src->DeviceID; + + dest->Revision = src->Revision; + + dest->u1.AsReg32 = src->u1.AsReg32; + + return 0; +} + +int stl_CopyStlNodeInfo(NODE_INFO * dest, STL_NODE_INFO * src, int cpyVerInfo) +{ + if (cpyVerInfo) { + dest->BaseVersion = src->BaseVersion; + dest->ClassVersion = src->ClassVersion; + } + else { + dest->BaseVersion = IB_BASE_VERSION; + dest->ClassVersion = IB_SM_CLASS_VERSION; + } + + dest->NodeType = src->NodeType; + dest->NumPorts = src->NumPorts; + + dest->SystemImageGUID = src->SystemImageGUID; + + dest->NodeGUID = src->NodeGUID; + dest->PortGUID = src->PortGUID; + + dest->PartitionCap = src->PartitionCap; + + dest->DeviceID = src->DeviceID; + + dest->Revision = src->Revision; + + dest->u1.AsReg32 = src->u1.AsReg32; + + return 0; +} + +int IB2STL_NODE_INFO(NODE_INFO *pIb, STL_NODE_INFO *pStl) +{ + if (!pIb || !pStl) return -1; + + // Fields shared with IB (in IB listed order) + pStl->BaseVersion = pIb->BaseVersion; + pStl->ClassVersion = pIb->ClassVersion; + pStl->NodeType = pIb->NodeType; + pStl->NumPorts = pIb->NumPorts; + pStl->SystemImageGUID = pIb->SystemImageGUID; + pStl->NodeGUID = pIb->NodeGUID; + pStl->PortGUID = pIb->PortGUID; + pStl->PartitionCap = pIb->PartitionCap; + pStl->DeviceID = pIb->DeviceID; + pStl->Revision = pIb->Revision; + pStl->u1.AsReg32 = pIb->u1.AsReg32; + + // STL fields with no IB equiv + pStl->Reserved = 0; + + return 0; +}; + +int STL2IB_NODE_INFO(STL_NODE_INFO *pStl, NODE_INFO *pIb) +{ + if (!pIb || !pStl) return -1; + + pIb->BaseVersion = pStl->BaseVersion; + pIb->ClassVersion = pStl->ClassVersion; + pIb->NodeType = pStl->NodeType; + pIb->NumPorts = pStl->NumPorts; + pIb->SystemImageGUID = pStl->SystemImageGUID; + pIb->NodeGUID = pStl->NodeGUID; + pIb->PortGUID = pStl->PortGUID; + pIb->PartitionCap = pStl->PartitionCap; + pIb->DeviceID = pStl->DeviceID; + pIb->Revision = pStl->Revision; + pIb->u1.AsReg32 = pStl->u1.AsReg32; + + return 0; +}; + +int IB2STL_PORT_INFO(PORT_INFO *pIb, STL_PORT_INFO *pStl) +{ + if (!pIb || !pStl) return -1; + + // Fields shared with IB (in IB listed order) + pStl->M_Key = pIb->M_Key; + pStl->SubnetPrefix = pIb->SubnetPrefix; + pStl->LID = (STL_LID)pIb->LID; + pStl->MasterSMLID = (STL_LID)pIb->MasterSMLID; + pStl->CapabilityMask.AsReg32 = pIb->CapabilityMask.AsReg32; + pStl->DiagCode.AsReg16 = pIb->DiagCode; + pStl->M_KeyLeasePeriod = pIb->M_KeyLeasePeriod; + pStl->LocalPortNum = pIb->LocalPortNum; + // TODO FIX THIS pStl->LinkWidth, pIb->LinkWidth; + //struct _LinkWidth { + // uint8 Enabled; /* Enabled link width */ + // uint8 Supported; /* Supported link width */ + // uint8 Active; /* Currently active link width */ + //} LinkWidth; +#if 0 + pStl->Link; + struct { +#if CPU_BE + uint8 SpeedSupported: 4; /* Supported link speed */ + uint8 PortState: 4; /* Port State. */ +#else + uint8 PortState: 4; /* Port State. */ + uint8 SpeedSupported: 4; /* Supported link speed */ +#endif +#if CPU_BE + uint8 PortPhysicalState: 4; + uint8 DownDefaultState: 4; +#else + uint8 DownDefaultState: 4; + uint8 PortPhysicalState: 4; +#endif + } Link; + + struct { +#if CPU_BE + uint8 M_KeyProtectBits: 2; /* see mgmt key usage */ + uint8 Reserved: 3; /* reserved, shall be zero */ + uint8 LMC: 3; /* LID mask for multipath support */ +#else + uint8 LMC: 3; /* LID mask for multipath support */ + uint8 Reserved: 3; /* reserved, shall be zero */ + uint8 M_KeyProtectBits: 2; /* see mgmt key usage */ +#endif + } s1; + + struct _LinkSpeed { +#if CPU_BE + uint8 Active: 4; /* Currently active link speed */ + uint8 Enabled: 4; /* Enabled link speed */ +#else + uint8 Enabled: 4; /* Enabled link speed */ + uint8 Active: 4; /* Currently active link speed */ +#endif + } LinkSpeed; + + struct { +#if CPU_BE + uint8 NeighborMTU: 4; + uint8 MasterSMSL: 4; +#else + uint8 MasterSMSL: 4; /* The adminstrative SL of the master */ + /* SM that is managing this port. */ + uint8 NeighborMTU: 4; /* MTU of neighbor endnode connected */ + /* to this port */ +#endif + } s2; + + + struct { + struct { +#if CPU_BE + uint8 Cap: 4; /* Virtual Lanes supported on this port */ + uint8 InitType: 4; /* IB_PORT_INIT_TYPE */ +#else + uint8 InitType: 4; /* IB_PORT_INIT_TYPE */ + uint8 Cap: 4; /* Virtual Lanes supported on this port */ +#endif + } s; + + uint8 HighLimit; /* Limit of high priority component of */ + /* VL Arbitration table */ + uint8 ArbitrationHighCap; + uint8 ArbitrationLowCap; + } VL; + + struct { +#if CPU_BE + uint8 InitTypeReply: 4; /* IB_PORT_INIT_TYPE */ + uint8 Cap: 4; /* Maximum MTU supported by this port. */ +#else + uint8 Cap: 4; /* Maximum MTU supported by this port. */ + uint8 InitTypeReply: 4; /* IB_PORT_INIT_TYPE */ +#endif + } MTU; + + struct { /* transmitter Queueing Controls */ +#if CPU_BE + uint8 VLStallCount: 3; + uint8 HOQLife: 5; +#else + uint8 HOQLife: 5; /* Applies to routers & switches only */ + uint8 VLStallCount: 3; /* Applies to switches only. */ +#endif + } XmitQ; + + struct { +#if CPU_BE + uint8 OperationalVL: 4; /* Virtual Lanes */ + uint8 PartitionEnforcementInbound: 1; + uint8 PartitionEnforcementOutbound: 1; + uint8 FilterRawInbound: 1; + uint8 FilterRawOutbound: 1; +#else + uint8 FilterRawOutbound: 1; + uint8 FilterRawInbound: 1; + uint8 PartitionEnforcementOutbound: 1; + uint8 PartitionEnforcementInbound: 1; + uint8 OperationalVL: 4; /* Virtual Lanes */ + /* operational on this port */ +#endif + } s3; + + struct _Violations { + uint16 M_Key; + uint16 P_Key; + uint16 Q_Key; + } Violations; + + pStl->GUIDCap = pIb->GUIDCap; + + struct { +#if CPU_BE + uint8 ClientReregister: 1; + uint8 Reserved: 2; + uint8 Timeout: 5; +#else + uint8 Timeout: 5; /* Timer value used for subnet timeout */ + uint8 Reserved: 2; + uint8 ClientReregister: 1; +#endif + } Subnet; + + + struct { +#if CPU_BE + uint8 Reserved: 3; + uint8 TimeValue: 5; +#else + uint8 TimeValue: 5; + uint8 Reserved: 3; +#endif + + } Resp; + + struct _ERRORS { +#if CPU_BE + uint8 LocalPhys: 4; + uint8 Overrun: 4; +#else + uint8 Overrun: 4; + uint8 LocalPhys: 4; +#endif + } Errors; +#endif // 0 + +#if 0 + struct _LATENCY { +#if CPU_BE + uint32 Reserved: 8; + uint32 LinkRoundTrip: 24; /* LinkRoundTripLatency */ +#else + uint32 LinkRoundTrip: 24; + uint32 Reserved: 8; +#endif + } Latency; +#endif // 0 + +#if 0 + struct _LinkSpeedExt { +#if CPU_BE + uint8 Active: 4; /* Currently active link speed extended */ + uint8 Supported: 4; /* Supported link speed extended */ +#else + uint8 Supported: 4; /* Supported link speed extended */ + uint8 Active: 4; /* Currently active link speed extended */ +#endif +#if CPU_BE + uint8 Reserved: 3; /* Reserved */ + uint8 Enabled: 5; /* Enabled link speed extended */ +#else + uint8 Enabled: 5; /* Enabled link speed extended */ + uint8 Reserved: 3; /* Reserved */ +#endif + } LinkSpeedExt; +#endif // 0 + + // STL fields with no IB equiv + // TODO + return -1; +}; + +int STL2IB_PORT_INFO(STL_PORT_INFO *pStl, PORT_INFO *pIb) +{ + if (!pIb || !pStl) return -1; + + // TODO + return -1; +}; + +int IB2STL_SWITCH_INFO(SWITCH_INFO *pIb, STL_SWITCH_INFO *pStl) +{ + if (!pIb || !pStl) return -1; + + // Fields shared with IB (in IB listed order) + // STL fields with no IB equiv + // TODO + return -1; +}; + +int STL2IB_SWITCH_INFO(STL_SWITCH_INFO *pStl, SWITCH_INFO *pIb) +{ + if (!pIb || !pStl) return -1; + + // TODO + return -1; +}; diff --git a/opamgt/src/stl_convertfuncs.h b/opamgt/src/stl_convertfuncs.h new file mode 100644 index 0000000..ce21d1d --- /dev/null +++ b/opamgt/src/stl_convertfuncs.h @@ -0,0 +1,74 @@ +/* BEGIN_ICS_COPYRIGHT5 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + * ** END_ICS_COPYRIGHT5 ****************************************/ +/* [ICS VERSION STRING: unknown] */ + +#ifndef _stl_convertfuncs_h_included_ +#define _stl_convertfuncs_h_included_ 1 + +#include "iba/ib_sm_priv.h" +#include "iba/stl_sm_priv.h" + +/** + @file Provides functions for converting IB to STL data structures. +*/ + +/** + IB->STL: copy/convert values from @c src to @c dest. + + @param cpyVerInfo If 0, set (Base|Class)Version to STL values, otherwise, copy from @c src. + + @return 0 on success, non-zero otherwise. +*/ +int stl_CopyIbNodeInfo(STL_NODE_INFO * dest, NODE_INFO * src, int cpyVerInfo); + +/** + STL->IB: copy/convert values from @c src to @c dest. + + @param cpyVerInfo If 0, set (Base|Class)Version to IB values, otherwise, copy from @c src. + + @return 0 on success, non-zero otherwise. +*/ +int stl_CopyStlNodeInfo(NODE_INFO * dest, STL_NODE_INFO * src, int cpyVerInfo); + +#if 1 +/* These functions facilitate conversions between IB and STL formats. */ +/* Primary user is intended to be the SM */ +/* A non-zero return value indicates a problem with the conversion and results should not be used. */ +/* IB can be exactly mapped to STL. Extra info in STL format is defaulted. */ +/* STL cannot be exactly mapped to IB. If STL value is not compatible with IB an error may be returned. */ +int IB2STL_NODE_INFO(NODE_INFO *pIb, STL_NODE_INFO *pStl); +int STL2IB_NODE_INFO(STL_NODE_INFO *pStl, NODE_INFO *pIb); +int IB2STL_PORT_INFO(PORT_INFO *pIb, STL_PORT_INFO *pStl); +int STL2IB_PORT_INFO(STL_PORT_INFO *pStl, PORT_INFO *pIb); +int IB2STL_SWITCH_INFO(SWITCH_INFO *pIb, STL_SWITCH_INFO *pStl); +int STL2IB_SWITCH_INFO(STL_SWITCH_INFO *pStl, SWITCH_INFO *pIb); +#endif + + +#endif /* _stl_convertfuncs_h_included_ */ diff --git a/opamgt/version b/opamgt/version new file mode 100644 index 0000000..1d0ba9e --- /dev/null +++ b/opamgt/version @@ -0,0 +1 @@ +0.4.0 diff --git a/opasadb/Makefile b/opasadb/Makefile new file mode 100644 index 0000000..38d3ac3 --- /dev/null +++ b/opasadb/Makefile @@ -0,0 +1,171 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** +# Makefile for opasadb + +# Include Make Control Settings +include $(TL_DIR)/$(PROJ_FILE_DIR)/Makesettings.project + +#=============================================================================# +# Definitions: +#-----------------------------------------------------------------------------# + +# Name of SubProjects +DS_SUBPROJECTS = +# name of executable or downloadable image +EXECUTABLE = +# list of sub directories to build +DIRS = \ + $(shell ls -d lib 2>/dev/null) \ + $(shell ls -d path_tools 2>/dev/null) \ + # Add more directories here + #$(shell ls -d job_tools 2>/dev/null) Removed from STL Gen 1. + #$(shell ls -d route_tools 2>/dev/null) Removed from STL Gen 1. + +# C files (.c) +CFILES = \ + # Add more c files here +# C++ files (.cpp) +CCFILES = \ + # Add more cpp files here +# lex files (.lex) +LFILES = \ + # Add more lex files here +# archive library files (basename, $ARFILES will add MOD_LIB_DIR/prefix and suffix) +LIBFILES = +# Windows Resource Files (.rc) +RSCFILES = +# Windows IDL File (.idl) +IDLFILE = +# Windows Linker Module Definitions (.def) file for dll's +DEFFILE = +# targets to build during INCLUDES phase (add public includes here) +INCLUDE_TARGETS = \ + # Add more h hpp files here +# Non-compiled files +MISC_FILES = +# all source files +SOURCES = $(CFILES) $(CCFILES) $(LFILES) $(RSCFILES) $(IDLFILE) +# Source files to include in DSP File +DSP_SOURCES = $(INCLUDE_TARGETS) $(SOURCES) $(MISC_FILES) \ + $(RSCFILES) $(DEFFILE) $(MAKEFILE) +# all object files +OBJECTS = $(CFILES:.c=$(OBJ_SUFFIX)) $(CCFILES:.cpp=$(OBJ_SUFFIX)) \ + $(LFILES:.lex=$(OBJ_SUFFIX)) \ + # Add more object files here +RSCOBJECTS = $(RSCFILES:.rc=$(RES_SUFFIX)) +# targets to build during LIBS phase +LIB_TARGETS_IMPLIB = +LIB_TARGETS_ARLIB = +LIB_TARGETS_EXP = $(LIB_TARGETS_IMPLIB:$(ARLIB_SUFFIX)=$(EXP_SUFFIX)) +LIB_TARGETS_MISC = +# targets to build during CMDS phase +#SHLIB_VERSION = +#CMD_TARGETS_SHLIB = +CMD_TARGETS_EXE = $(EXECUTABLE) +CMD_TARGETS_MISC = +# files to remove during clean phase +CLEAN_TARGETS_MISC = +CLEAN_TARGETS = $(OBJECTS) $(RSCOBJECTS) $(IDL_TARGETS) $(CLEAN_TARGETS_MISC) +# other files to remove during clobber phase +CLOBBER_TARGETS_MISC= +# sub-directory to install to within bin +BIN_SUBDIR = +# sub-directory to install to within include +INCLUDE_SUBDIR = + +# Additional Settings +#CLOCALDEBUG = User defined C debugging compilation flags [Empty] +#CCLOCALDEBUG = User defined C++ debugging compilation flags [Empty] +# User defined C flags for compiling +# User defined C++ flags for compiling +#CCLOCAL = +#BSCLOCAL = User flags for Browse File Builder [Empty] +#DEPENDLOCAL = user defined makedepend flags [Empty] +#LINTLOCAL = User defined lint flags [Empty] +# User include directories to search for C/C++ headers +LOCAL_INCLUDE_DIRS = +#LDLOCAL = User defined C flags for linking [Empty] +#IMPLIBLOCAL = User flags for Object Lirary Manager [Empty] +#MIDLLOCAL = User flags for IDL compiler [Empty] +#RSCLOCAL = User flags for resource compiler [Empty] +# User libraries to include in dependencies +LOCALDEPLIBS = +# User libraries to use when linking (in addition to LOCALDEPLIBS) +#LOCALLIBS = $(OPENIB_USER_LIBS) $(IBACCESS_USER_LIBS) +LOCALLIBS = $(OPENIB_USER_LIBS) +# User library directories for libpaths +#LOCAL_LIB_DIRS = $(OPENIB_USER_LIB_DIRS) $(IBACCESS_USER_LIB_DIRS) +LOCAL_LIB_DIRS = + +# Include Make Rules definitions and rules +include $(TL_DIR)/IbaTools/Makerules.module + +#=============================================================================# +# Overrides: +#-----------------------------------------------------------------------------# +# C++ optimization flags, default lets build config decide +#CCOPT = +# C optimization flags, default lets build config decide +#COPT = -fPIC +#SUBSYSTEM = Subsystem to build for (none, console or windows) [none] +# (Windows Only) +#USEMFC = How Windows MFC should be used (none, static, shared, no_mfc) [none] +# (Windows Only) +#=============================================================================# + +#=============================================================================# +# Rules: +#-----------------------------------------------------------------------------# +# process Sub-directories +include $(TL_DIR)/Makerules/Maketargets.toplevel + +# build cmds and libs +include $(TL_DIR)/Makerules/Maketargets.build + +# install for includes, libs and cmds phases +include $(TL_DIR)/Makerules/Maketargets.install + +# install for stage phase +#include $(TL_DIR)/Makerules/Maketargets.stage +STAGE:: + $(VS)$(STAGE_INSTALL) $(STAGE_INSTALL_DIR_OPT) $(PROJ_STAGE_FASTFABRIC_DIR) $(EXECUTABLE) + +clean:: + + +clobber:: + +# Unit test execution +#include $(TL_DIR)/Makerules/Maketargets.runtest + +#=============================================================================# + +#=============================================================================# +# DO NOT DELETE THIS LINE -- make depend depends on it. +#=============================================================================# diff --git a/opasadb/README b/opasadb/README new file mode 100644 index 0000000..ef70a3a --- /dev/null +++ b/opasadb/README @@ -0,0 +1,2 @@ +library of extended functions to support queries of SA replica +and job management APIs for FM diff --git a/opasadb/job_tools/Makefile b/opasadb/job_tools/Makefile new file mode 100644 index 0000000..73cccb7 --- /dev/null +++ b/opasadb/job_tools/Makefile @@ -0,0 +1,162 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** +# Makefile for opasadb/job_tools + +# Include Make Control Settings +include $(TL_DIR)/$(PROJ_FILE_DIR)/Makesettings.project + +#=============================================================================# +# Definitions: +#-----------------------------------------------------------------------------# + +# Name of SubProjects +DS_SUBPROJECTS = +# name of executable or downloadable image +EXECUTABLE = $(BUILDDIR)/iba_smjobgen$(EXE_SUFFIX) +# list of sub directories to build +DIRS = +# C files (.c) +CFILES = \ + opasadb_job_gen.c \ + # Add more c files here +# C++ files (.cpp) +CCFILES = \ + # Add more cpp files here +# lex files (.lex) +LFILES = \ + # Add more lex files here +# archive library files (basename, $ARFILES will add MOD_LIB_DIR/prefix and suffix) +LIBFILES = +# Windows Resource Files (.rc) +RSCFILES = +# Windows IDL File (.idl) +IDLFILE = +# Windows Linker Module Definitions (.def) file for dll's +DEFFILE = +# targets to build during INCLUDES phase (add public includes here) +INCLUDE_TARGETS = \ + # Add more h hpp files here +# Non-compiled files +MISC_FILES = +# all source files +SOURCES = $(CFILES) $(CCFILES) $(LFILES) $(RSCFILES) $(IDLFILE) +# Source files to include in DSP File +DSP_SOURCES = $(INCLUDE_TARGETS) $(SOURCES) $(MISC_FILES) \ + $(RSCFILES) $(DEFFILE) $(MAKEFILE) +# all object files +OBJECTS = $(CFILES:.c=$(OBJ_SUFFIX)) $(CCFILES:.cpp=$(OBJ_SUFFIX)) \ + $(LFILES:.lex=$(OBJ_SUFFIX)) \ + # Add more object files here +RSCOBJECTS = $(RSCFILES:.rc=$(RES_SUFFIX)) +# targets to build during LIBS phase +LIB_TARGETS_IMPLIB = +LIB_TARGETS_ARLIB = +LIB_TARGETS_EXP = $(LIB_TARGETS_IMPLIB:$(ARLIB_SUFFIX)=$(EXP_SUFFIX)) +LIB_TARGETS_MISC = +# targets to build during CMDS phase +SHLIB_VERSION = +CMD_TARGETS_SHLIB = +CMD_TARGETS_EXE = $(EXECUTABLE) +CMD_TARGETS_MISC = +# files to remove during clean phase +CLEAN_TARGETS_MISC = +CLEAN_TARGETS = $(OBJECTS) $(RSCOBJECTS) $(IDL_TARGETS) $(CLEAN_TARGETS_MISC) +# other files to remove during clobber phase +CLOBBER_TARGETS_MISC= +# sub-directory to install to within bin +BIN_SUBDIR = +# sub-directory to install to within include +INCLUDE_SUBDIR = + +# Additional Settings +#CLOCALDEBUG = User defined C debugging compilation flags [Empty] +#CCLOCALDEBUG = User defined C++ debugging compilation flags [Empty] +# User defined C flags for compiling +# User defined C++ flags for compiling +#CCLOCAL = +#BSCLOCAL = User flags for Browse File Builder [Empty] +#DEPENDLOCAL = user defined makedepend flags [Empty] +#LINTLOCAL = User defined lint flags [Empty] +# User include directories to search for C/C++ headers +LOCAL_INCLUDE_DIRS = +#LDLOCAL = User defined C flags for linking [Empty] +#IMPLIBLOCAL = User flags for Object Lirary Manager [Empty] +#MIDLLOCAL = User flags for IDL compiler [Empty] +#RSCLOCAL = User flags for resource compiler [Empty] +# User libraries to include in dependencies +LOCALDEPLIBS = $(IBACCESS_USER_LIBS) opamgt-priv +# User libraries to use when linking (in addition to LOCALDEPLIBS) +# opasadb is a shared library, not needed in LOCALDEPLIBS +LOCALLIBS = $(OPENIB_USER_LIBS) opasadb rt +# User library directories for libpaths +LOCAL_LIB_DIRS = $(OPENIB_USER_LIB_DIRS) $(IBACCESS_USER_LIB_DIRS) + +CLOCAL = $(CPIE) + +# Include Make Rules definitions and rules +include $(TL_DIR)/IbaTools/Makerules.module + +#=============================================================================# +# Overrides: +#-----------------------------------------------------------------------------# +# C++ optimization flags, default lets build config decide +#CCOPT = +# C optimization flags, default lets build config decide +#COPT = -fPIC +#SUBSYSTEM = Subsystem to build for (none, console or windows) [none] +# (Windows Only) +#USEMFC = How Windows MFC should be used (none, static, shared, no_mfc) [none] +# (Windows Only) +#=============================================================================# + +#=============================================================================# +# Rules: +#-----------------------------------------------------------------------------# +# process Sub-directories +include $(TL_DIR)/Makerules/Maketargets.toplevel + +# build cmds and libs +include $(TL_DIR)/Makerules/Maketargets.build + +# install for includes, libs and cmds phases +include $(TL_DIR)/Makerules/Maketargets.install + +# install for stage phase +#include $(TL_DIR)/Makerules/Maketargets.stage +STAGE:: + $(VS)$(STAGE_INSTALL) $(STAGE_INSTALL_DIR_OPT) $(PROJ_STAGE_FASTFABRIC_DIR) $(EXECUTABLE) + +# Unit test execution +#include $(TL_DIR)/Makerules/Maketargets.runtest + +#=============================================================================# + +#=============================================================================# +# DO NOT DELETE THIS LINE -- make depend depends on it. +#=============================================================================# diff --git a/opasadb/job_tools/opasadb_job_gen.c b/opasadb/job_tools/opasadb_job_gen.c new file mode 100644 index 0000000..001744d --- /dev/null +++ b/opasadb/job_tools/opasadb_job_gen.c @@ -0,0 +1,891 @@ +/* BEGIN_ICS_COPYRIGHT5 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT5 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + + +/******************************************************************************* + * + * INCLUDES + */ + +#include +#include +#include +#include + +#include "ib_ibt.h" + +#include "opamgt_sa_priv.h" +#include "opasadb_route2.h" +#include "statustext.h" + + +/******************************************************************************* + * + * DEFINES + */ + +// Configuration parameters +#define NAME_PROG "iba_smjobgen" // Program name + +#define NUM_PARAM_PORT_GUID_ALLOC 8 // Num port GUID params to alloc +#define MAX_CHARS_PORT_GUID_ENTER 18 // Max chars port GUID entry +#define MAX_CHARS_JOB_NAME_ENTER 64 // Max chars job name entry +#define MAX_CHARS_APP_NAME_ENTER 64 // Max chars app name entry + +#define MAX_COST_ENTRIES_LINE 14 // Max cost matrix values per line + +// Commands +typedef enum +{ + none = 0, // No command + show, // Show HFI port GUIDs + create // Create job + +} COMMAND; + +// Parameter allocation entry structures +// Note that these structs must align with op_route_param_alloc_entry in +// opasadb_route2.h +struct op_route_param_alloc_port_guid_entry +{ + uint64_t size_param; // Size of param (bf_data) allocated (bytes) + uint64_t size_data; // Size of param (bf_data) in use (bytes) + uint64_t size_enter; // Size of param entered (chars) + // NOTE: previous uint64_t ensures uint64_t alignment of bf_data + char bf_data[MAX_CHARS_PORT_GUID_ENTER + 1]; // Allocated param buffer +}; + + +/******************************************************************************* + * + * LOCAL VARIABLES + */ + +static COMMAND command = none; // Console command + +static uint8_t hfi = 0; +static uint8_t port = 0; +static uint64_t connect_portguid = 0; +static uint8_t optn_create_job = OP_ROUTE_CREATE_JOB_NORMAL; + +static struct op_route_param_alloc param_port_guid; + +static OP_ROUTE_JOB_ID job_id = 0; // Active job ID +static struct op_route_job_parameters job_params = // Active job parameters + {"", "", 0, 0}; +static uint16_t switch_index = 0; // Active switch index value +static struct op_route_portguid_vec portguid_vec; // Active portguid_vec +static struct op_route_switch_map switch_map; // Active switch_map +static uint16_t * p_cost_matrix; // Pointer to active cost matrix +static struct op_route_use_matrix use_matrix; // Active use_matrix + +static boolean fb_have_connectguid = FALSE; // Parsed connect portGUID value +static boolean fb_have_hfiport = FALSE; // Parsed HFI or port value +static boolean fb_allguids = FALSE; // All portGUIDs flag +static boolean fb_have_portguid = FALSE; // Parsed HFI portGUID value +static boolean fb_showcost = FALSE; // Show cost_matrix flag +static boolean fb_showguidswitch = FALSE; // Show GUID/switch flag +static boolean fb_showuse = FALSE; // Show use_matrix flag +static boolean fb_verbose = FALSE; // Verbose flag + +// Command line option table, each has a short and long flag name +static struct option tb_options[] = +{ + { "verbose", no_argument, NULL, 'v' }, + { "portguid", required_argument, NULL, 'g' }, + { "hfi", required_argument, NULL, 'h' }, + { "port", required_argument, NULL, 'p' }, + { "jobname", required_argument, NULL, 'J' }, + { "appname", required_argument, NULL, 'N' }, + { "pid", required_argument, NULL, 'i' }, + { "uid", required_argument, NULL, 'I' }, + { "allports", no_argument, NULL, 'a' }, + { "guid", required_argument, NULL, 'G' }, + { "nocreate", no_argument, NULL, 'n' }, + { "cost", no_argument, NULL, 'c' }, + { "switch", no_argument, NULL, 's' }, + { "index", no_argument, NULL, 'S' }, + { "use", no_argument, NULL, 'u' }, + { 0 } +}; + + +/******************************************************************************* + * + * FUNCTIONS + */ + + +/******************************************************************************* + * + * err_usage() + * + * Description: + * Output information about program usage and parameters. + * + * Inputs: + * none + * + * Outputs: + * none + */ +void err_usage(void) +{ + fprintf(stderr, "Usage: " NAME_PROG " show|create [-g portguid][-h hfi][-p port]\n"); + fprintf(stderr, " [-J job_name][-N app_name][-i pid][-I uid]\n"); + fprintf(stderr, " [-a][-G portguid][-n][-c][-s][-u][-S index][-v]\n"); + fprintf(stderr, " -g/--portguid portguid - port GUID to connect via\n"); + fprintf(stderr, " -h/--hfi hfi - hfi to connect via, numbered 1..n, 0= -p port will\n"); + fprintf(stderr, " be a system wide port num (default is 0)\n"); + fprintf(stderr, " -p/--port port - port to connect via, numbered 1..n, 0=1st active\n"); + fprintf(stderr, " (default is 1st active)\n"); + fprintf(stderr, " -J/--jobname job_name - create job_name\n"); + fprintf(stderr, " -N/--appname app_name - create app_name\n"); + fprintf(stderr, " -i/--pid pid - create pid\n"); + fprintf(stderr, " -I/--uid uid - create uid\n"); + fprintf(stderr, " -a/--allports - show/create all FI ports\n"); + fprintf(stderr, " -G/--guid portguid - show/create FI port GUID (multiple entries)\n"); + fprintf(stderr, " -n/--nocreate - don't create job\n"); + fprintf(stderr, " -c/--cost - show cost matrix for job\n"); + fprintf(stderr, " -s/--switch - show portGUID vector and switch map for job\n"); + fprintf(stderr, " -u/--use - show use matrix for job\n"); + fprintf(stderr, " -S/--index index - switch index for show cost matrix, default is 0\n"); + fprintf(stderr, " -v/--verbose - verbose output\n"); + + fprintf(stderr, "\n"); + fprintf(stderr, "The -h and -p options permit a variety of selections:\n"); + fprintf(stderr, " -h 0 - 1st active port in system (this is the default)\n"); + fprintf(stderr, " -h 0 -p 0 - 1st active port in system\n"); + fprintf(stderr, " -h x - 1st active port on HFI x\n"); + fprintf(stderr, " -h x -p 0 - 1st active port on HFI x\n"); + fprintf(stderr, " -h 0 -p y - port y within system (irrespective of which ports are active)\n"); + fprintf(stderr, " -h x -p y - HFI x, port y\n"); +} // End of err_usage() + +/******************************************************************************* + * + * get_opt() + * + * Description: + * Get command line options. Parses command line options using short and + * long option (parameter) definitions. Parameters (file static variables) + * are updated appropriately. + * + * Inputs: + * argc - Number of input parameters + * argv - Array of pointers to input parameters + * p_opt_short - Pointer to string of short option definitions + * tb_opt_long - Array of long option definitions + * + * Outputs: + * none + */ +void get_opt( int argc, char ** argv, const char *p_opt_short, + struct option tb_opt_long[] ) +{ + int ix; + int c_opt; // Option parsing char + int ix_opt; // Option parsing index + size_t len_str; // String length + uint64_t temp; // Temporary input area + char * p_opt_end; // Pointer to end of parsed parameter + // Pointer to port GUID param + struct op_route_param_alloc_port_guid_entry * p_param_port_guid; + + // Input command + if (argc >= 2) + { + if (!strcmp(argv[1], "show")) + command = show; + else if (!strcmp(argv[1], "create")) + command = create; + } + + if (command == none) + { + fprintf(stderr, NAME_PROG ": Invalid Command:%s\n", argc >= 2 ? argv[1] : "NULL"); + err_usage(); + return; + } + + // Shift arguments + for (ix = 1; ix < argc; ix++) + argv[ix] = argv[ix + 1]; + argc--; + + // Input command line arguments + while ( ( c_opt = getopt_long( argc, argv, p_opt_short, tb_opt_long, + &ix_opt ) ) != -1 ) + { + len_str = 0; + switch (c_opt) + { + + // Verbose + case 'v': + fb_verbose = TRUE; + break; + + // Connect port GUID specification + case 'g': + if (fb_have_hfiport) + { + fprintf(stderr, NAME_PROG ": Can't use -g with -h/-p\n"); + err_usage(); + return; + } + + if (!optarg) + { + fprintf(stderr, NAME_PROG ": No connect port GUID value\n"); + err_usage(); + return; + } + + errno = 0; + temp = strtoull(optarg, &p_opt_end, 0); + if (errno || !p_opt_end || (*p_opt_end != '\0')) + { + fprintf(stderr, NAME_PROG ": Invalid connect port GUID value:%s\n", optarg); + err_usage(); + return; + } + + connect_portguid = temp; + fb_have_connectguid = TRUE; + break; + + // HFI specification + case 'h': + if (fb_have_connectguid) + { + fprintf(stderr, NAME_PROG ": Can't use -h with -g\n"); + err_usage(); + return; + } + + if (!optarg) + { + fprintf(stderr, NAME_PROG ": No HFI value\n"); + err_usage(); + return; + } + + errno = 0; + temp = (uint64_t)strtoul(optarg, &p_opt_end, 0); + if ( (temp > IB_UINT8_MAX) || errno || !p_opt_end || + (*p_opt_end != '\0') ) + { + fprintf(stderr, NAME_PROG ": Invalid HFI value:%s\n", optarg); + err_usage(); + return; + } + + hfi = (uint8_t)temp; + fb_have_hfiport = TRUE; + break; + + // Port specification + case 'p': + if (fb_have_connectguid) + { + fprintf(stderr, NAME_PROG ": Can't use -p with -g\n"); + err_usage(); + return; + } + + if (!optarg) + { + fprintf(stderr, NAME_PROG ": No port value\n"); + err_usage(); + return; + } + + errno = 0; + temp = (uint64_t)strtoul(optarg, &p_opt_end, 0); + if ( (temp > IB_UINT8_MAX) || errno || !p_opt_end || + (*p_opt_end != '\0') ) + { + fprintf(stderr, NAME_PROG ": Invalid port value:%s\n", optarg); + err_usage(); + return; + } + + port = (uint8_t)temp; + fb_have_hfiport = TRUE; + break; + + // Job name specification + case 'J': + if (!optarg) + { + fprintf(stderr, NAME_PROG ": No job name\n"); + err_usage(); + return; + } + + len_str = strlen(optarg); + if (len_str > MAX_CHARS_JOB_NAME_ENTER) + { + fprintf( stderr, NAME_PROG ": Invalid job name length:%"PRIu64" %s\n", + len_str, optarg ); + err_usage(); + return; + } + + strcpy(job_params.name, optarg); + break; + + // App name specification + case 'N': + if (!optarg) + { + fprintf(stderr, NAME_PROG ": No app name\n"); + err_usage(); + return; + } + + len_str = strlen(optarg); + if (len_str > MAX_CHARS_APP_NAME_ENTER) + { + fprintf( stderr, NAME_PROG ": Invalid app name length:%"PRIu64" %s\n", + len_str, optarg ); + err_usage(); + return; + } + + strcpy(job_params.application_name, optarg); + break; + + // PID specification + case 'i': + if (!optarg) + { + fprintf(stderr, NAME_PROG ": No PID value\n"); + err_usage(); + return; + } + + errno = 0; + temp = strtoull(optarg, &p_opt_end, 0); + if (errno || !p_opt_end || (*p_opt_end != '\0')) + { + fprintf(stderr, NAME_PROG ": Invalid PID value:%s\n", optarg); + err_usage(); + return; + } + + job_params.pid = temp; + break; + + // UID specification + case 'I': + if (!optarg) + { + fprintf(stderr, NAME_PROG ": No UID value\n"); + err_usage(); + return; + } + + errno = 0; + temp = strtoull(optarg, &p_opt_end, 0); + if (errno || !p_opt_end || (*p_opt_end != '\0')) + { + fprintf(stderr, NAME_PROG ": Invalid UID value:%s\n", optarg); + err_usage(); + return; + } + + job_params.uid = temp; + break; + + // All FI port GUIDs specification + case 'a': + if (fb_have_portguid) + { + fprintf(stderr, NAME_PROG ": Can't use -a with -G\n"); + err_usage(); + return; + } + + fb_allguids = TRUE; + break; + + // FI port GUID specification + case 'G': + if (fb_allguids) + { + fprintf(stderr, NAME_PROG ": Can't use -G with -a\n"); + err_usage(); + return; + } + + if (!optarg) + { + fprintf(stderr, NAME_PROG ": No FI port GUID value\n"); + err_usage(); + return; + } + + errno = 0; + temp = strtoull(optarg, &p_opt_end, 0); + if (errno || !p_opt_end || (*p_opt_end != '\0')) + { + fprintf(stderr, NAME_PROG ": Invalid FI port GUID value:%s\n", optarg); + err_usage(); + return; + } + + // Store FI port GUID parameter + if (param_port_guid.num_used == param_port_guid.num_allocated) + if (op_route_alloc_param(¶m_port_guid)) + { + fprintf(stderr, NAME_PROG + ": Unable to allocate port GUID parameter\n"); + err_usage(); + return; + } + + p_param_port_guid = + &( (struct op_route_param_alloc_port_guid_entry *) + param_port_guid.p_params )[param_port_guid.num_used++]; + p_param_port_guid->size_param = sizeof(p_param_port_guid->bf_data); + p_param_port_guid->size_data = sizeof(uint64_t); + p_param_port_guid->size_enter = sizeof(uint64_t) * 2; + *(uint64_t *)(p_param_port_guid->bf_data) = temp; + + fb_have_portguid = TRUE; + break; + + // Don't create job specification + case 'n': + optn_create_job = OP_ROUTE_CREATE_JOB_NO_CREATE; + break; + + // Show cost matrix specification + case 'c': + fb_showcost = TRUE; + break; + + // Show port GUID vector and switch map specifications + case 's': + fb_showguidswitch = TRUE; + break; + + // Switch index value + case 'S': + if (!optarg) + { + fprintf(stderr, NAME_PROG ": No switch index value\n"); + err_usage(); + return; + } + + errno = 0; + temp = (uint64_t)strtoul(optarg, &p_opt_end, 0); + if ( (temp > OP_ROUTE_MAX_SWITCHES) || errno || !p_opt_end || + (*p_opt_end != '\0') ) + { + fprintf(stderr, NAME_PROG ": Invalid switch index value:%s\n", optarg); + err_usage(); + return; + } + + switch_index = (uint16_t)temp; + break; + + // Show use matrix specification + case 'u': + fb_showuse = TRUE; + break; + + default: + fprintf(stderr, NAME_PROG ": Invalid Option -<%c>\n", c_opt); + err_usage(); + return; + break; + + } // End of switch (c_opt) + + } // End of while ( ( c_opt = getopt_long( argc, argv, + + // Validate command line arguments + if (optind < argc) + { + fprintf(stderr, "%s: invalid argument %s\n", NAME_PROG, argv[optind]); + err_usage(); + return; + } + + if (command == show) + { + if (!fb_have_portguid) + fb_allguids = TRUE; + } + +} // End of get_opt() + +/******************************************************************************* + * + * main() + * + * Description: + * Console function; provides general maintenance and debugging facilities + * for library functions. + * + * Inputs: + * argc - Number of input parameters + * argv - Array of pointers to input parameters + * + * Outputs: + * Exit status 0 - no errors + * Exit status 2 - error + */ +int main(int argc, char ** argv) +{ + int ret_val = 0; + int64 ix, ix_2, ix_3; + FSTATUS fstatus; + uint8_t rstatus; + OP_ROUTE_PORT_HANDLE port_handle = 0; + OMGT_QUERY SDQuery; + QUERY_RESULT_VALUES *pSDQueryResults = NULL; + GUID_RESULTS *pSDGuidResults = NULL; + static struct omgt_port *omgt_port_session = NULL; + + struct op_route_param_alloc_port_guid_entry * p_param_port_guid; + + // Initialize allocated parameters + if ( op_route_init_param( ¶m_port_guid, + sizeof(struct op_route_param_alloc_port_guid_entry), + NUM_PARAM_PORT_GUID_ALLOC ) ) + { + fprintf(stderr, NAME_PROG ": Unable to allocate port_guid parameter\n"); + err_usage(); + return 2; + } + + // Get and validate command line arguments + get_opt(argc, argv, "vg:h:p:J:N:i:I:aG:ncsuS:", tb_options); + + // Initialize + memset(&portguid_vec, 0, sizeof(portguid_vec)); + memset(&switch_map, 0, sizeof(switch_map)); + memset(&use_matrix, 0, sizeof(use_matrix)); + + // Get default port GUID if none specified + if (!fb_have_connectguid) + { + fstatus = iba_get_portguid( hfi, port, NULL, &connect_portguid, NULL, + NULL, NULL, NULL ); + + if (FNOT_FOUND == fstatus) { + fprintf(stderr, NAME_PROG ": %s\n", + iba_format_get_portguid_error(hfi, port, caCount, portCount)); + //err_usage(); + exit(1); + } else if (fstatus != FSUCCESS) + { + fprintf( stderr, NAME_PROG + ": can't get port GUID from hfi:%u port:%u fstatus:%u (%s)\n", + hfi, port, (unsigned int)fstatus, iba_fstatus_msg(fstatus) ); + exit(1); + } + } + + fstatus = omgt_open_port_by_guid(&omgt_port_session, connect_portguid, NULL); + if (fstatus != FSUCCESS) { + fprintf(stderr, "Unable to open fabric interface.\n"); + ret_val = 2; + goto free_param; + } + + // Get list of all FI port GUIDS if all specified + if (fb_allguids) + { + memset(&SDQuery, 0, sizeof(SDQuery)); + SDQuery.InputType = InputTypeNodeType; + SDQuery.InputValue.IbNodeRecord.NodeType = STL_NODE_FI; + SDQuery.OutputType = OutputTypePortGuid; + + fstatus = omgt_query_sa(omgt_port_session, + &SDQuery, + &pSDQueryResults); + + if (fstatus != FSUCCESS || !pSDQueryResults) + { + fprintf( stderr, NAME_PROG ": SD query for FI port GUIDs failed (status=0x%X): %s\n", + (int)fstatus, iba_fstatus_msg(fstatus) ); + err_usage(); + ret_val = 2; + goto close_port; + } + + if ( !(pSDGuidResults = (GUID_RESULTS *)pSDQueryResults->QueryResult) || + !pSDGuidResults->NumGuids ) + { + fprintf(stderr, NAME_PROG ": No SD query FI port GUIDs\n"); + omgt_free_query_result_buffer(pSDQueryResults); + err_usage(); + ret_val = 2; + goto close_port; + } + + for (ix = 0; ix < pSDGuidResults->NumGuids; ix++) + { + if (param_port_guid.num_used == param_port_guid.num_allocated) + if (op_route_alloc_param(¶m_port_guid)) + { + fprintf( stderr, NAME_PROG + ": Unable to allocate port_guid parameter\n" ); + omgt_free_query_result_buffer(pSDQueryResults); + err_usage(); + ret_val = 2; + goto close_port; + } + + p_param_port_guid = + &( (struct op_route_param_alloc_port_guid_entry *) + param_port_guid.p_params )[param_port_guid.num_used++]; + p_param_port_guid->size_param = sizeof(p_param_port_guid->bf_data); + p_param_port_guid->size_data = sizeof(uint64_t); + p_param_port_guid->size_enter = sizeof(uint64_t) * 2; + *(uint64_t *)(p_param_port_guid->bf_data) = + pSDGuidResults->Guids[ix]; + + } // End of for (ix = 0; ix < pSDGuidResults->NumGuids; ix++) + + omgt_free_query_result_buffer(pSDQueryResults); + + } // End of if (fb_allguids) + + // Open port connection + if ( (rstatus = op_route_open(omgt_port_session, connect_portguid, &port_handle)) != + OP_ROUTE_STATUS_OK ) + { + fprintf( stderr, NAME_PROG ": open Error rstatus(0x%X):%s, GUID:0x%" + PRIX64"\n", rstatus, op_route_get_status_text(rstatus), + connect_portguid ); + err_usage(); + ret_val = 2; + goto close_port; + } + + // Copy param_port_guid to portguid_vec + if ((portguid_vec.num_guids = param_port_guid.num_used)) + if ( !( portguid_vec.p_guids = + calloc(portguid_vec.num_guids, sizeof(uint64_t)) ) ) + { + fprintf(stderr, NAME_PROG ": Unable to alloc port GUID vector\n"); + err_usage(); + ret_val = 2; + goto close_route; + } + + for ( ix = 0, p_param_port_guid = + (struct op_route_param_alloc_port_guid_entry *)param_port_guid.p_params; + ix < portguid_vec.num_guids; p_param_port_guid++, ix++ ) + portguid_vec.p_guids[ix] = *(uint64_t *)p_param_port_guid->bf_data; + + // Execute command + switch (command) + { + + // Show command + case show: + { + printf(NAME_PROG ": Show Ports\n"); + + printf("CA-Ports(%u):\n", param_port_guid.num_used); + for (ix = 0; ix < portguid_vec.num_guids; ix++) + printf(" %-3"PRId64" 0x%016"PRIX64"\n", ix, portguid_vec.p_guids[ix]); + + break; + + } // End of case show + + // Create job command + case create: + { + rstatus = op_route_create_job( port_handle, optn_create_job, &job_params, + &portguid_vec, omgt_port_session, &job_id, &switch_map, &p_cost_matrix ); + if (rstatus != OP_ROUTE_STATUS_OK) + { + fprintf(stderr, NAME_PROG ": Create Job Error rstatus(0x%X):%s\n", + rstatus, op_route_get_status_text(rstatus)); + goto close_route; + } + + printf(NAME_PROG ": Create Job: ID:0x%016"PRIX64"\n", job_id); + + // Show job parameters + if (fb_verbose) + { + printf("\nJob Parameters: Name:%s AppName:%s\n", job_params.name, + job_params.application_name ); + printf( " PID:0x%"PRIX64" UID:0x%"PRIX64"\n", + job_params.pid, job_params.uid ); + } + + // Show port GUID vector and switch map + if (fb_showguidswitch) + { + printf( "\nPortGUID Vector: GUIDs:%-5u Switch Map: Switches:%-u\n", + portguid_vec.num_guids, switch_map.num_switches ); + + for (ix = 0; ix < portguid_vec.num_guids; ix++) + printf( "%5"PRId64": 0x%016"PRIX64" %5u\n", + ix, portguid_vec.p_guids[ix], + switch_map.p_switch_indices[ix] ); + } + + // Get and show cost matrix + if (fb_showcost) + { + // Print title and column headers + printf( "\nCost Matrix (hex): Switches:%u\n", + switch_map.num_switches ); + if (switch_map.num_switches) + { + if (switch_index < switch_map.num_switches) + { + ix = switch_index; + if ( (ix_3 = switch_index + MAX_COST_ENTRIES_LINE) > + switch_map.num_switches ) + ix_3 = switch_map.num_switches; + } + + else + { + ix = 0; + if ( (ix_3 = switch_map.num_switches) > + MAX_COST_ENTRIES_LINE ) + ix_3 = MAX_COST_ENTRIES_LINE; + } + + printf(" %4"PRId64, ix++); + for ( ; ix < ix_3; ix++) + printf(" %4"PRId64, ix); + printf("\n"); + + // Print cost matrix data + for ( ix = 0; ix < switch_map.num_switches; + ix++ ) + { + printf(" %4"PRId64":", ix); + + ix_2 = ix * switch_map.num_switches; + if (switch_index < switch_map.num_switches) + { + ix_2 += switch_index; + if ( (ix_3 = switch_map.num_switches - switch_index) > + MAX_COST_ENTRIES_LINE ) + ix_3 = MAX_COST_ENTRIES_LINE; + } + + else + { + if ( (ix_3 = switch_map.num_switches) > + MAX_COST_ENTRIES_LINE ) + ix_3 = MAX_COST_ENTRIES_LINE; + } + + for ( ; ix_3 > 0; ix_3--) + printf(" %04X", p_cost_matrix[ix_2++]); + printf("\n"); + + } // End of for ( ix = 0; ix < switch_map.num_switches + + } // End of if (switch_map.num_switches) + + } // End of if (fb_showcost) + + // Get and show use matrix + if (fb_showuse) + { + printf( "\nUse Matrix: Elements:%u Default Use:%u Multiplier:%u\n", + use_matrix.num_elements, use_matrix.default_use, + use_matrix.multiplier ); + + for (ix = 0; ix < use_matrix.num_elements; ix++) + printf( " %4"PRId64": Index:%5d DLID:0x%04X Use:%u Bursty:%u\n", ix, + use_matrix.p_elements[ix].switch_index, + use_matrix.p_elements[ix].dlid, + use_matrix.p_elements[ix].use, + use_matrix.p_elements[ix].bursty ); + } + + if (fb_showguidswitch || fb_showcost || fb_showuse) + printf("\n"); + + // Release and clear tables + op_route_release_portguid_vec(&portguid_vec); + portguid_vec.num_guids = 0; + op_route_release_switch_map(&switch_map); + switch_map.num_switches = 0; + op_route_release_cost_matrix(p_cost_matrix); + p_cost_matrix = NULL; + op_route_release_use_matrix(&use_matrix); + use_matrix.num_elements = 0; + use_matrix.default_use = 0; + use_matrix.multiplier = 0; + + break; + + } // End of case create + + // Invalid command + default: + fprintf(stderr, NAME_PROG ": Invalid Command\n"); + err_usage(); + ret_val = 2; + break; + + } // End of switch (command) + + // Close port connection +close_route: + op_route_close(port_handle); + +close_port: + omgt_close_port(omgt_port_session); + +free_param: + op_route_free_param(¶m_port_guid); + + printf("--------------------------------------------------\n"); + + return (ret_val); + +} // End of main() + + +// End of file diff --git a/opasadb/lib/Makefile b/opasadb/lib/Makefile new file mode 100644 index 0000000..e40a9a0 --- /dev/null +++ b/opasadb/lib/Makefile @@ -0,0 +1,182 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** +# Makefile for opasadb/lib + +# Include Make Control Settings +include $(TL_DIR)/$(PROJ_FILE_DIR)/Makesettings.project + +#=============================================================================# +# Definitions: +#-----------------------------------------------------------------------------# + +# Name of SubProjects +DS_SUBPROJECTS = +# name of executable or downloadable image +EXECUTABLE = +# list of sub directories to build +DIRS = \ + $(shell ls -d route 2>/dev/null) \ + $(shell ls -d path 2>/dev/null) \ + $(shell ls -d debug 2>/dev/null) \ + # Add more directories here +# This is a bit of a hack, not worth the complexity of a modules style +# makefile for this handful of files +VPATH = debug route path +# C files (.c) +CFILES = \ + opasadb_debug.c \ + opasadb_route.c \ + opasadb_path.c \ + opasadb_path_private.c \ + opasadb_query_many.c \ + opasadb_static_db.c \ + # Add more c files here +# C++ files (.cpp) +CCFILES = \ + # Add more cpp files here +# lex files (.lex) +LFILES = \ + # Add more lex files here +# archive library files (basename, $ARFILES will add MOD_LIB_DIR/prefix and suffix) +LIBFILES = +# Windows Resource Files (.rc) +RSCFILES = +# Windows IDL File (.idl) +IDLFILE = +# Windows Linker Module Definitions (.def) file for dll's +DEFFILE = +# targets to build during INCLUDES phase (add public includes here) +INCLUDE_TARGETS = \ + # Add more h hpp files here +# Non-compiled files +MISC_FILES = +# all source files +SOURCES = $(CFILES) $(CCFILES) $(LFILES) $(RSCFILES) $(IDLFILE) +# Source files to include in DSP File +DSP_SOURCES = $(INCLUDE_TARGETS) $(SOURCES) $(MISC_FILES) \ + $(RSCFILES) $(DEFFILE) $(MAKEFILE) +# all object files +OBJECTS = $(CFILES:.c=$(OBJ_SUFFIX)) $(CCFILES:.cpp=$(OBJ_SUFFIX)) \ + $(LFILES:.lex=$(OBJ_SUFFIX)) \ + # Add more object files here +RSCOBJECTS = $(RSCFILES:.rc=$(RES_SUFFIX)) +# targets to build during LIBS phase +LIB_TARGETS_IMPLIB = +#LIB_TARGETS_ARLIB = $(LIB_PREFIX)opasadb$(ARLIB_SUFFIX) +LIB_TARGETS_ARLIB = +LIB_TARGETS_EXP = $(LIB_TARGETS_IMPLIB:$(ARLIB_SUFFIX)=$(EXP_SUFFIX)) +LIB_TARGETS_MISC = +# targets to build during CMDS phase +SHLIB_VERSION = 1.0.0 +CMD_TARGETS_SHLIB = $(LIB_PREFIX)opasadb$(SHLIB_VERSION_SUFFIX) +#CMD_TARGETS_SHLIB = +CMD_TARGETS_EXE = $(EXECUTABLE) +CMD_TARGETS_MISC = +# files to remove during clean phase +CLEAN_TARGETS_MISC = +CLEAN_TARGETS = $(OBJECTS) $(RSCOBJECTS) $(IDL_TARGETS) $(CLEAN_TARGETS_MISC) +# other files to remove during clobber phase +CLOBBER_TARGETS_MISC= libopasadb.map +# sub-directory to install to within bin +BIN_SUBDIR = +# sub-directory to install to within include +INCLUDE_SUBDIR = + +# Additional Settings +#CLOCALDEBUG = User defined C debugging compilation flags [Empty] +#CCLOCALDEBUG = User defined C++ debugging compilation flags [Empty] +# User defined C flags for compiling +CLOCAL = $(CPIC) +# User defined C++ flags for compiling +#CCLOCAL = +#BSCLOCAL = User flags for Browse File Builder [Empty] +#DEPENDLOCAL = user defined makedepend flags [Empty] +#LINTLOCAL = User defined lint flags [Empty] +# User include directories to search for C/C++ headers +LOCAL_INCLUDE_DIRS = +LDLOCAL = -Wl,--version-script=libopasadb.map +#IMPLIBLOCAL = User flags for Object Lirary Manager [Empty] +#MIDLLOCAL = User flags for IDL compiler [Empty] +#RSCLOCAL = User flags for resource compiler [Empty] +# User libraries to include in dependencies +LOCALDEPLIBS = opamgt-priv $(IBACCESS_USER_LIBS) +# User libraries to use when linking (in addition to LOCALDEPLIBS) +#LOCALLIBS = $(OPENIB_USER_LIBS) $(IBACCESS_USER_LIBS) +ifeq ($(shell cat path/opasadb_static_db.c),) +LOCALLIBS = $(OPENIB_USER_LIBS) rt +else +LOCALLIBS = $(OPENIB_USER_LIBS) rt json-c +endif +# User library directories for libpaths +LOCAL_LIB_DIRS = $(OPENIB_USER_LIB_DIRS) $(IBACCESS_USER_LIB_DIRS) + +# Include Make Rules definitions and rules +include $(TL_DIR)/IbaTools/Makerules.module + +CLOCAL += $(shell pkg-config --cflags json-c) +LDLOCAL+= $(shell pkg-config --libs json-c) + +#=============================================================================# +# Overrides: +#-----------------------------------------------------------------------------# +# C++ optimization flags, default lets build config decide +#CCOPT = +# C optimization flags, default lets build config decide +#COPT = -fPIC +#SUBSYSTEM = Subsystem to build for (none, console or windows) [none] +# (Windows Only) +#USEMFC = How Windows MFC should be used (none, static, shared, no_mfc) [none] +# (Windows Only) +#=============================================================================# + +#=============================================================================# +# Rules: +#-----------------------------------------------------------------------------# +# process Sub-directories +include $(TL_DIR)/Makerules/Maketargets.toplevel + +# build cmds and libs +include $(TL_DIR)/Makerules/Maketargets.build + +# install for includes, libs and cmds phases +include $(TL_DIR)/Makerules/Maketargets.install + +# install for stage phase +#include $(TL_DIR)/Makerules/Maketargets.stage +STAGE:: + $(VS)$(STAGE_INSTALL) $(STAGE_INSTALL_DIR_OPT) $(PROJ_STAGE_LIB_DIR) $(CMD_TARGETS_SHLIB) + +# Unit test execution +#include $(TL_DIR)/Makerules/Maketargets.runtest + +#=============================================================================# + +#=============================================================================# +# DO NOT DELETE THIS LINE -- make depend depends on it. +#=============================================================================# diff --git a/opasadb/lib/debug/Makefile b/opasadb/lib/debug/Makefile new file mode 100644 index 0000000..c0df238 --- /dev/null +++ b/opasadb/lib/debug/Makefile @@ -0,0 +1,162 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** +# Makefile for opasadb/lib/route + +# Include Make Control Settings +include $(TL_DIR)/$(PROJ_FILE_DIR)/Makesettings.project + +#=============================================================================# +# Definitions: +#-----------------------------------------------------------------------------# + +# Name of SubProjects +DS_SUBPROJECTS = +# name of executable or downloadable image +EXECUTABLE = +# list of sub directories to build +DIRS = +# C files (.c) +CFILES = \ + opasadb_debug.c \ + # Add more c files here +# C++ files (.cpp) +CCFILES = \ + # Add more cpp files here +# lex files (.lex) +LFILES = \ + # Add more lex files here +# archive library files (basename, $ARFILES will add MOD_LIB_DIR/prefix and suffix) +LIBFILES = +# Windows Resource Files (.rc) +RSCFILES = +# Windows IDL File (.idl) +IDLFILE = +# Windows Linker Module Definitions (.def) file for dll's +DEFFILE = +# targets to build during INCLUDES phase (add public includes here) +INCLUDE_TARGETS = \ + opasadb_debug.h \ + # Add more h hpp files here +# Non-compiled files +MISC_FILES = \ + # Add more misc files here +# all source files +SOURCES = $(CFILES) $(CCFILES) $(LFILES) $(RSCFILES) $(IDLFILE) +# Source files to include in DSP File +DSP_SOURCES = $(INCLUDE_TARGETS) $(SOURCES) $(MISC_FILES) \ + $(RSCFILES) $(DEFFILE) $(MAKEFILE) +# all object files +OBJECTS = $(CFILES:.c=$(OBJ_SUFFIX)) $(CCFILES:.cpp=$(OBJ_SUFFIX)) \ + $(LFILES:.lex=$(OBJ_SUFFIX)) \ + # Add more object files here +RSCOBJECTS = $(RSCFILES:.rc=$(RES_SUFFIX)) +# targets to build during LIBS phase +LIB_TARGETS_IMPLIB = +LIB_TARGETS_ARLIB = +LIB_TARGETS_EXP = $(LIB_TARGETS_IMPLIB:$(ARLIB_SUFFIX)=$(EXP_SUFFIX)) +LIB_TARGETS_MISC = +# targets to build during CMDS phase +#SHLIB_VERSION = +#CMD_TARGETS_SHLIB = +CMD_TARGETS_EXE = $(EXECUTABLE) +CMD_TARGETS_MISC = +# files to remove during clean phase +CLEAN_TARGETS_MISC = +CLEAN_TARGETS = $(OBJECTS) $(RSCOBJECTS) $(IDL_TARGETS) $(CLEAN_TARGETS_MISC) +# other files to remove during clobber phase +CLOBBER_TARGETS_MISC= +# sub-directory to install to within bin +BIN_SUBDIR = +# sub-directory to install to within include +INCLUDE_SUBDIR = + +# Additional Settings +#CLOCALDEBUG = User defined C debugging compilation flags [Empty] +#CCLOCALDEBUG = User defined C++ debugging compilation flags [Empty] +# User defined C flags for compiling +# User defined C++ flags for compiling +#CCLOCAL = +#BSCLOCAL = User flags for Browse File Builder [Empty] +#DEPENDLOCAL = user defined makedepend flags [Empty] +#LINTLOCAL = User defined lint flags [Empty] +# User include directories to search for C/C++ headers +LOCAL_INCLUDE_DIRS = +#LDLOCAL = User defined C flags for linking [Empty] +#IMPLIBLOCAL = User flags for Object Lirary Manager [Empty] +#MIDLLOCAL = User flags for IDL compiler [Empty] +#RSCLOCAL = User flags for resource compiler [Empty] +# User libraries to include in dependencies +LOCALDEPLIBS = +# User libraries to use when linking (in addition to LOCALDEPLIBS) +#LOCALLIBS = $(OPENIB_USER_LIBS) $(IBACCESS_USER_LIBS) +LOCALLIBS = +# User library directories for libpaths +#LOCAL_LIB_DIRS = $(OPENIB_USER_LIB_DIRS) $(IBACCESS_USER_LIB_DIRS) +LOCAL_LIB_DIRS = + +# Include Make Rules definitions and rules +include $(TL_DIR)/IbaTools/Makerules.module + +#=============================================================================# +# Overrides: +#-----------------------------------------------------------------------------# +# C++ optimization flags, default lets build config decide +#CCOPT = +# C optimization flags, default lets build config decide +#SUBSYSTEM = Subsystem to build for (none, console or windows) [none] +# (Windows Only) +#USEMFC = How Windows MFC should be used (none, static, shared, no_mfc) [none] +# (Windows Only) +#=============================================================================# + +#=============================================================================# +# Rules: +#-----------------------------------------------------------------------------# +# process Sub-directories +include $(TL_DIR)/Makerules/Maketargets.toplevel + +# build cmds and libs +include $(TL_DIR)/Makerules/Maketargets.build + +# install for includes, libs and cmds phases +include $(TL_DIR)/Makerules/Maketargets.install + +# install for stage phase +#include $(TL_DIR)/Makerules/Maketargets.stage +STAGE:: + $(VS)$(STAGE_INSTALL) $(STAGE_INSTALL_DIR_OPT) $(PROJ_STAGE_OPA_SA_DB_DIR) $(INCLUDE_TARGETS) + +# Unit test execution +#include $(TL_DIR)/Makerules/Maketargets.runtest + +#=============================================================================# + +#=============================================================================# +# DO NOT DELETE THIS LINE -- make depend depends on it. +#=============================================================================# diff --git a/opasadb/lib/debug/opasadb_debug.c b/opasadb/lib/debug/opasadb_debug.c new file mode 100644 index 0000000..7bd3c4d --- /dev/null +++ b/opasadb/lib/debug/opasadb_debug.c @@ -0,0 +1,106 @@ +/* BEGIN_ICS_COPYRIGHT4 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT4 ****************************************/ +/*! + + \file opasadb_debug.c + + $Revision: 1.10 $ + $Date: 2015/01/27 23:00:35 $ + +*/ +#include +#include +#include +#include +#include "opasadb_debug.h" + +static unsigned verbosity_level = _DBG_LVL_DEFAULT; +static unsigned use_syslog = 0; +static FILE *log_file = NULL; + +int op_log_set_file(const char *fname) { + FILE *f = fopen(fname,"a"); + if (!f) return -1; + + log_file = f; + use_syslog = 0; + return 0; +} + +FILE *op_log_get_file(void) { + return log_file; +} + +void op_log_syslog(const char *ident, unsigned level, unsigned facility) { + verbosity_level = level; + openlog(ident,LOG_NOWAIT,facility); + use_syslog = 1; +} + +void op_log_set_level(unsigned level) { + verbosity_level = level; +} + +void op_log(const char *fn, unsigned level, const char *format,...) +{ + va_list ap; + char buffer[1024]; + + // We have to do this here, because stderr isn't a constant. + if (!log_file && !use_syslog) log_file = stderr; + + if (verbosity_level >= level) { + if (use_syslog) { + sprintf(buffer,"%s%c%s", + (fn)?fn:"", + (fn)?'/':' ', + format); + } else { + char tbuf[1024]; + time_t t = time(NULL); + struct tm tm; + + localtime_r(&t,&tm); + strftime(tbuf,64,"%Y-%m-%d %H:%M:%S",&tm); + snprintf(buffer, sizeof(buffer), + "%s|%s%c%s", + tbuf, + (fn)?fn:"", + (fn)?'/':' ', + format); + } + + va_start(ap, format); + if (use_syslog) vsyslog(LOG_CRIT, buffer, ap); + else vfprintf(log_file, buffer, ap); + va_end(ap); + } + + if (!use_syslog) fflush(log_file); +} diff --git a/opasadb/lib/debug/opasadb_debug.h b/opasadb/lib/debug/opasadb_debug.h new file mode 100644 index 0000000..77decb4 --- /dev/null +++ b/opasadb/lib/debug/opasadb_debug.h @@ -0,0 +1,121 @@ +/* BEGIN_ICS_COPYRIGHT4 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT4 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +/*! + + \file srp_debug.h + + $Revision: 1.8 $ + $Date: 2015/01/22 18:04:15 $ + +*/ +#ifndef _DBG_DEBUG_H_ +#define _DBG_DEBUG_H_ + +#include +#include + +#if defined(__cplusplus) +extern "C" { +#endif + +/*---------------------------------------------------------------------------------- + Debug information. + --------------------------------------------------------------------------------*/ + +/* ------ Debug Levels definitions ------ + * Following is the list of Debug levels for the user of this debug utility + * Note: The numbers matches the kernel system log levels. Some of the levels + * as indicated are not used by this debug utility + */ +enum _DBG_LEVELS +{ + _DBG_LVL_EMERGENCY, /* 0, LOG_EMERG, System is unusable (Not used, reserved for system usage) */ + _DBG_LVL_ALERT, /* 1, LOG_ALERT, Action must be taken immediately (Not used, reserved for system usage) */ + _DBG_LVL_FATAL, /* 2 LOG_CRIT, Critical conditions */ + _DBG_LVL_ERROR, /* 3 LOG_ERR, Error conditions */ + _DBG_LVL_WARN, /* 4 LOG_WARNING,Warning conditions */ + _DBG_LVL_NOTICE, /* 5, LOG_NOTICE, Normal but significant condition. */ + _DBG_LVL_INFO, /* 6 LOG_INFO, Informational */ + _DBG_LVL_DEBUG, /* 7 LOG_DEBUG, Debug-level messages */ +}; + +/* Default Debug Level */ +#define _DBG_LVL_DEFAULT (_DBG_LVL_NOTICE) + +void op_log_syslog(const char *ident, unsigned level, unsigned facility); +void op_log_set_level(unsigned level); +void op_log(const char *fn, unsigned level, const char *format,...); +int op_log_set_file(const char *fname); +FILE *op_log_get_file(void); + +#define stringize(x) #x +#define add_quotes(x) stringize(x) + +#define _DBG_INIT(ident, level) op_log_syslog(ident, level, LOG_LOCAL6) + +#if defined(ICSDEBUG) + +#define _DBG_ASSERT(_exp_) { if(!(_exp_)) op_log(__func__, _DBG_LVL_ERROR, "ASSERT:"#_exp_"\n"); exit(-1); } +#define _DBG_FATAL(varParam...) { op_log(__func__, _DBG_LVL_FATAL, "FATAL: "varParam); exit(-1); } +#define _DBG_ERROR(varParam...) op_log(__func__, _DBG_LVL_ERROR, "ERROR: "varParam) +#define _DBG_WARN(varParam...) op_log(__func__, _DBG_LVL_WARN, "WARN: "varParam) +#define _DBG_PRINT(varParam...) op_log(__func__, _DBG_LVL_NOTICE, varParam) +#define _DBG_NOTICE(varParam...) op_log(__func__, _DBG_LVL_NOTICE, "NOTICE: "varParam) +#define _DBG_INFO(varParam...) op_log(__func__, _DBG_LVL_INFO, "INFO: "varParam) +#define _DBG_DEBUG(varParam...) op_log(__func__, _DBG_LVL_DEBUG, "DBG: "varParam) + +#define _DBG_FUNC_ENTRY op_log(__func__, _DBG_LVL_DEBUG, "Enter\n") +#define _DBG_FUNC_EXIT op_log(__func__, _DBG_LVL_DEBUG, "Exit\n") + +#else +// Note that asserts don't terminate in release builds. +#define _DBG_ASSERT(_exp_) { if(!(_exp_)) op_log(NULL, _DBG_LVL_ERROR, "ASSERT:"#_exp_"\n"); } +#define _DBG_FATAL(varParam...) { op_log(__func__, _DBG_LVL_FATAL, "FATAL: "varParam); exit(-1); } +#define _DBG_ERROR(varParam...) op_log(NULL, _DBG_LVL_ERROR, "ERROR: "varParam) +#define _DBG_WARN(varParam...) op_log(NULL, _DBG_LVL_WARN, "WARN: "varParam) +#define _DBG_PRINT(varParam...) op_log(NULL, _DBG_LVL_NOTICE, varParam) +#define _DBG_NOTICE(varParam...) op_log(NULL, _DBG_LVL_NOTICE, "NOTICE: "varParam) +#define _DBG_INFO(varParam...) op_log(NULL, _DBG_LVL_INFO, "INFO: "varParam) +#define _DBG_DEBUG(varParam...) op_log(NULL, _DBG_LVL_DEBUG, "DBG: "varParam) + +#define _DBG_FUNC_ENTRY +#define _DBG_FUNC_EXIT + +#endif + +#define _DBG_PTR(x) (x) + +#if defined(__cplusplus) +} + +#endif +#endif /* _DBG_DEBUG_H_ */ diff --git a/opasadb/lib/libopasadb.map b/opasadb/lib/libopasadb.map new file mode 100644 index 0000000..143d867 --- /dev/null +++ b/opasadb/lib/libopasadb.map @@ -0,0 +1,59 @@ +OPA_SA_DB_1.0.0 { + global: + op_path_find_hfi; + op_path_open; + op_path_close; + op_path_get_path_by_rec; + op_path_get_path_to_dgid; + op_path_find_pkey; + op_path_compute_timeout; + op_path_qp_attr; + op_path_check_version; + op_log_syslog; + op_log_set_level; + op_log; + op_log_set_file; + op_log_get_file; + op_route_open; + op_route_close; + op_route_create_job; + op_route_complete_job; + op_route_get_portguid_vec; + op_route_release_portguid_vec; + op_route_get_switch_map; + op_route_release_switch_map; + op_route_get_cost_matrix; + op_route_release_cost_matrix; + op_route_get_use_matrix; + op_route_set_use_matrix; + op_route_release_use_matrix; + op_route_get_job_list; + op_route_release_job_list; + op_route_poll_ready; + op_route_get_status_text; + op_route_dump; + op_route_init_param; + op_route_free_param; + op_route_alloc_param; + op_route_dump_param; + op_route_put_fvdebug; + op_ppath_create_writer; + op_ppath_initialize_ports; + op_ppath_initialize_subnets; + op_ppath_initialize_vfabrics; + op_ppath_add_subnet; + op_ppath_add_vfab; + op_ppath_add_sid; + op_ppath_add_port; + op_ppath_initialize_paths; + op_ppath_add_path; + op_ppath_publish; + op_ppath_close_writer; + op_ppath_create_reader; + op_ppath_find_path; + op_ppath_close_reader; + op_ppath_version; + local: *; +}; + + diff --git a/opasadb/lib/path/Makefile b/opasadb/lib/path/Makefile new file mode 100644 index 0000000..b891c0c --- /dev/null +++ b/opasadb/lib/path/Makefile @@ -0,0 +1,169 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** +# Makefile for opasadb/lib/route + +# Include Make Control Settings +include $(TL_DIR)/$(PROJ_FILE_DIR)/Makesettings.project + +#=============================================================================# +# Definitions: +#-----------------------------------------------------------------------------# + +# Name of SubProjects +DS_SUBPROJECTS = +# name of executable or downloadable image +EXECUTABLE = +# list of sub directories to build +DIRS = +# C files (.c) +CFILES = \ + opasadb_path.c \ + opasadb_path_private.c \ + opasadb_query_many.c \ + opasadb_static_db.c \ + # Add more c files here +# C++ files (.cpp) +CCFILES = \ + # Add more cpp files here +# lex files (.lex) +LFILES = \ + # Add more lex files here +# archive library files (basename, $ARFILES will add MOD_LIB_DIR/prefix and suffix) +LIBFILES = +# Windows Resource Files (.rc) +RSCFILES = +# Windows IDL File (.idl) +IDLFILE = +# Windows Linker Module Definitions (.def) file for dll's +DEFFILE = +# targets to build during INCLUDES phase (add public includes here) +INCLUDE_TARGETS = \ + opasadb.h \ + opasadb_path.h \ + opasadb_path_private.h \ + opasadb_static_db.h \ + # Add more h hpp files here +# Non-compiled files +MISC_FILES = +MISC_CONFIG_FILES = op_path_rec.conf +# all source files +SOURCES = $(CFILES) $(CCFILES) $(LFILES) $(RSCFILES) $(IDLFILE) +# Source files to include in DSP File +DSP_SOURCES = $(INCLUDE_TARGETS) $(SOURCES) $(MISC_FILES) \ + $(RSCFILES) $(DEFFILE) $(MAKEFILE) +# all object files +OBJECTS = $(CFILES:.c=$(OBJ_SUFFIX)) $(CCFILES:.cpp=$(OBJ_SUFFIX)) \ + $(LFILES:.lex=$(OBJ_SUFFIX)) \ + # Add more object files here +RSCOBJECTS = $(RSCFILES:.rc=$(RES_SUFFIX)) +# targets to build during LIBS phase +LIB_TARGETS_IMPLIB = +LIB_TARGETS_ARLIB = +LIB_TARGETS_EXP = $(LIB_TARGETS_IMPLIB:$(ARLIB_SUFFIX)=$(EXP_SUFFIX)) +LIB_TARGETS_MISC = +# targets to build during CMDS phase +#SHLIB_VERSION = +#CMD_TARGETS_SHLIB = +CMD_TARGETS_EXE = $(EXECUTABLE) +CMD_TARGETS_MISC = +# files to remove during clean phase +CLEAN_TARGETS_MISC = +CLEAN_TARGETS = $(OBJECTS) $(RSCOBJECTS) $(IDL_TARGETS) $(CLEAN_TARGETS_MISC) +# other files to remove during clobber phase +CLOBBER_TARGETS_MISC= op_path_rec.conf +# sub-directory to install to within bin +BIN_SUBDIR = +# sub-directory to install to within include +INCLUDE_SUBDIR = + +# Additional Settings +#CLOCALDEBUG = User defined C debugging compilation flags [Empty] +#CCLOCALDEBUG = User defined C++ debugging compilation flags [Empty] +# User defined C flags for compiling +# User defined C++ flags for compiling +#CCLOCAL = +#BSCLOCAL = User flags for Browse File Builder [Empty] +#DEPENDLOCAL = user defined makedepend flags [Empty] +#LINTLOCAL = User defined lint flags [Empty] +# User include directories to search for C/C++ headers +LOCAL_INCLUDE_DIRS = +#LDLOCAL = User defined C flags for linking [Empty] +#IMPLIBLOCAL = User flags for Object Lirary Manager [Empty] +#MIDLLOCAL = User flags for IDL compiler [Empty] +#RSCLOCAL = User flags for resource compiler [Empty] +# User libraries to include in dependencies +LOCALDEPLIBS = +# User libraries to use when linking (in addition to LOCALDEPLIBS) +#LOCALLIBS = $(OPENIB_USER_LIBS) $(IBACCESS_USER_LIBS) +LOCALLIBS = +# User library directories for libpaths +#LOCAL_LIB_DIRS = $(OPENIB_USER_LIB_DIRS) $(IBACCESS_USER_LIB_DIRS) +LOCAL_LIB_DIRS = + +# Include Make Rules definitions and rules +include $(TL_DIR)/IbaTools/Makerules.module + +#=============================================================================# +# Overrides: +#-----------------------------------------------------------------------------# +# C++ optimization flags, default lets build config decide +#CCOPT = +# C optimization flags, default lets build config decide +#SUBSYSTEM = Subsystem to build for (none, console or windows) [none] +# (Windows Only) +#USEMFC = How Windows MFC should be used (none, static, shared, no_mfc) [none] +# (Windows Only) +#=============================================================================# + +#=============================================================================# +# Rules: +#-----------------------------------------------------------------------------# +# process Sub-directories +include $(TL_DIR)/Makerules/Maketargets.toplevel + +# build cmds and libs +include $(TL_DIR)/Makerules/Maketargets.build + +# install for includes, libs and cmds phases +include $(TL_DIR)/Makerules/Maketargets.install + +# install for stage phase +include $(TL_DIR)/Makerules/Maketargets.stage +STAGE:: + $(VS)$(STAGE_INSTALL) $(STAGE_INSTALL_DIR_OPT) $(PROJ_STAGE_OPA_SA_DB_DIR) $(INCLUDE_TARGETS) + $(VS)$(STAGE_INSTALL) $(STAGE_INSTALL_DIR_OPT) $(PROJ_STAGE_DIR)/config $(MISC_CONFIG_FILES) $(MISC_FILES) + +# Unit test execution +#include $(TL_DIR)/Makerules/Maketargets.runtest + +#=============================================================================# + +#=============================================================================# +# DO NOT DELETE THIS LINE -- make depend depends on it. +#=============================================================================# diff --git a/opasadb/lib/path/op_path_rec.conf b/opasadb/lib/path/op_path_rec.conf new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/opasadb/lib/path/op_path_rec.conf diff --git a/opasadb/lib/path/opasadb.h b/opasadb/lib/path/opasadb.h new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/opasadb/lib/path/opasadb.h diff --git a/opasadb/lib/path/opasadb_path.c b/opasadb/lib/path/opasadb_path.c new file mode 100644 index 0000000..d5341bf --- /dev/null +++ b/opasadb/lib/path/opasadb_path.c @@ -0,0 +1,563 @@ +/* BEGIN_ICS_COPYRIGHT2 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT2 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "opasadb_debug.h" +#include "opasadb_path.h" + +/* + * IbAccess headers don't play well with OFED headers, and OFED doesn't + * export the path mask. I have to duplicate these defines here. + */ +#define IB_PATH_RECORD_COMP_SERVICEID 0x00000003 +#define IB_PATH_RECORD_COMP_DGID 0x00000004 +#define IB_PATH_RECORD_COMP_SGID 0x00000008 +#define IB_PATH_RECORD_COMP_DLID 0x00000010 +#define IB_PATH_RECORD_COMP_SLID 0x00000020 +#define IB_PATH_RECORD_COMP_RAWTRAFFIC 0x00000040 + /* reserved field 0x00000080 */ +#define IB_PATH_RECORD_COMP_FLOWLABEL 0x00000100 +#define IB_PATH_RECORD_COMP_HOPLIMIT 0x00000200 +#define IB_PATH_RECORD_COMP_TCLASS 0x00000400 +#define IB_PATH_RECORD_COMP_REVERSIBLE 0x00000800 +#define IB_PATH_RECORD_COMP_NUMBPATH 0x00001000 +#define IB_PATH_RECORD_COMP_PKEY 0x00002000 +#define IB_PATH_RECORD_COMP_QOS_CLASS 0x00004000 +#define IB_PATH_RECORD_COMP_SL 0x00008000 +#define IB_PATH_RECORD_COMP_MTUSELECTOR 0x00010000 +#define IB_PATH_RECORD_COMP_MTU 0x00020000 +#define IB_PATH_RECORD_COMP_RATESELECTOR 0x00040000 +#define IB_PATH_RECORD_COMP_RATE 0x00080000 +#define IB_PATH_RECORD_COMP_PKTLIFESELECTOR 0x00100000 +#define IB_PATH_RECORD_COMP_PKTLIFE 0x00200000 +#define IB_PATH_RECORD_COMP_PREFERENCE 0x00400000 + /* reserved field 0x00800000 */ +#define IB_PATH_RECORD_COMP_ALL 0x007fff7f + +/* + * IbAccess headers don't play well with OFED headers. Because of this, + * I have to put modified prototypes here. + */ +int op_ppath_find_path(void *reader, + const char *hfi_name, + __u16 port, + __u64 mask, + op_path_rec_t *query, + op_path_rec_t *result); + +void op_ppath_close_reader(void *r); +void *op_ppath_allocate_reader(void); +int op_ppath_create_reader(void *reader); + +struct op_path_context { + void *reader; + + struct ibv_context *ibv_context; + struct ibv_device_attr device_attr; + struct ibv_port_attr port_attr; + + __u16 port_num; + __u16 *pkey_table; +}; + +static uint64_t build_comp_mask(op_path_rec_t path) +{ + uint64_t mask = 0; + + if (path.service_id) + mask |= IB_PATH_RECORD_COMP_SERVICEID; + + if (path.dgid.unicast.interface_id | path.dgid.unicast.prefix) + mask |= IB_PATH_RECORD_COMP_DGID; + if (path.sgid.unicast.interface_id | path.sgid.unicast.prefix) + mask |= IB_PATH_RECORD_COMP_SGID; + if (path.dlid) + mask |= IB_PATH_RECORD_COMP_DLID; + if (path.slid) + mask |= IB_PATH_RECORD_COMP_SLID; + if (ntohl(path.hop_flow_raw) & 0x80000000) + mask |= IB_PATH_RECORD_COMP_RAWTRAFFIC; + if (ntohl(path.hop_flow_raw) & 0x0FFFFF00) + mask |= IB_PATH_RECORD_COMP_FLOWLABEL; + if (ntohl(path.hop_flow_raw) & 0x000000FF) + mask |= IB_PATH_RECORD_COMP_HOPLIMIT; + if (path.tclass) + mask |= IB_PATH_RECORD_COMP_TCLASS; + if (path.num_path & 0xFF) mask |= IB_PATH_RECORD_COMP_REVERSIBLE; + if (path.num_path & 0x7F) mask |= IB_PATH_RECORD_COMP_NUMBPATH; + if (path.pkey) mask |= IB_PATH_RECORD_COMP_PKEY; + if (ntohs(path.qos_class_sl) & 0x0FFF) + mask |= IB_PATH_RECORD_COMP_QOS_CLASS; + if (ntohs(path.qos_class_sl) & 0xF000) + mask |= IB_PATH_RECORD_COMP_SL; + if (path.mtu & 0xC0) + mask |= IB_PATH_RECORD_COMP_MTUSELECTOR; + if (path.mtu & 0x3F) + mask |= IB_PATH_RECORD_COMP_MTU; + if (path.rate & 0xC0) + mask |= IB_PATH_RECORD_COMP_RATESELECTOR; + if (path.rate & 0x3F) + mask |= IB_PATH_RECORD_COMP_RATE; + if (path.pkt_life & 0xC0) + mask |= IB_PATH_RECORD_COMP_PKTLIFESELECTOR; + if (path.pkt_life & 0x3F) + mask |= IB_PATH_RECORD_COMP_PKTLIFE; + if (path.preference) + mask |= IB_PATH_RECORD_COMP_PREFERENCE; + + return mask; +}; + +static struct ibv_device **dev_list = NULL; +static int num_devices = 0; + +/* + * Convenience function. Given the name of an HFI, + * returns the ibv_device structure associated with it. + * Returns NULL if the HFI could not be found. + * + * HFI can be identified by name ("mthfi0") or by number + * "1", "2", et cetera. + * + * OPENS THE HFI! Use ibv_close_device() to release it. + */ +struct ibv_context * +op_path_find_hfi(const char *name, + struct ibv_device **device) +{ + struct ibv_device *ibv_dev = NULL; + struct ibv_context *context = NULL; + int i; + + if (!dev_list) { + dev_list = ibv_get_device_list(&num_devices); + } + if (!dev_list) { + errno = EFAULT; + return NULL; + } + if (name == NULL || name[0]=='\0') { + i=0; + } else if (isdigit(name[0])) { + i = strtoul(name,NULL,0) - 1; + if (i < 0 || i >= num_devices){ + errno = EFAULT; + return NULL; + } + } else { + for (i=0; i < num_devices; i++) { + if (!strcmp(ibv_get_device_name(dev_list[i]), name)) + break; + } + if (i >= num_devices) { + errno = EFAULT; + return NULL; + } + } + ibv_dev = dev_list[i]; + + /* + * Opens the verbs interface to the HFI. + * Note that this will increment the usage counter for that + * HFI. This needs to be done before we release the device list. + */ + if(ibv_dev) { + context = ibv_open_device(ibv_dev); + if (!context) { + errno = EFAULT; + *device = NULL; + } else { + *device = ibv_dev; + } + } else { + *device = NULL; + errno = ENODEV; + } + + return context; +} + +/* + * Opens the interface to the opp module. + * Must be called before any use of the path functions. + * + * device The verbs context for the HFI. + * Can be acquired via op_path_find_hfi. + * + * port_num The port to use for sending queries. + * + * This information is used for querying pkeys and + * calculating timeouts. + * + * Returns a pointer to the op_path context on success, or returns NULL + * and sets errno if the device could not be opened. + */ +void * +op_path_open(struct ibv_device *device, int p) +{ + int i, err; + struct op_path_context *context; + + + if (!device) { + errno=ENXIO; + return NULL; + } + + context = malloc(sizeof(struct op_path_context)); + if (!context) { + errno=ENOMEM; + return NULL; + } + memset(context,0,sizeof(struct op_path_context)); + + context->ibv_context = ibv_open_device(device); + if (!context->ibv_context) { + errno=ENODEV; + goto open_device_failed; + } + + context->port_num = p; + + context->reader = op_ppath_allocate_reader(); + if (!context->reader) { + errno=ENOMEM; + goto alloc_reader_failed; + } + + err = op_ppath_create_reader(context->reader); + if (err) { + errno=err; + goto create_reader_failed; + } + + if ((err=ibv_query_device(context->ibv_context, + &(context->device_attr)))) { + errno=EFAULT; + goto query_attr_failed; + } + + if ((err=ibv_query_port(context->ibv_context, + context->port_num, + &(context->port_attr)))) { + errno=EFAULT; + goto query_attr_failed; + } + + context->pkey_table = malloc(context->device_attr.max_pkeys* sizeof(int)); + if (!context->pkey_table) { + errno= ENOMEM; + goto query_attr_failed; + } + memset(context->pkey_table,0,context->device_attr.max_pkeys* sizeof(int)); + + for (i = 0, err = 0; !err && idevice_attr.max_pkeys; i++) { + err = ibv_query_pkey(context->ibv_context, context->port_num, i, + &(context->pkey_table[i])); + if (err) { + errno=EFAULT; + goto query_pkey_failed; + } + } + + return context; + +query_pkey_failed: + free(context->pkey_table); +query_attr_failed: + op_ppath_close_reader(context->reader); +create_reader_failed: + free(context->reader); +alloc_reader_failed: + ibv_close_device(context->ibv_context); +open_device_failed: + free(context); + return NULL; +} + +/* + * Closes the interface to the opp module. + * No path functions will work after calling this function. + */ +void +op_path_close(void *uc) +{ + struct op_path_context *context = (struct op_path_context *)uc; + + + op_ppath_close_reader(context->reader); + + /* + * Close the HFI and release the memory being used. + */ + ibv_close_device(context->ibv_context); + + /* + * Releases the memory used by the list - and decrements the usage + * counters on the HFIs. Note that this is important; all the HFIs + * in the device list are flagged as being used from the time + * the list is acquired until it is freed. + */ + if (dev_list) { + ibv_free_device_list(dev_list); + dev_list = NULL; + num_devices = 0; + } + + free(context); +} + +/* + * Retrieves an IB Path Record given a particular query. + * + * context Pointer to the HFI and port to query on. + * + * query The path record to use for asking the query. + * All fields should be zero'ed out except for + * those being used to query! For example, + * a simple query might specify the source lid, + * the destination lid and a pkey. All fields should + * be in network byte order. + * + * response The path record where the completed path will + * be written. All fields are in network byte order. + * + * RETURN VAL: This function will return a 0 on success, + * or non-zero on error. + */ +int +op_path_get_path_by_rec(void *uc, + op_path_rec_t *query, + op_path_rec_t *response) +{ + uint64_t mask = build_comp_mask(*query); + struct op_path_context *context = (struct op_path_context *)uc; + + return op_ppath_find_path(context->reader, + ibv_get_device_name(context->ibv_context->device), + context->port_num, + mask, + query, + response); +} + +/* + * Retrieves an IB Path Record to a given destination. + * + * op_path_context A handle to the interface to query over. + * + * hfi_context A handle to the HFI that will be used for + * this path. + * + * port The local port number that will be used + * for this path. (not the lid.) + * + * dgid The destination GID. + * + * pkey The desired pkey. This should be zero to + * accept the default. + * + * response The path record where the completed path will + * be written. All fields are in network byte order. + * + * RETURN VAL: This function will return a value of 0 on success, + * or non-zero on error. + */ +int +op_path_get_path_to_dgid(void *uc, + uint16_t pkey, + union ibv_gid dgid, + op_path_rec_t *response) +{ + + op_path_rec_t query; + struct op_path_context *context = (struct op_path_context *)uc; + + memset(&query,0,sizeof(query)); + + query.dgid.unicast.prefix = dgid.global.subnet_prefix; + query.dgid.unicast.interface_id = dgid.global.interface_id; + query.pkey = pkey; + query.slid = ntohs(context->port_attr.lid); + + return op_path_get_path_by_rec(uc,&query,response); +} + + +/* + * Converts a pkey to a pkey index, which is needed by the queue pairs. + * Returns 0 on succes, non zero on error. + */ +int op_path_find_pkey(void *uc, uint16_t pkey, uint16_t *pkey_index) +{ + int i; + struct op_path_context *context = (struct op_path_context *)uc; + + for (i = 0; i< context->device_attr.max_pkeys; i++) { + if (pkey == context->pkey_table[i]) { + *pkey_index = (uint16_t) i; + return 0; + } + } + + return EINVAL; +} + +/* + * Given an HFI and a path record's packet lifetime attribute, + * compute the packet lifetime for a queue pair. + */ +uint8_t op_path_compute_timeout(struct ibv_context *hfi_context, + uint8_t pkt_life) +{ + uint8_t result; + struct ibv_device_attr device_attr; + + pkt_life &= 0x1f; + + if (ibv_query_device(hfi_context, &device_attr)) + return 0; + + /* Adding 1 has the effect of doubling the timeout. */ + /* We do this because we're looking for a round-trip figure. */ + result = pkt_life + 1; + + /* If the HFI's local delay is larger than the time out so far, */ + /* replace the result with the local delay, doubled. */ + if (pkt_life < device_attr.local_ca_ack_delay) { + result = device_attr.local_ca_ack_delay + 1; + } else { + /* The local delay is smaller than the packet life time, */ + /* so we'll simply double the timeout value again. */ + result += 1; + } + + if (result > 0x1f) result = 0x1f; + + return result; +} + +/* + * Fills out a qp_attr structure and its mask based on the contents + * of a path record and an optional alternate path. + * + * alt_path can be null. In that case, no alternate path will be + * set. + * + * Returns a mask listing the attributes that have been set. Returns 0 + * on error and sets errno. + */ +unsigned op_path_qp_attr(struct ibv_qp_attr *qp_attr, + void *uc, + op_path_rec_t *primary_path, + void *alt_uc, + op_path_rec_t *alt_path) + +{ + struct op_path_context *context = uc; + uint16_t pkey_index = 0; + + struct op_path_context *alt_context = alt_uc; + uint16_t alt_pkey_index = 0; + + unsigned mask = 0; + struct ibv_ah_attr *ah_attr = &qp_attr->ah_attr; + + if (op_path_find_pkey(context,primary_path->pkey, &pkey_index)) { + errno = EINVAL; + return 0; + } + + qp_attr->path_mtu = OP_PATH_REC_MTU(primary_path); + mask |= IBV_QP_PATH_MTU; + qp_attr->pkey_index = pkey_index; + mask |= IBV_QP_PKEY_INDEX; + + ah_attr->dlid = ntohs(primary_path->dlid); + ah_attr->sl = OP_PATH_REC_SL(primary_path); + ah_attr->src_path_bits = ntohs(primary_path->slid) & ((1<port_attr.lmc) - 1); + ah_attr->static_rate = primary_path->rate & 0x3f; + ah_attr->port_num = context->port_num; + ah_attr->is_global = (OP_PATH_REC_HOP_LIMIT(primary_path)>0)?1:0; + if (ah_attr->is_global) { + ah_attr->grh.dgid.global.subnet_prefix = primary_path->dgid.unicast.prefix; + ah_attr->grh.dgid.global.interface_id = primary_path->dgid.unicast.interface_id; + ah_attr->grh.flow_label = OP_PATH_REC_FLOW_LBL(primary_path); + ah_attr->grh.sgid_index = 0; // BUGBUG - One day this will be wrong. + ah_attr->grh.hop_limit = OP_PATH_REC_HOP_LIMIT(primary_path); + ah_attr->grh.traffic_class = primary_path->tclass; + } + mask |= IBV_QP_AV; + + if (alt_path && alt_context) { + struct ibv_ah_attr *alt_ah_attr = &qp_attr->alt_ah_attr; + + if (op_path_find_pkey(alt_context,alt_path->pkey, &alt_pkey_index)) + return 0; + + qp_attr->path_mig_state = IBV_MIG_ARMED; + mask |= IBV_QP_PATH_MIG_STATE; + qp_attr->alt_pkey_index = alt_pkey_index; + mask |= IBV_QP_ALT_PATH; + + alt_ah_attr->dlid = ntohs(alt_path->dlid); + alt_ah_attr->sl = OP_PATH_REC_SL(alt_path); + alt_ah_attr->src_path_bits = ntohs(alt_path->slid) & ((1<port_attr.lmc) - 1); + alt_ah_attr->static_rate = alt_path->rate & 0x3f; + alt_ah_attr->port_num = alt_context->port_num; + alt_ah_attr->is_global = (OP_PATH_REC_HOP_LIMIT(alt_path)>0)?1:0; + if (alt_ah_attr->is_global) { + alt_ah_attr->grh.dgid.global.subnet_prefix = alt_path->dgid.unicast.prefix; + alt_ah_attr->grh.dgid.global.interface_id = alt_path->dgid.unicast.interface_id; + alt_ah_attr->grh.flow_label = OP_PATH_REC_FLOW_LBL(alt_path); + alt_ah_attr->grh.sgid_index = 0; // BUGBUG - One day this will be wrong. + alt_ah_attr->grh.hop_limit = OP_PATH_REC_HOP_LIMIT(alt_path); + alt_ah_attr->grh.traffic_class = alt_path->tclass; + } + } + + return mask; +} + +unsigned op_path_check_version(void) +{ + return OPA_SA_DB_PATH_API_VERSION; +} diff --git a/opasadb/lib/path/opasadb_path.h b/opasadb/lib/path/opasadb_path.h new file mode 100644 index 0000000..f1a0f0f --- /dev/null +++ b/opasadb/lib/path/opasadb_path.h @@ -0,0 +1,379 @@ +/* BEGIN_ICS_COPYRIGHT2 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT2 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +#if !defined(_OPA_SA_DB_PATH_H) + +#define _OPA_SA_DB_PATH_H + +#include +#include +#include + +#define OPA_SA_DB_PATH_API_VERSION 3 + +/* + * Definitions for various bit fields used in the path record. + */ +#define OP_PATH_REC_SL_MASK 0x000F +#define OP_PATH_REC_QOS_CLASS_MASK 0xFFF0 +#define OP_PATH_REC_SELECTOR_MASK 0xC0 +#define OP_PATH_REC_BASE_MASK 0x3F +#define OP_PATH_RECORD_RATE_2_5_GBS 2 +#define OP_PATH_RECORD_RATE_10_GBS 3 +#define OP_PATH_RECORD_RATE_30_GBS 4 +#define OP_PATH_RECORD_RATE_5_GBS 5 +#define OP_PATH_RECORD_RATE_20_GBS 6 +#define OP_PATH_RECORD_RATE_40_GBS 7 +#define OP_PATH_RECORD_RATE_60_GBS 8 +#define OP_PATH_RECORD_RATE_80_GBS 9 +#define OP_PATH_RECORD_RATE_120_GBS 10 +#define OP_MIN_RATE OP_PATH_RECORD_RATE_2_5_GBS +#define OP_MAX_RATE OP_PATH_RECORD_RATE_120_GBS + +#define OP_PATH_REC_MTU(p_rec) ((uint8_t) (p_rec->mtu & OP_PATH_REC_BASE_MASK)) +#define OP_PATH_REC_SL(p_rec) ((uint8_t)(ntohs(p_rec->qos_class_sl) & OP_PATH_REC_SL_MASK)) +#define OP_PATH_REC_HOP_LIMIT(p_rec) ((uint8_t) (ntohl(p_rec->hop_flow_raw) & 0x000000FF)) +#define OP_PATH_REC_FLOW_LBL(p_rec) (((ntohl(p_rec->hop_flow_raw) >> 8) & 0x000FFFFF)) +#define OP_PATH_REC_NUM_PATH(p_rec) (p_rec->num_path & 0x7F) +#define OP_PATH_REC_QOS_CLASS(p_rec) (htons(p_rec->qos_class_sl) >> 4) +#define OP_PATH_REC_RATE(p_rec) ((uint8_t) (p_rec->rate & OP_PATH_REC_BASE_MASK)) +#define OP_PATH_REC_PKT_LIFE(p_rec) ((uint8_t) (p_rec->pkt_life & OP_PATH_REC_BASE_MASK)) + +#ifndef ntoh64 + #define ntoh64( x ) ( (((x) & 0x00000000000000FF) << 56) | \ + (((x) & 0x000000000000FF00) << 40) | \ + (((x) & 0x0000000000FF0000) << 24) | \ + (((x) & 0x00000000FF000000) << 8 ) | \ + (((x) & 0x000000FF00000000) >> 8 ) | \ + (((x) & 0x0000FF0000000000) >> 24) | \ + (((x) & 0x00FF000000000000) >> 40) | \ + (((x) & 0xFF00000000000000) >> 56) ) + #define hton64 ntoh64 +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/* Definition for a gid which is always maintained in network order (NO) */ +typedef union _IB_GID_NO { + uint8_t Raw[16]; + union _IB_GID_TYPE_NO { + struct { + uint64_t SubnetPrefix; + uint64_t InterfaceID; + } Global; + } Type; +} __attribute__((packed)) IB_GID_NO; + +/* Definition for a pathrecord which is always maintained in network order (NO) */ +typedef struct _IB_PATH_RECORD_NO { + uint64_t ServiceID; + IB_GID_NO DGID; /* Destination GID */ + IB_GID_NO SGID; /* Source GID */ + uint16_t DLID; /* Destination LID */ + uint16_t SLID; /* Source LID */ + + /* DO NOT ACCESS THESE FIELDS DIRECTLY ON LE SYSTEMS */ + union _u1 { + uint32_t AsReg32; + struct { +#if CPU_BE + uint32_t RawTraffic :1; /* 0 for IB Packet (P_Key must be valid) */ + /* 1 for Raw Packet (No P_Key) */ + uint32_t Reserved :3; + uint32_t FlowLabel :20;/* used in GRH */ + uint32_t HopLimit :8; /* Hop limit used in GRH */ +#else + uint32_t HopLimit :8; /* Hop limit used in GRH */ + uint32_t FlowLabel :20;/* used in GRH */ + uint32_t Reserved :3; + uint32_t RawTraffic :1; /* 0 for IB Packet (P_Key must be valid) */ + /* 1 for Raw Packet (No P_Key) */ +#endif + } __attribute__((packed)) s; + } u1; + + uint8_t TClass; /* Traffic Class used in GRH */ +#if CPU_BE + uint8_t Reversible :1; + uint8_t NumbPath :7; /* Max number of paths to (be) return(ed) */ +#else /* CPU_BE */ + uint8_t NumbPath :7; /* Max number of paths to (be) return(ed) */ + uint8_t Reversible :1; +#endif /* CPU_BE */ + uint16_t P_Key; /* Partition Key for this path */ + + /* DO NOT ACCESS THESE FIELDS DIRECTLY ON LE SYSTEMS */ + union _u2 { + uint16_t AsReg16; + struct { +#if CPU_BE + uint16_t QosType : 2; + uint16_t Reserved2 : 2; + uint16_t QosPriority : 8; + uint16_t SL : 4; +#else + uint16_t SL : 4; + uint16_t QosPriority : 8; + uint16_t Reserved2 : 2; + uint16_t QosType : 2; +#endif + } __attribute__((packed)) s; + } u2; + +#if CPU_BE + uint8_t MtuSelector :2; /* enum IB_SELECTOR */ + uint8_t Mtu :6; /* enum IB_MTU */ +#else + uint8_t Mtu :6; /* enum IB_MTU */ + uint8_t MtuSelector :2; /* enum IB_SELECTOR */ +#endif + +#if CPU_BE + uint8_t RateSelector:2; /* enum IB_SELECTOR */ + uint8_t Rate :6; /* enum IB_STATIC_RATE */ +#else + uint8_t Rate :6; /* enum IB_STATIC_RATE */ + uint8_t RateSelector:2; /* enum IB_SELECTOR */ +#endif + + /* ***************************************** */ + /* *** User be aware that the CM LifeTime & */ + /* *** TimeOut values are only 5-bit wide. */ + /* ***************************************** */ + /* */ + /* Accumulated packet life time for the path specified by an enumeration */ + /* deried from 4.096 usec * 2^PktLifeTime */ +#if CPU_BE + uint8_t PktLifeTimeSelector:2; /* enum IB_SELECTOR */ + uint8_t PktLifeTime :6; +#else + uint8_t PktLifeTime :6; + uint8_t PktLifeTimeSelector:2; /* enum IB_SELECTOR */ +#endif + + uint8_t Preference; /* 1.1 specific. see page 800 of volume 1 */ + uint8_t Reserved2 [6]; +} __attribute__((packed)) IB_PATH_RECORD_NO; + +#if CPU_BE +#define RAW_TRAFFIC(x) x.s.RawTraffic +#define FLOW_LABEL(x) x.s.FlowLabel +#define HOP_LIMIT(x) x.s.HopLimit + +#define QOS_TYPE(x) x.s.QosType +#define QOS_PRIORITY(x) x.s.QosPriority +#define SL(x) x.s.SL +#else +#define RAW_TRAFFIC(x) (((union _u1)(ntohl(x.AsReg32))).s.RawTraffic) +#define FLOW_LABEL(x) (htons(((union _u1)(ntohl(x.AsReg32))).s.FlowLabel)) +#define HOP_LIMIT(x) (((union _u1)(ntohl(x.AsReg32))).s.HopLimit) + +#define QOS_TYPE(x) (((union _u2)(ntohs(x.AsReg16))).s.QosType) +#define QOS_PRIORITY(x) (((union _u2)(ntohs(x.AsReg16))).s.QosPriority) +#define SL(x) (((union _u2)(ntohs(x.AsReg16))).s.SL) +#endif + +/* + * There's no "standard" place to define path records in OPENIB/OFED + * so we do it here. + * + * All fields are assumed to be in network byte order. + */ +typedef union _op_gid { + uint8_t raw[16]; + struct _op_gid_unicast { + uint64_t prefix; + uint64_t interface_id; + + } __attribute__((packed)) unicast; + + struct _op_gid_multicast { + uint8_t header[2]; + uint8_t raw_group_id[14]; + + } __attribute__((packed)) multicast; + +} __attribute__((packed)) op_gid_t; + +typedef struct _op_path_rec { + uint64_t service_id; + op_gid_t dgid; + op_gid_t sgid; + uint16_t dlid; + uint16_t slid; + uint32_t hop_flow_raw; + uint8_t tclass; + uint8_t num_path; + uint16_t pkey; + uint16_t qos_class_sl; + uint8_t mtu; + uint8_t rate; + uint8_t pkt_life; + uint8_t preference; + uint8_t resv2[6]; + +} __attribute__((packed)) op_path_rec_t; + +/* + * Convenience function. Given the name of an HFI, + * returns the ibv_device structure associated with it. + * Returns NULL if the HFI could not be found. + * + * OPENS THE HFI! Use ibv_close_device() to release it. + * + * Input: + * name: the name of the HFI, or NULL. + * + * Output: + * Returns a pointer to the opened HFI. Use ibv_close_device() to free it. + * device: will contain a pointer to the info structure for the device. + * DO NOT FREE THIS - it will be freed when op_path_close() is called. + * + * Sets errno on failure. + */ +struct ibv_context *op_path_find_hfi(const char *name, + struct ibv_device **device); + +/* + * Opens the interface to the opp module. + * Must be called before any use of the path functions. + * + * device The verbs context for the HFI. + * Can be acquired via op_path_find_hfi. + * + * port_num The port to use for sending queries. + * + * This information is used for querying pkeys and + * calculating timeouts. + * + * Returns a pointer to the USA context on success, or returns NULL + * and sets errno if the device could not be opened. + */ +void *op_path_open(struct ibv_device *device, int port_num); + +/* + * Closes the interface to the opp module. + * No path functions will work after calling this function. + */ +void op_path_close(void *context); + +/* + * Retrieves an IB Path Record given a particular query. + * + * context A handle to the interface to query over. + * + * query The path record to use for asking the query. + * All fields should be zero'ed out except for + * those being used to query! For example, + * a simple query might specify the source lid, + * the destination lid and a pkey. All fields should + * be in network byte order. + * + * response The path record where the completed path will + * be written. All fields are in network byte order. + * + * RETURN VAL: This function will return a value of 0 on success, + * or non-zero on error. + */ +int op_path_get_path_by_rec(void *context, + op_path_rec_t *query, + op_path_rec_t *response); + +/* + * Retrieves an IB Path Record to a given destination. + * + * op_path_context A handle to the interface to query over. + * + * hfi_context A handle to the HFI that will be used for + * this path. + * + * port The local port number that will be used + * for this path. (not the lid.) + * + * dgid The destination GID. + * + * pkey The desired pkey. This should be zero to + * accept the default. + * + * response The path record where the completed path will + * be written. All fields are in network byte order. + * + * RETURN VAL: This function will return a value of 0 on success, + * or non-zero on error. + */ +int op_path_get_path_to_dgid(void *op_path_context, + uint16_t pkey, + union ibv_gid dgid, + op_path_rec_t *response); + +/* + * Converts a pkey to a pkey index, which is needed by the queue pairs. + * + * Returns 0 on success, non-zero on error. + */ +int op_path_find_pkey(void *op_path_context, uint16_t pkey, uint16_t *pkey_index); + +/* + * Given an HFI and the packet life time from a path record, compute the packet lifetime + * for a queue pair. + */ +uint8_t op_path_compute_timeout(struct ibv_context *hfi_context, + uint8_t pkt_life); + +/* + * Fills out a qp_attr structure and its mask based on the contents + * of a path record and an optional alternate path. + * + * alt_path and alt_context can be null. In that case, no alternate path + * will be set. + * + * Returns a mask listing the attributes that have been set. Returns 0 + * on error and sets errno. + */ +unsigned op_path_qp_attr(struct ibv_qp_attr *qp_attr, + void *context, + op_path_rec_t *primary_path, + void *alt_context, + op_path_rec_t *alt_path); + +/* + * Returns the API version the path functions. + */ +unsigned op_path_check_version(void); + + +#ifdef __cplusplus +}; +#endif + +#endif /* _OPA_SA_DB_PATH_H */ diff --git a/opasadb/lib/path/opasadb_path_private.c b/opasadb/lib/path/opasadb_path_private.c new file mode 100644 index 0000000..a69d093 --- /dev/null +++ b/opasadb/lib/path/opasadb_path_private.c @@ -0,0 +1,1388 @@ +/* BEGIN_ICS_COPYRIGHT2 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT2 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ +#include +#include +#include +#include +#include +#include + + +#include +#include +#include +#include +#include +#include "opasadb_path_private.h" + +// 0 is a "reserved value" for the update counters. +#define BUMP_COUNT(x) { (x)++; if ((x)==0) (x)=1; } + +/* + * Fastest way to process LMC.. + */ +uint16_t lmc_mask[] = { + 0xffff, // LMC of zero + 0xfffe, // LMC of one + 0xfffc, // LMC of two + 0xfff8, // LMC of three. + 0xfff0, // LMC of four. + 0xffe0, // LMC of five. + 0xffc0, // LMC of six. + 0xff80, // LMC of seven. +}; + +void * +op_ppath_allocate_reader(void) +{ + void *p = malloc(sizeof(op_ppath_reader_t)); + return p; +} + +void * +op_ppath_allocate_writer(void) +{ + void *p = malloc(sizeof(op_ppath_writer_t)); + return p; +} + +static uint32 +gid_hash(IB_GID_NO *gid) +{ + uint32 hash=0; + int i; + + for (i=0; i<16;i++) { + hash += gid->Raw[i]; + } + + return hash & HASH_TABLE_MASK; +} + +#define GID_HASH(g) (gid_hash(g)) +#define LID_HASH(i) ((ntohs((uint32)(i)) & HASH_TABLE_MASK)) + +static void +close_and_unlink_tables(op_ppath_reader_t *r) +{ + char port_table_name[SHM_NAME_LENGTH]; + char subnet_table_name[SHM_NAME_LENGTH]; + char vfab_table_name[SHM_NAME_LENGTH]; + char path_table_name[SHM_NAME_LENGTH]; + + _DBG_FUNC_ENTRY; + /* The call to op_ppath_close_reader() will unmapped the shared table + and therefore we can't refer to it anymore. Copy the table names + here for unlinking */ + strncpy(port_table_name, r->shared_table->port_table_name, SHM_NAME_LENGTH -1); + port_table_name[SHM_NAME_LENGTH - 1] = '\0'; + strncpy(subnet_table_name, r->shared_table->subnet_table_name, SHM_NAME_LENGTH -1); + subnet_table_name[SHM_NAME_LENGTH - 1] = '\0'; + strncpy(vfab_table_name, r->shared_table->vfab_table_name, SHM_NAME_LENGTH -1); + vfab_table_name[SHM_NAME_LENGTH - 1] = '\0'; + strncpy(path_table_name, r->shared_table->path_table_name, SHM_NAME_LENGTH -1); + path_table_name[SHM_NAME_LENGTH - 1] = '\0'; + + op_ppath_close_reader(r); + + /* Finally, unlink the tables */ + if (strlen(port_table_name)) + shm_unlink(port_table_name); + if (strlen(subnet_table_name)) + shm_unlink(subnet_table_name); + if (strlen(vfab_table_name)) + shm_unlink(vfab_table_name); + if (strlen(path_table_name)) + shm_unlink(path_table_name); + + _DBG_FUNC_EXIT; +} + +void +op_ppath_close_reader(op_ppath_reader_t *r) +{ + _DBG_FUNC_ENTRY; + + if (r->path_table && r->path_table != MAP_FAILED) { + munmap(r->path_table,r->path_table->size); + r->path_table=NULL; + } + if (r->port_table && r->port_table != MAP_FAILED) { + munmap(r->port_table,r->port_table->size); + r->port_table=NULL; + } + if (r->vfab_table && r->vfab_table != MAP_FAILED) { + munmap(r->vfab_table,r->vfab_table->size); + r->vfab_table=NULL; + } + if (r->subnet_table && r->subnet_table != MAP_FAILED) { + munmap(r->subnet_table, + r->subnet_table->subnet_size + + r->subnet_table->sid_size); + r->subnet_table=NULL; + } + + if (r->path_fd>0) { close(r->path_fd); r->path_fd=0; } + if (r->port_fd>0) { close(r->port_fd); r->port_fd=0; } + if (r->subnet_fd>0) { close(r->subnet_fd); r->subnet_fd=0; } + if (r->vfab_fd>0) { close(r->vfab_fd); r->vfab_fd=0; } + + /* Use r->shared_fd to differentiate a "unpublished" reader from + a "published" reader for a writer */ + if (r->shared_fd > 0 && r->shared_table && + r->shared_table != MAP_FAILED) { + munmap(r->shared_table,sizeof(op_ppath_shared_table_t)); + r->shared_table=NULL; + } + if (r->shared_fd) { + close(r->shared_fd); + r->shared_fd = 0; + } + + _DBG_FUNC_EXIT; +} + +void +op_ppath_close_writer(op_ppath_writer_t *w) +{ + _DBG_FUNC_ENTRY; + + close_and_unlink_tables(&w->published); + close_and_unlink_tables(&w->unpublished); + + if (w->unpublished.shared_table) { + free(w->unpublished.shared_table); + } + + _DBG_FUNC_EXIT; +} + +/* + * Opens and maps the shared table with the name shm_name + * and permissions as specified by the rw flags. + */ +static int +open_shared_table(op_ppath_reader_t *r, char *name, int rw) +{ + int err= -1; + int prot; + + _DBG_FUNC_ENTRY; + + if (rw & O_RDWR) { + prot = PROT_READ | PROT_WRITE; + } else { + prot = PROT_READ; + } + + r->shared_fd = shm_open(name, rw, 0644); + if (r->shared_fd < 0) { + _DBG_DEBUG("Failed to open %s\n",name); + goto error; + } + + if (rw & O_CREAT) { + /* Create the file at the specified size. */ + if (ftruncate(r->shared_fd, sizeof(op_ppath_shared_table_t))) { + _DBG_ERROR("Unable to size %s\n",name); + goto error; + } + } + + r->shared_table = mmap(0, + sizeof(op_ppath_shared_table_t), + prot, + MAP_SHARED, + r->shared_fd, + 0); + if (r->shared_table == MAP_FAILED) { + _DBG_DEBUG("Failed to map %s to memory.\n",name); + goto error; + } + + _DBG_FUNC_EXIT; + return 0; +error: + err = errno; + if (r->shared_fd > 0) { + close(r->shared_fd); + if (rw & O_CREAT) + shm_unlink(name); + } + r->shared_fd = 0; + r->shared_table = NULL; + _DBG_FUNC_EXIT; + return err; +} + +enum { + PORT_TABLE, + PATH_TABLE, + SUBNET_TABLE, + VFAB_TABLE, + SID_TABLE +}; + +/* + * The following function opens and maps one of the other shared tables. + * + * table - the type of table being opened/created. + * rw - file access flags. + * c - # of items to allocate if creating. + * c2 - # of secondary items to allocate if creating SUBNET_TABLE, else 0. + */ +static int +open_ppath_table(op_ppath_reader_t *r, int table, int rw, unsigned c, unsigned c2) +{ + int err=0; + int prot; + char *name = NULL; + op_ppath_header_t *h; + off_t size1, size2; + int fd = -1; + + _DBG_FUNC_ENTRY; + + switch (table) { + case PORT_TABLE: + name = r->shared_table->port_table_name; + size1 = PORT_TABLE_SIZE(c); + size2 = 0; + if (rw & O_CREAT) { + BUMP_COUNT(r->shared_table->port_update_count); + sprintf(name, + SHM_TABLE_NAME PORT_TABLE_NAME "%06u", + (unsigned int)r->shared_table->port_update_count); + } + break; + case PATH_TABLE: + name = r->shared_table->path_table_name; + size1 = PATH_TABLE_SIZE(c); + size2 = 0; + if (rw & O_CREAT) { + BUMP_COUNT(r->shared_table->path_update_count); + sprintf(name, + SHM_TABLE_NAME PATH_TABLE_NAME "%06u", + (unsigned int)r->shared_table->path_update_count); + } + break; + case VFAB_TABLE: + name = r->shared_table->vfab_table_name; + size1 = VFAB_TABLE_SIZE(c); + size2 = 0; + if (rw & O_CREAT) { + BUMP_COUNT(r->shared_table->vfab_update_count); + sprintf(name, + SHM_TABLE_NAME VFAB_TABLE_NAME "%06u", + (unsigned int)r->shared_table->vfab_update_count); + } + break; + case SUBNET_TABLE: + name = r->shared_table->subnet_table_name; + size1 = SUBNET_TABLE_SIZE(c); + size2 = SID_TABLE_SIZE(c2); + if (rw & O_CREAT) { + BUMP_COUNT(r->shared_table->subnet_update_count); + sprintf(name, + SHM_TABLE_NAME SUBNET_TABLE_NAME "%06u", + (unsigned int)r->shared_table->subnet_update_count); + } + break; + default: + size1 = size2 = 0; + _DBG_ERROR("Bad table specified. (%d)\n", table); + goto error; + } + + if (rw & O_CREAT) { + prot = PROT_READ | PROT_WRITE; + } else { + // Note that this overrides the sizes set above. + // We will get the real sizes from the header. + prot = PROT_READ; + size1 = sizeof(op_ppath_header_t); + size2 = 0; + } + + fd = shm_open(name, rw, 0644); + if (fd < 0) { + _DBG_ERROR("Failed to open %s\n",name); + goto error; + } + + if (rw & O_CREAT) { + /* Create the file at the specified size. */ + if (ftruncate(fd, size1 + size2)) { + _DBG_ERROR("Unable to size %s\n",name); + goto error; + } + } + + h = (op_ppath_header_t*)mmap(0, size1 + size2, prot, MAP_SHARED, fd, 0); + if (h == MAP_FAILED) { + _DBG_ERROR("Unable to map %s\n",name); + goto error; + } + + if (rw & O_CREAT) { + /* + * clear the table & set the maximum lengths. + */ + memset((char*)h,0,size1+size2); + h->s1 = size1; + h->s2 = size2; + } else { + /* + * In this case, read the size out of the existing file + * and re-map to the correct size. + */ + off_t size3 = h->s1 + h->s2; + munmap(h,size1+size2); + h = (op_ppath_header_t*)mmap(0, size3, prot, MAP_SHARED, fd, 0); + + if ((void *)h == MAP_FAILED) goto error; + } + + // There are definitely times when OOP would be a big win. + switch (table) { + case PORT_TABLE: + r->old_port_update_count = r->shared_table->port_update_count; + r->port_table = (op_ppath_port_table_t*)h; + r->port_fd = fd; + break; + case PATH_TABLE: + r->old_path_update_count = r->shared_table->path_update_count; + r->path_table = (op_ppath_table_t*)h; + r->path_fd = fd; + break; + case VFAB_TABLE: + r->old_vfab_update_count = r->shared_table->vfab_update_count; + r->vfab_table = (op_ppath_vfab_table_t*)h; + r->vfab_fd = fd; + break; + case SUBNET_TABLE: + // The special case that makes much of this necessary. + // The sid table is appended to the end of the subnet table. + r->subnet_table = (op_ppath_subnet_table_t*)h; + r->sid_table = (op_ppath_sid_record_t*)(((char*)h)+(h->s1)); + r->subnet_fd = fd; + r->old_subnet_update_count = r->shared_table->subnet_update_count; + break; + } + _DBG_FUNC_EXIT; + return 0; + +error: + if (fd >= 0) { + close(fd); + if (rw & O_CREAT) + shm_unlink(name); + } + err = errno; + _DBG_FUNC_EXIT; + return err; +} + +/* + * Closes the specified table. + */ +static void +close_ppath_table(op_ppath_reader_t *r, int table) +{ + _DBG_FUNC_ENTRY; + + switch(table) { + case PATH_TABLE: + if (r->path_table && r->path_table != MAP_FAILED) { + munmap(r->path_table,r->path_table->size); + r->path_table=NULL; + } + if (r->path_fd>0) { close(r->path_fd); r->path_fd=0; } + break; + case PORT_TABLE: + if (r->port_table && r->port_table != MAP_FAILED) { + munmap(r->port_table,r->port_table->size); + r->port_table=NULL; + } + if (r->port_fd>0) { close(r->port_fd); r->port_fd=0; } + break; + case VFAB_TABLE: + if (r->vfab_table && r->vfab_table != MAP_FAILED) { + munmap(r->vfab_table,r->vfab_table->size); + r->vfab_table=NULL; + } + if (r->vfab_fd>0) { close(r->vfab_fd); r->vfab_fd=0; } + break; + case SUBNET_TABLE: + if (r->subnet_table && r->subnet_table != MAP_FAILED) { + munmap(r->subnet_table, + r->subnet_table->subnet_size + + r->subnet_table->sid_size); + r->subnet_table=NULL; + } + if (r->subnet_fd>0) { close(r->subnet_fd); r->subnet_fd=0; } + break; + } + + _DBG_FUNC_EXIT; +} + +static int +reopen_ppath_table(op_ppath_reader_t *r, int table, int rw, unsigned c, unsigned c2) +{ + close_ppath_table(r,table); + return open_ppath_table(r,table,rw,c,c2); +} + +/* + * Tries to connect to an existing shared_table and, + * if that fails, creates a new one. + */ +static int +connect_shared_table_rw(op_ppath_reader_t *r) +{ + int err; + + _DBG_FUNC_ENTRY; + //err = open_shared_table(r, SHM_TABLE_NAME, O_RDWR); + err = open_shared_table(r, SHM_TABLE_NAME, O_RDWR | O_CREAT); + if (err) { + _DBG_ERROR("Unable to create shared memory table.\n"); + } else { + memset(r->shared_table,0,sizeof(op_ppath_shared_table_t)); + r->shared_table->abi_version = OPA_SA_DB_PATH_TABLE_VERSION; + } + _DBG_FUNC_EXIT; + return err; +} + +/* + * Tries to connect to an existing shared_table. + * + * Returns non-zero on error. + */ +static int +connect_shared_table(op_ppath_reader_t *r) +{ + int err; + + _DBG_FUNC_ENTRY; + + err = open_shared_table(r, SHM_TABLE_NAME, O_RDONLY); + if (err) { + _DBG_ERROR("Unable to open shared memory table.\n"); + } else if (r->shared_table->abi_version != OPA_SA_DB_PATH_TABLE_VERSION) { + _DBG_ERROR("Incorrect ABI version.\n"); + } + _DBG_FUNC_EXIT; + return err; +} + +/* + * Tries to disconnect from an existing shared_table. + * This function is only called when it fails to + * create the writer after connecting to the shared table + * successfully. It covers only the last part of + * op_ppath_create_writer(). + */ +static void +disconnect_shared_table(op_ppath_reader_t *r) +{ + _DBG_FUNC_ENTRY; + + if (r->shared_table && r->shared_table != MAP_FAILED) { + munmap(r->shared_table, sizeof(op_ppath_shared_table_t)); + r->shared_table=NULL; + } + + if (r->shared_fd > 0) { + close(r->shared_fd); + shm_unlink(SHM_TABLE_NAME); + } + _DBG_FUNC_EXIT; +} + +/* + * Initializes the structures needed to write the shared memory tables. + * read/write access. Returns zero on success or non-zero on error. + * If the tables already exist this function will restore contact with them. + */ +int +op_ppath_create_writer(op_ppath_writer_t *w) +{ + int err = 0; + + _DBG_FUNC_ENTRY; + + memset(w, 0, sizeof(op_ppath_writer_t)); + + err = connect_shared_table_rw(&(w->published)); + if (err) goto error; + + + /* + * The "unpublished" table isn't shared, so we allocate local memory. + * In this case, the shared_fd is 0, which can be used to differentiate + * "unpublished" from "published" table. + */ + w->unpublished.shared_table = malloc(sizeof(op_ppath_shared_table_t)); + if (!(w->unpublished.shared_table)) { + err = ENOMEM; + disconnect_shared_table(&(w->published)); + goto error; + } + + memset(w->unpublished.shared_table,0,sizeof(op_ppath_shared_table_t)); + + /* We do this to ensure that when we open writeable tables, + * they will have an update count greater than the currently + * published tables. (If we did not find currently published + * tables, then we're just copying zeros.) + */ + w->unpublished.shared_table->port_update_count = w->published.shared_table->port_update_count; + w->unpublished.shared_table->subnet_update_count = w->published.shared_table->subnet_update_count; + w->unpublished.shared_table->vfab_update_count = w->published.shared_table->vfab_update_count; + w->unpublished.shared_table->path_update_count = w->published.shared_table->path_update_count; + +error: + _DBG_FUNC_EXIT; + return err; +} + +/* + * Opens the shared memory segments for read-only access. + * + * Note that if any of the opens fails, it closes everything + * and tries again, up to MAX_RETRIES times, on the assumption + * that the failure indicates a collision with discovery. + */ +int +op_ppath_create_reader(op_ppath_reader_t *r) +{ + int err = 0; + + _DBG_FUNC_ENTRY; + + memset(r, 0, sizeof(op_ppath_reader_t)); + + do { + err = connect_shared_table(r); + if (err) continue; + + err = open_ppath_table(r, PORT_TABLE, O_RDONLY, 0, 0); + if (err) { op_ppath_close_reader(r); continue; } + + err = open_ppath_table(r, PATH_TABLE, O_RDONLY, 0, 0); + if (err) { op_ppath_close_reader(r); continue; } + + err = open_ppath_table(r, SUBNET_TABLE, O_RDONLY, 0, 0); + if (err) { op_ppath_close_reader(r); continue; } + + err = open_ppath_table(r, VFAB_TABLE, O_RDONLY, 0, 0); + if (err) { op_ppath_close_reader(r); continue; } + + } while (0); + + _DBG_FUNC_EXIT; + return err; +} + + +/* + * Each of the following functions create a new, unpublished, table. + * If there is an existing table, it is closed an unmapped + * before the new one is created. + */ +int +op_ppath_initialize_ports(op_ppath_writer_t *w, unsigned max_ports) +{ + int err = 0; + op_ppath_reader_t *r = &(w->unpublished); + + _DBG_FUNC_ENTRY; + + close_ppath_table(r,PORT_TABLE); + + w->max_ports = max_ports; + + err = open_ppath_table(r, PORT_TABLE, O_RDWR | O_CREAT, max_ports, 0); + + + _DBG_FUNC_EXIT; + return err; +} + +int +op_ppath_initialize_vfabrics(op_ppath_writer_t *w, unsigned max_vfabs) +{ + int err = 0; + op_ppath_reader_t *r = &(w->unpublished); + + _DBG_FUNC_ENTRY; + + close_ppath_table(r,VFAB_TABLE); + + w->max_vfabs = max_vfabs; + + err = open_ppath_table(r, VFAB_TABLE, O_RDWR | O_CREAT, max_vfabs, 0); + + _DBG_FUNC_EXIT; + return err; +} + +int +op_ppath_initialize_paths(op_ppath_writer_t *w, unsigned max_paths) +{ + int err = 0; + op_ppath_reader_t *r = &(w->unpublished); + + _DBG_FUNC_ENTRY; + + close_ppath_table(r,PATH_TABLE); + + w->max_paths = max_paths; + + err = open_ppath_table(r, PATH_TABLE, O_RDWR | O_CREAT, max_paths, 0); + + _DBG_FUNC_EXIT; + return err; +} + +int +op_ppath_initialize_subnets(op_ppath_writer_t *w, unsigned max_subnets, unsigned max_sids) +{ + int err = 0; + op_ppath_reader_t *r = &(w->unpublished); + + _DBG_FUNC_ENTRY; + + if (!w) { + errno = EINVAL; + goto error; + } + + close_ppath_table(r,SUBNET_TABLE); + + w->max_subnets = max_subnets; w->max_sids = max_sids; + + err = open_ppath_table(r, SUBNET_TABLE, O_RDWR | O_CREAT, max_subnets, max_sids); + +error: + _DBG_FUNC_EXIT; + return err; +} + +/* + * The next several functions each add an item to an unpublished table. + * Returns 0 on success, ENOMEM if the table is full. + */ +int +op_ppath_add_subnet(op_ppath_writer_t *w, uint64 prefix) +{ + int err = 0; + op_ppath_reader_t *r = &(w->unpublished); + _DBG_FUNC_ENTRY; + + if (!w) { + errno = EINVAL; + goto error; + } + + if (r->subnet_table->subnet_count >= w->max_subnets) { + errno = ENOMEM; + goto error; + } + + r->subnet_table->subnet_count++; + r->subnet_table->subnet[r->subnet_table->subnet_count].source_prefix = prefix; + r->subnet_table->subnet[r->subnet_table->subnet_count].first_sid = 0; + r->subnet_table->subnet[r->subnet_table->subnet_count].reserved = 0; + + _DBG_FUNC_EXIT; + return 0; + +error: + _DBG_FUNC_EXIT; + err = errno; + return err; +} + +int +op_ppath_add_port(op_ppath_writer_t *w, op_ppath_port_record_t port) +{ + int err = 0; + int i; + op_ppath_reader_t *r = &(w->unpublished); + + _DBG_FUNC_ENTRY; + + if (!w) { + err = EINVAL; + goto error; + } + + if (r->port_table->count >= w->max_ports) { + err = ENOMEM; + goto error; + } + + r->port_table->count++; + + for (i=1; i <= r->subnet_table->subnet_count; i++) { + if (r->subnet_table->subnet[i].source_prefix == port.source_prefix) + break; + } + + if (i > r->subnet_table->subnet_count) { + _DBG_WARN("Trying to add a port without a matching subnet.\n"); + err = EINVAL; + goto error; + } + + port.subnet_id = i; + + r->port_table->port[r->port_table->count] = port; + + _DBG_FUNC_EXIT; + return 0; + +error: + _DBG_FUNC_EXIT; + return err; +} + +int +op_ppath_add_sid(op_ppath_writer_t *w, + uint64 prefix, + uint64 lower_sid, + uint64 upper_sid, + char *vfab_name) +{ + int err = 0; + int i, n; + uint16 subnet_id; + op_ppath_reader_t *r = &(w->unpublished); + + _DBG_FUNC_ENTRY; + + if (!w) { + errno = EINVAL; + goto error; + } + + if (r->subnet_table->sid_count >= w->max_sids) { + errno = ENOMEM; + goto error; + } + + // reserve a slot for our new record. + // note the pre-increment! + n = ++r->subnet_table->sid_count; + + r->sid_table[n].lower_sid = lower_sid; + r->sid_table[n].upper_sid = upper_sid; + + // Note that record 0 is reserved. + for (i=1; i <= r->subnet_table->subnet_count; i++) { + if (r->subnet_table->subnet[i].source_prefix == prefix) + break; + } + + if (i > r->subnet_table->subnet_count) { + _DBG_WARN("Trying to add a sid without a matching subnet.\n"); + errno = EINVAL; + goto error; + } + + subnet_id = i; + + // Note that record 0 is reserved. + for (i=1; i <= r->vfab_table->count; i++) { + if (!(strcmp(r->vfab_table->vfab[i].vfab_name, vfab_name))) + break; + } + + if (i > r->vfab_table->count) { + _DBG_WARN("Trying to add a sid without a matching virtual fabric.\n"); + errno = EINVAL; + goto error; + } + + r->sid_table[n].vfab_id = i; + r->sid_table[n].next = r->subnet_table->subnet[subnet_id].first_sid; + r->subnet_table->subnet[subnet_id].first_sid = n; + + _DBG_FUNC_EXIT; + return 0; + +error: + _DBG_FUNC_EXIT; + err = errno; + return err; +} + +/* + * Adds a virtual fabric to the unpublished vfab table. + * + * Returns 0 on success, or ENOMEM if the table is full. + */ +int op_ppath_add_vfab(op_ppath_writer_t *w, + char *name, + uint64 prefix, + uint16 pkey, + uint16 sl) +{ + int err = 0; + int i; + op_ppath_reader_t *r = &(w->unpublished); + + _DBG_FUNC_ENTRY; + + if (!w) { + errno = EINVAL; + goto error; + } + + if (r->vfab_table->count >= w->max_vfabs) { + errno = ENOMEM; + goto error; + } + + // Note the pre-increment. + i = ++r->vfab_table->count; + snprintf(r->vfab_table->vfab[i].vfab_name, VFAB_NAME_LENGTH, "%s", name); + r->vfab_table->vfab[i].source_prefix = prefix; + r->vfab_table->vfab[i].pkey = pkey; + r->vfab_table->vfab[i].sl = sl; + + _DBG_FUNC_EXIT; + return 0; + +error: + _DBG_FUNC_EXIT; + err = errno; + return err; +} + +/* + * Adds a path to the unpublished path table. + * Sorts the path into the appropriate subnet and + * virtual fabric based on the SID and SGID. + * + * Returns 0 on success, or ENOMEM if the table is full. + */ +int op_ppath_add_path(op_ppath_writer_t *w, IB_PATH_RECORD_NO *record) +{ + int err = 0; + int i; + + uint64 ho_sid; + + uint32 lid_hash; + uint32 guid_hash; + + op_ppath_reader_t *r = &(w->unpublished); + op_ppath_subnet_record_t *subnet; + op_ppath_vfab_record_t *vfab; + op_ppath_sid_record_t *sid; + op_ppath_record_t *path; + + _DBG_FUNC_ENTRY; + + if (!w) { + errno = EINVAL; + goto error; + } + + for (i=1; i <= r->subnet_table->subnet_count; i++) { + if (r->subnet_table->subnet[i].source_prefix == record->SGID.Type.Global.SubnetPrefix) + break; + } + if (i > r->subnet_table->subnet_count) { + _DBG_WARN("Trying to add a path without a matching subnet.\n"); + errno = EINVAL; + goto error; + } + + subnet = &(r->subnet_table->subnet[i]); + + ho_sid = ntoh64(record->ServiceID); + i = subnet->first_sid; + while (i) { + uint64 ho_lower_sid; + uint64 ho_upper_sid; + + sid = &(r->sid_table[i]); + ho_lower_sid = ntoh64(sid->lower_sid); + ho_upper_sid = ntoh64(sid->upper_sid); + + if (ho_lower_sid == 0 && ho_sid == 0) { + // Adding with a blank sid. Add to the default. + break; + } else if (ho_upper_sid == 0 && ho_sid == ho_lower_sid) { + // Exact match. + break; + } else if (ho_lower_sid != 0 && + ho_sid >= ho_lower_sid && + ho_sid <= ho_upper_sid) { + // Matches range. + break; + } + + i = sid->next; + } + + if (!i) { + _DBG_WARN("Trying to add a path without a matching virtual fabric.\n"); + errno = EINVAL; + goto error; + } + + vfab = &(r->vfab_table->vfab[sid->vfab_id]); + + if (r->path_table->count >= w->max_paths) { + errno = ENOMEM; + goto error; + } + + // Note the pre-increment. + i = ++r->path_table->count; + r->path_table->table[i].path=(*record); + r->path_table->table[i].flags=1; + path = &(r->path_table->table[i]); + + guid_hash = GID_HASH(&(record->DGID)); + lid_hash = LID_HASH(record->DLID); + + path->next_lid = vfab->first_dlid[lid_hash]; + path->next_guid = vfab->first_dguid[guid_hash]; + + vfab->first_dlid[lid_hash] = i; + vfab->first_dguid[guid_hash] = i; + + _DBG_FUNC_EXIT; + return 0; + +error: + _DBG_FUNC_EXIT; + err = errno; + return err; +} +void +op_ppath_publish(op_ppath_writer_t *w) +{ + _DBG_FUNC_ENTRY; + op_ppath_shared_table_t *published = w->published.shared_table; + op_ppath_shared_table_t *unpublished = w->unpublished.shared_table; + + if (published->port_update_count != unpublished->port_update_count) { + _DBG_INFO("Publishing updated port table.\n"); + close_ppath_table(&w->published, PORT_TABLE); + shm_unlink(published->port_table_name); + strcpy(published->port_table_name, + unpublished->port_table_name); + } + if (published->subnet_update_count != unpublished->subnet_update_count) { + _DBG_INFO("Publishing updated subnet table.\n"); + close_ppath_table(&w->published, SUBNET_TABLE); + shm_unlink(published->subnet_table_name); + strcpy(published->subnet_table_name, + unpublished->subnet_table_name); + } + if (published->vfab_update_count != unpublished->vfab_update_count) { + _DBG_INFO("Publishing updated vfab table.\n"); + close_ppath_table(&w->published, VFAB_TABLE); + shm_unlink(published->vfab_table_name); + strcpy(published->vfab_table_name, + unpublished->vfab_table_name); + } + if (published->path_update_count != unpublished->path_update_count) { + _DBG_INFO("Publishing updated path table.\n"); + close_ppath_table(&w->published, PATH_TABLE); + shm_unlink(published->path_table_name); + strcpy(published->path_table_name, + unpublished->path_table_name); + } + + /* + * We do these last to try to minimize the risk that a client + * will see the update before it has finished. Updating the names + * without updating the counters is safe, because active clients + * only look at the counts for changes. + */ + published->port_update_count = unpublished->port_update_count; + published->subnet_update_count = unpublished->subnet_update_count; + published->vfab_update_count = unpublished->vfab_update_count; + published->path_update_count = unpublished->path_update_count; + + _DBG_FUNC_EXIT; +} + +#if 0 +static int +cmp_rec(uint64 mask, IB_PATH_RECORD_NO *a, IB_PATH_RECORD_NO *b) +{ + if ((mask & IB_PATH_RECORD_COMP_SERVICEID) && + (a->ServiceID != b->ServiceID)) return -1; + if ((mask & IB_PATH_RECORD_COMP_DGID) && + memcmp((void*)&(a->DGID), (void*)&(b->DGID), + sizeof(a->DGID))) return -1; + if ((mask & IB_PATH_RECORD_COMP_SGID) && + memcmp((void*)&(a->SGID), (void*)&(b->SGID), + sizeof(a->SGID))) return -1; + if ((mask & IB_PATH_RECORD_COMP_DLID) && + (a->DLID != b->DLID)) return -1; + if ((mask & IB_PATH_RECORD_COMP_SLID) && + (a->SLID != b->SLID)) return -1; + if ((mask & IB_PATH_RECORD_COMP_RAWTRAFFIC) && + (RAW_TRAFFIC(a->u1) != RAW_TRAFFIC(b->u1))) return -1; + if ((mask & IB_PATH_RECORD_COMP_FLOWLABEL) && + (FLOW_LABEL(a->u1) != FLOW_LABEL(b->u1))) return -1; + if ((mask & IB_PATH_RECORD_COMP_HOPLIMIT) && + (HOP_LIMIT(a->u1) != HOP_LIMIT(b->u1))) return -1; + if ((mask & IB_PATH_RECORD_COMP_TCLASS) && + (a->TClass != b->TClass)) return -1; + if ((mask & IB_PATH_RECORD_COMP_REVERSIBLE) && + (a->Reversible != b->Reversible)) return -1; + if ((mask & IB_PATH_RECORD_COMP_PKEY) && + (a->P_Key != b->P_Key)) return -1; + if ((mask & IB_PATH_RECORD_COMP_SL) && + (SL(a->u2) != SL(b->u2))) return -1; + if ((mask & IB_PATH_RECORD_COMP_MTUSELECTOR) && + (a->MtuSelector != b->MtuSelector)) return -1; + if ((mask & IB_PATH_RECORD_COMP_MTU) && + (a->Mtu != b->Mtu)) return -1; + if ((mask & IB_PATH_RECORD_COMP_RATESELECTOR) && + (a->RateSelector != b->RateSelector)) return -1; + if ((mask & IB_PATH_RECORD_COMP_RATE) && + (a->Rate != b->Rate)) return -1; + if ((mask & IB_PATH_RECORD_COMP_PKTLIFESELECTOR) && + (a->PktLifeTimeSelector != b->PktLifeTimeSelector)) return -1; + if ((mask & IB_PATH_RECORD_COMP_PKTLIFE) && + (a->PktLifeTime != b->PktLifeTime)) return -1; + if ((mask & IB_PATH_RECORD_COMP_PREFERENCE) && + (a->Preference != b->Preference)) return -1; + + return 0; +} +#endif + +/* + * These functions check to see if the update count of the named table has been changed. + * + * Returns true if a re-open is needed. + */ +static inline int validate_port_table(op_ppath_reader_t *r) { return (r->old_port_update_count != r->shared_table->port_update_count); } +static inline int validate_path_table(op_ppath_reader_t *r) { return (r->old_path_update_count != r->shared_table->path_update_count); } +static inline int validate_vfab_table(op_ppath_reader_t *r) { return (r->old_vfab_update_count != r->shared_table->vfab_update_count); } +static inline int validate_subnet_table(op_ppath_reader_t *r) { return (r->old_subnet_update_count != r->shared_table->subnet_update_count); } + +int op_ppath_find_path(op_ppath_reader_t *r, + char *hfi_name, + uint16 port, + uint64 mask, + IB_PATH_RECORD_NO *query, + IB_PATH_RECORD_NO *result) +{ + int err=0; + int retries; + int gidquery = 0; + int valid = 0; + uint32 p; + op_ppath_port_record_t *port_record; + op_ppath_sid_record_t *sid_record; + op_ppath_vfab_record_t *vfab; + op_ppath_record_t *path_record = NULL; + uint64 ho_sid; + + + _DBG_FUNC_ENTRY; + + if (!query || !result) { + _DBG_INFO("Null query or result.\n"); + err = EINVAL; + goto error; + } + + if (mask & (IB_PATH_RECORD_COMP_SGID | IB_PATH_RECORD_COMP_DGID)) { + _DBG_DEBUG("GID based query.\n"); + gidquery = 1; + } else if (mask & (IB_PATH_RECORD_COMP_SLID | IB_PATH_RECORD_COMP_DLID)) { + _DBG_DEBUG("LID based query.\n"); + gidquery = 0; + } else { + _DBG_INFO("Must specify either the source & dest lids or the source & dest gids.\n"); + err = EINVAL; + goto error; + } + + + if (mask & IB_PATH_RECORD_COMP_SERVICEID) { + // We need host byte order for doing ranged compares. + _DBG_DEBUG("SID query.\n"); + ho_sid = ntoh64(query->ServiceID); + } else { + // Use the pkey, or just use the default vfabric + _DBG_DEBUG("non-SID query.\n"); + ho_sid = 0; + } + + memset(result,0,sizeof(IB_PATH_RECORD_NO)); + retries = 0; + do { + // Yield the processor so that, if an update is underway, + // it will have a chance to finish before we try to read the tables. + sched_yield(); + + retries++; + + err=0; + + // Find the correct port. If the port table changed, + // begin the query over again. + if (validate_port_table(r)) { + _DBG_DEBUG("Reloading the port table.\n"); + err = reopen_ppath_table(r, PORT_TABLE, O_RDONLY, 0, 0); + if (err) goto error; + continue; // NOTE THE CONTINUE! + } + + if (mask & IB_PATH_RECORD_COMP_SGID) { + _DBG_DEBUG("Identifying port by source gid.\n"); + for (p=1;p<=r->port_table->count;p++) { + if (r->port_table->port[p].source_guid == query->SGID.Type.Global.InterfaceID) + break; + } + } else if (hfi_name && hfi_name[0] !=0) { + uint16_t lid = ntohs(query->SLID); + _DBG_DEBUG("Identifying port by hfi and source lid.\n"); + for (p=1;p<=r->port_table->count;p++) { + uint16_t base_lid = lid & lmc_mask[r->port_table->port[p].lmc]; + if (r->port_table->port[p].base_lid == base_lid && !strcmp(r->port_table->port[p].hfi_name,hfi_name)) + break; + } + } else { + _DBG_INFO("Attempt to query a path without specifying HFI + Port or source gid.\n"); + err = EINVAL; + goto error; + } + + if (p>r->port_table->count) { + _DBG_INFO("Could not find a matching port.\n"); + err = EINVAL; + goto error; + } + + port_record = &(r->port_table->port[p]); + + if (mask & IB_PATH_RECORD_COMP_PKEY) { + // verify that the pkey is valid for this port. + _DBG_DEBUG("Validating the pkey against the port.\n"); + for (p=0; ppkey[p] != 0; p++) { + if ((query->P_Key&0x0080) && + (port_record->pkey[p] == query->P_Key)) { + /* Looking for a full-membership path. */ + break; + } else if ((port_record->pkey[p]&0xff7f) == query->P_Key) { + /* Looking for a limited membership path. */ + break; + } + } + if (p >= PKEY_TABLE_LENGTH || port_record->pkey[p] == 0) { + _DBG_INFO("Port is not a member of the specified partition.\n"); + err = EINVAL; + goto error; + } + } + + // Validate the subnet table. If the table is invalid, re-open it, + // then retry the whole query. + p=port_record->subnet_id; + if (validate_subnet_table(r)) { + _DBG_DEBUG("Reloading the subnet table.\n"); + err = reopen_ppath_table(r, SUBNET_TABLE, O_RDONLY, 0, 0); + if (err) goto error; + continue; // NOTE THE CONTINUE! + } + + // Validate the vfabric. + if (validate_vfab_table(r)) { + _DBG_DEBUG("Reloading the fabric table.\n"); + err = reopen_ppath_table(r, VFAB_TABLE, O_RDONLY, 0, 0); + if (err) goto error; + continue; // NOTE THE CONTINUE! + } + + if (mask & IB_PATH_RECORD_COMP_PKEY) { + // Match the pkey to a virtual fabric. + _DBG_DEBUG("Using the pkey to identify the virtual fabric.\n"); + for (p=1; p<=r->vfab_table->count; p++) { + // The VFab may or may not have the membership bit set. + // This is not a bug. + if ((r->vfab_table->vfab[p].source_prefix == + port_record->source_prefix) && + (r->vfab_table->vfab[p].pkey & 0xff7f) == + (query->P_Key & 0xff7f) ) + break; + } + if (p > r->vfab_table->count) { + _DBG_INFO("Could not find a matching pkey.\n"); + err = EINVAL; + goto error; + } + } else { + uint32 def_sid = 0; + // Find the sid. As before, if we can't find it + // re-try the whole query. + p = r->subnet_table->subnet[p].first_sid; + while (p) { + uint64 ho_lower_sid; + uint64 ho_upper_sid; + sid_record = &(r->sid_table[p]); + ho_lower_sid = ntoh64(sid_record->lower_sid); + ho_upper_sid = ntoh64(sid_record->upper_sid); + + // Flag the default vfab when we find it. + if (ho_lower_sid == 0) def_sid = p; + + if (ho_lower_sid == 0 && ho_sid == 0) { + // Queried with a blank sid. Return the default. + break; + } else if (ho_upper_sid == 0 && ho_sid == ho_lower_sid) { + // Exact match. + break; + } else if (ho_lower_sid != 0 && + ho_sid >= ho_lower_sid && + ho_sid <= ho_upper_sid) { + break; + } + p = sid_record->next; + } + if (!p) { + // Didn't find a good match, use the default. + p = def_sid; + sid_record = &(r->sid_table[p]); + } + if (!p) { + _DBG_INFO("Failed to match query to any sid.\n"); + err = EINVAL; + goto error; + } + + p=sid_record->vfab_id; + } + + vfab = &(r->vfab_table->vfab[p]); + + if (validate_path_table(r)) { + _DBG_DEBUG("Reloading the path table.\n"); + err = reopen_ppath_table(r, PATH_TABLE, O_RDONLY, 0, 0); + continue; // NOTE THE CONTINUE! + } + + // what's the first path to look at? + if (gidquery) { + p = vfab->first_dguid[GID_HASH(&(query->DGID))]; + } else { + p = vfab->first_dlid[LID_HASH(query->DLID)]; + } + + // At this point, we should be looking at a short list of paths. + // These paths will be on the correct subnet and vfabric, + // so we only check the lids. If we get out of this while loop + // with a hit, break out of the outer while loop, too. + while (p) { + path_record = &(r->path_table->table[p]); + + /* + * These if statements are hairy, so here's the logic: + * + * If we are doing a gidquery and the gids match and + * EITHER the pkey matches OR we are not doing pkey queries + * then we have a match. + * + * else, if we are NOT doing a gidquery and the LIDs match and + * EITHER the pkey matches OR we are not doing pkey queries + * then we have a match. + */ + if (gidquery && + !memcmp((void*)&(query->SGID), + (void*)&(path_record->path.SGID), + sizeof(IB_GID_NO)) && + !memcmp((void*)&(query->DGID), + (void*)&(path_record->path.DGID), + sizeof(IB_GID_NO)) && + ((!(mask & IB_PATH_RECORD_COMP_PKEY)) || + ((path_record->path.P_Key&0xff7f) == (query->P_Key&0xff7f)))) { + _DBG_DEBUG("gid match found.\n"); + valid = 1; + break; + } else if (!gidquery && + query->SLID == path_record->path.SLID && + query->DLID == path_record->path.DLID && + ((!(mask & IB_PATH_RECORD_COMP_PKEY)) || + ((path_record->path.P_Key&0xff7f) == (query->P_Key&0xff7f)))) { + _DBG_DEBUG("lid match found.\n"); + valid = 1; + break; + } + if (gidquery) { + p = path_record->next_guid; + } else { + p = path_record->next_lid; + } + } + + // One last sanity check. + if (valid && path_record->flags ==0) valid = 0; + + } while (!valid && (retries <= MAX_RETRIES)); + + if (valid) { + *result = path_record->path; + result->ServiceID = query->ServiceID; + err = 0; + } else if (err == 0) { + // If we got here, we never had an error, but we didn't find + // the path, either. + err = ENOENT; + } + +error: + _DBG_FUNC_EXIT; + return err; +} + + +unsigned op_ppath_version(void) +{ + return OPA_SA_DB_PATH_TABLE_VERSION; +} diff --git a/opasadb/lib/path/opasadb_path_private.h b/opasadb/lib/path/opasadb_path_private.h new file mode 100644 index 0000000..f0d851d --- /dev/null +++ b/opasadb/lib/path/opasadb_path_private.h @@ -0,0 +1,426 @@ +/* BEGIN_ICS_COPYRIGHT2 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT2 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +#if !defined(_OPA_SA_DB_PATH_PRIVATE_H) + +#define _OPA_SA_DB_PATH_PRIVATE_H +#define OPA_SA_DB_PATH_TABLE_VERSION 3 + +#include +#include + + +#include + +/* + * NOTE: THIS CODE IS NOT FOR USE EXCEPT BY DISCOVERY AND OPA_SA_DB. + * OTHER USERS SHOULD STICK TO USING OPA_SA_DB_PATH.H. + * + * opasadb exposes the path table as a set of shared-memory + * regions using a no-lock mechanism. See op_ppath_shared_table_t + * for a description of how access is managed. + * + * Unless noted, all functions return 0 on success, non-zero on error. + * The non-zero error will be one of the standard (errno.h) error codes. + * + * Note: all data should fall on 4-byte boundaries. + * + * Note: All table types except shared_table_t begin with 4 32-bit + * unsigned values. The first two indicate the maximum length of the + * table in bytes. (Most of the tables only use one length. In that + * case, the second field is reserved.) The second two indicate the + * number of records that are actually populated. + */ + +// Note that all name lengths fall on 4-byte boundaries. + +// The maximum length of one of names of the port, vfab and path tables. +#define SHM_NAME_LENGTH 32 + +// Cribbed from /usr/include/infiniband/verbs.h +#define HFI_NAME_LENGTH 64 + +// Pulled right out of thin air. TBD: What's the correct length? +#define VFAB_NAME_LENGTH 32 + +// There's some confusion as to the number of pkeys a port can have. +// I've always believed it was 32, but I can't find a spec indicating +// that value or any other. +#define PKEY_TABLE_LENGTH 32 + +// The shared table uses a "well known" name, all others have +// unique suffixes that change with each update. +#define SHM_TABLE_NAME "INTEL_SA_DSC" +#define SUBNET_TABLE_NAME "_SUB_" +#define VFAB_TABLE_NAME "_VFAB_" +#define PORT_TABLE_NAME "_PORT_" +#define PATH_TABLE_NAME "_PATH_" + +// Must be a power of 2 and (HASH_TABLE_MASK-1), respectively. +//#define HASH_TABLE_SIZE 16384 +//#define HASH_TABLE_MASK 16383 +// These are for developer testing only. +#define HASH_TABLE_SIZE 4096 +#define HASH_TABLE_MASK 4095 + +// How many times to retry a path query before giving up. +#define MAX_RETRIES 5 + +/* + * op_ppath_shared_table_t + * + * abi_version - used to detect collisions between different versions + * XX_update_count - allows clients to detect when the published data has + * changed. + * XX_table_name - the name of the shared memory object containing + * the named table. + * + * The shared memory model is designed to be lockless. This is done via + * a "publish" model. The tables named in this structure are "published" + * and will never change. They can, however, be replaced by new versions. + * When that happens, the update_count is incremented. Clients cache + * a copy of the update_count in local memory. When they notice that the + * published number no longer matches their cached value, they close and + * re-open the shared memory tables, allowing them to access the new + * versions. + * + * In this way, even if the update count changes in the middle of a query, + * the client can detect it an repeat the query. + * + * Note that an update_count of 0 has a special meaning - it means no data + * has been published yet. + */ +typedef struct { + uint32 abi_version; + + uint32 port_update_count; + uint32 subnet_update_count; + uint32 vfab_update_count; + uint32 path_update_count; + + uint64 reserved; + + char port_table_name[SHM_NAME_LENGTH]; + char subnet_table_name[SHM_NAME_LENGTH]; + char vfab_table_name[SHM_NAME_LENGTH]; + char path_table_name[SHM_NAME_LENGTH]; +} op_ppath_shared_table_t; + +/* + * All the data tables begin with 4 32-bit fields. This lets us get some + * info about the table without knowing which type it is. + * + * All *_table_t types should begin with the same structure. + */ +typedef struct { + // Maximum size of the tables, in bytes. + uint32 s1; + uint32 s2; + // Current size of the tables, in records. + uint32 c1; + uint32 c2; +} op_ppath_header_t; + +typedef struct { + char hfi_name[HFI_NAME_LENGTH]; + uint16 port; + uint16 subnet_id; + uint16 base_lid; + uint16 lmc; + uint64 source_prefix; + uint64 source_guid; + uint16 pkey[PKEY_TABLE_LENGTH]; // table ends with a zero value. +} op_ppath_port_record_t; + +typedef struct { + uint32 size; + uint32 reserved; + uint32 count; + uint32 reserved2; + op_ppath_port_record_t port[]; +} op_ppath_port_table_t; + +#define PORT_TABLE_SIZE(ps) (sizeof(op_ppath_port_table_t) + sizeof(op_ppath_port_record_t)*(ps+1)) + +typedef struct { + uint64 source_prefix; + uint32 first_sid; + uint32 reserved; +} op_ppath_subnet_record_t; + +typedef struct { + uint64 lower_sid; + uint64 upper_sid; + uint32 vfab_id; + uint32 next; +} op_ppath_sid_record_t; + +typedef struct { + uint32 subnet_size; + uint32 sid_size; + uint32 subnet_count; + uint32 sid_count; + op_ppath_subnet_record_t subnet[]; + // op_ppath_sid_record_t sid[]; +} op_ppath_subnet_table_t; + +#define SID_TABLE_SIZE(ss) (sizeof(op_ppath_sid_record_t)*(ss+1)) +#define SUBNET_TABLE_SIZE(fs) (sizeof(op_ppath_subnet_table_t)+sizeof(op_ppath_subnet_record_t)*(fs+1)) + +typedef struct { + char vfab_name[VFAB_NAME_LENGTH]; + uint64 source_prefix; + uint16 pkey; + uint16 sl; + uint32 first_dlid[HASH_TABLE_SIZE]; + uint32 first_dguid[HASH_TABLE_SIZE]; +} op_ppath_vfab_record_t; + +typedef struct { + uint32 size; + uint32 reserved; + uint32 count; + uint32 reserved2; + op_ppath_vfab_record_t vfab[]; +} op_ppath_vfab_table_t; + +#define VFAB_TABLE_SIZE(vfs) (sizeof(op_ppath_vfab_table_t)+sizeof(op_ppath_vfab_record_t)*(vfs+1)) + +typedef struct { + IB_PATH_RECORD_NO path; + uint32 flags; // if 0, this record is unused. + uint32 reserved; + uint32 next_guid; + uint32 next_lid; +} __attribute__((packed)) op_ppath_record_t; + + +typedef struct { + uint32 size; + uint32 reserved; + uint32 count; + uint32 reserved2; + op_ppath_record_t table[]; +} __attribute__((packed)) op_ppath_table_t; + +#define PATH_TABLE_SIZE(ps) (sizeof(op_ppath_table_t)+sizeof(op_ppath_record_t)*(ps+1)) + + +/* + ******************* + * API FOR BOTH WRITER & READERS + ******************* + */ + +typedef struct { + op_ppath_shared_table_t *shared_table; + op_ppath_port_table_t *port_table; + op_ppath_subnet_table_t *subnet_table; + op_ppath_vfab_table_t *vfab_table; + op_ppath_sid_record_t *sid_table; // Actually points into port_table mem. + op_ppath_table_t *path_table; + + // file descriptors for mmapped data. + int shared_fd; + int port_fd; + int subnet_fd; + int vfab_fd; + int path_fd; + + // Compared with the versions in shared_table to detect updates. + uint32 old_port_update_count; + uint32 old_subnet_update_count; + uint32 old_vfab_update_count; + uint32 old_path_update_count; +} op_ppath_reader_t; + +/* + * Convenience function. Allocates a reader (or writer) object. + * Used to help isolate IBAccess and OpenIB from each other. + */ +void *op_ppath_allocate_reader(void); +void *op_ppath_allocate_writer(void); + +/* + * Opens shared memory tables for reading only. + * Returns 0 on success (and fills in the reader structure) + * Non-zero on error. (see errno.h) + */ +int op_ppath_create_reader(op_ppath_reader_t *r); + +/* + * Search by query & mask. Because of the structure of + * the shared data, you must specify EITHER: + * + * hfi_name, port, source lid and destination lid + * + * OR: + * + * source gid, destination gid. + * + * The only other parameters that can be used at + * this point are the SID and the PKEY. All other + * fields are ignored. + */ +int op_ppath_find_path(op_ppath_reader_t *r, + char *hfi_name, + uint16 port, + uint64 mask, + IB_PATH_RECORD_NO *query, + IB_PATH_RECORD_NO *result); + +/* + * MHEINZ: TBD: add functions to examine the virtual fabric data? + */ + +void op_ppath_close_tables(op_ppath_reader_t *reader); + + +/* + ******************* + * API FOR WRITER ONLY (discovery) + ******************* + */ + +typedef struct { + /* + * The "published" version of the data. + */ + op_ppath_reader_t published; + + /* + * The "unpublished" version. + */ + op_ppath_reader_t unpublished; + + /* + * The size of each table, in records. + */ + uint32 max_ports; + uint32 max_sids; + uint32 max_subnets; + uint32 max_vfabs; + uint32 max_paths; +} op_ppath_writer_t; + + +/* + * Initializes the structures needed to write the shared memory tables. + * read/write access. Returns zero on success or non-zero on error. + * If the tables already exist this function will restore contact with them. + */ +int op_ppath_create_writer(op_ppath_writer_t *w); + +/* + * Each of the next 4 functions creates a new, unpublished, shared memory + * region for the named data. If an unpublished region already exists, + * it is unlinked. + */ +int op_ppath_initialize_ports(op_ppath_writer_t *w, + unsigned max_ports); + +int op_ppath_initialize_subnets(op_ppath_writer_t *w, + unsigned max_subnets, + unsigned max_sids); + +int op_ppath_initialize_vfabrics(op_ppath_writer_t *w, + unsigned max_vfabs); + +int op_ppath_initialize_paths(op_ppath_writer_t *w, + unsigned max_paths); + +/* + * Adds a subnet to the unpublished subnet table. + * + * Returns 0 on success, or -ENOMEM if the table is full. + */ +int op_ppath_add_subnet(op_ppath_writer_t *w, uint64 prefix); + +/* + * Adds a virtual fabric to the unpublished vfab table. + * + * Returns 0 on success, or -ENOMEM if the table is full. + */ +int op_ppath_add_vfab(op_ppath_writer_t *w, + char *name, + uint64 prefix, + uint16 pkey, + uint16 sl); + +/* + * Adds a port to the port table. + * + * Returns 0 on success, or -ENOMEM if the table is full. + */ +int op_ppath_add_port(op_ppath_writer_t *w, op_ppath_port_record_t port); + +/* + * Adds a SID range to the port & vfab tables. If the upper sid is zero, + * it is assumed that this is a single SID, rather than a range. + * + * Returns 0 on success, or -ENOMEM if the table is full. + */ +int op_ppath_add_sid(op_ppath_writer_t *w, + uint64 prefix, + uint64 lower_sid, + uint64 upper_sid, + char *vfab_name); + +/* + * Adds a path record to the path table and links it to the appropriate + * virtual fabric (based on the source guid and SID). + * + * Returns 0 on success, or -ENOMEM if the table is full. + */ +int op_ppath_add_path(op_ppath_writer_t *w, IB_PATH_RECORD_NO *record); + +/* + * Replaces existing tables with new "published" versions. + * Unaltered tables are not changed. + */ +void op_ppath_publish(op_ppath_writer_t *w); + +/* + * Closes the writer and unlinks the shared memory blocks. + */ +void op_ppath_close_writer(op_ppath_writer_t *w); + +/* + * Closes the reader does not unlink the shared memory blocks. + */ + void op_ppath_close_reader(op_ppath_reader_t *r); + + /* + * Returns the version # of the private API. + */ +unsigned op_ppath_version(void); + +#endif diff --git a/opasadb/lib/path/opasadb_query_many.c b/opasadb/lib/path/opasadb_query_many.c new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/opasadb/lib/path/opasadb_query_many.c diff --git a/opasadb/lib/path/opasadb_static_db.c b/opasadb/lib/path/opasadb_static_db.c new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/opasadb/lib/path/opasadb_static_db.c diff --git a/opasadb/lib/path/opasadb_static_db.h b/opasadb/lib/path/opasadb_static_db.h new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/opasadb/lib/path/opasadb_static_db.h diff --git a/opasadb/lib/route/Makefile b/opasadb/lib/route/Makefile new file mode 100644 index 0000000..d1a2558 --- /dev/null +++ b/opasadb/lib/route/Makefile @@ -0,0 +1,163 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** +# Makefile for opasadb/lib/route + +# Include Make Control Settings +include $(TL_DIR)/$(PROJ_FILE_DIR)/Makesettings.project + +#=============================================================================# +# Definitions: +#-----------------------------------------------------------------------------# + +# Name of SubProjects +DS_SUBPROJECTS = +# name of executable or downloadable image +EXECUTABLE = +# list of sub directories to build +DIRS = +# C files (.c) +CFILES = \ + opasadb_route.c \ + # Add more c files here +# C++ files (.cpp) +CCFILES = \ + # Add more cpp files here +# lex files (.lex) +LFILES = \ + # Add more lex files here +# archive library files (basename, $ARFILES will add MOD_LIB_DIR/prefix and suffix) +LIBFILES = +# Windows Resource Files (.rc) +RSCFILES = +# Windows IDL File (.idl) +IDLFILE = +# Windows Linker Module Definitions (.def) file for dll's +DEFFILE = +# targets to build during INCLUDES phase (add public includes here) +INCLUDE_TARGETS = \ + opasadb_route.h \ + opasadb_route2.h \ + # Add more h hpp files here +# Non-compiled files +MISC_FILES = \ + # Add more misc files here +# all source files +SOURCES = $(CFILES) $(CCFILES) $(LFILES) $(RSCFILES) $(IDLFILE) +# Source files to include in DSP File +DSP_SOURCES = $(INCLUDE_TARGETS) $(SOURCES) $(MISC_FILES) \ + $(RSCFILES) $(DEFFILE) $(MAKEFILE) +# all object files +OBJECTS = $(CFILES:.c=$(OBJ_SUFFIX)) $(CCFILES:.cpp=$(OBJ_SUFFIX)) \ + $(LFILES:.lex=$(OBJ_SUFFIX)) \ + # Add more object files here +RSCOBJECTS = $(RSCFILES:.rc=$(RES_SUFFIX)) +# targets to build during LIBS phase +LIB_TARGETS_IMPLIB = +LIB_TARGETS_ARLIB = +LIB_TARGETS_EXP = $(LIB_TARGETS_IMPLIB:$(ARLIB_SUFFIX)=$(EXP_SUFFIX)) +LIB_TARGETS_MISC = +# targets to build during CMDS phase +#SHLIB_VERSION = +#CMD_TARGETS_SHLIB = +CMD_TARGETS_EXE = $(EXECUTABLE) +CMD_TARGETS_MISC = +# files to remove during clean phase +CLEAN_TARGETS_MISC = +CLEAN_TARGETS = $(OBJECTS) $(RSCOBJECTS) $(IDL_TARGETS) $(CLEAN_TARGETS_MISC) +# other files to remove during clobber phase +CLOBBER_TARGETS_MISC= +# sub-directory to install to within bin +BIN_SUBDIR = +# sub-directory to install to within include +INCLUDE_SUBDIR = + +# Additional Settings +#CLOCALDEBUG = User defined C debugging compilation flags [Empty] +#CCLOCALDEBUG = User defined C++ debugging compilation flags [Empty] +# User defined C flags for compiling +# User defined C++ flags for compiling +#CCLOCAL = +#BSCLOCAL = User flags for Browse File Builder [Empty] +#DEPENDLOCAL = user defined makedepend flags [Empty] +#LINTLOCAL = User defined lint flags [Empty] +# User include directories to search for C/C++ headers +LOCAL_INCLUDE_DIRS = +#LDLOCAL = User defined C flags for linking [Empty] +#IMPLIBLOCAL = User flags for Object Lirary Manager [Empty] +#MIDLLOCAL = User flags for IDL compiler [Empty] +#RSCLOCAL = User flags for resource compiler [Empty] +# User libraries to include in dependencies +LOCALDEPLIBS = +# User libraries to use when linking (in addition to LOCALDEPLIBS) +#LOCALLIBS = $(OPENIB_USER_LIBS) $(IBACCESS_USER_LIBS) +LOCALLIBS = +# User library directories for libpaths +#LOCAL_LIB_DIRS = $(OPENIB_USER_LIB_DIRS) $(IBACCESS_USER_LIB_DIRS) +LOCAL_LIB_DIRS = + +# Include Make Rules definitions and rules +include $(TL_DIR)/IbaTools/Makerules.module + +#=============================================================================# +# Overrides: +#-----------------------------------------------------------------------------# +# C++ optimization flags, default lets build config decide +#CCOPT = +# C optimization flags, default lets build config decide +#SUBSYSTEM = Subsystem to build for (none, console or windows) [none] +# (Windows Only) +#USEMFC = How Windows MFC should be used (none, static, shared, no_mfc) [none] +# (Windows Only) +#=============================================================================# + +#=============================================================================# +# Rules: +#-----------------------------------------------------------------------------# +# process Sub-directories +include $(TL_DIR)/Makerules/Maketargets.toplevel + +# build cmds and libs +include $(TL_DIR)/Makerules/Maketargets.build + +# install for includes, libs and cmds phases +include $(TL_DIR)/Makerules/Maketargets.install + +# install for stage phase +#include $(TL_DIR)/Makerules/Maketargets.stage +STAGE:: + $(VS)$(STAGE_INSTALL) $(STAGE_INSTALL_DIR_OPT) $(PROJ_STAGE_OPA_SA_DB_DIR) $(INCLUDE_TARGETS) + +# Unit test execution +#include $(TL_DIR)/Makerules/Maketargets.runtest + +#=============================================================================# + +#=============================================================================# +# DO NOT DELETE THIS LINE -- make depend depends on it. +#=============================================================================# diff --git a/opasadb/lib/route/opasadb_route.c b/opasadb/lib/route/opasadb_route.c new file mode 100644 index 0000000..8d43803 --- /dev/null +++ b/opasadb/lib/route/opasadb_route.c @@ -0,0 +1,2095 @@ +/* BEGIN_ICS_COPYRIGHT5 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT5 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + + +/******************************************************************************* + * + * INCLUDES + */ + +#include + +#include "byteswap.h" +#include "opamgt_priv.h" +#include "opasadb_route2.h" +#include "statustext.h" + + +/******************************************************************************* + * + * DEFINES + */ + +// Port Handle Table Entry: table of entries, 1 for each created port handle +// Note that this struct must align with op_route_param_alloc_entry in +// opasadb_route2.h +struct param_alloc_port_handle_entry +{ + uint64_t reserved; // Not used + uint64_t reserved2; // Not used + uint64_t reserved3; // Not used + OP_ROUTE_PORT_HANDLE port_handle; // port_handle passed to user + uint64_t port_guid; // Port GUID associated w/port_handle + int port_id; // Port ID associated w/port_handle +}; + + +/******************************************************************************* + * + * LOCAL VARIABLES + */ + +// Port handle table +static struct op_route_param_alloc param_port_handle = + { 0, 0, 0, 0, NULL }; + +// Send/recv timeout mSec (start value 4294 mSec based on RespTimeValue = 19) +static int num_timeout_ms = (2 * 4096 * (1L << 19)) / 1000000; +static int ct_retry = DEFAULT_SD_RETRY_COUNT; // Send/recv retry count + + +/******************************************************************************* + * + * LOCAL FUNCTIONS + */ + +/******************************************************************************* + * + * op_route_hton() + * + * Description: + * Copy host data to network buffer, placing the most significant byte of + * interest of host data in the first byte of the network buffer. The + * copy is done a byte at a time so that the endian-ness of the CPU and + * word/long-word boundaries in the network buffer do not matter. The + * least significant 'length' bytes of host data are copied. The pointer + * to the network buffer is updated to point to the next available network + * data location. + * + * Inputs: + * pp_bfr_net - Pointer to pointer to network buffer + * host - Host data to copy + * length - Length of data (in bytes) to copy (max 8) + * + * Outputs: + * *pp_bfr_net - Next available network data location + */ +static void op_route_hton( uint8_t ** pp_bfr_net, + uint64_t host, + int length ) +{ + int ix; + uint8_t * p_bfr_net; + + if ( pp_bfr_net && (p_bfr_net = *pp_bfr_net) && (length > 0) && + (length <= 8) ) + { + for (ix = length, p_bfr_net += (length - 1); ix > 0; host >>= 8, ix--) + *p_bfr_net-- = host & 0xFF; + + *pp_bfr_net += length; + } + +} // End of op_route_hton() + +/******************************************************************************* + * + * op_route_ntoh() + * + * Description: + * Copy network buffer to host data, placing the first byte of the network + * buffer in the most significant byte of interest of host data. The + * copy is done a byte at a time so that the endian-ness of the CPU and + * word/long-word boundaries in the network buffer do not matter. 'length' + * bytes of the network buffer are copied to the least significant 'length' + * bytes of host data, which is returned to the caller. The pointer to + * the network buffer is updated to point to the next available network + * data location. + * + * Inputs: + * pp_bfr_net - Pointer to pointer to network buffer + * length - Length of data (in bytes) to copy (max 8) + * + * Outputs: + * host data - Network data available + * *pp_bfr_net = next available network data location + * 0 - No network data available) + */ +static uint64_t op_route_ntoh( uint8_t ** pp_bfr_net, + int length ) +{ + int ix; + uint8_t * p_bfr_net; + uint64_t host = 0; + + if ( pp_bfr_net && (p_bfr_net = *pp_bfr_net) && (length > 0) && + (length <= 8) ) + { + for (ix = length; ix > 0; ix--) + host = (host << 8) | *p_bfr_net++; + + *pp_bfr_net += length; + } + + return (host); + +} // End of op_route_ntoh() + +/******************************************************************************* + * + * op_route_gen_port_handle() + * + * Description: + * Generate a pseudo-random port handle. Use multiple calls to rand() if + * an int is smaller than OP_ROUTE_PORT_HANDLE or to prevent a port handle + * of 0. + * + * Inputs: + * none + * + * Outputs: + * OP_ROUTE_PORT_HANDLE + */ +static OP_ROUTE_PORT_HANDLE op_route_gen_port_handle(void) +{ + static unsigned seed_rand = 0; + OP_ROUTE_PORT_HANDLE port_handle; + int fb_loop; + + if (!seed_rand) + { + seed_rand = (unsigned)time(NULL); + srand(seed_rand); + } + + fb_loop = (sizeof(int) < sizeof(OP_ROUTE_PORT_HANDLE)); + for ( port_handle = (OP_ROUTE_PORT_HANDLE)rand(); fb_loop || !port_handle; + fb_loop = FALSE ) + port_handle = ( (port_handle << (sizeof(int) * 8)) | + (OP_ROUTE_PORT_HANDLE)rand() ); + + return (port_handle); + +} // End of op_route_gen_port_handle() + +/******************************************************************************* + * + * op_route_get_port_handle_entry() + * + * Description: + * Get the port table entry associated with the specified port_handle. + * + * Inputs: + * port_handle - OP_ROUTE_PORT_HANDLE + * + * Outputs: + * Pointer to port table entry, or NULL if entry not found + */ +static struct param_alloc_port_handle_entry * op_route_get_port_handle_entry( + OP_ROUTE_PORT_HANDLE port_handle ) +{ + uint32_t ix; + struct param_alloc_port_handle_entry * p_param_entry; + + if (port_handle) + for ( ix = param_port_handle.num_allocated, p_param_entry = + (struct param_alloc_port_handle_entry *)param_port_handle.p_params; + ix > 0; p_param_entry++, ix-- ) + if (p_param_entry->port_handle == port_handle) + return (p_param_entry); + + return (NULL); + +} // End of op_route_get_port_handle_entry() + +/******************************************************************************* + * + * op_route_send_recv_query() + * + * Description: + * Create an OP_ROUTE query, send it and get the response. The following + * queries are supported: + * OP_ROUTE_AMOD_CLASS_INFO + * OP_ROUTE_AMOD_CREATE_JOB + * OP_ROUTE_AMOD_SET_USE_MATRIX + * OP_ROUTE_AMOD_POLL_READY + * OP_ROUTE_AMOD_COMPLETE_JOB + * OP_ROUTE_AMOD_GET_PORTGUID_VEC + * OP_ROUTE_AMOD_GET_SWITCH_MAP + * OP_ROUTE_AMOD_GET_COST_MATRIX + * OP_ROUTE_AMOD_GET_USE_MATRIX + * OP_ROUTE_AMOD_GET_JOBS + * + * Inputs: + * attr_mod - Attribute modifier + * port_handle - OP_ROUTE_PORT_HANDLE + * optn_query - Query options (AMOD specific) + * p_job_id - Pointer to OP_ROUTE_JOB_ID + * p_job_status - Pointer to job_status + * p_job_params - Pointer to job parameters + * p_guid_vec - Pointer to portguid_vec + * p_switch_map - Pointer to switch_map + * pp_cost_matrix - Pointer to pointer to cost_matrix + * p_use_matrix - Pointer to use_matrix + * p_job_list - Pointer to job_list + * port - Pointer to opamgt handler + * + * Outputs: + * OP_ROUTE_STATUS_OK - Query successful + * OP_ROUTE_STATUS_INVALID_PARAM - port_handle invalid + * - p_job_status NULL + * - p_guid_vec NULL + * - p_switch_map NULL + * - pp_cost_matrix NULL + * - p_use_matrix NULL + * OP_ROUTE_STATUS_ERROR - Registration error + * - Unable to allocate memory + */ +static enum op_route_status op_route_send_recv_query( uint32_t attr_mod, + OP_ROUTE_PORT_HANDLE port_handle, + uint16_t optn_query, + OP_ROUTE_JOB_ID * p_job_id, + enum op_route_job_status * p_job_status, + struct op_route_job_parameters * p_job_params, + struct op_route_portguid_vec * p_guid_vec, + struct op_route_switch_map * p_switch_map, + uint16_t ** pp_cost_matrix, + struct op_route_use_matrix * p_use_matrix, + struct op_route_job_list * p_job_list, + struct omgt_port * port) +{ + FSTATUS fstatus; + enum op_route_status rstatus = OP_ROUTE_STATUS_OK; + int ix, ix_2, ix_3; + struct param_alloc_port_handle_entry * p_port_handle_entry = NULL; + SA_MAD * p_mad_send = NULL; + SA_MAD * p_mad_recv = NULL; + uint8_t * p_data_wire; + size_t len_data_alloc = sizeof(MAD_COMMON) + sizeof(RMPP_HEADER) + + sizeof(SA_HDR); + int len_recv; + int qp_sm = 1; + uint8_t base_version; + uint8_t mgmt_class; + uint8_t class_version; + uint8_t class_method; + MAD_STATUS mad_status; + static uint32_t trans_id = 1; + uint16_t attr_id; + uint32_t attr_mod_2; + + uint8_t wstatus; + OP_ROUTE_JOB_ID job_id; + uint64_t * p_guids = NULL; + uint64_t * p_guids_2; + uint16_t * p_switch_indices = NULL; + uint16_t * p_switch_indices_2; + uint16_t * p_cost_matrix_2 = NULL; + uint16_t * p_cost_matrix_l; + uint16_t * p_cost_matrix_l2; + uint16_t * p_cost_matrix_r; + uint16_t * p_cost_matrix_r2; + struct op_route_use_element * p_use_elements = NULL; + struct op_route_use_element * p_use_elements_2; + struct op_route_job_info * p_job_info = NULL; + struct op_route_job_info * p_job_info_2; + uint16_t num_guids=-1, num_guids_2=-1; + uint16_t num_switches=-1, num_switches_2=-1; + uint16_t num_elements=-1; + uint16_t use_multiplier; + uint8_t default_use; + uint16_t num_jobs; + uint64_t temp; + struct omgt_mad_addr addr; + uint8_t port_state; + + if (p_guid_vec) num_guids = p_guid_vec->num_guids; + + // Common processing + if (!(p_port_handle_entry = op_route_get_port_handle_entry(port_handle))) + return (OP_ROUTE_STATUS_INVALID_PARAM); + + // Ensure the port is active + (void)omgt_port_get_port_state(port, &port_state); + if (port_state != PortStateActive) + return (OP_ROUTE_STATUS_ERROR); + + // Construct query based on attribute modifier + switch (attr_mod) + { + + case OP_ROUTE_AMOD_CLASS_INFO: + case OP_ROUTE_AMOD_GET_JOBS: + { + if(!(p_mad_send = calloc(1, len_data_alloc))) + { + rstatus = OP_ROUTE_STATUS_ERROR; + goto cleanup; + } + + break; + + } // End of case OP_ROUTE_AMOD_CLASS_INFO / etc + + case OP_ROUTE_AMOD_CREATE_JOB: + { + len_data_alloc += ( sizeof(uint16_t) + OP_ROUTE_MAX_JOB_NAME_LEN + + OP_ROUTE_MAX_APP_NAME_LEN + sizeof(uint64_t) + sizeof(uint64_t) + + sizeof(uint16_t) + (num_guids * sizeof(uint64_t)) ); + + if(!(p_mad_send = calloc(1, len_data_alloc))) + { + rstatus = OP_ROUTE_STATUS_ERROR; + goto cleanup; + } + + p_data_wire = (uint8_t *)(p_mad_send->Data); + op_route_hton(&p_data_wire, optn_query, sizeof(uint16_t)); + strcpy((char *)p_data_wire, p_job_params->name); + p_data_wire += OP_ROUTE_MAX_JOB_NAME_LEN; + strcpy((char *)p_data_wire, p_job_params->application_name); + p_data_wire += OP_ROUTE_MAX_APP_NAME_LEN; + op_route_hton(&p_data_wire, p_job_params->pid, sizeof(p_job_params->pid)); + op_route_hton(&p_data_wire, p_job_params->uid, sizeof(p_job_params->uid)); + op_route_hton(&p_data_wire, num_guids, sizeof(uint16_t)); + for (ix = 0; ix < num_guids; ix++) + op_route_hton( &p_data_wire, p_guid_vec->p_guids[ix], + sizeof(uint64_t) ); + + break; + + } // End of case OP_ROUTE_AMOD_CREATE_JOB + + case OP_ROUTE_AMOD_SET_USE_MATRIX: + { + len_data_alloc += ( sizeof(OP_ROUTE_JOB_ID) + + sizeof(uint16_t) + sizeof(uint8_t) + sizeof(uint16_t) + + ( p_use_matrix->num_elements * + (sizeof(uint16_t) + sizeof(uint16_t) + sizeof(uint8_t)) ) ); + + if(!(p_mad_send = calloc(1, len_data_alloc))) + { + rstatus = OP_ROUTE_STATUS_ERROR; + goto cleanup; + } + + p_data_wire = (uint8_t *)(p_mad_send->Data); + op_route_hton(&p_data_wire, *p_job_id, sizeof(OP_ROUTE_JOB_ID)); + op_route_hton(&p_data_wire, p_use_matrix->multiplier, sizeof(uint16_t)); + *p_data_wire++ = p_use_matrix->default_use; + op_route_hton(&p_data_wire, p_use_matrix->num_elements, sizeof(uint16_t)); + + for ( ix = p_use_matrix->num_elements, + p_use_elements = p_use_matrix->p_elements; ix > 0; p_use_elements++, ix-- ) + { + op_route_hton( &p_data_wire, (p_use_elements->bursty << 15) | + p_use_elements->switch_index, sizeof(uint16_t) ); + op_route_hton(&p_data_wire, p_use_elements->dlid, sizeof(uint16_t)); + *p_data_wire++ = p_use_elements->use; + } + + break; + + } // End of case OP_ROUTE_AMOD_SET_USE_MATRIX + + case OP_ROUTE_AMOD_POLL_READY: + case OP_ROUTE_AMOD_COMPLETE_JOB: + case OP_ROUTE_AMOD_GET_PORTGUID_VEC: + case OP_ROUTE_AMOD_GET_SWITCH_MAP: + case OP_ROUTE_AMOD_GET_COST_MATRIX: + case OP_ROUTE_AMOD_GET_USE_MATRIX: + { + len_data_alloc += sizeof(OP_ROUTE_JOB_ID); + if(!(p_mad_send = calloc(1, len_data_alloc))) + { + rstatus = OP_ROUTE_STATUS_ERROR; + goto cleanup; + } + + p_data_wire = (uint8_t *)(p_mad_send->Data); + op_route_hton(&p_data_wire, *p_job_id, sizeof(OP_ROUTE_JOB_ID)); + + break; + + } // End of case OP_ROUTE_AMOD_POLL_READY / etc + + // Invalid attribute modifier + default: + printf("op_route_send_recv_query: invalid AMOD:%d\n", attr_mod); + rstatus = OP_ROUTE_STATUS_ERROR; + goto cleanup; + + } // End of switch (attr_mod) + + // Prep query for send; send query and receive response + MAD_SET_ATTRIB_MOD(p_mad_send, attr_mod); + MAD_SET_METHOD_TYPE(p_mad_send, SUBN_ADM_GETMULTI); + MAD_SET_VERSION_INFO( p_mad_send, IB_BASE_VERSION, MCLASS_SUBN_ADM, + IB_COMM_MGT_CLASS_VERSION ); + MAD_SET_TRANSACTION_ID(p_mad_send, trans_id++); + MAD_SET_ATTRIB_ID(p_mad_send, SA_ATTRIB_JOB_ROUTE_RECORD); + + if (len_data_alloc > MAD_BLOCK_SIZE) + p_mad_send->RmppHdr.RmppFlags.s.Active = 1; + + BSWAP_MAD_HEADER((MAD *)p_mad_send); + BSWAP_SA_HDR(&p_mad_send->SaHdr); + + // Send query + + memset(&addr, 0, sizeof(addr)); + (void)omgt_port_get_port_sm_lid(port, &addr.lid); + addr.qpn = qp_sm; + addr.qkey = QP1_WELL_KNOWN_Q_KEY; + addr.pkey = OMGT_DEFAULT_PKEY; + + fstatus = omgt_send_recv_mad_alloc(port, + (uint8_t *)p_mad_send, len_data_alloc, + &addr, + (uint8_t **)&p_mad_recv, (size_t *)&len_recv, + num_timeout_ms, + ct_retry); + + if (fstatus != FSUCCESS || !p_mad_recv) + { + if (fstatus == FTIMEOUT || fstatus == FNOT_DONE) + { + rstatus = OP_ROUTE_STATUS_TIMEOUT; + goto cleanup; + } + else + { + rstatus = OP_ROUTE_STATUS_RECV_ERROR; + goto cleanup; + } + } + + // Fix endian of the received data & check MAD header + if ((len_recv -= IBA_SUBN_ADM_HDRSIZE) < 0) + { + rstatus = OP_ROUTE_STATUS_ERROR; + goto cleanup; + } + + BSWAP_MAD_HEADER((MAD *)(p_mad_recv)); + BSWAP_SA_HDR(&p_mad_recv->SaHdr); + MAD_GET_VERSION_INFO(p_mad_recv, &base_version, &mgmt_class, &class_version); + MAD_GET_METHOD_TYPE(p_mad_recv, &class_method); + MAD_GET_STATUS(p_mad_recv, &mad_status); + MAD_GET_ATTRIB_ID(p_mad_recv, &attr_id); + MAD_GET_ATTRIB_MOD(p_mad_recv, &attr_mod_2); + + if ( (base_version < OP_ROUTE_MIN_BASE_VERSION) || + (mgmt_class != MCLASS_SUBN_ADM) || + (class_version < OP_ROUTE_MIN_SA_CLASS_VERSION) || + (class_method != SUBN_ADM_GETMULTI) || mad_status.AsReg16 || + (attr_id != SA_ATTRIB_JOB_ROUTE_RECORD) || (attr_mod_2 != attr_mod) ) + { + rstatus = OP_ROUTE_STATUS_ERROR; + goto cleanup; + } + + // Get wire status in recv data & process common errors + if ((len_recv -= 1) < 0) + { + rstatus = OP_ROUTE_STATUS_ERROR; + goto cleanup; + } + + p_data_wire = (uint8_t *)(p_mad_recv->Data); + wstatus = (enum op_route_wire_status) *p_data_wire++; + + if (wstatus == OP_ROUTE_WIRE_STATUS_INVALID_JOB) + { + rstatus = OP_ROUTE_STATUS_INVALID_JOB; + goto cleanup; + } + + if (wstatus == OP_ROUTE_WIRE_STATUS_ERROR) + { + rstatus = OP_ROUTE_STATUS_ERROR; + goto cleanup; + } + + // Process recv data based on attribute modifier + switch (attr_mod) + { + + case OP_ROUTE_AMOD_CLASS_INFO: + { + // Check wire status + if (wstatus == OP_ROUTE_WIRE_STATUS_OK_PARTIAL) + { + rstatus = OP_ROUTE_STATUS_ERROR; + goto cleanup; + } + + // Check for minimum amount of received data + if ((len_recv -= 16) < 0) + { + rstatus = OP_ROUTE_STATUS_ERROR; + goto cleanup; + } + + // Check JM class version + p_data_wire += 1; + if ( (temp = op_route_ntoh(&p_data_wire, sizeof(uint8_t))) < + OP_ROUTE_MIN_JM_CLASS_VERSION ) + { + rstatus = OP_ROUTE_STATUS_ERROR; + goto cleanup; + } + + // Get RespTimeValue and calculate num_timeout_ms; instead of doubling + // RespTimeValue-based value, could add PortInfo:SubnetTimeout + p_data_wire += 5; + num_timeout_ms = ( 2 * 4096 * + (1L << (op_route_ntoh(&p_data_wire, sizeof(uint8_t)) & 0x1F)) ) / + 1000000; + + // Verify redirection GID is 0 + if ((temp = op_route_ntoh(&p_data_wire, sizeof(uint64_t)))) + { + rstatus = OP_ROUTE_STATUS_ERROR; + goto cleanup; + } + + // Ignore remaining received data + len_recv = 0; + + break; + + } // End of case OP_ROUTE_AMOD_CLASS_INFO + + case OP_ROUTE_AMOD_CREATE_JOB: + { + // Check wire status + if (wstatus == OP_ROUTE_WIRE_STATUS_OK_PARTIAL) + rstatus = OP_ROUTE_STATUS_OK_PARTIAL; + + // Check for minimum amount of received data + if ( ( len_recv -= ( sizeof(OP_ROUTE_JOB_ID) + + ((num_guids + 2) * sizeof(uint16_t)) ) ) < 0 ) + { + rstatus = OP_ROUTE_STATUS_ERROR; + goto cleanup; + } + + // Get job ID + job_id = op_route_ntoh(&p_data_wire, sizeof(OP_ROUTE_JOB_ID)); + + // Get switch map + if ((len_data_alloc = num_guids * sizeof(uint16_t))) + { + if (!(p_switch_indices = calloc(1, len_data_alloc))) + { + rstatus = OP_ROUTE_STATUS_ERROR; + goto cleanup; + } + + num_guids_2 = op_route_ntoh(&p_data_wire, sizeof(uint16_t)); + num_switches = op_route_ntoh(&p_data_wire, sizeof(uint16_t)); + + if ( (num_guids_2 != num_guids) || + (num_switches > OP_ROUTE_MAX_NUM_SWITCHES) || + (num_switches > num_guids) ) + { + rstatus = OP_ROUTE_STATUS_ERROR; + goto cleanup; + } + + for ( ix = num_guids, p_switch_indices_2 = p_switch_indices; + ix > 0; p_switch_indices_2++, ix-- ) + { + if ( ( ( *p_switch_indices_2 = + op_route_ntoh(&p_data_wire, sizeof(uint16_t)) ) >= + num_switches ) && (*p_switch_indices_2 != 0xFFFF) ) + { + rstatus = OP_ROUTE_STATUS_ERROR; + goto cleanup; + } + } + } + + // Check for minimum amount of received data + if ((len_recv -= sizeof(uint16_t)) < 0) + { + rstatus = OP_ROUTE_STATUS_ERROR; + goto cleanup; + } + + // Get cost matrix; comes in as 'top right' half + num_switches_2 = op_route_ntoh(&p_data_wire, sizeof(uint16_t)); + + if (num_switches_2 != num_switches) + { + rstatus = OP_ROUTE_STATUS_ERROR; + goto cleanup; + } + + if ((len_data_alloc = num_switches * num_switches * sizeof(uint16_t))) + { + // Check amount of received data + if ( ( len_recv -= ( (num_switches * (num_switches - 1)) * + sizeof(uint16_t) / 2 ) ) < 0 ) + { + rstatus = OP_ROUTE_STATUS_ERROR; + goto cleanup; + } + + if (!(p_cost_matrix_2 = calloc(1, len_data_alloc))) + { + rstatus = OP_ROUTE_STATUS_ERROR; + goto cleanup; + } + + for ( ix = num_switches * (num_switches - 1) / 2, + ix_2 = num_switches - 1, + p_cost_matrix_r = p_cost_matrix_2 + 1, + p_cost_matrix_l = p_cost_matrix_2 + num_switches; + ix > 0; + p_cost_matrix_r += (num_switches + 1), + p_cost_matrix_l += (num_switches + 1), + ix_2-- ) + + for ( ix_3 = ix_2, + p_cost_matrix_r2 = p_cost_matrix_r, + p_cost_matrix_l2 = p_cost_matrix_l; + (ix_3 > 0) && (ix > 0); + p_cost_matrix_r2++, p_cost_matrix_l2 += num_switches, + ix_3--, ix-- ) + *p_cost_matrix_r2 = *p_cost_matrix_l2 = + (uint16_t)op_route_ntoh(&p_data_wire, sizeof(uint16_t)); + } + + // Return data to caller + if (!(optn_query & OP_ROUTE_CREATE_JOB_NO_CREATE)) + *p_job_id = job_id; + p_switch_map->num_switches = num_switches; + p_switch_map->p_switch_indices = p_switch_indices; + *pp_cost_matrix = p_cost_matrix_2; + + p_switch_indices = NULL; + p_cost_matrix_2 = NULL; + + break; + + } // End of case OP_ROUTE_AMOD_CREATE_JOB + + case OP_ROUTE_AMOD_SET_USE_MATRIX: + { + // Check wire status + if (wstatus == OP_ROUTE_WIRE_STATUS_OK_PARTIAL) + { + rstatus = OP_ROUTE_STATUS_ERROR; + goto cleanup; + } + + break; + + } // End of case OP_ROUTE_AMOD_SET_USE_MATRIX + + case OP_ROUTE_AMOD_POLL_READY: + { + // Check wire status + if (wstatus == OP_ROUTE_WIRE_STATUS_OK_PARTIAL) + { + rstatus = OP_ROUTE_STATUS_ERROR; + goto cleanup; + } + + // Get job_status + if ((len_recv -= 1) < 0) + { + rstatus = OP_ROUTE_STATUS_ERROR; + goto cleanup; + } + + *p_job_status = (enum op_route_job_status) *p_data_wire; + + break; + + } // End of case OP_ROUTE_AMOD_POLL_READY + + case OP_ROUTE_AMOD_COMPLETE_JOB: + { + // Check wire status + if (wstatus == OP_ROUTE_WIRE_STATUS_OK_PARTIAL) + { + rstatus = OP_ROUTE_STATUS_ERROR; + goto cleanup; + } + + break; + + } // End of case OP_ROUTE_AMOD_COMPLETE_JOB + + case OP_ROUTE_AMOD_GET_PORTGUID_VEC: + { + if (! p_guid_vec) + { + rstatus = OP_ROUTE_STATUS_INVALID_PARAM; + goto cleanup; + } + // Check wire status + if (wstatus == OP_ROUTE_WIRE_STATUS_OK_PARTIAL) + { + rstatus = OP_ROUTE_STATUS_ERROR; + goto cleanup; + } + + // Check for minimum amount of received data + if ((len_recv -= sizeof(uint16_t)) < 0) + { + rstatus = OP_ROUTE_STATUS_ERROR; + goto cleanup; + } + + // Get number of port GUIDs + num_guids = op_route_ntoh(&p_data_wire, sizeof(uint16_t)); + + // Check for minimum amount of received data + len_data_alloc = num_guids * sizeof(uint64_t); + if ((len_recv -= len_data_alloc) < 0) + { + rstatus = OP_ROUTE_STATUS_ERROR; + goto cleanup; + } + + if (len_data_alloc) + { + if (!(p_guids = calloc(1, len_data_alloc))) + { + rstatus = OP_ROUTE_STATUS_ERROR; + goto cleanup; + } + + // Get port GUIDs + for (ix = num_guids, p_guids_2 = p_guids; ix > 0; ix--) + *p_guids_2++ = op_route_ntoh(&p_data_wire, sizeof(uint64_t)); + } + + // Return data to caller + p_guid_vec->num_guids = num_guids; + p_guid_vec->p_guids = p_guids; + + break; + + } // End of case OP_ROUTE_AMOD_GET_PORTGUID_VEC + + case OP_ROUTE_AMOD_GET_SWITCH_MAP: + { + // Check wire status + if (wstatus == OP_ROUTE_WIRE_STATUS_OK_PARTIAL) + { + rstatus = OP_ROUTE_STATUS_ERROR; + goto cleanup; + } + + // Check for minimum amount of received data + if ((len_recv -= (sizeof(uint16_t) + sizeof(uint16_t))) < 0) + { + rstatus = OP_ROUTE_STATUS_ERROR; + goto cleanup; + } + + // Get num_guids and num_switches + num_guids = op_route_ntoh(&p_data_wire, sizeof(uint16_t)); + num_switches = op_route_ntoh(&p_data_wire, sizeof(uint16_t)); + + if ( (num_switches > OP_ROUTE_MAX_NUM_SWITCHES) || + (num_switches > num_guids) ) + { + rstatus = OP_ROUTE_STATUS_ERROR; + goto cleanup; + } + + // Check for minimum amount of received data + len_data_alloc = num_guids * sizeof(uint16_t); + if ((len_recv -= len_data_alloc ) < 0) + { + rstatus = OP_ROUTE_STATUS_ERROR; + goto cleanup; + } + + if (len_data_alloc) + { + if (!(p_switch_indices = calloc(1, len_data_alloc))) + { + rstatus = OP_ROUTE_STATUS_ERROR; + goto cleanup; + } + + // Get switch map + for ( ix = num_guids, p_switch_indices_2 = p_switch_indices; + ix > 0; p_switch_indices_2++, ix-- ) + { + if ( ( ( *p_switch_indices_2 = + op_route_ntoh(&p_data_wire, sizeof(uint16_t)) ) >= + num_switches ) && (*p_switch_indices_2 != 0xFFFF) ) + { + rstatus = OP_ROUTE_STATUS_ERROR; + goto cleanup; + } + } + } + + // Return data to caller + p_switch_map->num_switches = num_switches; + p_switch_map->p_switch_indices = p_switch_indices; + p_switch_indices = NULL; + + break; + + } // End of case OP_ROUTE_AMOD_GET_SWITCH_MAP + + case OP_ROUTE_AMOD_GET_COST_MATRIX: + { + // Check wire status + if (wstatus == OP_ROUTE_WIRE_STATUS_OK_PARTIAL) + { + rstatus = OP_ROUTE_STATUS_ERROR; + goto cleanup; + } + + // Check for minimum amount of received data + if ((len_recv -= sizeof(uint16_t)) < 0 ) + { + rstatus = OP_ROUTE_STATUS_ERROR; + goto cleanup; + } + + num_switches = op_route_ntoh(&p_data_wire, sizeof(uint16_t)); + if ( ( len_recv -= ( (num_switches * (num_switches - 1)) * + sizeof(uint16_t) / 2 ) ) < 0 ) + { + rstatus = OP_ROUTE_STATUS_ERROR; + goto cleanup; + } + + len_data_alloc = num_switches * num_switches * sizeof(uint16_t); + if (len_data_alloc) + { + if (!(p_cost_matrix_2 = calloc(1, len_data_alloc))) + { + rstatus = OP_ROUTE_STATUS_ERROR; + goto cleanup; + } + + // Get cost_matrix + for ( ix = num_switches * (num_switches - 1) / 2, + ix_2 = num_switches - 1, + p_cost_matrix_r = p_cost_matrix_2 + 1, + p_cost_matrix_l = p_cost_matrix_2 + num_switches; + ix > 0; + p_cost_matrix_r += (num_switches + 1), + p_cost_matrix_l += (num_switches + 1), + ix_2-- ) + + for ( ix_3 = ix_2, + p_cost_matrix_r2 = p_cost_matrix_r, + p_cost_matrix_l2 = p_cost_matrix_l; + (ix_3 > 0) && (ix > 0); + p_cost_matrix_r2++, p_cost_matrix_l2 += num_switches, + ix_3--, ix-- ) + *p_cost_matrix_r2 = *p_cost_matrix_l2 = + (uint16_t)op_route_ntoh(&p_data_wire, sizeof(uint16_t)); + } + + // Return data to caller + *pp_cost_matrix = p_cost_matrix_2; + p_cost_matrix_2 = NULL; + + break; + + } // End of case OP_ROUTE_AMOD_GET_COST_MATRIX + + case OP_ROUTE_AMOD_GET_USE_MATRIX: + { + // Check wire status + if (wstatus == OP_ROUTE_WIRE_STATUS_OK_PARTIAL) + { + rstatus = OP_ROUTE_STATUS_ERROR; + goto cleanup; + } + + // Check for minimum amount of received data + if ( ( len_recv -= ( sizeof(uint16_t) + sizeof(uint8_t) + + sizeof(uint16_t) ) ) < 0 ) + { + rstatus = OP_ROUTE_STATUS_ERROR; + goto cleanup; + } + + // Get multiplier, default use, and number of use elements + use_multiplier = op_route_ntoh(&p_data_wire, sizeof(uint16_t)); + default_use = *p_data_wire++; + num_elements = op_route_ntoh(&p_data_wire, sizeof(uint16_t)); + + // Check for minimum amount of received data + if ( ( len_recv -= ( num_elements * ( sizeof(uint16_t) + + sizeof(uint16_t) + sizeof(uint8_t) ) ) ) < 0 ) + { + rstatus = OP_ROUTE_STATUS_ERROR; + goto cleanup; + } + + len_data_alloc = num_elements * sizeof(struct op_route_use_element); + if (len_data_alloc) + { + if (!(p_use_elements = calloc(1, len_data_alloc))) + { + rstatus = OP_ROUTE_STATUS_ERROR; + goto cleanup; + } + + // Get use elements + for ( ix = num_elements, p_use_elements_2 = p_use_elements; ix > 0; + p_use_elements_2++, ix-- ) + { + temp = op_route_ntoh(&p_data_wire, sizeof(uint16_t)); + p_use_elements_2->bursty = (temp >> 15) & 0x0001; + p_use_elements_2->switch_index = temp & 0x7FFF; + p_use_elements_2->dlid = + op_route_ntoh(&p_data_wire, sizeof(uint16_t)); + p_use_elements_2->use = *p_data_wire++; + } + } + + // Return data to caller + p_use_matrix->default_use = default_use; + p_use_matrix->multiplier = use_multiplier; + p_use_matrix->num_elements = num_elements; + p_use_matrix->p_elements = p_use_elements; + + break; + + } // End of case OP_ROUTE_AMOD_GET_USE_MATRIX + + case OP_ROUTE_AMOD_GET_JOBS: + { + // Check wire status + if (wstatus == OP_ROUTE_WIRE_STATUS_OK_PARTIAL) + { + rstatus = OP_ROUTE_STATUS_ERROR; + goto cleanup; + } + + // Check for minimum amount of received data + if ((len_recv -= sizeof(uint16_t)) < 0) + { + rstatus = OP_ROUTE_STATUS_ERROR; + goto cleanup; + } + + // Get number of jobs + num_jobs = op_route_ntoh(&p_data_wire, sizeof(uint16_t)); + + // Check for minimum amount of received data + if ( ( len_recv -= ( num_jobs * ( sizeof(OP_ROUTE_JOB_ID) + + sizeof(uint64_t) + sizeof(uint16_t) + + OP_ROUTE_MAX_JOB_NAME_LEN + OP_ROUTE_MAX_APP_NAME_LEN + + sizeof(uint64_t) + sizeof(uint64_t) ) ) ) < 0 ) + { + rstatus = OP_ROUTE_STATUS_ERROR; + goto cleanup; + } + + if ((len_data_alloc = num_jobs * sizeof(struct op_route_job_info))) + { + if (!(p_job_info = calloc(1, len_data_alloc))) + { + rstatus = OP_ROUTE_STATUS_ERROR; + goto cleanup; + } + + // Get list of job info + for ( ix = num_jobs, p_job_info_2 = p_job_info; ix > 0; + p_job_info_2++, ix-- ) + { + p_job_info_2->job_id = + op_route_ntoh(&p_data_wire, sizeof(OP_ROUTE_JOB_ID)); + temp = op_route_ntoh(&p_data_wire, sizeof(uint64_t)); + p_job_info_2->time_stamp = temp; + temp = op_route_ntoh(&p_data_wire, sizeof(uint16_t)); + p_job_info_2->routed = (temp >> 1) & 0x0001; + p_job_info_2->has_use = temp & 0x0001; + strncpy( p_job_info_2->params.name, (char *)p_data_wire, + OP_ROUTE_MAX_JOB_NAME_LEN ); + p_data_wire += OP_ROUTE_MAX_JOB_NAME_LEN; + strncpy( p_job_info_2->params.application_name, (char *)p_data_wire, + OP_ROUTE_MAX_APP_NAME_LEN ); + p_data_wire += OP_ROUTE_MAX_APP_NAME_LEN; + p_job_info_2->params.pid = + op_route_ntoh(&p_data_wire, sizeof(uint64_t)); + p_job_info_2->params.uid = + op_route_ntoh(&p_data_wire, sizeof(uint64_t)); + } + } + + // Return data to caller + p_job_list->num_jobs = num_jobs; + p_job_list->p_job_info = p_job_info; + + break; + + } // End of case OP_ROUTE_AMOD_GET_JOBS + + // Invalid attribute modifier + default: + printf("op_route_send_recv_query: invalid AMOD:%d\n", attr_mod); + rstatus = OP_ROUTE_STATUS_ERROR; + + } // End of switch (attr_mod) + +cleanup: + // Deallocate local buffers if necessary + if (p_mad_send) + free(p_mad_send); + if (p_mad_recv) + free(p_mad_recv); + if (p_switch_indices) + free(p_switch_indices); + if (p_cost_matrix_2) + free(p_cost_matrix_2); + + return (rstatus); + +} // End of op_route_send_recv_query() + +/******************************************************************************* + * + * op_route_dump_job_info() + * + * Description: dump job_info structure to console. + * + * Inputs: + * p_title - Pointer to dump title string + * n_indent - Number of spaces to indent + * p_job_info - Pointer to job_info + * + * Outputs: + * job_info data + */ +static void op_route_dump_job_info( char * p_title, + int n_indent, + struct op_route_job_info * p_job_info ) +{ + if (p_job_info) + { + printf( "%*sjob_info(%s): job_id:0x%"PRIX64"\n", n_indent, "", p_title, + p_job_info->job_id ); + printf( "%*s time_stamp:%"PRIu64" %s", n_indent, "", + (uint64_t)p_job_info->time_stamp, ctime(&p_job_info->time_stamp) ); + printf( "%*s route:%u use:%u\n", n_indent, "", p_job_info->routed, + p_job_info->has_use ); + printf( "%*s name:(%s) app:(%s)\n", n_indent, "", + p_job_info->params.name, p_job_info->params.application_name ); + printf( "%*s pid:0x%016"PRIX64" uid:0x%016"PRIX64"\n", n_indent, "", + p_job_info->params.pid, p_job_info->params.uid ); + } + +} // End of op_route_dump_job_info() + +/******************************************************************************* + * + * op_route_dump_job_list() + * + * Description: dump job_list to console. + * + * Inputs: + * p_title - Pointer to dump title string + * n_indent - Number of spaces to indent + * p_job_list - Pointer to job_list + * + * Outputs: + * job_list data + */ +static void op_route_dump_job_list( char * p_title, + int n_indent, + struct op_route_job_list * p_job_list ) +{ + int ix; + struct op_route_job_info * p_job_info; + char bf_title2[81]; + + if (p_job_list) + { + printf( "%*sjob list(%s): num_jobs: %u\n", n_indent, "", p_title, + p_job_list->num_jobs ); + + for ( ix = 0, p_job_info = p_job_list->p_job_info; + (ix < p_job_list->num_jobs) && p_job_info; + p_job_info++, ix++ ) + { + sprintf(bf_title2, "%d", ix); + op_route_dump_job_info(bf_title2, n_indent+2, p_job_info); + } + } + +} // End of op_route_dump_job_list() + + +/******************************************************************************* + * + * GLOBAL FUNCTIONS + */ + +/******************************************************************************* + * + * op_route_dump() + * + * Description: top-level dump function for op_route data structures to console. + * This function calls specific dump functions needed based on calling + * parameters. + * + * Inputs: + * p_title - Pointer to dump title string + * fb_port_handles - Flag to dump port handles table + * p_port_handle - Pointer to OP_ROUTE_PORT_HANDLE + * p_job_id - Pointer to OP_ROUTE_JOB_ID + * p_job_params - Pointer to job parameters + * p_guid_vec - Pointer to portguid_vec + * p_switch_map - Pointer to switch_map + * p_cost_matrix - Pointer to cost_matrix + * p_use_matrix - Pointer to use_matrix + * p_job_info - Pointer to job_info + * p_job_list - Pointer to job_list + * + * Outputs: + * job information + */ +void op_route_dump( char * p_title, + int fb_port_handles, + OP_ROUTE_PORT_HANDLE * p_port_handle, + OP_ROUTE_JOB_ID * p_job_id, + struct op_route_job_parameters * p_job_params, + struct op_route_portguid_vec * p_guid_vec, + struct op_route_switch_map * p_switch_map, + uint16_t * p_cost_matrix, + struct op_route_use_matrix * p_use_matrix, + struct op_route_job_info * p_job_info, + struct op_route_job_list * p_job_list ) +{ + int ix, ix_2, ix_3; + int n_indent = 2; + uint16_t num_switches; + struct param_alloc_port_handle_entry * p_param_entry; + + printf("op_route_dump (%s):\n", p_title); + + if (fb_port_handles) + { + printf( "%*sport handles: alloc:%u inuse: %u\n", n_indent, "", + param_port_handle.num_allocated, param_port_handle.num_used ); + for ( ix = 0, p_param_entry = (struct param_alloc_port_handle_entry *) + param_port_handle.p_params; + ix < param_port_handle.num_allocated; p_param_entry++, ix++ ) + printf( "%*s%d: port_h:0x%"PRIX64" GUID:0x%"PRIX64 + " port_id:%d\n", n_indent+2, "", ix, p_param_entry->port_handle, + p_param_entry->port_guid, p_param_entry->port_id ); + } + + printf("%*sp_porthandle:0x%"PRIX64, n_indent, "", (uint64_t)p_port_handle); + if (p_port_handle) + printf(" porthandle:0x%"PRIX64, (uint64_t)*p_port_handle); + printf("\n"); + + if (p_job_id) + printf("%*sjob_id:0x%"PRIX64"\n", n_indent, "", (uint64_t)*p_job_id); + + if (p_job_params) + { + printf( "%*sjob_parameters: name:(%s) app:(%s)\n", n_indent, "", + p_job_params->name, p_job_params->application_name ); + printf( "%*spid:0x%016"PRIX64" uid:0x%016"PRIX64"\n", + n_indent+2, "", p_job_params->pid, p_job_params->uid ); + } + + if (p_guid_vec) + { + printf("%*sguid_vec: num_guids:%u\n", n_indent, "", p_guid_vec->num_guids); + for (ix = 0; (ix < p_guid_vec->num_guids) && p_guid_vec->p_guids; ix++) + printf( "%*s%5d: 0x%016"PRIX64"\n", n_indent+2, "", ix, + p_guid_vec->p_guids[ix] ); + } + + if (p_switch_map && p_guid_vec) + { + printf( "%*sswitch_map: num_switches:%u (num_guids:%u)\n", n_indent, "", + p_switch_map->num_switches, p_guid_vec->num_guids ); + for ( ix = 0; (ix < p_guid_vec->num_guids) && + p_switch_map->p_switch_indices; ix++ ) + printf( "%*s%5d: %5u\n", n_indent+2, "", ix, + p_switch_map->p_switch_indices[ix] ); + } + + if ( p_cost_matrix && p_switch_map && + ((num_switches = p_switch_map->num_switches)) ) + { + printf( "%*scost_matrix: (num_switches:%u)\n", n_indent, "", + num_switches ); + for (ix = 0; ix < num_switches; ix++) + printf("%*s%4d", ix ? 1 : n_indent+6, "", ix); + printf("\n"); + + for (ix = 0, ix_2 = 0; ix < num_switches; ix++) + { + printf("%*s%4d:", n_indent, "", ix); + for (ix_3 = 0; ix_3 < num_switches; ix_3++) + printf(" %04X", p_cost_matrix[ix_2++]); + printf("\n"); + } + } + + if (p_use_matrix) + { + printf( "%*suse_matrix: num_elements:%u default_use:%u multiplier:%u\n", + n_indent, "", p_use_matrix->num_elements, p_use_matrix->default_use, + p_use_matrix->multiplier ); + for ( ix = 0; (ix < p_use_matrix->num_elements) && + p_use_matrix->p_elements; ix++ ) + printf( "%*s%d: sw_index:%5d dlid:0x%04X use:%u bursty:%u\n", + n_indent+2, "", ix, p_use_matrix->p_elements[ix].switch_index, + p_use_matrix->p_elements[ix].dlid, + p_use_matrix->p_elements[ix].use, + p_use_matrix->p_elements[ix].bursty ); + } + + op_route_dump_job_info(p_title, n_indent, p_job_info); + op_route_dump_job_list(p_title, n_indent, p_job_list); + + +} // End of op_route_dump() + +/******************************************************************************* + * + * op_route_init_param() + * + * Description: + * Initialize the specified parameter structure. + * + * Inputs: + * p_param - Pointer to parameter structure + * size_param - Size of parameter entry + * num_alloc - Num of params in allocation unit + * + * Outputs: + * 0 - Initialization successful + * -1 - Initialization unsuccessful + */ +int op_route_init_param( struct op_route_param_alloc * p_param, + uint32_t size_param, uint32_t num_alloc ) +{ + void * p_alloc; + + if (!p_param || !size_param || !num_alloc) + return (-1); + + if ((p_alloc = calloc(num_alloc, size_param))) + { + p_param->size_param = size_param; + p_param->num_allocated = num_alloc; + p_param->num_used = 0; + p_param->num_alloc = num_alloc; + p_param->p_params = p_alloc; + } + + else + return (-1); + + return (0); + +} // End of op_route_init_param() + +/******************************************************************************* + * + * op_route_free_param() + * + * Description: + * Free parameters for the specified parameter structure. + * + * Inputs: + * p_param - Pointer to parameter structure + * + * Outputs: + * none + */ +void op_route_free_param(struct op_route_param_alloc * p_param) +{ + if (p_param && p_param->p_params) + { + free(p_param->p_params); + p_param->num_allocated = 0; + p_param->num_used = 0; + p_param->p_params = NULL; + } + +} // End of op_route_free_param() + +/******************************************************************************* + * + * op_route_alloc_param() + * + * Description: + * Allocate a block of parameters according to specified parameter pointer. + * + * Inputs: + * p_param - Pointer to parameter structure + * + * Outputs: + * 0 - Allocation successful + * -1 - Allocation unsuccessful + */ +int op_route_alloc_param(struct op_route_param_alloc * p_param) +{ + char * p_alloc; + + if (!p_param) + return (-1); + + if ( ( p_alloc = realloc( p_param->p_params, p_param->size_param * + (p_param->num_allocated + p_param->num_alloc) ) ) ) + { + memset( p_alloc + (p_param->size_param * p_param->num_allocated), 0, + p_param->size_param * p_param->num_alloc ); + p_param->p_params = (struct op_route_param_alloc_entry *)p_alloc; + p_param->num_allocated += p_param->num_alloc; + } + + else + return (-1); + + return (0); + +} // End of op_route_alloc_param() + +/******************************************************************************* + * + * op_route_dump_param() + * + * Description: dump information, as supplied by calling parameters, to console. + * + * Inputs: + * p_title - Pointer to dump title string + * p_param - Pointer to parameter structure + * + * Outputs: + * Allocated parameter information + */ +void op_route_dump_param( char * p_title, + struct op_route_param_alloc * p_param ) +{ + int ix; + struct op_route_param_alloc_entry * p_param_entry; + + printf("op_route_dump_param (%s):\n", p_title); + + if (p_param) + { + printf( " sz_param:%"PRIu64" allocd:%u used:%u alloc:%u p_params:0x%"PRIX64"\n", + p_param->size_param, p_param->num_allocated, p_param->num_used, + p_param->num_alloc, (uint64_t)p_param->p_params ); + + for (ix = 0; ix < p_param->num_allocated; ix++) + { + p_param_entry = (struct op_route_param_alloc_entry *) + ((char *)p_param->p_params + (p_param->size_param * ix)); + printf( " %4d: sz_param:%"PRIu64" sz_data:%"PRIu64" info_param:%" + PRIu64" data64:0x%016"PRIX64"\n", + ix, p_param_entry->size_param, p_param_entry->size_data, + p_param_entry->info_param, + *(uint64_t *)p_param_entry->bf_data ); + } + } + +} // End of op_route_dump_param() + +/******************************************************************************* + * + * op_route_get_status_text() + * + * Description: + * Get a text string corresponding to the specified op_route_status value. + * + * Inputs: + * status - Status value + * + * Outputs: + * status string - Valid status value + * NULL - Invalid status value + */ +extern char * op_route_get_status_text(enum op_route_status status) +{ + switch(status) + { + case OP_ROUTE_STATUS_OK: + return("No Error"); + + case OP_ROUTE_STATUS_OK_PARTIAL: + return("Partial Success"); + + case OP_ROUTE_STATUS_ERROR: + return("General Error"); + + case OP_ROUTE_STATUS_SEND_ERROR: + return("Send Error"); + + case OP_ROUTE_STATUS_RECV_ERROR: + return("Receive Error"); + + case OP_ROUTE_STATUS_TIMEOUT: + return("Response Timeout"); + + case OP_ROUTE_STATUS_INVALID_JOB: + return("Invalid Job ID"); + + case OP_ROUTE_STATUS_INVALID_PARAM: + return("Invalid Parameter"); + + default: + return(NULL); + } // End of switch(status) + +} // End of op_route_get_status_text() + +/******************************************************************************* + * + * op_route_open() + * + * Description: + * Open a routing connection by registering with SD. Each successful open + * creates an OP_ROUTE_PORT_HANDLE, which is entered in the port table, + * and passed back to the caller. + * + * Inputs: + * port - Pointer to opamgt handler + * port_guid - GUID of port on which to register + * p_port_handle - Pointer to OP_ROUTE_PORT_HANDLE + * + * Outputs: + * OP_ROUTE_STATUS_OK - Open successful + * *p_port_handle = OP_ROUTE_PORT_HANDLE + * OP_ROUTE_STATUS_INVALID_PARAM - p_port_handle NULL + * OP_ROUTE_STATUS_ERROR - port_guid already registered + * - Unable to allocate memory + * - Register error + */ +enum op_route_status op_route_open( struct omgt_port * port, + uint64_t port_guid, + OP_ROUTE_PORT_HANDLE * p_port_handle ) +{ + uint32_t ix, ix_2; + int fb_break; + struct param_alloc_port_handle_entry * p_param_entry, * p_param_entry_2; + + if (!p_port_handle) + return (OP_ROUTE_STATUS_INVALID_PARAM); + + // Check for port_guid already in port table + if (!param_port_handle.num_allocated) + if ( op_route_init_param( ¶m_port_handle, + sizeof(struct param_alloc_port_handle_entry), + NUM_PARAM_PORT_HANDLE_ALLOC ) ) + return (OP_ROUTE_STATUS_ERROR); + + for ( ix = param_port_handle.num_allocated, p_param_entry = + (struct param_alloc_port_handle_entry *)param_port_handle.p_params; + ix > 0; p_param_entry++, ix-- ) + if (p_param_entry->port_guid == port_guid) + return (OP_ROUTE_STATUS_ERROR); + + // Find first available port table entry and register + if (param_port_handle.num_used == param_port_handle.num_allocated) + if (op_route_alloc_param(¶m_port_handle)) + return (OP_ROUTE_STATUS_ERROR); + + for ( ix = param_port_handle.num_allocated, p_param_entry = + (struct param_alloc_port_handle_entry *)param_port_handle.p_params; + ix > 0; p_param_entry++, ix-- ) + { + if (!p_param_entry->port_handle) + { + // Get port_handle and check for duplicate + for (fb_break = FALSE; !fb_break; ) + { + p_param_entry->port_handle = op_route_gen_port_handle(); + + for ( ix_2 = param_port_handle.num_allocated, p_param_entry_2 = + (struct param_alloc_port_handle_entry *)param_port_handle.p_params; + ; p_param_entry_2++ ) + { + if ( (ix_2 != ix) && ( p_param_entry->port_handle == + p_param_entry_2->port_handle ) ) + break; // Get another port_handle + + else if (--ix_2 == 0) + { + fb_break = TRUE; + break; + } + } + } + + p_param_entry->port_guid = port_guid; + *p_port_handle = p_param_entry->port_handle; + + // Get ClassPortInfo + if ( op_route_send_recv_query( OP_ROUTE_AMOD_CLASS_INFO, + *p_port_handle, 0, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, port ) == OP_ROUTE_STATUS_OK ) + { + param_port_handle.num_used++; + return (OP_ROUTE_STATUS_OK); + } + + p_param_entry->port_handle = 0; + p_param_entry->port_guid = 0; + p_param_entry->port_id = 0; + + break; + + } // End of if (!!p_param_entry->port_handle) + + } // End of for ( ix = param_port_handle.num_allocated; ix > 0; + + return (OP_ROUTE_STATUS_ERROR); + +} // End of op_route_open() + +/******************************************************************************* + * + * op_route_close() + * + * Description: + * Close a routing connection by deregistering with SD. Remove the + * specified OP_ROUTE_PORT_HANDLE from the port table. + * + * Inputs: + * port_handle - OP_ROUTE_PORT_HANDLE + * + * Outputs: + * OP_ROUTE_STATUS_OK - Close successful + * OP_ROUTE_STATUS_INVALID_PARAM - Invalid OP_ROUTE_PORT_HANDLE + */ +enum op_route_status op_route_close(OP_ROUTE_PORT_HANDLE port_handle) +{ + struct param_alloc_port_handle_entry * p_param_entry; + + if ((p_param_entry = op_route_get_port_handle_entry(port_handle))) + { + p_param_entry->port_handle = 0; + p_param_entry->port_guid = 0; + p_param_entry->port_id = 0; + param_port_handle.num_used--; + + return (OP_ROUTE_STATUS_OK); + } + + return (OP_ROUTE_STATUS_INVALID_PARAM); + +} // End of op_route_close() + +/******************************************************************************* + * + * op_route_create_job() + * + * Description: + * Create a job on the specified port_handle, using the specified name and + * port GUID vector. Upon job creation, supply a job ID, switch map and + * cost matrix. + * + * Inputs: + * port_handle - OP_ROUTE_PORT_HANDLE + * optn_create - Options for create job (see OP_ROUTE_CREATE_JOB_xx) + * p_job_params - Pointer to job parameters + * p_guid_vec - Pointer to portguid_vec + * port - Pointer to opamgt handle + * p_job_id - Pointer to OP_ROUTE_JOB_ID + * p_switch_map - Pointer to switch_map + * pp_cost_matrix - Pointer to pointer to cost_matrix + * + * Outputs: + * OP_ROUTE_STATUS_OK - Create successful + * *p_switch_map->p_switch_indices = + * created switch_map + * **pp_cost_matrix = created cost_matrix + * OP_ROUTE_STATUS_INVALID_PARAM - port_handle NULL + * - p_job_params NULL + * - p_guid_vec NULL + * - p_job_id NULL + * - p_switch_map NULL + * - pp_cost_matrix NULL + * TBD restore next if OP_ROUTE_MIN_NUM_GUIDS raised above 0 + * ( - guid_vec too small ) + * OP_ROUTE_STATUS_ERROR - Error during create + */ +enum op_route_status op_route_create_job( OP_ROUTE_PORT_HANDLE port_handle, + uint16_t optn_create, + struct op_route_job_parameters * p_job_params, + struct op_route_portguid_vec * p_guid_vec, + struct omgt_port * port, + OP_ROUTE_JOB_ID * p_job_id, // output + struct op_route_switch_map * p_switch_map, // output + uint16_t ** pp_cost_matrix ) // output +{ + enum op_route_status rstatus; + + if ( !port_handle || !p_job_params || !p_guid_vec || ( !p_job_id && + !(optn_create & OP_ROUTE_CREATE_JOB_NO_CREATE) ) || + !p_switch_map || !pp_cost_matrix + /* TBD restore if #define changed || (p_guid_vec->num_guids < OP_ROUTE_MIN_NUM_GUIDS) */ ) + return (OP_ROUTE_STATUS_INVALID_PARAM); + + // Query CreateJob record + rstatus = op_route_send_recv_query( OP_ROUTE_AMOD_CREATE_JOB, port_handle, + optn_create, p_job_id, NULL, p_job_params, p_guid_vec, p_switch_map, + pp_cost_matrix, NULL, NULL, port ); + + return (rstatus); + +} // End of op_route_create_job() + +/******************************************************************************* + * + * op_route_complete_job() + * + * Description: + * Complete the specified job on the specified port_handle. + * + * Inputs: + * port_handle - OP_ROUTE_PORT_HANDLE + * p_job_id - Pointer to OP_ROUTE_JOB_ID + * port - Pointer to opamgt port handler + * + * Outputs: + * OP_ROUTE_STATUS_OK - Completion successful + * OP_ROUTE_STATUS_INVALID_PARAM - port_handle NULL + * OP_ROUTE_STATUS_ERROR - Error during completion + */ +enum op_route_status op_route_complete_job( OP_ROUTE_PORT_HANDLE port_handle, + OP_ROUTE_JOB_ID job_id, + struct omgt_port * port ) +{ + enum op_route_status rstatus; + + if (!port_handle) + return (OP_ROUTE_STATUS_INVALID_PARAM); + + // Query CompleteJob record + rstatus = op_route_send_recv_query( OP_ROUTE_AMOD_COMPLETE_JOB, port_handle, + 0, &job_id, NULL, NULL, NULL, NULL, NULL, NULL, NULL, port ); + + return (rstatus); + +} // End of op_route_complete_job() + +/******************************************************************************* + * + * op_route_get_portguid_vec() + * + * Description: + * Get port GUID vector for the specified job on the specified port_handle. + * + * Inputs: + * port_handle - OP_ROUTE_PORT_HANDLE + * job_id - OP_ROUTE_JOB_ID + * port - Pointer to opamgt handle + * p_portguid_vec - Pointer to portguid_vec + * + * Outputs: + * OP_ROUTE_STATUS_OK - Get successful + * *p_portguid_vec = portguid_vec + * OP_ROUTE_STATUS_INVALID_PARAM - port_handle NULL + * - p_guid_vec NULL + * OP_ROUTE_STATUS_ERROR - Error during get + */ +enum op_route_status op_route_get_portguid_vec( OP_ROUTE_PORT_HANDLE port_handle, + OP_ROUTE_JOB_ID job_id, + struct omgt_port * port, + struct op_route_portguid_vec * p_guid_vec ) // output +{ + enum op_route_status rstatus; + + if (!port_handle || !p_guid_vec) + return (OP_ROUTE_STATUS_INVALID_PARAM); + + // Query PortGUID vector record + rstatus = op_route_send_recv_query( OP_ROUTE_AMOD_GET_PORTGUID_VEC, + port_handle, 0, &job_id, NULL, NULL, p_guid_vec, NULL, NULL, NULL, + NULL, port ); + + return (rstatus); + +} // End of op_route_get_portguid_vec() + +/******************************************************************************* + * + * op_route_release_portguid_vec() + * + * Description: + * Release the specified portguid_vec. + * + * Inputs: + * p_guid_vec - Pointer to portguid_vec + * + * Outputs: + * none + */ +void op_route_release_portguid_vec(struct op_route_portguid_vec * p_guid_vec) +{ + if (p_guid_vec && p_guid_vec->p_guids) + { + free(p_guid_vec->p_guids); + p_guid_vec->p_guids = NULL; + } + +} // End of op_route_release_portguid_vec() + +/******************************************************************************* + * + * op_route_get_switch_map() + * + * Description: + * Get switch_map for the specified job on the specified port_handle. + * + * Inputs: + * port_handle - OP_ROUTE_PORT_HANDLE + * job_id - OP_ROUTE_JOB_ID + * port - Pointer to opamgt handle + * p_switch_map - Pointer to switch_map + * + * Outputs: + * OP_ROUTE_STATUS_OK - Get successful + * *p_switch_map = switch_map + * OP_ROUTE_STATUS_INVALID_PARAM - port_handle NULL + * - p_switch_map NULL + * OP_ROUTE_STATUS_ERROR - Error during get + */ +enum op_route_status op_route_get_switch_map( OP_ROUTE_PORT_HANDLE port_handle, + OP_ROUTE_JOB_ID job_id, + struct omgt_port * port, + struct op_route_switch_map * p_switch_map ) // output +{ + enum op_route_status rstatus; + + if (!port_handle || !p_switch_map) + return (OP_ROUTE_STATUS_INVALID_PARAM); + + // Query switch_map record + rstatus = op_route_send_recv_query( OP_ROUTE_AMOD_GET_SWITCH_MAP, + port_handle, 0, &job_id, NULL, NULL, NULL, p_switch_map, NULL, NULL, + NULL, port ); + + return (rstatus); + +} // End of op_route_get_switch_map() + +/******************************************************************************* + * + * op_route_release_switch_map() + * + * Description: + * Release the specified switch_map. + * + * Inputs: + * p_op_route_switch_map - Pointer to switch_map + * + * Outputs: + * none + */ +void op_route_release_switch_map(struct op_route_switch_map * p_switch_map) +{ + if (p_switch_map && p_switch_map->p_switch_indices) + { + free(p_switch_map->p_switch_indices); + p_switch_map->p_switch_indices = NULL; + } + +} // End of op_route_release_switch_map() + +/******************************************************************************* + * + * op_route_get_cost_matrix() + * + * Description: + * Get cost_matrix for the specified job on the specified port_handle. + * + * Inputs: + * port_handle - OP_ROUTE_PORT_HANDLE + * job_id - OP_ROUTE_JOB_ID + * port - Pointer to opamgt handle + * pp_cost_matrix - Pointer to pointer to cost_matrix + * + * Outputs: + * OP_ROUTE_STATUS_OK - Get successful + * **pp_cost_matrix = cost_matrix + * OP_ROUTE_STATUS_INVALID_PARAM - port_handle NULL + * - pp_cost_matrix NULL + * OP_ROUTE_STATUS_ERROR - Error during get + */ +enum op_route_status op_route_get_cost_matrix( OP_ROUTE_PORT_HANDLE port_handle, + OP_ROUTE_JOB_ID job_id, + struct omgt_port * port, + uint16_t ** pp_cost_matrix ) // output +{ + enum op_route_status rstatus; + + if (!port_handle || !pp_cost_matrix) + return (OP_ROUTE_STATUS_INVALID_PARAM); + + // Query cost_matrix record + rstatus = op_route_send_recv_query( OP_ROUTE_AMOD_GET_COST_MATRIX, + port_handle, 0, &job_id, NULL, NULL, NULL, NULL, pp_cost_matrix, NULL, + NULL, port ); + + return (rstatus); + +} // End of op_route_get_cost_matrix() + +/******************************************************************************* + * + * op_route_release_cost_matrix() + * + * Description: + * Release the specified cost_matrix. + * + * Inputs: + * p_cost_matrix - Pointer to cost_matrix + * + * Outputs: + * none + */ +void op_route_release_cost_matrix(uint16_t * p_cost_matrix) +{ + if (p_cost_matrix) + free(p_cost_matrix); + +} // End of op_route_release_cost_matrix() + +/******************************************************************************* + * + * op_route_get_use_matrix() + * + * Description: + * Get use_matrix for the specified job on the specified port_handle. + * + * Inputs: + * port_handle - OP_ROUTE_PORT_HANDLE + * job_id - OP_ROUTE_JOB_ID + * port - Pointer to opamgt handle + * p_use_matrix - Pointer to use_matrix + * + * Outputs: + * OP_ROUTE_STATUS_OK - Get successful + * *p_use_matrix = use_matrix + * OP_ROUTE_STATUS_INVALID_PARAM - port_handle NULL + * - p_use_matrix NULL + * OP_ROUTE_STATUS_ERROR - Error during get + */ +enum op_route_status op_route_get_use_matrix( OP_ROUTE_PORT_HANDLE port_handle, + OP_ROUTE_JOB_ID job_id, + struct omgt_port * port, + struct op_route_use_matrix * p_use_matrix ) +{ + enum op_route_status rstatus; + + if (!port_handle || !p_use_matrix) + return (OP_ROUTE_STATUS_INVALID_PARAM); + + // Query use_matrix record + rstatus = op_route_send_recv_query( OP_ROUTE_AMOD_GET_USE_MATRIX, + port_handle, 0, &job_id, NULL, NULL, NULL, NULL, NULL, p_use_matrix, + NULL, port ); + + return (rstatus); + +} // End of op_route_get_use_matrix() + +/******************************************************************************* + * + * op_route_set_use_matrix() + * + * Description: + * Set use_matrix for the specified job on the specified port_handle. + * + * Inputs: + * port_handle - OP_ROUTE_PORT_HANDLE + * job_id - OP_ROUTE_JOB_ID + * port - Pointer to opamgt handle + * p_use_matrix - Pointer to use_matrix + * + * Outputs: + * OP_ROUTE_STATUS_OK - Set successful + * OP_ROUTE_STATUS_INVALID_PARAM - port_handle NULL + * - p_use_matrix NULL + * OP_ROUTE_STATUS_ERROR - Error during set + */ +enum op_route_status op_route_set_use_matrix( OP_ROUTE_PORT_HANDLE port_handle, + OP_ROUTE_JOB_ID job_id, + struct omgt_port * port, + struct op_route_use_matrix * p_use_matrix ) +{ + enum op_route_status rstatus; + + if (!port_handle || !p_use_matrix) + return (OP_ROUTE_STATUS_INVALID_PARAM); + + // Send set use_matrix record + rstatus = op_route_send_recv_query( OP_ROUTE_AMOD_SET_USE_MATRIX, + port_handle, 0, &job_id, NULL, NULL, NULL, NULL, NULL, p_use_matrix, + NULL, port ); + + return (rstatus); + +} // End of op_route_set_use_matrix() + +/******************************************************************************* + * + * op_route_release_use_matrix() + * + * Description: + * Release the specified use_matrix. + * + * Inputs: + * p_use_matrix - Pointer to use_matrix + * + * Outputs: + * none + */ +void op_route_release_use_matrix(struct op_route_use_matrix * p_use_matrix) +{ + if (p_use_matrix && p_use_matrix->p_elements) + { + free(p_use_matrix->p_elements); + p_use_matrix->p_elements = NULL; + } + +} // End of op_route_release_use_matrix() + +/******************************************************************************* + * + * op_route_get_job_list() + * + * Description: + * Get a list of created jobs on the specified port_handle. + * + * Inputs: + * port_handle - OP_ROUTE_PORT_HANDLE + * port - Pointer to opamgt handle + * p_job_list - Pointer to job list (array of job_info) + * + * Outputs: + * OP_ROUTE_STATUS_OK - Get successful + * *p_job_list = job_list + * OP_ROUTE_STATUS_ERROR - Error during get + */ +enum op_route_status op_route_get_job_list( OP_ROUTE_PORT_HANDLE port_handle, + struct omgt_port * port, + struct op_route_job_list * p_job_list) // output +{ + enum op_route_status rstatus; + + if (!port_handle || !p_job_list) + return (OP_ROUTE_STATUS_INVALID_PARAM); + + // Query JobList record + rstatus = op_route_send_recv_query( OP_ROUTE_AMOD_GET_JOBS, port_handle, + 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, p_job_list, port ); + + return (rstatus); + +} // End of op_route_get_job_list() + +/******************************************************************************* + * + * op_route_release_job_list() + * + * Description: + * Release the specified job_list. + * + * Inputs: + * p_job_list - Pointer to job_list + * + * Outputs: + * none + */ +void op_route_release_job_list(struct op_route_job_list * p_job_list) +{ + if (p_job_list && p_job_list->p_job_info) + { + free(p_job_list->p_job_info); + p_job_list->p_job_info = NULL; + } + +} // End of op_route_release_job_list() + +/******************************************************************************* + * + * op_route_poll_ready() + * + * Description: + * Poll for the status of the specified job on the specified port_handle. + * + * Inputs: + * port_handle - OP_ROUTE_PORT_HANDLE + * job_id - OP_ROUTE_JOB_ID + * port - Pointer to opamgt handle + * p_job_status - Pointer to job status + * + * Outputs: + * OP_ROUTE_STATUS_OK - Poll successful + * *p_job_status = job status + * OP_ROUTE_STATUS_INVALID_PARAM - port_handle invalid + * - p_job_status NULL + * OP_ROUTE_STATUS_ERROR - Poll unsuccessful + */ +enum op_route_status op_route_poll_ready( OP_ROUTE_PORT_HANDLE port_handle, + OP_ROUTE_JOB_ID job_id, + struct omgt_port * port, + enum op_route_job_status * p_job_status ) +{ + enum op_route_status rstatus; + + if (!port_handle || !p_job_status) + return (OP_ROUTE_STATUS_INVALID_PARAM); + + // Query PollReady record + rstatus = op_route_send_recv_query( OP_ROUTE_AMOD_POLL_READY, port_handle, + 0, &job_id, p_job_status, NULL, NULL, NULL, NULL, NULL, NULL, port ); + + return (rstatus); + +} // End of op_route_poll_ready() + + +// End of file + diff --git a/opasadb/lib/route/opasadb_route.h b/opasadb/lib/route/opasadb_route.h new file mode 100644 index 0000000..d3518dd --- /dev/null +++ b/opasadb/lib/route/opasadb_route.h @@ -0,0 +1,268 @@ +/* BEGIN_ICS_COPYRIGHT2 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT2 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + + +#ifndef _OPA_SA_DB_ROUTE_H +#define _OPA_SA_DB_ROUTE_H + + +/******************************************************************************* + * + * INCLUDES + */ + +#include // type definitions + + +#ifdef __cplusplus +extern "C" { +#endif + + +/******************************************************************************* + * + * DEFINES + */ + +// Constants + +// Max number of port GUIDs in a job (LID values 0x0001-0xBFFF) +#define OP_ROUTE_MAX_GUIDS 49151 + +// Max number of switch indices in a job (index values 0x0000-0x7FFF) +// switch_index is 15 bits in struct op_route_use_element) +#define OP_ROUTE_MAX_SWITCHES 32768 + +// Max number of created jobs (num_jobs is 16 bits in struct op_route_job_list) +#define OP_ROUTE_MAX_JOBS 65535 + +// Max number of chars in names +#define OP_ROUTE_MAX_JOB_NAME_LEN 64 +#define OP_ROUTE_MAX_APP_NAME_LEN 64 + +// Create Job options +#define OP_ROUTE_CREATE_JOB_NORMAL 0x0000 // No options +#define OP_ROUTE_CREATE_JOB_NO_CREATE 0x0001 // Don't create job + +// Function call return status +enum op_route_status +{ + OP_ROUTE_STATUS_OK = 0, // success + OP_ROUTE_STATUS_OK_PARTIAL, // success w/exception + OP_ROUTE_STATUS_ERROR, // general failure + OP_ROUTE_STATUS_SEND_ERROR, // send failure + OP_ROUTE_STATUS_RECV_ERROR, // recv failure: bad response status + OP_ROUTE_STATUS_TIMEOUT, // recv failure: timeout + OP_ROUTE_STATUS_INVALID_JOB, // invalid job_id + OP_ROUTE_STATUS_INVALID_PARAM // invalid parameter +}; + +// Job status +enum op_route_job_status +{ + OP_ROUTE_JOB_STATUS_READY = 0, + OP_ROUTE_JOB_STATUS_NOT_READY +}; + +// PORT_HANDLE: handle for a connection to an HFI port +typedef uint64_t OP_ROUTE_PORT_HANDLE; + +// JOB_ID: identifier for a created job +typedef uint64_t OP_ROUTE_JOB_ID; + +// op_route_job_parameters: contains (application) parameters for a job +struct op_route_job_parameters +{ + // name associated with job + char name[OP_ROUTE_MAX_JOB_NAME_LEN + 1]; + // name associated with application + char application_name[OP_ROUTE_MAX_APP_NAME_LEN + 1]; + uint64_t pid; // process ID + uint64_t uid; // unique ID for job +}; + +// op_route_job_info: contains information about a job, including job_parameters +struct op_route_job_info +{ + OP_ROUTE_JOB_ID job_id; // unique (SM-assigned) ID for job + time_t time_stamp; // job start time stamp + uint16_t reserved : 14; // reserved flags + uint16_t routed : 1; // TRUE: job's routing complete + uint16_t has_use : 1; // TRUE: use matrix associated with job + struct op_route_job_parameters params; // job creation parameters +}; + +// op_route_job_list: contains list of all jobs for an OP_ROUTE_PORT_HANDLE +struct op_route_job_list +{ + uint16_t num_jobs; // Number of jobs in job_list + struct op_route_job_info * p_job_info; // array of job_list +}; + +// op_route_portguid_vec: vector (array) of HFI port GUIDs in a job. +struct op_route_portguid_vec +{ + uint16_t num_guids; // number of port GUIDs in vector + uint64_t * p_guids; // array of port GUIDs +}; + +/* switch_map: map (array) of switch indices associated with a job. Switch + * indices are assigned by the Subnet Manager as a reference to each edge + * switch in a job and range from 0 to num_switches - 1. Each + * switch_indices[n] entry provides the switch index for the switch + * associated with portguid_vec.guids[n]. The number of switch_indices + * entries in switch_map is the same as the number of port GUID entries + * in portguid_vec. + */ +struct op_route_switch_map +{ + uint16_t num_switches; // number of switches in map + uint16_t * p_switch_indices; // array of switch indices for port GUIDs +}; + +/* cost_matrix: matrix (table) of cost values for a job. cost_matrix is two + * dimensional, with source-switch index as the horizontal axis and + * dest-switch as the vertical axis. Each cost value represents the cost + * to use the fabric from source-switch to dest-switch. Cost values take + * into account link speed, link width and hop count, and are comparable + * between jobs. cost_matrix is stored, row-major order, as an array of + * cost values. + */ +// uint16_t * cost_matrix; + +/* use_matrix: matrix (table) of use values for a job. use_matrix is two + * dimensional, with switch index and DLID as the axis variables. Each use + * value represents the use that the corresponding switch-DLID combination + * is expected to make of the fabric. Use values are relative within a + * job as 8-bit values, but when multiplied by multiplier become comparable + * between jobs. + * + * use_matrix is expected to have most use values at a default value + * default_use. Only exceptions to this value are specified explicitly. + * Therefore use_matrix is stored as an array of elements for the + * explicit (non-default) values. Each element contains the corresponding + * switch_index and DLID values and the use value; a "bursty" flag is also + * included to indicate switch_index-DLID combinations whose use could + * experience temporary, significant change from a "sustained" condition. + */ +struct op_route_use_element +{ + uint16_t bursty : 1; // TRUE: bursty, otherwise sustained + uint16_t switch_index : 15; // switch index of the use element + uint16_t dlid; // DLID of the use element + uint8_t use; // (relative) value of the use element +}; + +struct op_route_use_matrix +{ + uint8_t default_use; // default use value + uint16_t multiplier; // use value multiplier + uint16_t num_elements; // number of use_matrix elements + struct op_route_use_element * p_elements; // use elements, 1 per switch-DLID +}; + + +/******************************************************************************* + * + * FUNCTION PROTOTYPES + */ + +extern enum op_route_status op_route_open( struct omgt_port * port, + uint64_t port_guid, + OP_ROUTE_PORT_HANDLE * p_port_handle ); // output + +extern enum op_route_status op_route_close(OP_ROUTE_PORT_HANDLE port_handle); + +extern enum op_route_status op_route_create_job( OP_ROUTE_PORT_HANDLE port_handle, + uint16_t optn_create, + struct op_route_job_parameters * p_job_params, + struct op_route_portguid_vec * p_guid_vec, + struct omgt_port * port, + OP_ROUTE_JOB_ID * p_job_id, // output + struct op_route_switch_map * p_switch_map, // output + uint16_t ** pp_cost_matrix ); // output + +extern enum op_route_status op_route_complete_job( OP_ROUTE_PORT_HANDLE port_handle, + OP_ROUTE_JOB_ID job_id, + struct omgt_port * port ); + +extern enum op_route_status op_route_get_portguid_vec( OP_ROUTE_PORT_HANDLE port_handle, + OP_ROUTE_JOB_ID job_id, + struct omgt_port * port, + struct op_route_portguid_vec * p_guid_vec ); // output + +extern void op_route_release_portguid_vec(struct op_route_portguid_vec * p_guid_vec); + +extern enum op_route_status op_route_get_switch_map( OP_ROUTE_PORT_HANDLE port_handle, + OP_ROUTE_JOB_ID job_id, + struct omgt_port * port, + struct op_route_switch_map * p_switch_map ); // output + +extern void op_route_release_switch_map(struct op_route_switch_map * p_switch_map); + +extern enum op_route_status op_route_get_cost_matrix( OP_ROUTE_PORT_HANDLE port_handle, + OP_ROUTE_JOB_ID job_id, + struct omgt_port * port, + uint16_t ** pp_cost_matrix ); // output + +extern void op_route_release_cost_matrix(uint16_t * p_cost_matrix); + +extern enum op_route_status op_route_get_use_matrix( OP_ROUTE_PORT_HANDLE port_handle, + OP_ROUTE_JOB_ID job_id, + struct omgt_port * port, + struct op_route_use_matrix * p_use_matrix ); // output + +extern enum op_route_status op_route_set_use_matrix( OP_ROUTE_PORT_HANDLE port_handle, + OP_ROUTE_JOB_ID job_id, + struct omgt_port * port, + struct op_route_use_matrix * p_use_matrix ); + +extern void op_route_release_use_matrix(struct op_route_use_matrix * p_use_matrix); + +extern enum op_route_status op_route_get_job_list( OP_ROUTE_PORT_HANDLE port_handle, + struct omgt_port * port, + struct op_route_job_list * p_job_list); // output + +extern void op_route_release_job_list(struct op_route_job_list * p_job_list); + +extern enum op_route_status op_route_poll_ready( OP_ROUTE_PORT_HANDLE port_handle, + OP_ROUTE_JOB_ID job_id, + struct omgt_port * port, + enum op_route_job_status * p_job_status ); + +extern char * op_route_get_status_text(enum op_route_status status); + +#ifdef __cplusplus +}; +#endif + +#endif /* _OPA_SA_DB_ROUTE_H */ + diff --git a/opasadb/lib/route/opasadb_route2.h b/opasadb/lib/route/opasadb_route2.h new file mode 100644 index 0000000..fcec436 --- /dev/null +++ b/opasadb/lib/route/opasadb_route2.h @@ -0,0 +1,150 @@ +/* BEGIN_ICS_COPYRIGHT7 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT7 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + + +#ifndef _OPA_SA_DB_ROUTE2_H +#define _OPA_SA_DB_ROUTE2_H + + +/******************************************************************************* + * + * INCLUDES + */ + +#include "opasadb_route.h" +#include "ib_sd.h" // opasadb_route built on ib_sd layer + + +#ifdef __cplusplus +extern "C" { +#endif + + +/******************************************************************************* + * + * DEFINES + */ + +// Attribute IDs + +// Attribute Modifiers +#define OP_ROUTE_AMOD_CLASS_INFO 0x0001 +#define OP_ROUTE_AMOD_CREATE_JOB 0x0002 +#define OP_ROUTE_AMOD_SET_USE_MATRIX 0x0003 +#define OP_ROUTE_AMOD_POLL_READY 0x0004 +#define OP_ROUTE_AMOD_COMPLETE_JOB 0x0005 +#define OP_ROUTE_AMOD_GET_PORTGUID_VEC 0x0006 +#define OP_ROUTE_AMOD_GET_SWITCH_MAP 0x0007 +#define OP_ROUTE_AMOD_GET_COST_MATRIX 0x0008 +#define OP_ROUTE_AMOD_GET_USE_MATRIX 0x0009 +#define OP_ROUTE_AMOD_GET_JOBS 0x000A + +#define OP_ROUTE_MIN_BASE_VERSION 1 // Min base for operation +#define OP_ROUTE_MIN_SA_CLASS_VERSION 2 // Min SA class for operation +#define OP_ROUTE_MIN_JM_CLASS_VERSION 1 // Min JM class for operation +// TBD change if minimum raised above 0 +#define OP_ROUTE_MIN_NUM_GUIDS 0 // Min number of GUIDS +#define OP_ROUTE_MAX_NUM_SWITCHES 32768 // Max number of switches + +// Configuration parameters +#define NUM_PARAM_PORT_HANDLE_ALLOC 8 // Num port table entries to alloc + +// Protocol wire status +enum op_route_wire_status +{ + OP_ROUTE_WIRE_STATUS_OK = 0, // success + OP_ROUTE_WIRE_STATUS_OK_PARTIAL, // success w/exception + OP_ROUTE_WIRE_STATUS_ERROR, // general failure + OP_ROUTE_WIRE_STATUS_INVALID_JOB // invalid job_id +}; + +// Parameter allocation structures +// Replicated (array) structure for an allocated parameter; this structure +// is a model for parameter-specific structures +struct op_route_param_alloc_entry +{ + uint64_t size_param; // Size of param (bf_data) allocated (bytes) + uint64_t size_data; // Size of param (bf_data) in use (bytes) + uint64_t info_param; // Info about param (param specific) + // NOTE: previous uint64_t ensures uint64_t alignment of bf_data + char bf_data[]; // Allocated param buffer +}; + +// Base (root) structure for an allocated parameter +struct op_route_param_alloc +{ + size_t size_param; // Size of param entry + uint16_t num_allocated; // Num params allocated + uint16_t num_used; // Num params in use + uint16_t num_alloc; // Num params in allocation unit + // Pointer to allocated parameters + struct op_route_param_alloc_entry * p_params; +}; + + +/******************************************************************************* + * + * FUNCTION PROTOTYPES + */ + +extern void op_route_dump( char * p_title, + int fb_port_handles, + OP_ROUTE_PORT_HANDLE * p_port_handle, + OP_ROUTE_JOB_ID * p_job_id, + struct op_route_job_parameters * p_job_params, + struct op_route_portguid_vec * p_guid_vec, + struct op_route_switch_map * p_switch_map, + uint16_t * p_cost_matrix, + struct op_route_use_matrix * p_use_matrix, + struct op_route_job_info * p_job_info, + struct op_route_job_list * p_job_list ); + +extern int op_route_init_param( struct op_route_param_alloc * p_param, + uint32_t size_param, + uint32_t num_alloc ); + +extern void op_route_free_param(struct op_route_param_alloc * p_param); + +extern int op_route_alloc_param(struct op_route_param_alloc * p_param); + +extern void op_route_dump_param( char * p_title, + struct op_route_param_alloc * p_param ); + +// DEBUG temporary +extern void op_route_put_fvdebug(uint32_t fvDebug); + + +#ifdef __cplusplus +}; +#endif + +#endif /* _OPA_SA_DB_ROUTE2_H */ + diff --git a/opasadb/opasadb.spec b/opasadb/opasadb.spec new file mode 100644 index 0000000..9a5fd5c --- /dev/null +++ b/opasadb/opasadb.spec @@ -0,0 +1,102 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +#[ICS VERSION STRING: unknown] +Name: opasadb +Version: 1.0.0 +Release: 1%{?dist} +Summary: opasadb library and tools + +Group: Applications/System +License: Copyright (c) 2014 Intel Corporation All Rights Reserved +Source0: %{name}-%{version}.tar.gz +BuildRoot: %{_builddir} +Vendor: Intel Corporation +AutoReqProv: no + +%description +The %{name} is package that contains a library for easy access to the shared +memory SA cache exported by distributed SA and a few tools that provide +the capability to stress test the distributed SA, dump and query the SA +cache, and generate jobs. + +%package devel +Summary: Headers file needed when building apps to use libopasadb. +Requires: %{name} = %{version}-%{release} +Group: System Environment/Daemons + +%description devel +To make use of the shared-memory SA cache, an application can call the +functions exported by the libopasadb library. + +%prep +%setup -q -n %{name}-%{version} + +%build +#nothing to do because we copy pre-built files into SOURCES + +%install +# simply copy the files +mkdir -p ${RPM_BUILD_ROOT}%{_bindir} +cp -pr opa_osd_dump ${RPM_BUILD_ROOT}%{_bindir}/ +cp -pr opa_osd_exercise ${RPM_BUILD_ROOT}%{_bindir}/ +cp -pr opa_osd_exercise_test.pl ${RPM_BUILD_ROOT}%{_bindir}/ +cp -pr opa_osd_perf ${RPM_BUILD_ROOT}%{_bindir}/ +cp -pr build_table.pl ${RPM_BUILD_ROOT}%{_bindir}/ +cp -pr opa_osd_query ${RPM_BUILD_ROOT}%{_bindir}/ +mkdir -p ${RPM_BUILD_ROOT}%{_libdir} +cp -pr lib%{name}.so.%{version} ${RPM_BUILD_ROOT}%{_libdir}/ +mkdir -p ${RPM_BUILD_ROOT}%{_includedir}/infiniband +cp -pr opasadb_path.h ${RPM_BUILD_ROOT}%{_includedir}/infiniband/ +cp -pr opasadb_route.h ${RPM_BUILD_ROOT}%{_includedir}/infiniband/ +cp -pr opasadb_route2.h ${RPM_BUILD_ROOT}%{_includedir}/infiniband/ + +%clean +rm -rf $RPM_BUILD_ROOT + +%files +%defattr(-,root,root,-) +%doc README +%{_libdir}/lib*.* +%{_bindir}/opa_osd_dump +%{_bindir}/opa_osd_exercise +%{_bindir}/opa_osd_exercise_test.pl +%{_bindir}/opa_osd_perf +%{_bindir}/build_table.pl +%{_bindir}/opa_osd_query + +%files devel +%defattr(-,root,root,-) +%{_includedir}/infiniband/opasadb_path.h +%{_includedir}/infiniband/opasadb_route.h +%{_includedir}/infiniband/opasadb_route2.h + + + + diff --git a/opasadb/path_tools/Makefile b/opasadb/path_tools/Makefile new file mode 100644 index 0000000..a6eaae5 --- /dev/null +++ b/opasadb/path_tools/Makefile @@ -0,0 +1,168 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** +# Makefile for opasadb + +# Include Make Control Settings +include $(TL_DIR)/$(PROJ_FILE_DIR)/Makesettings.project + +#=============================================================================# +# Definitions: +#-----------------------------------------------------------------------------# + +# Name of SubProjects +DS_SUBPROJECTS = +# name of executable or downloadable image +EXECUTABLE = +# list of sub directories to build +DIRS = \ + $(shell ls -d exercise 2>/dev/null) \ + $(shell ls -d query 2>/dev/null) \ + $(shell ls -d cache 2>/dev/null) \ + $(shell ls -d dump 2>/dev/null) \ + $(shell ls -d perf 2>/dev/null) \ + $(shell ls -d query_many 2>/dev/null) \ + $(shell ls -d load 2>/dev/null) \ + # Add more directories here +# C files (.c) +CFILES = \ + # Add more c files here +# C++ files (.cpp) +CCFILES = \ + # Add more cpp files here +# lex files (.lex) +LFILES = \ + # Add more lex files here +# archive library files (basename, $ARFILES will add MOD_LIB_DIR/prefix and suffix) +LIBFILES = +# Windows Resource Files (.rc) +RSCFILES = +# Windows IDL File (.idl) +IDLFILE = +# Windows Linker Module Definitions (.def) file for dll's +DEFFILE = +# targets to build during INCLUDES phase (add public includes here) +INCLUDE_TARGETS = \ + # Add more h hpp files here +# Non-compiled files +MISC_FILES = +# all source files +SOURCES = $(CFILES) $(CCFILES) $(LFILES) $(RSCFILES) $(IDLFILE) +# Source files to include in DSP File +DSP_SOURCES = $(INCLUDE_TARGETS) $(SOURCES) $(MISC_FILES) \ + $(RSCFILES) $(DEFFILE) $(MAKEFILE) +# all object files +OBJECTS = $(CFILES:.c=$(OBJ_SUFFIX)) $(CCFILES:.cpp=$(OBJ_SUFFIX)) \ + $(LFILES:.lex=$(OBJ_SUFFIX)) \ + # Add more object files here +RSCOBJECTS = $(RSCFILES:.rc=$(RES_SUFFIX)) +# targets to build during LIBS phase +LIB_TARGETS_IMPLIB = +LIB_TARGETS_ARLIB = +LIB_TARGETS_EXP = $(LIB_TARGETS_IMPLIB:$(ARLIB_SUFFIX)=$(EXP_SUFFIX)) +LIB_TARGETS_MISC = +# targets to build during CMDS phase +#SHLIB_VERSION = +#CMD_TARGETS_SHLIB = +CMD_TARGETS_EXE = $(EXECUTABLE) +CMD_TARGETS_MISC = +# files to remove during clean phase +CLEAN_TARGETS_MISC = +CLEAN_TARGETS = $(OBJECTS) $(RSCOBJECTS) $(IDL_TARGETS) $(CLEAN_TARGETS_MISC) +# other files to remove during clobber phase +CLOBBER_TARGETS_MISC= +# sub-directory to install to within bin +BIN_SUBDIR = +# sub-directory to install to within include +INCLUDE_SUBDIR = + +# Additional Settings +#CLOCALDEBUG = User defined C debugging compilation flags [Empty] +#CCLOCALDEBUG = User defined C++ debugging compilation flags [Empty] +# User defined C flags for compiling +# User defined C++ flags for compiling +#CCLOCAL = +#BSCLOCAL = User flags for Browse File Builder [Empty] +#DEPENDLOCAL = user defined makedepend flags [Empty] +#LINTLOCAL = User defined lint flags [Empty] +# User include directories to search for C/C++ headers +LOCAL_INCLUDE_DIRS = +#LDLOCAL = User defined C flags for linking [Empty] +#IMPLIBLOCAL = User flags for Object Lirary Manager [Empty] +#MIDLLOCAL = User flags for IDL compiler [Empty] +#RSCLOCAL = User flags for resource compiler [Empty] +# User libraries to include in dependencies +LOCALDEPLIBS = +# User libraries to use when linking (in addition to LOCALDEPLIBS) +#LOCALLIBS = $(OPENIB_USER_LIBS) $(IBACCESS_USER_LIBS) +LOCALLIBS = ibverbs +# User library directories for libpaths +#LOCAL_LIB_DIRS = $(OPENIB_USER_LIB_DIRS) $(IBACCESS_USER_LIB_DIRS) +LOCAL_LIB_DIRS = + +# Include Make Rules definitions and rules +include $(TL_DIR)/IbaTools/Makerules.module + +#=============================================================================# +# Overrides: +#-----------------------------------------------------------------------------# +# C++ optimization flags, default lets build config decide +#CCOPT = +# C optimization flags, default lets build config decide +#COPT = -fPIC +#SUBSYSTEM = Subsystem to build for (none, console or windows) [none] +# (Windows Only) +#USEMFC = How Windows MFC should be used (none, static, shared, no_mfc) [none] +# (Windows Only) +#=============================================================================# + +#=============================================================================# +# Rules: +#-----------------------------------------------------------------------------# +# process Sub-directories +include $(TL_DIR)/Makerules/Maketargets.toplevel + +# build cmds and libs +include $(TL_DIR)/Makerules/Maketargets.build + +# install for includes, libs and cmds phases +include $(TL_DIR)/Makerules/Maketargets.install + +# install for stage phase +#include $(TL_DIR)/Makerules/Maketargets.stage +STAGE:: + $(VS)$(STAGE_INSTALL) $(STAGE_INSTALL_DIR_OPT) $(PROJ_STAGE_OPA_SA_DB_DIR) $(EXECUTABLE) + +# Unit test execution +#include $(TL_DIR)/Makerules/Maketargets.runtest + +#=============================================================================# + +#=============================================================================# +# DO NOT DELETE THIS LINE -- make depend depends on it. +#=============================================================================# diff --git a/opasadb/path_tools/cache/Makefile b/opasadb/path_tools/cache/Makefile new file mode 100644 index 0000000..769bad7 --- /dev/null +++ b/opasadb/path_tools/cache/Makefile @@ -0,0 +1,163 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** +# Makefile for opasadb/route_tools + +# Include Make Control Settings +include $(TL_DIR)/$(PROJ_FILE_DIR)/Makesettings.project + +#=============================================================================# +# Definitions: +#-----------------------------------------------------------------------------# + +# Name of SubProjects +DS_SUBPROJECTS = +# name of executable or downloadable image +EXECUTABLE = $(BUILDDIR)/opp_cache_test$(EXE_SUFFIX) +# list of sub directories to build +DIRS = +# C files (.c) +CFILES = \ + mydumppath.c \ + opp_cache_test.c \ + # Add more c files here +# C++ files (.cpp) +CCFILES = \ + # Add more cpp files here +# lex files (.lex) +LFILES = \ + # Add more lex files here +# archive library files (basename, $ARFILES will add MOD_LIB_DIR/prefix and suffix) +LIBFILES = +# Windows Resource Files (.rc) +RSCFILES = +# Windows IDL File (.idl) +IDLFILE = +# Windows Linker Module Definitions (.def) file for dll's +DEFFILE = +# targets to build during INCLUDES phase (add public includes here) +INCLUDE_TARGETS = \ + # Add more h hpp files here +# Non-compiled files +MISC_FILES = +# all source files +SOURCES = $(CFILES) $(CCFILES) $(LFILES) $(RSCFILES) $(IDLFILE) +# Source files to include in DSP File +DSP_SOURCES = $(INCLUDE_TARGETS) $(SOURCES) $(MISC_FILES) \ + $(RSCFILES) $(DEFFILE) $(MAKEFILE) +# all object files +OBJECTS = $(CFILES:.c=$(OBJ_SUFFIX)) $(CCFILES:.cpp=$(OBJ_SUFFIX)) \ + $(LFILES:.lex=$(OBJ_SUFFIX)) \ + # Add more object files here +RSCOBJECTS = $(RSCFILES:.rc=$(RES_SUFFIX)) +# targets to build during LIBS phase +LIB_TARGETS_IMPLIB = +LIB_TARGETS_ARLIB = +LIB_TARGETS_EXP = $(LIB_TARGETS_IMPLIB:$(ARLIB_SUFFIX)=$(EXP_SUFFIX)) +LIB_TARGETS_MISC = +# targets to build during CMDS phase +SHLIB_VERSION = +CMD_TARGETS_SHLIB = +CMD_TARGETS_EXE = $(EXECUTABLE) +CMD_TARGETS_MISC = +# files to remove during clean phase +CLEAN_TARGETS_MISC = +CLEAN_TARGETS = $(OBJECTS) $(RSCOBJECTS) $(IDL_TARGETS) $(CLEAN_TARGETS_MISC) +# other files to remove during clobber phase +CLOBBER_TARGETS_MISC= +# sub-directory to install to within bin +BIN_SUBDIR = +# sub-directory to install to within include +INCLUDE_SUBDIR = + +# Additional Settings +#CLOCALDEBUG = User defined C debugging compilation flags [Empty] +#CCLOCALDEBUG = User defined C++ debugging compilation flags [Empty] +# User defined C flags for compiling +# User defined C++ flags for compiling +#CCLOCAL = +#BSCLOCAL = User flags for Browse File Builder [Empty] +#DEPENDLOCAL = user defined makedepend flags [Empty] +#LINTLOCAL = User defined lint flags [Empty] +# User include directories to search for C/C++ headers +LOCAL_INCLUDE_DIRS = .. +#LDLOCAL = User defined C flags for linking [Empty] +#IMPLIBLOCAL = User flags for Object Lirary Manager [Empty] +#MIDLLOCAL = User flags for IDL compiler [Empty] +#RSCLOCAL = User flags for resource compiler [Empty] +# User libraries to include in dependencies +LOCALDEPLIBS = IbPrint $(IBACCESS_USER_LIBS) opamgt-priv +# User libraries to use when linking (in addition to LOCALDEPLIBS) +# opasadb is a shared library, not needed in LOCALDEPLIBS +LOCALLIBS = $(OPENIB_USER_LIBS) opasadb rt +# User library directories for libpaths +LOCAL_LIB_DIRS = $(OPENIB_USER_LIB_DIRS) $(IBACCESS_USER_LIB_DIRS) + +CLOCAL = $(CPIE) + +# Include Make Rules definitions and rules +include $(TL_DIR)/IbaTools/Makerules.module + +#=============================================================================# +# Overrides: +#-----------------------------------------------------------------------------# +# C++ optimization flags, default lets build config decide +#CCOPT = +# C optimization flags, default lets build config decide +COPT = -g -D_GNU_SOURCE -Wall -fPIE +#SUBSYSTEM = Subsystem to build for (none, console or windows) [none] +# (Windows Only) +#USEMFC = How Windows MFC should be used (none, static, shared, no_mfc) [none] +# (Windows Only) +#=============================================================================# + +#=============================================================================# +# Rules: +#-----------------------------------------------------------------------------# +# process Sub-directories +include $(TL_DIR)/Makerules/Maketargets.toplevel + +# build cmds and libs +include $(TL_DIR)/Makerules/Maketargets.build + +# install for includes, libs and cmds phases +include $(TL_DIR)/Makerules/Maketargets.install + +# install for stage phase +#include $(TL_DIR)/Makerules/Maketargets.stage +STAGE:: +# $(VS)$(STAGE_INSTALL) $(STAGE_INSTALL_DIR_OPT) $(PROJ_STAGE_OPA_SA_DB_DIR) $(EXECUTABLE) + +# Unit test execution +#include $(TL_DIR)/Makerules/Maketargets.runtest + +#=============================================================================# + +#=============================================================================# +# DO NOT DELETE THIS LINE -- make depend depends on it. +#=============================================================================# diff --git a/opasadb/path_tools/cache/README b/opasadb/path_tools/cache/README new file mode 100644 index 0000000..d4ede08 --- /dev/null +++ b/opasadb/path_tools/cache/README @@ -0,0 +1,18 @@ +This program is meant to aid in developing and debugging the shared memory +interface between the QLogic Distributed SA (Discovery) and the opasadb user +library. It has 3 modes. + +In server mode, the tool exercises the creation portion of the interface, +by reading a formatted table of fabric information (see buildtable.pl) and +creating a set of tables to match. If the number of passes is greater than +1, server mode will do this repeatedly, with a one second delay between +passes, to simulate a changing fabric. + +In dump mode, the tool reads the current shared memory interface and dumps the +contents to the specified file. Note that the resulting file could be huge if +the hash tables are "full sized". (See HASH_TABLE_SIZE in opasadb_path_private.h) + +In client mode, the tool reads the same formatted file the server mode does, +but then randomly picks records from the file and queries for them. It will +return an error if the record that was returned does not match the record +loaded from the file. diff --git a/opasadb/path_tools/cache/build_table.pl b/opasadb/path_tools/cache/build_table.pl new file mode 100755 index 0000000..2738479 --- /dev/null +++ b/opasadb/path_tools/cache/build_table.pl @@ -0,0 +1,89 @@ +#!/usr/bin/perl +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +#[ICS VERSION STRING: unknown] +# +# To use this tool: +# +# /sbin/opasaquery -o path | ./build_table.pl >gidtable +# + +use strict; +use Data::Dumper; + +sub trim($) +{ + my $scratch = @_[0]; + + $scratch =~ s/^\s+//; + $scratch =~ s/\s+$//; + + return $scratch; +} + +my $done; +until ( $done ) { + my $line; + my @arg; + my @gid; + my @lid; + my $pkey; + + $line = readline STDIN; + until ( $line =~ /SGID/ || eof) { + $line = readline STDIN; + } + chomp; + $line = trim($line); + $line =~ s/0x/ /g; + ($arg[0], $gid[0], $gid[1]) = split(/:/, $line); + + $line = readline STDIN; + until ( $line =~ /DGID/ || eof) { + $line = readline STDIN; + } + chomp; + $line = trim($line); + $line =~ s/0x/ /g; + ($arg[0], $gid[2], $gid[3]) = split(/:/, $line); + + $line = readline STDIN; + until ( $line =~ /LID/ || eof) { + $line = readline STDIN; + } + chomp; + $line = trim($line); + ($arg[0], $lid[0], $arg[1], $lid[1], + $arg[2], $arg[4], $arg[4], $pkey) = split(/ /, $line); + + $done = eof; + print "$gid[0]$gid[1]:$gid[2]$gid[3]:$lid[0]:$lid[1]:$pkey\n" if ( ! $done) + +} diff --git a/opasadb/path_tools/cache/mydumppath.c b/opasadb/path_tools/cache/mydumppath.c new file mode 100644 index 0000000..2a443f0 --- /dev/null +++ b/opasadb/path_tools/cache/mydumppath.c @@ -0,0 +1,31 @@ +/* BEGIN_ICS_COPYRIGHT2 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT2 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ +#include "dumppath.c" diff --git a/opasadb/path_tools/cache/opp_cache_test.c b/opasadb/path_tools/cache/opp_cache_test.c new file mode 100644 index 0000000..525b1b7 --- /dev/null +++ b/opasadb/path_tools/cache/opp_cache_test.c @@ -0,0 +1,703 @@ +/* BEGIN_ICS_COPYRIGHT7 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT7 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "dumppath.h" + +#define SLEEPTIME 1 +#define QUERIESPERPASS 100000 +#define DEFAULTPASSES 10 + +#define MAXPATHS 32768 +#define MAXPKEYS 32 + +#define HFINAME "qib0" +#define PORTNO 1 + +static IB_PATH_RECORD_NO record[MAXPATHS]; +static uint16 pkey[MAXPKEYS]; +static int numrecs, numkeys; + +static char hfi_name[64] = HFINAME; +static uint16 port_no = PORTNO; + +static int done=0; + +static uint64_t build_comp_mask(IB_PATH_RECORD_NO path) +{ + uint64_t mask = 0; + + if (path.ServiceID) + mask |= IB_PATH_RECORD_COMP_SERVICEID; + if (path.DGID.Type.Global.InterfaceID | path.DGID.Type.Global.SubnetPrefix) + mask |= IB_PATH_RECORD_COMP_DGID; + if (path.SGID.Type.Global.InterfaceID | path.SGID.Type.Global.SubnetPrefix) + mask |= IB_PATH_RECORD_COMP_SGID; + if (path.DLID) + mask |= IB_PATH_RECORD_COMP_DLID; + if (path.SLID) + mask |= IB_PATH_RECORD_COMP_SLID; + if (path.P_Key) mask |= IB_PATH_RECORD_COMP_PKEY; + + return mask; +} + +static void my_sig(int signo) +{ + done=1; + return; +} + +static void sigalarm(int signo) +{ + return; +} + +static int my_sleep(unsigned int secs) +{ + if (signal(SIGALRM, sigalarm) == SIG_ERR) return -1; + + alarm(secs); + pause(); + return alarm(0); +} + +static int readline(FILE *f, char *s, int max) +{ + int i, c; + memset(s,0,max); + + i=0; + c=fgetc(f); + + while (c !='\n' && !feof(f) && i < max) { + s[i++]=c; + c=fgetc(f); + } + return i; +} + +#define asciitohex(c) ((((c)>='0') & ((c)<='9'))?((c)-'0'):((c)-'a'+10)) + +static void getraw(IB_GID_NO *gid, char *p) +{ + char *p2; + + gid->Type.Global.SubnetPrefix = hton64(strtoul(p,&p2,16)); + gid->Type.Global.InterfaceID = hton64(strtoul(p2,NULL,16)); +} + +int readrecord(FILE *f, IB_PATH_RECORD_NO *record) +{ + char *p, *l; + + char buffer[1024]; + + memset(record, 0, sizeof(IB_PATH_RECORD_NO)); + + if (readline(f,buffer,1024)<=0) { + return -1; + } + p=strtok_r(buffer,":", &l); + if (!p) + return -1; + getraw(&record->SGID,p); + p=strtok_r(NULL,":", &l); + if (!p) + return -1; + getraw(&record->DGID,p); + p=strtok_r(NULL,":", &l); + if (!p) + return -1; + record->SLID = htons(strtol(p,NULL,0)); + p=strtok_r(NULL,":", &l); + if (!p) + return -1; + record->DLID = htons(strtol(p,NULL,0)); + p=strtok_r(NULL,":", &l); + if (!p) + return -1; + record->P_Key = htons(strtol(p,NULL,0)); + + // We dummy up a SID that matches the pkey. + if (record->P_Key == 0xffff) { + record->ServiceID=0; + } else { + record->ServiceID=record->P_Key; + } + return 0; +} + +static int load_records(char *fname) +{ + FILE *f; + + f=fopen(fname,"r"); + if (f == NULL) { + _DBG_ERROR("Failed to open %s\n",fname); + return -1; + } + + printf("Loading %s.\n", fname); + numrecs = 0; + + do { + if (readrecord(f,&record[numrecs])) break; + numrecs++; + } while (numrecs < MAXPATHS); + fclose(f); + + return numrecs; +} + +static int find_pkeys(void) +{ + int i; + + for (numkeys=0, i=0; i=numkeys) { + pkey[numkeys]=record[i].P_Key; + numkeys++; + } + } + + return numkeys; +} + +/* + * Creates the shared memory tables. Uses the info from the supplied file, + * to create one or more virtual fabrics. NOTE: Only supports a single + * active port. + */ +int server(char *fname, int n) +{ + int i, err, pass; + op_ppath_writer_t w; + op_ppath_port_record_t port; + + _DBG_FUNC_ENTRY; + + if (load_records(fname) <= 0) { + return -1; + } + + if (find_pkeys() <= 0) { + _DBG_ERROR("No pkeys?!?\n"); + return -1; + } + + _DBG_NOTICE("Creating the shared memory table.\n"); + err = op_ppath_create_writer(&w); + if (err) { + _DBG_ERROR("Failed to create shared memory table: %s\n", + strerror(err)); + return err; + } + + _DBG_NOTICE("Creating the shared port table.\n"); + err = op_ppath_initialize_ports(&w, 1); + if (err) { + _DBG_ERROR( "Failed to create port table: %s\n", + strerror(err)); + goto error; + } + + _DBG_NOTICE("Creating the subnet table.\n"); + err = op_ppath_initialize_subnets(&w, 1, numkeys); + if (err) { + _DBG_ERROR( "Failed to create subnet table: %s\n", + strerror(err)); + goto error; + } + + _DBG_NOTICE("Creating the vfabric table.\n"); + err = op_ppath_initialize_vfabrics(&w, numkeys); + if (err) { + _DBG_ERROR( "Failed to create vfab table: %s\n", + strerror(err)); + goto error; + } + + _DBG_NOTICE("Adding the subnet.\n"); + err = op_ppath_add_subnet(&w, record[0].SGID.Type.Global.SubnetPrefix); + if (err) { + _DBG_ERROR( "Failed to add subnet: %s\n", + strerror(err)); + goto error; + } + + _DBG_NOTICE("Adding the vfabrics.\n"); + for (i=0; i0) my_sleep(SLEEPTIME); + + _DBG_NOTICE("Pass %d: Inserting records.\n", pass); + + _DBG_NOTICE("Creating the path table.\n"); + err = op_ppath_initialize_paths(&w, MAXPATHS); + if (err) { + _DBG_ERROR( "Failed to create path table: %s\n", + strerror(err)); + goto error; + } + + for (i=0;i= QUERIESPERPASS) { + pass++; + count=0; + printf("Pass %d complete.\n", pass); + } + } while (!done && pass < n); + +client_exit: + op_ppath_close_reader(&r); + return ret; +} + +int dump(char *fname) +{ + op_ppath_reader_t r; + int err; + unsigned i; + FILE *f = fopen(fname,"w"); + + if (!f) { + _DBG_ERROR("Can't open %s for writing.\n",fname); + return -1; + } + + err = op_ppath_create_reader(&r); + if (err) { + _DBG_ERROR( "Failed to access shared memory tables: %s\n", + strerror(err)); + fclose(f); + return err; + } + + fprintf(f,"Shared Table:\n"); + fprintf(f,"\tABI Version: %u\n", r.shared_table->abi_version); + fprintf(f,"\tSubnet Name: %s\n", r.shared_table->subnet_table_name); + fprintf(f,"\tSubnet Update Count: %u\n", + r.shared_table->subnet_update_count); + fprintf(f,"\tPort Name: %s\n", r.shared_table->port_table_name); + fprintf(f,"\tPort Update Count: %u\n", r.shared_table->port_update_count); + fprintf(f,"\tVFab Name: %s\n", r.shared_table->vfab_table_name); + fprintf(f,"\tVFab Update Count: %u\n", r.shared_table->vfab_update_count); + fprintf(f,"\tPath Name: %s\n", r.shared_table->path_table_name); + fprintf(f,"Path Update Count: %u\n", r.shared_table->path_update_count); + + fprintf(f,"\n\nSubnet Table:\n"); + fprintf(f,"\tSubnet Size: %u\n", r.subnet_table->subnet_size); + fprintf(f,"\tSubnet Count: %u\n", r.subnet_table->subnet_count); + fprintf(f,"\tSID Size: %u\n", r.subnet_table->sid_size); + fprintf(f,"\tSID Count: %u\n", r.subnet_table->sid_count); + for (i = 1; i <= r.subnet_table->subnet_count ; i++) { + fprintf(f,"\tSubnet[%u]:\n",i); + fprintf(f,"\t\tPrefix: 0x%016lx\n", + hton64(r.subnet_table->subnet[i].source_prefix)); + fprintf(f,"\t\tFirst SID: %u\n", + r.subnet_table->subnet[i].first_sid); + } + for (i = 1; i <= r.subnet_table->sid_count ; i++) { + fprintf(f,"\tSID[%u]:\n",i); + fprintf(f,"\t\tVFab ID: %u\n",r.sid_table[i].vfab_id); + fprintf(f,"\t\tLower: 0x%016lx\n", + hton64(r.sid_table[i].lower_sid)); + fprintf(f,"\t\tUpper: 0x%016lx\n", + hton64(r.sid_table[i].upper_sid)); + fprintf(f,"\t\tNext: %u\n", + r.sid_table[i].next); + } + + fprintf(f,"\n\nPort Table:\n"); + fprintf(f,"\tSize: %u\n", r.port_table->size); + fprintf(f,"\tCount: %u\n", r.port_table->count); + for (i = 1; i <= r.port_table->count ; i++) { + int j; + fprintf(f,"\tPort[%u]: %s/%u\n", i, + r.port_table->port[i].hfi_name, + r.port_table->port[i].port); + fprintf(f,"\t\tSubnet ID: %u\n", + r.port_table->port[i].subnet_id); + fprintf(f,"\t\tPrefix: 0x%016lx\n", + hton64(r.port_table->port[i].source_prefix)); + fprintf(f,"\t\tGuid: 0x%016lx\n", + hton64(r.port_table->port[i].source_guid)); + fprintf(f,"\t\tBase Lid: 0x%04x\n", + r.port_table->port[i].base_lid); + fprintf(f,"\t\tLMC: 0x%04x\n", + r.port_table->port[i].lmc); + fprintf(f,"\t\tPkeys:\n"); + for (j=0; jport[i].pkey[j]!=0; j++) + fprintf(f,"\t\t\t0x%04x\n", ntohs(r.port_table->port[i].pkey[j])); + } + + fprintf(f,"\n\nVFab Table:\n"); + fprintf(f,"\tSize: %u\n", r.vfab_table->size); + fprintf(f,"\tCount: %u\n", r.vfab_table->count); + for (i = 1; i <= r.vfab_table->count ; i++) { + int j; + fprintf(f,"\tVFab[%u]: %s\n", i, + r.vfab_table->vfab[i].vfab_name); + fprintf(f,"\t\tPrefix: 0x%16lx\n", + hton64(r.vfab_table->vfab[i].source_prefix)); + fprintf(f,"\t\tPKey: 0x%04x\n", + hton16(r.vfab_table->vfab[i].pkey)); + fprintf(f,"\t\tService Level: 0x%04x\n", + hton16(r.vfab_table->vfab[i].sl)); + + fprintf(f,"\n\t\tDLID Hash Table:\n"); + for (j=0;jvfab[i].first_dlid[j]); + } + + fprintf(f,"\n\t\tDGUID Hash Table:\n"); + for (j=0;jvfab[i].first_dguid[j]); + } + + } + + fprintf(f,"\n\nPath Table\n"); + fprintf(f,"\tSize: %u\n", r.path_table->size); + fprintf(f,"\tCount: %u\n", r.path_table->count); + for (i=1; i<= r.path_table->count; i++) { + char s[128]; + sprintf(s,"Record[%u] (%s) Lid->%u, Guid->%u",i, + r.path_table->table[i].flags?"Used":"Unused", + r.path_table->table[i].next_lid, + r.path_table->table[i].next_guid); + fprint_path_record(f,s,(op_path_rec_t*)&(r.path_table->table[i].path)); + } + + op_ppath_close_reader(&r); + fclose(f); + return 0; +} + +int main(int argc, char *argv[]) +{ + int mode = 's'; + int i; + int n=DEFAULTPASSES; + char filename[512]; + int debug = _DBG_LVL_NOTICE; + + memset(filename, 0, 512); + + do { + int c; + + static char *short_options = "sdcf:n:v:"; + static struct option long_options[] = { + {.name = "server",.has_arg = 0,.val = 's'}, + {.name = "client",.has_arg = 0,.val = 'c'}, + {.name = "dump",.has_arg = 0,.val = 'd'}, + {.name = "file",.has_arg = 1,.val = 'f'}, + {.name = "num",.has_arg = 1,.val = 'n'}, + {.name = "hfi",.has_arg = 1,.val = 'H'}, + {.name = "port",.has_arg = 1,.val = 'p'}, + {.name = "verbose",.has_arg = 1,.val = 'v'}, + {0} + }; + + static char *usage[] = { + "Server mode: loads the specified file and emulates dsap", + "Client mode: loads the specified file and emulates a client", + "Dumps the current contents of the discovery tables to the file.", + "the file containing the node table (required)", + "the number of passes to make", + "the default hfi. (Defaults to "HFINAME".)", + "the default port. (Defaults to 1.)", + "the level of logging to do.", + NULL + }; + + c = getopt_long(argc, argv, short_options, long_options, NULL); + if (c == -1) + break; + + switch (c) { + case 'H': + strcpy(hfi_name, optarg); + break; + case 'p': + port_no = strtoul(optarg, NULL, 0); + break; + case 'n': + n = strtoul(optarg,NULL,0); + break; + case 'c': + case 'd': + case 's': + mode = c; + break; + case 'v': + debug = strtol(optarg,NULL,0); + break; + case 'f': + strncpy(filename, optarg, 511); + break; + default: + i=0; + printf( "Usage: %s (options)\n", argv[0]); + printf( "Options are:\n"); + while (long_options[i].name != NULL) { + printf( " [--%-8s %s | -%c %s] %s\n", + long_options[i].name, + (long_options[i].has_arg) ? "" : "", + long_options[i].val, + (long_options[i].has_arg) ? "" : "", + usage[i]); + i++; + } + return -1; + } + } while(1); + + op_log_set_level(debug); + + if (filename[0]==0) { + _DBG_ERROR("You must provide a filename.\n"); + return -1; + } + + signal(SIGINT, my_sig); + + switch (mode) { + case 'c': + client(filename,n); + break; + case 's': + server(filename,n); + break; + case 'd': + dump(filename); + break; + } + return 0; +} diff --git a/opasadb/path_tools/dump/Makefile b/opasadb/path_tools/dump/Makefile new file mode 100644 index 0000000..4562df3 --- /dev/null +++ b/opasadb/path_tools/dump/Makefile @@ -0,0 +1,163 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** +# Makefile for opasadb/route_tools + +# Include Make Control Settings +include $(TL_DIR)/$(PROJ_FILE_DIR)/Makesettings.project + +#=============================================================================# +# Definitions: +#-----------------------------------------------------------------------------# + +# Name of SubProjects +DS_SUBPROJECTS = +# name of executable or downloadable image +EXECUTABLE = $(BUILDDIR)/opa_osd_dump$(EXE_SUFFIX) +# list of sub directories to build +DIRS = +# C files (.c) +CFILES = \ + mydumppath.c \ + opa_osd_dump.c \ + # Add more c files here +# C++ files (.cpp) +CCFILES = \ + # Add more cpp files here +# lex files (.lex) +LFILES = \ + # Add more lex files here +# archive library files (basename, $ARFILES will add MOD_LIB_DIR/prefix and suffix) +LIBFILES = +# Windows Resource Files (.rc) +RSCFILES = +# Windows IDL File (.idl) +IDLFILE = +# Windows Linker Module Definitions (.def) file for dll's +DEFFILE = +# targets to build during INCLUDES phase (add public includes here) +INCLUDE_TARGETS = \ + # Add more h hpp files here +# Non-compiled files +MISC_FILES = +# all source files +SOURCES = $(CFILES) $(CCFILES) $(LFILES) $(RSCFILES) $(IDLFILE) +# Source files to include in DSP File +DSP_SOURCES = $(INCLUDE_TARGETS) $(SOURCES) $(MISC_FILES) \ + $(RSCFILES) $(DEFFILE) $(MAKEFILE) +# all object files +OBJECTS = $(CFILES:.c=$(OBJ_SUFFIX)) $(CCFILES:.cpp=$(OBJ_SUFFIX)) \ + $(LFILES:.lex=$(OBJ_SUFFIX)) \ + # Add more object files here +RSCOBJECTS = $(RSCFILES:.rc=$(RES_SUFFIX)) +# targets to build during LIBS phase +LIB_TARGETS_IMPLIB = +LIB_TARGETS_ARLIB = +LIB_TARGETS_EXP = $(LIB_TARGETS_IMPLIB:$(ARLIB_SUFFIX)=$(EXP_SUFFIX)) +LIB_TARGETS_MISC = +# targets to build during CMDS phase +SHLIB_VERSION = +CMD_TARGETS_SHLIB = +CMD_TARGETS_EXE = $(EXECUTABLE) +CMD_TARGETS_MISC = +# files to remove during clean phase +CLEAN_TARGETS_MISC = +CLEAN_TARGETS = $(OBJECTS) $(RSCOBJECTS) $(IDL_TARGETS) $(CLEAN_TARGETS_MISC) +# other files to remove during clobber phase +CLOBBER_TARGETS_MISC= +# sub-directory to install to within bin +BIN_SUBDIR = +# sub-directory to install to within include +INCLUDE_SUBDIR = + +# Additional Settings +#CLOCALDEBUG = User defined C debugging compilation flags [Empty] +#CCLOCALDEBUG = User defined C++ debugging compilation flags [Empty] +# User defined C flags for compiling +# User defined C++ flags for compiling +#CCLOCAL = +#BSCLOCAL = User flags for Browse File Builder [Empty] +#DEPENDLOCAL = user defined makedepend flags [Empty] +#LINTLOCAL = User defined lint flags [Empty] +# User include directories to search for C/C++ headers +LOCAL_INCLUDE_DIRS = .. +#LDLOCAL = User defined C flags for linking [Empty] +#IMPLIBLOCAL = User flags for Object Lirary Manager [Empty] +#MIDLLOCAL = User flags for IDL compiler [Empty] +#RSCLOCAL = User flags for resource compiler [Empty] +# User libraries to include in dependencies +LOCALDEPLIBS = IbPrint $(IBACCESS_USER_LIBS) opamgt-priv +# User libraries to use when linking (in addition to LOCALDEPLIBS) +# opasadb is a shared library, not needed in LOCALDEPLIBS +LOCALLIBS = $(OPENIB_USER_LIBS) opasadb rt +# User library directories for libpaths +LOCAL_LIB_DIRS = $(OPENIB_USER_LIB_DIRS) $(IBACCESS_USER_LIB_DIRS) + +CLOCAL = $(CPIE) + +# Include Make Rules definitions and rules +include $(TL_DIR)/IbaTools/Makerules.module + +#=============================================================================# +# Overrides: +#-----------------------------------------------------------------------------# +# C++ optimization flags, default lets build config decide +#CCOPT = +# C optimization flags, default lets build config decide +COPT = -g -D_GNU_SOURCE -Wall -fPIE +#SUBSYSTEM = Subsystem to build for (none, console or windows) [none] +# (Windows Only) +#USEMFC = How Windows MFC should be used (none, static, shared, no_mfc) [none] +# (Windows Only) +#=============================================================================# + +#=============================================================================# +# Rules: +#-----------------------------------------------------------------------------# +# process Sub-directories +include $(TL_DIR)/Makerules/Maketargets.toplevel + +# build cmds and libs +include $(TL_DIR)/Makerules/Maketargets.build + +# install for includes, libs and cmds phases +include $(TL_DIR)/Makerules/Maketargets.install + +# install for stage phase +#include $(TL_DIR)/Makerules/Maketargets.stage +STAGE:: + $(VS)$(STAGE_INSTALL) $(STAGE_INSTALL_DIR_OPT) $(PROJ_STAGE_OPA_SA_DB_DIR) $(EXECUTABLE) + +# Unit test execution +#include $(TL_DIR)/Makerules/Maketargets.runtest + +#=============================================================================# + +#=============================================================================# +# DO NOT DELETE THIS LINE -- make depend depends on it. +#=============================================================================# diff --git a/opasadb/path_tools/dump/mydumppath.c b/opasadb/path_tools/dump/mydumppath.c new file mode 100644 index 0000000..2a443f0 --- /dev/null +++ b/opasadb/path_tools/dump/mydumppath.c @@ -0,0 +1,31 @@ +/* BEGIN_ICS_COPYRIGHT2 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT2 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ +#include "dumppath.c" diff --git a/opasadb/path_tools/dump/opa_osd_dump.c b/opasadb/path_tools/dump/opa_osd_dump.c new file mode 100644 index 0000000..8daa168 --- /dev/null +++ b/opasadb/path_tools/dump/opa_osd_dump.c @@ -0,0 +1,212 @@ +/* BEGIN_ICS_COPYRIGHT7 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT7 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "dumppath.h" + +#define HFINAME "qib0" +#define PORTNO 1 + +int +dump(FILE *f) +{ + op_ppath_reader_t r; + int err; + unsigned i; + + err = op_ppath_create_reader(&r); + if (err) { + _DBG_ERROR( "Failed to access shared memory tables: %s\n", + strerror(err)); + return err; + } + + fprintf(f,"Shared Table:\n"); + fprintf(f,"\tABI Version: %u\n", r.shared_table->abi_version); + fprintf(f,"\tSubnet Name: %s\n", r.shared_table->subnet_table_name); + fprintf(f,"\tSubnet Update Count: %u\n", + r.shared_table->subnet_update_count); + fprintf(f,"\tPort Name: %s\n", r.shared_table->port_table_name); + fprintf(f,"\tPort Update Count: %u\n", r.shared_table->port_update_count); + fprintf(f,"\tVFab Name: %s\n", r.shared_table->vfab_table_name); + fprintf(f,"\tVFab Update Count: %u\n", r.shared_table->vfab_update_count); + fprintf(f,"\tPath Name: %s\n", r.shared_table->path_table_name); + fprintf(f,"\tPath Update Count: %u\n", r.shared_table->path_update_count); + + fprintf(f,"\n\nSubnet Table:\n"); + fprintf(f,"\tSubnet Size: %u\n", r.subnet_table->subnet_size); + fprintf(f,"\tSubnet Count: %u\n", r.subnet_table->subnet_count); + fprintf(f,"\tSID Size: %u\n", r.subnet_table->sid_size); + fprintf(f,"\tSID Count: %u\n", r.subnet_table->sid_count); + for (i = 1; i <= r.subnet_table->subnet_count ; i++) { + fprintf(f,"\tSubnet[%u]:\n",i); + fprintf(f,"\t\tPrefix: 0x%016lx\n", + hton64(r.subnet_table->subnet[i].source_prefix)); + fprintf(f,"\t\tFirst SID: %u\n", + r.subnet_table->subnet[i].first_sid); + } + for (i = 1; i <= r.subnet_table->sid_count ; i++) { + fprintf(f,"\tSID[%u]:\n",i); + fprintf(f,"\t\tVFab ID: %u\n",r.sid_table[i].vfab_id); + fprintf(f,"\t\tLower: 0x%016lx\n", + hton64(r.sid_table[i].lower_sid)); + fprintf(f,"\t\tUpper: 0x%016lx\n", + hton64(r.sid_table[i].upper_sid)); + fprintf(f,"\t\tNext: %u\n", + r.sid_table[i].next); + } + + fprintf(f,"\n\nPort Table:\n"); + fprintf(f,"\tSize: %u\n", r.port_table->size); + fprintf(f,"\tCount: %u\n", r.port_table->count); + for (i = 1; i <= r.port_table->count ; i++) { + int j; + fprintf(f,"\tPort[%u]: %s/%u\n", i, + r.port_table->port[i].hfi_name, + r.port_table->port[i].port); + fprintf(f,"\t\tSubnet ID: %u\n", + r.port_table->port[i].subnet_id); + fprintf(f,"\t\tPrefix: 0x%016lx\n", + hton64(r.port_table->port[i].source_prefix)); + fprintf(f,"\t\tGuid: 0x%016lx\n", + hton64(r.port_table->port[i].source_guid)); + fprintf(f,"\t\tBase Lid: 0x%04x\n", + r.port_table->port[i].base_lid); + fprintf(f,"\t\tLMC: 0x%04x\n", + r.port_table->port[i].lmc); + fprintf(f,"\t\tPkeys:\n"); + for (j=0; jport[i].pkey[j]!=0; j++) + fprintf(f,"\t\t\t0x%04x\n", ntohs(r.port_table->port[i].pkey[j])); + } + + fprintf(f,"\n\nVFab Table:\n"); + fprintf(f,"\tSize: %u\n", r.vfab_table->size); + fprintf(f,"\tCount: %u\n", r.vfab_table->count); + for (i = 1; i <= r.vfab_table->count ; i++) { + int j; + op_ppath_vfab_record_t *vf = &r.vfab_table->vfab[i]; + fprintf(f,"\tVFab[%u]: %s\n", i, + vf->vfab_name); + fprintf(f,"\t\tPrefix: 0x%16lx\n", + hton64(vf->source_prefix)); + fprintf(f,"\t\tPKey: 0x%04x\n", + hton16(vf->pkey)); + fprintf(f,"\t\tService Level: 0x%04x\n", + hton16(vf->sl)); + + fprintf(f,"\n\t\tDLID Hash Table:\n"); + for (j=0;jfirst_dlid[j]); + } + fprintf(f,"\n\t\tDGUID Hash Table:\n"); + for (j=0;jfirst_dguid[j]); + } + + } + + fprintf(f,"\n\nPath Table\n"); + fprintf(f,"\tSize: %u\n", r.path_table->size); + fprintf(f,"\tCount: %u\n", r.path_table->count); + for (i=1; i<= r.path_table->count; i++) { + char s[128]; + sprintf(s,"Record[%u] (%s) Lid->%u, Guid->%u",i, + r.path_table->table[i].flags?"Used":"Unused", + r.path_table->table[i].next_lid, + r.path_table->table[i].next_guid); + fprint_path_record(f,s,(op_path_rec_t*)&(r.path_table->table[i].path)); + } + + op_ppath_close_reader(&r); + return 0; +} + +void Usage(int status) +{ + fprintf(stderr, "Usage: opa_osd_dump (options)\n"); + fprintf(stderr, "Print the current contents of the distributed SA shared memory database.\n"); + fprintf(stderr, "Options are:\n"); + fprintf(stderr, "\t-v/--verbose\t\tLog Level. Corresponds to a Kernel log level,\n\t\t\t\ta number from 1 to 7\n"); + fprintf(stderr, "\t--help\t\t\tPrint this help text\n"); + fprintf(stderr, "\nExample:\topa_osd_dump > opasadb_contents\n"); + + exit(status); +} + + +int main(int argc, char *argv[]) +{ + int debug = _DBG_LVL_NOTICE; + + do { + int c; + + static char *short_options = "v:"; + static struct option long_options[] = { + {.name = "verbose",.has_arg = 1,.val = 'v'}, + {.name = "help", .has_arg = 0, .val = '$'}, + {0} + }; + + c = getopt_long(argc, argv, short_options, long_options, NULL); + if (c == -1) + break; + + switch (c) { + case 'v': + debug = strtol(optarg,NULL,0); + break; + case '$': + Usage(0);//exits + break; + default: + Usage(2);//exits + break; + } + } while(1); + + op_log_set_level(debug); + + dump(stdout); + return 0; +} diff --git a/opasadb/path_tools/dumppath.c b/opasadb/path_tools/dumppath.c new file mode 100644 index 0000000..88fe8d6 --- /dev/null +++ b/opasadb/path_tools/dumppath.c @@ -0,0 +1,115 @@ +/* BEGIN_ICS_COPYRIGHT2 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT2 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ +#include +#include +#include +#include +#include "dumppath.h" +#include "opasadb_path.h" + +/* Returns 0 on error, non-zero on success. */ +int parse_gid(char *s, op_gid_t *gid) +{ + if (!strncmp(s,"0x",2)) { + /* GID format */ + + uint64_t prefix=0; + uint64_t subnet=0; + char *p, *l, *sep=":"; + + p = strtok_r(s,sep,&l); + if (!p) return 0; + + prefix = strtoull(p,NULL,0); + if (!prefix) return 0; + + p = strtok_r(NULL, sep, &l); + if (!p) return 0; + + subnet = strtoull(p,NULL,0); + if (!subnet) return 0; + + gid->unicast.interface_id = hton64(subnet); + gid->unicast.prefix = hton64(prefix); + + return 1; + + } else { + /* Inet 6 format */ + + return inet_pton(AF_INET6, s, gid->raw); + } + +} +void print_path_record(char *str, op_path_rec_t *p_path) +{ + return fprint_path_record(stdout,str,p_path); +} + +static void network_to_host_path_record(IB_PATH_RECORD_NO *p_net, + IB_PATH_RECORD *p_host) +{ + p_host->ServiceID = ntoh64(p_net->ServiceID); + p_host->DGID.Type.Global.SubnetPrefix = ntoh64(p_net->DGID.Type.Global.SubnetPrefix); + p_host->DGID.Type.Global.InterfaceID = ntoh64(p_net->DGID.Type.Global.InterfaceID); + p_host->SGID.Type.Global.SubnetPrefix = ntoh64(p_net->SGID.Type.Global.SubnetPrefix); + p_host->SGID.Type.Global.InterfaceID = ntoh64(p_net->SGID.Type.Global.InterfaceID); + p_host->DLID = ntoh16(p_net->DLID); + p_host->SLID = ntoh16(p_net->SLID); + + p_host->u1.AsReg32 = ntohl(p_net->u1.AsReg32); + p_host->TClass = p_net->TClass; + p_host->Reversible = p_net->Reversible; + p_host->NumbPath = p_net->NumbPath; + p_host->P_Key = ntohs(p_net->P_Key); + p_host->u2.AsReg16 = ntohs(p_net->u2.AsReg16); + p_host->MtuSelector = p_net->MtuSelector; + p_host->Mtu = p_net->Mtu; + p_host->RateSelector = p_net->RateSelector; + p_host->Rate = p_net->Rate; + p_host->PktLifeTimeSelector = p_net->PktLifeTimeSelector; + p_host->PktLifeTime = p_net->PktLifeTime; + p_host->Preference = p_net->Preference; +} + +void fprint_path_record(FILE *f, char *str, op_path_rec_t *p_path) +{ + IB_PATH_RECORD path; + PrintDest_t printdest; + + network_to_host_path_record((IB_PATH_RECORD_NO*)p_path, &path); + + PrintDestInitFile(&printdest,f); + + PrintFunc(&printdest, "%s:\n",str); + PrintExtendedPathRecord(&printdest,8, &path); +} + diff --git a/opasadb/path_tools/dumppath.h b/opasadb/path_tools/dumppath.h new file mode 100644 index 0000000..e1f14e4 --- /dev/null +++ b/opasadb/path_tools/dumppath.h @@ -0,0 +1,50 @@ +/* BEGIN_ICS_COPYRIGHT7 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT7 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +#if !defined(_DUMP_PATH_H_) +#define _DUMP_PATH_H_ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +void print_path_record(char *str, op_path_rec_t *p_path); +void fprint_path_record(FILE *f, char *str, op_path_rec_t *p_path); +int parse_gid(char *s, op_gid_t *gid); + +#endif diff --git a/opasadb/path_tools/exercise/Makefile b/opasadb/path_tools/exercise/Makefile new file mode 100644 index 0000000..ebed0f5 --- /dev/null +++ b/opasadb/path_tools/exercise/Makefile @@ -0,0 +1,163 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** +# Makefile for opasadb/route_tools + +# Include Make Control Settings +include $(TL_DIR)/$(PROJ_FILE_DIR)/Makesettings.project + +#=============================================================================# +# Definitions: +#-----------------------------------------------------------------------------# + +# Name of SubProjects +DS_SUBPROJECTS = +# name of executable or downloadable image +EXECUTABLE = $(BUILDDIR)/opa_osd_exercise$(EXE_SUFFIX) +# list of sub directories to build +DIRS = +# C files (.c) +CFILES = \ + mydumppath.c \ + opa_osd_exercise.c \ + # Add more c files here +# C++ files (.cpp) +CCFILES = \ + # Add more cpp files here +# lex files (.lex) +LFILES = \ + # Add more lex files here +# archive library files (basename, $ARFILES will add MOD_LIB_DIR/prefix and suffix) +LIBFILES = +# Windows Resource Files (.rc) +RSCFILES = +# Windows IDL File (.idl) +IDLFILE = +# Windows Linker Module Definitions (.def) file for dll's +DEFFILE = +# targets to build during INCLUDES phase (add public includes here) +INCLUDE_TARGETS = \ + # Add more h hpp files here +# Non-compiled files +MISC_FILES = +# all source files +SOURCES = $(CFILES) $(CCFILES) $(LFILES) $(RSCFILES) $(IDLFILE) +# Source files to include in DSP File +DSP_SOURCES = $(INCLUDE_TARGETS) $(SOURCES) $(MISC_FILES) \ + $(RSCFILES) $(DEFFILE) $(MAKEFILE) +# all object files +OBJECTS = $(CFILES:.c=$(OBJ_SUFFIX)) $(CCFILES:.cpp=$(OBJ_SUFFIX)) \ + $(LFILES:.lex=$(OBJ_SUFFIX)) \ + # Add more object files here +RSCOBJECTS = $(RSCFILES:.rc=$(RES_SUFFIX)) +# targets to build during LIBS phase +LIB_TARGETS_IMPLIB = +LIB_TARGETS_ARLIB = +LIB_TARGETS_EXP = $(LIB_TARGETS_IMPLIB:$(ARLIB_SUFFIX)=$(EXP_SUFFIX)) +LIB_TARGETS_MISC = +# targets to build during CMDS phase +SHLIB_VERSION = +CMD_TARGETS_SHLIB = +CMD_TARGETS_EXE = $(EXECUTABLE) +CMD_TARGETS_MISC = +# files to remove during clean phase +CLEAN_TARGETS_MISC = +CLEAN_TARGETS = $(OBJECTS) $(RSCOBJECTS) $(IDL_TARGETS) $(CLEAN_TARGETS_MISC) +# other files to remove during clobber phase +CLOBBER_TARGETS_MISC= +# sub-directory to install to within bin +BIN_SUBDIR = +# sub-directory to install to within include +INCLUDE_SUBDIR = + +# Additional Settings +#CLOCALDEBUG = User defined C debugging compilation flags [Empty] +#CCLOCALDEBUG = User defined C++ debugging compilation flags [Empty] +# User defined C flags for compiling +# User defined C++ flags for compiling +#CCLOCAL = +#BSCLOCAL = User flags for Browse File Builder [Empty] +#DEPENDLOCAL = user defined makedepend flags [Empty] +#LINTLOCAL = User defined lint flags [Empty] +# User include directories to search for C/C++ headers +LOCAL_INCLUDE_DIRS = .. +#LDLOCAL = User defined C flags for linking [Empty] +#IMPLIBLOCAL = User flags for Object Lirary Manager [Empty] +#MIDLLOCAL = User flags for IDL compiler [Empty] +#RSCLOCAL = User flags for resource compiler [Empty] +# User libraries to include in dependencies +LOCALDEPLIBS = IbPrint $(IBACCESS_USER_LIBS) opamgt-priv +# User libraries to use when linking (in addition to LOCALDEPLIBS) +# opasadb is a shared library, not needed in LOCALDEPLIBS +LOCALLIBS = $(OPENIB_USER_LIBS) opasadb rt +# User library directories for libpaths +LOCAL_LIB_DIRS = $(OPENIB_USER_LIB_DIRS) $(IBACCESS_USER_LIB_DIRS) + +CLOCAL = $(CPIE) + +# Include Make Rules definitions and rules +include $(TL_DIR)/IbaTools/Makerules.module + +#=============================================================================# +# Overrides: +#-----------------------------------------------------------------------------# +# C++ optimization flags, default lets build config decide +#CCOPT = +# C optimization flags, default lets build config decide +COPT = -g -D_GNU_SOURCE -Wall -fPIE +#SUBSYSTEM = Subsystem to build for (none, console or windows) [none] +# (Windows Only) +#USEMFC = How Windows MFC should be used (none, static, shared, no_mfc) [none] +# (Windows Only) +#=============================================================================# + +#=============================================================================# +# Rules: +#-----------------------------------------------------------------------------# +# process Sub-directories +include $(TL_DIR)/Makerules/Maketargets.toplevel + +# build cmds and libs +include $(TL_DIR)/Makerules/Maketargets.build + +# install for includes, libs and cmds phases +include $(TL_DIR)/Makerules/Maketargets.install + +# install for stage phase +#include $(TL_DIR)/Makerules/Maketargets.stage +STAGE:: + $(VS)$(STAGE_INSTALL) $(STAGE_INSTALL_DIR_OPT) $(PROJ_STAGE_OPA_SA_DB_DIR) $(EXECUTABLE) opa_osd_exercise_test.pl + +# Unit test execution +#include $(TL_DIR)/Makerules/Maketargets.runtest + +#=============================================================================# + +#=============================================================================# +# DO NOT DELETE THIS LINE -- make depend depends on it. +#=============================================================================# diff --git a/opasadb/path_tools/exercise/mydumppath.c b/opasadb/path_tools/exercise/mydumppath.c new file mode 100644 index 0000000..2a443f0 --- /dev/null +++ b/opasadb/path_tools/exercise/mydumppath.c @@ -0,0 +1,31 @@ +/* BEGIN_ICS_COPYRIGHT2 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT2 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ +#include "dumppath.c" diff --git a/opasadb/path_tools/exercise/opa_osd_exercise.c b/opasadb/path_tools/exercise/opa_osd_exercise.c new file mode 100644 index 0000000..74963de --- /dev/null +++ b/opasadb/path_tools/exercise/opa_osd_exercise.c @@ -0,0 +1,639 @@ +/* BEGIN_ICS_COPYRIGHT2 **************************************** + +Copyright (c) 2015, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT2 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +/* + * This program is meant to stress the path query system. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "dumppath.h" +#include "opasadb_path.h" +#include "opasadb_debug.h" + +#define MAX_SOURCE_PORTS (UMAD_CA_MAX_PORTS * UMAD_MAX_DEVICES) +#define MAX_SIDS 8 +#define MAX_PKEYS 8 +#define MAX_SECONDS (60 * 60 * 24) +#define MAX_TOGGLES 100 +#define SRCTOGGLERATE 0 +#define DELAY 10 + +#define DELIMITER ";" + +static char remote[512]; + +//Previously, this was used to stress the API, but since we're now using this +//to test the SM and the Distributed SA, that isn't the best use of our time. +//#define QUERIESPERPASS 100000 + +typedef struct _src_record { + int disable; + uint64_t prefix; + uint64_t guid; + uint16_t base_lid; + uint16_t num_lids; + uint16_t port_num; + char hfi_num; +} src_record; + +typedef struct _record { + int disable; + int simulated; + uint64_t guid; + uint16_t lid; + char name[64]; + int guid_fail_count; + int lid_fail_count; +} record; + +static void sig_alrm(int signo) { return; } + +static int +my_sleep(unsigned int secs) +{ + if (signal(SIGALRM, sig_alrm) == SIG_ERR) return -1; + + alarm(secs); + pause(); + return alarm(0); +} + +static int +readline(FILE *f, char *s, int max) +{ + int i, c; + memset(s,0,max); + + i=0; + c=fgetc(f); + + while (c !='\n' && !feof(f) && i < max) { + s[i++]=c; + c=fgetc(f); + } + return i; +} + +static void +portenable(record *r) +{ + char buffer[1024]; + + if (r->simulated) { + sprintf(buffer,"ssh root@%s simctl PortUp portguid:0x%016"PRIx64"\n", + remote, ntoh64(r->guid)); + } else { + sprintf(buffer,"ssh root@%s /sbin/opaportconfig -l %u enable\n", + r->name, htons(r->lid)); + } + + _DBG_DEBUG("%s",buffer); + system(buffer); +} + +static void +portdisable(record *r) +{ + char buffer[1024]; + + if (r->simulated) { + sprintf(buffer,"ssh root@%s simctl PortDown portguid:0x%016"PRIx64"\n", + remote, ntoh64(r->guid)); + } else { + sprintf(buffer,"ssh root@%s /sbin/opaportconfig -l %u disable\n", + r->name, htons(r->lid)); + } + + _DBG_DEBUG("%s",buffer); + system(buffer); +} + +static void +src_portenable(src_record *r) +{ + char buffer[1024]; + + sprintf(buffer,"/sbin/opaportconfig -l %u enable\n", + htons(r->base_lid)); + + _DBG_DEBUG("%s",buffer); + system(buffer); +} + +static void +src_portdisable(src_record *r) +{ + char buffer[1024]; + + sprintf(buffer,"/sbin/opaportconfig -l %u disable\n", + htons(r->base_lid)); + + _DBG_DEBUG("%s",buffer); + system(buffer); +} + +static int +readrecord(FILE *f, record *r) +{ + char *p, *l; + char buffer[1024]; + memset(r, 0, sizeof(record)); + + if (readline(f,buffer,1024)<=0) { + return -1; + } + + r->disable = 0; + + p=strtok_r(buffer,DELIMITER, &l); if (!p) return -1; + r->lid = htons(strtol(p,NULL,0)); + p=strtok_r(NULL,DELIMITER, &l); if (!p) return -1; + r->guid = hton64(strtoull(p,NULL,0)); + + p=strtok_r(NULL,DELIMITER, &l); if (!p) return -1; + strcpy(r->name, p); + + r->simulated = strstr(p,"Sim") != NULL; + if (!r->simulated) { + /* parse name */ + p = strstr(r->name," "); + if (p) *p=0; + } + + return 0; +} + +static void +usage(char **argv) +{ + fprintf(stderr, "Usage: %s [opts] guidlist\n", argv[0]); + fprintf(stderr, "Stress test SM and Distributed SA query system\n"); + fprintf(stderr, "\toptions include:\n"); + fprintf(stderr, "\t--help\n"); + fprintf(stderr, "\t\tProvide this help text.\n"); + fprintf(stderr, "\t-d \n"); + fprintf(stderr, "\t\t set debugging level.\n"); + fprintf(stderr, "\t-s \n"); + fprintf(stderr, "\t\tRun for at least seconds.\n"); + fprintf(stderr, "\t-r \n"); + fprintf(stderr, "\t\tThe host running the fabric simulator.\n"); + fprintf(stderr, "\t-x \n"); + fprintf(stderr, "\t\tHow many destinations to toggle up or down after each pass.\n"); + fprintf(stderr, "\t\t(up to " stringize(MAX_TOGGLES)".)\n"); + fprintf(stderr, "\t-X \n"); + fprintf(stderr, "\t\tHow often to toggle a source port up or down (in seconds).\n"); + fprintf(stderr, "\t-D \n"); + fprintf(stderr, "\t\tHow long to sleep after each pass.\n"); + fprintf(stderr, "\t\t(To give the SM time to process port events)\n"); + fprintf(stderr, "\t-p \n"); + fprintf(stderr, "\t\tInclude in the searches.\n"); + fprintf(stderr,"\t\t(Can be specified up to " add_quotes(MAX_PKEYS) " times.)\n"); + fprintf(stderr, "\t-S \n"); + fprintf(stderr, "\t\tInclude in the searches.\n"); + fprintf(stderr, "\t-t \n"); + fprintf(stderr, "\t\tAbort the test if the number of path errors to a single destination exceeds threshold.\n"); + fprintf(stderr, "\t\t(the count is reset to zero when a correct result is retrieved.)\n"); + fprintf(stderr,"\t\t(Can be specified up to " add_quotes(MAX_SIDS) " times. Note that\n"); + fprintf(stderr,"\t\tproviding both SIDs and pkeys may cause problems.)\n"); + fprintf(stderr, "\t-e\n"); + fprintf(stderr, "\t\tInstruct simulator to enable all ports before starting.\n"); + fprintf(stderr, "\n"); + fprintf(stderr, + "'guidlist' is a text file that lists the source and destination\n"); + fprintf(stderr, + "guids and lids \n"); + fprintf(stderr, + "guidlist format is\n"); + fprintf(stderr, + "lid_0;guid_0;node_desc_0\n"); + fprintf(stderr, + "lid_1;guid_1;node_desc_1\n"); + fprintf(stderr, + ".\n"); + fprintf(stderr, + ".\n"); + fprintf(stderr, + "\nExample:\t%s -p 0x9001 guidtable\n", argv[0]); +} + +static record *dest_ports; +static src_record src_ports[MAX_SOURCE_PORTS]; +int numsources = 0; + +int +get_sources(void) +{ + umad_port_t port; + char ca_names[UMAD_MAX_DEVICES][UMAD_CA_NAME_LEN]; + int ca_count; + int i, err; + + ca_count = umad_get_cas_names(ca_names, UMAD_MAX_DEVICES); + + for (i = 0; i < ca_count; i++) { + umad_ca_t ca; + int j; + + err = umad_get_ca(ca_names[i], &ca); + if (err) { + _DBG_ERROR("Failed to open %s\n", ca_names[i]); + return -1; + } + + for (j = 1; j <= ca.numports; j++) { + err = umad_get_port(ca_names[i], j, &port); + if (err) { + _DBG_ERROR("Failed to get info on port %d of %s\n", + j, ca_names[i]); + umad_release_ca(&ca); + return -1; + } + + if (port.state == IBV_PORT_ACTIVE) { + src_ports[numsources].disable = port.state != IBV_PORT_ACTIVE; + src_ports[numsources].prefix = port.gid_prefix; + src_ports[numsources].guid = port.port_guid; + src_ports[numsources].base_lid = htons(port.base_lid); + src_ports[numsources].num_lids = 1<<(port.lmc); + src_ports[numsources].port_num = j; + src_ports[numsources].hfi_num = i + 1; + numsources++; + } + } + } + return numsources; +} + +int +main(int argc, char **argv) +{ + FILE *f = NULL; + int c, err, pf; + int debug = _DBG_LVL_ERROR; + uint16_t port; + unsigned i, numdests, numtoggle, srctogglerate; + uint64_t sid[MAX_SIDS]; + unsigned pkey[MAX_PKEYS]; + unsigned numpkeys, numsids, enable_ports; + unsigned falsepos, falseneg, passes, seconds, queries, delay; + struct timeval start_time, end_time, elapsed_time, next_src_toggle, now_time; + void *context; + struct ibv_context *hfi; + struct ibv_device *device; + int error_threshold = 65536; // Just because... + int ret = 0; + + setlocale(LC_ALL, ""); + + /* Default values. */ + strcpy(remote,"strife"); + port = 1; + seconds = 0; + numdests = 1024; + numsources = 0; + numtoggle = 10; + numpkeys = 0; + numsids = 0; + enable_ports = 0; + srctogglerate = SRCTOGGLERATE; + delay = DELAY; + + if (argc > 1){ + if (!strcmp(argv[1], "--help")){ + usage(argv); + exit(0); + } + } + + while ((c = getopt(argc, argv, "ed:s:r:p:S:x:X:t:D:")) != EOF) { + switch (c) { + case 'e': + enable_ports = 1; + break; + case 'p': + if (numpkeys < MAX_PKEYS) { + pkey[numpkeys++] = htons(strtoul(optarg,NULL,0)); + } else { + _DBG_ERROR("Too many pkeys.\n"); + return -1; + } + break; + case 'S': + if (numsids < MAX_SIDS) { + sid[numsids++] = hton64(strtoull(optarg,NULL,0)); + } else { + _DBG_ERROR("Too many sids.\n"); + return -1; + } + break; + case 'd': + debug = strtoul(optarg,NULL,0); + op_log_set_level(strtoul(optarg,NULL,0)); + break; + case 'r': + strcpy(remote,optarg); + break; + case 'x': + numtoggle = strtoul(optarg, NULL, 0); + if (numtoggle == ULONG_MAX) + numtoggle = 0; + break; + case 'X': + srctogglerate = strtoul(optarg, NULL, 0); + if (srctogglerate > MAX_SECONDS) srctogglerate = MAX_SECONDS; + break; + case 's': + seconds = strtoul(optarg, NULL, 0); + if (seconds > MAX_SECONDS) seconds = MAX_SECONDS; + break; + case 't': + error_threshold = strtoul(optarg, NULL, 0); + break; + case 'D': + delay = strtoul(optarg, NULL, 0); + break; + default: + usage(argv); + return -1; + } + } + + if (optind >= argc) { + usage(argv); + return -1; + } + + f=fopen(argv[optind],"r"); + if (f == NULL) { + fprintf(stderr,"Failed to open guid file (%s)\n",argv[optind+1]); + return -1; + } + + numsources = get_sources(); + if (numsources < 0) { + fprintf(stderr,"Could not read source port data.\n"); + ret = -1; + goto failopenguid; + } + + hfi = op_path_find_hfi("",&device); + if (!hfi || !device) { + fprintf(stderr,"Could not open HFI.\n"); + ret = -1; + goto failopenguid; + } + + context = op_path_open(device, port); + if (!context) { + fprintf(stderr, "Could not open path interface.\n"); + goto failopen; + } + + dest_ports = malloc(sizeof(record)*numdests); + if (!dest_ports) { + fprintf(stderr, "Could not allocate memory for destinations.\n"); + goto failmalloc; + } + + i=0; + while (!readrecord(f, &dest_ports[i])) { + i++; + if (i >= numdests) { + numdests = numdests * 2; + dest_ports = realloc(dest_ports, numdests * sizeof(record)); + if (!dest_ports) { + fprintf(stderr, "Could not allocate memory for destinations.\n"); + goto failmalloc; + } + } + } + + fclose(f); + f = NULL; + numdests=i; + _DBG_NOTICE("Read %u destinations and %u sources.\n", + numdests,numsources); + if (numsources == 0 || numdests == 0) goto fail; + + falsepos=falseneg=queries=passes=0; + + gettimeofday(&start_time, NULL); + next_src_toggle = start_time; + next_src_toggle.tv_sec += srctogglerate; + + srand48(start_time.tv_sec); + + if (enable_ports) { + _DBG_PRINT("Instructing the simulator to enable all ports.\n"); + for (i=0; i= _DBG_LVL_INFO || dest_ports[d].lid_fail_count > error_threshold || + dest_ports[d].guid_fail_count > error_threshold) { + fprint_path_record(stderr,"Query",&query); + if (err == 0) + print_path_record("Response",&response); + if (dest_ports[d].lid_fail_count > error_threshold || + dest_ports[d].guid_fail_count > error_threshold) { + seconds = 0; + _DBG_ERROR("Aborting test.\n"); + } + } + } + } + + _DBG_NOTICE("Completed %u queries for pass %d, %u false negatives, %u false positives.\n", + j, passes, falseneg, falsepos); + + gettimeofday(&now_time, NULL); + if ((srctogglerate != 0) && (numsources > 1) && + (now_time.tv_sec > next_src_toggle.tv_sec)) { + static int disabled=0; + unsigned k; + + if (!disabled) { + k = (unsigned)lrand48() % numsources; + src_ports[k].disable = 1; + src_portdisable(&src_ports[k]); + disabled=1; + } else { + for (k=0; k 0) { + _DBG_PRINT("Sleeping %u seconds before next pass.\n", delay); + my_sleep(delay); + } else { + my_sleep(1); + } + + gettimeofday(&end_time, NULL); + timersub(&end_time, &start_time, &elapsed_time); + passes++; + } while (elapsed_time.tv_sec < seconds); + + if (srctogglerate) for (i=0; iguidtable +# + +use strict; +use Sys::Hostname; +use Data::Dumper; +use Getopt::Long; +use Cwd; + +# Don't change these. +my $cwd = &Cwd::cwd(); +my $report_opts = ''; +my $ca_extract_opts = '-H -s SMs -s Switches -e LID -e PortGUID -e NodeDesc'; +my $sm_extract_opts = '-H -e SM.PortGUID'; +my $guid_table = "guidtable_$$"; + +sub trim($) +{ + my $scratch = @_[0]; + + $scratch =~ s/^\s+//; + $scratch =~ s/\s+$//; + + return $scratch; +} + +my $args=''; +my $mode_opt=''; +my $simulator=''; +my $duration=600; +my @sid= (); + +my %mode = ( + "baseline" => "-x 0 -X 0 -D 0 -s 0", + "porttoggle" => "-x 10 -X 0 -D 20", + "smfailover" => "-x 10 -X 0 -D 20", + "stresstest" => "-x 10 -X 60 -D 20" +); + +GetOptions( + "duration=i" => \$duration, + "mode=s" => \$mode_opt, + "fsim=s" => \$simulator, + "sid=s" => \@sid); + +if (!($mode{$mode_opt})) { + my $m; + print "You must specify a mode.\n"; + print "Valid Modes are:\n"; + foreach $m (%mode) { + print "$m\n"; + } + die; +} + +$args = "$args " . $mode{$mode_opt}; + +my $sidi; +foreach $sidi (@sid) { + $args = "$args -S $sidi"; +} + +if ($mode_opt ne "baseline") { + $args = "$args -s $duration"; +} + +my $host = hostname; +($host) = split(/\./,$host); + +# We're playing a game here. We extract a list of the SMs and source ports +# then use grep to remove them from the list of valid destination ports. +# This prevents the tool from turning off the SM's ports. +open(LOCAL_FD,"/usr/sbin/opainfo -o info | grep GUID: |") || die "Could not get portinfo."; +open(OUTPUT_FD,">sms.$$") || die "Could not open output file."; + +until ( eof LOCAL_FD ) { + my $line; + my $guid; + my $dummy; + + $line = readline LOCAL_FD; + # Subnet: 0xfe80000000000000 GUID: 0x00117500005a6e8a GUID Cap: 5 + $line = trim($line); + ($dummy, $dummy, $dummy, $guid) = split(/ +/, $line); + + print OUTPUT_FD "$guid\n"; +} +close(LOCAL_FD); +close(OUTPUT_FD); + +system "opareport -x $report_opts >$$" || die "Failed to generate opareport."; +system "opaxmlextract $sm_extract_opts <$$ >>sms.$$" || die "Failed to generate list of SMs.\n"; +system "opaxmlextract $ca_extract_opts <$$ | grep -v -f sms.$$ >$guid_table" || die "Failed to generate list of destinations.\n"; + +unlink "$$"; +unlink "sms.$$"; + +my $arg; + +foreach $arg (@ARGV) { + $args = "$args $arg"; +} + +#system "cat $guid_table"; +print "$cwd/opa_osd_exercise $args $guid_table\n"; +system "$cwd/opa_osd_exercise $args $guid_table"; +unlink $guid_table; diff --git a/opasadb/path_tools/load/Makefile b/opasadb/path_tools/load/Makefile new file mode 100644 index 0000000..4e9d10b --- /dev/null +++ b/opasadb/path_tools/load/Makefile @@ -0,0 +1,163 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** +# Makefile for opasadb/path_tools/load + +# Include Make Control Settings +include $(TL_DIR)/$(PROJ_FILE_DIR)/Makesettings.project + +#=============================================================================# +# Definitions: +#-----------------------------------------------------------------------------# + +# Name of SubProjects +DS_SUBPROJECTS = +# name of executable or downloadable image +EXECUTABLE = $(BUILDDIR)/opa_osd_load$(EXE_SUFFIX) +# list of sub directories to build +DIRS = +# C files (.c) +CFILES = \ + opa_osd_load.c \ + # Add more c files here +# C++ files (.cpp) +CCFILES = \ + # Add more cpp files here +# lex files (.lex) +LFILES = \ + # Add more lex files here +# archive library files (basename, $ARFILES will add MOD_LIB_DIR/prefix and suffix) +LIBFILES = +# Windows Resource Files (.rc) +RSCFILES = +# Windows IDL File (.idl) +IDLFILE = +# Windows Linker Module Definitions (.def) file for dll's +DEFFILE = +# targets to build during INCLUDES phase (add public includes here) +INCLUDE_TARGETS = \ + # Add more h hpp files here +# Non-compiled files +MISC_FILES = opasadb.xml +# all source files +SOURCES = $(CFILES) $(CCFILES) $(LFILES) $(RSCFILES) $(IDLFILE) +# Source files to include in DSP File +DSP_SOURCES = $(INCLUDE_TARGETS) $(SOURCES) $(MISC_FILES) \ + $(RSCFILES) $(DEFFILE) $(MAKEFILE) +# all object files +OBJECTS = $(CFILES:.c=$(OBJ_SUFFIX)) $(CCFILES:.cpp=$(OBJ_SUFFIX)) \ + $(LFILES:.lex=$(OBJ_SUFFIX)) \ + # Add more object files here +RSCOBJECTS = $(RSCFILES:.rc=$(RES_SUFFIX)) +# targets to build during LIBS phase +LIB_TARGETS_IMPLIB = +LIB_TARGETS_ARLIB = +LIB_TARGETS_EXP = $(LIB_TARGETS_IMPLIB:$(ARLIB_SUFFIX)=$(EXP_SUFFIX)) +LIB_TARGETS_MISC = +# targets to build during CMDS phase +SHLIB_VERSION = +CMD_TARGETS_SHLIB = +CMD_TARGETS_EXE = $(EXECUTABLE) +CMD_TARGETS_MISC = +# files to remove during clean phase +CLEAN_TARGETS_MISC = +CLEAN_TARGETS = $(OBJECTS) $(RSCOBJECTS) $(IDL_TARGETS) $(CLEAN_TARGETS_MISC) +# other files to remove during clobber phase +CLOBBER_TARGETS_MISC= opasadb.xml +# sub-directory to install to within bin +BIN_SUBDIR = +# sub-directory to install to within include +INCLUDE_SUBDIR = + +# Additional Settings +#CLOCALDEBUG = User defined C debugging compilation flags [Empty] +#CCLOCALDEBUG = User defined C++ debugging compilation flags [Empty] +# User defined C flags for compiling +# User defined C++ flags for compiling +#CCLOCAL = +#BSCLOCAL = User flags for Browse File Builder [Empty] +#DEPENDLOCAL = user defined makedepend flags [Empty] +#LINTLOCAL = User defined lint flags [Empty] +# User include directories to search for C/C++ headers +LOCAL_INCLUDE_DIRS = .. +#LDLOCAL = User defined C flags for linking [Empty] +#IMPLIBLOCAL = User flags for Object Lirary Manager [Empty] +#MIDLLOCAL = User flags for IDL compiler [Empty] +#RSCLOCAL = User flags for resource compiler [Empty] +# User libraries to include in dependencies +LOCALDEPLIBS = IbPrint $(IBACCESS_USER_LIBS) opamgt-priv Xml +# User libraries to use when linking (in addition to LOCALDEPLIBS) +# opasadb is a shared library, not needed in LOCALDEPLIBS +LOCALLIBS = $(OPENIB_USER_LIBS) opasadb rt expat +# User library directories for libpaths +LOCAL_LIB_DIRS = $(OPENIB_USER_LIB_DIRS) $(IBACCESS_USER_LIB_DIRS) + +CLOCAL = $(CPIE) + +# Include Make Rules definitions and rules +include $(TL_DIR)/IbaTools/Makerules.module + +#=============================================================================# +# Overrides: +#-----------------------------------------------------------------------------# +# C++ optimization flags, default lets build config decide +#CCOPT = +# C optimization flags, default lets build config decide +COPT = -g -D_GNU_SOURCE -Wall -fPIE +#SUBSYSTEM = Subsystem to build for (none, console or windows) [none] +# (Windows Only) +#USEMFC = How Windows MFC should be used (none, static, shared, no_mfc) [none] +# (Windows Only) +#=============================================================================# + +#=============================================================================# +# Rules: +#-----------------------------------------------------------------------------# +# process Sub-directories +include $(TL_DIR)/Makerules/Maketargets.toplevel + +# build cmds and libs +include $(TL_DIR)/Makerules/Maketargets.build + +# install for includes, libs and cmds phases +include $(TL_DIR)/Makerules/Maketargets.install + +# install for stage phase +#include $(TL_DIR)/Makerules/Maketargets.stage +STAGE:: + $(VS)$(STAGE_INSTALL) $(STAGE_INSTALL_DIR_OPT) $(PROJ_STAGE_OPA_SA_DB_DIR) $(EXECUTABLE) + $(VS)$(STAGE_INSTALL) $(STAGE_INSTALL_DIR_OPT) $(PROJ_STAGE_DIR)/config $(MISC_FILES) + +# Unit test execution +#include $(TL_DIR)/Makerules/Maketargets.runtest + +#=============================================================================# + +#=============================================================================# +# DO NOT DELETE THIS LINE -- make depend depends on it. +#=============================================================================# diff --git a/opasadb/path_tools/load/opa_osd_load.c b/opasadb/path_tools/load/opa_osd_load.c new file mode 100644 index 0000000..ca6c403 --- /dev/null +++ b/opasadb/path_tools/load/opa_osd_load.c @@ -0,0 +1,40 @@ +/* BEGIN_ICS_COPYRIGHT2 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT2 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +/* + * This program is designed to populate the opasadb with pre-constructed + * subnet, virtual fabrics, source ports, and pathrecords. + */ +#include +int main(void) { + printf("This tool has not been implemented yet.\n"); + return 1; +} diff --git a/opasadb/path_tools/load/opasadb.xml b/opasadb/path_tools/load/opasadb.xml new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/opasadb/path_tools/load/opasadb.xml diff --git a/opasadb/path_tools/perf/Makefile b/opasadb/path_tools/perf/Makefile new file mode 100644 index 0000000..5029c4a --- /dev/null +++ b/opasadb/path_tools/perf/Makefile @@ -0,0 +1,162 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** +# Makefile for opasadb/route_tools + +# Include Make Control Settings +include $(TL_DIR)/$(PROJ_FILE_DIR)/Makesettings.project + +#=============================================================================# +# Definitions: +#-----------------------------------------------------------------------------# + +# Name of SubProjects +DS_SUBPROJECTS = +# name of executable or downloadable image +EXECUTABLE = $(BUILDDIR)/opa_osd_perf$(EXE_SUFFIX) +# list of sub directories to build +DIRS = +# C files (.c) +CFILES = \ + opa_osd_perf.c \ + # Add more c files here +# C++ files (.cpp) +CCFILES = \ + # Add more cpp files here +# lex files (.lex) +LFILES = \ + # Add more lex files here +# archive library files (basename, $ARFILES will add MOD_LIB_DIR/prefix and suffix) +LIBFILES = +# Windows Resource Files (.rc) +RSCFILES = +# Windows IDL File (.idl) +IDLFILE = +# Windows Linker Module Definitions (.def) file for dll's +DEFFILE = +# targets to build during INCLUDES phase (add public includes here) +INCLUDE_TARGETS = \ + # Add more h hpp files here +# Non-compiled files +MISC_FILES = +# all source files +SOURCES = $(CFILES) $(CCFILES) $(LFILES) $(RSCFILES) $(IDLFILE) +# Source files to include in DSP File +DSP_SOURCES = $(INCLUDE_TARGETS) $(SOURCES) $(MISC_FILES) \ + $(RSCFILES) $(DEFFILE) $(MAKEFILE) +# all object files +OBJECTS = $(CFILES:.c=$(OBJ_SUFFIX)) $(CCFILES:.cpp=$(OBJ_SUFFIX)) \ + $(LFILES:.lex=$(OBJ_SUFFIX)) \ + # Add more object files here +RSCOBJECTS = $(RSCFILES:.rc=$(RES_SUFFIX)) +# targets to build during LIBS phase +LIB_TARGETS_IMPLIB = +LIB_TARGETS_ARLIB = +LIB_TARGETS_EXP = $(LIB_TARGETS_IMPLIB:$(ARLIB_SUFFIX)=$(EXP_SUFFIX)) +LIB_TARGETS_MISC = +# targets to build during CMDS phase +SHLIB_VERSION = +CMD_TARGETS_SHLIB = +CMD_TARGETS_EXE = $(EXECUTABLE) +CMD_TARGETS_MISC = +# files to remove during clean phase +CLEAN_TARGETS_MISC = +CLEAN_TARGETS = $(OBJECTS) $(RSCOBJECTS) $(IDL_TARGETS) $(CLEAN_TARGETS_MISC) +# other files to remove during clobber phase +CLOBBER_TARGETS_MISC= +# sub-directory to install to within bin +BIN_SUBDIR = +# sub-directory to install to within include +INCLUDE_SUBDIR = + +# Additional Settings +#CLOCALDEBUG = User defined C debugging compilation flags [Empty] +#CCLOCALDEBUG = User defined C++ debugging compilation flags [Empty] +# User defined C flags for compiling +# User defined C++ flags for compiling +#CCLOCAL = +#BSCLOCAL = User flags for Browse File Builder [Empty] +#DEPENDLOCAL = user defined makedepend flags [Empty] +#LINTLOCAL = User defined lint flags [Empty] +# User include directories to search for C/C++ headers +LOCAL_INCLUDE_DIRS = +#LDLOCAL = User defined C flags for linking [Empty] +#IMPLIBLOCAL = User flags for Object Lirary Manager [Empty] +#MIDLLOCAL = User flags for IDL compiler [Empty] +#RSCLOCAL = User flags for resource compiler [Empty] +# User libraries to include in dependencies +LOCALDEPLIBS = IbPrint $(IBACCESS_USER_LIBS) opamgt-priv +# User libraries to use when linking (in addition to LOCALDEPLIBS) +# opasadb is a shared library, not needed in LOCALDEPLIBS +LOCALLIBS = $(OPENIB_USER_LIBS) opasadb rt +# User library directories for libpaths +LOCAL_LIB_DIRS = $(OPENIB_USER_LIB_DIRS) $(IBACCESS_USER_LIB_DIRS) + +CLOCAL = $(CPIE) + +# Include Make Rules definitions and rules +include $(TL_DIR)/IbaTools/Makerules.module + +#=============================================================================# +# Overrides: +#-----------------------------------------------------------------------------# +# C++ optimization flags, default lets build config decide +#CCOPT = +# C optimization flags, default lets build config decide +COPT = -g -D_GNU_SOURCE -Wall -fPIE +#SUBSYSTEM = Subsystem to build for (none, console or windows) [none] +# (Windows Only) +#USEMFC = How Windows MFC should be used (none, static, shared, no_mfc) [none] +# (Windows Only) +#=============================================================================# + +#=============================================================================# +# Rules: +#-----------------------------------------------------------------------------# +# process Sub-directories +include $(TL_DIR)/Makerules/Maketargets.toplevel + +# build cmds and libs +include $(TL_DIR)/Makerules/Maketargets.build + +# install for includes, libs and cmds phases +include $(TL_DIR)/Makerules/Maketargets.install + +# install for stage phase +#include $(TL_DIR)/Makerules/Maketargets.stage +STAGE:: + $(VS)$(STAGE_INSTALL) $(STAGE_INSTALL_DIR_OPT) $(PROJ_STAGE_OPA_SA_DB_DIR) $(EXECUTABLE) build_table.pl + +# Unit test execution +#include $(TL_DIR)/Makerules/Maketargets.runtest + +#=============================================================================# + +#=============================================================================# +# DO NOT DELETE THIS LINE -- make depend depends on it. +#=============================================================================# diff --git a/opasadb/path_tools/perf/build_table.pl b/opasadb/path_tools/perf/build_table.pl new file mode 100755 index 0000000..9f3f8da --- /dev/null +++ b/opasadb/path_tools/perf/build_table.pl @@ -0,0 +1,53 @@ +#!/usr/bin/perl +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +#[ICS VERSION STRING: unknown] +# +# This tool must be run as root. +# +# It builds a table of fabric simulator HCA nodes, the table +# can then be used by opa_osd_perf tool. +# + +use strict; + +# Don't change these. +my $report_opts = ''; +my $ca_extract_opts = '-H -s SMs -s Switches -e LID -e PortGUID -e NodeDesc'; +my $sm_extract_opts = '-H -e SM.PortGUID'; +my $guid_table = "guidtable_$$"; + +system "opareport -x $report_opts >$$" || die "Failed to generate opareport."; +system "opaxmlextract $sm_extract_opts <$$ >>sms.$$" || die "Failed to generate list of SMs.\n"; +system "opaxmlextract $ca_extract_opts <$$ | grep -v -f sms.$$ >$guid_table" || die "Failed to generate list of destinations.\n"; + +unlink "$$"; +unlink "sms.$$"; + diff --git a/opasadb/path_tools/perf/opa_osd_perf.c b/opasadb/path_tools/perf/opa_osd_perf.c new file mode 100644 index 0000000..ab8b453 --- /dev/null +++ b/opasadb/path_tools/perf/opa_osd_perf.c @@ -0,0 +1,433 @@ +/* BEGIN_ICS_COPYRIGHT2 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT2 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +/* + * This program is meant to determine the performance of the path query system. + * The destination file is generated by the perf script: + * ./build_table.pl + * The resulting file guidtable_xxxxx can be used with the tool: + * ./opa_osd_perf -q 20000000 -p 0x8001 guidtable_xxxxx + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "opasadb_path.h" +#include "opasadb_debug.h" + +#define MAX_SOURCE_PORTS (UMAD_CA_MAX_PORTS * UMAD_MAX_DEVICES) +#define MAX_SIDS 8 +#define MAX_PKEYS 8 + + +#define DELIMITER ";" + +static char remote[512]; + +typedef struct _src_record { + int disable; + uint64_t prefix; + uint64_t guid; + uint16_t base_lid; + uint16_t num_lids; + uint16_t port_num; + char hfi_num; +} src_record; + +typedef struct _record { + int disable; + int simulated; + uint64_t guid; + uint16_t lid; + char name[64]; + int guid_fail_count; + int lid_fail_count; +} record; + + +static int +readline(FILE *f, char *s, int max) +{ + int i, c; + + memset(s,0,max); + i=0; + c=fgetc(f); + + while (c !='\n' && !feof(f) && i < max) { + s[i++]=c; + c=fgetc(f); + } + return i; +} + + +static int +readrecord(FILE *f, record *r) +{ + char *p, *l; + char buffer[1024]; + + memset(r, 0, sizeof(record)); + + if (readline(f, buffer, 1024) <=0) + return -1; + + r->disable = 0; + + p = strtok_r(buffer, DELIMITER, &l); + if (!p) + return -1; + r->lid = htons(strtol(p,NULL,0)); + + p = strtok_r(NULL, DELIMITER, &l); + if (!p) + return -1; + r->guid = hton64(strtoull(p,NULL,0)); + + p = strtok_r(NULL,DELIMITER, &l); + if (!p) + return -1; + strcpy(r->name, p); + + r->simulated = strstr(p,"Sim") != NULL; + if (!r->simulated) { + /* parse name */ + p = strstr(r->name," "); + if (p) + *p=0; + } + + return 0; +} + +static void +usage(char **argv) +{ + fprintf(stderr, "Usage: %s [opts] guidtable\n", argv[0]); + fprintf(stderr, "Test performance of the distributed SA shared memory database.\n"); + fprintf(stderr, "\toptions include:\n"); + fprintf(stderr, "\t--help\n"); + fprintf(stderr, "\t\tProvide this help text.\n"); + fprintf(stderr, "\t-q \n"); + fprintf(stderr, "\t\tRun at least queries.\n"); + fprintf(stderr, "\t-p \n"); + fprintf(stderr, "\t\tInclude in the searches.\n"); + fprintf(stderr,"\t\t(Can be specified up to " add_quotes(MAX_PKEYS) + " times.)\n"); + fprintf(stderr, "\t-S \n"); + fprintf(stderr, "\t\tInclude in the searches.\n"); + fprintf(stderr,"\t\t(Can be specified up to " add_quotes(MAX_SIDS) + " times. Note that\n"); + fprintf(stderr,"\t\tproviding both SIDs and pkeys may cause problems." + ")\n"); + fprintf(stderr, "\n"); + fprintf(stderr, + "'guidtable' is a text file that lists the destination\n"); + fprintf(stderr, + "guids and lids (i.e., from build_table.pl)\n"); + fprintf(stderr, + "\nExample:\t%s -q 100000 -p 0x8001 guidtable\n", argv[0]); +} + +static record *dest_ports; +static src_record src_ports[MAX_SOURCE_PORTS]; +int numsources = 0; + +int +get_sources(void) +{ + umad_port_t port; + char ca_names[UMAD_MAX_DEVICES][UMAD_CA_NAME_LEN]; + int ca_count; + int i, err; + + ca_count = umad_get_cas_names(ca_names, UMAD_MAX_DEVICES); + + for (i = 0; i < ca_count; i++) { + umad_ca_t ca; + int j; + + err = umad_get_ca(ca_names[i], &ca); + if (err) { + _DBG_ERROR("Failed to open %s\n", ca_names[i]); + return -1; + } + + for (j = 1; j <= ca.numports; j++) { + err = umad_get_port(ca_names[i], j, &port); + if (err) { + _DBG_ERROR("Failed to get info on port %d of" + " %s\n", j, ca_names[i]); + umad_release_ca(&ca); + return -1; + } + + if (port.state == IBV_PORT_ACTIVE) { + src_ports[numsources].disable = + (port.state != IBV_PORT_ACTIVE); + src_ports[numsources].prefix = port.gid_prefix; + src_ports[numsources].guid = port.port_guid; + src_ports[numsources].base_lid = + htons(port.base_lid); + src_ports[numsources].num_lids = + 1 << (port.lmc); + src_ports[numsources].port_num = j; + src_ports[numsources].hfi_num = i + 1; + numsources++; + } + } + } + return numsources; +} + +int +main(int argc, char **argv) +{ + FILE *f; + int c, err; + uint16_t port; + unsigned i, numdests; + uint64_t sid[MAX_SIDS]; + unsigned pkey[MAX_PKEYS]; + unsigned numpkeys, numsids; + uint64_t falsepos, falseneg, passes, queries, req_queries, perf; + struct timeval start_time, end_time, elapsed_time; + void *context; + struct ibv_context *hfi; + struct ibv_device *device; + + setlocale(LC_ALL, ""); + + /* Default values. */ + strcpy(remote,"strife"); + port = 1; + req_queries = 0; + numdests = 1024; + numsources = 0; + numpkeys = 0; + numsids = 0; + + if (argc > 1){ + if (!strcmp(argv[1], "--help")){ + usage(argv); + exit(0); + } + } + + while ((c = getopt(argc, argv, "d:q:p:S:")) != EOF) { + switch (c) { + case 'p': + if (numpkeys < MAX_PKEYS) { + pkey[numpkeys++] = htons( + strtoul(optarg, NULL, 0)); + } else { + _DBG_ERROR("Too many pkeys.\n"); + return -1; + } + break; + case 'S': + if (numsids < MAX_SIDS) { + sid[numsids++] = hton64( + strtoull(optarg, NULL, 0)); + } else { + _DBG_ERROR("Too many sids.\n"); + return -1; + } + break; + case 'q': + req_queries = strtoul(optarg, NULL, 0); + if (req_queries == ULONG_MAX) { + _DBG_ERROR("Invalid req_queries arg: %s", optarg); + return -1; + } + break; + default: + usage(argv); + return -1; + } + } + + if (optind >= argc) { + usage(argv); + return -1; + } + + f=fopen(argv[optind], "r"); + if (f == NULL) { + fprintf(stderr, "Failed to open guid file (%s)\n", + argv[optind]); + return -1; + } + + numsources = get_sources(); + if (numsources < 0) { + fprintf(stderr, "Could not read source port data.\n"); + fclose(f); + return -1; + } + + hfi = op_path_find_hfi("",&device); + if (!hfi || !device) { + fprintf(stderr,"Could not open HFI.\n"); + fclose(f); + return -1; + } + + context = op_path_open(device, port); + if (!context) { + fprintf(stderr, "Could not open path interface.\n"); + goto failopen; + } + + dest_ports = malloc(sizeof(record) * numdests); + if (!dest_ports) { + fprintf(stderr, "Could not allocate memory for destinations.\n"); + goto failmalloc; + } + + i=0; + while (!readrecord(f, &dest_ports[i])) { + i++; + if (i >= numdests) { + numdests = numdests * 2; + dest_ports = realloc(dest_ports, numdests * sizeof(record)); + if (!dest_ports) { + fprintf(stderr, "Could not allocate memory for destinations.\n"); + goto failmalloc; + } + } + } + + numdests = i; + _DBG_NOTICE("Read %u destinations and %u sources.\n", + numdests, numsources); + if (numsources == 0 || numdests == 0) goto fail; + + falsepos = falseneg = queries = passes = 0; + + gettimeofday(&start_time, NULL); + + srand48(start_time.tv_sec); + + do { + unsigned j; + + for (j=0; j 1) { + perf = queries * 1000 / (elapsed_time.tv_sec * 1000 + + elapsed_time.tv_usec /1000); + _DBG_PRINT("Perf: %lu queries/sec.\n", perf); + } + +fail: + free(dest_ports); +failmalloc: + op_path_close(context); +failopen: + ibv_close_device(hfi); + fclose(f); + return 0; +} diff --git a/opasadb/path_tools/query/Makefile b/opasadb/path_tools/query/Makefile new file mode 100644 index 0000000..0b6e480 --- /dev/null +++ b/opasadb/path_tools/query/Makefile @@ -0,0 +1,162 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** +# Makefile for opasadb/route_tools + +# Include Make Control Settings +include $(TL_DIR)/$(PROJ_FILE_DIR)/Makesettings.project + +#=============================================================================# +# Definitions: +#-----------------------------------------------------------------------------# + +# Name of SubProjects +DS_SUBPROJECTS = +# name of executable or downloadable image +EXECUTABLE = $(BUILDDIR)/opa_osd_query$(EXE_SUFFIX) +# list of sub directories to build +DIRS = +# C files (.c) +CFILES = \ + mydumppath.c \ + opa_osd_query.c \ + # Add more c files here +# C++ files (.cpp) +CCFILES = \ + # Add more cpp files here +# lex files (.lex) +LFILES = \ + # Add more lex files here +# archive library files (basename, $ARFILES will add MOD_LIB_DIR/prefix and suffix) +LIBFILES = +# Windows Resource Files (.rc) +RSCFILES = +# Windows IDL File (.idl) +IDLFILE = +# Windows Linker Module Definitions (.def) file for dll's +DEFFILE = +# targets to build during INCLUDES phase (add public includes here) +INCLUDE_TARGETS = \ + # Add more h hpp files here +# Non-compiled files +MISC_FILES = +# all source files +SOURCES = $(CFILES) $(CCFILES) $(LFILES) $(RSCFILES) $(IDLFILE) +# Source files to include in DSP File +DSP_SOURCES = $(INCLUDE_TARGETS) $(SOURCES) $(MISC_FILES) \ + $(RSCFILES) $(DEFFILE) $(MAKEFILE) +# all object files +OBJECTS = $(CFILES:.c=$(OBJ_SUFFIX)) $(CCFILES:.cpp=$(OBJ_SUFFIX)) \ + $(LFILES:.lex=$(OBJ_SUFFIX)) \ + # Add more object files here +RSCOBJECTS = $(RSCFILES:.rc=$(RES_SUFFIX)) +# targets to build during LIBS phase +LIB_TARGETS_IMPLIB = +LIB_TARGETS_ARLIB = +LIB_TARGETS_EXP = $(LIB_TARGETS_IMPLIB:$(ARLIB_SUFFIX)=$(EXP_SUFFIX)) +LIB_TARGETS_MISC = +# targets to build during CMDS phase +SHLIB_VERSION = +CMD_TARGETS_SHLIB = +CMD_TARGETS_EXE = $(EXECUTABLE) +CMD_TARGETS_MISC = +# files to remove during clean phase +CLEAN_TARGETS_MISC = +CLEAN_TARGETS = $(OBJECTS) $(RSCOBJECTS) $(IDL_TARGETS) $(CLEAN_TARGETS_MISC) +# other files to remove during clobber phase +CLOBBER_TARGETS_MISC= +# sub-directory to install to within bin +BIN_SUBDIR = +# sub-directory to install to within include +INCLUDE_SUBDIR = + +# Additional Settings +#CLOCALDEBUG = User defined C debugging compilation flags [Empty] +#CCLOCALDEBUG = User defined C++ debugging compilation flags [Empty] +# User defined C flags for compiling +# User defined C++ flags for compiling +#CCLOCAL = +#BSCLOCAL = User flags for Browse File Builder [Empty] +#DEPENDLOCAL = user defined makedepend flags [Empty] +#LINTLOCAL = User defined lint flags [Empty] +# User include directories to search for C/C++ headers +LOCAL_INCLUDE_DIRS = .. +#LDLOCAL = User defined C flags for linking [Empty] +#IMPLIBLOCAL = User flags for Object Lirary Manager [Empty] +#MIDLLOCAL = User flags for IDL compiler [Empty] +#RSCLOCAL = User flags for resource compiler [Empty] +# User libraries to include in dependencies +LOCALDEPLIBS = IbPrint $(IBACCESS_USER_LIBS) opamgt-priv +# User libraries to use when linking (in addition to LOCALDEPLIBS) +# opasadb is a shared library, not needed in LOCALDEPLIBS +LOCALLIBS = $(OPENIB_USER_LIBS) opasadb rt +# User library directories for libpaths +LOCAL_LIB_DIRS = $(OPENIB_USER_LIB_DIRS) $(IBACCESS_USER_LIB_DIRS) +CLOCAL = $(CPIE) + +# Include Make Rules definitions and rules +include $(TL_DIR)/IbaTools/Makerules.module + +#=============================================================================# +# Overrides: +#-----------------------------------------------------------------------------# +# C++ optimization flags, default lets build config decide +#CCOPT = +# C optimization flags, default lets build config decide +COPT = -g -D_GNU_SOURCE -Wall -fPIE +#SUBSYSTEM = Subsystem to build for (none, console or windows) [none] +# (Windows Only) +#USEMFC = How Windows MFC should be used (none, static, shared, no_mfc) [none] +# (Windows Only) +#=============================================================================# + +#=============================================================================# +# Rules: +#-----------------------------------------------------------------------------# +# process Sub-directories +include $(TL_DIR)/Makerules/Maketargets.toplevel + +# build cmds and libs +include $(TL_DIR)/Makerules/Maketargets.build + +# install for includes, libs and cmds phases +include $(TL_DIR)/Makerules/Maketargets.install + +# install for stage phase +#include $(TL_DIR)/Makerules/Maketargets.stage +STAGE:: + $(VS)$(STAGE_INSTALL) $(STAGE_INSTALL_DIR_OPT) $(PROJ_STAGE_OPA_SA_DB_DIR) $(EXECUTABLE) + +# Unit test execution +#include $(TL_DIR)/Makerules/Maketargets.runtest + +#=============================================================================# + +#=============================================================================# +# DO NOT DELETE THIS LINE -- make depend depends on it. +#=============================================================================# diff --git a/opasadb/path_tools/query/mydumppath.c b/opasadb/path_tools/query/mydumppath.c new file mode 100644 index 0000000..2a443f0 --- /dev/null +++ b/opasadb/path_tools/query/mydumppath.c @@ -0,0 +1,31 @@ +/* BEGIN_ICS_COPYRIGHT2 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT2 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ +#include "dumppath.c" diff --git a/opasadb/path_tools/query/opa_osd_query.c b/opasadb/path_tools/query/opa_osd_query.c new file mode 100644 index 0000000..1f3371d --- /dev/null +++ b/opasadb/path_tools/query/opa_osd_query.c @@ -0,0 +1,226 @@ +/* BEGIN_ICS_COPYRIGHT2 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT2 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +/* + * This program demonstrates how to use the op_path_path functions. + * + * It allows the user to create an arbitrary path query and to view + * the response. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "dumppath.h" +#include "opasadb_path.h" +#include "opasadb_debug.h" + +#define DEFAULT_SID 0x1000117500000000 + +void Usage() +{ + fprintf(stderr,"Usage: opa_osd_query (options)\n"); + fprintf(stderr,"Query the opasadb for path records\n\n"); + fprintf(stderr,"Options are:\n"); + fprintf(stderr, "\t-v/--verbose\t\tDebug Level. Should be a number between 1 and 7\n"); + fprintf(stderr, "\t-s/--slid\t\tSource LID\n"); + fprintf(stderr, "\t-d/--dlid\t\tDestination LID\n"); + fprintf(stderr, "\t-S/--sgid\t\tSource GID (in GID or inet6 format)\n"); + fprintf(stderr, "\t-D/--dgid\t\tDestination GID (in GID or inet6 format)\n"); + fprintf(stderr, "\t-k/--pkey\t\tPartition Key\n"); + fprintf(stderr, "\t-i/--sid\t\tService ID\n"); + fprintf(stderr, "\t-h/--hfi\t\tThe HFI to use (Defaults to the first hfi)\n"); + fprintf(stderr, "\t-p/--port\t\tThe port to use (Defaults to the first port)\n"); + fprintf(stderr, "\t--help\t\t\tProvide full help text\n"); + + exit(2); +} + + +void Usage_full() +{ + fprintf(stderr,"Usage: opa_osd_query (options)\n"); + fprintf(stderr,"Query the opasadb for path records\n\n"); + fprintf(stderr,"Options are:\n"); + fprintf(stderr, "\t-v/--verbose\t\tDebug Level. Should be a number between 1 and 7\n"); + fprintf(stderr, "\t-s/--slid\t\tSource LID\n"); + fprintf(stderr, "\t-d/--dlid\t\tDestination LID\n"); + fprintf(stderr, "\t-S/--sgid\t\tSource GID (in GID or inet6 format)\n"); + fprintf(stderr, "\t-D/--dgid\t\tDestination GID (in GID or inet6 format)\n"); + fprintf(stderr, "\t-k/--pkey\t\tPartition Key\n"); + fprintf(stderr, "\t-i/--sid\t\tService ID\n"); + fprintf(stderr, "\t-h/--hfi\t\tThe HFI to use (Defaults to the first hfi)\n"); + fprintf(stderr, "\t-p/--port\t\tThe port to use (Defaults to the first port)\n"); + fprintf(stderr, "\t--help\t\t\tProvide full help text\n"); + fprintf(stderr,"\n" + "This tool allows you to create an arbitrary path\n" + "query and view the result. \n\n" + "All arguments are optional, but ill-formed\n" + "queries can be expected to fail. You must provide\n" + "at least a pair of lids, or a pair of gids.\n\n" + "Mixing of lids and gid in query is not permitted.\n\n" + "SID or PKey can also be provided but not both.\n\n" + "If you have multiple HFIs, the same lid can appear on\n" + "more than one HFI, so you must specify which HFI to use\n" + "when searching by lids and you have multiple HFIs.\n\n" + "Numbers can be in decimal, hex or octal.\n\n" + "Gids can be specified in GID format (\"0x00000000:0x00000000\")\n" + "or in Inet6 format (\"x:x:x:x:x:x:x:x\").\n\n" + "The HFI can be identified by name (\"hfi1_0\") or by\n" + "number (1, 2, 3, et cetera)\n\n" + "Example:\topa_osd_query -s2 -d4\n"); + exit(0); +} + +int main(int argc, char **argv) +{ + int err, debug; + char *hfi_name = NULL; + int port = 1; + + op_path_rec_t query; + op_path_rec_t response; + + struct ibv_context *context; + struct ibv_device *device; + void *hfi; + + memset(&query,0,sizeof(query)); + memset(&response,0,sizeof(response)); + + do { + int c; + + static char *short_options = "v:h:p:s:d:S:D:k:i:"; + static struct option long_options[] = { + { .name = "verbose", .has_arg = 1, .val = 'v' }, + { .name = "slid", .has_arg = 1, .val = 's' }, + { .name = "dlid", .has_arg = 1, .val = 'd' }, + { .name = "sgid", .has_arg = 1, .val = 'S' }, + { .name = "dgid", .has_arg = 1, .val = 'D' }, + { .name = "pkey", .has_arg = 1, .val = 'k' }, + { .name = "sid", .has_arg = 1, .val = 'i' }, + { .name = "hfi", .has_arg = 1, .val = 'h' }, + { .name = "port", .has_arg = 1, .val = 'p' }, + { .name = "help", .has_arg = 0, .val = '$' }, + {0} + }; + + c = getopt_long(argc, argv, short_options, long_options, NULL); + if (c == -1) + break; + + switch (c) { + case 'v': debug = strtol(optarg,NULL,0); op_log_set_level(debug); break; + case 'h': hfi_name = (char*)strdupa(optarg); break; + case 'p': port = strtol(optarg,NULL,0); break; + case 's': query.slid = htons(strtol(optarg,NULL,0)); break; + case 'd': query.dlid = htons(strtol(optarg,NULL,0)); break; + case 'k': query.pkey = htons(strtol(optarg,NULL,0)); break; + case 'i': query.service_id = hton64(strtoll(optarg, NULL, 0)); break; + case 'S': + if (!parse_gid(optarg, &query.sgid)) { + fprintf(stderr, "Badly formatted SGID.\n"); + return -1; + } + break; + case 'D': + if (!parse_gid(optarg, &query.dgid)) { + fprintf(stderr, "Badly formatted DGID.\n"); + return -1; + } + break; + case '$': + Usage_full(); //exits + break; + default: + Usage(); //exits + break; + } + } while (1); + + if ((query.pkey == 0) && (query.service_id == 0)) { + query.service_id = hton64(DEFAULT_SID); + } + print_path_record("Query Parameters", &query); + if ((query.pkey != 0) && (query.service_id != 0)) { + fprintf(stderr, "Query using both Service ID and PKey not supported\n"); + return -1; + } + /* + * Finds and opens the HFI. + */ + hfi = op_path_find_hfi(hfi_name,&device); + if (!device || !hfi) { + fprintf(stderr, "Could not open device %s, error code %d\n", (hfi_name?hfi_name:""), errno); + return -1; + } else { + fprintf(stderr,"Using device %s\n", + device->name); + } + + /* + * op_path_find_hfi maps the device name to an ibv_device + * structure. op_path_open opens a channel to the SM + * using the specified device and the specified port. + */ + if ((context=op_path_open(device,port)) == NULL) { + fprintf(stderr, "Could not access the Distributed SA. This may mean that\n" + "the ibacm/dsap has not been started, or that it has not been able\n" + "to contact the SA.\n"); + return -1; + } + + err = op_path_get_path_by_rec(context, + &query, + &response); + + if (err == EINVAL || err == ENOENT) { + printf("No path found that matches this query.\n"); + } else if (err) { + printf("******\n" + "Error: Get Path returned %d for query: %s\n" + "******\n", + err, strerror(err)); + } else { + print_path_record("Result",&response); + } + + ibv_close_device(hfi); + op_path_close(context); + + return 0; +} diff --git a/opasadb/path_tools/query_many/Makefile b/opasadb/path_tools/query_many/Makefile new file mode 100644 index 0000000..b7ff7d4 --- /dev/null +++ b/opasadb/path_tools/query_many/Makefile @@ -0,0 +1,162 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** +# Makefile for opasadb/route_tools + +# Include Make Control Settings +include $(TL_DIR)/$(PROJ_FILE_DIR)/Makesettings.project + +#=============================================================================# +# Definitions: +#-----------------------------------------------------------------------------# + +# Name of SubProjects +DS_SUBPROJECTS = +# name of executable or downloadable image +EXECUTABLE = $(BUILDDIR)/opa_osd_query_many$(EXE_SUFFIX) +# list of sub directories to build +DIRS = +# C files (.c) +CFILES = \ + ../dumppath.c \ + opa_osd_query_many.c \ + # Add more c files here +# C++ files (.cpp) +CCFILES = \ + # Add more cpp files here +# lex files (.lex) +LFILES = \ + # Add more lex files here +# archive library files (basename, $ARFILES will add MOD_LIB_DIR/prefix and suffix) +LIBFILES = +# Windows Resource Files (.rc) +RSCFILES = +# Windows IDL File (.idl) +IDLFILE = +# Windows Linker Module Definitions (.def) file for dll's +DEFFILE = +# targets to build during INCLUDES phase (add public includes here) +INCLUDE_TARGETS = \ + # Add more h hpp files here +# Non-compiled files +MISC_FILES = +# all source files +SOURCES = $(CFILES) $(CCFILES) $(LFILES) $(RSCFILES) $(IDLFILE) +# Source files to include in DSP File +DSP_SOURCES = $(INCLUDE_TARGETS) $(SOURCES) $(MISC_FILES) \ + $(RSCFILES) $(DEFFILE) $(MAKEFILE) +# all object files +OBJECTS = $(CFILES:.c=$(OBJ_SUFFIX)) $(CCFILES:.cpp=$(OBJ_SUFFIX)) \ + $(LFILES:.lex=$(OBJ_SUFFIX)) \ + # Add more object files here +RSCOBJECTS = $(RSCFILES:.rc=$(RES_SUFFIX)) +# targets to build during LIBS phase +LIB_TARGETS_IMPLIB = +LIB_TARGETS_ARLIB = +LIB_TARGETS_EXP = $(LIB_TARGETS_IMPLIB:$(ARLIB_SUFFIX)=$(EXP_SUFFIX)) +LIB_TARGETS_MISC = +# targets to build during CMDS phase +SHLIB_VERSION = +CMD_TARGETS_SHLIB = +CMD_TARGETS_EXE = $(EXECUTABLE) +CMD_TARGETS_MISC = +# files to remove during clean phase +CLEAN_TARGETS_MISC = +CLEAN_TARGETS = $(OBJECTS) $(RSCOBJECTS) $(IDL_TARGETS) $(CLEAN_TARGETS_MISC) +# other files to remove during clobber phase +CLOBBER_TARGETS_MISC= +# sub-directory to install to within bin +BIN_SUBDIR = +# sub-directory to install to within include +INCLUDE_SUBDIR = + +# Additional Settings +#CLOCALDEBUG = User defined C debugging compilation flags [Empty] +#CCLOCALDEBUG = User defined C++ debugging compilation flags [Empty] +# User defined C flags for compiling +# User defined C++ flags for compiling +#CCLOCAL = +#BSCLOCAL = User flags for Browse File Builder [Empty] +#DEPENDLOCAL = user defined makedepend flags [Empty] +#LINTLOCAL = User defined lint flags [Empty] +# User include directories to search for C/C++ headers +LOCAL_INCLUDE_DIRS = .. +#LDLOCAL = User defined C flags for linking [Empty] +#IMPLIBLOCAL = User flags for Object Lirary Manager [Empty] +#MIDLLOCAL = User flags for IDL compiler [Empty] +#RSCLOCAL = User flags for resource compiler [Empty] +# User libraries to include in dependencies +LOCALDEPLIBS = IbPrint $(IBACCESS_USER_LIBS) opamgt-priv +# User libraries to use when linking (in addition to LOCALDEPLIBS) +# opasadb is a shared library, not needed in LOCALDEPLIBS +LOCALLIBS = $(OPENIB_USER_LIBS) opasadb rt +# User library directories for libpaths +LOCAL_LIB_DIRS = $(OPENIB_USER_LIB_DIRS) $(IBACCESS_USER_LIB_DIRS) +CLOCAL = $(CPIE) + +# Include Make Rules definitions and rules +include $(TL_DIR)/IbaTools/Makerules.module + +#=============================================================================# +# Overrides: +#-----------------------------------------------------------------------------# +# C++ optimization flags, default lets build config decide +#CCOPT = +# C optimization flags, default lets build config decide +COPT = -g -D_GNU_SOURCE -Wall -fPIE +#SUBSYSTEM = Subsystem to build for (none, console or windows) [none] +# (Windows Only) +#USEMFC = How Windows MFC should be used (none, static, shared, no_mfc) [none] +# (Windows Only) +#=============================================================================# + +#=============================================================================# +# Rules: +#-----------------------------------------------------------------------------# +# process Sub-directories +include $(TL_DIR)/Makerules/Maketargets.toplevel + +# build cmds and libs +include $(TL_DIR)/Makerules/Maketargets.build + +# install for includes, libs and cmds phases +include $(TL_DIR)/Makerules/Maketargets.install + +# install for stage phase +#include $(TL_DIR)/Makerules/Maketargets.stage +STAGE:: + $(VS)$(STAGE_INSTALL) $(STAGE_INSTALL_DIR_OPT) $(PROJ_STAGE_OPA_SA_DB_DIR) $(EXECUTABLE) + +# Unit test execution +#include $(TL_DIR)/Makerules/Maketargets.runtest + +#=============================================================================# + +#=============================================================================# +# DO NOT DELETE THIS LINE -- make depend depends on it. +#=============================================================================# diff --git a/opasadb/path_tools/query_many/opa_osd_query_many.c b/opasadb/path_tools/query_many/opa_osd_query_many.c new file mode 100644 index 0000000..39f7b89 --- /dev/null +++ b/opasadb/path_tools/query_many/opa_osd_query_many.c @@ -0,0 +1,42 @@ +/* BEGIN_ICS_COPYRIGHT2 **************************************** + +Copyright (c) 2016, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT2 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + +/* + * This program demonstrates how to use opasa_path_get_many API + * + * It allows the user to create an arbitrary path query and to view + * the response. + */ +#include +int main(void) { + printf("This tool has not been implemented yet.\n"); + return 1; +} diff --git a/opasadb/route_tools/Makefile b/opasadb/route_tools/Makefile new file mode 100644 index 0000000..b3c2856 --- /dev/null +++ b/opasadb/route_tools/Makefile @@ -0,0 +1,162 @@ +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** +# Makefile for opasadb/route_tools + +# Include Make Control Settings +include $(TL_DIR)/$(PROJ_FILE_DIR)/Makesettings.project + +#=============================================================================# +# Definitions: +#-----------------------------------------------------------------------------# + +# Name of SubProjects +DS_SUBPROJECTS = +# name of executable or downloadable image +EXECUTABLE = $(BUILDDIR)/iba_smjobmgmt$(EXE_SUFFIX) +# list of sub directories to build +DIRS = +# C files (.c) +CFILES = \ + opasadb_route_console.c \ + # Add more c files here +# C++ files (.cpp) +CCFILES = \ + # Add more cpp files here +# lex files (.lex) +LFILES = \ + # Add more lex files here +# archive library files (basename, $ARFILES will add MOD_LIB_DIR/prefix and suffix) +LIBFILES = +# Windows Resource Files (.rc) +RSCFILES = +# Windows IDL File (.idl) +IDLFILE = +# Windows Linker Module Definitions (.def) file for dll's +DEFFILE = +# targets to build during INCLUDES phase (add public includes here) +INCLUDE_TARGETS = \ + # Add more h hpp files here +# Non-compiled files +MISC_FILES = +# all source files +SOURCES = $(CFILES) $(CCFILES) $(LFILES) $(RSCFILES) $(IDLFILE) +# Source files to include in DSP File +DSP_SOURCES = $(INCLUDE_TARGETS) $(SOURCES) $(MISC_FILES) \ + $(RSCFILES) $(DEFFILE) $(MAKEFILE) +# all object files +OBJECTS = $(CFILES:.c=$(OBJ_SUFFIX)) $(CCFILES:.cpp=$(OBJ_SUFFIX)) \ + $(LFILES:.lex=$(OBJ_SUFFIX)) \ + # Add more object files here +RSCOBJECTS = $(RSCFILES:.rc=$(RES_SUFFIX)) +# targets to build during LIBS phase +LIB_TARGETS_IMPLIB = +LIB_TARGETS_ARLIB = +LIB_TARGETS_EXP = $(LIB_TARGETS_IMPLIB:$(ARLIB_SUFFIX)=$(EXP_SUFFIX)) +LIB_TARGETS_MISC = +# targets to build during CMDS phase +SHLIB_VERSION = +CMD_TARGETS_SHLIB = +CMD_TARGETS_EXE = $(EXECUTABLE) +CMD_TARGETS_MISC = +# files to remove during clean phase +CLEAN_TARGETS_MISC = +CLEAN_TARGETS = $(OBJECTS) $(RSCOBJECTS) $(IDL_TARGETS) $(CLEAN_TARGETS_MISC) +# other files to remove during clobber phase +CLOBBER_TARGETS_MISC= +# sub-directory to install to within bin +BIN_SUBDIR = +# sub-directory to install to within include +INCLUDE_SUBDIR = + +# Additional Settings +#CLOCALDEBUG = User defined C debugging compilation flags [Empty] +#CCLOCALDEBUG = User defined C++ debugging compilation flags [Empty] +# User defined C flags for compiling +# User defined C++ flags for compiling +#CCLOCAL = +#BSCLOCAL = User flags for Browse File Builder [Empty] +#DEPENDLOCAL = user defined makedepend flags [Empty] +#LINTLOCAL = User defined lint flags [Empty] +# User include directories to search for C/C++ headers +LOCAL_INCLUDE_DIRS = +#LDLOCAL = User defined C flags for linking [Empty] +#IMPLIBLOCAL = User flags for Object Lirary Manager [Empty] +#MIDLLOCAL = User flags for IDL compiler [Empty] +#RSCLOCAL = User flags for resource compiler [Empty] +# User libraries to include in dependencies +LOCALDEPLIBS = $(IBACCESS_USER_LIBS) opamgt-priv +# User libraries to use when linking (in addition to LOCALDEPLIBS) +# opasadb is a shared library, not needed in LOCALDEPLIBS +LOCALLIBS = $(OPENIB_USER_LIBS) opasadb rt +# User library directories for libpaths +LOCAL_LIB_DIRS = $(OPENIB_USER_LIB_DIRS) $(IBACCESS_USER_LIB_DIRS) + +CLOCAL = $(CPIE) + +# Include Make Rules definitions and rules +include $(TL_DIR)/IbaTools/Makerules.module + +#=============================================================================# +# Overrides: +#-----------------------------------------------------------------------------# +# C++ optimization flags, default lets build config decide +#CCOPT = +# C optimization flags, default lets build config decide +#COPT = -fPIC +#SUBSYSTEM = Subsystem to build for (none, console or windows) [none] +# (Windows Only) +#USEMFC = How Windows MFC should be used (none, static, shared, no_mfc) [none] +# (Windows Only) +#=============================================================================# + +#=============================================================================# +# Rules: +#-----------------------------------------------------------------------------# +# process Sub-directories +include $(TL_DIR)/Makerules/Maketargets.toplevel + +# build cmds and libs +include $(TL_DIR)/Makerules/Maketargets.build + +# install for includes, libs and cmds phases +include $(TL_DIR)/Makerules/Maketargets.install + +# install for stage phase +#include $(TL_DIR)/Makerules/Maketargets.stage +STAGE:: + $(VS)$(STAGE_INSTALL) $(STAGE_INSTALL_DIR_OPT) $(PROJ_STAGE_FASTFABRIC_DIR) $(EXECUTABLE) + +# Unit test execution +#include $(TL_DIR)/Makerules/Maketargets.runtest + +#=============================================================================# + +#=============================================================================# +# DO NOT DELETE THIS LINE -- make depend depends on it. +#=============================================================================# diff --git a/opasadb/route_tools/opasadb_route_console.c b/opasadb/route_tools/opasadb_route_console.c new file mode 100644 index 0000000..051eb9e --- /dev/null +++ b/opasadb/route_tools/opasadb_route_console.c @@ -0,0 +1,1515 @@ +/* BEGIN_ICS_COPYRIGHT5 **************************************** + +Copyright (c) 2015-2017, Intel Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +** END_ICS_COPYRIGHT5 ****************************************/ + +/* [ICS VERSION STRING: unknown] */ + + +/******************************************************************************* + * + * INCLUDES + */ + +#include +#include +#include +#include + +#include "ib_ibt.h" + +#include "opamgt_priv.h" +#include "opasadb_route2.h" +#include "statustext.h" + + +/******************************************************************************* + * + * DEFINES + */ + +// Configuration parameters +#define NAME_PROG "iba_smjobmgmt" // Program name + +#define NUM_NAMES_CA_UMAD 16 // Num of HFI names from umad_get +#define NUM_PORT_GUIDS_UMAD 16 // Num of port GUIDs from umad_get +#define NUM_PARAM_PORT_GUID_ALLOC 8 // Num port GUID params to alloc +#define MAX_CHARS_PORT_GUID_ENTER 18 // Max chars job ID entry +#define MAX_DIGITS_PORT_GUID_MATCH 8 // Max digits for partial job ID match +#define NUM_PARAM_JOB_ID_ALLOC 16 // Num job ID params to alloc +#define MAX_CHARS_JOB_ID_ENTER 18 // Max chars job ID entry +#define MAX_DIGITS_JOB_ID_MATCH 8 // Max digits for partial job ID match +#define NUM_PARAM_JOB_NAME_ALLOC 8 // Num job name params to alloc +#define MAX_CHARS_JOB_NAME_ENTER 64 // Max chars job name entry +#define NUM_PARAM_APP_NAME_ALLOC 8 // Num app name params to alloc +#define MAX_CHARS_APP_NAME_ENTER 64 // Max chars app name entry +#define NUM_PARAM_PID_ALLOC 16 // Num PID params to alloc +#define MAX_CHARS_PID_ENTER 18 // Max chars PID entry +#define NUM_PARAM_UID_ALLOC 16 // Num UID params to alloc +#define MAX_CHARS_UID_ENTER 18 // Max chars UID entry +#define NUM_PARAM_TIME_STAMP_ALLOC 8 // Num time stamp params to alloc +#define NUM_PARAM_JOB_LIST_ALLOC 8 // Num job list params to alloc + +#define MAX_COST_ENTRIES_LINE 14 // Max cost matrix values per line + +// Commands +typedef enum +{ + none = 0, // No command + show, // Show jobs + clear // Clear jobs +} COMMAND; + +// Parameter allocation entry structures +// Note that these structs must align with op_route_param_alloc_entry in +// opasadb_route2.h +struct op_route_param_alloc_port_guid_entry +{ + uint64_t size_param; // Size of param (bf_data) allocated (bytes) + uint64_t size_data; // Size of param (bf_data) in use (bytes) + uint64_t size_enter; // Size of param entered (chars) + // NOTE: previous uint64_t ensures uint64_t alignment of bf_data + char bf_data[MAX_CHARS_PORT_GUID_ENTER + 1]; // Allocated param buffer +}; + +struct op_route_param_alloc_job_id_entry +{ + uint64_t size_param; // Size of param (bf_data) allocated (bytes) + uint64_t size_data; // Size of param (bf_data) in use (bytes) + uint64_t size_enter; // Size of param entered (chars) + // NOTE: previous uint64_t ensures uint64_t alignment of bf_data + char bf_data[MAX_CHARS_JOB_ID_ENTER + 1]; // Allocated param buffer +}; + +struct op_route_param_alloc_job_name_entry +{ + uint64_t size_param; // Size of param (bf_data) allocated (bytes) + uint64_t size_data; // Size of param (bf_data) in use (bytes) + uint64_t size_enter; // Size of param entered (chars) + // NOTE: previous uint64_t ensures uint64_t alignment of bf_data + char bf_data[MAX_CHARS_JOB_NAME_ENTER + 1]; // Allocated param buffer +}; + +struct op_route_param_alloc_app_name_entry +{ + uint64_t size_param; // Size of param (bf_data) allocated (bytes) + uint64_t size_data; // Size of param (bf_data) in use (bytes) + uint64_t size_enter; // Size of param entered (chars) + // NOTE: previous uint64_t ensures uint64_t alignment of bf_data + char bf_data[MAX_CHARS_APP_NAME_ENTER + 1]; // Allocated param buffer +}; + +struct op_route_param_alloc_pid_entry +{ + uint64_t size_param; // Size of param (bf_data) allocated (bytes) + uint64_t size_data; // Size of param (bf_data) in use (bytes) + uint64_t size_enter; // Size of param entered (chars) + // NOTE: previous uint64_t ensures uint64_t alignment of bf_data + char bf_data[MAX_CHARS_PID_ENTER + 1]; // Allocated param buffer +}; + +struct op_route_param_alloc_uid_entry +{ + uint64_t size_param; // Size of param (bf_data) allocated (bytes) + uint64_t size_data; // Size of param (bf_data) in use (bytes) + uint64_t size_enter; // Size of param entered (chars) + // NOTE: previous uint64_t ensures uint64_t alignment of bf_data + char bf_data[MAX_CHARS_UID_ENTER + 1]; // Allocated param buffer +}; + +struct op_route_param_alloc_time_stamp_entry +{ + uint64_t size_param; // Size of param (bf_data) allocated (bytes) + uint64_t size_data; // Size of param (bf_data) in use (bytes) + uint64_t fl_lessmore; // FALSE - less, TRUE - more + // (see cmp_param_time()) + // NOTE: previous uint64_t ensures uint64_t alignment of bf_data + char bf_data[sizeof(time_t)]; // Allocated param buffer +}; + +struct op_route_param_alloc_job_list_entry +{ + uint64_t reserved; // Not used + uint64_t reserved2; // Not used + uint64_t reserved3; // Not used + uint64_t port_guid; // port_guid of job_list + OP_ROUTE_PORT_HANDLE port_handle; // port_handle of job_list + struct op_route_job_list job_list; // Allocated job_list +}; + + +/******************************************************************************* + * + * LOCAL VARIABLES + */ + +static COMMAND command = none; // Console command + +static int32_t num_name_ca; +static char tb_name_ca_umad[NUM_NAMES_CA_UMAD][UMAD_CA_NAME_LEN]; +static int32_t num_port_guid = 0; +static uint64_t tb_port_guid_umad[NUM_PORT_GUIDS_UMAD]; +static uint8_t hfi = 0; +static uint8_t port = 0; +static uint64_t connect_portguid = 0; + +static struct op_route_param_alloc param_port_guid; +static struct op_route_param_alloc param_job_id; +static struct op_route_param_alloc param_job_name; +static struct op_route_param_alloc param_app_name; +static struct op_route_param_alloc param_pid; +static struct op_route_param_alloc param_uid; +static struct op_route_param_alloc param_time_stamp; +static struct op_route_param_alloc param_job_list; + +static uint16_t switch_index = 0; // Active switch index value +static struct op_route_portguid_vec portguid_vec; // Active portguid_vec +static struct op_route_switch_map switch_map; // Active switch_map +static uint16_t * p_cost_matrix; // Pointer to active cost matrix +static struct op_route_use_matrix use_matrix; // Active use_matrix + +static boolean fb_have_portguid = FALSE; // Parsed portGUID value +static boolean fb_have_hfiport = FALSE; // Parsed HFI or port value +static boolean fb_allguids = FALSE; // All portGUIDs flag +static boolean fb_have_jobid = FALSE; // Parsed job_id value +static boolean fb_have_jobname = FALSE; // Parsed job name value +static boolean fb_alljobs = FALSE; // All jobs flag +static boolean fb_have_appname = FALSE; // Parsed app name value +static boolean fb_have_pid = FALSE; // Parsed PID value +static boolean fb_have_uid = FALSE; // Parsed UID value +static boolean fb_have_timestamp = FALSE; // Parsed time_stamp value +static boolean fb_showcost = FALSE; // Show cost_matrix flag +static boolean fb_showguidswitch = FALSE; // Show GUID/switch flag +static boolean fb_showuse = FALSE; // Show use_matrix flag +static boolean fb_verbose = FALSE; // Verbose flag + +// Command line option table, each has a short and long flag name +static struct option tb_options[] = +{ + { "verbose", no_argument, NULL, 'v' }, + { "portguid", required_argument, NULL, 'g' }, + { "hfi", required_argument, NULL, 'h' }, + { "port", required_argument, NULL, 'p' }, + { "jobid", required_argument, NULL, 'j' }, + { "jobname", required_argument, NULL, 'J' }, + { "appname", required_argument, NULL, 'N' }, + { "pid", required_argument, NULL, 'i' }, + { "uid", required_argument, NULL, 'I' }, + { "timeless", required_argument, NULL, 't' }, + { "timemore", required_argument, NULL, 'T' }, + { "alljobs", no_argument, NULL, 'a' }, + { "allfabrics", no_argument, NULL, 'f' }, + { "cost", no_argument, NULL, 'c' }, + { "switch", no_argument, NULL, 's' }, + { "index", no_argument, NULL, 'S' }, + { "use", no_argument, NULL, 'u' }, + { 0 } +}; + + +/******************************************************************************* + * + * FUNCTIONS + */ + + +/******************************************************************************* + * + * cmp_param_str() + * + * Description: + * Compare specified parameter value to the specified parameter list as a + * string. Comparison for a partial match anywhere in the string is made + * with strstr(). + * + * Inputs: + * p_param - Pointer to parameter string on which to perform comparison + * p_param_alloc - Pointer to parameter list to compare + * + * Outputs: + * TRUE - Parameter string matches at least 1 parameter in parameter list + * FALSE - Invalid p_param_alloc + * No match + */ +int cmp_param_str( const char * p_param, + struct op_route_param_alloc * p_param_alloc ) +{ + uint32_t ix; + struct op_route_param_alloc_entry * p_param_entry; + + if ( !p_param || !p_param_alloc || !p_param_alloc->num_used || + !p_param_alloc->p_params ) + return (FALSE); + + for ( ix = p_param_alloc->num_used, p_param_entry = p_param_alloc->p_params; + ix > 0; ix-- ) + { + if (strstr(p_param, p_param_entry->bf_data)) + return (TRUE); + + p_param_entry = (struct op_route_param_alloc_entry *) + ((char *)p_param_entry + p_param_alloc->size_param); + } + + return (FALSE); + +} // End of cmp_param_str() + +/******************************************************************************* + * + * cmp_param_uint64() + * + * Description: + * Compare specified parameter value to the specified parameter list as + * uint64. Comparison for a partial match of the most significant n digits + * is made based on the number of digits (n = info_param) for each parameter + * in the parameter list. + * + * Inputs: + * n_param - Parameter value on which to perform comparison + * p_param_alloc - Pointer to parameter list to compare + * + * Outputs: + * TRUE - Parameter value matches at least 1 parameter in parameter list + * FALSE - Invalid p_param_alloc + * No match + */ +int cmp_param_uint64( uint64_t n_param, + struct op_route_param_alloc * p_param_alloc ) +{ + uint32_t ix; + struct op_route_param_alloc_entry * p_param_entry; + + if (!p_param_alloc || !p_param_alloc->num_used || !p_param_alloc->p_params) + return (FALSE); + + for ( ix = p_param_alloc->num_used, p_param_entry = p_param_alloc->p_params; + ix > 0; ix-- ) + { + if ( ( n_param & ( 0xFFFFFFFFFFFFFFFF << + (((sizeof(uint64_t) * 2) - p_param_entry->info_param) * 4) ) ) == + *(uint64_t *)p_param_entry->bf_data ) + return (TRUE); + + p_param_entry = (struct op_route_param_alloc_entry *) + ((char *)p_param_entry + p_param_alloc->size_param); + } + + return (FALSE); + +} // End of cmp_param_uint64() + +/******************************************************************************* + * + * cmp_param_time() + * + * Description: + * Compare specified parameter value to the specified parameter list as + * time_t. Comparison for < or > parameter list value is determined by + * fl_lessmore flag (see op_route_param_alloc_time_stamp_entry). + * + * Inputs: + * n_param - Parameter value on which to perform comparison + * p_param_alloc - Pointer to parameter list to compare + * + * Outputs: + * TRUE - Parameter value matches at least 1 parameter in parameter list + * FALSE - Invalid p_param_alloc + * No match + */ +int cmp_param_time( time_t n_param, + struct op_route_param_alloc * p_param_alloc ) +{ + uint32_t ix; + struct op_route_param_alloc_entry * p_param_entry; + + if (!p_param_alloc || !p_param_alloc->num_used || !p_param_alloc->p_params) + return (FALSE); + + for ( ix = p_param_alloc->num_used, p_param_entry = p_param_alloc->p_params; + ix > 0; ix-- ) + { + if ( ( !p_param_entry->info_param && + (n_param < *(uint64_t *)p_param_entry->bf_data) ) || + ( p_param_entry->info_param && + (n_param > *(uint64_t *)p_param_entry->bf_data) ) ) + return (TRUE); + + p_param_entry = (struct op_route_param_alloc_entry *) + ((char *)p_param_entry + p_param_alloc->size_param); + } + + return (FALSE); + +} // End of cmp_param_time() + +/******************************************************************************* + * + * err_usage() + * + * Description: + * Output information about program usage and parameters. + * + * Inputs: + * none + * + * Outputs: + * none + */ +void err_usage(void) +{ + fprintf(stderr, "Usage: " NAME_PROG " show|clear [-g portguid][-h hfi][-p port][-j job_id][-J job_name]\n"); + fprintf(stderr, " [-N app_name][-i pid][-I uid][-t timeless][-T timemore]\n"); + fprintf(stderr, " [-a][-f][-c][-s][-u][-S index][-v]\n"); + fprintf(stderr, " -g/--portguid portguid - port GUID to connect via (multiple entries)\n"); + fprintf(stderr, " -h/--hfi hfi - hfi to connect via, numbered 1..n, 0= -p port will\n"); + fprintf(stderr, " be a system wide port num (default is 0)\n"); + fprintf(stderr, " -p/--port port - port to connect via, numbered 1..n, 0=1st active\n"); + fprintf(stderr, " (default is 1st active)\n"); + fprintf(stderr, " -j/--jobid job_id - show/clear job job_id (multiple)\n"); + fprintf(stderr, " -J/--jobname job_name - show/clear job job_name (multiple)\n"); + fprintf(stderr, " -N/--appname app_name - show/clear job app_name (multiple)\n"); + fprintf(stderr, " -i/--pid pid - show/clear job pid (multiple)\n"); + fprintf(stderr, " -I/--uid uid - show/clear job uid (multiple)\n"); + fprintf(stderr, " -t/--timeless timestamp - show/clear job < timestamp (multiple)\n"); + fprintf(stderr, " -t/--timemore timestamp - show/clear job > timestamp (multiple)\n"); + fprintf(stderr, " -a/--alljobs - show/clear all jobs\n"); + fprintf(stderr, " -f/--allfabrics - show/clear all fabrics\n"); + fprintf(stderr, " -c/--cost - show cost matrix for job(s)\n"); + fprintf(stderr, " -s/--switch - show portGUID vector and switch map for job(s)\n"); + fprintf(stderr, " -u/--use - show use matrix for job(s)\n"); + fprintf(stderr, " -S/--index index - switch index for show cost matrix, default is 0\n"); + fprintf(stderr, " -v/--verbose - verbose output (show jobs)\n"); + fprintf(stderr, "\n"); + fprintf(stderr, "The -h and -p options permit a variety of selections:\n"); + fprintf(stderr, " -h 0 - 1st active port in system (this is the default)\n"); + fprintf(stderr, " -h 0 -p 0 - 1st active port in system\n"); + fprintf(stderr, " -h x - 1st active port on HFI x\n"); + fprintf(stderr, " -h x -p 0 - 1st active port on HFI x\n"); + fprintf(stderr, " -h 0 -p y - port y within system (irrespective of which ports are active)\n"); + fprintf(stderr, " -h x -p y - HFI x, port y\n"); + + exit(2); + +} // End of err_usage() + +/******************************************************************************* + * + * get_opt_time_tm() + * + * Description: + * Get command line time_stamp specification. Parses command line time_stamp + * option specification of the form 'mm/dd/yyyy hh:mm:ss', and returns the + * values in a tm struct. + * + * Inputs: + * p_str_arg - Pointer to argument string + * p_tm - Pointer to tm struct + * + * Outputs: + * 0 - Get successful + * *p_tm = time_stamp specification values + * -1 - Get unsuccessful + */ +int get_opt_time_tm(char * p_str_arg, struct tm *p_tm) +{ + + p_tm->tm_sec = 0; + p_tm->tm_min = 0; + p_tm->tm_hour = 0; + p_tm->tm_mday = 1; + p_tm->tm_mon = 0; + p_tm->tm_year = 0; + p_tm->tm_wday = 0; + p_tm->tm_yday = 0; + p_tm->tm_isdst = 0; + + if ( sscanf( p_str_arg, "%d/%d/%d %d:%d:%d", &p_tm->tm_mon, &p_tm->tm_mday, + &p_tm->tm_year, &p_tm->tm_hour, &p_tm->tm_min, &p_tm->tm_sec ) != 6 ) + return (-1); + + p_tm->tm_mon -= 1; + p_tm->tm_year -= 1900; + + return (0); + +} // End of get_opt_time_tm() + +/******************************************************************************* + * + * get_opt() + * + * Description: + * Get command line options. Parses command line options using short and + * long option (parameter) definitions. Parameters (file static variables) + * are updated appropriately. + * + * Inputs: + * argc - Number of input parameters + * argv - Array of pointers to input parameters + * p_opt_short - Pointer to string of short option definitions + * tb_opt_long - Array of long option definitions + * + * Outputs: + * none + */ +void get_opt( int argc, char ** argv, const char *p_opt_short, + struct option tb_opt_long[] ) +{ + int ix; + int c_opt; // Option parsing char + int ix_opt; // Option parsing index + size_t len_str; // String length + uint64_t temp; // Temporary input area + struct tm time_stamp; // Time stamp input area + char * p_opt_end; // Pointer to end of parsed parameter + // Pointer to port GUID param + struct op_route_param_alloc_port_guid_entry * p_param_port_guid; + // Pointer to job ID param + struct op_route_param_alloc_job_id_entry * p_param_job_id; + // Pointer to job name param + struct op_route_param_alloc_job_name_entry * p_param_job_name; + // Pointer to app name param + struct op_route_param_alloc_app_name_entry * p_param_app_name; + // Pointer to PID param + struct op_route_param_alloc_pid_entry * p_param_pid; + // Pointer to UID param + struct op_route_param_alloc_uid_entry * p_param_uid; + // Pointer to time stamp param + struct op_route_param_alloc_time_stamp_entry * p_param_time_stamp; + + // Input command + if (argc >= 2) + { + if (!strcmp(argv[1], "show")) + command = show; + else if (!strcmp(argv[1], "clear")) + command = clear; + } + + if (command == none) + { + fprintf(stderr, NAME_PROG ": Invalid Command:%s\n", argc >= 2 ? argv[1] : "NULL"); + err_usage(); + } + + // Shift arguments + for (ix = 1; ix < argc; ix++) + argv[ix] = argv[ix + 1]; + argc--; + + // Input command line arguments + while ( ( c_opt = getopt_long( argc, argv, p_opt_short, tb_opt_long, + &ix_opt ) ) != -1 ) + { + len_str = 0; + switch (c_opt) + { + + // Verbose + case 'v': + fb_verbose = TRUE; + break; + + // Port GUID specification + case 'g': + if (fb_have_hfiport || fb_allguids) + { + fprintf(stderr, NAME_PROG ": Can't use -g with -h/-p/-f\n"); + err_usage(); + } + + if (!optarg) + { + fprintf(stderr, NAME_PROG ": No port GUID value\n"); + err_usage(); + } + + errno = 0; + temp = strtoull(optarg, &p_opt_end, 0); + if (errno || !p_opt_end || (*p_opt_end != '\0')) + { + fprintf(stderr, NAME_PROG ": Invalid port GUID value:%s\n", optarg); + err_usage(); + } + + // Store port GUID parameter + if (param_port_guid.num_used == param_port_guid.num_allocated) + if (op_route_alloc_param(¶m_port_guid)) + { + fprintf(stderr, NAME_PROG + ": Unable to allocate port GUID parameter\n"); + err_usage(); + } + + p_param_port_guid = + &( (struct op_route_param_alloc_port_guid_entry *) + param_port_guid.p_params )[param_port_guid.num_used++]; + p_param_port_guid->size_param = sizeof(p_param_port_guid->bf_data); + p_param_port_guid->size_data = sizeof(uint64_t); + p_param_port_guid->size_enter = sizeof(uint64_t) * 2; + *(uint64_t *)(p_param_port_guid->bf_data) = temp; + connect_portguid = temp; + + fb_have_portguid = TRUE; + break; + + // HFI specification + case 'h': + if (fb_have_portguid || fb_allguids) + { + fprintf(stderr, NAME_PROG ": Can't use -h with -g/-f\n"); + err_usage(); + } + + if (!optarg) + { + fprintf(stderr, NAME_PROG ": No HFI value\n"); + err_usage(); + } + + errno = 0; + temp = (uint64_t)strtoul(optarg, &p_opt_end, 0); + if ( (temp > IB_UINT8_MAX) || errno || !p_opt_end || + (*p_opt_end != '\0') ) + { + fprintf(stderr, NAME_PROG ": Invalid HFI value:%s\n", optarg); + err_usage(); + } + + hfi = (uint8_t)temp; + fb_have_hfiport = TRUE; + break; + + // Port specification + case 'p': + if (fb_have_portguid || fb_allguids) + { + fprintf(stderr, NAME_PROG ": Can't use -p with -g/-f\n"); + err_usage(); + } + + if (!optarg) + { + fprintf(stderr, NAME_PROG ": No port value\n"); + err_usage(); + } + + errno = 0; + temp = (uint64_t)strtoul(optarg, &p_opt_end, 0); + if ( (temp > IB_UINT8_MAX) || errno || !p_opt_end || + (*p_opt_end != '\0') ) + { + fprintf(stderr, NAME_PROG ": Invalid port value:%s\n", optarg); + err_usage(); + } + + port = (uint8_t)temp; + fb_have_hfiport = TRUE; + break; + + // Job ID specification + case 'j': + if (fb_alljobs) + { + fprintf(stderr, NAME_PROG ": Can't use -j with -a\n"); + err_usage(); + } + + if (!optarg) + { + fprintf(stderr, NAME_PROG ": No job ID value\n"); + err_usage(); + } + + errno = 0; + temp = strtoull(optarg, &p_opt_end, 16); + if (errno || !p_opt_end || (*p_opt_end != '\0')) + { + fprintf(stderr, NAME_PROG ": Invalid job ID value:%s\n", optarg); + err_usage(); + } + + // Get length of job ID and process for partial matching + len_str = strlen(optarg); + if ((len_str > 2) && ((optarg[1] == 'x') || (optarg[1] == 'X'))) + len_str -= 2; + + if (len_str > MAX_DIGITS_JOB_ID_MATCH) // No partial ID matching + len_str = sizeof(OP_ROUTE_JOB_ID) * 2; + + // Store job ID parameter + if (param_job_id.num_used == param_job_id.num_allocated) + if (op_route_alloc_param(¶m_job_id)) + { + fprintf(stderr, NAME_PROG ": Unable to allocate parameter\n"); + err_usage(); + } + + p_param_job_id = &( (struct op_route_param_alloc_job_id_entry *) + param_job_id.p_params )[param_job_id.num_used++]; + p_param_job_id->size_param = sizeof(p_param_job_id->bf_data); + p_param_job_id->size_data = sizeof(OP_ROUTE_JOB_ID); + p_param_job_id->size_enter = len_str; + *(OP_ROUTE_JOB_ID *)(p_param_job_id->bf_data) = + temp << (((sizeof(OP_ROUTE_JOB_ID) * 2) - len_str) * 4); + fb_have_jobid = TRUE; + + break; + + // Job name specification + case 'J': + if (fb_alljobs) + { + fprintf(stderr, NAME_PROG ": Can't use -J with -a\n"); + err_usage(); + } + + if (!optarg) + { + fprintf(stderr, NAME_PROG ": No job name\n"); + err_usage(); + } + + len_str = strlen(optarg); + if (len_str > MAX_CHARS_JOB_NAME_ENTER) + { + fprintf( stderr, NAME_PROG ": Invalid job name length:%"PRIu64" %s\n", + len_str, optarg ); + err_usage(); + } + + // Store job name parameter + if (param_job_name.num_used == param_job_name.num_allocated) + if (op_route_alloc_param(¶m_job_name)) + { + fprintf(stderr, NAME_PROG ": Unable to allocate parameter\n"); + err_usage(); + } + + p_param_job_name = &( (struct op_route_param_alloc_job_name_entry *) + param_job_name.p_params )[param_job_name.num_used++]; + p_param_job_name->size_param = sizeof(p_param_job_name->bf_data); + p_param_job_name->size_data = MAX_CHARS_JOB_NAME_ENTER; + p_param_job_name->size_enter = len_str; + strcpy(p_param_job_name->bf_data, optarg); + fb_have_jobname = TRUE; + + break; + + // App name specification + case 'N': + if (fb_alljobs) + { + fprintf(stderr, NAME_PROG ": Can't use -N with -a\n"); + err_usage(); + } + + if (!optarg) + { + fprintf(stderr, NAME_PROG ": No app name\n"); + err_usage(); + } + + len_str = strlen(optarg); + if (len_str > MAX_CHARS_APP_NAME_ENTER) + { + fprintf( stderr, NAME_PROG ": Invalid app name length:%"PRIu64" %s\n", + len_str, optarg ); + err_usage(); + } + + // Store app name parameter + if (param_app_name.num_used == param_app_name.num_allocated) + if (op_route_alloc_param(¶m_app_name)) + { + fprintf(stderr, NAME_PROG ": Unable to allocate parameter\n"); + err_usage(); + } + + p_param_app_name = &( (struct op_route_param_alloc_app_name_entry *) + param_app_name.p_params )[param_app_name.num_used++]; + p_param_app_name->size_param = sizeof(p_param_app_name->bf_data); + p_param_app_name->size_data = MAX_CHARS_APP_NAME_ENTER; + p_param_app_name->size_enter = len_str; + strcpy(p_param_app_name->bf_data, optarg); + fb_have_appname = TRUE; + + break; + + // PID specification + case 'i': + if (fb_alljobs) + { + fprintf(stderr, NAME_PROG ": Can't use -i with -a\n"); + err_usage(); + } + + if (!optarg) + { + fprintf(stderr, NAME_PROG ": No PID value\n"); + err_usage(); + } + + errno = 0; + temp = strtoull(optarg, &p_opt_end, 0); + if (errno || !p_opt_end || (*p_opt_end != '\0')) + { + fprintf(stderr, NAME_PROG ": Invalid PID value:%s\n", optarg); + err_usage(); + } + + // Store PID parameter + if (param_pid.num_used == param_pid.num_allocated) + if (op_route_alloc_param(¶m_pid)) + { + fprintf(stderr, NAME_PROG + ": Unable to allocate PID parameter\n"); + err_usage(); + } + + p_param_pid = + &( (struct op_route_param_alloc_pid_entry *) + param_pid.p_params )[param_pid.num_used++]; + p_param_pid->size_param = sizeof(p_param_pid->bf_data); + p_param_pid->size_data = sizeof(uint64_t); + p_param_pid->size_enter = sizeof(uint64_t) * 2; + *(uint64_t *)(p_param_pid->bf_data) = temp; + + fb_have_pid = TRUE; + break; + + // UID specification + case 'I': + if (fb_alljobs) + { + fprintf(stderr, NAME_PROG ": Can't use -I with -a\n"); + err_usage(); + } + + if (!optarg) + { + fprintf(stderr, NAME_PROG ": No UID value\n"); + err_usage(); + } + + errno = 0; + temp = strtoull(optarg, &p_opt_end, 0); + if (errno || !p_opt_end || (*p_opt_end != '\0')) + { + fprintf(stderr, NAME_PROG ": Invalid UID value:%s\n", optarg); + err_usage(); + } + + // Store UID parameter + if (param_uid.num_used == param_uid.num_allocated) + if (op_route_alloc_param(¶m_uid)) + { + fprintf(stderr, NAME_PROG + ": Unable to allocate UID parameter\n"); + err_usage(); + } + + p_param_uid = + &( (struct op_route_param_alloc_uid_entry *) + param_uid.p_params )[param_uid.num_used++]; + p_param_uid->size_param = sizeof(p_param_uid->bf_data); + p_param_uid->size_data = sizeof(uint64_t); + p_param_uid->size_enter = sizeof(uint64_t) * 2; + *(uint64_t *)(p_param_uid->bf_data) = temp; + + fb_have_uid = TRUE; + break; + + // Less/more time_stamp specification + case 't': + case 'T': + if (fb_alljobs) + { + fprintf(stderr, NAME_PROG ": Can't use -t/-T with -a\n"); + err_usage(); + } + + if (!optarg) + { + fprintf(stderr, NAME_PROG ": No time stamp value\n"); + err_usage(); + } + + if ( get_opt_time_tm(optarg, &time_stamp) || + (time_stamp.tm_mday < 1) || (time_stamp.tm_mday > 31) || + (time_stamp.tm_mon < 0) || (time_stamp.tm_mon > 11) || + (time_stamp.tm_year < 70) || + (time_stamp.tm_hour < 0) || (time_stamp.tm_hour > 23) || + (time_stamp.tm_min < 0) || (time_stamp.tm_min > 59) || + (time_stamp.tm_sec < 0) || (time_stamp.tm_sec > 59) ) + { + fprintf(stderr, NAME_PROG ": Invalid time stamp value:(%s)\n", optarg); + err_usage(); + } + + // Store time_stamp parameter + if (param_time_stamp.num_used == param_time_stamp.num_allocated) + if (op_route_alloc_param(¶m_time_stamp)) + { + fprintf(stderr, NAME_PROG + ": Unable to allocate time_stamp parameter\n"); + err_usage(); + } + + p_param_time_stamp = + &( (struct op_route_param_alloc_time_stamp_entry *) + param_time_stamp.p_params )[param_time_stamp.num_used++]; + p_param_time_stamp->size_param = sizeof(p_param_time_stamp->bf_data); + p_param_time_stamp->size_data = sizeof(p_param_time_stamp->bf_data); + p_param_time_stamp->fl_lessmore = (c_opt == 'T'); + *(time_t *)(p_param_time_stamp->bf_data) = mktime(&time_stamp); + + fb_have_timestamp = TRUE; + break; + + // All jobs specification + case 'a': + if (fb_have_jobid) + { + fprintf(stderr, NAME_PROG ": Can't use -a with -j\n"); + err_usage(); + } + + fb_alljobs = TRUE; + break; + + // All portGUIDs specification + case 'f': + if (fb_have_portguid || fb_have_hfiport) + { + fprintf(stderr, NAME_PROG ": Can't use -f with -g/-h/-p\n"); + err_usage(); + } + + fb_allguids = TRUE; + break; + + // Show cost matrix specification + case 'c': + fb_showcost = TRUE; + break; + + // Show port GUID vector and switch map specifications + case 's': + fb_showguidswitch = TRUE; + break; + + // Switch index value + case 'S': + if (!optarg) + { + fprintf(stderr, NAME_PROG ": No switch index value\n"); + err_usage(); + } + + errno = 0; + temp = (uint64_t)strtoul(optarg, &p_opt_end, 0); + if ( (temp > OP_ROUTE_MAX_SWITCHES) || errno || !p_opt_end || + (*p_opt_end != '\0') ) + { + fprintf(stderr, NAME_PROG ": Invalid switch index value:%s\n", optarg); + err_usage(); + } + + switch_index = (uint16_t)temp; + break; + + // Show use matrix specification + case 'u': + fb_showuse = TRUE; + break; + + default: + fprintf(stderr, NAME_PROG ": Invalid Option -<%c>\n", c_opt); + err_usage(); + break; + + } // End of switch (c_opt) + + } // End of while ( ( c_opt = getopt_long( argc, argv, + + // Validate command line arguments + if (optind < argc) + { + fprintf(stderr, "%s: invalid argument %s\n", NAME_PROG, argv[optind]); + err_usage(); + } + + if (command == show) + { + if (!fb_have_portguid && !fb_have_hfiport) + fb_allguids = TRUE; + + if ( !fb_have_jobid && !fb_have_jobname && !fb_have_appname && + !fb_have_pid && !fb_have_uid && !fb_have_timestamp ) + fb_alljobs = TRUE; + } + +} // End of get_opt() + +/******************************************************************************* + * + * main() + * + * Description: + * Console function; provides general maintenance and debugging facilities + * for library functions. + * + * Inputs: + * argc - Number of input parameters + * argv - Array of pointers to input parameters + * + * Outputs: + * Exit status 0 - no errors + * Exit status 2 - error + */ +int main(int argc, char ** argv) +{ + int ret_val = 0; + int64 ix, ix_2, ix_3, ix_4, ix_5; + FSTATUS fstatus; + uint8_t rstatus; + uint64_t port_guid = 0; + static OP_ROUTE_PORT_HANDLE port_handle = 0; + static uint16_t num_job_lists = 0; + static uint32_t num_jobs = 0; + struct op_route_job_list job_list; + + struct op_route_param_alloc_port_guid_entry * p_param_port_guid; + struct op_route_param_alloc_job_list_entry * p_param_job_list; + struct op_route_job_info * p_job_info; + struct omgt_port *omgt_port_session = NULL; + + // Initialize allocated parameters + if ( op_route_init_param( ¶m_port_guid, + sizeof(struct op_route_param_alloc_port_guid_entry), + NUM_PARAM_PORT_GUID_ALLOC ) ) + { + fprintf(stderr, NAME_PROG ": Unable to allocate port_guid parameter\n"); + err_usage(); + } + + if ( op_route_init_param( ¶m_job_id, + sizeof(struct op_route_param_alloc_job_id_entry), + NUM_PARAM_JOB_ID_ALLOC ) ) + { + fprintf(stderr, NAME_PROG ": Unable to allocate job_id parameter\n"); + err_usage(); + } + + if ( op_route_init_param( ¶m_job_name, + sizeof(struct op_route_param_alloc_job_name_entry), + NUM_PARAM_JOB_NAME_ALLOC ) ) + { + fprintf(stderr, NAME_PROG ": Unable to allocate job name parameter\n"); + err_usage(); + } + + if ( op_route_init_param( ¶m_app_name, + sizeof(struct op_route_param_alloc_app_name_entry), + NUM_PARAM_APP_NAME_ALLOC ) ) + { + fprintf(stderr, NAME_PROG ": Unable to allocate app name parameter\n"); + err_usage(); + } + + if ( op_route_init_param( ¶m_pid, + sizeof(struct op_route_param_alloc_pid_entry), + NUM_PARAM_PID_ALLOC ) ) + { + fprintf(stderr, NAME_PROG ": Unable to allocate PID parameter\n"); + err_usage(); + } + + if ( op_route_init_param( ¶m_uid, + sizeof(struct op_route_param_alloc_uid_entry), + NUM_PARAM_UID_ALLOC ) ) + { + fprintf(stderr, NAME_PROG ": Unable to allocate UID parameter\n"); + err_usage(); + } + + if ( op_route_init_param( ¶m_time_stamp, + sizeof(struct op_route_param_alloc_time_stamp_entry), + NUM_PARAM_TIME_STAMP_ALLOC ) ) + { + fprintf(stderr, NAME_PROG ": Unable to allocate time stamp parameter\n"); + err_usage(); + } + + if ( op_route_init_param( ¶m_job_list, + sizeof(struct op_route_param_alloc_job_list_entry), + NUM_PARAM_JOB_LIST_ALLOC ) ) + { + fprintf(stderr, NAME_PROG ": Unable to allocate job_list parameter\n"); + err_usage(); + } + + // Get and validate command line arguments + get_opt(argc, argv, "vg:h:p:j:J:N:i:I:t:T:afcsuS:Z:", tb_options); + + // Initialize + portguid_vec.p_guids = NULL; + switch_map.p_switch_indices = NULL; + p_cost_matrix = NULL; + use_matrix.p_elements = NULL; + + // Get list of all port GUIDS on all HFIs if all specified + if (fb_allguids) + { + num_name_ca = umad_get_cas_names(tb_name_ca_umad, NUM_NAMES_CA_UMAD); + + for (ix = 0; ix < num_name_ca; ix++) + { + num_port_guid = umad_get_ca_portguids( tb_name_ca_umad[ix], + tb_port_guid_umad, NUM_PORT_GUIDS_UMAD ); + + for (ix_2 = 1; ix_2 < num_port_guid; ix_2++) + { + if (param_port_guid.num_used == param_port_guid.num_allocated) + if (op_route_alloc_param(¶m_port_guid)) + { + fprintf( stderr, NAME_PROG + ": Unable to allocate port_guid parameter\n" ); + err_usage(); + } + + p_param_port_guid = + &( (struct op_route_param_alloc_port_guid_entry *) + param_port_guid.p_params )[param_port_guid.num_used++]; + p_param_port_guid->size_param = sizeof(p_param_port_guid->bf_data); + p_param_port_guid->size_data = sizeof(uint64_t); + p_param_port_guid->size_enter = sizeof(uint64_t) * 2; + *(uint64_t *)(p_param_port_guid->bf_data) = + ntoh64(tb_port_guid_umad[ix_2]); + + } // End of for (ix_2 = 0; ix_2 < num_port_guid; ix_2++) + + } // End of for (ix = 0; ix < num_name_ca; ix++) + + } // End of if (fb_allguids) + + // Get default port GUID if none specified + if (!fb_have_portguid && !fb_allguids) + { + fstatus = iba_get_portguid( hfi, port, NULL, + (uint64_t *)param_port_guid.p_params->bf_data, NULL, NULL, + NULL, NULL ); + if (FNOT_FOUND == fstatus) { + fprintf(stderr, NAME_PROG ": %s\n", + iba_format_get_portguid_error(hfi, port, caCount, portCount)); + //err_usage(); + exit(1); + } else if (fstatus != FSUCCESS) + { + fprintf( stderr, NAME_PROG + ": can't get port GUID from hfi:%u port:%u fstatus:%d (%s)\n", + hfi, port, (int)fstatus, iba_fstatus_msg(fstatus) ); + //err_usage(); + exit(1); + } + + p_param_port_guid = (struct op_route_param_alloc_port_guid_entry *) + param_port_guid.p_params; + p_param_port_guid->size_param = + sizeof(p_param_port_guid->bf_data); + p_param_port_guid->size_data = sizeof(uint64_t); + p_param_port_guid->size_enter = sizeof(uint64_t) * 2; + param_port_guid.num_used++; + + connect_portguid = *(uint64_t *)p_param_port_guid->bf_data; + } + + fstatus = omgt_open_port_by_guid(&omgt_port_session, connect_portguid, NULL); + if (fstatus != FSUCCESS) { + fprintf(stderr, "Unable to open fabric interface.\n"); + err_usage(); + return ret_val; + } + + // Open port connection(s) and get job list(s) + for ( ix = param_port_guid.num_used, p_param_port_guid = + (struct op_route_param_alloc_port_guid_entry *)param_port_guid.p_params; + ix > 0; p_param_port_guid++, ix-- ) + { + port_guid = *(uint64_t *)p_param_port_guid->bf_data; + + if ( (rstatus = op_route_open(omgt_port_session, port_guid, &port_handle)) != + OP_ROUTE_STATUS_OK ) + { + fprintf( stderr, NAME_PROG ": open Error:%s, GUID:0x%"PRIX64"\n", + op_route_get_status_text(rstatus), port_guid ); + err_usage(); + } + + if (param_job_list.num_used == param_job_list.num_allocated) + if (op_route_alloc_param(¶m_job_list)) + { + fprintf(stderr, NAME_PROG ": Unable to allocate job_list parameter\n"); + err_usage(); + } + + if ( (rstatus = op_route_get_job_list(port_handle, omgt_port_session, &job_list)) != + OP_ROUTE_STATUS_OK ) + { + fprintf( stderr, NAME_PROG ": show Error:%s, can't get job list\n", + op_route_get_status_text(rstatus) ); + err_usage(); + } + + num_job_lists++; + p_param_job_list = (struct op_route_param_alloc_job_list_entry *) + param_job_list.p_params + param_job_list.num_used++; + p_param_job_list->port_guid = port_guid; + p_param_job_list->port_handle = port_handle; + p_param_job_list->job_list = job_list; + num_jobs += job_list.num_jobs; + + } + + // Execute command + p_param_job_list = + (struct op_route_param_alloc_job_list_entry *)param_job_list.p_params; + port_handle = p_param_job_list->port_handle; + + switch (command) + { + + // Show command + case show: + { + printf( "Show Job(s) (Fabrics:%u Total Jobs:%u):\n", num_job_lists, + num_jobs ); + + for (ix = param_job_list.num_used; ix > 0; p_param_job_list++, ix--) + { + if (p_param_job_list->job_list.num_jobs > 0) + printf( "\nPort GUID:0x%016"PRIX64 + "\nJob ID (hex) R:Job Routed U:Use Matrix Rec'd\n", + p_param_job_list->port_guid ); + + for ( ix_2 = p_param_job_list->job_list.num_jobs, + p_job_info = p_param_job_list->job_list.p_job_info; + ix_2 > 0; p_job_info++, ix_2-- ) + { + if ( fb_alljobs || + ( ( fb_have_jobid || fb_have_jobname || fb_have_appname || + fb_have_pid || fb_have_uid || fb_have_timestamp ) && + ( !fb_have_jobid || + cmp_param_uint64(p_job_info->job_id, ¶m_job_id) ) && + ( !fb_have_jobname || + cmp_param_str(p_job_info->params.name, ¶m_job_name) ) && + ( !fb_have_appname || + cmp_param_str( p_job_info->params.application_name, + ¶m_app_name ) ) && + ( !fb_have_pid || + cmp_param_uint64(p_job_info->params.pid, ¶m_pid) ) && + ( !fb_have_uid || + cmp_param_uint64(p_job_info->params.uid, ¶m_uid) ) && + ( !fb_have_timestamp || + cmp_param_time( p_job_info->time_stamp, + ¶m_time_stamp ) ) ) ) + { + // Show job info + printf( "%016"PRIX64" %c%c %s\n", p_job_info->job_id, + p_job_info->routed ? 'R' : '.', + p_job_info->has_use ? 'U' : '.', + p_job_info->params.name ); + + if (fb_verbose) + { + printf( " Timestamp(%"PRIu64"): %s", + (uint64_t)p_job_info->time_stamp, + ctime(&p_job_info->time_stamp) ); + printf( " Application:%s\n", + p_job_info->params.application_name ); + printf( " PID:0x%"PRIX64" UID:0x%"PRIX64"\n", + p_job_info->params.pid, + p_job_info->params.uid ); + } + + // Get interrelated tables + port_handle = p_param_job_list->port_handle; + + if (fb_showguidswitch) + if ( ( rstatus = op_route_get_portguid_vec( port_handle, + p_job_info->job_id, omgt_port_session, &portguid_vec ) ) != + OP_ROUTE_STATUS_OK ) + { + fprintf( stderr, NAME_PROG + ": show Error:%s, can't get port GUID vector\n", + op_route_get_status_text(rstatus) ); + err_usage(); + } + + if (fb_showguidswitch || fb_showcost) + if ( ( rstatus = op_route_get_switch_map( port_handle, + p_job_info->job_id, omgt_port_session, &switch_map ) ) != + OP_ROUTE_STATUS_OK ) + { + fprintf( stderr, NAME_PROG + ": show Error:%s, can't get switch map\n", + op_route_get_status_text(rstatus) ); + err_usage(); + } + + // Show port GUID vector and cost matrix + if (fb_showguidswitch) + { + printf( " PortGUID Vector: GUIDs:%-5u Switch Map: Switches:%-u\n", + portguid_vec.num_guids, switch_map.num_switches ); + + for (ix_3 = 0; ix_3 < portguid_vec.num_guids; ix_3++) + printf( " %5"PRId64": 0x%016"PRIX64" %5u\n", + ix_3, portguid_vec.p_guids[ix_3], + switch_map.p_switch_indices[ix_3] ); + } + + // Get and show cost matrix + if (fb_showcost) + { + if ( ( rstatus = op_route_get_cost_matrix( port_handle, + p_job_info->job_id, omgt_port_session, &p_cost_matrix ) ) != + OP_ROUTE_STATUS_OK ) + { + fprintf( stderr, NAME_PROG + ": show Error:%s, can't get cost matrix\n", + op_route_get_status_text(rstatus) ); + err_usage(); + } + if (! p_cost_matrix) + { + fprintf(stderr, NAME_PROG ": failed to get cost matrix\n"); + exit(0); + } + + // Print title and column headers + printf( " Cost Matrix (hex): Switches:%u\n", + switch_map.num_switches ); + if (switch_map.num_switches) + { + if (switch_index < switch_map.num_switches) + { + ix_3 = switch_index; + if ( (ix_5 = switch_index + MAX_COST_ENTRIES_LINE) > + switch_map.num_switches ) + ix_5 = switch_map.num_switches; + } + + else + { + ix_3 = 0; + if ( (ix_5 = switch_map.num_switches) > + MAX_COST_ENTRIES_LINE ) + ix_5 = MAX_COST_ENTRIES_LINE; + } + + printf(" %4"PRId64, ix_3++); + for ( ; ix_3 < ix_5; ix_3++) + printf(" %4"PRId64, ix_3); + printf("\n"); + + // Print cost matrix data + for ( ix_3 = 0; ix_3 < switch_map.num_switches; + ix_3++ ) + { + printf(" %4"PRId64":", ix_3); + + ix_4 = ix_3 * switch_map.num_switches; + if (switch_index < switch_map.num_switches) + { + ix_4 += switch_index; + if ( (ix_5 = switch_map.num_switches - switch_index) > + MAX_COST_ENTRIES_LINE ) + ix_5 = MAX_COST_ENTRIES_LINE; + } + + else + { + if ( (ix_5 = switch_map.num_switches) > + MAX_COST_ENTRIES_LINE ) + ix_5 = MAX_COST_ENTRIES_LINE; + } + + for ( ; ix_5 > 0; ix_5--) + printf(" %04X", p_cost_matrix[ix_4++]); + printf("\n"); + + } // End of for ( ix_3 = 0; ix_3 < switch_map.num_switches + + } // End of if (switch_map.num_switches) + + } // End of if (fb_showcost) + + // Get and show use matrix + if (fb_showuse) + { + if ( ( rstatus = op_route_get_use_matrix( port_handle, + p_job_info->job_id, omgt_port_session, &use_matrix ) ) != + OP_ROUTE_STATUS_OK ) + { + fprintf( stderr, NAME_PROG + ": show Error:%s, can't get use matrix\n", + op_route_get_status_text(rstatus) ); + err_usage(); + } + + printf( " Use Matrix: Elements:%u Default Use:%u Multiplier:%u\n", + use_matrix.num_elements, use_matrix.default_use, + use_matrix.multiplier ); + + for (ix_3 = 0; ix_3 < use_matrix.num_elements; ix_3++) + printf( " %4"PRId64": Index:%5d DLID:0x%04X Use:%u Bursty:%u\n", ix_3, + use_matrix.p_elements[ix_3].switch_index, + use_matrix.p_elements[ix_3].dlid, + use_matrix.p_elements[ix_3].use, + use_matrix.p_elements[ix_3].bursty ); + } + + if (fb_showguidswitch || fb_showcost || fb_showuse) + printf("\n"); + + // Release and clear tables + op_route_release_portguid_vec(&portguid_vec); + portguid_vec.num_guids = 0; + op_route_release_switch_map(&switch_map); + switch_map.num_switches = 0; + op_route_release_cost_matrix(p_cost_matrix); + p_cost_matrix = NULL; + op_route_release_use_matrix(&use_matrix); + use_matrix.num_elements = 0; + use_matrix.default_use = 0; + use_matrix.multiplier = 0; + + } // End of if ( fb_alljobs || ( fb_have_jobid && + + } // End of for ( ix_2 = job_list.num_jobs, p_job_info = + + } // End of for (ix = param_job_list.num_used; ix > 0; + + break; + + } // End of case show + + // Clear command + case clear: + { + + printf(NAME_PROG ": Clear Command\n"); + printf( "Clear Job(s) (Fabrics:%u Total Jobs:%u):\n", num_job_lists, + num_jobs ); + + for (ix = param_job_list.num_used; ix > 0; p_param_job_list++, ix--) + { + for ( ix_2 = p_param_job_list->job_list.num_jobs, + p_job_info = p_param_job_list->job_list.p_job_info; + ix_2 > 0; p_job_info++, ix_2-- ) + { + if ( fb_alljobs || + ( ( fb_have_jobid || fb_have_jobname || fb_have_appname || + fb_have_pid || fb_have_uid || fb_have_timestamp ) && + ( !fb_have_jobid || + cmp_param_uint64(p_job_info->job_id, ¶m_job_id) ) && + ( !fb_have_jobname || + cmp_param_str(p_job_info->params.name, ¶m_job_name) ) && + ( !fb_have_appname || + cmp_param_str( p_job_info->params.application_name, + ¶m_app_name ) ) && + ( !fb_have_pid || + cmp_param_uint64(p_job_info->params.pid, ¶m_pid) ) && + ( !fb_have_uid || + cmp_param_uint64(p_job_info->params.uid, ¶m_uid) ) && + ( !fb_have_timestamp || + cmp_param_time( p_job_info->time_stamp, + ¶m_time_stamp ) ) ) ) + { + // Complete job + port_handle = p_param_job_list->port_handle; + printf( " Completing Job ID:%016"PRIX64" %s\n", + p_job_info->job_id, p_job_info->params.name ); + + if ( ( rstatus = op_route_complete_job( port_handle, + p_job_info->job_id, omgt_port_session ) ) != OP_ROUTE_STATUS_OK ) + { + fprintf( stderr, NAME_PROG + ": clear Error:%s, can't complete job ID:%"PRIX64"\n", + op_route_get_status_text(rstatus), + p_job_info->job_id ); + err_usage(); + } + + } // End of if ( fb_alljobs || ( fb_have_jobid && + + } // End of for ( ix_2 = p_param_job_list->job_list.num_jobs + + } // End of for (ix = param_job_list.num_used; ix > 0; + + break; + + } // End of case clear + + // Invalid command + default: + fprintf(stderr, NAME_PROG ": Invalid Command\n"); + err_usage(); + break; + + } // End of switch (command) + + // Close port connection(s) + for ( ix = param_job_list.num_used, p_param_job_list = + (struct op_route_param_alloc_job_list_entry *)param_job_list.p_params; + ix > 0; p_param_job_list++, ix-- ) + { + port_handle = p_param_job_list->port_handle; + + rstatus = op_route_close(port_handle); + } + + // Free allocated parameters + op_route_free_param(¶m_port_guid); + op_route_free_param(¶m_job_list); + op_route_free_param(¶m_job_id); + + if (omgt_port_session != NULL) { + omgt_close_port(omgt_port_session); + } + + printf("--------------------------------------------------\n"); + + return (ret_val); + +} // End of main() + + +// End of file diff --git a/update_opa_spec.sh b/update_opa_spec.sh new file mode 100755 index 0000000..8f31c44 --- /dev/null +++ b/update_opa_spec.sh @@ -0,0 +1,237 @@ +#!/bin/bash +# BEGIN_ICS_COPYRIGHT8 **************************************** +# +# Copyright (c) 2015-2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# END_ICS_COPYRIGHT8 **************************************** + +#[ICS VERSION STRING: unknown] + +id=$(./get_id_and_versionid.sh | cut -f1 -d' ') +versionid=$(./get_id_and_versionid.sh | cut -f2 -d' ') + +from=$1 +to=$2 + +if [ "$from" = "" -o "$to" = "" ] +then + echo "Usage: update_opa-ff_spec.sh spec-in-file spec-file" + exit 1 +fi + +if [ "$from" != "$to" ] +then + cp $from $to +fi + +sed -i "s/__RPM_FS/OPA_FEATURE_SET=$OPA_FEATURE_SET/g" $to + + +source ./OpenIb_Host/ff_filegroups.sh + +sed -i "/__RPM_OPASNAPCONFIG1/d" $to +sed -i "/__RPM_OPASNAPCONFIG2/d" $to + +if [ "$id" = "rhel" -o "$id" = "centos" ] +then + GE_7_4=$(echo "$versionid >= 7.4" | bc) + GE_7_5=$(echo "$versionid >= 7.5" | bc) + + # __RPM_REQ_BASIC - + sed -i "s/__RPM_REQ_BASIC/expect%{?_isa}, tcl%{?_isa}, openssl%{?_isa}, expat%{?_isa}, libibumad%{?_isa}, libibverbs%{?_isa}/g" $to + + # __RPM_REQ_OPAMGT_DEV - different for RHEL7.4 and greater + if [ $GE_7_4 = 1 ] + then + sed -i "s/__RPM_REQ_OPAMGT_DEV/rdma-core-devel, openssl-devel, opa-libopamgt,/g" $to + else + sed -i "s/__RPM_REQ_OPAMGT_DEV/libibumad-devel, libibverbs-devel, openssl-devel, opa-libopamgt/g" $to + fi + + # __RPM_BLDREQ - different for RHEL 7.5, RHEL7.4, or earlier + if [ $GE_7_4 = 1 ] + then + sed -i "s/__RPM_BLDREQ/expat-devel, gcc-c++, openssl-devel, ncurses-devel, tcl-devel, zlib-devel, rdma-core-devel, ibacm-devel/g" $to + else + sed -i "s/__RPM_BLDREQ/expat-devel, gcc-c++, openssl-devel, ncurses-devel, tcl-devel, zlib-devel, libibumad-devel, libibverbs-devel, ibacm-devel/g" $to + fi + + # __RPM_REQ_ADDR_RES,__RPM_REQ_OPAMGT and __RPM_DEBUG same for all RHEL versions + sed -i "s/__RPM_REQ_ADDR_RES/opa-basic-tools ibacm/g" $to + sed -i "s/__RPM_REQ_OPAMGT/libibumad%{?_isa}, libibverbs%{?_isa}, openssl%{?_isa}/g" $to + sed -i "/__RPM_DEBUG_PKG/,+1d" $to + + #Setup Epoch tags for RHEL rpms + sed -i "s/__RPM_EPOCH_BASIC/Epoch: 1/g" $to + sed -i "s/__RPM_EPOCH_FF/Epoch: 1/g" $to + sed -i "s/__RPM_EPOCH_ADDR_RES/Epoch: 1/g" $to + sed -i "s/__RPM_EPOCH_LIBOPAMGT/Epoch: 1/g" $to + + +elif [ "$id" = "sles" ] +then + GE_11_1=$(echo "$versionid >= 11.1" | bc) + GE_12_2=$(echo "$versionid >= 12.2" | bc) + GE_12_3=$(echo "$versionid >= 12.3" | bc) + + # __RPM_DEBUG_PKG - needed for SLES 11.1 and greater + if [ $GE_11_1 = 1 ] + then + sed -i "s/__RPM_DEBUG_PKG/%debug_package/g" $to + else + sed -i "/__RPM_DEBUG_PKG/,+1d" $to + fi + + # __RPM_REQ_BASIC, __RPM_BLDREQ, and __RPM_REQ_OPAMGT_DEV different for SLES 12.3 and greater + if [ $GE_12_3 = 1 ] + then + sed -i "s/__RPM_REQ_BASIC/libexpat1, libibmad5, libibumad3, libibverbs1, openssl, expect, tcl/g" $to + sed -i "s/__RPM_BLDREQ/libexpat-devel, gcc-c++, libopenssl-devel, ncurses-devel, tcl-devel, zlib-devel, rdma-core-devel, ibacm-devel/g" $to + sed -i "s/__RPM_REQ_OPAMGT_DEV/rdma-core-devel, libopenssl-devel, opa-libopamgt/g" $to + else + sed -i "s/__RPM_REQ_BASIC/libexpat1, libibmad5, libibumad3, libibverbs1, openssl, expect, tcl/g" $to + sed -i "s/__RPM_BLDREQ/libexpat-devel, gcc-c++, libopenssl-devel, ncurses-devel, tcl-devel, zlib-devel, libibumad-devel, libibverbs-devel, ibacm-devel/g" $to + sed -i "s/__RPM_REQ_OPAMGT_DEV/libibumad-devel, libibverbs-devel, libopenssl-devel, opa-libopamgt/g" $to + fi + + # __RPM_REQ_ADDR_RES same for all SLES versions + sed -i "s/__RPM_REQ_ADDR_RES/opa-basic-tools, ibacm/g" $to + # __RPM_REQ_OPAMGT same for all SLES versions + sed -i "s/__RPM_REQ_OPAMGT/libibumad3, libibverbs1, openssl/g" $to + + #Cleanup EPOCH macros from sles spec. + #Note that SUSE discourages and does not use epochs + sed -i "/__RPM_EPOCH_*/d" $to + +elif [ "$id" = "fedora" ] +then + # __RPM_REQ_BASIC - + sed -i "s/__RPM_REQ_BASIC/expect%{?_isa}, tcl%{?_isa}, openssl%{?_isa}, expat%{?_isa}, libibumad%{?_isa}, libibverbs%{?_isa}/g" $to + + # __RPM_REQ_OPAMGT_DEV - different for RHEL7.4 and greater + sed -i "s/__RPM_REQ_OPAMGT_DEV/rdma-core-devel, openssl-devel, opa-libopamgt,/g" $to + + # __RPM_BLDREQ - different for RHEL 7.5, RHEL7.4, or earlier + sed -i "s/__RPM_BLDREQ/expat-devel, gcc-c++, openssl-devel, ncurses-devel, tcl-devel, zlib-devel, rdma-core-devel, ibacm-devel/g" $to + + # __RPM_REQ_ADDR_RES,__RPM_REQ_OPAMGT and __RPM_DEBUG same for all RHEL versions + sed -i "s/__RPM_REQ_ADDR_RES/opa-basic-tools ibacm/g" $to + sed -i "s/__RPM_REQ_OPAMGT/libibumad%{?_isa}, libibverbs%{?_isa}, openssl%{?_isa}/g" $to + sed -i "/__RPM_DEBUG_PKG/,+1d" $to + + #Setup Epoch tags for RHEL rpms + sed -i "s/__RPM_EPOCH_BASIC/Epoch: 1/g" $to + sed -i "s/__RPM_EPOCH_FF/Epoch: 1/g" $to + sed -i "s/__RPM_EPOCH_ADDR_RES/Epoch: 1/g" $to + sed -i "s/__RPM_EPOCH_LIBOPAMGT/Epoch: 1/g" $to + +else + echo ERROR: Unsupported distribution: $id $versionid + exit 1 +fi + +> .tmpspec +while read line +do + if [ "$line" = "__RPM_BASIC_FILES" ] + then + for i in $basic_tools_sbin $basic_tools_sbin_sym + do + echo "%{_sbindir}/$i" >> .tmpspec + done + for i in $basic_tools_opt + do + echo "/usr/lib/opa/tools/$i" >> .tmpspec + done + for i in $basic_mans + do + echo "%{_mandir}/man1/${i}.gz" >> .tmpspec + done + for i in $basic_samples + do + echo "/usr/share/opa/samples/$i" >> .tmpspec + done + else + echo "$line" >> .tmpspec + fi +done < $to +mv .tmpspec $to + +> .tmpspec +while read line +do + if [ "$line" = "__RPM_FF_FILES" ] + then + for i in $ff_tools_sbin opafmconfigcheck opafmconfigdiff + do + echo "%{_sbindir}/$i" >> .tmpspec + done + for i in $ff_tools_opt $ff_tools_misc $ff_tools_exp $ff_libs_misc + do + echo "/usr/lib/opa/tools/$i" >> .tmpspec + done + for i in $help_doc + do + echo "/usr/share/opa/help/$i" >> .tmpspec + done + for i in $ff_tools_fm + do + echo "/usr/lib/opa/fm_tools/$i" >> .tmpspec + done + for i in $ff_iba_samples + do + echo "/usr/share/opa/samples/$i" >> .tmpspec + done + for i in $ff_mans + do + echo "%{_mandir}/man8/${i}.gz" >> .tmpspec + done + for i in $mpi_apps_files + do + echo "/usr/src/opa/mpi_apps/$i" >> .tmpspec + done + else + echo "$line" >> .tmpspec + fi +done < $to +mv .tmpspec $to + +> .tmpspec +while read line +do + if [ "$line" = "__RPM_SNAP_FILES" ] + then + for i in $opasnapconfig_bin + do + echo "/usr/lib/opa/tools/$i" >> .tmpspec + done + else + echo "$line" >> .tmpspec + fi +done < $to +mv .tmpspec $to + +exit 0